-mm3
--- diff/Documentation/Changes	2004-02-18 08:54:06.000000000 +0000
+++ source/Documentation/Changes	2004-02-23 13:56:39.000000000 +0000
@@ -49,7 +49,7 @@ Card) hardware, for example, you probabl
 with pcmcia-cs.
 
 o  Gnu C                  2.95.3                  # gcc --version
-o  Gnu make               3.78                    # make --version
+o  Gnu make               3.79.1                  # make --version
 o  binutils               2.12                    # ld -v
 o  util-linux             2.10o                   # fdformat --version
 o  module-init-tools      0.9.10                  # depmod -V
@@ -96,7 +96,7 @@ your version of gcc 2.95.x, may necessit
 Make
 ----
 
-You will need Gnu make 3.78 or later to build the kernel.
+You will need Gnu make 3.79.1 or later to build the kernel.
 
 Binutils
 --------
@@ -216,13 +216,6 @@ chmod 0644 /dev/cpu/microcode
 as root before you can use this.  You'll probably also want to
 get the user-space microcode_ctl utility to use with this.
 
-If you have compiled the driver as a module you may need to add
-the following line:
-
-alias char-major-10-184 microcode
-
-to your /etc/modules.conf file.
-
 Powertweak
 ----------
 
@@ -259,17 +252,6 @@ mknod /dev/ppp c 108 0
 
 as root.
 
-If you build ppp support as modules, you will need the following in
-your /etc/modules.conf file:
-
-alias char-major-108	ppp_generic
-alias /dev/ppp		ppp_generic
-alias tty-ldisc-3	ppp_async
-alias tty-ldisc-14	ppp_synctty
-alias ppp-compress-21	bsd_comp
-alias ppp-compress-24	ppp_deflate
-alias ppp-compress-26	ppp_deflate
-
 If you use devfsd and build ppp support as modules, you will need
 the following in your /etc/devfsd.conf file:
 
@@ -319,9 +301,9 @@ gcc 2.95.3
 ----------
 o  <ftp://ftp.gnu.org/gnu/gcc/gcc-2.95.3.tar.gz>
 
-Make 3.78
----------
-o  <ftp://ftp.gnu.org/gnu/make/make-3.78.1.tar.gz>
+Make
+----
+o  <ftp://ftp.gnu.org/gnu/make/>
 
 Binutils
 --------
--- diff/Documentation/CodingStyle	2003-07-22 18:54:26.000000000 +0100
+++ source/Documentation/CodingStyle	2004-02-23 13:56:39.000000000 +0000
@@ -1,42 +1,75 @@
 
-		Linux kernel coding style 
+		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. 
+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. 
+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. 
+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. 
+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. 
+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. 
+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. 
+benefit of warning you when you're nesting your functions too deep.
+Heed that warning.
 
+Don't put multiple statements on a single line unless you have
+something to hide:
 
-		Chapter 2: Placing Braces
+	if (condition) do_this;
+	  do_something_everytime;
+
+Outside of comments, documentation and except in Kconfig, spaces are never
+used for indentation, and the above example is deliberately broken.
+
+Get a decent editor and don't leave whitespace at the end of lines.
+
+
+		Chapter 2: Breaking long lines and strings
+
+Coding style is all about readability and maintainability using commonly
+available tools.
+
+The limit on the length of lines is 80 columns and this is a hard limit.
+
+Statements longer than 80 columns will be broken into sensible chunks.
+Descendants are always substantially shorter than the parent and are placed
+substantially to the right. The same applies to function headers with a long
+argument list. Long strings are as well broken into shorter strings.
+
+void fun(int a, int b, int c)
+{
+	if (condition)
+		printk(KERN_WARNING "Warning this is a long printk with "
+						"3 parameters a: %u b: %u "
+						"c: %u \n", a, b, c);
+	else
+		next_statement;
+}
+
+		Chapter 3: 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
@@ -59,7 +92,7 @@ opening brace at the beginning of the ne
 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). 
+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,
@@ -79,60 +112,60 @@ and
 	} else {
 		....
 	}
-			
-Rationale: K&R. 
+
+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. 
+comments on.
 
 
-		Chapter 3: Naming
+		Chapter 4: 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. 
+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. 
+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()". 
+"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. 
+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". 
+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. 
+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. 
+problem, which is called the function-growth-hormone-imbalance syndrome.
+See next chapter.
+
 
-		
-		Chapter 4: Functions
+		Chapter 5: 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. 
+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. 
+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
@@ -140,41 +173,78 @@ understand what the function is all abou
 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
-than you would have done). 
+than 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. 
+to understand what you did 2 weeks from now.
+
+
+		Chapter 6: Centralized exiting of functions
+
+Albeit deprecated by some people, the equivalent of the goto statement is
+used frequently by compilers in form of the unconditional jump instruction.
 
+The goto statement comes in handy when a function exits from multiple
+locations and some common work such as cleanup has to be done.
 
-		Chapter 5: Commenting
+The rationale is:
+
+- unconditional statements are easier to understand and follow
+- nesting is reduced
+- errors by not updating individual exit points when making
+    modifications are prevented
+- saves the compiler work to optimize redundant code away ;)
+
+int fun(int )
+{
+	int result = 0;
+	char *buffer = kmalloc(SIZE);
+
+	if (buffer == NULL)
+		return -ENOMEM;
+
+	if (condition1) {
+		while (loop1) {
+			...
+		}
+		result = 1;
+		goto out;
+	}
+	...
+out:
+	kfree(buffer);
+	return result;
+}
+
+		Chapter 7: 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. 
+time to explain badly written code.
 
-Generally, you want your comments to tell WHAT your code does, not HOW. 
+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
+you should probably go back to chapter 5 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. 
+it.
 
 
-		Chapter 6: You've made a mess of it
+		Chapter 8: 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 - an infinite number of monkeys typing into GNU emacs would never
-make a good program). 
+make a good program).
 
 So, you can either get rid of GNU emacs, or change it to use saner
 values.  To do the latter, you can stick the following in your .emacs file:
@@ -192,7 +262,7 @@ two lines, this mode will be automatical
 to add
 
 (setq auto-mode-alist (cons '("/usr/src/linux.*/.*\\.[ch]$" . linux-c-mode)
-                       auto-mode-alist))
+			auto-mode-alist))
 
 to your .emacs file if you want to have linux-c-mode switched on
 automagically when you edit source files under /usr/src/linux.
@@ -201,33 +271,36 @@ But even if you fail in getting emacs to
 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. 
+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"). 
+options "-kr -i8" (stands for "K&R, 8 character indents"), or use
+"scripts/Lindent", which indents in the latest style.
 
 "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. 
+re-formatting you may want to take a look at the man page.  But
+remember: "indent" is not a fix for bad programming.
 
 
-		Chapter 7: Configuration-files
+		Chapter 9: Configuration-files
 
-For configuration options (arch/xxx/config.in, and all the Config.in files),
+For configuration options (arch/xxx/Kconfig, and all the Kconfig files),
 somewhat different indentation is used.
 
-An indention level of 3 is used in the code, while the text in the config-
-options should have an indention-level of 2 to indicate dependencies. The
-latter only applies to bool/tristate options. For other options, just use
-common sense. An example:
-
-if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
-   tristate 'Apply nitroglycerine inside the keyboard (DANGEROUS)' CONFIG_BOOM
-   if [ "$CONFIG_BOOM" != "n" ]; then
-      bool '  Output nice messages when you explode' CONFIG_CHEER
-   fi
-fi
+Help text is indented with 2 spaces.
+
+if CONFIG_EXPERIMENTAL
+	tristate CONFIG_BOOM
+	default n
+	help
+	  Apply nitroglycerine inside the keyboard (DANGEROUS)
+	bool CONFIG_CHEER
+	depends on CONFIG_BOOM
+	default y
+	help
+	  Output nice messages when you explode
+endif
 
 Generally, CONFIG_EXPERIMENTAL should surround all options not considered
 stable. All options that are known to trash data (experimental write-
@@ -235,20 +308,20 @@ support for file-systems, for instance) 
 experimental options should be denoted (EXPERIMENTAL).
 
 
-		Chapter 8: Data structures
+		Chapter 10: Data structures
 
 Data structures that have visibility outside the single-threaded
 environment they are created and destroyed in should always have
 reference counts.  In the kernel, garbage collection doesn't exist (and
 outside the kernel garbage collection is slow and inefficient), which
-means that you absolutely _have_ to reference count all your uses. 
+means that you absolutely _have_ to reference count all your uses.
 
 Reference counting means that you can avoid locking, and allows multiple
 users to have access to the data structure in parallel - and not having
 to worry about the structure suddenly going away from under them just
-because they slept or did something else for a while. 
+because they slept or did something else for a while.
 
-Note that locking is _not_ a replacement for reference counting. 
+Note that locking is _not_ a replacement for reference counting.
 Locking is used to keep data structures coherent, while reference
 counting is a memory management technique.  Usually both are needed, and
 they are not to be confused with each other.
@@ -264,3 +337,93 @@ filesystem code ("struct super_block": s
 
 Remember: if another thread can find your data structure, and you don't
 have a reference count on it, you almost certainly have a bug.
+
+
+		Chapter 11: Macros, Enums, Inline functions and RTL
+
+Names of macros defining constants and labels in enums are capitalized.
+
+#define CONSTANT 0x12345
+
+Enums are preferred when defining several related constants.
+
+CAPITALIZED macro names are appreciated but macros resembling functions
+may be named in lower case.
+
+Generally, inline functions are preferable to macros resembling functions.
+
+Macros with multiple statements should be enclosed in a do - while block:
+
+#define macrofun(a,b,c) 			\
+	do {					\
+		if (a == 5)			\
+			do_this(b,c);		\
+	} while (0)
+
+Things to avoid when using macros:
+
+1) macros that affect control flow:
+
+#define FOO(x)					\
+	do {					\
+		if (blah(x) < 0)		\
+			return -EBUGGERED;	\
+	} while(0)
+
+is a _very_ bad idea.  It looks like a function call but exits the "calling"
+function; don't break the internal parsers of those who will read the code.
+
+2) macros that depend on having a local variable with a magic name:
+
+#define FOO(val) bar(index, val)
+
+might look like a good thing, but it's confusing as hell when one reads the
+code and it's prone to breakage from seemingly innocent changes.
+
+3) macros with arguments that are used as l-values: FOO(x) = y; will
+bite you if somebody e.g. turns FOO into an inline function.
+
+4) forgetting about precedence: macros defining constants using expressions
+must enclose the expression in parentheses. Beware of similar issues with
+macros using parameters.
+
+#define CONSTANT 0x4000
+#define CONSTEXP (CONSTANT | 3)
+
+The cpp manual deals with macros exhaustively. The gcc internals manual also
+covers RTL which is used frequently with assembly language in the kernel.
+
+
+		Chapter 12: Printing kernel messages
+
+Kernel developers like to be seen as literate. Do mind the spelling
+of kernel messages to make a good impression. Do not use crippled
+words like "dont" and use "do not" or "don't" instead.
+
+Kernel messages do not have to be terminated with a period.
+
+Printing numbers in parentheses (%d) adds no value and should be avoided.
+
+
+		Chapter 13: References
+
+The C Programming Language, Second Edition
+by Brian W. Kernighan and Dennis M. Ritchie.
+Prentice Hall, Inc., 1988.
+ISBN 0-13-110362-8 (paperback), 0-13-110370-9 (hardback).
+URL: http://cm.bell-labs.com/cm/cs/cbook/
+
+The Practice of Programming
+by Brian W. Kernighan and Rob Pike.
+Addison-Wesley, Inc., 1999.
+ISBN 0-201-61586-X.
+URL: http://cm.bell-labs.com/cm/cs/tpop/
+
+GNU manuals - where in compliance with K&R and this text - for cpp, gcc,
+gcc internals and indent, all available from http://www.gnu.org
+
+WG14 is the international standardization working group for the programming
+language C, URL: http://std.dkuug.dk/JTC1/SC22/WG14/
+
+--
+Last updated on 16 February 2004 by a community effort on LKML.
--- diff/Documentation/DocBook/procfs_example.c	2003-07-22 18:54:26.000000000 +0100
+++ source/Documentation/DocBook/procfs_example.c	2004-02-23 13:56:39.000000000 +0000
@@ -51,7 +51,7 @@
 #include <asm/uaccess.h>
 
 
-#define MODULE_VERSION "1.0"
+#define MODULE_VERS "1.0"
 #define MODULE_NAME "procfs_example"
 
 #define FOOBAR_LEN 8
@@ -185,7 +185,7 @@ static int __init init_procfs_example(vo
 
 	/* everything OK */
 	printk(KERN_INFO "%s %s initialised\n",
-	       MODULE_NAME, MODULE_VERSION);
+	       MODULE_NAME, MODULE_VERS);
 	return 0;
 
 no_symlink:
@@ -213,7 +213,7 @@ static void __exit cleanup_procfs_exampl
 	remove_proc_entry(MODULE_NAME, NULL);
 
 	printk(KERN_INFO "%s %s removed\n",
-	       MODULE_NAME, MODULE_VERSION);
+	       MODULE_NAME, MODULE_VERS);
 }
 
 
--- diff/Documentation/MSI-HOWTO.txt	2004-01-19 10:22:54.000000000 +0000
+++ source/Documentation/MSI-HOWTO.txt	2004-02-23 13:56:39.000000000 +0000
@@ -1,6 +1,8 @@
 		The MSI Driver Guide HOWTO
 	Tom L Nguyen tom.l.nguyen@intel.com
 			10/03/2003
+	Revised Feb 12, 2004 by Martine Silbermann
+		email: Martine.Silbermann@hp.com
 
 1. About this guide
 
@@ -90,17 +92,14 @@ increase scalability.
 5. Configuring a driver to use MSI/MSI-X
 
 By default, the kernel will not enable MSI/MSI-X on all devices that
-support this capability once the patch is installed. A kernel
-configuration option must be selected to enable MSI/MSI-X support.
+support this capability. The CONFIG_PCI_USE_VECTOR kernel option
+must be selected to enable MSI/MSI-X support.
 
 5.1 Including MSI support into the kernel
 
-To include MSI support into the kernel requires users to patch the
-VECTOR-base patch first and then the MSI patch because the MSI
-support needs VECTOR based scheme. Once these patches are installed,
-setting CONFIG_PCI_USE_VECTOR enables the VECTOR based scheme and
-the option for MSI-capable device drivers to selectively enable MSI
-(using pci_enable_msi as desribed below).
+To allow MSI-Capable device drivers to selectively enable MSI (using
+pci_enable_msi as described below), the VECTOR based scheme needs to
+be enabled by setting CONFIG_PCI_USE_VECTOR.
 
 Since the target of the inbound message is the local APIC, providing
 CONFIG_PCI_USE_VECTOR is dependent on whether CONFIG_X86_LOCAL_APIC
@@ -130,7 +129,7 @@ PIN-IRQ assertion mode.
 5.2 Configuring for MSI support
 
 Due to the non-contiguous fashion in vector assignment of the
-existing Linux kernel, this patch does not support multiple
+existing Linux kernel, this version does not support multiple
 messages regardless of the device function is capable of supporting
 more than one vector. The bus driver initializes only entry 0 of
 this capability if pci_enable_msi(...) is called successfully by
@@ -232,7 +231,7 @@ however, in UP environment, users must m
 CONFIG_X86_LOCAL_APIC. Once CONFIG_X86_LOCAL_APIC=y, setting
 CONFIG_PCI_USE_VECTOR enables the VECTOR based scheme and
 the option for MSI-capable device drivers to selectively enable
-MSI (using pci_enable_msi as desribed below).
+MSI (using pci_enable_msi as described below).
 
 Note that CONFIG_X86_IO_APIC setting is irrelevant because MSI
 vector is allocated new during runtime and MSI support does not
--- diff/Documentation/binfmt_misc.txt	2003-10-09 09:47:33.000000000 +0100
+++ source/Documentation/binfmt_misc.txt	2004-02-23 13:56:39.000000000 +0000
@@ -15,7 +15,7 @@ First you must mount binfmt_misc:
 	mount binfmt_misc -t binfmt_misc /proc/sys/fs/binfmt_misc 
 
 To actually register a new binary type, you have to set up a string looking like
-:name:type:offset:magic:mask:interpreter: (where you can choose the ':' upon
+:name:type:offset:magic:mask:interpreter:flags (where you can choose the ':' upon
 your needs) and echo it to /proc/sys/fs/binfmt_misc/register.
 Here is what the fields mean:
  - 'name' is an identifier string. A new /proc file will be created with this
@@ -34,6 +34,28 @@ Here is what the fields mean:
    The mask is anded with the byte sequence of the file.
  - 'interpreter' is the program that should be invoked with the binary as first
    argument (specify the full path)
+ - 'flags' is an optional field that controls several aspects of the invocation
+   of the interpreter. It is a string of capital letters, each controls a certain
+   aspect. The following flags are supported -
+      'P' - preserve-argv[0].  Legacy behavior of binfmt_misc is to overwrite the
+            original argv[0] with the full path to the binary.  When this flag is
+            included, binfmt_misc will add an argument to the argument vector for
+            this purpose, thus preserving the original argv[0].
+      'O' - open-binary. Legacy behavior of binfmt_misc is to pass the full path
+            of the binary to the interpreter as an argument. When this flag is
+            included, binfmt_misc will open the file for reading and pass its
+            descriptor as an argument, instead of the full path, thus allowing
+            the interpreter to execute non-readable binaries. This feature should
+            be used with care - the interpreter has to be trusted not to emit
+            the contents of the non-readable binary.
+      'C' - credentials. Currently, the behavior of binfmt_misc is to calculate
+            the credentials and security token of the new process according to
+            the interpreter. When this flag is included, these attributes are
+            calculated according to the binary. It also implies the 'O' flag.
+            This feature should be used with care as the interpreter
+            will run with root permissions when a setuid binary owned by root
+            is run with binfmt_misc.
+
 
 There are some restrictions:
  - the whole register string may not exceed 255 characters
@@ -83,9 +105,9 @@ If you want to pass special arguments to
 write a wrapper script for it. See Documentation/java.txt for an
 example.
 
-Your interpreter should NOT look in the PATH for the filename; the
-kernel passes it the full filename to use.  Using the PATH can cause
-unexpected behaviour and be a security hazard.
+Your interpreter should NOT look in the PATH for the filename; the kernel
+passes it the full filename (or the file descriptor) to use.  Using $PATH can
+cause unexpected behaviour and can be a security hazard.
 
 
 There is a web page about binfmt_misc at
--- diff/Documentation/computone.txt	2003-08-20 14:16:23.000000000 +0100
+++ source/Documentation/computone.txt	2004-02-23 13:56:39.000000000 +0000
@@ -41,11 +41,11 @@ Hardware - If you have an ISA card, find
 
 	Note the hardware address from the Computone ISA cards installed into
 		the system.  These are required for editing ip2.c or editing
-		/etc/modules.conf, or for specification on the modprobe
+		/etc/modprobe.conf, or for specification on the modprobe
 		command line.
 
-	Note that the /etc/modules.conf file is named /etc/conf.modules
-		with older versions of the module utilities.
+	Note that the /etc/modules.conf should be used for older (pre-2.6)
+		kernels.
 
 Software -
 
@@ -58,7 +58,7 @@ b) Run "make config" or "make menuconfig
 c) Set address on ISA cards then:
    edit /usr/src/linux/drivers/char/ip2.c if needed 
 	or
-   edit /etc/modules.conf if needed (module).
+   edit /etc/modprobe.conf if needed (module).
 	or both to match this setting.
 d) Run "make modules"
 e) Run "make modules_install"
@@ -145,11 +145,11 @@ the irqs are not specified the driver us
 selects polled mode). If no base addresses are specified the defaults in 
 ip2.c are used. If you are autoloading the driver module with kerneld or
 kmod the base addresses and interrupt number must also be set in ip2.c
-and recompile or just insert and options line in /etc/modules.conf or both. 
+and recompile or just insert and options line in /etc/modprobe.conf or both.
 The options line is equivalent to the command line and takes precidence over 
 what is in ip2.c. 
 
-/etc/modules.conf sample:
+/etc/modprobe.conf sample:
 	options ip2 io=1,0x328 irq=1,10
 	alias char-major-71 ip2
 	alias char-major-72 ip2
--- diff/Documentation/crypto/api-intro.txt	2003-10-09 09:47:33.000000000 +0100
+++ source/Documentation/crypto/api-intro.txt	2004-02-23 13:56:39.000000000 +0000
@@ -68,7 +68,7 @@ Many real examples are available in the 
 CONFIGURATION NOTES
 
 As Triple DES is part of the DES module, for those using modular builds,
-add the following line to /etc/modules.conf:
+add the following line to /etc/modprobe.conf:
 
   alias des3_ede des
 
--- diff/Documentation/digiboard.txt	2003-10-09 09:47:16.000000000 +0100
+++ source/Documentation/digiboard.txt	2004-02-23 13:56:39.000000000 +0000
@@ -24,7 +24,7 @@ The driver can be built direct into the 
 The pcxx driver can be configured using the command line feature while
 loading the kernel with LILO or LOADLIN or, if built as a module,
 with arguments to insmod and modprobe or with parameters in
-/etc/modules.conf for modprobe and kerneld.
+/etc/modprobe.conf for modprobe and kerneld.
 
 After configuring the driver you need to create the device special files
 as described in "Device file creation:" below and set the appropriate
@@ -91,13 +91,13 @@ devices following that board, you can em
 
 The remaining board still uses ttyD8-ttyD15 and cud8-cud15.
 
-Example line for /etc/modules.conf for use with kerneld and as default
+Example line for /etc/modprobe.conf for use with kerneld and as default
 parameters for modprobe:
 
 options pcxx           io=0x200 numports=8
 
-For kerneld to work you will likely need to add these two lines to your
-/etc/modules.conf:
+For kmod to work you will likely need to add these two lines to your
+/etc/modprobe.conf:
 
 alias char-major-22    pcxx
 alias char-major-23    pcxx
--- diff/Documentation/early-userspace/README	2003-08-26 10:00:51.000000000 +0100
+++ source/Documentation/early-userspace/README	2004-02-23 13:56:39.000000000 +0000
@@ -72,4 +72,32 @@ For questions and help, you can sign up 
 mailing list at http://www.zytor.com/mailman/listinfo/klibc
 
 
+How does it work?
+=================
+
+The kernel has currently 3 ways to mount the root filesystem:
+a) all required device and filesystem drivers compiled into the
+   kernel, no initrd. init/main.c:init() will call prepare_namespace()
+   to mount the final root filesystem, based on the root= option
+   and optional init= to run some other init binary than listed
+   at the end of init/main.c:init().
+b) some device and filesystem drivers built as modules and stored in
+   an initrd. The initrd must contain a binary '/linuxrc' which is
+   supposed to load these driver modules. It is also possible to
+   mount the final root filesystem via linuxrc and use the pivot_root
+   syscall. The initrd is mounted and executed via prepare_namespace().
+c) using initramfs. The call to prepare_namespace() must be skipped. This
+   means that a binary must do all the work. Said binary can be stored
+   into initramfs either via modifying usr/gen_init_cpio.c or via the new
+   initrd format, an cpio archive. It must be called "/sbin/init".
+   A different binary can be specified with the kinit= boot option.
+   This binary is responsible to do all the things prepare_namespace()
+   would do.
+   To remain backwards compatibility, the kinit binary will only run if
+   it comes via an initramfs cpio archive, or if the kinit= option is
+   specified. If this is not the case, init/main.c:init() will run
+   prepare_namespace() to mount the final root and exec one of the
+   predefined init binaries.
+
+
 Bryan O'Sullivan <bos@serpentine.com>
--- diff/Documentation/fb/intel810.txt	2003-01-02 10:43:02.000000000 +0000
+++ source/Documentation/fb/intel810.txt	2004-02-23 13:56:39.000000000 +0000
@@ -194,7 +194,7 @@ Using the same setup as described above,
 	modprobe i810fb vram=2 xres=1024 bpp=8 hsync1=30 hsync2=55 vsync1=50 \
 	         vsync2=85 accel=1 mtrr=1
 
-Or just add the following to /etc/modules.conf
+Or just add the following to /etc/modprobe.conf
 
 	options i810fb vram=2 xres=1024 bpp=16 hsync1=30 hsync2=55 vsync1=50 \
 	vsync2=85 accel=1 mtrr=1
--- diff/Documentation/filesystems/jfs.txt	2003-10-27 09:20:36.000000000 +0000
+++ source/Documentation/filesystems/jfs.txt	2004-02-23 13:56:39.000000000 +0000
@@ -12,10 +12,9 @@ Barry Arndt        barndt@us.ibm.com
 The following mount options are supported:
 
 iocharset=name	Character set to use for converting from Unicode to
-		ASCII.  The default is compiled into the kernel as
-		CONFIG_NLS_DEFAULT.  Use iocharset=utf8 for UTF8
-		translations.  This requires CONFIG_NLS_UTF8 to be set
-		in the kernel .config file.
+		ASCII.  The default is to do no conversion.  Use
+		iocharset=utf8 for UTF8 translations.  This requires
+		CONFIG_NLS_UTF8 to be set in the kernel .config file.
 
 resize=value	Resize the volume to <value> blocks.  JFS only supports
 		growing a volume, not shrinking it.  This option is only
@@ -36,18 +35,6 @@ errors=continue		Keep going on a filesys
 errors=remount-ro	Default. Remount the filesystem read-only on an error.
 errors=panic		Panic and halt the machine if an error occurs.
 
-JFS TODO list:
-
-Plans for our near term development items
-
-   - enhance support for logfile on dedicated partition
-
-Longer term work items
-
-   - implement defrag utility, for online defragmenting
-   - add quota support
-   - add support for block sizes (512,1024,2048)
-
 Please send bugs, comments, cards and letters to shaggy@austin.ibm.com.
 
 The JFS mailing list can be subscribed to by using the link labeled
--- diff/Documentation/filesystems/proc.txt	2003-09-17 12:28:01.000000000 +0100
+++ source/Documentation/filesystems/proc.txt	2004-02-23 13:56:39.000000000 +0000
@@ -900,6 +900,15 @@ super-nr shows the number of currently a
 Every mounted file system needs a super block, so if you plan to mount lots of
 file systems, you may want to increase these numbers.
 
+aio-nr and aio-max-nr
+---------------------
+
+aio-nr is the running total of the number of events specified on the
+io_setup system call for all currently active aio contexts.  If aio-nr
+reaches aio-max-nr then io_setup will fail with EAGAIN.  Note that
+raising aio-max-nr does not result in the pre-allocation or re-sizing
+of any kernel data structures.
+
 2.2 /proc/sys/fs/binfmt_misc - Miscellaneous binary formats
 -----------------------------------------------------------
 
--- diff/Documentation/filesystems/ufs.txt	2002-10-16 04:28:31.000000000 +0100
+++ source/Documentation/filesystems/ufs.txt	2004-02-23 13:56:39.000000000 +0000
@@ -20,6 +20,9 @@ ufstype=type_of_ufs
 	44bsd	used in FreeBSD, NetBSD, OpenBSD
 		supported os read-write
 
+       ufs2    used in FreeBSD 5.x
+               supported os read-only
+
 	sun	used in SunOS (Solaris)
 		supported as read-write
 
--- diff/Documentation/ftape.txt	2003-10-09 09:47:33.000000000 +0100
+++ source/Documentation/ftape.txt	2004-02-23 13:56:39.000000000 +0000
@@ -242,15 +242,15 @@ C. Boot and load time configuration
    Module parameters can be specified either directly when invoking
    the program 'insmod' at the shell prompt:
 
-   insmod ftape.o ft_tracing=4
+   modprobe ftape ft_tracing=4
 
-   or by editing the file `/etc/modules.conf' in which case they take
+   or by editing the file `/etc/modprobe.conf' in which case they take
    effect each time when the module is loaded with `modprobe' (please
    refer to the respective manual pages). Thus, you should add a line
 
    options ftape ft_tracing=4
 
-   to `/etc/modules.conf` if you intend to increase the debugging
+   to `/etc/modprobe.conf` if you intend to increase the debugging
    output of the driver.
 
 
@@ -298,7 +298,7 @@ C. Boot and load time configuration
 5. Example module parameter setting
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    To do the same, but with ftape compiled as a loadable kernel
-   module, add the following line to `/etc/modules.conf':
+   module, add the following line to `/etc/modprobe.conf':
 
    options ftape ft_probe_fc10=1 ft_tracing=4
 
--- diff/Documentation/hayes-esp.txt	2002-10-16 04:27:12.000000000 +0100
+++ source/Documentation/hayes-esp.txt	2004-02-23 13:56:39.000000000 +0000
@@ -109,7 +109,7 @@ option with a space.  For example:
 insmod esp dma=3 trigger=512
 
 The esp module can be automatically loaded when needed.  To cause this to
-happen, add the following lines to /etc/modules.conf (replacing the last line
+happen, add the following lines to /etc/modprobe.conf (replacing the last line
 with options for your configuration):
 
 alias char-major-57 esp
--- diff/Documentation/ide.txt	2003-10-27 09:20:36.000000000 +0000
+++ source/Documentation/ide.txt	2004-02-23 13:56:39.000000000 +0000
@@ -198,12 +198,11 @@ drivers can always be compiled as loadab
 can only be compiled into the kernel, and the core code (ide.c) can be
 compiled as a loadable module provided no chipset support is needed.
 
-When using ide.c/ide-tape.c as modules in combination with kerneld, add:
+When using ide.c as a module in combination with kmod, add:
 
 	alias block-major-3 ide-probe
-	alias char-major-37 ide-tape
 
-respectively to /etc/modules.conf.
+to /etc/modprobe.conf.
 
 When ide.c is used as a module, you can pass command line parameters to the
 driver using the "options=" keyword to insmod, while replacing any ',' with
@@ -231,9 +230,10 @@ Summary of ide driver parameters for ker
  
  "hdx=cyl,head,sect"	: disk drive is present, with specified geometry
 
- "hdx=remap"		: remap access of sector 0 to sector 1 (for EZD)
+ "hdx=remap"		: remap access of sector 0 to sector 1 (for EZDrive)
 
- "hdx=remap63"		: remap the drive: shift all by 63 sectors (for DM)
+ "hdx=remap63"		: remap the drive: add 63 to all sector numbers
+			  (for DM OnTrack)
  
  "hdx=autotune"		: driver will attempt to tune interface speed
 			  to the fastest PIO mode supported,
@@ -242,17 +242,10 @@ Summary of ide driver parameters for ker
 			  and quite likely to cause trouble with
 			  older/odd IDE drives.
 
- "hdx=slow"		: insert a huge pause after each access to the data
-			  port. Should be used only as a last resort.
-
  "hdx=swapdata"		: when the drive is a disk, byte swap all data
 
  "hdx=bswap"		: same as above..........
 
- "hdx=flash"		: allows for more than one ata_flash disk to be
- 			  registered. In most cases, only one device
- 			  will be present.
-
  "hdx=scsi"		: the return of the ide-scsi flag, this is useful for
  			  allowing ide-floppy, ide-tape, and ide-cdrom|writers
  			  to use ide-scsi emulation on a device specific option.
--- diff/Documentation/ioctl-number.txt	2003-10-09 09:47:33.000000000 +0100
+++ source/Documentation/ioctl-number.txt	2004-02-23 13:56:39.000000000 +0000
@@ -187,3 +187,5 @@ Code	Seq#	Include File		Comments
 0xB1	00-1F	PPPoX			<mailto:mostrows@styx.uwaterloo.ca>
 0xCB	00-1F	CBM serial IEC bus	in development:
 					<mailto:michael.klein@puffin.lb.shuttle.de>
+0xDD	00-3F	ZFCP device driver	see drivers/s390/scsi/
+					<mailto:aherrman@de.ibm.com>
--- diff/Documentation/kbuild/makefiles.txt	2003-10-09 09:47:33.000000000 +0100
+++ source/Documentation/kbuild/makefiles.txt	2004-02-23 13:56:39.000000000 +0000
@@ -638,15 +638,6 @@ When kbuild executes the following steps
 		#arch/i386/Makefile
 		LDFLAGS_vmlinux := -e stext
 
-    LDFLAGS_BLOB	Options for $(LD) when linking the initramfs blob
-
-	The image used for initramfs is made during the build process.
-	LDFLAGS_BLOB is used to specify additional flags to be used when
-	creating the initramfs_data.o file.
-	Example:
-		#arch/i386/Makefile
-		LDFLAGS_BLOB := --format binary --oformat elf32-i386
-
     OBJCOPYFLAGS	objcopy flags
 
 	When $(call if_changed,objcopy) is used to translate a .o file,
--- diff/Documentation/kbuild/modules.txt	2004-01-19 10:22:54.000000000 +0000
+++ source/Documentation/kbuild/modules.txt	2004-02-23 13:56:39.000000000 +0000
@@ -17,12 +17,52 @@ out-of-the-box support for installation 
 
 Compiling modules outside the official kernel
 ---------------------------------------------
-Often modules are developed outside the official kernel.
-To keep up with changes in the build system the most portable way
-to compile a module outside the kernel is to use the following command-line:
+
+Often modules are developed outside the official kernel.  To keep up
+with changes in the build system the most portable way to compile a
+module outside the kernel is to use the kernel build system,
+kbuild. Use the following command-line:
 
 make -C path/to/kernel/src SUBDIRS=$PWD modules
 
 This requires that a makefile exits made in accordance to
-Documentation/kbuild/makefiles.txt.
+Documentation/kbuild/makefiles.txt. Read that file for more details on
+the build system.
+
+The following is a short summary of how to write your Makefile to get
+you up and running fast. Assuming your module will be called
+yourmodule.ko, your code should be in yourmodule.c and your Makefile
+should include
+
+obj-m := yourmodule.o
+
+If the code for your module is in multiple files that need to be
+linked, you need to tell the build system which files to compile. In
+the case of multiple files, none of these files can be named
+yourmodule.c because doing so would cause a problem with the linking
+step. Assuming your code exists in file1.c, file2.c, and file3.c and
+you want to build yourmodule.ko from them, your Makefile should
+include
+
+obj-m := yourmodule.o
+yourmodule-objs := file1.o file2.o file3.o
+
+Now for a final example to put it all together. Assuming the
+KERNEL_SOURCE environment variable is set to the directory where you
+compiled the kernel, a simple Makefile that builds yourmodule.ko as
+described above would look like
+
+# Tells the build system to build yourmodule.ko.
+obj-m := yourmodule.o
+
+# Tells the build system to build these object files and link them as
+# yourmodule.o, before building yourmodule.ko. This line can be left
+# out if all the code for your module is in one file, yourmodule.c. If
+# you are using multiple files, none of these files can be named
+# yourmodule.c.
+yourmodule-objs := file1.o file2.o file3.o
 
+# Invokes the kernel build system to come back to the current
+# directory and build yourmodule.ko.
+default:
+	make -C ${KERNEL_SOURCE} SUBDIRS=`pwd` modules
--- diff/Documentation/kernel-parameters.txt	2004-02-09 10:36:07.000000000 +0000
+++ source/Documentation/kernel-parameters.txt	2004-02-23 13:56:39.000000000 +0000
@@ -174,11 +174,18 @@ running once the system is up.
 
 	atascsi=	[HW,SCSI] Atari SCSI
 
-	atkbd.set=	[HW] Select keyboard code set
-			Format: <int>
+	atkbd.extra=	[HW] Enable extra LEDs and keys on IBM RapidAccess, EzKey
+			and similar keyboards
+
+	atkbd.reset=	[HW] Reset keyboard during initialization
+
+	atkbd.set=	[HW] Select keyboard code set 
+			Format: <int> (2 = AT (default) 3 = PS/2)
+
+	atkbd.scroll=	[HW] Enable scroll wheel on MS Office and similar keyboards
+	
 	atkbd.softrepeat=
 			[HW] Use software keyboard repeat
-	atkbd.reset=	[HW] Reset keyboard during initialization
 
 	autotest	[IA64]
 
@@ -237,7 +244,7 @@ running once the system is up.
 			Forces specified timesource (if avaliable) to be used
 			when calculating gettimeofday(). If specicified timesource
 			is not avalible, it defaults to PIT. 
-			Format: { pit | tsc | cyclone | ... }
+			Format: { pit | tsc | cyclone | pmtmr }
 
 	hpet=		[IA-32,HPET] option to disable HPET and use PIT.
 			Format: disable
@@ -292,6 +299,9 @@ running once the system is up.
 
 	devfs=		[DEVFS]
 			See Documentation/filesystems/devfs/boot-options.
+
+	dhash_entries=	[KNL]
+			Set number of hash buckets for dentry cache.
  
 	digi=		[HW,SERIAL]
 			IO parameters + enable/disable command.
@@ -310,6 +320,23 @@ running once the system is up.
 
 	dtc3181e=	[HW,SCSI]
 
+	earlyprintk=	[x86, x86_64]
+			early_printk=vga
+			early_printk=serial[,ttySn[,baudrate]]
+
+			Append ,keep to not disable it when the real console
+			takes over.
+
+			Only vga or serial at a time, not both.
+
+			Currently only ttyS0 and ttyS1 are supported.
+
+			Interaction with the standard serial driver is not
+			very good.
+
+			The VGA output is eventually overwritten by the real
+			console.
+
 	eata=		[HW,SCSI]
 
 	eda=		[HW,PS2]
@@ -424,6 +451,9 @@ running once the system is up.
 	idle=		[HW]
 			Format: idle=poll or idle=halt
  
+	ihash_entries=	[KNL]
+			Set number of hash buckets for inode cache.
+
 	in2000=		[HW,SCSI]
 			See header of drivers/scsi/in2000.c.
 
@@ -469,6 +499,9 @@ running once the system is up.
 
 	keepinitrd	[HW,ARM]
 
+	kinit=		Specify the path to the init executable to replace
+			prepare_namespace() (for initramfs archives)
+
 	l2cr=		[PPC]
 
 	lapic		[IA-32,APIC] Enable the local APIC even if BIOS disabled it.
@@ -873,6 +906,9 @@ running once the system is up.
 
 	resume=		[SWSUSP] Specify the partition device for software suspension
 
+	rhash_entries=	[KNL,NET]
+			Set number of hash buckets for route cache
+
 	riscom8=	[HW,SERIAL]
 			Format: <io_board1>[,<io_board2>[,...<io_boardN>]]
 
@@ -1135,6 +1171,9 @@ running once the system is up.
 	tgfx_2=		See Documentation/input/joystick-parport.txt.
 	tgfx_3=
 
+	thash_entries=	[KNL,NET]
+			Set number of hash buckets for TCP connection
+
 	tipar=		[HW]
 			See header of drivers/char/tipar.c.
 
--- diff/Documentation/networking/baycom.txt	2002-10-16 04:28:34.000000000 +0100
+++ source/Documentation/networking/baycom.txt	2004-02-23 13:56:39.000000000 +0000
@@ -93,10 +93,10 @@ Every time a driver is inserted into the
 modems it should access at which ports. This can be done with the setbaycom
 utility. If you are only using one modem, you can also configure the
 driver from the insmod command line (or by means of an option line in
-/etc/modules.conf).
+/etc/modprobe.conf).
 
 Examples:
-  insmod baycom_ser_fdx mode="ser12*" iobase=0x3f8 irq=4
+  modprobe baycom_ser_fdx mode="ser12*" iobase=0x3f8 irq=4
   sethdlc -i bcsf0 -p mode "ser12*" io 0x3f8 irq 4
 
 Both lines configure the first port to drive a ser12 modem at the first
--- diff/Documentation/networking/bonding.txt	2004-02-18 08:54:06.000000000 +0000
+++ source/Documentation/networking/bonding.txt	2004-02-23 13:56:39.000000000 +0000
@@ -31,6 +31,7 @@ Verifying Bond Configuration
 Frequently Asked Questions
 High Availability
 Promiscuous Sniffing notes
+8021q VLAN support
 Limitations
 Resources and Links
 
@@ -73,9 +74,9 @@ To install ifenslave.c, do:
 Bond Configuration
 ==================
 
-You will need to add at least the following line to /etc/modules.conf
+You will need to add at least the following line to /etc/modprobe.conf
 so the bonding driver will automatically load when the bond0 interface is
-configured. Refer to the modules.conf manual page for specific modules.conf
+configured. Refer to the modprobe.conf manual page for specific modprobe.conf
 syntax details. The Module Parameters section of this document describes each
 bonding driver parameter.
 
@@ -132,18 +133,14 @@ You can then create a script containing 
 appropriate rc directory.
 
 If you specifically need all network drivers loaded before the bonding driver,
-adding the following line to modules.conf will cause the network driver for
+adding the following line to modprobe.conf will cause the network driver for
 eth0 and eth1 to be loaded before the bonding driver.
 
-probeall bond0 eth0 eth1 bonding
+install bond0 /sbin/modprobe -a eth0 eth1 && /sbin/modprobe bonding
 
 Be careful not to reference bond0 itself at the end of the line, or modprobe
 will die in an endless recursive loop.
 
-To have device characteristics (such as MTU size) propagate to slave devices,
-set the bond characteristics before enslaving the device.  The characteristics
-are propagated during the enslave process.
-
 If running SNMP agents, the bonding driver should be loaded before any network
 drivers participating in a bond. This requirement is due to the the interface
 index (ipAdEntIfIndex) being associated to the first interface found with a
@@ -191,7 +188,7 @@ Module Parameters
 
 Optional parameters for the bonding driver can be supplied as command line
 arguments to the insmod command. Typically, these parameters are specified in
-the file /etc/modules.conf (see the manual page for modules.conf). The
+the file /etc/modprobe.conf (see the manual page for modprobe.conf). The
 available bonding driver parameters are listed below. If a parameter is not
 specified the default value is used. When initially configuring a bond, it
 is recommended "tail -f /var/log/messages" be run in a separate window to
@@ -601,7 +598,7 @@ Frequently Asked Questions
 	For ethernet cards not supporting MII status, the arp_interval and
         arp_ip_target parameters must be specified for bonding to work
         correctly. If packets have not been sent or received during the
-        specified arp_interval durration, an ARP request is sent to the
+        specified arp_interval duration, an ARP request is sent to the
         targets to generate send and receive traffic. If after this
         interval, either the successful send and/or receive count has not
         incremented, the next slave in the sequence will become the active
@@ -669,16 +666,8 @@ Frequently Asked Questions
 	that will be added.
 
 	To restore your slaves' MAC addresses, you need to detach them
-	from the bond (`ifenslave -d bond0 eth0'), set them down
-	(`ifconfig eth0 down'), unload the drivers (`rmmod 3c59x', for
-	example) and reload them to get the MAC addresses from their
-	eeproms. If the driver is shared by several devices, you need
-	to turn them all down. Another solution is to look for the MAC
-	address at boot time (dmesg or tail /var/log/messages) and to
-	reset it by hand with ifconfig :
-
-	  # ifconfig eth0 down
-	  # ifconfig eth0 hw ether 00:20:40:60:80:A0
+	from the bond (`ifenslave -d bond0 eth0'). The bonding driver will then
+	restore the MAC addresses that the slaves had before they were enslaved.
 
 9.  Which transmit polices can be used?
 
@@ -742,9 +731,8 @@ Example:
 
    # modprobe bonding miimon=100
 
-Or, put the following lines in /etc/modules.conf:
+Or, put the following line in /etc/modprobe.conf:
 
-   alias bond0 bonding
    options bond0 miimon=100
 
 There are currently two policies for high availability. They are dependent on
@@ -815,9 +803,8 @@ To use this mode, pass "mode=1" to the m
 
     # modprobe bonding miimon=100 mode=1
 
-Or, put in your /etc/modules.conf :
+Or, put in your /etc/modprobe.conf :
 
-    alias bond0 bonding
     options bond0 miimon=100 mode=active-backup
 
 Example 1: Using multiple host and multiple switches to build a "no single
@@ -843,7 +830,7 @@ point of failure" solution.
 
 In this configuration, there is an ISL - Inter Switch Link (could be a trunk),
 several servers (host1, host2 ...) attached to both switches each, and one or
-more ports to the outside world (port3...). One an only one slave on each host
+more ports to the outside world (port3...). One and only one slave on each host
 is active at a time, while all links are still monitored (the system can
 detect a failure of active and backup links).
 
@@ -919,7 +906,6 @@ setting by hand. Specifically, when you 
 must add the promisc flag there; it will be propagated down to the
 slave interfaces at ifenslave time; a full example might look like:
 
-   grep bond0 /etc/modules.conf || echo alias bond0 bonding >/etc/modules.conf
    ifconfig bond0 promisc up
    for if in eth1 eth2 ...;do
        ifconfig $if up
@@ -933,6 +919,41 @@ capacity aggregating; but it works fine 
 just ignore all the warnings it emits.
 
 
+8021q VLAN support
+==================
+
+It is possible to configure VLAN devices over a bond interface using the 8021q
+driver. However, only packets coming from the 8021q driver and passing through
+bonding will be tagged by default. Self generated packets, like bonding's
+learning packets or ARP packets generated by either ALB mode or the ARP
+monitor mechanism, are tagged internally by bonding itself. As a result,
+bonding has to "learn" what VLAN IDs are configured on top of it, and it uses
+those IDs to tag self generated packets.
+
+For simplicity reasons, and to support the use of adapters that can do VLAN
+hardware acceleration offloding, the bonding interface declares itself as
+fully hardware offloaing capable, it gets the add_vid/kill_vid notifications
+to gather the necessary information, and it propagates those actions to the
+slaves.
+In case of mixed adapter types, hardware accelerated tagged packets that should
+go through an adapter that is not offloading capable are "un-accelerated" by the
+bonding driver so the VLAN tag sits in the regular location.
+
+VLAN interfaces *must* be added on top of a bonding interface only after
+enslaving at least one slave. This is because until the first slave is added the
+bonding interface has a HW address of 00:00:00:00:00:00, which will be copied by
+the VLAN interface when it is created.
+
+Notice that a problem would occur if all slaves are released from a bond that
+still has VLAN interfaces on top of it. When later coming to add new slaves, the
+bonding interface would get a HW address from the first slave, which might not
+match that of the VLAN interfaces. It is recommended that either all VLANs are
+removed and then re-added, or to manually set the bonding interface's HW
+address so it matches the VLAN's. (Note: changing a VLAN interface's HW address
+would set the underlying device -- i.e. the bonding interface -- to promiscouos
+mode, which might not be what you want).
+
+
 Limitations
 ===========
 The main limitations are :
--- diff/Documentation/networking/dl2k.txt	2002-10-16 04:28:29.000000000 +0100
+++ source/Documentation/networking/dl2k.txt	2004-02-23 13:56:39.000000000 +0000
@@ -37,15 +37,15 @@ Quick Install
 Install linux driver as following command:
 
 1. make all
-2. insmod dl2k.o
+2. insmod dl2k.ko
 3. ifconfig eth0 up 10.xxx.xxx.xxx netmask 255.0.0.0
 		    ^^^^^^^^^^^^^^^\	    ^^^^^^^^\
 				    IP		     NETMASK
 Now eth0 should active, you can test it by "ping" or get more information by
 "ifconfig". If tested ok, continue the next step.
 
-4. cp dl2k.o /lib/modules/`uname -r`/kernel/drivers/net
-5. Add the following lines to /etc/modules.conf:
+4. cp dl2k.ko /lib/modules/`uname -r`/kernel/drivers/net
+5. Add the following line to /etc/modprobe.conf:
 	alias eth0 dl2k
 6. Run "netconfig" or "netconf" to create configuration script ifcfg-eth0
    located at /etc/sysconfig/network-scripts or create it manually.
@@ -154,8 +154,8 @@ Installing the Driver
   -----------------
   1. Copy dl2k.o to the network modules directory, typically
      /lib/modules/2.x.x-xx/net or /lib/modules/2.x.x/kernel/drivers/net.
-  2. Locate the boot module configuration file, most commonly modules.conf
-     or conf.modules in the /etc directory. Add the following lines:
+  2. Locate the boot module configuration file, most commonly modprobe.conf
+     or modules.conf (for 2.4) in the /etc directory. Add the following lines:
 
      alias ethx dl2k
      options dl2k <optional parameters>
--- diff/Documentation/networking/ifenslave.c	2004-02-18 08:54:06.000000000 +0000
+++ source/Documentation/networking/ifenslave.c	2004-02-23 13:56:39.000000000 +0000
@@ -89,13 +89,13 @@
  *	   while it is running. It was already set during enslave. To
  *	   simplify things, it is now handeled separately.
  *
- *    - 2003/09/24 - Shmulik Hen <shmulik.hen at intel dot com>
+ *    - 2003/12/01 - Shmulik Hen <shmulik.hen at intel dot com>
  *	 - Code cleanup and style changes
  *	   set version to 1.1.0
  */
 
 #define APP_VERSION	"1.1.0"
-#define APP_RELDATE	"Septemer 24, 2003"
+#define APP_RELDATE	"December 1, 2003"
 #define APP_NAME	"ifenslave"
 
 static char *version =
--- diff/Documentation/networking/ip-sysctl.txt	2004-02-18 08:54:06.000000000 +0000
+++ source/Documentation/networking/ip-sysctl.txt	2004-02-23 13:56:39.000000000 +0000
@@ -499,6 +499,55 @@ arp_filter - BOOLEAN
 	conf/{all,interface}/arp_filter is set to TRUE,
 	it will be disabled otherwise
 
+arp_announce - INTEGER
+	Define different restriction levels for announcing the local
+	source IP address from IP packets in ARP requests sent on
+	interface:
+	0 - (default) Use any local address, configured on any interface
+	1 - Try to avoid local addresses that are not in the target's
+	subnet for this interface. This mode is useful when target
+	hosts reachable via this interface require the source IP
+	address in ARP requests to be part of their logical network
+	configured on the receiving interface. When we generate the
+	request we will check all our subnets that include the
+	target IP and will preserve the source address if it is from
+	such subnet. If there is no such subnet we select source
+	address according to the rules for level 2.
+	2 - Always use the best local address for this target.
+	In this mode we ignore the source address in the IP packet
+	and try to select local address that we prefer for talks with
+	the target host. Such local address is selected by looking
+	for primary IP addresses on all our subnets on the outgoing
+	interface that include the target IP address. If no suitable
+	local address is found we select the first local address
+	we have on the outgoing interface or on all other interfaces,
+	with the hope we will receive reply for our request and
+	even sometimes no matter the source IP address we announce.
+
+	The max value from conf/{all,interface}/arp_announce is used.
+
+	Increasing the restriction level gives more chance for
+	receiving answer from the resolved target while decreasing
+	the level announces more valid sender's information.
+
+arp_ignore - INTEGER
+	Define different modes for sending replies in response to
+	received ARP requests that resolve local target IP addresses:
+	0 - (default): reply for any local target IP address, configured
+	on any interface
+	1 - reply only if the target IP address is local address
+	configured on the incoming interface
+	2 - reply only if the target IP address is local address
+	configured on the incoming interface and both with the
+	sender's IP address are part from same subnet on this interface
+	3 - do not reply for local addresses configured with scope host,
+	only resolutions for global and link addresses are replied
+	4-7 - reserved
+	8 - do not reply for all local addresses
+
+	The max value from conf/{all,interface}/arp_ignore is used
+	when ARP request is received on the {interface}
+
 tag - INTEGER
 	Allows you to write a number, which can be used as required.
 	Default value is 0.
--- diff/Documentation/networking/ltpc.txt	2002-10-16 04:27:48.000000000 +0100
+++ source/Documentation/networking/ltpc.txt	2004-02-23 13:56:39.000000000 +0000
@@ -25,7 +25,7 @@ the driver will try to determine them it
 
 If you load the driver as a module, you can pass the parameters "io=",
 "irq=", and "dma=" on the command line with insmod or modprobe, or add
-them as options in /etc/modules.conf:
+them as options in /etc/modprobe.conf:
 
  alias lt0 ltpc # autoload the module when the interface is configured
  options ltpc io=0x240 irq=9 dma=1
--- diff/Documentation/networking/sk98lin.txt	2004-02-09 10:36:07.000000000 +0000
+++ source/Documentation/networking/sk98lin.txt	2004-02-23 13:56:39.000000000 +0000
@@ -1,10 +1,10 @@
-(C)Copyright 1999-2003 Marvell(R).
+(C)Copyright 1999-2004 Marvell(R).
 All rights reserved
 ===========================================================================
 
-sk98lin.txt created 15-Dec-2003
+sk98lin.txt created 13-Feb-2004
 
-Readme File for sk98lin v6.21
+Readme File for sk98lin v6.23
 Marvell Yukon/SysKonnect SK-98xx Gigabit Ethernet Adapter family driver for LINUX
 
 This file contains
@@ -174,7 +174,7 @@ In some distributions, the configuration
 to the driver module.
 
 If you use the kernel module loader, you can set driver parameters
-in the file /etc/modules.conf (or old name: /etc/conf.modules).
+in the file /etc/modprobe.conf (or /etc/modules.conf in 2.4 or earlier).
 To set the driver parameters in this file, proceed as follows:
 
 1. Insert a line of the form :
--- diff/Documentation/networking/tuntap.txt	2003-05-21 11:49:49.000000000 +0100
+++ source/Documentation/networking/tuntap.txt	2004-02-23 13:56:39.000000000 +0000
@@ -45,13 +45,10 @@ Copyright (C) 1999-2000 Maxim Krasnyansk
      bogus network interfaces to trick firewalls or administrators.
 
   Driver module autoloading
-     Make sure that "Kernel module loader" - module auto-loading support is enabled 
-     in your kernel. 
 
-     Add the following line to the /etc/modules.conf:
-	alias char-major-10-200 tun
-     and run
-        depmod -a 
+     Make sure that "Kernel module loader" - module auto-loading
+     support is enabled in your kernel.  The kernel should load it on
+     first access.
   
   Manual loading 
      insert the module by hand:
--- diff/Documentation/networking/vortex.txt	2003-08-20 14:16:23.000000000 +0100
+++ source/Documentation/networking/vortex.txt	2004-02-23 13:56:39.000000000 +0000
@@ -59,8 +59,8 @@ Module parameters
 =================
 
 There are several parameters which may be provided to the driver when
-its module is loaded.  These are usually placed in /etc/modules.conf
-(used to be conf.modules).  Example:
+its module is loaded.  These are usually placed in /etc/modprobe.conf
+(/etc/modules.conf in 2.4).  Example:
 
 options 3c59x debug=3 rx_copybreak=300
 
@@ -216,6 +216,19 @@ watchdog=N
   to increase this value on LANs which have very high collision rates.
   The default value is 5000 (5.0 seconds).
 
+enable_wol=N1,N2,N3,...
+
+  Enable Wake-on-LAN support for the relevant interface.  Donald
+  Becker's `ether-wake' application may be used to wake suspended
+  machines.
+
+  Also enables the NIC's power management support.
+
+global_enable_wol=N
+
+  Sets enable_wol mode for all 3c59x NICs in the machine.  Entries in
+  the `enable_wol' array above will override any setting of this.
+
 Media selection
 ---------------
 
@@ -413,9 +426,9 @@ steps you should take:
 
       1) Increase the debug level.  Usually this is done via:
 
-         a) modprobe driver.o debug=7
-         b) In /etc/conf.modules (or modules.conf):
-            options driver_name debug=7
+         a) modprobe driver debug=7
+         b) In /etc/modprobe.conf (or /etc/modules.conf for 2.4):
+            options driver debug=7
 
       2) Recreate the problem with the higher debug level,
          send all logs to the maintainer.
--- diff/Documentation/parport.txt	2002-10-16 04:28:25.000000000 +0100
+++ source/Documentation/parport.txt	2004-02-23 13:56:40.000000000 +0000
@@ -39,7 +39,7 @@ are automatically detected.
 KMod
 ----
 
-If you use kmod, you will find it useful to edit /etc/modules.conf.
+If you use kmod, you will find it useful to edit /etc/modprobe.conf.
 Here is an example of the lines that need to be added:
 
 	alias parport_lowlevel parport_pc
--- diff/Documentation/rocket.txt	2003-06-30 10:07:18.000000000 +0100
+++ source/Documentation/rocket.txt	2004-02-23 13:56:40.000000000 +0000
@@ -43,7 +43,7 @@ in the system log at /var/log/messages.
 
 If installed as a module, the module must be loaded.  This can be done
 manually by entering "modprobe rocket".  To have the module loaded automatically
-upon system boot, edit the /etc/modules.conf file and add the line
+upon system boot, edit the /etc/modprobe.conf file and add the line
 "alias char-major-46 rocket".
 
 In order to use the ports, their device names (nodes) must be created with mknod.
--- diff/Documentation/s390/3270.txt	2003-08-20 14:16:23.000000000 +0100
+++ source/Documentation/s390/3270.txt	2004-02-23 13:56:40.000000000 +0000
@@ -48,7 +48,7 @@ one another.  ReIPL as soon as possible 
 script and the resulting /tmp/mkdev3270.
 
 If you have chosen to make tub3270 a module, you add a line to
-/etc/modules.conf.  If you are working on a VM virtual machine, you
+/etc/modprobe.conf.  If you are working on a VM virtual machine, you
 can use DEF GRAF to define virtual 3270 devices.
 
 You may generate both 3270 and 3215 console support, or one or the
@@ -60,7 +60,7 @@ at boot time to a 3270 if it is a 3215.
 
 In brief, these are the steps:
 	1. Install the tub3270 patch
-	2. (If a module) add a line to /etc/modules.conf
+	2. (If a module) add a line to /etc/modprobe.conf
 	3. (If VM) define devices with DEF GRAF
 	4. Reboot
 	5. Configure
@@ -84,13 +84,13 @@ Here are the installation steps in detai
 		make modules_install
 
 	2. (Perform this step only if you have configured tub3270 as a
-	module.)  Add a line to /etc/modules.conf to automatically
+	module.)  Add a line to /etc/modprobe.conf to automatically
 	load the driver when it's needed.  With this line added,
 	you will see login prompts appear on your 3270s as soon as
 	boot is complete (or with emulated 3270s, as soon as you dial
 	into your vm guest using the command "DIAL <vmguestname>").
 	Since the line-mode major number is 227, the line to add to
-	/etc/modules.conf should be:
+	/etc/modprobe.conf should be:
 		alias char-major-227 tub3270
 
 	3. Define graphic devices to your vm guest machine, if you
--- diff/Documentation/s390/CommonIO	2003-09-30 15:46:10.000000000 +0100
+++ source/Documentation/s390/CommonIO	2004-02-23 13:56:40.000000000 +0000
@@ -8,23 +8,26 @@ Command line parameters
   
   Determines whether information on found devices and sensed device 
   characteristics should be shown during startup, i. e. messages of the types 
-  "Detected device 4711 on subchannel 42" and "SenseID: Device 4711 reports: ...".
+  "Detected device 0.0.4711 on subchannel 0.0.0042" and "SenseID: Device
+  0.0.4711 reports: ...".
 
   Default is off.
 
 
 * cio_notoper_msg = yes | no
 
-  Determines whether messages of the type "Device 4711 became 'not operational'"
-  should be shown during startup; after startup, they will always be shown.
+  Determines whether messages of the type "Device 0.0.4711 became 'not
+  operational'" should be shown during startup; after startup, they will always
+  be shown.
   
   Default is on.
 
 
-* cio_ignore = <device number> | <range of device numbers>, 
-	       <device number> | <range of device numbers>, ...
+* cio_ignore = {all} |
+	       {<device> | <range of devices>} |
+	       {!<device> | !<range of devices>}
 
-  The given device numbers will be ignored by the common I/O-layer; no detection
+  The given devices will be ignored by the common I/O-layer; no detection
   and device sensing will be done on any of those devices. The subchannel to 
   which the device in question is attached will be treated as if no device was
   attached.
@@ -32,12 +35,19 @@ Command line parameters
   An ignored device can be un-ignored later; see the "/proc entries"-section for
   details.
 
-  The device numbers must be given hexadecimal.
+  The devices must be given either as bus ids (0.0.abcd) or as hexadecimal
+  device numbers (0xabcd or abcd, for 2.4 backward compatibility).
+  You can use the 'all' keyword to ignore all devices.
+  The '!' operator will cause the I/O-layer to _not_ ignore a device.
+  The order on the command line is not important.
 
   For example, 
-	cio_ignore=0x23-0x42,0x4711
-  will ignore all devices with device numbers ranging from 23 to 42 and the 
-  device with device number 4711, if detected.
+	cio_ignore=0.0.0023-0.0.0042,0.0.4711
+  will ignore all devices ranging from 0.0.0023 to 0.0.0042 and the device
+  0.0.4711, if detected.
+  As another example,
+	cio_ignore=all,!0.0.4711,!0.0.fd00-0.0.fd02
+  will ignore all devices but 0.0.4711, 0.0.fd00, 0.0.fd01, 0.0.fd02.
 
   By default, no devices are ignored.
 
@@ -47,17 +57,19 @@ Command line parameters
 
 * /proc/cio_ignore
 
-  Lists the ranges of device numbers which are ignored by common I/O.
+  Lists the ranges of devices (by bus id) which are ignored by common I/O.
 
   You can un-ignore certain or all devices by piping to /proc/cio_ignore. 
   "free all" will un-ignore all ignored devices, 
-  "free <devnorange>, <devnorange>, ..." will un-ignore the specified devices.
+  "free <device range>, <device range>, ..." will un-ignore the specified
+  devices.
 
-  For example, if devices 23 to 42 and 4711 are ignored,
-  - echo free 0x30-0x32 > /proc/cio_ignore
-    will un-ignore devices 30 to 32 and will leave devices 23 to 2F, 33 to 42
-    and 4711 ignored;
-  - echo free 0x41 > /proc/cio_ignore will furthermore un-ignore device 41;
+  For example, if devices 0.0.0023 to 0.0.0042 and 0.0.4711 are ignored,
+  - echo free 0.0.0030-0.0.0032 > /proc/cio_ignore
+    will un-ignore devices 0.0.0030 to 0.0.0032 and will leave devices 0.0.0023
+    to 0.0.002f, 0.0.0033 to 0.0.0042 and 0.0.4711 ignored;
+  - echo free 0.0.0041 > /proc/cio_ignore will furthermore un-ignore device
+    0.0.0041;
   - echo free all > /proc/cio_ignore will un-ignore all remaining ignored 
     devices.
 
@@ -66,15 +78,19 @@ Command line parameters
   available to the system.
 
   You can also add ranges of devices to be ignored by piping to 
-  /proc/cio_ignore; "add <devnorange>, <devnorange>, ..." will ignore the 
+  /proc/cio_ignore; "add <device range>, <device range>, ..." will ignore the
   specified devices.
 
-  Note: Already known devices cannot be ignored; this also applies to devices
-        which are gone after a machine check.
+  Note: Already known devices cannot be ignored.
 
-  For example, if device abcd is already known and all other devices a000-afff 
-  are not known, "echo add 0xa000-0xaccc, 0xaf00-0xafff > /proc/cio_ignore" 
-  will add af00-afff to the list of ignored devices and skip a000-accc.
+  For example, if device 0.0.abcd is already known and all other devices
+  0.0.a000-0.0.afff are not known,
+	"echo add 0.0.a000-0.0.accc, 0.0.af00-0.0.afff > /proc/cio_ignore"
+  will add 0.0.a000-0.0.abcc, 0.0.abce-0.0.accc and 0.0.af00-0.0.afff to the
+  list of ignored devices and skip 0.0.abcd.
+
+  The devices can be specified either by bus id (0.0.abcd) or, for 2.4 backward
+  compatibilty, by the device number in hexadecimal (0xabcd or abcd).
 
 
 * /proc/s390dbf/cio_*/ (S/390 debug feature)
--- diff/Documentation/s390/driver-model.txt	2004-02-09 10:36:07.000000000 +0000
+++ source/Documentation/s390/driver-model.txt	2004-02-23 13:56:40.000000000 +0000
@@ -216,9 +216,17 @@ mind that most drivers will need to impl
 
 Channel paths show up, like subchannels, under the channel subsystem root (css0)
 and are called 'chp0.<chpid>'. They have no driver and do not belong to any bus.
+Please note, that unlike /proc/chpids in 2.4, the channel path objects reflect
+only the logical state and not the physical state, since we cannot track the
+latter consistently due to lacking machine support (we don't need to be aware
+of anyway).
 
-status - Can be 'online', 'logically offline' or 'n/a'.
+status - Can be 'online' or 'offline'.
 	 Piping 'on' or 'off' sets the chpid logically online/offline.
+	 Piping 'on' to an online chpid triggers path reprobing for all devices
+	 the chpid connects to. This can be used to force the kernel to re-use
+	 a channel path the user knows to be online, but the machine hasn't
+	 created a machine check for.
 
 
 3. System devices
--- diff/Documentation/scsi/aic79xx.txt	2004-01-19 10:22:54.000000000 +0000
+++ source/Documentation/scsi/aic79xx.txt	2004-02-23 13:56:40.000000000 +0000
@@ -210,7 +210,7 @@ The following information is available i
                  INCORRECTLY CAN RENDER YOUR SYSTEM INOPERABLE.
                  USE THEM WITH CAUTION. 
 
-   Edit the file "modules.conf" in the directory /etc and add/edit a
+   Edit the file "modprobe.conf" in the directory /etc and add/edit a
    line containing 'options aic79xx aic79xx=[command[,command...]]' where
    'command' is one or more of the following:
    -----------------------------------------------------------------
--- diff/Documentation/scsi/aic7xxx.txt	2004-01-19 10:22:54.000000000 +0000
+++ source/Documentation/scsi/aic7xxx.txt	2004-02-23 13:56:40.000000000 +0000
@@ -186,7 +186,7 @@ The following information is available i
                  INCORRECTLY CAN RENDER YOUR SYSTEM INOPERABLE.
                  USE THEM WITH CAUTION. 
 
-   Edit the file "modules.conf" in the directory /etc and add/edit a
+   Edit the file "modprobe.conf" in the directory /etc and add/edit a
    line containing 'options aic7xxx aic7xxx=[command[,command...]]' where
    'command' is one or more of the following:
    -----------------------------------------------------------------
--- diff/Documentation/scsi/osst.txt	2002-11-18 10:11:54.000000000 +0000
+++ source/Documentation/scsi/osst.txt	2004-02-23 13:56:40.000000000 +0000
@@ -67,7 +67,7 @@ recognized.
 If you want to have the module autoloaded on access to /dev/osst, you may
 add something like
 alias char-major-206 osst
-to your /etc/modules.conf (old name: conf.modules).
+to your /etc/modprobe.conf (before 2.6: modules.conf).
 
 You may find it convenient to create a symbolic link 
 ln -s nosst0 /dev/tape
--- diff/Documentation/scsi/st.txt	2004-01-19 10:22:54.000000000 +0000
+++ source/Documentation/scsi/st.txt	2004-02-23 13:56:40.000000000 +0000
@@ -2,7 +2,7 @@ This file contains brief information abo
 The driver is currently maintained by Kai Mäkisara (email
 Kai.Makisara@kolumbus.fi)
 
-Last modified: Sun Nov  9 22:36:02 2003 by makisara
+Last modified: Thu Feb 19 21:57:30 2004 by makisara
 
 
 BASICS
@@ -113,6 +113,26 @@ backward compatible with the numbering u
 only 8 bits wide.
 
 
+SYSFS SUPPORT
+
+The driver creates the directory /sys/class/scsi_tape and populates it with
+directories corresponding to the existing tape devices. There are autorewind
+and non-rewind entries for each mode. The names are stxmy and stxmyn, where x
+is the tape number and y is the mode. For example, the directories for the
+first tape device are (assuming four modes): st0m0  st0m0n  st0m1  st0m1n
+st0m2  st0m2n  st0m3  st0m3n.
+
+Each directory contains the entries: default_blksize  default_compression
+default_density  defined  dev  device  driver. The file 'defined' contains 1
+if the mode is defined and zero if not defined. The files 'default_*' contain
+the defaults set by the user. The value -1 means the default is not set. The
+file 'dev' contains the device numbers corresponding to this device. The links
+'device' and 'driver' point to the SCSI device and driver entries.
+
+A link named 'tape' is made from the SCSI device directory to the class
+directory corresponding to the mode 0 auto-rewind device (e.g., st0m0). 
+
+
 BSD AND SYS V SEMANTICS
 
 The user can choose between these two behaviours of the tape driver by
@@ -126,7 +146,7 @@ The default is BSD semantics.
 
 BUFFERING
 
-The driver tries to do tranfers directly to/from user space. If this
+The driver tries to do transfers directly to/from user space. If this
 is not possible, a driver buffer allocated at run-time is used. If
 direct i/o is not possible for the whole transfer, the driver buffer
 is used (i.e., bounce buffers for individual pages are not
@@ -147,6 +167,12 @@ Buffer allocation uses chunks of memory 
 size). Because of this the actual buffer size may be larger than the
 minimum allowable buffer size.
 
+NOTE that if direct i/o is used, the small writes are not buffered. This may
+cause a surprise when moving from 2.4. There small writes (e.g., tar without
+-b option) may have had good throughput but this is not true any more with
+2.6. Direct i/o can be turned off to solve this problem but a better solution
+is to use bigger write() byte counts (e.g., tar -b 64).
+
 Asynchronous writing. Writing the buffer contents to the tape is
 started and the write call returns immediately. The status is checked
 at the next tape operation. Asynchronous writes are not done with
@@ -453,7 +479,7 @@ DEBUGGING HINTS
 
 To enable debugging messages, edit st.c and #define DEBUG 1. As seen
 above, debugging can be switched off with an ioctl if debugging is
-compiled into the driver. The debugging output is not voluminuous.
+compiled into the driver. The debugging output is not voluminous.
 
 If the tape seems to hang, I would be very interested to hear where
 the driver is waiting. With the command 'ps -l' you can see the state
--- diff/Documentation/sonypi.txt	2003-09-17 12:28:01.000000000 +0100
+++ source/Documentation/sonypi.txt	2004-02-23 13:56:40.000000000 +0000
@@ -43,7 +43,7 @@ Driver options:
 ---------------
 
 Several options can be passed to the sonypi driver, either by adding them
-to /etc/modules.conf file, when the driver is compiled as a module or by
+to /etc/modprobe.conf file, when the driver is compiled as a module or by
 adding the following to the kernel command line (in your bootloader):
 
 	sonypi=minor[,verbose[,fnkeyinit[,camera[,compat[,mask[,useinput]]]]]]
@@ -109,7 +109,7 @@ Module use:
 -----------
 
 In order to automatically load the sonypi module on use, you can put those
-lines in your /etc/modules.conf file:
+lines in your /etc/modprobe.conf file:
 
 	alias char-major-10-250 sonypi
 	options sonypi minor=250
--- diff/Documentation/sound/alsa/ALSA-Configuration.txt	2004-02-18 08:54:06.000000000 +0000
+++ source/Documentation/sound/alsa/ALSA-Configuration.txt	2004-02-23 13:56:40.000000000 +0000
@@ -692,6 +692,15 @@ Module parameters
 
     The power-management is supported.
 
+  Module snd-mixart
+  -----------------
+
+    Module for Digigram miXart8 soundcards.
+
+    Module supports multiple cards.
+    Note: One miXart8 board will be represented as 4 alsa cards.
+          See MIXART.txt for details.
+
   Module snd-mpu401
   -----------------
 
--- diff/Documentation/sound/oss/AWE32	2002-10-16 04:28:25.000000000 +0100
+++ source/Documentation/sound/oss/AWE32	2004-02-23 13:56:40.000000000 +0000
@@ -47,12 +47,12 @@ SB32.
 
    Copy it to a directory of your choice, and unpack it there.
 
-4) Edit /etc/modules.conf, and insert the following lines at the end of the
+4) Edit /etc/modprobe.conf, and insert the following lines at the end of the
    file:
 
   alias sound-slot-0 sb
   alias sound-service-0-1 awe_wave
-  post-install awe_wave /usr/local/bin/sfxload PATH_TO_SOUND_BANK_FILE
+  install awe_wave /sbin/modprobe --first-time -i awe_wave && /usr/local/bin/sfxload PATH_TO_SOUND_BANK_FILE
 
   You will of course have to change "PATH_TO_SOUND_BANK_FILE" to the full
   path of of the sound bank file. That will enable the Sound Blaster and AWE
--- diff/Documentation/sound/oss/AudioExcelDSP16	2002-10-16 04:27:08.000000000 +0100
+++ source/Documentation/sound/oss/AudioExcelDSP16	2004-02-23 13:56:40.000000000 +0000
@@ -41,7 +41,7 @@ mpu_base	I/O base address for activate M
 		(0x300, 0x310, 0x320 or 0x330)
 mpu_irq		MPU-401 irq line (5, 7, 9, 10 or 0)
 
-The /etc/modules.conf will have lines like this:
+The /etc/modprobe.conf will have lines like this:
 
 options opl3 io=0x388
 options ad1848 io=0x530 irq=11 dma=3
@@ -51,11 +51,11 @@ Where the aedsp16 options are the option
 ad1848 are the corresponding options for the MSS and OPL3 modules.
 
 Loading MSS and OPL3 needs to pre load the aedsp16 module to set up correctly
-the sound card. Installation dependencies must be written in the modules.conf
+the sound card. Installation dependencies must be written in the modprobe.conf
 file:
 
-pre-install ad1848 modprobe aedsp16
-pre-install opl3 modprobe aedsp16
+install ad1848 /sbin/modprobe aedsp16 && /sbin/modprobe -i ad1848
+install opl3 /sbin/modprobe aedsp16 && /sbin/modprobe -i opl3
 
 Then you must load the sound modules stack in this order:
 sound -> aedsp16 -> [ ad1848, opl3 ]
--- diff/Documentation/sound/oss/CMI8330	2004-01-19 10:22:54.000000000 +0000
+++ source/Documentation/sound/oss/CMI8330	2004-02-23 13:56:40.000000000 +0000
@@ -143,7 +143,7 @@ CONFIG_SOUND_MSS=m
 
 
 
-Alma Chao <elysian@ethereal.torsion.org> suggests the following /etc/modules.conf:
+Alma Chao <elysian@ethereal.torsion.org> suggests the following /etc/modprobe.conf:
 
 alias sound ad1848
 alias synth0 opl3
--- diff/Documentation/sound/oss/Introduction	2004-01-19 10:22:54.000000000 +0000
+++ source/Documentation/sound/oss/Introduction	2004-02-23 13:56:40.000000000 +0000
@@ -168,7 +168,7 @@ MODPROBE:
 =========
 
 If loading via modprobe, these common files are automatically loaded 
-when requested by modprobe.  For example, my /etc/modules.conf contains:
+when requested by modprobe.  For example, my /etc/modprobe.conf contains:
 
 alias sound sb 
 options sb io=0x240 irq=9 dma=3 dma16=5 mpu_io=0x300
@@ -228,7 +228,7 @@ http://www.opensound.com.  Before loadin
 driver, you should do the following:
 
 1.  remove sound modules (detailed above)
-2.  remove the sound modules from /etc/modules.conf
+2.  remove the sound modules from /etc/modprobe.conf
 3.  move the sound modules from /lib/modules/<kernel>/misc
     (for example, I make a /lib/modules/<kernel>/misc/tmp
     directory and copy the sound module files to that 
@@ -265,7 +265,7 @@ twice, you need to do the following:
     sb.o could be copied (or symlinked) to sb1.o for the
     second SoundBlaster.
 
-2.  Make a second entry in /etc/modules.conf, for example,
+2.  Make a second entry in /etc/modprobe.conf, for example,
     sound1 or sb1.  This second entry should refer to the
     new module names for example sb1, and should include
     the I/O, etc. for the second sound card.
@@ -369,7 +369,7 @@ There are several ways of configuring yo
 2)  On the command line when using insmod or in a bash script
     using command line calls to load sound.
 
-3)  In /etc/modules.conf when using modprobe.
+3)  In /etc/modprobe.conf when using modprobe.
 
 4)  Via Red Hat's GPL'd /usr/sbin/sndconfig program (text based).
 
--- diff/Documentation/sound/oss/MAD16	2002-10-16 04:29:06.000000000 +0100
+++ source/Documentation/sound/oss/MAD16	2004-02-23 13:56:40.000000000 +0000
@@ -1,4 +1,5 @@
-(This recipe has been edited to update the configuration symbols.)
+(This recipe has been edited to update the configuration symbols,
+ and change over to modprobe.conf for 2.6)
 
 From: Shaw Carruthers <shaw@shawc.demon.co.uk>
 
@@ -20,9 +21,9 @@ CONFIG_SOUND_ADLIB=m
 CONFIG_SOUND_MAD16=m
 CONFIG_SOUND_YM3812=m
 
-modules.conf has:
+modprobe.conf has:
 
-alias char-major-14 mad16
+alias char-major-14-* mad16
 options sb mad16=1
 options mad16 io=0x530 irq=7 dma=0 dma16=1  && /usr/local/bin/aumix -w 15 -p 20 -m 0 -1 0 -2 0 -3 0 -i 0
 
--- diff/Documentation/sound/oss/Maestro3	2002-10-16 04:28:34.000000000 +0100
+++ source/Documentation/sound/oss/Maestro3	2004-02-23 13:56:40.000000000 +0000
@@ -64,7 +64,7 @@ It may be modular or statically linked. 
 installed with the rest of the modules for the kernel on the system.
 Typically this will be in /lib/modules/ somewhere.  'alias sound-slot-0
 maestro3' should also be added to your module configs (typically
-/etc/modules.conf) if you're using modular OSS/Lite sound and want to
+/etc/modprobe.conf) if you're using modular OSS/Lite sound and want to
 default to using a maestro3 chip.
 
 There are very few options to the driver.  One is 'debug' which will 
--- diff/Documentation/sound/oss/OPL3-SA2	2002-10-16 04:27:14.000000000 +0100
+++ source/Documentation/sound/oss/OPL3-SA2	2004-02-23 13:56:40.000000000 +0000
@@ -162,7 +162,7 @@ modprobe opl3sa2 io=0x370 mss_io=0x530 m
 modprobe opl3 io=0x388
 
 See the section "Automatic Module Loading" below for how to set up
-/etc/modules.conf to automate this.
+/etc/modprobe.conf to automate this.
 
 An important thing to remember that the opl3sa2 module's io argument is
 for it's own control port, which handles the card's master mixer for
@@ -196,7 +196,7 @@ Automatic Module Loading
 
 Lastly, if you're using modules and want to set up automatic module
 loading with kmod, the kernel module loader, here is the section I
-currently use in my modules.conf file:
+currently use in my modprobe.conf file:
 
 # Sound
 alias sound-slot-0 opl3sa2
--- diff/Documentation/sound/oss/Opti	2002-10-16 04:27:53.000000000 +0100
+++ source/Documentation/sound/oss/Opti	2004-02-23 13:56:40.000000000 +0000
@@ -18,7 +18,7 @@ force the card into a mode in which it c
 If you have another OS installed on your computer it is recommended
 that Linux and the other OS use the same resources.
 
-Also, it is recommended that resources specified in /etc/modules.conf
+Also, it is recommended that resources specified in /etc/modprobe.conf
 and resources specified in /etc/isapnp.conf agree.
 
 Compiling the sound driver
@@ -68,9 +68,9 @@ address is hard-coded into the driver.
 Using kmod and autoloading the sound driver
 -------------------------------------------
 Comment: as of linux-2.1.90 kmod is replacing kerneld.
-The config file '/etc/modules.conf' is used as before.
+The config file '/etc/modprobe.conf' is used as before.
 
-This is the sound part of my /etc/modules.conf file.
+This is the sound part of my /etc/modprobe.conf file.
 Following that I will explain each line.
 
 alias mixer0 mad16
@@ -80,7 +80,7 @@ alias synth0 opl3
 options sb mad16=1
 options mad16 irq=10 dma=0 dma16=1 io=0x530 joystick=1 cdtype=0
 options opl3 io=0x388
-post-install mad16 /sbin/ad1848_mixer_reroute 14 8 15 3 16 6
+install mad16 /sbin/modprobe -i mad16 && /sbin/ad1848_mixer_reroute 14 8 15 3 16 6
 
 If you have an MPU daughtercard or onboard MPU you will want to add to the
 "options mad16" line - eg 
--- diff/Documentation/sound/oss/PAS16	2004-01-19 10:22:54.000000000 +0000
+++ source/Documentation/sound/oss/PAS16	2004-02-23 13:56:40.000000000 +0000
@@ -129,7 +129,7 @@ CONFIG_SOUND_YM3812
   You can then get OPL3 functionality by issuing the command:
   insmod opl3
   In addition, you must either add the following line to 
-  /etc/modules.conf:
+  /etc/modprobe.conf:
   options opl3 io=0x388
   or else add the following line to /etc/lilo.conf:
   opl3=0x388
@@ -159,5 +159,5 @@ following line would be appropriate:
 append="pas2=0x388,10,3,-1,0,-1,-1,-1 opl3=0x388"
 
 If sound is built totally modular, the above options may be 
-specified in /etc/modules.conf for pas2.o, sb.o and opl3.o 
+specified in /etc/modprobe.conf for pas2, sb and opl3
 respectively. 
--- diff/Documentation/sound/oss/README.modules	2002-10-16 04:27:53.000000000 +0100
+++ source/Documentation/sound/oss/README.modules	2004-02-23 13:56:40.000000000 +0000
@@ -26,10 +26,10 @@ Note that it is no longer necessary or p
 drivers/sound dir. Now one simply configures and makes one's kernel and
 modules in the usual way.
 
- Then, add to your /etc/modules.conf something like:
+ Then, add to your /etc/modprobe.conf something like:
 
-alias char-major-14 sb
-post-install sb /sbin/modprobe "-k" "adlib_card"
+alias char-major-14-* sb
+install sb /sbin/modprobe -i sb && /sbin/modprobe adlib_card
 options sb io=0x220 irq=7 dma=1 dma16=5 mpu_io=0x330
 options adlib_card io=0x388     # FM synthesizer
 
@@ -65,12 +65,12 @@ at the init_module() code for the card t
  Note that at present there is no way to configure the io, irq and other
 parameters for the modular drivers as one does for the wired drivers.. One
 needs to pass the modules the necessary parameters as arguments, either
-with /etc/modules.conf or with command-line args to modprobe, e.g.
+with /etc/modprobe.conf or with command-line args to modprobe, e.g.
 
-modprobe -k sb io=0x220 irq=7 dma=1 dma16=5 mpu_io=0x330
-modprobe -k adlib_card io=0x388
+modprobe sb io=0x220 irq=7 dma=1 dma16=5 mpu_io=0x330
+modprobe adlib_card io=0x388
 
- recommend using /etc/modules.conf.
+ recommend using /etc/modprobe.conf.
 
 Persistent DMA Buffers:
 
@@ -88,7 +88,7 @@ wasteful of RAM, but it guarantees that 
 
 To make the sound driver use persistent DMA buffers we need to pass the
 sound.o module a "dmabuf=1" command-line argument. This is normally done
-in /etc/modules.conf like so:
+in /etc/modprobe.conf like so:
 
 options sound		dmabuf=1
 
--- diff/Documentation/sound/oss/Wavefront	2004-01-19 10:22:54.000000000 +0000
+++ source/Documentation/sound/oss/Wavefront	2004-02-23 13:56:40.000000000 +0000
@@ -189,16 +189,15 @@ Here's my autoconf.h SOUND section:
 6) How do I configure my card ?
 ************************************************************
 
-You need to edit /etc/modules.conf. Here's mine (edited to show the
+You need to edit /etc/modprobe.conf. Here's mine (edited to show the
 relevant details):
 
   # Sound system
-  alias char-major-14 wavefront
+  alias char-major-14-* wavefront
   alias synth0 wavefront
   alias mixer0 cs4232
   alias audio0 cs4232
-  pre-install wavefront modprobe "-k" "cs4232"
-  post-install wavefront modprobe "-k" "opl3"
+  install wavefront /sbin/modprobe cs4232 && /sbin/modprobe -i wavefront && /sbin/modprobe opl3
   options wavefront io=0x200 irq=9
   options cs4232 synthirq=9 synthio=0x200 io=0x530 irq=5 dma=1 dma2=0
   options opl3 io=0x388
--- diff/Documentation/sysctl/fs.txt	2003-01-02 10:43:02.000000000 +0000
+++ source/Documentation/sysctl/fs.txt	2004-02-23 13:56:40.000000000 +0000
@@ -138,3 +138,13 @@ thus the maximum number of mounted files
 can have. You only need to increase super-max if you need to
 mount more filesystems than the current value in super-max
 allows you to.
+
+==============================================================
+
+aio-nr & aio-max-nr:
+
+aio-nr shows the current system-wide number of asynchronous io
+requests.  aio-max-nr allows you to change the maximum value
+aio-nr can grow to.
+
+==============================================================
--- diff/Documentation/usb/acm.txt	2002-10-16 04:27:22.000000000 +0100
+++ source/Documentation/usb/acm.txt	2004-02-23 13:56:40.000000000 +0000
@@ -28,7 +28,7 @@ in the package: See the file COPYING.
 
 1. Usage
 ~~~~~~~~
-  The drivers/usb/acm.c drivers works with USB modems and USB ISDN terminal
+  The drivers/usb/class/cdc-acm.c drivers works with USB modems and USB ISDN terminal
 adapters that conform to the Universal Serial Bus Communication Device Class
 Abstract Control Model (USB CDC ACM) specification.
 
@@ -65,9 +65,9 @@ minor/major numbers anywhere you want, b
 
   To use the modems you need these modules loaded:
 
-	usbcore.o
-	usb-[uo]hci.o or uhci.o
-	acm.o
+	usbcore.ko
+	uhci-hcd.ko ohci-hcd.ko or ehci-hcd.ko
+	cdc-acm.ko
 
   After that, the modem[s] should be accessible. You should be able to use
 minicom, ppp and mgetty with them.
--- diff/Documentation/usb/scanner.txt	2003-05-21 11:49:49.000000000 +0100
+++ source/Documentation/usb/scanner.txt	2004-02-23 13:56:40.000000000 +0000
@@ -146,14 +146,14 @@ options to the driver.  Simply add 
 
   options scanner vendor=0x#### product=0x****
 
-to the /etc/modules.conf file replacing the #'s and the *'s with the
+to the /etc/modprobe.conf file replacing the #'s and the *'s with the
 correct IDs.  The IDs can be retrieved from the messages file or
 using "cat /proc/bus/usb/devices".
 
 If the default timeout is too low, i.e. there are frequent "timeout" messages,
 you may want to increase the timeout manually by using the parameter
 "read_timeout".  The time is given in seconds.  This is an example for
-modules.conf with a timeout of 60 seconds:
+modprobe.conf with a timeout of 60 seconds:
 
   options scanner read_timeout=60
  
--- diff/Documentation/video4linux/CQcam.txt	2003-10-09 09:47:33.000000000 +0100
+++ source/Documentation/video4linux/CQcam.txt	2004-02-23 13:56:40.000000000 +0000
@@ -62,7 +62,7 @@ But that is my personal preference.
  
   The configuration requires module configuration and device
 configuration.  I like kmod or kerneld process with the
-/etc/modules.conf file so the modules can automatically load/unload as
+/etc/modprobe.conf file so the modules can automatically load/unload as
 they are used.  The video devices could already exist, be generated
 using MAKEDEV, or need to be created.  The following sections detail
 these procedures.
@@ -71,15 +71,15 @@ these procedures.
 2.1 Module Configuration  
 
   Using modules requires a bit of work to install and pass the
-parameters.  Understand that entries in /etc/modules.conf of:
+parameters.  Understand that entries in /etc/modprobe.conf of:
 
    alias parport_lowlevel parport_pc
    options parport_pc io=0x378 irq=none
    alias char-major-81 videodev
    alias char-major-81-0 c-qcam
 
-will cause the kmod/kerneld/modprobe to do certain things.  If you are
-using kmod or kerneld, then a request for a 'char-major-81-0' will cause
+will cause the kmod/modprobe to do certain things.  If you are
+using kmod, then a request for a 'char-major-81-0' will cause
 the 'c-qcam' module to load.  If you have other video sources with
 modules, you might want to assign the different minor numbers to
 different modules.
--- diff/Documentation/video4linux/Zoran	2003-09-30 15:46:10.000000000 +0100
+++ source/Documentation/video4linux/Zoran	2004-02-23 13:56:40.000000000 +0000
@@ -233,7 +233,7 @@ Load zr36067.o. If it can't autodetect y
 option with X being the card number as given in the previous section.
 To have more than one card, use card=X1[,X2[,X3,[X4[..]]]]
 
-To automate this, add the following to your /etc/modules.conf:
+To automate this, add the following to your /etc/modprobe.conf:
 
 options zr36067 card=X1[,X2[,X3[,X4[..]]]]
 alias char-major-81-0 zr36067
--- diff/Documentation/video4linux/bttv/Modules.conf	2002-10-16 04:28:23.000000000 +0100
+++ source/Documentation/video4linux/bttv/Modules.conf	2004-02-23 13:56:40.000000000 +0000
@@ -1,3 +1,6 @@
+# For modern kernels (2.6 or above), this belongs in /etc/modprobe.conf
+# For for 2.4 kernels or earlier, this belongs in /etc/modules.conf.
+
 # i2c
 alias char-major-89	i2c-dev
 options i2c-core	i2c_debug=1
--- diff/Documentation/video4linux/bttv/README	2004-02-09 10:36:07.000000000 +0000
+++ source/Documentation/video4linux/bttv/README	2004-02-23 13:56:40.000000000 +0000
@@ -22,7 +22,7 @@ very likely specified the wrong (or no) 
 cards is in CARDLIST.bttv
 
 If bttv takes very long to load (happens sometimes with the cheap
-cards which have no tuner), try adding this to your modules.conf:
+cards which have no tuner), try adding this to your modprobe.conf:
 	options i2c-algo-bit bit_test=1
 
 For the WinTV/PVR you need one firmware file from the driver CD:
--- diff/Documentation/video4linux/meye.txt	2003-11-25 15:24:57.000000000 +0000
+++ source/Documentation/video4linux/meye.txt	2004-02-23 13:56:40.000000000 +0000
@@ -42,7 +42,7 @@ Driver options:
 ---------------
 
 Several options can be passed to the meye driver, either by adding them
-to /etc/modules.conf file, when the driver is compiled as a module, or
+to /etc/modprobe.conf file, when the driver is compiled as a module, or
 by adding the following to the kernel command line (in your bootloader):
 
 	meye=gbuffers[,gbufsize[,video_nr]]
@@ -59,7 +59,7 @@ Module use:
 -----------
 
 In order to automatically load the meye module on use, you can put those lines
-in your /etc/modules.conf file:
+in your /etc/modprobe.conf file:
 
 	alias char-major-81 videodev
 	alias char-major-81-0 meye
--- diff/MAINTAINERS	2004-02-18 08:54:06.000000000 +0000
+++ source/MAINTAINERS	2004-02-23 13:56:48.000000000 +0000
@@ -521,7 +521,7 @@ CPU FREQUENCY DRIVERS
 P:	Dave Jones
 M:	davej@codemonkey.org.uk
 L:	cpufreq@www.linux.org.uk
-W:	http://www.codemonkey.org.uk/cpufreq/
+W:	http://www.codemonkey.org.uk/projects/cpufreq/
 S:	Maintained
 
 CPUID/MSR DRIVER
@@ -862,8 +862,8 @@ W:	http://www.nyx.net/~arobinso
 S:	Maintained
 
 HFS FILESYSTEM
-P:	Oliver Neukum
-M:	oliver@neukum.org
+P:	Roman Zippel
+M:	zippel@linux-m68k.org
 L:	linux-kernel@vger.kernel.org
 S:	Maintained
 
@@ -1186,6 +1186,12 @@ W:	http://sf.net/projects/kernel-janitor
 W:	http://developer.osdl.org/rddunlap/kj-patches/
 S:	Maintained
 
+KGDB FOR I386 PLATFORM
+P:	George Anzinger
+M:	george@mvista.com
+L:	linux-net@vger.kernel.org
+S:	Supported
+
 KERNEL NFSD
 P:	Neil Brown
 M:	neilb@cse.unsw.edu.au
--- diff/Makefile	2004-02-18 08:54:06.000000000 +0000
+++ source/Makefile	2004-02-23 13:56:48.000000000 +0000
@@ -1,7 +1,7 @@
 VERSION = 2
 PATCHLEVEL = 6
 SUBLEVEL = 3
-EXTRAVERSION =
+EXTRAVERSION = -mm3
 NAME=Feisty Dunnart
 
 # *DOCUMENTATION*
@@ -283,7 +283,7 @@ AFLAGS		:= -D__ASSEMBLY__
 export	VERSION PATCHLEVEL SUBLEVEL EXTRAVERSION KERNELRELEASE ARCH \
 	CONFIG_SHELL HOSTCC HOSTCFLAGS CROSS_COMPILE AS LD CC \
 	CPP AR NM STRIP OBJCOPY OBJDUMP MAKE AWK GENKSYMS PERL UTS_MACHINE \
-	HOSTCXX HOSTCXXFLAGS LDFLAGS_BLOB LDFLAGS_MODULE CHECK
+	HOSTCXX HOSTCXXFLAGS LDFLAGS_MODULE CHECK
 
 export CPPFLAGS NOSTDINC_FLAGS OBJCOPYFLAGS LDFLAGS
 export CFLAGS CFLAGS_KERNEL CFLAGS_MODULE 
@@ -444,6 +444,7 @@ endif
 
 ifdef CONFIG_DEBUG_INFO
 CFLAGS		+= -g
+AFLAGS		+= -g
 endif
 
 # warn about C99 declaration after statement
--- diff/arch/alpha/Kconfig	2004-02-09 10:36:07.000000000 +0000
+++ source/arch/alpha/Kconfig	2004-02-23 13:56:37.000000000 +0000
@@ -569,24 +569,6 @@ config VERBOSE_MCHECK_ON
 source "drivers/pci/Kconfig"
 source "drivers/eisa/Kconfig"
 
-config HOTPLUG
-	bool "Support for hot-pluggable devices"
-	---help---
-	  Say Y here if you want to plug devices into your computer while
-	  the system is running, and be able to use them quickly.  In many
-	  cases, the devices can likewise be unplugged at any time too.
-
-	  One well known example of this is PCMCIA- or PC-cards, credit-card
-	  size devices such as network cards, modems or hard drives which are
-	  plugged into slots found on all modern laptop computers.  Another
-	  example, used on modern desktops as well as laptops, is USB.
-
-	  Enable HOTPLUG and KMOD, and build a modular kernel.  Get agent
-	  software (at <http://linux-hotplug.sourceforge.net/>) and install it.
-	  Then your kernel will automatically call out to a user mode "policy
-	  agent" (/sbin/hotplug) to load modules and set up software needed
-	  to use devices as you hotplug them.
-
 source "drivers/pcmcia/Kconfig"
 
 config SRM_ENV
--- diff/arch/alpha/kernel/alpha_ksyms.c	2003-06-30 10:07:32.000000000 +0100
+++ source/arch/alpha/kernel/alpha_ksyms.c	2004-02-23 13:56:37.000000000 +0000
@@ -11,6 +11,7 @@
 #include <linux/user.h>
 #include <linux/elfcore.h>
 #include <linux/socket.h>
+#include <linux/syscalls.h>
 #include <linux/in.h>
 #include <linux/in6.h>
 #include <linux/pci.h>
--- diff/arch/alpha/kernel/irq.c	2004-01-19 10:22:54.000000000 +0000
+++ source/arch/alpha/kernel/irq.c	2004-02-23 13:56:37.000000000 +0000
@@ -252,7 +252,7 @@ static int
 irq_affinity_read_proc (char *page, char **start, off_t off,
 			int count, int *eof, void *data)
 {
-	int len = cpumask_snprintf(page, count, irq_affinity[(long)data]);
+	int len = cpumask_scnprintf(page, count, irq_affinity[(long)data]);
 	if (count - len < 2)
 		return -EINVAL;
 	len += sprintf(page + len, "\n");
@@ -333,7 +333,7 @@ static int
 prof_cpu_mask_read_proc(char *page, char **start, off_t off,
 			int count, int *eof, void *data)
 {
-	int len = cpumask_snprintf(page, count, *(cpumask_t *)data);
+	int len = cpumask_scnprintf(page, count, *(cpumask_t *)data);
 	if (count - len < 2)
 		return -EINVAL;
 	len += sprintf(page + len, "\n");
--- diff/arch/alpha/kernel/osf_sys.c	2003-08-20 14:16:23.000000000 +0100
+++ source/arch/alpha/kernel/osf_sys.c	2004-02-23 13:56:37.000000000 +0000
@@ -17,6 +17,7 @@
 #include <linux/smp.h>
 #include <linux/smp_lock.h>
 #include <linux/stddef.h>
+#include <linux/syscalls.h>
 #include <linux/unistd.h>
 #include <linux/ptrace.h>
 #include <linux/slab.h>
@@ -46,7 +47,6 @@
 #include <asm/processor.h>
 
 extern int do_pipe(int *);
-extern asmlinkage unsigned long sys_brk(unsigned long);
 
 /*
  * Brk needs to return an error.  Still support Linux's brk(0) query idiom,
@@ -821,7 +821,6 @@ osf_setsysinfo(unsigned long op, void *b
    affects all sorts of things, like timeval and itimerval.  */
 
 extern struct timezone sys_tz;
-extern asmlinkage int sys_utimes(char *, struct timeval *);
 extern int do_adjtimex(struct timex *);
 
 struct timeval32
@@ -1315,8 +1314,6 @@ arch_get_unmapped_area(struct file *filp
 }
 
 #ifdef CONFIG_OSF4_COMPAT
-extern ssize_t sys_readv(unsigned long, const struct iovec *, unsigned long);
-extern ssize_t sys_writev(unsigned long, const struct iovec *, unsigned long);
 
 /* Clear top 32 bits of iov_len in the user's buffer for
    compatibility with old versions of OSF/1 where iov_len
--- diff/arch/alpha/kernel/time.c	2003-10-09 09:47:33.000000000 +0100
+++ source/arch/alpha/kernel/time.c	2004-02-23 13:56:37.000000000 +0000
@@ -503,6 +503,7 @@ do_settimeofday(struct timespec *tv)
 	time_esterror = NTP_PHASE_LIMIT;
 
 	write_sequnlock_irq(&xtime_lock);
+	clock_was_set();
 	return 0;
 }
 
--- diff/arch/arm/Kconfig	2004-02-18 08:54:06.000000000 +0000
+++ source/arch/arm/Kconfig	2004-02-23 13:56:37.000000000 +0000
@@ -365,24 +365,6 @@ endif
 
 source "drivers/pci/Kconfig"
 
-config HOTPLUG
-	bool "Support for hot-pluggable devices"
-	---help---
-	  Say Y here if you want to plug devices into your computer while
-	  the system is running, and be able to use them quickly.  In many
-	  cases, the devices can likewise be unplugged at any time too.
-
-	  One well known example of this is PCMCIA- or PC-cards, credit-card
-	  size devices such as network cards, modems or hard drives which are
-	  plugged into slots found on all modern laptop computers.  Another
-	  example, used on modern desktops as well as laptops, is USB.
-
-	  Enable HOTPLUG and KMOD, and build a modular kernel.  Get agent
-	  software (at <http://linux-hotplug.sourceforge.net/>) and install it.
-	  Then your kernel will automatically call out to a user mode "policy
-	  agent" (/sbin/hotplug) to load modules and set up software needed
-	  to use devices as you hotplug them.
-
 source "drivers/pcmcia/Kconfig"
 
 comment "At least one math emulation must be selected"
@@ -439,9 +421,9 @@ config PM
 
 	  Power Management is most important for battery powered laptop
 	  computers; if you have a laptop, check out the Linux Laptop home
-	  page on the WWW at
-	  <http://www.cs.utexas.edu/users/kharker/linux-laptop/> and the
-	  Battery Powered Linux mini-HOWTO, available from
+	  page on the WWW at <http://www.linux-on-laptops.com/> or
+	  Tuxmobil - Linux on Mobile Computers at <http://www.tuxmobil.org/>
+	  and the Battery Powered Linux mini-HOWTO, available from
 	  <http://www.tldp.org/docs.html#howto>.
 
 	  Note that, even if you say N here, Linux on the x86 architecture
@@ -639,6 +621,8 @@ source "drivers/media/Kconfig"
 
 source "fs/Kconfig"
 
+source "arch/arm/oprofile/Kconfig"
+
 source "drivers/video/Kconfig"
 
 if ARCH_ACORN || ARCH_CLPS7500 || ARCH_TBOX || ARCH_SHARK || ARCH_SA1100 || PCI
--- diff/arch/arm/Makefile	2004-01-19 10:22:54.000000000 +0000
+++ source/arch/arm/Makefile	2004-02-23 13:56:37.000000000 +0000
@@ -8,7 +8,6 @@
 # Copyright (C) 1995-2001 by Russell King
 
 LDFLAGS_vmlinux	:=-p -X
-LDFLAGS_BLOB	:=--format binary
 AFLAGS_vmlinux.lds.o = -DTEXTADDR=$(TEXTADDR) -DDATAADDR=$(DATAADDR)
 OBJCOPYFLAGS	:=-O binary -R .note -R .comment -S
 GZFLAGS		:=-9
@@ -56,11 +55,6 @@ DATAADDR	:= .
 
 PROCESSOR	:= armv
 head-y		:= arch/arm/kernel/head.o arch/arm/kernel/init_task.o
-ifeq ($(CONFIG_CPU_BIG_ENDIAN),y)
-  LDFLAGS_BLOB	+= --oformat elf32-bigarm
-else
-  LDFLAGS_BLOB	+= --oformat elf32-littlearm
-endif
 textaddr-y	:= 0xC0008000
 
  machine-$(CONFIG_ARCH_ARCA5K)	   := arc
@@ -116,6 +110,7 @@ endif
 core-$(CONFIG_FPE_NWFPE)	+= arch/arm/nwfpe/
 core-$(CONFIG_FPE_FASTFPE)	+= $(FASTFPE_OBJ)
 
+drivers-$(CONFIG_OPROFILE)      += arch/arm/oprofile/
 drivers-$(CONFIG_ARCH_CLPS7500)	+= drivers/acorn/char/
 drivers-$(CONFIG_ARCH_L7200)	+= drivers/acorn/char/
 
--- diff/arch/arm/kernel/armksyms.c	2004-01-19 10:22:54.000000000 +0000
+++ source/arch/arm/kernel/armksyms.c	2004-02-23 13:56:37.000000000 +0000
@@ -22,6 +22,7 @@
 #include <linux/tty.h>
 #include <linux/vt_kern.h>
 #include <linux/smp_lock.h>
+#include <linux/syscalls.h>
 
 #include <asm/byteorder.h>
 #include <asm/elf.h>
@@ -44,14 +45,6 @@ extern void outswb(unsigned int port, co
 extern void __bad_xchg(volatile void *ptr, int size);
 
 /*
- * syscalls
- */
-extern int sys_write(int, const char *, int);
-extern int sys_read(int, char *, int);
-extern int sys_lseek(int, off_t, int);
-extern int sys_exit(int);
-
-/*
  * libgcc functions - functions that are used internally by the
  * compiler...  (prototypes are not correct though, but that
  * doesn't really matter since they're not versioned).
--- diff/arch/arm/kernel/sys_arm.c	2003-06-09 14:18:17.000000000 +0100
+++ source/arch/arm/kernel/sys_arm.c	2004-02-23 13:56:37.000000000 +0000
@@ -20,6 +20,7 @@
 #include <linux/msg.h>
 #include <linux/shm.h>
 #include <linux/stat.h>
+#include <linux/syscalls.h>
 #include <linux/mman.h>
 #include <linux/fs.h>
 #include <linux/file.h>
@@ -137,7 +138,6 @@ out:
  * Perform the select(nd, in, out, ex, tv) and mmap() system
  * calls.
  */
-extern asmlinkage int sys_select(int, fd_set *, fd_set *, fd_set *, struct timeval *);
 
 struct sel_arg_struct {
 	unsigned long n;
--- diff/arch/arm/kernel/time.c	2004-02-18 08:54:06.000000000 +0000
+++ source/arch/arm/kernel/time.c	2004-02-23 13:56:37.000000000 +0000
@@ -85,6 +85,9 @@ unsigned long long __attribute__((weak))
  */
 static inline void do_profile(struct pt_regs *regs)
 {
+
+	profile_hook(regs);
+
 	if (!user_mode(regs) &&
 	    prof_buffer &&
 	    current->pid) {
@@ -175,7 +178,7 @@ static int __init leds_init(void)
 	int ret;
 	ret = sysdev_class_register(&leds_sysclass);
 	if (ret == 0)
-		ret = sys_device_register(&leds_device);
+		ret = sysdev_register(&leds_device);
 	return ret;
 }
 
--- diff/arch/arm/mach-integrator/integrator_ap.c	2004-02-18 08:54:06.000000000 +0000
+++ source/arch/arm/mach-integrator/integrator_ap.c	2004-02-23 13:56:37.000000000 +0000
@@ -173,7 +173,7 @@ static int __init irq_init_sysfs(void)
 {
 	int ret = sysdev_class_register(&irq_class);
 	if (ret == 0)
-		ret = sys_device_register(&irq_device);
+		ret = sysdev_register(&irq_device);
 	return ret;
 }
 
--- diff/arch/arm/mach-sa1100/irq.c	2003-06-30 10:07:32.000000000 +0100
+++ source/arch/arm/mach-sa1100/irq.c	2004-02-23 13:56:37.000000000 +0000
@@ -278,7 +278,7 @@ static struct sys_device sa1100irq_devic
 static int __init sa1100irq_init_devicefs(void)
 {
 	sysdev_class_register(&sa1100irq_sysclass);
-	return sys_device_register(&sa1100irq_device);
+	return sysdev_register(&sa1100irq_device);
 }
 
 device_initcall(sa1100irq_init_devicefs);
--- diff/arch/arm/mm/Kconfig	2004-02-18 08:54:06.000000000 +0000
+++ source/arch/arm/mm/Kconfig	2004-02-23 13:56:37.000000000 +0000
@@ -91,10 +91,28 @@ config CPU_ARM922T
 	  Say Y if you want support for the ARM922T processor.
 	  Otherwise, say N.
 
+# ARM925T
+config CPU_ARM925T
+ 	bool
+ 	depends on ARCH_OMAP1510
+ 	default y
+	select CPU_32v4
+	select CPU_ABRT_EV4T
+	select CPU_CACHE_V4WT
+	select CPU_COPY_V4WB
+	select CPU_TLB_V4WBI
+ 	help
+ 	  The ARM925T is a mix between the ARM920T and ARM926T, but with
+	  different instruction and data caches. It is used in TI's OMAP
+ 	  device family.
+
+ 	  Say Y if you want support for the ARM925T processor.
+ 	  Otherwise, say N.
+
 # ARM926T
 config CPU_ARM926T
 	bool "Support ARM926T processor"
-	depends on ARCH_INTEGRATOR
+	depends on ARCH_INTEGRATOR || ARCH_OMAP1610
 	select CPU_32v5
 	select CPU_ABRT_EV5TJ
 	select CPU_COPY_V4WB
@@ -288,7 +306,7 @@ comment "Processor Features"
 
 config ARM_THUMB
 	bool "Support Thumb user binaries"
-	depends on CPU_ARM720T || CPU_ARM920T || CPU_ARM922T || CPU_ARM926T || CPU_ARM1020 || CPU_ARM1020E || CPU_ARM1022 || CPU_ARM1026 || CPU_XSCALE
+	depends on CPU_ARM720T || CPU_ARM920T || CPU_ARM922T || CPU_ARM925T || CPU_ARM926T || CPU_ARM1020 || CPU_ARM1020E || CPU_ARM1022 || CPU_ARM1026 || CPU_XSCALE
 	default y
 	help
 	  Say Y if you want to include kernel support for running user space
@@ -311,21 +329,21 @@ config CPU_BIG_ENDIAN
 
 config CPU_ICACHE_DISABLE
 	bool "Disable I-Cache"
-	depends on CPU_ARM920T || CPU_ARM922T || CPU_ARM926T || CPU_ARM1020
+	depends on CPU_ARM920T || CPU_ARM922T ||  CPU_ARM925T || CPU_ARM926T || CPU_ARM1020
 	help
 	  Say Y here to disable the processor instruction cache. Unless
 	  you have a reason not to or are unsure, say N.
 
 config CPU_DCACHE_DISABLE
 	bool "Disable D-Cache"
-	depends on CPU_ARM920T || CPU_ARM922T || CPU_ARM926T || CPU_ARM1020
+	depends on CPU_ARM920T || CPU_ARM922T || CPU_ARM925T || CPU_ARM926T || CPU_ARM1020
 	help
 	  Say Y here to disable the processor data cache. Unless
 	  you have a reason not to or are unsure, say N.
 
 config CPU_DCACHE_WRITETHROUGH
 	bool "Force write through D-cache"
-	depends on (CPU_ARM920T || CPU_ARM922T || CPU_ARM926T || CPU_ARM1020) && !CPU_DISABLE_DCACHE
+	depends on (CPU_ARM920T || CPU_ARM922T ||  CPU_ARM925T || CPU_ARM926T || CPU_ARM1020) && !CPU_DISABLE_DCACHE
 	help
 	  Say Y here to use the data cache in writethough mode. Unless you
 	  specifically require this or are unsure, say N.
--- diff/arch/arm/mm/Makefile	2003-09-30 15:46:11.000000000 +0100
+++ source/arch/arm/mm/Makefile	2004-02-23 13:56:37.000000000 +0000
@@ -39,6 +39,7 @@ obj-$(CONFIG_CPU_ARM710)	+= proc-arm6_7.
 obj-$(CONFIG_CPU_ARM720T)	+= proc-arm720.o
 obj-$(CONFIG_CPU_ARM920T)	+= proc-arm920.o
 obj-$(CONFIG_CPU_ARM922T)	+= proc-arm922.o
+obj-$(CONFIG_CPU_ARM925T)	+= proc-arm925.o
 obj-$(CONFIG_CPU_ARM926T)	+= proc-arm926.o
 obj-$(CONFIG_CPU_ARM1020)	+= proc-arm1020.o
 obj-$(CONFIG_CPU_ARM1020E)	+= proc-arm1020e.o
--- diff/arch/arm26/Kconfig	2003-09-30 15:46:11.000000000 +0100
+++ source/arch/arm26/Kconfig	2004-02-23 13:56:37.000000000 +0000
@@ -118,24 +118,6 @@ config XIP_KERNEL
 	  Select this option to create a kernel that can be programed into
 	  the OS ROMs.
 
-config HOTPLUG
-	bool "Support for hot-pluggable devices"
-	---help---
-	  Say Y here if you want to plug devices into your computer while
-	  the system is running, and be able to use them quickly.  In many
-	  cases, the devices can likewise be unplugged at any time too.
-
-	  One well known example of this is PCMCIA- or PC-cards, credit-card
-	  size devices such as network cards, modems or hard drives which are
-	  plugged into slots found on all modern laptop computers.  Another
-	  example, used on modern desktops as well as laptops, is USB.
-
-	  Enable HOTPLUG and KMOD, and build a modular kernel.  Get agent
-	  software (at <http://linux-hotplug.sourceforge.net/>) and install it.
-	  Then your kernel will automatically call out to a user mode "policy
-	  agent" (/sbin/hotplug) to load modules and set up software needed
-	  to use devices as you hotplug them.
-
 comment "At least one math emulation must be selected"
 
 config FPE_NWFPE
@@ -216,11 +198,6 @@ source "drivers/input/Kconfig"
 
 source "drivers/char/Kconfig"
 
-config KBDMOUSE
-	bool
-	depends on ARCH_ACORN && BUSMOUSE=y
-	default y
-
 source "drivers/media/Kconfig"
 
 source "fs/Kconfig"
--- diff/arch/arm26/Makefile	2003-09-17 12:28:01.000000000 +0100
+++ source/arch/arm26/Makefile	2004-02-23 13:56:37.000000000 +0000
@@ -8,7 +8,6 @@
 # Copyright (C) 1995-2001 by Russell King
 
 LDFLAGS_vmlinux	:=-p -X
-LDFLAGS_BLOB	:=--format binary
 AFLAGS_vmlinux.lds.o = -DTEXTADDR=$(TEXTADDR) -DDATAADDR=$(DATAADDR)
 OBJCOPYFLAGS	:=-O binary -R .note -R .comment -S
 GZFLAGS		:=-9
@@ -28,7 +27,6 @@ CFLAGS		+=-mapcs-26 -mcpu=arm3 -mshort-l
 AFLAGS		+=-mapcs-26 -mcpu=arm3 -mno-fpu -msoft-float -Wa,-mno-fpu
 
 head-y		:= arch/arm26/machine/head.o arch/arm26/kernel/init_task.o
-LDFLAGS_BLOB	+= --oformat elf32-littlearm
 
 ifeq ($(CONFIG_XIP_KERNEL),y)
   TEXTADDR	 := 0x03880000
--- diff/arch/arm26/kernel/armksyms.c	2003-06-30 10:07:18.000000000 +0100
+++ source/arch/arm26/kernel/armksyms.c	2004-02-23 13:56:37.000000000 +0000
@@ -21,6 +21,7 @@
 #include <linux/tty.h>
 #include <linux/vt_kern.h>
 #include <linux/smp_lock.h>
+#include <linux/syscalls.h>
 
 #include <asm/byteorder.h>
 #include <asm/elf.h>
@@ -43,14 +44,6 @@ extern void outswb(unsigned int port, co
 extern void __bad_xchg(volatile void *ptr, int size);
 
 /*
- * syscalls
- */
-extern int sys_write(int, const char *, int);
-extern int sys_read(int, char *, int);
-extern int sys_lseek(int, off_t, int);
-extern int sys_exit(int);
-
-/*
  * libgcc functions - functions that are used internally by the
  * compiler...  (prototypes are not correct though, but that
  * doesn't really matter since they're not versioned).
--- diff/arch/arm26/kernel/sys_arm.c	2003-06-30 10:07:18.000000000 +0100
+++ source/arch/arm26/kernel/sys_arm.c	2004-02-23 13:56:37.000000000 +0000
@@ -21,6 +21,7 @@
 #include <linux/msg.h>
 #include <linux/shm.h>
 #include <linux/stat.h>
+#include <linux/syscalls.h>
 #include <linux/mman.h>
 #include <linux/fs.h>
 #include <linux/file.h>
@@ -138,7 +139,6 @@ out:
  * Perform the select(nd, in, out, ex, tv) and mmap() system
  * calls.
  */
-extern asmlinkage int sys_select(int, fd_set *, fd_set *, fd_set *, struct timeval *);
 
 struct sel_arg_struct {
 	unsigned long n;
--- diff/arch/arm26/kernel/time.c	2003-10-09 09:47:33.000000000 +0100
+++ source/arch/arm26/kernel/time.c	2004-02-23 13:56:37.000000000 +0000
@@ -179,6 +179,7 @@ int do_settimeofday(struct timespec *tv)
 	time_maxerror = NTP_PHASE_LIMIT;
 	time_esterror = NTP_PHASE_LIMIT;
 	write_sequnlock_irq(&xtime_lock);
+	clock_was_set();
 	return 0;
 }
 
--- diff/arch/cris/Makefile	2003-08-26 10:00:51.000000000 +0100
+++ source/arch/cris/Makefile	2004-02-23 13:56:37.000000000 +0000
@@ -24,8 +24,6 @@ SARCH :=
 endif
 
 LD = $(CROSS_COMPILE)ld -mcrislinux
-LDFLAGS_BLOB	:= --format binary --oformat elf32-cris \
-		   -T arch/cris/$(SARCH)/output_arch.ld
 
 OBJCOPYFLAGS := -O binary -R .note -R .comment -S
 
--- diff/arch/cris/arch-v10/drivers/ethernet.c	2003-07-11 09:39:49.000000000 +0100
+++ source/arch/cris/arch-v10/drivers/ethernet.c	2004-02-23 13:56:37.000000000 +0000
@@ -482,7 +482,7 @@ etrax_ethernet_init(void)
 	/* Register device */
 	err = register_netdev(dev);
 	if (err) {
-		kfree(dev);
+		free_netdev(dev);
 		return err;
 	}
 
--- diff/arch/cris/kernel/sys_cris.c	2003-07-11 09:39:50.000000000 +0100
+++ source/arch/cris/kernel/sys_cris.c	2004-02-23 13:56:37.000000000 +0000
@@ -11,6 +11,7 @@
 
 #include <linux/errno.h>
 #include <linux/sched.h>
+#include <linux/syscalls.h>
 #include <linux/mm.h>
 #include <linux/smp.h>
 #include <linux/smp_lock.h>
--- diff/arch/cris/kernel/time.c	2003-10-09 09:47:33.000000000 +0100
+++ source/arch/cris/kernel/time.c	2004-02-23 13:56:37.000000000 +0000
@@ -108,6 +108,7 @@ int do_settimeofday(struct timespec *tv)
 	time_maxerror = NTP_PHASE_LIMIT;
 	time_esterror = NTP_PHASE_LIMIT;
 	local_irq_restore(flags);
+	clock_was_set();
 	return 0;
 }
 
--- diff/arch/h8300/Kconfig	2004-01-19 10:22:55.000000000 +0000
+++ source/arch/h8300/Kconfig	2004-02-23 13:56:37.000000000 +0000
@@ -154,29 +154,6 @@ config ROMKERNEL
 
 endchoice
 
-config DEFAULT_CMDLINE
-	bool "Use buildin commandline"
-	default n
-	help
-	  buildin kernel commandline enabled.
-
-config KERNEL_COMMAND
-	string "Buildin commmand string"
-	depends on DEFAULT_CMDLINE
-	help
-	  buildin kernel commandline strings.
-
-config BLKDEV_RESERVE
-	bool "BLKDEV Reserved Memory"
-	default n
-	help
-	  Reserved BLKDEV area.
-
-config CONFIG_BLKDEV_RESERVE_ADDRESS
-	hex 'start address'
-	depends on BLKDEV_RESERVE
-	help
-	  BLKDEV start address.
 endmenu
 
 menu "Executable file formats"
@@ -193,26 +170,19 @@ source "drivers/block/Kconfig"
 
 source "drivers/ide/Kconfig"
 
-source "net/Kconfig"
-
-source "drivers/isdn/Kconfig"
+source "arch/h8300/Kconfig.ide"
 
-source "drivers/telephony/Kconfig"
+source "net/Kconfig"
 
 #
-# input before char - char/joystick depends on it. As does USB.
+# input - input/joystick depends on it. As does USB.
 #
 source "drivers/input/Kconfig"
 
-#
-# Character device configuration
-#
-
 menu "Character devices"
 
 config VT
 	bool "Virtual terminal"
-	requires INPUT=y
 	---help---
 	  If you say Y here, you will get support for terminal devices with
 	  display and keyboard devices. These are called "virtual" because you
@@ -266,8 +236,37 @@ config HW_CONSOLE
 	depends on VT && !S390 && !UM
 	default y
 
+config SERIAL
+	tristate "Serial (8250, 16450, 16550 or compatible) support"
+	---help---
+	  This selects whether you want to include the driver for the standard
+	  serial ports.  The standard answer is Y.  People who might say N
+	  here are those that are setting up dedicated Ethernet WWW/FTP
+	  servers, or users that have one of the various bus mice instead of a
+	  serial mouse and don't intend to use their machine's standard serial
+	  port for anything.  (Note that the Cyclades and Stallion multi
+	  serial port drivers do not need this driver built in for them to
+	  work.)
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called serial.
+	  [WARNING: Do not compile this driver as a module if you are using
+	  non-standard serial ports, since the configuration information will
+	  be lost when the driver is unloaded.  This limitation may be lifted
+	  in the future.]
+
+	  BTW1: If you have a mouseman serial mouse which is not recognized by
+	  the X window system, try running gpm first.
+
+	  BTW2: If you intend to use a software modem (also called Winmodem)
+	  under Linux, forget it.  These modems are crippled and require
+	  proprietary drivers which are only available under Windows.
+
+	  Most people will say Y or M here, so that they can use serial mice,
+	  modems and similar devices connecting to the standard serial ports.
+
 config SH_SCI
-	tristate "Serial (SCI) support"
+	tristate "Serial (SCI, SCIF) support"
 	help
 	  Selecting this option will allow the Linux kernel to transfer data
 	  over SCI (Serial Communication Interface) and/or SCIF (Serial
@@ -301,6 +300,8 @@ config SERIAL_CONSOLE
 
 	  If unsure, say N.
 
+comment "Unix98 PTY support"
+
 config UNIX98_PTYS
 	bool "Unix98 PTY support"
 	---help---
@@ -343,15 +344,17 @@ config UNIX98_PTY_COUNT
 	  When not in use, each additional set of 256 PTYs occupy
 	  approximately 8 KB of kernel memory on 32-bit architectures.
 
-endmenu
+source "drivers/char/pcmcia/Kconfig"
 
-source "drivers/media/Kconfig"
-source "sound/Kconfig"
+source "drivers/serial/Kconfig"
 
-source "fs/Kconfig"
+source "drivers/i2c/Kconfig"
 
 source "drivers/usb/Kconfig"
+ 
+endmenu
 
+source "fs/Kconfig"
 
 menu "Kernel hacking"
 
@@ -400,6 +403,29 @@ config CONFIG_SH_STANDARD_BIOS
 	  serial console output using GDB protocol.
 	  Require eCos/RedBoot
 
+config DEFAULT_CMDLINE
+	bool "Use buildin commandline"
+	default n
+	help
+	  buildin kernel commandline enabled.
+
+config KERNEL_COMMAND
+	string "Buildin commmand string"
+	depends on DEFAULT_CMDLINE
+	help
+	  buildin kernel commandline strings.
+
+config BLKDEV_RESERVE
+	bool "BLKDEV Reserved Memory"
+	default n
+	help
+	  Reserved BLKDEV area.
+
+config CONFIG_BLKDEV_RESERVE_ADDRESS
+	hex 'start address'
+	depends on BLKDEV_RESERVE
+	help
+	  BLKDEV start address.
 endmenu
 
 source "security/Kconfig"
--- diff/arch/h8300/defconfig	2003-08-20 14:16:24.000000000 +0100
+++ source/arch/h8300/defconfig	2004-02-23 13:56:37.000000000 +0000
@@ -1,6 +1,7 @@
 #
 # Automatically generated make config: don't edit
 #
+CONFIG_H8300=y
 # CONFIG_MMU is not set
 # CONFIG_SWAP is not set
 # CONFIG_FPU is not set
@@ -13,6 +14,9 @@ CONFIG_ISA=y
 # Code maturity level options
 #
 CONFIG_EXPERIMENTAL=y
+CONFIG_CLEAN_COMPILE=y
+CONFIG_STANDALONE=y
+CONFIG_BROKEN_ON_SMP=y
 
 #
 # General setup
@@ -21,9 +25,15 @@ CONFIG_EXPERIMENTAL=y
 # CONFIG_BSD_PROCESS_ACCT is not set
 # CONFIG_SYSCTL is not set
 CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_IKCONFIG is not set
 CONFIG_EMBEDDED=y
+CONFIG_KALLSYMS=y
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
 
 #
 # Loadable module support
@@ -37,25 +47,30 @@ CONFIG_EPOLL=y
 # CONFIG_H8300H_AKI3068NET is not set
 # CONFIG_H8300H_H8MAX is not set
 CONFIG_H8300H_SIM=y
+# CONFIG_H8S_EDOSK2674 is not set
+# CONFIG_H8S_SIM is not set
 # CONFIG_H83002 is not set
 CONFIG_H83007=y
 # CONFIG_H83048 is not set
 # CONFIG_H83068 is not set
+# CONFIG_H8S2678 is not set
 CONFIG_CPU_H8300H=y
 CONFIG_CPU_CLOCK=16000
 # CONFIG_RAMKERNEL is not set
 CONFIG_ROMKERNEL=y
-# CONFIG_DEFAULT_CMDLINE is not set
 
 #
 # Executable file formats
 #
-CONFIG_KCORE_AOUT=y
 CONFIG_BINFMT_FLAT=y
 # CONFIG_BINFMT_ZFLAT is not set
 # CONFIG_BINFMT_MISC is not set
 
 #
+# Generic Driver Options
+#
+
+#
 # Memory Technology Devices (MTD)
 #
 CONFIG_MTD=y
@@ -72,6 +87,7 @@ CONFIG_MTD_CHAR=y
 CONFIG_MTD_BLOCK=y
 # CONFIG_FTL is not set
 # CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
 
 #
 # RAM/ROM/Flash chip drivers
@@ -86,6 +102,7 @@ CONFIG_MTD_RAM=y
 #
 # Mapping drivers for chip access
 #
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
 CONFIG_MTD_UCLINUX=y
 
 #
@@ -98,9 +115,9 @@ CONFIG_MTD_UCLINUX=y
 #
 # Disk-On-Chip Device Drivers
 #
-# CONFIG_MTD_DOC1000 is not set
 # CONFIG_MTD_DOC2000 is not set
 # CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
 
 #
 # NAND Flash Device Drivers
@@ -113,18 +130,100 @@ CONFIG_MTD_UCLINUX=y
 # CONFIG_BLK_DEV_FD is not set
 # CONFIG_BLK_DEV_XD is not set
 # CONFIG_BLK_DEV_LOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
 # CONFIG_BLK_DEV_RAM is not set
 # CONFIG_BLK_DEV_INITRD is not set
 
 #
-# ATA/IDE/MFM/RLL support
+# ATA/ATAPI/MFM/RLL support
 #
 # CONFIG_IDE is not set
 
 #
+# IDE Extra configuration
+#
+
+#
 # Networking support
 #
-# CONFIG_NET is not set
+CONFIG_NET=y
+
+#
+# Networking options
+#
+# CONFIG_PACKET is not set
+# CONFIG_NETLINK_DEV is not set
+# CONFIG_UNIX is not set
+# CONFIG_NET_KEY is not set
+# CONFIG_INET is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_DECNET is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_NETFILTER is not set
+# CONFIG_ATM is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_FASTROUTE is not set
+# CONFIG_NET_HW_FLOWCONTROL is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+CONFIG_NETDEVICES=y
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+# CONFIG_NET_ETHERNET is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+
+#
+# Ethernet (10000 Mbit)
+#
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Token Ring devices
+#
+# CONFIG_TR is not set
+# CONFIG_SHAPER is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
 
 #
 # Amateur Radio support
@@ -132,13 +231,14 @@ CONFIG_MTD_UCLINUX=y
 # CONFIG_HAMRADIO is not set
 
 #
-# ISDN subsystem
+# IrDA (infrared) support
 #
+# CONFIG_IRDA is not set
 
 #
-# Telephony Support
+# Bluetooth support
 #
-# CONFIG_PHONE is not set
+# CONFIG_BT is not set
 
 #
 # Input device support
@@ -155,6 +255,7 @@ CONFIG_MTD_UCLINUX=y
 # CONFIG_GAMEPORT is not set
 CONFIG_SOUND_GAMEPORT=y
 # CONFIG_SERIO is not set
+# CONFIG_SERIO_I8042 is not set
 
 #
 # Input Device Drivers
@@ -163,14 +264,38 @@ CONFIG_SOUND_GAMEPORT=y
 #
 # Character devices
 #
+# CONFIG_VT is not set
+# CONFIG_SERIAL is not set
 CONFIG_SH_SCI=y
 CONFIG_SERIAL_CONSOLE=y
+
+#
+# Unix98 PTY support
+#
 # CONFIG_UNIX98_PTYS is not set
 
 #
-# Multimedia devices
+# Serial drivers
 #
-# CONFIG_VIDEO_DEV is not set
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# USB support
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
 
 #
 # File systems
@@ -203,8 +328,10 @@ CONFIG_ROMFS_FS=y
 # Pseudo filesystems
 #
 CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
 # CONFIG_DEVFS_FS is not set
 # CONFIG_TMPFS is not set
+# CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
 
 #
@@ -226,14 +353,20 @@ CONFIG_RAMFS=y
 # CONFIG_UFS_FS is not set
 
 #
+# Network File Systems
+#
+# CONFIG_EXPORTFS is not set
+
+#
 # Partition Types
 #
 # CONFIG_PARTITION_ADVANCED is not set
 CONFIG_MSDOS_PARTITION=y
 
 #
-# USB support
+# Native Language Support
 #
+# CONFIG_NLS is not set
 
 #
 # Kernel hacking
@@ -243,7 +376,9 @@ CONFIG_FULLDEBUG=y
 # CONFIG_HIGHPROFILE is not set
 CONFIG_NO_KERNEL_MSG=y
 CONFIG_GDB_MAGICPRINT=y
-CONFIG_SYSCALL_PRINT=y
+# CONFIG_SYSCALL_PRINT is not set
+# CONFIG_DEFAULT_CMDLINE is not set
+# CONFIG_BLKDEV_RESERVE is not set
 
 #
 # Security options
--- diff/arch/h8300/kernel/signal.c	2003-09-30 15:46:11.000000000 +0100
+++ source/arch/h8300/kernel/signal.c	2004-02-23 13:56:37.000000000 +0000
@@ -28,6 +28,7 @@
 #include <linux/mm.h>
 #include <linux/kernel.h>
 #include <linux/signal.h>
+#include <linux/syscalls.h>
 #include <linux/errno.h>
 #include <linux/wait.h>
 #include <linux/ptrace.h>
@@ -46,8 +47,6 @@
 
 #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
 
-asmlinkage long sys_wait4(pid_t pid, unsigned int * stat_addr, int options,
-			struct rusage * ru);
 asmlinkage int do_signal(sigset_t *oldset, struct pt_regs *regs);
 
 /*
--- diff/arch/h8300/kernel/sys_h8300.c	2003-08-20 14:16:24.000000000 +0100
+++ source/arch/h8300/kernel/sys_h8300.c	2004-02-23 13:56:37.000000000 +0000
@@ -15,6 +15,7 @@
 #include <linux/msg.h>
 #include <linux/shm.h>
 #include <linux/stat.h>
+#include <linux/syscalls.h>
 #include <linux/mman.h>
 #include <linux/file.h>
 #include <linux/utsname.h>
@@ -155,8 +156,6 @@ out:
 }
 #endif
 
-extern asmlinkage int sys_select(int, fd_set *, fd_set *, fd_set *, struct timeval *);
-
 struct sel_arg_struct {
 	unsigned long n;
 	fd_set *inp, *outp, *exp;
@@ -261,7 +260,7 @@ asmlinkage int sys_ipc (uint call, int f
 	return -EINVAL;
 }
 
-asmlinkage int sys_ioperm(unsigned long from, unsigned long num, int on)
+asmlinkage long sys_ioperm(unsigned long from, unsigned long num, int on)
 {
   return -ENOSYS;
 }
--- diff/arch/h8300/kernel/time.c	2003-11-25 15:24:57.000000000 +0000
+++ source/arch/h8300/kernel/time.c	2004-02-23 13:56:37.000000000 +0000
@@ -139,6 +139,7 @@ int do_settimeofday(struct timespec *tv)
 	time_maxerror = NTP_PHASE_LIMIT;
 	time_esterror = NTP_PHASE_LIMIT;
 	write_sequnlock_irq(&xtime_lock);
+	clock_was_set();
 	return 0;
 }
 
--- diff/arch/h8300/platform/h8300h/aki3068net/timer.c	2003-08-26 10:00:51.000000000 +0100
+++ source/arch/h8300/platform/h8300h/aki3068net/timer.c	2004-02-23 13:56:37.000000000 +0000
@@ -27,10 +27,10 @@
 
 void __init platform_timer_setup(irqreturn_t (*timer_int)(int, void *, struct pt_regs *))
 {
-	outb(H8300_TIMER_COUNT_DATA,TCORA2);
-	outb(0x00,_8TCSR2);
+	ctrl_outb(H8300_TIMER_COUNT_DATA,TCORA2);
+	ctrl_outb(0x00,_8TCSR2);
 	request_irq(40,timer_int,0,"timer",0);
-	outb(0x40|0x08|0x03,_8TCR2);
+	ctrl_outb(0x40|0x08|0x03,_8TCR2);
 }
 
 void platform_timer_eoi(void)
--- diff/arch/h8300/platform/h8300h/entry.S	2003-08-26 10:00:51.000000000 +0100
+++ source/arch/h8300/platform/h8300h/entry.S	2004-02-23 13:56:37.000000000 +0000
@@ -236,7 +236,7 @@ SYMBOL_NAME_LABEL(system_call)
 	mov.l	@(LER3:16,sp),er2
 	jsr	@er4
 	mov.l	er0,@(LER0:16,sp)		/* save the return value */
-	jsr	SYMBOL_NAME(syscall_trace)
+	jsr	@SYMBOL_NAME(syscall_trace)
 
 SYMBOL_NAME_LABEL(ret_from_signal)
 
@@ -253,7 +253,7 @@ SYMBOL_NAME_LABEL(ret_from_exception)
 1:
 	mov.l	@(TI_FLAGS:16,er2),er1
 	btst	#TIF_NEED_RESCHED,r1l
-	bne	@SYMBOL_NAME(reschedule):16
+	bne	SYMBOL_NAME(reschedule):16
 	mov.l	sp,er1
 	subs	#4,er1			/* adjust retpc */
 	mov.l	er2,er0
@@ -273,7 +273,7 @@ SYMBOL_NAME_LABEL(reschedule)
 SYMBOL_NAME_LABEL(ret_from_fork)
 	mov.l	er2,er0
 	jsr	@SYMBOL_NAME(schedule_tail)
-	jmp	@SYMBOL_NAME_LABEL(ret_from_exception)	
+	jmp	@SYMBOL_NAME(ret_from_exception)	
 
 SYMBOL_NAME_LABEL(resume)
 	/*
--- diff/arch/h8300/platform/h8300h/generic/crt0_rom.S	2003-08-26 10:00:51.000000000 +0100
+++ source/arch/h8300/platform/h8300h/generic/crt0_rom.S	2004-02-23 13:56:37.000000000 +0000
@@ -105,6 +105,7 @@ gpio_table:
 	;; PBDDR
 	.byte	0x00,0x00
 
+	.section .rodata
 __target_name:	
 	.asciz	"generic"
 	
--- diff/arch/h8300/platform/h8300h/generic/timer.c	2003-08-20 14:16:24.000000000 +0100
+++ source/arch/h8300/platform/h8300h/generic/timer.c	2004-02-23 13:56:37.000000000 +0000
@@ -29,13 +29,14 @@ extern int request_irq_boot(unsigned int
 
 #if defined(CONFIG_H83007) || defined(CONFIG_H83068)
 #include <asm/regs306x.h>
+#define CMFA 6
 
 int platform_timer_setup(void (*timer_int)(int, void *, struct pt_regs *))
 {
-	outb(H8300_TIMER_COUNT_DATA,TMR8CMA2);
-	outb(0x00,TMR8TCSR2);
-	request_irq_boot(40,timer_int,0,"timer",0);
-	outb(0x40|0x08|0x03,TMR8TCNT2);
+	ctrl_outb(H8300_TIMER_COUNT_DATA,TCORA2);
+	ctrl_outb(0x00,_8TCSR2);
+	request_irq(40,timer_int,0,"timer",0);
+	ctrl_outb(0x40|0x08|0x03,_8TCR2);
 	return 0;
 }
 
@@ -65,19 +66,19 @@ int platform_timer_setup(void (*timer_in
 {
 	*(unsigned short *)GRA= H8300_TIMER_COUNT_DATA;
 	*(unsigned short *)TCNT=0;
-	outb(0x23,TCR);
-	outb(0x00,TIOR);
+	ctrl_outb(0x23,TCR);
+	ctrl_outb(0x00,TIOR);
 	request_timer_irq(26,timer_int,0,"timer",0);
-	outb(inb(TIER) | 0x01,TIER);
-	outb(inb(TSNC) & ~0x01,TSNC);
-	outb(inb(TMDR) & ~0x01,TMDR);
-	outb(inb(TSTR) | 0x01,TSTR);
+	ctrl_outb(inb(TIER) | 0x01,TIER);
+	ctrl_outb(inb(TSNC) & ~0x01,TSNC);
+	ctrl_outb(inb(TMDR) & ~0x01,TMDR);
+	ctrl_outb(inb(TSTR) | 0x01,TSTR);
 	return 0;
 }
 
 void platform_timer_eoi(void)
 {
-	outb(inb(TSR) & ~0x01,TSR);
+	ctrl_outb(inb(TSR) & ~0x01,TSR);
 }
 #endif
 
--- diff/arch/h8300/platform/h8300h/h8max/timer.c	2003-08-26 10:00:51.000000000 +0100
+++ source/arch/h8300/platform/h8300h/h8max/timer.c	2004-02-23 13:56:37.000000000 +0000
@@ -27,10 +27,10 @@
 
 void __init platform_timer_setup(irqreturn_t (*timer_int)(int, void *, struct pt_regs *))
 {
-	outb(H8300_TIMER_COUNT_DATA,TCORA2);
-	outb(0x00,_8TCSR2);
+	ctrl_outb(H8300_TIMER_COUNT_DATA,TCORA2);
+	ctrl_outb(0x00,_8TCSR2);
 	request_irq(40,timer_int,0,"timer",0);
-	outb(0x40|0x08|0x03,_8TCR2);
+	ctrl_outb(0x40|0x08|0x03,_8TCR2);
 }
 
 void platform_timer_eoi(void)
--- diff/arch/h8300/platform/h8s/edosk2674/crt0_rom.S	2003-08-20 14:16:36.000000000 +0100
+++ source/arch/h8300/platform/h8s/edosk2674/crt0_rom.S	2004-02-23 13:56:37.000000000 +0000
@@ -168,6 +168,7 @@ gpio_table:
 	;; PHDDR
 	.byte	0x00,0x00
 
+	.section .rodata
 __target_name:	
 	.asciz	"EDOSK-2674"
 	
--- diff/arch/h8300/platform/h8s/edosk2674/timer.c	2003-08-26 10:00:51.000000000 +0100
+++ source/arch/h8300/platform/h8s/edosk2674/timer.c	2004-02-23 13:56:37.000000000 +0000
@@ -29,13 +29,13 @@
 int __init platform_timer_setup(irqreturn_t (*timer_int)(int, void *, struct pt_regs *))
 {
 	unsigned char mstpcrl;
-	mstpcrl = inb(MSTPCRL);                  /* Enable timer */
+	mstpcrl = ctrl_inb(MSTPCRL);                  /* Enable timer */
 	mstpcrl &= ~0x01;
-	outb(mstpcrl,MSTPCRL);
-	outb(H8300_TIMER_COUNT_DATA,_8TCORA1);
-	outb(0x00,_8TCSR1);
+	ctrl_outb(mstpcrl,MSTPCRL);
+	ctrl_outb(H8300_TIMER_COUNT_DATA,_8TCORA1);
+	ctrl_outb(0x00,_8TCSR1);
 	request_irq(76,timer_int,0,"timer",0);
-	outb(0x40|0x08|0x03,_8TCR1);
+	ctrl_outb(0x40|0x08|0x03,_8TCR1);
 	return 0;
 }
 
--- diff/arch/h8300/platform/h8s/entry.S	2003-08-26 10:00:51.000000000 +0100
+++ source/arch/h8300/platform/h8s/entry.S	2004-02-23 13:56:37.000000000 +0000
@@ -233,7 +233,7 @@ SYMBOL_NAME_LABEL(system_call)
 	mov.l	@(LER3:16,sp),er2
 	jsr	@er4
 	mov.l	er0,@(LER0:16,sp)		/* save the return value */
-	jsr	SYMBOL_NAME(syscall_trace)
+	jsr	@SYMBOL_NAME(syscall_trace)
 
 SYMBOL_NAME_LABEL(ret_from_signal)
 
@@ -250,7 +250,7 @@ SYMBOL_NAME_LABEL(ret_from_exception)
 1:
 	mov.l	@(TI_FLAGS:16,er2),er1
 	btst	#TIF_NEED_RESCHED,r1l
-	bne	@SYMBOL_NAME(reschedule):16
+	bne	SYMBOL_NAME(reschedule):16
 	mov.l	sp,er1
 	subs	#4,er1			/* adjust retpc */
 	mov.l	er2,er0
@@ -270,7 +270,7 @@ SYMBOL_NAME_LABEL(reschedule)
 SYMBOL_NAME_LABEL(ret_from_fork)
 	mov.l	er2,er0
 	jsr	@SYMBOL_NAME(schedule_tail)
-	jmp	@SYMBOL_NAME_LABEL(ret_from_exception)	
+	jmp	@SYMBOL_NAME(ret_from_exception)	
 
 
 SYMBOL_NAME_LABEL(resume)
--- diff/arch/h8300/platform/h8s/generic/crt0_rom.S	2003-08-26 10:00:51.000000000 +0100
+++ source/arch/h8300/platform/h8s/generic/crt0_rom.S	2004-02-23 13:56:37.000000000 +0000
@@ -110,6 +110,7 @@ gpio_table:
 	;; PHDDR
 	.byte	0x00,0x00
 
+	.section .rodata
 __target_name:	
 	.asciz	"generic"
 	
--- diff/arch/h8300/platform/h8s/generic/timer.c	2003-08-26 10:00:51.000000000 +0100
+++ source/arch/h8300/platform/h8s/generic/timer.c	2004-02-23 13:56:37.000000000 +0000
@@ -25,10 +25,10 @@
 
 int platform_timer_setup(irqreturn_t (*timer_int)(int, void *, struct pt_regs *))
 {
-	outb(H8300_TIMER_COUNT_DATA,_8TCORA1);
-	outb(0x00,_8TCSR1);
+	ctrl_outb(H8300_TIMER_COUNT_DATA,_8TCORA1);
+	ctrl_outb(0x00,_8TCSR1);
 	request_irq(76,timer_int,0,"timer",0);
-	outb(0x40|0x08|0x03,_8TCR1);
+	ctrl_outb(0x40|0x08|0x03,_8TCR1);
 	return 0;
 }
 
--- diff/arch/i386/Kconfig	2004-02-18 08:54:07.000000000 +0000
+++ source/arch/i386/Kconfig	2004-02-23 13:56:37.000000000 +0000
@@ -43,6 +43,15 @@ config X86_PC
 	help
 	  Choose this option if your computer is a standard PC or compatible.
 
+config X86_ELAN
+	bool "AMD Elan"
+	help
+	  Select this for an AMD Elan processor.
+
+	  Do not use this option for K6/Athlon/Opteron processors!
+
+	  If unsure, choose "PC-compatible" instead.
+
 config X86_VOYAGER
 	bool "Voyager (NCR)"
 	help
@@ -130,6 +139,8 @@ config ES7000_CLUSTERED_APIC
 	default y
 	depends on SMP && X86_ES7000 && MPENTIUMIII
 
+if !X86_ELAN
+
 choice
 	prompt "Processor family"
 	default M686
@@ -222,14 +233,20 @@ config MPENTIUMIII
 	  extended prefetch instructions in addition to the Pentium II
 	  extensions.
 
+config MPENTIUMM
+	bool "Pentium M"
+	help
+	  Select this for Intel Pentium M (not Pentium-4 M)
+	  notebook chips.
+
 config MPENTIUM4
-	bool "Pentium-4/Celeron(P4-based)/Xeon"
+	bool "Pentium-4/Celeron(P4-based)/Pentium-4 M/Xeon"
 	help
-	  Select this for Intel Pentium 4 chips.  This includes both
-	  the Pentium 4 and P4-based Celeron chips.  This option
-	  enables compile flags optimized for the chip, uses the
-	  correct cache shift, and applies any applicable Pentium III
-	  optimizations.
+	  Select this for Intel Pentium 4 chips.  This includes the
+	  Pentium 4, P4-based Celeron and Xeon, and Pentium-4 M
+	  (not Pentium M) chips.  This option enables compile flags
+	  optimized for the chip, uses the correct cache shift, and
+	  applies any applicable Pentium III optimizations.
 
 config MK6
 	bool "K6/K6-II/K6-III"
@@ -312,6 +329,8 @@ config X86_GENERIC
 	  when it has moderate overhead. This is intended for generic 
 	  distributions kernels.
 
+endif
+
 #
 # Define implied options from the CPU selection here
 #
@@ -328,9 +347,9 @@ config X86_XADD
 config X86_L1_CACHE_SHIFT
 	int
 	default "7" if MPENTIUM4 || X86_GENERIC
-	default "4" if MELAN || M486 || M386
+	default "4" if X86_ELAN || M486 || M386
 	default "5" if MWINCHIP3D || MWINCHIP2 || MWINCHIPC6 || MCRUSOE || MCYRIXIII || MK6 || MPENTIUMIII || MPENTIUMII || M686 || M586MMX || M586TSC || M586 || MVIAC3_2
-	default "6" if MK7 || MK8
+	default "6" if MK7 || MK8 || MPENTIUMM
 
 config RWSEM_GENERIC_SPINLOCK
 	bool
@@ -374,22 +393,22 @@ config X86_POPAD_OK
 
 config X86_ALIGNMENT_16
 	bool
-	depends on MWINCHIP3D || MWINCHIP2 || MWINCHIPC6 || MCYRIXIII || MELAN || MK6 || M586MMX || M586TSC || M586 || M486 || MVIAC3_2
+	depends on MWINCHIP3D || MWINCHIP2 || MWINCHIPC6 || MCYRIXIII || X86_ELAN || MK6 || M586MMX || M586TSC || M586 || M486 || MVIAC3_2
 	default y
 
 config X86_GOOD_APIC
 	bool
-	depends on MK7 || MPENTIUM4 || MPENTIUMIII || MPENTIUMII || M686 || M586MMX || MK8
+	depends on MK7 || MPENTIUM4 || MPENTIUMM || MPENTIUMIII || MPENTIUMII || M686 || M586MMX || MK8
 	default y
 
 config X86_INTEL_USERCOPY
 	bool
-	depends on MPENTIUM4 || MPENTIUMIII || MPENTIUMII || M586MMX || X86_GENERIC || MK8 || MK7
+	depends on MPENTIUM4 || MPENTIUMM || MPENTIUMIII || MPENTIUMII || M586MMX || X86_GENERIC || MK8 || MK7
 	default y
 
 config X86_USE_PPRO_CHECKSUM
 	bool
-	depends on MWINCHIP3D || MWINCHIP2 || MWINCHIPC6 || MCYRIXIII || MK7 || MK6 || MPENTIUM4 || MPENTIUMIII || MPENTIUMII || M686 || MK8 || MVIAC3_2
+	depends on MWINCHIP3D || MWINCHIP2 || MWINCHIPC6 || MCYRIXIII || MK7 || MK6 || MPENTIUM4 || MPENTIUMM || MPENTIUMIII || MPENTIUMII || M686 || MK8 || MVIAC3_2
 	default y
 
 config X86_USE_3DNOW
@@ -402,6 +421,54 @@ config X86_OOSTORE
 	depends on (MWINCHIP3D || MWINCHIP2 || MWINCHIPC6) && MTRR
 	default y
 
+config X86_4G
+	bool "4 GB kernel-space and 4 GB user-space virtual memory support"
+	help
+          This option is only useful for systems that have more than 1 GB
+          of RAM.
+
+          The default kernel VM layout leaves 1 GB of virtual memory for
+          kernel-space mappings, and 3 GB of VM for user-space applications.
+          This option ups both the kernel-space VM and the user-space VM to
+          4 GB.
+
+          The cost of this option is additional TLB flushes done at
+          system-entry points that transition from user-mode into kernel-mode.
+          I.e. system calls and page faults, and IRQs that interrupt user-mode
+          code. There's also additional overhead to kernel operations that copy
+          memory to/from user-space. The overhead from this is hard to tell and
+          depends on the workload - it can be anything from no visible overhead
+          to 20-30% overhead. A good rule of thumb is to count with a runtime
+          overhead of 20%.
+
+          The upside is the much increased kernel-space VM, which more than
+          quadruples the maximum amount of RAM supported. Kernels compiled with
+          this option boot on 64GB of RAM and still have more than 3.1 GB of
+          'lowmem' left. Another bonus is that highmem IO bouncing decreases,
+          if used with drivers that still use bounce-buffers.
+
+          There's also a 33% increase in user-space VM size - database
+          applications might see a boost from this.
+
+          But the cost of the TLB flushes and the runtime overhead has to be
+          weighed against the bonuses offered by the larger VM spaces. The
+          dividing line depends on the actual workload - there might be 4 GB
+          systems that benefit from this option. Systems with less than 4 GB
+          of RAM will rarely see a benefit from this option - but it's not
+          out of question, the exact circumstances have to be considered.
+
+config X86_SWITCH_PAGETABLES
+	def_bool X86_4G
+
+config X86_4G_VM_LAYOUT
+	def_bool X86_4G
+
+config X86_UACCESS_INDIRECT
+	def_bool X86_4G
+
+config X86_HIGH_ENTRY
+	def_bool X86_4G
+
 config HPET_TIMER
 	bool "HPET Timer Support"
 	help
@@ -459,6 +526,16 @@ config NR_CPUS
 	  This is purely to save memory - each supported CPU adds
 	  approximately eight kilobytes to the kernel image.
 
+config SCHED_SMT
+	bool "SMT (Hyperthreading) scheduler support"
+	depends on SMP
+	default off
+	help
+	  SMT scheduler support improves the CPU scheduler's decision making
+	  when dealing with Intel Pentium 4 chips with HyperThreading at a
+	  cost of slightly increased overhead in some places. If unsure say
+	  N here.
+
 config PREEMPT
 	bool "Preemptible Kernel"
 	help
@@ -513,7 +590,7 @@ config X86_IO_APIC
 
 config X86_TSC
 	bool
-	depends on (MWINCHIP3D || MWINCHIP2 || MCRUSOE || MCYRIXIII || MK7 || MK6 || MPENTIUM4 || MPENTIUMIII || MPENTIUMII || M686 || M586MMX || M586TSC || MK8 || MVIAC3_2) && !X86_NUMAQ
+	depends on (MWINCHIP3D || MWINCHIP2 || MCRUSOE || MCYRIXIII || MK7 || MK6 || MPENTIUM4 || MPENTIUMM || MPENTIUMIII || MPENTIUMII || M686 || M586MMX || M586TSC || MK8 || MVIAC3_2) && !X86_NUMAQ
 	default y
 
 config X86_MCE
@@ -603,8 +680,6 @@ config MICROCODE
 
 	  To compile this driver as a module, choose M here: the
 	  module will be called microcode.
-	  If you use modprobe or kmod you may also want to add the line
-	  'alias char-major-10-184 microcode' to your /etc/modules.conf file.
 
 config X86_MSR
 	tristate "/dev/cpu/*/msr - Model-specific register support"
@@ -701,7 +776,7 @@ config X86_PAE
 # Common NUMA Features
 config NUMA
 	bool "Numa Memory Allocation Support"
-	depends on SMP && HIGHMEM64G && (X86_PC || X86_NUMAQ || X86_GENERICARCH || (X86_SUMMIT && ACPI))
+	depends on SMP && HIGHMEM64G && (X86_NUMAQ || X86_GENERICARCH || (X86_SUMMIT && ACPI))
 	default n if X86_PC
 	default y if (X86_NUMAQ || X86_SUMMIT)
 
@@ -809,6 +884,14 @@ config EFI
 	anything about EFI).  However, even with this option, the resultant
 	kernel should continue to boot on existing non-EFI platforms.
 
+config IRQBALANCE
+ 	bool "Enable kernel irq balancing"
+	depends on SMP
+	default y
+	help
+ 	  The defalut yes will allow the kernel to do irq load balancing.
+	  Saying no will keep the kernel from doing irq load balancing.
+
 config HAVE_DEC_LOCK
 	bool
 	depends on (SMP || PREEMPT) && X86_CMPXCHG
@@ -821,6 +904,19 @@ config BOOT_IOREMAP
 	depends on (((X86_SUMMIT || X86_GENERICARCH) && NUMA) || (X86 && EFI))
 	default y
 
+config REGPARM
+	bool "Use register arguments (EXPERIMENTAL)"
+	depends on EXPERIMENTAL
+	default n
+	help
+	Compile the kernel with -mregparm=3. This uses an different ABI
+	and passes the first three arguments of a function call in registers.
+	This will probably break binary only modules.
+
+	This feature is only enabled for gcc-3.0 and later - earlier compilers
+	generate incorrect output with certain kernel constructs when
+	-mregparm=3 is used.
+
 endmenu
 
 
@@ -1030,12 +1126,16 @@ config PCI_GOBIOS
 	  PCI-based systems don't have any BIOS at all. Linux can also try to
 	  detect the PCI hardware directly without using the BIOS.
 
-	  With this option, you can specify how Linux should detect the PCI
-	  devices. If you choose "BIOS", the BIOS will be used, if you choose
-	  "Direct", the BIOS won't be used, and if you choose "Any", the
-	  kernel will try the direct access method and falls back to the BIOS
-	  if that doesn't work. If unsure, go with the default, which is
-	  "Any".
+	  With this option, you can specify how Linux should detect the
+	  PCI devices. If you choose "BIOS", the BIOS will be used,
+	  if you choose "Direct", the BIOS won't be used, and if you
+	  choose "MMConfig", then PCI Express MMCONFIG will be used.
+	  If you choose "Any", the kernel will try MMCONFIG, then the
+	  direct access method and falls back to the BIOS if that doesn't
+	  work. If unsure, go with the default, which is "Any".
+
+config PCI_GOMMCONFIG
+	bool "MMConfig"
 
 config PCI_GODIRECT
 	bool "Direct"
@@ -1055,6 +1155,12 @@ config PCI_DIRECT
  	depends on PCI && ((PCI_GODIRECT || PCI_GOANY) || X86_VISWS)
 	default y
 
+config PCI_MMCONFIG
+	bool
+	depends on PCI && (PCI_GOMMCONFIG || PCI_GOANY)
+	select ACPI_BOOT
+	default y
+
 config PCI_USE_VECTOR
 	bool "Vector-based interrupt indexing"
 	depends on X86_LOCAL_APIC && X86_IO_APIC
@@ -1131,24 +1237,6 @@ config SCx200
 	  This support is also available as a module.  If compiled as a
 	  module, it will be called scx200.
 
-config HOTPLUG
-	bool "Support for hot-pluggable devices"
-	---help---
-	  Say Y here if you want to plug devices into your computer while
-	  the system is running, and be able to use them quickly.  In many
-	  cases, the devices can likewise be unplugged at any time too.
-
-	  One well known example of this is PCMCIA- or PC-cards, credit-card
-	  size devices such as network cards, modems or hard drives which are
-	  plugged into slots found on all modern laptop computers.  Another
-	  example, used on modern desktops as well as laptops, is USB.
-
-	  Enable HOTPLUG and KMOD, and build a modular kernel.  Get agent
-	  software (at <http://linux-hotplug.sourceforge.net/>) and install it.
-	  Then your kernel will automatically call out to a user mode "policy
-	  agent" (/sbin/hotplug) to load modules and set up software needed
-	  to use devices as you hotplug them.
-
 source "drivers/pcmcia/Kconfig"
 
 source "drivers/pci/hotplug/Kconfig"
@@ -1177,10 +1265,32 @@ config DEBUG_KERNEL
 	  Say Y here if you are developing drivers or trying to debug and
 	  identify kernel problems.
 
+config EARLY_PRINTK
+	bool "Early printk" if EMBEDDED
+	default y
+	help
+	  Write kernel log output directly into the VGA buffer or to a serial
+	  port.
+
+	  This is useful for kernel debugging when your machine crashes very
+	  early before the console code is initialized. For normal operation
+	  it is not recommended because it looks ugly and doesn't cooperate
+	  with klogd/syslogd or the X server. You should normally N here,
+	  unless you want to debug such a crash.
+
 config DEBUG_STACKOVERFLOW
 	bool "Check for stack overflows"
 	depends on DEBUG_KERNEL
 
+config DEBUG_STACK_USAGE
+	bool "Stack utilization instrumentation"
+	depends on DEBUG_KERNEL
+	help
+	  Enables the display of the minimum amount of free stack which each
+	  task has ever had available in the sysrq-T and sysrq-P debug output.
+
+	  This option will slow down process creation somewhat.
+
 config DEBUG_SLAB
 	bool "Debug memory allocations"
 	depends on DEBUG_KERNEL
@@ -1231,6 +1341,15 @@ config DEBUG_PAGEALLOC
 	  This results in a large slowdown, but helps to find certain types
 	  of memory corruptions.
 
+config SPINLINE
+	bool "Spinlock inlining"
+	depends on DEBUG_KERNEL
+	help
+	  This will change spinlocks from out of line to inline, making them
+	  account cost to the callers in readprofile, rather than the lock
+	  itself (as ".text.lock.filename"). This can be helpful for finding
+	  the callers of locks.
+
 config DEBUG_HIGHMEM
 	bool "Highmem debugging"
 	depends on DEBUG_KERNEL && HIGHMEM
@@ -1247,20 +1366,208 @@ config DEBUG_INFO
 	  Say Y here only if you plan to use gdb to debug the kernel.
 	  If you don't debug the kernel, you can say N.
 	  
+config LOCKMETER
+	bool "Kernel lock metering"
+	depends on SMP
+	help
+	  Say Y to enable kernel lock metering, which adds overhead to SMP locks,
+	  but allows you to see various statistics using the lockstat command.
+
 config DEBUG_SPINLOCK_SLEEP
 	bool "Sleep-inside-spinlock checking"
 	help
 	  If you say Y here, various routines which may sleep will become very
 	  noisy if they are called with a spinlock held.	
 
+config KGDB
+	bool "Include kgdb kernel debugger"
+	depends on DEBUG_KERNEL
+	help
+	  If you say Y here, the system will be compiled with the debug
+	  option (-g) and a debugging stub will be included in the
+	  kernel.  This stub communicates with gdb on another (host)
+	  computer via a serial port.  The host computer should have
+	  access to the kernel binary file (vmlinux) and a serial port
+	  that is connected to the target machine.  Gdb can be made to
+	  configure the serial port or you can use stty and setserial to
+	  do this. See the 'target' command in gdb. This option also
+	  configures in the ability to request a breakpoint early in the
+	  boot process.  To request the breakpoint just include 'kgdb'
+	  as a boot option when booting the target machine.  The system
+	  will then break as soon as it looks at the boot options.  This
+	  option also installs a breakpoint in panic and sends any
+	  kernel faults to the debugger. For more information see the
+	  Documentation/i386/kgdb/kgdb.txt file.
+
+choice
+	depends on KGDB
+    	prompt "Debug serial port BAUD"
+	default KGDB_115200BAUD
+	help
+	  Gdb and the kernel stub need to agree on the baud rate to be
+	  used.  Some systems (x86 family at this writing) allow this to
+	  be configured.
+
+config KGDB_9600BAUD
+	bool "9600"
+
+config KGDB_19200BAUD
+	bool "19200"
+
+config KGDB_38400BAUD
+	bool "38400"
+
+config KGDB_57600BAUD
+	bool "57600"
+
+config KGDB_115200BAUD
+	bool "115200"
+endchoice
+
+config KGDB_PORT
+	hex "hex I/O port address of the debug serial port"
+	depends on KGDB
+	default  3f8
+	help
+	  Some systems (x86 family at this writing) allow the port
+	  address to be configured.  The number entered is assumed to be
+	  hex, don't put 0x in front of it.  The standard address are:
+	  COM1 3f8 , irq 4 and COM2 2f8 irq 3.  Setserial /dev/ttySx
+	  will tell you what you have.  It is good to test the serial
+	  connection with a live system before trying to debug.
+
+config KGDB_IRQ
+	int "IRQ of the debug serial port"
+	depends on KGDB
+	default 4
+	help
+	  This is the irq for the debug port.  If everything is working
+	  correctly and the kernel has interrupts on a control C to the
+	  port should cause a break into the kernel debug stub.
+
+config DEBUG_INFO
+	bool
+	depends on KGDB
+	default y
+
+config KGDB_MORE
+	bool "Add any additional compile options"
+	depends on KGDB
+	default n
+	help
+	  Saying yes here turns on the ability to enter additional
+	  compile options.
+
+
+config KGDB_OPTIONS
+	depends on KGDB_MORE
+	string "Additional compile arguments"
+	default "-O1"
+	help
+	  This option allows you enter additional compile options for
+	  the whole kernel compile.  Each platform will have a default
+	  that seems right for it.  For example on PPC "-ggdb -O1", and
+	  for i386 "-O1".  Note that by configuring KGDB "-g" is already
+	  turned on.  In addition, on i386 platforms
+	  "-fomit-frame-pointer" is deleted from the standard compile
+	  options.
+
+config NO_KGDB_CPUS
+	int "Number of CPUs"
+	depends on KGDB && SMP
+	default NR_CPUS
+	help
+
+	  This option sets the number of cpus for kgdb ONLY.  It is used
+	  to prune some internal structures so they look "nice" when
+	  displayed with gdb.  This is to overcome possibly larger
+	  numbers that may have been entered above.  Enter the real
+	  number to get nice clean kgdb_info displays.
+
+config KGDB_TS
+	bool "Enable kgdb time stamp macros?"
+	depends on KGDB
+	default n
+	help
+	  Kgdb event macros allow you to instrument your code with calls
+	  to the kgdb event recording function.  The event log may be
+	  examined with gdb at a break point.  Turning on this
+	  capability also allows you to choose how many events to
+	  keep. Kgdb always keeps the lastest events.
+
+choice
+	depends on KGDB_TS
+	prompt "Max number of time stamps to save?"
+	default KGDB_TS_128
+
+config KGDB_TS_64
+	bool "64"
+
+config KGDB_TS_128
+	bool "128"
+
+config KGDB_TS_256
+	bool "256"
+
+config KGDB_TS_512
+	bool "512"
+
+config KGDB_TS_1024
+	bool "1024"
+
+endchoice
+
+config STACK_OVERFLOW_TEST
+	bool "Turn on kernel stack overflow testing?"
+	depends on KGDB
+	default n
+	help
+	  This option enables code in the front line interrupt handlers
+	  to check for kernel stack overflow on interrupts and system
+	  calls.  This is part of the kgdb code on x86 systems.
+
+config KGDB_CONSOLE
+	bool "Enable serial console thru kgdb port"
+	depends on KGDB
+	default n
+	help
+	  This option enables the command line "console=kgdb" option.
+	  When the system is booted with this option in the command line
+	  all kernel printk output is sent to gdb (as well as to other
+	  consoles).  For this to work gdb must be connected.  For this
+	  reason, this command line option will generate a breakpoint if
+	  gdb has not yet connected.  After the gdb continue command is
+	  given all pent up console output will be printed by gdb on the
+	  host machine.  Neither this option, nor KGDB require the
+	  serial driver to be configured.
+
+config KGDB_SYSRQ
+	bool "Turn on SysRq 'G' command to do a break?"
+	depends on KGDB
+	default y
+	help
+	  This option includes an option in the SysRq code that allows
+	  you to enter SysRq G which generates a breakpoint to the KGDB
+	  stub.  This will work if the keyboard is alive and can
+	  interrupt the system.  Because of constraints on when the
+	  serial port interrupt can be enabled, this code may allow you
+	  to interrupt the system before the serial port control C is
+	  available.  Just say yes here.
+
 config FRAME_POINTER
 	bool "Compile the kernel with frame pointers"
+	default KGDB
 	help
 	  If you say Y here the resulting kernel image will be slightly larger
 	  and slower, but it will give very useful debugging information.
 	  If you don't debug the kernel, you can say N, but we may not be able
 	  to solve problems without frame pointers.
 
+config MAGIC_SYSRQ
+	bool
+	depends on KGDB_SYSRQ
+	default y
+
 config X86_FIND_SMP_CONFIG
 	bool
 	depends on X86_LOCAL_APIC || X86_VOYAGER
--- diff/arch/i386/Makefile	2003-10-09 09:47:16.000000000 +0100
+++ source/arch/i386/Makefile	2004-02-23 13:56:37.000000000 +0000
@@ -19,7 +19,7 @@ LDFLAGS		:= -m elf_i386
 OBJCOPYFLAGS	:= -O binary -R .note -R .comment -S
 LDFLAGS_vmlinux :=
 
-CFLAGS += -pipe
+CFLAGS += -pipe -msoft-float
 
 # prevent gcc from keeping the stack 16 byte aligned
 CFLAGS += $(call check_gcc,-mpreferred-stack-boundary=2,)
@@ -34,8 +34,9 @@ cflags-$(CONFIG_M586MMX)	+= $(call check
 cflags-$(CONFIG_M686)		+= -march=i686
 cflags-$(CONFIG_MPENTIUMII)	+= $(call check_gcc,-march=pentium2,-march=i686)
 cflags-$(CONFIG_MPENTIUMIII)	+= $(call check_gcc,-march=pentium3,-march=i686)
+cflags-$(CONFIG_MPENTIUMM)	+= $(call check_gcc,-march=pentium3,-march=i686)
 cflags-$(CONFIG_MPENTIUM4)	+= $(call check_gcc,-march=pentium4,-march=i686)
-cflags-$(CONFIG_MK6)		+= $(call check_gcc,-march=k6,-march=i586)
+cflags-$(CONFIG_MK6)		+= -march=k6
 # Please note, that patches that add -march=athlon-xp and friends are pointless.
 # They make zero difference whatsosever to performance at this time.
 cflags-$(CONFIG_MK7)		+= $(call check_gcc,-march=athlon,-march=i686 $(align)-functions=4)
@@ -47,6 +48,18 @@ cflags-$(CONFIG_MWINCHIP3D)	+= $(call ch
 cflags-$(CONFIG_MCYRIXIII)	+= $(call check_gcc,-march=c3,-march=i486) $(align)-functions=0 $(align)-jumps=0 $(align)-loops=0
 cflags-$(CONFIG_MVIAC3_2)	+= $(call check_gcc,-march=c3-2,-march=i686)
 
+# AMD Elan support
+cflags-$(CONFIG_X86_ELAN)	+= -march=i486
+
+# -mregparm=3 works ok on gcc-3.0 and later
+#
+GCC_VERSION			:= $(shell $(CONFIG_SHELL) $(srctree)/scripts/gcc-version.sh $(CC))
+cflags-$(CONFIG_REGPARM) 	+= $(shell if [ $(GCC_VERSION) -ge 0300 ] ; then echo "-mregparm=3"; fi ;)
+
+# Enable unit-at-a-time mode when possible. It shrinks the
+# kernel considerably.
+CFLAGS += $(call check_gcc,-funit-at-a-time,)
+
 CFLAGS += $(cflags-y)
 
 # Default subarch .c files
@@ -84,6 +97,9 @@ mcore-$(CONFIG_X86_ES7000)	:= mach-es700
 # default subarch .h files
 mflags-y += -Iinclude/asm-i386/mach-default
 
+mflags-$(CONFIG_KGDB) += -gdwarf-2
+mflags-$(CONFIG_KGDB_MORE) += $(shell echo $(CONFIG_KGDB_OPTIONS) | sed -e 's/"//g')
+
 head-y := arch/i386/kernel/head.o arch/i386/kernel/init_task.o
 
 libs-y 					+= arch/i386/lib/
--- diff/arch/i386/boot/Makefile	2003-09-30 15:46:11.000000000 +0100
+++ source/arch/i386/boot/Makefile	2004-02-23 13:56:37.000000000 +0000
@@ -31,6 +31,8 @@ subdir- 	:= compressed
 
 host-progs	:= tools/build
 
+HOSTCFLAGS_build.o := -Iinclude
+
 # ---------------------------------------------------------------------------
 
 $(obj)/zImage:  IMAGE_OFFSET := 0x1000
--- diff/arch/i386/boot/setup.S	2004-02-18 08:54:07.000000000 +0000
+++ source/arch/i386/boot/setup.S	2004-02-23 13:56:37.000000000 +0000
@@ -164,7 +164,7 @@ cmd_line_ptr:	.long 0			# (Header versio
 					# can be located anywhere in
 					# low memory 0x10000 or higher.
 
-ramdisk_max:	.long MAXMEM-1		# (Header version 0x0203 or later)
+ramdisk_max:	.long __MAXMEM-1	# (Header version 0x0203 or later)
 					# The highest safe address for
 					# the contents of an initrd
 
@@ -776,7 +776,7 @@ end_move_self:					# now we are at the r
 # AMD Elan bug fix by Robert Schwebel.
 #
 
-#if defined(CONFIG_MELAN)
+#if defined(CONFIG_X86_ELAN)
 	movb $0x02, %al			# alternate A20 gate
 	outb %al, $0x92			# this works on SC410/SC520
 a20_elan_wait:
--- diff/arch/i386/kernel/Makefile	2004-01-19 10:22:55.000000000 +0000
+++ source/arch/i386/kernel/Makefile	2004-02-23 13:56:37.000000000 +0000
@@ -7,13 +7,14 @@ extra-y := head.o init_task.o vmlinux.ld
 obj-y	:= process.o semaphore.o signal.o entry.o traps.o irq.o vm86.o \
 		ptrace.o i8259.o ioport.o ldt.o setup.o time.o sys_i386.o \
 		pci-dma.o i386_ksyms.o i387.o dmi_scan.o bootflag.o \
-		doublefault.o
+		doublefault.o entry_trampoline.o
 
 obj-y				+= cpu/
 obj-y				+= timers/
 obj-$(CONFIG_ACPI_BOOT)		+= acpi/
 obj-$(CONFIG_X86_BIOS_REBOOT)	+= reboot.o
 obj-$(CONFIG_MCA)		+= mca.o
+obj-$(CONFIG_KGDB)		+= kgdb_stub.o
 obj-$(CONFIG_X86_MSR)		+= msr.o
 obj-$(CONFIG_X86_CPUID)		+= cpuid.o
 obj-$(CONFIG_MICROCODE)		+= microcode.o
@@ -31,6 +32,7 @@ obj-y				+= sysenter.o vsyscall.o
 obj-$(CONFIG_ACPI_SRAT) 	+= srat.o
 obj-$(CONFIG_HPET_TIMER) 	+= time_hpet.o
 obj-$(CONFIG_EFI) 		+= efi.o efi_stub.o
+obj-$(CONFIG_EARLY_PRINTK)	+= early_printk.o
 
 EXTRA_AFLAGS   := -traditional
 
--- diff/arch/i386/kernel/acpi/boot.c	2004-02-18 08:54:07.000000000 +0000
+++ source/arch/i386/kernel/acpi/boot.c	2004-02-23 13:56:37.000000000 +0000
@@ -96,6 +96,31 @@ char *__acpi_map_table(unsigned long phy
 }
 
 
+#ifdef CONFIG_PCI_MMCONFIG
+static int __init acpi_parse_mcfg(unsigned long phys_addr, unsigned long size)
+{
+	struct acpi_table_mcfg *mcfg;
+
+	if (!phys_addr || !size)
+		return -EINVAL;
+
+	mcfg = (struct acpi_table_mcfg *) __acpi_map_table(phys_addr, size);
+	if (!mcfg) {
+		printk(KERN_WARNING PREFIX "Unable to map MCFG\n");
+		return -ENODEV;
+	}
+
+	if (mcfg->base_reserved) {
+		printk(KERN_ERR PREFIX "MMCONFIG not in low 4GB of memory\n");
+		return -ENODEV;
+	}
+
+	pci_mmcfg_base_addr = mcfg->base_address;
+
+	return 0;
+}
+#endif /* CONFIG_PCI_MMCONFIG */
+
 #ifdef CONFIG_X86_LOCAL_APIC
 
 static u64 acpi_lapic_addr __initdata = APIC_DEFAULT_PHYS_BASE;
@@ -339,7 +364,7 @@ acpi_scan_rsdp (
 	 * RSDP signature.
 	 */
 	for (offset = 0; offset < length; offset += 16) {
-		if (strncmp((char *) (start + offset), "RSD PTR ", sig_len))
+		if (strncmp((char *) __va(start + offset), "RSD PTR ", sig_len))
 			continue;
 		return (start + offset);
 	}
@@ -376,6 +401,37 @@ static int __init acpi_parse_hpet(unsign
 }
 #endif
 
+/* detect the location of the ACPI PM Timer */
+#ifdef CONFIG_X86_PM_TIMER
+extern u32 pmtmr_ioport;
+
+static int __init acpi_parse_fadt(unsigned long phys, unsigned long size)
+{
+	struct fadt_descriptor_rev2 *fadt =0;
+
+	fadt = (struct fadt_descriptor_rev2*) __acpi_map_table(phys,size);
+	if(!fadt) {
+		printk(KERN_WARNING PREFIX "Unable to map FADT\n");
+		return 0;
+	}
+
+	if (fadt->revision >= FADT2_REVISION_ID) {
+		/* FADT rev. 2 */
+		if (fadt->xpm_tmr_blk.address_space_id != ACPI_ADR_SPACE_SYSTEM_IO)
+			return 0;
+
+		pmtmr_ioport = fadt->xpm_tmr_blk.address;
+	} else {
+		/* FADT rev. 1 */
+		pmtmr_ioport = fadt->V1_pm_tmr_blk;
+	}
+	if (pmtmr_ioport)
+		printk(KERN_INFO PREFIX "PM-Timer IO Port: %#x\n", pmtmr_ioport);
+	return 0;
+}
+#endif
+
+
 unsigned long __init
 acpi_find_rsdp (void)
 {
@@ -398,55 +454,14 @@ acpi_find_rsdp (void)
 	return rsdp_phys;
 }
 
-/*
- * acpi_boot_init()
- *  called from setup_arch(), always.
- *	1. maps ACPI tables for later use
- *	2. enumerates lapics
- *	3. enumerates io-apics
- *
- * side effects:
- *	acpi_lapic = 1 if LAPIC found
- *	acpi_ioapic = 1 if IOAPIC found
- *	if (acpi_lapic && acpi_ioapic) smp_found_config = 1;
- *	if acpi_blacklisted() acpi_disabled = 1;
- *	acpi_irq_model=...
- *	...
- *
- * return value: (currently ignored)
- *	0: success
- *	!0: failure
- */
 
-int __init
-acpi_boot_init (void)
+static int acpi_apic_setup(void)
 {
-	int			result = 0;
-
-	if (acpi_disabled && !acpi_ht)
-		 return 1;
+	int result;
 
-	/*
-	 * The default interrupt routing model is PIC (8259).  This gets
-	 * overriden if IOAPICs are enumerated (below).
-	 */
-	acpi_irq_model = ACPI_IRQ_MODEL_PIC;
-
-	/* 
-	 * Initialize the ACPI boot-time table parser.
-	 */
-	result = acpi_table_init();
-	if (result) {
-		acpi_disabled = 1;
-		return result;
-	}
-
-	result = acpi_blacklisted();
-	if (result) {
-		printk(KERN_WARNING PREFIX "BIOS listed in blacklist, disabling ACPI support\n");
-		acpi_disabled = 1;
-		return result;
-	}
+#ifdef CONFIG_X86_PM_TIMER
+	acpi_table_parse(ACPI_FADT, acpi_parse_fadt);
+#endif
 
 #ifdef CONFIG_X86_LOCAL_APIC
 
@@ -506,24 +521,17 @@ acpi_boot_init (void)
 
 	acpi_lapic = 1;
 
-#endif /*CONFIG_X86_LOCAL_APIC*/
+#endif /* CONFIG_X86_LOCAL_APIC */
 
 #if defined(CONFIG_X86_IO_APIC) && defined(CONFIG_ACPI_INTERPRETER)
 
 	/* 
 	 * I/O APIC 
-	 * --------
 	 */
 
-	/*
-	 * ACPI interpreter is required to complete interrupt setup,
-	 * so if it is off, don't enumerate the io-apics with ACPI.
-	 * If MPS is present, it will handle them,
-	 * otherwise the system will stay in PIC mode
-	 */
-	if (acpi_disabled || acpi_noirq) {
+	if (acpi_noirq) {
 		return 1;
-        }
+	}
 
 	/*
  	 * if "noapic" boot option, don't look for IO-APICs
@@ -538,8 +546,7 @@ acpi_boot_init (void)
 	if (!result) {
 		printk(KERN_ERR PREFIX "No IOAPIC entries present\n");
 		return -ENODEV;
-	}
-	else if (result < 0) {
+	} else if (result < 0) {
 		printk(KERN_ERR PREFIX "Error parsing IOAPIC entry\n");
 		return result;
 	}
@@ -576,9 +583,82 @@ acpi_boot_init (void)
 	}
 #endif
 
+	return 0;
+}
+
+/*
+ * acpi_boot_init()
+ *  called from setup_arch(), always.
+ *	1. maps ACPI tables for later use
+ *	2. enumerates lapics
+ *	3. enumerates io-apics
+ *
+ * side effects:
+ *	acpi_lapic = 1 if LAPIC found
+ *	acpi_ioapic = 1 if IOAPIC found
+ *	if (acpi_lapic && acpi_ioapic) smp_found_config = 1;
+ *	if acpi_blacklisted() acpi_disabled = 1;
+ *	acpi_irq_model=...
+ *	...
+ *
+ * return value: (currently ignored)
+ *	0: success
+ *	!0: failure
+ */
+
+int __init
+acpi_boot_init (void)
+{
+	int result, error;
+
+	if (acpi_disabled && !acpi_ht)
+		 return 1;
+
+	/*
+	 * The default interrupt routing model is PIC (8259).  This gets
+	 * overriden if IOAPICs are enumerated (below).
+	 */
+	acpi_irq_model = ACPI_IRQ_MODEL_PIC;
+
+	/*
+	 * Initialize the ACPI boot-time table parser.
+	 */
+	result = acpi_table_init();
+	if (result) {
+		acpi_disabled = 1;
+		return result;
+	}
+
+	result = acpi_blacklisted();
+	if (result) {
+		printk(KERN_WARNING PREFIX "BIOS listed in blacklist, disabling ACPI support\n");
+		acpi_disabled = 1;
+		return result;
+	}
+
+	error = acpi_apic_setup();
+
+#ifdef CONFIG_PCI_MMCONFIG
+	result = acpi_table_parse(ACPI_MCFG, acpi_parse_mcfg);
+	if (result < 0) {
+		printk(KERN_ERR PREFIX "Error %d parsing MCFG\n", result);
+		if (!error)
+			error = result;
+	} else if (result > 1) {
+		printk(KERN_WARNING PREFIX "Multiple MCFG tables exist\n");
+	}
+#endif /* CONFIG_PCI_MMCONFIG */
+
 #ifdef CONFIG_HPET_TIMER
-	acpi_table_parse(ACPI_HPET, acpi_parse_hpet);
+	result = acpi_table_parse(ACPI_HPET, acpi_parse_hpet);
+	if (result < 0) {
+		printk(KERN_ERR PREFIX "Error %d parsing HPET\n", result);
+		if (!error)
+			error = result;
+	} else if (result > 1) {
+		printk(KERN_WARNING PREFIX "Multiple HPET tables exist\n");
+	}
 #endif
 
-	return 0;
+	return error;
 }
--- diff/arch/i386/kernel/apic.c	2004-02-09 10:36:07.000000000 +0000
+++ source/arch/i386/kernel/apic.c	2004-02-23 13:56:37.000000000 +0000
@@ -595,7 +595,7 @@ static int __init init_lapic_sysfs(void)
 
 	error = sysdev_class_register(&lapic_sysclass);
 	if (!error)
-		error = sys_device_register(&device_lapic);
+		error = sysdev_register(&device_lapic);
 	return error;
 }
 device_initcall(init_lapic_sysfs);
--- diff/arch/i386/kernel/asm-offsets.c	2003-10-09 09:47:16.000000000 +0100
+++ source/arch/i386/kernel/asm-offsets.c	2004-02-23 13:56:37.000000000 +0000
@@ -4,9 +4,11 @@
  * to extract and format the required data.
  */
 
+#include <linux/sched.h>
 #include <linux/signal.h>
 #include <asm/ucontext.h>
 #include "sigframe.h"
+#include <asm/fixmap.h>
 
 #define DEFINE(sym, val) \
         asm volatile("\n->" #sym " %0 " #val : : "i" (val))
@@ -28,4 +30,17 @@ void foo(void)
 
 	DEFINE(RT_SIGFRAME_sigcontext,
 	       offsetof (struct rt_sigframe, uc.uc_mcontext));
+	DEFINE(TI_task, offsetof (struct thread_info, task));
+	DEFINE(TI_exec_domain, offsetof (struct thread_info, exec_domain));
+	DEFINE(TI_flags, offsetof (struct thread_info, flags));
+	DEFINE(TI_preempt_count, offsetof (struct thread_info, preempt_count));
+	DEFINE(TI_addr_limit, offsetof (struct thread_info, addr_limit));
+	DEFINE(TI_real_stack, offsetof (struct thread_info, real_stack));
+	DEFINE(TI_virtual_stack, offsetof (struct thread_info, virtual_stack));
+	DEFINE(TI_user_pgd, offsetof (struct thread_info, user_pgd));
+
+	DEFINE(FIX_ENTRY_TRAMPOLINE_0_addr, __fix_to_virt(FIX_ENTRY_TRAMPOLINE_0));
+	DEFINE(FIX_VSYSCALL_addr, __fix_to_virt(FIX_VSYSCALL));
+	DEFINE(PAGE_SIZE_asm, PAGE_SIZE);
+	DEFINE(task_thread_db7, offsetof (struct task_struct, thread.debugreg[7]));
 }
--- diff/arch/i386/kernel/cpu/centaur.c	2003-05-21 11:49:49.000000000 +0100
+++ source/arch/i386/kernel/cpu/centaur.c	2004-02-23 13:56:37.000000000 +0000
@@ -246,7 +246,15 @@ static void __init winchip2_protect_mcr(
 	lo&=~0x1C0;	/* blank bits 8-6 */
 	wrmsr(MSR_IDT_MCR_CTRL, lo, hi);
 }
-#endif
+#endif /* CONFIG_X86_OOSTORE */
+
+#define ACE_PRESENT	(1 << 6)
+#define ACE_ENABLED	(1 << 7)
+#define ACE_FCR		(1 << 28)	/* MSR_VIA_FCR */
+
+#define RNG_PRESENT	(1 << 2)
+#define RNG_ENABLED	(1 << 3)
+#define RNG_ENABLE	(1 << 6)	/* MSR_VIA_RNG */
 
 static void __init init_c3(struct cpuinfo_x86 *c)
 {
@@ -254,6 +262,24 @@ static void __init init_c3(struct cpuinf
 
 	/* Test for Centaur Extended Feature Flags presence */
 	if (cpuid_eax(0xC0000000) >= 0xC0000001) {
+		u32 tmp = cpuid_edx(0xC0000001);
+
+		/* enable ACE unit, if present and disabled */
+		if ((tmp & (ACE_PRESENT | ACE_ENABLED)) == ACE_PRESENT) {
+			rdmsr (MSR_VIA_FCR, lo, hi);
+			lo |= ACE_FCR;		/* enable ACE unit */
+			wrmsr (MSR_VIA_FCR, lo, hi);
+			printk(KERN_INFO "CPU: Enabled ACE h/w crypto\n");
+		}
+
+		/* enable RNG unit, if present and disabled */
+		if ((tmp & (RNG_PRESENT | RNG_ENABLED)) == RNG_PRESENT) {
+			rdmsr (MSR_VIA_RNG, lo, hi);
+			lo |= RNG_ENABLE;	/* enable RNG unit */
+			wrmsr (MSR_VIA_RNG, lo, hi);
+			printk(KERN_INFO "CPU: Enabled h/w RNG\n");
+		}
+
 		/* store Centaur Extended Feature Flags as
 		 * word 5 of the CPU capability bit array
 		 */
--- diff/arch/i386/kernel/cpu/common.c	2004-01-19 10:22:55.000000000 +0000
+++ source/arch/i386/kernel/cpu/common.c	2004-02-23 13:56:37.000000000 +0000
@@ -514,12 +514,16 @@ void __init cpu_init (void)
 	set_tss_desc(cpu,t);
 	cpu_gdt_table[cpu][GDT_ENTRY_TSS].b &= 0xfffffdff;
 	load_TR_desc();
-	load_LDT(&init_mm.context);
+	if (cpu)
+		load_LDT(&init_mm.context);
 
 	/* Set up doublefault TSS pointer in the GDT */
 	__set_tss_desc(cpu, GDT_ENTRY_DOUBLEFAULT_TSS, &doublefault_tss);
 	cpu_gdt_table[cpu][GDT_ENTRY_DOUBLEFAULT_TSS].b &= 0xfffffdff;
 
+	if (cpu)
+		trap_init_virtual_GDT();
+
 	/* Clear %fs and %gs. */
 	asm volatile ("xorl %eax, %eax; movl %eax, %fs; movl %eax, %gs");
 
--- diff/arch/i386/kernel/cpu/cpufreq/Kconfig	2004-02-09 10:36:07.000000000 +0000
+++ source/arch/i386/kernel/cpu/cpufreq/Kconfig	2004-02-23 13:56:37.000000000 +0000
@@ -54,7 +54,7 @@ config X86_ACPI_CPUFREQ_PROC_INTF
 
 config ELAN_CPUFREQ
 	tristate "AMD Elan"
-	depends on CPU_FREQ_TABLE && MELAN
+	depends on CPU_FREQ_TABLE && X86_ELAN
 	---help---
 	  This adds the CPUFreq driver for AMD Elan SC400 and SC410
 	  processors.
--- diff/arch/i386/kernel/cpu/cpufreq/longhaul.c	2004-02-18 08:54:07.000000000 +0000
+++ source/arch/i386/kernel/cpu/cpufreq/longhaul.c	2004-02-23 13:56:37.000000000 +0000
@@ -1,5 +1,5 @@
 /*
- *  (C) 2001-2003  Dave Jones. <davej@codemonkey.org.uk>
+ *  (C) 2001-2004  Dave Jones. <davej@codemonkey.org.uk>
  *  (C) 2002  Padraig Brady. <padraig@antefacto.com>
  *
  *  Licensed under the terms of the GNU GPL License version 2.
@@ -186,6 +186,7 @@ static int _guess (int guess, int maxmul
 	return target;
 }
 
+
 static int guess_fsb(int maxmult)
 {
 	int speed = (cpu_khz/1000);
@@ -203,7 +204,6 @@ static int guess_fsb(int maxmult)
 }
 
 
-
 static int __init longhaul_get_ranges (void)
 {
 	struct cpuinfo_x86 *c = cpu_data;
@@ -359,7 +359,7 @@ static int longhaul_target (struct cpufr
 	return 0;
 }
 
-static int longhaul_cpu_init (struct cpufreq_policy *policy)
+static int __init longhaul_cpu_init (struct cpufreq_policy *policy)
 {
 	struct cpuinfo_x86 *c = cpu_data;
 	char *cpuname=NULL;
--- diff/arch/i386/kernel/cpu/cpufreq/longrun.c	2003-09-17 12:28:01.000000000 +0100
+++ source/arch/i386/kernel/cpu/cpufreq/longrun.c	2004-02-23 13:56:37.000000000 +0000
@@ -220,7 +220,7 @@ static unsigned int __init longrun_deter
 }
 
 
-static int longrun_cpu_init(struct cpufreq_policy *policy)
+static int __init longrun_cpu_init(struct cpufreq_policy *policy)
 {
 	int                     result = 0;
 
--- diff/arch/i386/kernel/cpu/cpufreq/p4-clockmod.c	2004-02-18 08:54:07.000000000 +0000
+++ source/arch/i386/kernel/cpu/cpufreq/p4-clockmod.c	2004-02-23 13:56:37.000000000 +0000
@@ -57,8 +57,7 @@ static int cpufreq_p4_setdc(unsigned int
 	u32 l, h;
 	cpumask_t cpus_allowed, affected_cpu_map;
 	struct cpufreq_freqs freqs;
-	int hyperthreading = 0;
-	int sibling = 0;
+	int j;
 
 	if (!cpu_online(cpu) || (newstate > DC_DISABLE) || 
 		(newstate == DC_RESV))
@@ -68,13 +67,10 @@ static int cpufreq_p4_setdc(unsigned int
 	cpus_allowed = current->cpus_allowed;
 
 	/* only run on CPU to be set, or on its sibling */
-       affected_cpu_map = cpumask_of_cpu(cpu);
-#ifdef CONFIG_X86_HT
-	hyperthreading = ((cpu_has_ht) && (smp_num_siblings == 2));
-	if (hyperthreading) {
-		sibling = cpu_sibling_map[cpu];
-                cpu_set(sibling, affected_cpu_map);
-	}
+#ifdef CONFIG_SMP
+	affected_cpu_map = cpu_sibling_map[cpu];
+#else
+	affected_cpu_map = cpumask_of_cpu(cpu);
 #endif
 	set_cpus_allowed(current, affected_cpu_map);
         BUG_ON(!cpu_isset(smp_processor_id(), affected_cpu_map));
@@ -97,11 +93,11 @@ static int cpufreq_p4_setdc(unsigned int
 	/* notifiers */
 	freqs.old = stock_freq * l / 8;
 	freqs.new = stock_freq * newstate / 8;
-	freqs.cpu = cpu;
-	cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
-	if (hyperthreading) {
-		freqs.cpu = sibling;
-		cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
+	for_each_cpu(j) {
+		if (cpu_isset(j, affected_cpu_map)) {
+			freqs.cpu = j;
+			cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
+		}
 	}
 
 	rdmsr(MSR_IA32_THERM_STATUS, l, h);
@@ -132,10 +128,11 @@ static int cpufreq_p4_setdc(unsigned int
 	set_cpus_allowed(current, cpus_allowed);
 
 	/* notifiers */
-	cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
-	if (hyperthreading) {
-		freqs.cpu = cpu;
-		cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
+	for_each_cpu(j) {
+		if (cpu_isset(j, affected_cpu_map)) {
+			freqs.cpu = j;
+			cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
+		}
 	}
 
 	return 0;
--- diff/arch/i386/kernel/cpu/cpufreq/powernow-k7.c	2004-02-18 08:54:07.000000000 +0000
+++ source/arch/i386/kernel/cpu/cpufreq/powernow-k7.c	2004-02-23 13:56:37.000000000 +0000
@@ -1,7 +1,7 @@
 /*
  *  AMD K7 Powernow driver.
  *  (C) 2003 Dave Jones <davej@codemonkey.org.uk> on behalf of SuSE Labs.
- *  (C) 2003 Dave Jones <davej@redhat.com>
+ *  (C) 2003-2004 Dave Jones <davej@redhat.com>
  *
  *  Licensed under the terms of the GNU GPL License version 2.
  *  Based upon datasheets & sample CPUs kindly provided by AMD.
--- diff/arch/i386/kernel/cpu/cpufreq/powernow-k8.c	2004-02-18 08:54:07.000000000 +0000
+++ source/arch/i386/kernel/cpu/cpufreq/powernow-k8.c	2004-02-23 13:56:37.000000000 +0000
@@ -521,7 +521,8 @@ static int check_pst_table(struct pst_s 
 		}
 		if ((pst[j].fid > MAX_FID)
 		    || (pst[j].fid & 1)
-		    || (pst[j].fid < HI_FID_TABLE_BOTTOM)){
+		    || (j && (pst[j].fid < HI_FID_TABLE_BOTTOM))) {
+			/* Only first fid is allowed to be in "low" range */
 			printk(KERN_ERR PFX "fid %d invalid : 0x%x\n", j, pst[j].fid);
 			return -EINVAL;
 		}
--- diff/arch/i386/kernel/cpu/intel.c	2004-02-18 08:54:07.000000000 +0000
+++ source/arch/i386/kernel/cpu/intel.c	2004-02-23 13:56:37.000000000 +0000
@@ -10,6 +10,7 @@
 #include <asm/processor.h>
 #include <asm/msr.h>
 #include <asm/uaccess.h>
+#include <asm/desc.h>
 
 #include "cpu.h"
 
@@ -19,8 +20,6 @@
 #include <mach_apic.h>
 #endif
 
-extern int trap_init_f00f_bug(void);
-
 #ifdef CONFIG_X86_INTEL_USERCOPY
 /*
  * Alignment at which movsl is preferred for bulk memory copies.
@@ -165,7 +164,7 @@ static void __init init_intel(struct cpu
 
 		c->f00f_bug = 1;
 		if ( !f00f_workaround_enabled ) {
-			trap_init_f00f_bug();
+			trap_init_virtual_IDT();
 			printk(KERN_NOTICE "Intel Pentium with F0 0F bug - workaround enabled.\n");
 			f00f_workaround_enabled = 1;
 		}
@@ -231,6 +230,8 @@ static void __init init_intel(struct cpu
 			printk (KERN_INFO "CPU: L1 I cache: %dK", l1i);
 		if ( l1d )
 			printk(", L1 D cache: %dK\n", l1d);
+		else
+			printk("\n");
 		if ( l2 )
 			printk(KERN_INFO "CPU: L2 cache: %dK\n", l2);
 		if ( l3 )
@@ -248,6 +249,12 @@ static void __init init_intel(struct cpu
 	/* SEP CPUID bug: Pentium Pro reports SEP but doesn't have it until model 3 mask 3 */
 	if ((c->x86<<8 | c->x86_model<<4 | c->x86_mask) < 0x633)
 		clear_bit(X86_FEATURE_SEP, c->x86_capability);
+	/*
+	 * FIXME: SEP is disabled for 4G/4G for now:
+	 */
+#ifdef CONFIG_X86_HIGH_ENTRY
+	clear_bit(X86_FEATURE_SEP, c->x86_capability);
+#endif
 
 	/* Names for the Pentium II/Celeron processors 
 	   detectable only by also checking the cache size.
--- diff/arch/i386/kernel/cpu/mcheck/non-fatal.c	2004-02-09 10:36:07.000000000 +0000
+++ source/arch/i386/kernel/cpu/mcheck/non-fatal.c	2004-02-23 13:56:37.000000000 +0000
@@ -24,8 +24,6 @@
 
 #include "mce.h"
 
-static struct timer_list mce_timer;
-static int timerset;
 static int firstbank;
 
 #define MCE_RATE	15*HZ	/* timer rate is 15s */
@@ -35,14 +33,15 @@ static void mce_checkregs (void *info)
 	u32 low, high;
 	int i;
 
-	preempt_disable(); 
 	for (i=firstbank; i<nr_mce_banks; i++) {
 		rdmsr (MSR_IA32_MC0_STATUS+i*4, low, high);
 
 		if (high & (1<<31)) {
-			printk (KERN_EMERG "MCE: The hardware reports a non fatal, correctable incident occurred on CPU %d.\n",
+			printk(KERN_INFO "MCE: The hardware reports a non "
+				"fatal, correctable incident occurred on "
+				"CPU %d.\n",
 				smp_processor_id());
-			printk (KERN_EMERG "Bank %d: %08x%08x\n", i, high, low);
+			printk (KERN_INFO "Bank %d: %08x%08x\n", i, high, low);
 
 			/* Scrub the error so we don't pick it up in MCE_RATE seconds time. */
 			wrmsr (MSR_IA32_MC0_STATUS+i*4, 0UL, 0UL);
@@ -51,27 +50,17 @@ static void mce_checkregs (void *info)
 			wmb();
 		}
 	}
-	preempt_enable();
 }
 
-static void do_mce_timer(void *data)
+static void mce_work_fn(void *data);
+static DECLARE_WORK(mce_work, mce_work_fn, NULL);
+
+static void mce_work_fn(void *data)
 { 
-	smp_call_function (mce_checkregs, NULL, 1, 1);
+	on_each_cpu(mce_checkregs, NULL, 1, 1);
+	schedule_delayed_work(&mce_work, MCE_RATE);
 } 
 
-static DECLARE_WORK(mce_work, do_mce_timer, NULL);
-
-static void mce_timerfunc (unsigned long data)
-{
-	mce_checkregs (NULL);
-#ifdef CONFIG_SMP
-	if (num_online_cpus() > 1) 
-		schedule_work (&mce_work); 
-#endif
-	mce_timer.expires = jiffies + MCE_RATE;
-	add_timer (&mce_timer);
-}	
-
 static int __init init_nonfatal_mce_checker(void)
 {
 	struct cpuinfo_x86 *c = &boot_cpu_data;
@@ -91,17 +80,11 @@ static int __init init_nonfatal_mce_chec
 	else
 			firstbank = 0;
 
-	if (timerset == 0) {
-		/* Set the timer to check for non-fatal
-		   errors every MCE_RATE seconds */
-		init_timer (&mce_timer);
-		mce_timer.expires = jiffies + MCE_RATE;
-		mce_timer.data = 0;
-		mce_timer.function = &mce_timerfunc;
-		add_timer (&mce_timer);
-		timerset = 1;
-		printk(KERN_INFO "Machine check exception polling timer started.\n");
-	}
+	/*
+	 * Check for non-fatal errors every MCE_RATE s
+	 */
+	schedule_delayed_work(&mce_work, MCE_RATE);
+	printk(KERN_INFO "Machine check exception polling timer started.\n");
 	return 0;
 }
 module_init(init_nonfatal_mce_checker);
--- diff/arch/i386/kernel/cpu/mtrr/generic.c	2003-08-26 10:00:51.000000000 +0100
+++ source/arch/i386/kernel/cpu/mtrr/generic.c	2004-02-23 13:56:37.000000000 +0000
@@ -45,7 +45,7 @@ get_fixed_ranges(mtrr_type * frs)
 }
 
 /*  Grab all of the MTRR state for this CPU into *state  */
-void get_mtrr_state(void)
+void __init get_mtrr_state(void)
 {
 	unsigned int i;
 	struct mtrr_var_range *vrs;
@@ -142,7 +142,7 @@ void generic_get_mtrr(unsigned int reg, 
 	*type = base_lo & 0xff;
 }
 
-static int __init set_fixed_ranges(mtrr_type * frs)
+static int set_fixed_ranges(mtrr_type * frs)
 {
 	unsigned int *p = (unsigned int *) frs;
 	int changed = FALSE;
@@ -177,7 +177,7 @@ static int __init set_fixed_ranges(mtrr_
 
 /*  Set the MSR pair relating to a var range. Returns TRUE if
     changes are made  */
-static int __init set_mtrr_var_ranges(unsigned int index, struct mtrr_var_range *vr)
+static int set_mtrr_var_ranges(unsigned int index, struct mtrr_var_range *vr)
 {
 	unsigned int lo, hi;
 	int changed = FALSE;
--- diff/arch/i386/kernel/cpu/mtrr/main.c	2003-09-17 12:28:01.000000000 +0100
+++ source/arch/i386/kernel/cpu/mtrr/main.c	2004-02-23 13:56:37.000000000 +0000
@@ -111,7 +111,7 @@ void __init set_num_var_ranges(void)
 	num_var_ranges = config & 0xff;
 }
 
-static void init_table(void)
+static void __init init_table(void)
 {
 	int i, max;
 
@@ -541,7 +541,7 @@ static void __init init_ifs(void)
 	centaur_init_mtrr();
 }
 
-static void init_other_cpus(void)
+static void __init init_other_cpus(void)
 {
 	if (use_intel())
 		get_mtrr_state();
@@ -608,7 +608,7 @@ static struct sysdev_driver mtrr_sysdev_
 
 
 /**
- * mtrr_init - initialie mtrrs on the boot CPU
+ * mtrr_init - initialize mtrrs on the boot CPU
  *
  * This needs to be called early; before any of the other CPUs are 
  * initialized (i.e. before smp_init()).
@@ -618,7 +618,7 @@ static int __init mtrr_init(void)
 {
 	init_ifs();
 
-	if ( cpu_has_mtrr ) {
+	if (cpu_has_mtrr) {
 		mtrr_if = &generic_mtrr_ops;
 		size_or_mask = 0xff000000;	/* 36 bits */
 		size_and_mask = 0x00f00000;
@@ -660,7 +660,7 @@ static int __init mtrr_init(void)
 	} else {
 		switch (boot_cpu_data.x86_vendor) {
 		case X86_VENDOR_AMD:
-			if ( cpu_has_k6_mtrr ) {
+			if (cpu_has_k6_mtrr) {
 				/* Pre-Athlon (K6) AMD CPU MTRRs */
 				mtrr_if = mtrr_ops[X86_VENDOR_AMD];
 				size_or_mask = 0xfff00000;	/* 32 bits */
@@ -668,14 +668,14 @@ static int __init mtrr_init(void)
 			}
 			break;
 		case X86_VENDOR_CENTAUR:
-			if ( cpu_has_centaur_mcr ) {
+			if (cpu_has_centaur_mcr) {
 				mtrr_if = mtrr_ops[X86_VENDOR_CENTAUR];
 				size_or_mask = 0xfff00000;	/* 32 bits */
 				size_and_mask = 0;
 			}
 			break;
 		case X86_VENDOR_CYRIX:
-			if ( cpu_has_cyrix_arr ) {
+			if (cpu_has_cyrix_arr) {
 				mtrr_if = mtrr_ops[X86_VENDOR_CYRIX];
 				size_or_mask = 0xfff00000;	/* 32 bits */
 				size_and_mask = 0;
--- diff/arch/i386/kernel/cpu/proc.c	2003-08-26 10:00:51.000000000 +0100
+++ source/arch/i386/kernel/cpu/proc.c	2004-02-23 13:56:37.000000000 +0000
@@ -50,7 +50,7 @@ static int show_cpuinfo(struct seq_file 
 		NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
 
 		/* VIA/Cyrix/Centaur-defined */
-		NULL, NULL, "xstore", NULL, NULL, NULL, NULL, NULL,
+		NULL, NULL, "rng", "rng_en", NULL, NULL, "ace", "ace_en",
 		NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
 		NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
 		NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
--- diff/arch/i386/kernel/doublefault.c	2003-10-09 09:47:16.000000000 +0100
+++ source/arch/i386/kernel/doublefault.c	2004-02-23 13:56:37.000000000 +0000
@@ -7,12 +7,13 @@
 #include <asm/uaccess.h>
 #include <asm/pgtable.h>
 #include <asm/desc.h>
+#include <asm/fixmap.h>
 
 #define DOUBLEFAULT_STACKSIZE (1024)
 static unsigned long doublefault_stack[DOUBLEFAULT_STACKSIZE];
 #define STACK_START (unsigned long)(doublefault_stack+DOUBLEFAULT_STACKSIZE)
 
-#define ptr_ok(x) ((x) > 0xc0000000 && (x) < 0xc1000000)
+#define ptr_ok(x) (((x) > __PAGE_OFFSET && (x) < (__PAGE_OFFSET + 0x01000000)) || ((x) >= FIXADDR_START))
 
 static void doublefault_fn(void)
 {
@@ -38,8 +39,8 @@ static void doublefault_fn(void)
 
 			printk("eax = %08lx, ebx = %08lx, ecx = %08lx, edx = %08lx\n",
 				t->eax, t->ebx, t->ecx, t->edx);
-			printk("esi = %08lx, edi = %08lx\n",
-				t->esi, t->edi);
+			printk("esi = %08lx, edi = %08lx, ebp = %08lx\n",
+				t->esi, t->edi, t->ebp);
 		}
 	}
 
--- diff/arch/i386/kernel/edd.c	2004-02-18 08:54:07.000000000 +0000
+++ source/arch/i386/kernel/edd.c	2004-02-23 13:56:37.000000000 +0000
@@ -134,18 +134,18 @@ edd_show_host_bus(struct edd_device *ede
 
 	for (i = 0; i < 4; i++) {
 		if (isprint(info->params.host_bus_type[i])) {
-			p += snprintf(p, left, "%c", info->params.host_bus_type[i]);
+			p += scnprintf(p, left, "%c", info->params.host_bus_type[i]);
 		} else {
-			p += snprintf(p, left, " ");
+			p += scnprintf(p, left, " ");
 		}
 	}
 
 	if (!strncmp(info->params.host_bus_type, "ISA", 3)) {
-		p += snprintf(p, left, "\tbase_address: %x\n",
+		p += scnprintf(p, left, "\tbase_address: %x\n",
 			     info->params.interface_path.isa.base_address);
 	} else if (!strncmp(info->params.host_bus_type, "PCIX", 4) ||
 		   !strncmp(info->params.host_bus_type, "PCI", 3)) {
-		p += snprintf(p, left,
+		p += scnprintf(p, left,
 			     "\t%02x:%02x.%d  channel: %u\n",
 			     info->params.interface_path.pci.bus,
 			     info->params.interface_path.pci.slot,
@@ -154,12 +154,12 @@ edd_show_host_bus(struct edd_device *ede
 	} else if (!strncmp(info->params.host_bus_type, "IBND", 4) ||
 		   !strncmp(info->params.host_bus_type, "XPRS", 4) ||
 		   !strncmp(info->params.host_bus_type, "HTPT", 4)) {
-		p += snprintf(p, left,
+		p += scnprintf(p, left,
 			     "\tTBD: %llx\n",
 			     info->params.interface_path.ibnd.reserved);
 
 	} else {
-		p += snprintf(p, left, "\tunknown: %llx\n",
+		p += scnprintf(p, left, "\tunknown: %llx\n",
 			     info->params.interface_path.unknown.reserved);
 	}
 	return (p - buf);
@@ -178,43 +178,43 @@ edd_show_interface(struct edd_device *ed
 
 	for (i = 0; i < 8; i++) {
 		if (isprint(info->params.interface_type[i])) {
-			p += snprintf(p, left, "%c", info->params.interface_type[i]);
+			p += scnprintf(p, left, "%c", info->params.interface_type[i]);
 		} else {
-			p += snprintf(p, left, " ");
+			p += scnprintf(p, left, " ");
 		}
 	}
 	if (!strncmp(info->params.interface_type, "ATAPI", 5)) {
-		p += snprintf(p, left, "\tdevice: %u  lun: %u\n",
+		p += scnprintf(p, left, "\tdevice: %u  lun: %u\n",
 			     info->params.device_path.atapi.device,
 			     info->params.device_path.atapi.lun);
 	} else if (!strncmp(info->params.interface_type, "ATA", 3)) {
-		p += snprintf(p, left, "\tdevice: %u\n",
+		p += scnprintf(p, left, "\tdevice: %u\n",
 			     info->params.device_path.ata.device);
 	} else if (!strncmp(info->params.interface_type, "SCSI", 4)) {
-		p += snprintf(p, left, "\tid: %u  lun: %llu\n",
+		p += scnprintf(p, left, "\tid: %u  lun: %llu\n",
 			     info->params.device_path.scsi.id,
 			     info->params.device_path.scsi.lun);
 	} else if (!strncmp(info->params.interface_type, "USB", 3)) {
-		p += snprintf(p, left, "\tserial_number: %llx\n",
+		p += scnprintf(p, left, "\tserial_number: %llx\n",
 			     info->params.device_path.usb.serial_number);
 	} else if (!strncmp(info->params.interface_type, "1394", 4)) {
-		p += snprintf(p, left, "\teui: %llx\n",
+		p += scnprintf(p, left, "\teui: %llx\n",
 			     info->params.device_path.i1394.eui);
 	} else if (!strncmp(info->params.interface_type, "FIBRE", 5)) {
-		p += snprintf(p, left, "\twwid: %llx lun: %llx\n",
+		p += scnprintf(p, left, "\twwid: %llx lun: %llx\n",
 			     info->params.device_path.fibre.wwid,
 			     info->params.device_path.fibre.lun);
 	} else if (!strncmp(info->params.interface_type, "I2O", 3)) {
-		p += snprintf(p, left, "\tidentity_tag: %llx\n",
+		p += scnprintf(p, left, "\tidentity_tag: %llx\n",
 			     info->params.device_path.i2o.identity_tag);
 	} else if (!strncmp(info->params.interface_type, "RAID", 4)) {
-		p += snprintf(p, left, "\tidentity_tag: %x\n",
+		p += scnprintf(p, left, "\tidentity_tag: %x\n",
 			     info->params.device_path.raid.array_number);
 	} else if (!strncmp(info->params.interface_type, "SATA", 4)) {
-		p += snprintf(p, left, "\tdevice: %u\n",
+		p += scnprintf(p, left, "\tdevice: %u\n",
 			     info->params.device_path.sata.device);
 	} else {
-		p += snprintf(p, left, "\tunknown: %llx %llx\n",
+		p += scnprintf(p, left, "\tunknown: %llx %llx\n",
 			     info->params.device_path.unknown.reserved1,
 			     info->params.device_path.unknown.reserved2);
 	}
@@ -256,7 +256,7 @@ edd_show_version(struct edd_device *edev
 		return -EINVAL;
 	}
 
-	p += snprintf(p, left, "0x%02x\n", info->version);
+	p += scnprintf(p, left, "0x%02x\n", info->version);
 	return (p - buf);
 }
 
@@ -264,7 +264,7 @@ static ssize_t
 edd_show_disk80_sig(struct edd_device *edev, char *buf)
 {
 	char *p = buf;
-	p += snprintf(p, left, "0x%08x\n", edd_disk80_sig);
+	p += scnprintf(p, left, "0x%08x\n", edd_disk80_sig);
 	return (p - buf);
 }
 
@@ -278,16 +278,16 @@ edd_show_extensions(struct edd_device *e
 	}
 
 	if (info->interface_support & EDD_EXT_FIXED_DISK_ACCESS) {
-		p += snprintf(p, left, "Fixed disk access\n");
+		p += scnprintf(p, left, "Fixed disk access\n");
 	}
 	if (info->interface_support & EDD_EXT_DEVICE_LOCKING_AND_EJECTING) {
-		p += snprintf(p, left, "Device locking and ejecting\n");
+		p += scnprintf(p, left, "Device locking and ejecting\n");
 	}
 	if (info->interface_support & EDD_EXT_ENHANCED_DISK_DRIVE_SUPPORT) {
-		p += snprintf(p, left, "Enhanced Disk Drive support\n");
+		p += scnprintf(p, left, "Enhanced Disk Drive support\n");
 	}
 	if (info->interface_support & EDD_EXT_64BIT_EXTENSIONS) {
-		p += snprintf(p, left, "64-bit extensions\n");
+		p += scnprintf(p, left, "64-bit extensions\n");
 	}
 	return (p - buf);
 }
@@ -302,21 +302,21 @@ edd_show_info_flags(struct edd_device *e
 	}
 
 	if (info->params.info_flags & EDD_INFO_DMA_BOUNDARY_ERROR_TRANSPARENT)
-		p += snprintf(p, left, "DMA boundary error transparent\n");
+		p += scnprintf(p, left, "DMA boundary error transparent\n");
 	if (info->params.info_flags & EDD_INFO_GEOMETRY_VALID)
-		p += snprintf(p, left, "geometry valid\n");
+		p += scnprintf(p, left, "geometry valid\n");
 	if (info->params.info_flags & EDD_INFO_REMOVABLE)
-		p += snprintf(p, left, "removable\n");
+		p += scnprintf(p, left, "removable\n");
 	if (info->params.info_flags & EDD_INFO_WRITE_VERIFY)
-		p += snprintf(p, left, "write verify\n");
+		p += scnprintf(p, left, "write verify\n");
 	if (info->params.info_flags & EDD_INFO_MEDIA_CHANGE_NOTIFICATION)
-		p += snprintf(p, left, "media change notification\n");
+		p += scnprintf(p, left, "media change notification\n");
 	if (info->params.info_flags & EDD_INFO_LOCKABLE)
-		p += snprintf(p, left, "lockable\n");
+		p += scnprintf(p, left, "lockable\n");
 	if (info->params.info_flags & EDD_INFO_NO_MEDIA_PRESENT)
-		p += snprintf(p, left, "no media present\n");
+		p += scnprintf(p, left, "no media present\n");
 	if (info->params.info_flags & EDD_INFO_USE_INT13_FN50)
-		p += snprintf(p, left, "use int13 fn50\n");
+		p += scnprintf(p, left, "use int13 fn50\n");
 	return (p - buf);
 }
 
@@ -329,7 +329,7 @@ edd_show_default_cylinders(struct edd_de
 		return -EINVAL;
 	}
 
-	p += snprintf(p, left, "0x%x\n", info->params.num_default_cylinders);
+	p += scnprintf(p, left, "0x%x\n", info->params.num_default_cylinders);
 	return (p - buf);
 }
 
@@ -342,7 +342,7 @@ edd_show_default_heads(struct edd_device
 		return -EINVAL;
 	}
 
-	p += snprintf(p, left, "0x%x\n", info->params.num_default_heads);
+	p += scnprintf(p, left, "0x%x\n", info->params.num_default_heads);
 	return (p - buf);
 }
 
@@ -355,7 +355,7 @@ edd_show_default_sectors_per_track(struc
 		return -EINVAL;
 	}
 
-	p += snprintf(p, left, "0x%x\n", info->params.sectors_per_track);
+	p += scnprintf(p, left, "0x%x\n", info->params.sectors_per_track);
 	return (p - buf);
 }
 
@@ -368,7 +368,7 @@ edd_show_sectors(struct edd_device *edev
 		return -EINVAL;
 	}
 
-	p += snprintf(p, left, "0x%llx\n", info->params.number_of_sectors);
+	p += scnprintf(p, left, "0x%llx\n", info->params.number_of_sectors);
 	return (p - buf);
 }
 
--- diff/arch/i386/kernel/entry.S	2003-11-25 15:24:57.000000000 +0000
+++ source/arch/i386/kernel/entry.S	2004-02-23 13:56:37.000000000 +0000
@@ -43,11 +43,25 @@
 #include <linux/config.h>
 #include <linux/linkage.h>
 #include <asm/thread_info.h>
+#include <asm/asm_offsets.h>
 #include <asm/errno.h>
 #include <asm/segment.h>
+#include <asm/page.h>
 #include <asm/smp.h>
 #include <asm/page.h>
 #include "irq_vectors.h"
+        /* We do not recover from a stack overflow, but at least
+         * we know it happened and should be able to track it down.
+         */
+#ifdef CONFIG_STACK_OVERFLOW_TEST
+#define STACK_OVERFLOW_TEST \
+        testl $7680,%esp;    \
+        jnz   10f;            \
+        call  stack_overflow; \
+10:
+#else
+#define STACK_OVERFLOW_TEST
+#endif
 
 #define nr_syscalls ((syscall_table_size)/4)
 
@@ -87,7 +101,102 @@ TSS_ESP0_OFFSET = (4 - 0x200)
 #define resume_kernel		restore_all
 #endif
 
-#define SAVE_ALL \
+#ifdef CONFIG_X86_HIGH_ENTRY
+
+#ifdef CONFIG_X86_SWITCH_PAGETABLES
+
+#if defined(CONFIG_PREEMPT) && defined(CONFIG_SMP)
+/*
+ * If task is preempted in __SWITCH_KERNELSPACE, and moved to another cpu,
+ * __switch_to repoints %esp to the appropriate virtual stack; but %ebp is
+ * left stale, so we must check whether to repeat the real stack calculation.
+ */
+#define repeat_if_esp_changed				\
+	xorl %esp, %ebp;				\
+	testl $-THREAD_SIZE, %ebp;			\
+	jnz 0b
+#else
+#define repeat_if_esp_changed
+#endif
+
+/* clobbers ebx, edx and ebp */
+
+#define __SWITCH_KERNELSPACE				\
+	cmpl $0xff000000, %esp;				\
+	jb 1f;						\
+							\
+	/*						\
+	 * switch pagetables and load the real stack,	\
+	 * keep the stack offset:			\
+	 */						\
+							\
+	movl $swapper_pg_dir-__PAGE_OFFSET, %edx;	\
+							\
+	/* GET_THREAD_INFO(%ebp) intermixed */		\
+0:							\
+	movl %esp, %ebp;				\
+	movl %esp, %ebx;				\
+	andl $(-THREAD_SIZE), %ebp;				\
+	andl $(THREAD_SIZE-1), %ebx;				\
+	orl TI_real_stack(%ebp), %ebx;			\
+	repeat_if_esp_changed;				\
+							\
+	movl %edx, %cr3;				\
+	movl %ebx, %esp;				\
+1:
+
+#endif
+
+
+#define __SWITCH_USERSPACE \
+	/* interrupted any of the user return paths? */	\
+							\
+	movl EIP(%esp), %eax;				\
+							\
+	cmpl $int80_ret_start_marker, %eax;		\
+	jb 33f; /* nope - continue with sysexit check */\
+	cmpl $int80_ret_end_marker, %eax;		\
+	jb 22f; /* yes - switch to virtual stack */	\
+33:							\
+	cmpl $sysexit_ret_start_marker, %eax;		\
+	jb 44f; /* nope - continue with user check */	\
+	cmpl $sysexit_ret_end_marker, %eax;		\
+	jb 22f; /* yes - switch to virtual stack */	\
+	/* return to userspace? */			\
+44:							\
+	movl EFLAGS(%esp),%ecx;				\
+	movb CS(%esp),%cl;				\
+	testl $(VM_MASK | 3),%ecx;			\
+	jz 2f;						\
+22:							\
+	/*						\
+	 * switch to the virtual stack, then switch to	\
+	 * the userspace pagetables.			\
+	 */						\
+							\
+	GET_THREAD_INFO(%ebp);				\
+	movl TI_virtual_stack(%ebp), %edx;		\
+	movl TI_user_pgd(%ebp), %ecx;			\
+							\
+	movl %esp, %ebx;				\
+	andl $(THREAD_SIZE-1), %ebx;				\
+	orl %ebx, %edx;					\
+int80_ret_start_marker:					\
+	movl %edx, %esp; 				\
+	movl %ecx, %cr3;				\
+							\
+	__RESTORE_ALL;					\
+int80_ret_end_marker:					\
+2:
+
+#else /* !CONFIG_X86_HIGH_ENTRY */
+
+#define __SWITCH_KERNELSPACE
+#define __SWITCH_USERSPACE
+
+#endif
+
+#define __SAVE_ALL \
 	cld; \
 	pushl %es; \
 	pushl %ds; \
@@ -102,7 +211,7 @@ TSS_ESP0_OFFSET = (4 - 0x200)
 	movl %edx, %ds; \
 	movl %edx, %es;
 
-#define RESTORE_INT_REGS \
+#define __RESTORE_INT_REGS \
 	popl %ebx;	\
 	popl %ecx;	\
 	popl %edx;	\
@@ -111,29 +220,28 @@ TSS_ESP0_OFFSET = (4 - 0x200)
 	popl %ebp;	\
 	popl %eax
 
-#define RESTORE_REGS	\
-	RESTORE_INT_REGS; \
-1:	popl %ds;	\
-2:	popl %es;	\
+#define __RESTORE_REGS	\
+	__RESTORE_INT_REGS; \
+111:	popl %ds;	\
+222:	popl %es;	\
 .section .fixup,"ax";	\
-3:	movl $0,(%esp);	\
-	jmp 1b;		\
-4:	movl $0,(%esp);	\
-	jmp 2b;		\
+444:	movl $0,(%esp);	\
+	jmp 111b;	\
+555:	movl $0,(%esp);	\
+	jmp 222b;	\
 .previous;		\
 .section __ex_table,"a";\
 	.align 4;	\
-	.long 1b,3b;	\
-	.long 2b,4b;	\
+	.long 111b,444b;\
+	.long 222b,555b;\
 .previous
 
-
-#define RESTORE_ALL	\
-	RESTORE_REGS	\
+#define __RESTORE_ALL	\
+	__RESTORE_REGS	\
 	addl $4, %esp;	\
-1:	iret;		\
+333:	iret;		\
 .section .fixup,"ax";   \
-2:	sti;		\
+666:	sti;		\
 	movl $(__USER_DS), %edx; \
 	movl %edx, %ds; \
 	movl %edx, %es; \
@@ -142,10 +250,19 @@ TSS_ESP0_OFFSET = (4 - 0x200)
 .previous;		\
 .section __ex_table,"a";\
 	.align 4;	\
-	.long 1b,2b;	\
+	.long 333b,666b;\
 .previous
 
+#define SAVE_ALL \
+	__SAVE_ALL;					\
+	__SWITCH_KERNELSPACE;				\
+        STACK_OVERFLOW_TEST;
+
+#define RESTORE_ALL					\
+	__SWITCH_USERSPACE;				\
+	__RESTORE_ALL;
 
+.section .entry.text,"ax"
 
 ENTRY(lcall7)
 	pushfl			# We get a different stack layout with call
@@ -162,8 +279,8 @@ do_lcall:
 	movl %eax,EFLAGS(%ebp)	#
 	movl %edx,EIP(%ebp)	# Now we move them to their "normal" places
 	movl %ecx,CS(%ebp)	#
-	andl $-8192, %ebp	# GET_THREAD_INFO
-	movl TI_EXEC_DOMAIN(%ebp), %edx	# Get the execution domain
+	GET_THREAD_INFO_WITH_ESP(%ebp)	# GET_THREAD_INFO
+	movl TI_exec_domain(%ebp), %edx	# Get the execution domain
 	call *4(%edx)		# Call the lcall7 handler for the domain
 	addl $4, %esp
 	popl %eax
@@ -208,7 +325,7 @@ ENTRY(resume_userspace)
  	cli				# make sure we don't miss an interrupt
 					# setting need_resched or sigpending
 					# between sampling and the iret
-	movl TI_FLAGS(%ebp), %ecx
+	movl TI_flags(%ebp), %ecx
 	andl $_TIF_WORK_MASK, %ecx	# is there any work to be done on
 					# int/exception return?
 	jne work_pending
@@ -216,18 +333,18 @@ ENTRY(resume_userspace)
 
 #ifdef CONFIG_PREEMPT
 ENTRY(resume_kernel)
-	cmpl $0,TI_PRE_COUNT(%ebp)	# non-zero preempt_count ?
+	cmpl $0,TI_preempt_count(%ebp)	# non-zero preempt_count ?
 	jnz restore_all
 need_resched:
-	movl TI_FLAGS(%ebp), %ecx	# need_resched set ?
+	movl TI_flags(%ebp), %ecx	# need_resched set ?
 	testb $_TIF_NEED_RESCHED, %cl
 	jz restore_all
 	testl $IF_MASK,EFLAGS(%esp)     # interrupts off (exception path) ?
 	jz restore_all
-	movl $PREEMPT_ACTIVE,TI_PRE_COUNT(%ebp)
+	movl $PREEMPT_ACTIVE,TI_preempt_count(%ebp)
 	sti
 	call schedule
-	movl $0,TI_PRE_COUNT(%ebp)
+	movl $0,TI_preempt_count(%ebp)
 	cli
 	jmp need_resched
 #endif
@@ -246,37 +363,50 @@ sysenter_past_esp:
 	pushl $(__USER_CS)
 	pushl $SYSENTER_RETURN
 
-/*
- * Load the potential sixth argument from user stack.
- * Careful about security.
- */
-	cmpl $__PAGE_OFFSET-3,%ebp
-	jae syscall_fault
-1:	movl (%ebp),%ebp
-.section __ex_table,"a"
-	.align 4
-	.long 1b,syscall_fault
-.previous
-
 	pushl %eax
 	SAVE_ALL
 	GET_THREAD_INFO(%ebp)
 	cmpl $(nr_syscalls), %eax
 	jae syscall_badsys
 
-	testb $_TIF_SYSCALL_TRACE,TI_FLAGS(%ebp)
+	testb $_TIF_SYSCALL_TRACE,TI_flags(%ebp)
 	jnz syscall_trace_entry
 	call *sys_call_table(,%eax,4)
 	movl %eax,EAX(%esp)
 	cli
-	movl TI_FLAGS(%ebp), %ecx
+	movl TI_flags(%ebp), %ecx
 	testw $_TIF_ALLWORK_MASK, %cx
 	jne syscall_exit_work
+
+#ifdef CONFIG_X86_SWITCH_PAGETABLES
+
+	GET_THREAD_INFO(%ebp)
+	movl TI_virtual_stack(%ebp), %edx
+	movl TI_user_pgd(%ebp), %ecx
+	movl %esp, %ebx
+	andl $(THREAD_SIZE-1), %ebx
+	orl %ebx, %edx
+sysexit_ret_start_marker:
+	movl %edx, %esp
+	movl %ecx, %cr3
+#endif
+	/*
+	 * only ebx is not restored by the userspace sysenter vsyscall
+	 * code, it assumes it to be callee-saved.
+	 */
+	movl EBX(%esp), %ebx
+
 /* if something modifies registers it must also disable sysexit */
+
 	movl EIP(%esp), %edx
 	movl OLDESP(%esp), %ecx
+
 	sti
 	sysexit
+#ifdef CONFIG_X86_SWITCH_PAGETABLES
+sysexit_ret_end_marker:
+	nop
+#endif
 
 
 	# system call handler stub
@@ -287,7 +417,7 @@ ENTRY(system_call)
 	cmpl $(nr_syscalls), %eax
 	jae syscall_badsys
 					# system call tracing in operation
-	testb $_TIF_SYSCALL_TRACE,TI_FLAGS(%ebp)
+	testb $_TIF_SYSCALL_TRACE,TI_flags(%ebp)
 	jnz syscall_trace_entry
 syscall_call:
 	call *sys_call_table(,%eax,4)
@@ -296,10 +426,23 @@ syscall_exit:
 	cli				# make sure we don't miss an interrupt
 					# setting need_resched or sigpending
 					# between sampling and the iret
-	movl TI_FLAGS(%ebp), %ecx
+	movl TI_flags(%ebp), %ecx
 	testw $_TIF_ALLWORK_MASK, %cx	# current->work
 	jne syscall_exit_work
 restore_all:
+#ifdef CONFIG_TRAP_BAD_SYSCALL_EXITS
+	movl EFLAGS(%esp), %eax		# mix EFLAGS and CS
+	movb CS(%esp), %al
+	testl $(VM_MASK | 3), %eax
+	jz resume_kernelX		# returning to kernel or vm86-space
+
+	cmpl $0,TI_preempt_count(%ebp)	# non-zero preempt_count ?
+	jz resume_kernelX
+
+        int $3
+
+resume_kernelX:
+#endif
 	RESTORE_ALL
 
 	# perform work that needs to be done immediately before resumption
@@ -312,7 +455,7 @@ work_resched:
 	cli				# make sure we don't miss an interrupt
 					# setting need_resched or sigpending
 					# between sampling and the iret
-	movl TI_FLAGS(%ebp), %ecx
+	movl TI_flags(%ebp), %ecx
 	andl $_TIF_WORK_MASK, %ecx	# is there any work to be done other
 					# than syscall tracing?
 	jz restore_all
@@ -327,6 +470,22 @@ work_notifysig:				# deal with pending s
 					# vm86-space
 	xorl %edx, %edx
 	call do_notify_resume
+
+#if CONFIG_X86_HIGH_ENTRY
+	/*
+	 * Reload db7 if necessary:
+	 */
+	movl TI_flags(%ebp), %ecx
+	testb $_TIF_DB7, %cl
+	jnz work_db7
+
+	jmp restore_all
+
+work_db7:
+	movl TI_task(%ebp), %edx;
+	movl task_thread_db7(%edx), %edx;
+	movl %edx, %db7;
+#endif
 	jmp restore_all
 
 	ALIGN
@@ -382,7 +541,7 @@ syscall_badsys:
  */
 .data
 ENTRY(interrupt)
-.text
+.previous
 
 vector=0
 ENTRY(irq_entries_start)
@@ -392,7 +551,7 @@ ENTRY(irq_entries_start)
 	jmp common_interrupt
 .data
 	.long 1b
-.text
+.previous
 vector=vector+1
 .endr
 
@@ -433,12 +592,17 @@ error_code:
 	movl ES(%esp), %edi		# get the function address
 	movl %eax, ORIG_EAX(%esp)
 	movl %ecx, ES(%esp)
-	movl %esp, %edx
 	pushl %esi			# push the error code
-	pushl %edx			# push the pt_regs pointer
 	movl $(__USER_DS), %edx
 	movl %edx, %ds
 	movl %edx, %es
+
+/* clobbers edx, ebx and ebp */
+	__SWITCH_KERNELSPACE
+
+	leal 4(%esp), %edx		# prepare pt_regs
+	pushl %edx			# push pt_regs
+
 	call *%edi
 	addl $8, %esp
 	jmp ret_from_exception
@@ -515,8 +679,8 @@ ENTRY(nmi)
 	/* Do not access memory above the end of our stack page,
 	 * it might not exist.
 	 */
-	andl $0x1fff,%eax
-	cmpl $0x1fec,%eax
+	andl $(THREAD_SIZE-1),%eax
+	cmpl $(THREAD_SIZE-20),%eax
 	popl %eax
 	jae nmi_stack_correct
 	cmpl $sysenter_entry,12(%esp)
@@ -529,7 +693,7 @@ nmi_stack_correct:
 	pushl %edx
 	call do_nmi
 	addl $8, %esp
-	RESTORE_ALL
+	jmp restore_all
 
 nmi_stack_fixup:
 	FIX_STACK(12,nmi_stack_correct, 1)
@@ -606,6 +770,8 @@ ENTRY(spurious_interrupt_bug)
 	pushl $do_spurious_interrupt_bug
 	jmp error_code
 
+.previous
+
 .data
 ENTRY(sys_call_table)
 	.long sys_restart_syscall	/* 0 - old "setup()" system call, used for restarting */
--- diff/arch/i386/kernel/head.S	2003-10-09 09:47:16.000000000 +0100
+++ source/arch/i386/kernel/head.S	2004-02-23 13:56:37.000000000 +0000
@@ -16,6 +16,8 @@
 #include <asm/pgtable.h>
 #include <asm/desc.h>
 #include <asm/cache.h>
+#include <asm/thread_info.h>
+#include <asm/asm_offsets.h>
 
 #define OLD_CL_MAGIC_ADDR	0x90020
 #define OLD_CL_MAGIC		0xA33F
@@ -325,12 +327,12 @@ rp_sidt:
 	ret
 
 ENTRY(stack_start)
-	.long init_thread_union+8192
+	.long init_thread_union+THREAD_SIZE
 	.long __BOOT_DS
 
 /* This is the default interrupt "handler" :-) */
 int_msg:
-	.asciz "Unknown interrupt\n"
+	.asciz "Unknown interrupt or fault at EIP %p %p %p\n"
 	ALIGN
 ignore_int:
 	cld
@@ -342,9 +344,17 @@ ignore_int:
 	movl $(__KERNEL_DS),%eax
 	movl %eax,%ds
 	movl %eax,%es
+	pushl 16(%esp)
+	pushl 24(%esp)
+	pushl 32(%esp)
+	pushl 40(%esp)
 	pushl $int_msg
 	call printk
 	popl %eax
+	popl %eax
+	popl %eax
+	popl %eax
+	popl %eax
 	popl %ds
 	popl %es
 	popl %edx
@@ -377,23 +387,27 @@ cpu_gdt_descr:
 	.fill NR_CPUS-1,8,0		# space for the other GDT descriptors
 
 /*
- * This is initialized to create an identity-mapping at 0-8M (for bootup
- * purposes) and another mapping of the 0-8M area at virtual address
+ * This is initialized to create an identity-mapping at 0-16M (for bootup
+ * purposes) and another mapping of the 0-16M area at virtual address
  * PAGE_OFFSET.
  */
 .org 0x1000
 ENTRY(swapper_pg_dir)
 	.long 0x00102007
 	.long 0x00103007
-	.fill BOOT_USER_PGD_PTRS-2,4,0
-	/* default: 766 entries */
+	.long 0x00104007
+	.long 0x00105007
+	.fill BOOT_USER_PGD_PTRS-4,4,0
+	/* default: 764 entries */
 	.long 0x00102007
 	.long 0x00103007
-	/* default: 254 entries */
-	.fill BOOT_KERNEL_PGD_PTRS-2,4,0
+	.long 0x00104007
+	.long 0x00105007
+	/* default: 252 entries */
+	.fill BOOT_KERNEL_PGD_PTRS-4,4,0
 
 /*
- * The page tables are initialized to only 8MB here - the final page
+ * The page tables are initialized to only 16MB here - the final page
  * tables are set up later depending on memory size.
  */
 .org 0x2000
@@ -402,15 +416,21 @@ ENTRY(pg0)
 .org 0x3000
 ENTRY(pg1)
 
+.org 0x4000
+ENTRY(pg2)
+
+.org 0x5000
+ENTRY(pg3)
+
 /*
  * empty_zero_page must immediately follow the page tables ! (The
  * initialization loop counts until empty_zero_page)
  */
 
-.org 0x4000
+.org 0x6000
 ENTRY(empty_zero_page)
 
-.org 0x5000
+.org 0x7000
 
 /*
  * Real beginning of normal "text" segment
@@ -419,12 +439,12 @@ ENTRY(stext)
 ENTRY(_stext)
 
 /*
- * This starts the data section. Note that the above is all
- * in the text section because it has alignment requirements
- * that we cannot fulfill any other way.
+ * This starts the data section.
  */
 .data
 
+.align PAGE_SIZE_asm
+
 /*
  * The Global Descriptor Table contains 28 quadwords, per-CPU.
  */
@@ -439,7 +459,9 @@ ENTRY(boot_gdt_table)
 	.quad 0x00cf9a000000ffff	/* kernel 4GB code at 0x00000000 */
 	.quad 0x00cf92000000ffff	/* kernel 4GB data at 0x00000000 */
 #endif
-	.align L1_CACHE_BYTES
+
+.align PAGE_SIZE_asm
+
 ENTRY(cpu_gdt_table)
 	.quad 0x0000000000000000	/* NULL descriptor */
 	.quad 0x0000000000000000	/* 0x0b reserved */
--- diff/arch/i386/kernel/i386_ksyms.c	2004-02-18 08:54:07.000000000 +0000
+++ source/arch/i386/kernel/i386_ksyms.c	2004-02-23 13:56:37.000000000 +0000
@@ -97,7 +97,6 @@ EXPORT_SYMBOL_NOVERS(__down_failed_inter
 EXPORT_SYMBOL_NOVERS(__down_failed_trylock);
 EXPORT_SYMBOL_NOVERS(__up_wakeup);
 /* Networking helper routines. */
-EXPORT_SYMBOL(csum_partial_copy_generic);
 /* Delay loops */
 EXPORT_SYMBOL(__ndelay);
 EXPORT_SYMBOL(__udelay);
@@ -111,13 +110,17 @@ EXPORT_SYMBOL_NOVERS(__get_user_4);
 EXPORT_SYMBOL(strpbrk);
 EXPORT_SYMBOL(strstr);
 
+#if !defined(CONFIG_X86_UACCESS_INDIRECT)
 EXPORT_SYMBOL(strncpy_from_user);
-EXPORT_SYMBOL(__strncpy_from_user);
+EXPORT_SYMBOL(__direct_strncpy_from_user);
 EXPORT_SYMBOL(clear_user);
 EXPORT_SYMBOL(__clear_user);
 EXPORT_SYMBOL(__copy_from_user_ll);
 EXPORT_SYMBOL(__copy_to_user_ll);
 EXPORT_SYMBOL(strnlen_user);
+#else /* CONFIG_X86_UACCESS_INDIRECT */
+EXPORT_SYMBOL(direct_csum_partial_copy_generic);
+#endif
 
 EXPORT_SYMBOL(dma_alloc_coherent);
 EXPORT_SYMBOL(dma_free_coherent);
--- diff/arch/i386/kernel/i387.c	2004-02-18 08:54:07.000000000 +0000
+++ source/arch/i386/kernel/i387.c	2004-02-23 13:56:37.000000000 +0000
@@ -218,6 +218,7 @@ void set_fpu_mxcsr( struct task_struct *
 static int convert_fxsr_to_user( struct _fpstate __user *buf,
 					struct i387_fxsave_struct *fxsave )
 {
+	struct _fpreg tmp[8]; /* 80 bytes scratch area */
 	unsigned long env[7];
 	struct _fpreg __user *to;
 	struct _fpxreg *from;
@@ -234,23 +235,25 @@ static int convert_fxsr_to_user( struct 
 	if ( __copy_to_user( buf, env, 7 * sizeof(unsigned long) ) )
 		return 1;
 
-	to = &buf->_st[0];
+	to = tmp;
 	from = (struct _fpxreg *) &fxsave->st_space[0];
 	for ( i = 0 ; i < 8 ; i++, to++, from++ ) {
 		unsigned long *t = (unsigned long *)to;
 		unsigned long *f = (unsigned long *)from;
 
-		if (__put_user(*f, t) ||
-				__put_user(*(f + 1), t + 1) ||
-				__put_user(from->exponent, &to->exponent))
-			return 1;
+		*t = *f;
+		*(t + 1) = *(f+1);
+		to->exponent = from->exponent;
 	}
+	if (copy_to_user(buf->_st, tmp, sizeof(struct _fpreg [8])))
+		return 1;
 	return 0;
 }
 
 static int convert_fxsr_from_user( struct i387_fxsave_struct *fxsave,
 					  struct _fpstate __user *buf )
 {
+	struct _fpreg tmp[8]; /* 80 bytes scratch area */
 	unsigned long env[7];
 	struct _fpxreg *to;
 	struct _fpreg __user *from;
@@ -258,6 +261,8 @@ static int convert_fxsr_from_user( struc
 
 	if ( __copy_from_user( env, buf, 7 * sizeof(long) ) )
 		return 1;
+	if (copy_from_user(tmp, buf->_st, sizeof(struct _fpreg [8])))
+		return 1;
 
 	fxsave->cwd = (unsigned short)(env[0] & 0xffff);
 	fxsave->swd = (unsigned short)(env[1] & 0xffff);
@@ -269,15 +274,14 @@ static int convert_fxsr_from_user( struc
 	fxsave->fos = env[6];
 
 	to = (struct _fpxreg *) &fxsave->st_space[0];
-	from = &buf->_st[0];
+	from = tmp;
 	for ( i = 0 ; i < 8 ; i++, to++, from++ ) {
 		unsigned long *t = (unsigned long *)to;
 		unsigned long *f = (unsigned long *)from;
 
-		if (__get_user(*t, f) ||
-				__get_user(*(t + 1), f + 1) ||
-				__get_user(to->exponent, &from->exponent))
-			return 1;
+		*t = *f;
+		*(t + 1) = *(f + 1);
+		to->exponent = from->exponent;
 	}
 	return 0;
 }
--- diff/arch/i386/kernel/i8259.c	2004-01-19 10:22:55.000000000 +0000
+++ source/arch/i386/kernel/i8259.c	2004-02-23 13:56:37.000000000 +0000
@@ -258,7 +258,7 @@ static int __init i8259A_init_sysfs(void
 {
 	int error = sysdev_class_register(&i8259_sysdev_class);
 	if (!error)
-		error = sys_device_register(&device_i8259A);
+		error = sysdev_register(&device_i8259A);
 	return error;
 }
 
@@ -401,7 +401,7 @@ static int __init init_timer_sysfs(void)
 {
 	int error = sysdev_class_register(&timer_sysclass);
 	if (!error)
-		error = sys_device_register(&device_timer);
+		error = sysdev_register(&device_timer);
 	return error;
 }
 
--- diff/arch/i386/kernel/init_task.c	2003-10-09 09:47:33.000000000 +0100
+++ source/arch/i386/kernel/init_task.c	2004-02-23 13:56:37.000000000 +0000
@@ -26,7 +26,7 @@ EXPORT_SYMBOL(init_mm);
  */
 union thread_union init_thread_union 
 	__attribute__((__section__(".data.init_task"))) =
-		{ INIT_THREAD_INFO(init_task) };
+		{ INIT_THREAD_INFO(init_task, init_thread_union) };
 
 /*
  * Initial task structure.
@@ -44,5 +44,5 @@ EXPORT_SYMBOL(init_task);
  * section. Since TSS's are completely CPU-local, we want them
  * on exact cacheline boundaries, to eliminate cacheline ping-pong.
  */ 
-struct tss_struct init_tss[NR_CPUS] __cacheline_aligned = { [0 ... NR_CPUS-1] = INIT_TSS };
+struct tss_struct init_tss[NR_CPUS] __attribute__((__section__(".data.tss"))) = { [0 ... NR_CPUS-1] = INIT_TSS };
 
--- diff/arch/i386/kernel/io_apic.c	2004-02-09 10:36:07.000000000 +0000
+++ source/arch/i386/kernel/io_apic.c	2004-02-23 13:56:37.000000000 +0000
@@ -280,7 +280,7 @@ static void set_ioapic_affinity_irq(unsi
 	spin_unlock_irqrestore(&ioapic_lock, flags);
 }
 
-#if defined(CONFIG_SMP)
+#if defined(CONFIG_IRQBALANCE)
 # include <asm/processor.h>	/* kernel_thread() */
 # include <linux/kernel_stat.h>	/* kstat */
 # include <linux/slab.h>		/* kmalloc() */
@@ -317,8 +317,7 @@ struct irq_cpu_info {
 
 #define IRQ_ALLOWED(cpu, allowed_mask)	cpu_isset(cpu, allowed_mask)
 
-#define CPU_TO_PACKAGEINDEX(i) \
-		((physical_balance && i > cpu_sibling_map[i]) ? cpu_sibling_map[i] : i)
+#define CPU_TO_PACKAGEINDEX(i) (first_cpu(cpu_sibling_map[i]))
 
 #define MAX_BALANCED_IRQ_INTERVAL	(5*HZ)
 #define MIN_BALANCED_IRQ_INTERVAL	(HZ/2)
@@ -401,6 +400,7 @@ static void do_irq_balance(void)
 	unsigned long max_cpu_irq = 0, min_cpu_irq = (~0);
 	unsigned long move_this_load = 0;
 	int max_loaded = 0, min_loaded = 0;
+	int load;
 	unsigned long useful_load_threshold = balanced_irq_interval + 10;
 	int selected_irq;
 	int tmp_loaded, first_attempt = 1;
@@ -452,7 +452,7 @@ static void do_irq_balance(void)
 	for (i = 0; i < NR_CPUS; i++) {
 		if (!cpu_online(i))
 			continue;
-		if (physical_balance && i > cpu_sibling_map[i])
+		if (i != CPU_TO_PACKAGEINDEX(i))
 			continue;
 		if (min_cpu_irq > CPU_IRQ(i)) {
 			min_cpu_irq = CPU_IRQ(i);
@@ -471,7 +471,7 @@ tryanothercpu:
 	for (i = 0; i < NR_CPUS; i++) {
 		if (!cpu_online(i))
 			continue;
-		if (physical_balance && i > cpu_sibling_map[i])
+		if (i != CPU_TO_PACKAGEINDEX(i))
 			continue;
 		if (max_cpu_irq <= CPU_IRQ(i)) 
 			continue;
@@ -551,9 +551,14 @@ tryanotherirq:
 	 * We seek the least loaded sibling by making the comparison
 	 * (A+B)/2 vs B
 	 */
-	if (physical_balance && (CPU_IRQ(min_loaded) >> 1) >
-					CPU_IRQ(cpu_sibling_map[min_loaded]))
-		min_loaded = cpu_sibling_map[min_loaded];
+	load = CPU_IRQ(min_loaded) >> 1;
+	for_each_cpu_mask(j, cpu_sibling_map[min_loaded]) {
+		if (load > CPU_IRQ(j)) {
+			/* This won't change cpu_sibling_map[min_loaded] */
+			load = CPU_IRQ(j);
+			min_loaded = j;
+		}
+	}
 
 	cpus_and(allowed_mask, cpu_online_map, irq_affinity[selected_irq]);
 	target_cpu_mask = cpumask_of_cpu(min_loaded);
@@ -689,9 +694,11 @@ static inline void move_irq(int irq)
 
 __initcall(balanced_irq_init);
 
-#else /* !SMP */
+#else /* !CONFIG_IRQBALANCE */
 static inline void move_irq(int irq) { }
+#endif /* CONFIG_IRQBALANCE */
 
+#ifndef CONFIG_SMP
 void send_IPI_self(int vector)
 {
 	unsigned int cfg;
@@ -706,7 +713,7 @@ void send_IPI_self(int vector)
 	 */
 	apic_write_around(APIC_ICR, cfg);
 }
-#endif /* defined(CONFIG_SMP) */
+#endif /* !CONFIG_SMP */
 
 
 /*
@@ -2150,6 +2157,10 @@ static inline void check_timer(void)
 {
 	int pin1, pin2;
 	int vector;
+	unsigned int ver;
+
+	ver = apic_read(APIC_LVR);
+	ver = GET_APIC_VERSION(ver);
 
 	/*
 	 * get/set the timer IRQ vector:
@@ -2163,11 +2174,17 @@ static inline void check_timer(void)
 	 * mode for the 8259A whenever interrupts are routed
 	 * through I/O APICs.  Also IRQ0 has to be enabled in
 	 * the 8259A which implies the virtual wire has to be
-	 * disabled in the local APIC.
+	 * disabled in the local APIC.  Finally timer interrupts
+	 * need to be acknowledged manually in the 8259A for
+	 * do_slow_timeoffset() and for the i82489DX when using
+	 * the NMI watchdog.
 	 */
 	apic_write_around(APIC_LVT0, APIC_LVT_MASKED | APIC_DM_EXTINT);
 	init_8259A(1);
-	timer_ack = 1;
+	if (nmi_watchdog == NMI_IO_APIC && !APIC_INTEGRATED(ver))
+		timer_ack = 1;
+	else
+		timer_ack = !cpu_has_tsc;
 	enable_8259A_irq(0);
 
 	pin1 = find_isa_irq_pin(0, mp_INT);
@@ -2185,7 +2202,8 @@ static inline void check_timer(void)
 				disable_8259A_irq(0);
 				setup_nmi();
 				enable_8259A_irq(0);
-				check_nmi_watchdog();
+				if (check_nmi_watchdog() < 0);
+					timer_ack = !cpu_has_tsc;
 			}
 			return;
 		}
@@ -2208,7 +2226,8 @@ static inline void check_timer(void)
 				add_pin_to_irq(0, 0, pin2);
 			if (nmi_watchdog == NMI_IO_APIC) {
 				setup_nmi();
-				check_nmi_watchdog();
+				if (check_nmi_watchdog() < 0);
+					timer_ack = !cpu_has_tsc;
 			}
 			return;
 		}
--- diff/arch/i386/kernel/irq.c	2004-01-19 10:22:55.000000000 +0000
+++ source/arch/i386/kernel/irq.c	2004-02-23 13:56:37.000000000 +0000
@@ -435,7 +435,7 @@ asmlinkage unsigned int do_IRQ(struct pt
 		long esp;
 
 		__asm__ __volatile__("andl %%esp,%0" :
-					"=r" (esp) : "0" (8191));
+					"=r" (esp) : "0" (THREAD_SIZE - 1));
 		if (unlikely(esp < (sizeof(struct thread_info) + 1024))) {
 			printk("do_IRQ: stack overflow: %ld\n",
 				esp - sizeof(struct thread_info));
@@ -508,6 +508,8 @@ out:
 
 	irq_exit();
 
+	kgdb_process_breakpoint();
+
 	return 1;
 }
 
@@ -927,7 +929,7 @@ cpumask_t irq_affinity[NR_IRQS] = { [0 .
 static int irq_affinity_read_proc(char *page, char **start, off_t off,
 			int count, int *eof, void *data)
 {
-	int len = cpumask_snprintf(page, count, irq_affinity[(long)data]);
+	int len = cpumask_scnprintf(page, count, irq_affinity[(long)data]);
 	if (count - len < 2)
 		return -EINVAL;
 	len += sprintf(page + len, "\n");
@@ -968,7 +970,7 @@ static int irq_affinity_write_proc(struc
 static int prof_cpu_mask_read_proc (char *page, char **start, off_t off,
 			int count, int *eof, void *data)
 {
-	int len = cpumask_snprintf(page, count, *(cpumask_t *)data);
+	int len = cpumask_scnprintf(page, count, *(cpumask_t *)data);
 	if (count - len < 2)
 		return -EINVAL;
 	len += sprintf(page + len, "\n");
--- diff/arch/i386/kernel/ldt.c	2003-10-09 09:47:16.000000000 +0100
+++ source/arch/i386/kernel/ldt.c	2004-02-23 13:56:37.000000000 +0000
@@ -2,7 +2,7 @@
  * linux/kernel/ldt.c
  *
  * Copyright (C) 1992 Krishna Balasubramanian and Linus Torvalds
- * Copyright (C) 1999 Ingo Molnar <mingo@redhat.com>
+ * Copyright (C) 1999, 2003 Ingo Molnar <mingo@redhat.com>
  */
 
 #include <linux/errno.h>
@@ -18,6 +18,8 @@
 #include <asm/system.h>
 #include <asm/ldt.h>
 #include <asm/desc.h>
+#include <linux/highmem.h>
+#include <asm/atomic_kmap.h>
 
 #ifdef CONFIG_SMP /* avoids "defined but not used" warnig */
 static void flush_ldt(void *null)
@@ -29,34 +31,31 @@ static void flush_ldt(void *null)
 
 static int alloc_ldt(mm_context_t *pc, int mincount, int reload)
 {
-	void *oldldt;
-	void *newldt;
-	int oldsize;
+	int oldsize, newsize, i;
 
 	if (mincount <= pc->size)
 		return 0;
+	/*
+	 * LDT got larger - reallocate if necessary.
+	 */
 	oldsize = pc->size;
 	mincount = (mincount+511)&(~511);
-	if (mincount*LDT_ENTRY_SIZE > PAGE_SIZE)
-		newldt = vmalloc(mincount*LDT_ENTRY_SIZE);
-	else
-		newldt = kmalloc(mincount*LDT_ENTRY_SIZE, GFP_KERNEL);
-
-	if (!newldt)
-		return -ENOMEM;
-
-	if (oldsize)
-		memcpy(newldt, pc->ldt, oldsize*LDT_ENTRY_SIZE);
-	oldldt = pc->ldt;
-	memset(newldt+oldsize*LDT_ENTRY_SIZE, 0, (mincount-oldsize)*LDT_ENTRY_SIZE);
-	pc->ldt = newldt;
-	wmb();
+	newsize = mincount*LDT_ENTRY_SIZE;
+	for (i = 0; i < newsize; i += PAGE_SIZE) {
+		int nr = i/PAGE_SIZE;
+		BUG_ON(i >= 64*1024);
+		if (!pc->ldt_pages[nr]) {
+			pc->ldt_pages[nr] = alloc_page(GFP_HIGHUSER);
+			if (!pc->ldt_pages[nr])
+				return -ENOMEM;
+			clear_highpage(pc->ldt_pages[nr]);
+		}
+	}
 	pc->size = mincount;
-	wmb();
-
 	if (reload) {
 #ifdef CONFIG_SMP
 		cpumask_t mask;
+
 		preempt_disable();
 		load_LDT(pc);
 		mask = cpumask_of_cpu(smp_processor_id());
@@ -67,21 +66,20 @@ static int alloc_ldt(mm_context_t *pc, i
 		load_LDT(pc);
 #endif
 	}
-	if (oldsize) {
-		if (oldsize*LDT_ENTRY_SIZE > PAGE_SIZE)
-			vfree(oldldt);
-		else
-			kfree(oldldt);
-	}
 	return 0;
 }
 
 static inline int copy_ldt(mm_context_t *new, mm_context_t *old)
 {
-	int err = alloc_ldt(new, old->size, 0);
-	if (err < 0)
+	int i, err, size = old->size, nr_pages = (size*LDT_ENTRY_SIZE + PAGE_SIZE-1)/PAGE_SIZE;
+
+	err = alloc_ldt(new, size, 0);
+	if (err < 0) {
+		new->size = 0;
 		return err;
-	memcpy(new->ldt, old->ldt, old->size*LDT_ENTRY_SIZE);
+	}
+	for (i = 0; i < nr_pages; i++)
+		copy_user_highpage(new->ldt_pages[i], old->ldt_pages[i], 0);
 	return 0;
 }
 
@@ -96,6 +94,7 @@ int init_new_context(struct task_struct 
 
 	init_MUTEX(&mm->context.sem);
 	mm->context.size = 0;
+	memset(mm->context.ldt_pages, 0, sizeof(struct page *) * MAX_LDT_PAGES);
 	old_mm = current->mm;
 	if (old_mm && old_mm->context.size > 0) {
 		down(&old_mm->context.sem);
@@ -107,23 +106,21 @@ int init_new_context(struct task_struct 
 
 /*
  * No need to lock the MM as we are the last user
+ * Do not touch the ldt register, we are already
+ * in the next thread.
  */
 void destroy_context(struct mm_struct *mm)
 {
-	if (mm->context.size) {
-		if (mm == current->active_mm)
-			clear_LDT();
-		if (mm->context.size*LDT_ENTRY_SIZE > PAGE_SIZE)
-			vfree(mm->context.ldt);
-		else
-			kfree(mm->context.ldt);
-		mm->context.size = 0;
-	}
+	int i, nr_pages = (mm->context.size*LDT_ENTRY_SIZE + PAGE_SIZE-1) / PAGE_SIZE;
+
+	for (i = 0; i < nr_pages; i++)
+		__free_page(mm->context.ldt_pages[i]);
+	mm->context.size = 0;
 }
 
 static int read_ldt(void __user * ptr, unsigned long bytecount)
 {
-	int err;
+	int err, i;
 	unsigned long size;
 	struct mm_struct * mm = current->mm;
 
@@ -138,8 +135,25 @@ static int read_ldt(void __user * ptr, u
 		size = bytecount;
 
 	err = 0;
-	if (copy_to_user(ptr, mm->context.ldt, size))
-		err = -EFAULT;
+	/*
+	 * This is necessary just in case we got here straight from a
+	 * context-switch where the ptes were set but no tlb flush
+	 * was done yet. We rather avoid doing a TLB flush in the
+	 * context-switch path and do it here instead.
+	 */
+	__flush_tlb_global();
+
+	for (i = 0; i < size; i += PAGE_SIZE) {
+		int nr = i / PAGE_SIZE, bytes;
+		char *kaddr = kmap(mm->context.ldt_pages[nr]);
+
+		bytes = size - i;
+		if (bytes > PAGE_SIZE)
+			bytes = PAGE_SIZE;
+		if (copy_to_user(ptr + i, kaddr, size - i))
+			err = -EFAULT;
+		kunmap(mm->context.ldt_pages[nr]);
+	}
 	up(&mm->context.sem);
 	if (err < 0)
 		return err;
@@ -158,7 +172,7 @@ static int read_default_ldt(void __user 
 
 	err = 0;
 	address = &default_ldt[0];
-	size = 5*sizeof(struct desc_struct);
+	size = 5*LDT_ENTRY_SIZE;
 	if (size > bytecount)
 		size = bytecount;
 
@@ -200,7 +214,15 @@ static int write_ldt(void __user * ptr, 
 			goto out_unlock;
 	}
 
-	lp = (__u32 *) ((ldt_info.entry_number << 3) + (char *) mm->context.ldt);
+	/*
+	 * No rescheduling allowed from this point to the install.
+	 *
+	 * We do a TLB flush for the same reason as in the read_ldt() path.
+	 */
+	preempt_disable();
+	__flush_tlb_global();
+	lp = (__u32 *) ((ldt_info.entry_number << 3) +
+			(char *) __kmap_atomic_vaddr(KM_LDT_PAGE0));
 
    	/* Allow LDTs to be cleared by the user. */
    	if (ldt_info.base_addr == 0 && ldt_info.limit == 0) {
@@ -221,6 +243,7 @@ install:
 	*lp	= entry_1;
 	*(lp+1)	= entry_2;
 	error = 0;
+	preempt_enable();
 
 out_unlock:
 	up(&mm->context.sem);
@@ -248,3 +271,26 @@ asmlinkage int sys_modify_ldt(int func, 
 	}
 	return ret;
 }
+
+/*
+ * load one particular LDT into the current CPU
+ */
+void load_LDT_nolock(mm_context_t *pc, int cpu)
+{
+	struct page **pages = pc->ldt_pages;
+	int count = pc->size;
+	int nr_pages, i;
+
+	if (likely(!count)) {
+		pages = &default_ldt_page;
+		count = 5;
+	}
+       	nr_pages = (count*LDT_ENTRY_SIZE + PAGE_SIZE-1) / PAGE_SIZE;
+
+	for (i = 0; i < nr_pages; i++) {
+		__kunmap_atomic_type(KM_LDT_PAGE0 - i);
+		__kmap_atomic(pages[i], KM_LDT_PAGE0 - i);
+	}
+	set_ldt_desc(cpu, (void *)__kmap_atomic_vaddr(KM_LDT_PAGE0), count);
+	load_LDT_desc();
+}
--- diff/arch/i386/kernel/microcode.c	2003-10-27 09:20:43.000000000 +0000
+++ source/arch/i386/kernel/microcode.c	2004-02-23 13:56:37.000000000 +0000
@@ -371,7 +371,9 @@ static void do_update_one (void * unused
 	spin_lock_irqsave(&microcode_update_lock, flags);          
 
 	/* write microcode via MSR 0x79 */
-	wrmsr(MSR_IA32_UCODE_WRITE, (unsigned int)(uci->mc->bits), 0);
+	wrmsr(MSR_IA32_UCODE_WRITE,
+		(unsigned long) uci->mc->bits, 
+		(unsigned long) uci->mc->bits >> 16 >> 16);
 	wrmsr(MSR_IA32_UCODE_REV, 0, 0);
 
 	__asm__ __volatile__ ("cpuid" : : : "ax", "bx", "cx", "dx");
@@ -507,3 +509,4 @@ static void __exit microcode_exit (void)
 
 module_init(microcode_init)
 module_exit(microcode_exit)
+MODULE_ALIAS_MISCDEV(MICROCODE_MINOR);
--- diff/arch/i386/kernel/mpparse.c	2004-02-18 08:54:07.000000000 +0000
+++ source/arch/i386/kernel/mpparse.c	2004-02-23 13:56:37.000000000 +0000
@@ -668,7 +668,7 @@ void __init get_smp_config (void)
 		 * Read the physical hardware table.  Anything here will
 		 * override the defaults.
 		 */
-		if (!smp_read_mpc((void *)mpf->mpf_physptr)) {
+		if (!smp_read_mpc((void *)phys_to_virt(mpf->mpf_physptr))) {
 			smp_found_config = 0;
 			printk(KERN_ERR "BIOS bug, MP table errors detected!...\n");
 			printk(KERN_ERR "... disabling SMP support. (tell your hw vendor)\n");
--- diff/arch/i386/kernel/nmi.c	2003-10-09 09:47:16.000000000 +0100
+++ source/arch/i386/kernel/nmi.c	2004-02-23 13:56:37.000000000 +0000
@@ -31,7 +31,16 @@
 #include <asm/mpspec.h>
 #include <asm/nmi.h>
 
+#ifdef CONFIG_KGDB
+#include <asm/kgdb.h>
+#ifdef CONFIG_SMP
+unsigned int nmi_watchdog = NMI_IO_APIC;
+#else
+unsigned int nmi_watchdog = NMI_LOCAL_APIC;
+#endif
+#else
 unsigned int nmi_watchdog = NMI_NONE;
+#endif
 static unsigned int nmi_hz = HZ;
 unsigned int nmi_perfctr_msr;	/* the MSR to reset in NMI handler */
 extern void show_registers(struct pt_regs *regs);
@@ -42,7 +51,7 @@ extern void show_registers(struct pt_reg
  *     be enabled
  * -1: the lapic NMI watchdog is disabled, but can be enabled
  */
-static int nmi_active;
+int nmi_active;
 
 #define K7_EVNTSEL_ENABLE	(1 << 22)
 #define K7_EVNTSEL_INT		(1 << 20)
@@ -248,7 +257,7 @@ static int __init init_lapic_nmi_sysfs(v
 
 	error = sysdev_class_register(&nmi_sysclass);
 	if (!error)
-		error = sys_device_register(&device_lapic_nmi);
+		error = sysdev_register(&device_lapic_nmi);
 	return error;
 }
 /* must come after the local APIC's device_initcall() */
@@ -408,6 +417,9 @@ void touch_nmi_watchdog (void)
 	for (i = 0; i < NR_CPUS; i++)
 		alert_counter[i] = 0;
 }
+#ifdef CONFIG_KGDB
+int tune_watchdog = 5*HZ;
+#endif
 
 void nmi_watchdog_tick (struct pt_regs * regs)
 {
@@ -421,12 +433,24 @@ void nmi_watchdog_tick (struct pt_regs *
 
 	sum = irq_stat[cpu].apic_timer_irqs;
 
+#ifdef CONFIG_KGDB
+ 	if (! in_kgdb(regs) && last_irq_sums[cpu] == sum ) {
+
+#else
 	if (last_irq_sums[cpu] == sum) {
+#endif
 		/*
 		 * Ayiee, looks like this CPU is stuck ...
 		 * wait a few IRQs (5 seconds) before doing the oops ...
 		 */
 		alert_counter[cpu]++;
+#ifdef CONFIG_KGDB
+                if (alert_counter[cpu] == tune_watchdog) {
+                        kgdb_handle_exception(2, SIGPWR, 0, regs);
+                        last_irq_sums[cpu] = sum;
+                        alert_counter[cpu] = 0;
+                }
+#endif
 		if (alert_counter[cpu] == 5*nmi_hz) {
 			spin_lock(&nmi_print_lock);
 			/*
@@ -462,6 +486,7 @@ void nmi_watchdog_tick (struct pt_regs *
 	}
 }
 
+EXPORT_SYMBOL(nmi_active);
 EXPORT_SYMBOL(nmi_watchdog);
 EXPORT_SYMBOL(disable_lapic_nmi_watchdog);
 EXPORT_SYMBOL(enable_lapic_nmi_watchdog);
--- diff/arch/i386/kernel/process.c	2004-02-18 08:54:07.000000000 +0000
+++ source/arch/i386/kernel/process.c	2004-02-23 13:56:37.000000000 +0000
@@ -47,6 +47,7 @@
 #include <asm/i387.h>
 #include <asm/irq.h>
 #include <asm/desc.h>
+#include <asm/atomic_kmap.h>
 #ifdef CONFIG_MATH_EMULATION
 #include <asm/math_emu.h>
 #endif
@@ -304,6 +305,9 @@ void flush_thread(void)
 	struct task_struct *tsk = current;
 
 	memset(tsk->thread.debugreg, 0, sizeof(unsigned long)*8);
+#ifdef CONFIG_X86_HIGH_ENTRY
+	clear_thread_flag(TIF_DB7);
+#endif
 	memset(tsk->thread.tls_array, 0, sizeof(tsk->thread.tls_array));	
 	/*
 	 * Forget coprocessor state..
@@ -317,9 +321,8 @@ void release_thread(struct task_struct *
 	if (dead_task->mm) {
 		// temporary debugging check
 		if (dead_task->mm->context.size) {
-			printk("WARNING: dead process %8s still has LDT? <%p/%d>\n",
+			printk("WARNING: dead process %8s still has LDT? <%d>\n",
 					dead_task->comm,
-					dead_task->mm->context.ldt,
 					dead_task->mm->context.size);
 			BUG();
 		}
@@ -354,7 +357,17 @@ int copy_thread(int nr, unsigned long cl
 	p->thread.esp = (unsigned long) childregs;
 	p->thread.esp0 = (unsigned long) (childregs+1);
 
+	/*
+	 * get the two stack pages, for the virtual stack.
+	 *
+	 * IMPORTANT: this code relies on the fact that the task
+	 * structure is an 8K aligned piece of physical memory.
+	 */
+	p->thread.stack_page0 = virt_to_page((unsigned long)p->thread_info);
+	p->thread.stack_page1 = virt_to_page((unsigned long)p->thread_info + PAGE_SIZE);
+
 	p->thread.eip = (unsigned long) ret_from_fork;
+	p->thread_info->real_stack = p->thread_info;
 
 	savesegment(fs,p->thread.fs);
 	savesegment(gs,p->thread.gs);
@@ -506,10 +519,41 @@ struct task_struct * __switch_to(struct 
 
 	__unlazy_fpu(prev_p);
 
+#ifdef CONFIG_X86_HIGH_ENTRY
+	/*
+	 * Set the ptes of the virtual stack. (NOTE: a one-page TLB flush is
+	 * needed because otherwise NMIs could interrupt the
+	 * user-return code with a virtual stack and stale TLBs.)
+	 */
+	__kunmap_atomic_type(KM_VSTACK0);
+	__kunmap_atomic_type(KM_VSTACK1);
+	__kmap_atomic(next->stack_page0, KM_VSTACK0);
+	__kmap_atomic(next->stack_page1, KM_VSTACK1);
+
+	/*
+	 * NOTE: here we rely on the task being the stack as well
+	 */
+	next_p->thread_info->virtual_stack =
+			(void *)__kmap_atomic_vaddr(KM_VSTACK0);
+
+#if defined(CONFIG_PREEMPT) && defined(CONFIG_SMP)
+	/*
+	 * If next was preempted on entry from userspace to kernel,
+	 * and now it's on a different cpu, we need to adjust %esp.
+	 * This assumes that entry.S does not copy %esp while on the
+	 * virtual stack (with interrupts enabled): which is so,
+	 * except within __SWITCH_KERNELSPACE itself.
+	 */
+	if (unlikely(next->esp >= TASK_SIZE)) {
+		next->esp &= THREAD_SIZE - 1;
+		next->esp |= (unsigned long) next_p->thread_info->virtual_stack;
+	}
+#endif
+#endif
 	/*
 	 * Reload esp0, LDT and the page table pointer:
 	 */
-	load_esp0(tss, next);
+	load_virtual_esp0(tss, next_p);
 
 	/*
 	 * Load the per-thread Thread-Local Storage descriptor.
@@ -637,6 +681,8 @@ extern void scheduling_functions_start_h
 extern void scheduling_functions_end_here(void);
 #define first_sched	((unsigned long) scheduling_functions_start_here)
 #define last_sched	((unsigned long) scheduling_functions_end_here)
+#define top_esp                (THREAD_SIZE - sizeof(unsigned long))
+#define top_ebp                (THREAD_SIZE - 2*sizeof(unsigned long))
 
 unsigned long get_wchan(struct task_struct *p)
 {
@@ -647,12 +693,12 @@ unsigned long get_wchan(struct task_stru
 		return 0;
 	stack_page = (unsigned long)p->thread_info;
 	esp = p->thread.esp;
-	if (!stack_page || esp < stack_page || esp > 8188+stack_page)
+	if (!stack_page || esp < stack_page || esp > top_esp+stack_page)
 		return 0;
 	/* include/asm-i386/system.h:switch_to() pushes ebp last. */
 	ebp = *(unsigned long *) esp;
 	do {
-		if (ebp < stack_page || ebp > 8184+stack_page)
+		if (ebp < stack_page || ebp > top_ebp+stack_page)
 			return 0;
 		eip = *(unsigned long *) (ebp+4);
 		if (eip < first_sched || eip >= last_sched)
--- diff/arch/i386/kernel/reboot.c	2004-01-19 10:22:55.000000000 +0000
+++ source/arch/i386/kernel/reboot.c	2004-02-23 13:56:37.000000000 +0000
@@ -155,12 +155,11 @@ void machine_real_restart(unsigned char 
 	CMOS_WRITE(0x00, 0x8f);
 	spin_unlock_irqrestore(&rtc_lock, flags);
 
-	/* Remap the kernel at virtual address zero, as well as offset zero
-	   from the kernel segment.  This assumes the kernel segment starts at
-	   virtual address PAGE_OFFSET. */
-
-	memcpy (swapper_pg_dir, swapper_pg_dir + USER_PGD_PTRS,
-		sizeof (swapper_pg_dir [0]) * KERNEL_PGD_PTRS);
+	/*
+	 * Remap the first 16 MB of RAM (which includes the kernel image)
+	 * at virtual address zero:
+	 */
+	setup_identity_mappings(swapper_pg_dir, 0, 16*1024*1024);
 
 	/*
 	 * Use `swapper_pg_dir' as our page directory.
--- diff/arch/i386/kernel/setup.c	2004-02-18 08:54:07.000000000 +0000
+++ source/arch/i386/kernel/setup.c	2004-02-23 13:56:37.000000000 +0000
@@ -1118,6 +1118,19 @@ void __init setup_arch(char **cmdline_p)
 #endif
 	paging_init();
 
+#ifdef CONFIG_EARLY_PRINTK
+	{
+		char *s = strstr(*cmdline_p, "earlyprintk=");
+		if (s) {
+			extern void setup_early_printk(char *);
+
+			setup_early_printk(s);
+			printk("early console enabled\n");
+		}
+	}
+#endif
+
+
 	dmi_scan_machine();
 
 #ifdef CONFIG_X86_GENERICARCH
--- diff/arch/i386/kernel/signal.c	2003-11-25 15:24:57.000000000 +0000
+++ source/arch/i386/kernel/signal.c	2004-02-23 13:56:37.000000000 +0000
@@ -128,28 +128,29 @@ sys_sigaltstack(const stack_t __user *us
  */
 
 static int
-restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc, int *peax)
+restore_sigcontext(struct pt_regs *regs,
+		struct sigcontext __user *__sc, int *peax)
 {
-	unsigned int err = 0;
+	struct sigcontext scratch; /* 88 bytes of scratch area */
 
 	/* Always make any pending restarted system calls return -EINTR */
 	current_thread_info()->restart_block.fn = do_no_restart_syscall;
 
-#define COPY(x)		err |= __get_user(regs->x, &sc->x)
+	if (copy_from_user(&scratch, __sc, sizeof(scratch)))
+		return -EFAULT;
+
+#define COPY(x)		regs->x = scratch.x
 
 #define COPY_SEG(seg)							\
-	{ unsigned short tmp;						\
-	  err |= __get_user(tmp, &sc->seg);				\
+	{ unsigned short tmp = scratch.seg;				\
 	  regs->x##seg = tmp; }
 
 #define COPY_SEG_STRICT(seg)						\
-	{ unsigned short tmp;						\
-	  err |= __get_user(tmp, &sc->seg);				\
+	{ unsigned short tmp = scratch.seg;				\
 	  regs->x##seg = tmp|3; }
 
 #define GET_SEG(seg)							\
-	{ unsigned short tmp;						\
-	  err |= __get_user(tmp, &sc->seg);				\
+	{ unsigned short tmp = scratch.seg;				\
 	  loadsegment(seg,tmp); }
 
 	GET_SEG(gs);
@@ -168,27 +169,23 @@ restore_sigcontext(struct pt_regs *regs,
 	COPY_SEG_STRICT(ss);
 	
 	{
-		unsigned int tmpflags;
-		err |= __get_user(tmpflags, &sc->eflags);
+		unsigned int tmpflags = scratch.eflags;
 		regs->eflags = (regs->eflags & ~0x40DD5) | (tmpflags & 0x40DD5);
 		regs->orig_eax = -1;		/* disable syscall checks */
 	}
 
 	{
-		struct _fpstate __user * buf;
-		err |= __get_user(buf, &sc->fpstate);
+		struct _fpstate * buf = scratch.fpstate;
 		if (buf) {
 			if (verify_area(VERIFY_READ, buf, sizeof(*buf)))
-				goto badframe;
-			err |= restore_i387(buf);
+				return -EFAULT;
+			if (restore_i387(buf))
+				return -EFAULT;
 		}
 	}
 
-	err |= __get_user(*peax, &sc->eax);
-	return err;
-
-badframe:
-	return 1;
+	*peax = scratch.eax;
+	return 0;
 }
 
 asmlinkage int sys_sigreturn(unsigned long __unused)
@@ -266,46 +263,47 @@ badframe:
  */
 
 static int
-setup_sigcontext(struct sigcontext __user *sc, struct _fpstate __user *fpstate,
+setup_sigcontext(struct sigcontext __user *__sc, struct _fpstate __user *fpstate,
 		 struct pt_regs *regs, unsigned long mask)
 {
-	int tmp, err = 0;
+	struct sigcontext sc; /* 88 bytes of scratch area */
+	int tmp;
 
 	tmp = 0;
 	__asm__("movl %%gs,%0" : "=r"(tmp): "0"(tmp));
-	err |= __put_user(tmp, (unsigned int *)&sc->gs);
+	*(unsigned int *)&sc.gs = tmp;
 	__asm__("movl %%fs,%0" : "=r"(tmp): "0"(tmp));
-	err |= __put_user(tmp, (unsigned int *)&sc->fs);
-
-	err |= __put_user(regs->xes, (unsigned int *)&sc->es);
-	err |= __put_user(regs->xds, (unsigned int *)&sc->ds);
-	err |= __put_user(regs->edi, &sc->edi);
-	err |= __put_user(regs->esi, &sc->esi);
-	err |= __put_user(regs->ebp, &sc->ebp);
-	err |= __put_user(regs->esp, &sc->esp);
-	err |= __put_user(regs->ebx, &sc->ebx);
-	err |= __put_user(regs->edx, &sc->edx);
-	err |= __put_user(regs->ecx, &sc->ecx);
-	err |= __put_user(regs->eax, &sc->eax);
-	err |= __put_user(current->thread.trap_no, &sc->trapno);
-	err |= __put_user(current->thread.error_code, &sc->err);
-	err |= __put_user(regs->eip, &sc->eip);
-	err |= __put_user(regs->xcs, (unsigned int *)&sc->cs);
-	err |= __put_user(regs->eflags, &sc->eflags);
-	err |= __put_user(regs->esp, &sc->esp_at_signal);
-	err |= __put_user(regs->xss, (unsigned int *)&sc->ss);
+	*(unsigned int *)&sc.fs = tmp;
+	*(unsigned int *)&sc.es = regs->xes;
+	*(unsigned int *)&sc.ds = regs->xds;
+	sc.edi = regs->edi;
+	sc.esi = regs->esi;
+	sc.ebp = regs->ebp;
+	sc.esp = regs->esp;
+	sc.ebx = regs->ebx;
+	sc.edx = regs->edx;
+	sc.ecx = regs->ecx;
+	sc.eax = regs->eax;
+	sc.trapno = current->thread.trap_no;
+	sc.err = current->thread.error_code;
+	sc.eip = regs->eip;
+	*(unsigned int *)&sc.cs = regs->xcs;
+	sc.eflags = regs->eflags;
+	sc.esp_at_signal = regs->esp;
+	*(unsigned int *)&sc.ss = regs->xss;
 
 	tmp = save_i387(fpstate);
 	if (tmp < 0)
-	  err = 1;
-	else
-	  err |= __put_user(tmp ? fpstate : NULL, &sc->fpstate);
+		return 1;
+	sc.fpstate = tmp ? fpstate : NULL;
 
 	/* non-iBCS2 extensions.. */
-	err |= __put_user(mask, &sc->oldmask);
-	err |= __put_user(current->thread.cr2, &sc->cr2);
+	sc.oldmask = mask;
+	sc.cr2 = current->thread.cr2;
 
-	return err;
+	if (copy_to_user(__sc, &sc, sizeof(sc)))
+		return 1;
+	return 0;
 }
 
 /*
@@ -443,7 +441,7 @@ static void setup_rt_frame(int sig, stru
 	/* Create the ucontext.  */
 	err |= __put_user(0, &frame->uc.uc_flags);
 	err |= __put_user(0, &frame->uc.uc_link);
-	err |= __put_user(current->sas_ss_sp, &frame->uc.uc_stack.ss_sp);
+	err |= __put_user(current->sas_ss_sp, (unsigned long *)&frame->uc.uc_stack.ss_sp);
 	err |= __put_user(sas_ss_flags(regs->esp),
 			  &frame->uc.uc_stack.ss_flags);
 	err |= __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size);
--- diff/arch/i386/kernel/smp.c	2003-10-09 09:47:16.000000000 +0100
+++ source/arch/i386/kernel/smp.c	2004-02-23 13:56:37.000000000 +0000
@@ -327,10 +327,12 @@ asmlinkage void smp_invalidate_interrupt
 		 
 	if (flush_mm == cpu_tlbstate[cpu].active_mm) {
 		if (cpu_tlbstate[cpu].state == TLBSTATE_OK) {
+#ifndef CONFIG_X86_SWITCH_PAGETABLES
 			if (flush_va == FLUSH_ALL)
 				local_flush_tlb();
 			else
 				__flush_tlb_one(flush_va);
+#endif
 		} else
 			leave_mm(cpu);
 	}
@@ -396,21 +398,6 @@ static void flush_tlb_others(cpumask_t c
 	spin_unlock(&tlbstate_lock);
 }
 	
-void flush_tlb_current_task(void)
-{
-	struct mm_struct *mm = current->mm;
-	cpumask_t cpu_mask;
-
-	preempt_disable();
-	cpu_mask = mm->cpu_vm_mask;
-	cpu_clear(smp_processor_id(), cpu_mask);
-
-	local_flush_tlb();
-	if (!cpus_empty(cpu_mask))
-		flush_tlb_others(cpu_mask, mm, FLUSH_ALL);
-	preempt_enable();
-}
-
 void flush_tlb_mm (struct mm_struct * mm)
 {
 	cpumask_t cpu_mask;
@@ -442,7 +429,10 @@ void flush_tlb_page(struct vm_area_struc
 
 	if (current->active_mm == mm) {
 		if(current->mm)
-			__flush_tlb_one(va);
+#ifndef CONFIG_X86_SWITCH_PAGETABLES
+			__flush_tlb_one(va)
+#endif
+				;
 		 else
 		 	leave_mm(smp_processor_id());
 	}
@@ -466,7 +456,17 @@ void flush_tlb_all(void)
 {
 	on_each_cpu(do_flush_tlb_all, 0, 1, 1);
 }
-
+#ifdef CONFIG_KGDB
+/*
+ * By using the NMI code instead of a vector we just sneak thru the
+ * word generator coming out with just what we want.  AND it does
+ * not matter if clustered_apic_mode is set or not.
+ */
+void smp_send_nmi_allbutself(void)
+{
+	send_IPI_allbutself(APIC_DM_NMI);
+}
+#endif
 /*
  * this function sends a 'reschedule' IPI to another CPU.
  * it goes straight through and wastes no time serializing
--- diff/arch/i386/kernel/smpboot.c	2004-02-18 08:54:07.000000000 +0000
+++ source/arch/i386/kernel/smpboot.c	2004-02-23 13:56:37.000000000 +0000
@@ -39,6 +39,7 @@
 #include <linux/kernel.h>
 
 #include <linux/mm.h>
+#include <linux/sched.h>
 #include <linux/kernel_stat.h>
 #include <linux/smp_lock.h>
 #include <linux/irq.h>
@@ -934,7 +935,7 @@ static int boot_cpu_logical_apicid;
 /* Where the IO area was mapped on multiquad, always 0 otherwise */
 void *xquad_portio;
 
-int cpu_sibling_map[NR_CPUS] __cacheline_aligned;
+cpumask_t cpu_sibling_map[NR_CPUS] __cacheline_aligned;
 
 static void __init smp_boot_cpus(unsigned int max_cpus)
 {
@@ -948,10 +949,13 @@ static void __init smp_boot_cpus(unsigne
 	printk("CPU%d: ", 0);
 	print_cpu_info(&cpu_data[0]);
 
+	boot_cpu_physical_apicid = GET_APIC_ID(apic_read(APIC_ID));
 	boot_cpu_logical_apicid = logical_smp_processor_id();
 
 	current_thread_info()->cpu = 0;
 	smp_tune_scheduling();
+	cpus_clear(cpu_sibling_map[0]);
+	cpu_set(0, cpu_sibling_map[0]);
 
 	/*
 	 * If we couldn't find an SMP configuration at boot time,
@@ -1008,8 +1012,6 @@ static void __init smp_boot_cpus(unsigne
 	setup_local_APIC();
 	map_cpu_to_logical_apicid();
 
-	if (GET_APIC_ID(apic_read(APIC_ID)) != boot_cpu_physical_apicid)
-		BUG();
 
 	setup_portio_remap();
 
@@ -1080,32 +1082,34 @@ static void __init smp_boot_cpus(unsigne
 	Dprintk("Boot done.\n");
 
 	/*
-	 * If Hyper-Threading is avaialble, construct cpu_sibling_map[], so
-	 * that we can tell the sibling CPU efficiently.
+	 * construct cpu_sibling_map[], so that we can tell sibling CPUs
+	 * efficiently.
 	 */
-	if (cpu_has_ht && smp_num_siblings > 1) {
-		for (cpu = 0; cpu < NR_CPUS; cpu++)
-			cpu_sibling_map[cpu] = NO_PROC_ID;
-		
-		for (cpu = 0; cpu < NR_CPUS; cpu++) {
-			int 	i;
-			if (!cpu_isset(cpu, cpu_callout_map))
-				continue;
+	for (cpu = 0; cpu < NR_CPUS; cpu++)
+		cpus_clear(cpu_sibling_map[cpu]);
+
+	for (cpu = 0; cpu < NR_CPUS; cpu++) {
+		int siblings = 0;
+		int i;
+		if (!cpu_isset(cpu, cpu_callout_map))
+			continue;
 
+		if (smp_num_siblings > 1) {
 			for (i = 0; i < NR_CPUS; i++) {
-				if (i == cpu || !cpu_isset(i, cpu_callout_map))
+				if (!cpu_isset(i, cpu_callout_map))
 					continue;
 				if (phys_proc_id[cpu] == phys_proc_id[i]) {
-					cpu_sibling_map[cpu] = i;
-					printk("cpu_sibling_map[%d] = %d\n", cpu, cpu_sibling_map[cpu]);
-					break;
+					siblings++;
+					cpu_set(i, cpu_sibling_map[cpu]);
 				}
 			}
-			if (cpu_sibling_map[cpu] == NO_PROC_ID) {
-				smp_num_siblings = 1;
-				printk(KERN_WARNING "WARNING: No sibling found for CPU %d.\n", cpu);
-			}
+		} else {
+			siblings++;
+			cpu_set(cpu, cpu_sibling_map[cpu]);
 		}
+
+		if (siblings != smp_num_siblings)
+			printk(KERN_WARNING "WARNING: %d siblings found for CPU%d, should be %d\n", siblings, cpu, smp_num_siblings);
 	}
 
 	smpboot_setup_io_apic();
@@ -1119,6 +1123,216 @@ static void __init smp_boot_cpus(unsigne
 		synchronize_tsc_bp();
 }
 
+#ifdef CONFIG_SCHED_SMT
+#ifdef CONFIG_NUMA
+static struct sched_group sched_group_cpus[NR_CPUS];
+static struct sched_group sched_group_phys[NR_CPUS];
+static struct sched_group sched_group_nodes[MAX_NUMNODES];
+static DEFINE_PER_CPU(struct sched_domain, phys_domains);
+static DEFINE_PER_CPU(struct sched_domain, node_domains);
+__init void arch_init_sched_domains(void)
+{
+	int i;
+	struct sched_group *first_cpu = NULL, *last_cpu = NULL;
+
+	/* Set up domains */
+	for_each_cpu(i) {
+		struct sched_domain *cpu_domain = cpu_sched_domain(i);
+		struct sched_domain *phys_domain = &per_cpu(phys_domains, i);
+		struct sched_domain *node_domain = &per_cpu(node_domains, i);
+		int node = cpu_to_node(i);
+		cpumask_t nodemask = node_to_cpumask(node);
+
+		*cpu_domain = SD_SIBLING_INIT;
+		cpu_domain->span = cpu_sibling_map[i];
+
+		*phys_domain = SD_CPU_INIT;
+		phys_domain->span = nodemask;
+
+		*node_domain = SD_NODE_INIT;
+		node_domain->span = cpu_possible_map;
+	}
+
+	/* Set up CPU (sibling) groups */
+	for_each_cpu(i) {
+		struct sched_domain *cpu_domain = cpu_sched_domain(i);
+		int j;
+		first_cpu = last_cpu = NULL;
+
+		if (i != first_cpu(cpu_domain->span))
+			continue;
+
+		for_each_cpu_mask(j, cpu_domain->span) {
+			struct sched_group *cpu = &sched_group_cpus[j];
+
+			cpu->cpumask = CPU_MASK_NONE;
+			cpu_set(j, cpu->cpumask);
+			cpu->cpu_power = SCHED_LOAD_SCALE;
+
+			if (!first_cpu)
+				first_cpu = cpu;
+			if (last_cpu)
+				last_cpu->next = cpu;
+			last_cpu = cpu;
+		}
+		last_cpu->next = first_cpu;
+	}
+
+	for (i = 0; i < MAX_NUMNODES; i++) {
+		int j;
+		cpumask_t nodemask;
+		struct sched_group *node = &sched_group_nodes[i];
+		cpus_and(nodemask, node_to_cpumask(i), cpu_possible_map);
+
+		if (cpus_empty(nodemask))
+			continue;
+
+		first_cpu = last_cpu = NULL;
+		/* Set up physical groups */
+		for_each_cpu_mask(j, nodemask) {
+			struct sched_domain *cpu_domain = cpu_sched_domain(j);
+			struct sched_group *cpu = &sched_group_phys[j];
+
+			if (j != first_cpu(cpu_domain->span))
+				continue;
+
+			cpu->cpumask = cpu_domain->span;
+			/*
+			 * Make each extra sibling increase power by 10% of
+			 * the basic CPU. This is very arbitrary.
+			 */
+			cpu->cpu_power = SCHED_LOAD_SCALE + SCHED_LOAD_SCALE*(cpus_weight(cpu->cpumask)-1) / 10;
+			node->cpu_power += cpu->cpu_power;
+
+			if (!first_cpu)
+				first_cpu = cpu;
+			if (last_cpu)
+				last_cpu->next = cpu;
+			last_cpu = cpu;
+		}
+		last_cpu->next = first_cpu;
+	}
+
+	/* Set up nodes */
+	first_cpu = last_cpu = NULL;
+	for (i = 0; i < MAX_NUMNODES; i++) {
+		struct sched_group *cpu = &sched_group_nodes[i];
+		cpumask_t nodemask;
+		cpus_and(nodemask, node_to_cpumask(i), cpu_possible_map);
+
+		if (cpus_empty(nodemask))
+			continue;
+
+		cpu->cpumask = nodemask;
+		/* ->cpu_power already setup */
+
+		if (!first_cpu)
+			first_cpu = cpu;
+		if (last_cpu)
+			last_cpu->next = cpu;
+		last_cpu = cpu;
+	}
+	last_cpu->next = first_cpu;
+
+	mb();
+	for_each_cpu(i) {
+		int node = cpu_to_node(i);
+		struct sched_domain *cpu_domain = cpu_sched_domain(i);
+		struct sched_domain *phys_domain = &per_cpu(phys_domains, i);
+		struct sched_domain *node_domain = &per_cpu(node_domains, i);
+		struct sched_group *cpu_group = &sched_group_cpus[i];
+		struct sched_group *phys_group = &sched_group_phys[first_cpu(cpu_domain->span)];
+		struct sched_group *node_group = &sched_group_nodes[node];
+
+		cpu_domain->parent = phys_domain;
+		phys_domain->parent = node_domain;
+
+		node_domain->groups = node_group;
+		phys_domain->groups = phys_group;
+		cpu_domain->groups = cpu_group;
+	}
+}
+#else /* CONFIG_NUMA */
+static struct sched_group sched_group_cpus[NR_CPUS];
+static struct sched_group sched_group_phys[NR_CPUS];
+static DEFINE_PER_CPU(struct sched_domain, phys_domains);
+__init void arch_init_sched_domains(void)
+{
+	int i;
+	struct sched_group *first_cpu = NULL, *last_cpu = NULL;
+
+	/* Set up domains */
+	for_each_cpu(i) {
+		struct sched_domain *cpu_domain = cpu_sched_domain(i);
+		struct sched_domain *phys_domain = &per_cpu(phys_domains, i);
+
+		*cpu_domain = SD_SIBLING_INIT;
+		cpu_domain->span = cpu_sibling_map[i];
+
+		*phys_domain = SD_CPU_INIT;
+		phys_domain->span = cpu_possible_map;
+	}
+
+	/* Set up CPU (sibling) groups */
+	for_each_cpu(i) {
+		struct sched_domain *cpu_domain = cpu_sched_domain(i);
+		int j;
+		first_cpu = last_cpu = NULL;
+
+		if (i != first_cpu(cpu_domain->span))
+			continue;
+
+		for_each_cpu_mask(j, cpu_domain->span) {
+			struct sched_group *cpu = &sched_group_cpus[j];
+
+			cpus_clear(cpu->cpumask);
+			cpu_set(j, cpu->cpumask);
+			cpu->cpu_power = SCHED_LOAD_SCALE;
+
+			if (!first_cpu)
+				first_cpu = cpu;
+			if (last_cpu)
+				last_cpu->next = cpu;
+			last_cpu = cpu;
+		}
+		last_cpu->next = first_cpu;
+	}
+
+	first_cpu = last_cpu = NULL;
+	/* Set up physical groups */
+	for_each_cpu(i) {
+		struct sched_domain *cpu_domain = cpu_sched_domain(i);
+		struct sched_group *cpu = &sched_group_phys[i];
+
+		if (i != first_cpu(cpu_domain->span))
+			continue;
+
+		cpu->cpumask = cpu_domain->span;
+		/* See SMT+NUMA setup for comment */
+		cpu->cpu_power = SCHED_LOAD_SCALE + SCHED_LOAD_SCALE*(cpus_weight(cpu->cpumask)-1) / 10;
+
+		if (!first_cpu)
+			first_cpu = cpu;
+		if (last_cpu)
+			last_cpu->next = cpu;
+		last_cpu = cpu;
+	}
+	last_cpu->next = first_cpu;
+
+	mb();
+	for_each_cpu(i) {
+		struct sched_domain *cpu_domain = cpu_sched_domain(i);
+		struct sched_domain *phys_domain = &per_cpu(phys_domains, i);
+		struct sched_group *cpu_group = &sched_group_cpus[i];
+		struct sched_group *phys_group = &sched_group_phys[first_cpu(cpu_domain->span)];
+		cpu_domain->parent = phys_domain;
+		phys_domain->groups = phys_group;
+		cpu_domain->groups = cpu_group;
+	}
+}
+#endif /* CONFIG_NUMA */
+#endif /* CONFIG_SCHED_SMT */
+
 /* These are wrappers to interface to the new boot process.  Someone
    who understands all this stuff should rewrite it properly. --RR 15/Jul/02 */
 void __init smp_prepare_cpus(unsigned int max_cpus)
--- diff/arch/i386/kernel/sys_i386.c	2003-06-09 14:18:17.000000000 +0100
+++ source/arch/i386/kernel/sys_i386.c	2004-02-23 13:56:37.000000000 +0000
@@ -15,6 +15,7 @@
 #include <linux/msg.h>
 #include <linux/shm.h>
 #include <linux/stat.h>
+#include <linux/syscalls.h>
 #include <linux/mman.h>
 #include <linux/file.h>
 #include <linux/utsname.h>
@@ -106,8 +107,6 @@ out:
 }
 
 
-extern asmlinkage int sys_select(int, fd_set __user *, fd_set __user *, fd_set __user *, struct timeval __user *);
-
 struct sel_arg_struct {
 	unsigned long n;
 	fd_set __user *inp, *outp, *exp;
--- diff/arch/i386/kernel/sysenter.c	2003-10-09 09:47:16.000000000 +0100
+++ source/arch/i386/kernel/sysenter.c	2004-02-23 13:56:37.000000000 +0000
@@ -18,13 +18,18 @@
 #include <asm/msr.h>
 #include <asm/pgtable.h>
 #include <asm/unistd.h>
+#include <linux/highmem.h>
 
 extern asmlinkage void sysenter_entry(void);
 
 void enable_sep_cpu(void *info)
 {
 	int cpu = get_cpu();
+#ifdef CONFIG_X86_HIGH_ENTRY
+	struct tss_struct *tss = (struct tss_struct *) __fix_to_virt(FIX_TSS_0) + cpu;
+#else
 	struct tss_struct *tss = init_tss + cpu;
+#endif
 
 	tss->ss1 = __KERNEL_CS;
 	tss->esp1 = sizeof(struct tss_struct) + (unsigned long) tss;
--- diff/arch/i386/kernel/time.c	2004-02-09 10:36:07.000000000 +0000
+++ source/arch/i386/kernel/time.c	2004-02-23 13:56:37.000000000 +0000
@@ -346,7 +346,7 @@ static int time_init_device(void)
 {
 	int error = sysdev_class_register(&pit_sysclass);
 	if (!error)
-		error = sys_device_register(&device_i8253);
+		error = sysdev_register(&device_i8253);
 	return error;
 }
 
--- diff/arch/i386/kernel/timers/Makefile	2003-09-30 15:46:11.000000000 +0100
+++ source/arch/i386/kernel/timers/Makefile	2004-02-23 13:56:37.000000000 +0000
@@ -6,3 +6,4 @@ obj-y := timer.o timer_none.o timer_tsc.
 
 obj-$(CONFIG_X86_CYCLONE_TIMER)	+= timer_cyclone.o
 obj-$(CONFIG_HPET_TIMER)	+= timer_hpet.o
+obj-$(CONFIG_X86_PM_TIMER)	+= timer_pm.o
--- diff/arch/i386/kernel/timers/common.c	2003-09-30 15:46:11.000000000 +0100
+++ source/arch/i386/kernel/timers/common.c	2004-02-23 13:56:37.000000000 +0000
@@ -137,3 +137,23 @@ bad_calibration:
 }
 #endif
 
+/* calculate cpu_khz */
+void __init init_cpu_khz(void)
+{
+	if (cpu_has_tsc) {
+		unsigned long tsc_quotient = calibrate_tsc();
+		if (tsc_quotient) {
+			/* report CPU clock rate in Hz.
+			 * The formula is (10^6 * 2^32) / (2^32 * 1 / (clocks/us)) =
+			 * clock/second. Our precision is about 100 ppm.
+			 */
+			{	unsigned long eax=0, edx=1000;
+				__asm__("divl %2"
+		       		:"=a" (cpu_khz), "=d" (edx)
+        	       		:"r" (tsc_quotient),
+	                	"0" (eax), "1" (edx));
+				printk("Detected %lu.%03lu MHz processor.\n", cpu_khz / 1000, cpu_khz % 1000);
+			}
+		}
+	}
+}
--- diff/arch/i386/kernel/timers/timer.c	2003-09-17 12:28:01.000000000 +0100
+++ source/arch/i386/kernel/timers/timer.c	2004-02-23 13:56:37.000000000 +0000
@@ -19,6 +19,9 @@ static struct timer_opts* timers[] = {
 #ifdef CONFIG_HPET_TIMER
 	&timer_hpet,
 #endif
+#ifdef CONFIG_X86_PM_TIMER
+	&timer_pmtmr,
+#endif
 	&timer_tsc,
 	&timer_pit,
 	NULL,
--- diff/arch/i386/kernel/timers/timer_cyclone.c	2004-01-19 10:22:55.000000000 +0000
+++ source/arch/i386/kernel/timers/timer_cyclone.c	2004-02-23 13:56:37.000000000 +0000
@@ -212,26 +212,7 @@ static int __init init_cyclone(char* ove
 		}
 	}
 
-	/* init cpu_khz.
-	 * XXX - This should really be done elsewhere, 
-	 * 		and in a more generic fashion. -johnstul@us.ibm.com
-	 */
-	if (cpu_has_tsc) {
-		unsigned long tsc_quotient = calibrate_tsc();
-		if (tsc_quotient) {
-			/* report CPU clock rate in Hz.
-			 * The formula is (10^6 * 2^32) / (2^32 * 1 / (clocks/us)) =
-			 * clock/second. Our precision is about 100 ppm.
-			 */
-			{	unsigned long eax=0, edx=1000;
-				__asm__("divl %2"
-		       		:"=a" (cpu_khz), "=d" (edx)
-        	       		:"r" (tsc_quotient),
-	                	"0" (eax), "1" (edx));
-				printk("Detected %lu.%03lu MHz processor.\n", cpu_khz / 1000, cpu_khz % 1000);
-			}
-		}
-	}
+	init_cpu_khz();
 
 	/* Everything looks good! */
 	return 0;
--- diff/arch/i386/kernel/traps.c	2003-10-27 09:20:36.000000000 +0000
+++ source/arch/i386/kernel/traps.c	2004-02-23 13:56:37.000000000 +0000
@@ -54,12 +54,8 @@
 
 #include "mach_traps.h"
 
-asmlinkage int system_call(void);
-asmlinkage void lcall7(void);
-asmlinkage void lcall27(void);
-
-struct desc_struct default_ldt[] = { { 0, 0 }, { 0, 0 }, { 0, 0 },
-		{ 0, 0 }, { 0, 0 } };
+struct desc_struct default_ldt[] __attribute__((__section__(".data.default_ldt"))) = { { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 } };
+struct page *default_ldt_page;
 
 /* Do we ignore FPU interrupts ? */
 char ignore_fpu_irq = 0;
@@ -91,6 +87,43 @@ asmlinkage void alignment_check(void);
 asmlinkage void spurious_interrupt_bug(void);
 asmlinkage void machine_check(void);
 
+#ifdef CONFIG_KGDB
+extern void sysenter_entry(void);
+#include <asm/kgdb.h>
+#include <linux/init.h>
+extern void int3(void);
+extern void debug(void);
+void set_intr_gate(unsigned int n, void *addr);
+static void set_intr_usr_gate(unsigned int n, void *addr);
+/*
+ * Should be able to call this breakpoint() very early in
+ * bring up.  Just hard code the call where needed.
+ * The breakpoint() code is here because set_?_gate() functions
+ * are local (static) to trap.c.  They need be done only once,
+ * but it does not hurt to do them over.
+ */
+void breakpoint(void)
+{
+	init_entry_mappings();
+        set_intr_usr_gate(3,&int3); /* disable ints on trap */
+	set_intr_gate(1,&debug);
+	set_intr_gate(14,&page_fault);
+
+        BREAKPOINT;
+}
+#define	CHK_REMOTE_DEBUG(trapnr,signr,error_code,regs,after)		\
+    {									\
+	if (!user_mode(regs)  ) \
+	{								\
+		kgdb_handle_exception(trapnr, signr, error_code, regs);	\
+		after;							\
+	} else if ((trapnr == 3) && (regs->eflags &0x200)) local_irq_enable(); \
+    }
+#else
+#define	CHK_REMOTE_DEBUG(trapnr,signr,error_code,regs,after)
+#endif
+
+
 static int kstack_depth_to_print = 24;
 
 void show_trace(struct task_struct *task, unsigned long * stack)
@@ -119,7 +152,7 @@ void show_trace_task(struct task_struct 
 	unsigned long esp = tsk->thread.esp;
 
 	/* User space on another CPU? */
-	if ((esp ^ (unsigned long)tsk->thread_info) & (PAGE_MASK<<1))
+	if ((esp ^ (unsigned long)tsk->thread_info) & ~(THREAD_SIZE - 1))
 		return;
 	show_trace(tsk, (unsigned long *)esp);
 }
@@ -175,8 +208,9 @@ void show_registers(struct pt_regs *regs
 		ss = regs->xss & 0xffff;
 	}
 	print_modules();
-	printk("CPU:    %d\nEIP:    %04x:[<%08lx>]    %s\nEFLAGS: %08lx\n",
-		smp_processor_id(), 0xffff & regs->xcs, regs->eip, print_tainted(), regs->eflags);
+	printk("CPU:    %d\nEIP:    %04x:[<%08lx>]    %s VLI\nEFLAGS: %08lx\n",
+		smp_processor_id(), 0xffff & regs->xcs,
+		regs->eip, print_tainted(), regs->eflags);
 
 	print_symbol("EIP is at %s\n", regs->eip);
 	printk("eax: %08lx   ebx: %08lx   ecx: %08lx   edx: %08lx\n",
@@ -192,23 +226,27 @@ void show_registers(struct pt_regs *regs
 	 * time of the fault..
 	 */
 	if (in_kernel) {
+		u8 *eip;
 
 		printk("\nStack: ");
 		show_stack(NULL, (unsigned long*)esp);
 
 		printk("Code: ");
-		if(regs->eip < PAGE_OFFSET)
-			goto bad;
 
-		for(i=0;i<20;i++)
-		{
-			unsigned char c;
-			if(__get_user(c, &((unsigned char*)regs->eip)[i])) {
-bad:
+		eip = (u8 *)regs->eip - 43;
+		for (i = 0; i < 64; i++, eip++) {
+			unsigned char c = 0xff;
+
+			if ((user_mode(regs) && get_user(c, eip)) ||
+			    (!user_mode(regs) && __direct_get_user(c, eip))) {
+
 				printk(" Bad EIP value.");
 				break;
 			}
-			printk("%02x ", c);
+			if (eip == (u8 *)regs->eip)
+				printk("<%02x> ", c);
+			else
+				printk("%02x ", c);
 		}
 	}
 	printk("\n");
@@ -255,12 +293,36 @@ spinlock_t die_lock = SPIN_LOCK_UNLOCKED
 void die(const char * str, struct pt_regs * regs, long err)
 {
 	static int die_counter;
+	int nl = 0;
 
 	console_verbose();
 	spin_lock_irq(&die_lock);
 	bust_spinlocks(1);
 	handle_BUG(regs);
 	printk("%s: %04lx [#%d]\n", str, err & 0xffff, ++die_counter);
+#ifdef CONFIG_PREEMPT
+	printk("PREEMPT ");
+	nl = 1;
+#endif
+#ifdef CONFIG_SMP
+	printk("SMP ");
+	nl = 1;
+#endif
+#ifdef CONFIG_DEBUG_PAGEALLOC
+	printk("DEBUG_PAGEALLOC");
+	nl = 1;
+#endif
+	if (nl)
+		printk("\n");
+#ifdef CONFIG_KGDB
+	/* This is about the only place we want to go to kgdb even if in
+	 * user mode.  But we must go in via a trap so within kgdb we will
+	 * always be in kernel mode.
+	 */
+	if (user_mode(regs))
+		BREAKPOINT;
+#endif
+ 	CHK_REMOTE_DEBUG(0,SIGTRAP,err,regs,)
 	show_registers(regs);
 	bust_spinlocks(0);
 	spin_unlock_irq(&die_lock);
@@ -330,6 +392,7 @@ static inline void do_trap(int trapnr, i
 #define DO_ERROR(trapnr, signr, str, name) \
 asmlinkage void do_##name(struct pt_regs * regs, long error_code) \
 { \
+	CHK_REMOTE_DEBUG(trapnr,signr,error_code,regs,)\
 	do_trap(trapnr, signr, str, 0, regs, error_code, NULL); \
 }
 
@@ -347,7 +410,9 @@ asmlinkage void do_##name(struct pt_regs
 #define DO_VM86_ERROR(trapnr, signr, str, name) \
 asmlinkage void do_##name(struct pt_regs * regs, long error_code) \
 { \
+	CHK_REMOTE_DEBUG(trapnr, signr, error_code,regs, return)\
 	do_trap(trapnr, signr, str, 1, regs, error_code, NULL); \
+	return; \
 }
 
 #define DO_VM86_ERROR_INFO(trapnr, signr, str, name, sicode, siaddr) \
@@ -394,8 +459,10 @@ gp_in_vm86:
 	return;
 
 gp_in_kernel:
-	if (!fixup_exception(regs))
+	if (!fixup_exception(regs)){
+ 		CHK_REMOTE_DEBUG(13,SIGSEGV,error_code,regs,)
 		die("general protection fault", regs, error_code);
+	}
 }
 
 static void mem_parity_error(unsigned char reason, struct pt_regs * regs)
@@ -534,10 +601,18 @@ asmlinkage void do_debug(struct pt_regs 
 	if (regs->eflags & X86_EFLAGS_IF)
 		local_irq_enable();
 
-	/* Mask out spurious debug traps due to lazy DR7 setting */
+	/*
+	 * Mask out spurious debug traps due to lazy DR7 setting or
+	 * due to 4G/4G kernel mode:
+	 */
 	if (condition & (DR_TRAP0|DR_TRAP1|DR_TRAP2|DR_TRAP3)) {
 		if (!tsk->thread.debugreg[7])
 			goto clear_dr7;
+		if (!user_mode(regs)) {
+			// restore upon return-to-userspace:
+			set_thread_flag(TIF_DB7);
+			goto clear_dr7;
+		}
 	}
 
 	if (regs->eflags & VM_MASK)
@@ -557,8 +632,18 @@ asmlinkage void do_debug(struct pt_regs 
 		 * allowing programs to debug themselves without the ptrace()
 		 * interface.
 		 */
+#ifdef CONFIG_KGDB
+		/*
+		 * I think this is the only "real" case of a TF in the kernel
+		 * that really belongs to user space.  Others are
+		 * "Ours all ours!"
+		 */
+		if (((regs->xcs & 3) == 0) && ((void *)regs->eip == sysenter_entry))
+			goto clear_TF_reenable;
+#else
 		if ((regs->xcs & 3) == 0)
 			goto clear_TF_reenable;
+#endif
 		if ((tsk->ptrace & (PT_DTRACE|PT_PTRACED)) == PT_DTRACE)
 			goto clear_TF;
 	}
@@ -570,6 +655,17 @@ asmlinkage void do_debug(struct pt_regs 
 	info.si_errno = 0;
 	info.si_code = TRAP_BRKPT;
 	
+#ifdef CONFIG_KGDB
+        /*
+	 * If this is a kernel mode trap, we need to reset db7 to allow us
+	 * to continue sanely ALSO skip the signal delivery
+         */
+	if ((regs->xcs & 3) == 0)
+		goto clear_dr7;
+
+        /* if not kernel, allow ints but only if they were on */
+       if ( regs->eflags & 0x200) local_irq_enable();
+#endif
 	/* If this is a kernel mode trap, save the user PC on entry to 
 	 * the kernel, that's what the debugger can make sense of.
 	 */
@@ -584,6 +680,7 @@ clear_dr7:
 	__asm__("movl %0,%%db7"
 		: /* no output */
 		: "r" (0));
+	CHK_REMOTE_DEBUG(1,SIGTRAP,error_code,regs,)
 	return;
 
 debug_vm86:
@@ -779,19 +876,53 @@ asmlinkage void math_emulate(long arg)
 
 #endif /* CONFIG_MATH_EMULATION */
 
-#ifdef CONFIG_X86_F00F_BUG
-void __init trap_init_f00f_bug(void)
+void __init trap_init_virtual_IDT(void)
 {
-	__set_fixmap(FIX_F00F_IDT, __pa(&idt_table), PAGE_KERNEL_RO);
-
 	/*
-	 * Update the IDT descriptor and reload the IDT so that
-	 * it uses the read-only mapped virtual address.
+	 * "idt" is magic - it overlaps the idt_descr
+	 * variable so that updating idt will automatically
+	 * update the idt descriptor..
 	 */
-	idt_descr.address = fix_to_virt(FIX_F00F_IDT);
+	__set_fixmap(FIX_IDT, __pa(&idt_table), PAGE_KERNEL_RO);
+	idt_descr.address = __fix_to_virt(FIX_IDT);
+
 	__asm__ __volatile__("lidt %0" : : "m" (idt_descr));
 }
+
+void __init trap_init_virtual_GDT(void)
+{
+	int cpu = smp_processor_id();
+	struct Xgt_desc_struct *gdt_desc = cpu_gdt_descr + cpu;
+	struct Xgt_desc_struct tmp_desc = {0, 0};
+	struct tss_struct * t;
+
+	__asm__ __volatile__("sgdt %0": "=m" (tmp_desc): :"memory");
+
+#ifdef CONFIG_X86_HIGH_ENTRY
+	if (!cpu) {
+		__set_fixmap(FIX_GDT_0, __pa(cpu_gdt_table), PAGE_KERNEL);
+		__set_fixmap(FIX_GDT_1, __pa(cpu_gdt_table) + PAGE_SIZE, PAGE_KERNEL);
+		__set_fixmap(FIX_TSS_0, __pa(init_tss), PAGE_KERNEL);
+		__set_fixmap(FIX_TSS_1, __pa(init_tss) + 1*PAGE_SIZE, PAGE_KERNEL);
+		__set_fixmap(FIX_TSS_2, __pa(init_tss) + 2*PAGE_SIZE, PAGE_KERNEL);
+		__set_fixmap(FIX_TSS_3, __pa(init_tss) + 3*PAGE_SIZE, PAGE_KERNEL);
+	}
+
+	gdt_desc->address = __fix_to_virt(FIX_GDT_0) + sizeof(cpu_gdt_table[0]) * cpu;
+#else
+	gdt_desc->address = (unsigned long)cpu_gdt_table[cpu];
+#endif
+	__asm__ __volatile__("lgdt %0": "=m" (*gdt_desc));
+
+#ifdef CONFIG_X86_HIGH_ENTRY
+	t = (struct tss_struct *) __fix_to_virt(FIX_TSS_0) + cpu;
+#else
+	t = init_tss + cpu;
 #endif
+	set_tss_desc(cpu, t);
+	cpu_gdt_table[cpu][GDT_ENTRY_TSS].b &= 0xfffffdff;
+	load_TR_desc();
+}
 
 #define _set_gate(gate_addr,type,dpl,addr,seg) \
 do { \
@@ -818,20 +949,26 @@ void set_intr_gate(unsigned int n, void 
 	_set_gate(idt_table+n,14,0,addr,__KERNEL_CS);
 }
 
-static void __init set_trap_gate(unsigned int n, void *addr)
+void __init set_trap_gate(unsigned int n, void *addr)
 {
 	_set_gate(idt_table+n,15,0,addr,__KERNEL_CS);
 }
 
-static void __init set_system_gate(unsigned int n, void *addr)
+void __init set_system_gate(unsigned int n, void *addr)
 {
 	_set_gate(idt_table+n,15,3,addr,__KERNEL_CS);
 }
 
-static void __init set_call_gate(void *a, void *addr)
+void __init set_call_gate(void *a, void *addr)
 {
 	_set_gate(a,12,3,addr,__KERNEL_CS);
 }
+#ifdef CONFIG_KGDB
+void set_intr_usr_gate(unsigned int n, void *addr)
+{
+	_set_gate(idt_table+n,14,3,addr,__KERNEL_CS);
+}
+#endif
 
 static void __init set_task_gate(unsigned int n, unsigned int gdt_entry)
 {
@@ -850,11 +987,16 @@ void __init trap_init(void)
 #ifdef CONFIG_X86_LOCAL_APIC
 	init_apic_mappings();
 #endif
+	init_entry_mappings();
 
 	set_trap_gate(0,&divide_error);
 	set_intr_gate(1,&debug);
 	set_intr_gate(2,&nmi);
+#ifndef CONFIG_KGDB
 	set_system_gate(3,&int3);	/* int3-5 can be called from all */
+#else
+	set_intr_usr_gate(3,&int3);	/* int3-5 can be called from all */
+#endif
 	set_system_gate(4,&overflow);
 	set_system_gate(5,&bounds);
 	set_trap_gate(6,&invalid_op);
--- diff/arch/i386/kernel/vm86.c	2004-01-19 10:22:55.000000000 +0000
+++ source/arch/i386/kernel/vm86.c	2004-02-23 13:56:37.000000000 +0000
@@ -125,7 +125,7 @@ struct pt_regs * save_v86_state(struct k
 	tss = init_tss + get_cpu();
 	current->thread.esp0 = current->thread.saved_esp0;
 	current->thread.sysenter_cs = __KERNEL_CS;
-	load_esp0(tss, &current->thread);
+	load_virtual_esp0(tss, current);
 	current->thread.saved_esp0 = 0;
 	put_cpu();
 
@@ -305,7 +305,7 @@ static void do_sys_vm86(struct kernel_vm
 	tsk->thread.esp0 = (unsigned long) &info->VM86_TSS_ESP0;
 	if (cpu_has_sep)
 		tsk->thread.sysenter_cs = 0;
-	load_esp0(tss, &tsk->thread);
+	load_virtual_esp0(tss, tsk);
 	put_cpu();
 
 	tsk->thread.screen_bitmap = info->screen_bitmap;
--- diff/arch/i386/kernel/vmlinux.lds.S	2003-10-09 09:47:16.000000000 +0100
+++ source/arch/i386/kernel/vmlinux.lds.S	2004-02-23 13:56:37.000000000 +0000
@@ -3,6 +3,9 @@
  */
 
 #include <asm-generic/vmlinux.lds.h>
+#include <linux/config.h>
+#include <asm/page.h>
+#include <asm/asm_offsets.h>
 	
 OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386")
 OUTPUT_ARCH(i386)
@@ -10,7 +13,7 @@ ENTRY(startup_32)
 jiffies = jiffies_64;
 SECTIONS
 {
-  . = 0xC0000000 + 0x100000;
+  . = __PAGE_OFFSET + 0x100000;
   /* read-only */
   _text = .;			/* Text and read-only data */
   .text : {
@@ -19,6 +22,19 @@ SECTIONS
 	*(.gnu.warning)
 	} = 0x9090
 
+#ifdef CONFIG_X86_4G
+  . = ALIGN(PAGE_SIZE_asm);
+  __entry_tramp_start = .;
+  . = FIX_ENTRY_TRAMPOLINE_0_addr;
+  __start___entry_text = .;
+  .entry.text : AT (__entry_tramp_start) { *(.entry.text) }
+  __entry_tramp_end = __entry_tramp_start + SIZEOF(.entry.text);
+  . = __entry_tramp_end;
+  . = ALIGN(PAGE_SIZE_asm);
+#else
+  .entry.text : { *(.entry.text) }
+#endif
+
   _etext = .;			/* End of text section */
 
   . = ALIGN(16);		/* Exception table */
@@ -34,15 +50,12 @@ SECTIONS
 	CONSTRUCTORS
 	}
 
-  . = ALIGN(4096);
+  . = ALIGN(PAGE_SIZE_asm);
   __nosave_begin = .;
   .data_nosave : { *(.data.nosave) }
-  . = ALIGN(4096);
+  . = ALIGN(PAGE_SIZE_asm);
   __nosave_end = .;
 
-  . = ALIGN(4096);
-  .data.page_aligned : { *(.data.idt) }
-
   . = ALIGN(32);
   .data.cacheline_aligned : { *(.data.cacheline_aligned) }
 
@@ -52,7 +65,7 @@ SECTIONS
   .data.init_task : { *(.data.init_task) }
 
   /* will be freed after init */
-  . = ALIGN(4096);		/* Init code and data */
+  . = ALIGN(PAGE_SIZE_asm);		/* Init code and data */
   __init_begin = .;
   .init.text : { 
 	_sinittext = .;
@@ -91,7 +104,7 @@ SECTIONS
      from .altinstructions and .eh_frame */
   .exit.text : { *(.exit.text) }
   .exit.data : { *(.exit.data) }
-  . = ALIGN(4096);
+  . = ALIGN(PAGE_SIZE_asm);
   __initramfs_start = .;
   .init.ramfs : { *(.init.ramfs) }
   __initramfs_end = .;
@@ -99,10 +112,22 @@ SECTIONS
   __per_cpu_start = .;
   .data.percpu  : { *(.data.percpu) }
   __per_cpu_end = .;
-  . = ALIGN(4096);
+  . = ALIGN(PAGE_SIZE_asm);
   __init_end = .;
   /* freed after init ends here */
-	
+
+  . = ALIGN(PAGE_SIZE_asm);
+  .data.page_aligned_tss : { *(.data.tss) }
+
+  . = ALIGN(PAGE_SIZE_asm);
+  .data.page_aligned_default_ldt : { *(.data.default_ldt) }
+
+  . = ALIGN(PAGE_SIZE_asm);
+  .data.page_aligned_idt : { *(.data.idt) }
+
+  . = ALIGN(PAGE_SIZE_asm);
+  .data.page_aligned_gdt : { *(.data.gdt) }
+
   __bss_start = .;		/* BSS */
   .bss : { *(.bss) }
   __bss_stop = .; 
@@ -122,4 +147,6 @@ SECTIONS
   .stab.index 0 : { *(.stab.index) }
   .stab.indexstr 0 : { *(.stab.indexstr) }
   .comment 0 : { *(.comment) }
+
+
 }
--- diff/arch/i386/kernel/vsyscall-sysenter.S	2003-10-09 09:47:16.000000000 +0100
+++ source/arch/i386/kernel/vsyscall-sysenter.S	2004-02-23 13:56:37.000000000 +0000
@@ -7,6 +7,11 @@
 	.type __kernel_vsyscall,@function
 __kernel_vsyscall:
 .LSTART_vsyscall:
+	cmpl $192, %eax
+	jne 1f
+	int $0x80
+	ret
+1:
 	push %ecx
 .Lpush_ecx:
 	push %edx
--- diff/arch/i386/kernel/vsyscall.lds	2003-10-09 09:47:16.000000000 +0100
+++ source/arch/i386/kernel/vsyscall.lds	2004-02-23 13:56:37.000000000 +0000
@@ -5,7 +5,7 @@
  */
 
 /* This must match <asm/fixmap.h>.  */
-VSYSCALL_BASE = 0xffffe000;
+VSYSCALL_BASE = 0xffffd000;
 
 SECTIONS
 {
--- diff/arch/i386/lib/Makefile	2003-10-09 09:47:16.000000000 +0100
+++ source/arch/i386/lib/Makefile	2004-02-23 13:56:37.000000000 +0000
@@ -9,4 +9,5 @@ lib-y = checksum.o delay.o \
 
 lib-$(CONFIG_X86_USE_3DNOW) += mmx.o
 lib-$(CONFIG_HAVE_DEC_LOCK) += dec_and_lock.o
+lib-$(CONFIG_KGDB) += kgdb_serial.o
 lib-$(CONFIG_DEBUG_IOVIRT)  += iodebug.o
--- diff/arch/i386/lib/checksum.S	2003-10-09 09:47:16.000000000 +0100
+++ source/arch/i386/lib/checksum.S	2004-02-23 13:56:37.000000000 +0000
@@ -280,14 +280,14 @@ unsigned int csum_partial_copy_generic (
 	.previous
 
 .align 4
-.globl csum_partial_copy_generic
+.globl direct_csum_partial_copy_generic
 				
 #ifndef CONFIG_X86_USE_PPRO_CHECKSUM
 
 #define ARGBASE 16		
 #define FP		12
 		
-csum_partial_copy_generic:
+direct_csum_partial_copy_generic:
 	subl  $4,%esp	
 	pushl %edi
 	pushl %esi
@@ -422,7 +422,7 @@ DST(	movb %cl, (%edi)	)
 
 #define ARGBASE 12
 		
-csum_partial_copy_generic:
+direct_csum_partial_copy_generic:
 	pushl %ebx
 	pushl %edi
 	pushl %esi
--- diff/arch/i386/lib/dec_and_lock.c	2003-10-09 09:47:16.000000000 +0100
+++ source/arch/i386/lib/dec_and_lock.c	2004-02-23 13:56:37.000000000 +0000
@@ -10,6 +10,7 @@
 #include <linux/spinlock.h>
 #include <asm/atomic.h>
 
+#ifndef ATOMIC_DEC_AND_LOCK
 int atomic_dec_and_lock(atomic_t *atomic, spinlock_t *lock)
 {
 	int counter;
@@ -38,3 +39,5 @@ slow_path:
 	spin_unlock(lock);
 	return 0;
 }
+#endif
+
--- diff/arch/i386/lib/getuser.S	2003-10-09 09:47:16.000000000 +0100
+++ source/arch/i386/lib/getuser.S	2004-02-23 13:56:37.000000000 +0000
@@ -9,6 +9,7 @@
  * return value.
  */
 #include <asm/thread_info.h>
+#include <asm/asm_offsets.h>
 
 
 /*
@@ -28,7 +29,7 @@
 .globl __get_user_1
 __get_user_1:
 	GET_THREAD_INFO(%edx)
-	cmpl TI_ADDR_LIMIT(%edx),%eax
+	cmpl TI_addr_limit(%edx),%eax
 	jae bad_get_user
 1:	movzbl (%eax),%edx
 	xorl %eax,%eax
@@ -40,7 +41,7 @@ __get_user_2:
 	addl $1,%eax
 	jc bad_get_user
 	GET_THREAD_INFO(%edx)
-	cmpl TI_ADDR_LIMIT(%edx),%eax
+	cmpl TI_addr_limit(%edx),%eax
 	jae bad_get_user
 2:	movzwl -1(%eax),%edx
 	xorl %eax,%eax
@@ -52,7 +53,7 @@ __get_user_4:
 	addl $3,%eax
 	jc bad_get_user
 	GET_THREAD_INFO(%edx)
-	cmpl TI_ADDR_LIMIT(%edx),%eax
+	cmpl TI_addr_limit(%edx),%eax
 	jae bad_get_user
 3:	movl -3(%eax),%edx
 	xorl %eax,%eax
--- diff/arch/i386/lib/usercopy.c	2004-01-19 10:22:55.000000000 +0000
+++ source/arch/i386/lib/usercopy.c	2004-02-23 13:56:37.000000000 +0000
@@ -76,7 +76,7 @@ do {									   \
  * and returns @count.
  */
 long
-__strncpy_from_user(char *dst, const char __user *src, long count)
+__direct_strncpy_from_user(char *dst, const char __user *src, long count)
 {
 	long res;
 	__do_strncpy_from_user(dst, src, count, res);
@@ -102,7 +102,7 @@ __strncpy_from_user(char *dst, const cha
  * and returns @count.
  */
 long
-strncpy_from_user(char *dst, const char __user *src, long count)
+direct_strncpy_from_user(char *dst, const char __user *src, long count)
 {
 	long res = -EFAULT;
 	if (access_ok(VERIFY_READ, src, 1))
@@ -147,7 +147,7 @@ do {									\
  * On success, this will be zero.
  */
 unsigned long
-clear_user(void __user *to, unsigned long n)
+direct_clear_user(void __user *to, unsigned long n)
 {
 	might_sleep();
 	if (access_ok(VERIFY_WRITE, to, n))
@@ -167,7 +167,7 @@ clear_user(void __user *to, unsigned lon
  * On success, this will be zero.
  */
 unsigned long
-__clear_user(void __user *to, unsigned long n)
+__direct_clear_user(void __user *to, unsigned long n)
 {
 	__do_clear_user(to, n);
 	return n;
@@ -184,7 +184,7 @@ __clear_user(void __user *to, unsigned l
  * On exception, returns 0.
  * If the string is too long, returns a value greater than @n.
  */
-long strnlen_user(const char __user *s, long n)
+long direct_strnlen_user(const char __user *s, long n)
 {
 	unsigned long mask = -__addr_ok(s);
 	unsigned long res, tmp;
@@ -575,3 +575,4 @@ unsigned long __copy_from_user_ll(void *
 		n = __copy_user_zeroing_intel(to, (const void *) from, n);
 	return n;
 }
+
--- diff/arch/i386/math-emu/fpu_system.h	2003-10-09 09:47:16.000000000 +0100
+++ source/arch/i386/math-emu/fpu_system.h	2004-02-23 13:56:37.000000000 +0000
@@ -15,6 +15,7 @@
 #include <linux/sched.h>
 #include <linux/kernel.h>
 #include <linux/mm.h>
+#include <asm/atomic_kmap.h>
 
 /* This sets the pointer FPU_info to point to the argument part
    of the stack frame of math_emulate() */
@@ -22,7 +23,7 @@
 
 /* s is always from a cpu register, and the cpu does bounds checking
  * during register load --> no further bounds checks needed */
-#define LDT_DESCRIPTOR(s)	(((struct desc_struct *)current->mm->context.ldt)[(s) >> 3])
+#define LDT_DESCRIPTOR(s)	(((struct desc_struct *)__kmap_atomic_vaddr(KM_LDT_PAGE0))[(s) >> 3])
 #define SEG_D_SIZE(x)		((x).b & (3 << 21))
 #define SEG_G_BIT(x)		((x).b & (1 << 23))
 #define SEG_GRANULARITY(x)	(((x).b & (1 << 23)) ? 4096 : 1)
--- diff/arch/i386/mm/fault.c	2003-12-19 09:51:11.000000000 +0000
+++ source/arch/i386/mm/fault.c	2004-02-23 13:56:37.000000000 +0000
@@ -27,6 +27,7 @@
 #include <asm/pgalloc.h>
 #include <asm/hardirq.h>
 #include <asm/desc.h>
+#include <asm/tlbflush.h>
 
 extern void die(const char *,struct pt_regs *,long);
 
@@ -104,8 +105,17 @@ static inline unsigned long get_segment_
 	if (seg & (1<<2)) {
 		/* Must lock the LDT while reading it. */
 		down(&current->mm->context.sem);
+#if 1
+		/* horrible hack for 4/4 disabled kernels.
+		   I'm not quite sure what the TLB flush is good for,
+		   it's mindlessly copied from the read_ldt code */
+		__flush_tlb_global();
+		desc = kmap(current->mm->context.ldt_pages[(seg&~7)/PAGE_SIZE]);
+		desc = (void *)desc + ((seg & ~7) % PAGE_SIZE);
+#else
 		desc = current->mm->context.ldt;
 		desc = (void *)desc + (seg & ~7);
+#endif
 	} else {
 		/* Must disable preemption while reading the GDT. */
 		desc = (u32 *)&cpu_gdt_table[get_cpu()];
@@ -118,6 +128,9 @@ static inline unsigned long get_segment_
 		 (desc[1] & 0xff000000);
 
 	if (seg & (1<<2)) { 
+#if 1
+		kunmap((void *)((unsigned long)desc & PAGE_MASK));
+#endif
 		up(&current->mm->context.sem);
 	} else
 		put_cpu();
@@ -243,6 +256,19 @@ asmlinkage void do_page_fault(struct pt_
 	 * (error_code & 4) == 0, and that the fault was not a
 	 * protection error (error_code & 1) == 0.
 	 */
+#ifdef CONFIG_X86_4G
+	/*
+	 * On 4/4 all kernels faults are either bugs, vmalloc or prefetch
+	 */
+	if (unlikely((regs->xcs & 3) == 0)) {
+		if (error_code & 3)
+			goto bad_area_nosemaphore;
+
+		/* If it's vm86 fall through */
+		if (!(regs->eflags & VM_MASK))
+			goto vmalloc_fault;
+	}
+#else
 	if (unlikely(address >= TASK_SIZE)) { 
 		if (!(error_code & 5))
 			goto vmalloc_fault;
@@ -252,6 +278,7 @@ asmlinkage void do_page_fault(struct pt_
 		 */
 		goto bad_area_nosemaphore;
 	} 
+#endif
 
 	mm = tsk->mm;
 
@@ -403,6 +430,12 @@ no_context:
  * Oops. The kernel tried to access some bad page. We'll have to
  * terminate things with extreme prejudice.
  */
+#ifdef CONFIG_KGDB
+        if (!user_mode(regs)){
+                kgdb_handle_exception(14,SIGBUS, error_code, regs);
+                return;
+        }
+#endif
 
 	bust_spinlocks(1);
 
--- diff/arch/i386/mm/hugetlbpage.c	2004-01-19 10:22:55.000000000 +0000
+++ source/arch/i386/mm/hugetlbpage.c	2004-02-23 13:56:37.000000000 +0000
@@ -61,6 +61,27 @@ static struct page *alloc_fresh_huge_pag
 
 static void free_huge_page(struct page *page);
 
+#ifdef CONFIG_NUMA
+
+static inline void huge_inc_rss(struct mm_struct *mm, struct page *page)
+{
+	mm->rss += (HPAGE_SIZE / PAGE_SIZE);
+	mm->pernode_rss[page_nodenum(page)] += (HPAGE_SIZE / PAGE_SIZE);
+}
+
+static inline void huge_dec_rss(struct mm_struct *mm, struct page *page)
+{
+	mm->rss -= (HPAGE_SIZE / PAGE_SIZE);
+	mm->pernode_rss[page_nodenum(page)] -= (HPAGE_SIZE / PAGE_SIZE);
+}
+
+#else /* !CONFIG_NUMA */
+
+#define huge_inc_rss(mm, page)	((mm)->rss += (HPAGE_SIZE / PAGE_SIZE))
+#define huge_dec_rss(mm, page)	((mm)->rss -= (HPAGE_SIZE / PAGE_SIZE))
+
+#endif /* CONFIG_NUMA */
+
 static struct page *alloc_hugetlb_page(void)
 {
 	int i;
@@ -105,7 +126,7 @@ static void set_huge_pte(struct mm_struc
 {
 	pte_t entry;
 
-	mm->rss += (HPAGE_SIZE / PAGE_SIZE);
+	huge_inc_rss(mm, page);
 	if (write_access) {
 		entry =
 		    pte_mkwrite(pte_mkdirty(mk_pte(page, vma->vm_page_prot)));
@@ -145,7 +166,7 @@ int copy_hugetlb_page_range(struct mm_st
 		ptepage = pte_page(entry);
 		get_page(ptepage);
 		set_pte(dst_pte, entry);
-		dst->rss += (HPAGE_SIZE / PAGE_SIZE);
+		huge_inc_rss(dst, ptepage);
 		addr += HPAGE_SIZE;
 	}
 	return 0;
@@ -314,8 +335,8 @@ void unmap_hugepage_range(struct vm_area
 		page = pte_page(*pte);
 		huge_page_release(page);
 		pte_clear(pte);
+		huge_dec_rss(mm, page);
 	}
-	mm->rss -= (end - start) >> PAGE_SHIFT;
 	flush_tlb_range(vma, start, end);
 }
 
--- diff/arch/i386/mm/init.c	2004-01-19 10:22:55.000000000 +0000
+++ source/arch/i386/mm/init.c	2004-02-23 13:56:37.000000000 +0000
@@ -40,125 +40,13 @@
 #include <asm/tlb.h>
 #include <asm/tlbflush.h>
 #include <asm/sections.h>
+#include <asm/desc.h>
 
 DEFINE_PER_CPU(struct mmu_gather, mmu_gathers);
 unsigned long highstart_pfn, highend_pfn;
 
 static int do_test_wp_bit(void);
 
-/*
- * Creates a middle page table and puts a pointer to it in the
- * given global directory entry. This only returns the gd entry
- * in non-PAE compilation mode, since the middle layer is folded.
- */
-static pmd_t * __init one_md_table_init(pgd_t *pgd)
-{
-	pmd_t *pmd_table;
-		
-#ifdef CONFIG_X86_PAE
-	pmd_table = (pmd_t *) alloc_bootmem_low_pages(PAGE_SIZE);
-	set_pgd(pgd, __pgd(__pa(pmd_table) | _PAGE_PRESENT));
-	if (pmd_table != pmd_offset(pgd, 0)) 
-		BUG();
-#else
-	pmd_table = pmd_offset(pgd, 0);
-#endif
-
-	return pmd_table;
-}
-
-/*
- * Create a page table and place a pointer to it in a middle page
- * directory entry.
- */
-static pte_t * __init one_page_table_init(pmd_t *pmd)
-{
-	if (pmd_none(*pmd)) {
-		pte_t *page_table = (pte_t *) alloc_bootmem_low_pages(PAGE_SIZE);
-		set_pmd(pmd, __pmd(__pa(page_table) | _PAGE_TABLE));
-		if (page_table != pte_offset_kernel(pmd, 0))
-			BUG();	
-
-		return page_table;
-	}
-	
-	return pte_offset_kernel(pmd, 0);
-}
-
-/*
- * This function initializes a certain range of kernel virtual memory 
- * with new bootmem page tables, everywhere page tables are missing in
- * the given range.
- */
-
-/*
- * NOTE: The pagetables are allocated contiguous on the physical space 
- * so we can cache the place of the first one and move around without 
- * checking the pgd every time.
- */
-static void __init page_table_range_init (unsigned long start, unsigned long end, pgd_t *pgd_base)
-{
-	pgd_t *pgd;
-	pmd_t *pmd;
-	int pgd_idx, pmd_idx;
-	unsigned long vaddr;
-
-	vaddr = start;
-	pgd_idx = pgd_index(vaddr);
-	pmd_idx = pmd_index(vaddr);
-	pgd = pgd_base + pgd_idx;
-
-	for ( ; (pgd_idx < PTRS_PER_PGD) && (vaddr != end); pgd++, pgd_idx++) {
-		if (pgd_none(*pgd)) 
-			one_md_table_init(pgd);
-
-		pmd = pmd_offset(pgd, vaddr);
-		for (; (pmd_idx < PTRS_PER_PMD) && (vaddr != end); pmd++, pmd_idx++) {
-			if (pmd_none(*pmd)) 
-				one_page_table_init(pmd);
-
-			vaddr += PMD_SIZE;
-		}
-		pmd_idx = 0;
-	}
-}
-
-/*
- * This maps the physical memory to kernel virtual address space, a total 
- * of max_low_pfn pages, by creating page tables starting from address 
- * PAGE_OFFSET.
- */
-static void __init kernel_physical_mapping_init(pgd_t *pgd_base)
-{
-	unsigned long pfn;
-	pgd_t *pgd;
-	pmd_t *pmd;
-	pte_t *pte;
-	int pgd_idx, pmd_idx, pte_ofs;
-
-	pgd_idx = pgd_index(PAGE_OFFSET);
-	pgd = pgd_base + pgd_idx;
-	pfn = 0;
-
-	for (; pgd_idx < PTRS_PER_PGD; pgd++, pgd_idx++) {
-		pmd = one_md_table_init(pgd);
-		if (pfn >= max_low_pfn)
-			continue;
-		for (pmd_idx = 0; pmd_idx < PTRS_PER_PMD && pfn < max_low_pfn; pmd++, pmd_idx++) {
-			/* Map with big pages if possible, otherwise create normal page tables. */
-			if (cpu_has_pse) {
-				set_pmd(pmd, pfn_pmd(pfn, PAGE_KERNEL_LARGE));
-				pfn += PTRS_PER_PTE;
-			} else {
-				pte = one_page_table_init(pmd);
-
-				for (pte_ofs = 0; pte_ofs < PTRS_PER_PTE && pfn < max_low_pfn; pte++, pfn++, pte_ofs++)
-					set_pte(pte, pfn_pte(pfn, PAGE_KERNEL));
-			}
-		}
-	}	
-}
-
 static inline int page_kills_ppro(unsigned long pagenr)
 {
 	if (pagenr >= 0x70000 && pagenr <= 0x7003F)
@@ -206,11 +94,8 @@ static inline int page_is_ram(unsigned l
 	return 0;
 }
 
-#ifdef CONFIG_HIGHMEM
 pte_t *kmap_pte;
-pgprot_t kmap_prot;
 
-EXPORT_SYMBOL(kmap_prot);
 EXPORT_SYMBOL(kmap_pte);
 
 #define kmap_get_fixmap_pte(vaddr)					\
@@ -218,29 +103,7 @@ EXPORT_SYMBOL(kmap_pte);
 
 void __init kmap_init(void)
 {
-	unsigned long kmap_vstart;
-
-	/* cache the first kmap pte */
-	kmap_vstart = __fix_to_virt(FIX_KMAP_BEGIN);
-	kmap_pte = kmap_get_fixmap_pte(kmap_vstart);
-
-	kmap_prot = PAGE_KERNEL;
-}
-
-void __init permanent_kmaps_init(pgd_t *pgd_base)
-{
-	pgd_t *pgd;
-	pmd_t *pmd;
-	pte_t *pte;
-	unsigned long vaddr;
-
-	vaddr = PKMAP_BASE;
-	page_table_range_init(vaddr, vaddr + PAGE_SIZE*LAST_PKMAP, pgd_base);
-
-	pgd = swapper_pg_dir + pgd_index(vaddr);
-	pmd = pmd_offset(pgd, vaddr);
-	pte = pte_offset_kernel(pmd, vaddr);
-	pkmap_page_table = pte;	
+	kmap_pte = kmap_get_fixmap_pte(__fix_to_virt(FIX_KMAP_BEGIN));
 }
 
 void __init one_highpage_init(struct page *page, int pfn, int bad_ppro)
@@ -255,6 +118,8 @@ void __init one_highpage_init(struct pag
 		SetPageReserved(page);
 }
 
+#ifdef CONFIG_HIGHMEM
+
 #ifndef CONFIG_DISCONTIGMEM
 void __init set_highmem_pages_init(int bad_ppro) 
 {
@@ -266,12 +131,9 @@ void __init set_highmem_pages_init(int b
 #else
 extern void set_highmem_pages_init(int);
 #endif /* !CONFIG_DISCONTIGMEM */
-
 #else
-#define kmap_init() do { } while (0)
-#define permanent_kmaps_init(pgd_base) do { } while (0)
-#define set_highmem_pages_init(bad_ppro) do { } while (0)
-#endif /* CONFIG_HIGHMEM */
+# define set_highmem_pages_init(bad_ppro) do { } while (0)
+#endif
 
 unsigned long __PAGE_KERNEL = _PAGE_KERNEL;
 
@@ -281,30 +143,125 @@ unsigned long __PAGE_KERNEL = _PAGE_KERN
 extern void __init remap_numa_kva(void);
 #endif
 
-static void __init pagetable_init (void)
+static __init void prepare_pagetables(pgd_t *pgd_base, unsigned long address)
+{
+	pgd_t *pgd;
+	pmd_t *pmd;
+	pte_t *pte;
+
+	pgd = pgd_base + pgd_index(address);
+	pmd = pmd_offset(pgd, address);
+	if (!pmd_present(*pmd)) {
+		pte = (pte_t *) alloc_bootmem_low_pages(PAGE_SIZE);
+		set_pmd(pmd, __pmd(_PAGE_TABLE + __pa(pte)));
+	}
+}
+
+static void __init fixrange_init (unsigned long start, unsigned long end, pgd_t *pgd_base)
 {
 	unsigned long vaddr;
-	pgd_t *pgd_base = swapper_pg_dir;
 
+	for (vaddr = start; vaddr != end; vaddr += PAGE_SIZE)
+		prepare_pagetables(pgd_base, vaddr);
+}
+
+void setup_identity_mappings(pgd_t *pgd_base, unsigned long start, unsigned long end)
+{
+	unsigned long vaddr;
+	pgd_t *pgd;
+	int i, j, k;
+	pmd_t *pmd;
+	pte_t *pte, *pte_base;
+
+	pgd = pgd_base;
+
+	for (i = 0; i < PTRS_PER_PGD; pgd++, i++) {
+		vaddr = i*PGDIR_SIZE;
+		if (end && (vaddr >= end))
+			break;
+		pmd = pmd_offset(pgd, 0);
+		for (j = 0; j < PTRS_PER_PMD; pmd++, j++) {
+			vaddr = i*PGDIR_SIZE + j*PMD_SIZE;
+			if (end && (vaddr >= end))
+				break;
+			if (vaddr < start)
+				continue;
+			if (cpu_has_pse) {
+				unsigned long __pe;
+
+				set_in_cr4(X86_CR4_PSE);
+				boot_cpu_data.wp_works_ok = 1;
+				__pe = _KERNPG_TABLE + _PAGE_PSE + vaddr - start;
+				/* Make it "global" too if supported */
+				if (cpu_has_pge) {
+					set_in_cr4(X86_CR4_PGE);
+#if !defined(CONFIG_X86_SWITCH_PAGETABLES)
+					__pe += _PAGE_GLOBAL;
+					__PAGE_KERNEL |= _PAGE_GLOBAL;
+#endif
+				}
+				set_pmd(pmd, __pmd(__pe));
+				continue;
+			}
+			if (!pmd_present(*pmd))
+				pte_base = (pte_t *) alloc_bootmem_low_pages(PAGE_SIZE);
+			else
+				pte_base = (pte_t *) page_address(pmd_page(*pmd));
+			pte = pte_base;
+			for (k = 0; k < PTRS_PER_PTE; pte++, k++) {
+				vaddr = i*PGDIR_SIZE + j*PMD_SIZE + k*PAGE_SIZE;
+				if (end && (vaddr >= end))
+					break;
+				if (vaddr < start)
+					continue;
+				*pte = mk_pte_phys(vaddr-start, PAGE_KERNEL);
+			}
+			set_pmd(pmd, __pmd(_KERNPG_TABLE + __pa(pte_base)));
+		}
+	}
+}
+
+static void __init pagetable_init (void)
+{
+	unsigned long vaddr, end;
+	pgd_t *pgd_base;
 #ifdef CONFIG_X86_PAE
 	int i;
-	/* Init entries of the first-level page table to the zero page */
-	for (i = 0; i < PTRS_PER_PGD; i++)
-		set_pgd(pgd_base + i, __pgd(__pa(empty_zero_page) | _PAGE_PRESENT));
 #endif
 
-	/* Enable PSE if available */
-	if (cpu_has_pse) {
-		set_in_cr4(X86_CR4_PSE);
-	}
+	/*
+	 * This can be zero as well - no problem, in that case we exit
+	 * the loops anyway due to the PTRS_PER_* conditions.
+	 */
+	end = (unsigned long)__va(max_low_pfn*PAGE_SIZE);
 
-	/* Enable PGE if available */
-	if (cpu_has_pge) {
-		set_in_cr4(X86_CR4_PGE);
-		__PAGE_KERNEL |= _PAGE_GLOBAL;
+	pgd_base = swapper_pg_dir;
+#ifdef CONFIG_X86_PAE
+	/*
+	 * It causes too many problems if there's no proper pmd set up
+	 * for all 4 entries of the PGD - so we allocate all of them.
+	 * PAE systems will not miss this extra 4-8K anyway ...
+	 */
+	for (i = 0; i < PTRS_PER_PGD; i++) {
+		pmd_t *pmd = (pmd_t *) alloc_bootmem_low_pages(PAGE_SIZE);
+		set_pgd(pgd_base + i, __pgd(__pa(pmd) + 0x1));
 	}
+#endif
+	/*
+	 * Set up lowmem-sized identity mappings at PAGE_OFFSET:
+	 */
+	setup_identity_mappings(pgd_base, PAGE_OFFSET, end);
 
-	kernel_physical_mapping_init(pgd_base);
+	/*
+	 * Add flat-mode identity-mappings - SMP needs it when
+	 * starting up on an AP from real-mode. (In the non-PAE
+	 * case we already have these mappings through head.S.)
+	 * All user-space mappings are explicitly cleared after
+	 * SMP startup.
+	 */
+#if defined(CONFIG_SMP) && defined(CONFIG_X86_PAE)
+	setup_identity_mappings(pgd_base, 0, 16*1024*1024);
+#endif
 	remap_numa_kva();
 
 	/*
@@ -312,38 +269,64 @@ static void __init pagetable_init (void)
 	 * created - mappings will be set by set_fixmap():
 	 */
 	vaddr = __fix_to_virt(__end_of_fixed_addresses - 1) & PMD_MASK;
-	page_table_range_init(vaddr, 0, pgd_base);
+	fixrange_init(vaddr, 0, pgd_base);
 
-	permanent_kmaps_init(pgd_base);
+#ifdef CONFIG_HIGHMEM
+	{
+		pgd_t *pgd;
+		pmd_t *pmd;
+		pte_t *pte;
 
-#ifdef CONFIG_X86_PAE
-	/*
-	 * Add low memory identity-mappings - SMP needs it when
-	 * starting up on an AP from real-mode. In the non-PAE
-	 * case we already have these mappings through head.S.
-	 * All user-space mappings are explicitly cleared after
-	 * SMP startup.
-	 */
-	pgd_base[0] = pgd_base[USER_PTRS_PER_PGD];
+		/*
+		 * Permanent kmaps:
+		 */
+		vaddr = PKMAP_BASE;
+		fixrange_init(vaddr, vaddr + PAGE_SIZE*LAST_PKMAP, pgd_base);
+
+		pgd = swapper_pg_dir + pgd_index(vaddr);
+		pmd = pmd_offset(pgd, vaddr);
+		pte = pte_offset_kernel(pmd, vaddr);
+		pkmap_page_table = pte;
+	}
 #endif
 }
 
-void zap_low_mappings (void)
+/*
+ * Clear kernel pagetables in a PMD_SIZE-aligned range.
+ */
+static void clear_mappings(pgd_t *pgd_base, unsigned long start, unsigned long end)
 {
-	int i;
+	unsigned long vaddr;
+	pgd_t *pgd;
+	pmd_t *pmd;
+	int i, j;
+
+	pgd = pgd_base;
+
+	for (i = 0; i < PTRS_PER_PGD; pgd++, i++) {
+		vaddr = i*PGDIR_SIZE;
+		if (end && (vaddr >= end))
+			break;
+		pmd = pmd_offset(pgd, 0);
+		for (j = 0; j < PTRS_PER_PMD; pmd++, j++) {
+			vaddr = i*PGDIR_SIZE + j*PMD_SIZE;
+			if (end && (vaddr >= end))
+				break;
+			if (vaddr < start)
+				continue;
+			pmd_clear(pmd);
+		}
+	}
+	flush_tlb_all();
+}
+
+void zap_low_mappings(void)
+{
+	printk("zapping low mappings.\n");
 	/*
 	 * Zap initial low-memory mappings.
-	 *
-	 * Note that "pgd_clear()" doesn't do it for
-	 * us, because pgd_clear() is a no-op on i386.
 	 */
-	for (i = 0; i < USER_PTRS_PER_PGD; i++)
-#ifdef CONFIG_X86_PAE
-		set_pgd(swapper_pg_dir+i, __pgd(1 + __pa(empty_zero_page)));
-#else
-		set_pgd(swapper_pg_dir+i, __pgd(0));
-#endif
-	flush_tlb_all();
+	clear_mappings(swapper_pg_dir, 0, 16*1024*1024);
 }
 
 #ifndef CONFIG_DISCONTIGMEM
@@ -393,7 +376,15 @@ void __init paging_init(void)
 		set_in_cr4(X86_CR4_PAE);
 #endif
 	__flush_tlb_all();
-
+	/*
+	 * Subtle. SMP is doing it's boot stuff late (because it has to
+	 * fork idle threads) - but it also needs low mappings for the
+	 * protected-mode entry to work. We zap these entries only after
+	 * the WP-bit has been tested.
+	 */
+#ifndef CONFIG_SMP
+	zap_low_mappings();
+#endif
 	kmap_init();
 	zone_sizes_init();
 }
@@ -515,22 +506,18 @@ void __init mem_init(void)
 	if (boot_cpu_data.wp_works_ok < 0)
 		test_wp_bit();
 
-	/*
-	 * Subtle. SMP is doing it's boot stuff late (because it has to
-	 * fork idle threads) - but it also needs low mappings for the
-	 * protected-mode entry to work. We zap these entries only after
-	 * the WP-bit has been tested.
-	 */
-#ifndef CONFIG_SMP
-	zap_low_mappings();
-#endif
+	entry_trampoline_setup();
+	default_ldt_page = virt_to_page(default_ldt);
+	load_LDT(&init_mm.context);
 }
 
-kmem_cache_t *pgd_cache;
-kmem_cache_t *pmd_cache;
+kmem_cache_t *pgd_cache, *pmd_cache, *kpmd_cache;
 
 void __init pgtable_cache_init(void)
 {
+	void (*ctor)(void *, kmem_cache_t *, unsigned long);
+	void (*dtor)(void *, kmem_cache_t *, unsigned long);
+
 	if (PTRS_PER_PMD > 1) {
 		pmd_cache = kmem_cache_create("pmd",
 					PTRS_PER_PMD*sizeof(pmd_t),
@@ -540,13 +527,36 @@ void __init pgtable_cache_init(void)
 					NULL);
 		if (!pmd_cache)
 			panic("pgtable_cache_init(): cannot create pmd cache");
+
+		if (TASK_SIZE > PAGE_OFFSET) {
+			kpmd_cache = kmem_cache_create("kpmd",
+					PTRS_PER_PMD*sizeof(pmd_t),
+					0,
+					SLAB_HWCACHE_ALIGN | SLAB_MUST_HWCACHE_ALIGN,
+					kpmd_ctor,
+					NULL);
+			if (!kpmd_cache)
+				panic("pgtable_cache_init(): "
+						"cannot create kpmd cache");
+		}
 	}
+
+	if (PTRS_PER_PMD == 1 || TASK_SIZE <= PAGE_OFFSET)
+		ctor = pgd_ctor;
+	else
+		ctor = NULL;
+
+	if (PTRS_PER_PMD == 1 && TASK_SIZE <= PAGE_OFFSET)
+		dtor = pgd_dtor;
+	else
+		dtor = NULL;
+
 	pgd_cache = kmem_cache_create("pgd",
 				PTRS_PER_PGD*sizeof(pgd_t),
 				0,
 				SLAB_HWCACHE_ALIGN | SLAB_MUST_HWCACHE_ALIGN,
-				pgd_ctor,
-				PTRS_PER_PMD == 1 ? pgd_dtor : NULL);
+				ctor,
+				dtor);
 	if (!pgd_cache)
 		panic("pgtable_cache_init(): Cannot create pgd cache");
 }
--- diff/arch/i386/mm/pgtable.c	2003-10-09 09:47:16.000000000 +0100
+++ source/arch/i386/mm/pgtable.c	2004-02-23 13:56:37.000000000 +0000
@@ -21,6 +21,7 @@
 #include <asm/e820.h>
 #include <asm/tlb.h>
 #include <asm/tlbflush.h>
+#include <asm/atomic_kmap.h>
 
 void show_mem(void)
 {
@@ -157,11 +158,20 @@ void pmd_ctor(void *pmd, kmem_cache_t *c
 	memset(pmd, 0, PTRS_PER_PMD*sizeof(pmd_t));
 }
 
+void kpmd_ctor(void *__pmd, kmem_cache_t *cache, unsigned long flags)
+{
+	pmd_t *kpmd, *pmd;
+	kpmd = pmd_offset(&swapper_pg_dir[PTRS_PER_PGD-1],
+				(PTRS_PER_PMD - NR_SHARED_PMDS)*PMD_SIZE);
+	pmd = (pmd_t *)__pmd + (PTRS_PER_PMD - NR_SHARED_PMDS);
+
+	memset(__pmd, 0, (PTRS_PER_PMD - NR_SHARED_PMDS)*sizeof(pmd_t));
+	memcpy(pmd, kpmd, NR_SHARED_PMDS*sizeof(pmd_t));
+}
+
 /*
- * List of all pgd's needed for non-PAE so it can invalidate entries
- * in both cached and uncached pgd's; not needed for PAE since the
- * kernel pmd is shared. If PAE were not to share the pmd a similar
- * tactic would be needed. This is essentially codepath-based locking
+ * List of all pgd's needed so it can invalidate entries in both cached
+ * and uncached pgd's. This is essentially codepath-based locking
  * against pageattr.c; it is the unique case in which a valid change
  * of kernel pagetables can't be lazily synchronized by vmalloc faults.
  * vmalloc faults work because attached pagetables are never freed.
@@ -170,30 +180,60 @@ void pmd_ctor(void *pmd, kmem_cache_t *c
  * could be used. The locking scheme was chosen on the basis of
  * manfred's recommendations and having no core impact whatsoever.
  * -- wli
+ *
+ * The entire issue goes away when XKVA is configured.
  */
 spinlock_t pgd_lock = SPIN_LOCK_UNLOCKED;
 LIST_HEAD(pgd_list);
 
-void pgd_ctor(void *pgd, kmem_cache_t *cache, unsigned long unused)
+/*
+ * This is not that hard to figure out.
+ * (a) PTRS_PER_PMD == 1 means non-PAE.
+ * (b) PTRS_PER_PMD > 1 means PAE.
+ * (c) TASK_SIZE > PAGE_OFFSET means XKVA.
+ * (d) TASK_SIZE <= PAGE_OFFSET means non-XKVA.
+ *
+ * Do *NOT* back out the preconstruction like the patch I'm cleaning
+ * up after this very instant did, or at all, for that matter.
+ * This is never called when PTRS_PER_PMD > 1 && TASK_SIZE > PAGE_OFFSET.
+ * -- wli
+ */
+void pgd_ctor(void *__pgd, kmem_cache_t *cache, unsigned long unused)
 {
+	pgd_t *pgd = (pgd_t *)__pgd;
 	unsigned long flags;
 
-	if (PTRS_PER_PMD == 1)
-		spin_lock_irqsave(&pgd_lock, flags);
+	if (PTRS_PER_PMD == 1) {
+		if (TASK_SIZE <= PAGE_OFFSET)
+			spin_lock_irqsave(&pgd_lock, flags);
+		else
+ 			memcpy(&pgd[PTRS_PER_PGD - NR_SHARED_PMDS],
+ 				&swapper_pg_dir[PTRS_PER_PGD - NR_SHARED_PMDS],
+ 				NR_SHARED_PMDS * sizeof(pgd_t));
+	}
 
-	memcpy((pgd_t *)pgd + USER_PTRS_PER_PGD,
-			swapper_pg_dir + USER_PTRS_PER_PGD,
-			(PTRS_PER_PGD - USER_PTRS_PER_PGD) * sizeof(pgd_t));
+	if (TASK_SIZE <= PAGE_OFFSET)
+ 		memcpy(pgd + USER_PTRS_PER_PGD,
+ 			swapper_pg_dir + USER_PTRS_PER_PGD,
+ 			(PTRS_PER_PGD - USER_PTRS_PER_PGD) * sizeof(pgd_t));
 
 	if (PTRS_PER_PMD > 1)
 		return;
 
-	list_add(&virt_to_page(pgd)->lru, &pgd_list);
-	spin_unlock_irqrestore(&pgd_lock, flags);
-	memset(pgd, 0, USER_PTRS_PER_PGD*sizeof(pgd_t));
+	if (TASK_SIZE > PAGE_OFFSET)
+		memset(pgd, 0, (PTRS_PER_PGD - NR_SHARED_PMDS)*sizeof(pgd_t));
+	else {
+		list_add(&virt_to_page(pgd)->lru, &pgd_list);
+		spin_unlock_irqrestore(&pgd_lock, flags);
+		memset(pgd, 0, USER_PTRS_PER_PGD*sizeof(pgd_t));
+	}
 }
 
-/* never called when PTRS_PER_PMD > 1 */
+/*
+ * Never called when PTRS_PER_PMD > 1 || TASK_SIZE > PAGE_OFFSET
+ * for with PAE we would list_del() multiple times, and for non-PAE
+ * with XKVA all the AGP pgd shootdown code is unnecessary.
+ */
 void pgd_dtor(void *pgd, kmem_cache_t *cache, unsigned long unused)
 {
 	unsigned long flags; /* can be called from interrupt context */
@@ -203,6 +243,12 @@ void pgd_dtor(void *pgd, kmem_cache_t *c
 	spin_unlock_irqrestore(&pgd_lock, flags);
 }
 
+/*
+ * See the comments above pgd_ctor() wrt. preconstruction.
+ * Do *NOT* memcpy() here. If you do, you back out important
+ * anti- cache pollution code.
+ *
+ */
 pgd_t *pgd_alloc(struct mm_struct *mm)
 {
 	int i;
@@ -211,15 +257,33 @@ pgd_t *pgd_alloc(struct mm_struct *mm)
 	if (PTRS_PER_PMD == 1 || !pgd)
 		return pgd;
 
+	/*
+	 * In the 4G userspace case alias the top 16 MB virtual
+	 * memory range into the user mappings as well (these
+	 * include the trampoline and CPU data structures).
+	 */
 	for (i = 0; i < USER_PTRS_PER_PGD; ++i) {
-		pmd_t *pmd = kmem_cache_alloc(pmd_cache, GFP_KERNEL);
+		kmem_cache_t *cache;
+		pmd_t *pmd;
+
+		if (TASK_SIZE > PAGE_OFFSET && i == USER_PTRS_PER_PGD - 1)
+			cache = kpmd_cache;
+		else
+			cache = pmd_cache;
+
+		pmd = kmem_cache_alloc(cache, GFP_KERNEL);
 		if (!pmd)
 			goto out_oom;
 		set_pgd(&pgd[i], __pgd(1 + __pa((u64)((u32)pmd))));
 	}
-	return pgd;
 
+	return pgd;
 out_oom:
+	/*
+	 * we don't have to handle the kpmd_cache here, since it's the
+	 * last allocation, and has either nothing to free or when it
+	 * succeeds the whole operation succeeds.
+	 */
 	for (i--; i >= 0; i--)
 		kmem_cache_free(pmd_cache, (void *)__va(pgd_val(pgd[i])-1));
 	kmem_cache_free(pgd_cache, pgd);
@@ -230,10 +294,29 @@ void pgd_free(pgd_t *pgd)
 {
 	int i;
 
-	/* in the PAE case user pgd entries are overwritten before usage */
-	if (PTRS_PER_PMD > 1)
-		for (i = 0; i < USER_PTRS_PER_PGD; ++i)
-			kmem_cache_free(pmd_cache, (void *)__va(pgd_val(pgd[i])-1));
 	/* in the non-PAE case, clear_page_tables() clears user pgd entries */
+	if (PTRS_PER_PMD == 1)
+		goto out_free;
+
+	/* in the PAE case user pgd entries are overwritten before usage */
+	for (i = 0; i < USER_PTRS_PER_PGD; ++i) {
+		kmem_cache_t *cache;
+		pmd_t *pmd = __va(pgd_val(pgd[i]) - 1);
+
+		/*
+		 * only userspace pmd's are cleared for us
+		 * by mm/memory.c; it's a slab cache invariant
+		 * that we must separate the kernel pmd slab
+		 * all times, else we'll have bad pmd's.
+		 */
+		if (TASK_SIZE > PAGE_OFFSET && i == USER_PTRS_PER_PGD - 1)
+			cache = kpmd_cache;
+		else
+			cache = pmd_cache;
+
+		kmem_cache_free(cache, pmd);
+	}
+out_free:
 	kmem_cache_free(pgd_cache, pgd);
 }
+
--- diff/arch/i386/oprofile/nmi_int.c	2003-09-30 15:46:11.000000000 +0100
+++ source/arch/i386/oprofile/nmi_int.c	2004-02-23 13:56:37.000000000 +0000
@@ -65,14 +65,14 @@ static int __init init_driverfs(void)
 {
 	int error;
 	if (!(error = sysdev_class_register(&oprofile_sysclass)))
-		error = sys_device_register(&device_oprofile);
+		error = sysdev_register(&device_oprofile);
 	return error;
 }
 
 
 static void __exit exit_driverfs(void)
 {
-	sys_device_unregister(&device_oprofile);
+	sysdev_unregister(&device_oprofile);
 	sysdev_class_unregister(&oprofile_sysclass);
 }
 
@@ -295,8 +295,6 @@ struct oprofile_operations nmi_ops = {
 };
  
 
-#if !defined(CONFIG_X86_64)
-
 static int __init p4_init(void)
 {
 	__u8 cpu_model = current_cpu_data.x86_model;
@@ -335,7 +333,9 @@ static int __init ppro_init(void)
 	if (cpu_model > 0xd)
 		return 0;
 
-	if (cpu_model > 5) {
+	if (cpu_model == 9) {
+		nmi_ops.cpu_type = "i386/p6_mobile";
+	} else if (cpu_model > 5) {
 		nmi_ops.cpu_type = "i386/piii";
 	} else if (cpu_model > 2) {
 		nmi_ops.cpu_type = "i386/pii";
@@ -347,9 +347,6 @@ static int __init ppro_init(void)
 	return 1;
 }
 
-#endif /* !CONFIG_X86_64 */
- 
-
 /* in order to get driverfs right */
 static int using_nmi;
 
@@ -381,7 +378,6 @@ int __init nmi_init(struct oprofile_oper
 			}
 			break;
  
-#if !defined(CONFIG_X86_64)
 		case X86_VENDOR_INTEL:
 			switch (family) {
 				/* Pentium IV */
@@ -400,7 +396,6 @@ int __init nmi_init(struct oprofile_oper
 					return -ENODEV;
 			}
 			break;
-#endif /* !CONFIG_X86_64 */
 
 		default:
 			return -ENODEV;
--- diff/arch/i386/oprofile/nmi_timer_int.c	2003-06-30 10:07:32.000000000 +0100
+++ source/arch/i386/oprofile/nmi_timer_int.c	2004-02-23 13:56:37.000000000 +0000
@@ -48,9 +48,13 @@ static struct oprofile_operations nmi_ti
 	.cpu_type = "timer"
 };
 
- 
 int __init nmi_timer_init(struct oprofile_operations ** ops)
 {
+	extern int nmi_active;
+
+	if (nmi_active <= 0)
+		return -ENODEV;
+
 	*ops = &nmi_timer_ops;
 	printk(KERN_INFO "oprofile: using NMI timer interrupt.\n");
 	return 0;
--- diff/arch/i386/oprofile/op_model_p4.c	2003-08-26 10:00:51.000000000 +0100
+++ source/arch/i386/oprofile/op_model_p4.c	2004-02-23 13:56:37.000000000 +0000
@@ -382,11 +382,8 @@ static struct p4_event_binding p4_events
 static unsigned int get_stagger(void)
 {
 #ifdef CONFIG_SMP
-	int cpu;
-	if (smp_num_siblings > 1) {
-		cpu = smp_processor_id();
-		return (cpu_sibling_map[cpu] > cpu) ? 0 : 1;
-	}
+	int cpu = smp_processor_id();
+	return (cpu != first_cpu(cpu_sibling_map[cpu]));
 #endif	
 	return 0;
 }
--- diff/arch/i386/oprofile/op_model_ppro.c	2003-08-26 10:00:51.000000000 +0100
+++ source/arch/i386/oprofile/op_model_ppro.c	2004-02-23 13:56:37.000000000 +0000
@@ -13,6 +13,7 @@
 #include <linux/oprofile.h>
 #include <asm/ptrace.h>
 #include <asm/msr.h>
+#include <asm/apic.h>
  
 #include "op_x86_model.h"
 #include "op_counter.h"
@@ -101,6 +102,10 @@ static int ppro_check_ctrs(unsigned int 
 		}
 	}
 
+	/* Only P6 based Pentium M need to re-unmask the apic vector but it
+	 * doesn't hurt other P6 variant */
+	apic_write(APIC_LVTPC, apic_read(APIC_LVTPC) & ~APIC_LVT_MASKED);
+
 	/* We can't work out if we really handled an interrupt. We
 	 * might have caught a *second* counter just after overflowing
 	 * the interrupt for this counter then arrives
--- diff/arch/i386/pci/Makefile	2003-07-08 09:55:17.000000000 +0100
+++ source/arch/i386/pci/Makefile	2004-02-23 13:56:37.000000000 +0000
@@ -1,6 +1,7 @@
 obj-y				:= i386.o
 
 obj-$(CONFIG_PCI_BIOS)		+= pcbios.o
+obj-$(CONFIG_PCI_MMCONFIG)	+= mmconfig.o
 obj-$(CONFIG_PCI_DIRECT)	+= direct.o
 
 pci-y				:= fixup.o
--- diff/arch/i386/pci/common.c	2004-02-09 10:36:07.000000000 +0000
+++ source/arch/i386/pci/common.c	2004-02-23 13:56:37.000000000 +0000
@@ -20,7 +20,8 @@
 extern  void pcibios_sort(void);
 #endif
 
-unsigned int pci_probe = PCI_PROBE_BIOS | PCI_PROBE_CONF1 | PCI_PROBE_CONF2;
+unsigned int pci_probe = PCI_PROBE_BIOS | PCI_PROBE_CONF1 | PCI_PROBE_CONF2 |
+				PCI_PROBE_MMCONF;
 
 int pcibios_last_bus = -1;
 struct pci_bus *pci_root_bus = NULL;
@@ -198,6 +199,12 @@ char * __devinit  pcibios_setup(char *st
 		return NULL;
 	}
 #endif
+#ifdef CONFIG_PCI_MMCONFIG
+	else if (!strcmp(str, "nommconf")) {
+		pci_probe &= ~PCI_PROBE_MMCONF;
+		return NULL;
+	}
+#endif
 	else if (!strcmp(str, "noacpi")) {
 		acpi_noirq_set();
 		return NULL;
--- diff/arch/i386/pci/fixup.c	2003-08-20 14:16:24.000000000 +0100
+++ source/arch/i386/pci/fixup.c	2004-02-23 13:56:37.000000000 +0000
@@ -188,22 +188,107 @@ static void __devinit pci_fixup_transpar
 }
 
 struct pci_fixup pcibios_fixups[] = {
-	{ PCI_FIXUP_HEADER,	PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82451NX,	pci_fixup_i450nx },
-	{ PCI_FIXUP_HEADER,	PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82454GX,	pci_fixup_i450gx },
-	{ PCI_FIXUP_HEADER,	PCI_VENDOR_ID_UMC,	PCI_DEVICE_ID_UMC_UM8886BF,	pci_fixup_umc_ide },
-	{ PCI_FIXUP_HEADER,	PCI_VENDOR_ID_SI,	PCI_DEVICE_ID_SI_5513,		pci_fixup_ide_trash },
-	{ PCI_FIXUP_HEADER,	PCI_ANY_ID,		PCI_ANY_ID,			pci_fixup_ide_bases },
-	{ PCI_FIXUP_HEADER,	PCI_VENDOR_ID_SI,	PCI_DEVICE_ID_SI_5597,		pci_fixup_latency },
-	{ PCI_FIXUP_HEADER,	PCI_VENDOR_ID_SI,	PCI_DEVICE_ID_SI_5598,		pci_fixup_latency },
- 	{ PCI_FIXUP_HEADER,	PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82371AB_3,	pci_fixup_piix4_acpi },
- 	{ PCI_FIXUP_HEADER,	PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82801CA_10,	pci_fixup_ide_trash },
- 	{ PCI_FIXUP_HEADER,	PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82801CA_11,	pci_fixup_ide_trash },
- 	{ PCI_FIXUP_HEADER,	PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82801DB_9,	pci_fixup_ide_trash },
-	{ PCI_FIXUP_HEADER,	PCI_VENDOR_ID_VIA,	PCI_DEVICE_ID_VIA_8363_0,	pci_fixup_via_northbridge_bug },
-	{ PCI_FIXUP_HEADER,	PCI_VENDOR_ID_VIA,	PCI_DEVICE_ID_VIA_8622,	        pci_fixup_via_northbridge_bug },
-	{ PCI_FIXUP_HEADER,	PCI_VENDOR_ID_VIA,	PCI_DEVICE_ID_VIA_8361,	        pci_fixup_via_northbridge_bug },
-	{ PCI_FIXUP_HEADER,	PCI_VENDOR_ID_VIA,	PCI_DEVICE_ID_VIA_8367_0,	pci_fixup_via_northbridge_bug },
-	{ PCI_FIXUP_HEADER,	PCI_VENDOR_ID_NCR,	PCI_DEVICE_ID_NCR_53C810,	pci_fixup_ncr53c810 },
-	{ PCI_FIXUP_HEADER,	PCI_VENDOR_ID_INTEL,	PCI_ANY_ID,			pci_fixup_transparent_bridge },
-	{ 0 }
+	{
+		.pass		= PCI_FIXUP_HEADER,
+		.vendor		= PCI_VENDOR_ID_INTEL,
+		.device		= PCI_DEVICE_ID_INTEL_82451NX,
+		.hook		= pci_fixup_i450nx
+	},
+	{
+		.pass		= PCI_FIXUP_HEADER,
+		.vendor		= PCI_VENDOR_ID_INTEL,
+		.device		= PCI_DEVICE_ID_INTEL_82454GX,
+		.hook		= pci_fixup_i450gx
+	},
+	{
+		.pass		= PCI_FIXUP_HEADER,
+		.vendor		= PCI_VENDOR_ID_UMC,
+		.device		= PCI_DEVICE_ID_UMC_UM8886BF,
+		.hook		= pci_fixup_umc_ide
+	},
+	{
+		.pass		= PCI_FIXUP_HEADER,
+		.vendor		= PCI_VENDOR_ID_SI,
+		.device		= PCI_DEVICE_ID_SI_5513,
+		.hook		= pci_fixup_ide_trash
+	},
+	{
+		.pass		= PCI_FIXUP_HEADER,
+		.vendor		= PCI_ANY_ID,
+		.device		= PCI_ANY_ID,
+		.hook		= pci_fixup_ide_bases
+	},
+	{
+		.pass		= PCI_FIXUP_HEADER,
+		.vendor		= PCI_VENDOR_ID_SI,
+		.device		= PCI_DEVICE_ID_SI_5597,
+		.hook		= pci_fixup_latency
+	},
+	{
+		.pass		= PCI_FIXUP_HEADER,
+		.vendor		= PCI_VENDOR_ID_SI,
+		.device		= PCI_DEVICE_ID_SI_5598,
+		.hook		= pci_fixup_latency
+	},
+ 	{
+		.pass		= PCI_FIXUP_HEADER,
+		.vendor		= PCI_VENDOR_ID_INTEL,
+		.device		= PCI_DEVICE_ID_INTEL_82371AB_3,
+		.hook		= pci_fixup_piix4_acpi
+	},
+ 	{
+		.pass		= PCI_FIXUP_HEADER,
+		.vendor		= PCI_VENDOR_ID_INTEL,
+		.device		= PCI_DEVICE_ID_INTEL_82801CA_10,
+		.hook		= pci_fixup_ide_trash
+	},
+ 	{
+		.pass		= PCI_FIXUP_HEADER,
+		.vendor		= PCI_VENDOR_ID_INTEL,
+		.device		= PCI_DEVICE_ID_INTEL_82801CA_11,
+		.hook		= pci_fixup_ide_trash
+	},
+ 	{
+		.pass		= PCI_FIXUP_HEADER,
+		.vendor		= PCI_VENDOR_ID_INTEL,
+		.device		= PCI_DEVICE_ID_INTEL_82801DB_9,
+		.hook		= pci_fixup_ide_trash
+	},
+	{
+		.pass		= PCI_FIXUP_HEADER,
+		.vendor		= PCI_VENDOR_ID_VIA,
+		.device		= PCI_DEVICE_ID_VIA_8363_0,
+		.hook		= pci_fixup_via_northbridge_bug
+	},
+	{
+		.pass		= PCI_FIXUP_HEADER,
+		.vendor		= PCI_VENDOR_ID_VIA,
+		.device		= PCI_DEVICE_ID_VIA_8622,
+		.hook		= pci_fixup_via_northbridge_bug
+	},
+	{
+		.pass		= PCI_FIXUP_HEADER,
+		.vendor		= PCI_VENDOR_ID_VIA,
+		.device		= PCI_DEVICE_ID_VIA_8361,
+		.hook		= pci_fixup_via_northbridge_bug
+	},
+	{
+		.pass		= PCI_FIXUP_HEADER,
+		.vendor		= PCI_VENDOR_ID_VIA,
+		.device		= PCI_DEVICE_ID_VIA_8367_0,
+		.hook		= pci_fixup_via_northbridge_bug
+	},
+	{
+		.pass		= PCI_FIXUP_HEADER,
+		.vendor		= PCI_VENDOR_ID_NCR,
+		.device		= PCI_DEVICE_ID_NCR_53C810,
+		.hook		= pci_fixup_ncr53c810
+	},
+	{
+		.pass		= PCI_FIXUP_HEADER,
+		.vendor		= PCI_VENDOR_ID_INTEL,
+		.device		= PCI_ANY_ID,
+		.hook		= pci_fixup_transparent_bridge
+	},
+	{ .pass = 0 }
 };
--- diff/arch/i386/pci/pci.h	2004-02-09 10:36:07.000000000 +0000
+++ source/arch/i386/pci/pci.h	2004-02-23 13:56:37.000000000 +0000
@@ -15,6 +15,9 @@
 #define PCI_PROBE_BIOS		0x0001
 #define PCI_PROBE_CONF1		0x0002
 #define PCI_PROBE_CONF2		0x0004
+#define PCI_PROBE_MMCONF	0x0008
+#define PCI_PROBE_MASK		0x000f
+
 #define PCI_NO_SORT		0x0100
 #define PCI_BIOS_SORT		0x0200
 #define PCI_NO_CHECKS		0x0400
--- diff/arch/ia64/Kconfig	2004-02-09 10:36:07.000000000 +0000
+++ source/arch/ia64/Kconfig	2004-02-23 13:56:37.000000000 +0000
@@ -245,6 +245,12 @@ config IA64_MCA
 	  Say Y here to enable machine check support for IA-64.  If you're
 	  unsure, answer Y.
 
+config IA64_CYCLONE
+	bool "Support Cyclone(EXA) Time Source"
+	help
+		Say Y here to enable support for IBM EXA Cyclone time source.
+		If you're unsure, answer N.
+
 config PM
 	bool "Power Management support"
 	depends on IA64_GENERIC || IA64_DIG || IA64_HP_ZX1
@@ -439,24 +445,6 @@ config PCI_DOMAINS
 
 source "drivers/pci/Kconfig"
 
-config HOTPLUG
-	bool "Support for hot-pluggable devices"
-	help
-	  Say Y here if you want to plug devices into your computer while
-	  the system is running, and be able to use them quickly.  In many
-	  cases, the devices can likewise be unplugged at any time too.
-
-	  One well known example of this is PCMCIA- or PC-cards, credit-card
-	  size devices such as network cards, modems or hard drives which are
-	  plugged into slots found on all modern laptop computers.  Another
-	  example, used on modern desktops as well as laptops, is USB.
-
-	  Enable HOTPLUG and KMOD, and build a modular kernel.  Get agent
-	  software (at <http://linux-hotplug.sourceforge.net/>) and install it.
-	  Then your kernel will automatically call out to a user mode "policy
-	  agent" (/sbin/hotplug) to load modules and set up software needed
-	  to use devices as you hotplug them.
-
 source "drivers/pci/hotplug/Kconfig"
 
 source "drivers/pcmcia/Kconfig"
@@ -534,6 +522,13 @@ config BLK_DEV_RAM_SIZE
 	depends on BLK_DEV_RAM
 	default "4096"
 
+config LOCKMETER
+       bool "Kernel lock metering"
+       depends on SMP
+       help
+         Say Y to enable kernel lock metering, which adds overhead to SMP locks,
+         but allows you to see various statistics using the lockstat command.
+
 endmenu
 
 source "fs/Kconfig"
@@ -661,7 +656,11 @@ config DEBUG_INFO
 	  debugging info resulting in a larger kernel image.
 	  Say Y here only if you plan to use gdb to debug the kernel.
 	  If you don't debug the kernel, you can say N.
-	  
+
+config SYSVIPC_COMPAT
+	bool
+	depends on COMPAT && SYSVIPC
+	default y
 endmenu
 
 source "security/Kconfig"
--- diff/arch/ia64/hp/sim/simeth.c	2003-08-20 14:16:08.000000000 +0100
+++ source/arch/ia64/hp/sim/simeth.c	2004-02-23 13:56:37.000000000 +0000
@@ -224,7 +224,7 @@ simeth_probe1(void)
 
 	err = register_netdev(dev);
 	if (err) {
-		kfree(dev);
+		free_netdev(dev);
 		return err;
 	}
 
--- diff/arch/ia64/ia32/ia32_ioctl.c	2003-10-09 09:47:33.000000000 +0100
+++ source/arch/ia64/ia32/ia32_ioctl.c	2004-02-23 13:56:37.000000000 +0000
@@ -8,6 +8,7 @@
  */
 
 #include <linux/signal.h>	/* argh, msdos_fs.h isn't self-contained... */
+#include <linux/syscalls.h>
 #include "ia32priv.h"
   
 #define	INCLUDES
@@ -26,8 +27,6 @@
 	_ret;						\
 })
 
-asmlinkage long sys_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg);
-
 #define CODE
 #include "compat_ioctl.c"
 
--- diff/arch/ia64/ia32/ia32_signal.c	2003-11-25 15:24:57.000000000 +0000
+++ source/arch/ia64/ia32/ia32_signal.c	2004-02-23 13:56:37.000000000 +0000
@@ -20,6 +20,7 @@
 #include <linux/smp.h>
 #include <linux/smp_lock.h>
 #include <linux/stddef.h>
+#include <linux/syscalls.h>
 #include <linux/unistd.h>
 #include <linux/wait.h>
 #include <linux/compat.h>
@@ -550,9 +551,6 @@ sys32_rt_sigaction (int sig, struct siga
 }
 
 
-extern asmlinkage long sys_rt_sigprocmask (int how, sigset_t *set, sigset_t *oset,
-					   size_t sigsetsize);
-
 asmlinkage long
 sys32_rt_sigprocmask (int how, compat_sigset_t *set, compat_sigset_t *oset, unsigned int sigsetsize)
 {
@@ -584,8 +582,6 @@ asmlinkage long
 sys32_rt_sigtimedwait (compat_sigset_t *uthese, siginfo_t32 *uinfo,
 		struct compat_timespec *uts, unsigned int sigsetsize)
 {
-	extern asmlinkage long sys_rt_sigtimedwait (const sigset_t *, siginfo_t *,
-						    const struct timespec *, size_t);
 	extern int copy_siginfo_to_user32 (siginfo_t32 *, siginfo_t *);
 	mm_segment_t old_fs = get_fs();
 	struct timespec t;
@@ -611,7 +607,6 @@ sys32_rt_sigtimedwait (compat_sigset_t *
 asmlinkage long
 sys32_rt_sigqueueinfo (int pid, int sig, siginfo_t32 *uinfo)
 {
-	extern asmlinkage long sys_rt_sigqueueinfo (int, int, siginfo_t *);
 	extern int copy_siginfo_from_user32 (siginfo_t *to, siginfo_t32 *from);
 	mm_segment_t old_fs = get_fs();
 	siginfo_t info;
--- diff/arch/ia64/ia32/sys_ia32.c	2004-02-09 10:36:07.000000000 +0000
+++ source/arch/ia64/ia32/sys_ia32.c	2004-02-23 13:56:37.000000000 +0000
@@ -15,6 +15,7 @@
 
 #include <linux/config.h>
 #include <linux/kernel.h>
+#include <linux/syscalls.h>
 #include <linux/sysctl.h>
 #include <linux/sched.h>
 #include <linux/fs.h>
@@ -55,6 +56,7 @@
 #include <asm/semaphore.h>
 #include <asm/types.h>
 #include <asm/uaccess.h>
+#include <asm/unistd.h>
 
 #include "ia32priv.h"
 
@@ -81,16 +83,9 @@
 #define high2lowuid(uid) ((uid) > 65535 ? 65534 : (uid))
 #define high2lowgid(gid) ((gid) > 65535 ? 65534 : (gid))
 
-extern asmlinkage long sys_execve (char *, char **, char **, struct pt_regs *);
-extern asmlinkage long sys_mprotect (unsigned long, size_t, unsigned long);
-extern asmlinkage long sys_munmap (unsigned long, size_t);
 extern unsigned long arch_get_unmapped_area (struct file *, unsigned long, unsigned long,
 					     unsigned long, unsigned long);
 
-/* forward declaration: */
-asmlinkage long sys32_mprotect (unsigned int, unsigned int, int);
-asmlinkage unsigned long sys_brk(unsigned long);
-
 /*
  * Anything that modifies or inspects ia32 user virtual memory must hold this semaphore
  * while doing so.
@@ -949,9 +944,6 @@ sys32_old_select (struct sel_arg_struct 
 			    (struct compat_timeval *) A(a.tvp));
 }
 
-asmlinkage ssize_t sys_readv (unsigned long,const struct iovec *,unsigned long);
-asmlinkage ssize_t sys_writev (unsigned long,const struct iovec *,unsigned long);
-
 static struct iovec *
 get_compat_iovec (struct compat_iovec *iov32, struct iovec *iov_buf, u32 count, int type)
 {
@@ -1031,143 +1023,6 @@ sys32_writev (int fd, struct compat_iove
 	return ret;
 }
 
-/*
- * sys32_ipc() is the de-multiplexer for the SysV IPC calls in 32bit emulation..
- *
- * This is really horribly ugly.
- */
-
-struct msgbuf32 { s32 mtype; char mtext[1]; };
-
-struct ipc_perm32 {
-	key_t key;
-	compat_uid_t uid;
-	compat_gid_t gid;
-	compat_uid_t cuid;
-	compat_gid_t cgid;
-	compat_mode_t mode;
-	unsigned short seq;
-};
-
-struct ipc64_perm32 {
-	key_t key;
-	compat_uid32_t uid;
-	compat_gid32_t gid;
-	compat_uid32_t cuid;
-	compat_gid32_t cgid;
-	compat_mode_t mode;
-	unsigned short __pad1;
-	unsigned short seq;
-	unsigned short __pad2;
-	unsigned int unused1;
-	unsigned int unused2;
-};
-
-struct semid_ds32 {
-	struct ipc_perm32 sem_perm;               /* permissions .. see ipc.h */
-	compat_time_t   sem_otime;              /* last semop time */
-	compat_time_t   sem_ctime;              /* last change time */
-	u32 sem_base;              /* ptr to first semaphore in array */
-	u32 sem_pending;          /* pending operations to be processed */
-	u32 sem_pending_last;    /* last pending operation */
-	u32 undo;                  /* undo requests on this array */
-	unsigned short  sem_nsems;              /* no. of semaphores in array */
-};
-
-struct semid64_ds32 {
-	struct ipc64_perm32 sem_perm;
-	compat_time_t   sem_otime;
-	unsigned int __unused1;
-	compat_time_t   sem_ctime;
-	unsigned int __unused2;
-	unsigned int sem_nsems;
-	unsigned int __unused3;
-	unsigned int __unused4;
-};
-
-struct msqid_ds32 {
-	struct ipc_perm32 msg_perm;
-	u32 msg_first;
-	u32 msg_last;
-	compat_time_t   msg_stime;
-	compat_time_t   msg_rtime;
-	compat_time_t   msg_ctime;
-	u32 wwait;
-	u32 rwait;
-	unsigned short msg_cbytes;
-	unsigned short msg_qnum;
-	unsigned short msg_qbytes;
-	compat_ipc_pid_t msg_lspid;
-	compat_ipc_pid_t msg_lrpid;
-};
-
-struct msqid64_ds32 {
-	struct ipc64_perm32 msg_perm;
-	compat_time_t   msg_stime;
-	unsigned int __unused1;
-	compat_time_t   msg_rtime;
-	unsigned int __unused2;
-	compat_time_t   msg_ctime;
-	unsigned int __unused3;
-	unsigned int msg_cbytes;
-	unsigned int msg_qnum;
-	unsigned int msg_qbytes;
-	compat_pid_t msg_lspid;
-	compat_pid_t msg_lrpid;
-	unsigned int __unused4;
-	unsigned int __unused5;
-};
-
-struct shmid_ds32 {
-	struct ipc_perm32 shm_perm;
-	int shm_segsz;
-	compat_time_t   shm_atime;
-	compat_time_t   shm_dtime;
-	compat_time_t   shm_ctime;
-	compat_ipc_pid_t shm_cpid;
-	compat_ipc_pid_t shm_lpid;
-	unsigned short shm_nattch;
-};
-
-struct shmid64_ds32 {
-	struct ipc64_perm32 shm_perm;
-	compat_size_t shm_segsz;
-	compat_time_t   shm_atime;
-	unsigned int __unused1;
-	compat_time_t   shm_dtime;
-	unsigned int __unused2;
-	compat_time_t   shm_ctime;
-	unsigned int __unused3;
-	compat_pid_t shm_cpid;
-	compat_pid_t shm_lpid;
-	unsigned int shm_nattch;
-	unsigned int __unused4;
-	unsigned int __unused5;
-};
-
-struct shminfo64_32 {
-	unsigned int shmmax;
-	unsigned int shmmin;
-	unsigned int shmmni;
-	unsigned int shmseg;
-	unsigned int shmall;
-	unsigned int __unused1;
-	unsigned int __unused2;
-	unsigned int __unused3;
-	unsigned int __unused4;
-};
-
-struct shm_info32 {
-	int used_ids;
-	u32 shm_tot, shm_rss, shm_swp;
-	u32 swap_attempts, swap_successes;
-};
-
-struct ipc_kludge {
-	u32 msgp;
-	s32 msgtyp;
-};
-
 #define SEMOP		 1
 #define SEMGET		 2
 #define SEMCTL		 3
@@ -1181,454 +1036,6 @@ struct ipc_kludge {
 #define SHMGET		23
 #define SHMCTL		24
 
-#define IPCOP_MASK(__x)	(1UL << (__x))
-
-static int
-ipc_parse_version32 (int *cmd)
-{
-	if (*cmd & IPC_64) {
-		*cmd ^= IPC_64;
-		return IPC_64;
-	} else {
-		return IPC_OLD;
-	}
-}
-
-static int
-semctl32 (int first, int second, int third, void *uptr)
-{
-	union semun fourth;
-	u32 pad;
-	int err = 0, err2;
-	struct semid64_ds s;
-	mm_segment_t old_fs;
-	int version = ipc_parse_version32(&third);
-
-	if (!uptr)
-		return -EINVAL;
-	if (get_user(pad, (u32 *)uptr))
-		return -EFAULT;
-	if (third == SETVAL)
-		fourth.val = (int)pad;
-	else
-		fourth.__pad = (void *)A(pad);
-	switch (third) {
-	      default:
-		err = -EINVAL;
-		break;
-
-	      case IPC_INFO:
-	      case IPC_RMID:
-	      case IPC_SET:
-	      case SEM_INFO:
-	      case GETVAL:
-	      case GETPID:
-	      case GETNCNT:
-	      case GETZCNT:
-	      case GETALL:
-	      case SETVAL:
-	      case SETALL:
-		err = sys_semctl(first, second, third, fourth);
-		break;
-
-	      case IPC_STAT:
-	      case SEM_STAT:
-		fourth.__pad = &s;
-		old_fs = get_fs();
-		set_fs(KERNEL_DS);
-		err = sys_semctl(first, second, third, fourth);
-		set_fs(old_fs);
-
-		if (version == IPC_64) {
-			struct semid64_ds32 *usp64 = (struct semid64_ds32 *) A(pad);
-
-			if (!access_ok(VERIFY_WRITE, usp64, sizeof(*usp64))) {
-				err = -EFAULT;
-				break;
-			}
-			err2 = __put_user(s.sem_perm.key, &usp64->sem_perm.key);
-			err2 |= __put_user(s.sem_perm.uid, &usp64->sem_perm.uid);
-			err2 |= __put_user(s.sem_perm.gid, &usp64->sem_perm.gid);
-			err2 |= __put_user(s.sem_perm.cuid, &usp64->sem_perm.cuid);
-			err2 |= __put_user(s.sem_perm.cgid, &usp64->sem_perm.cgid);
-			err2 |= __put_user(s.sem_perm.mode, &usp64->sem_perm.mode);
-			err2 |= __put_user(s.sem_perm.seq, &usp64->sem_perm.seq);
-			err2 |= __put_user(s.sem_otime, &usp64->sem_otime);
-			err2 |= __put_user(s.sem_ctime, &usp64->sem_ctime);
-			err2 |= __put_user(s.sem_nsems, &usp64->sem_nsems);
-		} else {
-			struct semid_ds32 *usp32 = (struct semid_ds32 *) A(pad);
-
-			if (!access_ok(VERIFY_WRITE, usp32, sizeof(*usp32))) {
-				err = -EFAULT;
-				break;
-			}
-			err2 = __put_user(s.sem_perm.key, &usp32->sem_perm.key);
-			err2 |= __put_user(s.sem_perm.uid, &usp32->sem_perm.uid);
-			err2 |= __put_user(s.sem_perm.gid, &usp32->sem_perm.gid);
-			err2 |= __put_user(s.sem_perm.cuid, &usp32->sem_perm.cuid);
-			err2 |= __put_user(s.sem_perm.cgid, &usp32->sem_perm.cgid);
-			err2 |= __put_user(s.sem_perm.mode, &usp32->sem_perm.mode);
-			err2 |= __put_user(s.sem_perm.seq, &usp32->sem_perm.seq);
-			err2 |= __put_user(s.sem_otime, &usp32->sem_otime);
-			err2 |= __put_user(s.sem_ctime, &usp32->sem_ctime);
-			err2 |= __put_user(s.sem_nsems, &usp32->sem_nsems);
-		}
-		if (err2)
-		    err = -EFAULT;
-		break;
-	}
-	return err;
-}
-
-static int
-do_sys32_msgsnd (int first, int second, int third, void *uptr)
-{
-	struct msgbuf *p = kmalloc(second + sizeof(struct msgbuf), GFP_USER);
-	struct msgbuf32 *up = (struct msgbuf32 *)uptr;
-	mm_segment_t old_fs;
-	int err;
-
-	if (!p)
-		return -ENOMEM;
-	err = get_user(p->mtype, &up->mtype);
-	err |= copy_from_user(p->mtext, &up->mtext, second);
-	if (err)
-		goto out;
-	old_fs = get_fs();
-	set_fs(KERNEL_DS);
-	err = sys_msgsnd(first, p, second, third);
-	set_fs(old_fs);
-  out:
-	kfree(p);
-	return err;
-}
-
-static int
-do_sys32_msgrcv (int first, int second, int msgtyp, int third, int version, void *uptr)
-{
-	struct msgbuf32 *up;
-	struct msgbuf *p;
-	mm_segment_t old_fs;
-	int err;
-
-	if (!version) {
-		struct ipc_kludge *uipck = (struct ipc_kludge *)uptr;
-		struct ipc_kludge ipck;
-
-		err = -EINVAL;
-		if (!uptr)
-			goto out;
-		err = -EFAULT;
-		if (copy_from_user(&ipck, uipck, sizeof(struct ipc_kludge)))
-			goto out;
-		uptr = (void *)A(ipck.msgp);
-		msgtyp = ipck.msgtyp;
-	}
-	err = -ENOMEM;
-	p = kmalloc(second + sizeof(struct msgbuf), GFP_USER);
-	if (!p)
-		goto out;
-	old_fs = get_fs();
-	set_fs(KERNEL_DS);
-	err = sys_msgrcv(first, p, second, msgtyp, third);
-	set_fs(old_fs);
-	if (err < 0)
-		goto free_then_out;
-	up = (struct msgbuf32 *)uptr;
-	if (put_user(p->mtype, &up->mtype) || copy_to_user(&up->mtext, p->mtext, err))
-		err = -EFAULT;
-free_then_out:
-	kfree(p);
-out:
-	return err;
-}
-
-static int
-msgctl32 (int first, int second, void *uptr)
-{
-	int err = -EINVAL, err2;
-	struct msqid64_ds m64;
-	struct msqid_ds32 *up32 = (struct msqid_ds32 *)uptr;
-	struct msqid64_ds32 *up64 = (struct msqid64_ds32 *)uptr;
-	mm_segment_t old_fs;
-	int version = ipc_parse_version32(&second);
-
-	switch (second) {
-	      case IPC_INFO:
-	      case IPC_RMID:
-	      case MSG_INFO:
-		err = sys_msgctl(first, second, (struct msqid_ds *)uptr);
-		break;
-
-	      case IPC_SET:
-		if (version == IPC_64) {
-			err = get_user(m64.msg_perm.uid, &up64->msg_perm.uid);
-			err |= get_user(m64.msg_perm.gid, &up64->msg_perm.gid);
-			err |= get_user(m64.msg_perm.mode, &up64->msg_perm.mode);
-			err |= get_user(m64.msg_qbytes, &up64->msg_qbytes);
-		} else {
-			err = get_user(m64.msg_perm.uid, &up32->msg_perm.uid);
-			err |= get_user(m64.msg_perm.gid, &up32->msg_perm.gid);
-			err |= get_user(m64.msg_perm.mode, &up32->msg_perm.mode);
-			err |= get_user(m64.msg_qbytes, &up32->msg_qbytes);
-		}
-		if (err)
-			break;
-		old_fs = get_fs();
-		set_fs(KERNEL_DS);
-		err = sys_msgctl(first, second, (struct msqid_ds *)&m64);
-		set_fs(old_fs);
-		break;
-
-	      case IPC_STAT:
-	      case MSG_STAT:
-		old_fs = get_fs();
-		set_fs(KERNEL_DS);
-		err = sys_msgctl(first, second, (struct msqid_ds *)&m64);
-		set_fs(old_fs);
-
-		if (version == IPC_64) {
-			if (!access_ok(VERIFY_WRITE, up64, sizeof(*up64))) {
-				err = -EFAULT;
-				break;
-			}
-			err2 = __put_user(m64.msg_perm.key, &up64->msg_perm.key);
-			err2 |= __put_user(m64.msg_perm.uid, &up64->msg_perm.uid);
-			err2 |= __put_user(m64.msg_perm.gid, &up64->msg_perm.gid);
-			err2 |= __put_user(m64.msg_perm.cuid, &up64->msg_perm.cuid);
-			err2 |= __put_user(m64.msg_perm.cgid, &up64->msg_perm.cgid);
-			err2 |= __put_user(m64.msg_perm.mode, &up64->msg_perm.mode);
-			err2 |= __put_user(m64.msg_perm.seq, &up64->msg_perm.seq);
-			err2 |= __put_user(m64.msg_stime, &up64->msg_stime);
-			err2 |= __put_user(m64.msg_rtime, &up64->msg_rtime);
-			err2 |= __put_user(m64.msg_ctime, &up64->msg_ctime);
-			err2 |= __put_user(m64.msg_cbytes, &up64->msg_cbytes);
-			err2 |= __put_user(m64.msg_qnum, &up64->msg_qnum);
-			err2 |= __put_user(m64.msg_qbytes, &up64->msg_qbytes);
-			err2 |= __put_user(m64.msg_lspid, &up64->msg_lspid);
-			err2 |= __put_user(m64.msg_lrpid, &up64->msg_lrpid);
-			if (err2)
-				err = -EFAULT;
-		} else {
-			if (!access_ok(VERIFY_WRITE, up32, sizeof(*up32))) {
-				err = -EFAULT;
-				break;
-			}
-			err2 = __put_user(m64.msg_perm.key, &up32->msg_perm.key);
-			err2 |= __put_user(m64.msg_perm.uid, &up32->msg_perm.uid);
-			err2 |= __put_user(m64.msg_perm.gid, &up32->msg_perm.gid);
-			err2 |= __put_user(m64.msg_perm.cuid, &up32->msg_perm.cuid);
-			err2 |= __put_user(m64.msg_perm.cgid, &up32->msg_perm.cgid);
-			err2 |= __put_user(m64.msg_perm.mode, &up32->msg_perm.mode);
-			err2 |= __put_user(m64.msg_perm.seq, &up32->msg_perm.seq);
-			err2 |= __put_user(m64.msg_stime, &up32->msg_stime);
-			err2 |= __put_user(m64.msg_rtime, &up32->msg_rtime);
-			err2 |= __put_user(m64.msg_ctime, &up32->msg_ctime);
-			err2 |= __put_user(m64.msg_cbytes, &up32->msg_cbytes);
-			err2 |= __put_user(m64.msg_qnum, &up32->msg_qnum);
-			err2 |= __put_user(m64.msg_qbytes, &up32->msg_qbytes);
-			err2 |= __put_user(m64.msg_lspid, &up32->msg_lspid);
-			err2 |= __put_user(m64.msg_lrpid, &up32->msg_lrpid);
-			if (err2)
-				err = -EFAULT;
-		}
-		break;
-	}
-	return err;
-}
-
-static int
-shmat32 (int first, int second, int third, int version, void *uptr)
-{
-	unsigned long raddr;
-	u32 *uaddr = (u32 *)A((u32)third);
-	int err;
-
-	if (version == 1)
-		return -EINVAL;	/* iBCS2 emulator entry point: unsupported */
-	err = sys_shmat(first, uptr, second, &raddr);
-	if (err)
-		return err;
-	return put_user(raddr, uaddr);
-}
-
-static int
-shmctl32 (int first, int second, void *uptr)
-{
-	int err = -EFAULT, err2;
-
-	struct shmid64_ds s64;
-	struct shmid_ds32 *up32 = (struct shmid_ds32 *)uptr;
-	struct shmid64_ds32 *up64 = (struct shmid64_ds32 *)uptr;
-	mm_segment_t old_fs;
-	struct shm_info32 *uip = (struct shm_info32 *)uptr;
-	struct shm_info si;
-	int version = ipc_parse_version32(&second);
-	struct shminfo64 smi;
-	struct shminfo *usi32 = (struct shminfo *) uptr;
-	struct shminfo64_32 *usi64 = (struct shminfo64_32 *) uptr;
-
-	switch (second) {
-	      case IPC_INFO:
-		old_fs = get_fs();
-		set_fs(KERNEL_DS);
-		err = sys_shmctl(first, second, (struct shmid_ds *)&smi);
-		set_fs(old_fs);
-
-		if (version == IPC_64) {
-			if (!access_ok(VERIFY_WRITE, usi64, sizeof(*usi64))) {
-				err = -EFAULT;
-				break;
-			}
-			err2 = __put_user(smi.shmmax, &usi64->shmmax);
-			err2 |= __put_user(smi.shmmin, &usi64->shmmin);
-			err2 |= __put_user(smi.shmmni, &usi64->shmmni);
-			err2 |= __put_user(smi.shmseg, &usi64->shmseg);
-			err2 |= __put_user(smi.shmall, &usi64->shmall);
-		} else {
-			if (!access_ok(VERIFY_WRITE, usi32, sizeof(*usi32))) {
-				err = -EFAULT;
-				break;
-			}
-			err2 = __put_user(smi.shmmax, &usi32->shmmax);
-			err2 |= __put_user(smi.shmmin, &usi32->shmmin);
-			err2 |= __put_user(smi.shmmni, &usi32->shmmni);
-			err2 |= __put_user(smi.shmseg, &usi32->shmseg);
-			err2 |= __put_user(smi.shmall, &usi32->shmall);
-		}
-		if (err2)
-			err = -EFAULT;
-		break;
-
-	      case IPC_RMID:
-	      case SHM_LOCK:
-	      case SHM_UNLOCK:
-		err = sys_shmctl(first, second, (struct shmid_ds *)uptr);
-		break;
-
-	      case IPC_SET:
-		if (version == IPC_64) {
-			err = get_user(s64.shm_perm.uid, &up64->shm_perm.uid);
-			err |= get_user(s64.shm_perm.gid, &up64->shm_perm.gid);
-			err |= get_user(s64.shm_perm.mode, &up64->shm_perm.mode);
-		} else {
-			err = get_user(s64.shm_perm.uid, &up32->shm_perm.uid);
-			err |= get_user(s64.shm_perm.gid, &up32->shm_perm.gid);
-			err |= get_user(s64.shm_perm.mode, &up32->shm_perm.mode);
-		}
-		if (err)
-			break;
-		old_fs = get_fs();
-		set_fs(KERNEL_DS);
-		err = sys_shmctl(first, second, (struct shmid_ds *)&s64);
-		set_fs(old_fs);
-		break;
-
-	      case IPC_STAT:
-	      case SHM_STAT:
-		old_fs = get_fs();
-		set_fs(KERNEL_DS);
-		err = sys_shmctl(first, second, (struct shmid_ds *)&s64);
-		set_fs(old_fs);
-		if (err < 0)
-			break;
-		if (version == IPC_64) {
-			if (!access_ok(VERIFY_WRITE, up64, sizeof(*up64))) {
-				err = -EFAULT;
-				break;
-			}
-			err2 = __put_user(s64.shm_perm.key, &up64->shm_perm.key);
-			err2 |= __put_user(s64.shm_perm.uid, &up64->shm_perm.uid);
-			err2 |= __put_user(s64.shm_perm.gid, &up64->shm_perm.gid);
-			err2 |= __put_user(s64.shm_perm.cuid, &up64->shm_perm.cuid);
-			err2 |= __put_user(s64.shm_perm.cgid, &up64->shm_perm.cgid);
-			err2 |= __put_user(s64.shm_perm.mode, &up64->shm_perm.mode);
-			err2 |= __put_user(s64.shm_perm.seq, &up64->shm_perm.seq);
-			err2 |= __put_user(s64.shm_atime, &up64->shm_atime);
-			err2 |= __put_user(s64.shm_dtime, &up64->shm_dtime);
-			err2 |= __put_user(s64.shm_ctime, &up64->shm_ctime);
-			err2 |= __put_user(s64.shm_segsz, &up64->shm_segsz);
-			err2 |= __put_user(s64.shm_nattch, &up64->shm_nattch);
-			err2 |= __put_user(s64.shm_cpid, &up64->shm_cpid);
-			err2 |= __put_user(s64.shm_lpid, &up64->shm_lpid);
-		} else {
-			if (!access_ok(VERIFY_WRITE, up32, sizeof(*up32))) {
-				err = -EFAULT;
-				break;
-			}
-			err2 = __put_user(s64.shm_perm.key, &up32->shm_perm.key);
-			err2 |= __put_user(s64.shm_perm.uid, &up32->shm_perm.uid);
-			err2 |= __put_user(s64.shm_perm.gid, &up32->shm_perm.gid);
-			err2 |= __put_user(s64.shm_perm.cuid, &up32->shm_perm.cuid);
-			err2 |= __put_user(s64.shm_perm.cgid, &up32->shm_perm.cgid);
-			err2 |= __put_user(s64.shm_perm.mode, &up32->shm_perm.mode);
-			err2 |= __put_user(s64.shm_perm.seq, &up32->shm_perm.seq);
-			err2 |= __put_user(s64.shm_atime, &up32->shm_atime);
-			err2 |= __put_user(s64.shm_dtime, &up32->shm_dtime);
-			err2 |= __put_user(s64.shm_ctime, &up32->shm_ctime);
-			err2 |= __put_user(s64.shm_segsz, &up32->shm_segsz);
-			err2 |= __put_user(s64.shm_nattch, &up32->shm_nattch);
-			err2 |= __put_user(s64.shm_cpid, &up32->shm_cpid);
-			err2 |= __put_user(s64.shm_lpid, &up32->shm_lpid);
-		}
-		if (err2)
-			err = -EFAULT;
-		break;
-
-	      case SHM_INFO:
-		old_fs = get_fs();
-		set_fs(KERNEL_DS);
-		err = sys_shmctl(first, second, (void *)&si);
-		set_fs(old_fs);
-		if (err < 0)
-			break;
-
-		if (!access_ok(VERIFY_WRITE, uip, sizeof(*uip))) {
-			err = -EFAULT;
-			break;
-		}
-		err2 = __put_user(si.used_ids, &uip->used_ids);
-		err2 |= __put_user(si.shm_tot, &uip->shm_tot);
-		err2 |= __put_user(si.shm_rss, &uip->shm_rss);
-		err2 |= __put_user(si.shm_swp, &uip->shm_swp);
-		err2 |= __put_user(si.swap_attempts, &uip->swap_attempts);
-		err2 |= __put_user(si.swap_successes, &uip->swap_successes);
-		if (err2)
-			err = -EFAULT;
-		break;
-
-	}
-	return err;
-}
-
-extern int sem_ctls[];
-#define sc_semopm	(sem_ctls[2])
-
-static long
-semtimedop32(int semid, struct sembuf *tsops, int nsops,
-	     struct compat_timespec *timeout32)
-{
-	struct timespec t;
-	mm_segment_t oldfs;
-	long ret;
-
-	/* parameter checking precedence should mirror sys_semtimedop() */
-	if (nsops < 1 || semid < 0)
-		return -EINVAL;
-	if (nsops > sc_semopm)
-		return -E2BIG;
-	if (!access_ok(VERIFY_READ, tsops, nsops * sizeof(struct sembuf)) ||
-	    get_compat_timespec(&t, timeout32))
-		return -EFAULT;
-
-	oldfs = get_fs();
-	set_fs(KERNEL_DS);
-	ret = sys_semtimedop(semid, tsops, nsops, &t);
-	set_fs(oldfs);
-	return ret;
-}
-
 asmlinkage long
 sys32_ipc(u32 call, int first, int second, int third, u32 ptr, u32 fifth)
 {
@@ -1640,36 +1047,36 @@ sys32_ipc(u32 call, int first, int secon
 	switch (call) {
 	      case SEMTIMEDOP:
 		if (fifth)
-			return semtimedop32(first, (struct sembuf *)AA(ptr),
-				second, (struct compat_timespec *)AA(fifth));
+			return compat_sys_semtimedop(first, compat_ptr(ptr),
+				second, compat_ptr(fifth));
 		/* else fall through for normal semop() */
 	      case SEMOP:
 		/* struct sembuf is the same on 32 and 64bit :)) */
-		return sys_semtimedop(first, (struct sembuf *)AA(ptr), second,
+		return sys_semtimedop(first, compat_ptr(ptr), second,
 				      NULL);
 	      case SEMGET:
 		return sys_semget(first, second, third);
 	      case SEMCTL:
-		return semctl32(first, second, third, (void *)AA(ptr));
+		return compat_sys_semctl(first, second, third, compat_ptr(ptr));
 
 	      case MSGSND:
-		return do_sys32_msgsnd(first, second, third, (void *)AA(ptr));
+		return compat_sys_msgsnd(first, second, third, compat_ptr(ptr));
 	      case MSGRCV:
-		return do_sys32_msgrcv(first, second, fifth, third, version, (void *)AA(ptr));
+		return compat_sys_msgrcv(first, second, fifth, third, version, compat_ptr(ptr));
 	      case MSGGET:
 		return sys_msgget((key_t) first, second);
 	      case MSGCTL:
-		return msgctl32(first, second, (void *)AA(ptr));
+		return compat_sys_msgctl(first, second, compat_ptr(ptr));
 
 	      case SHMAT:
-		return shmat32(first, second, third, version, (void *)AA(ptr));
+		return compat_sys_shmat(first, second, third, version, compat_ptr(ptr));
 		break;
 	      case SHMDT:
-		return sys_shmdt((char *)AA(ptr));
+		return sys_shmdt(compat_ptr(ptr));
 	      case SHMGET:
 		return sys_shmget(first, second, third);
 	      case SHMCTL:
-		return shmctl32(first, second, (void *)AA(ptr));
+		return compat_sys_shmctl(first, second, compat_ptr(ptr));
 
 	      default:
 		return -ENOSYS;
@@ -2023,9 +1430,6 @@ restore_ia32_fpxstate (struct task_struc
 	return 0;
 }
 
-extern asmlinkage long sys_ptrace (long, pid_t, unsigned long, unsigned long, long, long, long,
-				   long, long);
-
 /*
  *  Note that the IA32 version of `ptrace' calls the IA64 routine for
  *    many of the requests.  This will only work for requests that do
@@ -2284,8 +1688,6 @@ sys32_pause (void)
 	return -ERESTARTNOHAND;
 }
 
-asmlinkage long sys_msync (unsigned long start, size_t len, int flags);
-
 asmlinkage int
 sys32_msync (unsigned int start, unsigned int len, int flags)
 {
@@ -2307,8 +1709,6 @@ struct sysctl32 {
 	unsigned int	__unused[4];
 };
 
-extern asmlinkage long sys_sysctl(struct __sysctl_args *args);
-
 asmlinkage long
 sys32_sysctl (struct sysctl32 *args)
 {
@@ -2358,7 +1758,6 @@ sys32_sysctl (struct sysctl32 *args)
 asmlinkage long
 sys32_newuname (struct new_utsname *name)
 {
-	extern asmlinkage long sys_newuname(struct new_utsname * name);
 	int ret = sys_newuname(name);
 
 	if (!ret)
@@ -2367,8 +1766,6 @@ sys32_newuname (struct new_utsname *name
 	return ret;
 }
 
-extern asmlinkage long sys_getresuid (uid_t *ruid, uid_t *euid, uid_t *suid);
-
 asmlinkage long
 sys32_getresuid16 (u16 *ruid, u16 *euid, u16 *suid)
 {
@@ -2385,8 +1782,6 @@ sys32_getresuid16 (u16 *ruid, u16 *euid,
 	return ret;
 }
 
-extern asmlinkage long sys_getresgid (gid_t *rgid, gid_t *egid, gid_t *sgid);
-
 asmlinkage long
 sys32_getresgid16 (u16 *rgid, u16 *egid, u16 *sgid)
 {
@@ -2407,65 +1802,100 @@ sys32_getresgid16 (u16 *rgid, u16 *egid,
 asmlinkage long
 sys32_lseek (unsigned int fd, int offset, unsigned int whence)
 {
-	extern off_t sys_lseek (unsigned int fd, off_t offset, unsigned int origin);
-
 	/* Sign-extension of "offset" is important here... */
 	return sys_lseek(fd, offset, whence);
 }
 
-extern asmlinkage long sys_getgroups (int gidsetsize, gid_t *grouplist);
+static int
+groups16_to_user(short *grouplist, struct group_info *group_info)
+{
+	int i;
+	short group;
+
+	for (i = 0; i < group_info->ngroups; i++) {
+		group = (short)GROUP_AT(group_info, i);
+		if (put_user(group, grouplist+i))
+			return -EFAULT;
+	}
+
+	return 0;
+}
+
+static int
+groups16_from_user(struct group_info *group_info, short *grouplist)
+{
+	int i;
+	short group;
+
+	for (i = 0; i < group_info->ngroups; i++) {
+		if (get_user(group, grouplist+i))
+			return  -EFAULT;
+		GROUP_AT(group_info, i) = (gid_t)group;
+	}
+
+	return 0;
+}
 
 asmlinkage long
 sys32_getgroups16 (int gidsetsize, short *grouplist)
 {
-	mm_segment_t old_fs = get_fs();
-	gid_t gl[NGROUPS];
-	int ret, i;
+	int i;
 
-	set_fs(KERNEL_DS);
-	ret = sys_getgroups(gidsetsize, gl);
-	set_fs(old_fs);
+	if (gidsetsize < 0)
+		return -EINVAL;
 
-	if (gidsetsize && ret > 0 && ret <= NGROUPS)
-		for (i = 0; i < ret; i++, grouplist++)
-			if (put_user(gl[i], grouplist))
-				return -EFAULT;
-	return ret;
+	get_group_info(current->group_info);
+	i = current->group_info->ngroups;
+	if (gidsetsize) {
+		if (i > gidsetsize) {
+			i = -EINVAL;
+			goto out;
+		}
+		if (groups16_to_user(grouplist, current->group_info)) {
+			i = -EFAULT;
+			goto out;
+		}
+	}
+out:
+	put_group_info(current->group_info);
+	return i;
 }
 
-extern asmlinkage long sys_setgroups (int gidsetsize, gid_t *grouplist);
-
 asmlinkage long
 sys32_setgroups16 (int gidsetsize, short *grouplist)
 {
-	mm_segment_t old_fs = get_fs();
-	gid_t gl[NGROUPS];
-	int ret, i;
+	struct group_info *group_info;
+	int retval;
 
-	if ((unsigned) gidsetsize > NGROUPS)
+	if (!capable(CAP_SETGID))
+		return -EPERM;
+	if ((unsigned)gidsetsize > NGROUPS_MAX)
 		return -EINVAL;
-	for (i = 0; i < gidsetsize; i++, grouplist++)
-		if (get_user(gl[i], grouplist))
-			return -EFAULT;
-	set_fs(KERNEL_DS);
-	ret = sys_setgroups(gidsetsize, gl);
-	set_fs(old_fs);
-	return ret;
+
+	group_info = groups_alloc(gidsetsize);
+	if (!group_info)
+		return -ENOMEM;
+	retval = groups16_from_user(group_info, grouplist);
+	if (retval) {
+		put_group_info(group_info);
+		return retval;
+	}
+
+	retval = set_current_groups(group_info);
+	put_group_info(group_info);
+
+	return retval;
 }
 
 asmlinkage long
 sys32_truncate64 (unsigned int path, unsigned int len_lo, unsigned int len_hi)
 {
-	extern asmlinkage long sys_truncate (const char *path, unsigned long length);
-
 	return sys_truncate((const char *) A(path), ((unsigned long) len_hi << 32) | len_lo);
 }
 
 asmlinkage long
 sys32_ftruncate64 (int fd, unsigned int len_lo, unsigned int len_hi)
 {
-	extern asmlinkage long sys_ftruncate (int fd, unsigned long length);
-
 	return sys_ftruncate(fd, ((unsigned long) len_hi << 32) | len_lo);
 }
 
@@ -2554,7 +1984,6 @@ struct sysinfo32 {
 asmlinkage long
 sys32_sysinfo (struct sysinfo32 *info)
 {
-	extern asmlinkage long sys_sysinfo (struct sysinfo *);
 	struct sysinfo s;
 	long ret, err;
 	int bitcount = 0;
@@ -2606,7 +2035,6 @@ sys32_sysinfo (struct sysinfo32 *info)
 asmlinkage long
 sys32_sched_rr_get_interval (pid_t pid, struct compat_timespec *interval)
 {
-	extern asmlinkage long sys_sched_rr_get_interval (pid_t, struct timespec *);
 	mm_segment_t old_fs = get_fs();
 	struct timespec t;
 	long ret;
@@ -2622,21 +2050,18 @@ sys32_sched_rr_get_interval (pid_t pid, 
 asmlinkage long
 sys32_pread (unsigned int fd, void *buf, unsigned int count, u32 pos_lo, u32 pos_hi)
 {
-	extern asmlinkage long sys_pread64 (unsigned int, char *, size_t, loff_t);
 	return sys_pread64(fd, buf, count, ((unsigned long) pos_hi << 32) | pos_lo);
 }
 
 asmlinkage long
 sys32_pwrite (unsigned int fd, void *buf, unsigned int count, u32 pos_lo, u32 pos_hi)
 {
-	extern asmlinkage long sys_pwrite64 (unsigned int, const char *, size_t, loff_t);
 	return sys_pwrite64(fd, buf, count, ((unsigned long) pos_hi << 32) | pos_lo);
 }
 
 asmlinkage long
 sys32_sendfile (int out_fd, int in_fd, int *offset, unsigned int count)
 {
-	extern asmlinkage long sys_sendfile (int, int, off_t *, size_t);
 	mm_segment_t old_fs = get_fs();
 	long ret;
 	off_t of;
@@ -2657,7 +2082,6 @@ sys32_sendfile (int out_fd, int in_fd, i
 asmlinkage long
 sys32_personality (unsigned int personality)
 {
-	extern asmlinkage long sys_personality (unsigned long);
 	long ret;
 
 	if (current->personality == PER_LINUX32 && personality == PER_LINUX)
@@ -2949,8 +2373,6 @@ sys32_timer_create(u32 clock, struct sig
 	return err;
 }
 
-extern long sys_fadvise64_64(int fd, loff_t offset, loff_t len, int advice);
-
 long sys32_fadvise64_64(int fd, __u32 offset_low, __u32 offset_high, 
 			__u32 len_low, __u32 len_high, int advice)
 { 
@@ -3049,9 +2471,6 @@ copy_mount_stuff_to_kernel(const void *u
 	return 0;
 }
 
-extern asmlinkage long sys_mount(char * dev_name, char * dir_name, char * type,
-				unsigned long new_flags, void *data);
-
 #define SMBFS_NAME	"smbfs"
 #define NCPFS_NAME	"ncpfs"
 
@@ -3116,8 +2535,6 @@ sys32_mount(char *dev_name, char *dir_na
 	}
 }
 
-extern asmlinkage long sys_setreuid(uid_t ruid, uid_t euid);
-
 asmlinkage long sys32_setreuid(compat_uid_t ruid, compat_uid_t euid)
 {
 	uid_t sruid, seuid;
@@ -3127,8 +2544,6 @@ asmlinkage long sys32_setreuid(compat_ui
 	return sys_setreuid(sruid, seuid);
 }
 
-extern asmlinkage long sys_setresuid(uid_t ruid, uid_t euid, uid_t suid);
-
 asmlinkage long
 sys32_setresuid(compat_uid_t ruid, compat_uid_t euid,
 		compat_uid_t suid)
@@ -3141,8 +2556,6 @@ sys32_setresuid(compat_uid_t ruid, compa
 	return sys_setresuid(sruid, seuid, ssuid);
 }
 
-extern asmlinkage long sys_setregid(gid_t rgid, gid_t egid);
-
 asmlinkage long
 sys32_setregid(compat_gid_t rgid, compat_gid_t egid)
 {
@@ -3153,8 +2566,6 @@ sys32_setregid(compat_gid_t rgid, compat
 	return sys_setregid(srgid, segid);
 }
 
-extern asmlinkage long sys_setresgid(gid_t rgid, gid_t egid, gid_t sgid);
-
 asmlinkage long
 sys32_setresgid(compat_gid_t rgid, compat_gid_t egid,
 		compat_gid_t sgid)
@@ -3284,8 +2695,6 @@ nfs_getfh32_res_trans(union nfsctl_res *
 	return err;
 }
 
-extern asmlinkage long sys_nfsservctl(int cmd, void *arg, void *resp);
-
 int asmlinkage
 sys32_nfsservctl(int cmd, struct nfsctl_arg32 *arg32, union nfsctl_res32 *res32)
 {
--- diff/arch/ia64/kernel/Makefile	2004-01-19 10:22:55.000000000 +0000
+++ source/arch/ia64/kernel/Makefile	2004-02-23 13:56:37.000000000 +0000
@@ -18,6 +18,7 @@ obj-$(CONFIG_IOSAPIC)		+= iosapic.o
 obj-$(CONFIG_MODULES)		+= module.o
 obj-$(CONFIG_SMP)		+= smp.o smpboot.o
 obj-$(CONFIG_PERFMON)		+= perfmon_default_smpl.o
+obj-$(CONFIG_IA64_CYCLONE)	+= cyclone.o
 
 # The gate DSO image is built using a special linker script.
 targets += gate.so gate-syms.o
--- diff/arch/ia64/kernel/acpi.c	2004-02-18 08:54:07.000000000 +0000
+++ source/arch/ia64/kernel/acpi.c	2004-02-23 13:56:37.000000000 +0000
@@ -49,6 +49,8 @@
 #include <asm/page.h>
 #include <asm/system.h>
 #include <asm/numa.h>
+#include <asm/sal.h>
+#include <asm/cyclone.h>
 
 
 #define PREFIX			"ACPI: "
@@ -304,6 +306,22 @@ acpi_parse_nmi_src (acpi_table_entry_hea
 	return 0;
 }
 
+/* Hook from generic ACPI tables.c */
+void __init acpi_madt_oem_check(char *oem_id, char *oem_table_id)
+{
+	if (!strncmp(oem_id, "IBM", 3) &&
+	    (!strncmp(oem_table_id, "SERMOW", 6))){
+
+		/* Unfortunatly ITC_DRIFT is not yet part of the
+		 * official SAL spec, so the ITC_DRIFT bit is not
+		 * set by the BIOS on this hardware.
+		 */
+		sal_platform_features |= IA64_SAL_PLATFORM_FEATURE_ITC_DRIFT;
+
+		/*Start cyclone clock*/
+		cyclone_setup(0);
+	}
+}
 
 static int __init
 acpi_parse_madt (unsigned long phys_addr, unsigned long size)
@@ -327,6 +345,10 @@ acpi_parse_madt (unsigned long phys_addr
 		ipi_base_addr = (unsigned long) ioremap(acpi_madt->lapic_address, 0);
 
 	printk(KERN_INFO PREFIX "Local APIC address 0x%lx\n", ipi_base_addr);
+
+	acpi_madt_oem_check(acpi_madt->header.oem_id,
+		acpi_madt->header.oem_table_id);
+
 	return 0;
 }
 
--- diff/arch/ia64/kernel/irq.c	2004-02-18 08:54:07.000000000 +0000
+++ source/arch/ia64/kernel/irq.c	2004-02-23 13:56:37.000000000 +0000
@@ -940,7 +940,7 @@ void set_irq_affinity_info (unsigned int
 static int irq_affinity_read_proc (char *page, char **start, off_t off,
 			int count, int *eof, void *data)
 {
-	int len = cpumask_snprintf(page, count, irq_affinity[(long)data]);
+	int len = cpumask_scnprintf(page, count, irq_affinity[(long)data]);
 	if (count - len < 2)
 		return -EINVAL;
 	len += sprintf(page + len, "\n");
@@ -1005,7 +1005,7 @@ static int irq_affinity_write_proc (stru
 static int prof_cpu_mask_read_proc (char *page, char **start, off_t off,
 			int count, int *eof, void *data)
 {
-	int len = cpumask_snprintf(page, count, *(cpumask_t *)data);
+	int len = cpumask_scnprintf(page, count, *(cpumask_t *)data);
 	if (count - len < 2)
 		return -EINVAL;
 	len += sprintf(page + len, "\n");
--- diff/arch/ia64/kernel/sys_ia64.c	2003-09-17 12:28:01.000000000 +0100
+++ source/arch/ia64/kernel/sys_ia64.c	2004-02-23 13:56:37.000000000 +0000
@@ -15,6 +15,7 @@
 #include <linux/file.h>		/* doh, must come after sched.h... */
 #include <linux/smp.h>
 #include <linux/smp_lock.h>
+#include <linux/syscalls.h>
 #include <linux/highuid.h>
 #include <linux/hugetlb.h>
 
@@ -74,7 +75,6 @@ arch_get_unmapped_area (struct file *fil
 asmlinkage long
 ia64_getpriority (int which, int who)
 {
-	extern long sys_getpriority (int, int);
 	long prio;
 
 	prio = sys_getpriority(which, who);
--- diff/arch/ia64/kernel/unwind.c	2004-02-18 08:54:07.000000000 +0000
+++ source/arch/ia64/kernel/unwind.c	2004-02-23 13:56:37.000000000 +0000
@@ -1416,7 +1416,7 @@ compile_reg (struct unw_state_record *sr
 
 	      case UNW_WHERE_FR:
 		if (rval <= 5)
-			val = unw.preg_index[UNW_REG_F2  + (rval -  1)];
+			val = unw.preg_index[UNW_REG_F2  + (rval -  2)];
 		else if (rval >= 16 && rval <= 31)
 			val = unw.preg_index[UNW_REG_F16 + (rval - 16)];
 		else {
--- diff/arch/ia64/lib/dec_and_lock.c	2004-01-19 10:22:55.000000000 +0000
+++ source/arch/ia64/lib/dec_and_lock.c	2004-02-23 13:56:37.000000000 +0000
@@ -13,6 +13,7 @@
 #include <linux/spinlock.h>
 #include <asm/atomic.h>
 
+#ifndef CONFIG_LOCKMETER
 /*
  * Decrement REFCOUNT and if the count reaches zero, acquire the spinlock.  Both of these
  * operations have to be done atomically, so that the count doesn't drop to zero without
@@ -40,3 +41,4 @@ atomic_dec_and_lock (atomic_t *refcount,
 }
 
 EXPORT_SYMBOL(atomic_dec_and_lock);
+#endif
--- diff/arch/ia64/pci/pci.c	2004-02-09 10:36:07.000000000 +0000
+++ source/arch/ia64/pci/pci.c	2004-02-23 13:56:37.000000000 +0000
@@ -55,8 +55,11 @@ struct pci_fixup pcibios_fixups[1];
 
 #define PCI_SAL_ADDRESS(seg, bus, devfn, reg) \
 	((u64)(seg << 24) | (u64)(bus << 16) | \
-	 (u64)(devfn << 8) | (u64)(reg))
+	 (u64)(devfn << 8) | (u64)(reg)), 0
 
+#define PCI_SAL_EXT_ADDRESS(seg, bus, devfn, reg) \
+	((u64)(seg << 28) | (u64)(bus << 20) | \
+	 (u64)(devfn << 12) | (u64)(reg)), 1
 
 static int
 pci_sal_read (int seg, int bus, int devfn, int reg, int len, u32 *value)
@@ -64,10 +67,14 @@ pci_sal_read (int seg, int bus, int devf
 	int result = 0;
 	u64 data = 0;
 
-	if (!value || (seg > 255) || (bus > 255) || (devfn > 255) || (reg > 255))
+	if (!value || (seg > 65535) || (bus > 255) || (devfn > 255) || (reg > 4095))
 		return -EINVAL;
 
-	result = ia64_sal_pci_config_read(PCI_SAL_ADDRESS(seg, bus, devfn, reg), len, &data);
+	if ((seg < 256) && (reg < 256)) {
+		result = ia64_sal_pci_config_read(PCI_SAL_ADDRESS(seg, bus, devfn, reg), len, &data);
+	} else {
+		result = ia64_sal_pci_config_read(PCI_SAL_EXT_ADDRESS(seg, bus, devfn, reg), len, &data);
+	}
 
 	*value = (u32) data;
 
@@ -77,13 +84,17 @@ pci_sal_read (int seg, int bus, int devf
 static int
 pci_sal_write (int seg, int bus, int devfn, int reg, int len, u32 value)
 {
-	if ((seg > 255) || (bus > 255) || (devfn > 255) || (reg > 255))
+	if ((seg > 65535) || (bus > 255) || (devfn > 255) || (reg > 4095))
 		return -EINVAL;
 
-	return ia64_sal_pci_config_write(PCI_SAL_ADDRESS(seg, bus, devfn, reg), len, value);
+	if ((seg < 256) && (reg < 256)) {
+		return ia64_sal_pci_config_write(PCI_SAL_ADDRESS(seg, bus, devfn, reg), len, value);
+	} else {
+		return ia64_sal_pci_config_write(PCI_SAL_EXT_ADDRESS(seg, bus, devfn, reg), len, value);
+	}
 }
 
-struct pci_raw_ops pci_sal_ops = {
+static struct pci_raw_ops pci_sal_ops = {
 	.read = 	pci_sal_read,
 	.write =	pci_sal_write
 };
@@ -153,8 +164,10 @@ alloc_resource (char *name, struct resou
 	res->end = end;
 	res->flags = flags;
 
-	if (insert_resource(root, res))
+	if (insert_resource(root, res))	{
+		kfree(res);
 		return -EBUSY;
+	}
 
 	return 0;
 }
--- diff/arch/ia64/sn/io/drivers/ioconfig_bus.c	2004-02-09 10:36:07.000000000 +0000
+++ source/arch/ia64/sn/io/drivers/ioconfig_bus.c	2004-02-23 13:56:37.000000000 +0000
@@ -16,6 +16,7 @@
 
 #include <linux/pci.h>
 
+#include <asm/uaccess.h>
 #include <asm/sn/sgi.h>
 #include <asm/io.h>
 #include <asm/sn/iograph.h>
--- diff/arch/ia64/sn/io/io.c	2004-02-18 08:54:07.000000000 +0000
+++ source/arch/ia64/sn/io/io.c	2004-02-23 13:56:37.000000000 +0000
@@ -12,7 +12,6 @@
 #include <asm/sn/types.h>
 #include <asm/sn/sgi.h>
 #include <asm/sn/driver.h>
-#include <asm/sn/iograph.h>
 #include <asm/param.h>
 #include <asm/sn/pio.h>
 #include <asm/sn/xtalk/xwidget.h>
--- diff/arch/ia64/sn/io/machvec/pci_bus_cvlink.c	2004-02-18 08:54:07.000000000 +0000
+++ source/arch/ia64/sn/io/machvec/pci_bus_cvlink.c	2004-02-23 13:56:37.000000000 +0000
@@ -9,7 +9,6 @@
 #include <linux/vmalloc.h>
 #include <linux/slab.h>
 #include <asm/sn/sgi.h>
-#include <asm/sn/iograph.h>
 #include <asm/sn/pci/pci_bus_cvlink.h>
 #include <asm/sn/sn_cpuid.h>
 #include <asm/sn/simulator.h>
@@ -28,7 +27,7 @@ vertex_hdl_t devfn_to_vertex(unsigned ch
 
 extern void register_pcibr_intr(int irq, pcibr_intr_t intr);
 
-static void sn_dma_flush_init(unsigned long start,
+static struct sn_flush_device_list *sn_dma_flush_init(unsigned long start,
 				unsigned long end,
 				int idx, int pin, int slot);
 extern int cbrick_type_get_nasid(nasid_t);
@@ -54,7 +53,7 @@ set_pci_provider(struct sn_device_sysdat
 }
 
 /*
- * pci_bus_cvlink_init() - To be called once during initialization before 
+ * pci_bus_cvlink_init() - To be called once during initialization before
  *	SGI IO Infrastructure init is called.
  */
 int
@@ -74,7 +73,7 @@ pci_bus_cvlink_init(void)
 }
 
 /*
- * pci_bus_to_vertex() - Given a logical Linux Bus Number returns the associated 
+ * pci_bus_to_vertex() - Given a logical Linux Bus Number returns the associated
  *	pci bus vertex from the SGI IO Infrastructure.
  */
 static inline vertex_hdl_t
@@ -92,7 +91,7 @@ pci_bus_to_vertex(unsigned char busnum)
 }
 
 /*
- * devfn_to_vertex() - returns the vertex of the device given the bus, slot, 
+ * devfn_to_vertex() - returns the vertex of the device given the bus, slot,
  *	and function numbers.
  */
 vertex_hdl_t
@@ -133,8 +132,8 @@ devfn_to_vertex(unsigned char busnum, un
 	 * ../pci/1, ../pci/2 ..
 	 */
 	if (func == 0) {
-        	sprintf(name, "%d", slot);
-		if (hwgraph_traverse(pci_bus, name, &device_vertex) == 
+		sprintf(name, "%d", slot);
+		if (hwgraph_traverse(pci_bus, name, &device_vertex) ==
 			GRAPH_SUCCESS) {
 			if (device_vertex) {
 				return(device_vertex);
@@ -156,19 +155,248 @@ devfn_to_vertex(unsigned char busnum, un
 	return(device_vertex);
 }
 
+/*
+ * sn_alloc_pci_sysdata() - This routine allocates a pci controller
+ *	which is expected as the pci_dev and pci_bus sysdata by the Linux
+ *      PCI infrastructure.
+ */
+static struct pci_controller *
+sn_alloc_pci_sysdata(void)
+{
+	struct pci_controller *pci_sysdata;
+
+	pci_sysdata = kmalloc(sizeof(*pci_sysdata), GFP_KERNEL);
+	if (!pci_sysdata)
+		return NULL;
+
+	memset(pci_sysdata, 0, sizeof(*pci_sysdata));
+	return pci_sysdata;
+}
+
+/*
+ * sn_pci_fixup_bus() - This routine sets up a bus's resources
+ * consistent with the Linux PCI abstraction layer.
+ */
+static int __init
+sn_pci_fixup_bus(struct pci_bus *bus)
+{
+	struct pci_controller *pci_sysdata;
+	struct sn_widget_sysdata *widget_sysdata;
+
+	pci_sysdata = sn_alloc_pci_sysdata();
+	if  (!pci_sysdata) {
+		printk(KERN_WARNING "sn_pci_fixup_bus(): Unable to "
+			       "allocate memory for pci_sysdata\n");
+		return -ENOMEM;
+	}
+	widget_sysdata = kmalloc(sizeof(struct sn_widget_sysdata),
+				 GFP_KERNEL);
+	if (!widget_sysdata) {
+		printk(KERN_WARNING "sn_pci_fixup_bus(): Unable to "
+			       "allocate memory for widget_sysdata\n");
+		kfree(pci_sysdata);
+		return -ENOMEM;
+	}
+
+	widget_sysdata->vhdl = pci_bus_to_vertex(bus->number);
+	pci_sysdata->platform_data = (void *)widget_sysdata;
+	bus->sysdata = pci_sysdata;
+	return 0;
+}
+
+
+/*
+ * sn_pci_fixup_slot() - This routine sets up a slot's resources
+ * consistent with the Linux PCI abstraction layer.  Resources acquired
+ * from our PCI provider include PIO maps to BAR space and interrupt
+ * objects.
+ */
+static int
+sn_pci_fixup_slot(struct pci_dev *dev)
+{
+	extern int bit_pos_to_irq(int);
+	unsigned int irq;
+	int idx;
+	u16 cmd;
+	vertex_hdl_t vhdl;
+	unsigned long size;
+	struct pci_controller *pci_sysdata;
+	struct sn_device_sysdata *device_sysdata;
+	pciio_intr_line_t lines = 0;
+	vertex_hdl_t device_vertex;
+	pciio_provider_t *pci_provider;
+	pciio_intr_t intr_handle;
+
+	/* Allocate a controller structure */
+	pci_sysdata = sn_alloc_pci_sysdata();
+	if (!pci_sysdata) {
+		printk(KERN_WARNING "sn_pci_fixup_slot: Unable to "
+			       "allocate memory for pci_sysdata\n");
+		return -ENOMEM;
+	}
+
+	/* Set the device vertex */
+	device_sysdata = kmalloc(sizeof(struct sn_device_sysdata), GFP_KERNEL);
+	if (!device_sysdata) {
+		printk(KERN_WARNING "sn_pci_fixup_slot: Unable to "
+			       "allocate memory for device_sysdata\n");
+		kfree(pci_sysdata);
+		return -ENOMEM;
+	}
+
+	device_sysdata->vhdl = devfn_to_vertex(dev->bus->number, dev->devfn);
+	pci_sysdata->platform_data = (void *) device_sysdata;
+	dev->sysdata = pci_sysdata;
+	set_pci_provider(device_sysdata);
+
+	pci_read_config_word(dev, PCI_COMMAND, &cmd);
+
+	/*
+	 * Set the resources address correctly.  The assumption here
+	 * is that the addresses in the resource structure has been
+	 * read from the card and it was set in the card by our
+	 * Infrastructure.  NOTE: PIC and TIOCP don't have big-window
+	 * upport for PCI I/O space.  So by mapping the I/O space
+	 * first we will attempt to use Device(x) registers for I/O
+	 * BARs (which can't use big windows like MEM BARs can).
+	 */
+	vhdl = device_sysdata->vhdl;
+
+	/* Allocate the IORESOURCE_IO space first */
+	for (idx = 0; idx < PCI_ROM_RESOURCE; idx++) {
+		unsigned long start, end, addr;
+
+		device_sysdata->pio_map[idx] = NULL;
+
+		if (!(dev->resource[idx].flags & IORESOURCE_IO))
+			continue;
+
+		start = dev->resource[idx].start;
+		end = dev->resource[idx].end;
+		size = end - start;
+		if (!size)
+			continue;
+
+		addr = (unsigned long)pciio_pio_addr(vhdl, 0,
+		PCIIO_SPACE_WIN(idx), 0, size,
+				&device_sysdata->pio_map[idx], 0);
+
+		if (!addr) {
+			dev->resource[idx].start = 0;
+			dev->resource[idx].end = 0;
+			printk("sn_pci_fixup(): pio map failure for "
+				"%s bar%d\n", dev->slot_name, idx);
+		} else {
+			addr |= __IA64_UNCACHED_OFFSET;
+			dev->resource[idx].start = addr;
+			dev->resource[idx].end = addr + size;
+		}
+
+		if (dev->resource[idx].flags & IORESOURCE_IO)
+			cmd |= PCI_COMMAND_IO;
+	}
+
+	/* Allocate the IORESOURCE_MEM space next */
+	for (idx = 0; idx < PCI_ROM_RESOURCE; idx++) {
+		unsigned long start, end, addr;
+
+		if ((dev->resource[idx].flags & IORESOURCE_IO))
+			continue;
+
+		start = dev->resource[idx].start;
+		end = dev->resource[idx].end;
+		size = end - start;
+		if (!size)
+			continue;
+
+		addr = (unsigned long)pciio_pio_addr(vhdl, 0,
+		PCIIO_SPACE_WIN(idx), 0, size,
+				&device_sysdata->pio_map[idx], 0);
+
+		if (!addr) {
+			dev->resource[idx].start = 0;
+			dev->resource[idx].end = 0;
+			printk("sn_pci_fixup(): pio map failure for "
+				"%s bar%d\n", dev->slot_name, idx);
+		} else {
+			addr |= __IA64_UNCACHED_OFFSET;
+			dev->resource[idx].start = addr;
+			dev->resource[idx].end = addr + size;
+		}
+
+		if (dev->resource[idx].flags & IORESOURCE_MEM)
+			cmd |= PCI_COMMAND_MEMORY;
+	}
+
+	/*
+	 * Update the Command Word on the Card.
+	 */
+	cmd |= PCI_COMMAND_MASTER; /* If the device doesn't support */
+				   /* bit gets dropped .. no harm */
+	pci_write_config_word(dev, PCI_COMMAND, cmd);
+
+	pci_read_config_byte(dev, PCI_INTERRUPT_PIN, (unsigned char *)&lines);
+	device_vertex = device_sysdata->vhdl;
+	pci_provider = device_sysdata->pci_provider;
+	device_sysdata->intr_handle = NULL;
+
+	if (!lines)
+		return 0;
+
+	irqpdaindr->curr = dev;
+
+	intr_handle = (pci_provider->intr_alloc)(device_vertex, NULL, lines, device_vertex);
+	if (intr_handle == NULL) {
+		printk(KERN_WARNING "sn_pci_fixup:  pcibr_intr_alloc() failed\n");
+		kfree(pci_sysdata);
+		kfree(device_sysdata);
+		return -ENOMEM;
+	}
+
+	device_sysdata->intr_handle = intr_handle;
+	irq = intr_handle->pi_irq;
+	irqpdaindr->device_dev[irq] = dev;
+	(pci_provider->intr_connect)(intr_handle, (intr_func_t)0, (intr_arg_t)0);
+	dev->irq = irq;
+
+	register_pcibr_intr(irq, (pcibr_intr_t)intr_handle);
+
+	for (idx = 0; idx < PCI_ROM_RESOURCE; idx++) {
+		int ibits = ((pcibr_intr_t)intr_handle)->bi_ibits;
+		int i;
+
+		size = dev->resource[idx].end -
+			dev->resource[idx].start;
+		if (size == 0) continue;
+
+		for (i=0; i<8; i++) {
+			if (ibits & (1 << i) ) {
+				extern pcibr_info_t pcibr_info_get(vertex_hdl_t);
+				device_sysdata->dma_flush_list =
+				 sn_dma_flush_init(dev->resource[idx].start,
+						   dev->resource[idx].end,
+						   idx,
+						   i,
+						   PCIBR_INFO_SLOT_GET_EXT(pcibr_info_get(device_sysdata->vhdl)));
+			}
+		}
+	}
+	return 0;
+}
+
 struct sn_flush_nasid_entry flush_nasid_list[MAX_NASIDS];
 
 /* Initialize the data structures for flushing write buffers after a PIO read.
- * The theory is: 
+ * The theory is:
  * Take an unused int. pin and associate it with a pin that is in use.
  * After a PIO read, force an interrupt on the unused pin, forcing a write buffer flush
- * on the in use pin.  This will prevent the race condition between PIO read responses and 
+ * on the in use pin.  This will prevent the race condition between PIO read responses and
  * DMA writes.
  */
-static void
+static struct sn_flush_device_list *
 sn_dma_flush_init(unsigned long start, unsigned long end, int idx, int pin, int slot)
 {
-	nasid_t nasid; 
+	nasid_t nasid;
 	unsigned long dnasid;
 	int wid_num;
 	int bus;
@@ -187,7 +415,7 @@ sn_dma_flush_init(unsigned long start, u
 			sizeof(struct sn_flush_device_list *), GFP_KERNEL);
 		if (!flush_nasid_list[nasid].widget_p) {
 			printk(KERN_WARNING "sn_dma_flush_init: Cannot allocate memory for nasid list\n");
-			return;
+			return NULL;
 		}
 		memset(flush_nasid_list[nasid].widget_p, 0, (HUB_WIDGET_ID_MAX+1) * sizeof(struct sn_flush_device_list *));
 	}
@@ -197,8 +425,8 @@ sn_dma_flush_init(unsigned long start, u
 
 		itte = HUB_L(IIO_ITTE_GET(nasid, itte_index));
 		flush_nasid_list[nasid].iio_itte[bwin] = itte;
-		wid_num = (itte >> IIO_ITTE_WIDGET_SHIFT) & 
-			  IIO_ITTE_WIDGET_MASK;
+		wid_num = (itte >> IIO_ITTE_WIDGET_SHIFT)
+				& IIO_ITTE_WIDGET_MASK;
 		bus = itte & IIO_ITTE_OFFSET_MASK;
 		if (bus == 0x4 || bus == 0x8) {
 			bus = 0;
@@ -211,16 +439,16 @@ sn_dma_flush_init(unsigned long start, u
 	 * because these are the IOC4 slots and we don't flush them.
 	 */
 	if (isIO9(nasid) && bus == 0 && (slot == 1 || slot == 4)) {
-		return;
+		return NULL;
 	}
 	if (flush_nasid_list[nasid].widget_p[wid_num] == NULL) {
 		flush_nasid_list[nasid].widget_p[wid_num] = (struct sn_flush_device_list *)kmalloc(
 			DEV_PER_WIDGET * sizeof (struct sn_flush_device_list), GFP_KERNEL);
 		if (!flush_nasid_list[nasid].widget_p[wid_num]) {
 			printk(KERN_WARNING "sn_dma_flush_init: Cannot allocate memory for nasid sub-list\n");
-			return;
+			return NULL;
 		}
-		memset(flush_nasid_list[nasid].widget_p[wid_num], 0, 
+		memset(flush_nasid_list[nasid].widget_p[wid_num], 0,
 			DEV_PER_WIDGET * sizeof (struct sn_flush_device_list));
 		p = &flush_nasid_list[nasid].widget_p[wid_num][0];
 		for (i=0; i<DEV_PER_WIDGET;i++) {
@@ -259,7 +487,7 @@ sn_dma_flush_init(unsigned long start, u
 	 * about the case when there is a card in slot 2.  A multifunction card will appear
 	 * to be in slot 6 (from an interrupt point of view) also.  That's the  most we'll
 	 * have to worry about.  A four function card will overload the interrupt lines in
-	 * slot 2 and 6.  
+	 * slot 2 and 6.
 	 * We also need to special case the 12160 device in slot 3.  Fortunately, we have
 	 * a spare intr. line for pin 4, so we'll use that for the 12160.
 	 * All other buses have slot 3 and 4 and slots 7 and 8 unused.  Since we can only
@@ -279,21 +507,21 @@ sn_dma_flush_init(unsigned long start, u
 			pcireg_bridge_intr_device_bit_set(b, (1<<18));
 			dnasid = NASID_GET(virt_to_phys(&p->flush_addr));
 			pcireg_bridge_intr_addr_set(b, 6, ((virt_to_phys(&p->flush_addr) & 0xfffffffff) |
-						    (dnasid << 36) | (0xfUL << 48)));
+					(dnasid << 36) | (0xfUL << 48)));
 		} else if (pin == 2) { /* 12160 SCSI device in IO9 */
 			p->force_int_addr = (unsigned long)pcireg_bridge_force_always_addr_get(b, 4);
 			pcireg_bridge_intr_device_bit_set(b, (2<<12));
 			dnasid = NASID_GET(virt_to_phys(&p->flush_addr));
 			pcireg_bridge_intr_addr_set(b, 4,
 					((virt_to_phys(&p->flush_addr) & 0xfffffffff) |
-					    (dnasid << 36) | (0xfUL << 48)));
+					(dnasid << 36) | (0xfUL << 48)));
 		} else { /* slot == 6 */
 			p->force_int_addr = (unsigned long)pcireg_bridge_force_always_addr_get(b, 7);
 			pcireg_bridge_intr_device_bit_set(b, (5<<21));
 			dnasid = NASID_GET(virt_to_phys(&p->flush_addr));
 			pcireg_bridge_intr_addr_set(b, 7,
 					((virt_to_phys(&p->flush_addr) & 0xfffffffff) |
-					    (dnasid << 36) | (0xfUL << 48)));
+					(dnasid << 36) | (0xfUL << 48)));
 		}
 	} else {
 		p->force_int_addr = (unsigned long)pcireg_bridge_force_always_addr_get(b, (pin +2));
@@ -301,239 +529,13 @@ sn_dma_flush_init(unsigned long start, u
 		dnasid = NASID_GET(virt_to_phys(&p->flush_addr));
 		pcireg_bridge_intr_addr_set(b, (pin + 2),
 				((virt_to_phys(&p->flush_addr) & 0xfffffffff) |
-				    (dnasid << 36) | (0xfUL << 48)));
-	}
-}
-
-/*
- * sn_pci_fixup() - This routine is called when platform_pci_fixup() is 
- *	invoked at the end of pcibios_init() to link the Linux pci 
- *	infrastructure to SGI IO Infrasturcture - ia64/kernel/pci.c
- *
- *	Other platform specific fixup can also be done here.
- */
-static void __init
-sn_pci_fixup(int arg)
-{
-	struct list_head *ln;
-	struct pci_bus *pci_bus = NULL;
-	struct pci_dev *device_dev = NULL;
-	struct sn_widget_sysdata *widget_sysdata;
-	struct sn_device_sysdata *device_sysdata;
-	pcibr_intr_t intr_handle;
-	pciio_provider_t *pci_provider;
-	vertex_hdl_t device_vertex;
-	pciio_intr_line_t lines = 0;
-	extern int numnodes;
-	int cnode;
-
-	if (arg == 0) {
-#ifdef CONFIG_PROC_FS
-		extern void register_sn_procfs(void);
-#endif
-		extern void sgi_master_io_infr_init(void);
-		extern void sn_init_cpei_timer(void);
-		
-		sgi_master_io_infr_init();
-		
-		for (cnode = 0; cnode < numnodes; cnode++) {
-			extern void intr_init_vecblk(cnodeid_t);
-			intr_init_vecblk(cnode);
-		} 
-
-		sn_init_cpei_timer();
-
-#ifdef CONFIG_PROC_FS
-		register_sn_procfs();
-#endif
-		return;
-	}
-
-
-	done_probing = 1;
-
-	/*
-	 * Initialize the pci bus vertex in the pci_bus struct.
-	 */
-	for( ln = pci_root_buses.next; ln != &pci_root_buses; ln = ln->next) {
-		pci_bus = pci_bus_b(ln);
-		widget_sysdata = kmalloc(sizeof(struct sn_widget_sysdata), 
-					GFP_KERNEL);
-		if (!widget_sysdata) {
-			printk(KERN_WARNING "sn_pci_fixup(): Unable to "
-			       "allocate memory for widget_sysdata\n");
-			return;
-		}			
-		widget_sysdata->vhdl = pci_bus_to_vertex(pci_bus->number);
-		pci_bus->sysdata = (void *)widget_sysdata;
-	}
-
-	/*
- 	 * set the root start and end so that drivers calling check_region()
-	 * won't see a conflict
-	 */
-
-#ifdef CONFIG_IA64_SGI_SN_SIM
-	if (! IS_RUNNING_ON_SIMULATOR()) {
-		ioport_resource.start  = 0xc000000000000000;
-		ioport_resource.end =    0xcfffffffffffffff;
-	}
-#endif
-
-	/*
-	 * Set the root start and end for Mem Resource.
-	 */
-	iomem_resource.start = 0;
-	iomem_resource.end = 0xffffffffffffffff;
-
-	/*
-	 * Initialize the device vertex in the pci_dev struct.
-	 */
-	while ((device_dev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, device_dev)) != NULL) {
-		unsigned int irq;
-		int idx;
-		u16 cmd;
-		vertex_hdl_t vhdl;
-		unsigned long size;
-		extern int bit_pos_to_irq(int);
-
-		/* Set the device vertex */
-
-		device_sysdata = kmalloc(sizeof(struct sn_device_sysdata),
-					 GFP_KERNEL);
-		if (!device_sysdata) {
-			printk(KERN_WARNING "sn_pci_fixup: Cannot allocate memory for device sysdata\n");
-			return;
-		}
-
-		device_sysdata->vhdl = devfn_to_vertex(device_dev->bus->number, device_dev->devfn);
-		device_dev->sysdata = (void *) device_sysdata;
-		set_pci_provider(device_sysdata);
-
-		pci_read_config_word(device_dev, PCI_COMMAND, &cmd);
-
-		/*
-		 * Set the resources address correctly.  The assumption here 
-		 * is that the addresses in the resource structure has been
-		 * read from the card and it was set in the card by our
-		 * Infrastructure ..
-		 */
-		vhdl = device_sysdata->vhdl;
-		/* Allocate the IORESOURCE_IO space first */
-		for (idx = 0; idx < PCI_ROM_RESOURCE; idx++) {
-			unsigned long start, end, addr;
-
-			if (!(device_dev->resource[idx].flags & IORESOURCE_IO))
-				continue; 
-			
-			start = device_dev->resource[idx].start;
-			end = device_dev->resource[idx].end;
-			size = end - start;
-			if (!size)
-				continue; 
-			
-			addr = (unsigned long)pciio_pio_addr(vhdl, 0, 
-					PCIIO_SPACE_WIN(idx), 0, size, 0, 0);
-			if (!addr) {
-				device_dev->resource[idx].start = 0;
-				device_dev->resource[idx].end = 0;
-				printk("sn_pci_fixup(): pio map failure for "
-				    "%s bar%d\n", device_dev->slot_name, idx);
-			} else {
-				addr |= __IA64_UNCACHED_OFFSET;
-				device_dev->resource[idx].start = addr;
-				device_dev->resource[idx].end = addr + size;
-			}	
-
-			if (device_dev->resource[idx].flags & IORESOURCE_IO) 
-				cmd |= PCI_COMMAND_IO; 
-		} 
-
-		/* Allocate the IORESOURCE_MEM space next */
-		for (idx = 0; idx < PCI_ROM_RESOURCE; idx++) {
-			unsigned long start, end, addr;
-
-			if ((device_dev->resource[idx].flags & IORESOURCE_IO))
-				continue; 
-
-			start = device_dev->resource[idx].start;
-			end = device_dev->resource[idx].end;
-			size = end - start;
-			if (!size)
-				continue; 
-
-			addr = (unsigned long)pciio_pio_addr(vhdl, 0, 
-					PCIIO_SPACE_WIN(idx), 0, size, 0, 0);
-			if (!addr) {
-				device_dev->resource[idx].start = 0;
-				device_dev->resource[idx].end = 0;
-				printk("sn_pci_fixup(): pio map failure for "
-				    "%s bar%d\n", device_dev->slot_name, idx);
-			} else {
-				addr |= __IA64_UNCACHED_OFFSET;
-				device_dev->resource[idx].start = addr;
-				device_dev->resource[idx].end = addr + size;
-			}	
-
-			if (device_dev->resource[idx].flags & IORESOURCE_MEM)
-				cmd |= PCI_COMMAND_MEMORY;
-		}
-
-		/*
-		 * Update the Command Word on the Card.
-		 */
-		cmd |= PCI_COMMAND_MASTER; /* If the device doesn't support */
-					   /* bit gets dropped .. no harm */
-		pci_write_config_word(device_dev, PCI_COMMAND, cmd);
-
-		pci_read_config_byte(device_dev, PCI_INTERRUPT_PIN,
-				     (unsigned char *)&lines);
-		device_sysdata = (struct sn_device_sysdata *)device_dev->sysdata;
-		device_vertex = device_sysdata->vhdl;
-		pci_provider = device_sysdata->pci_provider;
- 
-		if (!lines) {
-			continue;
-		}
-
-		irqpdaindr->curr = device_dev;
-		intr_handle = (pci_provider->intr_alloc)(device_vertex, NULL, lines, device_vertex);
-
-		if (intr_handle == NULL) {
-			printk("sn_pci_fixup:  pcibr_intr_alloc() failed\n");
-			continue;
-		}
-		irq = intr_handle->bi_irq;
-		irqpdaindr->device_dev[irq] = device_dev;
-		(pci_provider->intr_connect)(intr_handle, (intr_func_t)0, (intr_arg_t)0);
-		device_dev->irq = irq;
-		register_pcibr_intr(irq, (pcibr_intr_t)intr_handle);
-
-		for (idx = 0; idx < PCI_ROM_RESOURCE; idx++) {
-			int ibits = intr_handle->bi_ibits;
-			int i;
-
-			size = device_dev->resource[idx].end -
-				device_dev->resource[idx].start;
-			if (size == 0)
-				continue;
-
-			for (i=0; i<8; i++) {
-				if (ibits & (1 << i) ) {
-					sn_dma_flush_init(device_dev->resource[idx].start, 
-						device_dev->resource[idx].end,
-						idx,
-						i,
-						PCIBR_INFO_SLOT_GET_EXT(pcibr_info_get(device_sysdata->vhdl)));
-				}
-			}
-		}
-
+				(dnasid << 36) | (0xfUL << 48)));
 	}
+	return p;
 }
 
 /*
- * linux_bus_cvlink() Creates a link between the Linux PCI Bus number 
+ * linux_bus_cvlink() Creates a link between the Linux PCI Bus number
  *	to the actual hardware component that it represents:
  *	/dev/hw/linux/busnum/0 -> ../../../hw/module/001c01/slab/0/Ibrick/xtalk/15/pci
  *
@@ -553,7 +555,7 @@ linux_bus_cvlink(void)
 			continue;
 
 		sprintf(name, "%x", index);
-		(void) hwgraph_edge_add(linux_busnum, busnum_to_pcibr_vhdl[index], 
+		(void) hwgraph_edge_add(linux_busnum, busnum_to_pcibr_vhdl[index],
 				name);
 	}
 }
@@ -564,7 +566,7 @@ linux_bus_cvlink(void)
  *	Linux PCI Bus numbers are assigned from lowest module_id numbers
  *	(rack/slot etc.)
  */
-static int 
+static int
 pci_bus_map_create(struct pcibr_list_s *softlistp, moduleid_t moduleid)
 {
 	
@@ -574,10 +576,10 @@ pci_bus_map_create(struct pcibr_list_s *
 
 	memset(moduleid_str, 0, 16);
 	format_module_id(moduleid_str, moduleid, MODULE_FORMAT_BRIEF);
-        (void) ioconfig_get_busnum((char *)moduleid_str, &basebus_num);
+	(void) ioconfig_get_busnum((char *)moduleid_str, &basebus_num);
 
 	/*
-	 * Assign the correct bus number and also the nasid of this 
+	 * Assign the correct bus number and also the nasid of this
 	 * pci Xwidget.
 	 */
 	bus_number = basebus_num + pcibr_widget_to_bus(pci_bus);
@@ -605,20 +607,20 @@ pci_bus_map_create(struct pcibr_list_s *
 		printk("pci_bus_map_create: Cannot allocate memory for ate maps\n");
 		return -1;
 	}
-	memset(busnum_to_atedmamaps[bus_number], 0x0, 
+	memset(busnum_to_atedmamaps[bus_number], 0x0,
 			sizeof(struct pcibr_dmamap_s) * MAX_ATE_MAPS);
 	return(0);
 }
 
 /*
- * pci_bus_to_hcl_cvlink() - This routine is called after SGI IO Infrastructure 
+ * pci_bus_to_hcl_cvlink() - This routine is called after SGI IO Infrastructure
  *      initialization has completed to set up the mappings between PCI BRIDGE
- *      ASIC and logical pci bus numbers. 
+ *      ASIC and logical pci bus numbers.
  *
  *      Must be called before pci_init() is invoked.
  */
 int
-pci_bus_to_hcl_cvlink(void) 
+pci_bus_to_hcl_cvlink(void)
 {
 	int i;
 	extern pcibr_list_p pcibr_list;
@@ -635,7 +637,7 @@ pci_bus_to_hcl_cvlink(void) 
 			
 			/* Is this PCI bus associated with this moduleid? */
 			moduleid = NODE_MODULEID(
-			    NASID_TO_COMPACT_NODEID(pcibr_soft->bs_nasid));
+				NASID_TO_COMPACT_NODEID(pcibr_soft->bs_nasid));
 			if (modules[i]->id == moduleid) {
 				struct pcibr_list_s *new_element;
 
@@ -656,9 +658,9 @@ pci_bus_to_hcl_cvlink(void) 
 					continue;
 				}
 
-				/* 
- 				 * BASEIO IObricks attached to a module have 
-				 * a higher priority than non BASEIO IOBricks 
+				/*
+				 * BASEIO IObricks attached to a module have
+				 * a higher priority than non BASEIO IOBricks
 				 * when it comes to persistant pci bus
 				 * numbering, so put them on the front of the
 				 * list.
@@ -674,7 +676,7 @@ pci_bus_to_hcl_cvlink(void) 
 			softlistp = softlistp->bl_next;
 		}
 				
-		/* 
+		/*
 		 * We now have a list of all the pci bridges associated with
 		 * the module_id, modules[i].  Call pci_bus_map_create() for
 		 * each pci bridge
@@ -702,13 +704,26 @@ pci_bus_to_hcl_cvlink(void) 
 /*
  * Ugly hack to get PCI setup until we have a proper ACPI namespace.
  */
+
+#define PCI_BUSES_TO_SCAN 256
+
 extern struct pci_ops sn_pci_ops;
 int __init
 sn_pci_init (void)
 {
-#	define PCI_BUSES_TO_SCAN 256
 	int i = 0;
 	struct pci_controller *controller;
+	struct list_head *ln;
+	struct pci_bus *pci_bus = NULL;
+	struct pci_dev *pci_dev = NULL;
+	extern int numnodes;
+	int cnode, ret;
+#ifdef CONFIG_PROC_FS
+	extern void register_sn_procfs(void);
+#endif
+	extern void sgi_master_io_infr_init(void);
+	extern void sn_init_cpei_timer(void);
+
 
 	if (!ia64_platform_is("sn2") || IS_RUNNING_ON_SIMULATOR())
 		return 0;
@@ -721,7 +736,19 @@ sn_pci_init (void)
 	/*
 	 * set pci_raw_ops, etc.
 	 */
-	sn_pci_fixup(0);
+
+	sgi_master_io_infr_init();
+
+	for (cnode = 0; cnode < numnodes; cnode++) {
+		extern void intr_init_vecblk(cnodeid_t);
+		intr_init_vecblk(cnode);
+	}
+
+	sn_init_cpei_timer();
+
+#ifdef CONFIG_PROC_FS
+	register_sn_procfs();
+#endif
 
 	controller = kmalloc(sizeof(struct pci_controller), GFP_KERNEL);
 	if (controller) {
@@ -734,7 +761,53 @@ sn_pci_init (void)
 	/*
 	 * actually find devices and fill in hwgraph structs
 	 */
-	sn_pci_fixup(1);
+
+	done_probing = 1;
+
+	/*
+	 * Initialize the pci bus vertex in the pci_bus struct.
+	 */
+	for( ln = pci_root_buses.next; ln != &pci_root_buses; ln = ln->next) {
+		pci_bus = pci_bus_b(ln);
+		ret = sn_pci_fixup_bus(pci_bus);
+		if ( ret ) {
+			printk(KERN_WARNING
+				"sn_pci_fixup: sn_pci_fixup_bus fails : error %d\n",
+					ret);
+			return;
+		}
+	}
+
+	/*
+	 * set the root start and end so that drivers calling check_region()
+	 * won't see a conflict
+	 */
+
+#ifdef CONFIG_IA64_SGI_SN_SIM
+	if (! IS_RUNNING_ON_SIMULATOR()) {
+		ioport_resource.start  = 0xc000000000000000;
+		ioport_resource.end =    0xcfffffffffffffff;
+	}
+#endif
+
+	/*
+	 * Set the root start and end for Mem Resource.
+	 */
+	iomem_resource.start = 0;
+	iomem_resource.end = 0xffffffffffffffff;
+
+	/*
+	 * Initialize the device vertex in the pci_dev struct.
+	 */
+	while ((pci_dev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, pci_dev)) != NULL) {
+		ret = sn_pci_fixup_slot(pci_dev);
+		if ( ret ) {
+			printk(KERN_WARNING
+				"sn_pci_fixup: sn_pci_fixup_slot fails : error %d\n",
+					ret);
+			return;
+		}
+	}
 
 	return 0;
 }
--- diff/arch/ia64/sn/io/machvec/pci_dma.c	2004-02-18 08:54:07.000000000 +0000
+++ source/arch/ia64/sn/io/machvec/pci_dma.c	2004-02-23 13:56:37.000000000 +0000
@@ -127,7 +127,7 @@ sn_pci_alloc_consistent(struct pci_dev *
 	/*
 	 * Get hwgraph vertex for the device
 	 */
-	device_sysdata = (struct sn_device_sysdata *) hwdev->sysdata;
+	device_sysdata = SN_DEVICE_SYSDATA(hwdev);
 	vhdl = device_sysdata->vhdl;
 
 	/*
@@ -240,7 +240,7 @@ sn_pci_map_sg(struct pci_dev *hwdev, str
 	/*
 	 * Get the hwgraph vertex for the device
 	 */
-	device_sysdata = (struct sn_device_sysdata *) hwdev->sysdata;
+	device_sysdata = SN_DEVICE_SYSDATA(hwdev);
 	vhdl = device_sysdata->vhdl;
 
 	/*
@@ -367,7 +367,7 @@ sn_pci_map_single(struct pci_dev *hwdev,
 	/*
 	 * find vertex for the device
 	 */
-	device_sysdata = (struct sn_device_sysdata *)hwdev->sysdata;
+	device_sysdata = SN_DEVICE_SYSDATA(hwdev);
 	vhdl = device_sysdata->vhdl;
 
 	/*
--- diff/arch/ia64/sn/io/sn2/bte_error.c	2004-02-09 10:36:07.000000000 +0000
+++ source/arch/ia64/sn/io/sn2/bte_error.c	2004-02-23 13:56:37.000000000 +0000
@@ -12,7 +12,6 @@
 #include <asm/smp.h>
 #include <asm/sn/sgi.h>
 #include <asm/sn/io.h>
-#include <asm/sn/iograph.h>
 #include <asm/sn/hcl.h>
 #include <asm/sn/labelcl.h>
 #include <asm/sn/sn_private.h>
--- diff/arch/ia64/sn/io/sn2/geo_op.c	2004-02-09 10:36:07.000000000 +0000
+++ source/arch/ia64/sn/io/sn2/geo_op.c	2004-02-23 13:56:37.000000000 +0000
@@ -27,7 +27,6 @@
 #include <asm/hw_irq.h>
 #include <asm/sn/types.h>
 #include <asm/sn/sgi.h>
-#include <asm/sn/iograph.h>
 #include <asm/sn/hcl.h>
 #include <asm/sn/labelcl.h>
 #include <asm/sn/io.h>
--- diff/arch/ia64/sn/io/sn2/klconflib.c	2004-02-18 08:54:07.000000000 +0000
+++ source/arch/ia64/sn/io/sn2/klconflib.c	2004-02-23 13:56:37.000000000 +0000
@@ -474,8 +474,6 @@ board_serial_number_get(lboard_t *board,
 	return(0);
 }
 
-#include "asm/sn/sn_private.h"
-
 /*
  * Format a module id for printing.
  *
--- diff/arch/ia64/sn/io/sn2/ml_SN_init.c	2004-02-09 10:36:07.000000000 +0000
+++ source/arch/ia64/sn/io/sn2/ml_SN_init.c	2004-02-23 13:56:37.000000000 +0000
@@ -11,12 +11,12 @@
 #include <linux/bootmem.h>
 #include <asm/sn/sgi.h>
 #include <asm/sn/io.h>
-#include <asm/sn/iograph.h>
 #include <asm/sn/hcl.h>
 #include <asm/sn/labelcl.h>
 #include <asm/sn/sn_private.h>
 #include <asm/sn/klconfig.h>
 #include <asm/sn/sn_cpuid.h>
+#include <asm/sn/simulator.h>
 
 int		maxcpus;
 
@@ -69,12 +69,15 @@ void init_platform_nodepda(nodepda_t *np
 }
 
 void
-init_platform_hubinfo(nodepda_t **nodepdaindr) {
+init_platform_hubinfo(nodepda_t **nodepdaindr)
+{
 	cnodeid_t       cnode;
 	hubinfo_t hubinfo;
 	nodepda_t *npda;
 	extern int numionodes;
 
+	if (IS_RUNNING_ON_SIMULATOR())
+		return;
 	for (cnode = 0; cnode < numionodes; cnode++) {
 		npda = nodepdaindr[cnode];
 		hubinfo = (hubinfo_t)npda->pdinfo;
--- diff/arch/ia64/sn/io/sn2/ml_SN_intr.c	2004-02-09 10:36:07.000000000 +0000
+++ source/arch/ia64/sn/io/sn2/ml_SN_intr.c	2004-02-23 13:56:37.000000000 +0000
@@ -30,6 +30,7 @@
 #include <asm/sal.h>
 #include <asm/sn/sn_sal.h>
 #include <asm/sn/sn2/shub_mmr.h>
+#include <asm/sn/pda.h>
 
 extern irqpda_t	*irqpdaindr;
 extern cnodeid_t master_node_get(vertex_hdl_t vhdl);
@@ -216,7 +217,6 @@ static cpuid_t intr_cpu_choose_from_node
 {
 	cpuid_t		cpu, best_cpu = CPU_NONE;
 	int		slice, min_count = 1000;
-	irqpda_t	*irqs;
 
 	for (slice = CPUS_PER_NODE - 1; slice >= 0; slice--) {
 		int intrs;
@@ -227,8 +227,7 @@ static cpuid_t intr_cpu_choose_from_node
 		if (!cpu_online(cpu))
 			continue;
 
-		irqs = irqpdaindr;
-		intrs = irqs->num_irq_used;
+		intrs = pdacpu(cpu)->sn_num_irqs;
 
 		if (min_count > intrs) {
 			min_count = intrs;
@@ -243,6 +242,7 @@ static cpuid_t intr_cpu_choose_from_node
 			}
 		}
 	}
+	pdacpu(best_cpu)->sn_num_irqs++;
 	return best_cpu;
 }
 
--- diff/arch/ia64/sn/io/sn2/pcibr/pcibr_ate.c	2004-02-18 08:54:07.000000000 +0000
+++ source/arch/ia64/sn/io/sn2/pcibr/pcibr_ate.c	2004-02-23 13:56:37.000000000 +0000
@@ -8,7 +8,6 @@
 
 #include <linux/types.h>
 #include <asm/sn/sgi.h>
-#include <asm/sn/iograph.h>
 #include <asm/sn/pci/pciio.h>
 #include <asm/sn/pci/pcibr.h>
 #include <asm/sn/pci/pcibr_private.h>
--- diff/arch/ia64/sn/io/sn2/pcibr/pcibr_config.c	2004-02-18 08:54:07.000000000 +0000
+++ source/arch/ia64/sn/io/sn2/pcibr/pcibr_config.c	2004-02-23 13:56:37.000000000 +0000
@@ -8,7 +8,6 @@
 
 #include <linux/types.h>
 #include <asm/sn/sgi.h>
-#include <asm/sn/iograph.h>
 #include <asm/sn/pci/pciio.h>
 #include <asm/sn/pci/pcibr.h>
 #include <asm/sn/pci/pcibr_private.h>
--- diff/arch/ia64/sn/io/sn2/pcibr/pcibr_intr.c	2004-02-18 08:54:07.000000000 +0000
+++ source/arch/ia64/sn/io/sn2/pcibr/pcibr_intr.c	2004-02-23 13:56:37.000000000 +0000
@@ -10,7 +10,6 @@
 #include <linux/module.h>
 #include <asm/sn/sgi.h>
 #include <asm/sn/arch.h>
-#include <asm/sn/iograph.h>
 #include <asm/sn/pci/pciio.h>
 #include <asm/sn/pci/pcibr.h>
 #include <asm/sn/pci/pcibr_private.h>
--- diff/arch/ia64/sn/io/sn2/pcibr/pcibr_reg.c	2004-02-18 08:54:07.000000000 +0000
+++ source/arch/ia64/sn/io/sn2/pcibr/pcibr_reg.c	2004-02-23 13:56:37.000000000 +0000
@@ -8,7 +8,6 @@
 
 #include <linux/types.h>
 #include <asm/sn/sgi.h>
-#include <asm/sn/iograph.h>
 #include <asm/sn/addrs.h>
 #include <asm/sn/pci/pcibr.h>
 #include <asm/sn/pci/pcibr_private.h>
--- diff/arch/ia64/sn/io/sn2/pcibr/pcibr_rrb.c	2004-02-18 08:54:07.000000000 +0000
+++ source/arch/ia64/sn/io/sn2/pcibr/pcibr_rrb.c	2004-02-23 13:56:37.000000000 +0000
@@ -8,7 +8,6 @@
 
 #include <linux/types.h>
 #include <asm/sn/sgi.h>
-#include <asm/sn/iograph.h>
 #include <asm/sn/pci/pciio.h>
 #include <asm/sn/pci/pcibr.h>
 #include <asm/sn/pci/pcibr_private.h>
--- diff/arch/ia64/sn/io/sn2/pic.c	2004-02-18 08:54:07.000000000 +0000
+++ source/arch/ia64/sn/io/sn2/pic.c	2004-02-23 13:56:37.000000000 +0000
@@ -90,10 +90,15 @@ pic_bus1_widget_info_dup(vertex_hdl_t co
     		peer_widget_info->w_efunc = 0;
     		peer_widget_info->w_einfo = 0;
 		peer_widget_info->w_name = kmalloc(strlen(peer_path) + 1, GFP_KERNEL);
+		if (!peer_widget_info->w_name) {
+			kfree(peer_widget_info);
+			return -ENOMEM;
+		}
 		strcpy(peer_widget_info->w_name, peer_path);
 
 		if (hwgraph_info_add_LBL(peer_conn_v, INFO_LBL_XWIDGET,
 			(arbitrary_info_t)peer_widget_info) != GRAPH_SUCCESS) {
+			kfree(peer_widget_info->w_name);
 				kfree(peer_widget_info);
 				return 0;
 		}
@@ -359,6 +364,9 @@ pic_attach2(vertex_hdl_t xconn_vhdl, voi
 
     s = dev_to_name(pcibr_vhdl, devnm, MAXDEVNAME);
     pcibr_soft->bs_name = kmalloc(strlen(s) + 1, GFP_KERNEL);
+    if (!pcibr_soft->bs_name)
+	    return -ENOMEM;
+
     strcpy(pcibr_soft->bs_name, s);
 
     pcibr_soft->bs_conn = xconn_vhdl;
--- diff/arch/ia64/sn/io/sn2/shub.c	2004-02-09 10:36:07.000000000 +0000
+++ source/arch/ia64/sn/io/sn2/shub.c	2004-02-23 13:56:37.000000000 +0000
@@ -17,7 +17,6 @@
 #include <asm/system.h>
 #include <asm/sn/sgi.h>
 #include <asm/uaccess.h>
-#include <asm/sn/iograph.h>
 #include <asm/sn/hcl.h>
 #include <asm/sn/labelcl.h>
 #include <asm/sn/io.h>
--- diff/arch/ia64/sn/io/sn2/shub_intr.c	2004-02-09 10:36:07.000000000 +0000
+++ source/arch/ia64/sn/io/sn2/shub_intr.c	2004-02-23 13:56:37.000000000 +0000
@@ -11,7 +11,6 @@
 #include <asm/sn/types.h>
 #include <asm/sn/sgi.h>
 #include <asm/sn/driver.h>
-#include <asm/sn/iograph.h>
 #include <asm/param.h>
 #include <asm/sn/pio.h>
 #include <asm/sn/xtalk/xwidget.h>
--- diff/arch/ia64/sn/io/sn2/shuberror.c	2004-02-18 08:54:07.000000000 +0000
+++ source/arch/ia64/sn/io/sn2/shuberror.c	2004-02-23 13:56:37.000000000 +0000
@@ -16,7 +16,6 @@
 #include <asm/delay.h>
 #include <asm/sn/sgi.h>
 #include <asm/sn/io.h>
-#include <asm/sn/iograph.h>
 #include <asm/sn/hcl.h>
 #include <asm/sn/labelcl.h>
 #include <asm/sn/sn_private.h>
--- diff/arch/ia64/sn/io/xswitch.c	2004-02-18 08:54:07.000000000 +0000
+++ source/arch/ia64/sn/io/xswitch.c	2004-02-23 13:56:37.000000000 +0000
@@ -11,7 +11,6 @@
 #include <asm/errno.h>
 #include <asm/sn/sgi.h>
 #include <asm/sn/driver.h>
-#include <asm/sn/iograph.h>
 #include <asm/sn/hcl.h>
 #include <asm/sn/labelcl.h>
 #include <asm/sn/xtalk/xtalk.h>
--- diff/arch/ia64/sn/kernel/irq.c	2004-02-18 08:54:07.000000000 +0000
+++ source/arch/ia64/sn/kernel/irq.c	2004-02-23 13:56:37.000000000 +0000
@@ -18,7 +18,6 @@
 #include <asm/page.h>
 #include <asm/pgtable.h>
 #include <asm/sn/sgi.h>
-#include <asm/sn/iograph.h>
 #include <asm/sn/hcl.h>
 #include <asm/sn/types.h>
 #include <asm/sn/pci/pciio.h>
@@ -121,7 +120,7 @@ sn_end_irq(unsigned int irq)
 static void
 sn_set_affinity_irq(unsigned int irq, unsigned long cpu)
 {
-#if CONFIG_SMP
+#ifdef CONFIG_SMP
 	int redir = 0;
 	struct sn_intr_list_t *p = sn_intr_list[irq];
 	pcibr_intr_t intr;
--- diff/arch/ia64/sn/kernel/setup.c	2004-02-18 08:54:07.000000000 +0000
+++ source/arch/ia64/sn/kernel/setup.c	2004-02-23 13:56:37.000000000 +0000
@@ -85,6 +85,7 @@ int	numionodes;
 u64 master_node_bedrock_address;
 
 static void sn_init_pdas(char **);
+static void scan_for_ionodes(void);
 
 
 static nodepda_t	*nodepdaindr[MAX_COMPACT_NODES];
@@ -131,7 +132,7 @@ char drive_info[4*16];
  * may not be initialized yet.
  */
 
-static int
+static int __init
 pxm_to_nasid(int pxm)
 {
 	int i;
@@ -358,11 +359,10 @@ sn_setup(char **cmdline_p)
  *
  * One time setup for Node Data Area.  Called by sn_setup().
  */
-void
+void __init
 sn_init_pdas(char **cmdline_p)
 {
 	cnodeid_t	cnode;
-	void scan_for_ionodes(void);
 
 	/*
 	 * Make sure that the PDA fits entirely in the same page as the 
@@ -498,7 +498,7 @@ sn_cpu_init(void)
  * physical_node_map and the pda and increment numionodes.
  */
 
-void
+static void __init
 scan_for_ionodes(void)
 {
 	int nasid = 0;
--- diff/arch/m68k/Kconfig	2004-02-18 08:54:07.000000000 +0000
+++ source/arch/m68k/Kconfig	2004-02-23 13:56:37.000000000 +0000
@@ -70,8 +70,21 @@ config PCMCIA
 	  To compile this driver as modules, choose M here: the
 	  modules will be called pcmcia_core and ds.
 
+config SUN3
+	bool "Sun3 support"
+	select M68020
+	select MMU_SUN3 if MMU
+	help
+	  This option enables support for the Sun 3 series of workstations
+	  (3/50, 3/60, 3/1xx, 3/2xx systems). Enabling this option requires 
+	  that all other hardware types must be disabled, as Sun 3 kernels 
+	  are incompatible with all other m68k targets (including Sun 3x!).  
+
+	  If you don't want to compile a kernel exclusively for a Sun 3, say N.
+
 config AMIGA
 	bool "Amiga support"
+	depends on !MMU_SUN3
 	help
 	  This option enables support for the Amiga series of computers. If
 	  you plan to use this kernel on an Amiga, say Y here and browse the
@@ -79,6 +92,7 @@ config AMIGA
 
 config ATARI
 	bool "Atari support"
+	depends on !MMU_SUN3
 	help
 	  This option enables support for the 68000-based Atari series of
 	  computers (including the TT, Falcon and Medusa). If you plan to use
@@ -109,6 +123,7 @@ config PCI
 
 config MAC
 	bool "Macintosh support"
+	depends on !MMU_SUN3
 	help
 	  This option enables support for the Apple Macintosh series of
 	  computers (yes, there is experimental support now, at least for part
@@ -129,12 +144,14 @@ config M68K_L2_CACHE
 
 config APOLLO
 	bool "Apollo support"
+	depends on !MMU_SUN3
 	help
 	  Say Y here if you want to run Linux on an MC680x0-based Apollo
 	  Domain workstation such as the DN3500.
 
 config VME
 	bool "VME (Motorola and BVM) support"
+	depends on !MMU_SUN3
 	help
 	  Say Y here if you want to build a kernel for a 680x0 based VME
 	  board.  Boards currently supported include Motorola boards MVME147,
@@ -171,6 +188,7 @@ config BVME6000
 
 config HP300
 	bool "HP9000/300 support"
+	depends on !MMU_SUN3
 	help
 	  This option enables support for the HP9000/300 series of
 	  workstations. Support for these machines is still very experimental.
@@ -187,30 +205,20 @@ config DIO
 
 config SUN3X
 	bool "Sun3x support"
+	depends on !MMU_SUN3
+	select M68030
 	help
 	  This option enables support for the Sun 3x series of workstations.
-	  Be warned that this support is very experimental. You will also want
-	  to say Y to 68030 support and N to the other processors below.
+	  Be warned that this support is very experimental.
 	  Note that Sun 3x kernels are not compatible with Sun 3 hardware.
 	  General Linux information on the Sun 3x series (now discontinued)
 	  is at <http://www.angelfire.com/ca2/tech68k/sun3.html>.
 
 	  If you don't want to compile a kernel for a Sun 3x, say N.
 
-config SUN3
-	bool "Sun3 support"
-	help
-	  This option enables support for the Sun 3 series of workstations
-	  (3/50, 3/60, 3/1xx, 3/2xx systems). Enabling this option requires 
-	  that all other hardware types must be disabled, as Sun 3 kernels 
-	  are incompatible with all other m68k targets (including Sun 3x!).  
-	  Also, you will want to say Y to 68020 support and N to the other 
-	  processors below.
-
-	  If you don't want to compile a kernel exclusively for a Sun 3, say N.
-
 config Q40
 	bool "Q40/Q60 support"
+	depends on !MMU_SUN3
 	help
 	  The Q40 is a Motorola 68040-based successor to the Sinclair QL
 	  manufactured in Germany.  There is an official Q40 home page at
@@ -230,6 +238,7 @@ config M68020
 
 config M68030
 	bool "68030 support"
+	depends on !MMU_SUN3
 	help
 	  If you anticipate running this kernel on a computer with a MC68030
 	  processor, say Y. Otherwise, say N. Note that a MC68EC030 will not
@@ -237,6 +246,7 @@ config M68030
 
 config M68040
 	bool "68040 support"
+	depends on !MMU_SUN3
 	help
 	  If you anticipate running this kernel on a computer with a MC68LC040
 	  or MC68040 processor, say Y. Otherwise, say N. Note that an
@@ -245,10 +255,19 @@ config M68040
 
 config M68060
 	bool "68060 support"
+	depends on !MMU_SUN3
 	help
 	  If you anticipate running this kernel on a computer with a MC68060
 	  processor, say Y. Otherwise, say N.
 
+config MMU_MOTOROLA
+	bool
+	depends on MMU && !MMU_SUN3
+	default y
+
+config MMU_SUN3
+	bool
+
 config M68KFPU_EMU
 	bool "Math emulation support (EXPERIMENTAL)"
 	depends on EXPERIMENTAL
@@ -404,105 +423,6 @@ config PROC_HARDWARE
 	  including the model, CPU, MMU, clock speed, BogoMIPS rating,
 	  and memory size.
 
-config PARPORT
-	tristate "Parallel port support (EXPERIMENTAL)"
-	depends on EXPERIMENTAL
-	---help---
-	  If you want to use devices connected to your machine's parallel port
-	  (the connector at the computer with 25 holes), e.g. printer, ZIP
-	  drive, PLIP link (Parallel Line Internet Protocol is mainly used to
-	  create a mini network by connecting the parallel ports of two local
-	  machines) etc., then you need to say Y here; please read
-	  <file:Documentation/parport.txt> and
-	  <file:drivers/parport/BUGS-parport>.
-
-	  For extensive information about drivers for many devices attaching
-	  to the parallel port see <http://www.torque.net/linux-pp.html> on
-	  the WWW.
-
-	  It is possible to share a single parallel port among several devices
-	  and it is safe to compile all the corresponding drivers into the
-	  kernel. To compile parallel port support as a module, choose M here:
-	  the module will be called parport.
-	  If you have more than one parallel port and want to specify which
-	  port and IRQ to be used by this driver at module load time, take a
-	  look at <file:Documentation/parport.txt>.
-
-	  If unsure, say Y.
-
-config PARPORT_AMIGA
-	tristate "Amiga builtin port"
-	depends on AMIGA && PARPORT
-	help
-	  Say Y here if you need support for the parallel port hardware on
-	  Amiga machines. This code is also available as a module (say M),
-	  called parport_amiga. If in doubt, saying N is the safe plan.
-
-config PARPORT_MFC3
-	tristate "Multiface III parallel port"
-	depends on ZORRO && PARPORT
-	help
-	  Say Y here if you need parallel port support for the MFC3 card.
-	  This code is also available as a module (say M), called
-	  parport_mfc3. If in doubt, saying N is the safe plan.
-
-config PARPORT_PC
-	bool
-	depends on Q40 && PARPORT
-	default y
-	---help---
-	  You should say Y here if you have a PC-style parallel port. All IBM
-	  PC compatible computers and some Alphas have PC-style parallel
-	  ports.
-
-	  To compile this driver as a module, choose M here: the
-	  module will be called parport_pc.
-
-	  If unsure, say Y.
-
-config PARPORT_ATARI
-	tristate "Atari builtin port"
-	depends on ATARI && PARPORT
-	help
-	  Say Y here if you need support for the parallel port hardware on
-	  Atari machines. This code is also available as a module (say M),
-	  called parport_atari. If in doubt, saying N is the safe plan.
-
-config PRINTER
-	tristate "Parallel printer support"
-	depends on PARPORT
-	---help---
-	  If you intend to attach a printer to the parallel port of your Linux
-	  box (as opposed to using a serial printer; if the connector at the
-	  printer has 9 or 25 holes ["female"], then it's serial), say Y.
-	  Also read the Printing-HOWTO, available from
-	  <http://www.tldp.org/docs.html#howto>.
-
-	  It is possible to share one parallel port among several devices
-	  (e.g. printer and ZIP drive) and it is safe to compile the
-	  corresponding drivers into the kernel.
-	  To compile this driver as a module, choose M here and read
-	  <file:Documentation/parport.txt>.  The module will be called lp.
-
-	  If you have several parallel ports, you can specify which ports to
-	  use with the "lp" kernel command line option.  (Try "man bootparam"
-	  or see the documentation of your boot loader (lilo or loadlin) about
-	  how to pass options to the kernel at boot time.)  The syntax of the
-	  "lp" command line option can be found in <file:drivers/char/lp.c>.
-
-	  If you have more than 8 printers, you need to increase the LP_NO
-	  macro in lp.c and the PARPORT_MAX macro in parport.h.
-
-config PARPORT_1284
-	bool "IEEE 1284 transfer modes"
-	depends on PRINTER
-	help
-	  If you have a printer that supports status readback or device ID, or
-	  want to use a device that uses enhanced parallel port transfer modes
-	  such as EPP and ECP, say Y here to enable advanced IEEE 1284
-	  transfer modes. Also say Y if you want device ID information to
-	  appear in /proc/sys/dev/parport/*/autoprobe*. It is safe to say N.
-
 config ISA
 	bool
 	depends on Q40 || AMIGA_PCMCIA || GG2
@@ -523,192 +443,13 @@ source "drivers/pci/Kconfig"
 
 source "drivers/zorro/Kconfig"
 
-if Q40
-source "drivers/pnp/Kconfig"
-endif
-
 endmenu
 
-source "drivers/base/Kconfig"
-
-source "drivers/mtd/Kconfig"
-
-source "drivers/block/Kconfig"
-
-source "drivers/md/Kconfig"
-
-source "drivers/input/Kconfig"
-
-source "drivers/ide/Kconfig"
-
-source "drivers/scsi/Kconfig"
-
-source "net/Kconfig"
+source "drivers/Kconfig"
 
 
 menu "Character devices"
 
-config SERIAL
-	tristate "Q40 Standard/generic serial support" if Q40
-	default DN_SERIAL if APOLLO
-	---help---
-	  This selects whether you want to include the driver for the standard
-	  serial ports.  The standard answer is Y.  People who might say N
-	  here are those that are setting up dedicated Ethernet WWW/FTP
-	  servers, or users that have one of the various bus mice instead of a
-	  serial mouse and don't intend to use their machine's standard serial
-	  port for anything.  (Note that the Cyclades and Stallion multi
-	  serial port drivers do not need this driver built in for them to
-	  work.)
-
-	  To compile this driver as a module, choose M here: the
-	  module will be called serial.
-	  [WARNING: Do not compile this driver as a module if you are using
-	  non-standard serial ports, since the configuration information will
-	  be lost when the driver is unloaded.  This limitation may be lifted
-	  in the future.]
-
-	  BTW1: If you have a mouseman serial mouse which is not recognized by
-	  the X window system, try running gpm first.
-
-	  BTW2: If you intend to use a software modem (also called Winmodem)
-	  under Linux, forget it.  These modems are crippled and require
-	  proprietary drivers which are only available under Windows.
-
-	  Most people will say Y or M here, so that they can use serial mice,
-	  modems and similar devices connecting to the standard serial ports.
-
-config SERIAL_EXTENDED
-	bool "Extended dumb serial driver options"
-	depends on SERIAL=y
-	help
-	  If you wish to use any non-standard features of the standard "dumb"
-	  driver, say Y here. This includes HUB6 support, shared serial
-	  interrupts, special multiport support, support for more than the
-	  four COM 1/2/3/4 boards, etc.
-
-	  Note that the answer to this question won't directly affect the
-	  kernel: saying N will just cause the configurator to skip all
-	  the questions about serial driver options. If unsure, say N.
-
-config SERIAL_MANY_PORTS
-	bool "Support more than 4 serial ports"
-	depends on SERIAL_EXTENDED
-	help
-	  Say Y here if you have dumb serial boards other than the four
-	  standard COM 1/2/3/4 ports. This may happen if you have an AST
-	  FourPort, Accent Async, Boca (read the Boca mini-HOWTO, available
-	  from <http://www.tldp.org/docs.html#howto>), or other custom
-	  serial port hardware which acts similar to standard serial port
-	  hardware. If you only use the standard COM 1/2/3/4 ports, you can
-	  say N here to save some memory. You can also say Y if you have an
-	  "intelligent" multiport card such as Cyclades, Digiboards, etc.
-
-config SERIAL_SHARE_IRQ
-	bool "Support for sharing serial interrupts"
-	depends on SERIAL_EXTENDED
-	help
-	  Some serial boards have hardware support which allows multiple dumb
-	  serial ports on the same board to share a single IRQ. To enable
-	  support for this in the serial driver, say Y here.
-
-config SERIAL_MULTIPORT
-	bool "Support special multiport boards"
-	depends on SERIAL_EXTENDED
-	help
-	  Some multiport serial ports have special ports which are used to
-	  signal when there are any serial ports on the board which need
-	  servicing. Say Y here to enable the serial driver to take advantage
-	  of those special I/O ports.
-
-config HUB6
-	bool "Support the Bell Technologies HUB6 card"
-	depends on SERIAL_EXTENDED
-	help
-	  Say Y here to enable support in the dumb serial driver to support
-	  the HUB6 card.
-
-config VT
-	bool "Virtual terminal"
-	---help---
-	  If you say Y here, you will get support for terminal devices with
-	  display and keyboard devices. These are called "virtual" because you
-	  can run several virtual terminals (also called virtual consoles) on
-	  one physical terminal. This is rather useful, for example one
-	  virtual terminal can collect system messages and warnings, another
-	  one can be used for a text-mode user session, and a third could run
-	  an X session, all in parallel. Switching between virtual terminals
-	  is done with certain key combinations, usually Alt-<function key>.
-
-	  The setterm command ("man setterm") can be used to change the
-	  properties (such as colors or beeping) of a virtual terminal. The
-	  man page console_codes(4) ("man console_codes") contains the special
-	  character sequences that can be used to change those properties
-	  directly. The fonts used on virtual terminals can be changed with
-	  the setfont ("man setfont") command and the key bindings are defined
-	  with the loadkeys ("man loadkeys") command.
-
-	  You need at least one virtual terminal device in order to make use
-	  of your keyboard and monitor. Therefore, only people configuring an
-	  embedded system would want to say N here in order to save some
-	  memory; the only way to log into such a system is then via a serial
-	  or network connection.
-
-	  If unsure, say Y, or else you won't be able to do much with your new
-	  shiny Linux system :-)
-
-config VT_CONSOLE
-	bool "Support for console on virtual terminal"
-	depends on VT
-	---help---
-	  The system console is the device which receives all kernel messages
-	  and warnings and which allows logins in single user mode. If you
-	  answer Y here, a virtual terminal (the device used to interact with
-	  a physical terminal) can be used as system console. This is the most
-	  common mode of operations, so you should say Y here unless you want
-	  the kernel messages be output only to a serial port (in which case
-	  you should say Y to "Console on serial port", below).
-
-	  If you do say Y here, by default the currently visible virtual
-	  terminal (/dev/tty0) will be used as system console. You can change
-	  that with a kernel command line option such as "console=tty3" which
-	  would use the third virtual terminal as system console. (Try "man
-	  bootparam" or see the documentation of your boot loader (lilo or
-	  loadlin) about how to pass options to the kernel at boot time.)
-
-	  If unsure, say Y.
-
-config HW_CONSOLE
-	bool
-	depends on VT
-	default y
-
-config NVRAM
-	bool
-	depends on ATARI
-	default y
-	---help---
-	  If you say Y here and create a character special file /dev/nvram
-	  with major number 10 and minor number 144 using mknod ("man mknod"),
-	  you get read and write access to the 50 bytes of non-volatile memory
-	  in the real time clock (RTC), which is contained in every PC and
-	  most Ataris.
-
-	  This memory is conventionally called "CMOS RAM" on PCs and "NVRAM"
-	  on Ataris. /dev/nvram may be used to view settings there, or to
-	  change them (with some utility). It could also be used to frequently
-	  save a few bits of very important data that may not be lost over
-	  power-off and for which writing to disk is too insecure. Note
-	  however that most NVRAM space in a PC belongs to the BIOS and you
-	  should NEVER idly tamper with it. See Ralf Brown's interrupt list
-	  for a guide to the use of CMOS bytes by your BIOS.
-
-	  On Atari machines, /dev/nvram is always configured and does not need
-	  to be selected.
-
-	  To compile this driver as a module, choose M here: the
-	  module will be called nvram.
-
 config ATARI_MFPSER
 	tristate "Atari MFP serial support"
 	depends on ATARI
@@ -787,22 +528,6 @@ config MULTIFACE_III_TTY
 
 	  To compile this driver as a module, choose M here.
 
-config A2232
-	tristate "Commodore A2232 serial support (EXPERIMENTAL)"
-	depends on AMIGA && EXPERIMENTAL
-	---help---
-	  This option supports the 2232 7-port serial card shipped with the
-	  Amiga 2000 and other Zorro-bus machines, dating from 1989.  At
-	  a max of 19,200 bps, the ports are served by a 6551 ACIA UART chip
-	  each, plus a 8520 CIA, and a master 6502 CPU and buffer as well. The
-	  ports were connected with 8 pin DIN connectors on the card bracket,
-	  for which 8 pin to DB25 adapters were supplied. The card also had
-	  jumpers internally to toggle various pinning configurations.
-
-	  This driver can be built as a module; but then "generic_serial"
-	  will also be built as a module. This has to be loaded before
-	  "ser_a2232". If you want to do this, answer M here.
-
 config GVPIOEXT
 	tristate "GVP IO-Extender support"
 	depends on PARPORT=n && ZORRO
@@ -1009,87 +734,10 @@ config SERIAL_CONSOLE
 
 	  If unsure, say N.
 
-config USERIAL
-	bool "Support for user serial device modules"
-
-source "drivers/char/watchdog/Kconfig"
-
-config GEN_RTC
-	tristate "Generic /dev/rtc emulation" if !SUN3
-	default y if SUN3
-	---help---
-	  If you say Y here and create a character special file /dev/rtc with
-	  major number 10 and minor number 135 using mknod ("man mknod"), you
-	  will get access to the real time clock (or hardware clock) built
-	  into your computer.
-
-	  It reports status information via the file /proc/driver/rtc and its
-	  behaviour is set by various ioctls on /dev/rtc. If you enable the
-	  "extended RTC operation" below it will also provide an emulation
-	  for RTC_UIE which is required by some programs and may improve
-	  precision in some cases.
-
-	  To compile this driver as a module, choose M here: the
-	  module will be called genrtc. To load the module automatically
-	  add 'alias char-major-10-135 genrtc' to your /etc/modules.conf
-
-config GEN_RTC_X
-	bool "Extended RTC operation"
-	depends on GEN_RTC
-	help
-	  Provides an emulation for RTC_UIE which is required by some programs
-	  and may improve precision of the generic RTC support in some cases.
-
-config UNIX98_PTYS
-	bool "Unix98 PTY support"
-	---help---
-	  A pseudo terminal (PTY) is a software device consisting of two
-	  halves: a master and a slave. The slave device behaves identical to
-	  a physical terminal; the master device is used by a process to
-	  read data from and write data to the slave, thereby emulating a
-	  terminal. Typical programs for the master side are telnet servers
-	  and xterms.
-
-	  Linux has traditionally used the BSD-like names /dev/ptyxx for
-	  masters and /dev/ttyxx for slaves of pseudo terminals. This scheme
-	  has a number of problems. The GNU C library glibc 2.1 and later,
-	  however, supports the Unix98 naming standard: in order to acquire a
-	  pseudo terminal, a process opens /dev/ptmx; the number of the pseudo
-	  terminal is then made available to the process and the pseudo
-	  terminal slave can be accessed as /dev/pts/<number>. What was
-	  traditionally /dev/ttyp2 will then be /dev/pts/2, for example.
-
-	  The entries in /dev/pts/ are created on the fly by a virtual
-	  file system; therefore, if you say Y here you should say Y to
-	  "/dev/pts file system for Unix98 PTYs" as well.
-
-	  If you want to say Y here, you need to have the C library glibc 2.1
-	  or later (equal to libc-6.1, check with "ls -l /lib/libc.so.*").
-	  Read the instructions in <file:Documentation/Changes> pertaining to
-	  pseudo terminals. It's safe to say N.
-
-config UNIX98_PTY_COUNT
-	int "Maximum number of Unix98 PTYs in use (0-2048)"
-	depends on UNIX98_PTYS
-	default "256"
-	help
-	  The maximum number of Unix98 PTYs that can be used at any one time.
-	  The default is 256, and should be enough for desktop systems. Server
-	  machines which support incoming telnet/rlogin/ssh connections and/or
-	  serve several X terminals may want to increase this: every incoming
-	  connection and every xterm uses up one PTY.
-
-	  When not in use, each additional set of 256 PTYs occupy
-	  approximately 8 KB of kernel memory on 32-bit architectures.
-
 endmenu
 
-source "sound/Kconfig"
-
 source "fs/Kconfig"
 
-source "drivers/video/Kconfig"
-
 menu "Kernel hacking"
 
 config DEBUG_KERNEL
--- diff/arch/m68k/Makefile	2003-10-09 09:47:33.000000000 +0100
+++ source/arch/m68k/Makefile	2004-02-23 13:56:37.000000000 +0000
@@ -111,6 +111,14 @@ else
 	bzip2 -1c vmlinux >vmlinux.bz2
 endif
 
+prepare: include/asm-$(ARCH)/offsets.h
+CLEAN_FILES += include/asm-$(ARCH)/offsets.h
+
+arch/$(ARCH)/kernel/asm-offsets.s: include/asm include/linux/version.h \
+				   include/config/MARKER
+
+include/asm-$(ARCH)/offsets.h: arch/$(ARCH)/kernel/asm-offsets.s
+	$(call filechk,gen-asm-offsets)
+
 archclean:
 	rm -f vmlinux.gz vmlinux.bz2
-	rm -f arch/m68k/kernel/m68k_defs.h arch/m68k/kernel/m68k_defs.d
--- diff/arch/m68k/amiga/amiints.c	2003-06-09 14:18:17.000000000 +0100
+++ source/arch/m68k/amiga/amiints.c	2004-02-23 13:56:37.000000000 +0000
@@ -49,6 +49,7 @@
 #include <asm/amigahw.h>
 #include <asm/amigaints.h>
 #include <asm/amipcmcia.h>
+#include <asm/unistd.h>
 
 extern int cia_request_irq(struct ciabase *base,int irq,
                            irqreturn_t (*handler)(int, void *, struct pt_regs *),
--- diff/arch/m68k/atari/config.c	2003-06-09 14:18:17.000000000 +0100
+++ source/arch/m68k/atari/config.c	2004-02-23 13:56:37.000000000 +0000
@@ -344,7 +344,7 @@ void __init config_atari(void)
 	ATARIHW_SET(PCM_8BIT);
         printk( "PCM " );
     }
-    if (!MACH_IS_HADES && hwreg_present( &codec.unused5 )) {
+    if (!MACH_IS_HADES && hwreg_present( &falcon_codec.unused5 )) {
 	ATARIHW_SET(CODEC);
         printk( "CODEC " );
     }
--- diff/arch/m68k/bvme6000/bvmeints.c	2003-06-09 14:18:17.000000000 +0100
+++ source/arch/m68k/bvme6000/bvmeints.c	2004-02-23 13:56:37.000000000 +0000
@@ -20,6 +20,7 @@
 #include <asm/system.h>
 #include <asm/irq.h>
 #include <asm/traps.h>
+#include <asm/unistd.h>
 
 static irqreturn_t bvme6000_defhand (int irq, void *dev_id, struct pt_regs *fp);
 
--- diff/arch/m68k/fpsp040/skeleton.S	2002-11-11 11:09:42.000000000 +0000
+++ source/arch/m68k/fpsp040/skeleton.S	2004-02-23 13:56:37.000000000 +0000
@@ -40,7 +40,7 @@
 
 #include <linux/linkage.h>
 #include <asm/entry.h>
-#include "../kernel/m68k_defs.h"
+#include <asm/offsets.h>
 
 |SKELETON	idnt    2,1 | Motorola 040 Floating Point Software Package
 
--- diff/arch/m68k/hp300/time.c	2003-06-09 14:18:17.000000000 +0100
+++ source/arch/m68k/hp300/time.c	2004-02-23 13:56:37.000000000 +0000
@@ -17,6 +17,7 @@
 #include <asm/io.h>
 #include <asm/system.h>
 #include <asm/traps.h>
+#include <asm/unistd.h>
 #include "ints.h"
 
 /* Clock hardware definitions */
--- diff/arch/m68k/ifpsp060/iskeleton.S	2003-05-21 11:49:54.000000000 +0100
+++ source/arch/m68k/ifpsp060/iskeleton.S	2004-02-23 13:56:37.000000000 +0000
@@ -36,7 +36,7 @@
 
 #include <linux/linkage.h>
 #include <asm/entry.h>
-#include "../kernel/m68k_defs.h"
+#include <asm/offsets.h>
 
 
 |################################
--- diff/arch/m68k/kernel/Makefile	2003-08-26 10:00:52.000000000 +0100
+++ source/arch/m68k/kernel/Makefile	2004-02-23 13:56:37.000000000 +0000
@@ -16,20 +16,3 @@ obj-$(CONFIG_PCI)	+= bios32.o
 obj-$(CONFIG_MODULES)	+= module.o
 
 EXTRA_AFLAGS := -traditional
-
-$(obj)/head.o: $(obj)/head.S $(obj)/m68k_defs.h
-
-$(obj)/entry.o: $(obj)/entry.S $(obj)/m68k_defs.h
-
-$(obj)/sun3-head.o: $(obj)/sun3-head.S $(obj)/m68k_defs.h
-
-$(obj)/m68k_defs.h: $(src)/m68k_defs.c $(src)/m68k_defs.head
-	rm -f $(obj)/m68k_defs.d
-	SUNPRO_DEPENDENCIES="$(obj)/m68k_defs.d $(obj)/m68k_defs.h" \
-	$(CC) $(filter-out -MD,$(CFLAGS)) -S $(src)/m68k_defs.c -o \
-	$(obj)/m68k_defs.s
-	cp $(src)/m68k_defs.head $(obj)/m68k_defs.h
-	grep '^#define' $(obj)/m68k_defs.s >> $(obj)/m68k_defs.h
-	rm $(obj)/m68k_defs.s
--include $(obj)/m68k_defs.d
-
--- diff/arch/m68k/kernel/entry.S	2003-08-20 14:16:08.000000000 +0100
+++ source/arch/m68k/kernel/entry.S	2004-02-23 13:56:37.000000000 +0000
@@ -42,7 +42,7 @@
 #include <asm/traps.h>
 #include <asm/unistd.h>
 
-#include "m68k_defs.h"
+#include <asm/offsets.h>
 
 .globl system_call, buserr, trap
 .globl resume, ret_from_exception
--- diff/arch/m68k/kernel/head.S	2004-02-09 10:36:07.000000000 +0000
+++ source/arch/m68k/kernel/head.S	2004-02-23 13:56:37.000000000 +0000
@@ -262,7 +262,7 @@
 #include <asm/entry.h>
 #include <asm/pgtable.h>
 #include <asm/page.h>
-#include "m68k_defs.h"
+#include <asm/offsets.h>
 
 #ifdef CONFIG_MAC
 
--- diff/arch/m68k/kernel/module.c	2003-08-20 14:16:08.000000000 +0100
+++ source/arch/m68k/kernel/module.c	2004-02-23 13:56:37.000000000 +0000
@@ -82,9 +82,38 @@ int apply_relocate_add(Elf32_Shdr *sechd
 		       unsigned int relsec,
 		       struct module *me)
 {
-	printk(KERN_ERR "module %s: ADD RELOCATION unsupported\n",
-	       me->name);
-	return -ENOEXEC;
+	unsigned int i;
+	Elf32_Rela *rel = (void *)sechdrs[relsec].sh_addr;
+	Elf32_Sym *sym;
+	uint32_t *location;
+
+	DEBUGP("Applying relocate_add section %u to %u\n", relsec,
+	       sechdrs[relsec].sh_info);
+	for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) {
+		/* This is where to make the change */
+		location = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr
+			+ rel[i].r_offset;
+		/* This is the symbol it is referring to.  Note that all
+		   undefined symbols have been resolved.  */
+		sym = (Elf32_Sym *)sechdrs[symindex].sh_addr
+			+ ELF32_R_SYM(rel[i].r_info);
+
+		switch (ELF32_R_TYPE(rel[i].r_info)) {
+		case R_68K_32:
+			/* We add the value into the location given */
+			*location = rel[i].r_addend + sym->st_value;
+			break;
+		case R_68K_PC32:
+			/* Add the value, subtract its postition */
+			*location = rel[i].r_addend + sym->st_value - (uint32_t)location;
+			break;
+		default:
+			printk(KERN_ERR "module %s: Unknown relocation: %u\n",
+			       me->name, ELF32_R_TYPE(rel[i].r_info));
+			return -ENOEXEC;
+		}
+	}
+	return 0;
 }
 
 int module_finalize(const Elf_Ehdr *hdr,
--- diff/arch/m68k/kernel/setup.c	2003-06-09 14:18:17.000000000 +0100
+++ source/arch/m68k/kernel/setup.c	2004-02-23 13:56:37.000000000 +0000
@@ -538,7 +538,6 @@ void check_bugs(void)
 				"WHICH IS REQUIRED BY LINUX/M68K ***\n" );
 		printk( KERN_EMERG "Upgrade your hardware or join the FPU "
 				"emulation project\n" );
-		printk( KERN_EMERG "(see http://no-fpu.linux-m68k.org)\n" );
 		panic( "no FPU" );
 	}
 
--- diff/arch/m68k/kernel/signal.c	2003-09-30 15:46:11.000000000 +0100
+++ source/arch/m68k/kernel/signal.c	2004-02-23 13:56:37.000000000 +0000
@@ -32,6 +32,7 @@
 #include <linux/mm.h>
 #include <linux/kernel.h>
 #include <linux/signal.h>
+#include <linux/syscalls.h>
 #include <linux/errno.h>
 #include <linux/wait.h>
 #include <linux/ptrace.h>
--- diff/arch/m68k/kernel/sys_m68k.c	2003-06-09 14:18:17.000000000 +0100
+++ source/arch/m68k/kernel/sys_m68k.c	2004-02-23 13:56:37.000000000 +0000
@@ -15,6 +15,7 @@
 #include <linux/msg.h>
 #include <linux/shm.h>
 #include <linux/stat.h>
+#include <linux/syscalls.h>
 #include <linux/mman.h>
 #include <linux/file.h>
 #include <linux/utsname.h>
@@ -156,8 +157,6 @@ out:
 }
 #endif
 
-extern asmlinkage int sys_select(int, fd_set *, fd_set *, fd_set *, struct timeval *);
-
 struct sel_arg_struct {
 	unsigned long n;
 	fd_set *inp, *outp, *exp;
@@ -262,7 +261,7 @@ asmlinkage int sys_ipc (uint call, int f
 	return -EINVAL;
 }
 
-asmlinkage int sys_ioperm(unsigned long from, unsigned long num, int on)
+asmlinkage long sys_ioperm(unsigned long from, unsigned long num, int on)
 {
   return -ENOSYS;
 }
--- diff/arch/m68k/kernel/time.c	2003-10-09 09:47:33.000000000 +0100
+++ source/arch/m68k/kernel/time.c	2004-02-23 13:56:37.000000000 +0000
@@ -174,6 +174,7 @@ int do_settimeofday(struct timespec *tv)
 	time_maxerror = NTP_PHASE_LIMIT;
 	time_esterror = NTP_PHASE_LIMIT;
 	write_sequnlock_irq(&xtime_lock);
+	clock_was_set();
 	return 0;
 }
 
--- diff/arch/m68k/kernel/traps.c	2004-02-09 10:36:07.000000000 +0000
+++ source/arch/m68k/kernel/traps.c	2004-02-23 13:56:37.000000000 +0000
@@ -30,6 +30,7 @@
 #include <linux/linkage.h>
 #include <linux/init.h>
 #include <linux/ptrace.h>
+#include <linux/kallsyms.h>
 
 #include <asm/setup.h>
 #include <asm/fpu.h>
@@ -645,7 +646,7 @@ static inline void bus_error030 (struct 
 			if (do_page_fault (&fp->ptregs, addr, errorcode) < 0)
 				return;
 		} else if (!(mmusr & MMU_I)) {
-			/* propably a 020 cas fault */
+			/* probably a 020 cas fault */
 			if (!(ssw & RM))
 				printk("unexpected bus error (%#x,%#x)\n", ssw, mmusr);
 		} else if (mmusr & (MMU_B|MMU_L|MMU_S)) {
@@ -825,9 +826,12 @@ void show_trace(unsigned long *stack)
 		 * out the call path that was taken.
 		 */
 		if (kernel_text_address(addr)) {
-			if (i % 4 == 0)
+#ifndef CONFIG_KALLSYMS
+			if (i % 5 == 0)
 				printk("\n       ");
+#endif
 			printk(" [<%08lx>]", addr);
+			print_symbol(" %s\n", addr);
 			i++;
 		}
 	}
@@ -1098,8 +1102,10 @@ void die_if_kernel (char *str, struct pt
 
 	console_verbose();
 	printk("%s: %08x\n",str,nr);
-	printk("PC: [<%08lx>]\nSR: %04x  SP: %p  a2: %08lx\n",
-	       fp->pc, fp->sr, fp, fp->a2);
+	printk("PC: [<%08lx>]",fp->pc);
+	print_symbol(" %s\n", fp->pc);
+	printk("\nSR: %04x  SP: %p  a2: %08lx\n",
+	       fp->sr, fp, fp->a2);
 	printk("d0: %08lx    d1: %08lx    d2: %08lx    d3: %08lx\n",
 	       fp->d0, fp->d1, fp->d2, fp->d3);
 	printk("d4: %08lx    d5: %08lx    a0: %08lx    a1: %08lx\n",
--- diff/arch/m68k/mac/iop.c	2003-06-09 14:18:17.000000000 +0100
+++ source/arch/m68k/mac/iop.c	2004-02-23 13:56:37.000000000 +0000
@@ -87,7 +87,7 @@
  * or more messages on the receive channels have gone to the MSG_NEW state.
  *
  * Since each channel handles only one message we have to implement a small
- * interrupt-driven queue on our end. Messages to e sent are placed on the
+ * interrupt-driven queue on our end. Messages to be sent are placed on the
  * queue for sending and contain a pointer to an optional callback function.
  * The handler for a message is called when the message state goes to
  * MSG_COMPLETE.
@@ -118,6 +118,7 @@
 #include <asm/macints.h> 
 #include <asm/mac_iop.h>
 #include <asm/mac_oss.h>
+#include <asm/unistd.h>
 
 /*#define DEBUG_IOP*/
 
--- diff/arch/m68k/mac/macints.c	2003-06-09 14:18:17.000000000 +0100
+++ source/arch/m68k/mac/macints.c	2004-02-23 13:56:37.000000000 +0000
@@ -132,8 +132,8 @@
 #include <asm/mac_psc.h>
 #include <asm/hwtest.h>
 #include <asm/errno.h>
-
 #include <asm/macints.h>
+#include <asm/unistd.h>
 
 #define DEBUG_SPURIOUS
 #define SHUTUP_SONIC
--- diff/arch/m68k/mac/oss.c	2003-06-09 14:18:17.000000000 +0100
+++ source/arch/m68k/mac/oss.c	2004-02-23 13:56:37.000000000 +0000
@@ -26,6 +26,7 @@
 #include <asm/macints.h>
 #include <asm/mac_via.h>
 #include <asm/mac_oss.h>
+#include <asm/unistd.h>
 
 int oss_present;
 volatile struct mac_oss *oss;
--- diff/arch/m68k/mac/psc.c	2003-06-09 14:18:17.000000000 +0100
+++ source/arch/m68k/mac/psc.c	2004-02-23 13:56:37.000000000 +0000
@@ -24,6 +24,7 @@
 #include <asm/macintosh.h> 
 #include <asm/macints.h> 
 #include <asm/mac_psc.h>
+#include <asm/unistd.h>
 
 #define DEBUG_PSC
 
--- diff/arch/m68k/mac/via.c	2003-06-09 14:18:17.000000000 +0100
+++ source/arch/m68k/mac/via.c	2004-02-23 13:56:37.000000000 +0000
@@ -23,7 +23,6 @@
 #include <linux/mm.h>
 #include <linux/delay.h>
 #include <linux/init.h>
-
 #include <linux/ide.h>
 
 #include <asm/traps.h>
@@ -33,6 +32,7 @@
 #include <asm/machw.h> 
 #include <asm/mac_via.h>
 #include <asm/mac_psc.h>
+#include <asm/unistd.h>
 
 volatile __u8 *via1, *via2;
 #if 0
--- diff/arch/m68k/math-emu/fp_emu.h	2003-08-20 14:16:08.000000000 +0100
+++ source/arch/m68k/math-emu/fp_emu.h	2004-02-23 13:56:37.000000000 +0000
@@ -39,7 +39,7 @@
 #define _FP_EMU_H
 
 #ifdef __ASSEMBLY__
-#include "../kernel/m68k_defs.h"
+#include <asm/offsets.h>
 #endif
 #include <asm/math-emu.h>
 
--- diff/arch/m68k/mm/Makefile	2004-02-09 10:36:07.000000000 +0000
+++ source/arch/m68k/mm/Makefile	2004-02-23 13:56:37.000000000 +0000
@@ -4,8 +4,5 @@
 
 obj-y		:= init.o fault.o hwtest.o
 
-ifndef CONFIG_SUN3
-obj-y		+= kmap.o memory.o motorola.o
-else
-obj-y		+= sun3kmap.o sun3mmu.o
-endif
+obj-$(CONFIG_MMU_MOTOROLA)	+= kmap.o memory.o motorola.o
+obj-$(CONFIG_MMU_SUN3)		+= sun3kmap.o sun3mmu.o
--- diff/arch/m68k/mm/init.c	2003-08-20 14:16:08.000000000 +0100
+++ source/arch/m68k/mm/init.c	2004-02-23 13:56:37.000000000 +0000
@@ -82,7 +82,9 @@ void __init mem_init(void)
 	int datapages = 0;
 	int initpages = 0;
 	unsigned long tmp;
+#ifndef CONFIG_SUN3
 	int i;
+#endif
 
 	max_mapnr = num_physpages = (((unsigned long)high_memory - PAGE_OFFSET) >> PAGE_SHIFT);
 
--- diff/arch/m68k/q40/q40ints.c	2004-02-09 10:36:07.000000000 +0000
+++ source/arch/m68k/q40/q40ints.c	2004-02-23 13:56:38.000000000 +0000
@@ -26,6 +26,7 @@
 #include <asm/irq.h>
 #include <asm/hardirq.h>
 #include <asm/traps.h>
+#include <asm/unistd.h>
 
 #include <asm/q40_master.h>
 #include <asm/q40ints.h>
--- diff/arch/m68k/sun3/config.c	2003-10-09 09:47:33.000000000 +0100
+++ source/arch/m68k/sun3/config.c	2004-02-23 13:56:38.000000000 +0000
@@ -160,7 +160,7 @@ void __init config_sun3(void)
 	mach_hwclk           =  sun3_hwclk;
 	mach_halt	     =  sun3_halt;
 	mach_get_hardware_list = sun3_get_hardware_list;
-#if !defined(CONFIG_SERIAL_CONSOLE) && defined(CONFIG_DUMMY_CONSOLE)
+#if defined(CONFIG_DUMMY_CONSOLE)
 	conswitchp 	     = &dummy_con;
 #endif
 
--- diff/arch/m68k/sun3/sun3ints.c	2003-06-09 14:18:17.000000000 +0100
+++ source/arch/m68k/sun3/sun3ints.c	2004-02-23 13:56:38.000000000 +0000
@@ -15,6 +15,7 @@
 #include <asm/intersil.h>
 #include <asm/oplib.h>
 #include <asm/sun3ints.h>
+#include <asm/unistd.h>
 #include <linux/seq_file.h>
 
 extern void sun3_leds (unsigned char);
--- diff/arch/m68knommu/Kconfig	2003-09-30 15:46:11.000000000 +0100
+++ source/arch/m68knommu/Kconfig	2004-02-23 13:56:37.000000000 +0000
@@ -464,24 +464,6 @@ config COMEMPCI
 
 source "drivers/pci/Kconfig"
 
-config HOTPLUG
-	bool "Support for hot-pluggable device"
-	  ---help---
-	  Say Y here if you want to plug devices into your computer while
-	  the system is running, and be able to use them quickly.  In many
-	  cases, the devices can likewise be unplugged at any time too.
-
-	  One well known example of this is PCMCIA- or PC-cards, credit-card
-	  size devices such as network cards, modems or hard drives which are
-	  plugged into slots found on all modern laptop computers.  Another
-	  example, used on modern desktops as well as laptops, is USB.
-
-	  Enable HOTPLUG and KMOD, and build a modular kernel.  Get agent
-	  software (at <http://linux-hotplug.sourceforge.net/>) and install it.
-	  Then your kernel will automatically call out to a user mode "policy
-	  agent" (/sbin/hotplug) to load modules and set up software needed
-	  to use devices as you hotplug them.
-
 source "drivers/pcmcia/Kconfig"
 
 source "drivers/pci/hotplug/Kconfig"
--- diff/arch/m68knommu/kernel/signal.c	2003-09-30 15:46:11.000000000 +0100
+++ source/arch/m68knommu/kernel/signal.c	2004-02-23 13:56:38.000000000 +0000
@@ -32,6 +32,7 @@
 #include <linux/mm.h>
 #include <linux/kernel.h>
 #include <linux/signal.h>
+#include <linux/syscalls.h>
 #include <linux/errno.h>
 #include <linux/wait.h>
 #include <linux/ptrace.h>
@@ -50,8 +51,6 @@
 
 #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
 
-asmlinkage long sys_wait4(pid_t pid, unsigned int * stat_addr, int options,
-			struct rusage * ru);
 asmlinkage int do_signal(sigset_t *oldset, struct pt_regs *regs);
 
 /*
--- diff/arch/m68knommu/kernel/sys_m68k.c	2002-11-11 11:09:42.000000000 +0000
+++ source/arch/m68knommu/kernel/sys_m68k.c	2004-02-23 13:56:38.000000000 +0000
@@ -15,6 +15,7 @@
 #include <linux/msg.h>
 #include <linux/shm.h>
 #include <linux/stat.h>
+#include <linux/syscalls.h>
 #include <linux/mman.h>
 #include <linux/file.h>
 #include <linux/utsname.h>
@@ -111,8 +112,6 @@ out:
 	return error;
 }
 
-extern asmlinkage int sys_select(int, fd_set *, fd_set *, fd_set *, struct timeval *);
-
 struct sel_arg_struct {
 	unsigned long n;
 	fd_set *inp, *outp, *exp;
@@ -194,7 +193,7 @@ asmlinkage int sys_ipc (uint call, int f
 	return -EINVAL;
 }
 
-asmlinkage int sys_ioperm(unsigned long from, unsigned long num, int on)
+asmlinkage long sys_ioperm(unsigned long from, unsigned long num, int on)
 {
   return -ENOSYS;
 }
--- diff/arch/m68knommu/kernel/time.c	2004-02-09 10:36:07.000000000 +0000
+++ source/arch/m68knommu/kernel/time.c	2004-02-23 13:56:38.000000000 +0000
@@ -199,6 +199,7 @@ int do_settimeofday(struct timespec *tv)
 	time_maxerror = NTP_PHASE_LIMIT;
 	time_esterror = NTP_PHASE_LIMIT;
 	write_sequnlock_irq(&xtime_lock);
+	clock_was_set();
 	return 0;
 }
 
--- diff/arch/m68knommu/platform/5407/MOTOROLA/crt0_ram.S	2003-06-09 14:18:17.000000000 +0100
+++ source/arch/m68knommu/platform/5407/MOTOROLA/crt0_ram.S	2004-02-23 13:56:38.000000000 +0000
@@ -99,10 +99,12 @@ _start:
 	movec	%d0, %ACR3
 
 	/* Enable cache */
-	move.l	#0xa4098400, %d0		/* Write buffer, dflt precise */
+	move.l	#0xb6088400, %d0		/* Enable caches */
 	movec	%d0,%CACR
 	nop
 
+
+#ifdef CONFIG_ROMFS_FS
 	/*
 	 *	Move ROM filesystem above bss :-)
 	 */
@@ -124,6 +126,12 @@ _copy_romfs:
 	cmp.l	%a0, %a2			/* Check if at end */
 	bne	_copy_romfs
 
+#else /* CONFIG_ROMFS_FS */
+	lea.l	_ebss, %a1
+	move.l	%a1, _ramstart
+#endif /* CONFIG_ROMFS_FS */
+
+
 	/*
 	 *	Zero out the bss region.
 	 */
--- diff/arch/mips/Kconfig	2004-02-09 10:36:07.000000000 +0000
+++ source/arch/mips/Kconfig	2004-02-23 13:56:38.000000000 +0000
@@ -1,13 +1,15 @@
 config MIPS
 	bool
 	default y
+	# Horrible source of confusion.  Die, die, die ...
+	select EMBEDDED
 
 config MIPS64
 	bool "64-bit kernel"
 	help
 	  Select this option if you want to build a 64-bit kernel.  You should
 	  only select this option if you have hardware that actually has a
-	  32-bit processor and if your application will actually benefit from
+	  64-bit processor and if your application will actually benefit from
 	  64-bit processing, otherwise say N.  You must say Y for kernels for
 	  SGI IP27 (Origin 200 and 2000).  If in doubt say N.
 
@@ -25,14 +27,40 @@ source "init/Kconfig"
 
 menu "Machine selection"
 
+config MACH_JAZZ
+	bool "Support for the Jazz family of machines"
+	help
+	 This a family of machines based on the MIPS R4030 chipset which was
+	 used by several vendors to build RISC/os and Windows NT workstations.
+	 Members include the Acer PICA, MIPS Magnum 4000, MIPS Millenium and
+	 Olivetti M700-10 workstations.
+
 config ACER_PICA_61
 	bool "Support for Acer PICA 1 chipset (EXPERIMENTAL)"
-	depends on EXPERIMENTAL
+	depends on MACH_JAZZ && EXPERIMENTAL
 	help
 	  This is a machine with a R4400 133/150 MHz CPU. To compile a Linux
 	  kernel that runs on these, say Y here. For details about Linux on
 	  the MIPS architecture, check out the Linux/MIPS FAQ on the WWW at
-	  <http://oss.sgi.com/mips/>.
+	  <http://www.linux-mips.org/>.
+
+config MIPS_MAGNUM_4000
+	bool "Support for MIPS Magnum 4000"
+	depends on MACH_JAZZ
+	help
+	  This is a machine with a R4000 100 MHz CPU. To compile a Linux
+	  kernel that runs on these, say Y here. For details about Linux on
+	  the MIPS architecture, check out the Linux/MIPS FAQ on the WWW at
+	  <http://www.linux-mips.org/>.
+
+config OLIVETTI_M700
+	bool "Support for Olivetti M700-10"
+	depends on MACH_JAZZ
+	help
+	  This is a machine with a R4000 100 MHz CPU. To compile a Linux
+	  kernel that runs on these, say Y here. For details about Linux on
+	  the MIPS architecture, check out the Linux/MIPS FAQ on the WWW at
+	  <http://www.linux-mips.org/>.
 
 config BAGET_MIPS
 	bool "Support for BAGET MIPS series (EXPERIMENTAL)"
@@ -40,21 +68,59 @@ config BAGET_MIPS
 	help
 	  This enables support for the Baget, a Russian embedded system.  For
 	  more details about the Baget see the Linux/MIPS FAQ on
-	  <http://oss.sgi.com/mips/>.
+	  <http://www.linux-mips.org/>.
+
+config MACH_VR41XX
+	bool "Support for NEC VR41XX-based machines"
 
 config CASIO_E55
 	bool "Support for CASIO CASSIOPEIA E-10/15/55/65"
+	depends on MACH_VR41XX
+
+config IBM_WORKPAD
+	bool "Support for IBM WorkPad z50"
+	depends on MACH_VR41XX
+
+config NEC_EAGLE
+	bool "Support for NEC Eagle/Hawk board"
+	depends on MACH_VR41XX
+
+config TANBAC_TB0226
+	bool "Support for TANBAC TB0226 (Mbase)"
+	depends on MACH_VR41XX
+	help
+	  The TANBAC TB0226 (Mbase) is a MIPS-based platform manufactured by TANBAC.
+	  Please refer to <http://www.tanbac.co.jp/> about Mbase.
+
+config TANBAC_TB0229
+	bool "Support for TANBAC TB0229 (VR4131DIMM)"
+	depends on MACH_VR41XX
+	help
+	  The TANBAC TB0229 (VR4131DIMM) is a MIPS-based platform manufactured by TANBAC.
+	  Please refer to <http://www.tanbac.co.jp/> about VR4131DIMM.
+
+config VICTOR_MPC30X
+	bool "Support for Victor MP-C303/304"
+	depends on MACH_VR41XX
+
+config ZAO_CAPCELLA
+	bool "Support for ZAO Networks Capcella"
+	depends on MACH_VR41XX
+
+config TOSHIBA_JMR3927
+	bool "Support for Toshiba JMR-TX3927 board"
+	depends on MIPS32
 
 config MIPS_COBALT
 	bool "Support for Cobalt Server (EXPERIMENTAL)"
 	depends on EXPERIMENTAL
 
-config DECSTATION
+config MACH_DECSTATION
 	bool "Support for DECstations"
 	depends on MIPS32 || EXPERIMENTAL
 	---help---
 	  This enables support for DEC's MIPS based workstations.  For details
-	  see the Linux/MIPS FAQ on <http://oss.sgi.com/mips/> and the
+	  see the Linux/MIPS FAQ on <http://www.linux-mips.org/> and the
 	  DECstation porting pages on <http://decstation.unix-ag.org/>.
 
 	  If you have one of the following DECstation Models you definitely
@@ -74,46 +140,21 @@ config MIPS_EV64120
 	  This is an evaluation board based on the Galileo GT-64120
 	  single-chip system controller that contains a MIPS R5000 compatible
 	  core running at 75/100MHz.  Their website is located at
-	  <http://www.galileot.com/>.  Say Y here if you wish to build a
+	  <http://www.marvell.com/>.  Say Y here if you wish to build a
 	  kernel for this platform.
 
 config EVB_PCI1
 	bool "Enable Second PCI (PCI1)"
 	depends on MIPS_EV64120
 
-if MOMENCO_OCELOT_G || MOMENCO_OCELOT
-
-config SYSCLK_100
-	bool
-	default y
-
-endif
-if MIPS_EV64120
-
-choice
-	prompt "Galileo Chip Clock"
-	default SYSCLK_83
-
-config SYSCLK_75
-	bool "75"
-
-config SYSCLK_83
-	bool "83.3"
-
-config SYSCLK_100
-	bool "100" if MIPS_EV64120
-
-endchoice
-
-endif
-
 config MIPS_EV96100
 	bool "Support for Galileo EV96100 Evaluation board (EXPERIMENTAL)"
 	depends on EXPERIMENTAL
+	select MIPS_GT96100
 	help
-	  This is an evaluation board based on the Galielo GT-96100 LAN/WAN
+	  This is an evaluation board based on the Galileo GT-96100 LAN/WAN
 	  communications controllers containing a MIPS R5000 compatible core
-	  running at 83MHz. Their website is <http://www.galileot.com/>. Say Y
+	  running at 83MHz. Their website is <http://www.marvell.com/>. Say Y
 	  here if you wish to build a kernel for this platform.
 
 config MIPS_IVR
@@ -122,8 +163,8 @@ config MIPS_IVR
 	  This is an evaluation board built by Globespan to showcase thir
 	  iVR (Internet Video Recorder) design. It utilizes a QED RM5231
 	  R5000 MIPS core. More information can be found out their website
-	  located at <http://www.globespan.net/products/product4.html>P. Say Y
-	  here if you wish to build a kernel for this platform.
+	  located at <http://www.globespan.net/>. Say Y here if you wish to
+	  build a kernel for this platform.
 
 config LASAT
 	bool "Support for LASAT Networks platforms"
@@ -147,9 +188,6 @@ config LASAT_SYSCTL
 config HP_LASERJET
 	bool "Support for Hewlett Packard LaserJet board"
 
-config IBM_WORKPAD
-	bool "Support for IBM WorkPad z50"
-
 config MIPS_ITE8172
 	bool "Support for ITE 8172G board"
 	help
@@ -166,7 +204,7 @@ config IT8172_REVC
 	  Say Y here to support the older, Revision C version of the Integrated
 	  Technology Express, Inc. ITE8172 SBC.  Vendor page at
 	  <http://www.ite.com.tw/ia/brief_it8172bsp.htm>; picture of the
-	  board at <http://www.mvista.com/allies/semiconductor/ite.html>.
+	  board at <http://www.mvista.com/partners/semiconductor/ite.html>.
 
 config MIPS_ATLAS
 	bool "Support for MIPS Atlas board"
@@ -174,14 +212,6 @@ config MIPS_ATLAS
 	  This enables support for the QED R5231-based MIPS Atlas evaluation
 	  board.
 
-config MIPS_MAGNUM_4000
-	bool "Support for MIPS Magnum 4000"
-	help
-	  This is a machine with a R4000 100 MHz CPU. To compile a Linux
-	  kernel that runs on these, say Y here. For details about Linux on
-	  the MIPS architecture, check out the Linux/MIPS FAQ on the WWW at
-	  <http://oss.sgi.com/mips/>.
-
 config MIPS_MALTA
 	bool "Support for MIPS Malta board"
 	help
@@ -210,6 +240,22 @@ config MOMENCO_OCELOT_C
 	  The Ocelot is a MIPS-based Single Board Computer (SBC) made by
 	  Momentum Computer <http://www.momenco.com/>.
 
+config MOMENCO_JAGUAR_ATX
+	bool "Support for Momentum Jaguar board"
+	help
+	  The Jaguar ATX is a MIPS-based Single Board Computer (SBC) made by
+	  Momentum Computer <http://www.momenco.com/>.
+
+config PMC_YOSEMITE
+	bool "Support for PMC-Siera Yosemite eval board"
+	help
+	  Yosemite is an evaluation board for the RM9000x2 processor
+	  manufactured by PMC-Sierra
+
+config HYPERTRANSPORT
+	bool "Hypertransport Support for PMC-Sierra Yosemite"
+	depends on PMC_YOSEMITE
+
 config DDB5074
 	bool "Support for NEC DDB Vrc-5074 (EXPERIMENTAL)"
 	depends on EXPERIMENTAL
@@ -244,17 +290,6 @@ config DDB5477_BUS_FREQUENCY
 config NEC_OSPREY
 	bool "Support for NEC Osprey board"
 
-config NEC_EAGLE
-	bool "Support for NEC Eagle/Hawk board"
-
-config OLIVETTI_M700
-	bool "Support for Olivetti M700-10"
-	help
-	  This is a machine with a R4000 100 MHz CPU. To compile a Linux
-	  kernel that runs on these, say Y here. For details about Linux on
-	  the MIPS architecture, check out the Linux/MIPS FAQ on the WWW at
-	  <http://oss.sgi.com/mips/>.
-
 config SGI_IP22
 	bool "Support for SGI IP22 (Indy/Indigo2)"
 	help
@@ -286,8 +321,8 @@ config SGI_SN0_N_MODE
 	  running in M-Mode, so you should say N here.
 
 config DISCONTIGMEM
-	bool "Discontiguous Memory Support"
-	depends on SGI_IP27
+	bool
+	default y if SGI_IP27
 	help
 	  Say Y to upport efficient handling of discontiguous physical memory,
 	  for architectures which are either NUMA (Non-Uniform Memory Access)
@@ -352,7 +387,7 @@ config SOC_AU1500
 endchoice
 
 choice  
-        prompt "AMD/Alchemy Pb1x and Db1x board support"
+        prompt "AMD/Alchemy Au1x00 board support"
         depends on SOC_AU1X00
 	help
 	  These are evaluation boards built by AMD/Alchemy to
@@ -386,6 +421,22 @@ config MIPS_DB1500
 	bool "DB1500 board"
 	depends on SOC_AU1500
 
+config MIPS_BOSPORUS
+	bool "Bosporus board"
+	depends on SOC_AU1500
+
+config MIPS_MIRAGE
+	bool "Mirage board"
+	depends on SOC_AU1500
+
+config MIPS_XXS1500
+	bool "MyCable XXS1500 board"
+	depends on SOC_AU1500
+
+config MIPS_MTX1
+	bool "4G Systems MTX-1 board"
+	depends on SOC_AU1500
+
 endchoice
 
 config SIBYTE_SB1xxx_SOC
@@ -393,26 +444,174 @@ config SIBYTE_SB1xxx_SOC
 	depends on EXPERIMENTAL
 
 choice
-	prompt "BCM1xxx SOC Type"
+	prompt "BCM1xxx SOC-based board"
 	depends on SIBYTE_SB1xxx_SOC
-	default SIBYTE_SB1250
+	default SIBYTE_SWARM
+	help
+	  Enable support for boards based on the SiByte line of SOCs
+	  from Broadcom.  There are configurations for the known
+	  evaluation boards, or you can choose "Other" and add your
+	  own board support code.
 
-config SIBYTE_SB1250
+config SIBYTE_SWARM
+	bool "BCM91250A-SWARM"
+	select SIBYTE_SB1250
+
+config SIBYTE_SENTOSA
+	bool "BCM91250E-Sentosa"
+	select SIBYTE_SB1250
+
+config SIBYTE_RHONE
+	bool "BCM91125E-Rhone"
+	select SIBYTE_BCM1125H
+
+config SIBYTE_CARMEL
+	bool "BCM91120x-Carmel"
+	select SIBYTE_BCM1120
+
+config SIBYTE_PTSWARM
+	bool "BCM91250PT-PTSWARM"
+	select SIBYTE_SB1250
+
+config SIBYTE_LITTLESUR
+	bool "BCM91250C2-LittleSur"
+	select SIBYTE_SB1250
+
+config SIBYTE_CRHINE
+	bool "BCM91120C-CRhine"
+	select SIBYTE_BCM1120
+
+config SIBYTE_CRHONE
+	bool "BCM91125C-CRhone"
+	select SIBYTE_BCM1125
+
+config SIBYTE_UNKNOWN
+	bool "Other"
+
+endchoice
+
+config SIBYTE_BOARD
+	bool
+	depends on SIBYTE_SB1xxx_SOC && !SIBYTE_UNKNOWN
+	default y
+
+choice
+	prompt "BCM1xxx SOC Type"
+	depends on SIBYTE_UNKNOWN
+	default SIBYTE_UNK_BCM1250
+	help
+	  Since you haven't chosen a known evaluation board from
+	  Broadcom, you must explicitly pick the SOC this kernel is
+	  targetted for.
+
+config SIBYTE_UNK_BCM1250
 	bool "BCM1250"
+	select SIBYTE_SB1250
+
+config SIBYTE_UNK_BCM1120
+	bool "BCM1120"
+	select SIBYTE_BCM1120
+
+config SIBYTE_UNK_BCM1125
+	bool "BCM1125"
+	select SIBYTE_BCM1125
+
+config SIBYTE_UNK_BCM1125H
+	bool "BCM1125H"
+	select SIBYTE_BCM1125H
 
 endchoice
 
+config SIBYTE_SB1250
+	bool
+
+config SIBYTE_BCM1120
+	bool
+	select SIBYTE_BCM112X
+
+config SIBYTE_BCM1125
+	bool
+	select SIBYTE_BCM112X
+
+config SIBYTE_BCM1125H
+	bool
+	select SIBYTE_BCM112X
+
+config SIBYTE_BCM112X
+	bool
+
+choice
+	prompt "SiByte SOC Stepping"
+	depends on SIBYTE_SB1xxx_SOC
+
+config CPU_SB1_PASS_1
+	bool "1250 Pass1"
+	depends on SIBYTE_SB1250
+
+config CPU_SB1_PASS_2_1250
+	bool "1250 An"
+	depends on SIBYTE_SB1250
+	select CPU_SB1_PASS_2
+	help
+	  Also called BCM1250 Pass 2
+
+config CPU_SB1_PASS_2_2
+	bool "1250 Bn"
+	depends on SIBYTE_SB1250
+	help
+	  Also called BCM1250 Pass 2.2
+
+config CPU_SB1_PASS_4
+	bool "1250 Cn"
+	depends on SIBYTE_SB1250
+	help
+	  Also called BCM1250 Pass 3
+
+config CPU_SB1_PASS_2_112x
+	bool "112x Hybrid"
+	depends on SIBYTE_BCM112X
+	select CPU_SB1_PASS_2
+
+config CPU_SB1_PASS_3
+	bool "112x An"
+	depends on SIBYTE_BCM112X
+
+endchoice
+
+config CPU_SB1_PASS_2
+	bool
+
+config SIBYTE_HAS_PCI
+	bool
+	depends on SIBYTE_SB1250 || SIBYTE_BCM1125 || SIBYTE_BCM1125H
+	default y
+
+config SIBYTE_HAS_LDT
+	bool
+	depends on PCI && (SIBYTE_SB1250 || SIBYTE_BCM1125H)
+	default y
+
 config SIMULATION
 	bool "Running under simulation"
 	depends on SIBYTE_SB1xxx_SOC
+	help
+	  Build a kernel suitable for running under the GDB simulator.
+	  Primarily adjusts the kernel's notion of time.
 
 config SIBYTE_CFE
 	bool "Booting from CFE"
 	depends on SIBYTE_SB1xxx_SOC
+	help
+	  Make use of the CFE API for enumerating available memory,
+	  controlling secondary CPUs, and possibly console output.
 
 config SIBYTE_CFE_CONSOLE
 	bool "Use firmware console"
 	depends on SIBYTE_CFE
+	help
+	  Use the CFE API's console write routines during boot.  Other console
+	  options (VT console, sb1250 duart console, etc.) should not be
+	  configured.
 
 config SIBYTE_STANDALONE
 	bool
@@ -421,12 +620,25 @@ config SIBYTE_STANDALONE
 
 config SIBYTE_STANDALONE_RAM_SIZE
 	int "Memory size (in megabytes)"
-	depends on SIBYTE_SB1xxx_SOC && !SIBYTE_CFE
+	depends on SIBYTE_STANDALONE
 	default "32"
 
 config SIBYTE_BUS_WATCHER
-        bool "Support for Bus Watcher statistics"
+	bool "Support for Bus Watcher statistics"
 	depends on SIBYTE_SB1xxx_SOC
+	help
+	  Handle and keep statistics on the bus error interrupts (COR_ECC,
+	  BAD_ECC, IO_BUS).
+
+config SIBYTE_BW_TRACE
+	bool "Capture bus trace before bus error"
+	depends on SIBYTE_BUS_WATCHER
+	help
+	  Run a continuous bus trace, dumping the raw data as soon as
+	  a ZBbus error is detected.  Cannot work if ZBbus profiling
+	  is turned on, and also will interfere with JTAG-based trace
+	  buffer activity.  Raw buffer data is dumped to console, and
+	  must be processed off-line.
 
 config SIBYTE_SB1250_PROF
 	bool "Support for SB1/SOC profiling - SB1/SCD perf counters"
@@ -436,15 +648,6 @@ config SIBYTE_TBPROF
 	bool "Support for ZBbus profiling"
 	depends on SIBYTE_SB1xxx_SOC
 
-config SIBYTE_SWARM
-	bool "Support for SWARM board"
-	depends on SIBYTE_SB1250
-
-config SIBYTE_BOARD
-	bool
-	depends on SIBYTE_SWARM
-	default y
-
 config SNI_RM200_PCI
 	bool "Support for SNI RM200 PCI"
 	help
@@ -453,32 +656,10 @@ config SNI_RM200_PCI
 	  Technology and now in turn merged with Fujitsu.  Say Y here to
 	  support this machine type.
 
-config TANBAC_TB0226
-	bool "Support for TANBAC TB0226 (Mbase)"
-	help
-	  The TANBAC TB0226 (Mbase) is a MIPS-based platform manufactured by TANBAC.
-	  Please refer to <http://www.tanbac.co.jp/> about Mbase.
-
-config TANBAC_TB0229
-	bool "Support for TANBAC TB0229 (VR4131DIMM)"
-	help
-	  The TANBAC TB0229 (VR4131DIMM) is a MIPS-based platform manufactured by TANBAC.
-	  Please refer to <http://www.tanbac.co.jp/> about VR4131DIMM.
-
-config TOSHIBA_JMR3927
-	bool "Support for Toshiba JMR-TX3927 board"
-	depends on MIPS32
-
 config TOSHIBA_RBTX4927
 	bool "Support for Toshiba TBTX49[23]7 board"
 	depends on MIPS32
 
-config VICTOR_MPC30X
-	bool "Support for Victor MP-C303/304"
-
-config ZAO_CAPCELLA
-	bool "Support for ZAO Networks Capcella"
-
 config RWSEM_GENERIC_SPINLOCK
 	bool
 	default y
@@ -486,6 +667,10 @@ config RWSEM_GENERIC_SPINLOCK
 config RWSEM_XCHGADD_ALGORITHM
 	bool
 
+config HAVE_DEC_LOCK
+	bool
+	default y
+
 #
 # Select some configuration options automatically based on user selections.
 #
@@ -494,35 +679,54 @@ config ARC
 	depends on SNI_RM200_PCI || SGI_IP32 || SGI_IP27 || SGI_IP22 || MIPS_MAGNUM_4000 || OLIVETTI_M700 || ACER_PICA_61
 	default y
 
-config GENERIC_ISA_DMA
+config	DMA_COHERENT
 	bool
-	depends on SNI_RM200_PCI || MIPS_MAGNUM_4000 || OLIVETTI_M700 || ACER_PICA_61
+	depends on SIBYTE_SB1xxx_SOC
+	default y
+
+config	DMA_IP27
+	bool
+	depends on SGI_IP27
 	default y
 
-config CONFIG_GT64120
+config	DMA_NONCOHERENT
 	bool
-	depends on MIPS_EV64120 || MOMENCO_OCELOT
+	depends on ZAO_CAPCELLA || VICTOR_MPC30X || TOSHIBA_JMR3927 || TOSHIBA_RBTX4927 || SNI_RM200_PCI || SGI_IP32 || SGI_IP22 || NEC_EAGLE || NEC_OSPREY || DDB5477 || DDB5476 || DDB5074 || MOMENCO_OCELOT || MOMENCO_OCELOT_C || MOMENCO_OCELOT_G || MOMENCO_JAGUAR_ATX || MIPS_BOSPORUS || MIPS_DB1000 || MIPS_DB1100 || MIPS_DB1500 || MIPS_SEAD || MIPS_MALTA || MIPS_MAGNUM_4000 || MIPS_MIRAGE || MIPS_MTX1 || MIPS_XXS1500 || OLIVETTI_M700 || MIPS_ATLAS || LASAT || MIPS_ITE8172 || IBM_WORKPAD || HP_LASERJET || MIPS_IVR || MIPS_EV96100 || MIPS_EV64120 || MACH_DECSTATION || MIPS_COBALT || MIPS_PB1500 || MIPS_PB1100 || MIPS_PB1000 || CASIO_E55 || ACER_PICA_61 || TANBAC_TB0226 || TANBAC_TB0229
+	default y
+
+config EARLY_PRINTK
+	bool
+	depends on MACH_DECSTATION
+	default y
+
+config GENERIC_ISA_DMA
+	bool
+	depends on SNI_RM200_PCI || MIPS_MAGNUM_4000 || OLIVETTI_M700 || ACER_PICA_61 || MIPS_MALTA
 	default y
 
 config I8259
 	bool
-	depends on SNI_RM200_PCI || DDB5477 || DDB5476 || DDB5074 || MIPS_MALTA || MIPS_MAGNUM_4000 || OLIVETTI_M700 || MIPS_COBALT || ACER_PICA_61
+	depends on SNI_RM200_PCI || DDB5477 || DDB5476 || DDB5074 || MACH_JAZZ || MIPS_MALTA || MIPS_COBALT
+	default y
+
+config MIPS_BONITO64
+	bool
+	depends on MIPS_ATLAS || MIPS_MALTA
 	default y
 
-config MIPS_JAZZ
+config MIPS_MSC
 	bool
-	depends on MIPS_MAGNUM_4000 || OLIVETTI_M700 || ACER_PICA_61
+	depends on MIPS_ATLAS || MIPS_MALTA
 	default y
 
-config NONCOHERENT_IO
+config MIPS_NILE4
 	bool
-	depends on ZAO_CAPCELLA || VICTOR_MPC30X || TOSHIBA_JMR3927 || TOSHIBA_RBTX4927 || SNI_RM200_PCI || SGI_IP32 || SGI_IP22 || NEC_EAGLE || NEC_OSPREY || DDB5477 || DDB5476 || DDB5074 || MOMENCO_OCELOT || MOMENCO_OCELOT_C || MOMENCO_OCELOT_G || MIPS_SEAD || MIPS_MALTA || MIPS_MAGNUM_4000 || OLIVETTI_M700 || MIPS_ATLAS || LASAT || MIPS_ITE8172 || IBM_WORKPAD || HP_LASERJET || MIPS_IVR || MIPS_EV96100 || MIPS_EV64120 || DECSTATION || MIPS_COBALT || MIPS_PB1500 || MIPS_PB1100 || MIPS_PB1000 || CASIO_E55 || ACER_PICA_61 || TANBAC_TB0226 || TANBAC_TB0229
-	default y if ZAO_CAPCELLA || VICTOR_MPC30X || TOSHIBA_JMR3927 || TOSHIBA_RBTX4927 || SNI_RM200_PCI || SGI_IP32 || SGI_IP22 || NEC_EAGLE || NEC_OSPREY || DDB5477 || DDB5476 || DDB5074 || MOMENCO_OCELOT_G || MOMENCO_OCELOT || MIPS_SEAD || MIPS_MALTA || MIPS_MAGNUM_4000 || OLIVETTI_M700 || MIPS_ATLAS || LASAT || MIPS_ITE8172 || IBM_WORKPAD || HP_LASERJET || MIPS_IVR || MIPS_EV96100 || MIPS_EV64120 || DECSTATION || MIPS_COBALT || MIPS_PB1500 || MIPS_PB1100 || MIPS_PB1000 || CASIO_E55 || ACER_PICA_61 || TANBAC_TB0226 || TANBAC_TB0229
-	default n if (SIBYTE_SB1250 || SGI_IP27)
+	depends on LASAT
+	default y
 
 config CPU_LITTLE_ENDIAN
 	bool "Generate little endian code"
-	default y if ACER_PICA_61 || CASIO_E55 || DDB5074 || DDB5476 || DDB5477 || DECSTATION || HP_LASERJET || IBM_WORKPAD || LASAT || MIPS_COBALT || MIPS_ITE8172 || MIPS_IVR || MIPS_PB1000 || MIPS_PB1100 || MIPS_PB1500 || NEC_OSPREY || NEC_EAGLE || OLIVETTI_M700 || SNI_RM200_PCI || VICTOR_MPC30X || ZAO_CAPCELLA
+	default y if ACER_PICA_61 || CASIO_E55 || DDB5074 || DDB5476 || DDB5477 || MACH_DECSTATION || HP_LASERJET || IBM_WORKPAD || LASAT || MIPS_COBALT || MIPS_ITE8172 || MIPS_IVR || MIPS_PB1000 || MIPS_PB1100 || MIPS_PB1500 || NEC_OSPREY || NEC_EAGLE || OLIVETTI_M700 || SNI_RM200_PCI || VICTOR_MPC30X || ZAO_CAPCELLA
 	default n if BAGET_MIPS || MIPS_EV64120 || MIPS_EV96100 || MOMENCO_OCELOT || MOMENCO_OCELOT_G || SGI_IP22 || SGI_IP27 || SGI_IP32 || TOSHIBA_JMR3927
 	help
 	  Some MIPS machines can be configured for either little or big endian
@@ -531,23 +735,22 @@ config CPU_LITTLE_ENDIAN
 
 config IRQ_CPU
 	bool
-	depends on ZAO_CAPCELLA || VICTOR_MPC30X || SGI_IP22 || NEC_EAGLE || NEC_OSPREY || DDB5477 || DDB5476 || DDB5074 || IBM_WORKPAD || HP_LASERJET || DECSTATION || CASIO_E55 || TANBAC_TB0226 || TANBAC_TB0229
+	depends on CASIO_E55 || DDB5074 || DDB5476 || DDB5477 || MACH_DECSTATION || HP_LASERJET || IBM_WORKPAD || MIPS_COBALT || MIPS_EV96100 || MOMENCO_OCELOT || MIPS_SEAD || MOMENCO_OCELOT_G || NEC_EAGLE || NEC_OSPREY || SGI_IP22 || VICTOR_MPC30X || TANBAC_TB0226 || TANBAC_TB0229 || ZAO_CAPCELLA
 	default y
 
-config VR41XX_TIME_C
+config IRQ_CPU_RM7K
 	bool
-	depends on ZAO_CAPCELLA || VICTOR_MPC30X || NEC_EAGLE || IBM_WORKPAD || CASIO_E55 || TANBAC_TB0226 || TANBAC_TB0229
+	depends on MOMENCO_JAGUAR_ATX || MOMENCO_OCELOT || MOMENCO_OCELOT_G
 	default y
 
 config DUMMY_KEYB
 	bool
-	depends on ZAO_CAPCELLA || VICTOR_MPC30X || SIBYTE_SB1250 || NEC_EAGLE || NEC_OSPREY || DDB5477 || IBM_WORKPAD || CASIO_E55 || TANBAC_TB0226 || TANBAC_TB0229
+	depends on ZAO_CAPCELLA || VICTOR_MPC30X || SIBYTE_SB1xxx_SOC || NEC_EAGLE || NEC_OSPREY || DDB5477 || CASIO_E55 || TANBAC_TB0226 || TANBAC_TB0229
 	default y
 
-config VR41XX_COMMON
-	bool
-	depends on NEC_EAGLE || ZAO_CAPCELLA || VICTOR_MPC30X || IBM_WORKPAD || CASIO_E55 || TANBAC_TB0226 || TANBAC_TB0229
-	default y
+config VRC4171
+	tristate "NEC VRC4171 Support"
+	depends on IBM_WORKPAD
 
 config VRC4173
 	tristate "NEC VRC4173 Support"
@@ -563,31 +766,58 @@ config MIPS_BOARDS_GEN
 	depends on MIPS_ATLAS || MIPS_MALTA || MIPS_SEAD
 	default y
 
-config ITE_BOARD_GEN
+config MIPS_GT64111
 	bool
-	depends on MIPS_IVR || MIPS_ITE8172
+	depends on MIPS_COBALT
 	default y
 
-config NEW_PCI
+config MIPS_GT64120
 	bool
-	depends on ZAO_CAPCELLA || VICTOR_MPC30X || TOSHIBA_JMR3927 || TOSHIBA_RBTX4927 || NEC_EAGLE || DDB5477 || DDB5476 || DDB5074 || MIPS_ITE8172 || HP_LASERJET || MIPS_IVR || MIPS_EV96100 || MIPS_PB1500 || MIPS_PB1100 || MIPS_PB1000 || TANBAC_TB0226 || TANBAC_TB0229
+	depends on MIPS_EV64120 || MIPS_EV96100 || LASAT || MIPS_ATLAS || MIPS_MALTA || MOMENCO_OCELOT
 	default y
 
-config SWAP_IO_SPACE
-	bool "Support for paging of anonymous memory"
-	depends on TOSHIBA_JMR3927 || TOSHIBA_RBTX4927 || SIBYTE_SB1250 || SGI_IP22 || MOMENCO_OCELOT_C || MOMENCO_OCELOT_G || MOMENCO_OCELOT || MIPS_MALTA || MIPS_ATLAS || MIPS_EV96100 || MIPS_PB1100 || MIPS_PB1000
+config MIPS_MV64340
+	bool
+	depends on MOMENCO_JAGUAR_ATX || MOMENCO_OCELOT_C
 	default y
-	help
-	  This option allows you to choose whether you want to have support
-	  for socalled swap devices or swap files in your kernel that are
-	  used to provide more virtual memory than the actual RAM present
-	  in your computer.  If unusre say Y.
 
-config SIBYTE_HAS_LDT
+config MIPS_TX3927
+	bool
+	depends on TOSHIBA_JMR3927
+	default y
+
+config ITE_BOARD_GEN
+	bool
+	depends on MIPS_IVR || MIPS_ITE8172
+	default y
+
+config SWAP_IO_SPACE
 	bool
-	depends on SIBYTE_SB1xxx_SOC && PCI
+	depends on TOSHIBA_JMR3927 || TOSHIBA_RBTX4927 || SIBYTE_SB1xxx_SOC || SGI_IP22 || MOMENCO_OCELOT_C || MOMENCO_OCELOT_G || MOMENCO_OCELOT || MOMENCO_JAGUAR_ATX || MIPS_MALTA || MIPS_ATLAS || MIPS_EV96100 || MIPS_PB1100 || MIPS_PB1000
 	default y
 
+#
+# Unfortunately not all GT64120 systems run the chip at the same clock.
+# As the user for the clock rate and try to minimize the available options.
+#
+choice
+	prompt "Galileo Chip Clock"
+	#default SYSCLK_83 if MIPS_EV64120
+	depends on MIPS_EV64120 || MOMENCO_OCELOT || MOMENCO_OCELOT_G
+	default SYSCLK_83 if MIPS_EV64120
+	default SYSCLK_100 if MOMENCO_OCELOT || MOMENCO_OCELOT_G
+
+config SYSCLK_75
+	bool "75" if MIPS_EV64120
+
+config SYSCLK_83
+	bool "83.3" if MIPS_EV64120
+
+config SYSCLK_100
+	bool "100" if MIPS_EV64120 || MOMENCO_OCELOT || MOMENCO_OCELOT_G
+
+endchoice
+
 config AU1000_USB_DEVICE
 	bool
 	depends on MIPS_PB1500 || MIPS_PB1100 || MIPS_PB1000
@@ -598,11 +828,6 @@ config COBALT_LCD
 	depends on MIPS_COBALT
 	default y
 
-config MIPS_GT64120
-	bool
-	depends on MIPS_EV64120
-	default y
-
 config MIPS_GT96100
 	bool
 	depends on MIPS_EV96100
@@ -623,18 +848,18 @@ config IT8712
 
 config BOOT_ELF32
 	bool
-	depends on DECSTATION || MIPS_ATLAS || MIPS_MALTA || SIBYTE_SB1250 || SGI_IP32 || SGI_IP22 || SNI_RM200_PCI
+	depends on MACH_DECSTATION || MIPS_ATLAS || MIPS_MALTA || MOMENCO_JAGUAR_ATX || SIBYTE_SB1xxx_SOC || SGI_IP32 || SGI_IP22 || SNI_RM200_PCI
 	default y
 
-config L1_CACHE_SHIFT
+config MIPS_L1_CACHE_SHIFT
 	int
-	default "4" if DECSTATION
-	default "5" if SGI_IP32 || SGI_IP22 || MIPS_SEAD || MIPS_MALTA || MIPS_ATLAS
+	default "4" if MACH_DECSTATION
 	default "7" if SGI_IP27
+	default "5"
 
 config ARC32
 	bool
-	depends on SNI_RM200_PCI || SGI_IP32 || SGI_IP22 || MIPS_MAGNUM_4000 || OLIVETTI_M700
+	depends on MACH_JAZZ || SNI_RM200_PCI || SGI_IP22 || SGI_IP32
 	default y
 
 config FB
@@ -660,9 +885,8 @@ config FB
 
 	  You need an utility program called fbset to make full use of frame
 	  buffer devices. Please read <file:Documentation/fb/framebuffer.txt>
-	  and the Framebuffer-HOWTO at
-	  <http://www.tahallah.demon.co.uk/programming/prog.html> for more
-	  information.
+	  and the Framebuffer-HOWTO at <http://www.tldp.org/docs.html#howto>
+	  for more information.
 
 	  Say Y here and to the driver for your graphics board below if you
 	  are compiling a kernel for a non-x86 architecture.
@@ -694,17 +918,17 @@ config ARC_CONSOLE
 
 config ARC_MEMORY
 	bool
-	depends on SNI_RM200_PCI || SGI_IP32
+	depends on MACH_JAZZ || SNI_RM200_PCI || SGI_IP32
 	default y
 
 config ARC_PROMLIB
 	bool
-	depends on SNI_RM200_PCI || SGI_IP32 || SGI_IP22
+	depends on MACH_JAZZ || SNI_RM200_PCI || SGI_IP22 || SGI_IP32
 	default y
 
 config BOARD_SCACHE
 	bool
-	depends on MIPS_EV96100 || MOMENCO_OCELOT || SGI_IP22
+	depends on CPU_RM9000 || MIPS_EV96100 || MOMENCO_OCELOT || SGI_IP22
 	default y
 
 config ARC64
@@ -823,11 +1047,48 @@ config CPU_R10000
 config CPU_RM7000
 	bool "RM7000"
 
+config CPU_RM9000
+	bool "RM9000"
+
 config CPU_SB1
 	bool "SB1"
 
 endchoice
 
+choice
+	prompt "Kernel page size"
+	default PAGE_SIZE_4KB
+
+config PAGE_SIZE_4KB
+	bool "4kB"
+	help
+	 This option select the standard 4kB Linux page size.  On some
+	 R3000-family processors this is the only available page size.  Using
+	 4kB page size will minimize memory consumption and is therefore
+	 recommended for low memory systems. 
+
+config PAGE_SIZE_16KB
+	bool "16kB"
+	depends on EXPERIMENTAL && !CPU_R3000 && !CPU_TX39XX
+	help
+	  Using 16kB page size will result in higher performance kernel at
+	  the price of higher memory consumption.  This option is available on
+	  all non-R3000 family processor.  Not that at the time of this
+	  writing this option is still high experimental; there are also
+	  issues with compatibility of user applications.
+
+config PAGE_SIZE_64KB
+	bool "64kB"
+	depends on EXPERIMENTAL && !CPU_R3000 && !CPU_TX39XX
+	help
+	  Using 64kB page size will result in higher performance kernel at
+	  the price of higher memory consumption.  This option is available on
+	  all non-R3000 family processor.  Not that at the time of this
+	  writing this option is still high experimental; there are also
+	  issues with compatibility of user applications.
+
+endchoice
+
 config R5000_CPU_SCACHE
 	bool
 	depends on CPU_NEVADA || CPU_R5000
@@ -848,28 +1109,12 @@ config SIBYTE_DMA_PAGEOPS
 
 config CPU_HAS_PREFETCH
 	bool "Enable prefetches" if CPU_SB1 && !CPU_SB1_PASS_2
-	default y if CPU_RM7000 || CPU_MIPS64 || CPU_MIPS32
+	default y if CPU_MIPS32 || CPU_MIPS64 || CPU_RM7000 || CPU_RM9000
 
 config VTAG_ICACHE
 	bool "Support for Virtual Tagged I-cache" if CPU_MIPS64 || CPU_MIPS32
 	default y if CPU_SB1
 
-choice
-	prompt "SB1 Pass"
-	depends on CPU_SB1
-	default CPU_SB1_PASS_1
-
-config CPU_SB1_PASS_1
-	bool "Pass1"
-
-config CPU_SB1_PASS_2
-	bool "Pass2"
-
-config CPU_SB1_PASS_2_2
-	bool "Pass2.2"
-
-endchoice
-
 config SB1_PASS_1_WORKAROUNDS
 	bool
 	depends on CPU_SB1_PASS_1
@@ -880,23 +1125,14 @@ config SB1_PASS_2_WORKAROUNDS
 	depends on CPU_SB1 && (CPU_SB1_PASS_2_2 || CPU_SB1_PASS_2)
 	default y
 
-# Avoid prefetches on Pass 2 (before 2.2)
-# XXXKW for now, let 2.2 use same WORKAROUNDS flag as pre-2.2
-config SB1_CACHE_ERROR
-	bool "Support for SB1 Cache Error handler"
-	depends on CPU_SB1
-
-config SB1_CERR_IGNORE_RECOVERABLE
-	bool "Ignore recoverable cache errors"
-	depends on SB1_CACHE_ERROR
-
-config SB1_CERR_SPIN
-	bool "Spin instead of running handler"
-	depends on SB1_CACHE_ERROR
+config SB1_PASS_2_1_WORKAROUNDS
+	bool
+	depends on CPU_SB1 && CPU_SB1_PASS_2
+	default y
 
 config 64BIT_PHYS_ADDR
 	bool "Support for 64-bit physical address space"
-	depends on (CPU_R4X00 || CPU_R5000 || CPU_RM7000 || CPU_R10000 || CPU_SB1 || CPU_MIPS32 || CPU_MIPS64) && MIPS32
+	depends on (CPU_R4X00 || CPU_R5000 || CPU_RM7000 || CPU_RM9000 || CPU_R10000 || CPU_SB1 || CPU_MIPS32 || CPU_MIPS64) && MIPS32
 
 config CPU_ADVANCED
 	bool "Override CPU Options"
@@ -927,7 +1163,7 @@ config CPU_HAS_LLDSCD
 
 config CPU_HAS_WB
 	bool "Writeback Buffer available" if CPU_ADVANCED
-	default y if !CPU_ADVANCED && (CPU_R3000 || CPU_VR41XX || CPU_TX39XX) && DECSTATION
+	default y if !CPU_ADVANCED && CPU_R3000 && MACH_DECSTATION
 	help
 	  Say N here for slightly better performance.  You must say Y here for
 	  machines which require flushing of write buffers in software.  Saying
@@ -954,11 +1190,11 @@ config CPU_HAS_SYNC
 #
 config HIGHMEM
 	bool "High Memory Support"
-	depends on MIPS32 && (CPU_R3000 || CPU_SB1 || CPU_R7000 || CPU_R10000) && !(BAGET_MIPS || DECSTATION)
+	depends on MIPS32 && (CPU_R3000 || CPU_SB1 || CPU_R7000 || CPU_R10000) && !(BAGET_MIPS || MACH_DECSTATION)
 
 config SMP
 	bool "Multi-Processing support"
-	depends on SIBYTE_SB1xxx_SOC && SIBYTE_SB1250 && !SIBYTE_STANDALONE || SGI_IP27
+	depends on CPU_RM9000 || (SIBYTE_SB1250 && !SIBYTE_STANDALONE) || SGI_IP27
 	---help---
 	  This enables support for systems with more than one CPU. If you have
 	  a system with only one CPU, like most personal computers, say N. If
@@ -980,14 +1216,16 @@ config SMP
 	  If you don't know what to do here, say N.
 
 config NR_CPUS
-	int "Maximum number of CPUs (2-32)"
-	range 2 32
+	int "Maximum number of CPUs (2-64)"
+	range 2 64
 	depends on SMP
-	default "32"
+	default "64" if SGI_IP27
+	default "2"
 	help
 	  This allows you to specify the maximum number of CPUs which this
-	  kernel will support.  The maximum supported value is 32 and the
-	  minimum value which makes sense is 2.
+	  kernel will support.  The maximum supported value is 32 for 32-bit
+	  kernel and 64 for 64-bit kernels; the minimum value which makes
+	  sense is 2.
 
 	  This is purely to save memory - each supported CPU adds
 	  approximately eight kilobytes to the kernel image.
@@ -1001,6 +1239,15 @@ config PREEMPT
 	  This allows applications to run more reliably even when the system is
 	  under load.
 
+config DEBUG_SPINLOCK
+	bool "Spinlock debugging"
+	depends on DEBUG_KERNEL
+	help
+	  Say Y here and build SMP to catch missing spinlock initialization
+	  and certain other kinds of spinlock errors commonly made.  This is
+	  best used in conjunction with the NMI watchdog so that spinlock
+	  deadlocks are also debuggable.
+
 config DEBUG_SPINLOCK_SLEEP
 	bool "Sleep-inside-spinlock checking"
 	help
@@ -1031,7 +1278,7 @@ menu "Bus options (PCI, PCMCIA, EISA, IS
 
 config PCI
 	bool "Support for PCI controller"
-	depends on MIPS_DB1000 || DDB5074 || DDB5476 || DDB5477 || HP_LASERJET || LASAT || MIPS_IVR || MIPS_ATLAS || MIPS_COBALT || MIPS_EV64120 || MIPS_EV96100 || MIPS_ITE8172 || MIPS_MALTA || MOMENCO_OCELOT || MOMENCO_OCELOT_C || MOMENCO_OCELOT_G || MIPS_PB1000 || MIPS_PB1100 || MIPS_PB1500 || NEC_EAGLE || SGI_IP27 || SGI_IP32 || SIBYTE_SB1250 || SNI_RM200_PCI || TANBAC_TB0226 || TANBAC_TB0229 || TOSHIBA_JMR3927 || TOSHIBA_RBTX4927 || VICTOR_MPC30X || ZAO_CAPCELLA
+	depends on MIPS_DB1000 || DDB5074 || DDB5476 || DDB5477 || HP_LASERJET || LASAT || MIPS_IVR || MIPS_ATLAS || MIPS_COBALT || MIPS_EV64120 || MIPS_EV96100 || MIPS_ITE8172 || MIPS_MALTA || MOMENCO_OCELOT || MOMENCO_OCELOT_C || MOMENCO_OCELOT_G || MOMENCO_JAGUAR_ATX || MIPS_PB1000 || MIPS_PB1100 || SOC_AU1500 || NEC_EAGLE || SGI_IP27 || SGI_IP32 || SIBYTE_HAS_PCI || SNI_RM200_PCI || TANBAC_TB0226 || TANBAC_TB0229 || TOSHIBA_JMR3927 || TOSHIBA_RBTX4927 || VICTOR_MPC30X || ZAO_CAPCELLA
 	help
 	  Find out whether you have a PCI motherboard. PCI is the name of a
 	  bus system, i.e. the way the CPU talks to the other stuff inside
@@ -1056,13 +1303,6 @@ config ISA
 	  an older system, now being displaced by PCI; newer boards don't
 	  support it.  If you have ISA, say Y, otherwise N.
 
-#
-# The SCSI bits are needed to get the SCSI code to link ...
-#
-config GENERIC_ISA_DMA
-	bool
-	default y if ACER_PICA_61 || MIPS_MAGNUM_4000 || OLIVETTI_M700 || SNI_RM200_PCI || SCSI
-
 config EISA
 	bool "EISA support"
 	depends on ISA && (SGI_IP22 || SNI_RM200_PCI)
@@ -1083,7 +1323,7 @@ source "drivers/eisa/Kconfig"
 
 config TC
 	bool "TURBOchannel support"
-	depends on DECSTATION
+	depends on MACH_DECSTATION
 	help
 	  TurboChannel is a DEC (now Compaq (now HP)) bus for Alpha and MIPS
 	  processors.  Documentation on writing device drivers for TurboChannel
@@ -1104,24 +1344,6 @@ config MCA
 config SBUS
 	bool
 
-config HOTPLUG
-	bool "Support for hot-pluggable devices"
-	---help---
-	  Say Y here if you want to plug devices into your computer while
-	  the system is running, and be able to use them quickly.  In many
-	  cases, the devices can likewise be unplugged at any time too.
-
-	  One well known example of this is PCMCIA- or PC-cards, credit-card
-	  size devices such as network cards, modems or hard drives which are
-	  plugged into slots found on all modern laptop computers.  Another
-	  example, used on modern desktops as well as laptops, is USB.
-
-	  Enable HOTPLUG and KMOD, and build a modular kernel.  Get agent
-	  software (at <http://linux-hotplug.sourceforge.net/>) and install it.
-	  Then your kernel will automatically call out to a user mode "policy
-	  agent" (/sbin/hotplug) to load modules and set up software needed
-	  to use devices as you hotplug them.
-
 source "drivers/pcmcia/Kconfig"
 
 source "drivers/pci/hotplug/Kconfig"
@@ -1180,21 +1402,10 @@ config BINFMT_ELF32
 
 config PM
 	bool "Power Management support (EXPERIMENTAL)"
-	depends on EXPERIMENTAL && SOC_AU1X00
+	depends on EXPERIMENTAL && MACH_AU1X00
 
 endmenu
 
-source "drivers/mtd/Kconfig"
-
-source "drivers/parport/Kconfig"
-
-source "drivers/pnp/Kconfig"
-
-source "drivers/base/Kconfig"
-
-source "drivers/block/Kconfig"
-
-
 menu "MIPS initrd options"
 	depends on BLK_DEV_INITRD
 
@@ -1213,79 +1424,10 @@ config EMBEDDED_RAMDISK_IMAGE
 
 endmenu
 
-source "drivers/ide/Kconfig"
-
-source "drivers/scsi/Kconfig"
-
-source "drivers/cdrom/Kconfig"
-
-source "drivers/md/Kconfig"
-
-source "drivers/message/fusion/Kconfig"
-
-source "drivers/ieee1394/Kconfig"
-
-source "drivers/message/i2o/Kconfig"
-
-source "net/Kconfig"
-
-source "drivers/isdn/Kconfig"
-
-source "drivers/telephony/Kconfig"
-
-#
-# input before char - char/joystick depends on it. As does USB.
-#
-source "drivers/input/Kconfig"
-
-source "drivers/char/Kconfig"
-
-#source drivers/misc/Config.in
-
-source "drivers/media/Kconfig"
+source "drivers/Kconfig"
 
 source "fs/Kconfig"
 
-source "drivers/video/Kconfig"
-
-
-menu "Sound"
-
-config SOUND
-	tristate "Sound card support"
-	---help---
-	  If you have a sound card in your computer, i.e. if it can say more
-	  than an occasional beep, say Y.  Be sure to have all the information
-	  about your sound card and its configuration down (I/O port,
-	  interrupt and DMA channel), because you will be asked for it.
-
-	  You want to read the Sound-HOWTO, available from
-	  <http://www.tldp.org/docs.html#howto>. General information about
-	  the modular sound system is contained in the files
-	  <file:Documentation/sound/oss/Introduction>.  The file
-	  <file:Documentation/sound/oss/README.OSS> contains some slightly
-	  outdated but still useful information as well.
-
-	  If you have a PnP sound card and you want to configure it at boot
-	  time using the ISA PnP tools (read
-	  <http://www.roestock.demon.co.uk/isapnptools/>), then you need to
-	  compile the sound card support as a module and load that module
-	  after the PnP configuration is finished. To do this, choose M here
-	  and read <file:Documentation/sound/oss/README.modules>; the module
-	  will be called soundcore.
-
-	  I'm told that even without a sound card, you can make your computer
-	  say more than an occasional beep, by programming the PC speaker.
-	  Kernel patches and supporting utilities to do that are in the pcsp
-	  package, available at <ftp://ftp.infradead.org/pub/pcsp/>.
-
-source "sound/Kconfig"
-
-endmenu
-
-source "drivers/usb/Kconfig"
-
-
 menu "Kernel hacking"
 
 config CROSSCOMPILE
@@ -1294,12 +1436,32 @@ config CROSSCOMPILE
 	  Say Y here if you are compiling the kernel on a different
 	  architecture than the one it is intended to run on.
 
+config CMDLINE
+	string "Default kernel command string"
+	default ""
+	help
+          On some platforms, there is currently no way for the boot loader to
+          pass arguments to the kernel. For these platforms, you can supply
+          some command-line options at build time by entering them here.  In
+          other cases you can specify kernel args so that you don't have
+	  to set them up in board prom initialization routines.
+
 config DEBUG_KERNEL
 	bool "Kernel debugging"
 
+	config DEBUG_STACK_USAGE
+	bool "Enable stack utilization instrumentation"
+	depends on DEBUG_KERNEL
+	help
+	  Enables the display of the minimum amount of free stack which each
+	  task has ever had available in the sysrq-T and sysrq-P debug output.
+
+	  This option will slow down process creation somewhat.
+
 config KGDB
 	bool "Remote GDB kernel debugging"
 	depends on DEBUG_KERNEL
+	select DEBUG_INFO
 	help
 	  If you say Y here, it will be possible to remotely debug the MIPS
 	  kernel using gdb. This enlarges your kernel image disk size by
@@ -1315,6 +1477,23 @@ config GDB_CONSOLE
 	  would like kernel messages to be formatted into GDB $O packets so
 	  that GDB prints them as program output, say 'Y'.
 
+config DEBUG_INFO
+	bool "Compile the kernel with debug info"
+	depends on DEBUG_KERNEL && !KGDB
+	default y if KGDB
+	help
+	  If you say Y here the resulting kernel image will include
+	  debugging info resulting in a larger kernel image.
+	  Say Y here only if you plan to use gdb to debug the kernel.
+	  If you don't debug the kernel, you can say N.
+
+config SB1XXX_CORELIS
+	bool "Corelis Debugger"
+	depends on SIBYTE_SB1xxx_SOC && DEBUG_INFO
+	help
+	  Select compile flags that produce code that can be processed by the
+	  Corelis mksym utility and UDB Emulator.
+
 config RUNTIME_DEBUG
 	bool "Enable run-time debugging"
 	depends on DEBUG_KERNEL
--- diff/arch/mips/Makefile	2003-09-30 15:46:11.000000000 +0100
+++ source/arch/mips/Makefile	2004-02-23 13:56:38.000000000 +0000
@@ -5,7 +5,7 @@
 #
 # Copyright (C) 1994, 95, 96, 2003 by Ralf Baechle
 # DECStation modifications by Paul M. Antoine, 1996
-# Copyright (C) 2002  Maciej W. Rozycki
+# Copyright (C) 2002, 2003  Maciej W. Rozycki
 #
 # This file is included by the global makefile so that you can add your own
 # architecture-specific flags and dependencies. Remember to do have actions
@@ -16,22 +16,28 @@
 # Select the object file format to substitute into the linker script.
 #
 ifdef CONFIG_CPU_LITTLE_ENDIAN
-32bit-tool-prefix	= mips64el-linux-
+32bit-tool-prefix	= mipsel-linux-
 64bit-tool-prefix	= mips64el-linux-
 32bit-bfd		= elf32-tradlittlemips
 64bit-bfd		= elf64-tradlittlemips
 else
-32bit-tool-prefix	= mips64-linux-
+32bit-tool-prefix	= mips-linux-
 64bit-tool-prefix	= mips64-linux-
 32bit-bfd		= elf32-tradbigmips
 64bit-bfd		= elf64-tradbigmips
 endif
 
 ifdef CONFIG_MIPS32
+gcc-abi			= 32
+gas-abi			= 32
 tool-prefix		= $(32bit-tool-prefix)
+UTS_MACHINE		:= mips
 endif
 ifdef CONFIG_MIPS64
+gcc-abi			= 64
+gas-abi			= 32
 tool-prefix		= $(64bit-tool-prefix)
+UTS_MACHINE		:= mips64
 endif
 
 ifdef CONFIG_CROSSCOMPILE
@@ -50,76 +56,128 @@ endif
 #
 cflags-y			:= -I $(TOPDIR)/include/asm/gcc
 cflags-y			+= -G 0 -mno-abicalls -fno-pic -pipe
-cflags-$(CONFIG_MIPS32)		+= $(call check_gcc, -mabi=32,)
-cflags-$(CONFIG_MIPS64)		+= -mabi=64
+cflags-y			+= $(call check_gcc, -finline-limit=100000,)
 LDFLAGS_vmlinux			+= -G 0 -static # -N
 MODFLAGS			+= -mlong-calls
 
-cflags-$(CONFIG_KGDB)		+= -g
 cflags-$(CONFIG_SB1XXX_CORELIS)	+= -mno-sched-prolog -fno-omit-frame-pointer
 
 check_warning = $(shell if $(CC) $(1) -c -o /dev/null -xc /dev/null > /dev/null 2>&1; then echo "$(1)"; else echo "$(2)"; fi)
 
 #
+# Use: $(call set_gccflags,<cpu0>,<isa0>,<cpu1>,<isa1>,<isa2>)
+#
+# <cpu0>,<isa0> -- preferred CPU and ISA designations (may require
+#                  recent tools)
+# <cpu1>,<isa1> -- fallback CPU and ISA designations (have to work
+#                  with up to the oldest supported tools)
+# <isa2>        -- an ISA designation used as an ABI selector for
+#                  gcc versions that do not support "-mabi=32"
+#                  (depending on the CPU type, either "mips1" or
+#                  "mips2")
+#
+set_gccflags = $(shell \
+while :; do \
+	cpu=$(1); isa=-$(2); \
+	for gcc_opt in -march= -mcpu=; do \
+		$(CC) $$gcc_opt$$cpu $$isa -S -o /dev/null \
+			-xc /dev/null > /dev/null 2>&1 && \
+			break 2; \
+	done; \
+	cpu=$(3); isa=-$(4); \
+	for gcc_opt in -march= -mcpu=; do \
+		$(CC) $$gcc_opt$$cpu $$isa -S -o /dev/null \
+			-xc /dev/null > /dev/null 2>&1 && \
+			break 2; \
+	done; \
+	break; \
+done; \
+gcc_abi=-mabi=$(gcc-abi); gcc_cpu=$$cpu; \
+if $(CC) $$gcc_abi -S -o /dev/null -xc /dev/null > /dev/null 2>&1; then \
+	gcc_isa=$$isa; \
+else \
+	gcc_abi=; gcc_isa=-$(5); \
+fi; \
+gas_abi=-Wa,-$(gcc-abi); gas_cpu=$$cpu; gas_isa=-Wa,$$isa; \
+while :; do \
+	for gas_opt in -Wa,-march= -Wa,-mcpu=; do \
+		$(CC) $$gas_abi $$gas_opt$$cpu $$gas_isa -Wa,-Z -c \
+			-o /dev/null -xassembler /dev/null > /dev/null 2>&1 && \
+			break 2; \
+	done; \
+	gas_abi=; gas_opt=; gas_cpu=; gas_isa=; \
+	break; \
+done; \
+if test x$(gcc-abi) != x$(gas-abi); then \
+	gas_abi="-Wa,-$(gas-abi) -Wa,-mgp$(gcc-abi)"; \
+fi; \
+echo $$gcc_abi $$gcc_opt$$gcc_cpu $$gcc_isa $$gas_abi $$gas_opt$$gas_cpu $$gas_isa)
+
+#
 # CPU-dependent compiler/assembler options for optimization.
-# This is done in several steps:
 #
-#  - cflags-y    contains the options which select for which processor to
-#                optimize the code for.  The options should not contain any
-#                options that change the ISA level but only compiler flags to
-#                tune performance of the generated code.
-#  - 32bit-isa-y contains the options which select the ISA for 32-bit kernels.
-#                A kernel built those options will only work on hardware which
-#                actually supports this ISA.
-#  - 64bit-isa-y contains the options which select the ISA for 64-bit kernels.
-#                A kernel built those options will only work on hardware which
-#                actually supports this ISA.
-#
-cflags-$(CONFIG_CPU_R3000)	+= -mcpu=r3000
-32bit-isa-$(CONFIG_CPU_R3000)	+= -mips1
-64bit-isa-$(CONFIG_CPU_R3000)	+= -mboom
-cflags-$(CONFIG_CPU_TX39XX)	+= -mcpu=r3000
-32bit-isa-$(CONFIG_CPU_TX39XX)	+= -mips1
-64bit-isa-$(CONFIG_CPU_TX39XX)	+= -mboom
-cflags-$(CONFIG_CPU_R6000)	+= -mcpu=r6000
-32bit-isa-$(CONFIG_CPU_R6000)	+= -mips2 -Wa,--trap
-64bit-isa-$(CONFIG_CPU_R6000)	+= -mboom -Wa,--trap
-cflags-$(CONFIG_CPU_R4300)	+= -mcpu=r4300
-32bit-isa-$(CONFIG_CPU_R4300)	+= -mips2 -Wa,--trap
-64bit-isa-$(CONFIG_CPU_R4300)	+= -mips3 -Wa,--trap
-cflags-$(CONFIG_CPU_VR41XX)	+= -mcpu=r4600
-32bit-isa-$(CONFIG_CPU_VR41XX)	+= -mips2 -Wa,--trap
-64bit-isa-$(CONFIG_CPU_VR41XX)	+= -mips3 -Wa,--trap
-cflags-$(CONFIG_CPU_R4X00)	+= -mcpu=r4600
-32bit-isa-$(CONFIG_CPU_R4X00)	+= -mips2 -Wa,--trap
-64bit-isa-$(CONFIG_CPU_R4X00)	+= -mips3 -Wa,--trap
-cflags-$(CONFIG_CPU_MIPS32)	+= $(call check_gcc, -mtune=mips32, -mcpu=r4600)
-32bit-isa-$(CONFIG_CPU_MIPS32)	+= $(call check_gcc, -mips32 -mabi=32, -mips2) -Wa,--trap
-64bit-isa-$(CONFIG_CPU_MIPS32)	+= -mboom
-cflags-$(CONFIG_CPU_MIPS64)	+= 
-32bit-isa-$(CONFIG_CPU_MIPS64)	+= $(call check_gcc, -mips32, -mips2) -Wa,--trap
-64bit-isa-$(CONFIG_CPU_MIPS64)	+= $(call check_gcc, -mips64, -mips4) -Wa,--trap
-cflags-$(CONFIG_CPU_R5000)	+= -mcpu=r8000
-32bit-isa-$(CONFIG_CPU_R5000)	+= -mips2 -Wa,--trap
-64bit-isa-$(CONFIG_CPU_R5000)	+= -mips4 -Wa,--trap
-cflags-$(CONFIG_CPU_R5432)	+= -mcpu=r5000
-32bit-isa-$(CONFIG_CPU_R5432)	+= -mips1 -Wa,--trap
-64bit-isa-$(CONFIG_CPU_R5432)	+= -mips3 -Wa,--trap
-cflags-$(CONFIG_CPU_NEVADA)	+= -mcpu=r8000 -mmad
-32bit-isa-$(CONFIG_CPU_NEVADA)	+= -mips2 -Wa,--trap
-64bit-isa-$(CONFIG_CPU_NEVADA)	+= -mips3 -Wa,--trap
-cflags-$(CONFIG_CPU_RM7000)	+= $(call check_gcc, -mcpu=r7000, -mcpu=r5000)
-32bit-isa-$(CONFIG_CPU_RM7000)	+= -mips2 -Wa,--trap
-64bit-isa-$(CONFIG_CPU_RM7000)	+= -mips4 -Wa,--trap
-cflags-$(CONFIG_CPU_SB1)	+= $(call check_gcc, -mcpu=sb1, -mcpu=r8000)
-32bit-isa-$(CONFIG_CPU_SB1)	+= $(call check_gcc, -mips32, -mips2) -Wa,--trap
-64bit-isa-$(CONFIG_CPU_SB1)	+= $(call check_gcc, -mips64, -mips4) -Wa,--trap
-cflags-$(CONFIG_CPU_R8000)	+= -mcpu=r8000
-32bit-isa-$(CONFIG_CPU_R8000)	+= -mips2 -Wa,--trap
-64bit-isa-$(CONFIG_CPU_R8000)	+= -mips4 -Wa,--trap
-cflags-$(CONFIG_CPU_R10000)	+= -mcpu=r8000
-32bit-isa-$(CONFIG_CPU_R10000)	+= -mips2 -Wa,--trap
-64bit-isa-$(CONFIG_CPU_R10000)	+= -mips4 -Wa,--trap
+cflags-$(CONFIG_CPU_R3000)	+= \
+			$(call set_gccflags,r3000,mips1,r3000,mips1,mips1)
+
+cflags-$(CONFIG_CPU_TX39XX)	+= \
+			$(call set_gccflags,r3900,mips1,r3000,mips1,mips1)
+
+cflags-$(CONFIG_CPU_R6000)	+= \
+			$(call set_gccflags,r6000,mips2,r6000,mips2,mips2) \
+			-Wa,--trap
+
+cflags-$(CONFIG_CPU_R4300)	+= \
+			$(call set_gccflags,r4300,mips3,r4300,mips3,mips2) \
+			-Wa,--trap
+
+cflags-$(CONFIG_CPU_VR41XX)	+= \
+			$(call set_gccflags,r4100,mips3,r4600,mips3,mips2) \
+			-Wa,--trap
+
+cflags-$(CONFIG_CPU_R4X00)	+= \
+			$(call set_gccflags,r4600,mips3,r4600,mips3,mips2) \
+			-Wa,--trap
+
+cflags-$(CONFIG_CPU_MIPS32)	+= \
+			$(call set_gccflags,mips32,mips32,r4600,mips3,mips2) \
+			-Wa,--trap
+
+cflags-$(CONFIG_CPU_MIPS64)	+= \
+			$(call set_gccflags,mips64,mips64,r4600,mips3,mips2) \
+			-Wa,--trap
+
+cflags-$(CONFIG_CPU_R5000)	+= \
+			$(call set_gccflags,r5000,mips4,r5000,mips4,mips2) \
+			-Wa,--trap 
+
+cflags-$(CONFIG_CPU_R5432)	+= \
+			$(call set_gccflags,r5400,mips4,r5000,mips4,mips2) \
+			-Wa,--trap
+
+cflags-$(CONFIG_CPU_NEVADA)	+= \
+			$(call set_gccflags,rm5200,mips4,r5000,mips4,mips2) \
+			-Wa,--trap
+#			$(call check_gcc,-mmad,)
+
+cflags-$(CONFIG_CPU_RM7000)	+= \
+			$(call set_gccflags,rm7000,mips4,r5000,mips4,mips2) \
+			-Wa,--trap
+
+cflags-$(CONFIG_CPU_RM9000)	+= \
+			$(call set_gccflags,rm9000,mips4,r5000,mips4,mips2) \
+			-Wa,--trap
+
+cflags-$(CONFIG_CPU_SB1)	+= \
+			$(call set_gccflags,sb1,mips64,r5000,mips4,mips2) \
+			-Wa,--trap
+
+cflags-$(CONFIG_CPU_R8000)	+= \
+			$(call set_gccflags,r8000,mips4,r8000,mips4,mips2) \
+			-Wa,--trap
+
+cflags-$(CONFIG_CPU_R10000)	+= \
+			$(call set_gccflags,r10000,mips4,r8000,mips4,mips2) \
+			-Wa,--trap
 
 ifdef CONFIG_CPU_SB1
 ifdef CONFIG_SB1_PASS_1_WORKAROUNDS
@@ -129,13 +187,11 @@ endif
 
 #
 # ramdisk/initrd support
-# You need a compressed ramdisk image, named ramdisk.gz in
-# arch/mips/ramdisk
+# You need a compressed ramdisk image, named
+# CONFIG_EMBEDDED_RAMDISK_IMAGE. Relative pathnames 
+# are relative to arch/mips/ramdisk/.
 #
-ifdef CONFIG_EMBEDDED_RAMDISK
-CORE_FILES	+= arch/mips/ramdisk/ramdisk.o
-SUBDIRS		+= arch/mips/ramdisk
-endif
+core-$(CONFIG_EMBEDDED_RAMDISK)	+= arch/mips/ramdisk/
 
 #
 # Firmware support
@@ -150,18 +206,85 @@ libs-$(CONFIG_SIBYTE_CFE)	+= arch/mips/s
 #
 # Acer PICA 61, Mips Magnum 4000 and Olivetti M700.
 #
-core-$(CONFIG_MIPS_JAZZ)	+= arch/mips/jazz/
-load-$(CONFIG_MIPS_JAZZ)	+= 0x80080000
+core-$(CONFIG_MACH_JAZZ)	+= arch/mips/jazz/
+cflags-$(CONFIG_MACH_JAZZ)	+= -Iinclude/asm-mips/mach-jazz
+load-$(CONFIG_MACH_JAZZ)	+= 0x80080000
 
+#
+# Common Alchemy Au1x00 stuff
+#
+core-$(CONFIG_SOC_AU1X00)	+= arch/mips/au1000/common/
+cflags-$(CONFIG_SOC_AU1X00)	+= -Iinclude/asm-mips/mach-au1x00
 
 #
-# Au1500 (Alchemy Semi PB1500) eval board
+# AMD Alchemy Pb1000 eval board
+#
+libs-$(CONFIG_MIPS_PB1000)	+= arch/mips/au1000/pb1000/
+cflags-$(CONFIG_MIPS_PB1000)	+= -Iinclude/asm-mips/mach-pb1x00
+load-$(CONFIG_MIPS_PB1000)	+= 0x80100000
+
+#
+# AMD Alchemy Pb1100 eval board
+#
+libs-$(CONFIG_MIPS_PB1100)	+= arch/mips/au1000/pb1100/
+cflags-$(CONFIG_MIPS_PB1100)	+= -Iinclude/asm-mips/mach-pb1x00
+load-$(CONFIG_MIPS_PB1100)	+= 0x80100000
+
+#
+# AMD Alchemy Pb1500 eval board
 #
-core-$(CONFIG_MIPS_PB1500)	+= arch/mips/au1000/common/
 libs-$(CONFIG_MIPS_PB1500)	+= arch/mips/au1000/pb1500/
+cflags-$(CONFIG_MIPS_PB1500)	+= -Iinclude/asm-mips/mach-pb1x00
 load-$(CONFIG_MIPS_PB1500)	+= 0x80100000
 
 #
+# AMD Alchemy Db1000 eval board
+#
+libs-$(CONFIG_MIPS_DB1000)	+= arch/mips/au1000/db1x00/
+cflags-$(CONFIG_MIPS_DB1000)	+= -Iinclude/asm-mips/mach-db1x00
+load-$(CONFIG_MIPS_DB1000)	+= 0x80100000
+
+#
+# AMD Alchemy Db1100 eval board
+#
+libs-$(CONFIG_MIPS_DB1100)	+= arch/mips/au1000/db1x00/
+cflags-$(CONFIG_MIPS_DB1100)	+= -Iinclude/asm-mips/mach-db1x00
+load-$(CONFIG_MIPS_DB1100)	+= 0x80100000
+
+#
+# AMD Alchemy Db1500 eval board
+#
+libs-$(CONFIG_MIPS_DB1500)	+= arch/mips/au1000/db1x00/
+cflags-$(CONFIG_MIPS_DB1500)	+= -Iinclude/asm-mips/mach-db1x00
+load-$(CONFIG_MIPS_DB1500)	+= 0x80100000
+
+#
+# AMD Alchemy Bosporus eval board
+#
+libs-$(CONFIG_MIPS_BOSPORUS)	+= arch/mips/au1000/db1x00/
+cflags-$(CONFIG_MIPS_BOSPORUS)	+= -Iinclude/asm-mips/mach-db1x00
+load-$(CONFIG_MIPS_BOSPORUS)	+= 0x80100000
+
+#
+# AMD Alchemy Mirage eval board
+#
+libs-$(CONFIG_MIPS_MIRAGE)	+= arch/mips/au1000/db1x00/
+cflags-$(CONFIG_MIPS_MIRAGE)	+= -Iinclude/asm-mips/mach-db1x00
+load-$(CONFIG_MIPS_MIRAGE)	+= 0x80100000
+
+#
+# 4G-Systems eval board
+#
+libs-$(CONFIG_MIPS_MTX1)	+= arch/mips/au1000/mtx-1/
+load-$(CONFIG_MIPS_MTX1)	+= 0x80100000
+
+#
+# MyCable eval board
+#
+libs-$(CONFIG_MIPS_XXS1500)	+= arch/mips/au1000/xxs1500/
+load-$(CONFIG_MIPS_XXS1500)	+= 0x80100000
+
+#
 # Baget/MIPS
 #
 libs-$(CONFIG_BAGET_MIPS)	+= arch/mips/baget/ arch/mips/baget/prom/
@@ -176,22 +299,25 @@ load-$(CONFIG_MIPS_COBALT)	+= 0x80080000
 #
 # DECstation family
 #
-core-$(CONFIG_DECSTATION)	+= arch/mips/dec/
-libs-$(CONFIG_DECSTATION)	+= arch/mips/dec/prom/
-load-$(CONFIG_DECSTATION)	+= 0x80040000
+core-$(CONFIG_MACH_DECSTATION)	+= arch/mips/dec/
+cflags-$(CONFIG_MACH_DECSTATION)+= -Iinclude/asm-mips/mach-dec
+libs-$(CONFIG_MACH_DECSTATION)	+= arch/mips/dec/prom/
+load-$(CONFIG_MACH_DECSTATION)	+= 0x80040000
 CLEAN_FILES			+= drivers/tc/lk201-map.c
 
 #
 # Galileo EV64120 Board
 #
-core-$(CONFIG_MIPS_EV64120)	+= arch/mips/galileo-boards/ev64120/
+core-$(CONFIG_MIPS_EV64120)	+= arch/mips/gt64120/ev64120/
+core-$(CONFIG_MIPS_EV64120)	+= arch/mips/gt64120/common/
+cflags-$(CONFIG_MIPS_EV64120)	+= -Iinclude/asm-mips/mach-ev64120
 load-$(CONFIG_MIPS_EV64120)	+= 0x80100000
 
 #
 # Galileo EV96100 Board
 #
-core-$(CONFIG_MIPS_EV96100)	+= arch/mips/galileo-boards/generic/ \
-				   arch/mips/galileo-boards/ev96100/
+core-$(CONFIG_MIPS_EV96100)	+= arch/mips/galileo-boards/ev96100/
+cflags-$(CONFIG_MIPS_EV96100)	+= -Iinclude/asm-mips/mach-ev96100
 load-$(CONFIG_MIPS_EV96100)	+= 0x80100000
 
 #
@@ -214,16 +340,23 @@ core-$(CONFIG_MIPS_ITE8172)	+= arch/mips
 load-$(CONFIG_MIPS_ITE8172)	+= 0x80100000
 
 #
-# MIPS Atlas board
+# For all MIPS, Inc. eval boards
 #
 core-$(CONFIG_MIPS_BOARDS_GEN)	+= arch/mips/mips-boards/generic/
+
+#
+# MIPS Atlas board
+#
 core-$(CONFIG_MIPS_ATLAS)	+= arch/mips/mips-boards/atlas/
+cflags-$(CONFIG_MIPS_ATLAS)	+= -Iinclude/asm-mips/mach-atlas
+cflags-$(CONFIG_MIPS_ATLAS)	+= -Iinclude/asm-mips/mach-mips
 load-$(CONFIG_MIPS_ATLAS)	+= 0x80100000
 
 #
 # MIPS Malta board
 #
 core-$(CONFIG_MIPS_MALTA)	+= arch/mips/mips-boards/malta/
+cflags-$(CONFIG_MIPS_MALTA)	+= -Iinclude/asm-mips/mach-mips
 load-$(CONFIG_MIPS_MALTA)	+= 0x80100000
 
 #
@@ -240,6 +373,7 @@ load-$(CONFIG_MIPS_SEAD)	+= 0x80100000
 #
 core-$(CONFIG_MOMENCO_OCELOT)	+= arch/mips/gt64120/common/ \
 				   arch/mips/gt64120/momenco_ocelot/
+cflags-$(CONFIG_MOMENCO_OCELOT)	+= -Iinclude/asm-mips/mach-ocelot
 load-$(CONFIG_MOMENCO_OCELOT)	+= 0x80100000
 
 #
@@ -260,9 +394,23 @@ core-$(CONFIG_MOMENCO_OCELOT_C)	+= arch/
 load-$(CONFIG_MOMENCO_OCELOT_C)	+= 0x80100000
 
 #
-# NEC DDB Vrc-5074
+# Momentum Jaguar ATX
+#
+core-$(CONFIG_MOMENCO_JAGUAR_ATX)	+= arch/mips/momentum/jaguar_atx/
+ifdef CONFIG_JAGUAR_DMALOW
+load-$(CONFIG_MOMENCO_JAGUAR_ATX)	+= 0x88000000
+else
+load-$(CONFIG_MOMENCO_JAGUAR_ATX)	+= 0x80100000
+endif
+
+#
+# NEC DDB
 #
 core-$(CONFIG_DDB5XXX_COMMON)	+= arch/mips/ddb5xxx/common/
+
+#
+# NEC DDB Vrc-5074
+#
 core-$(CONFIG_DDB5074)		+= arch/mips/ddb5xxx/ddb5074/
 load-$(CONFIG_DDB5074)		+= 0x80080000
 
@@ -279,6 +427,7 @@ core-$(CONFIG_DDB5477)		+= arch/mips/ddb
 load-$(CONFIG_DDB5477)		+= 0x80100000
 
 core-$(CONFIG_LASAT)		+= arch/mips/lasat/
+cflags-$(CONFIG_LASAT)		+= -Iinclude/asm-mips/mach-lasat
 load-$(CONFIG_LASAT)		+= 0x80000000
 
 #
@@ -289,9 +438,14 @@ core-$(CONFIG_NEC_OSPREY)	+= arch/mips/v
 load-$(CONFIG_NEC_OSPREY)	+= 0x80002000
 
 #
+# Common VR41xx
+#
+core-$(CONFIG_MACH_VR41XX)	+= arch/mips/vr41xx/common/
+cflags-$(CONFIG_MACH_VR41XX)	+= -Iinclude/asm-mips/mach-vr41xx
+
+#
 # NEC Eagle/Hawk (VR4122/VR4131) board
 #
-core-$(CONFIG_VR41XX_COMMON)	+= arch/mips/vr41xx/common/
 core-$(CONFIG_NEC_EAGLE)	+= arch/mips/vr41xx/nec-eagle/
 load-$(CONFIG_NEC_EAGLE)	+= 0x80000000
 
@@ -340,6 +494,7 @@ load-$(CONFIG_TANBAC_TB0229)	+= 0x800000
 # will break so for 64-bit kernels we have to raise the start address by 8kb.
 #
 core-$(CONFIG_SGI_IP22)		+= arch/mips/sgi-ip22/
+cflags-$(CONFIG_SGI_IP22)	+= -Iinclude/asm-mips/mach-ip22
 ifdef CONFIG_MIPS32
 load-$(CONFIG_SGI_IP22)		+= 0x88002000
 endif
@@ -356,6 +511,7 @@ endif
 #
 ifdef CONFIG_SGI_IP27
 core-$(CONFIG_SGI_IP27)		+= arch/mips/sgi-ip27/
+cflags-$(CONFIG_SGI_IP27)	+= -Iinclude/asm-mips/mach-ip27
 #load-$(CONFIG_SGI_IP27)	+= 0xa80000000001c000
 ifdef CONFIG_MAPPED_KERNEL
 load-$(CONFIG_SGI_IP27)		+= 0xc001c000
@@ -373,11 +529,12 @@ endif
 # will break so for 64-bit kernels we have to raise the start address by 8kb.
 #
 core-$(CONFIG_SGI_IP32)		+= arch/mips/sgi-ip32/
+cflags-$(CONFIG_SGI_IP32)	+= -Iinclude/asm-mips/mach-ip32
 ifdef CONFIG_MIPS32
-load-$(CONFIG_SGI_IP32)		+= 0x88002000
+load-$(CONFIG_SGI_IP32)		+= 0x80002000
 endif
 ifdef CONFIG_MIPS64
-load-$(CONFIG_SGI_IP32)		+= 0x88004000
+load-$(CONFIG_SGI_IP32)		+= 0x80004000
 endif
 
 #
@@ -388,6 +545,7 @@ endif
 # removed (as happens, even if they have __initcall/module_init)
 #
 core-$(CONFIG_SIBYTE_BCM112X)	+= arch/mips/sibyte/sb1250/
+
 core-$(CONFIG_SIBYTE_SB1250)	+= arch/mips/sibyte/sb1250/
 
 #
@@ -414,7 +572,8 @@ load-$(CONFIG_SIBYTE_SWARM)	:= 0x8010000
 # SNI RM200 PCI
 #
 core-$(CONFIG_SNI_RM200_PCI)	+= arch/mips/sni/
-load-$(CONFIG_SNI_RM200_PCI)	+= 0x80080000
+cflags-$(CONFIG_SNI_RM200_PCI)	+= -Iinclude/asm-mips/mach-rm200
+load-$(CONFIG_SNI_RM200_PCI)	+= 0x80600000
 
 #
 # Toshiba JMR-TX3927 board
@@ -431,6 +590,7 @@ core-$(CONFIG_TOSHIBA_RBTX4927)	+= arch/
 core-$(CONFIG_TOSHIBA_RBTX4927)	+= arch/mips/tx4927/common/
 load-$(CONFIG_TOSHIBA_RBTX4927)	+= 0x80020000
 
+cflags-y			+= -Iinclude/asm-mips/mach-generic
 drivers-$(CONFIG_PCI)		+= arch/mips/pci/
 
 ifdef CONFIG_MIPS32
@@ -463,17 +623,6 @@ endif
 #AS += -64
 #LDFLAGS += -m elf64bmip
 
-ifdef CONFIG_MIPS64
-#
-# We use an unusual code model for building 64-bit kernels.  64-bit ELF,
-# squeezed into 32-bit ELF files.  Later version of gas throw silly warnings
-# which requires the use of -mgp64 which not all gas versions have ...
-#
-GRRR=-Wa,-mgp64
-cflags-$(CONFIG_BOOT_ELF32)	+= -Wa,-32 $(call check_warning, $(GRRR),)
-cflags-$(CONFIG_BOOT_ELF64)	+= -Wa,-32 $(call check_warning, $(GRRR),)
-endif
-
 #
 # Choosing incompatible machines durings configuration will result in
 # error messages during linking.  Select a default linkscript if
@@ -516,25 +665,32 @@ endif
 
 ifdef CONFIG_MAPPED_KERNEL
 vmlinux.64: vmlinux
-	$(OBJCOPY) -O $(64bit-bfd) --change-addresses=0xbfffffff40000000 $< $@
+	$(OBJCOPY) -O $(64bit-bfd) --remove-section=.reginfo \
+		--change-addresses=0xc000000080000000 $< $@
 else
 vmlinux.64: vmlinux
-	$(OBJCOPY) -O $(64bit-bfd) --change-addresses=0xa7ffffff80000000 $< $@
+	$(OBJCOPY) -O $(64bit-bfd) --remove-section=.reginfo \
+		--change-addresses=0xa800000080000000 $< $@
 endif
 
 makeboot =$(Q)$(MAKE) -f scripts/Makefile.build obj=arch/mips/boot $(1)
 
-#
-# SNI firmware is f*cked in interesting ways ...
-#
+ifdef CONFIG_SGI_IP27
+all:	vmlinux.64
+endif
+
 ifdef CONFIG_SNI_RM200_PCI
-all:	vmlinux.rm200
+all:	vmlinux.ecoff
 endif
 
 vmlinux.ecoff vmlinux.rm200: vmlinux
 	+@$(call makeboot,$@)
 
+vmlinux.srec: vmlinux
+	+@$(call makeboot,$@)
+
 CLEAN_FILES += vmlinux.ecoff \
+	       vmlinux.srec \
 	       vmlinux.rm200.tmp \
 	       vmlinux.rm200
 
@@ -594,4 +750,6 @@ include/asm-$(ARCH)/reg.h: arch/$(ARCH)/
 CLEAN_FILES += include/asm-$(ARCH)/offset.h.tmp \
 	       include/asm-$(ARCH)/offset.h \
 	       include/asm-$(ARCH)/reg.h.tmp \
-	       include/asm-$(ARCH)/reg.h
+	       include/asm-$(ARCH)/reg.h \
+	       vmlinux.64 \
+	       vmlinux.ecoff
--- diff/arch/mips/arc/cmdline.c	2003-07-08 09:55:17.000000000 +0100
+++ source/arch/mips/arc/cmdline.c	2004-02-23 13:56:38.000000000 +0000
@@ -16,8 +16,6 @@
 
 #undef DEBUG_CMDLINE
 
-char arcs_cmdline[CL_SIZE];
-
 char * __init prom_getcmdline(void)
 {
 	return arcs_cmdline;
--- diff/arch/mips/arc/identify.c	2003-07-08 09:55:17.000000000 +0100
+++ source/arch/mips/arc/identify.c	2004-02-23 13:56:38.000000000 +0000
@@ -63,7 +63,7 @@ static struct smatch mach_table[] = {
 		"SNI RM200_PCI",
 		MACH_GROUP_SNI_RM,
 		MACH_SNI_RM200_PCI,
-		0
+		PROM_FLAG_DONT_FREE_TEMP
 	}
 };
 
--- diff/arch/mips/arc/init.c	2003-07-08 09:55:17.000000000 +0100
+++ source/arch/mips/arc/init.c	2004-02-23 13:56:38.000000000 +0000
@@ -10,6 +10,7 @@
 #include <linux/init.h>
 #include <linux/kernel.h>
 
+#include <asm/bootinfo.h>
 #include <asm/sgialib.h>
 
 #undef DEBUG_PROM_INIT
@@ -19,13 +20,13 @@ struct linux_romvec *romvec;
 int prom_argc;
 LONG *_prom_argv, *_prom_envp;
 
-void __init prom_init(int argc, char **argv, char **envp, int *prom_vec)
+void __init prom_init(void)
 {
 	PSYSTEM_PARAMETER_BLOCK pb = PROMBLOCK;
 	romvec = ROMVECTOR;
-	prom_argc = argc;
-	_prom_argv = (LONG *) argv;
-	_prom_envp = (LONG *) envp;
+	prom_argc = fw_arg0;
+	_prom_argv = (LONG *) fw_arg1;
+	_prom_envp = (LONG *) fw_arg2;
 
 	if (pb->magic != 0x53435241) {
 		prom_printf("Aieee, bad prom vector magic %08lx\n", pb->magic);
--- diff/arch/mips/arc/memory.c	2003-07-08 09:55:17.000000000 +0100
+++ source/arch/mips/arc/memory.c	2004-02-23 13:56:38.000000000 +0000
@@ -26,6 +26,12 @@
 
 #undef DEBUG
 
+/*
+ * For ARC firmware memory functions the unit of meassuring memory is always
+ * a 4k page of memory
+ */
+#define ARC_PAGE_SHIFT	12
+
 struct linux_mdesc * __init ArcGetMemoryDescriptor(struct linux_mdesc *Current)
 {
 	return (struct linux_mdesc *) ARC_CALL1(get_mdesc, Current);
@@ -127,20 +133,23 @@ void __init prom_meminit(void)
 		unsigned long base, size;
 		long type;
 
-		base = p->base << PAGE_SHIFT;
-		size = p->pages << PAGE_SHIFT;
+		base = p->base << ARC_PAGE_SHIFT;
+		size = p->pages << ARC_PAGE_SHIFT;
 		type = prom_memtype_classify(p->type);
 
 		add_memory_region(base, size, type);
 	}
 }
 
-void __init prom_free_prom_memory (void)
+unsigned long __init prom_free_prom_memory(void)
 {
 	unsigned long freed = 0;
 	unsigned long addr;
 	int i;
 
+	if (prom_flags & PROM_FLAG_DONT_FREE_TEMP)
+		return 0;
+
 	for (i = 0; i < boot_mem_map.nr_map; i++) {
 		if (boot_mem_map.map[i].type != BOOT_MEM_ROM_DATA)
 			continue;
@@ -156,4 +165,6 @@ void __init prom_free_prom_memory (void)
 		}
 	}
 	printk(KERN_INFO "Freeing prom memory: %ldkb freed\n", freed >> 10);
+
+	return freed;
 }
--- diff/arch/mips/arc/misc.c	2003-07-08 09:55:17.000000000 +0100
+++ source/arch/mips/arc/misc.c	2004-02-23 13:56:38.000000000 +0000
@@ -101,3 +101,8 @@ ArcFlushAllCaches(VOID)
 {
 	ARC_CALL0(cache_flush);
 }
+
+DISPLAY_STATUS * __init ArcGetDisplayStatus(ULONG FileID)
+{
+	return ARC_CALL1(GetDisplayStatus, FileID);
+}
--- diff/arch/mips/au1000/common/Makefile	2003-07-08 09:55:17.000000000 +0100
+++ source/arch/mips/au1000/common/Makefile	2004-02-23 13:56:38.000000000 +0000
@@ -5,14 +5,11 @@
 #
 # Makefile for the Alchemy Au1000 CPU, generic files.
 #
-# 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).
-#
 
 obj-y				+= prom.o int-handler.o dma.o irq.o puts.o \
-				   time.o reset.o clocks.o power.o
+				   time.o reset.o clocks.o power.o setup.o \
+				   sleeper.o
 
 obj-$(CONFIG_AU1X00_USB_DEVICE)	+= usbdev.o
 obj-$(CONFIG_KGDB)		+= dbg_io.o
-obj-$(CONFIG_RTC)		+= rtc.o
+obj-$(CONFIG_PCI)		+= pci.o
--- diff/arch/mips/au1000/common/clocks.c	2003-07-08 09:55:17.000000000 +0100
+++ source/arch/mips/au1000/common/clocks.c	2004-02-23 13:56:38.000000000 +0000
@@ -28,7 +28,7 @@
  */
 
 #include <linux/module.h>
-#include <asm/au1000.h>
+#include <asm/mach-au1x00/au1000.h>
 
 static unsigned int au1x00_clock; // Hz
 static unsigned int lcd_clock;    // KHz
@@ -85,8 +85,7 @@ void set_au1x00_lcd_clock(void)
 		lcd_clock = sys_busclk / 4;
 
 	if (lcd_clock > 50000) /* Epson MAX */
-			printk("%s: warning: LCD clock too high (%d KHz)\n", 
-					__FUNCTION__, lcd_clock);
+		printk("warning: LCD clock too high (%d KHz)\n", lcd_clock);
 }
 
 unsigned int get_au1x00_lcd_clock(void)
--- diff/arch/mips/au1000/common/dbg_io.c	2003-07-08 09:55:17.000000000 +0100
+++ source/arch/mips/au1000/common/dbg_io.c	2004-02-23 13:56:38.000000000 +0000
@@ -1,7 +1,7 @@
 
 #include <linux/config.h>
 #include <asm/io.h>
-#include <asm/au1000.h>
+#include <asm/mach-au1x00/au1000.h>
 
 #ifdef CONFIG_KGDB
 
--- diff/arch/mips/au1000/common/dma.c	2003-09-17 12:28:02.000000000 +0100
+++ source/arch/mips/au1000/common/dma.c	2004-02-23 13:56:38.000000000 +0000
@@ -36,12 +36,12 @@
 #include <linux/spinlock.h>
 #include <linux/string.h>
 #include <linux/delay.h>
-#include <asm/au1000.h>
-#include <asm/au1000_dma.h>
+#include <linux/interrupt.h>
 #include <asm/system.h>
+#include <asm/mach-au1x00/au1000.h>
+#include <asm/mach-au1x00/au1000_dma.h>
 
-
-
+#if defined(CONFIG_SOC_AU1000) || defined(CONFIG_SOC_AU1500) || defined(CONFIG_SOC_AU1100)
 /*
  * A note on resource allocation:
  *
@@ -95,7 +95,6 @@ static const struct {
 	{I2S_DATA, DMA_DR | DMA_DW32 | DMA_NC}
 };
 
-
 int au1000_dma_read_proc(char *buf, char **start, off_t fpos,
 			 int length, int *eof, void *data)
 {
@@ -152,7 +151,7 @@ void dump_au1000_dma_channel(unsigned in
  * Requests the DMA done IRQ if irqhandler != NULL.
  */
 int request_au1000_dma(int dev_id, const char *dev_str,
-		       void (*irqhandler)(int, void *, struct pt_regs *),
+		       irqreturn_t (*irqhandler)(int, void *, struct pt_regs *),
 		       unsigned long irqflags,
 		       void *irq_dev_id)
 {
@@ -198,7 +197,6 @@ int request_au1000_dma(int dev_id, const
 	return i;
 }
 
-
 void free_au1000_dma(unsigned int dmanr)
 {
 	struct dma_chan *chan = get_dma_chan(dmanr);
@@ -215,3 +213,4 @@ void free_au1000_dma(unsigned int dmanr)
 	chan->irq_dev = NULL;
 	chan->dev_id = -1;
 }
+#endif // AU1000 AU1500 AU1100
--- diff/arch/mips/au1000/common/irq.c	2003-07-08 09:55:17.000000000 +0100
+++ source/arch/mips/au1000/common/irq.c	2004-02-23 13:56:38.000000000 +0000
@@ -26,6 +26,7 @@
  *  with this program; if not, write  to the Free Software Foundation, Inc.,
  *  675 Mass Ave, Cambridge, MA 02139, USA.
  */
+#include <linux/config.h>
 #include <linux/errno.h>
 #include <linux/init.h>
 #include <linux/irq.h>
@@ -46,22 +47,9 @@
 #include <asm/io.h>
 #include <asm/mipsregs.h>
 #include <asm/system.h>
-#include <asm/au1000.h>
-
-#if defined(CONFIG_MIPS_PB1000)
-#include <asm/pb1000.h>
-#elif defined(CONFIG_MIPS_PB1500)
-#include <asm/pb1500.h>
-#elif defined(CONFIG_MIPS_PB1100)
-#include <asm/pb1100.h>
-#elif defined(CONFIG_MIPS_DB1000)
-#include <asm/db1x00.h>
-#elif defined(CONFIG_MIPS_DB1100)
-#include <asm/db1x00.h>
-#elif defined(CONFIG_MIPS_DB1500)
-#include <asm/db1x00.h>
-#else
-#error unsupported Alchemy board
+#include <asm/mach-au1x00/au1000.h>
+#ifdef CONFIG_MIPS_PB1000
+#include <asm/mach-pb1x00/pb1000.h>
 #endif
 
 #undef DEBUG_IRQ
@@ -85,8 +73,6 @@ extern void breakpoint(void);
 extern asmlinkage void au1000_IRQ(void);
 extern void set_debug_traps(void);
 extern irq_cpustat_t irq_stat [NR_CPUS];
-unsigned int local_bh_count[NR_CPUS];
-unsigned int local_irq_count[NR_CPUS];
 
 static void setup_local_irq(unsigned int irq, int type, int int_req);
 static unsigned int startup_irq(unsigned int irq);
@@ -94,10 +80,12 @@ static void end_irq(unsigned int irq_nr)
 static inline void mask_and_ack_level_irq(unsigned int irq_nr);
 static inline void mask_and_ack_rise_edge_irq(unsigned int irq_nr);
 static inline void mask_and_ack_fall_edge_irq(unsigned int irq_nr);
+static inline void mask_and_ack_either_edge_irq(unsigned int irq_nr);
 inline void local_enable_irq(unsigned int irq_nr);
 inline void local_disable_irq(unsigned int irq_nr);
 
 extern void __init init_generic_irq(void);
+void	(*board_init_irq)(void);
 
 #ifdef CONFIG_PM
 extern void counter0_irq(int irq, void *dev_id, struct pt_regs *regs);
@@ -121,6 +109,11 @@ static void setup_local_irq(unsigned int
 				au_writel(1<<(irq_nr-32), IC1_CFG1SET);
 				au_writel(1<<(irq_nr-32), IC1_CFG0CLR);
 				break;
+			case INTC_INT_RISE_AND_FALL_EDGE: /* 0:1:1 */
+				au_writel(1<<(irq_nr-32), IC1_CFG2CLR);
+				au_writel(1<<(irq_nr-32), IC1_CFG1SET);
+				au_writel(1<<(irq_nr-32), IC1_CFG0SET);
+				break;
 			case INTC_INT_HIGH_LEVEL: /* 1:0:1 */
 				au_writel(1<<(irq_nr-32), IC1_CFG2SET);
 				au_writel(1<<(irq_nr-32), IC1_CFG1CLR);
@@ -163,6 +156,11 @@ static void setup_local_irq(unsigned int
 				au_writel(1<<irq_nr, IC0_CFG1SET);
 				au_writel(1<<irq_nr, IC0_CFG0CLR);
 				break;
+			case INTC_INT_RISE_AND_FALL_EDGE: /* 0:1:1 */
+				au_writel(1<<irq_nr, IC0_CFG2CLR);
+				au_writel(1<<irq_nr, IC0_CFG1SET);
+				au_writel(1<<irq_nr, IC0_CFG0SET);
+				break;
 			case INTC_INT_HIGH_LEVEL: /* 1:0:1 */
 				au_writel(1<<irq_nr, IC0_CFG2SET);
 				au_writel(1<<irq_nr, IC0_CFG1CLR);
@@ -267,6 +265,25 @@ static inline void mask_and_ack_fall_edg
 }
 
 
+static inline void mask_and_ack_either_edge_irq(unsigned int irq_nr)
+{
+	/* This may assume that we don't get interrupts from
+	 * both edges at once, or if we do, that we don't care.
+	 */
+	if (irq_nr > AU1000_LAST_INTC0_INT) {
+		au_writel(1<<(irq_nr-32), IC1_FALLINGCLR);
+		au_writel(1<<(irq_nr-32), IC1_RISINGCLR);
+		au_writel(1<<(irq_nr-32), IC1_MASKCLR);
+	}
+	else {
+		au_writel(1<<irq_nr, IC0_FALLINGCLR);
+		au_writel(1<<irq_nr, IC0_RISINGCLR);
+		au_writel(1<<irq_nr, IC0_MASKCLR);
+	}
+	au_sync();
+}
+
+
 static inline void mask_and_ack_level_irq(unsigned int irq_nr)
 {
 
@@ -352,7 +369,6 @@ static struct hw_interrupt_type rise_edg
 	NULL
 };
 
-/*
 static struct hw_interrupt_type fall_edge_irq_type = {
 	"Au1000 Fall Edge",
 	startup_irq,
@@ -363,7 +379,17 @@ static struct hw_interrupt_type fall_edg
 	end_irq,
 	NULL
 };
-*/
+
+static struct hw_interrupt_type either_edge_irq_type = {
+	"Au1000 Rise or Fall Edge",
+	startup_irq,
+	shutdown_irq,
+	local_enable_irq,
+	local_disable_irq,
+	mask_and_ack_either_edge_irq,
+	end_irq,
+	NULL
+};
 
 static struct hw_interrupt_type level_irq_type = {
 	"Au1000 Level",
@@ -388,6 +414,9 @@ void __init init_IRQ(void)
 {
 	int i;
 	unsigned long cp0_status;
+	au1xxx_irq_map_t *imp;
+	extern au1xxx_irq_map_t au1xxx_irq_map[];
+	extern int au1xxx_nr_irqs;
 
 	cp0_status = read_c0_status();
 	memset(irq_desc, 0, sizeof(irq_desc));
@@ -396,109 +425,54 @@ void __init init_IRQ(void)
 	init_generic_irq();
 
 	for (i = 0; i <= AU1000_MAX_INTR; i++) {
-		switch (i) {
-			case AU1000_UART0_INT:
-			case AU1000_UART3_INT:
-#ifdef CONFIG_MIPS_PB1000
-			case AU1000_UART1_INT:
-			case AU1000_UART2_INT:
+		/* default is active high, level interrupt */
+		setup_local_irq(i, INTC_INT_HIGH_LEVEL, 0);
+		irq_desc[i].handler = &level_irq_type;
+	}
 
-			case AU1000_SSI0_INT:
-			case AU1000_SSI1_INT:
-#endif
+	/* Now set up the irq mapping for the board.
+	*/
+	imp = au1xxx_irq_map;
+	for (i=0; i<au1xxx_nr_irqs; i++) {
 
-#ifdef CONFIG_MIPS_PB1100
-			case AU1000_UART1_INT:
+		setup_local_irq(imp->im_irq, imp->im_type, imp->im_request);
 
-			case AU1000_SSI0_INT:
-			case AU1000_SSI1_INT:
-#endif
-		        case AU1000_DMA_INT_BASE:
-		        case AU1000_DMA_INT_BASE+1:
-		        case AU1000_DMA_INT_BASE+2:
-		        case AU1000_DMA_INT_BASE+3:
-		        case AU1000_DMA_INT_BASE+4:
-		        case AU1000_DMA_INT_BASE+5:
-		        case AU1000_DMA_INT_BASE+6:
-		        case AU1000_DMA_INT_BASE+7:
-
-			case AU1000_IRDA_TX_INT:
-			case AU1000_IRDA_RX_INT:
-
-			case AU1000_MAC0_DMA_INT:
-#if defined(CONFIG_MIPS_PB1000) || defined(CONFIG_MIPS_DB1000) || defined(CONFIG_MIPS_PB1500) || defined(CONFIG_MIPS_DB1500)
-			case AU1000_MAC1_DMA_INT:
-#endif
-			case AU1500_GPIO_204:
-				setup_local_irq(i, INTC_INT_HIGH_LEVEL, 0);
-				irq_desc[i].handler = &level_irq_type;
-				break;
+		switch (imp->im_type) {
 
-#ifdef CONFIG_MIPS_PB1000
-			case AU1000_GPIO_15:
-#endif
-		        case AU1000_USB_HOST_INT:
-#if defined(CONFIG_MIPS_PB1500) || defined(CONFIG_MIPS_DB1500)
-			case AU1000_PCI_INTA:
-			case AU1000_PCI_INTB:
-			case AU1000_PCI_INTC:
-			case AU1000_PCI_INTD:
-			case AU1500_GPIO_201:
-			case AU1500_GPIO_202:
-			case AU1500_GPIO_203:
-			case AU1500_GPIO_205:
-			case AU1500_GPIO_207:
-#endif
+		case INTC_INT_HIGH_LEVEL:
+			irq_desc[imp->im_irq].handler = &level_irq_type;
+			break;
 
-#ifdef CONFIG_MIPS_PB1100
-			case AU1000_GPIO_9: // PCMCIA Card Fully_Interted#
-			case AU1000_GPIO_10: // PCMCIA_STSCHG#
-			case AU1000_GPIO_11: // PCMCIA_IRQ#
-			case AU1000_GPIO_13: // DC_IRQ#
-			case AU1000_GPIO_23: // 2-wire SCL
-#endif
-#if defined(CONFIG_MIPS_DB1000) || defined(CONFIG_MIPS_DB1100) || defined(CONFIG_MIPS_DB1500)
-			case AU1000_GPIO_0: // PCMCIA Card 0 Fully_Interted#
-			case AU1000_GPIO_1: // PCMCIA Card 0 STSCHG#
-			case AU1000_GPIO_2: // PCMCIA Card 0 IRQ#
-
-			case AU1000_GPIO_3: // PCMCIA Card 1 Fully_Interted#
-			case AU1000_GPIO_4: // PCMCIA Card 1 STSCHG#
-			case AU1000_GPIO_5: // PCMCIA Card 1 IRQ#
-#endif
-				setup_local_irq(i, INTC_INT_LOW_LEVEL, 0);
-				irq_desc[i].handler = &level_irq_type;
-                                break;
-			case AU1000_ACSYNC_INT:
-			case AU1000_AC97C_INT:
-			case AU1000_TOY_INT:
-			case AU1000_TOY_MATCH0_INT:
-			case AU1000_TOY_MATCH1_INT:
-		        case AU1000_USB_DEV_SUS_INT:
-		        case AU1000_USB_DEV_REQ_INT:
-			case AU1000_RTC_INT:
-			case AU1000_RTC_MATCH0_INT:
-			case AU1000_RTC_MATCH1_INT:
-			case AU1000_RTC_MATCH2_INT:
-				setup_local_irq(i, INTC_INT_RISE_EDGE, 0);
-				irq_desc[i].handler = &rise_edge_irq_type;
-				break;
-
-				 // Careful if you change match 2 request!
-				 // The interrupt handler is called directly
-				 // from the low level dispatch code.
-			case AU1000_TOY_MATCH2_INT:
-				 setup_local_irq(i, INTC_INT_RISE_EDGE, 1);
-				 irq_desc[i].handler = &rise_edge_irq_type;
-				  break;
-			default: /* active high, level interrupt */
-				setup_local_irq(i, INTC_INT_HIGH_LEVEL, 0);
-				irq_desc[i].handler = &level_irq_type;
-				break;
+		case INTC_INT_LOW_LEVEL:
+			irq_desc[imp->im_irq].handler = &level_irq_type;
+			break;
+
+		case INTC_INT_RISE_EDGE:
+			irq_desc[imp->im_irq].handler = &rise_edge_irq_type;
+			break;
+
+		case INTC_INT_FALL_EDGE:
+			irq_desc[imp->im_irq].handler = &fall_edge_irq_type;
+			break;
+
+		case INTC_INT_RISE_AND_FALL_EDGE:
+			irq_desc[imp->im_irq].handler = &either_edge_irq_type;
+			break;
+
+		default:
+			panic("Unknown au1xxx irq map");
+			break;
 		}
+		imp++;
 	}
 
 	set_c0_status(ALLINTS);
+
+	/* Board specific IRQ initialization.
+	*/
+	if (board_init_irq)
+		(*board_init_irq)();
+
 #ifdef CONFIG_KGDB
 	/* If local serial I/O used for debug port, enter kgdb at once */
 	puts("Waiting for kgdb to connect...");
@@ -516,7 +490,7 @@ void __init init_IRQ(void)
 
 void intc0_req0_irqdispatch(struct pt_regs *regs)
 {
-	int irq = 0, i;
+	int irq = 0;
 	static unsigned long intc0_req0 = 0;
 
 	intc0_req0 |= au_readl(IC0_REQ0INT);
@@ -534,43 +508,33 @@ void intc0_req0_irqdispatch(struct pt_re
 		return;
 	}
 
-	for (i=0; i<32; i++) {
-		if ((intc0_req0 & (1<<i))) {
-			intc0_req0 &= ~(1<<i);
-			do_IRQ(irq, regs);
-			break;
-		}
-		irq++;
-	}
+	irq = au_ffs(intc0_req0) - 1;
+	intc0_req0 &= ~(1<<irq);
+	do_IRQ(irq, regs);
 }
 
 
 void intc0_req1_irqdispatch(struct pt_regs *regs)
 {
-	int irq = 0, i;
+	int irq = 0;
 	static unsigned long intc0_req1 = 0;
 
-	intc0_req1 = au_readl(IC0_REQ1INT);
+	intc0_req1 |= au_readl(IC0_REQ1INT);
 
 	if (!intc0_req1) return;
 
-	for (i=0; i<32; i++) {
-		if ((intc0_req1 & (1<<i))) {
-			intc0_req1 &= ~(1<<i);
+	irq = au_ffs(intc0_req1) - 1;
+	intc0_req1 &= ~(1<<irq);
 #ifdef CONFIG_PM
-			if (i == AU1000_TOY_MATCH2_INT) {
-				mask_and_ack_rise_edge_irq(irq);
-				counter0_irq(irq, NULL, regs);
-				local_enable_irq(irq);
-			}
-			else
+	if (irq == AU1000_TOY_MATCH2_INT) {
+		mask_and_ack_rise_edge_irq(irq);
+		counter0_irq(irq, NULL, regs);
+		local_enable_irq(irq);
+	}
+	else
 #endif
-			{
-				do_IRQ(irq, regs);
-			}
-			break;
-		}
-		irq++;
+	{
+		do_IRQ(irq, regs);
 	}
 }
 
@@ -581,51 +545,114 @@ void intc0_req1_irqdispatch(struct pt_re
  */
 void intc1_req0_irqdispatch(struct pt_regs *regs)
 {
-	int irq = 0, i;
+	int irq = 0;
 	static unsigned long intc1_req0 = 0;
 
 	intc1_req0 |= au_readl(IC1_REQ0INT);
 
 	if (!intc1_req0) return;
 
-#if defined(CONFIG_MIPS_PB1000) && defined(DEBUG_IRQ)
-	au_writel(1, CPLD_AUX0); /* debug led 0 */
-#endif
-	for (i=0; i<32; i++) {
-		if ((intc1_req0 & (1<<i))) {
-			intc1_req0 &= ~(1<<i);
-#if defined(CONFIG_MIPS_PB1000) && defined(DEBUG_IRQ)
-			au_writel(2, CPLD_AUX0); /* turn on debug led 1  */
-			do_IRQ(irq+32, regs);
-			au_writel(0, CPLD_AUX0); /* turn off debug led 1 */
-#else
-			do_IRQ(irq+32, regs);
-#endif
-			break;
-		}
-		irq++;
-	}
-#if defined(CONFIG_MIPS_PB1000) && defined(DEBUG_IRQ)
-	au_writel(0, CPLD_AUX0);
-#endif
+	irq = au_ffs(intc1_req0) - 1;
+	intc1_req0 &= ~(1<<irq);
+	irq += 32;
+	do_IRQ(irq, regs);
 }
 
 
 void intc1_req1_irqdispatch(struct pt_regs *regs)
 {
-	int irq = 0, i;
+	int irq = 0;
 	static unsigned long intc1_req1 = 0;
 
 	intc1_req1 |= au_readl(IC1_REQ1INT);
 
 	if (!intc1_req1) return;
 
-	for (i=0; i<32; i++) {
-		if ((intc1_req1 & (1<<i))) {
-			intc1_req1 &= ~(1<<i);
-			do_IRQ(irq+32, regs);
-			break;
-		}
-		irq++;
-	}
+	irq = au_ffs(intc1_req1) - 1;
+	intc1_req1 &= ~(1<<irq);
+	irq += 32;
+	do_IRQ(irq, regs);
+}
+
+#ifdef CONFIG_PM
+
+/* Save/restore the interrupt controller state.
+ * Called from the save/restore core registers as part of the
+ * au_sleep function in power.c.....maybe I should just pm_register()
+ * them instead?
+ */
+static uint	sleep_intctl_config0[2];
+static uint	sleep_intctl_config1[2];
+static uint	sleep_intctl_config2[2];
+static uint	sleep_intctl_src[2];
+static uint	sleep_intctl_assign[2];
+static uint	sleep_intctl_wake[2];
+static uint	sleep_intctl_mask[2];
+
+void
+save_au1xxx_intctl(void)
+{
+	sleep_intctl_config0[0] = au_readl(IC0_CFG0RD);
+	sleep_intctl_config1[0] = au_readl(IC0_CFG1RD);
+	sleep_intctl_config2[0] = au_readl(IC0_CFG2RD);
+	sleep_intctl_src[0] = au_readl(IC0_SRCRD);
+	sleep_intctl_assign[0] = au_readl(IC0_ASSIGNRD);
+	sleep_intctl_wake[0] = au_readl(IC0_WAKERD);
+	sleep_intctl_mask[0] = au_readl(IC0_MASKRD);
+
+	sleep_intctl_config0[1] = au_readl(IC1_CFG0RD);
+	sleep_intctl_config1[1] = au_readl(IC1_CFG1RD);
+	sleep_intctl_config2[1] = au_readl(IC1_CFG2RD);
+	sleep_intctl_src[1] = au_readl(IC1_SRCRD);
+	sleep_intctl_assign[1] = au_readl(IC1_ASSIGNRD);
+	sleep_intctl_wake[1] = au_readl(IC1_WAKERD);
+	sleep_intctl_mask[1] = au_readl(IC1_MASKRD);
+}
+
+/* For most restore operations, we clear the entire register and
+ * then set the bits we found during the save.
+ */
+void
+restore_au1xxx_intctl(void)
+{
+	au_writel(0xffffffff, IC0_MASKCLR); au_sync();
+
+	au_writel(0xffffffff, IC0_CFG0CLR); au_sync();
+	au_writel(sleep_intctl_config0[0], IC0_CFG0SET); au_sync();
+	au_writel(0xffffffff, IC0_CFG1CLR); au_sync();
+	au_writel(sleep_intctl_config1[0], IC0_CFG1SET); au_sync();
+	au_writel(0xffffffff, IC0_CFG2CLR); au_sync();
+	au_writel(sleep_intctl_config2[0], IC0_CFG2SET); au_sync();
+	au_writel(0xffffffff, IC0_SRCCLR); au_sync();
+	au_writel(sleep_intctl_src[0], IC0_SRCSET); au_sync();
+	au_writel(0xffffffff, IC0_ASSIGNCLR); au_sync();
+	au_writel(sleep_intctl_assign[0], IC0_ASSIGNSET); au_sync();
+	au_writel(0xffffffff, IC0_WAKECLR); au_sync();
+	au_writel(sleep_intctl_wake[0], IC0_WAKESET); au_sync();
+	au_writel(0xffffffff, IC0_RISINGCLR); au_sync();
+	au_writel(0xffffffff, IC0_FALLINGCLR); au_sync();
+	au_writel(0x00000000, IC0_TESTBIT); au_sync();
+
+	au_writel(0xffffffff, IC1_MASKCLR); au_sync();
+
+	au_writel(0xffffffff, IC1_CFG0CLR); au_sync();
+	au_writel(sleep_intctl_config0[1], IC1_CFG0SET); au_sync();
+	au_writel(0xffffffff, IC1_CFG1CLR); au_sync();
+	au_writel(sleep_intctl_config1[1], IC1_CFG1SET); au_sync();
+	au_writel(0xffffffff, IC1_CFG2CLR); au_sync();
+	au_writel(sleep_intctl_config2[1], IC1_CFG2SET); au_sync();
+	au_writel(0xffffffff, IC1_SRCCLR); au_sync();
+	au_writel(sleep_intctl_src[1], IC1_SRCSET); au_sync();
+	au_writel(0xffffffff, IC1_ASSIGNCLR); au_sync();
+	au_writel(sleep_intctl_assign[1], IC1_ASSIGNSET); au_sync();
+	au_writel(0xffffffff, IC1_WAKECLR); au_sync();
+	au_writel(sleep_intctl_wake[1], IC1_WAKESET); au_sync();
+	au_writel(0xffffffff, IC1_RISINGCLR); au_sync();
+	au_writel(0xffffffff, IC1_FALLINGCLR); au_sync();
+	au_writel(0x00000000, IC1_TESTBIT); au_sync();
+
+	au_writel(sleep_intctl_mask[1], IC1_MASKSET); au_sync();
+
+	au_writel(sleep_intctl_mask[0], IC0_MASKSET); au_sync();
 }
+#endif /* CONFIG_PM */
--- diff/arch/mips/au1000/common/power.c	2003-07-08 09:55:17.000000000 +0100
+++ source/arch/mips/au1000/common/power.c	2004-02-23 13:56:38.000000000 +0000
@@ -39,7 +39,9 @@
 #include <asm/uaccess.h>
 #include <asm/io.h>
 #include <asm/system.h>
-#include <asm/au1000.h>
+#include <asm/mach-au1x00/au1000.h>
+
+#ifdef CONFIG_PM
 
 #define DEBUG 1
 #ifdef DEBUG
@@ -48,13 +50,12 @@
 #  define DPRINTK(fmt, args...)
 #endif
 
-extern void au1k_wait(void);
 static void calibrate_delay(void);
 
-extern void set_au1000_speed(unsigned int new_freq);
-extern unsigned int get_au1000_speed(void);
-extern unsigned long get_au1000_uart_baud_base(void);
-extern void set_au1000_uart_baud_base(unsigned long new_baud_base);
+extern void set_au1x00_speed(unsigned int new_freq);
+extern unsigned int get_au1x00_speed(void);
+extern unsigned long get_au1x00_uart_baud_base(void);
+extern void set_au1x00_uart_baud_base(unsigned long new_baud_base);
 extern unsigned long save_local_and_disable(int controller);
 extern void restore_local_and_enable(int controller, unsigned long mask);
 extern void local_enable_irq(unsigned int irq_nr);
@@ -64,10 +65,144 @@ extern void local_enable_irq(unsigned in
 #define	ACPI_S1_SLP_TYP 19
 #define	ACPI_SLEEP 21
 
-#ifdef CONFIG_PM
 
 static spinlock_t pm_lock = SPIN_LOCK_UNLOCKED;
 
+/* We need to save/restore a bunch of core registers that are
+ * either volatile or reset to some state across a processor sleep.
+ * If reading a register doesn't provide a proper result for a
+ * later restore, we have to provide a function for loading that
+ * register and save a copy.
+ *
+ * We only have to save/restore registers that aren't otherwise
+ * done as part of a driver pm_* function.
+ */
+static uint	sleep_aux_pll_cntrl;
+static uint	sleep_cpu_pll_cntrl;
+static uint	sleep_pin_function;
+static uint	sleep_uart0_inten;
+static uint	sleep_uart0_fifoctl;
+static uint	sleep_uart0_linectl;
+static uint	sleep_uart0_clkdiv;
+static uint	sleep_uart0_enable;
+static uint	sleep_usbhost_enable;
+static uint	sleep_usbdev_enable;
+static uint	sleep_static_memctlr[4][3];
+
+/* Define this to cause the value you write to /proc/sys/pm/sleep to
+ * set the TOY timer for the amount of time you want to sleep.
+ * This is done mainly for testing, but may be useful in other cases.
+ * The value is number of 32KHz ticks to sleep.
+ */
+#define SLEEP_TEST_TIMEOUT 1
+#ifdef SLEEP_TEST_TIMEOUT
+static	int	sleep_ticks;
+void wakeup_counter0_set(int ticks);
+#endif
+
+static void
+save_core_regs(void)
+{
+	extern void save_au1xxx_intctl(void);
+	extern void pm_eth0_shutdown(void);
+
+	/* Do the serial ports.....these really should be a pm_*
+	 * registered function by the driver......but of course the
+	 * standard serial driver doesn't understand our Au1xxx
+	 * unique registers.
+	 */
+	sleep_uart0_inten = au_readl(UART0_ADDR + UART_IER);
+	sleep_uart0_fifoctl = au_readl(UART0_ADDR + UART_FCR);
+	sleep_uart0_linectl = au_readl(UART0_ADDR + UART_LCR);
+	sleep_uart0_clkdiv = au_readl(UART0_ADDR + UART_CLK);
+	sleep_uart0_enable = au_readl(UART0_ADDR + UART_MOD_CNTRL);
+
+	/* Shutdown USB host/device.
+	*/
+	sleep_usbhost_enable = au_readl(USB_HOST_CONFIG);
+
+	/* There appears to be some undocumented reset register....
+	*/
+	au_writel(0, 0xb0100004); au_sync();
+	au_writel(0, USB_HOST_CONFIG); au_sync();
+
+	sleep_usbdev_enable = au_readl(USBD_ENABLE);
+	au_writel(0, USBD_ENABLE); au_sync();
+
+	/* Save interrupt controller state.
+	*/
+	save_au1xxx_intctl();
+
+	/* Clocks and PLLs.
+	*/
+	sleep_aux_pll_cntrl = au_readl(SYS_AUXPLL);
+
+	/* We don't really need to do this one, but unless we
+	 * write it again it won't have a valid value if we
+	 * happen to read it.
+	 */
+	sleep_cpu_pll_cntrl = au_readl(SYS_CPUPLL);
+
+	sleep_pin_function = au_readl(SYS_PINFUNC);
+
+	/* Save the static memory controller configuration.
+	*/
+	sleep_static_memctlr[0][0] = au_readl(MEM_STCFG0);
+	sleep_static_memctlr[0][1] = au_readl(MEM_STTIME0);
+	sleep_static_memctlr[0][2] = au_readl(MEM_STADDR0);
+	sleep_static_memctlr[1][0] = au_readl(MEM_STCFG1);
+	sleep_static_memctlr[1][1] = au_readl(MEM_STTIME1);
+	sleep_static_memctlr[1][2] = au_readl(MEM_STADDR1);
+	sleep_static_memctlr[2][0] = au_readl(MEM_STCFG2);
+	sleep_static_memctlr[2][1] = au_readl(MEM_STTIME2);
+	sleep_static_memctlr[2][2] = au_readl(MEM_STADDR2);
+	sleep_static_memctlr[3][0] = au_readl(MEM_STCFG3);
+	sleep_static_memctlr[3][1] = au_readl(MEM_STTIME3);
+	sleep_static_memctlr[3][2] = au_readl(MEM_STADDR3);
+}
+
+static void
+restore_core_regs(void)
+{
+	extern void restore_au1xxx_intctl(void);
+	extern void wakeup_counter0_adjust(void);
+
+	au_writel(sleep_aux_pll_cntrl, SYS_AUXPLL); au_sync();
+	au_writel(sleep_cpu_pll_cntrl, SYS_CPUPLL); au_sync();
+	au_writel(sleep_pin_function, SYS_PINFUNC); au_sync();
+
+	/* Restore the static memory controller configuration.
+	*/
+	au_writel(sleep_static_memctlr[0][0], MEM_STCFG0);
+	au_writel(sleep_static_memctlr[0][1], MEM_STTIME0);
+	au_writel(sleep_static_memctlr[0][2], MEM_STADDR0);
+	au_writel(sleep_static_memctlr[1][0], MEM_STCFG1);
+	au_writel(sleep_static_memctlr[1][1], MEM_STTIME1);
+	au_writel(sleep_static_memctlr[1][2], MEM_STADDR1);
+	au_writel(sleep_static_memctlr[2][0], MEM_STCFG2);
+	au_writel(sleep_static_memctlr[2][1], MEM_STTIME2);
+	au_writel(sleep_static_memctlr[2][2], MEM_STADDR2);
+	au_writel(sleep_static_memctlr[3][0], MEM_STCFG3);
+	au_writel(sleep_static_memctlr[3][1], MEM_STTIME3);
+	au_writel(sleep_static_memctlr[3][2], MEM_STADDR3);
+
+	/* Enable the UART if it was enabled before sleep.
+	 * I guess I should define module control bits........
+	 */
+	if (sleep_uart0_enable & 0x02) {
+		au_writel(0, UART0_ADDR + UART_MOD_CNTRL); au_sync();
+		au_writel(1, UART0_ADDR + UART_MOD_CNTRL); au_sync();
+		au_writel(3, UART0_ADDR + UART_MOD_CNTRL); au_sync();
+		au_writel(sleep_uart0_inten, UART0_ADDR + UART_IER); au_sync();
+		au_writel(sleep_uart0_fifoctl, UART0_ADDR + UART_FCR); au_sync();
+		au_writel(sleep_uart0_linectl, UART0_ADDR + UART_LCR); au_sync();
+		au_writel(sleep_uart0_clkdiv, UART0_ADDR + UART_CLK); au_sync();
+	}
+
+	restore_au1xxx_intctl();
+	wakeup_counter0_adjust();
+}
+
 unsigned long suspend_mode;
 
 void wakeup_from_suspend(void)
@@ -78,33 +213,48 @@ void wakeup_from_suspend(void)
 int au_sleep(void)
 {
 	unsigned long wakeup, flags;
+	extern	void	save_and_sleep(void);
+
 	spin_lock_irqsave(&pm_lock,flags);
 
+	save_core_regs();
+
 	flush_cache_all();
-	/* pin 6 is gpio */
+
+	/** The code below is all system dependent and we should probably
+	 ** have a function call out of here to set this up.  You need
+	 ** to configure the GPIO or timer interrupts that will bring
+	 ** you out of sleep.
+	 ** For testing, the TOY counter wakeup is useful.
+	 **/
+
+#if 0
 	au_writel(au_readl(SYS_PINSTATERD) & ~(1 << 11), SYS_PINSTATERD);
 
 	/* gpio 6 can cause a wake up event */
 	wakeup = au_readl(SYS_WAKEMSK);
 	wakeup &= ~(1 << 8);	/* turn off match20 wakeup */
 	wakeup |= 1 << 6;	/* turn on gpio 6 wakeup   */
-	au_writel(wakeup, SYS_WAKEMSK);
-
+#else
+	/* For testing, allow match20 to wake us up.
+	*/
+#ifdef SLEEP_TEST_TIMEOUT
+	wakeup_counter0_set(sleep_ticks);
+#endif
+	wakeup = 1 << 8;	/* turn on match20 wakeup   */
+	wakeup = 0;
+#endif
 	au_writel(1, SYS_WAKESRC);	/* clear cause */
-	au_writel(1, SYS_SLPPWR);	/* prepare to sleep */
+	au_sync();
+	au_writel(wakeup, SYS_WAKEMSK);
+	au_sync();
 
-	__asm__("la $4, 1f\n\t"
-		"lui $5, 0xb190\n\t"
-		"ori $5, 0x18\n\t"
-		"sw $4, 0($5)\n\t"
-		"li $4, 1\n\t"
-		"lui $5, 0xb190\n\t"
-		"ori $5, 0x7c\n\t"
-		"sw $4, 0($5)\n\t" "sync\n\t" "1:\t\n\t" "nop\n\t");
+	save_and_sleep();
 
 	/* after a wakeup, the cpu vectors back to 0x1fc00000 so
 	 * it's up to the boot code to get us back here.
 	 */
+	restore_core_regs();
 	spin_unlock_irqrestore(&pm_lock, flags);
 	return 0;
 }
@@ -113,11 +263,27 @@ static int pm_do_sleep(ctl_table * ctl, 
 		       void *buffer, size_t * len)
 {
 	int retval = 0;
+#ifdef SLEEP_TEST_TIMEOUT
+#define TMPBUFLEN2 16
+	char buf[TMPBUFLEN2], *p;
+#endif
 
 	if (!write) {
 		*len = 0;
 	} else {
+#ifdef SLEEP_TEST_TIMEOUT
+		if (*len > TMPBUFLEN2 - 1) {
+			return -EFAULT;
+		}
+		if (copy_from_user(buf, buffer, *len)) {
+			return -EFAULT;
+		}
+		buf[*len] = 0;
+		p = buf;
+		sleep_ticks = simple_strtoul(p, &p, 0);
+#endif
 		retval = pm_send_all(PM_SUSPEND, (void *) 2);
+
 		if (retval)
 			return retval;
 
@@ -131,6 +297,7 @@ static int pm_do_suspend(ctl_table * ctl
 			 void *buffer, size_t * len)
 {
 	int retval = 0;
+	void	au1k_wait(void);
 
 	if (!write) {
 		*len = 0;
@@ -187,13 +354,13 @@ static int pm_do_freq(ctl_table * ctl, i
 			return -EFAULT;
 		}
 
-		old_baud_base = get_au1000_uart_baud_base();
-		old_cpu_freq = get_au1000_speed();
+		old_baud_base = get_au1x00_uart_baud_base();
+		old_cpu_freq = get_au1x00_speed();
 
 		new_cpu_freq = pll * 12 * 1000000;
 		new_baud_base = (new_cpu_freq / 4) / 16;
-		set_au1000_speed(new_cpu_freq);
-		set_au1000_uart_baud_base(new_baud_base);
+		set_au1x00_speed(new_cpu_freq);
+		set_au1x00_uart_baud_base(new_baud_base);
 
 		old_refresh = au_readl(MEM_SDREFCFG) & 0x1ffffff;
 		new_refresh =
@@ -323,10 +490,4 @@ static void calibrate_delay(void)
 			loops_per_jiffy &= ~loopbit;
 	}
 }
-
-void au1k_wait(void)
-{
-	__asm__("nop\n\t" "nop\n\t");
-}
-
 #endif				/* CONFIG_PM */
--- diff/arch/mips/au1000/common/prom.c	2003-07-08 09:55:17.000000000 +0100
+++ source/arch/mips/au1000/common/prom.c	2004-02-23 13:56:38.000000000 +0000
@@ -44,7 +44,6 @@
 
 /* #define DEBUG_CMDLINE */
 
-char arcs_cmdline[CL_SIZE];
 extern int prom_argc;
 extern char **prom_argv, **prom_envp;
 
@@ -153,6 +152,11 @@ int get_ethernet_addr(char *ethernet_add
 	return 0;
 }
 
-void prom_free_prom_memory (void) {}
+unsigned long __init prom_free_prom_memory(void)
+{
+	return 0;
+}
+
 EXPORT_SYMBOL(prom_getcmdline);
 EXPORT_SYMBOL(get_ethernet_addr);
+EXPORT_SYMBOL(str2eaddr);
--- diff/arch/mips/au1000/common/puts.c	2003-07-08 09:55:17.000000000 +0100
+++ source/arch/mips/au1000/common/puts.c	2004-02-23 13:56:38.000000000 +0000
@@ -29,7 +29,7 @@
  */
 
 #include <linux/types.h>
-#include <asm/au1000.h>
+#include <asm/mach-au1x00/au1000.h>
 
 #define SERIAL_BASE   UART_BASE
 #define SER_CMD       0x7
@@ -40,11 +40,11 @@
 #define SLOW_DOWN
 
 static const char digits[16] = "0123456789abcdef";
-static volatile unsigned long * const com1 = (unsigned char *)SERIAL_BASE;
+static volatile unsigned long * const com1 = (unsigned long *)SERIAL_BASE;
 
 
 #ifdef SLOW_DOWN
-static inline void slow_down()
+static inline void slow_down(void)
 {
     int k;
     for (k=0; k<10000; k++);
--- diff/arch/mips/au1000/common/reset.c	2003-07-08 09:55:17.000000000 +0100
+++ source/arch/mips/au1000/common/reset.c	2004-02-23 13:56:38.000000000 +0000
@@ -35,9 +35,10 @@
 #include <asm/processor.h>
 #include <asm/reboot.h>
 #include <asm/system.h>
-#include <asm/au1000.h>
+#include <asm/mach-au1x00/au1000.h>
 
 extern int au_sleep(void);
+extern void (*flush_cache_all)(void);
 
 void au1000_restart(char *command)
 {
@@ -54,6 +55,10 @@ void au1000_restart(char *command)
 		au_writel(0x00, 0xb017fffc); /* usbh_enable */
 		au_writel(0x00, 0xb0200058); /* usbd_enable */
 		au_writel(0x00, 0xb0300040); /* ir_enable */
+		au_writel(0x00, 0xb4004104); /* mac dma */
+		au_writel(0x00, 0xb4004114); /* mac dma */
+		au_writel(0x00, 0xb4004124); /* mac dma */
+		au_writel(0x00, 0xb4004134); /* mac dma */
 		au_writel(0x00, 0xb0520000); /* macen0 */
 		au_writel(0x00, 0xb0520004); /* macen1 */
 		au_writel(0x00, 0xb1000008); /* i2s_enable  */
@@ -66,6 +71,8 @@ void au1000_restart(char *command)
 		au_writel(0x00, 0xb1900020); /* sys_freqctrl0 */
 		au_writel(0x00, 0xb1900024); /* sys_freqctrl1 */
 		au_writel(0x00, 0xb1900028); /* sys_clksrc */
+		au_writel(0x10, 0xb1900060); /* sys_cpupll */
+		au_writel(0x00, 0xb1900064); /* sys_auxpll */
 		au_writel(0x00, 0xb1900100); /* sys_pininputen */
 		break;
 	case 0x01000000: /* Au1500 */
@@ -74,6 +81,10 @@ void au1000_restart(char *command)
 		asm("sync");
 		au_writel(0x00, 0xb017fffc); /* usbh_enable */
 		au_writel(0x00, 0xb0200058); /* usbd_enable */
+		au_writel(0x00, 0xb4004104); /* mac dma */
+		au_writel(0x00, 0xb4004114); /* mac dma */
+		au_writel(0x00, 0xb4004124); /* mac dma */
+		au_writel(0x00, 0xb4004134); /* mac dma */
 		au_writel(0x00, 0xb1520000); /* macen0 */
 		au_writel(0x00, 0xb1520004); /* macen1 */
 		au_writel(0x00, 0xb1100100); /* uart0_enable */
@@ -81,6 +92,8 @@ void au1000_restart(char *command)
 		au_writel(0x00, 0xb1900020); /* sys_freqctrl0 */
 		au_writel(0x00, 0xb1900024); /* sys_freqctrl1 */
 		au_writel(0x00, 0xb1900028); /* sys_clksrc */
+		au_writel(0x10, 0xb1900060); /* sys_cpupll */
+		au_writel(0x00, 0xb1900064); /* sys_auxpll */
 		au_writel(0x00, 0xb1900100); /* sys_pininputen */
 		break;
 	case 0x02000000: /* Au1100 */
@@ -90,6 +103,10 @@ void au1000_restart(char *command)
 		au_writel(0x00, 0xb017fffc); /* usbh_enable */
 		au_writel(0x00, 0xb0200058); /* usbd_enable */
 		au_writel(0x00, 0xb0300040); /* ir_enable */
+		au_writel(0x00, 0xb4004104); /* mac dma */
+		au_writel(0x00, 0xb4004114); /* mac dma */
+		au_writel(0x00, 0xb4004124); /* mac dma */
+		au_writel(0x00, 0xb4004134); /* mac dma */
 		au_writel(0x00, 0xb0520000); /* macen0 */
 		au_writel(0x00, 0xb1000008); /* i2s_enable  */
 		au_writel(0x00, 0xb1100100); /* uart0_enable */
@@ -100,6 +117,8 @@ void au1000_restart(char *command)
 		au_writel(0x00, 0xb1900020); /* sys_freqctrl0 */
 		au_writel(0x00, 0xb1900024); /* sys_freqctrl1 */
 		au_writel(0x00, 0xb1900028); /* sys_clksrc */
+		au_writel(0x10, 0xb1900060); /* sys_cpupll */
+		au_writel(0x00, 0xb1900064); /* sys_auxpll */
 		au_writel(0x00, 0xb1900100); /* sys_pininputen */
 		break;
 
--- diff/arch/mips/au1000/common/time.c	2003-08-20 14:16:25.000000000 +0100
+++ source/arch/mips/au1000/common/time.c	2004-02-23 13:56:38.000000000 +0000
@@ -1,10 +1,13 @@
 /*
+ *
  * Copyright (C) 2001 MontaVista Software, ppopov@mvista.com
  * Copied and modified Carsten Langgaard's time.c
  *
  * Carsten Langgaard, carstenl@mips.com
  * Copyright (C) 1999,2000 MIPS Technologies, Inc.  All rights reserved.
  *
+ * ########################################################################
+ *
  *  This program is free software; you can distribute it and/or modify it
  *  under the terms of the GNU General Public License (Version 2) as
  *  published by the Free Software Foundation.
@@ -18,13 +21,21 @@
  *  with this program; if not, write to the Free Software Foundation, Inc.,
  *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
  *
+ * ########################################################################
+ *
  * Setting up the clock on the MIPS boards.
+ *
+ * Update.  Always configure the kernel with CONFIG_NEW_TIME_C.  This
+ * will use the user interface gettimeofday() functions from the
+ * arch/mips/kernel/time.c, and we provide the clock interrupt processing
+ * and the timer offset compute functions.  If CONFIG_PM is selected,
+ * we also ensure the 32KHz timer is available.   -- Dan
  */
+
 #include <linux/types.h>
 #include <linux/config.h>
 #include <linux/init.h>
 #include <linux/kernel_stat.h>
-#include <linux/time.h>
 #include <linux/sched.h>
 #include <linux/spinlock.h>
 
@@ -33,18 +44,20 @@
 #include <asm/time.h>
 #include <asm/hardirq.h>
 #include <asm/div64.h>
-#include <asm/au1000.h>
+#include <asm/mach-au1x00/au1000.h>
 
 #include <linux/mc146818rtc.h>
 #include <linux/timex.h>
 
 extern void startup_match20_interrupt(void);
+extern void do_softirq(void);
 extern volatile unsigned long wall_jiffies;
 unsigned long missed_heart_beats = 0;
 
 static unsigned long r4k_offset; /* Amount to increment compare reg each time */
 static unsigned long r4k_cur;    /* What counter should be at next timer irq */
-extern unsigned int mips_counter_frequency;
+int	no_au1xxx_32khz;
+void	(*au1k_wait_ptr)(void);
 
 /* Cycle counter value at the previous timer interrupt.. */
 static unsigned int timerhi = 0, timerlo = 0;
@@ -72,17 +85,10 @@ void mips_timer_interrupt(struct pt_regs
 {
 	int irq = 63;
 	unsigned long count;
-	int cpu = smp_processor_id();
 
 	irq_enter();
 	kstat_this_cpu.irqs[irq]++;
 
-#ifdef CONFIG_PM
-	printk(KERN_ERR "Unexpected CP0 interrupt\n");
-	regs->cp0_status &= ~IE_IRQ5; /* disable CP0 interrupt */
-	return;
-#endif
-
 	if (r4k_offset == 0)
 		goto null;
 
@@ -100,7 +106,6 @@ void mips_timer_interrupt(struct pt_regs
 	         - r4k_cur) < 0x7fffffff);
 
 	irq_exit();
-
 	return;
 
 null:
@@ -114,7 +119,7 @@ void counter0_irq(int irq, void *dev_id,
 	int time_elapsed;
 	static int jiffie_drift = 0;
 
-	kstat_this_cpu.irqs[irq]++;
+	kstat.irqs[0][irq]++;
 	if (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_M20) {
 		/* should never happen! */
 		printk(KERN_WARNING "counter 0 w status eror\n");
@@ -150,119 +155,148 @@ void counter0_irq(int irq, void *dev_id,
 		do_timer(regs); /* increment jiffies by one */
 	}
 }
-#endif
 
-/*
- * Figure out the r4k offset, the amount to increment the compare
- * register for each time tick.
- * Use the Programmable Counter 1 to do this.
+/* When we wakeup from sleep, we have to "catch up" on all of the
+ * timer ticks we have missed.
  */
-unsigned long cal_r4koff(void)
+void
+wakeup_counter0_adjust(void)
 {
-	unsigned long count;
-	unsigned long cpu_speed;
-	unsigned long start, end;
-	unsigned long counter;
-	int trim_divide = 16;
-	unsigned long flags;
-
-	spin_lock_irqsave(&time_lock, flags);
+	unsigned long pc0;
+	int time_elapsed;
 
-	counter = au_readl(SYS_COUNTER_CNTRL);
-	au_writel(counter | SYS_CNTRL_EN1, SYS_COUNTER_CNTRL);
+	pc0 = au_readl(SYS_TOYREAD);
+	if (pc0 < last_match20) {
+		/* counter overflowed */
+		time_elapsed = (0xffffffff - last_match20) + pc0;
+	}
+	else {
+		time_elapsed = pc0 - last_match20;
+	}
 
-	while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_T1S);
-	au_writel(trim_divide-1, SYS_RTCTRIM); /* RTC now ticks at 32.768/16 kHz */
-	while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_T1S);
-
-	while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_C1S);
-	au_writel (0, SYS_TOYWRITE);
-	while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_C1S);
-
-	start = au_readl(SYS_RTCREAD);
-	start += 2;
-	/* wait for the beginning of a new tick */
-	while (au_readl(SYS_RTCREAD) < start);
-
-	/* Start r4k counter. */
-	write_c0_count(0);
-	end = start + (32768 / trim_divide)/2; /* wait 0.5 seconds */
+	while (time_elapsed > 0) {
+		time_elapsed -= MATCH20_INC;
+		last_match20 += MATCH20_INC;
+	}
 
-	while (end > au_readl(SYS_RTCREAD));
+	last_pc0 = pc0;
+	au_writel(last_match20 + MATCH20_INC, SYS_TOYMATCH2);
+	au_sync();
 
-	count = read_c0_count();
-	cpu_speed = count * 2;
-	mips_counter_frequency = count;
-	set_au1x00_uart_baud_base(((cpu_speed) / 4) / 16);
-	spin_unlock_irqrestore(&time_lock, flags);
-	return (cpu_speed / HZ);
 }
 
-void __init au1x_time_init(void)
+/* This is just for debugging to set the timer for a sleep delay.
+*/
+void
+wakeup_counter0_set(int ticks)
 {
-        unsigned int est_freq;
-
-	printk("calculating r4koff... ");
-	r4k_offset = cal_r4koff();
-	printk("%08lx(%d)\n", r4k_offset, (int) r4k_offset);
+	unsigned long pc0;
 
-	//est_freq = 2*r4k_offset*HZ;
-	est_freq = r4k_offset*HZ;
-	est_freq += 5000;    /* round */
-	est_freq -= est_freq%10000;
-	printk("CPU frequency %d.%02d MHz\n", est_freq/1000000,
-	       (est_freq%1000000)*100/1000000);
- 	set_au1x00_speed(est_freq);
- 	set_au1x00_lcd_clock(); // program the LCD clock
-	r4k_cur = (read_c0_count() + r4k_offset);
+	pc0 = au_readl(SYS_TOYREAD);
+	last_pc0 = pc0;
+	au_writel(last_match20 + (MATCH20_INC * ticks), SYS_TOYMATCH2);
+	au_sync();
+}
+#endif
 
-	write_c0_compare(r4k_cur);
+/* I haven't found anyone that doesn't use a 12 MHz source clock,
+ * but just in case.....
+ */
+#ifdef CONFIG_AU1000_SRC_CLK
+#define AU1000_SRC_CLK	CONFIG_AU1000_SRC_CLK
+#else
+#define AU1000_SRC_CLK	12000000
+#endif
 
-	/* no RTC on the pb1000 */
-	xtime.tv_sec = 0;
-	//xtime.tv_usec = 0;
+/*
+ * We read the real processor speed from the PLL.  This is important
+ * because it is more accurate than computing it from the 32KHz
+ * counter, if it exists.  If we don't have an accurate processor
+ * speed, all of the peripherals that derive their clocks based on
+ * this advertised speed will introduce error and sometimes not work
+ * properly.  This function is futher convoluted to still allow configurations
+ * to do that in case they have really, really old silicon with a
+ * write-only PLL register, that we need the 32KHz when power management
+ * "wait" is enabled, and we need to detect if the 32KHz isn't present
+ * but requested......got it? :-)		-- Dan
+ */
+unsigned long cal_r4koff(void)
+{
+	unsigned long count;
+	unsigned long cpu_speed;
+	unsigned long flags;
+	unsigned long counter;
 
-#ifdef CONFIG_PM
-	/*
-	 * setup counter 0, since it keeps ticking after a
-	 * 'wait' instruction has been executed. The CP0 timer and
-	 * counter 1 do NOT continue running after 'wait'
-	 *
-	 * It's too early to call request_irq() here, so we handle
-	 * counter 0 interrupt as a special irq and it doesn't show
-	 * up under /proc/interrupts.
-	 */
-	while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_C0S);
-	au_writel(0, SYS_TOYWRITE);
-	while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_C0S);
+	spin_lock_irqsave(&time_lock, flags);
 
-	au_writel(au_readl(SYS_WAKEMSK) | (1<<8), SYS_WAKEMSK);
-	au_writel(~0, SYS_WAKESRC);
-	au_sync();
-	while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_M20);
+	/* Power management cares if we don't have a 32KHz counter.
+	*/
+	no_au1xxx_32khz = 0;
+	counter = au_readl(SYS_COUNTER_CNTRL);
+	if (counter & SYS_CNTRL_E0) {
+		int trim_divide = 16;
 
-	/* setup match20 to interrupt once every 10ms */
-	last_pc0 = last_match20 = au_readl(SYS_TOYREAD);
-	au_writel(last_match20 + MATCH20_INC, SYS_TOYMATCH2);
-	au_sync();
-	while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_M20);
-	startup_match20_interrupt();
-#endif
+		au_writel(counter | SYS_CNTRL_EN1, SYS_COUNTER_CNTRL);
 
-	//set_c0_status(ALLINTS);
-	au_sync();
-}
+		while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_T1S);
+		/* RTC now ticks at 32.768/16 kHz */
+		au_writel(trim_divide-1, SYS_RTCTRIM);
+		while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_T1S);
+
+		while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_C1S);
+		au_writel (0, SYS_TOYWRITE);
+		while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_C1S);
+
+#if defined(CONFIG_AU1000_USE32K)
+		{
+			unsigned long start, end;
+
+			start = au_readl(SYS_RTCREAD);
+			start += 2;
+			/* wait for the beginning of a new tick
+			*/
+			while (au_readl(SYS_RTCREAD) < start);
+
+			/* Start r4k counter.
+			*/
+			write_c0_count(0);
+
+			/* Wait 0.5 seconds.
+			*/
+			end = start + (32768 / trim_divide)/2;
 
-void __init au1x_timer_setup(struct irqaction *irq)
-{
+			while (end > au_readl(SYS_RTCREAD));
 
+			count = read_c0_count();
+			cpu_speed = count * 2;
+		}
+#else
+		cpu_speed = (au_readl(SYS_CPUPLL) & 0x0000003f) * 
+			AU1000_SRC_CLK;
+		count = cpu_speed / 2;
+#endif
+	}
+	else {
+		/* The 32KHz oscillator isn't running, so assume there
+		 * isn't one and grab the processor speed from the PLL.
+		 * NOTE: some old silicon doesn't allow reading the PLL.
+		 */
+		cpu_speed = (au_readl(SYS_CPUPLL) & 0x0000003f) * AU1000_SRC_CLK;
+		count = cpu_speed / 2;
+		no_au1xxx_32khz = 1;
+	}
+	mips_hpt_frequency = count;
+	// Equation: Baudrate = CPU / (SD * 2 * CLKDIV * 16)
+	set_au1x00_uart_baud_base(cpu_speed / (2 * ((int)(au_readl(SYS_POWERCTRL)&0x03) + 2) * 16));
+	spin_unlock_irqrestore(&time_lock, flags);
+	return (cpu_speed / HZ);
 }
 
 /* This is for machines which generate the exact clock. */
 #define USECS_PER_JIFFY (1000000/HZ)
 #define USECS_PER_JIFFY_FRAC (0x100000000*1000000/HZ&0xffffffff)
 
-#ifndef CONFIG_PM
+
 static unsigned long
 div64_32(unsigned long v1, unsigned long v2, unsigned long v3)
 {
@@ -270,30 +304,9 @@ div64_32(unsigned long v1, unsigned long
 	do_div64_32(r0, v1, v2, v3);
 	return r0;
 }
-#endif
 
-static unsigned long do_fast_gettimeoffset(void)
+static unsigned long do_fast_cp0_gettimeoffset(void)
 {
-#ifdef CONFIG_PM
-	unsigned long pc0;
-	unsigned long offset;
-
-	pc0 = au_readl(SYS_TOYREAD);
-	if (pc0 < last_pc0) {
-		offset = 0xffffffff - last_pc0 + pc0;
-		printk("offset over: %x\n", (unsigned)offset);
-	}
-	else {
-		offset = (unsigned long)(((pc0 - last_pc0) * 305) / 10);
-	}
-	if ((pc0-last_pc0) > 2*MATCH20_INC) {
-		printk("huge offset %x, last_pc0 %x last_match20 %x pc0 %x\n",
-				(unsigned)offset, (unsigned)last_pc0,
-				(unsigned)last_match20, (unsigned)pc0);
-	}
-	au_sync();
-	return offset;
-#else
 	u32 count;
 	unsigned long res, tmp;
 	unsigned long r0;
@@ -334,12 +347,118 @@ static unsigned long do_fast_gettimeoffs
 		 "r" (quotient));
 
 	/*
- 	 * Due to possible jiffies inconsistencies, we need to check
+ 	 * Due to possible jiffies inconsistencies, we need to check 
 	 * the result so that we'll get a timer that is monotonic.
 	 */
 	if (res >= USECS_PER_JIFFY)
 		res = USECS_PER_JIFFY-1;
 
 	return res;
+}
+
+#ifdef CONFIG_PM
+static unsigned long do_fast_pm_gettimeoffset(void)
+{
+	unsigned long pc0;
+	unsigned long offset;
+
+	pc0 = au_readl(SYS_TOYREAD);
+	au_sync();
+	offset = pc0 - last_pc0;
+	if (offset > 2*MATCH20_INC) {
+		printk("huge offset %x, last_pc0 %x last_match20 %x pc0 %x\n", 
+				(unsigned)offset, (unsigned)last_pc0, 
+				(unsigned)last_match20, (unsigned)pc0);
+	}
+	offset = (unsigned long)((offset * 305) / 10);
+	return offset;
+}
+#endif
+
+void au1xxx_timer_setup(struct irqaction *irq)
+{
+        unsigned int est_freq;
+	extern unsigned long (*do_gettimeoffset)(void);
+	extern void au1k_wait(void);
+
+	printk("calculating r4koff... ");
+	r4k_offset = cal_r4koff();
+	printk("%08lx(%d)\n", r4k_offset, (int) r4k_offset);
+
+	//est_freq = 2*r4k_offset*HZ;	
+	est_freq = r4k_offset*HZ;	
+	est_freq += 5000;    /* round */
+	est_freq -= est_freq%10000;
+	printk("CPU frequency %d.%02d MHz\n", est_freq/1000000, 
+	       (est_freq%1000000)*100/1000000);
+ 	set_au1x00_speed(est_freq);
+ 	set_au1x00_lcd_clock(); // program the LCD clock
+
+	r4k_cur = (read_c0_count() + r4k_offset);
+	write_c0_compare(r4k_cur);
+
+	/* no RTC on the pb1000 */
+	xtime.tv_sec = 0;
+	//xtime.tv_usec = 0;
+
+#ifdef CONFIG_PM
+	/*
+	 * setup counter 0, since it keeps ticking after a
+	 * 'wait' instruction has been executed. The CP0 timer and
+	 * counter 1 do NOT continue running after 'wait'
+	 *
+	 * It's too early to call request_irq() here, so we handle
+	 * counter 0 interrupt as a special irq and it doesn't show
+	 * up under /proc/interrupts.
+	 *
+	 * Check to ensure we really have a 32KHz oscillator before
+	 * we do this.
+	 */
+	if (no_au1xxx_32khz) {
+		unsigned int c0_status;
+
+		printk("WARNING: no 32KHz clock found.\n");
+		do_gettimeoffset = do_fast_cp0_gettimeoffset;
+
+		/* Ensure we get CPO_COUNTER interrupts.
+		*/
+		c0_status = read_c0_status();
+		c0_status |= IE_IRQ5;
+		write_c0_status(c0_status);
+	}
+	else {
+		while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_C0S);
+		au_writel(0, SYS_TOYWRITE);
+		while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_C0S);
+
+		au_writel(au_readl(SYS_WAKEMSK) | (1<<8), SYS_WAKEMSK);
+		au_writel(~0, SYS_WAKESRC);
+		au_sync();
+		while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_M20);
+
+		/* setup match20 to interrupt once every 10ms */
+		last_pc0 = last_match20 = au_readl(SYS_TOYREAD);
+		au_writel(last_match20 + MATCH20_INC, SYS_TOYMATCH2);
+		au_sync();
+		while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_M20);
+		startup_match20_interrupt();
+
+		do_gettimeoffset = do_fast_pm_gettimeoffset;
+
+		/* We can use the real 'wait' instruction.
+		*/
+		au1k_wait_ptr = au1k_wait;
+	}
+
+#else
+	/* We have to do this here instead of in timer_init because
+	 * the generic code in arch/mips/kernel/time.c will write
+	 * over our function pointer.
+	 */
+	do_gettimeoffset = do_fast_cp0_gettimeoffset;
 #endif
 }
+
+void __init au1xxx_time_init(void)
+{
+}
--- diff/arch/mips/au1000/common/usbdev.c	2003-07-08 09:55:17.000000000 +0100
+++ source/arch/mips/au1000/common/usbdev.c	2004-02-23 13:56:38.000000000 +0000
@@ -26,8 +26,6 @@
  *  with this program; if not, write  to the Free Software Foundation, Inc.,
  *  675 Mass Ave, Cambridge, MA 02139, USA.
  */
-
-#include <linux/config.h>
 #include <linux/kernel.h>
 #include <linux/ioport.h>
 #include <linux/sched.h>
--- diff/arch/mips/au1000/db1x00/Makefile	2003-07-08 09:55:17.000000000 +0100
+++ source/arch/mips/au1000/db1x00/Makefile	2004-02-23 13:56:38.000000000 +0000
@@ -3,18 +3,6 @@
 #  Author: MontaVista Software, Inc.
 #     	ppopov@mvista.com or source@mvista.com
 #
-# Makefile for the Alchemy Semiconductor PB1000 board.
-#
-# 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).
-#
-
-.S.s:
-	$(CPP) $(CFLAGS) $< -o $*.s
-.S.o:
-	$(CC) $(CFLAGS) -c $< -o $*.o
-
-O_TARGET := db1x00.o
+# Makefile for the Alchemy Semiconductor Db1x00 board.
 
-obj-y := init.o setup.o
+lib-y := init.o board_setup.o irqmap.o
--- diff/arch/mips/au1000/db1x00/init.c	2003-07-08 09:55:17.000000000 +0100
+++ source/arch/mips/au1000/db1x00/init.c	2004-02-23 13:56:38.000000000 +0000
@@ -1,5 +1,4 @@
 /*
- *
  * BRIEF MODULE DESCRIPTION
  *	PB1000 board setup
  *
@@ -37,7 +36,6 @@
 #include <linux/config.h>
 #include <linux/string.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 
 int prom_argc;
 char **prom_argv, **prom_envp;
@@ -46,28 +44,31 @@ extern char *prom_getenv(char *envname);
 
 const char *get_system_type(void)
 {
-	return "Alchemy Db1000";
+#ifdef CONFIG_MIPS_BOSPORUS
+	return "Alchemy Bosporus Gateway Reference";
+#else
+	return "Alchemy Db1x00";
+#endif
 }
 
-int __init prom_init(int argc, char **argv, char **envp, int *prom_vec)
+void __init prom_init(void)
 {
 	unsigned char *memsize_str;
 	unsigned long memsize;
 
-	prom_argc = argc;
-	prom_argv = argv;
-	prom_envp = envp;
+	prom_argc = fw_arg0;
+	prom_argv = (char **) fw_arg1;
+	prom_envp = (char **) fw_arg2;
 
 	mips_machgroup = MACH_GROUP_ALCHEMY;
 	mips_machtype = MACH_DB1000;	/* set the platform # */   
+
 	prom_init_cmdline();
 
 	memsize_str = prom_getenv("memsize");
-	if (!memsize_str) {
+	if (!memsize_str)
 		memsize = 0x04000000;
-	} else {
+	else
 		memsize = simple_strtol(memsize_str, NULL, 0);
-	}
 	add_memory_region(0, memsize, BOOT_MEM_RAM);
-	return 0;
 }
--- diff/arch/mips/au1000/pb1000/Makefile	2003-07-08 09:55:17.000000000 +0100
+++ source/arch/mips/au1000/pb1000/Makefile	2004-02-23 13:56:38.000000000 +0000
@@ -4,14 +4,5 @@
 #     	ppopov@mvista.com or source@mvista.com
 #
 # Makefile for the Alchemy Semiconductor PB1000 board.
-#
-# 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).
-#
-
-USE_STANDARD_AS_RULE := true
-
-O_TARGET := pb1000.o
 
-obj-y := init.o setup.o
+lib-y := init.o board_setup.o irqmap.o
--- diff/arch/mips/au1000/pb1000/init.c	2003-07-08 09:55:17.000000000 +0100
+++ source/arch/mips/au1000/pb1000/init.c	2004-02-23 13:56:38.000000000 +0000
@@ -1,5 +1,4 @@
 /*
- *
  * BRIEF MODULE DESCRIPTION
  *	PB1000 board setup
  *
@@ -35,7 +34,6 @@
 #include <asm/bootinfo.h>
 #include <linux/string.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 
 int prom_argc;
 char **prom_argv, **prom_envp;
@@ -47,14 +45,14 @@ const char *get_system_type(void)
 	return "Alchemy Pb1000";
 }
 
-int __init prom_init(int argc, char **argv, char **envp, int *prom_vec)
+void __init prom_init(void)
 {
 	unsigned char *memsize_str;
 	unsigned long memsize;
 
-	prom_argc = argc;
-	prom_argv = argv;
-	prom_envp = envp;
+	prom_argc = (int) fw_arg0;
+	prom_argv = (char **) fw_arg1;
+	prom_envp = (char **) fw_arg2;
 
 	mips_machgroup = MACH_GROUP_ALCHEMY;
 	mips_machtype = MACH_PB1000;
--- diff/arch/mips/au1000/pb1100/Makefile	2003-07-08 09:55:17.000000000 +0100
+++ source/arch/mips/au1000/pb1100/Makefile	2004-02-23 13:56:38.000000000 +0000
@@ -4,14 +4,5 @@
 #     	ppopov@mvista.com or source@mvista.com
 #
 # Makefile for the Alchemy Semiconductor Pb1100 board.
-#
-# 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).
-#
-
-USE_STANDARD_AS_RULE := true
-
-O_TARGET := pb1100.o
 
-obj-y := init.o setup.o
+lib-y := init.o board_setup.o irqmap.o
--- diff/arch/mips/au1000/pb1100/init.c	2003-07-08 09:55:17.000000000 +0100
+++ source/arch/mips/au1000/pb1100/init.c	2004-02-23 13:56:38.000000000 +0000
@@ -27,17 +27,14 @@
  *  with this program; if not, write  to the Free Software Foundation, Inc.,
  *  675 Mass Ave, Cambridge, MA 02139, USA.
  */
-
 #include <linux/init.h>
 #include <linux/mm.h>
 #include <linux/sched.h>
 #include <linux/bootmem.h>
 #include <asm/addrspace.h>
 #include <asm/bootinfo.h>
-#include <linux/config.h>
 #include <linux/string.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 
 int prom_argc;
 char **prom_argv, **prom_envp;
@@ -49,25 +46,25 @@ const char *get_system_type(void)
 	return "Alchemy Pb1100";
 }
 
-int __init prom_init(int argc, char **argv, char **envp, int *prom_vec)
+void __init prom_init(void)
 {
 	unsigned char *memsize_str;
 	unsigned long memsize;
 
-	prom_argc = argc;
-	prom_argv = argv;
-	prom_envp = envp;
+	prom_argc = fw_arg0;
+	prom_argv = (char **) fw_arg1;
+	prom_envp = (int *) fw_arg3;
 
 	mips_machgroup = MACH_GROUP_ALCHEMY;
 	mips_machtype = MACH_PB1100;
 
 	prom_init_cmdline();
+
 	memsize_str = prom_getenv("memsize");
-	if (!memsize_str) {
+	if (!memsize_str)
 		memsize = 0x04000000;
-	} else {
+	else
 		memsize = simple_strtol(memsize_str, NULL, 0);
-	}
+
 	add_memory_region(0, memsize, BOOT_MEM_RAM);
-	return 0;
 }
--- diff/arch/mips/au1000/pb1500/Makefile	2003-07-08 09:55:17.000000000 +0100
+++ source/arch/mips/au1000/pb1500/Makefile	2004-02-23 13:56:38.000000000 +0000
@@ -4,10 +4,5 @@
 #     	ppopov@mvista.com or source@mvista.com
 #
 # Makefile for the Alchemy Semiconductor Pb1500 board.
-#
-# 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).
-#
 
-lib-y := init.o setup.o
+lib-y := init.o board_setup.o irqmap.o
--- diff/arch/mips/au1000/pb1500/init.c	2003-07-08 09:55:17.000000000 +0100
+++ source/arch/mips/au1000/pb1500/init.c	2004-02-23 13:56:38.000000000 +0000
@@ -35,7 +35,6 @@
 #include <asm/bootinfo.h>
 #include <linux/string.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 
 int prom_argc;
 char **prom_argv, **prom_envp;
@@ -47,14 +46,14 @@ const char *get_system_type(void)
 	return "Alchemy Pb1500";
 }
 
-int __init prom_init(int argc, char **argv, char **envp, int *prom_vec)
+void __init prom_init(void)
 {
 	unsigned char *memsize_str;
 	unsigned long memsize;
 
-	prom_argc = argc;
-	prom_argv = argv;
-	prom_envp = envp;
+	prom_argc = (int) fw_arg0;
+	prom_argv = (char **) fw_arg1;
+	prom_envp = (char **) fw_arg2;
 
 	mips_machgroup = MACH_GROUP_ALCHEMY;
 	mips_machtype = MACH_PB1500;
@@ -67,5 +66,4 @@ int __init prom_init(int argc, char **ar
 		memsize = simple_strtol(memsize_str, NULL, 0);
 	}
 	add_memory_region(0, memsize, BOOT_MEM_RAM);
-	return 0;
 }
--- diff/arch/mips/baget/prom/init.c	2003-07-08 09:55:17.000000000 +0100
+++ source/arch/mips/baget/prom/init.c	2004-02-23 13:56:38.000000000 +0000
@@ -7,17 +7,15 @@
 #include <asm/addrspace.h>
 #include <asm/bootinfo.h>
 
-char arcs_cmdline[CL_SIZE];
-
 const char *get_system_type(void)
 {
 	/* Should probably return one of "BT23-201", "BT23-202" */
 	return "Baget";
 }
 
-void __init prom_init(unsigned int mem_upper)
+void __init prom_init(void)
 {
-	mem_upper = PHYSADDR(mem_upper);
+	mem_upper = PHYSADDR(fw_arg0);
 
 	mips_machgroup  = MACH_GROUP_UNKNOWN;
 	mips_machtype   = MACH_UNKNOWN;
@@ -28,6 +26,7 @@ void __init prom_init(unsigned int mem_u
 	add_memory_region(0, mem_upper, BOOT_MEM_RAM);
 }
 
-void prom_free_prom_memory (void)
+unsigned long __init prom_free_prom_memory(void)
 {
+	return 0;
 }
--- diff/arch/mips/baget/setup.c	2003-07-08 09:55:17.000000000 +0100
+++ source/arch/mips/baget/setup.c	2004-02-23 13:56:38.000000000 +0000
@@ -470,7 +470,7 @@ extern void baget_machine_restart(char *
 extern void baget_machine_halt(void);
 extern void baget_machine_power_off(void);
 
-void __init baget_setup(void)
+static void __init baget_setup(void)
 {
 	printk("BT23/63-201n found.\n");
 	*BAGET_WRERR_ACK = 0;
@@ -485,3 +485,5 @@ void __init baget_setup(void)
 	vac_start();
 	vic_start();
 }
+
+early_initcall(baget_setup);
--- diff/arch/mips/boot/Makefile	2003-07-08 09:55:17.000000000 +0100
+++ source/arch/mips/boot/Makefile	2004-02-23 13:56:38.000000000 +0000
@@ -9,7 +9,7 @@
 #
 # Some DECstations need all possible sections of an ECOFF executable
 #
-ifdef CONFIG_DECSTATION
+ifdef CONFIG_MACH_DECSTATION
   E2EFLAGS = -a
 else
   E2EFLAGS =
@@ -19,33 +19,29 @@ endif
 # Drop some uninteresting sections in the kernel.
 # This is only relevant for ELF kernels but doesn't hurt a.out
 #
-drop-sections	= .reginfo .mdebug .comment .note
+drop-sections	= .reginfo .mdebug .comment .note .pdr
 strip-flags	= $(addprefix --remove-section=,$(drop-sections))
 
-all: vmlinux.ecoff addinitrd
-
-vmlinux.rm200: vmlinux
-	$(OBJCOPY) \
-		--change-addresses=0xfffffffc \
-		-O elf32-tradlittlemips \
-		$(strip-flags) \
-		$< $@
+all: vmlinux.ecoff vmlinux.srec addinitrd
 
 vmlinux.ecoff:	$(obj)/elf2ecoff vmlinux
-	./elf2ecoff vmlinux $(obj)/vmlinux.ecoff $(E2EFLAGS)
+	$(obj)/elf2ecoff vmlinux vmlinux.ecoff $(E2EFLAGS)
 
 $(obj)/elf2ecoff: $(obj)/elf2ecoff.c
 	$(HOSTCC) -o $@ $^
 
+vmlinux.srec:   vmlinux
+	$(OBJCOPY) -S -O srec $(strip-flags) vmlinux $(obj)/vmlinux.srec
+
 $(obj)/addinitrd: $(obj)/addinitrd.c
 	$(HOSTCC) -o $@ $^
 
 archhelp:
-	@echo	'* vmlinux.rm200	- Bootable kernel image for RM200C'
+	@echo	'* vmlinux.ecoff	- ECOFF boot image'
 
 CLEAN_FILES += addinitrd \
 	       elf2ecoff \
 	       vmlinux.ecoff \
-	       vmlinux.rm200 \
+	       vmlinux.srec \
 	       zImage.tmp \
 	       zImage
--- diff/arch/mips/cobalt/Makefile	2003-07-08 09:55:17.000000000 +0100
+++ source/arch/mips/cobalt/Makefile	2004-02-23 13:56:38.000000000 +0000
@@ -2,6 +2,6 @@
 # Makefile for the Cobalt micro systems family specific parts of the kernel
 #
 
-obj-y	 := irq.o int-handler.o reset.o setup.o via.o promcon.o
+obj-y	 := irq.o int-handler.o reset.o setup.o promcon.o
 
 EXTRA_AFLAGS := $(CFLAGS)
--- diff/arch/mips/cobalt/int-handler.S	2003-07-08 09:55:17.000000000 +0100
+++ source/arch/mips/cobalt/int-handler.S	2004-02-23 13:56:38.000000000 +0000
@@ -1,11 +1,9 @@
 /*
- * Cobalt interrupt handler
- *
  * This file is subject to the terms and conditions of the GNU General Public
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  *
- * Copyright (C) 1995, 1996, 1997 by Ralf Baechle
+ * Copyright (C) 1995, 1996, 1997, 2003 by Ralf Baechle
  * Copyright (C) 2001, 2002, 2003 by Liam Davies (ldavies@agile.tv)
  */
 #include <asm/asm.h>
@@ -14,91 +12,14 @@
 #include <asm/regdef.h>
 #include <asm/stackframe.h>
 
-/*
- * cobalt_handle_int: Interrupt handler for Cobalt boards
- */
 		.text
-		.set	noreorder
-		.set	noat
 		.align	5
 		NESTED(cobalt_handle_int, PT_SIZE, sp)
 		SAVE_ALL
 		CLI
-		.set	at
-
-		/*
-		 * Get pending Interrupts
-		 */
-		mfc0    s0,CP0_CAUSE    # get raw irq status
-		mfc0    a0,CP0_STATUS   # get irq mask
-		and     s0,s0,a0        # compute masked irq status
-
-		andi	a0,s0,CAUSEF_IP2	/* Check for Galileo timer */
-		beq	a0,zero,1f
-		 andi	a0,s0,CAUSEF_IP6	/* Check for Via chip */
-
-		/* Galileo interrupt */
-		jal	galileo_irq
-		 move	a0,sp
-		j	ret_from_irq
-		 nop
-
-1:
-		beq	a0,zero,1f		/* Check IP6 */
-		 andi	a0,s0,CAUSEF_IP3
-
-		/* Via interrupt */
-		jal	via_irq
-		 move	a0,sp
-		j	ret_from_irq
-		 nop
-
-1:
-		beq	a0,zero,1f		/* Check IP3 */
-		 andi	a0,s0,CAUSEF_IP4
 
-		/* Ethernet 0 interrupt */
-		li	a0,COBALT_ETH0_IRQ
-		jal     do_IRQ
-		 move	a1,sp
-
-		j	ret_from_irq
-		 nop
-
-1:
-		beq	a0,zero,1f		/* Check IP4 */
-		 andi	a0,s0,CAUSEF_IP5
-
-		/* Ethernet 1 interrupt */
-		li	a0,COBALT_ETH1_IRQ
-		jal     do_IRQ
-		 move	a1,sp
-
-		j	ret_from_irq
-		 nop
-1:
-		beq	a0,zero,1f		/* Check IP5 */
-		 andi	a0,s0,CAUSEF_IP7
-
-		/* Serial interrupt */
-		li	a0,COBALT_SERIAL_IRQ
-		jal     do_IRQ
-		 move	a1,sp
-
-		j	ret_from_irq
-		 nop
-1:
-		beq	a0,zero,1f		/* Check IP7 */
-		  nop
-
-		/* PCI interrupt */
-		li	a0,COBALT_QUBE_SLOT_IRQ
-		jal     do_IRQ
-		 move	a1,sp
-
-1:
-		j	ret_from_irq
-		 nop
+		la	ra, ret_from_irq
+		move	a1, sp
+		j	cobalt_irq
 
 		END(cobalt_handle_int)
-
--- diff/arch/mips/cobalt/irq.c	2003-07-08 09:55:17.000000000 +0100
+++ source/arch/mips/cobalt/irq.c	2004-02-23 13:56:38.000000000 +0000
@@ -5,139 +5,98 @@
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  *
- * Copyright (C) 1995, 1996, 1997 by Ralf Baechle
- * Copyright (C) 2001 by Liam Davies (ldavies@agile.tv)
- *
+ * Copyright (C) 1995, 1996, 1997, 2003 by Ralf Baechle
  */
-
 #include <linux/kernel.h>
 #include <linux/init.h>
-#include <linux/spinlock.h>
-#include <linux/interrupt.h>
-#include <linux/ioport.h>
+#include <linux/irq.h>
 
-#include <asm/bootinfo.h>
 #include <asm/i8259.h>
-#include <asm/io.h>
-#include <asm/irq.h>
-#include <asm/mipsregs.h>
-#include <asm/system.h>
+#include <asm/irq_cpu.h>
+#include <asm/gt64120.h>
+#include <asm/ptrace.h>
 
 #include <asm/cobalt/cobalt.h>
 
-/* Cobalt Exception handler */
 extern void cobalt_handle_int(void);
 
-/* Via masking routines */
-extern void unmask_irq(unsigned int irqr);
-extern void mask_irq(unsigned int irq);
-
-
 /*
- * We have two types of interrupts that we handle, ones that come
- *  in through the CPU interrupt lines, and ones that come in on
- *  the via chip. The CPU mappings are:
- *    0,1 - S/W (ignored)
- *    2   - Galileo chip (timer)
- *    3   - Tulip 0 + NCR SCSI
- *    4   - Tulip 1
- *    5   - 16550 UART
- *    6   - VIA southbridge PIC
- *    7   - unused
+ * We have two types of interrupts that we handle, ones that come in through
+ * the CPU interrupt lines, and ones that come in on the via chip. The CPU
+ * mappings are:
  *
- * The VIA chip is a master/slave 8259 setup and has the
- *  following interrupts
- *    8   - RTC
- *    9   - PCI
- *    14  - IDE0
- *    15  - IDE1
+ *    16,  - Software interrupt 0 (unused)	IE_SW0
+ *    17   - Software interrupt 1 (unused)	IE_SW0
+ *    18   - Galileo chip (timer)		IE_IRQ0
+ *    19   - Tulip 0 + NCR SCSI			IE_IRQ1
+ *    20   - Tulip 1				IE_IRQ2
+ *    21   - 16550 UART				IE_IRQ3
+ *    22   - VIA southbridge PIC		IE_IRQ4
+ *    23   - unused				IE_IRQ5
  *
- * In the table we use a 1 to indicate that we use a VIA interrupt
- *  line, and IE_IRQx to indicate that we use a CPU interrupt line
+ * The VIA chip is a master/slave 8259 setup and has the following interrupts:
  *
- * We map all of these onto linux IRQ #s 0-15 and forget the rest
- */
-#define NOINT_LINE	0
-#define CPUINT_LINE(x)	IE_IRQ##x
-#define VIAINT_LINE	1
-
-#define COBALT_IRQS	16
-
-static unsigned short irqnr_to_type[COBALT_IRQS] =
-{ CPUINT_LINE(0),  NOINT_LINE,      VIAINT_LINE,  NOINT_LINE,
-  CPUINT_LINE(1),  NOINT_LINE,      NOINT_LINE,   CPUINT_LINE(3),
-  VIAINT_LINE,     VIAINT_LINE,     NOINT_LINE,   NOINT_LINE,
-  NOINT_LINE,      CPUINT_LINE(2),  VIAINT_LINE,  VIAINT_LINE };
-
-/*
- * Cobalt CPU irq
+ *     8  - RTC
+ *     9  - PCI
+ *    14  - IDE0
+ *    15  - IDE1
  */
 
-static void enable_cpu_irq(unsigned int irq)
+asmlinkage void cobalt_irq(struct pt_regs *regs)
 {
-	unsigned long flags;
+	unsigned int pending = read_c0_status() & read_c0_cause();
 
-	local_irq_save(flags);
-	change_c0_status(irqnr_to_type[irq], irqnr_to_type[irq]);
-	local_irq_restore(flags);
-}
+	if (pending & CAUSEF_IP2) {			/* int 18 */
+		unsigned long irq_src = GALILEO_INL(GT_INTRCAUSE_OFS);
 
-static unsigned startup_cpu_irq(unsigned int irq)
-{
-	enable_cpu_irq(irq);
+		/* Check for timer irq ... */
+		if (irq_src & GALILEO_T0EXP) {
+			/* Clear the int line */
+			GALILEO_OUTL(0, GT_INTRCAUSE_OFS);
+			do_IRQ(COBALT_TIMER_IRQ, regs);
+		}
+		return;
+	}
 
-	return 0;
-}
+	if (pending & CAUSEF_IP6) {			/* int 22 */
+		int irq = i8259_irq();
 
-static void disable_cpu_irq(unsigned int irq)
-{
-	unsigned long flags;
+		if (irq >= 0)
+			do_IRQ(irq, regs);
+		return;
+	}
 
-	local_irq_save(flags);
-	change_c0_status(irqnr_to_type[irq], ~(irqnr_to_type[irq]));
-	local_irq_restore(flags);
-}
+	if (pending & CAUSEF_IP3) {			/* int 19 */
+		do_IRQ(COBALT_ETH0_IRQ, regs);
+		return;
+	}
 
-#define shutdown_cpu_irq	disable_cpu_irq
-#define mask_and_ack_cpu_irq	disable_cpu_irq
+	if (pending & CAUSEF_IP4) {			/* int 20 */
+		do_IRQ(COBALT_ETH1_IRQ, regs);
+		return;
+	}
 
-static void end_cpu_irq(unsigned int irq)
-{
-	if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
-		enable_cpu_irq(irq);
-}
+	if (pending & CAUSEF_IP5) {			/* int 21 */
+		do_IRQ(COBALT_SERIAL_IRQ, regs);
+		return;
+	}
 
-static struct hw_interrupt_type cobalt_cpu_irq_type = {
-	"Cobalt CPU",
-	startup_cpu_irq,
-	shutdown_cpu_irq,
-	enable_cpu_irq,
-	disable_cpu_irq,
-	mask_and_ack_cpu_irq,
-	end_cpu_irq,
-	NULL
-};
+	if (pending & CAUSEF_IP7) {			/* int 23 */
+		do_IRQ(COBALT_QUBE_SLOT_IRQ, regs);
+		return;
+	}
+}
 
 void __init init_IRQ(void)
 {
-	int i;
-
-	/* Initialise all of the IRQ descriptors */
-	init_i8259_irqs();
-
-	/* Map the irqnr to the type int we have */
-	for (i=0; i < COBALT_IRQS; i++) {
-		if (irqnr_to_type[i] >= CPUINT_LINE(0))
-			/* cobalt_cpu_irq_type */
-			irq_desc[i].handler = &cobalt_cpu_irq_type;
-	}
-
-	/* Mask all cpu interrupts
-	    (except IE4, we already masked those at VIA level) */
-	clear_c0_status(ST0_IM);
-	set_c0_status(IE_IRQ4);
+	set_except_vector(0, cobalt_handle_int);
 
-	cli();
+	init_i8259_irqs();				/*  0 ... 15 */
+	mips_cpu_irq_init(16);				/* 16 ... 23 */
 
-	set_except_vector(0, cobalt_handle_int);
+	/*
+	 * Mask all cpu interrupts
+	 *  (except IE4, we already masked those at VIA level)
+	 */
+	change_c0_status(ST0_IM, IE_IRQ4);
 }
--- diff/arch/mips/cobalt/promcon.c	2003-07-08 09:55:17.000000000 +0100
+++ source/arch/mips/cobalt/promcon.c	2004-02-23 13:56:38.000000000 +0000
@@ -13,7 +13,6 @@
 #include <linux/init.h>
 #include <linux/console.h>
 #include <linux/kdev_t.h>
-#include <linux/major.h>
 #include <linux/serial_reg.h>
 
 #include <asm/delay.h>
@@ -70,22 +69,19 @@ void putDebugChar(char kgdb_char)
 	ns16550_cons_put_char(kgdb_char, port);
 }
 
-static kdev_t
-ns16550_console_dev(struct console *c)
-{
-	return mk_kdev(TTY_MAJOR, 64 + c->index);
-}
-
 static struct console ns16550_console = {
     .name	= "prom",
     .setup	= NULL,
     .write	= ns16550_console_write,
-    .device	= ns16550_console_dev,
     .flags	= CON_PRINTBUFFER,
     .index	= -1,
 };
 
-void __init ns16550_setup_console(void)
+static int __init ns16550_setup_console(void)
 {
 	register_console(&ns16550_console);
+
+	return 0;
 }
+
+console_initcall(ns16550_setup_console);
--- diff/arch/mips/cobalt/setup.c	2003-07-08 09:55:17.000000000 +0100
+++ source/arch/mips/cobalt/setup.c	2004-02-23 13:56:38.000000000 +0000
@@ -9,15 +9,13 @@
  * Copyright (C) 2001, 2002, 2003 by Liam Davies (ldavies@agile.tv)
  *
  */
-
 #include <linux/config.h>
 #include <linux/interrupt.h>
 #include <linux/pci.h>
-#include <linux/mc146818rtc.h>
 #include <linux/init.h>
-#include <linux/ide.h>
 
 #include <asm/bootinfo.h>
+#include <asm/pci_channel.h>
 #include <asm/time.h>
 #include <asm/io.h>
 #include <asm/irq.h>
@@ -31,11 +29,9 @@ extern void cobalt_machine_restart(char 
 extern void cobalt_machine_halt(void);
 extern void cobalt_machine_power_off(void);
 
-extern struct rtc_ops std_rtc_ops;
-extern struct ide_ops std_ide_ops;
-
+int cobalt_board_id;
 
-char arcs_cmdline[CL_SIZE] = {
+static char my_cmdline[CL_SIZE] = {
  "console=ttyS0,115200 "
 #ifdef CONFIG_IP_PNP
  "ip=on "
@@ -52,12 +48,6 @@ const char *get_system_type(void)
 	return "MIPS Cobalt";
 }
 
-
-static void __init cobalt_time_init(void)
-{
-	rtc_ops = &std_rtc_ops;
-}
-
 static void __init cobalt_timer_setup(struct irqaction *irq)
 {
 	/* Load timer value for 150 Hz */
@@ -72,22 +62,46 @@ static void __init cobalt_timer_setup(st
 	GALILEO_OUTL(0x100, GT_INTRMASK_OFS);
 }
 
+extern struct pci_ops gt64111_pci_ops;
+
+static struct resource cobalt_mem_resource = {
+	"GT64111 PCI MEM", GT64111_IO_BASE, 0xffffffffUL, IORESOURCE_MEM
+};
+
+static struct resource cobalt_io_resource = {
+	"GT64111 IO MEM", 0x00001000UL, 0x0fffffffUL, IORESOURCE_IO
+};
+
+static struct resource cobalt_io_resources[] = {
+	{ "dma1", 0x00, 0x1f, IORESOURCE_BUSY },
+	{ "timer", 0x40, 0x5f, IORESOURCE_BUSY },
+	{ "keyboard", 0x60, 0x6f, IORESOURCE_BUSY },
+	{ "dma page reg", 0x80, 0x8f, IORESOURCE_BUSY },
+	{ "dma2", 0xc0, 0xdf, IORESOURCE_BUSY },
+};
+
+#define COBALT_IO_RESOURCES (sizeof(cobalt_io_resources)/sizeof(struct resource))
+
+static struct pci_controller cobalt_pci_controller = {
+	.pci_ops	= &gt64111_pci_ops,
+	.mem_resource	= &cobalt_mem_resource,
+	.mem_offset	= 0,
+	.io_resource	= &cobalt_io_resource,
+	.io_offset	= 0x00001000UL - GT64111_IO_BASE
+};
 
-void __init cobalt_setup(void)
+static void __init cobalt_setup(void)
 {
+	unsigned int devfn = PCI_DEVFN(COBALT_PCICONF_VIA, 0);
+	int i;
 
 	_machine_restart = cobalt_machine_restart;
 	_machine_halt = cobalt_machine_halt;
 	_machine_power_off = cobalt_machine_power_off;
 
-	board_time_init = cobalt_time_init;
 	board_timer_setup = cobalt_timer_setup;
 
-#ifdef CONFIG_BLK_DEV_IDE
-	ide_ops = &std_ide_ops;
-#endif
-
-        set_io_port_base(KSEG1ADDR(0x10000000));
+        set_io_port_base(KSEG1ADDR(GT64111_IO_BASE));
 
 	/*
 	 * This is a prom style console. We just poke at the
@@ -96,18 +110,42 @@ void __init cobalt_setup(void)
 	 *  get to the stage of setting up a real serial console.
 	 */
 	/*ns16550_setup_console();*/
+
+	/* request I/O space for devices used on all i[345]86 PCs */
+	for (i = 0; i < COBALT_IO_RESOURCES; i++)
+		request_resource(&ioport_resource, cobalt_io_resources + i);
+
+        /* Read the cobalt id register out of the PCI config space */
+        PCI_CFG_SET(devfn, (VIA_COBALT_BRD_ID_REG & ~0x3));
+        cobalt_board_id = GALILEO_INL(GT_PCI0_CFGDATA_OFS);
+        cobalt_board_id >>= ((VIA_COBALT_BRD_ID_REG & 3) * 8);
+        cobalt_board_id = VIA_COBALT_BRD_REG_to_ID(cobalt_board_id);
+
+#ifdef CONFIG_PCI
+	register_pci_controller(&cobalt_pci_controller);
+#endif
 }
 
-/* Prom init. We read our one and only communication with the
-    firmware. Grab the amount of installed memory */
-void __init prom_init(int argc)
+early_initcall(cobalt_setup);
+
+/*
+ * Prom init. We read our one and only communication with the firmware.
+ * Grab the amount of installed memory
+ */
+
+void __init prom_init(void)
 {
+	int argc = fw_arg0;
+
+	strcpy(arcs_cmdline, my_cmdline);
+
 	mips_machgroup = MACH_GROUP_COBALT;
 
 	add_memory_region(0x0, argc & 0x7fffffff, BOOT_MEM_RAM);
 }
 
-void __init prom_free_prom_memory(void)
+unsigned long __init prom_free_prom_memory(void)
 {
 	/* Nothing to do! */
+	return 0;
 }
--- diff/arch/mips/ddb5xxx/common/prom.c	2003-07-08 09:55:17.000000000 +0100
+++ source/arch/mips/ddb5xxx/common/prom.c	2004-02-23 13:56:38.000000000 +0000
@@ -1,17 +1,11 @@
-/***********************************************************************
- *
+/*
  * Copyright 2001 MontaVista Software Inc.
  * Author: jsun@mvista.com or jsun@junsun.net
  *
- * arch/mips/ddb5xxx/common/prom.c
- *     prom.c file.
- *
  * This program is free software; you can redistribute  it and/or modify it
  * under  the terms of  the GNU General  Public License as published by the
  * Free Software Foundation;  either version 2 of the  License, or (at your
  * option) any later version.
- *
- ***********************************************************************
  */
 #include <linux/config.h>
 #include <linux/init.h>
@@ -24,8 +18,6 @@
 #include <asm/ddb5xxx/ddb5xxx.h>
 #include <asm/debug.h>
 
-char arcs_cmdline[CL_SIZE];
-
 const char *get_system_type(void)
 {
 	switch (mips_machtype) {
@@ -38,13 +30,22 @@ const char *get_system_type(void)
 	}
 }
 
+#if defined(CONFIG_DDB5477)
+void ddb5477_runtime_detection(void);
+#endif
+
 /* [jsun@junsun.net] PMON passes arguments in C main() style */
-void __init prom_init(int argc, const char **arg)
+void __init prom_init(void)
 {
+	int argc = fw_arg0;
+	char **arg = (char**) fw_arg1;
 	int i;
 
+	/* if user passes kernel args, ignore the default one */
+	if (argc > 1)
+		arcs_cmdline[0] = '\0';
+
 	/* arg[0] is "g", the rest is boot parameters */
-	arcs_cmdline[0] = '\0';
 	for (i = 1; i < argc; i++) {
 		if (strlen(arcs_cmdline) + strlen(arg[i] + 1)
 		    >= sizeof(arcs_cmdline))
@@ -53,9 +54,6 @@ void __init prom_init(int argc, const ch
 		strcat(arcs_cmdline, " ");
 	}
 
-	/* by default all these boards use dhcp/nfs root fs */
-	strcat(arcs_cmdline, "ip=bootp");
-
 	mips_machgroup = MACH_GROUP_NEC_DDB;
 
 #if defined(CONFIG_DDB5074)
@@ -70,8 +68,9 @@ void __init prom_init(int argc, const ch
 #endif
 }
 
-void __init prom_free_prom_memory(void)
+unsigned long __init prom_free_prom_memory(void)
 {
+	return 0;
 }
 
 #if defined(CONFIG_DDB5477)
--- diff/arch/mips/ddb5xxx/ddb5074/Makefile	2003-07-08 09:55:17.000000000 +0100
+++ source/arch/mips/ddb5xxx/ddb5074/Makefile	2004-02-23 13:56:38.000000000 +0000
@@ -3,6 +3,6 @@
 # under Linux.
 #
 
-obj-y			+= setup.o irq.o int-handler.o nile4_pic.o time.o
+obj-y			+= setup.o irq.o int-handler.o nile4_pic.o
 
 EXTRA_AFLAGS := $(CFLAGS)
--- diff/arch/mips/ddb5xxx/ddb5074/nile4_pic.c	2003-07-08 09:55:17.000000000 +0100
+++ source/arch/mips/ddb5xxx/ddb5074/nile4_pic.c	2004-02-23 13:56:38.000000000 +0000
@@ -9,6 +9,7 @@
  *  Author: jsun@mvista.com or jsun@junsun.net
  *
  */
+#include <linux/config.h>
 #include <linux/kernel.h>
 #include <linux/types.h>
 #include <linux/interrupt.h>
--- diff/arch/mips/ddb5xxx/ddb5074/setup.c	2003-07-08 09:55:17.000000000 +0100
+++ source/arch/mips/ddb5xxx/ddb5074/setup.c	2004-02-23 13:56:38.000000000 +0000
@@ -10,9 +10,7 @@
 #include <linux/kernel.h>
 #include <linux/kdev_t.h>
 #include <linux/types.h>
-#include <linux/console.h>
 #include <linux/sched.h>
-#include <linux/mc146818rtc.h>
 #include <linux/pci.h>
 #include <linux/ide.h>
 #include <linux/ioport.h>
@@ -28,20 +26,11 @@
 #include <asm/ddb5xxx/ddb5074.h>
 #include <asm/ddb5xxx/ddb5xxx.h>
 
-
 #ifdef CONFIG_KGDB
 extern void rs_kgdb_hook(int);
 extern void breakpoint(void);
 #endif
 
-#if defined(CONFIG_SERIAL_CONSOLE)
-extern void console_setup(char *);
-#endif
-
-extern struct ide_ops std_ide_ops;
-extern struct kbd_ops std_kbd_ops;
-extern struct rtc_ops ddb_rtc_ops;
-
 static void (*back_to_prom) (void) = (void (*)(void)) 0xbfc00000;
 
 static void ddb_machine_restart(char *command)
@@ -97,13 +86,13 @@ static void __init ddb_timer_init(struct
 
 static void __init ddb_time_init(void)
 {
-    /* we have ds1396 RTC chip */
+	/* we have ds1396 RTC chip */
 	rtc_ds1386_init(KSEG1ADDR(DDB_PCI_MEM_BASE));
 }
 
 
 
-void __init ddb_setup(void)
+static void __init ddb5074_setup(void)
 {
 	extern int panic_timeout;
 
@@ -118,25 +107,16 @@ void __init ddb_setup(void)
 	_machine_halt = ddb_machine_halt;
 	_machine_power_off = ddb_machine_power_off;
 
-#ifdef CONFIG_BLK_DEV_IDE
-	ide_ops = &std_ide_ops;
-#endif
-
-	rtc_ops = &ddb_rtc_ops;
-
-    ddb_out32(DDB_BAR0, 0);
+	ddb_out32(DDB_BAR0, 0);
 
 	ddb_set_pmr(DDB_PCIINIT0, DDB_PCICMD_IO, 0, 0x10);
 	ddb_set_pmr(DDB_PCIINIT1, DDB_PCICMD_MEM, DDB_PCI_MEM_BASE , 0x10);
 
-#ifdef CONFIG_FB
-    conswitchp = &dummy_con;
-#endif
-
 	/* Reboot on panic */
 	panic_timeout = 180;
 }
 
+early_initcall(ddb5074_setup);
 
 #define USE_NILE4_SERIAL	0
 
--- diff/arch/mips/ddb5xxx/ddb5476/setup.c	2003-07-08 09:55:17.000000000 +0100
+++ source/arch/mips/ddb5xxx/ddb5476/setup.c	2004-02-23 13:56:38.000000000 +0000
@@ -10,11 +10,8 @@
 #include <linux/kernel.h>
 #include <linux/kdev_t.h>
 #include <linux/types.h>
-#include <linux/console.h>
 #include <linux/sched.h>
-#include <linux/mc146818rtc.h>
 #include <linux/pci.h>
-#include <linux/ide.h>
 
 #include <asm/addrspace.h>
 #include <asm/bcache.h>
@@ -43,9 +40,6 @@
 extern void breakpoint(void);
 #endif
 
-extern struct ide_ops std_ide_ops;
-extern struct kbd_ops std_kbd_ops;
-
 static void (*back_to_prom) (void) = (void (*)(void)) 0xbfc00000;
 
 static void ddb_machine_restart(char *command)
@@ -82,7 +76,7 @@ extern void rtc_ds1386_init(unsigned lon
 static void __init ddb_time_init(void)
 {
 #if defined(USE_CPU_COUNTER_TIMER)
-	mips_counter_frequency = CPU_COUNTER_FREQUENCY;
+	mips_hpt_frequency = CPU_COUNTER_FREQUENCY;
 #endif
 
 	/* we have ds1396 RTC chip */
@@ -114,20 +108,16 @@ static void __init ddb_timer_setup(struc
 
 static struct {
 	struct resource dma1;
-	struct resource pic1;
 	struct resource timer;
 	struct resource rtc;
 	struct resource dma_page_reg;
-	struct resource pic2;
 	struct resource dma2;
 } ddb5476_ioport = {
 	{
 	"dma1", 0x00, 0x1f, IORESOURCE_BUSY}, {
-	"pic1", 0x20, 0x3f, IORESOURCE_BUSY}, {
 	"timer", 0x40, 0x5f, IORESOURCE_BUSY}, {
 	"rtc", 0x70, 0x7f, IORESOURCE_BUSY}, {
 	"dma page reg", 0x80, 0x8f, IORESOURCE_BUSY}, {
-	"pic2", 0xa0, 0xbf, IORESOURCE_BUSY}, {
 	"dma2", 0xc0, 0xdf, IORESOURCE_BUSY}
 };
 
@@ -142,8 +132,7 @@ static void ddb5476_board_init(void);
 extern void ddb5476_irq_setup(void);
 extern void (*irq_setup)(void);
 
-void __init
-ddb_setup(void)
+static void __init ddb5476_setup(void)
 {
 	extern int panic_timeout;
 
@@ -159,21 +148,16 @@ ddb_setup(void)
 
 	/* request io port/mem resources  */
 	if (request_resource(&ioport_resource, &ddb5476_ioport.dma1) ||
-	    request_resource(&ioport_resource, &ddb5476_ioport.pic1) ||
 	    request_resource(&ioport_resource, &ddb5476_ioport.timer) ||
 	    request_resource(&ioport_resource, &ddb5476_ioport.rtc) ||
 	    request_resource(&ioport_resource,
 			     &ddb5476_ioport.dma_page_reg)
-	    || request_resource(&ioport_resource, &ddb5476_ioport.pic2)
 	    || request_resource(&ioport_resource, &ddb5476_ioport.dma2)
 	    || request_resource(&iomem_resource, &ddb5476_iomem.nile4)) {
 		printk
 		    ("ddb_setup - requesting oo port resources failed.\n");
 		for (;;);
 	}
-#ifdef CONFIG_BLK_DEV_IDE
-	ide_ops = &std_ide_ops;
-#endif
 
 	/* Reboot on panic */
 	panic_timeout = 180;
@@ -181,14 +165,12 @@ ddb_setup(void)
 	/* [jsun] we need to set BAR0 so that SDRAM 0 appears at 0x0 in PCI */
 	/* *(long*)0xbfa00218 = 0x8; */
 
-#ifdef CONFIG_FB
-	conswitchp = &dummy_con;
-#endif
-
 	/* board initialization stuff */
 	ddb5476_board_init();
 }
 
+early_initcall(ddb5476_setup);
+
 /*
  * We don't trust bios.  We essentially does hardware re-initialization
  * as complete as possible, as far as we know we can safely do.
--- diff/arch/mips/ddb5xxx/ddb5477/setup.c	2003-07-08 09:55:17.000000000 +0100
+++ source/arch/mips/ddb5xxx/ddb5477/setup.c	2004-02-23 13:56:38.000000000 +0000
@@ -15,7 +15,6 @@
 #include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/types.h>
-#include <linux/console.h>
 #include <linux/sched.h>
 #include <linux/pci.h>
 #include <linux/ide.h>
@@ -36,9 +35,7 @@
 #include <asm/gdb-stub.h>
 #include <asm/traps.h>
 #include <asm/debug.h>
-#ifdef CONFIG_PC_KEYB
-#include <asm/keyboard.h> 
-#endif 
+#include <asm/pci_channel.h>
 
 #include <asm/ddb5xxx/ddb5xxx.h>
 
@@ -141,11 +138,11 @@ static void __init ddb_time_init(void)
 		bus_frequency = detect_bus_frequency(rtc_base);
 	}
 
-	/* mips_counter_frequency is 1/2 of the cpu core freq */
-	i =  (read_32bit_cp0_register(CP0_CONFIG) >> 28 ) & 7;
+	/* mips_hpt_frequency is 1/2 of the cpu core freq */
+	i =  (read_c0_config() >> 28 ) & 7;
 	if ((current_cpu_data.cputype == CPU_R5432) && (i == 3)) 
 		i = 4;
-	mips_counter_frequency = bus_frequency*(i+4)/4;
+	mips_hpt_frequency = bus_frequency*(i+4)/4;
 }
 
 extern int setup_irq(unsigned int irq, struct irqaction *irqaction);
@@ -153,7 +150,6 @@ extern int setup_irq(unsigned int irq, s
 static void __init ddb_timer_setup(struct irqaction *irq)
 {
 #if defined(USE_CPU_COUNTER_TIMER)
-	unsigned int count;
 
         /* we are using the cpu counter for timer interrupts */
 	setup_irq(CPU_IRQ_BASE + 7, irq);
@@ -170,17 +166,14 @@ static void __init ddb_timer_setup(struc
 
 static void ddb5477_board_init(void);
 extern void ddb5477_irq_setup(void);
+extern void (*irq_setup)(void);
 
-#if defined(CONFIG_BLK_DEV_INITRD)
-extern unsigned long __rd_start, __rd_end, initrd_start, initrd_end;
-#endif
+extern struct pci_controller ddb5477_ext_controller;
+extern struct pci_controller ddb5477_io_controller;
 
-void __init ddb_setup(void)
+static int  ddb5477_setup(void)
 {
 	extern int panic_timeout;
-#ifdef CONFIG_BLK_DEV_IDE
-	extern struct ide_ops std_ide_ops;   
-#endif
 
 	/* initialize board - we don't trust the loader */
         ddb5477_board_init();
@@ -202,27 +195,16 @@ void __init ddb_setup(void)
 	/* Reboot on panic */
 	panic_timeout = 180;
 
-#ifdef CONFIG_BLK_DEV_IDE
-	ide_ops = &std_ide_ops;
-#endif
-
-
-#ifdef CONFIG_FB
-	conswitchp = &dummy_con;
-#endif
+	register_pci_controller (&ddb5477_ext_controller);
+	register_pci_controller (&ddb5477_io_controller);
 
-#if defined(CONFIG_BLK_DEV_INITRD)
-	ROOT_DEV = Root_RAM0;
-	initrd_start = (unsigned long)&__rd_start;
-	initrd_end = (unsigned long)&__rd_end;
-#endif
+	return 0;
 }
 
+early_initcall(ddb5477_setup);
+
 static void __init ddb5477_board_init(void)
 {
-#ifdef CONFIG_PC_KEYB
-	extern struct kbd_ops std_kbd_ops;   
-#endif
 	/* ----------- setup PDARs ------------ */
 
 	/* SDRAM should have been set */
@@ -351,13 +333,6 @@ static void __init ddb5477_board_init(vo
 	/* For dual-function pins, make them all non-GPIO */
 	ddb_out32(DDB_GIUFUNSEL, 0x0);
 	// ddb_out32(DDB_GIUFUNSEL, 0xfe0fcfff);  /* NEC recommanded value */
-	
-	if (mips_machtype == MACH_NEC_ROCKHOPPERII) {
-#ifdef CONFIG_PC_KEYB
-	printk("kdb_ops is std\n");
-	kbd_ops = &std_kbd_ops;
-#endif                     
-	}
 
 	if (mips_machtype == MACH_NEC_ROCKHOPPERII) {
 
--- diff/arch/mips/dec/Makefile	2003-07-08 09:55:17.000000000 +0100
+++ source/arch/mips/dec/Makefile	2004-02-23 13:56:38.000000000 +0000
@@ -3,7 +3,7 @@
 #
 
 obj-y		:= ecc-berr.o int-handler.o ioasic-irq.o kn02-irq.o reset.o \
-		   rtc-dec.o setup.o time.o
+		   setup.o time.o
 
 obj-$(CONFIG_PROM_CONSOLE)	+= promcon.o
 obj-$(CONFIG_CPU_HAS_WB)	+= wbflush.o
--- diff/arch/mips/dec/ecc-berr.c	2003-07-08 09:55:17.000000000 +0100
+++ source/arch/mips/dec/ecc-berr.c	2004-02-23 13:56:38.000000000 +0000
@@ -74,7 +74,7 @@ static int dec_ecc_be_backend(struct pt_
 
 	if (!(erraddr & KN0X_EAR_VALID)) {
 		/* No idea what happened. */
-		printk(KERN_ALERT "Unindentified bus error %s.\n", kind);
+		printk(KERN_ALERT "Unidentified bus error %s.\n", kind);
 		return action;
 	}
 
@@ -198,12 +198,12 @@ int dec_ecc_be_handler(struct pt_regs *r
 	return dec_ecc_be_backend(regs, is_fixup, 0);
 }
 
-void dec_ecc_be_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+irqreturn_t dec_ecc_be_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
 	int action = dec_ecc_be_backend(regs, 0, 1);
 
 	if (action == MIPS_BE_DISCARD)
-		return;
+		return IRQ_NONE;
 
 	/*
 	 * FIXME: Find affected processes and kill them, otherwise we
--- diff/arch/mips/dec/int-handler.S	2003-07-08 09:55:17.000000000 +0100
+++ source/arch/mips/dec/int-handler.S	2004-02-23 13:56:38.000000000 +0000
@@ -13,6 +13,7 @@
  * Rewritten extensively for controller-driven IRQ support
  * by Maciej W. Rozycki.
  */
+#include <linux/config.h>
 #include <asm/asm.h>
 #include <asm/regdef.h>
 #include <asm/mipsregs.h>
--- diff/arch/mips/dec/prom/Makefile	2003-07-08 09:55:17.000000000 +0100
+++ source/arch/mips/dec/prom/Makefile	2004-02-23 13:56:38.000000000 +0000
@@ -3,7 +3,7 @@
 # under Linux.
 #
 
-lib-y			+= init.o memory.o cmdline.o identify.o
+lib-y			+= init.o memory.o cmdline.o identify.o console.o
 
 lib-$(CONFIG_MIPS32)	+= locore.o
 lib-$(CONFIG_MIPS64)	+= call_o32.o
--- diff/arch/mips/dec/prom/cmdline.c	2003-07-08 09:55:17.000000000 +0100
+++ source/arch/mips/dec/prom/cmdline.c	2004-02-23 13:56:38.000000000 +0000
@@ -2,6 +2,7 @@
  * cmdline.c: read the command line passed to us by the PROM.
  *
  * Copyright (C) 1998 Harald Koerfgen
+ * Copyright (C) 2002, 2004  Maciej W. Rozycki
  */
 #include <linux/init.h>
 #include <linux/kernel.h>
@@ -13,8 +14,6 @@
 
 #undef PROM_DEBUG
 
-char arcs_cmdline[CL_SIZE];
-
 void __init prom_init_cmdline(s32 argc, s32 *argv, u32 magic)
 {
 	char *arg;
@@ -35,6 +34,6 @@ void __init prom_init_cmdline(s32 argc, 
 	}
 
 #ifdef PROM_DEBUG
-	prom_printf("arcs_cmdline: %s\n", &(arcs_cmdline[0]));
+	printk("arcs_cmdline: %s\n", &(arcs_cmdline[0]));
 #endif
 }
--- diff/arch/mips/dec/prom/identify.c	2003-07-08 09:55:17.000000000 +0100
+++ source/arch/mips/dec/prom/identify.c	2004-02-23 13:56:38.000000000 +0000
@@ -2,11 +2,12 @@
  * identify.c: machine identification code.
  *
  * Copyright (C) 1998 Harald Koerfgen and Paul M. Antoine
- * Copyright (C) 2002, 2003  Maciej W. Rozycki
+ * Copyright (C) 2002, 2003, 2004  Maciej W. Rozycki
  */
 #include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/mc146818rtc.h>
+#include <linux/module.h>
 #include <linux/string.h>
 #include <linux/types.h>
 
@@ -61,6 +62,10 @@ const char *get_system_type(void)
  * early.  Semantically the functions belong to prom/init.c, but they
  * are compact enough we want them inlined. --macro
  */
+volatile u8 *dec_rtc_base;
+
+EXPORT_SYMBOL(dec_rtc_base);
+
 static inline void prom_init_kn01(void)
 {
 	dec_rtc_base = (void *)KN01_RTC_BASE;
@@ -100,11 +105,13 @@ void __init prom_identify_arch(u32 magic
 	u32 dec_sysid;
 
 	if (!prom_is_rex(magic)) {
-		dec_sysid = simple_strtoul(prom_getenv("systype"), (char **)0, 0);
+		dec_sysid = simple_strtoul(prom_getenv("systype"),
+					   (char **)0, 0);
 	} else {
 		dec_sysid = rex_getsysid();
 		if (dec_sysid == 0) {
-			prom_printf("Zero sysid returned from PROMs! Assuming PMAX-like machine.\n");
+			printk("Zero sysid returned from PROM! "
+			       "Assuming a PMAX-like machine.\n");
 			dec_sysid = 1;
 		}
 	}
@@ -163,10 +170,8 @@ void __init prom_identify_arch(u32 magic
 	}
 
 	if (mips_machtype == MACH_DSUNKNOWN)
-		prom_printf("This is an %s, id is %x\n",
-			    dec_system_strings[mips_machtype],
-			    dec_systype);
+		printk("This is an %s, id is %x\n",
+		       dec_system_strings[mips_machtype], dec_systype);
 	else
-		prom_printf("This is a %s\n",
-			    dec_system_strings[mips_machtype]);
+		printk("This is a %s\n", dec_system_strings[mips_machtype]);
 }
--- diff/arch/mips/dec/prom/init.c	2003-07-08 09:55:17.000000000 +0100
+++ source/arch/mips/dec/prom/init.c	2004-02-23 13:56:38.000000000 +0000
@@ -2,11 +2,12 @@
  * init.c: PROM library initialisation code.
  *
  * Copyright (C) 1998 Harald Koerfgen
- * Copyright (C) 2002  Maciej W. Rozycki
+ * Copyright (C) 2002, 2004  Maciej W. Rozycki
  */
 #include <linux/config.h>
 #include <linux/init.h>
 #include <linux/smp.h>
+#include <linux/string.h>
 #include <linux/types.h>
 
 #include <asm/bootinfo.h>
@@ -35,7 +36,7 @@ int (*__pmax_close)(int);
 
 
 /*
- * Detect which PROM's the DECSTATION has, and set the callback vectors
+ * Detect which PROM the DECSTATION has, and set the callback vectors
  * appropriately.
  */
 void __init which_prom(s32 magic, s32 *prom_vec)
@@ -82,12 +83,22 @@ void __init which_prom(s32 magic, s32 *p
 	}
 }
 
-int __init prom_init(s32 argc, s32 *argv, u32 magic, s32 *prom_vec)
+void __init prom_init(void)
 {
 	extern void dec_machine_halt(void);
+	static char cpu_msg[] __initdata =
+		"Sorry, this kernel is compiled for a wrong CPU type!\n";
+	static char r3k_msg[] __initdata =
+		"Please recompile with \"CONFIG_CPU_R3000 = y\".\n";
+	static char r4k_msg[] __initdata =
+		"Please recompile with \"CONFIG_CPU_R4x00 = y\".\n";
+	s32 argc = fw_arg0;
+	s32 argv = fw_arg1;
+	u32 magic = fw_arg2;
+	s32 prom_vec = fw_arg3;
 
 	/*
-	 * Determine which PROM's we have
+	 * Determine which PROM we have
 	 * (and therefore which machine we're on!)
 	 */
 	which_prom(magic, prom_vec);
@@ -95,12 +106,15 @@ int __init prom_init(s32 argc, s32 *argv
 	if (prom_is_rex(magic))
 		rex_clear_cache();
 
+	/* Register the early console.  */
+	register_prom_console();
+
 	/* Were we compiled with the right CPU option? */
 #if defined(CONFIG_CPU_R3000)
 	if ((current_cpu_data.cputype == CPU_R4000SC) ||
 	    (current_cpu_data.cputype == CPU_R4400SC)) {
-		prom_printf("Sorry, this kernel is compiled for the wrong CPU type!\n");
-		prom_printf("Please recompile with \"CONFIG_CPU_R4x00 = y\"\n");
+		printk(cpu_msg);
+		printk(r4k_msg);
 		dec_machine_halt();
 	}
 #endif
@@ -108,8 +122,8 @@ int __init prom_init(s32 argc, s32 *argv
 #if defined(CONFIG_CPU_R4X00)
 	if ((current_cpu_data.cputype == CPU_R3000) ||
 	    (current_cpu_data.cputype == CPU_R3000A)) {
-		prom_printf("Sorry, this kernel is compiled for the wrong CPU type!\n");
-		prom_printf("Please recompile with \"CONFIG_CPU_R3000 = y\"\n");
+		printk(cpu_msg);
+		printk(r3k_msg);
 		dec_machine_halt();
 	}
 #endif
@@ -117,6 +131,4 @@ int __init prom_init(s32 argc, s32 *argv
 	prom_meminit(magic);
 	prom_identify_arch(magic);
 	prom_init_cmdline(argc, argv, magic);
-
-	return 0;
 }
--- diff/arch/mips/dec/prom/memory.c	2003-07-08 09:55:17.000000000 +0100
+++ source/arch/mips/dec/prom/memory.c	2004-02-23 13:56:38.000000000 +0000
@@ -93,7 +93,7 @@ void __init prom_meminit(u32 magic)
 		rex_setup_memory_region();
 }
 
-void __init prom_free_prom_memory (void)
+unsigned long __init prom_free_prom_memory(void)
 {
 	unsigned long addr, end;
 
@@ -125,4 +125,6 @@ void __init prom_free_prom_memory (void)
 
 	printk("Freeing unused PROM memory: %ldk freed\n",
 	       (end - PAGE_SIZE) >> 10);
+
+	return end - PAGE_SIZE;
 }
--- diff/arch/mips/dec/promcon.c	2003-07-08 09:55:17.000000000 +0100
+++ source/arch/mips/dec/promcon.c	2004-02-23 13:56:38.000000000 +0000
@@ -6,7 +6,6 @@
  */
 
 #include <linux/tty.h>
-#include <linux/major.h>
 #include <linux/ptrace.h>
 #include <linux/init.h>
 #include <linux/console.h>
--- diff/arch/mips/dec/reset.c	2003-07-08 09:55:17.000000000 +0100
+++ source/arch/mips/dec/reset.c	2004-02-23 13:56:38.000000000 +0000
@@ -4,29 +4,38 @@
  * Copyright (C) 199x  the Anonymous
  * Copyright (C) 2001, 2002, 2003  Maciej W. Rozycki
  */
+#include <linux/interrupt.h>
+#include <linux/linkage.h>
 
 #include <asm/addrspace.h>
 #include <asm/ptrace.h>
 
-#define back_to_prom()	(((void (*)(void))KSEG1ADDR(0x1fc00000))())
+typedef void ATTRIB_NORET (* noret_func_t)(void);
 
-void dec_machine_restart(char *command)
+static inline void ATTRIB_NORET back_to_prom(void)
+{
+	noret_func_t func = (void *) KSEG1ADDR(0x1fc00000);
+
+	func();
+}
+
+void ATTRIB_NORET dec_machine_restart(char *command)
 {
 	back_to_prom();
 }
 
-void dec_machine_halt(void)
+void ATTRIB_NORET dec_machine_halt(void)
 {
 	back_to_prom();
 }
 
-void dec_machine_power_off(void)
+void ATTRIB_NORET dec_machine_power_off(void)
 {
     /* DECstations don't have a software power switch */
 	back_to_prom();
 }
 
-void dec_intr_halt(int irq, void *dev_id, struct pt_regs *regs)
+irqreturn_t dec_intr_halt(int irq, void *dev_id, struct pt_regs *regs)
 {
 	dec_machine_halt();
 }
--- diff/arch/mips/dec/setup.c	2003-07-08 09:55:17.000000000 +0100
+++ source/arch/mips/dec/setup.c	2004-02-23 13:56:38.000000000 +0000
@@ -11,7 +11,6 @@
 #include <linux/config.h>
 #include <linux/sched.h>
 #include <linux/interrupt.h>
-#include <linux/mc146818rtc.h>
 #include <linux/param.h>
 #include <linux/console.h>
 #include <linux/init.h>
@@ -19,12 +18,14 @@
 #include <linux/spinlock.h>
 #include <linux/types.h>
 
-#include <asm/cpu.h>
 #include <asm/bootinfo.h>
+#include <asm/cpu.h>
+#include <asm/cpu-features.h>
 #include <asm/irq.h>
 #include <asm/irq_cpu.h>
 #include <asm/mipsregs.h>
 #include <asm/reboot.h>
+#include <asm/time.h>
 #include <asm/traps.h>
 #include <asm/wbflush.h>
 
@@ -43,10 +44,15 @@
 extern void dec_machine_restart(char *command);
 extern void dec_machine_halt(void);
 extern void dec_machine_power_off(void);
-extern void dec_intr_halt(int irq, void *dev_id, struct pt_regs *regs);
+extern irqreturn_t dec_intr_halt(int irq, void *dev_id, struct pt_regs *regs);
 
 extern asmlinkage void decstation_handle_int(void);
 
+#ifdef CONFIG_BLK_DEV_INITRD
+extern unsigned long initrd_start, initrd_end;
+extern void * __rd_start, * __rd_end;
+#endif
+
 spinlock_t ioasic_ssr_lock;
 
 volatile u32 *ioasic_base;
@@ -105,28 +111,6 @@ static struct irqaction haltirq = {
 };
 
 
-void (*board_time_init)(struct irqaction *irq);
-
-
-/*
- * enable the periodic interrupts
- */
-static void __init dec_time_init(struct irqaction *irq)
-{
-	/*
-	* Here we go, enable periodic rtc interrupts.
-	*/
-
-#ifndef LOG_2_HZ
-#  define LOG_2_HZ 7
-#endif
-
-	CMOS_WRITE(RTC_REF_CLCK_32KHZ | (16 - LOG_2_HZ), RTC_REG_A);
-	CMOS_WRITE(CMOS_READ(RTC_REG_B) | RTC_PIE, RTC_REG_B);
-	setup_irq(dec_interrupt[DEC_IRQ_RTC], irq);
-}
-
-
 /*
  * Bus error (DBE/IBE exceptions and bus interrupts) handling setup.
  */
@@ -147,24 +131,28 @@ void __init dec_be_init(void)
 }
 
 
-void __init decstation_setup(void)
+extern void dec_time_init(void);
+extern void dec_timer_setup(struct irqaction *);
+
+static void __init decstation_setup(void)
 {
+#ifdef CONFIG_BLK_DEV_INITRD
+       ROOT_DEV = MKDEV(RAMDISK_MAJOR, 0);
+       initrd_start = (unsigned long)&__rd_start;
+       initrd_end = (unsigned long)&__rd_end;
+#endif
 	board_be_init = dec_be_init;
 	board_time_init = dec_time_init;
+	board_timer_setup = dec_timer_setup;
 
 	wbflush_setup();
 
 	_machine_restart = dec_machine_restart;
 	_machine_halt = dec_machine_halt;
 	_machine_power_off = dec_machine_power_off;
-
-#ifdef CONFIG_FB
-	conswitchp = &dummy_con;
-#endif
-
-	rtc_ops = &dec_rtc_ops;
 }
 
+early_initcall(decstation_setup);
 
 /*
  * Machine-specific initialisation for KN01, aka DS2100 (aka Pmin)
--- diff/arch/mips/dec/time.c	2003-10-09 09:47:33.000000000 +0100
+++ source/arch/mips/dec/time.c	2004-02-23 13:56:38.000000000 +0000
@@ -9,283 +9,98 @@
  *
  */
 #include <linux/bcd.h>
-#include <linux/module.h>
-#include <linux/types.h>
 #include <linux/errno.h>
 #include <linux/init.h>
-#include <linux/sched.h>
+#include <linux/interrupt.h>
 #include <linux/kernel.h>
+#include <linux/mc146818rtc.h>
+#include <linux/mm.h>
+#include <linux/module.h>
 #include <linux/param.h>
+#include <linux/sched.h>
 #include <linux/string.h>
-#include <linux/mm.h>
 #include <linux/time.h>
-#include <linux/interrupt.h>
-#include <linux/bcd.h>
+#include <linux/types.h>
 
-#include <asm/cpu.h>
 #include <asm/bootinfo.h>
-#include <asm/mipsregs.h>
+#include <asm/cpu.h>
+#include <asm/div64.h>
 #include <asm/io.h>
 #include <asm/irq.h>
+#include <asm/mipsregs.h>
 #include <asm/sections.h>
-#include <asm/dec/machtype.h>
+#include <asm/time.h>
+
+#include <asm/dec/interrupts.h>
 #include <asm/dec/ioasic.h>
 #include <asm/dec/ioasic_addrs.h>
+#include <asm/dec/machtype.h>
 
-#include <linux/mc146818rtc.h>
-#include <linux/timex.h>
-
-#include <asm/div64.h>
-
-extern void (*board_time_init)(struct irqaction *irq);
-
-extern volatile unsigned long wall_jiffies;
-
-/*
- * Change this if you have some constant time drift
- */
-/* This is the value for the PC-style PICs. */
-/* #define USECS_PER_JIFFY (1000020/HZ) */
-
-/* This is for machines which generate the exact clock. */
-#define USECS_PER_JIFFY (1000000/HZ)
-#define USECS_PER_JIFFY_FRAC ((u32)((1000000ULL << 32) / HZ))
-
-#define TICK_SIZE	(tick_nsec / 1000)
-
-/* Cycle counter value at the previous timer interrupt.. */
-
-static unsigned int timerhi, timerlo;
-
-/*
- * Cached "1/(clocks per usec)*2^32" value.
- * It has to be recalculated once each jiffy.
- */
-static unsigned long cached_quotient = 0;
-
-/* Last jiffy when do_fast_gettimeoffset() was called. */
-static unsigned long last_jiffies = 0;
-
-/*
- * On MIPS only R4000 and better have a cycle counter.
- *
- * FIXME: Does playing with the RP bit in c0_status interfere with this code?
- */
-static unsigned long do_fast_gettimeoffset(void)
-{
-	u32 count;
-	unsigned long res, tmp;
-	unsigned long quotient;
-
-	tmp = jiffies;
-
-	quotient = cached_quotient;
-
-	if (last_jiffies != tmp) {
-	    last_jiffies = tmp;
-	    if (last_jiffies != 0) {
-		unsigned long r0;
-		__asm__(".set	push\n\t"
-			".set	mips3\n\t"
-			"lwu	%0,%3\n\t"
-			"dsll32	%1,%2,0\n\t"
-			"or	%1,%1,%0\n\t"
-			"ddivu	$0,%1,%4\n\t"
-			"mflo	%1\n\t"
-			"dsll32	%0,%5,0\n\t"
-			"or	%0,%0,%6\n\t"
-			"ddivu	$0,%0,%1\n\t"
-			"mflo	%0\n\t"
-			".set	pop"
-			: "=&r" (quotient), "=&r" (r0)
-			: "r" (timerhi), "m" (timerlo),
-			  "r" (tmp), "r" (USECS_PER_JIFFY),
-			  "r" (USECS_PER_JIFFY_FRAC));
-		cached_quotient = quotient;
-	    }
-	}
-	/* Get last timer tick in absolute kernel time */
-	count = read_c0_count();
-
-	/* .. relative to previous jiffy (32 bits is enough) */
-	count -= timerlo;
-//printk("count: %08lx, %08lx:%08lx\n", count, timerhi, timerlo);
-
-	__asm__("multu	%2,%3"
-		: "=l" (tmp), "=h" (res)
-		: "r" (count), "r" (quotient));
-
-	/*
-	 * Due to possible jiffies inconsistencies, we need to check
-	 * the result so that we'll get a timer that is monotonic.
-	 */
-	if (res >= USECS_PER_JIFFY)
-		res = USECS_PER_JIFFY - 1;
-
-	return res;
-}
 
-static unsigned long do_ioasic_gettimeoffset(void)
+static unsigned long dec_rtc_get_time(void)
 {
-	u32 count;
-	unsigned long res, tmp;
-	unsigned long quotient;
-
-	tmp = jiffies;
-
-	quotient = cached_quotient;
-
-	if (last_jiffies != tmp) {
-		last_jiffies = tmp;
-		if (last_jiffies != 0) {
-			unsigned long r0;
-			do_div64_32(r0, timerhi, timerlo, tmp);
-			do_div64_32(quotient, USECS_PER_JIFFY,
-				    USECS_PER_JIFFY_FRAC, r0);
-			cached_quotient = quotient;
-		}
-	}
-	/* Get last timer tick in absolute kernel time */
-	count = ioasic_read(IO_REG_FCTR);
-
-	/* .. relative to previous jiffy (32 bits is enough) */
-	count -= timerlo;
-//printk("count: %08x, %08x:%08x\n", count, timerhi, timerlo);
-
-	__asm__("multu	%2,%3"
-		: "=l" (tmp), "=h" (res)
-		: "r" (count), "r" (quotient));
-
-	/*
-	 * Due to possible jiffies inconsistencies, we need to check
-	 * the result so that we'll get a timer that is monotonic.
-	 */
-	if (res >= USECS_PER_JIFFY)
-        	res = USECS_PER_JIFFY - 1;
-
-	return res;
-}
-
-/* This function must be called with interrupts disabled
- * It was inspired by Steve McCanne's microtime-i386 for BSD.  -- jrs
- *
- * However, the pc-audio speaker driver changes the divisor so that
- * it gets interrupted rather more often - it loads 64 into the
- * counter rather than 11932! This has an adverse impact on
- * do_gettimeoffset() -- it stops working! What is also not
- * good is that the interval that our timer function gets called
- * is no longer 10.0002 ms, but 9.9767 ms. To get around this
- * would require using a different timing source. Maybe someone
- * could use the RTC - I know that this can interrupt at frequencies
- * ranging from 8192Hz to 2Hz. If I had the energy, I'd somehow fix
- * it so that at startup, the timer code in sched.c would select
- * using either the RTC or the 8253 timer. The decision would be
- * based on whether there was any other device around that needed
- * to trample on the 8253. I'd set up the RTC to interrupt at 1024 Hz,
- * and then do some jiggery to have a version of do_timer that
- * advanced the clock by 1/1024 s. Every time that reached over 1/100
- * of a second, then do all the old code. If the time was kept correct
- * then do_gettimeoffset could just return 0 - there is no low order
- * divider that can be accessed.
- *
- * Ideally, you would be able to use the RTC for the speaker driver,
- * but it appears that the speaker driver really needs interrupt more
- * often than every 120 us or so.
- *
- * Anyway, this needs more thought....          pjsg (1993-08-28)
- *
- * If you are really that interested, you should be reading
- * comp.protocols.time.ntp!
- */
+	unsigned int year, mon, day, hour, min, sec, real_year;
+	int i;
 
-static unsigned long do_slow_gettimeoffset(void)
-{
-	/*
-	 * This is a kludge until I find a way for the
-	 * DECstations without bus cycle counter. HK
+	/* The Linux interpretation of the DS1287 clock register contents:
+	 * When the Update-In-Progress (UIP) flag goes from 1 to 0, the
+	 * RTC registers show the second which has precisely just started.
+	 * Let's hope other operating systems interpret the RTC the same way.
 	 */
-	return 0;
-}
-
-static unsigned long (*do_gettimeoffset) (void) = do_slow_gettimeoffset;
-
-/*
- * This version of gettimeofday has microsecond resolution
- * and better than microsecond precision on fast x86 machines with TSC.
- */
-void do_gettimeofday(struct timeval *tv)
-{
-	unsigned long seq;
-	unsigned long usec, sec;
-
+	/* read RTC exactly on falling edge of update flag */
+	for (i = 0; i < 1000000; i++)	/* may take up to 1 second... */
+		if (CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP)
+			break;
+	for (i = 0; i < 1000000; i++)	/* must try at least 2.228 ms */
+		if (!(CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP))
+			break;
+	/* Isn't this overkill?  UIP above should guarantee consistency */
 	do {
-		seq = read_seqbegin(&xtime_lock);
-		usec = do_gettimeoffset();
-		{
-			unsigned long lost = jiffies - wall_jiffies;
-			if (lost)
-				usec += lost * (1000000 / HZ);
-		}
-		sec = xtime.tv_sec;
-		usec += (xtime.tv_nsec / 1000);
-	} while (read_seqretry(&xtime_lock, seq));
-
-	while (usec >= 1000000) {
-		usec -= 1000000;
-		sec++;
+		sec = CMOS_READ(RTC_SECONDS);
+		min = CMOS_READ(RTC_MINUTES);
+		hour = CMOS_READ(RTC_HOURS);
+		day = CMOS_READ(RTC_DAY_OF_MONTH);
+		mon = CMOS_READ(RTC_MONTH);
+		year = CMOS_READ(RTC_YEAR);
+	} while (sec != CMOS_READ(RTC_SECONDS));
+	if (!(CMOS_READ(RTC_CONTROL) & RTC_DM_BINARY) || RTC_ALWAYS_BCD) {
+		sec = BCD2BIN(sec);
+		min = BCD2BIN(min);
+		hour = BCD2BIN(hour);
+		day = BCD2BIN(day);
+		mon = BCD2BIN(mon);
+		year = BCD2BIN(year);
 	}
-
-	tv->tv_sec = sec;
-	tv->tv_usec = usec;
-}
-
-EXPORT_SYMBOL(do_gettimeofday);
-
-void do_settimeofday(struct timeval *tv)
-{
-	write_seqlock_irq(&xtime_lock);
 	/*
-	 * This is revolting. We need to set "xtime" correctly. However, the
-	 * value in this location is the value at the most recent update of
-	 * wall time.  Discover what correction gettimeofday() would have
-	 * made, and then undo it!
+	 * The PROM will reset the year to either '72 or '73.
+	 * Therefore we store the real year separately, in one
+	 * of unused BBU RAM locations.
 	 */
-	tv->tv_usec -= do_gettimeoffset();
-	tv->tv_usec -= (jiffies - wall_jiffies) * (1000000 / HZ);
-
-	while (tv->tv_usec < 0) {
-		tv->tv_usec += 1000000;
-		tv->tv_sec--;
-	}
+	real_year = CMOS_READ(RTC_DEC_YEAR);
+	year += real_year - 72 + 2000;
 
-	xtime.tv_sec = tv->tv_sec;
-	xtime.tv_nsec = (tv->tv_usec * 1000);
-	time_adjust = 0;		/* stop active adjtime() */
-	time_status |= STA_UNSYNC;
-	time_maxerror = NTP_PHASE_LIMIT;
-	time_esterror = NTP_PHASE_LIMIT;
-	write_sequnlock_irq(&xtime_lock);
+	return mktime(year, mon, day, hour, min, sec);
 }
 
-EXPORT_SYMBOL(do_settimeofday);
-
 /*
- * In order to set the CMOS clock precisely, set_rtc_mmss has to be
- * called 500 ms after the second nowtime has started, because when
+ * In order to set the CMOS clock precisely, dec_rtc_set_mmss has to
+ * be called 500 ms after the second nowtime has started, because when
  * nowtime is written into the registers of the CMOS clock, it will
- * jump to the next second precisely 500 ms later. Check the Motorola
- * MC146818A or Dallas DS12887 data sheet for details.
+ * jump to the next second precisely 500 ms later.  Check the Dallas
+ * DS1287 data sheet for details.
  */
-static int set_rtc_mmss(unsigned long nowtime)
+static int dec_rtc_set_mmss(unsigned long nowtime)
 {
 	int retval = 0;
 	int real_seconds, real_minutes, cmos_minutes;
 	unsigned char save_control, save_freq_select;
 
-	save_control = CMOS_READ(RTC_CONTROL);	/* tell the clock it's being set */
+	/* tell the clock it's being set */
+	save_control = CMOS_READ(RTC_CONTROL);
 	CMOS_WRITE((save_control | RTC_SET), RTC_CONTROL);
 
-	save_freq_select = CMOS_READ(RTC_FREQ_SELECT);	/* stop and reset prescaler */
+	/* stop and reset prescaler */
+	save_freq_select = CMOS_READ(RTC_FREQ_SELECT);
 	CMOS_WRITE((save_freq_select | RTC_DIV_RESET2), RTC_FREQ_SELECT);
 
 	cmos_minutes = CMOS_READ(RTC_MINUTES);
@@ -319,10 +134,9 @@ static int set_rtc_mmss(unsigned long no
 	}
 
 	/* The following flags have to be released exactly in this order,
-	 * otherwise the DS12887 (popular MC146818A clone with integrated
-	 * battery and quartz) will not reset the oscillator and will not
-	 * update precisely 500 ms later. You won't find this mentioned in
-	 * the Dallas Semiconductor data sheets, but who believes data
+	 * otherwise the DS1287 will not reset the oscillator and will not
+	 * update precisely 500 ms later.  You won't find this mentioned
+	 * in the Dallas Semiconductor data sheets, but who believes data
 	 * sheets anyway ...                           -- Markus Kuhn
 	 */
 	CMOS_WRITE(save_control, RTC_CONTROL);
@@ -331,177 +145,56 @@ static int set_rtc_mmss(unsigned long no
 	return retval;
 }
 
-/* last time the cmos clock got updated */
-static long last_rtc_update;
 
-/*
- * timer_interrupt() needs to keep up the real-time clock,
- * as well as call the "do_timer()" routine every clocktick
- */
-static inline void
-timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static int dec_timer_state(void)
 {
-	volatile unsigned char dummy;
-	unsigned long seq;
-
-	dummy = CMOS_READ(RTC_REG_C);	/* ACK RTC Interrupt */
-
-	if (!user_mode(regs)) {
-		if (prof_buffer && current->pid) {
-			unsigned long pc = regs->cp0_epc;
-
-			pc -= (unsigned long) _stext;
-			pc >>= prof_shift;
-			/*
-			 * Dont ignore out-of-bounds pc values silently,
-			 * put them into the last histogram slot, so if
-			 * present, they will show up as a sharp peak.
-			 */
-			if (pc > prof_len - 1)
-				pc = prof_len - 1;
-			atomic_inc((atomic_t *) & prof_buffer[pc]);
-		}
-	}
-	do_timer(regs);
-
-	/*
-	 * If we have an externally synchronized Linux clock, then update
-	 * CMOS clock accordingly every ~11 minutes. Set_rtc_mmss() has to be
-	 * called as close as possible to 500 ms before the new second starts.
-	 */
-	do {
-		seq = read_seqbegin(&xtime_lock);
-
-		if ((time_status & STA_UNSYNC) == 0
-		    && xtime.tv_sec > last_rtc_update + 660
-		    && (xtime.tv_nsec / 1000) >= 500000 - ((unsigned) TICK_SIZE) / 2
-		    && (xtime.tv_nsec / 1000) <= 500000 + ((unsigned) TICK_SIZE) / 2) {
-			if (set_rtc_mmss(xtime.tv_sec) == 0)
-				last_rtc_update = xtime.tv_sec;
-			else
-				/* do it again in 60 s */
-				last_rtc_update = xtime.tv_sec - 600;
-		}
-	} while (read_seqretry(&xtime_lock, seq));
-
-	/* As we return to user mode fire off the other CPU schedulers.. this is
-	   basically because we don't yet share IRQ's around. This message is
-	   rigged to be safe on the 386 - basically it's a hack, so don't look
-	   closely for now.. */
-	/*smp_message_pass(MSG_ALL_BUT_SELF, MSG_RESCHEDULE, 0L, 0); */
-	write_sequnlock(&xtime_lock);
+	return (CMOS_READ(RTC_REG_C) & RTC_PF) != 0;
 }
 
-static void r4k_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static void dec_timer_ack(void)
 {
-	unsigned int count;
+	CMOS_READ(RTC_REG_C);			/* Ack the RTC interrupt.  */
+}
 
+static unsigned int dec_ioasic_hpt_read(void)
+{
 	/*
-	 * The cycle counter is only 32 bit which is good for about
-	 * a minute at current count rates of upto 150MHz or so.
+	 * The free-running counter is 32-bit which is good for about
+	 * 2 minutes, 50 seconds at possible count rates of up to 25MHz.
 	 */
-	count = read_c0_count();
-	timerhi += (count < timerlo);	/* Wrap around */
-	timerlo = count;
-
-	if (jiffies == ~0) {
-		/*
-		 * If jiffies is to overflow in this timer_interrupt we must
-		 * update the timer[hi]/[lo] to make do_fast_gettimeoffset()
-		 * quotient calc still valid. -arca
-		 */
-		write_c0_count(0);
-		timerhi = timerlo = 0;
-	}
+	return ioasic_read(IO_REG_FCTR);
+}
 
-	timer_interrupt(irq, dev_id, regs);
+static void dec_ioasic_hpt_init(unsigned int count)
+{
+	ioasic_write(IO_REG_FCTR, ioasic_read(IO_REG_FCTR) - count);
 }
 
-static void ioasic_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+
+void __init dec_time_init(void)
 {
-	unsigned int count;
+	rtc_get_time = dec_rtc_get_time;
+	rtc_set_mmss = dec_rtc_set_mmss;
 
-	/*
-	 * The free-running counter is 32 bit which is good for about
-	 * 2 minutes, 50 seconds at possible count rates of upto 25MHz.
-	 */
-	count = ioasic_read(IO_REG_FCTR);
-	timerhi += (count < timerlo);	/* Wrap around */
-	timerlo = count;
-
-	if (jiffies == ~0) {
-		/*
-		 * If jiffies is to overflow in this timer_interrupt we must
-		 * update the timer[hi]/[lo] to make do_fast_gettimeoffset()
-		 * quotient calc still valid. -arca
-		 */
-		ioasic_write(IO_REG_FCTR, 0);
-		timerhi = timerlo = 0;
+	mips_timer_state = dec_timer_state;
+	mips_timer_ack = dec_timer_ack;
+
+	if (!cpu_has_counter && IOASIC) {
+		/* For pre-R4k systems we use the I/O ASIC's counter.  */
+		mips_hpt_read = dec_ioasic_hpt_read;
+		mips_hpt_init = dec_ioasic_hpt_init;
 	}
 
-	timer_interrupt(irq, dev_id, regs);
+	/* Set up the rate of periodic DS1287 interrupts.  */
+	CMOS_WRITE(RTC_REF_CLCK_32KHZ | (16 - LOG_2_HZ), RTC_REG_A);
 }
 
-struct irqaction irq0 = {
-	.handler = timer_interrupt,
-	.flags = SA_INTERRUPT,
-	.name = "timer",
-};
+EXPORT_SYMBOL(do_settimeofday);
 
-void __init time_init(void)
+void __init dec_timer_setup(struct irqaction *irq)
 {
-	unsigned int year, mon, day, hour, min, sec, real_year;
-	int i;
-
-	/* The Linux interpretation of the CMOS clock register contents:
-	 * When the Update-In-Progress (UIP) flag goes from 1 to 0, the
-	 * RTC registers show the second which has precisely just started.
-	 * Let's hope other operating systems interpret the RTC the same way.
-	 */
-	/* read RTC exactly on falling edge of update flag */
-	for (i = 0; i < 1000000; i++)	/* may take up to 1 second... */
-		if (CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP)
-			break;
-	for (i = 0; i < 1000000; i++)	/* must try at least 2.228 ms */
-		if (!(CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP))
-			break;
-	do {			/* Isn't this overkill ? UIP above should guarantee consistency */
-		sec = CMOS_READ(RTC_SECONDS);
-		min = CMOS_READ(RTC_MINUTES);
-		hour = CMOS_READ(RTC_HOURS);
-		day = CMOS_READ(RTC_DAY_OF_MONTH);
-		mon = CMOS_READ(RTC_MONTH);
-		year = CMOS_READ(RTC_YEAR);
-	} while (sec != CMOS_READ(RTC_SECONDS));
-	if (!(CMOS_READ(RTC_CONTROL) & RTC_DM_BINARY) || RTC_ALWAYS_BCD) {
-		sec = BCD2BIN(sec);
-		min = BCD2BIN(min);
-		hour = BCD2BIN(hour);
-		day = BCD2BIN(day);
-		mon = BCD2BIN(mon);
-		year = BCD2BIN(year);
-	}
-	/*
-	 * The PROM will reset the year to either '72 or '73.
-	 * Therefore we store the real year separately, in one
-	 * of unused BBU RAM locations.
-	 */
-	real_year = CMOS_READ(RTC_DEC_YEAR);
-	year += real_year - 72 + 2000;
+	setup_irq(dec_interrupt[DEC_IRQ_RTC], irq);
 
-	write_seqlock_irq(&xtime_lock);
-	xtime.tv_sec = mktime(year, mon, day, hour, min, sec);
-	xtime.tv_nsec = 0;
-	write_sequnlock_irq(&xtime_lock);
-
-	if (cpu_has_counter) {
-		write_c0_count(0);
-		do_gettimeoffset = do_fast_gettimeoffset;
-		irq0.handler = r4k_timer_interrupt;
-	} else if (IOASIC) {
-		ioasic_write(IO_REG_FCTR, 0);
-		do_gettimeoffset = do_ioasic_gettimeoffset;
-		irq0.handler = ioasic_timer_interrupt;
-        }
-	board_time_init(&irq0);
+	/* Enable periodic DS1287 interrupts.  */
+	CMOS_WRITE(CMOS_READ(RTC_REG_B) | RTC_PIE, RTC_REG_B);
 }
--- diff/arch/mips/defconfig	2003-08-20 14:16:25.000000000 +0100
+++ source/arch/mips/defconfig	2004-02-23 13:56:38.000000000 +0000
@@ -3,12 +3,16 @@
 #
 CONFIG_MIPS=y
 # CONFIG_MIPS64 is not set
+# CONFIG_64BIT is not set
 CONFIG_MIPS32=y
 
 #
 # Code maturity level options
 #
 CONFIG_EXPERIMENTAL=y
+CONFIG_CLEAN_COMPILE=y
+CONFIG_STANDALONE=y
+CONFIG_BROKEN_ON_SMP=y
 
 #
 # General setup
@@ -18,12 +22,16 @@ CONFIG_SYSVIPC=y
 # CONFIG_BSD_PROCESS_ACCT is not set
 CONFIG_SYSCTL=y
 CONFIG_LOG_BUF_SHIFT=14
-# CONFIG_EMBEDDED is not set
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_EMBEDDED=y
 CONFIG_KALLSYMS=y
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
+CONFIG_IOSCHED_NOOP=y
 CONFIG_IOSCHED_AS=y
 CONFIG_IOSCHED_DEADLINE=y
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
 
 #
 # Loadable module support
@@ -38,51 +46,45 @@ CONFIG_KMOD=y
 #
 # Machine selection
 #
-# CONFIG_ACER_PICA_61 is not set
+# CONFIG_MACH_JAZZ is not set
 # CONFIG_BAGET_MIPS is not set
-# CONFIG_CASIO_E55 is not set
+# CONFIG_MACH_VR41XX is not set
+# CONFIG_TOSHIBA_JMR3927 is not set
 # CONFIG_MIPS_COBALT is not set
-# CONFIG_DECSTATION is not set
+# CONFIG_MACH_DECSTATION is not set
 # CONFIG_MIPS_EV64120 is not set
 # CONFIG_MIPS_EV96100 is not set
 # CONFIG_MIPS_IVR is not set
 # CONFIG_LASAT is not set
 # CONFIG_HP_LASERJET is not set
-# CONFIG_IBM_WORKPAD is not set
 # CONFIG_MIPS_ITE8172 is not set
 # CONFIG_MIPS_ATLAS is not set
-# CONFIG_MIPS_MAGNUM_4000 is not set
 # CONFIG_MIPS_MALTA is not set
 # CONFIG_MIPS_SEAD is not set
 # CONFIG_MOMENCO_OCELOT is not set
 # CONFIG_MOMENCO_OCELOT_G is not set
 # CONFIG_MOMENCO_OCELOT_C is not set
+# CONFIG_MOMENCO_JAGUAR_ATX is not set
+# CONFIG_PMC_YOSEMITE is not set
 # CONFIG_DDB5074 is not set
 # CONFIG_DDB5476 is not set
 # CONFIG_DDB5477 is not set
 # CONFIG_NEC_OSPREY is not set
-# CONFIG_NEC_EAGLE is not set
-# CONFIG_OLIVETTI_M700 is not set
 CONFIG_SGI_IP22=y
 # CONFIG_SGI_IP32 is not set
 # CONFIG_SOC_AU1X00 is not set
 # CONFIG_SIBYTE_SB1xxx_SOC is not set
 # CONFIG_SNI_RM200_PCI is not set
-# CONFIG_TANBAC_TB0226 is not set
-# CONFIG_TANBAC_TB0229 is not set
-# CONFIG_TOSHIBA_JMR3927 is not set
 # CONFIG_TOSHIBA_RBTX4927 is not set
-# CONFIG_VICTOR_MPC30X is not set
-# CONFIG_ZAO_CAPCELLA is not set
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_HAVE_DEC_LOCK=y
 CONFIG_ARC=y
-CONFIG_GENERIC_ISA_DMA=y
-CONFIG_NONCOHERENT_IO=y
+CONFIG_DMA_NONCOHERENT=y
 # CONFIG_CPU_LITTLE_ENDIAN is not set
 CONFIG_IRQ_CPU=y
 CONFIG_SWAP_IO_SPACE=y
 CONFIG_BOOT_ELF32=y
-CONFIG_L1_CACHE_SHIFT=5
+CONFIG_MIPS_L1_CACHE_SHIFT=5
 CONFIG_ARC32=y
 # CONFIG_FB is not set
 CONFIG_ARC_CONSOLE=y
@@ -107,7 +109,11 @@ CONFIG_CPU_R5000=y
 # CONFIG_CPU_R8000 is not set
 # CONFIG_CPU_R10000 is not set
 # CONFIG_CPU_RM7000 is not set
+# CONFIG_CPU_RM9000 is not set
 # CONFIG_CPU_SB1 is not set
+CONFIG_PAGE_SIZE_4KB=y
+# CONFIG_PAGE_SIZE_16KB is not set
+# CONFIG_PAGE_SIZE_64KB is not set
 CONFIG_R5000_CPU_SCACHE=y
 # CONFIG_64BIT_PHYS_ADDR is not set
 # CONFIG_CPU_ADVANCED is not set
@@ -127,13 +133,20 @@ CONFIG_MMU=y
 #
 # Executable file formats
 #
-CONFIG_KCORE_ELF=y
 CONFIG_BINFMT_ELF=y
-# CONFIG_BINFMT_MISC is not set
+CONFIG_BINFMT_MISC=m
 CONFIG_TRAD_SIGNALS=y
 CONFIG_BINFMT_IRIX=y
 
 #
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+
+#
 # Memory Technology Devices (MTD)
 #
 # CONFIG_MTD is not set
@@ -146,12 +159,6 @@ CONFIG_BINFMT_IRIX=y
 #
 # Plug and Play support
 #
-# CONFIG_PNP is not set
-
-#
-# Generic Driver Options
-#
-# CONFIG_FW_LOADER is not set
 
 #
 # Block devices
@@ -172,6 +179,7 @@ CONFIG_BINFMT_IRIX=y
 # SCSI device support
 #
 CONFIG_SCSI=y
+CONFIG_SCSI_PROC_FS=y
 
 #
 # SCSI support type (disk, tape, CD-ROM)
@@ -195,9 +203,8 @@ CONFIG_SCSI_CONSTANTS=y
 # SCSI low-level drivers
 #
 CONFIG_SGIWD93_SCSI=y
-# CONFIG_SCSI_AIC7XXX is not set
 # CONFIG_SCSI_AIC7XXX_OLD is not set
-# CONFIG_SCSI_DPT_I2O is not set
+# CONFIG_SCSI_SATA is not set
 # CONFIG_SCSI_EATA_PIO is not set
 # CONFIG_SCSI_DEBUG is not set
 
@@ -212,10 +219,19 @@ CONFIG_SGIWD93_SCSI=y
 # CONFIG_FUSION is not set
 
 #
+# IEEE 1394 (FireWire) support (EXPERIMENTAL)
+#
+# CONFIG_IEEE1394 is not set
+
+#
 # I2O device support
 #
 
 #
+# Macintosh device drivers
+#
+
+#
 # Networking support
 #
 CONFIG_NET=y
@@ -226,7 +242,6 @@ CONFIG_NET=y
 CONFIG_PACKET=y
 CONFIG_PACKET_MMAP=y
 CONFIG_NETLINK_DEV=y
-# CONFIG_NETFILTER is not set
 CONFIG_UNIX=y
 CONFIG_NET_KEY=y
 CONFIG_INET=y
@@ -240,27 +255,156 @@ CONFIG_IP_PNP_BOOTP=y
 # CONFIG_NET_IPGRE is not set
 # CONFIG_IP_MROUTE is not set
 # CONFIG_ARPD is not set
-# CONFIG_INET_ECN is not set
+CONFIG_INET_ECN=y
 # CONFIG_SYN_COOKIES is not set
-# CONFIG_INET_AH is not set
-# CONFIG_INET_ESP is not set
-# CONFIG_INET_IPCOMP is not set
-# CONFIG_IPV6 is not set
-# CONFIG_XFRM_USER is not set
+CONFIG_INET_AH=m
+CONFIG_INET_ESP=m
+CONFIG_INET_IPCOMP=m
+
+#
+# IP: Virtual Server Configuration
+#
+CONFIG_IP_VS=m
+# CONFIG_IP_VS_DEBUG is not set
+CONFIG_IP_VS_TAB_BITS=12
+
+#
+# IPVS transport protocol load balancing support
+#
+CONFIG_IP_VS_PROTO_TCP=y
+CONFIG_IP_VS_PROTO_UDP=y
+CONFIG_IP_VS_PROTO_ESP=y
+CONFIG_IP_VS_PROTO_AH=y
+
+#
+# IPVS scheduler
+#
+CONFIG_IP_VS_RR=m
+CONFIG_IP_VS_WRR=m
+CONFIG_IP_VS_LC=m
+CONFIG_IP_VS_WLC=m
+CONFIG_IP_VS_LBLC=m
+CONFIG_IP_VS_LBLCR=m
+CONFIG_IP_VS_DH=m
+CONFIG_IP_VS_SH=m
+CONFIG_IP_VS_SED=m
+CONFIG_IP_VS_NQ=m
+
+#
+# IPVS application helper
+#
+CONFIG_IP_VS_FTP=m
+CONFIG_IPV6=m
+CONFIG_IPV6_PRIVACY=y
+CONFIG_INET6_AH=m
+CONFIG_INET6_ESP=m
+CONFIG_INET6_IPCOMP=m
+CONFIG_IPV6_TUNNEL=m
+# CONFIG_DECNET is not set
+# CONFIG_BRIDGE is not set
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
+
+#
+# IP: Netfilter Configuration
+#
+CONFIG_IP_NF_CONNTRACK=m
+CONFIG_IP_NF_FTP=m
+CONFIG_IP_NF_IRC=m
+CONFIG_IP_NF_TFTP=m
+CONFIG_IP_NF_AMANDA=m
+CONFIG_IP_NF_QUEUE=m
+CONFIG_IP_NF_IPTABLES=m
+CONFIG_IP_NF_MATCH_LIMIT=m
+CONFIG_IP_NF_MATCH_IPRANGE=m
+CONFIG_IP_NF_MATCH_MAC=m
+CONFIG_IP_NF_MATCH_PKTTYPE=m
+CONFIG_IP_NF_MATCH_MARK=m
+CONFIG_IP_NF_MATCH_MULTIPORT=m
+CONFIG_IP_NF_MATCH_TOS=m
+CONFIG_IP_NF_MATCH_RECENT=m
+CONFIG_IP_NF_MATCH_ECN=m
+CONFIG_IP_NF_MATCH_DSCP=m
+CONFIG_IP_NF_MATCH_AH_ESP=m
+CONFIG_IP_NF_MATCH_LENGTH=m
+CONFIG_IP_NF_MATCH_TTL=m
+CONFIG_IP_NF_MATCH_TCPMSS=m
+CONFIG_IP_NF_MATCH_HELPER=m
+CONFIG_IP_NF_MATCH_STATE=m
+CONFIG_IP_NF_MATCH_CONNTRACK=m
+CONFIG_IP_NF_MATCH_OWNER=m
+CONFIG_IP_NF_FILTER=m
+CONFIG_IP_NF_TARGET_REJECT=m
+CONFIG_IP_NF_NAT=m
+CONFIG_IP_NF_NAT_NEEDED=y
+CONFIG_IP_NF_TARGET_MASQUERADE=m
+CONFIG_IP_NF_TARGET_REDIRECT=m
+CONFIG_IP_NF_TARGET_NETMAP=m
+CONFIG_IP_NF_TARGET_SAME=m
+CONFIG_IP_NF_NAT_LOCAL=y
+CONFIG_IP_NF_NAT_SNMP_BASIC=m
+CONFIG_IP_NF_NAT_IRC=m
+CONFIG_IP_NF_NAT_FTP=m
+CONFIG_IP_NF_NAT_TFTP=m
+CONFIG_IP_NF_NAT_AMANDA=m
+CONFIG_IP_NF_MANGLE=m
+CONFIG_IP_NF_TARGET_TOS=m
+CONFIG_IP_NF_TARGET_ECN=m
+CONFIG_IP_NF_TARGET_DSCP=m
+CONFIG_IP_NF_TARGET_MARK=m
+CONFIG_IP_NF_TARGET_CLASSIFY=m
+CONFIG_IP_NF_TARGET_LOG=m
+CONFIG_IP_NF_TARGET_ULOG=m
+CONFIG_IP_NF_TARGET_TCPMSS=m
+CONFIG_IP_NF_ARPTABLES=m
+CONFIG_IP_NF_ARPFILTER=m
+CONFIG_IP_NF_ARP_MANGLE=m
+CONFIG_IP_NF_COMPAT_IPCHAINS=m
+CONFIG_IP_NF_COMPAT_IPFWADM=m
+
+#
+# IPv6: Netfilter Configuration
+#
+CONFIG_IP6_NF_QUEUE=m
+CONFIG_IP6_NF_IPTABLES=m
+CONFIG_IP6_NF_MATCH_LIMIT=m
+CONFIG_IP6_NF_MATCH_MAC=m
+CONFIG_IP6_NF_MATCH_RT=m
+CONFIG_IP6_NF_MATCH_OPTS=m
+CONFIG_IP6_NF_MATCH_FRAG=m
+CONFIG_IP6_NF_MATCH_HL=m
+CONFIG_IP6_NF_MATCH_MULTIPORT=m
+CONFIG_IP6_NF_MATCH_OWNER=m
+CONFIG_IP6_NF_MATCH_MARK=m
+CONFIG_IP6_NF_MATCH_IPV6HEADER=m
+CONFIG_IP6_NF_MATCH_AHESP=m
+CONFIG_IP6_NF_MATCH_LENGTH=m
+CONFIG_IP6_NF_MATCH_EUI64=m
+CONFIG_IP6_NF_FILTER=m
+CONFIG_IP6_NF_TARGET_LOG=m
+CONFIG_IP6_NF_MANGLE=m
+CONFIG_IP6_NF_TARGET_MARK=m
+CONFIG_XFRM=y
+CONFIG_XFRM_USER=m
 
 #
 # SCTP Configuration (EXPERIMENTAL)
 #
-CONFIG_IPV6_SCTP__=y
-# CONFIG_IP_SCTP is not set
+CONFIG_IPV6_SCTP__=m
+CONFIG_IP_SCTP=m
+# CONFIG_SCTP_DBG_MSG is not set
+# CONFIG_SCTP_DBG_OBJCNT is not set
+# CONFIG_SCTP_HMAC_NONE is not set
+# CONFIG_SCTP_HMAC_SHA1 is not set
+CONFIG_SCTP_HMAC_MD5=y
 # CONFIG_ATM is not set
 # CONFIG_VLAN_8021Q is not set
-# CONFIG_LLC is not set
-# CONFIG_DECNET is not set
-# CONFIG_BRIDGE is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
 # CONFIG_X25 is not set
 # CONFIG_LAPB is not set
-# CONFIG_NET_DIVERT is not set
+CONFIG_NET_DIVERT=y
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
 # CONFIG_NET_FASTROUTE is not set
@@ -269,18 +413,41 @@ CONFIG_IPV6_SCTP__=y
 #
 # QoS and/or fair queueing
 #
-# CONFIG_NET_SCHED is not set
+CONFIG_NET_SCHED=y
+CONFIG_NET_SCH_CBQ=m
+CONFIG_NET_SCH_HTB=m
+CONFIG_NET_SCH_HFSC=m
+CONFIG_NET_SCH_CSZ=m
+CONFIG_NET_SCH_PRIO=m
+CONFIG_NET_SCH_RED=m
+CONFIG_NET_SCH_SFQ=m
+CONFIG_NET_SCH_TEQL=m
+CONFIG_NET_SCH_TBF=m
+CONFIG_NET_SCH_GRED=m
+CONFIG_NET_SCH_DSMARK=m
+CONFIG_NET_SCH_INGRESS=m
+CONFIG_NET_QOS=y
+CONFIG_NET_ESTIMATOR=y
+CONFIG_NET_CLS=y
+CONFIG_NET_CLS_TCINDEX=m
+CONFIG_NET_CLS_ROUTE4=m
+CONFIG_NET_CLS_ROUTE=y
+CONFIG_NET_CLS_FW=m
+CONFIG_NET_CLS_U32=m
+CONFIG_NET_CLS_RSVP=m
+CONFIG_NET_CLS_RSVP6=m
+CONFIG_NET_CLS_POLICE=y
 
 #
 # Network testing
 #
 # CONFIG_NET_PKTGEN is not set
 CONFIG_NETDEVICES=y
-# CONFIG_DUMMY is not set
-# CONFIG_BONDING is not set
-# CONFIG_EQUALIZER is not set
-# CONFIG_TUN is not set
-# CONFIG_ETHERTAP is not set
+CONFIG_DUMMY=m
+CONFIG_BONDING=m
+CONFIG_EQUALIZER=m
+CONFIG_TUN=m
+CONFIG_ETHERTAP=m
 
 #
 # Ethernet (10 or 100Mbit)
@@ -305,7 +472,7 @@ CONFIG_SGISEEQ=y
 # CONFIG_NET_RADIO is not set
 
 #
-# Token Ring devices (depends on LLC=y)
+# Token Ring devices
 #
 # CONFIG_SHAPER is not set
 
@@ -325,6 +492,11 @@ CONFIG_SGISEEQ=y
 # CONFIG_IRDA is not set
 
 #
+# Bluetooth support
+#
+# CONFIG_BT is not set
+
+#
 # ISDN subsystem
 #
 # CONFIG_ISDN_BOOL is not set
@@ -342,7 +514,10 @@ CONFIG_INPUT=y
 #
 # Userland interfaces
 #
-# CONFIG_INPUT_MOUSEDEV is not set
+CONFIG_INPUT_MOUSEDEV=y
+CONFIG_INPUT_MOUSEDEV_PSAUX=y
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
 # CONFIG_INPUT_JOYDEV is not set
 # CONFIG_INPUT_TSDEV is not set
 # CONFIG_INPUT_EVDEV is not set
@@ -387,27 +562,12 @@ CONFIG_HW_CONSOLE=y
 #
 # Non-8250 serial port support
 #
-CONFIG_SERIAL_IP22_ZILOG=y
-CONFIG_SERIAL_CORE=y
-CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_SERIAL_IP22_ZILOG=m
+CONFIG_SERIAL_CORE=m
 CONFIG_UNIX98_PTYS=y
 CONFIG_UNIX98_PTY_COUNT=256
 
 #
-# I2C support
-#
-# CONFIG_I2C is not set
-
-#
-# I2C Hardware Sensors Mainboard support
-#
-
-#
-# I2C Hardware Sensors Chip support
-#
-# CONFIG_I2C_SENSOR is not set
-
-#
 # Mice
 #
 # CONFIG_BUSMOUSE is not set
@@ -423,27 +583,12 @@ CONFIG_UNIX98_PTY_COUNT=256
 #
 CONFIG_WATCHDOG=y
 # CONFIG_WATCHDOG_NOWAYOUT is not set
+
+#
+# Watchdog Device Drivers
+#
 # CONFIG_SOFT_WATCHDOG is not set
-# CONFIG_WDT is not set
-# CONFIG_WDTPCI is not set
-# CONFIG_PCWATCHDOG is not set
-# CONFIG_ACQUIRE_WDT is not set
-# CONFIG_ADVANTECH_WDT is not set
-# CONFIG_EUROTECH_WDT is not set
-# CONFIG_IB700_WDT is not set
-# CONFIG_I810_TCO is not set
-# CONFIG_MIXCOMWD is not set
-# CONFIG_SCx200_WDT is not set
-# CONFIG_60XX_WDT is not set
-# CONFIG_W83877F_WDT is not set
-# CONFIG_MACHZ_WDT is not set
-CONFIG_INDYDOG=y
-# CONFIG_SC520_WDT is not set
-# CONFIG_AMD7XX_TCO is not set
-# CONFIG_ALIM7101_WDT is not set
-# CONFIG_SC1200_WDT is not set
-# CONFIG_WAFER_WDT is not set
-# CONFIG_CPU5_WDT is not set
+CONFIG_INDYDOG=m
 # CONFIG_NVRAM is not set
 # CONFIG_RTC is not set
 # CONFIG_GEN_RTC is not set
@@ -458,8 +603,13 @@ CONFIG_SGI_DS1286=y
 # CONFIG_FTAPE is not set
 # CONFIG_AGP is not set
 # CONFIG_DRM is not set
-# CONFIG_RAW_DRIVER is not set
-# CONFIG_HANGCHECK_TIMER is not set
+CONFIG_RAW_DRIVER=m
+CONFIG_MAX_RAW_DEVS=256
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
 
 #
 # Multimedia devices
@@ -472,9 +622,46 @@ CONFIG_SGI_DS1286=y
 # CONFIG_DVB is not set
 
 #
+# Graphics support
+#
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+# CONFIG_MDA_CONSOLE is not set
+CONFIG_SGI_NEWPORT_CONSOLE=y
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_FONT_8x16=y
+
+#
+# Logo configuration
+#
+CONFIG_LOGO=y
+# CONFIG_LOGO_LINUX_MONO is not set
+# CONFIG_LOGO_LINUX_VGA16 is not set
+# CONFIG_LOGO_LINUX_CLUT224 is not set
+CONFIG_LOGO_SGI_CLUT224=y
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
 # File systems
 #
-# CONFIG_EXT2_FS is not set
+CONFIG_EXT2_FS=m
+# CONFIG_EXT2_FS_XATTR is not set
 CONFIG_EXT3_FS=y
 CONFIG_EXT3_FS_XATTR=y
 CONFIG_EXT3_FS_POSIX_ACL=y
@@ -485,36 +672,48 @@ CONFIG_FS_MBCACHE=y
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
 CONFIG_FS_POSIX_ACL=y
-# CONFIG_XFS_FS is not set
-# CONFIG_MINIX_FS is not set
+CONFIG_XFS_FS=m
+# CONFIG_XFS_RT is not set
+CONFIG_XFS_QUOTA=y
+CONFIG_XFS_SECURITY=y
+# CONFIG_XFS_POSIX_ACL is not set
+CONFIG_MINIX_FS=m
 # CONFIG_ROMFS_FS is not set
-# CONFIG_QUOTA is not set
-CONFIG_AUTOFS_FS=y
-CONFIG_AUTOFS4_FS=y
+CONFIG_QUOTA=y
+# CONFIG_QFMT_V1 is not set
+CONFIG_QFMT_V2=m
+CONFIG_QUOTACTL=y
+CONFIG_AUTOFS_FS=m
+CONFIG_AUTOFS4_FS=m
 
 #
 # CD-ROM/DVD Filesystems
 #
-CONFIG_ISO9660_FS=y
-# CONFIG_JOLIET is not set
-# CONFIG_ZISOFS is not set
-# CONFIG_UDF_FS is not set
+CONFIG_ISO9660_FS=m
+CONFIG_JOLIET=y
+CONFIG_ZISOFS=y
+CONFIG_ZISOFS_FS=m
+CONFIG_UDF_FS=m
 
 #
 # DOS/FAT/NT Filesystems
 #
-# CONFIG_FAT_FS is not set
+CONFIG_FAT_FS=m
+CONFIG_MSDOS_FS=m
+CONFIG_VFAT_FS=m
 # CONFIG_NTFS_FS is not set
 
 #
 # Pseudo filesystems
 #
 CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
 # CONFIG_DEVFS_FS is not set
 CONFIG_DEVPTS_FS=y
 CONFIG_DEVPTS_FS_XATTR=y
 CONFIG_DEVPTS_FS_SECURITY=y
 # CONFIG_TMPFS is not set
+# CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
 
 #
@@ -525,27 +724,30 @@ CONFIG_RAMFS=y
 # CONFIG_HFS_FS is not set
 # CONFIG_BEFS_FS is not set
 # CONFIG_BFS_FS is not set
-# CONFIG_EFS_FS is not set
+CONFIG_EFS_FS=m
 # CONFIG_CRAMFS is not set
 # CONFIG_VXFS_FS is not set
 # CONFIG_HPFS_FS is not set
 # CONFIG_QNX4FS_FS is not set
 # CONFIG_SYSV_FS is not set
-# CONFIG_UFS_FS is not set
+CONFIG_UFS_FS=m
+# CONFIG_UFS_FS_WRITE is not set
 
 #
 # Network File Systems
 #
-CONFIG_NFS_FS=y
-# CONFIG_NFS_V3 is not set
+CONFIG_NFS_FS=m
+CONFIG_NFS_V3=y
 # CONFIG_NFS_V4 is not set
-CONFIG_NFSD=y
-# CONFIG_NFSD_V3 is not set
-# CONFIG_NFSD_TCP is not set
-CONFIG_ROOT_NFS=y
-CONFIG_LOCKD=y
-CONFIG_EXPORTFS=y
-CONFIG_SUNRPC=y
+# CONFIG_NFS_DIRECTIO is not set
+CONFIG_NFSD=m
+CONFIG_NFSD_V3=y
+# CONFIG_NFSD_V4 is not set
+CONFIG_NFSD_TCP=y
+CONFIG_LOCKD=m
+CONFIG_LOCKD_V4=y
+CONFIG_EXPORTFS=m
+CONFIG_SUNRPC=m
 # CONFIG_SUNRPC_GSS is not set
 # CONFIG_SMB_FS is not set
 # CONFIG_CIFS is not set
@@ -576,46 +778,53 @@ CONFIG_SGI_PARTITION=y
 # CONFIG_EFI_PARTITION is not set
 
 #
-# Graphics support
+# Native Language Support
 #
-
-#
-# Console display driver support
-#
-# CONFIG_VGA_CONSOLE is not set
-# CONFIG_MDA_CONSOLE is not set
-CONFIG_SGI_NEWPORT_CONSOLE=y
-CONFIG_DUMMY_CONSOLE=y
-CONFIG_FONT_8x16=y
-
-#
-# Logo configuration
-#
-CONFIG_LOGO=y
-# CONFIG_LOGO_LINUX_MONO is not set
-# CONFIG_LOGO_LINUX_VGA16 is not set
-# CONFIG_LOGO_LINUX_CLUT224 is not set
-CONFIG_LOGO_SGI_CLUT224=y
-
-#
-# Sound
-#
-# CONFIG_SOUND is not set
-
-#
-# USB support
-#
-# CONFIG_USB_GADGET is not set
-
-#
-# Bluetooth support
-#
-# CONFIG_BT is not set
+CONFIG_NLS=m
+CONFIG_NLS_DEFAULT="iso8859-1"
+CONFIG_NLS_CODEPAGE_437=m
+CONFIG_NLS_CODEPAGE_737=m
+CONFIG_NLS_CODEPAGE_775=m
+CONFIG_NLS_CODEPAGE_850=m
+CONFIG_NLS_CODEPAGE_852=m
+CONFIG_NLS_CODEPAGE_855=m
+CONFIG_NLS_CODEPAGE_857=m
+CONFIG_NLS_CODEPAGE_860=m
+CONFIG_NLS_CODEPAGE_861=m
+CONFIG_NLS_CODEPAGE_862=m
+CONFIG_NLS_CODEPAGE_863=m
+CONFIG_NLS_CODEPAGE_864=m
+CONFIG_NLS_CODEPAGE_865=m
+CONFIG_NLS_CODEPAGE_866=m
+CONFIG_NLS_CODEPAGE_869=m
+CONFIG_NLS_CODEPAGE_936=m
+CONFIG_NLS_CODEPAGE_950=m
+CONFIG_NLS_CODEPAGE_932=m
+CONFIG_NLS_CODEPAGE_949=m
+CONFIG_NLS_CODEPAGE_874=m
+CONFIG_NLS_ISO8859_8=m
+CONFIG_NLS_CODEPAGE_1250=m
+CONFIG_NLS_CODEPAGE_1251=m
+CONFIG_NLS_ISO8859_1=m
+CONFIG_NLS_ISO8859_2=m
+CONFIG_NLS_ISO8859_3=m
+CONFIG_NLS_ISO8859_4=m
+CONFIG_NLS_ISO8859_5=m
+CONFIG_NLS_ISO8859_6=m
+CONFIG_NLS_ISO8859_7=m
+CONFIG_NLS_ISO8859_9=m
+CONFIG_NLS_ISO8859_13=m
+CONFIG_NLS_ISO8859_14=m
+CONFIG_NLS_ISO8859_15=m
+CONFIG_NLS_KOI8_R=m
+CONFIG_NLS_KOI8_U=m
+CONFIG_NLS_UTF8=m
 
 #
 # Kernel hacking
 #
 CONFIG_CROSSCOMPILE=y
+CONFIG_CMDLINE=""
 # CONFIG_DEBUG_KERNEL is not set
 
 #
@@ -639,6 +848,8 @@ CONFIG_CRYPTO_BLOWFISH=y
 CONFIG_CRYPTO_TWOFISH=y
 CONFIG_CRYPTO_SERPENT=y
 CONFIG_CRYPTO_AES=y
+CONFIG_CRYPTO_CAST5=m
+CONFIG_CRYPTO_CAST6=m
 CONFIG_CRYPTO_DEFLATE=y
 # CONFIG_CRYPTO_TEST is not set
 
--- diff/arch/mips/galileo-boards/ev96100/Makefile	2003-07-08 09:55:17.000000000 +0100
+++ source/arch/mips/galileo-boards/ev96100/Makefile	2004-02-23 13:56:38.000000000 +0000
@@ -6,6 +6,4 @@
 # Makefile for the Galileo EV96100 board.
 #
 
-obj-y		+= init.o time.o irq.o int-handler.o setup.o puts.o
-
-EXTRA_AFLAGS := $(CFLAGS)
+obj-y		+= init.o irq.o puts.o reset.o time.o int-handler.o setup.o
--- diff/arch/mips/galileo-boards/ev96100/init.c	2003-07-08 09:55:17.000000000 +0100
+++ source/arch/mips/galileo-boards/ev96100/init.c	2004-02-23 13:56:38.000000000 +0000
@@ -33,13 +33,12 @@
 #include <linux/mm.h>
 #include <linux/sched.h>
 #include <linux/bootmem.h>
-#include <asm/addrspace.h>
-#include <asm/bootinfo.h>
 #include <linux/string.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 
-#include <asm/galileo-boards/ev96100.h>
+#include <asm/addrspace.h>
+#include <asm/bootinfo.h>
+#include <asm/gt64120.h>
 
 
 /* Environment variable */
@@ -51,7 +50,6 @@ typedef struct {
 
 int prom_argc;
 char **prom_argv, **prom_envp;
-char arcs_cmdline[CL_SIZE];
 
 int init_debug = 0;
 
@@ -60,8 +58,9 @@ char * __init prom_getcmdline(void)
 	return &(arcs_cmdline[0]);
 }
 
-void prom_free_prom_memory (void)
+unsigned long __init prom_free_prom_memory(void)
 {
+	return 0;
 }
 
 void  __init prom_init_cmdline(void)
@@ -155,14 +154,14 @@ const char *get_system_type(void)
 	return "Galileo EV96100";
 }
 
-void __init prom_init(int argc, char **argv, char **envp, int *prom_vec)
+void __init prom_init(void)
 {
 	volatile unsigned char *uart;
 	char ppbuf[8];
 
-	prom_argc = argc;
-	prom_argv = argv;
-	prom_envp = envp;
+	prom_argc = fw_arg0;
+	prom_argv = (char **) fw_arg1;
+	prom_envp = (char **) fw_arg2;
 
 	mips_machgroup = MACH_GROUP_GALILEO;
 	mips_machtype = MACH_EV96100;
--- diff/arch/mips/galileo-boards/ev96100/int-handler.S	2003-07-08 09:55:17.000000000 +0100
+++ source/arch/mips/galileo-boards/ev96100/int-handler.S	2004-02-23 13:56:38.000000000 +0000
@@ -23,8 +23,9 @@ NESTED(ev96100IRQ, PT_SIZE, sp)
 	j	ret_from_irq
 
 1:	beqz	t0, 3f			# spurious interrupt
+
 	move	a0, t0
-	move	a1, sp			# delay slot
+	move	a1, sp
 	jal	ev96100_cpu_irq
 	j	ret_from_irq
 
--- diff/arch/mips/galileo-boards/ev96100/irq.c	2003-07-08 09:55:17.000000000 +0100
+++ source/arch/mips/galileo-boards/ev96100/irq.c	2004-02-23 13:56:38.000000000 +0000
@@ -38,55 +38,10 @@
 #include <linux/sched.h>
 #include <linux/types.h>
 #include <linux/interrupt.h>
-#include <linux/ioport.h>
-#include <linux/timex.h>
-#include <linux/slab.h>
-#include <linux/random.h>
-
-#include <asm/bitops.h>
-#include <asm/bootinfo.h>
-#include <asm/io.h>
-#include <asm/mipsregs.h>
-#include <asm/system.h>
-#include <asm/galileo-boards/ev96100int.h>
+#include <asm/irq_cpu.h>
 
-extern void mips_timer_interrupt(int irq, struct pt_regs *regs);
 extern asmlinkage void ev96100IRQ(void);
 
-static void disable_ev96100_irq(unsigned int irq_nr)
-{
-	unsigned long flags;
-
-	local_irq_save(flags);
-	clear_c0_status(0x100 << irq_nr);
-	local_irq_restore(flags);
-}
-
-static inline void enable_ev96100_irq(unsigned int irq_nr)
-{
-	unsigned long flags;
-
-	local_irq_save(flags);
-	set_c0_status(0x100 << irq_nr);
-	local_irq_restore(flags);
-}
-
-static unsigned int startup_ev96100_irq(unsigned int irq)
-{
-	enable_ev96100_irq(irq);
-
-	return 0;	/* never anything pending */
-}
-
-#define shutdown_ev96100_irq		disable_ev96100_irq
-#define mask_and_ack_ev96100_irq	disable_ev96100_irq
-
-static void end_ev96100_irq (unsigned int irq)
-{
-	if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
-		enable_ev96100_irq(irq);
-}
-
 static inline unsigned int ffz8(unsigned int word)
 {
 	unsigned long k;
@@ -99,35 +54,14 @@ static inline unsigned int ffz8(unsigned
 	return k;
 }
 
-asmlinkage void ev96100_cpu_irq(unsigned long cause, struct pt_regs * regs)
+asmlinkage void ev96100_cpu_irq(unsigned int pendin)
 {
-	if (!(cause & 0xff00))
-		return;
-
-	do_IRQ(ffz8((cause >> 8) & 0xff), regs);
+	do_IRQ(ffz8(pending >> 8), regs);
 }
 
-static struct hw_interrupt_type ev96100_irq_type = {
-	"EV96100",
-	startup_ev96100_irq,
-	shutdown_ev96100_irq,
-	enable_ev96100_irq,
-	disable_ev96100_irq,
-	mask_and_ack_ev96100_irq,
-	end_ev96100_irq
-};
-
 void __init init_IRQ(void)
 {
-	int i;
-
 	set_except_vector(0, ev96100IRQ);
 	init_generic_irq();
-
-	for (i = 0; i < 8; i++) {
-		irq_desc[i].status	= IRQ_DISABLED;
-		irq_desc[i].action	= 0;
-		irq_desc[i].depth	= 1;
-		irq_desc[i].handler	= &ev96100_irq_type;
-	}
+	mips_cpu_irq_init(0);
 }
--- diff/arch/mips/galileo-boards/ev96100/puts.c	2003-07-08 09:55:17.000000000 +0100
+++ source/arch/mips/galileo-boards/ev96100/puts.c	2004-02-23 13:56:38.000000000 +0000
@@ -4,7 +4,7 @@
  */
 
 #include <linux/types.h>
-#include <asm/galileo-boards/ev96100.h>
+#include <asm/gt64120.h>
 
 
 //#define SERIAL_BASE    EV96100_UART0_REGS_BASE
@@ -22,123 +22,117 @@
 #undef SLOW_DOWN
 
 static const char digits[16] = "0123456789abcdef";
-static volatile unsigned char * const com1 = (unsigned char *)SERIAL_BASE;
+static volatile unsigned char *const com1 = (unsigned char *) SERIAL_BASE;
 
 
 #ifdef SLOW_DOWN
 static inline void slow_down()
 {
-    int k;
-    for (k=0; k<10000; k++);
+	int k;
+	for (k = 0; k < 10000; k++);
 }
 #else
 #define slow_down()
 #endif
 
-void
-putch(const unsigned char c)
+void putch(const unsigned char c)
 {
-    unsigned char ch;
-    int i = 0;
+	unsigned char ch;
+	int i = 0;
 
-    do {
-        ch = com1[SERB_CMD];
-        slow_down();
-        i++;
-        if (i>TIMEOUT) {
-            break;
-        }
-    } while (0 == (ch & TX_BUSY));
-    com1[SERB_DATA] = c;
-}
-
-void
-putchar(const unsigned char c)
-{
-    unsigned char ch;
-    int i = 0;
-
-    do {
-        ch = com1[SERB_CMD];
-        slow_down();
-        i++;
-        if (i>TIMEOUT) {
-            break;
-        }
-    } while (0 == (ch & TX_BUSY));
-    com1[SERB_DATA] = c;
-}
-
-void
-puts(unsigned char *cp)
-{
-    unsigned char ch;
-    int i = 0;
-
-    while (*cp) {
-        do {
-             ch = com1[SERB_CMD];
-            slow_down();
-            i++;
-            if (i>TIMEOUT) {
-                break;
-            }
-        } while (0 == (ch & TX_BUSY));
-        com1[SERB_DATA] = *cp++;
-    }
-    putch('\r');
-    putch('\n');
-}
-
-void
-fputs(unsigned char *cp)
-{
-    unsigned char ch;
-    int i = 0;
-
-    while (*cp) {
-
-        do {
-             ch = com1[SERB_CMD];
-             slow_down();
-            i++;
-            if (i>TIMEOUT) {
-                break;
-            }
-        } while (0 == (ch & TX_BUSY));
-        com1[SERB_DATA] = *cp++;
-    }
-}
-
-
-void
-put64(uint64_t ul)
-{
-    int cnt;
-    unsigned ch;
-
-    cnt = 16;            /* 16 nibbles in a 64 bit long */
-    putch('0');
-    putch('x');
-    do {
-        cnt--;
-        ch = (unsigned char)(ul >> cnt * 4) & 0x0F;
-                putch(digits[ch]);
-    } while (cnt > 0);
-}
-
-void
-put32(unsigned u)
-{
-    int cnt;
-    unsigned ch;
-
-    cnt = 8;            /* 8 nibbles in a 32 bit long */
-    putch('0');
-    putch('x');
-    do {
-        cnt--;
-        ch = (unsigned char)(u >> cnt * 4) & 0x0F;
-                putch(digits[ch]);
-    } while (cnt > 0);
+	do {
+		ch = com1[SERB_CMD];
+		slow_down();
+		i++;
+		if (i > TIMEOUT) {
+			break;
+		}
+	} while (0 == (ch & TX_BUSY));
+	com1[SERB_DATA] = c;
+}
+
+void putchar(const unsigned char c)
+{
+	unsigned char ch;
+	int i = 0;
+
+	do {
+		ch = com1[SERB_CMD];
+		slow_down();
+		i++;
+		if (i > TIMEOUT) {
+			break;
+		}
+	} while (0 == (ch & TX_BUSY));
+	com1[SERB_DATA] = c;
+}
+
+void puts(unsigned char *cp)
+{
+	unsigned char ch;
+	int i = 0;
+
+	while (*cp) {
+		do {
+			ch = com1[SERB_CMD];
+			slow_down();
+			i++;
+			if (i > TIMEOUT) {
+				break;
+			}
+		} while (0 == (ch & TX_BUSY));
+		com1[SERB_DATA] = *cp++;
+	}
+	putch('\r');
+	putch('\n');
+}
+
+void fputs(unsigned char *cp)
+{
+	unsigned char ch;
+	int i = 0;
+
+	while (*cp) {
+
+		do {
+			ch = com1[SERB_CMD];
+			slow_down();
+			i++;
+			if (i > TIMEOUT) {
+				break;
+			}
+		} while (0 == (ch & TX_BUSY));
+		com1[SERB_DATA] = *cp++;
+	}
+}
+
+
+void put64(uint64_t ul)
+{
+	int cnt;
+	unsigned ch;
+
+	cnt = 16;		/* 16 nibbles in a 64 bit long */
+	putch('0');
+	putch('x');
+	do {
+		cnt--;
+		ch = (unsigned char) (ul >> cnt * 4) & 0x0F;
+		putch(digits[ch]);
+	} while (cnt > 0);
+}
+
+void put32(unsigned u)
+{
+	int cnt;
+	unsigned ch;
+
+	cnt = 8;		/* 8 nibbles in a 32 bit long */
+	putch('0');
+	putch('x');
+	do {
+		cnt--;
+		ch = (unsigned char) (u >> cnt * 4) & 0x0F;
+		putch(digits[ch]);
+	} while (cnt > 0);
 }
--- diff/arch/mips/galileo-boards/ev96100/setup.c	2003-07-08 09:55:17.000000000 +0100
+++ source/arch/mips/galileo-boards/ev96100/setup.c	2004-02-23 13:56:38.000000000 +0000
@@ -36,13 +36,9 @@
 #include <linux/init.h>
 #include <linux/sched.h>
 #include <linux/ioport.h>
-#include <linux/mc146818rtc.h>
 #include <linux/string.h>
 #include <linux/ctype.h>
 #include <linux/pci.h>
-#include <linux/major.h>
-#include <linux/kdev_t.h>
-#include <linux/root_dev.h>
 
 #include <asm/cpu.h>
 #include <asm/bootinfo.h>
@@ -50,86 +46,44 @@
 #include <asm/irq.h>
 #include <asm/delay.h>
 #include <asm/gt64120.h>
-#include <asm/galileo-boards/ev96100.h>
 #include <asm/galileo-boards/ev96100int.h>
 
 
-#if defined(CONFIG_SERIAL_CONSOLE) || defined(CONFIG_PROM_CONSOLE)
-extern void console_setup(char *, int *);
-char serial_console[20];
-#endif
-
-extern char * __init prom_getcmdline(void);
+extern char *__init prom_getcmdline(void);
 
 extern void mips_reboot_setup(void);
-extern struct rtc_ops no_rtc_ops;
-extern struct resource ioport_resource;
 
 unsigned char mac_0_1[12];
 
-void __init ev96100_setup(void)
+static void __init ev96100_setup(void)
 {
-	unsigned long config = read_c0_config();
-	unsigned long status = read_c0_status();
-	unsigned long info = read_c0_info();
+	unsigned int config = read_c0_config();
+	unsigned int status = read_c0_status();
+	unsigned int info = read_c0_info();
 	u32 tmp;
 
 	char *argptr;
 
 	clear_c0_status(ST0_FR);
 
-        if (config & 0x8) {
-            printk("Secondary cache is enabled\n");
-        }
-        else {
-            printk("Secondary cache is disabled\n");
-        }
-
-        if (status & (1<<27)) {
-            printk("User-mode cache ops enabled\n");
-        }
-        else {
-            printk("User-mode cache ops disabled\n");
-        }
-
-        printk("CP0 info reg: %x\n", (unsigned)info);
-        if (info & (1<<28)) {
-            printk("burst mode Scache RAMS\n");
-        }
-        else {
-            printk("pipelined Scache RAMS\n");
-        }
-
-        if ((info & (0x3<<26)) >> 26 == 0) {
-            printk("67 percent drive strength\n");
-        }
-        else if ((info & (0x3<<26)) >> 26 == 1) {
-            printk("50 percent drive strength\n");
-        }
-        else if ((info & (0x3<<26)) >> 26 == 2) {
-            printk("100 percent drive strength\n");
-        }
-        else if ((info & (0x3<<26)) >> 26 == 3) {
-            printk("83 percent drive strength\n");
-        }
-
-
-        if ((info & (0x3<<23)) >> 23 == 0) {
-            printk("Write Protocol: R4000 compatible\n");
-        }
-        else if ((info & (0x3<<23)) >> 23 == 1) {
-            printk("Write Protocol: Reserved\n");
-        }
-        else if ((info & (0x3<<23)) >> 23 == 2) {
-            printk("Write Protocol: Pipelined\n");
-        }
-        else if ((info & (0x3<<23)) >> 23 == 3) {
-            printk("Write Protocol: Write re-issue\n");
-        }
-
-        if (info & 0x1) {
-            printk("Atomic Enable is set\n");
-        }
+	if (config & 0x8)
+		printk("Secondary cache is enabled\n");
+	else
+		printk("Secondary cache is disabled\n");
+
+	if (status & (1 << 27))
+		printk("User-mode cache ops enabled\n");
+	else
+		printk("User-mode cache ops disabled\n");
+
+	printk("CP0 info reg: %x\n", (unsigned) info);
+	if (info & (1 << 28))
+		printk("burst mode Scache RAMS\n");
+	else
+		printk("pipelined Scache RAMS\n");
+
+	if (info & 0x1)
+		printk("Atomic Enable is set\n");
 
 	argptr = prom_getcmdline();
 #ifdef CONFIG_SERIAL_CONSOLE
@@ -139,68 +93,70 @@ void __init ev96100_setup(void)
 	}
 #endif
 
-	rtc_ops = &no_rtc_ops;
 	mips_reboot_setup();
+
 	set_io_port_base(KSEG1);
 	ioport_resource.start = GT_PCI_IO_BASE;
-	ioport_resource.end   = GT_PCI_IO_BASE + 0x01ffffff;
+	ioport_resource.end = GT_PCI_IO_BASE + 0x01ffffff;
 
 #ifdef CONFIG_BLK_DEV_INITRD
-	ROOT_DEV = Root_RAM0;
+	ROOT_DEV = MKDEV(RAMDISK_MAJOR, 0);
 #endif
 
 
 	/*
-	 * setup gt controller master bit so we can do config cycles
+	 * Setup GT controller master bit so we can do config cycles
 	 */
 
 	/* Clear cause register bits */
 	GT_WRITE(GT_INTRCAUSE_OFS, ~(GT_INTRCAUSE_MASABORT0_BIT |
-	                             GT_INTRCAUSE_TARABORT0_BIT));
+				     GT_INTRCAUSE_TARABORT0_BIT));
 	/* Setup address */
 	GT_WRITE(GT_PCI0_CFGADDR_OFS,
-		 (0      << GT_PCI0_CFGADDR_BUSNUM_SHF)   |
-		 (0      << GT_PCI0_CFGADDR_FUNCTNUM_SHF) |
-		 ((PCI_COMMAND / 4) << GT_PCI0_CFGADDR_REGNUM_SHF)   |
+		 (0 << GT_PCI0_CFGADDR_BUSNUM_SHF) |
+		 (0 << GT_PCI0_CFGADDR_FUNCTNUM_SHF) |
+		 ((PCI_COMMAND / 4) << GT_PCI0_CFGADDR_REGNUM_SHF) |
 		 GT_PCI0_CFGADDR_CONFIGEN_BIT);
 
 	udelay(2);
-	tmp = le32_to_cpu(*(volatile u32 *)(MIPS_GT_BASE+GT_PCI0_CFGDATA_OFS));
+	tmp = GT_READ(GT_PCI0_CFGDATA_OFS);
 
 	tmp |= (PCI_COMMAND_IO | PCI_COMMAND_MEMORY |
 		PCI_COMMAND_MASTER | PCI_COMMAND_SERR);
 	GT_WRITE(GT_PCI0_CFGADDR_OFS,
-		 (0      << GT_PCI0_CFGADDR_BUSNUM_SHF)   |
-		 (0      << GT_PCI0_CFGADDR_FUNCTNUM_SHF) |
-		 ((PCI_COMMAND / 4) << GT_PCI0_CFGADDR_REGNUM_SHF)   |
+		 (0 << GT_PCI0_CFGADDR_BUSNUM_SHF) |
+		 (0 << GT_PCI0_CFGADDR_FUNCTNUM_SHF) |
+		 ((PCI_COMMAND / 4) << GT_PCI0_CFGADDR_REGNUM_SHF) |
 		 GT_PCI0_CFGADDR_CONFIGEN_BIT);
 	udelay(2);
-	*(volatile u32 *)(MIPS_GT_BASE+GT_PCI0_CFGDATA_OFS) = cpu_to_le32(tmp);
+	GT_WRITE(GT_PCI0_CFGDATA_OFS, tmp);
 
 	/* Setup address */
 	GT_WRITE(GT_PCI0_CFGADDR_OFS,
-		 (0      << GT_PCI0_CFGADDR_BUSNUM_SHF)   |
-		 (0      << GT_PCI0_CFGADDR_FUNCTNUM_SHF) |
-		 ((PCI_COMMAND / 4) << GT_PCI0_CFGADDR_REGNUM_SHF)   |
+		 (0 << GT_PCI0_CFGADDR_BUSNUM_SHF) |
+		 (0 << GT_PCI0_CFGADDR_FUNCTNUM_SHF) |
+		 ((PCI_COMMAND / 4) << GT_PCI0_CFGADDR_REGNUM_SHF) |
 		 GT_PCI0_CFGADDR_CONFIGEN_BIT);
 
 	udelay(2);
-	tmp = le32_to_cpu(*(volatile u32 *)(MIPS_GT_BASE+GT_PCI0_CFGDATA_OFS));
+	tmp = GT_READ(GT_PCI0_CFGDATA_OFS);
 }
 
+early_initcall(ev96100_setup);
+
 unsigned short get_gt_devid(void)
 {
 	u32 gt_devid;
 
 	/* Figure out if this is a gt96100 or gt96100A */
 	GT_WRITE(GT_PCI0_CFGADDR_OFS,
-		 (0      << GT_PCI0_CFGADDR_BUSNUM_SHF)   |
-		 (0      << GT_PCI0_CFGADDR_FUNCTNUM_SHF) |
-		 ((PCI_VENDOR_ID / 4) << GT_PCI0_CFGADDR_REGNUM_SHF)   |
+		 (0 << GT_PCI0_CFGADDR_BUSNUM_SHF) |
+		 (0 << GT_PCI0_CFGADDR_FUNCTNUM_SHF) |
+		 ((PCI_VENDOR_ID / 4) << GT_PCI0_CFGADDR_REGNUM_SHF) |
 		 GT_PCI0_CFGADDR_CONFIGEN_BIT);
 
 	udelay(4);
-	gt_devid = le32_to_cpu(*(volatile u32 *)
-			(MIPS_GT_BASE+GT_PCI0_CFGDATA_OFS));
-	return (unsigned short)(gt_devid>>16);
+	gt_devid = GT_READ(GT_PCI0_CFGDATA_OFS);
+
+	return gt_devid >> 16;
 }
--- diff/arch/mips/galileo-boards/ev96100/time.c	2003-10-09 09:47:33.000000000 +0100
+++ source/arch/mips/galileo-boards/ev96100/time.c	2004-02-23 13:56:38.000000000 +0000
@@ -37,11 +37,11 @@
 #include <linux/module.h>
 #include <linux/sched.h>
 #include <linux/spinlock.h>
+#include <linux/timex.h>
 
 #include <asm/mipsregs.h>
 #include <asm/ptrace.h>
-
-#include <linux/timex.h>
+#include <asm/time.h>
 
 
 #define ALLINTS (IE_IRQ0 | IE_IRQ1 | IE_IRQ2 | IE_IRQ3 | IE_IRQ4 | IE_IRQ5)
@@ -57,202 +57,6 @@ static inline void ack_r4ktimer(unsigned
 	write_c0_compare(newval);
 }
 
-static int set_rtc_mmss(unsigned long nowtime)
-{
-    /* EV96100 does not have a real time clock */
-    int retval = 0;
-
-    return retval;
-}
-
-
-
-/*
- * Figure out the r4k offset, the amount to increment the compare
- * register for each time tick.
- * Use the RTC to calculate offset.
- */
-static unsigned long __init cal_r4koff(void)
-{
-	unsigned long count;
-        count = 300000000/2;
-	return (count / HZ);
-}
-
-
-static unsigned long __init get_mips_time(void)
-{
-	unsigned int year, mon, day, hour, min, sec;
-
-        year = 2000;
-        mon = 10;
-        day = 31;
-        hour = 0;
-        min = 0;
-        sec = 0;
-	return mktime(year, mon, day, hour, min, sec);
-}
-
-
-/*
- * called from start_kernel()
- */
-void __init time_init(void)
-{
-
-        unsigned int est_freq;
-
-	r4k_offset = cal_r4koff();
-
-	est_freq = 2*r4k_offset*HZ;
-	est_freq += 5000;    /* round */
-	est_freq -= est_freq%10000;
-	printk("CPU frequency %d.%02d MHz\n", est_freq/1000000,
-	       (est_freq%1000000)*100/1000000);
-	r4k_cur = (read_c0_count() + r4k_offset);
-
-	write_c0_compare(r4k_cur);
-
-	change_c0_status(ST0_IM, IE_IRQ5);		/* FIX ME */
-}
-
-/* This is for machines which generate the exact clock. */
-#define USECS_PER_JIFFY (1000000/HZ)
-
-/* Cycle counter value at the previous timer interrupt.. */
-
-static unsigned int timerhi = 0, timerlo = 0;
-
-/*
- * FIXME: Does playing with the RP bit in c0_status interfere with this code?
- */
-static unsigned long do_fast_gettimeoffset(void)
-{
-	u32 count;
-	unsigned long res, tmp;
-
-	/* Last jiffy when do_fast_gettimeoffset() was called. */
-	static unsigned long last_jiffies=0;
-	unsigned long quotient;
-
-	/*
-	 * Cached "1/(clocks per usec)*2^32" value.
-	 * It has to be recalculated once each jiffy.
-	 */
-	static unsigned long cached_quotient=0;
-
-	tmp = jiffies;
-
-	quotient = cached_quotient;
-
-	if (tmp && last_jiffies != tmp) {
-		last_jiffies = tmp;
-		__asm__(".set\tnoreorder\n\t"
-			".set\tnoat\n\t"
-			".set\tmips3\n\t"
-			"lwu\t%0,%2\n\t"
-			"dsll32\t$1,%1,0\n\t"
-			"or\t$1,$1,%0\n\t"
-			"ddivu\t$0,$1,%3\n\t"
-			"mflo\t$1\n\t"
-			"dsll32\t%0,%4,0\n\t"
-			"nop\n\t"
-			"ddivu\t$0,%0,$1\n\t"
-			"mflo\t%0\n\t"
-			".set\tmips0\n\t"
-			".set\tat\n\t"
-			".set\treorder"
-			:"=&r" (quotient)
-			:"r" (timerhi),
-			 "m" (timerlo),
-			 "r" (tmp),
-			 "r" (USECS_PER_JIFFY));
-		cached_quotient = quotient;
-	}
-
-	/* Get last timer tick in absolute kernel time */
-	count = read_c0_count();
-
-	/* .. relative to previous jiffy (32 bits is enough) */
-	count -= timerlo;
-
-	__asm__("multu\t%1,%2\n\t"
-		"mfhi\t%0"
-		:"=r" (res)
-		:"r" (count),
-		 "r" (quotient));
-
-	/*
- 	 * Due to possible jiffies inconsistencies, we need to check
-	 * the result so that we'll get a timer that is monotonic.
-	 */
-	if (res >= USECS_PER_JIFFY)
-		res = USECS_PER_JIFFY-1;
-
-	return res;
-}
-
-/*
- * This version of gettimeofday has microsecond resolution
- * and better than microsecond precision on fast x86 machines with TSC.
- */
-void do_gettimeofday(struct timeval *tv)
-{
-	unsigned long seq;
-	unsigned long usec, sec;
-
-	do {
-		seq = read_seqbegin(&xtime_lock);
-
-		usec = do_gettimeoffset();
-		{
-			unsigned long lost = jiffies - wall_jiffies;
-			if (lost)
-				usec += lost * (1000000 / HZ);
-		}
-		sec = xtime.tv_sec;
-		usec += (xtime.tv_nsec / 1000);
-	} while (read_seqretry(&xtime_lock, seq));
-
-	while (usec >= 1000000) {
-		usec -= 1000000;
-		sec++;
-	}
-
-	tv->tv_sec = sec;
-	tv->tv_usec = usec;
-}
-
-EXPORT_SYMBOL(do_gettimeofday);
-
-void do_settimeofday(struct timeval *tv)
-{
-	write_seqlock_irq(&xtime_lock);
-	/*
-	 * This is revolting. We need to set "xtime" correctly. However, the
-	 * value in this location is the value at the most recent update of
-	 * wall time.  Discover what correction gettimeofday() would have
-	 * made, and then undo it!
-	 */
-	tv->tv_usec -= do_gettimeoffset();
-	tv->tv_usec -= (jiffies - wall_jiffies) * (1000000 / HZ);
-
-	while (tv->tv_usec < 0) {
-		tv->tv_usec += 1000000;
-		tv->tv_sec--;
-	}
-
-	xtime.tv_sec = tv->tv_sec;
-	xtime.tv_nsec = (tv->tv_usec * 1000);
-	time_adjust = 0;		/* stop active adjtime() */
-	time_status |= STA_UNSYNC;
-	time_maxerror = NTP_PHASE_LIMIT;
-	time_esterror = NTP_PHASE_LIMIT;
-	write_sequnlock_irq(&xtime_lock);
-}
-
-EXPORT_SYMBOL(do_settimeofday);
-
 /*
  * There are a lot of conceptually broken versions of the MIPS timer interrupt
  * handler floating around.  This one is rather different, but the algorithm
--- diff/arch/mips/gt64120/common/Makefile	2003-08-20 14:16:25.000000000 +0100
+++ source/arch/mips/gt64120/common/Makefile	2004-02-23 13:56:38.000000000 +0000
@@ -2,4 +2,5 @@
 # Makefile for common code of gt64120-based boards.
 #
 
-obj-y	 	+= gt_irq.o
+obj-y	 		+= time.o
+obj-$(CONFIG_PCI)	+= pci.o
--- diff/arch/mips/gt64120/momenco_ocelot/irq.c	2003-08-20 14:16:25.000000000 +0100
+++ source/arch/mips/gt64120/momenco_ocelot/irq.c	2004-02-23 13:56:38.000000000 +0000
@@ -5,7 +5,7 @@
  *
  * Copyright 2001 MontaVista Software Inc.
  * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net
- * Copyright (C) 2000, 2001 Ralf Baechle (ralf@gnu.org)
+ * Copyright (C) 2000, 2001, 2003 Ralf Baechle (ralf@gnu.org)
  *
  *  This program is free software; you can redistribute  it and/or modify it
  *  under  the terms of  the GNU General  Public License as published by the
@@ -45,103 +45,14 @@
 #include <asm/bootinfo.h>
 #include <asm/io.h>
 #include <asm/irq.h>
+#include <asm/irq_cpu.h>
 #include <asm/mipsregs.h>
 #include <asm/system.h>
 
-
-static spinlock_t rm7000_irq_lock = SPIN_LOCK_UNLOCKED;
-
-/* Function for careful CP0 interrupt mask access */
-static inline void modify_cp0_intmask(unsigned clr_mask_in, unsigned set_mask_in)
-{
-	unsigned long status;
-	unsigned clr_mask;
-	unsigned set_mask;
-
-	/* do the low 8 bits first */
-	clr_mask = 0xff & clr_mask_in;
-	set_mask = 0xff & set_mask_in;
-	status = read_c0_status();
-	status &= ~((clr_mask & 0xFF) << 8);
-	status |= (set_mask & 0xFF) << 8;
-	write_c0_status(status);
-
-	/* do the high 8 bits */
-	clr_mask = 0xff & (clr_mask_in >> 8);
-	set_mask = 0xff & (set_mask_in >> 8);
-	status = read_c0_intcontrol();
-	status &= ~((clr_mask & 0xFF) << 8);
-	status |= (set_mask & 0xFF) << 8;
-	write_c0_intcontrol(status);
-}
-
-static inline void mask_irq(unsigned int irq)
-{
-	modify_cp0_intmask(irq, 0);
-}
-
-static inline void unmask_irq(unsigned int irq)
-{
-	modify_cp0_intmask(0, irq);
-}
-
-static void enable_cp7000_irq(unsigned int irq)
-{
-	unsigned long flags;
-
-	spin_lock_irqsave(&rm7000_irq_lock, flags);
-	unmask_irq(1 << irq);
-	spin_unlock_irqrestore(&rm7000_irq_lock, flags);
-}
-
-static unsigned int startup_cp7000_irq(unsigned int irq)
-{
-	enable_cp7000_irq(irq);
-
-	return 0;				/* never anything pending */
-}
-
-static void disable_cp7000_irq(unsigned int irq)
-{
-	unsigned long flags;
-
-	spin_lock_irqsave(&rm7000_irq_lock, flags);
-	mask_irq(1 << irq);
-	spin_unlock_irqrestore(&rm7000_irq_lock, flags);
-}
-
-#define shutdown_cp7000_irq disable_cp7000_irq
-
-static void mask_and_ack_cp7000_irq(unsigned int irq)
-{
-	mask_irq(1 << irq);
-}
-
-static void end_cp7000_irq(unsigned int irq)
-{
-	if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
-		unmask_irq(1 << irq);
-}
-
-static struct hw_interrupt_type cp7000_hpcdma_irq_type = {
-	"CP7000",
-	startup_cp7000_irq,
-	shutdown_cp7000_irq,
-	enable_cp7000_irq,
-	disable_cp7000_irq,
-	mask_and_ack_cp7000_irq,
-	end_cp7000_irq,
-	NULL
-};
-
-
 extern asmlinkage void ocelot_handle_int(void);
-extern void gt64120_irq_init(void);
 
 void __init init_IRQ(void)
 {
-	int i;
-
 	/*
 	 * Clear all of the interrupts while we change the able around a bit.
 	 * int-handler is not on bootstrap
@@ -151,23 +62,14 @@ void __init init_IRQ(void)
 
 	/* Sets the first-level interrupt dispatcher. */
 	set_except_vector(0, ocelot_handle_int);
-	init_generic_irq();
-
-	for (i = 0; i <= 15; i++) {
-		irq_desc[i].status	= IRQ_DISABLED;
-		irq_desc[i].action	= 0;
-		irq_desc[i].depth	= 1;
-		irq_desc[i].handler	= &cp7000_hpcdma_irq_type;
-	}
 
-	gt64120_irq_init();
+	init_generic_irq();
+	mips_cpu_irq_init(0);
+	rm7k_cpu_irq_init(8);
 
 #ifdef CONFIG_KGDB
 	printk("start kgdb ...\n");
 	set_debug_traps();
 	breakpoint();	/* you may move this line to whereever you want :-) */
 #endif
-#ifdef CONFIG_GDB_CONSOLE
-	register_gdb_console();
-#endif
 }
--- diff/arch/mips/gt64120/momenco_ocelot/prom.c	2003-08-20 14:16:25.000000000 +0100
+++ source/arch/mips/gt64120/momenco_ocelot/prom.c	2004-02-23 13:56:38.000000000 +0000
@@ -27,7 +27,6 @@ struct callvectors {
 };
 
 struct callvectors* debug_vectors;
-char arcs_cmdline[CL_SIZE];
 
 extern unsigned long gt64120_base;
 
@@ -37,10 +36,14 @@ const char *get_system_type(void)
 }
 
 /* [jsun@junsun.net] PMON passes arguments in C main() style */
-void __init prom_init(int argc, char **arg, char** env, struct callvectors *cv)
+void __init prom_init(void)
 {
-	int i;
+	int argc = fw_arg0;
+	char **arg = (char **) fw_arg1;
+	char **env = (char **) fw_arg2;
+	struct callvectors *cv = (struct callvectors *) fw_arg3;
 	uint32_t tmp;
+	int i;
 
 	/* save the PROM vectors for debugging use */
 	debug_vectors = cv;
@@ -74,10 +77,7 @@ void __init prom_init(int argc, char **a
 	add_memory_region(0, 64 << 20, BOOT_MEM_RAM);
 }
 
-void __init prom_free_prom_memory(void)
-{
-}
-
-void __init prom_fixup_mem_map(unsigned long start, unsigned long end)
+unsigned long __init prom_free_prom_memory(void)
 {
+	return 0;
 }
--- diff/arch/mips/gt64120/momenco_ocelot/setup.c	2003-08-20 14:16:25.000000000 +0100
+++ source/arch/mips/gt64120/momenco_ocelot/setup.c	2004-02-23 13:56:38.000000000 +0000
@@ -39,7 +39,6 @@
 #include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/types.h>
-#include <linux/mc146818rtc.h>
 #include <linux/mm.h>
 #include <linux/swap.h>
 #include <linux/ioport.h>
@@ -51,23 +50,18 @@
 #include <asm/time.h>
 #include <asm/bootinfo.h>
 #include <asm/page.h>
-#include <asm/bootinfo.h>
 #include <asm/io.h>
 #include <asm/irq.h>
 #include <asm/pci.h>
 #include <asm/processor.h>
 #include <asm/ptrace.h>
 #include <asm/reboot.h>
-#include <asm/mc146818rtc.h>
 #include <asm/traps.h>
-#include <linux/version.h>
 #include <linux/bootmem.h>
 #include <linux/initrd.h>
-#include <asm/gt64120/gt64120.h>
+#include <asm/gt64120.h>
 #include "ocelot_pld.h"
 
-extern struct rtc_ops no_rtc_ops;
-
 unsigned long gt64120_base = KSEG1ADDR(GT_DEF_BASE);
 
 /* These functions are used for rebooting or halting the machine*/
@@ -156,7 +150,7 @@ void PMON_v2_setup()
 	gt64120_base = 0xe0000000;
 }
 
-void __init momenco_ocelot_setup(void)
+static void __init momenco_ocelot_setup(void)
 {
 	void (*l3func)(unsigned long)=KSEG1ADDR(&setup_l3cache);
 	unsigned int tmpword;
@@ -172,7 +166,6 @@ void __init momenco_ocelot_setup(void)
 	 * initrd_end = (ulong)ocelot_initrd_start + (ulong)ocelot_initrd_size;
 	 * initrd_below_start_ok = 1;
 	 */
-	rtc_ops = &no_rtc_ops;
 
 	/* do handoff reconfiguration */
 	if (gt64120_base == KSEG1ADDR(GT_DEF_BASE))
@@ -314,6 +307,8 @@ void __init momenco_ocelot_setup(void)
 	GT_WRITE(0x468, 0xfef73);
 }
 
+early_initcall(momenco_ocelot_setup);
+
 extern int rm7k_tcache_enabled;
 /*
  * This runs in KSEG1. See the verbiage in rm7k.c::probe_scache()
@@ -327,7 +322,7 @@ static void __init setup_l3cache(unsigne
 	printk("Enabling L3 cache...");
 
 	/* Enable the L3 cache in the GT64120A's CPU Configuration register */
-	GT_READ(0, &tmp);
+	tmp =  GT_READ(0);
 	GT_WRITE(0, tmp | (1<<14));
 
 	/* Enable the L3 cache in the CPU */
--- diff/arch/mips/hp-lj/init.c	2003-08-20 14:16:36.000000000 +0100
+++ source/arch/mips/hp-lj/init.c	2004-02-23 13:56:38.000000000 +0000
@@ -17,9 +17,7 @@
 const char CommandLine[] = Delimiter
   "root=/dev/hda3                                                                                                                                                                                                                                            ";
 
-char arcs_cmdline[CL_SIZE];
-
-int __init prom_init(int argc, char ** argv, char **envp)
+void __init prom_init(void)
 {
 	ulong mem_size = get_mem_avail();
         int reserve_size = 0;
@@ -43,11 +41,10 @@ int __init prom_init(int argc, char ** a
 	mips_machtype   = MACH_UNKNOWN;
 
 	strcpy(arcs_cmdline, CommandLine+strlen(Delimiter));
-
-	return 0;
 }
 
 
-void prom_free_prom_memory (void)
+unsigned long __init prom_free_prom_memory(void)
 {
+	return 0;
 }
--- diff/arch/mips/hp-lj/setup.c	2003-08-20 14:16:36.000000000 +0100
+++ source/arch/mips/hp-lj/setup.c	2004-02-23 13:56:38.000000000 +0000
@@ -14,52 +14,57 @@
 #include <linux/interrupt.h>
 #include <linux/ide.h>
 #include <linux/bootmem.h>
-#include <asm/mc146818rtc.h>
 #include <asm/reboot.h>
 #include <asm/time.h>
 #include <asm/hp-lj/asic.h>
 #include "utils.h"
 
+extern char CommandLine[];
+extern void pci_setup(void);
+
 #ifdef CONFIG_KGDB
 int remote_debug = 0;
 #endif
 
 const char *get_system_type(void)
 {
-	return "HP LaserJet";		/* But which exactly?  */
+	return "HP LaserJet";	/* But which exactly?  */
 }
 
-static void (*timer_interrupt_service)(int irq, void *dev_id, struct pt_regs * regs) = NULL;
+static void (*timer_interrupt_service) (int irq, void *dev_id,
+					struct pt_regs * regs) = NULL;
 
 
-static void andros_timer_interrupt(int irq, void *dev_id, struct pt_regs * regs)
+static void andros_timer_interrupt(int irq, void *dev_id,
+				   struct pt_regs *regs)
 {
-   if (!(*((volatile unsigned int*)0xbfea0010) & 0x20))  // mask = pend & en
-      return;
+	if (!(*((volatile unsigned int *) 0xbfea0010) & 0x20))	// mask = pend & en
+		return;
 
-   /* clear timer interrupt */
-   {
-      unsigned int tmr = *((volatile unsigned int*)0xbfe90040);   // ctl bits
-      *((volatile unsigned int*)0xbfe90040) = tmr;     // write to ack
-      *((volatile unsigned int*)0xbfea000c) = 0x20;    // sys int ack
-   }
+	/* clear timer interrupt */
+	{
+		unsigned int tmr = *((volatile unsigned int *) 0xbfe90040);	// ctl bits
+		*((volatile unsigned int *) 0xbfe90040) = tmr;	// write to ack
+		*((volatile unsigned int *) 0xbfea000c) = 0x20;	// sys int ack
+	}
 
-   /* service interrupt */
-   timer_interrupt_service(irq, dev_id, regs);
+	/* service interrupt */
+	timer_interrupt_service(irq, dev_id, regs);
 }
 
-static void harmony_timer_interrupt(int irq, void *dev_id, struct pt_regs * regs)
+static void harmony_timer_interrupt(int irq, void *dev_id,
+				    struct pt_regs *regs)
 {
-   if (!(*((volatile unsigned int*)0xbff63000) & 0x01))
-      return;  // big sys     int reg, 01-timer  did it
-   if (!(*((volatile unsigned int*)0xbff610a4) & 0x01))
-      return;  // local small int reg, 01-timer0 did it
+	if (!(*((volatile unsigned int *) 0xbff63000) & 0x01))
+		return;		// big sys     int reg, 01-timer  did it
+	if (!(*((volatile unsigned int *) 0xbff610a4) & 0x01))
+		return;		// local small int reg, 01-timer0 did it
 
-   *((volatile unsigned int*)0xbff610a4) = 1;   // ack local timer0 bit
-   *((volatile unsigned int*)0xbff63000) = 1;   // ack global timer bit
+	*((volatile unsigned int *) 0xbff610a4) = 1;	// ack local timer0 bit
+	*((volatile unsigned int *) 0xbff63000) = 1;	// ack global timer bit
 
-   /* service interrupt */
-   timer_interrupt_service(irq, dev_id, regs);
+	/* service interrupt */
+	timer_interrupt_service(irq, dev_id, regs);
 }
 
 
@@ -68,87 +73,78 @@ static void harmony_timer_interrupt(int 
 
 static void __init hp_time_init(struct irqaction *irq)
 {
-    timer_interrupt_service = irq->handler;
+	timer_interrupt_service = irq->handler;
 
-    if (GetAsicId() == AndrosAsic) {
-       //*((volatile unsigned int*)0xbfe90000) = 0x2f;  // set by bootloader to 0x20              // prescaler
-       *((volatile unsigned int*)0xbfe90040) = 0x21;    // 20-res of 1kHz,1-int ack                // control
-       *((volatile unsigned int*)0xbfe90048) = 0x09;    // 09-reload val                          // reload
-       *((volatile unsigned int*)0xbfe90044) = 0x09;    // 09-count val                           // count
-       *((volatile unsigned int*)0xbfe90040) = 0x2f;    // 8-int enable,4-reload en,2-count down en,1-int-ack
-
-       irq->handler = andros_timer_interrupt;
-       irq->flags |= SA_INTERRUPT | SA_SHIRQ;
-       printk("setting up timer in hp_time_init\n");
-       setup_irq(ASIC_IRQ_NUMBER, irq);
-
-       // enable timer interrupt
-       *((volatile unsigned int*)0xbfea0000) = 0x20;
-
-    } else if (GetAsicId() == HarmonyAsic) {
-
-        *((volatile unsigned int*)0xbff61000) = 99;  // prescaler, 100Mz sys clk
-        *((volatile unsigned int*)0xbff61028) = 0x09;  // reload reg
-        *((volatile unsigned int*)0xbff61024) = 0x09;  // count reg
-        *((volatile unsigned int*)0xbff61020) = 0x0b;  // 80-1khz res on timer, 2 reload en, 1 - count down en
-
-        irq->handler = harmony_timer_interrupt;
-        irq->flags |= SA_INTERRUPT | SA_SHIRQ;
-        setup_irq(ASIC_IRQ_NUMBER, irq);
-
-        *((volatile unsigned int*)0xbff610a0) |= 1;    // turn on timer0
-
-    } else if (GetAsicId() == UnknownAsic)
-        printk("Unknown asic in hp_time_init()\n");
-    else
-        printk("Unsupported asic in hp_time_init()\n");
+	if (GetAsicId() == AndrosAsic) {
+		//*((volatile unsigned int*)0xbfe90000) = 0x2f;  // set by bootloader to 0x20              // prescaler
+		*((volatile unsigned int *) 0xbfe90040) = 0x21;	// 20-res of 1kHz,1-int ack                // control
+		*((volatile unsigned int *) 0xbfe90048) = 0x09;	// 09-reload val                          // reload
+		*((volatile unsigned int *) 0xbfe90044) = 0x09;	// 09-count val                           // count
+		*((volatile unsigned int *) 0xbfe90040) = 0x2f;	// 8-int enable,4-reload en,2-count down en,1-int-ack
+
+		irq->handler = andros_timer_interrupt;
+		irq->flags |= SA_INTERRUPT | SA_SHIRQ;
+		printk("setting up timer in hp_time_init\n");
+		setup_irq(ASIC_IRQ_NUMBER, irq);
+
+		// enable timer interrupt
+		*((volatile unsigned int *) 0xbfea0000) = 0x20;
+
+	} else if (GetAsicId() == HarmonyAsic) {
+
+		*((volatile unsigned int *) 0xbff61000) = 99;	// prescaler, 100Mz sys clk
+		*((volatile unsigned int *) 0xbff61028) = 0x09;	// reload reg
+		*((volatile unsigned int *) 0xbff61024) = 0x09;	// count reg
+		*((volatile unsigned int *) 0xbff61020) = 0x0b;	// 80-1khz res on timer, 2 reload en, 1 - count down en
+
+		irq->handler = harmony_timer_interrupt;
+		irq->flags |= SA_INTERRUPT | SA_SHIRQ;
+		setup_irq(ASIC_IRQ_NUMBER, irq);
+
+		*((volatile unsigned int *) 0xbff610a0) |= 1;	// turn on timer0
+
+	} else if (GetAsicId() == UnknownAsic)
+		printk("Unknown asic in hp_time_init()\n");
+	else
+		printk("Unsupported asic in hp_time_init()\n");
 }
 
 
 static void hplj_restart(void)
 {
-   if (GetAsicId() == AndrosAsic)
-       *((volatile unsigned int *) 0xbfe900c0) = 0;
+	if (GetAsicId() == AndrosAsic)
+		*((volatile unsigned int *) 0xbfe900c0) = 0;
 
 
-    if (GetAsicId() == HarmonyAsic)
-        *((volatile unsigned int *) 0xbff62030) = 0;
+	if (GetAsicId() == HarmonyAsic)
+		*((volatile unsigned int *) 0xbff62030) = 0;
 
-   printk("Restart Failed ... halting instead\n");
-   while(1);
+	printk("Restart Failed ... halting instead\n");
+	while (1);
 }
 
 static void hplj_halt(void)
 {
-   while(1);
+	while (1);
 }
 
-void __init hp_setup(void)
+static void __init hp_setup(void)
 {
 #ifdef CONFIG_PCI
-   extern void pci_setup(void);
-   pci_setup();
-#endif
-
-#ifdef CONFIG_IDE
-   {
-      extern struct ide_ops std_ide_ops;
-      ide_ops = &std_ide_ops;
-   }
+	pci_setup();
 #endif
 
-   _machine_restart =(void (*)(char *)) hplj_restart;
-   _machine_halt = hplj_halt;
-   _machine_power_off = hplj_halt;
+	_machine_restart = (void (*)(char *)) hplj_restart;
+	_machine_halt = hplj_halt;
+	_machine_power_off = hplj_halt;
 
-   board_timer_setup = hp_time_init;
+	board_timer_setup = hp_time_init;
 
 #ifdef CONFIG_KGDB
-   {
-      extern char CommandLine[];
-      remote_debug = (strstr(CommandLine, "kgdb") != NULL);
-   }
+	remote_debug = (strstr(CommandLine, "kgdb") != NULL);
 #endif
 
-   printk("HP SETUP\n");
+	printk("HP SETUP\n");
 }
+
+early_initcall(hp_setup);
--- diff/arch/mips/ite-boards/generic/irq.c	2003-08-20 14:16:25.000000000 +0100
+++ source/arch/mips/ite-boards/generic/irq.c	2004-02-23 13:56:38.000000000 +0000
@@ -75,8 +75,6 @@ extern void breakpoint(void);
 
 #define ALLINTS_NOTIMER (IE_IRQ0 | IE_IRQ1 | IE_IRQ2 | IE_IRQ3 | IE_IRQ4)
 
-unsigned int local_bh_count[NR_CPUS];
-unsigned int local_irq_count[NR_CPUS];
 void disable_it8172_irq(unsigned int irq_nr);
 void enable_it8172_irq(unsigned int irq_nr);
 
@@ -84,8 +82,8 @@ extern void set_debug_traps(void);
 extern void mips_timer_interrupt(int irq, struct pt_regs *regs);
 extern asmlinkage void it8172_IRQ(void);
 
-struct it8172_intc_regs volatile *it8172_hw0_icregs
-	= (struct it8172_intc_regs volatile *)(KSEG1ADDR(IT8172_PCI_IO_BASE + IT_INTC_BASE));
+struct it8172_intc_regs volatile *it8172_hw0_icregs =
+	(struct it8172_intc_regs volatile *)(KSEG1ADDR(IT8172_PCI_IO_BASE + IT_INTC_BASE));
 
 /* Function for careful CP0 interrupt mask access */
 static inline void modify_cp0_intmask(unsigned clr_mask, unsigned set_mask)
@@ -244,7 +242,6 @@ static struct hw_interrupt_type cp0_irq_
 	end_none
 };
 
-
 void enable_cpu_timer(void)
 {
         unsigned long flags;
@@ -254,7 +251,6 @@ void enable_cpu_timer(void)
         local_irq_restore(flags);
 }
 
-
 void __init init_IRQ(void)
 {
 	int i;
@@ -334,8 +330,7 @@ void it8172_hw0_irqdispatch(struct pt_re
 	intstatus = it8172_hw0_icregs->intstatus;
 	if (intstatus & 0x8) {
 		panic("Got NMI interrupt");
-	}
-	else if (intstatus & 0x4) {
+	} else if (intstatus & 0x4) {
 		/* PCI interrupt */
 		irq = 0;
 		status |= it8172_hw0_icregs->pci_req;
@@ -372,10 +367,9 @@ void it8172_hw0_irqdispatch(struct pt_re
 		}
 		irq += IT8172_LPC_IRQ_BASE;
 		//printk("LPC int %d\n", irq);
-	}
-	else {
+	} else
 		return;
-	}
+
 	do_IRQ(irq, regs);
 }
 
--- diff/arch/mips/ite-boards/generic/it8172_setup.c	2003-08-20 14:16:25.000000000 +0100
+++ source/arch/mips/ite-boards/generic/it8172_setup.c	2004-02-23 13:56:38.000000000 +0000
@@ -30,7 +30,6 @@
 #include <linux/init.h>
 #include <linux/sched.h>
 #include <linux/ioport.h>
-#include <linux/console.h>
 #include <linux/serial_reg.h>
 #include <linux/major.h>
 #include <linux/kdev_t.h>
@@ -47,17 +46,8 @@
 #include <asm/it8172/it8172.h>
 #include <asm/it8712.h>
 
-#if defined(CONFIG_SERIAL_CONSOLE) || defined(CONFIG_PROM_CONSOLE)
-extern void console_setup(char *, int *);
-char serial_console[20];
-#endif
-
 extern struct resource ioport_resource;
-#ifdef CONFIG_BLK_DEV_IDE
-extern struct ide_ops std_ide_ops;
-extern struct ide_ops *ide_ops;
-#endif
-#ifdef CONFIG_PC_KEYB
+#ifdef CONFIG_SERIO_I8042
 int init_8712_keyboard(void);
 #endif
 
@@ -115,7 +105,7 @@ void __init it8172_init_ram_resource(uns
 	it8172_resources.ram.end = memsize;
 }
 
-void __init it8172_setup(void)
+static void __init it8172_setup(void)
 {
 	unsigned short dsr;
 	char *argptr;
@@ -138,10 +128,10 @@ void __init it8172_setup(void)
 	_machine_power_off = it8172_power_off;
 
 	/*
-	* IO/MEM resources.
-	*
-	* revisit this area.
-	*/
+	 * IO/MEM resources.
+	 * 
+	 * revisit this area.
+	 */
 	set_io_port_base(KSEG1);
 	ioport_resource.start = it8172_resources.pci_io.start;
 	ioport_resource.end = it8172_resources.pci_io.end;
@@ -161,6 +151,10 @@ void __init it8172_setup(void)
 	 * Pull enabled devices out of standby
 	 */
 	IT_IO_READ16(IT_PM_DSR, dsr);
+
+	/*
+	 * Fixme: This breaks when these drivers are modules!!!
+	 */
 #ifdef CONFIG_SOUND_IT8172
 	dsr &= ~IT_PM_DSR_ACSB;
 #else
@@ -168,30 +162,24 @@ void __init it8172_setup(void)
 #endif
 #ifdef CONFIG_BLK_DEV_IT8172
 	dsr &= ~IT_PM_DSR_IDESB;
-	ide_ops = &std_ide_ops;
 #else
 	dsr |= IT_PM_DSR_IDESB;
 #endif
 	IT_IO_WRITE16(IT_PM_DSR, dsr);
 
-#ifdef CONFIG_FB
-	conswitchp = &dummy_con;
-#endif
-
 	InitLPCInterface();
 
 #ifdef CONFIG_MIPS_ITE8172
 	if (SearchIT8712()) {
 		printk("Found IT8712 Super IO\n");
-		// enable IT8712 serial port
+		/* enable IT8712 serial port */
 		LPCSetConfig(LDN_SERIAL1, 0x30, 0x01); /* enable */
 		LPCSetConfig(LDN_SERIAL1, 0x23, 0x01); /* clock selection */
-#ifdef CONFIG_PC_KEYB
+#ifdef CONFIG_SERIO_I8042
 		if (init_8712_keyboard()) {
 			printk("Unable to initialize keyboard\n");
 			LPCSetConfig(LDN_KEYBOARD, 0x30, 0x0); /* disable keyboard */
-		}
-		else {
+		} else {
 			LPCSetConfig(LDN_KEYBOARD, 0x30, 0x1); /* enable keyboard */
 			LPCSetConfig(LDN_KEYBOARD, 0xf0, 0x2);
 			LPCSetConfig(LDN_KEYBOARD, 0x71, 0x3);
@@ -205,7 +193,6 @@ void __init it8172_setup(void)
 					(LPCGetConfig(LDN_MOUSE, 0x30) == 0))
 				printk("Error: keyboard or mouse not enabled\n");
 
-			kbd_ops = &std_kbd_ops;
 		}
 #endif
 	}
@@ -264,16 +251,20 @@ void __init it8172_setup(void)
 #endif /* CONFIG_IT8172_SCR1 */
 }
 
+early_initcall(it8172_setup);
 
-#ifdef CONFIG_PC_KEYB
+#ifdef CONFIG_SERIO_I8042
 /*
  * According to the ITE Special BIOS Note for waking up the
  * keyboard controller...
  */
-int init_8712_keyboard()
+static int init_8712_keyboard(void)
 {
 	unsigned int cmd_port = 0x14000064;
 	unsigned int data_port = 0x14000060;
+	                         ^^^^^^^^^^^
+	Somebody here doesn't grok the concept of io ports.
+
 	unsigned char data;
 	int i;
 
--- diff/arch/mips/ite-boards/generic/pmon_prom.c	2003-08-20 14:16:25.000000000 +0100
+++ source/arch/mips/ite-boards/generic/pmon_prom.c	2004-02-23 13:56:38.000000000 +0000
@@ -42,9 +42,6 @@
 
 #include <asm/bootinfo.h>
 
-/* #define DEBUG_CMDLINE */
-
-char arcs_cmdline[CL_SIZE];
 extern int prom_argc;
 extern char **prom_argv, **prom_envp;
 
@@ -111,8 +108,9 @@ static inline unsigned char str2hexnum(u
 	return 0; /* foo */
 }
 
-void prom_free_prom_memory (void)
+unsigned long __init prom_free_prom_memory(void)
 {
+	return 0;
 }
 
 unsigned long __init prom_get_memsize(void)
--- diff/arch/mips/ite-boards/generic/time.c	2003-08-20 14:16:25.000000000 +0100
+++ source/arch/mips/ite-boards/generic/time.c	2004-02-23 13:56:38.000000000 +0000
@@ -29,7 +29,6 @@
 #include <linux/sched.h>
 #include <linux/time.h>
 #include <linux/spinlock.h>
-#include <linux/mc146818rtc.h>
 
 #include <asm/time.h>
 #include <asm/mipsregs.h>
@@ -114,7 +113,7 @@ hour_hw_to_bin(unsigned char c)
 
 static unsigned long r4k_offset; /* Amount to increment compare reg each time */
 static unsigned long r4k_cur;    /* What counter should be at next timer irq */
-extern unsigned int mips_counter_frequency;
+extern unsigned int mips_hpt_frequency;
 
 /*
  * Figure out the r4k offset, the amount to increment the compare
@@ -138,12 +137,12 @@ static unsigned long __init cal_r4koff(v
 	while (CMOS_READ(RTC_REG_A) & RTC_UIP);
 	while (!(CMOS_READ(RTC_REG_A) & RTC_UIP));
 
-	mips_counter_frequency = read_c0_count();
+	mips_hpt_frequency = read_c0_count();
 
 	/* restore interrupts */
 	local_irq_restore(flags);
 
-	return (mips_counter_frequency / HZ);
+	return (mips_hpt_frequency / HZ);
 }
 
 static unsigned long 
--- diff/arch/mips/ite-boards/ivr/init.c	2003-08-20 14:16:25.000000000 +0100
+++ source/arch/mips/ite-boards/ivr/init.c	2004-02-23 13:56:38.000000000 +0000
@@ -1,5 +1,4 @@
 /*
- *
  * BRIEF MODULE DESCRIPTION
  *	IVR board setup.
  *
@@ -35,7 +34,6 @@
 #include <asm/bootinfo.h>
 #include <linux/string.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <asm/it8172/it8172.h>
 #include <asm/it8172/it8172_dbg.h>
 
@@ -55,16 +53,14 @@ const char *get_system_type(void)
 	return "Globespan IVR";
 }
 
-int __init prom_init(int argc, char **argv, char **envp, int *prom_vec)
+void __init prom_init(void)
 {
 	unsigned long mem_size;
 	unsigned long pcicr;
 
-	prom_argc = argc;
-	prom_argv = argv;
-	prom_envp = envp;
-
-	puts("IVR board running...");
+	prom_argc = fw_arg0;
+	prom_argv = (char **) fw_arg1;
+	prom_envp = (int *) fw_arg3;
 
 	mips_machgroup = MACH_GROUP_GLOBESPAN;
 	mips_machtype = MACH_IVR;  /* Globespan's iTVC15 reference board */
@@ -85,5 +81,4 @@ int __init prom_init(int argc, char **ar
 
 	it8172_init_ram_resource(mem_size);
 	add_memory_region(0, mem_size, BOOT_MEM_RAM);
-	return 0;
 }
--- diff/arch/mips/ite-boards/qed-4n-s01b/Makefile	2003-08-20 14:16:25.000000000 +0100
+++ source/arch/mips/ite-boards/qed-4n-s01b/Makefile	2004-02-23 13:56:38.000000000 +0000
@@ -8,5 +8,3 @@
 #
 
 obj-y := init.o
-
-obj-$(CONFIG_PCI) += pci_fixup.o
--- diff/arch/mips/ite-boards/qed-4n-s01b/init.c	2003-08-20 14:16:25.000000000 +0100
+++ source/arch/mips/ite-boards/qed-4n-s01b/init.c	2004-02-23 13:56:38.000000000 +0000
@@ -34,7 +34,6 @@
 #include <asm/bootinfo.h>
 #include <linux/string.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <asm/it8172/it8172.h>
 #include <asm/it8172/it8172_dbg.h>
 
@@ -54,16 +53,14 @@ const char *get_system_type(void)
 	return "ITE QED-4N-S01B";
 }
 
-int __init prom_init(int argc, char **argv, char **envp, int *prom_vec)
+void __init prom_init(void)
 {
 	unsigned long mem_size;
 	unsigned long pcicr;
 
-	prom_argc = argc;
-	prom_argv = argv;
-	prom_envp = envp;
-
-	puts("ITE board running...");
+	prom_argc = fw_arg0;
+	prom_argv = (char **) fw_arg1;
+	prom_envp = (int *) fw_arg3;
 
 	mips_machgroup = MACH_GROUP_ITE;
 	mips_machtype = MACH_QED_4N_S01B;  /* ITE board name/number */
@@ -85,6 +82,4 @@ int __init prom_init(int argc, char **ar
 
 	it8172_init_ram_resource(mem_size);
 	add_memory_region(0, mem_size, BOOT_MEM_RAM);
-
-	return 0;
 }
--- diff/arch/mips/jazz/Makefile	2003-08-20 14:16:25.000000000 +0100
+++ source/arch/mips/jazz/Makefile	2004-02-23 13:56:38.000000000 +0000
@@ -2,8 +2,6 @@
 # Makefile for the Jazz family specific parts of the kernel
 #
 
-export-syms	:= jazz-ksyms.o
-obj-y	 	:= int-handler.o irq.o jazzdma.o jazz-ksyms.o reset.o \
-		   rtc-jazz.o setup.o floppy-jazz.o kbd-jazz.o
+obj-y	 	:= int-handler.o irq.o jazzdma.o reset.o setup.o
 
 EXTRA_AFLAGS := $(CFLAGS)
--- diff/arch/mips/jazz/int-handler.S	2003-08-20 14:16:25.000000000 +0100
+++ source/arch/mips/jazz/int-handler.S	2004-02-23 13:56:38.000000000 +0000
@@ -88,9 +88,9 @@ ll_local_dev:	lbu	t0,JAZZ_IO_IRQ_SOURCE
  * cards.  Oh well - for all the Jazz boxes slots are more or less just
  * whistles and bells and we're aware of the problem.
  */
-ll_isa_irq:	lw	a0,JAZZ_EISA_IRQ_ACK
+ll_isa_irq:	lw	a0, JAZZ_EISA_IRQ_ACK
 
-		jal	i8259_do_irq
+		jal	do_IRQ
 		 move	a1,sp
 
 		j	ret_from_irq
@@ -133,7 +133,7 @@ ll_timer:	lw	zero,JAZZ_TIMER_REGISTER # 
 /*
  * CPU count/compare IRQ (unused)
  */
-ll_count:	j	return
+ll_count:	j	ret_from_irq
 		 mtc0	zero,CP0_COMPARE
 
 #if 0
--- diff/arch/mips/jazz/irq.c	2003-08-20 14:16:25.000000000 +0100
+++ source/arch/mips/jazz/irq.c	2004-02-23 13:56:38.000000000 +0000
@@ -4,9 +4,8 @@
  * for more details.
  *
  * Copyright (C) 1992 Linus Torvalds
- * Copyright (C) 1994 - 2001 Ralf Baechle
+ * Copyright (C) 1994 - 2001, 2003 Ralf Baechle
  */
-#include <linux/delay.h>
 #include <linux/init.h>
 #include <linux/interrupt.h>
 #include <linux/kernel.h>
@@ -18,6 +17,75 @@
 
 extern asmlinkage void jazz_handle_int(void);
 
+static spinlock_t r4030_lock = SPIN_LOCK_UNLOCKED;
+
+extern asmlinkage void sni_rm200_pci_handle_int(void);
+
+static void enable_r4030_irq(unsigned int irq)
+{
+	unsigned int mask = 1 << (irq - JAZZ_IE_PARALLEL);
+	unsigned long flags;
+
+	spin_lock_irqsave(&r4030_lock, flags);
+	mask |= r4030_read_reg16(JAZZ_IO_IRQ_ENABLE);
+	r4030_write_reg16(JAZZ_IO_IRQ_ENABLE, mask);
+	spin_unlock_irqrestore(&r4030_lock, flags);
+}
+
+static unsigned int startup_r4030_irq(unsigned int irq)
+{
+	enable_r4030_irq(irq);
+	return 0; /* never anything pending */
+}
+
+#define shutdown_r4030_irq	disable_r4030_irq
+
+void disable_r4030_irq(unsigned int irq)
+{
+	unsigned int mask = ~(1 << (irq - JAZZ_IE_PARALLEL));
+	unsigned long flags;
+
+	spin_lock_irqsave(&r4030_lock, flags);
+	mask &= r4030_read_reg16(JAZZ_IO_IRQ_ENABLE);
+	r4030_write_reg16(JAZZ_IO_IRQ_ENABLE, mask);
+	spin_unlock_irqrestore(&r4030_lock, flags);
+}
+
+#define mask_and_ack_r4030_irq disable_r4030_irq
+
+static void end_r4030_irq(unsigned int irq)
+{
+	if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
+		enable_r4030_irq(irq);
+}
+
+static struct hw_interrupt_type r4030_irq_type = {
+	"R4030",
+	startup_r4030_irq,
+	shutdown_r4030_irq,
+	enable_r4030_irq,
+	disable_r4030_irq,
+	mask_and_ack_r4030_irq,
+	end_r4030_irq,
+	NULL
+};
+
+void __init init_r4030_ints(void)
+{
+	int i;
+
+	for (i = JAZZ_PARALLEL_IRQ; i <= JAZZ_TIMER_IRQ; i++) {
+		irq_desc[i].status     = IRQ_DISABLED;
+		irq_desc[i].action     = 0;
+		irq_desc[i].depth      = 1;
+		irq_desc[i].handler    = &r4030_irq_type;
+	}
+
+	r4030_write_reg16(JAZZ_IO_IRQ_ENABLE, 0);
+	r4030_read_reg16(JAZZ_IO_IRQ_SOURCE);		/* clear pending IRQs */
+	r4030_read_reg32(JAZZ_R4030_INVAL_ADDR);	/* clear error bits */
+}
+
 /*
  * On systems with i8259-style interrupt controllers we assume for
  * driver compatibility reasons interrupts 0 - 15 to be the i8259
@@ -25,21 +93,11 @@ extern asmlinkage void jazz_handle_int(v
  */
 void __init init_IRQ (void)
 {
-	int i;
-
 	set_except_vector(0, jazz_handle_int);
 
 	init_generic_irq();
 	init_i8259_irqs();			/* Integrated i8259  */
-#if 0
-	init_jazz_irq();
+	init_r4030_ints();
 
-	/* Actually we've got more interrupts to handle ...  */
-	for (i = PCIMT_IRQ_INT2; i <= PCIMT_IRQ_ETHERNET; i++) {
-		irq_desc[i].status     = IRQ_DISABLED;
-		irq_desc[i].action     = 0;
-		irq_desc[i].depth      = 1;
-		irq_desc[i].handler    = &pciasic_irq_type;
-	}
-#endif
+	change_c0_status(ST0_IM, IE_IRQ4 | IE_IRQ3 | IE_IRQ2 | IE_IRQ1);
 }
--- diff/arch/mips/jazz/jazzdma.c	2003-08-20 14:16:25.000000000 +0100
+++ source/arch/mips/jazz/jazzdma.c	2004-02-23 13:56:38.000000000 +0000
@@ -9,6 +9,7 @@
  */
 #include <linux/kernel.h>
 #include <linux/init.h>
+#include <linux/module.h>
 #include <linux/errno.h>
 #include <linux/mm.h>
 #include <linux/bootmem.h>
@@ -78,7 +79,7 @@ void __init vdma_init(void)
 	vdma_pgtbl_init();
 
 	r4030_write_reg32(JAZZ_R4030_TRSTBL_BASE,
-			  PHYSADDR(vdma_pagetable_start));
+			  CPHYSADDR(vdma_pagetable_start));
 	r4030_write_reg32(JAZZ_R4030_TRSTBL_LIM, VDMA_PGTBL_SIZE);
 	r4030_write_reg32(JAZZ_R4030_TRSTBL_INV, 0);
 
@@ -170,6 +171,8 @@ unsigned long vdma_alloc(unsigned long p
 	return laddr;
 }
 
+EXPORT_SYMBOL(vdma_alloc);
+
 /*
  * Free previously allocated dma translation pages
  * Note that this does NOT change the translation table,
@@ -201,6 +204,8 @@ int vdma_free(unsigned long laddr)
 	return 0;
 }
 
+EXPORT_SYMBOL(vdma_free);
+
 /*
  * Map certain page(s) to another physical address.
  * Caller must have allocated the page(s) before.
@@ -310,6 +315,8 @@ unsigned long vdma_log2phys(unsigned lon
 	return pgtbl[laddr >> 12].frame + (laddr & (VDMA_PAGESIZE - 1));
 }
 
+EXPORT_SYMBOL(vdma_log2phys);
+
 /*
  * Print DMA statistics
  */
--- diff/arch/mips/jazz/reset.c	2003-08-20 14:16:25.000000000 +0100
+++ source/arch/mips/jazz/reset.c	2004-02-23 13:56:38.000000000 +0000
@@ -1,5 +1,8 @@
 /*
  * Reset a Jazz machine.
+ *
+ * We don't trust the firmware so we do it the classic way by poking and
+ * stabbing at the keyboard controller ...
  */
 #include <linux/jiffies.h>
 #include <asm/jazz.h>
@@ -8,25 +11,54 @@
 #include <asm/reboot.h>
 #include <asm/delay.h>
 
+#define jazz_kh ((keyboard_hardware *) JAZZ_KEYBOARD_ADDRESS)
+
+#define KBD_STAT_IBF		0x02	/* Keyboard input buffer full */
+
+static void jazz_write_output(unsigned char val)
+{
+	int status;
+
+	do {
+		status = jazz_kh->command;
+	} while (status & KBD_STAT_IBF);
+	jazz_kh->data = val;
+}
+
+static void jazz_write_command(unsigned char val)
+{
+	int status;
+
+	do {
+		status = jazz_kh->command;
+	} while (status & KBD_STAT_IBF);
+	jazz_kh->command = val;
+}
+
+static unsigned char jazz_read_status(void)
+{
+	return jazz_kh->command;
+}
+
 static inline void kb_wait(void)
 {
 	unsigned long start = jiffies;
 	unsigned long timeout = start + HZ/2;
 
 	do {
-		if (! (kbd_read_status() & 0x02))
+		if (! (jazz_read_status() & 0x02))
 			return;
-	} time_before_eq(jiffies, timeout);
+	} while (time_before_eq(jiffies, timeout));
 }
 
 void jazz_machine_restart(char *command)
 {
-    while (1) {
-	kb_wait ();
-	kbd_write_command (0xd1);
-	kb_wait ();
-	kbd_write_output (0x00);
-    }
+	while(1) {
+		kb_wait();
+		jazz_write_command (0xd1);
+		kb_wait();
+		jazz_write_output (0x00);
+	}
 }
 
 void jazz_machine_halt(void)
--- diff/arch/mips/jazz/setup.c	2003-09-30 15:46:11.000000000 +0100
+++ source/arch/mips/jazz/setup.c	2004-02-23 13:56:38.000000000 +0000
@@ -18,7 +18,6 @@
 #include <linux/mm.h>
 #include <linux/console.h>
 #include <linux/fb.h>
-#include <linux/mc146818rtc.h>
 #include <linux/ide.h>
 #include <asm/bootinfo.h>
 #include <asm/irq.h>
@@ -28,62 +27,33 @@
 #include <asm/reboot.h>
 #include <asm/io.h>
 #include <asm/pgtable.h>
+#include <asm/time.h>
 #include <asm/traps.h>
 
-/*
- * Initial irq handlers.
- */
-static void no_action(int cpl, void *dev_id, struct pt_regs *regs) { }
-
-/*
- * IRQ2 is cascade interrupt to second interrupt controller
- */
-static struct irqaction irq2  = { no_action, 0, 0, "cascade", NULL, NULL};
-
 extern asmlinkage void jazz_handle_int(void);
 
 extern void jazz_machine_restart(char *command);
 extern void jazz_machine_halt(void);
 extern void jazz_machine_power_off(void);
 
-extern struct ide_ops std_ide_ops;
-extern struct rtc_ops jazz_rtc_ops;
-extern struct kbd_ops jazz_kbd_ops;
-extern struct fd_ops *fd_ops;
-extern struct fd_ops jazz_fd_ops;
-
-void (*board_time_init)(struct irqaction *irq);
-
 static void __init jazz_time_init(struct irqaction *irq)
 {
-        /* set the clock to 100 Hz */
-        r4030_write_reg32(JAZZ_TIMER_INTERVAL, 9);
-        i8259_setup_irq(JAZZ_TIMER_IRQ, irq);
-}
-
-static void __init jazz_irq_setup(void)
-{
-        set_except_vector(0, jazz_handle_int);
-	r4030_write_reg16(JAZZ_IO_IRQ_ENABLE,
-			  JAZZ_IE_ETHERNET |
-			  JAZZ_IE_SCSI     |
-			  JAZZ_IE_SERIAL1  |
-			  JAZZ_IE_SERIAL2  |
- 			  JAZZ_IE_PARALLEL |
-			  JAZZ_IE_FLOPPY);
-	r4030_read_reg16(JAZZ_IO_IRQ_SOURCE); /* clear pending IRQs */
-	r4030_read_reg32(JAZZ_R4030_INVAL_ADDR); /* clear error bits */
-	change_c0_status(ST0_IM, IE_IRQ4 | IE_IRQ3 | IE_IRQ2 | IE_IRQ1);
 	/* set the clock to 100 Hz */
 	r4030_write_reg32(JAZZ_TIMER_INTERVAL, 9);
-	request_region(0x20, 0x20, "pic1");
-	request_region(0xa0, 0x20, "pic2");
-	i8259_setup_irq(2, &irq2);
+	setup_irq(JAZZ_TIMER_IRQ, irq);
 }
 
+static struct resource jazz_io_resources[] = {
+	{ "dma1", 0x00, 0x1f, IORESOURCE_BUSY },
+	{ "timer", 0x40, 0x5f, IORESOURCE_BUSY },
+	{ "dma page reg", 0x80, 0x8f, IORESOURCE_BUSY },
+	{ "dma2", 0xc0, 0xdf, IORESOURCE_BUSY },
+};
 
-void __init jazz_setup(void)
+static void __init jazz_setup(void)
 {
+	int i;
+
 	/* Map 0xe0000000 -> 0x0:800005C0, 0xe0010000 -> 0x1:30000580 */
 	add_wired_entry (0x02000017, 0x03c00017, 0xe0000000, PM_64K);
 
@@ -93,34 +63,24 @@ void __init jazz_setup(void)
 	/* Map 0xe4000000 -> 0x0:600005C0, 0xe4100000 -> 400005C0 */
 	add_wired_entry (0x01800017, 0x01000017, 0xe4000000, PM_4M);
 
-	irq_setup = jazz_irq_setup;
 	set_io_port_base(JAZZ_PORT_BASE);
 #ifdef CONFIG_EISA
 	if (mips_machtype == MACH_MIPS_MAGNUM_4000)
 		EISA_bus = 1;
 #endif
 	isa_slot_offset = 0xe3000000;
-	request_region(0x00,0x20,"dma1");
-	request_region(0x40,0x20,"timer");
-	request_region(0x80,0x10,"dma page reg");
-	request_region(0xc0,0x20,"dma2");
-        board_time_init = jazz_time_init;
+
+	/* request I/O space for devices used on all i[345]86 PCs */
+	for (i = 0; i < ARRAY_SIZE(jazz_io_resources); i++)
+		request_resource(&ioport_resource, jazz_io_resources + i);
+
+        board_timer_setup = jazz_time_init;
 	/* The RTC is outside the port address space */
 
 	_machine_restart = jazz_machine_restart;
 	_machine_halt = jazz_machine_halt;
 	_machine_power_off = jazz_machine_power_off;
 
-#ifdef CONFIG_BLK_DEV_IDE
-	ide_ops = &std_ide_ops;
-#endif
-#ifdef CONFIG_BLK_DEV_FD
-	fd_ops = &jazz_fd_ops;
-#endif
-#ifdef CONFIG_VT
-	conswitchp = &dummy_con;
-#endif
-
 #warning "Somebody should check if screen_info is ok for Jazz."
 
 	screen_info = (struct screen_info) {
@@ -135,8 +95,7 @@ void __init jazz_setup(void)
 		16		/* orig_video_points */
 	};
 
-	rtc_ops = &jazz_rtc_ops;
-	kbd_ops = &jazz_kbd_ops;
-
 	vdma_init();
 }
+
+early_initcall(jazz_setup);
--- diff/arch/mips/jmr3927/common/prom.c	2003-08-20 14:16:25.000000000 +0100
+++ source/arch/mips/jmr3927/common/prom.c	2004-02-23 13:56:38.000000000 +0000
@@ -41,9 +41,6 @@
 
 #include <asm/bootinfo.h>
 
-/* #define DEBUG_CMDLINE */
-
-char arcs_cmdline[CL_SIZE];
 extern int prom_argc;
 extern char **prom_argv, **prom_envp;
 
@@ -78,6 +75,7 @@ void  __init prom_init_cmdline(void)
 	*cp = '\0';
 }
 
-void prom_free_prom_memory (void)
+unsigned long __init prom_free_prom_memory(void)
 {
+	return 0;
 }
--- diff/arch/mips/jmr3927/rbhma3100/Makefile	2003-07-08 09:55:17.000000000 +0100
+++ source/arch/mips/jmr3927/rbhma3100/Makefile	2004-02-23 13:56:38.000000000 +0000
@@ -2,7 +2,7 @@
 # Makefile for TOSHIBA JMR-TX3927 board
 #
 
-obj-y	 			+= init.o int-handler.o irq.o setup.o rtc.o
+obj-y	 			+= init.o int-handler.o irq.o setup.o
 obj-$(CONFIG_RUNTIME_DEBUG) 	+= debug.o
 obj-$(CONFIG_KGDB)		+= kgdb_io.o
 
--- diff/arch/mips/jmr3927/rbhma3100/init.c	2003-07-08 09:55:17.000000000 +0100
+++ source/arch/mips/jmr3927/rbhma3100/init.c	2004-02-23 13:56:38.000000000 +0000
@@ -1,5 +1,4 @@
-/***********************************************************************
- *
+/*
  * Copyright 2001 MontaVista Software Inc.
  * Author: MontaVista Software, Inc.
  *              ahennessy@mvista.com
@@ -27,8 +26,6 @@
  *  You should have received a copy of the  GNU General Public License along
  *  with this program; if not, write  to the Free Software Foundation, Inc.,
  *  675 Mass Ave, Cambridge, MA 02139, USA.
- *
- ***********************************************************************
  */
 #include <linux/config.h>
 #include <linux/init.h>
@@ -57,16 +54,17 @@ const char *get_system_type(void)
 }
 
 extern void puts(unsigned char *cp);
-int __init prom_init(int argc, char **argv, char **envp, int *prom_vec)
+
+void __init prom_init(void)
 {
 #ifdef CONFIG_TOSHIBA_JMR3927
 	/* CCFG */
 	if ((tx3927_ccfgptr->ccfg & TX3927_CCFG_TLBOFF) == 0)
 		puts("Warning: TX3927 TLB off\n");
 #endif
-	prom_argc = argc;
-	prom_argv = argv;
-	prom_envp = envp;
+	prom_argc = fw_arg0;
+	prom_argv = (char **) fw_arg1;
+	prom_envp = (char **) fw_arg2;
 
 	mips_machgroup = MACH_GROUP_TOSHIBA;
 
@@ -76,5 +74,4 @@ int __init prom_init(int argc, char **ar
 
 	prom_init_cmdline();
 	add_memory_region(0, JMR3927_SDRAM_SIZE, BOOT_MEM_RAM);
-	return 0;
 }
--- diff/arch/mips/jmr3927/rbhma3100/irq.c	2003-07-08 09:55:17.000000000 +0100
+++ source/arch/mips/jmr3927/rbhma3100/irq.c	2004-02-23 13:56:38.000000000 +0000
@@ -63,10 +63,7 @@
 
 struct tb_irq_space* tb_irq_spaces;
 
-unsigned int local_bh_count[NR_CPUS];
-unsigned int local_irq_count[NR_CPUS];
-
-static int jmr3927_irq_base=-1;
+static int jmr3927_irq_base = -1;
 
 #ifdef CONFIG_PCI
 static int jmr3927_gen_iack(void)
@@ -84,6 +81,7 @@ extern asmlinkage void jmr3927_IRQ(void)
 
 #define irc_dlevel	0
 #define irc_elevel	1
+
 static unsigned char irc_level[TX3927_NUM_IR] = {
 	5, 5, 5, 5, 5, 5,	/* INT[5:0] */
 	7, 7,			/* SIO */
@@ -122,9 +120,12 @@ static inline void unmask_irq(unsigned i
 static void jmr3927_irq_disable(unsigned int irq_nr);
 static void jmr3927_irq_enable(unsigned int irq_nr);
 
+static spinlock_t jmr3927_irq_lock = SPIN_LOCK_UNLOCKED;
+
 static unsigned int jmr3927_irq_startup(unsigned int irq)
 {
 	jmr3927_irq_enable(irq);
+
 	return 0;
 }
 
@@ -132,10 +133,6 @@ static unsigned int jmr3927_irq_startup(
 
 static void jmr3927_irq_ack(unsigned int irq)
 {
-	db_assert(jmr3927_irq_base != -1);
-	db_assert(irq >= jmr3927_irq_base);
-	db_assert(irq < jmr3927_irq_base + JMR3927_NR_IRQ_IRC + JMR3927_NR_IRQ_IOC);
-
 	if (irq == JMR3927_IRQ_IRC_TMR0) {
 		jmr3927_tmrptr->tisr = 0;       /* ack interrupt */
 	}
@@ -145,10 +142,6 @@ static void jmr3927_irq_ack(unsigned int
 
 static void jmr3927_irq_end(unsigned int irq)
 {
-	db_assert(jmr3927_irq_base != -1);
-	db_assert(irq >= jmr3927_irq_base);
-	db_assert(irq < jmr3927_irq_base + JMR3927_NR_IRQ_IRC + JMR3927_NR_IRQ_IOC);
-
 	jmr3927_irq_enable(irq);
 }
 
@@ -156,26 +149,18 @@ static void jmr3927_irq_disable(unsigned
 {
 	unsigned long flags;
 
-	db_assert(jmr3927_irq_base != -1);
-	db_assert(irq >= jmr3927_irq_base);
-	db_assert(irq < jmr3927_irq_base + JMR3927_NR_IRQ_IRC + JMR3927_NR_IRQ_IOC);
-
-	local_irq_save(flags);
+	spinlock_irqsave(&jmr3927_irq_lock, flags);
 	mask_irq(irq_nr);
-	local_irq_restore(flags);
+	spinlock_irqrestore(&jmr3927_irq_lock, flags);
 }
 
 static void jmr3927_irq_enable(unsigned int irq_nr)
 {
 	unsigned long flags;
 
-	db_assert(jmr3927_irq_base != -1);
-	db_assert(irq >= jmr3927_irq_base);
-	db_assert(irq < jmr3927_irq_base + JMR3927_NR_IRQ_IRC + JMR3927_NR_IRQ_IOC);
-
-	local_irq_save(flags);
+	spinlock_irqsave(&jmr3927_irq_lock, flags);
 	unmask_irq(irq_nr);
-	local_irq_restore(flags);
+	spinlock_irqrestore(&jmr3927_irq_lock, flags);
 }
 
 /*
@@ -195,8 +180,7 @@ static void mask_irq_isac(int irq_nr, in
 static void unmask_irq_isac(int irq_nr, int space_id)
 {
 	/* 0: mask */
-	unsigned char imask =
-		jmr3927_isac_reg_in(JMR3927_ISAC_INTM_ADDR);
+	unsigned char imask = jmr3927_isac_reg_in(JMR3927_ISAC_INTM_ADDR);
 	unsigned int bit  = 1 << irq_nr;
 	jmr3927_isac_reg_out(imask | bit, JMR3927_ISAC_INTM_ADDR);
 	/* flush write buffer */
@@ -206,8 +190,7 @@ static void unmask_irq_isac(int irq_nr, 
 static void mask_irq_ioc(int irq_nr, int space_id)
 {
 	/* 0: mask */
-	unsigned char imask =
-		jmr3927_ioc_reg_in(JMR3927_IOC_INTM_ADDR);
+	unsigned char imask = jmr3927_ioc_reg_in(JMR3927_IOC_INTM_ADDR);
 	unsigned int bit = 1 << irq_nr;
 	jmr3927_ioc_reg_out(imask & ~bit, JMR3927_IOC_INTM_ADDR);
 	/* flush write buffer */
@@ -216,8 +199,7 @@ static void mask_irq_ioc(int irq_nr, int
 static void unmask_irq_ioc(int irq_nr, int space_id)
 {
 	/* 0: mask */
-	unsigned char imask =
-		jmr3927_ioc_reg_in(JMR3927_IOC_INTM_ADDR);
+	unsigned char imask = jmr3927_ioc_reg_in(JMR3927_IOC_INTM_ADDR);
 	unsigned int bit = 1 << irq_nr;
 	jmr3927_ioc_reg_out(imask | bit, JMR3927_IOC_INTM_ADDR);
 	/* flush write buffer */
@@ -440,6 +422,7 @@ void jmr3927_irq_setup(void)
 }
 
 void (*irq_setup)(void);
+
 void __init init_IRQ(void)
 {
 
@@ -456,7 +439,7 @@ void __init init_IRQ(void)
         irq_setup();
 }
 
-hw_irq_controller jmr3927_irq_controller = {
+static hw_irq_controller jmr3927_irq_controller = {
 	"jmr3927_irq",
 	jmr3927_irq_startup,
 	jmr3927_irq_shutdown,
@@ -464,15 +447,13 @@ hw_irq_controller jmr3927_irq_controller
 	jmr3927_irq_disable,
 	jmr3927_irq_ack,
 	jmr3927_irq_end,
-	NULL			/* no affinity stuff for UP */
 };
 
-void
-jmr3927_irq_init(u32 irq_base)
+void jmr3927_irq_init(u32 irq_base)
 {
-	extern irq_desc_t irq_desc[];
 	u32 i;
 
+	init_generic_irq();
 	for (i= irq_base; i< irq_base + JMR3927_NR_IRQ_IRC + JMR3927_NR_IRQ_IOC; i++) {
 		irq_desc[i].status = IRQ_DISABLED;
 		irq_desc[i].action = NULL;
--- diff/arch/mips/jmr3927/rbhma3100/setup.c	2003-07-08 09:55:17.000000000 +0100
+++ source/arch/mips/jmr3927/rbhma3100/setup.c	2004-02-23 13:56:38.000000000 +0000
@@ -38,7 +38,6 @@
 #include <linux/kernel.h>
 #include <linux/kdev_t.h>
 #include <linux/types.h>
-#include <linux/console.h>
 #include <linux/sched.h>
 #include <linux/pci.h>
 #include <linux/ide.h>
@@ -199,7 +198,7 @@ extern void jmr3927_irq_setup(void);
 extern struct resource pci_io_resource;
 extern struct resource pci_mem_resource;
 
-void __init jmr3927_setup(void)
+static void __init jmr3927_setup(void)
 {
 	extern int panic_timeout;
 	char *argptr;
@@ -282,6 +281,8 @@ void __init jmr3927_setup(void)
 #endif
 }
 
+early_initcall(jmr3927_setup);
+
 
 static void tx3927_setup(void);
 
@@ -294,9 +295,6 @@ unsigned long mips_pci_mem_size;
 unsigned long mips_pci_io_pciaddr = 0;
 #endif
 
-extern struct rtc_ops *rtc_ops;
-extern struct rtc_ops jmr3927_rtc_ops;
-
 static void __init jmr3927_board_init(void)
 {
 	char *argptr;
@@ -310,10 +308,6 @@ static void __init jmr3927_board_init(vo
 
 	tx3927_setup();
 
-#ifdef CONFIG_VT
-	conswitchp = &dummy_con;
-#endif
-
 	if (jmr3927_have_isac()) {
 
 #ifdef CONFIG_FB_E1355
@@ -328,11 +322,6 @@ static void __init jmr3927_board_init(vo
 		/* overrides PCI-IDE */
 #endif
 	}
-#ifdef USE_RTC_DS1742
-	if (jmr3927_have_nvram()) {
-		rtc_ops = &jmr3927_rtc_ops;
-	}
-#endif
 
 	/* SIO0 DTR on */
 	jmr3927_ioc_reg_out(0, JMR3927_IOC_DTR_ADDR);
--- diff/arch/mips/kernel/Makefile	2003-08-26 10:00:52.000000000 +0100
+++ source/arch/mips/kernel/Makefile	2004-02-23 13:56:38.000000000 +0000
@@ -24,6 +24,7 @@ obj-$(CONFIG_CPU_R4X00)		+= r4k_fpu.o r4
 obj-$(CONFIG_CPU_R5000)		+= r4k_fpu.o r4k_switch.o
 obj-$(CONFIG_CPU_R5432)		+= r4k_fpu.o r4k_switch.o
 obj-$(CONFIG_CPU_RM7000)	+= r4k_fpu.o r4k_switch.o
+obj-$(CONFIG_CPU_RM9000)	+= r4k_fpu.o r4k_switch.o
 obj-$(CONFIG_CPU_NEVADA)	+= r4k_fpu.o r4k_switch.o
 obj-$(CONFIG_CPU_R10000)	+= r4k_fpu.o r4k_switch.o
 obj-$(CONFIG_CPU_SB1)		+= r4k_fpu.o r4k_switch.o
@@ -35,6 +36,7 @@ obj-$(CONFIG_SMP)		+= smp.o
 
 obj-$(CONFIG_I8259)		+= i8259.o
 obj-$(CONFIG_IRQ_CPU)		+= irq_cpu.o
+obj-$(CONFIG_IRQ_CPU_RM7K)	+= irq-rm7000.o
 
 obj-$(CONFIG_MIPS32)		+= scall32-o32.o
 obj-$(CONFIG_MIPS64)		+= scall64-64.o
@@ -47,12 +49,10 @@ obj-$(CONFIG_MIPS32_O32)	+= binfmt_elfo3
 obj-$(CONFIG_KGDB)		+= gdb-low.o gdb-stub.o
 obj-$(CONFIG_PROC_FS)		+= proc.o
 
-ifndef CONFIG_MAPPED_DMA_IO
-obj-y				+= pci-dma.o
-endif
-
 obj-$(CONFIG_MIPS64)		+= cpu-bugs64.o
 
+obj-$(CONFIG_GEN_RTC)		+= genrtc.o
+
 CFLAGS_cpu-bugs64.o	= $(shell if $(CC) $(CFLAGS) -Wa,-mdaddi -c -o /dev/null -xc /dev/null >/dev/null 2>&1; then echo "-DHAVE_AS_SET_DADDI"; fi)
 
 EXTRA_AFLAGS := $(CFLAGS)
--- diff/arch/mips/kernel/binfmt_elfn32.c	2003-08-20 14:16:36.000000000 +0100
+++ source/arch/mips/kernel/binfmt_elfn32.c	2004-02-23 13:56:38.000000000 +0000
@@ -95,6 +95,19 @@ struct elf_prpsinfo32
 #define elf_caddr_t	u32
 #define init_elf_binfmt init_elfn32_binfmt
 
+#define jiffies_to_timeval jiffies_to_compat_timeval
+static __inline__ void
+jiffies_to_compat_timeval(unsigned long jiffies, struct compat_timeval *value)
+{
+	/*
+	 * Convert jiffies to nanoseconds and seperate with
+	 * one divide.
+	 */
+	u64 nsec = (u64)jiffies * TICK_NSEC; 
+	value->tv_sec = div_long_long_rem(nsec, NSEC_PER_SEC, &value->tv_usec);
+	value->tv_usec /= NSEC_PER_USEC;
+}
+
 #define ELF_CORE_EFLAGS EF_MIPS_ABI2
 
 #undef CONFIG_BINFMT_ELF
--- diff/arch/mips/kernel/binfmt_elfo32.c	2003-08-20 14:16:36.000000000 +0100
+++ source/arch/mips/kernel/binfmt_elfo32.c	2004-02-23 13:56:38.000000000 +0000
@@ -97,6 +97,18 @@ struct elf_prpsinfo32
 #define elf_caddr_t	u32
 #define init_elf_binfmt init_elf32_binfmt
 
+#define jiffies_to_timeval jiffies_to_compat_timeval
+static __inline__ void
+jiffies_to_compat_timeval(unsigned long jiffies, struct compat_timeval *value)
+{
+	/*
+	 * Convert jiffies to nanoseconds and seperate with
+	 * one divide.
+	 */
+	u64 nsec = (u64)jiffies * TICK_NSEC; 
+	value->tv_sec = div_long_long_rem(nsec, NSEC_PER_SEC, &value->tv_usec);
+	value->tv_usec /= NSEC_PER_USEC;
+}
 
 #undef ELF_CORE_COPY_REGS
 #define ELF_CORE_COPY_REGS(_dest,_regs) elf32_core_copy_regs(_dest,_regs);
--- diff/arch/mips/kernel/branch.c	2003-08-20 14:16:25.000000000 +0100
+++ source/arch/mips/kernel/branch.c	2004-02-23 13:56:38.000000000 +0000
@@ -11,6 +11,7 @@
 #include <linux/signal.h>
 #include <asm/branch.h>
 #include <asm/cpu.h>
+#include <asm/cpu-features.h>
 #include <asm/inst.h>
 #include <asm/ptrace.h>
 #include <asm/uaccess.h>
--- diff/arch/mips/kernel/cpu-bugs64.c	2003-08-20 14:16:36.000000000 +0100
+++ source/arch/mips/kernel/cpu-bugs64.c	2004-02-23 13:56:38.000000000 +0000
@@ -6,6 +6,7 @@
  * as published by the Free Software Foundation; either version
  * 2 of the License, or (at your option) any later version.
  */
+#include <linux/config.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/ptrace.h>
@@ -17,18 +18,40 @@
 #include <asm/mipsregs.h>
 #include <asm/system.h>
 
-static inline void check_mult_sh(void)
+static inline void align_mod(const int align, const int mod)
+{
+	asm volatile(
+		".set	push\n\t"
+		".set	noreorder\n\t"
+		".balign %0\n\t"
+		".rept	%1\n\t"
+		"nop\n\t"
+		".endr\n\t"
+		".set	pop"
+		:
+		: "n" (align), "n" (mod));
+}
+
+static inline void mult_sh_align_mod(long *v1, long *v2, long *w,
+				     const int align, const int mod)
 {
 	unsigned long flags;
 	int m1, m2;
-	long p, s, v;
+	long p, s, lv1, lv2, lw;
 
-	printk("Checking for the multiply/shift bug... ");
+	/*
+	 * We want the multiply and the shift to be isolated from the
+	 * rest of the code to disable gcc optimizations.  Hence the
+	 * asm statements that execute nothing, but make gcc not know
+	 * what the values of m1, m2 and s are and what lv2 and p are
+	 * used for.
+	 */
 
 	local_irq_save(flags);
 	/*
-	 * The following code leads to a wrong result of dsll32 when
-	 * executed on R4000 rev. 2.2 or 3.0.
+	 * The following code leads to a wrong result of the first
+	 * dsll32 when executed on R4000 rev. 2.2 or 3.0 (PRId
+	 * 00000422 or 00000430, respectively).
 	 *
 	 * See "MIPS R4000PC/SC Errata, Processor Revision 2.2 and
 	 * 3.0" by MIPS Technologies, Inc., errata #16 and #28 for
@@ -36,52 +59,97 @@ static inline void check_mult_sh(void)
 	 * sigh... --macro
 	 */
 	asm volatile(
+		""
+		: "=r" (m1), "=r" (m2), "=r" (s)
+		: "0" (5), "1" (8), "2" (5));
+	align_mod(align, mod);
+	/*
+	 * The trailing nop is needed to fullfill the two-instruction
+	 * requirement between reading hi/lo and staring a mult/div.
+	 * Leaving it out may cause gas insert a nop itself breaking
+	 * the desired alignment of the next chunk.
+	 */
+	asm volatile(
 		".set	push\n\t"
 		".set	noat\n\t"
 		".set	noreorder\n\t"
 		".set	nomacro\n\t"
-		"mult	%1, %2\n\t"
-		"dsll32	%0, %3, %4\n\t"
+		"mult	%2, %3\n\t"
+		"dsll32	%0, %4, %5\n\t"
 		"mflo	$0\n\t"
+		"dsll32	%1, %4, %5\n\t"
+		"nop\n\t"
 		".set	pop"
-		: "=r" (v)
-		: "r" (5), "r" (8), "r" (5), "I" (0)
+		: "=&r" (lv1), "=r" (lw)
+		: "r" (m1), "r" (m2), "r" (s), "I" (0)
 		: "hi", "lo", "accum");
-	local_irq_restore(flags);
-
-	if (v == 5L << 32) {
-		printk("no.\n");
-		return;
-	}
-
-	printk("yes, workaround... ");
-	local_irq_save(flags);
-	/*
-	 * We want the multiply and the shift to be isolated from the
-	 * rest of the code to disable gcc optimizations.  Hence the
-	 * asm statements that execute nothing, but make gcc not know
-	 * what the values of m1, m2 and s are and what v and p are
-	 * used for.
-	 *
-	 * We have to use single integers for m1 and m2 and a double
+	/* We have to use single integers for m1 and m2 and a double
 	 * one for p to be sure the mulsidi3 gcc's RTL multiplication
 	 * instruction has the workaround applied.  Older versions of
-	 * gcc have correct mulsi3, but other multiplication variants
-	 * lack the workaround.
+	 * gcc have correct umulsi3 and mulsi3, but other
+	 * multiplication variants lack the workaround.
 	 */
 	asm volatile(
 		""
 		: "=r" (m1), "=r" (m2), "=r" (s)
-		: "0" (5), "1" (8), "2" (5));
+		: "0" (m1), "1" (m2), "2" (s));
+	align_mod(align, mod);
 	p = m1 * m2;
-	v = s << 32;
+	lv2 = s << 32;
 	asm volatile(
 		""
-		: "=r" (v)
-		: "0" (v), "r" (p));
+		: "=r" (lv2)
+		: "0" (lv2), "r" (p));
 	local_irq_restore(flags);
 
-	if (v == 5L << 32) {
+	*v1 = lv1;
+	*v2 = lv2;
+	*w = lw;
+}
+
+static inline void check_mult_sh(void)
+{
+	long v1[8], v2[8], w[8];
+	int bug, fix, i;
+
+	printk("Checking for the multiply/shift bug... ");
+
+	/*
+	 * Testing discovered false negatives for certain code offsets
+	 * into cache lines.  Hence we test all possible offsets for
+	 * the worst assumption of an R4000 I-cache line width of 32
+	 * bytes.
+	 *
+	 * We can't use a loop as alignment directives need to be
+	 * immediates.
+	 */
+	mult_sh_align_mod(&v1[0], &v2[0], &w[0], 32, 0);
+	mult_sh_align_mod(&v1[1], &v2[1], &w[1], 32, 1);
+	mult_sh_align_mod(&v1[2], &v2[2], &w[2], 32, 2);
+	mult_sh_align_mod(&v1[3], &v2[3], &w[3], 32, 3);
+	mult_sh_align_mod(&v1[4], &v2[4], &w[4], 32, 4);
+	mult_sh_align_mod(&v1[5], &v2[5], &w[5], 32, 5);
+	mult_sh_align_mod(&v1[6], &v2[6], &w[6], 32, 6);
+	mult_sh_align_mod(&v1[7], &v2[7], &w[7], 32, 7);
+
+	bug = 0;
+	for (i = 0; i < 8; i++)
+		if (v1[i] != w[i])
+			bug = 1;
+		
+	if (bug == 0) {
+		printk("no.\n");
+		return;
+	}
+
+	printk("yes, workaround... ");
+
+	fix = 1;
+	for (i = 0; i < 8; i++)
+		if (v2[i] != w[i])
+			fix = 0;
+		
+	if (fix == 1) {
 		printk("yes.\n");
 		return;
 	}
@@ -117,7 +185,8 @@ static inline void check_daddi(void)
 	handler = set_except_vector(12, handle_daddi_ov);
 	/*
 	 * The following code fails to trigger an overflow exception
-	 * when executed on R4000 rev. 2.2 or 3.0.
+	 * when executed on R4000 rev. 2.2 or 3.0 (PRId 00000422 or
+	 * 00000430, respectively).
 	 *
 	 * See "MIPS R4000PC/SC Errata, Processor Revision 2.2 and
 	 * 3.0" by MIPS Technologies, Inc., erratum #23 for details.
@@ -177,15 +246,16 @@ static inline void check_daddiu(void)
 
 	/*
 	 * The following code leads to a wrong result of daddiu when
-	 * executed on R4400 rev. 1.0.
+	 * executed on R4400 rev. 1.0 (PRId 00000440).
 	 *
 	 * See "MIPS R4400PC/SC Errata, Processor Revision 1.0" by
 	 * MIPS Technologies, Inc., erratum #7 for details.
 	 *
 	 * According to "MIPS R4000PC/SC Errata, Processor Revision
 	 * 2.2 and 3.0" by MIPS Technologies, Inc., erratum #41 this
-	 * problem affects R4000 rev. 2.2 and 3.0, too.  Testing
-	 * failed to trigger it so far.
+	 * problem affects R4000 rev. 2.2 and 3.0 (PRId 00000422 and
+	 * 00000430, respectively), too.  Testing failed to trigger it
+	 * so far.
 	 *
 	 * I got no permission to duplicate the errata here, sigh...
 	 * --macro
--- diff/arch/mips/kernel/cpu-probe.c	2003-08-20 14:16:25.000000000 +0100
+++ source/arch/mips/kernel/cpu-probe.c	2004-02-23 13:56:38.000000000 +0000
@@ -9,6 +9,7 @@
  * as published by the Free Software Foundation; either version
  * 2 of the License, or (at your option) any later version.
  */
+#include <linux/config.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/ptrace.h>
@@ -89,12 +90,15 @@ static inline void check_wait(void)
 	case CPU_R5000:
 	case CPU_NEVADA:
 	case CPU_RM7000:
+/*	case CPU_RM9000: */
 	case CPU_TX49XX:
 	case CPU_4KC:
 	case CPU_4KEC:
 	case CPU_4KSC:
 	case CPU_5KC:
 /*	case CPU_20KC:*/
+	case CPU_24K:
+	case CPU_25KF:
 		cpu_wait = r4k_wait;
 		printk(" available.\n");
 		break;
@@ -160,350 +164,420 @@ static inline int __cpu_has_fpu(void)
 }
 
 #define R4K_OPTS (MIPS_CPU_TLB | MIPS_CPU_4KEX | MIPS_CPU_4KTLB \
-		| MIPS_CPU_COUNTER | MIPS_CPU_CACHE_CDEX)
+		| MIPS_CPU_COUNTER)
 
-__init void cpu_probe(void)
+static inline void cpu_probe_legacy(struct cpuinfo_mips *c)
 {
-	struct cpuinfo_mips *c = &current_cpu_data;
-	unsigned long config0 = read_c0_config();
-	unsigned long config1;
-
-	c->processor_id	= PRID_IMP_UNKNOWN;
-	c->fpu_id	= FPIR_IMP_NONE;
-	c->cputype	= CPU_UNKNOWN;
-
-        if (config0 & (1 << 31)) {
-		/* MIPS32 or MIPS64 compliant CPU. Read Config 1 register. */
-		c->options = MIPS_CPU_TLB | MIPS_CPU_4KEX |
-			MIPS_CPU_4KTLB | MIPS_CPU_COUNTER | MIPS_CPU_DIVEC |
-			MIPS_CPU_LLSC;
-		config1 = read_c0_config1();
-		if (config1 & (1 << 3))
-			c->options |= MIPS_CPU_WATCH;
-		if (config1 & (1 << 2))
-			c->options |= MIPS_CPU_MIPS16;
-		if (config1 & (1 << 1))
-			c->options |= MIPS_CPU_EJTAG;
-		if (config1 & 1) {
+	switch (c->processor_id & 0xff00) {
+	case PRID_IMP_R2000:
+		c->cputype = CPU_R2000;
+		c->isa_level = MIPS_CPU_ISA_I;
+		c->options = MIPS_CPU_TLB | MIPS_CPU_NOFPUEX |
+		             MIPS_CPU_LLSC;
+		if (__cpu_has_fpu())
 			c->options |= MIPS_CPU_FPU;
-			c->options |= MIPS_CPU_32FPR;
-		}
-		c->scache.flags = MIPS_CACHE_NOT_PRESENT;
-
-		c->tlbsize = ((config1 >> 25) & 0x3f) + 1;
-	}
-
-	c->processor_id = read_c0_prid();
-	switch (c->processor_id & 0xff0000) {
-	case PRID_COMP_LEGACY:
-		switch (c->processor_id & 0xff00) {
-		case PRID_IMP_R2000:
-			c->cputype = CPU_R2000;
-			c->isa_level = MIPS_CPU_ISA_I;
-			c->options = MIPS_CPU_TLB | MIPS_CPU_NOFPUEX |
-			             MIPS_CPU_LLSC;
-			if (__cpu_has_fpu())
-				c->options |= MIPS_CPU_FPU;
-			c->tlbsize = 64;
-			break;
-		case PRID_IMP_R3000:
-			if ((c->processor_id & 0xff) == PRID_REV_R3000A)
-				if (cpu_has_confreg())
-					c->cputype = CPU_R3081E;
-				else
-					c->cputype = CPU_R3000A;
+		c->tlbsize = 64;
+		break;
+	case PRID_IMP_R3000:
+		if ((c->processor_id & 0xff) == PRID_REV_R3000A)
+			if (cpu_has_confreg())
+				c->cputype = CPU_R3081E;
 			else
-				c->cputype = CPU_R3000;
-			c->isa_level = MIPS_CPU_ISA_I;
-			c->options = MIPS_CPU_TLB | MIPS_CPU_NOFPUEX |
-			             MIPS_CPU_LLSC;
-			if (__cpu_has_fpu())
-				c->options |= MIPS_CPU_FPU;
-			c->tlbsize = 64;
-			break;
-		case PRID_IMP_R4000:
+				c->cputype = CPU_R3000A;
+		else
+			c->cputype = CPU_R3000;
+		c->isa_level = MIPS_CPU_ISA_I;
+		c->options = MIPS_CPU_TLB | MIPS_CPU_NOFPUEX |
+		             MIPS_CPU_LLSC;
+		if (__cpu_has_fpu())
+			c->options |= MIPS_CPU_FPU;
+		c->tlbsize = 64;
+		break;
+	case PRID_IMP_R4000:
+		if (read_c0_config() & CONF_SC) {
+			if ((c->processor_id & 0xff) >= PRID_REV_R4400)
+				c->cputype = CPU_R4400PC;
+			else
+				c->cputype = CPU_R4000PC;
+		} else {
 			if ((c->processor_id & 0xff) >= PRID_REV_R4400)
 				c->cputype = CPU_R4400SC;
 			else
 				c->cputype = CPU_R4000SC;
-			c->isa_level = MIPS_CPU_ISA_III;
-			c->options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_32FPR |
-			             MIPS_CPU_WATCH | MIPS_CPU_VCE |
-			             MIPS_CPU_LLSC;
-			c->tlbsize = 48;
-			break;
-                case PRID_IMP_VR41XX:
-			switch (c->processor_id & 0xf0) {
-#ifndef CONFIG_VR4181
-			case PRID_REV_VR4111:
-				c->cputype = CPU_VR4111;
-				break;
-#else
-			case PRID_REV_VR4181:
-				c->cputype = CPU_VR4181;
-				break;
-#endif
-			case PRID_REV_VR4121:
-				c->cputype = CPU_VR4121;
-				break;
-			case PRID_REV_VR4122:
-				if ((c->processor_id & 0xf) < 0x3)
-					c->cputype = CPU_VR4122;
-				else
-					c->cputype = CPU_VR4181A;
-				break;
-			case PRID_REV_VR4131:
-				c->cputype = CPU_VR4131;
-				break;
-			default:
-				printk(KERN_INFO "Unexpected CPU of NEC VR4100 series\n");
-				c->cputype = CPU_VR41XX;
-				break;
-			}
-                        c->isa_level = MIPS_CPU_ISA_III;
-                        c->options = R4K_OPTS;
-                        c->tlbsize = 32;
-                        break;
-		case PRID_IMP_R4300:
-			c->cputype = CPU_R4300;
-			c->isa_level = MIPS_CPU_ISA_III;
-			c->options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_32FPR |
-			             MIPS_CPU_LLSC;
-			c->tlbsize = 32;
-			break;
-		case PRID_IMP_R4600:
-			c->cputype = CPU_R4600;
-			c->isa_level = MIPS_CPU_ISA_III;
-			c->options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_LLSC;
-			c->tlbsize = 48;
-			break;
-		#if 0
- 		case PRID_IMP_R4650:
-			/*
-			 * This processor doesn't have an MMU, so it's not
-			 * "real easy" to run Linux on it. It is left purely
-			 * for documentation.  Commented out because it shares
-			 * it's c0_prid id number with the TX3900.
-			 */
-	 		c->cputype = CPU_R4650;
-		 	c->isa_level = MIPS_CPU_ISA_III;
-			c->options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_LLSC;
-		        c->tlbsize = 48;
-			break;
-		#endif
-		case PRID_IMP_TX39:
-			c->isa_level = MIPS_CPU_ISA_I;
-			c->options = MIPS_CPU_TLB;
-
-			if ((c->processor_id & 0xf0) ==
-			    (PRID_REV_TX3927 & 0xf0)) {
-				c->cputype = CPU_TX3927;
-				c->tlbsize = 64;
-			} else {
-				switch (c->processor_id & 0xff) {
-				case PRID_REV_TX3912:
-					c->cputype = CPU_TX3912;
-					c->tlbsize = 32;
-					break;
-				case PRID_REV_TX3922:
-					c->cputype = CPU_TX3922;
-					c->tlbsize = 64;
-					break;
-				default:
-					c->cputype = CPU_UNKNOWN;
-					break;
-				}
-			}
-			break;
-		case PRID_IMP_R4700:
-			c->cputype = CPU_R4700;
-			c->isa_level = MIPS_CPU_ISA_III;
-			c->options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_32FPR |
-			             MIPS_CPU_LLSC;
-			c->tlbsize = 48;
-			break;
-		case PRID_IMP_TX49:
-			c->cputype = CPU_TX49XX;
-			c->isa_level = MIPS_CPU_ISA_III;
-			c->options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_32FPR |
-			             MIPS_CPU_LLSC;
-			c->tlbsize = 48;
-			break;
-		case PRID_IMP_R5000:
-			c->cputype = CPU_R5000;
-			c->isa_level = MIPS_CPU_ISA_IV;
-			c->options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_32FPR |
-			             MIPS_CPU_LLSC;
-			c->tlbsize = 48;
-			break;
-		case PRID_IMP_R5432:
-			c->cputype = CPU_R5432;
-			c->isa_level = MIPS_CPU_ISA_IV;
-			c->options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_32FPR |
-			             MIPS_CPU_WATCH | MIPS_CPU_LLSC;
-			c->tlbsize = 48;
-			break;
-		case PRID_IMP_R5500:
-			c->cputype = CPU_R5500;
-			c->isa_level = MIPS_CPU_ISA_IV;
-			c->options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_32FPR |
-			             MIPS_CPU_WATCH | MIPS_CPU_LLSC;
-			c->tlbsize = 48;
-			break;
-		case PRID_IMP_NEVADA:
-			c->cputype = CPU_NEVADA;
-			c->isa_level = MIPS_CPU_ISA_IV;
-			c->options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_32FPR |
-			             MIPS_CPU_DIVEC | MIPS_CPU_LLSC;
-			c->tlbsize = 48;
-			break;
-		case PRID_IMP_R6000:
-			c->cputype = CPU_R6000;
-			c->isa_level = MIPS_CPU_ISA_II;
-			c->options = MIPS_CPU_TLB | MIPS_CPU_FPU |
-			             MIPS_CPU_LLSC;
-			c->tlbsize = 32;
-			break;
-		case PRID_IMP_R6000A:
-			c->cputype = CPU_R6000A;
-			c->isa_level = MIPS_CPU_ISA_II;
-			c->options = MIPS_CPU_TLB | MIPS_CPU_FPU |
-			             MIPS_CPU_LLSC;
-			c->tlbsize = 32;
-			break;
-		case PRID_IMP_RM7000:
-			c->cputype = CPU_RM7000;
-			c->isa_level = MIPS_CPU_ISA_IV;
-			c->options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_32FPR |
-			             MIPS_CPU_LLSC;
-			/*
-			 * Undocumented RM7000:  Bit 29 in the info register of
-			 * the RM7000 v2.0 indicates if the TLB has 48 or 64
-			 * entries.
-			 *
-			 * 29      1 =>    64 entry JTLB
-			 *         0 =>    48 entry JTLB
-			 */
-			c->tlbsize = (read_c0_info() & (1 << 29)) ? 64 : 48;
-			break;
-		case PRID_IMP_R8000:
-			c->cputype = CPU_R8000;
-			c->isa_level = MIPS_CPU_ISA_IV;
-			c->options = MIPS_CPU_TLB | MIPS_CPU_4KEX |
-			             MIPS_CPU_FPU | MIPS_CPU_32FPR |
-			             MIPS_CPU_LLSC;
-			c->tlbsize = 384;      /* has weird TLB: 3-way x 128 */
-			break;
-		case PRID_IMP_R10000:
-			c->cputype = CPU_R10000;
-			c->isa_level = MIPS_CPU_ISA_IV;
-			c->options = MIPS_CPU_TLB | MIPS_CPU_4KEX |
-			             MIPS_CPU_FPU | MIPS_CPU_32FPR |
-				     MIPS_CPU_COUNTER | MIPS_CPU_WATCH |
-			             MIPS_CPU_LLSC;
-			c->tlbsize = 64;
-			break;
-		case PRID_IMP_R12000:
-			c->cputype = CPU_R12000;
-			c->isa_level = MIPS_CPU_ISA_IV;
-			c->options = MIPS_CPU_TLB | MIPS_CPU_4KEX |
-			             MIPS_CPU_FPU | MIPS_CPU_32FPR |
-				     MIPS_CPU_COUNTER | MIPS_CPU_WATCH |
-			             MIPS_CPU_LLSC;
-			c->tlbsize = 64;
-			break;
-		default:
-			c->cputype = CPU_UNKNOWN;
-			break;
 		}
+
+		c->isa_level = MIPS_CPU_ISA_III;
+		c->options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_32FPR |
+		             MIPS_CPU_WATCH | MIPS_CPU_VCE |
+		             MIPS_CPU_LLSC;
+		c->tlbsize = 48;
 		break;
-	case PRID_COMP_MIPS:
-		switch (c->processor_id & 0xff00) {
-		case PRID_IMP_4KC:
-			c->cputype = CPU_4KC;
-			c->isa_level = MIPS_CPU_ISA_M32;
+	case PRID_IMP_VR41XX:
+		switch (c->processor_id & 0xf0) {
+#ifndef CONFIG_VR4181
+		case PRID_REV_VR4111:
+			c->cputype = CPU_VR4111;
 			break;
-		case PRID_IMP_4KEC:
-			c->cputype = CPU_4KEC;
-			c->isa_level = MIPS_CPU_ISA_M32;
+#else
+		case PRID_REV_VR4181:
+			c->cputype = CPU_VR4181;
 			break;
-		case PRID_IMP_4KSC:
-			c->cputype = CPU_4KSC;
-			c->isa_level = MIPS_CPU_ISA_M32;
+#endif
+		case PRID_REV_VR4121:
+			c->cputype = CPU_VR4121;
 			break;
-		case PRID_IMP_5KC:
-			c->cputype = CPU_5KC;
-			c->isa_level = MIPS_CPU_ISA_M64;
+		case PRID_REV_VR4122:
+			if ((c->processor_id & 0xf) < 0x3)
+				c->cputype = CPU_VR4122;
+			else
+				c->cputype = CPU_VR4181A;
 			break;
-		case PRID_IMP_20KC:
-			c->cputype = CPU_20KC;
-			c->isa_level = MIPS_CPU_ISA_M64;
+		case PRID_REV_VR4130:
+			if ((c->processor_id & 0xf) < 0x4)
+				c->cputype = CPU_VR4131;
+			else
+				c->cputype = CPU_VR4133;
 			break;
 		default:
-			c->cputype = CPU_UNKNOWN;
-			break;
+			printk(KERN_INFO "Unexpected CPU of NEC VR4100 series\n");
+				c->cputype = CPU_VR41XX;
+				break;
 		}
+		c->isa_level = MIPS_CPU_ISA_III;
+		c->options = R4K_OPTS;
+		c->tlbsize = 32;
 		break;
-	case PRID_COMP_ALCHEMY:
-		switch (c->processor_id & 0xff00) {
-		case PRID_IMP_AU1_REV1:
-		case PRID_IMP_AU1_REV2:
-			switch ((c->processor_id >> 24) & 0xff) {
-			case 0:
- 				c->cputype = CPU_AU1000;
-				break;
-			case 1:
-				c->cputype = CPU_AU1500;
+	case PRID_IMP_R4300:
+		c->cputype = CPU_R4300;
+		c->isa_level = MIPS_CPU_ISA_III;
+		c->options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_32FPR |
+		             MIPS_CPU_LLSC;
+		c->tlbsize = 32;
+		break;
+	case PRID_IMP_R4600:
+		c->cputype = CPU_R4600;
+		c->isa_level = MIPS_CPU_ISA_III;
+		c->options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_LLSC;
+		c->tlbsize = 48;
+		break;
+	#if 0
+ 	case PRID_IMP_R4650:
+		/*
+		 * This processor doesn't have an MMU, so it's not
+		 * "real easy" to run Linux on it. It is left purely
+		 * for documentation.  Commented out because it shares
+		 * it's c0_prid id number with the TX3900.
+		 */
+ 		c->cputype = CPU_R4650;
+	 	c->isa_level = MIPS_CPU_ISA_III;
+		c->options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_LLSC;
+	        c->tlbsize = 48;
+		break;
+	#endif
+	case PRID_IMP_TX39:
+		c->isa_level = MIPS_CPU_ISA_I;
+		c->options = MIPS_CPU_TLB;
+
+		if ((c->processor_id & 0xf0) == (PRID_REV_TX3927 & 0xf0)) {
+			c->cputype = CPU_TX3927;
+			c->tlbsize = 64;
+		} else {
+			switch (c->processor_id & 0xff) {
+			case PRID_REV_TX3912:
+				c->cputype = CPU_TX3912;
+				c->tlbsize = 32;
 				break;
-			case 2:
-				c->cputype = CPU_AU1100;
+			case PRID_REV_TX3922:
+				c->cputype = CPU_TX3922;
+				c->tlbsize = 64;
 				break;
 			default:
-				panic("Unknown Au Core!");
+				c->cputype = CPU_UNKNOWN;
 				break;
 			}
-			c->isa_level = MIPS_CPU_ISA_M32;
- 			break;
-		default:
-			c->cputype = CPU_UNKNOWN;
-			break;
 		}
 		break;
-	case PRID_COMP_SIBYTE:
-		switch (c->processor_id & 0xff00) {
-		case PRID_IMP_SB1:
-			c->cputype = CPU_SB1;
-			c->isa_level = MIPS_CPU_ISA_M64;
-			c->options = MIPS_CPU_TLB | MIPS_CPU_4KEX |
-			             MIPS_CPU_COUNTER | MIPS_CPU_DIVEC |
-			             MIPS_CPU_MCHECK | MIPS_CPU_EJTAG |
-			             MIPS_CPU_WATCH | MIPS_CPU_LLSC;
-#ifndef CONFIG_SB1_PASS_1_WORKAROUNDS
-			/* FPU in pass1 is known to have issues. */
+	case PRID_IMP_R4700:
+		c->cputype = CPU_R4700;
+		c->isa_level = MIPS_CPU_ISA_III;
+		c->options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_32FPR |
+		             MIPS_CPU_LLSC;
+		c->tlbsize = 48;
+		break;
+	case PRID_IMP_TX49:
+		c->cputype = CPU_TX49XX;
+		c->isa_level = MIPS_CPU_ISA_III;
+		c->options = R4K_OPTS | MIPS_CPU_LLSC;
+		if (!(c->processor_id & 0x08))
 			c->options |= MIPS_CPU_FPU | MIPS_CPU_32FPR;
-#endif
+		c->tlbsize = 48;
+		break;
+	case PRID_IMP_R5000:
+		c->cputype = CPU_R5000;
+		c->isa_level = MIPS_CPU_ISA_IV;
+		c->options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_32FPR |
+		             MIPS_CPU_LLSC;
+		c->tlbsize = 48;
+		break;
+	case PRID_IMP_R5432:
+		c->cputype = CPU_R5432;
+		c->isa_level = MIPS_CPU_ISA_IV;
+		c->options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_32FPR |
+		             MIPS_CPU_WATCH | MIPS_CPU_LLSC;
+		c->tlbsize = 48;
+		break;
+	case PRID_IMP_R5500:
+		c->cputype = CPU_R5500;
+		c->isa_level = MIPS_CPU_ISA_IV;
+		c->options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_32FPR |
+		             MIPS_CPU_WATCH | MIPS_CPU_LLSC;
+		c->tlbsize = 48;
+		break;
+	case PRID_IMP_NEVADA:
+		c->cputype = CPU_NEVADA;
+		c->isa_level = MIPS_CPU_ISA_IV;
+		c->options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_32FPR |
+		             MIPS_CPU_DIVEC | MIPS_CPU_LLSC;
+		c->tlbsize = 48;
+		break;
+	case PRID_IMP_R6000:
+		c->cputype = CPU_R6000;
+		c->isa_level = MIPS_CPU_ISA_II;
+		c->options = MIPS_CPU_TLB | MIPS_CPU_FPU |
+		             MIPS_CPU_LLSC;
+		c->tlbsize = 32;
+		break;
+	case PRID_IMP_R6000A:
+		c->cputype = CPU_R6000A;
+		c->isa_level = MIPS_CPU_ISA_II;
+		c->options = MIPS_CPU_TLB | MIPS_CPU_FPU |
+		             MIPS_CPU_LLSC;
+		c->tlbsize = 32;
+		break;
+	case PRID_IMP_RM7000:
+		c->cputype = CPU_RM7000;
+		c->isa_level = MIPS_CPU_ISA_IV;
+		c->options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_32FPR |
+		             MIPS_CPU_LLSC;
+		/*
+		 * Undocumented RM7000:  Bit 29 in the info register of
+		 * the RM7000 v2.0 indicates if the TLB has 48 or 64
+		 * entries.
+		 *
+		 * 29      1 =>    64 entry JTLB
+		 *         0 =>    48 entry JTLB
+		 */
+		c->tlbsize = (read_c0_info() & (1 << 29)) ? 64 : 48;
+		break;
+	case PRID_IMP_RM9000:
+		c->cputype = CPU_RM9000;
+		c->isa_level = MIPS_CPU_ISA_IV;
+		c->options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_32FPR |
+			     MIPS_CPU_LLSC;
+		/*
+		 * Bit 29 in the info register of the RM9000
+		 * indicates if the TLB has 48 or 64 entries.
+		 *
+		 * 29      1 =>    64 entry JTLB
+		 *         0 =>    48 entry JTLB
+		 */
+		c->tlbsize = (read_c0_info() & (1 << 29)) ? 64 : 48;
+		break;
+	case PRID_IMP_R8000:
+		c->cputype = CPU_R8000;
+		c->isa_level = MIPS_CPU_ISA_IV;
+		c->options = MIPS_CPU_TLB | MIPS_CPU_4KEX |
+		             MIPS_CPU_FPU | MIPS_CPU_32FPR |
+		             MIPS_CPU_LLSC;
+		c->tlbsize = 384;      /* has weird TLB: 3-way x 128 */
+		break;
+	case PRID_IMP_R10000:
+		c->cputype = CPU_R10000;
+		c->isa_level = MIPS_CPU_ISA_IV;
+		c->options = MIPS_CPU_TLB | MIPS_CPU_4KEX |
+		             MIPS_CPU_FPU | MIPS_CPU_32FPR |
+			     MIPS_CPU_COUNTER | MIPS_CPU_WATCH |
+		             MIPS_CPU_LLSC;
+		c->tlbsize = 64;
+		break;
+	case PRID_IMP_R12000:
+		c->cputype = CPU_R12000;
+		c->isa_level = MIPS_CPU_ISA_IV;
+		c->options = MIPS_CPU_TLB | MIPS_CPU_4KEX |
+		             MIPS_CPU_FPU | MIPS_CPU_32FPR |
+			     MIPS_CPU_COUNTER | MIPS_CPU_WATCH |
+		             MIPS_CPU_LLSC;
+		c->tlbsize = 64;
+		break;
+	default:
+		c->cputype = CPU_UNKNOWN;
+		break;
+	}
+}
+
+static inline void decode_config1(struct cpuinfo_mips *c)
+{
+	unsigned long config0 = read_c0_config();
+	unsigned long config1;
+
+	if ((config0 & (1 << 31)) == 0)
+		return;			/* actually wort a panic() */
+
+	/* MIPS32 or MIPS64 compliant CPU. Read Config 1 register. */
+	c->options = MIPS_CPU_TLB | MIPS_CPU_4KEX |
+		MIPS_CPU_4KTLB | MIPS_CPU_COUNTER | MIPS_CPU_DIVEC |
+		MIPS_CPU_LLSC | MIPS_CPU_MCHECK;
+	config1 = read_c0_config1();
+	if (config1 & (1 << 3))
+		c->options |= MIPS_CPU_WATCH;
+	if (config1 & (1 << 2))
+		c->options |= MIPS_CPU_MIPS16;
+	if (config1 & (1 << 1))
+		c->options |= MIPS_CPU_EJTAG;
+	if (config1 & 1) {
+		c->options |= MIPS_CPU_FPU;
+		c->options |= MIPS_CPU_32FPR;
+	}
+	c->scache.flags = MIPS_CACHE_NOT_PRESENT;
+
+	c->tlbsize = ((config1 >> 25) & 0x3f) + 1;
+}
+
+static inline void cpu_probe_mips(struct cpuinfo_mips *c)
+{
+	decode_config1(c);
+	switch (c->processor_id & 0xff00) {
+	case PRID_IMP_4KC:
+		c->cputype = CPU_4KC;
+		c->isa_level = MIPS_CPU_ISA_M32;
+		break;
+	case PRID_IMP_4KEC:
+		c->cputype = CPU_4KEC;
+		c->isa_level = MIPS_CPU_ISA_M32;
+		break;
+	case PRID_IMP_4KSC:
+		c->cputype = CPU_4KSC;
+		c->isa_level = MIPS_CPU_ISA_M32;
+		break;
+	case PRID_IMP_5KC:
+		c->cputype = CPU_5KC;
+		c->isa_level = MIPS_CPU_ISA_M64;
+		break;
+	case PRID_IMP_20KC:
+		c->cputype = CPU_20KC;
+		c->isa_level = MIPS_CPU_ISA_M64;
+		break;
+	case PRID_IMP_24K:
+		c->cputype = CPU_24K;
+		c->isa_level = MIPS_CPU_ISA_M32;
+		break;
+	case PRID_IMP_25KF:
+		c->cputype = CPU_25KF;
+		c->isa_level = MIPS_CPU_ISA_M64;
+		/* Probe for L2 cache */
+		c->scache.flags &= ~MIPS_CACHE_NOT_PRESENT;
+		break;
+	default:
+		c->cputype = CPU_UNKNOWN;
+		break;
+	}
+}
+
+static inline void cpu_probe_alchemy(struct cpuinfo_mips *c)
+{
+	decode_config1(c);
+	switch (c->processor_id & 0xff00) {
+	case PRID_IMP_AU1_REV1:
+	case PRID_IMP_AU1_REV2:
+		switch ((c->processor_id >> 24) & 0xff) {
+		case 0:
+ 			c->cputype = CPU_AU1000;
+			break;
+		case 1:
+			c->cputype = CPU_AU1500;
+			break;
+		case 2:
+			c->cputype = CPU_AU1100;
 			break;
 		default:
-			c->cputype = CPU_UNKNOWN;
+			panic("Unknown Au Core!");
 			break;
 		}
+		c->isa_level = MIPS_CPU_ISA_M32;
+ 		break;
+	default:
+		c->cputype = CPU_UNKNOWN;
+		break;
+	}
+}
+
+static inline void cpu_probe_sibyte(struct cpuinfo_mips *c)
+{
+	decode_config1(c);
+	switch (c->processor_id & 0xff00) {
+	case PRID_IMP_SB1:
+		c->cputype = CPU_SB1;
+		c->isa_level = MIPS_CPU_ISA_M64;
+		c->options = MIPS_CPU_TLB | MIPS_CPU_4KEX |
+		             MIPS_CPU_COUNTER | MIPS_CPU_DIVEC |
+		             MIPS_CPU_MCHECK | MIPS_CPU_EJTAG |
+		             MIPS_CPU_WATCH | MIPS_CPU_LLSC;
+#ifndef CONFIG_SB1_PASS_1_WORKAROUNDS
+		/* FPU in pass1 is known to have issues. */
+		c->options |= MIPS_CPU_FPU | MIPS_CPU_32FPR;
+#endif
+		break;
+	default:
+		c->cputype = CPU_UNKNOWN;
+		break;
+	}
+}
+
+static inline void cpu_probe_sandcraft(struct cpuinfo_mips *c)
+{
+	decode_config1(c);
+	switch (c->processor_id & 0xff00) {
+	case PRID_IMP_SR71000:
+		c->cputype = CPU_SR71000;
+		c->isa_level = MIPS_CPU_ISA_M64;
+		c->options = MIPS_CPU_TLB | MIPS_CPU_4KEX |
+                                    MIPS_CPU_4KTLB | MIPS_CPU_FPU |
+		             MIPS_CPU_COUNTER | MIPS_CPU_MCHECK;
+		c->scache.ways = 8;
+		c->tlbsize = 64;
+		break;
+	default:
+		c->cputype = CPU_UNKNOWN;
+		break;
+	}
+}
+
+__init void cpu_probe(void)
+{
+	struct cpuinfo_mips *c = &current_cpu_data;
+
+	c->processor_id	= PRID_IMP_UNKNOWN;
+	c->fpu_id	= FPIR_IMP_NONE;
+	c->cputype	= CPU_UNKNOWN;
+
+	c->processor_id = read_c0_prid();
+	switch (c->processor_id & 0xff0000) {
+
+	case PRID_COMP_LEGACY:
+		cpu_probe_legacy(c);
+		break;
+	case PRID_COMP_MIPS:
+		cpu_probe_mips(c);
+		break;
+	case PRID_COMP_ALCHEMY:
+		cpu_probe_alchemy(c);
+		break;
+	case PRID_COMP_SIBYTE:
+		cpu_probe_sibyte(c);
 		break;
 
 	case PRID_COMP_SANDCRAFT:
-		switch (c->processor_id & 0xff00) {
-		case PRID_IMP_SR71000:
-			c->cputype = CPU_SR71000;
-			c->isa_level = MIPS_CPU_ISA_M64;
-			c->options = MIPS_CPU_TLB | MIPS_CPU_4KEX |
-                                     MIPS_CPU_4KTLB | MIPS_CPU_FPU |
-			             MIPS_CPU_COUNTER | MIPS_CPU_MCHECK;
-			c->scache.ways = 8;
-			c->tlbsize = 64;
-			break;
-		default:
-			c->cputype = CPU_UNKNOWN;
-			break;
-		}
+		cpu_probe_sandcraft(c);
 		break;
 	default:
 		c->cputype = CPU_UNKNOWN;
--- diff/arch/mips/kernel/entry.S	2003-08-20 14:16:25.000000000 +0100
+++ source/arch/mips/kernel/entry.S	2004-02-23 13:56:38.000000000 +0000
@@ -52,9 +52,10 @@ ENTRY(resume_kernel)
 need_resched:
 	LONG_L	t0, TI_FLAGS($28)
 	andi	t1, t0, _TIF_NEED_RESCHED
-	beqz	restore_all
-	if (in_exception_path)
-		goto restore_all;
+	beqz	t1, restore_all
+	LONG_L	t0, PT_STATUS(sp)		# Interrupts off?
+	andi	t0, 1
+	beqz	t0, restore_all
 	li	t0, PREEMPT_ACTIVE
 	sw	t0, TI_PRE_COUNT($28)
 	local_irq_enable t0
@@ -64,7 +65,7 @@ need_resched:
 #endif
 
 FEXPORT(ret_from_fork)
-	jal	schedule_tail
+	jal	schedule_tail		# a0 = task_t *prev
 
 FEXPORT(syscall_exit)
 	local_irq_disable		# make sure need_resched and
@@ -75,14 +76,19 @@ FEXPORT(syscall_exit)
 	and	t0, a2, t0
 	bnez	t0, syscall_exit_work
 
-FEXPORT(restore_all)
+FEXPORT(restore_all)			# restore full frame
 	.set	noat
-	RESTORE_ALL_AND_RET
+	RESTORE_TEMP
+	RESTORE_AT
+	RESTORE_STATIC
+FEXPORT(restore_partial)		# restore partial frame
+	RESTORE_SOME
+	RESTORE_SP_AND_RET
 	.set	at
 
 FEXPORT(work_pending)
 	andi	t0, a2, _TIF_NEED_RESCHED
-	bnez	t0, work_notifysig
+	beqz	t0, work_notifysig
 work_resched:
 	jal	schedule
 
@@ -103,11 +109,13 @@ work_notifysig:				# deal with pending s
 	jal	do_notify_resume	# a2 already loaded
 	j	restore_all
 
+FEXPORT(syscall_exit_work_partial)
+	SAVE_STATIC
 FEXPORT(syscall_exit_work)
 	LONG_L	t0, TI_FLAGS($28)
 	li	t1, _TIF_SYSCALL_TRACE
 	and	t0, t1
-	bnez	t0, work_pending	# trace bit is set
+	beqz	t0, work_pending	# trace bit is set
 	local_irq_enable		# could let do_syscall_trace()
 					# call schedule() instead
 	jal	do_syscall_trace
--- diff/arch/mips/kernel/gdb-low.S	2003-08-20 14:16:25.000000000 +0100
+++ source/arch/mips/kernel/gdb-low.S	2004-02-23 13:56:38.000000000 +0000
@@ -62,7 +62,7 @@
 1:
 		move	k0, sp
 		subu	sp, k1, GDB_FR_SIZE*2	# see comment above
-		LONG_S	$26, GDB_FR_REG29(sp)
+		LONG_S	k0, GDB_FR_REG29(sp)
 		LONG_S	$2, GDB_FR_REG2(sp)
 
 /*
@@ -90,7 +90,7 @@
 		LONG_S	$1, GDB_FR_REG1(sp)
 		/* v0 already saved */
 		LONG_S	$3, GDB_FR_REG3(sp)
-		LONG_S	$3, GDB_FR_REG4(sp)
+		LONG_S	$4, GDB_FR_REG4(sp)
 		LONG_S	$5, GDB_FR_REG5(sp)
 		LONG_S	$6, GDB_FR_REG6(sp)
 		LONG_S	$7, GDB_FR_REG7(sp)
@@ -296,7 +296,7 @@
 		LONG_L	v0, GDB_FR_HI(sp)
 		LONG_L	v1, GDB_FR_LO(sp)
 		mthi	v0
-		mtlo	v0
+		mtlo	v1
 		LONG_L	$31, GDB_FR_REG31(sp)
 		LONG_L	$30, GDB_FR_REG30(sp)
 		LONG_L	$28, GDB_FR_REG28(sp)
--- diff/arch/mips/kernel/gdb-stub.c	2003-08-20 14:16:25.000000000 +0100
+++ source/arch/mips/kernel/gdb-stub.c	2004-02-23 13:56:38.000000000 +0000
@@ -134,6 +134,7 @@
 #include <linux/reboot.h>
 
 #include <asm/asm.h>
+#include <asm/cacheflush.h>
 #include <asm/mipsregs.h>
 #include <asm/pgtable.h>
 #include <asm/system.h>
@@ -233,7 +234,7 @@ static void getpacket(char *buffer)
 		 * now, read until a # or end of buffer is found
 		 */
 		while (count < BUFMAX) {
-			ch = getDebugChar() & 0x7f;
+			ch = getDebugChar();
 			if (ch == '#')
 				break;
 			checksum = checksum + ch;
@@ -339,15 +340,22 @@ static unsigned char *mem2hex(char *mem,
  * may_fault is non-zero if we are reading from arbitrary memory, but is currently
  * not used.
  */
-static char *hex2mem(char *buf, char *mem, int count, int may_fault)
+static char *hex2mem(char *buf, char *mem, int count, int binary, int may_fault)
 {
 	int i;
 	unsigned char ch;
 
 	for (i=0; i<count; i++)
 	{
-		ch = hex(*buf++) << 4;
-		ch |= hex(*buf++);
+		if (binary) {
+			ch = *buf++;
+			if (ch == 0x7d)
+				ch = 0x20 ^ *buf++;
+		}
+		else {
+			ch = hex(*buf++) << 4;
+			ch |= hex(*buf++);
+		}
 		if (kgdb_write_byte(ch, mem++) != 0)
 			return 0;
 	}
@@ -414,10 +422,10 @@ void restore_debug_traps(void)
 	struct hard_trap_info *ht;
 	unsigned long flags;
 
-	save_and_cli(flags);
+	local_irq_save(flags);
 	for (ht = hard_trap_info; ht->tt && ht->signo; ht++)
 		set_except_vector(ht->tt, saved_vectors[ht->tt]);
-	restore_flags(flags);
+	local_irq_restore(flags);
 }
 
 /*
@@ -669,6 +677,7 @@ void handle_exception (struct gdb_regs *
 	char *ptr;
 	unsigned long *stack;
 	int i;
+	int bflag = 0;
 
 	kgdb_started = 1;
 
@@ -695,7 +704,7 @@ void handle_exception (struct gdb_regs *
 	/* 
 	 * acquire the CPU spinlocks
 	 */
-	for (i=0; i< smp_num_cpus; i++) 
+	for (i = num_online_cpus()-1; i >= 0; i--)
 		if (spin_trylock(&kgdb_cpulock[i]) == 0)
 			panic("kgdb: couldn't get cpulock %d\n", i);
 
@@ -817,17 +826,17 @@ void handle_exception (struct gdb_regs *
 		case 'G':
 		{
 			ptr = &input_buffer[1];
-			hex2mem(ptr, (char *)&regs->reg0, 32*sizeof(long), 0);
+			hex2mem(ptr, (char *)&regs->reg0, 32*sizeof(long), 0, 0);
 			ptr += 32*(2*sizeof(long));
-			hex2mem(ptr, (char *)&regs->cp0_status, 6*sizeof(long), 0);
+			hex2mem(ptr, (char *)&regs->cp0_status, 6*sizeof(long), 0, 0);
 			ptr += 6*(2*sizeof(long));
-			hex2mem(ptr, (char *)&regs->fpr0, 32*sizeof(long), 0);
+			hex2mem(ptr, (char *)&regs->fpr0, 32*sizeof(long), 0, 0);
 			ptr += 32*(2*sizeof(long));
-			hex2mem(ptr, (char *)&regs->cp1_fsr, 2*sizeof(long), 0);
+			hex2mem(ptr, (char *)&regs->cp1_fsr, 2*sizeof(long), 0, 0);
 			ptr += 2*(2*sizeof(long));
-			hex2mem(ptr, (char *)&regs->frame_ptr, 2*sizeof(long), 0);
+			hex2mem(ptr, (char *)&regs->frame_ptr, 2*sizeof(long), 0, 0);
 			ptr += 2*(2*sizeof(long));
-			hex2mem(ptr, (char *)&regs->cp0_index, 16*sizeof(long), 0);
+			hex2mem(ptr, (char *)&regs->cp0_index, 16*sizeof(long), 0, 0);
 			strcpy(output_buffer,"OK");
 		 }
 		break;
@@ -849,6 +858,13 @@ void handle_exception (struct gdb_regs *
 			break;
 
 		/*
+		 * XAA..AA,LLLL: Write LLLL escaped binary bytes at address AA.AA
+		 */
+		case 'X':
+			bflag = 1;
+			/* fall through */
+
+		/*
 		 * MAA..AA,LLLL: Write LLLL bytes at address AA.AA return OK
 		 */
 		case 'M':
@@ -858,7 +874,7 @@ void handle_exception (struct gdb_regs *
 				&& *ptr++ == ','
 				&& hexToInt(&ptr, &length)
 				&& *ptr++ == ':') {
-				if (hex2mem(ptr, (char *)addr, length, 1))
+				if (hex2mem(ptr, (char *)addr, length, bflag, 1))
 					strcpy(output_buffer, "OK");
 				else
 					strcpy(output_buffer, "E03");
@@ -963,7 +979,7 @@ finish_kgdb:
 
 exit_kgdb_exception:
 	/* release locks so other CPUs can go */
-	for (i=0; i < smp_num_cpus; i++) 
+	for (i = num_online_cpus()-1; i >= 0; i--)
 		spin_unlock(&kgdb_cpulock[i]);
 	spin_unlock(&kgdb_lock);
 
@@ -985,7 +1001,7 @@ void breakpoint(void)
 	__asm__ __volatile__(
 			".globl	breakinst\n\t" 
 			".set\tnoreorder\n\t"
-			"nop\n\t"
+			"nop\n"
 			"breakinst:\tbreak\n\t"
 			"nop\n\t"
 			".set\treorder"
@@ -998,7 +1014,7 @@ void async_breakpoint(void)
 	__asm__ __volatile__(
 			".globl	async_breakinst\n\t" 
 			".set\tnoreorder\n\t"
-			"nop\n\t"
+			"nop\n"
 			"async_breakinst:\tbreak\n\t"
 			"nop\n\t"
 			".set\treorder"
@@ -1061,9 +1077,13 @@ static struct console gdb_console = {
 	.index	= -1
 };
 
-__init void register_gdb_console(void)
+static int __init register_gdb_console(void)
 {
 	register_console(&gdb_console);
+
+	return 0;
 }
 
+console_initcall(register_gdb_console);
+
 #endif
--- diff/arch/mips/kernel/genex.S	2003-08-20 14:16:36.000000000 +0100
+++ source/arch/mips/kernel/genex.S	2004-02-23 13:56:38.000000000 +0000
@@ -17,6 +17,7 @@
 #include <asm/fpregdef.h>
 #include <asm/mipsregs.h>
 #include <asm/stackframe.h>
+#include <asm/war.h>
 
 	__INIT
 
@@ -123,84 +124,82 @@ NESTED(except_vec4, 0, sp)
 1:	j	1b			/* Dummy, will be replaced */
 	END(except_vec4)
 
-	/*
-	 * EJTAG debug exception handler.
-	 * The EJTAG debug exception entry point is 0xbfc00480, which
-	 * normally is in the boot PROM, so the boot PROM must do a
-	 * unconditional jump to this vector.
-	 */
+/*
+ * EJTAG debug exception handler.
+ * The EJTAG debug exception entry point is 0xbfc00480, which
+ * normally is in the boot PROM, so the boot PROM must do a
+ * unconditional jump to this vector.
+ */
 NESTED(except_vec_ejtag_debug, 0, sp)
 	j	ejtag_debug_handler
-	 nop
 	END(except_vec_ejtag_debug)
 
 	__FINIT
 
-	/*
-	 * EJTAG debug exception handler.
-	 */
-	NESTED(ejtag_debug_handler, PT_SIZE, sp)
+/*
+ * EJTAG debug exception handler.
+ */
+NESTED(ejtag_debug_handler, PT_SIZE, sp)
+	.set	push
 	.set	noat
 	.set	noreorder
-	mtc0	k0, CP0_DESAVE
+	MTC0	k0, CP0_DESAVE
 	mfc0	k0, CP0_DEBUG
 
 	sll	k0, k0, 30	# Check for SDBBP.
 	bgez	k0, ejtag_return
+	nop
 
-	la	k0, ejtag_debug_buffer
-	sw	k1, 0(k0)
+	PTR_LA	k0, ejtag_debug_buffer
+	LONG_S	k1, 0(k0)
 	SAVE_ALL
 	jal	ejtag_exception_handler
 	 move	a0, sp
 	RESTORE_ALL
-	la	k0, ejtag_debug_buffer
-	lw	k1, 0(k0)
+	PTR_LA	k0, ejtag_debug_buffer
+	LONG_L	k1, 0(k0)
 
 ejtag_return:
-	mfc0	k0, CP0_DESAVE
+	MFC0	k0, CP0_DESAVE
 	.set	mips32
 	deret
-	.set	mips0
-	 nop
-	.set	at
+ 	 nop
+	.set pop
 	END(ejtag_debug_handler)
 
-	/*
-	 * This buffer is reserved for the use of the EJTAG debug
-	 * handler.
-	 */
+/*
+ * This buffer is reserved for the use of the EJTAG debug
+ * handler.
+ */
 	.data
-	EXPORT(ejtag_debug_buffer)
+EXPORT(ejtag_debug_buffer)
 	.fill	LONGSIZE
 	.previous
 
 	__INIT
 
-	/*
-	 * NMI debug exception handler for MIPS reference boards.
-	 * The NMI debug exception entry point is 0xbfc00000, which
-	 * normally is in the boot PROM, so the boot PROM must do a
-	 * unconditional jump to this vector.
-	 */
-	NESTED(except_vec_nmi, 0, sp)
+/*
+ * NMI debug exception handler for MIPS reference boards.
+ * The NMI debug exception entry point is 0xbfc00000, which
+ * normally is in the boot PROM, so the boot PROM must do a
+ * unconditional jump to this vector.
+ */
+NESTED(except_vec_nmi, 0, sp)
 	j	nmi_handler
-	 nop
 	END(except_vec_nmi)
 
 	__FINIT
 
-	NESTED(nmi_handler, PT_SIZE, sp)
+NESTED(nmi_handler, PT_SIZE, sp)
+	.set	push
 	.set	noat
-	.set	noreorder
 	.set	mips3
 	SAVE_ALL
-	jal	nmi_exception_handler
  	move	a0, sp
+	jal	nmi_exception_handler
 	RESTORE_ALL
 	eret
-	.set	at
-	.set	mips0
+	.set	pop
 	END(nmi_handler)
 
 	.macro	__build_clear_none
@@ -236,34 +235,41 @@ ejtag_return:
 	   recognize an unknown escape code.  So make the arguments
 	   start with an n and gas will believe \n is ok ...  */
 	.macro	__BUILD_verbose	nexception
-	ld	a1, PT_EPC(sp)
+	LONG_L	a1, PT_EPC(sp)
+#if CONFIG_MIPS32
+	PRINT("Got \nexception at %08lx\012")
+#endif	
+#if CONFIG_MIPS64
 	PRINT("Got \nexception at %016lx\012")
+#endif	
 	.endm
 
 	.macro	__BUILD_count exception
-	.set	reorder
 	LONG_L	t0,exception_count_\exception
 	LONG_ADDIU t0, 1
 	LONG_S	t0,exception_count_\exception
-	.set	noreorder
 	.comm	exception_count\exception, 8, 8
 	.endm
 
-	.macro	BUILD_HANDLER exception handler clear verbose
+	.macro	__BUILD_HANDLER exception handler clear verbose ext
 	.align	5
 	NESTED(handle_\exception, PT_SIZE, sp)
 	.set	noat
 	SAVE_ALL
+	FEXPORT(handle_\exception\ext)
 	__BUILD_clear_\clear
 	.set	at
 	__BUILD_\verbose \exception
 	move	a0, sp
 	jal	do_\handler
 	j	ret_from_exception
-	 nop
 	END(handle_\exception)
 	.endm
 
+	.macro	BUILD_HANDLER exception handler clear verbose
+	__BUILD_HANDLER	\exception \handler \clear \verbose _int
+	.endm
+
 	BUILD_HANDLER adel ade ade silent		/* #4  */
 	BUILD_HANDLER ades ade ade silent		/* #5  */
 	BUILD_HANDLER ibe be cli silent			/* #6  */
--- diff/arch/mips/kernel/head.S	2003-08-20 14:16:25.000000000 +0100
+++ source/arch/mips/kernel/head.S	2004-02-23 13:56:38.000000000 +0000
@@ -20,7 +20,6 @@
 #include <asm/asm.h>
 #include <asm/regdef.h>
 #include <asm/page.h>
-#include <asm/processor.h>
 #include <asm/mipsregs.h>
 #include <asm/stackframe.h>
 #ifdef CONFIG_SGI_IP27
@@ -91,6 +90,19 @@
 	.endm
 
 	/*
+	 * For the moment set ST0_KU so the CPU will not spit fire when
+	 * executing 64-bit instructions.  The full initialization of the
+	 * CPU's status register is done later in per_cpu_trap_init().
+	 */
+	.macro	setup_c0_status
+#ifdef CONFIG_MIPS64
+	mfc0	t0, CP0_STATUS
+	or	t0, ST0_KX
+	mtc0	t0, CP0_STATUS
+#endif
+	.endm
+
+	/*
 	 * Reserved space for exception handlers.
 	 * Necessary for machines which link their kernels at KSEG0.
 	 */
@@ -102,6 +114,8 @@ EXPORT(_stext)
 	__INIT
 
 NESTED(kernel_entry, 16, sp)			# kernel entry point
+	setup_c0_status
+
 #ifdef CONFIG_SGI_IP27
 	GET_NASID_ASM	t1
 	move	t2, t1				# text and data are here
@@ -112,18 +126,7 @@ NESTED(kernel_entry, 16, sp)			# kernel 
 
 	CLI					# disable interrupts
 
-	PTR_LA		$28, init_thread_union
-	PTR_ADDIU	sp, $28, _THREAD_SIZE - 32
-	set_saved_sp	sp, t0, t1
-	PTR_SUBU	sp, 4 * SZREG		# init stack pointer
-
-	/*
-	 * The firmware/bootloader passes argc/argp/envp
-	 * to us as arguments.  But clear bss first because
-	 * the romvec and other important info is stored there
-	 * by prom_init().
-	 */
-	PTR_LA		t0, __bss_start
+	PTR_LA		t0, __bss_start		# clear .bss
 	LONG_S		zero, (t0)
 	PTR_LA		t1, __bss_stop - LONGSIZE
 1:
@@ -131,7 +134,17 @@ NESTED(kernel_entry, 16, sp)			# kernel 
 	LONG_S		zero, (t0)
 	bne		t0, t1, 1b
 
-	jal		init_arch
+	LONG_S		a0, fw_arg0		# firmware arguments
+	LONG_S		a1, fw_arg1
+	LONG_S		a2, fw_arg2
+	LONG_S		a3, fw_arg3
+
+	PTR_LA		$28, init_thread_union
+	PTR_ADDIU	sp, $28, _THREAD_SIZE - 32
+	set_saved_sp	sp, t0, t1
+	PTR_SUBU	sp, 4 * SZREG		# init stack pointer
+
+	jal		start_kernel
 	END(kernel_entry)
 
 #ifdef CONFIG_SMP
@@ -142,8 +155,8 @@ NESTED(kernel_entry, 16, sp)			# kernel 
 NESTED(smp_bootstrap, 16, sp)
 #ifdef CONFIG_SGI_IP27
 	GET_NASID_ASM	t1
-	li	t0, KLDIR_OFFSET + (KLI_KERN_VARS * KLDIR_ENT_SIZE) + \
-		    KLDIR_OFF_POINTER + K0BASE
+	dli	t0, KLDIR_OFFSET + (KLI_KERN_VARS * KLDIR_ENT_SIZE) + \
+		    KLDIR_OFF_POINTER + CAC_BASE
 	dsll	t1, NASID_SHFT
 	or	t0, t0, t1
 	ld	t0, 0(t0)			# t0 points to kern_vars struct
@@ -154,17 +167,7 @@ NESTED(smp_bootstrap, 16, sp)
 #endif /* CONFIG_SGI_IP27 */
 
 	CLI
-
-#ifdef CONFIG_MIPS64
-	/*
-	 * For the moment set ST0_KU so the CPU will not spit fire when
-	 * executing 64-bit instructions.  The full initialization of the
-	 * CPU's status register is done later in per_cpu_trap_init().
-	 */
-	mfc0	t0, CP0_STATUS
-	or	t0, ST0_KX
-	mtc0	t0, CP0_STATUS
-#endif
+	setup_c0_status
 	jal	start_secondary
 	END(smp_bootstrap)
 #endif /* CONFIG_SMP */
@@ -174,6 +177,11 @@ NESTED(smp_bootstrap, 16, sp)
 	.comm	kernelsp,    NR_CPUS * 8, 8
 	.comm	pgd_current, NR_CPUS * 8, 8
 
+	.comm	fw_arg0, SZREG, SZREG		# firmware arguments
+	.comm	fw_arg1, SZREG, SZREG
+	.comm	fw_arg2, SZREG, SZREG
+	.comm	fw_arg3, SZREG, SZREG
+
 	.macro	page name, order=0
 	.globl	\name
 \name:	.size	\name, (_PAGE_SIZE << \order)
@@ -184,22 +192,17 @@ NESTED(smp_bootstrap, 16, sp)
 	.data
 	.align	PAGE_SHIFT
 
-#ifdef CONFIG_MIPS32
-	/*
-	 * Here we only have a two-level pagetable structure ...
-	 */
-	page	swapper_pg_dir, _PGD_ORDER
-	page	invalid_pte_table, _PTE_ORDER
-#endif
-#ifdef CONFIG_MIPS64
 	/*
 	 * ... but on 64-bit we've got three-level pagetables with a
 	 * slightly different layout ...
 	 */
 	page	swapper_pg_dir, _PGD_ORDER
+#ifdef CONFIG_MIPS64
 	page	invalid_pmd_table, _PMD_ORDER
+#endif
 	page	invalid_pte_table, _PTE_ORDER
 
+#ifdef CONFIG_MIPS64
 	/*
 	 * 64-bit kernel mappings are really screwed up ...
 	 */
--- diff/arch/mips/kernel/i8259.c	2003-07-08 09:55:17.000000000 +0100
+++ source/arch/mips/kernel/i8259.c	2004-02-23 13:56:38.000000000 +0000
@@ -31,7 +31,7 @@ void disable_8259A_irq(unsigned int irq)
  * moves to arch independent land
  */
 
-static spinlock_t i8259A_lock = SPIN_LOCK_UNLOCKED;
+spinlock_t i8259A_lock = SPIN_LOCK_UNLOCKED;
 
 static void end_8259A_irq (unsigned int irq)
 {
@@ -242,7 +242,7 @@ static int __init i8259A_init_sysfs(void
 {
 	int error = sysdev_class_register(&i8259_sysdev_class);
 	if (!error)
-		error = sys_device_register(&device_i8259A);
+		error = sysdev_register(&device_i8259A);
 	return error;
 }
 
@@ -291,11 +291,6 @@ void __init init_8259A(int auto_eoi)
 	spin_unlock_irqrestore(&i8259A_lock, flags);
 }
 
-asmlinkage void i8259_do_irq(int irq, struct pt_regs regs)
-{
-	panic("i8259_do_irq: I want to be implemented");
-}
-
 /*
  * IRQ2 is cascade interrupt to second interrupt controller
  */
--- diff/arch/mips/kernel/init_task.c	2003-10-09 09:47:33.000000000 +0100
+++ source/arch/mips/kernel/init_task.c	2004-02-23 13:56:38.000000000 +0000
@@ -4,6 +4,7 @@
 #include <linux/init_task.h>
 #include <linux/fs.h>
 
+#include <asm/thread_info.h>
 #include <asm/uaccess.h>
 #include <asm/pgtable.h>
 
@@ -26,7 +27,8 @@ EXPORT_SYMBOL(init_mm);
  * The things we do for performance..
  */
 union thread_union init_thread_union
-	__attribute__((__section__(".data.init_task"))) =
+	__attribute__((__section__(".data.init_task"),
+	               __aligned__(THREAD_SIZE))) =
 		{ INIT_THREAD_INFO(init_task) };
 
 /*
--- diff/arch/mips/kernel/ioctl32.c	2003-09-17 12:28:02.000000000 +0100
+++ source/arch/mips/kernel/ioctl32.c	2004-02-23 13:56:38.000000000 +0000
@@ -4,7 +4,7 @@
  * Copyright (C) 2000 Silicon Graphics, Inc.
  * Written by Ulf Carlsson (ulfc@engr.sgi.com)
  * Copyright (C) 2000 Ralf Baechle
- * Copyright (C) 2002  Maciej W. Rozycki
+ * Copyright (C) 2002, 2003  Maciej W. Rozycki
  *
  * Mostly stolen from the sparc64 ioctl32 implementation.
  */
@@ -33,7 +33,9 @@
 #include <linux/blkdev.h>
 #include <linux/loop.h>
 #include <linux/fb.h>
+#include <linux/i2c.h>
 #include <linux/vt.h>
+#include <linux/vt_kern.h>
 #include <linux/kd.h>
 #include <linux/ext2_fs.h>
 #include <linux/videodev.h>
@@ -45,7 +47,6 @@
 #include <linux/hdreg.h>
 #include <linux/raid/md.h>
 #include <linux/blkpg.h>
-#include <linux/blkdev.h>
 #include <linux/elevator.h>
 #include <linux/rtc.h>
 #include <linux/pci.h>
@@ -60,6 +61,7 @@
 #include <linux/ethtool.h>
 #include <linux/mii.h>
 #include <linux/if_bonding.h>
+#include <linux/syscalls.h>
 #include <linux/watchdog.h>
 
 #include <asm/ioctls.h>
@@ -89,13 +91,12 @@
 #include <linux/nbd.h>
 #include <linux/random.h>
 #include <linux/filter.h>
+#include <linux/wireless.h>
 
 #ifdef CONFIG_SIBYTE_TBPROF
 #include <asm/sibyte/trace_prof.h>
 #endif
 
-long sys_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg);
-
 static int w_long(unsigned int fd, unsigned int cmd, unsigned long arg)
 {
 	mm_segment_t old_fs = get_fs();
@@ -383,7 +384,7 @@ static inline int dev_ifconf(unsigned in
 	struct ifreq32 *ifr32;
 	struct ifreq *ifr;
 	mm_segment_t old_fs;
-	int len;
+	unsigned int i, j;
 	int err;
 
 	if (copy_from_user(&ifc32, uifc32, sizeof(struct ifconf32)))
@@ -402,16 +403,14 @@ static inline int dev_ifconf(unsigned in
 	}
 	ifr = ifc.ifc_req;
 	ifr32 = (struct ifreq32 *)A(ifc32.ifcbuf);
-	len = ifc32.ifc_len / sizeof (struct ifreq32);
-	while (len--) {
+	for (i = 0; i < ifc32.ifc_len; i += sizeof (struct ifreq32)) {
 		if (copy_from_user(ifr++, ifr32++, sizeof (struct ifreq32))) {
-			err = -EFAULT;
-			goto out;
+			kfree (ifc.ifc_buf);
+			return -EFAULT;
 		}
 	}
 
-	old_fs = get_fs();
-	set_fs (KERNEL_DS);
+	old_fs = get_fs(); set_fs (KERNEL_DS);
 	err = sys_ioctl (fd, SIOCGIFCONF, (unsigned long)&ifc);
 	set_fs (old_fs);
 	if (err)
@@ -419,16 +418,26 @@ static inline int dev_ifconf(unsigned in
 
 	ifr = ifc.ifc_req;
 	ifr32 = (struct ifreq32 *)A(ifc32.ifcbuf);
-	len = ifc.ifc_len / sizeof (struct ifreq);
-	ifc32.ifc_len = len * sizeof (struct ifreq32);
-
-	while (len--) {
+	for (i = 0, j = 0; i < ifc32.ifc_len && j < ifc.ifc_len;
+	     i += sizeof (struct ifreq32), j += sizeof (struct ifreq)) {
 		if (copy_to_user(ifr32++, ifr++, sizeof (struct ifreq32))) {
 			err = -EFAULT;
 			goto out;
 		}
 	}
-
+	if (ifc32.ifcbuf == 0) {
+		/* Translate from 64-bit structure multiple to
+		 * a 32-bit one.
+		 */
+		i = ifc.ifc_len;
+		i = ((i / sizeof(struct ifreq)) * sizeof(struct ifreq32));
+		ifc32.ifc_len = i;
+	} else {
+		if (i <= ifc32.ifc_len)
+			ifc32.ifc_len = i;
+		else
+			ifc32.ifc_len = i - sizeof (struct ifreq32);
+	}
 	if (copy_to_user(uifc32, &ifc32, sizeof(struct ifconf32))) {
 		err = -EFAULT;
 		goto out;
@@ -803,6 +812,120 @@ static int ioc_settimeout(unsigned int f
 	return rw_long(fd, AUTOFS_IOC_SETTIMEOUT, arg);
 }
 
+#ifdef CONFIG_VT
+
+extern int tty_ioctl(struct inode * inode, struct file * file, unsigned int cmd, unsigned long arg);
+
+static int vt_check(struct file *file)
+{
+	struct tty_struct *tty;
+	struct inode *inode = file->f_dentry->d_inode;
+	
+	if (file->f_op->ioctl != tty_ioctl)
+		return -EINVAL;
+	                
+	tty = (struct tty_struct *)file->private_data;
+	if (tty_paranoia_check(tty, inode, "tty_ioctl"))
+		return -EINVAL;
+	                                                
+	if (tty->driver->ioctl != vt_ioctl)
+		return -EINVAL;
+	
+	/*
+	 * To have permissions to do most of the vt ioctls, we either have
+	 * to be the owner of the tty, or super-user.
+	 */
+	if (current->tty == tty || capable(CAP_SYS_TTY_CONFIG))
+		return 1;
+	return 0;
+}
+
+struct consolefontdesc32 {
+	unsigned short charcount;       /* characters in font (256 or 512) */
+	unsigned short charheight;      /* scan lines per character (1-32) */
+	u32 chardata;			/* font data in expanded form */
+};
+
+static int do_fontx_ioctl(unsigned int fd, int cmd, struct consolefontdesc32 *user_cfd, struct file *file)
+{
+	struct consolefontdesc cfdarg;
+	struct console_font_op op;
+	int i, perm;
+
+	perm = vt_check(file);
+	if (perm < 0) return perm;
+	
+	if (copy_from_user(&cfdarg, user_cfd, sizeof(struct consolefontdesc32)))
+		return -EFAULT;
+	
+	cfdarg.chardata = (unsigned char *)A(((struct consolefontdesc32 *)&cfdarg)->chardata);
+ 	
+	switch (cmd) {
+	case PIO_FONTX:
+		if (!perm)
+			return -EPERM;
+		op.op = KD_FONT_OP_SET;
+		op.flags = 0;
+		op.width = 8;
+		op.height = cfdarg.charheight;
+		op.charcount = cfdarg.charcount;
+		op.data = cfdarg.chardata;
+		return con_font_op(fg_console, &op);
+	case GIO_FONTX:
+		if (!cfdarg.chardata)
+			return 0;
+		op.op = KD_FONT_OP_GET;
+		op.flags = 0;
+		op.width = 8;
+		op.height = cfdarg.charheight;
+		op.charcount = cfdarg.charcount;
+		op.data = cfdarg.chardata;
+		i = con_font_op(fg_console, &op);
+		if (i)
+			return i;
+		cfdarg.charheight = op.height;
+		cfdarg.charcount = op.charcount;
+		((struct consolefontdesc32 *)&cfdarg)->chardata	= (unsigned long)cfdarg.chardata;
+		if (copy_to_user(user_cfd, &cfdarg, sizeof(struct consolefontdesc32)))
+			return -EFAULT;
+		return 0;
+	}
+	return -EINVAL;
+}
+
+struct console_font_op32 {
+	unsigned int op;        /* operation code KD_FONT_OP_* */
+	unsigned int flags;     /* KD_FONT_FLAG_* */
+	unsigned int width, height;     /* font size */
+	unsigned int charcount;
+	u32 data;    /* font data with height fixed to 32 */
+};
+                                        
+static int do_kdfontop_ioctl(unsigned int fd, unsigned int cmd, struct console_font_op32 *fontop, struct file *file)
+{
+	struct console_font_op op;
+	int perm = vt_check(file), i;
+	struct vt_struct *vt;
+	
+	if (perm < 0) return perm;
+	
+	if (copy_from_user(&op, (void *) fontop, sizeof(struct console_font_op32)))
+		return -EFAULT;
+	if (!perm && op.op != KD_FONT_OP_GET)
+		return -EPERM;
+	op.data = (unsigned char *)A(((struct console_font_op32 *)&op)->data);
+	op.flags |= KD_FONT_FLAG_OLD;
+	vt = (struct vt_struct *)((struct tty_struct *)file->private_data)->driver_data;
+	i = con_font_op(vt->vc_num, &op);
+	if (i) return i;
+	((struct console_font_op32 *)&op)->data = (unsigned long)op.data;
+	if (copy_to_user((void *) fontop, &op, sizeof(struct console_font_op32)))
+		return -EFAULT;
+	return 0;
+}
+
+#endif
+
 typedef int (* ioctl32_handler_t)(unsigned int, unsigned int, unsigned long, struct file *);
                                                                                 
 #define COMPATIBLE_IOCTL(cmd)		HANDLE_IOCTL((cmd),sys_ioctl)
@@ -819,6 +942,7 @@ COMPATIBLE_IOCTL(TCSETA)
 COMPATIBLE_IOCTL(TCSETAW)
 COMPATIBLE_IOCTL(TCSETAF)
 COMPATIBLE_IOCTL(TCSBRK)
+COMPATIBLE_IOCTL(TCSBRKP)
 COMPATIBLE_IOCTL(TCXONC)
 COMPATIBLE_IOCTL(TCFLSH)
 COMPATIBLE_IOCTL(TCGETS)
@@ -869,6 +993,7 @@ HANDLE_IOCTL(FBIOPUTCMAP, do_fbiocmap_io
 COMPATIBLE_IOCTL(FBIOPAN_DISPLAY)
 #endif /* CONFIG_FB */
 
+#ifdef CONFIG_VT
 /* Big K */
 COMPATIBLE_IOCTL(PIO_FONT)
 COMPATIBLE_IOCTL(GIO_FONT)
@@ -901,16 +1026,8 @@ COMPATIBLE_IOCTL(GIO_UNISCRNMAP)
 COMPATIBLE_IOCTL(PIO_UNISCRNMAP)
 COMPATIBLE_IOCTL(PIO_FONTRESET)
 COMPATIBLE_IOCTL(PIO_UNIMAPCLR)
-
-/* Big S */
-COMPATIBLE_IOCTL(SCSI_IOCTL_GET_IDLUN)
-COMPATIBLE_IOCTL(SCSI_IOCTL_DOORLOCK)
-COMPATIBLE_IOCTL(SCSI_IOCTL_DOORUNLOCK)
-COMPATIBLE_IOCTL(SCSI_IOCTL_TEST_UNIT_READY)
-COMPATIBLE_IOCTL(SCSI_IOCTL_TAGGED_ENABLE)
-COMPATIBLE_IOCTL(SCSI_IOCTL_TAGGED_DISABLE)
-COMPATIBLE_IOCTL(SCSI_IOCTL_GET_BUS_NUMBER)
-COMPATIBLE_IOCTL(SCSI_IOCTL_SEND_COMMAND)
+HANDLE_IOCTL(PIO_FONTX, do_fontx_ioctl)
+HANDLE_IOCTL(KDFONTOP, do_kdfontop_ioctl)
 
 /* Big V */
 COMPATIBLE_IOCTL(VT_SETMODE)
@@ -925,8 +1042,16 @@ COMPATIBLE_IOCTL(VT_RESIZE)
 COMPATIBLE_IOCTL(VT_RESIZEX)
 COMPATIBLE_IOCTL(VT_LOCKSWITCH)
 COMPATIBLE_IOCTL(VT_UNLOCKSWITCH)
+#endif
+
+/* Big S */
+COMPATIBLE_IOCTL(SCSI_IOCTL_GET_IDLUN)
+COMPATIBLE_IOCTL(SCSI_IOCTL_DOORLOCK)
+COMPATIBLE_IOCTL(SCSI_IOCTL_DOORUNLOCK)
+COMPATIBLE_IOCTL(SCSI_IOCTL_TEST_UNIT_READY)
+COMPATIBLE_IOCTL(SCSI_IOCTL_GET_BUS_NUMBER)
+COMPATIBLE_IOCTL(SCSI_IOCTL_SEND_COMMAND)
 
-#ifdef CONFIG_NET
 /* Socket level stuff */
 COMPATIBLE_IOCTL(FIOSETOWN)
 COMPATIBLE_IOCTL(SIOCSPGRP)
@@ -1034,6 +1159,7 @@ COMPATIBLE_IOCTL(DVD_AUTH)
 COMPATIBLE_IOCTL(LOOP_SET_FD)
 COMPATIBLE_IOCTL(LOOP_CLR_FD)
 
+#ifdef CONFIG_NET
 /* And these ioctls need translation */
 HANDLE_IOCTL(SIOCGIFNAME, dev_ifname32)
 HANDLE_IOCTL(SIOCGIFCONF, dev_ifconf)
@@ -1075,7 +1201,6 @@ HANDLE_IOCTL(SIOCDELRT, routing_ioctl)
  */
 HANDLE_IOCTL(SIOCRTMSG, ret_einval)
 HANDLE_IOCTL(SIOCGSTAMP, do_siocgstamp)
-
 #endif /* CONFIG_NET */
 
 HANDLE_IOCTL(EXT2_IOC32_GETFLAGS, do_ext2_ioctl)
@@ -1147,23 +1272,23 @@ COMPATIBLE_IOCTL(RESTART_ARRAY_RW)
 #endif /* CONFIG_MD */
 
 #ifdef CONFIG_SIBYTE_TBPROF
-COMPATIBLE_IOCTL(SBPROF_ZBSTART),
-COMPATIBLE_IOCTL(SBPROF_ZBSTOP),
-COMPATIBLE_IOCTL(SBPROF_ZBWAITFULL),
+COMPATIBLE_IOCTL(SBPROF_ZBSTART)
+COMPATIBLE_IOCTL(SBPROF_ZBSTOP)
+COMPATIBLE_IOCTL(SBPROF_ZBWAITFULL)
 #endif /* CONFIG_SIBYTE_TBPROF */
 
 #if defined(CONFIG_BLK_DEV_DM) || defined(CONFIG_BLK_DEV_DM_MODULE)
-	IOCTL32_DEFAULT(DM_VERSION),
-	IOCTL32_DEFAULT(DM_REMOVE_ALL),
-	IOCTL32_DEFAULT(DM_DEV_CREATE),
-	IOCTL32_DEFAULT(DM_DEV_REMOVE),
-	IOCTL32_DEFAULT(DM_DEV_RELOAD),
-	IOCTL32_DEFAULT(DM_DEV_SUSPEND),
-	IOCTL32_DEFAULT(DM_DEV_RENAME),
-	IOCTL32_DEFAULT(DM_DEV_DEPS),
-	IOCTL32_DEFAULT(DM_DEV_STATUS),
-	IOCTL32_DEFAULT(DM_TARGET_STATUS),
-	IOCTL32_DEFAULT(DM_TARGET_WAIT),
+COMPATIBLE_IOCTL(DM_VERSION)
+COMPATIBLE_IOCTL(DM_REMOVE_ALL)
+COMPATIBLE_IOCTL(DM_DEV_CREATE)
+COMPATIBLE_IOCTL(DM_DEV_REMOVE)
+COMPATIBLE_IOCTL(DM_DEV_RELOAD)
+COMPATIBLE_IOCTL(DM_DEV_SUSPEND)
+COMPATIBLE_IOCTL(DM_DEV_RENAME)
+COMPATIBLE_IOCTL(DM_DEV_DEPS)
+COMPATIBLE_IOCTL(DM_DEV_STATUS)
+COMPATIBLE_IOCTL(DM_TARGET_STATUS)
+COMPATIBLE_IOCTL(DM_TARGET_WAIT)
 #endif /* CONFIG_BLK_DEV_DM */
 
 COMPATIBLE_IOCTL(MTIOCTOP)			/* mtio.h ioctls  */
--- diff/arch/mips/kernel/irixioctl.c	2003-07-08 09:55:17.000000000 +0100
+++ source/arch/mips/kernel/irixioctl.c	2004-02-23 13:56:38.000000000 +0000
@@ -11,6 +11,7 @@
 #include <linux/smp.h>
 #include <linux/smp_lock.h>
 #include <linux/sockios.h>
+#include <linux/syscalls.h>
 #include <linux/tty.h>
 #include <linux/file.h>
 
@@ -26,9 +27,6 @@ struct irix_termios {
 	cc_t c_cc[NCCS];
 };
 
-extern asmlinkage int sys_ioctl(unsigned int fd, unsigned int cmd,
-				unsigned long arg);
-extern asmlinkage int sys_write(unsigned int fd,char * buf,unsigned int count);
 extern void start_tty(struct tty_struct *tty);
 static struct tty_struct *get_tty(int fd)
 {
--- diff/arch/mips/kernel/irixsig.c	2003-09-30 15:46:11.000000000 +0100
+++ source/arch/mips/kernel/irixsig.c	2004-02-23 13:56:38.000000000 +0000
@@ -210,7 +210,10 @@ irix_sigreturn(struct pt_regs *regs)
 	int sig, i, base = 0;
 	sigset_t blocked;
 
-	if(regs->regs[2] == 1000)
+	/* Always make any pending restarted system calls return -EINTR */
+	current_thread_info()->restart_block.fn = do_no_restart_syscall;
+
+	if (regs->regs[2] == 1000)
 		base = 1;
 
 	context = (struct sigctx_irix5 *) regs->regs[base + 4];
--- diff/arch/mips/kernel/irq.c	2004-01-19 10:22:55.000000000 +0000
+++ source/arch/mips/kernel/irq.c	2004-02-23 13:56:38.000000000 +0000
@@ -288,8 +288,10 @@ void inline disable_irq_nosync(unsigned 
 
 void disable_irq(unsigned int irq)
 {
+	irq_desc_t *desc = irq_desc + irq;
 	disable_irq_nosync(irq);
-	synchronize_irq(irq);
+	if (desc->action)
+		synchronize_irq(irq);
 }
 
 /**
@@ -310,7 +312,7 @@ void enable_irq(unsigned int irq)
 	spin_lock_irqsave(&desc->lock, flags);
 	switch (desc->depth) {
 	case 1: {
-		unsigned int status = desc->status & ~IRQ_DISABLED;
+		unsigned int status = desc->status & ~(IRQ_DISABLED | IRQ_INPROGRESS);
 		desc->status = status;
 		if ((status & (IRQ_PENDING | IRQ_REPLAY)) == IRQ_PENDING) {
 			desc->status = status | IRQ_REPLAY;
@@ -706,7 +708,7 @@ unsigned int probe_irq_mask(unsigned lon
  *	appears to have triggered the interrupt. If no interrupt was
  *	found then zero is returned. If more than one interrupt is
  *	found then minus the first candidate is returned to indicate
- *	their is doubt.
+ *	there is doubt.
  *
  *	The interrupt probe logic state is returned to its previous
  *	value.
@@ -835,7 +837,7 @@ static cpumask_t irq_affinity [NR_IRQS] 
 static int irq_affinity_read_proc (char *page, char **start, off_t off,
 			int count, int *eof, void *data)
 {
-	int len = cpumask_snprintf(page, count, irq_affinity[(long)data]);
+	int len = cpumask_scnprintf(page, count, irq_affinity[(long)data]);
 	if (count - len < 2)
 		return -EINVAL;
 	len += sprintf(page + len, "\n");
@@ -858,7 +860,7 @@ static int irq_affinity_write_proc (stru
 	 * way to make the system unusable accidentally :-) At least
 	 * one online CPU still has to be targeted.
 	 */
-	cpus_and(tmp, tmp, cpu_online_map);
+	cpus_and(tmp, new_value, cpu_online_map);
 	if (cpus_empty(tmp))
 		return -EINVAL;
 
@@ -873,7 +875,7 @@ static int irq_affinity_write_proc (stru
 static int prof_cpu_mask_read_proc (char *page, char **start, off_t off,
 			int count, int *eof, void *data)
 {
-	int len = cpumask_snprintf(page, count, *(cpumask_t *)data);
+	int len = cpumask_scnprintf(page, count, *(cpumask_t *)data);
 	if (count - len < 2)
 		return -EINVAL;
 	len += sprintf(page + len, "\n");
--- diff/arch/mips/kernel/irq_cpu.c	2003-07-08 09:55:17.000000000 +0100
+++ source/arch/mips/kernel/irq_cpu.c	2004-02-23 13:56:38.000000000 +0000
@@ -80,7 +80,7 @@ static unsigned int mips_cpu_irq_startup
 static void mips_cpu_irq_ack(unsigned int irq)
 {
 	/* Only necessary for soft interrupts */
-	clear_c0_cause(1 << (irq - mips_cpu_irq_base + 8));
+	clear_c0_cause(0x100 << (irq - mips_cpu_irq_base));
 
 	mask_mips_irq(irq);
 }
@@ -102,6 +102,7 @@ static hw_irq_controller mips_cpu_irq_co
 	NULL			/* no affinity stuff for UP */
 };
 
+
 void __init mips_cpu_irq_init(int irq_base)
 {
 	int i;
--- diff/arch/mips/kernel/linux32.c	2003-10-09 09:47:33.000000000 +0100
+++ source/arch/mips/kernel/linux32.c	2004-02-23 13:56:38.000000000 +0000
@@ -6,6 +6,7 @@
  * sys32_execve from ia64/ia32 code, Feb 2000, Kanoj Sarcar (kanoj@sgi.com)
  */
 #include <linux/config.h>
+#include <linux/compiler.h>
 #include <linux/mm.h>
 #include <linux/errno.h>
 #include <linux/file.h>
@@ -24,6 +25,7 @@
 #include <linux/sem.h>
 #include <linux/msg.h>
 #include <linux/icmpv6.h>
+#include <linux/syscalls.h>
 #include <linux/sysctl.h>
 #include <linux/utime.h>
 #include <linux/utsname.h>
@@ -123,8 +125,6 @@ out:
 }
 
 
-asmlinkage long sys_truncate(const char * path, unsigned long length);
-
 asmlinkage int sys_truncate64(const char *path, unsigned int high,
 			      unsigned int low)
 {
@@ -133,8 +133,6 @@ asmlinkage int sys_truncate64(const char
 	return sys_truncate(path, ((long) high << 32) | low);
 }
 
-asmlinkage long sys_ftruncate(unsigned int fd, unsigned long length);
-
 asmlinkage int sys_ftruncate64(unsigned int fd, unsigned int high,
 			       unsigned int low)
 {
@@ -175,26 +173,34 @@ static int count32(u32 * argv, int max)
  */
 int copy_strings32(int argc, u32 * argv, struct linux_binprm *bprm)
 {
+	struct page *kmapped_page = NULL;
+	char *kaddr = NULL;
+	int ret;
+
 	while (argc-- > 0) {
 		u32 str;
 		int len;
 		unsigned long pos;
 
 		if (get_user(str, argv+argc) || !str ||
-		     !(len = strnlen_user((char *)A(str), bprm->p)))
-			return -EFAULT;
-		if (bprm->p < len)
-			return -E2BIG;
+		     !(len = strnlen_user((char *)A(str), bprm->p))) {
+			ret = -EFAULT;
+			goto out;
+		}
+
+		if (bprm->p < len)  {
+			ret = -E2BIG;
+			goto out;
+		}
 
 		bprm->p -= len;
 		/* XXX: add architecture specific overflow check here. */
 
 		pos = bprm->p;
 		while (len > 0) {
-			char *kaddr;
 			int i, new, err;
-			struct page *page;
 			int offset, bytes_to_copy;
+			struct page *page;
 
 			offset = pos % PAGE_SIZE;
 			i = pos/PAGE_SIZE;
@@ -203,12 +209,19 @@ int copy_strings32(int argc, u32 * argv,
 			if (!page) {
 				page = alloc_page(GFP_HIGHUSER);
 				bprm->page[i] = page;
-				if (!page)
-					return -ENOMEM;
+				if (!page) {
+					ret = -ENOMEM;
+					goto out;
+				}
 				new = 1;
 			}
-			kaddr = kmap(page);
 
+			if (page != kmapped_page) {
+				if (kmapped_page)
+					kunmap(kmapped_page);
+				kmapped_page = page;
+				kaddr = kmap(kmapped_page);
+			}
 			if (new && offset)
 				memset(kaddr, 0, offset);
 			bytes_to_copy = PAGE_SIZE - offset;
@@ -220,20 +233,42 @@ int copy_strings32(int argc, u32 * argv,
 			}
 			err = copy_from_user(kaddr + offset, (char *)A(str),
 			                     bytes_to_copy);
-			flush_dcache_page(page);
-			kunmap(page);
-
-			if (err)
-				return -EFAULT;
+			if (err) {
+				ret = -EFAULT;
+				goto out;
+			}
 
 			pos += bytes_to_copy;
 			str += bytes_to_copy;
 			len -= bytes_to_copy;
 		}
 	}
-	return 0;
+	ret = 0;
+out:
+	if (kmapped_page)
+		kunmap(kmapped_page);
+	return ret;
+}
+
+#ifdef CONFIG_MMU
+
+#define free_arg_pages(bprm) do { } while (0)
+
+#else
+
+static inline void free_arg_pages(struct linux_binprm *bprm)
+{
+	int i;
+
+	for (i = 0; i < MAX_ARG_PAGES; i++) {
+		if (bprm->page[i])
+			__free_page(bprm->page[i]);
+		bprm->page[i] = NULL;
+	}
 }
 
+#endif /* CONFIG_MMU */
+
 /*
  * sys32_execve() executes a new program.
  */
@@ -243,7 +278,8 @@ do_execve32(char * filename, u32 * argv,
 	struct linux_binprm bprm;
 	struct file * file;
 	int retval;
-	int i;
+
+	sched_balance_exec();
 
 	file = open_exec(filename);
 
@@ -278,7 +314,8 @@ do_execve32(char * filename, u32 * argv,
 	if ((retval = bprm.envc) < 0)
 		goto out_mm;
 
-	if ((retval = security_bprm_alloc(&bprm)))
+	retval = security_bprm_alloc(&bprm);
+	if (retval)
 		goto out;
 
 	retval = prepare_binprm(&bprm);
@@ -300,6 +337,8 @@ do_execve32(char * filename, u32 * argv,
 
 	retval = search_binary_handler(&bprm, regs);
 	if (retval >= 0) {
+		free_arg_pages(&bprm);
+
 		/* execve success */
 		security_bprm_free(&bprm);
 		return retval;
@@ -307,17 +346,14 @@ do_execve32(char * filename, u32 * argv,
 
 out:
 	/* Something went wrong, return the inode and free the argument pages*/
-	for (i = 0 ; i < MAX_ARG_PAGES ; i++) {
-		struct page * page = bprm.page[i];
-		if (page)
-			__free_page(page);
-	}
+	free_arg_pages(&bprm);
 
 	if (bprm.security)
 		security_bprm_free(&bprm);
 
 out_mm:
-	mmdrop(bprm.mm);
+	if (bprm.mm)
+		mmdrop(bprm.mm);
 
 out_file:
 	if (bprm.file) {
@@ -336,7 +372,6 @@ asmlinkage int sys32_execve(nabi_no_rega
 	char * filename;
 
 	filename = getname((char *) (long)regs.regs[4]);
-	printk("Executing: %s\n", filename);
 	error = PTR_ERR(filename);
 	if (IS_ERR(filename))
 		goto out;
@@ -375,8 +410,6 @@ xlate_dirent(void *dirent64, void *diren
 	return;
 }
 
-asmlinkage long sys_getdents(unsigned int fd, void * dirent, unsigned int count);
-
 asmlinkage long
 sys32_getdents(unsigned int fd, void * dirent32, unsigned int count)
 {
@@ -497,8 +530,6 @@ struct sysinfo32 {
 	char _f[8];
 };
 
-extern asmlinkage int sys_sysinfo(struct sysinfo *info);
-
 asmlinkage int sys32_sysinfo(struct sysinfo32 *info)
 {
 	struct sysinfo s;
@@ -633,10 +664,6 @@ sys32_settimeofday(struct compat_timeval
 	return do_sys_settimeofday(tv ? &kts : NULL, tz ? &ktz : NULL);
 }
 
-extern asmlinkage long sys_llseek(unsigned int fd, unsigned long offset_high,
-			          unsigned long offset_low, loff_t * result,
-			          unsigned int origin);
-
 asmlinkage int sys32_llseek(unsigned int fd, unsigned int offset_high,
 			    unsigned int offset_low, loff_t * result,
 			    unsigned int origin)
@@ -704,6 +731,7 @@ do_readv_writev32(int type, struct file 
 	 * specially as they have atomicity guarantees and can handle
 	 * iovec's natively
 	 */
+#ifdef CONFIG_NET
 	if (inode->i_sock) {
 		int err;
 		err = sock_readv_writev(type, inode, file, iov, count, tot_len);
@@ -711,6 +739,7 @@ do_readv_writev32(int type, struct file 
 			kfree(iov);
 		return err;
 	}
+#endif
 
 	if (!file->f_op) {
 		if (iov != iovstack)
@@ -1018,10 +1047,6 @@ out_nofds:
 }
 
 
-
-extern asmlinkage int sys_sched_rr_get_interval(pid_t pid,
-	struct timespec *interval);
-
 asmlinkage int sys32_sched_rr_get_interval(compat_pid_t pid,
 	struct compat_timespec *interval)
 {
@@ -1183,10 +1208,10 @@ do_sys32_semctl(int first, int second, i
 	case IPC_STAT:
 	case SEM_STAT:
 		fourth.__pad = &s;
-		old_fs = get_fs ();
-		set_fs (KERNEL_DS);
-		err = sys_semctl (first, second, third, fourth);
-		set_fs (old_fs);
+		old_fs = get_fs();
+		set_fs(KERNEL_DS);
+		err = sys_semctl(first, second, third | IPC_64, fourth);
+		set_fs(old_fs);
 
 		if (third & IPC_64) {
 			struct semid64_ds32 *usp64 = (struct semid64_ds32 *) A(pad);
@@ -1348,18 +1373,18 @@ do_sys32_msgctl (int first, int second, 
 		}
 		if (err)
 			break;
-		old_fs = get_fs ();
-		set_fs (KERNEL_DS);
-		err = sys_msgctl (first, second, (struct msqid_ds *)&m);
-		set_fs (old_fs);
+		old_fs = get_fs();
+		set_fs(KERNEL_DS);
+		err = sys_msgctl(first, second | IPC_64, (struct msqid_ds *)&m);
+		set_fs(old_fs);
 		break;
 
 	case IPC_STAT:
 	case MSG_STAT:
-		old_fs = get_fs ();
-		set_fs (KERNEL_DS);
-		err = sys_msgctl (first, second, (struct msqid_ds *)&m);
-		set_fs (old_fs);
+		old_fs = get_fs();
+		set_fs(KERNEL_DS);
+		err = sys_msgctl(first, second | IPC_64, (struct msqid_ds *)&m);
+		set_fs(old_fs);
 		if (second & IPC_64) {
 			if (!access_ok(VERIFY_WRITE, up64, sizeof(*up64))) {
 				err = -EFAULT;
@@ -1420,8 +1445,6 @@ do_sys32_shmat (int first, int second, i
 
 	if (version == 1)
 		return err;
-	if (version == 1)
-		return err;
 	err = sys_shmat (first, uptr, second, &raddr);
 	if (err)
 		return err;
@@ -1429,21 +1452,23 @@ do_sys32_shmat (int first, int second, i
 	return err;
 }
 
+struct shm_info32 {
+	int used_ids;
+	u32 shm_tot, shm_rss, shm_swp;
+	u32 swap_attempts, swap_successes;
+};
+
 static int
 do_sys32_shmctl (int first, int second, void *uptr)
 {
+	struct shmid64_ds32 *up64 = (struct shmid64_ds32 *)uptr;
+	struct shmid_ds32 *up32 = (struct shmid_ds32 *)uptr;
+	struct shm_info32 *uip = (struct shm_info32 *)uptr;
 	int err = -EFAULT, err2;
-	struct shmid_ds s;
 	struct shmid64_ds s64;
-	struct shmid_ds32 *up32 = (struct shmid_ds32 *)uptr;
-	struct shmid64_ds32 *up64 = (struct shmid64_ds32 *)uptr;
 	mm_segment_t old_fs;
-	struct shm_info32 {
-		int used_ids;
-		u32 shm_tot, shm_rss, shm_swp;
-		u32 swap_attempts, swap_successes;
-	} *uip = (struct shm_info32 *)uptr;
 	struct shm_info si;
+	struct shmid_ds s;
 
 	switch (second & ~IPC_64) {
 	case IPC_INFO:
@@ -1451,7 +1476,7 @@ do_sys32_shmctl (int first, int second, 
 	case IPC_RMID:
 	case SHM_LOCK:
 	case SHM_UNLOCK:
-		err = sys_shmctl (first, second, (struct shmid_ds *)uptr);
+		err = sys_shmctl(first, second, (struct shmid_ds *)uptr);
 		break;
 	case IPC_SET:
 		if (second & IPC_64) {
@@ -1465,18 +1490,18 @@ do_sys32_shmctl (int first, int second, 
 		}
 		if (err)
 			break;
-		old_fs = get_fs ();
-		set_fs (KERNEL_DS);
-		err = sys_shmctl (first, second, &s);
-		set_fs (old_fs);
+		old_fs = get_fs();
+		set_fs(KERNEL_DS);
+		err = sys_shmctl(first, second & ~IPC_64, &s);
+		set_fs(old_fs);
 		break;
 
 	case IPC_STAT:
 	case SHM_STAT:
-		old_fs = get_fs ();
-		set_fs (KERNEL_DS);
-		err = sys_shmctl (first, second, (void *) &s64);
-		set_fs (old_fs);
+		old_fs = get_fs();
+		set_fs(KERNEL_DS);
+		err = sys_shmctl(first, second | IPC_64, (void *) &s64);
+		set_fs(old_fs);
 		if (err < 0)
 			break;
 		if (second & IPC_64) {
@@ -1523,32 +1548,46 @@ do_sys32_shmctl (int first, int second, 
 		break;
 
 	case SHM_INFO:
-		old_fs = get_fs ();
-		set_fs (KERNEL_DS);
-		err = sys_shmctl (first, second, (void *)&si);
-		set_fs (old_fs);
+		old_fs = get_fs();
+		set_fs(KERNEL_DS);
+		err = sys_shmctl(first, second, (void *)&si);
+		set_fs(old_fs);
 		if (err < 0)
 			break;
-		err2 = put_user (si.used_ids, &uip->used_ids);
-		err2 |= __put_user (si.shm_tot, &uip->shm_tot);
-		err2 |= __put_user (si.shm_rss, &uip->shm_rss);
-		err2 |= __put_user (si.shm_swp, &uip->shm_swp);
-		err2 |= __put_user (si.swap_attempts,
-				    &uip->swap_attempts);
-		err2 |= __put_user (si.swap_successes,
-				    &uip->swap_successes);
+		err2 = put_user(si.used_ids, &uip->used_ids);
+		err2 |= __put_user(si.shm_tot, &uip->shm_tot);
+		err2 |= __put_user(si.shm_rss, &uip->shm_rss);
+		err2 |= __put_user(si.shm_swp, &uip->shm_swp);
+		err2 |= __put_user(si.swap_attempts, &uip->swap_attempts);
+		err2 |= __put_user (si.swap_successes, &uip->swap_successes);
 		if (err2)
 			err = -EFAULT;
 		break;
 
 	default:
-		err = -ENOSYS;
+		err = -EINVAL;
 		break;
 	}
 
 	return err;
 }
 
+static int sys32_semtimedop(int semid, struct sembuf *tsems, int nsems,
+                            const struct compat_timespec *timeout32)
+{
+	struct compat_timespec t32;
+	struct timespec *t64 = compat_alloc_user_space(sizeof(*t64));
+
+	if (copy_from_user(&t32, timeout32, sizeof(t32)))
+		return -EFAULT;
+
+	if (put_user(t32.tv_sec, &t64->tv_sec) ||
+	    put_user(t32.tv_nsec, &t64->tv_nsec))
+		return -EFAULT;
+
+	return sys_semtimedop(semid, tsems, nsems, t64);
+}
+
 asmlinkage long
 sys32_ipc (u32 call, int first, int second, int third, u32 ptr, u32 fifth)
 {
@@ -1558,11 +1597,14 @@ sys32_ipc (u32 call, int first, int seco
 	call &= 0xffff;
 
 	switch (call) {
-
 	case SEMOP:
 		/* struct sembuf is the same on 32 and 64bit :)) */
-		err = sys_semop (first, (struct sembuf *)AA(ptr),
-				 second);
+		err = sys_semtimedop (first, (struct sembuf *)AA(ptr), second,
+		                      NULL);
+		break;
+	case SEMTIMEDOP:
+		err = sys32_semtimedop (first, (struct sembuf *)AA(ptr), second,
+		                      (const struct compat_timespec __user *)AA(fifth));
 		break;
 	case SEMGET:
 		err = sys_semget (first, second, third);
@@ -1668,56 +1710,6 @@ asmlinkage long sys32_sysctl(struct sysc
 
 #endif /* CONFIG_SYSCTL */
 
-extern asmlinkage int sys_sched_setaffinity(pid_t pid, unsigned int len,
-					    unsigned long *user_mask_ptr);
-
-asmlinkage int sys32_sched_setaffinity(compat_pid_t pid, unsigned int len,
-				       u32 *user_mask_ptr)
-{
-	unsigned long kernel_mask;
-	mm_segment_t old_fs;
-	int ret;
-
-	if (get_user(kernel_mask, user_mask_ptr))
-		return -EFAULT;
-
-	old_fs = get_fs();
-	set_fs(KERNEL_DS);
-	ret = sys_sched_setaffinity(pid,
-				    /* XXX Nice api... */
-				    sizeof(kernel_mask),
-				    &kernel_mask);
-	set_fs(old_fs);
-
-	return ret;
-}
-
-extern asmlinkage int sys_sched_getaffinity(pid_t pid, unsigned int len,
-					    unsigned long *user_mask_ptr);
-
-asmlinkage int sys32_sched_getaffinity(compat_pid_t pid, unsigned int len,
-				       u32 *user_mask_ptr)
-{
-	unsigned long kernel_mask;
-	mm_segment_t old_fs;
-	int ret;
-
-	old_fs = get_fs();
-	set_fs(KERNEL_DS);
-	ret = sys_sched_getaffinity(pid,
-				    /* XXX Nice api... */
-				    sizeof(kernel_mask),
-				    &kernel_mask);
-	set_fs(old_fs);
-
-	if (ret == 0) {
-		if (put_user(kernel_mask, user_mask_ptr))
-			ret = -EFAULT;
-	}
-
-	return ret;
-}
-
 asmlinkage long sys32_newuname(struct new_utsname * name)
 {
 	int ret = 0;
@@ -1734,8 +1726,6 @@ asmlinkage long sys32_newuname(struct ne
 	return ret;
 }
 
-extern asmlinkage long sys_personality(unsigned long);
-
 asmlinkage int sys32_personality(unsigned long personality)
 {
 	int ret;
@@ -1747,6 +1737,40 @@ asmlinkage int sys32_personality(unsigne
 	return ret;
 }
 
+/* ustat compatibility */
+struct ustat32 {
+	compat_daddr_t	f_tfree;
+	compat_ino_t	f_tinode;
+	char		f_fname[6];
+	char		f_fpack[6];
+};
+
+extern asmlinkage long sys_ustat(dev_t dev, struct ustat * ubuf);
+
+asmlinkage int sys32_ustat(dev_t dev, struct ustat32 * ubuf32)
+{
+	int err;
+        struct ustat tmp;
+	struct ustat32 tmp32;
+	mm_segment_t old_fs = get_fs();
+
+	set_fs(KERNEL_DS);
+	err = sys_ustat(dev, &tmp);
+	set_fs (old_fs);
+
+	if (err)
+		goto out;
+
+        memset(&tmp32,0,sizeof(struct ustat32));
+        tmp32.f_tfree = tmp.f_tfree;
+        tmp32.f_tinode = tmp.f_tinode;
+
+        err = copy_to_user(ubuf32,&tmp32,sizeof(struct ustat32)) ? -EFAULT : 0;
+
+out:
+	return err;
+}
+
 /* Handle adjtimex compatibility. */
 
 struct timex32 {
@@ -1820,8 +1844,6 @@ asmlinkage int sys32_adjtimex(struct tim
 	return ret;
 }
 
-extern asmlinkage ssize_t sys_sendfile(int out_fd, int in_fd, off_t *offset, size_t count);
-
 asmlinkage int sys32_sendfile(int out_fd, int in_fd, compat_off_t *offset,
 	s32 count)
 {
@@ -1842,29 +1864,122 @@ asmlinkage int sys32_sendfile(int out_fd
 	return ret;
 }
 
-asmlinkage ssize_t sys_readahead(int fd, loff_t offset, size_t count);
-
 asmlinkage ssize_t sys32_readahead(int fd, u32 pad0, u64 a2, u64 a3,
                                    size_t count)
 {
 	return sys_readahead(fd, merge_64(a2, a3), count);
 }
 
-asmlinkage long compat_sys_utimes(char __user * filename,
-	struct compat_timeval __user * utimes)
+/* Argument list sizes for sys_socketcall */
+#define AL(x) ((x) * sizeof(unsigned int))
+static unsigned char socketcall_nargs[18]={AL(0),AL(3),AL(3),AL(3),AL(2),AL(3),
+				AL(3),AL(3),AL(4),AL(4),AL(4),AL(6),
+				AL(6),AL(2),AL(5),AL(5),AL(3),AL(3)};
+#undef AL
+
+/*
+ *	System call vectors. 
+ *
+ *	Argument checking cleaned up. Saved 20% in size.
+ *  This function doesn't need to set the kernel lock because
+ *  it is set by the callees. 
+ */
+
+asmlinkage long sys32_socketcall(int call, unsigned int *args32)
 {
-	struct timeval times[2];
-                                                                                
-	if (utimes) {
-		if (verify_area(VERIFY_READ, utimes, 2 * sizeof(*utimes)))
-			return -EFAULT;
+	unsigned int a[6];
+	unsigned int a0,a1;
+	int err;
 
-		if (__get_user(times[0].tv_sec, &utimes[0].tv_sec) | 
-		    __get_user(times[0].tv_usec, &utimes[0].tv_usec) | 
-		    __get_user(times[1].tv_sec, &utimes[1].tv_sec) | 
-		    __get_user(times[1].tv_usec, &utimes[1].tv_usec))
-			return -EFAULT;
-	}
+	extern asmlinkage long sys_socket(int family, int type, int protocol);
+	extern asmlinkage long sys_bind(int fd, struct sockaddr __user *umyaddr, int addrlen);
+	extern asmlinkage long sys_connect(int fd, struct sockaddr __user *uservaddr, int addrlen);
+	extern asmlinkage long sys_listen(int fd, int backlog);
+	extern asmlinkage long sys_accept(int fd, struct sockaddr __user *upeer_sockaddr, int __user *upeer_addrlen);
+	extern asmlinkage long sys_getsockname(int fd, struct sockaddr __user *usockaddr, int __user *usockaddr_len);
+	extern asmlinkage long sys_getpeername(int fd, struct sockaddr __user *usockaddr, int __user *usockaddr_len);
+	extern asmlinkage long sys_socketpair(int family, int type, int protocol, int __user *usockvec);
+	extern asmlinkage long sys_send(int fd, void __user * buff, size_t len, unsigned flags);
+	extern asmlinkage long sys_sendto(int fd, void __user * buff, size_t len, unsigned flags,
+					  struct sockaddr __user *addr, int addr_len);
+	extern asmlinkage long sys_recv(int fd, void __user * ubuf, size_t size, unsigned flags);
+	extern asmlinkage long sys_recvfrom(int fd, void __user * ubuf, size_t size, unsigned flags,
+					    struct sockaddr __user *addr, int __user *addr_len);
+	extern asmlinkage long sys_shutdown(int fd, int how);
+	extern asmlinkage long sys_setsockopt(int fd, int level, int optname, char __user *optval, int optlen);
+	extern asmlinkage long sys_getsockopt(int fd, int level, int optname, char __user *optval, int *optlen);
+	extern asmlinkage long sys_sendmsg(int fd, struct msghdr __user *msg, unsigned flags);
+	extern asmlinkage long sys_recvmsg(int fd, struct msghdr __user *msg, unsigned int flags);
+
+
+	if(call<1||call>SYS_RECVMSG)
+		return -EINVAL;
 
-	return do_utimes(filename, utimes ? times : NULL);
+	/* copy_from_user should be SMP safe. */
+	if (copy_from_user(a, args32, socketcall_nargs[call]))
+		return -EFAULT;
+		
+	a0=a[0];
+	a1=a[1];
+	
+	switch(call) 
+	{
+		case SYS_SOCKET:
+			err = sys_socket(a0,a1,a[2]);
+			break;
+		case SYS_BIND:
+			err = sys_bind(a0,(struct sockaddr __user *)A(a1), a[2]);
+			break;
+		case SYS_CONNECT:
+			err = sys_connect(a0, (struct sockaddr __user *)A(a1), a[2]);
+			break;
+		case SYS_LISTEN:
+			err = sys_listen(a0,a1);
+			break;
+		case SYS_ACCEPT:
+			err = sys_accept(a0,(struct sockaddr __user *)A(a1), (int __user *)A(a[2]));
+			break;
+		case SYS_GETSOCKNAME:
+			err = sys_getsockname(a0,(struct sockaddr __user *)A(a1), (int __user *)A(a[2]));
+			break;
+		case SYS_GETPEERNAME:
+			err = sys_getpeername(a0, (struct sockaddr __user *)A(a1), (int __user *)A(a[2]));
+			break;
+		case SYS_SOCKETPAIR:
+			err = sys_socketpair(a0,a1, a[2], (int __user *)A(a[3]));
+			break;
+		case SYS_SEND:
+			err = sys_send(a0, (void __user *)A(a1), a[2], a[3]);
+			break;
+		case SYS_SENDTO:
+			err = sys_sendto(a0,(void __user *)A(a1), a[2], a[3],
+					 (struct sockaddr __user *)A(a[4]), a[5]);
+			break;
+		case SYS_RECV:
+			err = sys_recv(a0, (void __user *)A(a1), a[2], a[3]);
+			break;
+		case SYS_RECVFROM:
+			err = sys_recvfrom(a0, (void __user *)A(a1), a[2], a[3],
+					   (struct sockaddr __user *)A(a[4]), (int __user *)A(a[5]));
+			break;
+		case SYS_SHUTDOWN:
+			err = sys_shutdown(a0,a1);
+			break;
+		case SYS_SETSOCKOPT:
+			err = sys_setsockopt(a0, a1, a[2], (char __user *)A(a[3]), a[4]);
+			break;
+		case SYS_GETSOCKOPT:
+			err = sys_getsockopt(a0, a1, a[2], (char __user *)A(a[3]), (int __user *)A(a[4]));
+			break;
+		case SYS_SENDMSG:
+			err = sys_sendmsg(a0, (struct msghdr __user *) A(a1), a[2]);
+			break;
+		case SYS_RECVMSG:
+			err = sys_recvmsg(a0, (struct msghdr __user *) A(a1), a[2]);
+			break;
+		default:
+			err = -EINVAL;
+			break;
+	}
+	return err;
 }
--- diff/arch/mips/kernel/mips_ksyms.c	2003-09-30 15:46:11.000000000 +0100
+++ source/arch/mips/kernel/mips_ksyms.c	2004-02-23 13:56:38.000000000 +0000
@@ -8,27 +8,10 @@
  * Copyright (C) 1996, 97, 98, 99, 2000, 01, 03 by Ralf Baechle
  * Copyright (C) 1999, 2000, 01 Silicon Graphics, Inc.
  */
-#include <linux/config.h>
 #include <linux/module.h>
-#include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/interrupt.h>
-#include <linux/in6.h>
-#include <linux/pci.h>
-#include <linux/tty.h>
-#include <linux/ide.h>
-
-#include <asm/bootinfo.h>
 #include <asm/checksum.h>
-#include <asm/dma.h>
-#include <asm/io.h>
-#include <asm/page.h>
-#include <asm/pgalloc.h>
-#include <asm/semaphore.h>
+#include <asm/pgtable.h>
 #include <asm/uaccess.h>
-#ifdef CONFIG_BLK_DEV_FD
-#include <asm/floppy.h>
-#endif
 
 extern void *__bzero(void *__s, size_t __count);
 extern long __strncpy_from_user_nocheck_asm(char *__to,
@@ -40,11 +23,10 @@ extern long __strlen_user_asm(const char
 extern long __strnlen_user_nocheck_asm(const char *s);
 extern long __strnlen_user_asm(const char *s);
 
-EXPORT_SYMBOL(mips_machtype);
-
 /*
  * String functions
  */
+EXPORT_SYMBOL_NOVERS(memchr);
 EXPORT_SYMBOL_NOVERS(memcmp);
 EXPORT_SYMBOL_NOVERS(memset);
 EXPORT_SYMBOL_NOVERS(memcpy);
@@ -58,7 +40,6 @@ EXPORT_SYMBOL_NOVERS(strnlen);
 EXPORT_SYMBOL_NOVERS(strrchr);
 EXPORT_SYMBOL_NOVERS(strstr);
 
-EXPORT_SYMBOL(_clear_page);
 EXPORT_SYMBOL(kernel_thread);
 
 /*
@@ -73,24 +54,6 @@ EXPORT_SYMBOL_NOVERS(__strlen_user_asm);
 EXPORT_SYMBOL_NOVERS(__strnlen_user_nocheck_asm);
 EXPORT_SYMBOL_NOVERS(__strnlen_user_asm);
 
-EXPORT_SYMBOL(invalid_pte_table);
-
-/*
- * Semaphore stuff
- */
-EXPORT_SYMBOL(__down);
-EXPORT_SYMBOL(__down_interruptible);
-EXPORT_SYMBOL(__down_trylock);
-EXPORT_SYMBOL(__up);
+EXPORT_SYMBOL(csum_partial);
 
-/*
- * Kernel hacking ...
- */
-#include <asm/branch.h>
-#include <linux/sched.h>
-
-#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)
-EXPORT_SYMBOL(ide_ops);
-#endif
-
-EXPORT_SYMBOL(get_wchan);
+EXPORT_SYMBOL(invalid_pte_table);
--- diff/arch/mips/kernel/module-elf32.c	2003-08-20 14:16:36.000000000 +0100
+++ source/arch/mips/kernel/module-elf32.c	2004-02-23 13:56:38.000000000 +0000
@@ -1,20 +1,24 @@
-/*  Kernel module help for MIPS.
-    Copyright (C) 2001 Rusty Russell.
+/*
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ *  Copyright (C) 2001 Rusty Russell.
+ *  Copyright (C) 2003, 2004 Ralf Baechle (ralf@linux-mips.org)
+ */
+
+#undef DEBUG
 
-    This program is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 2 of the License, or
-    (at your option) any later version.
-
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with this program; if not, write to the Free Software
-    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-*/
 #include <linux/moduleloader.h>
 #include <linux/elf.h>
 #include <linux/vmalloc.h>
@@ -31,12 +35,6 @@ struct mips_hi16 {
 
 static struct mips_hi16 *mips_hi16_list;
 
-#if 0
-#define DEBUGP printk
-#else
-#define DEBUGP(fmt , ...)
-#endif
-
 void *module_alloc(unsigned long size)
 {
 	if (size == 0)
@@ -53,52 +51,170 @@ void module_free(struct module *mod, voi
            table entries. */
 }
 
-/* We don't need anything special. */
-long module_core_size(const Elf32_Ehdr *hdr,
-		      const Elf32_Shdr *sechdrs,
-		      const char *secstrings,
-		      struct module *module)
+int module_frob_arch_sections(Elf_Ehdr *hdr,
+			      Elf_Shdr *sechdrs,
+			      char *secstrings,
+			      struct module *mod)
 {
-	return module->core_size;
+	return 0;
 }
 
-long module_init_size(const Elf32_Ehdr *hdr,
-		      const Elf32_Shdr *sechdrs,
-		      const char *secstrings,
-		      struct module *module)
+static int apply_r_mips_none(struct module *me, uint32_t *location,
+	Elf32_Addr v)
 {
-	return module->init_size;
+	return 0;
 }
 
-int module_frob_arch_sections(Elf_Ehdr *hdr,
-			      Elf_Shdr *sechdrs,
-			      char *secstrings,
-			      struct module *mod)
+static int apply_r_mips_32(struct module *me, uint32_t *location,
+	Elf32_Addr v)
+{
+	*location += v;
+
+	return 0;
+}
+
+static int apply_r_mips_26(struct module *me, uint32_t *location,
+	Elf32_Addr v)
+{
+	if (v % 4) {
+		printk(KERN_ERR "module %s: dangerous relocation\n", me->name);
+		return -ENOEXEC;
+	}
+
+	if ((v & 0xf0000000) != (((unsigned long)location + 4) & 0xf0000000)) {
+		printk(KERN_ERR
+		       "module %s: relocation overflow\n",
+		       me->name);
+		return -ENOEXEC;
+	}
+
+	*location = (*location & ~0x03ffffff) |
+	            ((*location + (v >> 2)) & 0x03ffffff);
+
+	return 0;
+}
+
+static int apply_r_mips_hi16(struct module *me, uint32_t *location,
+	Elf32_Addr v)
 {
+	struct mips_hi16 *n;
+
+	/*
+	 * We cannot relocate this one now because we don't know the value of
+	 * the carry we need to add.  Save the information, and let LO16 do the
+	 * actual relocation.
+	 */
+	n = kmalloc(sizeof *n, GFP_KERNEL);
+	if (!n)
+		return -ENOMEM;
+
+	n->addr = location;
+	n->value = v;
+	n->next = mips_hi16_list;
+	mips_hi16_list = n;
+
 	return 0;
 }
 
+static int apply_r_mips_lo16(struct module *me, uint32_t *location,
+	Elf32_Addr v)
+{
+	unsigned long insnlo = *location;
+	Elf32_Addr val, vallo;
+
+	/* Sign extend the addend we extract from the lo insn.  */
+	vallo = ((insnlo & 0xffff) ^ 0x8000) - 0x8000;
+
+	if (mips_hi16_list != NULL) {
+		struct mips_hi16 *l;
+
+		l = mips_hi16_list;
+		while (l != NULL) {
+			struct mips_hi16 *next;
+			unsigned long insn;
+
+			/*
+			 * The value for the HI16 had best be the same.
+			 */
+			if (v != l->value)
+				goto out_danger;
+
+			/*
+			 * Do the HI16 relocation.  Note that we actually don't
+			 * need to know anything about the LO16 itself, except
+			 * where to find the low 16 bits of the addend needed
+			 * by the LO16.
+			 */
+			insn = *l->addr;
+			val = ((insn & 0xffff) << 16) + vallo;
+			val += v;
+
+			/*
+			 * Account for the sign extension that will happen in
+			 * the low bits.
+			 */
+			val = ((val >> 16) + ((val & 0x8000) != 0)) & 0xffff;
+
+			insn = (insn & ~0xffff) | val;
+			*l->addr = insn;
+
+			next = l->next;
+			kfree(l);
+			l = next;
+		}
+
+		mips_hi16_list = NULL;
+	}
+
+	/*
+	 * Ok, we're done with the HI16 relocs.  Now deal with the LO16.
+	 */
+	val = v + vallo;
+	insnlo = (insnlo & ~0xffff) | (val & 0xffff);
+	*location = insnlo;
+
+	return 0;
+
+out_danger:
+	printk(KERN_ERR "module %s: dangerous " "relocation\n", me->name);
+
+	return -ENOEXEC;
+}
+
+static int (*reloc_handlers[]) (struct module *me, uint32_t *location,
+	Elf32_Addr v) = {
+	[R_MIPS_NONE]	= apply_r_mips_none,
+	[R_MIPS_32]	= apply_r_mips_32,
+	[R_MIPS_26]	= apply_r_mips_26,
+	[R_MIPS_HI16]	= apply_r_mips_hi16,
+	[R_MIPS_LO16]	= apply_r_mips_lo16
+};
+
 int apply_relocate(Elf32_Shdr *sechdrs,
 		   const char *strtab,
 		   unsigned int symindex,
 		   unsigned int relsec,
 		   struct module *me)
 {
-	unsigned int i;
-	Elf32_Rel *rel = (void *)sechdrs[relsec].sh_offset;
+	Elf32_Rel *rel = (void *) sechdrs[relsec].sh_addr;
 	Elf32_Sym *sym;
 	uint32_t *location;
+	unsigned int i;
 	Elf32_Addr v;
+	int res;
 
-	DEBUGP("Applying relocate section %u to %u\n", relsec,
+	pr_debug("Applying relocate section %u to %u\n", relsec,
 	       sechdrs[relsec].sh_info);
+
 	for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) {
+		Elf32_Word r_info = rel[i].r_info;
+
 		/* This is where to make the change */
-		location = (void *)sechdrs[sechdrs[relsec].sh_info].sh_offset
+		location = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr
 			+ rel[i].r_offset;
 		/* This is the symbol it is referring to */
-		sym = (Elf32_Sym *)sechdrs[symindex].sh_offset
-			+ ELF32_R_SYM(rel[i].r_info);
+		sym = (Elf32_Sym *)sechdrs[symindex].sh_addr
+			+ ELF32_R_SYM(r_info);
 		if (!sym->st_value) {
 			printk(KERN_WARNING "%s: Unknown symbol %s\n",
 			       me->name, strtab + sym->st_name);
@@ -107,115 +223,11 @@ int apply_relocate(Elf32_Shdr *sechdrs,
 
 		v = sym->st_value;
 
-		switch (ELF32_R_TYPE(rel[i].r_info)) {
-		case R_MIPS_NONE:
-			break;
-
-		case R_MIPS_32:
-			*location += v;
-			break;
-
-		case R_MIPS_26:
-			if (v % 4)
-				printk(KERN_ERR
-				       "module %s: dangerous relocation\n",
-				       me->name);
-				return -ENOEXEC;
-			if ((v & 0xf0000000) !=
-			    (((unsigned long)location + 4) & 0xf0000000))
-				printk(KERN_ERR
-				       "module %s: relocation overflow\n",
-				       me->name);
-				return -ENOEXEC;
-			*location = (*location & ~0x03ffffff) |
-			            ((*location + (v >> 2)) & 0x03ffffff);
-			break;
-
-		case R_MIPS_HI16: {
-			struct mips_hi16 *n;
-
-			/*
-			 * We cannot relocate this one now because we don't
-			 * know the value of the carry we need to add.  Save
-			 * the information, and let LO16 do the actual
-			 * relocation.
-			 */
-			n = (struct mips_hi16 *) kmalloc(sizeof *n, GFP_KERNEL);
-			n->addr = location;
-			n->value = v;
-			n->next = mips_hi16_list;
-			mips_hi16_list = n;
-			break;
-		}
-
-		case R_MIPS_LO16: {
-			unsigned long insnlo = *location;
-			Elf32_Addr val, vallo;
-
-			/* Sign extend the addend we extract from the lo insn.  */
-			vallo = ((insnlo & 0xffff) ^ 0x8000) - 0x8000;
-
-			if (mips_hi16_list != NULL) {
-				struct mips_hi16 *l;
-
-				l = mips_hi16_list;
-				while (l != NULL) {
-					struct mips_hi16 *next;
-					unsigned long insn;
-
-					/*
-					 * The value for the HI16 had best be
-					 * the same.
-					 */
-					printk(KERN_ERR "module %s: dangerous "
-					       "relocation\n", me->name);
-					return -ENOEXEC;
-
-					/*
-					 * Do the HI16 relocation.  Note that
-					 * we actually don't need to know
-					 * anything about the LO16 itself,
-					 * except where to find the low 16 bits
-					 * of the addend needed by the LO16.
-					 */
-					insn = *l->addr;
-					val = ((insn & 0xffff) << 16) + vallo;
-					val += v;
-
-					/*
-					 * Account for the sign extension that
-					 * will happen in the low bits.
-					 */
-					val = ((val >> 16) + ((val & 0x8000) !=
-					      0)) & 0xffff;
-
-					insn = (insn & ~0xffff) | val;
-					*l->addr = insn;
-
-					next = l->next;
-					kfree(l);
-					l = next;
-				}
-
-				mips_hi16_list = NULL;
-			}
-
-			/*
-			 * Ok, we're done with the HI16 relocs.  Now deal with
-			 * the LO16.
-			 */
-			val = v + vallo;
-			insnlo = (insnlo & ~0xffff) | (val & 0xffff);
-			*location = insnlo;
-			break;
-		}
-
-		default:
-			printk(KERN_ERR "module %s: Unknown relocation: %u\n",
-			       me->name, ELF32_R_TYPE(rel[i].r_info));
-			return -ENOEXEC;
-		}
+		res = reloc_handlers[ELF32_R_TYPE(r_info)](me, location, v);
+		if (res)
+			return res;
 	}
+
 	return 0;
 }
 
@@ -225,6 +237,13 @@ int apply_relocate_add(Elf32_Shdr *sechd
 		       unsigned int relsec,
 		       struct module *me)
 {
+	/*
+	 * Current binutils always generate .rela relocations.  Keep smiling
+	 * if it's empty, abort otherwise.
+	 */
+	if (!sechdrs[relsec].sh_size)
+		return 0;
+
 	printk(KERN_ERR "module %s: ADD RELOCATION unsupported\n",
 	       me->name);
 	return -ENOEXEC;
--- diff/arch/mips/kernel/module-elf64.c	2003-08-20 14:16:36.000000000 +0100
+++ source/arch/mips/kernel/module-elf64.c	2004-02-23 13:56:38.000000000 +0000
@@ -160,23 +160,6 @@ void module_free(struct module *mod, voi
            table entries. */
 }
 
-/* We don't need anything special. */
-long module_core_size(const Elf32_Ehdr *hdr,
-		      const Elf32_Shdr *sechdrs,
-		      const char *secstrings,
-		      struct module *module)
-{
-	return module->core_size;
-}
-
-long module_init_size(const Elf32_Ehdr *hdr,
-		      const Elf32_Shdr *sechdrs,
-		      const char *secstrings,
-		      struct module *module)
-{
-	return module->init_size;
-}
-
 int module_frob_arch_sections(Elf_Ehdr *hdr,
 			      Elf_Shdr *sechdrs,
 			      char *secstrings,
--- diff/arch/mips/kernel/offset.c	2003-08-20 14:16:25.000000000 +0100
+++ source/arch/mips/kernel/offset.c	2004-02-23 13:56:38.000000000 +0000
@@ -8,6 +8,7 @@
  * Kevin Kissell, kevink@mips.com and Carsten Langgaard, carstenl@mips.com
  * Copyright (C) 2000 MIPS Technologies, Inc.
  */
+#include <linux/config.h>
 #include <linux/compat.h>
 #include <linux/types.h>
 #include <linux/sched.h>
@@ -22,7 +23,7 @@
 #define offset(string, ptr, member) \
 	__asm__("\n@@@" string "%0" : : "i" (_offset(ptr, member)))
 #define constant(string, member) \
-	__asm__("\n@@@" string "%x0" : : "i" (member))
+	__asm__("\n@@@" string "%x0" : : "ri" (member))
 #define size(string, size) \
 	__asm__("\n@@@" string "%0" : : "i" (sizeof(size)))
 #define linefeed text("")
@@ -202,10 +203,14 @@ void output_thread_fpu_defines(void)
 
 	offset("#define THREAD_FCR31   ",
 	       struct task_struct, thread.fpu.hard.fcr31);
+	linefeed;
 }
 
 void output_mm_defines(void)
 {
+	text("/* Size of struct page  */");
+	size("#define STRUCT_PAGE_SIZE   ", struct page);
+	linefeed;
 	text("/* Linux mm_struct offsets. */");
 	offset("#define MM_USERS      ", struct mm_struct, mm_users);
 	offset("#define MM_PGD        ", struct mm_struct, pgd);
@@ -214,8 +219,16 @@ void output_mm_defines(void)
 	constant("#define _PAGE_SIZE     ", PAGE_SIZE);
 	constant("#define _PAGE_SHIFT    ", PAGE_SHIFT);
 	linefeed;
-	constant("#define _PGDIR_SHIFT   ", PGDIR_SHIFT);
+	constant("#define _PGD_T_SIZE    ", sizeof(pgd_t));
+	constant("#define _PMD_T_SIZE    ", sizeof(pmd_t));
+	constant("#define _PTE_T_SIZE    ", sizeof(pte_t));
+	linefeed;
+	constant("#define _PGD_T_LOG2    ", PGD_T_LOG2);
+	constant("#define _PMD_T_LOG2    ", PMD_T_LOG2);
+	constant("#define _PTE_T_LOG2    ", PTE_T_LOG2);
+	linefeed;
 	constant("#define _PMD_SHIFT     ", PMD_SHIFT);
+	constant("#define _PGDIR_SHIFT   ", PGDIR_SHIFT);
 	linefeed;
 	constant("#define _PGD_ORDER     ", PGD_ORDER);
 	constant("#define _PMD_ORDER     ", PMD_ORDER);
@@ -223,6 +236,7 @@ void output_mm_defines(void)
 	linefeed;
 	constant("#define _PTRS_PER_PGD  ", PTRS_PER_PGD);
 	constant("#define _PTRS_PER_PMD  ", PTRS_PER_PMD);
+	constant("#define _PTRS_PER_PTE  ", PTRS_PER_PTE);
 	linefeed;
 }
 
--- diff/arch/mips/kernel/proc.c	2003-08-26 10:00:52.000000000 +0100
+++ source/arch/mips/kernel/proc.c	2004-02-23 13:56:38.000000000 +0000
@@ -11,6 +11,7 @@
 #include <linux/seq_file.h>
 #include <asm/bootinfo.h>
 #include <asm/cpu.h>
+#include <asm/cpu-features.h>
 #include <asm/mipsregs.h>
 #include <asm/processor.h>
 #include <asm/watch.h>
@@ -39,6 +40,7 @@ static const char *cpu_name[] = {
         [CPU_R6000A]	"R6000A",
 	[CPU_R8000]	"R8000",
 	[CPU_R10000]	"R10000",
+	[CPU_R12000]	"R12000",
 	[CPU_R4300]	"R4300",
 	[CPU_R4650]	"R4650",
 	[CPU_R4700]	"R4700",
@@ -47,6 +49,7 @@ static const char *cpu_name[] = {
 	[CPU_R4640]	"R4640",
 	[CPU_NEVADA]	"Nevada",
 	[CPU_RM7000]	"RM7000",
+	[CPU_RM9000]	"RM9000",
 	[CPU_R5432]	"R5432",
 	[CPU_4KC]	"MIPS 4Kc",
         [CPU_5KC]	"MIPS 5Kc",
@@ -63,10 +66,13 @@ static const char *cpu_name[] = {
 	[CPU_R5500]	"R5500",
 	[CPU_TX49XX]	"TX49xx",
 	[CPU_20KC]	"MIPS 20Kc",
+	[CPU_24K]	"MIPS 24K",
+	[CPU_25KF]	"MIPS 25Kf",
 	[CPU_VR4111]	"NEC VR4111",
 	[CPU_VR4121]	"NEC VR4121",
 	[CPU_VR4122]	"NEC VR4122",
 	[CPU_VR4131]	"NEC VR4131",
+	[CPU_VR4133]	"NEC VR4133",
 	[CPU_VR4181]	"NEC VR4181",
 	[CPU_VR4181A]	"NEC VR4181A",
 	[CPU_SR71000]	"Sandcraft SR71000"
--- diff/arch/mips/kernel/process.c	2003-08-20 14:16:25.000000000 +0100
+++ source/arch/mips/kernel/process.c	2004-02-23 13:56:38.000000000 +0000
@@ -6,7 +6,9 @@
  * Copyright (C) 1994 - 1999, 2000 by Ralf Baechle and others.
  * Copyright (C) 1999, 2000 Silicon Graphics, Inc.
  */
+#include <linux/config.h>
 #include <linux/errno.h>
+#include <linux/module.h>
 #include <linux/sched.h>
 #include <linux/kernel.h>
 #include <linux/mm.h>
@@ -246,7 +248,8 @@ static int __init get_frame_info(struct 
 
 	return 0;
 }
-void __init frame_info_init(void)
+
+static int __init frame_info_init(void)
 {
 	mips_frame_info_initialized =
 		!get_frame_info(&schedule_frame, schedule) &&
@@ -254,8 +257,12 @@ void __init frame_info_init(void)
 		!get_frame_info(&sleep_on_frame, sleep_on) &&
 		!get_frame_info(&sleep_on_timeout_frame, sleep_on_timeout) &&
 		!get_frame_info(&wait_for_completion_frame, wait_for_completion);
+
+	return 0;
 }
 
+arch_initcall(frame_info_init);
+
 /*
  * Return saved PC of a blocked thread.
  */
@@ -341,3 +348,5 @@ out:
 
 	return pc;
 }
+
+EXPORT_SYMBOL(get_wchan);
--- diff/arch/mips/kernel/ptrace.c	2003-08-20 14:16:25.000000000 +0100
+++ source/arch/mips/kernel/ptrace.c	2004-02-23 13:56:38.000000000 +0000
@@ -108,7 +108,7 @@ asmlinkage int sys_ptrace(long request, 
 	/* Read the word at location addr in the USER area. */
 	case PTRACE_PEEKUSR: {
 		struct pt_regs *regs;
-		unsigned long tmp;
+		unsigned long tmp = 0;
 
 		regs = (struct pt_regs *) ((unsigned long) child->thread_info +
 		       THREAD_SIZE - 32 - sizeof(struct pt_regs));
@@ -312,13 +312,9 @@ asmlinkage void do_syscall_trace(void)
 
 	/* The 0x80 provides a way for the tracing parent to distinguish
 	   between a syscall stop and SIGTRAP delivery */
-	current->exit_code = SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD)
-	                                ? 0x80 : 0);
-	preempt_disable();
-	current->state = TASK_STOPPED;
-	notify_parent(current, SIGCHLD);
-	schedule();
-	preempt_enable();
+	ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD) ?
+	                         0x80 : 0));
+
 	/*
 	 * this isn't the same as continuing with a signal, but it will do
 	 * for normal use.  strace only continues with a signal if the
--- diff/arch/mips/kernel/ptrace32.c	2003-08-20 14:16:36.000000000 +0100
+++ source/arch/mips/kernel/ptrace32.c	2004-02-23 13:56:38.000000000 +0000
@@ -14,7 +14,6 @@
  * At this time Linux/MIPS64 only supports syscall tracing, even for 32-bit
  * binaries.
  */
-#include <linux/config.h>
 #include <linux/compiler.h>
 #include <linux/kernel.h>
 #include <linux/sched.h>
--- diff/arch/mips/kernel/r2300_switch.S	2003-08-20 14:16:25.000000000 +0100
+++ source/arch/mips/kernel/r2300_switch.S	2004-02-23 13:56:38.000000000 +0000
@@ -17,7 +17,6 @@
 #include <asm/mipsregs.h>
 #include <asm/offset.h>
 #include <asm/page.h>
-#include <asm/processor.h>
 #include <asm/regdef.h>
 #include <asm/stackframe.h>
 #include <asm/thread_info.h>
@@ -31,7 +30,7 @@
  * Offset to the current process status flags, the first 32 bytes of the
  * stack are not used.
  */
-#define ST_OFF (THREAD_SIZE - 32 - PT_SIZE + PT_STATUS)
+#define ST_OFF (_THREAD_SIZE - 32 - PT_SIZE + PT_STATUS)
 
 /*
  * FPU context is saved iff the process has used it's FPU in the current
@@ -87,7 +86,7 @@ LEAF(resume)
 	move	$28, a2
 	cpu_restore_nonscratch a1
 
-	addiu	t1, $28, THREAD_SIZE-32
+	addiu	t1, $28, _THREAD_SIZE - 32
 	sw	t1, kernelsp
 
 	mfc0	t1, CP0_STATUS		/* Do we really need this? */
--- diff/arch/mips/kernel/r4k_fpu.S	2003-08-20 14:16:25.000000000 +0100
+++ source/arch/mips/kernel/r4k_fpu.S	2004-02-23 13:56:38.000000000 +0000
@@ -12,6 +12,7 @@
  * Copyright (C) 2000 MIPS Technologies, Inc.
  * Copyright (C) 1999, 2001 Silicon Graphics, Inc.
  */
+#include <linux/config.h>
 #include <asm/asm.h>
 #include <asm/errno.h>
 #include <asm/fpregdef.h>
--- diff/arch/mips/kernel/r4k_switch.S	2003-08-20 14:16:25.000000000 +0100
+++ source/arch/mips/kernel/r4k_switch.S	2004-02-23 13:56:38.000000000 +0000
@@ -18,15 +18,12 @@
 #include <asm/offset.h>
 #include <asm/page.h>
 #include <asm/pgtable-bits.h>
-#include <asm/processor.h>
 #include <asm/regdef.h>
 #include <asm/stackframe.h>
 #include <asm/thread_info.h>
 
 #include <asm/asmmacro.h>
 
-	.set	mips3
-
 /*
  * Offset to the current process status flags, the first 32 bytes of the
  * stack are not used.
@@ -196,7 +193,42 @@ LEAF(_init_fpu)
 	dmtc1	t1, $f31
 1:
 #endif
-
+	
+#ifdef CONFIG_CPU_MIPS32
+	mtc1	t1, $f0
+	mtc1	t1, $f1
+	mtc1	t1, $f2
+	mtc1	t1, $f3
+	mtc1	t1, $f4
+	mtc1	t1, $f5
+	mtc1	t1, $f6
+	mtc1	t1, $f7
+	mtc1	t1, $f8
+	mtc1	t1, $f9
+	mtc1	t1, $f10
+	mtc1	t1, $f11
+	mtc1	t1, $f12
+	mtc1	t1, $f13
+	mtc1	t1, $f14
+	mtc1	t1, $f15
+	mtc1	t1, $f16
+	mtc1	t1, $f17
+	mtc1	t1, $f18
+	mtc1	t1, $f19
+	mtc1	t1, $f20
+	mtc1	t1, $f21
+	mtc1	t1, $f22
+	mtc1	t1, $f23
+	mtc1	t1, $f24
+	mtc1	t1, $f25
+	mtc1	t1, $f26
+	mtc1	t1, $f27
+	mtc1	t1, $f28
+	mtc1	t1, $f29
+	mtc1	t1, $f30
+	mtc1	t1, $f31
+#else
+	.set	mips3
 	dmtc1	t1, $f0
 	dmtc1	t1, $f2
 	dmtc1	t1, $f4
@@ -213,5 +245,6 @@ LEAF(_init_fpu)
 	dmtc1	t1, $f26
 	dmtc1	t1, $f28
 	dmtc1	t1, $f30
+#endif
 	jr	ra
 	END(_init_fpu)
--- diff/arch/mips/kernel/scall32-o32.S	2003-08-20 14:16:36.000000000 +0100
+++ source/arch/mips/kernel/scall32-o32.S	2004-02-23 13:56:38.000000000 +0000
@@ -72,14 +72,12 @@ EXPORT(o32_syscall_exit)
 	LONG_L	a2, TI_FLAGS($28)	# current->work
 	li	t0, _TIF_ALLWORK_MASK
 	and	t0, a2, t0
-	bnez	a2, o32_syscall_exit_work
+	bnez	t0, o32_syscall_exit_work
 
-	RESTORE_SOME
-	RESTORE_SP_AND_RET
+	j	restore_partial
 
 o32_syscall_exit_work:
-	SAVE_STATIC
-	j	syscall_exit_work
+	j	syscall_exit_work_partial
 
 /* ------------------------------------------------------------------------ */
 
@@ -124,7 +122,7 @@ stackargs:
 	bltz	t0, bad_stack		# -> sp is bad
 
 	lw	t0, PT_R29(sp)		# get old user stack pointer
-	PTR_LA	t1, 3f			# copy 1 to 2 arguments
+	PTR_LA	t1, 4f			# copy 1 to 3 arguments
 	sll	t3, t3, 4
 	subu	t1, t3
 	jr	t1
@@ -139,21 +137,26 @@ stackargs:
 	.set    push
 	.set    noreorder
 	.set	nomacro
-1:	lw	t1, 20(t0)		# argument #6 from usp
+1:	lw	t1, 24(t0)		# argument #7 from usp
+	nop
+	sw	t1, 24(sp)
+	nop
+2:	lw	t1, 20(t0)		# argument #5 from usp
 	nop
 	sw	t1, 20(sp)
 	nop
-2:	lw	t1, 16(t0)		# argument #5 from usp
+3:	lw	t1, 16(t0)		# argument #5 from usp
 	nop
 	sw	t1, 16(sp)
 	nop
-3:	.set	pop
+4:	.set	pop
 
 	j	stack_done		# go back
 
 	.section __ex_table,"a"
 	PTR	1b,bad_stack
 	PTR	2b,bad_stack
+	PTR	3b,bad_stack
 	.previous
 
 	/*
@@ -225,8 +228,8 @@ illegal_syscall:
 	.previous
 #endif
 
+	sw	zero, PT_R7(sp)		# success
 	sw	v0, PT_R2(sp)		# result
-1:
 
 	/* Success, so skip usual error handling garbage.  */
 	LONG_L	a2, TI_FLAGS($28)	# syscall tracing enabled?
@@ -597,7 +600,7 @@ out:	jr	ra
 	sys	sys_remap_file_pages	5
 	sys	sys_set_tid_address	1
 	sys	sys_restart_syscall	0
-	sys	sys_fadvise64		6
+	sys	sys_fadvise64_64	7
 	sys	sys_statfs64		3	/* 4255 */
 	sys	sys_fstatfs64		2
 	sys	sys_timer_create	3
--- diff/arch/mips/kernel/scall64-64.S	2003-08-20 14:16:36.000000000 +0100
+++ source/arch/mips/kernel/scall64-64.S	2004-02-23 13:56:38.000000000 +0000
@@ -71,21 +71,14 @@ syscall_exit:
 					# signals dont change between
 					# sampling and return
 	LONG_L	a2, TI_FLAGS($28)	# current->work
-	bnez	a2, n64_syscall_exit_work
-
-	j	restore_all
+	li	t0, _TIF_ALLWORK_MASK
+	and	t0, a2, t0
+	bnez	t0, n64_syscall_exit_work
 
-work_notifysig:				# deal with pending signals and
-					# notify-resume requests
-	SAVE_STATIC
-	move	a0, sp
-	li	a1, 0
-	jal	do_notify_resume	# a2 already loaded
-	RESTORE_STATIC
-	j	restore_all
+	j	restore_partial
 
 n64_syscall_exit_work:
-	j	syscall_exit_work
+	j	syscall_exit_work_partial
 
 /* ------------------------------------------------------------------------ */
 
@@ -167,8 +160,8 @@ illegal_syscall:
 	.previous
 #endif
 
-	sw	v0, PT_R2(sp)		# result
-1:
+	sd	zero, PT_R7(sp)		# success
+	sd	v0, PT_R2(sp)		# result
 
 	/* Success, so skip usual error handling garbage.  */
 	LONG_L	a2, TI_FLAGS($28)	# syscall tracing enabled?
@@ -221,7 +214,7 @@ sys_call_table:
 	PTR	sys_newlstat
 	PTR	sys_poll
 	PTR	sys_lseek
-	PTR	sys_mmap2
+	PTR	old_mmap
 	PTR	sys_mprotect			/* 5010 */
 	PTR	sys_munmap
 	PTR	sys_brk
@@ -405,7 +398,7 @@ sys_call_table:
 	PTR	sys_lremovexattr		/* 5190 */
 	PTR	sys_fremovexattr
 	PTR	sys_tkill
-	PTR	sys_time
+	PTR	sys_ni_syscall
 	PTR	sys_futex
 	PTR	sys_sched_setaffinity		/* 5195 */
 	PTR	sys_sched_getaffinity
@@ -427,7 +420,7 @@ sys_call_table:
 	PTR	sys_set_tid_address
 	PTR	sys_restart_syscall
 	PTR	sys_semtimedop
-	PTR	sys_fadvise64			/* 5215 */
+	PTR	sys_fadvise64_64		/* 5215 */
 	PTR	sys_timer_create
 	PTR	sys_timer_settime
 	PTR	sys_timer_gettime
--- diff/arch/mips/kernel/scall64-n32.S	2003-08-20 14:16:36.000000000 +0100
+++ source/arch/mips/kernel/scall64-n32.S	2004-02-23 13:56:38.000000000 +0000
@@ -14,6 +14,7 @@
 #include <asm/mipsregs.h>
 #include <asm/regdef.h>
 #include <asm/stackframe.h>
+#include <asm/thread_info.h>
 #include <asm/unistd.h>
 
 /* This duplicates the definition from <linux/sched.h> */
@@ -67,14 +68,14 @@ FEXPORT(n32_syscall_exit)
 					# signals dont change between
 					# sampling and return
 	LONG_L  a2, TI_FLAGS($28)	# current->work
-	bnez	a2, n32_syscall_exit_work
+	li	t0, _TIF_ALLWORK_MASK
+	and	t0, a2, t0
+	bnez	t0, n32_syscall_exit_work
 
-	RESTORE_SOME
-	RESTORE_SP_AND_RET
+	j	restore_partial
 
 n32_syscall_exit_work:
-	SAVE_STATIC
-	j	syscall_exit_work
+	j	syscall_exit_work_partial
 
 /* ------------------------------------------------------------------------ */
 
@@ -118,7 +119,7 @@ EXPORT(sysn32_call_table)
 	PTR	sys_newlstat
 	PTR	sys_poll
 	PTR	sys_lseek
-	PTR	sys_mmap2
+	PTR	old_mmap
 	PTR	sys_mprotect			/* 6010 */
 	PTR	sys_munmap
 	PTR	sys_brk
@@ -302,10 +303,10 @@ EXPORT(sysn32_call_table)
 	PTR	sys_lremovexattr		/* 6190 */
 	PTR	sys_fremovexattr
 	PTR	sys_tkill
-	PTR	sys_time
+	PTR	sys_ni_syscall
 	PTR	compat_sys_futex
-	PTR	sys32_sched_setaffinity		/* 6195 */
-	PTR	sys32_sched_getaffinity
+	PTR	compat_sys_sched_setaffinity	/* 6195 */
+	PTR	compat_sys_sched_getaffinity
 	PTR	sys_cacheflush
 	PTR	sys_cachectl
 	PTR	sys_sysmips
@@ -325,7 +326,7 @@ EXPORT(sysn32_call_table)
 	PTR	sys_set_tid_address
 	PTR	sys_restart_syscall
 	PTR	sys_semtimedop			/* 6215 */
-	PTR	sys_fadvise64
+	PTR	sys_fadvise64_64
 	PTR	sys_statfs64
 	PTR	sys_fstatfs64
 	PTR	sys_sendfile64
--- diff/arch/mips/kernel/scall64-o32.S	2003-08-20 14:16:36.000000000 +0100
+++ source/arch/mips/kernel/scall64-o32.S	2004-02-23 13:56:38.000000000 +0000
@@ -12,12 +12,14 @@
  * to ABI64 calling convention.  64-bit syscalls are also processed
  * here for now.
  */
+#include <linux/config.h>
 #include <linux/errno.h>
 #include <asm/asm.h>
 #include <asm/asmmacro.h>
 #include <asm/mipsregs.h>
 #include <asm/regdef.h>
 #include <asm/stackframe.h>
+#include <asm/thread_info.h>
 #include <asm/unistd.h>
 #include <asm/sysmips.h>
 
@@ -76,14 +78,14 @@ FEXPORT(o32_syscall_exit)
 					# signals dont change between
 					# sampling and return
 	LONG_L	a2, TI_FLAGS($28)
-	bnez	a2, o32_syscall_exit_work
+	li	t0, _TIF_ALLWORK_MASK
+	and	t0, a2, t0
+	bnez	t0, o32_syscall_exit_work
 
-	RESTORE_SOME
-	RESTORE_SP_AND_RET
+	j	restore_partial
 
 o32_syscall_exit_work:
-	SAVE_STATIC
-	j	syscall_exit_work
+	j	syscall_exit_work_partial
 
 /* ------------------------------------------------------------------------ */
 
@@ -315,7 +317,7 @@ out:	jr	ra
 	sys	sys_olduname	1
 	sys	sys_umask	1			/* 4060 */
 	sys	sys_chroot	1
-	sys	sys_ustat	2
+	sys	sys32_ustat	2
 	sys	sys_dup2	2
 	sys	sys_getppid	0
 	sys	sys_getpgrp	0			/* 4065 */
@@ -355,7 +357,7 @@ out:	jr	ra
 	sys	compat_sys_statfs	2
 	sys	compat_sys_fstatfs	2		/* 4100 */
 	sys	sys_ni_syscall		0		/* sys_ioperm */
-	sys	sys_socketcall		2
+	sys	sys32_socketcall		2
 	sys	sys_syslog		3
 	sys	compat_sys_setitimer	3
 	sys	compat_sys_getitimer	2	/* 4105 */
@@ -492,8 +494,8 @@ out:	jr	ra
 	sys	sys_tkill		2
 	sys	sys_sendfile64		5
 	sys	compat_sys_futex	5
-	sys	sys32_sched_setaffinity	3
-	sys	sys32_sched_getaffinity	3		/* 4240 */
+	sys	compat_sys_sched_setaffinity	3
+	sys	compat_sys_sched_getaffinity	3	/* 4240 */
 	sys	sys_io_setup		2
 	sys	sys_io_destroy		1
 	sys	sys_io_getevents	5
@@ -507,7 +509,7 @@ out:	jr	ra
 	sys	sys_remap_file_pages	5
 	sys	sys_set_tid_address	1
 	sys	sys_restart_syscall	0
-	sys	sys_fadvise64		6
+	sys	sys_fadvise64_64	7
 	sys	sys_statfs64		3		/* 4255 */
 	sys	sys_fstatfs64		2
 	sys	sys_timer_create	3
--- diff/arch/mips/kernel/semaphore.c	2002-10-16 04:28:26.000000000 +0100
+++ source/arch/mips/kernel/semaphore.c	2004-02-23 13:56:38.000000000 +0000
@@ -1,129 +1,272 @@
 /*
- *  Generic semaphore code. Buyer beware. Do your own
- * specific changes in <asm/semaphore-helper.h>
+ * Copyright (C) 1999, 2001, 02, 03 Ralf Baechle
+ *
+ * Heavily inspired by the Alpha implementation
  */
-
+#include <linux/config.h>
+#include <linux/errno.h>
+#include <linux/module.h>
 #include <linux/sched.h>
-#include <asm/semaphore-helper.h>
+
+#ifdef CONFIG_CPU_HAS_LLDSCD
+/*
+ * On machines without lld/scd we need a spinlock to make the manipulation of
+ * sem->count and sem->waking atomic.  Scalability isn't an issue because
+ * this lock is used on UP only so it's just an empty variable.
+ */
+spinlock_t semaphore_lock = SPIN_LOCK_UNLOCKED;
+
+EXPORT_SYMBOL(semaphore_lock);
+#endif
 
 /*
- * Semaphores are implemented using a two-way counter:
- * The "count" variable is decremented for each process
- * that tries to sleep, while the "waking" variable is
- * incremented when the "up()" code goes to wake up waiting
- * processes.
- *
- * Notably, the inline "up()" and "down()" functions can
- * efficiently test if they need to do any extra work (up
- * needs to do something only if count was negative before
- * the increment operation.
- *
- * waking_non_zero() (from asm/semaphore.h) must execute
- * atomically.
- *
- * When __up() is called, the count was negative before
- * incrementing it, and we need to wake up somebody.
- *
- * This routine adds one to the count of processes that need to
- * wake up and exit.  ALL waiting processes actually wake up but
- * only the one that gets to the "waking" field first will gate
- * through and acquire the semaphore.  The others will go back
- * to sleep.
- *
- * Note that these functions are only called when there is
- * contention on the lock, and as such all this is the
- * "non-critical" part of the whole semaphore business. The
- * critical part is the inline stuff in <asm/semaphore.h>
- * where we want to avoid any extra jumps and calls.
+ * Semaphores are implemented using a two-way counter: The "count" variable is
+ * decremented for each process that tries to sleep, while the "waking" variable
+ * is incremented when the "up()" code goes to wake up waiting processes.
+ *
+ * Notably, the inline "up()" and "down()" functions can efficiently test if
+ * they need to do any extra work (up needs to do something only if count was
+ * negative before the increment operation.
+ *
+ * waking_non_zero() must execute atomically.
+ *
+ * When __up() is called, the count was negative before incrementing it, and we
+ * need to wake up somebody.
+ *
+ * This routine adds one to the count of processes that need to wake up and
+ * exit.  ALL waiting processes actually wake up but only the one that gets to
+ * the "waking" field first will gate through and acquire the semaphore.  The
+ * others will go back to sleep.
+ *
+ * Note that these functions are only called when there is contention on the
+ * lock, and as such all this is the "non-critical" part of the whole semaphore
+ * business. The critical part is the inline stuff in <asm/semaphore.h> where
+ * we want to avoid any extra jumps and calls.
  */
-void __up(struct semaphore *sem)
+void __up_wakeup(struct semaphore *sem)
 {
-	wake_one_more(sem);
 	wake_up(&sem->wait);
 }
 
+EXPORT_SYMBOL(__up_wakeup);
+
+#ifdef CONFIG_CPU_HAS_LLSC
+
+static inline int waking_non_zero(struct semaphore *sem)
+{
+	int ret, tmp;
+
+	__asm__ __volatile__(
+	"1:	ll	%1, %2			# waking_non_zero	\n"
+	"	blez	%1, 2f						\n"
+	"	subu	%0, %1, 1					\n"
+	"	sc	%0, %2						\n"
+	"	beqz	%0, 1b						\n"
+	"2:								\n"
+	: "=r" (ret), "=r" (tmp), "+m" (sem->waking)
+	: "0" (0));
+
+	return ret;
+}
+
+#else /* !CONFIG_CPU_HAS_LLSC */
+
+static inline int waking_non_zero(struct semaphore *sem)
+{
+	unsigned long flags;
+	int waking, ret = 0;
+
+	spin_lock_irqsave(&semaphore_lock, flags);
+	waking = atomic_read(&sem->waking);
+	if (waking > 0) {
+		atomic_set(&sem->waking, waking - 1);
+		ret = 1;
+	}
+	spin_unlock_irqrestore(&semaphore_lock, flags);
+
+	return ret;
+}
+
+#endif /* !CONFIG_CPU_HAS_LLSC */
+
 /*
- * Perform the "down" function.  Return zero for semaphore acquired,
- * return negative for signalled out of the function.
+ * Perform the "down" function.  Return zero for semaphore acquired, return
+ * negative for signalled out of the function.
  *
- * If called from __down, the return is ignored and the wait loop is
- * not interruptible.  This means that a task waiting on a semaphore
- * using "down()" cannot be killed until someone does an "up()" on
- * the semaphore.
- *
- * If called from __down_interruptible, the return value gets checked
- * upon return.  If the return value is negative then the task continues
- * with the negative value in the return register (it can be tested by
- * the caller).
+ * If called from down, the return is ignored and the wait loop is not
+ * interruptible.  This means that a task waiting on a semaphore using "down()"
+ * cannot be killed until someone does an "up()" on the semaphore.
  *
- * Either form may be used in conjunction with "up()".
+ * If called from down_interruptible, the return value gets checked upon return.
+ * If the return value is negative then the task continues with the negative
+ * value in the return register (it can be tested by the caller).
  *
+ * Either form may be used in conjunction with "up()".
  */
 
-#define DOWN_VAR				\
-	struct task_struct *tsk = current;	\
-	wait_queue_t wait;			\
+void __down_failed(struct semaphore * sem)
+{
+	struct task_struct *tsk = current;
+	wait_queue_t wait;
+
 	init_waitqueue_entry(&wait, tsk);
+	__set_current_state(TASK_UNINTERRUPTIBLE);
+	add_wait_queue_exclusive(&sem->wait, &wait);
 
-#define DOWN_HEAD(task_state)						\
-									\
-									\
-	tsk->state = (task_state);					\
-	add_wait_queue(&sem->wait, &wait);				\
-									\
-	/*								\
-	 * Ok, we're set up.  sem->count is known to be less than zero	\
-	 * so we must wait.						\
-	 *								\
-	 * We can let go the lock for purposes of waiting.		\
-	 * We re-acquire it after awaking so as to protect		\
-	 * all semaphore operations.					\
-	 *								\
-	 * If "up()" is called before we call waking_non_zero() then	\
-	 * we will catch it right away.  If it is called later then	\
-	 * we will have to go through a wakeup cycle to catch it.	\
-	 *								\
-	 * Multiple waiters contend for the semaphore lock to see	\
-	 * who gets to gate through and who has to wait some more.	\
-	 */								\
+	/*
+	 * Ok, we're set up.  sem->count is known to be less than zero
+	 * so we must wait.
+	 *
+	 * We can let go the lock for purposes of waiting.
+	 * We re-acquire it after awaking so as to protect
+	 * all semaphore operations.
+	 *
+	 * If "up()" is called before we call waking_non_zero() then
+	 * we will catch it right away.  If it is called later then
+	 * we will have to go through a wakeup cycle to catch it.
+	 *
+	 * Multiple waiters contend for the semaphore lock to see
+	 * who gets to gate through and who has to wait some more.
+	 */
 	for (;;) {
-
-#define DOWN_TAIL(task_state)			\
-		tsk->state = (task_state);	\
-	}					\
-	tsk->state = TASK_RUNNING;		\
+		if (waking_non_zero(sem))
+			break;
+		schedule();
+		__set_current_state(TASK_UNINTERRUPTIBLE);
+	}
+	__set_current_state(TASK_RUNNING);
 	remove_wait_queue(&sem->wait, &wait);
+}
+
+EXPORT_SYMBOL(__down_failed);
+
+#ifdef CONFIG_CPU_HAS_LLDSCD
+
+/*
+ * waking_non_zero_interruptible:
+ *	1	got the lock
+ *	0	go to sleep
+ *	-EINTR	interrupted
+ *
+ * We must undo the sem->count down_interruptible decrement
+ * simultaneously and atomically with the sem->waking adjustment,
+ * otherwise we can race with wake_one_more.
+ *
+ * This is accomplished by doing a 64-bit lld/scd on the 2 32-bit words.
+ *
+ * This is crazy.  Normally it's strictly forbidden to use 64-bit operations
+ * in the 32-bit MIPS kernel.  In this case it's however ok because if an
+ * interrupt has destroyed the upper half of registers sc will fail.
+ * Note also that this will not work for MIPS32 CPUs!
+ *
+ * Pseudocode:
+ *
+ * If(sem->waking > 0) {
+ *	Decrement(sem->waking)
+ *	Return(SUCCESS)
+ * } else If(signal_pending(tsk)) {
+ *	Increment(sem->count)
+ *	Return(-EINTR)
+ * } else {
+ *	Return(SLEEP)
+ * }
+ */
 
-void __down(struct semaphore * sem)
+static inline int
+waking_non_zero_interruptible(struct semaphore *sem, struct task_struct *tsk)
 {
-	DOWN_VAR
-	DOWN_HEAD(TASK_UNINTERRUPTIBLE)
-	if (waking_non_zero(sem))
-		break;
-	schedule();
-	DOWN_TAIL(TASK_UNINTERRUPTIBLE)
+	long ret, tmp;
+
+	__asm__ __volatile__(
+	"	.set	push		# waking_non_zero_interruptible	\n"
+	"	.set	mips3						\n"
+	"	.set	noat						\n"
+	"0:	lld	%1, %2						\n"
+	"	li	%0, 0						\n"
+	"	sll	$1, %1, 0					\n"
+	"	blez	$1, 1f						\n"
+	"	daddiu	%1, %1, -1					\n"
+	"	li	%0, 1						\n"
+	"	b	2f						\n"
+	"1:	beqz	%3, 2f						\n"
+	"	li	%0, %4						\n"
+	"	dli	$1, 0x0000000100000000				\n"
+	"	daddu	%1, %1, $1					\n"
+	"2:	scd	%1, %2						\n"
+	"	beqz	%1, 0b						\n"
+	"	.set	pop						\n"
+	: "=&r" (ret), "=&r" (tmp), "=m" (*sem)
+	: "r" (signal_pending(tsk)), "i" (-EINTR));
+
+	return ret;
 }
 
-int __down_interruptible(struct semaphore * sem)
+#else /* !CONFIG_CPU_HAS_LLDSCD */
+
+static inline int waking_non_zero_interruptible(struct semaphore *sem,
+						struct task_struct *tsk)
 {
-	int ret = 0;
-	DOWN_VAR
-	DOWN_HEAD(TASK_INTERRUPTIBLE)
+	int waking, pending, ret = 0;
+	unsigned long flags;
 
-	ret = waking_non_zero_interruptible(sem, tsk);
-	if (ret)
-	{
-		if (ret == 1)
-			/* ret != 0 only if we get interrupted -arca */
-			ret = 0;
-		break;
+	pending = signal_pending(tsk);
+
+	spin_lock_irqsave(&semaphore_lock, flags);
+	waking = atomic_read(&sem->waking);
+	if (waking > 0) {
+		atomic_set(&sem->waking, waking - 1);
+		ret = 1;
+	} else if (pending) {
+		atomic_set(&sem->count, atomic_read(&sem->count) + 1);
+		ret = -EINTR;
 	}
-	schedule();
-	DOWN_TAIL(TASK_INTERRUPTIBLE)
+	spin_unlock_irqrestore(&semaphore_lock, flags);
+
 	return ret;
 }
 
-int __down_trylock(struct semaphore * sem)
+#endif /* !CONFIG_CPU_HAS_LLDSCD */
+
+int __down_failed_interruptible(struct semaphore * sem)
 {
-	return waking_non_zero_trylock(sem);
+	struct task_struct *tsk = current;
+	wait_queue_t wait;
+	int ret = 0;
+
+	init_waitqueue_entry(&wait, tsk);
+	__set_current_state(TASK_INTERRUPTIBLE);
+	add_wait_queue_exclusive(&sem->wait, &wait);
+
+	/*
+	 * Ok, we're set up.  sem->count is known to be less than zero
+	 * so we must wait.
+	 *
+	 * We can let go the lock for purposes of waiting.
+	 * We re-acquire it after awaking so as to protect
+	 * all semaphore operations.
+	 *
+	 * If "up()" is called before we call waking_non_zero() then
+	 * we will catch it right away.  If it is called later then
+	 * we will have to go through a wakeup cycle to catch it.
+	 *
+	 * Multiple waiters contend for the semaphore lock to see
+	 * who gets to gate through and who has to wait some more.
+	 */
+	for (;;) {
+		ret = waking_non_zero_interruptible(sem, tsk);
+		if (ret) {
+			if (ret == 1)
+				/* ret != 0 only if we get interrupted -arca */
+				ret = 0;
+			break;
+		}
+		schedule();
+		__set_current_state(TASK_INTERRUPTIBLE);
+	}
+	__set_current_state(TASK_RUNNING);
+	remove_wait_queue(&sem->wait, &wait);
+
+	return ret;
 }
+
+EXPORT_SYMBOL(__down_failed_interruptible);
--- diff/arch/mips/kernel/setup.c	2003-09-30 15:46:11.000000000 +0100
+++ source/arch/mips/kernel/setup.c	2004-02-23 13:56:38.000000000 +0000
@@ -31,6 +31,8 @@
 #include <linux/major.h>
 #include <linux/kdev_t.h>
 #include <linux/root_dev.h>
+#include <linux/highmem.h>
+#include <linux/console.h>
 
 #include <asm/addrspace.h>
 #include <asm/bootinfo.h>
@@ -40,25 +42,21 @@
 
 struct cpuinfo_mips cpu_data[NR_CPUS];
 
+EXPORT_SYMBOL(cpu_data);
+
 #ifdef CONFIG_VT
 struct screen_info screen_info;
 #endif
 
-#if defined(CONFIG_BLK_DEV_FD) || defined(CONFIG_BLK_DEV_FD_MODULE)
-extern struct fd_ops no_fd_ops;
-struct fd_ops *fd_ops;
-#endif
+/*
+ * Despite it's name this variable is even if we don't have PCI
+ */
+unsigned int PCI_DMA_BUS_IS_PHYS;
 
-#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)
-extern struct ide_ops no_ide_ops;
-struct ide_ops *ide_ops;
-#endif
+EXPORT_SYMBOL(PCI_DMA_BUS_IS_PHYS);
 
 extern void * __rd_start, * __rd_end;
 
-extern struct rtc_ops no_rtc_ops;
-struct rtc_ops *rtc_ops;
-
 /*
  * Setup information
  *
@@ -67,11 +65,14 @@ struct rtc_ops *rtc_ops;
 unsigned long mips_machtype = MACH_UNKNOWN;
 unsigned long mips_machgroup = MACH_GROUP_UNKNOWN;
 
+EXPORT_SYMBOL(mips_machtype);
+EXPORT_SYMBOL(mips_machgroup);
+
 struct boot_mem_map boot_mem_map;
 
 static char command_line[CL_SIZE];
        char saved_command_line[CL_SIZE];
-extern char arcs_cmdline[CL_SIZE];
+       char arcs_cmdline[CL_SIZE]=CONFIG_CMDLINE;
 
 /*
  * mips_io_port_base is the begin of the address space to which x86 style
@@ -87,53 +88,22 @@ EXPORT_SYMBOL(mips_io_port_base);
 unsigned long isa_slot_offset;
 EXPORT_SYMBOL(isa_slot_offset);
 
-extern void SetUpBootInfo(void);
-extern void load_mmu(void);
-extern ATTRIB_NORET asmlinkage void start_kernel(void);
-extern void prom_init(int, char **, char **, int *);
-
 static struct resource code_resource = { "Kernel code" };
 static struct resource data_resource = { "Kernel data" };
 
-asmlinkage void __init init_arch(int argc, char **argv, char **envp,
-	int *prom_vec)
+void __init add_memory_region(phys_t start, phys_t size, long type)
 {
-	/* Determine which MIPS variant we are running on. */
-	cpu_probe();
-
-	prom_init(argc, argv, envp, prom_vec);
-
-	cpu_report();
-
-	/*
-	 * Determine the mmu/cache attached to this machine, then flush the
-	 * tlb and caches.  On the r4xx0 variants this also sets CP0_WIRED to
-	 * zero.
-	 */
-	load_mmu();
+	int x = boot_mem_map.nr_map;
+	struct boot_mem_map_entry *prev = boot_mem_map.map + x - 1;
 
-#ifdef CONFIG_MIPS32
-	/* Disable coprocessors and set FPU for 16/32 FPR register model */
-	clear_c0_status(ST0_CU1|ST0_CU2|ST0_CU3|ST0_KX|ST0_SX|ST0_FR);
-	set_c0_status(ST0_CU0);
-#endif
-#ifdef CONFIG_MIPS64
 	/*
-	 * On IP27, I am seeing the TS bit set when the kernel is loaded.
-	 * Maybe because the kernel is in ckseg0 and not xkphys? Clear it
-	 * anyway ...
+	 * Try to merge with previous entry if any.  This is far less than
+	 * perfect but is sufficient for most real world cases.
 	 */
-	clear_c0_status(ST0_BEV|ST0_TS|ST0_CU1|ST0_CU2|ST0_CU3);
-	set_c0_status(ST0_CU0|ST0_KX|ST0_SX|ST0_FR);
-#endif
-
-	start_kernel();
-}
-
-void __init add_memory_region(phys_t start, phys_t size,
-			      long type)
-{
-	int x = boot_mem_map.nr_map;
+	if (x && prev->addr + prev->size == start && prev->type == type) {
+		prev->size += size;
+		return;
+	}
 
 	if (x == BOOT_MEM_MAP_MAX) {
 		printk("Ooops! Too many entries in the memory map!\n");
@@ -149,11 +119,12 @@ void __init add_memory_region(phys_t sta
 static void __init print_memory_map(void)
 {
 	int i;
+	const int field = 2 * sizeof(unsigned long);
 
 	for (i = 0; i < boot_mem_map.nr_map; i++) {
 		printk(" memory: %0*Lx @ %0*Lx ",
-		       sizeof(long) * 2, (u64) boot_mem_map.map[i].size,
-		       sizeof(long) * 2, (u64) boot_mem_map.map[i].addr);
+		       field, (unsigned long long) boot_mem_map.map[i].size,
+		       field, (unsigned long long) boot_mem_map.map[i].addr);
 
 		switch (boot_mem_map.map[i].type) {
 		case BOOT_MEM_RAM:
@@ -233,15 +204,15 @@ static inline void parse_cmdline_early(v
 
 static inline void bootmem_init(void)
 {
+	unsigned long start_pfn;
+#ifndef CONFIG_SGI_IP27
+	unsigned long bootmap_size, max_low_pfn, first_usable_pfn;
+	int i;
+#endif
 #ifdef CONFIG_BLK_DEV_INITRD
 	unsigned long tmp;
 	unsigned long *initrd_header;
-#endif
-	unsigned long bootmap_size;
-	unsigned long start_pfn, max_low_pfn, first_usable_pfn;
-	int i;
 
-#ifdef CONFIG_BLK_DEV_INITRD
 	tmp = (((unsigned long)&_end + PAGE_SIZE-1) & PAGE_MASK) - 8;
 	if (tmp < (unsigned long)&_end)
 		tmp += PAGE_SIZE;
@@ -385,8 +356,7 @@ static inline void bootmem_init(void)
 		printk("Initial ramdisk at: 0x%p (%lu bytes)\n",
 		       (void *)initrd_start,
 		       initrd_size);
-/* FIXME: is this right? */
-#ifndef CONFIG_SGI_IP27
+
 		if (CPHYSADDR(initrd_end) > PFN_PHYS(max_low_pfn)) {
 			printk("initrd extends beyond end of memory "
 			       "(0x%0*Lx > 0x%0*Lx)\ndisabling initrd\n",
@@ -394,7 +364,6 @@ static inline void bootmem_init(void)
 			       sizeof(long) * 2, PFN_PHYS(max_low_pfn));
 			initrd_start = initrd_end = 0;
 		}
-#endif /* !CONFIG_SGI_IP27 */
 	}
 #endif /* CONFIG_BLK_DEV_INITRD  */
 }
@@ -456,229 +425,63 @@ static inline void resource_init(void)
 #undef MAXMEM
 #undef MAXMEM_PFN
 
-void __init setup_arch(char **cmdline_p)
+static int __initdata earlyinit_debug;
+
+static int __init earlyinit_debug_setup(char *str)
 {
-	extern void atlas_setup(void);
-	extern void baget_setup(void);
-	extern void cobalt_setup(void);
-	extern void lasat_setup(void);
-	extern void ddb_setup(void);
-	extern void decstation_setup(void);
-	extern void deskstation_setup(void);
-	extern void jazz_setup(void);
-	extern void sni_rm200_pci_setup(void);
-	extern void ip22_setup(void);
-	extern void ip27_setup(void);
-	extern void ip32_setup(void);
-	extern void ev96100_setup(void);
-	extern void malta_setup(void);
-	extern void sead_setup(void);
-	extern void ikos_setup(void);
-	extern void momenco_ocelot_setup(void);
-	extern void momenco_ocelot_g_setup(void);
-	extern void momenco_ocelot_c_setup(void);
-	extern void nec_osprey_setup(void);
-	extern void nec_eagle_setup(void);
-	extern void zao_capcella_setup(void);
-	extern void victor_mpc30x_setup(void);
-	extern void ibm_workpad_setup(void);
-	extern void casio_e55_setup(void);
-	extern void jmr3927_setup(void);
-	extern void it8172_setup(void);
-	extern void swarm_setup(void);
-	extern void hp_setup(void);
-	extern void au1x00_setup(void);
-	extern void frame_info_init(void);
+	earlyinit_debug = 1;
+	return 1;
+}
+__setup("earlyinit_debug", earlyinit_debug_setup);
 
-	frame_info_init();
+extern initcall_t __earlyinitcall_start, __earlyinitcall_end;
 
-#ifdef CONFIG_BLK_DEV_FD
-	fd_ops = &no_fd_ops;
-#endif
+static void __init do_earlyinitcalls(void)
+{
+	initcall_t *call, *start, *end;
 
-#ifdef CONFIG_BLK_DEV_IDE
-	ide_ops = &no_ide_ops;
-#endif
+	start = &__earlyinitcall_start;
+	end = &__earlyinitcall_end;
 
-	rtc_ops = &no_rtc_ops;
+	for (call = start; call < end; call++) {
+		if (earlyinit_debug)
+			printk("calling earlyinitcall 0x%p\n", *call);
 
-	switch (mips_machgroup) {
-#ifdef CONFIG_BAGET_MIPS
-	case MACH_GROUP_BAGET:
-		baget_setup();
-		break;
-#endif
-#ifdef CONFIG_MIPS_COBALT
-	case MACH_GROUP_COBALT:
-		cobalt_setup();
-		break;
-#endif
-#ifdef CONFIG_DECSTATION
-	case MACH_GROUP_DEC:
-		decstation_setup();
-		break;
-#endif
-#ifdef CONFIG_MIPS_ATLAS
-	case MACH_GROUP_UNKNOWN:
-		atlas_setup();
-		break;
-#endif
-#ifdef CONFIG_MIPS_JAZZ
-	case MACH_GROUP_JAZZ:
-		jazz_setup();
-		break;
-#endif
-#ifdef CONFIG_MIPS_MALTA
-	case MACH_GROUP_UNKNOWN:
-		malta_setup();
-		break;
-#endif
-#ifdef CONFIG_MOMENCO_OCELOT
-	case MACH_GROUP_MOMENCO:
-		momenco_ocelot_setup();
-		break;
-#endif
-#ifdef CONFIG_MOMENCO_OCELOT_G
-	case MACH_GROUP_MOMENCO:
-		momenco_ocelot_g_setup();
-		break;
-#endif
-#ifdef CONFIG_MOMENCO_OCELOT_C
-	case MACH_GROUP_MOMENCO:
-		momenco_ocelot_c_setup();
-		break;
-#endif
-#ifdef CONFIG_MIPS_SEAD
-	case MACH_GROUP_UNKNOWN:
-		sead_setup();
-		break;
-#endif
-#ifdef CONFIG_SGI_IP22
-	/* As of now this is only IP22.  */
-	case MACH_GROUP_SGI:
-		ip22_setup();
-		break;
-#endif
-#ifdef CONFIG_SGI_IP27
-	case MACH_GROUP_SGI:
-		ip27_setup();
-		break;
-#endif
-#ifdef CONFIG_SGI_IP32
-	case MACH_GROUP_SGI:
-		ip32_setup();
-		break;
-#endif
-#ifdef CONFIG_SNI_RM200_PCI
-	case MACH_GROUP_SNI_RM:
-		sni_rm200_pci_setup();
-		break;
-#endif
-#ifdef CONFIG_DDB5074
-	case MACH_GROUP_NEC_DDB:
-		ddb_setup();
-		break;
-#endif
-#ifdef CONFIG_DDB5476
-       case MACH_GROUP_NEC_DDB:
-               ddb_setup();
-               break;
-#endif
-#ifdef CONFIG_DDB5477
-       case MACH_GROUP_NEC_DDB:
-               ddb_setup();
-               break;
-#endif
-#ifdef CONFIG_CPU_VR41XX
-	case MACH_GROUP_NEC_VR41XX:
-		switch (mips_machtype) {
-#ifdef CONFIG_NEC_OSPREY
-		case MACH_NEC_OSPREY:
-			nec_osprey_setup();
-			break;
-#endif
-#ifdef CONFIG_NEC_EAGLE
-		case MACH_NEC_EAGLE:
-			nec_eagle_setup();
-			break;
-#endif
-#ifdef CONFIG_ZAO_CAPCELLA
-		case MACH_ZAO_CAPCELLA:
-			zao_capcella_setup();
-			break;
-#endif
-#ifdef CONFIG_VICTOR_MPC30X
-		case MACH_VICTOR_MPC30X:
-			victor_mpc30x_setup();
-			break;
-#endif
-#ifdef CONFIG_IBM_WORKPAD
-		case MACH_IBM_WORKPAD:
-			ibm_workpad_setup();
-			break;
-#endif
-#ifdef CONFIG_CASIO_E55
-		case MACH_CASIO_E55:
-			casio_e55_setup();
-			break;
-#endif
-#ifdef CONFIG_TANBAC_TB0229
-		case MACH_TANBAC_TB0229:
-			tanbac_tb0229_setup();
-			break;
-#endif
-		}
-		break;
-#endif
-#ifdef CONFIG_MIPS_EV96100
-	case MACH_GROUP_GALILEO:
-		ev96100_setup();
-		break;
-#endif
-#ifdef CONFIG_MIPS_EV64120
-	case MACH_GROUP_GALILEO:
-		ev64120_setup();
-		break;
-#endif
-#if defined(CONFIG_MIPS_IVR) || defined(CONFIG_MIPS_ITE8172)
-	case  MACH_GROUP_ITE:
-	case  MACH_GROUP_GLOBESPAN:
-		it8172_setup();
-		break;
-#endif
-#ifdef CONFIG_LASAT
-        case MACH_GROUP_LASAT:
-                lasat_setup();
-                break;
-#endif
-#ifdef CONFIG_SOC_AU1X00
-	case MACH_GROUP_ALCHEMY:
-		au1x00_setup();
-		break;
-#endif
-#ifdef CONFIG_TOSHIBA_JMR3927
-	case MACH_GROUP_TOSHIBA:
-		jmr3927_setup();
-		break;
+		(*call)();
+	}
+}
+
+void __init setup_arch(char **cmdline_p)
+{
+	cpu_probe();
+	prom_init();
+	cpu_report();
+
+#ifdef CONFIG_MIPS32
+	/* Disable coprocessors and set FPU for 16/32 FPR register model */
+	clear_c0_status(ST0_CU1|ST0_CU2|ST0_CU3|ST0_KX|ST0_SX|ST0_FR);
+	set_c0_status(ST0_CU0);
 #endif
-#ifdef CONFIG_TOSHIBA_RBTX4927
-	case MACH_GROUP_TOSHIBA:
-		tx4927_setup();
-		break;
+#ifdef CONFIG_MIPS64
+	/*
+	 * On IP27, I am seeing the TS bit set when the kernel is loaded.
+	 * Maybe because the kernel is in ckseg0 and not xkphys? Clear it
+	 * anyway ...
+	 */
+	clear_c0_status(ST0_BEV|ST0_TS|ST0_CU1|ST0_CU2|ST0_CU3);
+	set_c0_status(ST0_CU0|ST0_KX|ST0_SX|ST0_FR);
 #endif
-#ifdef CONFIG_SIBYTE_BOARD
-	case MACH_GROUP_SIBYTE:
-		swarm_setup();
-		break;
+
+#if defined(CONFIG_VT)
+#if defined(CONFIG_VGA_CONSOLE)
+        conswitchp = &vga_con;
+#elif defined(CONFIG_DUMMY_CONSOLE)
+        conswitchp = &dummy_con;
 #endif
-#ifdef CONFIG_HP_LASERJET
-        case MACH_GROUP_HP_LJ:
-                hp_setup();
-                break;
 #endif
-	default:
-		panic("Unsupported architecture");
-	}
+
+	/* call board setup routine */
+	do_earlyinitcalls();
 
 	strlcpy(command_line, arcs_cmdline, sizeof(command_line));
 	strlcpy(saved_command_line, command_line, sizeof(saved_command_line));
@@ -686,11 +489,8 @@ void __init setup_arch(char **cmdline_p)
 	*cmdline_p = command_line;
 
 	parse_cmdline_early();
-
 	bootmem_init();
-
 	paging_init();
-
 	resource_init();
 }
 
--- diff/arch/mips/kernel/signal.c	2003-08-20 14:16:25.000000000 +0100
+++ source/arch/mips/kernel/signal.c	2004-02-23 13:56:38.000000000 +0000
@@ -74,8 +74,6 @@ static_unused int _sys_rt_sigsuspend(nab
 	sigset_t *unewset, saveset, newset;
 	size_t sigsetsize;
 
-	save_static(&regs);
-
 	/* XXX Don't preclude handling different sized sigset_t's.  */
 	sigsetsize = regs.regs[5];
 	if (sigsetsize != sizeof(sigset_t))
@@ -156,6 +154,9 @@ asmlinkage int restore_sigcontext(struct
 {
 	int err = 0;
 
+	/* Always make any pending restarted system calls return -EINTR */
+	current_thread_info()->restart_block.fn = do_no_restart_syscall;
+
 	err |= __get_user(regs->cp0_epc, &sc->sc_pc);
 	err |= __get_user(regs->hi, &sc->sc_mdhi);
 	err |= __get_user(regs->lo, &sc->sc_mdlo);
@@ -490,7 +491,6 @@ static inline void handle_signal(unsigne
 
 	switch(regs->regs[0]) {
 	case ERESTART_RESTARTBLOCK:
-		current_thread_info()->restart_block.fn = do_no_restart_syscall;
 	case ERESTARTNOHAND:
 		regs->regs[2] = EINTR;
 		break;
@@ -508,9 +508,9 @@ static inline void handle_signal(unsigne
 	regs->regs[0] = 0;		/* Don't deal with this again.  */
 
 #ifdef CONFIG_TRAD_SIGNALS
-	if (ka->sa.sa_flags & SA_SIGINFO)
+	if (ka->sa.sa_flags & SA_SIGINFO) {
 #else
-	if (1)
+	if (1) {
 #endif
 #ifdef CONFIG_MIPS32_N32
 		if ((current->thread.mflags & MF_ABI_MASK) == MF_N32)
@@ -518,8 +518,11 @@ static inline void handle_signal(unsigne
 		else
 #endif
 			setup_rt_frame(ka, regs, sig, oldset, info);
+	}
+#ifdef CONFIG_TRAD_SIGNALS
 	else
 		setup_frame(ka, regs, sig, oldset);
+#endif
 
 	if (ka->sa.sa_flags & SA_ONESHOT)
 		ka->sa.sa_handler = SIG_DFL;
@@ -569,6 +572,7 @@ asmlinkage int do_signal(sigset_t *oldse
 		}
 		if (regs->regs[2] == ERESTART_RESTARTBLOCK) {
 			regs->regs[2] = __NR_restart_syscall;
+			regs->regs[7] = regs->regs[26];
 			regs->cp0_epc -= 4;
 		}
 	}
--- diff/arch/mips/kernel/signal32.c	2003-08-20 14:16:36.000000000 +0100
+++ source/arch/mips/kernel/signal32.c	2004-02-23 13:56:38.000000000 +0000
@@ -13,6 +13,7 @@
 #include <linux/smp_lock.h>
 #include <linux/kernel.h>
 #include <linux/signal.h>
+#include <linux/syscalls.h>
 #include <linux/errno.h>
 #include <linux/wait.h>
 #include <linux/ptrace.h>
@@ -28,7 +29,7 @@
 #include <asm/fpu.h>
 
 /*
- * Including <asm/unistd.h would give use the 64-bit syscall numbers ...
+ * Including <asm/unistd.h> would give use the 64-bit syscall numbers ...
  */
 #define __NR_O32_sigreturn		4119
 #define __NR_O32_rt_sigreturn		4193
@@ -126,12 +127,12 @@ static inline int get_sigset(sigset_t *k
 /*
  * Atomically swap in the new signal mask, and wait for a signal.
  */
-asmlinkage inline int sys32_sigsuspend(nabi_no_regargs struct pt_regs regs)
+save_static_function(sys32_sigsuspend);
+static_unused int _sys32_sigsuspend(nabi_no_regargs struct pt_regs regs)
 {
 	compat_sigset_t *uset;
 	sigset_t newset, saveset;
 
-	save_static(&regs);
 	uset = (compat_sigset_t *) regs.regs[4];
 	if (get_sigset(&newset, uset))
 		return -EFAULT;
@@ -153,13 +154,13 @@ asmlinkage inline int sys32_sigsuspend(n
 	}
 }
 
-asmlinkage int sys32_rt_sigsuspend(nabi_no_regargs struct pt_regs regs)
+save_static_function(sys32_rt_sigsuspend);
+static_unused int _sys32_rt_sigsuspend(nabi_no_regargs struct pt_regs regs)
 {
 	compat_sigset_t *uset;
 	sigset_t newset, saveset;
         size_t sigsetsize;
 
-	save_static(&regs);
 	/* XXX Don't preclude handling different sized sigset_t's.  */
 	sigsetsize = regs.regs[5];
 	if (sigsetsize != sizeof(compat_sigset_t))
@@ -241,7 +242,7 @@ asmlinkage int sys32_sigaltstack(nabi_no
 		if (!access_ok(VERIFY_READ, uss, sizeof(*uss)))
 			return -EFAULT;
 		err |= __get_user(sp, &uss->ss_sp);
-		kss.ss_size = (long) sp;
+		kss.ss_sp = (void *) (long) sp;
 		err |= __get_user(kss.ss_size, &uss->ss_size);
 		err |= __get_user(kss.ss_flags, &uss->ss_flags);
 		if (err)
@@ -270,6 +271,9 @@ static asmlinkage int restore_sigcontext
 {
 	int err = 0;
 
+	/* Always make any pending restarted system calls return -EINTR */
+	current_thread_info()->restart_block.fn = do_no_restart_syscall;
+
 	err |= __get_user(regs->cp0_epc, &sc->sc_pc);
 	err |= __get_user(regs->hi, &sc->sc_mdhi);
 	err |= __get_user(regs->lo, &sc->sc_mdlo);
@@ -651,7 +655,6 @@ static inline void handle_signal(unsigne
 
 	switch (regs->regs[0]) {
 	case ERESTART_RESTARTBLOCK:
-		current_thread_info()->restart_block.fn = do_no_restart_syscall;
 	case ERESTARTNOHAND:
 		regs->regs[2] = EINTR;
 		break;
@@ -712,6 +715,7 @@ asmlinkage int do_signal32(sigset_t *old
 		}
 		if (regs->regs[2] == ERESTART_RESTARTBLOCK) {
 			regs->regs[2] = __NR_O32_restart_syscall;
+			regs->regs[7] = regs->regs[26];
 			regs->cp0_epc -= 4;
 		}
 	}
@@ -761,9 +765,6 @@ out:
 	return ret;
 }
 
-asmlinkage long sys_rt_sigprocmask(int how, sigset_t *set, sigset_t *oset,
-				   size_t sigsetsize);
-
 asmlinkage int sys32_rt_sigprocmask(int how, compat_sigset_t *set,
 	compat_sigset_t *oset, unsigned int sigsetsize)
 {
@@ -785,8 +786,6 @@ asmlinkage int sys32_rt_sigprocmask(int 
 	return ret;
 }
 
-asmlinkage long sys_rt_sigpending(sigset_t *set, size_t sigsetsize);
-
 asmlinkage int sys32_rt_sigpending(compat_sigset_t *uset,
 	unsigned int sigsetsize)
 {
@@ -895,8 +894,6 @@ asmlinkage int sys32_rt_sigtimedwait(com
 	return ret;
 }
 
-extern asmlinkage int sys_rt_sigqueueinfo(int pid, int sig, siginfo_t *uinfo);
-
 asmlinkage int sys32_rt_sigqueueinfo(int pid, int sig, siginfo_t32 *uinfo)
 {
 	siginfo_t info;
--- diff/arch/mips/kernel/signal_n32.c	2003-08-20 14:16:36.000000000 +0100
+++ source/arch/mips/kernel/signal_n32.c	2004-02-23 13:56:38.000000000 +0000
@@ -15,8 +15,6 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  */
-
-#include <linux/config.h>
 #include <linux/sched.h>
 #include <linux/mm.h>
 #include <linux/smp.h>
--- diff/arch/mips/kernel/smp.c	2003-10-09 09:47:33.000000000 +0100
+++ source/arch/mips/kernel/smp.c	2004-02-23 13:56:38.000000000 +0000
@@ -16,7 +16,7 @@
  * Copyright (C) 2000, 2001 Kanoj Sarcar
  * Copyright (C) 2000, 2001 Ralf Baechle
  * Copyright (C) 2000, 2001 Silicon Graphics, Inc.
- * Copyright (C) 2000, 2001 Broadcom Corporation
+ * Copyright (C) 2000, 2001, 2003 Broadcom Corporation
  */
 #include <linux/config.h>
 #include <linux/cache.h>
@@ -29,6 +29,7 @@
 #include <linux/time.h>
 #include <linux/timex.h>
 #include <linux/sched.h>
+#include <linux/cpumask.h>
 
 #include <asm/atomic.h>
 #include <asm/cpu.h>
@@ -38,45 +39,18 @@
 #include <asm/mmu_context.h>
 #include <asm/smp.h>
 
-int smp_threads_ready;	/* Not used */
-
-// static atomic_t cpus_booted = ATOMIC_INIT(0);
-atomic_t cpus_booted = ATOMIC_INIT(0);
-
-cpumask_t phys_cpu_present_map;		/* Bitmask of physically CPUs */
+cpumask_t phys_cpu_present_map;		/* Bitmask of available CPUs */
+volatile cpumask_t cpu_callin_map;	/* Bitmask of started secondaries */
 cpumask_t cpu_online_map;		/* Bitmask of currently online CPUs */
-int __cpu_number_map[NR_CPUS];
-int __cpu_logical_map[NR_CPUS];
+int __cpu_number_map[NR_CPUS];		/* Map physical to logical */
+int __cpu_logical_map[NR_CPUS];		/* Map logical to physical */
 
 EXPORT_SYMBOL(cpu_online_map);
 
-/* These are defined by the board-specific code. */
-
-/*
- * Cause the function described by call_data to be executed on the passed
- * cpu.  When the function has finished, increment the finished field of
- * call_data.
- */
-void core_send_ipi(int cpu, unsigned int action);
-
-/*
- * Clear all undefined state in the cpu, set up sp and gp to the passed
- * values, and kick the cpu into smp_bootstrap();
- */
-void prom_boot_secondary(int cpu, unsigned long sp, unsigned long gp);
-
-/*
- *  After we've done initial boot, this function is called to allow the
- *  board code to clean up state, if needed
- */
-void prom_init_secondary(void);
-
-void prom_smp_finish(void);
-
 cycles_t cacheflush_time;
 unsigned long cache_decay_ticks;
 
-void smp_tune_scheduling (void)
+static void smp_tune_scheduling (void)
 {
 	struct cache_desc *cd = &current_cpu_data.scache;
 	unsigned long cachesize;       /* kB   */
@@ -119,49 +93,34 @@ void smp_tune_scheduling (void)
 		(cache_decay_ticks + 1) * 1000 / HZ);
 }
 
-void __init smp_callin(void)
-{
-#if 0
-	calibrate_delay();
-	smp_store_cpu_info(cpuid);
-#endif
-}
+extern void __init calibrate_delay(void);
 
-#ifndef CONFIG_SGI_IP27
 /*
- * Hook for doing final board-specific setup after the generic smp setup
- * is done
+ * First C code run on the secondary CPUs after being started up by
+ * the master.
  */
 asmlinkage void start_secondary(void)
 {
 	unsigned int cpu = smp_processor_id();
 
 	cpu_probe();
-	prom_init_secondary();
+	cpu_report();
 	per_cpu_trap_init();
+	prom_init_secondary();
 
 	/*
 	 * XXX parity protection should be folded in here when it's converted
 	 * to an option instead of something based on .cputype
 	 */
-	pgd_current[cpu] = init_mm.pgd;
+
+	calibrate_delay();
 	cpu_data[cpu].udelay_val = loops_per_jiffy;
+
 	prom_smp_finish();
-	printk("Slave cpu booted successfully\n");
-	cpu_set(cpu, cpu_online_map);
-	atomic_inc(&cpus_booted);
-	cpu_idle();
-}
-#endif /* CONFIG_SGI_IP27 */
 
-/*
- * this function sends a 'reschedule' IPI to another CPU.
- * it goes straight through and wastes no time serializing
- * anything. Worst case is that we lose a reschedule ...
- */
-void smp_send_reschedule(int cpu)
-{
-	core_send_ipi(cpu, SMP_RESCHEDULE_YOURSELF);
+	cpu_set(cpu, cpu_callin_map);
+
+	cpu_idle();
 }
 
 spinlock_t smp_call_lock = SPIN_LOCK_UNLOCKED;
@@ -201,10 +160,11 @@ int smp_call_function (void (*func) (voi
 
 	spin_lock(&smp_call_lock);
 	call_data = &data;
+	mb();
 
 	/* Send a message to all other CPUs and wait for them to respond */
 	for (i = 0; i < NR_CPUS; i++)
-		if (cpu_online(cpu) && i != cpu)
+		if (cpu_online(i) && i != cpu)
 			core_send_ipi(i, SMP_CALL_FUNCTION);
 
 	/* Wait for response */
@@ -261,6 +221,99 @@ void smp_send_stop(void)
 	smp_call_function(stop_this_cpu, NULL, 1, 0);
 }
 
+void __init smp_cpus_done(unsigned int max_cpus)
+{
+	prom_cpus_done();
+}
+
+/* called from main before smp_init() */
+void __init smp_prepare_cpus(unsigned int max_cpus)
+{
+	cpu_data[0].udelay_val = loops_per_jiffy;
+	init_new_context(current, &init_mm);
+	current_thread_info()->cpu = 0;
+	smp_tune_scheduling();
+	prom_build_cpu_map();
+	prom_prepare_cpus(max_cpus);
+}
+
+/* preload SMP state for boot cpu */
+void __devinit smp_prepare_boot_cpu(void)
+{
+	/*
+	 * This assumes that bootup is always handled by the processor
+	 * with the logic and physical number 0.
+	 */
+	__cpu_number_map[0] = 0;
+	__cpu_logical_map[0] = 0;
+	cpu_set(0, phys_cpu_present_map);
+	cpu_set(0, cpu_online_map);
+	cpu_set(0, cpu_callin_map);
+}
+
+static struct task_struct * __init fork_by_hand(void)
+{
+	struct pt_regs regs;
+	/*
+	 * don't care about the eip and regs settings since
+	 * we'll never reschedule the forked task.
+	 */
+	return copy_process(CLONE_VM|CLONE_IDLETASK, 0, &regs, 0, NULL, NULL);
+}
+
+/*
+ * Startup the CPU with this logical number
+ */
+static int __init do_boot_cpu(int cpu)
+{
+	struct task_struct *idle;
+
+	/*
+	 * The following code is purely to make sure
+	 * Linux can schedule processes on this slave.
+	 */
+	idle = fork_by_hand();
+	if (IS_ERR(idle))
+		panic("failed fork for CPU %d\n", cpu);
+
+	wake_up_forked_process(idle);
+
+	/*
+	 * We remove it from the pidhash and the runqueue once we've
+	 * got the process:
+	 */
+	init_idle(idle, cpu);
+
+	unhash_process(idle);
+
+	prom_boot_secondary(cpu, idle);
+
+	/* XXXKW timeout */
+	while (!cpu_isset(cpu, cpu_callin_map))
+		udelay(100);
+
+	cpu_set(cpu, cpu_online_map);
+
+	return 0;
+}
+
+/*
+ * Called once for each "cpu_possible(cpu)".  Needs to spin up the cpu
+ * and keep control until "cpu_online(cpu)" is set.  Note: cpu is
+ * physical, not logical.
+ */
+int __devinit __cpu_up(unsigned int cpu)
+{
+	int ret;
+
+	/* Processor goes to start_secondary(), sets online flag */
+	ret = do_boot_cpu(cpu);
+	if (ret < 0)
+		return ret;
+
+	return 0;
+}
+
 /* Not really SMP stuff ... */
 int setup_profiling_timer(unsigned int multiplier)
 {
--- diff/arch/mips/kernel/syscall.c	2003-08-20 14:16:25.000000000 +0100
+++ source/arch/mips/kernel/syscall.c	2004-02-23 13:56:38.000000000 +0000
@@ -16,6 +16,7 @@
 #include <linux/ptrace.h>
 #include <linux/sched.h>
 #include <linux/string.h>
+#include <linux/syscalls.h>
 #include <linux/file.h>
 #include <linux/slab.h>
 #include <linux/utsname.h>
@@ -111,7 +112,7 @@ static inline long
 do_mmap2(unsigned long addr, unsigned long len, unsigned long prot,
         unsigned long flags, unsigned long fd, unsigned long pgoff)
 {
-	int error = -EBADF;
+	unsigned long error = -EBADF;
 	struct file * file = NULL;
 
 	flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
@@ -134,7 +135,7 @@ out:
 asmlinkage unsigned long old_mmap(unsigned long addr, size_t len, int prot,
                                   int flags, int fd, off_t offset)
 {
-	int result;
+	unsigned long result;
 
 	result = -EINVAL;
 	if (offset & ~PAGE_MASK)
@@ -156,7 +157,6 @@ sys_mmap2(unsigned long addr, unsigned l
 save_static_function(sys_fork);
 static_unused int _sys_fork(nabi_no_regargs struct pt_regs regs)
 {
-	save_static(&regs);
 	return do_fork(SIGCHLD, regs.regs[29], &regs, 0, NULL, NULL);
 }
 
@@ -167,7 +167,6 @@ static_unused int _sys_clone(nabi_no_reg
 	unsigned long newsp;
 	int *parent_tidptr, *child_tidptr;
 
-	save_static(&regs);
 	clone_flags = regs.regs[4];
 	newsp = regs.regs[5];
 	if (!newsp)
@@ -297,7 +296,11 @@ asmlinkage int sys_ipc (uint call, int f
 
 	switch (call) {
 	case SEMOP:
-		return sys_semop (first, (struct sembuf *)ptr, second);
+		return sys_semtimedop (first, (struct sembuf *)ptr, second,
+		                       NULL);
+	case SEMTIMEDOP:
+		return sys_semtimedop (first, (struct sembuf *)ptr, second,
+		                       (const struct timespec __user *)fifth);
 	case SEMGET:
 		return sys_semget (first, second, third);
 	case SEMCTL: {
--- diff/arch/mips/kernel/sysirix.c	2003-09-30 15:46:11.000000000 +0100
+++ source/arch/mips/kernel/sysirix.c	2004-02-23 13:56:38.000000000 +0000
@@ -29,6 +29,7 @@
 #include <linux/namei.h>
 #include <linux/socket.h>
 #include <linux/security.h>
+#include <linux/syscalls.h>
 
 #include <asm/ptrace.h>
 #include <asm/page.h>
@@ -235,13 +236,6 @@ asmlinkage int irix_prctl(struct pt_regs
 #undef DEBUG_PROCGRPS
 
 extern unsigned long irix_mapelf(int fd, struct elf_phdr *user_phdrp, int cnt);
-extern asmlinkage int sys_setpgid(pid_t pid, pid_t pgid);
-extern void sys_sync(void);
-extern asmlinkage int sys_getsid(pid_t pid);
-extern asmlinkage long sys_write (unsigned int fd, const char *buf, unsigned long count);
-extern asmlinkage long sys_lseek (unsigned int fd, off_t offset, unsigned int origin);
-extern asmlinkage int sys_getgroups(int gidsetsize, gid_t *grouplist);
-extern asmlinkage int sys_setgroups(int gidsetsize, gid_t *grouplist);
 extern int getrusage(struct task_struct *p, int who, struct rusage *ru);
 extern char *prom_getenv(char *name);
 extern long prom_setenv(char *name, char *value);
@@ -368,7 +362,7 @@ asmlinkage int irix_syssgi(struct pt_reg
 			retval = HZ;
 			goto out;
 		case 4:
-			retval = NGROUPS;
+			retval = NGROUPS_MAX;
 			goto out;
 		case 5:
 			retval = NR_OPEN;
@@ -694,9 +688,6 @@ asmlinkage int irix_pause(void)
 	return -EINTR;
 }
 
-extern asmlinkage long sys_mount(char * dev_name, char * dir_name, char * type,
-				unsigned long new_flags, void * data);
-
 /* XXX need more than this... */
 asmlinkage int irix_mount(char *dev_name, char *dir_name, unsigned long flags,
 			  char *type, void *data, int datalen)
@@ -792,9 +783,6 @@ out:
 	return error;
 }
 
-extern asmlinkage int sys_setpgid(pid_t pid, pid_t pgid);
-extern asmlinkage int sys_setsid(void);
-
 asmlinkage int irix_setpgrp(int flags)
 {
 	int error;
@@ -883,8 +871,6 @@ asmlinkage unsigned long irix_sethostid(
 	return -EINVAL;
 }
 
-extern asmlinkage int sys_socket(int family, int type, int protocol);
-
 asmlinkage int irix_socket(int family, int type, int protocol)
 {
 	switch(type) {
@@ -1206,8 +1192,8 @@ static int irix_xstat32_xlate(struct kst
 	ub.st_ino     = stat->ino;
 	ub.st_mode    = stat->mode;
 	ub.st_nlink   = stat->nlink;
-	SET_STAT_UID(ub, stat->uid);
-	SET_STAT_GID(ub, stat->gid);
+	SET_UID(ub.st_uid, stat->uid);
+	SET_GID(ub.st_gid, stat->gid);
 	ub.st_rdev    = sysv_encode_dev(stat->rdev);
 #if BITS_PER_LONG == 32
 	if (stat->size > MAX_NON_LFS)
@@ -1356,8 +1342,6 @@ asmlinkage int irix_fxstat(int version, 
 	return error;
 }
 
-extern asmlinkage int sys_mknod(const char * filename, int mode, unsigned dev);
-
 asmlinkage int irix_xmknod(int ver, char *filename, int mode, unsigned dev)
 {
 	int retval;
@@ -1501,9 +1485,6 @@ asmlinkage int irix_sigqueue(int pid, in
 	return -EINVAL;
 }
 
-extern asmlinkage int sys_truncate(const char * path, unsigned long length);
-extern asmlinkage int sys_ftruncate(unsigned int fd, unsigned long length);
-
 asmlinkage int irix_truncate64(char *name, int pad, int size1, int size2)
 {
 	int retval;
@@ -1532,10 +1513,6 @@ out:
 	return retval;
 }
 
-extern asmlinkage unsigned long
-sys_mmap(unsigned long addr, size_t len, int prot, int flags, int fd,
-         off_t offset);
-
 asmlinkage int irix_mmap64(struct pt_regs *regs)
 {
 	int len, prot, flags, fd, off1, off2, error, base = 0;
@@ -2106,9 +2083,6 @@ out:
 
 #undef DEBUG_FCNTL
 
-extern asmlinkage long sys_fcntl(unsigned int fd, unsigned int cmd,
-				 unsigned long arg);
-
 #define IRIX_F_ALLOCSP 10
 
 asmlinkage int irix_fcntl(int fd, int cmd, int arg)
--- diff/arch/mips/kernel/time.c	2003-10-09 09:47:33.000000000 +0100
+++ source/arch/mips/kernel/time.c	2004-02-23 13:56:38.000000000 +0000
@@ -18,6 +18,7 @@
 #include <linux/sched.h>
 #include <linux/param.h>
 #include <linux/time.h>
+#include <linux/timex.h>
 #include <linux/smp.h>
 #include <linux/kernel_stat.h>
 #include <linux/spinlock.h>
@@ -26,14 +27,20 @@
 
 #include <asm/bootinfo.h>
 #include <asm/cpu.h>
+#include <asm/cpu-features.h>
 #include <asm/div64.h>
 #include <asm/hardirq.h>
 #include <asm/sections.h>
 #include <asm/time.h>
 
-/* This is for machines which generate the exact clock. */
-#define USECS_PER_JIFFY (1000000/HZ)
-#define USECS_PER_JIFFY_FRAC ((u32)((1000000ULL << 32) / HZ))
+/*
+ * The integer part of the number of usecs per jiffy is taken from tick,
+ * but the fractional part is not recorded, so we calculate it using the
+ * initial value of HZ.  This aids systems where tick isn't really an
+ * integer (e.g. for HZ = 128).
+ */
+#define USECS_PER_JIFFY		TICK_SIZE
+#define USECS_PER_JIFFY_FRAC	((unsigned long)(u32)((1000000ULL << 32) / HZ))
 
 #define TICK_SIZE	(tick_nsec / 1000)
 
@@ -53,6 +60,7 @@ spinlock_t rtc_lock = SPIN_LOCK_UNLOCKED
  */
 int emulate_local_timer_interrupt;
 
+
 /*
  * By default we provide the null RTC ops
  */
@@ -71,6 +79,85 @@ int (*rtc_set_time)(unsigned long) = nul
 int (*rtc_set_mmss)(unsigned long);
 
 
+/* usecs per counter cycle, shifted to left by 32 bits */
+static unsigned int sll32_usecs_per_cycle;
+
+/* how many counter cycles in a jiffy */
+static unsigned long cycles_per_jiffy;
+
+/* Cycle counter value at the previous timer interrupt.. */
+static unsigned int timerhi, timerlo;
+
+/* expirelo is the count value for next CPU timer interrupt */
+static unsigned int expirelo;
+
+
+/*
+ * Null timer ack for systems not needing one (e.g. i8254).
+ */
+static void null_timer_ack(void) { /* nothing */ }
+
+/*
+ * Null high precision timer functions for systems lacking one.
+ */
+static unsigned int null_hpt_read(void)
+{
+	return 0;
+}
+
+static void null_hpt_init(unsigned int count) { /* nothing */ }
+
+
+/*
+ * Timer ack for an R4k-compatible timer of a known frequency.
+ */
+static void c0_timer_ack(void)
+{
+	unsigned int count;
+
+	/* Ack this timer interrupt and set the next one.  */
+	expirelo += cycles_per_jiffy;
+	write_c0_compare(expirelo);
+
+	/* Check to see if we have missed any timer interrupts.  */
+	count = read_c0_count();
+	if ((count - expirelo) < 0x7fffffff) {
+		/* missed_timer_count++; */
+		expirelo = count + cycles_per_jiffy;
+		write_c0_compare(expirelo);
+	}
+}
+
+/*
+ * High precision timer functions for a R4k-compatible timer.
+ */
+static unsigned int c0_hpt_read(void)
+{
+	return read_c0_count();
+}
+
+/* For use solely as a high precision timer.  */
+static void c0_hpt_init(unsigned int count)
+{
+	write_c0_count(read_c0_count() - count);
+}
+
+/* For use both as a high precision timer and an interrupt source.  */
+static void c0_hpt_timer_init(unsigned int count)
+{
+	count = read_c0_count() - count;
+	expirelo = (count / cycles_per_jiffy + 1) * cycles_per_jiffy;
+	write_c0_count(expirelo - cycles_per_jiffy);
+	write_c0_compare(expirelo);
+	write_c0_count(count);
+}
+
+int (*mips_timer_state)(void);
+void (*mips_timer_ack)(void);
+unsigned int (*mips_hpt_read)(void);
+void (*mips_hpt_init)(unsigned int);
+
+
 /*
  * This version of gettimeofday has microsecond resolution and better than
  * microsecond precision on fast machines with cycle counter.
@@ -78,18 +165,33 @@ int (*rtc_set_mmss)(unsigned long);
 void do_gettimeofday(struct timeval *tv)
 {
 	unsigned long seq;
+	unsigned long lost;
 	unsigned long usec, sec;
+	unsigned long max_ntp_tick = tick_usec - tickadj;
 
 	do {
 		seq = read_seqbegin(&xtime_lock);
+
 		usec = do_gettimeoffset();
-		{
-			unsigned long lost = jiffies - wall_jiffies;
+
+		lost = jiffies - wall_jiffies;
+
+		/*
+		 * If time_adjust is negative then NTP is slowing the clock
+		 * so make sure not to go into next possible interval.
+		 * Better to lose some accuracy than have time go backwards..
+		 */
+		if (unlikely(time_adjust < 0)) {
+			usec = min(usec, max_ntp_tick);
+
 			if (lost)
-				usec += lost * (1000000 / HZ);
-		}
+				usec += lost * max_ntp_tick;
+		} else if (unlikely(lost))
+			usec += lost * tick_usec;
+
 		sec = xtime.tv_sec;
 		usec += (xtime.tv_nsec / 1000);
+
 	} while (read_seqretry(&xtime_lock, seq));
 
 	while (usec >= 1000000) {
@@ -112,14 +214,15 @@ int do_settimeofday(struct timespec *tv)
 		return -EINVAL;
 
 	write_seqlock_irq(&xtime_lock);
+
 	/*
-	 * This is revolting. We need to set "xtime" correctly. However, the
-	 * value in this location is the value at the most recent update of
-	 * wall time.  Discover what correction gettimeofday() would have
+	 * This is revolting.  We need to set "xtime" correctly.  However,
+	 * the value in this location is the value at the most recent update
+	 * of wall time.  Discover what correction gettimeofday() would have
 	 * made, and then undo it!
 	 */
 	nsec -= do_gettimeoffset() * NSEC_PER_USEC;
-	nsec -= (jiffies - wall_jiffies) * TICK_NSEC;
+	nsec -= (jiffies - wall_jiffies) * tick_nsec;
 
 	wtm_sec  = wall_to_monotonic.tv_sec + (xtime.tv_sec - sec);
 	wtm_nsec = wall_to_monotonic.tv_nsec + (xtime.tv_nsec - nsec);
@@ -127,12 +230,13 @@ int do_settimeofday(struct timespec *tv)
 	set_normalized_timespec(&xtime, sec, nsec);
 	set_normalized_timespec(&wall_to_monotonic, wtm_sec, wtm_nsec);
 
-	time_adjust = 0;		/* stop active adjtime() */
+	time_adjust = 0;			/* stop active adjtime() */
 	time_status |= STA_UNSYNC;
 	time_maxerror = NTP_PHASE_LIMIT;
 	time_esterror = NTP_PHASE_LIMIT;
-	write_sequnlock_irq(&xtime_lock);
 
+	write_sequnlock_irq(&xtime_lock);
+	clock_was_set();
 	return 0;
 }
 
@@ -145,42 +249,28 @@ EXPORT_SYMBOL(do_settimeofday);
  * If the exact CPU counter frequency is known, use fixed_rate_gettimeoffset.
  * Otherwise use calibrate_gettimeoffset()
  *
- * If the CPU does not have counter register all, you can either supply
- * your own gettimeoffset() routine, or use null_gettimeoffset() routines,
- * which gives the same resolution as HZ.
+ * If the CPU does not have the counter register, you can either supply
+ * your own gettimeoffset() routine, or use null_gettimeoffset(), which
+ * gives the same resolution as HZ.
  */
 
+static unsigned long null_gettimeoffset(void)
+{
+	return 0;
+}
 
-/* usecs per counter cycle, shifted to left by 32 bits */
-static unsigned int sll32_usecs_per_cycle;
-
-/* how many counter cycles in a jiffy */
-static unsigned long cycles_per_jiffy;
-
-/* Cycle counter value at the previous timer interrupt.. */
-static unsigned int timerhi, timerlo;
-
-/* expirelo is the count value for next CPU timer interrupt */
-static unsigned int expirelo;
-
-/* last time when xtime and rtc are sync'ed up */
-static long last_rtc_update;
 
-/* the function pointer to one of the gettimeoffset funcs*/
+/* The function pointer to one of the gettimeoffset funcs.  */
 unsigned long (*do_gettimeoffset)(void) = null_gettimeoffset;
 
-unsigned long null_gettimeoffset(void)
-{
-	return 0;
-}
 
-unsigned long fixed_rate_gettimeoffset(void)
+static unsigned long fixed_rate_gettimeoffset(void)
 {
 	u32 count;
 	unsigned long res;
 
 	/* Get last timer tick in absolute kernel time */
-	count = read_c0_count();
+	count = mips_hpt_read();
 
 	/* .. relative to previous jiffy (32 bits is enough) */
 	count -= timerlo;
@@ -200,6 +290,7 @@ unsigned long fixed_rate_gettimeoffset(v
 	return res;
 }
 
+
 /*
  * Cached "1/(clocks per usec) * 2^32" value.
  * It has to be recalculated once each jiffy.
@@ -209,11 +300,10 @@ static unsigned long cached_quotient;
 /* Last jiffy when calibrate_divXX_gettimeoffset() was called. */
 static unsigned long last_jiffies;
 
-
 /*
- * This is copied from dec/time.c:do_ioasic_gettimeoffset() by Maciej.
+ * This is moved from dec/time.c:do_ioasic_gettimeoffset() by Maciej.
  */
-unsigned long calibrate_div32_gettimeoffset(void)
+static unsigned long calibrate_div32_gettimeoffset(void)
 {
 	u32 count;
 	unsigned long res, tmp;
@@ -235,7 +325,7 @@ unsigned long calibrate_div32_gettimeoff
 	}
 
 	/* Get last timer tick in absolute kernel time */
-	count = read_c0_count();
+	count = mips_hpt_read();
 
 	/* .. relative to previous jiffy (32 bits is enough) */
 	count -= timerlo;
@@ -255,7 +345,7 @@ unsigned long calibrate_div32_gettimeoff
 	return res;
 }
 
-unsigned long calibrate_div64_gettimeoffset(void)
+static unsigned long calibrate_div64_gettimeoffset(void)
 {
 	u32 count;
 	unsigned long res, tmp;
@@ -265,30 +355,33 @@ unsigned long calibrate_div64_gettimeoff
 
 	quotient = cached_quotient;
 
-	if (tmp && last_jiffies != tmp) {
+	if (last_jiffies != tmp) {
 		last_jiffies = tmp;
-		__asm__(".set	push\n\t"
-			".set	noreorder\n\t"
-			".set	noat\n\t"
-			".set	mips3\n\t"
-			"lwu	%0,%2\n\t"
-			"dsll32	$1,%1,0\n\t"
-			"or	$1,$1,%0\n\t"
-			"ddivu	$0,$1,%3\n\t"
-			"mflo	$1\n\t"
-			"dsll32	%0,%4,0\n\t"
-			"nop\n\t"
-			"ddivu	$0,%0,$1\n\t"
-			"mflo	%0\n\t"
-			".set	pop"
-			: "=&r" (quotient)
-			: "r" (timerhi), "m" (timerlo),
-			  "r" (tmp), "r" (USECS_PER_JIFFY));
-		cached_quotient = quotient;
+		if (last_jiffies) {
+			unsigned long r0;
+			__asm__(".set	push\n\t"
+				".set	mips3\n\t"
+				"lwu	%0,%3\n\t"
+				"dsll32	%1,%2,0\n\t"
+				"or	%1,%1,%0\n\t"
+				"ddivu	$0,%1,%4\n\t"
+				"mflo	%1\n\t"
+				"dsll32	%0,%5,0\n\t"
+				"or	%0,%0,%6\n\t"
+				"ddivu	$0,%0,%1\n\t"
+				"mflo	%0\n\t"
+				".set	pop"
+				: "=&r" (quotient), "=&r" (r0)
+				: "r" (timerhi), "m" (timerlo),
+				  "r" (tmp), "r" (USECS_PER_JIFFY),
+				  "r" (USECS_PER_JIFFY_FRAC)
+				: "hi", "lo", "accum");
+			cached_quotient = quotient;
+		}
 	}
 
 	/* Get last timer tick in absolute kernel time */
-	count = read_c0_count();
+	count = mips_hpt_read();
 
 	/* .. relative to previous jiffy (32 bits is enough) */
 	count -= timerlo;
@@ -309,6 +402,9 @@ unsigned long calibrate_div64_gettimeoff
 }
 
 
+/* last time when xtime and rtc are sync'ed up */
+static long last_rtc_update;
+
 /*
  * local_timer_interrupt() does profiling and process accounting
  * on a per-CPU basis.
@@ -345,30 +441,20 @@ void local_timer_interrupt(int irq, void
 }
 
 /*
- * high-level timer interrupt service routines.  This function
+ * High-level timer interrupt service routines.  This function
  * is set as irqaction->handler and is invoked through do_IRQ.
  */
 irqreturn_t timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
-	if (cpu_has_counter) {
-		unsigned int count;
-
-		/* ack timer interrupt, and try to set next interrupt */
-		expirelo += cycles_per_jiffy;
-		write_c0_compare(expirelo);
-		count = read_c0_count();
+	unsigned long j;
+	unsigned int count;
 
-		/* check to see if we have missed any timer interrupts */
-		if ((count - expirelo) < 0x7fffffff) {
-			/* missed_timer_count++; */
-			expirelo = count + cycles_per_jiffy;
-			write_c0_compare(expirelo);
-		}
+	count = mips_hpt_read();
+	mips_timer_ack();
 
-		/* Update timerhi/timerlo for intra-jiffy calibration. */
-		timerhi += count < timerlo;	/* Wrap around */
-		timerlo = count;
-	}
+	/* Update timerhi/timerlo for intra-jiffy calibration. */
+	timerhi += count < timerlo;			/* Wrap around */
+	timerlo = count;
 
 	/*
 	 * call the generic timer interrupt handling
@@ -395,12 +481,44 @@ irqreturn_t timer_interrupt(int irq, voi
 	write_sequnlock(&xtime_lock);
 
 	/*
-	 * If jiffies has overflowed in this timer_interrupt we must
+	 * If jiffies has overflown in this timer_interrupt, we must
 	 * update the timer[hi]/[lo] to make fast gettimeoffset funcs
 	 * quotient calc still valid. -arca
+	 *
+	 * The first timer interrupt comes late as interrupts are
+	 * enabled long after timers are initialized.  Therefore the
+	 * high precision timer is fast, leading to wrong gettimeoffset()
+	 * calculations.  We deal with it by setting it based on the
+	 * number of its ticks between the second and the third interrupt.
+	 * That is still somewhat imprecise, but it's a good estimate.
+	 * --macro
 	 */
-	if (!jiffies) {
-		timerhi = timerlo = 0;
+	j = jiffies;
+	if (j < 4) {
+		static unsigned int prev_count;
+		static int hpt_initialized;
+
+		switch (j) {
+		case 0:
+			timerhi = timerlo = 0;
+			mips_hpt_init(count);
+			break;
+		case 2:
+			prev_count = count;
+			break;
+		case 3:
+			if (!hpt_initialized) {
+				unsigned int c3 = 3 * (count - prev_count);
+
+				timerhi = 0;
+				timerlo = c3;
+				mips_hpt_init(count - c3);
+				hpt_initialized = 1;
+			}
+			break;
+		default:
+			break;
+		}
 	}
 
 #if !defined(CONFIG_SMP)
@@ -445,7 +563,8 @@ asmlinkage void ll_timer_interrupt(int i
 asmlinkage void ll_local_timer_interrupt(int irq, struct pt_regs *regs)
 {
 	irq_enter();
-	kstat_this_cpu.irqs[irq]++;
+	if (smp_processor_id() != 0)
+		kstat_this_cpu.irqs[irq]++;
 
 	/* we keep interrupt disabled all the time */
 	local_timer_interrupt(irq, NULL, regs);
@@ -458,7 +577,7 @@ asmlinkage void ll_local_timer_interrupt
  *
  * 1) board_time_init() -
  * 	a) (optional) set up RTC routines,
- *      b) (optional) calibrate and set the mips_counter_frequency
+ *      b) (optional) calibrate and set the mips_hpt_frequency
  *	    (only needed if you intended to use fixed_rate_gettimeoffset
  *	     or use cpu counter as timer interrupt source)
  * 2) setup xtime based on rtc_get_time().
@@ -473,7 +592,7 @@ asmlinkage void ll_local_timer_interrupt
 void (*board_time_init)(void);
 void (*board_timer_setup)(struct irqaction *irq);
 
-unsigned int mips_counter_frequency;
+unsigned int mips_hpt_frequency;
 
 static struct irqaction timer_irqaction = {
 	.handler = timer_interrupt,
@@ -481,6 +600,49 @@ static struct irqaction timer_irqaction 
 	.name = "timer",
 };
 
+static unsigned int __init calibrate_hpt(void)
+{
+	u64 frequency;
+	u32 hpt_start, hpt_end, hpt_count, hz;
+
+	const int loops = HZ / 10;
+	int log_2_loops = 0;
+	int i;
+
+	/*
+	 * We want to calibrate for 0.1s, but to avoid a 64-bit
+	 * division we round the number of loops up to the nearest
+	 * power of 2.
+	 */
+	while (loops > 1 << log_2_loops)
+		log_2_loops++;
+	i = 1 << log_2_loops;
+
+	/*
+	 * Wait for a rising edge of the timer interrupt.
+	 */
+	while (mips_timer_state());
+	while (!mips_timer_state());
+
+	/*
+	 * Now see how many high precision timer ticks happen
+	 * during the calculated number of periods between timer
+	 * interrupts.
+	 */
+	hpt_start = mips_hpt_read();
+	do {
+		while (mips_timer_state());
+		while (!mips_timer_state());
+	} while (--i);
+	hpt_end = mips_hpt_read();
+
+	hpt_count = hpt_end - hpt_start;
+	hz = HZ;
+	frequency = (u64)hpt_count * (u64)hz;
+
+	return frequency >> log_2_loops;
+}
+
 void __init time_init(void)
 {
 	if (board_time_init)
@@ -495,50 +657,79 @@ void __init time_init(void)
 	set_normalized_timespec(&wall_to_monotonic,
 	                        -xtime.tv_sec, -xtime.tv_nsec);
 
-	/* choose appropriate gettimeoffset routine */
-	if (!cpu_has_counter) {
-		/* no cpu counter - sorry */
-		do_gettimeoffset = null_gettimeoffset;
-	} else if (mips_counter_frequency != 0) {
-		/* we have cpu counter and know counter frequency! */
-		do_gettimeoffset = fixed_rate_gettimeoffset;
-	} else if ((current_cpu_data.isa_level == MIPS_CPU_ISA_M32) ||
-		   (current_cpu_data.isa_level == MIPS_CPU_ISA_I) ||
-		   (current_cpu_data.isa_level == MIPS_CPU_ISA_II) ) {
-		/* we need to calibrate the counter but we don't have
-		 * 64-bit division. */
-		do_gettimeoffset = calibrate_div32_gettimeoffset;
+	/* Choose appropriate high precision timer routines.  */
+	if (!cpu_has_counter && !mips_hpt_read) {
+		/* No high precision timer -- sorry.  */
+		mips_hpt_read = null_hpt_read;
+		mips_hpt_init = null_hpt_init;
+	} else if (!mips_hpt_frequency && !mips_timer_state) {
+		/* A high precision timer of unknown frequency.  */
+		if (!mips_hpt_read) {
+			/* No external high precision timer -- use R4k.  */
+			mips_hpt_read = c0_hpt_read;
+			mips_hpt_init = c0_hpt_init;
+		}
+
+		if ((current_cpu_data.isa_level == MIPS_CPU_ISA_M32) ||
+			 (current_cpu_data.isa_level == MIPS_CPU_ISA_I) ||
+			 (current_cpu_data.isa_level == MIPS_CPU_ISA_II))
+			/*
+			 * We need to calibrate the counter but we don't have
+			 * 64-bit division.
+			 */
+			do_gettimeoffset = calibrate_div32_gettimeoffset;
+		else
+			/*
+			 * We need to calibrate the counter but we *do* have
+			 * 64-bit division.
+			 */
+			do_gettimeoffset = calibrate_div64_gettimeoffset;
 	} else {
-		/* we need to calibrate the counter but we *do* have
-		 * 64-bit division. */
-		do_gettimeoffset = calibrate_div64_gettimeoffset;
-	}
+		/* We know counter frequency.  Or we can get it.  */
+		if (!mips_hpt_read) {
+			/* No external high precision timer -- use R4k.  */
+			mips_hpt_read = c0_hpt_read;
+
+			if (mips_timer_state)
+				mips_hpt_init = c0_hpt_init;
+			else {
+				/* No external timer interrupt -- use R4k.  */
+				mips_hpt_init = c0_hpt_timer_init;
+				mips_timer_ack = c0_timer_ack;
+			}
+		}
+		if (!mips_hpt_frequency)
+			mips_hpt_frequency = calibrate_hpt();
 
-	/* caclulate cache parameters */
-	if (mips_counter_frequency) {
-		cycles_per_jiffy = mips_counter_frequency / HZ;
-
-		/* sll32_usecs_per_cycle = 10^6 * 2^32 / mips_counter_freq */
-		/* any better way to do this? */
-		sll32_usecs_per_cycle = mips_counter_frequency / 100000;
-		sll32_usecs_per_cycle = 0xffffffff / sll32_usecs_per_cycle;
-		sll32_usecs_per_cycle *= 10;
+		do_gettimeoffset = fixed_rate_gettimeoffset;
 
-		/*
-		 * For those using cpu counter as timer,  this sets up the
-		 * first interrupt
-		 */
-		write_c0_compare(cycles_per_jiffy);
-		write_c0_count(0);
-		expirelo = cycles_per_jiffy;
+		/* Calculate cache parameters.  */
+		cycles_per_jiffy = (mips_hpt_frequency + HZ / 2) / HZ;
+
+		/* sll32_usecs_per_cycle = 10^6 * 2^32 / mips_counter_freq  */
+		do_div64_32(sll32_usecs_per_cycle,
+			    1000000, mips_hpt_frequency / 2,
+			    mips_hpt_frequency);
+
+		/* Report the high precision timer rate for a reference.  */
+		printk("Using %u.%03u MHz high precision timer.\n",
+		       ((mips_hpt_frequency + 500) / 1000) / 1000,
+		       ((mips_hpt_frequency + 500) / 1000) % 1000);
 	}
 
+	if (!mips_timer_ack)
+		/* No timer interrupt ack (e.g. i8254).  */
+		mips_timer_ack = null_timer_ack;
+
+	/* This sets up the high precision timer for the first interrupt.  */
+	mips_hpt_init(mips_hpt_read());
+
 	/*
 	 * Call board specific timer interrupt setup.
 	 *
 	 * this pointer must be setup in machine setup routine.
 	 *
-	 * Even if the machine choose to use low-level timer interrupt,
+	 * Even if a machine chooses to use a low-level timer interrupt,
 	 * it still needs to setup the timer_irqaction.
 	 * In that case, it might be better to set timer_irqaction.handler
 	 * to be NULL function so that we are sure the high-level code
--- diff/arch/mips/kernel/traps.c	2003-10-09 09:47:33.000000000 +0100
+++ source/arch/mips/kernel/traps.c	2004-02-23 13:56:38.000000000 +0000
@@ -83,12 +83,12 @@ void show_stack(struct task_struct *task
 
 	sp = sp ? sp : (unsigned long *) &sp;
 
-	printk("Stack: ");
-	i = 1;
+	printk("Stack :");
+	i = 0;
 	while ((unsigned long) sp & (PAGE_SIZE - 1)) {
-		if (i && ((i % (64 / sizeof(unsigned long))) == 0))
+		if (i && ((i % (64 / field)) == 0))
 			printk("\n       ");
-		if (i > 40) {
+		if (i > 39) {
 			printk(" ...");
 			break;
 		}
@@ -116,7 +116,7 @@ void show_trace(struct task_struct *task
 #ifdef CONFIG_KALLSYMS
 	printk("\n");
 #endif
-	while (((long) stack & (THREAD_SIZE-1)) != 0) {
+	while (!kstack_end(stack)) {
 		addr = *stack++;
 		if (kernel_text_address(addr)) {
 			printk(" [<%0*lx>] ", field, addr);
@@ -162,6 +162,7 @@ void show_code(unsigned int *pc)
 void show_regs(struct pt_regs *regs)
 {
 	const int field = 2 * sizeof(unsigned long);
+	unsigned int cause = regs->cp0_cause;
 	int i;
 
 	printk("Cpu %d\n", smp_processor_id());
@@ -171,7 +172,7 @@ void show_regs(struct pt_regs *regs)
 	 */
 	for (i = 0; i < 32; ) {
 		if ((i % 4) == 0)
-			printk("$%2d :", i);
+			printk("$%2d   :", i);
 		if (i == 0)
 			printk(" %0*lx", field, 0UL);
 		else if (i == 26 || i == 27)
@@ -184,15 +185,19 @@ void show_regs(struct pt_regs *regs)
 			printk("\n");
 	}
 
-	printk("Hi      : %0*lx\n", field, regs->hi);
-	printk("Lo      : %0*lx\n", field, regs->lo);
+	printk("Hi    : %0*lx\n", field, regs->hi);
+	printk("Lo    : %0*lx\n", field, regs->lo);
 
 	/*
 	 * Saved cp0 registers
 	 */
-	printk("epc   : %0*lx    %s\n", field, regs->cp0_epc, print_tainted());
-	printk("Status: %0*lx\n", field, regs->cp0_status);
-	printk("Cause : %0*lx\n", field, regs->cp0_cause);
+	printk("epc   : %0*lx ", field, regs->cp0_epc);
+	print_symbol("%s ", regs->cp0_epc);
+	printk("    %s\n", print_tainted());
+	printk("ra    : %0*lx ", field, regs->regs[31]);
+	print_symbol("%s\n", regs->regs[31]);
+
+	printk("Status: %08x    ", (uint32_t) regs->cp0_status);
 
 	if (regs->cp0_status & ST0_KX)
 		printk("KX ");
@@ -220,15 +225,22 @@ void show_regs(struct pt_regs *regs)
 		printk("EXL ");
 	if (regs->cp0_status & ST0_IE)
 		printk("IE ");
+	printk("\n");
+
+	printk("Cause : %08x\n", cause);
+
+	cause = (cause & CAUSEF_EXCCODE) >> CAUSEB_EXCCODE;
+	if (1 <= cause && cause <= 5)
+		printk("BadVA : %0*lx\n", field, regs->cp0_badvaddr);
+
+	printk("PrId  : %08x\n", read_c0_prid());
 }
 
 void show_registers(struct pt_regs *regs)
 {
-	const int field = 2 * sizeof(unsigned long);
-
 	show_regs(regs);
-	printk("Process %s (pid: %d, stackpage=%0*lx)\n",
-		current->comm, current->pid, field, (unsigned long) current);
+	printk("Process %s (pid: %d, threadinfo=%p, task=%p)\n",
+	        current->comm, current->pid, current_thread_info(), current);
 	show_stack(current, (long *) regs->regs[29]);
 	show_trace(current, (long *) regs->regs[29]);
 	show_code((unsigned int *) regs->cp0_epc);
@@ -237,8 +249,8 @@ void show_registers(struct pt_regs *regs
 
 static spinlock_t die_lock = SPIN_LOCK_UNLOCKED;
 
-void __die(const char * str, struct pt_regs * regs, const char * file,
-	   const char * func, unsigned long line)
+NORET_TYPE void __die(const char * str, struct pt_regs * regs,
+	const char * file, const char * func, unsigned long line)
 {
 	static int die_counter;
 
@@ -271,6 +283,56 @@ void __declare_dbe_table(void)
 	);
 }
 
+#ifdef CONFIG_MDULES
+
+/* Given an address, look for it in the module exception tables. */
+const struct exception_table_entry *search_module_dbetables(unsigned long addr)
+{
+	unsigned long flags;
+	const struct exception_table_entry *e = NULL;
+	struct module *mod;
+
+	spin_lock_irqsave(&modlist_lock, flags);
+	list_for_each_entry(mod, &modules, list) {
+		if (mod->arch.num_dbeentries == 0)
+			continue;
+				
+		e = search_extable(mod->arch.dbe_table_start,
+				   mod->arch.dbe_table_end +
+		                   mod->arch.num_dbeentries - 1,
+				   addr);
+		if (e)
+			break;
+	}
+	spin_unlock_irqrestore(&modlist_lock, flags);
+
+	/* Now, if we found one, we are running inside it now, hence
+           we cannot unload the module, hence no refcnt needed. */
+	return e;
+}
+
+#else
+
+/* Given an address, look for it in the exception tables. */
+static inline const struct exception_table_entry *
+search_module_dbetables(unsigned long addr)
+{
+	return NULL;
+}
+
+#endif
+
+/* Given an address, look for it in the exception tables. */
+const struct exception_table_entry *search_dbe_tables(unsigned long addr)
+{
+	const struct exception_table_entry *e;
+
+	e = search_extable(__start___dbe_table, __stop___dbe_table - 1, addr);
+	if (!e)
+		e = search_module_dbetables(addr);
+	return e;
+}
+
 asmlinkage void do_be(struct pt_regs *regs)
 {
 	const int field = 2 * sizeof(unsigned long);
@@ -280,7 +342,7 @@ asmlinkage void do_be(struct pt_regs *re
 
 	/* XXX For now.  Fixme, this searches the wrong table ...  */
 	if (data && !user_mode(regs))
-		fixup = search_exception_tables(regs->cp0_epc);
+		fixup = search_dbe_tables(exception_epc(regs));
 
 	if (fixup)
 		action = MIPS_BE_FIXUP;
@@ -725,10 +787,10 @@ asmlinkage void cache_parity_error(void)
 
 #if defined(CONFIG_CPU_MIPS32) || defined (CONFIG_CPU_MIPS64)
 	if (reg_val & (1<<22))
-		printk("DErrAddr0: 0x%08x\n", read_c0_derraddr0());
+		printk("DErrAddr0: 0x%0*lx\n", field, read_c0_derraddr0());
 
 	if (reg_val & (1<<23))
-		printk("DErrAddr1: 0x%08x\n", read_c0_derraddr1());
+		printk("DErrAddr1: 0x%0*lx\n", field, read_c0_derraddr1());
 #endif
 
 	panic("Can't handle the cache error!");
@@ -794,9 +856,9 @@ void *set_except_vector(int n, void *add
 
 	exception_handlers[n] = handler;
 	if (n == 0 && cpu_has_divec) {
-		*(volatile u32 *)(KSEG0+0x200) = 0x08000000 |
+		*(volatile u32 *)(CAC_BASE + 0x200) = 0x08000000 |
 		                                 (0x03ffffff & (handler >> 2));
-		flush_icache_range(KSEG0+0x200, KSEG0 + 0x204);
+		flush_icache_range(CAC_BASE + 0x200, CAC_BASE + 0x204);
 	}
 	return (void *)old_handler;
 }
@@ -850,6 +912,9 @@ static inline void signal32_init(void)
 }
 #endif
 
+extern void cpu_cache_init(void);
+extern void tlb_init(void);
+
 void __init per_cpu_trap_init(void)
 {
 	unsigned int cpu = smp_processor_id();
@@ -860,6 +925,9 @@ void __init per_cpu_trap_init(void)
 	set_c0_status(ST0_CU0|ST0_FR|ST0_KX|ST0_SX|ST0_UX);
 #endif
 
+	if (current_cpu_data.isa_level == MIPS_CPU_ISA_IV)
+		set_c0_status(ST0_XX);
+
 	/*
 	 * Some MIPS CPUs have a dedicated interrupt vector which reduces the
 	 * interrupt processing overhead.  Use it where available.
@@ -868,19 +936,19 @@ void __init per_cpu_trap_init(void)
 		set_c0_cause(CAUSEF_IV);
 
 	cpu_data[cpu].asid_cache = ASID_FIRST_VERSION;
-#ifdef CONFIG_MIPS32
-	write_c0_context(cpu << 23);
-#endif
-#ifdef CONFIG_MIPS64
-	write_c0_context(((long)(&pgd_current[cpu])) << 23);
-#endif
-	write_c0_wired(0);
+	TLBMISS_HANDLER_SETUP();
+
+	atomic_inc(&init_mm.mm_count);
+	current->active_mm = &init_mm;
+	BUG_ON(current->mm);
+	enter_lazy_tlb(&init_mm, current);
+
+	cpu_cache_init();
+	tlb_init();
 }
 
 void __init trap_init(void)
 {
-	extern char except_vec0_generic;
-	extern char except_vec1_generic;
 	extern char except_vec3_generic, except_vec3_r4000;
 	extern char except_vec_ejtag_debug;
 	extern char except_vec4;
@@ -893,9 +961,7 @@ void __init trap_init(void)
 	 * This will be overriden later as suitable for a particular
 	 * configuration.
 	 */
-	memcpy((void *) KSEG0         , &except_vec0_generic, 0x80);
-	memcpy((void *)(KSEG0 + 0x080), &except_vec1_generic, 0x80);
-	memcpy((void *)(KSEG0 + 0x180), &except_vec3_generic, 0x80);
+	memcpy((void *)(CAC_BASE + 0x180), &except_vec3_generic, 0x80);
 
 	/*
 	 * Setup default vectors
@@ -908,7 +974,7 @@ void __init trap_init(void)
 	 * destination.
 	 */
 	if (cpu_has_ejtag)
-		memcpy((void *)(KSEG0 + 0x300), &except_vec_ejtag_debug, 0x80);
+		memcpy((void *)(CAC_BASE + 0x300), &except_vec_ejtag_debug, 0x80);
 
 	/*
 	 * Only some CPUs have the watch exceptions or a dedicated
@@ -922,7 +988,7 @@ void __init trap_init(void)
 	 * interrupt processing overhead.  Use it where available.
 	 */
 	if (cpu_has_divec)
-		memcpy((void *)(KSEG0 + 0x200), &except_vec4, 0x8);
+		memcpy((void *)(CAC_BASE + 0x200), &except_vec4, 0x8);
 
 	/*
 	 * Some CPUs can enable/disable for cache parity detection, but does
@@ -969,11 +1035,11 @@ void __init trap_init(void)
 		set_except_vector(24, handle_mcheck);
 
 	if (cpu_has_vce)
-		memcpy((void *)(KSEG0 + 0x180), &except_vec3_r4000, 0x80);
+		memcpy((void *)(CAC_BASE + 0x180), &except_vec3_r4000, 0x80);
 	else if (cpu_has_4kex)
-		memcpy((void *)(KSEG0 + 0x180), &except_vec3_generic, 0x80);
+		memcpy((void *)(CAC_BASE + 0x180), &except_vec3_generic, 0x80);
 	else
-		memcpy((void *)(KSEG0 + 0x080), &except_vec3_generic, 0x80);
+		memcpy((void *)(CAC_BASE + 0x080), &except_vec3_generic, 0x80);
 
 	if (current_cpu_data.cputype == CPU_R6000 ||
 	    current_cpu_data.cputype == CPU_R6000A) {
@@ -994,11 +1060,5 @@ void __init trap_init(void)
 	signal32_init();
 #endif
 
-	flush_icache_range(KSEG0, KSEG0 + 0x400);
-
-	if (current_cpu_data.isa_level == MIPS_CPU_ISA_IV)
-		set_c0_status(ST0_XX);
-
-	atomic_inc(&init_mm.mm_count);	/* XXX UP?  */
-	current->active_mm = &init_mm;
+	flush_icache_range(CAC_BASE, CAC_BASE + 0x400);
 }
--- diff/arch/mips/kernel/unaligned.c	2003-07-08 09:55:17.000000000 +0100
+++ source/arch/mips/kernel/unaligned.c	2004-02-23 13:56:38.000000000 +0000
@@ -40,7 +40,7 @@
  * Below a little program to play around with this feature.
  *
  * #include <stdio.h>
- * #include <asm/sysmips.h>
+ * #include <sys/sysmips.h>
  *
  * struct foo {
  *         unsigned char bar[8];
@@ -99,7 +99,6 @@ static inline int emulate_load_store_ins
 {
 	union mips_instruction insn;
 	unsigned long value;
-	const struct exception_table_entry *fixup;
 	unsigned int res;
 
 	regs->regs[0] = 0;
@@ -470,14 +469,8 @@ static inline int emulate_load_store_ins
 
 fault:
 	/* Did we have an exception handler installed? */
-	fixup = search_exception_tables(exception_epc(regs));
-	if (fixup) {
-		unsigned long new_epc = fixup->nextinsn;
-		printk(KERN_DEBUG "%s: Forwarding exception at [<%lx>] (%lx)\n",
-		       current->comm, regs->cp0_epc, new_epc);
-		regs->cp0_epc = new_epc;
+	if (fixup_exception(regs))
 		return 1;
-	}
 
 	die_if_kernel ("Unhandled kernel unaligned access", regs);
 	send_sig(SIGSEGV, current, 1);
--- diff/arch/mips/kernel/vmlinux.lds.S	2003-08-26 10:00:52.000000000 +0100
+++ source/arch/mips/kernel/vmlinux.lds.S	2004-02-23 13:56:38.000000000 +0000
@@ -1,3 +1,4 @@
+#include <linux/config.h>
 #include <asm-generic/vmlinux.lds.h>
 
 #undef mips		/* CPP really sucks for this job  */
@@ -44,10 +45,11 @@ SECTIONS
 
   RODATA
 
-  . = ALIGN(64);
-
   /* writeable */
   .data : {			/* Data */
+    . = . + MAPPED_OFFSET;	/* for CONFIG_MAPPED_KERNEL */
+    *(.data.init_task)
+
     *(.data)
 
    /* Align the initial ramdisk image (INITRD) on page boundaries. */
@@ -73,23 +75,11 @@ SECTIONS
   . = ALIGN(4096);
   __nosave_end = .;
 
-  . = ALIGN(4096);
-  .data.page_aligned : { *(.data.idt) }
-
   . = ALIGN(32);
   .data.cacheline_aligned : { *(.data.cacheline_aligned) }
 
   _edata =  .;			/* End of data section */
 
-#ifdef CONFIG_MIPS32
-  . = ALIGN(8192);		/* init_task */
-#endif
-#ifdef CONFIG_MIPS64
-  . = ALIGN(16384);		/* init_task */
-#endif
-  . = . + MAPPED_OFFSET;	/* for CONFIG_MAPPED_KERNEL */
-  .data.init_task : { *(.data.init_task) }
-
   /* will be freed after init */
   . = ALIGN(4096);		/* Init code and data */
   __init_begin = .;
@@ -108,6 +98,13 @@ SECTIONS
   __start___param = .;
   __param : { *(__param) }
   __stop___param = .;
+
+  .early_initcall.init : {
+  __earlyinitcall_start = .;
+	*(.initcall.early1.init)
+  }
+  __earlyinitcall_end = .;
+
   __initcall_start = .;
   .initcall.init : {
 	*(.initcall1.init)
@@ -119,6 +116,7 @@ SECTIONS
 	*(.initcall7.init)
   }
   __initcall_end = .;
+
   __con_initcall_start = .;
   .con_initcall.init : { *(.con_initcall.init) }
   __con_initcall_end = .;
--- diff/arch/mips/lasat/Makefile	2003-07-08 09:55:17.000000000 +0100
+++ source/arch/mips/lasat/Makefile	2004-02-23 13:56:38.000000000 +0000
@@ -7,6 +7,7 @@ obj-y	 			+= reset.o setup.o prom.o lasa
 
 obj-$(CONFIG_LASAT_SYSCTL)	+= sysctl.o
 obj-$(CONFIG_DS1603)		+= ds1603.o
+obj-$(CONFIG_PCI)		+= pci.o
 obj-$(CONFIG_PICVUE)		+= picvue.o
 obj-$(CONFIG_PICVUE_PROC)	+= picvue_proc.o
 
--- diff/arch/mips/lasat/interrupt.c	2003-08-20 14:16:25.000000000 +0100
+++ source/arch/mips/lasat/interrupt.c	2004-02-23 13:56:38.000000000 +0000
@@ -2,8 +2,6 @@
  * Carsten Langgaard, carstenl@mips.com
  * Copyright (C) 1999,2000 MIPS Technologies, Inc.  All rights reserved.
  *
- * ########################################################################
- *
  *  This program is free software; you can distribute it and/or modify it
  *  under the terms of the GNU General Public License (Version 2) as
  *  published by the Free Software Foundation.
@@ -17,13 +15,9 @@
  *  with this program; if not, write to the Free Software Foundation, Inc.,
  *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
  *
- * ########################################################################
- *
  * Routines for generic manipulation of the interrupts found on the 
  * Lasat boards.
- *
  */
-#include <linux/config.h>
 #include <linux/init.h>
 #include <linux/sched.h>
 #include <linux/slab.h>
@@ -41,16 +35,9 @@ static volatile int lasat_int_mask_shift
 
 extern asmlinkage void mipsIRQ(void);
 
-#if 0
-#define DEBUG_INT(x...) printk(x)
-#else
-#define DEBUG_INT(x...)
-#endif
-
 void disable_lasat_irq(unsigned int irq_nr)
 {
 	unsigned long flags;
-	DEBUG_INT("disable_lasat_irq: %d", irq_nr);
 
 	local_irq_save(flags);
 	*lasat_int_mask &= ~(1 << irq_nr) << lasat_int_mask_shift;
@@ -60,7 +47,6 @@ void disable_lasat_irq(unsigned int irq_
 void enable_lasat_irq(unsigned int irq_nr)
 {
 	unsigned long flags;
-	DEBUG_INT("enable_lasat_irq: %d", irq_nr);
 
 	local_irq_save(flags);
 	*lasat_int_mask |= (1 << irq_nr) << lasat_int_mask_shift;
@@ -70,6 +56,7 @@ void enable_lasat_irq(unsigned int irq_n
 static unsigned int startup_lasat_irq(unsigned int irq)
 {
 	enable_lasat_irq(irq);
+
 	return 0; /* never anything pending */
 }
 
@@ -111,7 +98,7 @@ static unsigned long (* get_int_status)(
 
 static unsigned long get_int_status_100(void)
 {
-	return (*lasat_int_status & *lasat_int_mask);
+	return *lasat_int_status & *lasat_int_mask;
 }
 
 static unsigned long get_int_status_200(void) 
@@ -132,28 +119,11 @@ void lasat_hw0_irqdispatch(struct pt_reg
 	int_status = get_int_status();
 
 	/* if int_status == 0, then the interrupt has already been cleared */
-	if (int_status == 0)
-		return;
+	if (int_status) {
+		irq = ls1bit32(int_status);
 
-	irq = ls1bit32(int_status);
-	action = irq_desc[irq].action;
-
-	DEBUG_INT("lasat_hw0_irqdispatch: irq=%d\n", irq);
-
-	/* if action == NULL, then we don't have a handler for the irq */
-	if (action == NULL) {
-		printk("No handler for hw0 irq: %i\n", irq);
-		atomic_inc(&irq_err_count);
-		disable_lasat_irq(irq);
-		return;
+		do_IRQ(irq, regs);
 	}
-
-	irq_enter();
-	kstat_this_cpu.irqs[irq]++;
-	action->handler(irq, action->dev_id, regs);
-	irq_exit();
-
-	return;		
 }
 
 void __init init_IRQ(void)
--- diff/arch/mips/lasat/lasatIRQ.S	2003-07-08 09:55:17.000000000 +0100
+++ source/arch/mips/lasat/lasatIRQ.S	2004-02-23 13:56:38.000000000 +0000
@@ -2,8 +2,6 @@
  * Carsten Langgaard, carstenl@mips.com
  * Copyright (C) 1999, 2000 MIPS Technologies, Inc.  All rights reserved.
  *
- * ########################################################################
- *
  *  This program is free software; you can distribute it and/or modify it
  *  under the terms of the GNU General Public License (Version 2) as
  *  published by the Free Software Foundation.
@@ -17,13 +15,8 @@
  *  with this program; if not, write to the Free Software Foundation, Inc.,
  *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
  *
- * ########################################################################
- *
  * Interrupt exception dispatch code.
- *
  */
-#include <linux/config.h>
-
 #include <asm/asm.h>
 #include <asm/mipsregs.h>
 #include <asm/regdef.h>
--- diff/arch/mips/lasat/lasat_board.c	2003-08-20 14:16:25.000000000 +0100
+++ source/arch/mips/lasat/lasat_board.c	2004-02-23 13:56:38.000000000 +0000
@@ -1,11 +1,7 @@
 /*
- * lasat_board.c
- *
  * Thomas Horsten <thh@lasat.com>
  * Copyright (C) 2000 LASAT Networks A/S.
  *
- * ########################################################################
- *
  *  This program is free software; you can distribute it and/or modify it
  *  under the terms of the GNU General Public License (Version 2) as
  *  published by the Free Software Foundation.
@@ -19,10 +15,9 @@
  *  with this program; if not, write to the Free Software Foundation, Inc.,
  *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
  *
- * ########################################################################
- *
  * Routines specific to the LASAT boards
  */
+#include <linux/config.h>
 #include <linux/types.h>
 #include <linux/crc32.h>
 #include <asm/lasat/lasat.h>
--- diff/arch/mips/lasat/prom.c	2003-08-20 14:16:25.000000000 +0100
+++ source/arch/mips/lasat/prom.c	2004-02-23 13:56:38.000000000 +0000
@@ -2,7 +2,6 @@
  * PROM interface routines.
  */
 #include <linux/types.h>
-#include <linux/config.h>
 #include <linux/init.h>
 #include <linux/string.h>
 #include <linux/ctype.h>
@@ -85,8 +84,6 @@ static void setup_prom_vectors(void)
 	prom_printf("prom vectors set up\n");
 }
 
-char arcs_cmdline[CL_SIZE];
-
 static struct at93c_defs at93c_defs[N_MACHTYPES] = {
 	{(void *)AT93C_REG_100, (void *)AT93C_RDATA_REG_100, AT93C_RDATA_SHIFT_100,
 	AT93C_WDATA_SHIFT_100, AT93C_CS_M_100, AT93C_CLK_M_100},
@@ -94,8 +91,11 @@ static struct at93c_defs at93c_defs[N_MA
 	AT93C_WDATA_SHIFT_200, AT93C_CS_M_200, AT93C_CLK_M_200},
 };
 
-void __init prom_init(int argc, char **argv, char **envp, int *prom_vec)
+void __init prom_init(void)
 {
+	int argc = fw_arg0;
+	char **argv = (char **) fw_arg1;
+
 	setup_prom_vectors();
 
 	if (current_cpu_data.cputype == CPU_R5000)
@@ -110,7 +110,7 @@ void __init prom_init(int argc, char **a
 	mips_machgroup = MACH_GROUP_LASAT;
 
 	/* Get the command line */
-	if (argc>0) {
+	if (argc > 0) {
 		strncpy(arcs_cmdline, argv[0], CL_SIZE-1);
 		arcs_cmdline[CL_SIZE-1] = '\0';
 	}
@@ -119,14 +119,15 @@ void __init prom_init(int argc, char **a
 	set_io_port_base(KSEG1);
 
 	/* Set memory regions */
-	ioport_resource.start = 0;		/* Should be KSEGx ???	*/
-	ioport_resource.end = 0xffffffff;	/* Should be ???	*/
+	ioport_resource.start = 0;
+	ioport_resource.end = 0xffffffff;	/* Wrong, fixme.  */
 
 	add_memory_region(0, lasat_board_info.li_memsize, BOOT_MEM_RAM);
 }
 
-void prom_free_prom_memory(void)
+unsigned long __init prom_free_prom_memory(void)
 {
+	return 0;
 }
 
 const char *get_system_type(void)
--- diff/arch/mips/lasat/reset.c	2003-07-08 09:55:17.000000000 +0100
+++ source/arch/mips/lasat/reset.c	2004-02-23 13:56:38.000000000 +0000
@@ -1,10 +1,7 @@
 /* 
- *
  * Thomas Horsten <thh@lasat.com>
  * Copyright (C) 2000 LASAT Networks A/S.
  *
- * ########################################################################
- *
  *  This program is free software; you can distribute it and/or modify it
  *  under the terms of the GNU General Public License (Version 2) as
  *  published by the Free Software Foundation.
@@ -18,12 +15,9 @@
  *  with this program; if not, write to the Free Software Foundation, Inc.,
  *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
  *
- * ########################################################################
- *
  * Reset the LASAT board.
- *
  */
-
+#include <linux/config.h>
 #include <linux/kernel.h>
 #include <asm/reboot.h>
 #include <asm/system.h>
--- diff/arch/mips/lasat/setup.c	2003-08-20 14:16:25.000000000 +0100
+++ source/arch/mips/lasat/setup.c	2004-02-23 13:56:38.000000000 +0000
@@ -26,20 +26,17 @@
 #include <linux/init.h>
 #include <linux/sched.h>
 #include <linux/pci.h>
-#include <linux/ide.h>
-
 #include <linux/interrupt.h>
-#include <asm/time.h>
+#include <linux/tty.h>
+#include <linux/serial.h>
+#include <linux/serial_core.h>
 
+#include <asm/time.h>
 #include <asm/cpu.h>
 #include <asm/bootinfo.h>
 #include <asm/irq.h>
-#include <asm/lasat/lasat.h>
-
-#include <linux/tty.h>
-#include <linux/serial.h>
-#include <linux/serial_core.h>
 #include <asm/serial.h>
+#include <asm/lasat/lasat.h>
 #include <asm/lasat/serial.h>
 
 #ifdef CONFIG_PICVUE
@@ -57,13 +54,6 @@
 int lasat_command_line = 0;
 void lasatint_init(void);
 
-#ifdef CONFIG_BLK_DEV_IDE
-extern struct ide_ops std_ide_ops;
-extern struct ide_ops *ide_ops;
-#endif
-
-extern char arcs_cmdline[CL_SIZE];
-
 extern void lasat_reboot_setup(void);
 extern void pcisetup(void);
 extern void edhac_init(void *, void *, void *);
@@ -122,19 +112,9 @@ static struct notifier_block lasat_panic
 	{ lasat_panic_prom_monitor, NULL, INT_MIN }
 };
 
-#ifdef CONFIG_BLK_DEV_IDE
-static int lasat_ide_default_irq(ide_ioreg_t base) {
-	return 0;
-}
-
-static ide_ioreg_t lasat_ide_default_io_base(int index) {
-	return 0;
-}
-#endif
-
 static void lasat_time_init(void)
 {
-	mips_counter_frequency = lasat_board_info.li_cpu_hz / 2;
+	mips_hpt_frequency = lasat_board_info.li_cpu_hz / 2;
 }
 
 static void lasat_timer_setup(struct irqaction *irq)
@@ -142,7 +122,7 @@ static void lasat_timer_setup(struct irq
 
 	write_c0_compare(
 		read_c0_count() + 
-		mips_counter_frequency / HZ);
+		mips_hpt_frequency / HZ);
 	change_c0_status(ST0_IM, IE_IRQ0 | IE_IRQ5);
 }
 
@@ -182,7 +162,7 @@ void __init serial_init(void)
 }
 #endif
 
-void __init lasat_setup(void)
+static void __init lasat_setup(void)
 {
 	int i;
 	lasat_misc  = &lasat_misc_info[mips_machtype];
@@ -194,12 +174,6 @@ void __init lasat_setup(void)
 	for (i = 0; i < sizeof(lasat_panic_block) / sizeof(struct notifier_block); i++)
 		notifier_chain_register(&panic_notifier_list, &lasat_panic_block[i]);
 
-#ifdef CONFIG_BLK_DEV_IDE
-	ide_ops = &std_ide_ops;
-	ide_ops->ide_default_irq = &lasat_ide_default_irq;
-	ide_ops->ide_default_io_base = &lasat_ide_default_io_base;
-#endif
-
 	lasat_reboot_setup();
 
 	board_time_init = lasat_time_init;
@@ -220,4 +194,4 @@ void __init lasat_setup(void)
 	prom_printf("Lasat specific initialization complete\n");
 }
 
-
+early_initcall(lasat_setup);
--- diff/arch/mips/lib-32/Makefile	2003-08-20 14:16:36.000000000 +0100
+++ source/arch/mips/lib-32/Makefile	2004-02-23 13:56:38.000000000 +0000
@@ -2,8 +2,7 @@
 # Makefile for MIPS-specific library files..
 #
 
-lib-y	+= csum_partial.o memset.o strlen_user.o strncpy_user.o strnlen_user.o \
-	   watch.o 
+lib-y	+= csum_partial.o memset.o watch.o 
 
 ifeq ($(CONFIG_CPU_R3000)$(CONFIG_CPU_TX39XX),y)
   lib-y	+= r3k_dump_tlb.o
--- diff/arch/mips/lib-32/csum_partial.S	2003-08-20 14:16:36.000000000 +0100
+++ source/arch/mips/lib-32/csum_partial.S	2004-02-23 13:56:38.000000000 +0000
@@ -103,8 +103,8 @@ small_csumcpy:
 
 	.align	5
 LEAF(csum_partial)
-	move sum, zero
-	move t7, zero
+	move	sum, zero
+	move	t7, zero
 
 	sltiu	t8, a1, 0x8
 	bnez	t8, small_csumcpy		/* < 8 bytes to copy */
--- diff/arch/mips/lib-32/dump_tlb.c	2003-08-20 14:16:36.000000000 +0100
+++ source/arch/mips/lib-32/dump_tlb.c	2004-02-23 13:56:38.000000000 +0000
@@ -143,7 +143,7 @@ void dump_list_process(struct task_struc
 
 	addr = (unsigned long) address;
 
-	printk("Addr                 == %08x\n", addr);
+	printk("Addr                 == %08lx\n", addr);
 	printk("task                 == %8p\n", t);
 	printk("task->mm             == %8p\n", t->mm);
 	//printk("tasks->mm.pgd        == %08x\n", (unsigned int) t->mm->pgd);
@@ -211,10 +211,10 @@ void dump16(unsigned long *p)
 {
 	int i;
 
-	for(i = 0; i < 8; i++) {
-		printk("*%8p = %08lx, ", p, *p);
+	for (i = 0; i < 8; i++) {
+		printk("*%08lx == %08lx, ", (unsigned long)p, *p);
 		p++;
-		printk("*%8p = %08lx\n", p, *p);
+		printk("*%08lx == %08lx\n", (unsigned long)p, *p);
 		p++;
 	}
 }
--- diff/arch/mips/lib-32/r3k_dump_tlb.c	2003-08-20 14:16:36.000000000 +0100
+++ source/arch/mips/lib-32/r3k_dump_tlb.c	2004-02-23 13:56:38.000000000 +0000
@@ -19,8 +19,7 @@
 
 extern int r3k_have_wired_reg;	/* defined in tlb-r3k.c */
 
-void
-dump_tlb(int first, int last)
+void dump_tlb(int first, int last)
 {
 	int	i;
 	unsigned int asid;
@@ -28,8 +27,7 @@ dump_tlb(int first, int last)
 
 	asid = read_c0_entryhi() & 0xfc0;
 
-	for(i=first;i<=last;i++)
-	{
+	for (i = first; i <= last; i++) {
 		write_c0_index(i<<8);
 		__asm__ __volatile__(
 			".set\tnoreorder\n\t"
@@ -63,14 +61,12 @@ dump_tlb(int first, int last)
 	write_c0_entryhi(asid);
 }
 
-void
-dump_tlb_all(void)
+void dump_tlb_all(void)
 {
 	dump_tlb(0, current_cpu_data.tlbsize - 1);
 }
 
-void
-dump_tlb_wired(void)
+void dump_tlb_wired(void)
 {
 	int wired = r3k_have_wired_reg ? read_c0_wired() : 8;
 
@@ -78,10 +74,9 @@ dump_tlb_wired(void)
 	dump_tlb(0, wired - 1);
 }
 
-void
-dump_tlb_addr(unsigned long addr)
+void dump_tlb_addr(unsigned long addr)
 {
-	unsigned int flags, oldpid;
+	unsigned long flags, oldpid;
 	int index;
 
 	local_irq_save(flags);
@@ -101,15 +96,13 @@ dump_tlb_addr(unsigned long addr)
 	dump_tlb(index, index);
 }
 
-void
-dump_tlb_nonwired(void)
+void dump_tlb_nonwired(void)
 {
 	int wired = r3k_have_wired_reg ? read_c0_wired() : 8;
 	dump_tlb(wired, current_cpu_data.tlbsize - 1);
 }
 
-void
-dump_list_process(struct task_struct *t, void *address)
+void dump_list_process(struct task_struct *t, void *address)
 {
 	pgd_t	*page_dir, *pgd;
 	pmd_t	*pmd;
@@ -148,14 +141,12 @@ dump_list_process(struct task_struct *t,
 	printk("\n");
 }
 
-void
-dump_list_current(void *address)
+void dump_list_current(void *address)
 {
 	dump_list_process(current, address);
 }
 
-unsigned int
-vtop(void *address)
+unsigned int vtop(void *address)
 {
 	pgd_t	*pgd;
 	pmd_t	*pmd;
@@ -172,16 +163,14 @@ vtop(void *address)
 	return paddr;
 }
 
-void
-dump16(unsigned long *p)
+void dump16(unsigned long *p)
 {
 	int i;
 
-	for(i=0;i<8;i++)
-	{
-		printk("*%08lx == %08lx, ",
-		       (unsigned long)p, (unsigned long)*p++);
-		printk("*%08lx == %08lx\n",
-		       (unsigned long)p, (unsigned long)*p++);
+	for (i = 0; i < 8; i++) {
+		printk("*%08lx == %08lx, ", (unsigned long)p, *p);
+		p++;
+		printk("*%08lx == %08lx\n", (unsigned long)p, *p);
+		p++;
 	}
 }
--- diff/arch/mips/lib-64/Makefile	2003-08-20 14:16:36.000000000 +0100
+++ source/arch/mips/lib-64/Makefile	2004-02-23 13:56:38.000000000 +0000
@@ -2,8 +2,7 @@
 # Makefile for MIPS-specific library files..
 #
 
-lib-y	+= csum_partial.o memset.o strlen_user.o strncpy_user.o strnlen_user.o \
-	   watch.o 
+lib-y	+= csum_partial.o memset.o watch.o 
 
 ifeq ($(CONFIG_CPU_R3000)$(CONFIG_CPU_TX39XX),y)
   lib-y	+= r3k_dump_tlb.o
--- diff/arch/mips/lib-64/dump_tlb.c	2003-08-20 14:16:36.000000000 +0100
+++ source/arch/mips/lib-64/dump_tlb.c	2004-02-23 13:56:38.000000000 +0000
@@ -200,12 +200,10 @@ void dump16(unsigned long *p)
 {
 	int i;
 
-	for(i = 0; i < 8; i++) {
-		printk("*%08lx == %08lx, ",
-		       (unsigned long)p, (unsigned long)*p);
+	for (i = 0; i < 8; i++) {
+		printk("*%08lx == %08lx, ", (unsigned long)p, *p);
 		p++;
-		printk("*%08lx == %08lx\n",
-		       (unsigned long)p, (unsigned long)*p);
+		printk("*%08lx == %08lx\n", (unsigned long)p, *p);
 		p++;
 	}
 }
--- diff/arch/mips/lib/Makefile	2003-08-20 14:16:25.000000000 +0100
+++ source/arch/mips/lib/Makefile	2004-02-23 13:56:38.000000000 +0000
@@ -2,9 +2,7 @@
 # Makefile for MIPS-specific library files..
 #
 
-lib-y	+= csum_partial_copy.o memcpy.o promlib.o rtc-no.o rtc-std.o
-
-lib-$(subst m,y,$(CONFIG_BLK_DEV_FD))	+= floppy-no.o floppy-std.o
-lib-$(subst m,y,$(CONFIG_IDE))		+= ide-no.o ide-std.o
+lib-y	+= csum_partial_copy.o dec_and_lock.o memcpy.o promlib.o strlen_user.o \
+	   strncpy_user.o strnlen_user.o
 
 EXTRA_AFLAGS := $(CFLAGS)
--- diff/arch/mips/math-emu/cp1emu.c	2003-08-20 14:16:25.000000000 +0100
+++ source/arch/mips/math-emu/cp1emu.c	2004-02-23 13:56:38.000000000 +0000
@@ -39,6 +39,7 @@
 #include <asm/inst.h>
 #include <asm/bootinfo.h>
 #include <asm/cpu.h>
+#include <asm/cpu-features.h>
 #include <asm/processor.h>
 #include <asm/ptrace.h>
 #include <asm/signal.h>
@@ -233,7 +234,7 @@ static int cop1Emulate(struct pt_regs *x
 			fpuemuprivate.stats.errors++;
 			return SIGBUS;
 		}
-		/* __computer_return_epc() will have updated cp0_epc */
+		/* __compute_return_epc() will have updated cp0_epc */
 		contpc = REG_TO_VA xcp->cp0_epc;
 		/* In order not to confuse ptrace() et al, tweak context */
 		xcp->cp0_epc = VA_TO_REG emulpc - 4;
--- diff/arch/mips/math-emu/dp_fint.c	2002-10-16 04:29:02.000000000 +0100
+++ source/arch/mips/math-emu/dp_fint.c	2004-02-23 13:56:38.000000000 +0000
@@ -33,6 +33,8 @@ ieee754dp ieee754dp_fint(int x)
 
 	CLEARCX;
 
+	xc = ( 0 ? xc : xc );
+
 	if (x == 0)
 		return ieee754dp_zero(0);
 	if (x == 1 || x == -1)
--- diff/arch/mips/math-emu/dp_flong.c	2003-07-08 09:55:17.000000000 +0100
+++ source/arch/mips/math-emu/dp_flong.c	2004-02-23 13:56:38.000000000 +0000
@@ -33,6 +33,8 @@ ieee754dp ieee754dp_flong(s64 x)
 
 	CLEARCX;
 
+	xc = ( 0 ? xc : xc );
+
 	if (x == 0)
 		return ieee754dp_zero(0);
 	if (x == 1 || x == -1)
--- diff/arch/mips/math-emu/kernel_linkage.c	2003-08-20 14:16:25.000000000 +0100
+++ source/arch/mips/math-emu/kernel_linkage.c	2004-02-23 13:56:38.000000000 +0000
@@ -19,6 +19,7 @@
  * manipulation primitives for the Algorithmics MIPS
  * FPU Emulator
  */
+#include <linux/config.h>
 #include <linux/sched.h>
 #include <asm/processor.h>
 #include <asm/signal.h>
--- diff/arch/mips/math-emu/sp_fint.c	2003-07-08 09:55:17.000000000 +0100
+++ source/arch/mips/math-emu/sp_fint.c	2004-02-23 13:56:38.000000000 +0000
@@ -33,6 +33,8 @@ ieee754sp ieee754sp_fint(int x)
 
 	CLEARCX;
 
+	xc = ( 0 ? xc : xc );
+
 	if (x == 0)
 		return ieee754sp_zero(0);
 	if (x == 1 || x == -1)
--- diff/arch/mips/math-emu/sp_flong.c	2003-07-08 09:55:17.000000000 +0100
+++ source/arch/mips/math-emu/sp_flong.c	2004-02-23 13:56:38.000000000 +0000
@@ -33,6 +33,8 @@ ieee754sp ieee754sp_flong(s64 x)
 
 	CLEARCX;
 
+	xc = ( 0 ? xc : xc );
+
 	if (x == 0)
 		return ieee754sp_zero(0);
 	if (x == 1 || x == -1)
--- diff/arch/mips/mips-boards/atlas/Makefile	2003-07-08 09:55:17.000000000 +0100
+++ source/arch/mips/mips-boards/atlas/Makefile	2004-02-23 13:56:38.000000000 +0000
@@ -2,8 +2,6 @@
 # Carsten Langgaard, carstenl@mips.com
 # Copyright (C) 1999,2000 MIPS Technologies, Inc.  All rights reserved.
 #
-# ########################################################################
-#
 # This program is free software; you can distribute it and/or modify it
 # under the terms of the GNU General Public License (Version 2) as
 # published by the Free Software Foundation.
@@ -17,10 +15,6 @@
 # with this program; if not, write to the Free Software Foundation, Inc.,
 # 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
 #
-# #######################################################################
-#
-# Makefile for the MIPS Atlas specific kernel interface routines
-# under Linux.
-#
 
-obj-y	:= atlas_int.o atlas_rtc.o atlas_setup.o
+obj-y			:= atlas_int.o atlas_setup.o
+obj-$(CONFIG_KGDB)	+= atlas_gdb.o
--- diff/arch/mips/mips-boards/atlas/atlas_int.c	2003-07-08 09:55:17.000000000 +0100
+++ source/arch/mips/mips-boards/atlas/atlas_int.c	2004-02-23 13:56:38.000000000 +0000
@@ -32,13 +32,13 @@
 #include <linux/kernel_stat.h>
 
 #include <asm/irq.h>
+#include <asm/io.h>
 #include <asm/mips-boards/atlas.h>
 #include <asm/mips-boards/atlasint.h>
 #include <asm/gdb-stub.h>
 
 
-struct atlas_ictrl_regs *atlas_hw0_icregs
-	= (struct atlas_ictrl_regs *)ATLAS_ICTRL_REGS_BASE;
+static struct atlas_ictrl_regs *atlas_hw0_icregs;
 
 extern asmlinkage void mipsIRQ(void);
 
@@ -50,12 +50,14 @@ extern asmlinkage void mipsIRQ(void);
 
 void disable_atlas_irq(unsigned int irq_nr)
 {
-	atlas_hw0_icregs->intrsten = (1 << irq_nr);
+	atlas_hw0_icregs->intrsten = (1 << (irq_nr-ATLASINT_BASE));
+	iob();
 }
 
 void enable_atlas_irq(unsigned int irq_nr)
 {
-	atlas_hw0_icregs->intseten = (1 << irq_nr);
+	atlas_hw0_icregs->intseten = (1 << (irq_nr-ATLASINT_BASE));
+	iob();
 }
 
 static unsigned int startup_atlas_irq(unsigned int irq)
@@ -109,7 +111,7 @@ void atlas_hw0_irqdispatch(struct pt_reg
 	if (unlikely(int_status == 0))
 		return;
 
-	irq = ls1bit32(int_status);
+	irq = ATLASINT_BASE + ls1bit32(int_status);
 
 	DEBUG_INT("atlas_hw0_irqdispatch: irq=%d\n", irq);
 
@@ -125,6 +127,8 @@ void __init init_IRQ(void)
 {
 	int i;
 
+	atlas_hw0_icregs = (struct atlas_ictrl_regs *)ioremap (ATLAS_ICTRL_REGS_BASE, sizeof(struct atlas_ictrl_regs *));
+	
 	/*
 	 * Mask out all interrupt by writing "1" to all bit position in
 	 * the interrupt reset reg.
@@ -134,7 +138,7 @@ void __init init_IRQ(void)
 	/* Now safe to set the exception vector. */
 	set_except_vector(0, mipsIRQ);
 
-	for (i = 0; i <= ATLASINT_END; i++) {
+	for (i = ATLASINT_BASE; i <= ATLASINT_END; i++) {
 		irq_desc[i].status	= IRQ_DISABLED;
 		irq_desc[i].action	= 0;
 		irq_desc[i].depth	= 1;
--- diff/arch/mips/mips-boards/atlas/atlas_setup.c	2003-07-08 09:55:17.000000000 +0100
+++ source/arch/mips/mips-boards/atlas/atlas_setup.c	2004-02-23 13:56:38.000000000 +0000
@@ -14,117 +14,82 @@
  *  You should have received a copy of the GNU General Public License along
  *  with this program; if not, write to the Free Software Foundation, Inc.,
  *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
- *
- * Atlas specific setup.
  */
 #include <linux/config.h>
 #include <linux/init.h>
 #include <linux/interrupt.h>
 #include <linux/sched.h>
-#include <linux/mc146818rtc.h>
 #include <linux/ioport.h>
+#include <linux/tty.h>
+#include <linux/serial.h>
+#include <linux/serial_core.h>
 
 #include <asm/cpu.h>
 #include <asm/bootinfo.h>
 #include <asm/irq.h>
 #include <asm/mips-boards/generic.h>
 #include <asm/mips-boards/prom.h>
+#include <asm/mips-boards/atlas.h>
 #include <asm/mips-boards/atlasint.h>
-#include <asm/gt64120.h>
 #include <asm/time.h>
 #include <asm/traps.h>
 
-#if defined(CONFIG_SERIAL_CONSOLE) || defined(CONFIG_PROM_CONSOLE)
-extern void console_setup(char *, int *);
-char serial_console[20];
-#endif
+extern void mips_reboot_setup(void);
+extern void mips_time_init(void);
+extern void mips_timer_setup(struct irqaction *irq);
+extern unsigned long mips_rtc_get_time(void);
 
 #ifdef CONFIG_KGDB
-extern void rs_kgdb_hook(int);
-extern void saa9730_kgdb_hook(void);
-extern void breakpoint(void);
-int remote_debug = 0;
+extern void kgdb_config(void);
 #endif
 
-extern struct rtc_ops atlas_rtc_ops;
-
-extern void mips_reboot_setup(void);
+static void __init serial_init(void);
 
 const char *get_system_type(void)
 {
 	return "MIPS Atlas";
 }
 
-extern void mips_time_init(void);
-extern void mips_timer_setup(struct irqaction *irq);
-extern unsigned long mips_rtc_get_time(void);
-
-void __init atlas_setup(void)
+static int __init atlas_setup(void)
 {
-#ifdef CONFIG_KGDB
-	int rs_putDebugChar(char);
-	char rs_getDebugChar(void);
-	int saa9730_putDebugChar(char);
-	char saa9730_getDebugChar(void);
-	extern int (*generic_putDebugChar)(char);
-	extern char (*generic_getDebugChar)(void);
-#endif
-	char *argptr;
-
 	ioport_resource.end = 0x7fffffff;
 
-#ifdef CONFIG_SERIAL_CONSOLE
-	argptr = prom_getcmdline();
-	if ((argptr = strstr(argptr, "console=ttyS0")) == NULL) {
-		int i = 0;
-		char *s = prom_getenv("modetty0");
-		while(s[i] >= '0' && s[i] <= '9')
-			i++;
-		strcpy(serial_console, "ttyS0,");
-		strncpy(serial_console + 6, s, i);
-		prom_printf("Config serial console: %s\n", serial_console);
-		console_setup(serial_console, NULL);
-	}
-#endif
+	serial_init ();
 
 #ifdef CONFIG_KGDB
-	argptr = prom_getcmdline();
-	if ((argptr = strstr(argptr, "kgdb=ttyS")) != NULL) {
-		int line;
-		argptr += strlen("kgdb=ttyS");
-		if (*argptr != '0' && *argptr != '1')
-			printk("KGDB: Uknown serial line /dev/ttyS%c, "
-			       "falling back to /dev/ttyS1\n", *argptr);
-		line = *argptr == '0' ? 0 : 1;
-		printk("KGDB: Using serial line /dev/ttyS%d for session\n",
-		       line ? 1 : 0);
-
-		if(line == 0) {
-			rs_kgdb_hook(line);
-			generic_putDebugChar = rs_putDebugChar;
-			generic_getDebugChar = rs_getDebugChar;
-		} else {
-			saa9730_kgdb_hook();
-			generic_putDebugChar = saa9730_putDebugChar;
-			generic_getDebugChar = saa9730_getDebugChar;
-		}
-
-		prom_printf("KGDB: Using serial line /dev/ttyS%d for session, "
-			    "please connect your debugger\n", line ? 1 : 0);
-
-		remote_debug = 1;
-		/* Breakpoints and stuff are in atlas_irq_setup() */
-	}
+	kgdb_config();
 #endif
-	argptr = prom_getcmdline();
-
-	if ((argptr = strstr(argptr, "nofpu")) != NULL)
-		cpu_data[0].options &= ~MIPS_CPU_FPU;
+	mips_reboot_setup();
 
-	rtc_ops = &atlas_rtc_ops;
 	board_time_init = mips_time_init;
 	board_timer_setup = mips_timer_setup;
 	rtc_get_time = mips_rtc_get_time;
 
-	mips_reboot_setup();
+	return 0;
+}
+
+early_initcall(atlas_setup);
+
+static void __init serial_init(void)
+{
+#ifdef CONFIG_SERIAL_8250
+	struct uart_port s;
+
+	memset(&s, 0, sizeof(s));
+
+#ifdef CONFIG_CPU_LITTLE_ENDIAN
+	s.iobase = ATLAS_UART_REGS_BASE;
+#else
+	s.iobase = ATLAS_UART_REGS_BASE+3;
+#endif
+	s.irq = ATLASINT_UART;
+	s.uartclk = ATLAS_BASE_BAUD * 16;
+	s.flags = ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST | UPF_RESOURCES | ASYNC_AUTO_IRQ;
+	s.iotype = SERIAL_IO_PORT;
+	s.regshift = 3;
+
+	if (early_serial_setup(&s) != 0) {
+		printk(KERN_ERR "Serial setup failed!\n");
+	}
+#endif
 }
--- diff/arch/mips/mips-boards/generic/Makefile	2003-07-08 09:55:17.000000000 +0100
+++ source/arch/mips/mips-boards/generic/Makefile	2004-02-23 13:56:38.000000000 +0000
@@ -19,9 +19,8 @@
 #
 
 obj-y				:= mipsIRQ.o reset.o display.o init.o memory.o \
-				   printf.o cmdline.o
-obj-$(CONFIG_MIPS_ATLAS)	+= time.o
-obj-$(CONFIG_MIPS_MALTA)	+= time.o
+				   printf.o cmdline.o time.o
+obj-$(CONFIG_PCI)		+= pci.o
 obj-$(CONFIG_KGDB)		+= gdb_hook.o
 
 EXTRA_AFLAGS := $(CFLAGS)
--- diff/arch/mips/mips-boards/generic/cmdline.c	2003-07-08 09:55:17.000000000 +0100
+++ source/arch/mips/mips-boards/generic/cmdline.c	2004-02-23 13:56:38.000000000 +0000
@@ -29,9 +29,7 @@ extern int *_prom_argv;
  * YAMON (32-bit PROM) pass arguments and environment as 32-bit pointer.
  * This macro take care of sign extension.
  */
-#define prom_argv(index) ((char *)(((int *)(int)_prom_argv)[(index)]))
-
-char arcs_cmdline[CL_SIZE];
+#define prom_argv(index) ((char *)(long)_prom_argv[(index)])
 
 char * __init prom_getcmdline(void)
 {
--- diff/arch/mips/mips-boards/generic/display.c	2003-07-08 09:55:17.000000000 +0100
+++ source/arch/mips/mips-boards/generic/display.c	2004-02-23 13:56:38.000000000 +0000
@@ -2,8 +2,6 @@
  * Carsten Langgaard, carstenl@mips.com
  * Copyright (C) 1999,2000 MIPS Technologies, Inc.  All rights reserved.
  *
- * ########################################################################
- *
  *  This program is free software; you can distribute it and/or modify it
  *  under the terms of the GNU General Public License (Version 2) as
  *  published by the Free Software Foundation.
@@ -17,20 +15,21 @@
  *  with this program; if not, write to the Free Software Foundation, Inc.,
  *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
  *
- * ########################################################################
- *
  * Display routines for display messages in MIPS boards ascii display.
- *
  */
 
+#include <linux/compiler.h>
+#include <asm/io.h>
 #include <asm/mips-boards/generic.h>
 
-
 void mips_display_message(const char *str)
 {
-        volatile unsigned int *display = (void *)ASCII_DISPLAY_POS_BASE;
+	static volatile unsigned int *display = NULL;
 	int i;
 
+	if (unlikely(display == NULL))
+		display = (volatile unsigned int *)ioremap(ASCII_DISPLAY_POS_BASE, 16*sizeof(int));
+
 	for (i = 0; i <= 14; i=i+2) {
 	         if (*str)
 		         display[i] = *str++;
@@ -38,12 +37,3 @@ void mips_display_message(const char *st
 		         display[i] = ' ';
 	}
 }
-
-#ifndef CONFIG_MIPS_SEAD
-void mips_display_word(unsigned int num)
-{
-        volatile unsigned int *display = (void *)ASCII_DISPLAY_WORD_BASE;
-
-	*display = num;
-}
-#endif
--- diff/arch/mips/mips-boards/generic/gdb_hook.c	2003-07-08 09:55:17.000000000 +0100
+++ source/arch/mips/mips-boards/generic/gdb_hook.c	2004-02-23 13:56:38.000000000 +0000
@@ -17,7 +17,9 @@
  *
  * This is the interface to the remote debugger stub.
  */
+#include <linux/types.h>
 #include <linux/config.h>
+#include <linux/serial.h>
 #include <linux/serialP.h>
 #include <linux/serial_reg.h>
 
@@ -44,7 +46,7 @@ static __inline__ void serial_out(struct
 	outb(value, info->port+offset);
 }
 
-void rs_kgdb_hook(int tty_no) {
+int rs_kgdb_hook(int tty_no, int speed) {
 	int t;
 	struct serial_state *ser = &rs_table[tty_no];
 
@@ -79,17 +81,19 @@ void rs_kgdb_hook(int tty_no) {
 
 	/*
 	 * and set the speed of the serial port
-	 * (currently hardwired to 9600 8N1
 	 */
+	if (speed == 0)
+		speed = 9600;
 
-	/* baud rate is fixed to 9600 (is this sufficient?)*/
-	t = kdb_port_info.state->baud_base / 9600;
+	t = kdb_port_info.state->baud_base / speed;
 	/* set DLAB */
 	serial_out(&kdb_port_info, UART_LCR, UART_LCR_WLEN8 | UART_LCR_DLAB);
 	serial_out(&kdb_port_info, UART_DLL, t & 0xff);/* LS of divisor */
 	serial_out(&kdb_port_info, UART_DLM, t >> 8);  /* MS of divisor */
 	/* reset DLAB */
 	serial_out(&kdb_port_info, UART_LCR, UART_LCR_WLEN8);
+
+	return speed;
 }
 
 int putDebugChar(char c)
@@ -126,84 +130,5 @@ char rs_getDebugChar(void)
 	while (!(serial_in(&kdb_port_info, UART_LSR) & 1))
 		;
 
-	return(serial_in(&kdb_port_info, UART_RX));
-}
-
-
-#ifdef CONFIG_MIPS_ATLAS
-
-#include <asm/mips-boards/atlas.h>
-#include <asm/mips-boards/saa9730_uart.h>
-
-#define INB(a)     inb((unsigned long)a)
-#define OUTB(x,a)  outb(x,(unsigned long)a)
-
-/*
- * This is the interface to the remote debugger stub
- * if the Philips part is used for the debug port,
- * called from the platform setup code.
- *
- * PCI init will not have been done yet, we make a
- * universal assumption about the way the bootloader (YAMON)
- * have located and set up the chip.
- */
-static t_uart_saa9730_regmap *kgdb_uart = (void *)(ATLAS_SAA9730_REG + SAA9730_UART_REGS_ADDR);
-
-static int saa9730_kgdb_active = 0;
-
-void saa9730_kgdb_hook(void)
-{
-        volatile unsigned char t;
-
-        /*
-         * Clear all interrupts
-         */
-	t = INB(&kgdb_uart->Lsr);
-	t += INB(&kgdb_uart->Msr);
-	t += INB(&kgdb_uart->Thr_Rbr);
-	t += INB(&kgdb_uart->Iir_Fcr);
-
-        /*
-         * Now, initialize the UART
-         */
-	/* 8 data bits, one stop bit, no parity */
-	OUTB(SAA9730_LCR_DATA8, &kgdb_uart->Lcr);
-
-        /* baud rate is fixed to 9600 (is this sufficient?)*/
-	OUTB(0, &kgdb_uart->BaudDivMsb); /* HACK - Assumes standard crystal */
-	OUTB(23, &kgdb_uart->BaudDivLsb); /* HACK - known for MIPS Atlas */
-
-	/* Set RTS/DTR active */
-	OUTB(SAA9730_MCR_DTR | SAA9730_MCR_RTS, &kgdb_uart->Mcr);
-	saa9730_kgdb_active = 1;
-}
-
-int saa9730_putDebugChar(char c)
-{
-
-        if (!saa9730_kgdb_active) {     /* need to init device first */
-                return 0;
-        }
-
-        while (!(INB(&kgdb_uart->Lsr) & SAA9730_LSR_THRE))
-                ;
-	OUTB(c, &kgdb_uart->Thr_Rbr);
-
-        return 1;
+	return serial_in(&kdb_port_info, UART_RX);
 }
-
-char saa9730_getDebugChar(void)
-{
-	char c;
-
-        if (!saa9730_kgdb_active) {     /* need to init device first */
-                return 0;
-        }
-        while (!(INB(&kgdb_uart->Lsr) & SAA9730_LSR_DR))
-                ;
-
-	c = INB(&kgdb_uart->Thr_Rbr);
-        return(c);
-}
-
-#endif
--- diff/arch/mips/mips-boards/generic/init.c	2003-07-08 09:55:17.000000000 +0100
+++ source/arch/mips/mips-boards/generic/init.c	2004-02-23 13:56:38.000000000 +0000
@@ -23,19 +23,28 @@
 #include <linux/kernel.h>
 
 #include <asm/io.h>
+#include <asm/bootinfo.h>
 #include <asm/mips-boards/prom.h>
 #include <asm/mips-boards/generic.h>
+#ifdef CONFIG_MIPS_GT64120
 #include <asm/gt64120.h>
-#include <asm/mips-boards/malta.h>
+#endif
 #include <asm/mips-boards/msc01_pci.h>
 #include <asm/mips-boards/bonito64.h>
+#ifdef CONFIG_MIPS_MALTA
+#include <asm/mips-boards/malta.h>
+#endif
 
-/* Environment variable */
-typedef struct
-{
-	char *name;
-	char *val;
-} t_env_var;
+#ifdef CONFIG_KGDB
+extern int rs_kgdb_hook(int, int);
+extern int rs_putDebugChar(char);
+extern char rs_getDebugChar(void);
+extern int saa9730_kgdb_hook(int);
+extern int saa9730_putDebugChar(char);
+extern char saa9730_getDebugChar(void);
+
+int remote_debug = 0;
+#endif
 
 int prom_argc;
 int *_prom_argv, *_prom_envp;
@@ -44,12 +53,22 @@ int *_prom_argv, *_prom_envp;
  * YAMON (32-bit PROM) pass arguments and environment as 32-bit pointer.
  * This macro take care of sign extension, if running in 64-bit mode.
  */
-#define prom_envp(index) ((char *)(((int *)(int)_prom_envp)[(index)]))
+#define prom_envp(index) ((char *)(long)_prom_envp[(index)])
 
 int init_debug = 0;
 
 unsigned int mips_revision_corid;
 
+/* Bonito64 system controller register base. */
+unsigned long _pcictrl_bonito;
+unsigned long _pcictrl_bonito_pcicfg;
+
+/* GT64120 system controller register base */
+unsigned long _pcictrl_gt64120;
+
+/* MIPS System controller register base */
+unsigned long _pcictrl_msc;
+
 char *prom_getenv(char *envname)
 {
 	/*
@@ -62,21 +81,21 @@ char *prom_getenv(char *envname)
 
 	i = strlen(envname);
 
-	while(prom_envp(index)) {
+	while (prom_envp(index)) {
 		if(strncmp(envname, prom_envp(index), i) == 0) {
 			return(prom_envp(index+1));
 		}
 		index += 2;
 	}
 
-	return(NULL);
+	return NULL;
 }
 
 static inline unsigned char str2hexnum(unsigned char c)
 {
-	if(c >= '0' && c <= '9')
+	if (c >= '0' && c <= '9')
 		return c - '0';
-	if(c >= 'a' && c <= 'f')
+	if (c >= 'a' && c <= 'f')
 		return c - 'a' + 10;
 	return 0; /* foo */
 }
@@ -85,7 +104,7 @@ static inline void str2eaddr(unsigned ch
 {
 	int i;
 
-	for(i = 0; i < 6; i++) {
+	for (i = 0; i < 6; i++) {
 		unsigned char num;
 
 		if((*str == '.') || (*str == ':'))
@@ -118,42 +137,150 @@ int get_ethernet_addr(char *ethernet_add
 	return 0;
 }
 
-int __init prom_init(int argc, char **argv, char **envp)
+#ifdef CONFIG_SERIAL_8250_CONSOLE
+static void __init console_config(void)
+{
+	char console_string[40];
+	int baud = 0;
+	char parity = '\0', bits = '\0', flow = '\0';
+	char *s;
+
+	if ((strstr(prom_getcmdline(), "console=ttyS")) == NULL) {
+		s = prom_getenv("modetty0");
+		if (s) {
+			while (*s >= '0' && *s <= '9')
+				baud = baud*10 + *s++ - '0';
+			if (*s == ',') s++;
+			if (*s) parity = *s++;
+			if (*s == ',') s++;
+			if (*s) bits = *s++;
+			if (*s == ',') s++;
+			if (*s == 'h') flow = 'r';
+		}
+		if (baud == 0)
+			baud = 38400;
+		if (parity != 'n' && parity != 'o' && parity != 'e')
+			parity = 'n';
+		if (bits != '7' && bits != '8')
+			bits = '8';
+		if (flow == '\0')
+			flow = 'r';
+		sprintf (console_string, " console=ttyS0,%d%c%c%c", baud, parity, bits, flow);
+		strcat (prom_getcmdline(), console_string);
+		prom_printf("Config serial console:%s\n", console_string);
+	}
+}
+#endif
+
+#ifdef CONFIG_KGDB
+void __init kgdb_config (void)
+{
+	extern int (*generic_putDebugChar)(char);
+	extern char (*generic_getDebugChar)(void);
+	char *argptr;
+	int line, speed;
+
+	argptr = prom_getcmdline();
+	if ((argptr = strstr(argptr, "kgdb=ttyS")) != NULL) {
+		argptr += strlen("kgdb=ttyS");
+		if (*argptr != '0' && *argptr != '1')
+			printk("KGDB: Unknown serial line /dev/ttyS%c, "
+			       "falling back to /dev/ttyS1\n", *argptr);
+		line = *argptr == '0' ? 0 : 1;
+		printk("KGDB: Using serial line /dev/ttyS%d for session\n", line);
+
+		speed = 0;
+		if (*++argptr == ',')
+		{
+			int c;
+			while ((c = *++argptr) && ('0' <= c && c <= '9'))
+				speed = speed * 10 + c - '0';
+		}
+#ifdef CONFIG_MIPS_ATLAS
+		if (line == 1) {
+			speed = saa9730_kgdb_hook(speed);
+			generic_putDebugChar = saa9730_putDebugChar;
+			generic_getDebugChar = saa9730_getDebugChar;
+		}
+		else 
+#endif
+		{
+			speed = rs_kgdb_hook(line, speed);
+			generic_putDebugChar = rs_putDebugChar;
+			generic_getDebugChar = rs_getDebugChar;
+		}
+
+		prom_printf("KGDB: Using serial line /dev/ttyS%d at %d for session, "
+			    "please connect your debugger\n", line ? 1 : 0, speed);
+
+		{
+			char *s;
+			for (s = "Please connect GDB to this port\r\n"; *s; )
+				generic_putDebugChar (*s++);
+		}
+
+		remote_debug = 1;
+		/* Breakpoint is invoked after interrupts are initialised */
+	}
+}
+#endif
+
+void __init prom_init(void)
 {
-	prom_argc = argc;
-	_prom_argv = (int *)argv;
-	_prom_envp = (int *)envp;
+	prom_argc = fw_arg0;
+	_prom_argv = (int *) fw_arg1;
+	_prom_envp = (int *) fw_arg2;
 
 	mips_display_message("LINUX");
 
 #ifdef CONFIG_MIPS_SEAD
 	set_io_port_base(KSEG1);
 #else
+	/*
+	 * early setup of _pcictrl_bonito so that we can determine
+	 * the system controller on a CORE_EMUL board
+	 */
+	_pcictrl_bonito = (unsigned long)ioremap(BONITO_REG_BASE, BONITO_REG_SIZE);
+
 	mips_revision_corid = MIPS_REVISION_CORID;
+
+	if (mips_revision_corid == MIPS_REVISION_CORID_CORE_EMUL) {
+		if (BONITO_PCIDID == 0x0001df53 || 
+		    BONITO_PCIDID == 0x0003df53)
+			mips_revision_corid = MIPS_REVISION_CORID_CORE_EMUL_BON;
+		else
+			mips_revision_corid = MIPS_REVISION_CORID_CORE_EMUL_MSC;
+	}
 	switch(mips_revision_corid) {
 	case MIPS_REVISION_CORID_QED_RM5261:
 	case MIPS_REVISION_CORID_CORE_LV:
 	case MIPS_REVISION_CORID_CORE_FPGA:
+	case MIPS_REVISION_CORID_CORE_FPGAR2:
 		/*
 		 * Setup the North bridge to do Master byte-lane swapping
 		 * when running in bigendian.
 		 */
-#if defined(__MIPSEL__)
+		_pcictrl_gt64120 = (unsigned long)ioremap(MIPS_GT_BASE, 0x2000);
+
+#ifdef CONFIG_CPU_LITTLE_ENDIAN
 		GT_WRITE(GT_PCI0_CMD_OFS, GT_PCI0_CMD_MBYTESWAP_BIT |
 			 GT_PCI0_CMD_SBYTESWAP_BIT);
 #else
 		GT_WRITE(GT_PCI0_CMD_OFS, 0);
 #endif
 
-#if defined(CONFIG_MIPS_MALTA)
+#ifdef CONFIG_MIPS_MALTA
 		set_io_port_base(MALTA_GT_PORT_BASE);
 #else
-		set_io_port_base(KSEG1);
+		set_io_port_base((unsigned long)ioremap(0, 0x20000000));
 #endif
-
 		break;
+
+	case MIPS_REVISION_CORID_CORE_EMUL_BON:
 	case MIPS_REVISION_CORID_BONITO64:
 	case MIPS_REVISION_CORID_CORE_20K:
+		_pcictrl_bonito_pcicfg = (unsigned long)ioremap(BONITO_PCICFG_BASE, BONITO_PCICFG_SIZE);
+
 		/*
 		 * Disable Bonito IOBC.
 		 */
@@ -165,7 +292,7 @@ int __init prom_init(int argc, char **ar
 		 * Setup the North bridge to do Master byte-lane swapping
 		 * when running in bigendian.
 		 */
-#if defined(__MIPSEL__)
+#ifdef CONFIG_CPU_LITTLE_ENDIAN
 		BONITO_BONGENCFG = BONITO_BONGENCFG &
 			~(BONITO_BONGENCFG_MSTRBYTESWAP |
 			  BONITO_BONGENCFG_BYTESWAP);
@@ -175,16 +302,19 @@ int __init prom_init(int argc, char **ar
 			BONITO_BONGENCFG_BYTESWAP;
 #endif
 
-#if defined(CONFIG_MIPS_MALTA)
-                set_io_port_base(MALTA_BONITO_PORT_BASE);
+#ifdef CONFIG_MIPS_MALTA
+		set_io_port_base(MALTA_BONITO_PORT_BASE);
 #else
-                set_io_port_base(KSEG1);
+		set_io_port_base((unsigned long)ioremap(0, 0x20000000));
 #endif
 		break;
 
 	case MIPS_REVISION_CORID_CORE_MSC:
-	        set_io_port_base(MALTA_MSC_PORT_BASE);
-#if defined(__MIPSEL__)
+	case MIPS_REVISION_CORID_CORE_FPGA2:
+	case MIPS_REVISION_CORID_CORE_EMUL_MSC:
+		_pcictrl_msc = (unsigned long)ioremap(MIPS_MSC01_PCI_REG_BASE, 0x2000); 
+
+#ifdef CONFIG_CPU_LITTLE_ENDIAN
 		MSC_WRITE(MSC01_PCI_SWAP, MSC01_PCI_SWAP_NOSWAP);
 #else
 		MSC_WRITE(MSC01_PCI_SWAP,
@@ -192,7 +322,14 @@ int __init prom_init(int argc, char **ar
 			  MSC01_PCI_SWAP_BYTESWAP << MSC01_PCI_SWAP_MEM_SHF |
 			  MSC01_PCI_SWAP_BYTESWAP << MSC01_PCI_SWAP_BAR0_SHF);
 #endif
+
+#ifdef CONFIG_MIPS_MALTA
+		set_io_port_base(MALTA_MSC_PORT_BASE);
+#else
+		set_io_port_base((unsigned long)ioremap(0, 0x20000000));
+#endif
 		break;
+
 	default:
 		/* Unknown Core card */
 		mips_display_message("CC Error");
@@ -202,6 +339,7 @@ int __init prom_init(int argc, char **ar
 	prom_printf("\nLINUX started...\n");
 	prom_init_cmdline();
 	prom_meminit();
-
-	return 0;
+#ifdef CONFIG_SERIAL_8250_CONSOLE
+	console_config();
+#endif
 }
--- diff/arch/mips/mips-boards/generic/memory.c	2003-07-08 09:55:17.000000000 +0100
+++ source/arch/mips/mips-boards/generic/memory.c	2004-02-23 13:56:38.000000000 +0000
@@ -96,10 +96,10 @@ struct prom_pmemblock * __init prom_getm
 
 	mdesc[3].type = yamon_dontuse;
 	mdesc[3].base = 0x00100000;
-	mdesc[3].size = PHYSADDR(PFN_ALIGN(&_end)) - mdesc[3].base;
+	mdesc[3].size = CPHYSADDR(PFN_ALIGN(&_end)) - mdesc[3].base;
 
 	mdesc[4].type = yamon_free;
-	mdesc[4].base = PHYSADDR(PFN_ALIGN(&_end));
+	mdesc[4].base = CPHYSADDR(PFN_ALIGN(&_end));
 	mdesc[4].size = memsize - mdesc[4].base;
 
 	return &mdesc[0];
@@ -147,12 +147,11 @@ void __init prom_meminit(void)
 	}
 }
 
-void __init
-prom_free_prom_memory (void)
+unsigned long __init prom_free_prom_memory(void)
 {
-	int i;
 	unsigned long freed = 0;
 	unsigned long addr;
+	int i;
 
 	for (i = 0; i < boot_mem_map.nr_map; i++) {
 		if (boot_mem_map.map[i].type != BOOT_MEM_ROM_DATA)
@@ -169,4 +168,6 @@ prom_free_prom_memory (void)
 		}
 	}
 	printk("Freeing prom memory: %ldkb freed\n", freed >> 10);
+
+	return freed;
 }
--- diff/arch/mips/mips-boards/generic/printf.c	2003-07-08 09:55:17.000000000 +0100
+++ source/arch/mips/mips-boards/generic/printf.c	2004-02-23 13:56:38.000000000 +0000
@@ -25,53 +25,39 @@
 #include <asm/io.h>
 
 #ifdef CONFIG_MIPS_ATLAS
-
 #include <asm/mips-boards/atlas.h>
 
-/*
- * Atlas registers are memory mapped on 64-bit aligned boundaries and
- * only word access are allowed.
- * When reading the UART 8 bit registers only the LSB are valid.
- */
-static inline unsigned int serial_in(int offset)
-{
-	return (*(volatile unsigned int *)(mips_io_port_base + ATLAS_UART_REGS_BASE + offset*8) & 0xff);
-}
-
-static inline void serial_out(int offset, int value)
-{
-	*(volatile unsigned int *)(mips_io_port_base + ATLAS_UART_REGS_BASE + offset*8) = value;
-}
+#ifdef CONFIG_CPU_LITTLE_ENDIAN
+#define PORT(offset) (ATLAS_UART_REGS_BASE     + ((offset)<<3))
+#else
+#define PORT(offset) (ATLAS_UART_REGS_BASE + 3 + ((offset)<<3))
+#endif
 
 #elif defined(CONFIG_MIPS_SEAD)
 
 #include <asm/mips-boards/sead.h>
 
-/*
- * SEAD registers are just like Atlas registers.
- */
-static inline unsigned int serial_in(int offset)
-{
-	return (*(volatile unsigned int *)(mips_io_port_base + SEAD_UART0_REGS_BASE + offset*8) & 0xff);
-}
-
-static inline void serial_out(int offset, int value)
-{
-	*(volatile unsigned int *)(mips_io_port_base + SEAD_UART0_REGS_BASE + offset*8) = value;
-}
+#ifdef CONFIG_CPU_LITTLE_ENDIAN
+#define PORT(offset) (SEAD_UART0_REGS_BASE     + ((offset)<<3))
+#else
+#define PORT(offset) (SEAD_UART0_REGS_BASE + 3 + ((offset)<<3))
+#endif
 
 #else
 
+#define PORT(offset) (0x3f8 + (offset))
+
+#endif
+
 static inline unsigned int serial_in(int offset)
 {
-	return inb(0x3f8 + offset);
+	return inb(PORT(offset));
 }
 
 static inline void serial_out(int offset, int value)
 {
-	outb(value, 0x3f8 + offset);
+	outb(value, PORT(offset));
 }
-#endif
 
 int putPromChar(char c)
 {
@@ -85,7 +71,7 @@ int putPromChar(char c)
 
 char getPromChar(void)
 {
-	while (!(serial_in(UART_LSR) & 1))
+	while (!(serial_in(UART_LSR) & UART_LSR_DR))
 		;
 
 	return serial_in(UART_RX);
@@ -102,9 +88,8 @@ void __init prom_printf(char *fmt, ...)
 	char *p, *buf_end;
 	long flags;
 
-	int putPromChar(char);
-
 	spin_lock_irqsave(con_lock, flags);
+
 	va_start(args, fmt);
 	l = vsprintf(buf, fmt, args); /* hopefully i < sizeof(buf) */
 	va_end(args);
@@ -117,5 +102,8 @@ void __init prom_printf(char *fmt, ...)
 			putPromChar('\r');
 		putPromChar(*p);
 	}
+	/* wait for output to drain */
+	while ((serial_in(UART_LSR) & UART_LSR_TEMT) == 0)
+		;
 	spin_unlock_irqrestore(con_lock, flags);
 }
--- diff/arch/mips/mips-boards/generic/reset.c	2002-10-16 04:28:32.000000000 +0100
+++ source/arch/mips/mips-boards/generic/reset.c	2004-02-23 13:56:38.000000000 +0000
@@ -24,6 +24,7 @@
  */
 #include <linux/config.h>
 
+#include <asm/io.h>
 #include <asm/reboot.h>
 #include <asm/mips-boards/generic.h>
 #if defined(CONFIG_MIPS_ATLAS)
@@ -38,14 +39,14 @@ static void atlas_machine_power_off(void
 
 static void mips_machine_restart(char *command)
 {
-        volatile unsigned int *softres_reg = (void *)SOFTRES_REG;
+        volatile unsigned int *softres_reg = (unsigned int *)ioremap (SOFTRES_REG, sizeof(unsigned int));
 
 	*softres_reg = GORESET;
 }
 
 static void mips_machine_halt(void)
 {
-        volatile unsigned int *softres_reg = (void *)SOFTRES_REG;
+        volatile unsigned int *softres_reg = (unsigned int *)ioremap (SOFTRES_REG, sizeof(unsigned int));
 
 	*softres_reg = GORESET;
 }
@@ -53,7 +54,7 @@ static void mips_machine_halt(void)
 #if defined(CONFIG_MIPS_ATLAS)
 static void atlas_machine_power_off(void)
 {
-        volatile unsigned int *psustby_reg = (void *)ATLAS_PSUSTBY_REG;
+        volatile unsigned int *psustby_reg = (unsigned int *)ioremap(ATLAS_PSUSTBY_REG, sizeof(unsigned int));
 
 	*psustby_reg = ATLAS_GOSTBY;
 }
@@ -66,7 +67,7 @@ void mips_reboot_setup(void)
 #if defined(CONFIG_MIPS_ATLAS)
 	_machine_power_off = atlas_machine_power_off;
 #endif
-#if defined(CONFIG_MIPS_MALTA)
+#if defined(CONFIG_MIPS_MALTA) || defined(CONFIG_MIPS_SEAD)
 	_machine_power_off = mips_machine_halt;
 #endif
 }
--- diff/arch/mips/mips-boards/generic/time.c	2003-07-08 09:55:17.000000000 +0100
+++ source/arch/mips/mips-boards/generic/time.c	2004-02-23 13:56:38.000000000 +0000
@@ -2,8 +2,6 @@
  * Carsten Langgaard, carstenl@mips.com
  * Copyright (C) 1999,2000 MIPS Technologies, Inc.  All rights reserved.
  *
- * ########################################################################
- *
  *  This program is free software; you can distribute it and/or modify it
  *  under the terms of the GNU General Public License (Version 2) as
  *  published by the Free Software Foundation.
@@ -17,10 +15,7 @@
  *  with this program; if not, write to the Free Software Foundation, Inc.,
  *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
  *
- * ########################################################################
- *
  * Setting up the clock on the MIPS boards.
- *
  */
 
 #include <linux/types.h>
@@ -40,14 +35,18 @@
 #include <asm/div64.h>
 #include <asm/cpu.h>
 #include <asm/time.h>
+#include <asm/mc146818-time.h>
 
 #include <asm/mips-boards/generic.h>
 #include <asm/mips-boards/prom.h>
 
-static unsigned int r4k_offset; /* Amount to increment compare reg each time */
-static unsigned int r4k_cur;    /* What counter should be at next timer irq */
+unsigned long cpu_khz;
 
+#if defined(CONFIG_MIPS_SEAD)
+#define ALLINTS (IE_IRQ0 | IE_IRQ1 | IE_IRQ5)
+#else
 #define ALLINTS (IE_IRQ0 | IE_IRQ1 | IE_IRQ2 | IE_IRQ3 | IE_IRQ4 | IE_IRQ5)
+#endif
 
 #if defined(CONFIG_MIPS_ATLAS)
 static char display_string[] = "        LINUX ON ATLAS       ";
@@ -55,19 +54,16 @@ static char display_string[] = "        
 #if defined(CONFIG_MIPS_MALTA)
 static char display_string[] = "        LINUX ON MALTA       ";
 #endif
+#if defined(CONFIG_MIPS_SEAD)
+static char display_string[] = "        LINUX ON SEAD       ";
+#endif
 static unsigned int display_count = 0;
 #define MAX_DISPLAY_COUNT (sizeof(display_string) - 8)
 
-#define MIPS_CPU_TIMER_IRQ 7
+#define MIPS_CPU_TIMER_IRQ (NR_IRQS-1)
 
 static unsigned int timer_tick_count=0;
 
-
-static inline void ack_r4ktimer(unsigned int newval)
-{
-	write_c0_compare(newval);
-}
-
 void mips_timer_interrupt(struct pt_regs *regs)
 {
 	if ((timer_tick_count++ % HZ) == 0) {
@@ -81,12 +77,27 @@ void mips_timer_interrupt(struct pt_regs
 }
 
 /*
- * Figure out the r4k offset, the amount to increment the compare
- * register for each time tick.
- * Use the RTC to calculate offset.
+ * Estimate CPU frequency.  Sets mips_counter_frequency as a side-effect
  */
-static unsigned int __init cal_r4koff(void)
+static unsigned int __init estimate_cpu_frequency(void)
 {
+	unsigned int prid = read_c0_prid() & 0xffff00;
+	unsigned int count;
+
+#ifdef CONFIG_MIPS_SEAD
+	/*
+	 * The SEAD board doesn't have a real time clock, so we can't
+	 * really calculate the timer frequency
+	 * For now we hardwire the SEAD board frequency to 12MHz.
+	 */
+	
+	if ((prid == (PRID_COMP_MIPS | PRID_IMP_20KC)) ||
+	    (prid == (PRID_COMP_MIPS | PRID_IMP_25KF)))
+		count = 12000000;
+	else
+		count = 6000000;
+#endif
+#if defined(CONFIG_MIPS_ATLAS) || defined(CONFIG_MIPS_MALTA)
 	unsigned int flags;
 
 	local_irq_save(flags);
@@ -102,73 +113,46 @@ static unsigned int __init cal_r4koff(vo
 	while (CMOS_READ(RTC_REG_A) & RTC_UIP);
 	while (!(CMOS_READ(RTC_REG_A) & RTC_UIP));
 
-	mips_counter_frequency = read_c0_count();
+	count = read_c0_count();
 
 	/* restore interrupts */
 	local_irq_restore(flags);
+#endif
 
-	return (mips_counter_frequency / HZ);
+	mips_hpt_frequency = count;
+	if ((prid != (PRID_COMP_MIPS | PRID_IMP_20KC)) &&
+	    (prid != (PRID_COMP_MIPS | PRID_IMP_25KF)))
+		count *= 2;
+
+	count += 5000;    /* round */
+	count -= count%10000;
+
+	return count;
 }
 
 unsigned long __init mips_rtc_get_time(void)
 {
-	unsigned int year, mon, day, hour, min, sec;
-	unsigned char save_control;
-
-	save_control = CMOS_READ(RTC_CONTROL);
-
-	/* Freeze it. */
-	CMOS_WRITE(save_control | RTC_SET, RTC_CONTROL);
-
-	/* Read regs. */
-	sec = CMOS_READ(RTC_SECONDS);
-	min = CMOS_READ(RTC_MINUTES);
-	hour = CMOS_READ(RTC_HOURS);
-
-	if (!(save_control & RTC_24H))
-	{
-		if ((hour & 0xf) == 0xc)
-		        hour &= 0x80;
-	        if (hour & 0x80)
-		        hour = (hour & 0xf) + 12;
-	}
-	day = CMOS_READ(RTC_DAY_OF_MONTH);
-	mon = CMOS_READ(RTC_MONTH);
-	year = CMOS_READ(RTC_YEAR);
-
-	/* Unfreeze clock. */
-	CMOS_WRITE(save_control, RTC_CONTROL);
-
-	if ((year += 1900) < 1970)
-	        year += 100;
-
-	return mktime(year, mon, day, hour, min, sec);
+	return mc146818_get_cmos_time();
 }
 
 void __init mips_time_init(void)
 {
-        unsigned int est_freq, flags;
+	unsigned int est_freq, flags;
 
 	local_irq_save(flags);
 
+#if defined(CONFIG_MIPS_ATLAS) || defined(CONFIG_MIPS_MALTA)
         /* Set Data mode - binary. */
         CMOS_WRITE(CMOS_READ(RTC_CONTROL) | RTC_DM_BINARY, RTC_CONTROL);
+#endif
 
-	printk("calculating r4koff... ");
-	r4k_offset = cal_r4koff();
-	printk("%08x(%d)\n", r4k_offset, r4k_offset);
-
-        if ((read_c0_prid() & 0xffff00) ==
-	    (PRID_COMP_MIPS | PRID_IMP_20KC))
-		est_freq = r4k_offset*HZ;
-	else
-		est_freq = 2*r4k_offset*HZ;
+	est_freq = estimate_cpu_frequency ();
 
-	est_freq += 5000;    /* round */
-	est_freq -= est_freq%10000;
 	printk("CPU frequency %d.%02d MHz\n", est_freq/1000000,
 	       (est_freq%1000000)*100/1000000);
 
+        cpu_khz = est_freq / 1000;
+
 	local_irq_restore(flags);
 }
 
@@ -179,7 +163,6 @@ void __init mips_timer_setup(struct irqa
 	setup_irq(MIPS_CPU_TIMER_IRQ, irq);
 
         /* to generate the first timer interrupt */
-	r4k_cur = (read_c0_count() + r4k_offset);
-	write_c0_compare(r4k_cur);
+	write_c0_compare (read_c0_count() + mips_hpt_frequency/HZ);
 	set_c0_status(ALLINTS);
 }
--- diff/arch/mips/mips-boards/malta/Makefile	2003-07-08 09:55:17.000000000 +0100
+++ source/arch/mips/mips-boards/malta/Makefile	2004-02-23 13:56:38.000000000 +0000
@@ -2,8 +2,6 @@
 # Carsten Langgaard, carstenl@mips.com
 # Copyright (C) 2000 MIPS Technologies, Inc.  All rights reserved.
 #
-# ########################################################################
-#
 # This program is free software; you can distribute it and/or modify it
 # under the terms of the GNU General Public License (Version 2) as
 # published by the Free Software Foundation.
@@ -17,10 +15,8 @@
 # with this program; if not, write to the Free Software Foundation, Inc.,
 # 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
 #
-# #######################################################################
-#
 # Makefile for the MIPS Malta specific kernel interface routines
 # under Linux.
 #
 
-obj-y := malta_int.o malta_rtc.o malta_setup.o
+obj-y := malta_int.o malta_setup.o
--- diff/arch/mips/mips-boards/malta/malta_int.c	2003-07-08 09:55:17.000000000 +0100
+++ source/arch/mips/mips-boards/malta/malta_int.c	2004-02-23 13:56:38.000000000 +0000
@@ -32,15 +32,14 @@
 
 #include <asm/i8259.h>
 #include <asm/io.h>
-#include <asm/mips-boards/generic.h>
 #include <asm/mips-boards/malta.h>
 #include <asm/mips-boards/maltaint.h>
 #include <asm/mips-boards/piix4.h>
-#include <asm/mips-boards/msc01_pci.h>
 #include <asm/gt64120.h>
+#include <asm/mips-boards/generic.h>
+#include <asm/mips-boards/msc01_pci.h>
 
 extern asmlinkage void mipsIRQ(void);
-extern int mips_pcibios_iack(void);
 
 #ifdef CONFIG_KGDB
 extern void breakpoint(void);
@@ -50,6 +49,55 @@ extern int remote_debug;
 
 static spinlock_t mips_irq_lock = SPIN_LOCK_UNLOCKED;
 
+static inline int mips_pcibios_iack(void)
+{
+	int irq;
+        u32 dummy;
+
+	/*
+	 * Determine highest priority pending interrupt by performing
+	 * a PCI Interrupt Acknowledge cycle.
+	 */
+	switch(mips_revision_corid) {
+	case MIPS_REVISION_CORID_CORE_MSC:
+	case MIPS_REVISION_CORID_CORE_FPGA2:
+	case MIPS_REVISION_CORID_CORE_EMUL_MSC:
+	        MSC_READ(MSC01_PCI_IACK, irq);
+		irq &= 0xff;
+		break;
+	case MIPS_REVISION_CORID_QED_RM5261:
+	case MIPS_REVISION_CORID_CORE_LV:
+	case MIPS_REVISION_CORID_CORE_FPGA:
+	case MIPS_REVISION_CORID_CORE_FPGAR2:
+		irq = GT_READ(GT_PCI0_IACK_OFS);
+		irq &= 0xff;
+		break;
+	case MIPS_REVISION_CORID_BONITO64:
+	case MIPS_REVISION_CORID_CORE_20K:
+	case MIPS_REVISION_CORID_CORE_EMUL_BON:
+		/* The following will generate a PCI IACK cycle on the
+		 * Bonito controller. It's a little bit kludgy, but it
+		 * was the easiest way to implement it in hardware at
+		 * the given time.
+		 */
+		BONITO_PCIMAP_CFG = 0x20000;
+
+		/* Flush Bonito register block */
+		dummy = BONITO_PCIMAP_CFG;
+		iob();    /* sync */
+
+		irq = *(volatile u32 *)(_pcictrl_bonito_pcicfg);
+		iob();    /* sync */
+		irq &= 0xff;
+		BONITO_PCIMAP_CFG = 0;
+		break;
+	default:
+	        printk("Unknown Core card, don't know the system controller.\n");
+		return -1;
+	}
+	return irq;
+}
+
 static inline int get_int(int *irq)
 {
 	unsigned long flags;
@@ -104,18 +152,22 @@ void corehi_irqdispatch(struct pt_regs *
 , regs->cp0_epc, regs->cp0_status, regs->cp0_cause, regs->cp0_badvaddr);
         switch(mips_revision_corid) {
         case MIPS_REVISION_CORID_CORE_MSC:
+        case MIPS_REVISION_CORID_CORE_FPGA2:
+	case MIPS_REVISION_CORID_CORE_EMUL_MSC:
                 break;
         case MIPS_REVISION_CORID_QED_RM5261:
         case MIPS_REVISION_CORID_CORE_LV:
         case MIPS_REVISION_CORID_CORE_FPGA:
-                GT_READ(GT_INTRCAUSE_OFS, data);
+        case MIPS_REVISION_CORID_CORE_FPGAR2:
+                data = GT_READ(GT_INTRCAUSE_OFS);
                 printk("GT_INTRCAUSE = %08x\n", data);
-                GT_READ(0x70, data);
-                GT_READ(0x78, datahi);
-                printk("GT_CPU_ERR_ADDR = %0x2%08x\n", datahi,data);
+                data = GT_READ(0x70);
+                datahi = GT_READ(0x78);
+                printk("GT_CPU_ERR_ADDR = %02x%08x\n", datahi, data);
                 break;
         case MIPS_REVISION_CORID_BONITO64:
         case MIPS_REVISION_CORID_CORE_20K:
+        case MIPS_REVISION_CORID_CORE_EMUL_BON:
                 data = BONITO_INTISR;
                 printk("BONITO_INTISR = %08x\n", data);
                 data = BONITO_INTEN;
--- diff/arch/mips/mips-boards/malta/malta_setup.c	2003-07-08 09:55:17.000000000 +0100
+++ source/arch/mips/mips-boards/malta/malta_setup.c	2004-02-23 13:56:38.000000000 +0000
@@ -18,12 +18,9 @@
 #include <linux/config.h>
 #include <linux/init.h>
 #include <linux/sched.h>
-#include <linux/mc146818rtc.h>
 #include <linux/ioport.h>
 #include <linux/pci.h>
-#ifdef CONFIG_BLK_DEV_IDE
-#include <linux/ide.h>
-#endif
+#include <linux/tty.h>
 
 #include <asm/cpu.h>
 #include <asm/bootinfo.h>
@@ -32,9 +29,6 @@
 #include <asm/mips-boards/prom.h>
 #include <asm/mips-boards/malta.h>
 #include <asm/mips-boards/maltaint.h>
-#ifdef CONFIG_BLK_DEV_FD
-#include <asm/floppy.h>
-#endif
 #include <asm/dma.h>
 #include <asm/time.h>
 #include <asm/traps.h>
@@ -42,54 +36,56 @@
 #include <linux/console.h>
 #endif
 
-#if defined(CONFIG_SERIAL_CONSOLE) || defined(CONFIG_PROM_CONSOLE)
-extern void console_setup(char *, int *);
-char serial_console[20];
-#endif
-
-#ifdef CONFIG_KGDB
-extern void rs_kgdb_hook(int);
-int remote_debug = 0;
-#endif
-
-extern struct ide_ops std_ide_ops;
-extern struct fd_ops std_fd_ops;
-extern struct rtc_ops malta_rtc_ops;
-extern struct kbd_ops std_kbd_ops;
-
 extern void mips_reboot_setup(void);
-
 extern void mips_time_init(void);
 extern void mips_timer_setup(struct irqaction *irq);
 extern unsigned long mips_rtc_get_time(void);
 
+#ifdef CONFIG_KGDB
+extern void kgdb_config(void);
+#endif
+
 struct resource standard_io_resources[] = {
 	{ "dma1", 0x00, 0x1f, IORESOURCE_BUSY },
 	{ "timer", 0x40, 0x5f, IORESOURCE_BUSY },
+	{ "keyboard", 0x60, 0x6f, IORESOURCE_BUSY },
 	{ "dma page reg", 0x80, 0x8f, IORESOURCE_BUSY },
 	{ "dma2", 0xc0, 0xdf, IORESOURCE_BUSY },
 };
 
-#define STANDARD_IO_RESOURCES (sizeof(standard_io_resources)/sizeof(struct resource))
-
 const char *get_system_type(void)
 {
 	return "MIPS Malta";
 }
 
-void __init malta_setup(void)
+#ifdef CONFIG_BLK_DEV_FD
+void __init fd_activate(void)
 {
-#ifdef CONFIG_KGDB
-	int rs_putDebugChar(char);
-	char rs_getDebugChar(void);
-	extern int (*generic_putDebugChar)(char);
-	extern char (*generic_getDebugChar)(void);
+	/*
+	 * Activate Floppy Controller in the SMSC FDC37M817 Super I/O
+	 * Controller.
+	 * Done by YAMON 2.00 onwards
+	 */
+	/* Entering config state. */
+	SMSC_WRITE(SMSC_CONFIG_ENTER, SMSC_CONFIG_REG);
+
+	/* Activate floppy controller. */
+	SMSC_WRITE(SMSC_CONFIG_DEVNUM, SMSC_CONFIG_REG);
+	SMSC_WRITE(SMSC_CONFIG_DEVNUM_FLOPPY, SMSC_DATA_REG);
+	SMSC_WRITE(SMSC_CONFIG_ACTIVATE, SMSC_CONFIG_REG);
+	SMSC_WRITE(SMSC_CONFIG_ACTIVATE_ENABLE, SMSC_DATA_REG);
+
+	/* Exit config state. */
+	SMSC_WRITE(SMSC_CONFIG_EXIT, SMSC_CONFIG_REG);
+}
 #endif
-	char *argptr;
-	int i;
+
+static int __init malta_setup(void)
+{
+	unsigned int i;
 
 	/* Request I/O space for devices used on the Malta board. */
-	for (i = 0; i < STANDARD_IO_RESOURCES; i++)
+	for (i = 0; i < ARRAY_SIZE(standard_io_resources); i++)
 		request_resource(&ioport_resource, standard_io_resources+i);
 
 	/*
@@ -97,54 +93,79 @@ void __init malta_setup(void)
 	 */
 	enable_dma(4);
 
-#ifdef CONFIG_SERIAL_CONSOLE
-	argptr = prom_getcmdline();
-	if ((argptr = strstr(argptr, "console=")) == NULL) {
-		argptr = prom_getcmdline();
-		strcat(argptr, " console=ttyS0,38400");
-	}
+#ifdef CONFIG_KGDB
+	kgdb_config ();
 #endif
 
-#ifdef CONFIG_KGDB
-	argptr = prom_getcmdline();
-	if ((argptr = strstr(argptr, "kgdb=ttyS")) != NULL) {
-		int line;
-		argptr += strlen("kgdb=ttyS");
-		if (*argptr != '0' && *argptr != '1')
-			printk("KGDB: Uknown serial line /dev/ttyS%c, "
-			       "falling back to /dev/ttyS1\n", *argptr);
-		line = *argptr == '0' ? 0 : 1;
-		printk("KGDB: Using serial line /dev/ttyS%d for session\n",
-		       line ? 1 : 0);
-
-		rs_kgdb_hook(line);
-		generic_putDebugChar = rs_putDebugChar;
-		generic_getDebugChar = rs_getDebugChar;
+	if ((mips_revision_corid == MIPS_REVISION_CORID_BONITO64) ||
+	    (mips_revision_corid == MIPS_REVISION_CORID_CORE_20K) ||
+	    (mips_revision_corid == MIPS_REVISION_CORID_CORE_EMUL_BON)) {
+		char *argptr;
 
-		prom_printf("KGDB: Using serial line /dev/ttyS%d for session, "
-			    "please connect your debugger\n", line ? 1 : 0);
+		argptr = prom_getcmdline();
+		if (strstr(argptr, "debug")) {
+			BONITO_BONGENCFG |= BONITO_BONGENCFG_DEBUGMODE;
+			printk ("Enabled Bonito debug mode\n");
+		}
+		else
+			BONITO_BONGENCFG &= ~BONITO_BONGENCFG_DEBUGMODE;
+
+#ifdef CONFIG_DMA_COHERENT
+		if (BONITO_PCICACHECTRL & BONITO_PCICACHECTRL_CPUCOH_PRES) {
+			BONITO_PCICACHECTRL |= BONITO_PCICACHECTRL_CPUCOH_EN;
+			printk("Enabled Bonito CPU coherency\n");
+
+			argptr = prom_getcmdline();
+			if (strstr(argptr, "iobcuncached")) {
+				BONITO_PCICACHECTRL &= ~BONITO_PCICACHECTRL_IOBCCOH_EN;
+				BONITO_PCIMEMBASECFG = BONITO_PCIMEMBASECFG & 
+					~(BONITO_PCIMEMBASECFG_MEMBASE0_CACHED |
+					  BONITO_PCIMEMBASECFG_MEMBASE1_CACHED);
+				printk("Disabled Bonito IOBC coherency\n");
+			}
+			else {
+				BONITO_PCICACHECTRL |= BONITO_PCICACHECTRL_IOBCCOH_EN;
+				BONITO_PCIMEMBASECFG |= 
+					(BONITO_PCIMEMBASECFG_MEMBASE0_CACHED | 
+					 BONITO_PCIMEMBASECFG_MEMBASE1_CACHED);
+				printk("Disabled Bonito IOBC coherency\n");
+			}
+		}
+		else
+			panic ("Hardware DMA cache coherency not supported\n");
 
-		remote_debug = 1;
-		/* Breakpoints are in init_IRQ() */
+#endif
+	}
+#ifdef CONFIG_DMA_COHERENT
+	else {
+		panic ("Hardware DMA cache coherency not supported\n");
 	}
 #endif
 
-	argptr = prom_getcmdline();
-	if ((argptr = strstr(argptr, "nofpu")) != NULL)
-		cpu_data[0].options &= ~MIPS_CPU_FPU;
-
-	rtc_ops = &malta_rtc_ops;
-
 #ifdef CONFIG_BLK_DEV_IDE
-        ide_ops = &std_ide_ops;
+	/* Check PCI clock */
+	{
+		int jmpr = (*((volatile unsigned int *)ioremap(MALTA_JMPRS_REG, sizeof(unsigned int))) >> 2) & 0x07;
+		static const int pciclocks[] __initdata = {
+			33, 20, 25, 30, 12, 16, 37, 10
+		};
+		int pciclock = pciclocks[jmpr];
+		char *argptr = prom_getcmdline();
+
+		if (pciclock != 33 && !strstr (argptr, "idebus=")) {
+			printk("WARNING: PCI clock is %dMHz, setting idebus\n", pciclock);
+			argptr += strlen(argptr);
+			sprintf (argptr, " idebus=%d", pciclock);
+			if (pciclock < 20 || pciclock > 66)
+				printk ("WARNING: IDE timing calculations will be incorrect\n");
+		}
+	}
 #endif
 #ifdef CONFIG_BLK_DEV_FD
-        fd_ops = &std_fd_ops;
+	fd_activate ();
 #endif
 #ifdef CONFIG_VT
 #if defined(CONFIG_VGA_CONSOLE)
-        conswitchp = &vga_con;
-
 	screen_info = (struct screen_info) {
 		0, 25,			/* orig-x, orig-y */
 		0,			/* unused */
@@ -153,11 +174,9 @@ void __init malta_setup(void)
 		80,			/* orig-video-cols */
 		0,0,0,			/* ega_ax, ega_bx, ega_cx */
 		25,			/* orig-video-lines */
-		1,			/* orig-video-isVGA */
+		VIDEO_TYPE_VGAC,	/* orig-video-isVGA */
 		16			/* orig-video-points */
 	};
-#elif defined(CONFIG_DUMMY_CONSOLE)
-        conswitchp = &dummy_con;
 #endif
 #endif
 	mips_reboot_setup();
@@ -165,4 +184,8 @@ void __init malta_setup(void)
 	board_time_init = mips_time_init;
 	board_timer_setup = mips_timer_setup;
 	rtc_get_time = mips_rtc_get_time;
+
+	return 0;
 }
+
+early_initcall(malta_setup);
--- diff/arch/mips/mips-boards/sead/Makefile	2003-07-08 09:55:17.000000000 +0100
+++ source/arch/mips/mips-boards/sead/Makefile	2004-02-23 13:56:38.000000000 +0000
@@ -23,4 +23,4 @@
 # under Linux.
 #
 
-obj-y		:= sead_int.o sead_setup.o sead_time.o
+obj-y		:= sead_int.o sead_setup.o
--- diff/arch/mips/mips-boards/sead/sead_int.c	2003-07-08 09:55:17.000000000 +0100
+++ source/arch/mips/mips-boards/sead/sead_int.c	2004-02-23 13:56:38.000000000 +0000
@@ -1,8 +1,7 @@
 /*
  * Carsten Langgaard, carstenl@mips.com
  * Copyright (C) 2002 MIPS Technologies, Inc.  All rights reserved.
- *
- * ########################################################################
+ * Copyright (C) 2003 Ralf Baechle (ralf@linux-mips.org)
  *
  *  This program is free software; you can distribute it and/or modify it
  *  under the terms of the GNU General Public License (Version 2) as
@@ -17,84 +16,29 @@
  *  with this program; if not, write to the Free Software Foundation, Inc.,
  *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
  *
- * ########################################################################
- *
  * Routines for generic manipulation of the interrupts found on the MIPS
  * Sead board.
- *
  */
-#include <linux/config.h>
 #include <linux/init.h>
 #include <linux/irq.h>
-#include <linux/sched.h>
-#include <linux/slab.h>
 #include <linux/interrupt.h>
-#include <linux/kernel_stat.h>
 
-#include <asm/mips-boards/sead.h>
 #include <asm/mips-boards/seadint.h>
 
 extern asmlinkage void mipsIRQ(void);
 
-void disable_sead_irq(unsigned int irq_nr)
-{
-	if (irq_nr == SEADINT_UART0)
-		clear_c0_status(0x00000400);
-	else
-		if (irq_nr == SEADINT_UART1)
-			clear_c0_status(0x00000800);
-}
-
-void enable_sead_irq(unsigned int irq_nr)
-{
-	if (irq_nr == SEADINT_UART0)
-		set_c0_status(0x00000400);
-	else
-		if (irq_nr == SEADINT_UART1)
-			set_c0_status(0x00000800);
-}
-
-static unsigned int startup_sead_irq(unsigned int irq)
-{
-	enable_sead_irq(irq);
-	return 0; /* never anything pending */
-}
-
-#define shutdown_sead_irq	disable_sead_irq
-
-#define mask_and_ack_sead_irq disable_sead_irq
-
-static void end_sead_irq(unsigned int irq)
-{
-	if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
-		enable_sead_irq(irq);
-}
-
-static struct hw_interrupt_type sead_irq_type = {
-	"SEAD",
-	startup_sead_irq,
-	shutdown_sead_irq,
-	enable_sead_irq,
-	disable_sead_irq,
-	mask_and_ack_sead_irq,
-	end_sead_irq,
-	NULL
-};
-
-void sead_hw0_irqdispatch(struct pt_regs *regs)
+asmlinkage void sead_hw0_irqdispatch(struct pt_regs *regs)
 {
-	do_IRQ(0, regs);
+	do_IRQ(SEADINT_UART0, regs);
 }
 
-void sead_hw1_irqdispatch(struct pt_regs *regs)
+asmlinkage void sead_hw1_irqdispatch(struct pt_regs *regs)
 {
-	do_IRQ(1, regs);
+	do_IRQ(SEADINT_UART1, regs);
 }
 
 void __init init_IRQ(void)
 {
-	int i;
-
         /*
          * Mask out all interrupt
 	 */
@@ -104,12 +48,5 @@ void __init init_IRQ(void)
 	set_except_vector(0, mipsIRQ);
 
 	init_generic_irq();
-
-	for (i = 0; i <= SEADINT_END; i++) {
-		irq_desc[i].status	= IRQ_DISABLED;
-		irq_desc[i].action	= NULL;
-		irq_desc[i].depth	= 1;
-		irq_desc[i].lock	= SPIN_LOCK_UNLOCKED;
-		irq_desc[i].handler	= &sead_irq_type;
-	}
+	mips_cpu_irq_init(0);
 }
--- diff/arch/mips/mips-boards/sead/sead_setup.c	2003-07-08 09:55:17.000000000 +0100
+++ source/arch/mips/mips-boards/sead/sead_setup.c	2004-02-23 13:56:38.000000000 +0000
@@ -20,58 +20,65 @@
 #include <linux/config.h>
 #include <linux/init.h>
 #include <linux/sched.h>
-#include <linux/mc146818rtc.h>
 #include <linux/ioport.h>
+#include <linux/tty.h>
+#include <linux/serial.h>
+#include <linux/serial_core.h>
 
 #include <asm/cpu.h>
 #include <asm/bootinfo.h>
 #include <asm/irq.h>
 #include <asm/mips-boards/generic.h>
 #include <asm/mips-boards/prom.h>
+#include <asm/mips-boards/sead.h>
 #include <asm/mips-boards/seadint.h>
 #include <asm/time.h>
 
-#if defined(CONFIG_SERIAL_CONSOLE) || defined(CONFIG_PROM_CONSOLE)
-extern void console_setup(char *, int *);
-char serial_console[20];
-#endif
-
 extern void mips_reboot_setup(void);
 extern void mips_time_init(void);
 extern void mips_timer_setup(struct irqaction *irq);
 
+static void __init serial_init(void);
+
 const char *get_system_type(void)
 {
 	return "MIPS SEAD";
 }
 
-void __init sead_setup(void)
+static void __init sead_setup(void)
 {
-	char *argptr;
-
 	ioport_resource.end = 0x7fffffff;
 
-#ifdef CONFIG_SERIAL_CONSOLE
-	argptr = prom_getcmdline();
-	if ((argptr = strstr(argptr, "console=ttyS0")) == NULL) {
-		int i = 0;
-		char *s = prom_getenv("modetty0");
-		while(s[i] >= '0' && s[i] <= '9')
-			i++;
-		strcpy(serial_console, "ttyS0,");
-		strncpy(serial_console + 6, s, i);
-		prom_printf("Config serial console: %s\n", serial_console);
-		console_setup(serial_console, NULL);
-	}
-#endif
-
-	argptr = prom_getcmdline();
-
-	if ((argptr = strstr(argptr, "nofpu")) != NULL)
-		cpu_data[0].options &= ~MIPS_CPU_FPU;
+	serial_init ();
 
 	board_time_init = mips_time_init;
 	board_timer_setup = mips_timer_setup;
 
 	mips_reboot_setup();
 }
+
+early_initcall(sead_setup);
+
+static void __init serial_init(void)
+{
+#ifdef CONFIG_SERIAL_8250
+	struct uart_port s;
+
+	memset(&s, 0, sizeof(s));
+
+#ifdef CONFIG_CPU_LITTLE_ENDIAN
+	s.iobase = SEAD_UART0_REGS_BASE;
+#else
+	s.iobase = SEAD_UART0_REGS_BASE+3;
+#endif
+	s.irq = SEADINT_UART0;
+	s.uartclk = SEAD_BASE_BAUD * 16;
+	s.flags = ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST | UPF_RESOURCES | ASYNC_AUTO_IRQ;
+	s.iotype = 0;
+	s.regshift = 3;
+
+	if (early_serial_setup(&s) != 0) {
+		printk(KERN_ERR "Serial setup failed!\n");
+	}
+#endif
+}
--- diff/arch/mips/mm-32/Makefile	2003-08-20 14:16:36.000000000 +0100
+++ source/arch/mips/mm-32/Makefile	2004-02-23 13:56:38.000000000 +0000
@@ -2,19 +2,18 @@
 # Makefile for the Linux/MIPS-specific parts of the memory manager.
 #
 
-obj-y				+= init.o
-
-obj-$(CONFIG_CPU_TX49XX)	+= pg-r4k.o tlbex-r4k.o
-obj-$(CONFIG_CPU_R4300)		+= pg-r4k.o tlbex-r4k.o
-obj-$(CONFIG_CPU_R4X00)		+= pg-r4k.o tlbex-r4k.o
-obj-$(CONFIG_CPU_VR41XX)	+= pg-r4k.o tlbex-r4k.o
-obj-$(CONFIG_CPU_R5000)		+= pg-r4k.o tlbex-r4k.o
-obj-$(CONFIG_CPU_NEVADA)	+= pg-r4k.o tlbex-r4k.o
-obj-$(CONFIG_CPU_R5432)		+= pg-r4k.o tlbex-r4k.o
-obj-$(CONFIG_CPU_RM7000)	+= pg-r4k.o tlbex-r4k.o
-obj-$(CONFIG_CPU_R10000)	+= pg-r4k.o tlbex-r4k.o
-obj-$(CONFIG_CPU_MIPS32)	+= pg-r4k.o tlbex-r4k.o
-obj-$(CONFIG_CPU_MIPS64)	+= pg-r4k.o tlbex-r4k.o
+obj-$(CONFIG_CPU_TX49XX)	+= tlbex-r4k.o
+obj-$(CONFIG_CPU_R4300)		+= tlbex-r4k.o
+obj-$(CONFIG_CPU_R4X00)		+= tlbex-r4k.o
+obj-$(CONFIG_CPU_VR41XX)	+= tlbex-r4k.o
+obj-$(CONFIG_CPU_R5000)		+= tlbex-r4k.o
+obj-$(CONFIG_CPU_NEVADA)	+= tlbex-r4k.o
+obj-$(CONFIG_CPU_R5432)		+= tlbex-r4k.o
+obj-$(CONFIG_CPU_RM7000)	+= tlbex-r4k.o
+obj-$(CONFIG_CPU_RM9000)	+= tlbex-r4k.o
+obj-$(CONFIG_CPU_R10000)	+= tlbex-r4k.o
+obj-$(CONFIG_CPU_MIPS32)	+= tlbex-r4k.o
+obj-$(CONFIG_CPU_MIPS64)	+= tlbex-r4k.o
 obj-$(CONFIG_CPU_SB1)		+= tlbex-r4k.o
 
 EXTRA_AFLAGS := $(CFLAGS)
--- diff/arch/mips/mm-32/tlbex-r4k.S	2003-08-20 14:16:36.000000000 +0100
+++ source/arch/mips/mm-32/tlbex-r4k.S	2004-02-23 13:56:38.000000000 +0000
@@ -19,7 +19,6 @@
 #include <asm/mipsregs.h>
 #include <asm/page.h>
 #include <asm/pgtable-bits.h>
-#include <asm/processor.h>
 #include <asm/regdef.h>
 #include <asm/stackframe.h>
 #include <asm/war.h>
@@ -179,9 +178,11 @@
 	PTE_SRL	k1, k1, 6			# convert to entrylo1
 	P_MTC0	k1, CP0_ENTRYLO1		# load it
 	b	1f
+	rm9000_tlb_hazard
 	tlbwr					# write random tlb entry
 1:
 	nop
+	rm9000_tlb_hazard
 	eret					# return from trap
 	END(except_vec0_r4000)
 
@@ -452,6 +453,7 @@
 #endif
 invalid_tlbl:
 #ifdef TLB_OPTIMIZE
+	.set	mips3
 	/* Test present bit in entry. */
 	LOAD_PTE(k0, k1)
 	R5K_HAZARD
@@ -459,11 +461,13 @@ invalid_tlbl:
 	PTE_PRESENT(k0, k1, nopage_tlbl)
 	PTE_MAKEVALID(k0, k1)
 	PTE_RELOAD(k1, k0)
+	rm9000_tlb_hazard
 	nop
 	b	1f
 	 tlbwi
 1:
 	nop
+	rm9000_tlb_hazard
 	.set	mips3
 	eret
 	.set	mips0
@@ -485,11 +489,13 @@ nopage_tlbl:
 	PTE_WRITABLE(k0, k1, nopage_tlbs)
 	PTE_MAKEWRITE(k0, k1)
 	PTE_RELOAD(k1, k0)
+	rm9000_tlb_hazard
 	nop
 	b	1f
 	 tlbwi
 1:
 	nop
+	rm9000_tlb_hazard
 	.set	mips3
 	eret
 	.set	mips0
@@ -516,10 +522,12 @@ nopage_tlbs:
 
 	/* Now reload the entry into the tlb. */
 	PTE_RELOAD(k1, k0)
+	rm9000_tlb_hazard
 	nop
 	b	1f
 	 tlbwi
 1:
+	rm9000_tlb_hazard
 	nop
 	.set	mips3
 	eret
@@ -529,4 +537,3 @@ nopage_tlbs:
 nowrite_mod:
 	DO_FAULT(1)
 	END(handle_mod)
-
--- diff/arch/mips/mm-64/Makefile	2003-08-20 14:16:36.000000000 +0100
+++ source/arch/mips/mm-64/Makefile	2004-02-23 13:56:38.000000000 +0000
@@ -2,17 +2,18 @@
 # Makefile for the Linux/MIPS-specific parts of the memory manager.
 #
 
-obj-y				:= init.o tlbex-r4k.o
+obj-y				:= tlbex-r4k.o
 
-obj-$(CONFIG_CPU_R4300)		+= pg-r4k.o tlb-glue-r4k.o
-obj-$(CONFIG_CPU_R4X00)		+= pg-r4k.o tlb-glue-r4k.o
-obj-$(CONFIG_CPU_R5000)		+= pg-r4k.o tlb-glue-r4k.o
-obj-$(CONFIG_CPU_NEVADA)	+= pg-r4k.o tlb-glue-r4k.o
-obj-$(CONFIG_CPU_R5432)		+= pg-r4k.o tlb-glue-r4k.o
-obj-$(CONFIG_CPU_RM7000)	+= pg-r4k.o tlb-glue-r4k.o
-obj-$(CONFIG_CPU_R10000)	+= pg-r4k.o tlb-glue-r4k.o
+obj-$(CONFIG_CPU_R4300)		+= tlb-glue-r4k.o
+obj-$(CONFIG_CPU_R4X00)		+= tlb-glue-r4k.o
+obj-$(CONFIG_CPU_R5000)		+= tlb-glue-r4k.o
+obj-$(CONFIG_CPU_NEVADA)	+= tlb-glue-r4k.o
+obj-$(CONFIG_CPU_R5432)		+= tlb-glue-r4k.o
+obj-$(CONFIG_CPU_RM7000)	+= tlb-glue-r4k.o
+obj-$(CONFIG_CPU_RM9000)	+= tlb-glue-r4k.o
+obj-$(CONFIG_CPU_R10000)	+= tlb-glue-r4k.o
 obj-$(CONFIG_CPU_SB1)		+= tlb-glue-sb1.o
-obj-$(CONFIG_CPU_MIPS64)	+= pg-r4k.o tlb-glue-r4k.o
+obj-$(CONFIG_CPU_MIPS64)	+= tlb-glue-r4k.o
 
 #
 # Debug TLB exception handler, currently unused
--- diff/arch/mips/mm-64/tlbex-r4k.S	2003-08-20 14:16:36.000000000 +0100
+++ source/arch/mips/mm-64/tlbex-r4k.S	2004-02-23 13:56:38.000000000 +0000
@@ -10,7 +10,9 @@
 #include <linux/config.h>
 #include <linux/init.h>
 #include <linux/threads.h>
+
 #include <asm/asm.h>
+#include <asm/hazards.h>
 #include <asm/regdef.h>
 #include <asm/mipsregs.h>
 #include <asm/stackframe.h>
@@ -133,9 +135,11 @@ LEAF(handle_vec1_r4k)
 	ld	k0, 0(k1)			# get even pte
 	ld	k1, 8(k1)			# get odd pte
 	PTE_RELOAD k0 k1
+	rm9000_tlb_hazard
 	b	1f
 	 tlbwr
 1:	nop
+	rm9000_tlb_hazard
 	eret
 
 9:						# handle the vmalloc range
@@ -143,9 +147,11 @@ LEAF(handle_vec1_r4k)
 	ld	k0, 0(k1)			# get even pte
 	ld	k1, 8(k1)			# get odd pte
 	PTE_RELOAD k0 k1
+	rm9000_tlb_hazard
 	b	1f
 	 tlbwr
 1:	nop
+	rm9000_tlb_hazard
 	eret
 END(handle_vec1_r4k)
 
@@ -173,8 +179,10 @@ LEAF(handle_vec1_r10k)
 	ld	k0, 0(k1)			# get even pte
 	ld	k1, 8(k1)			# get odd pte
 	PTE_RELOAD k0 k1
+	rm9000_tlb_hazard
 	nop
 	tlbwr
+	rm9000_tlb_hazard
 	eret
 
 9:						# handle the vmalloc range
@@ -182,8 +190,10 @@ LEAF(handle_vec1_r10k)
 	ld	k0, 0(k1)			# get even pte
 	ld	k1, 8(k1)			# get odd pte
 	PTE_RELOAD k0 k1
+	rm9000_tlb_hazard
 	nop
 	tlbwr
+	rm9000_tlb_hazard
 	eret
 END(handle_vec1_r10k)
 
@@ -191,7 +201,11 @@ END(handle_vec1_r10k)
 	.align	5
 LEAF(invalid_vmalloc_address)
 	.set	noat
+	SAVE_ALL
+	CLI
+	dmfc0	t0, CP0_BADVADDR
+	sd	t0, PT_BVADDR(sp)
+	move	a0, sp
+	jal	show_regs
 	PANIC("Invalid kernel address")
-1:	b	1b
-	 nop
 END(invalid_vmalloc_address)
--- diff/arch/mips/mm/Makefile	2004-02-09 10:36:07.000000000 +0000
+++ source/arch/mips/mm/Makefile	2004-02-23 13:56:38.000000000 +0000
@@ -2,30 +2,38 @@
 # Makefile for the Linux/MIPS-specific parts of the memory manager.
 #
 
-obj-y				+= cache.o fault.o loadmmu.o pgtable.o
+obj-y				+= cache.o extable.o fault.o init.o pgtable.o
 
 obj-$(CONFIG_MIPS32)		+= ioremap.o pgtable-32.o
 obj-$(CONFIG_MIPS64)		+= pgtable-64.o
 obj-$(CONFIG_HIGHMEM)		+= highmem.o
 
-obj-$(CONFIG_CPU_MIPS32)	+= c-r4k.o cex-gen.o tlb-r4k.o
-obj-$(CONFIG_CPU_MIPS64)	+= c-r4k.o cex-gen.o tlb-r4k.o
-obj-$(CONFIG_CPU_NEVADA)	+= c-r4k.o cex-gen.o tlb-r4k.o
-obj-$(CONFIG_CPU_R10000)	+= c-r4k.o cex-gen.o tlb-andes.o
-obj-$(CONFIG_CPU_R3000)		+= pg-r3k.o c-r3k.o tlb-r3k.o tlbex-r3k.o
-obj-$(CONFIG_CPU_R4300)		+= c-r4k.o cex-gen.o tlb-r4k.o
-obj-$(CONFIG_CPU_R4X00)		+= c-r4k.o cex-gen.o tlb-r4k.o
-obj-$(CONFIG_CPU_R5000)		+= c-r4k.o cex-gen.o tlb-r4k.o
-obj-$(CONFIG_CPU_R5432)		+= c-r4k.o cex-gen.o tlb-r4k.o
-obj-$(CONFIG_CPU_RM7000)	+= c-r4k.o cex-gen.o tlb-r4k.o
+obj-$(CONFIG_CPU_MIPS32)	+= c-r4k.o cex-gen.o pg-r4k.o tlb-r4k.o
+obj-$(CONFIG_CPU_MIPS64)	+= c-r4k.o cex-gen.o pg-r4k.o tlb-r4k.o
+obj-$(CONFIG_CPU_NEVADA)	+= c-r4k.o cex-gen.o pg-r4k.o tlb-r4k.o
+obj-$(CONFIG_CPU_R10000)	+= c-r4k.o cex-gen.o pg-r4k.o tlb-andes.o
+obj-$(CONFIG_CPU_R3000)		+= c-r3k.o tlb-r3k.o pg-r4k.o tlbex-r3k.o
+obj-$(CONFIG_CPU_R4300)		+= c-r4k.o cex-gen.o pg-r4k.o tlb-r4k.o
+obj-$(CONFIG_CPU_R4X00)		+= c-r4k.o cex-gen.o pg-r4k.o tlb-r4k.o
+obj-$(CONFIG_CPU_R5000)		+= c-r4k.o cex-gen.o pg-r4k.o tlb-r4k.o
+obj-$(CONFIG_CPU_R5432)		+= c-r4k.o cex-gen.o pg-r4k.o tlb-r4k.o
+obj-$(CONFIG_CPU_RM7000)	+= c-r4k.o cex-gen.o pg-r4k.o tlb-r4k.o
+obj-$(CONFIG_CPU_RM9000)	+= c-r4k.o cex-gen.o pg-r4k.o tlb-r4k.o
 obj-$(CONFIG_CPU_SB1)		+= c-sb1.o cerr-sb1.o cex-sb1.o pg-sb1.o \
 				   tlb-sb1.o
-obj-$(CONFIG_CPU_TX39XX)	+= c-tx39.o pg-r3k.o tlb-r3k.o tlbex-r3k.o
-obj-$(CONFIG_CPU_TX49XX)	+= c-r4k.o cex-gen.o tlb-r4k.o
-obj-$(CONFIG_CPU_VR41XX)	+= c-r4k.o cex-gen.o tlb-r4k.o
+obj-$(CONFIG_CPU_TX39XX)	+= c-tx39.o pg-r4k.o tlb-r3k.o tlbex-r3k.o
+obj-$(CONFIG_CPU_TX49XX)	+= c-r4k.o cex-gen.o pg-r4k.o tlb-r4k.o
+obj-$(CONFIG_CPU_VR41XX)	+= c-r4k.o cex-gen.o pg-r4k.o tlb-r4k.o
 
 obj-$(CONFIG_CPU_RM7000)	+= sc-rm7k.o
 obj-$(CONFIG_R5000_CPU_SCACHE)  += sc-r5k.o
 obj-$(CONFIG_SGI_IP22)		+= sc-ip22.o
 
+#
+# Choose one DMA coherency model
+#
+obj-$(CONFIG_DMA_COHERENT)	+= dma-coherent.o
+obj-$(CONFIG_DMA_NONCOHERENT)	+= dma-noncoherent.o
+obj-$(CONFIG_DMA_IP27)		+= dma-ip27.o
+
 EXTRA_AFLAGS := $(CFLAGS)
--- diff/arch/mips/mm/c-r3k.c	2003-07-08 09:55:17.000000000 +0100
+++ source/arch/mips/mm/c-r3k.c	2004-02-23 13:56:38.000000000 +0000
@@ -23,9 +23,6 @@
 #include <asm/bootinfo.h>
 #include <asm/cpu.h>
 
-void r3k_clear_page(void * page);
-void r3k_copy_page(void * to, void * from);
-
 static unsigned long icache_size, dcache_size;		/* Size in bytes */
 static unsigned long icache_lsize, dcache_lsize;	/* Size in bytes */
 
@@ -244,6 +241,7 @@ static inline void r3k_flush_cache_all(v
 
 static inline void r3k___flush_cache_all(void)
 {
+	r3k_flush_dcache_range(KSEG0, KSEG0 + dcache_size);
 	r3k_flush_icache_range(KSEG0, KSEG0 + icache_size);
 }
 
@@ -319,8 +317,8 @@ static void r3k_dma_cache_wback_inv(unsi
 
 void __init ld_mmu_r23000(void)
 {
-	_clear_page = r3k_clear_page;
-	_copy_page = r3k_copy_page;
+	extern void build_clear_page(void);
+	extern void build_copy_page(void);
 
 	r3k_probe_cache();
 
@@ -341,4 +339,7 @@ void __init ld_mmu_r23000(void)
 		icache_size >> 10, icache_lsize);
 	printk("Primary data cache %ldkB, linesize %ld bytes.\n",
 		dcache_size >> 10, dcache_lsize);
+
+	build_clear_page();
+	build_copy_page();
 }
--- diff/arch/mips/mm/c-r4k.c	2003-08-20 14:16:25.000000000 +0100
+++ source/arch/mips/mm/c-r4k.c	2004-02-23 13:56:38.000000000 +0000
@@ -18,6 +18,7 @@
 #include <asm/bootinfo.h>
 #include <asm/cacheops.h>
 #include <asm/cpu.h>
+#include <asm/cpu-features.h>
 #include <asm/io.h>
 #include <asm/page.h>
 #include <asm/pgtable.h>
@@ -28,27 +29,6 @@
 
 static unsigned long icache_size, dcache_size, scache_size;
 
-extern void andes_clear_page(void * page);
-extern void r4k_clear_page32_d16(void * page);
-extern void r4k_clear_page32_d32(void * page);
-extern void r4k_clear_page_d16(void * page);
-extern void r4k_clear_page_d32(void * page);
-extern void r4k_clear_page_r4600_v1(void * page);
-extern void r4k_clear_page_r4600_v2(void * page);
-extern void r4k_clear_page_s16(void * page);
-extern void r4k_clear_page_s32(void * page);
-extern void r4k_clear_page_s64(void * page);
-extern void r4k_clear_page_s128(void * page);
-extern void andes_copy_page(void * to, void * from);
-extern void r4k_copy_page_d16(void * to, void * from);
-extern void r4k_copy_page_d32(void * to, void * from);
-extern void r4k_copy_page_r4600_v1(void * to, void * from);
-extern void r4k_copy_page_r4600_v2(void * to, void * from);
-extern void r4k_copy_page_s16(void * to, void * from);
-extern void r4k_copy_page_s32(void * to, void * from);
-extern void r4k_copy_page_s64(void * to, void * from);
-extern void r4k_copy_page_s128(void * to, void * from);
-
 /*
  * Dummy cache handling routines for machines without boardcaches
  */
@@ -63,247 +43,215 @@ static struct bcache_ops no_sc_ops = {
 
 struct bcache_ops *bcops = &no_sc_ops;
 
+#define cpu_is_r4600_v1_x()	((read_c0_prid() & 0xfffffff0) == 0x2010)
+#define cpu_is_r4600_v2_x()	((read_c0_prid() & 0xfffffff0) == 0x2020)
+
 #define R4600_HIT_CACHEOP_WAR_IMPL					\
 do {									\
-	if (R4600_V2_HIT_CACHEOP_WAR &&					\
-	    (read_c0_prid() & 0xfff0) == 0x2020) {	/* R4600 V2.0 */\
+	if (R4600_V2_HIT_CACHEOP_WAR && cpu_is_r4600_v2_x())		\
 		*(volatile unsigned long *)KSEG1;			\
-	}								\
 	if (R4600_V1_HIT_CACHEOP_WAR)					\
 		__asm__ __volatile__("nop;nop;nop;nop");		\
 } while (0)
 
-static void r4k_blast_dcache_page(unsigned long addr)
-{
-	static void *l = &&init;
-	unsigned long dc_lsize;
-
-	goto *l;
+static void (*r4k_blast_dcache_page)(unsigned long addr);
 
-dc_16:
-	blast_dcache16_page(addr);
-	return;
-
-dc_32:
+static inline void r4k_blast_dcache_page_dc32(unsigned long addr)
+{
 	R4600_HIT_CACHEOP_WAR_IMPL;
 	blast_dcache32_page(addr);
-	return;
+}
 
-init:
-	dc_lsize = current_cpu_data.dcache.linesz;
+static inline void r4k_blast_dcache_page_setup(void)
+{
+	unsigned long  dc_lsize = cpu_dcache_line_size();
 
 	if (dc_lsize == 16)
-		l = &&dc_16;
+		r4k_blast_dcache_page = blast_dcache16_page;
 	else if (dc_lsize == 32)
-		l = &&dc_32;
-	goto *l;
+		r4k_blast_dcache_page = r4k_blast_dcache_page_dc32;
 }
 
-static void r4k_blast_dcache_page_indexed(unsigned long addr)
-{
-	static void *l = &&init;
-	unsigned long dc_lsize;
-
-	goto *l;
-
-dc_16:
-	blast_dcache16_page_indexed(addr);
-	return;
-
-dc_32:
-	blast_dcache32_page_indexed(addr);
-	return;
+static void (* r4k_blast_dcache_page_indexed)(unsigned long addr);
 
-init:
-	dc_lsize = current_cpu_data.dcache.linesz;
+static inline void r4k_blast_dcache_page_indexed_setup(void)
+{
+	unsigned long dc_lsize = cpu_dcache_line_size();
 
 	if (dc_lsize == 16)
-		l = &&dc_16;
+		r4k_blast_dcache_page_indexed = blast_dcache16_page_indexed;
 	else if (dc_lsize == 32)
-		l = &&dc_32;
-	goto *l;
+		r4k_blast_dcache_page_indexed = blast_dcache32_page_indexed;
 }
 
-static void r4k_blast_dcache(void)
-{
-	static void *l = &&init;
-	unsigned long dc_lsize;
-
-	goto *l;
+static void (* r4k_blast_dcache)(void);
 
-dc_16:
-	blast_dcache16();
-	return;
-
-dc_32:
-	blast_dcache32();
-	return;
-
-init:
-	dc_lsize = current_cpu_data.dcache.linesz;
+static void r4k_blast_dcache_setup(void)
+{
+	unsigned long dc_lsize = cpu_dcache_line_size();
 
 	if (dc_lsize == 16)
-		l = &&dc_16;
+		r4k_blast_dcache = blast_dcache16;
 	else if (dc_lsize == 32)
-		l = &&dc_32;
-	goto *l;
+		r4k_blast_dcache = blast_dcache32;
 }
 
-static void r4k_blast_icache_page(unsigned long addr)
-{
-	unsigned long ic_lsize = current_cpu_data.icache.linesz;
-	static void *l = &&init;
-
-	goto *l;
+/* force code alignment (used for TX49XX_ICACHE_INDEX_INV_WAR) */
+#define JUMP_TO_ALIGN(order) \
+	__asm__ __volatile__( \
+		"b\t1f\n\t" \
+		".align\t" #order "\n\t" \
+		"1:\n\t" \
+		)
+#define CACHE32_UNROLL32_ALIGN	JUMP_TO_ALIGN(10) /* 32 * 32 = 1024 */
+#define CACHE32_UNROLL32_ALIGN2	JUMP_TO_ALIGN(11)
 
-ic_16:
-	blast_icache16_page(addr);
-	return;
-
-ic_32:
-	blast_icache32_page(addr);
-	return;
+static inline void blast_r4600_v1_icache32(void)
+{
+	unsigned long flags;
 
-ic_64:
-	blast_icache64_page(addr);
-	return;
+	local_irq_save(flags);
+	blast_icache32();
+	local_irq_restore(flags);
+}
 
-init:
-	if (ic_lsize == 16)
-		l = &&ic_16;
-	else if (ic_lsize == 32)
-		l = &&ic_32;
-	else if (ic_lsize == 64)
-		l = &&ic_64;
-	goto *l;
+static inline void tx49_blast_icache32(void)
+{
+	unsigned long start = INDEX_BASE;
+	unsigned long end = start + current_cpu_data.icache.waysize;
+	unsigned long ws_inc = 1UL << current_cpu_data.icache.waybit;
+	unsigned long ws_end = current_cpu_data.icache.ways <<
+	                       current_cpu_data.icache.waybit;
+	unsigned long ws, addr;
+
+	CACHE32_UNROLL32_ALIGN2;
+	/* I'm in even chunk.  blast odd chunks */
+	for (ws = 0; ws < ws_end; ws += ws_inc) 
+		for (addr = start + 0x400; addr < end; addr += 0x400 * 2) 
+			cache32_unroll32(addr|ws,Index_Invalidate_I);
+	CACHE32_UNROLL32_ALIGN;
+	/* I'm in odd chunk.  blast even chunks */
+	for (ws = 0; ws < ws_end; ws += ws_inc) 
+		for (addr = start; addr < end; addr += 0x400 * 2) 
+			cache32_unroll32(addr|ws,Index_Invalidate_I);
 }
 
-static void r4k_blast_icache_page_indexed(unsigned long addr)
+static inline void blast_icache32_r4600_v1_page_indexed(unsigned long page)
 {
-	unsigned long ic_lsize = current_cpu_data.icache.linesz;
-	static void *l = &&init;
+	unsigned long flags;
 
-	goto *l;
+	local_irq_save(flags);
+	blast_icache32_page_indexed(page);
+	local_irq_restore(flags);
+}
 
-ic_16:
-	blast_icache16_page_indexed(addr);
-	return;
+static inline void tx49_blast_icache32_page_indexed(unsigned long page)
+{
+	unsigned long start = page;
+	unsigned long end = start + PAGE_SIZE;
+	unsigned long ws_inc = 1UL << current_cpu_data.icache.waybit;
+	unsigned long ws_end = current_cpu_data.icache.ways <<
+	                       current_cpu_data.icache.waybit;
+	unsigned long ws, addr;
+
+	CACHE32_UNROLL32_ALIGN2;
+	/* I'm in even chunk.  blast odd chunks */
+	for (ws = 0; ws < ws_end; ws += ws_inc) 
+		for (addr = start + 0x400; addr < end; addr += 0x400 * 2) 
+			cache32_unroll32(addr|ws,Index_Invalidate_I);
+	CACHE32_UNROLL32_ALIGN;
+	/* I'm in odd chunk.  blast even chunks */
+	for (ws = 0; ws < ws_end; ws += ws_inc) 
+		for (addr = start; addr < end; addr += 0x400 * 2) 
+			cache32_unroll32(addr|ws,Index_Invalidate_I);
+}
 
-ic_32:
-	blast_icache32_page_indexed(addr);
-	return;
+static void (* r4k_blast_icache_page)(unsigned long addr);
 
-ic_64:
-	blast_icache64_page_indexed(addr);
-	return;
+static inline void r4k_blast_icache_page_setup(void)
+{
+	unsigned long ic_lsize = cpu_icache_line_size();
 
-init:
 	if (ic_lsize == 16)
-		l = &&ic_16;
+		r4k_blast_icache_page = blast_icache16_page;
 	else if (ic_lsize == 32)
-		l = &&ic_32;
+		r4k_blast_icache_page = blast_icache32_page;
 	else if (ic_lsize == 64)
-		l = &&ic_64;
-	goto *l;
+		r4k_blast_icache_page = blast_icache64_page;
 }
 
-static void r4k_blast_icache(void)
-{
-	unsigned long ic_lsize = current_cpu_data.icache.linesz;
-	static void *l = &&init;
 
-	goto *l;
+static void (* r4k_blast_icache_page_indexed)(unsigned long addr);
 
-ic_16:
-	blast_icache16();
-	return;
-
-ic_32:
-	blast_icache32();
-	return;
-
-ic_64:
-	blast_icache64();
-	return;
+static inline void r4k_blast_icache_page_indexed_setup(void)
+{
+	unsigned long ic_lsize = cpu_icache_line_size();
 
-init:
 	if (ic_lsize == 16)
-		l = &&ic_16;
-	else if (ic_lsize == 32)
-		l = &&ic_32;
-	else if (ic_lsize == 64)
-		l = &&ic_64;
-	goto *l;
+		r4k_blast_icache_page_indexed = blast_icache16_page_indexed;
+	else if (ic_lsize == 32) {
+		if (TX49XX_ICACHE_INDEX_INV_WAR)
+			r4k_blast_icache_page_indexed =
+				tx49_blast_icache32_page_indexed;
+		else if (R4600_V1_INDEX_ICACHEOP_WAR && cpu_is_r4600_v1_x())
+			r4k_blast_icache_page_indexed =
+				blast_icache32_r4600_v1_page_indexed;
+		else
+			r4k_blast_icache_page_indexed =
+				blast_icache32_page_indexed;
+	} else if (ic_lsize == 64)
+		r4k_blast_icache_page_indexed = blast_icache64_page_indexed;
 }
 
-static void r4k_blast_scache_page(unsigned long addr)
-{
-	unsigned long sc_lsize = current_cpu_data.scache.linesz;
-	static void *l = &&init;
-
-	goto *l;
+static void (* r4k_blast_icache)(void);
 
-sc_16:
-	blast_scache16_page(addr);
-	return;
+static inline void r4k_blast_icache_setup(void)
+{
+	unsigned long ic_lsize = cpu_icache_line_size();
 
-sc_32:
-	blast_scache32_page(addr);
-	return;
+	if (ic_lsize == 16)
+		r4k_blast_icache = blast_icache16;
+	else if (ic_lsize == 32) {
+		if (R4600_V1_INDEX_ICACHEOP_WAR && cpu_is_r4600_v1_x())
+			r4k_blast_icache = blast_r4600_v1_icache32;
+		else if (TX49XX_ICACHE_INDEX_INV_WAR)
+			r4k_blast_icache = tx49_blast_icache32;
+		else
+			r4k_blast_icache = blast_icache32;
+	} else if (ic_lsize == 64)
+		r4k_blast_icache = blast_icache64;
+}
 
-sc_64:
-	blast_scache64_page(addr);
-	return;
+static void (* r4k_blast_scache_page)(unsigned long addr);
 
-sc_128:
-	blast_scache128_page(addr);
-	return;
+static inline void r4k_blast_scache_page_setup(void)
+{
+	unsigned long sc_lsize = cpu_scache_line_size();
 
-init:
 	if (sc_lsize == 16)
-		l = &&sc_16;
+		r4k_blast_scache_page = blast_scache16_page;
 	else if (sc_lsize == 32)
-		l = &&sc_32;
+		r4k_blast_scache_page = blast_scache32_page;
 	else if (sc_lsize == 64)
-		l = &&sc_64;
+		r4k_blast_scache_page = blast_scache64_page;
 	else if (sc_lsize == 128)
-		l = &&sc_128;
-	goto *l;
+		r4k_blast_scache_page = blast_scache128_page;
 }
 
-static void r4k_blast_scache(void)
-{
-	unsigned long sc_lsize = current_cpu_data.scache.linesz;
-	static void *l = &&init;
-
-	goto *l;
-
-sc_16:
-	blast_scache16();
-	return;
-
-sc_32:
-	blast_scache32();
-	return;
-
-sc_64:
-	blast_scache64();
-	return;
+static void (* r4k_blast_scache)(void);
 
-sc_128:
-	blast_scache128();
-	return;
+static inline void r4k_blast_scache_setup(void)
+{
+	unsigned long sc_lsize = cpu_scache_line_size();
 
-init:
 	if (sc_lsize == 16)
-		l = &&sc_16;
+		r4k_blast_scache = blast_scache16;
 	else if (sc_lsize == 32)
-		l = &&sc_32;
+		r4k_blast_scache = blast_scache32;
 	else if (sc_lsize == 64)
-		l = &&sc_64;
+		r4k_blast_scache = blast_scache64;
 	else if (sc_lsize == 128)
-		l = &&sc_128;
-	goto *l;
+		r4k_blast_scache = blast_scache128;
 }
 
 static void r4k_flush_cache_all(void)
@@ -334,11 +282,16 @@ static void r4k___flush_cache_all(void)
 static void r4k_flush_cache_range(struct vm_area_struct *vma,
 	unsigned long start, unsigned long end)
 {
-	if (cpu_context(smp_processor_id(), vma->vm_mm) != 0) {
+	int exec;
+
+	if (!(cpu_context(smp_processor_id(), vma->vm_mm)))
+		return;
+
+	exec = vma->vm_flags & VM_EXEC;
+	if (cpu_has_dc_aliases || exec)
 		r4k_blast_dcache();
-		if (vma->vm_flags & VM_EXEC)
-			r4k_blast_icache();
-	}
+	if (exec)
+		r4k_blast_icache();
 }
 
 static void r4k_flush_cache_mm(struct mm_struct *mm)
@@ -410,7 +363,7 @@ static void r4k_flush_cache_page(struct 
 	 * Do indexed flush, too much work to get the (possible) TLB refills
 	 * to work correctly.
 	 */
-	page = (KSEG0 + (page & (dcache_size - 1)));
+	page = INDEX_BASE + (page & (dcache_size - 1));
 	if (cpu_has_dc_aliases || (exec && !cpu_has_ic_fills_f_dc))
 		r4k_blast_dcache_page_indexed(page);
 	if (exec) {
@@ -493,7 +446,9 @@ static void r4k_flush_icache_page(struct
 	 */
 	if (cpu_has_subset_pcaches) {
 		unsigned long addr = (unsigned long) page_address(page);
+
 		r4k_blast_scache_page(addr);
+		ClearPageDcacheDirty(page);
 
 		return;
 	}
@@ -501,6 +456,7 @@ static void r4k_flush_icache_page(struct
 	if (!cpu_has_ic_fills_f_dc) {
 		unsigned long addr = (unsigned long) page_address(page);
 		r4k_blast_dcache_page(addr);
+		ClearPageDcacheDirty(page);
 	}
 
 	/*
@@ -516,7 +472,7 @@ static void r4k_flush_icache_page(struct
 		r4k_blast_icache();
 }
 
-#ifdef CONFIG_NONCOHERENT_IO
+#ifdef CONFIG_DMA_NONCOHERENT
 
 static void r4k_dma_cache_wback_inv(unsigned long addr, unsigned long size)
 {
@@ -606,7 +562,7 @@ static void r4k_dma_cache_inv(unsigned l
 
 	bc_inv(addr, size);
 }
-#endif /* CONFIG_NONCOHERENT_IO */
+#endif /* CONFIG_DMA_NONCOHERENT */
 
 /*
  * While we're protected against bad userland addresses we don't care
@@ -621,6 +577,26 @@ static void r4k_flush_cache_sigtramp(uns
 	R4600_HIT_CACHEOP_WAR_IMPL;
 	protected_writeback_dcache_line(addr & ~(dc_lsize - 1));
 	protected_flush_icache_line(addr & ~(ic_lsize - 1));
+	if (MIPS4K_ICACHE_REFILL_WAR) {
+		__asm__ __volatile__ (
+			".set push\n\t"
+			".set noat\n\t"
+			".set mips3\n\t"
+#if CONFIG_MIPS32
+			"la	$at,1f\n\t"
+#endif
+#if CONFIG_MIPS64
+			"dla	$at,1f\n\t"
+#endif
+			"cache	%0,($at)\n\t"
+			"nop; nop; nop\n"
+			"1:\n\t"
+			".set pop"
+			:
+			: "i" (Hit_Invalidate_I));
+	}
+	if (MIPS_CACHE_SYNC_WAR)
+		__asm__ __volatile__ ("sync");
 }
 
 static void r4k_flush_icache_all(void)
@@ -638,7 +614,7 @@ static inline void rm7k_erratum31(void)
 	write_c0_taglo(0);
 	write_c0_taghi(0);
 
-	for (addr = KSEG0; addr <= KSEG0 + 4096; addr += ic_lsize) {
+	for (addr = INDEX_BASE; addr <= INDEX_BASE + 4096; addr += ic_lsize) {
 		__asm__ __volatile__ (
 			".set noreorder\n\t"
 			".set mips3\n\t"
@@ -687,6 +663,8 @@ static void __init probe_pcache(void)
 		c->dcache.linesz = 16 << ((config & CONF_DB) >> 4);
 		c->dcache.ways = 2;
 		c->dcache.waybit= ffs(dcache_size/2) - 1;
+
+		c->options |= MIPS_CPU_CACHE_CDEX_P;
 		break;
 
 	case CPU_R5432:
@@ -700,6 +678,8 @@ static void __init probe_pcache(void)
 		c->dcache.linesz = 16 << ((config & CONF_DB) >> 4);
 		c->dcache.ways = 2;
 		c->dcache.waybit = 0;
+
+		c->options |= MIPS_CPU_CACHE_CDEX_P;
 		break;
 
 	case CPU_TX49XX:
@@ -712,6 +692,8 @@ static void __init probe_pcache(void)
 		c->dcache.linesz = 16 << ((config & CONF_DB) >> 4);
 		c->dcache.ways = 4;
 		c->dcache.waybit = 0;
+
+		c->options |= MIPS_CPU_CACHE_CDEX_P;
 		break;
 
 	case CPU_R4000PC:
@@ -730,6 +712,8 @@ static void __init probe_pcache(void)
 		c->dcache.linesz = 16 << ((config & CONF_DB) >> 4);
 		c->dcache.ways = 1;
 		c->dcache.waybit = 0;	/* does not matter */
+
+		c->options |= MIPS_CPU_CACHE_CDEX_P;
 		break;
 
 	case CPU_R10000:
@@ -743,9 +727,20 @@ static void __init probe_pcache(void)
 		c->dcache.linesz = 32;
 		c->dcache.ways = 2;
 		c->dcache.waybit = 0;
+
+		c->options |= MIPS_CPU_PREFETCH;
 		break;
 
+	case CPU_VR4133:
+		write_c0_config(config & ~CONF_EB);
 	case CPU_VR4131:
+		/* Workaround for cache instruction bug of VR4131 */
+		if (c->processor_id == 0x0c80U || c->processor_id == 0x0c81U ||
+		    c->processor_id == 0x0c82U) {
+			config &= ~0x00000030U;
+			config |= 0x00410000U;
+			write_c0_config(config);
+		}
 		icache_size = 1 << (10 + ((config & CONF_IC) >> 9));
 		c->icache.linesz = 16 << ((config & CONF_IB) >> 5);
 		c->icache.ways = 2;
@@ -755,6 +750,8 @@ static void __init probe_pcache(void)
 		c->dcache.linesz = 16 << ((config & CONF_DB) >> 4);
 		c->dcache.ways = 2;
 		c->dcache.waybit = ffs(dcache_size/2) - 1;
+
+		c->options |= MIPS_CPU_CACHE_CDEX_P;
 		break;
 
 	case CPU_VR41XX:
@@ -772,11 +769,14 @@ static void __init probe_pcache(void)
 		c->dcache.linesz = 16 << ((config & CONF_DB) >> 4);
 		c->dcache.ways = 1;
 		c->dcache.waybit = 0;	/* does not matter */
+
+		c->options |= MIPS_CPU_CACHE_CDEX_P;
 		break;
 
 	case CPU_RM7000:
 		rm7k_erratum31();
 
+	case CPU_RM9000:
 		icache_size = 1 << (12 + ((config & CONF_IC) >> 9));
 		c->icache.linesz = 16 << ((config & CONF_IB) >> 5);
 		c->icache.ways = 4;
@@ -786,6 +786,8 @@ static void __init probe_pcache(void)
 		c->dcache.linesz = 16 << ((config & CONF_DB) >> 4);
 		c->dcache.ways = 4;
 		c->dcache.waybit = ffs(dcache_size / c->dcache.ways) - 1;
+
+		c->options |= MIPS_CPU_CACHE_CDEX_P | MIPS_CPU_PREFETCH;
 		break;
 
 	default:
@@ -810,6 +812,9 @@ static void __init probe_pcache(void)
 		              c->icache.linesz;
 		c->icache.waybit = ffs(icache_size/c->icache.ways) - 1;
 
+		if (config & 0x8)		/* VI bit */
+			c->icache.flags |= MIPS_CACHE_VTAG;
+
 		/*
 		 * Now probe the MIPS32 / MIPS64 data cache.
 		 */
@@ -826,6 +831,8 @@ static void __init probe_pcache(void)
 		              c->dcache.ways *
 		              c->dcache.linesz;
 		c->dcache.waybit = ffs(dcache_size/c->dcache.ways) - 1;
+
+		c->options |= MIPS_CPU_PREFETCH;
 		break;
 	}
 
@@ -859,9 +866,6 @@ static void __init probe_pcache(void)
 		if (c->dcache.waysize > PAGE_SIZE)
 		        c->dcache.flags |= MIPS_CACHE_ALIASES;
 
-	if (config & 0x8)		/* VI bit */
-		c->icache.flags |= MIPS_CACHE_VTAG;
-
 	switch (c->cputype) {
 	case CPU_20KC:
 		/*
@@ -949,71 +953,6 @@ static int __init probe_scache(void)
 	return 1;
 }
 
-static void __init setup_noscache_funcs(void)
-{
-	unsigned int prid;
-
-	switch (current_cpu_data.dcache.linesz) {
-	case 16:
-		if (cpu_has_64bits)
-			_clear_page = r4k_clear_page_d16;
-		else
-			_clear_page = r4k_clear_page32_d16;
-		_copy_page = r4k_copy_page_d16;
-
-		break;
-	case 32:
-		prid = read_c0_prid() & 0xfff0;
-		if (prid == 0x2010) {			/* R4600 V1.7 */
-			_clear_page = r4k_clear_page_r4600_v1;
-			_copy_page = r4k_copy_page_r4600_v1;
-		} else if (prid == 0x2020) {		/* R4600 V2.0 */
-			_clear_page = r4k_clear_page_r4600_v2;
-			_copy_page = r4k_copy_page_r4600_v2;
-		} else {
-			if (cpu_has_64bits)
-				_clear_page = r4k_clear_page_d32;
-			else
-				_clear_page = r4k_clear_page32_d32;
-			_copy_page = r4k_copy_page_d32;
-		}
-		break;
-	}
-}
-
-static void __init setup_scache_funcs(void)
-{
-	struct cpuinfo_mips *c = &current_cpu_data;
-
-	if (c->dcache.linesz > c->scache.linesz)
-		panic("Invalid primary cache configuration detected");
-
-	if (c->cputype == CPU_R10000 || c->cputype == CPU_R12000) {
-		_clear_page = andes_clear_page;
-		_copy_page = andes_copy_page;
-		return;
-	}
-
-	switch (c->scache.linesz) {
-	case 16:
-		_clear_page = r4k_clear_page_s16;
-		_copy_page = r4k_copy_page_s16;
-		break;
-	case 32:
-		_clear_page = r4k_clear_page_s32;
-		_copy_page = r4k_copy_page_s32;
-		break;
-	case 64:
-		_clear_page = r4k_clear_page_s64;
-		_copy_page = r4k_copy_page_s64;
-		break;
-	case 128:
-		_clear_page = r4k_clear_page_s128;
-		_copy_page = r4k_copy_page_s128;
-		break;
-	}
-}
-
 typedef int (*probe_func_t)(unsigned long);
 extern int r5k_sc_init(void);
 extern int rm7k_sc_init(void);
@@ -1031,14 +970,14 @@ static void __init setup_scache(void)
 	 * Linux memory managment.
 	 */
 	switch (c->cputype) {
-	case CPU_R4000PC:
 	case CPU_R4000SC:
 	case CPU_R4000MC:
-	case CPU_R4400PC:
 	case CPU_R4400SC:
 	case CPU_R4400MC:
 		probe_scache_kseg1 = (probe_func_t) (KSEG1ADDR(&probe_scache));
 		sc_present = probe_scache_kseg1(config);
+		if (sc_present)
+			c->options |= MIPS_CPU_CACHE_CDEX_S;
 		break;
 
 	case CPU_R10000:
@@ -1052,14 +991,13 @@ static void __init setup_scache(void)
 
 	case CPU_R5000:
 	case CPU_NEVADA:
-		setup_noscache_funcs();
 #ifdef CONFIG_R5000_CPU_SCACHE
 		r5k_sc_init();
 #endif
                 return;
 
 	case CPU_RM7000:
-		setup_noscache_funcs();
+	case CPU_RM9000:
 #ifdef CONFIG_RM7000_CPU_SCACHE
 		rm7k_sc_init();
 #endif
@@ -1069,10 +1007,8 @@ static void __init setup_scache(void)
 		sc_present = 0;
 	}
 
-	if (!sc_present) {
-		setup_noscache_funcs();
+	if (!sc_present)
 		return;
-	}
 
 	if ((c->isa_level == MIPS_CPU_ISA_M32 ||
 	     c->isa_level == MIPS_CPU_ISA_M64) &&
@@ -1088,7 +1024,6 @@ static void __init setup_scache(void)
 	       scache_size >> 10, way_string[c->scache.ways], c->scache.linesz);
 
 	c->options |= MIPS_CPU_SUBSET_CACHES;
-        setup_scache_funcs();
 }
 
 static inline void coherency_setup(void)
@@ -1112,29 +1047,38 @@ static inline void coherency_setup(void)
 		clear_c0_config(CONF_CU);
 		break;
 	}
-
 }
 
 void __init ld_mmu_r4xx0(void)
 {
+	extern void build_clear_page(void);
+	extern void build_copy_page(void);
 	extern char except_vec2_generic;
 	struct cpuinfo_mips *c = &current_cpu_data;
 
 	/* Default cache error handler for R4000 and R5000 family */
-	memcpy((void *)(KSEG0 + 0x100), &except_vec2_generic, 0x80);
-	memcpy((void *)(KSEG1 + 0x100), &except_vec2_generic, 0x80);
+	memcpy((void *)(CAC_BASE   + 0x100), &except_vec2_generic, 0x80);
+	memcpy((void *)(UNCAC_BASE + 0x100), &except_vec2_generic, 0x80);
 
 	probe_pcache();
 	setup_scache();
-	coherency_setup();
 
 	if (c->dcache.sets * c->dcache.ways > PAGE_SIZE)
 		c->dcache.flags |= MIPS_CACHE_ALIASES;
 
+	r4k_blast_dcache_page_setup();
+	r4k_blast_dcache_page_indexed_setup();
+	r4k_blast_dcache_setup();
+	r4k_blast_icache_page_setup();
+	r4k_blast_icache_page_indexed_setup();
+	r4k_blast_icache_setup();
+	r4k_blast_scache_page_setup();
+	r4k_blast_scache_setup();
+
 	/*
 	 * Some MIPS32 and MIPS64 processors have physically indexed caches.
 	 * This code supports virtually indexed processors and will be
-	 * unnecessarily unefficient on physically indexed processors.
+	 * unnecessarily inefficient on physically indexed processors.
 	 */
 	shm_align_mask = max_t( unsigned long,
 				c->dcache.sets * c->dcache.linesz - 1,
@@ -1152,11 +1096,15 @@ void __init ld_mmu_r4xx0(void)
 	flush_data_cache_page	= r4k_flush_data_cache_page;
 	flush_icache_range	= r4k_flush_icache_range;
 
-#ifdef CONFIG_NONCOHERENT_IO
+#ifdef CONFIG_DMA_NONCOHERENT
 	_dma_cache_wback_inv	= r4k_dma_cache_wback_inv;
 	_dma_cache_wback	= r4k_dma_cache_wback_inv;
 	_dma_cache_inv		= r4k_dma_cache_inv;
 #endif
 
 	__flush_cache_all();
+	coherency_setup();
+
+	build_clear_page();
+	build_copy_page();
 }
--- diff/arch/mips/mm/c-sb1.c	2003-08-20 14:16:25.000000000 +0100
+++ source/arch/mips/mm/c-sb1.c	2004-02-23 13:56:38.000000000 +0000
@@ -1,7 +1,7 @@
 /*
  * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
  * Copyright (C) 1997, 2001 Ralf Baechle (ralf@gnu.org)
- * Copyright (C) 2000, 2001 Broadcom Corporation
+ * Copyright (C) 2000, 2001, 2002, 2003 Broadcom Corporation
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
@@ -25,14 +25,7 @@
 #include <asm/cpu.h>
 #include <asm/uaccess.h>
 
-#ifdef CONFIG_SIBYTE_DMA_PAGEOPS
 extern void sb1_dma_init(void);
-extern void sb1_clear_page_dma(void * page);
-extern void sb1_copy_page_dma(void * to, void * from);
-#else
-extern void sb1_clear_page(void * page);
-extern void sb1_copy_page(void * to, void * from);
-#endif
 
 /* These are probed at ld_mmu time */
 static unsigned long icache_size;
@@ -85,6 +78,11 @@ static unsigned int dcache_range_cutoff;
 	"	sync				\n"			\
 	"	.set	mips0")
 
+#define mispredict()							\
+	__asm__ __volatile__(						\
+	"	bnezl  $0, 1f		\n" /* Force mispredict */	\
+	"1:				\n");
+
 /*
  * Writeback and invalidate the entire dcache
  */
@@ -107,14 +105,18 @@ static inline void __sb1_writeback_inv_d
 static inline void __sb1_writeback_inv_dcache_range(unsigned long start,
 	unsigned long end)
 {
+	unsigned long index;
+
 	start &= ~(dcache_line_size - 1);
 	end = (end + dcache_line_size - 1) & ~(dcache_line_size - 1);
 
 	while (start != end) {
-		cache_set_op(Index_Writeback_Inv_D, start);
-		cache_set_op(Index_Writeback_Inv_D, start ^ (1<<12));
+		index = start & dcache_index_mask;
+		cache_set_op(Index_Writeback_Inv_D, index);
+		cache_set_op(Index_Writeback_Inv_D, index ^ (1<<12));
 		start += dcache_line_size;
 	}
+	sync();
 }
 
 /*
@@ -194,6 +196,7 @@ static void sb1_flush_cache_page(struct 
 	if (!(vma->vm_flags & VM_EXEC))
 		return;
 
+	addr &= PAGE_MASK;
 	args.vma = vma;
 	args.addr = addr;
 	on_each_cpu(sb1_flush_cache_page_ipi, (void *) &args, 1, 1);
@@ -219,11 +222,7 @@ static inline void __sb1_flush_icache_ra
 		cache_set_op(Index_Invalidate_I, start & icache_index_mask);
 		start += icache_line_size;
 	}
-
-	__asm__ __volatile__(
-	"	bnezl  $0, 1f		\n" /* Force mispredict */
-	"1:				\n");
-
+	mispredict();
 	sync();
 }
 
@@ -362,31 +361,10 @@ asm("sb1_flush_icache_page = local_sb1_f
  */
 static void local_sb1_flush_cache_sigtramp(unsigned long addr)
 {
-	__asm__ __volatile__ (
-	"	.set	push		\n"
-	"	.set	noreorder	\n"
-	"	.set	noat		\n"
-	"	.set	mips4		\n"
-	"	cache	%2, (0<<13)(%0)	\n" /* Index-inval this address */
-	"	cache	%2, (1<<13)(%0)	\n" /* Index-inval this address */
-	"	cache	%2, (2<<13)(%0)	\n" /* Index-inval this address */
-	"	cache	%2, (3<<13)(%0)	\n" /* Index-inval this address */
-	"	xori	$1, %0, 1<<12	\n" /* Flip index bit 12	*/
-	"	cache	%2, (0<<13)($1)	\n" /* Index-inval this address */
-	"	cache	%2, (1<<13)($1)	\n" /* Index-inval this address */
-	"	cache	%2, (2<<13)($1)	\n" /* Index-inval this address */
-	"	cache	%2, (3<<13)($1)	\n" /* Index-inval this address */
-	"	cache	%3, (0<<13)(%1)	\n" /* Index-inval this address */
-	"	cache	%3, (1<<13)(%1)	\n" /* Index-inval this address */
-	"	cache	%3, (2<<13)(%1)	\n" /* Index-inval this address */
-	"	cache	%3, (3<<13)(%1)	\n" /* Index-inval this address */
-	"	bnezl	$0, 1f		\n" /* Force mispredict */
-	"	 nop			\n"
-	"1:                             \n"
-	"	.set	pop		\n"
-	:
-	: "r" (addr & dcache_index_mask), "r" (addr & icache_index_mask),
-	  "i" (Index_Writeback_Inv_D), "i" (Index_Invalidate_I));
+	cache_set_op(Index_Writeback_Inv_D, addr & dcache_index_mask);
+	cache_set_op(Index_Writeback_Inv_D, (addr ^ (1<<12)) & dcache_index_mask);
+	cache_set_op(Index_Invalidate_I, addr & icache_index_mask);
+	mispredict();
 }
 
 #ifdef CONFIG_SMP
@@ -504,20 +482,17 @@ static __init void probe_cache_sizes(voi
 void ld_mmu_sb1(void)
 {
 	extern char except_vec2_sb1;
+	extern char handle_vec2_sb1;
 
 	/* Special cache error handler for SB1 */
-	memcpy((void *)(KSEG0 + 0x100), &except_vec2_sb1, 0x80);
-	memcpy((void *)(KSEG1 + 0x100), &except_vec2_sb1, 0x80);
+	memcpy((void *)(CAC_BASE   + 0x100), &except_vec2_sb1, 0x80);
+	memcpy((void *)(UNCAC_BASE + 0x100), &except_vec2_sb1, 0x80);
+	memcpy((void *)KSEG1ADDR(&handle_vec2_sb1), &handle_vec2_sb1, 0x80);
 
 	probe_cache_sizes();
 
 #ifdef CONFIG_SIBYTE_DMA_PAGEOPS
-	_clear_page = sb1_clear_page_dma;
-	_copy_page = sb1_copy_page_dma;
 	sb1_dma_init();
-#else
-	_clear_page = sb1_clear_page;
-	_copy_page = sb1_copy_page;
 #endif
 
 	/*
@@ -526,7 +501,6 @@ void ld_mmu_sb1(void)
 	 * occur
 	 */
 	flush_cache_range = (void *) sb1_nop;
-	flush_cache_page = sb1_flush_cache_page;
 	flush_cache_mm = (void (*)(struct mm_struct *))sb1_nop;
 	flush_cache_all = sb1_nop;
 
@@ -535,6 +509,9 @@ void ld_mmu_sb1(void)
 	flush_icache_page = sb1_flush_icache_page;
 	flush_icache_all = __sb1_flush_icache_all; /* local only */
 
+	/* This implies an Icache flush too, so can't be nop'ed */
+	flush_cache_page = sb1_flush_cache_page;
+
 	flush_cache_sigtramp = sb1_flush_cache_sigtramp;
 	flush_data_cache_page = (void *) sb1_nop;
 
@@ -547,13 +524,15 @@ void ld_mmu_sb1(void)
 	 * This is the only way to force the update of K0 to complete
 	 * before subsequent instruction fetch.
 	 */
-	write_c0_epc(&&here);
-here:
 	__asm__ __volatile__(
+	"	.set	noat			\n"
 	"	.set	noreorder		\n"
 	"	.set	mips3\n\t		\n"
+	"	la	$1, 1f			\n"
+	"	mtc0	$1, $14			\n"
 	"	eret				\n"
-	"	.set	mips0\n\t		\n"
+	"1:	.set	mips0\n\t		\n"
+	"	.set	at			\n"
 	"	.set	reorder"
 	:
 	:
--- diff/arch/mips/mm/c-tx39.c	2003-08-20 14:16:25.000000000 +0100
+++ source/arch/mips/mm/c-tx39.c	2004-02-23 13:56:38.000000000 +0000
@@ -28,9 +28,6 @@ static unsigned long icache_size, dcache
 
 #include <asm/r4kcache.h>
 
-extern void r3k_clear_page(void * page);
-extern void r3k_copy_page(void * to, void * from);
-
 extern int r3k_have_wired_reg;	/* in r3k-tlb.c */
 
 /* This sequence is required to ensure icache is disabled immediately */
@@ -410,11 +407,10 @@ static __init void tx39_probe_cache(void
 
 void __init ld_mmu_tx39(void)
 {
+	extern void build_clear_page(void);
+	extern void build_copy_page(void);
 	unsigned long config;
 
-	_clear_page = r3k_clear_page;
-	_copy_page = r3k_copy_page;
-
 	config = read_c0_conf();
 	config &= ~TX39_CONF_WBON;
 	write_c0_conf(config);
@@ -489,4 +485,7 @@ void __init ld_mmu_tx39(void)
 		icache_size >> 10, current_cpu_data.icache.linesz);
 	printk("Primary data cache %ldkb, linesize %d bytes\n",
 		dcache_size >> 10, current_cpu_data.dcache.linesz);
+
+	build_clear_page();
+	build_copy_page();
 }
--- diff/arch/mips/mm/cache.c	2003-08-20 14:16:25.000000000 +0100
+++ source/arch/mips/mm/cache.c	2004-02-23 13:56:38.000000000 +0000
@@ -5,12 +5,45 @@
  *
  * Copyright (C) 1994 - 2003 by Ralf Baechle
  */
+#include <linux/config.h>
+#include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/sched.h>
 #include <linux/mm.h>
 
 #include <asm/cacheflush.h>
+#include <asm/processor.h>
+#include <asm/cpu.h>
+#include <asm/cpu-features.h>
+
+/* Cache operations. */
+void (*flush_cache_all)(void);
+void (*__flush_cache_all)(void);
+void (*flush_cache_mm)(struct mm_struct *mm);
+void (*flush_cache_range)(struct vm_area_struct *vma, unsigned long start,
+	unsigned long end);
+void (*flush_cache_page)(struct vm_area_struct *vma, unsigned long page);
+void (*flush_icache_range)(unsigned long start, unsigned long end);
+void (*flush_icache_page)(struct vm_area_struct *vma, struct page *page);
+
+/* MIPS specific cache operations */
+void (*flush_cache_sigtramp)(unsigned long addr);
+void (*flush_data_cache_page)(unsigned long addr);
+void (*flush_icache_all)(void);
+
+#ifdef CONFIG_DMA_NONCOHERENT
+
+/* DMA cache operations. */
+void (*_dma_cache_wback_inv)(unsigned long start, unsigned long size);
+void (*_dma_cache_wback)(unsigned long start, unsigned long size);
+void (*_dma_cache_inv)(unsigned long start, unsigned long size);
+
+EXPORT_SYMBOL(_dma_cache_wback_inv);
+EXPORT_SYMBOL(_dma_cache_wback);
+EXPORT_SYMBOL(_dma_cache_inv);
+
+#endif /* CONFIG_DMA_NONCOHERENT */
 
 asmlinkage int sys_cacheflush(void *addr, int bytes, int cache)
 {
@@ -61,3 +94,59 @@ void __update_cache(struct vm_area_struc
 }
 
 EXPORT_SYMBOL(flush_dcache_page);
+
+extern void ld_mmu_r23000(void);
+extern void ld_mmu_r4xx0(void);
+extern void ld_mmu_tx39(void);
+extern void ld_mmu_r6000(void);
+extern void ld_mmu_tfp(void);
+extern void ld_mmu_andes(void);
+extern void ld_mmu_sb1(void);
+
+void __init cpu_cache_init(void)
+{
+	if (cpu_has_4ktlb) {
+#if defined(CONFIG_CPU_R4X00)  || defined(CONFIG_CPU_VR41XX) || \
+    defined(CONFIG_CPU_R4300)  || defined(CONFIG_CPU_R5000)  || \
+    defined(CONFIG_CPU_NEVADA) || defined(CONFIG_CPU_R5432)  || \
+    defined(CONFIG_CPU_R5500)  || defined(CONFIG_CPU_MIPS32) || \
+    defined(CONFIG_CPU_MIPS64) || defined(CONFIG_CPU_TX49XX) || \
+    defined(CONFIG_CPU_RM7000) || defined(CONFIG_CPU_RM9000)
+		ld_mmu_r4xx0();
+#endif
+	} else switch (current_cpu_data.cputype) {
+#ifdef CONFIG_CPU_R3000
+	case CPU_R2000:
+	case CPU_R3000:
+	case CPU_R3000A:
+	case CPU_R3081E:
+		ld_mmu_r23000();
+		break;
+#endif
+#ifdef CONFIG_CPU_TX39XX
+	case CPU_TX3912:
+	case CPU_TX3922:
+	case CPU_TX3927:
+		ld_mmu_tx39();
+		break;
+#endif
+#ifdef CONFIG_CPU_R10000
+	case CPU_R10000:
+	case CPU_R12000:
+		ld_mmu_r4xx0();
+		break;
+#endif
+#ifdef CONFIG_CPU_SB1
+	case CPU_SB1:
+		ld_mmu_sb1();
+		break;
+#endif
+
+	case CPU_R8000:
+		panic("R8000 is unsupported");
+		break;
+
+	default:
+		panic("Yeee, unsupported cache architecture.");
+	}
+}
--- diff/arch/mips/mm/cerr-sb1.c	2003-08-20 14:16:25.000000000 +0100
+++ source/arch/mips/mm/cerr-sb1.c	2004-02-23 13:56:38.000000000 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2001 Broadcom Corporation
+ * Copyright (C) 2001,2002,2003 Broadcom Corporation
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
@@ -15,7 +15,7 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  */
-
+#include <linux/config.h>
 #include <linux/sched.h>
 #include <asm/mipsregs.h>
 #include <asm/sibyte/sb1250.h>
@@ -25,7 +25,7 @@
 #include <asm/sibyte/sb1250_regs.h>
 #include <asm/sibyte/sb1250_scd.h>
 #endif
-
+ 
 /* SB1 definitions */
 
 /* XXX should come from config1 XXX */
@@ -141,11 +141,11 @@ static void check_bus_watcher(void)     
 	uint32_t status, l2_err, memio_err;
 
 	/* Destructive read, clears register and interrupt */
-	status = csr_in32(IO_SPACE_BASE | A_SCD_BUS_ERR_STATUS);
+	status = csr_in32(IOADDR(A_SCD_BUS_ERR_STATUS));
 	/* Bit 31 is always on, but there's no #define for that */
 	if (status & ~(1UL << 31)) {  
-		l2_err = csr_in32(IO_SPACE_BASE | A_BUS_L2_ERRORS);
-		memio_err = csr_in32(IO_SPACE_BASE | A_BUS_MEM_IO_ERRORS);
+		l2_err = csr_in32(IOADDR(A_BUS_L2_ERRORS));
+		memio_err = csr_in32(IOADDR(A_BUS_MEM_IO_ERRORS));
 		prom_printf("Bus watcher error counters: %08x %08x\n", l2_err, memio_err);
 		prom_printf("\nLast recorded signature:\n");
 		prom_printf("Request %02x from %d, answered by %d with Dcode %d\n",
@@ -192,7 +192,9 @@ asmlinkage void sb1_cache_error(void)
 		prom_printf(" c0_cerr_i   ==   %08x", cerr_i);
 		breakout_cerri(cerr_i);
 		if (CP0_CERRI_IDX_VALID(cerr_i)) {
-			if ((eepc & SB1_CACHE_INDEX_MASK) != (cerr_i & SB1_CACHE_INDEX_MASK))
+			/* Check index of EPC, allowing for delay slot */
+			if (((eepc & SB1_CACHE_INDEX_MASK) != (cerr_i & SB1_CACHE_INDEX_MASK)) &&
+			    ((eepc & SB1_CACHE_INDEX_MASK) != ((cerr_i & SB1_CACHE_INDEX_MASK) - 4)))
 				prom_printf(" cerr_i idx doesn't match eepc\n");
 			else {
 				res = extract_ic(cerr_i & SB1_CACHE_INDEX_MASK,
--- diff/arch/mips/mm/cex-sb1.S	2003-08-20 14:16:25.000000000 +0100
+++ source/arch/mips/mm/cex-sb1.S	2004-02-23 13:56:38.000000000 +0000
@@ -22,40 +22,122 @@
 #include <asm/regdef.h>
 #include <asm/mipsregs.h>
 #include <asm/stackframe.h>
+#include <asm/cacheops.h>
+#include <asm/processor.h>
 #include <asm/sibyte/board.h>
 
-	.text
-	.set	noat
-	.set	mips4
+#define C0_ERRCTL     $26             /* CP0: Error info */
+#define C0_CERR_I     $27             /* CP0: Icache error */
+#define C0_CERR_D     $27,1           /* CP0: Dcache error */
+
+	/*
+	 * Based on SiByte sample software cache-err/cerr.S
+	 * CVS revision 1.8.  Only the 'unrecoverable' case
+	 * is changed.
+	 */
 
         __INIT
-        
-	/* Cache Error handler for SB1 */
-	LEAF(except_vec2_sb1)
-	mfc0	k1, $26
-	# check if error was recoverable
-	bltz	k1, leave_cerr
-#ifdef CONFIG_SB1_PASS_1_WORKAROUNDS
-	# look for signature of spurious CErr
-	lui	k0, 0x4000
-	bne	k0, k1, 1f
-	.word	0x401Bd801			# mfc0	k1, $27, 1
-	lui	k0, 0xffe0
-	and	k1, k0, k1
-	lui	k0, 0x0200
-	beq	k0, k1, leave_cerr
-1:
-#endif
-	j	handle_vec2_sb1
 
-leave_cerr:
-	# clear/unlock the registers
-	mtc0	zero, $26
-	mtc0	zero, $27
-	.word	0x4080d801			# mtc0	zero, $27, 1
-	.word	0x4080d803			# mtc0	zero, $27, 3
+	.set	mips64
+	.set	noreorder
+	.set	noat
+
+	/*
+	 * sb1_cerr_vec: code to be copied to the Cache Error
+	 * Exception vector.  The code must be pushed out to memory
+	 * (either by copying to Kseg0 and Kseg1 both, or by flushing
+	 * the L1 and L2) since it is fetched as 0xa0000100.
+	 *
+	 * NOTE: Be sure this handler is at most 28 instructions long
+	 * since the final 16 bytes of the exception vector memory
+	 * (0x170-0x17f) are used to preserve k0, k1, and ra.
+	 */
+
+LEAF(except_vec2_sb1)
+	/*
+	 * If this error is recoverable, we need to exit the handler
+	 * without having dirtied any registers.  To do this,
+	 * save/restore k0 and k1 from low memory (Useg is direct
+	 * mapped while ERL=1). Note that we can't save to a
+	 * CPU-specific location without ruining a register in the
+	 * process.  This means we are vulnerable to data corruption
+	 * whenever the handler is reentered by a second CPU.
+	 */
+	sd	k0,0x170($0)
+	sd	k1,0x178($0)
+
+	/*
+	 * M_ERRCTL_RECOVERABLE is bit 31, which makes it easy to tell
+	 * if we can fast-path out of here for a h/w-recovered error.
+	 */
+	mfc0	k1,C0_ERRCTL
+	bgtz	k1,attempt_recovery
+	 sll	k0,k1,1
+
+recovered_dcache:
+	/*
+	 * Unlock CacheErr-D (which in turn unlocks CacheErr-DPA).
+	 * Ought to log the occurence of this recovered dcache error.
+	 */
+	b	recovered
+	 mtc0	$0,C0_CERR_D
+
+attempt_recovery:
+	/*
+	 * k0 has C0_ERRCTL << 1, which puts 'DC' at bit 31.  Any
+	 * Dcache errors we can recover from will take more extensive
+	 * processing.  For now, they are considered "unrecoverable".
+	 * Note that 'DC' becoming set (outside of ERL mode) will
+	 * cause 'IC' to clear; so if there's an Icache error, we'll
+	 * only find out about it if we recover from this error and
+	 * continue executing.
+	 */
+	bltz	k0,unrecoverable
+	 sll	k0,1
+
+	/*
+	 * k0 has C0_ERRCTL << 2, which puts 'IC' at bit 31.  If an
+	 * Icache error isn't indicated, I'm not sure why we got here.
+	 * Consider that case "unrecoverable" for now.
+	 */
+	bgez	k0,unrecoverable
+
+attempt_icache_recovery:
+	/*
+	 * External icache errors are due to uncorrectable ECC errors
+	 * in the L2 cache or Memory Controller and cannot be
+	 * recovered here.
+	 */
+	 mfc0	k0,C0_CERR_I		/* delay slot */
+	li	k1,1 << 26		/* ICACHE_EXTERNAL */
+	and	k1,k0
+	bnez	k1,unrecoverable
+	 andi	k0,0x1fe0
+
+	/*
+	 * Since the error is internal, the 'IDX' field from
+	 * CacheErr-I is valid and we can just invalidate all blocks
+	 * in that set.
+	 */
+	cache	Index_Invalidate_I,(0<<13)(k0)
+	cache	Index_Invalidate_I,(1<<13)(k0)
+	cache	Index_Invalidate_I,(2<<13)(k0)
+	cache	Index_Invalidate_I,(3<<13)(k0)
+
+	/* Ought to log this recovered icache error */
+
+recovered:
+	/* Restore the saved registers */
+	ld	k0,0x170($0)
+	ld	k1,0x178($0)
 	eret
-	END(except_vec2_sb1)
+
+unrecoverable:
+	/* Unrecoverable Icache or Dcache error; log it and/or fail */
+	j	handle_vec2_sb1
+	 nop
+
+END(except_vec2_sb1)
 
 	__FINIT
 
@@ -75,7 +157,16 @@ leave_cerr:
 	mfc0	k0, CP0_STATUS
 	sll	k0, k0, 3			# check CU0 (kernel?)
 	bltz	k0, 2f
+	 nop
+
+	/* Get a valid Kseg0 stack pointer.  Any task's stack pointer
+	 * will do, although if we ever want to resume execution we
+	 * better not have corrupted any state. */
 	get_saved_sp
-2:	j	sb1_cache_error
+	move	sp, k1
+
+2:
+	j	sb1_cache_error
+	 nop
 
 	END(handle_vec2_sb1)
--- diff/arch/mips/mm/fault.c	2003-08-20 14:16:25.000000000 +0100
+++ source/arch/mips/mm/fault.c	2004-02-23 13:56:38.000000000 +0000
@@ -5,7 +5,6 @@
  *
  * Copyright (C) 1995 - 2000 by Ralf Baechle
  */
-#include <linux/config.h>
 #include <linux/signal.h>
 #include <linux/sched.h>
 #include <linux/interrupt.h>
@@ -18,7 +17,6 @@
 #include <linux/mm.h>
 #include <linux/smp.h>
 #include <linux/smp_lock.h>
-#include <linux/version.h>
 #include <linux/vt_kern.h>		/* For unblank_screen() */
 #include <linux/module.h>
 
@@ -30,13 +28,6 @@
 #include <asm/uaccess.h>
 #include <asm/ptrace.h>
 
-#define development_version (LINUX_VERSION_CODE & 0x100)
-
-/*
- * Macro for exception fixup code to access integer registers.
- */
-#define dpf_reg(r) (regs->regs[r])
-
 /*
  * This routine handles page faults.  It determines the address,
  * and the problem, and then passes it off to one of the appropriate
@@ -45,19 +36,20 @@
 asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long write,
 			      unsigned long address)
 {
-	struct vm_area_struct * vma;
+	struct vm_area_struct * vma = NULL;
 	struct task_struct *tsk = current;
 	struct mm_struct *mm = tsk->mm;
-	const struct exception_table_entry *fixup;
-	const int szlong = sizeof(unsigned long);
+	const int field = sizeof(unsigned long) * 2;
 	siginfo_t info;
 
 #if 0
 	printk("Cpu%d[%s:%d:%0*lx:%ld:%0*lx]\n", smp_processor_id(),
-	       current->comm, current->pid, szlong, address, write,
-	       szlong, regs->cp0_epc);
+	       current->comm, current->pid, field, address, write,
+	       field, regs->cp0_epc);
 #endif
 
+	info.si_code = SEGV_MAPERR;
+
 	/*
 	 * We fault-in kernel-space virtual memory on-demand. The
 	 * 'reference' page table is init_mm.pgd.
@@ -67,16 +59,15 @@ asmlinkage void do_page_fault(struct pt_
 	 * only copy the information from the master page table,
 	 * nothing more.
 	 */
-	if (address >= VMALLOC_START)
+	if (unlikely(address >= VMALLOC_START))
 		goto vmalloc_fault;
 
-	info.si_code = SEGV_MAPERR;
 	/*
 	 * If we're in an interrupt or have no user
 	 * context, we must not take the fault..
 	 */
 	if (in_atomic() || !mm)
-		goto no_context;
+		goto bad_area_nosemaphore;
 
 	down_read(&mm->mmap_sem);
 	vma = find_vma(mm, address);
@@ -134,6 +125,7 @@ survive:
 bad_area:
 	up_read(&mm->mmap_sem);
 
+bad_area_nosemaphore:
 	/* User mode accesses just cause a SIGSEGV */
 	if (user_mode(regs)) {
 		tsk->thread.cp0_badvaddr = address;
@@ -143,9 +135,9 @@ bad_area:
 		       "invalid %s\n%0*lx (epc == %0*lx, ra == %0*lx)\n",
 		       tsk->comm,
 		       write ? "write access to" : "read access from",
-		       szlong, address,
-		       szlong, (unsigned long) regs->cp0_epc,
-		       szlong, (unsigned long) regs->regs[31]);
+		       field, address,
+		       field, (unsigned long) regs->cp0_epc,
+		       field, (unsigned long) regs->regs[31]);
 #endif
 		info.si_signo = SIGSEGV;
 		info.si_errno = 0;
@@ -157,15 +149,8 @@ bad_area:
 
 no_context:
 	/* Are we prepared to handle this kernel fault?  */
-	fixup = search_exception_tables(exception_epc(regs));
-	if (fixup) {
-		unsigned long new_epc = fixup->nextinsn;
-
-		tsk->thread.cp0_baduaddr = address;
-		if (development_version)
-			printk(KERN_DEBUG "%s: Exception at [<%lx>] (%lx)\n",
-			       tsk->comm, regs->cp0_epc, new_epc);
-		regs->cp0_epc = new_epc;
+	if (fixup_exception(regs)) {
+		current->thread.cp0_baduaddr = address;
 		return;
 	}
 
@@ -178,8 +163,8 @@ no_context:
 
 	printk(KERN_ALERT "CPU %d Unable to handle kernel paging request at "
 	       "virtual address %0*lx, epc == %0*lx, ra == %0*lx\n",
-	       smp_processor_id(), szlong, address, szlong, regs->cp0_epc,
-	       szlong,  regs->regs[31]);
+	       smp_processor_id(), field, address, field, regs->cp0_epc,
+	       field,  regs->regs[31]);
 	die("Oops", regs);
 
 /*
@@ -201,6 +186,10 @@ out_of_memory:
 do_sigbus:
 	up_read(&mm->mmap_sem);
 
+	/* Kernel mode? Handle exceptions or die */
+	if (!user_mode(regs))
+		goto no_context;
+
 	/*
 	 * Send a sigbus, regardless of whether we were in kernel
 	 * or user mode.
@@ -212,10 +201,6 @@ do_sigbus:
 	info.si_addr = (void *) address;
 	force_sig_info(SIGBUS, &info, tsk);
 
-	/* Kernel mode? Handle exceptions or die */
-	if (!user_mode(regs))
-		goto no_context;
-
 	return;
 
 vmalloc_fault:
--- diff/arch/mips/mm/highmem.c	2004-01-19 10:22:55.000000000 +0000
+++ source/arch/mips/mm/highmem.c	2004-02-23 13:56:38.000000000 +0000
@@ -1,3 +1,4 @@
+#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/highmem.h>
 #include <asm/tlbflush.h>
--- diff/arch/mips/mm/pg-sb1.c	2003-08-20 14:16:25.000000000 +0100
+++ source/arch/mips/mm/pg-sb1.c	2004-02-23 13:56:38.000000000 +0000
@@ -22,6 +22,7 @@
  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  */
 #include <linux/config.h>
+#include <linux/module.h>
 #include <linux/sched.h>
 #include <linux/smp.h>
 
@@ -38,8 +39,11 @@
 #define SB1_PREF_STORE_STREAMED_HINT "5"
 #endif
 
-/* These are the functions hooked by the memory management function pointers */
-void sb1_clear_page(void *page)
+#ifdef CONFIG_SIBYTE_DMA_PAGEOPS
+static inline void clear_page_cpu(void *page)
+#else
+void clear_page(void *page)
+#endif
 {
 	unsigned char *addr = (unsigned char *) page;
 	unsigned char *end = addr + PAGE_SIZE;
@@ -77,7 +81,11 @@ void sb1_clear_page(void *page)
 	} while (addr != end);
 }
 
-void sb1_copy_page(void *to, void *from)
+#ifdef CONFIG_SIBYTE_DMA_PAGEOPS
+static inline void copy_page_cpu(void *to, void *from)
+#else
+void copy_page(void *to, void *from)
+#endif
 {
 	unsigned char *src = from;
 	unsigned char *dst = to;
@@ -157,55 +165,58 @@ void sb1_dma_init(void)
 	uint64_t base_val = PHYSADDR(&page_descr[cpu]) | V_DM_DSCR_BASE_RINGSZ(1);
 
 	__raw_writeq(base_val,
-		     IO_SPACE_BASE + A_DM_REGISTER(cpu, R_DM_DSCR_BASE));
+		     IOADDR(A_DM_REGISTER(cpu, R_DM_DSCR_BASE)));
 	__raw_writeq(base_val | M_DM_DSCR_BASE_RESET,
-		     IO_SPACE_BASE + A_DM_REGISTER(cpu, R_DM_DSCR_BASE));
+		     IOADDR(A_DM_REGISTER(cpu, R_DM_DSCR_BASE)));
 	__raw_writeq(base_val | M_DM_DSCR_BASE_ENABL,
-		     IO_SPACE_BASE + A_DM_REGISTER(cpu, R_DM_DSCR_BASE));
+		     IOADDR(A_DM_REGISTER(cpu, R_DM_DSCR_BASE)));
 }
 
-void sb1_clear_page_dma(void *page)
+void clear_page(void *page)
 {
 	int cpu = smp_processor_id();
 
 	/* if the page is above Kseg0, use old way */
-	if (KSEGX(page) != K0BASE)
-		return sb1_clear_page(page);
+	if (KSEGX(page) != CAC_BASE)
+		return clear_page_cpu(page);
 
 	page_descr[cpu].dscr_a = PHYSADDR(page) | M_DM_DSCRA_ZERO_MEM | M_DM_DSCRA_L2C_DEST | M_DM_DSCRA_INTERRUPT;
 	page_descr[cpu].dscr_b = V_DM_DSCRB_SRC_LENGTH(PAGE_SIZE);
-	__raw_writeq(1, IO_SPACE_BASE + A_DM_REGISTER(cpu, R_DM_DSCR_COUNT));
+	__raw_writeq(1, IOADDR(A_DM_REGISTER(cpu, R_DM_DSCR_COUNT)));
 
 	/*
 	 * Don't really want to do it this way, but there's no
 	 * reliable way to delay completion detection.
 	 */
-	while (!(__raw_readq(IO_SPACE_BASE + A_DM_REGISTER(cpu, R_DM_DSCR_BASE_DEBUG)) & M_DM_DSCR_BASE_INTERRUPT))
+	while (!(__raw_readq(IOADDR(A_DM_REGISTER(cpu, R_DM_DSCR_BASE_DEBUG)) & M_DM_DSCR_BASE_INTERRUPT)))
 		;
-	__raw_readq(IO_SPACE_BASE + A_DM_REGISTER(cpu, R_DM_DSCR_BASE));
+	__raw_readq(IOADDR(A_DM_REGISTER(cpu, R_DM_DSCR_BASE)));
 }
 
-void sb1_copy_page_dma(void *to, void *from)
+void copy_page(void *to, void *from)
 {
 	unsigned long from_phys = PHYSADDR(from);
 	unsigned long to_phys = PHYSADDR(to);
 	int cpu = smp_processor_id();
 
 	/* if either page is above Kseg0, use old way */
-	if ((KSEGX(to) != K0BASE) || (KSEGX(from) != K0BASE))
-		return sb1_copy_page(to, from);
+	if ((KSEGX(to) != CAC_BASE) || (KSEGX(from) != CAC_BASE))
+		return copy_page_cpu(to, from);
 
 	page_descr[cpu].dscr_a = PHYSADDR(to_phys) | M_DM_DSCRA_L2C_DEST | M_DM_DSCRA_INTERRUPT;
 	page_descr[cpu].dscr_b = PHYSADDR(from_phys) | V_DM_DSCRB_SRC_LENGTH(PAGE_SIZE);
-	__raw_writeq(1, IO_SPACE_BASE + A_DM_REGISTER(cpu, R_DM_DSCR_COUNT));
+	__raw_writeq(1, IOADDR(A_DM_REGISTER(cpu, R_DM_DSCR_COUNT)));
 
 	/*
 	 * Don't really want to do it this way, but there's no
 	 * reliable way to delay completion detection.
 	 */
-	while (!(__raw_readq(IO_SPACE_BASE + A_DM_REGISTER(cpu, R_DM_DSCR_BASE_DEBUG)) & M_DM_DSCR_BASE_INTERRUPT))
+	while (!(__raw_readq(IOADDR(A_DM_REGISTER(cpu, R_DM_DSCR_BASE_DEBUG)) & M_DM_DSCR_BASE_INTERRUPT)))
 		;
-	__raw_readq(IO_SPACE_BASE + A_DM_REGISTER(cpu, R_DM_DSCR_BASE));
+	__raw_readq(IOADDR(A_DM_REGISTER(cpu, R_DM_DSCR_BASE)));
 }
 
 #endif
+
+EXPORT_SYMBOL(clear_page);
+EXPORT_SYMBOL(copy_page);
--- diff/arch/mips/mm/pgtable-32.c	2003-08-20 14:16:36.000000000 +0100
+++ source/arch/mips/mm/pgtable-32.c	2004-02-23 13:56:38.000000000 +0000
@@ -5,8 +5,11 @@
  *
  * Copyright (C) 2003 by Ralf Baechle
  */
+#include <linux/config.h>
 #include <linux/init.h>
 #include <linux/mm.h>
+#include <linux/bootmem.h>
+#include <linux/highmem.h>
 #include <asm/pgtable.h>
 
 void pgd_init(unsigned long page)
@@ -26,6 +29,37 @@ void pgd_init(unsigned long page)
 	}
 }
 
+#ifdef CONFIG_HIGHMEM
+static void __init fixrange_init (unsigned long start, unsigned long end,
+	pgd_t *pgd_base)
+{
+	pgd_t *pgd;
+	pmd_t *pmd;
+	pte_t *pte;
+	int i, j;
+	unsigned long vaddr;
+
+	vaddr = start;
+	i = __pgd_offset(vaddr);
+	j = __pmd_offset(vaddr);
+	pgd = pgd_base + i;
+
+	for ( ; (i < PTRS_PER_PGD) && (vaddr != end); pgd++, i++) {
+		pmd = (pmd_t *)pgd;
+		for (; (j < PTRS_PER_PMD) && (vaddr != end); pmd++, j++) {
+			if (pmd_none(*pmd)) {
+				pte = (pte_t *) alloc_bootmem_low_pages(PAGE_SIZE);
+				set_pmd(pmd, __pmd((unsigned long)pte));
+				if (pte != pte_offset_kernel(pmd, 0))
+					BUG();
+			}
+			vaddr += PMD_SIZE;
+		}
+		j = 0;
+	}
+}
+#endif
+
 void __init pagetable_init(void)
 {
 #ifdef CONFIG_HIGHMEM
--- diff/arch/mips/mm/pgtable-64.c	2003-08-20 14:16:36.000000000 +0100
+++ source/arch/mips/mm/pgtable-64.c	2004-02-23 13:56:38.000000000 +0000
@@ -64,7 +64,7 @@ void __init pagetable_init(void)
 
 	memset((void *)kptbl, 0, PAGE_SIZE << PGD_ORDER);
 	memset((void *)kpmdtbl, 0, PAGE_SIZE);
-	set_pgd(swapper_pg_dir, __pgd(kpmdtbl));
+	set_pgd(swapper_pg_dir, __pgd((unsigned long)kpmdtbl));
 
 	/*
 	 * The 64-bit kernel uses a flat pagetable for it's kernel mappings ...
--- diff/arch/mips/mm/pgtable.c	2003-07-08 09:55:17.000000000 +0100
+++ source/arch/mips/mm/pgtable.c	2004-02-23 13:56:38.000000000 +0000
@@ -4,6 +4,7 @@
 
 void show_mem(void)
 {
+#ifndef CONFIG_DISCONTIGMEM  /* XXX(hch): later.. */
 	int pfn, total = 0, reserved = 0;
 	int shared = 0, cached = 0;
 	int highmem = 0;
@@ -30,4 +31,5 @@ void show_mem(void)
 	printk("%d reserved pages\n",reserved);
 	printk("%d pages shared\n",shared);
 	printk("%d pages swap cached\n",cached);
+#endif
 }
--- diff/arch/mips/mm/sc-r5k.c	2003-07-08 09:55:17.000000000 +0100
+++ source/arch/mips/mm/sc-r5k.c	2004-02-23 13:56:38.000000000 +0000
@@ -14,6 +14,7 @@
 #include <asm/pgtable.h>
 #include <asm/system.h>
 #include <asm/mmu_context.h>
+#include <asm/r4kcache.h>
 
 /* Secondary cache size in bytes, if present.  */
 static unsigned long scache_size;
@@ -21,24 +22,13 @@ static unsigned long scache_size;
 #define SC_LINE 32
 #define SC_PAGE (128*SC_LINE)
 
-#define cache_op(base,op)                   \
-__asm__ __volatile__("				\
-		.set noreorder;                 \
-		.set mips3;                     \
-		cache %1, (%0);                 \
-		.set mips0;                     \
-		.set reorder"                   \
-		:                               \
-		: "r" (base),                   \
-		  "i" (op));
-
 static inline void blast_r5000_scache(void)
 {
-	unsigned long start = KSEG0;
-	unsigned long end = KSEG0 + scache_size;
+	unsigned long start = INDEX_BASE;
+	unsigned long end = start + scache_size;
 
 	while(start < end) {
-		cache_op(start, R5K_Page_Invalidate_S);
+		cache_op(R5K_Page_Invalidate_S, start);
 		start += SC_PAGE;
 	}
 }
@@ -59,7 +49,7 @@ static void r5k_dma_cache_inv_sc(unsigne
 	a = addr & ~(SC_PAGE - 1);
 	end = (addr + size - 1) & ~(SC_PAGE - 1);
 	while (a <= end) {
-		cache_op(a, R5K_Page_Invalidate_S);
+		cache_op(R5K_Page_Invalidate_S, a);
 		a += SC_PAGE;
 	}
 }
@@ -69,7 +59,7 @@ static void r5k_sc_enable(void)
         unsigned long flags;
 
 	local_irq_save(flags);
-	change_c0_config(R5K_CONF_SE, R5K_CONF_SE);
+	set_c0_config(R5K_CONF_SE);
 	blast_r5000_scache();
 	local_irq_restore(flags);
 }
@@ -80,7 +70,7 @@ static void r5k_sc_disable(void)
 
 	local_irq_save(flags);
 	blast_r5000_scache();
-	change_c0_config(R5K_CONF_SE, 0);
+	clear_c0_config(R5K_CONF_SE);
 	local_irq_restore(flags);
 }
 
--- diff/arch/mips/mm/sc-rm7k.c	2003-07-08 09:55:17.000000000 +0100
+++ source/arch/mips/mm/sc-rm7k.c	2004-02-23 13:56:38.000000000 +0000
@@ -129,7 +129,7 @@ static __init void rm7k_sc_enable(void)
 
 static void rm7k_sc_disable(void)
 {
-	set_c0_config(1<<3);				/* CONF_SE */
+	clear_c0_config(1<<3);				/* CONF_SE */
 }
 
 static inline int __init rm7k_sc_probe(void)
@@ -140,11 +140,11 @@ static inline int __init rm7k_sc_probe(v
 	if ((config >> 31) & 1)
 		return 0;
 
-	printk(KERN_INFO "Secondary cache size %ldK, linesize 32 bytes.\n",
+	printk(KERN_INFO "Secondary cache size %ldK, linesize %ld bytes.\n",
 	       (scache_size >> 10), sc_lsize);
 
-	if ((config >> 3) & 1)
-		return;
+	if ((config >> 3) & 1)                          /* CONF_SE */
+		return 1;
 
 	printk(KERN_INFO "Enabling secondary cache...");
 	func();
--- diff/arch/mips/mm/tlb-andes.c	2003-08-20 14:16:36.000000000 +0100
+++ source/arch/mips/mm/tlb-andes.c	2004-02-23 13:56:38.000000000 +0000
@@ -7,6 +7,7 @@
  * Copyright (C) 1999 Silicon Graphics, Inc.
  * Copyright (C) 2000 Kanoj Sarcar (kanoj@sgi.com)
  */
+#include <linux/config.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/sched.h>
@@ -16,6 +17,9 @@
 #include <asm/system.h>
 #include <asm/mmu_context.h>
 
+extern void except_vec0_generic(void);
+extern void except_vec0_r4000(void);
+extern void except_vec1_generic(void);
 extern void except_vec1_r10k(void);
 
 #define NTLB_ENTRIES       64
@@ -235,7 +239,7 @@ void __update_tlb(struct vm_area_struct 
 	local_irq_restore(flags);
 }
 
-void __init andes_tlb_init(void)
+void __init tlb_init(void)
 {
 	/*
 	 * You should never change this register:
@@ -253,5 +257,14 @@ void __init andes_tlb_init(void)
 
 	/* Did I tell you that ARC SUCKS?  */
 
-	memcpy((void *)KSEG1 + 0x080, except_vec1_r10k, 0x80);
+#ifdef CONFIG_MIPS32
+	memcpy((void *)KSEG0, &except_vec0_r4000, 0x80);
+	memcpy((void *)(KSEG0 + 0x080), &except_vec1_generic, 0x80);
+	flush_icache_range(KSEG0, KSEG0 + 0x100);
+#endif
+#ifdef CONFIG_MIPS64
+	memcpy((void *)(CKSEG0 + 0x000), &except_vec0_generic, 0x80);
+	memcpy((void *)(CKSEG0 + 0x080), except_vec1_r10k, 0x80);
+	flush_icache_range(CKSEG0 + 0x80, CKSEG0 + 0x100);
+#endif
 }
--- diff/arch/mips/mm/tlb-r3k.c	2003-07-08 09:55:17.000000000 +0100
+++ source/arch/mips/mm/tlb-r3k.c	2004-02-23 13:56:38.000000000 +0000
@@ -10,7 +10,6 @@
  * Copyright (C) 2002  Ralf Baechle
  * Copyright (C) 2002  Maciej W. Rozycki
  */
-#include <linux/config.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/sched.h>
@@ -282,7 +281,7 @@ void __init add_wired_entry(unsigned lon
 	}
 }
 
-void __init r3k_tlb_init(void)
+void __init tlb_init(void)
 {
 	local_flush_tlb_all();
 	memcpy((void *)KSEG0, &except_vec0_r2300, 0x80);
--- diff/arch/mips/mm/tlb-r4k.c	2003-08-20 14:16:25.000000000 +0100
+++ source/arch/mips/mm/tlb-r4k.c	2004-02-23 13:56:38.000000000 +0000
@@ -19,9 +19,11 @@
 #include <asm/pgtable.h>
 #include <asm/system.h>
 
+extern void except_vec0_generic(void);
 extern void except_vec0_nevada(void);
 extern void except_vec0_r4000(void);
 extern void except_vec0_r4600(void);
+extern void except_vec1_generic(void);
 extern void except_vec1_r4k(void);
 
 /* CP0 hazard avoidance. */
@@ -50,7 +52,7 @@ void local_flush_tlb_all(void)
 		 * Make sure all entries differ.  If they're not different
 		 * MIPS32 will take revenge ...
 		 */
-		write_c0_entryhi(KSEG0 + entry * 0x2000);
+		write_c0_entryhi(CKSEG0 + (entry << (PAGE_SHIFT + 1)));
 		write_c0_index(entry);
 		BARRIER;
 		tlb_write_indexed();
@@ -104,7 +106,8 @@ void local_flush_tlb_range(struct vm_are
 				if (idx < 0)
 					continue;
 				/* Make sure all entries differ. */
-				write_c0_entryhi(KSEG0 + idx * 0x2000);
+				write_c0_entryhi(CKSEG0 +
+				                 (idx << (PAGE_SHIFT + 1)));
 				BARRIER;
 				tlb_write_indexed();
 				BARRIER;
@@ -146,7 +149,7 @@ void local_flush_tlb_kernel_range(unsign
 			if (idx < 0)
 				continue;
 			/* Make sure all entries differ. */
-			write_c0_entryhi(KSEG0 + idx * 0x2000);
+			write_c0_entryhi(CKSEG0 + (idx << (PAGE_SHIFT + 1)));
 			BARRIER;
 			tlb_write_indexed();
 			BARRIER;
@@ -180,7 +183,7 @@ void local_flush_tlb_page(struct vm_area
 		if (idx < 0)
 			goto finish;
 		/* Make sure all entries differ. */
-		write_c0_entryhi(KSEG0 + idx * 0x2000);
+		write_c0_entryhi(CKSEG0 + (idx << (PAGE_SHIFT + 1)));
 		BARRIER;
 		tlb_write_indexed();
 
@@ -212,7 +215,7 @@ void local_flush_tlb_one(unsigned long p
 	write_c0_entrylo1(0);
 	if (idx >= 0) {
 		/* Make sure all entries differ. */
-		write_c0_entryhi(KSEG0+(idx<<(PAGE_SHIFT+1)));
+		write_c0_entryhi(CKSEG0 + (idx << (PAGE_SHIFT + 1)));
 		BARRIER;
 		tlb_write_indexed();
 	}
@@ -378,25 +381,25 @@ out:
 
 static void __init probe_tlb(unsigned long config)
 {
-	unsigned int prid, config1;
+	struct cpuinfo_mips *c = &current_cpu_data;
+	unsigned int reg;
 
-	prid = read_c0_prid() & ASID_MASK;
-	if (prid == PRID_IMP_RM7000 || !(config & (1 << 31)))
-		/*
-		 * Not a MIPS32/MIPS64 CPU..  Config 1 register not
-		 * supported, we assume R4k style.  Cpu probing already figured
-		 * out the number of tlb entries.
-		 */
+	/*
+	 * If this isn't a MIPS32 / MIPS64 compliant CPU.  Config 1 register
+	 * is not supported, we assume R4k style.  Cpu probing already figured
+	 * out the number of tlb entries.
+	 */
+	if ((c->processor_id  & 0xff0000) == PRID_COMP_LEGACY)
 		return;
 
-	config1 = read_c0_config1();
+	reg = read_c0_config1();
 	if (!((config >> 7) & 3))
-		panic("No MMU present");
-	else
-		current_cpu_data.tlbsize = ((config1 >> 25) & 0x3f) + 1;
+		panic("No TLB present");
+
+	c->tlbsize = ((reg >> 25) & 0x3f) + 1;
 }
 
-void __init r4k_tlb_init(void)
+void __init tlb_init(void)
 {
 	unsigned int config = read_c0_config();
 
@@ -408,7 +411,7 @@ void __init r4k_tlb_init(void)
 	 *     be set for 4kb pages.
 	 */
 	probe_tlb(config);
-	write_c0_pagemask(PM_4K);
+	write_c0_pagemask(PM_DEFAULT_MASK);
 	write_c0_wired(0);
 	temp_tlb_entry = current_cpu_data.tlbsize - 1;
 	local_flush_tlb_all();
@@ -420,10 +423,12 @@ void __init r4k_tlb_init(void)
 		memcpy((void *)KSEG0, &except_vec0_r4600, 0x80);
 	else
 		memcpy((void *)KSEG0, &except_vec0_r4000, 0x80);
-	flush_icache_range(KSEG0, KSEG0 + 0x80);
+	memcpy((void *)(KSEG0 + 0x080), &except_vec1_generic, 0x80);
+	flush_icache_range(KSEG0, KSEG0 + 0x100);
 #endif
 #ifdef CONFIG_MIPS64
-	memcpy((void *)(KSEG0 + 0x80), except_vec1_r4k, 0x80);
-	flush_icache_range(KSEG0 + 0x80, KSEG0 + 0x100);
+	memcpy((void *)(CKSEG0 + 0x00), &except_vec0_generic, 0x80);
+	memcpy((void *)(CKSEG0 + 0x80), except_vec1_r4k, 0x80);
+	flush_icache_range(CKSEG0 + 0x80, CKSEG0 + 0x100);
 #endif
 }
--- diff/arch/mips/mm/tlb-sb1.c	2003-08-20 14:16:25.000000000 +0100
+++ source/arch/mips/mm/tlb-sb1.c	2004-02-23 13:56:38.000000000 +0000
@@ -1,7 +1,7 @@
 /*
  * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
  * Copyright (C) 1997, 2001 Ralf Baechle (ralf@gnu.org)
- * Copyright (C) 2000, 2001 Broadcom Corporation
+ * Copyright (C) 2000, 2001, 2002, 2003 Broadcom Corporation
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
@@ -18,12 +18,21 @@
  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  */
 #include <linux/config.h>
+#include <linux/init.h>
 #include <asm/mmu_context.h>
 #include <asm/bootinfo.h>
 #include <asm/cpu.h>
 
+#ifdef CONFIG_MIPS32
 extern void except_vec0_sb1(void);
+extern void except_vec1_generic(void);
+#endif
+#ifdef CONFIG_MIPS64
+extern void except_vec0_generic(void);
 extern void except_vec1_sb1(void);
+#endif
+
+#define UNIQUE_ENTRYHI(idx) (KSEG0 + ((idx) << (PAGE_SHIFT + 1)))
 
 /* Dump the current entry* and pagemask registers */
 static inline void dump_cur_tlb_regs(void)
@@ -96,10 +105,13 @@ void local_flush_tlb_all(void)
 	old_ctx = read_c0_entryhi() & ASID_MASK;
 	write_c0_entrylo0(0);
 	write_c0_entrylo1(0);
-	for (entry = 0; entry < current_cpu_data.tlbsize; entry++) {
-		write_c0_entryhi(KSEG0 + (PAGE_SIZE << 1) * entry);
+
+	entry = read_c0_wired();
+	while (entry < current_cpu_data.tlbsize) {
+		write_c0_entryhi(UNIQUE_ENTRYHI(entry));
 		write_c0_index(entry);
 		tlb_write_indexed();
+		entry++;
 	}
 	write_c0_entryhi(old_ctx);
 	local_irq_restore(flags);
@@ -111,7 +123,7 @@ void local_flush_tlb_all(void)
  * Use increments of the maximum page size (16MB), and check for duplicate
  * entries before doing a given write.  Then, when we're safe from collisions
  * with the firmware, go back and give all the entries invalid addresses with
- * the normal flush routine.
+ * the normal flush routine.  Wired entries will be killed as well!
  */
 void sb1_sanitize_tlb(void)
 {
@@ -165,7 +177,7 @@ void local_flush_tlb_range(struct vm_are
 				idx = read_c0_index();
 				write_c0_entrylo0(0);
 				write_c0_entrylo1(0);
-				write_c0_entryhi(KSEG0 + (idx << (PAGE_SHIFT+1)));
+				write_c0_entryhi(UNIQUE_ENTRYHI(idx));
 				if (idx < 0)
 					continue;
 				tlb_write_indexed();
@@ -203,7 +215,7 @@ void local_flush_tlb_kernel_range(unsign
 			idx = read_c0_index();
 			write_c0_entrylo0(0);
 			write_c0_entrylo1(0);
-			write_c0_entryhi(KSEG0 + (idx << (PAGE_SHIFT+1)));
+			write_c0_entryhi(UNIQUE_ENTRYHI(idx));
 			if (idx < 0)
 				continue;
 			tlb_write_indexed();
@@ -231,10 +243,10 @@ void local_flush_tlb_page(struct vm_area
 		idx = read_c0_index();
 		write_c0_entrylo0(0);
 		write_c0_entrylo1(0);
-		if(idx < 0)
+		if (idx < 0)
 			goto finish;
 		/* Make sure all entries differ. */
-		write_c0_entryhi(KSEG0+(idx<<(PAGE_SHIFT+1)));
+		write_c0_entryhi(UNIQUE_ENTRYHI(idx));
 		tlb_write_indexed();
 	finish:
 		write_c0_entryhi(oldpid);
@@ -243,29 +255,30 @@ void local_flush_tlb_page(struct vm_area
 }
 
 /*
- * This one is only used for pages with the global bit set so we don't care
- * much about the ASID.
+ * Remove one kernel space TLB entry.  This entry is assumed to be marked
+ * global so we don't do the ASID thing.
  */
 void local_flush_tlb_one(unsigned long page)
 {
 	unsigned long flags;
 	int oldpid, idx;
 
-	local_irq_save(flags);
 	page &= (PAGE_MASK << 1);
 	oldpid = read_c0_entryhi() & ASID_MASK;
+
+	local_irq_save(flags);
 	write_c0_entryhi(page);
 	tlb_probe();
 	idx = read_c0_index();
-	write_c0_entrylo0(0);
-	write_c0_entrylo1(0);
 	if (idx >= 0) {
 		/* Make sure all entries differ. */
-		write_c0_entryhi(KSEG0+(idx<<(PAGE_SHIFT+1)));
+		write_c0_entryhi(UNIQUE_ENTRYHI(idx));
+		write_c0_entrylo0(0);
+		write_c0_entrylo1(0);
 		tlb_write_indexed();
 	}
-	write_c0_entryhi(oldpid);
 
+	write_c0_entryhi(oldpid);
 	local_irq_restore(flags);
 }
 
@@ -315,14 +328,43 @@ void __update_tlb(struct vm_area_struct 
 	local_irq_restore(flags);
 }
 
+void __init add_wired_entry(unsigned long entrylo0, unsigned long entrylo1,
+	unsigned long entryhi, unsigned long pagemask)
+{
+	unsigned long flags;
+	unsigned long wired;
+	unsigned long old_pagemask;
+	unsigned long old_ctx;
+
+	local_irq_save(flags);
+	old_ctx = read_c0_entryhi() & 0xff;
+	old_pagemask = read_c0_pagemask();
+	wired = read_c0_wired();
+	write_c0_wired(wired + 1);
+	write_c0_index(wired);
+
+	write_c0_pagemask(pagemask);
+	write_c0_entryhi(entryhi);
+	write_c0_entrylo0(entrylo0);
+	write_c0_entrylo1(entrylo1);
+	tlb_write_indexed();
+
+	write_c0_entryhi(old_ctx);
+	write_c0_pagemask(old_pagemask);
+
+	local_flush_tlb_all();
+	local_irq_restore(flags);
+}
+
 /*
  * This is called from loadmmu.c.  We have to set up all the
  * memory management function pointers, as well as initialize
  * the caches and tlbs
  */
-void sb1_tlb_init(void)
+void tlb_init(void)
 {
-	write_c0_pagemask(PM_4K);
+	write_c0_pagemask(PM_DEFAULT_MASK);
+	write_c0_wired(0);
 
 	/*
 	 * We don't know what state the firmware left the TLB's in, so this is
@@ -332,11 +374,13 @@ void sb1_tlb_init(void)
 	sb1_sanitize_tlb();
 
 #ifdef CONFIG_MIPS32
-	memcpy((void *)KSEG0, except_vec0_sb1, 0x80);
-	flush_icache_range(KSEG0, KSEG0 + 0x80);
+	memcpy((void *)KSEG0, &except_vec0_sb1, 0x80);
+	memcpy((void *)(KSEG0 + 0x080), &except_vec1_generic, 0x80);
+	flush_icache_range(KSEG0, KSEG0 + 0x100);
 #endif
 #ifdef CONFIG_MIPS64
-	memcpy((void *)KSEG0 + 0x80, except_vec1_sb1, 0x80);
-	flush_icache_range(KSEG0 + 0x80, KSEG0 + 0x100);
+	memcpy((void *)CKSEG0, &except_vec0_generic, 0x80);
+	memcpy((void *)(CKSEG0 + 0x80), &except_vec1_sb1, 0x80);
+	flush_icache_range(CKSEG0, CKSEG0 + 0x100);
 #endif
 }
--- diff/arch/mips/mm/tlbex-r3k.S	2003-07-08 09:55:17.000000000 +0100
+++ source/arch/mips/mm/tlbex-r3k.S	2004-02-23 13:56:38.000000000 +0000
@@ -19,7 +19,6 @@
 #include <asm/mipsregs.h>
 #include <asm/page.h>
 #include <asm/pgtable-bits.h>
-#include <asm/processor.h>
 #include <asm/regdef.h>
 #include <asm/stackframe.h>
 
--- diff/arch/mips/momentum/ocelot_c/cpci-irq.c	2003-07-08 09:55:17.000000000 +0100
+++ source/arch/mips/momentum/ocelot_c/cpci-irq.c	2004-02-23 13:56:38.000000000 +0000
@@ -22,7 +22,6 @@
 #include <linux/irq.h>
 #include <linux/kernel.h>
 #include <asm/ptrace.h>
-#include <linux/config.h>
 #include <linux/sched.h>
 #include <linux/kernel_stat.h>
 #include <asm/io.h>
--- diff/arch/mips/momentum/ocelot_c/int-handler.S	2003-07-08 09:55:17.000000000 +0100
+++ source/arch/mips/momentum/ocelot_c/int-handler.S	2004-02-23 13:56:38.000000000 +0000
@@ -12,8 +12,6 @@
  * Free Software Foundation;  either version 2 of the  License, or (at your
  * option) any later version.
  */
-#define __ASSEMBLY__
-#include <linux/config.h>
 #include <asm/asm.h>
 #include <asm/mipsregs.h>
 #include <asm/addrspace.h>
--- diff/arch/mips/momentum/ocelot_c/irq.c	2003-07-08 09:55:17.000000000 +0100
+++ source/arch/mips/momentum/ocelot_c/irq.c	2004-02-23 13:56:38.000000000 +0000
@@ -28,6 +28,7 @@
  *  675 Mass Ave, Cambridge, MA 02139, USA.
  *
  */
+#include <linux/config.h>
 #include <linux/errno.h>
 #include <linux/init.h>
 #include <linux/kernel_stat.h>
@@ -47,120 +48,31 @@
 #include <asm/mipsregs.h>
 #include <asm/system.h>
 
-
-static spinlock_t irq_lock = SPIN_LOCK_UNLOCKED;
-
-/* Function for careful CP0 interrupt mask access */
-static inline void modify_cp0_intmask(unsigned clr_mask_in, unsigned set_mask_in)
-{
-	unsigned long status;
-	unsigned clr_mask;
-	unsigned set_mask;
-
-	/* do the low 8 bits first */
-	clr_mask = 0xff & clr_mask_in;
-	set_mask = 0xff & set_mask_in;
-	status = read_c0_status();
-	status &= ~((clr_mask & 0xFF) << 8);
-	status |= (set_mask & 0xFF) << 8;
-	write_c0_status(status);
-}
-
-static inline void mask_irq(unsigned int irq)
-{
-	modify_cp0_intmask(irq, 0);
-}
-
-static inline void unmask_irq(unsigned int irq)
-{
-	modify_cp0_intmask(0, irq);
-}
-
-static void enable_cp7000_irq(unsigned int irq)
-{
-	unsigned long flags;
-
-	spin_lock_irqsave(&irq_lock, flags);
-	unmask_irq(1 << irq);
-	spin_unlock_irqrestore(&irq_lock, flags);
-}
-
-static unsigned int startup_cp7000_irq(unsigned int irq)
-{
-	enable_cp7000_irq(irq);
-
-	return 0;				/* never anything pending */
-}
-
-static void disable_cp7000_irq(unsigned int irq)
-{
-	unsigned long flags;
-
-	spin_lock_irqsave(&irq_lock, flags);
-	mask_irq(1 << irq);
-	spin_unlock_irqrestore(&irq_lock, flags);
-}
-
-#define shutdown_cp7000_irq disable_cp7000_irq
-
-static void mask_and_ack_cp7000_irq(unsigned int irq)
-{
-	mask_irq(1 << irq);
-}
-
-static void end_cp7000_irq(unsigned int irq)
-{
-	if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
-		unmask_irq(1 << irq);
-}
-
-static struct hw_interrupt_type cp7000_hpcdma_irq_type = {
-#ifdef CONFIG_CPU_SR71000
-	"SR71000",
-#else
-	"RM7000",
-#endif
-	startup_cp7000_irq,
-	shutdown_cp7000_irq,
-	enable_cp7000_irq,
-	disable_cp7000_irq,
-	mask_and_ack_cp7000_irq,
-	end_cp7000_irq,
-	NULL
-};
-
 extern asmlinkage void ocelot_handle_int(void);
 extern void mv64340_irq_init(void);
 extern void uart_irq_init(void);
 extern void cpci_irq_init(void);
 
-static struct irqaction cascade_fpga =
-	{ no_action, SA_INTERRUPT, 0, "cascade via FPGA", NULL, NULL };
-static struct irqaction cascade_mv64340 =
-	{ no_action, SA_INTERRUPT, 0, "cascade via MV64340", NULL, NULL };
+static struct irqaction cascade_fpga = {
+	no_action, SA_INTERRUPT, 0, "cascade via FPGA", NULL, NULL
+};
+
+static struct irqaction cascade_mv64340 = {
+	no_action, SA_INTERRUPT, 0, "cascade via MV64340", NULL, NULL
+};
 
 void __init init_IRQ(void)
 {
-	int i;
-
 	/*
 	 * Clear all of the interrupts while we change the able around a bit.
 	 * int-handler is not on bootstrap
 	 */
-	clear_c0_status(ST0_IM | ST0_BEV);
-	__cli();
+	clear_c0_status(ST0_IM);
 
 	/* Sets the first-level interrupt dispatcher. */
 	set_except_vector(0, ocelot_handle_int);
 	init_generic_irq();
-
-	/* set up handler for first 8 IRQs as the CPU */
-	for (i = 0; i < 8; i++) {
-		irq_desc[i].status	= IRQ_DISABLED;
-		irq_desc[i].action	= 0;
-		irq_desc[i].depth	= 1;
-		irq_desc[i].handler	= &cp7000_hpcdma_irq_type;
-	}
+	mips_cpu_irq_init(0);
 
 	/* set up the cascading interrupts */
 	setup_irq(3, &cascade_fpga);
@@ -176,7 +88,4 @@ void __init init_IRQ(void)
 	set_debug_traps();
 	breakpoint();	/* you may move this line to whereever you want :-) */
 #endif
-#ifdef CONFIG_GDB_CONSOLE
-	register_gdb_console();
-#endif
 }
--- diff/arch/mips/momentum/ocelot_c/mv-irq.c	2003-07-08 09:55:17.000000000 +0100
+++ source/arch/mips/momentum/ocelot_c/mv-irq.c	2004-02-23 13:56:38.000000000 +0000
@@ -4,7 +4,7 @@
  *
  * arch/mips/momentum/ocelot_c/mv-irq.c
  *     Interrupt routines for mv64340.  Interrupt numbers are assigned from
- *     MV64340_IRQ_BASE to MV64340_IRQ_BASE+64.
+ *     MV64340_IRQ_BASE to MV64340_IRQ_BASE+63.
  *
  * This program is free software; you can redistribute  it and/or modify it
  * under  the terms of  the GNU General  Public License as published by the
@@ -17,7 +17,6 @@
 #include <linux/irq.h>
 #include <linux/kernel.h>
 #include <asm/ptrace.h>
-#include <linux/config.h>
 #include <linux/sched.h>
 #include <linux/kernel_stat.h>
 #include <asm/io.h>
--- diff/arch/mips/momentum/ocelot_c/ocelot_c_fpga.h	2003-07-08 09:55:17.000000000 +0100
+++ source/arch/mips/momentum/ocelot_c/ocelot_c_fpga.h	2004-02-23 13:56:38.000000000 +0000
@@ -22,11 +22,21 @@
  *  You should have received a copy of the  GNU General Public License along
  *  with this program; if not, write  to the Free Software Foundation, Inc.,
  *  675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ *  Louis Hamilton, Red Hat, Inc.
+ *    hamilton@redhat.com  [MIPS64 modifications]
  */
+
 #ifndef __OCELOT_C_FPGA_H__
 #define __OCELOT_C_FPGA_H__
 
-#define OCELOT_C_CS0_ADDR (0xfc000000)
+#include <linux/config.h>
+
+#ifdef CONFIG_MIPS64
+#define OCELOT_C_CS0_ADDR       (0xfffffffffc000000)
+#else
+#define OCELOT_C_CS0_ADDR               (0xfc000000)
+#endif
 
 #define OCELOT_C_REG_BOARDREV		0x0
 #define OCELOT_C_REG_FPGA_REV		0x1
--- diff/arch/mips/momentum/ocelot_c/pci-irq.c	2003-07-08 09:55:17.000000000 +0100
+++ source/arch/mips/momentum/ocelot_c/pci-irq.c	2004-02-23 13:56:38.000000000 +0000
@@ -17,7 +17,6 @@
 #include <linux/types.h>
 #include <linux/pci.h>
 #include <linux/kernel.h>
-#include <linux/version.h>
 #include <linux/init.h>
 #include <asm/pci.h>
 
--- diff/arch/mips/momentum/ocelot_c/prom.c	2003-07-08 09:55:17.000000000 +0100
+++ source/arch/mips/momentum/ocelot_c/prom.c	2004-02-23 13:56:38.000000000 +0000
@@ -2,6 +2,9 @@
  * Copyright 2002 Momentum Computer Inc.
  * Author: Matthew Dharm <mdharm@momenco.com>
  *
+ * Louis Hamilton, Red Hat, Inc.
+ *   hamilton@redhat.com  [MIPS64 modifications]
+ *
  * Based on Ocelot Linux port, which is
  * Copyright 2001 MontaVista Software Inc.
  * Author: jsun@mvista.com or jsun@junsun.net
@@ -35,7 +38,6 @@ struct callvectors {
 };
 
 struct callvectors* debug_vectors;
-char arcs_cmdline[CL_SIZE];
 
 extern unsigned long mv64340_base;
 extern unsigned long cpu_clock;
@@ -101,11 +103,110 @@ void get_mac(char dest[6])
 }
 #endif
 
+
+#ifdef CONFIG_MIPS64
+
+unsigned long signext(unsigned long addr)
+{
+  addr &= 0xffffffff;
+  return (unsigned long)((int)addr);
+}
+
+void *get_arg(unsigned long args, int arc)
+{
+  unsigned long ul;
+  unsigned char *puc, uc;
+
+  args += (arc * 4);
+  ul = (unsigned long)signext(args);
+  puc = (unsigned char *)ul;
+  if (puc == 0)
+    return (void *)0;
+
+#ifdef CONFIG_CPU_LITTLE_ENDIAN
+  uc = *puc++;
+  ul = (unsigned long)uc;
+  uc = *puc++;
+  ul |= (((unsigned long)uc) << 8);
+  uc = *puc++;
+  ul |= (((unsigned long)uc) << 16);
+  uc = *puc++;
+  ul |= (((unsigned long)uc) << 24);
+#else  /* CONFIG_CPU_LITTLE_ENDIAN */
+  uc = *puc++;
+  ul = ((unsigned long)uc) << 24;
+  uc = *puc++;
+  ul |= (((unsigned long)uc) << 16);
+  uc = *puc++;
+  ul |= (((unsigned long)uc) << 8);
+  uc = *puc++;
+  ul |= ((unsigned long)uc);
+#endif  /* CONFIG_CPU_LITTLE_ENDIAN */
+  ul = signext(ul);
+  return (void *)ul;
+}
+
+char *arg64(unsigned long addrin, int arg_index)
+{
+  unsigned long args;
+  char *p;
+  args = signext(addrin);
+  p = (char *)get_arg(args, arg_index);
+  return p;
+}
+#endif  /* CONFIG_MIPS64 */
+
+
 /* [jsun@junsun.net] PMON passes arguments in C main() style */
-void __init prom_init(int argc, char **arg, char** env, struct callvectors *cv)
+void __init prom_init(void)
 {
+	int argc = fw_arg0;
+	char **arg = (char **) fw_arg1;
+	char **env = (char **) fw_arg2;
 	int i;
+#ifdef CONFIG_MIPS64
+	char *ptr;
+
+	printk("prom_init - MIPS64\n");
+	/* save the PROM vectors for debugging use */
+	debug_vectors = (struct callvectors *)signext((unsigned long)cv);
+
+	/* arg[0] is "g", the rest is boot parameters */
+	arcs_cmdline[0] = '\0';
+
+	for (i = 1; i < argc; i++) {
+		ptr = (char *)arg64((unsigned long)arg, i);
+		if ((strlen(arcs_cmdline) + strlen(ptr) + 1) >=
+		    sizeof(arcs_cmdline))
+			break;
+		strcat(arcs_cmdline, ptr);
+		strcat(arcs_cmdline, " ");
+	}
+	i = 0;
+	while (1) {
+		ptr = (char *)arg64((unsigned long)env, i);
+		if (! ptr)
+			break;
+
+		if (strncmp("gtbase", ptr, strlen("gtbase")) == 0) {
+			mv64340_base = simple_strtol(ptr + strlen("gtbase="),
+							NULL, 16);
+
+			if ((mv64340_base & 0xffffffff00000000) == 0)
+				mv64340_base |= 0xffffffff00000000;
+
+			printk("mv64340_base set to 0x%016lx\n", mv64340_base);
+		}
+		if (strncmp("cpuclock", ptr, strlen("cpuclock")) == 0) {
+			cpu_clock = simple_strtol(ptr + strlen("cpuclock="),
+							NULL, 10);
+			printk("cpu_clock set to %d\n", cpu_clock);
+		}
+		i++;
+	}
+	printk("arcs_cmdline: %s\n", arcs_cmdline);
 
+#else   /* CONFIG_MIPS64 */
 	/* save the PROM vectors for debugging use */
 	debug_vectors = cv;
 
@@ -119,9 +220,6 @@ void __init prom_init(int argc, char **a
 		strcat(arcs_cmdline, " ");
 	}
 
-	mips_machgroup = MACH_GROUP_MOMENCO;
-	mips_machtype = MACH_MOMENCO_OCELOT_C;
-
 	while (*env) {
 		if (strncmp("gtbase", *env, strlen("gtbase")) == 0) {
 			mv64340_base = simple_strtol(*env + strlen("gtbase="),
@@ -133,19 +231,22 @@ void __init prom_init(int argc, char **a
 		}
 		env++;
 	}
+#endif /* CONFIG_MIPS64 */
+
+	mips_machgroup = MACH_GROUP_MOMENCO;
+	mips_machtype = MACH_MOMENCO_OCELOT_C;
 
 #ifdef CONFIG_MV64340_ETH
 	/* get the base MAC address for on-board ethernet ports */
 	get_mac(prom_mac_addr_base);
 #endif
 
+#ifndef CONFIG_MIPS64
 	debug_vectors->printf("Booting Linux kernel...\n");
+#endif
 }
 
-void __init prom_free_prom_memory(void)
-{
-}
-
-void __init prom_fixup_mem_map(unsigned long start, unsigned long end)
+unsigned long __init prom_free_prom_memory(void)
 {
+	return 0;
 }
--- diff/arch/mips/momentum/ocelot_c/reset.c	2003-07-08 09:55:17.000000000 +0100
+++ source/arch/mips/momentum/ocelot_c/reset.c	2004-02-23 13:56:38.000000000 +0000
@@ -10,7 +10,11 @@
  *
  * Copyright (C) 2002 Momentum Computer Inc.
  * Author: Matthew Dharm <mdharm@momenco.com>
+ *
+ * Louis Hamilton, Red Hat, Inc.
+ * hamilton@redhat.com  [MIPS64 modifications]
  */
+#include <linux/config.h>
 #include <linux/sched.h>
 #include <linux/mm.h>
 #include <asm/io.h>
@@ -23,7 +27,12 @@
 void momenco_ocelot_restart(char *command)
 {
 	/* base address of timekeeper portion of part */
-	void *nvram = (void*) 0xfc807000;
+	void *nvram = (void *)
+#ifdef CONFIG_MIPS64
+		0xfffffffffc807000;
+#else
+		0xfc807000;
+#endif
 
  	/* Ask the NVRAM/RTC/watchdog chip to assert reset in 1/16 second */
 	writeb(0x84, nvram + 0xff7);
--- diff/arch/mips/momentum/ocelot_c/setup.c	2003-08-20 14:16:08.000000000 +0100
+++ source/arch/mips/momentum/ocelot_c/setup.c	2004-02-23 13:56:38.000000000 +0000
@@ -10,6 +10,9 @@
  * Author: Matthew Dharm, Momentum Computer
  *   mdharm@momenco.com
  *
+ * Louis Hamilton, Red Hat, Inc.
+ *   hamilton@redhat.com  [MIPS64 modifications]
+ *
  * Author: RidgeRun, Inc.
  *   glonnon@ridgerun.com, skranz@ridgerun.com, stevej@ridgerun.com
  *
@@ -37,11 +40,11 @@
  *  675 Mass Ave, Cambridge, MA 02139, USA.
  *
  */
+#include <linux/config.h>
 #include <linux/bcd.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/types.h>
-#include <linux/mc146818rtc.h>
 #include <linux/mm.h>
 #include <linux/swap.h>
 #include <linux/ioport.h>
@@ -53,21 +56,19 @@
 #include <asm/time.h>
 #include <asm/bootinfo.h>
 #include <asm/page.h>
-#include <asm/bootinfo.h>
 #include <asm/io.h>
 #include <asm/irq.h>
 #include <asm/pci.h>
 #include <asm/processor.h>
 #include <asm/ptrace.h>
 #include <asm/reboot.h>
-#include <asm/mc146818rtc.h>
-#include <linux/version.h>
 #include <linux/bootmem.h>
 #include <linux/blkdev.h>
 #include <asm/mv64340.h>
 #include "ocelot_c_fpga.h"
 
 unsigned long mv64340_base;
+extern unsigned long mv64340_sram_base;
 unsigned long cpu_clock;
 
 /* These functions are used for rebooting or halting the machine*/
@@ -79,6 +80,7 @@ void momenco_time_init(void);
 
 static char reset_reason;
 
+void add_wired_entry(unsigned long entrylo0, unsigned long entrylo1, unsigned long entryhi, unsigned long pagemask);
 #define ENTRYLO(x) ((pte_val(mk_pte_phys((x), PAGE_KERNEL_UNCACHED)) >> 6)|1)
 
 /* setup code for a handoff from a version 2 PMON 2000 PROM */
@@ -99,7 +101,19 @@ void PMON_v2_setup(void)
 		Internal SRAM		0xfe000000	0xfe000000
 		M-Systems DOC (CS3)	0xff000000	0xff000000
 	*/
+  printk("PMON_v2_setup\n");
 
+#ifdef CONFIG_MIPS64
+	/* marvell and extra space */
+	add_wired_entry(ENTRYLO(0xf4000000), ENTRYLO(0xf4010000), 0xfffffffff4000000, PM_64K);
+	/* fpga, rtc, and uart */
+	add_wired_entry(ENTRYLO(0xfc000000), ENTRYLO(0xfd000000), 0xfffffffffc000000, PM_16M);
+	/* m-sys and internal SRAM */
+	add_wired_entry(ENTRYLO(0xfe000000), ENTRYLO(0xff000000), 0xfffffffffe000000, PM_16M);
+
+	mv64340_base = 0xfffffffff4000000;
+	mv64340_sram_base = 0xfffffffffe000000;
+#else
 	/* marvell and extra space */
 	add_wired_entry(ENTRYLO(0xf4000000), ENTRYLO(0xf4010000), 0xf4000000, PM_64K);
 	/* fpga, rtc, and uart */
@@ -108,11 +122,17 @@ void PMON_v2_setup(void)
 	add_wired_entry(ENTRYLO(0xfe000000), ENTRYLO(0xff000000), 0xfe000000, PM_16M);
 
 	mv64340_base = 0xf4000000;
+	mv64340_sram_base = 0xfe000000;
+#endif
 }
 
 unsigned long m48t37y_get_time(void)
 {
+#ifdef CONFIG_MIPS64
+	unsigned char *rtc_base = (unsigned char*)0xfffffffffc800000;
+#else
 	unsigned char* rtc_base = (unsigned char*)0xfc800000;
+#endif
 	unsigned int year, month, day, hour, min, sec;
 
 	/* stop the update */
@@ -137,7 +157,11 @@ unsigned long m48t37y_get_time(void)
 
 int m48t37y_set_time(unsigned long sec)
 {
+#ifdef CONFIG_MIPS64
+	unsigned char* rtc_base = (unsigned char*)0xfffffffffc800000;
+#else
 	unsigned char* rtc_base = (unsigned char*)0xfc800000;
+#endif
 	struct rtc_time tm;
 
 	/* convert to a more useful format -- note months count from 0 */
@@ -179,19 +203,20 @@ void momenco_timer_setup(struct irqactio
 void momenco_time_init(void)
 {
 #ifdef CONFIG_CPU_SR71000
-	mips_counter_frequency = cpu_clock;
+	mips_hpt_frequency = cpu_clock;
 #elif defined(CONFIG_CPU_RM7000)
-	mips_counter_frequency = cpu_clock / 2;
+	mips_hpt_frequency = cpu_clock / 2;
 #else
 #error Unknown CPU for this board
 #endif
+	printk("momenco_time_init cpu_clock=%d\n", cpu_clock);
 	board_timer_setup = momenco_timer_setup;
 
 	rtc_get_time = m48t37y_get_time;
 	rtc_set_time = m48t37y_set_time;
 }
 
-void __init momenco_ocelot_c_setup(void)
+static void __init momenco_ocelot_c_setup(void)
 {
 	unsigned int tmpword;
 
@@ -307,6 +332,9 @@ void __init momenco_ocelot_c_setup(void)
 	}
 }
 
+early_initcall(momenco_ocelot_c_setup);
+
+#ifndef CONFIG_MIPS64
 /* This needs to be one of the first initcalls, because no I/O port access
    can work before this */
 static int io_base_ioremap(void)
@@ -324,3 +352,4 @@ static int io_base_ioremap(void)
 }
 
 module_init(io_base_ioremap);
+#endif
--- diff/arch/mips/momentum/ocelot_c/uart-irq.c	2003-07-08 09:55:17.000000000 +0100
+++ source/arch/mips/momentum/ocelot_c/uart-irq.c	2004-02-23 13:56:38.000000000 +0000
@@ -17,7 +17,6 @@
 #include <linux/irq.h>
 #include <linux/kernel.h>
 #include <asm/ptrace.h>
-#include <linux/config.h>
 #include <linux/sched.h>
 #include <linux/kernel_stat.h>
 #include <asm/io.h>
--- diff/arch/mips/momentum/ocelot_g/gt-irq.c	2003-07-08 09:55:17.000000000 +0100
+++ source/arch/mips/momentum/ocelot_g/gt-irq.c	2004-02-23 13:56:38.000000000 +0000
@@ -15,7 +15,6 @@
 #include <linux/interrupt.h>
 #include <linux/kernel.h>
 #include <asm/ptrace.h>
-#include <linux/config.h>
 #include <linux/sched.h>
 #include <linux/kernel_stat.h>
 #include <asm/io.h>
--- diff/arch/mips/momentum/ocelot_g/int-handler.S	2003-07-08 09:55:17.000000000 +0100
+++ source/arch/mips/momentum/ocelot_g/int-handler.S	2004-02-23 13:56:38.000000000 +0000
@@ -9,8 +9,6 @@
  * Free Software Foundation;  either version 2 of the  License, or (at your
  * option) any later version.
  */
-#define __ASSEMBLY__
-#include <linux/config.h>
 #include <asm/asm.h>
 #include <asm/mipsregs.h>
 #include <asm/addrspace.h>
--- diff/arch/mips/momentum/ocelot_g/irq.c	2003-07-08 09:55:17.000000000 +0100
+++ source/arch/mips/momentum/ocelot_g/irq.c	2004-02-23 13:56:38.000000000 +0000
@@ -28,6 +28,7 @@
  *  675 Mass Ave, Cambridge, MA 02139, USA.
  *
  */
+#include <linux/config.h>
 #include <linux/errno.h>
 #include <linux/init.h>
 #include <linux/kernel_stat.h>
@@ -44,120 +45,27 @@
 #include <asm/bootinfo.h>
 #include <asm/io.h>
 #include <asm/irq.h>
+#include <asm/irq_cpu.h>
 #include <asm/mipsregs.h>
 #include <asm/system.h>
 
-
-static spinlock_t rm7000_irq_lock = SPIN_LOCK_UNLOCKED;
-
-/* Function for careful CP0 interrupt mask access */
-static inline void modify_cp0_intmask(unsigned clr_mask_in, unsigned set_mask_in)
-{
-	unsigned long status;
-	unsigned clr_mask;
-	unsigned set_mask;
-
-	/* do the low 8 bits first */
-	clr_mask = 0xff & clr_mask_in;
-	set_mask = 0xff & set_mask_in;
-	status = read_c0_status();
-	status &= ~((clr_mask & 0xFF) << 8);
-	status |= (set_mask & 0xFF) << 8;
-	write_c0_status(status);
-
-	/* do the high 8 bits */
-	clr_mask = 0xff & (clr_mask_in >> 8);
-	set_mask = 0xff & (set_mask_in >> 8);
-	status = read_c0_intcontrol();
-	status &= ~((clr_mask & 0xFF) << 8);
-	status |= (set_mask & 0xFF) << 8;
-	write_c0_intrcontrol(status);
-}
-
-static inline void mask_irq(unsigned int irq)
-{
-	modify_cp0_intmask(irq, 0);
-}
-
-static inline void unmask_irq(unsigned int irq)
-{
-	modify_cp0_intmask(0, irq);
-}
-
-static void enable_cp7000_irq(unsigned int irq)
-{
-	unsigned long flags;
-
-	spin_lock_irqsave(&rm7000_irq_lock, flags);
-	unmask_irq(1 << irq);
-	spin_unlock_irqrestore(&rm7000_irq_lock, flags);
-}
-
-static unsigned int startup_cp7000_irq(unsigned int irq)
-{
-	enable_cp7000_irq(irq);
-
-	return 0;				/* never anything pending */
-}
-
-static void disable_cp7000_irq(unsigned int irq)
-{
-	unsigned long flags;
-
-	spin_lock_irqsave(&rm7000_irq_lock, flags);
-	mask_irq(1 << irq);
-	spin_unlock_irqrestore(&rm7000_irq_lock, flags);
-}
-
-#define shutdown_cp7000_irq disable_cp7000_irq
-
-static void mask_and_ack_cp7000_irq(unsigned int irq)
-{
-	mask_irq(1 << irq);
-}
-
-static void end_cp7000_irq(unsigned int irq)
-{
-	if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
-		unmask_irq(1 << irq);
-}
-
-static struct hw_interrupt_type cp7000_hpcdma_irq_type = {
-	"CP7000",
-	startup_cp7000_irq,
-	shutdown_cp7000_irq,
-	enable_cp7000_irq,
-	disable_cp7000_irq,
-	mask_and_ack_cp7000_irq,
-	end_cp7000_irq,
-	NULL
-};
-
-
 extern asmlinkage void ocelot_handle_int(void);
 extern void gt64240_irq_init(void);
 
 void __init init_IRQ(void)
 {
-	int i;
-
 	/*
 	 * Clear all of the interrupts while we change the able around a bit.
 	 * int-handler is not on bootstrap
 	 */
-	clear_c0_status(ST0_IM | ST0_BEV);
+	clear_c0_status(ST0_IM);
 	local_irq_disable();
 
 	/* Sets the first-level interrupt dispatcher. */
 	set_except_vector(0, ocelot_handle_int);
 	init_generic_irq();
-
-	for (i = 0; i <= 15; i++) {
-		irq_desc[i].status	= IRQ_DISABLED;
-		irq_desc[i].action	= 0;
-		irq_desc[i].depth	= 1;
-		irq_desc[i].handler	= &cp7000_hpcdma_irq_type;
-	}
+	mips_cpu_irq_init(0);
+	rm7k_cpu_irq_init(8);
 
 	gt64240_irq_init();
 
@@ -166,7 +74,4 @@ void __init init_IRQ(void)
 	set_debug_traps();
 	breakpoint();	/* you may move this line to whereever you want :-) */
 #endif
-#ifdef CONFIG_GDB_CONSOLE
-	register_gdb_console();
-#endif
 }
--- diff/arch/mips/momentum/ocelot_g/pci-irq.c	2003-07-08 09:55:17.000000000 +0100
+++ source/arch/mips/momentum/ocelot_g/pci-irq.c	2004-02-23 13:56:38.000000000 +0000
@@ -17,7 +17,6 @@
 #include <linux/types.h>
 #include <linux/pci.h>
 #include <linux/kernel.h>
-#include <linux/version.h>
 #include <linux/init.h>
 #include <asm/pci.h>
 
--- diff/arch/mips/momentum/ocelot_g/prom.c	2003-07-08 09:55:17.000000000 +0100
+++ source/arch/mips/momentum/ocelot_g/prom.c	2004-02-23 13:56:38.000000000 +0000
@@ -35,7 +35,6 @@ struct callvectors {
 };
 
 struct callvectors* debug_vectors;
-char arcs_cmdline[CL_SIZE];
 
 extern unsigned long gt64240_base;
 extern unsigned long bus_clock;
@@ -50,10 +49,14 @@ const char *get_system_type(void)
 }
 
 /* [jsun@junsun.net] PMON passes arguments in C main() style */
-void __init prom_init(int argc, char **arg, char** env, struct callvectors *cv)
+void __init prom_init(void)
 {
-	int i;
 	uint32_t tmp;
+	int argc = fw_arg0;
+	char **arg = (char **) fw_arg1;
+	char **env = (char **) fw_arg2;
+	struct callvectors *cv = (struct callvectors *) fw_arg3;
+	int i;
 
 	/* save the PROM vectors for debugging use */
 	debug_vectors = cv;
@@ -91,10 +94,7 @@ void __init prom_init(int argc, char **a
 	debug_vectors->printf("Booting Linux kernel...\n");
 }
 
-void __init prom_free_prom_memory(void)
-{
-}
-
-void __init prom_fixup_mem_map(unsigned long start, unsigned long end)
+unsigned long __init prom_free_prom_memory(void)
 {
+	return 0;
 }
--- diff/arch/mips/momentum/ocelot_g/setup.c	2003-08-20 14:16:08.000000000 +0100
+++ source/arch/mips/momentum/ocelot_g/setup.c	2004-02-23 13:56:38.000000000 +0000
@@ -39,10 +39,10 @@
  *  675 Mass Ave, Cambridge, MA 02139, USA.
  *
  */
+#include <linux/config.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/types.h>
-#include <linux/mc146818rtc.h>
 #include <linux/mm.h>
 #include <linux/swap.h>
 #include <linux/ioport.h>
@@ -54,22 +54,17 @@
 #include <asm/time.h>
 #include <asm/bootinfo.h>
 #include <asm/page.h>
-#include <asm/bootinfo.h>
 #include <asm/io.h>
 #include <asm/irq.h>
 #include <asm/pci.h>
 #include <asm/processor.h>
 #include <asm/ptrace.h>
 #include <asm/reboot.h>
-#include <asm/mc146818rtc.h>
-#include <linux/version.h>
 #include <linux/bootmem.h>
 #include <linux/blkdev.h>
 #include "gt64240.h"
 #include "ocelot_pld.h"
 
-extern struct rtc_ops no_rtc_ops;
-
 #ifdef CONFIG_GALILLEO_GT64240_ETH
 extern unsigned char prom_mac_addr_base[6];
 #endif
@@ -120,7 +115,7 @@ void PMON_v2_setup(void)
 	gt64240_base = 0xf4000000;
 }
 
-void __init momenco_ocelot_g_setup(void)
+static void __init momenco_ocelot_g_setup(void)
 {
 	void (*l3func)(unsigned long)=KSEG1ADDR(&setup_l3cache);
 	unsigned int tmpword;
@@ -136,7 +131,6 @@ void __init momenco_ocelot_g_setup(void)
 	 * initrd_end = (ulong)ocelot_initrd_start + (ulong)ocelot_initrd_size;
 	 * initrd_below_start_ok = 1;
 	 */
-	rtc_ops = &no_rtc_ops;
 
 	/* do handoff reconfiguration */
 	PMON_v2_setup();
@@ -203,6 +197,8 @@ void __init momenco_ocelot_g_setup(void)
 	GT_WRITE(0x468, 0xfef73);
 }
 
+early_initcall(momenco_ocelot_g_setup);
+
 extern int rm7k_tcache_enabled;
 /*
  * This runs in KSEG1. See the verbiage in rm7k.c::probe_scache()
--- diff/arch/mips/pci/Makefile	2003-08-20 14:16:25.000000000 +0100
+++ source/arch/mips/pci/Makefile	2004-02-23 13:56:38.000000000 +0000
@@ -1,36 +1,50 @@
 #
 # Makefile for the PCI specific kernel interface routines under Linux.
 #
-# This is all organized on a per system base which is horribly wrong and
-# really wants a cleanup.  You have been warned.
+
+obj-y				+= pci.o
+
+#
+# PCI bus host bridge specific code
 #
+obj-$(CONFIG_ITE_BOARD_GEN)	+= ops-it8172.o
+obj-$(CONFIG_MIPS_BONITO64)	+= ops-bonito64.o
+obj-$(CONFIG_MIPS_GT64111)	+= ops-gt64111.o
+obj-$(CONFIG_MIPS_GT64120)	+= ops-gt64120.o
+obj-$(CONFIG_MIPS_GT96100)	+= ops-gt96100.o
+obj-$(CONFIG_MIPS_MV64340)	+= ops-mv64340.o
+obj-$(CONFIG_MIPS_MSC)		+= ops-msc.o
+obj-$(CONFIG_MIPS_NILE4)	+= ops-nile4.o
+obj-$(CONFIG_MIPS_TX3927)	+= ops-jmr3927.o
 
-obj-$(CONFIG_NEW_PCI)		+= pci.o
-obj-$(CONFIG_PCI_AUTO)		+= pci-auto.o
-obj-$(CONFIG_DDB5074)		+= pci-ddb5074.o ops-ddb5074.o
-obj-$(CONFIG_DDB5476)		+= pci-ddb5476.o ops-ddb5476.o
-obj-$(CONFIG_DDB5477)		+= pci-ddb5477.o ops-ddb5477.o
+#
+# These are still pretty much in the old state, watch, go blind.
+#
+obj-$(CONFIG_DDB5074)		+= fixup-ddb5074.o pci-ddb5074.o ops-ddb5074.o
+obj-$(CONFIG_DDB5476)		+= ops-ddb5476.o pci-ddb5476.o
+obj-$(CONFIG_DDB5477)		+= fixup-ddb5477.o pci-ddb5477.o ops-ddb5477.o
 obj-$(CONFIG_HP_LASERJET)	+= pci-hplj.o
-obj-$(CONFIG_ITE_BOARD_GEN)	+= ops-it8172.o
-obj-$(CONFIG_LASAT)		+= pci-lasat.o common.o
-obj-$(CONFIG_MIPS_BOARDS_GEN)	+= pci-mips.o
-obj-$(CONFIG_MIPS_COBALT)	+= pci-cobalt.o
-obj-$(CONFIG_MIPS_EV64120)	+= ops-ev64120.o
-obj-$(CONFIG_MIPS_EV96100)	+= fixup-ev96100.o ops-ev96100.o
+obj-$(CONFIG_MIPS_ATLAS)	+= fixup-atlas.o
+obj-$(CONFIG_MIPS_COBALT)	+= fixup-cobalt.o
+obj-$(CONFIG_MIPS_EV96100)	+= fixup-ev64120.o
+obj-$(CONFIG_MIPS_EV96100)	+= fixup-ev96100.o pci-ev96100.o
 obj-$(CONFIG_MIPS_ITE8172)	+= fixup-ite8172g.o
 obj-$(CONFIG_MIPS_IVR)		+= fixup-ivr.o
-obj-$(CONFIG_MIPS_PB1500)	+= fixups-au1000.o ops-au1000.o
-obj-$(CONFIG_MOMENCO_OCELOT)	+= fixups-ocelot.o ops-ocelot.o
+obj-$(CONFIG_SOC_AU1500)	+= fixup-au1000.o ops-au1000.o
+obj-$(CONFIG_MIPS_MALTA)	+= fixup-malta.o
+obj-$(CONFIG_MOMENCO_OCELOT)	+= fixup-ocelot.o pci-ocelot.o
+obj-$(CONFIG_MOMENCO_OCELOT_C)	+= pci-ocelot-c.o
+obj-$(CONFIG_MOMENCO_OCELOT_G)	+= pci-ocelot-g.o
 obj-$(CONFIG_NEC_EAGLE)		+= fixup-eagle.o ops-vrc4173.o
+obj-$(CONFIG_PMC_YOSEMITE)	+= fixup-yosemite.o ops-titan.o
 obj-$(CONFIG_SGI_IP27)		+= pci-ip27.o
-obj-$(CONFIG_SGI_IP32)		+= pci-ip32.o
+obj-$(CONFIG_SGI_IP32)		+= fixup-ip32.o ops-mace.o pci-ip32.o
 obj-$(CONFIG_SIBYTE_SB1250)	+= pci-sb1250.o
-obj-$(CONFIG_SNI_RM200_PCI)	+= pci-sni.o
+obj-$(CONFIG_SNI_RM200_PCI)	+= fixup-sni.o ops-sni.o
 obj-$(CONFIG_TANBAC_TB0226)	+= fixup-tb0226.o
 obj-$(CONFIG_TANBAC_TB0229)	+= fixup-tb0229.o
-obj-$(CONFIG_TOSHIBA_JMR3927)	+= fixup-jmr3927.o ops-jmr3927.o
-#obj-$(CONFIG_MOMENCO_OCELOT_C)	+= pci-ocelot-c.o
-obj-$(CONFIG_MOMENCO_OCELOT_G)	+= pci-ocelot-g.o
+obj-$(CONFIG_TOSHIBA_JMR3927)	+= fixup-jmr3927.o pci-jmr3927.o
+obj-$(CONFIG_TOSHIBA_RBTX4927)	+= fixup-rbtx4927.o ops-tx4927.o
 obj-$(CONFIG_VICTOR_MPC30X)	+= fixup-capcella.o
-obj-$(CONFIG_VR41XX_COMMON)	+= pci-vr41xx.o
+obj-$(CONFIG_MACH_VR41XX)	+= pci-vr41xx.o
 obj-$(CONFIG_ZAO_CAPCELLA)	+= fixup-victor-mpc30x.o
--- diff/arch/mips/pci/fixup-au1000.c	2003-07-08 09:55:17.000000000 +0100
+++ source/arch/mips/pci/fixup-au1000.c	2004-02-23 13:56:38.000000000 +0000
@@ -32,93 +32,31 @@
 #include <linux/kernel.h>
 #include <linux/init.h>
 
-#include <asm/au1000.h>
+#include <asm/mach-au1x00/au1000.h>
 //#include <asm/pb1500.h>
 #ifdef CONFIG_MIPS_PB1000
-#include <asm/pb1000.h>
+#include <asm/mach-pb1x00/pb1000.h>
 #endif
 
-#undef	DEBUG
-#ifdef 	DEBUG
-#define	DBG(x...)	printk(x)
-#else
-#define	DBG(x...)
-#endif
+/*
+ * Shortcut
+ */
+#define INTA	AU1000_PCI_INTA
+#define INTB	AU1000_PCI_INTB
 
-static void fixup_resource(int r_num, struct pci_dev *dev);
-#ifdef CONFIG_SOC_AU1500
-static unsigned long virt_io_addr;
+static char irq_tab_alchemy[][5] __initdata = {
+ [11] = { -1, INTA, INTA, INTA, INTA },
+ [12] = { -1, INTA, INTA, INTA, INTA }
+#if defined( CONFIG_SOC_AU1550 )
+ [13] = { -1, INTB, INTB, INTB, INTB }
 #endif
+};
 
-void __init pcibios_fixup_resources(struct pci_dev *dev)
-{
-	/* will need to fixup IO resources */
-}
-
-void __init pcibios_fixup(void)
+int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
 {
-#ifdef CONFIG_SOC_AU1500
-	int i;
-	struct pci_dev *dev;
-
-	virt_io_addr = (unsigned long) ioremap(Au1500_PCI_IO_START,
-					       Au1500_PCI_IO_END -
-					       Au1500_PCI_IO_START + 1);
-
-	if (!virt_io_addr) {
-		printk(KERN_ERR "Unable to ioremap pci space\n");
-		return;
-	}
-
-	set_io_port_base(virt_io_addr);
-#endif
-
-#ifdef CONFIG_MIPS_PB1000	/* This is truly board specific */
-	unsigned long pci_mem_start = (unsigned long) PCI_MEM_START;
-
-	au_writel(0, PCI_BRIDGE_CONFIG);	// set extend byte to 0
-	au_writel(0, SDRAM_MBAR);	// set mbar to 0
-	au_writel(0x2, SDRAM_CMD);	// enable memory accesses
-	au_sync_delay(1);
-
-	// set extend byte to mbar of ext slot
-	au_writel(((pci_mem_start >> 24) & 0xff) |
-		  (1 << 8 | 1 << 9 | 1 << 10 | 1 << 27),
-		  PCI_BRIDGE_CONFIG);
-	DBG("Set bridge config to %x\n", au_readl(PCI_BRIDGE_CONFIG));
-#endif
+	return irq_tab_alchemy[slot][pin];
 }
 
-void __init pcibios_fixup_irqs(void)
-{
-#ifdef CONFIG_SOC_AU1500
-	unsigned int slot, func;
-	unsigned char pin;
-	struct pci_dev *dev = NULL;
-
-	while ((dev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) {
-		if (dev->bus->number != 0)
-			return;
-
-		dev->irq = 0xff;
-		slot = PCI_SLOT(dev->devfn);
-		switch (slot) {
-		case 12:
-		case 13:
-			dev->irq = AU1000_PCI_INTA;
-			break;
-
-		}
-		pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq);
-		DBG("slot %d irq %d\n", slot, dev->irq);
-	}
-#endif
-}
-unsigned int pcibios_assign_all_busses(void)
-{
-	return 0;
-}
-
-static void fixup_resource(int r_num, struct pci_dev *dev)
-{
-}
+struct pci_fixup pcibios_fixups[] __initdata = {
+	{ 0 }
+};
--- diff/arch/mips/pci/fixup-capcella.c	2003-07-08 09:55:17.000000000 +0100
+++ source/arch/mips/pci/fixup-capcella.c	2004-02-23 13:56:38.000000000 +0000
@@ -18,55 +18,23 @@
 
 #include <asm/vr41xx/capcella.h>
 
-void __init pcibios_fixup_resources(struct pci_dev *dev)
-{
-}
-
-void __init pcibios_fixup(void)
-{
-}
-
-void __init pcibios_fixup_irqs(void)
-{
-	struct pci_dev *dev = NULL;
-	u8 slot, func, pin;
-
-	while ((dev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) {
-		slot = PCI_SLOT(dev->devfn);
-		func = PCI_FUNC(dev->devfn);
-		dev->irq = 0;
-
-		switch (slot) {
-		case 11:
-			dev->irq = RTL8139_1_IRQ;
-			break;
-		case 12:
-			dev->irq = RTL8139_2_IRQ;
-			break;
-		case 14:
-			pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin);
-			switch (pin) {
-			case 1:
-				dev->irq = PC104PLUS_INTA_IRQ;
-				break;
-			case 2:
-				dev->irq = PC104PLUS_INTB_IRQ;
-				break;
-			case 3:
-				dev->irq = PC104PLUS_INTC_IRQ;
-				break;
-			case 4:
-				dev->irq = PC104PLUS_INTD_IRQ;
-				break;
-			}
-			break;
-		}
-
-		pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq);
-	}
-}
+/*
+ * Shortcuts
+ */
+#define INT1	RTL8139_1_IRQ
+#define INT2	RTL8139_2_IRQ
+#define INTA	PC104PLUS_INTA_IRQ
+#define INTB	PC104PLUS_INTB_IRQ
+#define INTC	PC104PLUS_INTC_IRQ
+#define INTD	PC104PLUS_INTD_IRQ
+
+static char irq_tab_capcella[][5] __initdata = {
+ [11] = { -1, INT1, INT1, INT1, INT1 },
+ [12] = { -1, INT2, INT2, INT2, INT2 },
+ [14] = { -1, INTA, INTB, INTC, INTD }
+};
 
-unsigned int pcibios_assign_all_busses(void)
+int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
 {
-	return 0;
+	return irq_tab_capcella[slot][pin];
 }
--- diff/arch/mips/pci/fixup-eagle.c	2003-07-08 09:55:17.000000000 +0100
+++ source/arch/mips/pci/fixup-eagle.c	2004-02-23 13:56:38.000000000 +0000
@@ -1,46 +1,14 @@
 /*
- * FILE NAME
- *	arch/mips/vr41xx/nec-eagle/pci_fixup.c
+ * arch/mips/vr41xx/nec-eagle/pci_fixup.c
  *
- * BRIEF MODULE DESCRIPTION
- *	The NEC Eagle/Hawk Board specific PCI fixups.
+ * The NEC Eagle/Hawk Board specific PCI fixups.
  *
- * Author: Yoichi Yuasa
- *         yyuasa@mvista.com or source@mvista.com
+ * Author: Yoichi Yuasa <you@mvista.com, or source@mvista.com>
  *
- * Copyright 2001,2002 MontaVista Software Inc.
- *
- *  This program is free software; you can redistribute it and/or modify it
- *  under the terms of the GNU General Public License as published by the
- *  Free Software Foundation; either version 2 of the License, or (at your
- *  option) any later version.
- *
- *  THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
- *  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- *  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
- *  OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- *  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
- *  TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
- *  USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- *  You should have received a copy of the GNU General Public License along
- *  with this program; if not, write to the Free Software Foundation, Inc.,
- *  675 Mass Ave, Cambridge, MA 02139, USA.
- */
-/*
- * Changes:
- *  MontaVista Software Inc. <yyuasa@mvista.com> or <source@mvista.com>
- *  - Moved mips_pci_channels[] to arch/mips/vr41xx/vr4122/eagle/setup.c.
- *  - Added support for NEC Hawk.
- *
- *  Paul Mundt <lethal@chaoticdreams.org>
- *  - Fix empty break statements.
- *
- *  MontaVista Software Inc. <yyuasa@mvista.com> or <source@mvista.com>
- *  - New creation, NEC Eagle is supported.
+ * 2001-2002,2004 (c) MontaVista, Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
  */
 #include <linux/init.h>
 #include <linux/pci.h>
@@ -48,119 +16,45 @@
 #include <asm/vr41xx/eagle.h>
 #include <asm/vr41xx/vrc4173.h>
 
-void __init pcibios_fixup_resources(struct pci_dev *dev)
-{
-}
+/*
+ * Shortcuts
+ */
+#define INTA	CP_INTA_IRQ
+#define INTB	CP_INTB_IRQ
+#define INTC	CP_INTC_IRQ
+#define INTD	CP_INTD_IRQ
+#define PCMCIA1	VRC4173_PCMCIA1_IRQ
+#define PCMCIA2	VRC4173_PCMCIA2_IRQ
+#define LAN	LANINTA_IRQ
+#define SLOT	PCISLOT_IRQ
+
+static char irq_tab_eagle[][5] __initdata = {
+ [ 8] = { 0,    INTA, INTB, INTC, INTD },
+ [ 9] = { 0,    INTD, INTA, INTB, INTC },
+ [10] = { 0,    INTC, INTD, INTA, INTB },
+ [12] = { 0, PCMCIA1,    0,    0,    0 },
+ [13] = { 0, PCMCIA2,    0,    0,    0 },
+ [28] = { 0,     LAN,    0,    0,    0 },
+ [29] = { 0,    SLOT, INTB, INTC, INTD },
+};
 
-void __init pcibios_fixup(void)
-{
-}
+/*
+ * This is a multifunction device.
+ */
+static char irq_func_tab[] __initdata = {
+	VRC4173_CASCADE_IRQ,
+	VRC4173_AC97_IRQ,
+	VRC4173_USB_IRQ
+};
 
-void __init pcibios_fixup_irqs(void)
+int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
 {
-	struct pci_dev *dev = NULL;
-	u8 slot, func, pin;
-
-	while ((dev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) {
-		slot = PCI_SLOT(dev->devfn);
-		func = PCI_FUNC(dev->devfn);
-		pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin);
-		dev->irq = 0;
-
-		switch (slot) {
-		case 8:
-			switch (pin) {
-			case 1:
-				dev->irq = CP_INTA_IRQ;
-				break;
-			case 2:
-				dev->irq = CP_INTB_IRQ;
-				break;
-			case 3:
-				dev->irq = CP_INTC_IRQ;
-				break;
-			case 4:
-				dev->irq = CP_INTD_IRQ;
-				break;
-			}
-			break;
-		case 9:
-			switch (pin) {
-			case 1:
-				dev->irq = CP_INTD_IRQ;
-				break;
-			case 2:
-				dev->irq = CP_INTA_IRQ;
-				break;
-			case 3:
-				dev->irq = CP_INTB_IRQ;
-				break;
-			case 4:
-				dev->irq = CP_INTC_IRQ;
-				break;
-			}
-			break;
-		case 10:
-			switch (pin) {
-			case 1:
-				dev->irq = CP_INTC_IRQ;
-				break;
-			case 2:
-				dev->irq = CP_INTD_IRQ;
-				break;
-			case 3:
-				dev->irq = CP_INTA_IRQ;
-				break;
-			case 4:
-				dev->irq = CP_INTB_IRQ;
-				break;
-			}
-			break;
-		case 12:
-			dev->irq = VRC4173_PCMCIA1_IRQ;
-			break;
-		case 13:
-			dev->irq = VRC4173_PCMCIA2_IRQ;
-			break;
-		case 28:
-			dev->irq = LANINTA_IRQ;
-			break;
-		case 29:
-			switch (pin) {
-			case 1:
-				dev->irq = PCISLOT_IRQ;
-				break;
-			case 2:
-				dev->irq = CP_INTB_IRQ;
-				break;
-			case 3:
-				dev->irq = CP_INTC_IRQ;
-				break;
-			case 4:
-				dev->irq = CP_INTD_IRQ;
-				break;
-			}
-			break;
-		case 30:
-			switch (func) {
-			case 0:
-				dev->irq = VRC4173_CASCADE_IRQ;
-				break;
-			case 1:
-				dev->irq = VRC4173_AC97_IRQ;
-				break;
-			case 2:
-				dev->irq = VRC4173_USB_IRQ;
-				break;
-			}
-			break;
-		}
+	if (slot == 30)
+		return irq_func_tab[PCI_FUNC(dev->devfn)];
 
-		pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq);
-	}
+	return irq_tab_eagle[slot][pin];
 }
 
-unsigned int pcibios_assign_all_busses(void)
-{
-	return 0;
-}
+struct pci_fixup pcibios_fixups[] __initdata = {
+	{	.pass = 0,	},
+};
--- diff/arch/mips/pci/fixup-ite8172g.c	2003-07-08 09:55:17.000000000 +0100
+++ source/arch/mips/pci/fixup-ite8172g.c	2004-02-23 13:56:38.000000000 +0000
@@ -35,155 +35,40 @@
 #include <asm/it8172/it8172_pci.h>
 #include <asm/it8172/it8172_int.h>
 
-void __init pcibios_fixup_resources(struct pci_dev *dev)
-{
-}
+/*
+ * Shortcuts
+ */
+#define INTA	IT8172_PCI_INTA_IRQ
+#define INTB	IT8172_PCI_INTB_IRQ
+#define INTC	IT8172_PCI_INTC_IRQ
+#define INTD	IT8172_PCI_INTD_IRQ
+
+static const int internal_func_irqs[7] __initdata = {
+	IT8172_AC97_IRQ,
+	IT8172_DMA_IRQ,
+	IT8172_CDMA_IRQ,
+	IT8172_USB_IRQ,
+	IT8172_BRIDGE_MASTER_IRQ,
+	IT8172_IDE_IRQ,
+	IT8172_MC68K_IRQ
+};
+
+static char irq_tab_ite8172g[][5] __initdata = {
+ [0x10] = {	0, INTA, INTB, INTC, INTD },
+ [0x11] = {	0, INTA, INTB, INTC, INTD },
+ [0x12] = {	0, INTB, INTC, INTD, INTA },
+ [0x13] = {	0, INTC, INTD, INTA, INTB },
+ [0x14] = {	0, INTD, INTA, INTB, INTC },
+};
 
-void __init pcibios_fixup(void)
+int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
 {
-}
-
-void __init pcibios_fixup_irqs(void)
-{
-	unsigned int slot, func;
-	unsigned char pin;
-	struct pci_dev *dev = NULL;
-
-	const int internal_func_irqs[7] = {
-		IT8172_AC97_IRQ,
-		IT8172_DMA_IRQ,
-		IT8172_CDMA_IRQ,
-		IT8172_USB_IRQ,
-		IT8172_BRIDGE_MASTER_IRQ,
-		IT8172_IDE_IRQ,
-		IT8172_MC68K_IRQ
-	};
-
-	while ((dev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) {
-		if (dev->bus->number != 0)
-			return;
-
-		pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin);
-		slot = PCI_SLOT(dev->devfn);
-		func = PCI_FUNC(dev->devfn);
-
-		switch (slot) {
-		case 0x01:
-			/*
-			 * Internal device 1 is actually 7 different
-			 * internal devices on the IT8172G (a multi-
-			 * function device).
-			 */
-			if (func < 7)
-				dev->irq = internal_func_irqs[func];
-			break;
-		case 0x10:
-			switch (pin) {
-			case 1:	/* pin A */
-				dev->irq = IT8172_PCI_INTA_IRQ;
-				break;
-			case 2:	/* pin B */
-				dev->irq = IT8172_PCI_INTB_IRQ;
-				break;
-			case 3:	/* pin C */
-				dev->irq = IT8172_PCI_INTC_IRQ;
-				break;
-			case 4:	/* pin D */
-				dev->irq = IT8172_PCI_INTD_IRQ;
-				break;
-			default:
-				dev->irq = 0xff;
-				break;
-
-			}
-			break;
-		case 0x11:
-			switch (pin) {
-			case 1:	/* pin A */
-				dev->irq = IT8172_PCI_INTA_IRQ;
-				break;
-			case 2:	/* pin B */
-				dev->irq = IT8172_PCI_INTB_IRQ;
-				break;
-			case 3:	/* pin C */
-				dev->irq = IT8172_PCI_INTC_IRQ;
-				break;
-			case 4:	/* pin D */
-				dev->irq = IT8172_PCI_INTD_IRQ;
-				break;
-			default:
-				dev->irq = 0xff;
-				break;
-
-			}
-			break;
-		case 0x12:
-			switch (pin) {
-			case 1:	/* pin A */
-				dev->irq = IT8172_PCI_INTB_IRQ;
-				break;
-			case 2:	/* pin B */
-				dev->irq = IT8172_PCI_INTC_IRQ;
-				break;
-			case 3:	/* pin C */
-				dev->irq = IT8172_PCI_INTD_IRQ;
-				break;
-			case 4:	/* pin D */
-				dev->irq = IT8172_PCI_INTA_IRQ;
-				break;
-			default:
-				dev->irq = 0xff;
-				break;
-
-			}
-			break;
-		case 0x13:
-			switch (pin) {
-			case 1:	/* pin A */
-				dev->irq = IT8172_PCI_INTC_IRQ;
-				break;
-			case 2:	/* pin B */
-				dev->irq = IT8172_PCI_INTD_IRQ;
-				break;
-			case 3:	/* pin C */
-				dev->irq = IT8172_PCI_INTA_IRQ;
-				break;
-			case 4:	/* pin D */
-				dev->irq = IT8172_PCI_INTB_IRQ;
-				break;
-			default:
-				dev->irq = 0xff;
-				break;
-
-			}
-			break;
-		case 0x14:
-			switch (pin) {
-			case 1:	/* pin A */
-				dev->irq = IT8172_PCI_INTD_IRQ;
-				break;
-			case 2:	/* pin B */
-				dev->irq = IT8172_PCI_INTA_IRQ;
-				break;
-			case 3:	/* pin C */
-				dev->irq = IT8172_PCI_INTB_IRQ;
-				break;
-			case 4:	/* pin D */
-				dev->irq = IT8172_PCI_INTC_IRQ;
-				break;
-			default:
-				dev->irq = 0xff;
-				break;
+	/*
+	 * Internal device 1 is actually 7 different internal devices on the
+	 * IT8172G (a multifunction device).
+	 */
+	if (slot == 1)
+		return internal_func_irqs[PCI_FUNC(dev->devfn)];
 
-			}
-			break;
-		default:
-			continue;	/* do nothing */
-		}
-#ifdef DEBUG
-		printk("irq fixup: slot %d, int line %d, int number %d\n",
-		       slot, pin, dev->irq);
-#endif
-		pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq);
-	}
+	return irq_tab_ite8172g[slot][pin];
 }
--- diff/arch/mips/pci/fixup-ivr.c	2003-07-08 09:55:17.000000000 +0100
+++ source/arch/mips/pci/fixup-ivr.c	2004-02-23 13:56:38.000000000 +0000
@@ -36,118 +36,34 @@
 #include <asm/it8172/it8172_pci.h>
 #include <asm/it8172/it8172_int.h>
 
-void __init pcibios_fixup_resources(struct pci_dev *dev)
-{
-}
-
-void __init pcibios_fixup(void)
-{
-}
+/*
+ * Shortcuts
+ */
+#define INTA	IT8172_PCI_INTA_IRQ
+#define INTB	IT8172_PCI_INTB_IRQ
+#define INTC	IT8172_PCI_INTC_IRQ
+#define INTD	IT8172_PCI_INTD_IRQ
+
+static const int internal_func_irqs[7] __initdata = {
+	IT8172_AC97_IRQ,
+	IT8172_DMA_IRQ,
+	IT8172_CDMA_IRQ,
+	IT8172_USB_IRQ,
+	IT8172_BRIDGE_MASTER_IRQ,
+	IT8172_IDE_IRQ,
+	IT8172_MC68K_IRQ
+};
+
+static char irq_tab_ivr[][5] __initdata = {
+ [0x11] = { INTC, INTC, INTD, INTA, INTB },	/* Realtek RTL-8139	*/
+ [0x12] = { INTB, INTB, INTB, INTC, INTC },	/* IVR slot		*/
+ [0x13] = { INTA, INTA, INTB, INTC, INTD }	/* Expansion slot	*/
+};
 
-void __init pcibios_fixup_irqs(void)
+int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
 {
-	unsigned int slot, func;
-	unsigned char pin;
-	struct pci_dev *dev = NULL;
-
-	const int internal_func_irqs[7] = {
-		IT8172_AC97_IRQ,
-		IT8172_DMA_IRQ,
-		IT8172_CDMA_IRQ,
-		IT8172_USB_IRQ,
-		IT8172_BRIDGE_MASTER_IRQ,
-		IT8172_IDE_IRQ,
-		IT8172_MC68K_IRQ
-	};
-
-	while ((dev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) {
-		if (dev->bus->number != 0)
-			return;
-
-		pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin);
-		slot = PCI_SLOT(dev->devfn);
-		func = PCI_FUNC(dev->devfn);
-
-		switch (slot) {
-		case 0x01:
-			/*
-			 * Internal device 1 is actually 7 different
-			 * internal devices on the IT8172G (multi-function
-			 * device).
-			 */
-			if (func < 7)
-				dev->irq = internal_func_irqs[func];
-			break;
-		case 0x11:	// Realtek RTL-8139
-			switch (pin) {
-			case 0:	/* pin A, hardware bug */
-			case 1:	/* pin A */
-				dev->irq = IT8172_PCI_INTC_IRQ;
-				break;
-			case 2:	/* pin B */
-				dev->irq = IT8172_PCI_INTD_IRQ;
-				break;
-			case 3:	/* pin C */
-				dev->irq = IT8172_PCI_INTA_IRQ;
-				break;
-			case 4:	/* pin D */
-				dev->irq = IT8172_PCI_INTB_IRQ;
-				break;
-			default:
-				dev->irq = 0xff;
-				break;
-
-			}
-			break;
-		case 0x12:	// ivr slot
-			switch (pin) {
-			case 0:	/* pin A, hardware bug */
-			case 1:	/* pin A */
-				dev->irq = IT8172_PCI_INTB_IRQ;
-				break;
-			case 2:	/* pin B */
-				dev->irq = IT8172_PCI_INTB_IRQ;
-				break;
-			case 3:	/* pin C */
-				dev->irq = IT8172_PCI_INTC_IRQ;
-				break;
-			case 4:	/* pin D */
-				dev->irq = IT8172_PCI_INTD_IRQ;
-				break;
-			default:
-				dev->irq = 0xff;
-				break;
-
-			}
-			break;
-		case 0x13:	// expansion slot
-			switch (pin) {
-			case 0:	/* pin A, hardware bug */
-			case 1:	/* pin A */
-				dev->irq = IT8172_PCI_INTA_IRQ;
-				break;
-			case 2:	/* pin B */
-				dev->irq = IT8172_PCI_INTB_IRQ;
-				break;
-			case 3:	/* pin C */
-				dev->irq = IT8172_PCI_INTC_IRQ;
-				break;
-			case 4:	/* pin D */
-				dev->irq = IT8172_PCI_INTD_IRQ;
-				break;
-			default:
-				dev->irq = 0xff;
-				break;
+	if (slot == 1)
+		return internal_func_irqs[PCI_FUNC(dev->devfn)];
 
-			}
-			break;
-		default:
-			break;
-		}
-#ifdef DEBUG
-		printk("irq fixup: slot %d, int line %d, int number %d\n",
-		       slot, pin, dev->irq);
-#endif
-		pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq);
-	}
+	return irq_tab_ivr[slot][pin];
 }
--- diff/arch/mips/pci/fixup-jmr3927.c	2003-07-08 09:55:17.000000000 +0100
+++ source/arch/mips/pci/fixup-jmr3927.c	2004-02-23 13:56:38.000000000 +0000
@@ -34,51 +34,27 @@
 
 #include <asm/jmr3927/jmr3927.h>
 
-#undef	DEBUG
-#ifdef 	DEBUG
-#define	DBG(x...)	printk(x)
-#else
-#define	DBG(x...)
-#endif
-
-void __init pcibios_fixup_resources(struct pci_dev *dev)
-{
-	/* will need to fixup IO resources */
-}
-
-void __init pcibios_fixup(void)
-{
-	/* nothing to do here */
-}
-
-int pci_get_irq(struct pci_dev *dev, int pin)
+int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
 {
 	unsigned char irq = pin;
 
 	/* IRQ rotation (PICMG) */
 	irq--;			/* 0-3 */
 	if (dev->bus->parent == NULL &&
-	    PCI_SLOT(dev->devfn) == TX3927_PCIC_IDSEL_AD_TO_SLOT(23)) {
+	    slot == TX3927_PCIC_IDSEL_AD_TO_SLOT(23)) {
 		/* PCI CardSlot (IDSEL=A23, DevNu=12) */
 		/* PCIA => PCIC (IDSEL=A23) */
 		/* NOTE: JMR3927 JP1 must be set to OPEN */
 		irq = (irq + 2) % 4;
 	} else if (dev->bus->parent == NULL &&
-		   PCI_SLOT(dev->devfn) ==
-		   TX3927_PCIC_IDSEL_AD_TO_SLOT(22)) {
+		   slot == TX3927_PCIC_IDSEL_AD_TO_SLOT(22)) {
 		/* PCI CardSlot (IDSEL=A22, DevNu=11) */
 		/* PCIA => PCIA (IDSEL=A22) */
 		/* NOTE: JMR3927 JP1 must be set to OPEN */
 		irq = (irq + 0) % 4;
 	} else {
 		/* PCI Backplane */
-		irq = (irq + 3 + PCI_SLOT(dev->devfn)) % 4;
-#if 0				/* ??? */
-		for (bus = dev->bus; bus->parent != NULL;
-		     bus = bus->parent) {
-			irq = (irq + 3 + PCI_SLOT(bus->self->devfn)) % 4;
-		}
-#endif
+		irq = (irq + 3 + slot) % 4;
 	}
 	irq++;			/* 1-4 */
 
@@ -101,7 +77,7 @@ int pci_get_irq(struct pci_dev *dev, int
 
 	/* Check OnBoard Ethernet (IDSEL=A24, DevNu=13) */
 	if (dev->bus->parent == NULL &&
-	    PCI_SLOT(dev->devfn) == TX3927_PCIC_IDSEL_AD_TO_SLOT(24)) {
+	    slot == TX3927_PCIC_IDSEL_AD_TO_SLOT(24)) {
 		extern int jmr3927_ether1_irq;
 		/* check this irq line was reserved for ether1 */
 		if (jmr3927_ether1_irq != JMR3927_IRQ_ETHER0)
@@ -112,27 +88,12 @@ int pci_get_irq(struct pci_dev *dev, int
 	return irq;
 }
 
-void __init pcibios_fixup_irqs(void)
+int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
 {
-	unsigned char irq;
-	struct pci_dev *dev = NULL;
+	/* SMSC SLC90E66 IDE uses irq 14, 15 (default) */
+	if (!(dev->vendor == PCI_VENDOR_ID_EFAR &&
+	      dev->device == PCI_DEVICE_ID_EFAR_SLC90E66_1))
+		return pci_get_irq(dev, pin);
 
-	while ((dev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) {
-		pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &irq);
-		if (irq == 0)
-			return;
-
-		/* SMSC SLC90E66 IDE uses irq 14, 15 (default) */
-		if (!(dev->vendor == PCI_VENDOR_ID_EFAR &&
-		      dev->device == PCI_DEVICE_ID_EFAR_SLC90E66_1)) {
-			irq = pci_get_irq(dev, irq);
-			pci_write_config_byte(dev, PCI_INTERRUPT_LINE,
-					      irq);
-		}
-
-		pci_read_config_byte(dev, PCI_INTERRUPT_LINE, &irq);
-		printk(KERN_INFO "PCI: %02x:%02x IRQ %02x\n",
-		       dev->bus->number, dev->devfn, irq);
-		dev->irq = irq;
-	}
+	dev->irq = irq;
 }
--- diff/arch/mips/pci/fixup-ocelot.c	2003-07-08 09:55:17.000000000 +0100
+++ source/arch/mips/pci/fixup-ocelot.c	2004-02-23 13:56:38.000000000 +0000
@@ -13,12 +13,11 @@
 #include <linux/types.h>
 #include <linux/pci.h>
 #include <linux/kernel.h>
-#include <linux/version.h>
 #include <linux/init.h>
 #include <asm/pci.h>
 
 
-void __devinit gt64120_board_pcibios_fixup_bus(struct pci_bus *bus)
+void __devinit pcibios_fixup_bus(struct pci_bus *bus)
 {
 	struct pci_bus *current_bus = bus;
 	struct pci_dev *devices;
@@ -38,8 +37,7 @@ void __devinit gt64120_board_pcibios_fix
 			 */
 			if ((devices->vendor != 0x8086) ||
 			    (devices->device != 0x1209)) {
-				panic
-				    ("gt64120_board_pcibios_fixup_bus: found "
+				panic("pcibios_fixup_bus: found "
 				     "unexpected PCI device in slot 1.");
 			}
 			devices->irq = 2;	/* irq_nr is 2 for INT0 */
--- diff/arch/mips/pci/fixup-tb0226.c	2003-07-08 09:55:17.000000000 +0100
+++ source/arch/mips/pci/fixup-tb0226.c	2004-02-23 13:56:38.000000000 +0000
@@ -18,14 +18,6 @@
 
 #include <asm/vr41xx/tb0226.h>
 
-void __init pcibios_fixup_resources(struct pci_dev *dev)
-{
-}
-
-void __init pcibios_fixup(void)
-{
-}
-
 void __init pcibios_fixup_irqs(void)
 {
 	struct pci_dev *dev = NULL;
@@ -84,8 +76,3 @@ void __init pcibios_fixup_irqs(void)
 		pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq);
 	}
 }
-
-unsigned int pcibios_assign_all_busses(void)
-{
-	return 0;
-}
--- diff/arch/mips/pci/fixup-tb0229.c	2003-07-08 09:55:17.000000000 +0100
+++ source/arch/mips/pci/fixup-tb0229.c	2004-02-23 13:56:38.000000000 +0000
@@ -19,14 +19,6 @@
 
 #include <asm/vr41xx/tb0229.h>
 
-void __init pcibios_fixup_resources(struct pci_dev *dev)
-{
-}
-
-void __init pcibios_fixup(void)
-{
-}
-
 void __init pcibios_fixup_irqs(void)
 {
 #ifdef CONFIG_TANBAC_TB0219
@@ -70,8 +62,3 @@ void __init pcibios_fixup_irqs(void)
 	}
 #endif
 }
-
-unsigned int pcibios_assign_all_busses(void)
-{
-	return 0;
-}
--- diff/arch/mips/pci/fixup-victor-mpc30x.c	2003-07-08 09:55:17.000000000 +0100
+++ source/arch/mips/pci/fixup-victor-mpc30x.c	2004-02-23 13:56:38.000000000 +0000
@@ -19,54 +19,30 @@
 #include <asm/vr41xx/vrc4173.h>
 #include <asm/vr41xx/mpc30x.h>
 
-void __init pcibios_fixup_resources(struct pci_dev *dev)
-{
-}
-
-void __init pcibios_fixup(void)
-{
-}
+/*
+ * Shortcuts
+ */
+#define PCMCIA1	VRC4173_PCMCIA1_IRQ
+#define PCMCIA2	VRC4173_PCMCIA2_IRQ
+#define MQ	MQ200_IRQ
+
+static const int internal_func_irqs[8] __initdata = {
+	VRC4173_CASCADE_IRQ,
+	VRC4173_AC97_IRQ,
+	VRC4173_USB_IRQ,
+	
+};
+
+static char irq_tab_mpc30x[][5] __initdata = {
+ [12] = { PCMCIA1, PCMCIA1, 0, 0 },
+ [13] = { PCMCIA2, PCMCIA2, 0, 0 },
+ [29] = {      MQ,      MQ, 0, 0 },		/* mediaQ MQ-200 */
+};
 
-void __init pcibios_fixup_irqs(void)
+int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
 {
-	struct pci_dev *dev = NULL;
-	u8 slot, func;
+	if (slot == 30)
+		return internal_func_irqs[PCI_FUNC(dev->devfn)];
 
-	while ((dev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) {
-		slot = PCI_SLOT(dev->devfn);
-		func = PCI_FUNC(dev->devfn);
-		dev->irq = 0;
-
-		switch (slot) {
-		case 12:	/* NEC VRC4173 CARDU1 */
-			dev->irq = VRC4173_PCMCIA1_IRQ;
-			break;
-		case 13:	/* NEC VRC4173 CARDU2 */
-			dev->irq = VRC4173_PCMCIA2_IRQ;
-			break;
-		case 29:	/* mediaQ MQ-200 */
-			dev->irq = MQ200_IRQ;
-			break;
-		case 30:
-			switch (func) {
-			case 0:	/* NEC VRC4173 */
-				dev->irq = VRC4173_CASCADE_IRQ;
-				break;
-			case 1:	/* NEC VRC4173 AC97U */
-				dev->irq = VRC4173_AC97_IRQ;
-				break;
-			case 2:	/* NEC VRC4173 USBU */
-				dev->irq = VRC4173_USB_IRQ;
-				break;
-			}
-			break;
-		}
-
-		pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq);
-	}
-}
-
-unsigned int pcibios_assign_all_busses(void)
-{
-	return 0;
+	return irq_tab_mpc30x[slot][pin];
 }
--- diff/arch/mips/pci/ops-au1000.c	2003-07-08 09:55:17.000000000 +0100
+++ source/arch/mips/pci/ops-au1000.c	2004-02-23 13:56:38.000000000 +0000
@@ -34,47 +34,14 @@
 #include <linux/kernel.h>
 #include <linux/init.h>
 
-#include <asm/au1000.h>
+#include <asm/mach-au1x00/au1000.h>
 #ifdef CONFIG_MIPS_PB1000
-#include <asm/pb1000.h>
+#include <asm/mac-pb1x00/pb1000.h>
 #endif
-#include <asm/pci_channel.h>
 
 #define PCI_ACCESS_READ  0
 #define PCI_ACCESS_WRITE 1
 
-#undef DEBUG
-#ifdef 	DEBUG
-#define	DBG(x...)	printk(x)
-#else
-#define	DBG(x...)
-#endif
-
-/* TBD */
-static struct resource pci_io_resource = {
-	"pci IO space",
-	(u32) PCI_IO_START,
-	(u32) PCI_IO_END,
-	IORESOURCE_IO
-};
-
-static struct resource pci_mem_resource = {
-	"pci memory space",
-	(u32) PCI_MEM_START,
-	(u32) PCI_MEM_END,
-	IORESOURCE_MEM
-};
-
-extern struct pci_ops au1x_pci_ops;
-
-struct pci_channel mips_pci_channels[] = {
-	{&au1x_pci_ops, &pci_io_resource, &pci_mem_resource,
-	 PCI_FIRST_DEVFN, PCI_LAST_DEVFN},
-	{(struct pci_ops *) NULL, (struct resource *) NULL,
-	 (struct resource *) NULL, (int) NULL, (int) NULL}
-};
-
-
 #ifdef CONFIG_MIPS_PB1000
 /*
  * "Bus 2" is really the first and only external slot on the pb1000.
@@ -102,12 +69,6 @@ static int config_access(unsigned char a
 	}
 	au_sync_udelay(1);
 
-	DBG("config_access: %d bus %d dev_fn %x at %x *data %x, conf %x\n",
-	    access_type, bus, dev_fn, where, *data, config);
-
-	DBG("bridge config reg: %x (%x)\n", au_readl(PCI_BRIDGE_CONFIG),
-	    *data);
-
 	if (au_readl(PCI_BRIDGE_CONFIG) & (1 << 16)) {
 		*data = 0xffffffff;
 		return -1;
@@ -178,20 +139,11 @@ static int config_access(unsigned char a
 	}
 	au_sync_udelay(2);
 
-
-	DBG("config_access: %d bus %d device %d at %x *data %x, conf %x\n",
-	    access_type, bus->number, device, where, *data, config);
-
 	/* unmap io space */
 	iounmap((void *) cfg_addr);
 
 	/* check master abort */
 	status = au_readl(Au1500_PCI_STATCMD);
-#if 0
-	if (access_type == PCI_ACCESS_READ) {
-		printk("read data: %x\n", *data);
-	}
-#endif
 	if (status & (1 << 29)) {
 		*data = 0xffffffff;
 		return -1;
@@ -268,9 +220,6 @@ write_config_word(struct pci_bus *bus, u
 {
 	u32 data = 0;
 
-	if (where & 1)
-		return PCIBIOS_BAD_REGISTER_NUMBER;
-
 	if (config_access(PCI_ACCESS_READ, bus, devfn, where, &data))
 		return -1;
 
@@ -288,9 +237,6 @@ static int
 write_config_dword(struct pci_bus *bus, unsigned int devfn, int where,
 		   u32 val)
 {
-	if (where & 3)
-		return PCIBIOS_BAD_REGISTER_NUMBER;
-
 	if (config_access(PCI_ACCESS_WRITE, bus, devfn, where, &val))
 		return -1;
 
--- diff/arch/mips/pci/ops-ddb5074.c	2003-07-08 09:55:17.000000000 +0100
+++ source/arch/mips/pci/ops-ddb5074.c	2004-02-23 13:56:38.000000000 +0000
@@ -14,7 +14,6 @@
  * option) any later version.
  *
  */
-#include <linux/config.h>
 #include <linux/pci.h>
 #include <linux/kernel.h>
 #include <linux/types.h>
@@ -270,66 +269,3 @@ struct pci_ops ddb5476_ext_pci_ops = {
 	extpci_write_config_word,
 	extpci_write_config_dword
 };
-
-
-#if defined(CONFIG_RUNTIME_DEBUG)
-void jsun_scan_pci_bus(void)
-{
-	struct pci_bus bus;
-	struct pci_dev dev;
-	unsigned int devfn;
-	int j;
-
-	pci_config_workaround = 0;
-
-	bus.parent = NULL;	/* we scan the top level only */
-	dev.bus = &bus;
-	dev.sysdata = NULL;
-
-	/* scan ext pci bus and io pci bus */
-	for (j = 0; j < 1; j++) {
-		printk(KERN_INFO "scan ddb5476 external PCI bus:\n");
-		bus.ops = &ddb5476_ext_pci_ops;
-
-		for (devfn = 0; devfn < 0x100; devfn += 8) {
-			u32 temp;
-			u16 temp16;
-			u8 temp8;
-			int i;
-
-			dev.devfn = devfn;
-			db_verify(pci_read_config_dword(&dev, 0, &temp),
-				  == PCIBIOS_SUCCESSFUL);
-			if (temp == 0xffffffff)
-				continue;
-
-			printk(KERN_INFO "slot %d: (addr %d) \n",
-			       devfn / 8, 11 + devfn / 8);
-
-			/* verify read word and byte */
-			db_verify(pci_read_config_word(&dev, 2, &temp16),
-				  == PCIBIOS_SUCCESSFUL);
-			db_assert(temp16 == (temp >> 16));
-			db_verify(pci_read_config_byte(&dev, 3, &temp8),
-				  == PCIBIOS_SUCCESSFUL);
-			db_assert(temp8 == (temp >> 24));
-			db_verify(pci_read_config_byte(&dev, 1, &temp8),
-				  == PCIBIOS_SUCCESSFUL);
-			db_assert(temp8 == ((temp >> 8) & 0xff));
-
-			for (i = 0; i < 16; i++) {
-				if ((i % 4) == 0)
-					printk(KERN_INFO);
-				db_verify(pci_read_config_dword
-					  (&dev, i * 4, &temp),
-					  == PCIBIOS_SUCCESSFUL);
-				printk("\t%08X", temp);
-				if ((i % 4) == 3)
-					printk("\n");
-			}
-		}
-	}
-
-	pci_config_workaround = 1;
-}
-#endif
--- diff/arch/mips/pci/ops-ddb5476.c	2003-07-08 09:55:17.000000000 +0100
+++ source/arch/mips/pci/ops-ddb5476.c	2004-02-23 13:56:38.000000000 +0000
@@ -14,7 +14,6 @@
  * option) any later version.
  *
  */
-#include <linux/config.h>
 #include <linux/pci.h>
 #include <linux/kernel.h>
 #include <linux/types.h>
@@ -285,66 +284,3 @@ struct pci_ops ddb5476_ext_pci_ops = {
 	extpci_write_config_word,
 	extpci_write_config_dword
 };
-
-
-#if defined(CONFIG_RUNTIME_DEBUG)
-void jsun_scan_pci_bus(void)
-{
-	struct pci_bus bus;
-	struct pci_dev dev;
-	unsigned int devfn;
-	int j;
-
-	pci_config_workaround = 0;
-
-	bus.parent = NULL;	/* we scan the top level only */
-	dev.bus = &bus;
-	dev.sysdata = NULL;
-
-	/* scan ext pci bus and io pci bus */
-	for (j = 0; j < 1; j++) {
-		printk(KERN_INFO "scan ddb5476 external PCI bus:\n");
-		bus.ops = &ddb5476_ext_pci_ops;
-
-		for (devfn = 0; devfn < 0x100; devfn += 8) {
-			u32 temp;
-			u16 temp16;
-			u8 temp8;
-			int i;
-
-			dev.devfn = devfn;
-			db_verify(pci_read_config_dword(&dev, 0, &temp),
-				  == PCIBIOS_SUCCESSFUL);
-			if (temp == 0xffffffff)
-				continue;
-
-			printk(KERN_INFO "slot %d: (addr %d) \n",
-			       devfn / 8, 11 + devfn / 8);
-
-			/* verify read word and byte */
-			db_verify(pci_read_config_word(&dev, 2, &temp16),
-				  == PCIBIOS_SUCCESSFUL);
-			db_assert(temp16 == (temp >> 16));
-			db_verify(pci_read_config_byte(&dev, 3, &temp8),
-				  == PCIBIOS_SUCCESSFUL);
-			db_assert(temp8 == (temp >> 24));
-			db_verify(pci_read_config_byte(&dev, 1, &temp8),
-				  == PCIBIOS_SUCCESSFUL);
-			db_assert(temp8 == ((temp >> 8) & 0xff));
-
-			for (i = 0; i < 16; i++) {
-				if ((i % 4) == 0)
-					printk(KERN_INFO);
-				db_verify(pci_read_config_dword
-					  (&dev, i * 4, &temp),
-					  == PCIBIOS_SUCCESSFUL);
-				printk("\t%08X", temp);
-				if ((i % 4) == 3)
-					printk("\n");
-			}
-		}
-	}
-
-	pci_config_workaround = 1;
-}
-#endif
--- diff/arch/mips/pci/ops-ddb5477.c	2003-07-08 09:55:17.000000000 +0100
+++ source/arch/mips/pci/ops-ddb5477.c	2004-02-23 13:56:38.000000000 +0000
@@ -67,7 +67,7 @@ static inline u32 ddb_access_config_base
 {
 	u32 pci_addr = 0;
 	u32 pciinit_offset = 0;
-	u32 virt_addr = swap->config_base;
+	u32 virt_addr;
 	u32 option;
 
 	/* minimum pdar (window) size is 2MB */
@@ -127,39 +127,41 @@ static inline void ddb_close_config_base
 }
 
 static int read_config_dword(struct pci_config_swap *swap,
-			     struct pci_bus *bus, u32 where, u32 * val)
+			     struct pci_bus *bus, u32 devfn, u32 where, 
+			     u32 * val)
 {
-	u32 bus, slot_num, func_num;
+	u32 bus_num, slot_num, func_num;
 	u32 base;
 
 	db_assert((where & 3) == 0);
 	db_assert(where < (1 << 8));
 
 	/* check if the bus is top-level */
-	if (dev->bus->parent != NULL) {
-		bus = dev->bus->number;
-		db_assert(bus != 0);
+	if (bus->parent != NULL) {
+		bus_num = bus->number;
+		db_assert(bus_num != 0);
 	} else {
-		bus = 0;
+		bus_num = 0;
 	}
 
-	slot_num = PCI_SLOT(dev->devfn);
-	func_num = PCI_FUNC(dev->devfn);
-	base = ddb_access_config_base(swap, bus, slot_num);
+	slot_num = PCI_SLOT(devfn);
+	func_num = PCI_FUNC(devfn);
+	base = ddb_access_config_base(swap, bus_num, slot_num);
 	*val = *(volatile u32 *) (base + (func_num << 8) + where);
 	ddb_close_config_base(swap);
 	return PCIBIOS_SUCCESSFUL;
 }
 
 static int read_config_word(struct pci_config_swap *swap,
-			    struct pci_bus *bus, u32 where, u16 * val)
+			    struct pci_bus *bus, u32 devfn, u32 where, 
+			    u16 * val)
 {
 	int status;
 	u32 result;
 
 	db_assert((where & 1) == 0);
 
-	status = read_config_dword(swap, bus, where & ~3, &result);
+	status = read_config_dword(swap, bus, devfn, where & ~3, &result);
 	if (where & 2)
 		result >>= 16;
 	*val = result & 0xffff;
@@ -167,13 +169,13 @@ static int read_config_word(struct pci_c
 }
 
 static int read_config_byte(struct pci_config_swap *swap,
-			    struct pci_bus *bus, unsigned int devfn,
+			    struct pci_bus *bus, u32 devfn, u32 where,
 			    u8 * val)
 {
 	int status;
 	u32 result;
 
-	status = read_config_dword(swap, bus, where & ~3, &result);
+	status = read_config_dword(swap, bus, devfn, where & ~3, &result);
 	if (where & 1)
 		result >>= 8;
 	if (where & 2)
@@ -184,10 +186,10 @@ static int read_config_byte(struct pci_c
 }
 
 static int write_config_dword(struct pci_config_swap *swap,
-			      struct pci_bus *bus, unsigned int devfn,
+			      struct pci_bus *bus, u32 devfn, u32 where,
 			      u32 val)
 {
-	u32 busno, slot_num, func_num;
+	u32 bus_num, slot_num, func_num;
 	u32 base;
 
 	db_assert((where & 3) == 0);
@@ -195,30 +197,29 @@ static int write_config_dword(struct pci
 
 	/* check if the bus is top-level */
 	if (bus->parent != NULL) {
-		busno = bus->number;
-		db_assert(busno != 0);
+		bus_num = bus->number;
+		db_assert(bus_num != 0);
 	} else {
-		busno = 0;
+		bus_num = 0;
 	}
 
 	slot_num = PCI_SLOT(devfn);
 	func_num = PCI_FUNC(devfn);
-	base = ddb_access_config_base(swap, busno, slot_num);
+	base = ddb_access_config_base(swap, bus_num, slot_num);
 	*(volatile u32 *) (base + (func_num << 8) + where) = val;
 	ddb_close_config_base(swap);
 	return PCIBIOS_SUCCESSFUL;
 }
 
 static int write_config_word(struct pci_config_swap *swap,
-			     struct pci_bus *bus, unsigned int devfn,
-			     int where, u16 val)
+			     struct pci_bus *bus, u32 devfn, u32 where, u16 val)
 {
 	int status, shift = 0;
 	u32 result;
 
 	db_assert((where & 1) == 0);
 
-	status = read_config_dword(swap, dev, where & ~3, &result);
+	status = read_config_dword(swap, bus, devfn, where & ~3, &result);
 	if (status != PCIBIOS_SUCCESSFUL)
 		return status;
 
@@ -226,17 +227,16 @@ static int write_config_word(struct pci_
 		shift += 16;
 	result &= ~(0xffff << shift);
 	result |= val << shift;
-	return write_config_dword(swap, dev, where & ~3, result);
+	return write_config_dword(swap, bus, devfn, where & ~3, result);
 }
 
 static int write_config_byte(struct pci_config_swap *swap,
-			     struct pci_bus *bus, unsigned int devfn,
-			     int where, u8 val)
+			     struct pci_bus *bus, u32 devfn, u32 where, u8 val)
 {
 	int status, shift = 0;
 	u32 result;
 
-	status = read_config_dword(swap, dev, where & ~3, &result);
+	status = read_config_dword(swap, bus, devfn, where & ~3, &result);
 	if (status != PCIBIOS_SUCCESSFUL)
 		return status;
 
@@ -246,28 +246,25 @@ static int write_config_byte(struct pci_
 		shift += 8;
 	result &= ~(0xff << shift);
 	result |= val << shift;
-	return write_config_dword(swap, dev, where & ~3, result);
+	return write_config_dword(swap, bus, devfn, where & ~3, result);
 }
 
-/*
- * Dump solution for now so I don't break hw I can't test on ...
- */
-#define	MAKE_PCI_OPS(prefix, rw, unitname, unittype, pciswap) \
-static int prefix##_##rw##_config(struct pci_bus *bus, int where, int size, unittype val) \
+#define        MAKE_PCI_OPS(prefix, rw, pciswap, star) \
+static int prefix##_##rw##_config(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 star val) \
 { \
 	if (size == 1) \
-     		return rw##_config_byte(pciswap, bus, where, val); \
+     		return rw##_config_byte(pciswap, bus, devfn, where, (u8 star)val); \
 	else if (size == 2) \
-     		return rw##_config_word(pciswap, bus, where, val); \
+     		return rw##_config_word(pciswap, bus, devfn, where, (u16 star)val); \
 	/* Size must be 4 */ \
-     	return rw##_config_dword(pciswap, bus, where, val); \
+     	return rw##_config_dword(pciswap, bus, devfn, where, val); \
 }
 
-MAKE_PCI_OPS(extpci, read, &ext_pci_swap)
-    MAKE_PCI_OPS(extpci, write, &ext_pci_swap)
+MAKE_PCI_OPS(extpci, read, &ext_pci_swap, *)
+MAKE_PCI_OPS(extpci, write, &ext_pci_swap,)
 
-    MAKE_PCI_OPS(iopci, read, &io_pci_swap)
-    MAKE_PCI_OPS(iopci, write, &io_pci_swap)
+MAKE_PCI_OPS(iopci, read, &io_pci_swap, *)
+MAKE_PCI_OPS(iopci, write, &io_pci_swap,)
 
 struct pci_ops ddb5477_ext_pci_ops = {
 	.read = extpci_read_config,
--- diff/arch/mips/pci/ops-it8172.c	2003-07-08 09:55:17.000000000 +0100
+++ source/arch/mips/pci/ops-it8172.c	2004-02-23 13:56:38.000000000 +0000
@@ -77,10 +77,10 @@ static struct resource pci_mem_resource_
 
 extern struct pci_ops it8172_pci_ops;
 
-struct pci_channel mips_pci_channels[] = {
-	{&it8172_pci_ops, &pci_io_resource, &pci_mem_resource_0, 0x10,
-	 0xff},
-	{NULL, NULL, NULL, NULL, NULL}
+struct pci_controller it8172_controller = {
+	.pci_ops	= &it8172_pci_ops,
+	.io_resource	= &pci_io_resource,
+	.mem_resource	= &pci_mem_resource_0,
 };
 
 static int it8172_pcibios_config_access(unsigned char access_type,
@@ -212,8 +212,3 @@ struct pci_ops it8172_pci_ops = {
 	.read = read_config,
 	.write = write_config,
 };
-
-unsigned __init int pcibios_assign_all_busses(void)
-{
-	return 1;
-}
--- diff/arch/mips/pci/pci-ddb5074.c	2003-07-08 09:55:17.000000000 +0100
+++ source/arch/mips/pci/pci-ddb5074.c	2004-02-23 13:56:38.000000000 +0000
@@ -24,9 +24,10 @@ static struct resource extpci_mem_resour
 
 extern struct pci_ops ddb5476_ext_pci_ops;
 
-struct pci_channel mips_pci_channels[] = {
-	{&ddb5476_ext_pci_ops, &extpci_io_resource, &extpci_mem_resource},
-	{NULL, NULL, NULL}
+struct pci_controller ddb5476_controller = {
+	.pci_ops	= &ddb5476_ext_pci_ops,
+	.io_resource	= &extpci_io_resource,
+	.mem_resource	= &extpci_mem_resource,
 };
 
 #define     PCI_EXT_INTA        8
@@ -38,40 +39,19 @@ struct pci_channel mips_pci_channels[] =
 #define     MAX_SLOT_NUM        14
 
 static unsigned char irq_map[MAX_SLOT_NUM] = {
-	/* SLOT:  0 */ nile4_to_irq(PCI_EXT_INTE),
-	/* SLOT:  1 */ nile4_to_irq(PCI_EXT_INTA),
-	/* SLOT:  2 */ nile4_to_irq(PCI_EXT_INTA),
-	/* SLOT:  3 */ nile4_to_irq(PCI_EXT_INTB),
-	/* SLOT:  4 */ nile4_to_irq(PCI_EXT_INTC),
-	/* SLOT:  5 */ nile4_to_irq(NILE4_INT_UART),
-	/* SLOT:  6 */ 0xff,
-	/* SLOT:  7 */ 0xff,
-	/* SLOT:  8 */ 0xff,
-	/* SLOT:  9 */ 0xff,
-	/* SLOT:  10 */ nile4_to_irq(PCI_EXT_INTE),
-	/* SLOT:  11 */ 0xff,
-	/* SLOT:  12 */ 0xff,
-	/* SLOT:  13 */ nile4_to_irq(PCI_EXT_INTE),
+  [ 0] = nile4_to_irq(PCI_EXT_INTE),
+  [ 1] = nile4_to_irq(PCI_EXT_INTA),
+  [ 2] = nile4_to_irq(PCI_EXT_INTA),
+  [ 3] = nile4_to_irq(PCI_EXT_INTB),
+  [ 4] = nile4_to_irq(PCI_EXT_INTC),
+  [ 5] = nile4_to_irq(NILE4_INT_UART),
+  [10] = nile4_to_irq(PCI_EXT_INTE),
+  [13] = nile4_to_irq(PCI_EXT_INTE),
 };
 
-void __init pcibios_fixup_irqs(void)
+int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
 {
-
-	struct pci_dev *dev = NULL;
-	int slot_num;
-
-	while ((dev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) {
-		slot_num = PCI_SLOT(dev->devfn);
-		db_assert(slot_num < MAX_SLOT_NUM);
-		printk("irq_map[%d]: %02x\n", slot_num, irq_map[slot_num]);
-		db_assert(irq_map[slot_num] != 0xff);
-
-		pci_write_config_byte(dev,
-				      PCI_INTERRUPT_LINE,
-				      irq_map[slot_num]);
-
-		dev->irq = irq_map[slot_num];
-	}
+	return irq_map[slot];
 }
 
 void __init ddb_pci_reset_bus(void)
@@ -92,38 +72,3 @@ void __init ddb_pci_reset_bus(void)
 	ddb_out32(DDB_PCICTRL + 4, temp);
 
 }
-
-unsigned __init int pcibios_assign_all_busses(void)
-{
-	/* we hope pci_auto has assigned the bus numbers to all buses */
-	return 1;
-}
-
-void __init pcibios_fixup_resources(struct pci_dev *dev)
-{
-}
-
-void __init pcibios_fixup(void)
-{
-	struct pci_dev *dev = NULL;
-
-	while ((dev = pci_find_device(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M7101,
-	        dev)) != NULL) {
-		/*
-		 * It's nice to have the LEDs on the GPIO pins
-		 * available for debugging
-		 */
-		extern struct pci_dev *pci_pmu;
-		u8 t8;
-
-		pci_pmu = dev;	/* for LEDs D2 and D3 */
-		/* Program the lines for LEDs D2 and D3 to output */
-		pci_read_config_byte(dev, 0x7d, &t8);
-		t8 |= 0xc0;
-		pci_write_config_byte(dev, 0x7d, t8);
-		/* Turn LEDs D2 and D3 off */
-		pci_read_config_byte(dev, 0x7e, &t8);
-		t8 |= 0xc0;
-		pci_write_config_byte(dev, 0x7e, t8);
-	}
-}
--- diff/arch/mips/pci/pci-ddb5476.c	2003-07-08 09:55:17.000000000 +0100
+++ source/arch/mips/pci/pci-ddb5476.c	2004-02-23 13:56:38.000000000 +0000
@@ -1,4 +1,3 @@
-#include <linux/config.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/types.h>
@@ -25,9 +24,10 @@ static struct resource extpci_mem_resour
 
 extern struct pci_ops ddb5476_ext_pci_ops;
 
-struct pci_channel mips_pci_channels[] = {
-	{&ddb5476_ext_pci_ops, &extpci_io_resource, &extpci_mem_resource},
-	{NULL, NULL, NULL}
+struct pci_controller ddb5476_controller = {
+	.pci_ops	= &ddb5476_ext_pci_ops,
+	.io_resource	= &extpci_io_resource,
+	.mem_resource	= &extpci_mem_resource
 };
 
 
@@ -53,64 +53,21 @@ struct pci_channel mips_pci_channels[] =
  */
 #define		MAX_SLOT_NUM		21
 static unsigned char irq_map[MAX_SLOT_NUM] = {
-	/* SLOT:  0, AD:11 */ 0xff,
-	/* SLOT:  1, AD:12 */ 0xff,
-					/* SLOT:  2, AD:13 */ 9,
-					/* USB */
-					/* SLOT:  3, AD:14 */ 10,
-					/* PMU */
-	/* SLOT:  4, AD:15 */ 0xff,
-					/* SLOT:  5, AD:16 */ 0x0,
-					/* P2P bridge */
-	/* SLOT:  6, AD:17 */ nile4_to_irq(PCI_EXT_INTB),
-	/* SLOT:  7, AD:18 */ nile4_to_irq(PCI_EXT_INTC),
-	/* SLOT:  8, AD:19 */ nile4_to_irq(PCI_EXT_INTD),
-	/* SLOT:  9, AD:20 */ nile4_to_irq(PCI_EXT_INTA),
-	/* SLOT: 10, AD:21 */ 0xff,
-	/* SLOT: 11, AD:22 */ 0xff,
-	/* SLOT: 12, AD:23 */ 0xff,
-					/* SLOT: 13, AD:24 */ 14,
-					/* HD controller, M5229 */
-	/* SLOT: 14, AD:25 */ 0xff,
-	/* SLOT: 15, AD:26 */ 0xff,
-	/* SLOT: 16, AD:27 */ 0xff,
-	/* SLOT: 17, AD:28 */ 0xff,
-	/* SLOT: 18, AD:29 */ 0xff,
-	/* SLOT: 19, AD:30 */ 0xff,
-	/* SLOT: 20, AD:31 */ 0xff
+ [ 2] = 9,				/* AD:13	USB		*/
+ [ 3] = 10,				/* AD:14	PMU		*/
+ [ 5] = 0,				/* AD:16 	P2P bridge	*/
+ [ 6] = nile4_to_irq(PCI_EXT_INTB),	/* AD:17			*/
+ [ 7] =	nile4_to_irq(PCI_EXT_INTC),	/* AD:18			*/
+ [ 8] = nile4_to_irq(PCI_EXT_INTD),	/* AD:19			*/
+ [ 9] = nile4_to_irq(PCI_EXT_INTA),	/* AD:20			*/
+ [13] = 14,				/* AD:24 HD controller, M5229	*/
 };
 
-extern int vrc5477_irq_to_irq(int irq);
-void __init pcibios_fixup_irqs(void)
+int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
 {
-	struct pci_dev *dev = NULL;
-	int slot_num;
-
-	while ((dev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) {
-		slot_num = PCI_SLOT(dev->devfn);
-
-		/* we don't do IRQ fixup for sub-bus yet */
-		if (dev->bus->parent != NULL) {
-			db_run(printk
-			       ("Don't know how to fixup irq for PCI device %d on sub-bus %d\n",
-				slot_num, dev->bus->number));
-			continue;
-		}
-
-		db_assert(slot_num < MAX_SLOT_NUM);
-		db_assert(irq_map[slot_num] != 0xff);
-
-		pci_write_config_byte(dev,
-				      PCI_INTERRUPT_LINE,
-				      irq_map[slot_num]);
-		dev->irq = irq_map[slot_num];
-	}
+	return irq_map[slot];
 }
 
-#if defined(CONFIG_RUNTIME_DEBUG)
-extern void jsun_scan_pci_bus(void);
-#endif
-
 void __init ddb_pci_reset_bus(void)
 {
 	u32 temp;
@@ -129,17 +86,3 @@ void __init ddb_pci_reset_bus(void)
 	ddb_out32(DDB_PCICTRL + 4, temp);
 
 }
-
-unsigned __init int pcibios_assign_all_busses(void)
-{
-	/* we hope pci_auto has assigned the bus numbers to all buses */
-	return 1;
-}
-
-void __init pcibios_fixup_resources(struct pci_dev *dev)
-{
-}
-
-void __init pcibios_fixup(void)
-{
-}
--- diff/arch/mips/pci/pci-ddb5477.c	2003-07-08 09:55:17.000000000 +0100
+++ source/arch/mips/pci/pci-ddb5477.c	2004-02-23 13:56:38.000000000 +0000
@@ -9,7 +9,6 @@
  * Free Software Foundation;  either version 2 of the  License, or (at your
  * option) any later version.
  */
-#include <linux/config.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/types.h>
@@ -52,12 +51,19 @@ static struct resource iopci_mem_resourc
 extern struct pci_ops ddb5477_ext_pci_ops;
 extern struct pci_ops ddb5477_io_pci_ops;
 
-struct pci_channel mips_pci_channels[] = {
-	{&ddb5477_ext_pci_ops, &extpci_io_resource, &extpci_mem_resource},
-	{&ddb5477_io_pci_ops, &iopci_io_resource, &iopci_mem_resource},
-	{NULL, NULL, NULL}
+struct pci_controller ddb5477_ext_controller = {
+	.pci_ops	= &ddb5477_ext_pci_ops,
+	.io_resource	= &extpci_io_resource,
+	.mem_resource	= &extpci_mem_resource
 };
 
+struct pci_controller ddb5477_io_controller = {
+	.pci_ops	= &ddb5477_io_pci_ops,
+	.io_resource	= &iopci_io_resource,
+	.mem_resource	= &iopci_mem_resource
+};
+
+
 
 /*
  * we fix up irqs based on the slot number.
@@ -82,16 +88,11 @@ static unsigned char irq_map[MAX_SLOT_NU
 	/* SLOT:  1, AD:12 */ 0xff,
 	/* SLOT:  2, AD:13 */ 0xff,
 	/* SLOT:  3, AD:14 */ 0xff,
-						/* SLOT:  4, AD:15 */ VRC5477_IRQ_INTA,
-						/* onboard tulip */
-						/* SLOT:  5, AD:16 */ VRC5477_IRQ_INTB,
-						/* slot 1 */
-						/* SLOT:  6, AD:17 */ VRC5477_IRQ_INTC,
-						/* slot 2 */
-						/* SLOT:  7, AD:18 */ VRC5477_IRQ_INTD,
-						/* slot 3 */
-						/* SLOT:  8, AD:19 */ VRC5477_IRQ_INTE,
-						/* slot 4 */
+	/* SLOT:  4, AD:15 */ VRC5477_IRQ_INTA, /* onboard tulip */
+	/* SLOT:  5, AD:16 */ VRC5477_IRQ_INTB, /* slot 1 */
+	/* SLOT:  6, AD:17 */ VRC5477_IRQ_INTC, /* slot 2 */
+	/* SLOT:  7, AD:18 */ VRC5477_IRQ_INTD, /* slot 3 */
+	/* SLOT:  8, AD:19 */ VRC5477_IRQ_INTE, /* slot 4 */
 	/* SLOT:  9, AD:20 */ 0xff,
 	/* SLOT: 10, AD:21 */ 0xff,
 	/* SLOT: 11, AD:22 */ 0xff,
@@ -101,31 +102,21 @@ static unsigned char irq_map[MAX_SLOT_NU
 	/* SLOT: 15, AD:26 */ 0xff,
 	/* SLOT: 16, AD:27 */ 0xff,
 	/* SLOT: 17, AD:28 */ 0xff,
-							/* SLOT: 18, AD:29 */ VRC5477_IRQ_IOPCI_INTC,
-							/* vrc5477 ac97 */
-							/* SLOT: 19, AD:30 */ VRC5477_IRQ_IOPCI_INTB,
-							/* vrc5477 usb peri */
-							/* SLOT: 20, AD:31 */ VRC5477_IRQ_IOPCI_INTA,
-							/* vrc5477 usb host */
+	/* SLOT: 18, AD:29 */ VRC5477_IRQ_IOPCI_INTC, /* vrc5477 ac97 */
+	/* SLOT: 19, AD:30 */ VRC5477_IRQ_IOPCI_INTB, /* vrc5477 usb peri */
+	/* SLOT: 20, AD:31 */ VRC5477_IRQ_IOPCI_INTA, /* vrc5477 usb host */
 };
 static unsigned char rockhopperII_irq_map[MAX_SLOT_NUM] = {
 	/* SLOT:  0, AD:11 */ 0xff,
-						/* SLOT:  1, AD:12 */ VRC5477_IRQ_INTB,
-						/* onboard AMD PCNET */
+	/* SLOT:  1, AD:12 */ VRC5477_IRQ_INTB, /* onboard AMD PCNET */
 	/* SLOT:  2, AD:13 */ 0xff,
 	/* SLOT:  3, AD:14 */ 0xff,
-					/* SLOT:  4, AD:15 */ 14,
-					/* M5229 ide ISA irq */
-						/* SLOT:  5, AD:16 */ VRC5477_IRQ_INTD,
-						/* slot 3 */
-						/* SLOT:  6, AD:17 */ VRC5477_IRQ_INTA,
-						/* slot 4 */
-						/* SLOT:  7, AD:18 */ VRC5477_IRQ_INTD,
-						/* slot 5 */
-					/* SLOT:  8, AD:19 */ 0,
-					/* M5457 modem nop */
-						/* SLOT:  9, AD:20 */ VRC5477_IRQ_INTA,
-						/* slot 2 */
+	/* SLOT:  4, AD:15 */ 14, /* M5229 ide ISA irq */
+	/* SLOT:  5, AD:16 */ VRC5477_IRQ_INTD, /* slot 3 */
+	/* SLOT:  6, AD:17 */ VRC5477_IRQ_INTA, /* slot 4 */
+	/* SLOT:  7, AD:18 */ VRC5477_IRQ_INTD, /* slot 5 */
+	/* SLOT:  8, AD:19 */ 0, /* M5457 modem nop */
+	/* SLOT:  9, AD:20 */ VRC5477_IRQ_INTA, /* slot 2 */
 	/* SLOT: 10, AD:21 */ 0xff,
 	/* SLOT: 11, AD:22 */ 0xff,
 	/* SLOT: 12, AD:23 */ 0xff,
@@ -133,62 +124,57 @@ static unsigned char rockhopperII_irq_ma
 	/* SLOT: 14, AD:25 */ 0xff,
 	/* SLOT: 15, AD:26 */ 0xff,
 	/* SLOT: 16, AD:27 */ 0xff,
-					/* SLOT: 17, AD:28 */ 0,
-					/* M7101 PMU nop */
-							/* SLOT: 18, AD:29 */ VRC5477_IRQ_IOPCI_INTC,
-							/* vrc5477 ac97 */
-							/* SLOT: 19, AD:30 */ VRC5477_IRQ_IOPCI_INTB,
-							/* vrc5477 usb peri */
-							/* SLOT: 20, AD:31 */ VRC5477_IRQ_IOPCI_INTA,
-							/* vrc5477 usb host */
+	/* SLOT: 17, AD:28 */ 0, /* M7101 PMU nop */
+	/* SLOT: 18, AD:29 */ VRC5477_IRQ_IOPCI_INTC, /* vrc5477 ac97 */
+	/* SLOT: 19, AD:30 */ VRC5477_IRQ_IOPCI_INTB, /* vrc5477 usb peri */
+	/* SLOT: 20, AD:31 */ VRC5477_IRQ_IOPCI_INTA, /* vrc5477 usb host */
 };
 
-void __init pcibios_fixup_irqs(void)
+int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
 {
-	struct pci_dev *dev = NULL;
 	int slot_num;
 	unsigned char *slot_irq_map;
 	unsigned char irq;
 
+	/* 
+	 * We ignore the swizzled slot and pin values.  The original
+	 * pci_fixup_irq() codes largely base irq number on the dev slot 
+	 * numbers because except for one case they are unique even
+	 * though there are multiple pci buses.
+	 */
+
 	if (mips_machtype == MACH_NEC_ROCKHOPPERII)
 		slot_irq_map = rockhopperII_irq_map;
 	else
 		slot_irq_map = irq_map;
 
+	slot_num = PCI_SLOT(dev->devfn);
+	irq = slot_irq_map[slot_num];
 
-	while ((dev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) {
-		slot_num = PCI_SLOT(dev->devfn);
-		irq = slot_irq_map[slot_num];
-
-		db_assert(slot_num < MAX_SLOT_NUM);
-
-		db_assert(irq != 0xff);
-
-		pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq);
-
-		dev->irq = irq;
-
-		if (mips_machtype == MACH_NEC_ROCKHOPPERII) {
-			/* hack to distinquish overlapping slot 20s, one
-			 * on bus 0 (ALI USB on the M1535 on the backplane), 
-			 * and one on bus 2 (NEC USB controller on the CPU board)
-			 * Make the M1535 USB - ISA IRQ number 9.
-			 */
-			if (slot_num == 20 && dev->bus->number == 0) {
-				pci_write_config_byte(dev,
-						      PCI_INTERRUPT_LINE,
-						      9);
-				dev->irq = 9;
-			}
+	db_assert(slot_num < MAX_SLOT_NUM);
+
+	db_assert(irq != 0xff);
+
+	pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq);
+
+	if (mips_machtype == MACH_NEC_ROCKHOPPERII) {
+		/* hack to distinquish overlapping slot 20s, one
+		 * on bus 0 (ALI USB on the M1535 on the backplane), 
+		 * and one on bus 2 (NEC USB controller on the CPU board)
+		 * Make the M1535 USB - ISA IRQ number 9.
+		 */
+		if (slot_num == 20 && dev->bus->number == 0) {
+			pci_write_config_byte(dev,
+					      PCI_INTERRUPT_LINE,
+					      9);
+			irq = 9;
 		}
 
 	}
+
+	return irq;
 }
 
-#if defined(CONFIG_RUNTIME_DEBUG)
-extern void jsun_scan_pci_bus(void);
-extern void jsun_assign_pci_resource(void);
-#endif
 void ddb_pci_reset_bus(void)
 {
 	u32 temp;
@@ -212,88 +198,3 @@ void ddb_pci_reset_bus(void)
 	temp &= ~0xc0000000;
 	ddb_out32(DDB_PCICTL1_H, temp);
 }
-
-unsigned __init int pcibios_assign_all_busses(void)
-{
-	/* we hope pci_auto has assigned the bus numbers to all buses */
-	return 1;
-}
-
-void __init pcibios_fixup_resources(struct pci_dev *dev)
-{
-}
-
-/* 
- * fixup baseboard AMD chip so that tx does not underflow.
- *	bcr_18 |= 0x0800
- * This sets NOUFLO bit which makes tx not start until whole pkt 
- * is fetched to the chip.
- */
-#define	PCNET32_WIO_RDP         0x10
-#define	PCNET32_WIO_RAP		0x12
-#define	PCNET32_WIO_RESET       0x14
-#define	PCNET32_WIO_BDP         0x16
-void __init fix_amd_lance(struct pci_dev *dev)
-{
-	unsigned long ioaddr;
-	u16 temp;
-
-	ioaddr = pci_resource_start(dev, 0);
-
-	inw(ioaddr + PCNET32_WIO_RESET);	/* reset chip */
-
-	/* bcr_18 |= 0x0800 */
-	outw(18, ioaddr + PCNET32_WIO_RAP);
-	temp = inw(ioaddr + PCNET32_WIO_BDP);
-	temp |= 0x0800;
-	outw(18, ioaddr + PCNET32_WIO_RAP);
-	outw(temp, ioaddr + PCNET32_WIO_BDP);
-}
-
-void __init pcibios_fixup(void)
-{
-	struct pci_dev *dev = NULL;
-
-	if (mips_machtype != MACH_NEC_ROCKHOPPERII)
-		return;
-
-
-#define M1535_CONFIG_PORT 0x3f0
-#define M1535_INDEX_PORT  0x3f0
-#define M1535_DATA_PORT   0x3f1
-
-	printk("Configuring ALI M1535 Super I/O mouse irq.\n");
-
-	request_region(M1535_CONFIG_PORT, 2, "M1535 Super I/O config");
-
-	/* Enter config mode. */
-	outb(0x51, M1535_CONFIG_PORT);
-	outb(0x23, M1535_CONFIG_PORT);
-
-	/* Select device 0x07. */
-	outb(0x07, M1535_INDEX_PORT);
-	outb(0x07, M1535_DATA_PORT);
-
-	/* Set mouse irq (register 0x72) to 12. */
-	outb(0x72, M1535_INDEX_PORT);
-	outb(0x0c, M1535_DATA_PORT);
-
-	/* Exit config mode. */
-	outb(0xbb, M1535_CONFIG_PORT);
-
-	while ((dev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) {
-		if (dev->vendor == PCI_VENDOR_ID_AL)
-			if (dev->device == PCI_DEVICE_ID_AL_M1535
-			    || dev->device == PCI_DEVICE_ID_AL_M1533) {
-				u8 old;
-				printk
-				    ("Enabling ALI M1533/35 PS2 keyboard/mouse.\n");
-				pci_read_config_byte(dev, 0x41, &old);
-				pci_write_config_byte(dev, 0x41, old | 0xd0);
-			}
-
-		if (dev->vendor == PCI_VENDOR_ID_AMD &&
-		    dev->device == PCI_DEVICE_ID_AMD_LANCE)
-			fix_amd_lance(dev);
-	}
-}
--- diff/arch/mips/pci/pci-hplj.c	2003-07-08 09:55:17.000000000 +0100
+++ source/arch/mips/pci/pci-hplj.c	2004-02-23 13:56:38.000000000 +0000
@@ -15,8 +15,8 @@
 #include <asm/pci_channel.h>
 #include <asm/hp-lj/asic.h>
 
-volatile u32 *pci_config_address_reg = (volatile u32 *) 0xfdead000;
-volatile u32 *pci_config_data_reg = (volatile u32 *) 0xfdead000;
+static volatile u32 *pci_config_address_reg = (volatile u32 *) 0xfdead000;
+static volatile u32 *pci_config_data_reg = (volatile u32 *) 0xfdead000;
 
 
 
@@ -107,21 +107,12 @@ struct pci_ops hp_pci_ops = {
 };
 
 
-struct pci_channel mips_pci_channels[] = {
-	{&hp_pci_ops, &ioport_resource, &iomem_resource},
-	{NULL, NULL, NULL}
+struct pci_controller hp_controller = {
+	.pci_ops	= &hp_pci_ops,
+	.io_resource	= &ioport_resource,
+	.mem_resource	= &iomem_resource,
 };
 
-unsigned __init int pcibios_assign_all_busses(void)
-{
-	return 1;
-}
-
-void __init pcibios_fixup(void)
-{
-}
-
-
 void __init pcibios_fixup_irqs(void)
 {
 	struct pci_dev *dev = NULL;
@@ -210,43 +201,4 @@ void __init pci_setup(void)
 	pci_config_data_reg = (u32 *) (((u32) mips_io_port_base) | 0xcfc);
 	pci_config_address_reg =
 	    (u32 *) (((u32) pci_regs_base_offset) | 0xcf8);
-
-}
-
-
-void __init pcibios_fixup_resources(struct pci_dev *dev)
-{
-	int pos;
-	int bases;
-
-	printk("adjusting pci device: %s\n", dev->name);
-
-	switch (dev->hdr_type) {
-	case PCI_HEADER_TYPE_NORMAL:
-		bases = 6;
-		break;
-	case PCI_HEADER_TYPE_BRIDGE:
-		bases = 2;
-		break;
-	case PCI_HEADER_TYPE_CARDBUS:
-		bases = 1;
-		break;
-	default:
-		bases = 0;
-		break;
-	}
-	for (pos = 0; pos < bases; pos++) {
-		struct resource *res = &dev->resource[pos];
-		if (res->start >= IO_MEM_LOGICAL_START &&
-		    res->end <= IO_MEM_LOGICAL_END) {
-			res->start += IO_MEM_VIRTUAL_OFFSET;
-			res->end += IO_MEM_VIRTUAL_OFFSET;
-		}
-		if (res->start >= IO_PORT_LOGICAL_START &&
-		    res->end <= IO_PORT_LOGICAL_END) {
-			res->start += IO_PORT_VIRTUAL_OFFSET;
-			res->end += IO_PORT_VIRTUAL_OFFSET;
-		}
-	}
-
 }
--- diff/arch/mips/pci/pci-ip27.c	2003-08-20 14:16:25.000000000 +0100
+++ source/arch/mips/pci/pci-ip27.c	2004-02-23 13:56:38.000000000 +0000
@@ -3,6 +3,7 @@
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  *
+ * Copyright (C) 2003 Christoph Hellwig (hch@lst.de)
  * Copyright (C) 1999, 2000 Ralf Baechle (ralf@gnu.org)
  * Copyright (C) 1999, 2000 Silicon Graphics, Inc.
  */
@@ -11,8 +12,9 @@
 #include <linux/pci.h>
 #include <asm/sn/arch.h>
 #include <asm/pci/bridge.h>
+#include <asm/pci_channel.h>
 #include <asm/paccess.h>
-#include <asm/sn/sn0/ip27.h>
+#include <asm/sn/intr.h>
 #include <asm/sn/sn0/hub.h>
 
 /*
@@ -26,6 +28,12 @@
 #define MAX_DEVICES_PER_PCIBUS	8
 
 /*
+ * XXX: No kmalloc available when we do our crosstalk scan,
+ * 	we should try to move it later in the boot process.
+ */
+static struct bridge_controller bridges[MAX_PCI_BUSSES];
+
+/*
  * No locking needed until PCI initialization is done parallely.
  */
 int irqstore[MAX_PCI_BUSSES][MAX_DEVICES_PER_PCIBUS];
@@ -34,7 +42,7 @@ int lastirq = BASE_PCI_IRQ;
 /*
  * Translate from irq to software PCI bus number and PCI slot.
  */
-int irq_to_bus[MAX_PCI_BUSSES * MAX_DEVICES_PER_PCIBUS];
+struct bridge_controller *irq_to_bridge[MAX_PCI_BUSSES * MAX_DEVICES_PER_PCIBUS];
 int irq_to_slot[MAX_PCI_BUSSES * MAX_DEVICES_PER_PCIBUS];
 
 /*
@@ -42,90 +50,136 @@ int irq_to_slot[MAX_PCI_BUSSES * MAX_DEV
  * not really documented, so right now I can't write code which uses it.
  * Therefore we use type 0 accesses for now even though they won't work
  * correcly for PCI-to-PCI bridges.
+ *
+ * The function is complicated by the ultimate brokeness of the IOC3 chip
+ * which is used in SGI systems.  The IOC3 can only handle 32-bit PCI
+ * accesses and does only decode parts of it's address space.
  */
-#define CF0_READ_PCI_CFG(bus,devfn,where,value,bm,mask)			\
-do {									\
-	bridge_t *bridge;                                               \
-	int slot = PCI_SLOT(devfn);					\
-	int fn = PCI_FUNC(devfn);					\
-	volatile u32 *addr;						\
-	u32 cf, __bit;							\
-	unsigned int bus_id = (unsigned) bus->number;              	\
-									\
-	bridge = (bridge_t *) NODE_SWIN_BASE(bus_to_nid[bus_id],        \
-                                             bus_to_wid[bus_id]);       \
-                                                                        \
-	__bit = (((where) & (bm)) << 3);				\
-	addr = &bridge->b_type0_cfg_dev[slot].f[fn].l[where >> 2];	\
-	if (get_dbe(cf, addr))						\
-		return PCIBIOS_DEVICE_NOT_FOUND;			\
-	*value = (cf >> __bit) & (mask);				\
-	return PCIBIOS_SUCCESSFUL;					\
-} while (0)
 
 static int pci_conf0_read_config(struct pci_bus *bus, unsigned int devfn,
 				 int where, int size, u32 * value)
 {
-	u32 vprod;
+	struct bridge_controller *bc = BRIDGE_CONTROLLER(bus);
+	bridge_t *bridge = bc->base;
+	int slot = PCI_SLOT(devfn);
+	int fn = PCI_FUNC(devfn);
+	volatile void *addr;
+	u32 cf, shift, mask;
+	int res;
+
+	addr = &bridge->b_type0_cfg_dev[slot].f[fn].c[PCI_VENDOR_ID];
+	if (get_dbe(cf, (u32 *) addr))
+		return PCIBIOS_DEVICE_NOT_FOUND;
 
-	CF0_READ_PCI_CFG(bus, devfn, PCI_VENDOR_ID, &vprod, 0, 0xffffffff);
-	if (vprod == (PCI_VENDOR_ID_SGI | (PCI_DEVICE_ID_SGI_IOC3 << 16))
-	    && ((where >= 0x14 && where < 0x40) || (where >= 0x48))) {
-		*value = 0;
-		return PCIBIOS_SUCCESSFUL;
-	}
+	/*
+	 * IOC3 is fucked fucked beyond believe ...  Don't even give the
+	 * generic PCI code a chance to look at it for real ...
+	 */
+	if (cf == (PCI_VENDOR_ID_SGI | (PCI_DEVICE_ID_SGI_IOC3 << 16)))
+		goto oh_my_gawd;
+
+	addr = &bridge->b_type0_cfg_dev[slot].f[fn].c[where ^ (4 - size)];
 
 	if (size == 1)
-		CF0_READ_PCI_CFG(bus, devfn, where, (u8 *) value, 3, 0xff);
+		res = get_dbe(*value, (u8 *) addr);
 	else if (size == 2)
-		CF0_READ_PCI_CFG(bus, devfn, where, (u16 *) value, 2,
-				 0xffff);
+		res = get_dbe(*value, (u16 *) addr);
 	else
-		CF0_READ_PCI_CFG(bus, devfn, where, (u32 *) value, 0,
-				 0xffffffff);
-}
+		res = get_dbe(*value, (u32 *) addr);
+
+	return PCIBIOS_SUCCESSFUL;
+
+oh_my_gawd:
+
+	/*
+	 * IOC3 is fucked fucked beyond believe ...  Don't even give the
+	 * generic PCI code a chance to look at the wrong register.
+	 */
+	if ((where >= 0x14 && where < 0x40) || (where >= 0x48)) {
+		*value = 0;
+		return PCIBIOS_SUCCESSFUL;
+	}
+
+	/*
+	 * IOC3 is fucked fucked beyond believe ...  Don't try to access
+	 * anything but 32-bit words ...
+	 */
+	addr = &bridge->b_type0_cfg_dev[slot].f[fn].l[where >> 2];
 
-#define CF0_WRITE_PCI_CFG(bus,devfn,where,value,bm,mask)		\
-do {									\
-	bridge_t *bridge;                                               \
-	int slot = PCI_SLOT(devfn);					\
-	int fn = PCI_FUNC(devfn);					\
-	volatile u32 *addr;						\
-	u32 cf, __bit;							\
-	unsigned int bus_id = (unsigned) bus->number;              	\
-									\
-	bridge = (bridge_t *) NODE_SWIN_BASE(bus_to_nid[bus_id],        \
-                                             bus_to_wid[bus_id]);       \
-                                                                        \
-	__bit = (((where) & (bm)) << 3);				\
-	addr = &bridge->b_type0_cfg_dev[slot].f[fn].l[where >> 2];	\
-	if (get_dbe(cf, addr))						\
-		return PCIBIOS_DEVICE_NOT_FOUND;			\
-	cf &= (~mask);							\
-	cf |= (value);							\
-	put_dbe(cf, addr);						\
-	return PCIBIOS_SUCCESSFUL;					\
-} while (0)
+	if (get_dbe(cf, (u32 *) addr))
+		return PCIBIOS_DEVICE_NOT_FOUND;
+
+	shift = ((where & 3) << 3);
+	mask = (0xffffffffU >> ((4 - size) << 3));
+	*value = (cf >> shift) & mask;
+
+	return PCIBIOS_SUCCESSFUL;
+}
 
 static int pci_conf0_write_config(struct pci_bus *bus, unsigned int devfn,
 				  int where, int size, u32 value)
 {
-	u32 vprod;
+	struct bridge_controller *bc = BRIDGE_CONTROLLER(bus);
+	bridge_t *bridge = bc->base;
+	int slot = PCI_SLOT(devfn);
+	int fn = PCI_FUNC(devfn);
+	volatile void *addr;
+	u32 cf, shift, mask, smask;
+	int res;
+
+	addr = &bridge->b_type0_cfg_dev[slot].f[fn].c[PCI_VENDOR_ID];
+	if (get_dbe(cf, (u32 *) addr))
+		return PCIBIOS_DEVICE_NOT_FOUND;
 
-	CF0_READ_PCI_CFG(bus, devfn, PCI_VENDOR_ID, &vprod, 0, 0xffffffff);
-	if (vprod == (PCI_VENDOR_ID_SGI | (PCI_DEVICE_ID_SGI_IOC3 << 16))
-	    && ((where >= 0x14 && where < 0x40) || (where >= 0x48))) {
-		return PCIBIOS_SUCCESSFUL;
+	/*
+	 * IOC3 is fucked fucked beyond believe ...  Don't even give the
+	 * generic PCI code a chance to look at it for real ...
+	 */
+	if (cf == (PCI_VENDOR_ID_SGI | (PCI_DEVICE_ID_SGI_IOC3 << 16)))
+		goto oh_my_gawd;
+
+	addr = &bridge->b_type0_cfg_dev[slot].f[fn].c[where ^ (4 - size)];
+
+	if (size == 1) {
+		res = put_dbe(value, (u8 *) addr);
+	} else if (size == 2) {
+		res = put_dbe(value, (u16 *) addr);
+	} else {
+		res = put_dbe(value, (u32 *) addr);
 	}
 
-	if (size == 1)
-		CF0_WRITE_PCI_CFG(bus, devfn, where, (u8) value, 3, 0xff);
-	else if (size == 2)
-		CF0_WRITE_PCI_CFG(bus, devfn, where, (u16) value, 2,
-				  0xffff);
-	else
-		CF0_WRITE_PCI_CFG(bus, devfn, where, (u32) value, 0,
-				  0xffffffff);
+	if (res)
+		return PCIBIOS_DEVICE_NOT_FOUND;
+
+	return PCIBIOS_SUCCESSFUL;
+
+oh_my_gawd:
+
+	/*
+	 * IOC3 is fucked fucked beyond believe ...  Don't even give the
+	 * generic PCI code a chance to touch the wrong register.
+	 */
+	if ((where >= 0x14 && where < 0x40) || (where >= 0x48))
+		return PCIBIOS_SUCCESSFUL;
+
+	/*
+	 * IOC3 is fucked fucked beyond believe ...  Don't try to access
+	 * anything but 32-bit words ...
+	 */
+	addr = &bridge->b_type0_cfg_dev[slot].f[fn].l[where >> 2];
+
+	if (get_dbe(cf, (u32 *) addr))
+		return PCIBIOS_DEVICE_NOT_FOUND;
+
+	shift = ((where & 3) << 3);
+	mask = (0xffffffffU >> ((4 - size) << 3));
+	smask = mask << shift;
+
+	cf = (cf & ~smask) | ((value & mask) << shift);
+	if (put_dbe(cf, (u32 *) addr))
+		return PCIBIOS_DEVICE_NOT_FOUND;
+
+	return PCIBIOS_SUCCESSFUL;
 }
 
 static struct pci_ops bridge_pci_ops = {
@@ -133,39 +187,79 @@ static struct pci_ops bridge_pci_ops = {
 	.write = pci_conf0_write_config,
 };
 
-static int __init pcibios_init(void)
+int __init bridge_probe(nasid_t nasid, int widget_id, int masterwid)
 {
-	struct pci_ops *ops = &bridge_pci_ops;
-	int i;
+	struct bridge_controller *bc;
+	bridge_t *bridge;
+	static int num_bridges = 0;
+
+	printk("a bridge\n");
+
+	/* XXX: kludge alert.. */
+	if (!num_bridges)
+		ioport_resource.end = ~0UL;
+
+	bc = &bridges[num_bridges++];
+
+	bc->pc.pci_ops		= &bridge_pci_ops;
+	bc->pc.mem_resource	= &bc->mem;
+	bc->pc.io_resource	= &bc->io;
+
+	bc->mem.name		= "Bridge PCI MEM";
+	bc->pc.mem_offset	= 0;
+	bc->mem.start		= 0;
+	bc->mem.end		= ~0UL;
+	bc->mem.flags		= IORESOURCE_MEM;
+
+	bc->io.name		= "Bridge IO MEM";
+	bc->io.start		= 0UL;
+	bc->pc.io_offset	= 0UL;
+	bc->io.end		= ~0UL;
+	bc->io.flags		= IORESOURCE_IO;
+
+	bc->irq_cpu = smp_processor_id();
+	bc->widget_id = widget_id;
+	bc->nasid = nasid;
 
-	ioport_resource.end = ~0UL;
+	bc->baddr = (u64)masterwid << 60;
+	bc->baddr |= (1UL << 56);	/* Barrier set */
 
-	for (i = 0; i < num_bridges; i++) {
-		printk("PCI: Probing PCI hardware on host bus %2d.\n", i);
-		pci_scan_bus(i, ops, NULL);
-	}
+	/*
+	 * point to this bridge
+	 */
+	bridge = (bridge_t *) RAW_NODE_SWIN_BASE(nasid, widget_id);
 
-	return 0;
-}
+	/*
+ 	 * Clear all pending interrupts.
+ 	 */
+	bridge->b_int_rst_stat = BRIDGE_IRR_ALL_CLR;
 
-subsys_initcall(pcibios_init);
+	/*
+ 	 * Until otherwise set up, assume all interrupts are from slot 0
+ 	 */
+	bridge->b_int_device = (u32) 0x0;
 
-static inline u8 bridge_swizzle(u8 pin, u8 slot)
-{
-	return (((pin - 1) + slot) % 4) + 1;
-}
+	/*
+ 	 * swap pio's to pci mem and io space (big windows)
+ 	 */
+	bridge->b_wid_control |= BRIDGE_CTRL_IO_SWAP |
+	                         BRIDGE_CTRL_MEM_SWAP;
 
-static u8 __devinit pci_swizzle(struct pci_dev *dev, u8 * pinp)
-{
-	u8 pin = *pinp;
+	/*
+	 * Hmm...  IRIX sets additional bits in the address which
+	 * are documented as reserved in the bridge docs.
+	 */
+	bridge->b_wid_int_upper = 0x8000 | (masterwid << 16);
+	bridge->b_wid_int_lower = 0x01800090;	/* PI_INT_PEND_MOD off*/
+	bridge->b_dir_map = (masterwid << 20);	/* DMA */
+	bridge->b_int_enable = 0;
 
-	while (dev->bus->self) {	/* Move up the chain of bridges. */
-		pin = bridge_swizzle(pin, PCI_SLOT(dev->devfn));
-		dev = dev->bus->self;
-	}
-	*pinp = pin;
+	bridge->b_wid_tflush;     /* wait until Bridge PIO complete */
+
+	bc->base = bridge;
 
-	return PCI_SLOT(dev->devfn);
+	register_pci_controller(&bc->pc);
+	return 0;
 }
 
 /*
@@ -177,9 +271,12 @@ static u8 __devinit pci_swizzle(struct p
  * A given PCI device, in general, should be able to intr any of the cpus
  * on any one of the hubs connected to its xbow.
  */
-static int __devinit pci_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+int __devinit pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
 {
-	if ((dev->bus->number >= MAX_PCI_BUSSES)
+	struct bridge_controller *bc = BRIDGE_CONTROLLER(dev->bus);
+	int busno = dev->bus->number;
+
+	if ((busno >= MAX_PCI_BUSSES)
 	    || (pin != 1)
 	    || (slot >= MAX_DEVICES_PER_PCIBUS))
 		panic("Increase supported PCI busses %d,%d,%d",
@@ -188,47 +285,14 @@ static int __devinit pci_map_irq(struct 
 	/*
 	 * Already assigned? Then return previously assigned value ...
 	 */
-	if (irqstore[dev->bus->number][slot])
-		return irqstore[dev->bus->number][slot];
+	if (irqstore[busno][slot])
+		return irqstore[busno][slot];
 
-	irq_to_bus[lastirq] = dev->bus->number;
+	irq_to_bridge[lastirq] = bc;
 	irq_to_slot[lastirq] = slot;
-	irqstore[dev->bus->number][slot] = lastirq;
-	lastirq++;
-	return lastirq - 1;
-}
-
-void __init pcibios_update_irq(struct pci_dev *dev, int irq)
-{
-	pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq);
-}
+	irqstore[busno][slot] = lastirq;
 
-void __devinit pcibios_fixup_bus(struct pci_bus *b)
-{
-	pci_fixup_irqs(pci_swizzle, pci_map_irq);
-}
-
-int pcibios_enable_device(struct pci_dev *dev, int mask)
-{
-	/* Not needed, since we enable all devices at startup.  */
-	return 0;
-}
-
-void pcibios_align_resource(void *data, struct resource *res,
-			    unsigned long size, unsigned long align)
-{
-}
-
-unsigned int pcibios_assign_all_busses(void)
-{
-	return 0;
-}
-
-char *__devinit pcibios_setup(char *str)
-{
-	/* Nothing to do for now.  */
-
-	return str;
+	return lastirq++;
 }
 
 /*
@@ -240,9 +304,8 @@ char *__devinit pcibios_setup(char *str)
 
 static void __init pci_disable_swapping(struct pci_dev *dev)
 {
-	unsigned int bus_id = (unsigned) dev->bus->number;
-	bridge_t *bridge = (bridge_t *) NODE_SWIN_BASE(bus_to_nid[bus_id],
-						       bus_to_wid[bus_id]);
+	struct bridge_controller *bc = BRIDGE_CONTROLLER(dev->bus);
+	bridge_t *bridge = bc->base;
 	int slot = PCI_SLOT(dev->devfn);
 
 	/* Turn off byte swapping */
@@ -252,9 +315,8 @@ static void __init pci_disable_swapping(
 
 static void __init pci_enable_swapping(struct pci_dev *dev)
 {
-	unsigned int bus_id = (unsigned) dev->bus->number;
-	bridge_t *bridge = (bridge_t *) NODE_SWIN_BASE(bus_to_nid[bus_id],
-						       bus_to_wid[bus_id]);
+	struct bridge_controller *bc = BRIDGE_CONTROLLER(dev->bus);
+	bridge_t *bridge = bc->base;
 	int slot = PCI_SLOT(dev->devfn);
 
 	/* Turn on byte swapping */
@@ -264,23 +326,23 @@ static void __init pci_enable_swapping(s
 
 static void __init pci_fixup_ioc3(struct pci_dev *d)
 {
-	unsigned long bus_id = (unsigned) d->bus->number;
+	struct bridge_controller *bc = BRIDGE_CONTROLLER(d->bus);
+	unsigned long offset = NODE_OFFSET(bc->nasid);
 
-	printk("PCI: Fixing base addresses for IOC3 device %s\n",
-	       pci_name(d));
+	printk("PCI: Fixing base addresses for IOC3 device %s\n", pci_name(d));
 
-	d->resource[0].start |= NODE_OFFSET(bus_to_nid[bus_id]);
-	d->resource[0].end |= NODE_OFFSET(bus_to_nid[bus_id]);
+	d->resource[0].start |= offset;
+	d->resource[0].end |= offset;
 
 	pci_disable_swapping(d);
 }
 
 static void __init pci_fixup_isp1020(struct pci_dev *d)
 {
+	struct bridge_controller *bc = BRIDGE_CONTROLLER(d->bus);
 	unsigned short command;
 
-	d->resource[0].start |=
-	    ((unsigned long) (bus_to_nid[d->bus->number]) << 32);
+	d->resource[0].start |= (unsigned long) bc->nasid << 32;
 	printk("PCI: Fixing isp1020 in [bus:slot.fn] %s\n", pci_name(d));
 
 	/*
@@ -289,7 +351,6 @@ static void __init pci_fixup_isp1020(str
 	 * bit set. Things stop working if we program the controllers as not
 	 * having PCI_COMMAND_MEMORY, so we have to fudge the mem_flags.
 	 */
-
 	pci_set_master(d);
 	pci_read_config_word(d, PCI_COMMAND, &command);
 	command |= PCI_COMMAND_MEMORY;
@@ -302,9 +363,8 @@ static void __init pci_fixup_isp1020(str
 
 static void __init pci_fixup_isp2x00(struct pci_dev *d)
 {
-	unsigned int bus_id = (unsigned) d->bus->number;
-	bridge_t *bridge = (bridge_t *) NODE_SWIN_BASE(bus_to_nid[bus_id],
-						       bus_to_wid[bus_id]);
+	struct bridge_controller *bc = BRIDGE_CONTROLLER(d->bus);
+	bridge_t *bridge = bc->base;
 	bridgereg_t devreg;
 	int i;
 	int slot = PCI_SLOT(d->devfn);
@@ -378,14 +438,11 @@ static void __init pci_fixup_isp2x00(str
 struct pci_fixup pcibios_fixups[] = {
 	{PCI_FIXUP_HEADER, PCI_VENDOR_ID_SGI, PCI_DEVICE_ID_SGI_IOC3,
 	 pci_fixup_ioc3},
-	{PCI_FIXUP_HEADER, PCI_VENDOR_ID_QLOGIC,
-	 PCI_DEVICE_ID_QLOGIC_ISP1020,
+	{PCI_FIXUP_HEADER, PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP1020,
 	 pci_fixup_isp1020},
-	{PCI_FIXUP_HEADER, PCI_VENDOR_ID_QLOGIC,
-	 PCI_DEVICE_ID_QLOGIC_ISP2100,
+	{PCI_FIXUP_HEADER, PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP2100,
 	 pci_fixup_isp2x00},
-	{PCI_FIXUP_HEADER, PCI_VENDOR_ID_QLOGIC,
-	 PCI_DEVICE_ID_QLOGIC_ISP2200,
+	{PCI_FIXUP_HEADER, PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP2200,
 	 pci_fixup_isp2x00},
 	{0}
 };
--- diff/arch/mips/pci/pci-ip32.c	2003-07-08 09:55:17.000000000 +0100
+++ source/arch/mips/pci/pci-ip32.c	2004-02-23 13:56:38.000000000 +0000
@@ -5,453 +5,141 @@
  *
  * Copyright (C) 2000, 2001 Keith M Wesolowski
  */
+#include <linux/config.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
+#include <linux/interrupt.h>
 #include <linux/pci.h>
 #include <linux/types.h>
-#include <asm/pci.h>
+#include <asm/pci_channel.h>
 #include <asm/ip32/mace.h>
-#include <asm/ip32/crime.h>
 #include <asm/ip32/ip32_ints.h>
-#include <linux/delay.h>
 
 #undef DEBUG_MACE_PCI
 
 /*
- * O2 has up to 5 PCI devices connected into the MACE bridge.  The device
- * map looks like this:
- *
- * 0  aic7xxx 0
- * 1  aic7xxx 1
- * 2  expansion slot
- * 3  N/C
- * 4  N/C
- */
-
-#define chkslot(_bus,_devfn)					\
-do {							        \
-	if ((_bus)->number > 0 || PCI_SLOT (_devfn) < 1	\
-	    || PCI_SLOT (_devfn) > 3)			        \
-		return PCIBIOS_DEVICE_NOT_FOUND;		\
-} while (0)
-
-#define mkaddr(_devfn, where) \
-((((_devfn) & 0xffUL) << 8) | ((where) & 0xfcUL))
-
-void macepci_error(int irq, void *dev, struct pt_regs *regs);
-
-static int macepci_read_config(struct pci_bus *bus, unsigned int devfn,
-			       int where, int size, u32 * val)
-{
-	switch (size) {
-	case 1:
-		*val = 0xff;
-		chkslot(bus, devfn);
-		mace_write_32(MACEPCI_CONFIG_ADDR, mkaddr(devfn, where));
-		*val =
-		    mace_read_8(MACEPCI_CONFIG_DATA +
-				((where & 3UL) ^ 3UL));
-
-		return PCIBIOS_SUCCESSFUL;
-
-	case 2:
-		*val = 0xffff;
-		chkslot(bus, devfn);
-		if (where & 1)
-			return PCIBIOS_BAD_REGISTER_NUMBER;
-		mace_write_32(MACEPCI_CONFIG_ADDR, mkaddr(devfn, where));
-		*val =
-		    mace_read_16(MACEPCI_CONFIG_DATA +
-				 ((where & 2UL) ^ 2UL));
-
-		return PCIBIOS_SUCCESSFUL;
-
-	case 4:
-		*val = 0xffffffff;
-		chkslot(bus, devfn);
-		if (where & 3)
-			return PCIBIOS_BAD_REGISTER_NUMBER;
-		mace_write_32(MACEPCI_CONFIG_ADDR, mkaddr(devfn, where));
-		*val = mace_read_32(MACEPCI_CONFIG_DATA);
-
-		return PCIBIOS_SUCCESSFUL;
-	}
-}
-
-static int macepci_write_config(struct pci_bus *bus, unsigned int devfn,
-				int where, int size, u32 val)
-{
-	switch (size) {
-	case 1:
-		chkslot(bus, devfn);
-		mace_write_32(MACEPCI_CONFIG_ADDR, mkaddr(devfn, where));
-		mace_write_8(MACEPCI_CONFIG_DATA + ((where & 3UL) ^ 3UL),
-			     val);
-
-		return PCIBIOS_SUCCESSFUL;
-
-	case 2:
-		chkslot(bus, devfn);
-		if (where & 1)
-			return PCIBIOS_BAD_REGISTER_NUMBER;
-		mace_write_32(MACEPCI_CONFIG_ADDR, mkaddr(devfn, where));
-		mace_write_16(MACEPCI_CONFIG_DATA + ((where & 2UL) ^ 2UL),
-			      val);
-
-		return PCIBIOS_SUCCESSFUL;
-
-	case 4:
-		chkslot(bus, devfn);
-		if (where & 3)
-			return PCIBIOS_BAD_REGISTER_NUMBER;
-		mace_write_32(MACEPCI_CONFIG_ADDR, mkaddr(devfn, where));
-		mace_write_32(MACEPCI_CONFIG_DATA, val);
-
-		return PCIBIOS_SUCCESSFUL;
-	}
-}
-
-static struct pci_ops macepci_ops = {
-	.read = macepci_read_config,
-	.write = macepci_write_config,
-};
-
-struct pci_fixup pcibios_fixups[] = { {0} };
-
-static int __init pcibios_init(void)
-{
-	struct pci_dev *dev = NULL;
-	u32 start, size;
-	u16 cmd;
-	u32 base_io = 0x3000;	/* The first i/o address to assign after SCSI */
-	u32 base_mem = 0x80100000;	/* Likewise */
-	u32 rev = mace_read_32(MACEPCI_REV);
-	int i;
-
-	printk("MACE: PCI rev %d detected at %016lx\n", rev,
-	       (u64) MACE_BASE + MACE_PCI);
-
-	/* These are *bus* addresses */
-	ioport_resource.start = 0;
-	ioport_resource.end = 0xffffffffUL;
-	iomem_resource.start = 0x80000000UL;
-	iomem_resource.end = 0xffffffffUL;
-
-	/* Clear any outstanding errors and enable interrupts */
-	mace_write_32(MACEPCI_ERROR_ADDR, 0);
-	mace_write_32(MACEPCI_ERROR_FLAGS, 0);
-	mace_write_32(MACEPCI_CONTROL, 0xff008500);
-	crime_write_64(CRIME_HARD_INT, 0UL);
-	crime_write_64(CRIME_SOFT_INT, 0UL);
-	crime_write_64(CRIME_INT_STAT, 0x000000000000ff00UL);
-
-	if (request_irq(MACE_PCI_BRIDGE_IRQ, macepci_error, 0,
-			"MACE PCI error", NULL))
-		panic("PCI bridge can't get interrupt; can't happen.");
-
-	pci_scan_bus(0, &macepci_ops, NULL);
-
-#ifdef DEBUG_MACE_PCI
-	while ((dev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) {
-		printk("Device: %d/%d/%d ARCS-assigned bus resource map\n",
-		       dev->bus->number, PCI_SLOT(dev->devfn),
-		       PCI_FUNC(dev->devfn));
-		for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) {
-			if (dev->resource[i].start == 0)
-				continue;
-			printk("%d: %016lx - %016lx (flags %04lx)\n",
-			       i, dev->resource[i].start,
-			       dev->resource[i].end,
-			       dev->resource[i].flags);
-		}
-	}
-#endif
-	/*
-	 * Assign sane resources to and enable all devices.  The requirement
-	 * for the SCSI controllers is well-known: a 256-byte I/O region
-	 * which we must assign, and a 1-page memory region which is
-	 * assigned by the system firmware.
-	 */
-	dev = NULL;
-	while ((dev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) {
-		switch (PCI_SLOT(dev->devfn)) {
-		case 1:	/* SCSI bus 0 */
-			dev->resource[0].start = 0x1000UL;
-			dev->resource[0].end = 0x10ffUL;
-			break;
-		case 2:	/* SCSI bus 1 */
-			dev->resource[0].start = 0x2000UL;
-			dev->resource[0].end = 0x20ffUL;
-			break;
-		default:	/* Slots - I guess we have only 1 */
-			for (i = 0; i < 6; i++) {
-				size = dev->resource[i].end
-				    - dev->resource[i].start;
-				if (!size
-				    || !(dev->resource[i].flags
-					 & (IORESOURCE_IO |
-					    IORESOURCE_MEM))) {
-					dev->resource[i].start =
-					    dev->resource[i].end = 0UL;
-					continue;
-				}
-				if (dev->resource[i].flags & IORESOURCE_IO) {
-					dev->resource[i].start = base_io;
-					base_io += PAGE_ALIGN(size);
-				} else {
-					dev->resource[i].start = base_mem;
-					base_mem += 0x100000UL;
-				}
-				dev->resource[i].end =
-				    dev->resource[i].start + size;
-			}
-			break;
-		}
-		for (i = 0; i < 6; i++) {
-			if (dev->resource[i].start == 0)
-				continue;
-			start = dev->resource[i].start;
-			if (dev->resource[i].flags & IORESOURCE_IO)
-				start |= 1;
-			pci_write_config_dword(dev,
-					       PCI_BASE_ADDRESS_0 +
-					       (i << 2), (u32) start);
-		}
-		pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, 0x20);
-		pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0x30);
-		pci_read_config_word(dev, PCI_COMMAND, &cmd);
-		cmd |=
-		    (PCI_COMMAND_IO | PCI_COMMAND_MEMORY |
-		     PCI_COMMAND_SPECIAL | PCI_COMMAND_INVALIDATE |
-		     PCI_COMMAND_PARITY);
-		pci_write_config_word(dev, PCI_COMMAND, cmd);
-		pci_set_master(dev);
-	}
-	/*
-	 * Fixup O2 PCI slot. Bad hack.
-	 */
-/*        devtag = pci_make_tag(0, 0, 3, 0);
-
-        slot = macepci_conf_read(0, devtag, PCI_COMMAND_STATUS_REG);
-        slot |= PCI_COMMAND_IO_ENABLE | PCI_COMMAND_MEM_ENABLE;
-        macepci_conf_write(0, devtag, PCI_COMMAND_STATUS_REG, slot);
-
-        slot = macepci_conf_read(0, devtag, PCI_MAPREG_START);
-        if (slot == 0xffffffe1)
-                macepci_conf_write(0, devtag, PCI_MAPREG_START, 0x00001000);
-
-        slot = macepci_conf_read(0, devtag, PCI_MAPREG_START + (2 << 2));
-        if ((slot & 0xffff0000) == 0) {
-                slot += 0x00010000;
-                macepci_conf_write(0, devtag, PCI_MAPREG_START + (2 << 2),
-                    0x00000000);
-        }
- */
-#ifdef DEBUG_MACE_PCI
-	printk("Triggering PCI bridge interrupt...\n");
-	mace_write_32(MACEPCI_ERROR_FLAGS, MACEPCI_ERROR_INTERRUPT_TEST);
-
-	dev = NULL;
-	while ((dev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) {
-		printk("Device: %d/%d/%d final bus resource map\n",
-		       dev->bus->number, PCI_SLOT(dev->devfn),
-		       PCI_FUNC(dev->devfn));
-		for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) {
-			if (dev->resource[i].start == 0)
-				continue;
-			printk("%d: %016lx - %016lx (flags %04lx)\n",
-			       i, dev->resource[i].start,
-			       dev->resource[i].end,
-			       dev->resource[i].flags);
-		}
-	}
-#endif
-
-	return 0;
-}
-
-subsys_initcall(pcibios_init);
-
-/*
- * Given a PCI slot number (a la PCI_SLOT(...)) and the interrupt pin of
- * the device (1-4 => A-D), tell what irq to use.  Note that we don't
- * in theory have slots 4 and 5, and we never normally use the shared
- * irqs.  I suppose a device without a pin A will thank us for doing it
- * right if there exists such a broken piece of crap.
- */
-static int __devinit macepci_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
-{
-	chkslot(dev->bus, dev->devfn);
-	if (pin == 0)
-		pin = 1;
-	switch (slot) {
-	case 1:
-		return MACEPCI_SCSI0_IRQ;
-	case 2:
-		return MACEPCI_SCSI1_IRQ;
-	case 3:
-		switch (pin) {
-		case 2:
-			return MACEPCI_SHARED0_IRQ;
-		case 3:
-			return MACEPCI_SHARED1_IRQ;
-		case 4:
-			return MACEPCI_SHARED2_IRQ;
-		case 1:
-		default:
-			return MACEPCI_SLOT0_IRQ;
-		}
-	case 4:
-		switch (pin) {
-		case 2:
-			return MACEPCI_SHARED2_IRQ;
-		case 3:
-			return MACEPCI_SHARED0_IRQ;
-		case 4:
-			return MACEPCI_SHARED1_IRQ;
-		case 1:
-		default:
-			return MACEPCI_SLOT1_IRQ;
-		}
-		return MACEPCI_SLOT1_IRQ;
-	case 5:
-		switch (pin) {
-		case 2:
-			return MACEPCI_SHARED1_IRQ;
-		case 3:
-			return MACEPCI_SHARED2_IRQ;
-		case 4:
-			return MACEPCI_SHARED0_IRQ;
-		case 1:
-		default:
-			return MACEPCI_SLOT2_IRQ;
-		}
-	default:
-		return 0;
-	}
-}
-
-/*
- * It's not entirely clear what this does in a system with no bridges.
- * In any case, bridges are not supported by Linux in O2.
- */
-static u8 __init macepci_swizzle(struct pci_dev *dev, u8 * pinp)
-{
-	if (PCI_SLOT(dev->devfn) == 2)
-		*pinp = 2;
-	else
-		*pinp = 1;
-	return PCI_SLOT(dev->devfn);
-}
-
-/* All devices are enabled during initialization. */
-int pcibios_enable_device(struct pci_dev *dev, int mask)
-{
-	return PCIBIOS_SUCCESSFUL;
-}
-
-char *__init pcibios_setup(char *str)
-{
-	return str;
-}
-
-void pcibios_align_resource(void *data, struct resource *res,
-			    unsigned long size, unsigned long align)
-{
-}
-
-void __init pcibios_update_irq(struct pci_dev *dev, int irq)
-{
-	pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq);
-}
-
-void __devinit pcibios_fixup_bus(struct pci_bus *b)
-{
-	pci_fixup_irqs(macepci_swizzle, macepci_map_irq);
-}
-
-/*
  * Handle errors from the bridge.  This includes master and target aborts,
  * various command and address errors, and the interrupt test.  This gets
  * registered on the bridge error irq.  It's conceivable that some of these
  * conditions warrant a panic.  Anybody care to say which ones?
  */
-void macepci_error(int irq, void *dev, struct pt_regs *regs)
+static irqreturn_t macepci_error(int irq, void *dev, struct pt_regs *regs)
 {
-	u32 flags, error_addr;
-	char space;
-
-	flags = mace_read_32(MACEPCI_ERROR_FLAGS);
-	error_addr = mace_read_32(MACEPCI_ERROR_ADDR);
+	char s;
+	unsigned int flags = mace->pci.error;
+	unsigned int addr = mace->pci.error_addr;
 
 	if (flags & MACEPCI_ERROR_MEMORY_ADDR)
-		space = 'M';
+		s = 'M';
 	else if (flags & MACEPCI_ERROR_CONFIG_ADDR)
-		space = 'C';
+		s = 'C';
 	else
-		space = 'X';
+		s = 'X';
 
 	if (flags & MACEPCI_ERROR_MASTER_ABORT) {
-		printk("MACEPCI: Master abort at 0x%08x (%c)\n",
-		       error_addr, space);
-		mace_write_32(MACEPCI_ERROR_FLAGS,
-			      flags & ~MACEPCI_ERROR_MASTER_ABORT);
+		printk("MACEPCI: Master abort at 0x%08x (%c)\n", addr, s);
+		flags &= ~MACEPCI_ERROR_MASTER_ABORT;
 	}
 	if (flags & MACEPCI_ERROR_TARGET_ABORT) {
-		printk("MACEPCI: Target abort at 0x%08x (%c)\n",
-		       error_addr, space);
-		mace_write_32(MACEPCI_ERROR_FLAGS,
-			      flags & ~MACEPCI_ERROR_TARGET_ABORT);
+		printk("MACEPCI: Target abort at 0x%08x (%c)\n", addr, s);
+		flags &= ~MACEPCI_ERROR_TARGET_ABORT;
 	}
 	if (flags & MACEPCI_ERROR_DATA_PARITY_ERR) {
-		printk("MACEPCI: Data parity error at 0x%08x (%c)\n",
-		       error_addr, space);
-		mace_write_32(MACEPCI_ERROR_FLAGS, flags
-			      & ~MACEPCI_ERROR_DATA_PARITY_ERR);
+		printk("MACEPCI: Data parity error at 0x%08x (%c)\n", addr, s);
+		flags &= ~MACEPCI_ERROR_DATA_PARITY_ERR;
 	}
 	if (flags & MACEPCI_ERROR_RETRY_ERR) {
-		printk("MACEPCI: Retry error at 0x%08x (%c)\n", error_addr,
-		       space);
-		mace_write_32(MACEPCI_ERROR_FLAGS, flags
-			      & ~MACEPCI_ERROR_RETRY_ERR);
+		printk("MACEPCI: Retry error at 0x%08x (%c)\n", addr, s);
+		flags &= ~MACEPCI_ERROR_RETRY_ERR;
 	}
 	if (flags & MACEPCI_ERROR_ILLEGAL_CMD) {
-		printk("MACEPCI: Illegal command at 0x%08x (%c)\n",
-		       error_addr, space);
-		mace_write_32(MACEPCI_ERROR_FLAGS,
-			      flags & ~MACEPCI_ERROR_ILLEGAL_CMD);
+		printk("MACEPCI: Illegal command at 0x%08x (%c)\n", addr, s);
+		flags &= ~MACEPCI_ERROR_ILLEGAL_CMD;
 	}
 	if (flags & MACEPCI_ERROR_SYSTEM_ERR) {
-		printk("MACEPCI: System error at 0x%08x (%c)\n",
-		       error_addr, space);
-		mace_write_32(MACEPCI_ERROR_FLAGS, flags
-			      & ~MACEPCI_ERROR_SYSTEM_ERR);
+		printk("MACEPCI: System error at 0x%08x (%c)\n", addr, s);
+		flags &= ~MACEPCI_ERROR_SYSTEM_ERR;
 	}
 	if (flags & MACEPCI_ERROR_PARITY_ERR) {
-		printk("MACEPCI: Parity error at 0x%08x (%c)\n",
-		       error_addr, space);
-		mace_write_32(MACEPCI_ERROR_FLAGS,
-			      flags & ~MACEPCI_ERROR_PARITY_ERR);
+		printk("MACEPCI: Parity error at 0x%08x (%c)\n", addr, s);
+		flags &= ~MACEPCI_ERROR_PARITY_ERR;
 	}
 	if (flags & MACEPCI_ERROR_OVERRUN) {
-		printk("MACEPCI: Overrun error at 0x%08x (%c)\n",
-		       error_addr, space);
-		mace_write_32(MACEPCI_ERROR_FLAGS, flags
-			      & ~MACEPCI_ERROR_OVERRUN);
+		printk("MACEPCI: Overrun error at 0x%08x (%c)\n", addr, s);
+		flags &= ~MACEPCI_ERROR_OVERRUN;
 	}
 	if (flags & MACEPCI_ERROR_SIG_TABORT) {
 		printk("MACEPCI: Signaled target abort (clearing)\n");
-		mace_write_32(MACEPCI_ERROR_FLAGS, flags
-			      & ~MACEPCI_ERROR_SIG_TABORT);
+		flags &= ~MACEPCI_ERROR_SIG_TABORT;
 	}
 	if (flags & MACEPCI_ERROR_INTERRUPT_TEST) {
 		printk("MACEPCI: Interrupt test triggered (clearing)\n");
-		mace_write_32(MACEPCI_ERROR_FLAGS, flags
-			      & ~MACEPCI_ERROR_INTERRUPT_TEST);
+		flags &= ~MACEPCI_ERROR_INTERRUPT_TEST;
 	}
+
+	mace->pci.error = flags;
+
+	return IRQ_HANDLED;
 }
 
-unsigned int pcibios_assign_all_busses(void)
+
+extern struct pci_ops mace_pci_ops;
+#ifdef CONFIG_MIPS64
+static struct resource mace_pci_mem_resource = {
+	.name	= "SGI O2 PCI MEM",
+	.start	= MACEPCI_HI_MEMORY,
+	.end	= 0x2FFFFFFFFUL,
+	.flags	= IORESOURCE_MEM,
+};
+static struct resource mace_pci_io_resource = {
+	.name	= "SGI O2 PCI IO",
+	.start	= 0x00000000UL,
+	.end	= 0xffffffffUL,
+	.flags	= IORESOURCE_IO,
+};
+#define MACE_PCI_MEM_OFFSET 0x200000000
+#else
+static struct resource mace_pci_mem_resource = {
+	.name	= "SGI O2 PCI MEM",
+	.start	= MACEPCI_LOW_MEMORY,
+	.end	= MACEPCI_LOW_MEMORY + 0x2000000 - 1,
+	.flags	= IORESOURCE_MEM,
+};
+static struct resource mace_pci_io_resource = {
+	.name	= "SGI O2 PCI IO",
+	.start	= 0x00000000,
+	.end	= 0xFFFFFFFF,
+	.flags	= IORESOURCE_IO,
+};
+#define MACE_PCI_MEM_OFFSET (MACEPCI_LOW_MEMORY - 0x80000000)
+#endif
+static struct pci_controller mace_pci_controller = {
+	.pci_ops	= &mace_pci_ops,
+	.mem_resource	= &mace_pci_mem_resource,
+	.io_resource	= &mace_pci_io_resource,
+	.iommu		= 0,
+	.mem_offset	= MACE_PCI_MEM_OFFSET,
+	.io_offset	= 0,
+};
+
+static int __init mace_init(void)
 {
+	PCIBIOS_MIN_IO = 0x1000;
+
+	/* Clear any outstanding errors and enable interrupts */
+	mace->pci.error_addr = 0;
+	mace->pci.error = 0;
+	mace->pci.control = 0xff008500;
+
+	printk("MACE PCI rev %d\n", mace->pci.rev);
+
+	BUG_ON(request_irq(MACE_PCI_BRIDGE_IRQ, macepci_error, 0,
+			   "MACE PCI error", NULL));
+
+	ioport_resource.end = mace_pci_io_resource.end;
+	register_pci_controller(&mace_pci_controller);
+
 	return 0;
 }
+
+arch_initcall(mace_init);
--- diff/arch/mips/pci/pci-ocelot-c.c	2003-08-20 14:16:25.000000000 +0100
+++ source/arch/mips/pci/pci-ocelot-c.c	2004-02-23 13:56:38.000000000 +0000
@@ -26,7 +26,6 @@
 #include <linux/pci.h>
 #include <linux/kernel.h>
 #include <linux/slab.h>
-#include <linux/version.h>
 #include <asm/pci.h>
 #include <asm/io.h>
 #include <asm/mv64340.h>
@@ -38,388 +37,8 @@
  * devices.
  */
 
-#define MAX_PCI_DEVS 10
-
 void mv64340_board_pcibios_fixup_bus(struct pci_bus *c);
 
-/*  Functions to implement "pci ops"  */
-static int marvell_pcibios_read_config_word(struct pci_dev *dev,
-					    int offset, u16 * val);
-static int marvell_pcibios_read_config_byte(struct pci_dev *dev,
-					    int offset, u8 * val);
-static int marvell_pcibios_read_config_dword(struct pci_dev *dev,
-					     int offset, u32 * val);
-static int marvell_pcibios_write_config_byte(struct pci_dev *dev,
-					     int offset, u8 val);
-static int marvell_pcibios_write_config_word(struct pci_dev *dev,
-					     int offset, u16 val);
-static int marvell_pcibios_write_config_dword(struct pci_dev *dev,
-					      int offset, u32 val);
-static void marvell_pcibios_set_master(struct pci_dev *dev);
-
-/*
- *  General-purpose PCI functions.
- */
-
-
-/*
- * pci_range_ck -
- *
- * Check if the pci device that are trying to access does really exists
- * on the evaluation board.  
- *
- * Inputs :
- * bus - bus number (0 for PCI 0 ; 1 for PCI 1)
- * dev - number of device on the specific pci bus
- *
- * Outpus :
- * 0 - if OK , 1 - if failure
- */
-static __inline__ int pci_range_ck(unsigned char bus, unsigned char dev)
-{
-	/* Accessing device 31 crashes the MV-64340. */
-	if (dev < 5)
-		return 0;
-	return -1;
-}
-
-/*
- * marvell_pcibios_(read/write)_config_(dword/word/byte) -
- *
- * reads/write a dword/word/byte register from the configuration space
- * of a device.
- *
- * Note that bus 0 and bus 1 are local, and we assume all other busses are
- * bridged from bus 1.  This is a safe assumption, since any other
- * configuration will require major modifications to the CP7000G
- *
- * Inputs :
- * bus - bus number
- * dev - device number
- * offset - register offset in the configuration space
- * val - value to be written / read
- *
- * Outputs :
- * PCIBIOS_SUCCESSFUL when operation was succesfull
- * PCIBIOS_DEVICE_NOT_FOUND when the bus or dev is errorneous
- * PCIBIOS_BAD_REGISTER_NUMBER when accessing non aligned
- */
-
-static int marvell_pcibios_read_config_dword(struct pci_dev *device,
-					     int offset, u32 * val)
-{
-	int dev, bus, func;
-	uint32_t address_reg, data_reg;
-	uint32_t address;
-
-	bus = device->bus->number;
-	dev = PCI_SLOT(device->devfn);
-	func = PCI_FUNC(device->devfn);
-
-	/* verify the range */
-	if (pci_range_ck(bus, dev))
-		return PCIBIOS_DEVICE_NOT_FOUND;
-
-	/* select the MV-64340 registers to communicate with the PCI bus */
-	if (bus == 0) {
-		address_reg = MV64340_PCI_0_CONFIG_ADDR;
-		data_reg = MV64340_PCI_0_CONFIG_DATA_VIRTUAL_REG;
-	} else {
-		address_reg = MV64340_PCI_1_CONFIG_ADDR;
-		data_reg = MV64340_PCI_1_CONFIG_DATA_VIRTUAL_REG;
-	}
-
-	address = (bus << 16) | (dev << 11) | (func << 8) |
-	    (offset & 0xfc) | 0x80000000;
-
-	/* start the configuration cycle */
-	MV_WRITE(address_reg, address);
-
-	/* read the data */
-	MV_READ(data_reg, val);
-
-	return PCIBIOS_SUCCESSFUL;
-}
-
-
-static int marvell_pcibios_read_config_word(struct pci_dev *device,
-					    int offset, u16 * val)
-{
-	int dev, bus, func;
-	uint32_t address_reg, data_reg;
-	uint32_t address;
-
-	bus = device->bus->number;
-	dev = PCI_SLOT(device->devfn);
-	func = PCI_FUNC(device->devfn);
-
-	/* verify the range */
-	if (pci_range_ck(bus, dev))
-		return PCIBIOS_DEVICE_NOT_FOUND;
-
-	/* select the MV-64340 registers to communicate with the PCI bus */
-	if (bus == 0) {
-		address_reg = MV64340_PCI_0_CONFIG_ADDR;
-		data_reg = MV64340_PCI_0_CONFIG_DATA_VIRTUAL_REG;
-	} else {
-		address_reg = MV64340_PCI_1_CONFIG_ADDR;
-		data_reg = MV64340_PCI_1_CONFIG_DATA_VIRTUAL_REG;
-	}
-
-	address = (bus << 16) | (dev << 11) | (func << 8) |
-	    (offset & 0xfc) | 0x80000000;
-
-	/* start the configuration cycle */
-	MV_WRITE(address_reg, address);
-
-	/* read the data */
-	MV_READ_16(data_reg + (offset & 0x3), val);
-
-	return PCIBIOS_SUCCESSFUL;
-}
-
-static int marvell_pcibios_read_config_byte(struct pci_dev *device,
-					    int offset, u8 * val)
-{
-	int dev, bus, func;
-	uint32_t address_reg, data_reg;
-	uint32_t address;
-
-	bus = device->bus->number;
-	dev = PCI_SLOT(device->devfn);
-	func = PCI_FUNC(device->devfn);
-
-	/* verify the range */
-	if (pci_range_ck(bus, dev))
-		return PCIBIOS_DEVICE_NOT_FOUND;
-
-	/* select the MV-64340 registers to communicate with the PCI bus */
-	if (bus == 0) {
-		address_reg = MV64340_PCI_0_CONFIG_ADDR;
-		data_reg = MV64340_PCI_0_CONFIG_DATA_VIRTUAL_REG;
-	} else {
-		address_reg = MV64340_PCI_1_CONFIG_ADDR;
-		data_reg = MV64340_PCI_1_CONFIG_DATA_VIRTUAL_REG;
-	}
-
-	address = (bus << 16) | (dev << 11) | (func << 8) |
-	    (offset & 0xfc) | 0x80000000;
-
-	/* start the configuration cycle */
-	MV_WRITE(address_reg, address);
-
-	/* write the data */
-	MV_READ_8(data_reg + (offset & 0x3), val);
-
-	return PCIBIOS_SUCCESSFUL;
-}
-
-static int marvell_pcibios_write_config_dword(struct pci_dev *device,
-					      int offset, u32 val)
-{
-	int dev, bus, func;
-	uint32_t address_reg, data_reg;
-	uint32_t address;
-
-	bus = device->bus->number;
-	dev = PCI_SLOT(device->devfn);
-	func = PCI_FUNC(device->devfn);
-
-	/* verify the range */
-	if (pci_range_ck(bus, dev))
-		return PCIBIOS_DEVICE_NOT_FOUND;
-
-	/* select the MV-64340 registers to communicate with the PCI bus */
-	if (bus == 0) {
-		address_reg = MV64340_PCI_0_CONFIG_ADDR;
-		data_reg = MV64340_PCI_0_CONFIG_DATA_VIRTUAL_REG;
-	} else {
-		address_reg = MV64340_PCI_1_CONFIG_ADDR;
-		data_reg = MV64340_PCI_1_CONFIG_DATA_VIRTUAL_REG;
-	}
-
-	address = (bus << 16) | (dev << 11) | (func << 8) |
-	    (offset & 0xfc) | 0x80000000;
-
-	/* start the configuration cycle */
-	MV_WRITE(address_reg, address);
-
-	/* write the data */
-	MV_WRITE(data_reg, val);
-
-	return PCIBIOS_SUCCESSFUL;
-}
-
-
-static int marvell_pcibios_write_config_word(struct pci_dev *device,
-					     int offset, u16 val)
-{
-	int dev, bus, func;
-	uint32_t address_reg, data_reg;
-	uint32_t address;
-
-	bus = device->bus->number;
-	dev = PCI_SLOT(device->devfn);
-	func = PCI_FUNC(device->devfn);
-
-	/* verify the range */
-	if (pci_range_ck(bus, dev))
-		return PCIBIOS_DEVICE_NOT_FOUND;
-
-	/* select the MV-64340 registers to communicate with the PCI bus */
-	if (bus == 0) {
-		address_reg = MV64340_PCI_0_CONFIG_ADDR;
-		data_reg = MV64340_PCI_0_CONFIG_DATA_VIRTUAL_REG;
-	} else {
-		address_reg = MV64340_PCI_1_CONFIG_ADDR;
-		data_reg = MV64340_PCI_1_CONFIG_DATA_VIRTUAL_REG;
-	}
-
-	address = (bus << 16) | (dev << 11) | (func << 8) |
-	    (offset & 0xfc) | 0x80000000;
-
-	/* start the configuration cycle */
-	MV_WRITE(address_reg, address);
-
-	/* write the data */
-	MV_WRITE_16(data_reg + (offset & 0x3), val);
-
-	return PCIBIOS_SUCCESSFUL;
-}
-
-static int marvell_pcibios_write_config_byte(struct pci_dev *device,
-					     int offset, u8 val)
-{
-	int dev, bus, func;
-	uint32_t address_reg, data_reg;
-	uint32_t address;
-
-	bus = device->bus->number;
-	dev = PCI_SLOT(device->devfn);
-	func = PCI_FUNC(device->devfn);
-
-	/* verify the range */
-	if (pci_range_ck(bus, dev))
-		return PCIBIOS_DEVICE_NOT_FOUND;
-
-	/* select the MV-64340 registers to communicate with the PCI bus */
-	if (bus == 0) {
-		address_reg = MV64340_PCI_0_CONFIG_ADDR;
-		data_reg = MV64340_PCI_0_CONFIG_DATA_VIRTUAL_REG;
-	} else {
-		address_reg = MV64340_PCI_1_CONFIG_ADDR;
-		data_reg = MV64340_PCI_1_CONFIG_DATA_VIRTUAL_REG;
-	}
-
-	address = (bus << 16) | (dev << 11) | (func << 8) |
-	    (offset & 0xfc) | 0x80000000;
-
-	/* start the configuration cycle */
-	MV_WRITE(address_reg, address);
-
-	/* write the data */
-	MV_WRITE_8(data_reg + (offset & 0x3), val);
-
-	return PCIBIOS_SUCCESSFUL;
-}
-
-static void marvell_pcibios_set_master(struct pci_dev *dev)
-{
-	u16 cmd;
-
-	marvell_pcibios_read_config_word(dev, PCI_COMMAND, &cmd);
-	cmd |= PCI_COMMAND_MASTER;
-	marvell_pcibios_write_config_word(dev, PCI_COMMAND, cmd);
-}
-
-/*  Externally-expected functions.  Do not change function names  */
-
-int pcibios_enable_resources(struct pci_dev *dev)
-{
-	u16 cmd, old_cmd;
-	u8 tmp1;
-	int idx;
-	struct resource *r;
-
-	marvell_pcibios_read_config_word(dev, PCI_COMMAND, &cmd);
-	old_cmd = cmd;
-	for (idx = 0; idx < 6; idx++) {
-		r = &dev->resource[idx];
-		if (!r->start && r->end) {
-			printk(KERN_ERR
-			       "PCI: Device %s not available because of "
-			       "resource collisions\n", pci_name(dev));
-			return -EINVAL;
-		}
-		if (r->flags & IORESOURCE_IO)
-			cmd |= PCI_COMMAND_IO;
-		if (r->flags & IORESOURCE_MEM)
-			cmd |= PCI_COMMAND_MEMORY;
-	}
-	if (cmd != old_cmd) {
-		marvell_pcibios_write_config_word(dev, PCI_COMMAND, cmd);
-	}
-
-	/*
-	 * Let's fix up the latency timer and cache line size here.  Cache
-	 * line size = 32 bytes / sizeof dword (4) = 8.
-	 * Latency timer must be > 8.  32 is random but appears to work.
-	 */
-	marvell_pcibios_read_config_byte(dev, PCI_CACHE_LINE_SIZE, &tmp1);
-	if (tmp1 != 8) {
-		printk(KERN_WARNING
-		       "PCI setting cache line size to 8 from " "%d\n",
-		       tmp1);
-		marvell_pcibios_write_config_byte(dev, PCI_CACHE_LINE_SIZE,
-						  8);
-	}
-	marvell_pcibios_read_config_byte(dev, PCI_LATENCY_TIMER, &tmp1);
-	if (tmp1 < 32) {
-		printk(KERN_WARNING
-		       "PCI setting latency timer to 32 from %d\n", tmp1);
-		marvell_pcibios_write_config_byte(dev, PCI_LATENCY_TIMER,
-						  32);
-	}
-
-	return 0;
-}
-
-int pcibios_enable_device(struct pci_dev *dev, int mask)
-{
-	return pcibios_enable_resources(dev);
-}
-
-void pcibios_align_resource(void *data, struct resource *res,
-			    unsigned long size)
-{
-	struct pci_dev *dev = data;
-
-	if (res->flags & IORESOURCE_IO) {
-		unsigned long start = res->start;
-
-		/* We need to avoid collisions with `mirrored' VGA ports
-		   and other strange ISA hardware, so we always want the
-		   addresses kilobyte aligned.  */
-		if (size > 0x100) {
-			printk(KERN_ERR "PCI: I/O Region %s/%d too large"
-			       " (%ld bytes)\n", pci_name(dev),
-			       dev->resource - res, size);
-		}
-
-		start = (start + 1024 - 1) & ~(1024 - 1);
-		res->start = start;
-	}
-}
-
-struct pci_ops marvell_pci_ops = {
-	marvell_pcibios_read_config_byte,
-	marvell_pcibios_read_config_word,
-	marvell_pcibios_read_config_dword,
-	marvell_pcibios_write_config_byte,
-	marvell_pcibios_write_config_word,
-	marvell_pcibios_write_config_dword
-};
-
 struct pci_fixup pcibios_fixups[] = {
 	{0}
 };
@@ -437,22 +56,6 @@ void __init pcibios_init(void)
 	iomem_resource.start = 0xc0000000;
 	iomem_resource.end = 0xc0000000 + 0x20000000 - 1;
 
-	pci_scan_bus(0, &marvell_pci_ops, NULL);
-	pci_scan_bus(1, &marvell_pci_ops, NULL);
-}
-
-/*
- * for parsing "pci=" kernel boot arguments.
- */
-char *pcibios_setup(char *str)
-{
-	printk(KERN_INFO "rr: pcibios_setup\n");
-	/* Nothing to do for now.  */
-
-	return str;
-}
-
-unsigned __init int pcibios_assign_all_busses(void)
-{
-	return 1;
+	pci_scan_bus(0, &mv64340_bus0_pci_ops, NULL);
+	pci_scan_bus(1, &mv64340_bus1_pci_ops, NULL);
 }
--- diff/arch/mips/pci/pci-ocelot-g.c	2003-08-20 14:16:25.000000000 +0100
+++ source/arch/mips/pci/pci-ocelot-g.c	2004-02-23 13:56:38.000000000 +0000
@@ -26,7 +26,6 @@
 #include <linux/pci.h>
 #include <linux/kernel.h>
 #include <linux/slab.h>
-#include <linux/version.h>
 #include <asm/pci.h>
 #include <asm/io.h>
 #include "gt64240.h"
@@ -41,8 +40,6 @@
  * devices.
  */
 
-#define MAX_PCI_DEVS 10
-
 void gt64240_board_pcibios_fixup_bus(struct pci_bus *c);
 
 /*  Functions to implement "pci ops"  */
@@ -58,9 +55,6 @@ static int galileo_pcibios_write_config_
 					     int offset, u16 val);
 static int galileo_pcibios_write_config_dword(int bus, int devfn,
 					      int offset, u32 val);
-#if 0
-static void galileo_pcibios_set_master(struct pci_dev *dev);
-#endif
 
 static int pci_read(struct pci_bus *bus, unsigned int devfs, int where,
 		    int size, u32 * val);
@@ -343,96 +337,6 @@ static int galileo_pcibios_write_config_
 	return PCIBIOS_SUCCESSFUL;
 }
 
-#if 0
-static void galileo_pcibios_set_master(struct pci_dev *dev)
-{
-	u16 cmd;
-
-	galileo_pcibios_read_config_word(dev, PCI_COMMAND, &cmd);
-	cmd |= PCI_COMMAND_MASTER;
-	galileo_pcibios_write_config_word(dev, PCI_COMMAND, cmd);
-}
-#endif
-
-/*  Externally-expected functions.  Do not change function names  */
-
-int pcibios_enable_resources(struct pci_dev *dev)
-{
-	u16 cmd, old_cmd;
-	u8 tmp1;
-	int idx;
-	struct resource *r;
-
-	pci_read(dev->bus, dev->devfn, PCI_COMMAND, 2, (u32 *) & cmd);
-	old_cmd = cmd;
-	for (idx = 0; idx < 6; idx++) {
-		r = &dev->resource[idx];
-		if (!r->start && r->end) {
-			printk(KERN_ERR
-			       "PCI: Device %s not available because of "
-			       "resource collisions\n", pci_name(dev));
-			return -EINVAL;
-		}
-		if (r->flags & IORESOURCE_IO)
-			cmd |= PCI_COMMAND_IO;
-		if (r->flags & IORESOURCE_MEM)
-			cmd |= PCI_COMMAND_MEMORY;
-	}
-	if (cmd != old_cmd) {
-		pci_write(dev->bus, dev->devfn, PCI_COMMAND, 2, cmd);
-	}
-
-	/*
-	 * Let's fix up the latency timer and cache line size here.  Cache
-	 * line size = 32 bytes / sizeof dword (4) = 8.
-	 * Latency timer must be > 8.  32 is random but appears to work.
-	 */
-	pci_read(dev->bus, dev->devfn, PCI_CACHE_LINE_SIZE, 1,
-		 (u32 *) & tmp1);
-	if (tmp1 != 8) {
-		printk(KERN_WARNING
-		       "PCI setting cache line size to 8 from " "%d\n",
-		       tmp1);
-		pci_write(dev->bus, dev->devfn, PCI_CACHE_LINE_SIZE, 1, 8);
-	}
-	pci_read(dev->bus, dev->devfn, PCI_LATENCY_TIMER, 1,
-		 (u32 *) & tmp1);
-	if (tmp1 < 32) {
-		printk(KERN_WARNING
-		       "PCI setting latency timer to 32 from %d\n", tmp1);
-		pci_write(dev->bus, dev->devfn, PCI_LATENCY_TIMER, 1, 32);
-	}
-
-	return 0;
-}
-
-int pcibios_enable_device(struct pci_dev *dev, int mask)
-{
-	return pcibios_enable_resources(dev);
-}
-
-void pcibios_align_resource(void *data, struct resource *res,
-			    unsigned long size, unsigned long align)
-{
-	struct pci_dev *dev = data;
-
-	if (res->flags & IORESOURCE_IO) {
-		unsigned long start = res->start;
-
-		/* We need to avoid collisions with `mirrored' VGA ports
-		   and other strange ISA hardware, so we always want the
-		   addresses kilobyte aligned.  */
-		if (size > 0x100) {
-			printk(KERN_ERR "PCI: I/O Region %s/%d too large"
-			       " (%ld bytes)\n", pci_name(dev),
-			       dev->resource - res, size);
-		}
-
-		start = (start + 1024 - 1) & ~(1024 - 1);
-		res->start = start;
-	}
-}
-
 struct pci_ops galileo_pci_ops = {
 	.read = pci_read,
 	.write = pci_write
@@ -554,19 +458,3 @@ static int __init pcibios_init(void)
 }
 
 subsys_initcall(pcibios_init);
-
-/*
- * for parsing "pci=" kernel boot arguments.
- */
-char *pcibios_setup(char *str)
-{
-	printk(KERN_INFO "rr: pcibios_setup\n");
-	/* Nothing to do for now.  */
-
-	return str;
-}
-
-unsigned __init int pcibios_assign_all_busses(void)
-{
-	return 1;
-}
--- diff/arch/mips/pci/pci-sb1250.c	2003-07-08 09:55:17.000000000 +0100
+++ source/arch/mips/pci/pci-sb1250.c	2004-02-23 13:56:38.000000000 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2001,2002 Broadcom Corporation
+ * Copyright (C) 2001,2002,2003 Broadcom Corporation
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
@@ -37,10 +37,13 @@
 #include <linux/mm.h>
 #include <linux/console.h>
 
+#include <asm/io.h>
+#include <asm/pci_channel.h>
+
 #include <asm/sibyte/sb1250_defs.h>
 #include <asm/sibyte/sb1250_regs.h>
 #include <asm/sibyte/sb1250_scd.h>
-#include <asm/io.h>
+#include <asm/sibyte/board.h>
 
 /*
  * Macros for calculating offsets into config space given a device
@@ -158,6 +161,8 @@ static int sb1250_pcibios_write(struct p
 	else if (size == 2)
 		data = (data & ~(0xffff << ((where & 3) << 3))) |
 		    (val << ((where & 3) << 3));
+	else
+		data = val;
 
 	WRITECFG32(cfgaddr, data);
 
@@ -169,8 +174,27 @@ struct pci_ops sb1250_pci_ops = {
 	.write = sb1250_pcibios_write
 };
 
+static struct resource sb1250_mem_resource = {
+	.name	= "SB1250 PCI MEM",
+	.start	= 0x14000000UL,
+	.end	= 0x17ffffffUL,
+	.flags	= IORESOURCE_MEM,
+};
+                                                                                
+static struct resource sb1250_io_resource = {
+	.name	= "SB1250 IO MEM",
+	.start	= 0x14000000UL,
+	.end	= 0x17ffffffUL,
+	.flags	= IORESOURCE_IO,
+};
+
+struct pci_controller sb1250_controller = {
+	.pci_ops	= &sb1250_pci_ops,
+	.mem_resource	= &sb1250_mem_resource,
+	.io_resource	= &sb1250_io_resource
+};
 
-void __init pcibios_init(void)
+int __init pcibios_init(void)	xxx This needs to be called somehow ...
 {
 	uint32_t cmdreg;
 	uint64_t reg;
@@ -181,7 +205,7 @@ void __init pcibios_init(void)
 	/*
 	 * See if the PCI bus has been configured by the firmware.
 	 */
-	reg = *((volatile uint64_t *) KSEG1ADDR(A_SCD_SYSTEM_CFG));
+	reg = *((volatile uint64_t *) IOADDR(A_SCD_SYSTEM_CFG));
 	if (!(reg & M_SYS_PCI_HOST)) {
 		sb1250_bus_status |= PCI_DEVICE_MODE;
 	} else {
@@ -193,7 +217,7 @@ void __init pcibios_init(void)
 			printk
 			    ("PCI: Skipping PCI probe.  Bus is not initialized.\n");
 			iounmap(cfg_space);
-			return;
+			return 0;
 		}
 		sb1250_bus_status |= PCI_BUS_ENABLED;
 	}
@@ -234,48 +258,14 @@ void __init pcibios_init(void)
 	}
 #endif
 
-	/* Probe for PCI hardware */
-
-	printk("PCI: Probing PCI hardware on host bus 0.\n");
-	pci_scan_bus(0, &sb1250_pci_ops, NULL);
+	register_pci_controller(&sb1250_controller);
 
 #ifdef CONFIG_VGA_CONSOLE
 	take_over_console(&vga_con, 0, MAX_NR_CONSOLES - 1, 1);
 #endif
-}
-
-int pcibios_enable_device(struct pci_dev *dev, int mask)
-{
-	/* Not needed, since we enable all devices at startup.  */
 	return 0;
 }
 
-void pcibios_align_resource(void *data, struct resource *res,
-			    unsigned long size, unsigned long align)
-{
-}
-
-char *__init pcibios_setup(char *str)
-{
-	/* Nothing to do for now.  */
-
-	return str;
-}
-
 struct pci_fixup pcibios_fixups[] = {
 	{0}
 };
-
-/*
- *  Called after each bus is probed, but before its children
- *  are examined.
- */
-void __devinit pcibios_fixup_bus(struct pci_bus *b)
-{
-	pci_read_bridge_bases(b);
-}
-
-unsigned int pcibios_assign_all_busses(void)
-{
-	return 1;
-}
--- diff/arch/mips/pci/pci-vr41xx.c	2003-07-08 09:55:17.000000000 +0100
+++ source/arch/mips/pci/pci-vr41xx.c	2004-02-23 13:56:38.000000000 +0000
@@ -8,7 +8,7 @@
  * Author: Yoichi Yuasa
  *         yyuasa@mvista.com or source@mvista.com
  *
- * Copyright 2001,2002 MontaVista Software Inc.
+ * Copyright 2001-2003 MontaVista Software Inc.
  *
  *  This program is free software; you can redistribute it and/or modify it
  *  under the terms of the GNU General Public License as published by the
@@ -49,9 +49,7 @@
 #include <asm/pci_channel.h>
 #include <asm/vr41xx/vr41xx.h>
 
-#include "pciu.h"
-
-extern unsigned long vr41xx_vtclock;
+#include "pci-vr41xx.h"
 
 static inline int vr41xx_pci_config_access(unsigned char bus,
 					   unsigned int devfn, int where)
@@ -150,6 +148,7 @@ struct pci_ops vr41xx_pci_ops = {
 void __init vr41xx_pciu_init(struct vr41xx_pci_address_map *map)
 {
 	struct vr41xx_pci_address_space *s;
+	unsigned long vtclock;
 	u32 config;
 	int n;
 
@@ -169,11 +168,12 @@ void __init vr41xx_pciu_init(struct vr41
 	udelay(1);
 
 	/* Select PCI clock */
-	if (vr41xx_vtclock < MAX_PCI_CLOCK)
+	vtclock = vr41xx_get_vtclock_frequency();
+	if (vtclock < MAX_PCI_CLOCK)
 		writel(EQUAL_VTCLOCK, PCICLKSELREG);
-	else if ((vr41xx_vtclock / 2) < MAX_PCI_CLOCK)
+	else if ((vtclock / 2) < MAX_PCI_CLOCK)
 		writel(HALF_VTCLOCK, PCICLKSELREG);
-	else if ((vr41xx_vtclock / 4) < MAX_PCI_CLOCK)
+	else if ((vtclock / 4) < MAX_PCI_CLOCK)
 		writel(QUARTER_VTCLOCK, PCICLKSELREG);
 	else
 		printk(KERN_INFO "Warning: PCI Clock is over 33MHz.\n");
--- diff/arch/mips/pci/pci-vr41xx.h	2003-07-08 09:55:17.000000000 +0100
+++ source/arch/mips/pci/pci-vr41xx.h	2004-02-23 13:56:38.000000000 +0000
@@ -107,9 +107,6 @@
 
 #define MAX_PCI_CLOCK			33333333
 
-#define PCIU_CLOCK			0x0080
-#define PCI_CLOCK			0x2000
-
 static inline int pciu_read_config_byte(int where, u8 * val)
 {
 	u32 data;
--- diff/arch/mips/pci/pci.c	2003-07-08 09:55:17.000000000 +0100
+++ source/arch/mips/pci/pci.c	2004-02-23 13:56:38.000000000 +0000
@@ -1,233 +1,304 @@
 /*
- * Copyright 2001 MontaVista Software Inc.
- * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net
- *
- * Modified to be mips generic, ppopov@mvista.com
- * arch/mips/kernel/pci.c
- *     Common MIPS PCI routines.
- *
  * This program is free software; you can redistribute  it and/or modify it
  * under  the terms of  the GNU General  Public License as published by the
  * Free Software Foundation;  either version 2 of the  License, or (at your
  * option) any later version.
- */
-
-/*
- * This file contains common PCI routines meant to be shared for
- * all MIPS machines.
- *
- * Strategies:
- *
- * . We rely on pci_auto.c file to assign PCI resources (MEM and IO)
- *   TODO: this should be optional for some machines where they do have
- *   a real "pcibios" that does resource assignment.
- *
- * . We then use pci_scan_bus() to "discover" all the resources for
- *   later use by Linux.
- *
- * . We finally reply on a board supplied function, pcibios_fixup_irq(), to
- *   to assign the interrupts.  We may use setup-irq.c under drivers/pci
- *   later.
- *
- * . Specifically, we will *NOT* use pci_assign_unassigned_resources(),
- *   because we assume all PCI devices should have the resources correctly
- *   assigned and recorded.
- *
- * Limitations:
  *
- * . We "collapse" all IO and MEM spaces in sub-buses under a top-level bus
- *   into a contiguous range.
- *
- * . In the case of Memory space, the rnage is 1:1 mapping with CPU physical
- *   address space.
- *
- * . In the case of IO space, it starts from 0, and the beginning address
- *   is mapped to KSEG0ADDR(mips_io_port) in the CPU physical address.
- *
- * . These are the current MIPS limitations (by ioremap, etc).  In the
- *   future, we may remove them.
- *
- * Credits:
- *	Most of the code are derived from the pci routines from PPC and Alpha,
- *	which were mostly writtne by
- *		Cort Dougan, cort@fsmlabs.com
- *		Matt Porter, mporter@mvista.com
- *		Dave Rusling david.rusling@reo.mts.dec.com
- *		David Mosberger davidm@cs.arizona.edu
+ * Copyright (C) 2003 Ralf Baechle (ralf@linux-mips.org)
  */
 #include <linux/config.h>
 #include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/bootmem.h>
 #include <linux/init.h>
 #include <linux/types.h>
 #include <linux/pci.h>
 
 #include <asm/pci_channel.h>
 
-extern void pcibios_fixup(void);
-extern void pcibios_fixup_irqs(void);
+/*
+ * Indicate whether we respect the PCI setup left by the firmware.
+ *
+ * Make this long-lived  so that we know when shutting down
+ * whether we probed only or not.
+ */
+int pci_probe_only;
 
-void __init pcibios_fixup_irqs(void)
-{
-	struct pci_dev *dev = NULL;
-	int slot_num;
+#define PCI_ASSIGN_ALL_BUSSES	1
 
+unsigned int pci_probe = PCI_ASSIGN_ALL_BUSSES;
 
-	while ((dev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) {
-		slot_num = PCI_SLOT(dev->devfn);
-		switch (slot_num) {
-		case 2:
-			dev->irq = 3;
-			break;
-		case 3:
-			dev->irq = 4;
-			break;
-		case 4:
-			dev->irq = 5;
-			break;
-		default:
-			break;
-		}
+/*
+ * The PCI controller list.
+ */
+
+struct pci_controller *hose_head, **hose_tail = &hose_head;
+struct pci_controller *pci_isa_hose;
+
+unsigned long PCIBIOS_MIN_IO	= 0x0000;
+unsigned long PCIBIOS_MIN_MEM	= 0;
+
+/*
+ * We need to avoid collisions with `mirrored' VGA ports
+ * and other strange ISA hardware, so we always want the
+ * addresses to be allocated in the 0x000-0x0ff region
+ * modulo 0x400.
+ *
+ * Why? Because some silly external IO cards only decode
+ * the low 10 bits of the IO address. The 0x00-0xff region
+ * is reserved for motherboard devices that decode all 16
+ * bits, so it's ok to allocate at, say, 0x2800-0x28ff,
+ * but we want to try to avoid allocating at 0x2900-0x2bff
+ * which might have be mirrored at 0x0100-0x03ff..
+ */
+void
+pcibios_align_resource(void *data, struct resource *res,
+		       unsigned long size, unsigned long align)
+{
+	struct pci_dev *dev = data;
+	struct pci_controller *hose = dev->sysdata;
+	unsigned long start = res->start;
+
+	if (res->flags & IORESOURCE_IO) {
+		/* Make sure we start at our min on all hoses */
+		if (start - hose->io_resource->start < PCIBIOS_MIN_IO)
+			start = PCIBIOS_MIN_IO + hose->io_resource->start;
+
+		/*
+		 * Put everything into 0x00-0xff region modulo 0x400
+		 */
+		if (start & 0x300)
+			start = (start + 0x3ff) & ~0x3ff;
+	} else if (res->flags & IORESOURCE_MEM) {
+		/* Make sure we start at our min on all hoses */
+		if (start - hose->mem_resource->start < PCIBIOS_MIN_MEM)
+			start = PCIBIOS_MIN_MEM + hose->mem_resource->start;
 	}
+
+	res->start = start;
 }
 
-void __init pcibios_fixup_resources(struct pci_dev *dev)
-{				/* HP-LJ */
-	int pos;
-	int bases;
-
-	printk("adjusting pci device: %s\n", dev->name);
-
-	switch (dev->hdr_type) {
-	case PCI_HEADER_TYPE_NORMAL:
-		bases = 6;
-		break;
-	case PCI_HEADER_TYPE_BRIDGE:
-		bases = 2;
-		break;
-	case PCI_HEADER_TYPE_CARDBUS:
-		bases = 1;
-		break;
-	default:
-		bases = 0;
-		break;
-	}
-	for (pos = 0; pos < bases; pos++) {
-		struct resource *res = &dev->resource[pos];
-		if (res->start >= IO_MEM_LOGICAL_START &&
-		    res->end <= IO_MEM_LOGICAL_END) {
-			res->start += IO_MEM_VIRTUAL_OFFSET;
-			res->end += IO_MEM_VIRTUAL_OFFSET;
-		}
-		if (res->start >= IO_PORT_LOGICAL_START &&
-		    res->end <= IO_PORT_LOGICAL_END) {
-			res->start += IO_PORT_VIRTUAL_OFFSET;
-			res->end += IO_PORT_VIRTUAL_OFFSET;
-		}
-	}
+struct pci_controller * __init alloc_pci_controller(void)
+{
+	return alloc_bootmem(sizeof(struct pci_controller));
+}
+
+void __init register_pci_controller(struct pci_controller *hose)
+{
+	*hose_tail = hose;
+	hose_tail = &hose->next;
+}
+
+/* Most MIPS systems have straight-forward swizzling needs.  */
 
+static inline u8 bridge_swizzle(u8 pin, u8 slot)
+{
+	return (((pin - 1) + slot) % 4) + 1;
 }
 
-struct pci_fixup pcibios_fixups[] = {
-	{PCI_FIXUP_HEADER, PCI_ANY_ID, PCI_ANY_ID,
-	 pcibios_fixup_resources},
-	{0}
-};
+static u8 __init common_swizzle(struct pci_dev *dev, u8 *pinp)
+{
+	u8 pin = *pinp;
 
-extern int pciauto_assign_resources(int busno, struct pci_channel *hose);
+	while (dev->bus->parent) {
+		pin = bridge_swizzle(pin, PCI_SLOT(dev->devfn));
+		/* Move up the chain of bridges. */
+		dev = dev->bus->self;
+        }
+	*pinp = pin;
+
+	/* The slot is the slot of the last bridge. */
+	return PCI_SLOT(dev->devfn);
+}
 
 static int __init pcibios_init(void)
 {
-	struct pci_channel *p;
+	struct pci_controller *hose;
 	struct pci_bus *bus;
-	int busno;
+	int next_busno;
+	int need_domain_info = 0;
 
-#ifdef CONFIG_PCI_AUTO
-	/* assign resources */
-	busno = 0;
-	for (p = mips_pci_channels; p->pci_ops != NULL; p++) {
-		busno = pciauto_assign_resources(busno, p) + 1;
-	}
-#endif
+	/* Scan all of the recorded PCI controllers.  */
+	for (next_busno = 0, hose = hose_head; hose; hose = hose->next) {
+
+		if (request_resource(&iomem_resource, hose->mem_resource) < 0)
+			goto out;
+		if (request_resource(&ioport_resource, hose->io_resource) < 0)
+			goto out_free_mem_resource;
+
+		if (!hose->iommu)
+			PCI_DMA_BUS_IS_PHYS = 1;
+
+		bus = pci_scan_bus(next_busno, hose->pci_ops, hose);
+		hose->bus = bus;
+		hose->need_domain_info = need_domain_info;
+		next_busno = bus->subordinate + 1;
+		/* Don't allow 8-bit bus number overflow inside the hose -
+		   reserve some space for bridges. */ 
+		if (next_busno > 224) {
+			next_busno = 0;
+			need_domain_info = 1;
+		}
+		continue;
 
-	/* scan the buses */
-	busno = 0;
-	for (p = mips_pci_channels; p->pci_ops != NULL; p++) {
-		bus = pci_scan_bus(busno, p->pci_ops, p);
-		busno = bus->subordinate + 1;
+out_free_mem_resource:
+		release_resource(hose->mem_resource);
+
+out:
+		printk(KERN_WARNING
+		       "Skipping PCI bus scan due to resource conflict\n");
 	}
 
-	/* machine dependent fixups */
-	pcibios_fixup();
-	/* fixup irqs (board specific routines) */
-	pcibios_fixup_irqs();
+	if (!pci_probe_only)
+		pci_assign_unassigned_resources();
+	pci_fixup_irqs(common_swizzle, pcibios_map_irq);
 
 	return 0;
 }
 
 subsys_initcall(pcibios_init);
 
-int pcibios_enable_device(struct pci_dev *dev, int mask)
+static int pcibios_enable_resources(struct pci_dev *dev, int mask)
 {
-	/* pciauto_assign_resources() will enable all devices found */
+	u16 cmd, old_cmd;
+	int idx;
+	struct resource *r;
+
+	pci_read_config_word(dev, PCI_COMMAND, &cmd);
+	old_cmd = cmd;
+	for(idx=0; idx<6; idx++) {
+		/* Only set up the requested stuff */
+		if (!(mask & (1<<idx)))
+			continue;
+
+		r = &dev->resource[idx];
+		if (!r->start && r->end) {
+			printk(KERN_ERR "PCI: Device %s not available because of resource collisions\n", pci_name(dev));
+			return -EINVAL;
+		}
+		if (r->flags & IORESOURCE_IO)
+			cmd |= PCI_COMMAND_IO;
+		if (r->flags & IORESOURCE_MEM)
+			cmd |= PCI_COMMAND_MEMORY;
+	}
+	if (dev->resource[PCI_ROM_RESOURCE].start)
+		cmd |= PCI_COMMAND_MEMORY;
+	if (cmd != old_cmd) {
+		printk("PCI: Enabling device %s (%04x -> %04x)\n", pci_name(dev), old_cmd, cmd);
+		pci_write_config_word(dev, PCI_COMMAND, cmd);
+	}
 	return 0;
 }
 
-unsigned long __init pci_bridge_check_io(struct pci_dev *bridge)
+/*
+ *  If we set up a device for bus mastering, we need to check the latency
+ *  timer as certain crappy BIOSes forget to set it properly.
+ */
+unsigned int pcibios_max_latency = 255;
+
+void pcibios_set_master(struct pci_dev *dev)
+{
+	u8 lat;
+	pci_read_config_byte(dev, PCI_LATENCY_TIMER, &lat);
+	if (lat < 16)
+		lat = (64 <= pcibios_max_latency) ? 64 : pcibios_max_latency;
+	else if (lat > pcibios_max_latency)
+		lat = pcibios_max_latency;
+	else
+		return;
+	printk(KERN_DEBUG "PCI: Setting latency timer of device %s to %d\n",
+	       pci_name(dev), lat);
+	pci_write_config_byte(dev, PCI_LATENCY_TIMER, lat);
+}
+
+unsigned int pcibios_assign_all_busses(void)
+{
+	return (pci_probe & PCI_ASSIGN_ALL_BUSSES) ? 1 : 0;
+}
+
+int pcibios_enable_device(struct pci_dev *dev, int mask)
 {
-	u16 io;
+	int err;
+
+	if ((err = pcibios_enable_resources(dev, mask)) < 0)
+		return err;
 
-	pci_read_config_word(bridge, PCI_IO_BASE, &io);
-	if (!io) {
-		pci_write_config_word(bridge, PCI_IO_BASE, 0xf0f0);
-		pci_read_config_word(bridge, PCI_IO_BASE, &io);
-		pci_write_config_word(bridge, PCI_IO_BASE, 0x0);
-	}
-	if (io)
-		return IORESOURCE_IO;
-	//printk(KERN_WARNING "PCI: bridge %s does not support I/O forwarding!\n", bridge->name);
 	return 0;
 }
 
+static void __init pcibios_fixup_device_resources(struct pci_dev *dev,
+	struct pci_bus *bus)
+{
+	/* Update device resources.  */
+	struct pci_controller *hose = (struct pci_controller *)bus->sysdata;
+	unsigned long offset;
+	int i;
+
+	for (i = 0; i < PCI_NUM_RESOURCES; i++) {
+		if (!dev->resource[i].start)
+			continue;
+		if (dev->resource[i].flags & IORESOURCE_IO)
+			offset = hose->io_offset;
+		else if (dev->resource[i].flags & IORESOURCE_MEM)
+			offset = hose->mem_offset;
+
+		dev->resource[i].start += offset;
+		dev->resource[i].end += offset;
+	}
+}
+
 void __devinit pcibios_fixup_bus(struct pci_bus *bus)
 {
-	/* Propogate hose info into the subordinate devices.  */
+	/* Propagate hose info into the subordinate devices.  */
 
-	struct pci_channel *hose = bus->sysdata;
+	struct pci_controller *hose = bus->sysdata;
+	struct list_head *ln;
 	struct pci_dev *dev = bus->self;
 
 	if (!dev) {
-		/* Root bus */
 		bus->resource[0] = hose->io_resource;
 		bus->resource[1] = hose->mem_resource;
-	} else {
-		/* This is a bridge. Do not care how it's initialized,
-		   just link its resources to the bus ones */
-		int i;
-
-		for (i = 0; i < 3; i++) {
-			bus->resource[i] =
-			    &dev->resource[PCI_BRIDGE_RESOURCES + i];
-			bus->resource[i]->name = bus->name;
-		}
-		bus->resource[0]->flags |= pci_bridge_check_io(dev);
-		bus->resource[1]->flags |= IORESOURCE_MEM;
-		/* For now, propagate hose limits to the bus;
-		   we'll adjust them later. */
-		bus->resource[0]->end = hose->io_resource->end;
-		bus->resource[1]->end = hose->mem_resource->end;
-		/* Turn off downstream PF memory address range by default */
-		bus->resource[2]->start = 1024 * 1024;
-		bus->resource[2]->end = bus->resource[2]->start - 1;
+	} else if (pci_probe_only &&
+		   (dev->class >> 8) == PCI_CLASS_BRIDGE_PCI) {
+		pci_read_bridge_bases(bus);
+		pcibios_fixup_device_resources(dev, bus);
+	} 
+
+	for (ln = bus->devices.next; ln != &bus->devices; ln = ln->next) {
+		struct pci_dev *dev = pci_dev_b(ln);
+
+		if ((dev->class >> 8) != PCI_CLASS_BRIDGE_PCI)
+			pcibios_fixup_device_resources(dev, bus);
 	}
 }
 
-char *pcibios_setup(char *str)
+void __init
+pcibios_update_irq(struct pci_dev *dev, int irq)
 {
-	return str;
+	pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq);
+}
+
+void __devinit
+pcibios_resource_to_bus(struct pci_dev *dev, struct pci_bus_region *region,
+			 struct resource *res)
+{
+	struct pci_controller *hose = (struct pci_controller *)dev->sysdata;
+	unsigned long offset = 0;
+
+	if (res->flags & IORESOURCE_IO)
+		offset = hose->io_offset;
+	else if (res->flags & IORESOURCE_MEM)
+		offset = hose->mem_offset;
+
+	region->start = res->start - offset;
+	region->end = res->end - offset;
 }
 
-void pcibios_align_resource(void *data, struct resource *res,
-			    unsigned long size, unsigned long align)
+#ifdef CONFIG_HOTPLUG
+EXPORT_SYMBOL(pcibios_resource_to_bus);
+#endif
+
+char *pcibios_setup(char *str)
 {
-	/* this should not be called */
+	return str;
 }
--- diff/arch/mips/ramdisk/Makefile	2003-08-20 14:16:08.000000000 +0100
+++ source/arch/mips/ramdisk/Makefile	2004-02-23 13:56:38.000000000 +0000
@@ -2,8 +2,19 @@
 # Makefile for a ramdisk image
 #
 
+obj-y += ramdisk.o
+
+
 O_FORMAT = $(shell $(OBJDUMP) -i | head -n 2 | grep elf32)
-img = $(CONFIG_EMBEDDED_RAMDISK_IMAGE)
-ramdisk.o: $(subst ",,$(img)) ld.script
-	echo "O_FORMAT:  " $(O_FORMAT)
-	$(LD) -T ld.script -b binary --oformat $(O_FORMAT) -o $@ $(img)
+img := $(subst ",,$(CONFIG_EMBEDDED_RAMDISK_IMAGE))
+# add $(src) when $(img) is relative
+img := $(subst $(src)//,/,$(src)/$(img))
+
+quiet_cmd_ramdisk = LD      $@
+define cmd_ramdisk
+	$(LD) -T $(src)/ld.script -b binary --oformat $(O_FORMAT) -o $@ $(img)
+endef
+
+$(obj)/ramdisk.o: $(img) $(src)/ld.script
+	$(call cmd,ramdisk)
+
--- diff/arch/mips/sgi-ip22/Makefile	2003-07-08 09:55:17.000000000 +0100
+++ source/arch/mips/sgi-ip22/Makefile	2004-02-23 13:56:38.000000000 +0000
@@ -4,8 +4,7 @@
 #
 
 obj-y	+= ip22-mc.o ip22-hpc.o ip22-int.o ip22-irq.o ip22-berr.o \
-	   ip22-time.o ip22-rtc.o ip22-nvram.o ip22-reset.o \
-	   ip22-setup.o ip22-ksyms.o
+	   ip22-time.o ip22-nvram.o ip22-reset.o ip22-setup.o
 
 obj-$(CONFIG_EISA)	+= ip22-eisa.o
 
--- diff/arch/mips/sgi-ip22/ip22-berr.c	2003-08-20 14:16:25.000000000 +0100
+++ source/arch/mips/sgi-ip22/ip22-berr.c	2004-02-23 13:56:38.000000000 +0000
@@ -44,18 +44,18 @@ static void save_and_clear_buserr(void)
 static void print_buserr(void)
 {
 	if (extio_stat & EXTIO_MC_BUSERR)
-		printk(KERN_ALERT "MC Bus Error\n");
+		printk(KERN_ERR "MC Bus Error\n");
 	if (extio_stat & EXTIO_HPC3_BUSERR)
-		printk(KERN_ALERT "HPC3 Bus Error 0x%x:<id=0x%x,%s,lane=0x%x>\n",
+		printk(KERN_ERR "HPC3 Bus Error 0x%x:<id=0x%x,%s,lane=0x%x>\n",
 			hpc3_berr_stat,
 			(hpc3_berr_stat & HPC3_BESTAT_PIDMASK) >>
 					  HPC3_BESTAT_PIDSHIFT,
 			(hpc3_berr_stat & HPC3_BESTAT_CTYPE) ? "PIO" : "DMA",
 			hpc3_berr_stat & HPC3_BESTAT_BLMASK);
 	if (extio_stat & EXTIO_EISA_BUSERR)
-		printk(KERN_ALERT "EISA Bus Error\n");
+		printk(KERN_ERR "EISA Bus Error\n");
 	if (cpu_err_stat & CPU_ERRMASK)
-		printk(KERN_ALERT "CPU error 0x%x<%s%s%s%s%s%s> @ 0x%08x\n",
+		printk(KERN_ERR "CPU error 0x%x<%s%s%s%s%s%s> @ 0x%08x\n",
 			cpu_err_stat,
 			cpu_err_stat & SGIMC_CSTAT_RD ? "RD " : "",
 			cpu_err_stat & SGIMC_CSTAT_PAR ? "PAR " : "",
@@ -65,7 +65,7 @@ static void print_buserr(void)
 			cpu_err_stat & SGIMC_CSTAT_BAD_DATA ? "BAD_DATA " : "",
 			cpu_err_addr);
 	if (gio_err_stat & GIO_ERRMASK)
-		printk(KERN_ALERT "GIO error 0x%x:<%s%s%s%s%s%s%s%s> @ 0x08%x\n",
+		printk(KERN_ERR "GIO error 0x%x:<%s%s%s%s%s%s%s%s> @ 0x08%x\n",
 			gio_err_stat,
 			gio_err_stat & SGIMC_GSTAT_RD ? "RD " : "",
 			gio_err_stat & SGIMC_GSTAT_WR ? "WR " : "",
@@ -87,13 +87,19 @@ static void print_buserr(void)
 
 void ip22_be_interrupt(int irq, struct pt_regs *regs)
 {
+	const int field = 2 * sizeof(unsigned long);
+
 	save_and_clear_buserr();
 	print_buserr();
-	panic("Bus error, epc == %08lx, ra == %08lx",
-	      regs->cp0_epc, regs->regs[31]);
+	printk(KERN_ALERT "%s bus error, epc == %0*lx, ra == %0*lx\n",
+	       (regs->cp0_cause & 4) ? "Data" : "Instruction",
+	       field, regs->cp0_epc, field, regs->regs[31]);
+	/* Assume it would be too dangerous to continue ... */
+	die_if_kernel("Oops", regs);
+	force_sig(SIGBUS, current);
 }
 
-int ip22_be_handler(struct pt_regs *regs, int is_fixup)
+static int ip22_be_handler(struct pt_regs *regs, int is_fixup)
 {
 	save_and_clear_buserr();
 	if (is_fixup)
--- diff/arch/mips/sgi-ip22/ip22-hpc.c	2003-07-08 09:55:17.000000000 +0100
+++ source/arch/mips/sgi-ip22/ip22-hpc.c	2004-02-23 13:56:38.000000000 +0000
@@ -6,16 +6,23 @@
  */
 
 #include <linux/init.h>
+#include <linux/module.h>
 #include <linux/types.h>
 
-#include <asm/addrspace.h>
+#include <asm/io.h>
 #include <asm/sgi/hpc3.h>
 #include <asm/sgi/ioc.h>
 #include <asm/sgi/ip22.h>
 
 struct hpc3_regs *hpc3c0, *hpc3c1;
+
+EXPORT_SYMBOL(hpc3c0);
+EXPORT_SYMBOL(hpc3c1);
+
 struct sgioc_regs *sgioc;
 
+EXPORT_SYMBOL(sgioc);
+
 /* We need software copies of these because they are write only. */
 u8 sgi_ioc_reset, sgi_ioc_write;
 
@@ -23,8 +30,11 @@ extern char *system_type;
 
 void __init sgihpc_init(void)
 {
-	hpc3c0 = (struct hpc3_regs *)(KSEG1 + HPC3_CHIP0_BASE);
-	hpc3c1 = (struct hpc3_regs *)(KSEG1 + HPC3_CHIP1_BASE);
+	/* ioremap can't fail */
+	hpc3c0 = (struct hpc3_regs *)
+		 ioremap(HPC3_CHIP0_BASE, sizeof(struct hpc3_regs));
+	hpc3c1 = (struct hpc3_regs *)
+		 ioremap(HPC3_CHIP1_BASE, sizeof(struct hpc3_regs));
 	/* IOC lives in PBUS PIO channel 6 */
 	sgioc = (struct sgioc_regs *)hpc3c0->pbus_extregs[6];
 
--- diff/arch/mips/sgi-ip22/ip22-int.c	2003-08-20 14:16:25.000000000 +0100
+++ source/arch/mips/sgi-ip22/ip22-int.c	2004-02-23 13:56:38.000000000 +0000
@@ -9,7 +9,7 @@
  *                    - Interrupt handling fixes
  * Copyright (C) 2001, 2003 Ladislav Michl (ladis@linux-mips.org)
  */
-
+#include <linux/config.h>
 #include <linux/types.h>
 #include <linux/init.h>
 #include <linux/kernel_stat.h>
--- diff/arch/mips/sgi-ip22/ip22-mc.c	2003-07-08 09:55:17.000000000 +0100
+++ source/arch/mips/sgi-ip22/ip22-mc.c	2004-02-23 13:56:38.000000000 +0000
@@ -7,11 +7,11 @@
  */
 
 #include <linux/init.h>
+#include <linux/module.h>
 #include <linux/kernel.h>
 
-#include <asm/addrspace.h>
+#include <asm/io.h>
 #include <asm/bootinfo.h>
-#include <asm/ptrace.h>
 #include <asm/sgialib.h>
 #include <asm/sgi/mc.h>
 #include <asm/sgi/hpc3.h>
@@ -19,6 +19,8 @@
 
 struct sgimc_regs *sgimc;
 
+EXPORT_SYMBOL(sgimc);
+
 static inline unsigned long get_bank_addr(unsigned int memconfig)
 {
 	return ((memconfig & SGIMC_MCONFIG_BASEADDR) <<
@@ -106,7 +108,9 @@ void __init sgimc_init(void)
 {
 	u32 tmp;
 
-	sgimc = (struct sgimc_regs *)(KSEG1 + SGIMC_BASE);
+	/* ioremap can't fail */
+	sgimc = (struct sgimc_regs *)
+		ioremap(SGIMC_BASE, sizeof(struct sgimc_regs));
 
 	printk(KERN_INFO "MC: SGI memory controller Revision %d\n",
 	       (int) sgimc->systemid & SGIMC_SYSID_MASKREV);
@@ -198,4 +202,7 @@ void __init sgimc_init(void)
 }
 
 void __init prom_meminit(void) {}
-void __init prom_free_prom_memory (void) {}
+unsigned long __init prom_free_prom_memory(void)
+{
+	return 0;
+}
--- diff/arch/mips/sgi-ip22/ip22-nvram.c	2003-07-08 09:55:17.000000000 +0100
+++ source/arch/mips/sgi-ip22/ip22-nvram.c	2004-02-23 13:56:38.000000000 +0000
@@ -3,6 +3,7 @@
  *
  * Copyright (C) 2003 Ladislav Michl (ladis@linux-mips.org)
  */
+#include <linux/module.h>
 
 #include <asm/sgi/hpc3.h>
 #include <asm/sgi/ip22.h>
@@ -95,6 +96,8 @@ unsigned short ip22_eeprom_read(volatile
 	return res;
 }
 
+EXPORT_SYMBOL(ip22_eeprom_read);
+
 /*
  * Read specified register from main NVRAM
  */
@@ -112,3 +115,5 @@ unsigned short ip22_nvram_read(int reg)
 		return (tmp << 8) | (hpc3c0->bbram[reg] & 0xff);
 	}		
 }
+
+EXPORT_SYMBOL(ip22_nvram_read);
--- diff/arch/mips/sgi-ip22/ip22-reset.c	2003-07-08 09:55:17.000000000 +0100
+++ source/arch/mips/sgi-ip22/ip22-reset.c	2004-02-23 13:56:38.000000000 +0000
@@ -6,6 +6,8 @@
  * Copyright (C) 1997, 1998, 2001, 2003 by Ralf Baechle
  */
 #include <linux/init.h>
+#include <linux/ds1286.h>
+#include <linux/module.h>
 #include <linux/interrupt.h>
 #include <linux/kernel.h>
 #include <linux/sched.h>
@@ -16,10 +18,10 @@
 #include <asm/irq.h>
 #include <asm/system.h>
 #include <asm/reboot.h>
-#include <asm/ds1286.h>
 #include <asm/sgialib.h>
 #include <asm/sgi/ioc.h>
 #include <asm/sgi/hpc3.h>
+#include <asm/sgi/mc.h>
 #include <asm/sgi/ip22.h>
 
 /*
@@ -45,12 +47,12 @@ static void sgi_machine_restart(char *co
 static void sgi_machine_halt(void) __attribute__((noreturn));
 static void sgi_machine_power_off(void) __attribute__((noreturn));
 
-/* XXX How to pass the reboot command to the firmware??? */
 static void sgi_machine_restart(char *command)
 {
 	if (machine_state & MACHINE_SHUTTING_DOWN)
 		sgi_machine_power_off();
-	ArcReboot();
+	sgimc->cpuctrl0 |= SGIMC_CCTRL0_SYSINIT;
+	while (1);
 }
 
 static void sgi_machine_halt(void)
@@ -62,23 +64,23 @@ static void sgi_machine_halt(void)
 
 static void sgi_machine_power_off(void)
 {
-	unsigned char val;
+	unsigned int tmp;
 
 	local_irq_disable();
 
 	/* Disable watchdog */
-	val = CMOS_READ(RTC_CMD);
-	CMOS_WRITE(val | RTC_WAM, RTC_CMD);
-	CMOS_WRITE(0, RTC_WSEC);
-	CMOS_WRITE(0, RTC_WHSEC);
+	tmp = hpc3c0->rtcregs[RTC_CMD] & 0xff;
+	hpc3c0->rtcregs[RTC_CMD] = tmp | RTC_WAM;
+	hpc3c0->rtcregs[RTC_WSEC] = 0;
+	hpc3c0->rtcregs[RTC_WHSEC] = 0;
 
-	while(1) {
+	while (1) {
 		sgioc->panel = ~SGIOC_PANEL_POWERON;
 		/* Good bye cruel world ...  */
 
 		/* If we're still running, we probably got sent an alarm
 		   interrupt.  Read the flag to clear it.  */
-		val = CMOS_READ(RTC_HOURS_ALARM);
+		tmp = hpc3c0->rtcregs[RTC_HOURS_ALARM];
 	}
 }
 
@@ -112,7 +114,7 @@ static void debounce(unsigned long data)
 	}
 
 	if (machine_state & MACHINE_PANICED)
-		ArcReboot();
+		sgimc->cpuctrl0 |= SGIMC_CCTRL0_SYSINIT;
 
 	enable_irq(SGI_PANEL_IRQ);
 }
@@ -139,6 +141,8 @@ static inline void power_button(void)
 
 void (*indy_volume_button)(int) = NULL;
 
+EXPORT_SYMBOL(indy_volume_button);
+
 static inline void volume_up_button(unsigned long data)
 {
 	del_timer(&volume_timer);
@@ -182,12 +186,10 @@ static irqreturn_t panel_int(int irq, vo
 	}
 
 	/* Power button was pressed 
-	 *
 	 * ioc.ps page 22: "The Panel Register is called Power Control by Full
 	 * House. Only lowest 2 bits are used. Guiness uses upper four bits
 	 * for volume control". This is not true, all bits are pulled high
-	 * on fullhouse
-	 */
+	 * on fullhouse */
 	if (ip22_is_fullhouse() || !(buttons & SGIOC_PANEL_POWERINTR)) {
 		power_button();
 		return IRQ_HANDLED;
--- diff/arch/mips/sgi-ip22/ip22-setup.c	2003-08-20 14:16:25.000000000 +0100
+++ source/arch/mips/sgi-ip22/ip22-setup.c	2004-02-23 13:56:38.000000000 +0000
@@ -5,6 +5,7 @@
  * Copyright (C) 1997, 1998 Ralf Baechle (ralf@gnu.org)
  */
 #include <linux/config.h>
+#include <linux/ds1286.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/kdev_t.h>
@@ -18,7 +19,6 @@
 #include <asm/bootinfo.h>
 #include <asm/irq.h>
 #include <asm/reboot.h>
-#include <asm/ds1286.h>
 #include <asm/time.h>
 #include <asm/gdb-stub.h>
 #include <asm/io.h>
@@ -34,12 +34,6 @@ extern void breakpoint(void);
 static int remote_debug = 0;
 #endif
 
-#if defined(CONFIG_IP22_SERIAL_CONSOLE) || defined(CONFIG_ARC_CONSOLE)
-extern void console_setup(char *);
-#endif
-
-extern struct rtc_ops ip22_rtc_ops;
-
 unsigned long sgi_gfxaddr;
 
 /*
@@ -63,7 +57,7 @@ void ip22_do_break(void)
 extern void ip22_be_init(void) __init;
 extern void ip22_time_init(void) __init;
 
-void __init ip22_setup(void)
+static int __init ip22_setup(void)
 {
 	char *ctype;
 #ifdef CONFIG_KGDB
@@ -87,8 +81,8 @@ void __init ip22_setup(void)
 	indy_sc_init();
 #endif
 
-	/* Set the IO space to some sane value */
-	set_io_port_base (KSEG1ADDR (0x00080000));
+	/* Set EISA IO port base for Indigo2 */
+	set_io_port_base(KSEG1ADDR(0x00080000));
 
 	/* ARCS console environment variable is set to "g?" for
 	 * graphics console, it is set to "d" for the first serial
@@ -96,20 +90,17 @@ void __init ip22_setup(void)
 	 */
 	ctype = ArcGetEnvironmentVariable("console");
 	if (ctype && *ctype == 'd') {
-#ifdef CONFIG_IP22_SERIAL_CONSOLE
-		if (*(ctype + 1) == '2')
-			console_setup("ttyS1");
-		else
-			console_setup("ttyS0");
-#endif
-	}
-#ifdef CONFIG_ARC_CONSOLE
-	else if (!ctype || *ctype != 'g') {
+		static char options[8];
+		char *baud = ArcGetEnvironmentVariable("dbaud");
+		if (baud)
+			strcpy(options, baud);
+		add_preferred_console("ttyS", *(ctype + 1) == '2' ? 1 : 0,
+				      baud ? options : NULL);
+	} else if (!ctype || *ctype != 'g') {
 		/* Use ARC if we don't want serial ('d') or Newport ('g'). */
 		prom_flags |= PROM_FLAG_USE_AS_CONSOLE;
-		console_setup("arc");
+		add_preferred_console("arc", 0, NULL);
 	}
-#endif
 
 #ifdef CONFIG_KGDB
 	kgdb_ttyd = prom_getcmdline();
@@ -133,14 +124,13 @@ void __init ip22_setup(void)
 #endif
 
 #ifdef CONFIG_VT
-	conswitchp = &dummy_con;
 #ifdef CONFIG_SGI_NEWPORT_CONSOLE
 	if (ctype && *ctype == 'g'){
-		unsigned long *gfxinfo;
-		long (*__vec)(void) =
-			(void *) *(long *)((PROMBLOCK)->pvector + 0x20);
+		ULONG *gfxinfo;
+		ULONG * (*__vec)(void) = (void *) (long)
+			*((_PULONG *)(long)((PROMBLOCK)->pvector + 0x20));
 
-		gfxinfo = (unsigned long *)__vec();
+		gfxinfo = __vec();
 		sgi_gfxaddr = ((gfxinfo[1] >= 0xa0000000
 			       && gfxinfo[1] <= 0xc0000000)
 			       ? gfxinfo[1] - 0xa0000000 : 0);
@@ -148,21 +138,12 @@ void __init ip22_setup(void)
 		/* newport addresses? */
 		if (sgi_gfxaddr == 0x1f0f0000 || sgi_gfxaddr == 0x1f4f0000) {
 			conswitchp = &newport_con;
-
-			screen_info = (struct screen_info) {
-				.orig_x			= 0,
-				.orig_y 		= 0,
-				.orig_video_page	= 0,
-				.orig_video_mode	= 0,
-				.orig_video_cols	= 160,
-				.orig_video_ega_bx	= 0,
-				.orig_video_lines	= 64,
-				.orig_video_isVGA	= 0,
-				.orig_video_points	= 16,
-			};
 		}
 	}
 #endif
 #endif
-	rtc_ops = &ip22_rtc_ops;
+
+	return 0;
 }
+
+early_initcall(ip22_setup);
--- diff/arch/mips/sgi-ip22/ip22-time.c	2003-08-20 14:16:25.000000000 +0100
+++ source/arch/mips/sgi-ip22/ip22-time.c	2004-02-23 13:56:38.000000000 +0000
@@ -7,9 +7,10 @@
  * Ralf Baechle or David S. Miller (sorry guys, i'm really not sure)
  *
  * Copyright (C) 2001 by Ladislav Michl
+ * Copyright (C) 2003 Ralf Baechle (ralf@linux-mips.org)
  */
-
 #include <linux/bcd.h>
+#include <linux/ds1286.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/interrupt.h>
@@ -21,7 +22,6 @@
 #include <asm/io.h>
 #include <asm/irq.h>
 #include <asm/time.h>
-#include <asm/ds1286.h>
 #include <asm/sgialib.h>
 #include <asm/sgi/ioc.h>
 #include <asm/sgi/hpc3.h>
@@ -41,7 +41,7 @@ static unsigned long indy_rtc_get_time(v
 
 	sec = BCD2BIN(hpc3c0->rtcregs[RTC_SECONDS] & 0xff);
 	min = BCD2BIN(hpc3c0->rtcregs[RTC_MINUTES] & 0xff);
-	hrs = BCD2BIN(hpc3c0->rtcregs[RTC_HOURS] & 0x1f);
+	hrs = BCD2BIN(hpc3c0->rtcregs[RTC_HOURS] & 0x3f);
 	day = BCD2BIN(hpc3c0->rtcregs[RTC_DATE] & 0xff);
 	mon = BCD2BIN(hpc3c0->rtcregs[RTC_MONTH] & 0x1f);
 	yrs = BCD2BIN(hpc3c0->rtcregs[RTC_YEAR] & 0xff);
@@ -114,7 +114,7 @@ static unsigned long dosample(void)
 	 * for every 1/HZ seconds. We round off the nearest 1 MHz of master
 	 * clock (= 1000000 / HZ / 2).
 	 */
-	//return (ct1 - ct0 + (500000/HZ/2)) / (500000/HZ) * (500000/HZ);
+	/*return (ct1 - ct0 + (500000/HZ/2)) / (500000/HZ) * (500000/HZ);*/
 	return (ct1 - ct0) / (500000/HZ) * (500000/HZ);
 }
 
@@ -164,7 +164,7 @@ static __init void indy_time_init(void)
 		(int) (r4k_tick / (500000 / HZ)),
 		(int) (r4k_tick % (500000 / HZ)));
 
-	mips_counter_frequency = r4k_tick * HZ;
+	mips_hpt_frequency = r4k_tick * HZ;
 }
 
 /* Generic SGI handler for (spurious) 8254 interrupts */
--- diff/arch/mips/sgi-ip27/Makefile	2003-07-08 09:55:17.000000000 +0100
+++ source/arch/mips/sgi-ip27/Makefile	2004-02-23 13:56:38.000000000 +0000
@@ -6,4 +6,6 @@ obj-y	:= ip27-berr.o ip27-console.o ip27
 	   ip27-klconfig.o ip27-klnuma.o ip27-memory.o ip27-nmi.o ip27-reset.o \
 	   ip27-setup.o ip27-timer.o
 
+obj-$(CONFIG_SMP)	+= ip27-smp.o
+
 EXTRA_AFLAGS := $(CFLAGS)
--- diff/arch/mips/sgi-ip27/ip27-console.c	2003-07-08 09:55:17.000000000 +0100
+++ source/arch/mips/sgi-ip27/ip27-console.c	2004-02-23 13:56:38.000000000 +0000
@@ -9,16 +9,23 @@
 #include <linux/console.h>
 #include <linux/kdev_t.h>
 #include <linux/major.h>
-#include <linux/serial.h>
+#include <linux/termios.h>
+#include <linux/sched.h>
+#include <linux/tty.h>
+
 #include <asm/page.h>
+#include <asm/semaphore.h>
 #include <asm/sn/addrs.h>
 #include <asm/sn/sn0/hub.h>
 #include <asm/sn/klconfig.h>
 #include <asm/sn/ioc3.h>
 #include <asm/sn/sn_private.h>
 
-#define IOC3_BAUD (22000000 / (3*16))
-#define IOC3_COM_FLAGS (ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST)
+#include <linux/serial.h>
+#include <linux/serial_core.h>
+
+#define IOC3_CLK	(22000000 / 3)
+#define IOC3_FLAGS	(0)
 
 static inline struct ioc3_uartregs *console_uart(void)
 {
@@ -44,19 +51,23 @@ char __init prom_getchar(void)
 
 static void inline ioc3_console_probe(void)
 {
-	struct serial_struct req;
+	struct uart_port up;
 
-	/* Register to interrupt zero because we share the interrupt with
-	   the serial driver which we don't properly support yet.  */
-	memset(&req, 0, sizeof(req));
-	req.irq             = 0;
-	req.flags           = IOC3_COM_FLAGS;
-	req.io_type         = SERIAL_IO_MEM;
-	req.iomem_reg_shift = 0;
-	req.baud_base       = IOC3_BAUD;
+	/*
+	 * Register to interrupt zero because we share the interrupt with
+	 * the serial driver which we don't properly support yet.
+	 */
+	memset(&up, 0, sizeof(up));
+	up.membase	= (unsigned char *) console_uart();
+	up.irq		= 0;
+	up.uartclk	= IOC3_CLK;
+	up.regshift	= 0;
+	up.iotype	= UPIO_MEM;
+	up.flags	= IOC3_FLAGS;
+	up.line		= 0;
 
-	req.iomem_base      = (unsigned char *) console_uart();
-	register_serial(&req);
+	if (early_serial_setup(&up))
+		printk(KERN_ERR "Early serial init of port 0 failed\n");
 }
 
 __init void ip27_setup_console(void)
--- diff/arch/mips/sgi-ip27/ip27-init.c	2003-08-26 10:00:52.000000000 +0100
+++ source/arch/mips/sgi-ip27/ip27-init.c	2004-02-23 13:56:38.000000000 +0000
@@ -6,13 +6,13 @@
  * Copyright (C) 2000 - 2001 by Kanoj Sarcar (kanoj@sgi.com)
  * Copyright (C) 2000 - 2001 by Silicon Graphics, Inc.
  */
-
 #include <linux/config.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/sched.h>
 #include <linux/mmzone.h>	/* for numnodes */
 #include <linux/mm.h>
+#include <linux/cpumask.h>
 #include <asm/cpu.h>
 #include <asm/pgalloc.h>
 #include <asm/pgtable.h>
@@ -34,25 +34,12 @@
 #include <asm/sn/sn_private.h>
 #include <asm/sn/sn0/ip27.h>
 #include <asm/sn/mapped_kernel.h>
-#include <asm/sn/sn0/addrs.h>
-#include <asm/sn/gda.h>
 
 #define CPU_NONE		(cpuid_t)-1
 
-/*
- * The following should work till 64 nodes, ie 128p SN0s.
- */
-#define CNODEMASK_CLRALL(p)	(p) = 0
-#define CNODEMASK_TSTB(p, bit)	((p) & (1ULL << (bit)))
-#define CNODEMASK_SETB(p, bit)	((p) |= 1ULL << (bit))
-
-cpumask_t	boot_cpumask;
-hubreg_t	region_mask;
+static DECLARE_BITMAP(hub_init_mask, MAX_COMPACT_NODES);
+static hubreg_t region_mask;
 static int	fine_mode;
-int		maxcpus;
-static spinlock_t hub_mask_lock = SPIN_LOCK_UNLOCKED;
-static cnodemask_t hub_init_mask;
-static atomic_t numstarted = ATOMIC_INIT(1);
 static int router_distance;
 nasid_t master_nasid = INVALID_NASID;
 
@@ -61,7 +48,7 @@ nasid_t		compact_to_nasid_node[MAX_COMPA
 cnodeid_t	cpuid_to_compact_node[MAXCPUS];
 char		node_distances[MAX_COMPACT_NODES][MAX_COMPACT_NODES];
 
-hubreg_t get_region(cnodeid_t cnode)
+static hubreg_t get_region(cnodeid_t cnode)
 {
 	if (fine_mode)
 		return COMPACT_TO_NASID_NODEID(cnode) >> NASID_TO_FINEREG_SHFT;
@@ -79,312 +66,47 @@ static void gen_region_mask(hubreg_t *re
 	}
 }
 
-int is_fine_dirmode(void)
+static int is_fine_dirmode(void)
 {
 	return (((LOCAL_HUB_L(NI_STATUS_REV_ID) & NSRI_REGIONSIZE_MASK)
 		>> NSRI_REGIONSIZE_SHFT) & REGIONSIZE_FINE);
 }
 
-nasid_t get_actual_nasid(lboard_t *brd)
-{
-	klhub_t *hub;
-
-	if (!brd)
-		return INVALID_NASID;
-
-	/* find out if we are a completely disabled brd. */
-	hub  = (klhub_t *)find_first_component(brd, KLSTRUCT_HUB);
-	if (!hub)
-		return INVALID_NASID;
-	if (!(hub->hub_info.flags & KLINFO_ENABLE))	/* disabled node brd */
-		return hub->hub_info.physid;
-	else
-		return brd->brd_nasid;
-}
-
-/* Tweak this for maximum number of CPUs to activate */
-static int max_cpus = NR_CPUS;
-
-int do_cpumask(cnodeid_t cnode, nasid_t nasid, cpumask_t *boot_cpumask,
-							int *highest)
-{
-	static int tot_cpus_found = 0;
-	lboard_t *brd;
-	klcpu_t *acpu;
-	int cpus_found = 0;
-	cpuid_t cpuid;
-
-	brd = find_lboard((lboard_t *)KL_CONFIG_INFO(nasid), KLTYPE_IP27);
-
-	do {
-		acpu = (klcpu_t *)find_first_component(brd, KLSTRUCT_CPU);
-		while (acpu) {
-			cpuid = acpu->cpu_info.virtid;
-			/* cnode is not valid for completely disabled brds */
-			if (get_actual_nasid(brd) == brd->brd_nasid)
-				cpuid_to_compact_node[cpuid] = cnode;
-			if (cpuid > *highest)
-				*highest = cpuid;
-			/* Only let it join in if it's marked enabled */
-			if ((acpu->cpu_info.flags & KLINFO_ENABLE) &&
-						(tot_cpus_found != max_cpus)) {
-				CPUMASK_SETB(*boot_cpumask, cpuid);
-				cpus_found++;
-				tot_cpus_found++;
-			}
-			acpu = (klcpu_t *)find_component(brd, (klinfo_t *)acpu,
-								KLSTRUCT_CPU);
-		}
-		brd = KLCF_NEXT(brd);
-		if (brd)
-			brd = find_lboard(brd,KLTYPE_IP27);
-		else
-			break;
-	} while (brd);
-
-	return cpus_found;
-}
-
-cpuid_t cpu_node_probe(cpumask_t *boot_cpumask, int *numnodes)
-{
-	int i, cpus = 0, highest = 0;
-	gda_t *gdap = GDA;
-	nasid_t nasid;
-
-	/*
-	 * Initialize the arrays to invalid nodeid (-1)
-	 */
-	for (i = 0; i < MAX_COMPACT_NODES; i++)
-		compact_to_nasid_node[i] = INVALID_NASID;
-	for (i = 0; i < MAX_NASIDS; i++)
-		nasid_to_compact_node[i] = INVALID_CNODEID;
-	for (i = 0; i < MAXCPUS; i++)
-		cpuid_to_compact_node[i] = INVALID_CNODEID;
-
-	*numnodes = 0;
-	for (i = 0; i < MAX_COMPACT_NODES; i++) {
-		if ((nasid = gdap->g_nasidtable[i]) == INVALID_NASID) {
-			break;
-		} else {
-			compact_to_nasid_node[i] = nasid;
-			nasid_to_compact_node[nasid] = i;
-			(*numnodes)++;
-			cpus += do_cpumask(i, nasid, boot_cpumask, &highest);
-		}
-	}
-
-	/*
-	 * Cpus are numbered in order of cnodes. Currently, disabled
-	 * cpus are not numbered.
-	 */
-
-	return highest + 1;
-}
-
-int cpu_enabled(cpuid_t cpu)
+extern void pcibr_setup(cnodeid_t);
+void per_hub_init(cnodeid_t cnode)
 {
-	if (cpu == CPU_NONE)
-		return 0;
-	return CPUMASK_TSTB(boot_cpumask, cpu) != 0;
-}
+	nasid_t		nasid = COMPACT_TO_NASID_NODEID(cnode);
 
-void mlreset(void)
-{
-	int i;
-	void init_topology_matrix(void);
-	void dump_topology(void);
-
-
-	master_nasid = get_nasid();
-	fine_mode = is_fine_dirmode();
+	if (test_and_set_bit(cnode, hub_init_mask))
+		return;
 
 	/*
-	 * Probe for all CPUs - this creates the cpumask and
-	 * sets up the mapping tables.
+	 * Set CRB timeout at 5ms, (< PI timeout of 10ms)
 	 */
-	CPUMASK_CLRALL(boot_cpumask);
-	maxcpus = cpu_node_probe(&boot_cpumask, &numnodes);
-	printk("Discovered %d cpus on %d nodes\n", maxcpus, numnodes);
+	REMOTE_HUB_S(nasid, IIO_ICTP, 0x800);
+	REMOTE_HUB_S(nasid, IIO_ICTO, 0xff);
 
-	init_topology_matrix();
-	dump_topology();
-
-	gen_region_mask(&region_mask, numnodes);
-	CNODEMASK_CLRALL(hub_init_mask);
-
-	setup_replication_mask(numnodes);
+	hub_rtc_init(cnode);
+	pcibr_setup(cnode);
 
+#ifdef CONFIG_REPLICATE_EXHANDLERS
 	/*
-	 * Set all nodes' calias sizes to 8k
+	 * If this is not a headless node initialization,
+	 * copy over the caliased exception handlers.
 	 */
-	for (i = 0; i < numnodes; i++) {
-		nasid_t nasid;
-
-		nasid = COMPACT_TO_NASID_NODEID(i);
-
-		/*
-		 * Always have node 0 in the region mask, otherwise
-		 * CALIAS accesses get exceptions since the hub
-		 * thinks it is a node 0 address.
-		 */
-		REMOTE_HUB_S(nasid, PI_REGION_PRESENT, (region_mask | 1));
-#ifdef CONFIG_REPLICATE_EXHANDLERS
-		REMOTE_HUB_S(nasid, PI_CALIAS_SIZE, PI_CALIAS_SIZE_8K);
-#else
-		REMOTE_HUB_S(nasid, PI_CALIAS_SIZE, PI_CALIAS_SIZE_0);
-#endif
-
-#ifdef LATER
-		/*
-		 * Set up all hubs to have a big window pointing at
-		 * widget 0. Memory mode, widget 0, offset 0
-		 */
-		REMOTE_HUB_S(nasid, IIO_ITTE(SWIN0_BIGWIN),
-			((HUB_PIO_MAP_TO_MEM << IIO_ITTE_IOSP_SHIFT) |
-			(0 << IIO_ITTE_WIDGET_SHIFT)));
-#endif
-	}
-}
-
-
-void intr_clear_bits(nasid_t nasid, volatile hubreg_t *pend, int base_level,
-							char *name)
-{
-	volatile hubreg_t bits;
-	int i;
-
-	/* Check pending interrupts */
-	if ((bits = HUB_L(pend)) != 0)
-		for (i = 0; i < N_INTPEND_BITS; i++)
-			if (bits & (1 << i))
-				LOCAL_HUB_CLR_INTR(base_level + i);
-}
-
-void intr_clear_all(nasid_t nasid)
-{
-	REMOTE_HUB_S(nasid, PI_INT_MASK0_A, 0);
-	REMOTE_HUB_S(nasid, PI_INT_MASK0_B, 0);
-	REMOTE_HUB_S(nasid, PI_INT_MASK1_A, 0);
-	REMOTE_HUB_S(nasid, PI_INT_MASK1_B, 0);
-	intr_clear_bits(nasid, REMOTE_HUB_ADDR(nasid, PI_INT_PEND0),
-		INT_PEND0_BASELVL, "INT_PEND0");
-	intr_clear_bits(nasid, REMOTE_HUB_ADDR(nasid, PI_INT_PEND1),
-		INT_PEND1_BASELVL, "INT_PEND1");
-}
-
-void sn_mp_setup(void)
-{
-	cnodeid_t	cnode;
-#if 0
-	cpuid_t		cpu;
-#endif
-
-	for (cnode = 0; cnode < numnodes; cnode++) {
-#if 0
-		init_platform_nodepda();
-#endif
-		intr_clear_all(COMPACT_TO_NASID_NODEID(cnode));
+	if (get_compact_nodeid() == cnode) {
+		extern char except_vec0, except_vec1_r10k;
+		extern char except_vec2_generic, except_vec3_generic;
+
+		memcpy((void *)(KSEG0 + 0x100), &except_vec2_generic, 0x80);
+		memcpy((void *)(KSEG0 + 0x180), &except_vec3_generic, 0x80);
+		memcpy((void *)KSEG0, &except_vec0, 0x80);
+		memcpy((void *)KSEG0 + 0x080, &except_vec1_r10k, 0x80);
+		memcpy((void *)(KSEG0 + 0x100), (void *) KSEG0, 0x80);
+		memcpy((void *)(KSEG0 + 0x180), &except_vec3_generic, 0x100);
+		__flush_cache_all();
 	}
-#if 0
-	for (cpu = 0; cpu < maxcpus; cpu++) {
-		init_platform_pda();
-	}
-#endif
-}
-
-void per_hub_init(cnodeid_t cnode)
-{
-	extern void pcibr_setup(cnodeid_t);
-	cnodemask_t	done;
-	nasid_t		nasid;
-
-	nasid = COMPACT_TO_NASID_NODEID(cnode);
-
-	spin_lock(&hub_mask_lock);
-	/* Test our bit. */
-	if (!(done = CNODEMASK_TSTB(hub_init_mask, cnode))) {
-		/* Turn our bit on in the mask. */
-		CNODEMASK_SETB(hub_init_mask, cnode);
-		/*
-	 	 * Do the actual initialization if it hasn't been done yet.
-	 	 * We don't need to hold a lock for this work.
-	 	 */
-		/*
-		 * Set CRB timeout at 5ms, (< PI timeout of 10ms)
-		 */
-		REMOTE_HUB_S(nasid, IIO_ICTP, 0x800);
-		REMOTE_HUB_S(nasid, IIO_ICTO, 0xff);
-		hub_rtc_init(cnode);
-		pcibr_setup(cnode);
-#ifdef CONFIG_REPLICATE_EXHANDLERS
-		/*
-		 * If this is not a headless node initialization,
-		 * copy over the caliased exception handlers.
-		 */
-		if (get_compact_nodeid() == cnode) {
-			extern char except_vec0, except_vec1_r10k;
-			extern char except_vec2_generic, except_vec3_generic;
-
-			memcpy((void *)(KSEG0 + 0x100), &except_vec2_generic,
-								0x80);
-			memcpy((void *)(KSEG0 + 0x180), &except_vec3_generic,
-								0x80);
-			memcpy((void *)KSEG0, &except_vec0, 0x80);
-			memcpy((void *)KSEG0 + 0x080, &except_vec1_r10k, 0x80);
-			memcpy((void *)(KSEG0 + 0x100), (void *) KSEG0, 0x80);
-			memcpy((void *)(KSEG0 + 0x180), &except_vec3_generic,
-								0x100);
-			__flush_cache_all();
-		}
-#endif
-	}
-	spin_unlock(&hub_mask_lock);
-}
-
-/*
- * This is similar to hard_smp_processor_id().
- */
-cpuid_t getcpuid(void)
-{
-	klcpu_t *klcpu;
-
-	klcpu = nasid_slice_to_cpuinfo(get_nasid(),LOCAL_HUB_L(PI_CPU_NUM));
-	return klcpu->cpu_info.virtid;
-}
-
-void per_cpu_init(void)
-{
-	extern void install_cpu_nmi_handler(int slice);
-	extern void load_mmu(void);
-	static int is_slave = 0;
-	int cpu = smp_processor_id();
-	cnodeid_t cnode = get_compact_nodeid();
-
-#if 0
-	intr_init();
-#endif
-	clear_c0_status(ST0_IM);
-	per_hub_init(cnode);
-	cpu_time_init();
-	if (smp_processor_id())	/* master can't do this early, no kmalloc */
-		install_cpuintr(cpu);
-	/* Install our NMI handler if symmon hasn't installed one. */
-	install_cpu_nmi_handler(cputoslice(cpu));
-#if 0
-	install_tlbintr(cpu);
 #endif
-	set_c0_status(SRB_DEV0 | SRB_DEV1);
-	if (is_slave) {
-		clear_c0_status(ST0_BEV);
-		if (current_cpu_data.isa_level == MIPS_CPU_ISA_IV)
-			set_c0_status(ST0_XX);
-		set_c0_status(ST0_KX|ST0_SX|ST0_UX);
-		local_irq_enable();
-		load_mmu();
-		atomic_inc(&numstarted);
-	} else {
-		is_slave = 1;
-	}
 }
 
 cnodeid_t get_compact_nodeid(void)
@@ -399,154 +121,9 @@ cnodeid_t get_compact_nodeid(void)
 	return NASID_TO_COMPACT_NODEID(nasid);
 }
 
-#ifdef CONFIG_SMP
-
-/*
- * Takes as first input the PROM assigned cpu id, and the kernel
- * assigned cpu id as the second.
- */
-static void alloc_cpupda(cpuid_t cpu, int cpunum)
-{
-	cnodeid_t	node;
-	nasid_t		nasid;
-
-	node = get_cpu_cnode(cpu);
-	nasid = COMPACT_TO_NASID_NODEID(node);
-
-	cputonasid(cpunum) = nasid;
-	cputocnode(cpunum) = node;
-	cputoslice(cpunum) = get_cpu_slice(cpu);
-	cpu_data[cpunum].p_cpuid = cpu;
-}
-
-static struct task_struct * __init fork_by_hand(void)
-{
-	struct pt_regs regs;
-	/*
-	 * don't care about the eip and regs settings since
-	 * we'll never reschedule the forked task.
-	 */
-	return copy_process(CLONE_VM|CLONE_IDLETASK, 0, &regs, 0, NULL, NULL);
-}
-
-static int __init do_boot_cpu(int cpu, int num_cpus)
-{
-	extern void smp_bootstrap(void);
-	cpuid_t mycpuid = getcpuid();
-	struct task_struct *idle;
-
-	if (cpu == mycpuid) {
-		alloc_cpupda(cpu, num_cpus);
-		return 1;
-	}
-
-	/* Skip holes in CPU space */
-	if (!CPUMASK_TSTB(boot_cpumask, cpu))
-		return 0;
-
-	/*
-	 * The following code is purely to make sure
-	 * Linux can schedule processes on this slave.
-	 */
-	idle = fork_by_hand();
-	if (IS_ERR(idle))
-		panic("failed fork for CPU %d", cpu);
-
-	/*
-	 * We remove it from the pidhash and the runqueue
-	 * once we got the process:
-	 */
-	init_idle(idle, cpu);
-
-	alloc_cpupda(cpu, num_cpus);
-
-	unhash_process(idle);
-
-	/*
- 	 * Launch a slave into smp_bootstrap().  It doesn't take an
-	 * argument, and we set sp to the kernel stack of the newly
-	 * created idle process, gp to the proc struct so that
-	 * current_thread_info() will work.
- 	 */
-	LAUNCH_SLAVE(cputonasid(num_cpus),cputoslice(num_cpus),
-		(launch_proc_t)MAPPED_KERN_RW_TO_K0(smp_bootstrap),
-		0, (void *)((unsigned long)idle->thread_info +
-		THREAD_SIZE - 32), (void *)idle);
-
-	/*
-	 * Now optimistically set the mapping arrays. We
-	 * need to wait here, verify the cpu booted up, then
-	 * fire up the next cpu.
-	 */
-	__cpu_number_map[cpu] = num_cpus;
-	__cpu_logical_map[num_cpus] = cpu;
-	cpu_set(cpu, cpu_online_map);
-
-	/*
-	 * Wait this cpu to start up and initialize its hub,
-	 * and discover the io devices it will control.
-	 *
-	 * XXX: We really want to fire up launch all the CPUs
-	 * at once.  We have to preserve the order of the
-	 * devices on the bridges first though.
-	 */
-	while (atomic_read(&numstarted) != num_cpus);
-
-	return 1;
-}
-
-void __init smp_boot_cpus(void)
-{
-	int		num_cpus = 0;
-	cpuid_t		cpu;
-	cnodeid_t	cnode;
-
-	init_new_context(current, &init_mm);
-	current_thread_info()->cpu = 0;
-	smp_tune_scheduling();
-
-	sn_mp_setup();
-	/* Master has already done per_cpu_init() */
-	install_cpuintr(smp_processor_id());
-#if 0
-	bte_lateinit();
-	ecc_init();
-#endif
-
-	replicate_kernel_text(numnodes);
-	/* Launch slaves. */
-	for (cpu = 0; cpu < maxcpus; cpu++) {
-		num_cpus += do_boot_cpu(cpu, num_cpus);
-	}
-
-#ifdef LATER
-	Wait logic goes here.
-#endif
-	for (cnode = 0; cnode < numnodes; cnode++) {
-#if 0
-		if (cnodetocpu(cnode) == -1) {
-			printk("Initializing headless hub,cnode %d", cnode);
-			per_hub_init(cnode);
-		}
-#endif
-	}
-#if 0
-	cpu_io_setup();
-	init_mfhi_war();
-#endif
-}
-
-#else /* CONFIG_SMP */
-void __init start_secondary(void)
-{
-	/* XXX Why do we need this empty definition at all?  */
-}
-#endif /* CONFIG_SMP */
-
-
 #define	rou_rflag	rou_flags
 
-void router_recurse(klrou_t *router_a, klrou_t *router_b, int depth)
+static void router_recurse(klrou_t *router_a, klrou_t *router_b, int depth)
 {
 	klrou_t *router;
 	lboard_t *brd;
@@ -582,13 +159,13 @@ void router_recurse(klrou_t *router_a, k
 	router_a->rou_rflag = 0;
 }
 
-int node_distance(nasid_t nasid_a, nasid_t nasid_b)
+static int node_distance(nasid_t nasid_a, nasid_t nasid_b)
 {
-	nasid_t nasid;
-	cnodeid_t cnode;
+	klrou_t *router, *router_a = NULL, *router_b = NULL;
 	lboard_t *brd, *dest_brd;
+	cnodeid_t cnode;
+	nasid_t nasid;
 	int port;
-	klrou_t *router, *router_a = NULL, *router_b = NULL;
 
 	/* Figure out which routers nodes in question are connected to */
 	for (cnode = 0; cnode < numnodes; cnode++) {
@@ -625,7 +202,7 @@ int node_distance(nasid_t nasid_a, nasid
 				}
 			}
 
-		} while ( (brd = find_lboard_class(KLCF_NEXT(brd), KLTYPE_ROUTER)) );
+		} while ((brd = find_lboard_class(KLCF_NEXT(brd), KLTYPE_ROUTER)));
 	}
 
 	if (router_a == NULL) {
@@ -649,7 +226,7 @@ int node_distance(nasid_t nasid_a, nasid
 	return router_distance;
 }
 
-void init_topology_matrix(void)
+static void init_topology_matrix(void)
 {
 	nasid_t nasid, nasid2;
 	cnodeid_t row, col;
@@ -667,7 +244,7 @@ void init_topology_matrix(void)
 	}
 }
 
-void dump_topology(void)
+static void dump_topology(void)
 {
 	nasid_t nasid;
 	cnodeid_t cnode;
@@ -728,93 +305,56 @@ void dump_topology(void)
 	}
 }
 
-#if 0
-#define		brd_widgetnum	brd_slot
-#define NODE_OFFSET_TO_KLINFO(n,off)    ((klinfo_t*) TO_NODE_CAC(n,off))
-void
-dump_klcfg(void)
+void mlreset(void)
 {
-	cnodeid_t       cnode;
 	int i;
-	nasid_t         nasid;
-	lboard_t        *lbptr;
-	gda_t           *gdap;
-
-	gdap = (gda_t *)GDA_ADDR(get_nasid());
-	if (gdap->g_magic != GDA_MAGIC) {
-		printk("dumpklcfg_cmd: Invalid GDA MAGIC\n");
-		return;
-	}
 
-	for (cnode = 0; cnode < MAX_COMPACT_NODES; cnode ++) {
-		nasid = gdap->g_nasidtable[cnode];
+	master_nasid = get_nasid();
+	fine_mode = is_fine_dirmode();
 
-		if (nasid == INVALID_NASID)
-			continue;
+	/*
+	 * Probe for all CPUs - this creates the cpumask and sets up the
+	 * mapping tables.  We need to do this as early as possible.
+	 */
+#ifdef CONFIG_SMP
+	cpu_node_probe();
+#endif
 
-		printk("\nDumpping klconfig Nasid %d:\n", nasid);
+	init_topology_matrix();
+	dump_topology();
 
-		lbptr = KL_CONFIG_INFO(nasid);
+	gen_region_mask(&region_mask, numnodes);
 
-		while (lbptr) {
-			printk("    %s, Nasid %d, Module %d, widget 0x%x, partition %d, NIC 0x%x lboard 0x%lx",
-				"board name here", /* BOARD_NAME(lbptr->brd_type), */
-				lbptr->brd_nasid, lbptr->brd_module,
-				lbptr->brd_widgetnum,
-				lbptr->brd_partition,
-				(lbptr->brd_nic), lbptr);
-			if (lbptr->brd_flags & DUPLICATE_BOARD)
-				printk(" -D");
-			printk("\n");
-			for (i = 0; i < lbptr->brd_numcompts; i++) {
-				klinfo_t *kli;
-				kli = NODE_OFFSET_TO_KLINFO(NASID_GET(lbptr), lbptr->brd_compts[i]);
-				printk("        type %2d, flags 0x%04x, diagval %3d, physid %4d, virtid %2d: %s\n",
-					kli->struct_type,
-					kli->flags,
-					kli->diagval,
-					kli->physid,
-					kli->virtid,
-					"comp. name here");
-					/* COMPONENT_NAME(kli->struct_type)); */
-			}
-			lbptr = KLCF_NEXT(lbptr);
-		}
-	}
-	printk("\n");
+	setup_replication_mask(numnodes);
+
+	/*
+	 * Set all nodes' calias sizes to 8k
+	 */
+	for (i = 0; i < numnodes; i++) {
+		nasid_t nasid;
 
-	/* Useful to print router maps also */
+		nasid = COMPACT_TO_NASID_NODEID(i);
 
-	for (cnode = 0; cnode < MAX_COMPACT_NODES; cnode ++) {
-		klrou_t *kr;
-		int i;
-
-        	nasid = gdap->g_nasidtable[cnode];
-        	if (nasid == INVALID_NASID)
-            		continue;
-        	lbptr = KL_CONFIG_INFO(nasid);
-
-        	while (lbptr) {
-
-			lbptr = find_lboard_class(lbptr, KLCLASS_ROUTER);
-			if(!lbptr)
-				break;
-			if (!KL_CONFIG_DUPLICATE_BOARD(lbptr)) {
-				printk("%llx -> \n", lbptr->brd_nic);
-				kr = (klrou_t *)find_first_component(lbptr,
-					KLSTRUCT_ROU);
-				for (i = 1; i <= MAX_ROUTER_PORTS; i++) {
-					printk("[%d, %llx]; ",
-						kr->rou_port[i].port_nasid,
-						kr->rou_port[i].port_offset);
-				}
-				printk("\n");
-			}
-			lbptr = KLCF_NEXT(lbptr);
-        	}
-        	printk("\n");
-    	}
+		/*
+		 * Always have node 0 in the region mask, otherwise
+		 * CALIAS accesses get exceptions since the hub
+		 * thinks it is a node 0 address.
+		 */
+		REMOTE_HUB_S(nasid, PI_REGION_PRESENT, (region_mask | 1));
+#ifdef CONFIG_REPLICATE_EXHANDLERS
+		REMOTE_HUB_S(nasid, PI_CALIAS_SIZE, PI_CALIAS_SIZE_8K);
+#else
+		REMOTE_HUB_S(nasid, PI_CALIAS_SIZE, PI_CALIAS_SIZE_0);
+#endif
 
-	dump_topology();
-}
+#ifdef LATER
+		/*
+		 * Set up all hubs to have a big window pointing at
+		 * widget 0. Memory mode, widget 0, offset 0
+		 */
+		REMOTE_HUB_S(nasid, IIO_ITTE(SWIN0_BIGWIN),
+			((HUB_PIO_MAP_TO_MEM << IIO_ITTE_IOSP_SHIFT) |
+			(0 << IIO_ITTE_WIDGET_SHIFT)));
 #endif
+	}
+}
--- diff/arch/mips/sgi-ip27/ip27-irq-glue.S	2003-07-08 09:55:17.000000000 +0100
+++ source/arch/mips/sgi-ip27/ip27-irq-glue.S	2004-02-23 13:56:38.000000000 +0000
@@ -12,53 +12,34 @@
 #include <asm/stackframe.h>
 
 	.text
-	.set	noat
 	.align	5
 NESTED(ip27_irq, PT_SIZE, sp)
 	SAVE_ALL
 	CLI
-	.set	at
 
-	/* IP27 may signal interrupt which we're not interested in.
-	   Mask them out.  */
 	mfc0	s0, CP0_CAUSE
 	mfc0	t0, CP0_STATUS
 	and	s0, t0
-
-	/* First check for RT interrupt.  */
-	andi	a0, s0, CAUSEF_IP4
-	beqz	a0, 1f
-
-	/* Ok, a timer interrupt. */
 	move	a0, sp
-	jal	rt_timer_interrupt
+	la	ra, ret_from_irq
 
-	j	ret_from_irq
-
-1:	andi	a0, s0, (CAUSEF_IP2 | CAUSEF_IP3)
-	beqz	a0, 1f
-
-	/* ... a device interrupt ...  */
-	move	a0, sp
-	jal	ip27_do_irq
-
-	j	ret_from_irq
-
-1:
-#if 1
-	mfc0	a1, CP0_STATUS
-	srl	a1, a1, 8
-	andi	a1, 0xff
-
-	mfc0	a2, CP0_CAUSE
-	srl	a2, a2, 8
-	andi	a2, 0xff
-
-	move	a3, s0
-	PRINT("Spurious interrupt, c0_status = %02x, c0_cause = %02x, pending %02x.\n")
-	ld	a1, PT_EPC(sp)
-0:	b	0b
-#endif
+	/* First check for RT interrupt.  */
+	andi	t0, s0, CAUSEF_IP4
+	bnez	t0, ip4
+	andi	t0, s0, CAUSEF_IP2
+	bnez	t0, ip2
+	andi	t0, s0, CAUSEF_IP3
+	bnez	t0, ip3
+	andi	t0, s0, CAUSEF_IP5
+	bnez	t0, ip5
+	andi	t0, s0, CAUSEF_IP6
+	bnez	t0, ip6
+	j	ra
+
+ip2:	j	ip27_do_irq_mask0	# PI_INT_PEND_0 or CC_PEND_{A|B}
+ip3:	j	ip27_do_irq_mask1	# PI_INT_PEND_1
+ip4:	j	ip27_rt_timer_interrupt
+ip5:	j	ip27_prof_timer
+ip6:	j	ip27_hub_error
 
-	j	ret_from_irq
 	END(ip27_irq)
--- diff/arch/mips/sgi-ip27/ip27-irq.c	2003-07-08 09:55:17.000000000 +0100
+++ source/arch/mips/sgi-ip27/ip27-irq.c	2004-02-23 13:56:38.000000000 +0000
@@ -38,7 +38,6 @@
 #include <asm/sn/intr.h>
 #include <asm/sn/intr_public.h>
 
-
 #undef DEBUG_IRQ
 #ifdef DEBUG_IRQ
 #define DBG(x...) printk(x)
@@ -46,10 +45,18 @@
 #define DBG(x...)
 #endif
 
-/* These should die */
-unsigned char bus_to_wid[256];	/* widget id for linux pci bus */
-unsigned char bus_to_nid[256];	/* nasid for linux pci bus */
-unsigned char num_bridges;	/* number of bridges in the system */
+/*
+ * Number of levels in INT_PEND0. Can be set to 128 if we also
+ * consider INT_PEND1.
+ */
+#define PERNODE_LEVELS	64
+
+/*
+ * we need to map irq's up to at least bit 7 of the INT_MASK0_A register
+ * since bits 0-6 are pre-allocated for other purposes.
+ */
+#define FAST_IRQ_TO_LEVEL(i)	(i)
+#define LEVEL_TO_IRQ(c, l) (node_level_to_irq[CPUID_TO_COMPACT_NODEID(c)][(l)])
 
 /*
  * Linux has a controller-independent x86 interrupt architecture.
@@ -69,30 +76,26 @@ unsigned char num_bridges;	/* number of 
 
 extern asmlinkage void ip27_irq(void);
 
-extern int irq_to_bus[], irq_to_slot[], bus_to_cpu[];
-int intr_connect_level(int cpu, int bit);
-int intr_disconnect_level(int cpu, int bit);
+extern struct bridge_controller *irq_to_bridge[];
+extern int irq_to_slot[];
 
 /*
  * There is a single intpend register per node, and we want to have
  * distinct levels for intercpu intrs for both cpus A and B on a node.
  */
-int node_level_to_irq[MAX_COMPACT_NODES][PERNODE_LEVELS];
+static int node_level_to_irq[MAX_COMPACT_NODES][PERNODE_LEVELS];
 
 /*
  * use these macros to get the encoded nasid and widget id
  * from the irq value
  */
-#define IRQ_TO_BUS(i)			irq_to_bus[(i)]
-#define IRQ_TO_CPU(i)			bus_to_cpu[IRQ_TO_BUS(i)]
-#define NASID_FROM_PCI_IRQ(i)		bus_to_nid[IRQ_TO_BUS(i)]
-#define WID_FROM_PCI_IRQ(i)		bus_to_wid[IRQ_TO_BUS(i)]
+#define IRQ_TO_BRIDGE(i)		irq_to_bridge[(i)]
 #define	SLOT_FROM_PCI_IRQ(i)		irq_to_slot[i]
 
 static inline int alloc_level(cpuid_t cpunum, int irq)
 {
 	cnodeid_t nodenum = CPUID_TO_COMPACT_NODEID(cpunum);
-	int j = LEAST_LEVEL + 3;	/* resched & crosscall entries taken */
+	int j = BASE_PCI_IRQ;			/* pre-allocated entries */
 
 	while (++j < PERNODE_LEVELS) {
 		if (node_level_to_irq[nodenum][j] == -1) {
@@ -100,9 +103,8 @@ static inline int alloc_level(cpuid_t cp
 			return j;
 		}
 	}
-	printk("Cpu %ld flooded with devices\n", cpunum);
-	while(1);
-	return -1;
+
+	panic("Cpu %ld flooded with devices\n", cpunum);
 }
 
 static inline int find_level(cpuid_t *cpunum, int irq)
@@ -111,16 +113,15 @@ static inline int find_level(cpuid_t *cp
 	cnodeid_t nodenum = INVALID_CNODEID;
 
 	while (++nodenum < MAX_COMPACT_NODES) {
-		j = LEAST_LEVEL + 3;	/* resched & crosscall entries taken */
+		j = BASE_PCI_IRQ;		/* Pre-allocated entries */
 		while (++j < PERNODE_LEVELS)
 			if (node_level_to_irq[nodenum][j] == irq) {
 				*cpunum = 0;	/* XXX Fixme */
 				return(j);
 			}
 	}
-	printk("Could not identify cpu/level for irq %d\n", irq);
-	while(1);
-	return(-1);
+
+	panic("Could not identify cpu/level for irq %d\n", irq);
 }
 
 /*
@@ -150,73 +151,206 @@ static int ms1bit(unsigned long x)
  * same intr. This effect is mostly seen for intercpu intrs.
  * Kanoj 05.13.00
  */
-void ip27_do_irq(struct pt_regs *regs)
+
+void ip27_do_irq_mask0(struct pt_regs *regs)
 {
 	int irq, swlevel;
 	hubreg_t pend0, mask0;
-	cpuid_t thiscpu = smp_processor_id();
-	int pi_int_mask0 = ((cputoslice(thiscpu) == 0) ?
-					PI_INT_MASK0_A : PI_INT_MASK0_B);
+	cpuid_t cpu = smp_processor_id();
+	int pi_int_mask0 =
+		(cputoslice(cpu) == 0) ?  PI_INT_MASK0_A : PI_INT_MASK0_B;
 
 	/* copied from Irix intpend0() */
-	while (((pend0 = LOCAL_HUB_L(PI_INT_PEND0)) &
-				(mask0 = LOCAL_HUB_L(pi_int_mask0))) != 0) {
-		pend0 &= mask0;		/* Pick intrs we should look at */
-		if (pend0) {
-			/* Prevent any of the picked intrs from recursing */
-			LOCAL_HUB_S(pi_int_mask0, mask0 & ~(pend0));
-			do {
-				swlevel = ms1bit(pend0);
-				LOCAL_HUB_CLR_INTR(swlevel);
-				/* "map" swlevel to irq */
-				irq = LEVEL_TO_IRQ(thiscpu, swlevel);
-				do_IRQ(irq, regs);
-				/* clear bit in pend0 */
-				pend0 ^= 1ULL << swlevel;
-			} while(pend0);
-			/* Now allow the set of serviced intrs again */
-			LOCAL_HUB_S(pi_int_mask0, mask0);
-			LOCAL_HUB_L(PI_INT_PEND0);
-		}
+	pend0 = LOCAL_HUB_L(PI_INT_PEND0);
+	mask0 = LOCAL_HUB_L(pi_int_mask0);
+
+	pend0 &= mask0;		/* Pick intrs we should look at */
+	if (!pend0)
+		return;
+
+	/* Prevent any of the picked intrs from recursing */
+	LOCAL_HUB_S(pi_int_mask0, mask0 & ~pend0);
+
+	swlevel = ms1bit(pend0);
+#ifdef CONFIG_SMP
+	if (pend0 & (1UL << CPU_RESCHED_A_IRQ)) {
+		LOCAL_HUB_CLR_INTR(CPU_RESCHED_A_IRQ);
+	} else if (pend0 & (1UL << CPU_RESCHED_B_IRQ)) {
+		LOCAL_HUB_CLR_INTR(CPU_RESCHED_B_IRQ);
+	} else if (pend0 & (1UL << CPU_CALL_A_IRQ)) {
+		LOCAL_HUB_CLR_INTR(CPU_CALL_A_IRQ);
+		smp_call_function_interrupt();
+	} else if (pend0 & (1UL << CPU_CALL_B_IRQ)) {
+		LOCAL_HUB_CLR_INTR(CPU_CALL_B_IRQ);
+		smp_call_function_interrupt();
+	} else
+#endif
+	{
+		/* "map" swlevel to irq */
+		irq = LEVEL_TO_IRQ(cpu, swlevel);
+		do_IRQ(irq, regs);
+	}
+
+	/* clear bit in pend0 */
+	pend0 ^= 1UL << swlevel;
+
+	/* Now allow the set of serviced intrs again */
+	LOCAL_HUB_S(pi_int_mask0, mask0);
+	LOCAL_HUB_L(PI_INT_PEND0);
+}
+
+void ip27_do_irq_mask1(struct pt_regs *regs)
+{
+	int irq, swlevel;
+	hubreg_t pend1, mask1;
+	cpuid_t cpu = smp_processor_id();
+	int pi_int_mask1 = (cputoslice(cpu) == 0) ?  PI_INT_MASK1_A : PI_INT_MASK1_B;
+
+	/* copied from Irix intpend0() */
+	pend1 = LOCAL_HUB_L(PI_INT_PEND1);
+	mask1 = LOCAL_HUB_L(pi_int_mask1);
+
+	pend1 &= mask1;		/* Pick intrs we should look at */
+	if (!pend1)
+		return;
+
+	/* Prevent any of the picked intrs from recursing */
+	LOCAL_HUB_S(pi_int_mask1, mask1 & ~pend1);
+
+	swlevel = ms1bit(pend1);
+	/* "map" swlevel to irq */
+	irq = LEVEL_TO_IRQ(cpu, swlevel);
+	LOCAL_HUB_CLR_INTR(swlevel);
+	do_IRQ(irq, regs);
+	/* clear bit in pend1 */
+	pend1 ^= 1UL << swlevel;
+
+	/* Now allow the set of serviced intrs again */
+	LOCAL_HUB_S(pi_int_mask1, mask1);
+	LOCAL_HUB_L(PI_INT_PEND1);
+}
+
+void ip27_prof_timer(struct pt_regs *regs)
+{
+	panic("CPU %d got a profiling interrupt", smp_processor_id());
+}
+
+void ip27_hub_error(struct pt_regs *regs)
+{
+	panic("CPU %d got a hub error interrupt", smp_processor_id());
+}
+
+/*
+ * Get values that vary depending on which CPU and bit we're operating on.
+ */
+static void intr_get_ptrs(cpuid_t cpu, int bit, int *new_bit,
+                          hubreg_t **intpend_masks, int *ip)
+{
+	struct hub_intmasks_s *hub_intmasks = &cpu_data[cpu].p_intmasks;
+
+	if (bit < N_INTPEND_BITS) {
+		*intpend_masks = &hub_intmasks->intpend0_masks;
+		*ip = 0;
+		*new_bit = bit;
+	} else {
+		*intpend_masks = &hub_intmasks->intpend1_masks;
+		*ip = 1;
+		*new_bit = bit - N_INTPEND_BITS;
 	}
 }
 
+static int intr_connect_level(int cpu, int bit)
+{
+	int ip;
+	int slice = cputoslice(cpu);
+	volatile hubreg_t *mask_reg;
+	hubreg_t *intpend_masks;
+	nasid_t nasid = COMPACT_TO_NASID_NODEID(cputocnode(cpu));
+
+	intr_get_ptrs(cpu, bit, &bit, &intpend_masks, &ip);
+
+	/* Make sure it's not already pending when we connect it. */
+	REMOTE_HUB_CLR_INTR(nasid, bit + ip * N_INTPEND_BITS);
+
+	*intpend_masks |= (1UL << bit);
+
+	if (ip == 0) {
+		mask_reg = REMOTE_HUB_ADDR(nasid, PI_INT_MASK0_A +
+		                PI_INT_MASK_OFFSET * slice);
+	} else {
+		mask_reg = REMOTE_HUB_ADDR(nasid, PI_INT_MASK1_A +
+				PI_INT_MASK_OFFSET * slice);
+	}
+	HUB_S(mask_reg, intpend_masks[0]);
+
+	return 0;
+}
+
+static int intr_disconnect_level(int cpu, int bit)
+{
+	int ip;
+	int slice = cputoslice(cpu);
+	volatile hubreg_t *mask_reg;
+	hubreg_t *intpend_masks;
+	nasid_t nasid = COMPACT_TO_NASID_NODEID(cputocnode(cpu));
+
+	intr_get_ptrs(cpu, bit, &bit, &intpend_masks, &ip);
+	intpend_masks[0] &= ~(1ULL << (u64)bit);
+	if (ip == 0) {
+		mask_reg = REMOTE_HUB_ADDR(nasid, PI_INT_MASK0_A +
+				PI_INT_MASK_OFFSET * slice);
+	} else {
+		mask_reg = REMOTE_HUB_ADDR(nasid, PI_INT_MASK1_A +
+				PI_INT_MASK_OFFSET * slice);
+	}
+	HUB_S(mask_reg, intpend_masks[0]);
+
+	return 0;
+}
 
 /* Startup one of the (PCI ...) IRQs routes over a bridge.  */
 static unsigned int startup_bridge_irq(unsigned int irq)
 {
+	struct bridge_controller *bc;
 	bridgereg_t device;
 	bridge_t *bridge;
 	int pin, swlevel;
-	cpuid_t cpu;
-	nasid_t master = NASID_FROM_PCI_IRQ(irq);
 
 	if (irq < BASE_PCI_IRQ)
 		return 0;
 
-        bridge = (bridge_t *) NODE_SWIN_BASE(master, WID_FROM_PCI_IRQ(irq));
 	pin = SLOT_FROM_PCI_IRQ(irq);
-	cpu = IRQ_TO_CPU(irq);
+	bc = IRQ_TO_BRIDGE(irq);
+	bridge = bc->base;
 
 	DBG("bridge_startup(): irq= 0x%x  pin=%d\n", irq, pin);
 	/*
 	 * "map" irq to a swlevel greater than 6 since the first 6 bits
 	 * of INT_PEND0 are taken
 	 */
-	swlevel = alloc_level(cpu, irq);
-	intr_connect_level(cpu, swlevel);
+	swlevel = alloc_level(bc->irq_cpu, irq);
+	intr_connect_level(bc->irq_cpu, swlevel);
 
-	bridge->b_int_addr[pin].addr = (0x20000 | swlevel | (master << 8));
+	bridge->b_int_addr[pin].addr = (0x20000 | swlevel | (bc->nasid << 8));
 	bridge->b_int_enable |= (1 << pin);
 	/* more stuff in int_enable reg */
 	bridge->b_int_enable |= 0x7ffffe00;
 
 	/*
-	 * XXX This only works if b_int_device is initialized to 0!
-	 * We program the bridge to have a 1:1 mapping between devices
+	 * Enable sending of an interrupt clear packt to the hub on a high to
+	 * low transition of the interrupt pin.
+	 *
+	 * IRIX sets additional bits in the address which are documented as
+	 * reserved in the bridge docs.
+	 */
+	bridge->b_int_mode |= (1UL << pin);
+
+	/*
+	 * We assume the bridge to have a 1:1 mapping between devices
 	 * (slots) and intr pins.
 	 */
 	device = bridge->b_int_device;
+	device &= ~(7 << (pin*3));
 	device |= (pin << (pin*3));
 	bridge->b_int_device = device;
 
@@ -226,17 +360,15 @@ static unsigned int startup_bridge_irq(u
 }
 
 /* Shutdown one of the (PCI ...) IRQs routes over a bridge.  */
-static unsigned int shutdown_bridge_irq(unsigned int irq)
+static void shutdown_bridge_irq(unsigned int irq)
 {
-	bridge_t *bridge;
+	struct bridge_controller *bc = IRQ_TO_BRIDGE(irq);
+	bridge_t *bridge = bc->base;
 	int pin, swlevel;
 	cpuid_t cpu;
 
-	if (irq < BASE_PCI_IRQ)
-		return 0;
+	BUG_ON(irq < BASE_PCI_IRQ);
 
-	bridge = (bridge_t *) NODE_SWIN_BASE(NASID_FROM_PCI_IRQ(irq),
-	                                     WID_FROM_PCI_IRQ(irq));
 	DBG("bridge_shutdown: irq 0x%x\n", irq);
 	pin = SLOT_FROM_PCI_IRQ(irq);
 
@@ -250,8 +382,6 @@ static unsigned int shutdown_bridge_irq(
 
 	bridge->b_int_enable &= ~(1 << pin);
 	bridge->b_widget.w_tflush;                      /* Flush */
-
-	return 0;       /* Never anything pending.  */
 }
 
 static inline void enable_bridge_irq(unsigned int irq)
@@ -269,20 +399,18 @@ static void mask_and_ack_bridge_irq(unsi
 	/* All the braindamage happens magically for us in ip27_do_irq */
 }
 
-static void end_bridge_irq (unsigned int irq)
+static void end_bridge_irq(unsigned int irq)
 {
-	if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
-		enable_bridge_irq(irq);
 }
 
 static struct hw_interrupt_type bridge_irq_type = {
-	"bridge",
-	startup_bridge_irq,
-	shutdown_bridge_irq,
-	enable_bridge_irq,
-	disable_bridge_irq,
-	mask_and_ack_bridge_irq,
-	end_bridge_irq
+	.typename	= "bridge",
+	.startup	= startup_bridge_irq,
+	.shutdown	= shutdown_bridge_irq,
+	.enable		= enable_bridge_irq,
+	.disable	= disable_bridge_irq,
+	.ack		= mask_and_ack_bridge_irq,
+	.end		= end_bridge_irq,
 };
 
 void irq_debug(void)
@@ -297,7 +425,11 @@ void irq_debug(void)
 
 void __init init_IRQ(void)
 {
-	int i;
+	int i, j;
+
+	for (i = 0; i < MAX_COMPACT_NODES; i++)
+		for (j = 0; j < PERNODE_LEVELS; j++)
+			node_level_to_irq[i][j] = -1;
 
 	set_except_vector(0, ip27_irq);
 
@@ -312,177 +444,29 @@ void __init init_IRQ(void)
 	}
 }
 
-/*
- * Get values that vary depending on which CPU and bit we're operating on.
- */
-static hub_intmasks_t *intr_get_ptrs(cpuid_t cpu, int bit, int *new_bit,
-				hubreg_t **intpend_masks, int *ip)
+void install_ipi(void)
 {
-	hub_intmasks_t *hub_intmasks;
-
-	hub_intmasks = &cpu_data[cpu].p_intmasks;
-	if (bit < N_INTPEND_BITS) {
-		*intpend_masks = hub_intmasks->intpend0_masks;
-		*ip = 0;
-		*new_bit = bit;
-	} else {
-		*intpend_masks = hub_intmasks->intpend1_masks;
-		*ip = 1;
-		*new_bit = bit - N_INTPEND_BITS;
-	}
-	return hub_intmasks;
-}
-
-int intr_connect_level(int cpu, int bit)
-{
-	int ip;
-	int slice = cputoslice(cpu);
-	volatile hubreg_t *mask_reg;
-	hubreg_t *intpend_masks;
-	nasid_t nasid = COMPACT_TO_NASID_NODEID(cputocnode(cpu));
-
-	(void)intr_get_ptrs(cpu, bit, &bit, &intpend_masks, &ip);
-
-	/* Make sure it's not already pending when we connect it. */
-	REMOTE_HUB_CLR_INTR(nasid, bit + ip * N_INTPEND_BITS);
-
-	intpend_masks[0] |= (1ULL << (u64)bit);
-
-	if (ip == 0) {
-		mask_reg = REMOTE_HUB_ADDR(nasid, PI_INT_MASK0_A +
-				PI_INT_MASK_OFFSET * slice);
+	int slice = LOCAL_HUB_L(PI_CPU_NUM);
+	int cpu = smp_processor_id();
+	hubreg_t mask, set;
+
+	if (slice == 0) {
+		LOCAL_HUB_CLR_INTR(CPU_RESCHED_A_IRQ);
+		LOCAL_HUB_CLR_INTR(CPU_CALL_A_IRQ);
+		mask = LOCAL_HUB_L(PI_INT_MASK0_A);	/* Slice A */
+		set = (1UL << FAST_IRQ_TO_LEVEL(CPU_RESCHED_A_IRQ)) |
+		      (1UL << FAST_IRQ_TO_LEVEL(CPU_CALL_A_IRQ));
+		mask |= set;
+		cpu_data[cpu].p_intmasks.intpend0_masks |= set;
+		LOCAL_HUB_S(PI_INT_MASK0_A, mask);
 	} else {
-		mask_reg = REMOTE_HUB_ADDR(nasid, PI_INT_MASK1_A +
-				PI_INT_MASK_OFFSET * slice);
+		LOCAL_HUB_CLR_INTR(CPU_RESCHED_B_IRQ);
+		LOCAL_HUB_CLR_INTR(CPU_CALL_B_IRQ);
+		mask = LOCAL_HUB_L(PI_INT_MASK0_B);	/* Slice B */
+		set = (1UL << FAST_IRQ_TO_LEVEL(CPU_RESCHED_B_IRQ)) |
+		      (1UL << FAST_IRQ_TO_LEVEL(CPU_CALL_B_IRQ));
+		mask |= set;
+		cpu_data[cpu].p_intmasks.intpend0_masks |= set;
+		LOCAL_HUB_S(PI_INT_MASK0_B, mask);
 	}
-	HUB_S(mask_reg, intpend_masks[0]);
-	return(0);
-}
-
-int intr_disconnect_level(int cpu, int bit)
-{
-	int ip;
-	int slice = cputoslice(cpu);
-	volatile hubreg_t *mask_reg;
-	hubreg_t *intpend_masks;
-	nasid_t nasid = COMPACT_TO_NASID_NODEID(cputocnode(cpu));
-
-	(void)intr_get_ptrs(cpu, bit, &bit, &intpend_masks, &ip);
-	intpend_masks[0] &= ~(1ULL << (u64)bit);
-	if (ip == 0) {
-		mask_reg = REMOTE_HUB_ADDR(nasid, PI_INT_MASK0_A +
-				PI_INT_MASK_OFFSET * slice);
-	} else {
-		mask_reg = REMOTE_HUB_ADDR(nasid, PI_INT_MASK1_A +
-				PI_INT_MASK_OFFSET * slice);
-	}
-	HUB_S(mask_reg, intpend_masks[0]);
-	return(0);
-}
-
-
-irqreturn_t handle_resched_intr(int irq, void *dev_id, struct pt_regs *regs)
-{
-	/* Nothing, the return from intr will work for us */
-	return IRQ_NONE;
-}
-
-#ifdef CONFIG_SMP
-
-void core_send_ipi(int destid, unsigned int action)
-{
-	int irq;
-
-#if (CPUS_PER_NODE == 2)
-	switch (action) {
-		case SMP_RESCHEDULE_YOURSELF:
-			irq = CPU_RESCHED_A_IRQ;
-			break;
-		case SMP_CALL_FUNCTION:
-			irq = CPU_CALL_A_IRQ;
-			break;
-		default:
-			panic("sendintr");
-	}
-	irq += cputoslice(destid);
-
-	/*
-	 * Convert the compact hub number to the NASID to get the correct
-	 * part of the address space.  Then set the interrupt bit associated
-	 * with the CPU we want to send the interrupt to.
-	 */
-	REMOTE_HUB_SEND_INTR(COMPACT_TO_NASID_NODEID(cputocnode(destid)),
-			FAST_IRQ_TO_LEVEL(irq));
-#else
-	<< Bomb!  Must redefine this for more than 2 CPUS. >>
-#endif
-}
-
-#endif
-
-extern irqreturn_t smp_call_function_interrupt(int irq, void *dev,
-	struct pt_regs *regs);
-
-void install_cpuintr(int cpu)
-{
-#ifdef CONFIG_SMP
-#if (CPUS_PER_NODE == 2)
-	static int done = 0;
-
-	/*
-	 * This is a hack till we have a pernode irqlist. Currently,
-	 * just have the master cpu set up the handlers for the per
-	 * cpu irqs.
-	 */
-	if (done == 0) {
-		int j;
-
-		if (request_irq(CPU_RESCHED_A_IRQ, handle_resched_intr,
-							0, "resched", 0))
-			panic("intercpu intr unconnectible");
-		if (request_irq(CPU_RESCHED_B_IRQ, handle_resched_intr,
-							0, "resched", 0))
-			panic("intercpu intr unconnectible");
-		if (request_irq(CPU_CALL_A_IRQ, smp_call_function_interrupt,
-							0, "callfunc", 0))
-			panic("intercpu intr unconnectible");
-		if (request_irq(CPU_CALL_B_IRQ, smp_call_function_interrupt,
-							0, "callfunc", 0))
-			panic("intercpu intr unconnectible");
-
-		for (j = 0; j < PERNODE_LEVELS; j++)
-			LEVEL_TO_IRQ(0, j) = -1;
-		LEVEL_TO_IRQ(0, FAST_IRQ_TO_LEVEL(CPU_RESCHED_A_IRQ)) =
-							CPU_RESCHED_A_IRQ;
-		LEVEL_TO_IRQ(0, FAST_IRQ_TO_LEVEL(CPU_RESCHED_B_IRQ)) =
-							CPU_RESCHED_B_IRQ;
-		LEVEL_TO_IRQ(0, FAST_IRQ_TO_LEVEL(CPU_CALL_A_IRQ)) =
-							CPU_CALL_A_IRQ;
-		LEVEL_TO_IRQ(0, FAST_IRQ_TO_LEVEL(CPU_CALL_B_IRQ)) =
-							CPU_CALL_B_IRQ;
-		for (j = 1; j < MAX_COMPACT_NODES; j++)
-			memcpy(&node_level_to_irq[j][0],
-			&node_level_to_irq[0][0],
-			sizeof(node_level_to_irq[0][0])*PERNODE_LEVELS);
-
-		done = 1;
-	}
-
-	intr_connect_level(cpu, FAST_IRQ_TO_LEVEL(CPU_RESCHED_A_IRQ +
-							cputoslice(cpu)));
-	intr_connect_level(cpu, FAST_IRQ_TO_LEVEL(CPU_CALL_A_IRQ +
-							cputoslice(cpu)));
-#else /* CPUS_PER_NODE */
-#error Must redefine this for more than 2 CPUS.
-#endif /* CPUS_PER_NODE */
-#endif /* CONFIG_SMP */
-}
-
-void install_tlbintr(int cpu)
-{
-#if 0
-	int intr_bit = N_INTPEND_BITS + TLB_INTR_A + cputoslice(cpu);
-
-	intr_connect_level(cpu, intr_bit);
-#endif
 }
--- diff/arch/mips/sgi-ip27/ip27-klnuma.c	2003-08-20 14:16:25.000000000 +0100
+++ source/arch/mips/sgi-ip27/ip27-klnuma.c	2004-02-23 13:56:38.000000000 +0000
@@ -15,8 +15,7 @@
 #include <asm/sn/types.h>
 #include <asm/sn/arch.h>
 #include <asm/sn/gda.h>
-#include <asm/mmzone.h>
-#include <asm/sn/klkernvars.h>
+#include <asm/sn/hub.h>
 #include <asm/sn/mapped_kernel.h>
 #include <asm/sn/sn_private.h>
 
@@ -34,8 +33,8 @@ void __init setup_replication_mask(int m
 	cnodeid_t	cnode;
 
 	/* Set only the master cnode's bit.  The master cnode is always 0. */
-	CPUMASK_CLRALL(ktext_repmask);
-	CPUMASK_SETB(ktext_repmask, 0);
+	cpus_clear(ktext_repmask);
+	cpu_set(0, ktext_repmask);
 
 	numa_kernel_replication_ratio = 0;
 #ifdef CONFIG_REPLICATE_KTEXT
@@ -51,7 +50,7 @@ void __init setup_replication_mask(int m
 		    !(cnode % numa_kernel_replication_ratio)) {
 
 			/* Advertise that we have a copy of the kernel */
-			CPUMASK_SETB(ktext_repmask, cnode);
+			cpu_set(cnode, ktext_repmask);
 		}
 	}
 
@@ -67,12 +66,11 @@ static __init void set_ktext_source(nasi
 
 	client_cnode = NASID_TO_COMPACT_NODEID(client_nasid);
 
-	kvp = &(PLAT_NODE_DATA(client_cnode)->kern_vars);
+	kvp = &(HUB_DATA(client_nasid)->kern_vars);
 
 	KERN_VARS_ADDR(client_nasid) = (unsigned long)kvp;
 
 	kvp->kv_magic = KV_MAGIC;
-
 	kvp->kv_ro_nasid = server_nasid;
 	kvp->kv_rw_nasid = master_nasid;
 	kvp->kv_ro_baseaddr = NODE_CAC_BASE(server_nasid);
@@ -109,7 +107,7 @@ void __init replicate_kernel_text(int ma
 		client_nasid = COMPACT_TO_NASID_NODEID(cnode);
 
 		/* Check if this node should get a copy of the kernel */
-		if (CPUMASK_TSTB(ktext_repmask, cnode)) {
+		if (cpu_isset(cnode, ktext_repmask)) {
 			server_nasid = client_nasid;
 			copy_kernel(server_nasid);
 		}
@@ -134,7 +132,7 @@ pfn_t node_getfirstfree(cnodeid_t cnode)
 	loadbase = CKSSEG + 16777216;
 #endif
 	offset = PAGE_ALIGN((unsigned long)(&_end)) - loadbase;
-	if ((cnode == 0) || (CPUMASK_TSTB(ktext_repmask, cnode)))
+	if ((cnode == 0) || (cpu_isset(cnode, ktext_repmask)))
 		return (TO_NODE(nasid, offset) >> PAGE_SHIFT);
 	else
 		return (KDM_TO_PHYS(PAGE_ALIGN(SYMMON_STK_ADDR(nasid, 0))) >>
--- diff/arch/mips/sgi-ip27/ip27-memory.c	2003-08-20 14:16:25.000000000 +0100
+++ source/arch/mips/sgi-ip27/ip27-memory.c	2004-02-23 13:56:38.000000000 +0000
@@ -23,6 +23,7 @@
 #include <asm/pgalloc.h>
 #include <asm/sn/types.h>
 #include <asm/sn/addrs.h>
+#include <asm/sn/hub.h>
 #include <asm/sn/klconfig.h>
 #include <asm/sn/arch.h>
 #include <asm/mmzone.h>
@@ -36,10 +37,10 @@ extern pfn_t node_getfirstfree(cnodeid_t
 
 short slot_lastfilled_cache[MAX_COMPACT_NODES];
 unsigned short slot_psize_cache[MAX_COMPACT_NODES][MAX_MEM_SLOTS];
-static pfn_t numpages;
 
-plat_pg_data_t *plat_node_data[MAX_COMPACT_NODES];
-bootmem_data_t plat_node_bdata[MAX_COMPACT_NODES];
+struct bootmem_data plat_node_bdata[MAX_COMPACT_NODES];
+struct pglist_data *node_data[MAX_COMPACT_NODES];
+struct hub_data *hub_data[MAX_COMPACT_NODES];
 
 int numa_debug(void)
 {
@@ -52,7 +53,7 @@ int numa_debug(void)
  * Return the number of pages of memory provided by the given slot
  * on the specified node.
  */
-pfn_t slot_getsize(cnodeid_t node, int slot)
+static pfn_t slot_getsize(cnodeid_t node, int slot)
 {
 	return (pfn_t) slot_psize_cache[node][slot];
 }
@@ -60,7 +61,7 @@ pfn_t slot_getsize(cnodeid_t node, int s
 /*
  * Return highest slot filled
  */
-int node_getlastslot(cnodeid_t node)
+static int node_getlastslot(cnodeid_t node)
 {
 	return (int) slot_lastfilled_cache[node];
 }
@@ -68,7 +69,7 @@ int node_getlastslot(cnodeid_t node)
 /*
  * Return the pfn of the last free page of memory on a node.
  */
-pfn_t node_getmaxclick(cnodeid_t node)
+static pfn_t node_getmaxclick(cnodeid_t node)
 {
 	pfn_t	slot_psize;
 	int	slot;
@@ -90,7 +91,7 @@ pfn_t node_getmaxclick(cnodeid_t node)
 	 * If there's no memory on the node, return 0. This is likely
 	 * to cause problems.
 	 */
-	return (pfn_t)0;
+	return 0;
 }
 
 static pfn_t slot_psize_compute(cnodeid_t node, int slot)
@@ -107,7 +108,7 @@ static pfn_t slot_psize_compute(cnodeid_
 		return 0;
 
 	/* Get the memory bank structure */
-	banks = (klmembnk_t *)find_first_component(brd, KLSTRUCT_MEMBNK);
+	banks = (klmembnk_t *) find_first_component(brd, KLSTRUCT_MEMBNK);
 	if (!banks)
 		return 0;
 
@@ -116,20 +117,19 @@ static pfn_t slot_psize_compute(cnodeid_
 
 	/* hack for 128 dimm banks */
 	if (size <= 128) {
-		if (slot%4 == 0) {
+		if (slot % 4 == 0) {
 			size <<= 20;		/* size in bytes */
 			return(size >> PAGE_SHIFT);
-		} else {
+		} else
 			return 0;
-		}
 	} else {
 		size /= 4;
 		size <<= 20;
-		return(size >> PAGE_SHIFT);
+		return size >> PAGE_SHIFT;
 	}
 }
 
-pfn_t szmem(pfn_t fpage, pfn_t maxpmem)
+static pfn_t szmem(void)
 {
 	cnodeid_t node;
 	int slot, numslots;
@@ -165,10 +165,8 @@ pfn_t szmem(pfn_t fpage, pfn_t maxpmem)
 				slot_lastfilled_cache[node] = slot;
 		}
 	}
-	if (maxpmem)
-		return((maxpmem > num_pages) ? num_pages : maxpmem);
-	else
-		return num_pages;
+
+	return num_pages;
 }
 
 /*
@@ -176,32 +174,32 @@ pfn_t szmem(pfn_t fpage, pfn_t maxpmem)
  * contains at least 32 MBytes of memory. We assume all bootmem data
  * fits on the first slot.
  */
+extern void mlreset(void);
 void __init prom_meminit(void)
 {
-	extern void mlreset(void);
 	cnodeid_t node;
-	pfn_t slot_firstpfn, slot_lastpfn, slot_freepfn;
-	unsigned long bootmap_size;
-	int node_datasz;
 
-	node_datasz = PFN_UP(sizeof(plat_pg_data_t));
 	mlreset();
-	numpages = szmem(0, 0);
-	for (node = (numnodes - 1); node >= 0; node--) {
-		slot_firstpfn = slot_getbasepfn(node, 0);
-		slot_lastpfn = slot_firstpfn + slot_getsize(node, 0);
-		slot_freepfn = node_getfirstfree(node);
-		/* Foll line hack for non discontigmem; remove once discontigmem
-		 * becomes the default. */
-		max_low_pfn = (slot_lastpfn - slot_firstpfn);
+
+	num_physpages = szmem();
+
+	for (node = 0; node < numnodes; node++) {
+		pfn_t slot_firstpfn = slot_getbasepfn(node, 0);
+		pfn_t slot_lastpfn = slot_firstpfn + slot_getsize(node, 0);
+		pfn_t slot_freepfn = node_getfirstfree(node);
+		unsigned long bootmap_size;
 
 		/*
-		 * Allocate the node data structure on the node first.
+		 * Allocate the node data structures on the node first.
 		 */
-		plat_node_data[node] = (plat_pg_data_t *)(__va(slot_freepfn \
-							<< PAGE_SHIFT));
-		NODE_DATA(node)->bdata = plat_node_bdata + node;
-		slot_freepfn += node_datasz;
+		node_data[node] = __va(slot_freepfn << PAGE_SHIFT);
+		node_data[node]->bdata = &plat_node_bdata[node];
+
+		hub_data[node] = node_data[node] + 1;
+
+		slot_freepfn += PFN_UP(sizeof(struct pglist_data) +
+				       sizeof(struct hub_data));
+	
 	  	bootmap_size = init_bootmem_node(NODE_DATA(node), slot_freepfn,
 						slot_firstpfn, slot_lastpfn);
 		free_bootmem_node(NODE_DATA(node), slot_firstpfn << PAGE_SHIFT,
@@ -209,123 +207,90 @@ void __init prom_meminit(void)
 		reserve_bootmem_node(NODE_DATA(node), slot_firstpfn << PAGE_SHIFT,
 		  ((slot_freepfn - slot_firstpfn) << PAGE_SHIFT) + bootmap_size);
 	}
-	printk("Total memory probed : 0x%lx pages\n", numpages);
 }
 
-void __init
-prom_free_prom_memory (void)
+unsigned long __init prom_free_prom_memory(void)
 {
 	/* We got nothing to free here ...  */
+	return 0;
 }
 
-#ifdef CONFIG_DISCONTIGMEM
-
-static pfn_t pagenr;
+extern void pagetable_init(void);
+extern unsigned long setup_zero_pages(void);
 
 void __init paging_init(void)
 {
-	pmd_t *pmd = kpmdtbl;
-	pte_t *pte = kptbl;
-
-	cnodeid_t node;
 	unsigned long zones_size[MAX_NR_ZONES] = {0, 0, 0};
-	int i;
+	unsigned node;
 
-	/* Initialize the entire pgd.  */
-	pgd_init((unsigned long)swapper_pg_dir);
-	pmd_init((unsigned long)invalid_pmd_table, (unsigned long)invalid_pte_table);
-	memset((void *)invalid_pte_table, 0, sizeof(pte_t) * PTRS_PER_PTE);
-
-	/* This is for vmalloc  */
-	memset((void *)kptbl, 0, PAGE_SIZE << PGD_ORDER);
-	memset((void *)kpmdtbl, 0, PAGE_SIZE);
-	set_pgd(swapper_pg_dir, __pgd(kpmdtbl));
-	for (i = 0; i < (1 << PGD_ORDER); pmd++,i++,pte+=PTRS_PER_PTE)
-		pmd_val(*pmd) = (unsigned long)pte;
+	pagetable_init();
 
 	for (node = 0; node < numnodes; node++) {
 		pfn_t start_pfn = slot_getbasepfn(node, 0);
-		pfn_t end_pfn = node_getmaxclick(node);
+		pfn_t end_pfn = node_getmaxclick(node) + 1;
+
+		zones_size[ZONE_DMA] = end_pfn - start_pfn;
+		free_area_init_node(node, NODE_DATA(node), NULL,
+				zones_size, start_pfn, NULL);
 
-		zones_size[ZONE_DMA] = end_pfn + 1 - start_pfn;
-		free_area_init_node(node, NODE_DATA(node), 0, zones_size,
-						start_pfn, 0);
+		if (end_pfn > max_low_pfn)
+			max_low_pfn = end_pfn;
 	}
 }
 
 void __init mem_init(void)
 {
-	extern unsigned long setup_zero_pages(void);
-	cnodeid_t nid;
-	unsigned long tmp;
-	unsigned long codesize, datasize, initsize;
-	int slot, numslots;
-	struct page *pg, *pslot;
-
-	num_physpages = numpages;	/* memory already sized by szmem */
-	max_mapnr = pagenr;		/* already found during paging_init */
-	high_memory = (void *) __va(max_mapnr << PAGE_SHIFT);
+	unsigned long codesize, datasize, initsize, tmp;
+	unsigned node;
 
-	for (nid = 0; nid < numnodes; nid++) {
+	high_memory = (void *) __va(num_physpages << PAGE_SHIFT);
 
-		/*
-		 * Hack till free_area_init_core() zeroes free_pages
-		 */
-		for (tmp = 0; tmp < MAX_NR_ZONES; tmp++)
-			PLAT_NODE_DATA(nid)->gendata.node_zones[tmp].free_pages=0;
+	for (node = 0; node < numnodes; node++) {
+		unsigned slot, numslots;
+		struct page *end, *p;
+	
 		/*
 	 	 * This will free up the bootmem, ie, slot 0 memory.
 	 	 */
-		totalram_pages += free_all_bootmem_node(NODE_DATA(nid));
+		totalram_pages += free_all_bootmem_node(NODE_DATA(node));
 
 		/*
 		 * We need to manually do the other slots.
 		 */
-		pg = NODE_DATA(nid)->node_mem_map + slot_getsize(nid, 0);
-		numslots = node_getlastslot(nid);
+		numslots = node_getlastslot(node);
 		for (slot = 1; slot <= numslots; slot++) {
-			pslot = NODE_DATA(nid)->node_mem_map +
-			   slot_getbasepfn(nid, slot) - slot_getbasepfn(nid, 0);
-
-			/*
-			 * Mark holes in previous slot. May also want to
-			 * free up the pages that hold the memmap entries.
-			 */
-			while (pg < pslot) {
-				pg++;
-			}
+			p = NODE_DATA(node)->node_mem_map +
+				(slot_getbasepfn(node, slot) -
+				 slot_getbasepfn(node, 0));
 
 			/*
 			 * Free valid memory in current slot.
 			 */
-			pslot += slot_getsize(nid, slot);
-			while (pg < pslot) {
+			for (end = p + slot_getsize(node, slot); p < end; p++) {
 				/* if (!page_is_ram(pgnr)) continue; */
 				/* commented out until page_is_ram works */
-				ClearPageReserved(pg);
-				atomic_set(&pg->count, 1);
-				__free_page(pg);
+				ClearPageReserved(p);
+				set_page_count(p, 1);
+				__free_page(p);
 				totalram_pages++;
-				pg++; pgnr++;
 			}
 		}
 	}
 
 	totalram_pages -= setup_zero_pages();	/* This comes from node 0 */
 
-	codesize =  (unsigned long) _etext - (unsigned long) _stext;
-	datasize =  (unsigned long) _edata - (unsigned long) _fdata;
-	initsize =  (unsigned long) __init_end - (unsigned long) __init_begin;
-
-	tmp = (unsigned long) nr_free_pages();
-	printk("Memory: %luk/%luk available (%ldk kernel code, %ldk reserved, "
-		"%ldk data, %ldk init)\n",
-		tmp << (PAGE_SHIFT-10),
-		num_physpages << (PAGE_SHIFT-10),
-		codesize >> 10,
-		(num_physpages - tmp) << (PAGE_SHIFT-10),
-		datasize >> 10,
-		initsize >> 10);
+	codesize =  (unsigned long) &_etext - (unsigned long) &_text;
+	datasize =  (unsigned long) &_edata - (unsigned long) &_etext;
+	initsize =  (unsigned long) &__init_end - (unsigned long) &__init_begin;
+
+	tmp = nr_free_pages();
+	printk(KERN_INFO "Memory: %luk/%luk available (%ldk kernel code, "
+	       "%ldk reserved, %ldk data, %ldk init, %ldk highmem)\n",
+	       tmp << (PAGE_SHIFT-10),
+	       num_physpages << (PAGE_SHIFT-10),
+	       codesize >> 10,
+	       (num_physpages - tmp) << (PAGE_SHIFT-10),
+	       datasize >> 10,
+	       initsize >> 10,
+	       (unsigned long) (totalhigh_pages << (PAGE_SHIFT-10)));
 }
-
-#endif /* CONFIG_DISCONTIGMEM */
--- diff/arch/mips/sgi-ip27/ip27-nmi.c	2003-07-08 09:55:17.000000000 +0100
+++ source/arch/mips/sgi-ip27/ip27-nmi.c	2004-02-23 13:56:38.000000000 +0000
@@ -1,3 +1,4 @@
+#include <linux/kallsyms.h>
 #include <linux/kernel.h>
 #include <linux/mmzone.h>
 #include <linux/spinlock.h>
@@ -51,24 +52,102 @@ void install_cpu_nmi_handler(int slice)
  * into the eframe format for the node under consideration.
  */
 
-void
-nmi_cpu_eframe_save(nasid_t nasid,
-		    int	    slice)
+void nmi_cpu_eframe_save(nasid_t nasid, int slice)
 {
-	int 		i, numberof_nmi_cpu_regs;
-	machreg_t	*prom_format;
-
-	/* Get the total number of registers being saved by the prom */
-	numberof_nmi_cpu_regs = sizeof(struct reg_struct) / sizeof(machreg_t);
+	struct reg_struct *nr;
+	int 		i;
 
 	/* Get the pointer to the current cpu's register set. */
-	prom_format =
-	    (machreg_t *)(TO_UNCAC(TO_NODE(nasid, IP27_NMI_KREGS_OFFSET)) +
-			  slice * IP27_NMI_KREGS_CPU_SIZE);
+	nr = (struct reg_struct *)
+		(TO_UNCAC(TO_NODE(nasid, IP27_NMI_KREGS_OFFSET)) +
+		slice * IP27_NMI_KREGS_CPU_SIZE);
 
 	printk("NMI nasid %d: slice %d\n", nasid, slice);
-	for (i = 0; i < numberof_nmi_cpu_regs; i++)
-		printk("0x%lx  ", prom_format[i]);
+
+	/*
+	 * Saved main processor registers
+	 */
+	for (i = 0; i < 32; ) {
+		if ((i % 4) == 0)
+			printk("$%2d   :", i);
+		printk(" %016lx", nr->gpr[i]);
+
+		i++;
+		if ((i % 4) == 0)
+			printk("\n");
+	}
+
+	printk("Hi    : (value lost)\n");
+	printk("Lo    : (value lost)\n");
+
+	/*
+	 * Saved cp0 registers
+	 */
+	printk("epc   : %016lx ", nr->epc);
+	print_symbol("%s ", nr->epc);
+	printk("%s\n", print_tainted());
+	printk("ErrEPC: %016lx ", nr->error_epc);
+	print_symbol("%s\n", nr->error_epc);
+	printk("ra    : %016lx ", nr->gpr[31]);
+	print_symbol("%s\n", nr->gpr[31]);
+	printk("Status: %08lx         ", nr->sr);
+
+	if (nr->sr & ST0_KX)
+		printk("KX ");
+	if (nr->sr & ST0_SX)
+		printk("SX 	");
+	if (nr->sr & ST0_UX)
+		printk("UX ");
+
+	switch (nr->sr & ST0_KSU) {
+	case KSU_USER:
+		printk("USER ");
+		break;
+	case KSU_SUPERVISOR:
+		printk("SUPERVISOR ");
+		break;
+	case KSU_KERNEL:
+		printk("KERNEL ");
+		break;
+	default:
+		printk("BAD_MODE ");
+		break;
+	}
+
+	if (nr->sr & ST0_ERL)
+		printk("ERL ");
+	if (nr->sr & ST0_EXL)
+		printk("EXL ");
+	if (nr->sr & ST0_IE)
+		printk("IE ");
+	printk("\n");
+
+	printk("Cause : %08lx\n", nr->cause);
+	printk("PrId  : %08x\n", read_c0_prid());
+	printk("BadVA : %016lx\n", nr->badva);
+	printk("CErr  : %016lx\n", nr->cache_err);
+	printk("NMI_SR: %016lx\n", nr->nmi_sr);
+
+	printk("\n");
+}
+
+void nmi_dump_hub_irq(nasid_t nasid, int slice)
+{
+	hubreg_t mask0, mask1, pend0, pend1;
+
+	if (slice == 0) {				/* Slice A */
+		mask0 = REMOTE_HUB_L(nasid, PI_INT_MASK0_A);
+		mask1 = REMOTE_HUB_L(nasid, PI_INT_MASK1_A);
+	} else {					/* Slice B */
+		mask0 = REMOTE_HUB_L(nasid, PI_INT_MASK0_B);
+		mask1 = REMOTE_HUB_L(nasid, PI_INT_MASK1_B);
+	}
+
+	pend0 = REMOTE_HUB_L(nasid, PI_INT_PEND0);
+	pend1 = REMOTE_HUB_L(nasid, PI_INT_PEND1);
+
+	printk("PI_INT_MASK0: %16lx PI_INT_MASK1: %16lx\n", mask0, mask1);
+	printk("PI_INT_PEND0: %16lx PI_INT_PEND1: %16lx\n", pend0, pend1);
 	printk("\n\n");
 }
 
@@ -76,11 +155,10 @@ nmi_cpu_eframe_save(nasid_t nasid,
  * Copy the cpu registers which have been saved in the IP27prom format
  * into the eframe format for the node under consideration.
  */
-void
-nmi_node_eframe_save(cnodeid_t  cnode)
+void nmi_node_eframe_save(cnodeid_t  cnode)
 {
-	int		cpu;
-	nasid_t		nasid;
+	nasid_t nasid;
+	int slice;
 
 	/* Make sure that we have a valid node */
 	if (cnode == CNODEID_NONE)
@@ -91,8 +169,10 @@ nmi_node_eframe_save(cnodeid_t  cnode)
 		return;
 
 	/* Save the registers into eframe for each cpu */
-	for(cpu = 0; cpu < NODE_NUM_CPUS(cnode); cpu++)
-		nmi_cpu_eframe_save(nasid, cpu);
+	for (slice = 0; slice < NODE_NUM_CPUS(slice); slice++) {
+		nmi_cpu_eframe_save(nasid, slice);
+		nmi_dump_hub_irq(nasid, slice);
+	}
 }
 
 /*
--- diff/arch/mips/sgi-ip27/ip27-setup.c	2003-07-08 09:55:17.000000000 +0100
+++ source/arch/mips/sgi-ip27/ip27-setup.c	2004-02-23 13:56:38.000000000 +0000
@@ -105,22 +105,99 @@ static void __init verify_mode(void)
 }
 
 #define XBOW_WIDGET_PART_NUM    0x0
-#define XXBOW_WIDGET_PART_NUM   0xd000          /* Xbridge */
+#define XXBOW_WIDGET_PART_NUM   0xd000  /* Xbow in Xbridge */
 #define BASE_XBOW_PORT  	8     /* Lowest external port */
 
-unsigned int bus_to_cpu[256];
-unsigned long bus_to_baddr[256];
+extern int bridge_probe(nasid_t nasid, int widget, int masterwid);
+
+static int __init probe_one_port(nasid_t nasid, int widget, int masterwid)
+{
+	widgetreg_t 		widget_id;
+	xwidget_part_num_t	partnum;
+
+	widget_id = *(volatile widgetreg_t *)
+		(RAW_NODE_SWIN_BASE(nasid, widget) + WIDGET_ID);
+	partnum = XWIDGET_PART_NUM(widget_id);
+
+	printk(KERN_INFO "Cpu %d, Nasid 0x%x, widget 0x%x (partnum 0x%x) is ",
+			smp_processor_id(), nasid, widget, partnum);
+
+	switch (partnum) {
+	case BRIDGE_WIDGET_PART_NUM:
+	case XBRIDGE_WIDGET_PART_NUM:
+		bridge_probe(nasid, widget, masterwid);
+		break;
+	default:
+		break;
+	}
+
+	return 0;
+}
+
+static int __init xbow_probe(nasid_t nasid)
+{
+	lboard_t *brd;
+	klxbow_t *xbow_p;
+	unsigned masterwid, i;
+
+	printk("is xbow\n");
+
+	/*
+	 * found xbow, so may have multiple bridges
+	 * need to probe xbow
+	 */
+	brd = find_lboard((lboard_t *)KL_CONFIG_INFO(nasid), KLTYPE_MIDPLANE8);
+	if (!brd)
+		return -ENODEV;
+	
+	xbow_p = (klxbow_t *)find_component(brd, NULL, KLSTRUCT_XBOW);
+	if (!xbow_p)
+		return -ENODEV;
+
+	/*
+	 * Okay, here's a xbow. Lets arbitrate and find
+	 * out if we should initialize it. Set enabled
+	 * hub connected at highest or lowest widget as
+	 * master.
+	 */
+#ifdef WIDGET_A
+	i = HUB_WIDGET_ID_MAX + 1;
+	do {
+		i--;
+	} while ((!XBOW_PORT_TYPE_HUB(xbow_p, i)) ||
+		 (!XBOW_PORT_IS_ENABLED(xbow_p, i)));
+#else
+	i = HUB_WIDGET_ID_MIN - 1;
+	do {
+		i++;
+	} while ((!XBOW_PORT_TYPE_HUB(xbow_p, i)) ||
+		 (!XBOW_PORT_IS_ENABLED(xbow_p, i)));
+#endif
+
+	masterwid = i;
+	if (nasid != XBOW_PORT_NASID(xbow_p, i))
+		return 1;
+
+	for (i = HUB_WIDGET_ID_MIN; i <= HUB_WIDGET_ID_MAX; i++) {
+		if (XBOW_PORT_IS_ENABLED(xbow_p, i) &&
+		    XBOW_PORT_TYPE_IO(xbow_p, i))
+			probe_one_port(nasid, i, masterwid);
+	}
+
+	return 0;
+}
+
+static spinlock_t pcibr_setup_lock = SPIN_LOCK_UNLOCKED;
 
 void __init pcibr_setup(cnodeid_t nid)
 {
-	int 			i, start, num;
-	unsigned long		masterwid;
-	bridge_t 		*bridge;
 	volatile u64 		hubreg;
-	nasid_t	 		nasid, masternasid;
+	nasid_t	 		nasid;
 	xwidget_part_num_t	partnum;
 	widgetreg_t 		widget_id;
-	static spinlock_t	pcibr_setup_lock = SPIN_LOCK_UNLOCKED;
+
+
+	spin_lock(&pcibr_setup_lock);
 
 	/*
 	 * If the master is doing this for headless node, nothing to do.
@@ -132,164 +209,66 @@ void __init pcibr_setup(cnodeid_t nid)
 	 * is selectable by WIDGET_A below.
 	 */
 	if (nid != get_compact_nodeid())
-		return;
-	/*
-	 * find what's on our local node
-	 */
-	spin_lock(&pcibr_setup_lock);
-	start = num_bridges;		/* Remember where we start from */
+		goto out;
+
+	/* find what's on our local node */
 	nasid = COMPACT_TO_NASID_NODEID(nid);
 	hubreg = REMOTE_HUB_L(nasid, IIO_LLP_CSR);
-	if (hubreg & IIO_LLP_CSR_IS_UP) {
-		/* link is up */
-		widget_id = *(volatile widgetreg_t *)
-                        (RAW_NODE_SWIN_BASE(nasid, 0x0) + WIDGET_ID);
-		partnum = XWIDGET_PART_NUM(widget_id);
-		printk("Cpu %d, Nasid 0x%x, pcibr_setup(): found partnum= 0x%x",
-					smp_processor_id(), nasid, partnum);
-		if (partnum == BRIDGE_WIDGET_PART_NUM) {
-			/*
-			 * found direct connected bridge so must be Origin200
-			 */
-			printk("...is bridge\n");
-			num_bridges = 1;
-        		bus_to_wid[0] = 0x8;
-			bus_to_nid[0] = 0;
-			masterwid = 0xa;
-			bus_to_baddr[0] = 0xa100000000000000UL;
-		} else if (partnum == XBOW_WIDGET_PART_NUM) {
-			lboard_t *brd;
-			klxbow_t *xbow_p;
-			/*
-			 * found xbow, so may have multiple bridges
-			 * need to probe xbow
-			 */
-			printk("...is xbow\n");
-
-			if ((brd = find_lboard((lboard_t *)KL_CONFIG_INFO(nasid),
-                                   KLTYPE_MIDPLANE8)) == NULL)
-				printk("argh\n");
-			else
-				printk("brd = 0x%lx\n", (unsigned long) brd);
-			if ((xbow_p = (klxbow_t *)
-			     find_component(brd, NULL, KLSTRUCT_XBOW)) == NULL)
-				printk("argh\n");
-			else {
-			   /*
-			    * Okay, here's a xbow. Lets arbitrate and find
-			    * out if we should initialize it. Set enabled
-			    * hub connected at highest or lowest widget as
-			    * master.
-			    */
-#ifdef WIDGET_A
-			   i = HUB_WIDGET_ID_MAX + 1;
-			   do {
-				i--;
-			   } while ((!XBOW_PORT_TYPE_HUB(xbow_p, i)) ||
-					(!XBOW_PORT_IS_ENABLED(xbow_p, i)));
-#else
-			   i = HUB_WIDGET_ID_MIN - 1;
-			   do {
-				i++;
-			   } while ((!XBOW_PORT_TYPE_HUB(xbow_p, i)) ||
-					(!XBOW_PORT_IS_ENABLED(xbow_p, i)));
-#endif
-			   masterwid = i;
-			   masternasid = XBOW_PORT_NASID(xbow_p, i);
-			   if (nasid == masternasid)
-			   for (i=HUB_WIDGET_ID_MIN; i<=HUB_WIDGET_ID_MAX; i++) {
-				if (!XBOW_PORT_IS_ENABLED(xbow_p, i))
-					continue;
-				if (XBOW_PORT_TYPE_IO(xbow_p, i)) {
-				   widget_id = *(volatile widgetreg_t *)
-                        		   (RAW_NODE_SWIN_BASE(nasid, i) + WIDGET_ID);
-				   partnum = XWIDGET_PART_NUM(widget_id);
-				   if (partnum == BRIDGE_WIDGET_PART_NUM) {
-					printk("widget 0x%x is a bridge\n", i);
-					bus_to_wid[num_bridges] = i;
-					bus_to_nid[num_bridges] = nasid;
-					bus_to_baddr[num_bridges] = ((masterwid << 60) | (1UL << 56));	/* Barrier set */
-					num_bridges++;
-				   }
-				}
-			   }
-			}
-		} else if (partnum == XXBOW_WIDGET_PART_NUM) {
-			/*
-			 * found xbridge, assume ibrick for now
-			 */
-			printk("...is xbridge\n");
-        		bus_to_wid[0] = 0xb;
-        		bus_to_wid[1] = 0xe;
-        		bus_to_wid[2] = 0xf;
-
-        		bus_to_nid[0] = 0;
-        		bus_to_nid[1] = 0;
-        		bus_to_nid[2] = 0;
-
-			bus_to_baddr[0] = 0xa100000000000000UL;
-			bus_to_baddr[1] = 0xa100000000000000UL;
-			bus_to_baddr[2] = 0xa100000000000000UL;
-			masterwid = 0xa;
-			num_bridges = 3;
-		}
-	}
-	num = num_bridges - start;
-	spin_unlock(&pcibr_setup_lock);
-	/*
-         * set bridge registers
-         */
-	for (i = start; i < (start + num); i++) {
-
-		DBG("pcibr_setup: bus= %d  bus_to_wid[%2d]= %d  bus_to_nid[%2d]= %d\n",
-                        i, i, bus_to_wid[i], i, bus_to_nid[i]);
-
-		bus_to_cpu[i] = smp_processor_id();
-		/*
-		 * point to this bridge
-		 */
-		bridge = (bridge_t *) NODE_SWIN_BASE(bus_to_nid[i],bus_to_wid[i]);
-		/*
-	 	 * Clear all pending interrupts.
-	 	 */
-		bridge->b_int_rst_stat = (BRIDGE_IRR_ALL_CLR);
-		/*
-	 	 * Until otherwise set up, assume all interrupts are from slot 0
-	 	 */
-		bridge->b_int_device = (u32) 0x0;
-		/*
-	 	 * swap pio's to pci mem and io space (big windows)
-	 	 */
-		bridge->b_wid_control |= BRIDGE_CTRL_IO_SWAP;
-		bridge->b_wid_control |= BRIDGE_CTRL_MEM_SWAP;
-
-		/*
-		 * Hmm...  IRIX sets additional bits in the address which
-		 * are documented as reserved in the bridge docs.
-		 */
-		bridge->b_int_mode = 0x0;		/* Don't clear ints */
-		bridge->b_wid_int_upper = 0x8000 | (masterwid << 16);
-		bridge->b_wid_int_lower = 0x01800090;	/* PI_INT_PEND_MOD off*/
-		bridge->b_dir_map = (masterwid << 20);	/* DMA */
-		bridge->b_int_enable = 0;
 
-		bridge->b_wid_tflush;     /* wait until Bridge PIO complete */
+	/* check whether the link is up */
+	if (!(hubreg & IIO_LLP_CSR_IS_UP))
+		goto out;
+
+	widget_id = *(volatile widgetreg_t *)
+                       (RAW_NODE_SWIN_BASE(nasid, 0x0) + WIDGET_ID);
+	partnum = XWIDGET_PART_NUM(widget_id);
+
+	printk(KERN_INFO "Cpu %d, Nasid 0x%x: partnum 0x%x is ",
+			smp_processor_id(), nasid, partnum);
+
+	switch (partnum) {
+	case BRIDGE_WIDGET_PART_NUM:
+		bridge_probe(nasid, 0x8, 0xa);
+		break;
+	case XBOW_WIDGET_PART_NUM:
+	case XXBOW_WIDGET_PART_NUM:
+		xbow_probe(nasid);
+		break;
+	default:
+		printk(" unknown widget??\n");
+		break;
 	}
+
+ out:
+	spin_unlock(&pcibr_setup_lock);
 }
 
 extern void ip27_setup_console(void);
 extern void ip27_time_init(void);
 extern void ip27_reboot_setup(void);
 
-void __init ip27_setup(void)
+void __init per_cpu_init(void)
+{
+	cnodeid_t cnode = get_compact_nodeid();
+	int cpu = smp_processor_id();
+
+	clear_c0_status(ST0_IM);
+	per_hub_init(cnode);
+	cpu_time_init();
+	install_ipi();
+	/* Install our NMI handler if symmon hasn't installed one. */
+	install_cpu_nmi_handler(cputoslice(cpu));
+	set_c0_status(SRB_DEV0 | SRB_DEV1);
+}
+
+static int __init ip27_setup(void)
 {
-	nasid_t nid;
 	hubreg_t p, e;
+	nasid_t nid;
 
 	ip27_setup_console();
 	ip27_reboot_setup();
 
-	num_bridges = 0;
 	/*
 	 * hub_rtc init and cpu clock intr enabled for later calibrate_delay.
 	 */
@@ -314,6 +293,11 @@ void __init ip27_setup(void)
 	ioc3_eth_init();
 	per_cpu_init();
 
-	mips_io_port_base = IO_BASE;
+	set_io_port_base(IO_BASE);
+
 	board_time_init = ip27_time_init;
+
+	return 0;
 }
+
+early_initcall(ip27_setup);
--- diff/arch/mips/sgi-ip27/ip27-timer.c	2003-08-20 14:16:25.000000000 +0100
+++ source/arch/mips/sgi-ip27/ip27-timer.c	2004-02-23 13:56:38.000000000 +0000
@@ -13,7 +13,6 @@
 #include <linux/time.h>
 #include <linux/timex.h>
 #include <linux/mm.h>
-#include <linux/bcd.h>
 
 #include <asm/time.h>
 #include <asm/pgtable.h>
@@ -90,10 +89,10 @@ static int set_rtc_mmss(unsigned long no
 	return retval;
 }
 
-void rt_timer_interrupt(struct pt_regs *regs)
+void ip27_rt_timer_interrupt(struct pt_regs *regs)
 {
 	int cpu = smp_processor_id();
-	int cpuA = ((cputoslice(cpu)) == 0);
+	int cpuA = cputoslice(cpu) == 0;
 	int irq = 9;				/* XXX Assign number */
 
 	irq_enter();
@@ -182,12 +181,23 @@ static __init unsigned long get_m48t35_t
         return mktime(year, month, date, hour, min, sec);
 }
 
+static void ip27_timer_setup(struct irqaction *irq)
+{
+	/* over-write the handler, we use our own way */
+	irq->handler = no_action;
+
+	/* setup irqaction */
+//	setup_irq(IP27_TIMER_IRQ, irq);		/* XXX Can't do this yet.  */
+}
+
 void __init ip27_time_init(void)
 {
 	xtime.tv_sec = get_m48t35_time();
 	xtime.tv_nsec = 0;
 
 	do_gettimeoffset = ip27_do_gettimeoffset;
+
+	board_timer_setup = ip27_timer_setup;
 }
 
 void __init cpu_time_init(void)
--- diff/arch/mips/sgi-ip32/Makefile	2003-07-08 09:55:17.000000000 +0100
+++ source/arch/mips/sgi-ip32/Makefile	2004-02-23 13:56:38.000000000 +0000
@@ -3,7 +3,7 @@
 # under Linux.
 #
 
-obj-y	+= ip32-berr.o ip32-rtc.o ip32-setup.o ip32-irq.o ip32-irq-glue.o \
-	   ip32-timer.o crime.o ip32-reset.o
+obj-y	+= ip32-berr.o ip32-irq.o ip32-irq-glue.o ip32-setup.o ip32-timer.o \
+	   crime.o ip32-reset.o
 
 EXTRA_AFLAGS := $(CFLAGS)
--- diff/arch/mips/sgi-ip32/crime.c	2003-08-20 14:16:25.000000000 +0100
+++ source/arch/mips/sgi-ip32/crime.c	2004-02-23 13:56:38.000000000 +0000
@@ -5,92 +5,101 @@
  *
  * Copyright (C) 2001, 2003 Keith M Wesolowski
  */
-#include <asm/ip32/crime.h>
-#include <asm/ptrace.h>
-#include <asm/bootinfo.h>
-#include <asm/page.h>
-#include <asm/mipsregs.h>
 #include <linux/types.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/interrupt.h>
+#include <asm/bootinfo.h>
+#include <asm/mipsregs.h>
+#include <asm/ptrace.h>
+#include <asm/page.h>
+#include <asm/ip32/crime.h>
+#include <asm/ip32/mace.h>
+
+void *sgi_crime;
+struct sgi_mace *mace;
 
-void __init crime_init (void)
+void __init crime_init(void)
 {
-	u64 id = crime_read_64 (CRIME_ID);
-	u64 rev = id & CRIME_ID_REV;
+	unsigned int id, rev;
+	const int field = 2 * sizeof(unsigned long);
+	
+	sgi_crime = ioremap(CRIME_BASE, 1);
+	mace = ioremap(MACE_BASE, sizeof(struct sgi_mace));
 
+	id = crime_read(CRIME_ID);
+	rev = id & CRIME_ID_REV;
 	id = (id & CRIME_ID_IDBITS) >> 4;
 
-	printk ("CRIME id %1lx rev %ld detected at 0x%016lx\n", id, rev,
-		(unsigned long) CRIME_BASE);
+	printk (KERN_INFO "CRIME id %1x rev %d at 0x%0*lx\n",
+		id, rev, field, (unsigned long) CRIME_BASE);
 }
 
-irqreturn_t crime_memerr_intr (unsigned int irq, void *dev_id, struct pt_regs *regs)
+irqreturn_t
+crime_memerr_intr (unsigned int irq, void *dev_id, struct pt_regs *regs)
 {
-	u64 memerr = crime_read_64 (CRIME_MEM_ERROR_STAT);
-	u64 addr = crime_read_64 (CRIME_MEM_ERROR_ADDR);
+	unsigned long stat, addr;
 	int fatal = 0;
 
-	memerr &= CRIME_MEM_ERROR_STAT_MASK;
-	addr &= CRIME_MEM_ERROR_ADDR_MASK;
+	stat = crime_read(CRIME_MEM_ERROR_STAT) & CRIME_MEM_ERROR_STAT_MASK;
+	addr = crime_read(CRIME_MEM_ERROR_ADDR) & CRIME_MEM_ERROR_ADDR_MASK;
 
-	printk("CRIME memory error at 0x%08lx ST 0x%08lx<", addr, memerr);
+	printk("CRIME memory error at 0x%08lx ST 0x%08lx<", addr, stat);
 
-	if (memerr & CRIME_MEM_ERROR_INV)
+	if (stat & CRIME_MEM_ERROR_INV)
 		printk("INV,");
-	if (memerr & CRIME_MEM_ERROR_ECC) {
-		u64 ecc_syn = crime_read_64(CRIME_MEM_ERROR_ECC_SYN);
-		u64 ecc_gen = crime_read_64(CRIME_MEM_ERROR_ECC_CHK);
-
-		ecc_syn &= CRIME_MEM_ERROR_ECC_SYN_MASK;
-		ecc_gen &= CRIME_MEM_ERROR_ECC_CHK_MASK;
+	if (stat & CRIME_MEM_ERROR_ECC) {
+		unsigned long ecc_syn = crime_read(CRIME_MEM_ERROR_ECC_SYN) &
+					CRIME_MEM_ERROR_ECC_SYN_MASK;
+		unsigned long ecc_gen = crime_read(CRIME_MEM_ERROR_ECC_CHK) &
+					CRIME_MEM_ERROR_ECC_CHK_MASK;
 
 		printk("ECC,SYN=0x%08lx,GEN=0x%08lx,", ecc_syn, ecc_gen);
 	}
-	if (memerr & CRIME_MEM_ERROR_MULTIPLE) {
+	if (stat & CRIME_MEM_ERROR_MULTIPLE) {
 		fatal = 1;
 		printk("MULTIPLE,");
 	}
-	if (memerr & CRIME_MEM_ERROR_HARD_ERR) {
+	if (stat & CRIME_MEM_ERROR_HARD_ERR) {
 		fatal = 1;
 		printk("HARD,");
 	}
-	if (memerr & CRIME_MEM_ERROR_SOFT_ERR)
+	if (stat & CRIME_MEM_ERROR_SOFT_ERR)
 		printk("SOFT,");
-	if (memerr & CRIME_MEM_ERROR_CPU_ACCESS)
+	if (stat & CRIME_MEM_ERROR_CPU_ACCESS)
 		printk("CPU,");
-	if (memerr & CRIME_MEM_ERROR_VICE_ACCESS)
+	if (stat & CRIME_MEM_ERROR_VICE_ACCESS)
 		printk("VICE,");
-	if (memerr & CRIME_MEM_ERROR_GBE_ACCESS)
+	if (stat & CRIME_MEM_ERROR_GBE_ACCESS)
 		printk("GBE,");
-	if (memerr & CRIME_MEM_ERROR_RE_ACCESS)
-		printk("RE,REID=0x%02lx,", (memerr & CRIME_MEM_ERROR_RE_ID)>>8);
-	if (memerr & CRIME_MEM_ERROR_MACE_ACCESS)
-		printk("MACE,MACEID=0x%02lx,", memerr & CRIME_MEM_ERROR_MACE_ID);
+	if (stat & CRIME_MEM_ERROR_RE_ACCESS)
+		printk("RE,REID=0x%02lx,", (stat & CRIME_MEM_ERROR_RE_ID)>>8);
+	if (stat & CRIME_MEM_ERROR_MACE_ACCESS)
+		printk("MACE,MACEID=0x%02lx,", stat & CRIME_MEM_ERROR_MACE_ID);
 
-	crime_write_64 (CRIME_MEM_ERROR_STAT, 0);
+	crime_write(0, CRIME_MEM_ERROR_STAT);
 
 	if (fatal) {
 		printk("FATAL>\n");
-		panic("Fatal memory error detected, halting\n");
-	} else {
+		panic("Fatal memory error.");
+	} else
 		printk("NONFATAL>\n");
-	}
 
 	return IRQ_HANDLED;
 }
 
-irqreturn_t crime_cpuerr_intr (unsigned int irq, void *dev_id, struct pt_regs *regs)
+irqreturn_t
+crime_cpuerr_intr (unsigned int irq, void *dev_id, struct pt_regs *regs)
 {
-	u64 cpuerr = crime_read_64 (CRIME_CPU_ERROR_STAT);
-	u64 addr = crime_read_64 (CRIME_CPU_ERROR_ADDR);
-	cpuerr &= CRIME_CPU_ERROR_MASK;
-	addr <<= 2UL;
+	unsigned long stat = crime_read(CRIME_CPU_ERROR_STAT) &
+			     CRIME_CPU_ERROR_MASK;
+	uint64_t addr = crime_read(CRIME_CPU_ERROR_ADDR) &
+			CRIME_CPU_ERROR_ADDR_MASK;
+	addr <<= 2;
+
+	printk ("CRIME CPU error at 0x%09lx status 0x%08lx\n", addr, stat);
 
-	printk ("CRIME CPU error detected at 0x%09lx status 0x%08lx\n",
-		addr, cpuerr);
+	crime_write(0, CRIME_CPU_ERROR_STAT);
 
-	crime_write_64 (CRIME_CPU_ERROR_STAT, 0);
 	return IRQ_HANDLED;
 }
--- diff/arch/mips/sgi-ip32/ip32-irq-glue.S	2003-07-08 09:55:17.000000000 +0100
+++ source/arch/mips/sgi-ip32/ip32-irq-glue.S	2004-02-23 13:56:38.000000000 +0000
@@ -13,7 +13,6 @@
 #include <asm/mipsregs.h>
 #include <asm/stackframe.h>
 #include <asm/addrspace.h>
-#include <asm/ip32/ip32_ints.h>
 
 		.text
 		.set    noreorder
--- diff/arch/mips/sgi-ip32/ip32-irq.c	2003-08-20 14:16:25.000000000 +0100
+++ source/arch/mips/sgi-ip32/ip32-irq.c	2004-02-23 13:56:38.000000000 +0000
@@ -22,15 +22,18 @@
 
 #include <asm/bitops.h>
 #include <asm/mipsregs.h>
+#include <asm/signal.h>
 #include <asm/system.h>
-#include <asm/ip32/ip32_ints.h>
 #include <asm/ip32/crime.h>
 #include <asm/ip32/mace.h>
-#include <asm/signal.h>
+#include <asm/ip32/ip32_ints.h>
 
 /* issue a PIO read to make sure no PIO writes are pending */
-#define flush_crime_bus() crime_read_64(CRIME_CONTROL);
-#define flush_mace_bus() mace_read_64(MACEISA_FLASH_NIC_REG);
+#define flush_crime_bus() crime_read(CRIME_CONTROL);
+static void inline flush_mace_bus(void)
+{
+	volatile unsigned long junk = mace_perif_ctrl_read(misc);
+}
 
 #undef DEBUG_IRQ
 #ifdef DEBUG_IRQ
@@ -54,16 +57,16 @@
  *
  * CRIME_INT_STAT 31:0:
  *
- * 0 -> 1 Video in 1
- * 1 -> 2 Video in 2
- * 2 -> 3 Video out
- * 3 -> 4 Mace ethernet
- * 4 -> S  SuperIO sub-interrupt
- * 5 -> M  Miscellaneous sub-interrupt
- * 6 -> A  Audio sub-interrupt
- * 7 -> 8  PCI bridge errors
- * 8 -> 9  PCI SCSI aic7xxx 0
- * 9 -> 10  PCI SCSI aic7xxx 1
+ * 0  -> 1  Video in 1
+ * 1  -> 2  Video in 2
+ * 2  -> 3  Video out
+ * 3  -> 4  Mace ethernet
+ * 4  -> S  SuperIO sub-interrupt
+ * 5  -> M  Miscellaneous sub-interrupt
+ * 6  -> A  Audio sub-interrupt
+ * 7  -> 8  PCI bridge errors
+ * 8  -> 9  PCI SCSI aic7xxx 0
+ * 9  -> 10 PCI SCSI aic7xxx 1
  * 10 -> 11 PCI slot 0
  * 11 -> 12 unused (PCI slot 1)
  * 12 -> 13 unused (PCI slot 2)
@@ -82,9 +85,9 @@
  * 25 -> 26 RE empty level
  * 26 -> 27 RE full level
  * 27 -> 28 RE idle level
- * 28 -> 29  unused (software 0) (E)
- * 29 -> 30  unused (software 1) (E)
- * 30 -> 31  unused (software 2) - crime 1.5 CPU SysCorError (E)
+ * 28 -> 29 unused (software 0) (E)
+ * 29 -> 30 unused (software 1) (E)
+ * 30 -> 31 unused (software 2) - crime 1.5 CPU SysCorError (E)
  * 31 -> 32 VICE
  *
  * S, M, A: Use the MACE ISA interrupt register
@@ -106,20 +109,24 @@
  * is quite different anyway.
  */
 
+/*
+ * IRQ spinlock - Ralf says not to disable CPU interrupts,
+ * and I think he knows better.
+ */
+static spinlock_t ip32_irq_lock = SPIN_LOCK_UNLOCKED;
+
 /* Some initial interrupts to set up */
 extern irqreturn_t crime_memerr_intr (int irq, void *dev_id,
-			       struct pt_regs *regs);
+				      struct pt_regs *regs);
 extern irqreturn_t crime_cpuerr_intr (int irq, void *dev_id,
-			       struct pt_regs *regs);
+				      struct pt_regs *regs);
 
 struct irqaction memerr_irq = { crime_memerr_intr, SA_INTERRUPT,
-			       0, "CRIME memory error", NULL,
-			       NULL };
+				0, "CRIME memory error", NULL, NULL };
 struct irqaction cpuerr_irq = { crime_cpuerr_intr, SA_INTERRUPT,
-			       0, "CRIME CPU error", NULL,
-			       NULL };
+				0, "CRIME CPU error", NULL, NULL };
 
-extern void ip32_handle_int (void);
+extern void ip32_handle_int(void);
 
 /*
  * For interrupts wired from a single device to the CPU.  Only the clock
@@ -144,7 +151,7 @@ static void disable_cpu_irq(unsigned int
 
 static void end_cpu_irq(unsigned int irq)
 {
-	if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
+	if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS)))
 		enable_cpu_irq (irq);
 }
 
@@ -167,21 +174,20 @@ static struct hw_interrupt_type ip32_cpu
  * We get to split the register in half and do faster lookups.
  */
 
-static u64 crime_mask=0;
+static uint64_t crime_mask;
 
 static void enable_crime_irq(unsigned int irq)
 {
 	unsigned long flags;
 
-	local_irq_save(flags);
+	spin_lock_irqsave(&ip32_irq_lock, flags);
 	crime_mask |= 1 << (irq - 1);
-	crime_write_64(CRIME_INT_MASK, crime_mask);
-	local_irq_restore(flags);
+	crime_write(crime_mask, CRIME_INT_MASK);
+	spin_unlock_irqrestore(&ip32_irq_lock, flags);
 }
 
 static unsigned int startup_crime_irq(unsigned int irq)
 {
-        crime_mask = crime_read_64(CRIME_INT_MASK);
 	enable_crime_irq(irq);
 	return 0; /* This is probably not right; we could have pending irqs */
 }
@@ -190,14 +196,14 @@ static void disable_crime_irq(unsigned i
 {
 	unsigned long flags;
 
-	local_irq_save(flags);
+	spin_lock_irqsave(&ip32_irq_lock, flags);
 	crime_mask &= ~(1 << (irq - 1));
-	crime_write_64(CRIME_INT_MASK, crime_mask);
+	crime_write(crime_mask, CRIME_INT_MASK);
 	flush_crime_bus();
-	local_irq_restore(flags);
+	spin_unlock_irqrestore(&ip32_irq_lock, flags);
 }
 
-static void mask_and_ack_crime_irq (unsigned int irq)
+static void mask_and_ack_crime_irq(unsigned int irq)
 {
 	unsigned long flags;
 
@@ -205,20 +211,20 @@ static void mask_and_ack_crime_irq (unsi
 	if ((irq >= CRIME_GBE0_IRQ && irq <= CRIME_GBE3_IRQ)
 	    || (irq >= CRIME_RE_EMPTY_E_IRQ && irq <= CRIME_RE_IDLE_E_IRQ)
 	    || (irq >= CRIME_SOFT0_IRQ && irq <= CRIME_SOFT2_IRQ)) {
-	        u64 crime_int;
-		local_irq_save(flags);
-		crime_int = crime_read_64(CRIME_HARD_INT);
+	        uint64_t crime_int;
+		spin_lock_irqsave(&ip32_irq_lock, flags);
+		crime_int = crime_read(CRIME_HARD_INT);
 		crime_int &= ~(1 << (irq - 1));
-		crime_write_64(CRIME_HARD_INT, crime_int);
-		local_irq_restore(flags);
+		crime_write(crime_int, CRIME_HARD_INT);
+		spin_unlock_irqrestore(&ip32_irq_lock, flags);
 	}
 	disable_crime_irq(irq);
 }
 
 static void end_crime_irq(unsigned int irq)
 {
-	if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
-		enable_crime_irq (irq);
+	if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS)))
+		enable_crime_irq(irq);
 }
 
 #define shutdown_crime_irq disable_crime_irq
@@ -240,24 +246,22 @@ static struct hw_interrupt_type ip32_cri
  * next chunk of the CRIME register in one piece.
  */
 
-static u32 macepci_mask;
+static unsigned long macepci_mask;
 
 static void enable_macepci_irq(unsigned int irq)
 {
 	unsigned long flags;
 
-	local_irq_save(flags);
+	spin_lock_irqsave(&ip32_irq_lock, flags);
 	macepci_mask |= MACEPCI_CONTROL_INT(irq - 9);
-	mace_write_32(MACEPCI_CONTROL, macepci_mask);
-        crime_mask |= 1 << (irq - 1);
-        crime_write_64(CRIME_INT_MASK, crime_mask);
-	local_irq_restore(flags);
+	mace->pci.control = macepci_mask;
+	crime_mask |= 1 << (irq - 1);
+	crime_write(crime_mask, CRIME_INT_MASK);
+	spin_unlock_irqrestore(&ip32_irq_lock, flags);
 }
 
 static unsigned int startup_macepci_irq(unsigned int irq)
 {
-	crime_mask = crime_read_64 (CRIME_INT_MASK);
-	macepci_mask = mace_read_32(MACEPCI_CONTROL);
   	enable_macepci_irq (irq);
 	return 0;
 }
@@ -266,20 +270,20 @@ static void disable_macepci_irq(unsigned
 {
 	unsigned long flags;
 
-	local_irq_save(flags);
+	spin_lock_irqsave(&ip32_irq_lock, flags);
 	crime_mask &= ~(1 << (irq - 1));
-	crime_write_64(CRIME_INT_MASK, crime_mask);
+	crime_write(crime_mask, CRIME_INT_MASK);
 	flush_crime_bus();
 	macepci_mask &= ~MACEPCI_CONTROL_INT(irq - 9);
-	mace_write_32(MACEPCI_CONTROL, macepci_mask);
+	mace->pci.control = macepci_mask;
 	flush_mace_bus();
-	local_irq_restore(flags);
+	spin_unlock_irqrestore(&ip32_irq_lock, flags);
 }
 
 static void end_macepci_irq(unsigned int irq)
 {
 	if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
-		enable_macepci_irq (irq);
+		enable_macepci_irq(irq);
 }
 
 #define shutdown_macepci_irq disable_macepci_irq
@@ -300,7 +304,40 @@ static struct hw_interrupt_type ip32_mac
  * CRIME register.
  */
 
-u32 maceisa_mask = 0;
+#define MACEISA_AUDIO_INT	(MACEISA_AUDIO_SW_INT |		\
+				 MACEISA_AUDIO_SC_INT |		\
+				 MACEISA_AUDIO1_DMAT_INT |	\
+				 MACEISA_AUDIO1_OF_INT |	\
+				 MACEISA_AUDIO2_DMAT_INT |	\
+				 MACEISA_AUDIO2_MERR_INT |	\
+				 MACEISA_AUDIO3_DMAT_INT |	\
+				 MACEISA_AUDIO3_MERR_INT)
+#define MACEISA_MISC_INT	(MACEISA_RTC_INT |		\
+				 MACEISA_KEYB_INT |		\
+				 MACEISA_KEYB_POLL_INT |	\
+				 MACEISA_MOUSE_INT |		\
+				 MACEISA_MOUSE_POLL_INT |	\
+				 MACEISA_TIMER0_INT |		\
+				 MACEISA_TIMER1_INT |		\
+				 MACEISA_TIMER2_INT)
+#define MACEISA_SUPERIO_INT	(MACEISA_PARALLEL_INT |		\
+				 MACEISA_PAR_CTXA_INT |		\
+				 MACEISA_PAR_CTXB_INT |		\
+				 MACEISA_PAR_MERR_INT |		\
+				 MACEISA_SERIAL1_INT |		\
+				 MACEISA_SERIAL1_TDMAT_INT |	\
+				 MACEISA_SERIAL1_TDMAPR_INT |	\
+				 MACEISA_SERIAL1_TDMAME_INT |	\
+				 MACEISA_SERIAL1_RDMAT_INT |	\
+				 MACEISA_SERIAL1_RDMAOR_INT |	\
+				 MACEISA_SERIAL2_INT |		\
+				 MACEISA_SERIAL2_TDMAT_INT |	\
+				 MACEISA_SERIAL2_TDMAPR_INT |	\
+				 MACEISA_SERIAL2_TDMAME_INT |	\
+				 MACEISA_SERIAL2_RDMAT_INT |	\
+				 MACEISA_SERIAL2_RDMAOR_INT)
+
+static unsigned long maceisa_mask;
 
 static void enable_maceisa_irq (unsigned int irq)
 {
@@ -320,19 +357,17 @@ static void enable_maceisa_irq (unsigned
 		crime_int = MACE_SUPERIO_INT;
 		break;
 	}
-	DBG ("crime_int %016lx enabled\n", crime_int);
-	local_irq_save(flags);
+	DBG ("crime_int %08x enabled\n", crime_int);
+	spin_lock_irqsave(&ip32_irq_lock, flags);
 	crime_mask |= crime_int;
-	crime_write_64(CRIME_INT_MASK, crime_mask);
+	crime_write(crime_mask, CRIME_INT_MASK);
 	maceisa_mask |= 1 << (irq - 33);
-	mace_write_32(MACEISA_INT_MASK, maceisa_mask);
-	local_irq_restore(flags);
+	mace_perif_ctrl_write(maceisa_mask, imask);
+	spin_unlock_irqrestore(&ip32_irq_lock, flags);
 }
 
-static unsigned int startup_maceisa_irq (unsigned int irq)
+static unsigned int startup_maceisa_irq(unsigned int irq)
 {
-	crime_mask = crime_read_64 (CRIME_INT_MASK);
-	maceisa_mask = mace_read_32(MACEISA_INT_MASK);
 	enable_maceisa_irq(irq);
 	return 0;
 }
@@ -342,7 +377,7 @@ static void disable_maceisa_irq(unsigned
 	unsigned int crime_int = 0;
 	unsigned long flags;
 
-	local_irq_save(flags);
+	spin_lock_irqsave(&ip32_irq_lock, flags);
 	maceisa_mask &= ~(1 << (irq - 33));
         if(!(maceisa_mask & MACEISA_AUDIO_INT))
 		crime_int |= MACE_AUDIO_INT;
@@ -351,28 +386,27 @@ static void disable_maceisa_irq(unsigned
         if(!(maceisa_mask & MACEISA_SUPERIO_INT))
 		crime_int |= MACE_SUPERIO_INT;
 	crime_mask &= ~crime_int;
-	crime_write_64(CRIME_INT_MASK, crime_mask);
+	crime_write(crime_mask, CRIME_INT_MASK);
 	flush_crime_bus();
-	mace_write_32(MACEISA_INT_MASK, maceisa_mask);
+	mace_perif_ctrl_write(maceisa_mask, imask);
 	flush_mace_bus();
-	local_irq_restore(flags);
+	spin_unlock_irqrestore(&ip32_irq_lock, flags);
 }
 
 static void mask_and_ack_maceisa_irq(unsigned int irq)
 {
-	u32 mace_int;
-	unsigned long flags;
+	unsigned long mace_int, flags;
 
 	switch (irq) {
 	case MACEISA_PARALLEL_IRQ:
 	case MACEISA_SERIAL1_TDMAPR_IRQ:
 	case MACEISA_SERIAL2_TDMAPR_IRQ:
 		/* edge triggered */
-		local_irq_save(flags);
-		mace_int = mace_read_32(MACEISA_INT_STAT);
+		spin_lock_irqsave(&ip32_irq_lock, flags);
+		mace_int = mace_perif_ctrl_read(istat);
 		mace_int &= ~(1 << (irq - 33));
-		mace_write_32(MACEISA_INT_STAT, mace_int);
-		local_irq_restore(flags);
+		mace_perif_ctrl_write(mace_int, istat);
+		spin_unlock_irqrestore(&ip32_irq_lock, flags);
 		break;
 	}
 	disable_maceisa_irq(irq);
@@ -380,8 +414,8 @@ static void mask_and_ack_maceisa_irq(uns
 
 static void end_maceisa_irq(unsigned irq)
 {
-	if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
-		enable_maceisa_irq (irq);
+	if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS)))
+		enable_maceisa_irq(irq);
 }
 
 #define shutdown_maceisa_irq disable_maceisa_irq
@@ -405,15 +439,14 @@ static void enable_mace_irq(unsigned int
 {
 	unsigned long flags;
 
-	local_irq_save(flags);
+	spin_lock_irqsave(&ip32_irq_lock, flags);
 	crime_mask |= 1 << (irq - 1);
-	crime_write_64 (CRIME_INT_MASK, crime_mask);
-	local_irq_restore (flags);
+	crime_write(crime_mask, CRIME_INT_MASK);
+	spin_unlock_irqrestore(&ip32_irq_lock, flags);
 }
 
 static unsigned int startup_mace_irq(unsigned int irq)
 {
-        crime_mask = crime_read_64 (CRIME_INT_MASK);
 	enable_mace_irq(irq);
 	return 0;
 }
@@ -422,17 +455,17 @@ static void disable_mace_irq(unsigned in
 {
 	unsigned long flags;
 
-	local_irq_save(flags);
+	spin_lock_irqsave(&ip32_irq_lock, flags);
 	crime_mask &= ~(1 << (irq - 1));
-	crime_write_64 (CRIME_INT_MASK, crime_mask);
+	crime_write(crime_mask, CRIME_INT_MASK);
 	flush_crime_bus();
-	local_irq_restore(flags);
+	spin_unlock_irqrestore(&ip32_irq_lock, flags);
 }
 
 static void end_mace_irq(unsigned int irq)
 {
 	if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
-		enable_mace_irq (irq);
+		enable_mace_irq(irq);
 }
 
 #define shutdown_mace_irq disable_mace_irq
@@ -449,28 +482,22 @@ static struct hw_interrupt_type ip32_mac
 	NULL
 };
 
-static void ip32_unknown_interrupt (struct pt_regs *regs)
+static void ip32_unknown_interrupt(struct pt_regs *regs)
 {
-	u64 crime;
-	u32 mace;
+	uint64_t crime;
 
 	printk ("Unknown interrupt occurred!\n");
-	printk ("cp0_status: %08x\n",
-		read_c0_status ());
-	printk ("cp0_cause: %08x\n",
-		read_c0_cause ());
-	crime = crime_read_64 (CRIME_INT_MASK);
-	printk ("CRIME interrupt mask: %016lx\n", crime);
-	crime = crime_read_64 (CRIME_INT_STAT);
-	printk ("CRIME interrupt status: %016lx\n", crime);
-	crime = crime_read_64 (CRIME_HARD_INT);
-	printk ("CRIME hardware interrupt register: %016lx\n", crime);
-	mace = mace_read_32 (MACEISA_INT_MASK);
-	printk ("MACE ISA interrupt mask: %08x\n", mace);
-	mace = mace_read_32 (MACEISA_INT_STAT);
-	printk ("MACE ISA interrupt status: %08x\n", mace);
-	mace = mace_read_32 (MACEPCI_CONTROL);
-	printk ("MACE PCI control register: %08x\n", mace);
+	printk ("cp0_status: %08x\n", read_c0_status());
+	printk ("cp0_cause: %08x\n", read_c0_cause());
+	crime = crime_read(CRIME_INT_MASK);
+	printk ("CRIME intr mask: %016lx\n", crime);
+	crime = crime_read(CRIME_INT_STAT);
+	printk ("CRIME intr status: %016lx\n", crime);
+	crime = crime_read(CRIME_HARD_INT);
+	printk ("CRIME hardware intr register: %016lx\n", crime);
+	printk ("MACE ISA intr mask: %08lx\n", mace_perif_ctrl_read(imask));
+	printk ("MACE ISA intr status: %08lx\n", mace_perif_ctrl_read(istat));
+	printk ("MACE PCI control register: %08x\n", mace->pci.control);
 
 	printk("Register dump:\n");
 	show_regs(regs);
@@ -481,18 +508,19 @@ static void ip32_unknown_interrupt (stru
 }
 
 /* CRIME 1.1 appears to deliver all interrupts to this one pin. */
+/* change this to loop over all edge-triggered irqs, exception masked out ones */
 void ip32_irq0(struct pt_regs *regs)
 {
-	u64 crime_int;
+	uint64_t crime_int;
 	int irq = 0;
 
-	crime_int = crime_read_64(CRIME_INT_STAT) & crime_mask;
-        irq = ffs(crime_int);
-        crime_int = 1ULL << (irq - 1);
+	crime_int = crime_read(CRIME_INT_STAT) & crime_mask;
+	irq = ffs(crime_int);
+	crime_int = 1 << (irq - 1);
 
 	if (crime_int & CRIME_MACEISA_INT_MASK) {
-		u32 mace_int = mace_read_32 (MACEISA_INT_STAT) & maceisa_mask;
-                irq = ffs (mace_int) + 32;
+		unsigned long mace_int = mace_perif_ctrl_read(istat);
+		irq = ffs(mace_int & maceisa_mask) + 32;
 	}
 	DBG("*irq %u*\n", irq);
 	do_IRQ(irq, regs);
@@ -500,51 +528,43 @@ void ip32_irq0(struct pt_regs *regs)
 
 void ip32_irq1(struct pt_regs *regs)
 {
-	ip32_unknown_interrupt (regs);
+	ip32_unknown_interrupt(regs);
 }
 
 void ip32_irq2(struct pt_regs *regs)
 {
-	ip32_unknown_interrupt (regs);
+	ip32_unknown_interrupt(regs);
 }
 
 void ip32_irq3(struct pt_regs *regs)
 {
-	ip32_unknown_interrupt (regs);
+	ip32_unknown_interrupt(regs);
 }
 
 void ip32_irq4(struct pt_regs *regs)
 {
-	ip32_unknown_interrupt (regs);
+	ip32_unknown_interrupt(regs);
 }
 
 void ip32_irq5(struct pt_regs *regs)
 {
-	do_IRQ (CLOCK_IRQ, regs);
+	do_IRQ(CLOCK_IRQ, regs);
 }
 
 void __init init_IRQ(void)
 {
 	unsigned int irq;
-	int i;
 
+	init_generic_irq();
 	/* Install our interrupt handler, then clear and disable all
-	 * CRIME and MACE interrupts.
-	 */
-	crime_write_64(CRIME_INT_MASK, 0);
-	crime_write_64(CRIME_HARD_INT, 0);
-	crime_write_64(CRIME_SOFT_INT, 0);
-	mace_write_32(MACEISA_INT_STAT, 0);
-	mace_write_32(MACEISA_INT_MASK, 0);
+	 * CRIME and MACE interrupts. */
+	crime_write(0, CRIME_INT_MASK);
+	crime_write(0, CRIME_HARD_INT);
+	crime_write(0, CRIME_SOFT_INT);
+	mace_perif_ctrl_write(0, istat);
+	mace_perif_ctrl_write(0, imask);
 	set_except_vector(0, ip32_handle_int);
 
-	for (i = 0; i < NR_IRQS; i++) {
-		irq_desc[i].status  = IRQ_DISABLED;
-		irq_desc[i].action  = NULL;
-		irq_desc[i].depth   = 1;
-		irq_desc[i].handler = &no_irq_type;
-	}
-
 	for (irq = 0; irq <= IP32_IRQ_MAX; irq++) {
 		hw_irq_controller *controller;
 
--- diff/arch/mips/sgi-ip32/ip32-reset.c	2003-08-20 14:16:25.000000000 +0100
+++ source/arch/mips/sgi-ip32/ip32-reset.c	2004-02-23 13:56:38.000000000 +0000
@@ -16,13 +16,13 @@
 #include <linux/ds17287rtc.h>
 #include <linux/interrupt.h>
 
+#include <asm/addrspace.h>
 #include <asm/irq.h>
 #include <asm/reboot.h>
-#include <asm/sgialib.h>
-#include <asm/addrspace.h>
-#include <asm/types.h>
 #include <asm/system.h>
 #include <asm/wbflush.h>
+#include <asm/ip32/mace.h>
+#include <asm/ip32/crime.h>
 #include <asm/ip32/ip32_ints.h>
 
 #define POWERDOWN_TIMEOUT	120
@@ -33,7 +33,7 @@
 #define PANIC_FREQ		(HZ / 8)
 
 static struct timer_list power_timer, blink_timer, debounce_timer;
-static int shuting_down = 0, has_paniced = 0;
+static int has_paniced, shuting_down;
 
 static void ip32_machine_restart(char *command) __attribute__((noreturn));
 static void ip32_machine_halt(void) __attribute__((noreturn));
@@ -41,16 +41,13 @@ static void ip32_machine_power_off(void)
 
 static void ip32_machine_restart(char *cmd)
 {
-	if (shuting_down)
-		ip32_machine_power_off();
-	ArcReboot();
+	crime_write(CRIME_CONTROL_HARD_RESET, CRIME_CONTROL);
+	while (1);
 }
 
 static inline void ip32_machine_halt(void)
 {
-	if (shuting_down)
-		ip32_machine_power_off();
-	ArcEnterInteractiveMode();
+	ip32_machine_power_off();
 }
 
 static void ip32_machine_power_off(void)
@@ -76,10 +73,7 @@ static void ip32_machine_power_off(void)
 	CMOS_WRITE(xctrl_a | DS_XCTRL4A_PAB, DS_B1_XCTRL4A);
 	CMOS_WRITE(reg_a, RTC_REG_A);
 	wbflush();
-
-	while(1) {
-	  	printk(KERN_DEBUG "Power off!\n");
-	}
+	while (1);
 }
 
 static void power_timeout(unsigned long data)
@@ -89,35 +83,33 @@ static void power_timeout(unsigned long 
 
 static void blink_timeout(unsigned long data)
 {
-	u64 mc_led =  mace_read_64(MACEISA_FLASH_NIC_REG);
-
-	mc_led ^= MACEISA_LED_RED;
-	mace_write_64(MACEISA_FLASH_NIC_REG, mc_led);
+	unsigned long led = mace_perif_ctrl_read(misc) ^ MACEISA_LED_RED;
+	mace_perif_ctrl_write(led, misc);
 	mod_timer(&blink_timer, jiffies+data);
 }
 
 static void debounce(unsigned long data)
 {
-	volatile unsigned char reg_a,reg_c,xctrl_a;
+	volatile unsigned char reg_a, reg_c, xctrl_a;
 
 	reg_c = CMOS_READ(RTC_INTR_FLAGS);
 	CMOS_WRITE(reg_a | DS_REGA_DV0, RTC_REG_A);
 	wbflush();
 	xctrl_a = CMOS_READ(DS_B1_XCTRL4A);
-	if( (xctrl_a & DS_XCTRL4A_IFS ) || ( reg_c & RTC_IRQF ) ) {
+	if ((xctrl_a & DS_XCTRL4A_IFS) || (reg_c & RTC_IRQF )) {
 		/* Interrupt still being sent. */
 		debounce_timer.expires = jiffies + 50;
 		add_timer(&debounce_timer);
 
 		/* clear interrupt source */
-		CMOS_WRITE( xctrl_a & ~DS_XCTRL4A_IFS, DS_B1_XCTRL4A);
+		CMOS_WRITE(xctrl_a & ~DS_XCTRL4A_IFS, DS_B1_XCTRL4A);
 		CMOS_WRITE(reg_a & ~DS_REGA_DV0, RTC_REG_A);
 		return;
 	}
 	CMOS_WRITE(reg_a & ~DS_REGA_DV0, RTC_REG_A);
 
 	if (has_paniced)
-		ArcReboot();
+		ip32_machine_restart(NULL);
 
 	enable_irq(MACEISA_RTC_IRQ);
 }
@@ -147,7 +139,7 @@ static irqreturn_t ip32_rtc_int(int irq,
 	volatile unsigned char reg_c;
 
 	reg_c = CMOS_READ(RTC_INTR_FLAGS);
-	if( ! (reg_c & RTC_IRQF) ) {
+	if (!(reg_c & RTC_IRQF)) {
 		printk(KERN_WARNING 
 			"%s: RTC IRQ without RTC_IRQF\n", __FUNCTION__);
 	}
@@ -164,18 +156,17 @@ static irqreturn_t ip32_rtc_int(int irq,
 }
 
 static int panic_event(struct notifier_block *this, unsigned long event,
-                      void *ptr)
+		       void *ptr)
 {
-	u64 mc_led;
+	unsigned long led;
 
 	if (has_paniced)
 		return NOTIFY_DONE;
 	has_paniced = 1;
 
 	/* turn off the green LED */
-	mc_led = mace_read_64(MACEISA_FLASH_NIC_REG);
-	mc_led |= MACEISA_LED_GREEN;
-	mace_write_64(MACEISA_FLASH_NIC_REG, mc_led);
+	led = mace_perif_ctrl_read(misc) | MACEISA_LED_GREEN;
+	mace_perif_ctrl_write(led, misc);
 
 	blink_timer.data = PANIC_FREQ;
 	blink_timeout(PANIC_FREQ);
@@ -189,7 +180,11 @@ static struct notifier_block panic_block
 
 static __init int ip32_reboot_setup(void)
 {
-	u64 mc_led =  mace_read_64(MACEISA_FLASH_NIC_REG);
+	/* turn on the green led only */
+	unsigned long led = mace_perif_ctrl_read(misc);
+	led |= MACEISA_LED_RED;
+	led &= ~MACEISA_LED_GREEN;
+	mace_perif_ctrl_write(led, misc);
 
 	_machine_restart = ip32_machine_restart;
 	_machine_halt = ip32_machine_halt;
@@ -199,11 +194,6 @@ static __init int ip32_reboot_setup(void
 	blink_timer.function = blink_timeout;
 	notifier_chain_register(&panic_notifier_list, &panic_block);
 
-	/* turn on the green led only */
-	mc_led |= MACEISA_LED_RED;
-	mc_led &= ~MACEISA_LED_GREEN;
-	mace_write_64(MACEISA_FLASH_NIC_REG, mc_led);
-
 	return 0;
 }
 
--- diff/arch/mips/sgi-ip32/ip32-setup.c	2003-08-20 14:16:25.000000000 +0100
+++ source/arch/mips/sgi-ip32/ip32-setup.c	2004-02-23 13:56:38.000000000 +0000
@@ -6,29 +6,26 @@
  * for more details.
  *
  * Copyright (C) 2000 Harald Koerfgen
+ * Copyright (C) 2002, 03 Ilya A. Volynets
  */
 #include <linux/config.h>
 #include <linux/sched.h>
 #include <linux/interrupt.h>
-#include <linux/mc146818rtc.h>
 #include <linux/param.h>
 #include <linux/init.h>
+#include <linux/console.h>
 
 #include <asm/time.h>
 #include <asm/mipsregs.h>
 #include <asm/bootinfo.h>
 #include <asm/mmu_context.h>
-#include <asm/ip32/crime.h>
-#include <asm/ip32/mace.h>
-#include <asm/ip32/ip32_ints.h>
 #include <asm/sgialib.h>
 #include <asm/traps.h>
-
-extern struct rtc_ops ip32_rtc_ops;
-extern u32 cc_interval;
+#include <asm/io.h>
+#include <asm/ip32/mace.h>
+#include <asm/ip32/ip32_ints.h>
 
 #ifdef CONFIG_SGI_O2MACE_ETH
-
 /*
  * This is taken care of in here 'cause they say using Arc later on is
  * problematic
@@ -60,44 +57,83 @@ static inline void str2eaddr(unsigned ch
 #endif
 
 extern void ip32_time_init(void);
-extern void ip32_be_init(void);                                                
-extern void __init ip32_timer_setup (struct irqaction *irq);                   
-extern void __init crime_init (void);                                          
+extern void ip32_be_init(void);
+extern void __init ip32_timer_setup (struct irqaction *irq);
+extern void __init crime_init (void);
+
+#ifdef CONFIG_SERIAL_8250
+#include <linux/tty.h>
+#include <linux/serial.h>
+#include <linux/serial_core.h>
+extern int __init early_serial_setup(struct uart_port *port);
+
+#define STD_COM_FLAGS (ASYNC_SKIP_TEST)
+#define BASE_BAUD (1843200 / 16)
 
+#endif /* CONFIG_SERIAL_8250 */
 
-void __init ip32_setup(void)
+static int __init ip32_setup(void)
 {
-#ifdef CONFIG_SERIAL_CONSOLE
-	char *ctype;
-#endif
-	TLBMISS_HANDLER_SETUP ();
+	set_io_port_base((unsigned long) ioremap(MACEPCI_LOW_IO, 0x2000000));
+
+	crime_init();
 
-	mips_io_port_base = UNCACHEDADDR(MACEPCI_HI_IO);;
+#ifdef CONFIG_SERIAL_8250
+ 	{
+		static struct uart_port o2_serial[2];
+
+		memset(o2_serial, 0, sizeof(o2_serial));
+		o2_serial[0].type	= PORT_16550A;
+		o2_serial[0].line	= 0;
+		o2_serial[0].irq	= MACEISA_SERIAL1_IRQ;
+		o2_serial[0].flags	= STD_COM_FLAGS | UPF_RESOURCES;
+		o2_serial[0].uartclk	= BASE_BAUD * 16;
+		o2_serial[0].iotype	= UPIO_MEM;
+		o2_serial[0].membase	= (char *)&mace->isa.serial1;
+		o2_serial[0].fifosize	= 14;
+                /* How much to shift register offset by. Each UART register
+		 * is replicated over 256 byte space */
+		o2_serial[0].regshift	= 8;
+		o2_serial[1].type	= PORT_16550A;
+		o2_serial[1].line	= 1;
+		o2_serial[1].irq	= MACEISA_SERIAL2_IRQ;
+		o2_serial[1].flags	= STD_COM_FLAGS | UPF_RESOURCES;
+		o2_serial[1].uartclk	= BASE_BAUD * 16;
+		o2_serial[1].iotype	= UPIO_MEM;
+		o2_serial[1].membase	= (char *)&mace->isa.serial2;
+		o2_serial[1].fifosize	= 14;
+		o2_serial[1].regshift	= 8;
 
-#ifdef CONFIG_SERIAL_CONSOLE
-	ctype = ArcGetEnvironmentVariable("console");
-	if (*ctype == 'd') {
-		if (ctype[1] == '2')
-			console_setup ("ttyS1");
-		else
-			console_setup ("ttyS0");
+		early_serial_setup(&o2_serial[0]);
+		early_serial_setup(&o2_serial[1]);
 	}
 #endif
 #ifdef CONFIG_SGI_O2MACE_ETH
 	{
-		char *mac=ArcGetEnvironmentVariable("eaddr");
+		char *mac = ArcGetEnvironmentVariable("eaddr");
 		str2eaddr(o2meth_eaddr, mac);
 	}
 #endif
 
-#ifdef CONFIG_VT
-	conswitchp = &dummy_con;
+#if defined(CONFIG_SERIAL_CORE_CONSOLE)
+	{
+		char* con = ArcGetEnvironmentVariable("console");
+		if (con && *con == 'd') {
+			static char options[8];
+			char *baud = ArcGetEnvironmentVariable("dbaud");
+			if (baud)
+				strcpy(options, baud);
+			add_preferred_console("ttyS", *(con + 1) == '2' ? 1 : 0,
+					      baud ? options : NULL);
+		}
+	}
 #endif
 
-	rtc_ops = &ip32_rtc_ops;
 	board_be_init = ip32_be_init;
 	board_time_init = ip32_time_init;
 	board_timer_setup = ip32_timer_setup;
 
-	crime_init();
+	return 0;
 }
+
+early_initcall(ip32_setup);
--- diff/arch/mips/sgi-ip32/ip32-timer.c	2003-08-20 14:16:25.000000000 +0100
+++ source/arch/mips/sgi-ip32/ip32-timer.c	2004-02-23 13:56:38.000000000 +0000
@@ -16,18 +16,18 @@
 #include <linux/string.h>
 #include <linux/interrupt.h>
 #include <linux/kernel_stat.h>
-#include <linux/mc146818rtc.h>
 #include <linux/timex.h>
 
 #include <asm/mipsregs.h>
 #include <asm/param.h>
-#include <asm/ip32/crime.h>
-#include <asm/ip32/ip32_ints.h>
 #include <asm/bootinfo.h>
 #include <asm/cpu.h>
-#include <asm/mipsregs.h>
 #include <asm/io.h>
 #include <asm/irq.h>
+#include <asm/ip32/crime.h>
+#include <asm/ip32/ip32_ints.h>
+
+#include <linux/mc146818rtc.h>
 
 extern volatile unsigned long wall_jiffies;
 
@@ -47,23 +47,25 @@ static unsigned int timerhi, timerlo;
 
 static irqreturn_t cc_timer_interrupt(int irq, void *dev_id, struct pt_regs * regs);
 
-void __init ip32_timer_setup (struct irqaction *irq)
+static inline uint64_t crime_time(void)
 {
-	u64 crime_time;
-	u32 cc_tick;
+	return crime_read(CRIME_TIMER) & CRIME_TIMER_MASK;
+}
 
+void __init ip32_timer_setup (struct irqaction *irq)
+{
+	uint64_t time;
+	unsigned int cc_tick;
 
 	write_c0_count(0);
 	irq->handler = cc_timer_interrupt;
 
 	printk("Calibrating system timer... ");
 
-	crime_time = crime_read_64(CRIME_TIME) & CRIME_TIME_MASK;
+	time = crime_time();
 	cc_tick = read_c0_count();
 
-	while ((crime_read_64 (CRIME_TIME) & CRIME_TIME_MASK) - crime_time
-		< WAIT_MS * 1000000 / CRIME_NS_PER_TICK)
-		;
+	while (crime_time() - time < WAIT_MS * 1000000 / CRIME_NS_PER_TICK) ;
 	cc_tick = read_c0_count() - cc_tick;
 	cc_interval = cc_tick / HZ * (1000 / WAIT_MS);
 	/*
@@ -75,7 +77,7 @@ void __init ip32_timer_setup (struct irq
 
 	printk("%d MHz CPU detected\n", (int) (cc_interval / PER_MHZ));
 
-	setup_irq (CLOCK_IRQ, irq);
+	setup_irq(CLOCK_IRQ, irq);
 #define ALLINTS (IE_IRQ0 | IE_IRQ1 | IE_IRQ2 | IE_IRQ3 | IE_IRQ4 | IE_IRQ5)
 	/* Set ourselves up for future interrupts */
 	write_c0_compare(read_c0_count() + cc_interval);
@@ -85,7 +87,7 @@ void __init ip32_timer_setup (struct irq
 
 static irqreturn_t cc_timer_interrupt(int irq, void *dev_id, struct pt_regs * regs)
 {
-	u32 count;
+	unsigned int count;
 
 	/*
 	 * The cycle counter is only 32 bit which is good for about
--- diff/arch/mips/sibyte/cfe/console.c	2003-09-17 12:28:02.000000000 +0100
+++ source/arch/mips/sibyte/cfe/console.c	2004-02-23 13:56:38.000000000 +0000
@@ -1,5 +1,5 @@
+#include <linux/config.h>
 #include <linux/init.h>
-#include <linux/major.h>
 #include <linux/errno.h>
 #include <linux/console.h>
 
@@ -41,12 +41,6 @@ static void cfe_console_write(struct con
 			
 }
 
-static struct tty_driver *cfe_console_device(struct console *c, int *index)
-{
-	*index = -1;
-	return NULL;
-}
-
 static int cfe_console_setup(struct console *cons, char *str)
 {
 	char consdev[32];
@@ -72,7 +66,6 @@ static int cfe_console_setup(struct cons
 static struct console sb1250_cfe_cons = {
 	.name		= "cfe",
 	.write		= cfe_console_write,
-	.device		= cfe_console_device,
 	.setup		= cfe_console_setup,
 	.flags		= CON_PRINTBUFFER,
 	.index		= -1,
--- diff/arch/mips/sibyte/cfe/setup.c	2003-08-20 14:16:25.000000000 +0100
+++ source/arch/mips/sibyte/cfe/setup.c	2004-02-23 13:56:38.000000000 +0000
@@ -51,17 +51,11 @@ phys_t board_mem_region_addrs[SIBYTE_MAX
 phys_t board_mem_region_sizes[SIBYTE_MAX_MEM_REGIONS];
 unsigned int board_mem_region_count;
 
-/* This is the kernel command line.  Actually, it's
-   copied, eventually, to command_line, and looks to be
-   quite redundant.  But not something to fix just now */
-extern char arcs_cmdline[];
-
 int cfe_cons_handle;
 
-#ifdef CONFIG_EMBEDDED_RAMDISK
-/* These are symbols defined by the ramdisk linker script */
-extern unsigned char __rd_start;
-extern unsigned char __rd_end;
+#ifdef CONFIG_BLK_DEV_INITRD
+extern unsigned long initrd_start, initrd_end;
+extern void * __rd_start, * __rd_end;
 #endif
 
 #ifdef CONFIG_SMP
@@ -191,6 +185,8 @@ static int __init initrd_setup(char *str
 {
 	char rdarg[64];
 	int idx;
+	char *tmp, *endptr;
+	unsigned long initrd_size;
 
 	/* Make a copy of the initrd argument so we can smash it up here */
 	for (idx = 0; idx < sizeof(rdarg)-1; idx++) {
@@ -205,8 +201,6 @@ static int __init initrd_setup(char *str
 	 *Initrd location comes in the form "<hex size of ramdisk in bytes>@<location in memory>"
 	 *  e.g. initrd=3abfd@80010000.  This is set up by the loader.
 	 */
-	char *tmp, *endptr;
-	unsigned long initrd_size;
 	for (tmp = str; *tmp != '@'; tmp++) {
 		if (!*tmp) {
 			goto fail;
@@ -240,12 +234,15 @@ static int __init initrd_setup(char *str
 #endif
 
 /*
- * prom_init is called just after the cpu type is determined, from init_arch()
+ * prom_init is called just after the cpu type is determined, from setup_arch()
  */
-__init int prom_init(int argc, char **argv, char **envp, int *prom_vec)
+void __init prom_init(void)
 {
 	uint64_t cfe_ept, cfe_handle;
 	unsigned int cfe_eptseal;
+	int argc = fw_arg0;
+	char **envp = (char **) fw_arg2;
+	int *prom_vec = (int *) fw_arg3;
 #ifdef CONFIG_KGDB
 	char *arg;
 #endif
@@ -345,13 +342,12 @@ __init int prom_init(int argc, char **ar
 
 	mips_machgroup = MACH_GROUP_SIBYTE;
 	prom_meminit();
-
-	return 0;
 }
 
-void prom_free_prom_memory(void)
+unsigned long __init prom_free_prom_memory(void)
 {
 	/* Not sure what I'm supposed to do here.  Nothing, I think */
+	return 0;
 }
 
 void prom_putchar(char c)
--- diff/arch/mips/sibyte/cfe/smp.c	2003-08-26 10:00:52.000000000 +0100
+++ source/arch/mips/sibyte/cfe/smp.c	2004-02-23 13:56:38.000000000 +0000
@@ -16,64 +16,82 @@
  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  */
 
+#include <linux/init.h>
 #include <linux/sched.h>
 #include <linux/smp.h>
-
-#include <asm/mipsregs.h>
+#include <asm/processor.h>
 
 #include "cfe_api.h"
 #include "cfe_error.h"
 
-extern void asmlinkage smp_bootstrap(void);
-
-/* Boot all other cpus in the system, initialize them, and
-   bring them into the boot fn */
-int prom_boot_secondary(int cpu, unsigned long sp, unsigned long gp)
+/*
+ * Use CFE to find out how many CPUs are available, setting up
+ * phys_cpu_present_map and the logical/physical mappings.
+ * XXXKW will the boot CPU ever not be physical 0?
+ */
+void __init prom_build_cpu_map(void)
 {
-	int retval;
-	
-	retval = cfe_cpu_start(cpu, &smp_bootstrap, sp, gp, 0);
-	if (retval != 0) {
-		printk("cfe_start_cpu(%i) returned %i\n" , cpu, retval);
-		return 0;
-	} else {
-		return 1;
+	int i, num;
+
+	cpus_clear(phys_cpu_present_map);
+	cpu_set(0, phys_cpu_present_map);
+	__cpu_number_map[0] = 0;
+	__cpu_logical_map[0] = 0;
+
+	for (i=1, num=0; i<NR_CPUS; i++) {
+		if (cfe_cpu_stop(i) == 0) {
+			cpu_set(i, phys_cpu_present_map);
+			__cpu_number_map[i] = ++num;
+			__cpu_logical_map[num] = i;
+		}
 	}
+	printk("Detected %i available secondary CPU(s)\n", num);
 }
 
-void prom_init_secondary(void)
+/*
+ * Common setup before any secondaries are started
+ */
+void prom_prepare_cpus(unsigned int max_cpus)
 {
-	extern void load_mmu(void);
-	unsigned int imask = STATUSF_IP4 | STATUSF_IP3 | STATUSF_IP2 |
-		STATUSF_IP1 | STATUSF_IP0;
-
-	/* Enable basic interrupts */
-	change_c0_status(ST0_IM, imask);
-	set_c0_status(ST0_IE);
-
-	/* cache and TLB setup */
-	load_mmu();
 }
 
 /*
- * Set up state, return the total number of cpus in the system, including
- * the master
+ * Setup the PC, SP, and GP of a secondary processor and start it
+ * running!
  */
-void prom_setup_smp(void)
+void prom_boot_secondary(int cpu, struct task_struct *idle)
 {
-	int i;
+	int retval;
+	
+	retval = cfe_cpu_start(cpu_logical_map(cpu), &smp_bootstrap,
+			       __KSTK_TOS(idle),
+			       (unsigned long)idle->thread_info, 0);
+	if (retval != 0)
+		printk("cfe_start_cpu(%i) returned %i\n" , cpu, retval);
+}
 
-	/* Use CFE to find out how many CPUs are available */
-	for (i=1; i<NR_CPUS; i++) {
-		if (cfe_cpu_stop(i) == 0) {
-			cpu_set(i, cpu_online_map);
-		}
-	}
-	printk("Detected %i available CPU(s)\n", num_online_cpus());
+/*
+ * Code to run on secondary just after probing the CPU
+ */
+void prom_init_secondary(void)
+{
+	extern void sb1250_smp_init(void);
+	sb1250_smp_init();
 }
 
+/*
+ * Do any tidying up before marking online and running the idle
+ * loop
+ */
 void prom_smp_finish(void)
 {
 	extern void sb1250_smp_finish(void);
 	sb1250_smp_finish();
 }
+
+/*
+ * Final cleanup after all secondaries booted
+ */
+void prom_cpus_done(void)
+{
+}
--- diff/arch/mips/sibyte/sb1250/bcm1250_tbprof.c	2003-09-17 12:28:02.000000000 +0100
+++ source/arch/mips/sibyte/sb1250/bcm1250_tbprof.c	2004-02-23 13:56:38.000000000 +0000
@@ -29,7 +29,6 @@
 #include <linux/errno.h>
 #include <linux/reboot.h>
 #include <asm/uaccess.h>
-#include <asm/smplock.h>
 #include <asm/io.h>
 #include <asm/sibyte/sb1250.h>
 #include <asm/sibyte/sb1250_regs.h>
@@ -65,8 +64,8 @@ static void arm_tb(void)
 	u_int64_t tb_options = M_SCD_TRACE_CFG_FREEZE_FULL;
 	/* Generate an SCD_PERFCNT interrupt in TB_PERIOD Zclks to
 	   trigger start of trace.  XXX vary sampling period */
-	__raw_writeq(0, KSEG1 + A_SCD_PERF_CNT_1);
-	scdperfcnt = __raw_readq(KSEG1 + A_SCD_PERF_CNT_CFG);
+	__raw_writeq(0, IOADDR(A_SCD_PERF_CNT_1));
+	scdperfcnt = __raw_readq(IOADDR(A_SCD_PERF_CNT_CFG));
 	/* Unfortunately, in Pass 2 we must clear all counters to knock down
 	   a previous interrupt request.  This means that bus profiling
 	   requires ALL of the SCD perf counters. */
@@ -74,15 +73,15 @@ static void arm_tb(void)
 		   M_SPC_CFG_ENABLE |		 // enable counting
 		   M_SPC_CFG_CLEAR |		 // clear all counters
 		   V_SPC_CFG_SRC1(1),		 // counter 1 counts cycles
-	      KSEG1 + A_SCD_PERF_CNT_CFG);
-	__raw_writeq(next, KSEG1 + A_SCD_PERF_CNT_1);
+	      IOADDR(A_SCD_PERF_CNT_CFG));
+	__raw_writeq(next, IOADDR(A_SCD_PERF_CNT_1));
 	/* Reset the trace buffer */
-	__raw_writeq(M_SCD_TRACE_CFG_RESET, KSEG1 + A_SCD_TRACE_CFG);
+	__raw_writeq(M_SCD_TRACE_CFG_RESET, IOADDR(A_SCD_TRACE_CFG));
 #if 0 && defined(M_SCD_TRACE_CFG_FORCECNT)
 	/* XXXKW may want to expose control to the data-collector */
 	tb_options |= M_SCD_TRACE_CFG_FORCECNT;
 #endif
-	__raw_writeq(tb_options, KSEG1 + A_SCD_TRACE_CFG);
+	__raw_writeq(tb_options, IOADDR(A_SCD_TRACE_CFG));
 	sbp.tb_armed = 1;
 }
 
@@ -94,22 +93,22 @@ static irqreturn_t sbprof_tb_intr(int ir
 		/* XXX should use XKPHYS to make writes bypass L2 */
 		u_int64_t *p = sbp.sbprof_tbbuf[sbp.next_tb_sample++];
 		/* Read out trace */
-		__raw_writeq(M_SCD_TRACE_CFG_START_READ, KSEG1 + A_SCD_TRACE_CFG);
+		__raw_writeq(M_SCD_TRACE_CFG_START_READ, IOADDR(A_SCD_TRACE_CFG));
 		__asm__ __volatile__ ("sync" : : : "memory");
 		/* Loop runs backwards because bundles are read out in reverse order */
 		for (i = 256 * 6; i > 0; i -= 6) {
 			// Subscripts decrease to put bundle in the order
 			//   t0 lo, t0 hi, t1 lo, t1 hi, t2 lo, t2 hi
-			p[i-1] = __raw_readq(KSEG1 + A_SCD_TRACE_READ); // read t2 hi
-			p[i-2] = __raw_readq(KSEG1 + A_SCD_TRACE_READ); // read t2 lo
-			p[i-3] = __raw_readq(KSEG1 + A_SCD_TRACE_READ); // read t1 hi
-			p[i-4] = __raw_readq(KSEG1 + A_SCD_TRACE_READ); // read t1 lo
-			p[i-5] = __raw_readq(KSEG1 + A_SCD_TRACE_READ); // read t0 hi
-			p[i-6] = __raw_readq(KSEG1 + A_SCD_TRACE_READ); // read t0 lo
+			p[i-1] = __raw_readq(IOADDR(A_SCD_TRACE_READ)); // read t2 hi
+			p[i-2] = __raw_readq(IOADDR(A_SCD_TRACE_READ)); // read t2 lo
+			p[i-3] = __raw_readq(IOADDR(A_SCD_TRACE_READ)); // read t1 hi
+			p[i-4] = __raw_readq(IOADDR(A_SCD_TRACE_READ)); // read t1 lo
+			p[i-5] = __raw_readq(IOADDR(A_SCD_TRACE_READ)); // read t0 hi
+			p[i-6] = __raw_readq(IOADDR(A_SCD_TRACE_READ)); // read t0 lo
 		}
 		if (!sbp.tb_enable) {
 			DBG(printk(DEVNAME ": tb_intr shutdown\n"));
-			__raw_writeq(M_SCD_TRACE_CFG_RESET, KSEG1 + A_SCD_TRACE_CFG);
+			__raw_writeq(M_SCD_TRACE_CFG_RESET, IOADDR(A_SCD_TRACE_CFG));
 			sbp.tb_armed = 0;
 			wake_up(&sbp.tb_sync);
 		} else {
@@ -118,7 +117,7 @@ static irqreturn_t sbprof_tb_intr(int ir
 	} else {
 		/* No more trace buffer samples */
 		DBG(printk(DEVNAME ": tb_intr full\n"));
-		__raw_writeq(M_SCD_TRACE_CFG_RESET, KSEG1 + A_SCD_TRACE_CFG);
+		__raw_writeq(M_SCD_TRACE_CFG_RESET, IOADDR(A_SCD_TRACE_CFG));
 		sbp.tb_armed = 0;
 		if (!sbp.tb_enable) {
 			wake_up(&sbp.tb_sync);
@@ -134,7 +133,7 @@ static irqreturn_t sbprof_pc_intr(int ir
 	return IRQ_NONE;
 }
 
-static int sbprof_zbprof_start(struct file *filp)
+int sbprof_zbprof_start(struct file *filp)
 {
 	u_int64_t scdperfcnt;
 
@@ -152,13 +151,13 @@ static int sbprof_zbprof_start(struct fi
 		return -EBUSY;
 	}
 	/* Make sure there isn't a perf-cnt interrupt waiting */
-	scdperfcnt = __raw_readq(KSEG1 + A_SCD_PERF_CNT_CFG);
+	scdperfcnt = __raw_readq(IOADDR(A_SCD_PERF_CNT_CFG));
 	/* Disable and clear counters, override SRC_1 */
 	__raw_writeq((scdperfcnt & ~(M_SPC_CFG_SRC1 | M_SPC_CFG_ENABLE)) |
 		   M_SPC_CFG_ENABLE |
 		   M_SPC_CFG_CLEAR |
 		   V_SPC_CFG_SRC1(1),
-	      KSEG1 + A_SCD_PERF_CNT_CFG);
+	      IOADDR(A_SCD_PERF_CNT_CFG));
 
 	/* We grab this interrupt to prevent others from trying to use
            it, even though we don't want to service the interrupts
@@ -173,51 +172,51 @@ static int sbprof_zbprof_start(struct fi
 	   pass them through.  I am exploiting my knowledge that
 	   cp0_status masks out IP[5]. krw */
 	__raw_writeq(K_INT_MAP_I3,
-	      KSEG1 + A_IMR_REGISTER(0, R_IMR_INTERRUPT_MAP_BASE) + (K_INT_PERF_CNT<<3));
+		     IOADDR(A_IMR_REGISTER(0, R_IMR_INTERRUPT_MAP_BASE) + (K_INT_PERF_CNT<<3)));
 
 	/* Initialize address traps */
-	__raw_writeq(0, KSEG1 + A_ADDR_TRAP_UP_0);
-	__raw_writeq(0, KSEG1 + A_ADDR_TRAP_UP_1);
-	__raw_writeq(0, KSEG1 + A_ADDR_TRAP_UP_2);
-	__raw_writeq(0, KSEG1 + A_ADDR_TRAP_UP_3);
-
-	__raw_writeq(0, KSEG1 + A_ADDR_TRAP_DOWN_0);
-	__raw_writeq(0, KSEG1 + A_ADDR_TRAP_DOWN_1);
-	__raw_writeq(0, KSEG1 + A_ADDR_TRAP_DOWN_2);
-	__raw_writeq(0, KSEG1 + A_ADDR_TRAP_DOWN_3);
-
-	__raw_writeq(0, KSEG1 + A_ADDR_TRAP_CFG_0);
-	__raw_writeq(0, KSEG1 + A_ADDR_TRAP_CFG_1);
-	__raw_writeq(0, KSEG1 + A_ADDR_TRAP_CFG_2);
-	__raw_writeq(0, KSEG1 + A_ADDR_TRAP_CFG_3);
+	__raw_writeq(0, IOADDR(A_ADDR_TRAP_UP_0));
+	__raw_writeq(0, IOADDR(A_ADDR_TRAP_UP_1));
+	__raw_writeq(0, IOADDR(A_ADDR_TRAP_UP_2));
+	__raw_writeq(0, IOADDR(A_ADDR_TRAP_UP_3));
+
+	__raw_writeq(0, IOADDR(A_ADDR_TRAP_DOWN_0));
+	__raw_writeq(0, IOADDR(A_ADDR_TRAP_DOWN_1));
+	__raw_writeq(0, IOADDR(A_ADDR_TRAP_DOWN_2));
+	__raw_writeq(0, IOADDR(A_ADDR_TRAP_DOWN_3));
+
+	__raw_writeq(0, IOADDR(A_ADDR_TRAP_CFG_0));
+	__raw_writeq(0, IOADDR(A_ADDR_TRAP_CFG_1));
+	__raw_writeq(0, IOADDR(A_ADDR_TRAP_CFG_2));
+	__raw_writeq(0, IOADDR(A_ADDR_TRAP_CFG_3));
 
 	/* Initialize Trace Event 0-7 */
 	//				when interrupt
-	__raw_writeq(M_SCD_TREVT_INTERRUPT, KSEG1 + A_SCD_TRACE_EVENT_0);
-	__raw_writeq(0, KSEG1 + A_SCD_TRACE_EVENT_1);
-	__raw_writeq(0, KSEG1 + A_SCD_TRACE_EVENT_2);
-	__raw_writeq(0, KSEG1 + A_SCD_TRACE_EVENT_3);
-	__raw_writeq(0, KSEG1 + A_SCD_TRACE_EVENT_4);
-	__raw_writeq(0, KSEG1 + A_SCD_TRACE_EVENT_5);
-	__raw_writeq(0, KSEG1 + A_SCD_TRACE_EVENT_6);
-	__raw_writeq(0, KSEG1 + A_SCD_TRACE_EVENT_7);
+	__raw_writeq(M_SCD_TREVT_INTERRUPT, IOADDR(A_SCD_TRACE_EVENT_0));
+	__raw_writeq(0, IOADDR(A_SCD_TRACE_EVENT_1));
+	__raw_writeq(0, IOADDR(A_SCD_TRACE_EVENT_2));
+	__raw_writeq(0, IOADDR(A_SCD_TRACE_EVENT_3));
+	__raw_writeq(0, IOADDR(A_SCD_TRACE_EVENT_4));
+	__raw_writeq(0, IOADDR(A_SCD_TRACE_EVENT_5));
+	__raw_writeq(0, IOADDR(A_SCD_TRACE_EVENT_6));
+	__raw_writeq(0, IOADDR(A_SCD_TRACE_EVENT_7));
 
 	/* Initialize Trace Sequence 0-7 */
 	//				     Start on event 0 (interrupt)
 	__raw_writeq(V_SCD_TRSEQ_FUNC_START|0x0fff,
-	      KSEG1 + A_SCD_TRACE_SEQUENCE_0);
+		     IOADDR(A_SCD_TRACE_SEQUENCE_0));
 	//			  dsamp when d used | asamp when a used
 	__raw_writeq(M_SCD_TRSEQ_ASAMPLE|M_SCD_TRSEQ_DSAMPLE|K_SCD_TRSEQ_TRIGGER_ALL,
-	      KSEG1 + A_SCD_TRACE_SEQUENCE_1);
-	__raw_writeq(0, KSEG1 + A_SCD_TRACE_SEQUENCE_2);
-	__raw_writeq(0, KSEG1 + A_SCD_TRACE_SEQUENCE_3);
-	__raw_writeq(0, KSEG1 + A_SCD_TRACE_SEQUENCE_4);
-	__raw_writeq(0, KSEG1 + A_SCD_TRACE_SEQUENCE_5);
-	__raw_writeq(0, KSEG1 + A_SCD_TRACE_SEQUENCE_6);
-	__raw_writeq(0, KSEG1 + A_SCD_TRACE_SEQUENCE_7);
+		     IOADDR(A_SCD_TRACE_SEQUENCE_1));
+	__raw_writeq(0, IOADDR(A_SCD_TRACE_SEQUENCE_2));
+	__raw_writeq(0, IOADDR(A_SCD_TRACE_SEQUENCE_3));
+	__raw_writeq(0, IOADDR(A_SCD_TRACE_SEQUENCE_4));
+	__raw_writeq(0, IOADDR(A_SCD_TRACE_SEQUENCE_5));
+	__raw_writeq(0, IOADDR(A_SCD_TRACE_SEQUENCE_6));
+	__raw_writeq(0, IOADDR(A_SCD_TRACE_SEQUENCE_7));
 
 	/* Now indicate the PERF_CNT interrupt as a trace-relevant interrupt */
-	__raw_writeq((1ULL << K_INT_PERF_CNT), KSEG1 + A_IMR_REGISTER(0, R_IMR_INTERRUPT_TRACE));
+	__raw_writeq((1ULL << K_INT_PERF_CNT), IOADDR(A_IMR_REGISTER(0, R_IMR_INTERRUPT_TRACE)));
 
 	arm_tb();
 
@@ -226,7 +225,7 @@ static int sbprof_zbprof_start(struct fi
 	return 0;
 }
 
-static int sbprof_zbprof_stop(void)
+int sbprof_zbprof_stop(void)
 {
 	DBG(printk(DEVNAME ": stopping\n"));
 
--- diff/arch/mips/sibyte/sb1250/bus_watcher.c	2003-08-20 14:16:25.000000000 +0100
+++ source/arch/mips/sibyte/sb1250/bus_watcher.c	2004-02-23 13:56:38.000000000 +0000
@@ -25,6 +25,7 @@
  * /proc/bus_watcher if PROC_FS is on.
  */
 
+#include <linux/config.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/interrupt.h>
@@ -80,10 +81,10 @@ void check_bus_watcher(void)
 
 #ifdef CONFIG_SB1_PASS_1_WORKAROUNDS
 	/* Destructive read, clears register and interrupt */
-	status = csr_in32(IO_SPACE_BASE | A_SCD_BUS_ERR_STATUS);
+	status = csr_in32(IOADDR(A_SCD_BUS_ERR_STATUS));
 #else
 	/* Use non-destructive register */
-	status = csr_in32(IO_SPACE_BASE | A_SCD_BUS_ERR_STATUS_DEBUG);
+	status = csr_in32(IOADDR(A_SCD_BUS_ERR_STATUS_DEBUG));
 #endif
 	if (!(status & 0x7fffffff)) {
 		printk("Using last values reaped by bus watcher driver\n");
@@ -91,8 +92,8 @@ void check_bus_watcher(void)
 		l2_err = bw_stats.l2_err;
 		memio_err = bw_stats.memio_err;
 	} else {
-		l2_err = csr_in32(IO_SPACE_BASE | A_BUS_L2_ERRORS);
-		memio_err = csr_in32(IO_SPACE_BASE | A_BUS_MEM_IO_ERRORS);
+		l2_err = csr_in32(IOADDR(A_BUS_L2_ERRORS));
+		memio_err = csr_in32(IOADDR(A_BUS_MEM_IO_ERRORS));
 	}
 	if (status & ~(1UL << 31))
 		print_summary(status, l2_err, memio_err);
@@ -175,31 +176,46 @@ static irqreturn_t sibyte_bw_int(int irq
 {
 	struct bw_stats_struct *stats = data;
 	unsigned long cntr;
+#ifdef CONFIG_SIBYTE_BW_TRACE
+	int i;
+#endif
 #ifndef CONFIG_PROC_FS
 	char bw_buf[1024];
 #endif
 
+#ifdef CONFIG_SIBYTE_BW_TRACE
+	csr_out32(M_SCD_TRACE_CFG_FREEZE, IOADDR(A_SCD_TRACE_CFG));
+	csr_out32(M_SCD_TRACE_CFG_START_READ, IOADDR(A_SCD_TRACE_CFG));
+
+	for (i=0; i<256*6; i++)
+		printk("%016llx\n", (unsigned long long)__raw_readq(IOADDR(A_SCD_TRACE_READ)));
+
+	csr_out32(M_SCD_TRACE_CFG_RESET, IOADDR(A_SCD_TRACE_CFG));
+	csr_out32(M_SCD_TRACE_CFG_START, IOADDR(A_SCD_TRACE_CFG));
+#endif
+
 	/* Destructive read, clears register and interrupt */
-	stats->status = csr_in32(IO_SPACE_BASE | A_SCD_BUS_ERR_STATUS);
+	stats->status = csr_in32(IOADDR(A_SCD_BUS_ERR_STATUS));
 	stats->status_printed = 0;
 
-	stats->l2_err = cntr = csr_in32(IO_SPACE_BASE | A_BUS_L2_ERRORS);
+	stats->l2_err = cntr = csr_in32(IOADDR(A_BUS_L2_ERRORS));
 	stats->l2_cor_d += G_SCD_L2ECC_CORR_D(cntr);
 	stats->l2_bad_d += G_SCD_L2ECC_BAD_D(cntr);
 	stats->l2_cor_t += G_SCD_L2ECC_CORR_T(cntr);
 	stats->l2_bad_t += G_SCD_L2ECC_BAD_T(cntr);
-	csr_out32(0, IO_SPACE_BASE | A_BUS_L2_ERRORS);
+	csr_out32(0, IOADDR(A_BUS_L2_ERRORS));
 
-	stats->memio_err = cntr = csr_in32(IO_SPACE_BASE | A_BUS_MEM_IO_ERRORS);
+	stats->memio_err = cntr = csr_in32(IOADDR(A_BUS_MEM_IO_ERRORS));
 	stats->mem_cor_d += G_SCD_MEM_ECC_CORR(cntr);
 	stats->mem_bad_d += G_SCD_MEM_ECC_BAD(cntr);
 	stats->bus_error += G_SCD_MEM_BUSERR(cntr);
-	csr_out32(0, IO_SPACE_BASE | A_BUS_MEM_IO_ERRORS);
+	csr_out32(0, IOADDR(A_BUS_MEM_IO_ERRORS));
 
 #ifndef CONFIG_PROC_FS
 	bw_print_buffer(bw_buf, stats);
 	printk(bw_buf);
 #endif
+
 	return IRQ_HANDLED;
 }
 
@@ -228,6 +244,14 @@ int __init sibyte_bus_watcher(void)
 	create_proc_decoder(&bw_stats);
 #endif
 
+#ifdef CONFIG_SIBYTE_BW_TRACE
+	csr_out32((M_SCD_TRSEQ_ASAMPLE | M_SCD_TRSEQ_DSAMPLE |
+		   K_SCD_TRSEQ_TRIGGER_ALL),
+		  IOADDR(A_SCD_TRACE_SEQUENCE_0));
+	csr_out32(M_SCD_TRACE_CFG_RESET, IOADDR(A_SCD_TRACE_CFG));
+	csr_out32(M_SCD_TRACE_CFG_START, IOADDR(A_SCD_TRACE_CFG));
+#endif
+
 	return 0;
 }
 
--- diff/arch/mips/sibyte/sb1250/irq.c	2003-08-20 14:16:25.000000000 +0100
+++ source/arch/mips/sibyte/sb1250/irq.c	2004-02-23 13:56:38.000000000 +0000
@@ -64,9 +64,6 @@ extern unsigned long ldt_eoi_space;
 #include <asm/gdb-stub.h>
 extern void breakpoint(void);
 static int kgdb_irq;
-#ifdef CONFIG_GDB_CONSOLE
-extern void register_gdb_console(void);
-#endif
 
 /* kgdb is on when configured.  Pass "nokgdb" kernel arg to turn it off */
 static int kgdb_flag = 1;
@@ -110,9 +107,9 @@ void sb1250_mask_irq(int cpu, int irq)
 	u64 cur_ints;
 
 	spin_lock_irqsave(&sb1250_imr_lock, flags);
-	cur_ints = ____raw_readq(KSEG1 + A_IMR_MAPPER(cpu) + R_IMR_INTERRUPT_MASK);
+	cur_ints = ____raw_readq(IOADDR(A_IMR_MAPPER(cpu) + R_IMR_INTERRUPT_MASK));
 	cur_ints |= (((u64) 1) << irq);
-	____raw_writeq(cur_ints, KSEG1 + A_IMR_MAPPER(cpu) + R_IMR_INTERRUPT_MASK);
+	____raw_writeq(cur_ints, IOADDR(A_IMR_MAPPER(cpu) + R_IMR_INTERRUPT_MASK));
 	spin_unlock_irqrestore(&sb1250_imr_lock, flags);
 }
 
@@ -122,9 +119,9 @@ void sb1250_unmask_irq(int cpu, int irq)
 	u64 cur_ints;
 
 	spin_lock_irqsave(&sb1250_imr_lock, flags);
-	cur_ints = ____raw_readq(KSEG1 + A_IMR_MAPPER(cpu) + R_IMR_INTERRUPT_MASK);
+	cur_ints = ____raw_readq(IOADDR(A_IMR_MAPPER(cpu) + R_IMR_INTERRUPT_MASK));
 	cur_ints &= ~(((u64) 1) << irq);
-	____raw_writeq(cur_ints, KSEG1 + A_IMR_MAPPER(cpu) + R_IMR_INTERRUPT_MASK);
+	____raw_writeq(cur_ints, IOADDR(A_IMR_MAPPER(cpu) + R_IMR_INTERRUPT_MASK));
 	spin_unlock_irqrestore(&sb1250_imr_lock, flags);
 }
 
@@ -159,19 +156,19 @@ static void sb1250_set_affinity(unsigned
 
 	/* Swizzle each CPU's IMR (but leave the IP selection alone) */
 	old_cpu = sb1250_irq_owner[irq];
-	cur_ints = ____raw_readq(KSEG1 + A_IMR_MAPPER(old_cpu) + R_IMR_INTERRUPT_MASK);
+	cur_ints = ____raw_readq(IOADDR(A_IMR_MAPPER(old_cpu) + R_IMR_INTERRUPT_MASK));
 	int_on = !(cur_ints & (((u64) 1) << irq));
 	if (int_on) {
 		/* If it was on, mask it */
 		cur_ints |= (((u64) 1) << irq);
-		____raw_writeq(cur_ints, KSEG1 + A_IMR_MAPPER(old_cpu) + R_IMR_INTERRUPT_MASK);
+		____raw_writeq(cur_ints, IOADDR(A_IMR_MAPPER(old_cpu) + R_IMR_INTERRUPT_MASK));
 	}
 	sb1250_irq_owner[irq] = cpu;
 	if (int_on) {
 		/* unmask for the new CPU */
-		cur_ints = ____raw_readq(KSEG1 + A_IMR_MAPPER(cpu) + R_IMR_INTERRUPT_MASK);
+		cur_ints = ____raw_readq(IOADDR(A_IMR_MAPPER(cpu) + R_IMR_INTERRUPT_MASK));
 		cur_ints &= ~(((u64) 1) << irq);
-		____raw_writeq(cur_ints, KSEG1 + A_IMR_MAPPER(cpu) + R_IMR_INTERRUPT_MASK);
+		____raw_writeq(cur_ints, IOADDR(A_IMR_MAPPER(cpu) + R_IMR_INTERRUPT_MASK));
 	}
 	spin_unlock(&sb1250_imr_lock);
 	spin_unlock_irqrestore(&desc->lock, flags);
@@ -214,19 +211,24 @@ static void ack_sb1250_irq(unsigned int 
 	 * deliver the interrupts to all CPUs (which makes affinity
 	 * changing easier for us)
 	 */
-	pending = __raw_readq(KSEG1 + A_IMR_REGISTER(sb1250_irq_owner[irq],
-						     R_IMR_LDT_INTERRUPT));
+	pending = __raw_readq(IOADDR(A_IMR_REGISTER(sb1250_irq_owner[irq],
+						    R_IMR_LDT_INTERRUPT)));
 	pending &= ((u64)1 << (irq));
 	if (pending) {
 		int i;
 		for (i=0; i<NR_CPUS; i++) {
+			int cpu;
+#ifdef CONFIG_SMP
+			cpu = cpu_logical_map(i);
+#else
+			cpu = i;
+#endif
 			/*
 			 * Clear for all CPUs so an affinity switch
 			 * doesn't find an old status
 			 */
 			__raw_writeq(pending, 
-				     KSEG1+A_IMR_REGISTER(cpu_logical_map(i),
-							  R_IMR_LDT_INTERRUPT_CLR));
+				     IOADDR(A_IMR_REGISTER(cpu, R_IMR_LDT_INTERRUPT_CLR)));
 		}
 
 		/*
@@ -341,13 +343,13 @@ void __init init_IRQ(void)
 	/* Default everything to IP2 */
 	for (i = 0; i < SB1250_NR_IRQS; i++) {	/* was I0 */
 		__raw_writeq(IMR_IP2_VAL,
-			     KSEG1 + A_IMR_REGISTER(0,
-						    R_IMR_INTERRUPT_MAP_BASE) +
-		      (i << 3));
+			     IOADDR(A_IMR_REGISTER(0,
+						   R_IMR_INTERRUPT_MAP_BASE) +
+				    (i << 3)));
 		__raw_writeq(IMR_IP2_VAL,
-			     KSEG1 + A_IMR_REGISTER(1,
+			     IOADDR(A_IMR_REGISTER(1,
 						    R_IMR_INTERRUPT_MAP_BASE) +
-		      (i << 3));
+				    (i << 3)));
 	}
 
 	init_sb1250_irqs();
@@ -357,32 +359,30 @@ void __init init_IRQ(void)
 	 * inter-cpu messages
 	 */
 	/* Was I1 */
-	__raw_writeq(IMR_IP3_VAL, KSEG1 + A_IMR_REGISTER(0, R_IMR_INTERRUPT_MAP_BASE) +
-	                   (K_INT_MBOX_0 << 3));
-	__raw_writeq(IMR_IP3_VAL, KSEG1 + A_IMR_REGISTER(1, R_IMR_INTERRUPT_MAP_BASE) +
-	                   (K_INT_MBOX_0 << 3));
+	__raw_writeq(IMR_IP3_VAL, IOADDR(A_IMR_REGISTER(0, R_IMR_INTERRUPT_MAP_BASE) +
+					 (K_INT_MBOX_0 << 3)));
+	__raw_writeq(IMR_IP3_VAL, IOADDR(A_IMR_REGISTER(1, R_IMR_INTERRUPT_MAP_BASE) +
+					 (K_INT_MBOX_0 << 3)));
 
 	/* Clear the mailboxes.  The firmware may leave them dirty */
 	__raw_writeq(0xffffffffffffffff,
-		     KSEG1 + A_IMR_REGISTER(0, R_IMR_MAILBOX_CLR_CPU));
+		     IOADDR(A_IMR_REGISTER(0, R_IMR_MAILBOX_CLR_CPU)));
 	__raw_writeq(0xffffffffffffffff,
-		     KSEG1 + A_IMR_REGISTER(1, R_IMR_MAILBOX_CLR_CPU));
+		     IOADDR(A_IMR_REGISTER(1, R_IMR_MAILBOX_CLR_CPU)));
 
 	/* Mask everything except the mailbox registers for both cpus */
 	tmp = ~((u64) 0) ^ (((u64) 1) << K_INT_MBOX_0);
-	__raw_writeq(tmp, KSEG1 + A_IMR_REGISTER(0, R_IMR_INTERRUPT_MASK));
-	__raw_writeq(tmp, KSEG1 + A_IMR_REGISTER(1, R_IMR_INTERRUPT_MASK));
+	__raw_writeq(tmp, IOADDR(A_IMR_REGISTER(0, R_IMR_INTERRUPT_MASK)));
+	__raw_writeq(tmp, IOADDR(A_IMR_REGISTER(1, R_IMR_INTERRUPT_MASK)));
 
 	sb1250_steal_irq(K_INT_MBOX_0);
 
 	/*
 	 * Note that the timer interrupts are also mapped, but this is
-	 * done in sb1250_time_init()
+	 * done in sb1250_time_init().  Also, the profiling driver 
+	 * does its own management of IP7.
 	 */
 
-#ifdef CONFIG_BCM1250_PROF
-	imask |= STATUSF_IP7;
-#endif
 #ifdef CONFIG_KGDB
 	imask |= STATUSF_IP6;
 #endif
@@ -398,17 +398,14 @@ void __init init_IRQ(void)
 		sb1250_duart_present[kgdb_port] = 0;
 #endif
 		/* Setup uart 1 settings, mapper */
-		__raw_writeq(M_DUART_IMR_BRK, IO_SPACE_BASE + A_DUART_IMRREG(kgdb_port));
+		__raw_writeq(M_DUART_IMR_BRK, IOADDR(A_DUART_IMRREG(kgdb_port)));
 
 		sb1250_steal_irq(kgdb_irq);
 		__raw_writeq(IMR_IP6_VAL,
-			     IO_SPACE_BASE + A_IMR_REGISTER(0, R_IMR_INTERRUPT_MAP_BASE) +
-			     (kgdb_irq<<3));
+			     IOADDR(A_IMR_REGISTER(0, R_IMR_INTERRUPT_MAP_BASE) +
+				    (kgdb_irq<<3)));
 		sb1250_unmask_irq(0, kgdb_irq);
 
-#ifdef CONFIG_GDB_CONSOLE
-		register_gdb_console();
-#endif
 		prom_printf("Waiting for GDB on UART port %d\n", kgdb_port);
 		set_debug_traps();
 		breakpoint();
@@ -420,8 +417,8 @@ void __init init_IRQ(void)
 
 #include <linux/delay.h>
 
-#define duart_out(reg, val)     csr_out32(val, KSEG1 + A_DUART_CHANREG(kgdb_port,reg))
-#define duart_in(reg)           csr_in32(KSEG1 + A_DUART_CHANREG(kgdb_port,reg))
+#define duart_out(reg, val)     csr_out32(val, IOADDR(A_DUART_CHANREG(kgdb_port,reg)))
+#define duart_in(reg)           csr_in32(IOADDR(A_DUART_CHANREG(kgdb_port,reg)))
 
 void sb1250_kgdb_interrupt(struct pt_regs *regs)
 {
@@ -430,7 +427,7 @@ void sb1250_kgdb_interrupt(struct pt_reg
 	 * host to stop the break, since we would see another
 	 * interrupt on the end-of-break too)
 	 */
-	kstat_this_cpu.irqs[K_INT_UART_1]++;
+	kstat_this_cpu.irqs[kgdb_irq]++;
 	mdelay(500);
 	duart_out(R_DUART_CMD, V_DUART_MISC_CMD_RESET_BREAK_INT |
 				M_DUART_RX_EN | M_DUART_TX_EN);
--- diff/arch/mips/sibyte/sb1250/irq_handler.S	2003-08-20 14:16:25.000000000 +0100
+++ source/arch/mips/sibyte/sb1250/irq_handler.S	2004-02-23 13:56:38.000000000 +0000
@@ -31,7 +31,6 @@
 #include <linux/config.h>
 
 #include <asm/addrspace.h>
-#include <asm/processor.h>
 #include <asm/asm.h>
 #include <asm/mipsregs.h>
 #include <asm/regdef.h>
@@ -53,8 +52,7 @@
 	.set	push
 	.set	noreorder
 	.set	noat
-	#.set	mips64
-	.set	mips4
+	.set	mips64
 	.align	5
 	NESTED(sb1250_irq_handler, PT_SIZE, sp)
 	SAVE_ALL
@@ -136,8 +134,7 @@
 	beqz	s0, 4f		/* No interrupts.  Return */
 	 move	a1, sp
 
-3:	#dclz	s1, s0		/* Find the next interrupt */
-	.word   0x72118824	# dclz s1, s0
+3:	dclz	s1, s0		/* Find the next interrupt */
 	dsubu	a0, zero, s1
 	daddiu	a0, a0, 63
 	jal	 do_IRQ
--- diff/arch/mips/sibyte/sb1250/prom.c	2003-08-20 14:16:25.000000000 +0100
+++ source/arch/mips/sibyte/sb1250/prom.c	2004-02-23 13:56:38.000000000 +0000
@@ -27,8 +27,6 @@
 #include <asm/bootinfo.h>
 #include <asm/reboot.h>
 
-extern char arcs_cmdline[];
-
 #ifdef CONFIG_EMBEDDED_RAMDISK
 /* These are symbols defined by the ramdisk linker script */
 extern unsigned char __rd_start;
@@ -91,9 +89,9 @@ static void prom_linux_exit(void)
 }
 
 /*
- * prom_init is called just after the cpu type is determined, from init_arch()
+ * prom_init is called just after the cpu type is determined, from setup_arch()
  */
-__init int prom_init(int argc, char **argv, char **envp, int *prom_vec)
+void __init prom_init(void)
 {
 	_machine_restart   = (void (*)(char *))prom_linux_exit;
 	_machine_halt      = prom_linux_exit;
@@ -103,13 +101,12 @@ __init int prom_init(int argc, char **ar
 
 	mips_machgroup = MACH_GROUP_SIBYTE;
 	prom_meminit();
-
-	return 0;
 }
 
-void prom_free_prom_memory(void)
+unsigned long __init prom_free_prom_memory(void)
 {
 	/* Not sure what I'm supposed to do here.  Nothing, I think */
+	return 0;
 }
 
 void prom_putchar(char c)
--- diff/arch/mips/sibyte/sb1250/setup.c	2003-08-20 14:16:25.000000000 +0100
+++ source/arch/mips/sibyte/sb1250/setup.c	2004-02-23 13:56:38.000000000 +0000
@@ -15,7 +15,7 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  */
-
+#include <linux/config.h>
 #include <linux/kernel.h>
 #include <linux/reboot.h>
 #include <linux/string.h>
@@ -23,7 +23,6 @@
 #include <asm/bootinfo.h>
 #include <asm/mipsregs.h>
 #include <asm/io.h>
-#include <asm/system.h>
 #include <asm/sibyte/sb1250.h>
 #include <asm/sibyte/sb1250_regs.h>
 #include <asm/sibyte/sb1250_scd.h>
@@ -154,7 +153,7 @@ void sb1250_setup(void)
 	int bad_config = 0;
 
 	sb1_pass = read_c0_prid() & 0xff;
-	sys_rev = __raw_readq(IO_SPACE_BASE | A_SCD_SYSTEM_REVISION);
+	sys_rev = __raw_readq(IOADDR(A_SCD_SYSTEM_REVISION));
 	soc_type = SYS_SOC_TYPE(sys_rev);
 	soc_pass = G_SYS_REVISION(sys_rev);
 
@@ -163,11 +162,8 @@ void sb1250_setup(void)
 		machine_restart(NULL);
 	}
 
-	plldiv = G_SYS_PLL_DIV(__raw_readq(IO_SPACE_BASE | A_SCD_SYSTEM_CFG));
+	plldiv = G_SYS_PLL_DIV(__raw_readq(IOADDR(A_SCD_SYSTEM_CFG)));
 	zbbus_mhz = ((plldiv >> 1) * 50) + ((plldiv & 1) * 25);
-#ifndef CONFIG_SB1_PASS_1_WORKAROUNDS
-	__raw_writeq(0, KSEG1 + A_SCD_ZBBUS_CYCLE_COUNT);
-#endif
 
 	prom_printf("Broadcom SiByte %s %s @ %d MHz (SB1 rev %d)\n",
 		    soc_str, pass_str, zbbus_mhz * 2, sb1_pass);
--- diff/arch/mips/sibyte/sb1250/smp.c	2003-08-26 10:00:52.000000000 +0100
+++ source/arch/mips/sibyte/sb1250/smp.c	2004-02-23 13:56:38.000000000 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2001 Broadcom Corporation
+ * Copyright (C) 2001, 2002, 2003 Broadcom Corporation
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
@@ -28,30 +28,44 @@
 #include <asm/sibyte/sb1250_regs.h>
 #include <asm/sibyte/sb1250_int.h>
 
-extern irqreturn_t smp_call_function_interrupt(int irq, void *dev,
-	struct pt_regs *regs);
-extern void smp_tune_scheduling(void);
-
-/*
- * These are routines for dealing with the sb1250 smp capabilities
- * independent of board/firmware
- */
-
-static u64 mailbox_set_regs[] = {
-	KSEG1 + A_IMR_CPU0_BASE + R_IMR_MAILBOX_SET_CPU,
-	KSEG1 + A_IMR_CPU1_BASE + R_IMR_MAILBOX_SET_CPU
+static void *mailbox_set_regs[] = {
+	(void *)IOADDR(A_IMR_CPU0_BASE + R_IMR_MAILBOX_SET_CPU),
+	(void *)IOADDR(A_IMR_CPU1_BASE + R_IMR_MAILBOX_SET_CPU)
 };
 
-static u64 mailbox_clear_regs[] = {
-	KSEG1 + A_IMR_CPU0_BASE + R_IMR_MAILBOX_CLR_CPU,
-	KSEG1 + A_IMR_CPU1_BASE + R_IMR_MAILBOX_CLR_CPU
+static void *mailbox_clear_regs[] = {
+	(void *)IOADDR(A_IMR_CPU0_BASE + R_IMR_MAILBOX_CLR_CPU),
+	(void *)IOADDR(A_IMR_CPU1_BASE + R_IMR_MAILBOX_CLR_CPU)
 };
 
-static u64 mailbox_regs[] = {
-	KSEG1 + A_IMR_CPU0_BASE + R_IMR_MAILBOX_CPU,
-	KSEG1 + A_IMR_CPU1_BASE + R_IMR_MAILBOX_CPU
+static void *mailbox_regs[] = {
+	(void *)IOADDR(A_IMR_CPU0_BASE + R_IMR_MAILBOX_CPU),
+	(void *)IOADDR(A_IMR_CPU1_BASE + R_IMR_MAILBOX_CPU)
 };
 
+/*
+ * SMP init and finish on secondary CPUs
+ */
+void sb1250_smp_init(void)
+{
+	unsigned int imask = STATUSF_IP4 | STATUSF_IP3 | STATUSF_IP2 |
+		STATUSF_IP1 | STATUSF_IP0;
+
+	/* Set interrupt mask, but don't enable */
+	change_c0_status(ST0_IM, imask);
+}
+
+void sb1250_smp_finish(void)
+{
+	extern void sb1250_time_init(void);
+	sb1250_time_init();
+	local_irq_enable();
+}
+
+/*
+ * These are routines for dealing with the sb1250 smp capabilities
+ * independent of board/firmware
+ */
 
 /*
  * Simple enough; everything is set up, so just poke the appropriate mailbox
@@ -62,14 +76,8 @@ void core_send_ipi(int cpu, unsigned int
 	__raw_writeq((((u64)action)<< 48), mailbox_set_regs[cpu]);
 }
 
-
-void sb1250_smp_finish(void)
-{
-	extern void sb1_sanitize_tlb(void);
-
-	sb1_sanitize_tlb();
-	sb1250_time_init();
-}
+extern irqreturn_t smp_call_function_interrupt(int irq, void *dev,
+	struct pt_regs *regs);
 
 void sb1250_mailbox_interrupt(struct pt_regs *regs)
 {
@@ -78,10 +86,10 @@ void sb1250_mailbox_interrupt(struct pt_
 
 	kstat_this_cpu.irqs[K_INT_MBOX_0]++;
 	/* Load the mailbox register to figure out what we're supposed to do */
-	action = (__raw_readq(mailbox_regs[cpu]) >> 48) & 0xffff;
+	action = (____raw_readq(mailbox_regs[cpu]) >> 48) & 0xffff;
 
 	/* Clear the mailbox to clear the interrupt */
-	__raw_writeq(((u64)action)<<48, mailbox_clear_regs[cpu]);
+	____raw_writeq(((u64)action)<<48, mailbox_clear_regs[cpu]);
 
 	/*
 	 * Nothing to do for SMP_RESCHEDULE_YOURSELF; returning from the
@@ -92,66 +100,3 @@ void sb1250_mailbox_interrupt(struct pt_
 		smp_call_function_interrupt(0, NULL, regs);
 	}
 }
-
-extern atomic_t cpus_booted;
-extern void prom_setup_smp(void);
-extern int prom_boot_secondary(int cpu, unsigned long sp, unsigned long gp);
-
-void __init smp_boot_cpus(void)
-{
-	int cur_cpu = 0;
-	int cpu;
-
-	prom_setup_smp();
-	init_new_context(current, &init_mm);
-	current_thread_info()->cpu = 0;
-	cpu_data[0].udelay_val = loops_per_jiffy;
-	cpu_data[0].asid_cache = ASID_FIRST_VERSION;
-	cpus_clear(cpu_online_map);
-	cpu_set(0, cpu_online_map);
-	atomic_set(&cpus_booted, 1);  /* Master CPU is already booted... */
-	smp_tune_scheduling();
-
-	/*
-	 * This loop attempts to compensate for "holes" in the CPU
-	 * numbering.  It's overkill, but general.
-	 */
-	for (cpu = 1; cpu < num_online_cpus(); ) {
-		struct task_struct *idle;
-		struct pt_regs regs;
-		int retval;
-		printk("Starting CPU %d... ", cpu);
-
-		/* Spawn a new process normally.  Grab a pointer to
-		   its task struct so we can mess with it */
-		idle = copy_process(CLONE_VM | CLONE_IDLETASK, 0, &regs, 0,
-		                    NULL, NULL);
-		if (IS_ERR(idle))
-			panic("failed fork for CPU %d", cpu);
-
-		/*
-		 * We remove it from the pidhash and the runqueue
-		 * once we got the process:
-		 */
-		init_idle(idle, cpu);
-
-		unhash_process(idle);
-
-		do {
-			/* Iterate until we find a CPU that comes up */
-			cur_cpu++;
-			retval = prom_boot_secondary(cur_cpu,
-					    (unsigned long)idle + THREAD_SIZE - 32,
-					    (unsigned long)idle);
-		} while (!retval && (cur_cpu < NR_CPUS));
-		if (retval) {
-			cpu++;
-		} else {
-			panic("CPU discovery disaster");
-		}
-	}
-
-	/* Wait for everyone to come up */
-	while (atomic_read(&cpus_booted) != num_online_cpus());
-	smp_threads_ready = 1;
-}
--- diff/arch/mips/sibyte/sb1250/time.c	2003-08-20 14:16:25.000000000 +0100
+++ source/arch/mips/sibyte/sb1250/time.c	2004-02-23 13:56:38.000000000 +0000
@@ -67,23 +67,21 @@ void sb1250_time_init(void)
 	sb1250_mask_irq(cpu, irq);
 
 	/* Map the timer interrupt to ip[4] of this cpu */
-	__raw_writeq(IMR_IP4_VAL, KSEG1 + A_IMR_REGISTER(cpu, R_IMR_INTERRUPT_MAP_BASE)
-	      + (irq<<3));
+	__raw_writeq(IMR_IP4_VAL, IOADDR(A_IMR_REGISTER(cpu, R_IMR_INTERRUPT_MAP_BASE) +
+					 (irq << 3)));
 
 	/* the general purpose timer ticks at 1 Mhz independent if the rest of the system */
 	/* Disable the timer and set up the count */
-	__raw_writeq(0, KSEG1 + A_SCD_TIMER_REGISTER(cpu, R_SCD_TIMER_CFG));
+	__raw_writeq(0, IOADDR(A_SCD_TIMER_REGISTER(cpu, R_SCD_TIMER_CFG)));
 #ifdef CONFIG_SIMULATION
-	__raw_writeq(50000 / HZ, KSEG1 +
-	                         A_SCD_TIMER_REGISTER(cpu, R_SCD_TIMER_INIT));
+	__raw_writeq(50000 / HZ, IOADDR(A_SCD_TIMER_REGISTER(cpu, R_SCD_TIMER_INIT)));
 #else
-	__raw_writeq(1000000/HZ, KSEG1 +
-	                         A_SCD_TIMER_REGISTER(cpu, R_SCD_TIMER_INIT));
+	__raw_writeq(1000000/HZ, IOADDR(A_SCD_TIMER_REGISTER(cpu, R_SCD_TIMER_INIT)));
 #endif
 
 	/* Set the timer running */
 	__raw_writeq(M_SCD_TIMER_ENABLE|M_SCD_TIMER_MODE_CONTINUOUS,
-	      KSEG1 + A_SCD_TIMER_REGISTER(cpu, R_SCD_TIMER_CFG));
+		     IOADDR(A_SCD_TIMER_REGISTER(cpu, R_SCD_TIMER_CFG)));
 
 	sb1250_unmask_irq(cpu, irq);
 	sb1250_steal_irq(irq);
@@ -105,7 +103,7 @@ void sb1250_timer_interrupt(struct pt_re
 
 	/* Reset the timer */
 	____raw_writeq(M_SCD_TIMER_ENABLE|M_SCD_TIMER_MODE_CONTINUOUS,
-		       KSEG1 + A_SCD_TIMER_REGISTER(cpu, R_SCD_TIMER_CFG));
+		       IOADDR(A_SCD_TIMER_REGISTER(cpu, R_SCD_TIMER_CFG)));
 
 	/*
 	 * CPU 0 handles the global timer interrupt job
@@ -129,7 +127,7 @@ void sb1250_timer_interrupt(struct pt_re
 unsigned long sb1250_gettimeoffset(void)
 {
 	unsigned long count =
-		__raw_readq(KSEG1 + A_SCD_TIMER_REGISTER(0, R_SCD_TIMER_CNT));
+		__raw_readq(IOADDR(A_SCD_TIMER_REGISTER(0, R_SCD_TIMER_CNT)));
 
 	return 1000000/HZ - count;
  }
--- diff/arch/mips/sibyte/swarm/Makefile	2003-07-08 09:55:17.000000000 +0100
+++ source/arch/mips/sibyte/swarm/Makefile	2004-02-23 13:56:38.000000000 +0000
@@ -1,3 +1,3 @@
-lib-y				= setup.o cmdline.o rtc_xicor1241.o rtc_m41t81.o
+lib-y				= setup.o rtc_xicor1241.o rtc_m41t81.o
 
 lib-$(CONFIG_KGDB)		+= dbg_io.o
--- diff/arch/mips/sibyte/swarm/dbg_io.c	2003-08-20 14:16:25.000000000 +0100
+++ source/arch/mips/sibyte/swarm/dbg_io.c	2004-02-23 13:56:38.000000000 +0000
@@ -37,8 +37,8 @@ static int duart_initialized = 0;	/* 0: 
 /* -------------------- END OF CONFIG --------------------- */
 extern int kgdb_port;
 
-#define	duart_out(reg, val)	csr_out32(val, KSEG1 + A_DUART_CHANREG(kgdb_port,reg))
-#define duart_in(reg)		csr_in32(KSEG1 + A_DUART_CHANREG(kgdb_port,reg))
+#define	duart_out(reg, val)	csr_out32(val, IOADDR(A_DUART_CHANREG(kgdb_port,reg)))
+#define duart_in(reg)		csr_in32(IOADDR(A_DUART_CHANREG(kgdb_port,reg)))
 
 void putDebugChar(unsigned char c);
 unsigned char getDebugChar(void);
--- diff/arch/mips/sibyte/swarm/rtc_m41t81.c	2003-08-20 14:16:25.000000000 +0100
+++ source/arch/mips/sibyte/swarm/rtc_m41t81.c	2004-02-23 13:56:38.000000000 +0000
@@ -82,7 +82,7 @@
 #define M41T81REG_SQW	0x13		/* square wave register */
 
 #define M41T81_CCR_ADDRESS	0x68
-#define SMB_CSR(reg) (KSEG1 | A_SMB_REGISTER(1, reg))
+#define SMB_CSR(reg) (IOADDR(A_SMB_REGISTER(1, reg)))
 
 static int m41t81_read(uint8_t addr)
 {
--- diff/arch/mips/sibyte/swarm/rtc_xicor1241.c	2003-08-20 14:16:25.000000000 +0100
+++ source/arch/mips/sibyte/swarm/rtc_xicor1241.c	2004-02-23 13:56:38.000000000 +0000
@@ -57,7 +57,7 @@
 
 #define X1241_CCR_ADDRESS	0x6F
 
-#define SMB_CSR(reg) (KSEG1 | A_SMB_REGISTER(1, reg))
+#define SMB_CSR(reg) (IOADDR(A_SMB_REGISTER(1, reg)))
 
 static int xicor_read(uint8_t addr)
 {
--- diff/arch/mips/sibyte/swarm/setup.c	2003-08-20 14:16:25.000000000 +0100
+++ source/arch/mips/sibyte/swarm/setup.c	2004-02-23 13:56:38.000000000 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2000, 2001 Broadcom Corporation
+ * Copyright (C) 2000, 2001, 2002, 2003 Broadcom Corporation
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
@@ -20,13 +20,12 @@
  * Setup code for the SWARM board
  */
 
+#include <linux/config.h>
 #include <linux/spinlock.h>
 #include <linux/mm.h>
 #include <linux/bootmem.h>
 #include <linux/blkdev.h>
 #include <linux/init.h>
-#include <linux/ide.h>
-#include <linux/console.h>
 
 #include <asm/irq.h>
 #include <asm/io.h>
@@ -40,13 +39,6 @@
 #include <asm/sibyte/sb1250_genbus.h>
 #include <asm/sibyte/board.h>
 
-extern struct rtc_ops *rtc_ops;
-extern struct rtc_ops swarm_rtc_ops;
-
-#ifdef CONFIG_BLK_DEV_IDE
-extern struct ide_ops sibyte_ide_ops;
-#endif
-
 extern void sb1250_setup(void);
 
 extern int xicor_probe(void);
@@ -88,7 +80,7 @@ int swarm_be_handler(struct pt_regs *reg
 	return (is_fixup ? MIPS_BE_FIXUP : MIPS_BE_FATAL);
 }
 
-void __init swarm_setup(void)
+static void __init swarm_setup(void)
 {
 	extern int panic_timeout;
 
@@ -125,14 +117,7 @@ void __init swarm_setup(void)
 #endif
 	       " CFE\n");
 
-#ifdef CONFIG_BLK_DEV_IDE
-	ide_ops = &sibyte_ide_ops;
-#endif
-
 #ifdef CONFIG_VT
-#ifdef CONFIG_DUMMY_CONSOLE
-	conswitchp = &dummy_con;
-#endif
 	screen_info = (struct screen_info) {
 		0, 0,           /* orig-x, orig-y */
 		0,              /* unused */
@@ -148,6 +133,8 @@ void __init swarm_setup(void)
 #endif
 }
 
+early_initcall(swarm_setup);
+
 #ifdef LEDS_PHYS
 
 #ifdef CONFIG_SIBYTE_CARMEL
@@ -157,7 +144,7 @@ void __init swarm_setup(void)
 #endif
 
 #define setled(index, c) \
-  ((unsigned char *)(LEDS_PHYS|IO_SPACE_BASE|0x20))[(3-(index))<<3] = (c)
+  ((unsigned char *)(IOADDR(LEDS_PHYS)+0x20))[(3-(index))<<3] = (c)
 void setleds(char *str)
 {
 	int i;
--- diff/arch/mips/sibyte/swarm/time.c	2003-08-20 14:16:25.000000000 +0100
+++ source/arch/mips/sibyte/swarm/time.c	2004-02-23 13:56:38.000000000 +0000
@@ -75,7 +75,7 @@ static unsigned int usec_bias = 0;
 
 #define X1241_CCR_ADDRESS	0x6F
 
-#define SMB_CSR(reg) (KSEG1 | A_SMB_REGISTER(1, reg))
+#define SMB_CSR(reg) (IOADDR(A_SMB_REGISTER(1, reg)))
 
 static int xicor_read(uint8_t addr)
 {
--- diff/arch/mips/sni/Makefile	2003-08-20 14:16:25.000000000 +0100
+++ source/arch/mips/sni/Makefile	2004-02-23 13:56:38.000000000 +0000
@@ -2,6 +2,6 @@
 # Makefile for the SNI specific part of the kernel
 #
 
-obj-y	 	+= int-handler.o io.o irq.o pcimt_scache.o reset.o setup.o
+obj-y	 	+= int-handler.o irq.o pcimt_scache.o reset.o setup.o
 
 EXTRA_AFLAGS := $(CFLAGS)
--- diff/arch/mips/sni/int-handler.S	2003-08-20 14:16:25.000000000 +0100
+++ source/arch/mips/sni/int-handler.S	2004-02-23 13:56:38.000000000 +0000
@@ -37,8 +37,12 @@ led_cache:	.byte	0
 		mfc0	t1, CP0_CAUSE
 		and	t0, t1
 
-		 andi	t1, t0, 0x4a00			# hardware interrupt 1
-		bnez	t1, _hwint134
+		 andi	t1, t0, 0x0800			# hardware interrupt 1
+		bnez	t1, _hwint1
+		 andi	t1, t0, 0x4000			# hardware interrupt 4
+		bnez	t1, _hwint4
+		 andi	t1, t0, 0x2000			# hardware interrupt 3
+		bnez	t1, _hwint3
 		 andi	t1, t0, 0x1000			# hardware interrupt 2
 		bnez	t1, _hwint2
 		 andi	t1, t0, 0x8000			# hardware interrupt 5
@@ -55,20 +59,48 @@ led_cache:	.byte	0
 /* hwint0 should deal with MP agent, ASIC PCI, EISA NMI and debug
    button interrupts.  */
 _hwint0:	jal	pciasic_hwint0
-		 move	a1, sp
+		 move	a0, sp
+		j	ret_from_irq
+		 nop
 
 /*
- * hwint 1 deals with EISA and SCSI interrupts,
- * hwint 3 should deal with the PCI A - D interrupts,
- * hwint 4 is used for only the onboard PCnet 32.
+ * hwint 1 deals with EISA and SCSI interrupts
  */
-_hwint134:	jal	pciasic_hwint134
+_hwint1:	jal	pciasic_hwint1
+		 move	a0, sp
+		j	ret_from_irq
+		 nop
 
 
-/* This interrupt was used for the com1 console on the first prototypes.  */
+/*
+ * This interrupt was used for the com1 console on the first prototypes;
+ * it's unsed otherwise
+ */
 _hwint2:	jal	pciasic_hwint2
+		 move	a0, sp
+		j	ret_from_irq
+		 nop
+
+/*
+ * hwint 3 are the PCI interrupts A - D
+ */
+_hwint3:	jal	pciasic_hwint3
+		 move	a0, sp
+		j	ret_from_irq
+		 nop
+
+/*
+ * hwint 4 is used for only the onboard PCnet 32.
+ */
+_hwint4:	jal	pciasic_hwint4
+		 move	a0, sp
+		j	ret_from_irq
+		 nop
 
 /* hwint5 is the r4k count / compare interrupt  */
 _hwint5:	jal	pciasic_hwint5
+		 move	a0, sp
+		j	ret_from_irq
+		 nop
 
 		END(sni_rm200_pci_handle_int)
--- diff/arch/mips/sni/irq.c	2003-08-20 14:16:25.000000000 +0100
+++ source/arch/mips/sni/irq.c	2004-02-23 13:56:38.000000000 +0000
@@ -21,7 +21,15 @@ spinlock_t pciasic_lock = SPIN_LOCK_UNLO
 
 extern asmlinkage void sni_rm200_pci_handle_int(void);
 
-static void enable_pciasic_irq(unsigned int irq);
+static void enable_pciasic_irq(unsigned int irq)
+{
+	unsigned int mask = 1 << (irq - PCIMT_IRQ_INT2);
+	unsigned long flags;
+
+	spin_lock_irqsave(&pciasic_lock, flags);
+	*(volatile u8 *) PCIMT_IRQSEL |= mask;
+	spin_unlock_irqrestore(&pciasic_lock, flags);
+}
 
 static unsigned int startup_pciasic_irq(unsigned int irq)
 {
@@ -41,16 +49,6 @@ void disable_pciasic_irq(unsigned int ir
 	spin_unlock_irqrestore(&pciasic_lock, flags);
 }
 
-static void enable_pciasic_irq(unsigned int irq)
-{
-	unsigned int mask = 1 << (irq - PCIMT_IRQ_INT2);
-	unsigned long flags;
-
-	spin_lock_irqsave(&pciasic_lock, flags);
-	*(volatile u8 *) PCIMT_IRQSEL |= mask;
-	spin_unlock_irqrestore(&pciasic_lock, flags);
-}
-
 #define mask_and_ack_pciasic_irq disable_pciasic_irq
 
 static void end_pciasic_irq(unsigned int irq)
@@ -60,7 +58,7 @@ static void end_pciasic_irq(unsigned int
 }
 
 static struct hw_interrupt_type pciasic_irq_type = {
-	"PCIASIC",
+	"ASIC-PCI",
 	startup_pciasic_irq,
 	shutdown_pciasic_irq,
 	enable_pciasic_irq,
@@ -92,36 +90,72 @@ void pciasic_hwint5(struct pt_regs *regs
 	panic("hwint5 and no handler yet");
 }
 
-static inline int ls1bit8(unsigned int x)
+static unsigned int ls1bit8(unsigned int x)
 {
-	int b = 8, s;
+	int b = 7, s;
 
-	x <<= 24;
 	s = 4; if ((x & 0x0f) == 0) s = 0; b -= s; x <<= s;
-	s = 2; if ((x & 0x03) == 0) s = 0; b -= s; x <<= s;
-	s = 1; if ((x & 0x01) == 0) s = 0; b -= s;
+	s = 2; if ((x & 0x30) == 0) s = 0; b -= s; x <<= s;
+	s = 1; if ((x & 0x40) == 0) s = 0; b -= s;
 
 	return b;
 }
 
 /*
  * hwint 1 deals with EISA and SCSI interrupts,
+ * 
+ * The EISA_INT bit in CSITPEND is high active, all others are low active.
+ */
+void pciasic_hwint1(struct pt_regs *regs)
+{
+	u8 pend = *(volatile char *)PCIMT_CSITPEND;
+	unsigned long flags;
+
+	if (pend & IT_EISA) {
+		int irq;
+		/*
+		 * Note: ASIC PCI's builtin interrupt achknowledge feature is
+		 * broken.  Using it may result in loss of some or all i8259
+		 * interupts, so don't use PCIMT_INT_ACKNOWLEDGE ...
+		 */
+		irq = i8259_irq();
+		if (unlikely(irq < 0))
+			return;
+
+		do_IRQ(irq, regs);
+	}
+
+	if (!(pend & IT_SCSI)) {
+		flags = read_c0_status();
+		clear_c0_status(ST0_IM);
+		do_IRQ(PCIMT_IRQ_SCSI, regs);
+		write_c0_status(flags);
+	}
+}
+
+/*
  * hwint 3 should deal with the PCI A - D interrupts,
- * hwint 4 is used for only the onboard PCnet 32.
  */
-void pciasic_hwint134(struct pt_regs *regs)
+void pciasic_hwint3(struct pt_regs *regs)
 {
 	u8 pend = *(volatile char *)PCIMT_CSITPEND;
 	int irq;
 
+	pend &= (IT_INTA | IT_INTB | IT_INTC | IT_INTD);
+	clear_c0_status(IE_IRQ3);
 	irq = PCIMT_IRQ_INT2 + ls1bit8(pend);
-	if (irq == PCIMT_IRQ_EISA) {
-		pend = *(volatile char *)PCIMT_INT_ACKNOWLEDGE;
-		if (!(pend ^ 0xff))
-			return;
-	}
 	do_IRQ(irq, regs);
-	return;
+	set_c0_status(IE_IRQ3);
+}
+
+/*
+ * hwint 4 is used for only the onboard PCnet 32.
+ */
+void pciasic_hwint4(struct pt_regs *regs)
+{
+	clear_c0_status(IE_IRQ4);
+	do_IRQ(PCIMT_IRQ_ETHERNET, regs);
+	set_c0_status(IE_IRQ4);
 }
 
 void __init init_pciasic(void)
@@ -156,4 +190,6 @@ void __init init_IRQ (void)
 		irq_desc[i].depth      = 1;
 		irq_desc[i].handler    = &pciasic_irq_type;
 	}
+
+	change_c0_status(ST0_IM, IE_IRQ1|IE_IRQ2|IE_IRQ3|IE_IRQ4);
 }
--- diff/arch/mips/sni/setup.c	2003-09-30 15:46:11.000000000 +0100
+++ source/arch/mips/sni/setup.c	2004-02-23 13:56:38.000000000 +0000
@@ -5,7 +5,7 @@
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  *
- * Copyright (C) 1996, 1997, 1998, 2000, 2003 by Ralf Baechle
+ * Copyright (C) 1996, 1997, 1998, 2000, 2003, 2004 by Ralf Baechle
  */
 #include <linux/config.h>
 #include <linux/eisa.h>
@@ -14,17 +14,20 @@
 #include <linux/sched.h>
 #include <linux/init.h>
 #include <linux/interrupt.h>
-#include <linux/timex.h>
-#include <linux/pci.h>
 #include <linux/mc146818rtc.h>
+#include <linux/pci.h>
 #include <linux/console.h>
 #include <linux/fb.h>
-#include <linux/ide.h>
+#include <linux/tty.h>
 
+#include <asm/arc/types.h>
+#include <asm/sgialib.h>
 #include <asm/bcache.h>
 #include <asm/bootinfo.h>
 #include <asm/io.h>
 #include <asm/irq.h>
+#include <asm/mc146818-time.h>
+#include <asm/pci_channel.h>
 #include <asm/processor.h>
 #include <asm/ptrace.h>
 #include <asm/reboot.h>
@@ -36,9 +39,6 @@ extern void sni_machine_restart(char *co
 extern void sni_machine_halt(void);
 extern void sni_machine_power_off(void);
 
-extern struct ide_ops std_ide_ops;
-extern struct rtc_ops std_rtc_ops;
-
 static void __init sni_rm200_pci_timer_setup(struct irqaction *irq)
 {
 	/* set the clock to 100 Hz */
@@ -48,9 +48,6 @@ static void __init sni_rm200_pci_timer_s
 	setup_irq(0, irq);
 }
 
-
-extern unsigned char sni_map_isa_cache;
-
 /*
  * A bit more gossip about the iron we're running on ...
  */
@@ -73,56 +70,135 @@ static inline void sni_pcimt_detect(void
 	printk("%s.\n", boardtype);
 }
 
-void __init sni_rm200_pci_setup(void)
+static void __init sni_display_setup(void)
+{
+#ifdef CONFIG_VT
+#if defined(CONFIG_VGA_CONSOLE)
+	struct screen_info *si = &screen_info;
+	DISPLAY_STATUS *di;
+
+	di = ArcGetDisplayStatus(1);
+
+	if (di) {
+		si->orig_x		= di->CursorXPosition;
+		si->orig_y		= di->CursorYPosition;
+		si->orig_video_cols	= di->CursorMaxXPosition;
+		si->orig_video_lines	= di->CursorMaxYPosition;
+		si->orig_video_isVGA	= VIDEO_TYPE_VGAC;
+		si->orig_video_points	= 16;
+	}
+#endif
+#endif
+}
+
+static struct resource sni_io_resource = {
+	"PCIMT IO MEM", 0x00001000UL, 0x03bfffffUL, IORESOURCE_IO,
+};
+
+static struct resource pcimt_io_resources[] = {
+	{ "dma1", 0x00, 0x1f, IORESOURCE_BUSY },
+	{ "timer", 0x40, 0x5f, IORESOURCE_BUSY },
+	{ "keyboard", 0x60, 0x6f, IORESOURCE_BUSY },
+	{ "dma page reg", 0x80, 0x8f, IORESOURCE_BUSY },
+	{ "dma2", 0xc0, 0xdf, IORESOURCE_BUSY },
+	{ "PCI config data", 0xcfc, 0xcff, IORESOURCE_BUSY }
+};
+
+static struct resource sni_mem_resource = {
+	"PCIMT PCI MEM", 0x10000000UL, 0xffffffffUL, IORESOURCE_MEM
+};
+
+/*
+ * The RM200/RM300 has a few holes in it's PCI/EISA memory address space used
+ * for other purposes.  Be paranoid and allocate all of the before the PCI
+ * code gets a chance to to map anything else there ...
+ * 
+ * This leaves the following areas available:
+ *
+ * 0x10000000 - 0x1009ffff (640kB) PCI/EISA/ISA Bus Memory
+ * 0x10100000 - 0x13ffffff ( 15MB) PCI/EISA/ISA Bus Memory
+ * 0x18000000 - 0x1fbfffff (124MB) PCI/EISA Bus Memory
+ * 0x1ff08000 - 0x1ffeffff (816kB) PCI/EISA Bus Memory
+ * 0xa0000000 - 0xffffffff (1.5GB) PCI/EISA Bus Memory
+ */
+static struct resource pcimt_mem_resources[] = {
+	{ "Video RAM area", 0x100a0000, 0x100bffff, IORESOURCE_BUSY },
+	{ "ISA Reserved", 0x100c0000, 0x100fffff, IORESOURCE_BUSY },
+	{ "PCI IO", 0x14000000, 0x17bfffff, IORESOURCE_BUSY },
+	{ "Cache Replacement Area", 0x17c00000, 0x17ffffff, IORESOURCE_BUSY},
+	{ "PCI INT Acknowledge", 0x1a000000, 0x1a000003, IORESOURCE_BUSY },
+	{ "Boot PROM", 0x1fc00000, 0x1fc7ffff, IORESOURCE_BUSY},
+	{ "Diag PROM", 0x1fc80000, 0x1fcfffff, IORESOURCE_BUSY},
+	{ "X-Bus", 0x1fd00000, 0x1fdfffff, IORESOURCE_BUSY},
+	{ "BIOS map", 0x1fe00000, 0x1fefffff, IORESOURCE_BUSY},
+	{ "NVRAM / EEPROM", 0x1ff00000, 0x1ff7ffff, IORESOURCE_BUSY},
+	{ "ASIC PCI", 0x1fff0000, 0x1fffefff, IORESOURCE_BUSY},
+	{ "MP Agent", 0x1ffff000, 0x1fffffff, IORESOURCE_BUSY},
+	{ "Main Memory", 0x20000000, 0x9fffffff, IORESOURCE_BUSY}
+};
+
+static void __init sni_resource_init(void)
+{
+	int i;
+
+	/* request I/O space for devices used on all i[345]86 PCs */
+	for (i = 0; i < ARRAY_SIZE(pcimt_io_resources); i++)
+		request_resource(&ioport_resource, pcimt_io_resources + i);
+
+	/* request mem space for pcimt-specific devices */
+	for (i = 0; i < ARRAY_SIZE(pcimt_mem_resources); i++)
+		request_resource(&sni_mem_resource, pcimt_mem_resources + i);
+
+	ioport_resource.end = sni_io_resource.end;
+}
+
+extern struct pci_ops sni_pci_ops;
+
+static struct pci_controller sni_controller = {
+	.pci_ops	= &sni_pci_ops,
+	.mem_resource	= &sni_mem_resource,
+	.mem_offset	= 0x10000000UL,
+	.io_resource	= &sni_io_resource,
+	.io_offset	= 0x00000000UL
+};
+
+static inline void sni_pcimt_time_init(void)
+{
+	rtc_get_time = mc146818_get_cmos_time;
+	rtc_set_time = mc146818_set_rtc_mmss;
+}
+
+static int __init sni_rm200_pci_setup(void)
 {
 	sni_pcimt_detect();
 	sni_pcimt_sc_init();
+	sni_pcimt_time_init();
 
 	set_io_port_base(SNI_PORT_BASE);
+	ioport_resource.end = sni_io_resource.end;
 
 	/*
 	 * Setup (E)ISA I/O memory access stuff
 	 */
 	isa_slot_offset = 0xb0000000;
-	// sni_map_isa_cache = 0;
 #ifdef CONFIG_EISA
 	EISA_bus = 1;
 #endif
 
-	request_region(0x00,0x20,"dma1");
-	request_region(0x40,0x20,"timer");
-	/* XXX FIXME: CONFIG_RTC */
-	request_region(0x70,0x10,"rtc");
-	request_region(0x80,0x10,"dma page reg");
-	request_region(0xc0,0x20,"dma2");
+	sni_resource_init();
 	board_timer_setup = sni_rm200_pci_timer_setup;
 
 	_machine_restart = sni_machine_restart;
 	_machine_halt = sni_machine_halt;
 	_machine_power_off = sni_machine_power_off;
 
-	/*
-	 * Some cluefull person has placed the PCI config data directly in
-	 * the I/O port space ...
-	 */
-	request_region(0xcfc,0x04,"PCI config data");
+	sni_display_setup();
 
-#ifdef CONFIG_BLK_DEV_IDE
-	ide_ops = &std_ide_ops;
+#ifdef CONFIG_PCI
+	register_pci_controller(&sni_controller);
 #endif
-	conswitchp = &vga_con;
-
-	screen_info = (struct screen_info) {
-		0, 0,		/* orig-x, orig-y */
-		0,		/* unused */
-		52,		/* orig_video_page */
-		3,		/* orig_video_mode */
-		80,		/* orig_video_cols */
-		4626, 3, 9,	/* unused, ega_bx, unused */
-		50,		/* orig_video_lines */
-		0x22,		/* orig_video_isVGA */
-		16		/* orig_video_points */
-	};
 
-	rtc_ops = &std_rtc_ops;
+	return 0;
 }
+
+early_initcall(sni_rm200_pci_setup);
--- diff/arch/mips/tx4927/common/tx4927_irq.c	2003-09-17 12:28:02.000000000 +0100
+++ source/arch/mips/tx4927/common/tx4927_irq.c	2004-02-23 13:56:38.000000000 +0000
@@ -23,6 +23,7 @@
  *  with this program; if not, write to the Free Software Foundation, Inc.,
  *  675 Mass Ave, Cambridge, MA 02139, USA.
  */
+#include <linux/config.h>
 #include <linux/errno.h>
 #include <linux/init.h>
 #include <linux/kernel_stat.h>
--- diff/arch/mips/tx4927/common/tx4927_irq_handler.S	2003-07-08 09:55:17.000000000 +0100
+++ source/arch/mips/tx4927/common/tx4927_irq_handler.S	2004-02-23 13:56:38.000000000 +0000
@@ -29,7 +29,6 @@
  *  with this program; if not, write to the Free Software Foundation, Inc.,
  *  675 Mass Ave, Cambridge, MA 02139, USA.
  */
-#include <linux/config.h>
 #include <asm/asm.h>
 #include <asm/mipsregs.h>
 #include <asm/addrspace.h>
--- diff/arch/mips/tx4927/common/tx4927_setup.c	2003-07-08 09:55:17.000000000 +0100
+++ source/arch/mips/tx4927/common/tx4927_setup.c	2004-02-23 13:56:38.000000000 +0000
@@ -1,8 +1,4 @@
 /*
- * linux/arch/mips/tx4927/common/tx4927_setup.c
- *
- * common tx4927 setup stuff
- *
  * Author: MontaVista Software, Inc.
  *         source@mvista.com
  *
@@ -28,7 +24,7 @@
  *  with this program; if not, write to the Free Software Foundation, Inc.,
  *  675 Mass Ave, Cambridge, MA 02139, USA.
  */
-
+#include <linux/config.h>
 #include <linux/errno.h>
 #include <linux/init.h>
 #include <linux/kernel_stat.h>
@@ -49,13 +45,11 @@
 #include <asm/mipsregs.h>
 #include <asm/system.h>
 #include <asm/time.h>
-#include <asm/time.h>
 #include <asm/tx4927/tx4927.h>
 
 
 #undef DEBUG
 
-void __init tx4927_setup(void);
 void __init tx4927_time_init(void);
 void __init tx4927_timer_setup(struct irqaction *irq);
 void dump_cp0(char *key);
@@ -70,7 +64,7 @@ static void tx4927_write_buffer_flush(vo
 }
 
 
-void __init tx4927_setup(void)
+static void __init tx4927_setup(void)
 {
 	board_time_init = tx4927_time_init;
 	board_timer_setup = tx4927_timer_setup;
@@ -86,6 +80,7 @@ void __init tx4927_setup(void)
 	return;
 }
 
+early_initcall(tx4927_setup);
 
 void __init tx4927_time_init(void)
 {
@@ -120,7 +115,7 @@ void __init tx4927_timer_setup(struct ir
 
 	/* to generate the first timer interrupt */
 	c1 = read_c0_count();
-	count = c1 + (mips_counter_frequency / HZ);
+	count = c1 + (mips_hpt_frequency / HZ);
 	write_c0_compare(count);
 	c2 = read_c0_count();
 
--- diff/arch/mips/tx4927/toshiba_rbtx4927/Makefile	2003-07-08 09:55:17.000000000 +0100
+++ source/arch/mips/tx4927/toshiba_rbtx4927/Makefile	2004-02-23 13:56:38.000000000 +0000
@@ -2,7 +2,4 @@ obj-y	+= toshiba_rbtx4927_prom.o 
 obj-y	+= toshiba_rbtx4927_setup.o 
 obj-y	+= toshiba_rbtx4927_irq.o 
 
-obj-$(CONFIG_PCI)	+= toshiba_rbtx4927_pci_fixup.o 
-obj-$(CONFIG_PCI)	+= toshiba_rbtx4927_pci_ops.o 
-
 EXTRA_AFLAGS := $(CFLAGS)
--- diff/arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_irq.c	2003-09-17 12:28:02.000000000 +0100
+++ source/arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_irq.c	2004-02-23 13:56:38.000000000 +0000
@@ -124,7 +124,6 @@ JP7 is not bus master -- do NOT use -- o
 #include <linux/timex.h>
 #include <asm/bootinfo.h>
 #include <asm/page.h>
-#include <asm/bootinfo.h>
 #include <asm/io.h>
 #include <asm/irq.h>
 #include <asm/pci.h>
@@ -132,7 +131,6 @@ JP7 is not bus master -- do NOT use -- o
 #include <asm/ptrace.h>
 #include <asm/reboot.h>
 #include <asm/time.h>
-#include <linux/version.h>
 #include <linux/bootmem.h>
 #include <linux/blkdev.h>
 #ifdef CONFIG_RTC_DS1742
--- diff/arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_prom.c	2003-07-08 09:55:17.000000000 +0100
+++ source/arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_prom.c	2004-02-23 13:56:38.000000000 +0000
@@ -36,14 +36,10 @@
 #include <asm/cpu.h>
 #include <asm/tx4927/tx4927.h>
 
-#ifndef COMMAND_LINE_SIZE
-#define COMMAND_LINE_SIZE CL_SIZE
-#endif
-
-char arcs_cmdline[COMMAND_LINE_SIZE] = "console=ttyS0,38400 ip=any root=nfs rw";
-
-void __init prom_init_cmdline(int argc, char **argv)
+void __init prom_init_cmdline(void)
 {
+	int argc = (int) fw_arg0;
+	char **argv = (char **) fw_arg1;
 	int i;			/* Always ignore the "-c" at argv[0] */
 
 	/* ignore all built-in args if any f/w args given */
@@ -59,14 +55,14 @@ void __init prom_init_cmdline(int argc, 
 	}
 }
 
-void __init prom_init(int argc, char **argv, char **envp, int *pvec)
+void __init prom_init(void)
 {
+	const char* toshiba_name_list[] = GROUP_TOSHIBA_NAMES;
 	extern int tx4927_get_mem_size(void);
+	extern char* toshiba_name;
 	int msize;
-        const char* toshiba_name_list[] = GROUP_TOSHIBA_NAMES;
-        extern char* toshiba_name;
 
-	prom_init_cmdline(argc, argv);
+	prom_init_cmdline();
 
 	mips_machgroup = MACH_GROUP_TOSHIBA;
 
@@ -81,13 +77,9 @@ void __init prom_init(int argc, char **a
 	add_memory_region(0, msize << 20, BOOT_MEM_RAM);
 }
 
-void __init prom_free_prom_memory(void)
-{
-}
-
-
-void __init prom_fixup_mem_map(unsigned long start, unsigned long end)
+unsigned long __init prom_free_prom_memory(void)
 {
+	return 0;
 }
 
 const char *get_system_type(void)
--- diff/arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_setup.c	2003-08-20 14:16:08.000000000 +0100
+++ source/arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_setup.c	2004-02-23 13:56:38.000000000 +0000
@@ -52,18 +52,14 @@
 #include <linux/timex.h>
 #include <asm/bootinfo.h>
 #include <asm/page.h>
-#include <asm/bootinfo.h>
 #include <asm/io.h>
 #include <asm/irq.h>
-#include <asm/pci.h>
 #include <asm/processor.h>
 #include <asm/ptrace.h>
 #include <asm/reboot.h>
 #include <asm/time.h>
-#include <linux/version.h>
 #include <linux/bootmem.h>
 #include <linux/blkdev.h>
-#include <linux/console.h>
 #ifdef CONFIG_RTC_DS1742
 #include <asm/rtc_ds1742.h>
 #endif
@@ -73,20 +69,11 @@
 #include <asm/tx4927/toshiba_rbtx4927.h>
 #ifdef CONFIG_PCI
 #include <asm/tx4927/tx4927_pci.h>
-#include <linux/types.h>
-#include <linux/pci.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
 #include <asm/pci_channel.h>
 #endif
-#ifdef CONFIG_PC_KEYB
-#include <asm/keyboard.h>
-#endif
 #ifdef CONFIG_BLK_DEV_IDEPCI
 #include <linux/hdreg.h>
-#include <asm/ptrace.h>
 #include <linux/ide.h>
-extern struct ide_ops std_ide_ops;
 #endif
 
 #undef TOSHIBA_RBTX4927_SETUP_DEBUG
@@ -326,7 +313,7 @@ void print_pci_status(void)
 	printk("PCIC STATUS %lx\n", tx4927_pcicptr->pcicstatus);
 }
 
-static struct pci_dev *fake_pci_dev(struct pci_channel *hose,
+static struct pci_dev *fake_pci_dev(struct pci_controller *hose,
 				    int top_bus, int busnr, int devfn)
 {
 	static struct pci_dev dev;
@@ -348,7 +335,7 @@ static struct pci_dev *fake_pci_dev(stru
 }
 
 #define EARLY_PCI_OP(rw, size, type)                                    \
-static int early_##rw##_config_##size(struct pci_channel *hose,                \
+static int early_##rw##_config_##size(struct pci_controller *hose,      \
         int top_bus, int bus, int devfn, int offset, type value)        \
 {                                                                       \
         return pci_##rw##_config_##size(                                \
@@ -363,22 +350,15 @@ EARLY_PCI_OP(write, byte, u8)
 EARLY_PCI_OP(write, word, u16)
 EARLY_PCI_OP(write, dword, u32)
 
-static int __init tx4927_pcibios_init(int busno, struct pci_channel *hose)
+static int __init tx4927_pcibios_init(int busno, struct pci_controller *hose)
 {
-	u32 pci_devfn;
-	int devfn_start = 0;
-	int devfn_stop = 0xff;
 	unsigned int id;
+	u32 pci_devfn;
 
 	TOSHIBA_RBTX4927_SETUP_DPRINTK(TOSHIBA_RBTX4927_SETUP_PCIBIOS,
 				       "-\n");
 
-	if (hose->first_devfn)
-		devfn_start = hose->first_devfn;
-	if (hose->last_devfn)
-		devfn_stop = hose->last_devfn;
-
-	for (pci_devfn = devfn_start; pci_devfn < devfn_stop; pci_devfn++) {
+	for (pci_devfn = 0x0; pci_devfn < 0xff; pci_devfn++) {
 		early_read_config_dword(hose, busno, busno, pci_devfn,
 					PCI_VENDOR_ID, &id);
 
@@ -604,7 +584,7 @@ static int __init tx4927_pcibios_init(in
 	TOSHIBA_RBTX4927_SETUP_DPRINTK(TOSHIBA_RBTX4927_SETUP_PCIBIOS,
 				       "+\n");
 
-	return (busno);
+	return busno;
 }
 
 extern struct resource pci_io_resource;
@@ -852,17 +832,9 @@ void tx4927_pci_setup(void)
 
 	TOSHIBA_RBTX4927_SETUP_DPRINTK(TOSHIBA_RBTX4927_SETUP_PCI2,
 				       ":pci setup complete:\n");
-      //tx4927_dump_pcic_settings();
-
-	{
-		struct pci_channel *p;
-		int busno;
+	//tx4927_dump_pcic_settings();
 
-		busno = 0;
-		for (p = mips_pci_channels; p->pci_ops != NULL; p++) {
-			busno = tx4927_pcibios_init(busno, p) + 1;
-		}
-	}
+	tx4927_pcibios_init(0, &tx4927_controller);
 
 	TOSHIBA_RBTX4927_SETUP_DPRINTK(TOSHIBA_RBTX4927_SETUP_PCI2, "+\n");
 }
@@ -972,31 +944,6 @@ void __init toshiba_rbtx4927_setup(void)
 	_machine_halt = toshiba_rbtx4927_halt;
 	_machine_power_off = toshiba_rbtx4927_power_off;
 
-
-#ifdef CONFIG_BLK_DEV_IDEPCI
-	{
-		TOSHIBA_RBTX4927_SETUP_DPRINTK
-		    (TOSHIBA_RBTX4927_SETUP_SETUP,
-		     ":ide_ops=&std_ide_ops(modified)\n");
-		ide_ops = &std_ide_ops;
-	}
-#else
-	{
-		TOSHIBA_RBTX4927_SETUP_DPRINTK
-		    (TOSHIBA_RBTX4927_SETUP_SETUP,
-		     ":ide_ops=<NOT_CONFIG>\n");
-	}
-#endif
-
-#ifdef CONFIG_FB
-	{
-		conswitchp = &dummy_con;
-	}
-#endif
-
-
-
-
 #ifdef CONFIG_PCI
 
 	/* PCIC */
@@ -1063,7 +1010,7 @@ void __init toshiba_rbtx4927_setup(void)
 
 	{
 		u32 id = 0;
-		early_read_config_dword(&mips_pci_channels[0], 0, 0, 0x90,
+		early_read_config_dword(&tx4927_controller, 0, 0, 0x90,
 					PCI_VENDOR_ID, &id);
 		if (id == 0x94601055) {
 			tx4927_using_backplane = 1;
@@ -1073,30 +1020,6 @@ void __init toshiba_rbtx4927_setup(void)
 		}
 	}
 
-
-	/* this is only done if backplane board installed, so must wait for pci */
-#ifdef CONFIG_PC_KEYB
-	{
-		if (tx4927_using_backplane) {
-			extern struct kbd_ops std_kbd_ops;
-			kbd_ops = &std_kbd_ops;
-			TOSHIBA_RBTX4927_SETUP_DPRINTK
-			    (TOSHIBA_RBTX4927_SETUP_SETUP,
-			     ":kbd_ops=&std_kbd_ops\n");
-		} else {
-			TOSHIBA_RBTX4927_SETUP_DPRINTK
-			    (TOSHIBA_RBTX4927_SETUP_SETUP,
-			     ":kbd_ops=<NO_BACKPLANE>\n");
-		}
-	}
-#else
-	{
-		TOSHIBA_RBTX4927_SETUP_DPRINTK
-		    (TOSHIBA_RBTX4927_SETUP_SETUP,
-		     ":kbd_ops=<NOT_CONFIG>\n");
-	}
-#endif
-
 	/* this is on ISA bus behind PCI bus, so need PCI up first */
 #ifdef CONFIG_TOSHIBA_FPCIB0
 	{
@@ -1167,7 +1090,7 @@ toshiba_rbtx4927_time_init(void)
 				       ":rtc_ds1742_init()+\n");
 
 	TOSHIBA_RBTX4927_SETUP_DPRINTK(TOSHIBA_RBTX4927_SETUP_TIME_INIT,
-				       ":Calibrate mips_counter_frequency-\n");
+				       ":Calibrate mips_hpt_frequency-\n");
 	rtc_ds1742_wait();
 
 	/* get the count */
@@ -1180,29 +1103,29 @@ toshiba_rbtx4927_time_init(void)
 	c2 = read_c0_count();
 
 	TOSHIBA_RBTX4927_SETUP_DPRINTK(TOSHIBA_RBTX4927_SETUP_TIME_INIT,
-				       ":Calibrate mips_counter_frequency+\n");
+				       ":Calibrate mips_hpt_frequency+\n");
 	TOSHIBA_RBTX4927_SETUP_DPRINTK(TOSHIBA_RBTX4927_SETUP_TIME_INIT,
 				       ":c1=%12u\n", c1);
 	TOSHIBA_RBTX4927_SETUP_DPRINTK(TOSHIBA_RBTX4927_SETUP_TIME_INIT,
 				       ":c2=%12u\n", c2);
 
 	/* this diff is as close as we are going to get to counter ticks per sec */
-	mips_counter_frequency = abs(c2 - c1);
+	mips_hpt_frequency = abs(c2 - c1);
 	TOSHIBA_RBTX4927_SETUP_DPRINTK(TOSHIBA_RBTX4927_SETUP_TIME_INIT,
-				       ":f1=%12u\n", mips_counter_frequency);
+				       ":f1=%12u\n", mips_hpt_frequency);
 
 	/* round to 1/10th of a MHz */
-	mips_counter_frequency /= (100 * 1000);
-	mips_counter_frequency *= (100 * 1000);
+	mips_hpt_frequency /= (100 * 1000);
+	mips_hpt_frequency *= (100 * 1000);
 	TOSHIBA_RBTX4927_SETUP_DPRINTK(TOSHIBA_RBTX4927_SETUP_TIME_INIT,
-				       ":f2=%12u\n", mips_counter_frequency);
+				       ":f2=%12u\n", mips_hpt_frequency);
 
 	TOSHIBA_RBTX4927_SETUP_DPRINTK(TOSHIBA_RBTX4927_SETUP_INFO,
-				       ":mips_counter_frequency=%uHz (%uMHz)\n",
-				       mips_counter_frequency,
-				       mips_counter_frequency / 1000000);
+				       ":mips_hpt_frequency=%uHz (%uMHz)\n",
+				       mips_hpt_frequency,
+				       mips_hpt_frequency / 1000000);
 #else
-	mips_counter_frequency = 100000000;
+	mips_hpt_frequency = 100000000;
 #endif
 
 	TOSHIBA_RBTX4927_SETUP_DPRINTK(TOSHIBA_RBTX4927_SETUP_TIME_INIT, "+\n");
--- diff/arch/mips/vr4181/osprey/prom.c	2003-08-20 14:16:36.000000000 +0100
+++ source/arch/mips/vr4181/osprey/prom.c	2004-02-23 13:56:38.000000000 +0000
@@ -19,8 +19,6 @@
 #include <asm/bootinfo.h>
 #include <asm/addrspace.h>
 
-char arcs_cmdline[CL_SIZE];
-
 const char *get_system_type(void)
 {
 	return "NEC_Vr41xx Osprey";
@@ -30,10 +28,11 @@ const char *get_system_type(void)
  * [jsun] right now we assume it is the nec debug monitor, which does
  * not pass any arguments.
  */
-void __init prom_init()
+void __init prom_init(void)
 {
-	strcpy(arcs_cmdline, "ip=bootp ");
-	strcat(arcs_cmdline, "ether=46,0x03fe0300,eth0 ");
+	// cmdline is now set in default config
+	// strcpy(arcs_cmdline, "ip=bootp ");
+	// strcat(arcs_cmdline, "ether=46,0x03fe0300,eth0 ");
 	// strcpy(arcs_cmdline, "ether=0,0x0300,eth0 "
 	// strcat(arcs_cmdline, "video=vr4181fb:xres:240,yres:320,bpp:8 ");
 
@@ -44,11 +43,7 @@ void __init prom_init()
 	add_memory_region(0, 16 << 20, BOOT_MEM_RAM);
 }
 
-void __init prom_free_prom_memory(void)
+unsigned long __init prom_free_prom_memory(void)
 {
+	return 0;
 }
-
-void __init prom_fixup_mem_map(unsigned long start, unsigned long end)
-{
-}
-
--- diff/arch/mips/vr4181/osprey/setup.c	2003-08-20 14:16:36.000000000 +0100
+++ source/arch/mips/vr4181/osprey/setup.c	2004-02-23 13:56:38.000000000 +0000
@@ -16,7 +16,6 @@
  */
 
 #include <linux/config.h>
-#include <linux/console.h>
 #include <linux/ide.h>
 #include <linux/init.h>
 #include <linux/delay.h>
@@ -32,7 +31,7 @@ extern void nec_osprey_power_off(void);
 extern void vr4181_init_serial(void);
 extern void vr4181_init_time(void);
 
-void __init nec_osprey_setup(void)
+static void __init nec_osprey_setup(void)
 {
 	set_io_port_base(VR4181_PORT_BASE);
 	isa_slot_offset = VR4181_ISAMEM_BASE;
@@ -40,10 +39,6 @@ void __init nec_osprey_setup(void)
 	vr4181_init_serial();
 	vr4181_init_time();
 
-#ifdef CONFIG_FB
-	conswitchp = &dummy_con;
-#endif
-
 	_machine_restart = nec_osprey_restart;
 	_machine_halt = nec_osprey_halt;
 	_machine_power_off = nec_osprey_power_off;
@@ -69,3 +64,5 @@ void __init nec_osprey_setup(void)
 	 */
 	*VR4181_GPINTTYPL = 0x3000;
 }
+
+early_initcall(nec_osprey_setup);
--- diff/arch/mips/vr41xx/casio-e55/Makefile	2003-07-08 09:55:17.000000000 +0100
+++ source/arch/mips/vr41xx/casio-e55/Makefile	2004-02-23 13:56:38.000000000 +0000
@@ -3,5 +3,3 @@
 #
 
 obj-y			+= init.o setup.o
-
-obj-$(CONFIG_IDE)	+= ide-e55.o
--- diff/arch/mips/vr41xx/casio-e55/init.c	2003-07-08 09:55:17.000000000 +0100
+++ source/arch/mips/vr41xx/casio-e55/init.c	2004-02-23 13:56:38.000000000 +0000
@@ -13,22 +13,21 @@
  *  Free Software Foundation; either version 2 of the License, or (at your
  *  option) any later version.
  */
-#include <linux/config.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/string.h>
 
 #include <asm/bootinfo.h>
 
-char arcs_cmdline[CL_SIZE];
-
 const char *get_system_type(void)
 {
 	return "CASIO CASSIOPEIA E-11/15/55/65";
 }
 
-void __init prom_init(int argc, char **argv, unsigned long magic, int *prom_vec)
+void __init prom_init(void)
 {
+	int argc = fw_arg0;
+	char **argv = (char **) fw_arg1;
 	int i;
 
 	/*
@@ -44,6 +43,7 @@ void __init prom_init(int argc, char **a
 	mips_machtype = MACH_CASIO_E55;
 }
 
-void __init prom_free_prom_memory (void)
+unsigned long __init prom_free_prom_memory(void)
 {
+	return 0;
 }
--- diff/arch/mips/vr41xx/casio-e55/setup.c	2003-07-08 09:55:17.000000000 +0100
+++ source/arch/mips/vr41xx/casio-e55/setup.c	2004-02-23 13:56:38.000000000 +0000
@@ -1,28 +1,29 @@
 /*
- * FILE NAME
- *	arch/mips/vr41xx/casio-e55/setup.c
+ *  setup.c, Setup for the CASIO CASSIOPEIA E-11/15/55/65.
  *
- * BRIEF MODULE DESCRIPTION
- *	Setup for the CASIO CASSIOPEIA E-11/15/55/65.
+ *  Copyright (C) 2002-2003  Yoichi Yuasa <yuasa@hh.iij4u.or.jp>
  *
- * Copyright 2002 Yoichi Yuasa
- *                yuasa@hh.iij4u.or.jp
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
  *
- *  This program is free software; you can redistribute it and/or modify it
- *  under the terms of the GNU General Public License as published by the
- *  Free Software Foundation; either version 2 of the License, or (at your
- *  option) any later version.
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
 #include <linux/config.h>
 #include <linux/init.h>
-#include <linux/console.h>
-#include <linux/ide.h>
 #include <linux/ioport.h>
 #include <linux/major.h>
 #include <linux/kdev_t.h>
 #include <linux/root_dev.h>
 
-#include <asm/reboot.h>
 #include <asm/time.h>
 #include <asm/vr41xx/e55.h>
 
@@ -31,11 +32,7 @@ extern unsigned long initrd_start, initr
 extern void * __rd_start, * __rd_end;
 #endif
 
-#ifdef CONFIG_BLK_DEV_IDE
-extern struct ide_ops e55_ide_ops;
-#endif
-
-void __init casio_e55_setup(void)
+static void __init casio_e55_setup(void)
 {
 	set_io_port_base(IO_PORT_BASE);
 	ioport_resource.start = IO_PORT_RESOURCE_START;
@@ -49,26 +46,18 @@ void __init casio_e55_setup(void)
 	initrd_end = (unsigned long)&__rd_end;
 #endif
 
-	_machine_restart = vr41xx_restart;
-	_machine_halt = vr41xx_halt;
-	_machine_power_off = vr41xx_power_off;
-
 	board_time_init = vr41xx_time_init;
 	board_timer_setup = vr41xx_timer_setup;
 
-#ifdef CONFIG_FB
-	conswitchp = &dummy_con;
-#endif
-
-#ifdef CONFIG_BLK_DEV_IDE
-	ide_ops = &e55_ide_ops;
-#endif
-
 	vr41xx_bcu_init();
 
-	vr41xx_cmu_init(0);
+	vr41xx_cmu_init();
+
+	vr41xx_pmu_init();
 
 #ifdef CONFIG_SERIAL_8250
 	vr41xx_siu_init(SIU_RS232C, 0);
 #endif
 }
+
+early_initcall(casio_e55_setup);
--- diff/arch/mips/vr41xx/common/Makefile	2003-07-08 09:55:17.000000000 +0100
+++ source/arch/mips/vr41xx/common/Makefile	2004-02-23 13:56:38.000000000 +0000
@@ -2,9 +2,9 @@
 # Makefile for common code of the NEC VR4100 series.
 #
 
-obj-y				+= bcu.o cmu.o giu.o icu.o int-handler.o reset.o
+obj-y				+= bcu.o cmu.o giu.o icu.o int-handler.o ksyms.o pmu.o rtc.o
 obj-$(CONFIG_SERIAL_8250)	+= serial.o
-obj-$(CONFIG_VR41XX_TIME_C)	+= time.o
+obj-$(CONFIG_VRC4171)		+= vrc4171.o
 obj-$(CONFIG_VRC4173)		+= vrc4173.o
 
 EXTRA_AFLAGS := $(CFLAGS)
--- diff/arch/mips/vr41xx/common/bcu.c	2003-07-08 09:55:17.000000000 +0100
+++ source/arch/mips/vr41xx/common/bcu.c	2004-02-23 13:56:38.000000000 +0000
@@ -33,27 +33,23 @@
 /*
  * Changes:
  *  MontaVista Software Inc. <yyuasa@mvista.com> or <source@mvista.com>
+ *  - New creation, NEC VR4122 and VR4131 are supported.
  *  - Added support for NEC VR4111 and VR4121.
  *
- *  Paul Mundt <lethal@chaoticdreams.org>
- *  - Calculate mips_counter_frequency properly on VR4131.
- *
- *  MontaVista Software Inc. <yyuasa@mvista.com> or <source@mvista.com>
- *  - New creation, NEC VR4122 and VR4131 are supported.
+ *  Yoichi Yuasa <yuasa@hh.iij4u.or.jp>
+ *  - Added support for NEC VR4133.
  */
 #include <linux/init.h>
+#include <linux/smp.h>
 #include <linux/types.h>
 
-#include <asm/addrspace.h>
 #include <asm/cpu.h>
 #include <asm/io.h>
-#include <asm/time.h>
-#include <asm/vr41xx/vr41xx.h>
 
-#define VR4111_CLKSPEEDREG	KSEG1ADDR(0x0b000014)
-#define VR4122_CLKSPEEDREG	KSEG1ADDR(0x0f000014)
-#define VR4131_CLKSPEEDREG	VR4122_CLKSPEEDREG
+#define CLKSPEEDREG_TYPE1	KSEG1ADDR(0x0b000014)
+#define CLKSPEEDREG_TYPE2	KSEG1ADDR(0x0f000014)
  #define CLKSP(x)		((x) & 0x001f)
+ #define CLKSP_VR4133(x)	((x) & 0x0007)
 
  #define DIV2B			0x8000
  #define DIV3B			0x4000
@@ -65,15 +61,27 @@
  #define TDIVMODE(x)		(2 << (((x) & 0x1000) >> 12))
  #define VTDIVMODE(x)		(((x) & 0x0700) >> 8)
 
-unsigned long vr41xx_vtclock = 0;
+static unsigned long vr41xx_vtclock;
+static unsigned long vr41xx_tclock;
+
+unsigned long vr41xx_get_vtclock_frequency(void)
+{
+	return vr41xx_vtclock;
+}
+
+unsigned long vr41xx_get_tclock_frequency(void)
+{
+	return vr41xx_tclock;
+}
 
-static inline u16 read_clkspeed(void)
+static inline uint16_t read_clkspeed(void)
 {
 	switch (current_cpu_data.cputype) {
 	case CPU_VR4111:
-	case CPU_VR4121: return readw(VR4111_CLKSPEEDREG);
-	case CPU_VR4122: return readw(VR4122_CLKSPEEDREG);
-	case CPU_VR4131: return readw(VR4131_CLKSPEEDREG);
+	case CPU_VR4121: return readw(CLKSPEEDREG_TYPE1);
+	case CPU_VR4122:
+	case CPU_VR4131:
+	case CPU_VR4133: return readw(CLKSPEEDREG_TYPE2);
 	default:
 		printk(KERN_INFO "Unexpected CPU of NEC VR4100 series\n");
 		break;
@@ -82,7 +90,7 @@ static inline u16 read_clkspeed(void)
 	return 0;
 }
 
-static inline unsigned long calculate_pclock(u16 clkspeed)
+static inline unsigned long calculate_pclock(uint16_t clkspeed)
 {
 	unsigned long pclock = 0;
 
@@ -90,63 +98,90 @@ static inline unsigned long calculate_pc
 	case CPU_VR4111:
 	case CPU_VR4121:
 		pclock = 18432000 * 64;
+		pclock /= CLKSP(clkspeed);
 		break;
 	case CPU_VR4122:
 		pclock = 18432000 * 98;
+		pclock /= CLKSP(clkspeed);
 		break;
 	case CPU_VR4131:
 		pclock = 18432000 * 108;
+		pclock /= CLKSP(clkspeed);
+		break;
+	case CPU_VR4133:
+		switch (CLKSP_VR4133(clkspeed)) {
+		case 0:
+			pclock = 133000000;
+			break;
+		case 1:
+			pclock = 149000000;
+			break;
+		case 2:
+			pclock = 165900000;
+			break;
+		case 3:
+			pclock = 199100000;
+			break;
+		case 4:
+			pclock = 265900000;
+			break;
+		default:
+			printk(KERN_INFO "Unknown PClock speed for NEC VR4133\n");
+			break;
+		}
 		break;
 	default:
 		printk(KERN_INFO "Unexpected CPU of NEC VR4100 series\n");
 		break;
 	}
 
-	pclock /= CLKSP(clkspeed);
 	printk(KERN_INFO "PClock: %ldHz\n", pclock);
 
 	return pclock;
 }
 
-static inline unsigned long calculate_vtclock(u16 clkspeed, unsigned long pclock)
+static inline unsigned long calculate_vtclock(uint16_t clkspeed, unsigned long pclock)
 {
+	unsigned long vtclock = 0;
+
 	switch (current_cpu_data.cputype) {
 	case CPU_VR4111:
 		/* The NEC VR4111 doesn't have the VTClock. */
 		break;
 	case CPU_VR4121:
-		vr41xx_vtclock = pclock;
+		vtclock = pclock;
 		/* DIVVT == 9 Divide by 1.5 . VTClock = (PClock * 6) / 9 */
 		if (DIVVT(clkspeed) == 9)
-			vr41xx_vtclock = pclock * 6;
+			vtclock = pclock * 6;
 		/* DIVVT == 10 Divide by 2.5 . VTClock = (PClock * 4) / 10 */
 		else if (DIVVT(clkspeed) == 10)
-			vr41xx_vtclock = pclock * 4;
-		vr41xx_vtclock /= DIVVT(clkspeed);
-		printk(KERN_INFO "VTClock: %ldHz\n", vr41xx_vtclock);
+			vtclock = pclock * 4;
+		vtclock /= DIVVT(clkspeed);
+		printk(KERN_INFO "VTClock: %ldHz\n", vtclock);
 		break;
 	case CPU_VR4122:
 		if(VTDIVMODE(clkspeed) == 7)
-			vr41xx_vtclock = pclock / 1;
+			vtclock = pclock / 1;
 		else if(VTDIVMODE(clkspeed) == 1)
-			vr41xx_vtclock = pclock / 2;
+			vtclock = pclock / 2;
 		else
-			vr41xx_vtclock = pclock / VTDIVMODE(clkspeed);
-		printk(KERN_INFO "VTClock: %ldHz\n", vr41xx_vtclock);
+			vtclock = pclock / VTDIVMODE(clkspeed);
+		printk(KERN_INFO "VTClock: %ldHz\n", vtclock);
 		break;
 	case CPU_VR4131:
-		vr41xx_vtclock = pclock / VTDIVMODE(clkspeed);
-		printk(KERN_INFO "VTClock: %ldHz\n", vr41xx_vtclock);
+	case CPU_VR4133:
+		vtclock = pclock / VTDIVMODE(clkspeed);
+		printk(KERN_INFO "VTClock: %ldHz\n", vtclock);
 		break;
 	default:
 		printk(KERN_INFO "Unexpected CPU of NEC VR4100 series\n");
 		break;
 	}
 
-	return vr41xx_vtclock;
+	return vtclock;
 }
 
-static inline unsigned long calculate_tclock(u16 clkspeed, unsigned long pclock,
+static inline unsigned long calculate_tclock(uint16_t clkspeed, unsigned long pclock,
                                              unsigned long vtclock)
 {
 	unsigned long tclock = 0;
@@ -165,6 +200,7 @@ static inline unsigned long calculate_tc
 		break;
 	case CPU_VR4122:
 	case CPU_VR4131:
+	case CPU_VR4133:
 		tclock = vtclock / TDIVMODE(clkspeed);
 		break;
 	default:
@@ -177,30 +213,14 @@ static inline unsigned long calculate_tc
 	return tclock;
 }
 
-static inline unsigned long calculate_mips_counter_frequency(unsigned long tclock)
-{
-	/*
-	 * VR4131 Revision 2.0 and 2.1 use a value of (tclock / 2).
-	 */
-	if ((current_cpu_data.processor_id == PRID_VR4131_REV2_0) ||
-	    (current_cpu_data.processor_id == PRID_VR4131_REV2_1))
-		tclock /= 2;
-	else
-		tclock /= 4;
-
-	return tclock;
-}
-
 void __init vr41xx_bcu_init(void)
 {
-	unsigned long pclock, vtclock, tclock;
-	u16 clkspeed;
+	unsigned long pclock;
+	uint16_t clkspeed;
 
 	clkspeed = read_clkspeed();
 
 	pclock = calculate_pclock(clkspeed);
-	vtclock = calculate_vtclock(clkspeed, pclock);
-	tclock = calculate_tclock(clkspeed, pclock, vtclock);
-
-	mips_counter_frequency = calculate_mips_counter_frequency(tclock);
+	vr41xx_vtclock = calculate_vtclock(clkspeed, pclock);
+	vr41xx_tclock = calculate_tclock(clkspeed, pclock, vr41xx_vtclock);
 }
--- diff/arch/mips/vr41xx/common/cmu.c	2003-07-08 09:55:17.000000000 +0100
+++ source/arch/mips/vr41xx/common/cmu.c	2004-02-23 13:56:38.000000000 +0000
@@ -33,52 +33,193 @@
 /*
  * Changes:
  *  MontaVista Software Inc. <yyuasa@mvista.com> or <source@mvista.com>
+ *  - New creation, NEC VR4122 and VR4131 are supported.
  *  - Added support for NEC VR4111 and VR4121.
  *
- *  MontaVista Software Inc. <yyuasa@mvista.com> or <source@mvista.com>
- *  - New creation, NEC VR4122 and VR4131 are supported.
+ *  Yoichi Yuasa <yuasa@hh.iij4u.or.jp>
+ *  - Added support for NEC VR4133.
  */
 #include <linux/init.h>
+#include <linux/smp.h>
 #include <linux/types.h>
 
 #include <asm/cpu.h>
 #include <asm/io.h>
+#include <asm/vr41xx/vr41xx.h>
 
-#define VR4111_CMUCLKMSK	KSEG1ADDR(0x0b000060)
-#define VR4122_CMUCLKMSK	KSEG1ADDR(0x0f000060)
-
-static u32 vr41xx_cmu_base = 0;
-static u16 cmuclkmsk = 0;
-
-#define write_cmu(mask)	writew((mask), vr41xx_cmu_base)
+#define CMUCLKMSK_TYPE1	KSEG1ADDR(0x0b000060)
+#define CMUCLKMSK_TYPE2	KSEG1ADDR(0x0f000060)
+ #define MSKPIU		0x0001
+ #define MSKSIU		0x0002
+ #define MSKAIU		0x0004
+ #define MSKKIU		0x0008
+ #define MSKFIR		0x0010
+ #define MSKDSIU	0x0820
+ #define MSKCSI		0x0040
+ #define MSKPCIU	0x0080
+ #define MSKSSIU	0x0100
+ #define MSKSHSP	0x0200
+ #define MSKFFIR	0x0400
+ #define MSKSCSI	0x1000
+ #define MSKPPCIU	0x2000
+#define CMUCLKMSK2	KSEG1ADDR(0x0f000064)
+ #define MSKCEU		0x0001
+ #define MSKMAC0	0x0002
+ #define MSKMAC1	0x0004
+
+static u32 vr41xx_cmu_base;
+static u16 cmuclkmsk, cmuclkmsk2;
+
+#define read_cmuclkmsk()	readw(vr41xx_cmu_base)
+#define read_cmuclkmsk2()	readw(CMUCLKMSK2)
+#define write_cmuclkmsk()	writew(cmuclkmsk, vr41xx_cmu_base)
+#define write_cmuclkmsk2()	writew(cmuclkmsk2, CMUCLKMSK2)
 
-void vr41xx_clock_supply(u16 mask)
+void vr41xx_clock_supply(unsigned int clock)
 {
-	cmuclkmsk |= mask;
-	write_cmu(cmuclkmsk);
+	switch (clock) {
+	case PIU_CLOCK:
+		cmuclkmsk |= MSKPIU;
+		break;
+	case SIU_CLOCK:
+		cmuclkmsk |= MSKSIU | MSKSSIU;
+		break;
+	case AIU_CLOCK:
+		cmuclkmsk |= MSKAIU;
+		break;
+	case KIU_CLOCK:
+		cmuclkmsk |= MSKKIU;
+		break;
+	case FIR_CLOCK:
+		cmuclkmsk |= MSKFIR | MSKFFIR;
+		break;
+	case DSIU_CLOCK:
+		if (current_cpu_data.cputype == CPU_VR4111 ||
+		    current_cpu_data.cputype == CPU_VR4121)
+			cmuclkmsk |= MSKDSIU;
+		else
+			cmuclkmsk |= MSKSIU | MSKDSIU;
+		break;
+	case CSI_CLOCK:
+		cmuclkmsk |= MSKCSI | MSKSCSI;
+		break;
+	case PCIU_CLOCK:
+		cmuclkmsk |= MSKPCIU;
+		break;
+	case HSP_CLOCK:
+		cmuclkmsk |= MSKSHSP;
+		break;
+	case PCI_CLOCK:
+		cmuclkmsk |= MSKPPCIU;
+		break;
+	case CEU_CLOCK:
+		cmuclkmsk2 |= MSKCEU;
+		break;
+	case ETHER0_CLOCK:
+		cmuclkmsk2 |= MSKMAC0;
+		break;
+	case ETHER1_CLOCK:
+		cmuclkmsk2 |= MSKMAC1;
+		break;
+	default:
+		break;
+	}
+
+	if (clock == CEU_CLOCK || clock == ETHER0_CLOCK ||
+	    clock == ETHER1_CLOCK)
+		write_cmuclkmsk2();
+	else
+		write_cmuclkmsk();
 }
 
-void vr41xx_clock_mask(u16 mask)
+void vr41xx_clock_mask(unsigned int clock)
 {
-	cmuclkmsk &= ~mask;
-	write_cmu(cmuclkmsk);
+	switch (clock) {
+	case PIU_CLOCK:
+		cmuclkmsk &= ~MSKPIU;
+		break;
+	case SIU_CLOCK:
+		if (current_cpu_data.cputype == CPU_VR4111 ||
+		    current_cpu_data.cputype == CPU_VR4121) {
+			cmuclkmsk &= ~(MSKSIU | MSKSSIU);
+		} else {
+			if (cmuclkmsk & MSKDSIU)
+				cmuclkmsk &= ~MSKSSIU;
+			else
+				cmuclkmsk &= ~(MSKSIU | MSKSSIU);
+		}
+		break;
+	case AIU_CLOCK:
+		cmuclkmsk &= ~MSKAIU;
+		break;
+	case KIU_CLOCK:
+		cmuclkmsk &= ~MSKKIU;
+		break;
+	case FIR_CLOCK:
+		cmuclkmsk &= ~(MSKFIR | MSKFFIR);
+		break;
+	case DSIU_CLOCK:
+		if (current_cpu_data.cputype == CPU_VR4111 ||
+		    current_cpu_data.cputype == CPU_VR4121) {
+			cmuclkmsk &= ~MSKDSIU;
+		} else {
+			if (cmuclkmsk & MSKSIU)
+				cmuclkmsk &= ~MSKDSIU;
+			else
+				cmuclkmsk &= ~(MSKSIU | MSKDSIU);
+		}
+		break;
+	case CSI_CLOCK:
+		cmuclkmsk &= ~(MSKCSI | MSKSCSI);
+		break;
+	case PCIU_CLOCK:
+		cmuclkmsk &= ~MSKPCIU;
+		break;
+	case HSP_CLOCK:
+		cmuclkmsk &= ~MSKSHSP;
+		break;
+	case PCI_CLOCK:
+		cmuclkmsk &= ~MSKPPCIU;
+		break;
+	case CEU_CLOCK:
+		cmuclkmsk2 &= ~MSKCEU;
+		break;
+	case ETHER0_CLOCK:
+		cmuclkmsk2 &= ~MSKMAC0;
+		break;
+	case ETHER1_CLOCK:
+		cmuclkmsk2 &= ~MSKMAC1;
+		break;
+	default:
+		break;
+	}
+
+	if (clock == CEU_CLOCK || clock == ETHER0_CLOCK ||
+	    clock == ETHER1_CLOCK)
+		write_cmuclkmsk2();
+	else
+		write_cmuclkmsk();
 }
 
-void __init vr41xx_cmu_init(u16 mask)
+void __init vr41xx_cmu_init(void)
 {
 	switch (current_cpu_data.cputype) {
         case CPU_VR4111:
         case CPU_VR4121:
-                vr41xx_cmu_base = VR4111_CMUCLKMSK;
+                vr41xx_cmu_base = CMUCLKMSK_TYPE1;
                 break;
         case CPU_VR4122:
         case CPU_VR4131:
-                vr41xx_cmu_base = VR4122_CMUCLKMSK;
+                vr41xx_cmu_base = CMUCLKMSK_TYPE2;
+                break;
+        case CPU_VR4133:
+                vr41xx_cmu_base = CMUCLKMSK_TYPE2;
+		cmuclkmsk2 = read_cmuclkmsk2();
                 break;
 	default:
 		panic("Unexpected CPU of NEC VR4100 series");
 		break;
         }
 
-	cmuclkmsk = mask;
+	cmuclkmsk = read_cmuclkmsk();
 }
--- diff/arch/mips/vr41xx/common/giu.c	2003-07-08 09:55:17.000000000 +0100
+++ source/arch/mips/vr41xx/common/giu.c	2004-02-23 13:56:38.000000000 +0000
@@ -34,20 +34,23 @@
  * Changes:
  *  MontaVista Software Inc. <yyuasa@mvista.com> or <source@mvista.com>
  *  - New creation, NEC VR4111, VR4121, VR4122 and VR4131 are supported.
+ *
+ *  Yoichi Yuasa <yuasa@hh.iij4u.or.jp>
+ *  - Added support for NEC VR4133.
  */
 #include <linux/errno.h>
 #include <linux/init.h>
 #include <linux/irq.h>
 #include <linux/kernel.h>
+#include <linux/smp.h>
 #include <linux/types.h>
 
-#include <asm/addrspace.h>
 #include <asm/cpu.h>
 #include <asm/io.h>
 #include <asm/vr41xx/vr41xx.h>
 
-#define VR4111_GIUIOSELL	KSEG1ADDR(0x0b000100)
-#define VR4122_GIUIOSELL	KSEG1ADDR(0x0f000140)
+#define GIUIOSELL_TYPE1	KSEG1ADDR(0x0b000100)
+#define GIUIOSELL_TYPE2	KSEG1ADDR(0x0f000140)
 
 #define GIUIOSELL	0x00
 #define GIUIOSELH	0x02
@@ -61,15 +64,19 @@
 #define GIUINTALSELH	0x16
 #define GIUINTHTSELL	0x18
 #define GIUINTHTSELH	0x1a
+#define GIUFEDGEINHL	0x20
+#define GIUFEDGEINHH	0x22
+#define GIUREDGEINHL	0x24
+#define GIUREDGEINHH	0x26
 
-u32 vr41xx_giu_base = 0;
+static uint32_t giu_base;
 
-#define read_giuint(offset)		readw(vr41xx_giu_base + (offset))
-#define write_giuint(val, offset)	writew((val), vr41xx_giu_base + (offset))
+#define read_giuint(offset)		readw(giu_base + (offset))
+#define write_giuint(val, offset)	writew((val), giu_base + (offset))
 
-static inline u16 set_giuint(u16 offset, u16 set)
+static inline uint16_t set_giuint(uint8_t offset, uint16_t set)
 {
-	u16 res;
+	uint16_t res;
 
 	res = read_giuint(offset);
 	res |= set;
@@ -78,9 +85,9 @@ static inline u16 set_giuint(u16 offset,
 	return res;
 }
 
-static inline u16 clear_giuint(u16 offset, u16 clear)
+static inline uint16_t clear_giuint(uint8_t offset, uint16_t clear)
 {
-	u16 res;
+	uint16_t res;
 
 	res = read_giuint(offset);
 	res &= ~clear;
@@ -92,51 +99,83 @@ static inline u16 clear_giuint(u16 offse
 void vr41xx_enable_giuint(int pin)
 {
 	if (pin < 16)
-		set_giuint(GIUINTENL, (u16)1 << pin);
+		set_giuint(GIUINTENL, (uint16_t)1 << pin);
 	else
-		set_giuint(GIUINTENH, (u16)1 << (pin - 16));
+		set_giuint(GIUINTENH, (uint16_t)1 << (pin - 16));
 }
 
 void vr41xx_disable_giuint(int pin)
 {
 	if (pin < 16)
-		clear_giuint(GIUINTENL, (u16)1 << pin);
+		clear_giuint(GIUINTENL, (uint16_t)1 << pin);
 	else
-		clear_giuint(GIUINTENH, (u16)1 << (pin - 16));
+		clear_giuint(GIUINTENH, (uint16_t)1 << (pin - 16));
 }
 
 void vr41xx_clear_giuint(int pin)
 {
 	if (pin < 16)
-		write_giuint((u16)1 << pin, GIUINTSTATL);
+		write_giuint((uint16_t)1 << pin, GIUINTSTATL);
 	else
-		write_giuint((u16)1 << (pin - 16), GIUINTSTATH);
+		write_giuint((uint16_t)1 << (pin - 16), GIUINTSTATH);
 }
 
 void vr41xx_set_irq_trigger(int pin, int trigger, int hold)
 {
-	u16 mask;
+	uint16_t mask;
 
 	if (pin < 16) {
-		mask = (u16)1 << pin;
-		if (trigger == TRIGGER_EDGE) {
+		mask = (uint16_t)1 << pin;
+		if (trigger != TRIGGER_LEVEL) {
         		set_giuint(GIUINTTYPL, mask);
 			if (hold == SIGNAL_HOLD)
 				set_giuint(GIUINTHTSELL, mask);
 			else
 				clear_giuint(GIUINTHTSELL, mask);
+			if (current_cpu_data.cputype == CPU_VR4133) {
+				switch (trigger) {
+				case TRIGGER_EDGE_FALLING:
+					set_giuint(GIUFEDGEINHL, mask);
+					clear_giuint(GIUREDGEINHL, mask);
+					break;
+				case TRIGGER_EDGE_RISING:
+					clear_giuint(GIUFEDGEINHL, mask);
+					set_giuint(GIUREDGEINHL, mask);
+					break;
+				default:
+					set_giuint(GIUFEDGEINHL, mask);
+					set_giuint(GIUREDGEINHL, mask);
+					break;
+				}
+			}
 		} else {
 			clear_giuint(GIUINTTYPL, mask);
 			clear_giuint(GIUINTHTSELL, mask);
 		}
 	} else {
-		mask = (u16)1 << (pin - 16);
-		if (trigger == TRIGGER_EDGE) {
+		mask = (uint16_t)1 << (pin - 16);
+		if (trigger != TRIGGER_LEVEL) {
 			set_giuint(GIUINTTYPH, mask);
 			if (hold == SIGNAL_HOLD)
 				set_giuint(GIUINTHTSELH, mask);
 			else
 				clear_giuint(GIUINTHTSELH, mask);
+			if (current_cpu_data.cputype == CPU_VR4133) {
+				switch (trigger) {
+				case TRIGGER_EDGE_FALLING:
+					set_giuint(GIUFEDGEINHH, mask);
+					clear_giuint(GIUREDGEINHH, mask);
+					break;
+				case TRIGGER_EDGE_RISING:
+					clear_giuint(GIUFEDGEINHH, mask);
+					set_giuint(GIUREDGEINHH, mask);
+					break;
+				default:
+					set_giuint(GIUFEDGEINHH, mask);
+					set_giuint(GIUREDGEINHH, mask);
+					break;
+				}
+			}
 		} else {
 			clear_giuint(GIUINTTYPH, mask);
 			clear_giuint(GIUINTHTSELH, mask);
@@ -148,16 +187,16 @@ void vr41xx_set_irq_trigger(int pin, int
 
 void vr41xx_set_irq_level(int pin, int level)
 {
-	u16 mask;
+	uint16_t mask;
 
 	if (pin < 16) {
-		mask = (u16)1 << pin;
+		mask = (uint16_t)1 << pin;
 		if (level == LEVEL_HIGH)
 			set_giuint(GIUINTALSELL, mask);
 		else
 			clear_giuint(GIUINTALSELL, mask);
 	} else {
-		mask = (u16)1 << (pin - 16);
+		mask = (uint16_t)1 << (pin - 16);
 		if (level == LEVEL_HIGH)
 			set_giuint(GIUINTALSELH, mask);
 		else
@@ -198,7 +237,7 @@ int vr41xx_cascade_irq(unsigned int irq,
 	if(!get_irq_number)
 		return -EINVAL;
 
-	pin = irq - GIU_IRQ(0);
+	pin = GIU_IRQ_TO_PIN(irq);
 	giuint_cascade[pin].flag = GIUINT_CASCADE;
 	giuint_cascade[pin].get_irq_number = get_irq_number;
 
@@ -219,7 +258,7 @@ unsigned int giuint_do_IRQ(int pin, stru
 
 	disable_irq(GIUINT_CASCADE_IRQ);
 	cascade = &giuint_cascade[pin];
-	giuint_irq = pin + GIU_IRQ(0);
+	giuint_irq = GIU_IRQ(pin);
 	if (cascade->flag == GIUINT_CASCADE) {
 		cascade_irq = cascade->get_irq_number(giuint_irq);
 		disable_irq(giuint_irq);
@@ -242,11 +281,12 @@ void __init vr41xx_giuint_init(void)
 	switch (current_cpu_data.cputype) {
 	case CPU_VR4111:
 	case CPU_VR4121:
-		vr41xx_giu_base = VR4111_GIUIOSELL;
+		giu_base = GIUIOSELL_TYPE1;
 		break;
 	case CPU_VR4122:
 	case CPU_VR4131:
-		vr41xx_giu_base = VR4122_GIUIOSELL;
+	case CPU_VR4133:
+		giu_base = GIUIOSELL_TYPE2;
 		break;
 	default:
 		panic("GIU: Unexpected CPU of NEC VR4100 series");
--- diff/arch/mips/vr41xx/common/icu.c	2003-07-08 09:55:17.000000000 +0100
+++ source/arch/mips/vr41xx/common/icu.c	2004-02-23 13:56:38.000000000 +0000
@@ -1,9 +1,9 @@
 /*
  * FILE NAME
- *	arch/mips/vr41xx/vr4122/common/icu.c
+ *	arch/mips/vr41xx/common/icu.c
  *
  * BRIEF MODULE DESCRIPTION
- *	Interrupt Control Unit routines for the NEC VR4122 and VR4131.
+ *	Interrupt Control Unit routines for the NEC VR4100 series.
  *
  * Author: Yoichi Yuasa
  *         yyuasa@mvista.com or source@mvista.com
@@ -33,65 +33,78 @@
 /*
  * Changes:
  *  MontaVista Software Inc. <yyuasa@mvista.com> or <source@mvista.com>
+ *  - New creation, NEC VR4122 and VR4131 are supported.
  *  - Added support for NEC VR4111 and VR4121.
  *
- *  Paul Mundt <lethal@chaoticdreams.org>
- *  - kgdb support.
- *
- *  MontaVista Software Inc. <yyuasa@mvista.com> or <source@mvista.com>
- *  - New creation, NEC VR4122 and VR4131 are supported.
+ *  Yoichi Yuasa <yuasa@hh.iij4u.or.jp>
+ *  - Coped with INTASSIGN of NEC VR4133.
  */
 #include <linux/errno.h>
 #include <linux/init.h>
 #include <linux/interrupt.h>
 #include <linux/irq.h>
+#include <linux/smp.h>
 #include <linux/types.h>
 
-#include <asm/addrspace.h>
 #include <asm/cpu.h>
-#include <asm/gdb-stub.h>
 #include <asm/io.h>
-#include <asm/mipsregs.h>
+#include <asm/irq.h>
+#include <asm/irq_cpu.h>
 #include <asm/vr41xx/vr41xx.h>
 
 extern asmlinkage void vr41xx_handle_interrupt(void);
 
-extern void __init init_generic_irq(void);
-extern void mips_cpu_irq_init(u32 irq_base);
-
 extern void vr41xx_giuint_init(void);
+extern void vr41xx_enable_giuint(int pin);
+extern void vr41xx_disable_giuint(int pin);
+extern void vr41xx_clear_giuint(int pin);
 extern unsigned int giuint_do_IRQ(int pin, struct pt_regs *regs);
 
-static u32 vr41xx_icu1_base = 0;
-static u32 vr41xx_icu2_base = 0;
+static uint32_t icu1_base;
+static uint32_t icu2_base;
 
-#define VR4111_SYSINT1REG	KSEG1ADDR(0x0b000080)
-#define VR4111_SYSINT2REG	KSEG1ADDR(0x0b000200)
+static unsigned char sysint1_assign[16] = {
+	0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
+static unsigned char sysint2_assign[16] = {
+	2, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
 
-#define VR4122_SYSINT1REG	KSEG1ADDR(0x0f000080)
-#define VR4122_SYSINT2REG	KSEG1ADDR(0x0f0000a0)
+#define SYSINT1REG_TYPE1	KSEG1ADDR(0x0b000080)
+#define SYSINT2REG_TYPE1	KSEG1ADDR(0x0b000200)
+
+#define SYSINT1REG_TYPE2	KSEG1ADDR(0x0f000080)
+#define SYSINT2REG_TYPE2	KSEG1ADDR(0x0f0000a0)
 
 #define SYSINT1REG	0x00
+#define INTASSIGN0	0x04
+#define INTASSIGN1	0x06
 #define GIUINTLREG	0x08
 #define MSYSINT1REG	0x0c
 #define MGIUINTLREG	0x14
 #define NMIREG		0x18
 #define SOFTREG		0x1a
+#define INTASSIGN2	0x1c
+#define INTASSIGN3	0x1e
 
 #define SYSINT2REG	0x00
 #define GIUINTHREG	0x02
 #define MSYSINT2REG	0x06
 #define MGIUINTHREG	0x08
 
-#define read_icu1(offset)	readw(vr41xx_icu1_base + (offset))
-#define write_icu1(val, offset)	writew((val), vr41xx_icu1_base + (offset))
+#define SYSINT1_IRQ_TO_PIN(x)	((x) - SYSINT1_IRQ_BASE)	/* Pin 0-15 */
+#define SYSINT2_IRQ_TO_PIN(x)	((x) - SYSINT2_IRQ_BASE)	/* Pin 0-15 */
+
+#define read_icu1(offset)	readw(icu1_base + (offset))
+#define write_icu1(val, offset)	writew((val), icu1_base + (offset))
 
-#define read_icu2(offset)	readw(vr41xx_icu2_base + (offset))
-#define write_icu2(val, offset)	writew((val), vr41xx_icu2_base + (offset))
+#define read_icu2(offset)	readw(icu2_base + (offset))
+#define write_icu2(val, offset)	writew((val), icu2_base + (offset))
 
-static inline u16 set_icu1(u16 offset, u16 set)
+#define INTASSIGN_MAX	4
+#define INTASSIGN_MASK	0x0007
+
+static inline uint16_t set_icu1(uint8_t offset, uint16_t set)
 {
-	u16 res;
+	uint16_t res;
 
 	res = read_icu1(offset);
 	res |= set;
@@ -100,9 +113,9 @@ static inline u16 set_icu1(u16 offset, u
 	return res;
 }
 
-static inline u16 clear_icu1(u16 offset, u16 clear)
+static inline uint16_t clear_icu1(uint8_t offset, uint16_t clear)
 {
-	u16 res;
+	uint16_t res;
 
 	res = read_icu1(offset);
 	res &= ~clear;
@@ -111,9 +124,9 @@ static inline u16 clear_icu1(u16 offset,
 	return res;
 }
 
-static inline u16 set_icu2(u16 offset, u16 set)
+static inline uint16_t set_icu2(uint8_t offset, uint16_t set)
 {
-	u16 res;
+	uint16_t res;
 
 	res = read_icu2(offset);
 	res |= set;
@@ -122,9 +135,9 @@ static inline u16 set_icu2(u16 offset, u
 	return res;
 }
 
-static inline u16 clear_icu2(u16 offset, u16 clear)
+static inline uint16_t clear_icu2(uint8_t offset, uint16_t clear)
 {
-	u16 res;
+	uint16_t res;
 
 	res = read_icu2(offset);
 	res &= ~clear;
@@ -137,17 +150,17 @@ static inline u16 clear_icu2(u16 offset,
 
 static void enable_sysint1_irq(unsigned int irq)
 {
-	set_icu1(MSYSINT1REG, (u16)1 << (irq - SYSINT1_IRQ_BASE));
+	set_icu1(MSYSINT1REG, (uint16_t)1 << SYSINT1_IRQ_TO_PIN(irq));
 }
 
 static void disable_sysint1_irq(unsigned int irq)
 {
-	clear_icu1(MSYSINT1REG, (u16)1 << (irq - SYSINT1_IRQ_BASE));
+	clear_icu1(MSYSINT1REG, (uint16_t)1 << SYSINT1_IRQ_TO_PIN(irq));
 }
 
 static unsigned int startup_sysint1_irq(unsigned int irq)
 {
-	set_icu1(MSYSINT1REG, (u16)1 << (irq - SYSINT1_IRQ_BASE));
+	set_icu1(MSYSINT1REG, (uint16_t)1 << SYSINT1_IRQ_TO_PIN(irq));
 
 	return 0; /* never anything pending */
 }
@@ -158,35 +171,34 @@ static unsigned int startup_sysint1_irq(
 static void end_sysint1_irq(unsigned int irq)
 {
 	if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS)))
-		set_icu1(MSYSINT1REG, (u16)1 << (irq - SYSINT1_IRQ_BASE));
+		set_icu1(MSYSINT1REG, (uint16_t)1 << SYSINT1_IRQ_TO_PIN(irq));
 }
 
 static struct hw_interrupt_type sysint1_irq_type = {
-	"SYSINT1",
-	startup_sysint1_irq,
-	shutdown_sysint1_irq,
-	enable_sysint1_irq,
-	disable_sysint1_irq,
-	ack_sysint1_irq,
-	end_sysint1_irq,
-	NULL
+	.typename	= "SYSINT1",
+	.startup	= startup_sysint1_irq,
+	.shutdown	= shutdown_sysint1_irq,
+	.enable		= enable_sysint1_irq,
+	.disable	= disable_sysint1_irq,
+	.ack		= ack_sysint1_irq,
+	.end		= end_sysint1_irq,
 };
 
 /*=======================================================================*/
 
 static void enable_sysint2_irq(unsigned int irq)
 {
-	set_icu2(MSYSINT2REG, (u16)1 << (irq - SYSINT2_IRQ_BASE));
+	set_icu2(MSYSINT2REG, (uint16_t)1 << SYSINT2_IRQ_TO_PIN(irq));
 }
 
 static void disable_sysint2_irq(unsigned int irq)
 {
-	clear_icu2(MSYSINT2REG, (u16)1 << (irq - SYSINT2_IRQ_BASE));
+	clear_icu2(MSYSINT2REG, (uint16_t)1 << SYSINT2_IRQ_TO_PIN(irq));
 }
 
 static unsigned int startup_sysint2_irq(unsigned int irq)
 {
-	set_icu2(MSYSINT2REG, (u16)1 << (irq - SYSINT2_IRQ_BASE));
+	set_icu2(MSYSINT2REG, (uint16_t)1 << SYSINT2_IRQ_TO_PIN(irq));
 
 	return 0; /* never anything pending */
 }
@@ -197,18 +209,17 @@ static unsigned int startup_sysint2_irq(
 static void end_sysint2_irq(unsigned int irq)
 {
 	if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS)))
-		set_icu2(MSYSINT2REG, (u16)1 << (irq - SYSINT2_IRQ_BASE));
+		set_icu2(MSYSINT2REG, (uint16_t)1 << SYSINT2_IRQ_TO_PIN(irq));
 }
 
 static struct hw_interrupt_type sysint2_irq_type = {
-	"SYSINT2",
-	startup_sysint2_irq,
-	shutdown_sysint2_irq,
-	enable_sysint2_irq,
-	disable_sysint2_irq,
-	ack_sysint2_irq,
-	end_sysint2_irq,
-	NULL
+	.typename	= "SYSINT2",
+	.startup	= startup_sysint2_irq,
+	.shutdown	= shutdown_sysint2_irq,
+	.enable		= enable_sysint2_irq,
+	.disable	= disable_sysint2_irq,
+	.ack		= ack_sysint2_irq,
+	.end		= end_sysint2_irq,
 };
 
 /*=======================================================================*/
@@ -217,12 +228,11 @@ static void enable_giuint_irq(unsigned i
 {
 	int pin;
 
-	pin = irq - GIU_IRQ_BASE;
+	pin = GIU_IRQ_TO_PIN(irq);
 	if (pin < 16)
-		set_icu1(MGIUINTLREG, (u16)1 << pin);
+		set_icu1(MGIUINTLREG, (uint16_t)1 << pin);
 	else
-		set_icu2(MGIUINTHREG, (u16)1 << (pin - 16));
-
+		set_icu2(MGIUINTHREG, (uint16_t)1 << (pin - 16));
 	vr41xx_enable_giuint(pin);
 }
 
@@ -230,18 +240,17 @@ static void disable_giuint_irq(unsigned 
 {
 	int pin;
 
-	pin = irq - GIU_IRQ_BASE;
+	pin = GIU_IRQ_TO_PIN(irq);
 	vr41xx_disable_giuint(pin);
-
 	if (pin < 16)
-		clear_icu1(MGIUINTLREG, (u16)1 << pin);
+		clear_icu1(MGIUINTLREG, (uint16_t)1 << pin);
 	else
-		clear_icu2(MGIUINTHREG, (u16)1 << (pin - 16));
+		clear_icu2(MGIUINTHREG, (uint16_t)1 << (pin - 16));
 }
 
 static unsigned int startup_giuint_irq(unsigned int irq)
 {
-	vr41xx_clear_giuint(irq - GIU_IRQ_BASE);
+	vr41xx_clear_giuint(GIU_IRQ_TO_PIN(irq));
 
 	enable_giuint_irq(irq);
 
@@ -254,7 +263,7 @@ static void ack_giuint_irq(unsigned int 
 {
 	disable_giuint_irq(irq);
 
-	vr41xx_clear_giuint(irq - GIU_IRQ_BASE);
+	vr41xx_clear_giuint(GIU_IRQ_TO_PIN(irq));
 }
 
 static void end_giuint_irq(unsigned int irq)
@@ -264,14 +273,13 @@ static void end_giuint_irq(unsigned int 
 }
 
 static struct hw_interrupt_type giuint_irq_type = {
-	"GIUINT",
-	startup_giuint_irq,
-	shutdown_giuint_irq,
-	enable_giuint_irq,
-	disable_giuint_irq,
-	ack_giuint_irq,
-	end_giuint_irq,
-	NULL
+	.typename	= "GIUINT",
+	.startup	= startup_giuint_irq,
+	.shutdown	= shutdown_giuint_irq,
+	.enable		= enable_giuint_irq,
+	.disable	= disable_giuint_irq,
+	.ack		= ack_giuint_irq,
+	.end		= end_giuint_irq,
 };
 
 /*=======================================================================*/
@@ -285,13 +293,14 @@ static void __init vr41xx_icu_init(void)
 	switch (current_cpu_data.cputype) {
 	case CPU_VR4111:
 	case CPU_VR4121:
-		vr41xx_icu1_base = VR4111_SYSINT1REG;
-		vr41xx_icu2_base = VR4111_SYSINT2REG;
+		icu1_base = SYSINT1REG_TYPE1;
+		icu2_base = SYSINT2REG_TYPE1;
 		break;
 	case CPU_VR4122:
 	case CPU_VR4131:
-		vr41xx_icu1_base = VR4122_SYSINT1REG;
-		vr41xx_icu2_base = VR4122_SYSINT2REG;
+	case CPU_VR4133:
+		icu1_base = SYSINT1REG_TYPE2;
+		icu2_base = SYSINT2REG_TYPE2;
 		break;
 	default:
 		panic("Unexpected CPU of NEC VR4100 series");
@@ -313,7 +322,11 @@ static void __init vr41xx_icu_init(void)
 			irq_desc[i].handler = &giuint_irq_type;
 	}
 
-	setup_irq(ICU_CASCADE_IRQ, &icu_cascade);
+	setup_irq(INT0_CASCADE_IRQ, &icu_cascade);
+	setup_irq(INT1_CASCADE_IRQ, &icu_cascade);
+	setup_irq(INT2_CASCADE_IRQ, &icu_cascade);
+	setup_irq(INT3_CASCADE_IRQ, &icu_cascade);
+	setup_irq(INT4_CASCADE_IRQ, &icu_cascade);
 }
 
 void __init init_IRQ(void)
@@ -327,31 +340,171 @@ void __init init_IRQ(void)
 	vr41xx_giuint_init();
 
 	set_except_vector(0, vr41xx_handle_interrupt);
+}
+
+/*=======================================================================*/
+
+static inline int set_sysint1_assign(unsigned int irq, unsigned char assign)
+{
+	irq_desc_t *desc = irq_desc + irq;
+	uint16_t intassign0, intassign1;
+	unsigned int pin;
+
+	pin = SYSINT1_IRQ_TO_PIN(irq);
+
+	spin_lock_irq(&desc->lock);
 
-#ifdef CONFIG_KGDB
-	printk("Setting debug traps - please connect the remote debugger.\n");
-	set_debug_traps();
-	breakpoint();
-#endif
+	intassign0 = read_icu1(INTASSIGN0);
+	intassign1 = read_icu1(INTASSIGN1);
+
+	switch (pin) {
+	case 0:
+		intassign0 &= ~INTASSIGN_MASK;
+		intassign0 |= (uint16_t)assign;
+		break;
+	case 1:
+		intassign0 &= ~(INTASSIGN_MASK << 3);
+		intassign0 |= (uint16_t)assign << 3;
+		break;
+	case 2:
+		intassign0 &= ~(INTASSIGN_MASK << 6);
+		intassign0 |= (uint16_t)assign << 6;
+		break;
+	case 3:
+		intassign0 &= ~(INTASSIGN_MASK << 9);
+		intassign0 |= (uint16_t)assign << 9;
+		break;
+	case 8:
+		intassign0 &= ~(INTASSIGN_MASK << 12);
+		intassign0 |= (uint16_t)assign << 12;
+		break;
+	case 9:
+		intassign1 &= ~INTASSIGN_MASK;
+		intassign1 |= (uint16_t)assign;
+		break;
+	case 11:
+		intassign1 &= ~(INTASSIGN_MASK << 6);
+		intassign1 |= (uint16_t)assign << 6;
+		break;
+	case 12:
+		intassign1 &= ~(INTASSIGN_MASK << 9);
+		intassign1 |= (uint16_t)assign << 9;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	sysint1_assign[pin] = assign;
+	write_icu1(intassign0, INTASSIGN0);
+	write_icu1(intassign1, INTASSIGN1);
+
+	spin_unlock_irq(&desc->lock);
+
+	return 0;
+}
+
+static inline int set_sysint2_assign(unsigned int irq, unsigned char assign)
+{
+	irq_desc_t *desc = irq_desc + irq;
+	uint16_t intassign2, intassign3;
+	unsigned int pin;
+
+	pin = SYSINT2_IRQ_TO_PIN(irq);
+
+	spin_lock_irq(&desc->lock);
+
+	intassign2 = read_icu1(INTASSIGN2);
+	intassign3 = read_icu1(INTASSIGN3);
+
+	switch (pin) {
+	case 0:
+		intassign2 &= ~INTASSIGN_MASK;
+		intassign2 |= (uint16_t)assign;
+		break;
+	case 1:
+		intassign2 &= ~(INTASSIGN_MASK << 3);
+		intassign2 |= (uint16_t)assign << 3;
+		break;
+	case 3:
+		intassign2 &= ~(INTASSIGN_MASK << 6);
+		intassign2 |= (uint16_t)assign << 6;
+		break;
+	case 4:
+		intassign2 &= ~(INTASSIGN_MASK << 9);
+		intassign2 |= (uint16_t)assign << 9;
+		break;
+	case 5:
+		intassign2 &= ~(INTASSIGN_MASK << 12);
+		intassign2 |= (uint16_t)assign << 12;
+		break;
+	case 6:
+		intassign3 &= ~INTASSIGN_MASK;
+		intassign3 |= (uint16_t)assign;
+		break;
+	case 7:
+		intassign3 &= ~(INTASSIGN_MASK << 3);
+		intassign3 |= (uint16_t)assign << 3;
+		break;
+	case 8:
+		intassign3 &= ~(INTASSIGN_MASK << 6);
+		intassign3 |= (uint16_t)assign << 6;
+		break;
+	case 9:
+		intassign3 &= ~(INTASSIGN_MASK << 9);
+		intassign3 |= (uint16_t)assign << 9;
+		break;
+	case 10:
+		intassign3 &= ~(INTASSIGN_MASK << 12);
+		intassign3 |= (uint16_t)assign << 12;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	sysint2_assign[pin] = assign;
+	write_icu1(intassign2, INTASSIGN2);
+	write_icu1(intassign3, INTASSIGN3);
+
+	spin_unlock_irq(&desc->lock);
+
+	return 0;
+}
+
+int vr41xx_set_intassign(unsigned int irq, unsigned char intassign)
+{
+	int retval = -EINVAL;
+
+	if (current_cpu_data.cputype != CPU_VR4133)
+		return -EINVAL;
+
+	if (intassign > INTASSIGN_MAX)
+		return -EINVAL;
+
+	if (irq >= SYSINT1_IRQ_BASE && irq <= SYSINT1_IRQ_LAST)
+		retval = set_sysint1_assign(irq, intassign);
+	else if (irq >= SYSINT2_IRQ_BASE && irq <= SYSINT2_IRQ_LAST)
+		retval = set_sysint2_assign(irq, intassign);
+
+	return retval;
 }
 
 /*=======================================================================*/
 
-static inline void giuint_irqdispatch(u16 pendl, u16 pendh, struct pt_regs *regs)
+static inline void giuint_irq_dispatch(uint16_t pendl, uint16_t pendh,
+                                       struct pt_regs *regs)
 {
 	int i;
 
 	if (pendl) {
 		for (i = 0; i < 16; i++) {
-			if (pendl & (0x0001 << i)) {
+			if (pendl & ((uint16_t)1 << i)) {
 				giuint_do_IRQ(i, regs);
 				return;
 			}
 		}
-	}
-	else if (pendh) {
+	} else {
 		for (i = 0; i < 16; i++) {
-			if (pendh & (0x0001 << i)) {
+			if (pendh & ((uint16_t)1 << i)) {
 				giuint_do_IRQ(i + 16, regs);
 				return;
 			}
@@ -359,10 +512,10 @@ static inline void giuint_irqdispatch(u1
 	}
 }
 
-asmlinkage void icu_irqdispatch(struct pt_regs *regs)
+asmlinkage void irq_dispatch(unsigned char intnum, struct pt_regs *regs)
 {
-	u16 pend1, pend2, pendl, pendh;
-	u16 mask1, mask2, maskl, maskh;
+	uint16_t pend1, pend2, pendl, pendh;
+	uint16_t mask1, mask2, maskl, maskh;
 	int i;
 
 	pend1 = read_icu1(SYSINT1REG);
@@ -377,31 +530,36 @@ asmlinkage void icu_irqdispatch(struct p
 	pendh = read_icu2(GIUINTHREG);
 	maskh = read_icu2(MGIUINTHREG);
 
-	pend1 &= mask1;
-	pend2 &= mask2;
-	pendl &= maskl;
-	pendh &= maskh;
-
-	if (pend1) {
-		if ((pend1 & 0x01ff) == 0x0100) {
-			giuint_irqdispatch(pendl, pendh, regs);
-		}
-		else {
-			for (i = 0; i < 16; i++) {
-				if (pend1 & (0x0001 << i)) {
-					do_IRQ(SYSINT1_IRQ_BASE + i, regs);
-					break;
+	mask1 &= pend1;
+	mask2 &= pend2;
+	maskl &= pendl;
+	maskh &= pendh;
+
+	if (mask1) {
+		for (i = 0; i < 16; i++) {
+			if (intnum == sysint1_assign[i] &&
+			    (mask1 & ((uint16_t)1 << i))) {
+				if (i == 8 && (maskl | maskh)) {
+					giuint_irq_dispatch(maskl, maskh, regs);
+					return;
+				} else {
+					do_IRQ(SYSINT1_IRQ(i), regs);
+					return;
 				}
 			}
 		}
-		return;
 	}
-	else if (pend2) {
+
+	if (mask2) {
 		for (i = 0; i < 16; i++) {
-			if (pend2 & (0x0001 << i)) {
-				do_IRQ(SYSINT2_IRQ_BASE + i, regs);
-				break;
+			if (intnum == sysint2_assign[i] &&
+			    (mask2 & ((uint16_t)1 << i))) {
+				do_IRQ(SYSINT2_IRQ(i), regs);
+				return;
 			}
 		}
 	}
+
+	printk(KERN_ERR "spurious interrupt: %04x,%04x,%04x,%04x\n", pend1, pend2, pendl, pendh);
+	atomic_inc(&irq_err_count);
 }
--- diff/arch/mips/vr41xx/common/int-handler.S	2003-07-08 09:55:17.000000000 +0100
+++ source/arch/mips/vr41xx/common/int-handler.S	2004-02-23 13:56:38.000000000 +0000
@@ -34,6 +34,9 @@
  * Changes:
  *  MontaVista Software Inc. <yyuasa@mvista.com> or <source@mvista.com>
  *  - New creation, NEC VR4100 series are supported.
+ *
+ *  Yoichi Yuasa <yuasa@hh.iij4u.or.jp>
+ *  - Coped with INTASSIGN of NEC VR4133.
  */
 #include <asm/asm.h>
 #include <asm/regdef.h>
@@ -59,55 +62,52 @@
 		andi	t0, 0xff00
 		and	t0, t0, t1
 
-		andi	t1, t0, CAUSEF_IP7	# timer interrupt
-		beqz	t1, 1f
+		andi	t1, t0, CAUSEF_IP7	# MIPS timer interrupt
+		bnez	t1, handle_irq
 		li	a0, 7
-		jal	ll_timer_interrupt
-		move	a1, sp
-		j	ret_from_irq
 
-1:
-		andi	t1, t0, 0x7800		# check for IP3-6
-		beqz	t1, 2f
+		andi	t1, t0, 0x7800		# check for Int1-4
+		beqz	t1, 1f
 
-		andi	t1, t0, CAUSEF_IP3	# check for IP3
-		bnez	t1, handle_it
+		andi	t1, t0, CAUSEF_IP3	# check for Int1
+		bnez	t1, handle_int
+		li	a0, 1
+
+		andi	t1, t0, CAUSEF_IP4	# check for Int2
+		bnez	t1, handle_int
+		li	a0, 2
+
+		andi	t1, t0, CAUSEF_IP5	# check for Int3
+		bnez	t1, handle_int
 		li	a0, 3
 
-		andi	t1, t0, CAUSEF_IP4	# check for IP4
-		bnez	t1, handle_it
+		andi	t1, t0, CAUSEF_IP6	# check for Int4
+		bnez	t1, handle_int
 		li	a0, 4
 
-		andi	t1, t0, CAUSEF_IP5	# check for IP5
-		bnez	t1, handle_it
-		li	a0, 5
-
-		andi	t1, t0, CAUSEF_IP6	# check for IP6
-		bnez	t1, handle_it
-		li	a0, 6
-
-2:
-		andi	t1, t0, CAUSEF_IP2	# check for IP2
-		beqz	t1, 3f
-		move	a0, sp
-		jal	icu_irqdispatch
-		nop
-		j	ret_from_irq
-		nop
+1:
+		andi	t1, t0, CAUSEF_IP2	# check for Int0
+		bnez	t1, handle_int
+		li	a0, 0
 
-3:
 		andi	t1, t0, CAUSEF_IP0	# check for IP0
-		bnez	t1, handle_it
+		bnez	t1, handle_irq
 		li	a0, 0
 
 		andi	t1, t0, CAUSEF_IP1	# check for IP1
-		bnez	t1, handle_it
+		bnez	t1, handle_irq
 		li	a0, 1
 
 		j	spurious_interrupt
 		nop
 
-handle_it:
+handle_int:
+		jal	irq_dispatch
+		move	a1, sp
+		j	ret_from_irq
+		nop
+
+handle_irq:
 		jal	do_IRQ
 		move	a1, sp
 		j	ret_from_irq
--- diff/arch/mips/vr41xx/common/serial.c	2003-07-08 09:55:17.000000000 +0100
+++ source/arch/mips/vr41xx/common/serial.c	2004-02-23 13:56:38.000000000 +0000
@@ -33,14 +33,16 @@
 /*
  * Changes:
  *  MontaVista Software Inc. <yyuasa@mvista.com> or <source@mvista.com>
+ *  - New creation, NEC VR4122 and VR4131 are supported.
  *  - Added support for NEC VR4111 and VR4121.
  *
- *  MontaVista Software Inc. <yyuasa@mvista.com> or <source@mvista.com>
- *  - New creation, NEC VR4122 and VR4131 are supported.
+ *  Yoichi Yuasa <yuasa@hh.iij4u.or.jp>
+ *  - Added support for NEC VR4133.
  */
 #include <linux/init.h>
 #include <linux/types.h>
 #include <linux/serial.h>
+#include <linux/smp.h>
 
 #include <asm/addrspace.h>
 #include <asm/cpu.h>
@@ -48,12 +50,12 @@
 #include <asm/vr41xx/vr41xx.h>
 
 /* VR4111 and VR4121 SIU Registers */
-#define VR4111_SIURB		KSEG1ADDR(0x0c000000)
-#define VR4111_SIUIRSEL		KSEG1ADDR(0x0c000008)
+#define SIURB_TYPE1		KSEG1ADDR(0x0c000000)
+#define SIUIRSEL_TYPE1		KSEG1ADDR(0x0c000008)
 
-/* VR4122 and VR4131 SIU Registers */
-#define VR4122_SIURB		KSEG1ADDR(0x0f000800)
-#define VR4122_SIUIRSEL		KSEG1ADDR(0x0f000808)
+/* VR4122, VR4131 and VR4133 SIU Registers */
+#define SIURB_TYPE2		KSEG1ADDR(0x0f000800)
+#define SIUIRSEL_TYPE2		KSEG1ADDR(0x0f000808)
 
  #define USE_RS232C		0x00
  #define USE_IRDA		0x01
@@ -66,7 +68,6 @@
  #define TMICMODE		0x20
 
 #define SIU_BASE_BAUD		1152000
-#define SIU_CLOCK		0x0102
 
 /* VR4122 and VR4131 DSIU Registers */
 #define DSIURB			KSEG1ADDR(0x0f000820)
@@ -75,7 +76,6 @@
  #define INTDSIU		0x0800
 
 #define DSIU_BASE_BAUD		1152000
-#define DSIU_CLOCK		0x0802
 
 int vr41xx_serial_ports = 0;
 
@@ -102,11 +102,12 @@ void vr41xx_siu_ifselect(int interface, 
 	switch (current_cpu_data.cputype) {
 	case CPU_VR4111:
 	case CPU_VR4121:
-		writew(val, VR4111_SIUIRSEL);
+		writew(val, SIUIRSEL_TYPE1);
 		break;
 	case CPU_VR4122:
 	case CPU_VR4131:
-		writew(val, VR4122_SIUIRSEL);
+	case CPU_VR4133:
+		writew(val, SIUIRSEL_TYPE2);
 		break;
 	default:
 		printk(KERN_INFO "Unexpected CPU of NEC VR4100 series\n");
@@ -129,11 +130,12 @@ void __init vr41xx_siu_init(int interfac
 	switch (current_cpu_data.cputype) {
 	case CPU_VR4111:
 	case CPU_VR4121:
-		s.iomem_base = (unsigned char *)VR4111_SIURB;
+		s.iomem_base = (unsigned char *)SIURB_TYPE1;
 		break;
 	case CPU_VR4122:
 	case CPU_VR4131:
-		s.iomem_base = (unsigned char *)VR4122_SIURB;
+	case CPU_VR4133:
+		s.iomem_base = (unsigned char *)SIURB_TYPE2;
 		break;
 	default:
 		panic("Unexpected CPU of NEC VR4100 series");
@@ -154,7 +156,8 @@ void __init vr41xx_dsiu_init(void)
 	struct serial_struct s;
 
 	if (current_cpu_data.cputype != CPU_VR4122 &&
-	    current_cpu_data.cputype != CPU_VR4131)
+	    current_cpu_data.cputype != CPU_VR4131 &&
+	    current_cpu_data.cputype != CPU_VR4133)
 		return;
 
 	memset(&s, 0, sizeof(s));
--- diff/arch/mips/vr41xx/common/vrc4173.c	2003-09-17 12:28:02.000000000 +0100
+++ source/arch/mips/vr41xx/common/vrc4173.c	2004-02-23 13:56:38.000000000 +0000
@@ -30,7 +30,6 @@
  *  with this program; if not, write to the Free Software Foundation, Inc.,
  *  675 Mass Ave, Cambridge, MA 02139, USA.
  */
-#include <linux/config.h>
 #include <linux/init.h>
 #include <linux/module.h>
 #include <linux/interrupt.h>
@@ -195,8 +194,8 @@ static inline void vrc4173_icu_init(int 
 	
 	vrc4173_outw(0, VRC4173_MSYSINT1REG);
 
-	vr41xx_set_irq_trigger(cascade_irq - GIU_IRQ(0), TRIGGER_LEVEL, SIGNAL_THROUGH);
-	vr41xx_set_irq_level(cascade_irq - GIU_IRQ(0), LEVEL_LOW);
+	vr41xx_set_irq_trigger(GIU_IRQ_TO_PIN(cascade_irq), TRIGGER_LEVEL, SIGNAL_THROUGH);
+	vr41xx_set_irq_level(GIU_IRQ_TO_PIN(cascade_irq), LEVEL_LOW);
 
 	for (i = VRC4173_IRQ_BASE; i <= VRC4173_IRQ_LAST; i++)
                 irq_desc[i].handler = &vrc4173_irq_type;
--- diff/arch/mips/vr41xx/ibm-workpad/Makefile	2003-07-08 09:55:17.000000000 +0100
+++ source/arch/mips/vr41xx/ibm-workpad/Makefile	2004-02-23 13:56:38.000000000 +0000
@@ -3,4 +3,3 @@
 #
 
 obj-y			+= init.o setup.o
-obj-$(CONFIG_IDE)	+= ide-workpad.o
--- diff/arch/mips/vr41xx/ibm-workpad/init.c	2003-07-08 09:55:17.000000000 +0100
+++ source/arch/mips/vr41xx/ibm-workpad/init.c	2004-02-23 13:56:38.000000000 +0000
@@ -13,22 +13,21 @@
  *  Free Software Foundation; either version 2 of the License, or (at your
  *  option) any later version.
  */
-#include <linux/config.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/string.h>
 
 #include <asm/bootinfo.h>
 
-char arcs_cmdline[CL_SIZE];
-
 const char *get_system_type(void)
 {
 	return "IBM WorkPad z50";
 }
 
-void __init prom_init(int argc, char **argv, unsigned long magic, int *prom_vec)
+void __init prom_init(void)
 {
+	int argc = fw_arg0;
+	char **argv = (char **) fw_arg1;
 	int i;
 
 	/*
@@ -44,6 +43,7 @@ void __init prom_init(int argc, char **a
 	mips_machtype = MACH_IBM_WORKPAD;
 }
 
-void __init prom_free_prom_memory (void)
+unsigned long __init prom_free_prom_memory(void)
 {
+	return 0;
 }
--- diff/arch/mips/vr41xx/ibm-workpad/setup.c	2003-07-08 09:55:17.000000000 +0100
+++ source/arch/mips/vr41xx/ibm-workpad/setup.c	2004-02-23 13:56:38.000000000 +0000
@@ -1,28 +1,29 @@
 /*
- * FILE NAME
- *	arch/mips/vr41xx/workpad/setup.c
+ *  setup.c, Setup for the IBM WorkPad z50.
  *
- * BRIEF MODULE DESCRIPTION
- *	Setup for the IBM WorkPad z50.
+ *  Copyright (C) 2002-2003  Yoichi Yuasa <yuasa@hh.iij4u.or.jp>
  *
- * Copyright 2002 Yoichi Yuasa
- *                yuasa@hh.iij4u.or.jp
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
  *
- *  This program is free software; you can redistribute it and/or modify it
- *  under the terms of the GNU General Public License as published by the
- *  Free Software Foundation; either version 2 of the License, or (at your
- *  option) any later version.
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
 #include <linux/config.h>
 #include <linux/init.h>
-#include <linux/console.h>
-#include <linux/ide.h>
 #include <linux/ioport.h>
 #include <linux/major.h>
 #include <linux/kdev_t.h>
 #include <linux/root_dev.h>
 
-#include <asm/reboot.h>
 #include <asm/time.h>
 #include <asm/vr41xx/workpad.h>
 
@@ -31,11 +32,7 @@ extern unsigned long initrd_start, initr
 extern void * __rd_start, * __rd_end;
 #endif
 
-#ifdef CONFIG_BLK_DEV_IDE
-extern struct ide_ops workpad_ide_ops;
-#endif
-
-void __init ibm_workpad_setup(void)
+static void __init ibm_workpad_setup(void)
 {
 	set_io_port_base(IO_PORT_BASE);
 	ioport_resource.start = IO_PORT_RESOURCE_START;
@@ -49,26 +46,18 @@ void __init ibm_workpad_setup(void)
 	initrd_end = (unsigned long)&__rd_end;
 #endif
 
-	_machine_restart = vr41xx_restart;
-	_machine_halt = vr41xx_halt;
-	_machine_power_off = vr41xx_power_off;
-
 	board_time_init = vr41xx_time_init;
 	board_timer_setup = vr41xx_timer_setup;
 
-#ifdef CONFIG_FB
-	conswitchp = &dummy_con;
-#endif
-
-#ifdef CONFIG_BLK_DEV_IDE
-	ide_ops = &workpad_ide_ops;
-#endif
-
 	vr41xx_bcu_init();
 
-	vr41xx_cmu_init(0);
+	vr41xx_cmu_init();
+
+	vr41xx_pmu_init();
 
 #ifdef CONFIG_SERIAL_8250
 	vr41xx_siu_init(SIU_RS232C, 0);
 #endif
 }
+
+early_initcall(ibm_workpad_setup);
--- diff/arch/mips/vr41xx/nec-eagle/Makefile	2003-07-08 09:55:17.000000000 +0100
+++ source/arch/mips/vr41xx/nec-eagle/Makefile	2004-02-23 13:56:38.000000000 +0000
@@ -8,4 +8,3 @@
 #
 
 obj-y			+= init.o irq.o setup.o
-obj-$(CONFIG_IDE)	+= ide-eagle.o
--- diff/arch/mips/vr41xx/nec-eagle/init.c	2003-07-08 09:55:17.000000000 +0100
+++ source/arch/mips/vr41xx/nec-eagle/init.c	2004-02-23 13:56:38.000000000 +0000
@@ -38,22 +38,21 @@
  *  MontaVista Software Inc. <yyuasa@mvista.com> or <source@mvista.com>
  *  - New creation, NEC Eagle is supported.
  */
-#include <linux/config.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/string.h>
 
 #include <asm/bootinfo.h>
 
-char arcs_cmdline[CL_SIZE];
-
 const char *get_system_type(void)
 {
 	return "NEC Eagle/Hawk";
 }
 
-void __init prom_init(int argc, char **argv, unsigned long magic, int *prom_vec)
+void __init prom_init(void)
 {
+	int argc = fw_arg0;
+	char **argv = (char **) fw_arg1;
 	int i;
 
 	/*
@@ -69,6 +68,7 @@ void __init prom_init(int argc, char **a
 	mips_machtype = MACH_NEC_EAGLE;
 }
 
-void __init prom_free_prom_memory (void)
+unsigned long __init prom_free_prom_memory(void)
 {
+	return 0;
 }
--- diff/arch/mips/vr41xx/nec-eagle/setup.c	2003-07-08 09:55:17.000000000 +0100
+++ source/arch/mips/vr41xx/nec-eagle/setup.c	2004-02-23 13:56:38.000000000 +0000
@@ -1,55 +1,23 @@
 /*
- * FILE NAME
- *	arch/mips/vr41xx/nec-eagle/setup.c
+ * arch/mips/vr41xx/nec-eagle/setup.c
  *
- * BRIEF MODULE DESCRIPTION
- *	Setup for the NEC Eagle/Hawk board.
+ * Setup for the NEC Eagle/Hawk board.
  *
- * Author: Yoichi Yuasa
- *         yyuasa@mvista.com or source@mvista.com
+ * Author: Yoichi Yuasa <yyuasa@mvista.com, or source@mvista.com>
  *
- * Copyright 2001,2002 MontaVista Software Inc.
- *
- *  This program is free software; you can redistribute it and/or modify it
- *  under the terms of the GNU General Public License as published by the
- *  Free Software Foundation; either version 2 of the License, or (at your
- *  option) any later version.
- *
- *  THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
- *  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- *  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
- *  OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- *  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
- *  TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
- *  USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- *  You should have received a copy of the GNU General Public License along
- *  with this program; if not, write to the Free Software Foundation, Inc.,
- *  675 Mass Ave, Cambridge, MA 02139, USA.
- */
-/*
- * Changes:
- *  MontaVista Software Inc. <yyuasa@mvista.com> or <source@mvista.com>
- *  - Moved mips_pci_channels[] from arch/mips/vr41xx/vr4122/eagle/setup.c.
- *  - Added support for NEC Hawk.
- *
- *  MontaVista Software Inc. <yyuasa@mvista.com> or <source@mvista.com>
- *  - New creation, NEC Eagle is supported.
+ * 2001-2004 (c) MontaVista, Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
  */
 #include <linux/config.h>
 #include <linux/init.h>
-#include <linux/console.h>
-#include <linux/ide.h>
 #include <linux/ioport.h>
 #include <linux/major.h>
 #include <linux/kdev_t.h>
 #include <linux/root_dev.h>
 
 #include <asm/pci_channel.h>
-#include <asm/reboot.h>
 #include <asm/time.h>
 #include <asm/vr41xx/eagle.h>
 
@@ -58,10 +26,6 @@ extern unsigned long initrd_start, initr
 extern void * __rd_start, * __rd_end;
 #endif
 
-#ifdef CONFIG_BLK_DEV_IDE
-extern struct ide_ops eagle_ide_ops;
-#endif
-
 extern void eagle_irq_init(void);
 
 #ifdef CONFIG_PCI
@@ -84,9 +48,10 @@ static struct resource vr41xx_pci_mem_re
 
 extern struct pci_ops vr41xx_pci_ops;
 
-struct pci_channel mips_pci_channels[] = {
-	{&vr41xx_pci_ops, &vr41xx_pci_io_resource, &vr41xx_pci_mem_resource, 0, 256},
-	{NULL, NULL, NULL, 0, 0}
+struct pci_controller vr41xx_controller = {
+	.pci_ops	= &vr41xx_pci_ops,
+	.io_resource	= &vr41xx_pci_io_resource,
+	.mem_resource	= &vr41xx_pci_mem_resource,
 };
 
 struct vr41xx_pci_address_space vr41xx_pci_mem1 = {
@@ -114,7 +79,7 @@ static struct vr41xx_pci_address_map pci
 };
 #endif
 
-void __init nec_eagle_setup(void)
+static int nec_eagle_setup(void)
 {
 	set_io_port_base(IO_PORT_BASE);
 	ioport_resource.start = IO_PORT_RESOURCE_START;
@@ -128,26 +93,16 @@ void __init nec_eagle_setup(void)
 	initrd_end = (unsigned long)&__rd_end;
 #endif
 
-	_machine_restart = vr41xx_restart;
-	_machine_halt = vr41xx_halt;
-	_machine_power_off = vr41xx_power_off;
-
 	board_time_init = vr41xx_time_init;
 	board_timer_setup = vr41xx_timer_setup;
 
 	board_irq_init = eagle_irq_init;
 
-#ifdef CONFIG_FB
-	conswitchp = &dummy_con;
-#endif
-
-#ifdef CONFIG_BLK_DEV_IDE
-	ide_ops = &eagle_ide_ops;
-#endif
-
 	vr41xx_bcu_init();
 
-	vr41xx_cmu_init(0);
+	vr41xx_cmu_init();
+
+	vr41xx_pmu_init();
 
 #ifdef CONFIG_SERIAL_8250
 	vr41xx_dsiu_init();
@@ -159,4 +114,8 @@ void __init nec_eagle_setup(void)
 
 	vrc4173_preinit();
 #endif
+
+	return 0;
 }
+
+early_initcall(nec_eagle_setup);
--- diff/arch/mips/vr41xx/tanbac-tb0226/init.c	2003-07-08 09:55:17.000000000 +0100
+++ source/arch/mips/vr41xx/tanbac-tb0226/init.c	2004-02-23 13:56:38.000000000 +0000
@@ -13,9 +13,9 @@
  *  Free Software Foundation; either version 2 of the License, or (at your
  *  option) any later version.
  */
-#include <linux/config.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
+#include <linux/smp.h>
 #include <linux/string.h>
 
 #include <asm/bootinfo.h>
@@ -23,16 +23,15 @@
 #include <asm/mipsregs.h>
 #include <asm/vr41xx/vr41xx.h>
 
-char arcs_cmdline[CL_SIZE];
-
 const char *get_system_type(void)
 {
 	return "TANBAC TB0226";
 }
 
-void __init prom_init(int argc, char **argv, unsigned long magic, int *prom_vec)
+void __init prom_init(void)
 {
-	u32 config;
+	int argc = fw_arg0;
+	char **argv = (char **) fw_arg1;
 	int i;
 
 	/*
@@ -46,19 +45,9 @@ void __init prom_init(int argc, char **a
 
 	mips_machgroup = MACH_GROUP_NEC_VR41XX;
 	mips_machtype = MACH_TANBAC_TB0226;
-
-	switch (current_cpu_data.processor_id) {
-	case PRID_VR4131_REV1_2:
-		config = read_c0_config();
-		config &= ~0x00000030UL;
-		config |= 0x00410000UL;
-		write_c0_config(config);
-		break;
-	default:
-		break;
-	}
 }
 
-void __init prom_free_prom_memory (void)
+unsigned long __init prom_free_prom_memory(void)
 {
+	return 0;
 }
--- diff/arch/mips/vr41xx/tanbac-tb0226/setup.c	2003-07-08 09:55:17.000000000 +0100
+++ source/arch/mips/vr41xx/tanbac-tb0226/setup.c	2004-02-23 13:56:38.000000000 +0000
@@ -1,26 +1,27 @@
 /*
- * FILE NAME
- *	arch/mips/vr41xx/tanbac-tb0226/setup.c
+ *  setup.c, Setup for the TANBAC TB0226.
  *
- * BRIEF MODULE DESCRIPTION
- *	Setup for the TANBAC TB0226.
+ *  Copyright (C) 2002-2003  Yoichi Yuasa <yuasa@hh.iij4u.or.jp>
  *
- * Copyright 2002,2003 Yoichi Yuasa
- *                yuasa@hh.iij4u.or.jp
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
  *
- *  This program is free software; you can redistribute it and/or modify it
- *  under the terms of the GNU General Public License as published by the
- *  Free Software Foundation; either version 2 of the License, or (at your
- *  option) any later version.
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
 #include <linux/config.h>
 #include <linux/init.h>
-#include <linux/console.h>
-#include <linux/ide.h>
 #include <linux/ioport.h>
 
 #include <asm/pci_channel.h>
-#include <asm/reboot.h>
 #include <asm/time.h>
 #include <asm/vr41xx/tb0226.h>
 
@@ -46,17 +47,10 @@ static struct resource vr41xx_pci_mem_re
 
 extern struct pci_ops vr41xx_pci_ops;
 
-struct pci_channel mips_pci_channels[] = {
-	{	.pci_ops	= &vr41xx_pci_ops,
-		.io_resource	= &vr41xx_pci_io_resource,
-		.mem_resource	= &vr41xx_pci_mem_resource,
-		.first_devfn	= 0,
-		.last_devfn	= 256, },
-	{	.pci_ops	= NULL,
-		.io_resource	= NULL,
-		.mem_resource	= NULL,
-		.first_devfn	= 0,
-		.last_devfn	= 0, },
+struct pci_controller vr41xx_controller[] = {
+	.pci_ops	= &vr41xx_pci_ops,
+	.io_resource	= &vr41xx_pci_io_resource,
+	.mem_resource	= &vr41xx_pci_mem_resource,
 };
 
 struct vr41xx_pci_address_space vr41xx_pci_mem1 = {
@@ -98,20 +92,14 @@ void __init tanbac_tb0226_setup(void)
 	initrd_end = (unsigned long)&__rd_end;
 #endif
 
-	_machine_restart = vr41xx_restart;
-	_machine_halt = vr41xx_halt;
-	_machine_power_off = vr41xx_power_off;
-
 	board_time_init = vr41xx_time_init;
 	board_timer_setup = vr41xx_timer_setup;
 
-#ifdef CONFIG_FB
-	conswitchp = &dummy_con;
-#endif
-
 	vr41xx_bcu_init();
 
-	vr41xx_cmu_init(0);
+	vr41xx_cmu_init();
+
+	vr41xx_pmu_init();
 
 	vr41xx_siu_init(SIU_RS232C, 0);
 
@@ -119,3 +107,5 @@ void __init tanbac_tb0226_setup(void)
 	vr41xx_pciu_init(&pci_address_map);
 #endif
 }
+
+early_initcall(tanbac_tb0226_setup);
--- diff/arch/mips/vr41xx/tanbac-tb0229/Makefile	2003-07-08 09:55:17.000000000 +0100
+++ source/arch/mips/vr41xx/tanbac-tb0229/Makefile	2004-02-23 13:56:38.000000000 +0000
@@ -2,4 +2,6 @@
 # Makefile for the TANBAC TB0229(VR4131DIMM) specific parts of the kernel
 #
 
-obj-y			:= init.o reboot.o setup.o
+obj-y				:= init.o setup.o
+
+obj-$(CONFIG_TANBAC_TB0219)	+= reboot.o
--- diff/arch/mips/vr41xx/tanbac-tb0229/init.c	2003-07-08 09:55:17.000000000 +0100
+++ source/arch/mips/vr41xx/tanbac-tb0229/init.c	2004-02-23 13:56:38.000000000 +0000
@@ -17,10 +17,10 @@
  *  Free Software Foundation; either version 2 of the License, or (at your
  *  option) any later version.
  */
-#include <linux/config.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/sched.h>
+#include <linux/smp.h>
 #include <linux/string.h>
 
 #include <asm/bootinfo.h>
@@ -28,16 +28,15 @@
 #include <asm/mipsregs.h>
 #include <asm/vr41xx/vr41xx.h>
 
-char arcs_cmdline[CL_SIZE];
-
 const char *get_system_type(void)
 {
 	return "TANBAC TB0229";
 }
 
-void __init prom_init(int argc, char **argv, unsigned long magic, int *prom_vec)
+void __init prom_init(void)
 {
-	u32 config;
+	int argc = fw_arg0;
+	char **argv = (char **) fw_arg1;
 	int i;
 
 	/*
@@ -51,19 +50,9 @@ void __init prom_init(int argc, char **a
 
 	mips_machgroup = MACH_GROUP_NEC_VR41XX;
 	mips_machtype = MACH_TANBAC_TB0229;
-
-	switch (current_cpu_data.processor_id) {
-	case PRID_VR4131_REV1_2:
-		config = read_c0_config();
-		config &= ~0x00000030UL;
-		config |= 0x00410000UL;
-		write_c0_config(config);
-		break;
-	default:
-		break;
-	}
 }
 
-void __init prom_free_prom_memory (void)
+unsigned long __init prom_free_prom_memory(void)
 {
+	return 0;
 }
--- diff/arch/mips/vr41xx/tanbac-tb0229/reboot.c	2003-07-08 09:55:17.000000000 +0100
+++ source/arch/mips/vr41xx/tanbac-tb0229/reboot.c	2004-02-23 13:56:38.000000000 +0000
@@ -13,6 +13,7 @@
  *  Free Software Foundation; either version 2 of the License, or (at your
  *  option) any later version.
  */
+#include <linux/config.h>
 #include <asm/io.h>
 #include <asm/vr41xx/tb0229.h>
 
@@ -20,11 +21,7 @@
 
 void tanbac_tb0229_restart(char *command)
 {
-#ifdef CONFIG_TANBAC_TB0219
 	local_irq_disable();
 	tb0229_hard_reset();
 	while (1);
-#else
-	vr41xx_restart(command);
-#endif
 }
--- diff/arch/mips/vr41xx/tanbac-tb0229/setup.c	2003-08-20 14:16:08.000000000 +0100
+++ source/arch/mips/vr41xx/tanbac-tb0229/setup.c	2004-02-23 13:56:38.000000000 +0000
@@ -1,25 +1,27 @@
 /*
- * FILE NAME
- *	arch/mips/vr41xx/tanbac-tb0229/setup.c
+ *  setup.c, Setup for the TANBAC TB0229 (VR4131DIMM)
  *
- * BRIEF MODULE DESCRIPTION
- *	Setup for the TANBAC TB0229 (VR4131DIMM)
+ *  Copyright (C) 2002-2003  Yoichi Yuasa <yuasa@hh.iij4u.or.jp>
  *
- * Copyright 2002,2003 Yoichi Yuasa
- *                yuasa@hh.iij4u.or.jp
+ *  Modified for TANBAC TB0229:
+ *  Copyright (C) 2003  Megasolution Inc.  <matsu@megasolution.jp>
  *
- * Modified for TANBAC TB0229:
- * Copyright 2003 Megasolution Inc.
- *                matsu@megasolution.jp
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
  *
- *  This program is free software; you can redistribute it and/or modify it
- *  under the terms of the GNU General Public License as published by the
- *  Free Software Foundation; either version 2 of the License, or (at your
- *  option) any later version.
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
 #include <linux/config.h>
 #include <linux/blkdev.h>
-#include <linux/console.h>
 #include <linux/init.h>
 #include <linux/ioport.h>
 #include <linux/root_dev.h>
@@ -50,17 +52,10 @@ static struct resource vr41xx_pci_mem_re
 
 extern struct pci_ops vr41xx_pci_ops;
 
-struct pci_channel mips_pci_channels[] = {
-	{	.pci_ops	= &vr41xx_pci_ops,
-		.io_resource	= &vr41xx_pci_io_resource,
-		.mem_resource	= &vr41xx_pci_mem_resource,
-		.first_devfn	= 0,
-		.last_devfn	= 256,	},
-	{	.pci_ops	= NULL,
-		.io_resource	= NULL,
-		.mem_resource	= NULL,
-		.first_devfn	= 0,
-		.last_devfn	= 0,	}
+struct pci_controller vr41xx_controller = {
+	.pci_ops	= &vr41xx_pci_ops,
+	.io_resource	= &vr41xx_pci_io_resource,
+	.mem_resource	= &vr41xx_pci_mem_resource,
 };
 
 struct vr41xx_pci_address_space vr41xx_pci_mem1 = {
@@ -88,7 +83,7 @@ static struct vr41xx_pci_address_map pci
 };
 #endif
 
-void __init tanbac_tb0229_setup(void)
+static void __init tanbac_tb0229_setup(void)
 {
 	set_io_port_base(IO_PORT_BASE);
 	ioport_resource.start = IO_PORT_RESOURCE_START;
@@ -102,20 +97,14 @@ void __init tanbac_tb0229_setup(void)
 	initrd_end = (unsigned long)&__rd_end;
 #endif
 
-	_machine_restart = tanbac_tb0229_restart;
-	_machine_halt = vr41xx_halt;
-	_machine_power_off = vr41xx_power_off;
-
 	board_time_init = vr41xx_time_init;
 	board_timer_setup = vr41xx_timer_setup;
 
-#ifdef CONFIG_FB
-	conswitchp = &dummy_con;
-#endif
-
 	vr41xx_bcu_init();
 
-	vr41xx_cmu_init(0);
+	vr41xx_cmu_init();
+
+	vr41xx_pmu_init();
 
 	vr41xx_siu_init(SIU_RS232C, 0);
 	vr41xx_dsiu_init();
@@ -123,5 +112,10 @@ void __init tanbac_tb0229_setup(void)
 #ifdef CONFIG_PCI
 	vr41xx_pciu_init(&pci_address_map);
 #endif
+
+#ifdef CONFIG_TANBAC_TB0219
+	_machine_restart = tanbac_tb0229_restart;
+#endif
 }
 
+early_initcall(tanbac_tb0229_setup);
--- diff/arch/mips/vr41xx/victor-mpc30x/Makefile	2003-07-08 09:55:17.000000000 +0100
+++ source/arch/mips/vr41xx/victor-mpc30x/Makefile	2004-02-23 13:56:39.000000000 +0000
@@ -3,4 +3,3 @@
 #
 
 obj-y			+= init.o setup.o
-obj-$(CONFIG_IDE)	+= ide-mpc30x.o
--- diff/arch/mips/vr41xx/victor-mpc30x/init.c	2003-07-08 09:55:17.000000000 +0100
+++ source/arch/mips/vr41xx/victor-mpc30x/init.c	2004-02-23 13:56:39.000000000 +0000
@@ -13,7 +13,6 @@
  *  Free Software Foundation; either version 2 of the License, or (at your
  *  option) any later version.
  */
-#include <linux/config.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/string.h>
@@ -23,15 +22,15 @@
 #include <asm/mipsregs.h>
 #include <asm/vr41xx/vr41xx.h>
 
-char arcs_cmdline[CL_SIZE];
-
 const char *get_system_type(void)
 {
 	return "Victor MP-C303/304";
 }
 
-void __init prom_init(int argc, char **argv, unsigned long magic, int *prom_vec)
+void __init prom_init(void)
 {
+	int argc = fw_arg0;
+	char **argv = (char **) fw_arg1;
 	int i;
 
 	/*
@@ -49,6 +48,7 @@ void __init prom_init(int argc, char **a
 	add_memory_region(0, 32 << 20, BOOT_MEM_RAM);
 }
 
-void __init prom_free_prom_memory (void)
+unsigned long __init prom_free_prom_memory(void)
 {
+	return 0;
 }
--- diff/arch/mips/vr41xx/victor-mpc30x/setup.c	2003-07-08 09:55:17.000000000 +0100
+++ source/arch/mips/vr41xx/victor-mpc30x/setup.c	2004-02-23 13:56:39.000000000 +0000
@@ -1,29 +1,30 @@
 /*
- * FILE NAME
- *	arch/mips/vr41xx/victor-mpc30x/setup.c
+ *  setup.c, Setup for the Victor MP-C303/304.
  *
- * BRIEF MODULE DESCRIPTION
- *	Setup for the Victor MP-C303/304.
+ *  Copyright (C) 2002-2003  Yoichi Yuasa <yuasa@hh.iij4u.or.jp>
  *
- * Copyright 2002 Yoichi Yuasa
- *                yuasa@hh.iij4u.or.jp
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
  *
- *  This program is free software; you can redistribute it and/or modify it
- *  under the terms of the GNU General Public License as published by the
- *  Free Software Foundation; either version 2 of the License, or (at your
- *  option) any later version.
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
 #include <linux/config.h>
 #include <linux/init.h>
-#include <linux/console.h>
-#include <linux/ide.h>
 #include <linux/ioport.h>
 #include <linux/major.h>
 #include <linux/kdev_t.h>
 #include <linux/root_dev.h>
 
 #include <asm/pci_channel.h>
-#include <asm/reboot.h>
 #include <asm/time.h>
 #include <asm/vr41xx/mpc30x.h>
 
@@ -32,10 +33,6 @@ extern unsigned long initrd_start, initr
 extern void * __rd_start, * __rd_end;
 #endif
 
-#ifdef CONFIG_BLK_DEV_IDE
-extern struct ide_ops mpc30x_ide_ops;
-#endif
-
 #ifdef CONFIG_PCI
 static struct resource vr41xx_pci_io_resource = {
 	"PCI I/O space",
@@ -53,9 +50,10 @@ static struct resource vr41xx_pci_mem_re
 
 extern struct pci_ops vr41xx_pci_ops;
 
-struct pci_channel mips_pci_channels[] = {
-	{&vr41xx_pci_ops, &vr41xx_pci_io_resource, &vr41xx_pci_mem_resource, 0, 256},
-	{NULL, NULL, NULL, 0, 0}
+struct pci_controller vr41xx_controller[] = {
+	.pci_ops	= &vr41xx_pci_ops,
+	.io_resource	= &vr41xx_pci_io_resource,
+	.mem_resource	= &vr41xx_pci_mem_resource,
 };
 
 struct vr41xx_pci_address_space vr41xx_pci_mem1 = {
@@ -83,7 +81,7 @@ static struct vr41xx_pci_address_map pci
 };
 #endif
 
-void __init victor_mpc30x_setup(void)
+static void __init victor_mpc30x_setup(void)
 {
 	set_io_port_base(IO_PORT_BASE);
 	ioport_resource.start = IO_PORT_RESOURCE_START;
@@ -97,24 +95,14 @@ void __init victor_mpc30x_setup(void)
 	initrd_end = (unsigned long)&__rd_end;
 #endif
 
-	_machine_restart = vr41xx_restart;
-	_machine_halt = vr41xx_halt;
-	_machine_power_off = vr41xx_power_off;
-
 	board_time_init = vr41xx_time_init;
 	board_timer_setup = vr41xx_timer_setup;
 
-#ifdef CONFIG_FB
-	conswitchp = &dummy_con;
-#endif
-
-#ifdef CONFIG_BLK_DEV_IDE
-	ide_ops = &mpc30x_ide_ops;
-#endif
-
 	vr41xx_bcu_init();
 
-	vr41xx_cmu_init(0);
+	vr41xx_cmu_init();
+
+	vr41xx_pmu_init();
 
 #ifdef CONFIG_SERIAL_8250
 	vr41xx_siu_init(SIU_RS232C, 0);
@@ -124,3 +112,5 @@ void __init victor_mpc30x_setup(void)
 	vr41xx_pciu_init(&pci_address_map);
 #endif
 }
+
+early_initcall(victor_mpc30x_setup);
--- diff/arch/mips/vr41xx/zao-capcella/Makefile	2003-07-08 09:55:17.000000000 +0100
+++ source/arch/mips/vr41xx/zao-capcella/Makefile	2004-02-23 13:56:39.000000000 +0000
@@ -3,4 +3,3 @@
 #
 
 obj-y			+= init.o setup.o
-obj-$(CONFIG_IDE)	+= ide-capcella.o
--- diff/arch/mips/vr41xx/zao-capcella/init.c	2003-07-08 09:55:17.000000000 +0100
+++ source/arch/mips/vr41xx/zao-capcella/init.c	2004-02-23 13:56:39.000000000 +0000
@@ -13,9 +13,9 @@
  *  Free Software Foundation; either version 2 of the License, or (at your
  *  option) any later version.
  */
-#include <linux/config.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
+#include <linux/smp.h>
 #include <linux/string.h>
 
 #include <asm/bootinfo.h>
@@ -23,8 +23,6 @@
 #include <asm/mipsregs.h>
 #include <asm/vr41xx/vr41xx.h>
 
-char arcs_cmdline[CL_SIZE];
-
 const char *get_system_type(void)
 {
 	return "ZAO Networks Capcella";
@@ -32,7 +30,8 @@ const char *get_system_type(void)
 
 void __init prom_init(int argc, char **argv, unsigned long magic, int *prom_vec)
 {
-	u32 config;
+	int argc = fw_arg0;
+	char **argv = (char **) fw_arg1;
 	int i;
 
 	/*
@@ -46,19 +45,9 @@ void __init prom_init(int argc, char **a
 
 	mips_machgroup = MACH_GROUP_NEC_VR41XX;
 	mips_machtype = MACH_ZAO_CAPCELLA;
-
-	switch (current_cpu_data.processor_id) {
-	case PRID_VR4131_REV1_2:
-		config = read_c0_config();
-		config &= ~0x00000030UL;
-		config |= 0x00410000UL;
-		write_c0_config(config);
-		break;
-	default:
-		break;
-	}
 }
 
-void __init prom_free_prom_memory (void)
+unsigned long __init prom_free_prom_memory(void)
 {
+	return 0;
 }
--- diff/arch/mips/vr41xx/zao-capcella/setup.c	2003-07-08 09:55:17.000000000 +0100
+++ source/arch/mips/vr41xx/zao-capcella/setup.c	2004-02-23 13:56:39.000000000 +0000
@@ -1,29 +1,30 @@
 /*
- * FILE NAME
- *	arch/mips/vr41xx/zao-capcella/setup.c
+ *  setup.c, Setup for the ZAO Networks Capcella.
  *
- * BRIEF MODULE DESCRIPTION
- *	Setup for the ZAO Networks Capcella.
+ *  Copyright (C) 2002-2003  Yoichi Yuasa <yuasa@hh.iij4u.or.jp>
  *
- * Copyright 2002 Yoichi Yuasa
- *                yuasa@hh.iij4u.or.jp
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
  *
- *  This program is free software; you can redistribute it and/or modify it
- *  under the terms of the GNU General Public License as published by the
- *  Free Software Foundation; either version 2 of the License, or (at your
- *  option) any later version.
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
 #include <linux/config.h>
 #include <linux/init.h>
-#include <linux/console.h>
-#include <linux/ide.h>
 #include <linux/ioport.h>
 #include <linux/major.h>
 #include <linux/kdev_t.h>
 #include <linux/root_dev.h>
 
 #include <asm/pci_channel.h>
-#include <asm/reboot.h>
 #include <asm/time.h>
 #include <asm/vr41xx/capcella.h>
 
@@ -32,10 +33,6 @@ extern unsigned long initrd_start, initr
 extern void * __rd_start, * __rd_end;
 #endif
 
-#ifdef CONFIG_BLK_DEV_IDE
-extern struct ide_ops capcella_ide_ops;
-#endif
-
 #ifdef CONFIG_PCI
 static struct resource vr41xx_pci_io_resource = {
 	"PCI I/O space",
@@ -53,9 +50,10 @@ static struct resource vr41xx_pci_mem_re
 
 extern struct pci_ops vr41xx_pci_ops;
 
-struct pci_channel mips_pci_channels[] = {
-	{&vr41xx_pci_ops, &vr41xx_pci_io_resource, &vr41xx_pci_mem_resource, 0, 256},
-	{NULL, NULL, NULL, 0, 0}
+struct pci_controller vr41xx_controller = {
+	.pci_ops	= &vr41xx_pci_ops,
+	.io_resource	= &vr41xx_pci_io_resource,
+	.mem_resource	= &vr41xx_pci_mem_resource,
 };
 
 struct vr41xx_pci_address_space vr41xx_pci_mem1 = {
@@ -83,7 +81,7 @@ static struct vr41xx_pci_address_map pci
 };
 #endif
 
-void __init zao_capcella_setup(void)
+static void __init zao_capcella_setup(void)
 {
 	set_io_port_base(IO_PORT_BASE);
 	ioport_resource.start = IO_PORT_RESOURCE_START;
@@ -97,24 +95,14 @@ void __init zao_capcella_setup(void)
 	initrd_end = (unsigned long)&__rd_end;
 #endif
 
-	_machine_restart = vr41xx_restart;
-	_machine_halt = vr41xx_halt;
-	_machine_power_off = vr41xx_power_off;
-
 	board_time_init = vr41xx_time_init;
 	board_timer_setup = vr41xx_timer_setup;
 
-#ifdef CONFIG_FB
-	conswitchp = &dummy_con;
-#endif
-
-#ifdef CONFIG_BLK_DEV_IDE
-	ide_ops = &capcella_ide_ops;
-#endif
-
 	vr41xx_bcu_init();
 
-	vr41xx_cmu_init(0x0102);
+	vr41xx_cmu_init();
+
+	vr41xx_pmu_init();
 
 #ifdef CONFIG_SERIAL_8250
 	vr41xx_siu_init(SIU_RS232C, 0);
@@ -125,3 +113,5 @@ void __init zao_capcella_setup(void)
 	vr41xx_pciu_init(&pci_address_map);
 #endif
 }
+
+early_initcall(zao_capcella_setup);
--- diff/arch/parisc/hpux/ioctl.c	2004-02-18 08:54:07.000000000 +0000
+++ source/arch/parisc/hpux/ioctl.c	2004-02-23 13:56:39.000000000 +0000
@@ -35,13 +35,12 @@
 
 #include <linux/sched.h>
 #include <linux/smp_lock.h>
+#include <linux/syscalls.h>
 #include <asm/errno.h>
 #include <asm/ioctl.h>
 #include <asm/termios.h>
 #include <asm/uaccess.h>
 
-int sys_ioctl(unsigned int, unsigned int, unsigned long);
- 
 static int hpux_ioctl_t(int fd, unsigned long cmd, unsigned long arg)
 {
 	int result = -EOPNOTSUPP;
--- diff/arch/parisc/hpux/sys_hpux.c	2004-02-18 08:54:07.000000000 +0000
+++ source/arch/parisc/hpux/sys_hpux.c	2004-02-23 13:56:39.000000000 +0000
@@ -26,6 +26,7 @@
 #include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/smp_lock.h>
+#include <linux/syscalls.h>
 #include <linux/utsname.h>
 #include <linux/vmalloc.h>
 #include <linux/vfs.h>
@@ -34,8 +35,6 @@
 #include <asm/pgalloc.h>
 #include <asm/uaccess.h>
 
-unsigned long sys_brk(unsigned long addr);
- 
 unsigned long hpux_brk(unsigned long addr)
 {
 	/* Sigh.  Looks like HP/UX libc relies on kernel bugs. */
@@ -61,7 +60,6 @@ int hpux_ptrace(void)
 
 int hpux_wait(int *stat_loc)
 {
-	extern int sys_waitpid(int, int *, int);
 	return sys_waitpid(-1, stat_loc, 0);
 }
 
@@ -213,7 +211,6 @@ int hpux_statfs(const char *path, struct
 	kfree(kpath);
 
 	/* just fake it, beginning of structures match */
-	extern int sys_statfs(const char *, struct statfs *);
 	error = sys_statfs(path, (struct statfs *) buf);
 
 	/* ignoring rest of statfs struct, but it should be zeros. Need to do 
@@ -269,9 +266,6 @@ static int hpux_uname(struct hpux_utsnam
 	return error;
 }
 
-int sys_sethostname(char *, int);
-int sys_gethostname(char *, int);
-
 /*  Note: HP-UX just uses the old suser() function to check perms
  *  in this system call.  We'll use capable(CAP_SYS_ADMIN).
  */
--- diff/arch/parisc/kernel/ioctl32.c	2004-01-19 10:22:55.000000000 +0000
+++ source/arch/parisc/kernel/ioctl32.c	2004-02-23 13:56:39.000000000 +0000
@@ -8,6 +8,8 @@
  * ioctls.
  */
 
+#include <linux/syscalls.h>
+
 #define INCLUDES
 #include "compat_ioctl.c"
 
--- diff/arch/parisc/kernel/parisc_ksyms.c	2004-02-18 08:54:07.000000000 +0000
+++ source/arch/parisc/kernel/parisc_ksyms.c	2004-02-23 13:56:39.000000000 +0000
@@ -27,6 +27,7 @@
 #include <linux/config.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
+#include <linux/syscalls.h>
 
 #include <linux/string.h>
 EXPORT_SYMBOL(memchr);
@@ -83,10 +84,6 @@ EXPORT_SYMBOL(__memcpy_fromio);
 EXPORT_SYMBOL(__memset_io);
 
 #include <asm/unistd.h>
-extern long sys_open(const char *, int, int);
-extern off_t sys_lseek(int, off_t, int);
-extern int sys_read(int, char *, int);
-extern int sys_write(int, const char *, int);
 EXPORT_SYMBOL(sys_open);
 EXPORT_SYMBOL(sys_lseek);
 EXPORT_SYMBOL(sys_read);
--- diff/arch/parisc/kernel/signal32.c	2004-02-18 08:54:07.000000000 +0000
+++ source/arch/parisc/kernel/signal32.c	2004-02-23 13:56:39.000000000 +0000
@@ -28,6 +28,7 @@
 #include <linux/smp_lock.h>
 #include <linux/init.h>
 #include <linux/sched.h>
+#include <linux/syscalls.h>
 #include <linux/types.h>
 #include <linux/errno.h>
 
@@ -92,9 +93,6 @@ get_sigset32(compat_sigset_t *up, sigset
 int sys32_rt_sigprocmask(int how, compat_sigset_t *set, compat_sigset_t *oset,
 				    unsigned int sigsetsize)
 {
-	extern long sys_rt_sigprocmask(int how,
-				    sigset_t *set, sigset_t *oset,
-				   size_t sigsetsize);
 	sigset_t old_set, new_set;
 	int ret;
 
@@ -115,7 +113,6 @@ int sys32_rt_sigpending(compat_sigset_t 
 {
 	int ret;
 	sigset_t set;
-	extern long sys_rt_sigpending(sigset_t *set, size_t sigsetsize);
 
 	KERNEL_SYSCALL(ret, sys_rt_sigpending, &set, sigsetsize);
 
--- diff/arch/parisc/kernel/sys_parisc.c	2004-02-18 08:54:07.000000000 +0000
+++ source/arch/parisc/kernel/sys_parisc.c	2004-02-23 13:56:39.000000000 +0000
@@ -30,6 +30,7 @@
 #include <linux/mman.h>
 #include <linux/shm.h>
 #include <linux/smp_lock.h>
+#include <linux/syscalls.h>
 
 int sys_pipe(int *fildes)
 {
@@ -182,10 +183,6 @@ long sys_shmat_wrapper(int shmid, char *
 /* Fucking broken ABI */
 
 #ifdef CONFIG_PARISC64
-extern asmlinkage long sys_truncate(const char *, unsigned long);
-extern asmlinkage long sys_ftruncate(unsigned int, unsigned long);
-extern asmlinkage long sys_fcntl(unsigned int, unsigned int, unsigned long);
-
 asmlinkage long parisc_truncate64(const char * path,
 					unsigned int high, unsigned int low)
 {
@@ -214,9 +211,6 @@ asmlinkage long sys_fcntl64(unsigned int
 }
 #else
 
-extern asmlinkage long sys_truncate64(const char *, loff_t);
-extern asmlinkage long sys_ftruncate64(unsigned int, loff_t);
-
 asmlinkage long parisc_truncate64(const char * path,
 					unsigned int high, unsigned int low)
 {
@@ -230,12 +224,6 @@ asmlinkage long parisc_ftruncate64(unsig
 }
 #endif
 
-extern asmlinkage ssize_t sys_pread64(unsigned int fd, char *buf,
-					size_t count, loff_t pos);
-extern asmlinkage ssize_t sys_pwrite64(unsigned int fd, const char *buf,
-					size_t count, loff_t pos);
-extern asmlinkage ssize_t sys_readahead(int fd, loff_t offset, size_t count);
-
 asmlinkage ssize_t parisc_pread64(unsigned int fd, char *buf, size_t count,
 					unsigned int high, unsigned int low)
 {
@@ -257,7 +245,7 @@ asmlinkage ssize_t parisc_readahead(int 
 /*
  * This changes the io permissions bitmap in the current task.
  */
-asmlinkage int sys_ioperm(unsigned long from, unsigned long num, int turn_on)
+asmlinkage long sys_ioperm(unsigned long from, unsigned long num, int turn_on)
 {
 	return -ENOSYS;
 }
--- diff/arch/parisc/kernel/sys_parisc32.c	2004-01-19 10:22:55.000000000 +0000
+++ source/arch/parisc/kernel/sys_parisc32.c	2004-02-23 13:56:39.000000000 +0000
@@ -47,6 +47,7 @@
 #include <linux/vfs.h>
 #include <linux/ptrace.h>
 #include <linux/swap.h>
+#include <linux/syscalls.h>
 
 #include <asm/types.h>
 #include <asm/uaccess.h>
@@ -357,7 +358,6 @@ asmlinkage long sys32_sched_rr_get_inter
 {
 	struct timespec t;
 	int ret;
-	extern asmlinkage long sys_sched_rr_get_interval(pid_t pid, struct timespec *interval);
 	
 	KERNEL_SYSCALL(ret, sys_sched_rr_get_interval, pid, &t);
 	if (put_compat_timespec(&t, interval))
@@ -1089,7 +1089,6 @@ asmlinkage long sys32_msgrcv(int msqid,
 }
 
 
-extern asmlinkage ssize_t sys_sendfile(int out_fd, int in_fd, off_t *offset, size_t count);
 asmlinkage int sys32_sendfile(int out_fd, int in_fd, compat_off_t *offset, s32 count)
 {
         mm_segment_t old_fs = get_fs();
@@ -1197,7 +1196,6 @@ asmlinkage int sys32_nfsservctl(int cmd,
 	return ret;
 }
 
-extern asmlinkage ssize_t sys_sendfile64(int out_fd, int in_fd, loff_t *offset, size_t count);
 typedef long __kernel_loff_t32;		/* move this to asm/posix_types.h? */
 
 asmlinkage int sys32_sendfile64(int out_fd, int in_fd, __kernel_loff_t32 *offset, s32 count)
@@ -1345,8 +1343,6 @@ asmlinkage int sys32_sysinfo(struct sysi
  * half of the argument has been zeroed by syscall.S.
  */
 
-extern asmlinkage off_t sys_lseek(unsigned int fd, off_t offset, unsigned int origin);
-
 asmlinkage int sys32_lseek(unsigned int fd, int offset, unsigned int origin)
 {
 	return sys_lseek(fd, offset, origin);
@@ -1367,8 +1363,6 @@ asmlinkage long sys32_semctl(int semid, 
 	return sys_semctl (semid, semnum, cmd, arg);
 }
 
-extern long sys_lookup_dcookie(u64 cookie64, char *buf, size_t len);
-
 long sys32_lookup_dcookie(u32 cookie_high, u32 cookie_low, char *buf,
 			  size_t len)
 {
--- diff/arch/parisc/kernel/time.c	2004-01-19 10:22:55.000000000 +0000
+++ source/arch/parisc/kernel/time.c	2004-02-23 13:56:39.000000000 +0000
@@ -230,6 +230,7 @@ do_settimeofday (struct timespec *tv)
 		time_esterror = NTP_PHASE_LIMIT;
 	}
 	write_sequnlock_irq(&xtime_lock);
+	clock_was_set();
 	return 0;
 }
 EXPORT_SYMBOL(do_settimeofday);
--- diff/arch/ppc/8260_io/enet.c	2003-09-30 15:46:11.000000000 +0100
+++ source/arch/ppc/8260_io/enet.c	2004-02-23 13:56:39.000000000 +0000
@@ -851,7 +851,7 @@ static int __init scc_enet_init(void)
 
 	err = register_netdev(dev);
 	if (err) {
-		kfree(dev);
+		free_netdev(dev);
 		return err;
 	}
 
--- diff/arch/ppc/8260_io/fcc_enet.c	2003-09-30 15:46:11.000000000 +0100
+++ source/arch/ppc/8260_io/fcc_enet.c	2004-02-23 13:56:39.000000000 +0000
@@ -1371,7 +1371,7 @@ static int __init fec_enet_init(void)
 
 		err = register_netdev(dev);
 		if (err) {
-			kfree(dev);
+			free_netdev(dev);
 			return err;
 		}
 
--- diff/arch/ppc/8xx_io/enet.c	2003-09-30 15:46:11.000000000 +0100
+++ source/arch/ppc/8xx_io/enet.c	2004-02-23 13:56:39.000000000 +0000
@@ -949,7 +949,7 @@ static int __init scc_enet_init(void)
 
 	err = register_netdev(dev);
 	if (err) {
-		kfree(dev);
+		free_netdev(dev);
 		return err;
 	}
 
--- diff/arch/ppc/8xx_io/fec.c	2003-06-30 10:07:19.000000000 +0100
+++ source/arch/ppc/8xx_io/fec.c	2004-02-23 13:56:39.000000000 +0000
@@ -1748,7 +1748,7 @@ static int __init fec_enet_init(void)
 
 	err = register_netdev(dev);
 	if (err) {
-		kfree(dev);
+		free_netdev(dev);
 		return err;
 	}
 
--- diff/arch/ppc/Kconfig	2004-02-18 08:54:07.000000000 +0000
+++ source/arch/ppc/Kconfig	2004-02-23 13:56:39.000000000 +0000
@@ -978,24 +978,6 @@ config PCI_PERMEDIA
 
 source "drivers/pci/Kconfig"
 
-config HOTPLUG
-	bool "Support for hot-pluggable devices"
-	---help---
-	  Say Y here if you want to plug devices into your computer while
-	  the system is running, and be able to use them quickly.  In many
-	  cases, the devices can likewise be unplugged at any time too.
-
-	  One well known example of this is PCMCIA- or PC-cards, credit-card
-	  size devices such as network cards, modems or hard drives which are
-	  plugged into slots found on all modern laptop computers.  Another
-	  example, used on modern desktops as well as laptops, is USB.
-
-	  Enable HOTPLUG and KMOD, and build a modular kernel.  Get agent
-	  software (at <http://linux-hotplug.sourceforge.net/>) and install it.
-	  Then your kernel will automatically call out to a user mode "policy
-	  agent" (/sbin/hotplug) to load modules and set up software needed
-	  to use devices as you hotplug them.
-
 source "drivers/pcmcia/Kconfig"
 
 endmenu
--- diff/arch/ppc/boot/ld.script	2003-10-09 09:47:16.000000000 +0100
+++ source/arch/ppc/boot/ld.script	2004-02-23 13:56:39.000000000 +0000
@@ -82,6 +82,7 @@ SECTIONS
     *(__ksymtab)
     *(__ksymtab_strings)
     *(__bug_table)
+    *(__kcrctab)
   }
 
 }
--- diff/arch/ppc/kernel/irq.c	2004-01-19 10:22:55.000000000 +0000
+++ source/arch/ppc/kernel/irq.c	2004-02-23 13:56:39.000000000 +0000
@@ -575,7 +575,7 @@ cpumask_t irq_affinity [NR_IRQS];
 static int irq_affinity_read_proc (char *page, char **start, off_t off,
 			int count, int *eof, void *data)
 {
-	int len = cpumask_snprintf(page, count, irq_affinity[(long)data]);
+	int len = cpumask_scnprintf(page, count, irq_affinity[(long)data]);
 	if (count - len < 2)
 		return -EINVAL;
 	len += sprintf(page + len, "\n");
@@ -616,7 +616,7 @@ static int irq_affinity_write_proc (stru
 static int prof_cpu_mask_read_proc (char *page, char **start, off_t off,
 			int count, int *eof, void *data)
 {
-	int len = cpumask_snprintf(page, count, *(cpumask_t *)data);
+	int len = cpumask_scnprintf(page, count, *(cpumask_t *)data);
 	if (count - len < 2)
 		return -EINVAL;
 	len += sprintf(page + len, "\n");
--- diff/arch/ppc/kernel/l2cr.S	2003-09-30 15:46:12.000000000 +0100
+++ source/arch/ppc/kernel/l2cr.S	2004-02-23 13:56:39.000000000 +0000
@@ -130,11 +130,6 @@ END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
 	mtspr	HID0,r4			/* Disable DPM */
 	sync
 
-	/* Flush & disable L1 */
-	mr	r5,r3
-	bl	__flush_disable_L1
-	mr	r3,r5
-
 	/* Get the current enable bit of the L2CR into r4 */
 	mfspr	r4,L2CR
 
@@ -236,7 +231,6 @@ END_FTR_SECTION_IFSET(CPU_FTR_SPEC7450)
 	sync
 
 4:
-	bl	__inval_enable_L1
 
 	/* Restore HID0[DPM] to whatever it was before */
 	sync
@@ -394,11 +388,10 @@ BEGIN_FTR_SECTION
 END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
  	sync
 
-	/* Load counter to 0x1000 cache lines (128k) and
+	/* Load counter to 0x4000 cache lines (512k) and
 	 * load cache with datas
 	 */
-	lis	r3,0x0002
-//	li	r3,0x1000	/* 128kB / 32B */
+	li	r3,0x4000	/* 512kB / 32B */
 	mtctr	r3
 	li	r3, 0
 1:
@@ -409,8 +402,7 @@ END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
 	sync
 
 	/* Now flush those cache lines */
-	lis	r3,0x0002
-//	li	r3,0x1000	/* 128kB / 32B */
+	li	r3,0x4000	/* 512kB / 32B */
 	mtctr	r3
 	li	r3, 0
 1:
--- diff/arch/ppc/kernel/setup.c	2004-02-18 08:54:07.000000000 +0000
+++ source/arch/ppc/kernel/setup.c	2004-02-23 13:56:39.000000000 +0000
@@ -53,7 +53,7 @@ extern void ppc6xx_idle(void);
 extern void power4_idle(void);
 
 extern boot_infos_t *boot_infos;
-char saved_command_line[256];
+char saved_command_line[COMMAND_LINE_SIZE];
 unsigned char aux_device_present;
 struct ide_machdep_calls ppc_ide_md;
 char *sysmap;
@@ -501,7 +501,7 @@ void parse_bootinfo(struct bi_record *re
 		ulong *data = rec->data;
 		switch (rec->tag) {
 		case BI_CMD_LINE:
-			memcpy(cmd_line, (void *)data, rec->size);
+			strlcpy(cmd_line, (void *)data, sizeof(cmd_line));
 			break;
 		case BI_SYSMAP:
 			sysmap = (char *)((data[0] >= (KERNELBASE)) ? data[0] :
@@ -538,7 +538,7 @@ machine_init(unsigned long r3, unsigned 
 	     unsigned long r6, unsigned long r7)
 {
 #ifdef CONFIG_CMDLINE
-	strcpy(cmd_line, CONFIG_CMDLINE);
+	strlcpy(cmd_line, CONFIG_CMDLINE, sizeof(cmd_line));
 #endif /* CONFIG_CMDLINE */
 
 #ifdef CONFIG_6xx
@@ -676,7 +676,7 @@ void __init setup_arch(char **cmdline_p)
 	init_mm.brk = (unsigned long) klimit;
 
 	/* Save unparsed command line copy for /proc/cmdline */
-	strcpy(saved_command_line, cmd_line);
+	strlcpy(saved_command_line, cmd_line, sizeof(saved_command_line));
 	*cmdline_p = cmd_line;
 
 	/* set up the bootmem stuff with available memory */
--- diff/arch/ppc/kernel/smp.c	2004-02-18 08:54:07.000000000 +0000
+++ source/arch/ppc/kernel/smp.c	2004-02-23 13:56:39.000000000 +0000
@@ -54,6 +54,7 @@ int smp_hw_index[NR_CPUS];
 struct thread_info *secondary_ti;
 
 EXPORT_SYMBOL(cpu_online_map);
+EXPORT_SYMBOL(cpu_possible_map);
 
 /* SMP operations for this machine */
 static struct smp_ops_t *smp_ops;
--- diff/arch/ppc/kernel/syscalls.c	2004-02-09 10:36:07.000000000 +0000
+++ source/arch/ppc/kernel/syscalls.c	2004-02-23 13:56:39.000000000 +0000
@@ -29,6 +29,7 @@
 #include <linux/msg.h>
 #include <linux/shm.h>
 #include <linux/stat.h>
+#include <linux/syscalls.h>
 #include <linux/mman.h>
 #include <linux/sys.h>
 #include <linux/ipc.h>
@@ -200,8 +201,6 @@ out:
 	return err;
 }
 
-extern int sys_select(int, fd_set *, fd_set *, fd_set *, struct timeval *);
-
 /*
  * Due to some executables calling the wrong select we sometimes
  * get wrong args.  This determines how the args are being passed
--- diff/arch/ppc/kernel/time.c	2003-10-09 09:47:33.000000000 +0100
+++ source/arch/ppc/kernel/time.c	2004-02-23 13:56:39.000000000 +0000
@@ -294,6 +294,7 @@ int do_settimeofday(struct timespec *tv)
 	time_maxerror = NTP_PHASE_LIMIT;
 	time_esterror = NTP_PHASE_LIMIT;
 	write_sequnlock_irqrestore(&xtime_lock, flags);
+	clock_was_set();
 	return 0;
 }
 
--- diff/arch/ppc/platforms/pmac_pic.c	2004-02-18 08:54:08.000000000 +0000
+++ source/arch/ppc/platforms/pmac_pic.c	2004-02-23 13:56:39.000000000 +0000
@@ -646,7 +646,7 @@ static int __init init_pmacpic_sysfs(voi
 
 	printk(KERN_DEBUG "Registering pmac pic with sysfs...\n");
 	sysdev_class_register(&pmacpic_sysclass);
-	sys_device_register(&device_pmacpic);
+	sysdev_register(&device_pmacpic);
 	sysdev_driver_register(&pmacpic_sysclass, &driver_pmacpic);
 	return 0;
 }
--- diff/arch/ppc/syslib/open_pic.c	2004-02-18 08:54:08.000000000 +0000
+++ source/arch/ppc/syslib/open_pic.c	2004-02-23 13:56:39.000000000 +0000
@@ -1032,7 +1032,7 @@ static int __init init_openpic_sysfs(voi
 		printk(KERN_ERR "Failed registering openpic sys class\n");
 		return -ENODEV;
 	}
-	rc = sys_device_register(&device_openpic);
+	rc = sysdev_register(&device_openpic);
 	if (rc) {
 		printk(KERN_ERR "Failed registering openpic sys device\n");
 		return -ENODEV;
--- diff/arch/ppc/syslib/open_pic2.c	2004-02-18 08:54:08.000000000 +0000
+++ source/arch/ppc/syslib/open_pic2.c	2004-02-23 13:56:39.000000000 +0000
@@ -699,7 +699,7 @@ static int __init init_openpic2_sysfs(vo
 		printk(KERN_ERR "Failed registering openpic sys class\n");
 		return -ENODEV;
 	}
-	rc = sys_device_register(&device_openpic2);
+	rc = sysdev_register(&device_openpic2);
 	if (rc) {
 		printk(KERN_ERR "Failed registering openpic sys device\n");
 		return -ENODEV;
--- diff/arch/ppc64/Kconfig	2004-02-18 08:54:08.000000000 +0000
+++ source/arch/ppc64/Kconfig	2004-02-23 13:56:39.000000000 +0000
@@ -227,24 +227,6 @@ source "fs/Kconfig.binfmt"
 
 source "drivers/pci/Kconfig"
 
-config HOTPLUG
-	bool "Support for hot-pluggable devices"
-	---help---
-	  Say Y here if you want to plug devices into your computer while
-	  the system is running, and be able to use them quickly.  In many
-	  cases, the devices can likewise be unplugged at any time too.
-
-	  One well known example of this is PCMCIA- or PC-cards, credit-card
-	  size devices such as network cards, modems or hard drives which are
-	  plugged into slots found on all modern laptop computers.  Another
-	  example, used on modern desktops as well as laptops, is USB.
-
-	  Enable HOTPLUG and KMOD, and build a modular kernel.  Get agent
-	  software (at <http://linux-hotplug.sourceforge.net/>) and install it.
-	  Then your kernel will automatically call out to a user mode "policy
-	  agent" (/sbin/hotplug) to load modules and set up software needed
-	  to use devices as you hotplug them.
-
 source "drivers/pcmcia/Kconfig"
 
 source "drivers/pci/hotplug/Kconfig"
@@ -334,6 +316,19 @@ config DEBUG_KERNEL
 	  Say Y here if you are developing drivers or trying to debug and
 	  identify kernel problems.
 
+config DEBUG_STACKOVERFLOW
+	bool "Check for stack overflows"
+	depends on DEBUG_KERNEL
+
+config DEBUG_STACK_USAGE
+	bool "Stack utilization instrumentation"
+	depends on DEBUG_KERNEL
+	help
+	  Enables the display of the minimum amount of free stack which each
+	  task has ever had available in the sysrq-T and sysrq-P debug output.
+
+	  This option will slow down process creation somewhat.
+
 config DEBUG_SLAB
 	bool "Debug memory allocations"
 	depends on DEBUG_KERNEL
--- diff/arch/ppc64/Makefile	2004-02-09 10:36:07.000000000 +0000
+++ source/arch/ppc64/Makefile	2004-02-23 13:56:39.000000000 +0000
@@ -27,15 +27,16 @@ LDFLAGS_vmlinux	:= -Bstatic -e $(KERNELL
 CFLAGS		+= -msoft-float -pipe -Wno-uninitialized -mminimal-toc \
 		   -mtraceback=none
 
-HAS_POWER4	:= $(shell if $(CC) -mcpu=power4 -S -o /dev/null -xc /dev/null > /dev/null 2>&1; then echo y; else echo n; fi;)
-ifeq ($(HAS_POWER4),y)
 ifeq ($(CONFIG_POWER4_ONLY),y)
-CFLAGS		+= -mcpu=power4
+	CFLAGS += $(call check_gcc,-mcpu=power4,)
 else
-CFLAGS		+= -mtune=power4
-endif
+	CFLAGS += $(call check_gcc,-mtune=power4,)
 endif
 
+# Enable unit-at-a-time mode when possible. It shrinks the
+# kernel considerably.
+CFLAGS += $(call check_gcc,-funit-at-a-time,)
+
 head-y := arch/ppc64/kernel/head.o
 
 libs-y				+= arch/ppc64/lib/
@@ -70,4 +71,11 @@ arch/ppc64/kernel/asm-offsets.s: include
 include/asm-ppc64/offsets.h: arch/ppc64/kernel/asm-offsets.s
 	$(call filechk,gen-asm-offsets)
 
+define archhelp
+  echo  '* zImage	- Compressed kernel image (arch/$(ARCH)/boot/zImage)'
+  echo  '  zImage.initrd- Compressed kernel image with initrd attached,
+  echo  '		   sourced from arch/$(ARCH)/boot/ramdisk.image.gz'
+  echo  '		   (arch/$(ARCH)/boot/zImage.initrd)'
+endef
+
 CLEAN_FILES += include/asm-ppc64/offsets.h
--- diff/arch/ppc64/boot/Makefile	2003-09-30 15:46:12.000000000 +0100
+++ source/arch/ppc64/boot/Makefile	2004-02-23 13:56:39.000000000 +0000
@@ -20,7 +20,7 @@
 #	CROSS32_COMPILE is setup as a prefix just like CROSS_COMPILE
 #	in the toplevel makefile.
 
-CROSS32_COMPILE =
+CROSS32_COMPILE ?=
 #CROSS32_COMPILE = /usr/local/ppc/bin/powerpc-linux-
 
 BOOTCC		:= $(CROSS32_COMPILE)gcc
--- diff/arch/ppc64/kernel/Makefile	2004-02-18 08:54:08.000000000 +0000
+++ source/arch/ppc64/kernel/Makefile	2004-02-23 13:56:39.000000000 +0000
@@ -14,11 +14,13 @@ obj-y               :=	setup.o entry.o t
 
 obj-$(CONFIG_PPC_OF) +=	of_device.o
 
-obj-$(CONFIG_PCI)	+= pci.o pci_dn.o pci_dma.o pci_dma_direct.o
+obj-$(CONFIG_PCI)	+= pci.o pci_dn.o pci_dma.o
 
 ifdef CONFIG_PPC_ISERIES
 obj-$(CONFIG_PCI)	+= iSeries_pci.o iSeries_pci_reset.o \
 			     iSeries_IoMmTable.o 
+else
+obj-$(CONFIG_PCI)	+= pci_dma_direct.o
 endif
 
 obj-$(CONFIG_PPC_ISERIES) += iSeries_irq.o \
--- diff/arch/ppc64/kernel/chrp_setup.c	2004-02-18 08:54:08.000000000 +0000
+++ source/arch/ppc64/kernel/chrp_setup.c	2004-02-23 13:56:39.000000000 +0000
@@ -129,7 +129,6 @@ void __init chrp_request_regions(void)
 void __init
 chrp_setup_arch(void)
 {
-	extern char cmd_line[];
 	struct device_node *root;
 	unsigned int *opprop;
 	
--- diff/arch/ppc64/kernel/cputable.c	2004-02-18 08:54:08.000000000 +0000
+++ source/arch/ppc64/kernel/cputable.c	2004-02-23 13:56:39.000000000 +0000
@@ -46,7 +46,7 @@ extern void __setup_cpu_ppc970(unsigned 
 
 struct cpu_spec	cpu_specs[] = {
     {	/* Power3 */
-	    0xffff0000, 0x00400000, "Power3 (630)",
+	    0xffff0000, 0x00400000, "POWER3 (630)",
 	    CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE |
 		    CPU_FTR_DABR | CPU_FTR_IABR,
 	    COMMON_USER_PPC64,
@@ -55,7 +55,7 @@ struct cpu_spec	cpu_specs[] = {
 	    COMMON_PPC64_FW
     },
     {	/* Power3+ */
-	    0xffff0000, 0x00410000, "Power3 (630+)",
+	    0xffff0000, 0x00410000, "POWER3 (630+)",
 	    CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE |
 		    CPU_FTR_DABR | CPU_FTR_IABR,
 	    COMMON_USER_PPC64,
@@ -64,7 +64,7 @@ struct cpu_spec	cpu_specs[] = {
 	    COMMON_PPC64_FW
     },
     {	/* Northstar */
-	    0xffff0000, 0x00330000, "Northstar",
+	    0xffff0000, 0x00330000, "RS64-II (northstar)",
 	    CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE |
 		    CPU_FTR_DABR | CPU_FTR_IABR,
 	    COMMON_USER_PPC64,
@@ -73,7 +73,7 @@ struct cpu_spec	cpu_specs[] = {
 	    COMMON_PPC64_FW
     },
     {	/* Pulsar */
-	    0xffff0000, 0x00340000, "Pulsar",
+	    0xffff0000, 0x00340000, "RS64-III (pulsar)",
 	    CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE |
 		    CPU_FTR_DABR | CPU_FTR_IABR,
 	    COMMON_USER_PPC64,
@@ -82,7 +82,7 @@ struct cpu_spec	cpu_specs[] = {
 	    COMMON_PPC64_FW
     },
     {	/* I-star */
-	    0xffff0000, 0x00360000, "I-star",
+	    0xffff0000, 0x00360000, "RS64-III (icestar)",
 	    CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE |
 		    CPU_FTR_DABR | CPU_FTR_IABR,
 	    COMMON_USER_PPC64,
@@ -91,7 +91,7 @@ struct cpu_spec	cpu_specs[] = {
 	    COMMON_PPC64_FW
     },
     {	/* S-star */
-	    0xffff0000, 0x00370000, "S-star",
+	    0xffff0000, 0x00370000, "RS64-IV (sstar)",
 	    CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE |
 		    CPU_FTR_DABR | CPU_FTR_IABR,
 	    COMMON_USER_PPC64,
@@ -100,7 +100,7 @@ struct cpu_spec	cpu_specs[] = {
 	    COMMON_PPC64_FW
     },
     {	/* Power4 */
-	    0xffff0000, 0x00350000, "Power4",
+	    0xffff0000, 0x00350000, "POWER4 (gp)",
 	    CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE |
 	    CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_DABR,
 	    COMMON_USER_PPC64,
@@ -109,7 +109,7 @@ struct cpu_spec	cpu_specs[] = {
 	    COMMON_PPC64_FW
     },
     {	/* Power4+ */
-	    0xffff0000, 0x00380000, "Power4+",
+	    0xffff0000, 0x00380000, "POWER4+ (gq)",
 	    CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE |
 	    CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_DABR,
 	    COMMON_USER_PPC64,
@@ -126,8 +126,17 @@ struct cpu_spec	cpu_specs[] = {
 	    __setup_cpu_ppc970,
 	    COMMON_PPC64_FW
     },
+    {	/* PPC970FX */
+	    0xffff0000, 0x003c0000, "PPC970FX",
+	    CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE |
+	    CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_ALTIVEC_COMP | CPU_FTR_CAN_NAP,
+	    COMMON_USER_PPC64 | PPC_FEATURE_HAS_ALTIVEC_COMP,
+	    128, 128,
+	    __setup_cpu_ppc970,
+	    COMMON_PPC64_FW
+    },
     {	/* Power5 */
-	    0xffff0000, 0x003a0000, "Power5",
+	    0xffff0000, 0x003a0000, "POWER5 (gr)",
 	    CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE |
 	    CPU_FTR_PPCAS_ARCH_V2,
 	    COMMON_USER_PPC64,
@@ -136,7 +145,7 @@ struct cpu_spec	cpu_specs[] = {
 	    COMMON_PPC64_FW
     },
     {	/* default match */
-	    0x00000000, 0x00000000, "(Power4-Compatible)",
+	    0x00000000, 0x00000000, "POWER4 (compatible)",
   	    CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE |
 	    CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_DABR,
 	    COMMON_USER_PPC64,
--- diff/arch/ppc64/kernel/eeh.c	2004-02-09 10:36:08.000000000 +0000
+++ source/arch/ppc64/kernel/eeh.c	2004-02-23 13:56:39.000000000 +0000
@@ -31,6 +31,7 @@
 #include <asm/processor.h>
 #include <asm/naca.h>
 #include <asm/io.h>
+#include <asm/machdep.h>
 #include "pci.h"
 
 #define BUID_HI(buid) ((buid) >> 32)
@@ -49,6 +50,8 @@ static int eeh_implemented;
 static char *eeh_opts;
 static int eeh_opts_last;
 
+unsigned char	slot_err_buf[RTAS_ERROR_LOG_MAX];
+
 pte_t *find_linux_pte(pgd_t *pgdir, unsigned long va);	/* from htab.c */
 static int eeh_check_opts_config(struct device_node *dn,
 				 int class_code, int vendor_id, int device_id,
@@ -113,8 +116,22 @@ unsigned long eeh_check_failure(void *to
 	 */
 	if (dn->eeh_config_addr) {
 		ret = rtas_call(ibm_read_slot_reset_state, 3, 3, rets,
-				dn->eeh_config_addr, BUID_HI(dn->phb->buid), BUID_LO(dn->phb->buid));
+				dn->eeh_config_addr, BUID_HI(dn->phb->buid),
+				BUID_LO(dn->phb->buid));
 		if (ret == 0 && rets[1] == 1 && rets[0] >= 2) {
+			unsigned long	slot_err_ret;
+
+			memset(slot_err_buf, 0, RTAS_ERROR_LOG_MAX);
+			slot_err_ret = rtas_call(rtas_token("ibm,slot-error-detail"),
+						 8, 1, NULL, dn->eeh_config_addr,
+						 BUID_HI(dn->phb->buid),
+						 BUID_LO(dn->phb->buid), NULL, 0,
+						 __pa(slot_err_buf), RTAS_ERROR_LOG_MAX,
+						 2 /* Permanent Error */);
+
+			if (slot_err_ret == 0)
+				log_error(slot_err_buf, ERR_TYPE_RTAS_LOG, 1 /* Fatal */);
+
 			/*
 			 * XXX We should create a separate sysctl for this.
 			 *
@@ -123,9 +140,11 @@ unsigned long eeh_check_failure(void *to
 			 * can use it here.
 			 */
 			if (panic_on_oops)
-				panic("EEH: MMIO failure (%ld) on device:\n%s\n", rets[0], pci_name(dev));
+				panic("EEH: MMIO failure (%ld) on device:\n%s\n",
+				      rets[0], pci_name(dev));
 			else
-				printk("EEH: MMIO failure (%ld) on device:\n%s\n", rets[0], pci_name(dev));
+				printk("EEH: MMIO failure (%ld) on device:\n%s\n",
+				       rets[0], pci_name(dev));
 		}
 	}
 	eeh_false_positives++;
@@ -228,10 +247,8 @@ void eeh_init(void)
 {
 	struct device_node *phb;
 	struct eeh_early_enable_info info;
-
-	extern char cmd_line[];	/* Very early cmd line parse.  Cheap, but works. */
-	char *eeh_force_off = strstr(cmd_line, "eeh-force-off");
-	char *eeh_force_on = strstr(cmd_line, "eeh-force-on");
+	char *eeh_force_off = strstr(saved_command_line, "eeh-force-off");
+	char *eeh_force_on = strstr(saved_command_line, "eeh-force-on");
 
 	ibm_set_eeh_option = rtas_token("ibm,set-eeh-option");
 	ibm_set_slot_reset = rtas_token("ibm,set-slot-reset");
--- diff/arch/ppc64/kernel/head.S	2004-02-18 08:54:08.000000000 +0000
+++ source/arch/ppc64/kernel/head.S	2004-02-23 13:56:39.000000000 +0000
@@ -2177,4 +2177,4 @@ stab_array:
  */
 	.globl	cmd_line
 cmd_line:
-	.space	512
+	.space	512	/* COMMAND_LINE_SIZE */
--- diff/arch/ppc64/kernel/iSeries_irq.c	2004-02-09 10:36:08.000000000 +0000
+++ source/arch/ppc64/kernel/iSeries_irq.c	2004-02-23 13:56:39.000000000 +0000
@@ -57,6 +57,7 @@ static hw_irq_controller iSeries_IRQ_han
 
 void iSeries_init_irq_desc(irq_desc_t *desc)
 {
+	desc->handler = &iSeries_IRQ_handler;
 }
 
 /* This is called by init_IRQ.  set in ppc_md.init_IRQ by iSeries_setup.c */
@@ -87,22 +88,6 @@ int __init iSeries_allocate_IRQ(HvBusNum
 #define IRQ_TO_IDSEL(irq)	(((((irq) - 1) >> 3) & 7) + 1)
 #define IRQ_TO_FUNC(irq)	(((irq) - 1) & 7)
 
-/*
- * This is called out of iSeries_scan_slot to assign the EADS slot
- * to its IRQ number
- */
-int __init iSeries_assign_IRQ(int irq, HvBusNumber busNumber,
-		HvSubBusNumber subBusNumber, HvAgentId deviceId)
-{
-	irq_desc_t *desc = get_real_irq_desc(irq);
-
-	if (desc == NULL)
-		return -1;
-	desc->handler = &iSeries_IRQ_handler;
-	return 0;
-}
-
-
 /* This is called by iSeries_activate_IRQs */
 static unsigned int iSeries_startup_IRQ(unsigned int irq)
 {
@@ -125,6 +110,11 @@ static unsigned int iSeries_startup_IRQ(
 }
 
 /*
+ * Temporary hack
+ */
+#define get_irq_desc(irq)	&irq_desc[(irq)]
+
+/*
  * This is called out of iSeries_fixup to activate interrupt
  * generation for usable slots
  */
--- diff/arch/ppc64/kernel/iSeries_pci.c	2004-02-18 08:54:08.000000000 +0000
+++ source/arch/ppc64/kernel/iSeries_pci.c	2004-02-23 13:56:39.000000000 +0000
@@ -406,7 +406,6 @@ static int iSeries_Scan_Bridge_Slot(HvBu
 
 	/* iSeries_allocate_IRQ.: 0x18.00.12(0xA3) */
   	Irq = iSeries_allocate_IRQ(Bus, 0, EADsIdSel);
-	iSeries_assign_IRQ(Irq, Bus, 0, EADsIdSel);
 	PPCDBG(PPCDBG_BUSWALK,
 		"PCI:- allocate and assign IRQ 0x%02X.%02X.%02X = 0x%02X\n",
 		Bus, 0, EADsIdSel, Irq);
--- diff/arch/ppc64/kernel/iSeries_setup.c	2004-02-18 08:54:08.000000000 +0000
+++ source/arch/ppc64/kernel/iSeries_setup.c	2004-02-23 13:56:39.000000000 +0000
@@ -315,7 +315,6 @@ void __init iSeries_init_early(void)
 	ppc_md.setup_residual = iSeries_setup_residual;
 	ppc_md.get_cpuinfo = iSeries_get_cpuinfo;
 	ppc_md.init_IRQ = iSeries_init_IRQ;
-	ppc_md.init_irq_desc = iSeries_init_irq_desc;
 	ppc_md.get_irq = iSeries_get_irq;
 	ppc_md.init = NULL;
 
--- diff/arch/ppc64/kernel/ioctl32.c	2003-10-09 09:47:33.000000000 +0100
+++ source/arch/ppc64/kernel/ioctl32.c	2004-02-23 13:56:39.000000000 +0000
@@ -23,6 +23,7 @@
 #define INCLUDES
 #include "compat_ioctl.c"
 #include <linux/ncp_fs.h>
+#include <linux/syscalls.h>
 #include <asm/ppc32.h>
 
 #define CODE
--- diff/arch/ppc64/kernel/irq.c	2004-02-09 10:36:08.000000000 +0000
+++ source/arch/ppc64/kernel/irq.c	2004-02-23 13:56:39.000000000 +0000
@@ -476,8 +476,18 @@ void ppc_irq_dispatch_handler(struct pt_
 	struct irqaction *action;
 	int cpu = smp_processor_id();
 	irq_desc_t *desc = irq_desc + irq;
+	irqreturn_t action_ret;
 
 	kstat_cpu(cpu).irqs[irq]++;
+
+	if (desc->status & IRQ_PER_CPU) {
+		/* no locking required for CPU-local interrupts: */
+		ack_irq(irq);
+		action_ret = handle_irq_event(irq, regs, desc->action);
+		desc->handler->end(irq);
+		return;
+	}
+
 	spin_lock(&desc->lock);
 	ack_irq(irq);	
 	/*
@@ -485,8 +495,7 @@ void ppc_irq_dispatch_handler(struct pt_
 	   WAITING is used by probe to mark irqs that are being tested
 	   */
 	status = desc->status & ~(IRQ_REPLAY | IRQ_WAITING);
-	if (!(status & IRQ_PER_CPU))
-		status |= IRQ_PENDING; /* we _want_ to handle it */
+	status |= IRQ_PENDING; /* we _want_ to handle it */
 
 	/*
 	 * If the IRQ is disabled for whatever reason, we cannot
@@ -509,8 +518,7 @@ void ppc_irq_dispatch_handler(struct pt_
 			goto out;
 		}
 		status &= ~IRQ_PENDING; /* we commit to handling */
-		if (!(status & IRQ_PER_CPU))
-			status |= IRQ_INPROGRESS; /* we are handling it */
+		status |= IRQ_INPROGRESS; /* we are handling it */
 	}
 	desc->status = status;
 
@@ -534,8 +542,6 @@ void ppc_irq_dispatch_handler(struct pt_
 	 * SMP environment.
 	 */
 	for (;;) {
-		irqreturn_t action_ret;
-
 		spin_unlock(&desc->lock);
 		action_ret = handle_irq_event(irq, regs, action);
 		spin_lock(&desc->lock);
@@ -568,6 +574,21 @@ int do_IRQ(struct pt_regs *regs)
 
 	irq_enter();
 
+#ifdef CONFIG_DEBUG_STACKOVERFLOW
+	/* Debugging check for stack overflow: is there less than 8KB free? */
+	{
+		long sp;
+
+		sp = __get_SP() & (THREAD_SIZE-1);
+
+		if (unlikely(sp < (sizeof(struct thread_info) + 8192))) {
+			printk("do_IRQ: stack overflow: %ld\n",
+				sp - sizeof(struct thread_info));
+			dump_stack();
+		}
+	}
+#endif
+
 	lpaca = get_paca();
 #ifdef CONFIG_SMP
 	if (lpaca->xLpPaca.xIntDword.xFields.xIpiCnt) {
@@ -664,7 +685,7 @@ cpumask_t irq_affinity [NR_IRQS] = { [0 
 static int irq_affinity_read_proc (char *page, char **start, off_t off,
 			int count, int *eof, void *data)
 {
-	int len = cpumask_snprintf(page, count, irq_affinity[(long)data]);
+	int len = cpumask_scnprintf(page, count, irq_affinity[(long)data]);
 	if (count - len < 2)
 		return -EINVAL;
 	len += sprintf(page + len, "\n");
@@ -702,7 +723,7 @@ static int irq_affinity_write_proc (stru
 static int prof_cpu_mask_read_proc (char *page, char **start, off_t off,
 			int count, int *eof, void *data)
 {
-	int len = cpumask_snprintf(page, count, *(cpumask_t *)data);
+	int len = cpumask_scnprintf(page, count, *(cpumask_t *)data);
 	if (count - len < 2)
 		return -EINVAL;
 	len += sprintf(page + len, "\n");
--- diff/arch/ppc64/kernel/lmb.c	2003-05-21 11:49:45.000000000 +0100
+++ source/arch/ppc64/kernel/lmb.c	2004-02-23 13:56:39.000000000 +0000
@@ -1,5 +1,4 @@
 /*
- *
  * Procedures for interfacing to Open Firmware.
  *
  * Peter Bergner, IBM Corp.	June 2001.
@@ -13,46 +12,63 @@
 
 #include <linux/config.h>
 #include <linux/kernel.h>
+#include <linux/init.h>
 #include <asm/types.h>
 #include <asm/page.h>
 #include <asm/prom.h>
 #include <asm/lmb.h>
 #include <asm/abs_addr.h>
 #include <asm/bitops.h>
-#include <asm/udbg.h>
 
-extern unsigned long klimit;
-extern unsigned long reloc_offset(void);
+struct lmb lmb __initdata;
 
+static unsigned long __init
+lmb_addrs_overlap(unsigned long base1, unsigned long size1,
+                  unsigned long base2, unsigned long size2)
+{
+	return ((base1 < (base2+size2)) && (base2 < (base1+size1)));
+}
 
-static long lmb_add_region(struct lmb_region *, unsigned long, unsigned long, unsigned long);
+static long __init
+lmb_addrs_adjacent(unsigned long base1, unsigned long size1,
+		   unsigned long base2, unsigned long size2)
+{
+	if (base2 == base1 + size1)
+		return 1;
+	else if (base1 == base2 + size2)
+		return -1;
 
-struct lmb lmb = {
-	0, 0,
-	{0,0,0,0,{{0,0,0}}},
-	{0,0,0,0,{{0,0,0}}}
-};
+	return 0;
+}
 
+static long __init
+lmb_regions_adjacent(struct lmb_region *rgn, unsigned long r1, unsigned long r2)
+{
+	unsigned long base1 = rgn->region[r1].base;
+	unsigned long size1 = rgn->region[r1].size;
+	unsigned long base2 = rgn->region[r2].base;
+	unsigned long size2 = rgn->region[r2].size;
+
+	return lmb_addrs_adjacent(base1, size1, base2, size2);
+}
 
 /* Assumption: base addr of region 1 < base addr of region 2 */
-static void
+static void __init
 lmb_coalesce_regions(struct lmb_region *rgn, unsigned long r1, unsigned long r2)
 {
 	unsigned long i;
 
 	rgn->region[r1].size += rgn->region[r2].size;
-	for (i=r2; i < rgn->cnt-1 ;i++) {
+	for (i=r2; i < rgn->cnt-1; i++) {
 		rgn->region[i].base = rgn->region[i+1].base;
 		rgn->region[i].physbase = rgn->region[i+1].physbase;
 		rgn->region[i].size = rgn->region[i+1].size;
-		rgn->region[i].type = rgn->region[i+1].type;
 	}
 	rgn->cnt--;
 }
 
-
 /* This routine called with relocation disabled. */
-void
+void __init
 lmb_init(void)
 {
 	unsigned long offset = reloc_offset();
@@ -63,38 +79,20 @@ lmb_init(void)
 	 */
 	_lmb->memory.region[0].base = 0;
 	_lmb->memory.region[0].size = 0;
-	_lmb->memory.region[0].type = LMB_MEMORY_AREA;
 	_lmb->memory.cnt = 1;
 
 	/* Ditto. */
 	_lmb->reserved.region[0].base = 0;
 	_lmb->reserved.region[0].size = 0;
-	_lmb->reserved.region[0].type = LMB_MEMORY_AREA;
 	_lmb->reserved.cnt = 1;
 }
 
-/* This is only used here, it doesn't deserve to be in bitops.h */
-static __inline__ long cnt_trailing_zeros(unsigned long mask)
-{
-        long cnt;
-
-	asm(
-"	addi	%0,%1,-1	\n\
-	andc	%0,%0,%1	\n\
-	cntlzd	%0,%0		\n\
-	subfic	%0,%0,64"
-	: "=r" (cnt)
-	: "r" (mask));
-	return cnt;
-}
-
 /* This routine called with relocation disabled. */
-void
+void __init
 lmb_analyze(void)
 {
 	unsigned long i;
 	unsigned long mem_size = 0;
-	unsigned long io_size = 0;
 	unsigned long size_mask = 0;
 	unsigned long offset = reloc_offset();
 	struct lmb *_lmb = PTRRELOC(&lmb);
@@ -102,13 +100,9 @@ lmb_analyze(void)
 	unsigned long physbase = 0;
 #endif
 
-	for (i=0; i < _lmb->memory.cnt ;i++) {
-		unsigned long lmb_type = _lmb->memory.region[i].type;
+	for (i=0; i < _lmb->memory.cnt; i++) {
 		unsigned long lmb_size;
 
-		if ( lmb_type != LMB_MEMORY_AREA )
-			continue;
-
 		lmb_size = _lmb->memory.region[i].size;
 
 #ifdef CONFIG_MSCHUNKS
@@ -121,84 +115,20 @@ lmb_analyze(void)
 		size_mask |= lmb_size;
 	}
 
-#ifdef CONFIG_MSCHUNKS
-	for (i=0; i < _lmb->memory.cnt ;i++) {
-		unsigned long lmb_type = _lmb->memory.region[i].type;
-		unsigned long lmb_size;
-
-		if ( lmb_type != LMB_IO_AREA )
-			continue;
-
-		lmb_size = _lmb->memory.region[i].size;
-
-		_lmb->memory.region[i].physbase = physbase;
-		physbase += lmb_size;
-		io_size += lmb_size;
-		size_mask |= lmb_size;
-	}
-#endif /* CONFIG_MSCHUNKS */
-
 	_lmb->memory.size = mem_size;
-	_lmb->memory.iosize = io_size;
-	_lmb->memory.lcd_size = (1UL << cnt_trailing_zeros(size_mask));
 }
 
 /* This routine called with relocation disabled. */
-long
-lmb_add(unsigned long base, unsigned long size)
-{
-	unsigned long offset = reloc_offset();
-	struct lmb *_lmb = PTRRELOC(&lmb);
-	struct lmb_region *_rgn = &(_lmb->memory);
-
-	/* On pSeries LPAR systems, the first LMB is our RMO region. */
-	if ( base == 0 )
-		_lmb->rmo_size = size;
-
-	return lmb_add_region(_rgn, base, size, LMB_MEMORY_AREA);
-
-}
-
-#ifdef CONFIG_MSCHUNKS
-/* This routine called with relocation disabled. */
-long
-lmb_add_io(unsigned long base, unsigned long size)
-{
-	unsigned long offset = reloc_offset();
-	struct lmb *_lmb = PTRRELOC(&lmb);
-	struct lmb_region *_rgn = &(_lmb->memory);
-
-	return lmb_add_region(_rgn, base, size, LMB_IO_AREA);
-
-}
-#endif /* CONFIG_MSCHUNKS */
-
-long
-lmb_reserve(unsigned long base, unsigned long size)
-{
-	unsigned long offset = reloc_offset();
-	struct lmb *_lmb = PTRRELOC(&lmb);
-	struct lmb_region *_rgn = &(_lmb->reserved);
-
-	return lmb_add_region(_rgn, base, size, LMB_MEMORY_AREA);
-}
-
-/* This routine called with relocation disabled. */
-static long
-lmb_add_region(struct lmb_region *rgn, unsigned long base, unsigned long size,
-		unsigned long type)
+static long __init
+lmb_add_region(struct lmb_region *rgn, unsigned long base, unsigned long size)
 {
 	unsigned long i, coalesced = 0;
 	long adjacent;
 
 	/* First try and coalesce this LMB with another. */
-	for (i=0; i < rgn->cnt ;i++) {
+	for (i=0; i < rgn->cnt; i++) {
 		unsigned long rgnbase = rgn->region[i].base;
 		unsigned long rgnsize = rgn->region[i].size;
-		unsigned long rgntype = rgn->region[i].type;
-
-		if ( rgntype != type )
-			continue;
 
 		adjacent = lmb_addrs_adjacent(base,size,rgnbase,rgnsize);
 		if ( adjacent > 0 ) {
@@ -227,17 +157,15 @@ lmb_add_region(struct lmb_region *rgn, u
 	}
 
 	/* Couldn't coalesce the LMB, so add it to the sorted table. */
-	for (i=rgn->cnt-1; i >= 0 ;i--) {
+	for (i=rgn->cnt-1; i >= 0; i--) {
 		if (base < rgn->region[i].base) {
 			rgn->region[i+1].base = rgn->region[i].base;
 			rgn->region[i+1].physbase = rgn->region[i].physbase;
 			rgn->region[i+1].size = rgn->region[i].size;
-			rgn->region[i+1].type = rgn->region[i].type;
 		}  else {
 			rgn->region[i+1].base = base;
 			rgn->region[i+1].physbase = lmb_abs_to_phys(base);
 			rgn->region[i+1].size = size;
-			rgn->region[i+1].type = type;
 			break;
 		}
 	}
@@ -246,12 +174,38 @@ lmb_add_region(struct lmb_region *rgn, u
 	return 0;
 }
 
-long
+/* This routine called with relocation disabled. */
+long __init
+lmb_add(unsigned long base, unsigned long size)
+{
+	unsigned long offset = reloc_offset();
+	struct lmb *_lmb = PTRRELOC(&lmb);
+	struct lmb_region *_rgn = &(_lmb->memory);
+
+	/* On pSeries LPAR systems, the first LMB is our RMO region. */
+	if ( base == 0 )
+		_lmb->rmo_size = size;
+
+	return lmb_add_region(_rgn, base, size);
+
+}
+
+long __init
+lmb_reserve(unsigned long base, unsigned long size)
+{
+	unsigned long offset = reloc_offset();
+	struct lmb *_lmb = PTRRELOC(&lmb);
+	struct lmb_region *_rgn = &(_lmb->reserved);
+
+	return lmb_add_region(_rgn, base, size);
+}
+
+long __init
 lmb_overlaps_region(struct lmb_region *rgn, unsigned long base, unsigned long size)
 {
 	unsigned long i;
 
-	for (i=0; i < rgn->cnt ;i++) {
+	for (i=0; i < rgn->cnt; i++) {
 		unsigned long rgnbase = rgn->region[i].base;
 		unsigned long rgnsize = rgn->region[i].size;
 		if ( lmb_addrs_overlap(base,size,rgnbase,rgnsize) ) {
@@ -262,13 +216,13 @@ lmb_overlaps_region(struct lmb_region *r
 	return (i < rgn->cnt) ? i : -1;
 }
 
-unsigned long
+unsigned long __init
 lmb_alloc(unsigned long size, unsigned long align)
 {
 	return lmb_alloc_base(size, align, LMB_ALLOC_ANYWHERE);
 }
 
-unsigned long
+unsigned long __init
 lmb_alloc_base(unsigned long size, unsigned long align, unsigned long max_addr)
 {
 	long i, j;
@@ -278,13 +232,9 @@ lmb_alloc_base(unsigned long size, unsig
 	struct lmb_region *_mem = &(_lmb->memory);
 	struct lmb_region *_rsv = &(_lmb->reserved);
 
-	for (i=_mem->cnt-1; i >= 0 ;i--) {
+	for (i=_mem->cnt-1; i >= 0; i--) {
 		unsigned long lmbbase = _mem->region[i].base;
 		unsigned long lmbsize = _mem->region[i].size;
-		unsigned long lmbtype = _mem->region[i].type;
-
-		if ( lmbtype != LMB_MEMORY_AREA )
-			continue;
 
 		if ( max_addr == LMB_ALLOC_ANYWHERE )
 			base = _ALIGN_DOWN(lmbbase+lmbsize-size, align);
@@ -305,12 +255,12 @@ lmb_alloc_base(unsigned long size, unsig
 	if ( i < 0 )
 		return 0;
 
-	lmb_add_region(_rsv, base, size, LMB_MEMORY_AREA);
+	lmb_add_region(_rsv, base, size);
 
 	return base;
 }
 
-unsigned long
+unsigned long __init
 lmb_phys_mem_size(void)
 {
 	unsigned long offset = reloc_offset();
@@ -327,7 +277,7 @@ lmb_phys_mem_size(void)
 #endif /* CONFIG_MSCHUNKS */
 }
 
-unsigned long
+unsigned long __init
 lmb_end_of_DRAM(void)
 {
 	unsigned long offset = reloc_offset();
@@ -335,9 +285,7 @@ lmb_end_of_DRAM(void)
 	struct lmb_region *_mem = &(_lmb->memory);
 	unsigned long idx;
 
-	for(idx=_mem->cnt-1; idx >= 0 ;idx--) {
-		if ( _mem->region[idx].type != LMB_MEMORY_AREA )
-			continue;
+	for(idx=_mem->cnt-1; idx >= 0; idx--) {
 #ifdef CONFIG_MSCHUNKS
 		return (_mem->region[idx].physbase + _mem->region[idx].size);
 #else
@@ -348,8 +296,7 @@ lmb_end_of_DRAM(void)
 	return 0;
 }
 
-
-unsigned long
+unsigned long __init
 lmb_abs_to_phys(unsigned long aa)
 {
 	unsigned long i, pa = aa;
@@ -357,7 +304,7 @@ lmb_abs_to_phys(unsigned long aa)
 	struct lmb *_lmb = PTRRELOC(&lmb);
 	struct lmb_region *_mem = &(_lmb->memory);
 
-	for (i=0; i < _mem->cnt ;i++) {
+	for (i=0; i < _mem->cnt; i++) {
 		unsigned long lmbbase = _mem->region[i].base;
 		unsigned long lmbsize = _mem->region[i].size;
 		if ( lmb_addrs_overlap(aa,1,lmbbase,lmbsize) ) {
@@ -368,47 +315,3 @@ lmb_abs_to_phys(unsigned long aa)
 
 	return pa;
 }
-
-void
-lmb_dump(char *str)
-{
-	unsigned long i;
-
-	udbg_printf("\nlmb_dump: %s\n", str);
-	udbg_printf("    debug                       = %s\n",
-		(lmb.debug) ? "TRUE" : "FALSE");
-	udbg_printf("    memory.cnt                  = %d\n",
-		lmb.memory.cnt);
-	udbg_printf("    memory.size                 = 0x%lx\n",
-		lmb.memory.size);
-	udbg_printf("    memory.lcd_size             = 0x%lx\n",
-		lmb.memory.lcd_size);
-	for (i=0; i < lmb.memory.cnt ;i++) {
-		udbg_printf("    memory.region[%d].base       = 0x%lx\n",
-			i, lmb.memory.region[i].base);
-		udbg_printf("                      .physbase = 0x%lx\n",
-			lmb.memory.region[i].physbase);
-		udbg_printf("                      .size     = 0x%lx\n",
-			lmb.memory.region[i].size);
-		udbg_printf("                      .type     = 0x%lx\n",
-			lmb.memory.region[i].type);
-	}
-
-	udbg_printf("\n");
-	udbg_printf("    reserved.cnt                = %d\n",
-		lmb.reserved.cnt);
-	udbg_printf("    reserved.size               = 0x%lx\n",
-		lmb.reserved.size);
-	udbg_printf("    reserved.lcd_size           = 0x%lx\n",
-		lmb.reserved.lcd_size);
-	for (i=0; i < lmb.reserved.cnt ;i++) {
-		udbg_printf("    reserved.region[%d].base     = 0x%lx\n",
-			i, lmb.reserved.region[i].base);
-		udbg_printf("                      .physbase = 0x%lx\n",
-			lmb.reserved.region[i].physbase);
-		udbg_printf("                      .size     = 0x%lx\n",
-			lmb.reserved.region[i].size);
-		udbg_printf("                      .type     = 0x%lx\n",
-			lmb.reserved.region[i].type);
-	}
-}
--- diff/arch/ppc64/kernel/lparcfg.c	2004-02-18 08:54:08.000000000 +0000
+++ source/arch/ppc64/kernel/lparcfg.c	2004-02-23 13:56:39.000000000 +0000
@@ -29,7 +29,7 @@
 #include <asm/hvcall.h>
 #include <asm/cputable.h>
 
-#define MODULE_VERSION "1.0"
+#define MODULE_VERS "1.0"
 #define MODULE_NAME "lparcfg"
 
 static struct proc_dir_entry *proc_ppc64_lparcfg;
@@ -134,7 +134,7 @@ static int lparcfg_data(unsigned char *b
 	memset(buf, 0, size); 
 
 	shared = (int)(lpaca->xLpPacaPtr->xSharedProc);
-	n += snprintf(buf, LPARCFG_BUFF_SIZE - n,
+	n += scnprintf(buf, LPARCFG_BUFF_SIZE - n,
 		      "serial_number=%c%c%c%c%c%c%c\n", 
 		      e2a(xItExtVpdPanel.mfgID[2]),
 		      e2a(xItExtVpdPanel.mfgID[3]),
@@ -144,7 +144,7 @@ static int lparcfg_data(unsigned char *b
 		      e2a(xItExtVpdPanel.systemSerial[4]),
 		      e2a(xItExtVpdPanel.systemSerial[5])); 
 
-	n += snprintf(buf+n, LPARCFG_BUFF_SIZE - n, 
+	n += scnprintf(buf+n, LPARCFG_BUFF_SIZE - n,
 		      "system_type=%c%c%c%c\n",
 		      e2a(xItExtVpdPanel.machineType[0]),
 		      e2a(xItExtVpdPanel.machineType[1]),
@@ -152,23 +152,23 @@ static int lparcfg_data(unsigned char *b
 		      e2a(xItExtVpdPanel.machineType[3])); 
 
 	lp_index = HvLpConfig_getLpIndex(); 
-	n += snprintf(buf+n, LPARCFG_BUFF_SIZE - n, 
+	n += scnprintf(buf+n, LPARCFG_BUFF_SIZE - n,
 		      "partition_id=%d\n", (int)lp_index); 
 
-	n += snprintf(buf+n, LPARCFG_BUFF_SIZE - n, 
+	n += scnprintf(buf+n, LPARCFG_BUFF_SIZE - n,
 		      "system_active_processors=%d\n", 
 		      (int)HvLpConfig_getSystemPhysicalProcessors()); 
 
-	n += snprintf(buf+n, LPARCFG_BUFF_SIZE - n, 
+	n += scnprintf(buf+n, LPARCFG_BUFF_SIZE - n,
 		      "system_potential_processors=%d\n", 
 		      (int)HvLpConfig_getSystemPhysicalProcessors()); 
 
 	processors = (int)HvLpConfig_getPhysicalProcessors(); 
-	n += snprintf(buf+n, LPARCFG_BUFF_SIZE - n, 
+	n += scnprintf(buf+n, LPARCFG_BUFF_SIZE - n,
 		      "partition_active_processors=%d\n", processors);  
 
 	max_processors = (int)HvLpConfig_getMaxPhysicalProcessors(); 
-	n += snprintf(buf+n, LPARCFG_BUFF_SIZE - n, 
+	n += scnprintf(buf+n, LPARCFG_BUFF_SIZE - n,
 		      "partition_potential_processors=%d\n", max_processors);  
 
 	if(shared) {
@@ -178,22 +178,22 @@ static int lparcfg_data(unsigned char *b
 		entitled_capacity = processors * 100; 
 		max_entitled_capacity = max_processors * 100; 
 	}
-	n += snprintf(buf+n, LPARCFG_BUFF_SIZE - n, 
+	n += scnprintf(buf+n, LPARCFG_BUFF_SIZE - n,
 		      "partition_entitled_capacity=%d\n", entitled_capacity);
 
-	n += snprintf(buf+n, LPARCFG_BUFF_SIZE - n, 
+	n += scnprintf(buf+n, LPARCFG_BUFF_SIZE - n,
 		      "partition_max_entitled_capacity=%d\n", 
 		      max_entitled_capacity);
 
 	if(shared) {
 		pool_id = HvLpConfig_getSharedPoolIndex(); 
-		n += snprintf(buf+n, LPARCFG_BUFF_SIZE - n, "pool=%d\n", 
+		n += scnprintf(buf+n, LPARCFG_BUFF_SIZE - n, "pool=%d\n",
 			      (int)pool_id); 
-		n += snprintf(buf+n, LPARCFG_BUFF_SIZE - n, 
+		n += scnprintf(buf+n, LPARCFG_BUFF_SIZE - n,
 			      "pool_capacity=%d\n", (int)(HvLpConfig_getNumProcsInSharedPool(pool_id)*100)); 
 	}
 
-	n += snprintf(buf+n, LPARCFG_BUFF_SIZE - n, 
+	n += scnprintf(buf+n, LPARCFG_BUFF_SIZE - n,
 		      "shared_processor_mode=%d\n", shared);
 
 	return 0;
@@ -297,13 +297,13 @@ static int lparcfg_data(unsigned char *b
 		if(lp_index_ptr) lp_index = *lp_index_ptr;
 	}
 
-	n  = snprintf(buf, LPARCFG_BUFF_SIZE - n,
+	n  = scnprintf(buf, LPARCFG_BUFF_SIZE - n,
 		      "serial_number=%s\n", system_id); 
 
-	n += snprintf(buf+n, LPARCFG_BUFF_SIZE - n, 
+	n += scnprintf(buf+n, LPARCFG_BUFF_SIZE - n,
 		      "system_type=%s\n", model); 
 
-	n += snprintf(buf+n, LPARCFG_BUFF_SIZE - n, 
+	n += scnprintf(buf+n, LPARCFG_BUFF_SIZE - n,
 		      "partition_id=%d\n", (int)lp_index); 
 
 	rtas_node = find_path_device("/rtas");
@@ -317,74 +317,74 @@ static int lparcfg_data(unsigned char *b
 	if (cur_cpu_spec->firmware_features & FW_FEATURE_SPLPAR) {
 		h_get_ppp(&h_entitled,&h_unallocated,&h_aggregation,&h_resource);
 #ifdef DEBUG
-		n += snprintf(buf+n, LPARCFG_BUFF_SIZE - n, 
+		n += scnprintf(buf+n, LPARCFG_BUFF_SIZE - n,
 			      "R4=0x%lx\n", h_entitled);
-		n += snprintf(buf+n, LPARCFG_BUFF_SIZE - n, 
+		n += scnprintf(buf+n, LPARCFG_BUFF_SIZE - n,
 			      "R5=0x%lx\n", h_unallocated);
-		n += snprintf(buf+n, LPARCFG_BUFF_SIZE - n, 
+		n += scnprintf(buf+n, LPARCFG_BUFF_SIZE - n,
 			      "R6=0x%lx\n", h_aggregation);
-		n += snprintf(buf+n, LPARCFG_BUFF_SIZE - n, 
+		n += scnprintf(buf+n, LPARCFG_BUFF_SIZE - n,
 			      "R7=0x%lx\n", h_resource);
 #endif /* DEBUG */
 	}
 
 	if (cur_cpu_spec->firmware_features & FW_FEATURE_SPLPAR) {
 		system_potential_processors =  get_splpar_potential_characteristics();
-		n += snprintf(buf+n, LPARCFG_BUFF_SIZE - n, 
+		n += scnprintf(buf+n, LPARCFG_BUFF_SIZE - n,
 			      "system_active_processors=%ld\n", 
 			      (h_resource >> 2*8) & 0xffff);
-		n += snprintf(buf+n, LPARCFG_BUFF_SIZE - n, 
+		n += scnprintf(buf+n, LPARCFG_BUFF_SIZE - n,
 			      "system_potential_processors=%d\n", 
 			      system_potential_processors);
 	} else {
 		system_potential_processors = system_active_processors;
-		n += snprintf(buf+n, LPARCFG_BUFF_SIZE - n, 
+		n += scnprintf(buf+n, LPARCFG_BUFF_SIZE - n,
 			      "system_active_processors=%d\n", 
 			      system_active_processors);
-		n += snprintf(buf+n, LPARCFG_BUFF_SIZE - n, 
+		n += scnprintf(buf+n, LPARCFG_BUFF_SIZE - n,
 			      "system_potential_processors=%d\n", 
 			      system_potential_processors);
 	}
 
 	processors = systemcfg->processorCount;
-	n += snprintf(buf+n, LPARCFG_BUFF_SIZE - n, 
+	n += scnprintf(buf+n, LPARCFG_BUFF_SIZE - n,
 		      "partition_active_processors=%d\n", processors);  
-	n += snprintf(buf+n, LPARCFG_BUFF_SIZE - n, 
+	n += scnprintf(buf+n, LPARCFG_BUFF_SIZE - n,
 		      "partition_potential_processors=%d\n",
 		      system_active_processors);
 
 	/* max_entitled_capacity will come out of get_splpar_potential_characteristics() when that function is complete */
 	max_entitled_capacity = system_active_processors * 100; 
 	if (cur_cpu_spec->firmware_features & FW_FEATURE_SPLPAR) {
-		n += snprintf(buf+n, LPARCFG_BUFF_SIZE - n, 
+		n += scnprintf(buf+n, LPARCFG_BUFF_SIZE - n,
 			      "partition_entitled_capacity=%ld\n", h_entitled);
 	} else {
-		n += snprintf(buf+n, LPARCFG_BUFF_SIZE - n, 
+		n += scnprintf(buf+n, LPARCFG_BUFF_SIZE - n,
 			      "partition_entitled_capacity=%d\n", system_active_processors*100);
 	}
 
-	n += snprintf(buf+n, LPARCFG_BUFF_SIZE - n, 
+	n += scnprintf(buf+n, LPARCFG_BUFF_SIZE - n,
 		      "partition_max_entitled_capacity=%d\n", 
 		      max_entitled_capacity);
 
 	shared = 0;
-	n += snprintf(buf+n, LPARCFG_BUFF_SIZE - n, 
+	n += scnprintf(buf+n, LPARCFG_BUFF_SIZE - n,
 		      "shared_processor_mode=%d\n", shared);
 
 	if (cur_cpu_spec->firmware_features & FW_FEATURE_SPLPAR) {
-		n += snprintf(buf+n, LPARCFG_BUFF_SIZE - n, 
+		n += scnprintf(buf+n, LPARCFG_BUFF_SIZE - n,
 			      "pool=%ld\n", (h_aggregation >> 0*8)&0xffff);
 
-		n += snprintf(buf+n, LPARCFG_BUFF_SIZE - n, 
+		n += scnprintf(buf+n, LPARCFG_BUFF_SIZE - n,
 			      "pool_capacity=%ld\n", (h_resource >> 3*8) &0xffff);
 
-		n += snprintf(buf+n, LPARCFG_BUFF_SIZE - n, 
+		n += scnprintf(buf+n, LPARCFG_BUFF_SIZE - n,
 			      "group=%ld\n", (h_aggregation >> 2*8)&0xffff);
 
-		n += snprintf(buf+n, LPARCFG_BUFF_SIZE - n, 
+		n += scnprintf(buf+n, LPARCFG_BUFF_SIZE - n,
 			      "capped=%ld\n", (h_resource >> 6*8)&0x40);
 
-		n += snprintf(buf+n, LPARCFG_BUFF_SIZE - n, 
+		n += scnprintf(buf+n, LPARCFG_BUFF_SIZE - n,
 			      "capacity_weight=%d\n", (int)(h_resource>>5*8)&0xFF);
 	}
 	return 0;
--- diff/arch/ppc64/kernel/misc.S	2004-02-18 08:54:08.000000000 +0000
+++ source/arch/ppc64/kernel/misc.S	2004-02-23 13:56:39.000000000 +0000
@@ -383,10 +383,6 @@ _GLOBAL(abs)
 	neg	r3,r3
 10:	blr
 
-_GLOBAL(_get_SP)
-	mr	r3,r1		/* Close enough */
-	blr
-	
 _GLOBAL(_get_PVR)
 	mfspr	r3,PVR
 	blr
--- diff/arch/ppc64/kernel/pSeries_nvram.c	2004-02-18 08:54:08.000000000 +0000
+++ source/arch/ppc64/kernel/pSeries_nvram.c	2004-02-23 13:56:39.000000000 +0000
@@ -41,7 +41,8 @@ static ssize_t pSeries_nvram_read(char *
 	unsigned long flags;
 	char *p = buf;
 
-	if (nvram_size == 0 || nvram_fetch)
+
+	if (nvram_size == 0 || nvram_fetch == RTAS_UNKNOWN_SERVICE)
 		return -ENODEV;
 
 	if (*index >= nvram_size)
@@ -83,7 +84,7 @@ static ssize_t pSeries_nvram_write(char 
 	unsigned long flags;
 	const char *p = buf;
 
-	if (nvram_size == 0 || nvram_store)
+	if (nvram_size == 0 || nvram_store == RTAS_UNKNOWN_SERVICE)
 		return -ENODEV;
 
 	if (*index >= nvram_size)
--- diff/arch/ppc64/kernel/pmac_setup.c	2004-02-18 08:54:08.000000000 +0000
+++ source/arch/ppc64/kernel/pmac_setup.c	2004-02-23 13:56:39.000000000 +0000
@@ -73,7 +73,6 @@
 
 #include "pmac.h"
 
-extern char saved_command_line[];
 static int current_root_goodness = -1;
 #define DEFAULT_ROOT_DEVICE Root_SDA1	/* sda1 - slightly silly choice */
 
--- diff/arch/ppc64/kernel/ppc_ksyms.c	2004-02-18 08:54:08.000000000 +0000
+++ source/arch/ppc64/kernel/ppc_ksyms.c	2004-02-23 13:56:39.000000000 +0000
@@ -20,6 +20,7 @@
 #include <linux/pci.h>
 #include <linux/delay.h>
 #include <linux/smp_lock.h>
+#include <linux/syscalls.h>
 
 #include <asm/page.h>
 #include <asm/semaphore.h>
@@ -48,7 +49,6 @@
 #include <asm/iSeries/HvLpConfig.h>
 #endif
 
-extern int sys_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg);
 extern int do_signal(sigset_t *, struct pt_regs *);
 
 int abs(int);
--- diff/arch/ppc64/kernel/process.c	2004-02-18 08:54:08.000000000 +0000
+++ source/arch/ppc64/kernel/process.c	2004-02-23 13:56:39.000000000 +0000
@@ -162,7 +162,7 @@ struct task_struct *__switch_to(struct t
 	 * for that first.
 	 */
 	if ((cur_cpu_spec->cpu_features & CPU_FTR_SLB) &&
-	    GET_ESID((unsigned long)_get_SP()) != GET_ESID(PAGE_OFFSET)) {
+	    GET_ESID(__get_SP()) != GET_ESID(PAGE_OFFSET)) {
 		union {
 			unsigned long word0;
 			slb_dword0 data;
@@ -171,7 +171,7 @@ struct task_struct *__switch_to(struct t
 		esid_data.word0 = 0;
 		/* class bit is in valid field for slbie instruction */
 		esid_data.data.v = 1;
-		esid_data.data.esid = GET_ESID((unsigned long)_get_SP());
+		esid_data.data.esid = GET_ESID(__get_SP());
 		asm volatile("isync; slbie %0; isync" : : "r" (esid_data));
 	}
 	local_irq_restore(flags);
@@ -202,13 +202,11 @@ void show_regs(struct pt_regs * regs)
 #endif /* CONFIG_SMP */
 
 	for (i = 0; i < 32; i++) {
-		long r;
 		if ((i % 4) == 0) {
 			printk("\n" KERN_INFO "GPR%02d: ", i);
 		}
-		if (__get_user(r, &(regs->gpr[i])))
-		    return;
-		printk("%016lX ", r);
+
+		printk("%016lX ", regs->gpr[i]);
 	}
 	printk("\n");
 	/*
@@ -473,6 +471,20 @@ out:
 	return error;
 }
 
+static int kstack_depth_to_print = 64;
+
+static inline int validate_sp(unsigned long sp, struct task_struct *p)
+{
+	unsigned long stack_page = (unsigned long)p->thread_info;
+
+	if (sp < stack_page + sizeof(struct thread_struct))
+		return 0;
+	if (sp >= stack_page + THREAD_SIZE)
+		return 0;
+
+	return 1;
+}
+
 /*
  * These bracket the sleeping functions..
  */
@@ -484,24 +496,23 @@ extern void scheduling_functions_end_her
 unsigned long get_wchan(struct task_struct *p)
 {
 	unsigned long ip, sp;
-	unsigned long stack_page = (unsigned long)p->thread_info;
 	int count = 0;
+
 	if (!p || p == current || p->state == TASK_RUNNING)
 		return 0;
+
 	sp = p->thread.ksp;
+	if (!validate_sp(sp, p))
+		return 0;
+
 	do {
 		sp = *(unsigned long *)sp;
-		if (sp < (stack_page + sizeof(struct thread_struct)) ||
-		    sp >= (stack_page + THREAD_SIZE))
+		if (!validate_sp(sp, p))
 			return 0;
 		if (count > 0) {
 			ip = *(unsigned long *)(sp + 16);
-			/*
-			 * XXX we mask the upper 32 bits until procps
-			 * gets fixed.
-			 */
 			if (ip < first_sched || ip >= last_sched)
-				return (ip & 0xFFFFFFFF);
+				return ip;
 		}
 	} while (count++ < 16);
 	return 0;
@@ -510,33 +521,35 @@ unsigned long get_wchan(struct task_stru
 void show_stack(struct task_struct *p, unsigned long *_sp)
 {
 	unsigned long ip;
-	unsigned long stack_page = (unsigned long)p->thread_info;
 	int count = 0;
 	unsigned long sp = (unsigned long)_sp;
 
-	if (!p)
+	if (sp == 0) {
+		if (p) {
+			sp = p->thread.ksp;
+		} else {
+			sp = __get_SP();
+			p = current;
+		}
+	}
+
+	if (!validate_sp(sp, p))
 		return;
 
-	if (sp == 0)
-		sp = p->thread.ksp;
 	printk("Call Trace:\n");
 	do {
-		if (__get_user(sp, (unsigned long *)sp))
-			break;
-		if (sp < stack_page + sizeof(struct thread_struct))
-			break;
-		if (sp >= stack_page + THREAD_SIZE)
-			break;
-		if (__get_user(ip, (unsigned long *)(sp + 16)))
-			break;
+		sp = *(unsigned long *)sp;
+		if (!validate_sp(sp, p))
+			return;
+		ip = *(unsigned long *)(sp + 16);
 		printk("[%016lx] ", ip);
 		print_symbol("%s\n", ip);
-	} while (count++ < 32);
+	} while (count++ < kstack_depth_to_print);
 }
 
 void dump_stack(void)
 {
-	show_stack(current, (unsigned long *)_get_SP());
+	show_stack(current, (unsigned long *)__get_SP());
 }
 
 EXPORT_SYMBOL(dump_stack);
--- diff/arch/ppc64/kernel/prom.c	2004-02-18 08:54:08.000000000 +0000
+++ source/arch/ppc64/kernel/prom.c	2004-02-23 13:56:39.000000000 +0000
@@ -30,6 +30,7 @@
 #include <linux/types.h>
 #include <linux/pci.h>
 #include <linux/proc_fs.h>
+#include <linux/stringify.h>
 #include <linux/delay.h>
 #include <asm/prom.h>
 #include <asm/rtas.h>
@@ -51,6 +52,7 @@
 #include <asm/ppcdebug.h>
 #include <asm/btext.h>
 #include <asm/sections.h>
+#include <asm/machdep.h>
 #include "open_pic.h"
 
 #ifdef CONFIG_LOGO_LINUX_CLUT224
@@ -184,14 +186,14 @@ extern void enter_prom(void *dummy,...);
 extern void copy_and_flush(unsigned long dest, unsigned long src,
 			   unsigned long size, unsigned long offset);
 
-extern char cmd_line[512];	/* XXX */
 unsigned long dev_tree_size;
+unsigned long _get_PIR(void);
 
 #ifdef CONFIG_HMT
 struct {
 	unsigned int pir;
 	unsigned int threadid;
-} hmt_thread_data[NR_CPUS] = {0};
+} hmt_thread_data[NR_CPUS];
 #endif /* CONFIG_HMT */
 
 char testString[] = "LINUX\n"; 
@@ -698,9 +700,6 @@ prom_dump_lmb(void)
         prom_print(RELOC("    memory.size                 = 0x"));
         prom_print_hex(_lmb->memory.size);
 	prom_print_nl();
-        prom_print(RELOC("    memory.lcd_size             = 0x"));
-        prom_print_hex(_lmb->memory.lcd_size);
-	prom_print_nl();
         for (i=0; i < _lmb->memory.cnt ;i++) {
                 prom_print(RELOC("    memory.region[0x"));
 		prom_print_hex(i);
@@ -713,9 +712,6 @@ prom_dump_lmb(void)
                 prom_print(RELOC("                      .size     = 0x"));
                 prom_print_hex(_lmb->memory.region[i].size);
 		prom_print_nl();
-                prom_print(RELOC("                      .type     = 0x"));
-                prom_print_hex(_lmb->memory.region[i].type);
-		prom_print_nl();
         }
 
 	prom_print_nl();
@@ -725,9 +721,6 @@ prom_dump_lmb(void)
         prom_print(RELOC("    reserved.size                 = 0x"));
         prom_print_hex(_lmb->reserved.size);
 	prom_print_nl();
-        prom_print(RELOC("    reserved.lcd_size             = 0x"));
-        prom_print_hex(_lmb->reserved.lcd_size);
-	prom_print_nl();
         for (i=0; i < _lmb->reserved.cnt ;i++) {
                 prom_print(RELOC("    reserved.region[0x"));
 		prom_print_hex(i);
@@ -740,9 +733,6 @@ prom_dump_lmb(void)
                 prom_print(RELOC("                      .size     = 0x"));
                 prom_print_hex(_lmb->reserved.region[i].size);
 		prom_print_nl();
-                prom_print(RELOC("                      .type     = 0x"));
-                prom_print_hex(_lmb->reserved.region[i].type);
-		prom_print_nl();
         }
 }
 #endif /* DEBUG_PROM */
@@ -1084,6 +1074,10 @@ prom_hold_cpus(unsigned long mem)
 
 			if (*acknowledge == cpuid) {
 				prom_print(RELOC("ok\n"));
+				/* We have to get every CPU out of OF,
+				 * even if we never start it. */
+				if (cpuid >= NR_CPUS)
+					goto next;
 #ifdef CONFIG_SMP
 				/* Set the number of active processors. */
 				_systemcfg->processorCount++;
@@ -1110,9 +1104,12 @@ prom_hold_cpus(unsigned long mem)
 			cpu_set(cpuid, RELOC(cpu_present_at_boot));
 		}
 
+	next:
 		/* Init paca for secondary threads.   They start later. */
 		for (i=1; i < cpu_threads; i++) {
 			cpuid++;
+			if (cpuid >= NR_CPUS)
+				continue;
 			_xPaca[cpuid].xHwProcNum = interrupt_server[i];
 			prom_print_hex(interrupt_server[i]);
 			prom_print(RELOC(" : preparing thread ... "));
@@ -1157,7 +1154,11 @@ prom_hold_cpus(unsigned long mem)
 		prom_print(RELOC("Processor is not HMT capable\n"));
 	}
 #endif
-	
+
+	if (cpuid >= NR_CPUS)
+		prom_print(RELOC("WARNING: maximum CPUs (" __stringify(NR_CPUS)
+				 ") exceeded: ignoring extras\n"));
+
 #ifdef DEBUG_PROM
 	prom_print(RELOC("prom_hold_cpus: end...\n"));
 #endif
@@ -1202,9 +1203,9 @@ smt_setup(void)
 				sizeof(option));
 			if (option[0] != 0) {
 				found = 1;
-				if (!strcmp(option, "off"))	
+				if (!strcmp(option, RELOC("off")))
 					my_smt_enabled = SMT_OFF;
-				else if (!strcmp(option, "on"))	
+				else if (!strcmp(option, RELOC("on")))
 					my_smt_enabled = SMT_ON;
 				else
 					my_smt_enabled = SMT_DYNAMIC;
@@ -1508,10 +1509,8 @@ prom_init(unsigned long r3, unsigned lon
 		call_prom(RELOC("getprop"), 4, 1, _prom->chosen, 
 			  RELOC("bootargs"), p, sizeof(cmd_line));
 		if (p != NULL && p[0] != 0)
-			strncpy(RELOC(cmd_line), p, sizeof(cmd_line));
+			strlcpy(RELOC(cmd_line), p, sizeof(cmd_line));
 	}
-	RELOC(cmd_line[sizeof(cmd_line) - 1]) = 0;
-
 
 	mem = prom_initialize_lmb(mem);
 
@@ -2987,8 +2986,10 @@ static int of_finish_dynamic_node(struct
 	/* now do the work of finish_node_interrupts */
 
 	ints = (unsigned int *) get_property(node, "interrupts", &intlen);
-	if (!ints)
+	if (!ints) {
+		err = -ENODEV;
 		goto out;
+	}
 
 	intrcells = prom_n_intr_cells(node);
 	intlen /= intrcells * sizeof(unsigned int);
--- diff/arch/ppc64/kernel/rtas-proc.c	2004-02-18 08:54:08.000000000 +0000
+++ source/arch/ppc64/kernel/rtas-proc.c	2004-02-23 13:56:39.000000000 +0000
@@ -287,9 +287,9 @@ static ssize_t ppc_rtas_poweron_read(str
 	char stkbuf[40];  /* its small, its on stack */
 	int n, sn;
 	if (power_on_time == 0)
-		n = snprintf(stkbuf, 40, "Power on time not set\n");
+		n = scnprintf(stkbuf,sizeof(stkbuf),"Power on time not set\n");
 	else
-		n = snprintf(stkbuf, 40, "%lu\n", power_on_time);
+		n = scnprintf(stkbuf,sizeof(stkbuf),"%lu\n",power_on_time);
 
 	sn = strlen (stkbuf) +1;
 	if (*ppos >= sn)
@@ -410,9 +410,10 @@ static ssize_t ppc_rtas_clock_read(struc
 	if (error != 0){
 		printk(KERN_WARNING "error: reading the clock returned: %s\n", 
 				ppc_rtas_process_error(error));
-		n = snprintf (stkbuf, 40, "0");
+		n = scnprintf (stkbuf, sizeof(stkbuf), "0");
 	} else { 
-		n = snprintf (stkbuf, 40, "%lu\n", mktime(year, mon, day, hour, min, sec));
+		n = scnprintf (stkbuf, sizeof(stkbuf), "%lu\n",
+				mktime(year, mon, day, hour, min, sec));
 	}
 	kfree(ret);
 
@@ -819,7 +820,7 @@ int get_location_code(struct individual_
 		n += check_location_string(ret, buffer + n);
 		n += sprintf ( buffer+n, " ");
 		/* see how many characters we have printed */
-		snprintf ( t, 50, "%s ", ret);
+		scnprintf(t, sizeof(t), "%s ", ret);
 
 		pos += strlen(t);
 		if (pos >= llen) pos=0;
@@ -863,7 +864,7 @@ static ssize_t ppc_rtas_tone_freq_read(s
 	int n, sn;
 	char stkbuf[40];  /* its small, its on stack */
 
-	n = snprintf(stkbuf, 40, "%lu\n", rtas_tone_frequency);
+	n = scnprintf(stkbuf, 40, "%lu\n", rtas_tone_frequency);
 
 	sn = strlen (stkbuf) +1;
 	if (*ppos >= sn)
@@ -917,7 +918,7 @@ static ssize_t ppc_rtas_tone_volume_read
 	int n, sn;
 	char stkbuf[40];  /* its small, its on stack */
 
-	n = snprintf(stkbuf, 40, "%lu\n", rtas_tone_volume);
+	n = scnprintf(stkbuf, 40, "%lu\n", rtas_tone_volume);
 
 	sn = strlen (stkbuf) +1;
 	if (*ppos >= sn)
--- diff/arch/ppc64/kernel/rtas.c	2004-02-09 10:36:09.000000000 +0000
+++ source/arch/ppc64/kernel/rtas.c	2004-02-23 13:56:39.000000000 +0000
@@ -59,6 +59,8 @@ struct rtas_t rtas = { 
 	.lock = SPIN_LOCK_UNLOCKED
 };
 
+char rtas_err_buf[RTAS_ERROR_LOG_MAX];
+
 extern unsigned long reloc_offset(void);
 
 spinlock_t rtas_data_buf_lock = SPIN_LOCK_UNLOCKED;
@@ -126,6 +128,34 @@ rtas_token(const char *service)
 	return tokp ? *tokp : RTAS_UNKNOWN_SERVICE;
 }
 
+void
+log_rtas_error(struct rtas_args	*rtas_args)
+{
+	struct rtas_args err_args;
+
+	err_args.token = rtas_token("rtas-last-error");
+	err_args.nargs = 2;
+	err_args.nret = 1;
+	err_args.rets = (rtas_arg_t *)&(err_args.args[2]);
+
+	err_args.args[0] = (rtas_arg_t)__pa(rtas_err_buf);
+	err_args.args[1] = RTAS_ERROR_LOG_MAX;
+	err_args.args[2] = 0;
+
+	get_paca()->xRtas = err_args;
+
+	PPCDBG(PPCDBG_RTAS, "\tentering rtas with 0x%lx\n",
+	       (void *)__pa((unsigned long)&err_args));
+	enter_rtas((void *)__pa((unsigned long)&get_paca()->xRtas));
+	PPCDBG(PPCDBG_RTAS, "\treturned from rtas ...\n");
+
+	err_args = get_paca()->xRtas;
+	get_paca()->xRtas = *rtas_args;
+
+	if (err_args.rets[0] == 0)
+		log_error(rtas_err_buf, ERR_TYPE_RTAS_LOG, 0);
+}
+
 long
 rtas_call(int token, int nargs, int nret,
 	  unsigned long *outputs, ...)
@@ -166,6 +196,10 @@ rtas_call(int token, int nargs, int nret
 		(void *)__pa((unsigned long)rtas_args));
 	enter_rtas((void *)__pa((unsigned long)rtas_args));
 	PPCDBG(PPCDBG_RTAS, "\treturned from rtas ...\n");
+
+	if (rtas_args->rets[0] == -1)
+		log_rtas_error(rtas_args);
+
 #if 0   /* Gotta do something different here, use global lock for now... */
 	spin_unlock_irqrestore(&rtas_args->lock, s);
 #else
@@ -410,9 +444,14 @@ asmlinkage int ppc_rtas(struct rtas_args
 		return -EFAULT;
 
 	spin_lock_irqsave(&rtas.lock, flags);
+
 	get_paca()->xRtas = args;
 	enter_rtas((void *)__pa((unsigned long)&get_paca()->xRtas));
 	args = get_paca()->xRtas;
+
+	if (args.rets[0] == -1)
+		log_rtas_error(&args);
+
 	spin_unlock_irqrestore(&rtas.lock, flags);
 
 	/* Copy out args. */
--- diff/arch/ppc64/kernel/rtas_flash.c	2004-02-09 10:36:09.000000000 +0000
+++ source/arch/ppc64/kernel/rtas_flash.c	2004-02-23 13:56:39.000000000 +0000
@@ -20,7 +20,7 @@
 #include <asm/uaccess.h>
 #include <asm/rtas.h>
 
-#define MODULE_VERSION "1.0"
+#define MODULE_VERS "1.0"
 #define MODULE_NAME "rtas_flash"
 
 #define FIRMWARE_FLASH_NAME "firmware_flash"   
--- diff/arch/ppc64/kernel/rtasd.c	2004-02-18 08:54:08.000000000 +0000
+++ source/arch/ppc64/kernel/rtasd.c	2004-02-23 13:56:39.000000000 +0000
@@ -18,6 +18,7 @@
 #include <linux/init.h>
 #include <linux/vmalloc.h>
 #include <linux/spinlock.h>
+#include <linux/cpu.h>
 
 #include <asm/uaccess.h>
 #include <asm/io.h>
@@ -336,15 +337,31 @@ static int get_eventscan_parms(void)
 	return 0;
 }
 
-extern long sys_sched_get_priority_max(int policy);
+static void do_event_scan(int event_scan)
+{
+	int error;
+	do {
+		memset(logdata, 0, rtas_error_log_max);
+		error = rtas_call(event_scan, 4, 1, NULL,
+				  RTAS_EVENT_SCAN_ALL_EVENTS, 0,
+				  __pa(logdata), rtas_error_log_max);
+		if (error == -1) {
+			printk(KERN_ERR "event-scan failed\n");
+			break;
+		}
+
+		if (error == 0)
+			pSeries_log_error(logdata, ERR_TYPE_RTAS_LOG, 0);
+
+	} while(error == 0);
+}
 
 static int rtasd(void *unused)
 {
 	unsigned int err_type;
 	int cpu = 0;
-	int error;
-	int first_pass = 1;
 	int event_scan = rtas_token("event-scan");
+	cpumask_t all = CPU_MASK_ALL;
 	int rc;
 
 	daemonize("rtasd");
@@ -375,48 +392,45 @@ static int rtasd(void *unused)
 		}
 	}
 
-repeat:
-	for (cpu = 0; cpu < NR_CPUS; cpu++) {
-		if (!cpu_online(cpu))
-			continue;
-
+	/* First pass. */
+	lock_cpu_hotplug();
+	for_each_online_cpu(cpu) {
 		DEBUG("scheduling on %d\n", cpu);
 		set_cpus_allowed(current, cpumask_of_cpu(cpu));
 		DEBUG("watchdog scheduled on cpu %d\n", smp_processor_id());
 
-		do {
-			memset(logdata, 0, rtas_error_log_max);
-			error = rtas_call(event_scan, 4, 1, NULL,
-					RTAS_EVENT_SCAN_ALL_EVENTS, 0,
-					__pa(logdata), rtas_error_log_max);
-			if (error == -1) {
-				printk(KERN_ERR "event-scan failed\n");
-				break;
-			}
-
-			if (error == 0)
-				pSeries_log_error(logdata, ERR_TYPE_RTAS_LOG, 0);
-
-		} while(error == 0);
-
-		/*
-		 * Check all cpus for pending events quickly, sleeping for
-		 * at least one second since some machines have problems
-		 * if we call event-scan too quickly
-		 */
+		do_event_scan(event_scan);
 		set_current_state(TASK_INTERRUPTIBLE);
-		schedule_timeout(first_pass ? HZ : (HZ*60/rtas_event_scan_rate) / 2);
+		schedule_timeout(HZ);
 	}
+	unlock_cpu_hotplug();
 
-	if (first_pass && (surveillance_timeout != -1)) {
+	if (surveillance_timeout != -1) {
 		DEBUG("enabling surveillance\n");
 		if (enable_surveillance(surveillance_timeout))
 			goto error_vfree;
 		DEBUG("surveillance enabled\n");
 	}
 
-	first_pass = 0;
-	goto repeat;
+	lock_cpu_hotplug();
+	cpu = first_cpu_const(mk_cpumask_const(cpu_online_map));
+	for (;;) {
+		set_cpus_allowed(current, cpumask_of_cpu(cpu));
+		do_event_scan(event_scan);
+		set_cpus_allowed(current, all);
+
+		/* Drop hotplug lock, and sleep for a bit (at least
+		 * one second since some machines have problems if we
+		 * call event-scan too quickly). */
+		unlock_cpu_hotplug();
+		set_current_state(TASK_INTERRUPTIBLE);
+		schedule_timeout((HZ*60/rtas_event_scan_rate) / 2);
+		lock_cpu_hotplug();
+
+		cpu = next_cpu_const(cpu, mk_cpumask_const(cpu_online_map));
+		if (cpu == NR_CPUS)
+			cpu = first_cpu_const(mk_cpumask_const(cpu_online_map));
+	}
 
 error_vfree:
 	if (rtas_log_buf)
--- diff/arch/ppc64/kernel/scanlog.c	2004-02-09 10:36:09.000000000 +0000
+++ source/arch/ppc64/kernel/scanlog.c	2004-02-23 13:56:39.000000000 +0000
@@ -30,7 +30,7 @@
 #include <asm/prom.h>
 #include <asm/proc_fs.h>
 
-#define MODULE_VERSION "1.0"
+#define MODULE_VERS "1.0"
 #define MODULE_NAME "scanlog"
 
 /* Status returns from ibm,scan-log-dump */
--- diff/arch/ppc64/kernel/setup.c	2004-02-18 08:54:08.000000000 +0000
+++ source/arch/ppc64/kernel/setup.c	2004-02-23 13:56:39.000000000 +0000
@@ -80,7 +80,7 @@ unsigned long decr_overclock_proc0_set =
 
 int powersave_nap;
 
-char saved_command_line[256];
+char saved_command_line[COMMAND_LINE_SIZE];
 unsigned char aux_device_present;
 
 void parse_cmd_line(unsigned long r3, unsigned long r4, unsigned long r5,
@@ -155,7 +155,7 @@ void __init disable_early_printk(void)
 void setup_system(unsigned long r3, unsigned long r4, unsigned long r5,
 		  unsigned long r6, unsigned long r7)
 {
-#ifdef CONFIG_PPC_PSERIES
+#if defined(CONFIG_SMP) && defined(CONFIG_PPC_PSERIES)
 	unsigned int ret, i;
 #endif
 
@@ -232,8 +232,8 @@ void setup_system(unsigned long r3, unsi
 				systemcfg->processorCount++;
 			}
 		}
-	}
 #endif /* CONFIG_SMP */
+	}
 #endif /* CONFIG_PPC_PSERIES */
 
 #ifdef CONFIG_PPC_PMAC
@@ -477,7 +477,7 @@ static int __init set_preferred_console(
 	char *name;
 
 	/* The user has requested a console so this is already set up. */
-	if (strstr(cmd_line, "console="))
+	if (strstr(saved_command_line, "console="))
 		return -EBUSY;
 
 	prom_stdout = find_path_device(of_stdout_device);
@@ -536,7 +536,7 @@ int parse_bootinfo(void)
 	for ( ; rec->tag != BI_LAST ; rec = bi_rec_next(rec) ) {
 		switch (rec->tag) {
 		case BI_CMD_LINE:
-			memcpy(cmd_line, (void *)rec->data, rec->size);
+			strlcpy(cmd_line, (void *)rec->data, sizeof(cmd_line));
 			break;
 		case BI_SYSMAP:
 			sysmap = __va(rec->data[0]);
@@ -620,7 +620,7 @@ void __init setup_arch(char **cmdline_p)
 	init_mm.brk = klimit;
 	
 	/* Save unparsed command line copy for /proc/cmdline */
-	strcpy(saved_command_line, cmd_line);
+	strlcpy(saved_command_line, cmd_line, sizeof(saved_command_line));
 	*cmdline_p = cmd_line;
 
 	/* set up the bootmem stuff with available memory */
--- diff/arch/ppc64/kernel/signal32.c	2004-02-09 10:36:09.000000000 +0000
+++ source/arch/ppc64/kernel/signal32.c	2004-02-23 13:56:39.000000000 +0000
@@ -21,6 +21,7 @@
 #include <linux/smp_lock.h>
 #include <linux/kernel.h>
 #include <linux/signal.h>
+#include <linux/syscalls.h>
 #include <linux/errno.h>
 #include <linux/elf.h>
 #include <linux/compat.h>
--- diff/arch/ppc64/kernel/smp.c	2004-02-18 08:54:08.000000000 +0000
+++ source/arch/ppc64/kernel/smp.c	2004-02-23 13:56:39.000000000 +0000
@@ -28,6 +28,8 @@
 #include <linux/spinlock.h>
 #include <linux/cache.h>
 #include <linux/err.h>
+#include <linux/sysdev.h>
+#include <linux/cpu.h>
 
 #include <asm/ptrace.h>
 #include <asm/atomic.h>
@@ -54,10 +56,9 @@
 int smp_threads_ready;
 unsigned long cache_decay_ticks;
 
-/* Initialised so it doesn't end up in bss */
-cpumask_t cpu_possible_map    = CPU_MASK_NONE;
+cpumask_t cpu_possible_map = CPU_MASK_NONE;
 cpumask_t cpu_online_map = CPU_MASK_NONE;
-cpumask_t cpu_available_map   = CPU_MASK_NONE;
+cpumask_t cpu_available_map = CPU_MASK_NONE;
 cpumask_t cpu_present_at_boot = CPU_MASK_NONE;
 
 EXPORT_SYMBOL(cpu_online_map);
@@ -71,14 +72,12 @@ extern unsigned char stab_array[];
 
 extern int cpu_idle(void *unused);
 void smp_call_function_interrupt(void);
-void smp_message_pass(int target, int msg, unsigned long data, int wait);
 extern long register_vpa(unsigned long flags, unsigned long proc,
 			 unsigned long vpa);
 
-#define smp_message_pass(t,m,d,w) smp_ops->message_pass((t),(m),(d),(w))
-
 /* Low level assembly function used to backup CPU 0 state */
 extern void __save_cpu_setup(void);
+
 #ifdef CONFIG_PPC_ISERIES
 static unsigned long iSeries_smp_message[NR_CPUS];
 
@@ -95,20 +94,24 @@ void iSeries_smp_message_recv( struct pt
 			smp_message_recv( msg, regs );
 }
 
-static void smp_iSeries_message_pass(int target, int msg, unsigned long data, int wait)
+static inline void smp_iSeries_do_message(int cpu, int msg)
+{
+	set_bit(msg, &iSeries_smp_message[cpu]);
+	HvCall_sendIPI(&(paca[cpu]));
+}
+
+static void smp_iSeries_message_pass(int target, int msg)
 {
 	int i;
 
-	for (i = 0; i < NR_CPUS; ++i) {
-		if (!cpu_online(i))
-			continue;
-
-		if ((target == MSG_ALL) || 
-		    (target == i) || 
-		    ((target == MSG_ALL_BUT_SELF) &&
-		     (i != smp_processor_id())) ) {
-			set_bit(msg, &iSeries_smp_message[i]);
-			HvCall_sendIPI(&(paca[i]));
+	if (target < NR_CPUS)
+		smp_iSeries_do_message(target, msg);
+	else {
+		for_each_online_cpu(i) {
+			if (target == MSG_ALL_BUT_SELF
+			    && i == smp_processor_id())
+				continue;
+			smp_iSeries_do_message(i, msg);
 		}
 	}
 }
@@ -150,22 +153,15 @@ static int smp_iSeries_probe(void)
 
 static void smp_iSeries_kick_cpu(int nr)
 {
-	struct ItLpPaca * lpPaca;
-	/* Verify we have a Paca for processor nr */
-	if ( ( nr <= 0 ) ||
-	     ( nr >= NR_CPUS ) )
-		return;
+	struct ItLpPaca *lpPaca;
+
+	BUG_ON(nr < 0 || nr >= NR_CPUS);
+
 	/* Verify that our partition has a processor nr */
 	lpPaca = paca[nr].xLpPacaPtr;
-	if ( lpPaca->xDynProcStatus >= 2 )
+	if (lpPaca->xDynProcStatus >= 2)
 		return;
 
-	/* The information for processor bringup must
-	 * be written out to main store before we release
-	 * the processor.
-	 */
-	mb();
-
 	/* The processor is currently spinning, waiting
 	 * for the xProcStart field to become non-zero
 	 * After we set xProcStart, the processor will
@@ -194,7 +190,7 @@ void __init smp_init_iSeries(void)
 #endif
 
 #ifdef CONFIG_PPC_PSERIES
-void smp_openpic_message_pass(int target, int msg, unsigned long data, int wait)
+void smp_openpic_message_pass(int target, int msg)
 {
 	/* make sure we're sending something that translates to an IPI */
 	if ( msg > 0x3 ){
@@ -219,13 +215,9 @@ void smp_openpic_message_pass(int target
 
 static int __init smp_openpic_probe(void)
 {
-	int i;
-	int nr_cpus = 0;
+	int nr_cpus;
 
-	for (i = 0; i < NR_CPUS; i++) {
-		if (cpu_possible(i))
-			nr_cpus++;
-	}
+	nr_cpus = cpus_weight(cpu_possible_map);
 
 	if (nr_cpus > 1)
 		openpic_request_IPIs();
@@ -240,16 +232,7 @@ static void __devinit smp_openpic_setup_
 
 static void smp_pSeries_kick_cpu(int nr)
 {
-	/* Verify we have a Paca for processor nr */
-	if ( ( nr <= 0 ) ||
-	     ( nr >= NR_CPUS ) )
-		return;
-
-	/* The information for processor bringup must
-	 * be written out to main store before we release
-	 * the processor.
-	 */
-	mb();
+	BUG_ON(nr < 0 || nr >= NR_CPUS);
 
 	/* The processor is currently spinning, waiting
 	 * for the xProcStart field to become non-zero
@@ -266,8 +249,8 @@ static void __init smp_space_timers(unsi
 	unsigned long offset = tb_ticks_per_jiffy / max_cpus;
 	unsigned long previous_tb = paca[boot_cpuid].next_jiffy_update_tb;
 
-	for (i = 0; i < NR_CPUS; i++) {
-		if (cpu_possible(i) && i != boot_cpuid) {
+	for_each_cpu(i) {
+		if (i != boot_cpuid) {
 			paca[i].next_jiffy_update_tb =
 				previous_tb + offset;
 			previous_tb = paca[i].next_jiffy_update_tb;
@@ -287,20 +270,25 @@ void vpa_init(int cpu)
 	register_vpa(flags, cpu, __pa((unsigned long)&(paca[cpu].xLpPaca))); 
 }
 
-static void smp_xics_message_pass(int target, int msg, unsigned long data, int wait)
+static inline void smp_xics_do_message(int cpu, int msg)
 {
-	int i;
+	set_bit(msg, &xics_ipi_message[cpu].value);
+	mb();
+	xics_cause_IPI(cpu);
+}
+
+static void smp_xics_message_pass(int target, int msg)
+{
+	unsigned int i;
 
-	for (i = 0; i < NR_CPUS; ++i) {
-		if (!cpu_online(i))
-			continue;
-
-		if (target == MSG_ALL || target == i
-		    || (target == MSG_ALL_BUT_SELF
-			&& i != smp_processor_id())) {
-			set_bit(msg, &xics_ipi_message[i].value);
-			mb();
-			xics_cause_IPI(i);
+	if (target < NR_CPUS) {
+		smp_xics_do_message(target, msg);
+	} else {
+		for_each_online_cpu(i) {
+			if (target == MSG_ALL_BUT_SELF
+			    && i == smp_processor_id())
+				continue;
+			smp_xics_do_message(i, msg);
 		}
 	}
 }
@@ -309,18 +297,11 @@ extern void xics_request_IPIs(void);
 
 static int __init smp_xics_probe(void)
 {
-	int i;
-	int nr_cpus = 0;
-
-	for (i = 0; i < NR_CPUS; i++) {
-		if (cpu_possible(i))
-			nr_cpus++;
-	}
 #ifdef CONFIG_SMP
 	xics_request_IPIs();
 #endif
 
-	return nr_cpus;
+	return cpus_weight(cpu_possible_map);
 }
 
 static void __devinit smp_xics_setup_cpu(int cpu)
@@ -422,13 +403,13 @@ void smp_message_recv(int msg, struct pt
 
 void smp_send_reschedule(int cpu)
 {
-	smp_message_pass(cpu, PPC_MSG_RESCHEDULE, 0, 0);
+	smp_ops->message_pass(cpu, PPC_MSG_RESCHEDULE);
 }
 
 #ifdef CONFIG_DEBUGGER
 void smp_send_debugger_break(int cpu)
 {
-	smp_message_pass(cpu, PPC_MSG_DEBUGGER_BREAK, 0, 0);
+	smp_ops->message_pass(cpu, PPC_MSG_DEBUGGER_BREAK);
 }
 #endif
 
@@ -498,7 +479,7 @@ int smp_call_function (void (*func) (voi
 	call_data = &data;
 	wmb();
 	/* Send a message to all other CPUs and wait for them to respond */
-	smp_message_pass(MSG_ALL_BUT_SELF, PPC_MSG_CALL_FUNCTION, 0, 0);
+	smp_ops->message_pass(MSG_ALL_BUT_SELF, PPC_MSG_CALL_FUNCTION);
 
 	/* Wait for response */
 	timeout = SMP_CALL_TIMEOUT;
@@ -554,6 +535,9 @@ void smp_call_function_interrupt(void)
 	info = call_data->info;
 	wait = call_data->wait;
 
+	if (!wait)
+		smp_mb__before_atomic_inc();
+
 	/*
 	 * Notify initiating CPU that I've grabbed the data and am
 	 * about to execute the function
@@ -563,8 +547,10 @@ void smp_call_function_interrupt(void)
 	 * At this point the info structure may be out of scope unless wait==1
 	 */
 	(*func)(info);
-	if (wait)
+	if (wait) {
+		smp_mb__before_atomic_inc();
 		atomic_inc(&call_data->finished);
+	}
 }
 
 extern unsigned long decr_overclock;
@@ -660,6 +646,12 @@ int __devinit __cpu_up(unsigned int cpu)
 	paca[cpu].xCurrent = (u64)p;
 	current_set[cpu] = p->thread_info;
 
+	/* The information for processor bringup must
+	 * be written out to main store before we release
+	 * the processor.
+	 */
+	mb();
+
 	/* wake up cpus */
 	smp_ops->kick_cpu(cpu);
 
@@ -736,3 +728,71 @@ void __init smp_cpus_done(unsigned int m
 
 	set_cpus_allowed(current, old_mask);
 }
+
+#ifdef CONFIG_NUMA
+static struct node node_devices[MAX_NUMNODES];
+
+static void register_nodes(void)
+{
+	int i;
+	int ret;
+
+	for (i = 0; i < MAX_NUMNODES; i++) {
+		if (node_online(i)) {
+			int p_node = parent_node(i);
+			struct node *parent = NULL;
+
+			if (p_node != i)
+				parent = &node_devices[p_node];
+
+			ret = register_node(&node_devices[i], i, parent);
+			if (ret)
+				printk(KERN_WARNING "register_nodes: "
+				       "register_node %d failed (%d)", i, ret);
+		}
+	}
+}
+#else
+static void register_nodes(void)
+{
+	return 0;
+}
+#endif
+
+/* Only valid if CPU is online. */
+static ssize_t show_physical_id(struct sys_device *dev, char *buf)
+{
+	struct cpu *cpu = container_of(dev, struct cpu, sysdev);
+
+	return sprintf(buf, "%u\n", get_hard_smp_processor_id(cpu->sysdev.id));
+}
+static SYSDEV_ATTR(physical_id, 0444, show_physical_id, NULL);
+
+static DEFINE_PER_CPU(struct cpu, cpu_devices);
+
+static int __init topology_init(void)
+{
+	int cpu;
+	struct node *parent = NULL;
+	int ret;
+
+	register_nodes();
+
+	for_each_cpu(cpu) {
+#ifdef CONFIG_NUMA
+		parent = &node_devices[cpu_to_node(cpu)];
+#endif
+		ret = register_cpu(&per_cpu(cpu_devices, cpu), cpu, parent);
+		if (ret)
+			printk(KERN_WARNING "topology_init: register_cpu %d "
+			       "failed (%d)\n", cpu, ret);
+
+		ret = sysdev_create_file(&per_cpu(cpu_devices, cpu).sysdev,
+					 &attr_physical_id);
+		if (ret)
+			printk(KERN_WARNING "toplogy_init: sysdev_create_file "
+			       "%d failed (%d)\n", cpu, ret);
+	}
+	return 0;
+}
+__initcall(topology_init);
--- diff/arch/ppc64/kernel/stab.c	2004-02-18 08:54:08.000000000 +0000
+++ source/arch/ppc64/kernel/stab.c	2004-02-23 13:56:39.000000000 +0000
@@ -18,12 +18,11 @@
 #include <asm/mmu_context.h>
 #include <asm/paca.h>
 #include <asm/naca.h>
-#include <asm/pmc.h>
 #include <asm/cputable.h>
 
-int make_ste(unsigned long stab, unsigned long esid, unsigned long vsid);
-void make_slbe(unsigned long esid, unsigned long vsid, int large,
-	       int kernel_segment);
+static int make_ste(unsigned long stab, unsigned long esid, unsigned long vsid);
+static void make_slbe(unsigned long esid, unsigned long vsid, int large,
+		      int kernel_segment);
 
 /*
  * Build an entry for the base kernel segment and put it into
@@ -69,7 +68,7 @@ DEFINE_PER_CPU(long, stab_cache[NR_STAB_
 /*
  * Create a segment table entry for the given esid/vsid pair.
  */
-int make_ste(unsigned long stab, unsigned long esid, unsigned long vsid)
+static int make_ste(unsigned long stab, unsigned long esid, unsigned long vsid)
 {
 	unsigned long entry, group, old_esid, castout_entry, i;
 	unsigned int global_entry;
@@ -88,7 +87,7 @@ int make_ste(unsigned long stab, unsigne
 				ste->dw0.dw0.kp = 1;
 				asm volatile("eieio":::"memory");
 				ste->dw0.dw0.v = 1;
-				return(global_entry | entry);
+				return (global_entry | entry);
 			}
 		}
 		/* Now search the secondary group. */
@@ -144,7 +143,7 @@ int make_ste(unsigned long stab, unsigne
 static inline void __ste_allocate(unsigned long esid, unsigned long vsid)
 {
 	unsigned char stab_entry;
-	unsigned long *offset;
+	unsigned long offset;
 	int region_id = REGION_ID(esid << SID_SHIFT);
 
 	stab_entry = make_ste(get_paca()->xStab_data.virt, esid, vsid);
@@ -152,11 +151,12 @@ static inline void __ste_allocate(unsign
 	if (region_id != USER_REGION_ID)
 		return;
 
-	offset = &__get_cpu_var(stab_cache_ptr);
-	if (*offset < NR_STAB_CACHE_ENTRIES) {
-		__get_cpu_var(stab_cache[*offset]) = stab_entry;
-	}
-	(*offset)++;
+	offset = __get_cpu_var(stab_cache_ptr);
+	if (offset < NR_STAB_CACHE_ENTRIES)
+		__get_cpu_var(stab_cache[offset++]) = stab_entry;
+	else
+		offset = NR_STAB_CACHE_ENTRIES+1;
+	__get_cpu_var(stab_cache_ptr) = offset;
 }
 
 /*
@@ -242,20 +242,18 @@ void flush_stab(struct task_struct *tsk,
 {
 	STE *stab = (STE *) get_paca()->xStab_data.virt;
 	STE *ste;
-	unsigned long *offset = &__get_cpu_var(stab_cache_ptr);
+	unsigned long offset = __get_cpu_var(stab_cache_ptr);
 
 	/* Force previous translations to complete. DRENG */
 	asm volatile("isync" : : : "memory");
 
-	if (*offset <= NR_STAB_CACHE_ENTRIES) {
+	if (offset <= NR_STAB_CACHE_ENTRIES) {
 		int i;
 
-		for (i = 0; i < *offset; i++) {
+		for (i = 0; i < offset; i++) {
 			ste = stab + __get_cpu_var(stab_cache[i]);
 			ste->dw0.dw0.v = 0;
 		}
-
-		asm volatile("sync; slbia; sync":::"memory");
 	} else {
 		unsigned long entry;
 
@@ -273,11 +271,11 @@ void flush_stab(struct task_struct *tsk,
 				ste->dw0.dw0.v = 0;
 			}
 		}
-
-		asm volatile("sync; slbia; sync":::"memory");
 	}
 
-	*offset = 0;
+	asm volatile("sync; slbia; sync":::"memory");
+
+	__get_cpu_var(stab_cache_ptr) = 0;
 
 	preload_stab(tsk, mm);
 }
@@ -292,8 +290,8 @@ void flush_stab(struct task_struct *tsk,
  * NOTE: A context syncronising instruction is required before and after
  * this, in the common case we use exception entry and rfid.
  */
-void make_slbe(unsigned long esid, unsigned long vsid, int large,
-	       int kernel_segment)
+static void make_slbe(unsigned long esid, unsigned long vsid, int large,
+		      int kernel_segment)
 {
 	unsigned long entry, castout_entry;
 	union {
@@ -326,7 +324,7 @@ void make_slbe(unsigned long esid, unsig
 			castout_entry = 1; 
 		asm volatile("slbmfee  %0,%1" : "=r" (esid_data) : "r" (entry));
 	} while (esid_data.data.v &&
-		 esid_data.data.esid == GET_ESID((unsigned long)_get_SP()));
+		 esid_data.data.esid == GET_ESID(__get_SP()));
 
 	get_paca()->xStab_data.next_round_robin = castout_entry;
 
@@ -350,7 +348,7 @@ void make_slbe(unsigned long esid, unsig
 
 	/*
 	 * No need for an isync before or after this slbmte. The exception
-         * we enter with and the rfid we exit with are context synchronizing.
+	 * we enter with and the rfid we exit with are context synchronizing.
 	 */
 	asm volatile("slbmte  %0,%1" : : "r" (vsid_data), "r" (esid_data)); 
 }
@@ -360,7 +358,7 @@ static inline void __slb_allocate(unsign
 {
 	int large = 0;
 	int region_id = REGION_ID(esid << SID_SHIFT);
-	unsigned long *offset;
+	unsigned long offset;
 
 	if (cur_cpu_spec->cpu_features & CPU_FTR_16M_PAGE) {
 		if (region_id == KERNEL_REGION_ID)
@@ -374,11 +372,12 @@ static inline void __slb_allocate(unsign
 	if (region_id != USER_REGION_ID)
 		return;
 
-	offset = &__get_cpu_var(stab_cache_ptr);
-	if (*offset < NR_STAB_CACHE_ENTRIES) {
-		__get_cpu_var(stab_cache[*offset]) = esid;
-	}
-	(*offset)++;
+	offset = __get_cpu_var(stab_cache_ptr);
+	if (offset < NR_STAB_CACHE_ENTRIES)
+		__get_cpu_var(stab_cache[offset++]) = esid;
+	else
+		offset = NR_STAB_CACHE_ENTRIES+1;
+	__get_cpu_var(stab_cache_ptr) = offset;
 }
 
 /*
@@ -457,9 +456,9 @@ static void preload_slb(struct task_stru
 /* Flush all user entries from the segment table of the current processor. */
 void flush_slb(struct task_struct *tsk, struct mm_struct *mm)
 {
-	unsigned long *offset = &__get_cpu_var(stab_cache_ptr);
+	unsigned long offset = __get_cpu_var(stab_cache_ptr);
 
-	if (*offset <= NR_STAB_CACHE_ENTRIES) {
+	if (offset <= NR_STAB_CACHE_ENTRIES) {
 		int i;
 		union {
 			unsigned long word0;
@@ -467,7 +466,7 @@ void flush_slb(struct task_struct *tsk, 
 		} esid_data;
 
 		asm volatile("isync" : : : "memory");
-		for (i = 0; i < *offset; i++) {
+		for (i = 0; i < offset; i++) {
 			esid_data.word0 = 0;
 			esid_data.data.esid = __get_cpu_var(stab_cache[i]);
 			asm volatile("slbie %0" : : "r" (esid_data));
@@ -477,7 +476,7 @@ void flush_slb(struct task_struct *tsk, 
 		asm volatile("isync; slbia; isync" : : : "memory");
 	}
 
-	*offset = 0;
+	__get_cpu_var(stab_cache_ptr) = 0;
 
 	preload_slb(tsk, mm);
 }
--- diff/arch/ppc64/kernel/sys_ppc32.c	2004-02-18 08:54:08.000000000 +0000
+++ source/arch/ppc64/kernel/sys_ppc32.c	2004-02-23 13:56:39.000000000 +0000
@@ -54,6 +54,8 @@
 #include <linux/ipv6.h>
 #include <linux/in.h>
 #include <linux/icmpv6.h>
+#include <linux/syscalls.h>
+#include <linux/unistd.h>
 #include <linux/sysctl.h>
 #include <linux/binfmts.h>
 #include <linux/dnotify.h>
@@ -65,6 +67,7 @@
 #include <asm/types.h>
 #include <asm/ipc.h>
 #include <asm/uaccess.h>
+#include <asm/unistd.h>
 
 #include <asm/semaphore.h>
 
@@ -778,8 +781,6 @@ int cp_compat_stat(struct kstat *stat, s
 	return err;
 }
 
-extern asmlinkage long sys_sysfs(int option, unsigned long arg1, unsigned long arg2);
-
 /* Note: it is necessary to treat option as an unsigned int,
  * with the corresponding cast to a signed int to insure that the 
  * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode)
@@ -1155,8 +1156,6 @@ struct sysinfo32 {
 	char _f[20-2*sizeof(int)-sizeof(int)];
 };
 
-extern asmlinkage long sys_sysinfo(struct sysinfo *info);
-
 asmlinkage long sys32_sysinfo(struct sysinfo32 *info)
 {
 	struct sysinfo s;
@@ -1868,8 +1867,6 @@ asmlinkage long sys32_ipc(u32 call, u32 
 	return err;
 }
 
-extern asmlinkage ssize_t sys_sendfile(int out_fd, int in_fd, off_t* offset, size_t count);
-
 /* Note: it is necessary to treat out_fd and in_fd as unsigned ints, 
  * with the corresponding cast to a signed int to insure that the 
  * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode)
@@ -1894,8 +1891,6 @@ asmlinkage long sys32_sendfile(u32 out_f
 	return ret;
 }
 
-extern asmlinkage ssize_t sys_sendfile64(int out_fd, int in_fd, loff_t *offset, size_t count);
-
 asmlinkage int sys32_sendfile64(int out_fd, int in_fd, compat_loff_t *offset, s32 count)
 {
 	mm_segment_t old_fs = get_fs();
@@ -2158,9 +2153,6 @@ void start_thread32(struct pt_regs* regs
 #endif /* CONFIG_ALTIVEC */
 }
 
-extern asmlinkage int sys_prctl(int option, unsigned long arg2, unsigned long arg3,
-				unsigned long arg4, unsigned long arg5);
-
 /* Note: it is necessary to treat option as an unsigned int, 
  * with the corresponding cast to a signed int to insure that the 
  * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode)
@@ -2175,14 +2167,12 @@ asmlinkage long sys32_prctl(u32 option, 
 			 (unsigned long) arg5);
 }
 
-extern asmlinkage int sys_sched_rr_get_interval(pid_t pid, struct timespec *interval);
-
 /* Note: it is necessary to treat pid as an unsigned int, 
  * with the corresponding cast to a signed int to insure that the 
  * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode)
  * and the register representation of a signed int (msr in 64-bit mode) is performed.
  */
-asmlinkage int sys32_sched_rr_get_interval(u32 pid, struct compat_timespec *interval)
+asmlinkage long sys32_sched_rr_get_interval(u32 pid, struct compat_timespec *interval)
 {
 	struct timespec t;
 	int ret;
@@ -2196,9 +2186,6 @@ asmlinkage int sys32_sched_rr_get_interv
 	return ret;
 }
 
-extern asmlinkage int sys_pciconfig_read(unsigned long bus, unsigned long dfn, unsigned long off,
-					 unsigned long len, unsigned char *buf);
-
 asmlinkage int sys32_pciconfig_read(u32 bus, u32 dfn, u32 off, u32 len, u32 ubuf)
 {
 	return sys_pciconfig_read((unsigned long) bus,
@@ -2208,12 +2195,6 @@ asmlinkage int sys32_pciconfig_read(u32 
 				  (unsigned char *)AA(ubuf));
 }
 
-
-
-
-extern asmlinkage int sys_pciconfig_write(unsigned long bus, unsigned long dfn, unsigned long off,
-					  unsigned long len, unsigned char *buf);
-
 asmlinkage int sys32_pciconfig_write(u32 bus, u32 dfn, u32 off, u32 len, u32 ubuf)
 {
 	return sys_pciconfig_write((unsigned long) bus,
@@ -2281,8 +2262,6 @@ asmlinkage int sys32_pciconfig_iobase(u3
 }
 
 
-extern asmlinkage int sys_newuname(struct new_utsname * name);
-
 asmlinkage int ppc64_newuname(struct new_utsname * name)
 {
 	int errno = sys_newuname(name);
@@ -2295,8 +2274,6 @@ asmlinkage int ppc64_newuname(struct new
 	return errno;
 }
 
-extern asmlinkage long sys_personality(unsigned long);
-
 asmlinkage int ppc64_personality(unsigned long personality)
 {
 	int ret;
@@ -2310,8 +2287,6 @@ asmlinkage int ppc64_personality(unsigne
 
 
 
-extern asmlinkage long sys_access(const char * filename, int mode);
-
 /* Note: it is necessary to treat mode as an unsigned int,
  * with the corresponding cast to a signed int to insure that the 
  * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode)
@@ -2323,8 +2298,6 @@ asmlinkage long sys32_access(const char 
 }
 
 
-extern asmlinkage long sys_creat(const char * pathname, int mode);
-
 /* Note: it is necessary to treat mode as an unsigned int,
  * with the corresponding cast to a signed int to insure that the 
  * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode)
@@ -2336,8 +2309,6 @@ asmlinkage long sys32_creat(const char *
 }
 
 
-extern asmlinkage long sys_waitpid(pid_t pid, unsigned int * stat_addr, int options);
-
 /* Note: it is necessary to treat pid and options as unsigned ints,
  * with the corresponding cast to a signed int to insure that the 
  * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode)
@@ -2349,8 +2320,6 @@ asmlinkage long sys32_waitpid(u32 pid, u
 }
 
 
-extern asmlinkage long sys_getgroups(int gidsetsize, gid_t *grouplist);
-
 /* Note: it is necessary to treat gidsetsize as an unsigned int,
  * with the corresponding cast to a signed int to insure that the 
  * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode)
@@ -2362,8 +2331,6 @@ asmlinkage long sys32_getgroups(u32 gids
 }
 
 
-extern asmlinkage long sys_getpgid(pid_t pid);
-
 /* Note: it is necessary to treat pid as an unsigned int,
  * with the corresponding cast to a signed int to insure that the 
  * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode)
@@ -2375,8 +2342,6 @@ asmlinkage long sys32_getpgid(u32 pid)
 }
 
 
-extern asmlinkage long sys_getpriority(int which, int who);
-
 /* Note: it is necessary to treat which and who as unsigned ints,
  * with the corresponding cast to a signed int to insure that the 
  * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode)
@@ -2388,8 +2353,6 @@ asmlinkage long sys32_getpriority(u32 wh
 }
 
 
-extern asmlinkage long sys_getsid(pid_t pid);
-
 /* Note: it is necessary to treat pid as an unsigned int,
  * with the corresponding cast to a signed int to insure that the 
  * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode)
@@ -2400,7 +2363,6 @@ asmlinkage long sys32_getsid(u32 pid)
 	return sys_getsid((int)pid);
 }
 
-extern asmlinkage long sys_kill(int pid, int sig);
 
 /* Note: it is necessary to treat pid and sig as unsigned ints,
  * with the corresponding cast to a signed int to insure that the 
@@ -2413,8 +2375,6 @@ asmlinkage long sys32_kill(u32 pid, u32 
 }
 
 
-extern asmlinkage long sys_mkdir(const char * pathname, int mode);
-
 /* Note: it is necessary to treat mode as an unsigned int,
  * with the corresponding cast to a signed int to insure that the 
  * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode)
@@ -2425,16 +2385,12 @@ asmlinkage long sys32_mkdir(const char *
 	return sys_mkdir(pathname, (int)mode);
 }
 
-extern asmlinkage long sys_nice(int increment);
-
 long sys32_nice(u32 increment)
 {
 	/* sign extend increment */
 	return sys_nice((int)increment);
 }
 
-extern off_t sys_lseek(unsigned int fd, off_t offset, unsigned int origin);
-
 off_t ppc32_lseek(unsigned int fd, u32 offset, unsigned int origin)
 {
 	/* sign extend n */
@@ -2472,8 +2428,6 @@ out_error:
 	goto out;
 }
 
-extern asmlinkage long sys_readlink(const char * path, char * buf, int bufsiz);
-
 /* Note: it is necessary to treat bufsiz as an unsigned int,
  * with the corresponding cast to a signed int to insure that the 
  * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode)
@@ -2484,8 +2438,6 @@ asmlinkage long sys32_readlink(const cha
 	return sys_readlink(path, buf, (int)bufsiz);
 }
 
-extern asmlinkage long sys_sched_get_priority_max(int policy);
-
 /* Note: it is necessary to treat option as an unsigned int,
  * with the corresponding cast to a signed int to insure that the 
  * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode)
@@ -2497,8 +2449,6 @@ asmlinkage long sys32_sched_get_priority
 }
 
 
-extern asmlinkage long sys_sched_get_priority_min(int policy);
-
 /* Note: it is necessary to treat policy as an unsigned int,
  * with the corresponding cast to a signed int to insure that the 
  * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode)
@@ -2510,8 +2460,6 @@ asmlinkage long sys32_sched_get_priority
 }
 
 
-extern asmlinkage long sys_sched_getparam(pid_t pid, struct sched_param *param);
-
 /* Note: it is necessary to treat pid as an unsigned int,
  * with the corresponding cast to a signed int to insure that the 
  * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode)
@@ -2523,8 +2471,6 @@ asmlinkage long sys32_sched_getparam(u32
 }
 
 
-extern asmlinkage long sys_sched_getscheduler(pid_t pid);
-
 /* Note: it is necessary to treat pid as an unsigned int,
  * with the corresponding cast to a signed int to insure that the 
  * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode)
@@ -2536,8 +2482,6 @@ asmlinkage long sys32_sched_getscheduler
 }
 
 
-extern asmlinkage long sys_sched_setparam(pid_t pid, struct sched_param *param);
-
 /* Note: it is necessary to treat pid as an unsigned int,
  * with the corresponding cast to a signed int to insure that the 
  * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode)
@@ -2549,8 +2493,6 @@ asmlinkage long sys32_sched_setparam(u32
 }
 
 
-extern asmlinkage long sys_sched_setscheduler(pid_t pid, int policy, struct sched_param *param);
-
 /* Note: it is necessary to treat pid and policy as unsigned ints,
  * with the corresponding cast to a signed int to insure that the 
  * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode)
@@ -2562,8 +2504,6 @@ asmlinkage long sys32_sched_setscheduler
 }
 
 
-extern asmlinkage long sys_setdomainname(char *name, int len);
-
 /* Note: it is necessary to treat len as an unsigned int,
  * with the corresponding cast to a signed int to insure that the 
  * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode)
@@ -2575,8 +2515,6 @@ asmlinkage long sys32_setdomainname(char
 }
 
 
-extern asmlinkage long sys_setgroups(int gidsetsize, gid_t *grouplist);
-
 /* Note: it is necessary to treat gidsetsize as an unsigned int,
  * with the corresponding cast to a signed int to insure that the 
  * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode)
@@ -2588,8 +2526,6 @@ asmlinkage long sys32_setgroups(u32 gids
 }
 
 
-extern asmlinkage long sys_sethostname(char *name, int len);
-
 asmlinkage long sys32_sethostname(char *name, u32 len)
 {
 	/* sign extend len */
@@ -2597,8 +2533,6 @@ asmlinkage long sys32_sethostname(char *
 }
 
 
-extern asmlinkage long sys_setpgid(pid_t pid, pid_t pgid);
-
 /* Note: it is necessary to treat pid and pgid as unsigned ints,
  * with the corresponding cast to a signed int to insure that the 
  * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode)
@@ -2610,16 +2544,12 @@ asmlinkage long sys32_setpgid(u32 pid, u
 }
 
 
-extern asmlinkage long sys_setpriority(int which, int who, int niceval);
-
 long sys32_setpriority(u32 which, u32 who, u32 niceval)
 {
 	/* sign extend which, who and niceval */
 	return sys_setpriority((int)which, (int)who, (int)niceval);
 }
 
-extern asmlinkage long sys_ssetmask(int newmask);
-
 /* Note: it is necessary to treat newmask as an unsigned int,
  * with the corresponding cast to a signed int to insure that the 
  * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode)
@@ -2630,8 +2560,6 @@ asmlinkage long sys32_ssetmask(u32 newma
 	return sys_ssetmask((int) newmask);
 }
 
-extern asmlinkage long sys_syslog(int type, char * buf, int len);
-
 long sys32_syslog(u32 type, char * buf, u32 len)
 {
 	/* sign extend len */
@@ -2639,8 +2567,6 @@ long sys32_syslog(u32 type, char * buf, 
 }
 
 
-extern asmlinkage long sys_umask(int mask);
-
 /* Note: it is necessary to treat mask as an unsigned int,
  * with the corresponding cast to a signed int to insure that the 
  * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode)
@@ -2652,8 +2578,6 @@ asmlinkage long sys32_umask(u32 mask)
 }
 
 
-extern asmlinkage long sys_umount(char * name, int flags);
-
 /* Note: it is necessary to treat flags as an unsigned int,
  * with the corresponding cast to a signed int to insure that the 
  * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode)
@@ -2756,10 +2680,6 @@ int sys32_olduname(struct oldold_utsname
 	return error;
 }
 
-extern unsigned long sys_mmap(unsigned long addr, size_t len,
-			      unsigned long prot, unsigned long flags,
-			      unsigned long fd, off_t offset);
-
 unsigned long sys32_mmap2(unsigned long addr, size_t len,
 			  unsigned long prot, unsigned long flags,
 			  unsigned long fd, unsigned long pgoff)
@@ -2801,8 +2721,6 @@ long sys32_utimes(char *filename, struct
 	return ret;
 }
 
-extern long sys_tgkill(int tgid, int pid, int sig);
-
 long sys32_tgkill(u32 tgid, u32 pid, int sig)
 {
 	/* sign extend tgid, pid */
@@ -2813,11 +2731,6 @@ long sys32_tgkill(u32 tgid, u32 pid, int
  * long long munging:
  * The 32 bit ABI passes long longs in an odd even register pair.
  */
-extern ssize_t sys_pread64(unsigned int fd, char *buf, size_t count,
-			   loff_t pos);
-
-extern ssize_t sys_pwrite64(unsigned int fd, const char *buf, size_t count,
-			    loff_t pos);
 
 compat_ssize_t sys32_pread64(unsigned int fd, char *ubuf, compat_size_t count,
 			     u32 reg6, u32 poshi, u32 poslo)
@@ -2831,16 +2744,11 @@ compat_ssize_t sys32_pwrite64(unsigned i
 	return sys_pwrite64(fd, ubuf, count, ((loff_t)poshi << 32) | poslo);
 }
 
-extern ssize_t sys_readahead(int fd, loff_t offset, size_t count);
-
 compat_ssize_t sys32_readahead(int fd, u32 r4, u32 offhi, u32 offlo, u32 count)
 {
 	return sys_readahead(fd, ((loff_t)offhi << 32) | offlo, count);
 }
 
-extern asmlinkage long sys_truncate(const char * path, unsigned long length);
-extern asmlinkage long sys_ftruncate(unsigned int fd, unsigned long length);
-
 asmlinkage int sys32_truncate64(const char * path, u32 reg4,
 				unsigned long high, unsigned long low)
 {
@@ -2853,8 +2761,6 @@ asmlinkage int sys32_ftruncate64(unsigne
 	return sys_ftruncate(fd, (high << 32) | low);
 }
 
-extern long sys_lookup_dcookie(u64 cookie64, char *buf, size_t len);
-
 long ppc32_lookup_dcookie(u32 cookie_high, u32 cookie_low, char *buf,
 			  size_t len)
 {
@@ -2862,8 +2768,6 @@ long ppc32_lookup_dcookie(u32 cookie_hig
 				  buf, len);
 }
 
-extern int sys_fadvise64(int fd, loff_t offset, size_t len, int advice);
-
 long ppc32_fadvise64(int fd, u32 unused, u32 offset_high, u32 offset_low,
 		     size_t len, int advice)
 {
--- diff/arch/ppc64/kernel/syscalls.c	2004-02-09 10:36:09.000000000 +0000
+++ source/arch/ppc64/kernel/syscalls.c	2004-02-23 13:56:39.000000000 +0000
@@ -22,6 +22,7 @@
 
 #include <linux/errno.h>
 #include <linux/sched.h>
+#include <linux/syscalls.h>
 #include <linux/mm.h>
 #include <linux/smp.h>
 #include <linux/smp_lock.h>
--- diff/arch/ppc64/kernel/time.c	2004-02-18 08:54:08.000000000 +0000
+++ source/arch/ppc64/kernel/time.c	2004-02-23 13:56:39.000000000 +0000
@@ -418,6 +418,7 @@ int do_settimeofday(struct timespec *tv)
 	}
 
 	write_sequnlock_irqrestore(&xtime_lock, flags);
+	clock_was_set();
 	return 0;
 }
 
--- diff/arch/ppc64/kernel/traps.c	2004-02-18 08:54:08.000000000 +0000
+++ source/arch/ppc64/kernel/traps.c	2004-02-23 13:56:39.000000000 +0000
@@ -70,11 +70,30 @@ static spinlock_t die_lock = SPIN_LOCK_U
 void die(const char *str, struct pt_regs *regs, long err)
 {
 	static int die_counter;
+	int nl = 0;
 
 	console_verbose();
 	spin_lock_irq(&die_lock);
 	bust_spinlocks(1);
 	printk("Oops: %s, sig: %ld [#%d]\n", str, err, ++die_counter);
+#ifdef CONFIG_PREEMPT
+	printk("PREEMPT ");
+	nl = 1;
+#endif
+#ifdef CONFIG_SMP
+	printk("SMP NR_CPUS=%d ", NR_CPUS);
+	nl = 1;
+#endif
+#ifdef CONFIG_DEBUG_PAGEALLOC
+	printk("DEBUG_PAGEALLOC ");
+	nl = 1;
+#endif
+#ifdef CONFIG_NUMA
+	printk("NUMA ");
+	nl = 1;
+#endif
+	if (nl)
+		printk("\n");
 	show_regs(regs);
 	bust_spinlocks(0);
 	spin_unlock_irq(&die_lock);
@@ -97,7 +116,7 @@ _exception(int signr, siginfo_t *info, s
 	if (!user_mode(regs)) {
 		if (debugger(regs))
 			return;
-		die("Exception in kernel mode\n", regs, signr);
+		die("Exception in kernel mode", regs, signr);
 	}
 
 	force_sig_info(signr, info, current);
--- diff/arch/ppc64/kernel/xics.c	2004-02-18 08:54:08.000000000 +0000
+++ source/arch/ppc64/kernel/xics.c	2004-02-23 13:56:39.000000000 +0000
@@ -475,9 +475,7 @@ nextnode:
 
 	if (systemcfg->platform == PLATFORM_PSERIES) {
 #ifdef CONFIG_SMP
-		for (i = 0; i < NR_CPUS; ++i) {
-			if (!cpu_possible(i))
-				continue;
+		for_each_cpu(i) {
 			xics_per_cpu[i] = __ioremap((ulong)inodes[get_hard_smp_processor_id(i)].addr, 
 						    (ulong)inodes[get_hard_smp_processor_id(i)].size,
 						    _PAGE_NO_CACHE);
--- diff/arch/ppc64/mm/init.c	2004-02-18 08:54:08.000000000 +0000
+++ source/arch/ppc64/mm/init.c	2004-02-23 13:56:39.000000000 +0000
@@ -699,10 +699,6 @@ void __init do_init_bootmem(void)
 	/* add all physical memory to the bootmem map */
 	for (i=0; i < lmb.memory.cnt; i++) {
 		unsigned long physbase, size;
-		unsigned long type = lmb.memory.region[i].type;
-
-		if ( type != LMB_MEMORY_AREA )
-			continue;
 
 		physbase = lmb.memory.region[i].physbase;
 		size = lmb.memory.region[i].size;
@@ -743,12 +739,8 @@ static int __init setup_kcore(void)
 
 	for (i=0; i < lmb.memory.cnt; i++) {
 		unsigned long physbase, size;
-		unsigned long type = lmb.memory.region[i].type;
 		struct kcore_list *kcore_mem;
 
-		if (type != LMB_MEMORY_AREA)
-			continue;
-
 		physbase = lmb.memory.region[i].physbase;
 		size = lmb.memory.region[i].size;
 
--- diff/arch/ppc64/mm/numa.c	2004-02-18 08:54:08.000000000 +0000
+++ source/arch/ppc64/mm/numa.c	2004-02-23 13:56:39.000000000 +0000
@@ -100,6 +100,8 @@ static int __init parse_numa_properties(
 		if (numa_domain >= MAX_NUMNODES)
 			BUG();
 
+		node_set_online(numa_domain);
+
 		if (max_domain < numa_domain)
 			max_domain = numa_domain;
 
@@ -201,13 +203,15 @@ err:
 	return -1;
 }
 
-void setup_nonnuma(void)
+static void __init setup_nonnuma(void)
 {
 	unsigned long i;
 
 	for (i = 0; i < NR_CPUS; i++)
 		map_cpu_to_node(i, 0);
 
+	node_set_online(0);
+
 	node_data[0].node_start_pfn = 0;
 	node_data[0].node_spanned_pages = lmb_end_of_DRAM() / PAGE_SIZE;
 
@@ -257,10 +261,6 @@ void __init do_init_bootmem(void)
 
 		for (i = 0; i < lmb.memory.cnt; i++) {
 			unsigned long physbase, size;
-			unsigned long type = lmb.memory.region[i].type;
-
-			if (type != LMB_MEMORY_AREA)
-				continue;
 
 			physbase = lmb.memory.region[i].physbase;
 			size = lmb.memory.region[i].size;
--- diff/arch/s390/Kconfig	2004-02-09 10:36:09.000000000 +0000
+++ source/arch/s390/Kconfig	2004-02-23 13:56:39.000000000 +0000
@@ -143,6 +143,11 @@ config COMPAT
 	depends on S390_SUPPORT
 	default y
 
+config SYSVIPC_COMPAT
+	bool
+	depends on COMPAT && SYSVIPC
+	default y
+
 config BINFMT_ELF32
 	tristate "Kernel support for 31 bit ELF binaries"
 	depends on S390_SUPPORT
@@ -250,6 +255,98 @@ config SHARED_KERNEL
 	  You should only select this option if you know what you are
 	  doing and want to exploit this feature.
 
+config CMM
+	tristate "Cooperative memory management"
+	help
+	  Select this option, if you want to enable the kernel interface
+	  to reduce the memory size of the system. This is accomplished
+	  by allocating pages of memory and put them "on hold". This only
+	  makes sense for a system running under VM where the unused pages
+	  will be reused by VM for other guest systems. The interface
+	  allows an external monitor to balance memory of many systems.
+	  Everybody who wants to run Linux under VM should select this
+	  option.
+
+config CMM_PROC
+	bool "/proc interface to cooperative memory management"
+	depends on CMM
+	help
+	  Select this option to enable the /proc interface to the
+	  cooperative memory management.
+
+config CMM_IUCV
+	bool "IUCV special message interface to cooperative memory management"
+	depends on CMM && (SMSGIUCV=y || CMM=SMSGIUCV)
+	help
+	  Select this option to enable the special message interface to
+	  the cooperative memory management.
+
+config VIRT_TIMER
+	bool "Virtual CPU timer support"
+	help
+	  This provides a kernel interface for virtual CPU timers.
+	  Default is disabled.
+
+config APPLDATA_BASE
+	bool "Linux - VM Monitor Stream, base infrastructure"
+	depends on PROC_FS && VIRT_TIMER=y
+	help
+	  This provides a kernel interface for creating and updating z/VM APPLDATA
+	  monitor records. The monitor records are updated at certain time
+	  intervals, once the timer is started.
+	  Writing 1 or 0 to /proc/appldata/timer starts(1) or stops(0) the timer,
+	  i.e. enables or disables monitoring on the Linux side.
+	  A custom interval value (in seconds) can be written to
+	  /proc/appldata/interval.
+
+	  Defaults are 60 seconds interval and timer off.
+	  The /proc entries can also be read from, showing the current settings.
+
+config APPLDATA_MEM
+	tristate "Monitor memory management statistics"
+	depends on APPLDATA_BASE
+	help
+	  This provides memory management related data to the Linux - VM Monitor
+	  Stream, like paging/swapping rate, memory utilisation, etc.
+	  Writing 1 or 0 to /proc/appldata/memory creates(1) or removes(0) a z/VM
+	  APPLDATA monitor record, i.e. enables or disables monitoring this record
+	  on the z/VM side.
+
+	  Default is disabled.
+	  The /proc entry can also be read from, showing the current settings.
+
+	  This can also be compiled as a module, which will be called
+	  appldata_mem.o.
+
+config APPLDATA_OS
+	tristate "Monitor OS statistics"
+	depends on APPLDATA_BASE
+	help
+	  This provides OS related data to the Linux - VM Monitor Stream, like
+	  CPU utilisation, etc.
+	  Writing 1 or 0 to /proc/appldata/os creates(1) or removes(0) a z/VM
+	  APPLDATA monitor record, i.e. enables or disables monitoring this record
+	  on the z/VM side.
+
+	  Default is disabled.
+	  This can also be compiled as a module, which will be called
+	  appldata_os.o.
+
+config APPLDATA_NET_SUM
+	tristate "Monitor overall network statistics"
+	depends on APPLDATA_BASE
+	help
+	  This provides network related data to the Linux - VM Monitor Stream,
+	  currently there is only a total sum of network I/O statistics, no
+	  per-interface data.
+	  Writing 1 or 0 to /proc/appldata/net_sum creates(1) or removes(0) a z/VM
+	  APPLDATA monitor record, i.e. enables or disables monitoring this record
+	  on the z/VM side.
+
+	  Default is disabled.
+	  This can also be compiled as a module, which will be called
+	  appldata_net_sum.o.
+
 endmenu
 
 config PCMCIA
--- diff/arch/s390/Makefile	2004-02-09 10:36:09.000000000 +0000
+++ source/arch/s390/Makefile	2004-02-23 13:56:39.000000000 +0000
@@ -35,6 +35,7 @@ cflags-$(CONFIG_MARCH_Z990) += $(call ch
 CFLAGS		+= $(cflags-y)
 CFLAGS		+= $(call check_gcc,-finline-limit=10000,)
 CFLAGS 		+= -pipe -fno-strength-reduce -Wno-sign-compare 
+CFLAGS		+= -mbackchain
 
 OBJCOPYFLAGS	:= -O binary
 LDFLAGS_vmlinux := -e start
@@ -43,7 +44,8 @@ head-$(CONFIG_ARCH_S390_31)	+= arch/$(AR
 head-$(CONFIG_ARCH_S390X)	+= arch/$(ARCH)/kernel/head64.o
 head-y				+= arch/$(ARCH)/kernel/init_task.o
 
-core-y		+= arch/$(ARCH)/mm/ arch/$(ARCH)/kernel/
+core-y		+= arch/$(ARCH)/mm/ arch/$(ARCH)/kernel/ \
+		   arch/$(ARCH)/appldata/
 libs-y		+= arch/$(ARCH)/lib/
 drivers-y	+= drivers/s390/
 drivers-$(CONFIG_MATHEMU) += arch/$(ARCH)/math-emu/
--- diff/arch/s390/defconfig	2004-02-09 10:36:09.000000000 +0000
+++ source/arch/s390/defconfig	2004-02-23 13:56:39.000000000 +0000
@@ -76,6 +76,8 @@ CONFIG_BINFMT_MISC=m
 # CONFIG_PROCESS_DEBUG is not set
 CONFIG_PFAULT=y
 # CONFIG_SHARED_KERNEL is not set
+# CONFIG_CMM is not set
+# CONFIG_VIRT_TIMER is not set
 # CONFIG_PCMCIA is not set
 
 #
@@ -132,11 +134,13 @@ CONFIG_BLK_DEV_INITRD=y
 # S/390 block device drivers
 #
 CONFIG_BLK_DEV_XPRAM=m
+# CONFIG_DCSSBLK is not set
 CONFIG_DASD=y
 # CONFIG_DASD_PROFILE is not set
 CONFIG_DASD_ECKD=y
 CONFIG_DASD_FBA=y
 CONFIG_DASD_DIAG=y
+# CONFIG_DASD_CMB is not set
 
 #
 # Multi-device support (RAID and LVM)
@@ -311,6 +315,8 @@ CONFIG_NET_ETHERNET=y
 CONFIG_LCS=m
 CONFIG_CTC=m
 CONFIG_IUCV=m
+# CONFIG_NETIUCV is not set
+# CONFIG_SMSGIUCV is not set
 CONFIG_QETH=y
 
 #
--- diff/arch/s390/kernel/compat_linux.c	2004-02-09 10:36:09.000000000 +0000
+++ source/arch/s390/kernel/compat_linux.c	2004-02-23 13:56:39.000000000 +0000
@@ -55,6 +55,7 @@
 #include <linux/ipv6.h>
 #include <linux/in.h>
 #include <linux/icmpv6.h>
+#include <linux/syscalls.h>
 #include <linux/sysctl.h>
 #include <linux/binfmts.h>
 #include <linux/compat.h>
@@ -71,17 +72,6 @@
 
 #include "compat_linux.h"
 
-extern asmlinkage long sys_chown(const char *, uid_t,gid_t);
-extern asmlinkage long sys_lchown(const char *, uid_t,gid_t);
-extern asmlinkage long sys_fchown(unsigned int, uid_t,gid_t);
-extern asmlinkage long sys_setregid(gid_t, gid_t);
-extern asmlinkage long sys_setgid(gid_t);
-extern asmlinkage long sys_setreuid(uid_t, uid_t);
-extern asmlinkage long sys_setuid(uid_t);
-extern asmlinkage long sys_setresuid(uid_t, uid_t, uid_t);
-extern asmlinkage long sys_setresgid(gid_t, gid_t, gid_t);
-extern asmlinkage long sys_setfsuid(uid_t);
-extern asmlinkage long sys_setfsgid(gid_t);
  
 /* For this source file, we want overflow handling. */
 
@@ -190,40 +180,81 @@ asmlinkage long sys32_setfsgid16(u16 gid
 	return sys_setfsgid((gid_t)gid);
 }
 
+static int groups16_to_user(u16 *grouplist, struct group_info *group_info)
+{
+	int i;
+	u16 group;
+
+	for (i = 0; i < group_info->ngroups; i++) {
+		group = (u16)GROUP_AT(group_info, i);
+		if (put_user(group, grouplist+i))
+			return -EFAULT;
+	}
+
+	return 0;
+}
+
+static int groups16_from_user(struct group_info *group_info, u16 *grouplist)
+{
+	int i;
+	u16 group;
+
+	for (i = 0; i < group_info->ngroups; i++) {
+		if (get_user(group, grouplist+i))
+			return  -EFAULT;
+		GROUP_AT(group_info, i) = (gid_t)group;
+	}
+
+	return 0;
+}
+
 asmlinkage long sys32_getgroups16(int gidsetsize, u16 *grouplist)
 {
-	u16 groups[NGROUPS];
-	int i,j;
+	int i;
 
 	if (gidsetsize < 0)
 		return -EINVAL;
-	i = current->ngroups;
+
+	get_group_info(current->group_info);
+	i = current->group_info->ngroups;
 	if (gidsetsize) {
-		if (i > gidsetsize)
-			return -EINVAL;
-		for(j=0;j<i;j++)
-			groups[j] = current->groups[j];
-		if (copy_to_user(grouplist, groups, sizeof(u16)*i))
-			return -EFAULT;
+		if (i > gidsetsize) {
+			i = -EINVAL;
+			goto out;
+		}
+		if (groups16_to_user(grouplist, current->group_info)) {
+			i = -EFAULT;
+			goto out;
+		}
 	}
+out:
+	put_group_info(current->group_info);
 	return i;
 }
 
 asmlinkage long sys32_setgroups16(int gidsetsize, u16 *grouplist)
 {
-	u16 groups[NGROUPS];
-	int i;
+	struct group_info *group_info;
+	int retval;
 
 	if (!capable(CAP_SETGID))
 		return -EPERM;
-	if ((unsigned) gidsetsize > NGROUPS)
+	if ((unsigned)gidsetsize > NGROUPS_MAX)
 		return -EINVAL;
-	if (copy_from_user(groups, grouplist, gidsetsize * sizeof(u16)))
-		return -EFAULT;
-	for (i = 0 ; i < gidsetsize ; i++)
-		current->groups[i] = (gid_t)groups[i];
-	current->ngroups = gidsetsize;
-	return 0;
+
+	group_info = groups_alloc(gidsetsize);
+	if (!group_info)
+		return -ENOMEM;
+	retval = groups16_from_user(group_info, grouplist);
+	if (retval) {
+		put_group_info(group_info);
+		return retval;
+	}
+
+	retval = set_current_groups(group_info);
+	put_group_info(group_info);
+
+	return retval;
 }
 
 asmlinkage long sys32_getuid16(void)
@@ -262,541 +293,6 @@ static inline long put_tv32(struct compa
 		 __put_user(i->tv_usec, &o->tv_usec)));
 }
 
-struct msgbuf32 { s32 mtype; char mtext[1]; };
-
-struct ipc64_perm_ds32
-{
-        __kernel_key_t          key;
-        __kernel_uid32_t        uid;
-        __kernel_gid32_t        gid;
-        __kernel_uid32_t        cuid;
-        __kernel_gid32_t        cgid;
-        compat_mode_t       mode;
-        unsigned short          __pad1;
-        unsigned short          seq;
-        unsigned short          __pad2;
-        unsigned int            __unused1;
-        unsigned int            __unused2;
-};
-
-struct ipc_perm32
-{
-	key_t    	  key;
-        compat_uid_t  uid;
-        compat_gid_t  gid;
-        compat_uid_t  cuid;
-        compat_gid_t  cgid;
-        compat_mode_t mode;
-        unsigned short  seq;
-};
-
-struct semid_ds32 {
-        struct ipc_perm32 sem_perm;               /* permissions .. see ipc.h */
-        compat_time_t   sem_otime;              /* last semop time */
-        compat_time_t   sem_ctime;              /* last change time */
-        u32 sem_base;              /* ptr to first semaphore in array */
-        u32 sem_pending;          /* pending operations to be processed */
-        u32 sem_pending_last;    /* last pending operation */
-        u32 undo;                  /* undo requests on this array */
-        unsigned short  sem_nsems;              /* no. of semaphores in array */
-};
-
-struct semid64_ds32 {
-	struct ipc64_perm_ds32 sem_perm;
-	unsigned int	  __pad1;
-	compat_time_t   sem_otime;
-	unsigned int	  __pad2;
-	compat_time_t   sem_ctime;
-	u32 sem_nsems;
-	u32 __unused1;
-	u32 __unused2;
-};
-
-struct msqid_ds32
-{
-        struct ipc_perm32 msg_perm;
-        u32 msg_first;
-        u32 msg_last;
-        compat_time_t   msg_stime;
-        compat_time_t   msg_rtime;
-        compat_time_t   msg_ctime;
-        u32 wwait;
-        u32 rwait;
-        unsigned short msg_cbytes;
-        unsigned short msg_qnum;  
-        unsigned short msg_qbytes;
-        compat_ipc_pid_t msg_lspid;
-        compat_ipc_pid_t msg_lrpid;
-};
-
-struct msqid64_ds32 {
-	struct ipc64_perm_ds32 msg_perm;
-	unsigned int   __pad1;
-	compat_time_t msg_stime;
-	unsigned int   __pad2;
-	compat_time_t msg_rtime;
-	unsigned int   __pad3;
-	compat_time_t msg_ctime;
-	unsigned int  msg_cbytes;
-	unsigned int  msg_qnum;
-	unsigned int  msg_qbytes;
-	compat_pid_t msg_lspid;
-	compat_pid_t msg_lrpid;
-	unsigned int  __unused1;
-	unsigned int  __unused2;
-};
-
-
-struct shmid_ds32 {
-	struct ipc_perm32       shm_perm;
-	int                     shm_segsz;
-	compat_time_t         shm_atime;
-	compat_time_t         shm_dtime;
-	compat_time_t         shm_ctime;
-	compat_ipc_pid_t    shm_cpid; 
-	compat_ipc_pid_t    shm_lpid; 
-	unsigned short          shm_nattch;
-};
-
-struct shmid64_ds32 {
-	struct ipc64_perm_ds32	shm_perm;
-	compat_size_t	shm_segsz;
-	compat_time_t  	shm_atime;
-	unsigned int		__unused1;
-	compat_time_t  	shm_dtime;
-	unsigned int		__unused2;
-	compat_time_t  	shm_ctime;
-	unsigned int		__unused3;
-	compat_pid_t	shm_cpid;
-	compat_pid_t	shm_lpid;
-	unsigned int		shm_nattch;
-	unsigned int		__unused4;
-	unsigned int		__unused5;
-};
-
-extern int sem_ctls[];
-#define sc_semopm	(sem_ctls[2])
-#define SEMOPM_FAST	64  /* ~ 372 bytes on stack */
-
-static long
-do_sys32_semtimedop (int semid, struct sembuf *tsops, int nsops,
-		     struct compat_timespec *timeout32)
-{
-	struct sembuf *sops, fast_sops[SEMOPM_FAST];
-	struct timespec t;
-	mm_segment_t oldfs;
-	long ret;
-
-	/* parameter checking precedence should mirror sys_semtimedop() */
-	if (nsops < 1 || semid < 0)
-		return -EINVAL;
-	if (nsops > sc_semopm)
-		return -E2BIG;
-	if (nsops <= SEMOPM_FAST)
-		sops = fast_sops;
-	else {
-		sops = kmalloc(nsops * sizeof(*sops), GFP_KERNEL);
-		if (sops == NULL)
-			return -ENOMEM;
-	}
-	if (copy_from_user(sops, tsops, nsops * sizeof(*tsops)) ||
-	    get_compat_timespec(&t, timeout32))
-		ret = -EFAULT;
-	else {
-		oldfs = get_fs();
-		set_fs(KERNEL_DS);
-		ret = sys_semtimedop(semid, sops, nsops, &t);
-		set_fs(oldfs);
-	}
-	if (sops != fast_sops)
-		kfree(sops);
-	return ret;
-}
-
-#define IPCOP_MASK(__x)	(1UL << (__x))
-static int do_sys32_semctl(int first, int second, int third, void *uptr)
-{
-	union semun fourth;
-	u32 pad;
-	int err = -EINVAL;
-
-	if (!uptr)
-		goto out;
-	err = -EFAULT;
-	if (get_user (pad, (u32 *)uptr))
-		goto out;
-	if(third == SETVAL)
-		fourth.val = (int)pad;
-	else
-		fourth.__pad = (void *)A(pad);
-	if (IPCOP_MASK (third) &
-	    (IPCOP_MASK (IPC_INFO) | IPCOP_MASK (SEM_INFO) | IPCOP_MASK (GETVAL) |
-	     IPCOP_MASK (GETPID) | IPCOP_MASK (GETNCNT) | IPCOP_MASK (GETZCNT) |
-	     IPCOP_MASK (GETALL) | IPCOP_MASK (SETALL) | IPCOP_MASK (IPC_RMID))) {
-		err = sys_semctl (first, second, third, fourth);
-	} else if (third & IPC_64) {
-		struct semid64_ds s;
-		struct semid64_ds32 *usp = (struct semid64_ds32 *)A(pad);
-		mm_segment_t old_fs;
-		int need_back_translation;
-
-		if (third == (IPC_SET|IPC_64)) {
-			err = get_user (s.sem_perm.uid, &usp->sem_perm.uid);
-			err |= __get_user (s.sem_perm.gid, &usp->sem_perm.gid);
-			err |= __get_user (s.sem_perm.mode, &usp->sem_perm.mode);
-			if (err)
-				goto out;
-			fourth.__pad = &s;
-		}
-		need_back_translation =
-			(IPCOP_MASK (third) &
-			 (IPCOP_MASK (SEM_STAT) | IPCOP_MASK (IPC_STAT))) != 0;
-		if (need_back_translation)
-			fourth.__pad = &s;
-		old_fs = get_fs ();
-		set_fs (KERNEL_DS);
-		err = sys_semctl (first, second, third, fourth);
-		set_fs (old_fs);
-		if (need_back_translation) {
-			int err2 = put_user (s.sem_perm.key, &usp->sem_perm.key);
-			err2 |= __put_user (high2lowuid(s.sem_perm.uid), &usp->sem_perm.uid);
-			err2 |= __put_user (high2lowgid(s.sem_perm.gid), &usp->sem_perm.gid);
-			err2 |= __put_user (high2lowuid(s.sem_perm.cuid), &usp->sem_perm.cuid);
-			err2 |= __put_user (high2lowgid(s.sem_perm.cgid), &usp->sem_perm.cgid);
-			err2 |= __put_user (s.sem_perm.mode, &usp->sem_perm.mode);
-			err2 |= __put_user (s.sem_perm.seq, &usp->sem_perm.seq);
-			err2 |= __put_user (s.sem_otime, &usp->sem_otime);
-			err2 |= __put_user (s.sem_ctime, &usp->sem_ctime);
-			err2 |= __put_user (s.sem_nsems, &usp->sem_nsems);
-			if (err2) err = -EFAULT;
-		}
-	} else {
-		struct semid_ds s;
-		struct semid_ds32 *usp = (struct semid_ds32 *)A(pad);
-		mm_segment_t old_fs;
-		int need_back_translation;
-
-		if (third == IPC_SET) {
-			err = get_user (s.sem_perm.uid, &usp->sem_perm.uid);
-			err |= __get_user (s.sem_perm.gid, &usp->sem_perm.gid);
-			err |= __get_user (s.sem_perm.mode, &usp->sem_perm.mode);
-			if (err)
-				goto out;
-			fourth.__pad = &s;
-		}
-		need_back_translation =
-			(IPCOP_MASK (third) &
-			 (IPCOP_MASK (SEM_STAT) | IPCOP_MASK (IPC_STAT))) != 0;
-		if (need_back_translation)
-			fourth.__pad = &s;
-		old_fs = get_fs ();
-		set_fs (KERNEL_DS);
-		err = sys_semctl (first, second, third, fourth);
-		set_fs (old_fs);
-		if (need_back_translation) {
-			int err2 = put_user (s.sem_perm.key, &usp->sem_perm.key);
-			err2 |= __put_user (high2lowuid(s.sem_perm.uid), &usp->sem_perm.uid);
-			err2 |= __put_user (high2lowgid(s.sem_perm.gid), &usp->sem_perm.gid);
-			err2 |= __put_user (high2lowuid(s.sem_perm.cuid), &usp->sem_perm.cuid);
-			err2 |= __put_user (high2lowgid(s.sem_perm.cgid), &usp->sem_perm.cgid);
-			err2 |= __put_user (s.sem_perm.mode, &usp->sem_perm.mode);
-			err2 |= __put_user (s.sem_perm.seq, &usp->sem_perm.seq);
-			err2 |= __put_user (s.sem_otime, &usp->sem_otime);
-			err2 |= __put_user (s.sem_ctime, &usp->sem_ctime);
-			err2 |= __put_user (s.sem_nsems, &usp->sem_nsems);
-			if (err2) err = -EFAULT;
-		}
-	}
-out:
-	return err;
-}
-
-static int do_sys32_msgsnd (int first, int second, int third, void *uptr)
-{
-	struct msgbuf *p = kmalloc (second + sizeof (struct msgbuf), GFP_USER);
-	struct msgbuf32 *up = (struct msgbuf32 *)uptr;
-	mm_segment_t old_fs;
-	int err;
-
-	if (!p)
-		return -ENOMEM;
-
-	err = -EINVAL;
-	if (second > MSGMAX || first < 0 || second < 0)
-		goto out;
-
-	err = -EFAULT;
-	if (!uptr)
-		goto out;
-        if (get_user (p->mtype, &up->mtype) ||
-	    __copy_from_user (p->mtext, &up->mtext, second))
-		goto out;
-	old_fs = get_fs ();
-	set_fs (KERNEL_DS);
-	err = sys_msgsnd (first, p, second, third);
-	set_fs (old_fs);
-out:
-	kfree (p);
-	return err;
-}
-
-static int do_sys32_msgrcv (int first, int second, int msgtyp, int third,
-			    int version, void *uptr)
-{
-	struct msgbuf32 *up;
-	struct msgbuf *p;
-	mm_segment_t old_fs;
-	int err;
-
-	if (first < 0 || second < 0)
-		return -EINVAL;
-
-	if (!version) {
-		struct ipc_kludge_32 *uipck = (struct ipc_kludge_32 *)uptr;
-		struct ipc_kludge_32 ipck;
-
-		err = -EINVAL;
-		if (!uptr)
-			goto out;
-		err = -EFAULT;
-		if (copy_from_user (&ipck, uipck, sizeof (struct ipc_kludge_32)))
-			goto out;
-		uptr = (void *)A(ipck.msgp);
-		msgtyp = ipck.msgtyp;
-	}
-	err = -ENOMEM;
-	p = kmalloc (second + sizeof (struct msgbuf), GFP_USER);
-	if (!p)
-		goto out;
-	old_fs = get_fs ();
-	set_fs (KERNEL_DS);
-	err = sys_msgrcv (first, p, second, msgtyp, third);
-	set_fs (old_fs);
-	if (err < 0)
-		goto free_then_out;
-	up = (struct msgbuf32 *)uptr;
-	if (put_user (p->mtype, &up->mtype) ||
-	    __copy_to_user (&up->mtext, p->mtext, err))
-		err = -EFAULT;
-free_then_out:
-	kfree (p);
-out:
-	return err;
-}
-
-static int do_sys32_msgctl (int first, int second, void *uptr)
-{
-	int err;
-
-	if (IPCOP_MASK (second) &
-	    (IPCOP_MASK (IPC_INFO) | IPCOP_MASK (MSG_INFO) |
-	     IPCOP_MASK (IPC_RMID))) {
-		err = sys_msgctl (first, second, (struct msqid_ds *)uptr);
-	} else if (second & IPC_64) {
-		struct msqid64_ds m;
-		struct msqid64_ds32 *up = (struct msqid64_ds32 *)uptr;
-		mm_segment_t old_fs;
-
-		if (second == (IPC_SET|IPC_64)) {
-			err = get_user (m.msg_perm.uid, &up->msg_perm.uid);
-			err |= __get_user (m.msg_perm.gid, &up->msg_perm.gid);
-			err |= __get_user (m.msg_perm.mode, &up->msg_perm.mode);
-			err |= __get_user (m.msg_qbytes, &up->msg_qbytes);
-			if (err)
-				goto out;
-		}
-		old_fs = get_fs ();
-		set_fs (KERNEL_DS);
-		err = sys_msgctl (first, second, (struct msqid_ds *)&m);
-		set_fs (old_fs);
-		if (IPCOP_MASK (second) &
-		    (IPCOP_MASK (MSG_STAT) | IPCOP_MASK (IPC_STAT))) {
-			int err2 = put_user (m.msg_perm.key, &up->msg_perm.key);
-			err2 |= __put_user (high2lowuid(m.msg_perm.uid), &up->msg_perm.uid);
-			err2 |= __put_user (high2lowgid(m.msg_perm.gid), &up->msg_perm.gid);
-			err2 |= __put_user (high2lowuid(m.msg_perm.cuid), &up->msg_perm.cuid);
-			err2 |= __put_user (high2lowgid(m.msg_perm.cgid), &up->msg_perm.cgid);
-			err2 |= __put_user (m.msg_perm.mode, &up->msg_perm.mode);
-			err2 |= __put_user (m.msg_perm.seq, &up->msg_perm.seq);
-			err2 |= __put_user (m.msg_stime, &up->msg_stime);
-			err2 |= __put_user (m.msg_rtime, &up->msg_rtime);
-			err2 |= __put_user (m.msg_ctime, &up->msg_ctime);
-			err2 |= __put_user (m.msg_cbytes, &up->msg_cbytes);
-			err2 |= __put_user (m.msg_qnum, &up->msg_qnum);
-			err2 |= __put_user (m.msg_qbytes, &up->msg_qbytes);
-			err2 |= __put_user (m.msg_lspid, &up->msg_lspid);
-			err2 |= __put_user (m.msg_lrpid, &up->msg_lrpid);
-			if (err2)
-				err = -EFAULT;
-		}
-	} else {
-		struct msqid_ds m;
-		struct msqid_ds32 *up = (struct msqid_ds32 *)uptr;
-		mm_segment_t old_fs;
-
-		if (second == IPC_SET) {
-			err = get_user (m.msg_perm.uid, &up->msg_perm.uid);
-			err |= __get_user (m.msg_perm.gid, &up->msg_perm.gid);
-			err |= __get_user (m.msg_perm.mode, &up->msg_perm.mode);
-			err |= __get_user (m.msg_qbytes, &up->msg_qbytes);
-			if (err)
-				goto out;
-		}
-		old_fs = get_fs ();
-		set_fs (KERNEL_DS);
-		err = sys_msgctl (first, second, &m);
-		set_fs (old_fs);
-		if (IPCOP_MASK (second) &
-		    (IPCOP_MASK (MSG_STAT) | IPCOP_MASK (IPC_STAT))) {
-			int err2 = put_user (m.msg_perm.key, &up->msg_perm.key);
-			err2 |= __put_user (high2lowuid(m.msg_perm.uid), &up->msg_perm.uid);
-			err2 |= __put_user (high2lowgid(m.msg_perm.gid), &up->msg_perm.gid);
-			err2 |= __put_user (high2lowuid(m.msg_perm.cuid), &up->msg_perm.cuid);
-			err2 |= __put_user (high2lowgid(m.msg_perm.cgid), &up->msg_perm.cgid);
-			err2 |= __put_user (m.msg_perm.mode, &up->msg_perm.mode);
-			err2 |= __put_user (m.msg_perm.seq, &up->msg_perm.seq);
-			err2 |= __put_user (m.msg_stime, &up->msg_stime);
-			err2 |= __put_user (m.msg_rtime, &up->msg_rtime);
-			err2 |= __put_user (m.msg_ctime, &up->msg_ctime);
-			err2 |= __put_user (m.msg_cbytes, &up->msg_cbytes);
-			err2 |= __put_user (m.msg_qnum, &up->msg_qnum);
-			err2 |= __put_user (m.msg_qbytes, &up->msg_qbytes);
-			err2 |= __put_user (m.msg_lspid, &up->msg_lspid);
-			err2 |= __put_user (m.msg_lrpid, &up->msg_lrpid);
-			if (err2)
-				err = -EFAULT;
-		}
-	}
-
-out:
-	return err;
-}
-
-static int do_sys32_shmat (int first, int second, int third, int version, void *uptr)
-{
-	unsigned long raddr;
-	u32 *uaddr = (u32 *)A((u32)third);
-	int err = -EINVAL;
-
-	if (version == 1)
-		goto out;
-	err = sys_shmat (first, uptr, second, &raddr);
-	if (err)
-		goto out;
-	err = put_user (raddr, uaddr);
-out:
-	return err;
-}
-
-static int do_sys32_shmctl (int first, int second, void *uptr)
-{
-	int err;
-
-	if (IPCOP_MASK (second) &
-	    (IPCOP_MASK (IPC_INFO) | IPCOP_MASK (SHM_LOCK) | IPCOP_MASK (SHM_UNLOCK) |
-	     IPCOP_MASK (IPC_RMID))) {
-		if (second == (IPC_INFO|IPC_64))
-			second = IPC_INFO; /* So that we don't have to translate it */
-		err = sys_shmctl (first, second, (struct shmid_ds *)uptr);
-	} else if ((second & IPC_64) && second != (SHM_INFO|IPC_64)) {
-		struct shmid64_ds s;
-		struct shmid64_ds32 *up = (struct shmid64_ds32 *)uptr;
-		mm_segment_t old_fs;
-
-		if (second == (IPC_SET|IPC_64)) {
-			err = get_user (s.shm_perm.uid, &up->shm_perm.uid);
-			err |= __get_user (s.shm_perm.gid, &up->shm_perm.gid);
-			err |= __get_user (s.shm_perm.mode, &up->shm_perm.mode);
-			if (err)
-				goto out;
-		}
-		old_fs = get_fs ();
-		set_fs (KERNEL_DS);
-		err = sys_shmctl (first, second, (struct shmid_ds *)&s);
-		set_fs (old_fs);
-		if (err < 0)
-			goto out;
-
-		/* Mask it even in this case so it becomes a CSE. */
-		if (IPCOP_MASK (second) &
-		    (IPCOP_MASK (SHM_STAT) | IPCOP_MASK (IPC_STAT))) {
-			int err2 = put_user (s.shm_perm.key, &up->shm_perm.key);
-			err2 |= __put_user (high2lowuid(s.shm_perm.uid), &up->shm_perm.uid);
-			err2 |= __put_user (high2lowgid(s.shm_perm.gid), &up->shm_perm.gid);
-			err2 |= __put_user (high2lowuid(s.shm_perm.cuid), &up->shm_perm.cuid);
-			err2 |= __put_user (high2lowgid(s.shm_perm.cgid), &up->shm_perm.cgid);
-			err2 |= __put_user (s.shm_perm.mode, &up->shm_perm.mode);
-			err2 |= __put_user (s.shm_perm.seq, &up->shm_perm.seq);
-			err2 |= __put_user (s.shm_atime, &up->shm_atime);
-			err2 |= __put_user (s.shm_dtime, &up->shm_dtime);
-			err2 |= __put_user (s.shm_ctime, &up->shm_ctime);
-			err2 |= __put_user (s.shm_segsz, &up->shm_segsz);
-			err2 |= __put_user (s.shm_nattch, &up->shm_nattch);
-			err2 |= __put_user (s.shm_cpid, &up->shm_cpid);
-			err2 |= __put_user (s.shm_lpid, &up->shm_lpid);
-			if (err2)
-				err = -EFAULT;
-		}
-	} else {
-		struct shmid_ds s;
-		struct shmid_ds32 *up = (struct shmid_ds32 *)uptr;
-		mm_segment_t old_fs;
-
-		second &= ~IPC_64;
-		if (second == IPC_SET) {
-			err = get_user (s.shm_perm.uid, &up->shm_perm.uid);
-			err |= __get_user (s.shm_perm.gid, &up->shm_perm.gid);
-			err |= __get_user (s.shm_perm.mode, &up->shm_perm.mode);
-			if (err)
-				goto out;
-		}
-		old_fs = get_fs ();
-		set_fs (KERNEL_DS);
-		err = sys_shmctl (first, second, &s);
-		set_fs (old_fs);
-		if (err < 0)
-			goto out;
-
-		/* Mask it even in this case so it becomes a CSE. */
-		if (second == SHM_INFO) {
-			struct shm_info32 {
-				int used_ids;
-				u32 shm_tot, shm_rss, shm_swp;
-				u32 swap_attempts, swap_successes;
-			} *uip = (struct shm_info32 *)uptr;
-			struct shm_info *kp = (struct shm_info *)&s;
-			int err2 = put_user (kp->used_ids, &uip->used_ids);
-			err2 |= __put_user (kp->shm_tot, &uip->shm_tot);
-			err2 |= __put_user (kp->shm_rss, &uip->shm_rss);
-			err2 |= __put_user (kp->shm_swp, &uip->shm_swp);
-			err2 |= __put_user (kp->swap_attempts, &uip->swap_attempts);
-			err2 |= __put_user (kp->swap_successes, &uip->swap_successes);
-			if (err2)
-				err = -EFAULT;
-		} else if (IPCOP_MASK (second) &
-			   (IPCOP_MASK (SHM_STAT) | IPCOP_MASK (IPC_STAT))) {
-			int err2 = put_user (s.shm_perm.key, &up->shm_perm.key);
-			err2 |= __put_user (high2lowuid(s.shm_perm.uid), &up->shm_perm.uid);
-			err2 |= __put_user (high2lowgid(s.shm_perm.gid), &up->shm_perm.gid);
-			err2 |= __put_user (high2lowuid(s.shm_perm.cuid), &up->shm_perm.cuid);
-			err2 |= __put_user (high2lowgid(s.shm_perm.cgid), &up->shm_perm.cgid);
-			err2 |= __put_user (s.shm_perm.mode, &up->shm_perm.mode);
-			err2 |= __put_user (s.shm_perm.seq, &up->shm_perm.seq);
-			err2 |= __put_user (s.shm_atime, &up->shm_atime);
-			err2 |= __put_user (s.shm_dtime, &up->shm_dtime);
-			err2 |= __put_user (s.shm_ctime, &up->shm_ctime);
-			err2 |= __put_user (s.shm_segsz, &up->shm_segsz);
-			err2 |= __put_user (s.shm_nattch, &up->shm_nattch);
-			err2 |= __put_user (s.shm_cpid, &up->shm_cpid);
-			err2 |= __put_user (s.shm_lpid, &up->shm_lpid);
-			if (err2)
-				err = -EFAULT;
-		}
-	}
-out:
-	return err;
-}
-
 /*
  * sys32_ipc() is the de-multiplexer for the SysV IPC calls in 32bit emulation.
  *
@@ -804,89 +300,66 @@ out:
  */
 asmlinkage int sys32_ipc (u32 call, int first, int second, int third, u32 ptr)
 {
-	int version, err;
+	if(call >> 16) /* hack for backward compatibility */
+		return -EINVAL;
 
-	version = call >> 16; /* hack for backward compatibility */
 	call &= 0xffff;
 
-	if(version)
-		return -EINVAL;
-
 	if (call <= SEMTIMEDOP)
 		switch (call) {
 		case SEMTIMEDOP:
-			if (third) {
-				err = do_sys32_semtimedop(first,
-					(struct sembuf *)AA(ptr),
-					second,
-					(struct compat_timespec *)
-						AA((u32)third));
-				goto out;
-			}
+			if (third)
+				return compat_sys_semtimedop(first,
+						compat_ptr(ptr), second,
+						compat_ptr(third));
 			/* else fall through for normal semop() */
 		case SEMOP:
 			/* struct sembuf is the same on 32 and 64bit :)) */
-			err = sys_semtimedop (first, (struct sembuf *)AA(ptr),
+			return sys_semtimedop (first, compat_ptr(ptr),
 					      second, NULL);
-			goto out;
 		case SEMGET:
-			err = sys_semget (first, second, third);
-			goto out;
+			return sys_semget (first, second, third);
 		case SEMCTL:
-			err = do_sys32_semctl (first, second, third, (void *)AA(ptr));
-			goto out;
+			return compat_sys_semctl (first, second, third,
+						 compat_ptr(ptr));
 		default:
-			err = -EINVAL;
-			goto out;
+			return -EINVAL;
 		};
 	if (call <= MSGCTL) 
 		switch (call) {
 		case MSGSND:
-			err = do_sys32_msgsnd (first, second, third, (void *)AA(ptr));
-			goto out;
+			return compat_sys_msgsnd (first, second, third,
+						compat_ptr(ptr));
 		case MSGRCV:
-			err = do_sys32_msgrcv (first, second, 0, third,
-					       version, (void *)AA(ptr));
-			goto out;
+			return compat_sys_msgrcv (first, second, 0, third,
+					       0, compat_ptr(ptr));
 		case MSGGET:
-			err = sys_msgget ((key_t) first, second);
-			goto out;
+			return sys_msgget ((key_t) first, second);
 		case MSGCTL:
-			err = do_sys32_msgctl (first, second, (void *)AA(ptr));
-			goto out;
+			return compat_sys_msgctl (first, second,
+						compat_ptr(ptr));
 		default:
-			err = -EINVAL;
-			goto out;
+			return -EINVAL;
 		}
 	if (call <= SHMCTL) 
 		switch (call) {
 		case SHMAT:
-			err = do_sys32_shmat (first, second, third,
-					      version, (void *)AA(ptr));
-			goto out;
+			return compat_sys_shmat (first, second, third,
+						0, compat_ptr(ptr));
 		case SHMDT: 
-			err = sys_shmdt ((char *)AA(ptr));
-			goto out;
+			return sys_shmdt(compat_ptr(ptr));
 		case SHMGET:
-			err = sys_shmget (first, second, third);
-			goto out;
+			return sys_shmget(first, second, third);
 		case SHMCTL:
-			err = do_sys32_shmctl (first, second, (void *)AA(ptr));
-			goto out;
+			return compat_sys_shmctl(first, second,
+						compat_ptr(ptr));
 		default:
-			err = -EINVAL;
-			goto out;
+			return -EINVAL;
 		}
 
-	err = -EINVAL;
-
-out:
-	return err;
+	return -EINVAL;
 }
 
-extern asmlinkage long sys_truncate(const char * path, unsigned long length);
-extern asmlinkage long sys_ftruncate(unsigned int fd, unsigned long length);
-
 asmlinkage int sys32_truncate64(const char * path, unsigned long high, unsigned long low)
 {
 	if ((int)high < 0)
@@ -1356,8 +829,6 @@ int cp_compat_stat(struct kstat *stat, s
 	return err;
 }
 
-extern asmlinkage int sys_sysfs(int option, unsigned long arg1, unsigned long arg2);
-
 asmlinkage int sys32_sysfs(int option, u32 arg1, u32 arg2)
 {
 	return sys_sysfs(option, arg1, arg2);
@@ -1531,9 +1002,7 @@ struct sysinfo32 {
         char _f[8];
 };
 
-extern asmlinkage int sys_sysinfo(struct sysinfo *info);
-
-asmlinkage int sys32_sysinfo(struct sysinfo32 *info)
+asmlinkage int sys32_sysinfo(struct sysinfo32 __user *info)
 {
 	struct sysinfo s;
 	int ret, err;
@@ -1561,10 +1030,8 @@ asmlinkage int sys32_sysinfo(struct sysi
 	return ret;
 }
 
-extern asmlinkage int sys_sched_rr_get_interval(pid_t pid, struct timespec *interval);
-
 asmlinkage int sys32_sched_rr_get_interval(compat_pid_t pid,
-		struct compat_timespec *interval)
+				struct compat_timespec __user *interval)
 {
 	struct timespec t;
 	int ret;
@@ -1578,9 +1045,8 @@ asmlinkage int sys32_sched_rr_get_interv
 	return ret;
 }
 
-extern asmlinkage int sys_rt_sigprocmask(int how, sigset_t *set, sigset_t *oset, size_t sigsetsize);
-
-asmlinkage int sys32_rt_sigprocmask(int how, compat_sigset_t *set, compat_sigset_t *oset, compat_size_t sigsetsize)
+asmlinkage int sys32_rt_sigprocmask(int how, compat_sigset_t __user *set,
+			compat_sigset_t __user *oset, compat_size_t sigsetsize)
 {
 	sigset_t s;
 	compat_sigset_t s32;
@@ -1614,9 +1080,8 @@ asmlinkage int sys32_rt_sigprocmask(int 
 	return 0;
 }
 
-extern asmlinkage int sys_rt_sigpending(sigset_t *set, size_t sigsetsize);
-
-asmlinkage int sys32_rt_sigpending(compat_sigset_t *set, compat_size_t sigsetsize)
+asmlinkage int sys32_rt_sigpending(compat_sigset_t __user *set,
+				compat_size_t sigsetsize)
 {
 	sigset_t s;
 	compat_sigset_t s32;
@@ -1723,11 +1188,8 @@ sys32_rt_sigtimedwait(compat_sigset_t *u
 	return ret;
 }
 
-extern asmlinkage int
-sys_rt_sigqueueinfo(int pid, int sig, siginfo_t *uinfo);
-
 asmlinkage int
-sys32_rt_sigqueueinfo(int pid, int sig, siginfo_t32 *uinfo)
+sys32_rt_sigqueueinfo(int pid, int sig, siginfo_t32 __user *uinfo)
 {
 	siginfo_t info;
 	int ret;
@@ -1956,40 +1418,30 @@ out:
 
 #ifdef CONFIG_MODULES
 
-extern asmlinkage int sys_init_module(const char *name_user, struct module *mod_user);
-
-/* Hey, when you're trying to init module, take time and prepare us a nice 64bit
- * module structure, even if from 32bit modutils... Why to pollute kernel... :))
- */
-asmlinkage int sys32_init_module(const char *name_user, struct module *mod_user)
+asmlinkage int
+sys32_init_module(void __user *umod, unsigned long len,
+		const char __user *uargs)
 {
-	return sys_init_module(name_user, mod_user);
+	return sys_init_module(umod, len, uargs);
 }
 
-extern asmlinkage int sys_delete_module(const char *name_user);
-
-asmlinkage int sys32_delete_module(const char *name_user)
+asmlinkage int
+sys32_delete_module(const char __user *name_user, unsigned int flags)
 {
-	return sys_delete_module(name_user);
+	return sys_delete_module(name_user, flags);
 }
 
-struct module_info32 {
-	u32 addr;
-	u32 size;
-	u32 flags;
-	s32 usecount;
-};
-
 #else /* CONFIG_MODULES */
 
 asmlinkage int
-sys32_init_module(const char *name_user, struct module *mod_user)
+sys32_init_module(void __user *umod, unsigned long len,
+		const char __user *uargs)
 {
 	return -ENOSYS;
 }
 
 asmlinkage int
-sys32_delete_module(const char *name_user)
+sys32_delete_module(const char __user *name_user, unsigned int flags)
 {
 	return -ENOSYS;
 }
@@ -2153,10 +1605,6 @@ static int nfs_getfh32_res_trans(union n
 	return copy_to_user(res32, kres, sizeof(*res32)) ? -EFAULT : 0;
 }
 
-/*
-asmlinkage long sys_ni_syscall(void); 
-*/
-
 int asmlinkage sys32_nfsservctl(int cmd, struct nfsctl_arg32 *arg32, union nfsctl_res32 *res32)
 {
 	struct nfsctl_arg *karg = NULL;
@@ -2271,9 +1719,8 @@ asmlinkage int sys32_settimeofday(struct
 	return do_sys_settimeofday(tv ? &kts : NULL, tz ? &ktz : NULL);
 }
 
-asmlinkage int sys_utimes(char *, struct timeval *);
-
-asmlinkage int sys32_utimes(char *filename, struct compat_timeval *tvs)
+asmlinkage int sys32_utimes(char __user *filename,
+			struct compat_timeval __user *tvs)
 {
 	char *kfilename;
 	struct timeval ktvs[2];
@@ -2307,8 +1754,6 @@ asmlinkage int sys32_pause(void)
 	return -ERESTARTNOHAND;
 }
 
-extern asmlinkage int sys_prctl(int option, unsigned long arg2, unsigned long arg3,
-				unsigned long arg4, unsigned long arg5);
 
 asmlinkage int sys32_prctl(int option, u32 arg2, u32 arg3, u32 arg4, u32 arg5)
 {
@@ -2320,12 +1765,6 @@ asmlinkage int sys32_prctl(int option, u
 }
 
 
-extern asmlinkage ssize_t sys_pread64(unsigned int fd, char * buf,
-				    size_t count, loff_t pos);
-
-extern asmlinkage ssize_t sys_pwrite64(unsigned int fd, const char * buf,
-				     size_t count, loff_t pos);
-
 asmlinkage compat_ssize_t sys32_pread64(unsigned int fd, char *ubuf,
 				 compat_size_t count, u32 poshi, u32 poslo)
 {
@@ -2342,15 +1781,11 @@ asmlinkage compat_ssize_t sys32_pwrite64
 	return sys_pwrite64(fd, ubuf, count, ((loff_t)AA(poshi) << 32) | AA(poslo));
 }
 
-extern asmlinkage ssize_t sys_readahead(int fd, loff_t offset, size_t count);
-
 asmlinkage compat_ssize_t sys32_readahead(int fd, u32 offhi, u32 offlo, s32 count)
 {
 	return sys_readahead(fd, ((loff_t)AA(offhi) << 32) | AA(offlo), count);
 }
 
-extern asmlinkage ssize_t sys_sendfile(int out_fd, int in_fd, off_t *offset, size_t count);
-
 asmlinkage int sys32_sendfile(int out_fd, int in_fd, compat_off_t *offset, s32 count)
 {
 	mm_segment_t old_fs = get_fs();
@@ -2370,9 +1805,6 @@ asmlinkage int sys32_sendfile(int out_fd
 	return ret;
 }
 
-extern asmlinkage ssize_t sys_sendfile64(int out_fd, int in_fd, 
-					 loff_t *offset, size_t count);
-
 asmlinkage int sys32_sendfile64(int out_fd, int in_fd, 
 				compat_loff_t *offset, s32 count)
 {
@@ -2466,8 +1898,6 @@ asmlinkage int sys32_adjtimex(struct tim
 	return ret;
 }
 
-extern asmlinkage long sys_setpriority(int which, int who, int niceval);
-
 asmlinkage int sys_setpriority32(u32 which, u32 who, u32 niceval)
 {
 	return sys_setpriority((int) which,
@@ -2485,7 +1915,7 @@ struct __sysctl_args32 {
 	u32 __unused[4];
 };
 
-extern asmlinkage long sys32_sysctl(struct __sysctl_args32 *args)
+asmlinkage long sys32_sysctl(struct __sysctl_args32 *args)
 {
 	struct __sysctl_args32 tmp;
 	int error;
@@ -2677,8 +2107,6 @@ out:
 	return error;
 }
 
-asmlinkage ssize_t sys_read(unsigned int fd, char * buf, size_t count);
-
 asmlinkage compat_ssize_t sys32_read(unsigned int fd, char * buf, size_t count)
 {
 	if ((compat_ssize_t) count < 0)
@@ -2687,8 +2115,6 @@ asmlinkage compat_ssize_t sys32_read(uns
 	return sys_read(fd, buf, count);
 }
 
-asmlinkage ssize_t sys_write(unsigned int fd, const char * buf, size_t count);
-
 asmlinkage compat_ssize_t sys32_write(unsigned int fd, char * buf, size_t count)
 {
 	if ((compat_ssize_t) count < 0)
--- diff/arch/s390/kernel/compat_linux.h	2004-02-09 10:36:09.000000000 +0000
+++ source/arch/s390/kernel/compat_linux.h	2004-02-23 13:56:39.000000000 +0000
@@ -4,6 +4,7 @@
 #include <linux/config.h>
 #include <linux/compat.h>
 #include <linux/socket.h>
+#include <linux/syscalls.h>
 #include <linux/nfs_fs.h>
 #include <linux/sunrpc/svc.h>
 #include <linux/nfsd/nfsd.h>
--- diff/arch/s390/kernel/compat_wrapper.S	2004-02-09 10:36:09.000000000 +0000
+++ source/arch/s390/kernel/compat_wrapper.S	2004-02-23 13:56:39.000000000 +0000
@@ -567,13 +567,15 @@ compat_sys_sigprocmask_wrapper:
 
 	.globl  sys32_init_module_wrapper 
 sys32_init_module_wrapper:
-	llgtr	%r2,%r2			# const char *
-	llgtr	%r3,%r3			# struct module *
+	llgtr	%r2,%r2			# void *
+	llgfr	%r3,%r3			# unsigned long
+	llgtr	%r4,%r4			# char *
 	jg	sys32_init_module	# branch to system call
 
 	.globl  sys32_delete_module_wrapper 
 sys32_delete_module_wrapper:
 	llgtr	%r2,%r2			# const char *
+	llgfr	%r3,%r3			# unsigned int
 	jg	sys32_delete_module	# branch to system call
 
 	.globl  sys32_quotactl_wrapper 
--- diff/arch/s390/kernel/process.c	2003-09-30 15:46:12.000000000 +0100
+++ source/arch/s390/kernel/process.c	2004-02-23 13:56:39.000000000 +0000
@@ -40,6 +40,9 @@
 #include <asm/io.h>
 #include <asm/processor.h>
 #include <asm/irq.h>
+#ifdef CONFIG_VIRT_TIMER
+#include <asm/timer.h>
+#endif
 
 asmlinkage void ret_from_fork(void) __asm__("ret_from_fork");
 
@@ -77,6 +80,14 @@ void default_idle(void)
                 return;
         }
 
+#ifdef CONFIG_VIRT_TIMER
+	/*
+	 * hook to stop timers that should not tick while CPU is idle
+	 */
+	if (stop_timers())
+		return;
+#endif
+
 	/* 
 	 * Wait for external, I/O or machine check interrupt and
 	 * switch off machine check bit after the wait has ended.
--- diff/arch/s390/kernel/s390_ext.c	2003-09-30 15:46:12.000000000 +0100
+++ source/arch/s390/kernel/s390_ext.c	2004-02-23 13:56:39.000000000 +0000
@@ -111,6 +111,7 @@ void do_extint(struct pt_regs *regs, uns
         int index;
 
 	irq_enter();
+	asm volatile ("mc 0,0");
 	if (S390_lowcore.int_clock >= S390_lowcore.jiffy_timer)
 		account_ticks(regs);
 	kstat_cpu(smp_processor_id()).irqs[EXTERNAL_INTERRUPT]++;
--- diff/arch/s390/kernel/s390_ksyms.c	2004-02-09 10:36:09.000000000 +0000
+++ source/arch/s390/kernel/s390_ksyms.c	2004-02-23 13:56:39.000000000 +0000
@@ -8,6 +8,7 @@
 #include <linux/module.h>
 #include <linux/mm.h>
 #include <linux/smp.h>
+#include <linux/syscalls.h>
 #include <linux/interrupt.h>
 #include <linux/ioctl32.h>
 #include <asm/checksum.h>
@@ -18,6 +19,9 @@
 #ifdef CONFIG_IP_MULTICAST
 #include <net/arp.h>
 #endif
+#ifdef CONFIG_VIRT_TIMER
+#include <asm/timer.h>
+#endif
 
 /*
  * memory management
@@ -28,6 +32,7 @@ EXPORT_SYMBOL_NOVERS(_zb_findmap);
 EXPORT_SYMBOL_NOVERS(__copy_from_user_asm);
 EXPORT_SYMBOL_NOVERS(__copy_to_user_asm);
 EXPORT_SYMBOL_NOVERS(__clear_user_asm);
+EXPORT_SYMBOL(diag10);
 
 /*
  * semaphore ops
@@ -53,6 +58,7 @@ EXPORT_SYMBOL_NOVERS(strnlen);
 EXPORT_SYMBOL_NOVERS(strrchr);
 EXPORT_SYMBOL_NOVERS(strstr);
 EXPORT_SYMBOL_NOVERS(strpbrk);
+EXPORT_SYMBOL_NOVERS(strcpy);
 
 /*
  * binfmt_elf loader 
@@ -64,6 +70,17 @@ EXPORT_SYMBOL(overflowgid);
 EXPORT_SYMBOL(empty_zero_page);
 
 /*
+ * virtual CPU timer
+ */
+#ifdef CONFIG_VIRT_TIMER
+EXPORT_SYMBOL(init_virt_timer);
+EXPORT_SYMBOL(add_virt_timer);
+EXPORT_SYMBOL(add_virt_timer_periodic);
+EXPORT_SYMBOL(mod_virt_timer);
+EXPORT_SYMBOL(del_virt_timer);
+#endif
+
+/*
  * misc.
  */
 EXPORT_SYMBOL(machine_flags);
@@ -75,5 +92,5 @@ EXPORT_SYMBOL(console_device);
 EXPORT_SYMBOL_NOVERS(do_call_softirq);
 EXPORT_SYMBOL(sys_wait4);
 EXPORT_SYMBOL(cpcmd);
+EXPORT_SYMBOL(smp_call_function_on);
 EXPORT_SYMBOL(sys_ioctl);
-
--- diff/arch/s390/kernel/semaphore.c	2004-02-09 10:36:09.000000000 +0000
+++ source/arch/s390/kernel/semaphore.c	2004-02-23 13:56:39.000000000 +0000
@@ -33,8 +33,9 @@ static inline int __sem_update_count(str
                              "   cs    %0,%1,0(%3)\n"
                              "   jl    0b\n"
                              : "=&d" (old_val), "=&d" (new_val),
-			       "+m" (sem->count)
-			     : "a" (&sem->count), "d" (incr) : "cc" );
+			       "=m" (sem->count)
+			     : "a" (&sem->count), "d" (incr), "m" (sem->count)
+			     : "cc" );
 	return old_val;
 }
 
--- diff/arch/s390/kernel/smp.c	2003-10-09 09:47:33.000000000 +0100
+++ source/arch/s390/kernel/smp.c	2004-02-23 13:56:39.000000000 +0000
@@ -30,6 +30,7 @@
 
 #include <linux/delay.h>
 #include <linux/cache.h>
+#include <linux/interrupt.h>
 
 #include <asm/sigp.h>
 #include <asm/pgalloc.h>
@@ -65,7 +66,7 @@ extern char vmpoff_cmd[];
 
 extern void do_reipl(unsigned long devno);
 
-static sigp_ccode smp_ext_bitcall(int, ec_bit_sig);
+static void smp_ext_bitcall(int, ec_bit_sig);
 static void smp_ext_bitcall_others(ec_bit_sig);
 
 /*
@@ -150,6 +151,59 @@ int smp_call_function (void (*func) (voi
 	return 0;
 }
 
+/*
+ * Call a function on one CPU
+ * cpu : the CPU the function should be executed on
+ *
+ * You must not call this function with disabled interrupts or from a
+ * hardware interrupt handler. You may call it from a bottom half.
+ *
+ * It is guaranteed that the called function runs on the specified CPU,
+ * preemption is disabled.
+ */
+int smp_call_function_on(void (*func) (void *info), void *info,
+			 int nonatomic, int wait, int cpu)
+{
+	struct call_data_struct data;
+	int curr_cpu;
+
+	if (!cpu_online(cpu))
+		return -EINVAL;
+
+	/* disable preemption for local function call */
+	curr_cpu = get_cpu();
+
+	if (curr_cpu == cpu) {
+		/* direct call to function */
+		func(info);
+		put_cpu();
+		return 0;
+	}
+
+	data.func = func;
+	data.info = info;
+	atomic_set(&data.started, 0);
+	data.wait = wait;
+	if (wait)
+		atomic_set(&data.finished, 0);
+
+	spin_lock_bh(&call_lock);
+	call_data = &data;
+	smp_ext_bitcall(cpu, ec_call_function);
+
+	/* Wait for response */
+	while (atomic_read(&data.started) != 1)
+		cpu_relax();
+
+	if (wait)
+		while (atomic_read(&data.finished) != 1)
+			cpu_relax();
+
+	spin_unlock_bh(&call_lock);
+	put_cpu();
+	return 0;
+}
+
 static inline void do_send_stop(void)
 {
         u32 dummy;
@@ -305,16 +359,14 @@ void do_ext_call_interrupt(struct pt_reg
  * Send an external call sigp to another cpu and return without waiting
  * for its completion.
  */
-static sigp_ccode smp_ext_bitcall(int cpu, ec_bit_sig sig)
+static void smp_ext_bitcall(int cpu, ec_bit_sig sig)
 {
-        sigp_ccode ccode;
-
         /*
          * Set signaling bit in lowcore of target cpu and kick it
          */
 	set_bit(sig, (unsigned long *) &lowcore_ptr[cpu]->ext_call_fast);
-        ccode = signal_processor(cpu, sigp_external_call);
-        return ccode;
+	while(signal_processor(cpu, sigp_external_call) == sigp_busy)
+		udelay(10);
 }
 
 /*
@@ -350,6 +402,7 @@ void smp_ptlb_all(void)
 {
         on_each_cpu(smp_ptlb_callback, NULL, 0, 1);
 }
+EXPORT_SYMBOL(smp_ptlb_all);
 #endif /* ! CONFIG_ARCH_S390X */
 
 /*
--- diff/arch/s390/kernel/sys_s390.c	2004-02-09 10:36:09.000000000 +0000
+++ source/arch/s390/kernel/sys_s390.c	2004-02-23 13:56:39.000000000 +0000
@@ -21,6 +21,7 @@
 #include <linux/msg.h>
 #include <linux/shm.h>
 #include <linux/stat.h>
+#include <linux/syscalls.h>
 #include <linux/mman.h>
 #include <linux/file.h>
 #include <linux/utsname.h>
@@ -125,8 +126,6 @@ out:
 	return error;
 }
 
-extern asmlinkage int sys_select(int, fd_set *, fd_set *, fd_set *, struct timeval *);
-
 #ifndef CONFIG_ARCH_S390X
 struct sel_arg_struct {
 	unsigned long n;
@@ -290,15 +289,13 @@ asmlinkage int sys_olduname(struct oldol
 	return error;
 }
 
-asmlinkage int sys_ioperm(unsigned long from, unsigned long num, int on)
+asmlinkage long sys_ioperm(unsigned long from, unsigned long num, int on)
 {
 	return -ENOSYS;
 }
 
 #else /* CONFIG_ARCH_S390X */
 
-extern asmlinkage int sys_newuname(struct new_utsname * name);
-
 asmlinkage int s390x_newuname(struct new_utsname * name)
 {
 	int ret = sys_newuname(name);
@@ -310,8 +307,6 @@ asmlinkage int s390x_newuname(struct new
 	return ret;
 }
 
-extern asmlinkage long sys_personality(unsigned long);
-
 asmlinkage int s390x_personality(unsigned long personality)
 {
 	int ret;
@@ -331,8 +326,6 @@ asmlinkage int s390x_personality(unsigne
  */
 #ifndef CONFIG_ARCH_S390X
 
-extern asmlinkage long sys_fadvise64(int, loff_t, size_t, int);
-
 asmlinkage long
 s390_fadvise64(int fd, u32 offset_high, u32 offset_low, size_t len, int advice)
 {
@@ -342,8 +335,6 @@ s390_fadvise64(int fd, u32 offset_high, 
 
 #endif
 
-extern asmlinkage long sys_fadvise64_64(int, loff_t, loff_t, int);
-
 struct fadvise64_64_args {
 	int fd;
 	long long offset;
--- diff/arch/s390/kernel/time.c	2003-10-09 09:47:33.000000000 +0100
+++ source/arch/s390/kernel/time.c	2004-02-23 13:56:39.000000000 +0000
@@ -24,16 +24,17 @@
 #include <linux/init.h>
 #include <linux/smp.h>
 #include <linux/types.h>
+#include <linux/timex.h>
+#include <linux/config.h>
 
 #include <asm/uaccess.h>
 #include <asm/delay.h>
 #include <asm/s390_ext.h>
 #include <asm/div64.h>
-
-#include <linux/timex.h>
-#include <linux/config.h>
-
 #include <asm/irq.h>
+#ifdef CONFIG_VIRT_TIMER
+#include <asm/timer.h>
+#endif
 
 /* change this if you have some constant time drift */
 #define USECS_PER_JIFFY     ((unsigned long) 1000000/HZ)
@@ -51,19 +52,25 @@ u64 jiffies_64 = INITIAL_JIFFIES;
 
 EXPORT_SYMBOL(jiffies_64);
 
-static ext_int_info_t ext_int_info_timer;
+static ext_int_info_t ext_int_info_cc;
 static u64 init_timer_cc;
 static u64 jiffies_timer_cc;
 static u64 xtime_cc;
 
 extern unsigned long wall_jiffies;
 
+#ifdef CONFIG_VIRT_TIMER
+#define VTIMER_MAGIC (0x4b87ad6e + 1)
+static ext_int_info_t ext_int_info_timer;
+DEFINE_PER_CPU(struct vtimer_queue, virt_cpu_timer);
+#endif
+
 /*
  * Scheduler clock - returns current time in nanosec units.
  */
 unsigned long long sched_clock(void)
 {
-	return (get_clock() - jiffies_timer_cc) >> 2;
+	return ((get_clock() - jiffies_timer_cc) * 1000) >> 12;
 }
 
 void tod_to_timeval(__u64 todval, struct timespec *xtime)
@@ -142,6 +149,7 @@ int do_settimeofday(struct timespec *tv)
 	time_maxerror = NTP_PHASE_LIMIT;
 	time_esterror = NTP_PHASE_LIMIT;
 	write_sequnlock_irq(&xtime_lock);
+	clock_was_set();
 	return 0;
 }
 
@@ -225,13 +233,208 @@ void account_ticks(struct pt_regs *regs)
 #endif
 }
 
+#ifdef CONFIG_VIRT_TIMER
+void start_cpu_timer(void)
+{
+	struct vtimer_queue *vt_list;
+
+	vt_list = &per_cpu(virt_cpu_timer, smp_processor_id());
+	set_vtimer(vt_list->idle);
+}
+
+int stop_cpu_timer(void)
+{
+	__u64 done;
+	struct vtimer_queue *vt_list;
+
+	vt_list = &per_cpu(virt_cpu_timer, smp_processor_id());
+
+	/* nothing to do */
+	if (list_empty(&vt_list->list)) {
+		vt_list->idle = VTIMER_MAX_SLICE;
+		goto fire;
+	}
+
+	/* store progress */
+	asm volatile ("STPT %0" : "=m" (done));
+
+	/*
+	 * If done is negative we do not stop the CPU timer
+	 * because we will get instantly an interrupt that
+	 * will start the CPU timer again.
+	 */
+	if (done & 1LL<<63)
+		return 1;
+	else
+		vt_list->offset += vt_list->to_expire - done;
+
+	/* save the actual expire value */
+	vt_list->idle = done;
+
+	/*
+	 * We cannot halt the CPU timer, we just write a value that
+	 * nearly never expires (only after 71 years) and re-write
+	 * the stored expire value if we continue the timer
+	 */
+ fire:
+	set_vtimer(VTIMER_MAX_SLICE);
+	return 0;
+}
+
+void do_monitor_call(struct pt_regs *regs, long interruption_code)
+{
+	/* disable monitor call class 0 */
+	__ctl_clear_bit(8, 15);
+
+	start_cpu_timer();
+}
+
+/*
+ * called from cpu_idle to stop any timers
+ * returns 1 if CPU should not be stopped
+ */
+int stop_timers(void)
+{
+	if (stop_cpu_timer())
+		return 1;
+
+	/* enable monitor call class 0 */
+	__ctl_set_bit(8, 15);
+
+	return 0;
+}
+
+void set_vtimer(__u64 expires)
+{
+	asm volatile ("SPT %0" : : "m" (expires));
+
+	/* store expire time for this CPU timer */
+	per_cpu(virt_cpu_timer, smp_processor_id()).to_expire = expires;
+}
+
+/*
+ * Sorted add to a list. List is linear searched until first bigger
+ * element is found.
+ */
+void list_add_sorted(struct vtimer_list *timer, struct list_head *head)
+{
+	struct vtimer_list *event;
+
+	list_for_each_entry(event, head, entry) {
+		if (event->expires > timer->expires) {
+			list_add_tail(&timer->entry, &event->entry);
+			return;
+		}
+	}
+	list_add_tail(&timer->entry, head);
+}
+
 /*
- * Start the clock comparator on the current CPU.
+ * Do the callback functions of expired vtimer events.
+ * Called from within the interrupt handler.
+ */
+static void do_callbacks(struct list_head *cb_list, struct pt_regs *regs)
+{
+	struct vtimer_queue *vt_list;
+	struct vtimer_list *event, *tmp;
+	void (*fn)(unsigned long, struct pt_regs*);
+	unsigned long data;
+
+	if (list_empty(cb_list))
+		return;
+
+	vt_list = &per_cpu(virt_cpu_timer, smp_processor_id());
+
+	list_for_each_entry_safe(event, tmp, cb_list, entry) {
+		fn = event->function;
+		data = event->data;
+		fn(data, regs);
+
+		if (!event->interval)
+			/* delete one shot timer */
+			list_del_init(&event->entry);
+		else {
+			/* move interval timer back to list */
+			spin_lock(&vt_list->lock);
+			list_del_init(&event->entry);
+			list_add_sorted(event, &vt_list->list);
+			spin_unlock(&vt_list->lock);
+		}
+	}
+}
+
+/*
+ * Handler for the virtual CPU timer.
+ */
+static void do_cpu_timer_interrupt(struct pt_regs *regs, __u16 error_code)
+{
+	int cpu;
+	__u64 next, delta;
+	struct vtimer_queue *vt_list;
+	struct vtimer_list *event, *tmp;
+	struct list_head *ptr;
+	/* the callback queue */
+	struct list_head cb_list;
+
+	INIT_LIST_HEAD(&cb_list);
+	cpu = smp_processor_id();
+	vt_list = &per_cpu(virt_cpu_timer, cpu);
+
+	/* walk timer list, fire all expired events */
+	spin_lock(&vt_list->lock);
+
+	if (vt_list->to_expire < VTIMER_MAX_SLICE)
+		vt_list->offset += vt_list->to_expire;
+
+	list_for_each_entry_safe(event, tmp, &vt_list->list, entry) {
+		if (event->expires > vt_list->offset)
+			/* found first unexpired event, leave */
+			break;
+
+		/* re-charge interval timer, we have to add the offset */
+		if (event->interval)
+			event->expires = event->interval + vt_list->offset;
+
+		/* move expired timer to the callback queue */
+		list_move_tail(&event->entry, &cb_list);
+	}
+	spin_unlock(&vt_list->lock);
+	do_callbacks(&cb_list, regs);
+
+	/* next event is first in list */
+	spin_lock(&vt_list->lock);
+	if (!list_empty(&vt_list->list)) {
+		ptr = vt_list->list.next;
+		event = list_entry(ptr, struct vtimer_list, entry);
+		next = event->expires - vt_list->offset;
+
+		/* add the expired time from this interrupt handler
+		 * and the callback functions
+		 */
+		asm volatile ("STPT %0" : "=m" (delta));
+		delta = 0xffffffffffffffffLL - delta + 1;
+		vt_list->offset += delta;
+		next -= delta;
+	} else {
+		vt_list->offset = 0;
+		next = VTIMER_MAX_SLICE;
+	}
+	spin_unlock(&vt_list->lock);
+	set_vtimer(next);
+}
+#endif
+
+/*
+ * Start the clock comparator and the virtual CPU timer
+ * on the current CPU.
  */
 void init_cpu_timer(void)
 {
 	unsigned long cr0;
 	__u64 timer;
+#ifdef CONFIG_VIRT_TIMER
+	struct vtimer_queue *vt_list;
+#endif
 
 	timer = jiffies_timer_cc + jiffies_64 * CLK_TICKS_PER_JIFFY;
 	S390_lowcore.jiffy_timer = timer + CLK_TICKS_PER_JIFFY;
@@ -241,6 +444,22 @@ void init_cpu_timer(void)
 	__ctl_store(cr0, 0, 0);
         cr0 |= 0x800;
 	__ctl_load(cr0, 0, 0);
+
+#ifdef CONFIG_VIRT_TIMER
+	/* kick the virtual timer */
+	timer = VTIMER_MAX_SLICE;
+	asm volatile ("SPT %0" : : "m" (timer));
+	__ctl_store(cr0, 0, 0);
+	cr0 |= 0x400;
+	__ctl_load(cr0, 0, 0);
+
+	vt_list = &per_cpu(virt_cpu_timer, smp_processor_id());
+	INIT_LIST_HEAD(&vt_list->list);
+	spin_lock_init(&vt_list->lock);
+	vt_list->to_expire = 0;
+	vt_list->offset = 0;
+	vt_list->idle = 0;
+#endif
 }
 
 /*
@@ -280,11 +499,252 @@ void __init time_init(void)
         set_normalized_timespec(&wall_to_monotonic,
                                 -xtime.tv_sec, -xtime.tv_nsec);
 
-        /* request the 0x1004 external interrupt */
+	/* request the clock comparator external interrupt */
         if (register_early_external_interrupt(0x1004, 0,
-					      &ext_int_info_timer) != 0)
+					      &ext_int_info_cc) != 0)
                 panic("Couldn't request external interrupt 0x1004");
 
-        /* init CPU timer */
+#ifdef CONFIG_VIRT_TIMER
+	/* request the cpu timer external interrupt */
+	if (register_early_external_interrupt(0x1005, do_cpu_timer_interrupt,
+					      &ext_int_info_timer) != 0)
+		panic("Couldn't request external interrupt 0x1005");
+#endif
+
         init_cpu_timer();
 }
+
+#ifdef CONFIG_VIRT_TIMER
+void init_virt_timer(struct vtimer_list *timer)
+{
+	timer->magic = VTIMER_MAGIC;
+	timer->function = NULL;
+	INIT_LIST_HEAD(&timer->entry);
+	spin_lock_init(&timer->lock);
+}
+
+static inline int check_vtimer(struct vtimer_list *timer)
+{
+	if (timer->magic != VTIMER_MAGIC)
+		return -EINVAL;
+	return 0;
+}
+
+static inline int vtimer_pending(struct vtimer_list *timer)
+{
+	return (!list_empty(&timer->entry));
+}
+
+/*
+ * this function should only run on the specified CPU
+ */
+static void internal_add_vtimer(struct vtimer_list *timer)
+{
+	unsigned long flags;
+	__u64 done;
+	struct vtimer_list *event;
+	struct vtimer_queue *vt_list;
+
+	vt_list = &per_cpu(virt_cpu_timer, timer->cpu);
+	spin_lock_irqsave(&vt_list->lock, flags);
+
+	if (timer->cpu != smp_processor_id())
+		printk("internal_add_vtimer: BUG, running on wrong CPU");
+
+	/* if list is empty we only have to set the timer */
+	if (list_empty(&vt_list->list)) {
+		/* reset the offset, this may happen if the last timer was
+		 * just deleted by mod_virt_timer and the interrupt
+		 * didn't happen until here
+		 */
+		vt_list->offset = 0;
+		goto fire;
+	}
+
+	/* save progress */
+	asm volatile ("STPT %0" : "=m" (done));
+
+	/* calculate completed work */
+	done = vt_list->to_expire - done + vt_list->offset;
+	vt_list->offset = 0;
+
+	list_for_each_entry(event, &vt_list->list, entry)
+		event->expires -= done;
+
+ fire:
+	list_add_sorted(timer, &vt_list->list);
+
+	/* get first element, which is the next vtimer slice */
+	event = list_entry(vt_list->list.next, struct vtimer_list, entry);
+
+	set_vtimer(event->expires);
+	spin_unlock_irqrestore(&vt_list->lock, flags);
+	/* release CPU aquired in prepare_vtimer or mod_virt_timer() */
+	put_cpu();
+}
+
+static inline int prepare_vtimer(struct vtimer_list *timer)
+{
+	if (check_vtimer(timer) || !timer->function) {
+		printk("add_virt_timer: uninitialized timer\n");
+		return -EINVAL;
+	}
+
+	if (!timer->expires || timer->expires > VTIMER_MAX_SLICE) {
+		printk("add_virt_timer: invalid timer expire value!\n");
+		return -EINVAL;
+	}
+
+	if (vtimer_pending(timer)) {
+		printk("add_virt_timer: timer pending\n");
+		return -EBUSY;
+	}
+
+	timer->cpu = get_cpu();
+	return 0;
+}
+
+/*
+ * add_virt_timer - add an oneshot virtual CPU timer
+ */
+void add_virt_timer(void *new)
+{
+	struct vtimer_list *timer;
+
+	timer = (struct vtimer_list *)new;
+
+	if (prepare_vtimer(timer) < 0)
+		return;
+
+	timer->interval = 0;
+	internal_add_vtimer(timer);
+}
+
+/*
+ * add_virt_timer_int - add an interval virtual CPU timer
+ */
+void add_virt_timer_periodic(void *new)
+{
+	struct vtimer_list *timer;
+
+	timer = (struct vtimer_list *)new;
+
+	if (prepare_vtimer(timer) < 0)
+		return;
+
+	timer->interval = timer->expires;
+	internal_add_vtimer(timer);
+}
+
+/*
+ * If we change a pending timer the function must be called on the CPU
+ * where the timer is running on, e.g. by smp_call_function_on()
+ *
+ * The original mod_timer adds the timer if it is not pending. For compatibility
+ * we do the same. The timer will be added on the current CPU as a oneshot timer.
+ *
+ * returns whether it has modified a pending timer (1) or not (0)
+ */
+int mod_virt_timer(struct vtimer_list *timer, __u64 expires)
+{
+	struct vtimer_queue *vt_list;
+	unsigned long flags;
+	int cpu;
+
+	if (check_vtimer(timer) || !timer->function) {
+		printk("mod_virt_timer: uninitialized timer\n");
+		return	-EINVAL;
+	}
+
+	if (!expires || expires > VTIMER_MAX_SLICE) {
+		printk("mod_virt_timer: invalid expire range\n");
+		return -EINVAL;
+	}
+
+	/*
+	 * This is a common optimization triggered by the
+	 * networking code - if the timer is re-modified
+	 * to be the same thing then just return:
+	 */
+	if (timer->expires == expires && vtimer_pending(timer))
+		return 1;
+
+	cpu = get_cpu();
+	vt_list = &per_cpu(virt_cpu_timer, cpu);
+
+	/* disable interrupts before test if timer is pending */
+	spin_lock_irqsave(&vt_list->lock, flags);
+
+	/* if timer isn't pending add it on the current CPU */
+	if (!vtimer_pending(timer)) {
+		spin_unlock_irqrestore(&vt_list->lock, flags);
+		/* we do not activate an interval timer with mod_virt_timer */
+		timer->interval = 0;
+		timer->expires = expires;
+		timer->cpu = cpu;
+		internal_add_vtimer(timer);
+		return 0;
+	}
+
+	/* check if we run on the right CPU */
+	if (timer->cpu != cpu) {
+		printk("mod_virt_timer: running on wrong CPU, check your code\n");
+		spin_unlock_irqrestore(&vt_list->lock, flags);
+		put_cpu();
+		return -EINVAL;
+	}
+
+	list_del_init(&timer->entry);
+	timer->expires = expires;
+
+	/* also change the interval if we have an interval timer */
+	if (timer->interval)
+		timer->interval = expires;
+
+	/* the timer can't expire anymore so we can release the lock */
+	spin_unlock_irqrestore(&vt_list->lock, flags);
+	internal_add_vtimer(timer);
+	return 1;
+}
+
+/*
+ * delete a virtual timer
+ *
+ * returns whether the deleted timer was pending (1) or not (0)
+ */
+int del_virt_timer(struct vtimer_list *timer)
+{
+	unsigned long flags;
+	struct vtimer_queue *vt_list;
+
+	if (check_vtimer(timer)) {
+		printk("del_virt_timer: timer not initialized\n");
+		return -EINVAL;
+	}
+
+	/* check if timer is pending */
+	if (!vtimer_pending(timer))
+		return 0;
+
+	if (!cpu_online(timer->cpu)) {
+		printk("del_virt_timer: CPU not present!\n");
+		return -1;
+	}
+
+	vt_list = &per_cpu(virt_cpu_timer, timer->cpu);
+	spin_lock_irqsave(&vt_list->lock, flags);
+
+	/* we don't interrupt a running timer, just let it expire! */
+	list_del_init(&timer->entry);
+
+	/* last timer removed */
+	if (list_empty(&vt_list->list)) {
+		vt_list->to_expire = 0;
+		vt_list->offset = 0;
+	}
+
+	spin_unlock_irqrestore(&vt_list->lock, flags);
+	return 1;
+}
+#endif
+
--- diff/arch/s390/kernel/traps.c	2004-02-09 10:36:09.000000000 +0000
+++ source/arch/s390/kernel/traps.c	2004-02-23 13:56:39.000000000 +0000
@@ -64,6 +64,9 @@ extern void pfault_fini(void);
 extern void pfault_interrupt(struct pt_regs *regs, __u16 error_code);
 static ext_int_info_t ext_int_pfault;
 #endif
+#ifdef CONFIG_VIRT_TIMER
+extern pgm_check_handler_t do_monitor_call;
+#endif
 
 #define stack_pointer ({ void **sp; asm("la %0,0(15)" : "=&d" (sp)); sp; })
 
@@ -625,6 +628,9 @@ void __init trap_init(void)
 #endif /* CONFIG_ARCH_S390X */
         pgm_check_table[0x15] = &operand_exception;
         pgm_check_table[0x1C] = &privileged_op;
+#ifdef CONFIG_VIRT_TIMER
+	pgm_check_table[0x40] = &do_monitor_call;
+#endif
 	if (MACHINE_IS_VM) {
 		/*
 		 * First try to get pfault pseudo page faults going.
--- diff/arch/s390/lib/Makefile	2003-06-30 10:07:19.000000000 +0100
+++ source/arch/s390/lib/Makefile	2004-02-23 13:56:39.000000000 +0000
@@ -5,5 +5,5 @@
 EXTRA_AFLAGS := -traditional
 
 lib-y += delay.o 
-lib-$(CONFIG_ARCH_S390_31) += memset.o strcmp.o strncpy.o uaccess.o
-lib-$(CONFIG_ARCH_S390X) += memset64.o strcmp64.o strncpy64.o uaccess64.o
+lib-$(CONFIG_ARCH_S390_31) += memset.o strcmp.o strcpy.o strncpy.o uaccess.o
+lib-$(CONFIG_ARCH_S390X) += memset64.o strcmp64.o strcpy64.o strncpy64.o uaccess64.o
--- diff/arch/s390/lib/strncpy.S	2002-10-16 04:28:25.000000000 +0100
+++ source/arch/s390/lib/strncpy.S	2004-02-23 13:56:39.000000000 +0000
@@ -23,8 +23,13 @@ strncpy_loop:
 	LA      3,1(3)
         STC     0,0(1)
 	LA      1,1(1)
-        JZ      strncpy_exit   # ICM inserted a 0x00
+        JZ      strncpy_pad    # ICM inserted a 0x00
         BRCT    4,strncpy_loop # R4 -= 1, jump to strncpy_loop if >  0
 strncpy_exit:
         BR      14
-
+strncpy_clear:
+	STC	0,0(1)
+	LA	1,1(1)
+strncpy_pad:
+	BRCT	4,strncpy_clear
+	BR	14
--- diff/arch/s390/lib/strncpy64.S	2003-05-21 11:50:08.000000000 +0100
+++ source/arch/s390/lib/strncpy64.S	2004-02-23 13:56:39.000000000 +0000
@@ -23,8 +23,13 @@ strncpy_loop:
 	LA      3,1(3)
         STC     0,0(1)
 	LA      1,1(1)
-        JZ      strncpy_exit   # ICM inserted a 0x00
+        JZ      strncpy_pad    # ICM inserted a 0x00
         BRCTG   4,strncpy_loop # R4 -= 1, jump to strncpy_loop if > 0
 strncpy_exit:
         BR      14
-
+strncpy_clear:
+	STC	0,0(1)
+	LA	1,1(1)
+strncpy_pad:
+	BRCTG	4,strncpy_clear
+	BR	14
--- diff/arch/s390/math-emu/math.c	2003-06-09 14:18:18.000000000 +0100
+++ source/arch/s390/math-emu/math.c	2004-02-23 13:56:39.000000000 +0000
@@ -99,7 +99,6 @@ int sysctl_ieee_emulation_warnings=1;
 
 static void display_emulation_not_implemented(struct pt_regs *regs, char *instr)
 {
-        struct pt_regs *regs;
         __u16 *location;
         
 #ifdef CONFIG_SYSCTL
--- diff/arch/s390/mm/Makefile	2004-02-09 10:36:09.000000000 +0000
+++ source/arch/s390/mm/Makefile	2004-02-23 13:56:39.000000000 +0000
@@ -2,4 +2,6 @@
 # Makefile for the linux s390-specific parts of the memory manager.
 #
 
-obj-y	 := init.o fault.o ioremap.o
+obj-y	 := init.o fault.o ioremap.o extmem.o
+obj-$(CONFIG_CMM) += cmm.o
+
--- diff/arch/s390/mm/init.c	2004-02-09 10:36:09.000000000 +0000
+++ source/arch/s390/mm/init.c	2004-02-23 13:56:39.000000000 +0000
@@ -40,6 +40,19 @@ DEFINE_PER_CPU(struct mmu_gather, mmu_ga
 pgd_t swapper_pg_dir[PTRS_PER_PGD] __attribute__((__aligned__(PAGE_SIZE)));
 char  empty_zero_page[PAGE_SIZE] __attribute__((__aligned__(PAGE_SIZE)));
 
+void diag10(unsigned long addr)
+{
+#ifdef __s390x__
+        if (addr >= 0x80000000)
+                return;
+        asm volatile ("sam31\n\t"
+                      "diag %0,%0,0x10\n\t"
+                      "sam64" : : "a" (addr) );
+#else
+        asm volatile ("diag %0,%0,0x10" : : "a" (addr) );
+#endif
+}
+
 void show_mem(void)
 {
         int i, total = 0, reserved = 0;
--- diff/arch/sh/Kconfig	2004-02-18 08:54:08.000000000 +0000
+++ source/arch/sh/Kconfig	2004-02-23 13:56:39.000000000 +0000
@@ -609,24 +609,6 @@ source "arch/sh/drivers/pci/Kconfig"
 
 source "drivers/pci/Kconfig"
 
-config HOTPLUG
-	bool "Support for hot-pluggable devices"
-	---help---
-	  Say Y here if you want to plug devices into your computer while
-	  the system is running, and be able to use them quickly.  In many
-	  cases, the devices can likewise be unplugged at any time too.
-
-	  One well known example of this is PCMCIA- or PC-cards, credit-card
-	  size devices such as network cards, modems or hard drives which are
-	  plugged into slots found on all modern laptop computers.  Another
-	  example, used on modern desktops as well as laptops, is USB.
-
-	  Enable HOTPLUG and KMOD, and build a modular kernel.  Get agent
-	  software (at <http://linux-hotplug.sourceforge.net/>) and install it.
-	  Then your kernel will automatically call out to a user mode "policy
-	  agent" (/sbin/hotplug) to load modules and set up software needed
-	  to use devices as you hotplug them.
-
 source "drivers/pcmcia/Kconfig"
 
 source "drivers/pci/hotplug/Kconfig"
--- diff/arch/sh/kernel/sys_sh.c	2004-02-09 10:36:09.000000000 +0000
+++ source/arch/sh/kernel/sys_sh.c	2004-02-23 13:56:39.000000000 +0000
@@ -17,6 +17,7 @@
 #include <linux/msg.h>
 #include <linux/shm.h>
 #include <linux/stat.h>
+#include <linux/syscalls.h>
 #include <linux/mman.h>
 #include <linux/file.h>
 #include <linux/utsname.h>
@@ -240,16 +241,12 @@ asmlinkage int sys_uname(struct old_utsn
 asmlinkage ssize_t sys_pread_wrapper(unsigned int fd, char * buf,
 			     size_t count, long dummy, loff_t pos)
 {
-	extern asmlinkage ssize_t sys_pread64(unsigned int fd, char * buf,
-					size_t count, loff_t pos);
 	return sys_pread64(fd, buf, count, pos);
 }
 
 asmlinkage ssize_t sys_pwrite_wrapper(unsigned int fd, const char * buf,
 			      size_t count, long dummy, loff_t pos)
 {
-	extern asmlinkage ssize_t sys_pwrite64(unsigned int fd, const char * buf,
-					size_t count, loff_t pos);
 	return sys_pwrite64(fd, buf, count, pos);
 }
 
--- diff/arch/sparc/Makefile	2004-01-19 10:22:55.000000000 +0000
+++ source/arch/sparc/Makefile	2004-02-23 13:56:39.000000000 +0000
@@ -11,21 +11,12 @@
 # Uncomment the first CFLAGS if you are doing kgdb source level
 # debugging of the kernel to get the proper debugging information.
 
-IS_EGCS := $(shell if $(CC) -m32 -S -o /dev/null -xc /dev/null >/dev/null 2>&1; then echo y; else echo n; fi; )
-NEW_GAS := $(shell if $(LD) --version 2>&1 | grep 'elf64_sparc' > /dev/null; then echo y; else echo n; fi)
-
-ifeq ($(NEW_GAS),y)
 AS              := $(AS) -32
 LDFLAGS		:= -m elf32_sparc
-endif
 
 #CFLAGS := $(CFLAGS) -g -pipe -fcall-used-g5 -fcall-used-g7
-ifneq ($(IS_EGCS),y)
-CFLAGS := $(CFLAGS) -pipe -mno-fpu -fcall-used-g5 -fcall-used-g7
-else
 CFLAGS := $(CFLAGS) -m32 -pipe -mno-fpu -fcall-used-g5 -fcall-used-g7
 AFLAGS := $(AFLAGS) -m32
-endif
 
 #LDFLAGS_vmlinux = -N -Ttext 0xf0004000
 #  Since 2.5.40, the first stage is left not btfix-ed.
--- diff/arch/sparc/kernel/entry.S	2004-01-19 10:22:55.000000000 +0000
+++ source/arch/sparc/kernel/entry.S	2004-02-23 13:56:39.000000000 +0000
@@ -19,7 +19,6 @@
 #include <asm/ptrace.h>
 #include <asm/asm_offsets.h>
 #include <asm/psr.h>
-#include <asm/cprefix.h>
 #include <asm/vaddrs.h>
 #include <asm/memreg.h>
 #include <asm/page.h>
@@ -68,8 +67,8 @@ in_trap_handler:
 ! available before jumping into C code.  It will also restore the world if you
 ! return from handle_exception.
 
-	.globl	C_LABEL(trap_low)
-C_LABEL(trap_low):
+	.globl	trap_low
+trap_low:
 	rd	%wim, %l3
 	SAVE_ALL
 
@@ -104,7 +103,7 @@ C_LABEL(trap_low):
 	wr	%l0, PSR_ET, %psr
 	WRITE_PAUSE
 
-	call	C_LABEL(handle_exception)
+	call	handle_exception
 	 add	%sp, STACKFRAME_SZ, %o0	! Pass address of registers
 
 	/* Load new kgdb register set. */
@@ -134,8 +133,8 @@ C_LABEL(trap_low):
 #ifdef CONFIG_BLK_DEV_FD
 	.text
 	.align	4
-	.globl	C_LABEL(floppy_hardint)
-C_LABEL(floppy_hardint):
+	.globl	floppy_hardint
+floppy_hardint:
 	/*
 	 * This code cannot touch registers %l0 %l1 and %l2
 	 * because SAVE_ALL depends on their values. It depends
@@ -149,21 +148,21 @@ C_LABEL(floppy_hardint):
 	 */
 
 	/* Do we have work to do? */
-	sethi	%hi(C_LABEL(doing_pdma)), %l7
-	ld	[%l7 + %lo(C_LABEL(doing_pdma))], %l7
+	sethi	%hi(doing_pdma), %l7
+	ld	[%l7 + %lo(doing_pdma)], %l7
 	cmp	%l7, 0
 	be	floppy_dosoftint
 	 nop
 
 	/* Load fdc register base */
-	sethi	%hi(C_LABEL(fdc_status)), %l3
-	ld	[%l3 + %lo(C_LABEL(fdc_status))], %l3
+	sethi	%hi(fdc_status), %l3
+	ld	[%l3 + %lo(fdc_status)], %l3
 
 	/* Setup register addresses */
-	sethi	%hi(C_LABEL(pdma_vaddr)), %l5	! transfer buffer
-	ld	[%l5 + %lo(C_LABEL(pdma_vaddr))], %l4
-	sethi	%hi(C_LABEL(pdma_size)), %l5	! bytes to go
-	ld	[%l5 + %lo(C_LABEL(pdma_size))], %l6
+	sethi	%hi(pdma_vaddr), %l5	! transfer buffer
+	ld	[%l5 + %lo(pdma_vaddr)], %l4
+	sethi	%hi(pdma_size), %l5	! bytes to go
+	ld	[%l5 + %lo(pdma_size)], %l6
 next_byte:
   	ldub	[%l3], %l7
 
@@ -195,15 +194,15 @@ floppy_write:
 
 	/* fall through... */
 floppy_tdone:
-	sethi	%hi(C_LABEL(pdma_vaddr)), %l5
-	st	%l4, [%l5 + %lo(C_LABEL(pdma_vaddr))]
-	sethi	%hi(C_LABEL(pdma_size)), %l5
-	st	%l6, [%l5 + %lo(C_LABEL(pdma_size))]
+	sethi	%hi(pdma_vaddr), %l5
+	st	%l4, [%l5 + %lo(pdma_vaddr)]
+	sethi	%hi(pdma_size), %l5
+	st	%l6, [%l5 + %lo(pdma_size)]
 	/* Flip terminal count pin */
-	set	C_LABEL(auxio_register), %l7
+	set	auxio_register, %l7
 	ld	[%l7], %l7
 
-	set	C_LABEL(sparc_cpu_model), %l5
+	set	sparc_cpu_model, %l5
 	ld	[%l5], %l5
 	subcc   %l5, 1, %g0		/* enum { sun4c = 1 }; */
 	be	1f
@@ -228,9 +227,9 @@ floppy_tdone:
 	stb     %l5, [%l7]
 
 	/* Prevent recursion */
-	sethi	%hi(C_LABEL(doing_pdma)), %l7
+	sethi	%hi(doing_pdma), %l7
 	b	floppy_dosoftint
-	 st	%g0, [%l7 + %lo(C_LABEL(doing_pdma))]
+	 st	%g0, [%l7 + %lo(doing_pdma)]
 
 	/* We emptied the FIFO, but we haven't read everything
 	 * as of yet.  Store the current transfer address and
@@ -238,10 +237,10 @@ floppy_tdone:
 	 * fast IRQ comes in.
 	 */
 floppy_fifo_emptied:
-	sethi	%hi(C_LABEL(pdma_vaddr)), %l5
-	st	%l4, [%l5 + %lo(C_LABEL(pdma_vaddr))]
-	sethi	%hi(C_LABEL(pdma_size)), %l7
-	st	%l6, [%l7 + %lo(C_LABEL(pdma_size))]
+	sethi	%hi(pdma_vaddr), %l5
+	st	%l4, [%l5 + %lo(pdma_vaddr)]
+	sethi	%hi(pdma_size), %l7
+	st	%l6, [%l7 + %lo(pdma_size)]
 
 	/* Restore condition codes */
 	wr	%l0, 0x0, %psr
@@ -251,13 +250,13 @@ floppy_fifo_emptied:
 	rett	%l2
 
 floppy_overrun:
-	sethi	%hi(C_LABEL(pdma_vaddr)), %l5
-	st	%l4, [%l5 + %lo(C_LABEL(pdma_vaddr))]
-	sethi	%hi(C_LABEL(pdma_size)), %l5
-	st	%l6, [%l5 + %lo(C_LABEL(pdma_size))]
+	sethi	%hi(pdma_vaddr), %l5
+	st	%l4, [%l5 + %lo(pdma_vaddr)]
+	sethi	%hi(pdma_size), %l5
+	st	%l6, [%l5 + %lo(pdma_size)]
 	/* Prevent recursion */
-	sethi	%hi(C_LABEL(doing_pdma)), %l7
-	st	%g0, [%l7 + %lo(C_LABEL(doing_pdma))]
+	sethi	%hi(doing_pdma), %l7
+	st	%g0, [%l7 + %lo(doing_pdma)]
 
 	/* fall through... */
 floppy_dosoftint:
@@ -273,7 +272,7 @@ floppy_dosoftint:
 
 	mov	11, %o0			! floppy irq level (unused anyway)
 	mov	%g0, %o1		! devid is not used in fast interrupts
-	call	C_LABEL(sparc_floppy_irq)
+	call	sparc_floppy_irq
 	 add	%sp, STACKFRAME_SZ, %o2	! struct pt_regs *regs
 
 	RESTORE_ALL
@@ -290,7 +289,7 @@ bad_trap_handler:
 
 	mov	%l7, %o0		! trap number
 	mov	%l0, %o1		! psr
-	call	C_LABEL(do_hw_interrupt)
+	call	do_hw_interrupt
 	 mov	%l1, %o2		! pc
 
 	RESTORE_ALL
@@ -322,7 +321,7 @@ real_irq_continue:
 	WRITE_PAUSE
 	mov	%l7, %o0		! irq level
 patch_handler_irq:
-	call	C_LABEL(handler_irq)
+	call	handler_irq
 	 add	%sp, STACKFRAME_SZ, %o1	! pt_regs ptr
 	or	%l0, PSR_PIL, %g2	! restore PIL after handler_irq
 	wr	%g2, PSR_ET, %psr	! keep ET up
@@ -339,7 +338,7 @@ smp4m_ticker:
 	WRITE_PAUSE
 	wr	%g2, PSR_ET, %psr
 	WRITE_PAUSE
-	call	C_LABEL(smp4m_percpu_timer_interrupt)
+	call	smp4m_percpu_timer_interrupt
 	 add	%sp, STACKFRAME_SZ, %o0
 	wr	%l0, PSR_ET, %psr
 	WRITE_PAUSE
@@ -351,7 +350,7 @@ smp4m_ticker:
 	 */
 maybe_smp4m_msg:
 	GET_PROCESSOR_MID(o3, o2)
-	set	C_LABEL(sun4m_interrupts), %l5
+	set	sun4m_interrupts, %l5
 	ld	[%l5], %o5
 	sethi	%hi(0x60000000), %o4
 	sll	%o3, 12, %o3
@@ -378,10 +377,10 @@ maybe_smp4m_msg:
 	tst	%o2
 	bne	2f
 	 nop
-	call	C_LABEL(smp_reschedule_irq)
+	call	smp_reschedule_irq
 	 add	%o7, 8, %o7
 2:
-	call	C_LABEL(smp_stop_cpu_irq)
+	call	smp_stop_cpu_irq
 	 nop
 	RESTORE_ALL
 
@@ -391,7 +390,7 @@ linux_trap_ipi15_sun4m:
 	SAVE_ALL
 	sethi	%hi(0x80000000), %o2
 	GET_PROCESSOR_MID(o0, o1)
-	set	C_LABEL(sun4m_interrupts), %l5
+	set	sun4m_interrupts, %l5
 	ld	[%l5], %o5
 	sll	%o0, 12, %o0
 	add	%o5, %o0, %o5
@@ -407,7 +406,7 @@ linux_trap_ipi15_sun4m:
 	WRITE_PAUSE
 	wr	%l4, PSR_ET, %psr
 	WRITE_PAUSE
-	call	C_LABEL(smp4m_cross_call_irq)
+	call	smp4m_cross_call_irq
 	 nop
 	b	ret_trap_lockless_ipi
 	 clr	%l6
@@ -426,7 +425,7 @@ linux_trap_ipi15_sun4m:
 	WRITE_PAUSE
 	wr	%l4, PSR_ET, %psr
 	WRITE_PAUSE
-	call	C_LABEL(sun4m_nmi)
+	call	sun4m_nmi
 	 nop
 	st	%l4, [%l5 + 0x8]
 	WRITE_PAUSE
@@ -447,7 +446,7 @@ smp4d_ticker:
 	WRITE_PAUSE
 	wr	%g2, PSR_ET, %psr
 	WRITE_PAUSE
-	call	C_LABEL(smp4d_percpu_timer_interrupt)
+	call	smp4d_percpu_timer_interrupt
 	 add	%sp, STACKFRAME_SZ, %o0
 	wr	%l0, PSR_ET, %psr
 	WRITE_PAUSE
@@ -475,7 +474,7 @@ linux_trap_ipi15_sun4d:
 	WRITE_PAUSE
 	wr	%l4, PSR_ET, %psr
 	WRITE_PAUSE
-	call	C_LABEL(smp4d_cross_call_irq)
+	call	smp4d_cross_call_irq
 	 nop
 	b	ret_trap_lockless_ipi
 	 clr	%l6
@@ -513,7 +512,7 @@ bad_instruction:
 	add	%sp, STACKFRAME_SZ, %o0
 	mov	%l1, %o1
 	mov	%l2, %o2
-	call	C_LABEL(do_illegal_instruction)
+	call	do_illegal_instruction
 	 mov	%l0, %o3
 
 	RESTORE_ALL
@@ -533,7 +532,7 @@ priv_instruction:
 	add	%sp, STACKFRAME_SZ, %o0
 	mov	%l1, %o1
 	mov	%l2, %o2
-	call	C_LABEL(do_priv_instruction)
+	call	do_priv_instruction
 	 mov	%l0, %o3
 
 	RESTORE_ALL
@@ -552,7 +551,7 @@ mna_handler:
 	WRITE_PAUSE
 
 	ld	[%l1], %o1
-	call	C_LABEL(kernel_unaligned_trap)
+	call	kernel_unaligned_trap
 	 add	%sp, STACKFRAME_SZ, %o0
 
 	RESTORE_ALL
@@ -564,7 +563,7 @@ mna_fromuser:
 	WRITE_PAUSE
 
 	ld	[%l1], %o1
-	call	C_LABEL(user_unaligned_trap)
+	call	user_unaligned_trap
 	 add	%sp, STACKFRAME_SZ, %o0
 
 	RESTORE_ALL
@@ -581,7 +580,7 @@ fpd_trap_handler:
 	add	%sp, STACKFRAME_SZ, %o0
 	mov	%l1, %o1
 	mov	%l2, %o2
-	call	C_LABEL(do_fpd_trap)
+	call	do_fpd_trap
 	 mov	%l0, %o3
 
 	RESTORE_ALL
@@ -593,8 +592,8 @@ fpe_trap_handler:
 	set	fpsave_magic, %l5
 	cmp	%l1, %l5
 	be	1f
-	 sethi	%hi(C_LABEL(fpsave)), %l5
-	or	%l5, %lo(C_LABEL(fpsave)), %l5
+	 sethi	%hi(fpsave), %l5
+	or	%l5, %lo(fpsave), %l5
 	cmp	%l1, %l5
 	bne	2f
 	 sethi	%hi(fpsave_catch2), %l5
@@ -620,7 +619,7 @@ fpe_trap_handler:
 	add	%sp, STACKFRAME_SZ, %o0
 	mov	%l1, %o1
 	mov	%l2, %o2
-	call	C_LABEL(do_fpe_trap)
+	call	do_fpe_trap
 	 mov	%l0, %o3
 
 	RESTORE_ALL
@@ -637,7 +636,7 @@ do_tag_overflow:
 	add	%sp, STACKFRAME_SZ, %o0
 	mov	%l1, %o1
 	mov	%l2, %o2
-	call	C_LABEL(handle_tag_overflow)
+	call	handle_tag_overflow
 	 mov	%l0, %o3
 
 	RESTORE_ALL
@@ -654,7 +653,7 @@ do_watchpoint:
 	add	%sp, STACKFRAME_SZ, %o0
 	mov	%l1, %o1
 	mov	%l2, %o2
-	call	C_LABEL(handle_watchpoint)
+	call	handle_watchpoint
 	 mov	%l0, %o3
 
 	RESTORE_ALL
@@ -671,7 +670,7 @@ do_reg_access:
 	add	%sp, STACKFRAME_SZ, %o0
 	mov	%l1, %o1
 	mov	%l2, %o2
-	call	C_LABEL(handle_reg_access)
+	call	handle_reg_access
 	 mov	%l0, %o3
 
 	RESTORE_ALL
@@ -688,7 +687,7 @@ do_cp_disabled:
 	add	%sp, STACKFRAME_SZ, %o0
 	mov	%l1, %o1
 	mov	%l2, %o2
-	call	C_LABEL(handle_cp_disabled)
+	call	handle_cp_disabled
 	 mov	%l0, %o3
 
 	RESTORE_ALL
@@ -705,7 +704,7 @@ do_cp_exception:
 	add	%sp, STACKFRAME_SZ, %o0
 	mov	%l1, %o1
 	mov	%l2, %o2
-	call	C_LABEL(handle_cp_exception)
+	call	handle_cp_exception
 	 mov	%l0, %o3
 
 	RESTORE_ALL
@@ -722,7 +721,7 @@ do_hw_divzero:
 	add	%sp, STACKFRAME_SZ, %o0
 	mov	%l1, %o1
 	mov	%l2, %o2
-	call	C_LABEL(handle_hw_divzero)
+	call	handle_hw_divzero
 	 mov	%l0, %o3
 
 	RESTORE_ALL
@@ -739,7 +738,7 @@ do_flush_windows:
 	bne	dfw_kernel
 	 nop
 
-	call	C_LABEL(flush_user_windows)
+	call	flush_user_windows
 	 nop
 
 	/* Advance over the trap instruction. */
@@ -805,8 +804,8 @@ linux_trap_nmi_sun4c:
 	/* Ugh, we need to clear the IRQ line.  This is now
 	 * a very sun4c specific trap handler...
 	 */
-	sethi	%hi(C_LABEL(interrupt_enable)), %l5
-	ld	[%l5 + %lo(C_LABEL(interrupt_enable))], %l5
+	sethi	%hi(interrupt_enable), %l5
+	ld	[%l5 + %lo(interrupt_enable)], %l5
 	ldub	[%l5], %l6
 	andn	%l6, INTS_ENAB, %l6
 	stb	%l6, [%l5]
@@ -829,51 +828,51 @@ linux_trap_nmi_sun4c:
 	lda	[%o0] ASI_CONTROL, %o4	! async vaddr
 	sub	%o0, 0x4, %o0
 	lda	[%o0] ASI_CONTROL, %o3	! async error
-	call	C_LABEL(sparc_lvl15_nmi)
+	call	sparc_lvl15_nmi
 	 add	%sp, STACKFRAME_SZ, %o0
 
 	RESTORE_ALL
 
 	.align	4
-	.globl	C_LABEL(invalid_segment_patch1_ff)
-	.globl	C_LABEL(invalid_segment_patch2_ff)
-C_LABEL(invalid_segment_patch1_ff):	cmp	%l4, 0xff
-C_LABEL(invalid_segment_patch2_ff):	mov	0xff, %l3
+	.globl	invalid_segment_patch1_ff
+	.globl	invalid_segment_patch2_ff
+invalid_segment_patch1_ff:	cmp	%l4, 0xff
+invalid_segment_patch2_ff:	mov	0xff, %l3
 
 	.align	4
-	.globl	C_LABEL(invalid_segment_patch1_1ff)
-	.globl	C_LABEL(invalid_segment_patch2_1ff)
-C_LABEL(invalid_segment_patch1_1ff):	cmp	%l4, 0x1ff
-C_LABEL(invalid_segment_patch2_1ff):	mov	0x1ff, %l3
+	.globl	invalid_segment_patch1_1ff
+	.globl	invalid_segment_patch2_1ff
+invalid_segment_patch1_1ff:	cmp	%l4, 0x1ff
+invalid_segment_patch2_1ff:	mov	0x1ff, %l3
 
 	.align	4
-	.globl	C_LABEL(num_context_patch1_16), C_LABEL(num_context_patch2_16)
-C_LABEL(num_context_patch1_16):		mov	0x10, %l7
-C_LABEL(num_context_patch2_16):		mov	0x10, %l7
+	.globl	num_context_patch1_16, num_context_patch2_16
+num_context_patch1_16:		mov	0x10, %l7
+num_context_patch2_16:		mov	0x10, %l7
 
 	.align	4
-	.globl	C_LABEL(vac_linesize_patch_32)
-C_LABEL(vac_linesize_patch_32):		subcc	%l7, 32, %l7
+	.globl	vac_linesize_patch_32
+vac_linesize_patch_32:		subcc	%l7, 32, %l7
 
 	.align	4
-	.globl	C_LABEL(vac_hwflush_patch1_on), C_LABEL(vac_hwflush_patch2_on)
+	.globl	vac_hwflush_patch1_on, vac_hwflush_patch2_on
 
 /*
  * Ugly, but we cant use hardware flushing on the sun4 and we'd require
  * two instructions (Anton)
  */
 #ifdef CONFIG_SUN4
-C_LABEL(vac_hwflush_patch1_on):		nop
+vac_hwflush_patch1_on:		nop
 #else
-C_LABEL(vac_hwflush_patch1_on):		addcc	%l7, -PAGE_SIZE, %l7
+vac_hwflush_patch1_on:		addcc	%l7, -PAGE_SIZE, %l7
 #endif
 
-C_LABEL(vac_hwflush_patch2_on):		sta	%g0, [%l3 + %l7] ASI_HWFLUSHSEG
+vac_hwflush_patch2_on:		sta	%g0, [%l3 + %l7] ASI_HWFLUSHSEG
 
-	.globl	C_LABEL(invalid_segment_patch1), C_LABEL(invalid_segment_patch2)
-	.globl	C_LABEL(num_context_patch1), C_LABEL(num_context_patch2)
-	.globl	C_LABEL(vac_linesize_patch), C_LABEL(vac_hwflush_patch1)
-	.globl	C_LABEL(vac_hwflush_patch2)
+	.globl	invalid_segment_patch1, invalid_segment_patch2
+	.globl	num_context_patch1, num_context_patch2
+	.globl	vac_linesize_patch, vac_hwflush_patch1
+	.globl	vac_hwflush_patch2
 
 	.align	4
 	.globl	sun4c_fault
@@ -886,8 +885,8 @@ C_LABEL(vac_hwflush_patch2_on):		sta	%g0
 ! We want error in %l5, vaddr in %l6
 sun4c_fault:
 #ifdef CONFIG_SUN4
-	sethi	%hi(C_LABEL(sun4c_memerr_reg)), %l4
-	ld	[%l4+%lo(C_LABEL(sun4c_memerr_reg))], %l4  ! memerr ctrl reg addr
+	sethi	%hi(sun4c_memerr_reg), %l4
+	ld	[%l4+%lo(sun4c_memerr_reg)], %l4  ! memerr ctrl reg addr
 	ld	[%l4], %l6		! memerr ctrl reg
 	ld	[%l4 + 4], %l5		! memerr vaddr reg
 	andcc	%l6, 0x80, %g0		! check for error type
@@ -895,7 +894,7 @@ sun4c_fault:
 	be	0f			! normal error
 	 sethi	%hi(AC_BUS_ERROR), %l4	! bus err reg addr
 
-	call	C_LABEL(prom_halt)	! something weird happened
+	call	prom_halt	! something weird happened
 					! what exactly did happen?
 					! what should we do here?
 
@@ -959,12 +958,12 @@ sun4c_fault:
 	/* Test for NULL pte_t * in vmalloc area. */
 	sethi   %hi(VMALLOC_START), %l4
 	cmp     %l5, %l4
-	blu,a   C_LABEL(invalid_segment_patch1)
+	blu,a   invalid_segment_patch1
 	 lduXa	[%l5] ASI_SEGMAP, %l4
 
-	sethi   %hi(C_LABEL(swapper_pg_dir)), %l4
+	sethi   %hi(swapper_pg_dir), %l4
 	srl     %l5, SUN4C_PGDIR_SHIFT, %l6
-	or      %l4, %lo(C_LABEL(swapper_pg_dir)), %l4
+	or      %l4, %lo(swapper_pg_dir), %l4
 	sll     %l6, 2, %l6
 	ld      [%l4 + %l6], %l4
 #ifdef CONFIG_SUN4
@@ -976,15 +975,15 @@ sun4c_fault:
 	be      sun4c_fault_fromuser
 	 lduXa  [%l5] ASI_SEGMAP, %l4
 
-C_LABEL(invalid_segment_patch1):
+invalid_segment_patch1:
 	cmp	%l4, 0x7f
 	bne	1f
-	 sethi	%hi(C_LABEL(sun4c_kfree_ring)), %l4
-	or	%l4, %lo(C_LABEL(sun4c_kfree_ring)), %l4
+	 sethi	%hi(sun4c_kfree_ring), %l4
+	or	%l4, %lo(sun4c_kfree_ring), %l4
 	ld	[%l4 + 0x18], %l3
 	deccc	%l3			! do we have a free entry?
 	bcs,a	2f			! no, unmap one.
-	 sethi	%hi(C_LABEL(sun4c_kernel_ring)), %l4
+	 sethi	%hi(sun4c_kernel_ring), %l4
 
 	st	%l3, [%l4 + 0x18]	! sun4c_kfree_ring.num_entries--
 
@@ -997,8 +996,8 @@ C_LABEL(invalid_segment_patch1):
 	st	%l7, [%l3 + 0x04]	! next->prev = entry->prev
 	st	%l3, [%l7 + 0x00]	! entry->prev->next = next
 
-	sethi	%hi(C_LABEL(sun4c_kernel_ring)), %l4
-	or	%l4, %lo(C_LABEL(sun4c_kernel_ring)), %l4
+	sethi	%hi(sun4c_kernel_ring), %l4
+	or	%l4, %lo(sun4c_kernel_ring), %l4
 					! head = &sun4c_kernel_ring.ringhd
 
 	ld	[%l4 + 0x00], %l7	! head->next
@@ -1016,7 +1015,7 @@ C_LABEL(invalid_segment_patch1):
 	 ld	[%l6 + 0x08], %l5
 
 2:
-	or	%l4, %lo(C_LABEL(sun4c_kernel_ring)), %l4
+	or	%l4, %lo(sun4c_kernel_ring), %l4
 					! head = &sun4c_kernel_ring.ringhd
 
 	ld	[%l4 + 0x04], %l6	! entry = head->prev
@@ -1030,11 +1029,11 @@ C_LABEL(invalid_segment_patch1):
 	sethi	%hi((64 * 1024)), %l7
 #endif
 9:
-C_LABEL(vac_hwflush_patch1):
-C_LABEL(vac_linesize_patch):
+vac_hwflush_patch1:
+vac_linesize_patch:
 	subcc	%l7, 16, %l7
 	bne	9b
-C_LABEL(vac_hwflush_patch2):
+vac_hwflush_patch2:
 	 sta	%g0, [%l3 + %l7] ASI_FLUSHSEG
 
 	st	%l5, [%l6 + 0x08]	! entry->vaddr = address
@@ -1055,7 +1054,7 @@ C_LABEL(vac_hwflush_patch2):
 	mov	%l3, %l5		! address = tmp
 
 4:
-C_LABEL(num_context_patch1):
+num_context_patch1:
 	mov	0x08, %l7
 
 	ld	[%l6 + 0x08], %l4
@@ -1072,7 +1071,7 @@ C_LABEL(num_context_patch1):
 3:	deccc	%l7
 	sethi	%hi(AC_CONTEXT), %l3
 	stba	%l7, [%l3] ASI_CONTROL
-C_LABEL(invalid_segment_patch2):
+invalid_segment_patch2:
 	mov	0x7f, %l3
 	stXa	%l3, [%l5] ASI_SEGMAP
 	andn	%l4, 0x1ff, %l3
@@ -1108,12 +1107,12 @@ C_LABEL(invalid_segment_patch2):
 	 add	%l5, %l4, %l5
 
 	b	7f
-	 sethi	%hi(C_LABEL(sun4c_kernel_faults)), %l4
+	 sethi	%hi(sun4c_kernel_faults), %l4
 
 1:
 	srl	%l5, SUN4C_PGDIR_SHIFT, %l3
-	sethi	%hi(C_LABEL(swapper_pg_dir)), %l4
-	or	%l4, %lo(C_LABEL(swapper_pg_dir)), %l4
+	sethi	%hi(swapper_pg_dir), %l4
+	or	%l4, %lo(swapper_pg_dir), %l4
 	sll	%l3, 2, %l3
 	ld	[%l4 + %l3], %l4
 #ifndef CONFIG_SUN4
@@ -1137,11 +1136,11 @@ C_LABEL(invalid_segment_patch2):
 	bne	2b
 	 add	%l5, %l4, %l5
 
-	sethi	%hi(C_LABEL(sun4c_kernel_faults)), %l4
+	sethi	%hi(sun4c_kernel_faults), %l4
 7:
-	ld	[%l4 + %lo(C_LABEL(sun4c_kernel_faults))], %l3
+	ld	[%l4 + %lo(sun4c_kernel_faults)], %l3
 	inc	%l3
-	st	%l3, [%l4 + %lo(C_LABEL(sun4c_kernel_faults))]
+	st	%l3, [%l4 + %lo(sun4c_kernel_faults)]
 
 	/* Restore condition codes */
 	wr	%l0, 0x0, %psr
@@ -1163,14 +1162,14 @@ sun4c_fault_fromuser:
 	wr	%l0, PSR_ET, %psr
 	WRITE_PAUSE
 
-	call	C_LABEL(do_sun4c_fault)
+	call	do_sun4c_fault
 	 add	%sp, STACKFRAME_SZ, %o0	! arg1 = pt_regs ptr
 
 	RESTORE_ALL
 
 	.align	4
-	.globl	C_LABEL(srmmu_fault)
-C_LABEL(srmmu_fault):
+	.globl	srmmu_fault
+srmmu_fault:
 	mov	0x400, %l5
 	mov	0x300, %l4
 
@@ -1197,7 +1196,7 @@ C_LABEL(srmmu_fault):
 	wr	%l0, PSR_ET, %psr
 	WRITE_PAUSE
 
-	call	C_LABEL(do_sparc_fault)
+	call	do_sparc_fault
 	 add	%sp, STACKFRAME_SZ, %o0	! arg1 = pt_regs ptr
 
 	RESTORE_ALL
@@ -1207,19 +1206,19 @@ C_LABEL(srmmu_fault):
 	 * like indir_syscall(scall_num, arg0, arg1, arg2...);  etc.
 	 * This is complete brain damage.
 	 */
-	.globl	C_LABEL(sunos_indir)
-C_LABEL(sunos_indir):
+	.globl	sunos_indir
+sunos_indir:
 	mov	%o7, %l4
 	cmp	%o0, NR_SYSCALLS
 	blu,a	1f
 	 sll	%o0, 0x2, %o0
 
-	sethi	%hi(C_LABEL(sunos_nosys)), %l6
+	sethi	%hi(sunos_nosys), %l6
 	b	2f
-	 or	%l6, %lo(C_LABEL(sunos_nosys)), %l6
+	 or	%l6, %lo(sunos_nosys), %l6
 
 1:
-	set	C_LABEL(sunos_sys_table), %l7
+	set	sunos_sys_table, %l7
 	ld	[%l7 + %o0], %l6
 
 2:	
@@ -1233,17 +1232,17 @@ C_LABEL(sunos_indir):
 #endif
 
 	.align	4
-	.globl	C_LABEL(sys_nis_syscall)
-C_LABEL(sys_nis_syscall):
+	.globl	sys_nis_syscall
+sys_nis_syscall:
 	mov	%o7, %l5
 	add	%sp, STACKFRAME_SZ, %o0		! pt_regs *regs arg
-	call	C_LABEL(c_sys_nis_syscall)
+	call	c_sys_nis_syscall
 	 mov	%l5, %o7
 
 	.align 4
-	.globl	C_LABEL(sys_ptrace)
-C_LABEL(sys_ptrace):
-	call	C_LABEL(do_ptrace)
+	.globl	sys_ptrace
+sys_ptrace:
+	call	do_ptrace
 	 add	%sp, STACKFRAME_SZ, %o0
 
 	ld	[%curptr + TI_FLAGS], %l5
@@ -1251,49 +1250,49 @@ C_LABEL(sys_ptrace):
 	be	1f
 	 nop
 
-	call	C_LABEL(syscall_trace)
+	call	syscall_trace
 	 nop
 
 1:
 	RESTORE_ALL
 
 	.align	4
-	.globl	C_LABEL(sys_execve)
-C_LABEL(sys_execve):
+	.globl	sys_execve
+sys_execve:
 	mov	%o7, %l5
 	add	%sp, STACKFRAME_SZ, %o0		! pt_regs *regs arg
-	call	C_LABEL(sparc_execve)
+	call	sparc_execve
 	 mov	%l5, %o7
 
 	.align	4
-	.globl	C_LABEL(sys_pipe)
-C_LABEL(sys_pipe):
+	.globl	sys_pipe
+sys_pipe:
 	mov	%o7, %l5
 	add	%sp, STACKFRAME_SZ, %o0		! pt_regs *regs arg
-	call	C_LABEL(sparc_pipe)
+	call	sparc_pipe
 	 mov	%l5, %o7
 
 	.align	4
-	.globl	C_LABEL(sys_sigaltstack)
-C_LABEL(sys_sigaltstack):
+	.globl	sys_sigaltstack
+sys_sigaltstack:
 	mov	%o7, %l5
 	mov	%fp, %o2
-	call	C_LABEL(do_sigaltstack)
+	call	do_sigaltstack
 	 mov	%l5, %o7
 
 	.align	4
-	.globl	C_LABEL(sys_sigstack)
-C_LABEL(sys_sigstack):
+	.globl	sys_sigstack
+sys_sigstack:
 	mov	%o7, %l5
 	mov	%fp, %o2
-	call	C_LABEL(do_sys_sigstack)
+	call	do_sys_sigstack
 	 mov	%l5, %o7
 
 	.align	4
-	.globl	C_LABEL(sys_sigpause)
-C_LABEL(sys_sigpause):
+	.globl	sys_sigpause
+sys_sigpause:
 	/* Note: %o0 already has correct value... */
-	call	C_LABEL(do_sigpause)
+	call	do_sigpause
 	 add	%sp, STACKFRAME_SZ, %o1
 
 	ld	[%curptr + TI_FLAGS], %l5
@@ -1301,7 +1300,7 @@ C_LABEL(sys_sigpause):
 	be	1f
 	 nop
 
-	call	C_LABEL(syscall_trace)
+	call	syscall_trace
 	 nop
 
 1:
@@ -1309,9 +1308,9 @@ C_LABEL(sys_sigpause):
 	RESTORE_ALL
 
 	.align	4
-	.globl	C_LABEL(sys_sigsuspend)
-C_LABEL(sys_sigsuspend):
-	call	C_LABEL(do_sigsuspend)
+	.globl	sys_sigsuspend
+sys_sigsuspend:
+	call	do_sigsuspend
 	 add	%sp, STACKFRAME_SZ, %o0
 
 	ld	[%curptr + TI_FLAGS], %l5
@@ -1319,7 +1318,7 @@ C_LABEL(sys_sigsuspend):
 	be	1f
 	 nop
 
-	call	C_LABEL(syscall_trace)
+	call	syscall_trace
 	 nop
 
 1:
@@ -1327,10 +1326,10 @@ C_LABEL(sys_sigsuspend):
 	RESTORE_ALL
 
 	.align	4
-	.globl	C_LABEL(sys_rt_sigsuspend)
-C_LABEL(sys_rt_sigsuspend):
+	.globl	sys_rt_sigsuspend
+sys_rt_sigsuspend:
 	/* Note: %o0, %o1 already have correct value... */
-	call	C_LABEL(do_rt_sigsuspend)
+	call	do_rt_sigsuspend
 	 add	%sp, STACKFRAME_SZ, %o2
 
 	ld	[%curptr + TI_FLAGS], %l5
@@ -1338,7 +1337,7 @@ C_LABEL(sys_rt_sigsuspend):
 	be	1f
 	 nop
 
-	call	C_LABEL(syscall_trace)
+	call	syscall_trace
 	 nop
 
 1:
@@ -1346,9 +1345,9 @@ C_LABEL(sys_rt_sigsuspend):
 	RESTORE_ALL
 
 	.align	4
-	.globl	C_LABEL(sys_sigreturn)
-C_LABEL(sys_sigreturn):
-	call	C_LABEL(do_sigreturn)
+	.globl	sys_sigreturn
+sys_sigreturn:
+	call	do_sigreturn
 	 add	%sp, STACKFRAME_SZ, %o0
 
 	ld	[%curptr + TI_FLAGS], %l5
@@ -1356,7 +1355,7 @@ C_LABEL(sys_sigreturn):
 	be	1f
 	 nop
 
-	call	C_LABEL(syscall_trace)
+	call	syscall_trace
 	 nop
 
 1:
@@ -1366,9 +1365,9 @@ C_LABEL(sys_sigreturn):
 	RESTORE_ALL
 
 	.align	4
-	.globl	C_LABEL(sys_rt_sigreturn)
-C_LABEL(sys_rt_sigreturn):
-	call	C_LABEL(do_rt_sigreturn)
+	.globl	sys_rt_sigreturn
+sys_rt_sigreturn:
+	call	do_rt_sigreturn
 	 add	%sp, STACKFRAME_SZ, %o0
 
 	ld	[%curptr + TI_FLAGS], %l5
@@ -1376,7 +1375,7 @@ C_LABEL(sys_rt_sigreturn):
 	be	1f
 	 nop
 
-	call	C_LABEL(syscall_trace)
+	call	syscall_trace
 	 nop
 
 1:
@@ -1391,8 +1390,8 @@ C_LABEL(sys_rt_sigreturn):
 	 * XXX code just like on sparc64... -DaveM
 	 */
 	.align	4
-	.globl	C_LABEL(sys_fork), flush_patch_two
-C_LABEL(sys_fork):
+	.globl	sys_fork, flush_patch_two
+sys_fork:
 	mov	%o7, %l5
 flush_patch_two:
 	FLUSH_ALL_KERNEL_WINDOWS;
@@ -1406,12 +1405,12 @@ flush_patch_two:
 	std	%g4, [%o4 + AOFF_task_thread + AOFF_thread_fork_kpsr]
 	add	%sp, STACKFRAME_SZ, %o2		! arg2:	pt_regs ptr
 	mov	0, %o3
-	call	C_LABEL(sparc_do_fork)
+	call	sparc_do_fork
 	 mov	%l5, %o7
 
 	/* Whee, kernel threads! */
-	.globl	C_LABEL(sys_clone), flush_patch_three
-C_LABEL(sys_clone):
+	.globl	sys_clone, flush_patch_three
+sys_clone:
 	mov	%o7, %l5
 flush_patch_three:
 	FLUSH_ALL_KERNEL_WINDOWS;
@@ -1430,12 +1429,12 @@ flush_patch_three:
 	std	%g4, [%o4 + AOFF_task_thread + AOFF_thread_fork_kpsr]
 	add	%sp, STACKFRAME_SZ, %o2		! arg2:	pt_regs ptr
 	mov	0, %o3
-	call	C_LABEL(sparc_do_fork)
+	call	sparc_do_fork
 	 mov	%l5, %o7
 
 	/* Whee, real vfork! */
-	.globl	C_LABEL(sys_vfork), flush_patch_four
-C_LABEL(sys_vfork):
+	.globl	sys_vfork, flush_patch_four
+sys_vfork:
 flush_patch_four:
 	FLUSH_ALL_KERNEL_WINDOWS;
 	ld	[%curptr + TI_TASK], %o4
@@ -1447,16 +1446,16 @@ flush_patch_four:
 	sethi	%hi(0x4000 | 0x0100 | SIGCHLD), %o0
 	mov	%fp, %o1
 	or	%o0, %lo(0x4000 | 0x0100 | SIGCHLD), %o0
-	sethi	%hi(C_LABEL(sparc_do_fork)), %l1
+	sethi	%hi(sparc_do_fork), %l1
 	mov	0, %o3
-	jmpl	%l1 + %lo(C_LABEL(sparc_do_fork)), %g0
+	jmpl	%l1 + %lo(sparc_do_fork), %g0
 	 add	%sp, STACKFRAME_SZ, %o2
 
         .align  4
 linux_sparc_ni_syscall:
-	sethi   %hi(C_LABEL(sys_ni_syscall)), %l7
+	sethi   %hi(sys_ni_syscall), %l7
 	b       syscall_is_too_hard
-	 or     %l7, %lo(C_LABEL(sys_ni_syscall)), %l7
+	 or     %l7, %lo(sys_ni_syscall), %l7
 
 linux_fast_syscall:
 	andn	%l7, 3, %l7
@@ -1467,7 +1466,7 @@ linux_fast_syscall:
 	 mov	%i3, %o3
 
 linux_syscall_trace:
-	call	C_LABEL(syscall_trace)
+	call	syscall_trace
 	 nop
 	mov	%i0, %o0
 	mov	%i1, %o1
@@ -1476,11 +1475,11 @@ linux_syscall_trace:
 	b	2f
 	 mov	%i4, %o4
 
-	.globl	C_LABEL(ret_from_fork)
-C_LABEL(ret_from_fork):
+	.globl	ret_from_fork
+ret_from_fork:
 	call	schedule_tail
 	 mov	%g3, %o0
-	b	C_LABEL(ret_sys_call)
+	b	ret_sys_call
 	 ld	[%sp + STACKFRAME_SZ + PT_I0], %o0
 
 	/* Linux native and SunOS system calls enter here... */
@@ -1518,8 +1517,8 @@ syscall_is_too_hard:
 
 	st	%o0, [%sp + STACKFRAME_SZ + PT_I0]
 
-	.globl	C_LABEL(ret_sys_call)
-C_LABEL(ret_sys_call):
+	.globl	ret_sys_call
+ret_sys_call:
 	ld	[%curptr + TI_FLAGS], %l6
 	cmp	%o0, -ENOIOCTLCMD
 	ld	[%sp + STACKFRAME_SZ + PT_PSR], %g3
@@ -1554,7 +1553,7 @@ C_LABEL(ret_sys_call):
 	 st	%l2, [%sp + STACKFRAME_SZ + PT_NPC]
 
 linux_syscall_trace2:
-	call	C_LABEL(syscall_trace)
+	call	syscall_trace
 	 add	%l1, 0x4, %l2			/* npc = npc+4 */
 	st	%l1, [%sp + STACKFRAME_SZ + PT_PC]
 	b	ret_trap_entry
@@ -1595,7 +1594,7 @@ solaris_syscall:
 	nop
 	mov	%i0, %l5
 
-	call	C_LABEL(do_solaris_syscall)
+	call	do_solaris_syscall
 	 add	%sp, STACKFRAME_SZ, %o0
 
 	st	%o0, [%sp + STACKFRAME_SZ + PT_I0]
@@ -1651,7 +1650,7 @@ sunos_syscall:
 	nop
 	nop
 	mov	%i0, %l5
-	call	C_LABEL(do_sunos_syscall)
+	call	do_sunos_syscall
 	 add	%sp, STACKFRAME_SZ, %o0
 #endif
 
@@ -1664,7 +1663,7 @@ bsd_syscall:
 	blu,a	1f
 	 sll	%g1, 2, %l4
 
-	set	C_LABEL(sys_ni_syscall), %l7
+	set	sys_ni_syscall, %l7
 	b	bsd_is_too_hard
 	 nop
 
@@ -1707,8 +1706,8 @@ bsd_is_too_hard:
 	 */
 	sub	%g0, %o0, %o0
 #if 0 /* XXX todo XXX */
-	sethi	%hi(C_LABEL(bsd_xlatb_rorl), %o3
-	or	%o3, %lo(C_LABEL(bsd_xlatb_rorl)), %o3
+	sethi	%hi(bsd_xlatb_rorl), %o3
+	or	%o3, %lo(bsd_xlatb_rorl), %o3
 	sll	%o0, 2, %o0
 	ld	[%o3 + %o0], %o0
 #endif
@@ -1731,8 +1730,8 @@ bsd_is_too_hard:
  *             void *fpqueue, unsigned long *fpqdepth)
  */
 
-	.globl	C_LABEL(fpsave)
-C_LABEL(fpsave):
+	.globl	fpsave
+fpsave:
 	st	%fsr, [%o1]	! this can trap on us if fpu is in bogon state
 	ld	[%o1], %g1
 	set	0x2000, %g4
@@ -1782,13 +1781,13 @@ fpsave_catch:
 	 st	%fsr, [%o1]
 
 fpsave_catch2:
-	b	C_LABEL(fpsave) + 4
+	b	fpsave + 4
 	 st	%fsr, [%o1]
 
 	/* void fpload(unsigned long *fpregs, unsigned long *fsr); */
 
-	.globl	C_LABEL(fpload)
-C_LABEL(fpload):
+	.globl	fpload
+fpload:
 	ldd	[%o0 + 0x00], %f0
 	ldd	[%o0 + 0x08], %f2
 	ldd	[%o0 + 0x10], %f4
@@ -1809,8 +1808,8 @@ C_LABEL(fpload):
 	retl
 	 nop
 
-	.globl	C_LABEL(ndelay)
-C_LABEL(ndelay):
+	.globl	ndelay
+ndelay:
 	save	%sp, -STACKFRAME_SZ, %sp
 	mov	%i0, %o0
 	call	.umul
@@ -1818,8 +1817,8 @@ C_LABEL(ndelay):
 	ba	delay_continue
 	 nop
 
-	.globl	C_LABEL(udelay)
-C_LABEL(udelay):
+	.globl	udelay
+udelay:
 	save	%sp, -STACKFRAME_SZ, %sp
 	mov	%i0, %o0
 	sethi	%hi(0x10c6), %o1
@@ -1827,12 +1826,12 @@ C_LABEL(udelay):
 	 or	%o1, %lo(0x10c6), %o1
 delay_continue:
 #ifndef CONFIG_SMP
-	sethi	%hi(C_LABEL(loops_per_jiffy)), %o3
+	sethi	%hi(loops_per_jiffy), %o3
 	call	.umul
-	 ld	[%o3 + %lo(C_LABEL(loops_per_jiffy))], %o1
+	 ld	[%o3 + %lo(loops_per_jiffy)], %o1
 #else
 	GET_PROCESSOR_OFFSET(o4, o2)
-	set	C_LABEL(cpu_data), %o3
+	set	cpu_data, %o3
 	call	.umul
 	 ld	[%o3 + %o4], %o1
 #endif
@@ -1858,14 +1857,14 @@ breakpoint_trap:
 	WRITE_PAUSE
 
 	st	%i0, [%sp + STACKFRAME_SZ + PT_G0] ! for restarting syscalls
-	call	C_LABEL(sparc_breakpoint)
+	call	sparc_breakpoint
 	 add	%sp, STACKFRAME_SZ, %o0
 
 	RESTORE_ALL
 
 	.align	4
-	.globl	C_LABEL(__handle_exception), flush_patch_exception
-C_LABEL(__handle_exception):
+	.globl	__handle_exception, flush_patch_exception
+__handle_exception:
 flush_patch_exception:
 	FLUSH_ALL_KERNEL_WINDOWS;
 	ldd	[%o0], %o6
@@ -1873,7 +1872,7 @@ flush_patch_exception:
 	 mov	1, %g1				! signal EFAULT condition
 
 	.align	4
-	.globl	C_LABEL(kill_user_windows), kuw_patch1_7win
+	.globl	kill_user_windows, kuw_patch1_7win
 	.globl	kuw_patch1
 kuw_patch1_7win:	sll	%o3, 6, %o3
 
@@ -1881,7 +1880,7 @@ kuw_patch1_7win:	sll	%o3, 6, %o3
 	 * case scenerio, it is several times better than taking the
 	 * traps with the old method of just doing flush_user_windows().
 	 */
-C_LABEL(kill_user_windows):
+kill_user_windows:
 	ld	[%g6 + TI_UWINMASK], %o0	! get current umask
 	orcc	%g0, %o0, %g0			! if no bits set, we are done
 	be	3f				! nothing to do
@@ -1911,8 +1910,8 @@ kuw_patch1:
 	 st	%g0, [%g6 + TI_W_SAVED]		! no windows saved
 
 	.align	4
-	.globl	C_LABEL(restore_current)
-C_LABEL(restore_current):
+	.globl	restore_current
+restore_current:
 	LOAD_CURRENT(g6, o0)
 	retl
 	 nop
@@ -1932,8 +1931,8 @@ linux_trap_ipi15_pcic:
 	 * The busy loop is necessary because the PIO error
 	 * sometimes does not go away quickly and we trap again.
 	 */
-	sethi	%hi(C_LABEL(pcic_regs)), %o1
-	ld	[%o1 + %lo(C_LABEL(pcic_regs))], %o2
+	sethi	%hi(pcic_regs), %o1
+	ld	[%o1 + %lo(pcic_regs)], %o2
 
 	! Get pending status for printouts later.
 	ld	[%o2 + PCI_SYS_INT_PENDING], %o0
@@ -1952,12 +1951,12 @@ linux_trap_ipi15_pcic:
 	wr	%l4, PSR_ET, %psr
 	WRITE_PAUSE
 
-	call	C_LABEL(pcic_nmi)
+	call	pcic_nmi
 	 add	%sp, STACKFRAME_SZ, %o1	! struct pt_regs *regs
 	RESTORE_ALL
 
-	.globl	C_LABEL(pcic_nmi_trap_patch)
-C_LABEL(pcic_nmi_trap_patch):
+	.globl	pcic_nmi_trap_patch
+pcic_nmi_trap_patch:
 	sethi	%hi(linux_trap_ipi15_pcic), %l3
 	jmpl	%l3 + %lo(linux_trap_ipi15_pcic), %g0
 	 rd	%psr, %l0
--- diff/arch/sparc/kernel/etrap.S	2004-01-19 10:22:55.000000000 +0000
+++ source/arch/sparc/kernel/etrap.S	2004-02-23 13:56:39.000000000 +0000
@@ -5,7 +5,6 @@
  * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
  */
 
-#include <asm/cprefix.h>
 #include <asm/head.h>
 #include <asm/asi.h>
 #include <asm/contregs.h>
@@ -217,9 +216,9 @@ tsetup_patch6:
 	/* Call MMU-architecture dependent stack checking
 	 * routine.
 	 */
-	.globl	C_LABEL(tsetup_mmu_patchme)
-C_LABEL(tsetup_mmu_patchme):
-	b	C_LABEL(tsetup_sun4c_stackchk)
+	.globl	tsetup_mmu_patchme
+tsetup_mmu_patchme:
+	b	tsetup_sun4c_stackchk
 	 andcc	%sp, 0x7, %g0
 
 	/* Architecture specific stack checking routines.  When either
@@ -229,8 +228,8 @@ C_LABEL(tsetup_mmu_patchme):
 	 */
 #define glob_tmp     g1
 
-	.globl	C_LABEL(tsetup_sun4c_stackchk)
-C_LABEL(tsetup_sun4c_stackchk):
+	.globl	tsetup_sun4c_stackchk
+tsetup_sun4c_stackchk:
 	/* Done by caller: andcc %sp, 0x7, %g0 */
 	bne	trap_setup_user_stack_is_bolixed
 	 sra	%sp, 29, %glob_tmp
@@ -276,8 +275,8 @@ tsetup_sun4c_onepage:
 	jmpl	%t_retpc + 0x8, %g0
 	 mov	%t_kstack, %sp
 
-	.globl	C_LABEL(tsetup_srmmu_stackchk)
-C_LABEL(tsetup_srmmu_stackchk):
+	.globl	tsetup_srmmu_stackchk
+tsetup_srmmu_stackchk:
 	/* Check results of callers andcc %sp, 0x7, %g0 */
 	bne	trap_setup_user_stack_is_bolixed
 	 sethi   %hi(PAGE_OFFSET), %glob_tmp
--- diff/arch/sparc/kernel/head.S	2003-05-21 11:50:14.000000000 +0100
+++ source/arch/sparc/kernel/head.S	2004-02-23 13:56:39.000000000 +0000
@@ -14,7 +14,6 @@
 #include <linux/config.h>
 #include <linux/init.h>
 
-#include <asm/cprefix.h>
 #include <asm/head.h>
 #include <asm/asi.h>
 #include <asm/contregs.h>
@@ -34,18 +33,18 @@
  */
 
 	.align 4
-        .globl  C_LABEL(cputyp)
-C_LABEL(cputyp):
+        .globl  cputyp
+cputyp:
         .word   1
 
 	.align 4
-	.globl C_LABEL(cputypval)
-C_LABEL(cputypval):
+	.globl cputypval
+cputypval:
 	.asciz "sun4c"
 	.ascii "     "
 
-C_LABEL(cputypvalend):
-C_LABEL(cputypvallen) = C_LABEL(cputypvar) - C_LABEL(cputypval)
+cputypvalend:
+cputypvallen = cputypvar - cputypval
 
 	.align 4
 /*
@@ -56,12 +55,12 @@ C_LABEL(cputypvallen) = C_LABEL(cputypva
 /* Uh, actually Linus it is I who cannot spell. Too much murky
  * Sparc assembly will do this to ya.
  */
-C_LABEL(cputypvar):
+cputypvar:
 	.asciz "compatability"
 
 /* Tested on SS-5, SS-10. Probably someone at Sun applied a spell-checker. */
 	.align 4
-C_LABEL(cputypvar_sun4m):
+cputypvar_sun4m:
 	.asciz "compatible"
 
 	.align 4
@@ -88,14 +87,14 @@ sun4e_notsup:
 	/* The Sparc trap table, bootloader gives us control at _start. */
 	.text
 	.globl	start, _stext, _start, __stext
-	.globl  C_LABEL(trapbase)
+	.globl  trapbase
 _start:   /* danger danger */
 __stext:
 _stext:
 start:
-C_LABEL(trapbase):
+trapbase:
 #ifdef CONFIG_SMP
-C_LABEL(trapbase_cpu0):
+trapbase_cpu0:
 #endif
 /* We get control passed to us here at t_zero. */
 t_zero:	b gokernel; nop; nop; nop;
@@ -202,13 +201,13 @@ t_badfc:BAD_TRAP(0xfc) BAD_TRAP(0xfd)
 dbtrap:	BAD_TRAP(0xfe)                      /* Debugger/PROM breakpoint #1   */
 dbtrap2:BAD_TRAP(0xff)                      /* Debugger/PROM breakpoint #2   */	
 
-	.globl	C_LABEL(end_traptable)
-C_LABEL(end_traptable):
+	.globl	end_traptable
+end_traptable:
 
 #ifdef CONFIG_SMP
 	/* Trap tables for the other cpus. */
-	.globl	C_LABEL(trapbase_cpu1), C_LABEL(trapbase_cpu2), C_LABEL(trapbase_cpu3)
-C_LABEL(trapbase_cpu1):
+	.globl	trapbase_cpu1, trapbase_cpu2, trapbase_cpu3
+trapbase_cpu1:
 	BAD_TRAP(0x0) SRMMU_TFAULT TRAP_ENTRY(0x2, bad_instruction)
 	TRAP_ENTRY(0x3, priv_instruction) TRAP_ENTRY(0x4, fpd_trap_handler)
 	WINDOW_SPILL WINDOW_FILL TRAP_ENTRY(0x7, mna_handler)
@@ -276,7 +275,7 @@ C_LABEL(trapbase_cpu1):
 	BAD_TRAP(0xf7) BAD_TRAP(0xf8) BAD_TRAP(0xf9) BAD_TRAP(0xfa) BAD_TRAP(0xfb)
 	BAD_TRAP(0xfc) BAD_TRAP(0xfd) BAD_TRAP(0xfe) BAD_TRAP(0xff)
 
-C_LABEL(trapbase_cpu2):
+trapbase_cpu2:
 	BAD_TRAP(0x0) SRMMU_TFAULT TRAP_ENTRY(0x2, bad_instruction)
 	TRAP_ENTRY(0x3, priv_instruction) TRAP_ENTRY(0x4, fpd_trap_handler)
 	WINDOW_SPILL WINDOW_FILL TRAP_ENTRY(0x7, mna_handler)
@@ -344,7 +343,7 @@ C_LABEL(trapbase_cpu2):
 	BAD_TRAP(0xf7) BAD_TRAP(0xf8) BAD_TRAP(0xf9) BAD_TRAP(0xfa) BAD_TRAP(0xfb)
 	BAD_TRAP(0xfc) BAD_TRAP(0xfd) BAD_TRAP(0xfe) BAD_TRAP(0xff)
 
-C_LABEL(trapbase_cpu3):
+trapbase_cpu3:
 	BAD_TRAP(0x0) SRMMU_TFAULT TRAP_ENTRY(0x2, bad_instruction)
 	TRAP_ENTRY(0x3, priv_instruction) TRAP_ENTRY(0x4, fpd_trap_handler)
 	WINDOW_SPILL WINDOW_FILL TRAP_ENTRY(0x7, mna_handler)
@@ -418,25 +417,25 @@ C_LABEL(trapbase_cpu3):
 /* This was the only reasonable way I could think of to properly align
  * these page-table data structures.
  */
-	.globl C_LABEL(pg0), C_LABEL(pg1), C_LABEL(pg2), C_LABEL(pg3)
-	.globl C_LABEL(empty_bad_page)
-	.globl C_LABEL(empty_bad_page_table)
-	.globl C_LABEL(empty_zero_page)
-	.globl C_LABEL(swapper_pg_dir)
-C_LABEL(swapper_pg_dir):		.skip PAGE_SIZE
-C_LABEL(pg0):				.skip PAGE_SIZE
-C_LABEL(pg1):				.skip PAGE_SIZE
-C_LABEL(pg2):				.skip PAGE_SIZE
-C_LABEL(pg3):				.skip PAGE_SIZE
-C_LABEL(empty_bad_page):		.skip PAGE_SIZE
-C_LABEL(empty_bad_page_table):		.skip PAGE_SIZE
-C_LABEL(empty_zero_page):		.skip PAGE_SIZE
-
-	.global C_LABEL(root_flags)
-	.global C_LABEL(ram_flags)
-	.global C_LABEL(root_dev)
-	.global C_LABEL(sparc_ramdisk_image)
-	.global C_LABEL(sparc_ramdisk_size)
+	.globl pg0, pg1, pg2, pg3
+	.globl empty_bad_page
+	.globl empty_bad_page_table
+	.globl empty_zero_page
+	.globl swapper_pg_dir
+swapper_pg_dir:		.skip PAGE_SIZE
+pg0:			.skip PAGE_SIZE
+pg1:			.skip PAGE_SIZE
+pg2:			.skip PAGE_SIZE
+pg3:			.skip PAGE_SIZE
+empty_bad_page:		.skip PAGE_SIZE
+empty_bad_page_table:	.skip PAGE_SIZE
+empty_zero_page:	.skip PAGE_SIZE
+
+	.global root_flags
+	.global ram_flags
+	.global root_dev
+	.global sparc_ramdisk_image
+	.global sparc_ramdisk_size
 
 /* This stuff has to be in sync with SILO and other potential boot loaders
  * Fields should be kept upward compatible and whenever any change is made,
@@ -445,17 +444,17 @@ C_LABEL(empty_zero_page):		.skip PAGE_SI
 	.ascii	"HdrS"
 	.word	LINUX_VERSION_CODE
 	.half	0x0203		/* HdrS version */
-C_LABEL(root_flags):
+root_flags:
 	.half	1
-C_LABEL(root_dev):
+root_dev:
 	.half	0
-C_LABEL(ram_flags):
+ram_flags:
 	.half	0
-C_LABEL(sparc_ramdisk_image):
+sparc_ramdisk_image:
 	.word	0
-C_LABEL(sparc_ramdisk_size):
+sparc_ramdisk_size:
 	.word	0
-	.word	C_LABEL(reboot_command)
+	.word	reboot_command
 	.word	0, 0, 0
 	.word	_end
 
@@ -517,7 +516,7 @@ copy_prom_lvl14:
 		/* DJHR
 		 * preserve our linked/calculated instructions
 		 */
-		set	C_LABEL(lvl14_save), %g1
+		set	lvl14_save, %g1
 		set	t_irq14, %g3
 		sub	%g1, %l6, %g1		! translate to physical
 		sub	%g3, %l6, %g3		! translate to physical
@@ -761,11 +760,11 @@ execute_in_high_mem:
 		mov	%l0, %o0		! put back romvec
 		mov	%l1, %o1		! and debug_vec
 
-		sethi	%hi( C_LABEL(prom_vector_p) ), %g1
-		st	%o0, [%g1 + %lo( C_LABEL(prom_vector_p) )]
+		sethi	%hi(prom_vector_p), %g1
+		st	%o0, [%g1 + %lo(prom_vector_p)]
 
-		sethi	%hi( C_LABEL(linux_dbvec) ), %g1
-		st	%o1, [%g1 + %lo( C_LABEL(linux_dbvec) )]
+		sethi	%hi(linux_dbvec), %g1
+		st	%o1, [%g1 + %lo(linux_dbvec)]
 
 		ld	[%o0 + 0x4], %o3
 		and	%o3, 0x3, %o5			! get the version
@@ -808,10 +807,10 @@ found_version:
 		 or	%g0, %g0, %o0		! next_node(0) = first_node
 		or	%o0, %g0, %g6
 
-		sethi	%hi( C_LABEL(cputypvar) ), %o1	! First node has cpu-arch
-		or	%o1, %lo( C_LABEL(cputypvar) ), %o1
-		sethi	%hi( C_LABEL(cputypval) ), %o2	! information, the string
-		or	%o2, %lo( C_LABEL(cputypval) ), %o2
+		sethi	%hi(cputypvar), %o1	! First node has cpu-arch
+		or	%o1, %lo(cputypvar), %o1
+		sethi	%hi(cputypval), %o2	! information, the string
+		or	%o2, %lo(cputypval), %o2
 		ld	[%l1], %l0		! 'compatibility' tells
 		ld	[%l0 + 0xc], %l0	! that we want 'sun4x' where
 		call	%l0			! x is one of '', 'c', 'm',
@@ -824,17 +823,17 @@ found_version:
 		 nop
 
 		or	%g6, %g0, %o0
-		sethi	%hi( C_LABEL(cputypvar_sun4m) ), %o1
-		or	%o1, %lo( C_LABEL(cputypvar_sun4m) ), %o1
-		sethi	%hi( C_LABEL(cputypval) ), %o2
-		or	%o2, %lo( C_LABEL(cputypval) ), %o2
+		sethi	%hi(cputypvar_sun4m), %o1
+		or	%o1, %lo(cputypvar_sun4m), %o1
+		sethi	%hi(cputypval), %o2
+		or	%o2, %lo(cputypval), %o2
 		ld	[%l1], %l0
 		ld	[%l0 + 0xc], %l0
 		call	%l0
 		 nop
 
 got_prop:
-		set	C_LABEL(cputypval), %o2
+		set	cputypval, %o2
 		ldub	[%o2 + 0x4], %l1
 
 		cmp	%l1, ' '
@@ -853,7 +852,7 @@ got_prop:
 		b	no_sun4u_here		! AIEEE, a V9 sun4u... Get our BIG BROTHER kernel :))
 		 nop
 
-1:		set	C_LABEL(cputypval), %l1
+1:		set	cputypval, %l1
 		ldub	[%l1 + 0x4], %l1
 		cmp	%l1, 'm'		! Test for sun4d, sun4e ?
 		be	sun4m_init
@@ -875,8 +874,8 @@ got_prop:
 
 sun4d_init:
 	/* Need to patch call to handler_irq */
-	set	C_LABEL(patch_handler_irq), %g4
-	set	C_LABEL(sun4d_handler_irq), %g5
+	set	patch_handler_irq, %g4
+	set	sun4d_handler_irq, %g5
 	sethi	%hi(0x40000000), %g3		! call
 	sub	%g5, %g4, %g5
 	srl	%g5, 2, %g5
@@ -997,8 +996,8 @@ sun4c_continue_boot:
  * show-time!
  */
 
-		sethi	%hi( C_LABEL(cputyp) ), %o0
-		st	%g4, [%o0 + %lo( C_LABEL(cputyp) )]
+		sethi	%hi(cputyp), %o0
+		st	%g4, [%o0 + %lo(cputyp)]
 
 		/* Turn on Supervisor, EnableFloating, and all the PIL bits.
 		 * Also puts us in register window zero with traps off.
@@ -1008,14 +1007,14 @@ sun4c_continue_boot:
 		WRITE_PAUSE
 
 		/* I want a kernel stack NOW! */
-		set	C_LABEL(init_thread_union), %g1
+		set	init_thread_union, %g1
 		set	(THREAD_SIZE - STACKFRAME_SZ), %g2
 		add	%g1, %g2, %sp
 		mov	0, %fp			/* And for good luck */
 
 		/* Zero out our BSS section. */
-		set	C_LABEL(__bss_start) , %o0	! First address of BSS
-		set	C_LABEL(end) , %o1		! Last address of BSS
+		set	__bss_start , %o0	! First address of BSS
+		set	end , %o1		! Last address of BSS
 		add	%o0, 0x1, %o0
 1:	
 		stb	%g0, [%o0]
@@ -1026,11 +1025,11 @@ sun4c_continue_boot:
 		/* Initialize the uwinmask value for init task just in case.
 		 * But first make current_set[boot_cpu_id] point to something useful.
 		 */
-		set	C_LABEL(init_thread_union), %g6
-		set	C_LABEL(current_set), %g2
+		set	init_thread_union, %g6
+		set	current_set, %g2
 #ifdef CONFIG_SMP
-		sethi	%hi(C_LABEL(boot_cpu_id4)), %g3
-		ldub	[%g3 + %lo(C_LABEL(boot_cpu_id4))], %g3
+		sethi	%hi(boot_cpu_id4), %g3
+		ldub	[%g3 + %lo(boot_cpu_id4)], %g3
 		st	%g6, [%g2]
 		add	%g2, %g3, %g2
 #endif
@@ -1124,14 +1123,14 @@ sun4c_continue_boot:
 		st	%g4, [%g5 + 0x1c]
 
 2:		
-		sethi	%hi( C_LABEL(nwindows) ), %g4
-		st	%g3, [%g4 + %lo( C_LABEL(nwindows) )]	! store final value
+		sethi	%hi(nwindows), %g4
+		st	%g3, [%g4 + %lo(nwindows)]	! store final value
 		sub	%g3, 0x1, %g3
-		sethi	%hi( C_LABEL(nwindowsm1) ), %g4
-		st	%g3, [%g4 + %lo( C_LABEL(nwindowsm1) )]
+		sethi	%hi(nwindowsm1), %g4
+		st	%g3, [%g4 + %lo(nwindowsm1)]
 
 		/* Here we go, start using Linux's trap table... */
-		set	C_LABEL(trapbase), %g3
+		set	trapbase, %g3
 		wr	%g3, 0x0, %tbr
 		WRITE_PAUSE
 
@@ -1147,12 +1146,12 @@ sun4c_continue_boot:
 		 * off to start_kernel().
 		 */
 
-		sethi	%hi( C_LABEL(prom_vector_p) ), %g5
-		ld	[%g5 + %lo( C_LABEL(prom_vector_p) )], %o0
-		call	C_LABEL(prom_init)
+		sethi	%hi(prom_vector_p), %g5
+		ld	[%g5 + %lo(prom_vector_p)], %o0
+		call	prom_init
 		 nop
 
-		call 	C_LABEL(start_kernel)
+		call 	start_kernel
 		 nop
 	
 		/* We should not get here. */
@@ -1162,7 +1161,7 @@ sun4c_continue_boot:
 sun4_init:
 #ifdef CONFIG_SUN4
 /* There, happy now Adrian? */
-		set	C_LABEL(cputypval), %o2		! Let everyone know we
+		set	cputypval, %o2		! Let everyone know we
 		set	' ', %o0			! are a "sun4 " architecture
 		stb	%o0, [%o2 + 0x4]		
 
@@ -1289,8 +1288,8 @@ halt_me:
  * gets initialized in c-code so all routines can use it.
  */
 
-	.globl	C_LABEL(prom_vector_p)
-C_LABEL(prom_vector_p):
+	.globl	prom_vector_p
+prom_vector_p:
 		.word 0
 
 /* We calculate the following at boot time, window fills/spills and trap entry
@@ -1298,25 +1297,25 @@ C_LABEL(prom_vector_p):
  */
 
 	.align 4
-	.globl	C_LABEL(nwindows)
-	.globl	C_LABEL(nwindowsm1)
-C_LABEL(nwindows):
+	.globl	nwindows
+	.globl	nwindowsm1
+nwindows:
 	.word	8
-C_LABEL(nwindowsm1):
+nwindowsm1:
 	.word	7
 
 /* Boot time debugger vector value.  We need this later on. */
 
 	.align 4
-	.globl	C_LABEL(linux_dbvec)
-C_LABEL(linux_dbvec):
+	.globl	linux_dbvec
+linux_dbvec:
 	.word	0
 	.word	0
 
 	.align 8
 
-	.globl	C_LABEL(lvl14_save)
-C_LABEL(lvl14_save):
+	.globl	lvl14_save
+lvl14_save:
 	.word	0
 	.word	0
 	.word	0
--- diff/arch/sparc/kernel/rtrap.S	2004-01-19 10:22:55.000000000 +0000
+++ source/arch/sparc/kernel/rtrap.S	2004-02-23 13:56:39.000000000 +0000
@@ -4,7 +4,6 @@
  * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
  */
 
-#include <asm/cprefix.h>
 #include <asm/page.h>
 #include <asm/ptrace.h>
 #include <asm/psr.h>
@@ -47,9 +46,9 @@ rtrap_7win_patch5:	and	%g1, 0x7f, %g1
 
 	.globl	ret_trap_entry, rtrap_patch1, rtrap_patch2
 	.globl	rtrap_patch3, rtrap_patch4, rtrap_patch5
-	.globl	C_LABEL(ret_trap_lockless_ipi)
+	.globl	ret_trap_lockless_ipi
 ret_trap_entry:
-C_LABEL(ret_trap_lockless_ipi):
+ret_trap_lockless_ipi:
 	andcc	%t_psr, PSR_PS, %g0
 	be	1f
 	 nop
@@ -64,7 +63,7 @@ C_LABEL(ret_trap_lockless_ipi):
 	be	signal_p
 	 nop
 
-	call	C_LABEL(schedule)
+	call	schedule
 	 nop
 
 	ld	[%curptr + TI_FLAGS], %g2
@@ -76,7 +75,7 @@ signal_p:
 	clr	%o0
 	mov	%l5, %o2
 	mov	%l6, %o3
-	call	C_LABEL(do_signal)
+	call	do_signal
 	 add	%sp, STACKFRAME_SZ, %o1	! pt_regs ptr
 
 	/* Fall through. */
@@ -95,7 +94,7 @@ ret_trap_continue:
 	WRITE_PAUSE
 
 	mov	1, %o1
-	call	C_LABEL(try_to_clear_window_buffer)
+	call	try_to_clear_window_buffer
 	 add	%sp, STACKFRAME_SZ, %o0
 
 	b	signal_p
@@ -131,8 +130,8 @@ rtrap_patch2:	and	%glob_tmp, 0xff, %glob
 				 * branch to the user stack checking routine
 				 * for return from traps.
 				 */
-				.globl	C_LABEL(rtrap_mmu_patchme)
-C_LABEL(rtrap_mmu_patchme):	b	C_LABEL(sun4c_rett_stackchk)
+				.globl	rtrap_mmu_patchme
+rtrap_mmu_patchme:	b	sun4c_rett_stackchk
 				 andcc	%fp, 0x7, %g0	
 
 ret_trap_userwins_ok:
@@ -165,7 +164,7 @@ ret_trap_unaligned_pc:
 	wr	%t_psr, PSR_ET, %psr
 	WRITE_PAUSE
 
-	call	C_LABEL(do_memaccess_unaligned)
+	call	do_memaccess_unaligned
 	 nop
 
 	b	signal_p
@@ -215,15 +214,15 @@ ret_trap_user_stack_is_bolixed:
 	wr	%t_psr, PSR_ET, %psr
 	WRITE_PAUSE
 
-	call	C_LABEL(window_ret_fault)
+	call	window_ret_fault
 	 add	%sp, STACKFRAME_SZ, %o0
 
 	b	signal_p
 	 ld	[%curptr + TI_FLAGS], %g2
 
 
-	.globl	C_LABEL(sun4c_rett_stackchk)
-C_LABEL(sun4c_rett_stackchk):
+	.globl	sun4c_rett_stackchk
+sun4c_rett_stackchk:
 	be	1f
 	 and	%fp, 0xfff, %g1		! delay slot
 
@@ -286,8 +285,8 @@ sun4c_rett_onepage:
 	b	ret_trap_userwins_ok
 	 save	%g0, %g0, %g0
 
-	.globl	C_LABEL(srmmu_rett_stackchk)
-C_LABEL(srmmu_rett_stackchk):
+	.globl	srmmu_rett_stackchk
+srmmu_rett_stackchk:
 	bne	ret_trap_user_stack_is_bolixed
 	 sethi   %hi(PAGE_OFFSET), %g1
 	cmp	%g1, %fp
--- diff/arch/sparc/kernel/sclow.S	2003-06-09 14:18:18.000000000 +0100
+++ source/arch/sparc/kernel/sclow.S	2004-02-23 13:56:39.000000000 +0000
@@ -6,7 +6,6 @@
  * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
  */
 
-#include <asm/cprefix.h>
 #include <asm/ptrace.h>
 #include <asm/asm_offsets.h>
 #include <asm/errno.h>
@@ -31,7 +30,7 @@
 	jmp	%l2; \
 	rett	%l2 + 4;
 
-#define LABEL(func)  CONCAT(func, _low)
+#define LABEL(func)  func##_low
 
 	.globl	LABEL(sunosnop)
 LABEL(sunosnop):
--- diff/arch/sparc/kernel/setup.c	2004-01-19 10:22:55.000000000 +0000
+++ source/arch/sparc/kernel/setup.c	2004-02-23 13:56:39.000000000 +0000
@@ -22,6 +22,7 @@
 #include <linux/config.h>
 #include <linux/fs.h>
 #include <linux/seq_file.h>
+#include <linux/syscalls.h>
 #include <linux/kdev_t.h>
 #include <linux/major.h>
 #include <linux/string.h>
@@ -66,7 +67,6 @@ struct screen_info screen_info = {
 
 extern unsigned long trapbase;
 void (*prom_palette)(int);
-asmlinkage void sys_sync(void);	/* it's really int */
 
 /* Pretty sick eh? */
 void prom_sync_me(void)
--- diff/arch/sparc/kernel/smp.c	2004-02-18 08:54:08.000000000 +0000
+++ source/arch/sparc/kernel/smp.c	2004-02-23 13:56:39.000000000 +0000
@@ -56,9 +56,6 @@ int smp_activated = 0;
 volatile int __cpu_number_map[NR_CPUS];
 volatile int __cpu_logical_map[NR_CPUS];
 cycles_t cacheflush_time = 0; /* XXX */
-spinlock_t __atomic_hash[ATOMIC_HASH_SIZE] = {
-	[0 ... (ATOMIC_HASH_SIZE-1)] = SPIN_LOCK_UNLOCKED
-};
 
 /* The only guaranteed locking primitive available on all Sparc
  * processors is 'ldstub [%reg + immediate], %dest_reg' which atomically
--- diff/arch/sparc/kernel/sparc_ksyms.c	2004-02-18 08:54:08.000000000 +0000
+++ source/arch/sparc/kernel/sparc_ksyms.c	2004-02-23 13:56:39.000000000 +0000
@@ -298,8 +298,7 @@ EXPORT_SYMBOL(__copy_user);
 EXPORT_SYMBOL(__strncpy_from_user);
 
 /* Networking helper routines. */
-/* XXX This is NOVERS because C_LABEL_STR doesn't get the version number. -DaveM */
-EXPORT_SYMBOL_NOVERS(__csum_partial_copy_sparc_generic);
+EXPORT_SYMBOL(__csum_partial_copy_sparc_generic);
 EXPORT_SYMBOL(csum_partial);
 
 /* Cache flushing.  */
--- diff/arch/sparc/kernel/sunos_asm.S	2003-05-21 11:50:14.000000000 +0100
+++ source/arch/sparc/kernel/sunos_asm.S	2004-02-23 13:56:39.000000000 +0000
@@ -9,7 +9,6 @@
  * Copyright (C) 1995 Adrian M. Rodriguez (adrian@remus.rutgers.edu)
  */
 
-#include <asm/cprefix.h>
 #include <asm/ptrace.h>
 
 	.text
@@ -19,50 +18,50 @@
 	 * value as in [%sp + STACKFRAME_SZ + PT_I0] */
 
 	/* SunOS getpid() returns pid in %o0 and ppid in %o1 */
-	.globl	C_LABEL(sunos_getpid)
-C_LABEL(sunos_getpid):
-	call	C_LABEL(sys_getppid)
+	.globl	sunos_getpid
+sunos_getpid:
+	call	sys_getppid
 	 nop
 
-	call	C_LABEL(sys_getpid)
+	call	sys_getpid
 	 st	%o0, [%sp + STACKFRAME_SZ + PT_I1]
 
-	b	C_LABEL(ret_sys_call)
+	b	ret_sys_call
 	 st	%o0, [%sp + STACKFRAME_SZ + PT_I0]
 
 	/* SunOS getuid() returns uid in %o0 and euid in %o1 */
-	.globl	C_LABEL(sunos_getuid)
-C_LABEL(sunos_getuid):
-	call	C_LABEL(sys_geteuid16)
+	.globl	sunos_getuid
+sunos_getuid:
+	call	sys_geteuid16
 	 nop
 
-	call	C_LABEL(sys_getuid16)
+	call	sys_getuid16
 	 st	%o0, [%sp + STACKFRAME_SZ + PT_I1]
 
-	b	C_LABEL(ret_sys_call)
+	b	ret_sys_call
 	 st	%o0, [%sp + STACKFRAME_SZ + PT_I0]
 
 	/* SunOS getgid() returns gid in %o0 and egid in %o1 */
-	.globl	C_LABEL(sunos_getgid)
-C_LABEL(sunos_getgid):
-	call	C_LABEL(sys_getegid16)
+	.globl	sunos_getgid
+sunos_getgid:
+	call	sys_getegid16
 	 nop
 
-	call	C_LABEL(sys_getgid16)
+	call	sys_getgid16
 	 st	%o0, [%sp + STACKFRAME_SZ + PT_I1]
 
-	b	C_LABEL(ret_sys_call)
+	b	ret_sys_call
 	 st	%o0, [%sp + STACKFRAME_SZ + PT_I0]
 
 	/* SunOS's execv() call only specifies the argv argument, the
 	 * environment settings are the same as the calling processes.
 	 */
-	.globl	C_LABEL(sunos_execv)
-C_LABEL(sunos_execv):
+	.globl	sunos_execv
+sunos_execv:
 	st	%g0, [%sp + STACKFRAME_SZ + PT_I2]
 
-	call	C_LABEL(sparc_execve)
+	call	sparc_execve
 	 add	%sp, STACKFRAME_SZ, %o0
 
-	b	C_LABEL(ret_sys_call)
+	b	ret_sys_call
 	 ld	[%sp + STACKFRAME_SZ + PT_I0], %o0
--- diff/arch/sparc/kernel/sunos_ioctl.c	2002-10-16 04:27:53.000000000 +0100
+++ source/arch/sparc/kernel/sunos_ioctl.c	2004-02-23 13:56:39.000000000 +0000
@@ -21,6 +21,7 @@
 #include <linux/mm.h>
 #include <linux/smp.h>
 #include <linux/smp_lock.h>
+#include <linux/syscalls.h>
 #include <linux/file.h>
 #include <asm/kbio.h>
 
@@ -32,7 +33,6 @@ extern char sunkbd_layout;
 /* NR_OPEN is now larger and dynamic in recent kernels. */
 #define SUNOS_NR_OPEN	256
 
-extern asmlinkage int sys_ioctl(unsigned int, unsigned int, unsigned long);
 extern asmlinkage int sys_setsid(void);
 
 asmlinkage int sunos_ioctl (int fd, unsigned long cmd, unsigned long arg)
--- diff/arch/sparc/kernel/sys_sparc.c	2003-07-22 18:54:27.000000000 +0100
+++ source/arch/sparc/kernel/sys_sparc.c	2004-02-23 13:56:39.000000000 +0000
@@ -16,6 +16,7 @@
 #include <linux/msg.h>
 #include <linux/shm.h>
 #include <linux/stat.h>
+#include <linux/syscalls.h>
 #include <linux/mman.h>
 #include <linux/utsname.h>
 #include <linux/smp.h>
@@ -78,8 +79,6 @@ unsigned long arch_get_unmapped_area(str
 	}
 }
 
-extern asmlinkage unsigned long sys_brk(unsigned long brk);
-
 asmlinkage unsigned long sparc_brk(unsigned long brk)
 {
 	if(ARCH_SUN4C_SUN4) {
--- diff/arch/sparc/kernel/sys_sunos.c	2003-09-17 12:28:03.000000000 +0100
+++ source/arch/sparc/kernel/sys_sunos.c	2004-02-23 13:56:39.000000000 +0000
@@ -33,6 +33,7 @@
 #include <linux/errno.h>
 #include <linux/smp.h>
 #include <linux/smp_lock.h>
+#include <linux/syscalls.h>
 
 #include <net/sock.h>
 
@@ -564,8 +565,6 @@ asmlinkage int sunos_pathconf(char *path
 }
 
 /* SunOS mount system call emulation */
-extern asmlinkage int
-sys_select(int n, fd_set *inp, fd_set *outp, fd_set *exp, struct timeval *tvp);
 
 asmlinkage int sunos_select(int width, fd_set *inp, fd_set *outp, fd_set *exp, struct timeval *tvp)
 {
@@ -621,11 +620,6 @@ struct sunos_nfs_mount_args {
 };
 
 
-extern asmlinkage int sys_connect(int fd, struct sockaddr *uservaddr, int addrlen);
-extern asmlinkage int sys_socket(int family, int type, int protocol);
-extern asmlinkage int sys_bind(int fd, struct sockaddr *umyaddr, int addrlen);
-
-
 /* Bind the socket on a local reserved port and connect it to the
  * remote server.  This on Linux/i386 is done by the mount program,
  * not by the kernel.
@@ -814,8 +808,6 @@ out:
 	return ret;
 }
 
-extern asmlinkage int sys_setsid(void);
-extern asmlinkage int sys_setpgid(pid_t, pid_t);
 
 asmlinkage int sunos_setpgrp(pid_t pid, pid_t pgid)
 {
@@ -1050,15 +1042,6 @@ static inline int check_nonblock(int ret
 	return ret;
 }
 
-extern asmlinkage ssize_t sys_read(unsigned int fd,char *buf,int count);
-extern asmlinkage ssize_t sys_write(unsigned int fd,char *buf,int count);
-extern asmlinkage int sys_recv(int fd, void * ubuf, int size, unsigned flags);
-extern asmlinkage int sys_send(int fd, void * buff, int len, unsigned flags);
-extern asmlinkage int sys_accept(int fd, struct sockaddr *sa, int *addrlen);
-extern asmlinkage int sys_readv(unsigned long fd, const struct iovec * vector, long count);
-extern asmlinkage int sys_writev(unsigned long fd, const struct iovec * vector, long count);
-
-
 asmlinkage int sunos_read(unsigned int fd,char *buf,int count)
 {
 	int ret;
@@ -1164,9 +1147,6 @@ sunos_sigaction(int sig, const struct ol
 }
 
 
-extern asmlinkage int sys_setsockopt(int fd, int level, int optname, char *optval, int optlen);
-extern asmlinkage int sys_getsockopt(int fd, int level, int optname, char *optval, int *optlen);
-
 asmlinkage int sunos_setsockopt(int fd, int level, int optname, char *optval,
 				int optlen)
 {
--- diff/arch/sparc/kernel/time.c	2003-12-19 09:51:02.000000000 +0000
+++ source/arch/sparc/kernel/time.c	2004-02-23 13:56:39.000000000 +0000
@@ -535,6 +535,7 @@ int do_settimeofday(struct timespec *tv)
 	write_seqlock_irq(&xtime_lock);
 	ret = bus_do_settimeofday(tv);
 	write_sequnlock_irq(&xtime_lock);
+	clock_was_set();
 	return ret;
 }
 
--- diff/arch/sparc/kernel/trampoline.S	2003-05-21 11:50:14.000000000 +0100
+++ source/arch/sparc/kernel/trampoline.S	2004-02-23 13:56:39.000000000 +0000
@@ -6,7 +6,6 @@
  */
 
 #include <linux/init.h>
-#include <asm/cprefix.h>
 #include <asm/head.h>
 #include <asm/psr.h>
 #include <asm/page.h>
@@ -15,8 +14,8 @@
 #include <asm/vaddrs.h>
 #include <asm/contregs.h>
 
-	.globl C_LABEL(sun4m_cpu_startup), C_LABEL(__smp4m_processor_id)
-	.globl C_LABEL(sun4d_cpu_startup), C_LABEL(__smp4d_processor_id)
+	.globl sun4m_cpu_startup, __smp4m_processor_id
+	.globl sun4d_cpu_startup, __smp4d_processor_id
 
 	__INIT
 	.align 4
@@ -26,21 +25,21 @@
  * in and sets PIL in %psr to 15, no irqs.
  */
 
-C_LABEL(sun4m_cpu_startup):
+sun4m_cpu_startup:
 cpu1_startup:
-	sethi	%hi(C_LABEL(trapbase_cpu1)), %g3
+	sethi	%hi(trapbase_cpu1), %g3
 	b	1f
-	 or	%g3, %lo(C_LABEL(trapbase_cpu1)), %g3
+	 or	%g3, %lo(trapbase_cpu1), %g3
 
 cpu2_startup:
-	sethi	%hi(C_LABEL(trapbase_cpu2)), %g3
+	sethi	%hi(trapbase_cpu2), %g3
 	b	1f
-	 or	%g3, %lo(C_LABEL(trapbase_cpu2)), %g3
+	 or	%g3, %lo(trapbase_cpu2), %g3
 
 cpu3_startup:
-	sethi	%hi(C_LABEL(trapbase_cpu3)), %g3
+	sethi	%hi(trapbase_cpu3), %g3
 	b	1f
-	 or	%g3, %lo(C_LABEL(trapbase_cpu3)), %g3
+	 or	%g3, %lo(trapbase_cpu3), %g3
 
 1:
 	/* Set up a sane %psr -- PIL<0xf> S<0x1> PS<0x1> CWP<0x0> */
@@ -58,7 +57,7 @@ cpu3_startup:
 	WRITE_PAUSE
 
 	/* Give ourselves a stack and curptr. */
-	set	C_LABEL(current_set), %g5
+	set	current_set, %g5
 	srl	%g3, 10, %g4
 	and	%g4, 0xc, %g4
 	ld	[%g5 + %g4], %g6
@@ -73,13 +72,13 @@ cpu3_startup:
 	WRITE_PAUSE
 
 	/* Init our caches, etc. */
-	set	C_LABEL(poke_srmmu), %g5
+	set	poke_srmmu, %g5
 	ld	[%g5], %g5
 	call	%g5
 	 nop
 
 	/* Start this processor. */
-	call	C_LABEL(smp4m_callin)
+	call	smp4m_callin
 	 nop
 
 	b,a	smp_do_cpu_idle
@@ -88,22 +87,22 @@ cpu3_startup:
 	.align	4
 
 smp_do_cpu_idle:
-	call	C_LABEL(init_idle)
+	call	init_idle
 	 nop
-	call	C_LABEL(cpu_idle)
+	call	cpu_idle
 	 mov	0, %o0
 
-	call	C_LABEL(cpu_panic)
+	call	cpu_panic
 	 nop
 
-C_LABEL(__smp4m_processor_id):
+__smp4m_processor_id:
 	rd	%tbr, %g2
 	srl	%g2, 12, %g2
 	and	%g2, 3, %g2
 	retl
 	 mov	%g1, %o7
 
-C_LABEL(__smp4d_processor_id):
+__smp4d_processor_id:
 	lda	[%g0] ASI_M_VIKING_TMP1, %g2
 	retl
 	 mov	%g1, %o7
@@ -114,7 +113,7 @@ C_LABEL(__smp4d_processor_id):
 	__INIT
 	.align	4
 
-C_LABEL(sun4d_cpu_startup):
+sun4d_cpu_startup:
 	/* Set up a sane %psr -- PIL<0xf> S<0x1> PS<0x1> CWP<0x0> */
 	set	(PSR_PIL | PSR_S | PSR_PS), %g1
 	wr	%g1, 0x0, %psr		! traps off though
@@ -126,7 +125,7 @@ C_LABEL(sun4d_cpu_startup):
 	WRITE_PAUSE
 
 	/* Set tbr - we use just one trap table. */
-	set	C_LABEL(trapbase), %g1
+	set	trapbase, %g1
 	wr	%g1, 0x0, %tbr
 	WRITE_PAUSE
 
@@ -138,7 +137,7 @@ C_LABEL(sun4d_cpu_startup):
 	sta	%g1, [%g0] ASI_M_VIKING_TMP1
 
 	/* Give ourselves a stack and curptr. */
-	set	C_LABEL(current_set), %g5
+	set	current_set, %g5
 	srl	%g3, 1, %g4
 	ld	[%g5 + %g4], %g6
 
@@ -152,13 +151,13 @@ C_LABEL(sun4d_cpu_startup):
 	WRITE_PAUSE
 
 	/* Init our caches, etc. */
-	set	C_LABEL(poke_srmmu), %g5
+	set	poke_srmmu, %g5
 	ld	[%g5], %g5
 	call	%g5
 	 nop
 
 	/* Start this processor. */
-	call	C_LABEL(smp4d_callin)
+	call	smp4d_callin
 	 nop
 
 	b,a	smp_do_cpu_idle
--- diff/arch/sparc/kernel/wof.S	2004-01-19 10:22:55.000000000 +0000
+++ source/arch/sparc/kernel/wof.S	2004-02-23 13:56:39.000000000 +0000
@@ -4,7 +4,6 @@
  * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
  */
 
-#include <asm/cprefix.h>
 #include <asm/contregs.h>
 #include <asm/page.h>
 #include <asm/ptrace.h>
@@ -164,8 +163,8 @@ spwin_fromuser:
 	 * the label 'spwin_user_stack_is_bolixed' which will take
 	 * care of things at that point.
 	 */
-				.globl	C_LABEL(spwin_mmu_patchme)
-C_LABEL(spwin_mmu_patchme):	b	C_LABEL(spwin_sun4c_stackchk)
+	.globl	spwin_mmu_patchme
+spwin_mmu_patchme:	b	spwin_sun4c_stackchk
 				 andcc	%sp, 0x7, %g0
 
 spwin_good_ustack:
@@ -253,7 +252,7 @@ spnwin_patch3:	and	%twin_tmp, 0xff, %twi
 	/* Turn on traps and call c-code to deal with it. */
 	wr	%t_psr, PSR_ET, %psr
 	nop
-	call	C_LABEL(window_overflow_fault)
+	call	window_overflow_fault
 	 nop
 
 	/* Return from trap if C-code actually fixes things, if it
@@ -307,8 +306,8 @@ spwin_bad_ustack_from_kernel:
  * As noted above %curptr cannot be touched by this routine at all.
  */
 
-	.globl	C_LABEL(spwin_sun4c_stackchk)
-C_LABEL(spwin_sun4c_stackchk):
+	.globl	spwin_sun4c_stackchk
+spwin_sun4c_stackchk:
 	/* LOCATION: Window to be saved on the stack */
 
 	/* See if the stack is in the address space hole but first,
@@ -379,8 +378,8 @@ spwin_sun4c_onepage:
 	 * works for all current v8/srmmu implementations, we'll
 	 * see...
 	 */
-	.globl	C_LABEL(spwin_srmmu_stackchk)
-C_LABEL(spwin_srmmu_stackchk):
+	.globl	spwin_srmmu_stackchk
+spwin_srmmu_stackchk:
 	/* LOCATION: Window to be saved on the stack */
 
 	/* Because of SMP concerns and speed we play a trick.
--- diff/arch/sparc/kernel/wuf.S	2004-01-19 10:22:55.000000000 +0000
+++ source/arch/sparc/kernel/wuf.S	2004-02-23 13:56:39.000000000 +0000
@@ -4,7 +4,6 @@
  * Copyright (C) 1995 David S. Miller
  */
 
-#include <asm/cprefix.h>
 #include <asm/contregs.h>
 #include <asm/page.h>
 #include <asm/ptrace.h>
@@ -135,8 +134,8 @@ fwin_from_user:
 	/* Branch to the architecture specific stack validation
 	 * routine.  They can be found below...
 	 */
-				.globl	C_LABEL(fwin_mmu_patchme)
-C_LABEL(fwin_mmu_patchme):	b	C_LABEL(sun4c_fwin_stackchk)
+	.globl	fwin_mmu_patchme
+fwin_mmu_patchme:	b	sun4c_fwin_stackchk
 				 andcc	%sp, 0x7, %g0
 
 #define STACK_OFFSET (THREAD_SIZE - TRACEREG_SZ - STACKFRAME_SZ)
@@ -190,7 +189,7 @@ fwin_user_stack_is_bolixed:
 
 	wr	%t_psr, PSR_ET, %psr			! enable traps
 	nop
-	call	C_LABEL(window_underflow_fault)
+	call	window_underflow_fault
 	 mov	%g4, %o0
 
 	b	ret_trap_entry
@@ -244,8 +243,8 @@ fwin_user_finish_up:
 	 */
 
 	.align	4
-	.globl	C_LABEL(sun4c_fwin_stackchk)
-C_LABEL(sun4c_fwin_stackchk):
+	.globl	sun4c_fwin_stackchk
+sun4c_fwin_stackchk:
 	/* LOCATION: Window 'W' */
 
 	/* Caller did 'andcc %sp, 0x7, %g0' */
@@ -295,8 +294,8 @@ sun4c_fwin_onepage:
 	/* A page had bad page permissions, losing... */
 	b,a	fwin_user_stack_is_bolixed
 
-	.globl	C_LABEL(srmmu_fwin_stackchk)
-C_LABEL(srmmu_fwin_stackchk):
+	.globl	srmmu_fwin_stackchk
+srmmu_fwin_stackchk:
 	/* LOCATION: Window 'W' */
 
 	/* Caller did 'andcc %sp, 0x7, %g0' */
--- diff/arch/sparc/lib/Makefile	2003-06-30 10:07:20.000000000 +0100
+++ source/arch/sparc/lib/Makefile	2004-02-23 13:56:39.000000000 +0000
@@ -7,5 +7,5 @@ EXTRA_AFLAGS := -ansi -DST_DIV0=0x02
 lib-y := mul.o rem.o sdiv.o udiv.o umul.o urem.o ashrdi3.o memcpy.o memset.o \
          strlen.o checksum.o blockops.o memscan.o memcmp.o strncmp.o \
 	 strncpy_from_user.o divdi3.o udivdi3.o strlen_user.o \
-	 copy_user.o locks.o atomic.o bitops.o debuglocks.o lshrdi3.o \
-	 ashldi3.o rwsem.o muldi3.o bitext.o
+	 copy_user.o locks.o atomic.o atomic32.o bitops.o debuglocks.o \
+	 lshrdi3.o ashldi3.o rwsem.o muldi3.o bitext.o
--- diff/arch/sparc/lib/ashldi3.S	2002-10-16 04:27:16.000000000 +0100
+++ source/arch/sparc/lib/ashldi3.S	2004-02-23 13:56:39.000000000 +0000
@@ -5,12 +5,10 @@
  * Copyright (C) 1999 David S. Miller (davem@redhat.com)
  */
 
-#include <asm/cprefix.h>
-
 	.text
 	.align	4
-	.globl	C_LABEL(__ashldi3)
-C_LABEL(__ashldi3):
+	.globl	__ashldi3
+__ashldi3:
 	cmp	%o2, 0
 	be	9f
 	 mov	0x20, %g2
--- diff/arch/sparc/lib/ashrdi3.S	2002-10-16 04:28:24.000000000 +0100
+++ source/arch/sparc/lib/ashrdi3.S	2004-02-23 13:56:39.000000000 +0000
@@ -5,12 +5,10 @@
  * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
  */
 
-#include <asm/cprefix.h>
-
 	.text
 	.align	4
-	.globl C_LABEL(__ashrdi3)
-C_LABEL(__ashrdi3):
+	.globl __ashrdi3
+__ashrdi3:
 	tst	%o2
 	be	3f
 	 or	%g0, 32, %g2
--- diff/arch/sparc/lib/atomic.S	2004-02-18 08:54:08.000000000 +0000
+++ source/arch/sparc/lib/atomic.S	2004-02-23 13:56:39.000000000 +0000
@@ -4,7 +4,6 @@
  */
 
 #include <linux/config.h>
-#include <asm/cprefix.h>
 #include <asm/ptrace.h>
 #include <asm/psr.h>
 
--- diff/arch/sparc/lib/bitops.S	2002-10-16 04:28:31.000000000 +0100
+++ source/arch/sparc/lib/bitops.S	2004-02-23 13:56:39.000000000 +0000
@@ -4,7 +4,6 @@
  */
 
 #include <linux/config.h>
-#include <asm/cprefix.h>
 #include <asm/ptrace.h>
 #include <asm/psr.h>
 
@@ -29,7 +28,7 @@ ___set_bit:
 	wr	%g5, 0x0, %psr
 	nop; nop; nop
 #ifdef CONFIG_SMP
-	set	C_LABEL(bitops_spinlock), %g5
+	set	bitops_spinlock, %g5
 2:	ldstub	[%g5], %g7		! Spin on the byte lock for SMP.
 	orcc	%g7, 0x0, %g0		! Did we get it?
 	bne	2b			! Nope...
@@ -39,7 +38,7 @@ ___set_bit:
 	and	%g7, %g2, %g2
 #ifdef CONFIG_SMP
 	st	%g5, [%g1]
-	set	C_LABEL(bitops_spinlock), %g5
+	set	bitops_spinlock, %g5
 	stb	%g0, [%g5]
 #else
 	st	%g5, [%g1]
@@ -58,7 +57,7 @@ ___clear_bit:
 	wr	%g5, 0x0, %psr
 	nop; nop; nop
 #ifdef CONFIG_SMP
-	set	C_LABEL(bitops_spinlock), %g5
+	set	bitops_spinlock, %g5
 2:	ldstub	[%g5], %g7		! Spin on the byte lock for SMP.
 	orcc	%g7, 0x0, %g0		! Did we get it?
 	bne	2b			! Nope...
@@ -68,7 +67,7 @@ ___clear_bit:
 	and	%g7, %g2, %g2
 #ifdef CONFIG_SMP
 	st	%g5, [%g1]
-	set	C_LABEL(bitops_spinlock), %g5
+	set	bitops_spinlock, %g5
 	stb	%g0, [%g5]
 #else
 	st	%g5, [%g1]
@@ -87,7 +86,7 @@ ___change_bit:
 	wr	%g5, 0x0, %psr
 	nop; nop; nop
 #ifdef CONFIG_SMP
-	set	C_LABEL(bitops_spinlock), %g5
+	set	bitops_spinlock, %g5
 2:	ldstub	[%g5], %g7		! Spin on the byte lock for SMP.
 	orcc	%g7, 0x0, %g0		! Did we get it?
 	bne	2b			! Nope...
@@ -97,7 +96,7 @@ ___change_bit:
 	and	%g7, %g2, %g2
 #ifdef CONFIG_SMP
 	st	%g5, [%g1]
-	set	C_LABEL(bitops_spinlock), %g5
+	set	bitops_spinlock, %g5
 	stb	%g0, [%g5]
 #else
 	st	%g5, [%g1]
--- diff/arch/sparc/lib/blockops.S	2003-05-21 11:49:45.000000000 +0100
+++ source/arch/sparc/lib/blockops.S	2004-02-23 13:56:39.000000000 +0000
@@ -4,7 +4,6 @@
  * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
  */
 
-#include <asm/cprefix.h>
 #include <asm/page.h>
 
 	/* Zero out 64 bytes of memory at (buf + offset).
@@ -46,9 +45,9 @@
 
 	.text
 	.align	4
-	.globl	C_LABEL(bzero_1page), C_LABEL(__copy_1page)
+	.globl	bzero_1page, __copy_1page
 
-C_LABEL(bzero_1page):
+bzero_1page:
 /* NOTE: If you change the number of insns of this routine, please check
  * arch/sparc/mm/hypersparc.S */
 	/* %o0 = buf */
@@ -67,7 +66,7 @@ C_LABEL(bzero_1page):
 	retl
 	 nop
 
-C_LABEL(__copy_1page):
+__copy_1page:
 /* NOTE: If you change the number of insns of this routine, please check
  * arch/sparc/mm/hypersparc.S */
 	/* %o0 = dst, %o1 = src */
--- diff/arch/sparc/lib/checksum.S	2003-09-30 15:46:12.000000000 +0100
+++ source/arch/sparc/lib/checksum.S	2004-02-23 13:56:39.000000000 +0000
@@ -13,7 +13,6 @@
  *	BSD4.4 portable checksum routine
  */
 
-#include <asm/cprefix.h>
 #include <asm/errno.h>
 
 #define CSUM_BIGCHUNK(buf, offset, sum, t0, t1, t2, t3, t4, t5)	\
@@ -104,8 +103,8 @@ csum_partial_fix_alignment:
 	/* The common case is to get called with a nicely aligned
 	 * buffer of size 0x20.  Follow the code path for that case.
 	 */
-	.globl	C_LABEL(csum_partial)
-C_LABEL(csum_partial):			/* %o0=buf, %o1=len, %o2=sum */
+	.globl	csum_partial
+csum_partial:			/* %o0=buf, %o1=len, %o2=sum */
 	andcc	%o0, 0x7, %g0				! alignment problems?
 	bne	csum_partial_fix_alignment		! yep, handle it
 	 sethi	%hi(cpte - 8), %g7			! prepare table jmp ptr
@@ -142,8 +141,8 @@ cpte:	bne	csum_partial_end_cruft			! yep
 cpout:	retl						! get outta here
 	 mov	%o2, %o0				! return computed csum
 
-	.globl C_LABEL(__csum_partial_copy_start), C_LABEL(__csum_partial_copy_end)
-C_LABEL(__csum_partial_copy_start):
+	.globl __csum_partial_copy_start, __csum_partial_copy_end
+__csum_partial_copy_start:
 
 /* Work around cpp -rob */
 #define ALLOC #alloc
@@ -329,8 +328,8 @@ cc_dword_align:
 	 * out of you, game over, lights out.
 	 */
 	.align	8
-	.globl	C_LABEL(__csum_partial_copy_sparc_generic)
-C_LABEL(__csum_partial_copy_sparc_generic):
+	.globl	__csum_partial_copy_sparc_generic
+__csum_partial_copy_sparc_generic:
 					/* %o0=src, %o1=dest, %g1=len, %g7=sum */
 	xor	%o0, %o1, %o4		! get changing bits
 	andcc	%o4, 3, %g0		! check for mismatched alignment
@@ -472,7 +471,7 @@ ccslow:	cmp	%g1, 0
 4:	addcc	%g7, %g5, %g7
 	retl	
 	 addx	%g0, %g7, %o0
-C_LABEL(__csum_partial_copy_end):
+__csum_partial_copy_end:
 
 /* We do these strange calculations for the csum_*_from_user case only, ie.
  * we only bother with faults on loads... */
@@ -551,7 +550,7 @@ C_LABEL(__csum_partial_copy_end):
         mov     %i5, %o0
         mov     %i7, %o1
         mov	%i4, %o2
-        call    C_LABEL(lookup_fault)
+        call    lookup_fault
 	 mov	%g7, %i4
 	cmp	%o0, 2
 	bne	1f	
@@ -561,7 +560,7 @@ C_LABEL(__csum_partial_copy_end):
 	 mov	%i0, %o1
 	mov	%i1, %o0
 5:
-	call	C_LABEL(__memcpy)
+	call	__memcpy
 	 mov	%i2, %o2
 	tst	%o0
 	bne,a	2f
@@ -570,7 +569,7 @@ C_LABEL(__csum_partial_copy_end):
 2:
 	mov	%i1, %o0
 6:
-	call	C_LABEL(__bzero)
+	call	__bzero
 	 mov	%i3, %o1
 1:
 	ld	[%sp + 168], %o2		! struct_ptr of parent
--- diff/arch/sparc/lib/copy_user.S	2003-09-30 15:46:12.000000000 +0100
+++ source/arch/sparc/lib/copy_user.S	2004-02-23 13:56:39.000000000 +0000
@@ -11,7 +11,6 @@
  * Returns 0 if successful, otherwise count of bytes not copied yet
  */
 
-#include <asm/cprefix.h>
 #include <asm/ptrace.h>
 #include <asm/asmmacro.h>
 #include <asm/page.h>
@@ -118,7 +117,7 @@
 	.globl  __copy_user_begin
 __copy_user_begin:
 
-	.globl	C_LABEL(__copy_user)
+	.globl	__copy_user
 dword_align:
 	andcc	%o1, 1, %g0
 	be	4f
@@ -145,7 +144,7 @@ dword_align:
 	b	3f
 	 add	%o0, 2, %o0
 
-C_LABEL(__copy_user):	/* %o0=dst %o1=src %o2=len */
+__copy_user:	/* %o0=dst %o1=src %o2=len */
 	xor	%o0, %o1, %o4
 1:
 	andcc	%o4, 3, %o5
--- diff/arch/sparc/lib/locks.S	2002-10-16 04:29:02.000000000 +0100
+++ source/arch/sparc/lib/locks.S	2004-02-23 13:56:39.000000000 +0000
@@ -6,7 +6,6 @@
  * Copyright (C) 1998 Jakub Jelinek   (jj@ultra.linux.cz)
  */
 
-#include <asm/cprefix.h>
 #include <asm/ptrace.h>
 #include <asm/psr.h>
 #include <asm/smp.h>
--- diff/arch/sparc/lib/lshrdi3.S	2002-10-16 04:27:55.000000000 +0100
+++ source/arch/sparc/lib/lshrdi3.S	2004-02-23 13:56:39.000000000 +0000
@@ -1,9 +1,7 @@
 /* $Id: lshrdi3.S,v 1.1 1999/03/21 06:37:45 davem Exp $ */
 
-#include <asm/cprefix.h>
-
-	.globl	C_LABEL(__lshrdi3)
-C_LABEL(__lshrdi3):
+	.globl	__lshrdi3
+__lshrdi3:
 	cmp	%o2, 0
 	be	3f
 	 mov	0x20, %g2
--- diff/arch/sparc/lib/memcmp.S	2002-10-16 04:28:33.000000000 +0100
+++ source/arch/sparc/lib/memcmp.S	2004-02-23 13:56:39.000000000 +0000
@@ -1,10 +1,8 @@
-#include <asm/cprefix.h>
-
 	.text
 	.align 4
-	.global C_LABEL(__memcmp), C_LABEL(memcmp)
-C_LABEL(__memcmp):
-C_LABEL(memcmp):
+	.global __memcmp, memcmp
+__memcmp:
+memcmp:
 #if 1
 	cmp	%o2, 0
 	ble	L3
--- diff/arch/sparc/lib/memcpy.S	2002-10-16 04:29:06.000000000 +0100
+++ source/arch/sparc/lib/memcpy.S	2004-02-23 13:56:39.000000000 +0000
@@ -9,13 +9,11 @@
 
 #ifdef __KERNEL__
 
-#include <asm/cprefix.h>
-
 #define FUNC(x) 											\
-	.globl	C_LABEL(x);										\
-	.type	C_LABEL(x),@function;									\
+	.globl	x;		\
+	.type	x,@function;	\
 	.align	4;											\
-C_LABEL(x):
+x:
 
 #undef FASTER_REVERSE
 #undef FASTER_NONALIGNED
--- diff/arch/sparc/lib/memscan.S	2002-10-16 04:27:53.000000000 +0100
+++ source/arch/sparc/lib/memscan.S	2004-02-23 13:56:39.000000000 +0000
@@ -4,8 +4,6 @@
  * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
  */
 
-#include <asm/cprefix.h>
-
 /* In essence, this is just a fancy strlen. */
 
 #define LO_MAGIC 0x01010101
@@ -13,9 +11,9 @@
 
 	.text
 	.align	4
-	.globl	C_LABEL(__memscan_zero), C_LABEL(__memscan_generic)
-	.globl	C_LABEL(memscan)
-C_LABEL(__memscan_zero):
+	.globl	__memscan_zero, __memscan_generic
+	.globl	memscan
+__memscan_zero:
 	/* %o0 = addr, %o1 = size */
 	cmp	%o1, 0
 	bne,a	1f
@@ -114,8 +112,8 @@ mzero_found_it:
 	retl
 	 sub	%o0, 2, %o0
 
-C_LABEL(memscan):
-C_LABEL(__memscan_generic):
+memscan:
+__memscan_generic:
 	/* %o0 = addr, %o1 = c, %o2 = size */
 	cmp	%o2, 0
 	bne,a	0f
--- diff/arch/sparc/lib/memset.S	2003-09-30 15:46:12.000000000 +0100
+++ source/arch/sparc/lib/memset.S	2004-02-23 13:56:39.000000000 +0000
@@ -7,7 +7,6 @@
  * occurs and we were called as clear_user.
  */
 
-#include <asm/cprefix.h>
 #include <asm/ptrace.h>
 
 /* Work around cpp -rob */
@@ -61,12 +60,12 @@
         .globl  __bzero_begin
 __bzero_begin:
 
-	.globl	C_LABEL(__bzero), C_LABEL(__memset), 
-	.globl	C_LABEL(memset)
-	.globl	C_LABEL(__memset_start), C_LABEL(__memset_end)
-C_LABEL(__memset_start):
-C_LABEL(__memset):
-C_LABEL(memset):
+	.globl	__bzero, __memset, 
+	.globl	memset
+	.globl	__memset_start, __memset_end
+__memset_start:
+__memset:
+memset:
 	and	%o1, 0xff, %g3
 	sll	%g3, 8, %g2
 	or	%g3, %g2, %g3
@@ -90,7 +89,7 @@ C_LABEL(memset):
 	b	4f
 	 sub	%o0, %o2, %o0
 
-C_LABEL(__bzero):
+__bzero:
 	mov	%g0, %g3
 1:
 	cmp	%o1, 7
@@ -168,7 +167,7 @@ C_LABEL(__bzero):
 0:
 	retl
 	 clr	%o0
-C_LABEL(__memset_end):
+__memset_end:
 
 	.section .fixup,#alloc,#execinstr
 	.align	4
@@ -195,7 +194,7 @@ C_LABEL(__memset_end):
 	save	%sp, -104, %sp
 	mov	%i5, %o0
 	mov	%i7, %o1
-	call	C_LABEL(lookup_fault)
+	call	lookup_fault
 	 mov	%i4, %o2
 	ret
 	 restore
--- diff/arch/sparc/lib/strlen.S	2002-10-16 04:28:32.000000000 +0100
+++ source/arch/sparc/lib/strlen.S	2004-02-23 13:56:39.000000000 +0000
@@ -5,8 +5,6 @@
  * Copyright (C) 1996 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
  */
 
-#include <asm/cprefix.h>
-
 #define LO_MAGIC 0x01010101
 #define HI_MAGIC 0x80808080
 
@@ -42,8 +40,8 @@
 	 mov	2, %o0
 
 	.align 4
-	.global C_LABEL(strlen)
-C_LABEL(strlen):
+	.global strlen
+strlen:
 	mov	%o0, %o1
 	andcc	%o0, 3, %g0
 	bne	0b
--- diff/arch/sparc/lib/strlen_user.S	2002-10-16 04:27:57.000000000 +0100
+++ source/arch/sparc/lib/strlen_user.S	2004-02-23 13:56:39.000000000 +0000
@@ -8,8 +8,6 @@
  * Copyright (C) 1996 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
  */
 
-#include <asm/cprefix.h>
-
 #define LO_MAGIC 0x01010101
 #define HI_MAGIC 0x80808080
 
@@ -47,10 +45,10 @@
 	 mov	3, %o0
 
 	.align 4
-	.global C_LABEL(__strlen_user), C_LABEL(__strnlen_user)
-C_LABEL(__strlen_user):
+	.global __strlen_user, __strnlen_user
+__strlen_user:
 	sethi	%hi(32768), %o1
-C_LABEL(__strnlen_user):
+__strnlen_user:
 	mov	%o1, %g1
 	mov	%o0, %o1
 	andcc	%o0, 3, %g0
--- diff/arch/sparc/lib/strncmp.S	2002-10-16 04:27:19.000000000 +0100
+++ source/arch/sparc/lib/strncmp.S	2004-02-23 13:56:39.000000000 +0000
@@ -3,13 +3,11 @@
  *            generic strncmp routine.
  */
 
-#include <asm/cprefix.h>
-
 	.text
 	.align 4
-	.global C_LABEL(__strncmp), C_LABEL(strncmp)
-C_LABEL(__strncmp):
-C_LABEL(strncmp):
+	.global __strncmp, strncmp
+__strncmp:
+strncmp:
 	mov	%o0, %g3
 	mov	0, %o3
 
--- diff/arch/sparc/lib/strncpy_from_user.S	2002-10-16 04:28:28.000000000 +0100
+++ source/arch/sparc/lib/strncpy_from_user.S	2004-02-23 13:56:39.000000000 +0000
@@ -3,7 +3,6 @@
  *  Copyright(C) 1996 David S. Miller
  */
 
-#include <asm/cprefix.h>
 #include <asm/ptrace.h>
 #include <asm/errno.h>
 
@@ -17,8 +16,8 @@
 	 * bytes copied		if we hit a null byte
 	 */
 
-	.globl	C_LABEL(__strncpy_from_user)
-C_LABEL(__strncpy_from_user):
+	.globl	__strncpy_from_user
+__strncpy_from_user:
 	/* %o0=dest, %o1=src, %o2=count */
 	mov	%o2, %o3
 1:
--- diff/arch/sparc/math-emu/Makefile	2002-12-16 09:26:06.000000000 +0000
+++ source/arch/sparc/math-emu/Makefile	2004-02-23 13:56:39.000000000 +0000
@@ -2,7 +2,7 @@
 # Makefile for the FPU instruction emulation.
 #
 
-obj-y    := math.o ashldi3.o
+obj-y    := math.o
 
 EXTRA_AFLAGS := -ansi
 EXTRA_CFLAGS = -I. -I$(TOPDIR)/include/math-emu -w
--- diff/arch/sparc/mm/viking.S	2002-11-11 11:09:36.000000000 +0000
+++ source/arch/sparc/mm/viking.S	2004-02-23 13:56:39.000000000 +0000
@@ -15,7 +15,6 @@
 #include <asm/page.h>
 #include <asm/pgtsrmmu.h>
 #include <asm/viking.h>
-#include <asm/cprefix.h>
 #include <asm/btfixup.h>
 
 #ifdef CONFIG_SMP
--- diff/arch/sparc/prom/printf.c	2002-10-16 04:27:16.000000000 +0100
+++ source/arch/sparc/prom/printf.c	2004-02-23 13:56:39.000000000 +0000
@@ -39,7 +39,7 @@ prom_printf(char *fmt, ...)
 	int i;
 
 	va_start(args, fmt);
-	i = vsnprintf(ppbuf, sizeof(ppbuf), fmt, args);
+	i = vscnprintf(ppbuf, sizeof(ppbuf), fmt, args);
 	va_end(args);
 
 	prom_write(ppbuf, i);
--- diff/arch/sparc64/Kconfig	2004-02-18 08:54:08.000000000 +0000
+++ source/arch/sparc64/Kconfig	2004-02-23 13:56:39.000000000 +0000
@@ -186,24 +186,6 @@ config SPARC64
 	  SPARC64 ports; its web page is available at
 	  <http://www.ultralinux.org/>.
 
-config HOTPLUG
-	bool "Support for hot-pluggable devices"
-	---help---
-	  Say Y here if you want to plug devices into your computer while
-	  the system is running, and be able to use them quickly.  In many
-	  cases, the devices can likewise be unplugged at any time too.
-
-	  One well known example of this is PCMCIA- or PC-cards, credit-card
-	  size devices such as network cards, modems or hard drives which are
-	  plugged into slots found on all modern laptop computers.  Another
-	  example, used on modern desktops as well as laptops, is USB.
-
-	  Enable HOTPLUG and KMOD, and build a modular kernel.  Get agent
-	  software (at <http://linux-hotplug.sourceforge.net/>) and install it.
-	  Then your kernel will automatically call out to a user mode "policy
-	  agent" (/sbin/hotplug) to load modules and set up software needed
-	  to use devices as you hotplug them.
-
 # Global things across all Sun machines.
 config RWSEM_GENERIC_SPINLOCK
 	bool
@@ -718,12 +700,19 @@ config DEBUG_BOOTMEM
 	depends on DEBUG_KERNEL
 	bool "Debug BOOTMEM initialization"
 
+config LOCKMETER
+	bool "Kernel lock metering"
+	depends on SMP && !PREEMPT
+	help
+	  Say Y to enable kernel lock metering, which adds overhead to SMP locks,
+	  but allows you to see various statistics using the lockstat command.
+
 # We have a custom atomic_dec_and_lock() implementation but it's not
 # compatible with spinlock debugging so we need to fall back on
 # the generic version in that case.
 config HAVE_DEC_LOCK
 	bool
-	depends on SMP && !DEBUG_SPINLOCK
+	depends on SMP && !DEBUG_SPINLOCK && !LOCKMETER
 	default y
 
 config MCOUNT
--- diff/arch/sparc64/defconfig	2004-02-18 08:54:08.000000000 +0000
+++ source/arch/sparc64/defconfig	2004-02-23 13:56:39.000000000 +0000
@@ -120,6 +120,7 @@ CONFIG_FB=y
 CONFIG_FB_CG6=y
 # CONFIG_FB_RIVA is not set
 # CONFIG_FB_MATROX is not set
+# CONFIG_FB_RADEON_OLD is not set
 # CONFIG_FB_RADEON is not set
 # CONFIG_FB_ATY128 is not set
 # CONFIG_FB_ATY is not set
@@ -233,6 +234,7 @@ CONFIG_IDE_TASKFILE_IO=y
 #
 # IDE chipset support/bugfixes
 #
+CONFIG_IDE_GENERIC=y
 CONFIG_BLK_DEV_IDEPCI=y
 # CONFIG_IDEPCI_SHARE_IRQ is not set
 # CONFIG_BLK_DEV_OFFBOARD is not set
@@ -253,6 +255,7 @@ CONFIG_BLK_DEV_CY82C693=m
 CONFIG_BLK_DEV_CS5520=m
 CONFIG_BLK_DEV_CS5530=m
 CONFIG_BLK_DEV_HPT34X=m
+# CONFIG_HPT34X_AUTODMA is not set
 CONFIG_BLK_DEV_HPT366=m
 CONFIG_BLK_DEV_SC1200=m
 CONFIG_BLK_DEV_PIIX=m
@@ -340,15 +343,16 @@ CONFIG_SCSI_QLOGIC_FC=y
 CONFIG_SCSI_QLOGIC_FC_FIRMWARE=y
 # CONFIG_SCSI_QLOGIC_1280 is not set
 CONFIG_SCSI_QLOGICPTI=m
-CONFIG_SCSI_QLA2XXX_CONFIG=y
-CONFIG_SCSI_QLA2XXX=m
-CONFIG_SCSI_QLA21XX=m
-CONFIG_SCSI_QLA22XX=m
-CONFIG_SCSI_QLA23XX=m
+CONFIG_SCSI_QLA2XXX=y
+# CONFIG_SCSI_QLA21XX is not set
+# CONFIG_SCSI_QLA22XX is not set
+# CONFIG_SCSI_QLA2300 is not set
+# CONFIG_SCSI_QLA2322 is not set
+# CONFIG_SCSI_QLA6312 is not set
+# CONFIG_SCSI_QLA6322 is not set
 CONFIG_SCSI_DC395x=m
 CONFIG_SCSI_DC390T=m
 # CONFIG_SCSI_DC390T_NOGENSUPP is not set
-# CONFIG_SCSI_NSP32 is not set
 CONFIG_SCSI_DEBUG=m
 CONFIG_SCSI_SUNESP=y
 
@@ -382,6 +386,7 @@ CONFIG_MD_RAID6=m
 CONFIG_MD_MULTIPATH=m
 CONFIG_BLK_DEV_DM=m
 # CONFIG_DM_IOCTL_V4 is not set
+CONFIG_DM_CRYPT=m
 
 #
 # Fusion MPT device support
@@ -615,7 +620,6 @@ CONFIG_XFRM_USER=m
 #
 CONFIG_IPV6_SCTP__=m
 CONFIG_IP_SCTP=m
-# CONFIG_SCTP_ADLER32 is not set
 # CONFIG_SCTP_DBG_MSG is not set
 # CONFIG_SCTP_DBG_OBJCNT is not set
 # CONFIG_SCTP_HMAC_NONE is not set
@@ -649,6 +653,7 @@ CONFIG_NET_DIVERT=y
 CONFIG_NET_SCHED=y
 CONFIG_NET_SCH_CBQ=m
 CONFIG_NET_SCH_HTB=m
+CONFIG_NET_SCH_HFSC=m
 CONFIG_NET_SCH_CSZ=m
 CONFIG_NET_SCH_ATM=y
 CONFIG_NET_SCH_PRIO=m
@@ -709,6 +714,8 @@ CONFIG_DE2104X=m
 CONFIG_TULIP=m
 # CONFIG_TULIP_MWI is not set
 # CONFIG_TULIP_MMIO is not set
+CONFIG_TULIP_NAPI=y
+CONFIG_TULIP_NAPI_HW_MITIGATION=y
 CONFIG_DE4X5=m
 CONFIG_WINBOND_840=m
 # CONFIG_DM9102 is not set
@@ -724,6 +731,7 @@ CONFIG_DGRS=m
 CONFIG_EEPRO100=m
 # CONFIG_EEPRO100_PIO is not set
 CONFIG_E100=m
+CONFIG_E100_NAPI=y
 CONFIG_FEALNX=m
 CONFIG_NATSEMI=m
 CONFIG_NE2K_PCI=m
@@ -733,6 +741,7 @@ CONFIG_8139TOO=m
 # CONFIG_8139TOO_TUNE_TWISTER is not set
 # CONFIG_8139TOO_8129 is not set
 # CONFIG_8139_OLD_RX_RESET is not set
+CONFIG_8139_RXBUF_IDX=1
 CONFIG_SIS900=m
 CONFIG_EPIC100=m
 CONFIG_SUNDANCE=m
@@ -800,6 +809,8 @@ CONFIG_HERMES=m
 CONFIG_PLX_HERMES=m
 CONFIG_TMD_HERMES=m
 CONFIG_PCI_HERMES=m
+CONFIG_ATMEL=m
+CONFIG_PCI_ATMEL=m
 CONFIG_NET_WIRELESS=y
 
 #
@@ -904,6 +915,7 @@ CONFIG_IRDA_FAST_RR=y
 # FIR device drivers
 #
 # CONFIG_USB_IRDA is not set
+CONFIG_SIGMATEL_FIR=m
 # CONFIG_TOSHIBA_FIR is not set
 # CONFIG_VLSI_FIR is not set
 
@@ -936,17 +948,20 @@ CONFIG_BT_HCIVHCI=m
 #
 # ISDN subsystem
 #
-CONFIG_ISDN_BOOL=y
+CONFIG_ISDN=m
+
+#
+# Old ISDN4Linux
+#
+# CONFIG_ISDN_I4L is not set
 
 #
 # CAPI subsystem
 #
 CONFIG_ISDN_CAPI=m
-CONFIG_ISDN_DRV_AVMB1_VERBOSE_REASON=y
-CONFIG_ISDN_CAPI_MIDDLEWARE=y
+# CONFIG_ISDN_DRV_AVMB1_VERBOSE_REASON is not set
+# CONFIG_ISDN_CAPI_MIDDLEWARE is not set
 CONFIG_ISDN_CAPI_CAPI20=m
-CONFIG_ISDN_CAPI_CAPIFS_BOOL=y
-CONFIG_ISDN_CAPI_CAPIFS=m
 
 #
 # CAPI hardware drivers
@@ -955,12 +970,18 @@ CONFIG_ISDN_CAPI_CAPIFS=m
 #
 # Active AVM cards
 #
-# CONFIG_CAPI_AVM is not set
+CONFIG_CAPI_AVM=y
 
 #
 # Active Eicon DIVA Server cards
 #
-# CONFIG_CAPI_EICON is not set
+CONFIG_CAPI_EICON=y
+CONFIG_ISDN_DIVAS=m
+CONFIG_ISDN_DIVAS_BRIPCI=y
+CONFIG_ISDN_DIVAS_PRIPCI=y
+CONFIG_ISDN_DIVAS_DIVACAPI=m
+CONFIG_ISDN_DIVAS_USERIDI=m
+CONFIG_ISDN_DIVAS_MAINT=m
 
 #
 # Telephony Support
@@ -1080,6 +1101,8 @@ CONFIG_I2C_SENSOR=m
 CONFIG_SENSORS_ADM1021=m
 CONFIG_SENSORS_ASB100=m
 CONFIG_SENSORS_EEPROM=m
+CONFIG_SENSORS_FSCHER=m
+CONFIG_SENSORS_GL518SM=m
 CONFIG_SENSORS_IT87=m
 CONFIG_SENSORS_LM75=m
 CONFIG_SENSORS_LM78=m
@@ -1100,11 +1123,11 @@ CONFIG_EXT2_FS=y
 CONFIG_EXT2_FS_XATTR=y
 CONFIG_EXT2_FS_POSIX_ACL=y
 CONFIG_EXT2_FS_SECURITY=y
-CONFIG_EXT3_FS=m
+CONFIG_EXT3_FS=y
 CONFIG_EXT3_FS_XATTR=y
 CONFIG_EXT3_FS_POSIX_ACL=y
 CONFIG_EXT3_FS_SECURITY=y
-CONFIG_JBD=m
+CONFIG_JBD=y
 # CONFIG_JBD_DEBUG is not set
 CONFIG_FS_MBCACHE=y
 # CONFIG_REISERFS_FS is not set
@@ -1116,6 +1139,7 @@ CONFIG_FS_POSIX_ACL=y
 CONFIG_XFS_FS=m
 # CONFIG_XFS_RT is not set
 CONFIG_XFS_QUOTA=y
+CONFIG_XFS_SECURITY=y
 CONFIG_XFS_POSIX_ACL=y
 CONFIG_MINIX_FS=m
 CONFIG_ROMFS_FS=m
@@ -1145,7 +1169,9 @@ CONFIG_VFAT_FS=m
 #
 CONFIG_PROC_FS=y
 CONFIG_PROC_KCORE=y
-# CONFIG_DEVFS_FS is not set
+CONFIG_DEVFS_FS=y
+CONFIG_DEVFS_MOUNT=y
+# CONFIG_DEVFS_DEBUG is not set
 CONFIG_DEVPTS_FS=y
 CONFIG_DEVPTS_FS_XATTR=y
 # CONFIG_DEVPTS_FS_SECURITY is not set
@@ -1205,7 +1231,6 @@ CONFIG_NCP_FS=m
 # CONFIG_NCPFS_EXTRAS is not set
 CONFIG_CODA_FS=m
 # CONFIG_CODA_FS_OLD_API is not set
-# CONFIG_INTERMEZZO_FS is not set
 CONFIG_AFS_FS=m
 CONFIG_RXRPC=m
 
@@ -1386,6 +1411,7 @@ CONFIG_SND_VIRMIDI=m
 #
 CONFIG_SND_ALI5451=m
 CONFIG_SND_AZT3328=m
+CONFIG_SND_BT87X=m
 CONFIG_SND_CS46XX=m
 # CONFIG_SND_CS46XX_NEW_DSP is not set
 CONFIG_SND_CS4281=m
@@ -1488,7 +1514,6 @@ CONFIG_USB_KBTAB=m
 # USB Imaging devices
 #
 CONFIG_USB_MDC800=m
-CONFIG_USB_SCANNER=m
 CONFIG_USB_MICROTEK=m
 CONFIG_USB_HPUSBSCSI=m
 
@@ -1594,12 +1619,29 @@ CONFIG_USB_LCD=m
 CONFIG_USB_LED=m
 CONFIG_USB_SPEEDTOUCH=m
 CONFIG_USB_TEST=m
+
+#
+# USB Gadget Support
+#
 # CONFIG_USB_GADGET is not set
 
 #
-# Watchdog
+# Watchdog Cards
+#
+CONFIG_WATCHDOG=y
+# CONFIG_WATCHDOG_NOWAYOUT is not set
+
+#
+# Watchdog Device Drivers
+#
+CONFIG_SOFT_WATCHDOG=m
+
+#
+# PCI-based Watchdog Cards
 #
-# CONFIG_SOFT_WATCHDOG is not set
+CONFIG_PCIPCWATCHDOG=m
+CONFIG_WDTPCI=m
+CONFIG_WDT_501_PCI=y
 
 #
 # Profiling support
@@ -1619,6 +1661,7 @@ CONFIG_MAGIC_SYSRQ=y
 # CONFIG_DEBUG_DCFLUSH is not set
 # CONFIG_DEBUG_INFO is not set
 # CONFIG_STACK_DEBUG is not set
+# CONFIG_DEBUG_BOOTMEM is not set
 CONFIG_HAVE_DEC_LOCK=y
 
 #
--- diff/arch/sparc64/kernel/ioctl32.c	2003-10-09 09:47:33.000000000 +0100
+++ source/arch/sparc64/kernel/ioctl32.c	2004-02-23 13:56:39.000000000 +0000
@@ -12,6 +12,7 @@
 #define INCLUDES
 #include "compat_ioctl.c"
 #include <linux/ncp_fs.h>
+#include <linux/syscalls.h>
 #include <asm/fbio.h>
 #include <asm/kbio.h>
 #include <asm/vuid_event.h>
--- diff/arch/sparc64/kernel/irq.c	2004-01-19 10:22:55.000000000 +0000
+++ source/arch/sparc64/kernel/irq.c	2004-02-23 13:56:39.000000000 +0000
@@ -1211,7 +1211,7 @@ static int irq_affinity_read_proc (char 
 	if (cpus_empty(mask))
 		mask = cpu_online_map;
 
-	len = cpumask_snprintf(page, count, mask);
+	len = cpumask_scnprintf(page, count, mask);
 	if (count - len < 2)
 		return -EINVAL;
 	len += sprintf(page + len, "\n");
--- diff/arch/sparc64/kernel/setup.c	2004-02-09 10:36:09.000000000 +0000
+++ source/arch/sparc64/kernel/setup.c	2004-02-23 13:56:39.000000000 +0000
@@ -21,6 +21,7 @@
 #include <linux/config.h>
 #include <linux/fs.h>
 #include <linux/seq_file.h>
+#include <linux/syscalls.h>
 #include <linux/kdev_t.h>
 #include <linux/major.h>
 #include <linux/string.h>
@@ -71,7 +72,6 @@ struct screen_info screen_info = {
 
 void (*prom_palette)(int);
 void (*prom_keyboard)(void);
-asmlinkage void sys_sync(void);	/* it's really int */
 
 static void
 prom_console_write(struct console *con, const char *s, unsigned n)
@@ -603,7 +603,7 @@ static int __init set_preferred_console(
 }
 console_initcall(set_preferred_console);
 
-asmlinkage int sys_ioperm(unsigned long from, unsigned long num, int on)
+asmlinkage long sys_ioperm(unsigned long from, unsigned long num, int on)
 {
 	return -EIO;
 }
--- diff/arch/sparc64/kernel/sparc64_ksyms.c	2004-01-19 10:22:55.000000000 +0000
+++ source/arch/sparc64/kernel/sparc64_ksyms.c	2004-02-23 13:56:39.000000000 +0000
@@ -22,6 +22,7 @@
 #include <linux/fs.h>
 #include <linux/mm.h>
 #include <linux/socket.h>
+#include <linux/syscalls.h>
 #include <linux/percpu.h>
 #include <net/compat.h>
 
@@ -84,21 +85,13 @@ extern void syscall_trace(void);
 extern u32 sunos_sys_table[], sys_call_table32[];
 extern void tl0_solaris(void);
 extern void sys_sigsuspend(void);
-extern int sys_getppid(void);
-extern int sys_getpid(void);
-extern int sys_geteuid(void);
-extern int sys_getuid(void);
-extern int sys_getegid(void);
-extern int sys_getgid(void);
 extern int svr4_getcontext(svr4_ucontext_t *uc, struct pt_regs *regs);
 extern int svr4_setcontext(svr4_ucontext_t *uc, struct pt_regs *regs);
-extern int sys_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg);
 extern int compat_sys_ioctl(unsigned int fd, unsigned int cmd, u32 arg);
 extern int (*handle_mathemu)(struct pt_regs *, struct fpustate *);
 extern long sparc32_open(const char * filename, int flags, int mode);
 extern int io_remap_page_range(struct vm_area_struct *vma, unsigned long from, unsigned long offset, unsigned long size, pgprot_t prot, int space);
-extern long sys_close(unsigned int);
-                
+
 extern int __ashrdi3(int, int);
 
 extern void dump_thread(struct pt_regs *, struct user *);
--- diff/arch/sparc64/kernel/sunos_ioctl32.c	2003-05-21 11:50:14.000000000 +0100
+++ source/arch/sparc64/kernel/sunos_ioctl32.c	2004-02-23 13:56:39.000000000 +0000
@@ -22,6 +22,7 @@
 #include <linux/mm.h>
 #include <linux/smp.h>
 #include <linux/smp_lock.h>
+#include <linux/syscalls.h>
 #include <linux/compat.h>
 #include <asm/kbio.h>
 
@@ -90,8 +91,6 @@ struct ifconf32 {
         compat_caddr_t  ifcbuf;
 };
 
-extern asmlinkage int sys_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg);
-
 extern asmlinkage int compat_sys_ioctl(unsigned int, unsigned int, u32);
 extern asmlinkage int sys_setsid(void);
 
--- diff/arch/sparc64/kernel/sys_sparc.c	2003-07-22 18:54:27.000000000 +0100
+++ source/arch/sparc64/kernel/sys_sparc.c	2004-02-23 13:56:39.000000000 +0000
@@ -22,6 +22,7 @@
 #include <linux/smp.h>
 #include <linux/smp_lock.h>
 #include <linux/slab.h>
+#include <linux/syscalls.h>
 #include <linux/ipc.h>
 #include <linux/personality.h>
 
@@ -161,8 +162,6 @@ unsigned long get_fb_unmapped_area(struc
 	return addr;
 }
 
-extern asmlinkage unsigned long sys_brk(unsigned long brk);
-
 asmlinkage unsigned long sparc_brk(unsigned long brk)
 {
 	/* People could try to be nasty and use ta 0x6d in 32bit programs */
@@ -280,8 +279,6 @@ out:
 	return err;
 }
 
-extern asmlinkage int sys_newuname(struct new_utsname __user *name);
-
 asmlinkage int sparc64_newuname(struct new_utsname __user *name)
 {
 	int ret = sys_newuname(name);
@@ -292,8 +289,6 @@ asmlinkage int sparc64_newuname(struct n
 	return ret;
 }
 
-extern asmlinkage long sys_personality(unsigned long);
-
 asmlinkage int sparc64_personality(unsigned long personality)
 {
 	int ret;
--- diff/arch/sparc64/kernel/sys_sparc32.c	2004-02-18 08:54:08.000000000 +0000
+++ source/arch/sparc64/kernel/sys_sparc32.c	2004-02-23 13:56:39.000000000 +0000
@@ -47,6 +47,7 @@
 #include <linux/ipv6.h>
 #include <linux/in.h>
 #include <linux/icmpv6.h>
+#include <linux/syscalls.h>
 #include <linux/sysctl.h>
 #include <linux/binfmts.h>
 #include <linux/dnotify.h>
@@ -88,17 +89,6 @@
 	__ret;				\
 })
 
-extern asmlinkage long sys_chown(const char *, uid_t,gid_t);
-extern asmlinkage long sys_lchown(const char *, uid_t,gid_t);
-extern asmlinkage long sys_fchown(unsigned int, uid_t,gid_t);
-extern asmlinkage long sys_setregid(gid_t, gid_t);
-extern asmlinkage long sys_setgid(gid_t);
-extern asmlinkage long sys_setreuid(uid_t, uid_t);
-extern asmlinkage long sys_setuid(uid_t);
-extern asmlinkage long sys_setresuid(uid_t, uid_t, uid_t);
-extern asmlinkage long sys_setresgid(gid_t, gid_t, gid_t);
-extern asmlinkage long sys_setfsuid(uid_t);
-extern asmlinkage long sys_setfsgid(gid_t);
  
 asmlinkage long sys32_chown16(const char * filename, u16 user, u16 group)
 {
@@ -179,40 +169,81 @@ asmlinkage long sys32_setfsgid16(u16 gid
 	return sys_setfsgid((gid_t)gid);
 }
 
+static int groups16_to_user(u16 *grouplist, struct group_info *group_info)
+{
+	int i;
+	u16 group;
+
+	for (i = 0; i < group_info->ngroups; i++) {
+		group = (u16)GROUP_AT(group_info, i);
+		if (put_user(group, grouplist+i))
+			return -EFAULT;
+	}
+
+	return 0;
+}
+
+static int groups16_from_user(struct group_info *group_info, u16 *grouplist)
+{
+	int i;
+	u16 group;
+
+	for (i = 0; i < group_info->ngroups; i++) {
+		if (get_user(group, grouplist+i))
+			return  -EFAULT;
+		GROUP_AT(group_info, i) = (gid_t)group;
+	}
+
+	return 0;
+}
+
 asmlinkage long sys32_getgroups16(int gidsetsize, u16 *grouplist)
 {
-	u16 groups[NGROUPS];
-	int i,j;
+	int i;
 
 	if (gidsetsize < 0)
 		return -EINVAL;
-	i = current->ngroups;
+
+	get_group_info(current->group_info);
+	i = current->group_info->ngroups;
 	if (gidsetsize) {
-		if (i > gidsetsize)
-			return -EINVAL;
-		for(j=0;j<i;j++)
-			groups[j] = current->groups[j];
-		if (copy_to_user(grouplist, groups, sizeof(u16)*i))
-			return -EFAULT;
+		if (i > gidsetsize) {
+			i = -EINVAL;
+			goto out;
+		}
+		if (groups16_to_user(grouplist, current->group_info)) {
+			i = -EFAULT;
+			goto out;
+		}
 	}
+out:
+	put_group_info(current->group_info);
 	return i;
 }
 
 asmlinkage long sys32_setgroups16(int gidsetsize, u16 *grouplist)
 {
-	u16 groups[NGROUPS];
-	int i;
+	struct group_info *group_info;
+	int retval;
 
 	if (!capable(CAP_SETGID))
 		return -EPERM;
-	if ((unsigned) gidsetsize > NGROUPS)
+	if ((unsigned)gidsetsize > NGROUPS_MAX)
 		return -EINVAL;
-	if (copy_from_user(groups, grouplist, gidsetsize * sizeof(u16)))
-		return -EFAULT;
-	for (i = 0 ; i < gidsetsize ; i++)
-		current->groups[i] = (gid_t)groups[i];
-	current->ngroups = gidsetsize;
-	return 0;
+
+	group_info = groups_alloc(gidsetsize);
+	if (!group_info)
+		return -ENOMEM;
+	retval = groups16_from_user(group_info, grouplist);
+	if (retval) {
+		put_group_info(group_info);
+		return retval;
+	}
+
+	retval = set_current_groups(group_info);
+	put_group_info(group_info);
+
+	return retval;
 }
 
 asmlinkage long sys32_getuid16(void)
@@ -251,9 +282,7 @@ static inline long put_tv32(struct compa
 		 __put_user(i->tv_usec, &o->tv_usec)));
 }
 
-extern asmlinkage int sys_ioperm(unsigned long from, unsigned long num, int on);
-
-asmlinkage int sys32_ioperm(u32 from, u32 num, int on)
+asmlinkage long sys32_ioperm(u32 from, u32 num, int on)
 {
 	return sys_ioperm((unsigned long)from, (unsigned long)num, on);
 }
@@ -795,9 +824,6 @@ out:
 	return err;
 }
 
-extern asmlinkage long sys_truncate(const char * path, unsigned long length);
-extern asmlinkage long sys_ftruncate(unsigned int fd, unsigned long length);
-
 asmlinkage int sys32_truncate64(const char * path, unsigned long high, unsigned long low)
 {
 	if ((int)high < 0)
@@ -1303,8 +1329,6 @@ int cp_compat_stat(struct kstat *stat, s
 	return err;
 }
 
-extern asmlinkage int sys_sysfs(int option, unsigned long arg1, unsigned long arg2);
-
 asmlinkage int sys32_sysfs(int option, u32 arg1, u32 arg2)
 {
 	return sys_sysfs(option, arg1, arg2);
@@ -1530,8 +1554,6 @@ struct sysinfo32 {
 	char _f[20-2*sizeof(int)-sizeof(int)];
 };
 
-extern asmlinkage int sys_sysinfo(struct sysinfo *info);
-
 asmlinkage int sys32_sysinfo(struct sysinfo32 *info)
 {
 	struct sysinfo s;
@@ -1579,8 +1601,6 @@ asmlinkage int sys32_sysinfo(struct sysi
 	return ret;
 }
 
-extern asmlinkage int sys_sched_rr_get_interval(pid_t pid, struct timespec *interval);
-
 asmlinkage int sys32_sched_rr_get_interval(compat_pid_t pid, struct compat_timespec *interval)
 {
 	struct timespec t;
@@ -1595,8 +1615,6 @@ asmlinkage int sys32_sched_rr_get_interv
 	return ret;
 }
 
-extern asmlinkage int sys_rt_sigprocmask(int how, sigset_t *set, sigset_t *oset, size_t sigsetsize);
-
 asmlinkage int sys32_rt_sigprocmask(int how, compat_sigset_t *set, compat_sigset_t *oset, compat_size_t sigsetsize)
 {
 	sigset_t s;
@@ -1631,8 +1649,6 @@ asmlinkage int sys32_rt_sigprocmask(int 
 	return 0;
 }
 
-extern asmlinkage int sys_rt_sigpending(sigset_t *set, size_t sigsetsize);
-
 asmlinkage int sys32_rt_sigpending(compat_sigset_t *set, compat_size_t sigsetsize)
 {
 	sigset_t s;
@@ -1740,9 +1756,6 @@ sys32_rt_sigtimedwait(compat_sigset_t *u
 	return ret;
 }
 
-extern asmlinkage int
-sys_rt_sigqueueinfo(int pid, int sig, siginfo_t *uinfo);
-
 asmlinkage int
 sys32_rt_sigqueueinfo(int pid, int sig, siginfo_t32 *uinfo)
 {
@@ -2073,15 +2086,11 @@ out:
 
 #ifdef CONFIG_MODULES
 
-extern asmlinkage long sys_init_module(void *, unsigned long, const char *);
-
 asmlinkage int sys32_init_module(void *umod, u32 len, const char *uargs)
 {
 	return sys_init_module(umod, len, uargs);
 }
 
-extern asmlinkage long sys_delete_module(const char *, unsigned int);
-
 asmlinkage int sys32_delete_module(const char *name_user, unsigned int flags)
 {
 	return sys_delete_module(name_user, flags);
@@ -2323,7 +2332,6 @@ done:
 	return err;
 }
 #else /* !NFSD */
-extern asmlinkage long sys_ni_syscall(void);
 int asmlinkage sys32_nfsservctl(int cmd, void *notused, void *notused2)
 {
 	return sys_ni_syscall();
@@ -2416,17 +2424,6 @@ asmlinkage int sys32_pause(void)
 }
 
 /* PCI config space poking. */
-extern asmlinkage int sys_pciconfig_read(unsigned long bus,
-					 unsigned long dfn,
-					 unsigned long off,
-					 unsigned long len,
-					 unsigned char *buf);
-
-extern asmlinkage int sys_pciconfig_write(unsigned long bus,
-					  unsigned long dfn,
-					  unsigned long off,
-					  unsigned long len,
-					  unsigned char *buf);
 
 asmlinkage int sys32_pciconfig_read(u32 bus, u32 dfn, u32 off, u32 len, u32 ubuf)
 {
@@ -2446,9 +2443,6 @@ asmlinkage int sys32_pciconfig_write(u32
 				   (unsigned char *)AA(ubuf));
 }
 
-extern asmlinkage int sys_prctl(int option, unsigned long arg2, unsigned long arg3,
-				unsigned long arg4, unsigned long arg5);
-
 asmlinkage int sys32_prctl(int option, u32 arg2, u32 arg3, u32 arg4, u32 arg5)
 {
 	return sys_prctl(option,
@@ -2459,12 +2453,6 @@ asmlinkage int sys32_prctl(int option, u
 }
 
 
-extern asmlinkage ssize_t sys_pread64(unsigned int fd, char * buf,
-				    size_t count, loff_t pos);
-
-extern asmlinkage ssize_t sys_pwrite64(unsigned int fd, const char * buf,
-				     size_t count, loff_t pos);
-
 asmlinkage compat_ssize_t sys32_pread64(unsigned int fd, char *ubuf,
 				   compat_size_t count, u32 poshi, u32 poslo)
 {
@@ -2477,8 +2465,6 @@ asmlinkage compat_ssize_t sys32_pwrite64
 	return sys_pwrite64(fd, ubuf, count, ((loff_t)AA(poshi) << 32) | AA(poslo));
 }
 
-extern asmlinkage ssize_t sys_readahead(int fd, loff_t offset, size_t count);
-
 asmlinkage compat_ssize_t sys32_readahead(int fd, u32 offhi, u32 offlo, s32 count)
 {
 	return sys_readahead(fd, ((loff_t)AA(offhi) << 32) | AA(offlo), count);
@@ -2495,8 +2481,6 @@ long sys32_fadvise64_64(int fd, u32 offh
 				((loff_t)AA(lenhi)<<32)|AA(lenlo), advice);
 }
 
-extern asmlinkage ssize_t sys_sendfile(int out_fd, int in_fd, off_t *offset, size_t count);
-
 asmlinkage int sys32_sendfile(int out_fd, int in_fd, compat_off_t *offset, s32 count)
 {
 	mm_segment_t old_fs = get_fs();
@@ -2516,8 +2500,6 @@ asmlinkage int sys32_sendfile(int out_fd
 	return ret;
 }
 
-extern asmlinkage ssize_t sys_sendfile64(int out_fd, int in_fd, loff_t *offset, size_t count);
-
 asmlinkage int sys32_sendfile64(int out_fd, int in_fd, compat_loff_t *offset, s32 count)
 {
 	mm_segment_t old_fs = get_fs();
@@ -2692,8 +2674,6 @@ out:
 	return ret;       
 }
 
-extern asmlinkage long sys_setpriority(int which, int who, int niceval);
-
 asmlinkage int sys_setpriority32(u32 which, u32 who, u32 niceval)
 {
 	return sys_setpriority((int) which,
@@ -2753,8 +2733,6 @@ asmlinkage long sys32_sysctl(struct __sy
 #endif
 }
 
-extern long sys_lookup_dcookie(u64 cookie64, char *buf, size_t len);
-
 long sys32_lookup_dcookie(u32 cookie_high, u32 cookie_low, char *buf, size_t len)
 {
 	return sys_lookup_dcookie((u64)cookie_high << 32 | cookie_low,
--- diff/arch/sparc64/kernel/sys_sunos32.c	2003-09-17 12:28:03.000000000 +0100
+++ source/arch/sparc64/kernel/sys_sunos32.c	2004-02-23 13:56:39.000000000 +0000
@@ -33,6 +33,7 @@
 #include <linux/errno.h>
 #include <linux/smp.h>
 #include <linux/smp_lock.h>
+#include <linux/syscalls.h>
 
 #include <asm/uaccess.h>
 #include <asm/page.h>
@@ -584,11 +585,6 @@ struct sunos_nfs_mount_args {
 	char       *netname;   /* server's netname */
 };
 
-extern asmlinkage int sys_mount(char *, char *, char *, unsigned long, void *);
-extern asmlinkage int sys_connect(int fd, struct sockaddr *uservaddr, int addrlen);
-extern asmlinkage int sys_socket(int family, int type, int protocol);
-extern asmlinkage int sys_bind(int fd, struct sockaddr *umyaddr, int addrlen);
-
 
 /* Bind the socket on a local reserved port and connect it to the
  * remote server.  This on Linux/i386 is done by the mount program,
@@ -781,8 +777,6 @@ out:
 	return ret;
 }
 
-extern asmlinkage int sys_setsid(void);
-extern asmlinkage int sys_setpgid(pid_t, pid_t);
 
 asmlinkage int sunos_setpgrp(pid_t pid, pid_t pgid)
 {
@@ -1200,11 +1194,6 @@ static inline int check_nonblock(int ret
 	return ret;
 }
 
-extern asmlinkage ssize_t sys_read(unsigned int fd, char *buf, unsigned long count);
-extern asmlinkage ssize_t sys_write(unsigned int fd, char *buf, unsigned long count);
-extern asmlinkage int sys_recv(int fd, void *ubuf, size_t size, unsigned flags);
-extern asmlinkage int sys_send(int fd, void *buff, size_t len, unsigned flags);
-extern asmlinkage int sys_accept(int fd, struct sockaddr *sa, int *addrlen);
 extern asmlinkage int sys32_readv(u32 fd, u32 vector, s32 count);
 extern asmlinkage int sys32_writev(u32 fd, u32 vector, s32 count);
 
@@ -1302,9 +1291,6 @@ asmlinkage int sunos_sigaction (int sig,
 	return ret;
 }
 
-extern asmlinkage int sys_setsockopt(int fd, int level, int optname,
-				     char *optval, int optlen);
-
 asmlinkage int sunos_setsockopt(int fd, int level, int optname, u32 optval,
 				int optlen)
 {
--- diff/arch/sparc64/kernel/time.c	2003-11-25 15:24:57.000000000 +0000
+++ source/arch/sparc64/kernel/time.c	2004-02-23 13:56:39.000000000 +0000
@@ -1126,6 +1126,7 @@ int do_settimeofday(struct timespec *tv)
 	time_maxerror = NTP_PHASE_LIMIT;
 	time_esterror = NTP_PHASE_LIMIT;
 	write_sequnlock_irq(&xtime_lock);
+	clock_was_set();
 	return 0;
 }
 
--- diff/arch/sparc64/lib/rwlock.S	2003-11-25 15:24:57.000000000 +0000
+++ source/arch/sparc64/lib/rwlock.S	2004-02-23 13:56:39.000000000 +0000
@@ -85,5 +85,20 @@ __write_trylock_succeed:
 __write_trylock_fail:
 	retl
 	 mov		0, %o0
+
+	.globl	__read_trylock
+__read_trylock: /* %o0 = lock_ptr */
+	ldsw		[%o0], %g5
+	brlz,pn		%g5, 100f
+	add		%g5, 1, %g7
+	cas		[%o0], %g5, %g7
+	cmp		%g5, %g7
+	bne,pn		%icc, __read_trylock
+	 membar		#StoreLoad | #StoreStore
+	retl
+	mov		1, %o0
+100:	retl
+	mov		0, %o0
+
 rwlock_impl_end:
 
--- diff/arch/sparc64/prom/printf.c	2003-05-21 11:50:14.000000000 +0100
+++ source/arch/sparc64/prom/printf.c	2004-02-23 13:56:39.000000000 +0000
@@ -40,7 +40,7 @@ prom_printf(char *fmt, ...)
 	int i;
 
 	va_start(args, fmt);
-	i = vsnprintf(ppbuf, sizeof(ppbuf), fmt, args);
+	i = vscnprintf(ppbuf, sizeof(ppbuf), fmt, args);
 	va_end(args);
 
 	prom_write(ppbuf, i);
--- diff/arch/sparc64/solaris/ioctl.c	2003-05-21 11:50:14.000000000 +0100
+++ source/arch/sparc64/solaris/ioctl.c	2004-02-23 13:56:39.000000000 +0000
@@ -17,6 +17,7 @@
 #include <linux/sched.h>
 #include <linux/smp.h>
 #include <linux/smp_lock.h>
+#include <linux/syscalls.h>
 #include <linux/ioctl.h>
 #include <linux/fs.h>
 #include <linux/file.h>
@@ -34,8 +35,6 @@
 #include "conv.h"
 #include "socksys.h"
 
-extern asmlinkage int sys_ioctl(unsigned int fd, unsigned int cmd, 
-	unsigned long arg);
 extern asmlinkage int compat_sys_ioctl(unsigned int fd, unsigned int cmd,
 	u32 arg);
 asmlinkage int solaris_ioctl(unsigned int fd, unsigned int cmd, u32 arg);
--- diff/arch/sparc64/solaris/socksys.c	2003-09-17 12:28:03.000000000 +0100
+++ source/arch/sparc64/solaris/socksys.c	2004-02-23 13:56:39.000000000 +0000
@@ -24,6 +24,7 @@
 #include <linux/init.h>
 #include <linux/poll.h>
 #include <linux/slab.h>
+#include <linux/syscalls.h>
 #include <linux/in.h>
 #include <linux/devfs_fs_kernel.h>
 
@@ -35,9 +36,6 @@
 #include "conv.h"
 #include "socksys.h"
 
-extern asmlinkage int sys_ioctl(unsigned int fd, unsigned int cmd, 
-	unsigned long arg);
-	
 static int af_inet_protocols[] = {
 IPPROTO_ICMP, IPPROTO_ICMP, IPPROTO_IGMP, IPPROTO_IPIP, IPPROTO_TCP,
 IPPROTO_EGP, IPPROTO_PUP, IPPROTO_UDP, IPPROTO_IDP, IPPROTO_RAW,
--- diff/arch/sparc64/solaris/timod.c	2003-09-17 12:28:03.000000000 +0100
+++ source/arch/sparc64/solaris/timod.c	2004-02-23 13:56:39.000000000 +0000
@@ -27,8 +27,6 @@
 #include "conv.h"
 #include "socksys.h"
 
-extern asmlinkage int sys_ioctl(unsigned int fd, unsigned int cmd, 
-	unsigned long arg);
 asmlinkage int solaris_ioctl(unsigned int fd, unsigned int cmd, u32 arg);
 
 static spinlock_t timod_pagelock = SPIN_LOCK_UNLOCKED;
--- diff/arch/um/Makefile-i386	2003-10-09 09:47:16.000000000 +0100
+++ source/arch/um/Makefile-i386	2004-02-23 13:56:39.000000000 +0000
@@ -9,7 +9,6 @@ ELF_ARCH = $(SUBARCH)
 ELF_FORMAT = elf32-$(SUBARCH)
 
 OBJCOPYFLAGS  := -O binary -R .note -R .comment -S
-LDFLAGS_BLOB	:= --format binary --oformat elf32-i386
 
 SYS_DIR		:= $(ARCH_DIR)/include/sysdep-i386
 SYS_UTIL_DIR	:= $(ARCH_DIR)/sys-i386/util
--- diff/arch/um/drivers/net_kern.c	2003-10-09 09:47:16.000000000 +0100
+++ source/arch/um/drivers/net_kern.c	2004-02-23 13:56:39.000000000 +0000
@@ -358,8 +358,12 @@ static int eth_configure(int n, void *in
 	rtnl_lock();
 	err = register_netdevice(dev);
 	rtnl_unlock();
-	if (err)
+	if (err) {
+		device->dev = NULL;
+		/* XXX: should we call ->remove() here? */
+		free_netdev(dev);
 		return 1;
+	}
 	lp = dev->priv;
 
 	INIT_LIST_HEAD(&lp->list);
--- diff/arch/um/include/kern_util.h	2003-10-09 09:47:16.000000000 +0100
+++ source/arch/um/include/kern_util.h	2004-02-23 13:56:39.000000000 +0000
@@ -45,7 +45,6 @@ extern int page_mask(void);
 extern int need_finish_fork(void);
 extern void free_stack(unsigned long stack, int order);
 extern void add_input_request(int op, void (*proc)(int), void *arg);
-extern int sys_execve(char *file, char **argv, char **env);
 extern char *current_cmd(void);
 extern void timer_handler(int sig, union uml_pt_regs *regs);
 extern int set_signals(int enable);
--- diff/arch/um/kernel/irq.c	2004-01-19 10:22:55.000000000 +0000
+++ source/arch/um/kernel/irq.c	2004-02-23 13:56:39.000000000 +0000
@@ -575,7 +575,7 @@ static cpumask_t irq_affinity [NR_IRQS] 
 static int irq_affinity_read_proc (char *page, char **start, off_t off,
 			int count, int *eof, void *data)
 {
-	int len = cpumask_snprintf(page, count, irq_affinity[(long)data]);
+	int len = cpumask_scnprintf(page, count, irq_affinity[(long)data]);
 	if (count - len < 2)
 		return -EINVAL;
 	len += sprintf(page + len, "\n");
@@ -613,7 +613,7 @@ static int irq_affinity_write_proc (stru
 static int prof_cpu_mask_read_proc (char *page, char **start, off_t off,
 			int count, int *eof, void *data)
 {
-	int len = cpumask_snprintf(page, count, *(cpumask_t *)data);
+	int len = cpumask_scnprintf(page, count, *(cpumask_t *)data);
 	if (count - len < 2)
 		return -EINVAL;
 	len += sprintf(page + len, "\n");
--- diff/arch/um/kernel/sys_call_table.c	2003-10-09 09:47:16.000000000 +0100
+++ source/arch/um/kernel/sys_call_table.c	2004-02-23 13:56:39.000000000 +0000
@@ -8,6 +8,7 @@
 #include "linux/version.h"
 #include "linux/sys.h"
 #include "linux/swap.h"
+#include "linux/syscalls.h"
 #include "linux/sysctl.h"
 #include "asm/signal.h"
 #include "sysdep/syscalls.h"
@@ -268,9 +269,9 @@ syscall_handler_t *sys_call_table[] = {
 	[ __NR_creat ] = sys_creat,
 	[ __NR_link ] = sys_link,
 	[ __NR_unlink ] = sys_unlink,
+	[ __NR_execve ] = (syscall_handler_t *) sys_execve,
 
 	/* declared differently in kern_util.h */
-	[ __NR_execve ] = (syscall_handler_t *) sys_execve,
 	[ __NR_chdir ] = sys_chdir,
 	[ __NR_time ] = um_time,
 	[ __NR_mknod ] = sys_mknod,
--- diff/arch/um/kernel/syscall_kern.c	2003-10-09 09:47:16.000000000 +0100
+++ source/arch/um/kernel/syscall_kern.c	2004-02-23 13:56:39.000000000 +0000
@@ -11,6 +11,7 @@
 #include "linux/msg.h"
 #include "linux/shm.h"
 #include "linux/sys.h"
+#include "linux/syscalls.h"
 #include "linux/unistd.h"
 #include "linux/slab.h"
 #include "linux/utime.h"
--- diff/arch/um/kernel/time.c	2003-10-09 09:47:33.000000000 +0100
+++ source/arch/um/kernel/time.c	2004-02-23 13:56:39.000000000 +0000
@@ -93,6 +93,7 @@ void do_gettimeofday(struct timeval *tv)
 	gettimeofday(tv, NULL);
 	timeradd(tv, &local_offset, tv);
 	time_unlock(flags);
+	clock_was_set();
 }
 
 EXPORT_SYMBOL(do_gettimeofday);
--- diff/arch/v850/Kconfig	2003-10-09 09:47:33.000000000 +0100
+++ source/arch/v850/Kconfig	2004-02-23 13:56:39.000000000 +0000
@@ -236,24 +236,6 @@ menu "Bus options (PCI, PCMCIA, EISA, MC
 
 source "drivers/pci/Kconfig"
 
-config HOTPLUG
-	bool "Support for hot-pluggable device"
-	  ---help---
-	  Say Y here if you want to plug devices into your computer while
-	  the system is running, and be able to use them quickly.  In many
-	  cases, the devices can likewise be unplugged at any time too.
-
-	  One well known example of this is PCMCIA- or PC-cards, credit-card
-	  size devices such as network cards, modems or hard drives which are
-	  plugged into slots found on all modern laptop computers.  Another
-	  example, used on modern desktops as well as laptops, is USB.
-
-	  Enable HOTPLUG and KMOD, and build a modular kernel.  Get agent
-	  software (at <http://linux-hotplug.sourceforge.net/>) and install it.
-	  Then your kernel will automatically call out to a user mode "policy
-	  agent" (/sbin/hotplug) to load modules and set up software needed
-	  to use devices as you hotplug them.
-
 source "drivers/pcmcia/Kconfig"
 
 source "drivers/pci/hotplug/Kconfig"
--- diff/arch/v850/kernel/ptrace.c	2003-06-30 10:07:20.000000000 +0100
+++ source/arch/v850/kernel/ptrace.c	2004-02-23 13:56:39.000000000 +0000
@@ -141,7 +141,7 @@ int sys_ptrace(long request, long pid, l
 
 	rval = -EPERM;
 	if (pid == 1)		/* you may not mess with init */
-		goto out;
+		goto out_tsk;
 
 	if (request == PTRACE_ATTACH) {
 		rval = ptrace_attach(child);
--- diff/arch/v850/kernel/syscalls.c	2002-12-30 10:17:12.000000000 +0000
+++ source/arch/v850/kernel/syscalls.c	2004-02-23 13:56:39.000000000 +0000
@@ -20,6 +20,7 @@
 #include <linux/mm.h>
 #include <linux/smp.h>
 #include <linux/smp_lock.h>
+#include <linux/syscalls.h>
 #include <linux/sem.h>
 #include <linux/msg.h>
 #include <linux/shm.h>
--- diff/arch/v850/kernel/time.c	2003-10-09 09:47:33.000000000 +0100
+++ source/arch/v850/kernel/time.c	2004-02-23 13:56:39.000000000 +0000
@@ -193,6 +193,7 @@ int do_settimeofday(struct timespec *tv)
 	time_esterror = NTP_PHASE_LIMIT;
 
 	write_sequnlock_irq (&xtime_lock);
+	clock_was_set();
 	return 0;
 }
 
--- diff/arch/x86_64/Kconfig	2004-02-09 10:36:09.000000000 +0000
+++ source/arch/x86_64/Kconfig	2004-02-23 13:56:39.000000000 +0000
@@ -15,6 +15,7 @@ config X86_64
 	help
 	  Port to the x86-64 architecture. x86-64 is a 64-bit extension to the
 	  classical 32-bit x86 architecture. For details see http://www.x86-64.org
+	  and http://www.intel.com/technology/64bitextensions/
 
 config 64BIT
 	def_bool y
@@ -48,12 +49,14 @@ config EARLY_PRINTK
 	bool
 	default y
 	help
-	  Write kernel log output directly into the VGA buffer. This is useful
-	  for kernel debugging when your machine crashes very early before
-	  the console code is initialized. For normal operation it is not
-	  recommended because it looks ugly and doesn't cooperate with 
-	  klogd/syslogd or the X server. You should normally N here, unless
-	  you want to debug such a crash.
+	  Write kernel log output directly into the VGA buffer or to a serial
+	  port.
+
+	  This is useful for kernel debugging when your machine crashes very
+	  early before the console code is initialized. For normal operation
+	  it is not recommended because it looks ugly and doesn't cooperate
+	  with klogd/syslogd or the X server. You should normally N here,
+	  unless you want to debug such a crash.
 	  
 config HPET_TIMER
 	bool
@@ -89,6 +92,11 @@ config MK8
 	help
 	  Optimize for AMD Opteron/Athlon64/Hammer/K8 CPUs. 
 
+config MPSC
+	bool "Intel x86-64"
+	help
+	  Optimize for Intel CPUs with 64-bit extension technology.
+       
 config GENERIC_CPU
 	bool "Generic-x86-64"
 	help
@@ -101,11 +109,13 @@ endchoice
 #
 config X86_L1_CACHE_BYTES
 	int
-	default "64"
+	default "128" if GENERIC_CPU || MPSC
+	default "64" if MK8
 
 config X86_L1_CACHE_SHIFT
 	int
-	default "6"
+	default "7" if GENERIC_CPU || MPSC
+	default "6" if MK8
 
 config X86_TSC
 	bool
@@ -115,6 +125,23 @@ config X86_GOOD_APIC
 	bool
 	default y
 
+config MICROCODE
+	tristate "/dev/cpu/microcode - Intel CPU microcode support"
+	---help---
+	  If you say Y here the 'File systems' section, you will be
+	  able to update the microcode on Intel processors. You will 
+	  obviously need the actual microcode binary data itself which is 
+	  not shipped with the Linux kernel.
+
+	  For latest news and information on obtaining all the required
+	  ingredients for this driver, check:
+	  <http://www.urbanmyth.org/microcode/>.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called microcode.
+	  If you use modprobe or kmod you may also want to add the line
+	  'alias char-major-10-184 microcode' to your /etc/modules.conf file.
+
 config X86_MSR
 	tristate "/dev/cpu/*/msr - Model-specific register support"
 	help
@@ -132,6 +159,11 @@ config X86_CPUID
 	  with major 203 and minors 0 to 31 for /dev/cpu/0/cpuid to
 	  /dev/cpu/31/cpuid.
 
+config X86_HT
+	bool
+	depends on SMP
+	default y
+       
 config MATH_EMULATION
 	bool
 
@@ -256,9 +288,13 @@ config GART_IOMMU
 	  Normally the kernel will take the right choice by itself.
 	  If unsure say Y 
 
+config SWIOTLB
+       select GART_IOMMU
+       bool "Software IOTLB support"
+
 config DUMMY_IOMMU
 	bool
-	depends on !GART_IOMMU
+	depends on !GART_IOMMU && !SWIOTLB
 	default y
 	help
 	  Don't use IOMMU code. This will cause problems when you have more than 4GB 
@@ -315,24 +351,6 @@ config PCI_USE_VECTOR
 
 source "drivers/pci/Kconfig"
 
-config HOTPLUG
-	bool "Support for hot-pluggable devices"
-	---help---
-	  Say Y here if you want to plug devices into your computer while
-	  the system is running, and be able to use them quickly.  In many
-	  cases, the devices can likewise be unplugged at any time too.
-
-	  One well-known example of this is PCMCIA- or PC-cards, credit-card
-	  size devices such as network cards, modems, or hard drives which are
-	  plugged into slots found on all modern laptop computers.  Another
-	  example, used on modern desktops as well as laptops, is USB.
-
-	  Enable HOTPLUG and KMOD, and build a modular kernel.  Get agent
-	  software (at <http://linux-hotplug.sourceforge.net/>) and install it.
-	  Then your kernel will automatically call out to a user mode "policy
-	  agent" (/sbin/hotplug) to load modules and set up software needed
-	  to use devices as you hotplug them.
-
 source "drivers/pcmcia/Kconfig"
 
 source "drivers/pci/hotplug/Kconfig"
@@ -362,6 +380,10 @@ config COMPAT
 	depends on IA32_EMULATION
 	default y
 
+config SYSVIPC_COMPAT
+	bool
+	depends on COMPAT && SYSVIPC
+	default y
 
 config UID16
 	bool
@@ -433,6 +455,7 @@ config INIT_DEBUG
 config DEBUG_INFO
 	bool "Compile the kernel with debug info"
 	depends on DEBUG_KERNEL
+	default n
 	help
           If you say Y here the resulting kernel image will include
 	  debugging info resulting in a larger kernel image.
@@ -464,9 +487,8 @@ config IOMMU_LEAK
        help
          Add a simple leak tracer to the IOMMU code. This is useful when you
 	 are debugging a buggy device driver that leaks IOMMU mappings.
-       
-#config X86_REMOTE_DEBUG
-#       bool "kgdb debugging stub"
+
+source "arch/x86_64/Kconfig.kgdb"
 
 endmenu
 
--- diff/arch/x86_64/Makefile	2004-02-09 10:36:09.000000000 +0000
+++ source/arch/x86_64/Makefile	2004-02-23 13:56:39.000000000 +0000
@@ -39,6 +39,10 @@ LDFLAGS_vmlinux := -e stext
 
 check_gcc = $(shell if $(CC) $(1) -S -o /dev/null -xc /dev/null > /dev/null 2>&1 ; then echo "$(1)"; else echo "$(2)"; fi)
 
+cflags-$(CONFIG_MK8) += $(call check_gcc,-march=k8,)
+cflags-$(CONFIG_MPSC) += $(call check_gcc,-march=pentium4,)
+CFLAGS += $(cflags-y)
+
 CFLAGS += -mno-red-zone
 CFLAGS += -mcmodel=kernel
 CFLAGS += -pipe
@@ -52,7 +56,10 @@ CFLAGS += -Wno-sign-compare
 ifneq ($(CONFIG_DEBUG_INFO),y)
 CFLAGS += -fno-asynchronous-unwind-tables
 endif
-#CFLAGS += $(call check_gcc,-funit-at-a-time,)
+
+# Enable unit-at-a-time mode when possible. It shrinks the
+# kernel considerably.
+CFLAGS += $(call check_gcc,-funit-at-a-time,)
 
 head-y := arch/x86_64/kernel/head.o arch/x86_64/kernel/head64.o arch/x86_64/kernel/init_task.o
 
--- diff/arch/x86_64/boot/setup.S	2003-07-22 18:54:27.000000000 +0100
+++ source/arch/x86_64/boot/setup.S	2004-02-23 13:56:39.000000000 +0000
@@ -292,8 +292,9 @@ loader_ok:
 	/* minimum CPUID flags for x86-64 */
 	/* see http://www.x86-64.org/lists/discuss/msg02971.html */		
 #define SSE_MASK ((1<<25)|(1<<26))
-#define REQUIRED_MASK1 ((1<<0)|(1<<3)|(1<<4)|(1<<5)|(1<<6)|(1<<8)|(1<<11)| \
-					   (1<<13)|(1<<15)|(1<<24)|(1<<29))
+#define REQUIRED_MASK1 ((1<<0)|(1<<3)|(1<<4)|(1<<5)|(1<<6)|(1<<8)|\
+					   (1<<13)|(1<<15)|(1<<24))
+#define REQUIRED_MASK2 (1<<29)
 
 	pushfl				/* standard way to check for cpuid */
 	popl	%eax
@@ -305,10 +306,10 @@ loader_ok:
 	popl	%eax
 	cmpl	%eax,%ebx
 	jz	no_longmode		/* cpu has no cpuid */
-	movl	$0x80000000,%eax
+	movl	$0x0,%eax
 	cpuid
-	cmpl	$0x80000001,%eax
-	jb	no_longmode		/* no extended cpuid */
+	cmpl	$0x1,%eax
+	jb	no_longmode		/* no cpuid 1 */
 	xor	%di,%di
 	cmpl	$0x68747541,%ebx	/* AuthenticAMD */
 	jnz	noamd
@@ -318,11 +319,20 @@ loader_ok:
 	jnz	noamd
 	mov	$1,%di			/* cpu is from AMD */
 noamd:		
-	movl	$0x80000001,%eax		
+	movl    $0x1,%eax
 	cpuid
 	andl	$REQUIRED_MASK1,%edx
 	xorl	$REQUIRED_MASK1,%edx
 	jnz	no_longmode
+	movl    $0x80000000,%eax
+	cpuid
+	cmpl    $0x80000001,%eax
+	jb      no_longmode             /* no extended cpuid */
+	movl    $0x80000001,%eax
+	cpuid
+	andl    $REQUIRED_MASK2,%edx
+	xorl    $REQUIRED_MASK2,%edx
+	jnz     no_longmode
 sse_test:		
 	movl	$1,%eax
 	cpuid
--- diff/arch/x86_64/ia32/ia32_ioctl.c	2004-01-19 10:22:55.000000000 +0000
+++ source/arch/x86_64/ia32/ia32_ioctl.c	2004-02-23 13:56:39.000000000 +0000
@@ -10,12 +10,11 @@
  */
 
 #define INCLUDES
+#include <linux/syscalls.h>
 #include "compat_ioctl.c"
 #include <asm/mtrr.h>
 #include <asm/ia32.h>
 
-extern asmlinkage long sys_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg);
-
 #define CODE
 #include "compat_ioctl.c"
   
--- diff/arch/x86_64/ia32/ipc32.c	2003-08-20 14:16:26.000000000 +0100
+++ source/arch/x86_64/ia32/ipc32.c	2004-02-23 13:56:39.000000000 +0000
@@ -1,655 +1,19 @@
 #include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/fs.h> 
-#include <linux/file.h> 
+#include <linux/spinlock.h>
+#include <linux/list.h>
+#include <linux/syscalls.h>
+#include <linux/time.h>
 #include <linux/sem.h>
 #include <linux/msg.h>
-#include <linux/mm.h>
 #include <linux/shm.h>
-#include <linux/slab.h>
 #include <linux/ipc.h>
 #include <linux/compat.h>
-#include <asm/mman.h>
-#include <asm/types.h>
-#include <asm/uaccess.h>
-#include <asm/semaphore.h>
-#include <asm/ipc.h>
-
-#include <asm/ia32.h>
-
-/*
- * sys32_ipc() is the de-multiplexer for the SysV IPC calls in 32bit emulation..
- *
- * This is really horribly ugly.
- */
-
-struct msgbuf32 { 
-	s32 mtype; 
-	char mtext[1]; 
-};
-
-struct ipc_perm32 {
-	int key;
-	compat_uid_t uid;
-	compat_gid_t gid;
-	compat_uid_t cuid;
-	compat_gid_t cgid;
-	unsigned short mode;
-	unsigned short seq;
-};
-
-struct ipc64_perm32 {
-        unsigned key;
-	compat_uid32_t uid;
-	compat_gid32_t gid;
-	compat_uid32_t cuid;
-	compat_gid32_t cgid;
-	unsigned short mode;
-	unsigned short __pad1;
-	unsigned short seq;
-	unsigned short __pad2;
-	unsigned int unused1;
-	unsigned int unused2;
-};
-
-struct semid_ds32 {
-	struct ipc_perm32 sem_perm;               /* permissions .. see ipc.h */
-	compat_time_t sem_otime;              /* last semop time */
-	compat_time_t sem_ctime;              /* last change time */
-	u32 sem_base;              /* ptr to first semaphore in array */
-	u32 sem_pending;          /* pending operations to be processed */
-	u32 sem_pending_last;    /* last pending operation */
-	u32 undo;                  /* undo requests on this array */
-	unsigned short  sem_nsems;              /* no. of semaphores in array */
-};
-
-struct semid64_ds32 {
-	struct ipc64_perm32 sem_perm;
-	compat_time_t sem_otime;
-	unsigned int __unused1;
-	compat_time_t sem_ctime;
-	unsigned int __unused2;
-	unsigned int sem_nsems;
-	unsigned int __unused3;
-	unsigned int __unused4;
-};
-
-struct msqid_ds32 {
-	struct ipc_perm32 msg_perm;
-	u32 msg_first;
-	u32 msg_last;
-	compat_time_t msg_stime;
-	compat_time_t msg_rtime;
-	compat_time_t msg_ctime;
-	u32 wwait;
-	u32 rwait;
-	unsigned short msg_cbytes;
-	unsigned short msg_qnum;
-	unsigned short msg_qbytes;
-	compat_ipc_pid_t msg_lspid;
-	compat_ipc_pid_t msg_lrpid;
-};
-
-struct msqid64_ds32 {
-	struct ipc64_perm32 msg_perm;
-	compat_time_t msg_stime;
-	unsigned int __unused1;
-	compat_time_t msg_rtime;
-	unsigned int __unused2;
-	compat_time_t msg_ctime;
-	unsigned int __unused3;
-	unsigned int msg_cbytes;
-	unsigned int msg_qnum;
-	unsigned int msg_qbytes;
-	compat_pid_t msg_lspid;
-	compat_pid_t msg_lrpid;
-	unsigned int __unused4;
-	unsigned int __unused5;
-};
-
-struct shmid_ds32 {
-	struct ipc_perm32 shm_perm;
-	int shm_segsz;
-	compat_time_t shm_atime;
-	compat_time_t shm_dtime;
-	compat_time_t shm_ctime;
-	compat_ipc_pid_t shm_cpid;
-	compat_ipc_pid_t shm_lpid;
-	unsigned short shm_nattch;
-};
-
-struct shmid64_ds32 {
-	struct ipc64_perm32 shm_perm;
-	compat_size_t shm_segsz;
-	compat_time_t shm_atime;
-	unsigned int __unused1;
-	compat_time_t shm_dtime;
-	unsigned int __unused2;
-	compat_time_t shm_ctime;
-	unsigned int __unused3;
-	compat_pid_t shm_cpid;
-	compat_pid_t shm_lpid;
-	unsigned int shm_nattch;
-	unsigned int __unused4;
-	unsigned int __unused5;
-};
-
-struct shminfo64_32 {
-	unsigned int shmmax;
-	unsigned int shmmin;
-	unsigned int shmmni;
-	unsigned int shmseg;
-	unsigned int shmall;
-	unsigned int __unused1;
-	unsigned int __unused2;
-	unsigned int __unused3;
-	unsigned int __unused4;
-};
-
-struct shm_info32 {
-	int used_ids;
-	u32 shm_tot, shm_rss, shm_swp;
-	u32 swap_attempts, swap_successes;
-};
-
-struct ipc_kludge {
-	u32 msgp;
-	s32 msgtyp;
-};
-
-
-#define A(__x)		((unsigned long)(__x))
-#define AA(__x)		((unsigned long)(__x))
-
-#define SEMOP		 1
-#define SEMGET		 2
-#define SEMCTL		 3
-#define TIMEDSEMOP	 4
-#define MSGSND		11
-#define MSGRCV		12
-#define MSGGET		13
-#define MSGCTL		14
-#define SHMAT		21
-#define SHMDT		22
-#define SHMGET		23
-#define SHMCTL		24
-
-#define IPCOP_MASK(__x)	(1UL << (__x))
-
-static int
-ipc_parse_version32 (int *cmd)
-{
-	if (*cmd & IPC_64) {
-		*cmd ^= IPC_64;
-		return IPC_64;
-	} else {
-		return IPC_OLD;
-	}
-}
-
-static int put_semid(void *user_semid, struct semid64_ds *s, int version)
-{
-	int err2;
-	switch (version) { 
-	case IPC_64: { 
-		struct semid64_ds32 *usp64 = (struct semid64_ds32 *) user_semid;
-		
-		if (!access_ok(VERIFY_WRITE, usp64, sizeof(*usp64))) {
-			err2 = -EFAULT;
-			break;
-		} 
-		err2 = __put_user(s->sem_perm.key, &usp64->sem_perm.key);
-		err2 |= __put_user(s->sem_perm.uid, &usp64->sem_perm.uid);
-		err2 |= __put_user(s->sem_perm.gid, &usp64->sem_perm.gid);
-		err2 |= __put_user(s->sem_perm.cuid, &usp64->sem_perm.cuid);
-		err2 |= __put_user(s->sem_perm.cgid, &usp64->sem_perm.cgid);
-		err2 |= __put_user(s->sem_perm.mode, &usp64->sem_perm.mode);
-		err2 |= __put_user(s->sem_perm.seq, &usp64->sem_perm.seq);
-		err2 |= __put_user(s->sem_otime, &usp64->sem_otime);
-		err2 |= __put_user(s->sem_ctime, &usp64->sem_ctime);
-		err2 |= __put_user(s->sem_nsems, &usp64->sem_nsems);
-		break;
-	}
-	default: {
-		struct semid_ds32 *usp32 = (struct semid_ds32 *) user_semid;
-		
-		if (!access_ok(VERIFY_WRITE, usp32, sizeof(*usp32))) {
-			err2 = -EFAULT;
-			break;
-		} 
-		err2 = __put_user(s->sem_perm.key, &usp32->sem_perm.key);
-		err2 |= __put_user(s->sem_perm.uid, &usp32->sem_perm.uid);
-		err2 |= __put_user(s->sem_perm.gid, &usp32->sem_perm.gid);
-		err2 |= __put_user(s->sem_perm.cuid, &usp32->sem_perm.cuid);
-		err2 |= __put_user(s->sem_perm.cgid, &usp32->sem_perm.cgid);
-		err2 |= __put_user(s->sem_perm.mode, &usp32->sem_perm.mode);
-		err2 |= __put_user(s->sem_perm.seq, &usp32->sem_perm.seq);
-		err2 |= __put_user(s->sem_otime, &usp32->sem_otime);
-		err2 |= __put_user(s->sem_ctime, &usp32->sem_ctime);
-		err2 |= __put_user(s->sem_nsems, &usp32->sem_nsems);
-		break;
-	}
-	}
-	return err2;
-}
-
-static int
-semctl32 (int first, int second, int third, void *uptr)
-{
-	union semun fourth;
-	u32 pad;
-	int err;
-	struct semid64_ds s;
-	mm_segment_t old_fs;
-	int version = ipc_parse_version32(&third);
-
-	if (!uptr)
-		return -EINVAL;
-	if (get_user(pad, (u32 *)uptr))
-		return -EFAULT;
-	if (third == SETVAL)
-		fourth.val = (int)pad;
-	else
-		fourth.__pad = (void *)A(pad);
-	switch (third) {
-	      case IPC_INFO:
-	      case IPC_RMID:
-	      case IPC_SET:
-	      case SEM_INFO:
-	      case GETVAL:
-	      case GETPID:
-	      case GETNCNT:
-	      case GETZCNT:
-	      case GETALL:
-	      case SETVAL:
-	      case SETALL:
-		err = sys_semctl(first, second, third, fourth);
-		break;
-
-	      case IPC_STAT:
-	      case SEM_STAT:
-		fourth.__pad = &s;
-		old_fs = get_fs();
-		set_fs(KERNEL_DS);
-		err = sys_semctl(first, second, third, fourth);
-		set_fs(old_fs);
-		if (!err)
-			err = put_semid((void *)A(pad), &s, version);
-		break;
-	default:
-		err = -EINVAL;
-		break;
-	}
-	return err;
-}
-
-#define MAXBUF (64*1024)
-
-static int
-do_sys32_msgsnd (int first, int second, int third, void *uptr)
-{
-	struct msgbuf *p;
-	struct msgbuf32 *up = (struct msgbuf32 *)uptr;
-	mm_segment_t old_fs;
-	int err;
-
-	if (second >= MAXBUF-sizeof(struct msgbuf))
-		return -EINVAL;
-	p = kmalloc(second + sizeof(struct msgbuf), GFP_USER);
-	if (!p)
-		return -ENOMEM;
-	err = get_user(p->mtype, &up->mtype);
-	err |= (copy_from_user(p->mtext, &up->mtext, second) ? -EFAULT : 0);
-	if (err)
-		goto out;
-	old_fs = get_fs();
-	set_fs(KERNEL_DS);
-	err = sys_msgsnd(first, p, second, third);
-	set_fs(old_fs);
-  out:
-	kfree(p);
-	return err;
-}
-
-static int
-do_sys32_msgrcv (int first, int second, int msgtyp, int third, int version, void *uptr)
-{
-	struct msgbuf32 *up;
-	struct msgbuf *p;
-	mm_segment_t old_fs;
-	int err;
-
-	if (!version) {
-		struct ipc_kludge *uipck = (struct ipc_kludge *)uptr;
-		struct ipc_kludge ipck;
-
-		err = -EINVAL;
-		if (!uptr)
-			goto out;
-		err = -EFAULT;
-		if (copy_from_user(&ipck, uipck, sizeof(struct ipc_kludge)))
-			goto out;
-		uptr = (void *)A(ipck.msgp);
-		msgtyp = ipck.msgtyp;
-	}
-	if (second >= MAXBUF-sizeof(struct msgbuf))
-		return -EINVAL; 
-	err = -ENOMEM;
-	p = kmalloc(second + sizeof(struct msgbuf), GFP_USER);
-	if (!p)
-		goto out;
-	old_fs = get_fs();
-	set_fs(KERNEL_DS);
-	err = sys_msgrcv(first, p, second, msgtyp, third);
-	set_fs(old_fs);
-	if (err < 0)
-		goto free_then_out;
-	up = (struct msgbuf32 *)uptr;
-	if (put_user(p->mtype, &up->mtype) || copy_to_user(&up->mtext, p->mtext, err))
-		err = -EFAULT;
-free_then_out:
-	kfree(p);
-out:
-	return err;
-}
-
-
-static int
-msgctl32 (int first, int second, void *uptr)
-{
-	int err = -EINVAL, err2;
-	struct msqid_ds m;
-	struct msqid64_ds m64;
-	struct msqid_ds32 *up32 = (struct msqid_ds32 *)uptr;
-	struct msqid64_ds32 *up64 = (struct msqid64_ds32 *)uptr;
-	mm_segment_t old_fs;
-	int version = ipc_parse_version32(&second);
-
-	switch (second) {
-	      case IPC_INFO:
-	      case IPC_RMID:
-	      case MSG_INFO:
-		err = sys_msgctl(first, second, (struct msqid_ds *)uptr);
-		break;
-
-	      case IPC_SET:
-		if (version == IPC_64) {
-			err = get_user(m.msg_perm.uid, &up64->msg_perm.uid);
-			err |= get_user(m.msg_perm.gid, &up64->msg_perm.gid);
-			err |= get_user(m.msg_perm.mode, &up64->msg_perm.mode);
-			err |= get_user(m.msg_qbytes, &up64->msg_qbytes);
-		} else {
-			err = get_user(m.msg_perm.uid, &up32->msg_perm.uid);
-			err |= get_user(m.msg_perm.gid, &up32->msg_perm.gid);
-			err |= get_user(m.msg_perm.mode, &up32->msg_perm.mode);
-			err |= get_user(m.msg_qbytes, &up32->msg_qbytes);
-		}
-		if (err)
-			break;
-		old_fs = get_fs();
-		set_fs(KERNEL_DS);
-		err = sys_msgctl(first, second, &m);
-		set_fs(old_fs);
-		break;
-
-	      case IPC_STAT:
-	      case MSG_STAT:
-		old_fs = get_fs();
-		set_fs(KERNEL_DS);
-		err = sys_msgctl(first, second, (void *) &m64);
-		set_fs(old_fs);
-		if (version == IPC_64) {
-			if (!access_ok(VERIFY_WRITE, up64, sizeof(*up64))) {
-				err = -EFAULT;
-				break;
-			}
-			err2 = __put_user(m64.msg_perm.key, &up64->msg_perm.key);
-			err2 |= __put_user(m64.msg_perm.uid, &up64->msg_perm.uid);
-			err2 |= __put_user(m64.msg_perm.gid, &up64->msg_perm.gid);
-			err2 |= __put_user(m64.msg_perm.cuid, &up64->msg_perm.cuid);
-			err2 |= __put_user(m64.msg_perm.cgid, &up64->msg_perm.cgid);
-			err2 |= __put_user(m64.msg_perm.mode, &up64->msg_perm.mode);
-			err2 |= __put_user(m64.msg_perm.seq, &up64->msg_perm.seq);
-			err2 |= __put_user(m64.msg_stime, &up64->msg_stime);
-			err2 |= __put_user(m64.msg_rtime, &up64->msg_rtime);
-			err2 |= __put_user(m64.msg_ctime, &up64->msg_ctime);
-			err2 |= __put_user(m64.msg_cbytes, &up64->msg_cbytes);
-			err2 |= __put_user(m64.msg_qnum, &up64->msg_qnum);
-			err2 |= __put_user(m64.msg_qbytes, &up64->msg_qbytes);
-			err2 |= __put_user(m64.msg_lspid, &up64->msg_lspid);
-			err2 |= __put_user(m64.msg_lrpid, &up64->msg_lrpid);
-			if (err2)
-				err = -EFAULT;
-		} else {
-			if (!access_ok(VERIFY_WRITE, up32, sizeof(*up32))) {
-				err = -EFAULT;
-				break;
-			}
-			err2 = __put_user(m64.msg_perm.key, &up32->msg_perm.key);
-			err2 |= __put_user(m64.msg_perm.uid, &up32->msg_perm.uid);
-			err2 |= __put_user(m64.msg_perm.gid, &up32->msg_perm.gid);
-			err2 |= __put_user(m64.msg_perm.cuid, &up32->msg_perm.cuid);
-			err2 |= __put_user(m64.msg_perm.cgid, &up32->msg_perm.cgid);
-			err2 |= __put_user(m64.msg_perm.mode, &up32->msg_perm.mode);
-			err2 |= __put_user(m64.msg_perm.seq, &up32->msg_perm.seq);
-			err2 |= __put_user(m64.msg_stime, &up32->msg_stime);
-			err2 |= __put_user(m64.msg_rtime, &up32->msg_rtime);
-			err2 |= __put_user(m64.msg_ctime, &up32->msg_ctime);
-			err2 |= __put_user(m64.msg_cbytes, &up32->msg_cbytes);
-			err2 |= __put_user(m64.msg_qnum, &up32->msg_qnum);
-			err2 |= __put_user(m64.msg_qbytes, &up32->msg_qbytes);
-			err2 |= __put_user(m64.msg_lspid, &up32->msg_lspid);
-			err2 |= __put_user(m64.msg_lrpid, &up32->msg_lrpid);
-			if (err2)
-				err = -EFAULT;
-		}
-		break;
-	}
-	return err;
-}
-
-static int
-shmat32 (int first, int second, int third, int version, void *uptr)
-{
-	unsigned long raddr;
-	u32 *uaddr = (u32 *)A((u32)third);
-	int err;
-
-	if (version == 1)
-		return -EINVAL;	/* iBCS2 emulator entry point: unsupported */
-	err = sys_shmat(first, uptr, second, &raddr);
-	if (err)
-		return err;
-	return put_user(raddr, uaddr);
-}
-
-static int put_shmid64(struct shmid64_ds *s64p, void *uptr, int version) 
-{ 
-	int err2; 
-#define s64 (*s64p)
-	if (version == IPC_64) {
-		struct shmid64_ds32 *up64 = (struct shmid64_ds32 *)uptr;
-
-		if (!access_ok(VERIFY_WRITE, up64, sizeof(*up64)))
-			return -EFAULT;
-
-		err2 = __put_user(s64.shm_perm.key, &up64->shm_perm.key);
-		err2 |= __put_user(s64.shm_perm.uid, &up64->shm_perm.uid);
-		err2 |= __put_user(s64.shm_perm.gid, &up64->shm_perm.gid);
-		err2 |= __put_user(s64.shm_perm.cuid, &up64->shm_perm.cuid);
-		err2 |= __put_user(s64.shm_perm.cgid, &up64->shm_perm.cgid);
-		err2 |= __put_user(s64.shm_perm.mode, &up64->shm_perm.mode);
-		err2 |= __put_user(s64.shm_perm.seq, &up64->shm_perm.seq);
-		err2 |= __put_user(s64.shm_atime, &up64->shm_atime);
-		err2 |= __put_user(s64.shm_dtime, &up64->shm_dtime);
-		err2 |= __put_user(s64.shm_ctime, &up64->shm_ctime);
-		err2 |= __put_user(s64.shm_segsz, &up64->shm_segsz);
-		err2 |= __put_user(s64.shm_nattch, &up64->shm_nattch);
-		err2 |= __put_user(s64.shm_cpid, &up64->shm_cpid);
-		err2 |= __put_user(s64.shm_lpid, &up64->shm_lpid);
-	} else {
-		struct shmid_ds32 *up32 = (struct shmid_ds32 *)uptr;
-
-		if (!access_ok(VERIFY_WRITE, up32, sizeof(*up32))) 
-			return -EFAULT;
-
-		err2 = __put_user(s64.shm_perm.key, &up32->shm_perm.key);
-		err2 |= __put_user(s64.shm_perm.uid, &up32->shm_perm.uid);
-		err2 |= __put_user(s64.shm_perm.gid, &up32->shm_perm.gid);
-		err2 |= __put_user(s64.shm_perm.cuid, &up32->shm_perm.cuid);
-		err2 |= __put_user(s64.shm_perm.cgid, &up32->shm_perm.cgid);
-		err2 |= __put_user(s64.shm_perm.mode, &up32->shm_perm.mode);
-		err2 |= __put_user(s64.shm_perm.seq, &up32->shm_perm.seq);
-		err2 |= __put_user(s64.shm_atime, &up32->shm_atime);
-		err2 |= __put_user(s64.shm_dtime, &up32->shm_dtime);
-		err2 |= __put_user(s64.shm_ctime, &up32->shm_ctime);
-		err2 |= __put_user(s64.shm_segsz, &up32->shm_segsz);
-		err2 |= __put_user(s64.shm_nattch, &up32->shm_nattch);
-		err2 |= __put_user(s64.shm_cpid, &up32->shm_cpid);
-		err2 |= __put_user(s64.shm_lpid, &up32->shm_lpid);
-	}
-#undef s64
-	return err2 ? -EFAULT : 0;
-}
-static int
-shmctl32 (int first, int second, void *uptr)
-{
-	int err = -EFAULT, err2;
-	struct shmid_ds s;
-	struct shmid64_ds s64;
-	mm_segment_t old_fs;
-	struct shm_info32 *uip = (struct shm_info32 *)uptr;
-	struct shm_info si;
-	int version = ipc_parse_version32(&second);
-	struct shminfo64 smi;
-	struct shminfo *usi32 = (struct shminfo *) uptr;
-	struct shminfo64_32 *usi64 = (struct shminfo64_32 *) uptr;
-
-	switch (second) {
-	      case IPC_INFO:
-		old_fs = get_fs();
-		set_fs(KERNEL_DS);
-		err = sys_shmctl(first, second, (struct shmid_ds *)&smi);
-		set_fs(old_fs);
-
-		if (version == IPC_64) {
-			if (!access_ok(VERIFY_WRITE, usi64, sizeof(*usi64))) {
-				err = -EFAULT;
-				break;
-			}
-			err2 = __put_user(smi.shmmax, &usi64->shmmax);
-			err2 |= __put_user(smi.shmmin, &usi64->shmmin);
-			err2 |= __put_user(smi.shmmni, &usi64->shmmni);
-			err2 |= __put_user(smi.shmseg, &usi64->shmseg);
-			err2 |= __put_user(smi.shmall, &usi64->shmall);
-		} else {
-			if (!access_ok(VERIFY_WRITE, usi32, sizeof(*usi32))) {
-				err = -EFAULT;
-				break;
-			}
-			err2 = __put_user(smi.shmmax, &usi32->shmmax);
-			err2 |= __put_user(smi.shmmin, &usi32->shmmin);
-			err2 |= __put_user(smi.shmmni, &usi32->shmmni);
-			err2 |= __put_user(smi.shmseg, &usi32->shmseg);
-			err2 |= __put_user(smi.shmall, &usi32->shmall);
-		}
-		if (err2)
-			err = -EFAULT;
-		break;
-
-	      case IPC_RMID:
-	      case SHM_LOCK:
-	      case SHM_UNLOCK:
-		err = sys_shmctl(first, second, (struct shmid_ds *)uptr);
-		break;
-
-	      case IPC_SET: 
-		if (version == IPC_64) {
-			struct shmid64_ds32 *up64 = (struct shmid64_ds32 *)uptr;
-			err = get_user(s.shm_perm.uid, &up64->shm_perm.uid);
-			err |= get_user(s.shm_perm.gid, &up64->shm_perm.gid);
-			err |= get_user(s.shm_perm.mode, &up64->shm_perm.mode);
-		} else {
-			struct shmid_ds32 *up32 = (struct shmid_ds32 *)uptr;
-			err = get_user(s.shm_perm.uid, &up32->shm_perm.uid);
-			err |= get_user(s.shm_perm.gid, &up32->shm_perm.gid);
-			err |= get_user(s.shm_perm.mode, &up32->shm_perm.mode);
-		}
-		if (err)
-			break;
-		old_fs = get_fs();
-		set_fs(KERNEL_DS);
-		err = sys_shmctl(first, second, &s);
-		set_fs(old_fs);
-		break;
-
-	      case IPC_STAT:
-	      case SHM_STAT:
-		old_fs = get_fs();
-		set_fs(KERNEL_DS);
-		err = sys_shmctl(first, second, (void *) &s64);
-		set_fs(old_fs);
-		
-		if (err < 0)
-			break;
-	        err2 = put_shmid64(&s64, uptr, version); 		
-		if (err2) 
-			err = err2;
-		break;
-
-	      case SHM_INFO:
-		old_fs = get_fs();
-		set_fs(KERNEL_DS);
-		err = sys_shmctl(first, second, (void *)&si);
-		set_fs(old_fs);
-		if (err < 0)
-			break;
-
-		if (!access_ok(VERIFY_WRITE, uip, sizeof(*uip))) {
-			err = -EFAULT;
-			break;
-		}
-		err2 = __put_user(si.used_ids, &uip->used_ids);
-		err2 |= __put_user(si.shm_tot, &uip->shm_tot);
-		err2 |= __put_user(si.shm_rss, &uip->shm_rss);
-		err2 |= __put_user(si.shm_swp, &uip->shm_swp);
-		err2 |= __put_user(si.swap_attempts, &uip->swap_attempts);
-		err2 |= __put_user(si.swap_successes, &uip->swap_successes);
-		if (err2)
-			err = -EFAULT;
-		break;
-	default:
-		err = -EINVAL;
-		break;
-	}
-	return err;
-}
-
-extern int sem_ctls[];
-
-static long semtimedop32(int semid, struct sembuf *sb, 
-			 unsigned nsops, struct compat_timespec *ts32)
-{ 
-	struct timespec ts;
-	mm_segment_t oldfs = get_fs(); 
-	long ret;
-
-	if (nsops > sem_ctls[2]) 
-		return -E2BIG;
-	if (!access_ok(VERIFY_READ, sb, nsops * sizeof(struct sembuf)))
-		return -EFAULT; 
-	if (ts32 && get_compat_timespec(&ts, ts32))
-		return -EFAULT;
-
-	set_fs(KERNEL_DS);  
-	ret = sys_semtimedop(semid, sb, nsops, ts32 ? &ts : NULL);
-	set_fs(oldfs); 
-	return ret;
-}
 
+#include <asm-i386/ipc.h>
 
 asmlinkage long
-sys32_ipc (u32 call, int first, int second, int third, u32 ptr, u32 fifth)
+sys32_ipc(u32 call, int first, int second, int third,
+		compat_uptr_t ptr, u32 fifth)
 {
 	int version;
 
@@ -659,35 +23,35 @@ sys32_ipc (u32 call, int first, int seco
 	switch (call) {
 	      case SEMOP:
 		/* struct sembuf is the same on 32 and 64bit :)) */
-		return sys_semtimedop(first, (struct sembuf *)AA(ptr), second,
-				      NULL);
-	      case TIMEDSEMOP:
-		return semtimedop32(first, (struct sembuf *)AA(ptr), second,
-				  (struct compat_timespec *)AA(fifth)); 
+		return sys_semtimedop(first, compat_ptr(ptr), second, NULL);
+	      case SEMTIMEDOP:
+		return compat_sys_semtimedop(first, compat_ptr(ptr), second,
+						compat_ptr(fifth));
 	      case SEMGET:
 		return sys_semget(first, second, third);
 	      case SEMCTL:
-		return semctl32(first, second, third, (void *)AA(ptr));
+		return compat_sys_semctl(first, second, third, compat_ptr(ptr));
 
 	      case MSGSND:
-		return do_sys32_msgsnd(first, second, third, (void *)AA(ptr));
+		return compat_sys_msgsnd(first, second, third, compat_ptr(ptr));
 	      case MSGRCV:
-		return do_sys32_msgrcv(first, second, fifth, third, version, (void *)AA(ptr));
+		return compat_sys_msgrcv(first, second, fifth, third,
+					 version, compat_ptr(ptr));
 	      case MSGGET:
 		return sys_msgget((key_t) first, second);
 	      case MSGCTL:
-		return msgctl32(first, second, (void *)AA(ptr));
+		return compat_sys_msgctl(first, second, compat_ptr(ptr));
 
 	      case SHMAT:
-		return shmat32(first, second, third, version, (void *)AA(ptr));
+		return compat_sys_shmat(first, second, third, version,
+					compat_ptr(ptr));
 		break;
 	      case SHMDT:
-		return sys_shmdt((char *)AA(ptr));
+		return sys_shmdt(compat_ptr(ptr));
 	      case SHMGET:
 		return sys_shmget(first, second, third);
 	      case SHMCTL:
-		return shmctl32(first, second, (void *)AA(ptr));
+		return compat_sys_shmctl(first, second, compat_ptr(ptr));
 	}
 	return -ENOSYS;
 }
-
--- diff/arch/x86_64/ia32/ptrace32.c	2004-02-09 10:36:09.000000000 +0000
+++ source/arch/x86_64/ia32/ptrace32.c	2004-02-23 13:56:39.000000000 +0000
@@ -14,6 +14,8 @@
 #include <linux/kernel.h>
 #include <linux/stddef.h>
 #include <linux/sched.h>
+#include <linux/syscalls.h>
+#include <linux/unistd.h>
 #include <linux/mm.h>
 #include <asm/ptrace.h>
 #include <asm/uaccess.h>
@@ -223,8 +225,6 @@ static struct task_struct *find_target(i
 	
 } 
 
-extern asmlinkage long sys_ptrace(long request, long pid, unsigned long addr, unsigned long data);
-
 asmlinkage long sys32_ptrace(long request, u32 pid, u32 addr, u32 data)
 {
 	struct task_struct *child;
--- diff/arch/x86_64/ia32/sys_ia32.c	2004-02-18 08:54:08.000000000 +0000
+++ source/arch/x86_64/ia32/sys_ia32.c	2004-02-23 13:56:39.000000000 +0000
@@ -26,6 +26,7 @@
 #include <linux/fs.h> 
 #include <linux/file.h> 
 #include <linux/signal.h>
+#include <linux/syscalls.h>
 #include <linux/resource.h>
 #include <linux/times.h>
 #include <linux/utsname.h>
@@ -110,9 +111,6 @@ int cp_compat_stat(struct kstat *kbuf, s
 	return 0;
 }
 
-extern long sys_truncate(char *, loff_t);
-extern long sys_ftruncate(int, loff_t);
-
 asmlinkage long
 sys32_truncate64(char * filename, unsigned long offset_low, unsigned long offset_high)
 {
@@ -236,8 +234,6 @@ sys32_mmap(struct mmap_arg_struct *arg)
 	return retval;
 }
 
-extern asmlinkage long sys_mprotect(unsigned long start,size_t len,unsigned long prot);
-
 asmlinkage long 
 sys32_mprotect(unsigned long start, size_t len, unsigned long prot)
 {
@@ -363,12 +359,9 @@ sys32_sigaction (int sig, struct old_sig
 	return ret;
 }
 
-extern asmlinkage long sys_rt_sigprocmask(int how, sigset_t *set, sigset_t *oset,
-					  size_t sigsetsize);
-
 asmlinkage long
-sys32_rt_sigprocmask(int how, compat_sigset_t *set, compat_sigset_t *oset,
-		     unsigned int sigsetsize)
+sys32_rt_sigprocmask(int how, compat_sigset_t __user *set,
+			compat_sigset_t __user *oset, unsigned int sigsetsize)
 {
 	sigset_t s;
 	compat_sigset_t s32;
@@ -734,9 +727,6 @@ sys32_old_select(struct sel_arg_struct *
 			    (struct compat_timeval *)A(a.tvp));
 }
 
-asmlinkage ssize_t sys_readv(unsigned long,const struct iovec *,unsigned long);
-asmlinkage ssize_t sys_writev(unsigned long,const struct iovec *,unsigned long);
-
 static struct iovec *
 get_compat_iovec(struct compat_iovec *iov32, struct iovec *iov_buf, u32 *count, int type, int *errp)
 {
@@ -878,18 +868,12 @@ int sys32_ni_syscall(int call)
 
 /* 32-bit timeval and related flotsam.  */
 
-extern asmlinkage long sys_sysfs(int option, unsigned long arg1,
-				unsigned long arg2);
-
 asmlinkage long
 sys32_sysfs(int option, u32 arg1, u32 arg2)
 {
 	return sys_sysfs(option, arg1, arg2);
 }
 
-extern asmlinkage long sys_mount(char * dev_name, char * dir_name, char * type,
-				unsigned long new_flags, void *data);
-
 static char *badfs[] = {
 	"smbfs", "ncpfs", NULL
 }; 	
@@ -940,8 +924,6 @@ struct sysinfo32 {
         char _f[20-2*sizeof(u32)-sizeof(int)];
 };
 
-extern asmlinkage long sys_sysinfo(struct sysinfo *info);
-
 asmlinkage long
 sys32_sysinfo(struct sysinfo32 *info)
 {
@@ -991,9 +973,6 @@ sys32_sysinfo(struct sysinfo32 *info)
 	return 0;
 }
                 
-extern asmlinkage long sys_sched_rr_get_interval(pid_t pid,
-						struct timespec *interval);
-
 asmlinkage long
 sys32_sched_rr_get_interval(compat_pid_t pid, struct compat_timespec *interval)
 {
@@ -1009,10 +988,8 @@ sys32_sched_rr_get_interval(compat_pid_t
 	return ret;
 }
 
-extern asmlinkage long sys_rt_sigpending(sigset_t *set, size_t sigsetsize);
-
 asmlinkage long
-sys32_rt_sigpending(compat_sigset_t *set, compat_size_t sigsetsize)
+sys32_rt_sigpending(compat_sigset_t __user *set, compat_size_t sigsetsize)
 {
 	sigset_t s;
 	compat_sigset_t s32;
@@ -1035,9 +1012,6 @@ sys32_rt_sigpending(compat_sigset_t *set
 	return ret;
 }
 
-extern asmlinkage long
-sys_rt_sigtimedwait(const sigset_t *uthese, siginfo_t *uinfo,
-		    const struct timespec *uts, size_t sigsetsize);
 
 asmlinkage long
 sys32_rt_sigtimedwait(compat_sigset_t *uthese, siginfo_t32 *uinfo,
@@ -1077,9 +1051,6 @@ sys32_rt_sigtimedwait(compat_sigset_t *u
 	return ret;
 }
 
-extern asmlinkage long
-sys_rt_sigqueueinfo(int pid, int sig, siginfo_t *uinfo);
-
 asmlinkage long
 sys32_rt_sigqueueinfo(int pid, int sig, siginfo_t32 *uinfo)
 {
@@ -1165,12 +1136,6 @@ sys32_sysctl(struct sysctl_ia32 *args32)
 #endif
 }
 
-extern asmlinkage ssize_t sys_pread64(unsigned int fd, char * buf,
-				    size_t count, loff_t pos);
-
-extern asmlinkage ssize_t sys_pwrite64(unsigned int fd, const char * buf,
-				     size_t count, loff_t pos);
-
 /* warning: next two assume little endian */ 
 asmlinkage long
 sys32_pread(unsigned int fd, char *ubuf, u32 count, u32 poslo, u32 poshi)
@@ -1187,8 +1152,6 @@ sys32_pwrite(unsigned int fd, char *ubuf
 }
 
 
-extern asmlinkage long sys_personality(unsigned long);
-
 asmlinkage long
 sys32_personality(unsigned long personality)
 {
@@ -1202,9 +1165,6 @@ sys32_personality(unsigned long personal
 	return ret;
 }
 
-extern asmlinkage ssize_t sys_sendfile(int out_fd, int in_fd, off_t *offset,
-				       size_t count); 
-
 asmlinkage long
 sys32_sendfile(int out_fd, int in_fd, compat_off_t *offset, s32 count)
 {
@@ -1375,9 +1335,7 @@ long sys32_uname(struct old_utsname * na
 	return err?-EFAULT:0;
 }
 
-extern int sys_ustat(dev_t, struct ustat *);
-
-long sys32_ustat(unsigned dev, struct ustat32 *u32p)
+long sys32_ustat(unsigned dev, struct ustat32 __user *u32p)
 {
 	struct ustat u;
 	mm_segment_t seg;
@@ -1500,15 +1458,11 @@ asmlinkage long sys32_clone(unsigned int
  * Some system calls that need sign extended arguments. This could be done by a generic wrapper.
  */ 
 
-extern off_t sys_lseek (unsigned int fd, off_t offset, unsigned int origin);
-
 long sys32_lseek (unsigned int fd, int offset, unsigned int whence)
 {
 	return sys_lseek(fd, offset, whence);
 }
 
-extern int sys_kill(pid_t pid, int sig); 
-
 long sys32_kill(int pid, int sig)
 {
 	return sys_kill(pid, sig);
@@ -1736,15 +1690,12 @@ done:
 	return err;
 }
 #else /* !NFSD */
-extern asmlinkage long sys_ni_syscall(void);
 long asmlinkage sys32_nfsservctl(int cmd, void *notused, void *notused2)
 {
 	return sys_ni_syscall();
 }
 #endif
 
-extern long sys_io_setup(unsigned nr_reqs, aio_context_t *ctx);
-
 long sys32_io_setup(unsigned nr_reqs, u32 *ctx32p)
 { 
 	long ret; 
@@ -1802,11 +1753,6 @@ asmlinkage long sys32_io_submit(aio_cont
 	return i ? i : ret;
 }
 
-extern asmlinkage long sys_io_getevents(aio_context_t ctx_id,
-					  long min_nr,
-					  long nr,
-					  struct io_event *events,
-					  struct timespec *timeout);
 
 asmlinkage long sys32_io_getevents(aio_context_t ctx_id,
 				 unsigned long min_nr,
@@ -1895,8 +1841,6 @@ sys32_timer_create(u32 clock, struct sig
 	return err; 
 } 
 
-extern long sys_fadvise64_64(int fd, loff_t offset, loff_t len, int advice);
-
 long sys32_fadvise64_64(int fd, __u32 offset_low, __u32 offset_high, 
 			__u32 len_low, __u32 len_high, int advice)
 { 
--- diff/arch/x86_64/kernel/Makefile	2004-01-19 10:22:55.000000000 +0000
+++ source/arch/x86_64/kernel/Makefile	2004-02-23 13:56:39.000000000 +0000
@@ -12,6 +12,7 @@ obj-y	:= process.o semaphore.o signal.o 
 obj-$(CONFIG_MTRR)		+= ../../i386/kernel/cpu/mtrr/
 obj-$(CONFIG_ACPI)		+= acpi/
 obj-$(CONFIG_X86_MSR)		+= msr.o
+obj-$(CONFIG_MICROCODE)		+= microcode.o
 obj-$(CONFIG_X86_CPUID)		+= cpuid.o
 obj-$(CONFIG_SMP)		+= smp.o smpboot.o trampoline.o
 obj-$(CONFIG_X86_LOCAL_APIC)	+= apic.o  nmi.o
@@ -22,12 +23,15 @@ obj-$(CONFIG_CPU_FREQ)		+= cpufreq/
 obj-$(CONFIG_EARLY_PRINTK)	+= early_printk.o
 obj-$(CONFIG_GART_IOMMU)	+= pci-gart.o aperture.o
 obj-$(CONFIG_DUMMY_IOMMU)	+= pci-nommu.o pci-dma.o
+obj-$(CONFIG_SWIOTLB)		+= swiotlb.o
 
 obj-$(CONFIG_MODULES)		+= module.o
+obj-$(CONFIG_KGDB)		+= kgdb_stub.o
 
 obj-y				+= topology.o
 
 bootflag-y			+= ../../i386/kernel/bootflag.o
 cpuid-$(subst m,y,$(CONFIG_X86_CPUID))  += ../../i386/kernel/cpuid.o
 topology-y                     += ../../i386/mach-default/topology.o
-
+swiotlb-$(CONFIG_SWIOTLB)      += ../../ia64/lib/swiotlb.o
+microcode-$(subst m,y,$(CONFIG_X86_CPUID))  += ../../i386/kernel/microcode.o
--- diff/arch/x86_64/kernel/aperture.c	2004-02-18 08:54:08.000000000 +0000
+++ source/arch/x86_64/kernel/aperture.c	2004-02-23 13:56:39.000000000 +0000
@@ -24,6 +24,8 @@
 #include <asm/proto.h>
 #include <asm/pci-direct.h>
 
+int iommu_aperture;
+
 int fallback_aper_order __initdata = 1; /* 64MB */
 int fallback_aper_force __initdata = 0; 
 
@@ -206,6 +208,8 @@ void __init iommu_hole_init(void) 
 		if (read_pci_config(0, num, 3, 0x00) != NB_ID_3) 
 			continue;	
 
+		iommu_aperture = 1;; 
+
 		aper_order = (read_pci_config(0, num, 3, 0x90) >> 1) & 7; 
 		aper_size = (32 * 1024 * 1024) << aper_order; 
 		aper_base = read_pci_config(0, num, 3, 0x94) & 0x7fff;
--- diff/arch/x86_64/kernel/apic.c	2004-01-19 10:22:55.000000000 +0000
+++ source/arch/x86_64/kernel/apic.c	2004-02-23 13:56:39.000000000 +0000
@@ -552,7 +552,7 @@ static int __init init_lapic_sysfs(void)
 	/* XXX: remove suspend/resume procs if !apic_pm_state.active? */
 	error = sysdev_class_register(&lapic_sysclass);
 	if (!error)
-		error = sys_device_register(&device_lapic);
+		error = sysdev_register(&device_lapic);
 	return error;
 }
 device_initcall(init_lapic_sysfs);
--- diff/arch/x86_64/kernel/early_printk.c	2003-06-09 14:18:18.000000000 +0100
+++ source/arch/x86_64/kernel/early_printk.c	2004-02-23 13:56:39.000000000 +0000
@@ -7,7 +7,11 @@
 
 /* Simple VGA output */
 
+#ifdef __i386__
+#define VGABASE		__pa(__PAGE_OFFSET + 0xb8000UL)
+#else
 #define VGABASE		0xffffffff800b8000UL
+#endif
 
 #define MAX_YPOS	25
 #define MAX_XPOS	80
@@ -22,15 +26,14 @@ static void early_vga_write(struct conso
 	while ((c = *str++) != '\0' && n-- > 0) {
 		if (current_ypos >= MAX_YPOS) {
 			/* scroll 1 line up */
-			for(k = 1, j = 0; k < MAX_YPOS; k++, j++) {
-				for(i = 0; i < MAX_XPOS; i++) {
+			for (k = 1, j = 0; k < MAX_YPOS; k++, j++) {
+				for (i = 0; i < MAX_XPOS; i++) {
 					writew(readw(VGABASE + 2*(MAX_XPOS*k + i)),
 					       VGABASE + 2*(MAX_XPOS*j + i));
 				}
 			}
-			for(i = 0; i < MAX_XPOS; i++) {
+			for (i = 0; i < MAX_XPOS; i++)
 				writew(0x720, VGABASE + 2*(MAX_XPOS*j + i));
-			}
 			current_ypos = MAX_YPOS-1;
 		}
 		if (c == '\n') {
@@ -38,7 +41,8 @@ static void early_vga_write(struct conso
 			current_ypos++;
 		} else if (c != '\r')  {
 			writew(((0x7 << 8) | (unsigned short) c),
-			       VGABASE + 2*(MAX_XPOS*current_ypos + current_xpos++));
+			       VGABASE + 2*(MAX_XPOS*current_ypos +
+						current_xpos++));
 			if (current_xpos >= MAX_XPOS) {
 				current_xpos = 0;
 				current_ypos++;
@@ -78,7 +82,7 @@ static int early_serial_putc(unsigned ch
 { 
 	unsigned timeout = 0xffff; 
 	while ((inb(early_serial_base + LSR) & XMTRDY) == 0 && --timeout) 
-		rep_nop(); 
+		cpu_relax();
 	outb(ch, early_serial_base + TXR);
 	return timeout ? 0 : -1;
 } 
@@ -93,10 +97,13 @@ static void early_serial_write(struct co
 	} 
 } 
 
+#define DEFAULT_BAUD 9600
+
 static __init void early_serial_init(char *opt)
 {
 	unsigned char c; 
-	unsigned divisor, baud = 38400;
+	unsigned divisor;
+	unsigned baud = DEFAULT_BAUD;
 	char *s, *e;
 
 	if (*opt == ',') 
@@ -109,25 +116,26 @@ static __init void early_serial_init(cha
 			early_serial_base = simple_strtoul(s, &e, 16);
 		} else {
 			static int bases[] = { 0x3f8, 0x2f8 };
-		if (!strncmp(s,"ttyS",4)) 
-			s+=4; 
-		port = simple_strtoul(s, &e, 10); 
-		if (port > 1 || s == e) 
-			port = 0; 
-		early_serial_base = bases[port];
-	}
+
+			if (!strncmp(s,"ttyS",4))
+				s += 4;
+			port = simple_strtoul(s, &e, 10);
+			if (port > 1 || s == e)
+				port = 0;
+			early_serial_base = bases[port];
+		}
 	}
 
-	outb(0x3, early_serial_base + LCR); /* 8n1 */
-	outb(0, early_serial_base + IER); /* no interrupt */ 
-	outb(0, early_serial_base + FCR); /* no fifo */ 
-	outb(0x3, early_serial_base + MCR); /* DTR + RTS */ 
+	outb(0x3, early_serial_base + LCR);	/* 8n1 */
+	outb(0, early_serial_base + IER);	/* no interrupt */
+	outb(0, early_serial_base + FCR);	/* no fifo */
+	outb(0x3, early_serial_base + MCR);	/* DTR + RTS */
 
 	s = strsep(&opt, ","); 
 	if (s != NULL) { 
 		baud = simple_strtoul(s, &e, 0); 
 		if (baud == 0 || s == e) 
-			baud = 38400;
+			baud = DEFAULT_BAUD;
 	} 
 	
 	divisor = 115200 / baud; 
@@ -154,8 +162,9 @@ void early_printk(const char *fmt, ...)
 	char buf[512]; 
 	int n; 
 	va_list ap;
+
 	va_start(ap,fmt); 
-	n = vsnprintf(buf,512,fmt,ap);
+	n = vscnprintf(buf,512,fmt,ap);
 	early_console->write(early_console,buf,n);
 	va_end(ap); 
 } 
@@ -170,6 +179,8 @@ int __init setup_early_printk(char *opt)
 	if (early_console_initialized)
 		return -1;
 
+	opt = strchr(opt, '=') + 1;
+
 	strlcpy(buf,opt,sizeof(buf)); 
 	space = strchr(buf, ' '); 
 	if (space)
@@ -200,19 +211,12 @@ void __init disable_early_printk(void)
 	if (!early_console_initialized || !early_console)
 		return;
 	if (!keep_early) {
-		printk("disabling early console...\n"); 
+		printk("disabling early console\n");
 		unregister_console(early_console);
 		early_console_initialized = 0;
 	} else { 
-		printk("keeping early console.\n"); 
+		printk("keeping early console\n");
 	}
 } 
 
-/* syntax: earlyprintk=vga
-           earlyprintk=serial[,ttySn[,baudrate]] 
-   Append ,keep to not disable it when the real console takes over.
-   Only vga or serial at a time, not both.
-   Currently only ttyS0 and ttyS1 are supported. 
-   Interaction with the standard serial driver is not very good. 
-   The VGA output is eventually overwritten by the real console. */
-__setup("earlyprintk=", setup_early_printk);  
+__setup("earlyprintk=", setup_early_printk);
--- diff/arch/x86_64/kernel/head.S	2004-01-19 10:22:55.000000000 +0000
+++ source/arch/x86_64/kernel/head.S	2004-02-23 13:56:39.000000000 +0000
@@ -16,6 +16,7 @@
 #include <asm/segment.h>
 #include <asm/page.h>
 #include <asm/msr.h>
+#include <asm/cache.h>
 	
 /* we are not able to switch in one step to the final KERNEL ADRESS SPACE
  * because we need identity-mapped pages on setup so define __START_KERNEL to
@@ -322,7 +323,6 @@ gdt:
 	.endr
 #endif
 
-.align 64 /* cacheline aligned */
 ENTRY(gdt_table32)
 	.quad	0x0000000000000000	/* This one is magic */
 	.quad	0x0000000000000000	/* unused */
@@ -334,7 +334,7 @@ gdt32_end:	
  * Also sysret mandates a special GDT layout 
  */
 		 		
-.align 64 /* cacheline aligned, keep this synchronized with asm/desc.h */
+.align L1_CACHE_BYTES
 
 /* The TLS descriptors are currently at a different place compared to i386.
    Hopefully nobody expects them at a fixed place (Wine?) */
@@ -354,18 +354,13 @@ ENTRY(cpu_gdt_table)
 	.quad	0			/* unused now */
 	.quad	0x00009a000000ffff	/* __KERNEL16_CS - 16bit PM for S3 wakeup. */
 					/* base must be patched for real base address. */
-	/* This should be a multiple of the cache line size */
 gdt_end:	
-	.globl gdt_end
-
-	/* GDTs of other CPUs */	
-#ifdef CONFIG_SMP
-	.rept NR_CPUS-1
-	.quad 0,0,0,0,0,0,0,0,0,0,0
-	.endr	
-#endif
+	/* asm/segment.h:GDT_ENTRIES must match this */	
+	/* This should be a multiple of the cache line size */
+	/* GDTs of other CPUs: */	
+	.fill (GDT_SIZE * NR_CPUS) - (gdt_end - cpu_gdt_table)
 
-	.align  64
+	.align  L1_CACHE_BYTES
 ENTRY(idt_table)	
 	.rept   256
 	.quad   0
--- diff/arch/x86_64/kernel/head64.c	2003-05-21 11:50:00.000000000 +0100
+++ source/arch/x86_64/kernel/head64.c	2004-02-23 13:56:39.000000000 +0000
@@ -83,9 +83,9 @@ void __init x86_64_start_kernel(char * r
 	/* default console: */
 	if (!strstr(saved_command_line, "console="))
 		strcat(saved_command_line, " console=tty0"); 
-	s = strstr(saved_command_line, "earlyprintk="); 
+	s = strstr(saved_command_line, "earlyprintk=");
 	if (s != NULL)
-		setup_early_printk(s+12); 
+		setup_early_printk(s);
 #ifdef CONFIG_DISCONTIGMEM
 	s = strstr(saved_command_line, "numa=");
 	if (s != NULL)
--- diff/arch/x86_64/kernel/i8259.c	2004-01-19 10:22:55.000000000 +0000
+++ source/arch/x86_64/kernel/i8259.c	2004-02-23 13:56:39.000000000 +0000
@@ -430,7 +430,7 @@ static int __init init_timer_sysfs(void)
 {
 	int error = sysdev_class_register(&timer_sysclass);
 	if (!error)
-		error = sys_device_register(&device_timer);
+		error = sysdev_register(&device_timer);
 	return error;
 }
 
--- diff/arch/x86_64/kernel/irq.c	2004-01-19 10:22:55.000000000 +0000
+++ source/arch/x86_64/kernel/irq.c	2004-02-23 13:56:39.000000000 +0000
@@ -405,6 +405,9 @@ out:
 	spin_unlock(&desc->lock);
 
 	irq_exit();
+
+	kgdb_process_breakpoint();
+
 	return 1;
 }
 
@@ -826,7 +829,7 @@ static cpumask_t irq_affinity [NR_IRQS] 
 static int irq_affinity_read_proc (char *page, char **start, off_t off,
 			int count, int *eof, void *data)
 {
-	int len = cpumask_snprintf(page, count, irq_affinity[(long)data]);
+	int len = cpumask_scnprintf(page, count, irq_affinity[(long)data]);
 	if (count - len < 2)
 		return -EINVAL;
 	len += sprintf(page + len, "\n");
@@ -864,7 +867,7 @@ static int irq_affinity_write_proc (stru
 static int prof_cpu_mask_read_proc (char *page, char **start, off_t off,
 			int count, int *eof, void *data)
 {
-	int len = cpumask_snprintf(page, count, *(cpumask_t *)data);
+	int len = cpumask_scnprintf(page, count, *(cpumask_t *)data);
 	if (count - len < 2)
 		return -EINVAL;
 	len += sprintf(page + len, "\n");
--- diff/arch/x86_64/kernel/nmi.c	2004-02-18 08:54:08.000000000 +0000
+++ source/arch/x86_64/kernel/nmi.c	2004-02-23 13:56:39.000000000 +0000
@@ -39,7 +39,7 @@
  *     be enabled
  * -1: the lapic NMI watchdog is disabled, but can be enabled
  */
-static int nmi_active;
+int nmi_active;		/* oprofile uses this */
 static int panic_on_timeout;
 
 unsigned int nmi_watchdog = NMI_LOCAL_APIC;
@@ -218,7 +218,7 @@ static int __init init_lapic_nmi_sysfs(v
 
 	error = sysdev_class_register(&nmi_sysclass);
 	if (!error)
-		error = sys_device_register(&device_lapic_nmi);
+		error = sysdev_register(&device_lapic_nmi);
 	return error;
 }
 /* must come after the local APIC's device_initcall() */
@@ -380,6 +380,7 @@ void unset_nmi_callback(void)
 	nmi_callback = dummy_nmi_callback;
 }
 
+EXPORT_SYMBOL(nmi_active);
 EXPORT_SYMBOL(nmi_watchdog);
 EXPORT_SYMBOL(disable_lapic_nmi_watchdog);
 EXPORT_SYMBOL(enable_lapic_nmi_watchdog);
--- diff/arch/x86_64/kernel/pci-gart.c	2004-02-18 08:54:08.000000000 +0000
+++ source/arch/x86_64/kernel/pci-gart.c	2004-02-23 13:56:39.000000000 +0000
@@ -354,6 +354,11 @@ dma_addr_t pci_map_single(struct pci_dev
 
 	BUG_ON(dir == PCI_DMA_NONE);
 
+#ifdef CONFIG_SWIOTLB
+	if (swiotlb)
+		return swiotlb_map_single(&dev->dev,addr,size,dir);
+#endif
+
 	phys_mem = virt_to_phys(addr); 
 	if (!need_iommu(dev, phys_mem, size))
 		return phys_mem; 
@@ -460,6 +465,12 @@ int pci_map_sg(struct pci_dev *dev, stru
 	BUG_ON(dir == PCI_DMA_NONE);
 	if (nents == 0) 
 		return 0;
+
+#ifdef CONFIG_SWIOTLB
+	if (swiotlb)
+		return swiotlb_map_sg(&dev->dev,sg,nents,dir);
+#endif
+
 	out = 0;
 	start = 0;
 	for (i = 0; i < nents; i++) {
@@ -520,6 +531,14 @@ void pci_unmap_single(struct pci_dev *hw
 	unsigned long iommu_page; 
 	int npages;
 	int i;
+
+#ifdef CONFIG_SWIOTLB
+	if (swiotlb) {
+		swiotlb_unmap_single(&hwdev->dev,dma_addr,size,direction);
+		return;
+	}
+#endif
+
 	if (dma_addr < iommu_bus_base + EMERGENCY_PAGES*PAGE_SIZE || 
 	    dma_addr >= iommu_bus_base + iommu_size)
 		return;
@@ -570,7 +589,7 @@ int pci_dma_supported(struct pci_dev *de
 		return 0; 
 	}
 
-	if (no_iommu && (mask < (end_pfn << PAGE_SHIFT)))
+	if (no_iommu && (mask < (end_pfn << PAGE_SHIFT)) && !swiotlb)
 		return 0;
 
 	return 1;
@@ -680,6 +699,7 @@ static __init int init_k8_gatt(struct ag
 	return 0;
 
  nommu:
+ 	/* Should not happen anymore */
 	printk(KERN_ERR "PCI-DMA: More than 4GB of RAM and no IOMMU\n"
 	       KERN_ERR "PCI-DMA: 32bit PCI IO may malfunction."); 
 	return -1; 
@@ -694,6 +714,7 @@ static int __init pci_iommu_init(void)
 	unsigned long iommu_start;
 	struct pci_dev *dev;
 		
+
 #ifndef CONFIG_AGP_AMD64
 	no_agp = 1; 
 #else
@@ -704,7 +725,14 @@ static int __init pci_iommu_init(void)
 		(agp_copy_info(&info) < 0); 
 #endif	
 
-	if (no_iommu || (!force_iommu && end_pfn < 0xffffffff>>PAGE_SHIFT)) { 
+	if (swiotlb) { 
+		no_iommu = 1;
+		printk(KERN_INFO "PCI-DMA: Using SWIOTLB :-(\n"); 
+		return -1; 
+	} 
+	
+	if (no_iommu || (!force_iommu && end_pfn < 0xffffffff>>PAGE_SHIFT) || 
+	    !iommu_aperture) {
 		printk(KERN_INFO "PCI-DMA: Disabling IOMMU.\n"); 
 		no_iommu = 1;
 		return -1;
--- diff/arch/x86_64/kernel/process.c	2004-02-09 10:36:09.000000000 +0000
+++ source/arch/x86_64/kernel/process.c	2004-02-23 13:56:39.000000000 +0000
@@ -140,6 +140,52 @@ void cpu_idle (void)
 	}
 }
 
+/*
+ * This uses new MONITOR/MWAIT instructions on P4 processors with PNI,
+ * which can obviate IPI to trigger checking of need_resched.
+ * We execute MONITOR against need_resched and enter optimized wait state
+ * through MWAIT. Whenever someone changes need_resched, we would be woken
+ * up from MWAIT (without an IPI).
+ */
+static void mwait_idle(void)
+{
+	local_irq_enable();
+
+	if (!need_resched()) {
+		set_thread_flag(TIF_POLLING_NRFLAG);
+		do {
+			__monitor((void *)&current_thread_info()->flags, 0, 0);
+			if (need_resched())
+				break;
+			__mwait(0, 0);
+		} while (!need_resched());
+		clear_thread_flag(TIF_POLLING_NRFLAG);
+	}
+}
+
+void __init select_idle_routine(const struct cpuinfo_x86 *c)
+{
+	static int printed;
+	if (cpu_has(c, X86_FEATURE_MWAIT)) {
+		/*
+		 * Skip, if setup has overridden idle.
+		 * Also, take care of system with asymmetric CPUs.
+		 * Use, mwait_idle only if all cpus support it.
+		 * If not, we fallback to default_idle()
+		 */
+		if (!pm_idle) {
+			if (!printed) {
+				printk("using mwait in idle threads.\n");
+				printed = 1;
+			}
+			pm_idle = mwait_idle;
+		}
+		return;
+	}
+	pm_idle = default_idle;
+	return;
+}
+
 static int __init idle_setup (char *str)
 {
 	if (!strncmp(str, "poll", 4)) {
--- diff/arch/x86_64/kernel/setup.c	2004-02-09 10:36:09.000000000 +0000
+++ source/arch/x86_64/kernel/setup.c	2004-02-23 13:56:39.000000000 +0000
@@ -76,6 +76,9 @@ unsigned long pci_mem_start = 0x10000000
 
 unsigned long saved_video_mode;
 
+int swiotlb;
+EXPORT_SYMBOL(swiotlb);
+
 /*
  * Setup options
  */
@@ -440,7 +443,6 @@ void __init setup_arch(char **cmdline_p)
 		}
 	}
 #endif
-
 	paging_init();
 
 #ifndef CONFIG_SMP
@@ -584,6 +586,193 @@ static int __init init_amd(struct cpuinf
 	return r;
 }
 
+static void __init detect_ht(void)
+{
+#ifdef CONFIG_SMP
+	extern	int phys_proc_id[NR_CPUS];
+	
+	u32 	eax, ebx, ecx, edx;
+	int 	index_lsb, index_msb, tmp;
+	int	initial_apic_id;
+	int 	cpu = smp_processor_id();
+	
+	cpuid(1, &eax, &ebx, &ecx, &edx);
+	smp_num_siblings = (ebx & 0xff0000) >> 16;
+	
+	if (smp_num_siblings == 1) {
+		printk(KERN_INFO  "CPU: Hyper-Threading is disabled\n");
+	} else if (smp_num_siblings > 1) {
+		index_lsb = 0;
+		index_msb = 31;
+		/*
+		 * At this point we only support two siblings per
+		 * processor package.
+		 */
+#define NR_SIBLINGS	2
+		if (smp_num_siblings != NR_SIBLINGS) {
+			printk(KERN_WARNING "CPU: Unsupported number of the siblings %d", smp_num_siblings);
+			smp_num_siblings = 1;
+			return;
+		}
+		tmp = smp_num_siblings;
+		while ((tmp & 1) == 0) {
+			tmp >>=1 ;
+			index_lsb++;
+		}
+		tmp = smp_num_siblings;
+		while ((tmp & 0x80000000 ) == 0) {
+			tmp <<=1 ;
+			index_msb--;
+		}
+		if (index_lsb != index_msb )
+			index_msb++;
+		initial_apic_id = ebx >> 24 & 0xff;
+		phys_proc_id[cpu] = initial_apic_id >> index_msb;
+		
+		printk(KERN_INFO  "CPU: Physical Processor ID: %d\n",
+		       phys_proc_id[cpu]);
+	}
+#endif
+}
+	
+#define LVL_1_INST	1
+#define LVL_1_DATA	2
+#define LVL_2		3
+#define LVL_3		4
+#define LVL_TRACE	5
+
+struct _cache_table
+{
+	unsigned char descriptor;
+	char cache_type;
+	short size;
+};
+
+/* all the cache descriptor types we care about (no TLB or trace cache entries) */
+static struct _cache_table cache_table[] __initdata =
+{
+	{ 0x06, LVL_1_INST, 8 },
+	{ 0x08, LVL_1_INST, 16 },
+	{ 0x0a, LVL_1_DATA, 8 },
+	{ 0x0c, LVL_1_DATA, 16 },
+	{ 0x22, LVL_3,      512 },
+	{ 0x23, LVL_3,      1024 },
+	{ 0x25, LVL_3,      2048 },
+	{ 0x29, LVL_3,      4096 },
+	{ 0x2c, LVL_1_DATA, 32 },
+	{ 0x30, LVL_1_INST, 32 },
+	{ 0x39, LVL_2,      128 },
+	{ 0x3b, LVL_2,      128 },
+	{ 0x3c, LVL_2,      256 },
+	{ 0x41, LVL_2,      128 },
+	{ 0x42, LVL_2,      256 },
+	{ 0x43, LVL_2,      512 },
+	{ 0x44, LVL_2,      1024 },
+	{ 0x45, LVL_2,      2048 },
+	{ 0x66, LVL_1_DATA, 8 },
+	{ 0x67, LVL_1_DATA, 16 },
+	{ 0x68, LVL_1_DATA, 32 },
+	{ 0x70, LVL_TRACE,  12 },
+	{ 0x71, LVL_TRACE,  16 },
+	{ 0x72, LVL_TRACE,  32 },
+	{ 0x79, LVL_2,      128 },
+	{ 0x7a, LVL_2,      256 },
+	{ 0x7b, LVL_2,      512 },
+	{ 0x7c, LVL_2,      1024 },
+	{ 0x82, LVL_2,      256 },
+	{ 0x83, LVL_2,      512 },
+	{ 0x84, LVL_2,      1024 },
+	{ 0x85, LVL_2,      2048 },
+	{ 0x86, LVL_2,      512 },
+	{ 0x87, LVL_2,      1024 },
+	{ 0x00, 0, 0}
+};
+
+static void __init init_intel(struct cpuinfo_x86 *c)
+{
+	/* Cache sizes */
+	unsigned int trace = 0, l1i = 0, l1d = 0, l2 = 0, l3 = 0; 
+	unsigned n;
+
+	select_idle_routine(c);
+	if (c->cpuid_level > 1) {
+		/* supports eax=2  call */
+		int i, j, n;
+		int regs[4];
+		unsigned char *dp = (unsigned char *)regs;
+
+		/* Number of times to iterate */
+		n = cpuid_eax(2) & 0xFF;
+
+		for ( i = 0 ; i < n ; i++ ) {
+			cpuid(2, &regs[0], &regs[1], &regs[2], &regs[3]);
+			
+			/* If bit 31 is set, this is an unknown format */
+			for ( j = 0 ; j < 3 ; j++ ) {
+				if ( regs[j] < 0 ) regs[j] = 0;
+			}
+
+			/* Byte 0 is level count, not a descriptor */
+			for ( j = 1 ; j < 16 ; j++ ) {
+				unsigned char des = dp[j];
+				unsigned char k = 0;
+
+				/* look up this descriptor in the table */
+				while (cache_table[k].descriptor != 0)
+				{
+					if (cache_table[k].descriptor == des) {
+						switch (cache_table[k].cache_type) {
+						case LVL_1_INST:
+							l1i += cache_table[k].size;
+							break;
+						case LVL_1_DATA:
+							l1d += cache_table[k].size;
+							break;
+						case LVL_2:
+							l2 += cache_table[k].size;
+							break;
+						case LVL_3:
+							l3 += cache_table[k].size;
+							break;
+						case LVL_TRACE:
+							trace += cache_table[k].size;
+							break;
+						}
+
+						break;
+					}
+
+					k++;
+				}
+			}
+		}
+
+		if (trace)
+			printk (KERN_INFO "CPU: Trace cache: %dK uops", trace);
+		else if (l1i)
+			printk (KERN_INFO "CPU: L1 I cache: %dK", l1i);
+		if (l1d)
+			printk(", L1 D cache: %dK\n", l1d);
+		else
+			printk("\n"); 
+		if (l2)
+			printk(KERN_INFO "CPU: L2 cache: %dK\n", l2);
+		if (l3)
+			printk(KERN_INFO "CPU: L3 cache: %dK\n", l3);
+
+		c->x86_cache_size = l2 ? l2 : (l1i+l1d);
+	}
+
+	if (cpu_has(c, X86_FEATURE_HT))
+		detect_ht(); 
+
+	n = cpuid_eax(0x80000000);
+	if (n >= 0x80000008) {
+		unsigned eax = cpuid_eax(0x80000008);
+		c->x86_virt_bits = (eax >> 8) & 0xff;
+		c->x86_phys_bits = eax & 0xff;
+	}
+}
 
 void __init get_cpu_vendor(struct cpuinfo_x86 *c)
 {
@@ -591,6 +780,8 @@ void __init get_cpu_vendor(struct cpuinf
 
 	if (!strcmp(v, "AuthenticAMD"))
 		c->x86_vendor = X86_VENDOR_AMD;
+	else if (!strcmp(v, "GenuineIntel"))
+		c->x86_vendor = X86_VENDOR_INTEL;
 	else
 		c->x86_vendor = X86_VENDOR_UNKNOWN;
 }
@@ -606,7 +797,7 @@ struct cpu_model_info {
  */
 void __init identify_cpu(struct cpuinfo_x86 *c)
 {
-	int junk, i;
+	int i;
 	u32 xlvl, tfms;
 
 	c->loops_per_jiffy = loops_per_jiffy;
@@ -630,7 +821,7 @@ void __init identify_cpu(struct cpuinfo_
 	/* Intel-defined flags: level 0x00000001 */
 	if (c->cpuid_level >= 0x00000001) {
 		__u32 misc;
-		cpuid(0x00000001, &tfms, &misc, &junk,
+		cpuid(0x00000001, &tfms, &misc, &c->x86_capability[4],
 		      &c->x86_capability[0]);
 		c->x86 = (tfms >> 8) & 0xf;
 		c->x86_model = (tfms >> 4) & 0xf;
@@ -679,9 +870,13 @@ void __init identify_cpu(struct cpuinfo_
 			init_amd(c);
 			break;
 
+		case X86_VENDOR_INTEL:
+			init_intel(c); 
+			break; 
+
 		case X86_VENDOR_UNKNOWN:
 		default:
-			/* Not much we can do here... */
+			display_cacheinfo(c);
 			break;
 	}
 	
@@ -732,7 +927,7 @@ static int show_cpuinfo(struct seq_file 
 	        "fpu", "vme", "de", "pse", "tsc", "msr", "pae", "mce",
 	        "cx8", "apic", NULL, "sep", "mtrr", "pge", "mca", "cmov",
 	        "pat", "pse36", "pn", "clflush", NULL, "dts", "acpi", "mmx",
-	        "fxsr", "sse", "sse2", "ss", NULL, "tm", "ia64", NULL,
+	        "fxsr", "sse", "sse2", "ss", "ht", "tm", "ia64", NULL,
 
 		/* AMD-defined */
 		NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
@@ -751,6 +946,12 @@ static int show_cpuinfo(struct seq_file 
 		NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
 		NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
 		NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+
+		/* Intel-defined (#2) */
+		"pni", NULL, NULL, "monitor", "ds_cpl", NULL, NULL, "tm2",
+		"est", NULL, "cid", NULL, NULL, NULL, NULL, NULL,
+		NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+		NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
 	};
 	static char *x86_power_flags[] = { 
 		"ts",	/* temperature sensor */
@@ -790,6 +991,14 @@ static int show_cpuinfo(struct seq_file 
 	if (c->x86_cache_size >= 0) 
 		seq_printf(m, "cache size\t: %d KB\n", c->x86_cache_size);
 	
+#ifdef CONFIG_X86_HT
+	if (cpu_has_ht) {
+		extern int phys_proc_id[NR_CPUS];
+		seq_printf(m, "physical id\t: %d\n", phys_proc_id[c - cpu_data]);
+		seq_printf(m, "siblings\t: %d\n", smp_num_siblings);
+	}
+#endif	
+
 	seq_printf(m,
 	        "fpu\t\t: yes\n"
 	        "fpu_exception\t: yes\n"
--- diff/arch/x86_64/kernel/smp.c	2003-11-25 15:24:57.000000000 +0000
+++ source/arch/x86_64/kernel/smp.c	2004-02-23 13:56:39.000000000 +0000
@@ -362,6 +362,18 @@ void smp_send_reschedule(int cpu)
 	send_IPI_mask(cpumask_of_cpu(cpu), RESCHEDULE_VECTOR);
 }
 
+#ifdef CONFIG_KGDB
+/*
+ * By using the NMI code instead of a vector we just sneak thru the
+ * word generator coming out with just what we want.  AND it does
+ * not matter if clustered_apic_mode is set or not.
+ */
+void smp_send_nmi_allbutself(void)
+{
+	send_IPI_allbutself(APIC_DM_NMI);
+}
+#endif
+
 /*
  * Structure and data for smp_call_function(). This is designed to minimise
  * static memory requirements. It also looks cleaner.
--- diff/arch/x86_64/kernel/smpboot.c	2003-09-17 12:28:03.000000000 +0100
+++ source/arch/x86_64/kernel/smpboot.c	2004-02-23 13:56:39.000000000 +0000
@@ -53,6 +53,10 @@
 #include <asm/tlbflush.h>
 #include <asm/proto.h>
 
+/* Number of siblings per CPU package */
+int smp_num_siblings = 1;
+int phys_proc_id[NR_CPUS]; /* Package ID of each logical CPU */
+
 /* Bitmask of currently online CPUs */
 cpumask_t cpu_online_map;
 
@@ -66,6 +70,8 @@ struct cpuinfo_x86 cpu_data[NR_CPUS] __c
 /* Set when the idlers are all forked */
 int smp_threads_ready;
 
+int cpu_sibling_map[NR_CPUS] __cacheline_aligned;
+
 /*
  * Trampoline 80x86 program as an array.
  */
@@ -857,6 +863,34 @@ static void __init smp_boot_cpus(unsigne
 		Dprintk("Before bogocount - setting activated=1.\n");
 	}
 
+	/*
+	 * If Hyper-Threading is avaialble, construct cpu_sibling_map[], so
+	 * that we can tell the sibling CPU efficiently.
+	 */
+	if (cpu_has_ht && smp_num_siblings > 1) {
+		for (cpu = 0; cpu < NR_CPUS; cpu++)
+			cpu_sibling_map[cpu] = NO_PROC_ID;
+		
+		for (cpu = 0; cpu < NR_CPUS; cpu++) {
+			int 	i;
+			if (!cpu_isset(cpu, cpu_callout_map))
+				continue;
+
+			for (i = 0; i < NR_CPUS; i++) {
+				if (i == cpu || !cpu_isset(i, cpu_callout_map))
+					continue;
+				if (phys_proc_id[cpu] == phys_proc_id[i]) {
+					cpu_sibling_map[cpu] = i;
+					break;
+				}
+			}
+			if (cpu_sibling_map[cpu] == NO_PROC_ID) {
+				smp_num_siblings = 1;
+				printk(KERN_WARNING "WARNING: No sibling found for CPU %d.\n", cpu);
+			}
+		}
+	}
+
 	Dprintk("Boot done.\n");
 
 	/*
--- diff/arch/x86_64/kernel/sys_x86_64.c	2004-02-18 08:54:08.000000000 +0000
+++ source/arch/x86_64/kernel/sys_x86_64.c	2004-02-23 13:56:39.000000000 +0000
@@ -4,6 +4,7 @@
 
 #include <linux/errno.h>
 #include <linux/sched.h>
+#include <linux/syscalls.h>
 #include <linux/mm.h>
 #include <linux/smp.h>
 #include <linux/smp_lock.h>
--- diff/arch/x86_64/kernel/traps.c	2004-02-09 10:36:09.000000000 +0000
+++ source/arch/x86_64/kernel/traps.c	2004-02-23 13:56:39.000000000 +0000
@@ -45,6 +45,9 @@
 #include <asm/proto.h>
 
 #include <linux/irq.h>
+#ifdef CONFIG_KGDB
+#include <asm/kgdb.h>
+#endif
 
 extern struct gate_struct idt_table[256]; 
 
--- diff/arch/x86_64/kernel/x8664_ksyms.c	2004-02-09 10:36:09.000000000 +0000
+++ source/arch/x86_64/kernel/x8664_ksyms.c	2004-02-23 13:56:39.000000000 +0000
@@ -11,6 +11,7 @@
 #include <linux/apm_bios.h>
 #include <linux/kernel.h>
 #include <linux/string.h>
+#include <linux/syscalls.h>
 #include <linux/tty.h>
 
 #include <asm/semaphore.h>
@@ -180,8 +181,6 @@ EXPORT_SYMBOL_NOVERS(memcpy);
 EXPORT_SYMBOL_NOVERS(__memcpy);
 
 /* syscall export needed for misdesigned sound drivers. */
-extern ssize_t sys_read(unsigned int fd, char * buf, size_t count);
-extern off_t sys_lseek(unsigned int fd, off_t offset, unsigned int origin);
 EXPORT_SYMBOL(sys_read);
 EXPORT_SYMBOL(sys_lseek);
 EXPORT_SYMBOL(sys_open);
@@ -194,6 +193,10 @@ EXPORT_SYMBOL(atomic_dec_and_lock);
 
 EXPORT_SYMBOL(die_chain);
 
+#ifdef CONFIG_SMP
+EXPORT_SYMBOL(cpu_sibling_map);
+#endif
+
 extern void do_softirq_thunk(void);
 EXPORT_SYMBOL_NOVERS(do_softirq_thunk);
 
--- diff/arch/x86_64/lib/Makefile	2003-06-30 10:07:20.000000000 +0100
+++ source/arch/x86_64/lib/Makefile	2004-02-23 13:56:39.000000000 +0000
@@ -11,3 +11,4 @@ lib-y += memcpy.o memmove.o memset.o cop
 
 lib-$(CONFIG_IO_DEBUG) += iodebug.o
 lib-$(CONFIG_HAVE_DEC_LOCK) += dec_and_lock.o
+lib-$(CONFIG_KGDB) += kgdb_serial.o
--- diff/arch/x86_64/lib/copy_page.S	2003-09-30 15:46:12.000000000 +0100
+++ source/arch/x86_64/lib/copy_page.S	2004-02-23 13:56:39.000000000 +0000
@@ -8,11 +8,6 @@
 	.globl copy_page
 	.p2align 4
 copy_page:
-	prefetch (%rsi) 
-	prefetch 1*64(%rsi)
-	prefetchw (%rdi) 
-	prefetchw 1*64(%rdi) 
-
 	subq	$3*8,%rsp
 	movq	%rbx,(%rsp)
 	movq	%r12,1*8(%rsp)
@@ -32,7 +27,7 @@ copy_page:
 	movq     48 (%rsi), %r11
 	movq     56 (%rsi), %r12
 
-	prefetch 5*64(%rsi)
+	prefetcht0 5*64(%rsi)
 
 	movq     %rax,    (%rdi)
 	movq     %rbx,  8 (%rdi)
@@ -43,8 +38,6 @@ copy_page:
 	movq     %r11, 48 (%rdi)
 	movq     %r12, 56 (%rdi)
 
-	prefetchw 5*64(%rdi)
-
 	leaq    64 (%rsi), %rsi
 	leaq    64 (%rdi), %rdi
 
--- diff/arch/x86_64/lib/csum-copy.S	2003-09-30 15:46:12.000000000 +0100
+++ source/arch/x86_64/lib/csum-copy.S	2004-02-23 13:56:39.000000000 +0000
@@ -59,15 +59,6 @@ csum_partial_copy_generic:
 	cmpl	 $3*64,%edx
 	jle	 .Lignore
 
-	ignore
-	prefetch (%rdi)
-	ignore
-	prefetch 1*64(%rdi)
-	ignore
-	prefetchw (%rsi)
-	ignore
-	prefetchw 1*64(%rsi)
-
 .Lignore:		
 	subq  $7*8,%rsp
 	movq  %rbx,2*8(%rsp)
@@ -115,7 +106,7 @@ csum_partial_copy_generic:
 	movq  56(%rdi),%r13
 		
 	ignore 2f
-	prefetch 5*64(%rdi)
+	prefetcht0 5*64(%rdi)
 2:							
 	adcq  %rbx,%rax
 	adcq  %r8,%rax
@@ -146,8 +137,6 @@ csum_partial_copy_generic:
 	dest
 	movq %r13,56(%rsi)
 	
-	ignore 3f
-	prefetchw 5*64(%rsi)
 3:
 	
 	leaq 64(%rdi),%rdi
--- diff/arch/x86_64/mm/init.c	2004-02-18 08:54:08.000000000 +0000
+++ source/arch/x86_64/mm/init.c	2004-02-23 13:56:39.000000000 +0000
@@ -402,6 +402,13 @@ void __init mem_init(void)
 	int codesize, reservedpages, datasize, initsize;
 	int tmp;
 
+#ifdef CONFIG_SWIOTLB
+       if (!iommu_aperture && end_pfn >= 0xffffffff>>PAGE_SHIFT) { 
+	       swiotlb_init();
+	       swiotlb = 1;
+       }
+#endif
+
 	/* How many end-of-memory variables you have, grandma! */
 	max_low_pfn = end_pfn;
 	max_pfn = end_pfn;
--- diff/arch/x86_64/oprofile/Makefile	2003-09-30 15:46:12.000000000 +0100
+++ source/arch/x86_64/oprofile/Makefile	2004-02-23 13:56:39.000000000 +0000
@@ -1,7 +1,6 @@
 #
 # oprofile for x86-64.
-# Just reuse the one from i386. The Hammer performance counters 
-# are similar to Athlon.
+# Just reuse the one from i386. 
 #
 
 obj-$(CONFIG_OPROFILE) += oprofile.o
@@ -13,7 +12,8 @@ DRIVER_OBJS = $(addprefix ../../../drive
 	timer_int.o )
 
 OPROFILE-y := init.o
-OPROFILE-$(CONFIG_X86_LOCAL_APIC) += nmi_int.o op_model_athlon.o
+OPROFILE-$(CONFIG_X86_LOCAL_APIC) += nmi_int.o op_model_athlon.o op_model_p4.o \
+				     op_model_ppro.o
 OPROFILE-$(CONFIG_X86_IO_APIC)    += nmi_timer_int.o 
 
 oprofile-y = $(DRIVER_OBJS) $(addprefix ../../i386/oprofile/, $(OPROFILE-y))
--- diff/drivers/Makefile	2003-09-17 12:28:03.000000000 +0100
+++ source/drivers/Makefile	2004-02-23 13:56:43.000000000 +0000
@@ -45,7 +45,7 @@ obj-$(CONFIG_I2C)		+= i2c/
 obj-$(CONFIG_PHONE)		+= telephony/
 obj-$(CONFIG_MD)		+= md/
 obj-$(CONFIG_BT)		+= bluetooth/
-obj-$(CONFIG_ISDN_BOOL)		+= isdn/
+obj-$(CONFIG_ISDN)		+= isdn/
 obj-$(CONFIG_MCA)		+= mca/
 obj-$(CONFIG_EISA)		+= eisa/
 obj-$(CONFIG_CPU_FREQ)		+= cpufreq/
--- diff/drivers/acorn/char/i2c.c	2004-02-09 10:36:09.000000000 +0000
+++ source/drivers/acorn/char/i2c.c	2004-02-23 13:56:40.000000000 +0000
@@ -311,9 +311,6 @@ static struct i2c_adapter ioc_ops = {
 	.algo_data		= &ioc_data,
 	.client_register	= ioc_client_reg,
 	.client_unregister	= ioc_client_unreg,
-	.dev			= {
-		.name		= "IOC/IOMD",
-	},
 };
 
 static int __init i2c_ioc_init(void)
--- diff/drivers/acorn/char/pcf8583.c	2003-06-09 14:18:18.000000000 +0100
+++ source/drivers/acorn/char/pcf8583.c	2004-02-23 13:56:40.000000000 +0000
@@ -37,8 +37,7 @@ static struct i2c_client_address_data ad
 #define DAT(x) ((unsigned int)(x->dev.driver_data))
 
 static int
-pcf8583_attach(struct i2c_adapter *adap, int addr, unsigned short flags,
-	       int kind)
+pcf8583_attach(struct i2c_adapter *adap, int addr, int kind)
 {
 	struct i2c_client *c;
 	unsigned char buf[1], ad[1] = { 0 };
@@ -51,13 +50,11 @@ pcf8583_attach(struct i2c_adapter *adap,
 	if (!c)
 		return -ENOMEM;
 
-	strcpy(c->dev.name, "PCF8583");
+	memset(c, 0, sizeof(*c));
 	c->id		= pcf8583_driver.id;
-	c->flags	= 0;
 	c->addr		= addr;
 	c->adapter	= adap;
 	c->driver	= &pcf8583_driver;
-	c->dev.driver_data = NULL;
 
 	if (i2c_transfer(c->adapter, msgs, 2) == 2)
 		DAT(c) = buf[0];
--- diff/drivers/acpi/Kconfig	2004-02-18 08:54:08.000000000 +0000
+++ source/drivers/acpi/Kconfig	2004-02-23 13:56:40.000000000 +0000
@@ -263,5 +263,23 @@ config ACPI_RELAXED_AML
 	  particular, many Toshiba laptops require this for correct operation
 	  of the AC module.
 
+config X86_PM_TIMER
+	bool "Power Management Timer Support"
+	depends on X86 && ACPI
+	depends on ACPI_BOOT && EXPERIMENTAL
+	default n
+	help
+	  The Power Management Timer is available on all ACPI-capable,
+	  in most cases even if ACPI is unusable or blacklisted.
+
+	  This timing source is not affected by powermanagement features
+	  like aggressive processor idling, throttling, frequency and/or
+	  voltage scaling, unlike the commonly used Time Stamp Counter
+	  (TSC) timing source.
+
+	  So, if you see messages like 'Losing too many ticks!' in the
+	  kernel logs, and/or you are using a this on a notebook which
+	  does not yet have an HPET, you should say "Y" here.
+
 endmenu
 
--- diff/drivers/acpi/dispatcher/dsmthdat.c	2004-02-09 10:36:09.000000000 +0000
+++ source/drivers/acpi/dispatcher/dsmthdat.c	2004-02-23 13:56:40.000000000 +0000
@@ -206,8 +206,7 @@ acpi_ds_method_data_init_args (
 		 * Store the argument in the method/walk descriptor.
 		 * Do not copy the arg in order to implement call by reference
 		 */
-		status = acpi_ds_method_data_set_value (AML_ARG_OP, index, params[index],
-				 walk_state);
+		status = acpi_ds_method_data_set_value (AML_ARG_OP, index, params[index], walk_state);
 		if (ACPI_FAILURE (status)) {
 			return_ACPI_STATUS (status);
 		}
@@ -465,6 +464,7 @@ acpi_ds_method_data_get_value (
 			return_ACPI_STATUS (AE_AML_UNINITIALIZED_LOCAL);
 
 		default:
+			ACPI_REPORT_ERROR (("Not Arg/Local opcode: %X\n", opcode));
 			return_ACPI_STATUS (AE_AML_INTERNAL);
 		}
 	}
@@ -597,7 +597,10 @@ acpi_ds_store_object_to_local (
 
 	/*
 	 * If the reference count on the object is more than one, we must
-	 * take a copy of the object before we store.
+	 * take a copy of the object before we store.  A reference count
+	 * of exactly 1 means that the object was just created during the
+	 * evaluation of an expression, and we can safely use it since it
+	 * is not used anywhere else.
 	 */
 	new_obj_desc = obj_desc;
 	if (obj_desc->common.reference_count > 1) {
--- diff/drivers/acpi/dispatcher/dsobject.c	2004-02-09 10:36:09.000000000 +0000
+++ source/drivers/acpi/dispatcher/dsobject.c	2004-02-23 13:56:40.000000000 +0000
@@ -582,6 +582,11 @@ acpi_ds_init_object_from_op (
 
 			obj_desc->reference.opcode = AML_ARG_OP;
 			obj_desc->reference.offset = opcode - AML_ARG_OP;
+
+#ifndef ACPI_NO_METHOD_EXECUTION
+			status = acpi_ds_method_data_get_node (AML_ARG_OP, obj_desc->reference.offset,
+					 walk_state, (struct acpi_namespace_node **) &obj_desc->reference.object);
+#endif
 			break;
 
 		default: /* Other literals, etc.. */
--- diff/drivers/acpi/dispatcher/dsopcode.c	2004-02-09 10:36:09.000000000 +0000
+++ source/drivers/acpi/dispatcher/dsopcode.c	2004-02-23 13:56:40.000000000 +0000
@@ -243,8 +243,8 @@ acpi_ds_get_buffer_arguments (
 
 	node = obj_desc->buffer.node;
 	if (!node) {
-		ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
-				"No pointer back to NS node in buffer %p\n", obj_desc));
+		ACPI_REPORT_ERROR ((
+				"No pointer back to NS node in buffer obj %p\n", obj_desc));
 		return_ACPI_STATUS (AE_AML_INTERNAL);
 	}
 
@@ -290,7 +290,7 @@ acpi_ds_get_package_arguments (
 
 	node = obj_desc->package.node;
 	if (!node) {
-		ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
+		ACPI_REPORT_ERROR ((
 				"No pointer back to NS node in package %p\n", obj_desc));
 		return_ACPI_STATUS (AE_AML_INTERNAL);
 	}
--- diff/drivers/acpi/dispatcher/dsutils.c	2004-02-09 10:36:09.000000000 +0000
+++ source/drivers/acpi/dispatcher/dsutils.c	2004-02-23 13:56:40.000000000 +0000
@@ -280,7 +280,8 @@ acpi_ds_resolve_operands (
 
 	/*
 	 * Attempt to resolve each of the valid operands
-	 * Method arguments are passed by value, not by reference
+	 * Method arguments are passed by reference, not by value.  This means
+	 * that the actual objects are passed, not copies of the objects.
 	 */
 	for (i = 0; i < walk_state->num_operands; i++) {
 		status = acpi_ex_resolve_to_value (&walk_state->operands[i], walk_state);
--- diff/drivers/acpi/dispatcher/dswstate.c	2004-02-09 10:36:09.000000000 +0000
+++ source/drivers/acpi/dispatcher/dswstate.c	2004-02-23 13:56:40.000000000 +0000
@@ -328,7 +328,7 @@ acpi_ds_result_push (
 
 	state = walk_state->results;
 	if (!state) {
-		ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "No result stack frame\n"));
+		ACPI_REPORT_ERROR (("No result stack frame during push\n"));
 		return (AE_AML_INTERNAL);
 	}
 
--- diff/drivers/acpi/executer/exconvrt.c	2004-02-09 10:36:10.000000000 +0000
+++ source/drivers/acpi/executer/exconvrt.c	2004-02-23 13:56:40.000000000 +0000
@@ -55,8 +55,9 @@
  *
  * FUNCTION:    acpi_ex_convert_to_integer
  *
- * PARAMETERS:  *obj_desc       - Object to be converted.  Must be an
+ * PARAMETERS:  obj_desc        - Object to be converted.  Must be an
  *                                Integer, Buffer, or String
+ *              result_desc     - Where the new Integer object is returned
  *              walk_state      - Current method state
  *
  * RETURN:      Status
@@ -189,8 +190,9 @@ acpi_ex_convert_to_integer (
  *
  * FUNCTION:    acpi_ex_convert_to_buffer
  *
- * PARAMETERS:  *obj_desc       - Object to be converted.  Must be an
+ * PARAMETERS:  obj_desc        - Object to be converted.  Must be an
  *                                Integer, Buffer, or String
+ *              result_desc     - Where the new buffer object is returned
  *              walk_state      - Current method state
  *
  * RETURN:      Status
@@ -319,6 +321,7 @@ acpi_ex_convert_to_ascii (
 
 	ACPI_FUNCTION_ENTRY ();
 
+
 	if (data_width < sizeof (acpi_integer)) {
 		leading_zero = FALSE;
 		length = data_width;
@@ -328,22 +331,21 @@ acpi_ex_convert_to_ascii (
 		length = sizeof (acpi_integer);
 	}
 
-
 	switch (base) {
 	case 10:
 
 		remainder = 0;
-		for (i = ACPI_MAX_DECIMAL_DIGITS; i > 0 ; i--) {
+		for (i = ACPI_MAX_DECIMAL_DIGITS; i > 0; i--) {
 			/* Divide by nth factor of 10 */
 
 			digit = integer;
-			for (j = 1; j < i; j++) {
+			for (j = 0; j < i; j++) {
 				(void) acpi_ut_short_divide (&digit, 10, &digit, &remainder);
 			}
 
 			/* Create the decimal digit */
 
-			if (digit != 0) {
+			if (remainder != 0) {
 				leading_zero = FALSE;
 			}
 
@@ -354,6 +356,7 @@ acpi_ex_convert_to_ascii (
 		}
 		break;
 
+
 	case 16:
 
 		/* Copy the integer to the buffer */
@@ -372,13 +375,14 @@ acpi_ex_convert_to_ascii (
 		}
 		break;
 
+
 	default:
 		break;
 	}
 
 	/*
 	 * Since leading zeros are supressed, we must check for the case where
-	 * the integer equals 0.
+	 * the integer equals 0
 	 *
 	 * Finally, null terminate the string and return the length
 	 */
@@ -396,8 +400,11 @@ acpi_ex_convert_to_ascii (
  *
  * FUNCTION:    acpi_ex_convert_to_string
  *
- * PARAMETERS:  *obj_desc       - Object to be converted.  Must be an
- *                                Integer, Buffer, or String
+ * PARAMETERS:  obj_desc        - Object to be converted.  Must be an
+ *                                  Integer, Buffer, or String
+ *              result_desc     - Where the string object is returned
+ *              Base            - 10 or 16
+ *              max_length      - Max length of the returned string
  *              walk_state      - Current method state
  *
  * RETURN:      Status
@@ -415,10 +422,10 @@ acpi_ex_convert_to_string (
 	struct acpi_walk_state          *walk_state)
 {
 	union acpi_operand_object       *ret_desc;
-	u32                             i;
-	u32                             string_length;
 	u8                              *new_buf;
 	u8                              *pointer;
+	u32                             string_length;
+	u32                             i;
 
 
 	ACPI_FUNCTION_TRACE_PTR ("ex_convert_to_string", obj_desc);
@@ -539,7 +546,6 @@ acpi_ex_convert_to_string (
 		return_ACPI_STATUS (AE_TYPE);
 	}
 
-
 	/*
 	 * If we are about to overwrite the original object on the operand stack,
 	 * we must remove a reference on the original object because we are
@@ -562,6 +568,7 @@ acpi_ex_convert_to_string (
  *
  * PARAMETERS:  destination_type    - Current type of the destination
  *              source_desc         - Source object to be converted.
+ *              result_desc         - Where the converted object is returned
  *              walk_state          - Current method state
  *
  * RETURN:      Status
@@ -653,6 +660,8 @@ acpi_ex_convert_to_target_type (
 
 
 		default:
+			ACPI_REPORT_ERROR (("Bad destination type during conversion: %X\n",
+				destination_type));
 			status = AE_AML_INTERNAL;
 			break;
 		}
@@ -672,6 +681,8 @@ acpi_ex_convert_to_target_type (
 			GET_CURRENT_ARG_TYPE (walk_state->op_info->runtime_args),
 			walk_state->op_info->name, acpi_ut_get_type_name (destination_type)));
 
+		ACPI_REPORT_ERROR (("Bad Target Type (ARGI): %X\n",
+			GET_CURRENT_ARG_TYPE (walk_state->op_info->runtime_args)))
 		status = AE_AML_INTERNAL;
 	}
 
--- diff/drivers/acpi/executer/exfldio.c	2004-02-09 10:36:10.000000000 +0000
+++ source/drivers/acpi/executer/exfldio.c	2004-02-23 13:56:40.000000000 +0000
@@ -507,8 +507,8 @@ acpi_ex_field_datum_io (
 
 	default:
 
-		ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "%p, Wrong object type - %s\n",
-			obj_desc, acpi_ut_get_object_type_name (obj_desc)));
+		ACPI_REPORT_ERROR (("Wrong object type in field I/O %X\n",
+			ACPI_GET_OBJECT_TYPE (obj_desc)));
 		status = AE_AML_INTERNAL;
 		break;
 	}
--- diff/drivers/acpi/executer/exmisc.c	2004-02-09 10:36:10.000000000 +0000
+++ source/drivers/acpi/executer/exmisc.c	2004-02-23 13:56:40.000000000 +0000
@@ -103,7 +103,7 @@ acpi_ex_get_object_reference (
 
 		default:
 
-			ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Unknown Reference subtype %X\n",
+			ACPI_REPORT_ERROR (("Unknown Reference subtype in get ref %X\n",
 				obj_desc->reference.opcode));
 			return_ACPI_STATUS (AE_AML_INTERNAL);
 		}
@@ -121,8 +121,8 @@ acpi_ex_get_object_reference (
 
 	default:
 
-		ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "%p has invalid descriptor [%s]\n",
-				obj_desc, acpi_ut_get_descriptor_name (obj_desc)));
+		ACPI_REPORT_ERROR (("Invalid descriptor type in get ref: %X\n",
+				ACPI_GET_DESCRIPTOR_TYPE (obj_desc)));
 		return_ACPI_STATUS (AE_TYPE);
 	}
 
@@ -349,6 +349,8 @@ acpi_ex_do_concatenate (
 
 		/* Invalid object type, should not happen here */
 
+		ACPI_REPORT_ERROR (("Concat - invalid obj type: %X\n",
+				ACPI_GET_OBJECT_TYPE (obj_desc1)));
 		status = AE_AML_INTERNAL;
 		return_desc = NULL;
 	}
--- diff/drivers/acpi/executer/exoparg2.c	2004-02-09 10:36:10.000000000 +0000
+++ source/drivers/acpi/executer/exoparg2.c	2004-02-23 13:56:40.000000000 +0000
@@ -329,6 +329,8 @@ acpi_ex_opcode_2A_1T_1R (
 			break;
 
 		default:
+			ACPI_REPORT_ERROR (("Concat - invalid obj type: %X\n",
+					ACPI_GET_OBJECT_TYPE (operand[0])));
 			status = AE_AML_INTERNAL;
 		}
 
@@ -433,7 +435,7 @@ acpi_ex_opcode_2A_1T_1R (
 			}
 
 			return_desc->reference.target_type = ACPI_TYPE_PACKAGE;
-			return_desc->reference.object    = operand[0]->package.elements [index];
+			return_desc->reference.object    = operand[0];
 			return_desc->reference.where     = &operand[0]->package.elements [index];
 		}
 		else {
--- diff/drivers/acpi/executer/exprep.c	2004-02-09 10:36:10.000000000 +0000
+++ source/drivers/acpi/executer/exprep.c	2004-02-23 13:56:40.000000000 +0000
@@ -507,7 +507,7 @@ acpi_ex_prep_field_value (
 			(info->field_bit_position / ACPI_MUL_8 (obj_desc->field.access_byte_width));
 
 		if (!obj_desc->index_field.data_obj || !obj_desc->index_field.index_obj) {
-			ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Null Index Object\n"));
+			ACPI_REPORT_ERROR (("Null Index Object during field prep\n"));
 			return_ACPI_STATUS (AE_AML_INTERNAL);
 		}
 
--- diff/drivers/acpi/executer/exresolv.c	2004-02-09 10:36:10.000000000 +0000
+++ source/drivers/acpi/executer/exresolv.c	2004-02-23 13:56:40.000000000 +0000
@@ -238,8 +238,8 @@ acpi_ex_resolve_object_to_value (
 
 				/* Invalid reference object */
 
-				ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
-					"Unknown target_type %X in Index/Reference obj %p\n",
+				ACPI_REPORT_ERROR ((
+					"During resolve, Unknown target_type %X in Index/Reference obj %p\n",
 					stack_desc->reference.target_type, stack_desc));
 				status = AE_AML_INTERNAL;
 				break;
@@ -258,7 +258,7 @@ acpi_ex_resolve_object_to_value (
 
 		default:
 
-			ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Unknown Reference opcode %X (%s) in %p\n",
+			ACPI_REPORT_ERROR (("During resolve, Unknown Reference opcode %X (%s) in %p\n",
 				opcode, acpi_ps_get_opcode_name (opcode), stack_desc));
 			status = AE_AML_INTERNAL;
 			break;
--- diff/drivers/acpi/executer/exresop.c	2004-02-09 10:36:10.000000000 +0000
+++ source/drivers/acpi/executer/exresop.c	2004-02-23 13:56:40.000000000 +0000
@@ -154,7 +154,7 @@ acpi_ex_resolve_operands (
 
 	arg_types = op_info->runtime_args;
 	if (arg_types == ARGI_INVALID_OPCODE) {
-		ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Internal - %X is not a valid AML opcode\n",
+		ACPI_REPORT_ERROR (("resolve_operands: %X is not a valid AML opcode\n",
 			opcode));
 
 		return_ACPI_STATUS (AE_AML_INTERNAL);
@@ -172,7 +172,7 @@ acpi_ex_resolve_operands (
 	 */
 	while (GET_CURRENT_ARG_TYPE (arg_types)) {
 		if (!stack_ptr || !*stack_ptr) {
-			ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Internal - null stack entry at %p\n",
+			ACPI_REPORT_ERROR (("resolve_operands: Null stack entry at %p\n",
 				stack_ptr));
 
 			return_ACPI_STATUS (AE_AML_INTERNAL);
--- diff/drivers/acpi/executer/exstore.c	2004-02-09 10:36:10.000000000 +0000
+++ source/drivers/acpi/executer/exstore.c	2004-02-23 13:56:40.000000000 +0000
@@ -125,7 +125,7 @@ acpi_ex_store (
 
 	default:
 
-		/* Destination is not an Reference */
+		/* Destination is not a Reference object */
 
 		ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
 			"Destination is not a Reference or Constant object [%p]\n", dest_desc));
@@ -189,35 +189,38 @@ acpi_ex_store (
 		switch (ACPI_GET_OBJECT_TYPE (source_desc)) {
 		case ACPI_TYPE_INTEGER:
 
-			ACPI_DEBUG_PRINT_RAW ((ACPI_DB_DEBUG_OBJECT, "%8.8X%8.8X\n",
+			ACPI_DEBUG_PRINT_RAW ((ACPI_DB_DEBUG_OBJECT, "0x%8.8X%8.8X\n",
 					ACPI_FORMAT_UINT64 (source_desc->integer.value)));
 			break;
 
 
 		case ACPI_TYPE_BUFFER:
 
-			ACPI_DEBUG_PRINT_RAW ((ACPI_DB_DEBUG_OBJECT, "Length %.2X\n",
+			ACPI_DEBUG_PRINT_RAW ((ACPI_DB_DEBUG_OBJECT, "Length 0x%.2X",
 					(u32) source_desc->buffer.length));
+			ACPI_DUMP_BUFFER (source_desc->buffer.pointer,
+				(source_desc->buffer.length < 32) ? source_desc->buffer.length : 32);
 			break;
 
 
 		case ACPI_TYPE_STRING:
 
-			ACPI_DEBUG_PRINT_RAW ((ACPI_DB_DEBUG_OBJECT, "%s\n", source_desc->string.pointer));
+			ACPI_DEBUG_PRINT_RAW ((ACPI_DB_DEBUG_OBJECT, "Length 0x%.2X, \"%s\"\n",
+					source_desc->string.length, source_desc->string.pointer));
 			break;
 
 
 		case ACPI_TYPE_PACKAGE:
 
-			ACPI_DEBUG_PRINT_RAW ((ACPI_DB_DEBUG_OBJECT, "Elements Ptr - %p\n",
-					source_desc->package.elements));
+			ACPI_DEBUG_PRINT_RAW ((ACPI_DB_DEBUG_OBJECT, "Size 0x%.2X Elements Ptr - %p\n",
+					source_desc->package.count, source_desc->package.elements));
 			break;
 
 
 		default:
 
-			ACPI_DEBUG_PRINT_RAW ((ACPI_DB_DEBUG_OBJECT, "Type %s %p\n",
-					acpi_ut_get_object_type_name (source_desc), source_desc));
+			ACPI_DEBUG_PRINT_RAW ((ACPI_DB_DEBUG_OBJECT, "%p\n",
+					source_desc));
 			break;
 		}
 
@@ -227,7 +230,7 @@ acpi_ex_store (
 
 	default:
 
-		ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Unknown Reference opcode %X\n",
+		ACPI_REPORT_ERROR (("ex_store: Unknown Reference opcode %X\n",
 			ref_desc->reference.opcode));
 		ACPI_DUMP_ENTRY (ref_desc, ACPI_LV_ERROR);
 
@@ -263,6 +266,7 @@ acpi_ex_store_object_to_index (
 	union acpi_operand_object       *obj_desc;
 	union acpi_operand_object       *new_desc;
 	u8                              value = 0;
+	u32                             i;
 
 
 	ACPI_FUNCTION_TRACE ("ex_store_object_to_index");
@@ -283,6 +287,7 @@ acpi_ex_store_object_to_index (
 		/*
 		 * The object at *(index_desc->Reference.Where) is the
 		 * element within the package that is to be modified.
+		 * The parent package object is at index_desc->Reference.Object
 		 */
 		obj_desc = *(index_desc->reference.where);
 
@@ -309,6 +314,12 @@ acpi_ex_store_object_to_index (
 			if (new_desc == source_desc) {
 				acpi_ut_add_reference (new_desc);
 			}
+
+			/* Increment reference count by the ref count of the parent package -1 */
+
+			for (i = 1; i < ((union acpi_operand_object *) index_desc->reference.object)->common.reference_count; i++) {
+				acpi_ut_add_reference (new_desc);
+			}
 		}
 		break;
 
--- diff/drivers/acpi/executer/exstoren.c	2004-02-09 10:36:10.000000000 +0000
+++ source/drivers/acpi/executer/exstoren.c	2004-02-23 13:56:40.000000000 +0000
@@ -112,6 +112,12 @@ acpi_ex_resolve_object (
 			}
 		}
 
+		/* For copy_object, no further validation necessary */
+
+		if (walk_state->opcode == AML_COPY_OP) {
+			break;
+		}
+
 		/*
 		 * Must have a Integer, Buffer, or String
 		 */
@@ -136,7 +142,7 @@ acpi_ex_resolve_object (
 		/*
 		 * Aliases are resolved by acpi_ex_prep_operands
 		 */
-		ACPI_DEBUG_PRINT ((ACPI_DB_WARN, "Store into Alias - should never happen\n"));
+		ACPI_REPORT_ERROR (("Store into Alias - should never happen\n"));
 		status = AE_AML_INTERNAL;
 		break;
 
--- diff/drivers/acpi/namespace/nsaccess.c	2004-02-09 10:36:10.000000000 +0000
+++ source/drivers/acpi/namespace/nsaccess.c	2004-02-23 13:56:40.000000000 +0000
@@ -314,7 +314,7 @@ acpi_ns_lookup (
 	else {
 		prefix_node = scope_info->scope.node;
 		if (ACPI_GET_DESCRIPTOR_TYPE (prefix_node) != ACPI_DESC_TYPE_NAMED) {
-			ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "%p Not a namespace node [%s]\n",
+			ACPI_REPORT_ERROR (("ns_lookup: %p is not a namespace node [%s]\n",
 					prefix_node, acpi_ut_get_descriptor_name (prefix_node)));
 			return_ACPI_STATUS (AE_AML_INTERNAL);
 		}
--- diff/drivers/acpi/parser/psargs.c	2004-02-09 10:36:10.000000000 +0000
+++ source/drivers/acpi/parser/psargs.c	2004-02-23 13:56:40.000000000 +0000
@@ -315,8 +315,8 @@ acpi_ps_get_next_namepath (
 				acpi_ps_append_arg (arg, name_op);
 
 				if (!method_desc) {
-					ACPI_DEBUG_PRINT ((ACPI_DB_PARSE,
-						"Control Method - %p has no attached object\n",
+					ACPI_REPORT_ERROR ((
+						"ps_get_next_namepath: Control Method %p has no attached object\n",
 						node));
 					return_ACPI_STATUS (AE_AML_INTERNAL);
 				}
--- diff/drivers/acpi/sleep/proc.c	2004-02-09 10:36:10.000000000 +0000
+++ source/drivers/acpi/sleep/proc.c	2004-02-23 13:56:40.000000000 +0000
@@ -44,10 +44,10 @@ static int acpi_system_sleep_open_fs(str
 	return single_open(file, acpi_system_sleep_seq_show, PDE(inode)->data);
 }
 
-static int
+static ssize_t
 acpi_system_write_sleep (
 	struct file		*file,
-	const char		*buffer,
+	const char __user	*buffer,
 	size_t			count,
 	loff_t			*ppos)
 {
@@ -189,10 +189,10 @@ get_date_field (
 }
 
 
-static int
+static ssize_t
 acpi_system_write_alarm (
 	struct file		*file,
-	const char		*buffer,
+	const char __user	*buffer,
 	size_t			count,
 	loff_t			*ppos)
 {
--- diff/drivers/acpi/tables.c	2004-02-18 08:54:08.000000000 +0000
+++ source/drivers/acpi/tables.c	2004-02-23 13:56:40.000000000 +0000
@@ -58,6 +58,7 @@ static char *acpi_table_signatures[ACPI_
 	[ACPI_SSDT]		= "SSDT",
 	[ACPI_SPMI]		= "SPMI",
 	[ACPI_HPET]		= "HPET",
+	[ACPI_MCFG]		= "MCFG",
 };
 
 static char *mps_inti_flags_polarity[] = { "dfl", "high", "res", "low" };
--- diff/drivers/acpi/utils.c	2003-02-26 16:00:53.000000000 +0000
+++ source/drivers/acpi/utils.c	2004-02-23 13:56:40.000000000 +0000
@@ -350,7 +350,7 @@ acpi_evaluate_reference (
 	if ((buffer.length == 0) || !package) {
 		ACPI_DEBUG_PRINT((ACPI_DB_ERROR, 
 			"No return object (len %X ptr %p)\n", 
-			buffer.length, package));
+			(unsigned)buffer.length, package));
 		status = AE_BAD_DATA;
 		acpi_util_eval_error(handle, pathname, status);
 		goto end;
--- diff/drivers/base/Makefile	2004-02-18 08:54:08.000000000 +0000
+++ source/drivers/base/Makefile	2004-02-23 13:56:40.000000000 +0000
@@ -2,7 +2,8 @@
 
 obj-y			:= core.o sys.o interface.o bus.o \
 			   driver.o class.o class_simple.o platform.o \
-			   cpu.o firmware.o init.o map.o dmapool.o
+			   cpu.o firmware.o init.o map.o
+obj-$(CONFIG_PCI)	+= dmapool.o
 obj-y			+= power/
 obj-$(CONFIG_FW_LOADER)	+= firmware_class.o
 obj-$(CONFIG_NUMA)	+= node.o
--- diff/drivers/base/cpu.c	2003-10-27 09:20:43.000000000 +0000
+++ source/drivers/base/cpu.c	2004-02-23 13:56:40.000000000 +0000
@@ -7,6 +7,7 @@
 #include <linux/init.h>
 #include <linux/cpu.h>
 #include <linux/topology.h>
+#include <linux/device.h>
 
 
 struct sysdev_class cpu_sysdev_class = {
@@ -14,6 +15,46 @@ struct sysdev_class cpu_sysdev_class = {
 };
 EXPORT_SYMBOL(cpu_sysdev_class);
 
+#ifdef CONFIG_HOTPLUG_CPU
+static ssize_t show_online(struct sys_device *dev, char *buf)
+{
+	struct cpu *cpu = container_of(dev, struct cpu, sysdev);
+
+	return sprintf(buf, "%u\n", !!cpu_online(cpu->sysdev.id));
+}
+
+static ssize_t store_online(struct sys_device *dev, const char *buf,
+			    size_t count)
+{
+	struct cpu *cpu = container_of(dev, struct cpu, sysdev);
+	ssize_t ret;
+
+	switch (buf[0]) {
+	case '0':
+		ret = cpu_down(cpu->sysdev.id);
+		break;
+	case '1':
+		ret = cpu_up(cpu->sysdev.id);
+		break;
+	default:
+		ret = -EINVAL;
+	}
+
+	if (ret >= 0)
+		ret = count;
+	return ret;
+}
+static SYSDEV_ATTR(online, 0600, show_online, store_online);
+
+static void __init register_cpu_control(struct cpu *cpu)
+{
+	sysdev_create_file(&cpu->sysdev, &attr_online);
+}
+#else /* ... !CONFIG_HOTPLUG_CPU */
+static void __init register_cpu_control(struct cpu *cpu)
+{
+}
+#endif /* CONFIG_HOTPLUG_CPU */
 
 /*
  * register_cpu - Setup a driverfs device for a CPU.
@@ -29,11 +70,13 @@ int __init register_cpu(struct cpu *cpu,
 	cpu->sysdev.id = num;
 	cpu->sysdev.cls = &cpu_sysdev_class;
 
-	error = sys_device_register(&cpu->sysdev);
+	error = sysdev_register(&cpu->sysdev);
 	if (!error && root)
 		error = sysfs_create_link(&root->sysdev.kobj,
 					  &cpu->sysdev.kobj,
 					  kobject_name(&cpu->sysdev.kobj));
+	if (!error)
+		register_cpu_control(cpu);
 	return error;
 }
 
--- diff/drivers/base/dmapool.c	2004-02-18 08:54:08.000000000 +0000
+++ source/drivers/base/dmapool.c	2004-02-23 13:56:40.000000000 +0000
@@ -52,7 +52,7 @@ show_pools (struct device *dev, char *bu
 	next = buf;
 	size = PAGE_SIZE;
 
-	temp = snprintf (next, size, "poolinfo - 0.1\n");
+	temp = scnprintf(next, size, "poolinfo - 0.1\n");
 	size -= temp;
 	next += temp;
 
@@ -67,7 +67,7 @@ show_pools (struct device *dev, char *bu
 		}
 
 		/* per-pool info, no real statistics yet */
-		temp = snprintf (next, size, "%-16s %4u %4Zu %4Zu %2u\n",
+		temp = scnprintf(next, size, "%-16s %4u %4Zu %4Zu %2u\n",
 				pool->name,
 				blocks, pages * pool->blocks_per_page,
 				pool->size, pages);
--- diff/drivers/base/node.c	2004-01-19 10:22:55.000000000 +0000
+++ source/drivers/base/node.c	2004-02-23 13:56:40.000000000 +0000
@@ -23,7 +23,7 @@ static ssize_t node_read_cpumap(struct s
 
 	/* FIXME - someone should pass us a buffer size (count) or
 	 * use seq_file or something to avoid buffer overrun risk. */
-	len = cpumask_snprintf(buf, 99 /* XXX FIXME */, mask);
+	len = cpumask_scnprintf(buf, 99 /* XXX FIXME */, mask);
 	len += sprintf(buf + len, "\n");
 	return len;
 }
@@ -69,7 +69,7 @@ int __init register_node(struct node *no
 	node->cpumap = node_to_cpumask(num);
 	node->sysdev.id = num;
 	node->sysdev.cls = &node_class;
-	error = sys_device_register(&node->sysdev);
+	error = sysdev_register(&node->sysdev);
 
 	if (!error){
 		sysdev_create_file(&node->sysdev, &attr_cpumap);
--- diff/drivers/base/sys.c	2003-09-17 12:28:03.000000000 +0100
+++ source/drivers/base/sys.c	2004-02-23 13:56:40.000000000 +0000
@@ -8,7 +8,7 @@
  * 
  * This exports a 'system' bus type. 
  * By default, a 'sys' bus gets added to the root of the system. There will
- * always be core system devices. Devices can use sys_device_register() to
+ * always be core system devices. Devices can use sysdev_register() to
  * add themselves as children of the system bus.
  */
 
@@ -164,11 +164,11 @@ EXPORT_SYMBOL(sysdev_driver_unregister);
 
 
 /**
- *	sys_device_register - add a system device to the tree
+ *	sysdev_register - add a system device to the tree
  *	@sysdev:	device in question
  *
  */
-int sys_device_register(struct sys_device * sysdev)
+int sysdev_register(struct sys_device * sysdev)
 {
 	int error;
 	struct sysdev_class * cls = sysdev->cls;
@@ -212,7 +212,7 @@ int sys_device_register(struct sys_devic
 	return error;
 }
 
-void sys_device_unregister(struct sys_device * sysdev)
+void sysdev_unregister(struct sys_device * sysdev)
 {
 	struct sysdev_driver * drv;
 
@@ -390,5 +390,5 @@ int __init sys_bus_init(void)
 	return subsystem_register(&system_subsys);
 }
 
-EXPORT_SYMBOL(sys_device_register);
-EXPORT_SYMBOL(sys_device_unregister);
+EXPORT_SYMBOL(sysdev_register);
+EXPORT_SYMBOL(sysdev_unregister);
--- diff/drivers/block/Kconfig	2004-02-09 10:36:10.000000000 +0000
+++ source/drivers/block/Kconfig	2004-02-23 13:56:40.000000000 +0000
@@ -235,10 +235,13 @@ config BLK_DEV_LOOP
 	  bits of, say, a sound file). This is also safe if the file resides
 	  on a remote file server.
 
-	  There are several ways of doing this. Some of these require kernel
-	  patches. The vanilla kernel offers the cryptoloop option. If you
-	  want to use that, say Y to both LOOP and CRYPTOLOOP, and make sure
-	  you have a recent (version 2.12 or later) version of util-linux.
+	  There are several ways of encrypting disks. Some of these require
+	  kernel patches. The vanilla kernel offers the cryptoloop option
+	  and a Device Mapper target (which is superior, as it supports all
+	  file systems). If you want to use the cryptoloop, say Y to both
+	  LOOP and CRYPTOLOOP, and make sure you have a recent (version 2.12
+	  or later) version of util-linux. Additionally, be aware that
+	  the cryptoloop is not safe for storing journaled filesystems.
 
 	  Note that this loop device has nothing to do with the loopback
 	  device used for network connections from the machine to itself.
@@ -257,6 +260,11 @@ config BLK_DEV_CRYPTOLOOP
 	  provided by the CryptoAPI as loop transformation. This might be
 	  used as hard disk encryption.
 
+	  WARNING: This device is not safe for journaled file systems like
+	  ext3 or Reiserfs. Please use the Device Mapper crypto module
+	  instead, which can be configured to be on-disk compatible with the
+	  cryptoloop device.
+
 config BLK_DEV_NBD
 	tristate "Network block device support"
 	depends on NET
--- diff/drivers/block/Kconfig.iosched	2003-10-09 09:47:16.000000000 +0100
+++ source/drivers/block/Kconfig.iosched	2004-02-23 13:56:40.000000000 +0000
@@ -27,3 +27,10 @@ config IOSCHED_DEADLINE
 	  a disk at any one time, its behaviour is almost identical to the
 	  anticipatory I/O scheduler and so is a good choice.
 
+config IOSCHED_CFQ
+	bool "CFQ I/O scheduler" if EMBEDDED
+	default y
+	---help---
+	  The CFQ I/O scheduler tries to distribute bandwidth equally
+	  among all processes in the system. It should provide a fair
+	  working environment, suitable for desktop systems.
--- diff/drivers/block/Makefile	2003-10-27 09:20:37.000000000 +0000
+++ source/drivers/block/Makefile	2004-02-23 13:56:40.000000000 +0000
@@ -18,6 +18,7 @@ obj-y	:= elevator.o ll_rw_blk.o ioctl.o 
 obj-$(CONFIG_IOSCHED_NOOP)	+= noop-iosched.o
 obj-$(CONFIG_IOSCHED_AS)	+= as-iosched.o
 obj-$(CONFIG_IOSCHED_DEADLINE)	+= deadline-iosched.o
+obj-$(CONFIG_IOSCHED_CFQ)	+= cfq-iosched.o
 obj-$(CONFIG_MAC_FLOPPY)	+= swim3.o
 obj-$(CONFIG_BLK_DEV_FD)	+= floppy.o
 obj-$(CONFIG_BLK_DEV_FD98)	+= floppy98.o
--- diff/drivers/block/cryptoloop.c	2003-08-26 10:00:52.000000000 +0100
+++ source/drivers/block/cryptoloop.c	2004-02-23 13:56:40.000000000 +0000
@@ -87,43 +87,49 @@ typedef int (*encdec_ecb_t)(struct crypt
 
 
 static int
-cryptoloop_transfer_ecb(struct loop_device *lo, int cmd, char *raw_buf,
-		     char *loop_buf, int size, sector_t IV)
+cryptoloop_transfer_ecb(struct loop_device *lo, int cmd,
+			struct page *raw_page, unsigned raw_off,
+			struct page *loop_page, unsigned loop_off,
+			int size, sector_t IV)
 {
 	struct crypto_tfm *tfm = (struct crypto_tfm *) lo->key_data;
 	struct scatterlist sg_out = { 0, };
 	struct scatterlist sg_in = { 0, };
 
 	encdec_ecb_t encdecfunc;
-	char const *in;
-	char *out;
+	struct page *in_page, *out_page;
+	unsigned in_offs, out_offs;
 
 	if (cmd == READ) {
-		in = raw_buf;
-		out = loop_buf;
+		in_page = raw_page;
+		in_offs = raw_off;
+		out_page = loop_page;
+		out_offs = loop_off;
 		encdecfunc = tfm->crt_u.cipher.cit_decrypt;
 	} else {
-		in = loop_buf;
-		out = raw_buf;
+		in_page = loop_page;
+		in_offs = loop_off;
+		out_page = raw_page;
+		out_offs = raw_off;
 		encdecfunc = tfm->crt_u.cipher.cit_encrypt;
 	}
 
 	while (size > 0) {
 		const int sz = min(size, LOOP_IV_SECTOR_SIZE);
 
-		sg_in.page = virt_to_page(in);
-		sg_in.offset = (unsigned long)in & ~PAGE_MASK;
+		sg_in.page = in_page;
+		sg_in.offset = in_offs;
 		sg_in.length = sz;
 
-		sg_out.page = virt_to_page(out);
-		sg_out.offset = (unsigned long)out & ~PAGE_MASK;
+		sg_out.page = out_page;
+		sg_out.offset = out_offs;
 		sg_out.length = sz;
 
 		encdecfunc(tfm, &sg_out, &sg_in, sz);
 
 		size -= sz;
-		in += sz;
-		out += sz;
+		in_offs += sz;
+		out_offs += sz;
 	}
 
 	return 0;
@@ -135,24 +141,30 @@ typedef int (*encdec_cbc_t)(struct crypt
 			unsigned int nsg, u8 *iv);
 
 static int
-cryptoloop_transfer_cbc(struct loop_device *lo, int cmd, char *raw_buf,
-		     char *loop_buf, int size, sector_t IV)
+cryptoloop_transfer_cbc(struct loop_device *lo, int cmd,
+			struct page *raw_page, unsigned raw_off,
+			struct page *loop_page, unsigned loop_off,
+			int size, sector_t IV)
 {
 	struct crypto_tfm *tfm = (struct crypto_tfm *) lo->key_data;
 	struct scatterlist sg_out = { 0, };
 	struct scatterlist sg_in = { 0, };
 
 	encdec_cbc_t encdecfunc;
-	char const *in;
-	char *out;
+	struct page *in_page, *out_page;
+	unsigned in_offs, out_offs;
 
 	if (cmd == READ) {
-		in = raw_buf;
-		out = loop_buf;
+		in_page = raw_page;
+		in_offs = raw_off;
+		out_page = loop_page;
+		out_offs = loop_off;
 		encdecfunc = tfm->crt_u.cipher.cit_decrypt_iv;
 	} else {
-		in = loop_buf;
-		out = raw_buf;
+		in_page = loop_page;
+		in_offs = loop_off;
+		out_page = raw_page;
+		out_offs = raw_off;
 		encdecfunc = tfm->crt_u.cipher.cit_encrypt_iv;
 	}
 
@@ -161,39 +173,43 @@ cryptoloop_transfer_cbc(struct loop_devi
 		u32 iv[4] = { 0, };
 		iv[0] = cpu_to_le32(IV & 0xffffffff);
 
-		sg_in.page = virt_to_page(in);
-		sg_in.offset = offset_in_page(in);
+		sg_in.page = in_page;
+		sg_in.offset = in_offs;
 		sg_in.length = sz;
 
-		sg_out.page = virt_to_page(out);
-		sg_out.offset = offset_in_page(out);
+		sg_out.page = out_page;
+		sg_out.offset = out_offs;
 		sg_out.length = sz;
 
 		encdecfunc(tfm, &sg_out, &sg_in, sz, (u8 *)iv);
 
 		IV++;
 		size -= sz;
-		in += sz;
-		out += sz;
+		in_offs += sz;
+		out_offs += sz;
 	}
 
 	return 0;
 }
 
 static int
-cryptoloop_transfer(struct loop_device *lo, int cmd, char *raw_buf,
-		     char *loop_buf, int size, sector_t IV)
+cryptoloop_transfer(struct loop_device *lo, int cmd,
+		    struct page *raw_page, unsigned raw_off,
+		    struct page *loop_page, unsigned loop_off,
+		    int size, sector_t IV)
 {
 	struct crypto_tfm *tfm = (struct crypto_tfm *) lo->key_data;
 	if(tfm->crt_cipher.cit_mode == CRYPTO_TFM_MODE_ECB)
 	{
 		lo->transfer = cryptoloop_transfer_ecb;
-		return cryptoloop_transfer_ecb(lo, cmd, raw_buf, loop_buf, size, IV);
+		return cryptoloop_transfer_ecb(lo, cmd, raw_page, raw_off,
+					       loop_page, loop_off, size, IV);
 	}	
 	if(tfm->crt_cipher.cit_mode == CRYPTO_TFM_MODE_CBC)
 	{	
 		lo->transfer = cryptoloop_transfer_cbc;
-		return cryptoloop_transfer_cbc(lo, cmd, raw_buf, loop_buf, size, IV);
+		return cryptoloop_transfer_cbc(lo, cmd, raw_page, raw_off,
+					       loop_page, loop_off, size, IV);
 	}
 	
 	/*  This is not supposed to happen */
--- diff/drivers/block/floppy.c	2004-02-18 08:54:08.000000000 +0000
+++ source/drivers/block/floppy.c	2004-02-23 13:56:40.000000000 +0000
@@ -4242,6 +4242,15 @@ int __init floppy_init(void)
 		disks[i] = alloc_disk(1);
 		if (!disks[i])
 			goto Enomem;
+
+		disks[i]->major = FLOPPY_MAJOR;
+		disks[i]->first_minor = TOMINOR(i);
+		disks[i]->fops = &floppy_fops;
+		sprintf(disks[i]->disk_name, "fd%d", i);
+
+		init_timer(&motor_off_timer[i]);
+		motor_off_timer[i].data = i;
+		motor_off_timer[i].function = motor_off_callback;
 	}
 
 	devfs_mk_dir ("floppy");
@@ -4255,13 +4264,6 @@ int __init floppy_init(void)
 		goto fail_queue;
 	}
 
-	for (i=0; i<N_DRIVE; i++) {
-		disks[i]->major = FLOPPY_MAJOR;
-		disks[i]->first_minor = TOMINOR(i);
-		disks[i]->fops = &floppy_fops;
-		sprintf(disks[i]->disk_name, "fd%d", i);
-	}
-
 	blk_register_region(MKDEV(FLOPPY_MAJOR, 0), 256, THIS_MODULE,
 				floppy_find, NULL, NULL);
 
@@ -4366,9 +4368,6 @@ int __init floppy_init(void)
 	}
 	
 	for (drive = 0; drive < N_DRIVE; drive++) {
-		init_timer(&motor_off_timer[drive]);
-		motor_off_timer[drive].data = drive;
-		motor_off_timer[drive].function = motor_off_callback;
 		if (!(allowed_drive_mask & (1 << drive)))
 			continue;
 		if (fdc_state[FDC(drive)].version == FDC_NONE)
--- diff/drivers/block/genhd.c	2004-02-18 08:54:08.000000000 +0000
+++ source/drivers/block/genhd.c	2004-02-23 13:56:40.000000000 +0000
@@ -262,8 +262,9 @@ static int show_partition(struct seq_fil
 
 	/* Don't show non-partitionable removeable devices or empty devices */
 	if (!get_capacity(sgp) ||
-	    (sgp->minors == 1 && (sgp->flags & GENHD_FL_REMOVABLE))
-		)
+			(sgp->minors == 1 && (sgp->flags & GENHD_FL_REMOVABLE)))
+		return 0;
+	if (sgp->flags & GENHD_FL_SUPPRESS_PARTITION_INFO)
 		return 0;
 
 	/* show the full disk and all non-0 size partitions of it */
--- diff/drivers/block/ll_rw_blk.c	2004-02-09 10:36:10.000000000 +0000
+++ source/drivers/block/ll_rw_blk.c	2004-02-23 13:56:40.000000000 +0000
@@ -27,6 +27,7 @@
 #include <linux/completion.h>
 #include <linux/slab.h>
 #include <linux/swap.h>
+#include <linux/writeback.h>
 
 static void blk_unplug_work(void *data);
 static void blk_unplug_timeout(unsigned long data);
@@ -521,10 +522,10 @@ init_tag_map(request_queue_t *q, struct 
 {
 	int bits, i;
 
-	if (depth > q->nr_requests * 2) {
-		depth = q->nr_requests * 2;
-		printk(KERN_ERR "%s: adjusted depth to %d\n",
-				__FUNCTION__, depth);
+	if (depth > q->nr_requests / 2) {
+		q->nr_requests = depth * 2;
+		printk(KERN_INFO "%s: large TCQ depth: adjusted nr_requests "
+				 "to %lu\n", __FUNCTION__, q->nr_requests);
 	}
 
 	tags->tag_index = kmalloc(depth * sizeof(struct request *), GFP_ATOMIC);
@@ -1334,6 +1335,8 @@ static elevator_t *chosen_elevator =
 	&iosched_as;
 #elif defined(CONFIG_IOSCHED_DEADLINE)
 	&iosched_deadline;
+#elif defined(CONFIG_IOSCHED_CFQ)
+	&iosched_cfq;
 #elif defined(CONFIG_IOSCHED_NOOP)
 	&elevator_noop;
 #else
@@ -1352,6 +1355,10 @@ static int __init elevator_setup(char *s
 	if (!strcmp(str, "as"))
 		chosen_elevator = &iosched_as;
 #endif
+#ifdef CONFIG_IOSCHED_CFQ
+	if (!strcmp(str, "cfq"))
+		chosen_elevator = &iosched_cfq;
+#endif
 #ifdef CONFIG_IOSCHED_NOOP
 	if (!strcmp(str, "noop"))
 		chosen_elevator = &elevator_noop;
@@ -1884,18 +1891,22 @@ EXPORT_SYMBOL(blk_put_request);
  * Waits for up to @timeout jiffies for a queue (any queue) to exit congestion.
  * If no queues are congested then just wait for the next request to be
  * returned.
+ *
+ * Returns the number of jiffies remaining, this is zero, unless we returned
+ * before @timeout expired.
  */
-void blk_congestion_wait(int rw, long timeout)
+long blk_congestion_wait(int rw, long timeout)
 {
+	long ret;
 	DEFINE_WAIT(wait);
 	wait_queue_head_t *wqh = &congestion_wqh[rw];
 
 	blk_run_queues();
 	prepare_to_wait(wqh, &wait, TASK_UNINTERRUPTIBLE);
-	io_schedule_timeout(timeout);
+	ret = io_schedule_timeout(timeout);
 	finish_wait(wqh, &wait);
+	return ret;
 }
-
 EXPORT_SYMBOL(blk_congestion_wait);
 
 /*
@@ -2305,6 +2316,15 @@ int submit_bio(int rw, struct bio *bio)
 		mod_page_state(pgpgout, count);
 	else
 		mod_page_state(pgpgin, count);
+
+	if (unlikely(block_dump)) {
+		char b[BDEVNAME_SIZE];
+		printk("%s(%d): %s block %Lu on %s\n",
+			current->comm, current->pid,
+			(rw & WRITE) ? "WRITE" : "READ",
+			(unsigned long long)bio->bi_sector, bdevname(bio->bi_bdev,b));
+	}
+
 	generic_make_request(bio);
 	return 1;
 }
@@ -2592,10 +2612,22 @@ void end_that_request_last(struct reques
 		unsigned long duration = jiffies - req->start_time;
 		switch (rq_data_dir(req)) {
 		    case WRITE:
+			/*
+			 * schedule the writeout of pending dirty data when the disk is idle.
+			 * (Writeback is not postponed by writes, only by reads.)
+			 */
+			if (unlikely(laptop_mode))
+				disk_is_spun_up(0);
 			disk_stat_inc(disk, writes);
 			disk_stat_add(disk, write_ticks, duration);
 			break;
 		    case READ:
+			/*
+			 * schedule the writeout of pending dirty data when the disk is idle.
+			 * (postpone writeback until system is quiescent again.)
+			 */
+			if (unlikely(laptop_mode))
+				disk_is_spun_up(1);
 			disk_stat_inc(disk, reads);
 			disk_stat_add(disk, read_ticks, duration);
 			break;
--- diff/drivers/block/loop.c	2004-02-09 10:36:10.000000000 +0000
+++ source/drivers/block/loop.c	2004-02-23 13:56:40.000000000 +0000
@@ -76,24 +76,34 @@ static struct gendisk **disks;
 /*
  * Transfer functions
  */
-static int transfer_none(struct loop_device *lo, int cmd, char *raw_buf,
-			 char *loop_buf, int size, sector_t real_block)
+static int transfer_none(struct loop_device *lo, int cmd,
+			 struct page *raw_page, unsigned raw_off,
+			 struct page *loop_page, unsigned loop_off,
+			 int size, sector_t real_block)
 {
-	if (raw_buf != loop_buf) {
-		if (cmd == READ)
-			memcpy(loop_buf, raw_buf, size);
-		else
-			memcpy(raw_buf, loop_buf, size);
-	}
+	char *raw_buf = kmap_atomic(raw_page, KM_USER0) + raw_off;
+	char *loop_buf = kmap_atomic(loop_page, KM_USER1) + loop_off;
+
+	if (cmd == READ)
+		memcpy(loop_buf, raw_buf, size);
+	else
+		memcpy(raw_buf, loop_buf, size);
 
+	kunmap_atomic(raw_buf, KM_USER0);
+	kunmap_atomic(loop_buf, KM_USER1);
+	cond_resched();
 	return 0;
 }
 
-static int transfer_xor(struct loop_device *lo, int cmd, char *raw_buf,
-			char *loop_buf, int size, sector_t real_block)
+static int transfer_xor(struct loop_device *lo, int cmd,
+			struct page *raw_page, unsigned raw_off,
+			struct page *loop_page, unsigned loop_off,
+			int size, sector_t real_block)
 {
-	char	*in, *out, *key;
-	int	i, keysize;
+	char *raw_buf = kmap_atomic(raw_page, KM_USER0) + raw_off;
+	char *loop_buf = kmap_atomic(loop_page, KM_USER1) + loop_off;
+	char *in, *out, *key;
+	int i, keysize;
 
 	if (cmd == READ) {
 		in = raw_buf;
@@ -107,6 +117,10 @@ static int transfer_xor(struct loop_devi
 	keysize = lo->lo_encrypt_key_size;
 	for (i = 0; i < size; i++)
 		*out++ = *in++ ^ key[(i & 511) % keysize];
+
+	kunmap_atomic(raw_buf, KM_USER0);
+	kunmap_atomic(loop_buf, KM_USER1);
+	cond_resched();
 	return 0;
 }
 
@@ -162,13 +176,15 @@ figure_loop_size(struct loop_device *lo)
 }
 
 static inline int
-lo_do_transfer(struct loop_device *lo, int cmd, char *rbuf,
-	       char *lbuf, int size, sector_t rblock)
+lo_do_transfer(struct loop_device *lo, int cmd,
+	       struct page *rpage, unsigned roffs,
+	       struct page *lpage, unsigned loffs,
+	       int size, sector_t rblock)
 {
 	if (!lo->transfer)
 		return 0;
 
-	return lo->transfer(lo, cmd, rbuf, lbuf, size, rblock);
+	return lo->transfer(lo, cmd, rpage, roffs, lpage, loffs, size, rblock);
 }
 
 static int
@@ -178,16 +194,15 @@ do_lo_send(struct loop_device *lo, struc
 	struct address_space *mapping = file->f_mapping;
 	struct address_space_operations *aops = mapping->a_ops;
 	struct page *page;
-	char *kaddr, *data;
 	pgoff_t index;
-	unsigned size, offset;
+	unsigned size, offset, bv_offs;
 	int len;
 	int ret = 0;
 
 	down(&mapping->host->i_sem);
 	index = pos >> PAGE_CACHE_SHIFT;
 	offset = pos & ((pgoff_t)PAGE_CACHE_SIZE - 1);
-	data = kmap(bvec->bv_page) + bvec->bv_offset;
+	bv_offs = bvec->bv_offset;
 	len = bvec->bv_len;
 	while (len > 0) {
 		sector_t IV;
@@ -204,25 +219,28 @@ do_lo_send(struct loop_device *lo, struc
 			goto fail;
 		if (aops->prepare_write(file, page, offset, offset+size))
 			goto unlock;
-		kaddr = kmap(page);
-		transfer_result = lo_do_transfer(lo, WRITE, kaddr + offset,
-						 data, size, IV);
+		transfer_result = lo_do_transfer(lo, WRITE, page, offset,
+						 bvec->bv_page, bv_offs,
+						 size, IV);
 		if (transfer_result) {
+			char *kaddr;
+
 			/*
 			 * The transfer failed, but we still write the data to
 			 * keep prepare/commit calls balanced.
 			 */
 			printk(KERN_ERR "loop: transfer error block %llu\n",
 			       (unsigned long long)index);
+			kaddr = kmap_atomic(page, KM_USER0);
 			memset(kaddr + offset, 0, size);
+			kunmap_atomic(kaddr, KM_USER0);
 		}
 		flush_dcache_page(page);
-		kunmap(page);
 		if (aops->commit_write(file, page, offset, offset+size))
 			goto unlock;
 		if (transfer_result)
 			goto unlock;
-		data += size;
+		bv_offs += size;
 		len -= size;
 		offset = 0;
 		index++;
@@ -232,7 +250,6 @@ do_lo_send(struct loop_device *lo, struc
 	}
 	up(&mapping->host->i_sem);
 out:
-	kunmap(bvec->bv_page);
 	return ret;
 
 unlock:
@@ -247,12 +264,10 @@ fail:
 static int
 lo_send(struct loop_device *lo, struct bio *bio, int bsize, loff_t pos)
 {
-	unsigned vecnr;
-	int ret = 0;
-
-	for (vecnr = 0; vecnr < bio->bi_vcnt; vecnr++) {
-		struct bio_vec *bvec = &bio->bi_io_vec[vecnr];
+	struct bio_vec *bvec;
+	int i, ret = 0;
 
+	bio_for_each_segment(bvec, bio, i) {
 		ret = do_lo_send(lo, bvec, bsize, pos);
 		if (ret < 0)
 			break;
@@ -263,7 +278,8 @@ lo_send(struct loop_device *lo, struct b
 
 struct lo_read_data {
 	struct loop_device *lo;
-	char *data;
+	struct page *page;
+	unsigned offset;
 	int bsize;
 };
 
@@ -271,7 +287,6 @@ static int
 lo_read_actor(read_descriptor_t *desc, struct page *page,
 	      unsigned long offset, unsigned long size)
 {
-	char *kaddr;
 	unsigned long count = desc->count;
 	struct lo_read_data *p = (struct lo_read_data*)desc->buf;
 	struct loop_device *lo = p->lo;
@@ -282,18 +297,16 @@ lo_read_actor(read_descriptor_t *desc, s
 	if (size > count)
 		size = count;
 
-	kaddr = kmap(page);
-	if (lo_do_transfer(lo, READ, kaddr + offset, p->data, size, IV)) {
+	if (lo_do_transfer(lo, READ, page, offset, p->page, p->offset, size, IV)) {
 		size = 0;
 		printk(KERN_ERR "loop: transfer error block %ld\n",
 		       page->index);
 		desc->error = -EINVAL;
 	}
-	kunmap(page);
 	
 	desc->count = count - size;
 	desc->written += size;
-	p->data += size;
+	p->offset += size;
 	return size;
 }
 
@@ -306,24 +319,22 @@ do_lo_receive(struct loop_device *lo,
 	int retval;
 
 	cookie.lo = lo;
-	cookie.data = kmap(bvec->bv_page) + bvec->bv_offset;
+	cookie.page = bvec->bv_page;
+	cookie.offset = bvec->bv_offset;
 	cookie.bsize = bsize;
 	file = lo->lo_backing_file;
 	retval = file->f_op->sendfile(file, &pos, bvec->bv_len,
 			lo_read_actor, &cookie);
-	kunmap(bvec->bv_page);
 	return (retval < 0)? retval: 0;
 }
 
 static int
 lo_receive(struct loop_device *lo, struct bio *bio, int bsize, loff_t pos)
 {
-	unsigned vecnr;
-	int ret = 0;
-
-	for (vecnr = 0; vecnr < bio->bi_vcnt; vecnr++) {
-		struct bio_vec *bvec = &bio->bi_io_vec[vecnr];
+	struct bio_vec *bvec;
+	int i, ret = 0;
 
+	bio_for_each_segment(bvec, bio, i) {
 		ret = do_lo_receive(lo, bvec, bsize, pos);
 		if (ret < 0)
 			break;
@@ -345,23 +356,6 @@ static int do_bio_filebacked(struct loop
 	return ret;
 }
 
-static int loop_end_io_transfer(struct bio *, unsigned int, int);
-
-static void loop_put_buffer(struct bio *bio)
-{
-	/*
-	 * check bi_end_io, may just be a remapped bio
-	 */
-	if (bio && bio->bi_end_io == loop_end_io_transfer) {
-		int i;
-
-		for (i = 0; i < bio->bi_vcnt; i++)
-			__free_page(bio->bi_io_vec[i].bv_page);
-
-		bio_put(bio);
-	}
-}
-
 /*
  * Add bio to back of pending list
  */
@@ -399,129 +393,8 @@ static struct bio *loop_get_bio(struct l
 	return bio;
 }
 
-/*
- * if this was a WRITE lo->transfer stuff has already been done. for READs,
- * queue it for the loop thread and let it do the transfer out of
- * bi_end_io context (we don't want to do decrypt of a page with irqs
- * disabled)
- */
-static int loop_end_io_transfer(struct bio *bio, unsigned int bytes_done, int err)
-{
-	struct bio *rbh = bio->bi_private;
-	struct loop_device *lo = rbh->bi_bdev->bd_disk->private_data;
-
-	if (bio->bi_size)
-		return 1;
-
-	if (err || bio_rw(bio) == WRITE) {
-		bio_endio(rbh, rbh->bi_size, err);
-		if (atomic_dec_and_test(&lo->lo_pending))
-			up(&lo->lo_bh_mutex);
-		loop_put_buffer(bio);
-	} else
-		loop_add_bio(lo, bio);
-
-	return 0;
-}
-
-static struct bio *loop_copy_bio(struct bio *rbh)
-{
-	struct bio *bio;
-	struct bio_vec *bv;
-	int i;
-
-	bio = bio_alloc(__GFP_NOWARN, rbh->bi_vcnt);
-	if (!bio)
-		return NULL;
-
-	/*
-	 * iterate iovec list and alloc pages
-	 */
-	__bio_for_each_segment(bv, rbh, i, 0) {
-		struct bio_vec *bbv = &bio->bi_io_vec[i];
-
-		bbv->bv_page = alloc_page(__GFP_NOWARN|__GFP_HIGHMEM);
-		if (bbv->bv_page == NULL)
-			goto oom;
-
-		bbv->bv_len = bv->bv_len;
-		bbv->bv_offset = bv->bv_offset;
-	}
-
-	bio->bi_vcnt = rbh->bi_vcnt;
-	bio->bi_size = rbh->bi_size;
-
-	return bio;
-
-oom:
-	while (--i >= 0)
-		__free_page(bio->bi_io_vec[i].bv_page);
-
-	bio_put(bio);
-	return NULL;
-}
-
-static struct bio *loop_get_buffer(struct loop_device *lo, struct bio *rbh)
-{
-	struct bio *bio;
-
-	/*
-	 * When called on the page reclaim -> writepage path, this code can
-	 * trivially consume all memory.  So we drop PF_MEMALLOC to avoid
-	 * stealing all the page reserves and throttle to the writeout rate.
-	 * pdflush will have been woken by page reclaim.  Let it do its work.
-	 */
-	do {
-		int flags = current->flags;
-
-		current->flags &= ~PF_MEMALLOC;
-		bio = loop_copy_bio(rbh);
-		if (flags & PF_MEMALLOC)
-			current->flags |= PF_MEMALLOC;
-
-		if (bio == NULL)
-			blk_congestion_wait(WRITE, HZ/10);
-	} while (bio == NULL);
-
-	bio->bi_end_io = loop_end_io_transfer;
-	bio->bi_private = rbh;
-	bio->bi_sector = rbh->bi_sector + (lo->lo_offset >> 9);
-	bio->bi_rw = rbh->bi_rw;
-	bio->bi_bdev = lo->lo_device;
-
-	return bio;
-}
-
-static int loop_transfer_bio(struct loop_device *lo,
-			     struct bio *to_bio, struct bio *from_bio)
-{
-	sector_t IV;
-	struct bio_vec *from_bvec, *to_bvec;
-	char *vto, *vfrom;
-	int ret = 0, i;
-
-	IV = from_bio->bi_sector + (lo->lo_offset >> 9);
-
-	__bio_for_each_segment(from_bvec, from_bio, i, 0) {
-		to_bvec = &to_bio->bi_io_vec[i];
-
-		kmap(from_bvec->bv_page);
-		kmap(to_bvec->bv_page);
-		vfrom = page_address(from_bvec->bv_page) + from_bvec->bv_offset;
-		vto = page_address(to_bvec->bv_page) + to_bvec->bv_offset;
-		ret |= lo_do_transfer(lo, bio_data_dir(to_bio), vto, vfrom,
-					from_bvec->bv_len, IV);
-		kunmap(from_bvec->bv_page);
-		kunmap(to_bvec->bv_page);
-		IV += from_bvec->bv_len >> 9;
-	}
-
-	return ret;
-}
-		
 static int loop_make_request(request_queue_t *q, struct bio *old_bio)
 {
-	struct bio *new_bio = NULL;
 	struct loop_device *lo = q->queuedata;
 	int rw = bio_rw(old_bio);
 
@@ -543,31 +416,11 @@ static int loop_make_request(request_que
 		printk(KERN_ERR "loop: unknown command (%x)\n", rw);
 		goto err;
 	}
-
-	/*
-	 * file backed, queue for loop_thread to handle
-	 */
-	if (lo->lo_flags & LO_FLAGS_DO_BMAP) {
-		loop_add_bio(lo, old_bio);
-		return 0;
-	}
-
-	/*
-	 * piggy old buffer on original, and submit for I/O
-	 */
-	new_bio = loop_get_buffer(lo, old_bio);
-	if (rw == WRITE) {
-		if (loop_transfer_bio(lo, new_bio, old_bio))
-			goto err;
-	}
-
-	generic_make_request(new_bio);
+	loop_add_bio(lo, old_bio);
 	return 0;
-
 err:
 	if (atomic_dec_and_test(&lo->lo_pending))
 		up(&lo->lo_bh_mutex);
-	loop_put_buffer(new_bio);
 out:
 	bio_io_error(old_bio, old_bio->bi_size);
 	return 0;
@@ -580,20 +433,8 @@ static inline void loop_handle_bio(struc
 {
 	int ret;
 
-	/*
-	 * For block backed loop, we know this is a READ
-	 */
-	if (lo->lo_flags & LO_FLAGS_DO_BMAP) {
-		ret = do_bio_filebacked(lo, bio);
-		bio_endio(bio, bio->bi_size, ret);
-	} else {
-		struct bio *rbh = bio->bi_private;
-
-		ret = loop_transfer_bio(lo, bio, rbh);
-
-		bio_endio(rbh, rbh->bi_size, ret);
-		loop_put_buffer(bio);
-	}
+	ret = do_bio_filebacked(lo, bio);
+	bio_endio(bio, bio->bi_size, ret);
 }
 
 /*
@@ -684,31 +525,23 @@ static int loop_set_fd(struct loop_devic
 		lo_flags |= LO_FLAGS_READ_ONLY;
 
 	error = -EINVAL;
-	if (S_ISBLK(inode->i_mode)) {
-		lo_device = I_BDEV(inode);
-		if (lo_device == bdev) {
-			error = -EBUSY;
-			goto out_putf;
-		}
-		lo_blocksize = block_size(lo_device);
-		if (bdev_read_only(lo_device))
-			lo_flags |= LO_FLAGS_READ_ONLY;
-	} else if (S_ISREG(inode->i_mode)) {
+	if (S_ISREG(inode->i_mode) || S_ISBLK(inode->i_mode)) {
 		struct address_space_operations *aops = mapping->a_ops;
 		/*
 		 * If we can't read - sorry. If we only can't write - well,
 		 * it's going to be read-only.
 		 */
-		if (!inode->i_fop->sendfile)
+		if (!lo_file->f_op->sendfile)
 			goto out_putf;
 
 		if (!aops->prepare_write || !aops->commit_write)
 			lo_flags |= LO_FLAGS_READ_ONLY;
 
 		lo_blocksize = inode->i_blksize;
-		lo_flags |= LO_FLAGS_DO_BMAP;
-	} else
+		error = 0;
+	} else {
 		goto out_putf;
+	}
 
 	if (!(lo_file->f_mode & FMODE_WRITE))
 		lo_flags |= LO_FLAGS_READ_ONLY;
@@ -738,21 +571,6 @@ static int loop_set_fd(struct loop_devic
 	blk_queue_make_request(lo->lo_queue, loop_make_request);
 	lo->lo_queue->queuedata = lo;
 
-	/*
-	 * we remap to a block device, make sure we correctly stack limits
-	 */
-	if (S_ISBLK(inode->i_mode)) {
-		request_queue_t *q = bdev_get_queue(lo_device);
-
-		blk_queue_max_sectors(lo->lo_queue, q->max_sectors);
-		blk_queue_max_phys_segments(lo->lo_queue,q->max_phys_segments);
-		blk_queue_max_hw_segments(lo->lo_queue, q->max_hw_segments);
-		blk_queue_hardsect_size(lo->lo_queue, queue_hardsect_size(q));
-		blk_queue_max_segment_size(lo->lo_queue, q->max_segment_size);
-		blk_queue_segment_boundary(lo->lo_queue, q->seg_boundary_mask);
-		blk_queue_merge_bvec(lo->lo_queue, q->merge_bvec_fn);
-	}
-
 	set_blocksize(bdev, lo_blocksize);
 
 	kernel_thread(loop_thread, lo, CLONE_KERNEL);
@@ -1196,7 +1014,6 @@ int __init loop_init(void)
 		lo->lo_queue = blk_alloc_queue(GFP_KERNEL);
 		if (!lo->lo_queue)
 			goto out_mem4;
-		disks[i]->queue = lo->lo_queue;
 		init_MUTEX(&lo->lo_ctl_mutex);
 		init_MUTEX_LOCKED(&lo->lo_sem);
 		init_MUTEX_LOCKED(&lo->lo_bh_mutex);
@@ -1209,14 +1026,18 @@ int __init loop_init(void)
 		sprintf(disk->devfs_name, "loop/%d", i);
 		disk->private_data = lo;
 		disk->queue = lo->lo_queue;
-		add_disk(disk);
 	}
+
+	/* We cannot fail after we call this, so another loop!*/
+	for (i = 0; i < max_loop; i++)
+		add_disk(disks[i]);
 	printk(KERN_INFO "loop: loaded (max %d devices)\n", max_loop);
 	return 0;
 
 out_mem4:
 	while (i--)
 		blk_put_queue(loop_dev[i].lo_queue);
+	devfs_remove("loop");
 	i = max_loop;
 out_mem3:
 	while (i--)
--- diff/drivers/block/nbd.c	2003-08-26 10:00:52.000000000 +0100
+++ source/drivers/block/nbd.c	2004-02-23 13:56:40.000000000 +0000
@@ -36,7 +36,7 @@
  * 03-06-24 Remove unneeded blksize_bits field from nbd_device struct.
  *   <ldl@aros.net>
  * 03-06-24 Cleanup PARANOIA usage & code. <ldl@aros.net>
- *
+ * 04-02-19 Remove PARANOIA, plus various cleanups (Paul Clements)
  * possible FIXME: make set_sock / set_blksize / set_size / do_it one syscall
  * why not: would need verify_area and friends, would share yet another 
  *          structure with userland
@@ -61,12 +61,9 @@
 #include <asm/uaccess.h>
 #include <asm/types.h>
 
-/* Define PARANOIA in linux/nbd.h to turn on extra sanity checking */
 #include <linux/nbd.h>
 
-#ifdef PARANOIA
 #define LO_MAGIC 0x68797548
-#endif
 
 #ifdef NDEBUG
 #define dprintk(flags, fmt...)
@@ -97,11 +94,6 @@ static struct nbd_device nbd_dev[MAX_NBD
  */
 static spinlock_t nbd_lock = SPIN_LOCK_UNLOCKED;
 
-#ifdef PARANOIA
-static int requests_in;
-static int requests_out;
-#endif
-
 #ifndef NDEBUG
 static const char *ioctl_cmd_to_ascii(int cmd)
 {
@@ -153,9 +145,6 @@ static void nbd_end_request(struct reque
 	}
 	spin_unlock(&lo->queue_lock);
 
-#ifdef PARANOIA
-	requests_out++;
-#endif
 	spin_lock_irqsave(q->queue_lock, flags);
 	if (!end_that_request_first(req, uptodate, req->nr_sectors)) {
 		end_that_request_last(req);
@@ -217,10 +206,8 @@ static int sock_xmit(struct socket *sock
 		}
 
 		if (result <= 0) {
-#ifdef PARANOIA
-			printk(KERN_ERR "nbd: %s - sock=%p at buf=%p, size=%d returned %d.\n",
-			       send? "send": "receive", sock, buf, size, result);
-#endif
+			if (result == 0)
+				result = -EPIPE; /* short read */
 			break;
 		}
 		size -= result;
@@ -309,7 +296,7 @@ void nbd_send_req(struct nbd_device *lo,
 	up(&lo->tx_lock);
 	return;
 
-      error_out:
+error_out:
 	up(&lo->tx_lock);
 	req->errors++;
 }
@@ -358,23 +345,22 @@ struct request *nbd_read_stat(struct nbd
 	if (result <= 0) {
 		printk(KERN_ERR "%s: Receive control failed (result %d)\n",
 				lo->disk->disk_name, result);
-		lo->harderror = result;
-		return NULL;
+		goto harderror;
 	}
 	req = nbd_find_request(lo, reply.handle);
 	if (req == NULL) {
 		printk(KERN_ERR "%s: Unexpected reply (%p)\n",
 				lo->disk->disk_name, reply.handle);
-		lo->harderror = result;
-		return NULL;
+		result = -EBADR;
+		goto harderror;
 	}
 
 	if (ntohl(reply.magic) != NBD_REPLY_MAGIC) {
 		printk(KERN_ERR "%s: Wrong magic (0x%lx)\n",
 				lo->disk->disk_name,
 				(unsigned long)ntohl(reply.magic));
-		lo->harderror = result;
-		return NULL;
+		result = -EPROTO;
+		goto harderror;
 	}
 	if (ntohl(reply.error)) {
 		printk(KERN_ERR "%s: Other side returned error (%d)\n",
@@ -396,8 +382,7 @@ struct request *nbd_read_stat(struct nbd
 					printk(KERN_ERR "%s: Receive data failed (result %d)\n",
 							lo->disk->disk_name,
 							result);
-					lo->harderror = result;
-					return NULL;
+					goto harderror;
 				}
 				dprintk(DBG_RX, "%s: request %p: got %d bytes data\n",
 					lo->disk->disk_name, req, bvec->bv_len);
@@ -405,19 +390,19 @@ struct request *nbd_read_stat(struct nbd
 		}
 	}
 	return req;
+harderror:
+	lo->harderror = result;
+	return NULL;
 }
 
 void nbd_do_it(struct nbd_device *lo)
 {
 	struct request *req;
 
-#ifdef PARANOIA
 	BUG_ON(lo->magic != LO_MAGIC);
-#endif
+
 	while ((req = nbd_read_stat(lo)) != NULL)
 		nbd_end_request(req);
-	printk(KERN_NOTICE "%s: req should never be null\n",
-			lo->disk->disk_name);
 	return;
 }
 
@@ -425,9 +410,7 @@ void nbd_clear_que(struct nbd_device *lo
 {
 	struct request *req;
 
-#ifdef PARANOIA
 	BUG_ON(lo->magic != LO_MAGIC);
-#endif
 
 	do {
 		req = NULL;
@@ -466,9 +449,9 @@ static void do_nbd_request(request_queue
 			goto error_out;
 
 		lo = req->rq_disk->private_data;
-#ifdef PARANOIA
+
 		BUG_ON(lo->magic != LO_MAGIC);
-#endif
+
 		if (!lo->file) {
 			printk(KERN_ERR "%s: Request when not-ready\n",
 					lo->disk->disk_name);
@@ -483,9 +466,6 @@ static void do_nbd_request(request_queue
 				goto error_out;
 			}
 		}
-#ifdef PARANOIA
-		requests_in++;
-#endif
 
 		req->errors = 0;
 		spin_unlock_irq(q->queue_lock);
@@ -526,7 +506,7 @@ static void do_nbd_request(request_queue
 		spin_lock_irq(q->queue_lock);
 		continue;
 
-	      error_out:
+error_out:
 		req->errors++;
 		spin_unlock(q->queue_lock);
 		nbd_end_request(req);
@@ -544,9 +524,9 @@ static int nbd_ioctl(struct inode *inode
 
 	if (!capable(CAP_SYS_ADMIN))
 		return -EPERM;
-#ifdef PARANOIA
+
 	BUG_ON(lo->magic != LO_MAGIC);
-#endif
+
 	/* Anyone capable of this syscall can do *real bad* things */
 	dprintk(DBG_IOCTL, "%s: nbd_ioctl cmd=%s(0x%x) arg=%lu\n",
 			lo->disk->disk_name, ioctl_cmd_to_ascii(cmd), cmd, arg);
@@ -662,15 +642,10 @@ static int nbd_ioctl(struct inode *inode
 		nbd_clear_que(lo);
 		return 0;
 	case NBD_PRINT_DEBUG:
-#ifdef PARANOIA
-		printk(KERN_INFO "%s: next = %p, prev = %p. Global: in %d, out %d\n",
-			inode->i_bdev->bd_disk->disk_name, lo->queue_head.next,
-			lo->queue_head.prev, requests_in, requests_out);
-#else
-		printk(KERN_INFO "%s: next = %p, prev = %p\n",
+		printk(KERN_INFO "%s: next = %p, prev = %p, head = %p\n",
 			inode->i_bdev->bd_disk->disk_name,
-			lo->queue_head.next, lo->queue_head.prev);
-#endif
+			lo->queue_head.next, lo->queue_head.prev,
+			&lo->queue_head);
 		return 0;
 	}
 	return -EINVAL;
@@ -692,12 +667,10 @@ static int __init nbd_init(void)
 	int err = -ENOMEM;
 	int i;
 
-#ifdef PARANOIA
 	if (sizeof(struct nbd_request) != 28) {
-		printk(KERN_CRIT "nbd: Sizeof nbd_request needs to be 28 in order to work!\n" );
+		printk(KERN_CRIT "nbd: sizeof nbd_request needs to be 28 in order to work!\n" );
 		return -EIO;
 	}
-#endif
 
 	for (i = 0; i < MAX_NBD; i++) {
 		struct gendisk *disk = alloc_disk(1);
@@ -728,30 +701,28 @@ static int __init nbd_init(void)
 	for (i = 0; i < MAX_NBD; i++) {
 		struct gendisk *disk = nbd_dev[i].disk;
 		nbd_dev[i].file = NULL;
-#ifdef PARANOIA
 		nbd_dev[i].magic = LO_MAGIC;
-#endif
 		nbd_dev[i].flags = 0;
 		spin_lock_init(&nbd_dev[i].queue_lock);
 		INIT_LIST_HEAD(&nbd_dev[i].queue_head);
 		init_MUTEX(&nbd_dev[i].tx_lock);
 		nbd_dev[i].blksize = 1024;
-		nbd_dev[i].bytesize = ((u64)0x7ffffc00) << 10; /* 2TB */
+		nbd_dev[i].bytesize = 0x7ffffc00ULL << 10; /* 2TB */
 		disk->major = NBD_MAJOR;
 		disk->first_minor = i;
 		disk->fops = &nbd_fops;
 		disk->private_data = &nbd_dev[i];
+		disk->flags |= GENHD_FL_SUPPRESS_PARTITION_INFO;
 		sprintf(disk->disk_name, "nbd%d", i);
 		sprintf(disk->devfs_name, "nbd/%d", i);
-		set_capacity(disk, 0x3ffffe);
+		set_capacity(disk, 0x7ffffc00ULL << 1); /* 2 TB */
 		add_disk(disk);
 	}
 
 	return 0;
 out:
 	while (i--) {
-		if (nbd_dev[i].disk->queue)
-			blk_cleanup_queue(nbd_dev[i].disk->queue);
+		blk_cleanup_queue(nbd_dev[i].disk->queue);
 		put_disk(nbd_dev[i].disk);
 	}
 	return err;
@@ -763,9 +734,8 @@ static void __exit nbd_cleanup(void)
 	for (i = 0; i < MAX_NBD; i++) {
 		struct gendisk *disk = nbd_dev[i].disk;
 		if (disk) {
-			if (disk->queue)
-				blk_cleanup_queue(disk->queue);
 			del_gendisk(disk);
+			blk_cleanup_queue(disk->queue);
 			put_disk(disk);
 		}
 	}
--- diff/drivers/block/rd.c	2003-10-09 09:47:16.000000000 +0100
+++ source/drivers/block/rd.c	2004-02-23 13:56:40.000000000 +0000
@@ -1,15 +1,15 @@
 /*
  * ramdisk.c - Multiple RAM disk driver - gzip-loading version - v. 0.8 beta.
- * 
- * (C) Chad Page, Theodore Ts'o, et. al, 1995. 
+ *
+ * (C) Chad Page, Theodore Ts'o, et. al, 1995.
  *
  * This RAM disk is designed to have filesystems created on it and mounted
- * just like a regular floppy disk.  
- *  
+ * just like a regular floppy disk.
+ *
  * It also does something suggested by Linus: use the buffer cache as the
  * RAM disk data.  This makes it possible to dynamically allocate the RAM disk
- * buffer - with some consequences I have to deal with as I write this. 
- * 
+ * buffer - with some consequences I have to deal with as I write this.
+ *
  * This code is based on the original ramdisk.c, written mostly by
  * Theodore Ts'o (TYT) in 1991.  The code was largely rewritten by
  * Chad Page to use the buffer cache to store the RAM disk data in
@@ -33,7 +33,7 @@
  *
  *  Added initrd: Werner Almesberger & Hans Lermen, Feb '96
  *
- * 4/25/96 : Made RAM disk size a parameter (default is now 4 MB) 
+ * 4/25/96 : Made RAM disk size a parameter (default is now 4 MB)
  *		- Chad Page
  *
  * Add support for fs images split across >1 disk, Paul Gortmaker, Mar '98
@@ -60,7 +60,7 @@
 #include <asm/uaccess.h>
 
 /* The RAM disk size is now a parameter */
-#define NUM_RAMDISKS 16		/* This cannot be overridden (yet) */ 
+#define NUM_RAMDISKS 16		/* This cannot be overridden (yet) */
 
 /* Various static variables go here.  Most are used only in the RAM disk code.
  */
@@ -73,7 +73,7 @@ static struct request_queue *rd_queue[NU
  * Parameters for the boot-loading of the RAM disk.  These are set by
  * init/main.c (from arguments to the kernel command line) or from the
  * architecture-specific setup routine (from the stored boot sector
- * information). 
+ * information).
  */
 int rd_size = CONFIG_BLK_DEV_RAM_SIZE;		/* Size of the RAM disks */
 /*
@@ -94,7 +94,7 @@ int rd_blocksize = BLOCK_SIZE;			/* bloc
  *               2000 Transmeta Corp.
  * aops copied from ramfs.
  */
-static int ramdisk_readpage(struct file *file, struct page * page)
+static int ramdisk_readpage(struct file *file, struct page *page)
 {
 	if (!PageUptodate(page)) {
 		void *kaddr = kmap_atomic(page, KM_USER0);
@@ -108,7 +108,8 @@ static int ramdisk_readpage(struct file 
 	return 0;
 }
 
-static int ramdisk_prepare_write(struct file *file, struct page *page, unsigned offset, unsigned to)
+static int ramdisk_prepare_write(struct file *file, struct page *page,
+				unsigned offset, unsigned to)
 {
 	if (!PageUptodate(page)) {
 		void *kaddr = kmap_atomic(page, KM_USER0);
@@ -122,7 +123,8 @@ static int ramdisk_prepare_write(struct 
 	return 0;
 }
 
-static int ramdisk_commit_write(struct file *file, struct page *page, unsigned offset, unsigned to)
+static int ramdisk_commit_write(struct file *file, struct page *page,
+				unsigned offset, unsigned to)
 {
 	return 0;
 }
@@ -212,7 +214,7 @@ static int rd_blkdev_pagecache_IO(int rw
  * 19-JAN-1998  Richard Gooch <rgooch@atnf.csiro.au>  Added devfs support
  *
  */
-static int rd_make_request(request_queue_t * q, struct bio *bio)
+static int rd_make_request(request_queue_t *q, struct bio *bio)
 {
 	struct block_device *bdev = bio->bi_bdev;
 	struct address_space * mapping = bdev->bd_inode->i_mapping;
@@ -242,7 +244,8 @@ fail:
 	return 0;
 } 
 
-static int rd_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
+static int rd_ioctl(struct inode *inode, struct file *file,
+			unsigned int cmd, unsigned long arg)
 {
 	int error;
 	struct block_device *bdev = inode->i_bdev;
@@ -250,9 +253,11 @@ static int rd_ioctl(struct inode *inode,
 	if (cmd != BLKFLSBUF)
 		return -EINVAL;
 
-	/* special: we want to release the ramdisk memory,
-	   it's not like with the other blockdevices where
-	   this ioctl only flushes away the buffer cache. */
+	/*
+	 * special: we want to release the ramdisk memory, it's not like with
+	 * the other blockdevices where this ioctl only flushes away the buffer
+	 * cache
+	 */
 	error = -EBUSY;
 	down(&bdev->bd_sem);
 	if (bdev->bd_openers <= 2) {
@@ -268,7 +273,7 @@ static struct backing_dev_info rd_backin
 	.memory_backed	= 1,	/* Does not contribute to dirty memory */
 };
 
-static int rd_open(struct inode * inode, struct file * filp)
+static int rd_open(struct inode *inode, struct file *filp)
 {
 	unsigned unit = iminor(inode);
 
@@ -295,33 +300,37 @@ static struct block_device_operations rd
 	.ioctl =	rd_ioctl,
 };
 
-/* Before freeing the module, invalidate all of the protected buffers! */
-static void __exit rd_cleanup (void)
+/*
+ * Before freeing the module, invalidate all of the protected buffers!
+ */
+static void __exit rd_cleanup(void)
 {
 	int i;
 
-	for (i = 0 ; i < NUM_RAMDISKS; i++) {
+	for (i = 0; i < NUM_RAMDISKS; i++) {
 		struct block_device *bdev = rd_bdev[i];
 		rd_bdev[i] = NULL;
 		if (bdev) {
 			invalidate_bdev(bdev, 1);
-			blkdev_put(bdev, BDEV_FILE);
+			blkdev_put(bdev);
 		}
 		del_gendisk(rd_disks[i]);
 		put_disk(rd_disks[i]);
 	}
 	devfs_remove("rd");
-	unregister_blkdev(RAMDISK_MAJOR, "ramdisk" );
+	unregister_blkdev(RAMDISK_MAJOR, "ramdisk");
 }
 
-/* This is the registration and initialization section of the RAM disk driver */
-static int __init rd_init (void)
+/*
+ * This is the registration and initialization section of the RAM disk driver
+ */
+static int __init rd_init(void)
 {
 	int i;
 	int err = -ENOMEM;
 
 	if (rd_blocksize > PAGE_SIZE || rd_blocksize < 512 ||
-	    (rd_blocksize & (rd_blocksize-1))) {
+			(rd_blocksize & (rd_blocksize-1))) {
 		printk("RAMDISK: wrong blocksize %d, reverting to defaults\n",
 		       rd_blocksize);
 		rd_blocksize = BLOCK_SIZE;
@@ -354,6 +363,7 @@ static int __init rd_init (void)
 		disk->first_minor = i;
 		disk->fops = &rd_bd_op;
 		disk->queue = rd_queue[i];
+		disk->flags |= GENHD_FL_SUPPRESS_PARTITION_INFO;
 		sprintf(disk->disk_name, "ram%d", i);
 		sprintf(disk->devfs_name, "rd/%d", i);
 		set_capacity(disk, rd_size * 2);
@@ -362,8 +372,8 @@ static int __init rd_init (void)
 
 	/* rd_size is given in kB */
 	printk("RAMDISK driver initialized: "
-	       "%d RAM disks of %dK size %d blocksize\n",
-	       NUM_RAMDISKS, rd_size, rd_blocksize);
+		"%d RAM disks of %dK size %d blocksize\n",
+		NUM_RAMDISKS, rd_size, rd_blocksize);
 
 	return 0;
 out_queue:
--- diff/drivers/block/scsi_ioctl.c	2004-02-18 08:54:08.000000000 +0000
+++ source/drivers/block/scsi_ioctl.c	2004-02-23 13:56:40.000000000 +0000
@@ -312,7 +312,7 @@ static int sg_scsi_ioctl(request_queue_t
 		return -EFAULT;
 	if (in_len > PAGE_SIZE || out_len > PAGE_SIZE)
 		return -EINVAL;
-	if (get_user(opcode, sic->data))
+	if (get_user(opcode, (int *)sic->data))
 		return -EFAULT;
 
 	bytes = max(in_len, out_len);
--- diff/drivers/block/swim3.c	2004-02-18 08:54:08.000000000 +0000
+++ source/drivers/block/swim3.c	2004-02-23 13:56:40.000000000 +0000
@@ -319,7 +319,7 @@ static void start_request(struct floppy_
 #if 0
 		printk("do_fd_req: dev=%s cmd=%d sec=%ld nr_sec=%ld buf=%p\n",
 		       req->rq_disk->disk_name, req->cmd,
-		       req->sector, req->nr_sectors, req->buffer);
+		       (long)req->sector, req->nr_sectors, req->buffer);
 		printk("           rq_status=%d errors=%d current_nr_sectors=%ld\n",
 		       req->rq_status, req->errors, req->current_nr_sectors);
 #endif
@@ -346,8 +346,13 @@ static void start_request(struct floppy_
 			}
 		}
 
-		fs->req_cyl = req->sector / fs->secpercyl;
-		x = req->sector % fs->secpercyl;
+		/* Do not remove the cast. req->sector is now a sector_t and
+		 * can be 64 bits, but it will never go past 32 bits for this
+		 * driver anyway, so we can safely cast it down and not have
+		 * to do a 64/32 division
+		 */
+		fs->req_cyl = ((long)req->sector) / fs->secpercyl;
+		x = ((long)req->sector) % fs->secpercyl;
 		fs->head = x / fs->secpertrack;
 		fs->req_sector = x % fs->secpertrack + 1;
 		fd_req = req;
@@ -614,7 +619,7 @@ static void xfer_timeout(unsigned long d
 	fd_req->sector += s;
 	fd_req->current_nr_sectors -= s;
 	printk(KERN_ERR "swim3: timeout %sing sector %ld\n",
-	       (rq_data_dir(fd_req)==WRITE? "writ": "read"), fd_req->sector);
+	       (rq_data_dir(fd_req)==WRITE? "writ": "read"), (long)fd_req->sector);
 	end_request(fd_req, 0);
 	fs->state = idle;
 	start_request(fs);
@@ -730,7 +735,7 @@ static irqreturn_t swim3_interrupt(int i
 			} else {
 				printk("swim3: error %sing block %ld (err=%x)\n",
 				       rq_data_dir(fd_req) == WRITE? "writ": "read",
-				       fd_req->sector, err);
+				       (long)fd_req->sector, err);
 				end_request(fd_req, 0);
 				fs->state = idle;
 			}
--- diff/drivers/char/Kconfig	2004-02-18 08:54:09.000000000 +0000
+++ source/drivers/char/Kconfig	2004-02-23 13:56:41.000000000 +0000
@@ -445,7 +445,8 @@ config A2232
 source "drivers/serial/Kconfig"
 
 config UNIX98_PTYS
-	bool "Unix98 PTY support"
+	bool "Unix98 PTY support" if EMBEDDED
+	default y
 	---help---
 	  A pseudo terminal (PTY) is a software device consisting of two
 	  halves: a master and a slave. The slave device behaves identical to
@@ -463,28 +464,38 @@ config UNIX98_PTYS
 	  terminal slave can be accessed as /dev/pts/<number>. What was
 	  traditionally /dev/ttyp2 will then be /dev/pts/2, for example.
 
-	  The entries in /dev/pts/ are created on the fly by a virtual
-	  file system; therefore, if you say Y here you should say Y to
-	  "/dev/pts file system for Unix98 PTYs" as well.
-
-	  If you want to say Y here, you need to have the C library glibc 2.1
-	  or later (equal to libc-6.1, check with "ls -l /lib/libc.so.*").
-	  Read the instructions in <file:Documentation/Changes> pertaining to
-	  pseudo terminals. It's safe to say N.
-
-config UNIX98_PTY_COUNT
-	int "Maximum number of Unix98 PTYs in use (0-2048)"
-	depends on UNIX98_PTYS
+	  All modern Linux systems use the Unix98 ptys.  Say Y unless
+	  you're on an embedded system and want to conserve memory.
+
+config LEGACY_PTYS
+	bool "Legacy (BSD) PTY support"
+	default y
+	---help---
+	  A pseudo terminal (PTY) is a software device consisting of two
+	  halves: a master and a slave. The slave device behaves identical to
+	  a physical terminal; the master device is used by a process to
+	  read data from and write data to the slave, thereby emulating a
+	  terminal. Typical programs for the master side are telnet servers
+	  and xterms.
+
+	  Linux has traditionally used the BSD-like names /dev/ptyxx
+	  for masters and /dev/ttyxx for slaves of pseudo
+	  terminals. This scheme has a number of problems, including
+	  security.  This option enables these legacy devices; on most
+	  systems, it is safe to say N.
+
+
+config LEGACY_PTY_COUNT
+	int "Maximum number of legacy PTY in use"
+	depends on LEGACY_PTYS
 	default "256"
-	help
-	  The maximum number of Unix98 PTYs that can be used at any one time.
-	  The default is 256, and should be enough for desktop systems. Server
-	  machines which support incoming telnet/rlogin/ssh connections and/or
-	  serve several X terminals may want to increase this: every incoming
-	  connection and every xterm uses up one PTY.
+	---help---
+	  The maximum number of legacy PTYs that can be used at any one time.
+	  The default is 256, and should be more than enough.  Embedded
+	  systems may want to reduce this to save memory.
 
-	  When not in use, each additional set of 256 PTYs occupy
-	  approximately 8 KB of kernel memory on 32-bit architectures.
+	  When not in use, each legacy PTY occupies 12 bytes on 32-bit
+	  architectures and 24 bytes on 64-bit architectures.
 
 config PRINTER
 	tristate "Parallel printer support"
@@ -588,30 +599,6 @@ config PC9800_OLDLP_CONSOLE
 	bool "Support for console on line printer"
 	depends on PC9800_OLDLP
 
-
-menu "Mice"
-
-config BUSMOUSE
-	tristate "Bus Mouse Support"
-	---help---
-	  Say Y here if your machine has a bus mouse as opposed to a serial
-	  mouse. Most people have a regular serial MouseSystem or
-	  Microsoft mouse (made by Logitech) that plugs into a COM port
-	  (rectangular with 9 or 25 pins). These people say N here. 
-
-	  If you have a laptop, you either have to check the documentation or
-	  experiment a bit to find out whether the trackball is a serial mouse
-	  or not; it's best to say Y here for you.
-
-	  This is the generic bus mouse driver code. If you have a bus mouse,
-	  you will have to say Y here and also to the specific driver for your
-	  mouse below.
-
-	  To compile this driver as a module, choose M here: the
-	  module will be called busmouse.
-
-endmenu
-
 config QIC02_TAPE
 	tristate "QIC-02 tape support"
 	help
@@ -754,7 +741,7 @@ config NVRAM
 
 config RTC
 	tristate "Enhanced Real Time Clock Support"
-	depends on !PPC32 && !PARISC && !IA64 && !X86_PC9800
+	depends on !PPC32 && !PARISC && !IA64 && !X86_PC9800 && !M68K
 	---help---
 	  If you say Y here and create a character special file /dev/rtc with
 	  major number 10 and minor number 135 using mknod ("man mknod"), you
@@ -794,8 +781,7 @@ config GEN_RTC
 	  precision in some cases.
 
 	  To compile this driver as a module, choose M here: the
-	  module will be called genrtc. To load the module automatically
-	  add 'alias char-major-10-135 genrtc' to your /etc/modules.conf
+	  module will be called genrtc.
 
 config GEN_RTC_X
 	bool "Extended RTC operation"
--- diff/drivers/char/Makefile	2004-02-18 08:54:09.000000000 +0000
+++ source/drivers/char/Makefile	2004-02-23 13:56:41.000000000 +0000
@@ -49,7 +49,6 @@ obj-$(CONFIG_PRINTER) += lp.o
 obj-$(CONFIG_TIPAR) += tipar.o
 obj-$(CONFIG_PC9800_OLDLP) += lp_old98.o
 
-obj-$(CONFIG_BUSMOUSE) += busmouse.o
 obj-$(CONFIG_DTLK) += dtlk.o
 obj-$(CONFIG_R3964) += n_r3964.o
 obj-$(CONFIG_APPLICOM) += applicom.o
--- diff/drivers/char/agp/Kconfig	2004-02-18 08:54:09.000000000 +0000
+++ source/drivers/char/agp/Kconfig	2004-02-23 13:56:40.000000000 +0000
@@ -1,5 +1,5 @@
 config AGP
-	tristate "/dev/agpgart (AGP Support)" if !GART_IOMMU
+	tristate "/dev/agpgart (AGP Support)" if !GART_IOMMU && !M68K
 	default y if GART_IOMMU
 	---help---
 	  AGP (Accelerated Graphics Port) is a bus system mainly used to
@@ -77,7 +77,7 @@ config AGP_AMD64
 
 config AGP_INTEL
 	tristate "Intel 440LX/BX/GX, I8xx and E7x05 chipset support"
-	depends on AGP && X86 && !X86_64
+	depends on AGP && X86
 	help
 	  This option gives you AGP support for the GLX component of XFree86 4.x
 	  on Intel 440LX/BX/GX, 815, 820, 830, 840, 845, 850, 860, 875,
@@ -151,3 +151,13 @@ config AGP_UNINORTH
 	  This option gives you AGP support for Apple machines with a
 	  UniNorth bridge.
 
+config AGP_EFFICEON
+	tristate "Transmeta Efficeon support"
+	depends on AGP && X86 && !X86_64
+	help
+	  This option fives you AGP support for the Transmeta Efficeon
+	  series processors with integrated northbridges.
+
+	  You should say Y here if you use XFree86 3.3.6 or 4.x and want to
+	  use GLX or DRI.  If unsure, say Y.
+
--- diff/drivers/char/agp/Makefile	2003-09-17 12:28:04.000000000 +0100
+++ source/drivers/char/agp/Makefile	2004-02-23 13:56:40.000000000 +0000
@@ -6,6 +6,7 @@ obj-$(CONFIG_AGP_ATI)		+= ati-agp.o
 obj-$(CONFIG_AGP_AMD)		+= amd-k7-agp.o
 obj-$(CONFIG_AGP_AMD64)		+= amd64-agp.o
 obj-$(CONFIG_AGP_ALPHA_CORE)	+= alpha-agp.o
+obj-$(CONFIG_AGP_EFFICEON)	+= efficeon-agp.o
 obj-$(CONFIG_AGP_HP_ZX1)	+= hp-agp.o
 obj-$(CONFIG_AGP_I460)		+= i460-agp.o
 obj-$(CONFIG_AGP_INTEL)		+= intel-agp.o
--- diff/drivers/char/agp/intel-agp.c	2004-01-19 10:22:56.000000000 +0000
+++ source/drivers/char/agp/intel-agp.c	2004-02-23 13:56:40.000000000 +0000
@@ -1432,6 +1432,8 @@ static int agp_intel_resume(struct pci_d
 		intel_configure();
 	else if (bridge->driver == &intel_845_driver)
 		intel_845_configure();
+	else if (bridge->driver == &intel_830mp_driver)
+		intel_830mp_configure();
 
 	return 0;
 }
--- diff/drivers/char/amiserial.c	2003-10-09 09:47:33.000000000 +0100
+++ source/drivers/char/amiserial.c	2004-02-23 13:56:40.000000000 +0000
@@ -1248,57 +1248,48 @@ static int get_lsr_info(struct async_str
 }
 
 
-static int get_modem_info(struct async_struct * info, unsigned int *value)
+static int rs_tiocmget(struct tty_struct *tty, struct file *file)
 {
+	struct async_struct * info = (struct async_struct *)tty->driver_data;
 	unsigned char control, status;
-	unsigned int result;
 	unsigned long flags;
 
+	if (serial_paranoia_check(info, tty->name, "rs_ioctl"))
+		return -ENODEV;
+	if (tty->flags & (1 << TTY_IO_ERROR))
+		return -EIO;
+
 	control = info->MCR;
 	local_irq_save(flags);
 	status = ciab.pra;
 	local_irq_restore(flags);
-	result =  ((control & SER_RTS) ? TIOCM_RTS : 0)
+	return    ((control & SER_RTS) ? TIOCM_RTS : 0)
 		| ((control & SER_DTR) ? TIOCM_DTR : 0)
 		| (!(status  & SER_DCD) ? TIOCM_CAR : 0)
 		| (!(status  & SER_DSR) ? TIOCM_DSR : 0)
 		| (!(status  & SER_CTS) ? TIOCM_CTS : 0);
-	if (copy_to_user(value, &result, sizeof(int)))
-		return -EFAULT;
-	return 0;
 }
 
-static int set_modem_info(struct async_struct * info, unsigned int cmd,
-			  unsigned int *value)
+static int rs_tiocmset(struct tty_struct *tty, struct file *file,
+		       unsigned int set, unsigned int clear)
 {
-	unsigned int arg;
+	struct async_struct * info = (struct async_struct *)tty->driver_data;
 	unsigned long flags;
 
-	if (copy_from_user(&arg, value, sizeof(int)))
-		return -EFAULT;
+	if (serial_paranoia_check(info, tty->name, "rs_ioctl"))
+		return -ENODEV;
+	if (tty->flags & (1 << TTY_IO_ERROR))
+		return -EIO;
 
-	switch (cmd) {
-	case TIOCMBIS: 
-	        if (arg & TIOCM_RTS)
-			info->MCR |= SER_RTS;
-		if (arg & TIOCM_DTR)
-			info->MCR |= SER_DTR;
-		break;
-	case TIOCMBIC:
-	        if (arg & TIOCM_RTS)
-			info->MCR &= ~SER_RTS;
-		if (arg & TIOCM_DTR)
-			info->MCR &= ~SER_DTR;
-		break;
-	case TIOCMSET:
-		info->MCR = ((info->MCR & ~(SER_RTS | SER_DTR))
-			     | ((arg & TIOCM_RTS) ? SER_RTS : 0)
-			     | ((arg & TIOCM_DTR) ? SER_DTR : 0));
-		break;
-	default:
-		return -EINVAL;
-	}
 	local_irq_save(flags);
+	if (set & TIOCM_RTS)
+		info->MCR |= SER_RTS;
+	if (set & TIOCM_DTR)
+		info->MCR |= SER_DTR;
+	if (clear & TIOCM_RTS)
+		info->MCR &= ~SER_RTS;
+	if (clear & TIOCM_DTR)
+		info->MCR &= ~SER_DTR;
 	rtsdtr_ctrl(info->MCR);
 	local_irq_restore(flags);
 	return 0;
@@ -1344,12 +1335,6 @@ static int rs_ioctl(struct tty_struct *t
 	}
 
 	switch (cmd) {
-		case TIOCMGET:
-			return get_modem_info(info, (unsigned int *) arg);
-		case TIOCMBIS:
-		case TIOCMBIC:
-		case TIOCMSET:
-			return set_modem_info(info, cmd, (unsigned int *) arg);
 		case TIOCGSERIAL:
 			return get_serial_info(info,
 					       (struct serial_struct *) arg);
@@ -2045,6 +2030,8 @@ static struct tty_operations serial_ops 
 	.send_xchar = rs_send_xchar,
 	.wait_until_sent = rs_wait_until_sent,
 	.read_proc = rs_read_proc,
+	.tiocmget = rs_tiocmget,
+	.tiocmset = rs_tiocmset,
 };
 
 /*
--- diff/drivers/char/cyclades.c	2003-10-09 09:47:33.000000000 +0100
+++ source/drivers/char/cyclades.c	2004-02-23 13:56:40.000000000 +0000
@@ -3632,8 +3632,9 @@ static int get_lsr_info(struct cyclades_
 }
 
 static int
-get_modem_info(struct cyclades_port * info, unsigned int *value)
+cy_tiocmget(struct tty_struct *tty, struct file *file)
 {
+  struct cyclades_port * info = (struct cyclades_port *)tty->driver_data;
   int card,chip,channel,index;
   unsigned char *base_addr;
   unsigned long flags;
@@ -3645,6 +3646,9 @@ get_modem_info(struct cyclades_port * in
   struct BOARD_CTRL *board_ctrl;
   struct CH_CTRL *ch_ctrl;
 
+    if (serial_paranoia_check(info, tty->name, __FUNCTION__))
+	return -ENODEV;
+
     card = info->card;
     channel = (info->line) - (cy_card[card].first_line);
     if (!IS_CYC_Z(cy_card[card])) {
@@ -3700,24 +3704,27 @@ get_modem_info(struct cyclades_port * in
 	}
 
     }
-    return cy_put_user(result, value);
-} /* get_modem_info */
+    return result;
+} /* cy_tiomget */
 
 
 static int
-set_modem_info(struct cyclades_port * info, unsigned int cmd,
-                          unsigned int *value)
+cy_tiocmset(struct tty_struct *tty, struct file *file,
+            unsigned int set, unsigned int clear)
 {
+  struct cyclades_port * info = (struct cyclades_port *)tty->driver_data;
   int card,chip,channel,index;
   unsigned char *base_addr;
   unsigned long flags;
-  unsigned int arg = cy_get_user((unsigned long *) value);
   struct FIRM_ID *firm_id;
   struct ZFW_CTRL *zfw_ctrl;
   struct BOARD_CTRL *board_ctrl;
   struct CH_CTRL *ch_ctrl;
   int retval;
 
+    if (serial_paranoia_check(info, tty->name, __FUNCTION__))
+	return -ENODEV;
+
     card = info->card;
     channel = (info->line) - (cy_card[card].first_line);
     if (!IS_CYC_Z(cy_card[card])) {
@@ -3728,66 +3735,7 @@ set_modem_info(struct cyclades_port * in
 		       (cy_card[card].base_addr
 		       + (cy_chip_offset[chip]<<index));
 
-	switch (cmd) {
-	case TIOCMBIS:
-	    if (arg & TIOCM_RTS){
-		CY_LOCK(info, flags);
-		cy_writeb((u_long)base_addr+(CyCAR<<index), (u_char)channel);
-                if (info->rtsdtr_inv) {
-		    cy_writeb((u_long)base_addr+(CyMSVR2<<index), CyDTR);
-                } else {
-		    cy_writeb((u_long)base_addr+(CyMSVR1<<index), CyRTS);
-                }
-		CY_UNLOCK(info, flags);
-	    }
-	    if (arg & TIOCM_DTR){
-		CY_LOCK(info, flags);
-		cy_writeb((u_long)base_addr+(CyCAR<<index), (u_char)channel);
-                if (info->rtsdtr_inv) {
-		    cy_writeb((u_long)base_addr+(CyMSVR1<<index), CyRTS);
-                } else {
-		    cy_writeb((u_long)base_addr+(CyMSVR2<<index), CyDTR);
-                }
-#ifdef CY_DEBUG_DTR
-		printk("cyc:set_modem_info raising DTR\n");
-		printk("     status: 0x%x, 0x%x\n",
-		    cy_readb(base_addr+(CyMSVR1<<index)), 
-                    cy_readb(base_addr+(CyMSVR2<<index)));
-#endif
-		CY_UNLOCK(info, flags);
-	    }
-	    break;
-	case TIOCMBIC:
-	    if (arg & TIOCM_RTS){
-		CY_LOCK(info, flags);
-		cy_writeb((u_long)base_addr+(CyCAR<<index), 
-                          (u_char)channel);
-                if (info->rtsdtr_inv) {
-		    	cy_writeb((u_long)base_addr+(CyMSVR2<<index), ~CyDTR);
-                } else {
-		    	cy_writeb((u_long)base_addr+(CyMSVR1<<index), ~CyRTS);
-                }
-		CY_UNLOCK(info, flags);
-	    }
-	    if (arg & TIOCM_DTR){
-		CY_LOCK(info, flags);
-		cy_writeb((u_long)base_addr+(CyCAR<<index), (u_char)channel);
-                if (info->rtsdtr_inv) {
-			cy_writeb((u_long)base_addr+(CyMSVR1<<index), ~CyRTS);
-                } else {
-			cy_writeb((u_long)base_addr+(CyMSVR2<<index), ~CyDTR);
-                }
-#ifdef CY_DEBUG_DTR
-		printk("cyc:set_modem_info dropping DTR\n");
-		printk("     status: 0x%x, 0x%x\n",
-		    cy_readb(base_addr+(CyMSVR1<<index)), 
-                    cy_readb(base_addr+(CyMSVR2<<index)));
-#endif
-		CY_UNLOCK(info, flags);
-	    }
-	    break;
-	case TIOCMSET:
-	    if (arg & TIOCM_RTS){
+	if (set & TIOCM_RTS){
 		CY_LOCK(info, flags);
 	        cy_writeb((u_long)base_addr+(CyCAR<<index), (u_char)channel);
                 if (info->rtsdtr_inv) {
@@ -3796,7 +3744,8 @@ set_modem_info(struct cyclades_port * in
 			cy_writeb((u_long)base_addr+(CyMSVR1<<index), CyRTS);
                 }
 		CY_UNLOCK(info, flags);
-	    }else{
+	}
+	if (clear & TIOCM_RTS) {
 		CY_LOCK(info, flags);
 		cy_writeb((u_long)base_addr+(CyCAR<<index), (u_char)channel);
                 if (info->rtsdtr_inv) {
@@ -3805,8 +3754,8 @@ set_modem_info(struct cyclades_port * in
 			cy_writeb((u_long)base_addr+(CyMSVR1<<index), ~CyRTS);
                 }
 		CY_UNLOCK(info, flags);
-	    }
-	    if (arg & TIOCM_DTR){
+	}
+	if (set & TIOCM_DTR){
 		CY_LOCK(info, flags);
 		cy_writeb((u_long)base_addr+(CyCAR<<index), (u_char)channel);
                 if (info->rtsdtr_inv) {
@@ -3821,7 +3770,8 @@ set_modem_info(struct cyclades_port * in
                     cy_readb(base_addr+(CyMSVR2<<index)));
 #endif
 		CY_UNLOCK(info, flags);
-	    }else{
+	}
+	if (clear & TIOCM_DTR) {
 		CY_LOCK(info, flags);
 		cy_writeb((u_long)base_addr+(CyCAR<<index), (u_char)channel);
                 if (info->rtsdtr_inv) {
@@ -3837,10 +3787,6 @@ set_modem_info(struct cyclades_port * in
                     cy_readb(base_addr+(CyMSVR2<<index)));
 #endif
 		CY_UNLOCK(info, flags);
-	    }
-	    break;
-	default:
-	    return -EINVAL;
 	}
     } else {
 	base_addr = (unsigned char*) (cy_card[card].base_addr);
@@ -3854,54 +3800,19 @@ set_modem_info(struct cyclades_port * in
 	    board_ctrl = &zfw_ctrl->board_ctrl;
 	    ch_ctrl = zfw_ctrl->ch_ctrl;
 
-	    switch (cmd) {
-	    case TIOCMBIS:
-		if (arg & TIOCM_RTS){
-		    CY_LOCK(info, flags);
-		    cy_writel(&ch_ctrl[channel].rs_control,
-                       cy_readl(&ch_ctrl[channel].rs_control) | C_RS_RTS);
-		    CY_UNLOCK(info, flags);
-		}
-		if (arg & TIOCM_DTR){
-		    CY_LOCK(info, flags);
-		    cy_writel(&ch_ctrl[channel].rs_control,
-                       cy_readl(&ch_ctrl[channel].rs_control) | C_RS_DTR);
-#ifdef CY_DEBUG_DTR
-		    printk("cyc:set_modem_info raising Z DTR\n");
-#endif
-		    CY_UNLOCK(info, flags);
-		}
-		break;
-	    case TIOCMBIC:
-		if (arg & TIOCM_RTS){
-		    CY_LOCK(info, flags);
-		    cy_writel(&ch_ctrl[channel].rs_control,
-                       cy_readl(&ch_ctrl[channel].rs_control) & ~C_RS_RTS);
-		    CY_UNLOCK(info, flags);
-		}
-		if (arg & TIOCM_DTR){
-		    CY_LOCK(info, flags);
-		    cy_writel(&ch_ctrl[channel].rs_control,
-                       cy_readl(&ch_ctrl[channel].rs_control) & ~C_RS_DTR);
-#ifdef CY_DEBUG_DTR
-		    printk("cyc:set_modem_info clearing Z DTR\n");
-#endif
-		    CY_UNLOCK(info, flags);
-		}
-		break;
-	    case TIOCMSET:
-		if (arg & TIOCM_RTS){
+	    if (set & TIOCM_RTS){
 		    CY_LOCK(info, flags);
 		    cy_writel(&ch_ctrl[channel].rs_control,
                        cy_readl(&ch_ctrl[channel].rs_control) | C_RS_RTS);
 		    CY_UNLOCK(info, flags);
-		}else{
+	    }
+	    if (clear & TIOCM_RTS) {
 		    CY_LOCK(info, flags);
 		    cy_writel(&ch_ctrl[channel].rs_control,
                        cy_readl(&ch_ctrl[channel].rs_control) & ~C_RS_RTS);
 		    CY_UNLOCK(info, flags);
-		}
-		if (arg & TIOCM_DTR){
+	    }
+	    if (set & TIOCM_DTR){
 		    CY_LOCK(info, flags);
 		    cy_writel(&ch_ctrl[channel].rs_control,
                        cy_readl(&ch_ctrl[channel].rs_control) | C_RS_DTR);
@@ -3909,7 +3820,8 @@ set_modem_info(struct cyclades_port * in
 		    printk("cyc:set_modem_info raising Z DTR\n");
 #endif
 		    CY_UNLOCK(info, flags);
-		}else{
+	    }
+	    if (clear & TIOCM_DTR) {
 		    CY_LOCK(info, flags);
 		    cy_writel(&ch_ctrl[channel].rs_control,
                        cy_readl(&ch_ctrl[channel].rs_control) & ~C_RS_DTR);
@@ -3917,10 +3829,6 @@ set_modem_info(struct cyclades_port * in
 		    printk("cyc:set_modem_info clearing Z DTR\n");
 #endif
 		    CY_UNLOCK(info, flags);
-		}
-		break;
-	    default:
-		return -EINVAL;
 	    }
 	}else{
 	    return -ENODEV;
@@ -3935,7 +3843,7 @@ set_modem_info(struct cyclades_port * in
 	CY_UNLOCK(info, flags);
     }
     return 0;
-} /* set_modem_info */
+} /* cy_tiocmset */
 
 /*
  * cy_break() --- routine which turns the break handling on or off
@@ -4242,14 +4150,6 @@ cy_ioctl(struct tty_struct *tty, struct 
 	case CYGETWAIT:
 	    ret_val = info->closing_wait / (HZ/100);
 	    break;
-        case TIOCMGET:
-            ret_val = get_modem_info(info, (unsigned int *) arg);
-            break;
-        case TIOCMBIS:
-        case TIOCMBIC:
-        case TIOCMSET:
-            ret_val = set_modem_info(info, cmd, (unsigned int *) arg);
-            break;
         case TIOCGSERIAL:
             ret_val = get_serial_info(info, (struct serial_struct *) arg);
             break;
@@ -5429,6 +5329,8 @@ static struct tty_operations cy_ops = {
     .break_ctl = cy_break,
     .wait_until_sent = cy_wait_until_sent,
     .read_proc = cyclades_get_proc_info,
+    .tiocmget = cy_tiocmget,
+    .tiocmset = cy_tiocmset,
 };
 
 static int __init
--- diff/drivers/char/drm/Kconfig	2004-02-09 10:36:10.000000000 +0000
+++ source/drivers/char/drm/Kconfig	2004-02-23 13:56:41.000000000 +0000
@@ -76,7 +76,7 @@ config DRM_SIS
 	tristate "SiS video cards"
 	depends on DRM && AGP
 	help
-	  Choose this option if you have a SiS 630 or compatibel video 
+	  Choose this option if you have a SiS 630 or compatible video 
           chipset. If M is selected the module will be called sis. AGP
           support is required for this driver to work.
 
--- diff/drivers/char/drm/drm.h	2003-07-22 18:54:27.000000000 +0100
+++ source/drivers/char/drm/drm.h	2004-02-23 13:56:40.000000000 +0000
@@ -580,6 +580,16 @@ typedef struct drm_scatter_gather {
 	unsigned long handle;	/**< Used for mapping / unmapping */
 } drm_scatter_gather_t;
 
+/**
+ * DRM_IOCTL_SET_VERSION ioctl argument type.
+ */
+typedef struct drm_set_version {
+	int drm_di_major;
+	int drm_di_minor;
+	int drm_dd_major;
+	int drm_dd_minor;
+} drm_set_version_t;
+
 
 #define DRM_IOCTL_BASE			'd'
 #define DRM_IO(nr)			_IO(DRM_IOCTL_BASE,nr)
@@ -594,6 +604,7 @@ typedef struct drm_scatter_gather {
 #define DRM_IOCTL_GET_MAP               DRM_IOWR(0x04, drm_map_t)
 #define DRM_IOCTL_GET_CLIENT            DRM_IOWR(0x05, drm_client_t)
 #define DRM_IOCTL_GET_STATS             DRM_IOR( 0x06, drm_stats_t)
+#define DRM_IOCTL_SET_VERSION		DRM_IOWR(0x07, drm_set_version_t)
 
 #define DRM_IOCTL_SET_UNIQUE		DRM_IOW( 0x10, drm_unique_t)
 #define DRM_IOCTL_AUTH_MAGIC		DRM_IOW( 0x11, drm_auth_t)
--- diff/drivers/char/drm/drmP.h	2004-01-19 10:22:56.000000000 +0000
+++ source/drivers/char/drm/drmP.h	2004-02-23 13:56:40.000000000 +0000
@@ -92,8 +92,8 @@
 #ifndef __HAVE_DMA
 #define __HAVE_DMA		0
 #endif
-#ifndef __HAVE_DMA_IRQ
-#define __HAVE_DMA_IRQ		0
+#ifndef __HAVE_IRQ
+#define __HAVE_IRQ		0
 #endif
 #ifndef __HAVE_DMA_WAITLIST
 #define __HAVE_DMA_WAITLIST	0
@@ -324,6 +324,7 @@ do {											\
 #define DRM_BUFCOUNT(x) ((x)->count - DRM_LEFTCOUNT(x))
 #define DRM_WAITCOUNT(dev,idx) DRM_BUFCOUNT(&dev->queuelist[idx]->waitlist)
 
+#define DRM_IF_VERSION(maj, min) ((maj) << 16 | (min))
 /**
  * Get the private SAREA mapping.
  *
@@ -362,10 +363,13 @@ do {									\
 typedef int drm_ioctl_t( struct inode *inode, struct file *filp,
 			 unsigned int cmd, unsigned long arg );
 
-typedef struct drm_pci_list {
-	u16 vendor;
-	u16 device;
-} drm_pci_list_t;
+typedef struct drm_pci_id_list
+{
+	int vendor;
+	int device;
+	long driver_private;
+	char *name;
+} drm_pci_id_list_t;
 
 typedef struct drm_ioctl_desc {
 	drm_ioctl_t	     *func;
@@ -488,6 +492,9 @@ typedef struct drm_file {
 	struct drm_device *dev;
 	int 		  remove_auth_on_close;
 	unsigned long     lock_count;
+#ifdef DRIVER_FILE_FIELDS
+	DRIVER_FILE_FIELDS;
+#endif
 } drm_file_t;
 
 /** Wait queue */
@@ -622,6 +629,8 @@ typedef struct drm_device {
 	int		  unique_len;	/**< Length of unique field */
 	dev_t		  device;	/**< Device number for mknod */
 	char		  *devname;	/**< For /proc/interrupts */
+	int		  minor;        /**< Minor device number */
+	int		  if_version;	/**< Highest interface version set */
 
 	int		  blocked;	/**< Blocked due to VC switch? */
 	struct proc_dir_entry *root;	/**< Root for this device's entries */
@@ -679,6 +688,7 @@ typedef struct drm_device {
 	/** \name Context support */
 	/*@{*/
 	int		  irq;		/**< Interrupt used by board */
+	int		  irq_enabled;	/**< True if irq handler is enabled */
 	__volatile__ long context_flag;	/**< Context swapping flag */
 	__volatile__ long interrupt_flag; /**< Interruption handler flag */
 	__volatile__ long dma_flag;	/**< DMA dispatch flag */
@@ -714,7 +724,12 @@ typedef struct drm_device {
 #if __REALLY_HAVE_AGP
 	drm_agp_head_t    *agp;	/**< AGP data */
 #endif
-	struct pci_dev *pdev;		/**< PCI device structure */
+
+	struct pci_dev    *pdev;	/**< PCI device structure */
+	int               pci_domain;	/**< PCI bus domain number */
+	int               pci_bus;	/**< PCI bus number */
+	int               pci_slot;	/**< PCI slot number */
+	int               pci_func;	/**< PCI function number */
 #ifdef __alpha__
 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,3)
 	struct pci_controler *hose;
@@ -804,8 +819,8 @@ extern int           DRM(unbind_agp)(DRM
 #endif
 
 				/* Misc. IOCTL support (drm_ioctl.h) */
-extern int	     DRM(irq_busid)(struct inode *inode, struct file *filp,
-				    unsigned int cmd, unsigned long arg);
+extern int	     DRM(irq_by_busid)(struct inode *inode, struct file *filp,
+				       unsigned int cmd, unsigned long arg);
 extern int	     DRM(getunique)(struct inode *inode, struct file *filp,
 				    unsigned int cmd, unsigned long arg);
 extern int	     DRM(setunique)(struct inode *inode, struct file *filp,
@@ -816,6 +831,8 @@ extern int	     DRM(getclient)(struct in
 				    unsigned int cmd, unsigned long arg);
 extern int	     DRM(getstats)(struct inode *inode, struct file *filp,
 				   unsigned int cmd, unsigned long arg);
+extern int	     DRM(setversion)(struct inode *inode, struct file *filp,
+				     unsigned int cmd, unsigned long arg);
 
 				/* Context IOCTL support (drm_context.h) */
 extern int	     DRM(resctx)( struct inode *inode, struct file *filp,
@@ -900,12 +917,17 @@ extern int	     DRM(dma_setup)(drm_devic
 extern void	     DRM(dma_takedown)(drm_device_t *dev);
 extern void	     DRM(free_buffer)(drm_device_t *dev, drm_buf_t *buf);
 extern void	     DRM(reclaim_buffers)( struct file *filp );
-#if __HAVE_DMA_IRQ
+#endif /* __HAVE_DMA */
+
+				/* IRQ support (drm_irq.h) */
+#if __HAVE_IRQ || __HAVE_DMA
 extern int           DRM(control)( struct inode *inode, struct file *filp,
 				   unsigned int cmd, unsigned long arg );
-extern int           DRM(irq_install)( drm_device_t *dev, int irq );
+#endif
+#if __HAVE_IRQ
+extern int           DRM(irq_install)( drm_device_t *dev );
 extern int           DRM(irq_uninstall)( drm_device_t *dev );
-extern irqreturn_t   DRM(dma_service)( DRM_IRQ_ARGS );
+extern irqreturn_t   DRM(irq_handler)( DRM_IRQ_ARGS );
 extern void          DRM(driver_irq_preinstall)( drm_device_t *dev );
 extern void          DRM(driver_irq_postinstall)( drm_device_t *dev );
 extern void          DRM(driver_irq_uninstall)( drm_device_t *dev );
@@ -915,12 +937,11 @@ extern int           DRM(wait_vblank)(st
 extern int           DRM(vblank_wait)(drm_device_t *dev, unsigned int *vbl_seq);
 extern void          DRM(vbl_send_signals)( drm_device_t *dev );
 #endif
-#if __HAVE_DMA_IRQ_BH
-extern void          DRM(dma_immediate_bh)( void *dev );
+#if __HAVE_IRQ_BH
+extern void          DRM(irq_immediate_bh)( void *dev );
 #endif
 #endif
 
-#endif /* __HAVE_DMA */
 
 #if __REALLY_HAVE_AGP
 				/* AGP/GART support (drm_agpsupport.h) */
--- diff/drivers/char/drm/drm_bufs.h	2003-07-22 18:54:27.000000000 +0100
+++ source/drivers/char/drm/drm_bufs.h	2004-02-23 13:56:40.000000000 +0000
@@ -147,7 +147,9 @@ int DRM(addmap)( struct inode *inode, st
 					      MTRR_TYPE_WRCOMB, 1 );
 		}
 #endif
-		map->handle = DRM(ioremap)( map->offset, map->size, dev );
+		if (map->type == _DRM_REGISTERS)
+			map->handle = DRM(ioremap)( map->offset, map->size,
+						    dev );
 		break;
 
 	case _DRM_SHM:
@@ -160,6 +162,12 @@ int DRM(addmap)( struct inode *inode, st
 		}
 		map->offset = (unsigned long)map->handle;
 		if ( map->flags & _DRM_CONTAINS_LOCK ) {
+			/* Prevent a 2nd X Server from creating a 2nd lock */
+			if (dev->lock.hw_lock != NULL) {
+				vfree( map->handle );
+				DRM(free)( map, sizeof(*map), DRM_MEM_MAPS );
+				return -EBUSY;
+			}
 			dev->sigdata.lock =
 			dev->lock.hw_lock = map->handle; /* Pointer to lock */
 		}
--- diff/drivers/char/drm/drm_dma.h	2003-07-22 18:54:27.000000000 +0100
+++ source/drivers/char/drm/drm_dma.h	2004-02-23 13:56:40.000000000 +0000
@@ -43,15 +43,6 @@
 #ifndef __HAVE_DMA_RECLAIM
 #define __HAVE_DMA_RECLAIM	0
 #endif
-#ifndef __HAVE_SHARED_IRQ
-#define __HAVE_SHARED_IRQ	0
-#endif
-
-#if __HAVE_SHARED_IRQ
-#define DRM_IRQ_TYPE		SA_SHIRQ
-#else
-#define DRM_IRQ_TYPE		0
-#endif
 
 #if __HAVE_DMA
 
@@ -214,293 +205,11 @@ void DRM(reclaim_buffers)( struct file *
 }
 #endif
 
-
-
-
-#if __HAVE_DMA_IRQ
-
-/**
- * Install IRQ handler.
- *
- * \param dev DRM device.
- * \param irq IRQ number.
- *
- * Initializes the IRQ related data, and setups drm_device::vbl_queue. Installs the handler, calling the driver
- * \c DRM(driver_irq_preinstall)() and \c DRM(driver_irq_postinstall)() functions
- * before and after the installation.
- */
-int DRM(irq_install)( drm_device_t *dev, int irq )
-{
-	int ret;
-
-	if ( !irq )
-		return -EINVAL;
-
-	down( &dev->struct_sem );
-
-	/* Driver must have been initialized */
-	if ( !dev->dev_private ) {
-		up( &dev->struct_sem );
-		return -EINVAL;
-	}
-
-	if ( dev->irq ) {
-		up( &dev->struct_sem );
-		return -EBUSY;
-	}
-	dev->irq = irq;
-	up( &dev->struct_sem );
-
-	DRM_DEBUG( "%s: irq=%d\n", __FUNCTION__, irq );
-
-	dev->context_flag = 0;
-	dev->interrupt_flag = 0;
-	dev->dma_flag = 0;
-
-	dev->dma->next_buffer = NULL;
-	dev->dma->next_queue = NULL;
-	dev->dma->this_buffer = NULL;
-
-#if __HAVE_DMA_IRQ_BH
-	INIT_WORK(&dev->work, DRM(dma_immediate_bh), dev);
-#endif
-
-#if __HAVE_VBL_IRQ
-	init_waitqueue_head(&dev->vbl_queue);
-
-	spin_lock_init( &dev->vbl_lock );
-
-	INIT_LIST_HEAD( &dev->vbl_sigs.head );
-
-	dev->vbl_pending = 0;
-#endif
-
-				/* Before installing handler */
-	DRM(driver_irq_preinstall)(dev);
-
-				/* Install handler */
-	ret = request_irq( dev->irq, DRM(dma_service),
-			   DRM_IRQ_TYPE, dev->devname, dev );
-	if ( ret < 0 ) {
-		down( &dev->struct_sem );
-		dev->irq = 0;
-		up( &dev->struct_sem );
-		return ret;
-	}
-
-				/* After installing handler */
-	DRM(driver_irq_postinstall)(dev);
-
-	return 0;
-}
-
-/**
- * Uninstall the IRQ handler.
- *
- * \param dev DRM device.
- *
- * Calls the driver's \c DRM(driver_irq_uninstall)() function, and stops the irq.
- */
-int DRM(irq_uninstall)( drm_device_t *dev )
-{
-	int irq;
-
-	down( &dev->struct_sem );
-	irq = dev->irq;
-	dev->irq = 0;
-	up( &dev->struct_sem );
-
-	if ( !irq )
-		return -EINVAL;
-
-	DRM_DEBUG( "%s: irq=%d\n", __FUNCTION__, irq );
-
-	DRM(driver_irq_uninstall)( dev );
-
-	free_irq( irq, dev );
-
-	return 0;
-}
-
-/**
- * IRQ control ioctl.
- *
- * \param inode device inode.
- * \param filp file pointer.
- * \param cmd command.
- * \param arg user argument, pointing to a drm_control structure.
- * \return zero on success or a negative number on failure.
- *
- * Calls irq_install() or irq_uninstall() according to \p arg.
- */
-int DRM(control)( struct inode *inode, struct file *filp,
-		  unsigned int cmd, unsigned long arg )
-{
-	drm_file_t *priv = filp->private_data;
-	drm_device_t *dev = priv->dev;
-	drm_control_t ctl;
-
-	if ( copy_from_user( &ctl, (drm_control_t *)arg, sizeof(ctl) ) )
-		return -EFAULT;
-
-	switch ( ctl.func ) {
-	case DRM_INST_HANDLER:
-		return DRM(irq_install)( dev, ctl.irq );
-	case DRM_UNINST_HANDLER:
-		return DRM(irq_uninstall)( dev );
-	default:
-		return -EINVAL;
-	}
-}
-
-#if __HAVE_VBL_IRQ
-
-/**
- * Wait for VBLANK.
- *
- * \param inode device inode.
- * \param filp file pointer.
- * \param cmd command.
- * \param data user argument, pointing to a drm_wait_vblank structure.
- * \return zero on success or a negative number on failure.
- *
- * Verifies the IRQ is installed. 
- *
- * If a signal is requested checks if this task has already scheduled the same signal
- * for the same vblank sequence number - nothing to be done in
- * that case. If the number of tasks waiting for the interrupt exceeds 100 the
- * function fails. Otherwise adds a new entry to drm_device::vbl_sigs for this
- * task.
- *
- * If a signal is not requested, then calls vblank_wait().
- */
-int DRM(wait_vblank)( DRM_IOCTL_ARGS )
-{
-	drm_file_t *priv = filp->private_data;
-	drm_device_t *dev = priv->dev;
-	drm_wait_vblank_t vblwait;
-	struct timeval now;
-	int ret = 0;
-	unsigned int flags;
-
-	if (!dev->irq)
-		return -EINVAL;
-
-	DRM_COPY_FROM_USER_IOCTL( vblwait, (drm_wait_vblank_t *)data,
-				  sizeof(vblwait) );
-
-	switch ( vblwait.request.type & ~_DRM_VBLANK_FLAGS_MASK ) {
-	case _DRM_VBLANK_RELATIVE:
-		vblwait.request.sequence += atomic_read( &dev->vbl_received );
-		vblwait.request.type &= ~_DRM_VBLANK_RELATIVE;
-	case _DRM_VBLANK_ABSOLUTE:
-		break;
-	default:
-		return -EINVAL;
-	}
-
-	flags = vblwait.request.type & _DRM_VBLANK_FLAGS_MASK;
-	
-	if ( flags & _DRM_VBLANK_SIGNAL ) {
-		unsigned long irqflags;
-		drm_vbl_sig_t *vbl_sig;
-		
-		vblwait.reply.sequence = atomic_read( &dev->vbl_received );
-
-		spin_lock_irqsave( &dev->vbl_lock, irqflags );
-
-		/* Check if this task has already scheduled the same signal
-		 * for the same vblank sequence number; nothing to be done in
-		 * that case
-		 */
-		list_for_each_entry( vbl_sig, &dev->vbl_sigs.head, head ) {
-			if (vbl_sig->sequence == vblwait.request.sequence
-			    && vbl_sig->info.si_signo == vblwait.request.signal
-			    && vbl_sig->task == current)
-			{
-				spin_unlock_irqrestore( &dev->vbl_lock, irqflags );
-				goto done;
-			}
-		}
-
-		if ( dev->vbl_pending >= 100 ) {
-			spin_unlock_irqrestore( &dev->vbl_lock, irqflags );
-			return -EBUSY;
-		}
-
-		dev->vbl_pending++;
-
-		spin_unlock_irqrestore( &dev->vbl_lock, irqflags );
-
-		if ( !( vbl_sig = DRM_MALLOC( sizeof( drm_vbl_sig_t ) ) ) ) {
-			return -ENOMEM;
-		}
-
-		memset( (void *)vbl_sig, 0, sizeof(*vbl_sig) );
-
-		vbl_sig->sequence = vblwait.request.sequence;
-		vbl_sig->info.si_signo = vblwait.request.signal;
-		vbl_sig->task = current;
-
-		spin_lock_irqsave( &dev->vbl_lock, irqflags );
-
-		list_add_tail( (struct list_head *) vbl_sig, &dev->vbl_sigs.head );
-
-		spin_unlock_irqrestore( &dev->vbl_lock, irqflags );
-	} else {
-		ret = DRM(vblank_wait)( dev, &vblwait.request.sequence );
-
-		do_gettimeofday( &now );
-		vblwait.reply.tval_sec = now.tv_sec;
-		vblwait.reply.tval_usec = now.tv_usec;
-	}
-
-done:
-	DRM_COPY_TO_USER_IOCTL( (drm_wait_vblank_t *)data, vblwait,
-				sizeof(vblwait) );
-
-	return ret;
-}
-
-/**
- * Send the VBLANK signals.
- *
- * \param dev DRM device.
- *
- * Sends a signal for each task in drm_device::vbl_sigs and empties the list.
- *
- * If a signal is not requested, then calls vblank_wait().
+#if !__HAVE_IRQ
+/* This stub DRM_IOCTL_CONTROL handler is for the drivers that used to require
+ * IRQs for DMA but no longer do.  It maintains compatibility with the X Servers
+ * that try to use the control ioctl by simply returning success.
  */
-void DRM(vbl_send_signals)( drm_device_t *dev )
-{
-	struct list_head *list, *tmp;
-	drm_vbl_sig_t *vbl_sig;
-	unsigned int vbl_seq = atomic_read( &dev->vbl_received );
-	unsigned long flags;
-
-	spin_lock_irqsave( &dev->vbl_lock, flags );
-
-	list_for_each_safe( list, tmp, &dev->vbl_sigs.head ) {
-		vbl_sig = list_entry( list, drm_vbl_sig_t, head );
-		if ( ( vbl_seq - vbl_sig->sequence ) <= (1<<23) ) {
-			vbl_sig->info.si_code = vbl_seq;
-			send_sig_info( vbl_sig->info.si_signo, &vbl_sig->info, vbl_sig->task );
-
-			list_del( list );
-
-			DRM_FREE( vbl_sig, sizeof(*vbl_sig) );
-
-			dev->vbl_pending--;
-		}
-	}
-
-	spin_unlock_irqrestore( &dev->vbl_lock, flags );
-}
-
-#endif	/* __HAVE_VBL_IRQ */
-
-#else
-
 int DRM(control)( struct inode *inode, struct file *filp,
 		  unsigned int cmd, unsigned long arg )
 {
@@ -517,7 +226,6 @@ int DRM(control)( struct inode *inode, s
 		return -EINVAL;
 	}
 }
-
-#endif /* __HAVE_DMA_IRQ */
+#endif
 
 #endif /* __HAVE_DMA */
--- diff/drivers/char/drm/drm_drv.h	2003-10-27 09:20:43.000000000 +0000
+++ source/drivers/char/drm/drm_drv.h	2004-02-23 13:56:40.000000000 +0000
@@ -58,8 +58,8 @@
 #ifndef __HAVE_CTX_BITMAP
 #define __HAVE_CTX_BITMAP		0
 #endif
-#ifndef __HAVE_DMA_IRQ
-#define __HAVE_DMA_IRQ			0
+#ifndef __HAVE_IRQ
+#define __HAVE_IRQ			0
 #endif
 #ifndef __HAVE_DMA_QUEUE
 #define __HAVE_DMA_QUEUE		0
@@ -126,6 +126,9 @@
 #ifndef DRIVER_IOCTLS
 #define DRIVER_IOCTLS
 #endif
+#ifndef DRIVER_OPEN_HELPER
+#define DRIVER_OPEN_HELPER( priv, dev )
+#endif
 #ifndef DRIVER_FOPS
 #define DRIVER_FOPS				\
 static struct file_operations	DRM(fops) = {	\
@@ -159,15 +162,8 @@ __setup( DRIVER_NAME "=", DRM_OPTIONS_FU
 #undef DRM_OPTIONS_FUNC
 #endif
 
-/**
- * The default number of instances (minor numbers) to initialize.
- */
-#ifndef DRIVER_NUM_CARDS
-#define DRIVER_NUM_CARDS 1
-#endif
-
-static drm_device_t	*DRM(device);
-static int		*DRM(minor);
+#define MAX_DEVICES 4
+static drm_device_t	DRM(device)[MAX_DEVICES];
 static int		DRM(numdevs) = 0;
 
 DRIVER_FOPS;
@@ -177,10 +173,13 @@ static drm_ioctl_desc_t		  DRM(ioctls)[]
 	[DRM_IOCTL_NR(DRM_IOCTL_VERSION)]       = { DRM(version),     0, 0 },
 	[DRM_IOCTL_NR(DRM_IOCTL_GET_UNIQUE)]    = { DRM(getunique),   0, 0 },
 	[DRM_IOCTL_NR(DRM_IOCTL_GET_MAGIC)]     = { DRM(getmagic),    0, 0 },
-	[DRM_IOCTL_NR(DRM_IOCTL_IRQ_BUSID)]     = { DRM(irq_busid),   0, 1 },
+#if __HAVE_IRQ
+	[DRM_IOCTL_NR(DRM_IOCTL_IRQ_BUSID)]     = { DRM(irq_by_busid), 0, 1 },
+#endif
 	[DRM_IOCTL_NR(DRM_IOCTL_GET_MAP)]       = { DRM(getmap),      0, 0 },
 	[DRM_IOCTL_NR(DRM_IOCTL_GET_CLIENT)]    = { DRM(getclient),   0, 0 },
 	[DRM_IOCTL_NR(DRM_IOCTL_GET_STATS)]     = { DRM(getstats),    0, 0 },
+	[DRM_IOCTL_NR(DRM_IOCTL_SET_VERSION)]   = { DRM(setversion),  0, 1 },
 
 	[DRM_IOCTL_NR(DRM_IOCTL_SET_UNIQUE)]    = { DRM(setunique),   1, 1 },
 	[DRM_IOCTL_NR(DRM_IOCTL_BLOCK)]         = { DRM(noop),        1, 1 },
@@ -222,9 +221,9 @@ static drm_ioctl_desc_t		  DRM(ioctls)[]
 	[DRM_IOCTL_NR(DRM_IOCTL_INFO_BUFS)]     = { DRM(infobufs),    1, 0 },
 	[DRM_IOCTL_NR(DRM_IOCTL_MAP_BUFS)]      = { DRM(mapbufs),     1, 0 },
 	[DRM_IOCTL_NR(DRM_IOCTL_FREE_BUFS)]     = { DRM(freebufs),    1, 0 },
-
-	/* The DRM_IOCTL_DMA ioctl should be defined by the driver.
-	 */
+	/* The DRM_IOCTL_DMA ioctl should be defined by the driver. */
+#endif
+#if __HAVE_IRQ || __HAVE_DMA
 	[DRM_IOCTL_NR(DRM_IOCTL_CONTROL)]       = { DRM(control),     1, 1 },
 #endif
 
@@ -337,7 +336,7 @@ static int DRM(setup)( drm_device_t *dev
 	dev->queue_reserved = 0;
 	dev->queue_slots = 0;
 	dev->queuelist = NULL;
-	dev->irq = 0;
+	dev->irq_enabled = 0;
 	dev->context_flag = 0;
 	dev->interrupt_flag = 0;
 	dev->dma_flag = 0;
@@ -345,6 +344,7 @@ static int DRM(setup)( drm_device_t *dev
 	dev->last_switch = 0;
 	dev->last_checked = 0;
 	init_waitqueue_head( &dev->context_wait );
+	dev->if_version = 0;
 
 	dev->ctx_start = 0;
 	dev->lck_start = 0;
@@ -391,8 +391,8 @@ static int DRM(takedown)( drm_device_t *
 	DRM_DEBUG( "\n" );
 
 	DRIVER_PRETAKEDOWN();
-#if __HAVE_DMA_IRQ
-	if ( dev->irq ) DRM(irq_uninstall)( dev );
+#if __HAVE_IRQ
+	if ( dev->irq_enabled ) DRM(irq_uninstall)( dev );
 #endif
 
 	down( &dev->struct_sem );
@@ -534,52 +534,111 @@ static int DRM(takedown)( drm_device_t *
 	return 0;
 }
 
-/**
- * Figure out how many instances to initialize.
- *
- * \return number of cards found.
- *
- * Searches for every PCI card in \c DRIVER_CARD_LIST with matching vendor and device ids.
- */
-static int drm_count_cards(void)
+static drm_pci_id_list_t DRM(pciidlist)[] = {
+	DRIVER_PCI_IDS
+};
+
+static int DRM(probe)(struct pci_dev *pdev)
 {
-	int num = 0;
-#if defined(DRIVER_CARD_LIST)
-	int i;
-	drm_pci_list_t *l;
-	u16 device, vendor;
-	struct pci_dev *pdev = NULL;
+	drm_device_t *dev;
+#if __HAVE_CTX_BITMAP
+	int retcode;
 #endif
+	int i;
+	char *desc = NULL;
 
 	DRM_DEBUG( "\n" );
 
-#if defined(DRIVER_COUNT_CARDS)
-	num = DRIVER_COUNT_CARDS();
-#elif defined(DRIVER_CARD_LIST)
-	for (i = 0, l = DRIVER_CARD_LIST; l[i].vendor != 0; i++) {
-		pdev = NULL;
-		vendor = l[i].vendor;
-		device = l[i].device;
-		if(device == 0xffff) device = PCI_ANY_ID;
-		if(vendor == 0xffff) vendor = PCI_ANY_ID;
-		while ((pdev = pci_find_device(vendor, device, pdev))) {
-			num++;
+	for (i = 0; DRM(pciidlist)[i].vendor != 0; i++) {
+		if ((DRM(pciidlist)[i].vendor == pdev->vendor) &&
+		    (DRM(pciidlist)[i].device == pdev->device)) {
+			desc = DRM(pciidlist)[i].name;
 		}
 	}
+	if (desc == NULL)
+		return -ENODEV;
+
+	if (DRM(numdevs) >= MAX_DEVICES)
+		return -ENODEV;
+
+	dev = &(DRM(device)[DRM(numdevs)]);
+
+	memset( (void *)dev, 0, sizeof(*dev) );
+	dev->count_lock = SPIN_LOCK_UNLOCKED;
+	init_timer( &dev->timer );
+	sema_init( &dev->struct_sem, 1 );
+
+	if ((dev->minor = DRM(stub_register)(DRIVER_NAME, &DRM(fops),dev)) < 0)
+		return -EPERM;
+	dev->device = MKDEV(DRM_MAJOR, dev->minor );
+	dev->name   = DRIVER_NAME;
+
+	dev->pdev   = pdev;
+#ifdef __alpha__
+	dev->hose   = pdev->sysdata;
+	dev->pci_domain = dev->hose->bus->number;
 #else
-	num = DRIVER_NUM_CARDS;
+	dev->pci_domain = 0;
+#endif
+	dev->pci_bus = pdev->bus->number;
+	dev->pci_slot = PCI_SLOT(pdev->devfn);
+	dev->pci_func = PCI_FUNC(pdev->devfn);
+	dev->irq = pdev->irq;
+
+	DRIVER_PREINIT();
+
+#if __REALLY_HAVE_AGP
+	dev->agp = DRM(agp_init)();
+#if __MUST_HAVE_AGP
+	if ( dev->agp == NULL ) {
+		DRM_ERROR( "Cannot initialize the agpgart module.\n" );
+		DRM(stub_unregister)(dev->minor);
+		DRM(takedown)( dev );
+		return -ENOMEM;
+	}
+#endif
+#if __REALLY_HAVE_MTRR
+	if (dev->agp)
+		dev->agp->agp_mtrr = mtrr_add( dev->agp->agp_info.aper_base,
+					dev->agp->agp_info.aper_size*1024*1024,
+					MTRR_TYPE_WRCOMB,
+					1 );
+#endif
+#endif
+
+#if __HAVE_CTX_BITMAP
+	retcode = DRM(ctxbitmap_init)( dev );
+	if( retcode ) {
+		DRM_ERROR( "Cannot allocate memory for context bitmap.\n" );
+		DRM(stub_unregister)(dev->minor);
+		DRM(takedown)( dev );
+		return retcode;
+ 	}
 #endif
-	DRM_DEBUG("numdevs = %d\n", num);
-	return num;
+	DRM(numdevs)++; /* no errors, mark it reserved */
+	
+	DRM_INFO( "Initialized %s %d.%d.%d %s on minor %d: %s\n",
+		DRIVER_NAME,
+		DRIVER_MAJOR,
+		DRIVER_MINOR,
+		DRIVER_PATCHLEVEL,
+		DRIVER_DATE,
+		dev->minor,
+		desc );
+
+	DRIVER_POSTINIT();
+
+	return 0;
 }
 
+
 /**
  * Module initialization. Called via init_module at module load time, or via
  * linux/init/main.c (this is not currently supported).
  *
  * \return zero on success or a negative number on failure.
  *
- * Allocates and initialize an array of drm_device structures, and attempts to
+ * Initializes an array of drm_device structures, and attempts to
  * initialize all available devices, using consecutive minors, registering the
  * stubs and initializing the AGP device.
  * 
@@ -588,88 +647,19 @@ static int drm_count_cards(void)
  */
 static int __init drm_init( void )
 {
+	struct pci_dev *pdev = NULL;
 
-	drm_device_t *dev;
-	int i;
-#if __HAVE_CTX_BITMAP
-	int retcode;
-#endif
 	DRM_DEBUG( "\n" );
 
 #ifdef MODULE
 	DRM(parse_options)( drm_opts );
 #endif
 
-	DRM(numdevs) = drm_count_cards();
-	/* Force at least one instance. */
-	if (DRM(numdevs) <= 0)
-		DRM(numdevs) = 1;
-
-	DRM(device) = kmalloc(sizeof(*DRM(device)) * DRM(numdevs), GFP_KERNEL);
-	if (!DRM(device)) {
-		return -ENOMEM;
-	}
-	DRM(minor) = kmalloc(sizeof(*DRM(minor)) * DRM(numdevs), GFP_KERNEL);
-	if (!DRM(minor)) {
-		kfree(DRM(device));
-		return -ENOMEM;
-	}
-
-	DRIVER_PREINIT();
-
 	DRM(mem_init)();
 
-	for (i = 0; i < DRM(numdevs); i++) {
-		dev = &(DRM(device)[i]);
-		memset( (void *)dev, 0, sizeof(*dev) );
-		dev->count_lock = SPIN_LOCK_UNLOCKED;
-		init_timer( &dev->timer );
-		sema_init( &dev->struct_sem, 1 );
-
-		if ((DRM(minor)[i] = DRM(stub_register)(DRIVER_NAME, &DRM(fops),dev)) < 0)
-			return -EPERM;
-		dev->device = MKDEV(DRM_MAJOR, DRM(minor)[i] );
-		dev->name   = DRIVER_NAME;
-
-#if __REALLY_HAVE_AGP
-		dev->agp = DRM(agp_init)();
-#if __MUST_HAVE_AGP
-		if ( dev->agp == NULL ) {
-			DRM_ERROR( "Cannot initialize the agpgart module.\n" );
-			DRM(stub_unregister)(DRM(minor)[i]);
-			DRM(takedown)( dev );
-			return -EINVAL;
-		}
-#endif
-#if __REALLY_HAVE_MTRR
-		if (dev->agp)
-			dev->agp->agp_mtrr = mtrr_add( dev->agp->agp_info.aper_base,
-				       dev->agp->agp_info.aper_size*1024*1024,
-				       MTRR_TYPE_WRCOMB,
-				       1 );
-#endif
-#endif
-
-#if __HAVE_CTX_BITMAP
-		retcode = DRM(ctxbitmap_init)( dev );
-		if( retcode ) {
-			DRM_ERROR( "Cannot allocate memory for context bitmap.\n" );
-			DRM(stub_unregister)(DRM(minor)[i]);
-			DRM(takedown)( dev );
-			return retcode;
-		}
-#endif
-		DRM_INFO( "Initialized %s %d.%d.%d %s on minor %d\n",
-		  	DRIVER_NAME,
-		  	DRIVER_MAJOR,
-		  	DRIVER_MINOR,
-		  	DRIVER_PATCHLEVEL,
-		  	DRIVER_DATE,
-		  	DRM(minor)[i] );
+	while ((pdev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, pdev)) != NULL) {
+		DRM(probe)(pdev);
 	}
-
-	DRIVER_POSTINIT();
-
 	return 0;
 }
 
@@ -689,10 +679,10 @@ static void __exit drm_cleanup( void )
 
 	for (i = DRM(numdevs) - 1; i >= 0; i--) {
 		dev = &(DRM(device)[i]);
-		if ( DRM(stub_unregister)(DRM(minor)[i]) ) {
+		if ( DRM(stub_unregister)(dev->minor) ) {
 			DRM_ERROR( "Cannot unload module\n" );
 		} else {
-			DRM_DEBUG("minor %d unregistered\n", DRM(minor)[i]);
+			DRM_DEBUG("minor %d unregistered\n", dev->minor);
 			if (i == 0) {
 				DRM_INFO( "Module unloaded\n" );
 			}
@@ -722,8 +712,6 @@ static void __exit drm_cleanup( void )
 #endif
 	}
 	DRIVER_POSTCLEANUP();
-	kfree(DRM(minor));
-	kfree(DRM(device));
 	DRM(numdevs) = 0;
 }
 
@@ -795,7 +783,7 @@ int DRM(open)( struct inode *inode, stru
 	int i;
 
 	for (i = 0; i < DRM(numdevs); i++) {
-		if (iminor(inode) == DRM(minor)[i]) {
+		if (iminor(inode) == DRM(device)[i].minor) {
 			dev = &(DRM(device)[i]);
 			break;
 		}
--- diff/drivers/char/drm/drm_fops.h	2003-10-09 09:47:16.000000000 +0100
+++ source/drivers/char/drm/drm_fops.h	2004-02-23 13:56:40.000000000 +0000
@@ -72,6 +72,8 @@ int DRM(open_helper)(struct inode *inode
 	priv->authenticated = capable(CAP_SYS_ADMIN);
 	priv->lock_count    = 0;
 
+	DRIVER_OPEN_HELPER( priv, dev );
+
 	down(&dev->struct_sem);
 	if (!dev->file_last) {
 		priv->next	= NULL;
--- diff/drivers/char/drm/drm_ioctl.h	2003-07-22 18:54:27.000000000 +0100
+++ source/drivers/char/drm/drm_ioctl.h	2004-02-23 13:56:40.000000000 +0000
@@ -35,69 +35,7 @@
 
 #include "drmP.h"
 
-
-/**
- * Get interrupt from bus id.
- * 
- * \param inode device inode.
- * \param filp file pointer.
- * \param cmd command.
- * \param arg user argument, pointing to a drm_irq_busid structure.
- * \return zero on success or a negative number on failure.
- * 
- * Finds the PCI device with the specified bus id and gets its IRQ number.
- */
-int DRM(irq_busid)(struct inode *inode, struct file *filp,
-		   unsigned int cmd, unsigned long arg)
-{
-	drm_irq_busid_t p;
-	struct pci_dev	*dev;
-
-	if (copy_from_user(&p, (drm_irq_busid_t *)arg, sizeof(p)))
-		return -EFAULT;
-#ifdef __alpha__
-	{
-		int domain = p.busnum >> 8;
-		p.busnum &= 0xff;
-
-		/*
-		 * Find the hose the device is on (the domain number is the
-		 * hose index) and offset the bus by the root bus of that
-		 * hose.
-		 */
-                for(dev = pci_find_device(PCI_ANY_ID,PCI_ANY_ID,NULL);
-                    dev;
-                    dev = pci_find_device(PCI_ANY_ID,PCI_ANY_ID,dev)) {
-			struct pci_controller *hose = dev->sysdata;
-			
-			if (hose->index == domain) {
-				p.busnum += hose->bus->number;
-				break;
-			}
-		}
-	}
-#endif
-	dev = pci_find_slot(p.busnum, PCI_DEVFN(p.devnum, p.funcnum));
-	if (!dev) {
-		DRM_ERROR("pci_find_slot failed for %d:%d:%d\n",
-			  p.busnum, p.devnum, p.funcnum);
-		p.irq = 0;
-		goto out;
-	}			
-	if (pci_enable_device(dev) != 0) {
-		DRM_ERROR("pci_enable_device failed for %d:%d:%d\n",
-			  p.busnum, p.devnum, p.funcnum);
-		p.irq = 0;
-		goto out;
-	}		
-	p.irq = dev->irq;
- out:
-	DRM_DEBUG("%d:%d:%d => IRQ %d\n",
-		  p.busnum, p.devnum, p.funcnum, p.irq);
-	if (copy_to_user((drm_irq_busid_t *)arg, &p, sizeof(p)))
-		return -EFAULT;
-	return 0;
-}
+#include <linux/pci.h>
 
 /**
  * Get the bus id.
@@ -138,8 +76,10 @@ int DRM(getunique)(struct inode *inode, 
  * \param arg user argument, pointing to a drm_unique structure.
  * \return zero on success or a negative number on failure.
  *
- * Copies the bus id from userspace into drm_device::unique, and searches for
- * the respective PCI device, updating drm_device::pdev.
+ * Copies the bus id from userspace into drm_device::unique, and verifies that
+ * it matches the device this DRM is attached to (EINVAL otherwise).  Deprecated
+ * in interface version 1.1 and will return EBUSY when setversion has requested
+ * version 1.1 or greater.
  */
 int DRM(setunique)(struct inode *inode, struct file *filp,
 		   unsigned int cmd, unsigned long arg)
@@ -147,6 +87,7 @@ int DRM(setunique)(struct inode *inode, 
 	drm_file_t	 *priv	 = filp->private_data;
 	drm_device_t	 *dev	 = priv->dev;
 	drm_unique_t	 u;
+	int		 domain, bus, slot, func, ret;
 
 	if (dev->unique_len || dev->unique) return -EBUSY;
 
@@ -164,55 +105,42 @@ int DRM(setunique)(struct inode *inode, 
 
 	dev->devname = DRM(alloc)(strlen(dev->name) + strlen(dev->unique) + 2,
 				  DRM_MEM_DRIVER);
-	if(!dev->devname) {
-		DRM(free)(dev->devname, sizeof(*dev->devname), DRM_MEM_DRIVER);
+	if (!dev->devname)
 		return -ENOMEM;
-	}
+
 	sprintf(dev->devname, "%s@%s", dev->name, dev->unique);
 
-	do {
-		struct pci_dev *pci_dev;
-                int domain, b, d, f;
-                char *p;
- 
-                for(p = dev->unique; p && *p && *p != ':'; p++);
-                if (!p || !*p) break;
-                b = (int)simple_strtoul(p+1, &p, 10);
-                if (*p != ':') break;
-                d = (int)simple_strtoul(p+1, &p, 10);
-                if (*p != ':') break;
-                f = (int)simple_strtoul(p+1, &p, 10);
-                if (*p) break;
- 
-		domain = b >> 8;
-		b &= 0xff;
-
-#ifdef __alpha__
-		/*
-		 * Find the hose the device is on (the domain number is the
-		 * hose index) and offset the bus by the root bus of that
-		 * hose.
-		 */
-                for(pci_dev = pci_find_device(PCI_ANY_ID,PCI_ANY_ID,NULL);
-                    pci_dev;
-                    pci_dev = pci_find_device(PCI_ANY_ID,PCI_ANY_ID,pci_dev)) {
-			struct pci_controller *hose = pci_dev->sysdata;
-			
-			if (hose->index == domain) {
-				b += hose->bus->number;
-				break;
-			}
-		}
-#endif
+	/* Return error if the busid submitted doesn't match the device's actual
+	 * busid.
+	 */
+	ret = sscanf(dev->unique, "PCI:%d:%d:%d", &bus, &slot, &func);
+	if (ret != 3)
+		return DRM_ERR(EINVAL);
+	domain = bus >> 8;
+	bus &= 0xff;
+	
+	if ((domain != dev->pci_domain) ||
+	    (bus != dev->pci_bus) ||
+	    (slot != dev->pci_slot) ||
+	    (func != dev->pci_func))
+		return -EINVAL;
 
-                pci_dev = pci_find_slot(b, PCI_DEVFN(d,f));
-                if (pci_dev) {
-			dev->pdev = pci_dev;
-#ifdef __alpha__
-			dev->hose = pci_dev->sysdata;
-#endif
-		}
-        } while(0);
+	return 0;
+}
+
+static int
+DRM(set_busid)(drm_device_t *dev)
+{
+	if (dev->unique != NULL)
+		return EBUSY;
+
+	dev->unique_len = 20;
+	dev->unique = DRM(alloc)(dev->unique_len + 1, DRM_MEM_DRIVER);
+	if (dev->unique == NULL)
+		return ENOMEM;
+
+	snprintf(dev->unique, dev->unique_len, "pci:%04x:%02x:%02x.%d",
+		dev->pci_domain, dev->pci_bus, dev->pci_slot, dev->pci_func);
 
 	return 0;
 }
@@ -363,3 +291,48 @@ int DRM(getstats)( struct inode *inode, 
 		return -EFAULT;
 	return 0;
 }
+
+#define DRM_IF_MAJOR	1
+#define DRM_IF_MINOR	2
+
+int DRM(setversion)(DRM_IOCTL_ARGS)
+{
+	DRM_DEVICE;
+	drm_set_version_t sv;
+	drm_set_version_t retv;
+	int if_version;
+
+	DRM_COPY_FROM_USER_IOCTL(sv, (drm_set_version_t *)data, sizeof(sv));
+
+	retv.drm_di_major = DRM_IF_MAJOR;
+	retv.drm_di_minor = DRM_IF_MINOR;
+	retv.drm_dd_major = DRIVER_MAJOR;
+	retv.drm_dd_minor = DRIVER_MINOR;
+
+	DRM_COPY_TO_USER_IOCTL((drm_set_version_t *)data, retv, sizeof(sv));
+
+	if (sv.drm_di_major != -1) {
+		if (sv.drm_di_major != DRM_IF_MAJOR ||
+		    sv.drm_di_minor < 0 || sv.drm_di_minor > DRM_IF_MINOR)
+			return EINVAL;
+		if_version = DRM_IF_VERSION(sv.drm_di_major, sv.drm_dd_minor);
+		dev->if_version = DRM_MAX(if_version, dev->if_version);
+		if (sv.drm_di_minor >= 1) {
+			/*
+			 * Version 1.1 includes tying of DRM to specific device
+			 */
+			DRM(set_busid)(dev);
+		}
+	}
+
+	if (sv.drm_dd_major != -1) {
+		if (sv.drm_dd_major != DRIVER_MAJOR ||
+		    sv.drm_dd_minor < 0 || sv.drm_dd_minor > DRIVER_MINOR)
+			return EINVAL;
+#ifdef DRIVER_SETVERSION
+		DRIVER_SETVERSION(dev, &sv);
+#endif
+	}
+	return 0;
+}
+
--- diff/drivers/char/drm/drm_os_linux.h	2003-09-30 15:46:12.000000000 +0100
+++ source/drivers/char/drm/drm_os_linux.h	2004-02-23 13:56:40.000000000 +0000
@@ -62,8 +62,12 @@
 	verify_area( VERIFY_READ, uaddr, size )
 #define DRM_COPY_FROM_USER_UNCHECKED(arg1, arg2, arg3) 	\
 	__copy_from_user(arg1, arg2, arg3)
+#define DRM_COPY_TO_USER_UNCHECKED(arg1, arg2, arg3)	\
+	__copy_to_user(arg1, arg2, arg3)
 #define DRM_GET_USER_UNCHECKED(val, uaddr)		\
 	__get_user(val, uaddr)
+#define DRM_PUT_USER_UNCHECKED(uaddr, val)		\
+	__put_user(val, uaddr)
 
 
 /** 'malloc' without the overhead of DRM(alloc)() */
@@ -71,6 +75,8 @@
 /** 'free' without the overhead of DRM(free)() */
 #define DRM_FREE(x,size) kfree(x)
 
+#define DRM_GET_PRIV_WITH_RETURN(_priv, _filp) _priv = _filp->private_data
+
 /** 
  * Get the pointer to the SAREA.
  *
--- diff/drivers/char/drm/gamma.h	2003-05-21 11:50:14.000000000 +0100
+++ source/drivers/char/drm/gamma.h	2004-02-23 13:56:40.000000000 +0000
@@ -53,6 +53,10 @@
 	[DRM_IOCTL_NR(DRM_IOCTL_GAMMA_INIT)] = { gamma_dma_init,  1, 1 }, \
 	[DRM_IOCTL_NR(DRM_IOCTL_GAMMA_COPY)] = { gamma_dma_copy,  1, 1 }
 
+#define DRIVER_PCI_IDS							\
+	{0x3d3d, 0x0008, 0, "3DLabs GLINT Gamma G1"},			\
+	{0, 0, 0, NULL}
+
 #define IOCTL_TABLE_NAME	DRM(ioctls)
 #define IOCTL_FUNC_NAME 	DRM(ioctl)
 
@@ -104,8 +108,8 @@
 	return 0;							\
 } while (0)
 
-#define __HAVE_DMA_IRQ			1
-#define __HAVE_DMA_IRQ_BH		1
+#define __HAVE_IRQ			1
+#define __HAVE_IRQ_BH			1
 
 #define DRIVER_AGP_BUFFERS_MAP( dev )					\
 	((drm_gamma_private_t *)((dev)->dev_private))->buffers
--- diff/drivers/char/drm/gamma_dma.c	2003-09-30 15:46:12.000000000 +0100
+++ source/drivers/char/drm/gamma_dma.c	2004-02-23 13:56:40.000000000 +0000
@@ -116,7 +116,7 @@ static inline int gamma_dma_is_ready(drm
 	return (!GAMMA_READ(GAMMA_DMACOUNT));
 }
 
-irqreturn_t gamma_dma_service( DRM_IRQ_ARGS )
+irqreturn_t gamma_irq_handler( DRM_IRQ_ARGS )
 {
 	drm_device_t	 *dev = (drm_device_t *)arg;
 	drm_device_dma_t *dma = dev->dma;
@@ -262,7 +262,7 @@ static void gamma_dma_timer_bh(unsigned 
 	gamma_dma_schedule((drm_device_t *)dev, 0);
 }
 
-void gamma_dma_immediate_bh(void *dev)
+void gamma_irq_immediate_bh(void *dev)
 {
 	gamma_dma_schedule(dev, 0);
 }
@@ -656,12 +656,12 @@ int gamma_do_cleanup_dma( drm_device_t *
 {
 	DRM_DEBUG( "%s\n", __FUNCTION__ );
 
-#if _HAVE_DMA_IRQ
+#if __HAVE_IRQ
 	/* Make sure interrupts are disabled here because the uninstall ioctl
 	 * may not have been called from userspace and after dev_private
 	 * is freed, it's too late.
 	 */
-	if ( dev->irq ) DRM(irq_uninstall)(dev);
+	if ( dev->irq_enabled ) DRM(irq_uninstall)(dev);
 #endif
 
 	if ( dev->dev_private ) {
--- diff/drivers/char/drm/gamma_drv.c	2003-05-21 11:50:14.000000000 +0100
+++ source/drivers/char/drm/gamma_drv.c	2004-02-23 13:56:40.000000000 +0000
@@ -48,6 +48,7 @@
 #include "drm_fops.h"
 #include "drm_init.h"
 #include "drm_ioctl.h"
+#include "drm_irq.h"
 #include "gamma_lists.h"        /* NOTE */
 #include "drm_lock.h"
 #include "gamma_lock.h"		/* NOTE */
--- diff/drivers/char/drm/i810.h	2003-08-26 10:00:52.000000000 +0100
+++ source/drivers/char/drm/i810.h	2004-02-23 13:56:40.000000000 +0000
@@ -77,7 +77,14 @@
 	[DRM_IOCTL_NR(DRM_IOCTL_I810_MC)]      = { i810_dma_mc,     1, 1 }, \
 	[DRM_IOCTL_NR(DRM_IOCTL_I810_RSTATUS)] = { i810_rstatus,    1, 0 }, \
 	[DRM_IOCTL_NR(DRM_IOCTL_I810_FLIP)] =    { i810_flip_bufs,  1, 0 }
- 
+
+#define DRIVER_PCI_IDS							\
+	{0x8086, 0x7121, 0, "Intel i810 GMCH"},				\
+	{0x8086, 0x7123, 0, "Intel i810-DC100 GMCH"},			\
+	{0x8086, 0x7125, 0, "Intel i810E GMCH"},			\
+	{0x8086, 0x1132, 0, "Intel i815 GMCH"},				\
+	{0, 0, 0, NULL}
+
 
 #define __HAVE_COUNTERS         4
 #define __HAVE_COUNTER6         _DRM_STAT_IRQ
@@ -112,7 +119,7 @@
  * a noop stub is generated for compatibility.
  */
 /* XXX: Add vblank support? */
-#define __HAVE_DMA_IRQ		0
+#define __HAVE_IRQ		0
 
 /* Buffer customization:
  */
--- diff/drivers/char/drm/i810_dma.c	2003-09-30 15:46:12.000000000 +0100
+++ source/drivers/char/drm/i810_dma.c	2004-02-23 13:56:40.000000000 +0000
@@ -53,41 +53,41 @@
 
 static inline void i810_print_status_page(drm_device_t *dev)
 {
-   	drm_device_dma_t *dma = dev->dma;
-      	drm_i810_private_t *dev_priv = dev->dev_private;
+	drm_device_dma_t *dma = dev->dma;
+	drm_i810_private_t *dev_priv = dev->dev_private;
 	u32 *temp = dev_priv->hw_status_page;
-   	int i;
+	int i;
 
-   	DRM_DEBUG(  "hw_status: Interrupt Status : %x\n", temp[0]);
-   	DRM_DEBUG(  "hw_status: LpRing Head ptr : %x\n", temp[1]);
-   	DRM_DEBUG(  "hw_status: IRing Head ptr : %x\n", temp[2]);
-      	DRM_DEBUG(  "hw_status: Reserved : %x\n", temp[3]);
+	DRM_DEBUG(  "hw_status: Interrupt Status : %x\n", temp[0]);
+	DRM_DEBUG(  "hw_status: LpRing Head ptr : %x\n", temp[1]);
+	DRM_DEBUG(  "hw_status: IRing Head ptr : %x\n", temp[2]);
+	DRM_DEBUG(  "hw_status: Reserved : %x\n", temp[3]);
 	DRM_DEBUG(  "hw_status: Last Render: %x\n", temp[4]);
-   	DRM_DEBUG(  "hw_status: Driver Counter : %d\n", temp[5]);
-   	for(i = 6; i < dma->buf_count + 6; i++) {
-	   	DRM_DEBUG( "buffer status idx : %d used: %d\n", i - 6, temp[i]);
+	DRM_DEBUG(  "hw_status: Driver Counter : %d\n", temp[5]);
+	for(i = 6; i < dma->buf_count + 6; i++) {
+		DRM_DEBUG( "buffer status idx : %d used: %d\n", i - 6, temp[i]);
 	}
 }
 
 static drm_buf_t *i810_freelist_get(drm_device_t *dev)
 {
-   	drm_device_dma_t *dma = dev->dma;
+	drm_device_dma_t *dma = dev->dma;
 	int		 i;
-   	int 		 used;
+	int		 used;
 
 	/* Linear search might not be the best solution */
 
-   	for (i = 0; i < dma->buf_count; i++) {
-	   	drm_buf_t *buf = dma->buflist[ i ];
-	   	drm_i810_buf_priv_t *buf_priv = buf->dev_private;
+	for (i = 0; i < dma->buf_count; i++) {
+		drm_buf_t *buf = dma->buflist[ i ];
+		drm_i810_buf_priv_t *buf_priv = buf->dev_private;
 		/* In use is already a pointer */
-	   	used = cmpxchg(buf_priv->in_use, I810_BUF_FREE,
+		used = cmpxchg(buf_priv->in_use, I810_BUF_FREE,
 			       I810_BUF_CLIENT);
 		if (used == I810_BUF_FREE) {
 			return buf;
 		}
 	}
-   	return NULL;
+	return NULL;
 }
 
 /* This should only be called if the buffer is not sent to the hardware
@@ -96,17 +96,17 @@ static drm_buf_t *i810_freelist_get(drm_
 
 static int i810_freelist_put(drm_device_t *dev, drm_buf_t *buf)
 {
-   	drm_i810_buf_priv_t *buf_priv = buf->dev_private;
-   	int used;
+	drm_i810_buf_priv_t *buf_priv = buf->dev_private;
+	int used;
 
-   	/* In use is already a pointer */
-   	used = cmpxchg(buf_priv->in_use, I810_BUF_CLIENT, I810_BUF_FREE);
+	/* In use is already a pointer */
+	used = cmpxchg(buf_priv->in_use, I810_BUF_CLIENT, I810_BUF_FREE);
 	if (used != I810_BUF_CLIENT) {
-	   	DRM_ERROR("Freeing buffer thats not in use : %d\n", buf->idx);
-	   	return -EINVAL;
+		DRM_ERROR("Freeing buffer thats not in use : %d\n", buf->idx);
+		return -EINVAL;
 	}
 
-   	return 0;
+	return 0;
 }
 
 static struct file_operations i810_buffer_fops = {
@@ -135,7 +135,7 @@ int i810_mmap_buffers(struct file *filp,
 	vma->vm_flags |= (VM_IO | VM_DONTCOPY);
 	vma->vm_file = filp;
 
-   	buf_priv->currently_mapped = I810_BUF_MAPPED;
+	buf_priv->currently_mapped = I810_BUF_MAPPED;
 	unlock_kernel();
 
 	if (remap_page_range(DRM_RPR_ARG(vma) vma->vm_start,
@@ -150,8 +150,8 @@ static int i810_map_buffer(drm_buf_t *bu
 	drm_file_t	  *priv	  = filp->private_data;
 	drm_device_t	  *dev	  = priv->dev;
 	drm_i810_buf_priv_t *buf_priv = buf->dev_private;
-      	drm_i810_private_t *dev_priv = dev->dev_private;
-   	struct file_operations *old_fops;
+	drm_i810_private_t *dev_priv = dev->dev_private;
+	struct file_operations *old_fops;
 	int retcode = 0;
 
 	if (buf_priv->currently_mapped == I810_BUF_MAPPED) 
@@ -192,8 +192,8 @@ static int i810_unmap_buffer(drm_buf_t *
 			    (size_t) buf->total);
 	up_write(&current->mm->mmap_sem);
 
-   	buf_priv->currently_mapped = I810_BUF_UNMAPPED;
-   	buf_priv->virtual = 0;
+	buf_priv->currently_mapped = I810_BUF_UNMAPPED;
+	buf_priv->virtual = 0;
 
 	return retcode;
 }
@@ -208,22 +208,22 @@ static int i810_dma_get_buffer(drm_devic
 	buf = i810_freelist_get(dev);
 	if (!buf) {
 		retcode = -ENOMEM;
-	   	DRM_DEBUG("retcode=%d\n", retcode);
+		DRM_DEBUG("retcode=%d\n", retcode);
 		return retcode;
 	}
 
 	retcode = i810_map_buffer(buf, filp);
 	if (retcode) {
 		i810_freelist_put(dev, buf);
-	   	DRM_ERROR("mapbuf failed, retcode %d\n", retcode);
+		DRM_ERROR("mapbuf failed, retcode %d\n", retcode);
 		return retcode;
 	}
 	buf->filp = filp;
 	buf_priv = buf->dev_private;
 	d->granted = 1;
-   	d->request_idx = buf->idx;
-   	d->request_size = buf->total;
-   	d->virtual = buf_priv->virtual;
+	d->request_idx = buf->idx;
+	d->request_size = buf->total;
+	d->virtual = buf_priv->virtual;
 
 	return retcode;
 }
@@ -232,33 +232,33 @@ int i810_dma_cleanup(drm_device_t *dev)
 {
 	drm_device_dma_t *dma = dev->dma;
 
-#if _HAVE_DMA_IRQ
+#if __HAVE_IRQ
 	/* Make sure interrupts are disabled here because the uninstall ioctl
 	 * may not have been called from userspace and after dev_private
 	 * is freed, it's too late.
 	 */
-	if (dev->irq) DRM(irq_uninstall)(dev);
+	if (dev->irq_enabled) DRM(irq_uninstall)(dev);
 #endif
 
 	if (dev->dev_private) {
 		int i;
-	   	drm_i810_private_t *dev_priv =
-	     		(drm_i810_private_t *) dev->dev_private;
+		drm_i810_private_t *dev_priv =
+			(drm_i810_private_t *) dev->dev_private;
 
 		if (dev_priv->ring.virtual_start) {
-		   	DRM(ioremapfree)((void *) dev_priv->ring.virtual_start,
+			DRM(ioremapfree)((void *) dev_priv->ring.virtual_start,
 					 dev_priv->ring.Size, dev);
 		}
-	   	if (dev_priv->hw_status_page) {
-		   	pci_free_consistent(dev->pdev, PAGE_SIZE,
+		if (dev_priv->hw_status_page) {
+			pci_free_consistent(dev->pdev, PAGE_SIZE,
 					    dev_priv->hw_status_page,
 					    dev_priv->dma_status_page);
-		   	/* Need to rewrite hardware status page */
-		   	I810_WRITE(0x02080, 0x1ffff000);
+			/* Need to rewrite hardware status page */
+			I810_WRITE(0x02080, 0x1ffff000);
 		}
-	   	DRM(free)(dev->dev_private, sizeof(drm_i810_private_t),
+		DRM(free)(dev->dev_private, sizeof(drm_i810_private_t),
 			 DRM_MEM_DRIVER);
-	   	dev->dev_private = NULL;
+		dev->dev_private = NULL;
 
 		for (i = 0; i < dma->buf_count; i++) {
 			drm_buf_t *buf = dma->buflist[ i ];
@@ -267,73 +267,73 @@ int i810_dma_cleanup(drm_device_t *dev)
 				DRM(ioremapfree)(buf_priv->kernel_virtual, buf->total, dev);
 		}
 	}
-   	return 0;
+	return 0;
 }
 
 static int i810_wait_ring(drm_device_t *dev, int n)
 {
-   	drm_i810_private_t *dev_priv = dev->dev_private;
-   	drm_i810_ring_buffer_t *ring = &(dev_priv->ring);
-   	int iters = 0;
-   	unsigned long end;
+	drm_i810_private_t *dev_priv = dev->dev_private;
+	drm_i810_ring_buffer_t *ring = &(dev_priv->ring);
+	int iters = 0;
+	unsigned long end;
 	unsigned int last_head = I810_READ(LP_RING + RING_HEAD) & HEAD_ADDR;
 
 	end = jiffies + (HZ*3);
-   	while (ring->space < n) {
-	   	ring->head = I810_READ(LP_RING + RING_HEAD) & HEAD_ADDR;
-	   	ring->space = ring->head - (ring->tail+8);
+	while (ring->space < n) {
+		ring->head = I810_READ(LP_RING + RING_HEAD) & HEAD_ADDR;
+		ring->space = ring->head - (ring->tail+8);
 		if (ring->space < 0) ring->space += ring->Size;
-	   
+
 		if (ring->head != last_head) {
 			end = jiffies + (HZ*3);
 			last_head = ring->head;
 		}
 	  
-	   	iters++;
+		iters++;
 		if (time_before(end, jiffies)) {
-		   	DRM_ERROR("space: %d wanted %d\n", ring->space, n);
-		   	DRM_ERROR("lockup\n");
-		   	goto out_wait_ring;
+			DRM_ERROR("space: %d wanted %d\n", ring->space, n);
+			DRM_ERROR("lockup\n");
+			goto out_wait_ring;
 		}
 		udelay(1);
 	}
 
 out_wait_ring:
-   	return iters;
+	return iters;
 }
 
 static void i810_kernel_lost_context(drm_device_t *dev)
 {
-      	drm_i810_private_t *dev_priv = dev->dev_private;
-   	drm_i810_ring_buffer_t *ring = &(dev_priv->ring);
+	drm_i810_private_t *dev_priv = dev->dev_private;
+	drm_i810_ring_buffer_t *ring = &(dev_priv->ring);
 
-   	ring->head = I810_READ(LP_RING + RING_HEAD) & HEAD_ADDR;
-     	ring->tail = I810_READ(LP_RING + RING_TAIL);
-     	ring->space = ring->head - (ring->tail+8);
-     	if (ring->space < 0) ring->space += ring->Size;
+	ring->head = I810_READ(LP_RING + RING_HEAD) & HEAD_ADDR;
+	ring->tail = I810_READ(LP_RING + RING_TAIL);
+	ring->space = ring->head - (ring->tail+8);
+	if (ring->space < 0) ring->space += ring->Size;
 }
 
 static int i810_freelist_init(drm_device_t *dev, drm_i810_private_t *dev_priv)
 {
-      	drm_device_dma_t *dma = dev->dma;
-   	int my_idx = 24;
-   	u32 *hw_status = (u32 *)(dev_priv->hw_status_page + my_idx);
-   	int i;
+	drm_device_dma_t *dma = dev->dma;
+	int my_idx = 24;
+	u32 *hw_status = (u32 *)(dev_priv->hw_status_page + my_idx);
+	int i;
 
 	if (dma->buf_count > 1019) {
-	   	/* Not enough space in the status page for the freelist */
-	   	return -EINVAL;
+		/* Not enough space in the status page for the freelist */
+		return -EINVAL;
 	}
 
-   	for (i = 0; i < dma->buf_count; i++) {
-	   	drm_buf_t *buf = dma->buflist[ i ];
-	   	drm_i810_buf_priv_t *buf_priv = buf->dev_private;
+	for (i = 0; i < dma->buf_count; i++) {
+		drm_buf_t *buf = dma->buflist[ i ];
+		drm_i810_buf_priv_t *buf_priv = buf->dev_private;
 
-	   	buf_priv->in_use = hw_status++;
-	   	buf_priv->my_use_idx = my_idx;
-	   	my_idx += 4;
+		buf_priv->in_use = hw_status++;
+		buf_priv->my_use_idx = my_idx;
+		my_idx += 4;
 
-	   	*buf_priv->in_use = I810_BUF_FREE;
+		*buf_priv->in_use = I810_BUF_FREE;
 
 		buf_priv->kernel_virtual = DRM(ioremap)(buf->bus_address,
 							buf->total, dev);
@@ -347,7 +347,7 @@ static int i810_dma_initialize(drm_devic
 {
 	struct list_head *list;
 
-   	memset(dev_priv, 0, sizeof(drm_i810_private_t));
+	memset(dev_priv, 0, sizeof(drm_i810_private_t));
 
 	list_for_each(list, &dev->maplist->head) {
 		drm_map_list_t *r_list = list_entry(list, drm_map_list_t, head);
@@ -355,51 +355,51 @@ static int i810_dma_initialize(drm_devic
 		    r_list->map->type == _DRM_SHM &&
 		    r_list->map->flags & _DRM_CONTAINS_LOCK ) {
 			dev_priv->sarea_map = r_list->map;
- 			break;
- 		}
- 	}
+			break;
+		}
+	}
 	if (!dev_priv->sarea_map) {
 		dev->dev_private = (void *)dev_priv;
-	   	i810_dma_cleanup(dev);
-	   	DRM_ERROR("can not find sarea!\n");
-	   	return -EINVAL;
+		i810_dma_cleanup(dev);
+		DRM_ERROR("can not find sarea!\n");
+		return -EINVAL;
 	}
 	DRM_FIND_MAP( dev_priv->mmio_map, init->mmio_offset );
 	if (!dev_priv->mmio_map) {
 		dev->dev_private = (void *)dev_priv;
-	   	i810_dma_cleanup(dev);
-	   	DRM_ERROR("can not find mmio map!\n");
-	   	return -EINVAL;
+		i810_dma_cleanup(dev);
+		DRM_ERROR("can not find mmio map!\n");
+		return -EINVAL;
 	}
 	DRM_FIND_MAP( dev_priv->buffer_map, init->buffers_offset );
 	if (!dev_priv->buffer_map) {
 		dev->dev_private = (void *)dev_priv;
-	   	i810_dma_cleanup(dev);
-	   	DRM_ERROR("can not find dma buffer map!\n");
-	   	return -EINVAL;
+		i810_dma_cleanup(dev);
+		DRM_ERROR("can not find dma buffer map!\n");
+		return -EINVAL;
 	}
 
 	dev_priv->sarea_priv = (drm_i810_sarea_t *)
 		((u8 *)dev_priv->sarea_map->handle +
 		 init->sarea_priv_offset);
 
-   	dev_priv->ring.Start = init->ring_start;
-   	dev_priv->ring.End = init->ring_end;
-   	dev_priv->ring.Size = init->ring_size;
+	dev_priv->ring.Start = init->ring_start;
+	dev_priv->ring.End = init->ring_end;
+	dev_priv->ring.Size = init->ring_size;
 
-   	dev_priv->ring.virtual_start = DRM(ioremap)(dev->agp->base +
+	dev_priv->ring.virtual_start = DRM(ioremap)(dev->agp->base +
 						    init->ring_start,
 						    init->ring_size, dev);
 
-   	if (dev_priv->ring.virtual_start == NULL) {
+	if (dev_priv->ring.virtual_start == NULL) {
 		dev->dev_private = (void *) dev_priv;
-	   	i810_dma_cleanup(dev);
-	   	DRM_ERROR("can not ioremap virtual address for"
+		i810_dma_cleanup(dev);
+		DRM_ERROR("can not ioremap virtual address for"
 			  " ring buffer\n");
-	   	return -ENOMEM;
+		return -ENOMEM;
 	}
 
-   	dev_priv->ring.tail_mask = dev_priv->ring.Size - 1;
+	dev_priv->ring.tail_mask = dev_priv->ring.Size - 1;
 
 	dev_priv->w = init->w;
 	dev_priv->h = init->h;
@@ -415,33 +415,33 @@ static int i810_dma_initialize(drm_devic
 	dev_priv->back_di1 = init->back_offset | init->pitch_bits;
 	dev_priv->zi1 = init->depth_offset | init->pitch_bits;
 
-   	/* Program Hardware Status Page */
-   	dev_priv->hw_status_page =
+	/* Program Hardware Status Page */
+	dev_priv->hw_status_page =
 		pci_alloc_consistent(dev->pdev, PAGE_SIZE,
 						&dev_priv->dma_status_page);
-   	if (!dev_priv->hw_status_page) {
+	if (!dev_priv->hw_status_page) {
 		dev->dev_private = (void *)dev_priv;
 		i810_dma_cleanup(dev);
 		DRM_ERROR("Can not allocate hardware status page\n");
 		return -ENOMEM;
 	}
-   	memset(dev_priv->hw_status_page, 0, PAGE_SIZE);
-   	DRM_DEBUG("hw status page @ %p\n", dev_priv->hw_status_page);
+	memset(dev_priv->hw_status_page, 0, PAGE_SIZE);
+	DRM_DEBUG("hw status page @ %p\n", dev_priv->hw_status_page);
 
 	I810_WRITE(0x02080, dev_priv->dma_status_page);
-   	DRM_DEBUG("Enabled hardware status page\n");
+	DRM_DEBUG("Enabled hardware status page\n");
 
-   	/* Now we need to init our freelist */
+	/* Now we need to init our freelist */
 	if (i810_freelist_init(dev, dev_priv) != 0) {
 		dev->dev_private = (void *)dev_priv;
-	   	i810_dma_cleanup(dev);
-	   	DRM_ERROR("Not enough space in the status page for"
+		i810_dma_cleanup(dev);
+		DRM_ERROR("Not enough space in the status page for"
 			  " the freelist\n");
-	   	return -ENOMEM;
+		return -ENOMEM;
 	}
 	dev->dev_private = (void *)dev_priv;
 
-   	return 0;
+	return 0;
 }
 
 /* i810 DRM version 1.1 used a smaller init structure with different
@@ -476,12 +476,12 @@ int i810_dma_init_compat(drm_i810_init_t
 
 		/* This is a v1.1 client, fix the params */
 		DRM_INFO("Using PRE v1.2 init.\n");
-	 	init->pitch_bits = init->h;
-	 	init->pitch = init->w;
-	 	init->h = init->overlay_physical;
-	 	init->w = init->overlay_offset;
-	 	init->overlay_physical = 0;
-	 	init->overlay_offset = 0;
+		init->pitch_bits = init->h;
+		init->pitch = init->w;
+		init->h = init->overlay_physical;
+		init->w = init->overlay_offset;
+		init->overlay_physical = 0;
+		init->overlay_offset = 0;
 	}
 
 	return 0;
@@ -490,55 +490,55 @@ int i810_dma_init_compat(drm_i810_init_t
 int i810_dma_init(struct inode *inode, struct file *filp,
 		  unsigned int cmd, unsigned long arg)
 {
-   	drm_file_t *priv = filp->private_data;
-   	drm_device_t *dev = priv->dev;
-   	drm_i810_private_t *dev_priv;
-   	drm_i810_init_t init;
-   	int retcode = 0;
+	drm_file_t *priv = filp->private_data;
+	drm_device_t *dev = priv->dev;
+	drm_i810_private_t *dev_priv;
+	drm_i810_init_t init;
+	int retcode = 0;
 
 	/* Get only the init func */
 	if (copy_from_user(&init, (void *)arg, sizeof(drm_i810_init_func_t))) 
 		return -EFAULT;
 
-   	switch(init.func) {
-	 	case I810_INIT_DMA:
-	 	       	/* This case is for backward compatibility. It
+	switch(init.func) {
+		case I810_INIT_DMA:
+			/* This case is for backward compatibility. It
 			 * handles XFree 4.1.0 and 4.2.0, and has to
 			 * do some parameter checking as described below.
 			 * It will someday go away.
 			 */
 			retcode = i810_dma_init_compat(&init, arg);
-			if (retcode)
+			if (retcode) 
 				return retcode;
 
-	   		dev_priv = DRM(alloc)(sizeof(drm_i810_private_t),
+			dev_priv = DRM(alloc)(sizeof(drm_i810_private_t),
 					     DRM_MEM_DRIVER);
-	   		if (dev_priv == NULL)
-				return -ENOMEM;
-	   		retcode = i810_dma_initialize(dev, dev_priv, &init);
+			if (dev_priv == NULL)
+			       return -ENOMEM;
+			retcode = i810_dma_initialize(dev, dev_priv, &init);
 			break;
 
 		default:
-	 	case I810_INIT_DMA_1_4:
+		case I810_INIT_DMA_1_4:
 			DRM_INFO("Using v1.4 init.\n");
-  			if (copy_from_user(&init, (drm_i810_init_t *)arg,
+			if (copy_from_user(&init, (drm_i810_init_t *)arg,
 					  sizeof(drm_i810_init_t))) {
 				return -EFAULT;
 			}
-	   		dev_priv = DRM(alloc)(sizeof(drm_i810_private_t),
+			dev_priv = DRM(alloc)(sizeof(drm_i810_private_t),
 					     DRM_MEM_DRIVER);
 			if (dev_priv == NULL) 
 				return -ENOMEM;
-	   		retcode = i810_dma_initialize(dev, dev_priv, &init);
+			retcode = i810_dma_initialize(dev, dev_priv, &init);
 			break;
 
-	 	case I810_CLEANUP_DMA:
-		        DRM_INFO("DMA Cleanup\n");
-	   		retcode = i810_dma_cleanup(dev);
-              	   	break;
+		case I810_CLEANUP_DMA:
+			DRM_INFO("DMA Cleanup\n");
+			retcode = i810_dma_cleanup(dev);
+			break;
 	}
 
-   	return retcode;
+	return retcode;
 }
 
 
@@ -552,7 +552,7 @@ int i810_dma_init(struct inode *inode, s
 static void i810EmitContextVerified( drm_device_t *dev,
 				     volatile unsigned int *code )
 {
-   	drm_i810_private_t *dev_priv = dev->dev_private;
+	drm_i810_private_t *dev_priv = dev->dev_private;
 	int i, j = 0;
 	unsigned int tmp;
 	RING_LOCALS;
@@ -586,7 +586,7 @@ static void i810EmitContextVerified( drm
 static void i810EmitTexVerified( drm_device_t *dev,
 				 volatile unsigned int *code )
 {
-   	drm_i810_private_t *dev_priv = dev->dev_private;
+	drm_i810_private_t *dev_priv = dev->dev_private;
 	int i, j = 0;
 	unsigned int tmp;
 	RING_LOCALS;
@@ -622,7 +622,7 @@ static void i810EmitTexVerified( drm_dev
 static void i810EmitDestVerified( drm_device_t *dev,
 				  volatile unsigned int *code )
 {
-   	drm_i810_private_t *dev_priv = dev->dev_private;
+	drm_i810_private_t *dev_priv = dev->dev_private;
 	unsigned int tmp;
 	RING_LOCALS;
 
@@ -658,8 +658,8 @@ static void i810EmitDestVerified( drm_de
 
 static void i810EmitState( drm_device_t *dev )
 {
-   	drm_i810_private_t *dev_priv = dev->dev_private;
-      	drm_i810_sarea_t *sarea_priv = dev_priv->sarea_priv;
+	drm_i810_private_t *dev_priv = dev->dev_private;
+	drm_i810_sarea_t *sarea_priv = dev_priv->sarea_priv;
 	unsigned int dirty = sarea_priv->dirty;
 	
 	DRM_DEBUG("%s %x\n", __FUNCTION__, dirty);
@@ -693,8 +693,8 @@ static void i810_dma_dispatch_clear( drm
 				     unsigned int clear_color,
 				     unsigned int clear_zval )
 {
-   	drm_i810_private_t *dev_priv = dev->dev_private;
-      	drm_i810_sarea_t *sarea_priv = dev_priv->sarea_priv;
+	drm_i810_private_t *dev_priv = dev->dev_private;
+	drm_i810_sarea_t *sarea_priv = dev_priv->sarea_priv;
 	int nbox = sarea_priv->nbox;
 	drm_clip_rect_t *pbox = sarea_priv->boxes;
 	int pitch = dev_priv->pitch;
@@ -703,17 +703,17 @@ static void i810_dma_dispatch_clear( drm
 	RING_LOCALS;
 	
 	if ( dev_priv->current_page == 1 ) {
-	        unsigned int tmp = flags;
-	       
+		unsigned int tmp = flags;
+
 		flags &= ~(I810_FRONT | I810_BACK);
 		if (tmp & I810_FRONT) flags |= I810_BACK;
 		if (tmp & I810_BACK) flags |= I810_FRONT;
 	}
 
-  	i810_kernel_lost_context(dev);
+	i810_kernel_lost_context(dev);
 
-      	if (nbox > I810_NR_SAREA_CLIPRECTS)
-     		nbox = I810_NR_SAREA_CLIPRECTS;
+	if (nbox > I810_NR_SAREA_CLIPRECTS)
+		nbox = I810_NR_SAREA_CLIPRECTS;
 
 	for (i = 0 ; i < nbox ; i++, pbox++) {
 		unsigned int x = pbox->x1;
@@ -728,7 +728,7 @@ static void i810_dma_dispatch_clear( drm
 		    pbox->y2 > dev_priv->h)
 			continue;
 
-	   	if ( flags & I810_FRONT ) {
+		if ( flags & I810_FRONT ) {
 			BEGIN_LP_RING( 6 );
 			OUT_RING( BR00_BITBLT_CLIENT |
 				  BR00_OP_COLOR_BLT | 0x3 );
@@ -768,8 +768,8 @@ static void i810_dma_dispatch_clear( drm
 
 static void i810_dma_dispatch_swap( drm_device_t *dev )
 {
-   	drm_i810_private_t *dev_priv = dev->dev_private;
-      	drm_i810_sarea_t *sarea_priv = dev_priv->sarea_priv;
+	drm_i810_private_t *dev_priv = dev->dev_private;
+	drm_i810_sarea_t *sarea_priv = dev_priv->sarea_priv;
 	int nbox = sarea_priv->nbox;
 	drm_clip_rect_t *pbox = sarea_priv->boxes;
 	int pitch = dev_priv->pitch;
@@ -779,10 +779,10 @@ static void i810_dma_dispatch_swap( drm_
 
 	DRM_DEBUG("swapbuffers\n");
 
-  	i810_kernel_lost_context(dev);
+	i810_kernel_lost_context(dev);
 
-      	if (nbox > I810_NR_SAREA_CLIPRECTS)
-     		nbox = I810_NR_SAREA_CLIPRECTS;
+	if (nbox > I810_NR_SAREA_CLIPRECTS)
+		nbox = I810_NR_SAREA_CLIPRECTS;
 
 	for (i = 0 ; i < nbox; i++, pbox++)
 	{
@@ -820,19 +820,19 @@ static void i810_dma_dispatch_vertex(drm
 				     int discard,
 				     int used)
 {
-   	drm_i810_private_t *dev_priv = dev->dev_private;
+	drm_i810_private_t *dev_priv = dev->dev_private;
 	drm_i810_buf_priv_t *buf_priv = buf->dev_private;
-   	drm_i810_sarea_t *sarea_priv = dev_priv->sarea_priv;
-   	drm_clip_rect_t *box = sarea_priv->boxes;
-   	int nbox = sarea_priv->nbox;
+	drm_i810_sarea_t *sarea_priv = dev_priv->sarea_priv;
+	drm_clip_rect_t *box = sarea_priv->boxes;
+	int nbox = sarea_priv->nbox;
 	unsigned long address = (unsigned long)buf->bus_address;
 	unsigned long start = address - dev->agp->base;
 	int i = 0;
-   	RING_LOCALS;
+	RING_LOCALS;
 
-   	i810_kernel_lost_context(dev);
+	i810_kernel_lost_context(dev);
 
-   	if (nbox > I810_NR_SAREA_CLIPRECTS)
+	if (nbox > I810_NR_SAREA_CLIPRECTS)
 		nbox = I810_NR_SAREA_CLIPRECTS;
 
 	if (used > 4*1024)
@@ -898,7 +898,7 @@ static void i810_dma_dispatch_vertex(drm
 
 static void i810_dma_dispatch_flip( drm_device_t *dev )
 {
-        drm_i810_private_t *dev_priv = dev->dev_private;
+	drm_i810_private_t *dev_priv = dev->dev_private;
 	int pitch = dev_priv->pitch;
 	RING_LOCALS;
 
@@ -907,10 +907,10 @@ static void i810_dma_dispatch_flip( drm_
 		dev_priv->current_page,
 		dev_priv->sarea_priv->pf_current_page);
 	
-        i810_kernel_lost_context(dev);
+	i810_kernel_lost_context(dev);
 
 	BEGIN_LP_RING( 2 );
-   	OUT_RING( INST_PARSER_CLIENT | INST_OP_FLUSH | INST_FLUSH_MAP_CACHE ); 
+	OUT_RING( INST_PARSER_CLIENT | INST_OP_FLUSH | INST_FLUSH_MAP_CACHE ); 
 	OUT_RING( 0 );
 	ADVANCE_LP_RING();
 
@@ -945,44 +945,44 @@ static void i810_dma_dispatch_flip( drm_
 
 void i810_dma_quiescent(drm_device_t *dev)
 {
-      	drm_i810_private_t *dev_priv = dev->dev_private;
-   	RING_LOCALS;
+	drm_i810_private_t *dev_priv = dev->dev_private;
+	RING_LOCALS;
 
-/*  	printk("%s\n", __FUNCTION__); */
+/*	printk("%s\n", __FUNCTION__); */
 
-  	i810_kernel_lost_context(dev);
+	i810_kernel_lost_context(dev);
 
-   	BEGIN_LP_RING(4);
-   	OUT_RING( INST_PARSER_CLIENT | INST_OP_FLUSH | INST_FLUSH_MAP_CACHE );
-   	OUT_RING( CMD_REPORT_HEAD );
-      	OUT_RING( 0 );
-      	OUT_RING( 0 );
-   	ADVANCE_LP_RING();
+	BEGIN_LP_RING(4);
+	OUT_RING( INST_PARSER_CLIENT | INST_OP_FLUSH | INST_FLUSH_MAP_CACHE );
+	OUT_RING( CMD_REPORT_HEAD );
+	OUT_RING( 0 );
+	OUT_RING( 0 );
+	ADVANCE_LP_RING();
 
 	i810_wait_ring( dev, dev_priv->ring.Size - 8 );
 }
 
 static int i810_flush_queue(drm_device_t *dev)
 {
-   	drm_i810_private_t *dev_priv = dev->dev_private;
+	drm_i810_private_t *dev_priv = dev->dev_private;
 	drm_device_dma_t *dma = dev->dma;
-   	int i, ret = 0;
-   	RING_LOCALS;
+	int i, ret = 0;
+	RING_LOCALS;
 	
-/*  	printk("%s\n", __FUNCTION__); */
+/*	printk("%s\n", __FUNCTION__); */
 
-   	i810_kernel_lost_context(dev);
+	i810_kernel_lost_context(dev);
 
-   	BEGIN_LP_RING(2);
-      	OUT_RING( CMD_REPORT_HEAD );
-      	OUT_RING( 0 );
-      	ADVANCE_LP_RING();
+	BEGIN_LP_RING(2);
+	OUT_RING( CMD_REPORT_HEAD );
+	OUT_RING( 0 );
+	ADVANCE_LP_RING();
 
 	i810_wait_ring( dev, dev_priv->ring.Size - 8 );
 
-   	for (i = 0; i < dma->buf_count; i++) {
-	   	drm_buf_t *buf = dma->buflist[ i ];
-	   	drm_i810_buf_priv_t *buf_priv = buf->dev_private;
+	for (i = 0; i < dma->buf_count; i++) {
+		drm_buf_t *buf = dma->buflist[ i ];
+		drm_i810_buf_priv_t *buf_priv = buf->dev_private;
 
 		int used = cmpxchg(buf_priv->in_use, I810_BUF_HARDWARE,
 				   I810_BUF_FREE);
@@ -993,7 +993,7 @@ static int i810_flush_queue(drm_device_t
 			DRM_DEBUG("still on client\n");
 	}
 
-   	return ret;
+	return ret;
 }
 
 /* Must be called with the lock held */
@@ -1005,14 +1005,14 @@ void i810_reclaim_buffers(struct file *f
 	int		 i;
 
 	if (!dma) return;
-      	if (!dev->dev_private) return;
+	if (!dev->dev_private) return;
 	if (!dma->buflist) return;
 
-        i810_flush_queue(dev);
+	i810_flush_queue(dev);
 
 	for (i = 0; i < dma->buf_count; i++) {
-	   	drm_buf_t *buf = dma->buflist[ i ];
-	   	drm_i810_buf_priv_t *buf_priv = buf->dev_private;
+		drm_buf_t *buf = dma->buflist[ i ];
+		drm_i810_buf_priv_t *buf_priv = buf->dev_private;
 
 		if (buf->filp == filp && buf_priv) {
 			int used = cmpxchg(buf_priv->in_use, I810_BUF_CLIENT,
@@ -1021,7 +1021,7 @@ void i810_reclaim_buffers(struct file *f
 			if (used == I810_BUF_CLIENT)
 				DRM_DEBUG("reclaimed from client\n");
 			if (buf_priv->currently_mapped == I810_BUF_MAPPED)
-		     		buf_priv->currently_mapped = I810_BUF_UNMAPPED;
+				buf_priv->currently_mapped = I810_BUF_UNMAPPED;
 		}
 	}
 }
@@ -1029,16 +1029,16 @@ void i810_reclaim_buffers(struct file *f
 int i810_flush_ioctl(struct inode *inode, struct file *filp,
 		     unsigned int cmd, unsigned long arg)
 {
-   	drm_file_t	  *priv	  = filp->private_data;
-   	drm_device_t	  *dev	  = priv->dev;
+	drm_file_t	  *priv	  = filp->private_data;
+	drm_device_t	  *dev	  = priv->dev;
 
 	if (!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) {
 		DRM_ERROR("i810_flush_ioctl called without lock held\n");
 		return -EINVAL;
 	}
 
-   	i810_flush_queue(dev);
-   	return 0;
+	i810_flush_queue(dev);
+	return 0;
 }
 
 
@@ -1048,10 +1048,10 @@ int i810_dma_vertex(struct inode *inode,
 	drm_file_t *priv = filp->private_data;
 	drm_device_t *dev = priv->dev;
 	drm_device_dma_t *dma = dev->dma;
-   	drm_i810_private_t *dev_priv = (drm_i810_private_t *)dev->dev_private;
-      	u32 *hw_status = dev_priv->hw_status_page;
-   	drm_i810_sarea_t *sarea_priv = (drm_i810_sarea_t *)
-     					dev_priv->sarea_priv;
+	drm_i810_private_t *dev_priv = (drm_i810_private_t *)dev->dev_private;
+	u32 *hw_status = dev_priv->hw_status_page;
+	drm_i810_sarea_t *sarea_priv = (drm_i810_sarea_t *)
+					dev_priv->sarea_priv;
 	drm_i810_vertex_t vertex;
 
 	if (copy_from_user(&vertex, (drm_i810_vertex_t *)arg, sizeof(vertex)))
@@ -1072,10 +1072,10 @@ int i810_dma_vertex(struct inode *inode,
 				  dma->buflist[ vertex.idx ],
 				  vertex.discard, vertex.used );
 
-   	atomic_add(vertex.used, &dev->counts[_DRM_STAT_SECONDARY]);
+	atomic_add(vertex.used, &dev->counts[_DRM_STAT_SECONDARY]);
 	atomic_inc(&dev->counts[_DRM_STAT_DMA]);
 	sarea_priv->last_enqueue = dev_priv->counter-1;
-   	sarea_priv->last_dispatch = (int) hw_status[5];
+	sarea_priv->last_dispatch = (int) hw_status[5];
 
 	return 0;
 }
@@ -1089,7 +1089,7 @@ int i810_clear_bufs(struct inode *inode,
 	drm_device_t *dev = priv->dev;
 	drm_i810_clear_t clear;
 
-   	if (copy_from_user(&clear, (drm_i810_clear_t *)arg, sizeof(clear)))
+	if (copy_from_user(&clear, (drm_i810_clear_t *)arg, sizeof(clear)))
 		return -EFAULT;
 
 	if (!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) {
@@ -1097,15 +1097,15 @@ int i810_clear_bufs(struct inode *inode,
 		return -EINVAL;
 	}
 
- 	/* GH: Someone's doing nasty things... */
- 	if (!dev->dev_private) {
- 		return -EINVAL;
- 	}
+	/* GH: Someone's doing nasty things... */
+	if (!dev->dev_private) {
+		return -EINVAL;
+	}
 
 	i810_dma_dispatch_clear( dev, clear.flags,
 				 clear.clear_color,
 				 clear.clear_depth );
-   	return 0;
+	return 0;
 }
 
 int i810_swap_bufs(struct inode *inode, struct file *filp,
@@ -1122,20 +1122,20 @@ int i810_swap_bufs(struct inode *inode, 
 	}
 
 	i810_dma_dispatch_swap( dev );
-   	return 0;
+	return 0;
 }
 
 int i810_getage(struct inode *inode, struct file *filp, unsigned int cmd,
 		unsigned long arg)
 {
-   	drm_file_t	  *priv	    = filp->private_data;
+	drm_file_t	  *priv	    = filp->private_data;
 	drm_device_t	  *dev	    = priv->dev;
-   	drm_i810_private_t *dev_priv = (drm_i810_private_t *)dev->dev_private;
-      	u32 *hw_status = dev_priv->hw_status_page;
-   	drm_i810_sarea_t *sarea_priv = (drm_i810_sarea_t *)
-     					dev_priv->sarea_priv;
+	drm_i810_private_t *dev_priv = (drm_i810_private_t *)dev->dev_private;
+	u32 *hw_status = dev_priv->hw_status_page;
+	drm_i810_sarea_t *sarea_priv = (drm_i810_sarea_t *)
+					dev_priv->sarea_priv;
 
-      	sarea_priv->last_dispatch = (int) hw_status[5];
+	sarea_priv->last_dispatch = (int) hw_status[5];
 	return 0;
 }
 
@@ -1146,12 +1146,12 @@ int i810_getbuf(struct inode *inode, str
 	drm_device_t	  *dev	    = priv->dev;
 	int		  retcode   = 0;
 	drm_i810_dma_t	  d;
-   	drm_i810_private_t *dev_priv = (drm_i810_private_t *)dev->dev_private;
-   	u32 *hw_status = dev_priv->hw_status_page;
-   	drm_i810_sarea_t *sarea_priv = (drm_i810_sarea_t *)
-     					dev_priv->sarea_priv;
+	drm_i810_private_t *dev_priv = (drm_i810_private_t *)dev->dev_private;
+	u32 *hw_status = dev_priv->hw_status_page;
+	drm_i810_sarea_t *sarea_priv = (drm_i810_sarea_t *)
+					dev_priv->sarea_priv;
 
-   	if (copy_from_user(&d, (drm_i810_dma_t *)arg, sizeof(d)))
+	if (copy_from_user(&d, (drm_i810_dma_t *)arg, sizeof(d)))
 		return -EFAULT;
 
 	if (!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) {
@@ -1168,7 +1168,7 @@ int i810_getbuf(struct inode *inode, str
 
 	if (copy_to_user((drm_dma_t *)arg, &d, sizeof(d)))
 		return -EFAULT;
-   	sarea_priv->last_dispatch = (int) hw_status[5];
+	sarea_priv->last_dispatch = (int) hw_status[5];
 
 	return retcode;
 }
@@ -1384,5 +1384,5 @@ int i810_flip_bufs(struct inode *inode, 
 		i810_do_init_pageflip( dev );
 
 	i810_dma_dispatch_flip( dev );
-   	return 0;
+	return 0;
 }
--- diff/drivers/char/drm/i830.h	2003-05-21 11:50:14.000000000 +0100
+++ source/drivers/char/drm/i830.h	2004-02-23 13:56:41.000000000 +0000
@@ -77,6 +77,13 @@
 	[DRM_IOCTL_NR(DRM_IOCTL_I830_GETPARAM)] = { i830_getparam,  1, 0 }, \
 	[DRM_IOCTL_NR(DRM_IOCTL_I830_SETPARAM)] = { i830_setparam,  1, 0 } 
 
+#define DRIVER_PCI_IDS							\
+	{0x8086, 0x3577, 0, "Intel i830M GMCH"},			\
+	{0x8086, 0x2562, 0, "Intel i845G GMCH"},			\
+	{0x8086, 0x3582, 0, "Intel i852GM/i855GM GMCH"},		\
+ 	{0x8086, 0x2572, 0, "Intel i865G GMCH"}, 		\
+	{0, 0, 0, NULL}
+
 #define __HAVE_COUNTERS         4
 #define __HAVE_COUNTER6         _DRM_STAT_IRQ
 #define __HAVE_COUNTER7         _DRM_STAT_PRIMARY
@@ -115,10 +122,10 @@
 #define USE_IRQS 0
 
 #if USE_IRQS
-#define __HAVE_DMA_IRQ		1
+#define __HAVE_IRQ		1
 #define __HAVE_SHARED_IRQ	1
 #else
-#define __HAVE_DMA_IRQ          0
+#define __HAVE_IRQ		0
 #endif
 
 
--- diff/drivers/char/drm/i830_dma.c	2003-06-09 14:18:18.000000000 +0100
+++ source/drivers/char/drm/i830_dma.c	2004-02-23 13:56:41.000000000 +0000
@@ -231,12 +231,12 @@ int i830_dma_cleanup(drm_device_t *dev)
 {
 	drm_device_dma_t *dma = dev->dma;
 
-#if _HAVE_DMA_IRQ
+#if __HAVE_IRQ
 	/* Make sure interrupts are disabled here because the uninstall ioctl
 	 * may not have been called from userspace and after dev_private
 	 * is freed, it's too late.
 	 */
-	if (dev->irq) DRM(irq_uninstall)(dev);
+	if (dev->irq_enabled) DRM(irq_uninstall)(dev);
 #endif
 
 	if (dev->dev_private) {
@@ -1539,7 +1539,7 @@ int i830_getparam( struct inode *inode, 
 
 	switch( param.param ) {
 	case I830_PARAM_IRQ_ACTIVE:
-		value = dev->irq ? 1 : 0;
+		value = dev->irq_enabled;
 		break;
 	default:
 		return -EINVAL;
--- diff/drivers/char/drm/i830_drv.c	2003-05-21 11:50:14.000000000 +0100
+++ source/drivers/char/drm/i830_drv.c	2004-02-23 13:56:41.000000000 +0000
@@ -50,6 +50,7 @@
 #include "drm_fops.h"
 #include "drm_init.h"
 #include "drm_ioctl.h"
+#include "drm_irq.h"
 #include "drm_lock.h"
 #include "drm_memory.h"
 #include "drm_proc.h"
--- diff/drivers/char/drm/i830_irq.c	2003-09-30 15:46:12.000000000 +0100
+++ source/drivers/char/drm/i830_irq.c	2004-02-23 13:56:41.000000000 +0000
@@ -35,7 +35,7 @@
 #include <linux/delay.h>
 
 
-irqreturn_t DRM(dma_service)( DRM_IRQ_ARGS )
+irqreturn_t DRM(irq_handler)( DRM_IRQ_ARGS )
 {
 	drm_device_t	 *dev = (drm_device_t *)arg;
       	drm_i830_private_t *dev_priv = (drm_i830_private_t *)dev->dev_private;
--- diff/drivers/char/drm/mga.h	2003-05-21 11:50:14.000000000 +0100
+++ source/drivers/char/drm/mga.h	2004-02-23 13:56:41.000000000 +0000
@@ -64,6 +64,12 @@
 	[DRM_IOCTL_NR(DRM_IOCTL_MGA_BLIT)]    = { mga_dma_blit,    1, 0 }, \
 	[DRM_IOCTL_NR(DRM_IOCTL_MGA_GETPARAM)]= { mga_getparam,    1, 0 },
 
+#define DRIVER_PCI_IDS							\
+	{0x102b, 0x0521, 0, "Matrox G200 (AGP)"},			\
+	{0x102b, 0x0525, 0, "Matrox G400/G450 (AGP)"},			\
+	{0x102b, 0x2527, 0, "Matrox G550 (AGP)"},			\
+	{0, 0, 0, NULL}
+
 #define __HAVE_COUNTERS         3
 #define __HAVE_COUNTER6         _DRM_STAT_IRQ
 #define __HAVE_COUNTER7         _DRM_STAT_PRIMARY
@@ -78,7 +84,7 @@
 /* DMA customization:
  */
 #define __HAVE_DMA		1
-#define __HAVE_DMA_IRQ		1
+#define __HAVE_IRQ		1
 #define __HAVE_VBL_IRQ		1
 #define __HAVE_SHARED_IRQ       1
 
--- diff/drivers/char/drm/mga_dma.c	2003-06-09 14:18:18.000000000 +0100
+++ source/drivers/char/drm/mga_dma.c	2004-02-23 13:56:41.000000000 +0000
@@ -500,14 +500,6 @@ static int mga_do_init_dma( drm_device_t
 		return DRM_ERR(EINVAL);
 	}
 
-	DRM_FIND_MAP( dev_priv->fb, init->fb_offset );
-	if(!dev_priv->fb) {
-		DRM_ERROR( "failed to find framebuffer!\n" );
-		/* Assign dev_private so we can do cleanup. */
-		dev->dev_private = (void *)dev_priv;
-		mga_do_cleanup_dma( dev );
-		return DRM_ERR(EINVAL);
-	}
 	DRM_FIND_MAP( dev_priv->mmio, init->mmio_offset );
 	if(!dev_priv->mmio) {
 		DRM_ERROR( "failed to find mmio region!\n" );
@@ -639,12 +631,12 @@ int mga_do_cleanup_dma( drm_device_t *de
 {
 	DRM_DEBUG( "\n" );
 
-#if _HAVE_DMA_IRQ
+#if __HAVE_IRQ
 	/* Make sure interrupts are disabled here because the uninstall ioctl
 	 * may not have been called from userspace and after dev_private
 	 * is freed, it's too late.
 	 */
-	if ( dev->irq ) DRM(irq_uninstall)(dev);
+	if ( dev->irq_enabled ) DRM(irq_uninstall)(dev);
 #endif
 
 	if ( dev->dev_private ) {
--- diff/drivers/char/drm/mga_drv.c	2002-10-16 04:27:56.000000000 +0100
+++ source/drivers/char/drm/mga_drv.c	2004-02-23 13:56:41.000000000 +0000
@@ -45,6 +45,7 @@
 #include "drm_fops.h"
 #include "drm_init.h"
 #include "drm_ioctl.h"
+#include "drm_irq.h"
 #include "drm_lock.h"
 #include "drm_memory.h"
 #include "drm_proc.h"
--- diff/drivers/char/drm/mga_drv.h	2003-06-09 14:18:18.000000000 +0100
+++ source/drivers/char/drm/mga_drv.h	2004-02-23 13:56:41.000000000 +0000
@@ -91,7 +91,6 @@ typedef struct drm_mga_private {
 	unsigned int texture_size;
 
 	drm_local_map_t *sarea;
-	drm_local_map_t *fb;
 	drm_local_map_t *mmio;
 	drm_local_map_t *status;
 	drm_local_map_t *warp;
--- diff/drivers/char/drm/mga_irq.c	2003-05-21 11:50:14.000000000 +0100
+++ source/drivers/char/drm/mga_irq.c	2004-02-23 13:56:41.000000000 +0000
@@ -36,7 +36,7 @@
 #include "mga_drm.h"
 #include "mga_drv.h"
 
-irqreturn_t mga_dma_service( DRM_IRQ_ARGS )
+irqreturn_t mga_irq_handler( DRM_IRQ_ARGS )
 {
 	drm_device_t *dev = (drm_device_t *) arg;
 	drm_mga_private_t *dev_priv = 
--- diff/drivers/char/drm/r128.h	2003-08-26 10:00:52.000000000 +0100
+++ source/drivers/char/drm/r128.h	2004-02-23 13:56:41.000000000 +0000
@@ -79,6 +79,46 @@
    [DRM_IOCTL_NR(DRM_IOCTL_R128_INDIRECT)]   = { r128_cce_indirect, 1, 1 }, \
    [DRM_IOCTL_NR(DRM_IOCTL_R128_GETPARAM)]   = { r128_getparam, 1, 0 },
 
+#define DRIVER_PCI_IDS							\
+	{0x1002, 0x4c45, 0, "ATI Rage 128 Mobility LE (PCI)"},		\
+	{0x1002, 0x4c46, 0, "ATI Rage 128 Mobility LF (AGP)"},		\
+	{0x1002, 0x4d46, 0, "ATI Rage 128 Mobility MF (AGP)"},		\
+	{0x1002, 0x4d4c, 0, "ATI Rage 128 Mobility ML (AGP)"},		\
+	{0x1002, 0x5041, 0, "ATI Rage 128 Pro PA (PCI)"},		\
+	{0x1002, 0x5042, 0, "ATI Rage 128 Pro PB (AGP)"},		\
+	{0x1002, 0x5043, 0, "ATI Rage 128 Pro PC (AGP)"},		\
+	{0x1002, 0x5044, 0, "ATI Rage 128 Pro PD (PCI)"},		\
+	{0x1002, 0x5045, 0, "ATI Rage 128 Pro PE (AGP)"},		\
+	{0x1002, 0x5046, 0, "ATI Rage 128 Pro PF (AGP)"},		\
+	{0x1002, 0x5047, 0, "ATI Rage 128 Pro PG (PCI)"},		\
+	{0x1002, 0x5048, 0, "ATI Rage 128 Pro PH (AGP)"},		\
+	{0x1002, 0x5049, 0, "ATI Rage 128 Pro PI (AGP)"},		\
+	{0x1002, 0x504A, 0, "ATI Rage 128 Pro PJ (PCI)"},		\
+	{0x1002, 0x504B, 0, "ATI Rage 128 Pro PK (AGP)"},		\
+	{0x1002, 0x504C, 0, "ATI Rage 128 Pro PL (AGP)"},		\
+	{0x1002, 0x504D, 0, "ATI Rage 128 Pro PM (PCI)"},		\
+	{0x1002, 0x504E, 0, "ATI Rage 128 Pro PN (AGP)"},		\
+	{0x1002, 0x504F, 0, "ATI Rage 128 Pro PO (AGP)"},		\
+	{0x1002, 0x5050, 0, "ATI Rage 128 Pro PP (PCI)"},		\
+	{0x1002, 0x5051, 0, "ATI Rage 128 Pro PQ (AGP)"},		\
+	{0x1002, 0x5052, 0, "ATI Rage 128 Pro PR (PCI)"},		\
+	{0x1002, 0x5053, 0, "ATI Rage 128 Pro PS (PCI)"},		\
+	{0x1002, 0x5054, 0, "ATI Rage 128 Pro PT (AGP)"},		\
+	{0x1002, 0x5055, 0, "ATI Rage 128 Pro PU (AGP)"},		\
+	{0x1002, 0x5056, 0, "ATI Rage 128 Pro PV (PCI)"},		\
+	{0x1002, 0x5057, 0, "ATI Rage 128 Pro PW (AGP)"},		\
+	{0x1002, 0x5058, 0, "ATI Rage 128 Pro PX (AGP)"},		\
+	{0x1002, 0x5245, 0, "ATI Rage 128 RE (PCI)"},			\
+	{0x1002, 0x5246, 0, "ATI Rage 128 RF (AGP)"},			\
+	{0x1002, 0x5247, 0, "ATI Rage 128 RG (AGP)"},			\
+	{0x1002, 0x524b, 0, "ATI Rage 128 RK (PCI)"},			\
+	{0x1002, 0x524c, 0, "ATI Rage 128 RL (AGP)"},			\
+	{0x1002, 0x534d, 0, "ATI Rage 128 SM (AGP)"},			\
+	{0x1002, 0x5446, 0, "ATI Rage 128 Pro Ultra TF (AGP)"},		\
+	{0x1002, 0x544C, 0, "ATI Rage 128 Pro Ultra TL (AGP)"},		\
+	{0x1002, 0x5452, 0, "ATI Rage 128 Pro Ultra TR (AGP)"},		\
+	{0, 0, 0, NULL}
+
 /* Driver customization:
  */
 #define DRIVER_PRERELEASE() do {					\
@@ -97,7 +137,7 @@
 /* DMA customization:
  */
 #define __HAVE_DMA		1
-#define __HAVE_DMA_IRQ		1
+#define __HAVE_IRQ		1
 #define __HAVE_VBL_IRQ		1
 #define __HAVE_SHARED_IRQ       1
 
--- diff/drivers/char/drm/r128_cce.c	2003-09-30 15:46:12.000000000 +0100
+++ source/drivers/char/drm/r128_cce.c	2004-02-23 13:56:41.000000000 +0000
@@ -212,7 +212,7 @@ int r128_do_cce_idle( drm_r128_private_t
 	int i;
 
 	for ( i = 0 ; i < dev_priv->usec_timeout ; i++ ) {
-		if ( GET_RING_HEAD( &dev_priv->ring ) == dev_priv->ring.tail ) {
+		if ( GET_RING_HEAD( dev_priv ) == dev_priv->ring.tail ) {
 			int pm4stat = R128_READ( R128_PM4_STAT );
 			if ( ( (pm4stat & R128_PM4_FIFOCNT_MASK) >=
 			       dev_priv->cce_fifo_size ) &&
@@ -238,7 +238,8 @@ static void r128_do_cce_start( drm_r128_
 	r128_do_wait_for_idle( dev_priv );
 
 	R128_WRITE( R128_PM4_BUFFER_CNTL,
-		    dev_priv->cce_mode | dev_priv->ring.size_l2qw );
+		    dev_priv->cce_mode | dev_priv->ring.size_l2qw
+		    | R128_PM4_BUFFER_CNTL_NOUPDATE );
 	R128_READ( R128_PM4_BUFFER_ADDR ); /* as per the sample code */
 	R128_WRITE( R128_PM4_MICRO_CNTL, R128_PM4_MICRO_FREERUN );
 
@@ -253,7 +254,6 @@ static void r128_do_cce_reset( drm_r128_
 {
 	R128_WRITE( R128_PM4_BUFFER_DL_WPTR, 0 );
 	R128_WRITE( R128_PM4_BUFFER_DL_RPTR, 0 );
-	SET_RING_HEAD( &dev_priv->ring, 0 );
 	dev_priv->ring.tail = 0;
 }
 
@@ -264,7 +264,8 @@ static void r128_do_cce_reset( drm_r128_
 static void r128_do_cce_stop( drm_r128_private_t *dev_priv )
 {
 	R128_WRITE( R128_PM4_MICRO_CNTL, 0 );
-	R128_WRITE( R128_PM4_BUFFER_CNTL, R128_PM4_NONPM4 );
+	R128_WRITE( R128_PM4_BUFFER_CNTL,
+		    R128_PM4_NONPM4 | R128_PM4_BUFFER_CNTL_NOUPDATE );
 
 	dev_priv->cce_running = 0;
 }
@@ -333,26 +334,6 @@ static void r128_cce_init_ring_buffer( d
 	R128_WRITE( R128_PM4_BUFFER_DL_WPTR, 0 );
 	R128_WRITE( R128_PM4_BUFFER_DL_RPTR, 0 );
 
-	/* DL_RPTR_ADDR is a physical address in AGP space. */
-	SET_RING_HEAD( &dev_priv->ring, 0 );
-
-	if ( !dev_priv->is_pci ) {
-		R128_WRITE( R128_PM4_BUFFER_DL_RPTR_ADDR,
-			    dev_priv->ring_rptr->offset );
-	} else {
-		drm_sg_mem_t *entry = dev->sg;
-		unsigned long tmp_ofs, page_ofs;
-
-		tmp_ofs = dev_priv->ring_rptr->offset - dev->sg->handle;
-		page_ofs = tmp_ofs >> PAGE_SHIFT;
-
-		R128_WRITE( R128_PM4_BUFFER_DL_RPTR_ADDR,
-     			    entry->busaddr[page_ofs]);
-		DRM_DEBUG( "ring rptr: offset=0x%08lx handle=0x%08lx\n",
-			   (unsigned long) entry->busaddr[page_ofs],
-     			   entry->handle + tmp_ofs );
-	}
-
 	/* Set watermark control */
 	R128_WRITE( R128_PM4_BUFFER_WM_CNTL,
 		    ((R128_WATERMARK_L/4) << R128_WMA_SHIFT)
@@ -486,13 +467,6 @@ static int r128_do_init_cce( drm_device_
 		return DRM_ERR(EINVAL);
 	}
 
-	DRM_FIND_MAP( dev_priv->fb, init->fb_offset );
-	if(!dev_priv->fb) {
-		DRM_ERROR("could not find framebuffer!\n");
-		dev->dev_private = (void *)dev_priv;
-		r128_do_cleanup_cce( dev );
-		return DRM_ERR(EINVAL);
-	}
 	DRM_FIND_MAP( dev_priv->mmio, init->mmio_offset );
 	if(!dev_priv->mmio) {
 		DRM_ERROR("could not find mmio region!\n");
@@ -567,9 +541,6 @@ static int r128_do_init_cce( drm_device_
 #endif
 		dev_priv->cce_buffers_offset = dev->sg->handle;
 
-	dev_priv->ring.head = ((__volatile__ u32 *)
-			       dev_priv->ring_rptr->handle);
-
 	dev_priv->ring.start = (u32 *)dev_priv->cce_ring->handle;
 	dev_priv->ring.end = ((u32 *)dev_priv->cce_ring->handle
 			      + init->ring_size / sizeof(u32));
@@ -580,7 +551,6 @@ static int r128_do_init_cce( drm_device_
 		(dev_priv->ring.size / sizeof(u32)) - 1;
 
 	dev_priv->ring.high_mark = 128;
-	dev_priv->ring.ring_rptr = dev_priv->ring_rptr;
 
 	dev_priv->sarea_priv->last_frame = 0;
 	R128_WRITE( R128_LAST_FRAME_REG, dev_priv->sarea_priv->last_frame );
@@ -589,8 +559,9 @@ static int r128_do_init_cce( drm_device_
 	R128_WRITE( R128_LAST_DISPATCH_REG,
 		    dev_priv->sarea_priv->last_dispatch );
 
-#if __REALLY_HAVE_SG
+#if __REALLY_HAVE_AGP
 	if ( dev_priv->is_pci ) {
+#endif
 		if (!DRM(ati_pcigart_init)( dev, &dev_priv->phys_pci_gart,
      					    &dev_priv->bus_pci_gart) ) {
 			DRM_ERROR( "failed to init PCI GART!\n" );
@@ -599,6 +570,7 @@ static int r128_do_init_cce( drm_device_
 			return DRM_ERR(ENOMEM);
 		}
 		R128_WRITE( R128_PCI_GART_PAGE, dev_priv->bus_pci_gart );
+#if __REALLY_HAVE_AGP
 	}
 #endif
 
@@ -615,12 +587,12 @@ static int r128_do_init_cce( drm_device_
 int r128_do_cleanup_cce( drm_device_t *dev )
 {
 
-#if _HAVE_DMA_IRQ
+#if __HAVE_IRQ
 	/* Make sure interrupts are disabled here because the uninstall ioctl
 	 * may not have been called from userspace and after dev_private
 	 * is freed, it's too late.
 	 */
-	if ( dev->irq ) DRM(irq_uninstall)(dev);
+	if ( dev->irq_enabled ) DRM(irq_uninstall)(dev);
 #endif
 
 	if ( dev->dev_private ) {
@@ -901,7 +873,7 @@ int r128_wait_ring( drm_r128_private_t *
 	int i;
 
 	for ( i = 0 ; i < dev_priv->usec_timeout ; i++ ) {
-		r128_update_ring_snapshot( ring );
+		r128_update_ring_snapshot( dev_priv );
 		if ( ring->space >= n )
 			return 0;
 		DRM_UDELAY( 1 );
--- diff/drivers/char/drm/r128_drv.c	2002-10-16 04:27:48.000000000 +0100
+++ source/drivers/char/drm/r128_drv.c	2004-02-23 13:56:41.000000000 +0000
@@ -47,6 +47,7 @@
 #include "drm_fops.h"
 #include "drm_init.h"
 #include "drm_ioctl.h"
+#include "drm_irq.h"
 #include "drm_lock.h"
 #include "drm_memory.h"
 #include "drm_proc.h"
--- diff/drivers/char/drm/r128_drv.h	2003-08-20 14:16:27.000000000 +0100
+++ source/drivers/char/drm/r128_drv.h	2004-02-23 13:56:41.000000000 +0000
@@ -34,8 +34,7 @@
 #ifndef __R128_DRV_H__
 #define __R128_DRV_H__
 
-#define GET_RING_HEAD(ring)		DRM_READ32(  (ring)->ring_rptr, 0 ) /* (ring)->head */
-#define SET_RING_HEAD(ring,val)		DRM_WRITE32( (ring)->ring_rptr, 0, (val) ) /* (ring)->head */
+#define GET_RING_HEAD(dev_priv)		R128_READ( R128_PM4_BUFFER_DL_RPTR )
 
 typedef struct drm_r128_freelist {
    	unsigned int age;
@@ -50,13 +49,11 @@ typedef struct drm_r128_ring_buffer {
 	int size;
 	int size_l2qw;
 
-	volatile u32 *head;
 	u32 tail;
 	u32 tail_mask;
 	int space;
 
 	int high_mark;
-	drm_local_map_t *ring_rptr;
 } drm_r128_ring_buffer_t;
 
 typedef struct drm_r128_private {
@@ -100,7 +97,6 @@ typedef struct drm_r128_private {
 	u32 span_pitch_offset_c;
 
 	drm_local_map_t *sarea;
-	drm_local_map_t *fb;
 	drm_local_map_t *mmio;
 	drm_local_map_t *cce_ring;
 	drm_local_map_t *ring_rptr;
@@ -132,14 +128,6 @@ extern drm_buf_t *r128_freelist_get( drm
 
 extern int r128_wait_ring( drm_r128_private_t *dev_priv, int n );
 
-static __inline__ void
-r128_update_ring_snapshot( drm_r128_ring_buffer_t *ring )
-{
-	ring->space = (GET_RING_HEAD( ring ) - ring->tail) * sizeof(u32);
-	if ( ring->space <= 0 )
-		ring->space += ring->size;
-}
-
 extern int r128_do_cce_idle( drm_r128_private_t *dev_priv );
 extern int r128_do_cleanup_cce( drm_device_t *dev );
 extern int r128_do_cleanup_pageflip( drm_device_t *dev );
@@ -279,6 +267,7 @@ extern int r128_cce_indirect( DRM_IOCTL_
 #	define R128_PM4_64PIO_64VCBM_64INDBM	(7  << 28)
 #	define R128_PM4_64BM_64VCBM_64INDBM	(8  << 28)
 #	define R128_PM4_64PIO_64VCPIO_64INDPIO	(15 << 28)
+#	define R128_PM4_BUFFER_CNTL_NOUPDATE	(1  << 27)
 
 #define R128_PM4_BUFFER_WM_CNTL		0x0708
 #	define R128_WMA_SHIFT			0
@@ -403,6 +392,15 @@ extern int R128_READ_PLL(drm_device_t *d
 					 (pkt) | ((n) << 16))
 
 
+static __inline__ void
+r128_update_ring_snapshot( drm_r128_private_t *dev_priv )
+{
+	drm_r128_ring_buffer_t *ring = &dev_priv->ring;
+	ring->space = (GET_RING_HEAD( dev_priv ) - ring->tail) * sizeof(u32);
+	if ( ring->space <= 0 )
+		ring->space += ring->size;
+}
+
 /* ================================================================
  * Misc helper macros
  */
@@ -412,7 +410,7 @@ do {									\
 	drm_r128_ring_buffer_t *ring = &dev_priv->ring; int i;		\
 	if ( ring->space < ring->high_mark ) {				\
 		for ( i = 0 ; i < dev_priv->usec_timeout ; i++ ) {	\
-			r128_update_ring_snapshot( ring );		\
+			r128_update_ring_snapshot( dev_priv );		\
 			if ( ring->space >= ring->high_mark )		\
 				goto __ring_space_done;			\
 			DRM_UDELAY(1);				\
@@ -445,17 +443,10 @@ do {									\
  * Ring control
  */
 
-#if defined(__powerpc__)
-#define r128_flush_write_combine()	(void) GET_RING_HEAD( &dev_priv->ring )
-#else
-#define r128_flush_write_combine()	DRM_WRITEMEMORYBARRIER()
-#endif
-
-
 #define R128_VERBOSE	0
 
 #define RING_LOCALS							\
-	int write; unsigned int tail_mask; volatile u32 *ring;
+	int write, _nr; unsigned int tail_mask; volatile u32 *ring;
 
 #define BEGIN_RING( n ) do {						\
 	if ( R128_VERBOSE ) {						\
@@ -463,9 +454,10 @@ do {									\
 			   (n), __FUNCTION__ );				\
 	}								\
 	if ( dev_priv->ring.space <= (n) * sizeof(u32) ) {		\
+		COMMIT_RING();						\
 		r128_wait_ring( dev_priv, (n) * sizeof(u32) );		\
 	}								\
-	dev_priv->ring.space -= (n) * sizeof(u32);			\
+	_nr = n; dev_priv->ring.space -= (n) * sizeof(u32);		\
 	ring = dev_priv->ring.start;					\
 	write = dev_priv->ring.tail;					\
 	tail_mask = dev_priv->ring.tail_mask;				\
@@ -488,9 +480,23 @@ do {									\
 			dev_priv->ring.start,				\
 			write * sizeof(u32) );				\
 	}								\
-	r128_flush_write_combine();					\
-	dev_priv->ring.tail = write;					\
-	R128_WRITE( R128_PM4_BUFFER_DL_WPTR, write );			\
+	if (((dev_priv->ring.tail + _nr) & tail_mask) != write) {	\
+		DRM_ERROR( 						\
+			"ADVANCE_RING(): mismatch: nr: %x write: %x line: %d\n",	\
+			((dev_priv->ring.tail + _nr) & tail_mask),	\
+			write, __LINE__);				\
+	} else								\
+		dev_priv->ring.tail = write;				\
+} while (0)
+
+#define COMMIT_RING() do {						\
+	if ( R128_VERBOSE ) {						\
+		DRM_INFO( "COMMIT_RING() tail=0x%06x\n",		\
+			dev_priv->ring.tail );				\
+	}								\
+	DRM_MEMORYBARRIER();						\
+	R128_WRITE( R128_PM4_BUFFER_DL_WPTR, dev_priv->ring.tail );	\
+	R128_READ( R128_PM4_BUFFER_DL_WPTR );				\
 } while (0)
 
 #define OUT_RING( x ) do {						\
--- diff/drivers/char/drm/r128_irq.c	2003-05-21 11:50:14.000000000 +0100
+++ source/drivers/char/drm/r128_irq.c	2004-02-23 13:56:41.000000000 +0000
@@ -36,7 +36,7 @@
 #include "r128_drm.h"
 #include "r128_drv.h"
 
-irqreturn_t r128_dma_service( DRM_IRQ_ARGS )
+irqreturn_t r128_irq_handler( DRM_IRQ_ARGS )
 {
 	drm_device_t *dev = (drm_device_t *) arg;
 	drm_r128_private_t *dev_priv = 
--- diff/drivers/char/drm/r128_state.c	2003-08-20 14:16:27.000000000 +0100
+++ source/drivers/char/drm/r128_state.c	2004-02-23 13:56:41.000000000 +0000
@@ -45,7 +45,7 @@ static void r128_emit_clip_rects( drm_r1
 	RING_LOCALS;
 	DRM_DEBUG( "    %s\n", __FUNCTION__ );
 
-	BEGIN_RING( 17 );
+	BEGIN_RING( (count < 3? count: 3) * 5 + 2 );
 
 	if ( count >= 1 ) {
 		OUT_RING( CCE_PACKET0( R128_AUX1_SC_LEFT, 3 ) );
@@ -1269,6 +1269,7 @@ int r128_cce_clear( DRM_IOCTL_ARGS )
 		sarea_priv->nbox = R128_NR_SAREA_CLIPRECTS;
 
 	r128_cce_dispatch_clear( dev, &clear );
+	COMMIT_RING();
 
 	/* Make sure we restore the 3D state next time.
 	 */
@@ -1304,8 +1305,10 @@ int r128_do_cleanup_pageflip( drm_device
 	R128_WRITE( R128_CRTC_OFFSET,      dev_priv->crtc_offset );
 	R128_WRITE( R128_CRTC_OFFSET_CNTL, dev_priv->crtc_offset_cntl );
 
-	if (dev_priv->current_page != 0)
+	if (dev_priv->current_page != 0) {
 		r128_cce_dispatch_flip( dev );
+		COMMIT_RING();
+	}
 
 	dev_priv->page_flipping = 0;
 	return 0;
@@ -1330,6 +1333,7 @@ int r128_cce_flip( DRM_IOCTL_ARGS )
 
 	r128_cce_dispatch_flip( dev );
 
+	COMMIT_RING();
 	return 0;
 }
 
@@ -1351,6 +1355,7 @@ int r128_cce_swap( DRM_IOCTL_ARGS )
 	dev_priv->sarea_priv->dirty |= (R128_UPLOAD_CONTEXT |
 					R128_UPLOAD_MASKS);
 
+	COMMIT_RING();
 	return 0;
 }
 
@@ -1410,6 +1415,7 @@ int r128_cce_vertex( DRM_IOCTL_ARGS )
 
 	r128_cce_dispatch_vertex( dev, buf );
 
+	COMMIT_RING();
 	return 0;
 }
 
@@ -1481,6 +1487,7 @@ int r128_cce_indices( DRM_IOCTL_ARGS )
 
 	r128_cce_dispatch_indices( dev, buf, elts.start, elts.end, count );
 
+	COMMIT_RING();
 	return 0;
 }
 
@@ -1490,6 +1497,7 @@ int r128_cce_blit( DRM_IOCTL_ARGS )
 	drm_device_dma_t *dma = dev->dma;
 	drm_r128_private_t *dev_priv = dev->dev_private;
 	drm_r128_blit_t blit;
+	int ret;
 
 	LOCK_TEST_WITH_RETURN( dev, filp );
 
@@ -1507,7 +1515,10 @@ int r128_cce_blit( DRM_IOCTL_ARGS )
 	RING_SPACE_TEST_WITH_RETURN( dev_priv );
 	VB_AGE_TEST_WITH_RETURN( dev_priv );
 
-	return r128_cce_dispatch_blit( filp, dev, &blit );
+	ret = r128_cce_dispatch_blit( filp, dev, &blit );
+
+	COMMIT_RING();
+	return ret;
 }
 
 int r128_cce_depth( DRM_IOCTL_ARGS )
@@ -1515,6 +1526,7 @@ int r128_cce_depth( DRM_IOCTL_ARGS )
 	DRM_DEVICE;
 	drm_r128_private_t *dev_priv = dev->dev_private;
 	drm_r128_depth_t depth;
+	int ret;
 
 	LOCK_TEST_WITH_RETURN( dev, filp );
 
@@ -1523,18 +1535,20 @@ int r128_cce_depth( DRM_IOCTL_ARGS )
 
 	RING_SPACE_TEST_WITH_RETURN( dev_priv );
 
+	ret = DRM_ERR(EINVAL);
 	switch ( depth.func ) {
 	case R128_WRITE_SPAN:
-		return r128_cce_dispatch_write_span( dev, &depth );
+		ret = r128_cce_dispatch_write_span( dev, &depth );
 	case R128_WRITE_PIXELS:
-		return r128_cce_dispatch_write_pixels( dev, &depth );
+		ret = r128_cce_dispatch_write_pixels( dev, &depth );
 	case R128_READ_SPAN:
-		return r128_cce_dispatch_read_span( dev, &depth );
+		ret = r128_cce_dispatch_read_span( dev, &depth );
 	case R128_READ_PIXELS:
-		return r128_cce_dispatch_read_pixels( dev, &depth );
+		ret = r128_cce_dispatch_read_pixels( dev, &depth );
 	}
 
-	return DRM_ERR(EINVAL);
+	COMMIT_RING();
+	return ret;
 }
 
 int r128_cce_stipple( DRM_IOCTL_ARGS )
@@ -1557,6 +1571,7 @@ int r128_cce_stipple( DRM_IOCTL_ARGS )
 
 	r128_cce_dispatch_stipple( dev, mask );
 
+	COMMIT_RING();
 	return 0;
 }
 
@@ -1632,6 +1647,7 @@ int r128_cce_indirect( DRM_IOCTL_ARGS )
 	 */
 	r128_cce_dispatch_indirect( dev, buf, indirect.start, indirect.end );
 
+	COMMIT_RING();
 	return 0;
 }
 
--- diff/drivers/char/drm/radeon.h	2003-09-30 15:46:12.000000000 +0100
+++ source/drivers/char/drm/radeon.h	2004-02-23 13:56:41.000000000 +0000
@@ -51,7 +51,7 @@
 #define DRIVER_DATE		"20020828"
 
 #define DRIVER_MAJOR		1
-#define DRIVER_MINOR		9
+#define DRIVER_MINOR		10
 #define DRIVER_PATCHLEVEL	0
 
 /* Interface history:
@@ -81,6 +81,9 @@
  *       Add 'GET' queries for starting additional clients on different VT's.
  * 1.9 - Add DRM_IOCTL_RADEON_CP_RESUME ioctl.
  *       Add texture rectangle support for r100.
+ * 1.10- Add SETPARAM ioctl; first parameter to set is FB_LOCATION, which
+ *       clients use to tell the DRM where they think the framebuffer is 
+ *       located in the card's address space
  */
 #define DRIVER_IOCTLS							     \
  [DRM_IOCTL_NR(DRM_IOCTL_DMA)]               = { radeon_cp_buffers,  1, 0 }, \
@@ -106,10 +109,82 @@
  [DRM_IOCTL_NR(DRM_IOCTL_RADEON_ALLOC)]      = { radeon_mem_alloc,   1, 0 }, \
  [DRM_IOCTL_NR(DRM_IOCTL_RADEON_FREE)]       = { radeon_mem_free,    1, 0 }, \
  [DRM_IOCTL_NR(DRM_IOCTL_RADEON_INIT_HEAP)]  = { radeon_mem_init_heap, 1, 1 }, \
- [DRM_IOCTL_NR(DRM_IOCTL_RADEON_IRQ_EMIT)]   = { radeon_irq_emit, 1, 0 }, \
- [DRM_IOCTL_NR(DRM_IOCTL_RADEON_IRQ_WAIT)]   = { radeon_irq_wait, 1, 0 },
+ [DRM_IOCTL_NR(DRM_IOCTL_RADEON_IRQ_EMIT)]   = { radeon_irq_emit,    1, 0 }, \
+ [DRM_IOCTL_NR(DRM_IOCTL_RADEON_IRQ_WAIT)]   = { radeon_irq_wait,    1, 0 }, \
+ [DRM_IOCTL_NR(DRM_IOCTL_RADEON_SETPARAM)]   = { radeon_cp_setparam, 1, 0 }, \
+
+#define DRIVER_PCI_IDS							\
+	{0x1002, 0x4136, 0, "ATI Radeon RS100 IGP 320M"},		\
+	{0x1002, 0x4137, 0, "ATI Radeon RS200 IGP"},			\
+	{0x1002, 0x4237, 0, "ATI Radeon RS250 IGP"},			\
+	{0x1002, 0x4242, 0, "ATI Radeon BB R200 AIW 8500DV"},		\
+	{0x1002, 0x4242, 0, "ATI Radeon BC R200"},			\
+	{0x1002, 0x4336, 0, "ATI Radeon RS100 Mobility U1"},		\
+	{0x1002, 0x4337, 0, "ATI Radeon RS200 Mobility IGP 340M"},	\
+	{0x1002, 0x4437, 0, "ATI Radeon RS250 Mobility IGP"},		\
+	{0x1002, 0x4964, 0, "ATI Radeon Id R250 9000"},			\
+	{0x1002, 0x4965, 0, "ATI Radeon Ie R250 9000"},			\
+	{0x1002, 0x4966, 0, "ATI Radeon If R250 9000"},			\
+	{0x1002, 0x4967, 0, "ATI Radeon Ig R250 9000"},			\
+	{0x1002, 0x4C57, 0, "ATI Radeon LW Mobility 7500 M7"},		\
+	{0x1002, 0x4C58, 0, "ATI Radeon LX RV200 Mobility FireGL 7800 M7"}, \
+	{0x1002, 0x4C59, 0, "ATI Radeon LY Mobility M6"},		\
+	{0x1002, 0x4C5A, 0, "ATI Radeon LZ Mobility M6"},		\
+	{0x1002, 0x4C64, 0, "ATI Radeon Ld R250 Mobility 9000 M9"},	\
+	{0x1002, 0x4C65, 0, "ATI Radeon Le R250 Mobility 9000 M9"},	\
+	{0x1002, 0x4C66, 0, "ATI Radeon Lf R250 Mobility 9000 M9"},	\
+	{0x1002, 0x4C67, 0, "ATI Radeon Lg R250 Mobility 9000 M9"},	\
+	{0x1002, 0x5144, 0, "ATI Radeon QD R100"},			\
+	{0x1002, 0x5145, 0, "ATI Radeon QE R100"},			\
+	{0x1002, 0x5146, 0, "ATI Radeon QF R100"},			\
+	{0x1002, 0x5147, 0, "ATI Radeon QG R100"},			\
+	{0x1002, 0x5148, 0, "ATI Radeon QH R200 8500"},			\
+	{0x1002, 0x5149, 0, "ATI Radeon QI R200"},			\
+	{0x1002, 0x514A, 0, "ATI Radeon QJ R200"},			\
+	{0x1002, 0x514B, 0, "ATI Radeon QK R200"},			\
+	{0x1002, 0x514C, 0, "ATI Radeon QL R200 8500 LE"},		\
+	{0x1002, 0x514D, 0, "ATI Radeon QM R200 9100"},			\
+	{0x1002, 0x514E, 0, "ATI Radeon QN R200 8500 LE"},		\
+	{0x1002, 0x514F, 0, "ATI Radeon QO R200 8500 LE"},		\
+	{0x1002, 0x5157, 0, "ATI Radeon QW RV200 7500"},		\
+	{0x1002, 0x5158, 0, "ATI Radeon QX RV200 7500"},		\
+	{0x1002, 0x5159, 0, "ATI Radeon QY RV100 7000/VE"},		\
+	{0x1002, 0x515A, 0, "ATI Radeon QZ RV100 7000/VE"},		\
+	{0x1002, 0x5168, 0, "ATI Radeon Qh R200"},			\
+	{0x1002, 0x5169, 0, "ATI Radeon Qi R200"},			\
+	{0x1002, 0x516A, 0, "ATI Radeon Qj R200"},			\
+	{0x1002, 0x516B, 0, "ATI Radeon Qk R200"},			\
+	{0x1002, 0x516C, 0, "ATI Radeon Ql R200"},			\
+	{0x1002, 0x5834, 0, "ATI Radeon RS300 IGP"},			\
+	{0x1002, 0x5835, 0, "ATI Radeon RS300 Mobility IGP"},		\
+	{0x1002, 0x5836, 0, "ATI Radeon RS300 IGP"},			\
+	{0x1002, 0x5837, 0, "ATI Radeon RS300 IGP"},			\
+	{0x1002, 0x5960, 0, "ATI Radeon RV280 9200"},			\
+	{0x1002, 0x5961, 0, "ATI Radeon RV280 9200 SE"},		\
+	{0x1002, 0x5962, 0, "ATI Radeon RV280 9200"},			\
+	{0x1002, 0x5963, 0, "ATI Radeon RV280 9200"},			\
+	{0x1002, 0x5964, 0, "ATI Radeon RV280 9200 SE"},		\
+	{0x1002, 0x5968, 0, "ATI Radeon RV280 9200"},			\
+	{0x1002, 0x5969, 0, "ATI Radeon RV280 9200"},			\
+	{0x1002, 0x596A, 0, "ATI Radeon RV280 9200"},			\
+	{0x1002, 0x596B, 0, "ATI Radeon RV280 9200"},			\
+	{0x1002, 0x5c61, 0, "ATI Radeon RV280 Mobility"},		\
+	{0x1002, 0x5c62, 0, "ATI Radeon RV280"},			\
+	{0x1002, 0x5c63, 0, "ATI Radeon RV280 Mobility"},		\
+	{0x1002, 0x5c64, 0, "ATI Radeon RV280"},			\
+	{0, 0, 0, NULL}
 
+#define DRIVER_FILE_FIELDS						\
+	int64_t radeon_fb_delta;					\
 
+#define DRIVER_OPEN_HELPER( filp_priv, dev )				\
+do {									\
+	drm_radeon_private_t *dev_priv = dev->dev_private;		\
+	if ( dev_priv )							\
+		filp_priv->radeon_fb_delta = dev_priv->fb_location;	\
+	else								\
+		filp_priv->radeon_fb_delta = 0;				\
+} while( 0 )
 
 /* When a client dies:
  *    - Check for and clean up flipped page state
@@ -125,7 +200,7 @@ do {									\
 			radeon_do_cleanup_pageflip( dev );		\
 		}							\
 		radeon_mem_release( filp, dev_priv->gart_heap );	\
-                radeon_mem_release( filp, dev_priv->fb_heap );		\
+		radeon_mem_release( filp, dev_priv->fb_heap );		\
 	}								\
 } while (0)
 
@@ -142,7 +217,7 @@ do {						\
 /* DMA customization:
  */
 #define __HAVE_DMA		1
-#define __HAVE_DMA_IRQ		1
+#define __HAVE_IRQ		1
 #define __HAVE_VBL_IRQ		1
 #define __HAVE_SHARED_IRQ       1
 
--- diff/drivers/char/drm/radeon_cp.c	2003-09-30 15:46:12.000000000 +0100
+++ source/drivers/char/drm/radeon_cp.c	2004-02-23 13:56:41.000000000 +0000
@@ -855,7 +855,8 @@ static void radeon_cp_init_ring_buffer( 
 
 	/* Initialize the memory controller */
 	RADEON_WRITE( RADEON_MC_FB_LOCATION,
-		      (dev_priv->gart_vm_start - 1) & 0xffff0000 );
+		      ( ( dev_priv->gart_vm_start - 1 ) & 0xffff0000 )
+		    | ( dev_priv->fb_location >> 16 ) );
 
 #if __REALLY_HAVE_AGP
 	if ( !dev_priv->is_pci ) {
@@ -1071,13 +1072,6 @@ static int radeon_do_init_cp( drm_device
 	dev_priv->depth_offset	= init->depth_offset;
 	dev_priv->depth_pitch	= init->depth_pitch;
 
-	dev_priv->front_pitch_offset = (((dev_priv->front_pitch/64) << 22) |
-					(dev_priv->front_offset >> 10));
-	dev_priv->back_pitch_offset = (((dev_priv->back_pitch/64) << 22) |
-				       (dev_priv->back_offset >> 10));
-	dev_priv->depth_pitch_offset = (((dev_priv->depth_pitch/64) << 22) |
-					(dev_priv->depth_offset >> 10));
-
 	/* Hardware state for depth clears.  Remove this if/when we no
 	 * longer clear the depth buffer with a 3D rectangle.  Hard-code
 	 * all values to prevent unwanted 3D state from slipping through
@@ -1124,13 +1118,6 @@ static int radeon_do_init_cp( drm_device
 		return DRM_ERR(EINVAL);
 	}
 
-	DRM_FIND_MAP( dev_priv->fb, init->fb_offset );
-	if(!dev_priv->fb) {
-		DRM_ERROR("could not find framebuffer!\n");
-		dev->dev_private = (void *)dev_priv;
-		radeon_do_cleanup_cp(dev);
-		return DRM_ERR(EINVAL);
-	}
 	DRM_FIND_MAP( dev_priv->mmio, init->mmio_offset );
 	if(!dev_priv->mmio) {
 		DRM_ERROR("could not find mmio region!\n");
@@ -1204,9 +1191,26 @@ static int radeon_do_init_cp( drm_device
 			   dev_priv->buffers->handle );
 	}
 
+	dev_priv->fb_location = ( RADEON_READ( RADEON_MC_FB_LOCATION )
+				& 0xffff ) << 16;
+
+	dev_priv->front_pitch_offset = (((dev_priv->front_pitch/64) << 22) |
+					( ( dev_priv->front_offset
+					  + dev_priv->fb_location ) >> 10 ) );
+
+	dev_priv->back_pitch_offset = (((dev_priv->back_pitch/64) << 22) |
+				       ( ( dev_priv->back_offset
+					 + dev_priv->fb_location ) >> 10 ) );
+
+	dev_priv->depth_pitch_offset = (((dev_priv->depth_pitch/64) << 22) |
+					( ( dev_priv->depth_offset
+					  + dev_priv->fb_location ) >> 10 ) );
+
 
 	dev_priv->gart_size = init->gart_size;
-	dev_priv->gart_vm_start = RADEON_READ( RADEON_CONFIG_APER_SIZE );
+	dev_priv->gart_vm_start = dev_priv->fb_location
+				+ RADEON_READ( RADEON_CONFIG_APER_SIZE );
+
 #if __REALLY_HAVE_AGP
 	if ( !dev_priv->is_pci )
 		dev_priv->gart_buffers_offset = (dev_priv->buffers->offset
@@ -1271,12 +1275,12 @@ int radeon_do_cleanup_cp( drm_device_t *
 {
 	DRM_DEBUG( "\n" );
 
-#if _HAVE_DMA_IRQ
+#if __HAVE_IRQ
 	/* Make sure interrupts are disabled here because the uninstall ioctl
 	 * may not have been called from userspace and after dev_private
 	 * is freed, it's too late.
 	 */
-	if ( dev->irq ) DRM(irq_uninstall)(dev);
+	if ( dev->irq_enabled ) DRM(irq_uninstall)(dev);
 #endif
 
 	if ( dev->dev_private ) {
--- diff/drivers/char/drm/radeon_drm.h	2003-09-30 15:46:12.000000000 +0100
+++ source/drivers/char/drm/radeon_drm.h	2004-02-23 13:56:41.000000000 +0000
@@ -390,6 +390,7 @@ typedef struct {
 #define DRM_IOCTL_RADEON_IRQ_WAIT   DRM_IOW( 0x57, drm_radeon_irq_wait_t)
 /* added by Charl P. Botha - see radeon_cp.c for details */
 #define DRM_IOCTL_RADEON_CP_RESUME  DRM_IO(0x58)
+#define DRM_IOCTL_RADEON_SETPARAM   DRM_IOW(0x59, drm_radeon_setparam_t)
 
 typedef struct drm_radeon_init {
 	enum {
@@ -502,7 +503,7 @@ typedef struct drm_radeon_tex_image {
 } drm_radeon_tex_image_t;
 
 typedef struct drm_radeon_texture {
-	int offset;
+	unsigned int offset;
 	int pitch;
 	int format;
 	int width;			/* Texture image coordinates */
@@ -537,6 +538,7 @@ typedef struct drm_radeon_indirect {
 #define RADEON_PARAM_STATUS_HANDLE         8
 #define RADEON_PARAM_SAREA_HANDLE          9
 #define RADEON_PARAM_GART_TEX_HANDLE       10
+#define RADEON_PARAM_SCRATCH_OFFSET        11
 
 typedef struct drm_radeon_getparam {
 	int param;
@@ -578,4 +580,16 @@ typedef struct drm_radeon_irq_wait {
 } drm_radeon_irq_wait_t;
 
 
+/* 1.10: Clients tell the DRM where they think the framebuffer is located in
+ * the card's address space, via a new generic ioctl to set parameters
+ */
+
+typedef struct drm_radeon_setparam {
+	unsigned int param;
+	int64_t      value;
+} drm_radeon_setparam_t;
+
+#define RADEON_SETPARAM_FB_LOCATION    1 /* determined framebuffer location */
+
+
 #endif
--- diff/drivers/char/drm/radeon_drv.c	2003-07-22 18:54:27.000000000 +0100
+++ source/drivers/char/drm/radeon_drv.c	2004-02-23 13:56:41.000000000 +0000
@@ -48,6 +48,7 @@
 #include "drm_fops.h"
 #include "drm_init.h"
 #include "drm_ioctl.h"
+#include "drm_irq.h"
 #include "drm_lock.h"
 #include "drm_memory.h"
 #include "drm_proc.h"
--- diff/drivers/char/drm/radeon_drv.h	2003-09-30 15:46:12.000000000 +0100
+++ source/drivers/char/drm/radeon_drv.h	2004-02-23 13:56:41.000000000 +0000
@@ -73,6 +73,8 @@ typedef struct drm_radeon_private {
 	drm_radeon_ring_buffer_t ring;
 	drm_radeon_sarea_t *sarea_priv;
 
+	u32 fb_location;
+
 	int gart_size;
 	u32 gart_vm_start;
 	unsigned long gart_buffers_offset;
@@ -133,7 +135,6 @@ typedef struct drm_radeon_private {
 	unsigned long gart_textures_offset;
 
 	drm_local_map_t *sarea;
-	drm_local_map_t *fb;
 	drm_local_map_t *mmio;
 	drm_local_map_t *cp_ring;
 	drm_local_map_t *ring_rptr;
@@ -184,6 +185,7 @@ extern int radeon_cp_indirect( DRM_IOCTL
 extern int radeon_cp_vertex2( DRM_IOCTL_ARGS );
 extern int radeon_cp_cmdbuf( DRM_IOCTL_ARGS );
 extern int radeon_cp_getparam( DRM_IOCTL_ARGS );
+extern int radeon_cp_setparam( DRM_IOCTL_ARGS );
 extern int radeon_cp_flip( DRM_IOCTL_ARGS );
 
 extern int radeon_mem_alloc( DRM_IOCTL_ARGS );
@@ -239,6 +241,7 @@ extern void radeon_do_release(drm_device
 #define RADEON_CRTC2_OFFSET		0x0324
 #define RADEON_CRTC2_OFFSET_CNTL	0x0328
 
+#define RADEON_RB3D_COLOROFFSET		0x1c40
 #define RADEON_RB3D_COLORPITCH		0x1c48
 
 #define RADEON_DP_GUI_MASTER_CNTL	0x146c
@@ -332,6 +335,7 @@ extern void radeon_do_release(drm_device
 #define RADEON_PP_MISC			0x1c14
 #define RADEON_PP_ROT_MATRIX_0		0x1d58
 #define RADEON_PP_TXFILTER_0		0x1c54
+#define RADEON_PP_TXOFFSET_0		0x1c5c
 #define RADEON_PP_TXFILTER_1		0x1c6c
 #define RADEON_PP_TXFILTER_2		0x1c84
 
--- diff/drivers/char/drm/radeon_irq.c	2003-05-21 11:50:14.000000000 +0100
+++ source/drivers/char/drm/radeon_irq.c	2004-02-23 13:56:41.000000000 +0000
@@ -54,7 +54,7 @@
  * tied to dma at all, this is just a hangover from dri prehistory.
  */
 
-irqreturn_t DRM(dma_service)( DRM_IRQ_ARGS )
+irqreturn_t DRM(irq_handler)( DRM_IRQ_ARGS )
 {
 	drm_device_t *dev = (drm_device_t *) arg;
 	drm_radeon_private_t *dev_priv = 
--- diff/drivers/char/drm/radeon_state.c	2004-02-18 08:54:09.000000000 +0000
+++ source/drivers/char/drm/radeon_state.c	2004-02-23 13:56:41.000000000 +0000
@@ -36,6 +36,151 @@
 
 
 /* ================================================================
+ * Helper functions for client state checking and fixup
+ */
+
+static __inline__ int radeon_check_and_fixup_offset( drm_radeon_private_t *dev_priv,
+						     drm_file_t *filp_priv,
+						     u32 *offset ) {
+	u32 off = *offset;
+
+	if ( off >= dev_priv->fb_location &&
+	     off < ( dev_priv->gart_vm_start + dev_priv->gart_size ) )
+		return 0;
+
+	off += filp_priv->radeon_fb_delta;
+
+	DRM_DEBUG( "offset fixed up to 0x%x\n", off );
+
+	if ( off < dev_priv->fb_location ||
+	     off >= ( dev_priv->gart_vm_start + dev_priv->gart_size ) )
+		return DRM_ERR( EINVAL );
+
+	*offset = off;
+
+	return 0;
+}
+
+static __inline__ int radeon_check_and_fixup_offset_user( drm_radeon_private_t *dev_priv,
+							  drm_file_t *filp_priv,
+							  u32 *offset ) {
+	u32 off;
+
+	DRM_GET_USER_UNCHECKED( off, offset );
+
+	if ( radeon_check_and_fixup_offset( dev_priv, filp_priv, &off ) )
+		return DRM_ERR( EINVAL );
+
+	DRM_PUT_USER_UNCHECKED( offset, off );
+
+	return 0;
+}
+
+static __inline__ int radeon_check_and_fixup_packets( drm_radeon_private_t *dev_priv,
+						      drm_file_t *filp_priv,
+						      int id,
+						      u32 *data ) {
+	if ( id == RADEON_EMIT_PP_MISC &&
+	     radeon_check_and_fixup_offset_user( dev_priv, filp_priv,
+						 &data[( RADEON_RB3D_DEPTHOFFSET
+							 - RADEON_PP_MISC ) / 4] ) ) {
+		DRM_ERROR( "Invalid depth buffer offset\n" );
+		return DRM_ERR( EINVAL );
+	} else if ( id == RADEON_EMIT_PP_CNTL &&
+		    radeon_check_and_fixup_offset_user( dev_priv, filp_priv,
+							&data[( RADEON_RB3D_COLOROFFSET
+								- RADEON_PP_CNTL ) / 4] ) ) {
+		DRM_ERROR( "Invalid colour buffer offset\n" );
+		return DRM_ERR( EINVAL );
+	} else if ( id >= R200_EMIT_PP_TXOFFSET_0 &&
+		    id <= R200_EMIT_PP_TXOFFSET_5 &&
+		    radeon_check_and_fixup_offset_user( dev_priv, filp_priv,
+							&data[0] ) ) {
+		DRM_ERROR( "Invalid R200 texture offset\n" );
+		return DRM_ERR( EINVAL );
+	} else if ( ( id == RADEON_EMIT_PP_TXFILTER_0 || id == RADEON_EMIT_PP_TXFILTER_1 ||
+		      id == RADEON_EMIT_PP_TXFILTER_2 /*|| id == RADEON_EMIT_PP_TXFILTER_3 ||
+		      id == RADEON_EMIT_PP_TXFILTER_4 || id == RADEON_EMIT_PP_TXFILTER_5*/ ) &&
+		    radeon_check_and_fixup_offset_user( dev_priv, filp_priv,
+							&data[( RADEON_PP_TXOFFSET_0
+								- RADEON_PP_TXFILTER_0 ) / 4] ) ) {
+		DRM_ERROR( "Invalid R100 texture offset\n" );
+		return DRM_ERR( EINVAL );
+	} else if ( id == R200_PP_CUBIC_OFFSET_F1_0 || id == R200_PP_CUBIC_OFFSET_F1_1 ||
+		    id == R200_PP_CUBIC_OFFSET_F1_2 || id == R200_PP_CUBIC_OFFSET_F1_3 ||
+		    id == R200_PP_CUBIC_OFFSET_F1_4 || id == R200_PP_CUBIC_OFFSET_F1_5 ) {
+		int i;
+		for ( i = 0; i < 6; i++ ) {
+			if ( radeon_check_and_fixup_offset_user( dev_priv,
+								 filp_priv,
+								 &data[i] ) ) {
+				DRM_ERROR( "Invalid R200 cubic texture offset\n" );
+				return DRM_ERR( EINVAL );
+			}
+		}
+	}
+
+	return 0;
+}
+
+static __inline__ int radeon_check_and_fixup_packet3( drm_radeon_private_t *dev_priv,
+						      drm_file_t *filp_priv,
+						      drm_radeon_cmd_buffer_t *cmdbuf,
+						      unsigned int *cmdsz ) {
+	u32 tmp[4], *cmd = ( u32* )cmdbuf->buf;
+
+	if ( DRM_COPY_FROM_USER_UNCHECKED( tmp, cmd, sizeof( tmp ) ) ) {
+		DRM_ERROR( "Failed to copy data from user space\n" );
+		return DRM_ERR( EFAULT );
+	}
+
+	*cmdsz = 2 + ( ( tmp[0] & RADEON_CP_PACKET_COUNT_MASK ) >> 16 );
+
+	if ( ( tmp[0] & 0xc0000000 ) != RADEON_CP_PACKET3 ) {
+		DRM_ERROR( "Not a type 3 packet\n" );
+		return DRM_ERR( EINVAL );
+	}
+
+	if ( 4 * *cmdsz > cmdbuf->bufsz ) {
+		DRM_ERROR( "Packet size larger than size of data provided\n" );
+		return DRM_ERR( EINVAL );
+	}
+
+	/* Check client state and fix it up if necessary */
+	if ( tmp[0] & 0x8000 ) { /* MSB of opcode: next DWORD GUI_CNTL */
+		u32 offset;
+
+		if ( tmp[1] & ( RADEON_GMC_SRC_PITCH_OFFSET_CNTL
+			      | RADEON_GMC_DST_PITCH_OFFSET_CNTL ) ) {
+			offset = tmp[2] << 10;
+			if ( radeon_check_and_fixup_offset( dev_priv, filp_priv, &offset ) ) {
+				DRM_ERROR( "Invalid first packet offset\n" );
+				return DRM_ERR( EINVAL );
+			}
+			tmp[2] = ( tmp[2] & 0xffc00000 ) | offset >> 10;
+		}
+
+		if ( ( tmp[1] & RADEON_GMC_SRC_PITCH_OFFSET_CNTL ) &&
+		     ( tmp[1] & RADEON_GMC_DST_PITCH_OFFSET_CNTL ) ) {
+			offset = tmp[3] << 10;
+			if ( radeon_check_and_fixup_offset( dev_priv, filp_priv, &offset ) ) {
+				DRM_ERROR( "Invalid second packet offset\n" );
+				return DRM_ERR( EINVAL );
+			}
+			tmp[3] = ( tmp[3] & 0xffc00000 ) | offset >> 10;
+		}
+
+		if ( DRM_COPY_TO_USER_UNCHECKED( cmd, tmp, sizeof( tmp ) ) ) {
+			DRM_ERROR( "Failed to copy data to user space\n" );
+			return DRM_ERR( EFAULT );
+		}
+	}
+
+	return 0;
+}
+
+
+/* ================================================================
  * CP hardware state programming functions
  */
 
@@ -57,15 +202,28 @@ static __inline__ void radeon_emit_clip_
 
 /* Emit 1.1 state
  */
-static void radeon_emit_state( drm_radeon_private_t *dev_priv,
-			       drm_radeon_context_regs_t *ctx,
-			       drm_radeon_texture_regs_t *tex,
-			       unsigned int dirty )
+static int radeon_emit_state( drm_radeon_private_t *dev_priv,
+			      drm_file_t *filp_priv,
+			      drm_radeon_context_regs_t *ctx,
+			      drm_radeon_texture_regs_t *tex,
+			      unsigned int dirty )
 {
 	RING_LOCALS;
 	DRM_DEBUG( "dirty=0x%08x\n", dirty );
 
 	if ( dirty & RADEON_UPLOAD_CONTEXT ) {
+		if ( radeon_check_and_fixup_offset( dev_priv, filp_priv,
+						    &ctx->rb3d_depthoffset ) ) {
+			DRM_ERROR( "Invalid depth buffer offset\n" );
+			return DRM_ERR( EINVAL );
+		}
+
+		if ( radeon_check_and_fixup_offset( dev_priv, filp_priv,
+						    &ctx->rb3d_coloroffset ) ) {
+			DRM_ERROR( "Invalid depth buffer offset\n" );
+			return DRM_ERR( EINVAL );
+		}
+
 		BEGIN_RING( 14 );
 		OUT_RING( CP_PACKET0( RADEON_PP_MISC, 6 ) );
 		OUT_RING( ctx->pp_misc );
@@ -149,6 +307,12 @@ static void radeon_emit_state( drm_radeo
 	}
 
 	if ( dirty & RADEON_UPLOAD_TEX0 ) {
+		if ( radeon_check_and_fixup_offset( dev_priv, filp_priv,
+						    &tex[0].pp_txoffset ) ) {
+			DRM_ERROR( "Invalid texture offset for unit 0\n" );
+			return DRM_ERR( EINVAL );
+		}
+
 		BEGIN_RING( 9 );
 		OUT_RING( CP_PACKET0( RADEON_PP_TXFILTER_0, 5 ) );
 		OUT_RING( tex[0].pp_txfilter );
@@ -163,6 +327,12 @@ static void radeon_emit_state( drm_radeo
 	}
 
 	if ( dirty & RADEON_UPLOAD_TEX1 ) {
+		if ( radeon_check_and_fixup_offset( dev_priv, filp_priv,
+						    &tex[1].pp_txoffset ) ) {
+			DRM_ERROR( "Invalid texture offset for unit 1\n" );
+			return DRM_ERR( EINVAL );
+		}
+
 		BEGIN_RING( 9 );
 		OUT_RING( CP_PACKET0( RADEON_PP_TXFILTER_1, 5 ) );
 		OUT_RING( tex[1].pp_txfilter );
@@ -177,6 +347,12 @@ static void radeon_emit_state( drm_radeo
 	}
 
 	if ( dirty & RADEON_UPLOAD_TEX2 ) {
+		if ( radeon_check_and_fixup_offset( dev_priv, filp_priv,
+						    &tex[2].pp_txoffset ) ) {
+			DRM_ERROR( "Invalid texture offset for unit 2\n" );
+			return DRM_ERR( EINVAL );
+		}
+
 		BEGIN_RING( 9 );
 		OUT_RING( CP_PACKET0( RADEON_PP_TXFILTER_2, 5 ) );
 		OUT_RING( tex[2].pp_txfilter );
@@ -189,12 +365,15 @@ static void radeon_emit_state( drm_radeo
 		OUT_RING( tex[2].pp_border_color );
 		ADVANCE_RING();
 	}
+
+	return 0;
 }
 
 /* Emit 1.2 state
  */
-static void radeon_emit_state2( drm_radeon_private_t *dev_priv,
-				drm_radeon_state_t *state )
+static int radeon_emit_state2( drm_radeon_private_t *dev_priv,
+			       drm_file_t *filp_priv,
+			       drm_radeon_state_t *state )
 {
 	RING_LOCALS;
 
@@ -206,7 +385,7 @@ static void radeon_emit_state2( drm_rade
 		ADVANCE_RING();
 	}
 
-	radeon_emit_state( dev_priv, &state->context, 
+	return radeon_emit_state( dev_priv, filp_priv, &state->context,
 			   state->tex, state->dirty );
 }
 
@@ -1065,6 +1244,7 @@ static int radeon_cp_dispatch_texture( D
 				       drm_radeon_tex_image_t *image )
 {
 	drm_radeon_private_t *dev_priv = dev->dev_private;
+	drm_file_t *filp_priv;
 	drm_buf_t *buf;
 	u32 format;
 	u32 *buffer;
@@ -1074,6 +1254,13 @@ static int radeon_cp_dispatch_texture( D
 	int i;
 	RING_LOCALS;
 
+	DRM_GET_PRIV_WITH_RETURN( filp_priv, filp );
+
+	if ( radeon_check_and_fixup_offset( dev_priv, filp_priv, &tex->offset ) ) {
+		DRM_ERROR( "Invalid destination offset\n" );
+		return DRM_ERR( EINVAL );
+	}
+
 	dev_priv->stats.boxes |= RADEON_BOX_TEXTURE_LOAD;
 
 	/* Flush the pixel cache.  This ensures no pixel data gets mixed
@@ -1377,6 +1564,7 @@ int radeon_cp_vertex( DRM_IOCTL_ARGS )
 {
 	DRM_DEVICE;
 	drm_radeon_private_t *dev_priv = dev->dev_private;
+	drm_file_t *filp_priv;
 	drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
 	drm_device_dma_t *dma = dev->dma;
 	drm_buf_t *buf;
@@ -1390,6 +1578,8 @@ int radeon_cp_vertex( DRM_IOCTL_ARGS )
 		return DRM_ERR(EINVAL);
 	}
 
+	DRM_GET_PRIV_WITH_RETURN( filp_priv, filp );
+
 	DRM_COPY_FROM_USER_IOCTL( vertex, (drm_radeon_vertex_t *)data,
 			     sizeof(vertex) );
 
@@ -1429,11 +1619,14 @@ int radeon_cp_vertex( DRM_IOCTL_ARGS )
 		buf->used = vertex.count; /* not used? */
 
 		if ( sarea_priv->dirty & ~RADEON_UPLOAD_CLIPRECTS ) {
-			radeon_emit_state( dev_priv,
-					   &sarea_priv->context_state,
-					   sarea_priv->tex_state,
-					   sarea_priv->dirty );
-			
+			if ( radeon_emit_state( dev_priv, filp_priv,
+						&sarea_priv->context_state,
+						sarea_priv->tex_state,
+						sarea_priv->dirty ) ) {
+				DRM_ERROR( "radeon_emit_state failed\n" );
+				return DRM_ERR( EINVAL );
+			}
+
 			sarea_priv->dirty &= ~(RADEON_UPLOAD_TEX0IMAGES |
 					       RADEON_UPLOAD_TEX1IMAGES |
 					       RADEON_UPLOAD_TEX2IMAGES |
@@ -1461,6 +1654,7 @@ int radeon_cp_indices( DRM_IOCTL_ARGS )
 {
 	DRM_DEVICE;
 	drm_radeon_private_t *dev_priv = dev->dev_private;
+	drm_file_t *filp_priv;
 	drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
 	drm_device_dma_t *dma = dev->dma;
 	drm_buf_t *buf;
@@ -1475,6 +1669,8 @@ int radeon_cp_indices( DRM_IOCTL_ARGS )
 		return DRM_ERR(EINVAL);
 	}
 
+	DRM_GET_PRIV_WITH_RETURN( filp_priv, filp );
+
 	DRM_COPY_FROM_USER_IOCTL( elts, (drm_radeon_indices_t *)data,
 			     sizeof(elts) );
 
@@ -1523,10 +1719,13 @@ int radeon_cp_indices( DRM_IOCTL_ARGS )
 	buf->used = elts.end;
 
 	if ( sarea_priv->dirty & ~RADEON_UPLOAD_CLIPRECTS ) {
-		radeon_emit_state( dev_priv,
-				   &sarea_priv->context_state,
-				   sarea_priv->tex_state,
-				   sarea_priv->dirty );
+		if ( radeon_emit_state( dev_priv, filp_priv,
+					&sarea_priv->context_state,
+					sarea_priv->tex_state,
+					sarea_priv->dirty ) ) {
+			DRM_ERROR( "radeon_emit_state failed\n" );
+			return DRM_ERR( EINVAL );
+		}
 
 		sarea_priv->dirty &= ~(RADEON_UPLOAD_TEX0IMAGES |
 				       RADEON_UPLOAD_TEX1IMAGES |
@@ -1686,6 +1885,7 @@ int radeon_cp_vertex2( DRM_IOCTL_ARGS )
 {
 	DRM_DEVICE;
 	drm_radeon_private_t *dev_priv = dev->dev_private;
+	drm_file_t *filp_priv;
 	drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
 	drm_device_dma_t *dma = dev->dma;
 	drm_buf_t *buf;
@@ -1700,6 +1900,8 @@ int radeon_cp_vertex2( DRM_IOCTL_ARGS )
 		return DRM_ERR(EINVAL);
 	}
 
+	DRM_GET_PRIV_WITH_RETURN( filp_priv, filp );
+
 	DRM_COPY_FROM_USER_IOCTL( vertex, (drm_radeon_vertex2_t *)data,
 			     sizeof(vertex) );
 
@@ -1747,7 +1949,10 @@ int radeon_cp_vertex2( DRM_IOCTL_ARGS )
 					     sizeof(state) ) )
 				return DRM_ERR(EFAULT);
 
-			radeon_emit_state2( dev_priv, &state );
+			if ( radeon_emit_state2( dev_priv, filp_priv, &state ) ) {
+				DRM_ERROR( "radeon_emit_state2 failed\n" );
+				return DRM_ERR( EINVAL );
+			}
 
 			laststate = prim.stateidx;
 		}
@@ -1784,6 +1989,7 @@ int radeon_cp_vertex2( DRM_IOCTL_ARGS )
 
 static int radeon_emit_packets( 
 	drm_radeon_private_t *dev_priv,
+	drm_file_t *filp_priv,
 	drm_radeon_cmd_header_t header,
 	drm_radeon_cmd_buffer_t *cmdbuf )
 {
@@ -1798,8 +2004,15 @@ static int radeon_emit_packets( 
 	sz = packet[id].len;
 	reg = packet[id].start;
 
-	if (sz * sizeof(int) > cmdbuf->bufsz) 
+	if (sz * sizeof(int) > cmdbuf->bufsz) {
+		DRM_ERROR( "Packet size provided larger than data provided\n" );
 		return DRM_ERR(EINVAL);
+	}
+
+	if ( radeon_check_and_fixup_packets( dev_priv, filp_priv, id, data ) ) {
+		DRM_ERROR( "Packet verification failed\n" );
+		return DRM_ERR( EINVAL );
+	}
 
 	BEGIN_RING(sz+1);
 	OUT_RING( CP_PACKET0( reg, (sz-1) ) );
@@ -1882,24 +2095,21 @@ static __inline__ int radeon_emit_vector
 
 
 static int radeon_emit_packet3( drm_device_t *dev,
+				drm_file_t *filp_priv,
 				drm_radeon_cmd_buffer_t *cmdbuf )
 {
 	drm_radeon_private_t *dev_priv = dev->dev_private;
-	int cmdsz, tmp;
-	int *cmd = (int *)cmdbuf->buf;
+	unsigned int cmdsz;
+	int *cmd = (int *)cmdbuf->buf, ret;
 	RING_LOCALS;
 
-
 	DRM_DEBUG("\n");
 
-	if (DRM_GET_USER_UNCHECKED( tmp, &cmd[0]))
-		return DRM_ERR(EFAULT);
-
-	cmdsz = 2 + ((tmp & RADEON_CP_PACKET_COUNT_MASK) >> 16);
-
-	if ((tmp & 0xc0000000) != RADEON_CP_PACKET3 ||
-	    cmdsz * 4 > cmdbuf->bufsz)
-		return DRM_ERR(EINVAL);
+	if ( ( ret = radeon_check_and_fixup_packet3( dev_priv, filp_priv,
+						     cmdbuf, &cmdsz ) ) ) {
+		DRM_ERROR( "Packet verification failed\n" );
+		return ret;
+	}
 
 	BEGIN_RING( cmdsz );
 	OUT_RING_USER_TABLE( cmd, cmdsz );
@@ -1912,27 +2122,25 @@ static int radeon_emit_packet3( drm_devi
 
 
 static int radeon_emit_packet3_cliprect( drm_device_t *dev,
+					 drm_file_t *filp_priv,
 					 drm_radeon_cmd_buffer_t *cmdbuf,
 					 int orig_nbox )
 {
 	drm_radeon_private_t *dev_priv = dev->dev_private;
 	drm_clip_rect_t box;
-	int cmdsz, tmp;
-	int *cmd = (int *)cmdbuf->buf;
+	unsigned int cmdsz;
+	int *cmd = (int *)cmdbuf->buf, ret;
 	drm_clip_rect_t *boxes = cmdbuf->boxes;
 	int i = 0;
 	RING_LOCALS;
 
 	DRM_DEBUG("\n");
 
-	if (DRM_GET_USER_UNCHECKED( tmp, &cmd[0]))
-		return DRM_ERR(EFAULT);
-
-	cmdsz = 2 + ((tmp & RADEON_CP_PACKET_COUNT_MASK) >> 16);
-
-	if ((tmp & 0xc0000000) != RADEON_CP_PACKET3 ||
-	    cmdsz * 4 > cmdbuf->bufsz)
-		return DRM_ERR(EINVAL);
+	if ( ( ret = radeon_check_and_fixup_packet3( dev_priv, filp_priv,
+						     cmdbuf, &cmdsz ) ) ) {
+		DRM_ERROR( "Packet verification failed\n" );
+		return ret;
+	}
 
 	if (!orig_nbox)
 		goto out;
@@ -2009,6 +2217,7 @@ int radeon_cp_cmdbuf( DRM_IOCTL_ARGS )
 {
 	DRM_DEVICE;
 	drm_radeon_private_t *dev_priv = dev->dev_private;
+	drm_file_t *filp_priv;
 	drm_device_dma_t *dma = dev->dma;
 	drm_buf_t *buf = 0;
 	int idx;
@@ -2023,6 +2232,8 @@ int radeon_cp_cmdbuf( DRM_IOCTL_ARGS )
 		return DRM_ERR(EINVAL);
 	}
 
+	DRM_GET_PRIV_WITH_RETURN( filp_priv, filp );
+
 	DRM_COPY_FROM_USER_IOCTL( cmdbuf, (drm_radeon_cmd_buffer_t *)data,
 			     sizeof(cmdbuf) );
 
@@ -2053,7 +2264,7 @@ int radeon_cp_cmdbuf( DRM_IOCTL_ARGS )
 		switch (header.header.cmd_type) {
 		case RADEON_CMD_PACKET: 
 			DRM_DEBUG("RADEON_CMD_PACKET\n");
-			if (radeon_emit_packets( dev_priv, header, &cmdbuf )) {
+			if (radeon_emit_packets( dev_priv, filp_priv, header, &cmdbuf )) {
 				DRM_ERROR("radeon_emit_packets failed\n");
 				return DRM_ERR(EINVAL);
 			}
@@ -2096,7 +2307,7 @@ int radeon_cp_cmdbuf( DRM_IOCTL_ARGS )
 
 		case RADEON_CMD_PACKET3:
 			DRM_DEBUG("RADEON_CMD_PACKET3\n");
-			if (radeon_emit_packet3( dev, &cmdbuf )) {
+			if (radeon_emit_packet3( dev, filp_priv, &cmdbuf )) {
 				DRM_ERROR("radeon_emit_packet3 failed\n");
 				return DRM_ERR(EINVAL);
 			}
@@ -2104,7 +2315,7 @@ int radeon_cp_cmdbuf( DRM_IOCTL_ARGS )
 
 		case RADEON_CMD_PACKET3_CLIP:
 			DRM_DEBUG("RADEON_CMD_PACKET3_CLIP\n");
-			if (radeon_emit_packet3_cliprect( dev, &cmdbuf, orig_nbox )) {
+			if (radeon_emit_packet3_cliprect( dev, filp_priv, &cmdbuf, orig_nbox )) {
 				DRM_ERROR("radeon_emit_packet3_clip failed\n");
 				return DRM_ERR(EINVAL);
 			}
@@ -2214,3 +2425,31 @@ int radeon_cp_getparam( DRM_IOCTL_ARGS )
 	
 	return 0;
 }
+
+int radeon_cp_setparam( DRM_IOCTL_ARGS ) {
+	DRM_DEVICE;
+	drm_radeon_private_t *dev_priv = dev->dev_private;
+	drm_file_t *filp_priv;
+	drm_radeon_setparam_t sp;
+
+	if ( !dev_priv ) {
+		DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ );
+		return DRM_ERR( EINVAL );
+	}
+
+	DRM_GET_PRIV_WITH_RETURN( filp_priv, filp );
+
+	DRM_COPY_FROM_USER_IOCTL( sp, ( drm_radeon_setparam_t* )data,
+				  sizeof( sp ) );
+
+	switch( sp.param ) {
+	case RADEON_SETPARAM_FB_LOCATION:
+		filp_priv->radeon_fb_delta = dev_priv->fb_location - sp.value;
+		break;
+	default:
+		DRM_DEBUG( "Invalid parameter %d\n", sp.param );
+		return DRM_ERR( EINVAL );
+	}
+
+	return 0;
+}
--- diff/drivers/char/drm/sis.h	2003-09-30 15:46:12.000000000 +0100
+++ source/drivers/char/drm/sis.h	2004-02-23 13:56:41.000000000 +0000
@@ -62,6 +62,13 @@
 	[DRM_IOCTL_NR(DRM_IOCTL_SIS_AGP_FREE)]	= { sis_ioctl_agp_free,	1, 0 }, \
 	[DRM_IOCTL_NR(DRM_IOCTL_SIS_FB_INIT)]	= { sis_fb_init,	1, 1 }
 
+#define DRIVER_PCI_IDS							\
+	{0x1039, 0x0300, 0, "SiS 300/305"},				\
+	{0x1039, 0x5300, 0, "SiS 540"},					\
+	{0x1039, 0x6300, 0, "SiS 630"},					\
+	{0x1039, 0x7300, 0, "SiS 730"},					\
+	{0, 0, 0, NULL}
+
 #define __HAVE_COUNTERS		5
 
 /* Buffer customization:
--- diff/drivers/char/drm/sis_mm.c	2003-09-30 15:46:12.000000000 +0100
+++ source/drivers/char/drm/sis_mm.c	2004-02-23 13:56:41.000000000 +0000
@@ -34,7 +34,11 @@
 #include "sis_drv.h"
 #include "sis_ds.h"
 #if defined(__linux__) && defined(CONFIG_FB_SIS)
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
 #include <video/sisfb.h>
+#else
+#include <linux/sisfb.h>
+#endif
 #endif
 
 #define MAX_CONTEXT 100
@@ -132,7 +136,7 @@ int sis_fb_free( DRM_IOCTL_ARGS )
 		retval = DRM_ERR(EINVAL);
 	sis_free(fb.free);
 
-	DRM_DEBUG("free fb, offset = %lu\n", fb.free);
+	DRM_DEBUG("free fb, offset = 0x%lx\n", fb.free);
 
 	return retval;
 }
--- diff/drivers/char/drm/tdfx.h	2002-10-16 04:28:22.000000000 +0100
+++ source/drivers/char/drm/tdfx.h	2004-02-23 13:56:41.000000000 +0000
@@ -39,4 +39,22 @@
 #define __HAVE_MTRR		1
 #define __HAVE_CTX_BITMAP	1
 
+#define DRIVER_AUTHOR		"VA Linux Systems Inc."
+
+#define DRIVER_NAME		"tdfx"
+#define DRIVER_DESC		"3dfx Banshee/Voodoo3+"
+#define DRIVER_DATE		"20010216"
+
+#define DRIVER_MAJOR		1
+#define DRIVER_MINOR		0
+#define DRIVER_PATCHLEVEL	0
+
+#define DRIVER_PCI_IDS							\
+	{0x121a, 0x0003, 0, "3dfx Voodoo Banshee"},			\
+	{0x121a, 0x0004, 0, "3dfx Voodoo3 2000"},			\
+	{0x121a, 0x0005, 0, "3dfx Voodoo3 3000"},			\
+	{0x121a, 0x0007, 0, "3dfx Voodoo4"},				\
+	{0x121a, 0x0009, 0, "3dfx Voodoo5"},				\
+	{0, 0, 0, NULL}
+
 #endif
--- diff/drivers/char/drm/tdfx_drv.c	2002-10-16 04:28:22.000000000 +0100
+++ source/drivers/char/drm/tdfx_drv.c	2004-02-23 13:56:41.000000000 +0000
@@ -34,47 +34,6 @@
 #include "tdfx.h"
 #include "drmP.h"
 
-#define DRIVER_AUTHOR		"VA Linux Systems Inc."
-
-#define DRIVER_NAME		"tdfx"
-#define DRIVER_DESC		"3dfx Banshee/Voodoo3+"
-#define DRIVER_DATE		"20010216"
-
-#define DRIVER_MAJOR		1
-#define DRIVER_MINOR		0
-#define DRIVER_PATCHLEVEL	0
-
-#ifndef PCI_VENDOR_ID_3DFX
-#define PCI_VENDOR_ID_3DFX 0x121A
-#endif
-#ifndef PCI_DEVICE_ID_3DFX_VOODOO5
-#define PCI_DEVICE_ID_3DFX_VOODOO5 0x0009
-#endif
-#ifndef PCI_DEVICE_ID_3DFX_VOODOO4
-#define PCI_DEVICE_ID_3DFX_VOODOO4 0x0007
-#endif
-#ifndef PCI_DEVICE_ID_3DFX_VOODOO3_3000 /* Voodoo3 3000 */
-#define PCI_DEVICE_ID_3DFX_VOODOO3_3000 0x0005
-#endif
-#ifndef PCI_DEVICE_ID_3DFX_VOODOO3_2000 /* Voodoo3 3000 */
-#define PCI_DEVICE_ID_3DFX_VOODOO3_2000 0x0004
-#endif
-#ifndef PCI_DEVICE_ID_3DFX_BANSHEE
-#define PCI_DEVICE_ID_3DFX_BANSHEE 0x0003
-#endif
-
-static drm_pci_list_t DRM(idlist)[] = {
-	{ PCI_VENDOR_ID_3DFX, PCI_DEVICE_ID_3DFX_BANSHEE },
-	{ PCI_VENDOR_ID_3DFX, PCI_DEVICE_ID_3DFX_VOODOO3_2000 },
-	{ PCI_VENDOR_ID_3DFX, PCI_DEVICE_ID_3DFX_VOODOO3_3000 },
-	{ PCI_VENDOR_ID_3DFX, PCI_DEVICE_ID_3DFX_VOODOO4 },
-	{ PCI_VENDOR_ID_3DFX, PCI_DEVICE_ID_3DFX_VOODOO5 },
-	{ 0, 0 }
-};
-
-#define DRIVER_CARD_LIST DRM(idlist)
-
-
 #include "drm_auth.h"
 #include "drm_bufs.h"
 #include "drm_context.h"
--- diff/drivers/char/epca.c	2003-10-09 09:47:16.000000000 +0100
+++ source/drivers/char/epca.c	2004-02-23 13:56:41.000000000 +0000
@@ -2931,6 +2931,96 @@ static int info_ioctl(struct tty_struct 
 }
 /* --------------------- Begin pc_ioctl  ----------------------- */
 
+static int pc_tiocmget(struct tty_struct *tty, struct file *file)
+{
+	struct channel *ch = (struct channel *) tty->driver_data;
+	volatile struct board_chan *bc;
+	unsigned int mstat, mflag = 0;
+	unsigned long flags;
+
+	if (ch)
+		bc = ch->brdchan;
+	else
+	{
+		printk(KERN_ERR "<Error> - ch is NULL in pc_tiocmget!\n");
+		return(-EINVAL);
+	}
+
+	save_flags(flags);
+	cli();
+	globalwinon(ch);
+	mstat = bc->mstat;
+	memoff(ch);
+	restore_flags(flags);
+
+	if (mstat & ch->m_dtr)
+		mflag |= TIOCM_DTR;
+
+	if (mstat & ch->m_rts)
+		mflag |= TIOCM_RTS;
+
+	if (mstat & ch->m_cts)
+		mflag |= TIOCM_CTS;
+
+	if (mstat & ch->dsr)
+		mflag |= TIOCM_DSR;
+
+	if (mstat & ch->m_ri)
+		mflag |= TIOCM_RI;
+
+	if (mstat & ch->dcd)
+		mflag |= TIOCM_CD;
+
+	return mflag;
+}
+
+static int pc_tiocmset(struct tty_struct *tty, struct file *file,
+		       unsigned int set, unsigned int clear)
+{
+	struct channel *ch = (struct channel *) tty->driver_data;
+	unsigned long flags;
+
+	if (!ch) {
+		printk(KERN_ERR "<Error> - ch is NULL in pc_tiocmset!\n");
+		return(-EINVAL);
+	}
+
+	save_flags(flags);
+	cli();
+	/*
+	 * I think this modemfake stuff is broken.  It doesn't
+	 * correctly reflect the behaviour desired by the TIOCM*
+	 * ioctls.  Therefore this is probably broken.
+	 */
+	if (set & TIOCM_RTS) {
+		ch->modemfake |= ch->m_rts;
+		ch->modem |= ch->m_rts;
+	}
+	if (set & TIOCM_DTR) {
+		ch->modemfake |= ch->m_dtr;
+		ch->modem |= ch->m_dtr;
+	}
+	if (clear & TIOCM_RTS) {
+		ch->modemfake |= ch->m_rts;
+		ch->modem &= ~ch->m_rts;
+	}
+	if (clear & TIOCM_DTR) {
+		ch->modemfake |= ch->m_dtr;
+		ch->modem &= ~ch->m_dtr;
+	}
+
+	globalwinon(ch);
+
+	/*  --------------------------------------------------------------
+		The below routine generally sets up parity, baud, flow control
+		issues, etc.... It effect both control flags and input flags.
+	------------------------------------------------------------------ */
+
+	epcaparam(tty,ch);
+	memoff(ch);
+	restore_flags(flags);
+}
+
 static int pc_ioctl(struct tty_struct *tty, struct file * file,
 		    unsigned int cmd, unsigned long arg)
 { /* Begin pc_ioctl */
@@ -3021,90 +3111,15 @@ static int pc_ioctl(struct tty_struct *t
 		}
 
 		case TIOCMODG:
-		case TIOCMGET:
-
-			mflag = 0;
-
-			cli();
-			globalwinon(ch);
-			mstat = bc->mstat;
-			memoff(ch);
-			restore_flags(flags);
-
-			if (mstat & ch->m_dtr)
-				mflag |= TIOCM_DTR;
-
-			if (mstat & ch->m_rts)
-				mflag |= TIOCM_RTS;
-
-			if (mstat & ch->m_cts)
-				mflag |= TIOCM_CTS;
-
-			if (mstat & ch->dsr)
-				mflag |= TIOCM_DSR;
-
-			if (mstat & ch->m_ri)
-				mflag |= TIOCM_RI;
-
-			if (mstat & ch->dcd)
-				mflag |= TIOCM_CD;
-
-			error = verify_area(VERIFY_WRITE, (void *) arg,sizeof(long));
-
-			if (error)
-				return error;
-
-			putUser(mflag, (unsigned int *) arg);
-
+			mflag = pc_tiocmget(tty, file);
+			if (putUser(mflag, (unsigned int *) arg))
+				return -EFAULT;
 			break;
 
-		case TIOCMBIS:
-		case TIOCMBIC:
 		case TIOCMODS:
-		case TIOCMSET:
-
-			getUser(mstat, (unsigned int *)arg);
-
-			mflag = 0;
-			if (mstat & TIOCM_DTR)
-				mflag |= ch->m_dtr;
-
-			if (mstat & TIOCM_RTS)
-				mflag |= ch->m_rts;
-
-			switch (cmd) 
-			{ /* Begin switch cmd */
-
-				case TIOCMODS:
-				case TIOCMSET:
-					ch->modemfake = ch->m_dtr|ch->m_rts;
-					ch->modem = mflag;
-					break;
-
-				case TIOCMBIS:
-					ch->modemfake |= mflag;
-					ch->modem |= mflag;
-					break;
-
-				case TIOCMBIC:
-					ch->modemfake |= mflag;
-					ch->modem &= ~mflag;
-					break;
-
-			} /* End switch cmd */
-
-			cli();
-			globalwinon(ch);
-
-			/*  --------------------------------------------------------------
-				The below routine generally sets up parity, baud, flow control 
-				issues, etc.... It effect both control flags and input flags.
-			------------------------------------------------------------------ */
-
-			epcaparam(tty,ch);
-			memoff(ch);
-			restore_flags(flags);
-			break;
+			if (getUser(mstat, (unsigned int *)arg))
+				return -EFAULT;
+			return pc_tiocmset(tty, file, mstat, ~mstat);
 
 		case TIOCSDTR:
 			ch->omodem |= ch->m_dtr;
--- diff/drivers/char/esp.c	2003-10-09 09:47:34.000000000 +0100
+++ source/drivers/char/esp.c	2004-02-23 13:56:41.000000000 +0000
@@ -1753,55 +1753,52 @@ static int get_lsr_info(struct esp_struc
 }
 
 
-static int get_modem_info(struct esp_struct * info, unsigned int *value)
+static int esp_tiocmget(struct tty_struct *tty, struct file *file)
 {
+	struct esp_struct * info = (struct esp_struct *)tty->driver_data;
 	unsigned char control, status;
-	unsigned int result;
+
+	if (serial_paranoia_check(info, tty->name, __FUNCTION__))
+		return -ENODEV;
+	if (tty->flags & (1 << TTY_IO_ERROR))
+		return -EIO;
 
 	control = info->MCR;
 	cli();
 	serial_out(info, UART_ESI_CMD1, ESI_GET_UART_STAT);
 	status = serial_in(info, UART_ESI_STAT2);
 	sti();
-	result =  ((control & UART_MCR_RTS) ? TIOCM_RTS : 0)
+	return    ((control & UART_MCR_RTS) ? TIOCM_RTS : 0)
 		| ((control & UART_MCR_DTR) ? TIOCM_DTR : 0)
 		| ((status  & UART_MSR_DCD) ? TIOCM_CAR : 0)
 		| ((status  & UART_MSR_RI) ? TIOCM_RNG : 0)
 		| ((status  & UART_MSR_DSR) ? TIOCM_DSR : 0)
 		| ((status  & UART_MSR_CTS) ? TIOCM_CTS : 0);
-	return put_user(result,value);
 }
 
-static int set_modem_info(struct esp_struct * info, unsigned int cmd,
-			  unsigned int *value)
+static int esp_tiocmset(struct tty_struct *tty, struct file *file,
+			unsigned int set, unsigned int clear)
 {
+	struct esp_struct * info = (struct esp_struct *)tty->driver_data;
 	unsigned int arg;
 
-	if (get_user(arg, value))
-		return -EFAULT;
+	if (serial_paranoia_check(info, tty->name, __FUNCTION__))
+		return -ENODEV;
+	if (tty->flags & (1 << TTY_IO_ERROR))
+		return -EIO;
 
-	switch (cmd) {
-	case TIOCMBIS: 
-		if (arg & TIOCM_RTS)
-			info->MCR |= UART_MCR_RTS;
-		if (arg & TIOCM_DTR)
-			info->MCR |= UART_MCR_DTR;
-		break;
-	case TIOCMBIC:
-		if (arg & TIOCM_RTS)
-			info->MCR &= ~UART_MCR_RTS;
-		if (arg & TIOCM_DTR)
-			info->MCR &= ~UART_MCR_DTR;
-		break;
-	case TIOCMSET:
-		info->MCR = ((info->MCR & ~(UART_MCR_RTS | UART_MCR_DTR))
-			     | ((arg & TIOCM_RTS) ? UART_MCR_RTS : 0)
-			     | ((arg & TIOCM_DTR) ? UART_MCR_DTR : 0));
-		break;
-	default:
-		return -EINVAL;
-	}
 	cli();
+
+	if (set & TIOCM_RTS)
+		info->MCR |= UART_MCR_RTS;
+	if (set & TIOCM_DTR)
+		info->MCR |= UART_MCR_DTR;
+
+	if (clear & TIOCM_RTS)
+		info->MCR &= ~UART_MCR_RTS;
+	if (clear & TIOCM_DTR)
+		info->MCR &= ~UART_MCR_DTR;
+
 	serial_out(info, UART_ESI_CMD1, ESI_WRITE_UART);
 	serial_out(info, UART_ESI_CMD2, UART_MCR);
 	serial_out(info, UART_ESI_CMD2, info->MCR);
@@ -1853,12 +1850,6 @@ static int rs_ioctl(struct tty_struct *t
 	}
 	
 	switch (cmd) {
-		case TIOCMGET:
-			return get_modem_info(info, (unsigned int *) arg);
-		case TIOCMBIS:
-		case TIOCMBIC:
-		case TIOCMSET:
-			return set_modem_info(info, cmd, (unsigned int *) arg);
 		case TIOCGSERIAL:
 			return get_serial_info(info,
 					       (struct serial_struct *) arg);
@@ -2444,6 +2435,8 @@ static struct tty_operations esp_ops = {
 	.hangup = esp_hangup,
 	.break_ctl = esp_break,
 	.wait_until_sent = rs_wait_until_sent,
+	.tiocmget = esp_tiocmget,
+	.tiocmset = esp_tiocmset,
 };
 
 /*
--- diff/drivers/char/ftape/compressor/zftape-compress.c	2003-10-09 09:47:34.000000000 +0100
+++ source/drivers/char/ftape/compressor/zftape-compress.c	2004-02-23 13:56:41.000000000 +0000
@@ -60,8 +60,6 @@
 
 /* local variables 
  */
-static int keep_module_locked = 1;
-
 static void *zftc_wrk_mem = NULL;
 static __u8 *zftc_buf     = NULL;
 static void *zftc_scratch_buf  = NULL;
@@ -268,10 +266,6 @@ static void get_next_cluster(cmpr_info *
 
 static void zftc_lock(void)
 {
-	MOD_INC_USE_COUNT; /*  sets MOD_VISITED and MOD_USED_ONCE,
-			    *  locking is done with can_unload()
-			    */
-	keep_module_locked = 1;
 }
 
 /*  this function is needed for zftape_reset_position in zftape-io.c 
@@ -282,7 +276,6 @@ static void zftc_reset(void)
 
 	memset((void *)&cseg, '\0', sizeof(cseg));
 	zftc_stats();
-	keep_module_locked = 0;
 	TRACE_EXIT;
 }
 
@@ -555,10 +548,6 @@ static int zftc_write(int *write_cnt,
 	int buf_pos_write = pos->seg_byte_pos;
 	TRACE_FUN(ft_t_flow);
 	
-	keep_module_locked = 1;
-	MOD_INC_USE_COUNT; /*  sets MOD_VISITED and MOD_USED_ONCE,
-			    *  locking is done with can_unload()
-			    */
 	/* Note: we do not unlock the module because
 	 * there are some values cached in that `cseg' variable.  We
 	 * don't don't want to use this information when being
@@ -676,10 +665,6 @@ static int zftc_read (int *read_cnt, 
 	int remaining = to_do;
 	TRACE_FUN(ft_t_flow);
 
-	keep_module_locked = 1;
-	MOD_INC_USE_COUNT; /*  sets MOD_VISITED and MOD_USED_ONCE,
-			    *  locking is done with can_unload()
-			    */
 	TRACE_CATCH(zft_allocate_cmpr_mem(volume->blk_sz),);
 	if (pos->seg_byte_pos == 0) {
 		/* new segment just read
@@ -800,10 +785,6 @@ static int zftc_seek(unsigned int new_bl
 	int fast_seek_trials = 0;
 	TRACE_FUN(ft_t_flow);
 
-	keep_module_locked = 1;
-	MOD_INC_USE_COUNT; /*  sets MOD_VISITED and MOD_USED_ONCE,
-			    *  locking is done with can_unload()
-			    */
 	if (new_block_pos == 0) {
 		pos->seg_pos      = volume->start_seg;
 		pos->seg_byte_pos = 0;
@@ -1222,31 +1203,7 @@ MODULE_LICENSE("GPL");
  */
 int init_module(void)
 {
-	int result;
-
-#if 0 /* FIXME --RR */
-	if (!mod_member_present(&__this_module, can_unload))
-		return -EBUSY;
-	__this_module.can_unload = can_unload;
-#endif
-	result = zft_compressor_init();
-	keep_module_locked = 0;
-	return result;
+	return zft_compressor_init();
 }
 
-/* Called by modules package when removing the driver 
- */
-void cleanup_module(void)
-{
-	TRACE_FUN(ft_t_flow);
-
-	if (zft_cmpr_unregister() != &cmpr_ops) {
-		TRACE(ft_t_info, "failed");
-	} else {
-		TRACE(ft_t_info, "successful");
-	}
-	zftc_cleanup();
-        printk(KERN_INFO "zft-compressor successfully unloaded.\n");
-	TRACE_EXIT;
-}
 #endif /* MODULE */
--- diff/drivers/char/genrtc.c	2004-02-09 10:36:10.000000000 +0000
+++ source/drivers/char/genrtc.c	2004-02-23 13:56:41.000000000 +0000
@@ -523,4 +523,4 @@ module_exit(rtc_generic_exit);
 
 MODULE_AUTHOR("Richard Zidlicky");
 MODULE_LICENSE("GPL");
-
+MODULE_ALIAS_MISCDEV(RTC_MINOR);
--- diff/drivers/char/hw_random.c	2003-09-30 15:46:13.000000000 +0100
+++ source/drivers/char/hw_random.c	2004-02-23 13:56:41.000000000 +0000
@@ -454,11 +454,7 @@ static int __init via_init(struct pci_de
 
 static void via_cleanup(void)
 {
-	u32 lo, hi;
-
-	rdmsr(MSR_VIA_RNG, lo, hi);
-	lo &= ~VIA_RNG_ENABLE;
-	wrmsr(MSR_VIA_RNG, lo, hi);
+	/* do nothing */
 }
 
 
--- diff/drivers/char/ip2/ip2.h	2003-05-21 11:49:54.000000000 +0100
+++ source/drivers/char/ip2/ip2.h	2004-02-23 13:56:41.000000000 +0000
@@ -59,7 +59,7 @@
  * console warning.
  
  * When the driver is loaded as a module these setting can be overridden on the 
- * modprobe command line or on an option line in /etc/modules.conf.
+ * modprobe command line or on an option line in /etc/modprobe.conf.
  * If the driver is built-in the configuration must be 
  * set here for ISA cards and address set to 1 and 2 for PCI and EISA.
  *
@@ -80,7 +80,7 @@
 
  /* this structure is zeroed out because the suggested method is to configure
   * the driver as a module, set up the parameters with an options line in
-  * /etc/modules.conf and load with modprobe, kerneld or kmod, the kernel
+  * /etc/modprobe.conf and load with modprobe or kmod, the kernel
   * module loader
   */
 
--- diff/drivers/char/ip2main.c	2003-10-09 09:47:34.000000000 +0100
+++ source/drivers/char/ip2main.c	2004-02-23 13:56:41.000000000 +0000
@@ -186,6 +186,9 @@ static void ip2_unthrottle(PTTY);
 static void ip2_stop(PTTY);
 static void ip2_start(PTTY);
 static void ip2_hangup(PTTY);
+static int  ip2_tiocmget(struct tty_struct *tty, struct file *file);
+static int  ip2_tiocmset(struct tty_struct *tty, struct file *file,
+			 unsigned int set, unsigned int clear);
 
 static void set_irq(int, int);
 static void ip2_interrupt_bh(i2eBordStrPtr pB);
@@ -466,6 +469,8 @@ static struct tty_operations ip2_ops = {
 	.start           = ip2_start,
 	.hangup          = ip2_hangup,
 	.read_proc       = ip2_read_proc,
+	.tiocmget	 = ip2_tiocmget,
+	.tiocmset	 = ip2_tiocmset,
 };
 
 /******************************************************************************/
@@ -1951,6 +1956,80 @@ ip2_stop ( PTTY tty )
 /* Device Ioctl Section                                                       */
 /******************************************************************************/
 
+static int ip2_tiocmget(struct tty_struct *tty, struct file *file)
+{
+	i2ChanStrPtr pCh = DevTable[tty->index];
+	wait_queue_t wait;
+
+	if (pCh == NULL)
+		return -ENODEV;
+
+/*
+	FIXME - the following code is causing a NULL pointer dereference in
+	2.3.51 in an interrupt handler.  It's suppose to prompt the board
+	to return the DSS signal status immediately.  Why doesn't it do
+	the same thing in 2.2.14?
+*/
+
+/*	This thing is still busted in the 1.2.12 driver on 2.4.x
+	and even hoses the serial console so the oops can be trapped.
+		/\/\|=mhw=|\/\/			*/
+
+#ifdef	ENABLE_DSSNOW
+	i2QueueCommands(PTYPE_BYPASS, pCh, 100, 1, CMD_DSS_NOW);
+
+	init_waitqueue_entry(&wait, current);
+	add_wait_queue(&pCh->dss_now_wait, &wait);
+	set_current_state( TASK_INTERRUPTIBLE );
+
+	serviceOutgoingFifo( pCh->pMyBord );
+
+	schedule();
+
+	set_current_state( TASK_RUNNING );
+	remove_wait_queue(&pCh->dss_now_wait, &wait);
+
+	if (signal_pending(current)) {
+		return -EINTR;
+	}
+#endif
+	return  ((pCh->dataSetOut & I2_RTS) ? TIOCM_RTS : 0)
+	      | ((pCh->dataSetOut & I2_DTR) ? TIOCM_DTR : 0)
+	      | ((pCh->dataSetIn  & I2_DCD) ? TIOCM_CAR : 0)
+	      | ((pCh->dataSetIn  & I2_RI)  ? TIOCM_RNG : 0)
+	      | ((pCh->dataSetIn  & I2_DSR) ? TIOCM_DSR : 0)
+	      | ((pCh->dataSetIn  & I2_CTS) ? TIOCM_CTS : 0);
+}
+
+static int ip2_tiocmset(struct tty_struct *tty, struct file *file,
+			unsigned int set, unsigned int clear)
+{
+	i2ChanStrPtr pCh = DevTable[tty->index];
+
+	if (pCh == NULL)
+		return -ENODEV;
+
+	if (set & TIOCM_RTS) {
+		i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_RTSUP);
+		pCh->dataSetOut |= I2_RTS;
+	}
+	if (set & TIOCM_DTR) {
+		i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_DTRUP);
+		pCh->dataSetOut |= I2_DTR;
+	}
+
+	if (clear & TIOCM_RTS) {
+		i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_RTSDN);
+		pCh->dataSetOut &= ~I2_RTS;
+	}
+	if (clear & TIOCM_DTR) {
+		i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_DTRDN);
+		pCh->dataSetOut &= ~I2_DTR;
+	}
+	serviceOutgoingFifo( pCh->pMyBord );
+	return 0;
+}
+
 /******************************************************************************/
 /* Function:   ip2_ioctl()                                                    */
 /* Parameters: Pointer to tty structure                                       */
@@ -2078,57 +2157,6 @@ ip2_ioctl ( PTTY tty, struct file *pFile
 		
 		break;
 
-	case TIOCMGET:
-
-		ip2trace (CHANN, ITRC_IOCTL, 8, 1, rc );
-
-/*
-	FIXME - the following code is causing a NULL pointer dereference in
-	2.3.51 in an interrupt handler.  It's suppose to prompt the board
-	to return the DSS signal status immediately.  Why doesn't it do
-	the same thing in 2.2.14?
-*/
-
-/*	This thing is still busted in the 1.2.12 driver on 2.4.x
-	and even hoses the serial console so the oops can be trapped.
-		/\/\|=mhw=|\/\/			*/
-
-#ifdef	ENABLE_DSSNOW
-		i2QueueCommands(PTYPE_BYPASS, pCh, 100, 1, CMD_DSS_NOW);
-
-		init_waitqueue_entry(&wait, current);
-		add_wait_queue(&pCh->dss_now_wait, &wait);
-		set_current_state( TASK_INTERRUPTIBLE );
-
-		serviceOutgoingFifo( pCh->pMyBord );
-
-		schedule();
-
-		set_current_state( TASK_RUNNING );
-		remove_wait_queue(&pCh->dss_now_wait, &wait);
-
-		if (signal_pending(current)) {
-			return -EINTR;
-		}
-#endif
-		rc = put_user(
-				    ((pCh->dataSetOut & I2_RTS) ? TIOCM_RTS : 0)
-				  | ((pCh->dataSetOut & I2_DTR) ? TIOCM_DTR : 0)
-				  | ((pCh->dataSetIn  & I2_DCD) ? TIOCM_CAR : 0)
-				  | ((pCh->dataSetIn  & I2_RI)  ? TIOCM_RNG : 0)
-				  | ((pCh->dataSetIn  & I2_DSR) ? TIOCM_DSR : 0)
-				  | ((pCh->dataSetIn  & I2_CTS) ? TIOCM_CTS : 0),
-				(unsigned int *) arg);
-		break;
-
-	case TIOCMBIS:
-	case TIOCMBIC:
-	case TIOCMSET:
-		ip2trace (CHANN, ITRC_IOCTL, 9, 0 );
-
-		rc = set_modem_info(pCh, cmd, (unsigned int *) arg);
-		break;
-
 	/*
 	 * Wait for any of the 4 modem inputs (DCD,RI,DSR,CTS) to change - mask
 	 * passed in arg for lines of interest (use |'ed TIOCM_RNG/DSR/CD/CTS
@@ -2239,70 +2267,6 @@ ip2_ioctl ( PTTY tty, struct file *pFile
 }
 
 /******************************************************************************/
-/* Function:   set_modem_info()                                               */
-/* Parameters: Pointer to channel structure                                   */
-/*             Specific ioctl command                                         */
-/*             Pointer to source for new settings                             */
-/* Returns:    Nothing                                                        */
-/*                                                                            */
-/* Description:                                                               */
-/* This returns the current settings of the dataset signal inputs to the user */
-/* program.                                                                   */
-/******************************************************************************/
-static int
-set_modem_info(i2ChanStrPtr pCh, unsigned cmd, unsigned int *value)
-{
-	int rc;
-	unsigned int arg;
-
-	rc = get_user(arg,value);
-	if (rc)
-		return rc;
-	switch(cmd) {
-	case TIOCMBIS:
-		if (arg & TIOCM_RTS) {
-			i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_RTSUP);
-			pCh->dataSetOut |= I2_RTS;
-		}
-		if (arg & TIOCM_DTR) {
-			i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_DTRUP);
-			pCh->dataSetOut |= I2_DTR;
-		}
-		break;
-	case TIOCMBIC:
-		if (arg & TIOCM_RTS) {
-			i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_RTSDN);
-			pCh->dataSetOut &= ~I2_RTS;
-		}
-		if (arg & TIOCM_DTR) {
-			i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_DTRDN);
-			pCh->dataSetOut &= ~I2_DTR;
-		}
-		break;
-	case TIOCMSET:
-		if ( (arg & TIOCM_RTS) && !(pCh->dataSetOut & I2_RTS) ) {
-			i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_RTSUP);
-			pCh->dataSetOut |= I2_RTS;
-		} else if ( !(arg & TIOCM_RTS) && (pCh->dataSetOut & I2_RTS) ) {
-			i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_RTSDN);
-			pCh->dataSetOut &= ~I2_RTS;
-		}
-		if ( (arg & TIOCM_DTR) && !(pCh->dataSetOut & I2_DTR) ) {
-			i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_DTRUP);
-			pCh->dataSetOut |= I2_DTR;
-		} else if ( !(arg & TIOCM_DTR) && (pCh->dataSetOut & I2_DTR) ) {
-			i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_DTRDN);
-			pCh->dataSetOut &= ~I2_DTR;
-		}
-		break;
-	default:
-		return -EINVAL;
-	}
-	serviceOutgoingFifo( pCh->pMyBord );
-	return 0;
-}
-
-/******************************************************************************/
 /* Function:   GetSerialInfo()                                                */
 /* Parameters: Pointer to channel structure                                   */
 /*             Pointer to old termios structure                               */
@@ -2964,7 +2928,7 @@ ip2_ipl_ioctl ( struct inode *pInode, st
 			rc = put_user(ip2_throttle, pIndex++ );
 			rc = put_user(ip2_unthrottle, pIndex++ );
 			rc = put_user(ip2_ioctl, pIndex++ );
-			rc = put_user(set_modem_info, pIndex++ );
+			rc = put_user(0, pIndex++ );
 			rc = put_user(get_serial_info, pIndex++ );
 			rc = put_user(set_serial_info, pIndex++ );
 			rc = put_user(ip2_set_termios, pIndex++ );
--- diff/drivers/char/ipmi/ipmi_kcs_intf.c	2003-08-26 10:00:52.000000000 +0100
+++ source/drivers/char/ipmi/ipmi_kcs_intf.c	2004-02-23 13:56:41.000000000 +0000
@@ -55,6 +55,7 @@
 #include <linux/rcupdate.h>
 #include <linux/ipmi_smi.h>
 #include <asm/io.h>
+#include <asm/irq.h>
 #include "ipmi_kcs_sm.h"
 #include <linux/init.h>
 
--- diff/drivers/char/ipmi/ipmi_kcs_sm.c	2003-05-21 11:50:00.000000000 +0100
+++ source/drivers/char/ipmi/ipmi_kcs_sm.c	2004-02-23 13:56:41.000000000 +0000
@@ -37,8 +37,11 @@
  * that document.
  */
 
+#include <linux/types.h>
+
 #include <asm/io.h>
 #include <asm/string.h>		/* Gets rid of memcpy warning */
+#include <asm/system.h>
 
 #include "ipmi_kcs_sm.h"
 
--- diff/drivers/char/isicom.c	2003-10-09 09:47:34.000000000 +0100
+++ source/drivers/char/isicom.c	2004-02-23 13:56:41.000000000 +0000
@@ -29,7 +29,7 @@
  *	You can find the original tools for this direct from Multitech
  *		ftp://ftp.multitech.com/ISI-Cards/
  *
- *	Having installed the cards the module options (/etc/modules.conf)
+ *	Having installed the cards the module options (/etc/modprobe.conf)
  *
  *	options isicom   io=card1,card2,card3,card4 irq=card1,card2,card3,card4
  *
@@ -1291,63 +1291,44 @@ static inline void isicom_send_break(str
 out:	restore_flags(flags);
 }
 
-static int isicom_get_modem_info(struct isi_port * port, unsigned int * value)
+static int isicom_tiocmget(struct tty_struct *tty, struct file *file)
 {
+	struct isi_port * port = (struct isi_port *) tty->driver_data;
 	/* just send the port status */
-	unsigned int info;
 	unsigned short status = port->status;
+
+	if (isicom_paranoia_check(port, tty->name, "isicom_ioctl"))
+		return -ENODEV;
 	
-	info =  ((status & ISI_RTS) ? TIOCM_RTS : 0) |
+	return  ((status & ISI_RTS) ? TIOCM_RTS : 0) |
 		((status & ISI_DTR) ? TIOCM_DTR : 0) |
 		((status & ISI_DCD) ? TIOCM_CAR : 0) |
 		((status & ISI_DSR) ? TIOCM_DSR : 0) |
 		((status & ISI_CTS) ? TIOCM_CTS : 0) |
 		((status & ISI_RI ) ? TIOCM_RI  : 0);
-	return put_user(info, (unsigned int *) value);
 }
 
-static int isicom_set_modem_info(struct isi_port * port, unsigned int cmd,
-					unsigned int * value)
+static int isicom_tiocmset(struct tty_struct *tty, struct file *file,
+			   unsigned int set, unsigned int clear)
 {
+	struct isi_port * port = (struct isi_port *) tty->driver_data;
 	unsigned int arg;
 	unsigned long flags;
 	
-	if(get_user(arg, value))
-		return -EFAULT;
+	if (isicom_paranoia_check(port, tty->name, "isicom_ioctl"))
+		return -ENODEV;
 	
 	save_flags(flags); cli();
-	
-	switch(cmd) {
-		case TIOCMBIS:
-			if (arg & TIOCM_RTS) 
-				raise_rts(port);
-			if (arg & TIOCM_DTR) 
-				raise_dtr(port);
-			break;
-		
-		case TIOCMBIC:
-			if (arg & TIOCM_RTS)
-				drop_rts(port);
-			if (arg & TIOCM_DTR)
-				drop_dtr(port);	
-			break;
-			
-		case TIOCMSET:
-			if (arg & TIOCM_RTS)
-				raise_rts(port);
-			else
-				drop_rts(port);
-			
-			if (arg & TIOCM_DTR)
-				raise_dtr(port);
-			else
-				drop_dtr(port);
-			break;
-		
-		default:
-			restore_flags(flags);
-			return -EINVAL;		 	
-	}
+	if (set & TIOCM_RTS)
+		raise_rts(port);
+	if (set & TIOCM_DTR)
+		raise_dtr(port);
+
+	if (clear & TIOCM_RTS)
+		drop_rts(port);
+	if (clear & TIOCM_DTR)
+		drop_dtr(port);
+
 	restore_flags(flags);
 	return 0;
 }			
@@ -1445,15 +1426,6 @@ static int isicom_ioctl(struct tty_struc
 				(arg ? CLOCAL : 0));
 			return 0;	
 			
-		case TIOCMGET:
-			return isicom_get_modem_info(port, (unsigned int*) arg);
-			
-		case TIOCMBIS:
-		case TIOCMBIC:
-		case TIOCMSET: 	
-			return isicom_set_modem_info(port, cmd, 
-					(unsigned int *) arg);
-		
 		case TIOCGSERIAL:
 			return isicom_get_serial_info(port, 
 					(struct serial_struct *) arg);
@@ -1640,6 +1612,8 @@ static struct tty_operations isicom_ops 
 	.start	= isicom_start,
 	.hangup	= isicom_hangup,
 	.flush_buffer	= isicom_flush_buffer,
+	.tiocmget	= isicom_tiocmget,
+	.tiocmset	= isicom_tiocmset,
 };
 
 static int register_drivers(void)
--- diff/drivers/char/istallion.c	2004-02-18 08:54:09.000000000 +0000
+++ source/drivers/char/istallion.c	2004-02-23 13:56:41.000000000 +0000
@@ -1991,6 +1991,61 @@ static int stli_setserial(stliport_t *po
 
 /*****************************************************************************/
 
+static int stli_tiocmget(struct tty_struct *tty, struct file *file)
+{
+	stliport_t *portp = tty->driver_data;
+	stlibrd_t *brdp;
+	int rc;
+
+	if (portp == (stliport_t *) NULL)
+		return(-ENODEV);
+	if ((portp->brdnr < 0) || (portp->brdnr >= stli_nrbrds))
+		return(0);
+	brdp = stli_brds[portp->brdnr];
+	if (brdp == (stlibrd_t *) NULL)
+		return(0);
+	if (tty->flags & (1 << TTY_IO_ERROR))
+		return(-EIO);
+
+	if ((rc = stli_cmdwait(brdp, portp, A_GETSIGNALS,
+			       &portp->asig, sizeof(asysigs_t), 1)) < 0)
+		return(rc);
+
+	return stli_mktiocm(portp->asig.sigvalue);
+}
+
+static int stli_tiocmset(struct tty_struct *tty, struct file *file,
+			 unsigned int set, unsigned int clear)
+{
+	stliport_t *portp = tty->driver_data;
+	stlibrd_t *brdp;
+	int rts = -1, dtr = -1;
+
+	if (portp == (stliport_t *) NULL)
+		return(-ENODEV);
+	if ((portp->brdnr < 0) || (portp->brdnr >= stli_nrbrds))
+		return(0);
+	brdp = stli_brds[portp->brdnr];
+	if (brdp == (stlibrd_t *) NULL)
+		return(0);
+	if (tty->flags & (1 << TTY_IO_ERROR))
+		return(-EIO);
+
+	if (set & TIOCM_RTS)
+		rts = 1;
+	if (set & TIOCM_DTR)
+		dtr = 1;
+	if (clear & TIOCM_RTS)
+		rts = 0;
+	if (clear & TIOCM_DTR)
+		dtr = 0;
+
+	stli_mkasysigs(&portp->asig, dtr, rts);
+
+	return stli_cmdwait(brdp, portp, A_SETSIGNALS, &portp->asig,
+			    sizeof(asysigs_t), 0);
+}
+
 static int stli_ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd, unsigned long arg)
 {
 	stliport_t	*portp;
@@ -2034,43 +2089,6 @@ static int stli_ioctl(struct tty_struct 
 				(tty->termios->c_cflag & ~CLOCAL) |
 				(ival ? CLOCAL : 0);
 		break;
-	case TIOCMGET:
-		if ((rc = verify_area(VERIFY_WRITE, (void *) arg,
-		    sizeof(unsigned int))) == 0) {
-			if ((rc = stli_cmdwait(brdp, portp, A_GETSIGNALS,
-			    &portp->asig, sizeof(asysigs_t), 1)) < 0)
-				return(rc);
-			lval = stli_mktiocm(portp->asig.sigvalue);
-			put_user(lval, (unsigned int *) arg);
-		}
-		break;
-	case TIOCMBIS:
-		if ((rc = get_user(ival, (unsigned int *) arg)) == 0) {
-			stli_mkasysigs(&portp->asig,
-				((ival & TIOCM_DTR) ? 1 : -1),
-				((ival & TIOCM_RTS) ? 1 : -1));
-			rc = stli_cmdwait(brdp, portp, A_SETSIGNALS,
-				&portp->asig, sizeof(asysigs_t), 0);
-		}
-		break;
-	case TIOCMBIC:
-		if ((rc = get_user(ival, (unsigned int *) arg)) == 0) {
-			stli_mkasysigs(&portp->asig,
-				((ival & TIOCM_DTR) ? 0 : -1),
-				((ival & TIOCM_RTS) ? 0 : -1));
-			rc = stli_cmdwait(brdp, portp, A_SETSIGNALS,
-				&portp->asig, sizeof(asysigs_t), 0);
-		}
-		break;
-	case TIOCMSET:
-		if ((rc = get_user(ival, (unsigned int *) arg)) == 0) {
-			stli_mkasysigs(&portp->asig,
-				((ival & TIOCM_DTR) ? 1 : 0),
-				((ival & TIOCM_RTS) ? 1 : 0));
-			rc = stli_cmdwait(brdp, portp, A_SETSIGNALS,
-				&portp->asig, sizeof(asysigs_t), 0);
-		}
-		break;
 	case TIOCGSERIAL:
 		if ((rc = verify_area(VERIFY_WRITE, (void *) arg,
 		    sizeof(struct serial_struct))) == 0)
@@ -5255,6 +5273,8 @@ static struct tty_operations stli_ops = 
 	.wait_until_sent = stli_waituntilsent,
 	.send_xchar = stli_sendxchar,
 	.read_proc = stli_readproc,
+	.tiocmget = stli_tiocmget,
+	.tiocmset = stli_tiocmset,
 };
 
 /*****************************************************************************/
--- diff/drivers/char/keyboard.c	2004-02-18 08:54:09.000000000 +0000
+++ source/drivers/char/keyboard.c	2004-02-23 13:56:41.000000000 +0000
@@ -1066,6 +1066,9 @@ void kbd_keycode(unsigned int keycode, i
 	}
 	if (sysrq_down && down && !rep) {
 		handle_sysrq(kbd_sysrq_xlate[keycode], regs, tty);
+#ifdef CONFIG_KGDB_SYSRQ
+                sysrq_down = 0;        /* in case we miss the "up" event */
+#endif
 		return;
 	}
 #endif
--- diff/drivers/char/lp.c	2004-02-09 10:36:10.000000000 +0000
+++ source/drivers/char/lp.c	2004-02-23 13:56:41.000000000 +0000
@@ -862,10 +862,9 @@ static void lp_detach (struct parport *p
 }
 
 static struct parport_driver lp_driver = {
-	"lp",
-	lp_attach,
-	lp_detach,
-	NULL
+	.name = "lp",
+	.attach = lp_attach,
+	.detach = lp_detach,
 };
 
 int __init lp_init (void)
--- diff/drivers/char/mem.c	2004-02-09 10:36:10.000000000 +0000
+++ source/drivers/char/mem.c	2004-02-23 13:56:41.000000000 +0000
@@ -11,8 +11,6 @@
 #include <linux/config.h>
 #include <linux/mm.h>
 #include <linux/miscdevice.h>
-#include <linux/tpqic02.h>
-#include <linux/ftape.h>
 #include <linux/slab.h>
 #include <linux/vmalloc.h>
 #include <linux/mman.h>
@@ -41,6 +39,7 @@ extern void fbmem_init(void);
 extern void tapechar_init(void);
 #endif
 
+#ifdef pgprot_noncached
 /*
  * Architectures vary in how they handle caching for addresses
  * outside of main memory.
@@ -66,19 +65,21 @@ static inline int uncached_access(struct
 	  && addr >= __pa(high_memory);
 #elif defined(CONFIG_IA64)
 	/*
-	 * On ia64, we ignore O_SYNC because we cannot tolerate memory attribute aliases.
+	 * On ia64, we ignore O_SYNC because we cannot tolerate memory
+	 * attribute aliases.
 	 */
 	return !(efi_mem_attributes(addr) & EFI_MEMORY_WB);
 #else
 	/*
-	 * Accessing memory above the top the kernel knows about or through a file pointer
-	 * that was marked O_SYNC will be done non-cached.
+	 * Accessing memory above the top the kernel knows about or through a
+	 * file pointer that was marked O_SYNC will be done non-cached.
 	 */
 	if (file->f_flags & O_SYNC)
 		return 1;
 	return addr >= __pa(high_memory);
 #endif
 }
+#endif		/* pgprot_noncached */
 
 #ifndef ARCH_HAS_VALID_PHYS_ADDR_RANGE
 static inline int valid_phys_addr_range(unsigned long addr, size_t *count)
@@ -168,28 +169,24 @@ static ssize_t write_mem(struct file * f
 	return do_write_mem(file, __va(p), p, buf, count, ppos);
 }
 
-static int mmap_mem(struct file * file, struct vm_area_struct * vma)
+static int mmap_mem(struct file *file, struct vm_area_struct *vma)
 {
 	unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;
-	int uncached;
 
-	uncached = uncached_access(file, offset);
 #ifdef pgprot_noncached
-	if (uncached)
+	if (uncached_access(file, offset))
 		vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
 #endif
 
-	/* Don't try to swap out physical pages.. */
-	vma->vm_flags |= VM_RESERVED;
-
 	/*
-	 * Don't dump addresses that are not real memory to a core file.
+	 * Don't try to swap out physical pages..
+	 * And treat /dev/mem mappings as "IO" regions: they may not
+	 * describe valid pageframes.
 	 */
-	if (uncached)
-		vma->vm_flags |= VM_IO;
+	vma->vm_flags |= VM_RESERVED|VM_IO;
 
-	if (remap_page_range(vma, vma->vm_start, offset, vma->vm_end-vma->vm_start,
-			     vma->vm_page_prot))
+	if (remap_page_range(vma, vma->vm_start, offset,
+			vma->vm_end-vma->vm_start, vma->vm_page_prot))
 		return -EAGAIN;
 	return 0;
 }
--- diff/drivers/char/misc.c	2004-02-09 10:36:10.000000000 +0000
+++ source/drivers/char/misc.c	2004-02-23 13:56:41.000000000 +0000
@@ -212,6 +212,9 @@ static struct file_operations misc_fops 
 int misc_register(struct miscdevice * misc)
 {
 	struct miscdevice *c;
+	struct class_device *class;
+	dev_t dev;
+	int err;
 	
 	down(&misc_sem);
 	list_for_each_entry(c, &misc_list, list) {
@@ -240,19 +243,30 @@ int misc_register(struct miscdevice * mi
 		snprintf(misc->devfs_name, sizeof(misc->devfs_name),
 				"misc/%s", misc->name);
 	}
+	dev = MKDEV(MISC_MAJOR, misc->minor);
 
-	class_simple_device_add(misc_class, MKDEV(MISC_MAJOR, misc->minor),
-				misc->dev, misc->name);
-	devfs_mk_cdev(MKDEV(MISC_MAJOR, misc->minor),
-			S_IFCHR|S_IRUSR|S_IWUSR|S_IRGRP, misc->devfs_name);
+	class = class_simple_device_add(misc_class, dev,
+					misc->dev, misc->name);
+	if (IS_ERR(class)) {
+		err = PTR_ERR(class);
+		goto out;
+	}
+
+	err = devfs_mk_cdev(dev, S_IFCHR|S_IRUSR|S_IWUSR|S_IRGRP, 
+			    misc->devfs_name);
+	if (err) {
+		class_simple_device_remove(dev);
+		goto out;
+	}
 
 	/*
 	 * Add it to the front, so that later devices can "override"
 	 * earlier defaults
 	 */
 	list_add(&misc->list, &misc_list);
+ out:
 	up(&misc_sem);
-	return 0;
+	return err;
 }
 
 /**
--- diff/drivers/char/moxa.c	2004-02-18 08:54:09.000000000 +0000
+++ source/drivers/char/moxa.c	2004-02-23 13:56:41.000000000 +0000
@@ -232,6 +232,9 @@ static void moxa_set_termios(struct tty_
 static void moxa_stop(struct tty_struct *);
 static void moxa_start(struct tty_struct *);
 static void moxa_hangup(struct tty_struct *);
+static int moxa_tiocmget(struct tty_struct *tty, struct file *file);
+static int moxa_tiocmset(struct tty_struct *tty, struct file *file,
+			 unsigned int set, unsigned int clear);
 static void moxa_poll(unsigned long);
 static void set_tty_param(struct tty_struct *);
 static int block_till_ready(struct tty_struct *, struct file *,
@@ -289,6 +292,8 @@ static struct tty_operations moxa_ops = 
 	.stop = moxa_stop,
 	.start = moxa_start,
 	.hangup = moxa_hangup,
+	.tiocmget = moxa_tiocmget,
+	.tiocmset = moxa_tiocmset,
 };
 
 static int __init moxa_init(void)
@@ -742,6 +747,55 @@ static void moxa_put_char(struct tty_str
 	ch->statusflags |= LOWWAIT;
 }
 
+static int moxa_tiocmget(struct tty_struct *tty, struct file *file)
+{
+	struct moxa_str *ch = (struct moxa_str *) tty->driver_data;
+	int port;
+	int flag = 0, dtr, rts;
+
+	port = PORTNO(tty);
+	if ((port != MAX_PORTS) && (!ch))
+		return (-EINVAL);
+
+	MoxaPortGetLineOut(ch->port, &dtr, &rts);
+	if (dtr)
+		flag |= TIOCM_DTR;
+	if (rts)
+		flag |= TIOCM_RTS;
+	dtr = MoxaPortLineStatus(ch->port);
+	if (dtr & 1)
+		flag |= TIOCM_CTS;
+	if (dtr & 2)
+		flag |= TIOCM_DSR;
+	if (dtr & 4)
+		flag |= TIOCM_CD;
+	return flag;
+}
+
+static int moxa_tiocmset(struct tty_struct *tty, struct file *file,
+			 unsigned int set, unsigned int clear)
+{
+	struct moxa_str *ch = (struct moxa_str *) tty->driver_data;
+	int port;
+	int flag = 0, dtr, rts;
+
+	port = PORTNO(tty);
+	if ((port != MAX_PORTS) && (!ch))
+		return (-EINVAL);
+
+	MoxaPortGetLineOut(ch->port, &dtr, &rts);
+	if (set & TIOCM_RTS)
+		rts = 1;
+	if (set & TIOCM_DTR)
+		dtr = 1;
+	if (clear & TIOCM_RTS)
+		rts = 0;
+	if (clear & TIOCM_DTR)
+		dtr = 0;
+	MoxaPortLineCtrl(ch->port, dtr, rts);
+	return 0;
+}
+
 static int moxa_ioctl(struct tty_struct *tty, struct file *file,
 		      unsigned int cmd, unsigned long arg)
 {
@@ -785,51 +839,6 @@ static int moxa_ioctl(struct tty_struct 
 		else
 			ch->asyncflags |= ASYNC_CHECK_CD;
 		return (0);
-	case TIOCMGET:
-		flag = 0;
-		MoxaPortGetLineOut(ch->port, &dtr, &rts);
-		if (dtr)
-			flag |= TIOCM_DTR;
-		if (rts)
-			flag |= TIOCM_RTS;
-		dtr = MoxaPortLineStatus(ch->port);
-		if (dtr & 1)
-			flag |= TIOCM_CTS;
-		if (dtr & 2)
-			flag |= TIOCM_DSR;
-		if (dtr & 4)
-			flag |= TIOCM_CD;
-		return put_user(flag, (unsigned int *) arg);
-	case TIOCMBIS:
-		if(get_user(retval, (unsigned int *) arg))
-			return -EFAULT;
-		MoxaPortGetLineOut(ch->port, &dtr, &rts);
-		if (retval & TIOCM_RTS)
-			rts = 1;
-		if (retval & TIOCM_DTR)
-			dtr = 1;
-		MoxaPortLineCtrl(ch->port, dtr, rts);
-		return (0);
-	case TIOCMBIC:
-		if(get_user(retval, (unsigned int *) arg))
-			return -EFAULT;
-		MoxaPortGetLineOut(ch->port, &dtr, &rts);
-		if (retval & TIOCM_RTS)
-			rts = 0;
-		if (retval & TIOCM_DTR)
-			dtr = 0;
-		MoxaPortLineCtrl(ch->port, dtr, rts);
-		return (0);
-	case TIOCMSET:
-		if(get_user(retval, (unsigned long *) arg))
-			return -EFAULT;
-		dtr = rts = 0;
-		if (retval & TIOCM_RTS)
-			rts = 1;
-		if (retval & TIOCM_DTR)
-			dtr = 1;
-		MoxaPortLineCtrl(ch->port, dtr, rts);
-		return (0);
 	case TIOCGSERIAL:
 		return (moxa_get_serial_info(ch, (struct serial_struct *) arg));
 
--- diff/drivers/char/mxser.c	2004-02-18 08:54:09.000000000 +0000
+++ source/drivers/char/mxser.c	2004-02-23 13:56:41.000000000 +0000
@@ -350,8 +350,8 @@ static int mxser_get_serial_info(struct 
 static int mxser_set_serial_info(struct mxser_struct *, struct serial_struct *);
 static int mxser_get_lsr_info(struct mxser_struct *, unsigned int *);
 static void mxser_send_break(struct mxser_struct *, int);
-static int mxser_get_modem_info(struct mxser_struct *, unsigned int *);
-static int mxser_set_modem_info(struct mxser_struct *, unsigned int, unsigned int *);
+static int mxser_tiocmget(struct tty_struct *, struct file *);
+static int mxser_tiocmset(struct tty_struct *, struct file *, unsigned int, unsigned int);
 
 /*
  * The MOXA C168/C104 serial driver boot-time initialization code!
@@ -492,6 +492,8 @@ static struct tty_operations mxser_ops =
 	.stop = mxser_stop,
 	.start = mxser_start,
 	.hangup = mxser_hangup,
+	.tiocmget = mxser_tiocmget,
+	.tiocmset = mxser_tiocmset,
 };
 
 static int __init mxser_module_init(void)
@@ -1009,12 +1011,6 @@ static int mxser_ioctl(struct tty_struct
 		tty->termios->c_cflag = ((tty->termios->c_cflag & ~CLOCAL) |
 					 (arg ? CLOCAL : 0));
 		return (0);
-	case TIOCMGET:
-		return (mxser_get_modem_info(info, (unsigned int *) arg));
-	case TIOCMBIS:
-	case TIOCMBIC:
-	case TIOCMSET:
-		return (mxser_set_modem_info(info, cmd, (unsigned int *) arg));
 	case TIOCGSERIAL:
 		return (mxser_get_serial_info(info, (struct serial_struct *) arg));
 	case TIOCSSERIAL:
@@ -2150,13 +2146,18 @@ static void mxser_send_break(struct mxse
 	restore_flags(flags);
 }
 
-static int mxser_get_modem_info(struct mxser_struct *info,
-				unsigned int *value)
+static int mxser_tiocmget(struct tty_struct *tty, struct file *file)
 {
+	struct mxser_struct *info = (struct mxser_struct *) tty->driver_data;
 	unsigned char control, status;
 	unsigned int result;
 	unsigned long flags;
 
+	if (PORTNO(tty) == MXSER_PORTS)
+		return (-ENOIOCTLCMD);
+	if (tty->flags & (1 << TTY_IO_ERROR))
+		return (-EIO);
+
 	control = info->MCR;
 	save_flags(flags);
 	cli();
@@ -2164,46 +2165,38 @@ static int mxser_get_modem_info(struct m
 	if (status & UART_MSR_ANY_DELTA)
 		mxser_check_modem_status(info, status);
 	restore_flags(flags);
-	result = ((control & UART_MCR_RTS) ? TIOCM_RTS : 0) |
+	return ((control & UART_MCR_RTS) ? TIOCM_RTS : 0) |
 	    ((control & UART_MCR_DTR) ? TIOCM_DTR : 0) |
 	    ((status & UART_MSR_DCD) ? TIOCM_CAR : 0) |
 	    ((status & UART_MSR_RI) ? TIOCM_RNG : 0) |
 	    ((status & UART_MSR_DSR) ? TIOCM_DSR : 0) |
 	    ((status & UART_MSR_CTS) ? TIOCM_CTS : 0);
-	return put_user(result, value);
 }
 
-static int mxser_set_modem_info(struct mxser_struct *info, unsigned int cmd,
-				unsigned int *value)
+static int mxser_tiocmset(struct tty_struct *tty, struct file *file,
+			  unsigned int set, unsigned int clear)
 {
+	struct mxser_struct *info = (struct mxser_struct *) tty->driver_data;
 	unsigned int arg;
 	unsigned long flags;
 
-	if(get_user(arg, value))
-		return -EFAULT;
-	switch (cmd) {
-	case TIOCMBIS:
-		if (arg & TIOCM_RTS)
-			info->MCR |= UART_MCR_RTS;
-		if (arg & TIOCM_DTR)
-			info->MCR |= UART_MCR_DTR;
-		break;
-	case TIOCMBIC:
-		if (arg & TIOCM_RTS)
-			info->MCR &= ~UART_MCR_RTS;
-		if (arg & TIOCM_DTR)
-			info->MCR &= ~UART_MCR_DTR;
-		break;
-	case TIOCMSET:
-		info->MCR = ((info->MCR & ~(UART_MCR_RTS | UART_MCR_DTR)) |
-			     ((arg & TIOCM_RTS) ? UART_MCR_RTS : 0) |
-			     ((arg & TIOCM_DTR) ? UART_MCR_DTR : 0));
-		break;
-	default:
-		return (-EINVAL);
-	}
+	if (PORTNO(tty) == MXSER_PORTS)
+		return (-ENOIOCTLCMD);
+	if (tty->flags & (1 << TTY_IO_ERROR))
+		return (-EIO);
+
 	save_flags(flags);
 	cli();
+	if (set & TIOCM_RTS)
+		info->MCR |= UART_MCR_RTS;
+	if (set & TIOCM_DTR)
+		info->MCR |= UART_MCR_DTR;
+
+	if (clear & TIOCM_RTS)
+		info->MCR &= ~UART_MCR_RTS;
+	if (clear & TIOCM_DTR)
+		info->MCR &= ~UART_MCR_DTR;
+
 	outb(info->MCR, info->base + UART_MCR);
 	restore_flags(flags);
 	return (0);
--- diff/drivers/char/pcxx.c	2003-10-09 09:47:34.000000000 +0100
+++ source/drivers/char/pcxx.c	2004-02-23 13:56:41.000000000 +0000
@@ -173,6 +173,9 @@ static inline void txwinon(struct channe
 static inline void memoff(struct channel *ch);
 static inline void assertgwinon(struct channel *ch);
 static inline void assertmemoff(struct channel *ch);
+static int pcxe_tiocmget(struct tty_struct *tty, struct file *file);
+static int pcxe_tiocmset(struct tty_struct *tty, struct file *file,
+			 unsigned int set, unsigned int clear);
 
 #define TZ_BUFSZ 4096
 
@@ -1029,6 +1032,8 @@ static struct tty_operations pcxe_ops = 
 	.stop = pcxe_stop,
 	.start = pcxe_start,
 	.hangup = pcxe_hangup,
+	.tiocmget = pcxe_tiocmget,
+	.tiocmset = pcxe_tiocmset,
 };
 
 /*
@@ -1983,6 +1988,89 @@ static void receive_data(struct channel 
 }
 
 
+static int pcxe_tiocmget(struct tty_struct *tty, struct file *file)
+{
+	struct channel *ch = (struct channel *) tty->driver_data;
+	volatile struct board_chan *bc;
+	unsigned long flags;
+	int mflag = 0;
+
+	if(ch)
+		bc = ch->brdchan;
+	else {
+		printk("ch is NULL in %s!\n", __FUNCTION__);
+		return(-EINVAL);
+	}
+
+	save_flags(flags);
+	cli();
+	globalwinon(ch);
+	mstat = bc->mstat;
+	memoff(ch);
+	restore_flags(flags);
+
+	if(mstat & DTR)
+		mflag |= TIOCM_DTR;
+	if(mstat & RTS)
+		mflag |= TIOCM_RTS;
+	if(mstat & CTS)
+		mflag |= TIOCM_CTS;
+	if(mstat & ch->dsr)
+		mflag |= TIOCM_DSR;
+	if(mstat & RI)
+		mflag |= TIOCM_RI;
+	if(mstat & ch->dcd)
+		mflag |= TIOCM_CD;
+
+	return mflag;
+}
+
+
+static int pcxe_tiocmset(struct tty_struct *tty, struct file *file,
+			 unsigned int set, unsigned int clear)
+{
+	struct channel *ch = (struct channel *) tty->driver_data;
+	volatile struct board_chan *bc;
+	unsigned long flags;
+
+	if(ch)
+		bc = ch->brdchan;
+	else {
+		printk("ch is NULL in %s!\n", __FUNCTION__);
+		return(-EINVAL);
+	}
+
+	save_flags(flags);
+	cli();
+	/*
+	 * I think this modemfake stuff is broken.  It doesn't
+	 * correctly reflect the behaviour desired by the TIOCM*
+	 * ioctls.  Therefore this is probably broken.
+	 */
+	if (set & TIOCM_DTR) {
+		ch->modemfake |= DTR;
+		ch->modem |= DTR;
+	}
+	if (set & TIOCM_RTS) {
+		ch->modemfake |= RTS;
+		ch->modem |= RTS;
+	}
+
+	if (clear & TIOCM_DTR) {
+		ch->modemfake |= DTR;
+		ch->modem &= ~DTR;
+	}
+	if (clear & TIOCM_RTS) {
+		ch->modemfake |= RTS;
+		ch->modem &= ~RTS;
+	}
+	globalwinon(ch);
+	pcxxparam(tty,ch);
+	memoff(ch);
+	restore_flags(flags);
+}
+
+
 static int pcxe_ioctl(struct tty_struct *tty, struct file * file,
 		    unsigned int cmd, unsigned long arg)
 {
@@ -2036,69 +2124,15 @@ static int pcxe_ioctl(struct tty_struct 
 			return 0;
 
 		case TIOCMODG:
-		case TIOCMGET:
-			mflag = 0;
-
-			cli();
-			globalwinon(ch);
-			mstat = bc->mstat;
-			memoff(ch);
-			restore_flags(flags);
-
-			if(mstat & DTR)
-				mflag |= TIOCM_DTR;
-			if(mstat & RTS)
-				mflag |= TIOCM_RTS;
-			if(mstat & CTS)
-				mflag |= TIOCM_CTS;
-			if(mstat & ch->dsr)
-				mflag |= TIOCM_DSR;
-			if(mstat & RI)
-				mflag |= TIOCM_RI;
-			if(mstat & ch->dcd)
-				mflag |= TIOCM_CD;
-
+			mflag = pcxe_tiocmget(tty, file);
 			if (put_user(mflag, (unsigned int *) arg))
 				return -EFAULT;
 			break;
 
-		case TIOCMBIS:
-		case TIOCMBIC:
 		case TIOCMODS:
-		case TIOCMSET:
 			if (get_user(mstat, (unsigned int *) arg))
 				return -EFAULT;
-
-			mflag = 0;
-			if(mstat & TIOCM_DTR)
-				mflag |= DTR;
-			if(mstat & TIOCM_RTS)
-				mflag |= RTS;
-
-			switch(cmd) {
-				case TIOCMODS:
-				case TIOCMSET:
-					ch->modemfake = DTR|RTS;
-					ch->modem = mflag;
-					break;
-
-				case TIOCMBIS:
-					ch->modemfake |= mflag;
-					ch->modem |= mflag;
-					break;
-
-				case TIOCMBIC:
-					ch->modemfake &= ~mflag;
-					ch->modem &= ~mflag;
-					break;
-			}
-
-			cli();
-			globalwinon(ch);
-			pcxxparam(tty,ch);
-			memoff(ch);
-			restore_flags(flags);
-			break;
+			return pcxe_tiocmset(tty, file, mstat, ~mstat);
 
 		case TIOCSDTR:
 			cli();
--- diff/drivers/char/pty.c	2003-09-30 15:46:13.000000000 +0100
+++ source/drivers/char/pty.c	2004-02-23 13:56:41.000000000 +0000
@@ -25,16 +25,21 @@
 #include <linux/mm.h>
 #include <linux/init.h>
 #include <linux/devfs_fs_kernel.h>
+#include <linux/sysctl.h>
 
 #include <asm/uaccess.h>
 #include <asm/system.h>
 #include <asm/bitops.h>
 #include <linux/devpts_fs.h>
 
+#if defined(CONFIG_LEGACY_PTYS) || defined(CONFIG_UNIX98_PTYS)
+
+#ifdef CONFIG_LEGACY_PTYS
 static struct tty_driver *pty_driver, *pty_slave_driver;
+#endif
 
-#ifdef CONFIG_UNIX98_PTYS
 /* These are global because they are accessed in tty_io.c */
+#ifdef CONFIG_UNIX98_PTYS
 struct tty_driver *ptm_driver;
 struct tty_driver *pts_driver;
 #endif
@@ -226,8 +231,9 @@ static int pty_set_lock(struct tty_struc
 	return 0;
 }
 
+#ifdef CONFIG_LEGACY_PTYS
 static int pty_bsd_ioctl(struct tty_struct *tty, struct file *file,
-			unsigned int cmd, unsigned long arg)
+			 unsigned int cmd, unsigned long arg)
 {
 	if (!tty) {
 		printk("pty_ioctl called with NULL tty!\n");
@@ -239,6 +245,7 @@ static int pty_bsd_ioctl(struct tty_stru
 	}
 	return -ENOIOCTLCMD;
 }
+#endif
 
 #ifdef CONFIG_UNIX98_PTYS
 static int pty_unix98_ioctl(struct tty_struct *tty, struct file *file,
@@ -249,11 +256,13 @@ static int pty_unix98_ioctl(struct tty_s
 		return -EIO;
 	}
 	switch(cmd) {
+	case TIOCSPTLCK: /* Set PT Lock (disallow slave open) */
+		return pty_set_lock(tty, (int *)arg);
 	case TIOCGPTN: /* Get PT Number */
 		return pty_get_device_number(tty, (unsigned int *)arg);
 	}
 
-	return pty_bsd_ioctl(tty,file,cmd,arg);
+	return -ENOIOCTLCMD;
 }
 #endif
 
@@ -313,8 +322,41 @@ static struct tty_operations pty_ops = {
 	.set_termios = pty_set_termios,
 };
 
+/* sysctl support for setting limits on the number of Unix98 ptys allocated.
+   Otherwise one can eat up all kernel memory by opening /dev/ptmx repeatedly. */
+#ifdef CONFIG_UNIX98_PTYS
+int pty_limit = NR_UNIX98_PTY_DEFAULT;
+static int pty_limit_min = 0;
+static int pty_limit_max = NR_UNIX98_PTY_MAX;
+
+ctl_table pty_table[] = {
+	{
+		.ctl_name	= PTY_MAX,
+		.procname	= "max",
+		.maxlen		= sizeof(int),
+		.mode		= 0644,
+		.data		= &pty_limit,
+		.proc_handler	= &proc_dointvec_minmax,
+		.strategy	= &sysctl_intvec,
+		.extra1		= &pty_limit_min,
+		.extra2		= &pty_limit_max,
+	}, {
+		.ctl_name	= PTY_NR,
+		.procname	= "nr",
+		.maxlen		= sizeof(int),
+		.mode		= 0444,
+		.proc_handler	= &proc_dointvec,
+	}, {
+		.ctl_name	= 0
+	}
+};
+#endif
+
+/* Initialization */
+
 static int __init pty_init(void)
 {
+#ifdef CONFIG_LEGACY_PTYS
 	/* Traditional BSD devices */
 
 	pty_driver = alloc_tty_driver(NR_PTYS);
@@ -363,15 +405,15 @@ static int __init pty_init(void)
 	if (tty_register_driver(pty_slave_driver))
 		panic("Couldn't register pty slave driver");
 
+#endif /* CONFIG_LEGACY_PTYS */
 
-	/* Unix98 devices */
 #ifdef CONFIG_UNIX98_PTYS
+	/* Unix98 devices */
 	devfs_mk_dir("pts");
-	printk("pty: %d Unix98 ptys configured\n", UNIX98_NR_MAJORS*NR_PTYS);
-	ptm_driver = alloc_tty_driver(UNIX98_NR_MAJORS * NR_PTYS);
+	ptm_driver = alloc_tty_driver(NR_UNIX98_PTY_MAX);
 	if (!ptm_driver)
 		panic("Couldn't allocate Unix98 ptm driver");
-	pts_driver = alloc_tty_driver(UNIX98_NR_MAJORS * NR_PTYS);
+	pts_driver = alloc_tty_driver(NR_UNIX98_PTY_MAX);
 	if (!pts_driver)
 		panic("Couldn't allocate Unix98 pts driver");
 
@@ -388,7 +430,7 @@ static int __init pty_init(void)
 	ptm_driver->init_termios.c_cflag = B38400 | CS8 | CREAD;
 	ptm_driver->init_termios.c_lflag = 0;
 	ptm_driver->flags = TTY_DRIVER_RESET_TERMIOS | TTY_DRIVER_REAL_RAW |
-				TTY_DRIVER_NO_DEVFS;
+		TTY_DRIVER_NO_DEVFS | TTY_DRIVER_DEVPTS_MEM;
 	ptm_driver->other = pts_driver;
 	tty_set_operations(ptm_driver, &pty_ops);
 	ptm_driver->ioctl = pty_unix98_ioctl;
@@ -402,8 +444,8 @@ static int __init pty_init(void)
 	pts_driver->subtype = PTY_TYPE_SLAVE;
 	pts_driver->init_termios = tty_std_termios;
 	pts_driver->init_termios.c_cflag = B38400 | CS8 | CREAD;
-	pts_driver->flags = TTY_DRIVER_RESET_TERMIOS |
-			TTY_DRIVER_REAL_RAW | TTY_DRIVER_NO_DEVFS;
+	pts_driver->flags = TTY_DRIVER_RESET_TERMIOS | TTY_DRIVER_REAL_RAW |
+		TTY_DRIVER_NO_DEVFS | TTY_DRIVER_DEVPTS_MEM;
 	pts_driver->other = ptm_driver;
 	tty_set_operations(pts_driver, &pty_ops);
 	
@@ -411,7 +453,12 @@ static int __init pty_init(void)
 		panic("Couldn't register Unix98 ptm driver");
 	if (tty_register_driver(pts_driver))
 		panic("Couldn't register Unix98 pts driver");
-#endif
+
+	pty_table[1].data = &ptm_driver->refcount;
+#endif /* CONFIG_UNIX98_PTYS */
+
 	return 0;
 }
 module_init(pty_init);
+
+#endif /* CONFIG_LEGACY_PTYS || CONFIG_UNIX98_PTYS */
--- diff/drivers/char/raw.c	2004-02-09 10:36:10.000000000 +0000
+++ source/drivers/char/raw.c	2004-02-23 13:56:41.000000000 +0000
@@ -60,7 +60,7 @@ static int raw_open(struct inode *inode,
 	if (!bdev)
 		goto out;
 	igrab(bdev->bd_inode);
-	err = blkdev_get(bdev, filp->f_mode, 0, BDEV_RAW);
+	err = blkdev_get(bdev, filp->f_mode, 0);
 	if (err)
 		goto out;
 	err = bd_claim(bdev, raw_open);
@@ -81,7 +81,7 @@ static int raw_open(struct inode *inode,
 out2:
 	bd_release(bdev);
 out1:
-	blkdev_put(bdev, BDEV_RAW);
+	blkdev_put(bdev);
 out:
 	up(&raw_mutex);
 	return err;
@@ -106,7 +106,7 @@ static int raw_release(struct inode *ino
 	up(&raw_mutex);
 
 	bd_release(bdev);
-	blkdev_put(bdev, BDEV_RAW);
+	blkdev_put(bdev);
 	return 0;
 }
 
--- diff/drivers/char/rio/rio_linux.c	2003-10-09 09:47:34.000000000 +0100
+++ source/drivers/char/rio/rio_linux.c	2004-02-23 13:56:41.000000000 +0000
@@ -728,6 +728,11 @@ static int rio_ioctl (struct tty_struct 
       rc = gs_setserial(&PortP->gs, (struct serial_struct *) arg);
     break;
 #if 0
+  /*
+   * note: these IOCTLs no longer reach here.  Use
+   * tiocmset/tiocmget driver methods instead.  The
+   * #if 0 disablement predates this comment.
+   */
   case TIOCMGET:
     if ((rc = verify_area(VERIFY_WRITE, (void *) arg,
                           sizeof(unsigned int))) == 0) {
--- diff/drivers/char/riscom8.c	2003-09-17 12:28:05.000000000 +0100
+++ source/drivers/char/riscom8.c	2004-02-23 13:56:41.000000000 +0000
@@ -1306,13 +1306,17 @@ static void rc_flush_buffer(struct tty_s
 		(tty->ldisc.write_wakeup)(tty);
 }
 
-static int rc_get_modem_info(struct riscom_port * port, unsigned int *value)
+static int rc_tiocmget(struct tty_struct *tty, struct file *file)
 {
+	struct riscom_port *port = (struct riscom_port *)tty->driver_data;
 	struct riscom_board * bp;
 	unsigned char status;
 	unsigned int result;
 	unsigned long flags;
 
+	if (rc_paranoia_check(port, tty->name, __FUNCTION__))
+		return -ENODEV;
+
 	bp = port_Board(port);
 	save_flags(flags); cli();
 	rc_out(bp, CD180_CAR, port_No(port));
@@ -1324,41 +1328,32 @@ static int rc_get_modem_info(struct risc
 		| ((status & MSVR_CD)  ? TIOCM_CAR : 0)
 		| ((status & MSVR_DSR) ? TIOCM_DSR : 0)
 		| ((status & MSVR_CTS) ? TIOCM_CTS : 0);
-	return put_user(result, value);
+	return result;
 }
 
-static int rc_set_modem_info(struct riscom_port * port, unsigned int cmd,
-			     unsigned int *value)
+static int rc_tiocmset(struct tty_struct *tty, struct file *file,
+		       unsigned int set, unsigned int clear)
 {
-	unsigned int arg;
+	struct riscom_port *port = (struct riscom_port *)tty->driver_data;
 	unsigned long flags;
-	struct riscom_board *bp = port_Board(port);
+	struct riscom_board *bp;
+
+	if (rc_paranoia_check(port, tty->name, __FUNCTION__))
+		return -ENODEV;
+
+	bp = port_Board(port);
 
-	if (get_user(arg, value))
-		return -EFAULT;
-	switch (cmd) {
-	 case TIOCMBIS: 
-		if (arg & TIOCM_RTS) 
-			port->MSVR |= MSVR_RTS;
-		if (arg & TIOCM_DTR)
-			bp->DTR &= ~(1u << port_No(port));
-		break;
-	case TIOCMBIC:
-		if (arg & TIOCM_RTS)
-			port->MSVR &= ~MSVR_RTS;
-		if (arg & TIOCM_DTR)
-			bp->DTR |= (1u << port_No(port));
-		break;
-	case TIOCMSET:
-		port->MSVR = (arg & TIOCM_RTS) ? (port->MSVR | MSVR_RTS) : 
-					         (port->MSVR & ~MSVR_RTS);
-		bp->DTR = arg & TIOCM_DTR ? (bp->DTR &= ~(1u << port_No(port))) :
-					    (bp->DTR |=  (1u << port_No(port)));
-		break;
-	 default:
-		return -EINVAL;
-	}
 	save_flags(flags); cli();
+	if (set & TIOCM_RTS)
+		port->MSVR |= MSVR_RTS;
+	if (set & TIOCM_DTR)
+		bp->DTR &= ~(1u << port_No(port));
+
+	if (clear & TIOCM_RTS)
+		port->MSVR &= ~MSVR_RTS;
+	if (clear & TIOCM_DTR)
+		bp->DTR |= (1u << port_No(port));
+
 	rc_out(bp, CD180_CAR, port_No(port));
 	rc_out(bp, CD180_MSVR, port->MSVR);
 	rc_out(bp, RC_DTR, bp->DTR);
@@ -1485,12 +1480,6 @@ static int rc_ioctl(struct tty_struct * 
 			((tty->termios->c_cflag & ~CLOCAL) |
 			(arg ? CLOCAL : 0));
 		break;
-	 case TIOCMGET:
-		return rc_get_modem_info(port, (unsigned int *) arg);
-	 case TIOCMBIS:
-	 case TIOCMBIC:
-	 case TIOCMSET:
-		return rc_set_modem_info(port, cmd, (unsigned int *) arg);
 	 case TIOCGSERIAL:	
 		return rc_get_serial_info(port, (struct serial_struct *) arg);
 	 case TIOCSSERIAL:	
@@ -1677,6 +1666,8 @@ static struct tty_operations riscom_ops 
 	.stop = rc_stop,
 	.start = rc_start,
 	.hangup = rc_hangup,
+	.tiocmget = rc_tiocmget,
+	.tiocmset = rc_tiocmset,
 };
 
 static inline int rc_init_drivers(void)
--- diff/drivers/char/rocket.c	2003-10-27 09:20:37.000000000 +0000
+++ source/drivers/char/rocket.c	2004-02-23 13:56:41.000000000 +0000
@@ -1216,59 +1216,6 @@ static int sGetChanRI(CHANNEL_T * ChP)
 /********************************************************************************************/
 /*  Here are the routines used by rp_ioctl.  These are all called from exception handlers.  */
 
-static int get_modem_info(struct r_port *info, unsigned int *value)
-{
-	unsigned int control, result, ChanStatus;
-
-	ChanStatus = sGetChanStatusLo(&info->channel);
-
-	control = info->channel.TxControl[3];
-	result = ((control & SET_RTS) ? TIOCM_RTS : 0) | 
-		((control & SET_DTR) ?  TIOCM_DTR : 0) |
-		((ChanStatus & CD_ACT) ? TIOCM_CAR : 0) |
-		(sGetChanRI(&info->channel) ? TIOCM_RNG : 0) |
-		((ChanStatus & DSR_ACT) ? TIOCM_DSR : 0) |
-		((ChanStatus & CTS_ACT) ? TIOCM_CTS : 0);
-
-	if (copy_to_user(value, &result, sizeof (int)))
-		return -EFAULT;
-	return 0;
-}
-
-static int set_modem_info(struct r_port *info, unsigned int cmd,
-			  unsigned int *value)
-{
-	unsigned int arg;
-
-	if (copy_from_user(&arg, value, sizeof (int)))
-		return -EFAULT;
-
-	switch (cmd) {
-	case TIOCMBIS:
-		if (arg & TIOCM_RTS)
-			info->channel.TxControl[3] |= SET_RTS;
-		if (arg & TIOCM_DTR)
-			info->channel.TxControl[3] |= SET_DTR;
-		break;
-	case TIOCMBIC:
-		if (arg & TIOCM_RTS)
-			info->channel.TxControl[3] &= ~SET_RTS;
-		if (arg & TIOCM_DTR)
-			info->channel.TxControl[3] &= ~SET_DTR;
-		break;
-	case TIOCMSET:
-		info->channel.TxControl[3] = ((info->channel.TxControl[3] & ~(SET_RTS | SET_DTR)) | 
-					      ((arg & TIOCM_RTS) ? SET_RTS : 0) | 
-					      ((arg & TIOCM_DTR) ? SET_DTR : 0));
-		break;
-	default:
-		return -EINVAL;
-	}
-
-	sOutDW(info->channel.IndexAddr, *(DWord_t *) & (info->channel.TxControl[0]));
-	return 0;
-}
-
 /*
  *  Returns the state of the serial modem control lines.  These next 2 functions 
  *  are the way kernel versions > 2.5 handle modem control lines rather than IOCTLs.
@@ -1432,12 +1379,6 @@ static int rp_ioctl(struct tty_struct *t
 		return -ENXIO;
 
 	switch (cmd) {
-	case TIOCMGET:
-		return get_modem_info(info, (unsigned int *) arg);
-	case TIOCMBIS:
-	case TIOCMBIC:
-	case TIOCMSET:
-		return set_modem_info(info, cmd, (unsigned int *) arg);
 	case RCKP_GET_STRUCT:
 		if (copy_to_user((void *) arg, info, sizeof (struct r_port)))
 			return -EFAULT;
--- diff/drivers/char/serial167.c	2003-10-09 09:47:34.000000000 +0100
+++ source/drivers/char/serial167.c	2004-02-23 13:56:41.000000000 +0000
@@ -1492,8 +1492,9 @@ check_and_exit:
 } /* set_serial_info */
 
 static int
-get_modem_info(struct cyclades_port * info, unsigned int *value)
+cy_tiocmget(struct tty_struct *tty, struct file *file)
 {
+  struct cyclades_port * info = (struct cyclades_port *)tty->driver_data;
   int channel;
   volatile unsigned char *base_addr = (u_char *)BASE_ADDR;
   unsigned long flags;
@@ -1507,36 +1508,32 @@ get_modem_info(struct cyclades_port * in
         status = base_addr[CyMSVR1] | base_addr[CyMSVR2];
     local_irq_restore(flags);
 
-    result =  ((status  & CyRTS) ? TIOCM_RTS : 0)
+    return    ((status  & CyRTS) ? TIOCM_RTS : 0)
             | ((status  & CyDTR) ? TIOCM_DTR : 0)
             | ((status  & CyDCD) ? TIOCM_CAR : 0)
             | ((status  & CyDSR) ? TIOCM_DSR : 0)
             | ((status  & CyCTS) ? TIOCM_CTS : 0);
-    return put_user(result,(unsigned int *) value);
-} /* get_modem_info */
+} /* cy_tiocmget */
 
 static int
-set_modem_info(struct cyclades_port * info, unsigned int cmd,
-                          unsigned int *value)
+cy_tiocmset(struct tty_struct *tty, struct file *file,
+	    unsigned int set, unsigned int clear)
 {
+  struct cyclades_port * info = (struct cyclades_port *)tty->driver_data;
   int channel;
   volatile unsigned char *base_addr = (u_char *)BASE_ADDR;
   unsigned long flags;
   unsigned int arg;
 	  
-    if (get_user(arg, (unsigned long *) value))
-	return -EFAULT;
     channel = info->line;
 
-    switch (cmd) {
-    case TIOCMBIS:
-	if (arg & TIOCM_RTS){
+	if (set & TIOCM_RTS){
 	    local_irq_save(flags);
 		base_addr[CyCAR] = (u_char)channel;
 		base_addr[CyMSVR1] = CyRTS;
 	    local_irq_restore(flags);
 	}
-	if (arg & TIOCM_DTR){
+	if (set & TIOCM_DTR){
 	    local_irq_save(flags);
 	    base_addr[CyCAR] = (u_char)channel;
 /* CP('S');CP('2'); */
@@ -1547,15 +1544,14 @@ set_modem_info(struct cyclades_port * in
 #endif
 	    local_irq_restore(flags);
 	}
-	break;
-    case TIOCMBIC:
-	if (arg & TIOCM_RTS){
+
+	if (clear & TIOCM_RTS){
 	    local_irq_save(flags);
 		base_addr[CyCAR] = (u_char)channel;
 		base_addr[CyMSVR1] = 0;
 	    local_irq_restore(flags);
 	}
-	if (arg & TIOCM_DTR){
+	if (clear & TIOCM_DTR){
 	    local_irq_save(flags);
 	    base_addr[CyCAR] = (u_char)channel;
 /* CP('C');CP('2'); */
@@ -1566,44 +1562,7 @@ set_modem_info(struct cyclades_port * in
 #endif
 	    local_irq_restore(flags);
 	}
-	break;
-    case TIOCMSET:
-	if (arg & TIOCM_RTS){
-	    local_irq_save(flags);
-		base_addr[CyCAR] = (u_char)channel;
-		base_addr[CyMSVR1] = CyRTS;
-	    local_irq_restore(flags);
-	}else{
-	    local_irq_save(flags);
-		base_addr[CyCAR] = (u_char)channel;
-		base_addr[CyMSVR1] = 0;
-	    local_irq_restore(flags);
-	}
-	if (arg & TIOCM_DTR){
-	    local_irq_save(flags);
-	    base_addr[CyCAR] = (u_char)channel;
-/* CP('S');CP('3'); */
-	    base_addr[CyMSVR2] = CyDTR;
-#ifdef SERIAL_DEBUG_DTR
-            printk("cyc: %d: raising DTR\n", __LINE__);
-            printk("     status: 0x%x, 0x%x\n", base_addr[CyMSVR1], base_addr[CyMSVR2]);
-#endif
-	    local_irq_restore(flags);
-	}else{
-	    local_irq_save(flags);
-	    base_addr[CyCAR] = (u_char)channel;
-/* CP('C');CP('3'); */
-	    base_addr[CyMSVR2] = 0;
-#ifdef SERIAL_DEBUG_DTR
-            printk("cyc: %d: dropping DTR\n", __LINE__);
-            printk("     status: 0x%x, 0x%x\n", base_addr[CyMSVR1], base_addr[CyMSVR2]);
-#endif
-	    local_irq_restore(flags);
-	}
-	break;
-    default:
-		return -EINVAL;
-        }
+
     return 0;
 } /* set_modem_info */
 
@@ -1777,11 +1736,6 @@ cy_ioctl(struct tty_struct *tty, struct 
             tty_wait_until_sent(tty,0);
             send_break(info, arg ? arg*(HZ/10) : HZ/4);
             break;
-        case TIOCMBIS:
-        case TIOCMBIC:
-        case TIOCMSET:
-            ret_val = set_modem_info(info, cmd, (unsigned int *) arg);
-            break;
 
 /* The following commands are incompletely implemented!!! */
         case TIOCGSOFTCAR:
@@ -1794,9 +1748,6 @@ cy_ioctl(struct tty_struct *tty, struct 
             tty->termios->c_cflag =
                     ((tty->termios->c_cflag & ~CLOCAL) | (val ? CLOCAL : 0));
             break;
-        case TIOCMGET:
-            ret_val = get_modem_info(info, (unsigned int *) arg);
-            break;
         case TIOCGSERIAL:
             ret_val = get_serial_info(info, (struct serial_struct *) arg);
             break;
@@ -2299,6 +2250,8 @@ static struct tty_operations cy_ops = {
 	.stop = cy_stop,
 	.start = cy_start,
 	.hangup = cy_hangup,
+	.tiocmget = cy_tiocmget,
+	.tiocmset = cy_tiocmset,
 };
 /* The serial driver boot-time initialization code!
     Hardware I/O ports are mapped to character special devices on a
--- diff/drivers/char/sh-sci.c	2004-02-18 08:54:09.000000000 +0000
+++ source/drivers/char/sh-sci.c	2004-02-23 13:56:41.000000000 +0000
@@ -1109,6 +1109,31 @@ static void sci_close(void *ptr)
         return;
 }
 
+static int sci_tiocmget(struct tty_struct *tty, struct file *file)
+{
+	struct sci_port *port = tty->driver_data;
+	return sci_getsignals(port);
+}
+
+static int sci_tiocmset(struct tty_struct *tty, struct file *file,
+			unsigned int set, unsigned int clear)
+{
+	struct sci_port *port = tty->driver_data;
+	int rts = -1, dtr = -1;
+
+	if (set & TIOCM_RTS)
+		rts = 1;
+	if (set & TIOCM_DTR)
+		dtr = 1;
+	if (clear & TIOCM_RTS)
+		rts = 0;
+	if (clear & TIOCM_DTR)
+		dtr = 0;
+
+	sci_setsignals(port, dtr, rts);
+	return 0;
+}
+
 static int sci_ioctl(struct tty_struct * tty, struct file * filp, 
                      unsigned int cmd, unsigned long arg)
 {
@@ -1139,26 +1164,6 @@ static int sci_ioctl(struct tty_struct *
 			rc = gs_setserial(&port->gs,
 					  (struct serial_struct *) arg);
 		break;
-	case TIOCMGET:
-		ival = sci_getsignals(port);
-		rc = put_user(ival, (unsigned int __user *) arg);
-		break;
-	case TIOCMBIS:
-		if ((rc = get_user(ival, (unsigned int __user *) arg)) == 0)
-			sci_setsignals(port, ((ival & TIOCM_DTR) ? 1 : -1),
-			                     ((ival & TIOCM_RTS) ? 1 : -1));
-		break;
-	case TIOCMBIC:
-		if ((rc = get_user(ival, (unsigned int __user *) arg)) == 0)
-			sci_setsignals(port, ((ival & TIOCM_DTR) ? 0 : -1),
-			                     ((ival & TIOCM_RTS) ? 0 : -1));
-		break;
-	case TIOCMSET:
-		if ((rc = get_user(ival, (unsigned int __user *)arg)) == 0)
-			sci_setsignals(port, ((ival & TIOCM_DTR) ? 1 : 0),
-			                     ((ival & TIOCM_RTS) ? 1 : 0));
-		break;
-
 	default:
 		rc = -ENOIOCTLCMD;
 		break;
@@ -1272,6 +1277,8 @@ static struct tty_operations sci_ops = {
 #ifdef CONFIG_PROC_FS
 	.read_proc = sci_read_proc,
 #endif
+	.tiocmget = sci_tiocmget,
+	.tiocmset = sci_tiocmset,
 };
 
 /* ********************************************************************** *
--- diff/drivers/char/sn_serial.c	2004-02-18 08:54:09.000000000 +0000
+++ source/drivers/char/sn_serial.c	2004-02-23 13:56:41.000000000 +0000
@@ -259,7 +259,7 @@ sn_debug_printf(const char *fmt, ...)
 	va_list args;
 
 	va_start(args, fmt);
-	printed_len = vsnprintf(printk_buf, sizeof(printk_buf), fmt, args);
+	printed_len = vscnprintf(printk_buf, sizeof(printk_buf), fmt, args);
 	early_printk_sn_sal(printk_buf, printed_len);
 	va_end(args);
 	return printed_len;
--- diff/drivers/char/specialix.c	2004-02-18 08:54:09.000000000 +0000
+++ source/drivers/char/specialix.c	2004-02-23 13:56:41.000000000 +0000
@@ -1653,13 +1653,17 @@ static void sx_flush_buffer(struct tty_s
 }
 
 
-static int sx_get_modem_info(struct specialix_port * port, unsigned int *value)
+static int sx_tiocmget(struct tty_struct *tty, struct file *file)
 {
+	struct specialix_port *port = (struct specialix_port *)tty->driver_data;
 	struct specialix_board * bp;
 	unsigned char status;
 	unsigned int result;
 	unsigned long flags;
 
+	if (sx_paranoia_check(port, tty->name, __FUNCTION__))
+		return -ENODEV;
+
 	bp = port_Board(port);
 	save_flags(flags); cli();
 	sx_out(bp, CD186x_CAR, port_No(port));
@@ -1683,71 +1687,51 @@ static int sx_get_modem_info(struct spec
 		          |/* ((status & MSVR_DSR) ? */ TIOCM_DSR /* : 0) */
 		          |   ((status & MSVR_CTS) ? TIOCM_CTS : 0);
 	}
-	put_user(result,(unsigned int *) value);
-	return 0;
+
+	return result;
 }
 
 
-static int sx_set_modem_info(struct specialix_port * port, unsigned int cmd,
-                             unsigned int *value)
+static int sx_tiocmset(struct tty_struct *tty, struct file *file,
+		       unsigned int set, unsigned int clear)
 {
+	struct specialix_port *port = (struct specialix_port *)tty->driver_data;
 	int error;
 	unsigned int arg;
 	unsigned long flags;
-	struct specialix_board *bp = port_Board(port);
+	struct specialix_board *bp;
 
-	error = verify_area(VERIFY_READ, value, sizeof(int));
-	if (error) 
-		return error;
+	if (sx_paranoia_check(port, tty->name, __FUNCTION__))
+		return -ENODEV;
+
+	bp = port_Board(port);
 
-	get_user(arg, (unsigned long *) value);
-	switch (cmd) {
-	case TIOCMBIS: 
-	   /*	if (arg & TIOCM_RTS) 
-			port->MSVR |= MSVR_RTS; */
-	   /*   if (arg & TIOCM_DTR)
-			port->MSVR |= MSVR_DTR; */
-
-		if (SX_CRTSCTS(port->tty)) {
-			if (arg & TIOCM_RTS)
-				port->MSVR |= MSVR_DTR; 
-		} else {
-			if (arg & TIOCM_DTR)
-				port->MSVR |= MSVR_DTR; 
-		}	     
-		break;
-	case TIOCMBIC:
-	  /*	if (arg & TIOCM_RTS)
-			port->MSVR &= ~MSVR_RTS; */
-	  /*    if (arg & TIOCM_DTR)
-			port->MSVR &= ~MSVR_DTR; */
-		if (SX_CRTSCTS(port->tty)) {
-			if (arg & TIOCM_RTS)
-				port->MSVR &= ~MSVR_DTR;
-		} else {
-			if (arg & TIOCM_DTR)
-				port->MSVR &= ~MSVR_DTR;
-		}
-		break;
-	case TIOCMSET:
-	  /* port->MSVR = (arg & TIOCM_RTS) ? (port->MSVR | MSVR_RTS) : 
-						 (port->MSVR & ~MSVR_RTS); */
-	  /* port->MSVR = (arg & TIOCM_DTR) ? (port->MSVR | MSVR_DTR) : 
-						 (port->MSVR & ~MSVR_DTR); */
-		if (SX_CRTSCTS(port->tty)) {
-	  		port->MSVR = (arg & TIOCM_RTS) ? 
-			                         (port->MSVR |  MSVR_DTR) : 
-			                         (port->MSVR & ~MSVR_DTR);
-		} else {
-			port->MSVR = (arg & TIOCM_DTR) ?
-			                         (port->MSVR |  MSVR_DTR):
-			                         (port->MSVR & ~MSVR_DTR);
-		}
-		break;
-	default:
-		return -EINVAL;
-	}
 	save_flags(flags); cli();
+   /*	if (set & TIOCM_RTS)
+		port->MSVR |= MSVR_RTS; */
+   /*   if (set & TIOCM_DTR)
+		port->MSVR |= MSVR_DTR; */
+
+	if (SX_CRTSCTS(port->tty)) {
+		if (set & TIOCM_RTS)
+			port->MSVR |= MSVR_DTR;
+	} else {
+		if (set & TIOCM_DTR)
+			port->MSVR |= MSVR_DTR;
+	}
+
+  /*	if (clear & TIOCM_RTS)
+		port->MSVR &= ~MSVR_RTS; */
+  /*    if (clear & TIOCM_DTR)
+		port->MSVR &= ~MSVR_DTR; */
+	if (SX_CRTSCTS(port->tty)) {
+		if (clear & TIOCM_RTS)
+			port->MSVR &= ~MSVR_DTR;
+	} else {
+		if (clear & TIOCM_DTR)
+			port->MSVR &= ~MSVR_DTR;
+	}
+
 	sx_out(bp, CD186x_CAR, port_No(port));
 	sx_out(bp, CD186x_MSVR, port->MSVR);
 	restore_flags(flags);
@@ -1897,16 +1881,6 @@ static int sx_ioctl(struct tty_struct * 
 			((tty->termios->c_cflag & ~CLOCAL) |
 			(arg ? CLOCAL : 0));
 		return 0;
-	 case TIOCMGET:
-		error = verify_area(VERIFY_WRITE, (void *) arg,
-		                    sizeof(unsigned int));
-		if (error)
-			return error;
-		return sx_get_modem_info(port, (unsigned int *) arg);
-	 case TIOCMBIS:
-	 case TIOCMBIC:
-	 case TIOCMSET:
-		return sx_set_modem_info(port, cmd, (unsigned int *) arg);
 	 case TIOCGSERIAL:	
 		return sx_get_serial_info(port, (struct serial_struct *) arg);
 	 case TIOCSSERIAL:	
@@ -2116,6 +2090,8 @@ static struct tty_operations sx_ops = {
 	.stop = sx_stop,
 	.start = sx_start,
 	.hangup = sx_hangup,
+	.tiocmget = sx_tiocmget,
+	.tiocmset = sx_tiocmset,
 };
 
 static int sx_init_drivers(void)
--- diff/drivers/char/stallion.c	2003-10-09 09:47:34.000000000 +0100
+++ source/drivers/char/stallion.c	2004-02-23 13:56:41.000000000 +0000
@@ -1514,6 +1514,48 @@ static int stl_setserial(stlport_t *port
 
 /*****************************************************************************/
 
+static int stl_tiocmget(struct tty_struct *tty, struct file *file)
+{
+	stlport_t	*portp;
+
+	if (tty == (struct tty_struct *) NULL)
+		return(-ENODEV);
+	portp = tty->driver_data;
+	if (portp == (stlport_t *) NULL)
+		return(-ENODEV);
+	if (tty->flags & (1 << TTY_IO_ERROR))
+		return(-EIO);
+
+	return stl_getsignals(portp);
+}
+
+static int stl_tiocmset(struct tty_struct *tty, struct file *file,
+			unsigned int set, unsigned int clear)
+{
+	stlport_t	*portp;
+	int rts = -1, dtr = -1;
+
+	if (tty == (struct tty_struct *) NULL)
+		return(-ENODEV);
+	portp = tty->driver_data;
+	if (portp == (stlport_t *) NULL)
+		return(-ENODEV);
+	if (tty->flags & (1 << TTY_IO_ERROR))
+		return(-EIO);
+
+	if (set & TIOCM_RTS)
+		rts = 1;
+	if (set & TIOCM_DTR)
+		dtr = 1;
+	if (clear & TIOCM_RTS)
+		rts = 0;
+	if (clear & TIOCM_DTR)
+		dtr = 0;
+
+	stl_setsignals(portp, dtr, rts);
+	return 0;
+}
+
 static int stl_ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd, unsigned long arg)
 {
 	stlport_t	*portp;
@@ -1553,37 +1595,6 @@ static int stl_ioctl(struct tty_struct *
 				(ival ? CLOCAL : 0);
 		}
 		break;
-	case TIOCMGET:
-		if ((rc = verify_area(VERIFY_WRITE, (void *) arg,
-		    sizeof(unsigned int))) == 0) {
-			ival = stl_getsignals(portp);
-			put_user(ival, (unsigned int *) arg);
-		}
-		break;
-	case TIOCMBIS:
-		if ((rc = verify_area(VERIFY_READ, (void *) arg,
-		    sizeof(unsigned int))) == 0) {
-			get_user(ival, (unsigned int *) arg);
-			stl_setsignals(portp, ((ival & TIOCM_DTR) ? 1 : -1),
-				((ival & TIOCM_RTS) ? 1 : -1));
-		}
-		break;
-	case TIOCMBIC:
-		if ((rc = verify_area(VERIFY_READ, (void *) arg,
-		    sizeof(unsigned int))) == 0) {
-			get_user(ival, (unsigned int *) arg);
-			stl_setsignals(portp, ((ival & TIOCM_DTR) ? 0 : -1),
-				((ival & TIOCM_RTS) ? 0 : -1));
-		}
-		break;
-	case TIOCMSET:
-		if ((rc = verify_area(VERIFY_READ, (void *) arg,
-		    sizeof(unsigned int))) == 0) {
-			get_user(ival, (unsigned int *) arg);
-			stl_setsignals(portp, ((ival & TIOCM_DTR) ? 1 : 0),
-				((ival & TIOCM_RTS) ? 1 : 0));
-		}
-		break;
 	case TIOCGSERIAL:
 		if ((rc = verify_area(VERIFY_WRITE, (void *) arg,
 		    sizeof(struct serial_struct))) == 0)
@@ -3137,6 +3148,8 @@ static struct tty_operations stl_ops = {
 	.wait_until_sent = stl_waituntilsent,
 	.send_xchar = stl_sendxchar,
 	.read_proc = stl_readproc,
+	.tiocmget = stl_tiocmget,
+	.tiocmset = stl_tiocmset,
 };
 
 /*****************************************************************************/
--- diff/drivers/char/sx.c	2004-01-19 10:22:56.000000000 +0000
+++ source/drivers/char/sx.c	2004-02-23 13:56:41.000000000 +0000
@@ -1743,6 +1743,32 @@ static void sx_break (struct tty_struct 
 }
 
 
+static int sx_tiocmget(struct tty_struct *tty, struct file *file)
+{
+	struct sx_port *port = tty->driver_data;
+	return sx_getsignals(port);
+}
+
+static int sx_tiocmset(struct tty_struct *tty, struct file *file,
+		       unsigned int set, unsigned int clear)
+{
+	struct sx_port *port = tty->driver_data;
+	int rts = -1, dtr = -1;
+
+	if (set & TIOCM_RTS)
+		rts = 1;
+	if (set & TIOCM_DTR)
+		dtr = 1;
+	if (clear & TIOCM_RTS)
+		rts = 0;
+	if (clear & TIOCM_DTR)
+		dtr = 0;
+
+	sx_setsignals(port, dtr, rts);
+	sx_reconfigure_port(port);
+	return 0;
+}
+
 static int sx_ioctl (struct tty_struct * tty, struct file * filp, 
                      unsigned int cmd, unsigned long arg)
 {
@@ -1775,34 +1801,6 @@ static int sx_ioctl (struct tty_struct *
 		                      sizeof(struct serial_struct))) == 0)
 			rc = gs_setserial(&port->gs, (struct serial_struct *) arg);
 		break;
-	case TIOCMGET:
-		if ((rc = verify_area(VERIFY_WRITE, (void *) arg,
-		                      sizeof(unsigned int))) == 0) {
-			ival = sx_getsignals(port);
-			put_user(ival, (unsigned int *) arg);
-		}
-		break;
-	case TIOCMBIS:
-		if ((rc = get_user(ival, (unsigned int *) arg)) == 0) {
-			sx_setsignals(port, ((ival & TIOCM_DTR) ? 1 : -1),
-			                     ((ival & TIOCM_RTS) ? 1 : -1));
-			sx_reconfigure_port(port);
-		}
-		break;
-	case TIOCMBIC:
-		if ((rc = get_user(ival, (unsigned int *) arg)) == 0) {
-			sx_setsignals(port, ((ival & TIOCM_DTR) ? 0 : -1),
-			                     ((ival & TIOCM_RTS) ? 0 : -1));
-			sx_reconfigure_port(port);
-		}
-		break;
-	case TIOCMSET:
-		if ((rc = get_user(ival, (unsigned int *) arg)) == 0) {
-			sx_setsignals(port, ((ival & TIOCM_DTR) ? 1 : 0),
-			                     ((ival & TIOCM_RTS) ? 1 : 0));
-			sx_reconfigure_port(port);
-		}
-		break;
 	default:
 		rc = -ENOIOCTLCMD;
 		break;
@@ -2217,6 +2215,8 @@ static struct tty_operations sx_ops = {
 	.stop = gs_stop,
 	.start = gs_start,
 	.hangup = gs_hangup,
+	.tiocmget = sx_tiocmget,
+	.tiocmset = sx_tiocmset,
 };
 
 static int sx_init_drivers(void)
--- diff/drivers/char/sysrq.c	2004-02-09 10:36:10.000000000 +0000
+++ source/drivers/char/sysrq.c	2004-02-23 13:56:41.000000000 +0000
@@ -35,6 +35,25 @@
 #include <linux/spinlock.h>
 
 #include <asm/ptrace.h>
+#ifdef CONFIG_KGDB_SYSRQ
+
+#define  GDB_OP &kgdb_op
+static void kgdb_sysrq(int key, struct pt_regs *pt_regs, struct tty_struct *tty)
+{
+	printk("kgdb sysrq\n");
+	breakpoint();
+}
+
+static struct sysrq_key_op kgdb_op = {
+	.handler	= kgdb_sysrq,
+	.help_msg	= "kGdb|Fgdb",
+	.action_msg	= "Debug breakpoint\n",
+};
+
+#else
+#define  GDB_OP NULL
+#endif
+
 
 extern void reset_vc(unsigned int);
 
@@ -238,8 +257,8 @@ static struct sysrq_key_op *sysrq_key_ta
 /* c */ NULL,
 /* d */	NULL,
 /* e */	&sysrq_term_op,
-/* f */	NULL,
-/* g */	NULL,
+/* f */	GDB_OP,
+/* g */	GDB_OP,
 /* h */	NULL,
 /* i */	&sysrq_kill_op,
 /* j */	NULL,
--- diff/drivers/char/tipar.c	2003-09-17 12:28:05.000000000 +0100
+++ source/drivers/char/tipar.c	2004-02-23 13:56:41.000000000 +0000
@@ -463,10 +463,9 @@ tipar_detach(struct parport *port)
 }
 
 static struct parport_driver tipar_driver = {
-	"tipar",
-	tipar_attach,
-	tipar_detach,
-	NULL
+	.name = "tipar",
+	.attach = tipar_attach,
+	.detach = tipar_detach,
 };
 
 int __init
--- diff/drivers/char/tty_io.c	2004-02-18 08:54:09.000000000 +0000
+++ source/drivers/char/tty_io.c	2004-02-23 13:56:41.000000000 +0000
@@ -124,7 +124,7 @@ struct tty_ldisc ldiscs[NR_LDISCS];	/* l
 
 #ifdef CONFIG_UNIX98_PTYS
 extern struct tty_driver *ptm_driver;	/* Unix98 pty masters; for /dev/ptmx */
-extern struct tty_driver *pts_driver;	/* Unix98 pty slaves;  for /dev/ptmx */
+extern int pty_limit;		/* Config limit on Unix98 ptys */
 #endif
 
 extern void disable_early_printk(void);
@@ -799,7 +799,13 @@ static int init_dev(struct tty_driver *d
 	down_tty_sem(idx);
 
 	/* check whether we're reopening an existing tty */
-	tty = driver->ttys[idx];
+	if (driver->flags & TTY_DRIVER_DEVPTS_MEM) {
+		tty = devpts_get_tty(idx);
+		if (tty && driver->subtype == PTY_TYPE_MASTER)
+			tty = tty->link;
+	} else {
+		tty = driver->ttys[idx];
+	}
 	if (tty) goto fast_track;
 
 	/*
@@ -827,7 +833,14 @@ static int init_dev(struct tty_driver *d
 	tty->index = idx;
 	tty_line_name(driver, idx, tty->name);
 
-	tp_loc = &driver->termios[idx];
+	if (driver->flags & TTY_DRIVER_DEVPTS_MEM) {
+		tp_loc = &tty->termios;
+		ltp_loc = &tty->termios_locked;
+	} else {
+		tp_loc = &driver->termios[idx];
+		ltp_loc = &driver->termios_locked[idx];
+	}
+
 	if (!*tp_loc) {
 		tp = (struct termios *) kmalloc(sizeof(struct termios),
 						GFP_KERNEL);
@@ -836,7 +849,6 @@ static int init_dev(struct tty_driver *d
 		*tp = driver->init_termios;
 	}
 
-	ltp_loc = &driver->termios_locked[idx];
 	if (!*ltp_loc) {
 		ltp = (struct termios *) kmalloc(sizeof(struct termios),
 						 GFP_KERNEL);
@@ -854,7 +866,14 @@ static int init_dev(struct tty_driver *d
 		o_tty->index = idx;
 		tty_line_name(driver->other, idx, o_tty->name);
 
-		o_tp_loc  = &driver->other->termios[idx];
+		if (driver->flags & TTY_DRIVER_DEVPTS_MEM) {
+			o_tp_loc = &o_tty->termios;
+			o_ltp_loc = &o_tty->termios_locked;
+		} else {
+			o_tp_loc = &driver->other->termios[idx];
+			o_ltp_loc = &driver->other->termios_locked[idx];
+		}
+
 		if (!*o_tp_loc) {
 			o_tp = (struct termios *)
 				kmalloc(sizeof(struct termios), GFP_KERNEL);
@@ -863,7 +882,6 @@ static int init_dev(struct tty_driver *d
 			*o_tp = driver->other->init_termios;
 		}
 
-		o_ltp_loc = &driver->other->termios_locked[idx];
 		if (!*o_ltp_loc) {
 			o_ltp = (struct termios *)
 				kmalloc(sizeof(struct termios), GFP_KERNEL);
@@ -875,7 +893,9 @@ static int init_dev(struct tty_driver *d
 		/*
 		 * Everything allocated ... set up the o_tty structure.
 		 */
-		driver->other->ttys[idx] = o_tty;
+		if (!(driver->other->flags & TTY_DRIVER_DEVPTS_MEM)) {
+			driver->other->ttys[idx] = o_tty;
+		}
 		if (!*o_tp_loc)
 			*o_tp_loc = o_tp;
 		if (!*o_ltp_loc)
@@ -896,7 +916,9 @@ static int init_dev(struct tty_driver *d
 	 * Failures after this point use release_mem to clean up, so 
 	 * there's no need to null out the local pointers.
 	 */
-	driver->ttys[idx] = tty;
+	if (!(driver->flags & TTY_DRIVER_DEVPTS_MEM)) {
+		driver->ttys[idx] = tty;
+	}
 	
 	if (!*tp_loc)
 		*tp_loc = tp;
@@ -994,12 +1016,20 @@ static void release_mem(struct tty_struc
 {
 	struct tty_struct *o_tty;
 	struct termios *tp;
+	int devpts = tty->driver->flags & TTY_DRIVER_DEVPTS_MEM;
 
 	if ((o_tty = tty->link) != NULL) {
-		o_tty->driver->ttys[idx] = NULL;
+		if (!devpts)
+			o_tty->driver->ttys[idx] = NULL;
 		if (o_tty->driver->flags & TTY_DRIVER_RESET_TERMIOS) {
-			tp = o_tty->driver->termios[idx];
-			o_tty->driver->termios[idx] = NULL;
+			tp = o_tty->termios;
+			if (!devpts)
+				o_tty->driver->termios[idx] = NULL;
+			kfree(tp);
+
+			tp = o_tty->termios_locked;
+			if (!devpts)
+				o_tty->driver->termios_locked[idx] = NULL;
 			kfree(tp);
 		}
 		o_tty->magic = 0;
@@ -1010,12 +1040,20 @@ static void release_mem(struct tty_struc
 		free_tty_struct(o_tty);
 	}
 
-	tty->driver->ttys[idx] = NULL;
+	if (!devpts)
+		tty->driver->ttys[idx] = NULL;
 	if (tty->driver->flags & TTY_DRIVER_RESET_TERMIOS) {
-		tp = tty->driver->termios[idx];
-		tty->driver->termios[idx] = NULL;
+		tp = tty->termios;
+		if (!devpts)
+			tty->driver->termios[idx] = NULL;
+		kfree(tp);
+
+		tp = tty->termios_locked;
+		if (!devpts)
+			tty->driver->termios_locked[idx] = NULL;
 		kfree(tp);
 	}
+
 	tty->magic = 0;
 	tty->driver->refcount--;
 	file_list_lock();
@@ -1059,22 +1097,24 @@ static void release_dev(struct file * fi
 				  "free (%s)\n", tty->name);
 		return;
 	}
-	if (tty != tty->driver->ttys[idx]) {
-		printk(KERN_DEBUG "release_dev: driver.table[%d] not tty "
-				  "for (%s)\n", idx, tty->name);
-		return;
-	}
-	if (tty->termios != tty->driver->termios[idx]) {
-		printk(KERN_DEBUG "release_dev: driver.termios[%d] not termios "
-		       "for (%s)\n",
-		       idx, tty->name);
-		return;
-	}
-	if (tty->termios_locked != tty->driver->termios_locked[idx]) {
-		printk(KERN_DEBUG "release_dev: driver.termios_locked[%d] not "
-		       "termios_locked for (%s)\n",
-		       idx, tty->name);
-		return;
+	if (!(tty->driver->flags & TTY_DRIVER_DEVPTS_MEM)) {
+		if (tty != tty->driver->ttys[idx]) {
+			printk(KERN_DEBUG "release_dev: driver.table[%d] not tty "
+			       "for (%s)\n", idx, tty->name);
+			return;
+		}
+		if (tty->termios != tty->driver->termios[idx]) {
+			printk(KERN_DEBUG "release_dev: driver.termios[%d] not termios "
+			       "for (%s)\n",
+			       idx, tty->name);
+			return;
+		}
+		if (tty->termios_locked != tty->driver->termios_locked[idx]) {
+			printk(KERN_DEBUG "release_dev: driver.termios_locked[%d] not "
+			       "termios_locked for (%s)\n",
+			       idx, tty->name);
+			return;
+		}
 	}
 #endif
 
@@ -1084,7 +1124,8 @@ static void release_dev(struct file * fi
 #endif
 
 #ifdef TTY_PARANOIA_CHECK
-	if (tty->driver->other) {
+	if (tty->driver->other &&
+	     !(tty->driver->flags & TTY_DRIVER_DEVPTS_MEM)) {
 		if (o_tty != tty->driver->other->ttys[idx]) {
 			printk(KERN_DEBUG "release_dev: other->table[%d] "
 					  "not o_tty for (%s)\n",
@@ -1328,23 +1369,29 @@ retry_open:
 		return -ENODEV;
 	}
 
-	if (device == MKDEV(TTYAUX_MAJOR,2)) {
 #ifdef CONFIG_UNIX98_PTYS
+	if (device == MKDEV(TTYAUX_MAJOR,2)) {
 		/* find a device that is not in use. */
+		static int next_ptmx_dev = 0;
 		retval = -1;
 		driver = ptm_driver;
-		for (index = 0; index < driver->num ; index++)
+		while (driver->refcount < pty_limit) {
+			index = next_ptmx_dev;
+			next_ptmx_dev = (next_ptmx_dev+1) % driver->num;
 			if (!init_dev(driver, index, &tty))
 				goto ptmx_found; /* ok! */
+		}
 		return -EIO; /* no free ptys */
 	ptmx_found:
 		set_bit(TTY_PTY_LOCK, &tty->flags); /* LOCK THE SLAVE */
-		devpts_pty_new(index, MKDEV(pts_driver->major, pts_driver->minor_start) + index);
+		if (devpts_pty_new(tty->link)) {
+			/* BADNESS - need to destroy both ptm and pts! */
+			return -ENOMEM;
+		}
 		noctty = 1;
-#else
-		return -ENODEV;
-#endif  /* CONFIG_UNIX_98_PTYS */
-	} else {
+	} else
+#endif
+	{
 		driver = get_tty_driver(device, &index);
 		if (!driver)
 			return -ENODEV;
@@ -2190,15 +2237,17 @@ int tty_register_driver(struct tty_drive
         int i;
 	dev_t dev;
 	char *s;
-	void **p;
+	void **p = NULL;
 
 	if (driver->flags & TTY_DRIVER_INSTALLED)
 		return 0;
 
-	p = kmalloc(driver->num * 3 * sizeof(void *), GFP_KERNEL);
-	if (!p)
-		return -ENOMEM;
-	memset(p, 0, driver->num * 3 * sizeof(void *));
+	if (!(driver->flags & TTY_DRIVER_DEVPTS_MEM)) {
+		p = kmalloc(driver->num * 3 * sizeof(void *), GFP_KERNEL);
+		if (!p)
+			return -ENOMEM;
+		memset(p, 0, driver->num * 3 * sizeof(void *));
+	}
 
 	if (!driver->major) {
 		error = alloc_chrdev_region(&dev, driver->minor_start, driver->num,
@@ -2217,9 +2266,15 @@ int tty_register_driver(struct tty_drive
 		return error;
 	}
 
-	driver->ttys = (struct tty_struct **)p;
-	driver->termios = (struct termios **)(p + driver->num);
-	driver->termios_locked = (struct termios **)(p + driver->num * 2);
+	if (p) {
+		driver->ttys = (struct tty_struct **)p;
+		driver->termios = (struct termios **)(p + driver->num);
+		driver->termios_locked = (struct termios **)(p + driver->num * 2);
+	} else {
+		driver->ttys = NULL;
+		driver->termios = NULL;
+		driver->termios_locked = NULL;
+	}
 
 	driver->cdev.kobj.parent = &tty_kobj;
 	strcpy(driver->cdev.kobj.name, driver->name);
@@ -2388,7 +2443,7 @@ static int __init tty_init(void)
 	devfs_mk_cdev(MKDEV(TTYAUX_MAJOR, 2), S_IFCHR|S_IRUGO|S_IWUGO, "ptmx");
 	class_simple_device_add(tty_class, MKDEV(TTYAUX_MAJOR, 2), NULL, "ptmx");
 #endif
-	
+
 #ifdef CONFIG_VT
 	strcpy(vc0_cdev.kobj.name, "dev.vc0");
 	cdev_init(&vc0_cdev, &console_fops);
--- diff/drivers/char/viocons.c	2004-02-09 10:36:10.000000000 +0000
+++ source/drivers/char/viocons.c	2004-02-23 13:56:41.000000000 +0000
@@ -149,7 +149,7 @@ void hvlog(char *fmt, ...)
 
 	spin_lock_irqsave(&consoleloglock, flags);
 	va_start(args, fmt);
-	i = vsnprintf(buf, sizeof(buf) - 1, fmt, args);
+	i = vscnprintf(buf, sizeof(buf) - 1, fmt, args);
 	va_end(args);
 	buf[i++] = '\r';
 	HvCall_writeLogBuffer(buf, i);
--- diff/drivers/char/vt.c	2004-02-18 08:54:09.000000000 +0000
+++ source/drivers/char/vt.c	2004-02-23 13:56:41.000000000 +0000
@@ -1883,14 +1883,24 @@ static int do_con_write(struct tty_struc
 	int c, tc, ok, n = 0, draw_x = -1;
 	unsigned int currcons;
 	unsigned long draw_from = 0, draw_to = 0;
-	struct vt_struct *vt = (struct vt_struct *)tty->driver_data;
+	struct vt_struct *vt;
 	u16 himask, charmask;
 	const unsigned char *orig_buf = NULL;
 	int orig_count;
 
 	if (in_interrupt())
 		return count;
-		
+
+	might_sleep();
+
+	acquire_console_sem();
+	vt = (struct vt_struct *)tty->driver_data;
+	if (vt == NULL) {
+		printk(KERN_ERR "vt: argh, driver_data is NULL !\n");
+		release_console_sem();
+		return 0;
+	}
+
 	currcons = vt->vc_num;
 	if (!vc_cons_allocated(currcons)) {
 	    /* could this happen? */
@@ -1899,13 +1909,16 @@ static int do_con_write(struct tty_struc
 		error = 1;
 		printk("con_write: tty %d not allocated\n", currcons+1);
 	    }
+	    release_console_sem();
 	    return 0;
 	}
+	release_console_sem();
 
 	orig_buf = buf;
 	orig_count = count;
 
 	if (from_user) {
+
 		down(&con_buf_sem);
 
 again:
@@ -1929,6 +1942,13 @@ again:
 
 	acquire_console_sem();
 
+	vt = (struct vt_struct *)tty->driver_data;
+	if (vt == NULL) {
+		printk(KERN_ERR "vt: argh, driver_data _became_ NULL !\n");
+		release_console_sem();
+		goto out;
+	}
+
 	himask = hi_font_mask;
 	charmask = himask ? 0x1ff : 0xff;
 
@@ -2442,14 +2462,16 @@ static int con_open(struct tty_struct *t
 
 	acquire_console_sem();
 	i = vc_allocate(currcons);
-	release_console_sem();
-	if (i)
+	if (i) {
+		release_console_sem();
 		return i;
-
+	}
 	vt_cons[currcons]->vc_num = currcons;
 	tty->driver_data = vt_cons[currcons];
 	vc_cons[currcons].d->vc_tty = tty;
 
+	release_console_sem();
+
 	if (!tty->winsize.ws_row && !tty->winsize.ws_col) {
 		tty->winsize.ws_row = video_num_lines;
 		tty->winsize.ws_col = video_num_columns;
@@ -2467,10 +2489,12 @@ static void con_close(struct tty_struct 
 		return;
 
 	vcs_remove_devfs(tty);
+	acquire_console_sem();
 	vt = (struct vt_struct*)tty->driver_data;
 	if (vt)
 		vc_cons[vt->vc_num].d->vc_tty = NULL;
 	tty->driver_data = 0;
+	release_console_sem();
 }
 
 static void vc_init(unsigned int currcons, unsigned int rows, unsigned int cols, int do_clear)
--- diff/drivers/char/vt_ioctl.c	2004-02-18 08:54:09.000000000 +0000
+++ source/drivers/char/vt_ioctl.c	2004-02-23 13:56:41.000000000 +0000
@@ -60,7 +60,7 @@ struct vt_struct *vt_cons[MAX_NR_CONSOLE
 unsigned char keyboard_type = KB_101;
 
 #ifdef CONFIG_X86
-asmlinkage long sys_ioperm(unsigned long from, unsigned long num, int on);
+#include <linux/syscalls.h>
 #endif
 
 /*
--- diff/drivers/cpufreq/cpufreq.c	2004-02-09 10:36:10.000000000 +0000
+++ source/drivers/cpufreq/cpufreq.c	2004-02-23 13:56:41.000000000 +0000
@@ -198,7 +198,7 @@ static ssize_t show_scaling_governor (st
 	else if (policy->policy == CPUFREQ_POLICY_PERFORMANCE)
 		return sprintf(buf, "performance\n");
 	else if (policy->governor)
-		return snprintf(buf, CPUFREQ_NAME_LEN, "%s\n", policy->governor->name);
+		return scnprintf(buf, CPUFREQ_NAME_LEN, "%s\n", policy->governor->name);
 	return -EINVAL;
 }
 
@@ -234,7 +234,7 @@ static ssize_t store_scaling_governor (s
  */
 static ssize_t show_scaling_driver (struct cpufreq_policy * policy, char *buf)
 {
-	return snprintf(buf, CPUFREQ_NAME_LEN, "%s\n", cpufreq_driver->name);
+	return scnprintf(buf, CPUFREQ_NAME_LEN, "%s\n", cpufreq_driver->name);
 }
 
 /**
@@ -254,7 +254,7 @@ static ssize_t show_scaling_available_go
 	list_for_each_entry(t, &cpufreq_governor_list, governor_list) {
 		if (i >= (ssize_t) ((PAGE_SIZE / sizeof(char)) - (CPUFREQ_NAME_LEN + 2)))
 			goto out;
-		i += snprintf(&buf[i], CPUFREQ_NAME_LEN, "%s ", t->name);
+		i += scnprintf(&buf[i], CPUFREQ_NAME_LEN, "%s ", t->name);
 	}
  out:
 	i += sprintf(&buf[i], "\n");
--- diff/drivers/cpufreq/proc_intf.c	2003-09-17 12:28:05.000000000 +0100
+++ source/drivers/cpufreq/proc_intf.c	2004-02-23 13:56:41.000000000 +0000
@@ -139,7 +139,7 @@ static int cpufreq_proc_read (
 				break;
 			} 
 		} else
-			p += snprintf(p, CPUFREQ_NAME_LEN, "%s\n", policy.governor->name);
+			p += scnprintf(p, CPUFREQ_NAME_LEN, "%s\n", policy.governor->name);
 	}
 end:
 	len = (p - page);
--- diff/drivers/i2c/Kconfig	2004-02-09 10:36:10.000000000 +0000
+++ source/drivers/i2c/Kconfig	2004-02-23 13:56:41.000000000 +0000
@@ -15,9 +15,6 @@ config I2C
 
 	  Both I2C and SMBus are supported here. You will need this for
 	  hardware sensors support, and also for Video For Linux support.
-	  Specifically, if you want to use a BT848 based frame grabber/overlay
-	  boards under Linux, say Y here and also to "I2C bit-banging
-	  interfaces", below.
 
 	  If you want I2C support, you should say Y here and also to the
 	  specific driver for your bus adapter(s) below.
--- diff/drivers/i2c/busses/Kconfig	2004-02-18 08:54:09.000000000 +0000
+++ source/drivers/i2c/busses/Kconfig	2004-02-23 13:56:41.000000000 +0000
@@ -144,6 +144,17 @@ config I2C_ITE
 	  This support is also available as a module.  If so, the module 
 	  will be called i2c-ite.
 
+config I2C_IXP42X
+	tristate "IXP42x GPIO-Based I2C Interface"
+	depends on I2C && ARCH_IXP425
+	select I2C_ALGOBIT
+	help
+	  Say Y here if you have an Intel IXP42x(420,421,422,425) based 
+	  system and are using GPIO lines for an I2C bus.
+
+	  This support is also available as a module. If so, the module
+	  will be called i2c-ixp42x.
+
 config I2C_KEYWEST
 	tristate "Powermac Keywest I2C interface"
 	depends on I2C && PPC_PMAC
--- diff/drivers/i2c/busses/Makefile	2004-02-18 08:54:09.000000000 +0000
+++ source/drivers/i2c/busses/Makefile	2004-02-23 13:56:41.000000000 +0000
@@ -15,6 +15,7 @@ obj-$(CONFIG_I2C_IBM_IIC)	+= i2c-ibm_iic
 obj-$(CONFIG_I2C_IOP3XX)	+= i2c-iop3xx.o
 obj-$(CONFIG_I2C_ISA)		+= i2c-isa.o
 obj-$(CONFIG_I2C_ITE)		+= i2c-ite.o
+obj-$(CONFIG_I2C_IXP42X)	+= i2c-ixp42x.o
 obj-$(CONFIG_I2C_KEYWEST)	+= i2c-keywest.o
 obj-$(CONFIG_I2C_NFORCE2)	+= i2c-nforce2.o
 obj-$(CONFIG_I2C_PHILIPSPAR)	+= i2c-philips-par.o
--- diff/drivers/i2c/busses/i2c-ali1535.c	2004-02-09 10:36:10.000000000 +0000
+++ source/drivers/i2c/busses/i2c-ali1535.c	2004-02-23 13:56:41.000000000 +0000
@@ -517,6 +517,7 @@ static int __devinit ali1535_probe(struc
 static void __devexit ali1535_remove(struct pci_dev *dev)
 {
 	i2c_del_adapter(&ali1535_adapter);
+	release_region(ali1535_smba, ALI1535_SMB_IOSIZE);
 }
 
 static struct pci_driver ali1535_driver = {
@@ -534,7 +535,6 @@ static int __init i2c_ali1535_init(void)
 static void __exit i2c_ali1535_exit(void)
 {
 	pci_unregister_driver(&ali1535_driver);
-	release_region(ali1535_smba, ALI1535_SMB_IOSIZE);
 }
 
 MODULE_AUTHOR("Frodo Looijaard <frodol@dds.nl>, "
--- diff/drivers/i2c/busses/i2c-elv.c	2004-02-09 10:36:10.000000000 +0000
+++ source/drivers/i2c/busses/i2c-elv.c	2004-02-23 13:56:41.000000000 +0000
@@ -38,11 +38,11 @@
 #include <asm/io.h>
 
 #define DEFAULT_BASE 0x378
-static int base=0;
+static long base=0;
 static unsigned char port_data = 0;
 
 /* --- Convenience defines for the parallel port:			*/
-#define BASE	(unsigned int)(data)
+#define BASE	(unsigned long)(data)
 #define DATA	BASE			/* Centronics data port		*/
 #define STAT	(BASE+1)		/* Centronics status port	*/
 #define CTRL	(BASE+2)		/* Centronics control port	*/
--- diff/drivers/i2c/busses/i2c-savage4.c	2004-02-09 10:36:10.000000000 +0000
+++ source/drivers/i2c/busses/i2c-savage4.c	2004-02-23 13:56:41.000000000 +0000
@@ -124,7 +124,7 @@ static int bit_savi2c_getsda(void *data)
 
 static int config_s4(struct pci_dev *dev)
 {
-	unsigned int cadr;
+	unsigned long cadr;
 
 	/* map memory */
 	cadr = dev->resource[0].start;
--- diff/drivers/i2c/busses/i2c-velleman.c	2004-02-09 10:36:10.000000000 +0000
+++ source/drivers/i2c/busses/i2c-velleman.c	2004-02-23 13:56:41.000000000 +0000
@@ -44,13 +44,13 @@
 
 
 /* --- Convenience defines for the parallel port:			*/
-#define BASE	(unsigned int)(data)
+#define BASE	(unsigned long)(data)
 #define DATA	BASE			/* Centronics data port		*/
 #define STAT	(BASE+1)		/* Centronics status port	*/
 #define CTRL	(BASE+2)		/* Centronics control port	*/
 
 #define DEFAULT_BASE 0x378
-static int base=0;
+static long base=0;
 
 /* ----- local functions --------------------------------------------------- */
 
--- diff/drivers/i2c/busses/i2c-voodoo3.c	2004-02-09 10:36:10.000000000 +0000
+++ source/drivers/i2c/busses/i2c-voodoo3.c	2004-02-23 13:56:41.000000000 +0000
@@ -144,7 +144,7 @@ static int bit_vooddc_getsda(void *data)
 
 static int config_v3(struct pci_dev *dev)
 {
-	unsigned int cadr;
+	unsigned long cadr;
 
 	/* map Voodoo3 memory */
 	cadr = dev->resource[0].start;
@@ -171,6 +171,7 @@ static struct i2c_algo_bit_data voo_i2c_
 
 static struct i2c_adapter voodoo3_i2c_adapter = {
 	.owner		= THIS_MODULE,
+	.class		= I2C_ADAP_CLASS_TV_ANALOG, 
 	.name		= "I2C Voodoo3/Banshee adapter",
 	.algo_data	= &voo_i2c_bit_data,
 };
@@ -187,6 +188,7 @@ static struct i2c_algo_bit_data voo_ddc_
 
 static struct i2c_adapter voodoo3_ddc_adapter = {
 	.owner		= THIS_MODULE,
+	.class		= I2C_ADAP_CLASS_DDC, 
 	.name		= "DDC Voodoo3/Banshee adapter",
 	.algo_data	= &voo_ddc_bit_data,
 };
--- diff/drivers/i2c/chips/Kconfig	2004-02-18 08:54:09.000000000 +0000
+++ source/drivers/i2c/chips/Kconfig	2004-02-23 13:56:41.000000000 +0000
@@ -102,6 +102,17 @@ config SENSORS_LM78
 	  This driver can also be built as a module.  If so, the module
 	  will be called lm78.
 
+config SENSORS_LM80
+	tristate "National Semiconductor LM80"
+	depends on I2C && EXPERIMENTAL
+	select I2C_SENSOR
+	help
+	  If you say yes here you get support for National Semiconductor
+	  LM80 sensor chips.
+
+	  This driver can also be built as a module.  If so, the module
+	  will be called lm80.
+
 config SENSORS_LM83
 	tristate "National Semiconductor LM83"
 	depends on I2C && EXPERIMENTAL
--- diff/drivers/i2c/chips/Makefile	2004-02-18 08:54:09.000000000 +0000
+++ source/drivers/i2c/chips/Makefile	2004-02-23 13:56:41.000000000 +0000
@@ -13,6 +13,7 @@ obj-$(CONFIG_SENSORS_GL518SM)	+= gl518sm
 obj-$(CONFIG_SENSORS_IT87)	+= it87.o
 obj-$(CONFIG_SENSORS_LM75)	+= lm75.o
 obj-$(CONFIG_SENSORS_LM78)	+= lm78.o
+obj-$(CONFIG_SENSORS_LM80)	+= lm80.o
 obj-$(CONFIG_SENSORS_LM83)	+= lm83.o
 obj-$(CONFIG_SENSORS_LM85)	+= lm85.o
 obj-$(CONFIG_SENSORS_LM90)	+= lm90.o
--- diff/drivers/i2c/chips/fscher.c	2004-02-18 08:54:09.000000000 +0000
+++ source/drivers/i2c/chips/fscher.c	2004-02-23 13:56:41.000000000 +0000
@@ -26,6 +26,11 @@
  *  and Philip Edelbrock <phil@netroedge.com>
  */
 
+#include <linux/config.h>
+#ifdef CONFIG_I2C_DEBUG_CHIP
+#define DEBUG	1
+#endif
+
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/slab.h>
--- diff/drivers/i2c/chips/lm85.c	2004-02-18 08:54:09.000000000 +0000
+++ source/drivers/i2c/chips/lm85.c	2004-02-23 13:56:41.000000000 +0000
@@ -383,7 +383,7 @@ struct lm85_data {
 	u8 syncpwm3;		/* Saved PWM3 for TACH 2,3,4 config */
 	u8 oppoint[3];		/* Register value */
 	u16 tmin_ctl;		/* Register value */
-	u32 therm_total;	/* Cummulative therm count */
+	unsigned long therm_total; /* Cummulative therm count */
 	u8 therm_limit;		/* Register value */
 	u16 alarms;		/* Register encoding, combined */
 	struct lm85_autofan autofan[3];
--- diff/drivers/i2c/chips/w83l785ts.c	2004-02-18 08:54:09.000000000 +0000
+++ source/drivers/i2c/chips/w83l785ts.c	2004-02-23 13:56:41.000000000 +0000
@@ -12,6 +12,9 @@
  * Ported to Linux 2.6 by Wolfgang Ziegler <nuppla@gmx.at> and Jean Delvare
  * <khali@linux-fr.org>.
  *
+ * Thanks to James Bolt <james@evilpenguin.com> for benchmarking the read
+ * error handling mechanism.
+ *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
--- diff/drivers/i2c/i2c-core.c	2004-02-18 08:54:09.000000000 +0000
+++ source/drivers/i2c/i2c-core.c	2004-02-23 13:56:41.000000000 +0000
@@ -618,7 +618,7 @@ int i2c_control(struct i2c_client *clien
 	int ret = 0;
 	struct i2c_adapter *adap = client->adapter;
 
-	dev_dbg(&client->dev, "i2c ioctl, cmd: 0x%x, arg: %#lx\n", cmd, arg);
+	dev_dbg(&client->adapter->dev, "i2c ioctl, cmd: 0x%x, arg: %#lx\n", cmd, arg);
 	switch (cmd) {
 		case I2C_RETRIES:
 			adap->retries = arg;
--- diff/drivers/ide/ide-cd.c	2004-02-18 08:54:09.000000000 +0000
+++ source/drivers/ide/ide-cd.c	2004-02-23 13:56:41.000000000 +0000
@@ -3517,7 +3517,7 @@ static int ide_cdrom_attach (ide_drive_t
 		printk("%s: Can't allocate a cdrom structure\n", drive->name);
 		goto failed;
 	}
-	if (ide_register_subdriver(drive, &ide_cdrom_driver, IDE_SUBDRIVER_VERSION)) {
+	if (ide_register_subdriver(drive, &ide_cdrom_driver)) {
 		printk("%s: Failed to register the driver with ide.c\n",
 			drive->name);
 		kfree(info);
--- diff/drivers/ide/ide-default.c	2003-09-30 15:46:14.000000000 +0100
+++ source/drivers/ide/ide-default.c	2004-02-23 13:56:41.000000000 +0000
@@ -51,8 +51,7 @@ ide_driver_t idedefault_driver = {
 
 static int idedefault_attach (ide_drive_t *drive)
 {
-	if (ide_register_subdriver(drive,
-			&idedefault_driver, IDE_SUBDRIVER_VERSION)) {
+	if (ide_register_subdriver(drive, &idedefault_driver)) {
 		printk(KERN_ERR "ide-default: %s: Failed to register the "
 			"driver with ide.c\n", drive->name);
 		return 1;
--- diff/drivers/ide/ide-disk.c	2004-02-18 08:54:09.000000000 +0000
+++ source/drivers/ide/ide-disk.c	2004-02-23 13:56:41.000000000 +0000
@@ -834,13 +834,6 @@ ide_startstop_t idedisk_error (ide_drive
 		ide_end_drive_cmd(drive, stat, err);
 		return ide_stopped;
 	}
-#if 0
-	else if (rq->flags & REQ_DRIVE_TASKFILE) {
-		rq->errors = 1;
-		ide_end_taskfile(drive, stat, err);
-		return ide_stopped;
-	}
-#endif
 #ifdef CONFIG_IDE_TASKFILE_IO
 	/* make rq completion pointers new submission pointers */
 	blk_rq_prep_restart(rq);
@@ -1700,7 +1693,6 @@ static ide_driver_t idedisk_driver = {
 	.busy			= 0,
 	.supports_dsc_overlap	= 0,
 	.cleanup		= idedisk_cleanup,
-	.flushcache		= do_idedisk_flushcache,
 	.do_request		= ide_do_rw_disk,
 	.sense			= idedisk_dump_status,
 	.error			= idedisk_error,
@@ -1829,7 +1821,7 @@ static int idedisk_attach(ide_drive_t *d
 	if (drive->media != ide_disk)
 		goto failed;
 
-	if (ide_register_subdriver (drive, &idedisk_driver, IDE_SUBDRIVER_VERSION)) {
+	if (ide_register_subdriver(drive, &idedisk_driver)) {
 		printk (KERN_ERR "ide-disk: %s: Failed to register the driver with ide.c\n", drive->name);
 		goto failed;
 	}
--- diff/drivers/ide/ide-floppy.c	2004-02-18 08:54:09.000000000 +0000
+++ source/drivers/ide/ide-floppy.c	2004-02-23 13:56:41.000000000 +0000
@@ -2055,7 +2055,7 @@ static int idefloppy_attach (ide_drive_t
 		printk (KERN_ERR "ide-floppy: %s: Can't allocate a floppy structure\n", drive->name);
 		goto failed;
 	}
-	if (ide_register_subdriver (drive, &idefloppy_driver, IDE_SUBDRIVER_VERSION)) {
+	if (ide_register_subdriver(drive, &idefloppy_driver)) {
 		printk (KERN_ERR "ide-floppy: %s: Failed to register the driver with ide.c\n", drive->name);
 		kfree (floppy);
 		goto failed;
--- diff/drivers/ide/ide-generic.c	2004-02-18 08:54:09.000000000 +0000
+++ source/drivers/ide/ide-generic.c	2004-02-23 13:56:41.000000000 +0000
@@ -22,9 +22,8 @@ static int __init ide_generic_init(void)
 	if (ide_hwifs[0].io_ports[IDE_DATA_OFFSET])
 		ide_release_lock();	/* for atari only */
 
-#ifdef CONFIG_PROC_FS
 	create_proc_ide_interfaces();
-#endif
+
 	return 0;
 }
 
--- diff/drivers/ide/ide-io.c	2004-01-19 10:22:56.000000000 +0000
+++ source/drivers/ide/ide-io.c	2004-02-23 13:56:41.000000000 +0000
@@ -300,7 +300,6 @@ ide_startstop_t ide_error (ide_drive_t *
 	if (rq->flags & REQ_DRIVE_TASKFILE) {
 		rq->errors = 1;
 		ide_end_drive_cmd(drive, stat, err);
-//		ide_end_taskfile(drive, stat, err);
 		return ide_stopped;
 	}
 
@@ -387,7 +386,6 @@ ide_startstop_t ide_abort(ide_drive_t *d
 	if (rq->flags & REQ_DRIVE_TASKFILE) {
 		rq->errors = 1;
 		ide_end_drive_cmd(drive, BUSY_STAT, 0);
-//		ide_end_taskfile(drive, BUSY_STAT, 0);
 		return ide_stopped;
 	}
 
@@ -591,7 +589,7 @@ EXPORT_SYMBOL(execute_drive_cmd);
 ide_startstop_t start_request (ide_drive_t *drive, struct request *rq)
 {
 	ide_startstop_t startstop;
-	unsigned long block;
+	sector_t block;
 
 	BUG_ON(!(rq->flags & REQ_STARTED));
 
--- diff/drivers/ide/ide-probe.c	2004-02-09 10:36:10.000000000 +0000
+++ source/drivers/ide/ide-probe.c	2004-02-23 13:56:41.000000000 +0000
@@ -237,27 +237,9 @@ static inline void do_identify (ide_driv
 	 */
 	if (id->config & (1<<7))
 		drive->removable = 1;
-		
-	/*
-	 * Prevent long system lockup probing later for non-existant
-	 * slave drive if the hwif is actually a flash memory card of
-	 * some variety:
-	 */
-	drive->is_flash = 0;
-	if (drive_is_flashcard(drive)) {
-#if 0
-		/* The new IDE adapter widgets don't follow this heuristic
-		   so we must nowdays just bite the bullet and take the
-		   probe hit */	
-		ide_drive_t *mate = &hwif->drives[1^drive->select.b.unit];		
-		ide_drive_t *mate = &hwif->drives[1^drive->select.b.unit];
-		if (!mate->ata_flash) {
-			mate->present = 0;
-			mate->noprobe = 1;
-		}
-#endif		
+
+	if (drive_is_flashcard(drive))
 		drive->is_flash = 1;
-	}
 	drive->media = ide_disk;
 	printk("%s DISK drive\n", (drive->is_flash) ? "CFA" : "ATA" );
 	QUIRK_LIST(drive);
--- diff/drivers/ide/ide-proc.c	2004-02-09 10:36:10.000000000 +0000
+++ source/drivers/ide/ide-proc.c	2004-02-23 13:56:41.000000000 +0000
@@ -109,17 +109,6 @@ static int xx_xx_parse_error (const char
 	return -EINVAL;
 }
 
-static struct proc_dir_entry * proc_ide_root = NULL;
-
-#ifdef CONFIG_BLK_DEV_IDEPCI
-#include <linux/delay.h>
-/*
- * This is the list of registered PCI chipset driver data structures.
- */
-static ide_pci_host_proc_t * ide_pci_host_proc_list;
-
-#endif /* CONFIG_BLK_DEV_IDEPCI */
-
 static int proc_ide_write_config
 	(struct file *file, const char *buffer, unsigned long count, void *data)
 {
@@ -787,27 +776,16 @@ void create_proc_ide_interfaces(void)
 	}
 }
 
+EXPORT_SYMBOL(create_proc_ide_interfaces);
+
 #ifdef CONFIG_BLK_DEV_IDEPCI
-void ide_pci_register_host_proc (ide_pci_host_proc_t *p)
+void ide_pci_create_host_proc(const char *name, get_info_t *get_info)
 {
-	ide_pci_host_proc_t *tmp;
-
-	if (!p) return;
-	p->next = NULL;
-	p->set = 1;
-	if (ide_pci_host_proc_list) {
-		tmp = ide_pci_host_proc_list;
-		while (tmp->next) tmp = tmp->next;
-		tmp->next = p;
-	} else
-		ide_pci_host_proc_list = p;
+	create_proc_info_entry(name, 0, proc_ide_root, get_info);
 }
 
-EXPORT_SYMBOL(ide_pci_register_host_proc);
-
-#endif /* CONFIG_BLK_DEV_IDEPCI */
-
-EXPORT_SYMBOL(create_proc_ide_interfaces);
+EXPORT_SYMBOL_GPL(ide_pci_create_host_proc);
+#endif
 
 void destroy_proc_ide_interfaces(void)
 {
@@ -846,45 +824,22 @@ static struct file_operations ide_driver
 
 void proc_ide_create(void)
 {
-#ifdef CONFIG_BLK_DEV_IDEPCI
-	ide_pci_host_proc_t *p = ide_pci_host_proc_list;
-#endif /* CONFIG_BLK_DEV_IDEPCI */
 	struct proc_dir_entry *entry;
-	proc_ide_root = proc_mkdir("ide", 0);
-	if (!proc_ide_root) return;
+
+	if (!proc_ide_root)
+		return;
 
 	create_proc_ide_interfaces();
 
 	entry = create_proc_entry("drivers", 0, proc_ide_root);
 	if (entry)
 		entry->proc_fops = &ide_drivers_operations;
-
-#ifdef CONFIG_BLK_DEV_IDEPCI
-	while (p != NULL)
-	{
-		if (p->name != NULL && p->set == 1 && p->get_info != NULL) 
-		{
-			p->parent = proc_ide_root;
-			create_proc_info_entry(p->name, 0, p->parent, p->get_info);
-			p->set = 2;
-		}
-		p = p->next;
-	}
-#endif /* CONFIG_BLK_DEV_IDEPCI */
 }
 
 EXPORT_SYMBOL(proc_ide_create);
 
 void proc_ide_destroy(void)
 {
-#ifdef CONFIG_BLK_DEV_IDEPCI
-	ide_pci_host_proc_t *p;
-
-	for (p = ide_pci_host_proc_list; p; p = p->next) {
-		if (p->set == 2)
-			remove_proc_entry(p->name, p->parent);
-	}
-#endif /* CONFIG_BLK_DEV_IDEPCI */
 	remove_proc_entry("ide/drivers", proc_ide_root);
 	destroy_proc_ide_interfaces();
 	remove_proc_entry("ide", 0);
--- diff/drivers/ide/ide-tape.c	2004-02-18 08:54:09.000000000 +0000
+++ source/drivers/ide/ide-tape.c	2004-02-23 13:56:41.000000000 +0000
@@ -451,18 +451,6 @@
 #include <asm/bitops.h>
 
 /*
- *	OnStream support
- */
-#define ONSTREAM_DEBUG		(0)
-#define OS_CONFIG_PARTITION	(0xff)
-#define OS_DATA_PARTITION	(0)
-#define OS_PARTITION_VERSION	(1)
-#define OS_EW			300
-#define OS_ADR_MINREV		2
-
-#define OS_DATA_STARTFRAME1	20
-#define OS_DATA_ENDFRAME1	2980
-/*
  * partition
  */
 typedef struct os_partition_s {
@@ -498,87 +486,6 @@ typedef struct os_dat_s {
 	os_dat_entry_t	dat_list[16];
 } os_dat_t;
 
-/*
- * Frame types
- */
-#define OS_FRAME_TYPE_FILL	(0)
-#define OS_FRAME_TYPE_EOD	(1 << 0)
-#define OS_FRAME_TYPE_MARKER	(1 << 1)
-#define OS_FRAME_TYPE_HEADER	(1 << 3)
-#define OS_FRAME_TYPE_DATA	(1 << 7)
-
-/*
- * AUX
- */
-typedef struct os_aux_s {
-	__u32		format_id;		/* hardware compatibility AUX is based on */
-	char		application_sig[4];	/* driver used to write this media */
-	__u32		hdwr;			/* reserved */
-	__u32		update_frame_cntr;	/* for configuration frame */
-	__u8		frame_type;
-	__u8		frame_type_reserved;
-	__u8		reserved_18_19[2];
-	os_partition_t	partition;
-	__u8		reserved_36_43[8];
-	__u32		frame_seq_num;
-	__u32		logical_blk_num_high;
-	__u32		logical_blk_num;
-	os_dat_t	dat;
-	__u8		reserved188_191[4];
-	__u32		filemark_cnt;
-	__u32		phys_fm;
-	__u32		last_mark_addr;
-	__u8		reserved204_223[20];
-
-	/*
-	 * __u8		app_specific[32];
-	 *
-	 * Linux specific fields:
-	 */
-	 __u32		next_mark_addr;		/* when known, points to next marker */
-	 __u8		linux_specific[28];
-
-	__u8		reserved_256_511[256];
-} os_aux_t;
-
-typedef struct os_header_s {
-	char		ident_str[8];
-	__u8		major_rev;
-	__u8		minor_rev;
-	__u8		reserved10_15[6];
-	__u8		par_num;
-	__u8		reserved1_3[3];
-	os_partition_t	partition;
-} os_header_t;
-
-/*
- *	OnStream Tape Parameters Page
- */
-typedef struct {
-	unsigned	page_code	:6;	/* Page code - Should be 0x2b */
-	unsigned	reserved1_6	:1;
-	unsigned	ps		:1;
-	__u8		reserved2;
-	__u8		density;		/* kbpi */
-	__u8		reserved3,reserved4;
-	__u16		segtrk;                 /* segment of per track */
-	__u16		trks;                   /* tracks per tape */
-	__u8		reserved5,reserved6,reserved7,reserved8,reserved9,reserved10;
-} onstream_tape_paramtr_page_t;
-
-/*
- * OnStream ADRL frame
- */
-#define OS_FRAME_SIZE	(32 * 1024 + 512)
-#define OS_DATA_SIZE	(32 * 1024)
-#define OS_AUX_SIZE	(512)
-
-/*
- * internal error codes for onstream
- */
-#define OS_PART_ERROR    2
-#define OS_WRITE_ERROR   1
-
 #include <linux/mtio.h>
 
 /**************************** Tunable parameters *****************************/
@@ -842,7 +749,6 @@ typedef struct idetape_stage_s {
 	struct request rq;			/* The corresponding request */
 	struct idetape_bh *bh;			/* The data buffers */
 	struct idetape_stage_s *next;		/* Pointer to the next stage */
-	os_aux_t *aux;				/* OnStream aux ptr */
 } idetape_stage_t;
 
 /*
@@ -1037,52 +943,6 @@ typedef struct {
 	char write_prot;
 
 	/*
-	 * OnStream flags
-	 */
-	/* the tape is an OnStream tape */
-	int onstream;
-	/* OnStream raw access (32.5KB block size) */
-	int raw;
-	/* current number of frames in internal buffer */
-	int cur_frames;
-	/* max number of frames in internal buffer */
-	int max_frames;
-	/* logical block number */
-	int logical_blk_num;
-	/* write pass counter */
-	__u16 wrt_pass_cntr;
-	/* update frame counter */
-	__u32 update_frame_cntr;
-	struct completion *waiting;
-	/* write error recovery active */
-	int onstream_write_error;
-	/* header frame verified ok */
-	int header_ok;
-	/* reading linux-specific media */
-	int linux_media;
-	int linux_media_version;
-	/* application signature */
-	char application_sig[5];
-	int filemark_cnt;
-	int first_mark_addr;
-	int last_mark_addr;
-	int eod_frame_addr;
-	unsigned long cmd_start_time;
-	unsigned long max_cmd_time;
-	unsigned capacity;
-
-	/*
-	 * Optimize the number of "buffer filling"
-	 * mode sense commands.
-	 */
-	/* last time in which we issued fill cmd */
-	unsigned long last_buffer_fill;
-	/* buffer fill command requested */
-	int req_buffer_fill;
-	int writes_since_buffer_fill;
-	int reads_since_buffer_fill;
-
-	/*
 	 * Limit the number of times a request can
 	 * be postponed, to avoid an infinite postpone
 	 * deadlock.
@@ -1468,7 +1328,6 @@ char *idetape_command_key_verbose(u8 ide
  *      Function declarations
  *
  */
-static void idetape_onstream_mode_sense_tape_parameter_page(ide_drive_t *drive, int debug);
 static int idetape_chrdev_release (struct inode *inode, struct file *filp);
 static void idetape_write_release (ide_drive_t *drive, unsigned int minor);
 
@@ -1659,13 +1518,6 @@ static void idetape_analyze_error (ide_d
 #endif /* IDETAPE_DEBUG_LOG_VERBOSE */
 #endif /* IDETAPE_DEBUG_LOG */
 
-	if (tape->onstream && result->sense_key == 2 &&
-	    result->asc == 0x53 && result->ascq == 2) {
-		clear_bit(PC_DMA_ERROR, &pc->flags);
-		ide_stall_queue(drive, HZ / 2);
-		return;
-	}
-
 	/*
 	 *	Correct pc->actually_transferred by asking the tape.
 	 */
@@ -1706,7 +1558,7 @@ static void idetape_analyze_error (ide_d
 			set_bit(PC_ABORT, &pc->flags);
 		}
 		if (!test_bit(PC_ABORT, &pc->flags) &&
-		    (tape->onstream || pc->actually_transferred))
+		    pc->actually_transferred)
 			pc->retries = IDETAPE_MAX_PC_RETRIES + 1;
 	}
 }
@@ -1868,11 +1720,6 @@ static int idetape_end_request(ide_drive
 	int error;
 	int remove_stage = 0;
 	idetape_stage_t *active_stage;
-#if ONSTREAM_DEBUG
-	idetape_stage_t *stage;
-	os_aux_t *aux;
-	unsigned char *p;
-#endif
 
 #if IDETAPE_DEBUG_LOG
         if (tape->debug_level >= 4)
@@ -1897,50 +1744,11 @@ static int idetape_end_request(ide_drive
 		tape->active_data_request = NULL;
 		tape->nr_pending_stages--;
 		if (rq->cmd[0] & REQ_IDETAPE_WRITE) {
-#if ONSTREAM_DEBUG
-			if (tape->debug_level >= 2) {
-				if (tape->onstream) {
-					stage = tape->first_stage;
-					aux = stage->aux;
-					p = stage->bh->b_data;
-					if (ntohl(aux->logical_blk_num) < 11300 && ntohl(aux->logical_blk_num) > 11100)
-						printk(KERN_INFO "ide-tape: finished writing logical blk %u (data %x %x %x %x)\n", ntohl(aux->logical_blk_num), *p++, *p++, *p++, *p++);
-				}
-			}
-#endif
-			if (tape->onstream && !tape->raw) {
-				if (tape->first_frame_position == OS_DATA_ENDFRAME1) { 
-#if ONSTREAM_DEBUG
-					if (tape->debug_level >= 2)
-						printk("ide-tape: %s: skipping over config partition.\n", tape->name);
-#endif
-					tape->onstream_write_error = OS_PART_ERROR;
-					if (tape->waiting) {
-						rq->waiting = NULL;
-						complete(tape->waiting);
-					}
-				}
-			}
 			remove_stage = 1;
 			if (error) {
 				set_bit(IDETAPE_PIPELINE_ERROR, &tape->flags);
 				if (error == IDETAPE_ERROR_EOD)
 					idetape_abort_pipeline(drive, active_stage);
-				if (tape->onstream && !tape->raw &&
-				    error == IDETAPE_ERROR_GENERAL &&
-				    tape->sense.sense_key == 3) {
-					clear_bit(IDETAPE_PIPELINE_ERROR, &tape->flags);
-					printk(KERN_ERR "ide-tape: %s: write error, enabling error recovery\n", tape->name);
-					tape->onstream_write_error = OS_WRITE_ERROR;
-					remove_stage = 0;
-					tape->nr_pending_stages++;
-					tape->next_stage = tape->first_stage;
-					rq->current_nr_sectors = rq->nr_sectors;
-					if (tape->waiting) {
-						rq->waiting = NULL;
-						complete(tape->waiting);
-					}
-				}
 			}
 		} else if (rq->cmd[0] & REQ_IDETAPE_READ) {
 			if (error == IDETAPE_ERROR_EOD) {
@@ -1948,7 +1756,7 @@ static int idetape_end_request(ide_drive
 				idetape_abort_pipeline(drive, active_stage);
 			}
 		}
-		if (tape->next_stage != NULL && !tape->onstream_write_error) {
+		if (tape->next_stage != NULL) {
 			idetape_active_next_stage(drive);
 
 			/*
@@ -1956,7 +1764,6 @@ static int idetape_end_request(ide_drive
 			 */
 			(void) ide_do_drive_cmd(drive, tape->active_data_request, ide_end);
 		} else if (!error) {
-			if (!tape->onstream)
 				idetape_increase_max_pipeline_stages(drive);
 		}
 	}
@@ -2089,7 +1896,6 @@ static ide_startstop_t idetape_pc_intr (
 	idetape_pc_t *pc = tape->pc;
 
 	unsigned int temp;
-	unsigned long cmd_time;
 #if SIMULATE_ERRORS
 	static int error_sim_count = 0;
 #endif
@@ -2139,8 +1945,6 @@ static ide_startstop_t idetape_pc_intr (
 
 	/* No more interrupts */
 	if (!status.b.drq) {
-		cmd_time = (jiffies - tape->cmd_start_time) * 1000 / HZ;
-		tape->max_cmd_time = max(cmd_time, tape->max_cmd_time);
 #if IDETAPE_DEBUG_LOG
 		if (tape->debug_level >= 2)
 			printk(KERN_INFO "ide-tape: Packet command completed, %d bytes transferred\n", pc->actually_transferred);
@@ -2178,8 +1982,7 @@ static ide_startstop_t idetape_pc_intr (
 			return idetape_retry_pc(drive);
 		}
 		pc->error = 0;
-		if (!tape->onstream &&
-		    test_bit(PC_WAIT_FOR_DSC, &pc->flags) &&
+		if (test_bit(PC_WAIT_FOR_DSC, &pc->flags) &&
 		    !status.b.dsc) {
 			/* Media access command */
 			tape->dsc_polling_start = jiffies;
@@ -2333,7 +2136,6 @@ static ide_startstop_t idetape_transfer_
 				"a packet command\n");
 		return ide_do_reset(drive);
 	}
-	tape->cmd_start_time = jiffies;
 	/* Set the interrupt routine */
 	ide_set_handler(drive, &idetape_pc_intr, IDETAPE_WAIT_CMD, NULL);
 #ifdef CONFIG_BLK_DEV_IDEDMA
@@ -2383,12 +2185,6 @@ static ide_startstop_t idetape_issue_pac
 						tape->name, pc->c[0],
 						tape->sense_key, tape->asc,
 						tape->ascq);
-				if (tape->onstream &&
-				    pc->c[0] == IDETAPE_READ_CMD &&
-				    tape->sense_key == 3 &&
-				    tape->asc == 0x11)
-					/* AJN-1: 11 should be 0x11 */
-					printk(KERN_ERR "ide-tape: %s: enabling read error recovery\n", tape->name);
 			}
 			/* Giving up */
 			pc->error = IDETAPE_ERROR_GENERAL;
@@ -2482,48 +2278,6 @@ static void idetape_create_mode_sense_cm
 	pc->callback = &idetape_pc_callback;
 }
 
-static ide_startstop_t idetape_onstream_buffer_fill_callback (ide_drive_t *drive)
-{
-	idetape_tape_t *tape = drive->driver_data;
-
-	tape->max_frames = tape->pc->buffer[4 + 2];
-	tape->cur_frames = tape->pc->buffer[4 + 3];
-	if (tape->chrdev_direction == idetape_direction_write)
-		tape->tape_head = tape->buffer_head - tape->cur_frames;
-	else
-		tape->tape_head = tape->buffer_head + tape->cur_frames;
-	if (tape->tape_head != tape->last_tape_head) {
-		tape->last_tape_head = tape->tape_head;
-		tape->tape_still_time_begin = jiffies;
-		if (tape->tape_still_time > 200)
-			tape->measure_insert_time = 1;
-	}
-	tape->tape_still_time = (jiffies - tape->tape_still_time_begin) * 1000 / HZ;
-#if USE_IOTRACE
-	IO_trace(IO_IDETAPE_FIFO, tape->pipeline_head, tape->buffer_head,
-			tape->tape_head, tape->minor);
-#endif
-#if IDETAPE_DEBUG_LOG
-	if (tape->debug_level >= 1)
-		printk(KERN_INFO "ide-tape: buffer fill callback, %d/%d\n",
-			tape->cur_frames, tape->max_frames);
-#endif
-	idetape_end_request(drive, tape->pc->error ? 0 : 1, 0);
-	return ide_stopped;
-}
-
-static void idetape_queue_onstream_buffer_fill (ide_drive_t *drive)
-{
-	idetape_pc_t *pc;
-	struct request *rq;
-
-	pc = idetape_next_pc_storage(drive);
-	rq = idetape_next_rq_storage(drive);
-	idetape_create_mode_sense_cmd(pc, IDETAPE_BUFFER_FILLING_PAGE);
-	pc->callback = idetape_onstream_buffer_fill_callback;
-	idetape_queue_pc_head(drive, pc, rq);
-}
-
 static void calculate_speeds(ide_drive_t *drive)
 {
 	idetape_tape_t *tape = drive->driver_data;
@@ -2579,8 +2333,6 @@ static ide_startstop_t idetape_media_acc
 	idetape_pc_t *pc = tape->pc;
 	atapi_status_t status;
 
-	if (tape->onstream)
-		printk(KERN_INFO "ide-tape: bug: onstream, media_access_finished\n");
 	status.all = HWIF(drive)->INB(IDE_STATUS_REG);
 	if (status.b.dsc) {
 		if (status.b.check) {
@@ -2641,7 +2393,6 @@ static ide_startstop_t idetape_rw_callba
 
 static void idetape_create_read_cmd(idetape_tape_t *tape, idetape_pc_t *pc, unsigned int length, struct idetape_bh *bh)
 {
-	struct idetape_bh *p = bh;
 	idetape_init_pc(pc);
 	pc->c[0] = IDETAPE_READ_CMD;
 	put_unaligned(htonl(length), (unsigned int *) &pc->c[1]);
@@ -2650,23 +2401,9 @@ static void idetape_create_read_cmd(idet
 	pc->bh = bh;
 	atomic_set(&bh->b_count, 0);
 	pc->buffer = NULL;
-	if (tape->onstream) {
-		while (p) {
-			atomic_set(&p->b_count, 0);
-			p = p->b_reqnext;
-		}
-	}
-	if (!tape->onstream) {
-		pc->request_transfer = pc->buffer_size = length * tape->tape_block_size;
-		if (pc->request_transfer == tape->stage_size)
-			set_bit(PC_DMA_RECOMMENDED, &pc->flags);
-	} else  {
-		if (length) {
-			pc->request_transfer = pc->buffer_size = 32768 + 512;
-			set_bit(PC_DMA_RECOMMENDED, &pc->flags);
-		} else
-			pc->request_transfer = 0;
-	}
+	pc->request_transfer = pc->buffer_size = length * tape->tape_block_size;
+	if (pc->request_transfer == tape->stage_size)
+		set_bit(PC_DMA_RECOMMENDED, &pc->flags);
 }
 
 static void idetape_create_read_buffer_cmd(idetape_tape_t *tape, idetape_pc_t *pc, unsigned int length, struct idetape_bh *bh)
@@ -2692,35 +2429,19 @@ static void idetape_create_read_buffer_c
 
 static void idetape_create_write_cmd(idetape_tape_t *tape, idetape_pc_t *pc, unsigned int length, struct idetape_bh *bh)
 {
-	struct idetape_bh *p = bh;
-
 	idetape_init_pc(pc);
 	pc->c[0] = IDETAPE_WRITE_CMD;
 	put_unaligned(htonl(length), (unsigned int *) &pc->c[1]);
 	pc->c[1] = 1;
 	pc->callback = &idetape_rw_callback;
 	set_bit(PC_WRITING, &pc->flags);
-	if (tape->onstream) {
-		while (p) {
-			atomic_set(&p->b_count, p->b_size);
-			p = p->b_reqnext;
-		}
-	}
 	pc->bh = bh;
 	pc->b_data = bh->b_data;
 	pc->b_count = atomic_read(&bh->b_count);
 	pc->buffer = NULL;
-	if (!tape->onstream) {
-		pc->request_transfer = pc->buffer_size = length * tape->tape_block_size;
-		if (pc->request_transfer == tape->stage_size)
-			set_bit(PC_DMA_RECOMMENDED, &pc->flags);
-	} else  {
-		if (length) {
-			pc->request_transfer = pc->buffer_size = 32768 + 512;
-			set_bit(PC_DMA_RECOMMENDED, &pc->flags);
-		} else
-			pc->request_transfer = 0;
-	}
+	pc->request_transfer = pc->buffer_size = length * tape->tape_block_size;
+	if (pc->request_transfer == tape->stage_size)
+		set_bit(PC_DMA_RECOMMENDED, &pc->flags);
 }
 
 /*
@@ -2782,65 +2503,14 @@ static ide_startstop_t idetape_do_reques
 	 */
 	status.all = HWIF(drive)->INB(IDE_STATUS_REG);
 
-	/*
-	 * The OnStream tape drive doesn't support DSC. Assume
-	 * that DSC is always set.
-	 */
-	if (tape->onstream)
-		status.b.dsc = 1;
 	if (!drive->dsc_overlap && !(rq->cmd[0] & REQ_IDETAPE_PC2))
 		set_bit(IDETAPE_IGNORE_DSC, &tape->flags);
 
-	/*
-	 * For the OnStream tape, check the current status of the tape
-	 * internal buffer using data gathered from the buffer fill
-	 * mode page, and postpone our request, effectively "disconnecting"
-	 * from the IDE bus, in case the buffer is full (writing) or
-	 * empty (reading), and there is a danger that our request will
-	 * hold the IDE bus during actual media access.
-	 */
 	if (tape->tape_still_time > 100 && tape->tape_still_time < 200)
 		tape->measure_insert_time = 1;
-	if (tape->req_buffer_fill &&
-	    (rq->cmd[0] & (REQ_IDETAPE_WRITE | REQ_IDETAPE_READ))) {
-		tape->req_buffer_fill = 0;
-		tape->writes_since_buffer_fill = 0;
-		tape->reads_since_buffer_fill = 0;
-		tape->last_buffer_fill = jiffies;
-		idetape_queue_onstream_buffer_fill(drive);
-		if (time_after(jiffies, tape->insert_time))
-			tape->insert_speed = tape->insert_size / 1024 * HZ / (jiffies - tape->insert_time);
-		return ide_stopped;
-	}
 	if (time_after(jiffies, tape->insert_time))
 		tape->insert_speed = tape->insert_size / 1024 * HZ / (jiffies - tape->insert_time);
 	calculate_speeds(drive);
-	if (tape->onstream && tape->max_frames &&
-	    (((rq->cmd[0] & REQ_IDETAPE_WRITE) &&
-              ( tape->cur_frames == tape->max_frames ||
-                ( tape->speed_control && tape->cur_frames > 5 &&
-                       (tape->insert_speed > tape->max_insert_speed ||
-                        (0 /* tape->cur_frames > 30 && tape->tape_still_time > 200 */) ) ) ) ) ||
-	     ((rq->cmd[0] & REQ_IDETAPE_READ) &&
-	      ( tape->cur_frames == 0 ||
-		( tape->speed_control && (tape->cur_frames < tape->max_frames - 5) &&
-			tape->insert_speed > tape->max_insert_speed ) ) && rq->nr_sectors) ) ) {
-#if IDETAPE_DEBUG_LOG
-		if (tape->debug_level >= 4)
-			printk(KERN_INFO "ide-tape: postponing request, "
-					"cmd %ld, cur %d, max %d\n",
-				rq->cmd[0], tape->cur_frames, tape->max_frames);
-#endif
-		if (tape->postpone_cnt++ < 500) {
-			status.b.dsc = 0;
-			tape->req_buffer_fill = 1;
-		}
-#if ONSTREAM_DEBUG
-		else if (tape->debug_level >= 4) 
-			printk(KERN_INFO "ide-tape: %s: postpone_cnt %d\n",
-				tape->name, tape->postpone_cnt);
-#endif
-	}
 	if (!test_and_clear_bit(IDETAPE_IGNORE_DSC, &tape->flags) &&
 	    !status.b.dsc) {
 		if (postponed_rq == NULL) {
@@ -2867,13 +2537,6 @@ static ide_startstop_t idetape_do_reques
 		IO_trace(IO_IDETAPE_FIFO, tape->pipeline_head, tape->buffer_head, tape->tape_head, tape->minor);
 #endif
 		tape->postpone_cnt = 0;
-		tape->reads_since_buffer_fill++;
-		if (tape->onstream) {
-			if (tape->cur_frames - tape->reads_since_buffer_fill <= 0)
-				tape->req_buffer_fill = 1;
-			if (time_after(jiffies, tape->last_buffer_fill + 5 * HZ / 100))
-				tape->req_buffer_fill = 1;
-		}
 		pc = idetape_next_pc_storage(drive);
 		idetape_create_read_cmd(tape, pc, rq->current_nr_sectors, (struct idetape_bh *)rq->special);
 		goto out;
@@ -2884,14 +2547,6 @@ static ide_startstop_t idetape_do_reques
 		IO_trace(IO_IDETAPE_FIFO, tape->pipeline_head, tape->buffer_head, tape->tape_head, tape->minor);
 #endif
 		tape->postpone_cnt = 0;
-		tape->writes_since_buffer_fill++;
-		if (tape->onstream) {
-			if (tape->cur_frames + tape->writes_since_buffer_fill >= tape->max_frames)
-				tape->req_buffer_fill = 1;
-			if (time_after(jiffies, tape->last_buffer_fill + 5 * HZ / 100))
-				tape->req_buffer_fill = 1;
-			calculate_speeds(drive);
-		}
 		pc = idetape_next_pc_storage(drive);
 		idetape_create_write_cmd(tape, pc, rq->current_nr_sectors, (struct idetape_bh *)rq->special);
 		goto out;
@@ -2995,8 +2650,6 @@ static idetape_stage_t *__idetape_kmallo
 	bh->b_size -= tape->excess_bh_size;
 	if (full)
 		atomic_sub(tape->excess_bh_size, &bh->b_count);
-	if (tape->onstream)
-		stage->aux = (os_aux_t *) (bh->b_data + bh->b_size - OS_AUX_SIZE);
 	return stage;
 abort:
 	__idetape_kfree_stage(stage);
@@ -3093,14 +2746,10 @@ static void idetape_init_merge_stage (id
 static void idetape_switch_buffers (idetape_tape_t *tape, idetape_stage_t *stage)
 {
 	struct idetape_bh *tmp;
-	os_aux_t *tmp_aux;
 
 	tmp = stage->bh;
-	tmp_aux = stage->aux;
 	stage->bh = tape->merge_stage->bh;
-	stage->aux = tape->merge_stage->aux;
 	tape->merge_stage->bh = tmp;
-	tape->merge_stage->aux = tmp_aux;
 	idetape_init_merge_stage(tape);
 }
 
@@ -3131,68 +2780,6 @@ static void idetape_add_stage_tail (ide_
 }
 
 /*
- * Initialize the OnStream AUX
- */
-static void idetape_init_stage (ide_drive_t *drive, idetape_stage_t *stage, int frame_type, int logical_blk_num)
-{
-	idetape_tape_t *tape = drive->driver_data;
-	os_aux_t *aux = stage->aux;
-	os_partition_t *par = &aux->partition;
-	os_dat_t *dat = &aux->dat;
-
-	if (!tape->onstream || tape->raw)
-		return;
-	memset(aux, 0, sizeof(*aux));
-	aux->format_id = htonl(0);
-	memcpy(aux->application_sig, "LIN3", 4);
-	aux->hdwr = htonl(0);
-	aux->frame_type = frame_type;
-
-	if (frame_type == OS_FRAME_TYPE_HEADER) {
-		aux->update_frame_cntr = htonl(tape->update_frame_cntr);
-		par->partition_num = OS_CONFIG_PARTITION;
-		par->par_desc_ver = OS_PARTITION_VERSION;
-		par->wrt_pass_cntr = htons(0xffff);
-		par->first_frame_addr = htonl(0);
-		par->last_frame_addr = htonl(0xbb7); /* 2999 */
-		aux->frame_seq_num = htonl(0);
-		aux->logical_blk_num_high = htonl(0);
-		aux->logical_blk_num = htonl(0);
-		aux->next_mark_addr = htonl(tape->first_mark_addr);
-	} else {
-		aux->update_frame_cntr = htonl(0);
-		par->partition_num = OS_DATA_PARTITION;
-		par->par_desc_ver = OS_PARTITION_VERSION;
-		par->wrt_pass_cntr = htons(tape->wrt_pass_cntr);
-		par->first_frame_addr = htonl(OS_DATA_STARTFRAME1);
-		par->last_frame_addr = htonl(tape->capacity);
-		aux->frame_seq_num = htonl(logical_blk_num);
-		aux->logical_blk_num_high = htonl(0);
-		aux->logical_blk_num = htonl(logical_blk_num);
-		dat->dat_sz = 8;
-		dat->reserved1 = 0;
-		dat->entry_cnt = 1;
-		dat->reserved3 = 0;
-		if (frame_type == OS_FRAME_TYPE_DATA)
-			dat->dat_list[0].blk_sz = htonl(32 * 1024);
-		else
-			dat->dat_list[0].blk_sz = 0;
-		dat->dat_list[0].blk_cnt = htons(1);
-		if (frame_type == OS_FRAME_TYPE_MARKER)
-			dat->dat_list[0].flags = OS_DAT_FLAGS_MARK;
-		else
-			dat->dat_list[0].flags = OS_DAT_FLAGS_DATA;
-		dat->dat_list[0].reserved = 0;
-	}
-	/* shouldn't this be htonl ?? */
-	aux->filemark_cnt = ntohl(tape->filemark_cnt);
-	/* shouldn't this be htonl ?? */
-	aux->phys_fm = ntohl(0xffffffff);
-	/* shouldn't this be htonl ?? */
-	aux->last_mark_addr = ntohl(tape->last_mark_addr);
-}
-
-/*
  *	idetape_wait_for_request installs a completion in a pending request
  *	and sleeps until it is serviced.
  *
@@ -3211,11 +2798,9 @@ static void idetape_wait_for_request (id
 	}
 #endif /* IDETAPE_DEBUG_BUGS */
 	rq->waiting = &wait;
-	tape->waiting = &wait;
 	spin_unlock_irq(&tape->spinlock);
 	wait_for_completion(&wait);
 	/* The stage and its struct request have been deallocated */
-	tape->waiting = NULL;
 	spin_lock_irq(&tape->spinlock);
 }
 
@@ -3269,13 +2854,9 @@ static ide_startstop_t idetape_read_posi
  */
 static void idetape_create_write_filemark_cmd (ide_drive_t *drive, idetape_pc_t *pc,int write_filemark)
 {
-	idetape_tape_t *tape = drive->driver_data;
-
 	idetape_init_pc(pc);
 	pc->c[0] = IDETAPE_WRITE_FILEMARK_CMD;
-	if (tape->onstream)
-		pc->c[1] = 1; /* Immed bit */
-	pc->c[4] = write_filemark;  /* not used for OnStream ?? */
+	pc->c[4] = write_filemark;
 	set_bit(PC_WAIT_FOR_DSC, &pc->flags);
 	pc->callback = &idetape_pc_callback;
 }
@@ -3318,16 +2899,9 @@ static int __idetape_queue_pc_tail (ide_
 
 static void idetape_create_load_unload_cmd (ide_drive_t *drive, idetape_pc_t *pc,int cmd)
 {
-	idetape_tape_t *tape = drive->driver_data;
-
 	idetape_init_pc(pc);
 	pc->c[0] = IDETAPE_LOAD_UNLOAD_CMD;
 	pc->c[4] = cmd;
-	if (tape->onstream) {
-		pc->c[1] = 1;
-		if (cmd == !IDETAPE_LU_LOAD_MASK)
-			pc->c[4] = 4;
-	}
 	set_bit(PC_WAIT_FOR_DSC, &pc->flags);
 	pc->callback = &idetape_pc_callback;
 }
@@ -3366,20 +2940,7 @@ static int idetape_wait_ready(ide_drive_
 
 static int idetape_queue_pc_tail (ide_drive_t *drive,idetape_pc_t *pc)
 {
-	idetape_tape_t *tape = drive->driver_data;
-	int rc;
-
-	rc = __idetape_queue_pc_tail(drive, pc);
-	if (rc)
-		return rc;
-	if (tape->onstream && test_bit(PC_WAIT_FOR_DSC, &pc->flags)) {
-		/* AJN-4: Changed from 5 to 10 minutes;
-		 * because retension takes approx.
-		 * 8:20 with Onstream 30GB tape
-		 */
-		rc = idetape_wait_ready(drive, 60 * 10 * HZ);
-	}
-	return rc;
+	return __idetape_queue_pc_tail(drive, pc);
 }
 
 static int idetape_flush_tape_buffers (ide_drive_t *drive)
@@ -3422,23 +2983,11 @@ static int idetape_read_position (ide_dr
 
 static void idetape_create_locate_cmd (ide_drive_t *drive, idetape_pc_t *pc, unsigned int block, u8 partition, int skip)
 {
-	idetape_tape_t *tape = drive->driver_data;
-
 	idetape_init_pc(pc);
 	pc->c[0] = IDETAPE_LOCATE_CMD;
-	if (tape->onstream)
-		pc->c[1] = 1; /* Immediate bit */
-	else
-		pc->c[1] = 2;
+	pc->c[1] = 2;
 	put_unaligned(htonl(block), (unsigned int *) &pc->c[3]);
 	pc->c[8] = partition;
-	if (tape->onstream)
-                /*
-                 * Set SKIP bit.
-                 * In case of write error this will write buffered
-                 * data in the drive to this new position!
-                 */
-		pc->c[9] = skip << 7;
 	set_bit(PC_WAIT_FOR_DSC, &pc->flags);
 	pc->callback = &idetape_pc_callback;
 }
@@ -3539,10 +3088,6 @@ static void idetape_discard_read_pipelin
 	cnt = __idetape_discard_read_pipeline(drive);
 	if (restore_position) {
 		position = idetape_read_position(drive);
-#if ONSTREAM_DEBUG
-		if (tape->debug_level >= 2)
-			printk(KERN_INFO "ide-tape: address %u, nr_stages %d\n", position, cnt);
-#endif
 		seek = position > cnt ? position - cnt : 0;
 		if (idetape_position_tape(drive, seek, 0, 0)) {
 			printk(KERN_INFO "ide-tape: %s: position_tape failed in discard_pipeline()\n", tape->name);
@@ -3551,15 +3096,6 @@ static void idetape_discard_read_pipelin
 	}
 }
 
-static void idetape_update_stats (ide_drive_t *drive)
-{
-	idetape_pc_t pc;
-
-	idetape_create_mode_sense_cmd(&pc, IDETAPE_BUFFER_FILLING_PAGE);
-	pc.callback = idetape_onstream_buffer_fill_callback;
-	(void) idetape_queue_pc_tail(drive, &pc);
-}
-
 /*
  * idetape_queue_rw_tail generates a read/write request for the block
  * device interface and wait for it to be serviced.
@@ -3584,8 +3120,6 @@ static int idetape_queue_rw_tail(ide_dri
 	rq.special = (void *)bh;
 	rq.sector = tape->first_frame_position;
 	rq.nr_sectors = rq.current_nr_sectors = blocks;
-	if (tape->onstream)
-		tape->postpone_cnt = 600;
 	(void) ide_do_drive_cmd(drive, &rq, ide_wait);
 
 	if ((cmd & (REQ_IDETAPE_READ | REQ_IDETAPE_WRITE)) == 0)
@@ -3599,108 +3133,6 @@ static int idetape_queue_rw_tail(ide_dri
 }
 
 /*
- * Read back the drive's internal buffer contents, as a part
- * of the write error recovery mechanism for old OnStream
- * firmware revisions.
- */
-static void idetape_onstream_read_back_buffer (ide_drive_t *drive)
-{
-	idetape_tape_t *tape = drive->driver_data;
-	int frames, i, logical_blk_num;
-	idetape_stage_t *stage, *first = NULL, *last = NULL;
-	os_aux_t *aux;
-	struct request *rq;
-	unsigned char *p;
-	unsigned long flags;
-
-	idetape_update_stats(drive);
-	frames = tape->cur_frames;
-	logical_blk_num = ntohl(tape->first_stage->aux->logical_blk_num) - frames;
-	printk(KERN_INFO "ide-tape: %s: reading back %d frames from the drive's internal buffer\n", tape->name, frames);
-	for (i = 0; i < frames; i++) {
-		stage = __idetape_kmalloc_stage(tape, 0, 0);
-		if (!first)
-			first = stage;
-		aux = stage->aux;
-		p = stage->bh->b_data;
-		idetape_queue_rw_tail(drive, REQ_IDETAPE_READ_BUFFER, tape->capabilities.ctl, stage->bh);
-#if ONSTREAM_DEBUG
-		if (tape->debug_level >= 2)
-			printk(KERN_INFO "ide-tape: %s: read back logical block %d, data %x %x %x %x\n", tape->name, logical_blk_num, *p++, *p++, *p++, *p++);
-#endif
-		rq = &stage->rq;
-		idetape_init_rq(rq, REQ_IDETAPE_WRITE);
-		rq->sector = tape->first_frame_position;
-		rq->nr_sectors = rq->current_nr_sectors = tape->capabilities.ctl;
-		idetape_init_stage(drive, stage, OS_FRAME_TYPE_DATA, logical_blk_num++);
-		stage->next = NULL;
-		if (last)
-			last->next = stage;
-		last = stage;
-	}
-	if (frames) {
-		spin_lock_irqsave(&tape->spinlock, flags);
-		last->next = tape->first_stage;
-		tape->next_stage = tape->first_stage = first;
-		tape->nr_stages += frames;
-		tape->nr_pending_stages += frames;
-		spin_unlock_irqrestore(&tape->spinlock, flags);
-	}
-	idetape_update_stats(drive);
-#if ONSTREAM_DEBUG
-	if (tape->debug_level >= 2)
-		printk(KERN_INFO "ide-tape: %s: frames left in buffer: %d\n", tape->name, tape->cur_frames);
-#endif
-}
-
-/*
- * Error recovery algorithm for the OnStream tape.
- */
-static void idetape_onstream_write_error_recovery (ide_drive_t *drive)
-{
-	idetape_tape_t *tape = drive->driver_data;
-	unsigned int block;
-
-	if (tape->onstream_write_error == OS_WRITE_ERROR) {
-		printk(KERN_ERR "ide-tape: %s: onstream_write_error_recovery: detected physical bad block at %u, logical %u first frame %u last_frame %u bufblocks %u stages %u skipping %u frames\n",
-			tape->name, ntohl(tape->sense.information), tape->logical_blk_num,
-			tape->first_frame_position, tape->last_frame_position,
-			tape->blocks_in_buffer, tape->nr_stages,
- 			(ntohl(tape->sense.command_specific) >> 16) & 0xff );
-		block = ntohl(tape->sense.information) + ((ntohl(tape->sense.command_specific) >> 16) & 0xff);
-		idetape_update_stats(drive);
-		printk(KERN_ERR "ide-tape: %s: relocating %d buffered logical blocks to physical block %u\n", tape->name, tape->cur_frames, block);
-#if 0  /* isn't once enough ??? MM */
-		idetape_update_stats(drive);
-#endif
-		if (tape->firmware_revision_num >= 106)
-			idetape_position_tape(drive, block, 0, 1);
-		else {
-			idetape_onstream_read_back_buffer(drive);
-			idetape_position_tape(drive, block, 0, 0);
-		}
-#if 0     /* already done in idetape_position_tape MM */
-		idetape_read_position(drive);
-#endif
-#if ONSTREAM_DEBUG
-		if (tape->debug_level >= 1)
-			printk(KERN_ERR "ide-tape: %s: positioning complete, cur_frames %d, pos %d, tape pos %d\n", tape->name, tape->cur_frames, tape->first_frame_position, tape->last_frame_position);
-#endif
-	} else if (tape->onstream_write_error == OS_PART_ERROR) {
-#if ONSTREAM_DEBUG
-		if (tape->debug_level >= 1)
-			printk(KERN_INFO "ide-tape: %s: skipping over config partition\n", tape->name);
-#endif
-		idetape_flush_tape_buffers(drive);
-		block = idetape_read_position(drive);
-		if (block != OS_DATA_ENDFRAME1)  
-			printk(KERN_ERR "ide-tape: warning, current position %d, expected %d\n", block, OS_DATA_ENDFRAME1);
-		idetape_position_tape(drive, 0xbb8, 0, 0); /* 3000 */
-	}
-	tape->onstream_write_error = 0;
-}
-
-/*
  *	idetape_insert_pipeline_into_queue is used to start servicing the
  *	pipeline stages, starting from tape->next_stage.
  */
@@ -3711,8 +3143,6 @@ static void idetape_insert_pipeline_into
 	if (tape->next_stage == NULL)
 		return;
 	if (!idetape_pipeline_active(tape)) {
-		if (tape->onstream_write_error)
-			idetape_onstream_write_error_recovery(drive);
 		set_bit(IDETAPE_PIPELINE_ACTIVE, &tape->flags);
 		idetape_active_next_stage(drive);
 		(void) ide_do_drive_cmd(drive, tape->active_data_request, ide_end);
@@ -3729,16 +3159,13 @@ static void idetape_create_inquiry_cmd (
 
 static void idetape_create_rewind_cmd (ide_drive_t *drive, idetape_pc_t *pc)
 {
-	idetape_tape_t *tape = drive->driver_data;
-
 	idetape_init_pc(pc);
 	pc->c[0] = IDETAPE_REWIND_CMD;
-	if (tape->onstream)
-		pc->c[1] = 1;
 	set_bit(PC_WAIT_FOR_DSC, &pc->flags);
 	pc->callback = &idetape_pc_callback;
 }
 
+#if 0
 static void idetape_create_mode_select_cmd (idetape_pc_t *pc, int length)
 {
 	idetape_init_pc(pc);
@@ -3749,6 +3176,7 @@ static void idetape_create_mode_select_c
 	pc->request_transfer = 255;
 	pc->callback = &idetape_pc_callback;
 }
+#endif
 
 static void idetape_create_erase_cmd (idetape_pc_t *pc)
 {
@@ -3769,82 +3197,6 @@ static void idetape_create_space_cmd (id
 	pc->callback = &idetape_pc_callback;
 }
 
-/*
- * Verify that we have the correct tape frame
- */
-static int idetape_verify_stage (ide_drive_t *drive, idetape_stage_t *stage, int logical_blk_num, int quiet)
-{
-	idetape_tape_t *tape = drive->driver_data;
-	os_aux_t *aux = stage->aux;
-	os_partition_t *par = &aux->partition;
-	struct request *rq = &stage->rq;
-	struct idetape_bh *bh;
-
-	if (!tape->onstream)
-		return 1;
-	if (tape->raw) {
-		if (rq->errors) {
-			bh = stage->bh;
-			while (bh) {
-				memset(bh->b_data, 0, bh->b_size);
-				bh = bh->b_reqnext;
-			}
-			strcpy(stage->bh->b_data, "READ ERROR ON FRAME");
-		}
-		return 1;
-	}
-	if (rq->errors == IDETAPE_ERROR_GENERAL) {
-		printk(KERN_INFO "ide-tape: %s: skipping frame %d, read error\n", tape->name, tape->first_frame_position);
-		return 0;
-	}
-	if (rq->errors == IDETAPE_ERROR_EOD) {
-		printk(KERN_INFO "ide-tape: %s: skipping frame %d, eod\n", tape->name, tape->first_frame_position);
-		return 0;
-	}
-	if (ntohl(aux->format_id) != 0) {
-		printk(KERN_INFO "ide-tape: %s: skipping frame %d, format_id %u\n", tape->name, tape->first_frame_position, ntohl(aux->format_id));
-		return 0;
-	}
-	if (memcmp(aux->application_sig, tape->application_sig, 4) != 0) {
-		printk(KERN_INFO "ide-tape: %s: skipping frame %d, incorrect application signature\n", tape->name, tape->first_frame_position);
-		return 0;
-	}
-	if (aux->frame_type != OS_FRAME_TYPE_DATA &&
-	    aux->frame_type != OS_FRAME_TYPE_EOD &&
-	    aux->frame_type != OS_FRAME_TYPE_MARKER) {
-		printk(KERN_INFO "ide-tape: %s: skipping frame %d, frame type %x\n", tape->name, tape->first_frame_position, aux->frame_type);
-		return 0;
-	}
-	if (par->partition_num != OS_DATA_PARTITION) {
-		if (!tape->linux_media || tape->linux_media_version != 2) {
-			printk(KERN_INFO "ide-tape: %s: skipping frame %d, partition num %d\n", tape->name, tape->first_frame_position, par->partition_num);
-			return 0;
-		}
-	}
-	if (par->par_desc_ver != OS_PARTITION_VERSION) {
-		printk(KERN_INFO "ide-tape: %s: skipping frame %d, partition version %d\n", tape->name, tape->first_frame_position, par->par_desc_ver);
-		return 0;
-	}
-	if (ntohs(par->wrt_pass_cntr) != tape->wrt_pass_cntr) {
-		printk(KERN_INFO "ide-tape: %s: skipping frame %d, wrt_pass_cntr %d (expected %d)(logical_blk_num %u)\n", tape->name, tape->first_frame_position, ntohs(par->wrt_pass_cntr), tape->wrt_pass_cntr, ntohl(aux->logical_blk_num));
-		return 0;
-	}
-	if (aux->frame_seq_num != aux->logical_blk_num) {
-		printk(KERN_INFO "ide-tape: %s: skipping frame %d, seq != logical\n", tape->name, tape->first_frame_position);
-		return 0;
-	}
-	if (logical_blk_num != -1 && ntohl(aux->logical_blk_num) != logical_blk_num) {
-		if (!quiet)
-			printk(KERN_INFO "ide-tape: %s: skipping frame %d, logical_blk_num %u (expected %d)\n", tape->name, tape->first_frame_position, ntohl(aux->logical_blk_num), logical_blk_num);
-		return 0;
-	}
-	if (aux->frame_type == OS_FRAME_TYPE_MARKER) {
-		rq->errors = IDETAPE_ERROR_FILEMARK;
-		rq->current_nr_sectors = rq->nr_sectors;
-	}
-	return 1;
-}
-
 static void idetape_wait_first_stage (ide_drive_t *drive)
 {
 	idetape_tape_t *tape = drive->driver_data;
@@ -3909,8 +3261,6 @@ static int idetape_add_chrdev_write_requ
 	rq->nr_sectors = rq->current_nr_sectors = blocks;
 
 	idetape_switch_buffers(tape, new_stage);
-	idetape_init_stage(drive, new_stage, OS_FRAME_TYPE_DATA, tape->logical_blk_num);
-	tape->logical_blk_num++;
 	idetape_add_stage_tail(drive, new_stage);
 	tape->pipeline_head++;
 #if USE_IOTRACE
@@ -3924,15 +3274,6 @@ static int idetape_add_chrdev_write_requ
 	 *	writing anymore, wait for the pipeline to be full enough
 	 *	(90%) before starting to service requests, so that we will
 	 *	be able to keep up with the higher speeds of the tape.
-	 *
-	 *	For the OnStream drive, we can query the number of pending
-	 *	frames in the drive's internal buffer. As long as the tape
-	 *	is still writing, it is better to write frames immediately
-	 *	rather than gather them in the pipeline. This will give the
-	 *	tape's firmware the ability to sense the current incoming
-	 *	data rate more accurately, and since the OnStream tape
-	 *	supports variable speeds, it can try to adjust itself to the
-	 *	incoming data rate.
 	 */
 	if (!idetape_pipeline_active(tape)) {
 		if (tape->nr_stages >= tape->max_stages * 9 / 10 ||
@@ -3942,10 +3283,6 @@ static int idetape_add_chrdev_write_requ
 			tape->insert_size = 0;
 			tape->insert_speed = 0;
 			idetape_insert_pipeline_into_queue(drive);
-		} else if (tape->onstream) {
-			idetape_update_stats(drive);
-			if (tape->cur_frames > 5)
-				idetape_insert_pipeline_into_queue(drive);
 		}
 	}
 	if (test_and_clear_bit(IDETAPE_PIPELINE_ERROR, &tape->flags))
@@ -4052,7 +3389,6 @@ static void idetape_restart_speed_contro
 
 	tape->restart_speed_control_req = 0;
 	tape->pipeline_head = 0;
-	tape->buffer_head = tape->tape_head = tape->cur_frames;
 	tape->controlled_last_pipeline_head = tape->uncontrolled_last_pipeline_head = 0;
 	tape->controlled_previous_pipeline_head = tape->uncontrolled_previous_pipeline_head = 0;
 	tape->pipeline_head_speed = tape->controlled_pipeline_head_speed = 5000;
@@ -4084,7 +3420,6 @@ static int idetape_initiate_read (ide_dr
 		if ((tape->merge_stage = __idetape_kmalloc_stage(tape, 0, 0)) == NULL)
 			return -ENOMEM;
 		tape->chrdev_direction = idetape_direction_read;
-		tape->logical_blk_num = 0;
 
 		/*
 		 *	Issue a read 0 command to ensure that DSC handshake
@@ -4126,89 +3461,11 @@ static int idetape_initiate_read (ide_dr
 			tape->insert_size = 0;
 			tape->insert_speed = 0;
 			idetape_insert_pipeline_into_queue(drive);
-		} else if (tape->onstream) {
-			idetape_update_stats(drive);
-			if (tape->cur_frames < tape->max_frames - 5)
-				idetape_insert_pipeline_into_queue(drive);
 		}
 	}
 	return 0;
 }
 
-static int idetape_get_logical_blk (ide_drive_t *drive, int logical_blk_num, int max_stages, int quiet)
-{
-	idetape_tape_t *tape = drive->driver_data;
-	unsigned long flags;
-	int cnt = 0, x, position;
-
-	/*
-	 * Search and wait for the next logical tape block
-	 */
-	while (1) {
-		if (cnt++ > 1000) {   /* AJN: was 100 */
-			printk(KERN_INFO "ide-tape: %s: couldn't find logical block %d, aborting\n", tape->name, logical_blk_num);
-			return 0;
-		}
-		idetape_initiate_read(drive, max_stages);
-		if (tape->first_stage == NULL) {
-			if (tape->onstream) {
-#if ONSTREAM_DEBUG
-				if (tape->debug_level >= 1)
-					printk(KERN_INFO "ide-tape: %s: first_stage == NULL, pipeline error %ld\n", tape->name, (long)test_bit(IDETAPE_PIPELINE_ERROR, &tape->flags));
-#endif
-				clear_bit(IDETAPE_PIPELINE_ERROR, &tape->flags);
-				position = idetape_read_position(drive);
-				printk(KERN_INFO "ide-tape: %s: blank block detected at %d\n", tape->name, position);
-				if (position >= 3000 && position < 3080)
-					/* Why is this check and number ??? MM */
-					position += 32;
-				if (position >= OS_DATA_ENDFRAME1 &&
-				    position < 3000)
-					position = 3000;
-				else
-					/*
-					 * compensate for write errors that
-					 * generally skip 80 frames, expect
-					 * around 20 read errors in a row...
-					 */
-					position += 60;
-				if (position >= OS_DATA_ENDFRAME1 &&
-				    position < 3000)
-					position = 3000;
-				printk(KERN_INFO "ide-tape: %s: positioning tape to block %d\n", tape->name, position);
-
-				/* seems to be needed to correctly position
-				 * at block 3000 MM
-				 */
-				if (position == 3000)
-					idetape_position_tape(drive, 0, 0, 0);
-				idetape_position_tape(drive, position, 0, 0);
-				cnt += 40;
-				continue;
-			} else
-				return 0;
-		}
-		idetape_wait_first_stage(drive);
-		if (idetape_verify_stage(drive, tape->first_stage, logical_blk_num, quiet))
-			break;
-		if (tape->first_stage->rq.errors == IDETAPE_ERROR_EOD)
-			cnt--;
-		if (idetape_verify_stage(drive, tape->first_stage, -1, quiet)) {
-			x = ntohl(tape->first_stage->aux->logical_blk_num);
-			if (x > logical_blk_num) {
-				printk(KERN_ERR "ide-tape: %s: couldn't find logical block %d, aborting (block %d found)\n", tape->name, logical_blk_num, x);
-				return 0;
-			}
-		}
-		spin_lock_irqsave(&tape->spinlock, flags);
-		idetape_remove_stage_head(drive);
-		spin_unlock_irqrestore(&tape->spinlock, flags);
-	}
-	if (tape->onstream)
-		tape->logical_blk_num = ntohl(tape->first_stage->aux->logical_blk_num);
-	return 1;
-}
-
 /*
  *	idetape_add_chrdev_read_request is called from idetape_chrdev_read
  *	to service a character device read request and add read-ahead
@@ -4233,48 +3490,30 @@ static int idetape_add_chrdev_read_reque
 		return 0;
 
 	/*
-	 * Wait for the next logical block to be available at the head
+	 * Wait for the next block to be available at the head
 	 * of the pipeline
 	 */
-	if (!idetape_get_logical_blk(drive, tape->logical_blk_num, tape->max_stages, 0)) {
-		if (tape->onstream) {
-			set_bit(IDETAPE_READ_ERROR, &tape->flags);
-			return 0;
-		}
+	idetape_initiate_read(drive, tape->max_stages);
+	if (tape->first_stage == NULL) {
 		if (test_bit(IDETAPE_PIPELINE_ERROR, &tape->flags))
-		 	return 0;
+			return 0;
 		return idetape_queue_rw_tail(drive, REQ_IDETAPE_READ, blocks, tape->merge_stage->bh);
 	}
+	idetape_wait_first_stage(drive);
 	rq_ptr = &tape->first_stage->rq;
 	bytes_read = tape->tape_block_size * (rq_ptr->nr_sectors - rq_ptr->current_nr_sectors);
 	rq_ptr->nr_sectors = rq_ptr->current_nr_sectors = 0;
 
 
-	if (tape->onstream && !tape->raw &&
-	    tape->first_stage->aux->frame_type == OS_FRAME_TYPE_EOD) {
-#if ONSTREAM_DEBUG
-		if (tape->debug_level >= 2)
-			printk(KERN_INFO "ide-tape: %s: EOD reached\n",
-				tape->name);
-#endif
-		return 0;
-	}
 	if (rq_ptr->errors == IDETAPE_ERROR_EOD)
 		return 0;
 	else {
 		idetape_switch_buffers(tape, tape->first_stage);
-		if (rq_ptr->errors == IDETAPE_ERROR_GENERAL) {
-#if ONSTREAM_DEBUG
-			if (tape->debug_level >= 1)
-				printk(KERN_INFO "ide-tape: error detected, bytes_read %d\n", bytes_read);
-#endif
-		}
 		if (rq_ptr->errors == IDETAPE_ERROR_FILEMARK)
 			set_bit(IDETAPE_FILEMARK, &tape->flags);
 		spin_lock_irqsave(&tape->spinlock, flags);
 		idetape_remove_stage_head(drive);
 		spin_unlock_irqrestore(&tape->spinlock, flags);
-		tape->logical_blk_num++;
 		tape->pipeline_head++;
 #if USE_IOTRACE
 		IO_trace(IO_IDETAPE_FIFO, tape->pipeline_head, tape->buffer_head, tape->tape_head, tape->minor);
@@ -4342,8 +3581,8 @@ static int idetape_rewind_tape (ide_driv
 {
 	int retval;
 	idetape_pc_t pc;
-	idetape_tape_t *tape = drive->driver_data;
 #if IDETAPE_DEBUG_LOG
+	idetape_tape_t *tape = drive->driver_data;
 	if (tape->debug_level >= 2)
 		printk(KERN_INFO "ide-tape: Reached idetape_rewind_tape\n");
 #endif /* IDETAPE_DEBUG_LOG */	
@@ -4357,7 +3596,6 @@ static int idetape_rewind_tape (ide_driv
 	retval = idetape_queue_pc_tail(drive, &pc);
 	if (retval)
 		return retval;
-	tape->logical_blk_num = 0;
 	return 0;
 }
 
@@ -4406,206 +3644,26 @@ static void idetape_pre_reset (ide_drive
 		set_bit(IDETAPE_IGNORE_DSC, &tape->flags);
 }
 
-static int idetape_onstream_space_over_filemarks_backward (ide_drive_t *drive,short mt_op,int mt_count)
+/*
+ *	idetape_space_over_filemarks is now a bit more complicated than just
+ *	passing the command to the tape since we may have crossed some
+ *	filemarks during our pipelined read-ahead mode.
+ *
+ *	As a minor side effect, the pipeline enables us to support MTFSFM when
+ *	the filemark is in our internal pipeline even if the tape doesn't
+ *	support spacing over filemarks in the reverse direction.
+ */
+static int idetape_space_over_filemarks (ide_drive_t *drive,short mt_op,int mt_count)
 {
 	idetape_tape_t *tape = drive->driver_data;
-	int cnt = 0;
-	int last_mark_addr;
+	idetape_pc_t pc;
 	unsigned long flags;
+	int retval,count=0;
 
-	if (!idetape_get_logical_blk(drive, -1, 10, 0)) {
-		printk(KERN_INFO "ide-tape: %s: couldn't get logical blk num in space_filemarks_bwd\n", tape->name);
-		return -EIO;
-	}
-	while (cnt != mt_count) {
-		last_mark_addr = ntohl(tape->first_stage->aux->last_mark_addr);
-		if (last_mark_addr == -1)
-			return -EIO;
-#if ONSTREAM_DEBUG
-		if (tape->debug_level >= 2)
-			printk(KERN_INFO "ide-tape: positioning to last mark at %d\n", last_mark_addr);
-#endif
-		idetape_position_tape(drive, last_mark_addr, 0, 0);
-		cnt++;
-		if (!idetape_get_logical_blk(drive, -1, 10, 0)) {
-			printk(KERN_INFO "ide-tape: %s: couldn't get logical blk num in space_filemarks\n", tape->name);
-			return -EIO;
-		}
-		if (tape->first_stage->aux->frame_type != OS_FRAME_TYPE_MARKER) {
-			printk(KERN_INFO "ide-tape: %s: expected to find marker at block %d, not found\n", tape->name, last_mark_addr);
-			return -EIO;
-		}
-	}
-	if (mt_op == MTBSFM) {
-		spin_lock_irqsave(&tape->spinlock, flags);
-		idetape_remove_stage_head(drive);
-		tape->logical_blk_num++;
-		spin_unlock_irqrestore(&tape->spinlock, flags);
-	}
-	return 0;
-}
-
-/*
- * ADRL 1.1 compatible "slow" space filemarks fwd version
- *
- * Just scans for the filemark sequentially.
- */
-static int idetape_onstream_space_over_filemarks_forward_slow (ide_drive_t *drive,short mt_op,int mt_count)
-{
-	idetape_tape_t *tape = drive->driver_data;
-	int cnt = 0;
-	unsigned long flags;
-
-	if (!idetape_get_logical_blk(drive, -1, 10, 0)) {
-		printk(KERN_INFO "ide-tape: %s: couldn't get logical blk num in space_filemarks_fwd\n", tape->name);
-		return -EIO;
-	}
-	while (1) {
-		if (!idetape_get_logical_blk(drive, -1, 10, 0)) {
-			printk(KERN_INFO "ide-tape: %s: couldn't get logical blk num in space_filemarks\n", tape->name);
-			return -EIO;
-		}
-		if (tape->first_stage->aux->frame_type == OS_FRAME_TYPE_MARKER)
-			cnt++;
-		if (tape->first_stage->aux->frame_type == OS_FRAME_TYPE_EOD) {
-#if ONSTREAM_DEBUG
-			if (tape->debug_level >= 2)
-				printk(KERN_INFO "ide-tape: %s: space_fwd: EOD reached\n", tape->name);
-#endif
-			return -EIO;
-		}
-		if (cnt == mt_count)
-			break;
-		spin_lock_irqsave(&tape->spinlock, flags);
-		idetape_remove_stage_head(drive);
-		spin_unlock_irqrestore(&tape->spinlock, flags);
-	}
-	if (mt_op == MTFSF) {
-		spin_lock_irqsave(&tape->spinlock, flags);
-		idetape_remove_stage_head(drive);
-		tape->logical_blk_num++;
-		spin_unlock_irqrestore(&tape->spinlock, flags);
-	}
-	return 0;
-}
-
-
-/*
- * Fast linux specific version of OnStream FSF
- */
-static int idetape_onstream_space_over_filemarks_forward_fast (ide_drive_t *drive,short mt_op,int mt_count)
-{
-	idetape_tape_t *tape = drive->driver_data;
-	int cnt = 0, next_mark_addr;
-	unsigned long flags;
-
-	if (!idetape_get_logical_blk(drive, -1, 10, 0)) {
-		printk(KERN_INFO "ide-tape: %s: couldn't get logical blk num in space_filemarks_fwd\n", tape->name);
-		return -EIO;
-	}
-
-	/*
-	 * Find nearest (usually previous) marker
-	 */
-	while (1) {
-		if (tape->first_stage->aux->frame_type == OS_FRAME_TYPE_MARKER)
-			break;
-		if (tape->first_stage->aux->frame_type == OS_FRAME_TYPE_EOD) {
-#if ONSTREAM_DEBUG
-			if (tape->debug_level >= 2)
-				printk(KERN_INFO "ide-tape: %s: space_fwd: EOD reached\n", tape->name);
-#endif
-			return -EIO;
-		}
-		if (ntohl(tape->first_stage->aux->filemark_cnt) == 0) {
-			if (tape->first_mark_addr == -1) {
-				printk(KERN_INFO "ide-tape: %s: reverting to slow filemark space\n", tape->name);
-				return idetape_onstream_space_over_filemarks_forward_slow(drive, mt_op, mt_count);
-			}
-			idetape_position_tape(drive, tape->first_mark_addr, 0, 0);
-			if (!idetape_get_logical_blk(drive, -1, 10, 0)) {
-				printk(KERN_INFO "ide-tape: %s: couldn't get logical blk num in space_filemarks_fwd_fast\n", tape->name);
-				return -EIO;
-			}
-			if (tape->first_stage->aux->frame_type != OS_FRAME_TYPE_MARKER) {
-				printk(KERN_INFO "ide-tape: %s: expected to find filemark at %d\n", tape->name, tape->first_mark_addr);
-				return -EIO;
-			}
-		} else {
-			if (idetape_onstream_space_over_filemarks_backward(drive, MTBSF, 1) < 0)
-				return -EIO;
-			mt_count++;
-		}
-	}
-	cnt++;
-	while (cnt != mt_count) {
-		next_mark_addr = ntohl(tape->first_stage->aux->next_mark_addr);
-		if (!next_mark_addr || next_mark_addr > tape->eod_frame_addr) {
-			printk(KERN_INFO "ide-tape: %s: reverting to slow filemark space\n", tape->name);
-			return idetape_onstream_space_over_filemarks_forward_slow(drive, mt_op, mt_count - cnt);
-#if ONSTREAM_DEBUG
-		} else if (tape->debug_level >= 2) {
-		     printk(KERN_INFO "ide-tape: positioning to next mark at %d\n", next_mark_addr);
-#endif
-		}
-		idetape_position_tape(drive, next_mark_addr, 0, 0);
-		cnt++;
-		if (!idetape_get_logical_blk(drive, -1, 10, 0)) {
-			printk(KERN_INFO "ide-tape: %s: couldn't get logical blk num in space_filemarks\n", tape->name);
-			return -EIO;
-		}
-		if (tape->first_stage->aux->frame_type != OS_FRAME_TYPE_MARKER) {
-			printk(KERN_INFO "ide-tape: %s: expected to find marker at block %d, not found\n", tape->name, next_mark_addr);
-			return -EIO;
-		}
-	}
-	if (mt_op == MTFSF) {
-		spin_lock_irqsave(&tape->spinlock, flags);
-		idetape_remove_stage_head(drive);
-		tape->logical_blk_num++;
-		spin_unlock_irqrestore(&tape->spinlock, flags);
-	}
-	return 0;
-}
-
-/*
- *	idetape_space_over_filemarks is now a bit more complicated than just
- *	passing the command to the tape since we may have crossed some
- *	filemarks during our pipelined read-ahead mode.
- *
- *	As a minor side effect, the pipeline enables us to support MTFSFM when
- *	the filemark is in our internal pipeline even if the tape doesn't
- *	support spacing over filemarks in the reverse direction.
- */
-static int idetape_space_over_filemarks (ide_drive_t *drive,short mt_op,int mt_count)
-{
-	idetape_tape_t *tape = drive->driver_data;
-	idetape_pc_t pc;
-	unsigned long flags;
-	int retval,count=0;
-	int speed_control;
-
-	if (tape->onstream) {
-		if (tape->raw)
-			return -EIO;
-		speed_control = tape->speed_control;
-		tape->speed_control = 0;
-		if (mt_op == MTFSF || mt_op == MTFSFM) {
-			if (tape->linux_media)
-				retval = idetape_onstream_space_over_filemarks_forward_fast(drive, mt_op, mt_count);
-			else
-				retval = idetape_onstream_space_over_filemarks_forward_slow(drive, mt_op, mt_count);
-		} else
-			retval = idetape_onstream_space_over_filemarks_backward(drive, mt_op, mt_count);
-		tape->speed_control = speed_control;
-		tape->restart_speed_control_req = 1;
-		return retval;
-	}
- 
-	if (mt_count == 0)
-		return 0;
-	if (MTBSF == mt_op || MTBSFM == mt_op) {
-		if (!tape->capabilities.sprev)
+	if (mt_count == 0)
+		return 0;
+	if (MTBSF == mt_op || MTBSFM == mt_op) {
+		if (!tape->capabilities.sprev)
 			return -EIO;
 		mt_count = - mt_count;
 	}
@@ -4700,10 +3758,6 @@ static ssize_t idetape_chrdev_read (stru
 		/* "A request was outside the capabilities of the device." */
 		return -ENXIO;
 	}
-	if (tape->onstream && (count != tape->tape_block_size)) {
-		printk(KERN_ERR "ide-tape: %s: use %d bytes as block size (%Zd used)\n", tape->name, tape->tape_block_size, count);
-		return -EINVAL;
-	}
 #if IDETAPE_DEBUG_LOG
 	if (tape->debug_level >= 3)
 		printk(KERN_INFO "ide-tape: Reached idetape_chrdev_read, count %Zd\n", count);
@@ -4753,179 +3807,15 @@ finish:
 		idetape_space_over_filemarks(drive, MTFSF, 1);
 		return 0;
 	}
-	if (tape->onstream && !actually_read &&
-	    test_and_clear_bit(IDETAPE_READ_ERROR, &tape->flags)) {
-		printk(KERN_ERR "ide-tape: %s: unrecovered read error on "
-			"logical block number %d, skipping\n",
-			tape->name, tape->logical_blk_num);
-		tape->logical_blk_num++;
-		return -EIO;
-	}
 	return actually_read;
 }
 
-static void idetape_update_last_marker (ide_drive_t *drive, int last_mark_addr, int next_mark_addr)
-{
-	idetape_tape_t *tape = drive->driver_data;
-	idetape_stage_t *stage;
-	os_aux_t *aux;
-	int position;
-
-	if (!tape->onstream || tape->raw)
-		return;
-	if (last_mark_addr == -1)
-		return;
-	stage = __idetape_kmalloc_stage(tape, 0, 0);
-	if (stage == NULL)
-		return;
-	idetape_flush_tape_buffers(drive);
-	position = idetape_read_position(drive);
-#if ONSTREAM_DEBUG
-	if (tape->debug_level >= 2)
-		printk(KERN_INFO "ide-tape: current position (2) %d, "
-			"lblk %d\n", position, tape->logical_blk_num);
-	if (tape->debug_level >= 2)
-		printk(KERN_INFO "ide-tape: current position (2) "
-			"tape block %d\n", tape->last_frame_position);
-#endif
-	idetape_position_tape(drive, last_mark_addr, 0, 0);
-	if (!idetape_queue_rw_tail(drive, REQ_IDETAPE_READ, 1, stage->bh)) {
-		printk(KERN_INFO "ide-tape: %s: couldn't read last marker\n",
-			tape->name);
-		__idetape_kfree_stage(stage);
-		idetape_position_tape(drive, position, 0, 0);
-		return;
-	}
-	aux = stage->aux;
-	if (aux->frame_type != OS_FRAME_TYPE_MARKER) {
-		printk(KERN_INFO "ide-tape: %s: expected to find marker "
-			"at addr %d\n", tape->name, last_mark_addr);
-		__idetape_kfree_stage(stage);
-		idetape_position_tape(drive, position, 0, 0);
-		return;
-	}
-#if ONSTREAM_DEBUG
-	if (tape->debug_level >= 2)
-		printk(KERN_INFO "ide-tape: writing back marker\n");
-#endif
-	aux->next_mark_addr = htonl(next_mark_addr);
-	idetape_position_tape(drive, last_mark_addr, 0, 0);
-	if (!idetape_queue_rw_tail(drive, REQ_IDETAPE_WRITE, 1, stage->bh)) {
-		printk(KERN_INFO "ide-tape: %s: couldn't write back marker "
-			"frame at %d\n", tape->name, last_mark_addr);
-		__idetape_kfree_stage(stage);
-		idetape_position_tape(drive, position, 0, 0);
-		return;
-	}
-	__idetape_kfree_stage(stage);
-	idetape_flush_tape_buffers(drive);
-	idetape_position_tape(drive, position, 0, 0);
-	return;
-}
-
-static void idetape_write_filler (ide_drive_t *drive, int block, int cnt)
-{
-	idetape_tape_t *tape = drive->driver_data;
-	idetape_stage_t *stage;
-	int rc;
-
-	if (!tape->onstream || tape->raw)
-		return;
-	stage = __idetape_kmalloc_stage(tape, 1, 1);
-	if (stage == NULL)
-		return;
-	idetape_init_stage(drive, stage, OS_FRAME_TYPE_FILL, 0);
-	idetape_wait_ready(drive, 60 * 5 * HZ);
-	rc = idetape_position_tape(drive, block, 0, 0);
-#if ONSTREAM_DEBUG
-	printk(KERN_INFO "write_filler: positioning failed it returned %d\n", rc);
-#endif
-	if (rc != 0)
-		/* don't write fillers if we cannot position the tape. */
-		return;
-
-	strcpy(stage->bh->b_data, "Filler");
-	while (cnt--) {
-		if (!idetape_queue_rw_tail(drive, REQ_IDETAPE_WRITE, 1, stage->bh)) {
-			printk(KERN_INFO "ide-tape: %s: write_filler: "
-				"couldn't write header frame\n", tape->name);
-			__idetape_kfree_stage(stage);
-			return;
-		}
-	}
-	__idetape_kfree_stage(stage);
-}
-
-static void __idetape_write_header (ide_drive_t *drive, int block, int cnt)
-{
-	idetape_tape_t *tape = drive->driver_data;
-	idetape_stage_t *stage;
-	os_header_t header;
-
-	stage = __idetape_kmalloc_stage(tape, 1, 1);
-	if (stage == NULL)
-		return;
-	idetape_init_stage(drive, stage, OS_FRAME_TYPE_HEADER, tape->logical_blk_num);
-	idetape_wait_ready(drive, 60 * 5 * HZ);
-	idetape_position_tape(drive, block, 0, 0);
-	memset(&header, 0, sizeof(header));
-	strcpy(header.ident_str, "ADR_SEQ");
-	header.major_rev = 1;
-	header.minor_rev = OS_ADR_MINREV;
-	header.par_num = 1;
-	header.partition.partition_num = OS_DATA_PARTITION;
-	header.partition.par_desc_ver = OS_PARTITION_VERSION;
-	header.partition.first_frame_addr = htonl(OS_DATA_STARTFRAME1);
-	header.partition.last_frame_addr = htonl(tape->capacity);
-	header.partition.wrt_pass_cntr = htons(tape->wrt_pass_cntr);
-	header.partition.eod_frame_addr = htonl(tape->eod_frame_addr);
-	memcpy(stage->bh->b_data, &header, sizeof(header));
-	while (cnt--) {
-		if (!idetape_queue_rw_tail(drive, REQ_IDETAPE_WRITE, 1, stage->bh)) {
-			printk(KERN_INFO "ide-tape: %s: couldn't write "
-				"header frame\n", tape->name);
-			__idetape_kfree_stage(stage);
-			return;
-		}
-	}
-	__idetape_kfree_stage(stage);
-	idetape_flush_tape_buffers(drive);
-}
-
-static void idetape_write_header (ide_drive_t *drive, int locate_eod)
-{
-	idetape_tape_t *tape = drive->driver_data;
-
-#if ONSTREAM_DEBUG
-	if (tape->debug_level >= 2)
-		printk(KERN_INFO "ide-tape: %s: writing tape header\n",
-			tape->name);
-#endif
-	if (!tape->onstream || tape->raw)
-		return;
-	tape->update_frame_cntr++;
-	__idetape_write_header(drive, 5, 5);
-	__idetape_write_header(drive, 0xbae, 5); /* 2990 */
-	if (locate_eod) {
-#if ONSTREAM_DEBUG
-		if (tape->debug_level >= 2)
-			printk(KERN_INFO "ide-tape: %s: locating back to eod "
-				"frame addr %d\n", tape->name,
-				tape->eod_frame_addr);
-#endif
-		idetape_position_tape(drive, tape->eod_frame_addr, 0, 0);
-	}
-}
-
 static ssize_t idetape_chrdev_write (struct file *file, const char *buf,
 				     size_t count, loff_t *ppos)
 {
-	struct inode *inode = file->f_dentry->d_inode;
 	ide_drive_t *drive = file->private_data;
 	idetape_tape_t *tape = drive->driver_data;
-	unsigned int minor = iminor(inode);
 	ssize_t retval, actually_written = 0;
-	int position;
 
 	if (ppos != &file->f_pos) {
 		/* "A request was outside the capabilities of the device." */
@@ -4942,28 +3832,6 @@ static ssize_t idetape_chrdev_write (str
 			"count %Zd\n", count);
 #endif /* IDETAPE_DEBUG_LOG */
 
-	if (tape->onstream) {
-		if (count != tape->tape_block_size) {
-			printk(KERN_ERR "ide-tape: %s: chrdev_write: use %d "
-				"bytes as block size (%Zd used)\n",
-				tape->name, tape->tape_block_size, count);
-			return -EINVAL;
-		}
-		/*
-		 * Check if we reach the end of the tape. Just assume the whole
-		 * pipeline is filled with write requests!
-		 */
-		if (tape->first_frame_position + tape->nr_stages >= tape->capacity - OS_EW)  {
-#if ONSTREAM_DEBUG
-			printk(KERN_INFO, "chrdev_write: Write truncated at "
-				"EOM early warning");
-#endif
-			if (tape->chrdev_direction == idetape_direction_write)
-				idetape_write_release(drive, minor);
-			return -ENOSPC;
-		}
-	}
-
 	/* Initialize write operation */
 	if (tape->chrdev_direction != idetape_direction_write) {
 		if (tape->chrdev_direction == idetape_direction_read)
@@ -4980,39 +3848,6 @@ static ssize_t idetape_chrdev_write (str
 		tape->chrdev_direction = idetape_direction_write;
 		idetape_init_merge_stage(tape);
 
-		if (tape->onstream) {
-			position = idetape_read_position(drive);
-			if (position <= OS_DATA_STARTFRAME1) {
-				tape->logical_blk_num = 0;
-				tape->wrt_pass_cntr++;
-#if ONSTREAM_DEBUG
-				if (tape->debug_level >= 2)
-					printk(KERN_INFO "ide-tape: %s: logical block num 0, setting eod to %d\n", tape->name, OS_DATA_STARTFRAME1);
-				if (tape->debug_level >= 2)
-					printk(KERN_INFO "ide-tape: %s: allocating new write pass counter %d\n", tape->name, tape->wrt_pass_cntr);
-#endif
-				tape->filemark_cnt = 0;
-				tape->eod_frame_addr = OS_DATA_STARTFRAME1;
-				tape->first_mark_addr = tape->last_mark_addr = -1;
-				idetape_write_header(drive, 1);
-			}
-#if ONSTREAM_DEBUG
-			if (tape->debug_level >= 2)
-				printk(KERN_INFO "ide-tape: %s: positioning "
-					"tape to eod at %d\n",
-					tape->name, tape->eod_frame_addr);
-#endif
-			position = idetape_read_position(drive);
-			if (position != tape->eod_frame_addr)
-				idetape_position_tape(drive, tape->eod_frame_addr, 0, 0);
-#if ONSTREAM_DEBUG
-			if (tape->debug_level >= 2)
-				printk(KERN_INFO "ide-tape: %s: "
-					"first_frame_position %d\n",
-					tape->name, tape->first_frame_position);
-#endif
-		}
-
 		/*
 		 *	Issue a write 0 command to ensure that DSC handshake
 		 *	is switched from completion mode to buffer available
@@ -5029,11 +3864,6 @@ static ssize_t idetape_chrdev_write (str
 				return retval;
 			}
 		}
-#if ONSTREAM_DEBUG
-		if (tape->debug_level >= 2)
-			printk("ide-tape: first_frame_position %d\n",
-				tape->first_frame_position);
-#endif
 	}
 	if (count == 0)
 		return (0);
@@ -5078,88 +3908,14 @@ static ssize_t idetape_chrdev_write (str
 
 static int idetape_write_filemark (ide_drive_t *drive)
 {
-	idetape_tape_t *tape = drive->driver_data;
-	int last_mark_addr;
 	idetape_pc_t pc;
 
-	if (!tape->onstream) {
-		/* Write a filemark */
-		idetape_create_write_filemark_cmd(drive, &pc, 1);
-		if (idetape_queue_pc_tail(drive, &pc)) {
-			printk(KERN_ERR "ide-tape: Couldn't write a filemark\n");
-			return -EIO;
-		}
-	} else if (!tape->raw) {
-		last_mark_addr = idetape_read_position(drive);
-		tape->merge_stage = __idetape_kmalloc_stage(tape, 1, 0);
-		if (tape->merge_stage != NULL) {
-			idetape_init_stage(drive, tape->merge_stage, OS_FRAME_TYPE_MARKER, tape->logical_blk_num);
-			idetape_pad_zeros(drive, tape->stage_size);
-			tape->logical_blk_num++;
-			__idetape_kfree_stage(tape->merge_stage);
-			tape->merge_stage = NULL;
-		}
-		if (tape->filemark_cnt)
-			idetape_update_last_marker(drive, tape->last_mark_addr, last_mark_addr);
-		tape->last_mark_addr = last_mark_addr;
-		if (tape->filemark_cnt++ == 0)
-			tape->first_mark_addr = last_mark_addr;
-	}
-	return 0;
-}
-
-static void idetape_write_eod (ide_drive_t *drive)
-{
-	idetape_tape_t *tape = drive->driver_data;
-
-	if (!tape->onstream || tape->raw)
-		return;
-	tape->merge_stage = __idetape_kmalloc_stage(tape, 1, 0);
-	if (tape->merge_stage != NULL) {
-		tape->eod_frame_addr = idetape_read_position(drive);
-		idetape_init_stage(drive, tape->merge_stage, OS_FRAME_TYPE_EOD, tape->logical_blk_num);
-		idetape_pad_zeros(drive, tape->stage_size);
-		__idetape_kfree_stage(tape->merge_stage);
-		tape->merge_stage = NULL;
-	}
-	return;
-}
-
-int idetape_seek_logical_blk (ide_drive_t *drive, int logical_blk_num)
-{
-	idetape_tape_t *tape = drive->driver_data;
-	int estimated_address = logical_blk_num + 20;
-	int retries = 0;
-	int speed_control;
-
-	speed_control = tape->speed_control;
-	tape->speed_control = 0;
-	if (logical_blk_num < 0)
-		logical_blk_num = 0;
-	if (idetape_get_logical_blk(drive, logical_blk_num, 10, 1))
-		goto ok;
-	while (++retries < 10) {
-		idetape_discard_read_pipeline(drive, 0);
-		idetape_position_tape(drive, estimated_address, 0, 0);
-		if (idetape_get_logical_blk(drive, logical_blk_num, 10, 1))
-			goto ok;
-		if (!idetape_get_logical_blk(drive, -1, 10, 1))
-			goto error;
-		if (tape->logical_blk_num < logical_blk_num)
-			estimated_address += logical_blk_num - tape->logical_blk_num;
-		else
-			break;
+	/* Write a filemark */
+	idetape_create_write_filemark_cmd(drive, &pc, 1);
+	if (idetape_queue_pc_tail(drive, &pc)) {
+		printk(KERN_ERR "ide-tape: Couldn't write a filemark\n");
+		return -EIO;
 	}
-error:
-	tape->speed_control = speed_control;
-	tape->restart_speed_control_req = 1;
-	printk(KERN_INFO "ide-tape: %s: couldn't seek to logical block %d "
-		"(at %d), %d retries\n", tape->name, logical_blk_num,
-		tape->logical_blk_num, retries);
-	return -EIO;
-ok:
-	tape->speed_control = speed_control;
-	tape->restart_speed_control_req = 1;
 	return 0;
 }
 
@@ -5266,8 +4022,6 @@ static int idetape_mtioctop (ide_drive_t
 			idetape_discard_read_pipeline(drive, 0);
 			if (idetape_rewind_tape(drive))
 				return -EIO;
-			if (tape->onstream && !tape->raw)
-				return idetape_position_tape(drive, OS_DATA_STARTFRAME1, 0, 0);
 			return 0;
 		case MTLOAD:
 			idetape_discard_read_pipeline(drive, 0);
@@ -5298,50 +4052,13 @@ static int idetape_mtioctop (ide_drive_t
 			idetape_create_load_unload_cmd(drive, &pc,IDETAPE_LU_RETENSION_MASK | IDETAPE_LU_LOAD_MASK);
 			return (idetape_queue_pc_tail(drive, &pc));
 		case MTEOM:
-			if (tape->onstream) {
-#if ONSTREAM_DEBUG
-				if (tape->debug_level >= 2)
-					printk(KERN_INFO "ide-tape: %s: positioning tape to eod at %d\n", tape->name, tape->eod_frame_addr);
-#endif
-				idetape_position_tape(drive, tape->eod_frame_addr, 0, 0);
-				if (!idetape_get_logical_blk(drive, -1, 10, 0))
-					return -EIO;
-				if (tape->first_stage->aux->frame_type != OS_FRAME_TYPE_EOD)
-					return -EIO;
-				return 0;
-			}
 			idetape_create_space_cmd(&pc, 0, IDETAPE_SPACE_TO_EOD);
 			return (idetape_queue_pc_tail(drive, &pc));
 		case MTERASE:
-			if (tape->onstream) {
-				tape->eod_frame_addr = OS_DATA_STARTFRAME1;
-				tape->logical_blk_num = 0;
-				tape->first_mark_addr = tape->last_mark_addr = -1;
-				idetape_position_tape(drive, tape->eod_frame_addr, 0, 0);
-				idetape_write_eod(drive);
-				idetape_flush_tape_buffers(drive);
-				idetape_write_header(drive, 0);
-				/*
-				 * write filler frames to the unused frames...
-				 * REMOVE WHEN going to LIN4 application type...
-				 */
-				idetape_write_filler(drive, OS_DATA_STARTFRAME1 - 10, 10);
-				idetape_write_filler(drive, OS_DATA_ENDFRAME1, 10);
-				idetape_flush_tape_buffers(drive);
-				(void) idetape_rewind_tape(drive);
-				return 0;
-			}
 			(void) idetape_rewind_tape(drive);
 			idetape_create_erase_cmd(&pc);
 			return (idetape_queue_pc_tail(drive, &pc));
 		case MTSETBLK:
-			if (tape->onstream) {
-				if (mt_count != tape->tape_block_size) {
-					printk(KERN_INFO "ide-tape: %s: MTSETBLK %d -- only %d bytes block size supported\n", tape->name, mt_count, tape->tape_block_size);
-					return -EINVAL;
-				}
-				return 0;
-			}
 			if (mt_count) {
 				if (mt_count < tape->tape_block_size || mt_count % tape->tape_block_size)
 					return -EIO;
@@ -5351,28 +4068,13 @@ static int idetape_mtioctop (ide_drive_t
 				set_bit(IDETAPE_DETECT_BS, &tape->flags);
 			return 0;
 		case MTSEEK:
-			if (!tape->onstream || tape->raw) {
-				idetape_discard_read_pipeline(drive, 0);
-				return idetape_position_tape(drive, mt_count * tape->user_bs_factor, tape->partition, 0);
-			}
-			return idetape_seek_logical_blk(drive, mt_count);
+			idetape_discard_read_pipeline(drive, 0);
+			return idetape_position_tape(drive, mt_count * tape->user_bs_factor, tape->partition, 0);
 		case MTSETPART:
 			idetape_discard_read_pipeline(drive, 0);
-			if (tape->onstream)
-				return -EIO;
 			return (idetape_position_tape(drive, 0, mt_count, 0));
 		case MTFSR:
 		case MTBSR:
-			if (tape->onstream) {
-				if (!idetape_get_logical_blk(drive, -1, 10, 0))
-					return -EIO;
-				if (mt_op == MTFSR)
-					return idetape_seek_logical_blk(drive, tape->logical_blk_num + mt_count);
-				else {
-					idetape_discard_read_pipeline(drive, 0);
-					return idetape_seek_logical_blk(drive, tape->logical_blk_num - mt_count);
-				}
-			}
 		case MTLOCK:
 			if (!idetape_create_prevent_cmd(drive, &pc, 1))
 				return 0;
@@ -5450,34 +4152,16 @@ static int idetape_chrdev_ioctl (struct 
 		case MTIOCGET:
 			memset(&mtget, 0, sizeof (struct mtget));
 			mtget.mt_type = MT_ISSCSI2;
-			if (!tape->onstream || tape->raw)
-				mtget.mt_blkno = position / tape->user_bs_factor - block_offset;
-			else {
-				if (!idetape_get_logical_blk(drive, -1, 10, 0))
-					mtget.mt_blkno = -1;
-				else
-					mtget.mt_blkno = tape->logical_blk_num;
-			}
+			mtget.mt_blkno = position / tape->user_bs_factor - block_offset;
 			mtget.mt_dsreg = ((tape->tape_block_size * tape->user_bs_factor) << MT_ST_BLKSIZE_SHIFT) & MT_ST_BLKSIZE_MASK;
-			if (tape->onstream) {
-				mtget.mt_gstat |= GMT_ONLINE(0xffffffff);
-				if (tape->first_stage && tape->first_stage->aux->frame_type == OS_FRAME_TYPE_EOD)
-					mtget.mt_gstat |= GMT_EOD(0xffffffff);
-				if (position <= OS_DATA_STARTFRAME1)
-					mtget.mt_gstat |= GMT_BOT(0xffffffff);
-			} else if (tape->drv_write_prot) {
+			if (tape->drv_write_prot) {
 				mtget.mt_gstat |= GMT_WR_PROT(0xffffffff);
 			}
 			if (copy_to_user((char *) arg,(char *) &mtget, sizeof(struct mtget)))
 				return -EFAULT;
 			return 0;
 		case MTIOCPOS:
-			if (tape->onstream && !tape->raw) {
-				if (!idetape_get_logical_blk(drive, -1, 10, 0))
-					return -EIO;
-				mtpos.mt_blkno = tape->logical_blk_num;
-			} else
-				mtpos.mt_blkno = position / tape->user_bs_factor - block_offset;
+			mtpos.mt_blkno = position / tape->user_bs_factor - block_offset;
 			if (copy_to_user((char *) arg,(char *) &mtpos, sizeof(struct mtpos)))
 				return -EFAULT;
 			return 0;
@@ -5488,106 +4172,6 @@ static int idetape_chrdev_ioctl (struct 
 	}
 }
 
-static int __idetape_analyze_headers (ide_drive_t *drive, int block)
-{
-	idetape_tape_t *tape = drive->driver_data;
-	idetape_stage_t *stage;
-	os_header_t *header;
-	os_aux_t *aux;
-
-	if (!tape->onstream || tape->raw) {
-		tape->header_ok = tape->linux_media = 1;
-		return 1;
-	}
-	tape->header_ok = tape->linux_media = 0;
-	tape->update_frame_cntr = 0;
-	tape->wrt_pass_cntr = 0;
-	tape->eod_frame_addr = OS_DATA_STARTFRAME1;
-	tape->first_mark_addr = tape->last_mark_addr = -1;
-	stage = __idetape_kmalloc_stage(tape, 0, 0);
-	if (stage == NULL)
-		return 0;
-#if ONSTREAM_DEBUG
-	if (tape->debug_level >= 2)
-		printk(KERN_INFO "ide-tape: %s: reading header\n", tape->name);
-#endif
-	idetape_position_tape(drive, block, 0, 0);
-	if (!idetape_queue_rw_tail(drive, REQ_IDETAPE_READ, 1, stage->bh)) {
-		printk(KERN_INFO "ide-tape: %s: couldn't read header frame\n",
-			tape->name);
-		__idetape_kfree_stage(stage);
-		return 0;
-	}
-	header = (os_header_t *) stage->bh->b_data;
-	aux = stage->aux;
-	if (strncmp(header->ident_str, "ADR_SEQ", 7) != 0) {
-		printk(KERN_INFO "ide-tape: %s: invalid header identification string\n", tape->name);
-		__idetape_kfree_stage(stage);
-		return 0;
-	}
-	if (header->major_rev != 1 || (header->minor_rev > OS_ADR_MINREV))
-		printk(KERN_INFO "ide-tape: warning: revision %d.%d "
-			"detected (up to 1.%d supported)\n",
-			header->major_rev, header->minor_rev, OS_ADR_MINREV);
-	if (header->par_num != 1)
-		printk(KERN_INFO "ide-tape: warning: %d partitions defined, only one supported\n", header->par_num);
-	tape->wrt_pass_cntr = ntohs(header->partition.wrt_pass_cntr);
-	tape->eod_frame_addr = ntohl(header->partition.eod_frame_addr);
-	tape->filemark_cnt = ntohl(aux->filemark_cnt);
-	tape->first_mark_addr = ntohl(aux->next_mark_addr);
-	tape->last_mark_addr = ntohl(aux->last_mark_addr);
-	tape->update_frame_cntr = ntohl(aux->update_frame_cntr);
-	memcpy(tape->application_sig, aux->application_sig, 4);
-	tape->application_sig[4] = 0;
-	if (memcmp(tape->application_sig, "LIN", 3) == 0) {
-		tape->linux_media = 1;
-		tape->linux_media_version = tape->application_sig[3] - '0';
-		if (tape->linux_media_version != 3)
-			printk(KERN_INFO "ide-tape: %s: Linux media version "
-				"%d detected (current 3)\n",
-				 tape->name, tape->linux_media_version);
-	} else {
-		printk(KERN_INFO "ide-tape: %s: non Linux media detected "
-			"(%s)\n", tape->name, tape->application_sig);
-		tape->linux_media = 0;
-	}
-#if ONSTREAM_DEBUG
-	if (tape->debug_level >= 2)
-		printk(KERN_INFO "ide-tape: %s: detected write pass counter "
-			"%d, eod frame addr %d\n", tape->name,
-			tape->wrt_pass_cntr, tape->eod_frame_addr);
-#endif
-	__idetape_kfree_stage(stage);
-	return 1;
-}
-
-static int idetape_analyze_headers (ide_drive_t *drive)
-{
-	idetape_tape_t *tape = drive->driver_data;
-	int position, block;
-
-	if (!tape->onstream || tape->raw) {
-		tape->header_ok = tape->linux_media = 1;
-		return 1;
-	}
-	tape->header_ok = tape->linux_media = 0;
-	position = idetape_read_position(drive);
-	for (block = 5; block < 10; block++)
-		if (__idetape_analyze_headers(drive, block))
-			goto ok;
-	for (block = 0xbae; block < 0xbb3; block++) /* 2990 - 2994 */
-		if (__idetape_analyze_headers(drive, block))
-			goto ok;
-	printk(KERN_ERR "ide-tape: %s: failed to find valid ADRL header\n", tape->name);
-	return 0;
-ok:
-	if (position < OS_DATA_STARTFRAME1)
-		position = OS_DATA_STARTFRAME1;
-	idetape_position_tape(drive, position, 0, 0);
-	tape->header_ok = 1;
-	return 1;
-}
-
 static void idetape_get_blocksize_from_block_descriptor(ide_drive_t *drive);
 
 /*
@@ -5613,16 +4197,6 @@ static int idetape_chrdev_open (struct i
 
 	if (test_and_set_bit(IDETAPE_BUSY, &tape->flags))
 		return -EBUSY;
-	if (tape->onstream) {
-		if (minor & 64) {
-			tape->tape_block_size = tape->stage_size = 32768 + 512;
-			tape->raw = 1;
-		} else {
-			tape->tape_block_size = tape->stage_size = 32768;
-			tape->raw = 0;
-		}
-                idetape_onstream_mode_sense_tape_parameter_page(drive, tape->debug_level);
-	}
 	retval = idetape_wait_ready(drive, 60 * HZ);
 	if (retval) {
 		clear_bit(IDETAPE_BUSY, &tape->flags);
@@ -5657,7 +4231,6 @@ static int idetape_chrdev_open (struct i
 
 	/*
 	 * Lock the tape drive door so user can't eject.
-	 * Analyze headers for OnStream drives.
 	 */
 	if (tape->chrdev_direction == idetape_direction_none) {
 		if (idetape_create_prevent_cmd(drive, &pc, 1)) {
@@ -5666,9 +4239,7 @@ static int idetape_chrdev_open (struct i
 					tape->door_locked = DOOR_LOCKED;
 			}
 		}
-		idetape_analyze_headers(drive);
 	}
-	tape->max_frames = tape->cur_frames = tape->req_buffer_fill = 0;
 	idetape_restart_speed_control(drive);
 	tape->restart_speed_control_req = 0;
 	return 0;
@@ -5686,9 +4257,7 @@ static void idetape_write_release (ide_d
 		tape->merge_stage = NULL;
 	}
 	idetape_write_filemark(drive);
-	idetape_write_eod(drive);
 	idetape_flush_tape_buffers(drive);
-	idetape_write_header(drive, minor >= 128);
 	idetape_flush_tape_buffers(drive);
 }
 
@@ -5867,100 +4436,6 @@ static int idetape_identify_device (ide_
 }
 
 /*
- * Notify vendor ID to the OnStream tape drive
- */
-static void idetape_onstream_set_vendor (ide_drive_t *drive, char *vendor)
-{
-	idetape_pc_t pc;
-	idetape_mode_parameter_header_t *header;
-
-	idetape_create_mode_select_cmd(&pc, sizeof(*header) + 8);
-	pc.buffer[0] = 3 + 8;	/* Mode Data Length */
-	pc.buffer[1] = 0;	/* Medium Type - ignoring */
-	pc.buffer[2] = 0;	/* Reserved */
-	pc.buffer[3] = 0;	/* Block Descriptor Length */
-	pc.buffer[4 + 0] = 0x36 | (1 << 7);
-	pc.buffer[4 + 1] = 6;
-	pc.buffer[4 + 2] = vendor[0];
-	pc.buffer[4 + 3] = vendor[1];
-	pc.buffer[4 + 4] = vendor[2];
-	pc.buffer[4 + 5] = vendor[3];
-	pc.buffer[4 + 6] = 0;
-	pc.buffer[4 + 7] = 0;
-	if (idetape_queue_pc_tail(drive, &pc))
-		printk(KERN_ERR "ide-tape: Couldn't set vendor name to %s\n", vendor);
-
-}
-
-/*
- * Various unused OnStream commands
- */
-#if ONSTREAM_DEBUG
-static void idetape_onstream_set_retries (ide_drive_t *drive, int retries)
-{
-	idetape_pc_t pc;
-
-	idetape_create_mode_select_cmd(&pc, sizeof(idetape_mode_parameter_header_t) + 4);
-	pc.buffer[0] = 3 + 4;
-	pc.buffer[1] = 0;	/* Medium Type - ignoring */
-	pc.buffer[2] = 0;	/* Reserved */
-	pc.buffer[3] = 0;	/* Block Descriptor Length */
-	pc.buffer[4 + 0] = 0x2f | (1 << 7);
-	pc.buffer[4 + 1] = 2;
-	pc.buffer[4 + 2] = 4;
-	pc.buffer[4 + 3] = retries;
-	if (idetape_queue_pc_tail(drive, &pc))
-		printk(KERN_ERR "ide-tape: Couldn't set retries to %d\n", retries);
-}
-#endif
-
-/*
- * Configure 32.5KB block size.
- */
-static void idetape_onstream_configure_block_size (ide_drive_t *drive)
-{
-	idetape_pc_t pc;
-	idetape_mode_parameter_header_t *header;
-	idetape_block_size_page_t *bs;
-
-	/*
-	 * Get the current block size from the block size mode page
-	 */
-	idetape_create_mode_sense_cmd(&pc, IDETAPE_BLOCK_SIZE_PAGE);
-	if (idetape_queue_pc_tail(drive, &pc))
-		printk(KERN_ERR "ide-tape: can't get tape block size mode page\n");
-	header = (idetape_mode_parameter_header_t *) pc.buffer;
-	bs = (idetape_block_size_page_t *) (pc.buffer + sizeof(idetape_mode_parameter_header_t) + header->bdl);
-
-#if IDETAPE_DEBUG_INFO
-	printk(KERN_INFO "ide-tape: 32KB play back: %s\n", bs->play32 ? "Yes" : "No");
-	printk(KERN_INFO "ide-tape: 32.5KB play back: %s\n", bs->play32_5 ? "Yes" : "No");
-	printk(KERN_INFO "ide-tape: 32KB record: %s\n", bs->record32 ? "Yes" : "No");
-	printk(KERN_INFO "ide-tape: 32.5KB record: %s\n", bs->record32_5 ? "Yes" : "No");
-#endif /* IDETAPE_DEBUG_INFO */
-
-	/*
-	 * Configure default auto columns mode, 32.5KB block size
-	 */ 
-	bs->one = 1;
-	bs->play32 = 0;
-	bs->play32_5 = 1;
-	bs->record32 = 0;
-	bs->record32_5 = 1;
-	idetape_create_mode_select_cmd(&pc, sizeof(*header) + sizeof(*bs));
-	if (idetape_queue_pc_tail(drive, &pc))
-		printk(KERN_ERR "ide-tape: Couldn't set tape block size mode page\n");
-
-#if ONSTREAM_DEBUG
-	/*
-	 * In debug mode, we want to see as many errors as possible
-	 * to test the error recovery mechanism.
-	 */
-	idetape_onstream_set_retries(drive, 0);
-#endif
-}
-
-/*
  * Use INQUIRY to get the firmware revision
  */
 static void idetape_get_inquiry_results (ide_drive_t *drive)
@@ -5985,63 +4460,10 @@ static void idetape_get_inquiry_results 
 	r = tape->firmware_revision;
 	if (*(r + 1) == '.')
 		tape->firmware_revision_num = (*r - '0') * 100 + (*(r + 2) - '0') * 10 + *(r + 3) - '0';
-	else if (tape->onstream)
-		tape->firmware_revision_num = (*r - '0') * 100 + (*(r + 1) - '0') * 10 + *(r + 2) - '0';
 	printk(KERN_INFO "ide-tape: %s <-> %s: %s %s rev %s\n", drive->name, tape->name, tape->vendor_id, tape->product_id, tape->firmware_revision);
 }
 
 /*
- * Configure the OnStream ATAPI tape drive for default operation
- */
-static void idetape_configure_onstream (ide_drive_t *drive)
-{
-	idetape_tape_t *tape = drive->driver_data;
-
-	if (tape->firmware_revision_num < 105) {
-		printk(KERN_INFO "ide-tape: %s: Old OnStream firmware revision detected (%s)\n", tape->name, tape->firmware_revision);
-		printk(KERN_INFO "ide-tape: %s: An upgrade to version 1.05 or above is recommended\n", tape->name);
-	}
-
-	/*
-	 * Configure 32.5KB (data+aux) block size.
-	 */
-	idetape_onstream_configure_block_size(drive);
-
-	/*
-	 * Set vendor name to 'LIN3' for "Linux support version 3".
-	 */
-	idetape_onstream_set_vendor(drive, "LIN3");
-}
-
-/*
- *	idetape_get_mode_sense_parameters asks the tape about its various
- *	parameters. This may work for other drives to???
- */
-static void idetape_onstream_mode_sense_tape_parameter_page(ide_drive_t *drive, int debug)
-{
-	idetape_tape_t *tape = drive->driver_data;
-	idetape_pc_t pc;
-	idetape_mode_parameter_header_t *header;
-	onstream_tape_paramtr_page_t *prm;
-	
-	idetape_create_mode_sense_cmd(&pc, IDETAPE_PARAMTR_PAGE);
-	if (idetape_queue_pc_tail(drive, &pc)) {
-		printk(KERN_ERR "ide-tape: Can't get tape parameters page - probably no tape inserted in onstream drive\n");
-		return;
-	}
-	header = (idetape_mode_parameter_header_t *) pc.buffer;
-	prm = (onstream_tape_paramtr_page_t *) (pc.buffer + sizeof(idetape_mode_parameter_header_t) + header->bdl);
-
-        tape->capacity = ntohs(prm->segtrk) * ntohs(prm->trks);
-        if (debug) {
-	    printk(KERN_INFO "ide-tape: %s <-> %s: Tape length %dMB (%d frames/track, %d tracks = %d blocks, density: %dKbpi)\n",
-               drive->name, tape->name, tape->capacity/32, ntohs(prm->segtrk), ntohs(prm->trks), tape->capacity, prm->density);
-        }
-
-        return;
-}
-
-/*
  *	idetape_get_mode_sense_results asks the tape about its various
  *	parameters. In particular, we will adjust our data transfer buffer
  *	size to the recommended value as returned by the tape.
@@ -6084,8 +4506,6 @@ static void idetape_get_mode_sense_resul
 		tape->tape_block_size = 512;
 	else if (capabilities->blk1024)
 		tape->tape_block_size = 1024;
-	else if (tape->onstream && capabilities->blk32768)
-		tape->tape_block_size = 32768;
 
 #if IDETAPE_DEBUG_INFO
 	printk(KERN_INFO "ide-tape: Dumping the results of the MODE SENSE packet command\n");
@@ -6169,18 +4589,6 @@ static void idetape_add_settings (ide_dr
 	ide_add_setting(drive,	"pipeline_head_speed_u",SETTING_READ,	-1,	-1,	TYPE_INT,	0,			0xffff,			1,				1,				&tape->uncontrolled_pipeline_head_speed,	NULL);
 	ide_add_setting(drive,	"avg_speed",	SETTING_READ,	-1,	-1,		TYPE_INT,	0,			0xffff,			1,				1,				&tape->avg_speed,		NULL);
 	ide_add_setting(drive,	"debug_level",SETTING_RW,	-1,	-1,		TYPE_INT,	0,			0xffff,			1,				1,				&tape->debug_level,		NULL);
-	if (tape->onstream) {
-		ide_add_setting(drive,	"cur_frames",	SETTING_READ,	-1,	-1,		TYPE_SHORT,	0,			0xffff,			1,				1,				&tape->cur_frames,		NULL);
-		ide_add_setting(drive,	"max_frames",	SETTING_READ,	-1,	-1,		TYPE_SHORT,	0,			0xffff,			1,				1,				&tape->max_frames,		NULL);
-		ide_add_setting(drive,	"insert_speed",	SETTING_READ,	-1,	-1,		TYPE_INT,	0,			0xffff,			1,				1,				&tape->insert_speed,		NULL);
-		ide_add_setting(drive,	"speed_control",SETTING_RW,	-1,	-1,		TYPE_INT,	0,			0xffff,			1,				1,				&tape->speed_control,		NULL);
-		ide_add_setting(drive,	"tape_still_time",SETTING_READ,	-1,	-1,		TYPE_INT,	0,			0xffff,			1,				1,				&tape->tape_still_time,		NULL);
-		ide_add_setting(drive,	"max_insert_speed",SETTING_RW,	-1,	-1,		TYPE_INT,	0,			0xffff,			1,				1,				&tape->max_insert_speed,	NULL);
-		ide_add_setting(drive,	"insert_size",	SETTING_READ,	-1,	-1,		TYPE_INT,	0,			0xffff,			1,				1,				&tape->insert_size,		NULL);
-		ide_add_setting(drive,	"capacity",	SETTING_READ,	-1,	-1,		TYPE_INT,	0,			0xffff,			1,				1,				&tape->capacity,		NULL);
-		ide_add_setting(drive,	"first_frame",	SETTING_READ,	-1,	-1,		TYPE_INT,	0,			0xffff,			1,				1,				&tape->first_frame_position,		NULL);
-		ide_add_setting(drive,	"logical_blk",	SETTING_READ,	-1,	-1,		TYPE_INT,	0,			0xffff,			1,				1,				&tape->logical_blk_num,		NULL);
-	}
 }
 
 /*
@@ -6208,11 +4616,9 @@ static void idetape_setup (ide_drive_t *
 	drive->driver_data = tape;
 	/* An ATAPI device ignores DRDY */
 	drive->ready_stat = 0;
-	if (strstr(drive->id->model, "OnStream DI-"))
-		tape->onstream = 1;
 	drive->dsc_overlap = 1;
 #ifdef CONFIG_BLK_DEV_IDEPCI
-	if (!tape->onstream && HWIF(drive)->pci_dev != NULL) {
+	if (HWIF(drive)->pci_dev != NULL) {
 		/*
 		 * These two ide-pci host adapters appear to need DSC overlap disabled.
 		 * This probably needs further analysis.
@@ -6245,10 +4651,6 @@ static void idetape_setup (ide_drive_t *
 	idetape_get_inquiry_results(drive);
 	idetape_get_mode_sense_results(drive);
 	idetape_get_blocksize_from_block_descriptor(drive);
-	if (tape->onstream) {
-		idetape_onstream_mode_sense_tape_parameter_page(drive, 1);
-		idetape_configure_onstream(drive);
-	}
 	tape->user_bs_factor = 1;
 	tape->stage_size = tape->capabilities.ctl * tape->tape_block_size;
 	while (tape->stage_size > 0xffff) {
@@ -6257,8 +4659,6 @@ static void idetape_setup (ide_drive_t *
 		tape->stage_size = tape->capabilities.ctl * tape->tape_block_size;
 	}
 	stage_size = tape->stage_size;
-	if (tape->onstream)
-		stage_size = 32768 + 512;
 	tape->pages_per_stage = stage_size / PAGE_SIZE;
 	if (stage_size % PAGE_SIZE) {
 		tape->pages_per_stage++;
@@ -6454,7 +4854,7 @@ static int idetape_attach (ide_drive_t *
 		printk(KERN_ERR "ide-tape: %s: Can't allocate a tape structure\n", drive->name);
 		goto failed;
 	}
-	if (ide_register_subdriver (drive, &idetape_driver, IDE_SUBDRIVER_VERSION)) {
+	if (ide_register_subdriver(drive, &idetape_driver)) {
 		printk(KERN_ERR "ide-tape: %s: Failed to register the driver with ide.c\n", drive->name);
 		kfree(tape);
 		goto failed;
@@ -6502,3 +4902,4 @@ static int idetape_init (void)
 
 module_init(idetape_init);
 module_exit(idetape_exit);
+MODULE_ALIAS_CHARDEV_MAJOR(IDETAPE_MAJOR);
--- diff/drivers/ide/ide-taskfile.c	2004-02-18 08:54:09.000000000 +0000
+++ source/drivers/ide/ide-taskfile.c	2004-02-23 13:56:41.000000000 +0000
@@ -219,66 +219,6 @@ ide_startstop_t do_rw_taskfile (ide_driv
 EXPORT_SYMBOL(do_rw_taskfile);
 
 /*
- * Clean up after success/failure of an explicit taskfile operation.
- */
-void ide_end_taskfile (ide_drive_t *drive, u8 stat, u8 err)
-{
-	ide_hwif_t *hwif = HWIF(drive);
-	unsigned long flags;
-	struct request *rq;
-	ide_task_t *args;
-	task_ioreg_t command;
-
-	spin_lock_irqsave(&ide_lock, flags);
-	rq = HWGROUP(drive)->rq;
-	spin_unlock_irqrestore(&ide_lock, flags);
-	args = (ide_task_t *) rq->special;
-
-	command = args->tfRegister[IDE_COMMAND_OFFSET];
-
-	if (rq->errors == 0)
-		rq->errors = !OK_STAT(stat,READY_STAT,BAD_STAT);
-
-	if (args->tf_in_flags.b.data) {
-		u16 data = hwif->INW(IDE_DATA_REG);
-		args->tfRegister[IDE_DATA_OFFSET] = (data) & 0xFF;
-		args->hobRegister[IDE_DATA_OFFSET_HOB]	= (data >> 8) & 0xFF;
-	}
-	args->tfRegister[IDE_ERROR_OFFSET]   = err;
-	args->tfRegister[IDE_NSECTOR_OFFSET] = hwif->INB(IDE_NSECTOR_REG);
-	args->tfRegister[IDE_SECTOR_OFFSET]  = hwif->INB(IDE_SECTOR_REG);
-	args->tfRegister[IDE_LCYL_OFFSET]    = hwif->INB(IDE_LCYL_REG);
-	args->tfRegister[IDE_HCYL_OFFSET]    = hwif->INB(IDE_HCYL_REG);
-	args->tfRegister[IDE_SELECT_OFFSET]  = hwif->INB(IDE_SELECT_REG);
-	args->tfRegister[IDE_STATUS_OFFSET]  = stat;
-	if ((drive->id->command_set_2 & 0x0400) &&
-	    (drive->id->cfs_enable_2 & 0x0400) &&
-	    (drive->addressing == 1)) {
-		hwif->OUTB(drive->ctl|0x80, IDE_CONTROL_REG_HOB);
-		args->hobRegister[IDE_FEATURE_OFFSET_HOB] = hwif->INB(IDE_FEATURE_REG);
-		args->hobRegister[IDE_NSECTOR_OFFSET_HOB] = hwif->INB(IDE_NSECTOR_REG);
-		args->hobRegister[IDE_SECTOR_OFFSET_HOB]  = hwif->INB(IDE_SECTOR_REG);
-		args->hobRegister[IDE_LCYL_OFFSET_HOB]    = hwif->INB(IDE_LCYL_REG);
-		args->hobRegister[IDE_HCYL_OFFSET_HOB]    = hwif->INB(IDE_HCYL_REG);
-	}
-
-#if 0
-/*	taskfile_settings_update(drive, args, command); */
-
-	if (args->posthandler != NULL)
-		args->posthandler(drive, args);
-#endif
-
-	spin_lock_irqsave(&ide_lock, flags);
-	blkdev_dequeue_request(rq);
-	HWGROUP(drive)->rq = NULL;
-	end_that_request_last(rq);
-	spin_unlock_irqrestore(&ide_lock, flags);
-}
-
-EXPORT_SYMBOL(ide_end_taskfile);
-
-/*
  * set_multmode_intr() is invoked on completion of a WIN_SETMULT cmd.
  */
 ide_startstop_t set_multmode_intr (ide_drive_t *drive)
@@ -1669,7 +1609,6 @@ EXPORT_SYMBOL(ide_wait_cmd);
  */
 int ide_cmd_ioctl (ide_drive_t *drive, unsigned int cmd, unsigned long arg)
 {
-#if 1
 	int err = 0;
 	u8 args[4], *argbuf = args;
 	u8 xfer_rate = 0;
@@ -1720,70 +1659,6 @@ abort:
 	if (argsize > 4)
 		kfree(argbuf);
 	return err;
-
-#else
-
-	int err = -EIO;
-	u8 args[4], *argbuf = args;
-	u8 xfer_rate = 0;
-	int argsize = 0;
-	ide_task_t tfargs;
-
-	if (NULL == (void *) arg) {
-		struct request rq;
-		ide_init_drive_cmd(&rq);
-		return ide_do_drive_cmd(drive, &rq, ide_wait);
-	}
-
-	if (copy_from_user(args, (void *)arg, 4))
-		return -EFAULT;
-
-	memset(&tfargs, 0, sizeof(ide_task_t));
-	tfargs.tfRegister[IDE_FEATURE_OFFSET] = args[2];
-	tfargs.tfRegister[IDE_NSECTOR_OFFSET] = args[3];
-	tfargs.tfRegister[IDE_SECTOR_OFFSET]  = args[1];
-	tfargs.tfRegister[IDE_LCYL_OFFSET]    = 0x00;
-	tfargs.tfRegister[IDE_HCYL_OFFSET]    = 0x00;
-	tfargs.tfRegister[IDE_SELECT_OFFSET]  = 0x00;
-	tfargs.tfRegister[IDE_COMMAND_OFFSET] = args[0];
-
-	if (args[3]) {
-		argsize = (SECTOR_WORDS * 4 * args[3]);
-		argbuf = kmalloc(argsize, GFP_KERNEL);
-		if (argbuf == NULL)
-			return -ENOMEM;
-	}
-
-	if (set_transfer(drive, &tfargs)) {
-		xfer_rate = args[1];
-		if (ide_ata66_check(drive, &tfargs))
-			goto abort;
-	}
-
-	tfargs.command_type = ide_cmd_type_parser(&tfargs);
-	err = ide_raw_taskfile(drive, &tfargs, argbuf);
-
-	if (!err && xfer_rate) {
-		/* active-retuning-calls future */
-		ide_set_xfer_rate(driver, xfer_rate);
-		ide_driveid_update(drive);
-	}
-abort:
-	args[0] = tfargs.tfRegister[IDE_COMMAND_OFFSET];
-	args[1] = tfargs.tfRegister[IDE_FEATURE_OFFSET];
-	args[2] = tfargs.tfRegister[IDE_NSECTOR_OFFSET];
-	args[3] = 0;
-
-	if (copy_to_user((void *)arg, argbuf, 4))
-		err = -EFAULT;
-	if (argbuf != NULL) {
-		if (copy_to_user((void *)arg, argbuf + 4, argsize))
-			err = -EFAULT;
-		kfree(argbuf);
-	}
-	return err;
-
-#endif
 }
 
 EXPORT_SYMBOL(ide_cmd_ioctl);
--- diff/drivers/ide/ide.c	2004-02-18 08:54:09.000000000 +0000
+++ source/drivers/ide/ide.c	2004-02-23 13:56:41.000000000 +0000
@@ -474,6 +474,8 @@ struct seq_operations ide_drivers_op = {
 };
 
 #ifdef CONFIG_PROC_FS
+struct proc_dir_entry *proc_ide_root;
+
 ide_proc_entry_t generic_subdriver_entries[] = {
 	{ "capacity",	S_IFREG|S_IRUGO,	proc_ide_read_capacity,	NULL },
 	{ NULL, 0, NULL, NULL }
@@ -642,10 +644,9 @@ void ide_unregister (unsigned int index)
 		drive = &hwif->drives[unit];
 		if (!drive->present)
 			continue;
-		if (drive->usage)
-			goto abort;
-		if (DRIVER(drive)->shutdown(drive))
+		if (drive->usage || DRIVER(drive)->busy)
 			goto abort;
+		drive->dead = 1;
 	}
 	hwif->present = 0;
 	
@@ -994,9 +995,7 @@ found:
 
 	if (!initializing) {
 		probe_hwif_init(hwif);
-#ifdef CONFIG_PROC_FS
 		create_proc_ide_interfaces();
-#endif
 	}
 
 	if (hwifp)
@@ -1392,7 +1391,6 @@ void ide_add_generic_settings (ide_drive
 	ide_add_setting(drive,	"keepsettings",		SETTING_RW,					HDIO_GET_KEEPSETTINGS,	HDIO_SET_KEEPSETTINGS,	TYPE_BYTE,	0,	1,				1,		1,		&drive->keep_settings,		NULL);
 	ide_add_setting(drive,	"nice1",		SETTING_RW,					-1,			-1,			TYPE_BYTE,	0,	1,				1,		1,		&drive->nice1,			NULL);
 	ide_add_setting(drive,	"pio_mode",		SETTING_WRITE,					-1,			HDIO_SET_PIO_MODE,	TYPE_BYTE,	0,	255,				1,		1,		NULL,				set_pio_mode);
-	ide_add_setting(drive,	"slow",			SETTING_RW,					-1,			-1,			TYPE_BYTE,	0,	1,				1,		1,		&drive->slow,			NULL);
 	ide_add_setting(drive,	"unmaskirq",		drive->no_unmask ? SETTING_READ : SETTING_RW,	HDIO_GET_UNMASKINTR,	HDIO_SET_UNMASKINTR,	TYPE_BYTE,	0,	1,				1,		1,		&drive->unmask,			NULL);
 	ide_add_setting(drive,	"using_dma",		SETTING_RW,					HDIO_GET_DMA,		HDIO_SET_DMA,		TYPE_BYTE,	0,	1,				1,		1,		&drive->using_dma,		set_using_dma);
 	ide_add_setting(drive,	"init_speed",		SETTING_RW,					-1,			-1,			TYPE_BYTE,	0,	70,				1,		1,		&drive->init_speed,		NULL);
@@ -1786,83 +1784,9 @@ static int __initdata is_chipset_set[MAX
 
 /*
  * ide_setup() gets called VERY EARLY during initialization,
- * to handle kernel "command line" strings beginning with "hdx="
- * or "ide".  Here is the complete set currently supported:
- *
- * "hdx="  is recognized for all "x" from "a" to "h", such as "hdc".
- * "idex=" is recognized for all "x" from "0" to "3", such as "ide1".
+ * to handle kernel "command line" strings beginning with "hdx=" or "ide".
  *
- * "hdx=noprobe"	: drive may be present, but do not probe for it
- * "hdx=none"		: drive is NOT present, ignore cmos and do not probe
- * "hdx=nowerr"		: ignore the WRERR_STAT bit on this drive
- * "hdx=cdrom"		: drive is present, and is a cdrom drive
- * "hdx=cyl,head,sect"	: disk drive is present, with specified geometry
- * "hdx=remap63"	: add 63 to all sector numbers (for OnTrack DM)
- * "hdx=remap"		: remap 0->1 (for EZDrive)
- * "hdx=autotune"	: driver will attempt to tune interface speed
- *				to the fastest PIO mode supported,
- *				if possible for this drive only.
- *				Not fully supported by all chipset types,
- *				and quite likely to cause trouble with
- *				older/odd IDE drives.
- * "hdx=slow"		: insert a huge pause after each access to the data
- *				port. Should be used only as a last resort.
- *
- * "hdx=swapdata"	: when the drive is a disk, byte swap all data
- * "hdx=bswap"		: same as above..........
- * "hdxlun=xx"          : set the drive last logical unit.
- * "hdx=flash"		: allows for more than one ata_flash disk to be
- *				registered. In most cases, only one device
- *				will be present.
- * "hdx=scsi"		: the return of the ide-scsi flag, this is useful for
- *				allowing ide-floppy, ide-tape, and ide-cdrom|writers
- *				to use ide-scsi emulation on a device specific option.
- * "idebus=xx"		: inform IDE driver of VESA/PCI bus speed in MHz,
- *				where "xx" is between 20 and 66 inclusive,
- *				used when tuning chipset PIO modes.
- *				For PCI bus, 25 is correct for a P75 system,
- *				30 is correct for P90,P120,P180 systems,
- *				and 33 is used for P100,P133,P166 systems.
- *				If in doubt, use idebus=33 for PCI.
- *				As for VLB, it is safest to not specify it.
- *
- * "idex=noprobe"	: do not attempt to access/use this interface
- * "idex=base"		: probe for an interface at the addr specified,
- *				where "base" is usually 0x1f0 or 0x170
- *				and "ctl" is assumed to be "base"+0x206
- * "idex=base,ctl"	: specify both base and ctl
- * "idex=base,ctl,irq"	: specify base, ctl, and irq number
- * "idex=autotune"	: driver will attempt to tune interface speed
- *				to the fastest PIO mode supported,
- *				for all drives on this interface.
- *				Not fully supported by all chipset types,
- *				and quite likely to cause trouble with
- *				older/odd IDE drives.
- * "idex=noautotune"	: driver will NOT attempt to tune interface speed
- *				This is the default for most chipsets,
- *				except the cmd640.
- * "idex=serialize"	: do not overlap operations on idex and ide(x^1)
- * "idex=four"		: four drives on idex and ide(x^1) share same ports
- * "idex=reset"		: reset interface before first use
- * "idex=dma"		: enable DMA by default on both drives if possible
- * "idex=ata66"		: informs the interface that it has an 80c cable
- *				for chipsets that are ATA-66 capable, but
- *				the ablity to bit test for detection is
- *				currently unknown.
- * "ide=reverse"	: Formerly called to pci sub-system, but now local.
- *
- * The following are valid ONLY on ide0, (except dc4030)
- * and the defaults for the base,ctl ports must not be altered.
- *
- * "ide0=dtc2278"	: probe/support DTC2278 interface
- * "ide0=ht6560b"	: probe/support HT6560B interface
- * "ide0=cmd640_vlb"	: *REQUIRED* for VLB cards with the CMD640 chip
- *			  (not for PCI -- automatically detected)
- * "ide0=qd65xx"	: probe/support qd65xx interface
- * "ide0=ali14xx"	: probe/support ali14xx chipsets (ALI M1439, M1443, M1445)
- * "ide0=umc8672"	: probe/support umc8672 chipsets
- * "idex=dc4030"	: probe/support Promise DC4030VL interface
- * "ide=doubler"	: probe/support IDE doublers on Amiga
+ * Remember to update Documentation/ide.txt if you change something here.
  */
 int __init ide_setup (char *s)
 {
@@ -1915,8 +1839,8 @@ int __init ide_setup (char *s)
 	if (s[0] == 'h' && s[1] == 'd' && s[2] >= 'a' && s[2] <= max_drive) {
 		const char *hd_words[] = {
 			"none", "noprobe", "nowerr", "cdrom", "serialize",
-			"autotune", "noautotune", "slow", "swapdata", "bswap",
-			"flash", "remap", "remap63", "scsi", NULL };
+			"autotune", "noautotune", "minus8", "swapdata", "bswap",
+			"minus11", "remap", "remap63", "scsi", NULL };
 		unit = s[2] - 'a';
 		hw   = unit / MAX_DRIVES;
 		unit = unit % MAX_DRIVES;
@@ -1941,7 +1865,6 @@ int __init ide_setup (char *s)
 		}
 		switch (match_parm(&s[3], hd_words, vals, 3)) {
 			case -1: /* "none" */
-				drive->nobios = 1;  /* drop into "noprobe" */
 			case -2: /* "noprobe" */
 				drive->noprobe = 1;
 				goto done;
@@ -1963,16 +1886,10 @@ int __init ide_setup (char *s)
 			case -7: /* "noautotune" */
 				drive->autotune = IDE_TUNE_NOAUTO;
 				goto done;
-			case -8: /* "slow" */
-				drive->slow = 1;
-				goto done;
 			case -9: /* "swapdata" */
 			case -10: /* "bswap" */
 				drive->bswap = 1;
 				goto done;
-			case -11: /* "flash" */
-				drive->ata_flash = 1;
-				goto done;
 			case -12: /* "remap" */
 				drive->remap_0_to_1 = 1;
 				goto done;
@@ -2251,34 +2168,6 @@ static int default_cleanup (ide_drive_t 
 	return ide_unregister_subdriver(drive);
 }
 
-/*
- *	Check if we can unregister the subdriver. Called with the
- *	request lock held.
- */
- 
-static int default_shutdown(ide_drive_t *drive)
-{
-	if (drive->usage || DRIVER(drive)->busy) {
-		return 1;
-	}
-	drive->dead = 1;
-	return 0;
-}
-
-/*
- *	Default function to use for the cache flush operation. This
- *	must be replaced for disk devices (see ATA specification
- *	documents on cache flush and drive suspend rules)
- *
- *	If we have no device attached or the device is not writable
- *	this handler is sufficient.
- */
- 
-static int default_flushcache (ide_drive_t *drive)
-{
-	return 0;
-}
-
 static ide_startstop_t default_do_request (ide_drive_t *drive, struct request *rq, sector_t block)
 {
 	ide_end_request(drive, 0, 0);
@@ -2341,8 +2230,6 @@ static ide_startstop_t default_start_pow
 static void setup_driver_defaults (ide_driver_t *d)
 {
 	if (d->cleanup == NULL)		d->cleanup = default_cleanup;
-	if (d->shutdown == NULL)	d->shutdown = default_shutdown;
-	if (d->flushcache == NULL)	d->flushcache = default_flushcache;
 	if (d->do_request == NULL)	d->do_request = default_do_request;
 	if (d->end_request == NULL)	d->end_request = default_end_request;
 	if (d->sense == NULL)		d->sense = default_sense;
@@ -2356,15 +2243,15 @@ static void setup_driver_defaults (ide_d
 		d->start_power_step = default_start_power_step;
 }
 
-int ide_register_subdriver (ide_drive_t *drive, ide_driver_t *driver, int version)
+int ide_register_subdriver(ide_drive_t *drive, ide_driver_t *driver)
 {
 	unsigned long flags;
-	
-	BUG_ON(drive->driver == NULL);
-	
+
+	BUG_ON(!drive->driver);
+
 	spin_lock_irqsave(&ide_lock, flags);
-	if (version != IDE_SUBDRIVER_VERSION || !drive->present ||
-	    drive->driver != &idedefault_driver || drive->usage || drive->dead) {
+	if (!drive->present || drive->driver != &idedefault_driver ||
+	    drive->usage || drive->dead) {
 		spin_unlock_irqrestore(&ide_lock, flags);
 		return 1;
 	}
@@ -2477,12 +2364,6 @@ void ide_unregister_driver(ide_driver_t 
 			printk(KERN_ERR "%s: cleanup_module() called while still busy\n", drive->name);
 			BUG();
 		}
-		/* We must remove proc entries defined in this module.
-		   Otherwise we oops while accessing these entries */
-#ifdef CONFIG_PROC_FS
-		if (drive->proc)
-			ide_remove_proc_entries(drive->proc, driver->proc);
-#endif
 		ata_attach(drive);
 	}
 }
@@ -2521,6 +2402,10 @@ int __init ide_init (void)
 
 	init_ide_data();
 
+#ifdef CONFIG_PROC_FS
+	proc_ide_root = proc_mkdir("ide", 0);
+#endif
+
 #ifdef CONFIG_BLK_DEV_ALI14XX
 	if (probe_ali14xx)
 		(void)ali14xx_init();
--- diff/drivers/ide/pci/Makefile	2004-02-09 10:36:10.000000000 +0000
+++ source/drivers/ide/pci/Makefile	2004-02-23 13:56:41.000000000 +0000
@@ -11,7 +11,6 @@ obj-$(CONFIG_BLK_DEV_CY82C693)		+= cy82c
 obj-$(CONFIG_BLK_DEV_HPT34X)		+= hpt34x.o
 obj-$(CONFIG_BLK_DEV_HPT366)		+= hpt366.o
 #obj-$(CONFIG_BLK_DEV_HPT37X)		+= hpt37x.o
-obj-$(CONFIG_BLK_DEV_IDE_ICSIDE)	+= icside.o
 obj-$(CONFIG_BLK_DEV_IT8172)		+= it8172.o
 obj-$(CONFIG_BLK_DEV_NS87415)		+= ns87415.o
 obj-$(CONFIG_BLK_DEV_OPTI621)		+= opti621.o
--- diff/drivers/ide/pci/aec62xx.c	2004-02-18 08:54:09.000000000 +0000
+++ source/drivers/ide/pci/aec62xx.c	2004-02-23 13:56:41.000000000 +0000
@@ -423,7 +423,7 @@ static unsigned int __init init_chipset_
 
 	if (!aec62xx_proc) {
 		aec62xx_proc = 1;
-		ide_pci_register_host_proc(&aec62xx_procs[0]);
+		ide_pci_create_host_proc("aec62xx", aec62xx_get_info);
 	}
 #endif /* DISPLAY_AEC62XX_TIMINGS && CONFIG_PROC_FS */
 
--- diff/drivers/ide/pci/aec62xx.h	2004-02-18 08:54:09.000000000 +0000
+++ source/drivers/ide/pci/aec62xx.h	2004-02-23 13:56:41.000000000 +0000
@@ -70,24 +70,6 @@ struct chipset_bus_clock_list_entry aec6
 #define BUSCLOCK(D)	\
 	((struct chipset_bus_clock_list_entry *) pci_get_drvdata((D)))
 
-#if defined(DISPLAY_AEC62XX_TIMINGS) && defined(CONFIG_PROC_FS)
-#include <linux/stat.h>
-#include <linux/proc_fs.h>
-
-static u8 aec62xx_proc;
-
-static int aec62xx_get_info(char *, char **, off_t, int);
-
-static ide_pci_host_proc_t aec62xx_procs[] = {
-	{
-		.name		= "aec62xx",
-		.set		= 1,
-		.get_info	= aec62xx_get_info,
-		.parent		= NULL,
-	},
-};
-#endif /* DISPLAY_AEC62XX_TIMINGS && CONFIG_PROC_FS */
-
 static void init_setup_aec6x80(struct pci_dev *, ide_pci_device_t *);
 static void init_setup_aec62xx(struct pci_dev *, ide_pci_device_t *);
 static unsigned int init_chipset_aec62xx(struct pci_dev *, const char *);
--- diff/drivers/ide/pci/alim15x3.c	2004-02-18 08:54:09.000000000 +0000
+++ source/drivers/ide/pci/alim15x3.c	2004-02-23 13:56:41.000000000 +0000
@@ -1,5 +1,5 @@
 /*
- * linux/drivers/ide/pci/alim15x3.c		Version 0.16	2003/01/02
+ * linux/drivers/ide/pci/alim15x3.c		Version 0.17	2003/01/02
  *
  *  Copyright (C) 1998-2000 Michel Aubry, Maintainer
  *  Copyright (C) 1998-2000 Andrzej Krzysztofowicz, Maintainer
@@ -19,6 +19,7 @@
  *	Don't use LBA48 mode on ALi <= 0xC4
  *	Don't poke 0x79 with a non ALi northbridge
  *	Don't flip undefined bits on newer chipsets (fix Fujitsu laptop hang)
+ *	Allow UDMA6 on revisions > 0xC4
  *
  *  Documentation
  *	Chipset documentation available under NDA only
@@ -406,7 +407,9 @@ static u8 ali15x3_ratemask (ide_drive_t 
 {
 	u8 mode = 0, can_ultra	= ali15x3_can_ultra(drive);
 
-	if (m5229_revision >= 0xC4 && can_ultra) {
+	if (m5229_revision > 0xC4 && can_ultra) {
+		mode = 4;
+	} else if (m5229_revision == 0xC4 && can_ultra) {
 		mode = 3;
 	} else if (m5229_revision >= 0xC2 && can_ultra) {
 		mode = 2;
@@ -439,11 +442,15 @@ static int ali15x3_tune_chipset (ide_dri
 {
 	ide_hwif_t *hwif	= HWIF(drive);
 	struct pci_dev *dev	= hwif->pci_dev;
-	u8 speed	= ide_rate_filter(ali15x3_ratemask(drive), xferspeed);
+	u8 speed		= ide_rate_filter(ali15x3_ratemask(drive), xferspeed);
+	u8 speed1		= speed;
 	u8 unit			= (drive->select.b.unit & 0x01);
 	u8 tmpbyte		= 0x00;
 	int m5229_udma		= (hwif->channel) ? 0x57 : 0x56;
 
+        if (speed == XFER_UDMA_6)
+                speed1 = 0x47;
+
 	if (speed < XFER_UDMA_0) {
 		u8 ultra_enable	= (unit) ? 0x7f : 0xf7;
 		/*
@@ -461,7 +468,7 @@ static int ali15x3_tune_chipset (ide_dri
 		/*
 		 * enable ultra dma and set timing
 		 */
-		tmpbyte |= ((0x08 | ((4-speed)&0x07)) << (unit << 2));
+		tmpbyte |= ((0x08 | ((4-speed1)&0x07)) << (unit << 2));
 		pci_write_config_byte(dev, m5229_udma, tmpbyte);
 		if (speed >= XFER_UDMA_3) {
 			pci_read_config_byte(dev, 0x4b, &tmpbyte);
@@ -588,7 +595,7 @@ static unsigned int __init init_chipset_
 	if (!ali_proc) {
 		ali_proc = 1;
 		bmide_dev = dev;
-		ide_pci_register_host_proc(&ali_procs[0]);
+		ide_pci_create_host_proc("ali", ali_get_info);
 	}
 #endif  /* defined(DISPLAY_ALI_TIMINGS) && defined(CONFIG_PROC_FS) */
 
@@ -757,7 +764,7 @@ static void __init init_hwif_common_ali1
 	hwif->atapi_dma = 1;
 
 	if (m5229_revision > 0x20)
-		hwif->ultra_mask = 0x3f;
+		hwif->ultra_mask = 0x7f;
 	hwif->mwdma_mask = 0x07;
 	hwif->swdma_mask = 0x07;
 
--- diff/drivers/ide/pci/alim15x3.h	2004-02-18 08:54:09.000000000 +0000
+++ source/drivers/ide/pci/alim15x3.h	2004-02-23 13:56:41.000000000 +0000
@@ -7,24 +7,6 @@
 
 #define DISPLAY_ALI_TIMINGS
 
-#if defined(DISPLAY_ALI_TIMINGS) && defined(CONFIG_PROC_FS)
-#include <linux/stat.h>
-#include <linux/proc_fs.h>
-
-static u8 ali_proc;
-
-static int ali_get_info(char *, char **, off_t, int);
-
-static ide_pci_host_proc_t ali_procs[] = {
-	{
-		.name		= "ali",
-		.set		= 1,
-		.get_info	= ali_get_info,
-		.parent		= NULL,
-	},
-};
-#endif /* DISPLAY_ALI_TIMINGS && CONFIG_PROC_FS */
-
 static unsigned int init_chipset_ali15x3(struct pci_dev *, const char *);
 static void init_hwif_common_ali15x3(ide_hwif_t *);
 static void init_hwif_ali15x3(ide_hwif_t *);
--- diff/drivers/ide/pci/amd74xx.c	2004-02-18 08:54:09.000000000 +0000
+++ source/drivers/ide/pci/amd74xx.c	2004-02-23 13:56:41.000000000 +0000
@@ -88,6 +88,8 @@ static unsigned char amd_cyc2udma[] = { 
 #include <linux/stat.h>
 #include <linux/proc_fs.h>
 
+static u8 amd74xx_proc;
+
 static unsigned char amd_udma2cyc[] = { 4, 6, 8, 10, 3, 2, 1, 15 };
 static unsigned long amd_base;
 static struct pci_dev *bmide_dev;
@@ -398,7 +400,7 @@ static unsigned int __init init_chipset_
         if (!amd74xx_proc) {
                 amd_base = pci_resource_start(dev, 4);
                 bmide_dev = dev;
-                ide_pci_register_host_proc(&amd74xx_procs[0]);
+		ide_pci_create_host_proc("amd74xx", amd74xx_get_info);
                 amd74xx_proc = 1;
         }
 #endif /* DISPLAY_AMD_TIMINGS && CONFIG_PROC_FS */
--- diff/drivers/ide/pci/amd74xx.h	2004-02-18 08:54:09.000000000 +0000
+++ source/drivers/ide/pci/amd74xx.h	2004-02-23 13:56:41.000000000 +0000
@@ -7,24 +7,6 @@
 
 #define DISPLAY_AMD_TIMINGS
 
-#if defined(DISPLAY_AMD_TIMINGS) && defined(CONFIG_PROC_FS)
-#include <linux/stat.h>
-#include <linux/proc_fs.h>
-
-static u8 amd74xx_proc;
-
-static int amd74xx_get_info(char *, char **, off_t, int);
-
-static ide_pci_host_proc_t amd74xx_procs[] = {
-	{
-		.name		= "amd74xx",
-		.set		= 1,
-		.get_info	= amd74xx_get_info,
-		.parent		= NULL,
-	},
-};
-#endif  /* defined(DISPLAY_AMD_TIMINGS) && defined(CONFIG_PROC_FS) */
-
 static unsigned int init_chipset_amd74xx(struct pci_dev *, const char *);
 static void init_hwif_amd74xx(ide_hwif_t *);
 
--- diff/drivers/ide/pci/cmd64x.c	2004-02-18 08:54:09.000000000 +0000
+++ source/drivers/ide/pci/cmd64x.c	2004-02-23 13:56:41.000000000 +0000
@@ -667,7 +667,7 @@ static unsigned int __init init_chipset_
 
 	if (!cmd64x_proc) {
 		cmd64x_proc = 1;
-		ide_pci_register_host_proc(&cmd64x_procs[0]);
+		ide_pci_create_host_proc("cmd64x", cmd64x_get_info);
 	}
 #endif /* DISPLAY_CMD64X_TIMINGS && CONFIG_PROC_FS */
 
--- diff/drivers/ide/pci/cmd64x.h	2004-02-18 08:54:09.000000000 +0000
+++ source/drivers/ide/pci/cmd64x.h	2004-02-23 13:56:41.000000000 +0000
@@ -60,25 +60,6 @@
 #define UDIDETCR1	0x7B
 #define DTPR1		0x7C
 
-#if defined(DISPLAY_CMD64X_TIMINGS) && defined(CONFIG_PROC_FS)
-#include <linux/stat.h>
-#include <linux/proc_fs.h>
-
-static u8 cmd64x_proc;
-
-static char * print_cmd64x_get_info(char *, struct pci_dev *, int);
-static int cmd64x_get_info(char *, char **, off_t, int);
-
-static ide_pci_host_proc_t cmd64x_procs[] = {
-	{
-		.name		= "cmd64x",
-		.set		= 1,
-		.get_info	= cmd64x_get_info,
-		.parent		= NULL,
-	},
-};
-#endif  /* defined(DISPLAY_CMD64X_TIMINGS) && defined(CONFIG_PROC_FS) */
-
 static unsigned int init_chipset_cmd64x(struct pci_dev *, const char *);
 static void init_hwif_cmd64x(ide_hwif_t *);
 
--- diff/drivers/ide/pci/cs5520.c	2004-02-18 08:54:09.000000000 +0000
+++ source/drivers/ide/pci/cs5520.c	2004-02-23 13:56:41.000000000 +0000
@@ -196,7 +196,7 @@ static unsigned int __devinit init_chips
 	if (!cs5520_proc) {
 		cs5520_proc = 1;
 		bmide_dev = dev;
-		ide_pci_register_host_proc(&cs5520_procs[0]);
+		ide_pci_create_host_proc("cs5520", cs5520_get_info);
 	}
 #endif /* DISPLAY_CS5520_TIMINGS && CONFIG_PROC_FS */
 	return 0;
--- diff/drivers/ide/pci/cs5520.h	2004-02-18 08:54:09.000000000 +0000
+++ source/drivers/ide/pci/cs5520.h	2004-02-23 13:56:41.000000000 +0000
@@ -7,24 +7,6 @@
 
 #define DISPLAY_CS5520_TIMINGS
 
-#if defined(DISPLAY_CS5520_TIMINGS) && defined(CONFIG_PROC_FS)
-#include <linux/stat.h>
-#include <linux/proc_fs.h>
-
-static u8 cs5520_proc;
-
-static int cs5520_get_info(char *, char **, off_t, int);
-
-static ide_pci_host_proc_t cs5520_procs[] = {
-	{
-		.name		= "cs5520",
-		.set		= 1,
-		.get_info	= cs5520_get_info,
-		.parent		= NULL,
-	},
-};
-#endif  /* defined(DISPLAY_CS5520_TIMINGS) && defined(CONFIG_PROC_FS) */
-
 static unsigned int init_chipset_cs5520(struct pci_dev *, const char *);
 static void init_hwif_cs5520(ide_hwif_t *);
 static void cs5520_init_setup_dma(struct pci_dev *dev, struct ide_pci_device_s *d, ide_hwif_t *hwif);
--- diff/drivers/ide/pci/cs5530.c	2004-02-18 08:54:09.000000000 +0000
+++ source/drivers/ide/pci/cs5530.c	2004-02-23 13:56:41.000000000 +0000
@@ -276,7 +276,7 @@ static unsigned int __init init_chipset_
 	if (!cs5530_proc) {
 		cs5530_proc = 1;
 		bmide_dev = dev;
-		ide_pci_register_host_proc(&cs5530_procs[0]);
+		ide_pci_create_host_proc("cs5530", cs5530_get_info);
 	}
 #endif /* DISPLAY_CS5530_TIMINGS && CONFIG_PROC_FS */
 
--- diff/drivers/ide/pci/cs5530.h	2004-02-18 08:54:09.000000000 +0000
+++ source/drivers/ide/pci/cs5530.h	2004-02-23 13:56:41.000000000 +0000
@@ -7,24 +7,6 @@
 
 #define DISPLAY_CS5530_TIMINGS
 
-#if defined(DISPLAY_CS5530_TIMINGS) && defined(CONFIG_PROC_FS)
-#include <linux/stat.h>
-#include <linux/proc_fs.h>
-
-static u8 cs5530_proc;
-
-static int cs5530_get_info(char *, char **, off_t, int);
-
-static ide_pci_host_proc_t cs5530_procs[] = {
-	{
-		.name		= "cs5530",
-		.set		= 1,
-		.get_info	= cs5530_get_info,
-		.parent		= NULL,
-	},
-};
-#endif /* DISPLAY_CS5530_TIMINGS && CONFIG_PROC_FS */
-
 static unsigned int init_chipset_cs5530(struct pci_dev *, const char *);
 static void init_hwif_cs5530(ide_hwif_t *);
 
--- diff/drivers/ide/pci/hpt34x.c	2004-02-18 08:54:09.000000000 +0000
+++ source/drivers/ide/pci/hpt34x.c	2004-02-23 13:56:41.000000000 +0000
@@ -282,7 +282,7 @@ static unsigned int __init init_chipset_
 
 	if (!hpt34x_proc) {
 		hpt34x_proc = 1;
-		ide_pci_register_host_proc(&hpt34x_procs[0]);
+		ide_pci_create_host_proc("hpt34x", hpt34x_get_info);
 	}
 #endif /* DISPLAY_HPT34X_TIMINGS && CONFIG_PROC_FS */
 
--- diff/drivers/ide/pci/hpt34x.h	2004-02-18 08:54:09.000000000 +0000
+++ source/drivers/ide/pci/hpt34x.h	2004-02-23 13:56:41.000000000 +0000
@@ -13,24 +13,6 @@
 
 #undef DISPLAY_HPT34X_TIMINGS
 
-#if defined(DISPLAY_HPT34X_TIMINGS) && defined(CONFIG_PROC_FS)
-#include <linux/stat.h>
-#include <linux/proc_fs.h>
-
-static u8 hpt34x_proc;
-
-static int hpt34x_get_info(char *, char **, off_t, int);
-
-static ide_pci_host_proc_t hpt34x_procs[] = {
-	{
-		.name		= "hpt34x",
-		.set		= 1,
-		.get_info	= hpt34x_get_info,
-		.parent		= NULL,
-	},
-};
-#endif  /* defined(DISPLAY_HPT34X_TIMINGS) && defined(CONFIG_PROC_FS) */
-
 static unsigned int init_chipset_hpt34x(struct pci_dev *, const char *);
 static void init_hwif_hpt34x(ide_hwif_t *);
 
--- diff/drivers/ide/pci/hpt366.c	2004-02-18 08:54:09.000000000 +0000
+++ source/drivers/ide/pci/hpt366.c	2004-02-23 13:56:41.000000000 +0000
@@ -972,7 +972,7 @@ static unsigned int __init init_chipset_
 
 	if (!hpt366_proc) {
 		hpt366_proc = 1;
-		ide_pci_register_host_proc(&hpt366_procs[0]);
+		ide_pci_create_host_proc("hpt366", hpt366_get_info);
 	}
 #endif /* DISPLAY_HPT366_TIMINGS && CONFIG_PROC_FS */
 
--- diff/drivers/ide/pci/hpt366.h	2004-02-18 08:54:09.000000000 +0000
+++ source/drivers/ide/pci/hpt366.h	2004-02-23 13:56:41.000000000 +0000
@@ -416,24 +416,6 @@ struct chipset_bus_clock_list_entry sixt
 #define F_LOW_PCI_50      0x2d
 #define F_LOW_PCI_66      0x42
 
-#if defined(DISPLAY_HPT366_TIMINGS) && defined(CONFIG_PROC_FS)
-#include <linux/stat.h>
-#include <linux/proc_fs.h>
-
-static u8 hpt366_proc;
-
-static int hpt366_get_info(char *, char **, off_t, int);
-
-static ide_pci_host_proc_t hpt366_procs[] = {
-	{
-		.name		= "hpt366",
-		.set		= 1,
-		.get_info	= hpt366_get_info,
-		.parent		= NULL,
-	},
-};
-#endif  /* defined(DISPLAY_HPT366_TIMINGS) && defined(CONFIG_PROC_FS) */
-
 static void init_setup_hpt366(struct pci_dev *, ide_pci_device_t *);
 static void init_setup_hpt37x(struct pci_dev *, ide_pci_device_t *);
 static void init_setup_hpt374(struct pci_dev *, ide_pci_device_t *);
--- diff/drivers/ide/pci/pdc202xx_new.c	2004-02-18 08:54:09.000000000 +0000
+++ source/drivers/ide/pci/pdc202xx_new.c	2004-02-23 13:56:41.000000000 +0000
@@ -574,7 +574,7 @@ static unsigned int __init init_chipset_
 
 	if (!pdcnew_proc) {
 		pdcnew_proc = 1;
-		ide_pci_register_host_proc(&pdcnew_procs[0]);
+		ide_pci_create_host_proc("pdcnew", pdcnew_get_info);
 	}
 #endif /* DISPLAY_PDC202XX_TIMINGS && CONFIG_PROC_FS */
 
--- diff/drivers/ide/pci/pdc202xx_new.h	2004-02-18 08:54:09.000000000 +0000
+++ source/drivers/ide/pci/pdc202xx_new.h	2004-02-23 13:56:41.000000000 +0000
@@ -164,25 +164,6 @@ static void decode_registers (u8 registe
 
 #define DISPLAY_PDC202XX_TIMINGS
 
-#if defined(DISPLAY_PDC202XX_TIMINGS) && defined(CONFIG_PROC_FS)
-#include <linux/stat.h>
-#include <linux/proc_fs.h>
-
-static u8 pdcnew_proc;
-
-static int pdcnew_get_info(char *, char **, off_t, int);
-
-static ide_pci_host_proc_t pdcnew_procs[] = {
-	{
-		.name		= "pdcnew",
-		.set		= 1,
-		.get_info	= pdcnew_get_info,
-		.parent		= NULL,
-	},
-};
-#endif /* DISPLAY_PDC202XX_TIMINGS && CONFIG_PROC_FS */
-
-
 static void init_setup_pdcnew(struct pci_dev *, ide_pci_device_t *);
 static void init_setup_pdc20270(struct pci_dev *, ide_pci_device_t *);
 static void init_setup_pdc20276(struct pci_dev *dev, ide_pci_device_t *d);
--- diff/drivers/ide/pci/pdc202xx_old.c	2004-02-18 08:54:09.000000000 +0000
+++ source/drivers/ide/pci/pdc202xx_old.c	2004-02-23 13:56:41.000000000 +0000
@@ -707,7 +707,7 @@ static unsigned int __init init_chipset_
 
 	if (!pdc202xx_proc) {
 		pdc202xx_proc = 1;
-		ide_pci_register_host_proc(&pdc202xx_procs[0]);
+		ide_pci_create_host_proc("pdc202xx", pdc202xx_get_info);
 	}
 #endif /* DISPLAY_PDC202XX_TIMINGS && CONFIG_PROC_FS */
 
--- diff/drivers/ide/pci/pdc202xx_old.h	2004-02-18 08:54:09.000000000 +0000
+++ source/drivers/ide/pci/pdc202xx_old.h	2004-02-23 13:56:41.000000000 +0000
@@ -199,25 +199,6 @@ static void decode_registers (u8 registe
 
 #define DISPLAY_PDC202XX_TIMINGS
 
-#if defined(DISPLAY_PDC202XX_TIMINGS) && defined(CONFIG_PROC_FS)
-#include <linux/stat.h>
-#include <linux/proc_fs.h>
-
-static u8 pdc202xx_proc;
-
-static int pdc202xx_get_info(char *, char **, off_t, int);
-
-static ide_pci_host_proc_t pdc202xx_procs[] = {
-	{
-		.name		= "pdc202xx",
-		.set		= 1,
-		.get_info	= pdc202xx_get_info,
-		.parent		= NULL,
-	},
-};
-#endif /* DISPLAY_PDC202XX_TIMINGS && CONFIG_PROC_FS */
-
-
 static void init_setup_pdc202ata4(struct pci_dev *dev, ide_pci_device_t *d);
 static void init_setup_pdc20265(struct pci_dev *, ide_pci_device_t *);
 static void init_setup_pdc202xx(struct pci_dev *, ide_pci_device_t *);
--- diff/drivers/ide/pci/piix.c	2004-02-18 08:54:09.000000000 +0000
+++ source/drivers/ide/pci/piix.c	2004-02-23 13:56:41.000000000 +0000
@@ -636,7 +636,7 @@ static unsigned int __devinit init_chips
 
 	if (!piix_proc) {
 		piix_proc = 1;
-		ide_pci_register_host_proc(&piix_procs[0]);
+		ide_pci_create_host_proc("piix", piix_get_info);
 	}
 #endif /* DISPLAY_PIIX_TIMINGS && CONFIG_PROC_FS */
 	return 0;
--- diff/drivers/ide/pci/piix.h	2004-02-18 08:54:09.000000000 +0000
+++ source/drivers/ide/pci/piix.h	2004-02-23 13:56:41.000000000 +0000
@@ -9,24 +9,6 @@
 
 #define DISPLAY_PIIX_TIMINGS
 
-#if defined(DISPLAY_PIIX_TIMINGS) && defined(CONFIG_PROC_FS)
-#include <linux/stat.h>
-#include <linux/proc_fs.h>
-
-static u8 piix_proc;
-
-static int piix_get_info(char *, char **, off_t, int);
-
-static ide_pci_host_proc_t piix_procs[] = {
-	{
-		.name		= "piix",
-		.set		= 1,
-		.get_info	= piix_get_info,
-		.parent		= NULL,
-	},
-};
-#endif  /* defined(DISPLAY_PIIX_TIMINGS) && defined(CONFIG_PROC_FS) */
-
 static void init_setup_piix(struct pci_dev *, ide_pci_device_t *);
 static unsigned int __devinit init_chipset_piix(struct pci_dev *, const char *);
 static void init_hwif_piix(ide_hwif_t *);
--- diff/drivers/ide/pci/sc1200.c	2004-02-18 08:54:09.000000000 +0000
+++ source/drivers/ide/pci/sc1200.c	2004-02-23 13:56:41.000000000 +0000
@@ -515,7 +515,7 @@ static unsigned int __init init_chipset_
 	if (!bmide_dev) {
 		sc1200_proc = 1;
 		bmide_dev = dev;
-		ide_pci_register_host_proc(&sc1200_procs[0]);
+		ide_pci_create_host_proc("sc1200", sc1200_get_info);
 	}
 #endif /* DISPLAY_SC1200_TIMINGS && CONFIG_PROC_FS */
 	return 0;
--- diff/drivers/ide/pci/sc1200.h	2004-02-18 08:54:09.000000000 +0000
+++ source/drivers/ide/pci/sc1200.h	2004-02-23 13:56:41.000000000 +0000
@@ -7,24 +7,6 @@
 
 #define DISPLAY_SC1200_TIMINGS
 
-#if defined(DISPLAY_SC1200_TIMINGS) && defined(CONFIG_PROC_FS)
-#include <linux/stat.h>
-#include <linux/proc_fs.h>
-
-static u8 sc1200_proc;
-
-static int sc1200_get_info(char *, char **, off_t, int);
-
-static ide_pci_host_proc_t sc1200_procs[] = {
-	{
-		.name		= "sc1200",
-		.set		= 1,
-		.get_info	= sc1200_get_info,
-		.parent		= NULL,
-	},
-};
-#endif /* DISPLAY_SC1200_TIMINGS && CONFIG_PROC_FS */
-
 static unsigned int init_chipset_sc1200(struct pci_dev *, const char *);
 static void init_hwif_sc1200(ide_hwif_t *);
 
--- diff/drivers/ide/pci/serverworks.c	2004-02-18 08:54:09.000000000 +0000
+++ source/drivers/ide/pci/serverworks.c	2004-02-23 13:56:41.000000000 +0000
@@ -621,7 +621,7 @@ static unsigned int __init init_chipset_
 
 	if (!svwks_proc) {
 		svwks_proc = 1;
-		ide_pci_register_host_proc(&svwks_procs[0]);
+		ide_pci_create_host_proc("svwks", svwks_get_info);
 	}
 #endif /* DISPLAY_SVWKS_TIMINGS && CONFIG_PROC_FS */
 
--- diff/drivers/ide/pci/serverworks.h	2004-02-18 08:54:09.000000000 +0000
+++ source/drivers/ide/pci/serverworks.h	2004-02-23 13:56:41.000000000 +0000
@@ -23,24 +23,6 @@ const char *svwks_bad_ata100[] = {
 
 #define DISPLAY_SVWKS_TIMINGS	1
 
-#if defined(DISPLAY_SVWKS_TIMINGS) && defined(CONFIG_PROC_FS)
-#include <linux/stat.h>
-#include <linux/proc_fs.h>
-
-static u8 svwks_proc;
-
-static int svwks_get_info(char *, char **, off_t, int);
-
-static ide_pci_host_proc_t svwks_procs[] = {
-{
-		.name		= "svwks",
-		.set		= 1,
-		.get_info	= svwks_get_info,
-		.parent		= NULL,
-	},
-};
-#endif  /* defined(DISPLAY_SVWKS_TIMINGS) && defined(CONFIG_PROC_FS) */
-
 static void init_setup_svwks(struct pci_dev *, ide_pci_device_t *);
 static void init_setup_csb6(struct pci_dev *, ide_pci_device_t *);
 static unsigned int init_chipset_svwks(struct pci_dev *, const char *);
--- diff/drivers/ide/pci/siimage.c	2004-02-18 08:54:09.000000000 +0000
+++ source/drivers/ide/pci/siimage.c	2004-02-23 13:56:41.000000000 +0000
@@ -1,5 +1,5 @@
 /*
- * linux/drivers/ide/pci/siimage.c		Version 1.06	June 11, 2003
+ * linux/drivers/ide/pci/siimage.c		Version 1.07	Nov 30, 2003
  *
  * Copyright (C) 2001-2002	Andre Hedrick <andre@linux-ide.org>
  * Copyright (C) 2003		Red Hat <alan@redhat.com>
@@ -785,7 +785,7 @@ static void proc_reports_siimage (struct
 
 	if (!siimage_proc) {
 		siimage_proc = 1;
-		ide_pci_register_host_proc(&siimage_procs[0]);
+		ide_pci_create_host_proc("siimage", siimage_get_info);
 	}
 #endif /* DISPLAY_SIIMAGE_TIMINGS && CONFIG_PROC_FS */
 }
@@ -1046,6 +1046,27 @@ static void __init init_mmio_iops_siimag
 	hwif->mmio			= 2;
 }
 
+static int is_dev_seagate_sata(ide_drive_t *drive)
+{
+	const char *s = &drive->id->model[0];
+	unsigned len;
+
+	if (!drive->present)
+		return 0;
+
+	len = strnlen(s, sizeof(drive->id->model));
+
+	if ((len > 4) && (!memcmp(s, "ST", 2))) {
+		if ((!memcmp(s + len - 2, "AS", 2)) ||
+		    (!memcmp(s + len - 3, "ASL", 3))) {
+			printk(KERN_INFO "%s: applying pessimistic Seagate "
+					 "errata fix\n", drive->name);
+			return 1;
+		}
+	}
+	return 0;
+}
+
 /**
  *	init_iops_siimage	-	set up iops
  *	@hwif: interface to set up
@@ -1067,7 +1088,7 @@ static void __init init_iops_siimage (id
 	hwif->hwif_data = 0;
 
 	hwif->rqsize = 128;
-	if (is_sata(hwif))
+	if (is_sata(hwif) && is_dev_seagate_sata(&hwif->drives[0]))
 		hwif->rqsize = 15;
 
 	if (pci_get_drvdata(dev) == NULL)
--- diff/drivers/ide/pci/siimage.h	2004-02-18 08:54:09.000000000 +0000
+++ source/drivers/ide/pci/siimage.h	2004-02-23 13:56:41.000000000 +0000
@@ -21,26 +21,6 @@
 #define siiprintk(x...)
 #endif
 
-
-#if defined(DISPLAY_SIIMAGE_TIMINGS) && defined(CONFIG_PROC_FS)
-#include <linux/stat.h>
-#include <linux/proc_fs.h>
-
-static char * print_siimage_get_info(char *, struct pci_dev *, int);
-static int siimage_get_info(char *, char **, off_t, int);
-
-static u8 siimage_proc;
-
-static ide_pci_host_proc_t siimage_procs[] = {
-	{
-		.name		= "siimage",
-		.set		= 1,
-		.get_info	= siimage_get_info,
-		.parent		= NULL,
-	},
-};
-#endif /* DISPLAY_SIIMAGE_TIMINGS && CONFIG_PROC_FS */	
-
 static unsigned int init_chipset_siimage(struct pci_dev *, const char *);
 static void init_iops_siimage(ide_hwif_t *);
 static void init_hwif_siimage(ide_hwif_t *);
--- diff/drivers/ide/pci/sis5513.c	2004-02-18 08:54:09.000000000 +0000
+++ source/drivers/ide/pci/sis5513.c	2004-02-23 13:56:41.000000000 +0000
@@ -881,7 +881,7 @@ static unsigned int __init init_chipset_
 		if (!sis_proc) {
 			sis_proc = 1;
 			bmide_dev = dev;
-			ide_pci_register_host_proc(&sis_procs[0]);
+			ide_pci_create_host_proc("sis", sis_get_info);
 		}
 #endif
 	}
--- diff/drivers/ide/pci/sis5513.h	2004-02-18 08:54:09.000000000 +0000
+++ source/drivers/ide/pci/sis5513.h	2004-02-23 13:56:41.000000000 +0000
@@ -7,24 +7,6 @@
 
 #define DISPLAY_SIS_TIMINGS
 
-#if defined(DISPLAY_SIS_TIMINGS) && defined(CONFIG_PROC_FS)
-#include <linux/stat.h>
-#include <linux/proc_fs.h>
-
-static u8 sis_proc;
-
-static int sis_get_info(char *, char **, off_t, int);
-
-static ide_pci_host_proc_t sis_procs[] = {
-{
-		.name		= "sis",
-		.set		= 1,
-		.get_info	= sis_get_info,
-		.parent		= NULL,
-	},
-};
-#endif /* defined(DISPLAY_SIS_TIMINGS) && defined(CONFIG_PROC_FS) */
-
 static unsigned int init_chipset_sis5513(struct pci_dev *, const char *);
 static void init_hwif_sis5513(ide_hwif_t *);
 
--- diff/drivers/ide/pci/slc90e66.c	2004-02-18 08:54:09.000000000 +0000
+++ source/drivers/ide/pci/slc90e66.c	2004-02-23 13:56:41.000000000 +0000
@@ -319,7 +319,7 @@ static unsigned int __init init_chipset_
 	if (!slc90e66_proc) {
 		slc90e66_proc = 1;
 		bmide_dev = dev;
-		ide_pci_register_host_proc(&slc90e66_procs[0]);
+		ide_pci_create_host_proc("slc90e66", slc90e66_get_info);
 	}
 #endif /* DISPLAY_SLC90E66_TIMINGS && CONFIG_PROC_FS */
 	return 0;
--- diff/drivers/ide/pci/slc90e66.h	2004-02-18 08:54:09.000000000 +0000
+++ source/drivers/ide/pci/slc90e66.h	2004-02-23 13:56:41.000000000 +0000
@@ -9,24 +9,6 @@
 
 #define SLC90E66_DEBUG_DRIVE_INFO	0
 
-#if defined(DISPLAY_SLC90E66_TIMINGS) && defined(CONFIG_PROC_FS)
-#include <linux/stat.h>
-#include <linux/proc_fs.h>
-
-static u8 slc90e66_proc;
-
-static int slc90e66_get_info(char *, char **, off_t, int);
-
-static ide_pci_host_proc_t slc90e66_procs[] = {
-	{
-		.name		= "slc90e66",
-		.set		= 1,
-		.get_info	= slc90e66_get_info,
-		.parent		= NULL,
-	},
-};
-#endif	/* defined(DISPLAY_SLC90E66_TIMINGS) && defined(CONFIG_PROC_FS) */
-
 static unsigned int init_chipset_slc90e66(struct pci_dev *, const char *);
 static void init_hwif_slc90e66(ide_hwif_t *);
 
--- diff/drivers/ide/pci/triflex.c	2004-02-18 08:54:09.000000000 +0000
+++ source/drivers/ide/pci/triflex.c	2004-02-23 13:56:41.000000000 +0000
@@ -212,7 +212,7 @@ static unsigned int __init init_chipset_
 		const char *name) 
 {
 #ifdef CONFIG_PROC_FS
-	ide_pci_register_host_proc(&triflex_proc);
+	ide_pci_create_host_proc("triflex", triflex_get_info);
 #endif
 	return 0;	
 }
--- diff/drivers/ide/pci/triflex.h	2004-02-18 08:54:09.000000000 +0000
+++ source/drivers/ide/pci/triflex.h	2004-02-23 13:56:41.000000000 +0000
@@ -14,15 +14,6 @@
 
 static unsigned int __devinit init_chipset_triflex(struct pci_dev *, const char *);
 static void init_hwif_triflex(ide_hwif_t *);
-#ifdef CONFIG_PROC_FS
-static int triflex_get_info(char *, char **, off_t, int);
-
-static ide_pci_host_proc_t triflex_proc = {
-	.name		= "triflex",
-	.set		= 1,
-	.get_info 	= triflex_get_info,
-};
-#endif
 
 static ide_pci_device_t triflex_devices[] __devinitdata = {
 	{
--- diff/drivers/ide/pci/via82cxxx.c	2004-02-18 08:54:09.000000000 +0000
+++ source/drivers/ide/pci/via82cxxx.c	2004-02-23 13:56:41.000000000 +0000
@@ -567,7 +567,7 @@ static unsigned int __init init_chipset_
 		via_base = pci_resource_start(dev, 4);
 		bmide_dev = dev;
 		isa_dev = isa;
-		ide_pci_register_host_proc(&via_procs[0]);
+		ide_pci_create_host_proc("via", via_get_info);
 		via_proc = 1;
 	}
 #endif /* DISPLAY_VIA_TIMINGS && CONFIG_PROC_FS */
--- diff/drivers/ide/pci/via82cxxx.h	2004-02-18 08:54:09.000000000 +0000
+++ source/drivers/ide/pci/via82cxxx.h	2004-02-23 13:56:41.000000000 +0000
@@ -7,24 +7,6 @@
 
 #define DISPLAY_VIA_TIMINGS
 
-#if defined(DISPLAY_VIA_TIMINGS) && defined(CONFIG_PROC_FS)
-#include <linux/stat.h>
-#include <linux/proc_fs.h>
-
-static u8 via_proc;
-
-static int via_get_info(char *, char **, off_t, int);
-
-static ide_pci_host_proc_t via_procs[] = {
-	{
-		.name		= "via",
-		.set		= 1,
-		.get_info	= via_get_info,
-		.parent		= NULL,
-	},
-};
-#endif /* DISPLAY_VIA_TIMINGS && CONFIG_PROC_FS */
-
 static unsigned int init_chipset_via82cxxx(struct pci_dev *, const char *);
 static void init_hwif_via82cxxx(ide_hwif_t *);
 
--- diff/drivers/ide/ppc/pmac.c	2004-02-18 08:54:09.000000000 +0000
+++ source/drivers/ide/ppc/pmac.c	2004-02-23 13:56:41.000000000 +0000
@@ -55,7 +55,7 @@ extern void ide_do_request(ide_hwgroup_t
 
 #define IDE_PMAC_DEBUG
 
-#define DMA_WAIT_TIMEOUT	100
+#define DMA_WAIT_TIMEOUT	50
 
 typedef struct pmac_ide_hwif {
 	unsigned long			regbase;
@@ -2026,8 +2026,11 @@ pmac_ide_dma_end (ide_drive_t *drive)
 	dstat = readl(&dma->status);
 	writel(((RUN|WAKE|DEAD) << 16), &dma->control);
 	pmac_ide_destroy_dmatable(drive);
-	/* verify good dma status */
-	return (dstat & (RUN|DEAD|ACTIVE)) != RUN;
+	/* verify good dma status. we don't check for ACTIVE beeing 0. We should...
+	 * in theory, but with ATAPI decices doing buffer underruns, that would
+	 * cause us to disable DMA, which isn't what we want
+	 */
+	return (dstat & (RUN|DEAD)) != RUN;
 }
 
 /*
@@ -2041,7 +2044,7 @@ pmac_ide_dma_test_irq (ide_drive_t *driv
 {
 	pmac_ide_hwif_t* pmif = (pmac_ide_hwif_t *)HWIF(drive)->hwif_data;
 	volatile struct dbdma_regs *dma;
-	unsigned long status;
+	unsigned long status, timeout;
 
 	if (pmif == NULL)
 		return 0;
@@ -2057,17 +2060,8 @@ pmac_ide_dma_test_irq (ide_drive_t *driv
 	 * - The dbdma fifo hasn't yet finished flushing to
 	 * to system memory when the disk interrupt occurs.
 	 * 
-	 * The trick here is to increment drive->waiting_for_dma,
-	 * and return as if no interrupt occurred. If the counter
-	 * reach a certain timeout value, we then return 1. If
-	 * we really got the interrupt, it will happen right away
-	 * again.
-	 * Apple's solution here may be more elegant. They issue
-	 * a DMA channel interrupt (a separate irq line) via a DBDMA
-	 * NOP command just before the STOP, and wait for both the
-	 * disk and DBDMA interrupts to have completed.
 	 */
- 
+
 	/* If ACTIVE is cleared, the STOP command have passed and
 	 * transfer is complete.
 	 */
@@ -2079,15 +2073,26 @@ pmac_ide_dma_test_irq (ide_drive_t *driv
 			called while not waiting\n", HWIF(drive)->index);
 
 	/* If dbdma didn't execute the STOP command yet, the
-	 * active bit is still set */
-	drive->waiting_for_dma++;
-	if (drive->waiting_for_dma >= DMA_WAIT_TIMEOUT) {
-		printk(KERN_WARNING "ide%d, timeout waiting \
-			for dbdma command stop\n", HWIF(drive)->index);
-		return 1;
-	}
-	udelay(5);
-	return 0;
+	 * active bit is still set. We consider that we aren't
+	 * sharing interrupts (which is hopefully the case with
+	 * those controllers) and so we just try to flush the
+	 * channel for pending data in the fifo
+	 */
+	udelay(1);
+	writel((FLUSH << 16) | FLUSH, &dma->control);
+	timeout = 0;
+	for (;;) {
+		udelay(1);
+		status = readl(&dma->status);
+		if ((status & FLUSH) == 0)
+			break;
+		if (++timeout > 100) {
+			printk(KERN_WARNING "ide%d, ide_dma_test_irq \
+			timeout flushing channel\n", HWIF(drive)->index);
+			break;
+		}
+	}	
+	return 1;
 }
 
 static int __pmac
--- diff/drivers/ide/setup-pci.c	2004-02-18 08:54:09.000000000 +0000
+++ source/drivers/ide/setup-pci.c	2004-02-23 13:56:41.000000000 +0000
@@ -749,6 +749,8 @@ void ide_setup_pci_device (struct pci_de
 		probe_hwif_init(&ide_hwifs[index_list.b.low]);
 	if ((index_list.b.high & 0xf0) != 0xf0)
 		probe_hwif_init(&ide_hwifs[index_list.b.high]);
+
+	create_proc_ide_interfaces();
 }
 
 EXPORT_SYMBOL_GPL(ide_setup_pci_device);
@@ -766,6 +768,8 @@ void ide_setup_pci_devices (struct pci_d
 		probe_hwif_init(&ide_hwifs[index_list2.b.low]);
 	if ((index_list2.b.high & 0xf0) != 0xf0)
 		probe_hwif_init(&ide_hwifs[index_list2.b.high]);
+
+	create_proc_ide_interfaces();
 }
 
 EXPORT_SYMBOL_GPL(ide_setup_pci_devices);
--- diff/drivers/ieee1394/Kconfig	2004-02-09 10:36:10.000000000 +0000
+++ source/drivers/ieee1394/Kconfig	2004-02-23 13:56:41.000000000 +0000
@@ -1,10 +1,9 @@
 # -*- shell-script -*-
 
-menu "IEEE 1394 (FireWire) support (EXPERIMENTAL)"
-	depends on EXPERIMENTAL
+menu "IEEE 1394 (FireWire) support"
 
 config IEEE1394
-	tristate "IEEE 1394 (FireWire) support (EXPERIMENTAL)"
+	tristate "IEEE 1394 (FireWire) support"
 	help
 	  IEEE 1394 describes a high performance serial bus, which is also
 	  known as FireWire(tm) or i.Link(tm) and is used for connecting all
@@ -108,10 +107,14 @@ config IEEE1394_SBP2_PHYS_DMA
 
 config IEEE1394_ETH1394
 	tristate "Ethernet over 1394"
-	depends on IEEE1394
+	depends on IEEE1394 && EXPERIMENTAL
 	help
-	  Extremely Experimental! This driver is a Linux specific way to use your
-	  IEEE1394 Host as an Ethernet type device. This is _NOT_ IP1394.
+	  This driver implements a functional majority of RFC 2734: IPv4 over
+	  1394.  It will provide IP connectivity with implementations of RFC
+	  2734 found on other operating systems.  It will not communicate with
+	  older versions of this driver found in stock kernels prior to 2.6.3.
+	  This driver is still considered experimental.  It does not yet support
+	  MCAP, therefore multicast support is significantly limited.
 
 config IEEE1394_DV1394
 	tristate "OHCI-DV I/O support"
--- diff/drivers/ieee1394/Makefile	2003-09-17 12:28:06.000000000 +0100
+++ source/drivers/ieee1394/Makefile	2004-02-23 13:56:41.000000000 +0000
@@ -3,7 +3,8 @@
 #
 
 ieee1394-objs := ieee1394_core.o ieee1394_transactions.o hosts.o \
-		 highlevel.o csr.o nodemgr.o oui.o dma.o iso.o
+		 highlevel.o csr.o nodemgr.o oui.o dma.o iso.o \
+		 csr1212.o
 
 obj-$(CONFIG_IEEE1394) += ieee1394.o
 obj-$(CONFIG_IEEE1394_PCILYNX) += pcilynx.o
--- diff/drivers/ieee1394/amdtp.c	2004-02-18 08:54:09.000000000 +0000
+++ source/drivers/ieee1394/amdtp.c	2004-02-23 13:56:41.000000000 +0000
@@ -862,14 +862,14 @@ static int stream_alloc_packet_lists(str
 
 static void stream_free_packet_lists(struct stream *s)
 {
-	struct list_head *lh, *next;
+	struct packet_list *packet_l, *packet_l_next;
 
 	if (s->current_packet_list != NULL)
 		packet_list_free(s->current_packet_list, s);
-	list_for_each_safe(lh, next, &s->dma_packet_lists)
-		packet_list_free(list_entry(lh, struct packet_list, link), s);
-	list_for_each_safe(lh, next, &s->free_packet_lists)
-		packet_list_free(list_entry(lh, struct packet_list, link), s);
+	list_for_each_entry_safe(packet_l, packet_l_next, &s->dma_packet_lists, link)
+		packet_list_free(packet_l, s);
+	list_for_each_entry_safe(packet_l, packet_l_next, &s->free_packet_lists, link)
+		packet_list_free(packet_l, s);
 	if (s->packet_pool != NULL)
 		pci_pool_destroy(s->packet_pool);
 
--- diff/drivers/ieee1394/csr.c	2004-02-09 10:36:10.000000000 +0000
+++ source/drivers/ieee1394/csr.c	2004-02-23 13:56:41.000000000 +0000
@@ -23,6 +23,7 @@
 #include <linux/param.h>
 #include <linux/spinlock.h>
 
+#include "csr1212.h"
 #include "ieee1394_types.h"
 #include "hosts.h"
 #include "ieee1394.h"
@@ -35,7 +36,10 @@ static int fcp = 1;
 module_param(fcp, int, 0444);
 MODULE_PARM_DESC(fcp, "Map FCP registers (default = 1, disable = 0).");
 
+static struct csr1212_keyval *node_cap = NULL;
+
 static void add_host(struct hpsb_host *host);
+static void remove_host(struct hpsb_host *host);
 static void host_reset(struct hpsb_host *host);
 static int read_maps(struct hpsb_host *host, int nodeid, quadlet_t *buffer,
 		     u64 addr, size_t length, u16 fl);
@@ -49,10 +53,15 @@ static int lock_regs(struct hpsb_host *h
 		     u64 addr, quadlet_t data, quadlet_t arg, int extcode, u16 fl);
 static int lock64_regs(struct hpsb_host *host, int nodeid, octlet_t * store,
 		       u64 addr, octlet_t data, octlet_t arg, int extcode, u16 fl);
+static int read_config_rom(struct hpsb_host *host, int nodeid, quadlet_t *buffer,
+			   u64 addr, size_t length, u16 fl);
+static u64 allocate_addr_range(u64 size, u32 alignment, void *__host);
+static void release_addr_range(u64 addr, void *__host);
 
 static struct hpsb_highlevel csr_highlevel = {
 	.name =		"standard registers",
 	.add_host =	add_host,
+	.remove_host =	remove_host,
 	.host_reset =	host_reset,
 };
 
@@ -71,6 +80,15 @@ static struct hpsb_address_ops reg_ops =
 	.lock64 = lock64_regs,
 };
 
+static struct hpsb_address_ops config_rom_ops = {
+	.read = read_config_rom,
+};
+
+struct csr1212_bus_ops csr_bus_ops = {
+	.allocate_addr_range =	allocate_addr_range,
+	.release_addr =		release_addr_range,
+};
+
 
 static u16 csr_crc16(unsigned *data, int length)
 {
@@ -162,10 +180,13 @@ static inline void calculate_expire(stru
 
 static void add_host(struct hpsb_host *host)
 {
+	struct csr1212_keyval *root;
+	quadlet_t bus_info[CSR_BUS_INFO_SIZE];
+
 	hpsb_register_addrspace(&csr_highlevel, host, &reg_ops,
 				CSR_REGISTER_BASE,
 				CSR_REGISTER_BASE + CSR_CONFIG_ROM);
-	hpsb_register_addrspace(&csr_highlevel, host, &map_ops,
+	hpsb_register_addrspace(&csr_highlevel, host, &config_rom_ops,
 				CSR_REGISTER_BASE + CSR_CONFIG_ROM,
 				CSR_REGISTER_BASE + CSR_CONFIG_ROM_END);
 	if (fcp) {
@@ -182,8 +203,6 @@ static void add_host(struct hpsb_host *h
 
         host->csr.lock = SPIN_LOCK_UNLOCKED;
 
-        host->csr.rom_size = host->driver->get_rom(host, &host->csr.rom);
-        host->csr.rom_version           = 0;
         host->csr.state                 = 0;
         host->csr.node_ids              = 0;
         host->csr.split_timeout_hi      = 0;
@@ -202,43 +221,100 @@ static void add_host(struct hpsb_host *h
 			host->driver->hw_csr_reg(host, 2, 0xfffffffe, ~0);
 		}
 	}
+
+	if (host->csr.max_rec >= 9)
+		host->csr.max_rom = 2;
+	else if (host->csr.max_rec >= 5)
+		host->csr.max_rom = 1;
+	else
+		host->csr.max_rom = 0;
+
+	host->csr.generation = 2;
+
+	bus_info[1] = __constant_cpu_to_be32(0x31333934);
+	bus_info[2] = cpu_to_be32((1 << CSR_IRMC_SHIFT) |
+				  (1 << CSR_CMC_SHIFT) |
+				  (1 << CSR_ISC_SHIFT) |
+				  (0 << CSR_BMC_SHIFT) |
+				  (0 << CSR_PMC_SHIFT) |
+				  (host->csr.cyc_clk_acc << CSR_CYC_CLK_ACC_SHIFT) |
+				  (host->csr.max_rec << CSR_MAX_REC_SHIFT) |
+				  (host->csr.max_rom << CSR_MAX_ROM_SHIFT) |
+				  (host->csr.generation << CSR_GENERATION_SHIFT) |
+				  host->csr.lnk_spd);
+
+	bus_info[3] = cpu_to_be32(host->csr.guid_hi);
+	bus_info[4] = cpu_to_be32(host->csr.guid_lo);
+
+	/* The hardware copy of the bus info block will be set later when a
+	 * bus reset is issued. */
+
+	csr1212_init_local_csr(host->csr.rom, bus_info, host->csr.max_rom);
+
+	host->csr.rom->max_rom = host->csr.max_rom;
+
+	root = host->csr.rom->root_kv;
+
+	if(csr1212_attach_keyval_to_directory(root, node_cap) != CSR1212_SUCCESS) {
+		HPSB_ERR("Failed to attach Node Capabilities to root directory");
+	}
+
+	host->update_config_rom = 1;
 }
 
-int hpsb_update_config_rom(struct hpsb_host *host, const quadlet_t *new_rom, 
-	size_t size, unsigned char rom_version)
+static void remove_host(struct hpsb_host *host)
 {
-	unsigned long flags;
-	int ret;
+	quadlet_t bus_info[CSR_BUS_INFO_SIZE];
 
-        spin_lock_irqsave(&host->csr.lock, flags); 
-        if (rom_version != host->csr.rom_version)
-                 ret = -1;
-        else if (size > (CSR_CONFIG_ROM_SIZE << 2))
-                 ret = -2;
-        else {
-                 memcpy(host->csr.rom,new_rom,size);
-                 host->csr.rom_size=size;
-                 host->csr.rom_version++;
-                 ret=0;
-        }
-        spin_unlock_irqrestore(&host->csr.lock, flags);
-        return ret;
+	bus_info[1] = __constant_cpu_to_be32(0x31333934);
+	bus_info[2] = cpu_to_be32((0 << CSR_IRMC_SHIFT) |
+				  (0 << CSR_CMC_SHIFT) |
+				  (0 << CSR_ISC_SHIFT) |
+				  (0 << CSR_BMC_SHIFT) |
+				  (0 << CSR_PMC_SHIFT) |
+				  (host->csr.cyc_clk_acc << CSR_CYC_CLK_ACC_SHIFT) |
+				  (host->csr.max_rec << CSR_MAX_REC_SHIFT) |
+				  (0 << CSR_MAX_ROM_SHIFT) |
+				  (0 << CSR_GENERATION_SHIFT) |
+				  host->csr.lnk_spd);
+
+	bus_info[3] = cpu_to_be32(host->csr.guid_hi);
+	bus_info[4] = cpu_to_be32(host->csr.guid_lo);
+
+	csr1212_detach_keyval_from_directory(host->csr.rom->root_kv, node_cap);
+
+	csr1212_init_local_csr(host->csr.rom, bus_info, 0);
+	host->update_config_rom = 1;
 }
 
-int hpsb_get_config_rom(struct hpsb_host *host, quadlet_t *buffer, 
-	size_t buffersize, size_t *rom_size, unsigned char *rom_version)
+
+int hpsb_update_config_rom(struct hpsb_host *host, const quadlet_t *new_rom, 
+	size_t buffersize, unsigned char rom_version)
 {
 	unsigned long flags;
 	int ret;
 
+	HPSB_NOTICE("hpsb_update_config_rom() is deprecated");
+
         spin_lock_irqsave(&host->csr.lock, flags); 
-        *rom_version=host->csr.rom_version;
-        *rom_size=host->csr.rom_size;
-        if (buffersize < host->csr.rom_size)
-                 ret = -1;
+	if (rom_version != host->csr.generation)
+                ret = -1;
+	else if (buffersize > host->csr.rom->cache_head->size)
+		ret = -2;
         else {
-                 memcpy(buffer,host->csr.rom,host->csr.rom_size);
-                 ret=0;
+		/* Just overwrite the generated ConfigROM image with new data,
+		 * it can be regenerated later. */
+		memcpy(host->csr.rom->cache_head->data, new_rom, buffersize);
+		host->csr.rom->cache_head->len = buffersize;
+
+		if (host->driver->set_hw_config_rom)
+			host->driver->set_hw_config_rom(host, host->csr.rom->bus_info_data);
+		/* Increment the generation number to keep some sort of sync
+		 * with the newer ConfigROM manipulation method. */
+		host->csr.generation++;
+		if (host->csr.generation > 0xf || host->csr.generation < 2)
+			host->csr.generation = 2;
+		ret=0;
         }
         spin_unlock_irqrestore(&host->csr.lock, flags);
         return ret;
@@ -255,13 +331,7 @@ static int read_maps(struct hpsb_host *h
 
         spin_lock_irqsave(&host->csr.lock, flags); 
 
-        if (csraddr < CSR_TOPOLOGY_MAP) {
-                if (csraddr + length > CSR_CONFIG_ROM + host->csr.rom_size) {
-                        spin_unlock_irqrestore(&host->csr.lock, flags);
-                        return RCODE_ADDRESS_ERROR;
-                }
-                src = ((char *)host->csr.rom) + csraddr - CSR_CONFIG_ROM;
-        } else if (csraddr < CSR_SPEED_MAP) {
+	if (csraddr < CSR_SPEED_MAP) {
                 src = ((char *)host->csr.topology_map) + csraddr 
                         - CSR_TOPOLOGY_MAP;
         } else {
@@ -738,14 +808,52 @@ static int write_fcp(struct hpsb_host *h
         return RCODE_COMPLETE;
 }
 
+static int read_config_rom(struct hpsb_host *host, int nodeid, quadlet_t *buffer,
+			   u64 addr, size_t length, u16 fl)
+{
+	u32 offset = addr - CSR1212_REGISTER_SPACE_BASE;
 
+	if (csr1212_read(host->csr.rom, offset, buffer, length) == CSR1212_SUCCESS)
+		return RCODE_COMPLETE;
+	else
+		return RCODE_ADDRESS_ERROR;
+}
 
-void init_csr(void)
+static u64 allocate_addr_range(u64 size, u32 alignment, void *__host)
 {
+ 	struct hpsb_host *host = (struct hpsb_host*)__host;
+
+	return hpsb_allocate_and_register_addrspace(&csr_highlevel,
+						    host,
+						    &config_rom_ops,
+						    size, alignment,
+						    CSR1212_UNITS_SPACE_BASE,
+						    CSR1212_UNITS_SPACE_END);
+}
+
+static void release_addr_range(u64 addr, void *__host)
+{
+ 	struct hpsb_host *host = (struct hpsb_host*)__host;
+	hpsb_unregister_addrspace(&csr_highlevel, host, addr);
+}
+
+
+int init_csr(void)
+{
+	node_cap = csr1212_new_immediate(CSR1212_KV_ID_NODE_CAPABILITIES, 0x0083c0);
+	if (!node_cap) {
+		HPSB_ERR("Failed to allocate memory for Node Capabilties ConfigROM entry!");
+		return -ENOMEM;
+	}
+
 	hpsb_register_highlevel(&csr_highlevel);
+
+	return 0;
 }
 
 void cleanup_csr(void)
 {
+	if (node_cap)
+		csr1212_release_keyval(node_cap);
         hpsb_unregister_highlevel(&csr_highlevel);
 }
--- diff/drivers/ieee1394/csr.h	2003-08-20 14:16:09.000000000 +0100
+++ source/drivers/ieee1394/csr.h	2004-02-23 13:56:41.000000000 +0000
@@ -6,6 +6,8 @@
 #include <linux/sched.h>
 #endif
 
+#include "csr1212.h"
+
 #define CSR_REGISTER_BASE  0xfffff0000000ULL
 
 /* register offsets relative to CSR_REGISTER_BASE */
@@ -34,6 +36,27 @@
 #define CSR_SPEED_MAP             0x2000
 #define CSR_SPEED_MAP_END         0x3000
 
+/* IEEE 1394 bus specific Configuration ROM Key IDs */
+#define IEEE1394_KV_ID_POWER_REQUIREMENTS (0x30)
+
+/* IEEE 1394 Bus Inforamation Block specifics */
+#define CSR_BUS_INFO_SIZE (5 * sizeof(quadlet_t))
+
+#define CSR_IRMC_SHIFT 31
+#define CSR_CMC_SHIFT  30
+#define CSR_ISC_SHIFT  29
+#define CSR_BMC_SHIFT  28
+#define CSR_PMC_SHIFT  27
+#define CSR_CYC_CLK_ACC_SHIFT 16
+#define CSR_MAX_REC_SHIFT 12
+#define CSR_MAX_ROM_SHIFT 8
+#define CSR_GENERATION_SHIFT 4
+
+#define CSR_SET_BUS_INFO_GENERATION(csr, gen)				\
+	((csr)->bus_info_data[2] =					\
+		cpu_to_be32((be32_to_cpu((csr)->bus_info_data[2]) &	\
+			     ~(0xf << CSR_GENERATION_SHIFT)) |          \
+			    (gen) << CSR_GENERATION_SHIFT))
 
 struct csr_control {
         spinlock_t lock;
@@ -49,17 +72,25 @@ struct csr_control {
         quadlet_t channels_available_hi, channels_available_lo;
 	quadlet_t broadcast_channel;
 
-        quadlet_t *rom;
-        size_t rom_size;
-        unsigned char rom_version;
+	/* Bus Info */
+	quadlet_t guid_hi, guid_lo;
+	u8 cyc_clk_acc;
+	u8 max_rec;
+	u8 max_rom;
+	u8 generation;	/* Only use values between 0x2 and 0xf */
+	u8 lnk_spd;
+
+	unsigned long gen_timestamp[16];
 
+	struct csr1212_csr *rom;
 
         quadlet_t topology_map[256];
         quadlet_t speed_map[1024];
 };
 
+extern struct csr1212_bus_ops csr_bus_ops;
 
-void init_csr(void);
+int init_csr(void);
 void cleanup_csr(void);
 
 #endif /* _IEEE1394_CSR_H */
--- diff/drivers/ieee1394/dv1394.c	2004-02-18 08:54:09.000000000 +0000
+++ source/drivers/ieee1394/dv1394.c	2004-02-23 13:56:41.000000000 +0000
@@ -1801,15 +1801,12 @@ static int dv1394_open(struct inode *ino
 		
 	} else {
 		/* look up the card by ID */
-		
-		struct list_head *lh;
 		unsigned long flags;
 		
 		spin_lock_irqsave(&dv1394_cards_lock, flags);
 		if (!list_empty(&dv1394_cards)) {
 			struct video_card *p;
-			list_for_each(lh, &dv1394_cards) {
-				p = list_entry(lh, struct video_card, list);
+			list_for_each_entry(p, &dv1394_cards, list) {
 				if ((p->id) == ieee1394_file_to_instance(file)) {
 					video = p;
 					break;
@@ -2374,7 +2371,6 @@ static void dv1394_host_reset(struct hps
 	struct ti_ohci *ohci;
 	struct video_card *video = NULL;
 	unsigned long flags;
-	struct list_head *lh;
 	
 	/* We only work with the OHCI-1394 driver */
 	if (strcmp(host->driver->name, OHCI1394_DRIVER_NAME))
@@ -2386,8 +2382,7 @@ static void dv1394_host_reset(struct hps
 	/* find the corresponding video_cards */
 	spin_lock_irqsave(&dv1394_cards_lock, flags);
 	if (!list_empty(&dv1394_cards)) {
-		list_for_each(lh, &dv1394_cards) {
-			video = list_entry(lh, struct video_card, list);
+		list_for_each_entry(video, &dv1394_cards, list) {
 			if ((video->id >> 2) == ohci->id)
 				break;
 		}
--- diff/drivers/ieee1394/eth1394.c	2004-02-18 08:54:09.000000000 +0000
+++ source/drivers/ieee1394/eth1394.c	2004-02-23 13:56:41.000000000 +0000
@@ -29,7 +29,6 @@
  *
  * TODO:
  * RFC 2734 related:
- * - Add Config ROM entry
  * - Add MCAP. Limited Multicast exists only to 224.0.0.1 and 224.0.0.2.
  *
  * Non-RFC 2734 related:
@@ -38,7 +37,6 @@
  * - Convert kmalloc/kfree for link fragments to use kmem_cache_* instead
  * - Stability improvements
  * - Performance enhancements
- * - Change hardcoded 1394 bus address region to a dynamic memory space allocation
  * - Consider garbage collecting old partial datagrams after X amount of time
  */
 
@@ -69,6 +67,7 @@
 #include <asm/semaphore.h>
 #include <net/arp.h>
 
+#include "csr1212.h"
 #include "ieee1394_types.h"
 #include "ieee1394_core.h"
 #include "ieee1394_transactions.h"
@@ -89,7 +88,7 @@
 #define TRACE() printk(KERN_ERR "%s:%s[%d] ---- TRACE\n", driver_name, __FUNCTION__, __LINE__)
 
 static char version[] __devinitdata =
-	"$Rev: 1096 $ Ben Collins <bcollins@debian.org>";
+	"$Rev: 1133 $ Ben Collins <bcollins@debian.org>";
 
 struct fragment_info {
 	struct list_head list;
@@ -107,8 +106,35 @@ struct partial_datagram {
 	struct list_head frag_info;
 };
 
+static struct csr1212_keyval *eth1394_ud = NULL;
+
+struct pdg_list {
+	struct list_head list;		/* partial datagram list per node	*/
+	unsigned int sz;		/* partial datagram list size per node	*/
+	spinlock_t lock;		/* partial datagram lock		*/
+};
+
+struct eth1394_host_info {
+	struct hpsb_host *host;
+	struct net_device *dev;
+};
+
+struct eth1394_node_ref {
+	struct unit_directory *ud;
+	struct list_head list;
+};
+
+struct eth1394_node_info {
+	u16 maxpayload;			/* Max payload			*/
+	u8 sspd;			/* Max speed			*/
+	u64 fifo;			/* FIFO address			*/
+	struct pdg_list pdg;		/* partial RX datagram lists	*/
+	int dgl;			/* Outgoing datagram label	*/
+};
+
 /* Our ieee1394 highlevel driver */
-static const char driver_name[] = "eth1394";
+#define ETH1394_DRIVER_NAME "IP/1394"
+static const char driver_name[] = ETH1394_DRIVER_NAME;
 
 static kmem_cache_t *packet_task_cache;
 
@@ -188,94 +214,36 @@ static struct hpsb_highlevel eth1394_hig
 };
 
 
-static void eth1394_iso_shutdown(struct eth1394_priv *priv)
-{
-	priv->bc_state = ETHER1394_BC_CLOSED;
-
-	if (priv->iso != NULL) {
-		if (!in_interrupt())
-			hpsb_iso_shutdown(priv->iso);
-		priv->iso = NULL;
-	}
-}
-
-static int ether1394_init_bc(struct net_device *dev)
-{
-	struct eth1394_priv *priv = (struct eth1394_priv *)dev->priv;
-
-	/* First time sending?  Need a broadcast channel for ARP and for
-	 * listening on */
-	if (priv->bc_state == ETHER1394_BC_CHECK) {
-		quadlet_t bc;
-
-		/* Get the local copy of the broadcast channel and check its
-		 * validity (the IRM should validate it for us) */
-
-		bc = priv->host->csr.broadcast_channel;
-
-		if ((bc & 0xc0000000) != 0xc0000000) {
-			/* broadcast channel not validated yet */
-			ETH1394_PRINT(KERN_WARNING, dev->name,
-				      "Error BROADCAST_CHANNEL register valid "
-				      "bit not set, can't send IP traffic\n");
-
-			eth1394_iso_shutdown(priv);
-
-			return -EAGAIN;
-		}
-		if (priv->broadcast_channel != (bc & 0x3f)) {
-			/* This really shouldn't be possible, but just in case
-			 * the IEEE 1394 spec changes regarding broadcast
-			 * channels in the future. */
-
-			eth1394_iso_shutdown(priv);
-
-			if (in_interrupt())
-				return -EAGAIN;
-
-			priv->broadcast_channel = bc & 0x3f;
-			ETH1394_PRINT(KERN_INFO, dev->name,
-				      "Changing to broadcast channel %d...\n",
-				      priv->broadcast_channel);
-
-			priv->iso = hpsb_iso_recv_init(priv->host, 16 * 4096,
-						       16, priv->broadcast_channel,
-						       HPSB_ISO_DMA_PACKET_PER_BUFFER, 1, ether1394_iso);
-			if (priv->iso == NULL) {
-				ETH1394_PRINT(KERN_ERR, dev->name,
-					      "failed to change broadcast "
-					      "channel\n");
-				return -EAGAIN;
-			}
-		}
-		if (hpsb_iso_recv_start(priv->iso, -1, (1 << 3), -1) < 0) {
-			ETH1394_PRINT(KERN_ERR, dev->name,
-				      "Could not start data stream reception\n");
-
-			eth1394_iso_shutdown(priv);
-
-			return -EAGAIN;
-		}
-		priv->bc_state = ETHER1394_BC_OPENED;
-	}
-    
-	return 0;
-}
-
 /* This is called after an "ifup" */
 static int ether1394_open (struct net_device *dev)
 {
 	struct eth1394_priv *priv = (struct eth1394_priv *)dev->priv;
-	unsigned long flags;
-	int ret;
+	int ret = 0;
 
 	/* Something bad happened, don't even try */
-	if (priv->bc_state == ETHER1394_BC_CLOSED)
-		return -EAGAIN;
-
-	spin_lock_irqsave(&priv->lock, flags);
-	ret = ether1394_init_bc(dev);
-	spin_unlock_irqrestore(&priv->lock, flags);
+	if (priv->bc_state == ETHER1394_BC_ERROR) {
+		/* we'll try again */
+		priv->iso = hpsb_iso_recv_init(priv->host,
+					       ETHER1394_GASP_BUFFERS * 2 *
+					       (1 << (priv->host->csr.max_rec +
+						      1)),
+					       ETHER1394_GASP_BUFFERS,
+					       priv->broadcast_channel,
+					       HPSB_ISO_DMA_PACKET_PER_BUFFER,
+					       1, ether1394_iso);
+		if (priv->iso == NULL) {
+			ETH1394_PRINT(KERN_ERR, dev->name,
+				      "Could not allocate isochronous receive "
+				      "context for the broadcast channel\n");
+			priv->bc_state = ETHER1394_BC_ERROR;
+			ret = -EAGAIN;
+		} else {
+			if (hpsb_iso_recv_start(priv->iso, -1, (1 << 3), -1) < 0)
+				priv->bc_state = ETHER1394_BC_STOPPED;
+			else
+				priv->bc_state = ETHER1394_BC_RUNNING;
+		}
+	}
 
 	if (ret)
 		return ret;
@@ -312,66 +280,229 @@ static void ether1394_tx_timeout (struct
 static int ether1394_change_mtu(struct net_device *dev, int new_mtu)
 {
 	struct eth1394_priv *priv = (struct eth1394_priv *)dev->priv;
-	int phy_id = NODEID_TO_NODE(priv->host->node_id);
 
-	if ((new_mtu < 68) || (new_mtu > min(ETH1394_DATA_LEN, (int)(priv->maxpayload[phy_id] -
-					     (sizeof(union eth1394_hdr) + ETHER1394_GASP_OVERHEAD)))))
+	if ((new_mtu < 68) ||
+	    (new_mtu > min(ETH1394_DATA_LEN,
+			   (int)((1 << (priv->host->csr.max_rec + 1)) -
+				 (sizeof(union eth1394_hdr) +
+				  ETHER1394_GASP_OVERHEAD)))))
 		return -EINVAL;
 	dev->mtu = new_mtu;
 	return 0;
 }
 
-static inline void ether1394_register_limits(int nodeid, u16 maxpayload,
-					     unsigned char sspd, u64 eui, u64 fifo,
-					     struct eth1394_priv *priv)
+
+/******************************************
+ * 1394 bus activity functions
+ ******************************************/
+
+static struct eth1394_node_ref *eth1394_find_node(struct list_head *inl,
+						  struct unit_directory *ud)
 {
-	if (nodeid < 0 || nodeid >= ALL_NODES) {
-		ETH1394_PRINT_G (KERN_ERR, "Cannot register invalid nodeid %d\n", nodeid);
-		return;
+	struct eth1394_node_ref *node;
+
+	list_for_each_entry(node, inl, list)
+		if (node->ud == ud)
+			return node;
+
+	return NULL;
+}
+
+static struct eth1394_node_ref *eth1394_find_node_guid(struct list_head *inl,
+						       u64 guid)
+{
+	struct eth1394_node_ref *node;
+
+	list_for_each_entry(node, inl, list)
+		if (node->ud->ne->guid == guid)
+			return node;
+
+	return NULL;
+}
+
+static struct eth1394_node_ref *eth1394_find_node_nodeid(struct list_head *inl,
+							 nodeid_t nodeid)
+{
+	struct eth1394_node_ref *node;
+	list_for_each_entry(node, inl, list) {
+		if (node->ud->ne->nodeid == nodeid)
+			return node;
 	}
 
-	priv->maxpayload[nodeid]	= maxpayload;
-	priv->sspd[nodeid]		= sspd;
-	priv->fifo[nodeid]		= fifo;
-	priv->eui[nodeid]		= eui;
+	return NULL;
+}
 
-	priv->maxpayload[ALL_NODES] = min(priv->maxpayload[ALL_NODES], maxpayload);
-	priv->sspd[ALL_NODES] = min(priv->sspd[ALL_NODES], sspd);
+static int eth1394_probe(struct device *dev)
+{
+	struct unit_directory *ud;
+	struct eth1394_host_info *hi;
+	struct eth1394_priv *priv;
+	struct eth1394_node_ref *new_node;
+	struct eth1394_node_info *node_info;
 
-	return;
+	ud = container_of(dev, struct unit_directory, device);
+
+	hi = hpsb_get_hostinfo(&eth1394_highlevel, ud->ne->host);
+	if (!hi)
+		return -ENOENT;
+
+	new_node = kmalloc(sizeof(struct eth1394_node_ref),
+			   in_interrupt() ? GFP_ATOMIC : GFP_KERNEL);
+	if (!new_node)
+		return -ENOMEM;
+
+	node_info = kmalloc(sizeof(struct eth1394_node_info),
+			    in_interrupt() ? GFP_ATOMIC : GFP_KERNEL);
+	if (!node_info) {
+		kfree(new_node);
+		return -ENOMEM;
+	}
+
+	spin_lock_init(&node_info->pdg.lock);
+	INIT_LIST_HEAD(&node_info->pdg.list);
+	node_info->pdg.sz = 0;
+	node_info->fifo = ETHER1394_INVALID_ADDR;
+
+	ud->device.driver_data = node_info;
+	new_node->ud = ud;
+
+	priv = (struct eth1394_priv *)hi->dev->priv;
+	list_add_tail(&new_node->list, &priv->ip_node_list);
+
+	return 0;
+}
+
+static int eth1394_remove(struct device *dev)
+{
+	struct unit_directory *ud;
+	struct eth1394_host_info *hi;
+	struct eth1394_priv *priv;
+	struct eth1394_node_ref *old_node;
+	struct eth1394_node_info *node_info;
+	struct list_head *lh, *n;
+	unsigned long flags;
+
+	ud = container_of(dev, struct unit_directory, device);
+	hi = hpsb_get_hostinfo(&eth1394_highlevel, ud->ne->host);
+	if (!hi)
+		return -ENOENT;
+
+	priv = (struct eth1394_priv *)hi->dev->priv;
+
+	old_node = eth1394_find_node(&priv->ip_node_list, ud);
+
+	if (old_node) {
+		list_del(&old_node->list);
+		kfree(old_node);
+
+		node_info = (struct eth1394_node_info*)ud->device.driver_data;
+
+		spin_lock_irqsave(&node_info->pdg.lock, flags);
+		/* The partial datagram list should be empty, but we'll just
+		 * make sure anyway... */
+		list_for_each_safe(lh, n, &node_info->pdg.list) {
+			purge_partial_datagram(lh);
+		}
+		spin_unlock_irqrestore(&node_info->pdg.lock, flags);
+
+		kfree(node_info);
+		ud->device.driver_data = NULL;
+	}
+	return 0;
 }
 
+static int eth1394_update(struct unit_directory *ud)
+{
+	struct eth1394_host_info *hi;
+	struct eth1394_priv *priv;
+	struct eth1394_node_ref *node;
+	struct eth1394_node_info *node_info;
+
+	hi = hpsb_get_hostinfo(&eth1394_highlevel, ud->ne->host);
+	if (!hi)
+		return -ENOENT;
+
+	priv = (struct eth1394_priv *)hi->dev->priv;
+
+	node = eth1394_find_node(&priv->ip_node_list, ud);
+
+	if (!node) {
+		node = kmalloc(sizeof(struct eth1394_node_ref),
+			       in_interrupt() ? GFP_ATOMIC : GFP_KERNEL);
+		if (!node)
+			return -ENOMEM;
+
+
+		node_info = kmalloc(sizeof(struct eth1394_node_info),
+				    in_interrupt() ? GFP_ATOMIC : GFP_KERNEL);
+
+		spin_lock_init(&node_info->pdg.lock);
+		INIT_LIST_HEAD(&node_info->pdg.list);
+		node_info->pdg.sz = 0;
+
+		ud->device.driver_data = node_info;
+		node->ud = ud;
+
+		priv = (struct eth1394_priv *)hi->dev->priv;
+		list_add_tail(&node->list, &priv->ip_node_list);
+	}
+
+	return 0;
+}
+
+
+static struct ieee1394_device_id eth1394_id_table[] = {
+	{
+		.match_flags = (IEEE1394_MATCH_SPECIFIER_ID |
+				IEEE1394_MATCH_VERSION),
+		.specifier_id =	ETHER1394_GASP_SPECIFIER_ID,
+		.version = ETHER1394_GASP_VERSION,
+	},
+	{}
+};
+
+static struct hpsb_protocol_driver eth1394_proto_driver = {
+	.name		= "IPv4 over 1394 Driver",
+	.id_table	= eth1394_id_table,
+	.update		= eth1394_update,
+	.driver		= {
+		.name		= ETH1394_DRIVER_NAME,
+		.bus		= &ieee1394_bus_type,
+		.probe		= eth1394_probe,
+		.remove		= eth1394_remove,
+	},
+};
+
+
 static void ether1394_reset_priv (struct net_device *dev, int set_mtu)
 {
 	unsigned long flags;
 	int i;
 	struct eth1394_priv *priv = (struct eth1394_priv *)dev->priv;
 	struct hpsb_host *host = priv->host;
-	int phy_id = NODEID_TO_NODE(host->node_id);
-	u64 guid = *((u64*)&(host->csr.rom[3]));
-	u16 maxpayload = 1 << (((be32_to_cpu(host->csr.rom[2]) >> 12) & 0xf) + 1);
+	u64 guid = *((u64*)&(host->csr.rom->bus_info_data[3]));
+	u16 maxpayload = 1 << (host->csr.max_rec + 1);
+	int max_speed = IEEE1394_SPEED_MAX;
 
 	spin_lock_irqsave (&priv->lock, flags);
 
-	/* Clear the speed/payload/offset tables */
-	memset (priv->maxpayload, 0, sizeof (priv->maxpayload));
-	memset (priv->sspd, 0, sizeof (priv->sspd));
-	memset (priv->fifo, 0, sizeof (priv->fifo));
-
-	priv->sspd[ALL_NODES] = ETH1394_SPEED_DEF;
-	priv->maxpayload[ALL_NODES] = eth1394_speedto_maxpayload[priv->sspd[ALL_NODES]];
-
-	priv->bc_state = ETHER1394_BC_CHECK;
-
-	/* Register our limits now */
-	ether1394_register_limits(phy_id, maxpayload,
-				  host->speed_map[(phy_id << 6) + phy_id],
-				  guid, ETHER1394_REGION_ADDR, priv);
+	memset(priv->ud_list, 0, sizeof(struct node_entry*) * ALL_NODES);
+	priv->bc_maxpayload = 512;
+
+	/* Determine speed limit */
+	for (i = 0; i < host->node_count; i++)
+		if (max_speed > host->speed_map[NODEID_TO_NODE(host->node_id) *
+						64 + i])
+			max_speed = host->speed_map[NODEID_TO_NODE(host->node_id) *
+						    64 + i];
+	priv->bc_sspd = max_speed;
 
 	/* We'll use our maxpayload as the default mtu */
 	if (set_mtu) {
-		dev->mtu = min(ETH1394_DATA_LEN, (int)(priv->maxpayload[phy_id] -
-			       (sizeof(union eth1394_hdr) + ETHER1394_GASP_OVERHEAD)));
+		dev->mtu = min(ETH1394_DATA_LEN,
+			       (int)(maxpayload -
+				     (sizeof(union eth1394_hdr) +
+				      ETHER1394_GASP_OVERHEAD)));
 
 		/* Set our hardware address while we're at it */
 		*(u64*)dev->dev_addr = guid;
@@ -379,20 +510,6 @@ static void ether1394_reset_priv (struct
 	}
 
 	spin_unlock_irqrestore (&priv->lock, flags);
-
-	for (i = 0; i < ALL_NODES; i++) {
-		struct list_head *lh, *n;
-
-		spin_lock_irqsave(&priv->pdg[i].lock, flags);
-		if (!set_mtu) {
-			list_for_each_safe(lh, n, &priv->pdg[i].list) {
-				purge_partial_datagram(lh);
-			}
-		}
-		INIT_LIST_HEAD(&(priv->pdg[i].list));
-		priv->pdg[i].sz = 0;
-		spin_unlock_irqrestore(&priv->pdg[i].lock, flags);
-	}
 }
 
 /* This function is called right before register_netdev */
@@ -432,15 +549,21 @@ static void ether1394_init_dev (struct n
  */
 static void ether1394_add_host (struct hpsb_host *host)
 {
-	int i;
-	struct host_info *hi = NULL;
+	struct eth1394_host_info *hi = NULL;
 	struct net_device *dev = NULL;
 	struct eth1394_priv *priv;
 	static int version_printed = 0;
 
-	hpsb_register_addrspace(&eth1394_highlevel, host, &addr_ops,
-				ETHER1394_REGION_ADDR,
-				ETHER1394_REGION_ADDR_END);
+	u64 fifo_addr;
+
+	fifo_addr = hpsb_allocate_and_register_addrspace(&eth1394_highlevel,
+							 host,
+							 &addr_ops,
+							 ETHER1394_REGION_ADDR_LEN,
+							 ETHER1394_REGION_ADDR_LEN,
+							 -1, -1);
+	if (fifo_addr == ~0ULL)
+		goto out;
 
 	if (version_printed++ == 0)
 		ETH1394_PRINT_G (KERN_INFO, "%s\n", version);
@@ -461,14 +584,11 @@ static void ether1394_add_host (struct h
 
 	priv = (struct eth1394_priv *)dev->priv;
 
+	INIT_LIST_HEAD(&priv->ip_node_list);
+
 	spin_lock_init(&priv->lock);
 	priv->host = host;
-
-	for (i = 0; i < ALL_NODES; i++) {
-                spin_lock_init(&priv->pdg[i].lock);
-		INIT_LIST_HEAD(&priv->pdg[i].list);
-		priv->pdg[i].sz = 0;
-	}
+	priv->local_fifo = fifo_addr;
 
 	hi = hpsb_create_hostinfo(&eth1394_highlevel, host, sizeof(*hi));
 
@@ -486,8 +606,8 @@ static void ether1394_add_host (struct h
 		goto out;
 	}
 
-	ETH1394_PRINT (KERN_ERR, dev->name, "IEEE-1394 IPv4 over 1394 Ethernet (%s)\n",
-		       host->driver->name);
+	ETH1394_PRINT (KERN_ERR, dev->name, "IEEE-1394 IPv4 over 1394 Ethernet (fw-host%d)\n",
+		       host->id);
 
 	hi->host = host;
 	hi->dev = dev;
@@ -496,11 +616,32 @@ static void ether1394_add_host (struct h
 	 * be checked when the eth device is opened. */
 	priv->broadcast_channel = host->csr.broadcast_channel & 0x3f;
 
-	priv->iso = hpsb_iso_recv_init(host, 16 * 4096, 16, priv->broadcast_channel,
-					HPSB_ISO_DMA_PACKET_PER_BUFFER, 1, ether1394_iso);
+	priv->iso = hpsb_iso_recv_init(host, (ETHER1394_GASP_BUFFERS * 2 *
+					      (1 << (host->csr.max_rec + 1))),
+				       ETHER1394_GASP_BUFFERS,
+				       priv->broadcast_channel,
+				       HPSB_ISO_DMA_PACKET_PER_BUFFER,
+				       1, ether1394_iso);
 	if (priv->iso == NULL) {
-		priv->bc_state = ETHER1394_BC_CLOSED;
+		ETH1394_PRINT(KERN_ERR, dev->name,
+			      "Could not allocate isochronous receive context "
+			      "for the broadcast channel\n");
+		priv->bc_state = ETHER1394_BC_ERROR;
+	} else {
+		if (hpsb_iso_recv_start(priv->iso, -1, (1 << 3), -1) < 0)
+			priv->bc_state = ETHER1394_BC_STOPPED;
+		else
+			priv->bc_state = ETHER1394_BC_RUNNING;
 	}
+
+	if (csr1212_attach_keyval_to_directory(host->csr.rom->root_kv,
+					       eth1394_ud) != CSR1212_SUCCESS) {
+		ETH1394_PRINT (KERN_ERR, dev->name,
+			       "Cannot attach IP 1394 Unit Directory to "
+			       "Config ROM\n");
+		goto out;
+	}
+	hi->host->update_config_rom = 1;
 	return;
 
 out:
@@ -515,12 +656,21 @@ out:
 /* Remove a card from our list */
 static void ether1394_remove_host (struct hpsb_host *host)
 {
-	struct host_info *hi = hpsb_get_hostinfo(&eth1394_highlevel, host);
-
+	struct eth1394_host_info *hi;
+	
+	hi = hpsb_get_hostinfo(&eth1394_highlevel, host);
 	if (hi != NULL) {
 		struct eth1394_priv *priv = (struct eth1394_priv *)hi->dev->priv;
 
-		eth1394_iso_shutdown(priv);
+		hpsb_unregister_addrspace(&eth1394_highlevel, host,
+					  priv->local_fifo);
+
+		if (priv->iso != NULL) 
+			hpsb_iso_shutdown(priv->iso);
+
+		csr1212_detach_keyval_from_directory(hi->host->csr.rom->root_kv,
+						     eth1394_ud);
+		hi->host->update_config_rom = 1;
 
 		if (hi->dev) {
 			unregister_netdev (hi->dev);
@@ -534,18 +684,42 @@ static void ether1394_remove_host (struc
 /* A reset has just arisen */
 static void ether1394_host_reset (struct hpsb_host *host)
 {
-	struct host_info *hi = hpsb_get_hostinfo(&eth1394_highlevel, host);
+	struct eth1394_host_info *hi;
+	struct eth1394_priv *priv;
 	struct net_device *dev;
+	struct list_head *lh, *n;
+	struct eth1394_node_ref *node;
+	struct eth1394_node_info *node_info;
+	unsigned long flags;
+
+	hi = hpsb_get_hostinfo(&eth1394_highlevel, host);
 
 	/* This can happen for hosts that we don't use */
 	if (hi == NULL)
 		return;
 
 	dev = hi->dev;
+	priv = (struct eth1394_priv *)dev->priv;
 
 	/* Reset our private host data, but not our mtu */
 	netif_stop_queue (dev);
 	ether1394_reset_priv (dev, 0);
+
+	list_for_each_entry(node, &priv->ip_node_list, list) {
+		node_info = (struct eth1394_node_info*)node->ud->device.driver_data;
+
+		spin_lock_irqsave(&node_info->pdg.lock, flags);
+
+		list_for_each_safe(lh, n, &node_info->pdg.list) {
+			purge_partial_datagram(lh);
+		}
+
+		INIT_LIST_HEAD(&(node_info->pdg.list));
+		node_info->pdg.sz = 0;
+
+		spin_unlock_irqrestore(&node_info->pdg.lock, flags);
+	}
+
 	netif_wake_queue (dev);
 }
 
@@ -622,7 +796,8 @@ static int ether1394_header_parse(struct
 static int ether1394_header_cache(struct neighbour *neigh, struct hh_cache *hh)
 {
 	unsigned short type = hh->hh_type;
-	struct eth1394hdr *eth = (struct eth1394hdr*)(((u8*)hh->hh_data) + 6);
+	struct eth1394hdr *eth = (struct eth1394hdr*)(((u8*)hh->hh_data) +
+						      (16 - ETH1394_HLEN));
 	struct net_device *dev = neigh->dev;
 
 	if (type == __constant_htons(ETH_P_802_3)) {
@@ -641,7 +816,7 @@ static void ether1394_header_cache_updat
 					  struct net_device *dev,
 					  unsigned char * haddr)
 {
-	memcpy(((u8*)hh->hh_data) + 6, haddr, dev->addr_len);
+	memcpy(((u8*)hh->hh_data) + (16 - ETH1394_HLEN), haddr, dev->addr_len);
 }
 
 static int ether1394_mac_addr(struct net_device *dev, void *p)
@@ -650,7 +825,7 @@ static int ether1394_mac_addr(struct net
 		return -EBUSY;
 
 	/* Not going to allow setting the MAC address, we really need to use
-	 * the real one suppliled by the hardware */
+	 * the real one supplied by the hardware */
 	 return -EINVAL;
  }
 
@@ -710,31 +885,37 @@ static inline u16 ether1394_parse_encap(
 	if (destid == (LOCAL_BUS | ALL_NODES))
 		dest_hw = ~0ULL;  /* broadcast */
 	else
-		dest_hw = priv->eui[NODEID_TO_NODE(destid)];
+		dest_hw = cpu_to_be64((((u64)priv->host->csr.guid_hi) << 32) |
+				      priv->host->csr.guid_lo);
 
 	/* If this is an ARP packet, convert it. First, we want to make
 	 * use of some of the fields, since they tell us a little bit
 	 * about the sending machine.  */
 	if (ether_type == __constant_htons (ETH_P_ARP)) {
-		unsigned long flags;
 		struct eth1394_arp *arp1394 = (struct eth1394_arp*)skb->data;
 		struct arphdr *arp = (struct arphdr *)skb->data;
 		unsigned char *arp_ptr = (unsigned char *)(arp + 1);
 		u64 fifo_addr = (u64)ntohs(arp1394->fifo_hi) << 32 |
 			ntohl(arp1394->fifo_lo);
-		u8 host_max_rec = (be32_to_cpu(priv->host->csr.rom[2]) >>
-				   12) & 0xf;
-		u8 max_rec = min(host_max_rec, (u8)(arp1394->max_rec));
+		u8 max_rec = min(priv->host->csr.max_rec,
+				 (u8)(arp1394->max_rec));
 		u16 maxpayload = min(eth1394_speedto_maxpayload[arp1394->sspd],
 				     (u16)(1 << (max_rec + 1)));
+		struct eth1394_node_ref *node;
+		struct eth1394_node_info *node_info;
 
+		node = eth1394_find_node_guid(&priv->ip_node_list,
+					      be64_to_cpu(arp1394->s_uniq_id));
+		if (!node) {
+			return 0;
+		}
+
+		node_info = (struct eth1394_node_info*)node->ud->device.driver_data;
 
 		/* Update our speed/payload/fifo_offset table */
-		spin_lock_irqsave (&priv->lock, flags);
-		ether1394_register_limits(NODEID_TO_NODE(srcid), maxpayload,
-					  arp1394->sspd, arp1394->s_uniq_id,
-					  fifo_addr, priv);
-		spin_unlock_irqrestore (&priv->lock, flags);
+		node_info->maxpayload =	maxpayload;
+		node_info->sspd =	arp1394->sspd;
+		node_info->fifo =	fifo_addr;
 
 		/* Now that we're done with the 1394 specific stuff, we'll
 		 * need to alter some of the data.  Believe it or not, all
@@ -743,9 +924,8 @@ static inline u16 ether1394_parse_encap(
 		 * in and the hardware address length set to 8.
 		 *
 		 * IMPORTANT: The code below overwrites 1394 specific data
-		 * needed above data so keep the call to
-		 * ether1394_register_limits() before munging the data for the
-		 * higher level IP stack. */
+		 * needed above so keep the munging of the data for the
+		 * higher level IP stack last. */
 
 		arp->ar_hln = 8;
 		arp_ptr += arp->ar_hln;		/* skip over sender unique id */
@@ -754,9 +934,9 @@ static inline u16 ether1394_parse_encap(
 
 		if (arp->ar_op == 1)
 			/* just set ARP req target unique ID to 0 */
-			memset(arp_ptr, 0, ETH1394_ALEN);
+			*((u64*)arp_ptr) = 0;
 		else
-			memcpy(arp_ptr, dev->dev_addr, ETH1394_ALEN);
+			*((u64*)arp_ptr) = *((u64*)dev->dev_addr);
 	}
 
 	/* Now add the ethernet header. */
@@ -769,12 +949,9 @@ static inline u16 ether1394_parse_encap(
 
 static inline int fragment_overlap(struct list_head *frag_list, int offset, int len)
 {
-	struct list_head *lh;
 	struct fragment_info *fi;
 
-	list_for_each(lh, frag_list) {
-		fi = list_entry(lh, struct fragment_info, list);
-
+	list_for_each_entry(fi, frag_list, list) {
 		if ( ! ((offset > (fi->offset + fi->len - 1)) ||
 		       ((offset + len - 1) < fi->offset)))
 			return 1;
@@ -784,13 +961,11 @@ static inline int fragment_overlap(struc
 
 static inline struct list_head *find_partial_datagram(struct list_head *pdgl, int dgl)
 {
-	struct list_head *lh;
 	struct partial_datagram *pd;
 
-	list_for_each(lh, pdgl) {
-		pd = list_entry(lh, struct partial_datagram, list);
+	list_for_each_entry(pd, pdgl, list) {
 		if (pd->dgl == dgl)
-			return lh;
+			return &pd->list;
 	}
 	return NULL;
 }
@@ -939,12 +1114,29 @@ static int ether1394_data_handler(struct
 {
 	struct sk_buff *skb;
 	unsigned long flags;
-	struct eth1394_priv *priv;
+	struct eth1394_priv *priv = (struct eth1394_priv *)dev->priv;
 	union eth1394_hdr *hdr = (union eth1394_hdr *)buf;
 	u16 ether_type = 0;  /* initialized to clear warning */
 	int hdr_len;
+	struct unit_directory *ud = priv->ud_list[NODEID_TO_NODE(srcid)];
+	struct eth1394_node_info *node_info;
 
-	priv = (struct eth1394_priv *)dev->priv;
+	if (!ud) {
+		struct eth1394_node_ref *node;
+		node = eth1394_find_node_nodeid(&priv->ip_node_list, srcid);
+		if (!node) {
+			HPSB_PRINT(KERN_ERR, "ether1394 rx: sender nodeid "
+				   "lookup failure: " NODE_BUS_FMT,
+				   NODE_BUS_ARGS(priv->host, srcid));
+			priv->stats.rx_dropped++;
+			return -1;
+		}
+		ud = node->ud;
+
+		priv->ud_list[NODEID_TO_NODE(srcid)] = ud;
+	}
+
+	node_info = (struct eth1394_node_info*)ud->device.driver_data;
 
 	/* First, did we receive a fragmented or unfragmented datagram? */
 	hdr->words.word1 = ntohs(hdr->words.word1);
@@ -975,8 +1167,7 @@ static int ether1394_data_handler(struct
 		int dg_size;
 		int dgl;
 		int retval;
-		int sid = NODEID_TO_NODE(srcid);
-                struct pdg_list *pdg = &(priv->pdg[sid]);
+		struct pdg_list *pdg = &(node_info->pdg);
 
 		hdr->words.word3 = ntohs(hdr->words.word3);
 		/* The 4th header word is reserved so no need to do ntohs() */
@@ -1110,8 +1301,9 @@ bad_proto:
 static int ether1394_write(struct hpsb_host *host, int srcid, int destid,
 			   quadlet_t *data, u64 addr, size_t len, u16 flags)
 {
-	struct host_info *hi = hpsb_get_hostinfo(&eth1394_highlevel, host);
+	struct eth1394_host_info *hi;
 
+	hi = hpsb_get_hostinfo(&eth1394_highlevel, host);
 	if (hi == NULL) {
 		ETH1394_PRINT_G(KERN_ERR, "Could not find net device for host %s\n",
 				host->driver->name);
@@ -1128,7 +1320,7 @@ static void ether1394_iso(struct hpsb_is
 {
 	quadlet_t *data;
 	char *buf;
-	struct host_info *hi = hpsb_get_hostinfo(&eth1394_highlevel, iso->host);
+	struct eth1394_host_info *hi;
 	struct net_device *dev;
 	struct eth1394_priv *priv;
 	unsigned int len;
@@ -1137,6 +1329,7 @@ static void ether1394_iso(struct hpsb_is
 	int i;
 	int nready;
 
+	hi = hpsb_get_hostinfo(&eth1394_highlevel, iso->host);
 	if (hi == NULL) {
 		ETH1394_PRINT_G(KERN_ERR, "Could not find net device for host %s\n",
 				iso->host->driver->name);
@@ -1193,7 +1386,6 @@ static inline void ether1394_arp_to_1394
 					    struct net_device *dev)
 {
 	struct eth1394_priv *priv = (struct eth1394_priv *)(dev->priv);
-	u16 phy_id = NODEID_TO_NODE(priv->host->node_id);
 
 	struct arphdr *arp = (struct arphdr *)skb->data;
 	unsigned char *arp_ptr = (unsigned char *)(arp + 1);
@@ -1203,10 +1395,10 @@ static inline void ether1394_arp_to_1394
 	 * and set hw_addr_len, max_rec, sspd, fifo_hi and fifo_lo.  */
 	arp1394->hw_addr_len	= 16;
 	arp1394->sip		= *(u32*)(arp_ptr + ETH1394_ALEN);
-	arp1394->max_rec	= (be32_to_cpu(priv->host->csr.rom[2]) >> 12) & 0xf;
-	arp1394->sspd		= priv->sspd[phy_id];
-	arp1394->fifo_hi	= htons (priv->fifo[phy_id] >> 32);
-	arp1394->fifo_lo	= htonl (priv->fifo[phy_id] & ~0x0);
+	arp1394->max_rec	= priv->host->csr.max_rec;
+	arp1394->sspd		= priv->host->csr.lnk_spd;
+	arp1394->fifo_hi	= htons (priv->local_fifo >> 32);
+	arp1394->fifo_lo	= htonl (priv->local_fifo & ~0x0);
 
 	return;
 }
@@ -1333,15 +1525,15 @@ static inline void ether1394_prep_gasp_p
 	p->data_size = length;
 	p->data = ((quadlet_t*)skb->data) - 2;
 	p->data[0] = cpu_to_be32((priv->host->node_id << 16) |
-				      ETHER1394_GASP_SPECIFIER_ID_HI);
-	p->data[1] = cpu_to_be32((ETHER1394_GASP_SPECIFIER_ID_LO << 24) |
-				      ETHER1394_GASP_VERSION);
+				 ETHER1394_GASP_SPECIFIER_ID_HI);
+	p->data[1] = __constant_cpu_to_be32((ETHER1394_GASP_SPECIFIER_ID_LO << 24) |
+					    ETHER1394_GASP_VERSION);
 
 	/* Setting the node id to ALL_NODES (not LOCAL_BUS | ALL_NODES)
 	 * prevents hpsb_send_packet() from setting the speed to an arbitrary
 	 * value based on packet->node_id if packet->node_id is not set. */
 	p->node_id = ALL_NODES;
-	p->speed_code = priv->sspd[ALL_NODES];
+	p->speed_code = priv->bc_sspd;
 }
 
 static inline void ether1394_free_packet(struct hpsb_packet *packet)
@@ -1458,7 +1650,8 @@ static int ether1394_tx (struct sk_buff 
 	u16 dg_size;
 	u16 dgl;
 	struct packet_task *ptask;
-	struct node_entry *ne;
+	struct eth1394_node_ref *node;
+	struct eth1394_node_info *node_info = NULL;
 
 	ptask = kmem_cache_alloc(packet_task_cache, kmflags);
 	if (ptask == NULL) {
@@ -1466,22 +1659,11 @@ static int ether1394_tx (struct sk_buff 
 		goto fail;
 	}
 
-	spin_lock_irqsave (&priv->lock, flags);
-	if (priv->bc_state == ETHER1394_BC_CLOSED) {
-		ETH1394_PRINT(KERN_ERR, dev->name,
-			      "Cannot send packet, no broadcast channel available.\n");
+	if ((priv->host->csr.broadcast_channel & 0xc0000000) != 0xc0000000) {
 		ret = -EAGAIN;
-		spin_unlock_irqrestore (&priv->lock, flags);
-		goto fail;
-	}
-
-	if ((ret = ether1394_init_bc(dev))) {
-		spin_unlock_irqrestore (&priv->lock, flags);
 		goto fail;
 	}
 
-	spin_unlock_irqrestore (&priv->lock, flags);
-
 	if ((skb = skb_share_check (skb, kmflags)) == NULL) {
 		ret = -ENOMEM;
 		goto fail;
@@ -1491,28 +1673,8 @@ static int ether1394_tx (struct sk_buff 
 	eth = (struct eth1394hdr*)skb->data;
 	skb_pull(skb, ETH1394_HLEN);
 
-	ne = hpsb_guid_get_entry(be64_to_cpu(*(u64*)eth->h_dest));
-	if (!ne)
-		dest_node = LOCAL_BUS | ALL_NODES;
-	else
-		dest_node = ne->nodeid;
-
 	proto = eth->h_proto;
-
-	/* If this is an ARP packet, convert it */
-	if (proto == __constant_htons (ETH_P_ARP))
-		ether1394_arp_to_1394arp (skb, dev);
-
-	max_payload = priv->maxpayload[NODEID_TO_NODE(dest_node)];
-
-	/* This check should be unnecessary, but we'll keep it for safety for
-	 * a while longer. */
-	if (max_payload < 512) {
-		ETH1394_PRINT(KERN_WARNING, dev->name,
-			      "max_payload too small: %d   (setting to 512)\n",
-			      max_payload);
-		max_payload = 512;
-	}
+	dg_size = skb->len;
 
 	/* Set the transmission type for the packet.  ARP packets and IP
 	 * broadcast packets are sent via GASP. */
@@ -1521,18 +1683,38 @@ static int ether1394_tx (struct sk_buff 
 	    (proto == __constant_htons(ETH_P_IP) &&
 	     IN_MULTICAST(__constant_ntohl(skb->nh.iph->daddr)))) {
 		tx_type = ETH1394_GASP;
-                max_payload -= ETHER1394_GASP_OVERHEAD;
+		dest_node = LOCAL_BUS | ALL_NODES;
+		max_payload = priv->bc_maxpayload;
+		BUG_ON(max_payload < (512 - ETHER1394_GASP_OVERHEAD));
+		dgl = priv->bc_dgl;
+		if (max_payload < dg_size + hdr_type_len[ETH1394_HDR_LF_UF])
+			priv->bc_dgl++;
 	} else {
+		node = eth1394_find_node_guid(&priv->ip_node_list,
+					      be64_to_cpu(*(u64*)eth->h_dest));
+		if (!node) {
+			ret = -EAGAIN;
+			goto fail;
+		}
+		node_info = (struct eth1394_node_info*)node->ud->device.driver_data;
+		if (node_info->fifo == ETHER1394_INVALID_ADDR) {
+			ret = -EAGAIN;
+			goto fail;
+		}
+
+		dest_node = node->ud->ne->nodeid;
+		max_payload = node_info->maxpayload;
+		BUG_ON(max_payload < (512 - ETHER1394_GASP_OVERHEAD));
+
+		dgl = node_info->dgl;
+		if (max_payload < dg_size + hdr_type_len[ETH1394_HDR_LF_UF])
+			node_info->dgl++;
 		tx_type = ETH1394_WRREQ;
 	}
 
-	dg_size = skb->len;
-
-	spin_lock_irqsave (&priv->lock, flags);
-	dgl = priv->dgl[NODEID_TO_NODE(dest_node)];
-	if (max_payload < dg_size + hdr_type_len[ETH1394_HDR_LF_UF])
-		priv->dgl[NODEID_TO_NODE(dest_node)]++;
-	spin_unlock_irqrestore (&priv->lock, flags);
+	/* If this is an ARP packet, convert it */
+	if (proto == __constant_htons (ETH_P_ARP))
+		ether1394_arp_to_1394arp (skb, dev);
 
 	ptask->hdr.words.word1 = 0;
 	ptask->hdr.words.word2 = 0;
@@ -1545,17 +1727,8 @@ static int ether1394_tx (struct sk_buff 
 	if (tx_type != ETH1394_GASP) {
 		u64 addr;
 
-		/* This test is just temporary until ConfigROM support has
-		 * been added to eth1394.  Until then, we need an ARP packet
-		 * after a bus reset from the current destination node so that
-		 * we can get FIFO information. */
-		if (priv->fifo[NODEID_TO_NODE(dest_node)] == 0ULL) {
-			ret = -EAGAIN;
-			goto fail;
-		}
-
 		spin_lock_irqsave(&priv->lock, flags);
-		addr = priv->fifo[NODEID_TO_NODE(dest_node)];
+		addr = node_info->fifo;
 		spin_unlock_irqrestore(&priv->lock, flags);
 
 		ptask->addr = addr;
@@ -1621,7 +1794,7 @@ static int ether1394_ethtool_ioctl(struc
 		case ETHTOOL_GDRVINFO: {
 			struct ethtool_drvinfo info = { ETHTOOL_GDRVINFO };
 			strcpy (info.driver, driver_name);
-			strcpy (info.version, "$Rev: 1096 $");
+			strcpy (info.version, "$Rev: 1133 $");
 			/* FIXME XXX provide sane businfo */
 			strcpy (info.bus_info, "ieee1394");
 			if (copy_to_user (useraddr, &info, sizeof (info)))
@@ -1644,19 +1817,78 @@ static int ether1394_ethtool_ioctl(struc
 
 static int __init ether1394_init_module (void)
 {
+	int ret;
+	struct csr1212_keyval *spec_id = NULL;
+	struct csr1212_keyval *spec_desc = NULL;
+	struct csr1212_keyval *ver = NULL;
+	struct csr1212_keyval *ver_desc = NULL;
+
 	packet_task_cache = kmem_cache_create("packet_task", sizeof(struct packet_task),
 					      0, 0, NULL, NULL);
 
+	eth1394_ud = csr1212_new_directory(CSR1212_KV_ID_UNIT);
+	spec_id = csr1212_new_immediate(CSR1212_KV_ID_SPECIFIER_ID,
+					ETHER1394_GASP_SPECIFIER_ID);
+	spec_desc = csr1212_new_string_descriptor_leaf("IANA");
+	ver = csr1212_new_immediate(CSR1212_KV_ID_VERSION,
+				    ETHER1394_GASP_VERSION);
+	ver_desc = csr1212_new_string_descriptor_leaf("IPv4");
+
+	if ((!eth1394_ud) ||
+	    (!spec_id) ||
+	    (!spec_desc) ||
+	    (!ver) ||
+	    (!ver_desc)) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	ret = csr1212_associate_keyval(spec_id, spec_desc);
+	if (ret != CSR1212_SUCCESS)
+		goto out;
+
+	ret = csr1212_associate_keyval(ver, ver_desc);
+	if (ret != CSR1212_SUCCESS)
+		goto out;
+
+	ret = csr1212_attach_keyval_to_directory(eth1394_ud, spec_id);
+	if (ret != CSR1212_SUCCESS)
+		goto out;
+
+	ret = csr1212_attach_keyval_to_directory(eth1394_ud, ver);
+	if (ret != CSR1212_SUCCESS)
+		goto out;
+
 	/* Register ourselves as a highlevel driver */
 	hpsb_register_highlevel(&eth1394_highlevel);
 
-	return 0;
+	ret = hpsb_register_protocol(&eth1394_proto_driver);
+
+out:
+	if ((ret != 0) && eth1394_ud) {
+		csr1212_release_keyval(eth1394_ud);
+	}
+	if (spec_id)
+		csr1212_release_keyval(spec_id);
+	if (spec_desc)
+		csr1212_release_keyval(spec_desc);
+	if (ver)
+		csr1212_release_keyval(ver);
+	if (ver_desc)
+		csr1212_release_keyval(ver_desc);
+
+	return ret;
 }
 
 static void __exit ether1394_exit_module (void)
 {
+	hpsb_unregister_protocol(&eth1394_proto_driver);
 	hpsb_unregister_highlevel(&eth1394_highlevel);
 	kmem_cache_destroy(packet_task_cache);
+
+	if (eth1394_ud) {
+		csr1212_release_keyval(eth1394_ud);
+	}
 }
 
 module_init(ether1394_init_module);
--- diff/drivers/ieee1394/eth1394.h	2003-08-20 14:16:28.000000000 +0100
+++ source/drivers/ieee1394/eth1394.h	2004-02-23 13:56:41.000000000 +0000
@@ -29,8 +29,8 @@
 /* Register for incoming packets. This is 4096 bytes, which supports up to
  * S3200 (per Table 16-3 of IEEE 1394b-2002). */
 #define ETHER1394_REGION_ADDR_LEN	4096
-#define ETHER1394_REGION_ADDR		0xfffff0200000ULL
-#define ETHER1394_REGION_ADDR_END	(ETHER1394_REGION_ADDR + ETHER1394_REGION_ADDR_LEN)
+
+#define ETHER1394_INVALID_ADDR		~0ULL
 
 /* GASP identifier numbers for IPv4 over IEEE 1394 */
 #define ETHER1394_GASP_SPECIFIER_ID	0x00005E
@@ -40,37 +40,30 @@
 
 #define ETHER1394_GASP_OVERHEAD (2 * sizeof(quadlet_t))  /* GASP header overhead */
 
+#define ETHER1394_GASP_BUFFERS 16
+
 /* Node set == 64 */
 #define NODE_SET			(ALL_NODES + 1)
 
-enum eth1394_bc_states { ETHER1394_BC_CLOSED, ETHER1394_BC_OPENED,
-			 ETHER1394_BC_CHECK };
+enum eth1394_bc_states { ETHER1394_BC_ERROR,
+			 ETHER1394_BC_RUNNING,
+			 ETHER1394_BC_STOPPED };
 
-struct pdg_list {
-	struct list_head list;		/* partial datagram list per node */
-	unsigned int sz;		/* partial datagram list size per node	*/
-	spinlock_t lock;		/* partial datagram lock		*/
-};
 
 /* Private structure for our ethernet driver */
 struct eth1394_priv {
 	struct net_device_stats stats;	/* Device stats			 */
 	struct hpsb_host *host;		/* The card for this dev	 */
-	u16 maxpayload[NODE_SET];	/* Max payload per node		 */
-	unsigned char sspd[NODE_SET];	/* Max speed per node		 */
-	u64 fifo[ALL_NODES];		/* FIFO offset per node		 */
-	u64 eui[ALL_NODES];		/* EUI-64 per node		 */
+	u16 bc_maxpayload;		/* Max broadcast payload	 */
+	u8 bc_sspd;			/* Max broadcast speed		 */
+	u64 local_fifo;			/* Local FIFO Address		 */
 	spinlock_t lock;		/* Private lock			 */
 	int broadcast_channel;		/* Async stream Broadcast Channel */
 	enum eth1394_bc_states bc_state; /* broadcast channel state	 */
 	struct hpsb_iso *iso;		/* Async stream recv handle	 */
-	struct pdg_list pdg[ALL_NODES]; /* partial RX datagram lists     */
-	int dgl[NODE_SET];              /* Outgoing datagram label per node */
-};
-
-struct host_info {
-	struct hpsb_host *host;
-	struct net_device *dev;
+	int bc_dgl;			/* Outgoing broadcast datagram label */
+	struct list_head ip_node_list;	/* List of IP capable nodes	 */
+	struct unit_directory *ud_list[ALL_NODES]; /* Cached unit dir list */
 };
 
 
--- diff/drivers/ieee1394/highlevel.c	2004-02-18 08:54:09.000000000 +0000
+++ source/drivers/ieee1394/highlevel.c	2004-02-23 13:56:41.000000000 +0000
@@ -20,6 +20,7 @@
 #include <linux/config.h>
 #include <linux/slab.h>
 #include <linux/list.h>
+#include <linux/bitops.h>
 
 #include "ieee1394.h"
 #include "ieee1394_types.h"
@@ -44,7 +45,6 @@ static DECLARE_RWSEM(hl_drivers_sem);
 static LIST_HEAD(hl_irqs);
 static rwlock_t hl_irqs_lock = RW_LOCK_UNLOCKED;
 
-static LIST_HEAD(addr_space);
 static rwlock_t addr_space_lock = RW_LOCK_UNLOCKED;
 
 /* addr_space list will have zero and max already included as bounds */
@@ -56,21 +56,20 @@ static struct hl_host_info *hl_get_hosti
 					      struct hpsb_host *host)
 {
 	struct hl_host_info *hi = NULL;
-	struct list_head *lh;
 
 	if (!hl || !host)
 		return NULL;
 
 	read_lock(&hl->host_info_lock);
-	list_for_each (lh, &hl->host_info_list) {
-		hi = list_entry(lh, struct hl_host_info, list);
-		if (hi->host == host)
-			break;
-		hi = NULL;
+	list_for_each_entry(hi, &hl->host_info_list, list) {
+		if (hi->host == host) {
+			read_unlock(&hl->host_info_lock);
+			return hi;
+		}
 	}
 	read_unlock(&hl->host_info_lock);
 
-	return hi;
+	return NULL;
 }
 
 
@@ -188,7 +187,6 @@ unsigned long hpsb_get_hostinfo_key(stru
 
 void *hpsb_get_hostinfo_bykey(struct hpsb_highlevel *hl, unsigned long key)
 {
-	struct list_head *lh;
 	struct hl_host_info *hi;
 	void *data = NULL;
 
@@ -196,8 +194,7 @@ void *hpsb_get_hostinfo_bykey(struct hps
 		return NULL;
 
 	read_lock(&hl->host_info_lock);
-	list_for_each (lh, &hl->host_info_list) {
-		hi = list_entry(lh, struct hl_host_info, list);
+	list_for_each_entry(hi, &hl->host_info_list, list) {
 		if (hi->key == key) {
 			data = hi->data;
 			break;
@@ -211,7 +208,6 @@ void *hpsb_get_hostinfo_bykey(struct hps
 
 struct hpsb_host *hpsb_get_host_bykey(struct hpsb_highlevel *hl, unsigned long key)
 {
-	struct list_head *lh;
 	struct hl_host_info *hi;
 	struct hpsb_host *host = NULL;
 
@@ -219,8 +215,7 @@ struct hpsb_host *hpsb_get_host_bykey(st
 		return NULL;
 
 	read_lock(&hl->host_info_lock);
-	list_for_each (lh, &hl->host_info_list) {
-		hi = list_entry(lh, struct hl_host_info, list);
+	list_for_each_entry(hi, &hl->host_info_list, list) {
 		if (hi->key == key) {
 			host = hi->host;
 			break;
@@ -237,6 +232,13 @@ static int highlevel_for_each_host_reg(s
 
 	hl->add_host(host);
 
+        if (host->update_config_rom) {
+		if (hpsb_update_config_rom_image(host) < 0) {
+			HPSB_ERR("Failed to generate Configuration ROM image for host "
+				 "%s-%d", hl->name, host->id);
+		}
+	}
+
 	return 0;
 }
 
@@ -261,12 +263,20 @@ void hpsb_register_highlevel(struct hpsb
         return;
 }
 
-static void __unregister_host(struct hpsb_highlevel *hl, struct hpsb_host *host)
+static void __delete_addr(struct hpsb_address_serve *as)
+{
+	list_del(&as->host_list);
+	list_del(&as->hl_list);
+	kfree(as);
+}
+
+static void __unregister_host(struct hpsb_highlevel *hl, struct hpsb_host *host, int update_cr)
 {
 	unsigned long flags;
 	struct list_head *lh, *next;
 	struct hpsb_address_serve *as;
 
+	/* First, let the highlevel driver unreg */
 	if (hl->remove_host)
 		hl->remove_host(host);
 
@@ -274,19 +284,24 @@ static void __unregister_host(struct hps
 	 * and this particular host. */
 	write_lock_irqsave(&addr_space_lock, flags);
 	list_for_each_safe (lh, next, &hl->addr_list) {
-		as = list_entry(lh, struct hpsb_address_serve, addr_list);
+		as = list_entry(lh, struct hpsb_address_serve, hl_list);
 
-		if (as->host != host)
-			continue;
+		if (as->host == host)
+			__delete_addr(as);
+	}
+	write_unlock_irqrestore(&addr_space_lock, flags);
 
-		if (!list_empty(&as->addr_list)) {
-			list_del(&as->as_list);
-			list_del(&as->addr_list);
-			kfree(as);
+	/* Now update the config-rom to reflect anything removed by the
+	 * highlevel driver. */
+	if (update_cr && host->update_config_rom) {
+		if (hpsb_update_config_rom_image(host) < 0) {
+			HPSB_ERR("Failed to generate Configuration ROM image for host "
+				 "%s-%d", hl->name, host->id);
 		}
 	}
-	write_unlock_irqrestore(&addr_space_lock, flags);
 
+	/* And finally, remove all the host info associated between these
+	 * two. */
 	hpsb_destroy_hostinfo(hl, host);
 }
 
@@ -294,7 +309,7 @@ static int highlevel_for_each_host_unreg
 {
 	struct hpsb_highlevel *hl = __data;
 
-	__unregister_host(hl, host);
+	__unregister_host(hl, host, 1);
 
 	return 0;
 }
@@ -312,11 +327,86 @@ void hpsb_unregister_highlevel(struct hp
 	nodemgr_for_each_host(hl, highlevel_for_each_host_unreg);
 }
 
+u64 hpsb_allocate_and_register_addrspace(struct hpsb_highlevel *hl,
+					 struct hpsb_host *host,
+					 struct hpsb_address_ops *ops,
+					 u64 size, u64 alignment,
+					 u64 start, u64 end)
+{
+	struct hpsb_address_serve *as, *a1, *a2;
+	struct list_head *entry;
+	u64 retval = ~0ULL;
+	unsigned long flags;
+	u64 align_mask = ~(alignment - 1);
+
+	if ((alignment & 3) || (alignment > 0x800000000000ULL) ||
+	    ((hweight32(alignment >> 32) +
+	      hweight32(alignment & 0xffffffff) != 1))) {
+		HPSB_ERR("%s called with invalid alignment: 0x%048llx",
+			 __FUNCTION__, (unsigned long long)alignment);
+		return retval;
+	}
+
+	if (start == ~0ULL && end == ~0ULL) {
+		start = CSR1212_ALL_SPACE_BASE + 0xffff00000000ULL;  /* ohci1394.c limit */
+		end = CSR1212_ALL_SPACE_END;
+	}
+
+	if (((start|end) & ~align_mask) || (start >= end) || (end > 0x1000000000000ULL)) {
+		HPSB_ERR("%s called with invalid addresses (start = %012Lx    end = %012Lx)",
+			 __FUNCTION__, (unsigned long long)start, (unsigned long long)end);
+		return retval;
+	}
+
+	as = (struct hpsb_address_serve *)
+		kmalloc(sizeof(struct hpsb_address_serve), GFP_KERNEL);
+	if (as == NULL) {
+		return retval;
+	}
+
+	INIT_LIST_HEAD(&as->host_list);
+	INIT_LIST_HEAD(&as->hl_list);
+	as->op = ops;
+	as->host = host;
+
+	write_lock_irqsave(&addr_space_lock, flags);
+
+	list_for_each(entry, &host->addr_space) {
+		u64 a1sa, a1ea;
+		u64 a2sa, a2ea;
+
+		a1 = list_entry(entry, struct hpsb_address_serve, host_list);
+		a2 = list_entry(entry->next, struct hpsb_address_serve, host_list);
+
+		a1sa = a1->start & align_mask;
+		a1ea = (a1->end + alignment -1) & align_mask;
+		a2sa = a2->start & align_mask;
+		a2ea = (a2->end + alignment -1) & align_mask;
+
+		if ((a2sa - a1ea >= size) && (a2sa - start >= size) && (end - a1ea >= size)) {
+			as->start = max(start, a1ea);
+			as->end = as->start + size;
+			list_add(&as->host_list, entry);
+			list_add_tail(&as->hl_list, &hl->addr_list);
+			retval = as->start;
+			break;
+		}
+	}
+
+	write_unlock_irqrestore(&addr_space_lock, flags);
+
+	if (retval == ~0ULL) {
+		kfree(as);
+	}
+
+	return retval;
+}
+
 int hpsb_register_addrspace(struct hpsb_highlevel *hl, struct hpsb_host *host,
                             struct hpsb_address_ops *ops, u64 start, u64 end)
 {
         struct hpsb_address_serve *as;
-        struct list_head *entry;
+	struct list_head *lh;
         int retval = 0;
         unsigned long flags;
 
@@ -331,31 +421,35 @@ int hpsb_register_addrspace(struct hpsb_
                 return 0;
         }
 
-        INIT_LIST_HEAD(&as->as_list);
-        INIT_LIST_HEAD(&as->addr_list);
+        INIT_LIST_HEAD(&as->host_list);
+        INIT_LIST_HEAD(&as->hl_list);
         as->op = ops;
         as->start = start;
         as->end = end;
+	as->host = host;
 
-        write_lock_irqsave(&addr_space_lock, flags);
-        entry = host->addr_space.next;
+	write_lock_irqsave(&addr_space_lock, flags);
 
-        while (list_entry(entry, struct hpsb_address_serve, as_list)->end
-               <= start) {
-                if (list_entry(entry->next, struct hpsb_address_serve, as_list)
-                    ->start >= end) {
-                        list_add(&as->as_list, entry);
-                        list_add_tail(&as->addr_list, &hl->addr_list);
-                        retval = 1;
-                        break;
-                }
-                entry = entry->next;
-        }
-        write_unlock_irqrestore(&addr_space_lock, flags);
+	list_for_each(lh, &host->addr_space) {
+		struct hpsb_address_serve *as_this =
+			list_entry(lh, struct hpsb_address_serve, host_list);
+		struct hpsb_address_serve *as_next =
+			list_entry(lh->next, struct hpsb_address_serve, host_list);
 
-        if (retval == 0) {
-                kfree(as);
-        }
+		if (as_this->end > as->start)
+			break;
+
+		if (as_next->start >= as->end) {
+			list_add(&as->host_list, lh);
+			list_add_tail(&as->hl_list, &hl->addr_list);
+			retval = 1;
+			break;
+		}
+	}
+	write_unlock_irqrestore(&addr_space_lock, flags);
+
+	if (retval == 0)
+		kfree(as);
 
         return retval;
 }
@@ -365,20 +459,15 @@ int hpsb_unregister_addrspace(struct hps
 {
         int retval = 0;
         struct hpsb_address_serve *as;
-        struct list_head *entry;
+        struct list_head *lh, *next;
         unsigned long flags;
 
         write_lock_irqsave(&addr_space_lock, flags);
 
-        entry = hl->addr_list.next;
-
-        while (entry != &hl->addr_list) {
-                as = list_entry(entry, struct hpsb_address_serve, addr_list);
-                entry = entry->next;
+	list_for_each_safe (lh, next, &hl->addr_list) {
+                as = list_entry(lh, struct hpsb_address_serve, hl_list);
                 if (as->start == start && as->host == host) {
-                        list_del(&as->as_list);
-                        list_del(&as->addr_list);
-                        kfree(as);
+			__delete_addr(as);
                         retval = 1;
                         break;
                 }
@@ -419,18 +508,18 @@ void hpsb_unlisten_channel(struct hpsb_h
 
 static void init_hpsb_highlevel(struct hpsb_host *host)
 {
-	INIT_LIST_HEAD(&dummy_zero_addr.as_list);
-	INIT_LIST_HEAD(&dummy_zero_addr.addr_list);
-	INIT_LIST_HEAD(&dummy_max_addr.as_list);
-	INIT_LIST_HEAD(&dummy_max_addr.addr_list);
+	INIT_LIST_HEAD(&dummy_zero_addr.host_list);
+	INIT_LIST_HEAD(&dummy_zero_addr.hl_list);
+	INIT_LIST_HEAD(&dummy_max_addr.host_list);
+	INIT_LIST_HEAD(&dummy_max_addr.hl_list);
 
 	dummy_zero_addr.op = dummy_max_addr.op = &dummy_ops;
 
 	dummy_zero_addr.start = dummy_zero_addr.end = 0;
 	dummy_max_addr.start = dummy_max_addr.end = ((u64) 1) << 48;
 
-	list_add_tail(&dummy_zero_addr.as_list, &host->addr_space);
-	list_add_tail(&dummy_max_addr.as_list, &host->addr_space);
+	list_add_tail(&dummy_zero_addr.host_list, &host->addr_space);
+	list_add_tail(&dummy_max_addr.host_list, &host->addr_space);
 }
 
 void highlevel_add_host(struct hpsb_host *host)
@@ -445,6 +534,11 @@ void highlevel_add_host(struct hpsb_host
 			hl->add_host(host);
         }
 	up_read(&hl_drivers_sem);
+	if (host->update_config_rom) {
+		if (hpsb_update_config_rom_image(host) < 0)
+			HPSB_ERR("Failed to generate Configuration ROM image for "
+				 "host %s-%d", hl->name, host->id);
+	}
 }
 
 void highlevel_remove_host(struct hpsb_host *host)
@@ -453,7 +547,7 @@ void highlevel_remove_host(struct hpsb_h
 
 	down_read(&hl_drivers_sem);
 	list_for_each_entry(hl, &hl_drivers, hl_list)
-		__unregister_host(hl, host);
+		__unregister_host(hl, host, 0);
 	up_read(&hl_drivers_sem);
 }
 
@@ -501,16 +595,15 @@ int highlevel_read(struct hpsb_host *hos
                    u64 addr, unsigned int length, u16 flags)
 {
         struct hpsb_address_serve *as;
-        struct list_head *entry;
         unsigned int partlength;
         int rcode = RCODE_ADDRESS_ERROR;
 
         read_lock(&addr_space_lock);
 
-        entry = host->addr_space.next;
-        as = list_entry(entry, struct hpsb_address_serve, as_list);
+	list_for_each_entry(as, &host->addr_space, host_list) {
+		if (as->start > addr)
+			break;
 
-        while (as->start <= addr) {
                 if (as->end > addr) {
                         partlength = min(as->end - addr, (u64) length);
 
@@ -529,9 +622,6 @@ int highlevel_read(struct hpsb_host *hos
                                 break;
                         }
                 }
-
-                entry = entry->next;
-                as = list_entry(entry, struct hpsb_address_serve, as_list);
         }
 
         read_unlock(&addr_space_lock);
@@ -547,16 +637,15 @@ int highlevel_write(struct hpsb_host *ho
 		    void *data, u64 addr, unsigned int length, u16 flags)
 {
         struct hpsb_address_serve *as;
-        struct list_head *entry;
         unsigned int partlength;
         int rcode = RCODE_ADDRESS_ERROR;
 
         read_lock(&addr_space_lock);
 
-        entry = host->addr_space.next;
-        as = list_entry(entry, struct hpsb_address_serve, as_list);
+	list_for_each_entry(as, &host->addr_space, host_list) {
+		if (as->start > addr)
+			break;
 
-        while (as->start <= addr) {
                 if (as->end > addr) {
                         partlength = min(as->end - addr, (u64) length);
 
@@ -575,9 +664,6 @@ int highlevel_write(struct hpsb_host *ho
                                 break;
                         }
                 }
-
-                entry = entry->next;
-                as = list_entry(entry, struct hpsb_address_serve, as_list);
         }
 
         read_unlock(&addr_space_lock);
@@ -594,15 +680,14 @@ int highlevel_lock(struct hpsb_host *hos
                    u64 addr, quadlet_t data, quadlet_t arg, int ext_tcode, u16 flags)
 {
         struct hpsb_address_serve *as;
-        struct list_head *entry;
         int rcode = RCODE_ADDRESS_ERROR;
 
         read_lock(&addr_space_lock);
 
-        entry = host->addr_space.next;
-        as = list_entry(entry, struct hpsb_address_serve, as_list);
+	list_for_each_entry(as, &host->addr_space, host_list) {
+		if (as->start > addr)
+			break;
 
-        while (as->start <= addr) {
                 if (as->end > addr) {
                         if (as->op->lock) {
                                 rcode = as->op->lock(host, nodeid, store, addr,
@@ -613,9 +698,6 @@ int highlevel_lock(struct hpsb_host *hos
 
                         break;
                 }
-
-                entry = entry->next;
-                as = list_entry(entry, struct hpsb_address_serve, as_list);
         }
 
         read_unlock(&addr_space_lock);
@@ -627,15 +709,14 @@ int highlevel_lock64(struct hpsb_host *h
                      u64 addr, octlet_t data, octlet_t arg, int ext_tcode, u16 flags)
 {
         struct hpsb_address_serve *as;
-        struct list_head *entry;
         int rcode = RCODE_ADDRESS_ERROR;
 
         read_lock(&addr_space_lock);
 
-        entry = host->addr_space.next;
-        as = list_entry(entry, struct hpsb_address_serve, as_list);
+	list_for_each_entry(as, &host->addr_space, host_list) {
+		if (as->start > addr)
+			break;
 
-        while (as->start <= addr) {
                 if (as->end > addr) {
                         if (as->op->lock64) {
                                 rcode = as->op->lock64(host, nodeid, store,
@@ -647,9 +728,6 @@ int highlevel_lock64(struct hpsb_host *h
 
                         break;
                 }
-
-                entry = entry->next;
-                as = list_entry(entry, struct hpsb_address_serve, as_list);
         }
 
         read_unlock(&addr_space_lock);
--- diff/drivers/ieee1394/highlevel.h	2004-02-09 10:36:10.000000000 +0000
+++ source/drivers/ieee1394/highlevel.h	2004-02-23 13:56:41.000000000 +0000
@@ -4,9 +4,9 @@
 
 
 struct hpsb_address_serve {
-        struct list_head as_list; /* global list */
+        struct list_head host_list; /* per host list */
         
-        struct list_head addr_list; /* hpsb_highlevel list */
+        struct list_head hl_list; /* hpsb_highlevel list */
 
         struct hpsb_address_ops *op;
 
@@ -140,6 +140,11 @@ void hpsb_unregister_highlevel(struct hp
  * It returns true for successful allocation.  There is no unregister function,
  * all address spaces are deallocated together with the hpsb_highlevel.
  */
+u64 hpsb_allocate_and_register_addrspace(struct hpsb_highlevel *hl,
+					 struct hpsb_host *host,
+					 struct hpsb_address_ops *ops,
+					 u64 size, u64 alignment,
+					 u64 start, u64 end);
 int hpsb_register_addrspace(struct hpsb_highlevel *hl, struct hpsb_host *host,
                             struct hpsb_address_ops *ops, u64 start, u64 end);
 
--- diff/drivers/ieee1394/hosts.c	2004-02-09 10:36:10.000000000 +0000
+++ source/drivers/ieee1394/hosts.c	2004-02-23 13:56:41.000000000 +0000
@@ -17,14 +17,46 @@
 #include <linux/init.h>
 #include <linux/slab.h>
 #include <linux/pci.h>
+#include <linux/timer.h>
 
+#include "csr1212.h"
+#include "ieee1394.h"
 #include "ieee1394_types.h"
 #include "hosts.h"
 #include "ieee1394_core.h"
 #include "highlevel.h"
 #include "nodemgr.h"
+#include "csr.h"
 
 
+static void delayed_reset_bus(unsigned long __reset_info)
+{
+	struct hpsb_host *host = (struct hpsb_host*)__reset_info;
+	int generation = host->csr.generation + 1;
+
+	/* The generation field rolls over to 2 rather than 0 per IEEE
+	 * 1394a-2000. */
+	if (generation > 0xf || generation < 2)
+		generation = 2;
+
+	CSR_SET_BUS_INFO_GENERATION(host->csr.rom, generation);
+	if (csr1212_generate_csr_image(host->csr.rom) != CSR1212_SUCCESS) {
+		/* CSR image creation failed, reset generation field and do not
+		 * issue a bus reset. */
+		CSR_SET_BUS_INFO_GENERATION(host->csr.rom, host->csr.generation);
+		return;
+	}
+
+	host->csr.generation = generation;
+
+	host->update_config_rom = 0;
+	if (host->driver->set_hw_config_rom)
+		host->driver->set_hw_config_rom(host, host->csr.rom->bus_info_data);
+
+	host->csr.gen_timestamp[host->csr.generation] = jiffies;
+	hpsb_reset_bus(host, SHORT_RESET);
+}
+
 static int dummy_transmit_packet(struct hpsb_host *h, struct hpsb_packet *p)
 {
         return 0;
@@ -83,6 +115,12 @@ struct hpsb_host *hpsb_alloc_host(struct
         if (!h) return NULL;
         memset(h, 0, sizeof(struct hpsb_host) + extra);
 
+	h->csr.rom = csr1212_create_csr(&csr_bus_ops, CSR_BUS_INFO_SIZE, h);
+	if (!h->csr.rom) {
+		kfree(h);
+		return NULL;
+	}
+
 	h->hostdata = h + 1;
         h->driver = drv;
 
@@ -91,6 +129,12 @@ struct hpsb_host *hpsb_alloc_host(struct
 
 	INIT_LIST_HEAD(&h->addr_space);
 
+	init_timer(&h->delayed_reset);
+	h->delayed_reset.function = delayed_reset_bus;
+	h->delayed_reset.data = (unsigned long)h;
+	for (i = 2; i < 16; i++)
+		h->csr.gen_timestamp[i] = jiffies - 60 * HZ;
+
 	for (i = 0; i < ARRAY_SIZE(h->tpool); i++)
 		HPSB_TPOOL_INIT(&h->tpool[i]);
 
@@ -116,7 +160,14 @@ struct hpsb_host *hpsb_alloc_host(struct
 	memcpy(&h->device, &nodemgr_dev_template_host, sizeof(h->device));
 	h->device.parent = dev;
 	snprintf(h->device.bus_id, BUS_ID_SIZE, "fw-host%d", h->id);
+
+	h->class_dev.dev = &h->device;
+	h->class_dev.class = &hpsb_host_class;
+	snprintf(h->class_dev.class_id, BUS_ID_SIZE, "fw-host%d", h->id);
+
 	device_register(&h->device);
+	class_device_register(&h->class_dev);
+	get_device(&h->device);
 
 	return h;
 }
@@ -124,7 +175,6 @@ struct hpsb_host *hpsb_alloc_host(struct
 void hpsb_add_host(struct hpsb_host *host)
 {
         highlevel_add_host(host);
-        host->driver->devctl(host, RESET_BUS, LONG_RESET);
 }
 
 void hpsb_remove_host(struct hpsb_host *host)
@@ -134,5 +184,38 @@ void hpsb_remove_host(struct hpsb_host *
 
         highlevel_remove_host(host);
 
+	class_device_unregister(&host->class_dev);
 	device_unregister(&host->device);
 }
+
+int hpsb_update_config_rom_image(struct hpsb_host *host)
+{
+	unsigned long reset_time;
+	int next_gen = host->csr.generation + 1;
+
+	if (!host->update_config_rom)
+		return -EINVAL;
+
+	if (next_gen > 0xf)
+		next_gen = 2;
+
+	/* Stop the delayed interrupt, we're about to change the config rom and
+	 * it would be a waste to do a bus reset twice. */
+	del_timer_sync(&host->delayed_reset);
+
+	/* IEEE 1394a-2000 prohibits using the same generation number
+	 * twice in a 60 second period. */
+	if (jiffies - host->csr.gen_timestamp[next_gen] < 60 * HZ)
+		/* Wait 60 seconds from the last time this generation number was
+		 * used. */
+		reset_time = (60 * HZ) + host->csr.gen_timestamp[next_gen];
+	else
+		/* Wait 1 second in case some other code wants to change the
+		 * Config ROM in the near future. */
+		reset_time = jiffies + HZ;
+
+	/* This will add the timer as well as modify it */
+	mod_timer(&host->delayed_reset, reset_time);
+
+	return 0;
+}
--- diff/drivers/ieee1394/hosts.h	2004-02-09 10:36:10.000000000 +0000
+++ source/drivers/ieee1394/hosts.h	2004-02-23 13:56:41.000000000 +0000
@@ -10,14 +10,6 @@
 #include "ieee1394_types.h"
 #include "csr.h"
 
-/* size of the array used to store config rom (in quadlets)
-   maximum is 0x100. About 0x40 is needed for the default
-   entries. So 0x80 should provide enough space for additional
-   directories etc. 
-   Note: All lowlevel drivers are required to allocate at least
-         this amount of memory for the configuration rom!
-*/
-#define CSR_CONFIG_ROM_SIZE       0x100
 
 struct hpsb_packet;
 struct hpsb_iso;
@@ -69,6 +61,10 @@ struct hpsb_host {
 	int id;
 
 	struct device device;
+	struct class_device class_dev;
+
+	int update_config_rom;
+	struct timer_list delayed_reset;
 
 	struct list_head addr_space;
 };
@@ -153,12 +149,10 @@ struct hpsb_host_driver {
 	struct module *owner;
 	const char *name;
 
-        /* This function must store a pointer to the configuration ROM into the
-         * location referenced to by pointer and return the size of the ROM. It
-         * may not fail.  If any allocation is required, it must be done
-         * earlier.
-         */
-        size_t (*get_rom) (struct hpsb_host *host, quadlet_t **pointer);
+	/* The hardware driver may optionally support a function that is used
+	 * to set the hardware ConfigROM if the hardware supports handling
+	 * reads to the ConfigROM on its own. */
+	void (*set_hw_config_rom) (struct hpsb_host *host, quadlet_t *config_rom);
 
         /* This function shall implement packet transmission based on
          * packet->type.  It shall CRC both parts of the packet (unless
@@ -200,24 +194,18 @@ struct hpsb_host *hpsb_alloc_host(struct
 void hpsb_add_host(struct hpsb_host *host);
 void hpsb_remove_host(struct hpsb_host *h);
 
-/* updates the configuration rom of a host.
- * rom_version must be the current version,
- * otherwise it will fail with return value -1.
- * Return value -2 indicates that the new
- * rom version is too big.
- * Return value 0 indicates success
- */
+/* The following 2 functions are deprecated and will be removed when the
+ * raw1394/libraw1394 update is complete. */
 int hpsb_update_config_rom(struct hpsb_host *host,
       const quadlet_t *new_rom, size_t size, unsigned char rom_version);
-
-/* reads the current version of the configuration rom of a host.
- * buffersize is the size of the buffer, rom_size
- * returns the size of the current rom image.
- * rom_version is the version number of the fetched rom.
- * return value -1 indicates, that the buffer was
- * too small, 0 indicates success.
- */
 int hpsb_get_config_rom(struct hpsb_host *host, quadlet_t *buffer,
       size_t buffersize, size_t *rom_size, unsigned char *rom_version);
 
+/* Updates the configuration rom image of a host.  rom_version must be the
+ * current version, otherwise it will fail with return value -1. If this
+ * host does not support config-rom-update, it will return -EINVAL.
+ * Return value 0 indicates success.
+ */
+int hpsb_update_config_rom_image(struct hpsb_host *host);
+
 #endif /* _IEEE1394_HOSTS_H */
--- diff/drivers/ieee1394/ieee1394_core.c	2004-02-09 10:36:10.000000000 +0000
+++ source/drivers/ieee1394/ieee1394_core.c	2004-02-23 13:56:41.000000000 +0000
@@ -515,9 +515,9 @@ int hpsb_send_packet(struct hpsb_packet 
         if (packet->node_id == host->node_id)
         { /* it is a local request, so handle it locally */
                 quadlet_t *data;
-                size_t size=packet->data_size+packet->header_size;
+                size_t size = packet->data_size + packet->header_size;
 
-                data = kmalloc(packet->header_size + packet->data_size, GFP_ATOMIC);
+                data = kmalloc(size, GFP_ATOMIC);
                 if (!data) {
                         HPSB_ERR("unable to allocate memory for concatenating header and data");
                         return -ENOMEM;
@@ -526,12 +526,12 @@ int hpsb_send_packet(struct hpsb_packet 
                 memcpy(data, packet->header, packet->header_size);
 
                 if (packet->data_size)
-			memcpy(((u8*)data)+packet->header_size, packet->data, packet->data_size);
+			memcpy(((u8*)data) + packet->header_size, packet->data, packet->data_size);
 
                 dump_packet("send packet local:", packet->header,
                             packet->header_size);
 
-                hpsb_packet_sent(host, packet,  packet->expect_response?ACK_PENDING:ACK_COMPLETE);
+                hpsb_packet_sent(host, packet, packet->expect_response ? ACK_PENDING : ACK_COMPLETE);
                 hpsb_packet_received(host, data, size, 0);
 
                 kfree(data);
@@ -935,8 +935,7 @@ void hpsb_packet_received(struct hpsb_ho
 void abort_requests(struct hpsb_host *host)
 {
         unsigned long flags;
-        struct hpsb_packet *packet;
-        struct list_head *lh, *tlh;
+        struct hpsb_packet *packet, *packet_next;
         LIST_HEAD(llist);
 
         host->driver->devctl(host, CANCEL_REQUESTS, 0);
@@ -946,8 +945,7 @@ void abort_requests(struct hpsb_host *ho
         INIT_LIST_HEAD(&host->pending_packets);
         spin_unlock_irqrestore(&host->pending_pkt_lock, flags);
 
-        list_for_each_safe(lh, tlh, &llist) {
-                packet = list_entry(lh, struct hpsb_packet, list);
+        list_for_each_entry_safe(packet, packet_next, &llist, list) {
                 list_del(&packet->list);
                 packet->state = hpsb_complete;
                 packet->ack_code = ACKX_ABORTED;
@@ -959,9 +957,8 @@ void abort_timedouts(unsigned long __opa
 {
 	struct hpsb_host *host = (struct hpsb_host *)__opaque;
         unsigned long flags;
-        struct hpsb_packet *packet;
+        struct hpsb_packet *packet, *packet_next;
         unsigned long expire;
-        struct list_head *lh, *tlh;
         LIST_HEAD(expiredlist);
 
         spin_lock_irqsave(&host->csr.lock, flags);
@@ -970,8 +967,7 @@ void abort_timedouts(unsigned long __opa
 
         spin_lock_irqsave(&host->pending_pkt_lock, flags);
 
-	list_for_each_safe(lh, tlh, &host->pending_packets) {
-                packet = list_entry(lh, struct hpsb_packet, list);
+	list_for_each_entry_safe(packet, packet_next, &host->pending_packets, list) {
                 if (time_before(packet->sendtime + expire, jiffies)) {
                         list_del(&packet->list);
                         list_add(&packet->list, &expiredlist);
@@ -983,8 +979,7 @@ void abort_timedouts(unsigned long __opa
 
         spin_unlock_irqrestore(&host->pending_pkt_lock, flags);
 
-        list_for_each_safe(lh, tlh, &expiredlist) {
-                packet = list_entry(lh, struct hpsb_packet, list);
+        list_for_each_entry_safe(packet, packet_next, &expiredlist, list) {
                 list_del(&packet->list);
                 packet->state = hpsb_complete;
                 packet->ack_code = ACKX_TIMEOUT;
@@ -995,6 +990,8 @@ void abort_timedouts(unsigned long __opa
 
 static int __init ieee1394_init(void)
 {
+	int i;
+
 	devfs_mk_dir("ieee1394");
 
 	if (register_chrdev_region(IEEE1394_CORE_DEV, 256, "ieee1394")) {
@@ -1008,8 +1005,12 @@ static int __init ieee1394_init(void)
 					      0, 0, NULL, NULL);
 
 	bus_register(&ieee1394_bus_type);
+	for (i = 0; fw_bus_attrs[i]; i++)
+		bus_create_file(&ieee1394_bus_type, fw_bus_attrs[i]);
+	class_register(&hpsb_host_class);
 
-	init_csr();
+	if (init_csr())
+		return -ENOMEM;
 
 	if (!disable_nodemgr)
 		init_ieee1394_nodemgr();
@@ -1021,11 +1022,16 @@ static int __init ieee1394_init(void)
 
 static void __exit ieee1394_cleanup(void)
 {
+	int i;
+
 	if (!disable_nodemgr)
 		cleanup_ieee1394_nodemgr();
 
 	cleanup_csr();
 
+	class_unregister(&hpsb_host_class);
+	for (i = 0; fw_bus_attrs[i]; i++)
+		bus_remove_file(&ieee1394_bus_type, fw_bus_attrs[i]);
 	bus_unregister(&ieee1394_bus_type);
 
 	kmem_cache_destroy(hpsb_packet_cache);
@@ -1043,6 +1049,7 @@ module_exit(ieee1394_cleanup);
 EXPORT_SYMBOL(hpsb_alloc_host);
 EXPORT_SYMBOL(hpsb_add_host);
 EXPORT_SYMBOL(hpsb_remove_host);
+EXPORT_SYMBOL(hpsb_update_config_rom_image);
 
 /** ieee1394_core.c **/
 EXPORT_SYMBOL(hpsb_speedto_str);
@@ -1081,6 +1088,7 @@ EXPORT_SYMBOL(hpsb_register_highlevel);
 EXPORT_SYMBOL(hpsb_unregister_highlevel);
 EXPORT_SYMBOL(hpsb_register_addrspace);
 EXPORT_SYMBOL(hpsb_unregister_addrspace);
+EXPORT_SYMBOL(hpsb_allocate_and_register_addrspace);
 EXPORT_SYMBOL(hpsb_listen_channel);
 EXPORT_SYMBOL(hpsb_unlisten_channel);
 EXPORT_SYMBOL(hpsb_get_hostinfo);
@@ -1113,7 +1121,6 @@ EXPORT_SYMBOL(nodemgr_for_each_host);
 
 /** csr.c **/
 EXPORT_SYMBOL(hpsb_update_config_rom);
-EXPORT_SYMBOL(hpsb_get_config_rom);
 
 /** dma.c **/
 EXPORT_SYMBOL(dma_prog_region_init);
@@ -1144,3 +1151,34 @@ EXPORT_SYMBOL(hpsb_iso_packet_sent);
 EXPORT_SYMBOL(hpsb_iso_packet_received);
 EXPORT_SYMBOL(hpsb_iso_wake);
 EXPORT_SYMBOL(hpsb_iso_recv_flush);
+
+/** csr1212.c **/
+EXPORT_SYMBOL(csr1212_create_csr);
+EXPORT_SYMBOL(csr1212_init_local_csr);
+EXPORT_SYMBOL(csr1212_new_immediate);
+EXPORT_SYMBOL(csr1212_new_leaf);
+EXPORT_SYMBOL(csr1212_new_csr_offset);
+EXPORT_SYMBOL(csr1212_new_directory);
+EXPORT_SYMBOL(csr1212_associate_keyval);
+EXPORT_SYMBOL(csr1212_attach_keyval_to_directory);
+EXPORT_SYMBOL(csr1212_new_extended_immediate);
+EXPORT_SYMBOL(csr1212_new_extended_leaf);
+EXPORT_SYMBOL(csr1212_new_descriptor_leaf);
+EXPORT_SYMBOL(csr1212_new_textual_descriptor_leaf);
+EXPORT_SYMBOL(csr1212_new_string_descriptor_leaf);
+EXPORT_SYMBOL(csr1212_new_icon_descriptor_leaf);
+EXPORT_SYMBOL(csr1212_new_modifiable_descriptor_leaf);
+EXPORT_SYMBOL(csr1212_new_keyword_leaf);
+EXPORT_SYMBOL(csr1212_detach_keyval_from_directory);
+EXPORT_SYMBOL(csr1212_disassociate_keyval);
+EXPORT_SYMBOL(csr1212_release_keyval);
+EXPORT_SYMBOL(csr1212_destroy_csr);
+EXPORT_SYMBOL(csr1212_read);
+EXPORT_SYMBOL(csr1212_generate_positions);
+EXPORT_SYMBOL(csr1212_generate_layout_order);
+EXPORT_SYMBOL(csr1212_fill_cache);
+EXPORT_SYMBOL(csr1212_generate_csr_image);
+EXPORT_SYMBOL(csr1212_parse_keyval);
+EXPORT_SYMBOL(csr1212_parse_csr);
+EXPORT_SYMBOL(_csr1212_read_keyval);
+EXPORT_SYMBOL(_csr1212_destroy_keyval);
--- diff/drivers/ieee1394/ieee1394_core.h	2004-02-09 10:36:10.000000000 +0000
+++ source/drivers/ieee1394/ieee1394_core.h	2004-02-23 13:56:41.000000000 +0000
@@ -215,5 +215,6 @@ static inline unsigned char ieee1394_fil
 
 /* Our sysfs bus entry */
 extern struct bus_type ieee1394_bus_type;
+extern struct class hpsb_host_class;
 
 #endif /* _IEEE1394_CORE_H */
--- diff/drivers/ieee1394/nodemgr.c	2004-01-19 10:22:56.000000000 +0000
+++ source/drivers/ieee1394/nodemgr.c	2004-02-23 13:56:41.000000000 +0000
@@ -18,6 +18,7 @@
 #include <linux/completion.h>
 #include <linux/delay.h>
 #include <linux/pci.h>
+#include <linux/moduleparam.h>
 #include <asm/atomic.h>
 
 #include "ieee1394_types.h"
@@ -28,6 +29,15 @@
 #include "csr.h"
 #include "nodemgr.h"
 
+static int ignore_drivers = 0;
+module_param(ignore_drivers, int, 0444);
+MODULE_PARM_DESC(ignore_drivers, "Disable automatic probing for drivers.");
+
+struct nodemgr_csr_info {
+	struct hpsb_host *host;
+	nodeid_t nodeid;
+	unsigned int generation;
+};
 
 
 static char *nodemgr_find_oui_name(int oui)
@@ -47,6 +57,37 @@ static char *nodemgr_find_oui_name(int o
 }
 
 
+static int nodemgr_bus_read(struct csr1212_csr *csr, u64 addr, u16 length,
+                            void *buffer, void *__ci)
+{
+	struct nodemgr_csr_info *ci = (struct nodemgr_csr_info*)__ci;
+	int i, ret = 0;
+
+	for (i = 0; i < 3; i++) {
+		ret = hpsb_read(ci->host, ci->nodeid, ci->generation, addr,
+				buffer, length);
+		if (!ret)
+			break;
+
+		set_current_state(TASK_INTERRUPTIBLE);
+		if (schedule_timeout (HZ/3))
+			return -EINTR;
+	}
+
+	return ret;
+}
+
+static int nodemgr_get_max_rom(quadlet_t *bus_info_data, void *__ci)
+{
+	return (bus_info_data[2] >> 8) & 0x3;
+}
+
+static struct csr1212_bus_ops nodemgr_csr_ops = {
+	.bus_read =	nodemgr_bus_read,
+	.get_max_rom =	nodemgr_get_max_rom
+};
+
+
 /* 
  * Basically what we do here is start off retrieving the bus_info block.
  * From there will fill in some info about the node, verify it is of IEEE
@@ -69,7 +110,6 @@ static char *nodemgr_find_oui_name(int o
 
 static DECLARE_MUTEX(nodemgr_serialize);
 
-
 struct host_info {
 	struct hpsb_host *host;
 	struct list_head list;
@@ -79,19 +119,108 @@ struct host_info {
 	char daemon_name[15];
 };
 
+static int nodemgr_bus_match(struct device * dev, struct device_driver * drv);
+static int nodemgr_hotplug(struct device *dev, char **envp, int num_envp,
+			   char *buffer, int buffer_size);
+static void nodemgr_resume_ne(struct node_entry *ne);
+static void nodemgr_remove_ne(struct node_entry *ne);
+static struct node_entry *find_entry_by_guid(u64 guid);
+
+struct bus_type ieee1394_bus_type = {
+	.name		= "ieee1394",
+	.match		= nodemgr_bus_match,
+	.hotplug	= nodemgr_hotplug,
+};
+
+static void host_cls_release(struct class_device *class_dev)
+{
+	put_device(&container_of((class_dev), struct hpsb_host, class_dev)->device);
+}
+
+struct class hpsb_host_class = {
+	.name		= "ieee1394_host",
+	.release	= host_cls_release,
+};
+
+static void ne_cls_release(struct class_device *class_dev)
+{
+	put_device(&container_of((class_dev), struct node_entry, class_dev)->device);
+}
+
+struct class nodemgr_ne_class = {
+	.name		= "ieee1394_node",
+	.release	= ne_cls_release,
+};
+
 static struct hpsb_highlevel nodemgr_highlevel;
 
-static int nodemgr_driverdata_ne;
-static int nodemgr_driverdata_host;
+static int nodemgr_platform_data_ud;
+
+static int nodemgr_generic_probe(struct device *dev)
+{
+	return -ENODEV;
+}
 
 static struct device_driver nodemgr_driver_ne = {
 	.name	= "ieee1394_node",
 	.bus	= &ieee1394_bus_type,
+	.probe	= nodemgr_generic_probe,
 };
 
 static struct device_driver nodemgr_driver_host = {
 	.name	= "ieee1394_host",
 	.bus	= &ieee1394_bus_type,
+	.probe	= nodemgr_generic_probe,
+};
+
+static void nodemgr_release_ud(struct device *dev)
+{
+	struct unit_directory *ud = container_of(dev, struct unit_directory, device);
+
+	if (ud->vendor_name_kv)
+		csr1212_release_keyval(ud->vendor_name_kv);
+	if (ud->model_name_kv)
+		csr1212_release_keyval(ud->model_name_kv);
+
+	kfree(ud);
+}
+
+static void nodemgr_release_ne(struct device *dev)
+{
+	struct node_entry *ne = container_of(dev, struct node_entry, device);
+
+	if (ne->vendor_name_kv)
+		csr1212_release_keyval(ne->vendor_name_kv);
+
+	kfree(ne);
+}
+
+
+static void nodemgr_release_host(struct device *dev)
+{
+	struct hpsb_host *host = container_of(dev, struct hpsb_host, device);
+
+	csr1212_destroy_csr(host->csr.rom);
+
+	kfree(host);
+}
+
+static struct device nodemgr_dev_template_ud = {
+	.bus		= &ieee1394_bus_type,
+	.release	= nodemgr_release_ud,
+	.platform_data	= &nodemgr_platform_data_ud,
+};
+
+static struct device nodemgr_dev_template_ne = {
+	.bus		= &ieee1394_bus_type,
+	.release	= nodemgr_release_ne,
+	.driver		= &nodemgr_driver_ne,
+};
+
+struct device nodemgr_dev_template_host = {
+	.bus		= &ieee1394_bus_type,
+	.release	= nodemgr_release_host,
+	.driver		= &nodemgr_driver_host,
 };
 
 
@@ -107,6 +236,26 @@ static struct device_attribute dev_attr_
 	.show   = fw_show_##class##_##field,				\
 };
 
+#define fw_attr_td(class, class_type, td_kv)				\
+static ssize_t fw_show_##class##_##td_kv (struct device *dev, char *buf)\
+{									\
+	int len;							\
+	class_type *class = container_of(dev, class_type, device);	\
+	len = (class->td_kv->value.leaf.len - 2) * sizeof(quadlet_t);	\
+	memcpy(buf,							\
+	       CSR1212_TEXTUAL_DESCRIPTOR_LEAF_DATA(class->td_kv),	\
+	       len);							\
+	while ((buf + len - 1) == '\0')					\
+		len--;							\
+	buf[len++] = '\n';						\
+	buf[len] = '\0';						\
+	return len;							\
+}									\
+static struct device_attribute dev_attr_##class##_##td_kv = {		\
+	.attr = {.name = __stringify(td_kv), .mode = S_IRUGO },		\
+	.show   = fw_show_##class##_##td_kv,				\
+};
+
 
 #define fw_drv_attr(field, type, format_string)			\
 static ssize_t fw_drv_show_##field (struct device_driver *drv, char *buf) \
@@ -126,10 +275,13 @@ static ssize_t fw_show_ne_bus_options(st
 	struct node_entry *ne = container_of(dev, struct node_entry, device);
 
 	return sprintf(buf, "IRMC(%d) CMC(%d) ISC(%d) BMC(%d) PMC(%d) GEN(%d) "
-			"LSPD(%d) MAX_REC(%d) CYC_CLK_ACC(%d)\n", ne->busopt.irmc,
-			ne->busopt.cmc, ne->busopt.isc, ne->busopt.bmc,
-			ne->busopt.pmc, ne->busopt.generation, ne->busopt.lnkspd,
-			ne->busopt.max_rec, ne->busopt.cyc_clk_acc);
+		       "LSPD(%d) MAX_REC(%d) MAX_ROM(%d) CYC_CLK_ACC(%d)\n",
+		       ne->busopt.irmc,
+		       ne->busopt.cmc, ne->busopt.isc, ne->busopt.bmc,
+		       ne->busopt.pmc, ne->busopt.generation, ne->busopt.lnkspd,
+		       ne->busopt.max_rec, 
+		       ne->busopt.max_rom,
+		       ne->busopt.cyc_clk_acc);
 }
 static DEVICE_ATTR(bus_options,S_IRUGO,fw_show_ne_bus_options,NULL);
 
@@ -159,19 +311,121 @@ static ssize_t fw_show_ne_tlabels_mask(s
 	return sprintf(buf, "0x%016lx\n", ne->tpool->pool[0]);
 #endif
 }
-static DEVICE_ATTR(tlabels_mask,S_IRUGO,fw_show_ne_tlabels_mask,NULL);
+static DEVICE_ATTR(tlabels_mask, S_IRUGO, fw_show_ne_tlabels_mask, NULL);
+
+
+static ssize_t fw_set_ignore_driver(struct device *dev, const char *buf, size_t count)
+{
+	struct unit_directory *ud = container_of(dev, struct unit_directory, device);
+	int state = simple_strtoul(buf, NULL, 10);
+
+	if (state == 1) {
+		down_write(&dev->bus->subsys.rwsem);
+		device_release_driver(dev);
+		ud->ignore_driver = 1;
+		up_write(&dev->bus->subsys.rwsem);
+	} else if (!state)
+		ud->ignore_driver = 0;
+
+	return count;
+}
+static ssize_t fw_get_ignore_driver(struct device *dev, char *buf)
+{
+	struct unit_directory *ud = container_of(dev, struct unit_directory, device);
+
+	return sprintf(buf, "%d\n", ud->ignore_driver);
+}	
+static DEVICE_ATTR(ignore_driver, S_IWUSR | S_IRUGO, fw_get_ignore_driver, fw_set_ignore_driver);
+
+
+static ssize_t fw_set_destroy_node(struct bus_type *bus, const char *buf, size_t count)
+{
+	struct node_entry *ne;
+	u64 guid = (u64)simple_strtoull(buf, NULL, 16);
+
+	ne = find_entry_by_guid(guid);
+
+	if (ne == NULL || !ne->in_limbo)
+		return -EINVAL;
+
+	nodemgr_remove_ne(ne);
+
+	return count;
+}
+static ssize_t fw_get_destroy_node(struct bus_type *bus, char *buf)
+{
+	return sprintf(buf, "You can destroy in_limbo nodes by writing their GUID to this file\n");
+}
+static BUS_ATTR(destroy_node, S_IWUSR | S_IRUGO, fw_get_destroy_node, fw_set_destroy_node);
+
+static int nodemgr_rescan_bus_thread(void *__unused)
+{
+	/* No userlevel access needed */
+	daemonize("kfwrescan");
+	allow_signal(SIGTERM);
+
+	bus_rescan_devices(&ieee1394_bus_type);
+
+	return 0;
+}
+
+static ssize_t fw_set_rescan(struct bus_type *bus, const char *buf, size_t count)
+{
+	int state = simple_strtoul(buf, NULL, 10);
+
+	/* Don't wait for this, or care about errors. Root could do
+	 * something stupid and spawn this a lot of times, but that's
+	 * root's fault. */
+	if (state == 1)
+		kernel_thread(nodemgr_rescan_bus_thread, NULL, CLONE_KERNEL);
+
+	return count;
+}
+static ssize_t fw_get_rescan(struct bus_type *bus, char *buf)
+{
+	return sprintf(buf, "You can force a rescan of the bus for "
+			"drivers by writing a 1 to this file\n");
+}
+static BUS_ATTR(rescan, S_IWUSR | S_IRUGO, fw_get_rescan, fw_set_rescan);
+
+
+static ssize_t fw_set_ignore_drivers(struct bus_type *bus, const char *buf, size_t count)
+{
+	int state = simple_strtoul(buf, NULL, 10);
+
+	if (state == 1)
+		ignore_drivers = 1;
+	else if (!state)
+		ignore_drivers = 0;
+
+	return count;
+}
+static ssize_t fw_get_ignore_drivers(struct bus_type *bus, char *buf)
+{
+	return sprintf(buf, "%d\n", ignore_drivers);
+}
+static BUS_ATTR(ignore_drivers, S_IWUSR | S_IRUGO, fw_get_ignore_drivers, fw_set_ignore_drivers);
+
+
+struct bus_attribute *const fw_bus_attrs[] = {
+	&bus_attr_destroy_node,
+	&bus_attr_rescan,
+	&bus_attr_ignore_drivers,
+	NULL
+};
 
 
 fw_attr(ne, struct node_entry, capabilities, unsigned int, "0x%06x\n")
 fw_attr(ne, struct node_entry, nodeid, unsigned int, "0x%04x\n")
 
 fw_attr(ne, struct node_entry, vendor_id, unsigned int, "0x%06x\n")
-fw_attr(ne, struct node_entry, vendor_name, const char *, "%s\n")
+fw_attr_td(ne, struct node_entry, vendor_name_kv)
 fw_attr(ne, struct node_entry, vendor_oui, const char *, "%s\n")
 
 fw_attr(ne, struct node_entry, guid, unsigned long long, "0x%016Lx\n")
 fw_attr(ne, struct node_entry, guid_vendor_id, unsigned int, "0x%06x\n")
 fw_attr(ne, struct node_entry, guid_vendor_oui, const char *, "%s\n")
+fw_attr(ne, struct node_entry, in_limbo, int, "%d\n");
 
 static struct device_attribute *const fw_ne_attrs[] = {
 	&dev_attr_ne_guid,
@@ -194,13 +448,14 @@ fw_attr(ud, struct unit_directory, vendo
 fw_attr(ud, struct unit_directory, model_id, unsigned int, "0x%06x\n")
 fw_attr(ud, struct unit_directory, specifier_id, unsigned int, "0x%06x\n")
 fw_attr(ud, struct unit_directory, version, unsigned int, "0x%06x\n")
-fw_attr(ud, struct unit_directory, vendor_name, const char *, "%s\n")
+fw_attr_td(ud, struct unit_directory, vendor_name_kv)
 fw_attr(ud, struct unit_directory, vendor_oui, const char *, "%s\n")
-fw_attr(ud, struct unit_directory, model_name, const char *, "%s\n")
+fw_attr_td(ud, struct unit_directory, model_name_kv)
 
 static struct device_attribute *const fw_ud_attrs[] = {
 	&dev_attr_ud_address,
 	&dev_attr_ud_length,
+	&dev_attr_ignore_driver,
 };
 
 
@@ -358,14 +613,14 @@ static void nodemgr_create_ud_dev_files(
 
 	if (ud->flags & UNIT_DIRECTORY_VENDOR_ID) {
 		device_create_file(dev, &dev_attr_ud_vendor_id);
-		if (ud->flags & UNIT_DIRECTORY_VENDOR_TEXT)
-			device_create_file(dev, &dev_attr_ud_vendor_name);
+		if (ud->vendor_name_kv)
+			device_create_file(dev, &dev_attr_ud_vendor_name_kv);
 	}
 
 	if (ud->flags & UNIT_DIRECTORY_MODEL_ID) {
 		device_create_file(dev, &dev_attr_ud_model_id);
-		if (ud->flags & UNIT_DIRECTORY_MODEL_TEXT)
-			device_create_file(dev, &dev_attr_ud_model_name);
+		if (ud->model_name_kv)
+			device_create_file(dev, &dev_attr_ud_model_name_kv);
 	}
 }
 
@@ -376,14 +631,17 @@ static int nodemgr_bus_match(struct devi
         struct unit_directory *ud;
 	struct ieee1394_device_id *id;
 
-	if (dev->driver_data == &nodemgr_driverdata_ne ||
-	    dev->driver_data == &nodemgr_driverdata_host ||
-	    drv == &nodemgr_driver_ne || drv == &nodemgr_driver_host)
+	/* We only match unit directories, and ignore our internal drivers */
+	if (dev->platform_data != &nodemgr_platform_data_ud ||
+	    drv->probe == nodemgr_generic_probe)
 		return 0;
 
 	ud = container_of(dev, struct unit_directory, device);
 	driver = container_of(drv, struct hpsb_protocol_driver, driver);
 
+	if (ud->ne->in_limbo || ud->ignore_driver)
+		return 0;
+
         for (id = driver->id_table; id->match_flags != 0; id++) {
                 if ((id->match_flags & IEEE1394_MATCH_VENDOR_ID) &&
                     id->vendor_id != ud->vendor_id)
@@ -408,24 +666,6 @@ static int nodemgr_bus_match(struct devi
 }
 
 
-static void nodemgr_release_ud(struct device *dev)
-{
-	kfree(container_of(dev, struct unit_directory, device));
-}
-
-
-static void nodemgr_release_ne(struct device *dev)
-{
-	kfree(container_of(dev, struct node_entry, device));
-}
-
-
-static void nodemgr_release_host(struct device *dev)
-{
-	kfree(container_of(dev, struct hpsb_host, device));
-}
-
-
 static void nodemgr_remove_ud(struct unit_directory *ud)
 {
 	struct device *dev = &ud->device;
@@ -444,10 +684,10 @@ static void nodemgr_remove_ud(struct uni
 	device_remove_file(dev, &dev_attr_ud_specifier_id);
 	device_remove_file(dev, &dev_attr_ud_version);
 	device_remove_file(dev, &dev_attr_ud_vendor_id);
-	device_remove_file(dev, &dev_attr_ud_vendor_name);
+	device_remove_file(dev, &dev_attr_ud_vendor_name_kv);
 	device_remove_file(dev, &dev_attr_ud_vendor_oui);
 	device_remove_file(dev, &dev_attr_ud_model_id);
-	device_remove_file(dev, &dev_attr_ud_model_name);
+	device_remove_file(dev, &dev_attr_ud_model_name_kv);
 
 	device_unregister(dev);
 }
@@ -470,15 +710,20 @@ static void nodemgr_remove_ne(struct nod
 	struct device *dev = &ne->device;
 	int i;
 
+	HPSB_DEBUG("Node removed: ID:BUS[" NODE_BUS_FMT "]  GUID[%016Lx]",
+		   NODE_BUS_ARGS(ne->host, ne->nodeid), (unsigned long long)ne->guid);
+
 	nodemgr_remove_node_uds(ne);
 
 	for (i = 0; i < ARRAY_SIZE(fw_ne_attrs); i++)
 		device_remove_file(dev, fw_ne_attrs[i]);
 
 	device_remove_file(dev, &dev_attr_ne_guid_vendor_oui);
-	device_remove_file(dev, &dev_attr_ne_vendor_name);
+	device_remove_file(dev, &dev_attr_ne_vendor_name_kv);
 	device_remove_file(dev, &dev_attr_ne_vendor_oui);
+	device_remove_file(dev, &dev_attr_ne_in_limbo);
 
+	class_device_unregister(&ne->class_dev);
 	device_unregister(dev);
 }
 
@@ -503,188 +748,13 @@ static void nodemgr_remove_host_dev(stru
 }
 
 
-static struct device nodemgr_dev_template_ud = {
-	.bus		= &ieee1394_bus_type,
-	.release	= nodemgr_release_ud,
-};
-
-
-static struct device nodemgr_dev_template_ne = {
-	.bus		= &ieee1394_bus_type,
-	.release	= nodemgr_release_ne,
-	.driver		= &nodemgr_driver_ne,
-	.driver_data	= &nodemgr_driverdata_ne,
-};
-
-struct device nodemgr_dev_template_host = {
-	.bus		= &ieee1394_bus_type,
-	.release	= nodemgr_release_host,
-	.driver		= &nodemgr_driver_host,
-	.driver_data	= &nodemgr_driverdata_host,
-};
-
-
-static int nodemgr_hotplug(struct device *dev, char **envp, int num_envp,
-                           char *buffer, int buffer_size);
-
-
-struct bus_type ieee1394_bus_type = {
-	.name		= "ieee1394",
-	.match		= nodemgr_bus_match,
-	.hotplug	= nodemgr_hotplug,
-};
-
-
-static int nodemgr_read_quadlet(struct hpsb_host *host,
-				nodeid_t nodeid, unsigned int generation,
-				octlet_t address, quadlet_t *quad)
+static void nodemgr_update_bus_options(struct node_entry *ne)
 {
-	int i;
-	int ret = 0;
-
-	for (i = 0; i < 3; i++) {
-		ret = hpsb_read(host, nodeid, generation, address, quad, 4);
-		if (!ret)
-			break;
-
-		set_current_state(TASK_INTERRUPTIBLE);
-		if (schedule_timeout (HZ/3))
-			return -1;
-	}
-	*quad = be32_to_cpu(*quad);
-
-	return ret;
-}
-
-static int nodemgr_size_text_leaf(struct hpsb_host *host,
-				  nodeid_t nodeid, unsigned int generation,
-				  octlet_t address)
-{
-	quadlet_t quad;
-	int size = 0;
-
-	if (nodemgr_read_quadlet(host, nodeid, generation, address, &quad))
-		return -1;
-
-	if (CONFIG_ROM_KEY(quad) == CONFIG_ROM_DESCRIPTOR_LEAF) {
-		/* This is the offset.  */
-		address += 4 * CONFIG_ROM_VALUE(quad); 
-		if (nodemgr_read_quadlet(host, nodeid, generation, address, &quad))
-			return -1;
-		/* Now we got the size of the text descriptor leaf. */
-		size = CONFIG_ROM_LEAF_LENGTH(quad);
-	}
-
-	return size;
-}
-
-static int nodemgr_read_text_leaf(struct node_entry *ne,
-				  octlet_t address,
-				  quadlet_t *quadp)
-{
-	quadlet_t quad;
-	int i, size, ret;
-
-	if (nodemgr_read_quadlet(ne->host, ne->nodeid, ne->generation, address, &quad)
-	    || CONFIG_ROM_KEY(quad) != CONFIG_ROM_DESCRIPTOR_LEAF)
-		return -1;
-
-	/* This is the offset.  */
-	address += 4 * CONFIG_ROM_VALUE(quad);
-	if (nodemgr_read_quadlet(ne->host, ne->nodeid, ne->generation, address, &quad))
-		return -1;
-
-	/* Now we got the size of the text descriptor leaf. */
-	size = CONFIG_ROM_LEAF_LENGTH(quad) - 2;
-	if (size <= 0)
-		return -1;
-
-	address += 4;
-	for (i = 0; i < 2; i++, address += 4, quadp++) {
-		if (nodemgr_read_quadlet(ne->host, ne->nodeid, ne->generation, address, quadp))
-			return -1;
-	}
-
-	/* Now read the text string.  */
-	ret = -ENXIO;
-	for (; size > 0; size--, address += 4, quadp++) {
-		for (i = 0; i < 3; i++) {
-			ret = hpsb_node_read(ne, address, quadp, 4);
-			if (ret != -EAGAIN)
-				break;
-		}
-		if (ret)
-			break;
-	}
-
-	return ret;
-}
-
-static struct node_entry *nodemgr_scan_root_directory
-	(struct hpsb_host *host, nodeid_t nodeid, unsigned int generation)
-{
-	octlet_t address;
-	quadlet_t quad;
-	int length;
-	int code, size, total_size;
-	struct node_entry *ne;
-
-	address = CSR_REGISTER_BASE + CSR_CONFIG_ROM;
-	
-	if (nodemgr_read_quadlet(host, nodeid, generation, address, &quad))
-		return NULL;
-
-	if (CONFIG_ROM_BUS_INFO_LENGTH(quad) == 1)  /* minimal config rom */
-		return NULL;
-
-	address += 4 + CONFIG_ROM_BUS_INFO_LENGTH(quad) * 4;
-
-	if (nodemgr_read_quadlet(host, nodeid, generation, address, &quad))
-		return NULL;
-	length = CONFIG_ROM_ROOT_LENGTH(quad);
-	address += 4;
-
-	size = 0;
-	total_size = sizeof(struct node_entry);
-	for (; length > 0; length--, address += 4) {
-		if (nodemgr_read_quadlet(host, nodeid, generation, address, &quad))
-			return NULL;
-		code = CONFIG_ROM_KEY(quad);
-
-		if (code == CONFIG_ROM_VENDOR_ID && length > 0) {
-			/* Check if there is a text descriptor leaf
-			   immediately after this.  */
-			size = nodemgr_size_text_leaf(host, nodeid, generation,
-						      address + 4);
-			if (size > 0) {
-				address += 4;
-				length--;
-				total_size += (size + 1) * sizeof (quadlet_t);
-			} else if (size < 0)
-				return NULL;
-		}
-	}
-	ne = kmalloc(total_size, GFP_KERNEL);
-
-	if (!ne)
-		return NULL;
-
-	memset(ne, 0, total_size);
-
-	if (size != 0) {
-		ne->vendor_name = (const char *) &(ne->quadlets[2]);
-		ne->quadlets[size] = 0;
-	} else {
-		ne->vendor_name = NULL;
-	}
-
-	return ne; 
-}
-
+#ifdef CONFIG_IEEE1394_VERBOSEDEBUG
+	static const u16 mr[] = { 4, 64, 1024, 0};
+#endif
+	quadlet_t busoptions = be32_to_cpu(ne->csr->bus_info_data[2]);
 
-static void nodemgr_update_bus_options(struct node_entry *ne,
-                                       quadlet_t busoptions)
-{
 	ne->busopt.irmc         = (busoptions >> 31) & 1;
 	ne->busopt.cmc          = (busoptions >> 30) & 1;
 	ne->busopt.isc          = (busoptions >> 29) & 1;
@@ -692,28 +762,32 @@ static void nodemgr_update_bus_options(s
 	ne->busopt.pmc          = (busoptions >> 27) & 1;
 	ne->busopt.cyc_clk_acc  = (busoptions >> 16) & 0xff;
 	ne->busopt.max_rec      = 1 << (((busoptions >> 12) & 0xf) + 1);
+	ne->busopt.max_rom	= (busoptions >> 8) & 0x3;
 	ne->busopt.generation   = (busoptions >> 4) & 0xf;
 	ne->busopt.lnkspd       = busoptions & 0x7;
 	
 	HPSB_VERBOSE("NodeMgr: raw=0x%08x irmc=%d cmc=%d isc=%d bmc=%d pmc=%d "
-		     "cyc_clk_acc=%d max_rec=%d gen=%d lspd=%d",
+		     "cyc_clk_acc=%d max_rec=%d max_rom=%d gen=%d lspd=%d",
 		     busoptions, ne->busopt.irmc, ne->busopt.cmc,
 		     ne->busopt.isc, ne->busopt.bmc, ne->busopt.pmc,
 		     ne->busopt.cyc_clk_acc, ne->busopt.max_rec,
+		     mr[ne->busopt.max_rom],
 		     ne->busopt.generation, ne->busopt.lnkspd);
 }
 
 
-static struct node_entry *nodemgr_create_node(octlet_t guid, quadlet_t busoptions,
+static struct node_entry *nodemgr_create_node(octlet_t guid, struct csr1212_csr *csr,
 					      struct host_info *hi, nodeid_t nodeid,
 					      unsigned int generation)
 {
 	struct hpsb_host *host = hi->host;
         struct node_entry *ne;
 
-	ne = nodemgr_scan_root_directory (host, nodeid, generation);
+	ne = kmalloc(sizeof(struct node_entry), GFP_KERNEL);
         if (!ne) return NULL;
 
+	memset(ne, 0, sizeof(struct node_entry));
+
 	ne->tpool = &host->tpool[nodeid & NODE_MASK];
 
         ne->host = host;
@@ -724,6 +798,7 @@ static struct node_entry *nodemgr_create
         ne->guid = guid;
 	ne->guid_vendor_id = (guid >> 40) & 0xffffff;
 	ne->guid_vendor_oui = nodemgr_find_oui_name(ne->guid_vendor_id);
+	ne->csr = csr;
 
 	memcpy(&ne->device, &nodemgr_dev_template_ne,
 	       sizeof(ne->device));
@@ -731,13 +806,20 @@ static struct node_entry *nodemgr_create
 	snprintf(ne->device.bus_id, BUS_ID_SIZE, "%016Lx",
 		 (unsigned long long)(ne->guid));
 
+	ne->class_dev.dev = &ne->device;
+	ne->class_dev.class = &nodemgr_ne_class;
+	snprintf(ne->class_dev.class_id, BUS_ID_SIZE, "%016Lx",
+		 (unsigned long long)(ne->guid));
+
 	device_register(&ne->device);
+	class_device_register(&ne->class_dev);
+	get_device(&ne->device);
 
 	if (ne->guid_vendor_oui)
 		device_create_file(&ne->device, &dev_attr_ne_guid_vendor_oui);
 	nodemgr_create_ne_dev_files(ne);
 
-	nodemgr_update_bus_options(ne, busoptions);
+	nodemgr_update_bus_options(ne);
 
 	HPSB_DEBUG("%s added: ID:BUS[" NODE_BUS_FMT "]  GUID[%016Lx]",
 		   (host->node_id == nodeid) ? "Host" : "Node",
@@ -747,319 +829,168 @@ static struct node_entry *nodemgr_create
 }
 
 
-struct guid_search_baton {
-	u64 guid;
-	struct node_entry *ne;
-};
-
-static int nodemgr_guid_search_cb(struct device *dev, void *__data)
-{
-        struct guid_search_baton *search = __data;
-        struct node_entry *ne;
-
-        if (dev->driver_data != &nodemgr_driverdata_ne)
-                return 0;
-
-        ne = container_of(dev, struct node_entry, device);
-
-        if (ne->guid == search->guid) {
-		search->ne = ne;
-		return 1;
-	}
-
-	return 0;
-}
-
 static struct node_entry *find_entry_by_guid(u64 guid)
 {
-	struct guid_search_baton search;
-
-	search.guid = guid;
-	search.ne = NULL;
-
-	bus_for_each_dev(&ieee1394_bus_type, NULL, &search, nodemgr_guid_search_cb);
-
-        return search.ne;
-}
-
-
-struct nodeid_search_baton {
-	nodeid_t nodeid;
-	struct node_entry *ne;
-	struct hpsb_host *host;
-};
-
-static int nodemgr_nodeid_search_cb(struct device *dev, void *__data)
-{
-	struct nodeid_search_baton *search = __data;
-	struct node_entry *ne;
-
-	if (dev->driver_data != &nodemgr_driverdata_ne)
-		return 0;
-
-	ne = container_of(dev, struct node_entry, device);
+	struct class *class = &nodemgr_ne_class;
+	struct class_device *cdev;
+	struct node_entry *ne, *ret_ne = NULL;
+
+	down_read(&class->subsys.rwsem);
+	list_for_each_entry(cdev, &class->children, node) {
+		ne = container_of(cdev, struct node_entry, class_dev);
 
-	if (ne->host == search->host && ne->nodeid == search->nodeid) {
-		search->ne = ne;
-		/* Returning 1 stops the iteration */
-		return 1;
+		if (ne->guid == guid) {
+			ret_ne = ne;
+			break;
+		}
 	}
+	up_read(&class->subsys.rwsem);
 
-	return 0;
+        return ret_ne;
 }
 
-static struct node_entry *find_entry_by_nodeid(struct hpsb_host *host, nodeid_t nodeid)
-{
-	struct nodeid_search_baton search;
-
-	search.nodeid = nodeid;
-	search.ne = NULL;
-	search.host = host;
-
-	bus_for_each_dev(&ieee1394_bus_type, NULL, &search, nodemgr_nodeid_search_cb);
-
-	return search.ne;
-}
 
-static struct unit_directory *nodemgr_scan_unit_directory
-	(struct node_entry *ne, octlet_t address)
+static struct node_entry *find_entry_by_nodeid(struct hpsb_host *host, nodeid_t nodeid)
 {
-	struct unit_directory *ud;
-	quadlet_t quad;
-	u8 flags, todo;
-	int length, size, total_size, count;
-	int vendor_name_size, model_name_size;
-
-	if (nodemgr_read_quadlet(ne->host, ne->nodeid, ne->generation, address, &quad))
-		return NULL;
-
-	length = CONFIG_ROM_DIRECTORY_LENGTH(quad) ;
-	address += 4;
-
-	size = 0;
-	total_size = sizeof (struct unit_directory);
-	flags = 0;
-	count = 0;
-	vendor_name_size = 0;
-	model_name_size = 0;
-	for (; length > 0; length--, address += 4) {
-		int code;
-		quadlet_t value;
-
-		if (nodemgr_read_quadlet(ne->host, ne->nodeid, ne->generation,
-					 address, &quad))
-			return NULL;
-		code = CONFIG_ROM_KEY(quad);
-		value = CONFIG_ROM_VALUE(quad);
-
-		todo = 0;
-		switch (code) {
-		case CONFIG_ROM_VENDOR_ID:
-			todo = UNIT_DIRECTORY_VENDOR_TEXT;
-			break;
-
-		case CONFIG_ROM_MODEL_ID:
-			todo = UNIT_DIRECTORY_MODEL_TEXT;
-			break;
-
-		case CONFIG_ROM_SPECIFIER_ID:
-		case CONFIG_ROM_UNIT_SW_VERSION:
-			break;
-
-		case CONFIG_ROM_DESCRIPTOR_LEAF:
-		case CONFIG_ROM_DESCRIPTOR_DIRECTORY:
-			/* TODO: read strings... icons? */
-			break;
+	struct class *class = &nodemgr_ne_class;
+	struct class_device *cdev;
+	struct node_entry *ne, *ret_ne = NULL;
+
+	down_read(&class->subsys.rwsem);
+	list_for_each_entry(cdev, &class->children, node) {
+		ne = container_of(cdev, struct node_entry, class_dev);
 
-		default:
-			/* Which types of quadlets do we want to
-			   store?  Only count immediate values and
-			   CSR offsets for now.  */
-			code &= CONFIG_ROM_KEY_TYPE_MASK;
-			if ((code & CONFIG_ROM_KEY_TYPE_LEAF) == 0)
-				count++;
+		if (ne->host == host && ne->nodeid == nodeid) {
+			ret_ne = ne;
 			break;
 		}
-
-		if (todo && length > 0) {
-			/* Check if there is a text descriptor leaf
-			   immediately after this.  */
-			size = nodemgr_size_text_leaf(ne->host,
-						      ne->nodeid,
-						      ne->generation,
-						      address + 4);
-
-			if (todo == UNIT_DIRECTORY_VENDOR_TEXT)
-				vendor_name_size = size;
-			else
-				model_name_size = size;
-
-			if (size > 0) {
-				address += 4;
-				length--;
-				flags |= todo;
-				total_size += (size + 1) * sizeof (quadlet_t);
-			}
-			else if (size < 0)
-				return NULL;
-		}
 	}
+	up_read(&class->subsys.rwsem);
 
-	total_size += count * sizeof (quadlet_t);
-	ud = kmalloc (total_size, GFP_KERNEL);
-
-	if (ud != NULL) {
-		memset (ud, 0, total_size);
-		ud->flags = flags;
-		ud->length = count;
-		ud->vendor_name_size = vendor_name_size;
-		ud->model_name_size = model_name_size;
-	}
-
-	return ud;
+	return ret_ne;
 }
 
 
+
 /* This implementation currently only scans the config rom and its
  * immediate unit directories looking for software_id and
  * software_version entries, in order to get driver autoloading working. */
 static struct unit_directory *nodemgr_process_unit_directory
-	(struct host_info *hi, struct node_entry *ne, octlet_t address, unsigned int *id,
-	 struct unit_directory *parent)
+	(struct host_info *hi, struct node_entry *ne, struct csr1212_keyval *ud_kv,
+	 unsigned int *id, struct unit_directory *parent)
 {
 	struct unit_directory *ud;
-	quadlet_t quad;
-	quadlet_t *infop;
-	int length;
 	struct unit_directory *ud_temp = NULL;
+	struct csr1212_dentry *dentry;
+	struct csr1212_keyval *kv;
+	u8 last_key_id = 0;
 
-	if (!(ud = nodemgr_scan_unit_directory(ne, address)))
+	ud = kmalloc(sizeof(struct unit_directory), GFP_KERNEL);
+	if (!ud)
 		goto unit_directory_error;
 
+	memset (ud, 0, sizeof(struct unit_directory));
+
 	ud->ne = ne;
-	ud->address = address;
+	ud->ignore_driver = ignore_drivers;
+	ud->address = ud_kv->offset + CSR1212_CONFIG_ROM_SPACE_BASE;
+	ud->ud_kv = ud_kv;
 	ud->id = (*id)++;
 
-	if (nodemgr_read_quadlet(ne->host, ne->nodeid, ne->generation,
-				 address, &quad))
-		goto unit_directory_error;
-	length = CONFIG_ROM_DIRECTORY_LENGTH(quad) ;
-	address += 4;
+	csr1212_for_each_dir_entry(ne->csr, kv, ud_kv, dentry) {
+		switch (kv->key.id) {
+		case CSR1212_KV_ID_VENDOR:
+			if (kv->key.type == CSR1212_KV_TYPE_IMMEDIATE) {
+				ud->vendor_id = kv->value.immediate;
+				ud->flags |= UNIT_DIRECTORY_VENDOR_ID;
 
-	infop = (quadlet_t *) ud->quadlets;
-	for (; length > 0; length--, address += 4) {
-		int code;
-		quadlet_t value;
-		quadlet_t *quadp;
-
-		if (nodemgr_read_quadlet(ne->host, ne->nodeid, ne->generation,
-					 address, &quad))
-			goto unit_directory_error;
-		code = CONFIG_ROM_KEY(quad) ;
-		value = CONFIG_ROM_VALUE(quad);
-
-		switch (code) {
-		case CONFIG_ROM_VENDOR_ID:
-			ud->vendor_id = value;
-			ud->flags |= UNIT_DIRECTORY_VENDOR_ID;
-
-			if (ud->vendor_id)
-				ud->vendor_oui = nodemgr_find_oui_name(ud->vendor_id);
-
-			if ((ud->flags & UNIT_DIRECTORY_VENDOR_TEXT) != 0) {
-				length--;
-				address += 4;
-				quadp = &(ud->quadlets[ud->length]);
-				if (nodemgr_read_text_leaf(ne, address, quadp) == 0
-				    && quadp[0] == 0 && quadp[1] == 0) {
-				    	/* We only support minimal
-					   ASCII and English. */
-					quadp[ud->vendor_name_size] = 0;
-					ud->vendor_name
-						= (const char *) &(quadp[2]);
-				}
+				if (ud->vendor_id)
+					ud->vendor_oui = nodemgr_find_oui_name(ud->vendor_id);
 			}
 			break;
 
-		case CONFIG_ROM_MODEL_ID:
-			ud->model_id = value;
+		case CSR1212_KV_ID_MODEL:
+			ud->model_id = kv->value.immediate;
 			ud->flags |= UNIT_DIRECTORY_MODEL_ID;
-			if ((ud->flags & UNIT_DIRECTORY_MODEL_TEXT) != 0) {
-				length--;
-				address += 4;
-				quadp = &(ud->quadlets[ud->length + ud->vendor_name_size + 1]);
-				if (nodemgr_read_text_leaf(ne, address, quadp) == 0
-				    && quadp[0] == 0 && quadp[1] == 0) {
-				    	/* We only support minimal
-					   ASCII and English. */
-					quadp[ud->model_name_size] = 0;
-					ud->model_name
-						= (const char *) &(quadp[2]);
-				}
-			}
 			break;
 
-		case CONFIG_ROM_SPECIFIER_ID:
-			ud->specifier_id = value;
+		case CSR1212_KV_ID_SPECIFIER_ID:
+			ud->specifier_id = kv->value.immediate;
 			ud->flags |= UNIT_DIRECTORY_SPECIFIER_ID;
 			break;
 
-		case CONFIG_ROM_UNIT_SW_VERSION:
-			ud->version = value;
+		case CSR1212_KV_ID_VERSION:
+			ud->version = kv->value.immediate;
 			ud->flags |= UNIT_DIRECTORY_VERSION;
 			break;
 
-		case CONFIG_ROM_DESCRIPTOR_LEAF:
-		case CONFIG_ROM_DESCRIPTOR_DIRECTORY:
-			/* TODO: read strings... icons? */
+		case CSR1212_KV_ID_DESCRIPTOR:
+			if (kv->key.type == CSR1212_KV_TYPE_LEAF &&
+			    CSR1212_DESCRIPTOR_LEAF_TYPE(kv) == 0 &&
+			    CSR1212_DESCRIPTOR_LEAF_SPECIFIER_ID(kv) == 0 &&
+			    CSR1212_TEXTUAL_DESCRIPTOR_LEAF_WIDTH(kv) == 0 &&
+			    CSR1212_TEXTUAL_DESCRIPTOR_LEAF_CHAR_SET(kv) == 0 &&
+			    CSR1212_TEXTUAL_DESCRIPTOR_LEAF_LANGUAGE(kv) == 0) {
+				switch (last_key_id) {
+				case CSR1212_KV_ID_VENDOR:
+					ud->vendor_name_kv = kv;
+					csr1212_keep_keyval(kv);
+					break;
+
+				case CSR1212_KV_ID_MODEL:
+					ud->model_name_kv = kv;
+					csr1212_keep_keyval(kv);
+					break;
+
+				}
+			} /* else if (kv->key.type == CSR1212_KV_TYPE_DIRECTORY) ... */
 			break;
 
-		case CONFIG_ROM_LOGICAL_UNIT_DIRECTORY:
-			ud->flags |= UNIT_DIRECTORY_HAS_LUN_DIRECTORY;
-			ud_temp = nodemgr_process_unit_directory(hi, ne, address + value * 4, id,
-								 parent);
-
-			if (ud_temp == NULL)
-				break;
-
-			/* inherit unspecified values */
-			if ((ud->flags & UNIT_DIRECTORY_VENDOR_ID) &&
-				!(ud_temp->flags & UNIT_DIRECTORY_VENDOR_ID))
-			{
-				ud_temp->flags |=  UNIT_DIRECTORY_VENDOR_ID;
-				ud_temp->vendor_id = ud->vendor_id;
-				ud_temp->vendor_oui = ud->vendor_oui;
-			}
-			if ((ud->flags & UNIT_DIRECTORY_MODEL_ID) &&
-				!(ud_temp->flags & UNIT_DIRECTORY_MODEL_ID))
-			{
-				ud_temp->flags |=  UNIT_DIRECTORY_MODEL_ID;
-				ud_temp->model_id = ud->model_id;
-			}
-			if ((ud->flags & UNIT_DIRECTORY_SPECIFIER_ID) &&
-				!(ud_temp->flags & UNIT_DIRECTORY_SPECIFIER_ID))
-			{
-				ud_temp->flags |=  UNIT_DIRECTORY_SPECIFIER_ID;
-				ud_temp->specifier_id = ud->specifier_id;
-			}
-			if ((ud->flags & UNIT_DIRECTORY_VERSION) &&
-				!(ud_temp->flags & UNIT_DIRECTORY_VERSION))
-			{
-				ud_temp->flags |=  UNIT_DIRECTORY_VERSION;
-				ud_temp->version = ud->version;
+		case CSR1212_KV_ID_DEPENDENT_INFO:
+			if (kv->key.type == CSR1212_KV_TYPE_DIRECTORY) {
+				/* This should really be done in SBP2 as this is
+				 * doing SBP2 specific parsing. */
+				ud->flags |= UNIT_DIRECTORY_HAS_LUN_DIRECTORY;
+				ud_temp = nodemgr_process_unit_directory(hi, ne, kv, id,
+									 parent);
+
+				if (ud_temp == NULL)
+					break;
+
+				/* inherit unspecified values */
+				if ((ud->flags & UNIT_DIRECTORY_VENDOR_ID) &&
+				    !(ud_temp->flags & UNIT_DIRECTORY_VENDOR_ID))
+				{
+					ud_temp->flags |=  UNIT_DIRECTORY_VENDOR_ID;
+					ud_temp->vendor_id = ud->vendor_id;
+					ud_temp->vendor_oui = ud->vendor_oui;
+				}
+				if ((ud->flags & UNIT_DIRECTORY_MODEL_ID) &&
+				    !(ud_temp->flags & UNIT_DIRECTORY_MODEL_ID))
+				{
+					ud_temp->flags |=  UNIT_DIRECTORY_MODEL_ID;
+					ud_temp->model_id = ud->model_id;
+				}
+				if ((ud->flags & UNIT_DIRECTORY_SPECIFIER_ID) &&
+				    !(ud_temp->flags & UNIT_DIRECTORY_SPECIFIER_ID))
+				{
+					ud_temp->flags |=  UNIT_DIRECTORY_SPECIFIER_ID;
+					ud_temp->specifier_id = ud->specifier_id;
+				}
+				if ((ud->flags & UNIT_DIRECTORY_VERSION) &&
+				    !(ud_temp->flags & UNIT_DIRECTORY_VERSION))
+				{
+					ud_temp->flags |=  UNIT_DIRECTORY_VERSION;
+					ud_temp->version = ud->version;
+				}
 			}
 
 			break;
 
 		default:
-			/* Which types of quadlets do we want to
-			   store?  Only count immediate values and
-			   CSR offsets for now.  */
-			code &= CONFIG_ROM_KEY_TYPE_MASK;
-			if ((code & CONFIG_ROM_KEY_TYPE_LEAF) == 0)
-				*infop++ = quad;
 			break;
 		}
+		last_key_id = kv->key.id;
 	}
 
 	memcpy(&ud->device, &nodemgr_dev_template_ud,
@@ -1091,76 +1022,51 @@ unit_directory_error:
 
 static void nodemgr_process_root_directory(struct host_info *hi, struct node_entry *ne)
 {
-	octlet_t address;
-	quadlet_t quad;
-	int length;
 	unsigned int ud_id = 0;
-
-	device_remove_file(&ne->device, &dev_attr_ne_vendor_oui);
-
-	address = CSR_REGISTER_BASE + CSR_CONFIG_ROM;
-	
-	if (nodemgr_read_quadlet(ne->host, ne->nodeid, ne->generation,
-				 address, &quad))
-		return;
-	address += 4 + CONFIG_ROM_BUS_INFO_LENGTH(quad) * 4;
-
-	if (nodemgr_read_quadlet(ne->host, ne->nodeid, ne->generation,
-				 address, &quad))
-		return;
-	length = CONFIG_ROM_ROOT_LENGTH(quad);
-	address += 4;
-
-	for (; length > 0; length--, address += 4) {
-		int code, value;
-
-		if (nodemgr_read_quadlet(ne->host, ne->nodeid, ne->generation,
-					 address, &quad))
-			return;
-		code = CONFIG_ROM_KEY(quad);
-		value = CONFIG_ROM_VALUE(quad);
-
-		switch (code) {
-		case CONFIG_ROM_VENDOR_ID:
-			ne->vendor_id = value;
+	struct csr1212_dentry *dentry;
+	struct csr1212_keyval *kv;
+	u8 last_key_id = 0;
+
+	ne->needs_probe = 0;
+
+	csr1212_for_each_dir_entry(ne->csr, kv, ne->csr->root_kv, dentry) {
+		switch (kv->key.id) {
+		case CSR1212_KV_ID_VENDOR:
+			ne->vendor_id = kv->value.immediate;
 
 			if (ne->vendor_id)
 				ne->vendor_oui = nodemgr_find_oui_name(ne->vendor_id);
-
-			/* Now check if there is a vendor name text
-			   string.  */
-			if (ne->vendor_name != NULL) {
-				length--;
-				address += 4;
-				if (nodemgr_read_text_leaf(ne, address, ne->quadlets) != 0
-				    || ne->quadlets[0] != 0 || ne->quadlets[1] != 0)
-				    	/* We only support minimal
-					   ASCII and English. */
-					ne->vendor_name = NULL;
-				else
-					device_create_file(&ne->device,
-						&dev_attr_ne_vendor_name);
-			}
 			break;
 
-		case CONFIG_ROM_NODE_CAPABILITES:
-			ne->capabilities = value;
+		case CSR1212_KV_ID_NODE_CAPABILITIES:
+			ne->capabilities = kv->value.immediate;
 			break;
 
-		case CONFIG_ROM_UNIT_DIRECTORY:
-			nodemgr_process_unit_directory(hi, ne, address + value * 4, &ud_id,
-						       NULL);
+		case CSR1212_KV_ID_UNIT:
+			nodemgr_process_unit_directory(hi, ne, kv, &ud_id, NULL);
 			break;			
 
-		case CONFIG_ROM_DESCRIPTOR_LEAF:
-		case CONFIG_ROM_DESCRIPTOR_DIRECTORY:
-			/* TODO: read strings... icons? */
+		case CSR1212_KV_ID_DESCRIPTOR:
+			if (last_key_id == CSR1212_KV_ID_VENDOR) {
+				if (kv->key.type == CSR1212_KV_TYPE_LEAF &&
+				    CSR1212_DESCRIPTOR_LEAF_TYPE(kv) == 0 &&
+				    CSR1212_DESCRIPTOR_LEAF_SPECIFIER_ID(kv) == 0 &&
+				    CSR1212_TEXTUAL_DESCRIPTOR_LEAF_WIDTH(kv) == 0 &&
+				    CSR1212_TEXTUAL_DESCRIPTOR_LEAF_CHAR_SET(kv) == 0 &&
+				    CSR1212_TEXTUAL_DESCRIPTOR_LEAF_LANGUAGE(kv) == 0) {
+					ne->vendor_name_kv = kv;
+					csr1212_keep_keyval(kv);
+				}
+			}
 			break;
 		}
+		last_key_id = kv->key.id;
 	}
 
 	if (ne->vendor_oui)
 		device_create_file(&ne->device, &dev_attr_ne_vendor_oui);
+	if (ne->vendor_name_kv)
+		device_create_file(&ne->device, &dev_attr_ne_vendor_name_kv);
 }
 
 #ifdef CONFIG_HOTPLUG
@@ -1176,13 +1082,14 @@ static int nodemgr_hotplug(struct device
 	if (!dev)
 		return -ENODEV;
 
-	/* Have to check driver_data, since on remove, driver == NULL */
-	if (dev->driver_data == &nodemgr_driverdata_ne ||
-	    dev->driver_data == &nodemgr_driverdata_host)
+	if (dev->platform_data != &nodemgr_platform_data_ud)
 		return -ENODEV;
 
 	ud = container_of(dev, struct unit_directory, device);
 
+	if (ud->ne->in_limbo || ud->ignore_driver)
+		return -ENODEV;
+
 	scratch = buffer;
 
 #define PUT_ENVP(fmt,val) 					\
@@ -1261,7 +1168,7 @@ void hpsb_unregister_protocol(struct hps
  * informed that this device just went through a bus reset, to allow
  * the to take whatever actions required.
  */
-static void nodemgr_update_node(struct node_entry *ne, quadlet_t busoptions,
+static void nodemgr_update_node(struct node_entry *ne, struct csr1212_csr *csr,
 				struct host_info *hi, nodeid_t nodeid,
 				unsigned int generation)
 {
@@ -1272,87 +1179,29 @@ static void nodemgr_update_node(struct n
 		ne->nodeid = nodeid;
 	}
 
-	if (ne->busopt.generation != ((busoptions >> 4) & 0xf)) {
+	if (ne->busopt.generation != ((be32_to_cpu(csr->bus_info_data[2]) >> 4) & 0xf)) {
+		kfree(ne->csr->private);
+		csr1212_destroy_csr(ne->csr);
+		ne->csr = csr;
+
 		/* If the node's configrom generation has changed, we
 		 * unregister all the unit directories. */
 		nodemgr_remove_node_uds(ne);
 
-		nodemgr_update_bus_options(ne, busoptions);
+		nodemgr_update_bus_options(ne);
 
 		/* Mark the node as new, so it gets re-probed */
 		ne->needs_probe = 1;
 	}
 
+	if (ne->in_limbo)
+		nodemgr_resume_ne(ne);
+
 	/* Mark the node current */
 	ne->generation = generation;
 }
 
-static int read_businfo_block(struct hpsb_host *host, nodeid_t nodeid, unsigned int generation,
-			      quadlet_t *buffer, int buffer_length)
-{
-	octlet_t addr = CSR_REGISTER_BASE + CSR_CONFIG_ROM;
-	unsigned header_size;
-	int i;
-
-	/* IEEE P1212 says that devices should support 64byte block
-	 * reads, aligned on 64byte boundaries. That doesn't seem to
-	 * work though, and we are forced to doing quadlet sized
-	 * reads.  */
-
-	HPSB_VERBOSE("Initiating ConfigROM request for node " NODE_BUS_FMT,
-		     NODE_BUS_ARGS(host, nodeid));
-
-	/* 
-	 * Must retry a few times if config rom read returns zero (how long?). Will
-	 * not normally occur, but we should do the right thing. For example, with
-	 * some sbp2 devices, the bridge chipset cannot return valid config rom reads
-	 * immediately after power-on, since they need to detect the type of 
-	 * device attached (disk or CD-ROM).
-	 */
-	for (i = 0; i < 4; i++) {
-		if (nodemgr_read_quadlet(host, nodeid, generation,
-					 addr, &buffer[0]) < 0) {
-			HPSB_ERR("ConfigROM quadlet transaction error for node "
-				 NODE_BUS_FMT, NODE_BUS_ARGS(host, nodeid));
-			return -1;
-		}
-		if (buffer[0])
-			break;
-
-		set_current_state(TASK_INTERRUPTIBLE);
-		if (schedule_timeout (HZ/4))
-			return -1;
-	}
-
-	header_size = buffer[0] >> 24;
-	addr += 4;
-
-	if (header_size == 1) {
-		HPSB_INFO("Node " NODE_BUS_FMT " has a minimal ROM.  "
-			  "Vendor is %08x",
-			  NODE_BUS_ARGS(host, nodeid), buffer[0] & 0x00ffffff);
-		return -1;
-	}
-
-	if (header_size < 4) {
-		HPSB_INFO("Node " NODE_BUS_FMT " has non-standard ROM "
-			  "format (%d quads), cannot parse",
-			  NODE_BUS_ARGS(host, nodeid), header_size);
-		return -1;
-	}
-
-	for (i = 1; i < buffer_length; i++, addr += 4) {
-		if (nodemgr_read_quadlet(host, nodeid, generation,
-					 addr, &buffer[i]) < 0) {
-			HPSB_ERR("ConfigROM quadlet transaction "
-				 "error for node " NODE_BUS_FMT,
-				 NODE_BUS_ARGS(host, nodeid));
-			return -1;
-		}
-	}
-
-	return 0;
-}		
+		
 
 
 static void nodemgr_node_scan_one(struct host_info *hi,
@@ -1360,17 +1209,32 @@ static void nodemgr_node_scan_one(struct
 {
 	struct hpsb_host *host = hi->host;
 	struct node_entry *ne;
-	quadlet_t buffer[5];
 	octlet_t guid;
+	struct csr1212_csr *csr;
+	struct nodemgr_csr_info *ci;
+
+	ci = kmalloc(sizeof(struct nodemgr_csr_info), GFP_KERNEL);
+	if (!ci)
+		return;
+
+	ci->host = host;
+	ci->nodeid = nodeid;
+	ci->generation = generation;
 
 	/* We need to detect when the ConfigROM's generation has changed,
 	 * so we only update the node's info when it needs to be.  */
 
-	if (read_businfo_block (host, nodeid, generation,
-				buffer, sizeof(buffer) >> 2))
+	csr = csr1212_create_csr(&nodemgr_csr_ops, 5 * sizeof(quadlet_t), ci);
+	if (!csr || csr1212_parse_csr(csr) != CSR1212_SUCCESS) {
+		HPSB_ERR("Error parsing configrom for node " NODE_BUS_FMT,
+			 NODE_BUS_ARGS(host, nodeid));
+		if (csr)
+			csr1212_destroy_csr(csr);
+		kfree(ci);
 		return;
+	}
 
-	if (buffer[1] != IEEE1394_BUSID_MAGIC) {
+	if (csr->bus_info_data[1] != IEEE1394_BUSID_MAGIC) {
 		/* This isn't a 1394 device, but we let it slide. There
 		 * was a report of a device with broken firmware which
 		 * reported '2394' instead of '1394', which is obviously a
@@ -1379,176 +1243,199 @@ static void nodemgr_node_scan_one(struct
 		 * shouldn't be held responsible, so we'll allow it with a
 		 * warning.  */
 		HPSB_WARN("Node " NODE_BUS_FMT " has invalid busID magic [0x%08x]",
-			  NODE_BUS_ARGS(host, nodeid), buffer[1]);
+			  NODE_BUS_ARGS(host, nodeid), csr->bus_info_data[1]);
 	}
 
-	guid = ((u64)buffer[3] << 32) | buffer[4];
+	guid = ((u64)be32_to_cpu(csr->bus_info_data[3]) << 32) | be32_to_cpu(csr->bus_info_data[4]);
 	ne = find_entry_by_guid(guid);
 
+	if (ne && ne->host != host && ne->in_limbo) {
+		/* Must have moved this device from one host to another */
+		nodemgr_remove_ne(ne);
+		ne = NULL;
+	}
+
 	if (!ne)
-		nodemgr_create_node(guid, buffer[2], hi, nodeid, generation);
+		nodemgr_create_node(guid, csr, hi, nodeid, generation);
 	else
-		nodemgr_update_node(ne, buffer[2], hi, nodeid, generation);
+		nodemgr_update_node(ne, csr, hi, nodeid, generation);
 
 	return;
 }
 
 
-struct cleanup_baton {
-	unsigned int generation;
-	struct hpsb_host *host;
-	struct node_entry *ne;
-};
+static void nodemgr_node_scan(struct host_info *hi, int generation)
+{
+        int count;
+        struct hpsb_host *host = hi->host;
+        struct selfid *sid = (struct selfid *)host->topology_map;
+        nodeid_t nodeid = LOCAL_BUS;
+
+        /* Scan each node on the bus */
+        for (count = host->selfid_count; count; count--, sid++) {
+                if (sid->extended)
+                        continue;
+
+                if (!sid->link_active) {
+                        nodeid++;
+                        continue;
+                }
+                nodemgr_node_scan_one(hi, nodeid++, generation);
+        }
+}
+
 
-static int nodemgr_remove_node(struct device *dev, void *__data)
+static void nodemgr_suspend_ud(struct unit_directory *ud)
 {
-	struct cleanup_baton *cleanup = __data;
-	struct node_entry *ne;
+	struct device *dev;
 
-	if (dev->driver_data != &nodemgr_driverdata_ne)
-		return 0;
+	list_for_each_entry(dev, &ud->device.children, node)
+		nodemgr_suspend_ud(container_of(dev, struct unit_directory, device));
 
-	ne = container_of(dev, struct node_entry, device);
+	if (ud->device.driver) {
+		int ret = -1;
 
-	if (ne->host != cleanup->host)
-		return 0;
+		if (ud->device.driver->suspend)
+			ret = ud->device.driver->suspend(&ud->device, 0, 0);
 
-	if (ne->generation != cleanup->generation) {
-		cleanup->ne = ne;
-		return 1;
-	}
+		if (ret) {
+			dev = &ud->device;
+			down_write(&dev->bus->subsys.rwsem);
+			device_release_driver(dev);
+			up_write(&dev->bus->subsys.rwsem);
+		}
+	}								
+}
 
-	return 0;
+
+static void nodemgr_suspend_ne(struct node_entry *ne)
+{
+	struct device *dev;
+
+	HPSB_DEBUG("Node suspended: ID:BUS[" NODE_BUS_FMT "]  GUID[%016Lx]",
+		   NODE_BUS_ARGS(ne->host, ne->nodeid), (unsigned long long)ne->guid);
+
+	ne->in_limbo = 1;
+	device_create_file(&ne->device, &dev_attr_ne_in_limbo);
+
+	list_for_each_entry(dev, &ne->device.children, node)
+		nodemgr_suspend_ud(container_of(dev, struct unit_directory, device));
 }
 
-struct ne_cb_data_struct {
-	struct host_info *hi;
-	struct node_entry *ne;
-};
 
-static int nodemgr_probe_ne_cb(struct device *dev, void *__data)
+static void nodemgr_resume_ud(struct unit_directory *ud)
 {
-	struct ne_cb_data_struct *ne_cb_data = __data;
-	struct host_info *hi = ne_cb_data->hi;
-	struct node_entry *ne;
+	struct device *dev;
 
-	if (dev->driver_data != &nodemgr_driverdata_ne)
-		return 0;
+	list_for_each_entry(dev, &ud->device.children, node)
+		nodemgr_resume_ud(container_of(dev, struct unit_directory, device));
 
-	ne = ne_cb_data->ne = container_of(dev, struct node_entry, device);
+	if (ud->device.driver && ud->device.driver->resume)
+		ud->device.driver->resume(&ud->device, 0);
+}
 
-	if (ne->host != hi->host)
-		return 0;
 
-	/* We can't call nodemgr_process_root_directory() here because
-	 * that can call device_register. Since this callback is under a
-	 * rwsem, the device_register would deadlock. So, we signal back
-	 * to the callback, and process things there. */
+static void nodemgr_resume_ne(struct node_entry *ne)
+{
+	struct device *dev;
 
-	if (ne->needs_probe) {
-		ne->needs_probe = 0;
-		return 1;
-	} else {
-		struct list_head *lh;
+	ne->in_limbo = 0;
+	device_remove_file(&ne->device, &dev_attr_ne_in_limbo);
 
-		/* Update unit_dirs with attached drivers */
-		list_for_each(lh, &dev->children) {
-			struct unit_directory *ud;
-			
-			ud = container_of(list_to_dev(lh), struct unit_directory, device);
+	list_for_each_entry(dev, &ne->device.children, node)
+		nodemgr_resume_ud(container_of(dev, struct unit_directory, device));
 
-			if (ud->device.driver) {
-				struct hpsb_protocol_driver *pdrv;
+	HPSB_DEBUG("Node resumed: ID:BUS[" NODE_BUS_FMT "]  GUID[%016Lx]",
+		   NODE_BUS_ARGS(ne->host, ne->nodeid), (unsigned long long)ne->guid);
+}
 
-				pdrv = container_of(ud->device.driver,
-						    struct hpsb_protocol_driver, driver);
 
-				if (pdrv->update)
-					pdrv->update(ud);
-			}
+static void nodemgr_ud_update_pdrv(struct unit_directory *ud)
+{
+	struct device *dev;
+	struct hpsb_protocol_driver *pdrv;
+
+	if (!get_device(&ud->device))
+		return;
+
+	list_for_each_entry(dev, &ud->device.children, node)
+		nodemgr_ud_update_pdrv(container_of(dev, struct unit_directory, device));
+
+	if (ud->device.driver) {
+		pdrv = container_of(ud->device.driver, struct hpsb_protocol_driver, driver);
+
+		if (pdrv->update && pdrv->update(ud)) {
+			down_write(&ud->device.bus->subsys.rwsem);
+			device_release_driver(&ud->device);
+			up_write(&ud->device.bus->subsys.rwsem);
 		}
 	}
-	return 0;
+
+	put_device(&ud->device);
 }
 
 
-static void nodemgr_node_scan(struct host_info *hi, int generation)
+static void nodemgr_probe_ne(struct host_info *hi, struct node_entry *ne, int generation)
 {
-        int count;
-        struct hpsb_host *host = hi->host;
-        struct selfid *sid = (struct selfid *)host->topology_map;
-        nodeid_t nodeid = LOCAL_BUS;
+	struct device *dev, *udev;
 
-        /* Scan each node on the bus */
-        for (count = host->selfid_count; count; count--, sid++) {
-                if (sid->extended)
-                        continue;
+	if (ne->host != hi->host || ne->in_limbo)
+		return;
 
-                if (!sid->link_active) {
-                        nodeid++;
-                        continue;
-                }
-                nodemgr_node_scan_one(hi, nodeid++, generation);
-        }
+	dev = get_device(&ne->device);
+	if (!dev)
+		return;
+
+	/* If "needs_probe", then this is either a new or changed node we
+	 * rescan totally. If the generation matches for an existing node
+	 * (one that existed prior to the bus reset) we send update calls
+	 * down to the drivers. Otherwise, this is a dead node and we
+	 * suspend it. */
+	if (ne->needs_probe)
+		nodemgr_process_root_directory(hi, ne);
+	else if (ne->generation == generation)
+		list_for_each_entry(udev, &dev->children, node)
+			nodemgr_ud_update_pdrv(container_of(udev, struct unit_directory, device));
+	else
+		nodemgr_suspend_ne(ne);
+
+	put_device(dev);
 }
 
+
 static void nodemgr_node_probe(struct host_info *hi, int generation)
 {
 	struct hpsb_host *host = hi->host;
-	struct ne_cb_data_struct ne_cb_data;
-
-	ne_cb_data.hi = hi;
-	ne_cb_data.ne = NULL;
+	struct class *class = &nodemgr_ne_class;
+	struct class_device *cdev;
 
 	/* Do some processing of the nodes we've probed. This pulls them
 	 * into the sysfs layer if needed, and can result in processing of
 	 * unit-directories, or just updating the node and it's
 	 * unit-directories. */
-	while (bus_for_each_dev(&ieee1394_bus_type, ne_cb_data.ne ? &ne_cb_data.ne->device : NULL,
-	       &ne_cb_data, nodemgr_probe_ne_cb)) {
-		/* If we get in here, we've got a node that needs it's
-		 * unit directories processed. */
-		struct device *dev = get_device(&ne_cb_data.ne->device);
-
-		if (dev) {
-			nodemgr_process_root_directory(hi, ne_cb_data.ne);
-			put_device(dev);
-		}
-	}
+	down_read(&class->subsys.rwsem);
+	list_for_each_entry(cdev, &class->children, node)
+		nodemgr_probe_ne(hi, container_of(cdev, struct node_entry, class_dev), generation);
+        up_read(&class->subsys.rwsem);
+
 
 	/* If we had a bus reset while we were scanning the bus, it is
 	 * possible that we did not probe all nodes.  In that case, we
 	 * skip the clean up for now, since we could remove nodes that
 	 * were still on the bus.  The bus reset increased hi->reset_sem,
 	 * so there's a bus scan pending which will do the clean up
-	 * eventually. */
-	if (generation == get_hpsb_generation(host)) {
-		struct cleanup_baton cleanup;
-
-		cleanup.generation = generation;
-		cleanup.host = host;
-
-		/* This will iterate until all devices that do not match
-		 * the generation are removed. */
-		while (bus_for_each_dev(&ieee1394_bus_type, NULL, &cleanup,
-					nodemgr_remove_node)) {
-			struct node_entry *ne = cleanup.ne;
-
-			HPSB_DEBUG("Node removed: ID:BUS[" NODE_BUS_FMT "]  GUID[%016Lx]",
-				   NODE_BUS_ARGS(host, ne->nodeid), (unsigned long long)ne->guid);
-
-			nodemgr_remove_ne(ne);
-		}
+	 * eventually.
+	 *
+	 * Now let's tell the bus to rescan our devices. This may seem
+	 * like overhead, but the driver-model core will only scan a
+	 * device for a driver when either the device is added, or when a
+	 * new driver is added. A bus reset is a good reason to rescan
+	 * devices that were there before.  For example, an sbp2 device
+	 * may become available for login, if the host that held it was
+	 * just removed.  */
 
-		/* Now let's tell the bus to rescan our devices. This may
-		 * seem like overhead, but the driver-model core will only
-		 * scan a device for a driver when either the device is
-		 * added, or when a new driver is added. A bus reset is a
-		 * good reason to rescan devices that were there before.
-		 * For example, an sbp2 device may become available for
-		 * login, if the host that held it was just removed. */
+	if (generation == get_hpsb_generation(host))
 		bus_rescan_devices(&ieee1394_bus_type);
-	}
 
 	return;
 }
@@ -1736,32 +1623,24 @@ struct node_entry *hpsb_nodeid_get_entry
 	return ne;
 }
 
-struct for_each_host_struct {
-	int (*cb)(struct hpsb_host *, void *);
-	void *data;
-};
 
-static int nodemgr_for_each_host_cb(struct device *dev, void *__data)
+int nodemgr_for_each_host(void *__data, int (*cb)(struct hpsb_host *, void *))
 {
-	struct for_each_host_struct *host_data = __data;
+	struct class *class = &hpsb_host_class;
+	struct class_device *cdev;
 	struct hpsb_host *host;
+	int error = 0;
 
-	if (dev->driver_data != &nodemgr_driverdata_host)
-		return 0;
-
-	host = container_of(dev, struct hpsb_host, device);
+	down_read(&class->subsys.rwsem);
+	list_for_each_entry(cdev, &class->children, node) {
+		host = container_of(cdev, struct hpsb_host, class_dev);
 
-	return host_data->cb(host, host_data->data);
-}
-
-int nodemgr_for_each_host(void *__data, int (*cb)(struct hpsb_host *, void *))
-{
-	struct for_each_host_struct host_data;
-
-	host_data.cb = cb;
-	host_data.data = __data;
+		if ((error = cb(host, __data)))
+			break;
+	}
+	up_read(&class->subsys.rwsem);
 
-	return bus_for_each_dev(&ieee1394_bus_type, NULL, &host_data, nodemgr_for_each_host_cb);
+	return error;
 }
 
 /* The following four convenience functions use a struct node_entry
@@ -1887,6 +1766,7 @@ void init_ieee1394_nodemgr(void)
 {
 	driver_register(&nodemgr_driver_host);
 	driver_register(&nodemgr_driver_ne);
+	class_register(&nodemgr_ne_class);
 
 	hpsb_register_highlevel(&nodemgr_highlevel);
 }
@@ -1895,6 +1775,7 @@ void cleanup_ieee1394_nodemgr(void)
 {
         hpsb_unregister_highlevel(&nodemgr_highlevel);
 
+	class_unregister(&nodemgr_ne_class);
 	driver_unregister(&nodemgr_driver_ne);
 	driver_unregister(&nodemgr_driver_host);
 }
--- diff/drivers/ieee1394/nodemgr.h	2004-01-19 10:22:56.000000000 +0000
+++ source/drivers/ieee1394/nodemgr.h	2004-02-23 13:56:41.000000000 +0000
@@ -21,50 +21,12 @@
 #define _IEEE1394_NODEMGR_H
 
 #include <linux/device.h>
+#include "csr1212.h"
 #include "ieee1394_core.h"
 #include "ieee1394_hotplug.h"
 
-#define CONFIG_ROM_BUS_INFO_LENGTH(q)		((q) >> 24)
-#define CONFIG_ROM_BUS_CRC_LENGTH(q)		(((q) >> 16) & 0xff)
-#define CONFIG_ROM_BUS_CRC(q)			((q) & 0xffff)
-
-#define CONFIG_ROM_ROOT_LENGTH(q)		((q) >> 16)
-#define CONFIG_ROM_ROOT_CRC(q)			((q) & 0xffff)
-
-#define CONFIG_ROM_DIRECTORY_LENGTH(q)		((q) >> 16)
-#define CONFIG_ROM_DIRECTORY_CRC(q)		((q) & 0xffff)
-
-#define CONFIG_ROM_LEAF_LENGTH(q)		((q) >> 16)
-#define CONFIG_ROM_LEAF_CRC(q)			((q) & 0xffff)
-
-#define CONFIG_ROM_DESCRIPTOR_TYPE(q)		((q) >> 24)
-#define CONFIG_ROM_DESCRIPTOR_SPECIFIER_ID(q)	((q) & 0xffffff)
-#define CONFIG_ROM_DESCRIPTOR_WIDTH(q)		((q) >> 28)
-#define CONFIG_ROM_DESCRIPTOR_CHAR_SET(q)	(((q) >> 16) & 0xfff)
-#define CONFIG_ROM_DESCRIPTOR_LANG(q)		((q) & 0xffff)
-
-#define CONFIG_ROM_KEY_ID_MASK			0x3f
-#define CONFIG_ROM_KEY_TYPE_MASK		0xc0
-#define CONFIG_ROM_KEY_TYPE_IMMEDIATE		0x00
-#define CONFIG_ROM_KEY_TYPE_OFFSET		0x40
-#define CONFIG_ROM_KEY_TYPE_LEAF		0x80
-#define CONFIG_ROM_KEY_TYPE_DIRECTORY		0xc0
-
-#define CONFIG_ROM_KEY(q)			((q) >> 24)
-#define CONFIG_ROM_VALUE(q)			((q) & 0xffffff)
-
-#define CONFIG_ROM_VENDOR_ID			0x03
-#define CONFIG_ROM_MODEL_ID			0x17
-#define CONFIG_ROM_NODE_CAPABILITES		0x0C
-#define CONFIG_ROM_UNIT_DIRECTORY		0xd1
-#define CONFIG_ROM_LOGICAL_UNIT_DIRECTORY	0xd4
-#define CONFIG_ROM_SPECIFIER_ID			0x12 
-#define CONFIG_ROM_UNIT_SW_VERSION		0x13
-#define CONFIG_ROM_DESCRIPTOR_LEAF		0x81
-#define CONFIG_ROM_DESCRIPTOR_DIRECTORY		0xc1
-
 /* '1' '3' '9' '4' in ASCII */
-#define IEEE1394_BUSID_MAGIC	0x31333934
+#define IEEE1394_BUSID_MAGIC	__constant_cpu_to_be32(0x31333934)
 
 /* This is the start of a Node entry structure. It should be a stable API
  * for which to gather info from the Node Manager about devices attached
@@ -76,6 +38,7 @@ struct bus_options {
 	u8	bmc;		/* Bus Master Capable */
 	u8	pmc;		/* Power Manager Capable (PNP spec) */
 	u8	cyc_clk_acc;	/* Cycle clock accuracy */
+	u8	max_rom;	/* Maximum block read supported in the CSR */
 	u8	generation;	/* Incremented when configrom changes */
 	u8	lnkspd;		/* Link speed */
 	u16	max_rec;	/* Maximum packet size node can receive */
@@ -86,10 +49,8 @@ struct bus_options {
 #define UNIT_DIRECTORY_MODEL_ID			0x02
 #define UNIT_DIRECTORY_SPECIFIER_ID		0x04
 #define UNIT_DIRECTORY_VERSION			0x08
-#define UNIT_DIRECTORY_VENDOR_TEXT		0x10
-#define UNIT_DIRECTORY_MODEL_TEXT		0x20
-#define UNIT_DIRECTORY_HAS_LUN_DIRECTORY	0x40
-#define UNIT_DIRECTORY_LUN_DIRECTORY		0x80
+#define UNIT_DIRECTORY_HAS_LUN_DIRECTORY	0x10
+#define UNIT_DIRECTORY_LUN_DIRECTORY		0x20
 
 /*
  * A unit directory corresponds to a protocol supported by the
@@ -98,28 +59,27 @@ struct bus_options {
  */
 struct unit_directory {
 	struct node_entry *ne;  /* The node which this directory belongs to */
-	octlet_t address;	/* Address of the unit directory on the node */
+	octlet_t address;       /* Address of the unit directory on the node */
 	u8 flags;		/* Indicates which entries were read */
 
 	quadlet_t vendor_id;
-	const char *vendor_name;
+	struct csr1212_keyval *vendor_name_kv;
 	const char *vendor_oui;
 
-	int vendor_name_size;
 	quadlet_t model_id;
-	const char *model_name;
-	int model_name_size;
+	struct csr1212_keyval *model_name_kv;
 	quadlet_t specifier_id;
 	quadlet_t version;
 
 	unsigned int id;
 
+	int ignore_driver;
+
 	int length;		/* Number of quadlets */
 
 	struct device device;
 
-	/* XXX Must be last in the struct! */
-	quadlet_t quadlets[0];
+	struct csr1212_keyval *ud_kv;
 };
 
 struct node_entry {
@@ -135,7 +95,7 @@ struct node_entry {
 
 	/* The following is read from the config rom */
 	u32 vendor_id;
-	const char *vendor_name;
+	struct csr1212_keyval *vendor_name_kv;
 	const char *vendor_oui;
 
 	u32 capabilities;
@@ -143,8 +103,12 @@ struct node_entry {
 
 	struct device device;
 
-	/* XXX Must be last in the struct! */
-	quadlet_t quadlets[0];
+	struct class_device class_dev;
+
+	/* Means this node is not attached anymore */
+	int in_limbo;
+
+	struct csr1212_csr *csr;
 };
 
 struct hpsb_protocol_driver {
@@ -164,9 +128,11 @@ struct hpsb_protocol_driver {
 	 * The update function is called when the node has just
 	 * survived a bus reset, i.e. it is still present on the bus.
 	 * However, it may be necessary to reestablish the connection
-	 * or login into the node again, depending on the protocol.
+	 * or login into the node again, depending on the protocol. If the
+	 * probe fails (returns non-zero), we unbind the driver from this
+	 * device.
 	 */
-	void (*update)(struct unit_directory *ud);
+	int (*update)(struct unit_directory *ud);
 
 	/* Our LDM structure */
 	struct device_driver driver;
@@ -231,4 +197,7 @@ void cleanup_ieee1394_nodemgr(void);
 /* The template for a host device */
 extern struct device nodemgr_dev_template_host;
 
+/* Bus attributes we export */
+extern struct bus_attribute *const fw_bus_attrs[];
+
 #endif /* _IEEE1394_NODEMGR_H */
--- diff/drivers/ieee1394/ohci1394.c	2004-02-09 10:36:10.000000000 +0000
+++ source/drivers/ieee1394/ohci1394.c	2004-02-23 13:56:41.000000000 +0000
@@ -115,6 +115,7 @@
 #include <asm/pci-bridge.h>
 #endif
 
+#include "csr1212.h"
 #include "ieee1394.h"
 #include "ieee1394_types.h"
 #include "hosts.h"
@@ -161,7 +162,7 @@ printk(level "%s: " fmt "\n" , OHCI1394_
 printk(level "%s: fw-host%d: " fmt "\n" , OHCI1394_DRIVER_NAME, card , ## args)
 
 static char version[] __devinitdata =
-	"$Rev: 1097 $ Ben Collins <bcollins@debian.org>";
+	"$Rev: 1131 $ Ben Collins <bcollins@debian.org>";
 
 /* Module Parameters */
 static int phys_dma = 1;
@@ -495,8 +496,6 @@ static int get_nb_iso_ctx(struct ti_ohci
 	return ctx;
 }
 
-static void ohci_init_config_rom(struct ti_ohci *ohci);
-
 /* Global initialization */
 static void ohci_initialize(struct ti_ohci *ohci)
 {
@@ -524,7 +523,8 @@ static void ohci_initialize(struct ti_oh
   
 	/* Enable cycle timer and cycle master and set the IRM
 	 * contender bit in our self ID packets. */
-	reg_write(ohci, OHCI1394_LinkControlSet, 0x00300000);
+	reg_write(ohci, OHCI1394_LinkControlSet, OHCI1394_LinkControl_CycleTimerEnable |
+		  OHCI1394_LinkControl_CycleMaster);
 	set_phy_reg_mask(ohci, 4, 0xc0);
 
 	/* Clear interrupt registers */
@@ -534,15 +534,13 @@ static void ohci_initialize(struct ti_oh
 	/* Set up self-id dma buffer */
 	reg_write(ohci, OHCI1394_SelfIDBuffer, ohci->selfid_buf_bus);
 
-	/* enable self-id dma */
-	reg_write(ohci, OHCI1394_LinkControlSet, 0x00000200);
+	/* enable self-id and phys */
+	reg_write(ohci, OHCI1394_LinkControlSet, OHCI1394_LinkControl_RcvSelfID |
+		  OHCI1394_LinkControl_RcvPhyPkt);
 
 	/* Set the Config ROM mapping register */
 	reg_write(ohci, OHCI1394_ConfigROMmap, ohci->csr_config_rom_bus);
 
-	/* Initialize the Config ROM */
-	ohci_init_config_rom(ohci);
-
 	/* Now get our max packet size */
 	ohci->max_packet_size = 
 		1<<(((reg_read(ohci, OHCI1394_BusOptions)>>12)&0xf)+1);
@@ -974,11 +972,15 @@ static int ohci_devctl(struct hpsb_host 
 				 */
 				DBGMSG(ohci->id, "Cycle master enabled");
 				reg_write(ohci, OHCI1394_LinkControlSet, 
-					  0x00300000);
+					  OHCI1394_LinkControl_CycleTimerEnable |
+					  OHCI1394_LinkControl_CycleMaster);
 			}
 		} else {
 			/* disable cycleTimer, cycleMaster, cycleSource */
-			reg_write(ohci, OHCI1394_LinkControlClear, 0x00700000);
+			reg_write(ohci, OHCI1394_LinkControlClear,
+				  OHCI1394_LinkControl_CycleTimerEnable |
+				  OHCI1394_LinkControl_CycleMaster |
+				  OHCI1394_LinkControl_CycleSource);
 		}
 		break;
 
@@ -2211,14 +2213,12 @@ static void ohci_schedule_iso_tasklets(s
 				       quadlet_t rx_event,
 				       quadlet_t tx_event)
 {
-	struct list_head *lh;
 	struct ohci1394_iso_tasklet *t;
 	unsigned long mask;
 
 	spin_lock(&ohci->iso_tasklet_list_lock);
 
-	list_for_each(lh, &ohci->iso_tasklet_list) {
-		t = list_entry(lh, struct ohci1394_iso_tasklet, link);
+	list_for_each_entry(t, &ohci->iso_tasklet_list, link) {
 		mask = 1 << t->context;
 
 		if (t->type == OHCI_ISO_TRANSMIT && tx_event & mask)
@@ -3085,154 +3085,16 @@ alloc_dma_trm_ctx(struct ti_ohci *ohci, 
 	return 0;
 }
 
-static u16 ohci_crc16 (u32 *ptr, int length)
+static void ohci_set_hw_config_rom(struct hpsb_host *host, quadlet_t *config_rom)
 {
-	int shift;
-	u32 crc, sum, data;
-
-	crc = 0;
-	for (; length > 0; length--) {
-		data = be32_to_cpu(*ptr++);
-		for (shift = 28; shift >= 0; shift -= 4) {
-			sum = ((crc >> 12) ^ (data >> shift)) & 0x000f;
-			crc = (crc << 4) ^ (sum << 12) ^ (sum << 5) ^ sum;
-		}
-		crc &= 0xffff;
-	}
-	return crc;
-}
-
-/* Config ROM macro implementation influenced by NetBSD OHCI driver */
-
-struct config_rom_unit {
-	u32 *start;
-	u32 *refer;
-	int length;
-	int refunit;
-};
-
-struct config_rom_ptr {
-	u32 *data;
-	int unitnum;
-	struct config_rom_unit unitdir[10];
-};
-
-#define cf_put_1quad(cr, q) (((cr)->data++)[0] = cpu_to_be32(q))
-
-#define cf_put_4bytes(cr, b1, b2, b3, b4) \
-	(((cr)->data++)[0] = cpu_to_be32(((b1) << 24) | ((b2) << 16) | ((b3) << 8) | (b4)))
-
-#define cf_put_keyval(cr, key, val) (((cr)->data++)[0] = cpu_to_be32(((key) << 24) | (val)))
-
-static inline void cf_put_str(struct config_rom_ptr *cr, const char *str)
-{
-	int t;
-	char fourb[4];
-
-	while (str[0]) {
-		memset(fourb, 0, 4);
-		for (t = 0; t < 4 && str[t]; t++)
-			fourb[t] = str[t];
-		cf_put_4bytes(cr, fourb[0], fourb[1], fourb[2], fourb[3]);
-		str += strlen(str) < 4 ? strlen(str) : 4;
-	}
-	return;
-}
-
-static inline void cf_put_crc16(struct config_rom_ptr *cr, int unit)
-{
-	*cr->unitdir[unit].start =
-		cpu_to_be32((cr->unitdir[unit].length << 16) |
-			    ohci_crc16(cr->unitdir[unit].start + 1,
-				       cr->unitdir[unit].length));
-}
-
-static inline void cf_unit_begin(struct config_rom_ptr *cr, int unit)
-{
-	if (cr->unitdir[unit].refer != NULL) {
-		*cr->unitdir[unit].refer |=
-			cpu_to_be32 (cr->data - cr->unitdir[unit].refer);
-		cf_put_crc16(cr, cr->unitdir[unit].refunit);
-	}
-	cr->unitnum = unit;
-	cr->unitdir[unit].start = cr->data++;
-}
-
-static inline void cf_put_refer(struct config_rom_ptr *cr, char key, int unit)
-{
-	cr->unitdir[unit].refer = cr->data;
-	cr->unitdir[unit].refunit = cr->unitnum;
-	(cr->data++)[0] = cpu_to_be32(key << 24);
-}
-
-static inline void cf_unit_end(struct config_rom_ptr *cr)
-{
-	cr->unitdir[cr->unitnum].length = cr->data -
-		(cr->unitdir[cr->unitnum].start + 1);
-	cf_put_crc16(cr, cr->unitnum);
-}
-
-/* End of NetBSD derived code.  */
-
-static void ohci_init_config_rom(struct ti_ohci *ohci)
-{
-	struct config_rom_ptr cr;
-
-	memset(&cr, 0, sizeof(cr));
-	memset(ohci->csr_config_rom_cpu, 0, OHCI_CONFIG_ROM_LEN);
-
-	cr.data = ohci->csr_config_rom_cpu;
-
-	/* Bus info block */
-	cf_unit_begin(&cr, 0);
-	cf_put_1quad(&cr, reg_read(ohci, OHCI1394_BusID));
-	cf_put_1quad(&cr, reg_read(ohci, OHCI1394_BusOptions));
-	cf_put_1quad(&cr, reg_read(ohci, OHCI1394_GUIDHi));
-	cf_put_1quad(&cr, reg_read(ohci, OHCI1394_GUIDLo));
-	cf_unit_end(&cr);
-
-	DBGMSG(ohci->id, "GUID: %08x:%08x", reg_read(ohci, OHCI1394_GUIDHi),
-		reg_read(ohci, OHCI1394_GUIDLo));
-
-	/* IEEE P1212 suggests the initial ROM header CRC should only
-	 * cover the header itself (and not the entire ROM). Since we do
-	 * this, then we can make our bus_info_len the same as the CRC
-	 * length.  */
-	ohci->csr_config_rom_cpu[0] |= cpu_to_be32(
-		(be32_to_cpu(ohci->csr_config_rom_cpu[0]) & 0x00ff0000) << 8);
-	reg_write(ohci, OHCI1394_ConfigROMhdr,
-		  be32_to_cpu(ohci->csr_config_rom_cpu[0]));
-
-	/* Root directory */
-	cf_unit_begin(&cr, 1);
-	/* Vendor ID */
-	cf_put_keyval(&cr, 0x03, reg_read(ohci,OHCI1394_VendorID) & 0xFFFFFF);
-	cf_put_refer(&cr, 0x81, 2);		/* Textual description unit */
-	cf_put_keyval(&cr, 0x0c, 0x0083c0);	/* Node capabilities */
-	/* NOTE: Add other unit referers here, and append at bottom */
-	cf_unit_end(&cr);
+	struct ti_ohci *ohci = host->hostdata;
 
-	/* Textual description - "Linux 1394" */
-	cf_unit_begin(&cr, 2);
-	cf_put_keyval(&cr, 0, 0);
-	cf_put_1quad(&cr, 0);
-	cf_put_str(&cr, "Linux OHCI-1394");
-	cf_unit_end(&cr);
+	reg_write(ohci, OHCI1394_ConfigROMhdr, be32_to_cpu(config_rom[0]));
+	reg_write(ohci, OHCI1394_BusOptions, be32_to_cpu(config_rom[2]));
 
-	ohci->csr_config_rom_length = cr.data - ohci->csr_config_rom_cpu;
+	memcpy(ohci->csr_config_rom_cpu, config_rom, OHCI_CONFIG_ROM_LEN);
 }
 
-static size_t ohci_get_rom(struct hpsb_host *host, quadlet_t **ptr)
-{
-	struct ti_ohci *ohci=host->hostdata;
-
-	DBGMSG(ohci->id, "request csr_rom address: %p",
-		ohci->csr_config_rom_cpu);
-
-	*ptr = ohci->csr_config_rom_cpu;
-
-	return ohci->csr_config_rom_length * 4;
-}
 
 static quadlet_t ohci_hw_csr_reg(struct hpsb_host *host, int reg,
                                  quadlet_t data, quadlet_t compare)
@@ -3257,7 +3119,7 @@ static quadlet_t ohci_hw_csr_reg(struct 
 static struct hpsb_host_driver ohci1394_driver = {
 	.owner =		THIS_MODULE,
 	.name =			OHCI1394_DRIVER_NAME,
-	.get_rom =		ohci_get_rom,
+	.set_hw_config_rom =	ohci_set_hw_config_rom,
 	.transmit_packet =	ohci_transmit,
 	.devctl =		ohci_devctl,
 	.isoctl =               ohci_isoctl,
@@ -3280,6 +3142,11 @@ do {						\
 static int __devinit ohci1394_pci_probe(struct pci_dev *dev,
 					const struct pci_device_id *ent)
 {
+	struct csr1212_keyval *root;
+	struct csr1212_keyval *vend_id = NULL;
+	struct csr1212_keyval *text = NULL;
+	int ret;
+
 	static int version_printed = 0;
 
 	struct hpsb_host *host;
@@ -3422,6 +3289,11 @@ static int __devinit ohci1394_pci_probe(
 	 * will lock up the machine.  Wait 50msec to make sure we have
 	 * full link enabled.  */
 	reg_write(ohci, OHCI1394_HCControlSet, OHCI1394_HCControl_LPS);
+
+	/* Disable and clear interrupts */
+	reg_write(ohci, OHCI1394_IntEventClear, 0xffffffff);
+	reg_write(ohci, OHCI1394_IntMaskClear, 0xffffffff);
+
 	mdelay(50);
 
 	/* Determine the number of available IR and IT contexts. */
@@ -3458,6 +3330,45 @@ static int __devinit ohci1394_pci_probe(
 	ohci->init_state = OHCI_INIT_HAVE_IRQ;
 	ohci_initialize(ohci);
 
+	/* Setup initial root directory entries */
+	root = host->csr.rom->root_kv;
+
+	vend_id = csr1212_new_immediate(CSR1212_KV_ID_VENDOR,
+					reg_read(ohci, OHCI1394_GUIDHi) >> 8);
+	text = csr1212_new_string_descriptor_leaf("Linux 1394 - OHCI");
+
+	if (!vend_id || !text) {
+		if (vend_id) {
+			csr1212_release_keyval(vend_id);
+		}
+		if (text) {
+			csr1212_release_keyval(text);
+		}
+		FAIL(-ENOMEM, "Failed to allocate memory for mandatory ConfigROM entries!");
+	}
+
+	ret = csr1212_associate_keyval(vend_id, text);
+	csr1212_release_keyval(text);
+	if(ret != CSR1212_SUCCESS) {
+		csr1212_release_keyval(vend_id);
+		FAIL(ret, "Failed to associate text descriptor to vendor id");
+	}
+
+	ret = csr1212_attach_keyval_to_directory(root, vend_id);
+	if(ret != CSR1212_SUCCESS) {
+		csr1212_release_keyval(vend_id);
+		FAIL(ret, "Failed to attach vendor id to root directory");
+	}
+
+	host->update_config_rom = 1;
+
+	/* Set certain csr values */
+	host->csr.guid_hi = reg_read(ohci, OHCI1394_GUIDHi);
+	host->csr.guid_lo = reg_read(ohci, OHCI1394_GUIDLo);
+	host->csr.cyc_clk_acc = 100;  /* how do we determine clk accuracy? */
+	host->csr.max_rec = (reg_read(ohci, OHCI1394_BusOptions) >> 12) & 0xf;
+	host->csr.lnk_spd = reg_read(ohci, OHCI1394_BusOptions) & 0x7;
+
 	/* Tell the highlevel this host is ready */
 	hpsb_add_host(host);
 	ohci->init_state = OHCI_INIT_DONE;
@@ -3574,14 +3485,41 @@ static void ohci1394_pci_remove(struct p
 }
 
 
-#ifdef  CONFIG_PM
-static int ohci1394_pci_resume (struct pci_dev *dev)
+static int ohci1394_pci_resume (struct pci_dev *pdev)
 {
-	pci_enable_device(dev);
+#ifdef CONFIG_PMAC_PBOOK
+	{
+		struct device_node *of_node;
+
+		/* Re-enable 1394 */
+		of_node = pci_device_to_OF_node (pdev);
+		if (of_node)
+			pmac_call_feature (PMAC_FTR_1394_ENABLE, of_node, 0, 1);
+	}
+#endif
+
+	pci_enable_device(pdev);
+
 	return 0;
 }
+
+
+static int ohci1394_pci_suspend (struct pci_dev *pdev, u32 state)
+{
+#ifdef CONFIG_PMAC_PBOOK
+	{
+		struct device_node *of_node;
+
+		/* Disable 1394 */
+		of_node = pci_device_to_OF_node (pdev);
+		if (of_node)
+			pmac_call_feature(PMAC_FTR_1394_ENABLE, of_node, 0, 0);
+	}
 #endif
 
+	return 0;
+}
+
 
 #define PCI_CLASS_FIREWIRE_OHCI     ((PCI_CLASS_SERIAL_FIREWIRE << 8) | 0x10)
 
@@ -3604,10 +3542,8 @@ static struct pci_driver ohci1394_pci_dr
 	.id_table =	ohci1394_pci_tbl,
 	.probe =	ohci1394_pci_probe,
 	.remove =	ohci1394_pci_remove,
-
-#ifdef  CONFIG_PM
 	.resume =	ohci1394_pci_resume,
-#endif  /* PM */
+	.suspend =	ohci1394_pci_suspend,
 };
 
 
--- diff/drivers/ieee1394/ohci1394.h	2003-09-17 12:28:06.000000000 +0100
+++ source/drivers/ieee1394/ohci1394.h	2004-02-23 13:56:41.000000000 +0000
@@ -320,6 +320,11 @@ static inline u32 reg_read(const struct 
 #define OHCI1394_FairnessControl              0x0DC
 #define OHCI1394_LinkControlSet               0x0E0
 #define OHCI1394_LinkControlClear             0x0E4
+#define  OHCI1394_LinkControl_RcvSelfID		0x00000200
+#define  OHCI1394_LinkControl_RcvPhyPkt		0x00000400
+#define  OHCI1394_LinkControl_CycleTimerEnable	0x00100000
+#define  OHCI1394_LinkControl_CycleMaster	0x00200000
+#define  OHCI1394_LinkControl_CycleSource	0x00400000
 #define OHCI1394_NodeID                       0x0E8
 #define OHCI1394_PhyControl                   0x0EC
 #define OHCI1394_IsochronousCycleTimer        0x0F0
--- diff/drivers/ieee1394/pcilynx.c	2004-01-19 10:22:56.000000000 +0000
+++ source/drivers/ieee1394/pcilynx.c	2004-02-23 13:56:41.000000000 +0000
@@ -49,6 +49,7 @@
 #include <asm/io.h>
 #include <asm/uaccess.h>
 
+#include "csr1212.h"
 #include "ieee1394.h"
 #include "ieee1394_types.h"
 #include "hosts.h"
@@ -1515,6 +1516,11 @@ static int __devinit add_card(struct pci
         return error; \
         } while (0)
 
+	struct csr1212_keyval *root;
+	struct csr1212_keyval *vend_id = NULL;
+	struct csr1212_keyval *text = NULL;
+	int ret;
+
 	char irq_buf[16];
 	struct hpsb_host *host;
         struct ti_lynx *lynx; /* shortcut to currently handled device */
@@ -1527,8 +1533,6 @@ static int __devinit add_card(struct pci
         struct i2c_adapter i2c_adapter;
         struct i2c_algo_bit_data i2c_adapter_data;
 
-        int got_valid_bus_info_block = 0; /* set to 1, if we were able to get a valid bus info block from serial eeprom */
-
         error = -ENXIO;
 
         if (pci_set_dma_mask(dev, 0xffffffff))
@@ -1814,14 +1818,15 @@ static int __devinit add_card(struct pci
 
         	if (i2c_bit_add_bus(&i2c_adapter) < 0)
         	{
-	        	PRINT(KERN_ERR, lynx->id,  "unable to register i2c");
+			error = -ENXIO;
+			FAIL("unable to register i2c");
         	}
         	else
         	{
                         /* do i2c stuff */
                         unsigned char i2c_cmd = 0x10;
                         struct i2c_msg msg[2] = { { 0x50, 0, 1, &i2c_cmd }, 
-                                                  { 0x50, I2C_M_RD, 20, (unsigned char*) lynx->config_rom }
+                                                  { 0x50, I2C_M_RD, 20, (unsigned char*) lynx->bus_info_block }
                                                 };
 
 
@@ -1858,16 +1863,16 @@ static int __devinit add_card(struct pci
 
                                 for (i = 0; i < 5 ; i++)
                                         PRINTD(KERN_DEBUG, lynx->id, "Businfo block quadlet %i: %08x",
-					       i, be32_to_cpu(lynx->config_rom[i]));
+					       i, be32_to_cpu(lynx->bus_info_block[i]));
 
                                 /* info_length, crc_length and 1394 magic number to check, if it is really a bus info block */
-                                if (((be32_to_cpu(lynx->config_rom[0]) & 0xffff0000) == 0x04040000) &&
-                                    (lynx->config_rom[1] == __constant_cpu_to_be32(0x31333934)))
+				if (((be32_to_cpu(lynx->bus_info_block[0]) & 0xffff0000) == 0x04040000) &&
+				    (lynx->bus_info_block[1] == __constant_cpu_to_be32(0x31333934)))
                                 {
                                         PRINT(KERN_DEBUG, lynx->id, "read a valid bus info block from");
-                                        got_valid_bus_info_block = 1;
                                 } else {
-                                        PRINT(KERN_WARNING, lynx->id, "read something from serial eeprom, but it does not seem to be a valid bus info block");
+					error = -ENXIO;
+					FAIL("read something from serial eeprom, but it does not seem to be a valid bus info block");
                                 }
 
                         }
@@ -1876,29 +1881,55 @@ static int __devinit add_card(struct pci
                 }
         }
 
-        if (got_valid_bus_info_block) {
-                memcpy(lynx->config_rom+5,lynx_csr_rom+5,sizeof(lynx_csr_rom)-20);
-        } else {
-                PRINT(KERN_INFO, lynx->id, "since we did not get a bus info block from serial eeprom, we use a generic one with a hard coded GUID");
-                memcpy(lynx->config_rom,lynx_csr_rom,sizeof(lynx_csr_rom));
-        }
-
-        hpsb_add_host(host);
-        lynx->state = is_host;
+	host->csr.guid_hi = be32_to_cpu(lynx->bus_info_block[3]);
+	host->csr.guid_lo = be32_to_cpu(lynx->bus_info_block[4]);
+	host->csr.cyc_clk_acc = (be32_to_cpu(lynx->bus_info_block[2]) >> 16) & 0xff;
+	host->csr.max_rec = (be32_to_cpu(lynx->bus_info_block[2]) >> 12) & 0xf;
+	if (!lynx->phyic.reg_1394a)
+		host->csr.lnk_spd = (get_phy_reg(lynx, 2) & 0xc0) >> 6;
+	else
+		host->csr.lnk_spd = be32_to_cpu(lynx->bus_info_block[2]) & 0x7;
+
+	/* Setup initial root directory entries */
+	root = host->csr.rom->root_kv;
+
+	vend_id = csr1212_new_immediate(CSR1212_KV_ID_VENDOR,
+					be32_to_cpu(lynx->bus_info_block[3]) >> 8);
+	text = csr1212_new_string_descriptor_leaf("Linux 1394 - PCI-Lynx");
+
+	if (!vend_id || !text) {
+		if (vend_id)
+			csr1212_release_keyval(vend_id);
+		if (text)
+			csr1212_release_keyval(text);
+		error = -ENOMEM;
+		FAIL("Failed to allocate memory for mandatory ConfigROM entries!");
+	}
 
-        return 0;
-#undef FAIL
-}
+	ret = csr1212_associate_keyval(vend_id, text);
+	csr1212_release_keyval(text);		/* no longer needed locally. */
+	if(ret != CSR1212_SUCCESS) {
+		csr1212_release_keyval(vend_id);
+		error = ret;
+		FAIL("Failed to associate text descriptor to vendor id");
+	}
 
+	ret = csr1212_attach_keyval_to_directory(root, vend_id);
+	csr1212_release_keyval(vend_id);	/* no longer needed locally. */
+	if(ret != CSR1212_SUCCESS) {
+		error = ret;
+		FAIL("Failed to attach vendor id to root directory");
+	}
 
+	host->update_config_rom = 1;
+	hpsb_add_host(host);
+	lynx->state = is_host;
 
-static size_t get_lynx_rom(struct hpsb_host *host, quadlet_t **ptr)
-{
-        struct ti_lynx *lynx = host->hostdata;
-        *ptr = lynx->config_rom;
-        return sizeof(lynx_csr_rom);
+	return ret;
+#undef FAIL
 }
 
+
 static struct pci_device_id pci_table[] = {
 	{
                 .vendor =    PCI_VENDOR_ID_TI,
@@ -1919,7 +1950,7 @@ static struct pci_driver lynx_pci_driver
 static struct hpsb_host_driver lynx_driver = {
 	.owner =	   THIS_MODULE,
 	.name =		   PCILYNX_DRIVER_NAME,
-        .get_rom =         get_lynx_rom,
+	.set_hw_config_rom = NULL,
         .transmit_packet = lynx_transmit,
         .devctl =          lynx_devctl,
 	.isoctl =          NULL,
--- diff/drivers/ieee1394/pcilynx.h	2003-02-26 16:01:01.000000000 +0000
+++ source/drivers/ieee1394/pcilynx.h	2004-02-23 13:56:41.000000000 +0000
@@ -1,3 +1,6 @@
+#ifndef __PCILYNX_H__
+#define __PCILYNX_H__
+
 #include <linux/config.h>
 
 #define PCILYNX_DRIVER_NAME      "pcilynx"
@@ -50,7 +53,7 @@ struct ti_lynx {
         void *local_rom;
         void *local_ram;
         void *aux_port;
-        quadlet_t config_rom[PCILYNX_CONFIG_ROM_LENGTH/4];
+	quadlet_t bus_info_block[5];
 
 #ifdef CONFIG_IEEE1394_PCILYNX_PORTS
         atomic_t aux_intr_seen;
@@ -510,76 +513,4 @@ static inline void run_pcl(const struct 
 #define PCL_BIGENDIAN          (1<<16)
 #define PCL_ISOMODE            (1<<12)
 
-
-#define _(x) (__constant_cpu_to_be32(x))
-
-static quadlet_t lynx_csr_rom[] = {
-/* bus info block     offset (hex) */
-        _(0x04046aaf), /* info/CRC length, CRC              400  */
-        _(0x31333934), /* 1394 magic number                 404  */
-        _(0xf064a000), /* misc. settings                    408  */
-        _(0x08002850), /* vendor ID, chip ID high           40c  */
-        _(0x0000ffff), /* chip ID low                       410  */
-/* root directory */
-        _(0x00095778), /* directory length, CRC             414  */
-        _(0x03080028), /* vendor ID (Texas Instr.)          418  */
-        _(0x81000008), /* offset to textual ID              41c  */
-        _(0x0c000200), /* node capabilities                 420  */
-        _(0x8d00000e), /* offset to unique ID               424  */
-        _(0xc7000010), /* offset to module independent info 428  */
-        _(0x04000000), /* module hardware version           42c  */
-        _(0x81000014), /* offset to textual ID              430  */
-        _(0x09000000), /* node hardware version             434  */
-        _(0x81000018), /* offset to textual ID              438  */
-/* module vendor ID textual */
-        _(0x00070812), /* CRC length, CRC                   43c  */
-        _(0x00000000), /*                                   440  */
-        _(0x00000000), /*                                   444  */
-        _(0x54455841), /* "Texas Instruments"               448  */
-        _(0x5320494e), /*                                   44c  */
-        _(0x53545255), /*                                   450  */
-        _(0x4d454e54), /*                                   454  */
-        _(0x53000000), /*                                   458  */
-/* node unique ID leaf */
-        _(0x00022ead), /* CRC length, CRC                   45c  */
-        _(0x08002850), /* vendor ID, chip ID high           460  */
-        _(0x0000ffff), /* chip ID low                       464  */
-/* module dependent info */
-        _(0x0005d837), /* CRC length, CRC                   468  */
-        _(0x81000012), /* offset to module textual ID       46c  */
-        _(0x81000017), /* textual descriptor                470  */
-        _(0x39010000), /* SRAM size                         474  */
-        _(0x3a010000), /* AUXRAM size                       478  */
-        _(0x3b000000), /* AUX device                        47c  */
-/* module textual ID */
-        _(0x000594df), /* CRC length, CRC                   480  */
-        _(0x00000000), /*                                   484  */
-        _(0x00000000), /*                                   488  */
-        _(0x54534231), /* "TSB12LV21"                       48c  */
-        _(0x324c5632), /*                                   490  */
-        _(0x31000000), /*                                   494  */
-/* part number */
-        _(0x00068405), /* CRC length, CRC                   498  */
-        _(0x00000000), /*                                   49c  */
-        _(0x00000000), /*                                   4a0  */
-        _(0x39383036), /* "9806000-0001"                    4a4  */
-        _(0x3030302d), /*                                   4a8  */
-        _(0x30303031), /*                                   4ac  */
-        _(0x20000001), /*                                   4b0  */
-/* module hardware version textual */
-        _(0x00056501), /* CRC length, CRC                   4b4  */
-        _(0x00000000), /*                                   4b8  */
-        _(0x00000000), /*                                   4bc  */
-        _(0x5453424b), /* "TSBKPCITST"                      4c0  */
-        _(0x50434954), /*                                   4c4  */
-        _(0x53540000), /*                                   4c8  */
-/* node hardware version textual */
-        _(0x0005d805), /* CRC length, CRC                   4d0  */
-        _(0x00000000), /*                                   4d4  */
-        _(0x00000000), /*                                   4d8  */
-        _(0x54534232), /* "TSB21LV03"                       4dc  */
-        _(0x314c5630), /*                                   4e0  */
-        _(0x33000000)  /*                                   4e4  */
-};
-
-#undef _
+#endif
--- diff/drivers/ieee1394/raw1394-private.h	2003-02-26 16:01:01.000000000 +0000
+++ source/drivers/ieee1394/raw1394-private.h	2004-02-23 13:56:41.000000000 +0000
@@ -7,6 +7,8 @@
 #define RAW1394_DEVICE_MAJOR      171
 #define RAW1394_DEVICE_NAME       "raw1394"
 
+#define RAW1394_MAX_USER_CSR_DIRS	16
+
 struct iso_block_store {
         atomic_t refcount;
         size_t data_size;
@@ -45,6 +47,12 @@ struct file_info {
 	/* new rawiso API */
 	enum raw1394_iso_state iso_state;
 	struct hpsb_iso *iso_handle;
+
+	/* User space's CSR1212 dynamic ConfigROM directories */
+	struct csr1212_keyval *csr1212_dirs[RAW1394_MAX_USER_CSR_DIRS];
+
+	/* Legacy ConfigROM update flag */
+	u8 cfgrom_upd;
 };
 
 struct arm_addr {
--- diff/drivers/ieee1394/raw1394.c	2004-02-18 08:54:09.000000000 +0000
+++ source/drivers/ieee1394/raw1394.c	2004-02-23 13:56:41.000000000 +0000
@@ -43,6 +43,7 @@
 #include <asm/atomic.h>
 #include <linux/devfs_fs_kernel.h>
 
+#include "csr1212.h"
 #include "ieee1394.h"
 #include "ieee1394_types.h"
 #include "ieee1394_core.h"
@@ -214,15 +215,11 @@ static void add_host(struct hpsb_host *h
 
 static struct host_info *find_host_info(struct hpsb_host *host)
 {
-        struct list_head *lh;
         struct host_info *hi;
 
-        list_for_each(lh, &host_info_list) {
-                hi = list_entry(lh, struct host_info, list);
-                if (hi->host == host) {
+        list_for_each_entry(hi, &host_info_list, list)
+                if (hi->host == host)
                         return hi;
-                }
-        }
 
         return NULL;
 }
@@ -261,7 +258,6 @@ static void remove_host(struct hpsb_host
 static void host_reset(struct hpsb_host *host)
 {
         unsigned long flags;
-        struct list_head *lh;
         struct host_info *hi;
         struct file_info *fi;
         struct pending_request *req;
@@ -270,8 +266,7 @@ static void host_reset(struct hpsb_host 
         hi = find_host_info(host);
 
         if (hi != NULL) {
-                list_for_each(lh, &hi->file_info_list) {
-                        fi = list_entry(lh, struct file_info, list);
+                list_for_each_entry(fi, &hi->file_info_list, list) {
                         if (fi->notification == RAW1394_NOTIFY_ON) {
                                 req = __alloc_pending_request(SLAB_ATOMIC);
 
@@ -298,10 +293,9 @@ static void iso_receive(struct hpsb_host
                         size_t length)
 {
         unsigned long flags;
-        struct list_head *lh;
         struct host_info *hi;
         struct file_info *fi;
-        struct pending_request *req;
+        struct pending_request *req, *req_next;
         struct iso_block_store *ibs = NULL;
         LIST_HEAD(reqs);
 
@@ -314,12 +308,9 @@ static void iso_receive(struct hpsb_host
         hi = find_host_info(host);
 
         if (hi != NULL) {
-		list_for_each(lh, &hi->file_info_list) {
-                        fi = list_entry(lh, struct file_info, list);
-
-                        if (!(fi->listen_channels & (1ULL << channel))) {
+		list_for_each_entry(fi, &hi->file_info_list, list) {
+                        if (!(fi->listen_channels & (1ULL << channel)))
                                 continue;
-                        }
 
                         req = __alloc_pending_request(SLAB_ATOMIC);
                         if (!req) break;
@@ -354,23 +345,17 @@ static void iso_receive(struct hpsb_host
         }
         spin_unlock_irqrestore(&host_info_lock, flags);
 
-        lh = reqs.next;
-        while (lh != &reqs) {
-                req = list_entry(lh, struct pending_request, list);
-                lh = lh->next;
-
+	list_for_each_entry_safe(req, req_next, &reqs, list)
                 queue_complete_req(req);
-        }
 }
 
 static void fcp_request(struct hpsb_host *host, int nodeid, int direction,
 			int cts, u8 *data, size_t length)
 {
         unsigned long flags;
-        struct list_head *lh;
         struct host_info *hi;
         struct file_info *fi;
-        struct pending_request *req;
+        struct pending_request *req, *req_next;
         struct iso_block_store *ibs = NULL;
         LIST_HEAD(reqs);
 
@@ -383,12 +368,9 @@ static void fcp_request(struct hpsb_host
         hi = find_host_info(host);
 
         if (hi != NULL) {
-		list_for_each(lh, &hi->file_info_list) {
-                        fi = list_entry(lh, struct file_info, list);
-
-                        if (!fi->fcp_buffer) {
+		list_for_each_entry(fi, &hi->file_info_list, list) {
+                        if (!fi->fcp_buffer)
                                 continue;
-                        }
 
                         req = __alloc_pending_request(SLAB_ATOMIC);
                         if (!req) break;
@@ -423,13 +405,8 @@ static void fcp_request(struct hpsb_host
         }
         spin_unlock_irqrestore(&host_info_lock, flags);
 
-        lh = reqs.next;
-        while (lh != &reqs) {
-                req = list_entry(lh, struct pending_request, list);
-                lh = lh->next;
-
+	list_for_each_entry_safe(req, req_next, &reqs, list)
                 queue_complete_req(req);
-        }
 }
 
 
@@ -505,7 +482,6 @@ static int state_opened(struct file_info
 
 static int state_initialized(struct file_info *fi, struct pending_request *req)
 {
-        struct list_head *lh;
         struct host_info *hi;
         struct raw1394_khost_list *khl;
 
@@ -527,12 +503,9 @@ static int state_initialized(struct file
                         req->req.misc = host_count;
                         req->data = (quadlet_t *)khl;
                         
-                        list_for_each(lh, &host_info_list) {
-                                hi = list_entry(lh, struct host_info, list);
-
+                        list_for_each_entry(hi, &host_info_list, list) {
                                 khl->nodes = hi->host->node_count;
                                 strcpy(khl->name, hi->host->driver->name);
-
                                 khl++;
                         }
                 }
@@ -550,23 +523,17 @@ static int state_initialized(struct file
                 break;
 
         case RAW1394_REQ_SET_CARD:
-                lh = NULL;
-
                 spin_lock_irq(&host_info_lock);
                 if (req->req.misc < host_count) {
-                        lh = host_info_list.next;
-                        while (req->req.misc--) {
-                                lh = lh->next;
-                        }
-                        hi = list_entry(lh, struct host_info, list);
+			list_for_each_entry(hi, &host_info_list, list) {
+				if (!req->req.misc--)
+					break;
+			}
 			get_device(&hi->host->device); // XXX Need to handle failure case
                         list_add_tail(&fi->list, &hi->file_info_list);
                         fi->host = hi->host;
                         fi->state = connected;
-                }
-                spin_unlock_irq(&host_info_lock);
 
-                if (lh != NULL) {
                         req->req.error = RAW1394_ERROR_NONE;
                         req->req.generation = get_hpsb_generation(fi->host);
                         req->req.misc = (fi->host->node_id << 16) 
@@ -577,6 +544,7 @@ static int state_initialized(struct file
                 } else {
                         req->req.error = RAW1394_ERROR_INVALID_ARG;
                 }
+		spin_unlock_irq(&host_info_lock);
 
                 req->req.length = 0;
                 break;
@@ -898,7 +866,6 @@ static int arm_read (struct hpsb_host *h
 		     u64 addr, size_t length, u16 flags)
 {
         struct pending_request *req;
-        struct list_head *lh;
         struct host_info *hi;
         struct file_info *fi = NULL;
         struct list_head *entry;
@@ -915,8 +882,7 @@ static int arm_read (struct hpsb_host *h
         spin_lock(&host_info_lock);
         hi = find_host_info(host); /* search address-entry */
         if (hi != NULL) {
-                list_for_each(lh, &hi->file_info_list) {
-                        fi = list_entry(lh, struct file_info, list);
+                list_for_each_entry(fi, &hi->file_info_list, list) {
                         entry = fi->addr_list.next;
                         while (entry != &(fi->addr_list)) {
                                 arm_addr = list_entry(entry, struct arm_addr, addr_list);
@@ -1034,7 +1000,6 @@ static int arm_write (struct hpsb_host *
 		      quadlet_t *data, u64 addr, size_t length, u16 flags)
 {
         struct pending_request *req;
-        struct list_head *lh;
         struct host_info *hi;
         struct file_info *fi = NULL;
         struct list_head *entry;
@@ -1051,8 +1016,7 @@ static int arm_write (struct hpsb_host *
         spin_lock(&host_info_lock);
         hi = find_host_info(host); /* search address-entry */
         if (hi != NULL) {
-                list_for_each(lh, &hi->file_info_list) {
-                        fi = list_entry(lh, struct file_info, list);
+                list_for_each_entry(fi, &hi->file_info_list, list) {
                         entry = fi->addr_list.next;
                         while (entry != &(fi->addr_list)) {
                                 arm_addr = list_entry(entry, struct arm_addr, addr_list);
@@ -1161,7 +1125,6 @@ static int arm_lock (struct hpsb_host *h
              u64 addr, quadlet_t data, quadlet_t arg, int ext_tcode, u16 flags)
 {
         struct pending_request *req;
-        struct list_head *lh;
         struct host_info *hi;
         struct file_info *fi = NULL;
         struct list_head *entry;
@@ -1187,8 +1150,7 @@ static int arm_lock (struct hpsb_host *h
         spin_lock(&host_info_lock);
         hi = find_host_info(host); /* search address-entry */
         if (hi != NULL) {
-                list_for_each(lh, &hi->file_info_list) {
-                        fi = list_entry(lh, struct file_info, list);
+                list_for_each_entry(fi, &hi->file_info_list, list) {
                         entry = fi->addr_list.next;
                         while (entry != &(fi->addr_list)) {
                                 arm_addr = list_entry(entry, struct arm_addr, addr_list);
@@ -1359,7 +1321,6 @@ static int arm_lock64 (struct hpsb_host 
                u64 addr, octlet_t data, octlet_t arg, int ext_tcode, u16 flags)
 {
         struct pending_request *req;
-        struct list_head *lh;
         struct host_info *hi;
         struct file_info *fi = NULL;
         struct list_head *entry;
@@ -1394,8 +1355,7 @@ static int arm_lock64 (struct hpsb_host 
         spin_lock(&host_info_lock);
         hi = find_host_info(host); /* search addressentry in file_info's for host */
         if (hi != NULL) {
-                list_for_each(lh, &hi->file_info_list) {
-                        fi = list_entry(lh, struct file_info, list);
+                list_for_each_entry(fi, &hi->file_info_list, list) {
                         entry = fi->addr_list.next;
                         while (entry != &(fi->addr_list)) {
                                 arm_addr = list_entry(entry, struct arm_addr, addr_list);
@@ -1566,7 +1526,6 @@ static int arm_register(struct file_info
 {
         int retval;
         struct arm_addr *addr;
-        struct list_head *lh, *lh_1, *lh_2;
         struct host_info *hi;
         struct file_info *fi_hlp = NULL;
         struct list_head *entry;
@@ -1630,8 +1589,7 @@ static int arm_register(struct file_info
         same_host = 0;
         another_host = 0;
         /* same host with address-entry containing same addressrange ? */
-        list_for_each(lh, &hi->file_info_list) {
-                fi_hlp = list_entry(lh, struct file_info, list);
+        list_for_each_entry(fi_hlp, &hi->file_info_list, list) {
                 entry = fi_hlp->addr_list.next;
                 while (entry != &(fi_hlp->addr_list)) {
                         arm_addr = list_entry(entry, struct arm_addr, addr_list);
@@ -1656,11 +1614,9 @@ static int arm_register(struct file_info
                 return (-EALREADY);
         }
         /* another host with valid address-entry containing same addressrange */
-        list_for_each(lh_1, &host_info_list) {
-                hi = list_entry(lh_1, struct host_info, list);
+        list_for_each_entry(hi, &host_info_list, list) {
                 if (hi->host != fi->host) {
-                        list_for_each(lh_2, &hi->file_info_list) {
-                                fi_hlp = list_entry(lh_2, struct file_info, list);
+                        list_for_each_entry(fi_hlp, &hi->file_info_list, list) {
                                 entry = fi_hlp->addr_list.next;
                                 while (entry != &(fi_hlp->addr_list)) {
                                         arm_addr = list_entry(entry, struct arm_addr, addr_list);
@@ -1719,7 +1675,6 @@ static int arm_unregister(struct file_in
         int retval = 0;
         struct list_head *entry;
         struct arm_addr  *addr = NULL;
-        struct list_head *lh_1, *lh_2;
         struct host_info *hi;
         struct file_info *fi_hlp = NULL;
         struct arm_addr  *arm_addr = NULL;
@@ -1750,11 +1705,9 @@ static int arm_unregister(struct file_in
         another_host = 0;
         /* another host with valid address-entry containing 
            same addressrange */
-        list_for_each(lh_1, &host_info_list) {
-                hi = list_entry(lh_1, struct host_info, list);
+        list_for_each_entry(hi, &host_info_list, list) {
                 if (hi->host != fi->host) {
-                        list_for_each(lh_2, &hi->file_info_list) {
-                                fi_hlp = list_entry(lh_2, struct file_info, list);
+                        list_for_each_entry(fi_hlp, &hi->file_info_list, list) {
                                 entry = fi_hlp->addr_list.next;
                                 while (entry != &(fi_hlp->addr_list)) {
                                         arm_addr = list_entry(entry, 
@@ -1822,9 +1775,9 @@ static int arm_get_buf(struct file_info 
 			if (req->req.address + req->req.length <= arm_addr->end) {
 				offset = req->req.address - arm_addr->start;
 
-				DBGMSG("arm_get_buf copy_to_user( %08X, %08X, %u )",
+				DBGMSG("arm_get_buf copy_to_user( %08X, %p, %u )",
 				       (u32) req->req.recvb,
-				       (u32) (arm_addr->addr_space_buffer+offset),
+				       arm_addr->addr_space_buffer+offset,
 				       (u32) req->req.length);
 
 				if (copy_to_user(int2ptr(req->req.recvb), arm_addr->addr_space_buffer+offset, req->req.length)) {
@@ -1833,7 +1786,10 @@ static int arm_get_buf(struct file_info 
 				}
 
 				spin_unlock_irqrestore(&host_info_lock, flags);
-				free_pending_request(req); /* we have to free the request, because we queue no response, and therefore nobody will free it */
+				/* We have to free the request, because we
+				 * queue no response, and therefore nobody
+				 * will free it. */
+				free_pending_request(req);
 				return sizeof(struct raw1394_request);
 			} else {
 				DBGMSG("arm_get_buf request exceeded mapping");
@@ -1873,8 +1829,8 @@ static int arm_set_buf(struct file_info 
 			if (req->req.address + req->req.length <= arm_addr->end) {
 				offset = req->req.address - arm_addr->start;
 
-				DBGMSG("arm_set_buf copy_from_user( %08X, %08X, %u )",
-				       (u32) (arm_addr->addr_space_buffer+offset),
+				DBGMSG("arm_set_buf copy_from_user( %p, %08X, %u )",
+				       arm_addr->addr_space_buffer+offset,
 				       (u32) req->req.sendb,
 				       (u32) req->req.length);
 
@@ -1941,22 +1897,22 @@ static int write_phypacket(struct file_i
 
 static int get_config_rom(struct file_info *fi, struct pending_request *req)
 {
-        size_t return_size;
-        unsigned char rom_version;
         int ret=sizeof(struct raw1394_request);
         quadlet_t *data = kmalloc(req->req.length, SLAB_KERNEL);
         int status;
+
         if (!data) return -ENOMEM;
-        status = hpsb_get_config_rom(fi->host, data, 
-                req->req.length, &return_size, &rom_version);
+
+	status = csr1212_read(fi->host->csr.rom, CSR1212_CONFIG_ROM_SPACE_OFFSET,
+			      data, req->req.length);
         if (copy_to_user(int2ptr(req->req.recvb), data, 
                 req->req.length))
                 ret = -EFAULT;
-        if (copy_to_user(int2ptr(req->req.tag), &return_size, 
-                sizeof(return_size)))
+	if (copy_to_user(int2ptr(req->req.tag), &fi->host->csr.rom->cache_head->len,
+			 sizeof(fi->host->csr.rom->cache_head->len)))
                 ret = -EFAULT;
-        if (copy_to_user(int2ptr(req->req.address), &rom_version, 
-                sizeof(rom_version)))
+	if (copy_to_user(int2ptr(req->req.address), &fi->host->csr.generation,
+			 sizeof(fi->host->csr.generation)))
                 ret = -EFAULT;
         if (copy_to_user(int2ptr(req->req.sendb), &status, 
                 sizeof(status)))
@@ -1987,10 +1943,122 @@ static int update_config_rom(struct file
         kfree(data);
         if (ret >= 0) {
                 free_pending_request(req); /* we have to free the request, because we queue no response, and therefore nobody will free it */
+		fi->cfgrom_upd = 1;
         }
         return ret;
 }
 
+static int modify_config_rom(struct file_info *fi, struct pending_request *req)
+{
+	struct csr1212_keyval *kv;
+	struct csr1212_csr_rom_cache *cache;
+	struct csr1212_dentry *dentry;
+	u32 dr;
+	int ret = 0;
+
+	if (req->req.misc == ~0) {
+		if (req->req.length == 0) return -EINVAL;
+
+		/* Find an unused slot */
+		for (dr = 0; dr < RAW1394_MAX_USER_CSR_DIRS && fi->csr1212_dirs[dr]; dr++);
+
+		if (dr == RAW1394_MAX_USER_CSR_DIRS) return -ENOMEM;
+
+		fi->csr1212_dirs[dr] = csr1212_new_directory(CSR1212_KV_ID_VENDOR);
+		if (!fi->csr1212_dirs[dr]) return -ENOMEM;
+	} else {
+		dr = req->req.misc;
+		if (!fi->csr1212_dirs[dr]) return -EINVAL;
+
+		/* Delete old stuff */
+		for (dentry = fi->csr1212_dirs[dr]->value.directory.dentries_head;
+		     dentry; dentry = dentry->next) {
+			csr1212_detach_keyval_from_directory(fi->host->csr.rom->root_kv,
+							     dentry->kv);
+		}
+
+		if (req->req.length == 0) {
+			csr1212_release_keyval(fi->csr1212_dirs[dr]);
+			fi->csr1212_dirs[dr] = NULL;
+
+			hpsb_update_config_rom_image(fi->host);
+			free_pending_request(req);
+			return sizeof(struct raw1394_request);
+		}
+	}
+
+	cache = csr1212_rom_cache_malloc(0, req->req.length);
+	if (!cache) {
+		csr1212_release_keyval(fi->csr1212_dirs[dr]);
+		fi->csr1212_dirs[dr] = NULL;
+		return -ENOMEM;
+	}
+
+	cache->filled_head = kmalloc(sizeof(struct csr1212_cache_region), GFP_KERNEL);
+	if (!cache->filled_head) {
+		csr1212_release_keyval(fi->csr1212_dirs[dr]);
+		fi->csr1212_dirs[dr] = NULL;
+		CSR1212_FREE(cache);
+		return -ENOMEM;
+	}
+	cache->filled_tail = cache->filled_head;
+
+	if (copy_from_user(cache->data, int2ptr(req->req.sendb),
+			   req->req.length)) {
+		csr1212_release_keyval(fi->csr1212_dirs[dr]);
+		fi->csr1212_dirs[dr] = NULL;
+		CSR1212_FREE(cache);
+		ret= -EFAULT;
+	} else {
+		cache->len = req->req.length;
+		cache->filled_head->offset_start = 0;
+		cache->filled_head->offset_end = cache->size -1;
+
+		cache->layout_head = cache->layout_tail = fi->csr1212_dirs[dr];
+
+		ret = CSR1212_SUCCESS;
+		/* parse all the items */
+		for (kv = cache->layout_head; ret == CSR1212_SUCCESS && kv;
+		     kv = kv->next) {
+			ret = csr1212_parse_keyval(kv, cache);
+		}
+
+		/* attach top level items to the root directory */
+		for (dentry = fi->csr1212_dirs[dr]->value.directory.dentries_head;
+		     ret == CSR1212_SUCCESS && dentry; dentry = dentry->next) {
+			ret = csr1212_attach_keyval_to_directory(fi->host->csr.rom->root_kv,
+								 dentry->kv);
+		}
+
+		if (ret == CSR1212_SUCCESS) {
+			ret = hpsb_update_config_rom_image(fi->host);
+
+			if (ret >= 0 && copy_to_user(int2ptr(req->req.recvb), 
+						    &dr, sizeof(dr))) {
+				ret = -ENOMEM;
+			}
+		}
+	}
+	kfree(cache->filled_head);
+	kfree(cache);
+
+	if (ret >= 0) {
+		/* we have to free the request, because we queue no response,
+		 * and therefore nobody will free it */		
+		free_pending_request(req);
+		return sizeof(struct raw1394_request);
+	} else {
+		for (dentry = fi->csr1212_dirs[dr]->value.directory.dentries_head;
+		     dentry; dentry = dentry->next) {
+			csr1212_detach_keyval_from_directory(fi->host->csr.rom->root_kv,
+							     dentry->kv);
+		}
+		csr1212_release_keyval(fi->csr1212_dirs[dr]);
+		fi->csr1212_dirs[dr] = NULL;
+		return ret;
+	}
+}
+
 static int state_connected(struct file_info *fi, struct pending_request *req)
 {
         int node = req->req.address >> 48;
@@ -2049,6 +2117,9 @@ static int state_connected(struct file_i
 
         case RAW1394_REQ_UPDATE_ROM:
                 return update_config_rom(fi, req);
+
+	case RAW1394_REQ_MODIFY_ROM:
+		return modify_config_rom(fi, req);
         }
 
         if (req->req.generation != get_hpsb_generation(fi->host)) {
@@ -2125,15 +2196,11 @@ static ssize_t raw1394_write(struct file
  * completion queue (reqlists_lock must be taken) */
 static inline int __rawiso_event_in_queue(struct file_info *fi)
 {
-	struct list_head *lh;
 	struct pending_request *req;
 
-	list_for_each(lh, &fi->req_complete) {
-		req = list_entry(lh, struct pending_request, list);
-		if (req->req.type == RAW1394_REQ_RAWISO_ACTIVITY) {
+	list_for_each_entry(req, &fi->req_complete, list)
+		if (req->req.type == RAW1394_REQ_RAWISO_ACTIVITY)
 			return 1;
-		}
-	}
 
 	return 0;
 }
@@ -2167,15 +2234,14 @@ static void queue_rawiso_event(struct fi
 static void rawiso_activity_cb(struct hpsb_iso *iso)
 {
 	unsigned long flags;
-        struct list_head *lh;
         struct host_info *hi;
+	struct file_info *fi;
 
         spin_lock_irqsave(&host_info_lock, flags);
         hi = find_host_info(iso->host);
 
 	if (hi != NULL) {
-		list_for_each(lh, &hi->file_info_list) {
-			struct file_info *fi = list_entry(lh, struct file_info, list);
+		list_for_each_entry(fi, &hi->file_info_list, list) {
 			if (fi->iso_handle == iso)
 				queue_rawiso_event(fi);
 		}
@@ -2495,11 +2561,11 @@ static int raw1394_release(struct inode 
         int retval = 0;
         struct list_head *entry;
         struct arm_addr  *addr = NULL;
-        struct list_head *lh_1, *lh_2;
         struct host_info *hi;
         struct file_info *fi_hlp = NULL;
         struct arm_addr  *arm_addr = NULL;
         int another_host;
+	int csr_mod = 0;
 
 	if (fi->iso_state != RAW1394_ISO_INACTIVE)
 		raw1394_iso_shutdown(fi);
@@ -2524,11 +2590,9 @@ static int raw1394_release(struct inode 
                 addr = list_entry(lh, struct arm_addr, addr_list);
                 /* another host with valid address-entry containing 
                    same addressrange? */
-                list_for_each(lh_1, &host_info_list) {
-                        hi = list_entry(lh_1, struct host_info, list);
+                list_for_each_entry(hi, &host_info_list, list) {
                         if (hi->host != fi->host) {
-                                list_for_each(lh_2, &hi->file_info_list) {
-                                        fi_hlp = list_entry(lh_2, struct file_info, list);
+                                list_for_each_entry(fi_hlp, &hi->file_info_list, list) {
                                         entry = fi_hlp->addr_list.next;
                                         while (entry != &(fi_hlp->addr_list)) {
                                                 arm_addr = list_entry(entry, 
@@ -2587,6 +2651,22 @@ static int raw1394_release(struct inode 
                 if (!done) down_interruptible(&fi->complete_sem);
         }
 
+	/* Remove any sub-trees left by user space programs */
+	for (i = 0; i < RAW1394_MAX_USER_CSR_DIRS; i++) {
+		struct csr1212_dentry *dentry;
+		if (!fi->csr1212_dirs[i]) continue;
+		for (dentry = fi->csr1212_dirs[i]->value.directory.dentries_head;
+		     dentry; dentry = dentry->next) {
+			csr1212_detach_keyval_from_directory(fi->host->csr.rom->root_kv, dentry->kv);
+		}
+		csr1212_release_keyval(fi->csr1212_dirs[i]);
+		fi->csr1212_dirs[i] = NULL;
+		csr_mod = 1;
+	}
+
+	if ((csr_mod || fi->cfgrom_upd) && hpsb_update_config_rom_image(fi->host) < 0)
+		HPSB_ERR("Failed to generate Configuration ROM image for host %d", fi->host->id);
+
         if (fi->state == connected) {
                 spin_lock_irq(&host_info_lock);
                 list_del(&fi->list);
--- diff/drivers/ieee1394/raw1394.h	2004-01-19 10:22:56.000000000 +0000
+++ source/drivers/ieee1394/raw1394.h	2004-02-23 13:56:41.000000000 +0000
@@ -27,6 +27,7 @@
 #define RAW1394_REQ_GET_ROM         203
 #define RAW1394_REQ_UPDATE_ROM      204
 #define RAW1394_REQ_ECHO            205
+#define RAW1394_REQ_MODIFY_ROM      206
 
 #define RAW1394_REQ_ARM_REGISTER    300
 #define RAW1394_REQ_ARM_UNREGISTER  301
--- diff/drivers/ieee1394/sbp2.c	2004-02-09 10:36:10.000000000 +0000
+++ source/drivers/ieee1394/sbp2.c	2004-02-23 13:56:41.000000000 +0000
@@ -67,6 +67,7 @@
 #include "../scsi/scsi.h"
 #include "../scsi/hosts.h"
 
+#include "csr1212.h"
 #include "ieee1394.h"
 #include "ieee1394_types.h"
 #include "ieee1394_core.h"
@@ -77,7 +78,7 @@
 #include "sbp2.h"
 
 static char version[] __devinitdata =
-	"$Rev: 1096 $ Ben Collins <bcollins@debian.org>";
+	"$Rev: 1144 $ Ben Collins <bcollins@debian.org>";
 
 /*
  * Module load parameter definitions
@@ -230,9 +231,17 @@ static Scsi_Host_Template scsi_driver_te
 
 const u8 sbp2_speedto_max_payload[] = { 0x7, 0x8, 0x9, 0xA, 0xB, 0xC };
 
+static void sbp2_remove_host(struct hpsb_host *host);
+static void sbp2_host_reset(struct hpsb_host *host);
+
+static int sbp2_probe(struct device *dev);
+static int sbp2_remove(struct device *dev);
+static int sbp2_update(struct unit_directory *ud);
+
 static struct hpsb_highlevel sbp2_highlevel = {
 	.name =		SBP2_DEVICE_NAME,
 	.remove_host =	sbp2_remove_host,
+	.host_reset =	sbp2_host_reset,
 };
 
 static struct hpsb_address_ops sbp2_ops = {
@@ -401,7 +410,7 @@ static int sbp2util_create_command_orb_p
 	unsigned long flags, orbs;
 	struct sbp2_command_info *command;
 
-	orbs = serialize_io ? 2 : SBP2_MAX_COMMAND_ORBS;
+	orbs = serialize_io ? 2 : SBP2_MAX_CMDS;
         
 	spin_lock_irqsave(&scsi_id->sbp2_command_orb_lock, flags);
 	for (i = 0; i < orbs; i++) {
@@ -468,14 +477,12 @@ static void sbp2util_remove_command_orb_
 static struct sbp2_command_info *sbp2util_find_command_for_orb(
 		struct scsi_id_instance_data *scsi_id, dma_addr_t orb)
 {
-	struct list_head *lh;
 	struct sbp2_command_info *command;
 	unsigned long flags;
 
 	spin_lock_irqsave(&scsi_id->sbp2_command_orb_lock, flags);
 	if (!list_empty(&scsi_id->sbp2_command_orb_inuse)) {
-		list_for_each(lh, &scsi_id->sbp2_command_orb_inuse) {
-			command = list_entry(lh, struct sbp2_command_info, list);
+		list_for_each_entry(command, &scsi_id->sbp2_command_orb_inuse, list) {
 			if (command->command_orb_dma == orb) {
 				spin_unlock_irqrestore(&scsi_id->sbp2_command_orb_lock, flags);
 				return (command);
@@ -495,14 +502,12 @@ static struct sbp2_command_info *sbp2uti
  */
 static struct sbp2_command_info *sbp2util_find_command_for_SCpnt(struct scsi_id_instance_data *scsi_id, void *SCpnt)
 {
-	struct list_head *lh;
 	struct sbp2_command_info *command;
 	unsigned long flags;
 
 	spin_lock_irqsave(&scsi_id->sbp2_command_orb_lock, flags);
 	if (!list_empty(&scsi_id->sbp2_command_orb_inuse)) {
-		list_for_each(lh, &scsi_id->sbp2_command_orb_inuse) {
-			command = list_entry(lh, struct sbp2_command_info, list);
+		list_for_each_entry(command, &scsi_id->sbp2_command_orb_inuse, list) {
 			if (command->Current_SCpnt == SCpnt) {
 				spin_unlock_irqrestore(&scsi_id->sbp2_command_orb_lock, flags);
 				return (command);
@@ -543,15 +548,17 @@ static struct sbp2_command_info *sbp2uti
 /* Free our DMA's */
 static void sbp2util_free_command_dma(struct sbp2_command_info *command)
 {
+	struct scsi_id_instance_data *scsi_id =
+		(struct scsi_id_instance_data *)command->Current_SCpnt->device->host->hostdata[0];
 	struct hpsb_host *host;
 
-	host = hpsb_get_host_bykey(&sbp2_highlevel,
-			(unsigned long)command->Current_SCpnt->device->host);
-	if (!host) {
-		printk(KERN_ERR "%s: host == NULL\n", __FUNCTION__);
+	if (!scsi_id) {
+		printk(KERN_ERR "%s: scsi_id == NULL\n", __FUNCTION__);
 		return;
 	}
 
+	host = scsi_id->ud->ne->host;
+
 	if (command->cmd_dma) {
 		if (command->dma_type == CMD_DMA_SINGLE) {
 			pci_unmap_single(host->pdev, command->cmd_dma,
@@ -593,13 +600,14 @@ static void sbp2util_mark_command_comple
 /*********************************************
  * IEEE-1394 core driver stack related section
  *********************************************/
+static struct scsi_id_instance_data *sbp2_alloc_device(struct unit_directory *ud);
 
 static int sbp2_probe(struct device *dev)
 {
 	struct unit_directory *ud;
-	struct sbp2scsi_host_info *hi;
+	struct scsi_id_instance_data *scsi_id;
 
-	SBP2_DEBUG(__FUNCTION__);
+	SBP2_DEBUG("sbp2_probe");
 
 	ud = container_of(dev, struct unit_directory, device);
 
@@ -608,207 +616,184 @@ static int sbp2_probe(struct device *dev
 	if (ud->flags & UNIT_DIRECTORY_HAS_LUN_DIRECTORY)
 		return -ENODEV;
 
-	/* This will only add it if it doesn't exist */
-	hi = sbp2_add_host(ud->ne->host);
+        scsi_id = sbp2_alloc_device(ud);
 
-	if (!hi)
-		return -ENODEV;
+        if (!scsi_id)
+                return -ENOMEM;
 
-	return sbp2_start_ud(hi, ud);
+        sbp2_parse_unit_directory(scsi_id, ud);
+
+        return sbp2_start_device(scsi_id);
 }
 
 static int sbp2_remove(struct device *dev)
 {
-	struct scsi_id_group *scsi_group;
-	struct list_head *lh, *next;
 	struct unit_directory *ud;
 	struct scsi_id_instance_data *scsi_id;
 
-	SBP2_DEBUG(__FUNCTION__);
+	SBP2_DEBUG("sbp2_remove");
 
 	ud = container_of(dev, struct unit_directory, device);
-	scsi_group = ud->device.driver_data;
-	ud->device.driver_data = NULL;
+	scsi_id = ud->device.driver_data;
 
-	list_for_each_safe (lh, next, &scsi_group->scsi_id_list) {
-		scsi_id = list_entry(lh, struct scsi_id_instance_data, list);
-
-		if (scsi_id != NULL) {
-			sbp2_logout_device(scsi_id);
- 			sbp2_remove_device(scsi_id);
-		}
-	}
-
-	kfree(scsi_group);
+	sbp2_logout_device(scsi_id);
+	sbp2_remove_device(scsi_id);
 
 	return 0;
 }
 
-static void sbp2_update(struct unit_directory *ud)
+static int sbp2_update(struct unit_directory *ud)
 {
-	struct sbp2scsi_host_info *hi;
-	struct scsi_id_group *scsi_group = ud->device.driver_data;
-	struct list_head *lh, *next;
-	struct scsi_id_instance_data *scsi_id;
-	unsigned long flags;
+	struct scsi_id_instance_data *scsi_id = ud->device.driver_data;
 
 	SBP2_DEBUG("sbp2_update");
 
-	list_for_each_safe (lh, next, &scsi_group->scsi_id_list) {
-		scsi_id = list_entry(lh, struct scsi_id_instance_data, list);
-
-		hi = scsi_id->hi;
-
-		if (sbp2_reconnect_device(scsi_id)) {
+	if (sbp2_reconnect_device(scsi_id)) {
 		
-			/* 
-			 * Ok, reconnect has failed. Perhaps we didn't
-			 * reconnect fast enough. Try doing a regular login.
-			 */
-			if (sbp2_login_device(scsi_id)) {
-				/* Login failed too, just remove the device. */
-				SBP2_ERR("sbp2_reconnect_device failed!");
-				sbp2_remove_device(scsi_id);
-				return;
-			}
+		/* 
+		 * Ok, reconnect has failed. Perhaps we didn't
+		 * reconnect fast enough. Try doing a regular login, but
+		 * first do a logout just in case of any weirdness.
+		 */
+		sbp2_logout_device(scsi_id);
+
+		if (sbp2_login_device(scsi_id)) {
+			/* Login failed too, just fail, and the backend
+			 * will call our sbp2_remove for us */
+			SBP2_INFO("sbp2_reconnect_device failed!");
+			return -EBUSY;
 		}
+	}
 
-		/* Set max retries to something large on the device. */
-		sbp2_set_busy_timeout(scsi_id);
+	/* Set max retries to something large on the device. */
+	sbp2_set_busy_timeout(scsi_id);
 
-		/* Do a SBP-2 fetch agent reset. */
-		sbp2_agent_reset(scsi_id, 1);
-	
-		/* Get the max speed and packet size that we can use. */
-		sbp2_max_speed_and_size(scsi_id);
+	/* Do a SBP-2 fetch agent reset. */
+	sbp2_agent_reset(scsi_id, 1);
 
-		/* Complete any pending commands with busy (so they get
-		 * retried) and remove them from our queue
-		 */
-		spin_lock_irqsave(&hi->sbp2_command_lock, flags);
-		sbp2scsi_complete_all_commands(scsi_id, DID_BUS_BUSY);
-		spin_unlock_irqrestore(&hi->sbp2_command_lock, flags);
-	}
+	/* Get the max speed and packet size that we can use. */
+	sbp2_max_speed_and_size(scsi_id);
+
+	/* Complete any pending commands with busy (so they get
+	 * retried) and remove them from our queue
+	 */
+	sbp2scsi_complete_all_commands(scsi_id, DID_BUS_BUSY);
+
+	return 0;
 }
 
-/* This functions is called by the sbp2_probe, for each new device. If the
- * host_info already exists, it will return it. If not, it allocated a new
- * host_info entry and a corresponding scsi_host. */
-static struct sbp2scsi_host_info *sbp2_add_host(struct hpsb_host *host)
+/* This functions is called by the sbp2_probe, for each new device. We now
+ * allocate one scsi host for each scsi_id (unit directory). */
+static struct scsi_id_instance_data *sbp2_alloc_device(struct unit_directory *ud)
 {
 	struct sbp2scsi_host_info *hi;
-	struct Scsi_Host *scsi_host;
+	struct Scsi_Host *scsi_host = NULL;
+	struct scsi_id_instance_data *scsi_id = NULL;
 
-	SBP2_DEBUG("sbp2_add_host");
+	SBP2_DEBUG("sbp2_alloc_device");
 
-	hi = hpsb_get_hostinfo(&sbp2_highlevel, host);
-	if (hi)
-		return hi;
-
-	/* Register our host with the SCSI stack. */
-	scsi_host = scsi_host_alloc(&scsi_driver_template, 0);
-	if (!scsi_host) {
-		SBP2_ERR("failed to register scsi host");
-		return NULL;
+	scsi_id = kmalloc(sizeof(*scsi_id), GFP_KERNEL);
+	if (!scsi_id) {
+		SBP2_ERR("failed to create scsi_id");
+		goto failed_alloc;
 	}
+	memset(scsi_id, 0, sizeof(*scsi_id));
+
+	scsi_id->ne = ud->ne;
+	scsi_id->ud = ud;
+	scsi_id->speed_code = IEEE1394_SPEED_100;
+	scsi_id->max_payload_size = sbp2_speedto_max_payload[IEEE1394_SPEED_100];
+	atomic_set(&scsi_id->sbp2_login_complete, 0);
+	INIT_LIST_HEAD(&scsi_id->sbp2_command_orb_inuse);
+	INIT_LIST_HEAD(&scsi_id->sbp2_command_orb_completed);
+	INIT_LIST_HEAD(&scsi_id->scsi_list);
+	scsi_id->sbp2_command_orb_lock = SPIN_LOCK_UNLOCKED;
+	scsi_id->sbp2_device_type_and_lun = SBP2_DEVICE_TYPE_LUN_UNINITIALIZED;
 
-	/* Register our sbp2 status address space... */
-	hpsb_register_addrspace(&sbp2_highlevel, host, &sbp2_ops,
-				SBP2_STATUS_FIFO_ADDRESS,
-				SBP2_STATUS_FIFO_ADDRESS +
-				SBP2_STATUS_FIFO_ENTRY_TO_OFFSET(SBP2SCSI_MAX_SCSI_IDS+1));
+	ud->device.driver_data = scsi_id;
 
-	/* Handle data movement if physical dma is not enabled/supported
-	 * on host controller */
+	hi = hpsb_get_hostinfo(&sbp2_highlevel, ud->ne->host);
+	if (!hi) {
+		hi = hpsb_create_hostinfo(&sbp2_highlevel, ud->ne->host, sizeof(*hi));
+		if (!hi) {
+			SBP2_ERR("failed to allocate hostinfo");
+			goto failed_alloc;
+		}
+		SBP2_DEBUG("sbp2_alloc_device: allocated hostinfo");
+		hi->host = ud->ne->host;
+		INIT_LIST_HEAD(&hi->scsi_ids);
+
+		/* Register our sbp2 status address space... */
+		hpsb_register_addrspace(&sbp2_highlevel, ud->ne->host, &sbp2_ops,
+					SBP2_STATUS_FIFO_ADDRESS,
+					SBP2_STATUS_FIFO_ADDRESS +
+					SBP2_STATUS_FIFO_ENTRY_TO_OFFSET(SBP2_MAX_UDS_PER_NODE+1));
 #ifdef CONFIG_IEEE1394_SBP2_PHYS_DMA
-	hpsb_register_addrspace(&sbp2_highlevel, host, &sbp2_physdma_ops, 0x0ULL, 0xfffffffcULL);
+		/* Handle data movement if physical dma is not
+		 * enabled/supportedon host controller */
+		hpsb_register_addrspace(&sbp2_highlevel, ud->ne->host, &sbp2_physdma_ops,
+					0x0ULL, 0xfffffffcULL);
 #endif
-
-	hi = hpsb_create_hostinfo(&sbp2_highlevel, host, sizeof(*hi));
-	if (!hi) {
-		SBP2_ERR("failed to allocate hostinfo");
-		scsi_host_put(hi->scsi_host);
 	}
 
-	hpsb_set_hostinfo_key(&sbp2_highlevel, host, (unsigned long)scsi_host);
+	scsi_id->hi = hi;
 
-	hi->scsi_host = scsi_host;
-	hi->host = host;
-	hi->sbp2_command_lock = SPIN_LOCK_UNLOCKED;
-	hi->scsi_host->max_id = SBP2SCSI_MAX_SCSI_IDS;
+	list_add_tail(&scsi_id->scsi_list, &hi->scsi_ids);
 
-	/* XXX We need a device to pass here as the scsi-host class. Can't
-	 * use the PCI device, since it is already bound to the ieee1394
-	 * host. Can't use the fw-host device since it is multi-class
-	 * enabled (scsi-host uses classdata member of the device). */
-	if (scsi_add_host(hi->scsi_host, NULL)) {
-		SBP2_ERR("failed to add scsi host");
-		scsi_host_put(hi->scsi_host);
-		hpsb_destroy_hostinfo(&sbp2_highlevel, host);
-		return NULL;
+	/* Register our host with the SCSI stack. */
+	scsi_host = scsi_host_alloc(&scsi_driver_template, 0);
+	if (!scsi_host) {
+		SBP2_ERR("failed to register scsi host");
+		goto failed_alloc;
 	}
 
-	return hi;
+	scsi_host->hostdata[0] = (unsigned long)scsi_id;
+
+	if (!scsi_add_host(scsi_host, &ud->device)) {
+		scsi_id->scsi_host = scsi_host;
+		return scsi_id;
+	}
+
+	SBP2_ERR("failed to add scsi host");
+	scsi_host_put(scsi_host);
+
+failed_alloc:
+	sbp2_remove_device(scsi_id);
+	return NULL;
 }
 
 
-/*
- * This function is called when a host is removed.
- */
-static void sbp2_remove_host(struct hpsb_host *host)
+static void sbp2_host_reset(struct hpsb_host *host)
 {
 	struct sbp2scsi_host_info *hi;
-
-	SBP2_DEBUG("sbp2_remove_host");
+	struct scsi_id_instance_data *scsi_id;
 
 	hi = hpsb_get_hostinfo(&sbp2_highlevel, host);
 
 	if (hi) {
-		scsi_remove_host(hi->scsi_host);
-		scsi_host_put(hi->scsi_host);
+		list_for_each_entry(scsi_id, &hi->scsi_ids, scsi_list)
+			scsi_block_requests(scsi_id->scsi_host);
 	}
 }
 
-static int sbp2_start_ud(struct sbp2scsi_host_info *hi, struct unit_directory *ud)
+
+static void sbp2_remove_host(struct hpsb_host *host)
 {
-	struct scsi_id_instance_data *scsi_id;
-	struct scsi_id_group *scsi_group;
-	struct list_head *lh, *next;
+	struct sbp2scsi_host_info *hi;
 
-	SBP2_DEBUG("sbp2_start_ud");
+	SBP2_DEBUG("sbp2_remove_host");
 
-	scsi_group = kmalloc(sizeof(*scsi_group), GFP_KERNEL);
-	if (!scsi_group) {
-		SBP2_ERR ("Could not allocate memory for scsi_group");
-		return -ENOMEM;
-	}
+	hi = hpsb_get_hostinfo(&sbp2_highlevel, host);
 
-	INIT_LIST_HEAD(&scsi_group->scsi_id_list);
-	ud->device.driver_data = scsi_group;
-	sbp2_parse_unit_directory(scsi_group, ud);
-
-	list_for_each_safe (lh, next, &scsi_group->scsi_id_list) {
-		scsi_id = list_entry(lh, struct scsi_id_instance_data, list);
-
-		scsi_id->ne = ud->ne;
-		scsi_id->hi = hi;
-		scsi_id->speed_code = IEEE1394_SPEED_100;
-		scsi_id->max_payload_size = sbp2_speedto_max_payload[IEEE1394_SPEED_100];
-		atomic_set(&scsi_id->sbp2_login_complete, 0);
-		INIT_LIST_HEAD(&scsi_id->sbp2_command_orb_inuse);
-		INIT_LIST_HEAD(&scsi_id->sbp2_command_orb_completed);
-		scsi_id->sbp2_command_orb_lock = SPIN_LOCK_UNLOCKED;
-
-		sbp2_start_device(scsi_id);
-	}
-
-	/* Check to see if any of our devices survived the ordeal */
-	if (list_empty(&scsi_group->scsi_id_list)) {
-		kfree(scsi_group);
-		return -ENODEV;
-	}
+	if (hi) {
+		struct scsi_id_instance_data *scsi_id;
 
-	return 0;
+		list_for_each_entry(scsi_id, &hi->scsi_ids, scsi_list) {
+			down_write(&scsi_id->ud->device.bus->subsys.rwsem);
+			device_release_driver(&scsi_id->ud->device);
+			up_write(&scsi_id->ud->device.bus->subsys.rwsem);
+		}
+	}
 }
 
 
@@ -820,7 +805,6 @@ static int sbp2_start_device(struct scsi
 {
 	struct sbp2scsi_host_info *hi = scsi_id->hi;
 	struct scsi_device *sdev;
-	int i;
 
 	SBP2_DEBUG("sbp2_start_device");
 
@@ -912,7 +896,7 @@ alloc_fail:
 
 		kfree(scsi_id);
 
-		list_del(&scsi_id->list);
+		list_del(&scsi_id->scsi_list);
 
 		SBP2_ERR ("Could not allocate memory for scsi_id");
 
@@ -920,17 +904,7 @@ alloc_fail:
 	}
 	SBP2_DMA_ALLOC("consistent DMA region for login ORB");
 
-	/*
-	 * Find an empty spot to stick our scsi id instance data. 
-	 */
-	for (i = 0; i < hi->scsi_host->max_id; i++) {
-		if (!hi->scsi_id[i]) {
-			hi->scsi_id[i] = scsi_id;
-			scsi_id->id = i;
-			SBP2_DEBUG("New SBP-2 device inserted, SCSI ID = %x", (unsigned int) i);
-			break;
-		}
-	}
+	SBP2_DEBUG("New SBP-2 device inserted, SCSI ID = %x", scsi_id->ud->id);
 
 	/*
 	 * Create our command orb pool
@@ -941,15 +915,6 @@ alloc_fail:
 		return -ENOMEM;
 	}
 
-	/*
-	 * Make sure we are not out of space
-	 */
-	if (i == hi->scsi_host->max_id) {
-		SBP2_ERR("No slots left for SBP-2 device");
-		sbp2_remove_device(scsi_id);
-		return -EBUSY;
-	}
-
 	/* Schedule a timeout here. The reason is that we may be so close
 	 * to a bus reset, that the device is not available for logins.
 	 * This can happen when the bus reset is caused by the host
@@ -985,15 +950,12 @@ alloc_fail:
 	sbp2_max_speed_and_size(scsi_id);
 
 	/* Add this device to the scsi layer now */
-	sdev = scsi_add_device(hi->scsi_host, 0, scsi_id->id, 0);
+	sdev = scsi_add_device(scsi_id->scsi_host, 0, scsi_id->ud->id, 0);
 	if (IS_ERR(sdev)) {
 		SBP2_ERR("scsi_add_device failed");
 		return PTR_ERR(sdev);
 	}
 
-	sdev->hostdata = scsi_id;
-	scsi_id->sdev = sdev;
-
 	return 0;
 }
 
@@ -1002,22 +964,24 @@ alloc_fail:
  */
 static void sbp2_remove_device(struct scsi_id_instance_data *scsi_id)
 {
-	struct sbp2scsi_host_info *hi = scsi_id->hi;
+	struct sbp2scsi_host_info *hi;
 
 	SBP2_DEBUG("sbp2_remove_device");
 
-	/* Complete any pending commands with selection timeout */
-	sbp2scsi_complete_all_commands(scsi_id, DID_NO_CONNECT);
+	if (!scsi_id)
+		return;
 
-	/* Remove it from the scsi layer now */
-	if (scsi_id->sdev) {
-		scsi_remove_device(scsi_id->sdev);
-		scsi_device_put(scsi_id->sdev);
+	hi = scsi_id->hi;
+
+	/* This will remove our scsi device aswell */
+	if (scsi_id->scsi_host) {
+		scsi_remove_host(scsi_id->scsi_host);
+		scsi_host_put(scsi_id->scsi_host);
 	}
 
 	sbp2util_remove_command_orb_pool(scsi_id);
 
-	hi->scsi_id[scsi_id->id] = NULL;
+	list_del(&scsi_id->scsi_list);
 
 	if (scsi_id->login_response) {
 		pci_free_consistent(hi->host->pdev,
@@ -1067,9 +1031,9 @@ static void sbp2_remove_device(struct sc
 		SBP2_DMA_FREE("single query logins data");
 	}
 
-	SBP2_DEBUG("SBP-2 device removed, SCSI ID = %d", scsi_id->id);
+	scsi_id->ud->device.driver_data = NULL;
 
-	list_del(&scsi_id->list);
+	SBP2_DEBUG("SBP-2 device removed, SCSI ID = %d", scsi_id->ud->id);
 
 	kfree(scsi_id);
 }
@@ -1157,7 +1121,7 @@ static int sbp2_query_logins(struct scsi
 	SBP2_DEBUG("sbp2_query_logins: reserved_resp_length initialized");
 
 	scsi_id->query_logins_orb->status_FIFO_lo = SBP2_STATUS_FIFO_ADDRESS_LO +
-						    SBP2_STATUS_FIFO_ENTRY_TO_OFFSET(scsi_id->id);
+						    SBP2_STATUS_FIFO_ENTRY_TO_OFFSET(scsi_id->ud->id);
 	scsi_id->query_logins_orb->status_FIFO_hi = (ORB_SET_NODE_ID(hi->host->node_id) |
 						     SBP2_STATUS_FIFO_ADDRESS_HI);
 	SBP2_DEBUG("sbp2_query_logins: status FIFO initialized");
@@ -1185,12 +1149,12 @@ static int sbp2_query_logins(struct scsi
 	SBP2_DEBUG("sbp2_query_logins: written");
 
 	if (sbp2util_down_timeout(&scsi_id->sbp2_login_complete, 2*HZ)) {
-		SBP2_ERR("Error querying logins to SBP-2 device - timed out");
+		SBP2_INFO("Error querying logins to SBP-2 device - timed out");
 		return(-EIO);
 	}
 
 	if (scsi_id->status_block.ORB_offset_lo != scsi_id->query_logins_orb_dma) {
-		SBP2_ERR("Error querying logins to SBP-2 device - timed out");
+		SBP2_INFO("Error querying logins to SBP-2 device - timed out");
 		return(-EIO);
 	}
 
@@ -1198,7 +1162,7 @@ static int sbp2_query_logins(struct scsi
 	    STATUS_GET_DEAD_BIT(scsi_id->status_block.ORB_offset_hi_misc) ||
 	    STATUS_GET_SBP_STATUS(scsi_id->status_block.ORB_offset_hi_misc)) {
 
-		SBP2_ERR("Error querying logins to SBP-2 device - timed out");
+		SBP2_INFO("Error querying logins to SBP-2 device - timed out");
 		return(-EIO);
 	}
 
@@ -1207,13 +1171,13 @@ static int sbp2_query_logins(struct scsi
 	SBP2_DEBUG("length_max_logins = %x",
 		   (unsigned int)scsi_id->query_logins_response->length_max_logins);
 
-	SBP2_INFO("Query logins to SBP-2 device successful");
+	SBP2_DEBUG("Query logins to SBP-2 device successful");
 
 	max_logins = RESPONSE_GET_MAX_LOGINS(scsi_id->query_logins_response->length_max_logins);
-	SBP2_INFO("Maximum concurrent logins supported: %d", max_logins);
+	SBP2_DEBUG("Maximum concurrent logins supported: %d", max_logins);
                                                                                 
 	active_logins = RESPONSE_GET_ACTIVE_LOGINS(scsi_id->query_logins_response->length_max_logins);
-	SBP2_INFO("Number of active logins: %d", active_logins);
+	SBP2_DEBUG("Number of active logins: %d", active_logins);
                                                                                 
 	if (active_logins >= max_logins) {
 		return(-EIO);
@@ -1240,7 +1204,7 @@ static int sbp2_login_device(struct scsi
 
 	if (!exclusive_login) {
 		if (sbp2_query_logins(scsi_id)) {
-			SBP2_ERR("Device does not support any more concurrent logins");
+			SBP2_INFO("Device does not support any more concurrent logins");
 			return(-EIO);
 		}
 	}
@@ -1271,7 +1235,7 @@ static int sbp2_login_device(struct scsi
 	SBP2_DEBUG("sbp2_login_device: passwd_resp_lengths initialized");
 
 	scsi_id->login_orb->status_FIFO_lo = SBP2_STATUS_FIFO_ADDRESS_LO + 
-					     SBP2_STATUS_FIFO_ENTRY_TO_OFFSET(scsi_id->id);
+					     SBP2_STATUS_FIFO_ENTRY_TO_OFFSET(scsi_id->ud->id);
 	scsi_id->login_orb->status_FIFO_hi = (ORB_SET_NODE_ID(hi->host->node_id) |
 					      SBP2_STATUS_FIFO_ADDRESS_HI);
 	SBP2_DEBUG("sbp2_login_device: status FIFO initialized");
@@ -1387,7 +1351,7 @@ static int sbp2_logout_device(struct scs
 
 	scsi_id->logout_orb->reserved5 = 0x0;
 	scsi_id->logout_orb->status_FIFO_lo = SBP2_STATUS_FIFO_ADDRESS_LO + 
-					      SBP2_STATUS_FIFO_ENTRY_TO_OFFSET(scsi_id->id);
+					      SBP2_STATUS_FIFO_ENTRY_TO_OFFSET(scsi_id->ud->id);
 	scsi_id->logout_orb->status_FIFO_hi = (ORB_SET_NODE_ID(hi->host->node_id) |
 					       SBP2_STATUS_FIFO_ADDRESS_HI);
 
@@ -1447,7 +1411,7 @@ static int sbp2_reconnect_device(struct 
 
 	scsi_id->reconnect_orb->reserved5 = 0x0;
 	scsi_id->reconnect_orb->status_FIFO_lo = SBP2_STATUS_FIFO_ADDRESS_LO + 
-						 SBP2_STATUS_FIFO_ENTRY_TO_OFFSET(scsi_id->id);
+						 SBP2_STATUS_FIFO_ENTRY_TO_OFFSET(scsi_id->ud->id);
 	scsi_id->reconnect_orb->status_FIFO_hi =
 		(ORB_SET_NODE_ID(hi->host->node_id) | SBP2_STATUS_FIFO_ADDRESS_HI);
 
@@ -1530,16 +1494,17 @@ static int sbp2_set_busy_timeout(struct 
 	return(0);
 }
 
+
 /*
  * This function is called to parse sbp2 device's config rom unit
  * directory. Used to determine things like sbp2 management agent offset,
  * and command set used (SCSI or RBC). 
  */
-static void sbp2_parse_unit_directory(struct scsi_id_group *scsi_group,
+static void sbp2_parse_unit_directory(struct scsi_id_instance_data *scsi_id,
 				      struct unit_directory *ud)
 {
-	struct scsi_id_instance_data *scsi_id;
-	struct list_head *lh;
+	struct csr1212_keyval *kv;
+	struct csr1212_dentry *dentry;
 	u64 management_agent_addr;
 	u32 command_set_spec_id, command_set, unit_characteristics,
 		firmware_revision, workarounds;
@@ -1554,29 +1519,31 @@ static void sbp2_parse_unit_directory(st
 	firmware_revision = 0x0;
 
 	/* Handle different fields in the unit directory, based on keys */
-	for (i = 0; i < ud->length; i++) {
-		switch (CONFIG_ROM_KEY(ud->quadlets[i])) {
-		case SBP2_CSR_OFFSET_KEY:
-			/* Save off the management agent address */
-			management_agent_addr =
-				CSR_REGISTER_BASE + 
-				(CONFIG_ROM_VALUE(ud->quadlets[i]) << 2);
-
-			SBP2_DEBUG("sbp2_management_agent_addr = %x",
-				   (unsigned int) management_agent_addr);
+	csr1212_for_each_dir_entry(ud->ne->csr, kv, ud->ud_kv, dentry) {
+		switch (kv->key.id) {
+		case CSR1212_KV_ID_DEPENDENT_INFO:
+			if (kv->key.type == CSR1212_KV_TYPE_CSR_OFFSET) {
+				/* Save off the management agent address */
+				management_agent_addr =
+					CSR1212_REGISTER_SPACE_BASE +
+					(kv->value.csr_offset << 2);
+
+				SBP2_DEBUG("sbp2_management_agent_addr = %x",
+					   (unsigned int) management_agent_addr);
+			} else
+				scsi_id->sbp2_device_type_and_lun = kv->value.immediate;
 			break;
 
 		case SBP2_COMMAND_SET_SPEC_ID_KEY:
 			/* Command spec organization */
-			command_set_spec_id
-				= CONFIG_ROM_VALUE(ud->quadlets[i]);
+			command_set_spec_id = kv->value.immediate;
 			SBP2_DEBUG("sbp2_command_set_spec_id = %x",
 				   (unsigned int) command_set_spec_id);
 			break;
 
 		case SBP2_COMMAND_SET_KEY:
 			/* Command set used by sbp2 device */
-			command_set = CONFIG_ROM_VALUE(ud->quadlets[i]);
+			command_set = kv->value.immediate;
 			SBP2_DEBUG("sbp2_command_set = %x",
 				   (unsigned int) command_set);
 			break;
@@ -1586,35 +1553,14 @@ static void sbp2_parse_unit_directory(st
 			 * Unit characterisitcs (orb related stuff
 			 * that I'm not yet paying attention to)
 			 */
-			unit_characteristics
-				= CONFIG_ROM_VALUE(ud->quadlets[i]);
+			unit_characteristics = kv->value.immediate;
 			SBP2_DEBUG("sbp2_unit_characteristics = %x",
 				   (unsigned int) unit_characteristics);
 			break;
 
-		case SBP2_DEVICE_TYPE_AND_LUN_KEY:
-			/*
-			 * Device type and lun (used for
-			 * detemining type of sbp2 device)
-			 */
-			scsi_id = kmalloc(sizeof(*scsi_id), GFP_KERNEL);
-			if (!scsi_id) {
-				SBP2_ERR("Out of memory adding scsi_id, not all LUN's will be added");
-				break;
-			}
-			memset(scsi_id, 0, sizeof(*scsi_id));
-
-			scsi_id->sbp2_device_type_and_lun
-				= CONFIG_ROM_VALUE(ud->quadlets[i]);
-			SBP2_DEBUG("sbp2_device_type_and_lun = %x",
-				   (unsigned int) scsi_id->sbp2_device_type_and_lun);
-			list_add_tail(&scsi_id->list, &scsi_group->scsi_id_list);
-			break;
-
 		case SBP2_FIRMWARE_REVISION_KEY:
 			/* Firmware revision */
-			firmware_revision
-				= CONFIG_ROM_VALUE(ud->quadlets[i]);
+			firmware_revision = kv->value.immediate;
 			if (force_inquiry_hack)
 				SBP2_INFO("sbp2_firmware_revision = %x",
 				   (unsigned int) firmware_revision);
@@ -1664,37 +1610,18 @@ static void sbp2_parse_unit_directory(st
 	}
 
 	/* If this is a logical unit directory entry, process the parent
-	 * to get the common values. */
+	 * to get the values. */
 	if (ud->flags & UNIT_DIRECTORY_LUN_DIRECTORY) {
 		struct unit_directory *parent_ud =
 			container_of(ud->device.parent, struct unit_directory, device);
-		sbp2_parse_unit_directory(scsi_group, parent_ud);
+		sbp2_parse_unit_directory(scsi_id, parent_ud);
 	} else {
-		/* If our list is empty, add a base scsi_id (happens in a normal
-		 * case where there is no logical_unit_number entry */
-		if (list_empty(&scsi_group->scsi_id_list)) {
-			scsi_id = kmalloc(sizeof(*scsi_id), GFP_KERNEL);
-			if (!scsi_id) {
-				SBP2_ERR("Out of memory adding scsi_id");
-				return;
-			}
-			memset(scsi_id, 0, sizeof(*scsi_id));
-
-			scsi_id->sbp2_device_type_and_lun = SBP2_DEVICE_TYPE_LUN_UNINITIALIZED;
-			list_add_tail(&scsi_id->list, &scsi_group->scsi_id_list);
-		}
-
-		/* Update the generic fields in all the LUN's */
-		list_for_each (lh, &scsi_group->scsi_id_list) {
-			scsi_id = list_entry(lh, struct scsi_id_instance_data, list);
-
-			scsi_id->sbp2_management_agent_addr = management_agent_addr;
-			scsi_id->sbp2_command_set_spec_id = command_set_spec_id;
-			scsi_id->sbp2_command_set = command_set;
-			scsi_id->sbp2_unit_characteristics = unit_characteristics;
-			scsi_id->sbp2_firmware_revision = firmware_revision;
-			scsi_id->workarounds = workarounds;
-		}
+		scsi_id->sbp2_management_agent_addr = management_agent_addr;
+		scsi_id->sbp2_command_set_spec_id = command_set_spec_id;
+		scsi_id->sbp2_command_set = command_set;
+		scsi_id->sbp2_unit_characteristics = unit_characteristics;
+		scsi_id->sbp2_firmware_revision = firmware_revision;
+		scsi_id->workarounds = workarounds;
 	}
 }
 
@@ -1727,7 +1654,7 @@ static int sbp2_max_speed_and_size(struc
 	/* Payload size is the lesser of what our speed supports and what
 	 * our host supports.  */
 	scsi_id->max_payload_size = min(sbp2_speedto_max_payload[scsi_id->speed_code],
-					(u8)(((be32_to_cpu(hi->host->csr.rom[2]) >> 12) & 0xf) - 1));
+					(u8)(hi->host->csr.max_rec - 1));
 
 	SBP2_ERR("Node " NODE_BUS_FMT ": Max speed [%s] - Max payload [%u]",
 		 NODE_BUS_ARGS(hi->host, scsi_id->ne->nodeid),
@@ -2392,10 +2319,9 @@ static void sbp2_check_sbp2_response(str
 static int sbp2_handle_status_write(struct hpsb_host *host, int nodeid, int destid,
 				    quadlet_t *data, u64 addr, size_t length, u16 fl)
 {
-	struct sbp2scsi_host_info *hi = NULL;
-	struct scsi_id_instance_data *scsi_id = NULL;
+	struct sbp2scsi_host_info *hi;
+	struct scsi_id_instance_data *scsi_id = NULL, *scsi_id_tmp;
 	u32 id;
-	unsigned long flags;
 	Scsi_Cmnd *SCpnt = NULL;
 	u32 scsi_status = SBP2_SCSI_STATUS_GOOD;
 	struct sbp2_command_info *command;
@@ -2416,18 +2342,20 @@ static int sbp2_handle_status_write(stru
 		return(RCODE_ADDRESS_ERROR);
 	}
 
-	spin_lock_irqsave(&hi->sbp2_command_lock, flags);
-
 	/*
 	 * Find our scsi_id structure by looking at the status fifo address written to by
 	 * the sbp2 device.
 	 */
-	id = SBP2_STATUS_FIFO_OFFSET_TO_ENTRY((u32)(addr - SBP2_STATUS_FIFO_ADDRESS)); 
-	scsi_id = hi->scsi_id[id];
+	id = SBP2_STATUS_FIFO_OFFSET_TO_ENTRY((u32)(addr - SBP2_STATUS_FIFO_ADDRESS));
+	list_for_each_entry(scsi_id_tmp, &hi->scsi_ids, scsi_list) {
+		if (scsi_id_tmp->ne->nodeid == nodeid && scsi_id_tmp->ud->id == id) {
+			scsi_id = scsi_id_tmp;
+			break;
+		}
+	}
 
 	if (!scsi_id) {
 		SBP2_ERR("scsi_id is NULL - device is gone?");
-		spin_unlock_irqrestore(&hi->sbp2_command_lock, flags);
 		return(RCODE_ADDRESS_ERROR);
 	}
 
@@ -2515,18 +2443,9 @@ static int sbp2_handle_status_write(stru
 		}
 	}
 
-	spin_unlock_irqrestore(&hi->sbp2_command_lock, flags);
-
-
 	if (SCpnt) {
 
-		/*
-		 * Complete the SCSI command.
-		 *
-		 * Only do it after we've released the sbp2_command_lock,
-		 * as it might otherwise deadlock with the 
-		 * io_request_lock (in sbp2scsi_queuecommand).
-		 */
+		/* Complete the SCSI command. */
 		SBP2_DEBUG("Completing SCSI command");
 		sbp2scsi_complete_command(scsi_id, scsi_status, SCpnt,
 					  command->Current_done);
@@ -2547,31 +2466,26 @@ static int sbp2_handle_status_write(stru
  */
 static int sbp2scsi_queuecommand (Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *)) 
 {
-	struct sbp2scsi_host_info *hi = NULL;
-	struct scsi_id_instance_data *scsi_id = NULL;
-	unsigned long flags;
+	struct scsi_id_instance_data *scsi_id =
+		(struct scsi_id_instance_data *)SCpnt->device->host->hostdata[0];
+	struct sbp2scsi_host_info *hi;
 
 	SBP2_DEBUG("sbp2scsi_queuecommand");
 
 	/*
-	 * Pull our host info and scsi id instance data from the scsi command
+	 * If scsi_id is null, it means there is no device in this slot,
+	 * so we should return selection timeout.
 	 */
-	hi = hpsb_get_hostinfo_bykey(&sbp2_highlevel, (unsigned long)SCpnt->device->host);
-
-	if (!hi) {
-		SBP2_ERR("sbp2scsi_host_info is NULL - this is bad!");
+	if (!scsi_id) {
 		SCpnt->result = DID_NO_CONNECT << 16;
 		done (SCpnt);
-		return(0);
+		return 0;
 	}
 
-	scsi_id = hi->scsi_id[SCpnt->device->id];
+	hi = scsi_id->hi;
 
-	/*
-	 * If scsi_id is null, it means there is no device in this slot,
-	 * so we should return selection timeout.
-	 */
-	if (!scsi_id) {
+	if (!hi) {
+		SBP2_ERR("sbp2scsi_host_info is NULL - this is bad!");
 		SCpnt->result = DID_NO_CONNECT << 16;
 		done (SCpnt);
 		return(0);
@@ -2612,13 +2526,11 @@ static int sbp2scsi_queuecommand (Scsi_C
 	/*
 	 * Try and send our SCSI command
 	 */
-	spin_lock_irqsave(&hi->sbp2_command_lock, flags);
 	if (sbp2_send_command(scsi_id, SCpnt, done)) {
 		SBP2_ERR("Error sending SCSI command");
 		sbp2scsi_complete_command(scsi_id, SBP2_SCSI_STATUS_SELECTION_TIMEOUT,
 					  SCpnt, done);
 	}
-	spin_unlock_irqrestore(&hi->sbp2_command_lock, flags);
 
 	return(0);
 }
@@ -2634,7 +2546,7 @@ static void sbp2scsi_complete_all_comman
 	struct list_head *lh;
 	struct sbp2_command_info *command;
 
-	SBP2_DEBUG("sbp2_complete_all_commands");
+	SBP2_DEBUG("sbp2scsi_complete_all_commands");
 
 	while (!list_empty(&scsi_id->sbp2_command_orb_inuse)) {
 		SBP2_DEBUG("Found pending command to complete");
@@ -2654,6 +2566,8 @@ static void sbp2scsi_complete_all_comman
 		}
 	}
 
+	scsi_unblock_requests(scsi_id->scsi_host);
+
 	return;
 }
 
@@ -2766,24 +2680,32 @@ static void sbp2scsi_complete_command(st
 	/*
 	 * Tell scsi stack that we're done with this command
 	 */
-	spin_lock_irqsave(scsi_id->hi->scsi_host->host_lock,flags);
+	spin_lock_irqsave(scsi_id->scsi_host->host_lock,flags);
 	done (SCpnt);
-	spin_unlock_irqrestore(scsi_id->hi->scsi_host->host_lock,flags);
+	spin_unlock_irqrestore(scsi_id->scsi_host->host_lock,flags);
 
 	return;
 }
 
+
+static int sbp2scsi_slave_configure (struct scsi_device *sdev)
+{
+	blk_queue_dma_alignment(sdev->request_queue, (512 - 1));
+
+	return 0;
+}
+
+
 /*
  * Called by scsi stack when something has really gone wrong.  Usually
  * called when a command has timed-out for some reason.
  */
 static int sbp2scsi_abort (Scsi_Cmnd *SCpnt) 
 {
-	struct sbp2scsi_host_info *hi = hpsb_get_hostinfo_bykey(&sbp2_highlevel,
-								(unsigned long)SCpnt->device->host);
-	struct scsi_id_instance_data *scsi_id = hi->scsi_id[SCpnt->device->id];
+	struct scsi_id_instance_data *scsi_id =
+		(struct scsi_id_instance_data *)SCpnt->device->host->hostdata[0];
+	struct sbp2scsi_host_info *hi = scsi_id->hi;
 	struct sbp2_command_info *command;
-	unsigned long flags;
 
 	SBP2_ERR("aborting sbp2 command");
 	print_command (SCpnt->cmnd);
@@ -2794,7 +2716,6 @@ static int sbp2scsi_abort (Scsi_Cmnd *SC
 		 * Right now, just return any matching command structures
 		 * to the free pool.
 		 */
-		spin_lock_irqsave(&hi->sbp2_command_lock, flags);
 		command = sbp2util_find_command_for_SCpnt(scsi_id, SCpnt);
 		if (command) {
 			SBP2_DEBUG("Found command to abort");
@@ -2819,7 +2740,6 @@ static int sbp2scsi_abort (Scsi_Cmnd *SC
 		 */
 		sbp2_agent_reset(scsi_id, 0);
 		sbp2scsi_complete_all_commands(scsi_id, DID_BUS_BUSY);		
-		spin_unlock_irqrestore(&hi->sbp2_command_lock, flags);
 	}
 
 	return(SUCCESS);
@@ -2830,9 +2750,8 @@ static int sbp2scsi_abort (Scsi_Cmnd *SC
  */
 static int sbp2scsi_reset (Scsi_Cmnd *SCpnt) 
 {
-	struct sbp2scsi_host_info *hi = hpsb_get_hostinfo_bykey(&sbp2_highlevel,
-								(unsigned long)SCpnt->device->host);
-	struct scsi_id_instance_data *scsi_id = hi->scsi_id[SCpnt->device->id];
+	struct scsi_id_instance_data *scsi_id =
+		(struct scsi_id_instance_data *)SCpnt->device->host->hostdata[0];
 
 	SBP2_ERR("reset requested");
 
@@ -2849,24 +2768,30 @@ static const char *sbp2scsi_info (struct
         return "SCSI emulation for IEEE-1394 SBP-2 Devices";
 }
 
-static ssize_t sbp2_sysfs_ieee1394_guid_show(struct device *dev, char *buf)
+static ssize_t sbp2_sysfs_ieee1394_id_show(struct device *dev, char *buf)
 {
 	struct scsi_device *sdev;
 	struct scsi_id_instance_data *scsi_id;
+	int lun;
 
 	if (!(sdev = to_scsi_device(dev)))
 		return 0;
 
-	if (!(scsi_id = sdev->hostdata))
+	if (!(scsi_id = (struct scsi_id_instance_data *)sdev->host->hostdata[0]))
 		return 0;
 
-	return sprintf(buf, "%016Lx\n", (unsigned long long)scsi_id->ne->guid);
-}
+	if (scsi_id->sbp2_device_type_and_lun == SBP2_DEVICE_TYPE_LUN_UNINITIALIZED)
+		lun = 0;
+	else
+		lun = ORB_SET_LUN(scsi_id->sbp2_device_type_and_lun);
 
-static DEVICE_ATTR(ieee1394_guid, S_IRUGO, sbp2_sysfs_ieee1394_guid_show, NULL);
+	return sprintf(buf, "%016Lx:%d:%d\n", (unsigned long long)scsi_id->ne->guid,
+		       scsi_id->ud->id, lun);
+}
+static DEVICE_ATTR(ieee1394_id, S_IRUGO, sbp2_sysfs_ieee1394_id_show, NULL);
 
 static struct device_attribute *sbp2_sysfs_sdev_attrs[] = {
-	&dev_attr_ieee1394_guid,
+	&dev_attr_ieee1394_id,
 	NULL
 };
 
@@ -2886,11 +2811,12 @@ static Scsi_Host_Template scsi_driver_te
 	.eh_device_reset_handler =	sbp2scsi_reset,
 	.eh_bus_reset_handler =		sbp2scsi_reset,
 	.eh_host_reset_handler =	sbp2scsi_reset,
+	.slave_configure =		sbp2scsi_slave_configure,
 	.this_id =			-1,
 	.sg_tablesize =			SG_ALL,
 	.use_clustering =		ENABLE_CLUSTERING,
-	.cmd_per_lun =			SBP2_MAX_CMDS_PER_LUN,
-	.can_queue = 			SBP2_MAX_SCSI_QUEUE,
+	.cmd_per_lun =			SBP2_MAX_CMDS,
+	.can_queue = 			SBP2_MAX_CMDS,
 	.emulated =			1,
 	.sdev_attrs =			sbp2_sysfs_sdev_attrs,
 };
--- diff/drivers/ieee1394/sbp2.h	2004-02-09 10:36:10.000000000 +0000
+++ source/drivers/ieee1394/sbp2.h	2004-02-23 13:56:41.000000000 +0000
@@ -195,20 +195,22 @@ struct sbp2_status_block {
  * Miscellaneous SBP2 related config rom defines
  */
 
-/* 
- * The status fifo address definition below is used as a status base, with a chunk
- * separately assigned for each sbp2 device detected. For example, 0xfffe00000000ULL 
- * is used for the first sbp2 device detected, 0xfffe00000020ULL for the next sbp2 
- * device, and so on.
+/* The status fifo address definition below is used as a base for each
+ * node, which a chunk seperately assigned to each unit directory in the
+ * node.  For example, 0xfffe00000000ULL is used for the first sbp2 device
+ * detected on node 0, 0xfffe00000020ULL for the next sbp2 device on node
+ * 0, and so on.
  *
- * Note: We could use a single status fifo address for all sbp2 devices, and figure 
- * out which sbp2 device the status belongs to by looking at the source node id of
- * the status write... but, using separate addresses for each sbp2 device allows for
- * better code and the ability to support multiple luns within a single 1394 node.
+ * Note: We could use a single status fifo address for all sbp2 devices,
+ * and figure out which sbp2 device the status belongs to by looking at
+ * the source node id of the status write... but, using separate addresses
+ * for each sbp2 unit directory allows for better code and the ability to
+ * support multiple luns within a single 1394 node.
  *
- * Also note that we choose the address range below as it is a region specified for
- * write posting, where the ohci controller will automatically send an ack_complete
- * when the status is written by the sbp2 device... saving a split transaction.   =)
+ * Also note that we choose the address range below as it is a region
+ * specified for write posting, where the ohci controller will
+ * automatically send an ack_complete when the status is written by the
+ * sbp2 device... saving a split transaction.   =)
  */ 
 #define SBP2_STATUS_FIFO_ADDRESS				0xfffe00000000ULL
 #define SBP2_STATUS_FIFO_ADDRESS_HI                             0xfffe
@@ -261,7 +263,7 @@ struct sbp2_status_block {
  */
 
 #define SBP2_MAX_SG_ELEMENT_LENGTH	0xf000
-#define SBP2SCSI_MAX_SCSI_IDS		32	/* Max sbp2 device instances supported */
+#define SBP2_MAX_UDS_PER_NODE		16	/* Maximum scsi devices per node */
 #define SBP2_MAX_SECTORS		255	/* Max sectors supported */
 
 #ifndef TYPE_SDAD
@@ -304,11 +306,8 @@ static unchar sbp2scsi_direction_table[0
 	DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN
 };
 
-/* This should be safe. If there's more than one LUN per node, we could
- * saturate the tlabel's though.  */
-#define SBP2_MAX_CMDS_PER_LUN   8
-#define SBP2_MAX_SCSI_QUEUE	(SBP2_MAX_CMDS_PER_LUN * SBP2SCSI_MAX_SCSI_IDS)
-#define SBP2_MAX_COMMAND_ORBS	SBP2_MAX_SCSI_QUEUE
+/* This should be safe */
+#define SBP2_MAX_CMDS		8
 
 /* This is the two dma types we use for cmd_dma below */
 enum cmd_dma_types {
@@ -351,9 +350,6 @@ struct sbp2scsi_host_info;
  * Information needed on a per scsi id basis (one for each sbp2 device)
  */
 struct scsi_id_instance_data {
-	/* SCSI ID */
-	int id;
-
 	/*
 	 * Various sbp2 specific structures
 	 */
@@ -402,50 +398,28 @@ struct scsi_id_instance_data {
 	struct list_head sbp2_command_orb_inuse;
 	struct list_head sbp2_command_orb_completed;
 
-	struct list_head list;
+	struct list_head scsi_list;
 
 	/* Node entry, as retrieved from NodeMgr entries */
 	struct node_entry *ne;
+	struct unit_directory *ud;
 
 	/* A backlink to our host_info */
 	struct sbp2scsi_host_info *hi;
 
-	/* The scsi_device associated with this scsi_id */
+	/* SCSI related pointers */
 	struct scsi_device *sdev;
+	struct Scsi_Host *scsi_host;
 
 	/* Device specific workarounds/brokeness */
 	u32 workarounds;
 };
 
 
-/* Describes a per-ud scsi_id group */
-struct scsi_id_group {
-	struct list_head scsi_id_list;
-};
-
-
-/*
- * Sbp2 host data structure (one per sbp2 host)
- */
+/* Sbp2 host data structure (one per IEEE1394 host) */
 struct sbp2scsi_host_info {
-	struct hpsb_host *host;
-
-	/*
-	 * Spin locks for command processing
-	 */
-	spinlock_t sbp2_command_lock;
-
-	/*
-	 * This is the scsi host we register with the scsi mid level.
-	 * We keep a reference to it here, so we can unregister it
-	 * when the hpsb_host is removed.
-	 */
-	struct Scsi_Host *scsi_host;
-
-	/*
-	 * SCSI ID instance data (one for each sbp2 device instance possible)
-	 */
-	struct scsi_id_instance_data *scsi_id[SBP2SCSI_MAX_SCSI_IDS];
+	struct hpsb_host *host;		/* IEEE1394 host */
+	struct list_head scsi_ids;	/* List of scsi ids on this host */
 };
 
 /*
@@ -465,18 +439,7 @@ static struct sbp2_command_info *sbp2uti
 static void sbp2util_mark_command_completed(struct scsi_id_instance_data *scsi_id,
 		struct sbp2_command_info *command);
 
-/*
- * IEEE-1394 core driver related prototypes
- */
-static struct sbp2scsi_host_info *sbp2_add_host(struct hpsb_host *host);
-static void sbp2_remove_host(struct hpsb_host *host);
-
-static int sbp2_probe(struct device *dev);
-static int sbp2_remove(struct device *dev);
-static void sbp2_update(struct unit_directory *ud);
 
-static int sbp2_start_ud(struct sbp2scsi_host_info *hi,
-			 struct unit_directory *ud);
 static int sbp2_start_device(struct scsi_id_instance_data *scsi_id);
 static void sbp2_remove_device(struct scsi_id_instance_data *scsi_id);
 
@@ -511,7 +474,7 @@ static int sbp2_send_command(struct scsi
 static unsigned int sbp2_status_to_sense_data(unchar *sbp2_status, unchar *sense_data);
 static void sbp2_check_sbp2_command(struct scsi_id_instance_data *scsi_id, unchar *cmd);
 static void sbp2_check_sbp2_response(struct scsi_id_instance_data *scsi_id, Scsi_Cmnd *SCpnt);
-static void sbp2_parse_unit_directory(struct scsi_id_group *scsi_group,
+static void sbp2_parse_unit_directory(struct scsi_id_instance_data *scsi_id,
 				      struct unit_directory *ud);
 static int sbp2_set_busy_timeout(struct scsi_id_instance_data *scsi_id);
 static int sbp2_max_speed_and_size(struct scsi_id_instance_data *scsi_id);
--- diff/drivers/ieee1394/video1394.c	2004-02-18 08:54:09.000000000 +0000
+++ source/drivers/ieee1394/video1394.c	2004-02-23 13:56:41.000000000 +0000
@@ -476,11 +476,9 @@ static void initialize_dma_ir_ctx(struct
 static struct dma_iso_ctx *
 find_ctx(struct list_head *list, int type, int channel)
 {
-	struct list_head *lh;
+	struct dma_iso_ctx *ctx;
 
-	list_for_each(lh, list) {
-		struct dma_iso_ctx *ctx;
-		ctx = list_entry(lh, struct dma_iso_ctx, link);
+	list_for_each_entry(ctx, list, link) {
 		if (ctx->type == type && ctx->channel == channel)
 			return ctx;
 	}
--- diff/drivers/input/gameport/ns558.c	2003-08-26 10:00:52.000000000 +0100
+++ source/drivers/input/gameport/ns558.c	2004-02-23 13:56:41.000000000 +0000
@@ -77,7 +77,7 @@ static void ns558_isa_probe(int io)
  * No one should be using this address.
  */
 
-	if (check_region(io, 1))
+	if (!request_region(io, 1, "ns558-isa"))
 		return;
 
 /*
@@ -89,7 +89,8 @@ static void ns558_isa_probe(int io)
 	outb(~c & ~3, io);
 	if (~(u = v = inb(io)) & 3) {
 		outb(c, io);
-		return;
+		i = 0;
+		goto out;
 	}
 /*
  * After a trigger, there must be at least some bits changing.
@@ -99,7 +100,8 @@ static void ns558_isa_probe(int io)
 
 	if (u == v) {
 		outb(c, io);
-		return;
+		i = 0;
+		goto out;
 	}
 	wait_ms(3);
 /*
@@ -110,7 +112,8 @@ static void ns558_isa_probe(int io)
 	for (i = 0; i < 1000; i++)
 		if ((u ^ inb(io)) & 0xf) {
 			outb(c, io);
-			return;
+			i = 0;
+			goto out;
 		}
 /* 
  * And now find the number of mirrors of the port.
@@ -118,7 +121,9 @@ static void ns558_isa_probe(int io)
 
 	for (i = 1; i < 5; i++) {
 
-		if (check_region(io & (-1 << i), (1 << i)))	/* Don't disturb anyone */
+		release_region(io & (-1 << (i-1)), (1 << (i-1)));
+
+		if (!request_region(io & (-1 << i), (1 << i), "ns558-isa"))	/* Don't disturb anyone */
 			break;
 
 		outb(0xff, io & (-1 << i));
@@ -126,18 +131,25 @@ static void ns558_isa_probe(int io)
 			if (inb(io & (-1 << i)) != inb((io & (-1 << i)) + (1 << i) - 1)) b++;
 		wait_ms(3);
 
-		if (b > 300)					/* We allow 30% difference */
+		if (b > 300) {					/* We allow 30% difference */
+			release_region(io & (-1 << i), (1 << i));
 			break;
+		}
 	}
 
 	i--;
 
+	if (i != 4) {
+		if (!request_region(io & (-1 << i), (1 << i), "ns558-isa"))
+			return;
+	}
+
 	if (!(port = kmalloc(sizeof(struct ns558), GFP_KERNEL))) {
 		printk(KERN_ERR "ns558: Memory allocation failed.\n");
-		return;
+		goto out;
 	}
-       	memset(port, 0, sizeof(struct ns558));
-	
+	memset(port, 0, sizeof(struct ns558));
+
 	port->type = NS558_ISA;
 	port->size = (1 << i);
 	port->gameport.io = io;
@@ -148,8 +160,6 @@ static void ns558_isa_probe(int io)
 	sprintf(port->phys, "isa%04x/gameport0", io & (-1 << i));
 	sprintf(port->name, "NS558 ISA");
 
-	request_region(io & (-1 << i), (1 << i), "ns558-isa");
-
 	gameport_register_port(&port->gameport);
 
 	printk(KERN_INFO "gameport: NS558 ISA at %#x", port->gameport.io);
@@ -157,6 +167,9 @@ static void ns558_isa_probe(int io)
 	printk(" speed %d kHz\n", port->gameport.speed);
 
 	list_add(&port->node, &ns558_list);
+	return;
+out:
+	release_region(io & (-1 << i), (1 << i));
 }
 
 #ifdef CONFIG_PNP
--- diff/drivers/input/keyboard/Kconfig	2003-10-09 09:47:34.000000000 +0100
+++ source/drivers/input/keyboard/Kconfig	2004-02-23 13:56:41.000000000 +0000
@@ -17,6 +17,7 @@ config KEYBOARD_ATKBD
 	depends on INPUT && INPUT_KEYBOARD
 	select SERIO
 	select SERIO_I8042 if PC
+	select SERIO_GSCPS2 if GSC
 	help
 	  Say Y here if you want to use a standard AT or PS/2 keyboard. Usually
 	  you'll need this, unless you have a different type keyboard (USB, ADB
--- diff/drivers/input/keyboard/atkbd.c	2004-02-09 10:36:10.000000000 +0000
+++ source/drivers/input/keyboard/atkbd.c	2004-02-23 13:56:41.000000000 +0000
@@ -37,14 +37,13 @@ MODULE_LICENSE("GPL");
 
 static int atkbd_set = 2;
 module_param_named(set, atkbd_set, int, 0);
-MODULE_PARM_DESC(set, "Select keyboard code set (2 = default, 3, 4)");
+MODULE_PARM_DESC(set, "Select keyboard code set (2 = default, 3 = PS/2 native)");
+
 #if defined(__i386__) || defined(__x86_64__) || defined(__hppa__)
 static int atkbd_reset;
 #else
 static int atkbd_reset = 1;
 #endif
-static int atkbd_softrepeat;
-
 module_param_named(reset, atkbd_reset, bool, 0);
 MODULE_PARM_DESC(reset, "Reset keyboard during initialization");
 
@@ -52,6 +51,14 @@ static int atkbd_softrepeat;
 module_param_named(softrepeat, atkbd_softrepeat, bool, 0);
 MODULE_PARM_DESC(softrepeat, "Use software keyboard repeat");
 
+static int atkbd_scroll;
+module_param_named(scroll, atkbd_scroll, bool, 0);
+MODULE_PARM_DESC(scroll, "Enable scroll-wheel on MS Office and similar keyboards");
+
+static int atkbd_extra;
+module_param_named(extra, atkbd_extra, bool, 0);
+MODULE_PARM_DESC(extra, "Enable extra LEDs and keys on IBM RapidAcces, EzKey and similar keyboards");
+
 /*
  * Scancode to keycode tables. These are just the default setting, and
  * are loadable via an userland utility.
@@ -127,11 +134,11 @@ static unsigned char atkbd_unxlate_table
 #define ATKBD_CMD_EX_SETLEDS	0x20eb
 #define ATKBD_CMD_OK_GETID	0x02e8
 
+
 #define ATKBD_RET_ACK		0xfa
 #define ATKBD_RET_NAK		0xfe
 #define ATKBD_RET_BAT		0xaa
 #define ATKBD_RET_EMUL0		0xe0
-#define ATKBD_RET_EMULX		0x80
 #define ATKBD_RET_EMUL1		0xe1
 #define ATKBD_RET_RELEASE	0xf0
 #define ATKBD_RET_HANGUEL	0xf1
@@ -141,6 +148,22 @@ static unsigned char atkbd_unxlate_table
 #define ATKBD_KEY_UNKNOWN	  0
 #define ATKBD_KEY_NULL		255
 
+#define ATKBD_SCR_1		254
+#define ATKBD_SCR_2		253
+#define ATKBD_SCR_4		252
+#define ATKBD_SCR_8		251
+#define ATKBD_SCR_CLICK		250
+
+#define ATKBD_SPECIAL		250
+
+static unsigned char atkbd_scroll_keys[5][2] = {
+	{ ATKBD_SCR_1,     0x45 },
+	{ ATKBD_SCR_2,     0x29 },
+	{ ATKBD_SCR_4,     0x36 },
+	{ ATKBD_SCR_8,     0x27 },
+	{ ATKBD_SCR_CLICK, 0x60 },
+};
+
 /*
  * The atkbd control structure
  */
@@ -155,6 +178,7 @@ struct atkbd {
 	unsigned char cmdbuf[4];
 	unsigned char cmdcnt;
 	unsigned char set;
+	unsigned char extra;
 	unsigned char release;
 	int lastkey;
 	volatile signed char ack;
@@ -189,6 +213,7 @@ static irqreturn_t atkbd_interrupt(struc
 {
 	struct atkbd *atkbd = serio->private;
 	unsigned int code = data;
+	int scroll = 0, click = -1;
 	int value;
 
 #ifdef ATKBD_DEBUG
@@ -284,6 +309,21 @@ static irqreturn_t atkbd_interrupt(struc
 			else
 				printk(KERN_WARNING "atkbd.c: Use 'setkeycodes %s%02x <keycode>' to make it known.\n",						code & 0x80 ? "e0" : "", code & 0x7f);
 			break;
+		case ATKBD_SCR_1:
+			scroll = 1 - atkbd->release * 2;
+			break;
+		case ATKBD_SCR_2:
+			scroll = 2 - atkbd->release * 4;
+			break;
+		case ATKBD_SCR_4:
+			scroll = 4 - atkbd->release * 8;
+			break;
+		case ATKBD_SCR_8:
+			scroll = 8 - atkbd->release * 16;
+			break;
+		case ATKBD_SCR_CLICK:
+			click = !atkbd->release;
+			break;
 		default:
 			value = atkbd->release ? 0 :
 				(1 + (!atkbd_softrepeat && test_bit(atkbd->keycode[code], atkbd->dev.key)));
@@ -305,6 +345,13 @@ static irqreturn_t atkbd_interrupt(struc
 			atkbd_report_key(&atkbd->dev, regs, atkbd->keycode[code], value);
 	}
 
+	if (scroll || click != -1) {
+		input_regs(&atkbd->dev, regs);
+		input_report_key(&atkbd->dev, BTN_MIDDLE, click);
+		input_report_rel(&atkbd->dev, REL_WHEEL, scroll);
+		input_sync(&atkbd->dev);
+	}
+
 	atkbd->release = 0;
 out:
 	return IRQ_HANDLED;
@@ -420,7 +467,7 @@ static int atkbd_event(struct input_dev 
 			         | (test_bit(LED_CAPSL,   dev->led) ? 4 : 0);
 		        atkbd_command(atkbd, param, ATKBD_CMD_SETLEDS);
 
-			if (atkbd->set == 4) {
+			if (atkbd->extra) {
 				param[0] = 0;
 				param[1] = (test_bit(LED_COMPOSE, dev->led) ? 0x01 : 0)
 					 | (test_bit(LED_SLEEP,   dev->led) ? 0x02 : 0)
@@ -529,21 +576,22 @@ static int atkbd_set_3(struct atkbd *atk
 		return 3;
 	}
 
-	if (atkbd_set != 2) 
-		if (!atkbd_command(atkbd, param, ATKBD_CMD_OK_GETID)) {
-			atkbd->id = param[0] << 8 | param[1];
+	if (atkbd_extra) {
+		param[0] = 0x71;
+		if (!atkbd_command(atkbd, param, ATKBD_CMD_EX_ENABLE)) {
+			atkbd->extra = 1;
 			return 2;
 		}
-
-	if (atkbd_set == 4) {
-		param[0] = 0x71;
-		if (!atkbd_command(atkbd, param, ATKBD_CMD_EX_ENABLE))
-			return 4;
 	}
 
 	if (atkbd_set != 3) 
 		return 2;
 
+	if (!atkbd_command(atkbd, param, ATKBD_CMD_OK_GETID)) {
+		atkbd->id = param[0] << 8 | param[1];
+		return 2;
+	}
+
 	param[0] = 3;
 	if (atkbd_command(atkbd, param, ATKBD_CMD_SSCANSET))
 		return 2;
@@ -696,24 +744,32 @@ static void atkbd_connect(struct serio *
 		atkbd->id = 0xab00;
 	}
 
-	if (atkbd->set == 4) {
+	if (atkbd->extra) {
 		atkbd->dev.ledbit[0] |= BIT(LED_COMPOSE) | BIT(LED_SUSPEND) | BIT(LED_SLEEP) | BIT(LED_MUTE) | BIT(LED_MISC);
-		sprintf(atkbd->name, "AT Set 2 Extended keyboard");
+		sprintf(atkbd->name, "AT Set 2 Extra keyboard");
 	} else
 		sprintf(atkbd->name, "AT %s Set %d keyboard",
 			atkbd->translated ? "Translated" : "Raw", atkbd->set);
 
 	sprintf(atkbd->phys, "%s/input0", serio->phys);
 
+	if (atkbd_scroll) {
+		for (i = 0; i < 5; i++)
+			atkbd_set2_keycode[atkbd_scroll_keys[i][1]] = atkbd_scroll_keys[i][0];
+		atkbd->dev.evbit[0] |= BIT(EV_REL);
+		atkbd->dev.relbit[0] = BIT(REL_WHEEL);
+		set_bit(BTN_MIDDLE, atkbd->dev.keybit);
+	}
+
 	if (atkbd->translated) {
 		for (i = 0; i < 128; i++) {
 			atkbd->keycode[i] = atkbd_set2_keycode[atkbd_unxlate_table[i]];
 			atkbd->keycode[i | 0x80] = atkbd_set2_keycode[atkbd_unxlate_table[i] | 0x80];
 		}
-	} else if (atkbd->set == 2) {
-		memcpy(atkbd->keycode, atkbd_set2_keycode, sizeof(atkbd->keycode));
-	} else {
+	} else if (atkbd->set == 3) {
 		memcpy(atkbd->keycode, atkbd_set3_keycode, sizeof(atkbd->keycode));
+	} else {
+		memcpy(atkbd->keycode, atkbd_set2_keycode, sizeof(atkbd->keycode));
 	}
 
 	atkbd->dev.name = atkbd->name;
@@ -724,7 +780,7 @@ static void atkbd_connect(struct serio *
 	atkbd->dev.id.version = atkbd->id;
 
 	for (i = 0; i < 512; i++)
-		if (atkbd->keycode[i] && atkbd->keycode[i] < 255)
+		if (atkbd->keycode[i] && atkbd->keycode[i] < ATKBD_SPECIAL)
 			set_bit(atkbd->keycode[i], atkbd->dev.keybit);
 
 	input_register_device(&atkbd->dev);
@@ -741,46 +797,20 @@ static int atkbd_reconnect(struct serio 
 {
 	struct atkbd *atkbd = serio->private;
 	struct serio_dev *dev = serio->dev;
-	int i;
 
-        if (!dev) {
-                printk(KERN_DEBUG "atkbd: reconnect request, but serio is disconnected, ignoring...\n");
-                return -1;
-        }
+	if (!dev) {
+		printk(KERN_DEBUG "atkbd: reconnect request, but serio is disconnected, ignoring...\n");
+		return -1;
+	}
 
 	if (atkbd->write) {
 		if (atkbd_probe(atkbd))
 			return -1;
-
-		atkbd->set = atkbd_set_3(atkbd);
+		if (atkbd->set != atkbd_set_3(atkbd))
+			return -1;
 		atkbd_enable(atkbd);
-	} else {
-		atkbd->set = 2;
-		atkbd->id = 0xab00;
-	}
-
-	/*
-	 * Here we probably should check if the keyboard has the same set that
-         * it had before and bail out if it's different. But this will most likely
-         * cause new keyboard device be created... and for the user it will look
-         * like keyboard is lost
-	 */
-
-	if (atkbd->translated) {
-		for (i = 0; i < 128; i++) {
-			atkbd->keycode[i] = atkbd_set2_keycode[atkbd_unxlate_table[i]];
-			atkbd->keycode[i | 0x80] = atkbd_set2_keycode[atkbd_unxlate_table[i] | 0x80];
-		}
-	} else if (atkbd->set == 2) {
-		memcpy(atkbd->keycode, atkbd_set2_keycode, sizeof(atkbd->keycode));
-	} else {
-		memcpy(atkbd->keycode, atkbd_set3_keycode, sizeof(atkbd->keycode));
 	}
 
-	for (i = 0; i < 512; i++)
-		if (atkbd->keycode[i] && atkbd->keycode[i] < 255)
-			set_bit(atkbd->keycode[i], atkbd->dev.keybit);
-
 	return 0;
 }
 
--- diff/drivers/input/keyboard/hpps2atkbd.h	2004-02-09 10:36:10.000000000 +0000
+++ source/drivers/input/keyboard/hpps2atkbd.h	2004-02-23 13:56:41.000000000 +0000
@@ -4,14 +4,9 @@
  * Copyright (c) 2004 Helge Deller <deller@gmx.de>
  * Copyright (c) 2002 Laurent Canet <canetl@esiee.fr>
  * Copyright (c) 2002 Thibaut Varene <varenet@esiee.fr>
+ * Copyright (c) 2000 Xavier Debacker <debackex@esiee.fr>
  *
- * based on linux-2.4's hp_mouse.c & hp_keyb.c
- * 	Copyright (c) 1999 Alex deVries <adevries@thepuffingroup.com>
- *	Copyright (c) 1999-2000 Philipp Rumpf <prumpf@tux.org>
- *	Copyright (c) 2000 Xavier Debacker <debackex@esiee.fr>
- *	Copyright (c) 2000-2001 Thomas Marteau <marteaut@esiee.fr>
- *
- * HP PS/2 AT-compatible Keyboard, found in PA/RISC Workstations
+ * HP PS/2 AT-compatible Keyboard, found in PA/RISC Workstations & Laptops
  *
  * This file is subject to the terms and conditions of the GNU General Public
  * License.  See the file "COPYING" in the main directory of this archive
@@ -19,87 +14,100 @@
  */
 
 
-#define KBD_UNKNOWN 0
-
-/* Raw SET 2 scancode table */
+/* undefine if you have a RDI PRECISIONBOOK */
+#define STANDARD_KEYBOARD
 
-#if 0
-	/* conflicting keys between a RDI Precisionbook keyboard and a normal HP keyboard */
-        keytable[0x07] = KEY_F1;        /* KEY_F12      */
-        keytable[0x11] = KEY_LEFTCTRL;  /* KEY_LEFTALT  */
-        keytable[0x14] = KEY_CAPSLOCK;  /* KEY_LEFTCTRL */
-        keytable[0x61] = KEY_LEFT;      /* KEY_102ND    */
+#if defined(STANDARD_KEYBOARD)
+# define CONFLICT(x,y) x
+#else
+# define CONFLICT(x,y) y
 #endif
 
+/* sadly RDI (Tadpole) decided to ship a different keyboard layout
+   than HP for their PS/2 laptop keyboard which leads to conflicting
+   keycodes between a normal HP PS/2 keyboard and a RDI Precisionbook.
+                                HP:		RDI:            */
+#define C_07	CONFLICT(	KEY_F12,	KEY_F1		)
+#define C_11	CONFLICT(	KEY_LEFTALT,	KEY_LEFTCTRL	)
+#define C_14	CONFLICT(	KEY_LEFTCTRL,	KEY_CAPSLOCK	)
+#define C_58	CONFLICT(	KEY_CAPSLOCK,	KEY_RIGHTCTRL	)
+#define C_61	CONFLICT(	KEY_102ND,	KEY_LEFT	)
 
-static unsigned char atkbd_set2_keycode[512] = {
+/* Raw SET 2 scancode table */
 
-	/* 00 */  KBD_UNKNOWN,  KEY_F9,        KBD_UNKNOWN,   KEY_F5,        KEY_F3,        KEY_F1,       KEY_F2,        KEY_F1,
-	/* 08 */  KEY_ESC,      KEY_F10,       KEY_F8,        KEY_F6,        KEY_F4,        KEY_TAB,      KEY_GRAVE,     KEY_F2,
-	/* 10 */  KBD_UNKNOWN,  KEY_LEFTCTRL,  KEY_LEFTSHIFT, KBD_UNKNOWN,   KEY_CAPSLOCK,  KEY_Q,        KEY_1,         KEY_F3,
-	/* 18 */  KBD_UNKNOWN,  KEY_LEFTALT,   KEY_Z,         KEY_S,         KEY_A,         KEY_W,        KEY_2,         KEY_F4,
-	/* 20 */  KBD_UNKNOWN,  KEY_C,         KEY_X,         KEY_D,         KEY_E,         KEY_4,        KEY_3,         KEY_F5,
-	/* 28 */  KBD_UNKNOWN,  KEY_SPACE,     KEY_V,         KEY_F,         KEY_T,         KEY_R,        KEY_5,         KEY_F6,
-	/* 30 */  KBD_UNKNOWN,  KEY_N,         KEY_B,         KEY_H,         KEY_G,         KEY_Y,        KEY_6,         KEY_F7,
-	/* 38 */  KBD_UNKNOWN,  KEY_RIGHTALT,  KEY_M,         KEY_J,         KEY_U,         KEY_7,        KEY_8,         KEY_F8,
-	/* 40 */  KBD_UNKNOWN,  KEY_COMMA,     KEY_K,         KEY_I,         KEY_O,         KEY_0,        KEY_9,         KEY_F9,
-	/* 48 */  KBD_UNKNOWN,  KEY_DOT,       KEY_SLASH,     KEY_L,         KEY_SEMICOLON, KEY_P,        KEY_MINUS,     KEY_F10,
-	/* 50 */  KBD_UNKNOWN,  KBD_UNKNOWN,   KEY_APOSTROPHE,KBD_UNKNOWN,   KEY_LEFTBRACE, KEY_EQUAL,    KEY_F11,       KEY_SYSRQ,
-	/* 58 */  KEY_CAPSLOCK, KEY_RIGHTSHIFT,KEY_ENTER,     KEY_RIGHTBRACE,KEY_BACKSLASH, KEY_BACKSLASH,KEY_F12,       KEY_SCROLLLOCK,
-	/* 60 */  KEY_DOWN,     KEY_LEFT,      KEY_PAUSE,     KEY_UP,        KEY_DELETE,    KEY_END,      KEY_BACKSPACE, KEY_INSERT,
-	/* 68 */  KBD_UNKNOWN,  KEY_KP1,       KEY_RIGHT,     KEY_KP4,       KEY_KP7,       KEY_PAGEDOWN, KEY_HOME,      KEY_PAGEUP,
-	/* 70 */  KEY_KP0,      KEY_KPDOT,     KEY_KP2,       KEY_KP5,       KEY_KP6,       KEY_KP8,      KEY_ESC,       KEY_NUMLOCK,
-	/* 78 */  KEY_F11,      KEY_KPPLUS,    KEY_KP3,       KEY_KPMINUS,   KEY_KPASTERISK,KEY_KP9,      KEY_SCROLLLOCK,KEY_103RD,
-	/* 80 */  KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,
-	/* 88 */  KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,
-	/* 90 */  KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,
-	/* 98 */  KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,
-	/* a0 */  KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,
-	/* a8 */  KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,
-	/* b0 */  KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,
-	/* b8 */  KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,
-	/* c0 */  KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,
-	/* c8 */  KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,
-	/* d0 */  KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,
-	/* d8 */  KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,
-	/* e0 */  KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,
-	/* e8 */  KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,
-	/* f0 */  KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,
-	/* f8 */  KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,
-
-	/* These are offset for escaped keycodes: */
-
-	/* 00 */  KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,   KEY_F7,        KBD_UNKNOWN,   KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,
-	/* 08 */  KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,   KEY_LEFTMETA,  KEY_RIGHTMETA, KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,
-	/* 10 */  KBD_UNKNOWN,  KEY_RIGHTALT,  KBD_UNKNOWN,   KBD_UNKNOWN,   KEY_RIGHTCTRL, KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,
-	/* 18 */  KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,
-	/* 20 */  KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,
-	/* 28 */  KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,
-	/* 30 */  KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,
-	/* 38 */  KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,
-	/* 40 */  KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,
-	/* 48 */  KBD_UNKNOWN,  KBD_UNKNOWN,   KEY_KPSLASH,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,
-	/* 50 */  KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,
-	/* 58 */  KBD_UNKNOWN,  KBD_UNKNOWN,   KEY_KPENTER,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,
-	/* 60 */  KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,
-	/* 68 */  KBD_UNKNOWN,  KEY_END,       KBD_UNKNOWN,   KEY_LEFT,      KEY_HOME,      KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,
-	/* 70 */  KEY_INSERT,   KEY_DELETE,    KEY_DOWN,      KBD_UNKNOWN,   KEY_RIGHT,     KEY_UP,       KBD_UNKNOWN,   KBD_UNKNOWN,
-	/* 78 */  KBD_UNKNOWN,  KBD_UNKNOWN,   KEY_PAGEDOWN,  KBD_UNKNOWN,   KEY_SYSRQ,     KEY_PAGEUP,   KBD_UNKNOWN,   KBD_UNKNOWN,
-	/* 80 */  KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,
-	/* 88 */  KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,
-	/* 90 */  KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,
-	/* 98 */  KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,
-	/* a0 */  KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,
-	/* a8 */  KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,
-	/* b0 */  KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,
-	/* b8 */  KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,
-	/* c0 */  KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,
-	/* c8 */  KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,
-	/* d0 */  KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,
-	/* d8 */  KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,
-	/* e0 */  KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,
-	/* e8 */  KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,
-	/* f0 */  KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,
-	/* f8 */  KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN
+/* 00 */  KEY_RESERVED, KEY_F9,        KEY_RESERVED,  KEY_F5,        KEY_F3,        KEY_F1,       KEY_F2,        C_07,
+/* 08 */  KEY_ESC,      KEY_F10,       KEY_F8,        KEY_F6,        KEY_F4,        KEY_TAB,      KEY_GRAVE,     KEY_F2,
+/* 10 */  KEY_RESERVED, C_11,          KEY_LEFTSHIFT, KEY_RESERVED,  C_14,          KEY_Q,        KEY_1,         KEY_F3,
+/* 18 */  KEY_RESERVED, KEY_LEFTALT,   KEY_Z,         KEY_S,         KEY_A,         KEY_W,        KEY_2,         KEY_F4,
+/* 20 */  KEY_RESERVED, KEY_C,         KEY_X,         KEY_D,         KEY_E,         KEY_4,        KEY_3,         KEY_F5,
+/* 28 */  KEY_RESERVED, KEY_SPACE,     KEY_V,         KEY_F,         KEY_T,         KEY_R,        KEY_5,         KEY_F6,
+/* 30 */  KEY_RESERVED, KEY_N,         KEY_B,         KEY_H,         KEY_G,         KEY_Y,        KEY_6,         KEY_F7,
+/* 38 */  KEY_RESERVED, KEY_RIGHTALT,  KEY_M,         KEY_J,         KEY_U,         KEY_7,        KEY_8,         KEY_F8,
+/* 40 */  KEY_RESERVED, KEY_COMMA,     KEY_K,         KEY_I,         KEY_O,         KEY_0,        KEY_9,         KEY_F9,
+/* 48 */  KEY_RESERVED, KEY_DOT,       KEY_SLASH,     KEY_L,         KEY_SEMICOLON, KEY_P,        KEY_MINUS,     KEY_F10,
+/* 50 */  KEY_RESERVED, KEY_RESERVED,  KEY_APOSTROPHE,KEY_RESERVED,  KEY_LEFTBRACE, KEY_EQUAL,    KEY_F11,       KEY_SYSRQ,
+/* 58 */  C_58,         KEY_RIGHTSHIFT,KEY_ENTER,     KEY_RIGHTBRACE,KEY_BACKSLASH, KEY_BACKSLASH,KEY_F12,       KEY_SCROLLLOCK,
+/* 60 */  KEY_DOWN,     C_61,          KEY_PAUSE,     KEY_UP,        KEY_DELETE,    KEY_END,      KEY_BACKSPACE, KEY_INSERT,
+/* 68 */  KEY_RESERVED, KEY_KP1,       KEY_RIGHT,     KEY_KP4,       KEY_KP7,       KEY_PAGEDOWN, KEY_HOME,      KEY_PAGEUP,
+/* 70 */  KEY_KP0,      KEY_KPDOT,     KEY_KP2,       KEY_KP5,       KEY_KP6,       KEY_KP8,      KEY_ESC,       KEY_NUMLOCK,
+/* 78 */  KEY_F11,      KEY_KPPLUS,    KEY_KP3,       KEY_KPMINUS,   KEY_KPASTERISK,KEY_KP9,      KEY_SCROLLLOCK,KEY_103RD,
+/* 80 */  KEY_RESERVED, KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED, KEY_RESERVED,  KEY_RESERVED,
+/* 88 */  KEY_RESERVED, KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED, KEY_RESERVED,  KEY_RESERVED,
+/* 90 */  KEY_RESERVED, KEY_RIGHTALT,  KEY_SYSRQ,     KEY_RESERVED,  KEY_RIGHTCTRL, KEY_RESERVED, KEY_RESERVED,  KEY_RESERVED,
+/* 98 */  KEY_RESERVED, KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED,  KEY_CAPSLOCK, KEY_RESERVED,  KEY_LEFTMETA,
+/* a0 */  KEY_RESERVED, KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED, KEY_RESERVED,  KEY_RIGHTMETA,
+/* a8 */  KEY_RESERVED, KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED, KEY_RESERVED,  KEY_COMPOSE,
+/* b0 */  KEY_RESERVED, KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED, KEY_RESERVED,  KEY_RESERVED,
+/* b8 */  KEY_RESERVED, KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED, KEY_RESERVED,  KEY_RESERVED,
+/* c0 */  KEY_RESERVED, KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED, KEY_RESERVED,  KEY_RESERVED,
+/* c8 */  KEY_RESERVED, KEY_RESERVED,  KEY_KPSLASH,   KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED, KEY_RESERVED,  KEY_RESERVED,
+/* d0 */  KEY_RESERVED, KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED, KEY_RESERVED,  KEY_RESERVED,
+/* d8 */  KEY_RESERVED, KEY_RESERVED,  KEY_KPENTER,   KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED, KEY_RESERVED,  KEY_RESERVED,
+/* e0 */  KEY_RESERVED, KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED, KEY_RESERVED,  KEY_RESERVED,
+/* e8 */  KEY_RESERVED, KEY_END,       KEY_RESERVED,  KEY_LEFT,      KEY_HOME,      KEY_RESERVED, KEY_RESERVED,  KEY_RESERVED,
+/* f0 */  KEY_INSERT,   KEY_DELETE,    KEY_DOWN,      KEY_RESERVED,  KEY_RIGHT,     KEY_UP,       KEY_RESERVED,  KEY_PAUSE,
+/* f8 */  KEY_RESERVED, KEY_RESERVED,  KEY_PAGEDOWN,  KEY_RESERVED,  KEY_SYSRQ,     KEY_PAGEUP,   KEY_RESERVED,  KEY_RESERVED,
+
+/* These are offset for escaped keycodes: */
+
+/* 00 */  KEY_RESERVED, KEY_RESERVED,  KEY_RESERVED,  KEY_F7,        KEY_RESERVED,  KEY_RESERVED, KEY_RESERVED,  KEY_RESERVED,
+/* 08 */  KEY_RESERVED, KEY_RESERVED,  KEY_RESERVED,  KEY_LEFTMETA,  KEY_RIGHTMETA, KEY_RESERVED, KEY_RESERVED,  KEY_RESERVED,
+/* 10 */  KEY_RESERVED, KEY_RIGHTALT,  KEY_RESERVED,  KEY_RESERVED,  KEY_RIGHTCTRL, KEY_RESERVED, KEY_RESERVED,  KEY_RESERVED,
+/* 18 */  KEY_RESERVED, KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED, KEY_RESERVED,  KEY_RESERVED,
+/* 20 */  KEY_RESERVED, KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED, KEY_RESERVED,  KEY_RESERVED,
+/* 28 */  KEY_RESERVED, KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED, KEY_RESERVED,  KEY_RESERVED,
+/* 30 */  KEY_RESERVED, KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED, KEY_RESERVED,  KEY_RESERVED,
+/* 38 */  KEY_RESERVED, KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED, KEY_RESERVED,  KEY_RESERVED,
+/* 40 */  KEY_RESERVED, KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED, KEY_RESERVED,  KEY_RESERVED,
+/* 48 */  KEY_RESERVED, KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED, KEY_RESERVED,  KEY_RESERVED,
+/* 50 */  KEY_RESERVED, KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED, KEY_RESERVED,  KEY_RESERVED,
+/* 58 */  KEY_RESERVED, KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED, KEY_RESERVED,  KEY_RESERVED,
+/* 60 */  KEY_RESERVED, KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED, KEY_RESERVED,  KEY_RESERVED,
+/* 68 */  KEY_RESERVED, KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED, KEY_RESERVED,  KEY_RESERVED,
+/* 70 */  KEY_RESERVED, KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED, KEY_RESERVED,  KEY_RESERVED,
+/* 78 */  KEY_RESERVED, KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED, KEY_RESERVED,  KEY_RESERVED,
+/* 80 */  KEY_RESERVED, KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED, KEY_RESERVED,  KEY_RESERVED,
+/* 88 */  KEY_RESERVED, KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED, KEY_RESERVED,  KEY_RESERVED,
+/* 90 */  KEY_RESERVED, KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED, KEY_RESERVED,  KEY_RESERVED,
+/* 98 */  KEY_RESERVED, KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED, KEY_RESERVED,  KEY_RESERVED,
+/* a0 */  KEY_RESERVED, KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED, KEY_RESERVED,  KEY_RESERVED,
+/* a8 */  KEY_RESERVED, KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED, KEY_RESERVED,  KEY_RESERVED,
+/* b0 */  KEY_RESERVED, KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED, KEY_RESERVED,  KEY_RESERVED,
+/* b8 */  KEY_RESERVED, KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED, KEY_RESERVED,  KEY_RESERVED,
+/* c0 */  KEY_RESERVED, KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED, KEY_RESERVED,  KEY_RESERVED,
+/* c8 */  KEY_RESERVED, KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED, KEY_RESERVED,  KEY_RESERVED,
+/* d0 */  KEY_RESERVED, KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED, KEY_RESERVED,  KEY_RESERVED,
+/* d8 */  KEY_RESERVED, KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED, KEY_RESERVED,  KEY_RESERVED,
+/* e0 */  KEY_RESERVED, KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED, KEY_RESERVED,  KEY_RESERVED,
+/* e8 */  KEY_RESERVED, KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED, KEY_RESERVED,  KEY_RESERVED,
+/* f0 */  KEY_RESERVED, KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED, KEY_RESERVED,  KEY_RESERVED,
+/* f8 */  KEY_RESERVED, KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED, KEY_RESERVED,  KEY_RESERVED
+
+#undef STANDARD_KEYBOARD
+#undef CONFLICT
+#undef C_07
+#undef C_11
+#undef C_14
+#undef C_58
+#undef C_61
 
-};
--- diff/drivers/input/keyboard/sunkbd.c	2003-08-20 14:16:09.000000000 +0100
+++ source/drivers/input/keyboard/sunkbd.c	2004-02-23 13:56:41.000000000 +0000
@@ -77,6 +77,7 @@ struct sunkbd {
 	struct input_dev dev;
 	struct serio *serio;
 	struct work_struct tq;
+	wait_queue_head_t wait;
 	char name[64];
 	char phys[32];
 	char type;
@@ -96,11 +97,13 @@ static irqreturn_t sunkbd_interrupt(stru
 
 	if (sunkbd->reset <= -1) {		/* If cp[i] is 0xff, sunkbd->reset will stay -1. */
 		sunkbd->reset = data;		/* The keyboard sends 0xff 0xff 0xID on powerup */
+		wake_up_interruptible(&sunkbd->wait);
 		goto out;
 	}
 
 	if (sunkbd->layout == -1) {
 		sunkbd->layout = data;
+		wake_up_interruptible(&sunkbd->wait);
 		goto out;
 	}
 
@@ -176,22 +179,19 @@ static int sunkbd_event(struct input_dev
 
 static int sunkbd_initialize(struct sunkbd *sunkbd)
 {
-	int t;
-
-	t = 1000;
 	sunkbd->reset = -2;
 	sunkbd->serio->write(sunkbd->serio, SUNKBD_CMD_RESET);
-	while (sunkbd->reset < 0 && --t) mdelay(1);
-	if (!t) return -1;
+	wait_event_interruptible_timeout(sunkbd->wait, sunkbd->reset >= 0, HZ);
+	if (sunkbd->reset <0)
+		return -1;
 
 	sunkbd->type = sunkbd->reset;
 
 	if (sunkbd->type == 4) {	/* Type 4 keyboard */
-		t = 250;
 		sunkbd->layout = -2;
 		sunkbd->serio->write(sunkbd->serio, SUNKBD_CMD_LAYOUT);
-		while (sunkbd->layout < 0 && --t) mdelay(1);
-		if (!t) return -1;
+		wait_event_interruptible_timeout(sunkbd->wait, sunkbd->layout >= 0, HZ/4);
+		if (sunkbd->layout < 0) return -1;
 		if (sunkbd->layout & SUNKBD_LAYOUT_5_MASK) sunkbd->type = 5;
 	}
 
@@ -206,9 +206,8 @@ static int sunkbd_initialize(struct sunk
 static void sunkbd_reinit(void *data)
 {
 	struct sunkbd *sunkbd = data;
-	int t = 1000;
 
-	while (sunkbd->reset < 0 && --t) mdelay(1);
+	wait_event_interruptible_timeout(sunkbd->wait, sunkbd->reset >= 0, HZ);
 
 	sunkbd->serio->write(sunkbd->serio, SUNKBD_CMD_SETLED);
 	sunkbd->serio->write(sunkbd->serio, 
@@ -239,6 +238,7 @@ static void sunkbd_connect(struct serio 
 	memset(sunkbd, 0, sizeof(struct sunkbd));
 
 	init_input_dev(&sunkbd->dev);
+	init_waitqueue_head(&sunkbd->wait);
 
 	sunkbd->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_LED) | BIT(EV_SND) | BIT(EV_REP);
 	sunkbd->dev.ledbit[0] = BIT(LED_CAPSL) | BIT(LED_COMPOSE) | BIT(LED_SCROLLL) | BIT(LED_NUML);
@@ -275,7 +275,7 @@ static void sunkbd_connect(struct serio 
 		set_bit(sunkbd->keycode[i], sunkbd->dev.keybit);
 	clear_bit(0, sunkbd->dev.keybit);
 
-	sprintf(sunkbd->name, "%s/input", serio->phys);
+	sprintf(sunkbd->phys, "%s/input0", serio->phys);
 
 	sunkbd->dev.name = sunkbd->name;
 	sunkbd->dev.phys = sunkbd->phys;
--- diff/drivers/input/misc/Kconfig	2003-09-30 15:46:14.000000000 +0100
+++ source/drivers/input/misc/Kconfig	2004-02-23 13:56:41.000000000 +0000
@@ -54,12 +54,3 @@ config INPUT_UINPUT
 	  To compile this driver as a module, choose M here: the
 	  module will be called uinput.
 
-config INPUT_GSC
-	tristate "PA-RISC GSC PS/2 keyboard/mouse support"
-	depends on GSC && INPUT && INPUT_MISC
-	help
-	  Say Y here if you have a PS/2 keyboard and/or mouse attached
-	  to your PA-RISC box.	HP run the keyboard in AT mode rather than
-	  XT mode like everyone else, so we need our own driver.
-	  Furthermore, the GSC PS/2 controller shares IRQ between mouse and
-	  keyboard.
--- diff/drivers/input/misc/Makefile	2003-02-26 16:00:54.000000000 +0000
+++ source/drivers/input/misc/Makefile	2004-02-23 13:56:41.000000000 +0000
@@ -9,4 +9,3 @@ obj-$(CONFIG_INPUT_PCSPKR)		+= pcspkr.o
 obj-$(CONFIG_INPUT_M68K_BEEP)		+= m68kspkr.o
 obj-$(CONFIG_INPUT_98SPKR)		+= 98spkr.o
 obj-$(CONFIG_INPUT_UINPUT)		+= uinput.o
-obj-$(CONFIG_INPUT_GSC)			+= gsc_ps2.o
--- diff/drivers/input/mouse/Kconfig	2004-02-09 10:36:10.000000000 +0000
+++ source/drivers/input/mouse/Kconfig	2004-02-23 13:56:41.000000000 +0000
@@ -17,6 +17,7 @@ config MOUSE_PS2
 	depends on INPUT && INPUT_MOUSE
 	select SERIO
 	select SERIO_I8042 if PC
+	select SERIO_GSCPS2 if GSC
 	---help---
 	  Say Y here if you have a PS/2 mouse connected to your system. This
 	  includes the standard 2 or 3-button PS/2 mouse, as well as PS/2
--- diff/drivers/input/mouse/psmouse-base.c	2004-02-09 10:36:10.000000000 +0000
+++ source/drivers/input/mouse/psmouse-base.c	2004-02-23 13:56:41.000000000 +0000
@@ -134,6 +134,13 @@ static irqreturn_t psmouse_interrupt(str
 		goto out;
 	}
 
+	if (flags & (SERIO_PARITY|SERIO_TIMEOUT)) {
+		printk(KERN_WARNING "psmouse.c: bad data from KBC -%s%s\n",
+			flags & SERIO_TIMEOUT ? " timeout" : "",
+			flags & SERIO_PARITY ? " bad parity" : "");
+		goto out;
+	}
+
 	if (psmouse->acking) {
 		switch (data) {
 			case PSMOUSE_RET_ACK:
--- diff/drivers/input/serio/Kconfig	2003-09-30 15:46:14.000000000 +0100
+++ source/drivers/input/serio/Kconfig	2004-02-23 13:56:42.000000000 +0000
@@ -20,6 +20,7 @@ config SERIO_I8042
 	tristate "i8042 PC Keyboard controller" if EMBEDDED || !X86
 	default y
 	select SERIO
+	depends on !PARISC
 	---help---
 	  i8042 is the chip over which the standard AT keyboard and PS/2
 	  mouse are connected to the computer. If you use these devices,
@@ -48,6 +49,7 @@ config SERIO_SERPORT
 config SERIO_CT82C710
 	tristate "ct82c710 Aux port controller"
 	depends on SERIO
+	depends on !PARISC
 	---help---
 	  Say Y here if you have a Texas Instruments TravelMate notebook
 	  equipped with the ct82c710 chip and want to use a mouse connected
@@ -105,6 +107,20 @@ config SERIO_98KBD
 	  To compile this driver as a module, choose M here: the
 	  module will be called 98kbd-io.
 
+config SERIO_GSCPS2
+	tristate "HP GSC PS/2 keyboard and PS/2 mouse controller"
+	depends on GSC && SERIO
+	default y
+	help
+	  This driver provides support for the PS/2 ports on PA-RISC machines
+	  over which HP PS/2 keyboards and PS/2 mice may be connected.
+	  If you use these devices, you'll need to say Y here.
+
+	  It's safe to enable this driver, so if unsure, say Y.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called gscps2.
+
 config SERIO_PCIPS2
 	tristate "PCI PS/2 keyboard and PS/2 mouse controller"
 	depends on PCI && SERIO
--- diff/drivers/input/serio/Makefile	2003-06-30 10:07:29.000000000 +0100
+++ source/drivers/input/serio/Makefile	2004-02-23 13:56:42.000000000 +0000
@@ -14,4 +14,5 @@ obj-$(CONFIG_SERIO_SA1111)	+= sa1111ps2.
 obj-$(CONFIG_SERIO_AMBAKMI)	+= ambakmi.o
 obj-$(CONFIG_SERIO_Q40KBD)	+= q40kbd.o
 obj-$(CONFIG_SERIO_98KBD)	+= 98kbd-io.o
+obj-$(CONFIG_SERIO_GSCPS2)	+= gscps2.o
 obj-$(CONFIG_SERIO_PCIPS2)	+= pcips2.o
--- diff/drivers/input/serio/ambakmi.c	2003-09-30 15:46:14.000000000 +0100
+++ source/drivers/input/serio/ambakmi.c	2004-02-23 13:56:41.000000000 +0000
@@ -33,7 +33,6 @@ struct amba_kmi_port {
 	unsigned int		irq;
 	unsigned int		divisor;
 	unsigned int		open;
-	struct resource		*res;
 };
 
 static irqreturn_t amba_kmi_int(int irq, void *dev_id, struct pt_regs *regs)
@@ -97,10 +96,17 @@ static void amba_kmi_close(struct serio 
 static int amba_kmi_probe(struct amba_device *dev, void *id)
 {
 	struct amba_kmi_port *kmi;
+	int ret;
+
+	ret = amba_request_regions(dev, NULL);
+	if (ret)
+		return ret;
 
 	kmi = kmalloc(sizeof(struct amba_kmi_port), GFP_KERNEL);
-	if (!kmi)
-		return -ENOMEM;
+	if (!kmi) {
+		ret = -ENOMEM;
+		goto out;
+	}
 
 	memset(kmi, 0, sizeof(struct amba_kmi_port));
 
@@ -112,26 +118,24 @@ static int amba_kmi_probe(struct amba_de
 	kmi->io.phys	= dev->dev.bus_id;
 	kmi->io.driver	= kmi;
 
-	kmi->res	= request_mem_region(dev->res.start, KMI_SIZE, "kmi-pl050");
-	if (!kmi->res) {
-		kfree(kmi);
-		return -EBUSY;
-	}
-
 	kmi->base	= ioremap(dev->res.start, KMI_SIZE);
 	if (!kmi->base) {
-		release_resource(kmi->res);
-		kfree(kmi);
-		return -ENOMEM;
+		ret = -ENOMEM;
+		goto out;
 	}
 
-	kmi->irq	= dev->irq;
+	kmi->irq	= dev->irq[0];
 	kmi->divisor	= 24 / 8 - 1;
 
 	amba_set_drvdata(dev, kmi);
 
 	serio_register_port(&kmi->io);
 	return 0;
+
+ out:
+	kfree(kmi);
+	amba_release_regions(dev);
+	return ret;
 }
 
 static int amba_kmi_remove(struct amba_device *dev)
@@ -142,8 +146,8 @@ static int amba_kmi_remove(struct amba_d
 
 	serio_unregister_port(&kmi->io);
 	iounmap(kmi->base);
-	release_resource(kmi->res);
 	kfree(kmi);
+	amba_release_regions(dev);
 	return 0;
 }
 
--- diff/drivers/input/serio/i8042.c	2004-02-18 08:54:09.000000000 +0000
+++ source/drivers/input/serio/i8042.c	2004-02-23 13:56:42.000000000 +0000
@@ -957,7 +957,7 @@ int __init i8042_init(void)
 	mod_timer(&i8042_timer, jiffies + I8042_POLL_PERIOD);
 
         if (sysdev_class_register(&kbc_sysclass) == 0) {
-                if (sys_device_register(&device_i8042) == 0)
+                if (sysdev_register(&device_i8042) == 0)
 			i8042_sysdev_initialized = 1;
 		else
 			sysdev_class_unregister(&kbc_sysclass);
@@ -980,7 +980,7 @@ void __exit i8042_exit(void)
 		pm_unregister(i8042_pm_dev);
 
 	if (i8042_sysdev_initialized) {
-		sys_device_unregister(&device_i8042);
+		sysdev_unregister(&device_i8042);
 		sysdev_class_unregister(&kbc_sysclass);
 	}
 
--- diff/drivers/isdn/Kconfig	2004-02-09 10:36:10.000000000 +0000
+++ source/drivers/isdn/Kconfig	2004-02-23 13:56:43.000000000 +0000
@@ -4,8 +4,8 @@
 
 menu "ISDN subsystem"
 
-config ISDN_BOOL
-	bool "ISDN support"
+config ISDN
+	tristate "ISDN support"
 	depends on NET
 	---help---
 	  ISDN ("Integrated Services Digital Networks", called RNIS in France)
@@ -22,9 +22,9 @@ config ISDN_BOOL
 
 
 menu "Old ISDN4Linux"
-	depends on NET && ISDN_BOOL && BROKEN_ON_SMP
+	depends on NET && ISDN
 
-config ISDN
+config ISDN_I4L
 	tristate "Old ISDN4Linux (obsolete)"
 	---help---
 	  This driver allows you to use an ISDN-card for networking
@@ -41,18 +41,18 @@ config ISDN
 	  Therefore the old ISDN4Linux layer is becoming obsolete. It is 
 	  still usable, though, if you select this option.
 
-if ISDN
+if ISDN_I4L
 source "drivers/isdn/i4l/Kconfig"
 endif
 
 endmenu
 
 comment "CAPI subsystem"
-	depends on NET && ISDN_BOOL
+	depends on NET && ISDN
 
 config ISDN_CAPI
 	tristate "CAPI2.0 support"
-	depends on ISDN_BOOL
+	depends on ISDN
 	help
 	  This provides the CAPI (Common ISDN Application Programming
 	  Interface, a standard making it easy for programs to access ISDN
--- diff/drivers/isdn/Makefile	2004-02-09 10:36:10.000000000 +0000
+++ source/drivers/isdn/Makefile	2004-02-23 13:56:43.000000000 +0000
@@ -2,7 +2,7 @@
 
 # Object files in subdirectories
 
-obj-$(CONFIG_ISDN)			+= i4l/
+obj-$(CONFIG_ISDN_I4L)			+= i4l/
 obj-$(CONFIG_ISDN_CAPI)			+= capi/
 obj-$(CONFIG_ISDN_CAPI)			+= hardware/
 obj-$(CONFIG_ISDN_DIVERSION)		+= divert/
--- diff/drivers/isdn/act2000/Kconfig	2002-11-11 11:09:36.000000000 +0000
+++ source/drivers/isdn/act2000/Kconfig	2004-02-23 13:56:42.000000000 +0000
@@ -3,7 +3,7 @@
 #
 config ISDN_DRV_ACT2000
 	tristate "IBM Active 2000 support"
-	depends on ISDN && ISA
+	depends on ISDN_I4L && ISA
 	help
 	  Say Y here if you have an IBM Active 2000 ISDN card. In order to use
 	  this card, additional firmware is necessary, which has to be loaded
--- diff/drivers/isdn/act2000/act2000.h	2002-10-16 04:28:22.000000000 +0100
+++ source/drivers/isdn/act2000/act2000.h	2004-02-23 13:56:42.000000000 +0000
@@ -147,34 +147,36 @@ typedef union irq_data {
  * Per card driver data
  */
 typedef struct act2000_card {
-        unsigned short port;             /* Base-port-address                */
-        unsigned short irq;              /* Interrupt                        */
-        u_char ptype;                    /* Protocol type (1TR6 or Euro)     */
-        u_char bus;                      /* Cardtype (ISA, MCA, PCMCIA)      */
-        struct act2000_card *next;	 /* Pointer to next device struct    */
-        int myid;                        /* Driver-Nr. assigned by linklevel */
-        unsigned long flags;             /* Statusflags                      */
-        unsigned long ilock;             /* Semaphores for IRQ-Routines      */
-	struct sk_buff_head rcvq;        /* Receive-Message queue            */
-	struct sk_buff_head sndq;        /* Send-Message queue               */
-	struct sk_buff_head ackq;        /* Data-Ack-Message queue           */
-	u_char *ack_msg;                 /* Ptr to User Data in User skb     */
-	__u16 need_b3ack;                /* Flag: Need ACK for current skb   */
-	struct sk_buff *sbuf;            /* skb which is currently sent      */
-	struct timer_list ptimer;        /* Poll timer                       */
-	struct work_struct snd_tq;         /* Task struct for xmit bh          */
-	struct work_struct rcv_tq;         /* Task struct for rcv bh           */
-	struct work_struct poll_tq;        /* Task struct for polled rcv bh    */
+	unsigned short port;		/* Base-port-address                */
+	unsigned short irq;		/* Interrupt                        */
+	u_char ptype;			/* Protocol type (1TR6 or Euro)     */
+	u_char bus;			/* Cardtype (ISA, MCA, PCMCIA)      */
+	struct act2000_card *next;	/* Pointer to next device struct    */
+	spinlock_t lock;		/* protect critical operations      */
+	int myid;			/* Driver-Nr. assigned by linklevel */
+	unsigned long flags;		/* Statusflags                      */
+	unsigned long ilock;		/* Semaphores for IRQ-Routines      */
+	struct sk_buff_head rcvq;	/* Receive-Message queue            */
+	struct sk_buff_head sndq;	/* Send-Message queue               */
+	struct sk_buff_head ackq;	/* Data-Ack-Message queue           */
+	u_char *ack_msg;		/* Ptr to User Data in User skb     */
+	__u16 need_b3ack;		/* Flag: Need ACK for current skb   */
+	struct sk_buff *sbuf;		/* skb which is currently sent      */
+	struct timer_list ptimer;	/* Poll timer                       */
+	struct work_struct snd_tq;	/* Task struct for xmit bh          */
+	struct work_struct rcv_tq;	/* Task struct for rcv bh           */
+	struct work_struct poll_tq;	/* Task struct for polled rcv bh    */
 	msn_entry *msn_list;
-	unsigned short msgnum;           /* Message number fur sending       */
-	act2000_chan bch[ACT2000_BCH];   /* B-Channel status/control         */
-	char   status_buf[256];          /* Buffer for status messages       */
+	unsigned short msgnum;		/* Message number for sending       */
+	spinlock_t mnlock;		/* lock for msgnum                  */
+	act2000_chan bch[ACT2000_BCH];	/* B-Channel status/control         */
+	char   status_buf[256];		/* Buffer for status messages       */
 	char   *status_buf_read;
 	char   *status_buf_write;
 	char   *status_buf_end;
-	irq_data idat;                   /* Data used for IRQ handler        */
-        isdn_if interface;               /* Interface to upper layer         */
-        char regname[35];                /* Name used for request_region     */
+	irq_data idat;			/* Data used for IRQ handler        */
+	isdn_if interface;		/* Interface to upper layer         */
+	char regname[35];		/* Name used for request_region     */
 } act2000_card;
 
 extern __inline__ void act2000_schedule_tx(act2000_card *card)
--- diff/drivers/isdn/act2000/act2000_isa.c	2003-05-21 11:50:15.000000000 +0100
+++ source/drivers/isdn/act2000/act2000_isa.c	2004-02-23 13:56:42.000000000 +0000
@@ -21,10 +21,8 @@ static act2000_card *irq2card_map[16];
 static void
 act2000_isa_delay(long t)
 {
-        sti();
         set_current_state(TASK_INTERRUPTIBLE);
         schedule_timeout(t);
-        sti();
 }
 
 /*
@@ -64,8 +62,10 @@ act2000_isa_detect(unsigned short portba
 {
         int ret = 0;
 
-        if (!check_region(portbase, ISA_REGION))
+	if (request_region(portbase, ACT2000_PORTLEN, "act2000isa")) {
                 ret = act2000_isa_reset(portbase);
+		release_region(portbase, ISA_REGION);
+	}
         return ret;
 }
 
@@ -177,14 +177,13 @@ act2000_isa_config_port(act2000_card * c
                 release_region(card->port, ISA_REGION);
                 card->flags &= ~ACT2000_FLAGS_PVALID;
         }
-        if (!check_region(portbase, ISA_REGION)) {
-                if (request_region(portbase, ACT2000_PORTLEN, card->regname) == NULL)
-			return -EIO;
+	if (request_region(portbase, ACT2000_PORTLEN, card->regname) == NULL)
+		return -EBUSY;
+	else {
                 card->port = portbase;
                 card->flags |= ACT2000_FLAGS_PVALID;
                 return 0;
         }
-        return -EBUSY;
 }
 
 /*
@@ -195,8 +194,7 @@ act2000_isa_release(act2000_card * card)
 {
         unsigned long flags;
 
-        save_flags(flags);
-        cli();
+        spin_lock_irqsave(&card->lock, flags);
         if (card->flags & ACT2000_FLAGS_IVALID) {
                 free_irq(card->irq, NULL);
                 irq2card_map[card->irq] = NULL;
@@ -205,7 +203,7 @@ act2000_isa_release(act2000_card * card)
         if (card->flags & ACT2000_FLAGS_PVALID)
                 release_region(card->port, ISA_REGION);
         card->flags &= ~ACT2000_FLAGS_PVALID;
-        restore_flags(flags);
+        spin_unlock_irqrestore(&card->lock, flags);
 }
 
 static int
@@ -316,8 +314,7 @@ act2000_isa_send(act2000_card * card)
         if (test_and_set_bit(ACT2000_LOCK_TX, (void *) &card->ilock) != 0)
 		return;
 	while (1) {
-		save_flags(flags);
-		cli();
+		spin_lock_irqsave(&card->lock, flags);
 		if (!(card->sbuf)) {
 			if ((card->sbuf = skb_dequeue(&card->sndq))) {
 				card->ack_msg = card->sbuf->data;
@@ -330,7 +327,7 @@ act2000_isa_send(act2000_card * card)
 				}
 			}
 		}
-		restore_flags(flags);
+		spin_unlock_irqrestore(&card->lock, flags);
 		if (!(card->sbuf)) {
 			/* No more data to send */
 			test_and_clear_bit(ACT2000_LOCK_TX, (void *) &card->ilock);
--- diff/drivers/isdn/act2000/capi.c	2002-10-16 04:29:02.000000000 +0100
+++ source/drivers/isdn/act2000/capi.c	2004-02-23 13:56:42.000000000 +0000
@@ -591,10 +591,9 @@ handle_ack(act2000_card *card, act2000_c
 	struct actcapi_msg *m;
 	int ret = 0;
 
-	save_flags(flags);
-	cli();
+	spin_lock_irqsave(&card->lock, flags);
 	skb = skb_peek(&card->ackq);
-	restore_flags(flags);
+	spin_unlock_irqrestore(&card->lock, flags);
         if (!skb) {
 		printk(KERN_WARNING "act2000: handle_ack nothing found!\n");
 		return 0;
@@ -614,10 +613,9 @@ handle_ack(act2000_card *card, act2000_c
 				chan->queued = 0;
                         return ret;
                 }
-		save_flags(flags);
-		cli();
+                spin_lock_irqsave(&card->lock, flags);
                 tmp = skb_peek((struct sk_buff_head *)tmp);
-		restore_flags(flags);
+                spin_unlock_irqrestore(&card->lock, flags);
                 if ((tmp == skb) || (tmp == NULL)) {
 			/* reached end of queue */
 			printk(KERN_WARNING "act2000: handle_ack nothing found!\n");
--- diff/drivers/isdn/act2000/capi.h	2002-10-16 04:29:05.000000000 +0100
+++ source/drivers/isdn/act2000/capi.h	2004-02-23 13:56:42.000000000 +0000
@@ -336,12 +336,11 @@ actcapi_nextsmsg(act2000_card *card)
 	unsigned long flags;
 	unsigned short n;
 
-	save_flags(flags);
-	cli();
+	spin_lock_irqsave(&card->mnlock, flags);
 	n = card->msgnum;
 	card->msgnum++;
 	card->msgnum &= 0x7fff;
-	restore_flags(flags);
+	spin_unlock_irqrestore(&card->mnlock, flags);
 	return n;
 }
 #define DEBUG_MSG
--- diff/drivers/isdn/act2000/module.c	2003-06-09 14:18:18.000000000 +0100
+++ source/drivers/isdn/act2000/module.c	2004-02-23 13:56:42.000000000 +0000
@@ -62,19 +62,18 @@ find_channel(act2000_card *card, int cha
 static void
 act2000_clear_msn(act2000_card *card)
 {
-        struct msn_entry *p = card->msn_list;
-        struct msn_entry *q;
+	struct msn_entry *p = card->msn_list;
+	struct msn_entry *q;
 	unsigned long flags;
 
-	save_flags(flags);
-	cli();
-        card->msn_list = NULL;
-	restore_flags(flags);
-        while (p) {
-                q  = p->next;
-                kfree(p);
-                p = q;
-        }
+	spin_lock_irqsave(&card->lock, flags);
+	card->msn_list = NULL;
+	spin_unlock_irqrestore(&card->lock, flags);
+	while (p) {
+		q  = p->next;
+		kfree(p);
+		p = q;
+	}
 }
 
 /*
@@ -143,13 +142,12 @@ act2000_set_msn(act2000_card *card, char
 		/* Delete a single MSN */
 		while (p) {
 			if (p->eaz == eazmsn[0]) {
-				save_flags(flags);
-				cli();
+				spin_lock_irqsave(&card->lock, flags);
 				if (q)
 					q->next = p->next;
 				else
 					card->msn_list = p->next;
-				restore_flags(flags);
+				spin_unlock_irqrestore(&card->lock, flags);
 				kfree(p);
 				printk(KERN_DEBUG
 				       "Mapping for EAZ %c deleted\n",
@@ -165,10 +163,9 @@ act2000_set_msn(act2000_card *card, char
 	while (p) {
 		/* Found in list, replace MSN */
 		if (p->eaz == eazmsn[0]) {
-			save_flags(flags);
-			cli();
+			spin_lock_irqsave(&card->lock, flags);
 			strcpy(p->msn, &eazmsn[1]);
-			restore_flags(flags);
+			spin_unlock_irqrestore(&card->lock, flags);
 			printk(KERN_DEBUG
 			       "Mapping for EAZ %c changed to %s\n",
 			       eazmsn[0],
@@ -184,10 +181,9 @@ act2000_set_msn(act2000_card *card, char
 	p->eaz = eazmsn[0];
 	strcpy(p->msn, &eazmsn[1]);
 	p->next = card->msn_list;
-	save_flags(flags);
-	cli();
+	spin_lock_irqsave(&card->lock, flags);
 	card->msn_list = p;
-	restore_flags(flags);
+	spin_unlock_irqrestore(&card->lock, flags);
 	printk(KERN_DEBUG
 	       "Mapping %c -> %s added\n",
 	       eazmsn[0],
@@ -232,10 +228,9 @@ act2000_poll(unsigned long data)
 	unsigned long flags;
 
 	act2000_receive(card);
-        save_flags(flags);
-        cli();
-        mod_timer(&card->ptimer, jiffies+3);
-        restore_flags(flags);
+	spin_lock_irqsave(&card->lock, flags);
+	mod_timer(&card->ptimer, jiffies+3);
+	spin_unlock_irqrestore(&card->lock, flags);
 }
 
 static int
@@ -311,10 +306,9 @@ act2000_command(act2000_card * card, isd
 				return -ENODEV;
 			if (!(chan = find_channel(card, c->arg & 0x0f)))
 				break;
-			save_flags(flags);
-			cli();
+			spin_lock_irqsave(&card->lock, flags);
 			if (chan->fsm_state != ACT2000_STATE_NULL) {
-				restore_flags(flags);
+				spin_unlock_irqrestore(&card->lock, flags);
 				printk(KERN_WARNING "Dial on channel with state %d\n",
 					chan->fsm_state);
 				return -EBUSY;
@@ -325,7 +319,7 @@ act2000_command(act2000_card * card, isd
 				tmp[0] = c->parm.setup.eazmsn[0];
 			chan->fsm_state = ACT2000_STATE_OCALL;
 			chan->callref = 0xffff;
-			restore_flags(flags);
+			spin_unlock_irqrestore(&card->lock, flags);
 			ret = actcapi_connect_req(card, chan, c->parm.setup.phone,
 						  tmp[0], c->parm.setup.si1,
 						  c->parm.setup.si2);
@@ -580,6 +574,8 @@ act2000_alloccard(int bus, int port, int
                 return;
         }
         memset((char *) card, 0, sizeof(act2000_card));
+        spin_lock_init(&card->lock);
+        spin_lock_init(&card->mnlock);
 	skb_queue_head_init(&card->sndq);
 	skb_queue_head_init(&card->rcvq);
 	skb_queue_head_init(&card->ackq);
--- diff/drivers/isdn/capi/Kconfig	2002-11-11 11:09:36.000000000 +0000
+++ source/drivers/isdn/capi/Kconfig	2004-02-23 13:56:42.000000000 +0000
@@ -44,7 +44,7 @@ config ISDN_CAPI_CAPIFS
 
 config ISDN_CAPI_CAPIDRV
 	tristate "CAPI2.0 capidrv interface support"
-	depends on ISDN_CAPI && ISDN
+	depends on ISDN_CAPI && ISDN_I4L
 	help
 	  This option provides the glue code to hook up CAPI driven cards to
 	  the legacy isdn4linux link layer.  If you have a card which is
--- diff/drivers/isdn/capi/capi.c	2003-09-17 12:28:06.000000000 +0100
+++ source/drivers/isdn/capi/capi.c	2004-02-23 13:56:42.000000000 +0000
@@ -1,4 +1,4 @@
-/* $Id: capi.c,v 1.1.4.1.2.2 2001/12/21 15:00:17 kai Exp $
+/* $Id: capi.c,v 1.1.2.3 2004/01/16 21:09:26 keil Exp $
  *
  * CAPI 2.0 Interface for Linux
  *
@@ -44,7 +44,7 @@
 #include "capifs.h"
 #endif
 
-static char *revision = "$Revision: 1.1.4.1.2.2 $";
+static char *revision = "$Revision: 1.1.2.3 $";
 
 MODULE_DESCRIPTION("CAPI4Linux: Userspace /dev/capi20 interface");
 MODULE_AUTHOR("Carsten Paeth");
@@ -203,7 +203,7 @@ static struct capiminor *capiminor_alloc
 	struct list_head *l;
 	unsigned int minor = 0;
 	unsigned long flags;
-  
+
 	mp = kmalloc(sizeof(*mp), GFP_ATOMIC);
   	if (!mp) {
   		printk(KERN_ERR "capi: can't alloc capiminor\n");
@@ -220,19 +220,24 @@ static struct capiminor *capiminor_alloc
 	skb_queue_head_init(&mp->outqueue);
 
 	write_lock_irqsave(&capiminor_list_lock, flags);
-	list_for_each(l, &capiminor_list) {
-		p = list_entry(l, struct capiminor, list);
-		if (p->minor > minor) {
-			mp->minor = minor;
-			list_add_tail(&mp->list, &p->list);
-			break;
+	if (list_empty(&capiminor_list)) {
+		list_add(&mp->list, &capiminor_list);
+		write_unlock_irqrestore(&capiminor_list_lock, flags);
+	} else {
+		list_for_each(l, &capiminor_list) {
+			p = list_entry(l, struct capiminor, list);
+			if (p->minor > minor) {
+				mp->minor = minor;
+				list_add_tail(&mp->list, &p->list);
+				break;
+			}
+			minor++;
+		}
+		write_unlock_irqrestore(&capiminor_list_lock, flags);
+		if (l == &capiminor_list) {
+			kfree(mp);
+			return NULL;
 		}
-		minor++;
-	}
-	write_unlock_irqrestore(&capiminor_list_lock, flags);
-	if (l == &capiminor_list) {
-		kfree(mp);
-		return NULL;
 	}
 	return mp;
 }
@@ -297,7 +302,7 @@ static struct capincci *capincci_alloc(s
 		printk(KERN_DEBUG "set mp->nccip\n");
 #endif
 #if defined(CONFIG_ISDN_CAPI_CAPIFS) || defined(CONFIG_ISDN_CAPI_CAPIFS_MODULE)
-		capifs_new_ncci(0, mp->minor, MKDEV(capi_ttymajor, mp->minor));
+		capifs_new_ncci(mp->minor, MKDEV(capi_ttymajor, mp->minor));
 #endif
 	}
 #endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */
@@ -322,8 +327,7 @@ static void capincci_free(struct capidev
 #ifdef CONFIG_ISDN_CAPI_MIDDLEWARE
 			if ((mp = np->minorp) != 0) {
 #if defined(CONFIG_ISDN_CAPI_CAPIFS) || defined(CONFIG_ISDN_CAPI_CAPIFS_MODULE)
-				capifs_free_ncci('r', mp->minor);
-				capifs_free_ncci(0, mp->minor);
+				capifs_free_ncci(mp->minor);
 #endif
 				if (mp->tty) {
 					mp->nccip = 0;
--- diff/drivers/isdn/capi/capidrv.c	2003-09-17 12:28:06.000000000 +0100
+++ source/drivers/isdn/capi/capidrv.c	2004-02-23 13:56:42.000000000 +0000
@@ -1,4 +1,4 @@
-/* $Id: capidrv.c,v 1.39.6.7 2001/09/23 22:24:33 kai Exp $
+/* $Id: capidrv.c,v 1.1.2.2 2004/01/12 23:17:24 keil Exp $
  *
  * ISDN4Linux Driver, using capi20 interface (kernelcapi)
  *
@@ -34,7 +34,7 @@
 #include <linux/isdn/capicmd.h>
 #include "capidrv.h"
 
-static char *revision = "$Revision: 1.39.6.7 $";
+static char *revision = "$Revision: 1.1.2.2 $";
 static int debugmode = 0;
 
 MODULE_DESCRIPTION("CAPI4Linux: Interface to ISDN4Linux");
@@ -1263,6 +1263,10 @@ static void handle_ncci(_cmsg * cmsg)
 		goto ignored;
 
 	case CAPI_DATA_B3_CONF:	/* ncci */
+		if (cmsg->Info) {
+			printk(KERN_WARNING "CAPI_DATA_B3_CONF: Info %x - %s\n",
+				cmsg->Info, capi_info2str(cmsg->Info));
+		}
 		if (!(nccip = find_ncci(card, cmsg->adr.adrNCCI)))
 			goto notfound;
 
@@ -1368,7 +1372,7 @@ static _cmsg s_cmsg;
 static void capidrv_recv_message(struct capi20_appl *ap, struct sk_buff *skb)
 {
 	capi_message2cmsg(&s_cmsg, skb->data);
-	if (debugmode > 2)
+	if (debugmode > 3)
 		printk(KERN_DEBUG "capidrv_signal: applid=%d %s\n",
 		       ap->applid, capi_cmsg2str(&s_cmsg));
 	
@@ -1825,7 +1829,7 @@ static int if_sendbuf(int id, int channe
 		       id);
 		return 0;
 	}
-	if (debugmode > 1)
+	if (debugmode > 4)
 		printk(KERN_DEBUG "capidrv-%d: sendbuf len=%d skb=%p doack=%d\n",
 					card->contrnr, len, skb, doack);
 	bchan = &card->bchans[channel % card->nbchan];
@@ -1866,6 +1870,9 @@ static int if_sendbuf(int id, int channe
 			nccip->datahandle++;
 			return len;
 		}
+		if (debugmode > 3)
+			printk(KERN_DEBUG "capidrv-%d: sendbuf putmsg ret(%x) - %s\n",
+				card->contrnr, errcode, capi_info2str(errcode));
 	        (void)capidrv_del_ack(nccip, datahandle);
 	        dev_kfree_skb(nskb);
 		return errcode == CAPI_SENDQUEUEFULL ? 0 : -1;
@@ -1876,6 +1883,9 @@ static int if_sendbuf(int id, int channe
 			nccip->datahandle++;
 			return len;
 		}
+		if (debugmode > 3)
+			printk(KERN_DEBUG "capidrv-%d: sendbuf putmsg ret(%x) - %s\n",
+				card->contrnr, errcode, capi_info2str(errcode));
 		skb_pull(skb, msglen);
 	        (void)capidrv_del_ack(nccip, datahandle);
 		return errcode == CAPI_SENDQUEUEFULL ? 0 : -1;
--- diff/drivers/isdn/capi/capifs.c	2003-10-09 09:47:16.000000000 +0100
+++ source/drivers/isdn/capi/capifs.c	2004-02-23 13:56:42.000000000 +0000
@@ -1,4 +1,4 @@
-/* $Id: capifs.c,v 1.14.6.8 2001/09/23 22:24:33 kai Exp $
+/* $Id: capifs.c,v 1.1.2.3 2004/01/16 21:09:26 keil Exp $
  * 
  * Copyright 2000 by Carsten Paeth <calle@calle.de>
  *
@@ -20,99 +20,75 @@ MODULE_DESCRIPTION("CAPI4Linux: /dev/cap
 MODULE_AUTHOR("Carsten Paeth");
 MODULE_LICENSE("GPL");
 
-static char *revision = "$Revision: 1.14.6.8 $";
+/* ------------------------------------------------------------------ */
+
+static char *revision = "$Revision: 1.1.2.3 $";
+
+/* ------------------------------------------------------------------ */
 
-struct options {
+#define CAPIFS_SUPER_MAGIC (('C'<<8)|'N')
+
+static struct vfsmount *capifs_mnt;
+static struct dentry *capifs_root;
+
+static struct {
 	int setuid;
 	int setgid;
 	uid_t   uid;
 	gid_t   gid;
 	umode_t mode;
-};
-static struct options options = {.mode = 0600};
-
-#define CAPIFS_SUPER_MAGIC (('C'<<8)|'N')
+} config = {.mode = 0600};
 
 /* ------------------------------------------------------------------ */
 
-
-static int capifs_parse_options(char *s, struct options *p)
+static int capifs_remount(struct super_block *s, int *flags, char *data)
 {
 	int setuid = 0;
 	int setgid = 0;
 	uid_t uid = 0;
 	gid_t gid = 0;
 	umode_t mode = 0600;
-	char *this_char, *value;
+	char *this_char;
 
-	if (!s)
-		return 0;
-
-	while ((this_char = strsep(&s, ",")) != NULL) {
+	this_char = NULL;
+	while ((this_char = strsep(&data, ",")) != NULL) {
+		int n;
+		char dummy;
 		if (!*this_char)
 			continue;
-		if ((value = strchr(this_char,'=')) != NULL)
-			*value++ = 0;
-		if (!strcmp(this_char,"uid")) {
-			if (!value || !*value)
-				return 1;
-			uid = simple_strtoul(value,&value,0);
-			if (*value)
-				return 1;
+		if (sscanf(this_char, "uid=%i%c", &n, &dummy) == 1) {
 			setuid = 1;
-		}
-		else if (!strcmp(this_char,"gid")) {
-			if (!value || !*value)
-				return 1;
-			gid = simple_strtoul(value,&value,0);
-			if (*value)
-				return 1;
+			uid = n;
+		} else if (sscanf(this_char, "gid=%i%c", &n, &dummy) == 1) {
 			setgid = 1;
+			gid = n;
+		} else if (sscanf(this_char, "mode=%o%c", &n, &dummy) == 1)
+			mode = n & ~S_IFMT;
+		else {
+			printk("capifs: called with bogus options\n");
+			return -EINVAL;
 		}
-		else if (!strcmp(this_char,"mode")) {
-			if (!value || !*value)
-				return 1;
-			mode = simple_strtoul(value,&value,8);
-			if (*value)
-				return 1;
-		}
-	}
-	p->setuid   = setuid;
-	p->setgid   = setgid;
-	p->uid      = uid;
-	p->gid      = gid;
-	p->mode     = mode & ~S_IFMT;
-
-	return 0;
-}
-
-static int capifs_remount(struct super_block *s, int *flags, char *data)
-{
-	struct options new;
-	if (capifs_parse_options(data, &new)) {
-		printk("capifs: called with bogus options\n");
-		return -EINVAL;
 	}
-	options = new;
+	config.setuid  = setuid;
+	config.setgid  = setgid;
+	config.uid     = uid;
+	config.gid     = gid;
+	config.mode    = mode;
 	return 0;
 }
 
-
 static struct super_operations capifs_sops =
 {
 	.statfs		= simple_statfs,
 	.remount_fs	= capifs_remount,
 };
 
-static int capifs_fill_super(struct super_block *s, void *data, int silent)
+
+static int
+capifs_fill_super(struct super_block *s, void *data, int silent)
 {
 	struct inode * inode;
 
-	if (capifs_parse_options(data, &options)) {
-		printk("capifs: called with bogus options\n");
-		return -EINVAL;
-	}
-
 	s->s_blocksize = 1024;
 	s->s_blocksize_bits = 10;
 	s->s_magic = CAPIFS_SUPER_MAGIC;
@@ -120,24 +96,25 @@ static int capifs_fill_super(struct supe
 
 	inode = new_inode(s);
 	if (!inode)
-		return -ENOMEM;
+		goto fail;
+	inode->i_ino = 1;
 	inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
 	inode->i_blocks = 0;
 	inode->i_blksize = 1024;
 	inode->i_uid = inode->i_gid = 0;
-	inode->i_ino = 1;
 	inode->i_mode = S_IFDIR | S_IRUGO | S_IXUGO | S_IWUSR;
 	inode->i_op = &simple_dir_inode_operations;
 	inode->i_fop = &simple_dir_operations;
 	inode->i_nlink = 2;
-	s->s_root = d_alloc_root(inode);
 
-	if (!s->s_root) {
-		printk("capifs: get root dentry failed\n");
-		iput(inode);
-		return -ENOMEM;
-	}
-	return 0;
+	capifs_root = s->s_root = d_alloc_root(inode);
+	if (s->s_root)
+		return 0;
+	
+	printk("capifs: get root dentry failed\n");
+	iput(inode);
+fail:
+	return -ENOMEM;
 }
 
 static struct super_block *capifs_get_sb(struct file_system_type *fs_type,
@@ -153,78 +130,48 @@ static struct file_system_type capifs_fs
 	.kill_sb	= kill_anon_super,
 };
 
-static struct vfsmount *capifs_mnt;
-static int entry_count;
-
-static int grab_instance(void)
-{
-	return simple_pin_fs("capifs", &capifs_mnt, &entry_count);
-}
-
-static void drop_instance(void)
-{
-	return simple_release_fs(&capifs_mnt, &entry_count);
-}
-
-static struct dentry *get_node(int type, int num)
+static struct dentry *get_node(int num)
 {
 	char s[10];
-	int len;
-	struct dentry *root = capifs_mnt->mnt_root;
-	if (type)
-		len = sprintf(s, "%d", num);
-	else
-		len = sprintf(s, "%c%d", type, num);
+	struct dentry *root = capifs_root;
 	down(&root->d_inode->i_sem);
-	return lookup_one_len(s, root, len);
+	return lookup_one_len(s, root, sprintf(s, "%d", num));
 }
 
-void capifs_new_ncci(char type, unsigned int num, dev_t device)
+void capifs_new_ncci(unsigned int number, dev_t device)
 {
-	struct super_block *sb;
 	struct dentry *dentry;
-	struct inode *inode;
-
-	if (grab_instance() < 0)
+	struct inode *inode = new_inode(capifs_mnt->mnt_sb);
+	if (!inode)
 		return;
-	sb = capifs_mnt->mnt_sb;
-	inode = new_inode(sb);
-	if (inode) {
-		inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
-		inode->i_blocks = 0;
-		inode->i_blksize = 1024;
-		inode->i_uid = options.setuid ? options.uid : current->fsuid;
-		inode->i_gid = options.setgid ? options.gid : current->fsgid;
-		inode->i_nlink = 1;
-		init_special_inode(inode, S_IFCHR | options.mode, device);
-		dentry = get_node(type, num);
-		if (!IS_ERR(dentry) && !dentry->d_inode) {
-			grab_instance();
-			d_instantiate(dentry, inode);
-		} else
-			iput(inode);
-		up(&sb->s_root->d_inode->i_sem);
-	}
-	drop_instance();
+	inode->i_ino = number+2;
+	inode->i_blksize = 1024;
+	inode->i_uid = config.setuid ? config.uid : current->fsuid;
+	inode->i_gid = config.setgid ? config.gid : current->fsgid;
+	inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
+	init_special_inode(inode, S_IFCHR|config.mode, device);
+	//inode->i_op = &capifs_file_inode_operations;
+
+	dentry = get_node(number);
+	if (!IS_ERR(dentry) && !dentry->d_inode)
+		d_instantiate(dentry, inode);
+	up(&capifs_root->d_inode->i_sem);
 }
 
-void capifs_free_ncci(char type, unsigned int num)
+void capifs_free_ncci(unsigned int number)
 {
-	if (grab_instance() == 0) {
-		struct dentry *dentry = get_node(type, num);
-		if (!IS_ERR(dentry)) {
-			struct inode *inode = dentry->d_inode;
-			if (inode) {
-				inode->i_nlink--;
-				d_delete(dentry);
-				dput(dentry);
-				drop_instance();
-			}
+	struct dentry *dentry = get_node(number);
+
+	if (!IS_ERR(dentry)) {
+		struct inode *inode = dentry->d_inode;
+		if (inode) {
+			inode->i_nlink--;
+			d_delete(dentry);
 			dput(dentry);
 		}
-		up(&capifs_mnt->mnt_root->d_inode->i_sem);
-		drop_instance();
+		dput(dentry);
 	}
+	up(&capifs_root->d_inode->i_sem);
 }
 
 static int __init capifs_init(void)
@@ -241,14 +188,20 @@ static int __init capifs_init(void)
 		strcpy(rev, "1.0");
 
 	err = register_filesystem(&capifs_fs_type);
+	if (!err) {
+		capifs_mnt = kern_mount(&capifs_fs_type);
+		if (IS_ERR(capifs_mnt))
+			err = PTR_ERR(capifs_mnt);
+	}
 	if (!err)
 		printk(KERN_NOTICE "capifs: Rev %s\n", rev);
-	return 0;
+	return err;
 }
 
 static void __exit capifs_exit(void)
 {
 	unregister_filesystem(&capifs_fs_type);
+	mntput(capifs_mnt);
 }
 
 EXPORT_SYMBOL(capifs_new_ncci);
--- diff/drivers/isdn/capi/capifs.h	2003-05-21 11:50:15.000000000 +0100
+++ source/drivers/isdn/capi/capifs.h	2004-02-23 13:56:42.000000000 +0000
@@ -1,4 +1,4 @@
-/* $Id: capifs.h,v 1.2.6.2 2001/09/23 22:24:33 kai Exp $
+/* $Id: capifs.h,v 1.1.2.2 2004/01/16 21:09:26 keil Exp $
  * 
  * Copyright 2000 by Carsten Paeth <calle@calle.de>
  *
@@ -7,5 +7,5 @@
  *
  */
 
-void capifs_new_ncci(char type, unsigned int num, dev_t device);
-void capifs_free_ncci(char type, unsigned int num);
+void capifs_new_ncci(unsigned int num, dev_t device);
+void capifs_free_ncci(unsigned int num);
--- diff/drivers/isdn/capi/kcapi.c	2003-10-27 09:20:43.000000000 +0000
+++ source/drivers/isdn/capi/kcapi.c	2004-02-23 13:56:42.000000000 +0000
@@ -1,4 +1,4 @@
-/* $Id: kcapi.c,v 1.21.6.8 2001/09/23 22:24:33 kai Exp $
+/* $Id: kcapi.c,v 1.1.2.4 2004/02/10 01:07:11 keil Exp $
  * 
  * Kernel CAPI 2.0 Module
  * 
@@ -31,7 +31,7 @@
 #include <linux/b1lli.h>
 #endif
 
-static char *revision = "$Revision: 1.21.6.8 $";
+static char *revision = "$Revision: 1.1.2.4 $";
 
 /* ------------------------------------------------------------- */
 
@@ -61,7 +61,7 @@ static char capi_manufakturer[64] = "AVM
 #define NCCI2CTRL(ncci)    (((ncci) >> 24) & 0x7f)
 
 LIST_HEAD(capi_drivers);
-spinlock_t capi_drivers_lock = SPIN_LOCK_UNLOCKED;
+rwlock_t capi_drivers_list_lock = RW_LOCK_UNLOCKED;
 
 struct capi20_appl *capi_applications[CAPI_MAXAPPL];
 struct capi_ctr *capi_cards[CAPI_MAXCONTR];
@@ -309,12 +309,10 @@ static void recv_handler(void *dummy)
 			continue;
 		}
 
-		if (   CAPIMSG_COMMAND(skb->data) == CAPI_DATA_B3
-		    && CAPIMSG_SUBCOMMAND(skb->data) == CAPI_IND) {
+		if (CAPIMSG_CMD(skb->data) == CAPI_DATA_B3_IND)
 			ap->nrecvdatapkt++;
-		} else {
+		else
 			ap->nrecvctlpkt++;
-		}
 		ap->recv_message(ap, skb);
 	}
 }
@@ -498,6 +496,28 @@ int detach_capi_ctr(struct capi_ctr *car
 
 EXPORT_SYMBOL(detach_capi_ctr);
 
+void register_capi_driver(struct capi_driver *driver)
+{
+	unsigned long flags;
+
+	write_lock_irqsave(&capi_drivers_list_lock, flags);
+	list_add_tail(&driver->list, &capi_drivers);
+	write_unlock_irqrestore(&capi_drivers_list_lock, flags);
+}
+
+EXPORT_SYMBOL(register_capi_driver);
+
+void unregister_capi_driver(struct capi_driver *driver)
+{
+	unsigned long flags;
+
+	write_lock_irqsave(&capi_drivers_list_lock, flags);
+	list_del(&driver->list);
+	write_unlock_irqrestore(&capi_drivers_list_lock, flags);
+}
+
+EXPORT_SYMBOL(unregister_capi_driver);
+
 /* ------------------------------------------------------------- */
 /* -------- CAPI2.0 Interface ---------------------------------- */
 /* ------------------------------------------------------------- */
@@ -704,12 +724,68 @@ EXPORT_SYMBOL(capi20_get_profile);
 static int old_capi_manufacturer(unsigned int cmd, void *data)
 {
 	avmb1_loadandconfigdef ldef;
+	avmb1_extcarddef cdef;
 	avmb1_resetdef rdef;
+	capicardparams cparams;
 	struct capi_ctr *card;
+	struct capi_driver *driver = 0;
 	capiloaddata ldata;
+	struct list_head *l;
+	unsigned long flags;
 	int retval;
 
 	switch (cmd) {
+	case AVMB1_ADDCARD:
+	case AVMB1_ADDCARD_WITH_TYPE:
+		if (cmd == AVMB1_ADDCARD) {
+		   if ((retval = copy_from_user((void *) &cdef, data,
+					    sizeof(avmb1_carddef))))
+			   return retval;
+		   cdef.cardtype = AVM_CARDTYPE_B1;
+		} else {
+		   if ((retval = copy_from_user((void *) &cdef, data,
+					    sizeof(avmb1_extcarddef))))
+			   return retval;
+		}
+		cparams.port = cdef.port;
+		cparams.irq = cdef.irq;
+		cparams.cardnr = cdef.cardnr;
+
+		read_lock_irqsave(&capi_drivers_list_lock, flags);
+                switch (cdef.cardtype) {
+			case AVM_CARDTYPE_B1:
+				list_for_each(l, &capi_drivers) {
+					driver = list_entry(l, struct capi_driver, list);
+					if (strcmp(driver->name, "b1isa") == 0)
+						break;
+				}
+				break;
+			case AVM_CARDTYPE_T1:
+				list_for_each(l, &capi_drivers) {
+					driver = list_entry(l, struct capi_driver, list);
+					if (strcmp(driver->name, "t1isa") == 0)
+						break;
+				}
+				break;
+			default:
+				driver = 0;
+				break;
+		}
+		if (!driver) {
+			read_unlock_irqrestore(&capi_drivers_list_lock, flags);
+			printk(KERN_ERR "kcapi: driver not loaded.\n");
+			return -EIO;
+		}
+		if (!driver->add_card) {
+			read_unlock_irqrestore(&capi_drivers_list_lock, flags);
+			printk(KERN_ERR "kcapi: driver has no add card function.\n");
+			return -EIO;
+		}
+
+		retval = driver->add_card(driver, &cparams);
+		read_unlock_irqrestore(&capi_drivers_list_lock, flags);
+		return retval;
+
 	case AVMB1_LOAD:
 	case AVMB1_LOAD_AND_CONFIG:
 
@@ -832,6 +908,43 @@ int capi20_manufacturer(unsigned int cmd
 			card->cnr, card->traceflag);
 		return 0;
 	}
+	case KCAPI_CMD_ADDCARD:
+	{
+		struct list_head *l;
+		struct capi_driver *driver = 0;
+		capicardparams cparams;
+		kcapi_carddef cdef;
+		int retval;
+
+		if ((retval = copy_from_user((void *) &cdef, data,
+							sizeof(cdef))))
+			return retval;
+
+		cparams.port = cdef.port;
+		cparams.irq = cdef.irq;
+		cparams.membase = cdef.membase;
+		cparams.cardnr = cdef.cardnr;
+		cparams.cardtype = 0;
+		cdef.driver[sizeof(cdef.driver)-1] = 0;
+
+		list_for_each(l, &capi_drivers) {
+			driver = list_entry(l, struct capi_driver, list);
+			if (strcmp(driver->name, cdef.driver) == 0)
+				break;
+		}
+		if (driver == 0) {
+			printk(KERN_ERR "kcapi: driver \"%s\" not loaded.\n",
+					cdef.driver);
+			return -ESRCH;
+		}
+
+		if (!driver->add_card) {
+			printk(KERN_ERR "kcapi: driver \"%s\" has no add card function.\n", cdef.driver);
+			return -EIO;
+		}
+
+		return driver->add_card(driver, &cparams);
+	}
 
 	default:
 		printk(KERN_ERR "kcapi: manufacturer command %d unknown.\n",
--- diff/drivers/isdn/capi/kcapi.h	2002-10-16 04:27:48.000000000 +0100
+++ source/drivers/isdn/capi/kcapi.h	2004-02-23 13:56:42.000000000 +0000
@@ -15,10 +15,13 @@
 #include <linux/list.h>
 #include <linux/isdn/capilli.h>
 
+#ifdef KCAPI_DEBUG
 #define DBG(format, arg...) do { \
 printk(KERN_DEBUG "%s: " format "\n" , __FUNCTION__ , ## arg); \
 } while (0)
-
+#else
+#define DBG(format, arg...) /* */
+#endif
 
 enum {
 	CARD_DETECTED = 1,
@@ -27,7 +30,7 @@ enum {
 };
 
 extern struct list_head capi_drivers;
-extern spinlock_t capi_drivers_lock;
+extern rwlock_t capi_drivers_list_lock;
 
 extern struct capi20_appl *capi_applications[CAPI_MAXAPPL];
 extern struct capi_ctr *capi_cards[CAPI_MAXCONTR];
--- diff/drivers/isdn/capi/kcapi_proc.c	2002-10-16 04:28:22.000000000 +0100
+++ source/drivers/isdn/capi/kcapi_proc.c	2004-02-23 13:56:42.000000000 +0000
@@ -243,16 +243,84 @@ create_seq_entry(char *name, mode_t mode
 
 // ---------------------------------------------------------------------------
 
+
+static __inline__ struct capi_driver *capi_driver_get_idx(loff_t pos)
+{
+	struct capi_driver *drv = 0;
+	struct list_head *l;
+	loff_t i;
+
+	i = 0;
+	list_for_each(l, &capi_drivers) {
+		drv = list_entry(l, struct capi_driver, list);
+		if (i++ == pos)
+			return drv;
+	}
+	return 0;
+}
+
+static void *capi_driver_start(struct seq_file *seq, loff_t *pos)
+{
+	struct capi_driver *drv;
+	read_lock(&capi_drivers_list_lock);
+	drv = capi_driver_get_idx(*pos);
+	return drv;
+}
+
+static void *capi_driver_next(struct seq_file *seq, void *v, loff_t *pos)
+{
+	struct capi_driver *drv = (struct capi_driver *)v;
+	++*pos;
+	if (drv->list.next == &capi_drivers) return 0;
+	return list_entry(drv->list.next, struct capi_driver, list);
+}
+
+static void capi_driver_stop(struct seq_file *seq, void *v)
+{
+	read_unlock(&capi_drivers_list_lock);
+}
+
+static int capi_driver_show(struct seq_file *seq, void *v)
+{
+	struct capi_driver *drv = (struct capi_driver *)v;
+	seq_printf(seq, "%-32s %s\n", drv->name, drv->revision);
+	return 0;
+}
+
+struct seq_operations seq_capi_driver_ops = {
+	.start	= capi_driver_start,
+	.next	= capi_driver_next,
+	.stop	= capi_driver_stop,
+	.show	= capi_driver_show,
+};
+
+static int
+seq_capi_driver_open(struct inode *inode, struct file *file)
+{
+	int err;
+	err = seq_open(file, &seq_capi_driver_ops);
+	return err;
+}
+
+static struct file_operations proc_driver_ops = {
+	.open		= seq_capi_driver_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= seq_release,
+};
+
+// ---------------------------------------------------------------------------
+
 void __init 
 kcapi_proc_init(void)
 {
 	proc_mkdir("capi",             NULL);
 	proc_mkdir("capi/controllers", NULL);
-	proc_mkdir("capi/drivers",     NULL);
 	create_seq_entry("capi/controller",   0, &proc_controller_ops);
 	create_seq_entry("capi/contrstats",   0, &proc_contrstats_ops);
 	create_seq_entry("capi/applications", 0, &proc_applications_ops);
 	create_seq_entry("capi/applstats",    0, &proc_applstats_ops);
+	create_seq_entry("capi/driver",       0, &proc_driver_ops);
 }
 
 void __exit
@@ -263,7 +331,6 @@ kcapi_proc_exit(void)
 	remove_proc_entry("capi/contrstats",   NULL);
 	remove_proc_entry("capi/applications", NULL);
 	remove_proc_entry("capi/applstats",    NULL);
-	remove_proc_entry("capi/drivers",      NULL);
 	remove_proc_entry("capi/controllers",  NULL);
 	remove_proc_entry("capi",              NULL);
 }
--- diff/drivers/isdn/hardware/Kconfig	2004-02-09 10:36:10.000000000 +0000
+++ source/drivers/isdn/hardware/Kconfig	2004-02-23 13:56:42.000000000 +0000
@@ -2,32 +2,9 @@
 # ISDN hardware drivers
 #
 comment "CAPI hardware drivers"
-	depends on NET && ISDN_BOOL && ISDN_CAPI
+	depends on NET && ISDN && ISDN_CAPI
 
 source "drivers/isdn/hardware/avm/Kconfig"
 
 source "drivers/isdn/hardware/eicon/Kconfig"
 
-comment "ISDN4Linux hardware drivers"
-	depends on NET && ISDN_BOOL && ISDN
-
-source "drivers/isdn/hisax/Kconfig"
-
-
-menu "Active cards"
-	depends on NET && ISDN_BOOL && ISDN!=n
-
-source "drivers/isdn/icn/Kconfig"
-
-source "drivers/isdn/pcbit/Kconfig"
-
-source "drivers/isdn/sc/Kconfig"
-
-source "drivers/isdn/act2000/Kconfig"
-
-source "drivers/isdn/tpam/Kconfig"
-
-source "drivers/isdn/hysdn/Kconfig"
-
-endmenu
-
--- diff/drivers/isdn/hardware/avm/Kconfig	2003-09-17 12:28:06.000000000 +0100
+++ source/drivers/isdn/hardware/avm/Kconfig	2004-02-23 13:56:42.000000000 +0000
@@ -3,7 +3,7 @@
 #
 
 menu "Active AVM cards"
-	depends on NET && ISDN_BOOL && ISDN_CAPI!=n
+	depends on NET && ISDN && ISDN_CAPI!=n
 
 config CAPI_AVM
 	bool "Support AVM cards"
--- diff/drivers/isdn/hardware/avm/b1.c	2003-09-17 12:28:06.000000000 +0100
+++ source/drivers/isdn/hardware/avm/b1.c	2004-02-23 13:56:42.000000000 +0000
@@ -1,4 +1,4 @@
-/* $Id: b1.c,v 1.1.4.1.2.1 2001/12/21 15:00:17 kai Exp $
+/* $Id: b1.c,v 1.1.2.2 2004/01/16 21:09:27 keil Exp $
  * 
  * Common module for AVM B1 cards.
  * 
@@ -28,7 +28,7 @@
 #include <linux/isdn/capicmd.h>
 #include <linux/isdn/capiutil.h>
 
-static char *revision = "$Revision: 1.1.4.1.2.1 $";
+static char *revision = "$Revision: 1.1.2.2 $";
 
 /* ------------------------------------------------------------- */
 
@@ -76,7 +76,7 @@ avmcard *b1_alloc_card(int nr_controller
 		kfree(card);
 		return 0;
 	}
-	memset(cinfo, 0, sizeof(*cinfo));
+	memset(cinfo, 0, sizeof(*cinfo) * nr_controllers);
 
 	card->ctrlinfo = cinfo;
 	for (i = 0; i < nr_controllers; i++) {
@@ -308,14 +308,13 @@ int b1_load_firmware(struct capi_ctr *ct
 		return -EIO;
 	}
 
-	save_flags(flags);
-	cli();
+	spin_lock_irqsave(&card->lock, flags);
 	b1_setinterrupt(port, card->irq, card->cardtype);
 	b1_put_byte(port, SEND_INIT);
 	b1_put_word(port, CAPI_MAXAPPL);
 	b1_put_word(port, AVM_NCCI_PER_CHANNEL*2);
 	b1_put_word(port, ctrl->cnr - 1);
-	restore_flags(flags);
+	spin_unlock_irqrestore(&card->lock, flags);
 
 	return 0;
 }
@@ -348,15 +347,14 @@ void b1_register_appl(struct capi_ctr *c
 	else nconn = ctrl->profile.nbchannel * -want;
 	if (nconn == 0) nconn = ctrl->profile.nbchannel;
 
-	save_flags(flags);
-	cli();
+	spin_lock_irqsave(&card->lock, flags);
 	b1_put_byte(port, SEND_REGISTER);
 	b1_put_word(port, appl);
 	b1_put_word(port, 1024 * (nconn+1));
 	b1_put_word(port, nconn);
 	b1_put_word(port, rp->datablkcnt);
 	b1_put_word(port, rp->datablklen);
-	restore_flags(flags);
+	spin_unlock_irqrestore(&card->lock, flags);
 }
 
 void b1_release_appl(struct capi_ctr *ctrl, u16 appl)
@@ -368,11 +366,10 @@ void b1_release_appl(struct capi_ctr *ct
 
 	capilib_release_appl(&cinfo->ncci_head, appl);
 
-	save_flags(flags);
-	cli();
+	spin_lock_irqsave(&card->lock, flags);
 	b1_put_byte(port, SEND_RELEASE);
 	b1_put_word(port, appl);
-	restore_flags(flags);
+	spin_unlock_irqrestore(&card->lock, flags);
 }
 
 u16 b1_send_message(struct capi_ctr *ctrl, struct sk_buff *skb)
@@ -396,20 +393,18 @@ u16 b1_send_message(struct capi_ctr *ctr
 
 		dlen = CAPIMSG_DATALEN(skb->data);
 
-		save_flags(flags);
-		cli();
+	 	spin_lock_irqsave(&card->lock, flags);
 		b1_put_byte(port, SEND_DATA_B3_REQ);
 		b1_put_slice(port, skb->data, len);
 		b1_put_slice(port, skb->data + len, dlen);
-		restore_flags(flags);
+		spin_unlock_irqrestore(&card->lock, flags);
 	} else {
 		retval = CAPI_NOERROR;
 
-		save_flags(flags);
-		cli();
+	 	spin_lock_irqsave(&card->lock, flags);
 		b1_put_byte(port, SEND_MESSAGE);
 		b1_put_slice(port, skb->data, len);
-		restore_flags(flags);
+		spin_unlock_irqrestore(&card->lock, flags);
 	}
  out:
 	dev_kfree_skb_any(skb);
@@ -505,9 +500,14 @@ irqreturn_t b1_interrupt(int interrupt, 
 	unsigned DataB3Len;
 	unsigned NCCI;
 	unsigned WindowSize;
+	unsigned long flags;
+
+	spin_lock_irqsave(&card->lock, flags);
 
-	if (!b1_rx_full(card->port))
-	   return IRQ_NONE;
+	if (!b1_rx_full(card->port)) {
+		spin_unlock_irqrestore(&card->lock, flags);
+		return IRQ_NONE;
+	}
 
 	b1cmd = b1_get_byte(card->port);
 
@@ -518,6 +518,7 @@ irqreturn_t b1_interrupt(int interrupt, 
 		ApplId = (unsigned) b1_get_word(card->port);
 		MsgLen = b1_get_slice(card->port, card->msgbuf);
 		DataB3Len = b1_get_slice(card->port, card->databuf);
+		spin_unlock_irqrestore(&card->lock, flags);
 
 		if (MsgLen < 30) { /* not CAPI 64Bit */
 			memset(card->msgbuf+MsgLen, 0, 30-MsgLen);
@@ -538,6 +539,7 @@ irqreturn_t b1_interrupt(int interrupt, 
 
 		ApplId = (unsigned) b1_get_word(card->port);
 		MsgLen = b1_get_slice(card->port, card->msgbuf);
+		spin_unlock_irqrestore(&card->lock, flags);
 		if (!(skb = alloc_skb(MsgLen, GFP_ATOMIC))) {
 			printk(KERN_ERR "%s: incoming packet dropped\n",
 					card->name);
@@ -557,6 +559,7 @@ irqreturn_t b1_interrupt(int interrupt, 
 		ApplId = b1_get_word(card->port);
 		NCCI = b1_get_word(card->port);
 		WindowSize = b1_get_word(card->port);
+		spin_unlock_irqrestore(&card->lock, flags);
 
 		capilib_new_ncci(&cinfo->ncci_head, ApplId, NCCI, WindowSize);
 
@@ -566,6 +569,7 @@ irqreturn_t b1_interrupt(int interrupt, 
 
 		ApplId = b1_get_word(card->port);
 		NCCI = b1_get_word(card->port);
+		spin_unlock_irqrestore(&card->lock, flags);
 
 		if (NCCI != 0xffffffff)
 			capilib_free_ncci(&cinfo->ncci_head, ApplId, NCCI);
@@ -574,16 +578,19 @@ irqreturn_t b1_interrupt(int interrupt, 
 
 	case RECEIVE_START:
 	   	/* b1_put_byte(card->port, SEND_POLLACK); */
+		spin_unlock_irqrestore(&card->lock, flags);
 		capi_ctr_resume_output(ctrl);
 		break;
 
 	case RECEIVE_STOP:
+		spin_unlock_irqrestore(&card->lock, flags);
 		capi_ctr_suspend_output(ctrl);
 		break;
 
 	case RECEIVE_INIT:
 
 		cinfo->versionlen = b1_get_slice(card->port, cinfo->versionbuf);
+		spin_unlock_irqrestore(&card->lock, flags);
 		b1_parse_version(cinfo);
 		printk(KERN_INFO "%s: %s-card (%s) now active\n",
 		       card->name,
@@ -595,6 +602,7 @@ irqreturn_t b1_interrupt(int interrupt, 
 	case RECEIVE_TASK_READY:
 		ApplId = (unsigned) b1_get_word(card->port);
 		MsgLen = b1_get_slice(card->port, card->msgbuf);
+		spin_unlock_irqrestore(&card->lock, flags);
 		card->msgbuf[MsgLen] = 0;
 		while (    MsgLen > 0
 		       && (   card->msgbuf[MsgLen-1] == '\n'
@@ -608,6 +616,7 @@ irqreturn_t b1_interrupt(int interrupt, 
 
 	case RECEIVE_DEBUGMSG:
 		MsgLen = b1_get_slice(card->port, card->msgbuf);
+		spin_unlock_irqrestore(&card->lock, flags);
 		card->msgbuf[MsgLen] = 0;
 		while (    MsgLen > 0
 		       && (   card->msgbuf[MsgLen-1] == '\n'
@@ -619,9 +628,11 @@ irqreturn_t b1_interrupt(int interrupt, 
 		break;
 
 	case 0xff:
+		spin_unlock_irqrestore(&card->lock, flags);
 		printk(KERN_ERR "%s: card removed ?\n", card->name);
 		return IRQ_NONE;
 	default:
+		spin_unlock_irqrestore(&card->lock, flags);
 		printk(KERN_ERR "%s: b1_interrupt: 0x%x ???\n",
 				card->name, b1cmd);
 		return IRQ_HANDLED;
--- diff/drivers/isdn/hardware/avm/b1dma.c	2003-06-09 14:18:18.000000000 +0100
+++ source/drivers/isdn/hardware/avm/b1dma.c	2004-02-23 13:56:42.000000000 +0000
@@ -1,4 +1,4 @@
-/* $Id: b1dma.c,v 1.1.4.1.2.1 2001/12/21 15:00:17 kai Exp $
+/* $Id: b1dma.c,v 1.1.2.3 2004/02/10 01:07:12 keil Exp $
  * 
  * Common module for AVM B1 cards that support dma with AMCC
  * 
@@ -28,11 +28,9 @@
 #include <linux/isdn/capicmd.h>
 #include <linux/isdn/capiutil.h>
 
-#if BITS_PER_LONG != 32
-#error FIXME: driver requires 32-bit platform
-#endif
+static char *revision = "$Revision: 1.1.2.3 $";
 
-static char *revision = "$Revision: 1.1.4.1.2.1 $";
+#undef CONFIG_B1DMA_DEBUG
 
 /* ------------------------------------------------------------- */
 
@@ -239,7 +237,7 @@ void b1dma_reset(avmcard *card)
 
 /* ------------------------------------------------------------- */
 
-int b1dma_detect(avmcard *card)
+static int b1dma_detect(avmcard *card)
 {
 	b1dma_writel(card, 0, AMCC_MCSR);
 	mdelay(10);
@@ -578,11 +576,16 @@ static void b1dma_handle_rx(avmcard *car
 
 static void b1dma_handle_interrupt(avmcard *card)
 {
-	u32 status = b1dma_readl(card, AMCC_INTCSR);
+	u32 status;
 	u32 newcsr;
 
-	if ((status & ANY_S5933_INT) == 0) 
+	spin_lock(&card->lock);
+
+	status = b1dma_readl(card, AMCC_INTCSR);
+	if ((status & ANY_S5933_INT) == 0) {
+		spin_unlock(&card->lock);
 		return;
+	}
 
         newcsr = card->csr | (status & ALL_INT);
 	if (status & TX_TC_INT) newcsr &= ~EN_TX_TC_INT;
@@ -593,20 +596,28 @@ static void b1dma_handle_interrupt(avmca
 		struct avmcard_dmainfo *dma = card->dma;
 		u32 rxlen;
 	   	if (card->dma->recvlen == 0) {
-			dma->recvlen = *((u32 *)dma->recvbuf.dmabuf);
-			rxlen = (dma->recvlen + 3) & ~3;
-			b1dma_writel(card, dma->recvbuf.dmaaddr+4, AMCC_RXPTR);
-			b1dma_writel(card, rxlen, AMCC_RXLEN);
+	        	rxlen = b1dma_readl(card, AMCC_RXLEN);
+			if (rxlen == 0) {
+				dma->recvlen = *((u32 *)dma->recvbuf.dmabuf);
+				rxlen = (dma->recvlen + 3) & ~3;
+				b1dma_writel(card, dma->recvbuf.dmaaddr+4, AMCC_RXPTR);
+				b1dma_writel(card, rxlen, AMCC_RXLEN);
+#ifdef CONFIG_B1DMA_DEBUG
+			} else {
+				printk(KERN_ERR "%s: rx not complete (%d).\n",
+					card->name, rxlen);
+#endif
+			}
 		} else {
+			spin_unlock(&card->lock);
 			b1dma_handle_rx(card);
 	   		dma->recvlen = 0;
+			spin_lock(&card->lock);
 			b1dma_writel(card, dma->recvbuf.dmaaddr, AMCC_RXPTR);
 			b1dma_writel(card, 4, AMCC_RXLEN);
 		}
 	}
 
-	spin_lock(&card->lock);
-
 	if ((status & TX_TC_INT) != 0) {
 		if (skb_queue_empty(&card->dma->send_queue))
 			card->csr &= ~EN_TX_TC_INT;
@@ -736,18 +747,19 @@ void b1dma_reset_ctr(struct capi_ctr *ct
 {
 	avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata);
 	avmcard *card = cinfo->card;
+	unsigned long flags;
 
+	spin_lock_irqsave(&card->lock, flags);
  	b1dma_reset(card);
+	spin_unlock_irqrestore(&card->lock, flags);
 
 	memset(cinfo->version, 0, sizeof(cinfo->version));
 	capilib_release(&cinfo->ncci_head);
 	capi_ctr_reseted(ctrl);
 }
 
-
 /* ------------------------------------------------------------- */
 
-
 void b1dma_register_appl(struct capi_ctr *ctrl,
 				u16 appl,
 				capi_register_params *rp)
@@ -844,6 +856,7 @@ int b1dmactl_read_proc(char *page, char 
 	int len = 0;
 	char *s;
 	u32 txoff, txlen, rxoff, rxlen, csr;
+	unsigned long flags;
 
 	len += sprintf(page+len, "%-16s %s\n", "name", card->name);
 	len += sprintf(page+len, "%-16s 0x%x\n", "io", card->port);
@@ -896,6 +909,9 @@ int b1dmactl_read_proc(char *page, char 
 	}
 	len += sprintf(page+len, "%-16s %s\n", "cardname", cinfo->cardname);
 
+
+	spin_lock_irqsave(&card->lock, flags);
+
 	txoff = (dma_addr_t)b1dma_readl(card, AMCC_TXPTR)-card->dma->sendbuf.dmaaddr;
 	txlen = b1dma_readl(card, AMCC_TXLEN);
 
@@ -904,6 +920,8 @@ int b1dmactl_read_proc(char *page, char 
 
 	csr  = b1dma_readl(card, AMCC_INTCSR);
 
+	spin_unlock_irqrestore(&card->lock, flags);
+
         len += sprintf(page+len, "%-16s 0x%lx\n",
 				"csr (cached)", (unsigned long)card->csr);
         len += sprintf(page+len, "%-16s 0x%lx\n",
--- diff/drivers/isdn/hardware/avm/b1isa.c	2003-08-20 14:16:28.000000000 +0100
+++ source/drivers/isdn/hardware/avm/b1isa.c	2004-02-23 13:56:42.000000000 +0000
@@ -1,4 +1,4 @@
-/* $Id: b1isa.c,v 1.10.6.6 2001/09/23 22:24:33 kai Exp $
+/* $Id: b1isa.c,v 1.1.2.3 2004/02/10 01:07:12 keil Exp $
  * 
  * Module for AVM B1 ISA-card.
  * 
@@ -27,6 +27,10 @@
 
 /* ------------------------------------------------------------- */
 
+static char *revision = "$Revision: 1.1.2.3 $";
+
+/* ------------------------------------------------------------- */
+
 MODULE_DESCRIPTION("CAPI4Linux: Driver for AVM B1 ISA card");
 MODULE_AUTHOR("Carsten Paeth");
 MODULE_LICENSE("GPL");
@@ -56,7 +60,7 @@ static void b1isa_remove(struct pci_dev 
 
 static char *b1isa_procinfo(struct capi_ctr *ctrl);
 
-static int __init b1isa_probe(struct pci_dev *pdev)
+static int b1isa_probe(struct pci_dev *pdev)
 {
 	avmctrl_info *cinfo;
 	avmcard *card;
@@ -108,6 +112,7 @@ static int __init b1isa_probe(struct pci
 	b1_reset(card->port);
 	b1_getrevision(card);
 
+	cinfo->capi_ctrl.owner = THIS_MODULE;
 	cinfo->capi_ctrl.driver_name   = "b1isa";
 	cinfo->capi_ctrl.driverdata    = cinfo;
 	cinfo->capi_ctrl.register_appl = b1_register_appl;
@@ -118,7 +123,6 @@ static int __init b1isa_probe(struct pci
 	cinfo->capi_ctrl.procinfo      = b1isa_procinfo;
 	cinfo->capi_ctrl.ctr_read_proc = b1ctl_read_proc;
 	strcpy(cinfo->capi_ctrl.name, card->name);
-	cinfo->capi_ctrl.owner = THIS_MODULE;
 
 	retval = attach_capi_ctr(&cinfo->capi_ctrl);
 	if (retval) {
@@ -170,23 +174,56 @@ MODULE_PARM(irq, "1-" __MODULE_STRING(MA
 MODULE_PARM_DESC(io, "I/O base address(es)");
 MODULE_PARM_DESC(irq, "IRQ number(s) (assigned)");
 
+static int b1isa_add_card(struct capi_driver *driver, capicardparams *data)
+{
+	int i;
+
+	for (i = 0; i < MAX_CARDS; i++) {
+		if (isa_dev[i].resource[0].start)
+			continue;
+
+		isa_dev[i].resource[0].start = data->port;
+		isa_dev[i].irq = data->irq;
+
+		if (b1isa_probe(&isa_dev[i]) == 0)
+			return 0;
+	}
+	return -ENODEV;
+}
+
+static struct capi_driver capi_driver_b1isa = {
+	.name		= "b1isa",
+	.revision	= "1.0",
+	.add_card       = b1isa_add_card,
+};
+
 static int __init b1isa_init(void)
 {
+	char *p;
+	char rev[32];
 	int i;
-	int found = 0;
+
+	if ((p = strchr(revision, ':')) != 0 && p[1]) {
+		strlcpy(rev, p + 2, 32);
+		if ((p = strchr(rev, '$')) != 0 && p > rev)
+		   *(p-1) = 0;
+	} else
+		strcpy(rev, "1.0");
 
 	for (i = 0; i < MAX_CARDS; i++) {
 		if (!io[i])
 			break;
 
 		isa_dev[i].resource[0].start = io[i];
-		isa_dev[i].irq_resource[0].start = irq[i];
+		isa_dev[i].irq = irq[i];
 
-		if (b1isa_probe(&isa_dev[i]) == 0)
-			found++;
+		if (b1isa_probe(&isa_dev[i]) != 0)
+			return -ENODEV;
 	}
-	if (found == 0)
-		return -ENODEV;
+
+	strlcpy(capi_driver_b1isa.revision, rev, 32);
+	register_capi_driver(&capi_driver_b1isa);
+	printk(KERN_INFO "b1isa: revision %s\n", rev);
 
 	return 0;
 }
@@ -201,6 +238,7 @@ static void __exit b1isa_exit(void)
 
 		b1isa_remove(&isa_dev[i]);
 	}
+	unregister_capi_driver(&capi_driver_b1isa);
 }
 
 module_init(b1isa_init);
--- diff/drivers/isdn/hardware/avm/b1pci.c	2003-08-20 14:16:28.000000000 +0100
+++ source/drivers/isdn/hardware/avm/b1pci.c	2004-02-23 13:56:42.000000000 +0000
@@ -1,4 +1,4 @@
-/* $Id: b1pci.c,v 1.1.4.1.2.1 2001/12/21 15:00:17 kai Exp $
+/* $Id: b1pci.c,v 1.1.2.2 2004/01/16 21:09:27 keil Exp $
  * 
  * Module for AVM B1 PCI-card.
  * 
@@ -28,6 +28,10 @@
 
 /* ------------------------------------------------------------- */
 
+static char *revision = "$Revision: 1.1.2.2 $";
+
+/* ------------------------------------------------------------- */
+
 static struct pci_device_id b1pci_pci_tbl[] = {
 	{ PCI_VENDOR_ID_AVM, PCI_DEVICE_ID_AVM_B1, PCI_ANY_ID, PCI_ANY_ID },
 	{ }				/* Terminating entry */
@@ -362,13 +366,50 @@ static struct pci_driver b1pci_pci_drive
 	.remove		= __devexit_p(b1pci_pci_remove),
 };
 
+static struct capi_driver capi_driver_b1pci = {
+	.name		= "b1pci",
+	.revision	= "1.0",
+};
+#ifdef CONFIG_ISDN_DRV_AVMB1_B1PCIV4
+static struct capi_driver capi_driver_b1pciv4 = {
+	.name		= "b1pciv4",
+	.revision	= "1.0",
+};
+#endif
+
 static int __init b1pci_init(void)
 {
-	return pci_module_init(&b1pci_pci_driver);
+	char *p;
+	char rev[32];
+	int err;
+
+	if ((p = strchr(revision, ':')) != 0 && p[1]) {
+		strlcpy(rev, p + 2, 32);
+		if ((p = strchr(rev, '$')) != 0 && p > rev)
+		   *(p-1) = 0;
+	} else
+		strcpy(rev, "1.0");
+
+
+	err = pci_module_init(&b1pci_pci_driver);
+	if (!err) {
+		strlcpy(capi_driver_b1pci.revision, rev, 32);
+		register_capi_driver(&capi_driver_b1pci);
+#ifdef CONFIG_ISDN_DRV_AVMB1_B1PCIV4
+		strlcpy(capi_driver_b1pciv4.revision, rev, 32);
+		register_capi_driver(&capi_driver_b1pciv4);
+#endif
+		printk(KERN_INFO "b1pci: revision %s\n", rev);
+	}
+	return err;
 }
 
 static void __exit b1pci_exit(void)
 {
+	unregister_capi_driver(&capi_driver_b1pci);
+#ifdef CONFIG_ISDN_DRV_AVMB1_B1PCIV4
+	unregister_capi_driver(&capi_driver_b1pciv4);
+#endif
 	pci_unregister_driver(&b1pci_pci_driver);
 }
 
--- diff/drivers/isdn/hardware/avm/b1pcmcia.c	2003-06-30 10:07:33.000000000 +0100
+++ source/drivers/isdn/hardware/avm/b1pcmcia.c	2004-02-23 13:56:42.000000000 +0000
@@ -1,4 +1,4 @@
-/* $Id: b1pcmcia.c,v 1.12.6.5 2001/09/23 22:24:33 kai Exp $
+/* $Id: b1pcmcia.c,v 1.1.2.2 2004/01/16 21:09:27 keil Exp $
  * 
  * Module for AVM B1/M1/M2 PCMCIA-card.
  * 
@@ -27,6 +27,10 @@
 
 /* ------------------------------------------------------------- */
 
+static char *revision = "$Revision: 1.1.2.2 $";
+
+/* ------------------------------------------------------------- */
+
 MODULE_DESCRIPTION("CAPI4Linux: Driver for AVM PCMCIA cards");
 MODULE_AUTHOR("Carsten Paeth");
 MODULE_LICENSE("GPL");
@@ -186,3 +190,36 @@ EXPORT_SYMBOL(b1pcmcia_addcard_b1);
 EXPORT_SYMBOL(b1pcmcia_addcard_m1);
 EXPORT_SYMBOL(b1pcmcia_addcard_m2);
 EXPORT_SYMBOL(b1pcmcia_delcard);
+
+static struct capi_driver capi_driver_b1pcmcia = {
+	.name		= "b1pcmcia",
+	.revision	= "1.0",
+};
+
+static int __init b1pcmcia_init(void)
+{
+	char *p;
+	char rev[32];
+	int err;
+
+	if ((p = strchr(revision, ':')) != 0 && p[1]) {
+		strlcpy(rev, p + 2, 32);
+		if ((p = strchr(rev, '$')) != 0 && p > rev)
+		   *(p-1) = 0;
+	} else
+		strcpy(rev, "1.0");
+
+	strlcpy(capi_driver_b1pcmcia.revision, rev, 32);
+	register_capi_driver(&capi_driver_b1pcmcia);
+	printk(KERN_INFO "b1pci: revision %s\n", rev);
+
+	return 0;
+}
+
+static void __exit b1pcmcia_exit(void)
+{
+	unregister_capi_driver(&capi_driver_b1pcmcia);
+}
+
+module_init(b1pcmcia_init);
+module_exit(b1pcmcia_exit);
--- diff/drivers/isdn/hardware/avm/c4.c	2003-09-17 12:28:06.000000000 +0100
+++ source/drivers/isdn/hardware/avm/c4.c	2004-02-23 13:56:42.000000000 +0000
@@ -1,4 +1,4 @@
-/* $Id: c4.c,v 1.1.4.1.2.1 2001/12/21 15:00:17 kai Exp $
+/* $Id: c4.c,v 1.1.2.2 2004/01/16 21:09:27 keil Exp $
  * 
  * Module for AVM C4 & C2 card.
  * 
@@ -34,6 +34,10 @@
 
 /* ------------------------------------------------------------- */
 
+static char *revision = "$Revision: 1.1.2.2 $";
+
+/* ------------------------------------------------------------- */
+
 static int suppress_pollack;
 
 static struct pci_device_id c4_pci_tbl[] = {
@@ -404,18 +408,14 @@ static int c4_detect(avmcard *card)
 static void c4_dispatch_tx(avmcard *card)
 {
 	avmcard_dmainfo *dma = card->dma;
-	unsigned long flags;
 	struct sk_buff *skb;
 	u8 cmd, subcmd;
 	u16 len;
 	u32 txlen;
 	void *p;
-	
-	save_flags(flags);
-	cli();
+
 
 	if (card->csr & DBELL_DOWN_ARM) { /* tx busy */
-	        restore_flags(flags);
 		return;
 	}
 
@@ -424,7 +424,6 @@ static void c4_dispatch_tx(avmcard *card
 #ifdef CONFIG_C4_DEBUG
 		printk(KERN_DEBUG "%s: tx underrun\n", card->name);
 #endif
-	        restore_flags(flags);
 		return;
 	}
 
@@ -470,7 +469,6 @@ static void c4_dispatch_tx(avmcard *card
 
 	c4outmeml(card->mbase+DOORBELL, DBELL_DOWN_ARM);
 
-	restore_flags(flags);
 	dev_kfree_skb_any(skb);
 }
 
@@ -664,11 +662,15 @@ static void c4_handle_rx(avmcard *card)
 
 static irqreturn_t c4_handle_interrupt(avmcard *card)
 {
-	u32 status = c4inmeml(card->mbase+DOORBELL);
+	u32 status;
+
+	spin_lock(&card->lock);
+	status = c4inmeml(card->mbase+DOORBELL);
 
 	if (status & DBELL_RESET_HOST) {
 		u_int i;
 		c4outmeml(card->mbase+PCI_OUT_INT_MASK, 0x0c);
+		spin_unlock(&card->lock);
 		if (card->nlogcontr == 0)
 			return IRQ_HANDLED;
 		printk(KERN_ERR "%s: unexpected reset\n", card->name);
@@ -683,8 +685,10 @@ static irqreturn_t c4_handle_interrupt(a
 	}
 
 	status &= (DBELL_UP_HOST | DBELL_DOWN_HOST);
-	if (!status)
+	if (!status) {
+		spin_unlock(&card->lock);
 		return IRQ_HANDLED;
+	}
 	c4outmeml(card->mbase+DOORBELL, status);
 
 	if ((status & DBELL_UP_HOST) != 0) {
@@ -705,6 +709,7 @@ static irqreturn_t c4_handle_interrupt(a
 			c4_dispatch_tx(card);
 		}
 	}
+	spin_unlock(&card->lock);
 	return IRQ_HANDLED;
 }
 
@@ -767,6 +772,7 @@ static int queue_sendconfigword(avmcard 
 static int queue_sendconfig(avmcard *card, char cval[4])
 {
 	struct sk_buff *skb;
+	unsigned long flags;
 	void *p;
 
 	skb = alloc_skb(3+4, GFP_ATOMIC);
@@ -786,7 +792,10 @@ static int queue_sendconfig(avmcard *car
 	skb_put(skb, (u8 *)p - (u8 *)skb->data);
 
 	skb_queue_tail(&card->dma->send_queue, skb);
+	
+	spin_lock_irqsave(&card->lock, flags);
 	c4_dispatch_tx(card);
+	spin_unlock_irqrestore(&card->lock, flags);
 	return 0;
 }
 
@@ -835,7 +844,6 @@ static int c4_load_firmware(struct capi_
 {
 	avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata);
 	avmcard *card = cinfo->card;
-	unsigned long flags;
 	int retval;
 
 	if ((retval = c4_load_t4file(card, &data->firmware))) {
@@ -845,9 +853,6 @@ static int c4_load_firmware(struct capi_
 		return retval;
 	}
 
-	save_flags(flags);
-	cli();
-
 	card->csr = 0;
 	c4outmeml(card->mbase+MBOX_UP_LEN, 0);
 	c4outmeml(card->mbase+MBOX_DOWN_LEN, 0);
@@ -862,7 +867,6 @@ static int c4_load_firmware(struct capi_
 	c4outmeml(card->mbase+MBOX_UP_ADDR, card->dma->recvbuf.dmaaddr);
 	c4outmeml(card->mbase+MBOX_UP_LEN, card->dma->recvbuf.size);
 	c4outmeml(card->mbase+DOORBELL, DBELL_UP_ARM);
-	restore_flags(flags);
 
 	if (data->configuration.len > 0 && data->configuration.data) {
 		retval = c4_send_config(card, &data->configuration);
@@ -885,9 +889,14 @@ void c4_reset_ctr(struct capi_ctr *ctrl)
 	avmcard *card = ((avmctrl_info *)(ctrl->driverdata))->card;
 	avmctrl_info *cinfo;
 	u_int i;
+	unsigned long flags;
+
+	spin_lock_irqsave(&card->lock, flags);
 
  	c4_reset(card);
 
+	spin_unlock_irqrestore(&card->lock, flags);
+
         for (i=0; i < card->nr_controllers; i++) {
 		cinfo = &card->ctrlinfo[i];
 		memset(cinfo->version, 0, sizeof(cinfo->version));
@@ -931,6 +940,7 @@ void c4_register_appl(struct capi_ctr *c
 	avmcard *card = cinfo->card;
 	struct sk_buff *skb;
 	int want = rp->level3cnt;
+	unsigned long flags;
 	int nconn;
 	void *p;
 
@@ -958,7 +968,10 @@ void c4_register_appl(struct capi_ctr *c
 		skb_put(skb, (u8 *)p - (u8 *)skb->data);
 
 		skb_queue_tail(&card->dma->send_queue, skb);
+	
+		spin_lock_irqsave(&card->lock, flags);
 		c4_dispatch_tx(card);
+		spin_unlock_irqrestore(&card->lock, flags);
 	}
 }
 
@@ -968,6 +981,7 @@ void c4_release_appl(struct capi_ctr *ct
 {
 	avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata);
 	avmcard *card = cinfo->card;
+	unsigned long flags;
 	struct sk_buff *skb;
 	void *p;
 
@@ -988,7 +1002,9 @@ void c4_release_appl(struct capi_ctr *ct
 
 		skb_put(skb, (u8 *)p - (u8 *)skb->data);
 		skb_queue_tail(&card->dma->send_queue, skb);
+		spin_lock_irqsave(&card->lock, flags);
 		c4_dispatch_tx(card);
+		spin_unlock_irqrestore(&card->lock, flags);
 	}
 }
 
@@ -1000,6 +1016,7 @@ static u16 c4_send_message(struct capi_c
 	avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata);
 	avmcard *card = cinfo->card;
 	u16 retval = CAPI_NOERROR;
+	unsigned long flags;
 
  	if (CAPIMSG_CMD(skb->data) == CAPI_DATA_B3_REQ) {
 		retval = capilib_data_b3_req(&cinfo->ncci_head,
@@ -1009,7 +1026,9 @@ static u16 c4_send_message(struct capi_c
 	}
 	if (retval == CAPI_NOERROR) {
 		skb_queue_tail(&card->dma->send_queue, skb);
+		spin_lock_irqsave(&card->lock, flags);
 		c4_dispatch_tx(card);
+		spin_unlock_irqrestore(&card->lock, flags);
 	} else {
 		dev_kfree_skb_any(skb);
 	}
@@ -1164,6 +1183,7 @@ static int c4_add_card(struct capicardpa
 
 	for (i=0; i < nr_controllers ; i++) {
 		cinfo = &card->ctrlinfo[i];
+		cinfo->capi_ctrl.owner = THIS_MODULE;
 		cinfo->capi_ctrl.driver_name   = "c4";
 		cinfo->capi_ctrl.driverdata    = cinfo;
 		cinfo->capi_ctrl.register_appl = c4_register_appl;
@@ -1174,7 +1194,6 @@ static int c4_add_card(struct capicardpa
 		cinfo->capi_ctrl.procinfo      = c4_procinfo;
 		cinfo->capi_ctrl.ctr_read_proc = c4_read_proc;
 		strcpy(cinfo->capi_ctrl.name, card->name);
-		cinfo->capi_ctrl.owner = THIS_MODULE;
 
 		retval = attach_capi_ctr(&cinfo->capi_ctrl);
 		if (retval) {
@@ -1247,13 +1266,44 @@ static struct pci_driver c4_pci_driver =
        .remove         = c4_remove,
 };
 
+static struct capi_driver capi_driver_c2 = {
+	.name		= "c2",
+	.revision	= "1.0",
+};
+
+static struct capi_driver capi_driver_c4 = {
+	.name		= "c4",
+	.revision	= "1.0",
+};
+
 static int __init c4_init(void)
 {
-	return pci_module_init(&c4_pci_driver);
+	char *p;
+	char rev[32];
+	int err;
+
+	if ((p = strchr(revision, ':')) != 0 && p[1]) {
+		strlcpy(rev, p + 2, 32);
+		if ((p = strchr(rev, '$')) != 0 && p > rev)
+		   *(p-1) = 0;
+	} else
+		strcpy(rev, "1.0");
+
+	err = pci_module_init(&c4_pci_driver);
+	if (!err) {
+		strlcpy(capi_driver_c2.revision, rev, 32);
+		register_capi_driver(&capi_driver_c2);
+		strlcpy(capi_driver_c4.revision, rev, 32);
+		register_capi_driver(&capi_driver_c4);
+		printk(KERN_INFO "c4: revision %s\n", rev);
+	}
+	return err;
 }
 
 static void __exit c4_exit(void)
 {
+	unregister_capi_driver(&capi_driver_c2);
+	unregister_capi_driver(&capi_driver_c4);
 	pci_unregister_driver(&c4_pci_driver);
 }
 
--- diff/drivers/isdn/hardware/avm/t1isa.c	2003-08-20 14:16:28.000000000 +0100
+++ source/drivers/isdn/hardware/avm/t1isa.c	2004-02-23 13:56:42.000000000 +0000
@@ -1,4 +1,4 @@
-/* $Id: t1isa.c,v 1.16.6.7 2001/09/23 22:24:34 kai Exp $
+/* $Id: t1isa.c,v 1.1.2.3 2004/02/10 01:07:12 keil Exp $
  * 
  * Module for AVM T1 HEMA-card.
  * 
@@ -29,6 +29,10 @@
 
 /* ------------------------------------------------------------- */
 
+static char *revision = "$Revision: 1.1.2.3 $";
+
+/* ------------------------------------------------------------- */
+
 MODULE_DESCRIPTION("CAPI4Linux: Driver for AVM T1 HEMA ISA card");
 MODULE_AUTHOR("Carsten Paeth");
 MODULE_LICENSE("GPL");
@@ -58,7 +62,6 @@ static int t1_detectandinit(unsigned int
 {
 	unsigned char cregs[8];
 	unsigned char reverse_cardnr;
-	unsigned long flags;
 	unsigned char dummy;
 	int i;
 
@@ -73,8 +76,12 @@ static int t1_detectandinit(unsigned int
 	cregs[6] = 0;
 	cregs[7] = 0;
 
-	save_flags(flags);
-	cli();
+	/*
+	 * no one else should use the ISA bus in this moment,
+	 * but no function there to prevent this :-(
+	 * save_flags(flags); cli();
+	 */
+
 	/* board reset */
 	t1outp(base, T1_RESETBOARD, 0xf);
 	mdelay(100);
@@ -87,7 +94,7 @@ static int t1_detectandinit(unsigned int
 	t1outp(base, HEMA_PAL_ID >> 4, cregs[0]);
 	for(i=1;i<7;i++) t1outp(base, 0, cregs[i]);
 	t1outp(base, ((base >> 4)) & 0x3, cregs[7]);
-	restore_flags(flags);
+	/* restore_flags(flags); */
 
 	mdelay(100);
 	t1outp(base, T1_FASTLINK+T1_RESETLINK, 0);
@@ -137,6 +144,9 @@ static irqreturn_t t1isa_interrupt(int i
 	unsigned DataB3Len;
 	unsigned NCCI;
 	unsigned WindowSize;
+	unsigned long flags;
+
+	spin_lock_irqsave(&card->lock, flags);
 
 	while (b1_rx_full(card->port)) {
 
@@ -149,6 +159,7 @@ static irqreturn_t t1isa_interrupt(int i
 			ApplId = (unsigned) b1_get_word(card->port);
 			MsgLen = t1_get_slice(card->port, card->msgbuf);
 			DataB3Len = t1_get_slice(card->port, card->databuf);
+			spin_unlock_irqrestore(&card->lock, flags);
 
 			if (MsgLen < 30) { /* not CAPI 64Bit */
 				memset(card->msgbuf+MsgLen, 0, 30-MsgLen);
@@ -169,6 +180,7 @@ static irqreturn_t t1isa_interrupt(int i
 
 			ApplId = (unsigned) b1_get_word(card->port);
 			MsgLen = t1_get_slice(card->port, card->msgbuf);
+			spin_unlock_irqrestore(&card->lock, flags);
 			if (!(skb = alloc_skb(MsgLen, GFP_ATOMIC))) {
 				printk(KERN_ERR "%s: incoming packet dropped\n",
 						card->name);
@@ -188,6 +200,7 @@ static irqreturn_t t1isa_interrupt(int i
 			ApplId = b1_get_word(card->port);
 			NCCI = b1_get_word(card->port);
 			WindowSize = b1_get_word(card->port);
+			spin_unlock_irqrestore(&card->lock, flags);
 
 			capilib_new_ncci(&cinfo->ncci_head, ApplId, NCCI, WindowSize);
 
@@ -197,6 +210,7 @@ static irqreturn_t t1isa_interrupt(int i
 
 			ApplId = b1_get_word(card->port);
 			NCCI = b1_get_word(card->port);
+			spin_unlock_irqrestore(&card->lock, flags);
 
 			if (NCCI != 0xffffffff)
 				capilib_free_ncci(&cinfo->ncci_head, ApplId, NCCI);
@@ -205,16 +219,19 @@ static irqreturn_t t1isa_interrupt(int i
 
 		case RECEIVE_START:
 			b1_put_byte(card->port, SEND_POLLACK);
+			spin_unlock_irqrestore(&card->lock, flags);
 			capi_ctr_resume_output(ctrl);
 			break;
 
 		case RECEIVE_STOP:
+			spin_unlock_irqrestore(&card->lock, flags);
 			capi_ctr_suspend_output(ctrl);
 			break;
 
 		case RECEIVE_INIT:
 
 			cinfo->versionlen = t1_get_slice(card->port, cinfo->versionbuf);
+			spin_unlock_irqrestore(&card->lock, flags);
 			b1_parse_version(cinfo);
 			printk(KERN_INFO "%s: %s-card (%s) now active\n",
 			       card->name,
@@ -226,6 +243,7 @@ static irqreturn_t t1isa_interrupt(int i
 		case RECEIVE_TASK_READY:
 			ApplId = (unsigned) b1_get_word(card->port);
 			MsgLen = t1_get_slice(card->port, card->msgbuf);
+			spin_unlock_irqrestore(&card->lock, flags);
 			card->msgbuf[MsgLen] = 0;
 			while (    MsgLen > 0
 			       && (   card->msgbuf[MsgLen-1] == '\n'
@@ -239,6 +257,7 @@ static irqreturn_t t1isa_interrupt(int i
 
 		case RECEIVE_DEBUGMSG:
 			MsgLen = t1_get_slice(card->port, card->msgbuf);
+			spin_unlock_irqrestore(&card->lock, flags);
 			card->msgbuf[MsgLen] = 0;
 			while (    MsgLen > 0
 			       && (   card->msgbuf[MsgLen-1] == '\n'
@@ -251,9 +270,11 @@ static irqreturn_t t1isa_interrupt(int i
 
 
 		case 0xff:
+			spin_unlock_irqrestore(&card->lock, flags);
 			printk(KERN_ERR "%s: card reseted ?\n", card->name);
 			return IRQ_HANDLED;
 		default:
+			spin_unlock_irqrestore(&card->lock, flags);
 			printk(KERN_ERR "%s: b1_interrupt: 0x%x ???\n",
 					card->name, b1cmd);
 			return IRQ_NONE;
@@ -296,14 +317,13 @@ static int t1isa_load_firmware(struct ca
 		return -EIO;
 	}
 
-	save_flags(flags);
-	cli();
+	spin_lock_irqsave(&card->lock, flags);
 	b1_setinterrupt(port, card->irq, card->cardtype);
 	b1_put_byte(port, SEND_INIT);
 	b1_put_word(port, CAPI_MAXAPPL);
 	b1_put_word(port, AVM_NCCI_PER_CHANNEL*30);
 	b1_put_word(port, ctrl->cnr - 1);
-	restore_flags(flags);
+	spin_unlock_irqrestore(&card->lock, flags);
 
 	return 0;
 }
@@ -349,7 +369,7 @@ static void t1isa_remove(struct pci_dev 
 static u16 t1isa_send_message(struct capi_ctr *ctrl, struct sk_buff *skb);
 static char *t1isa_procinfo(struct capi_ctr *ctrl);
 
-static int __init t1isa_probe(struct pci_dev *pdev, int cardnr)
+static int t1isa_probe(struct pci_dev *pdev, int cardnr)
 {
 	avmctrl_info *cinfo;
 	avmcard *card;
@@ -401,6 +421,7 @@ static int __init t1isa_probe(struct pci
 	t1_disable_irq(card->port);
 	b1_reset(card->port);
 
+	cinfo->capi_ctrl.owner = THIS_MODULE;
 	cinfo->capi_ctrl.driver_name   = "t1isa";
 	cinfo->capi_ctrl.driverdata    = cinfo;
 	cinfo->capi_ctrl.register_appl = b1_register_appl;
@@ -411,7 +432,6 @@ static int __init t1isa_probe(struct pci
 	cinfo->capi_ctrl.procinfo      = t1isa_procinfo;
 	cinfo->capi_ctrl.ctr_read_proc = b1ctl_read_proc;
 	strcpy(cinfo->capi_ctrl.name, card->name);
-	cinfo->capi_ctrl.owner = THIS_MODULE;
 
 	retval = attach_capi_ctr(&cinfo->capi_ctrl);
 	if (retval) {
@@ -456,20 +476,18 @@ static u16 t1isa_send_message(struct cap
 
 		dlen = CAPIMSG_DATALEN(skb->data);
 
-		save_flags(flags);
-		cli();
+		spin_lock_irqsave(&card->lock, flags);
 		b1_put_byte(port, SEND_DATA_B3_REQ);
 		t1_put_slice(port, skb->data, len);
 		t1_put_slice(port, skb->data + len, dlen);
-		restore_flags(flags);
+		spin_unlock_irqrestore(&card->lock, flags);
 	} else {
 		retval = CAPI_NOERROR;
 
-		save_flags(flags);
-		cli();
+		spin_lock_irqsave(&card->lock, flags);
 		b1_put_byte(port, SEND_MESSAGE);
 		t1_put_slice(port, skb->data, len);
-		restore_flags(flags);
+		spin_unlock_irqrestore(&card->lock, flags);
 	}
  out:
 	dev_kfree_skb_any(skb);
@@ -509,23 +527,56 @@ MODULE_PARM_DESC(io, "I/O base address(e
 MODULE_PARM_DESC(irq, "IRQ number(s) (assigned)");
 MODULE_PARM_DESC(cardnr, "Card number(s) (as jumpered)");
 
+static int t1isa_add_card(struct capi_driver *driver, capicardparams *data)
+{
+	int i;
+
+	for (i = 0; i < MAX_CARDS; i++) {
+		if (isa_dev[i].resource[0].start)
+			continue;
+
+		isa_dev[i].resource[0].start = data->port;
+		isa_dev[i].irq = data->irq;
+
+		if (t1isa_probe(&isa_dev[i], data->cardnr) == 0)
+			return 0;
+	}
+	return -ENODEV;
+}
+
+static struct capi_driver capi_driver_t1isa = {
+	.name		= "t1isa",
+	.revision	= "1.0",
+	.add_card       = t1isa_add_card,
+};
+
 static int __init t1isa_init(void)
 {
+	char rev[32];
+	char *p;
 	int i;
-	int found = 0;
+
+	if ((p = strchr(revision, ':')) != 0 && p[1]) {
+		strlcpy(rev, p + 2, 32);
+		if ((p = strchr(rev, '$')) != 0 && p > rev)
+		   *(p-1) = 0;
+	} else
+		strcpy(rev, "1.0");
 
 	for (i = 0; i < MAX_CARDS; i++) {
 		if (!io[i])
 			break;
 
 		isa_dev[i].resource[0].start = io[i];
-		isa_dev[i].irq_resource[0].start = irq[i];
+		isa_dev[i].irq = irq[i];
 
-		if (t1isa_probe(&isa_dev[i], cardnr[i]) == 0)
-			found++;
+		if (t1isa_probe(&isa_dev[i], cardnr[i]) != 0)
+			return -ENODEV;
 	}
-	if (found == 0)
-		return -ENODEV;
+
+	strlcpy(capi_driver_t1isa.revision, rev, 32);
+	register_capi_driver(&capi_driver_t1isa);
+	printk(KERN_INFO "t1isa: revision %s\n", rev);
 
 	return 0;
 }
--- diff/drivers/isdn/hardware/avm/t1pci.c	2003-08-20 14:16:28.000000000 +0100
+++ source/drivers/isdn/hardware/avm/t1pci.c	2004-02-23 13:56:42.000000000 +0000
@@ -1,4 +1,4 @@
-/* $Id: t1pci.c,v 1.1.4.1.2.1 2001/12/21 15:00:17 kai Exp $
+/* $Id: t1pci.c,v 1.1.2.2 2004/01/16 21:09:27 keil Exp $
  * 
  * Module for AVM T1 PCI-card.
  * 
@@ -30,6 +30,8 @@
 #undef CONFIG_T1PCI_POLLDEBUG
 
 /* ------------------------------------------------------------- */
+static char *revision = "$Revision: 1.1.2.2 $";
+/* ------------------------------------------------------------- */
 
 static struct pci_device_id t1pci_pci_tbl[] = {
 	{ PCI_VENDOR_ID_AVM, PCI_DEVICE_ID_AVM_T1, PCI_ANY_ID, PCI_ANY_ID },
@@ -221,13 +223,36 @@ static struct pci_driver t1pci_pci_drive
        .remove         = t1pci_remove,
 };
 
+static struct capi_driver capi_driver_t1pci = {
+	.name		= "t1pci",
+	.revision	= "1.0",
+};
+
 static int __init t1pci_init(void)
 {
-	return pci_module_init(&t1pci_pci_driver);
+	char *p;
+	char rev[32];
+	int err;
+
+	if ((p = strchr(revision, ':')) != 0 && p[1]) {
+		strlcpy(rev, p + 2, 32);
+		if ((p = strchr(rev, '$')) != 0 && p > rev)
+		   *(p-1) = 0;
+	} else
+		strcpy(rev, "1.0");
+
+	err = pci_module_init(&t1pci_pci_driver);
+	if (!err) {
+		strlcpy(capi_driver_t1pci.revision, rev, 32);
+		register_capi_driver(&capi_driver_t1pci);
+		printk(KERN_INFO "t1pci: revision %s\n", rev);
+	}
+	return err;
 }
 
 static void __exit t1pci_exit(void)
 {
+	unregister_capi_driver(&capi_driver_t1pci);
 	pci_unregister_driver(&t1pci_pci_driver);
 }
 
--- diff/drivers/isdn/hardware/eicon/Kconfig	2003-09-30 15:46:14.000000000 +0100
+++ source/drivers/isdn/hardware/eicon/Kconfig	2004-02-23 13:56:42.000000000 +0000
@@ -3,7 +3,7 @@
 #
 
 menu "Active Eicon DIVA Server cards"
-	depends on NET && ISDN_BOOL && ISDN_CAPI!=n
+	depends on NET && ISDN && ISDN_CAPI!=n
 
 config CAPI_EICON
 	bool "Support Eicon cards"
--- diff/drivers/isdn/hisax/Kconfig	2003-10-09 09:47:34.000000000 +0100
+++ source/drivers/isdn/hisax/Kconfig	2004-02-23 13:56:42.000000000 +0000
@@ -1,6 +1,6 @@
 
 menu "Passive cards"
-	depends on ISDN
+	depends on ISDN_I4L
 
 config ISDN_DRV_HISAX
 	tristate "HiSax SiemensChipSet driver support"
@@ -341,8 +341,8 @@ config HISAX_HFC_SX
 #      bool '  TESTEMULATOR (EXPERIMENTAL)' CONFIG_HISAX_TESTEMU
 
 config HISAX_ENTERNOW_PCI
-	bool "Formula-n enter:now PCI card (EXPERIMENTAL)"
-	depends on PCI && EXPERIMENTAL
+	bool "Formula-n enter:now PCI card"
+	depends on PCI
 	help
 	  This enables HiSax support for the Formula-n enter:now PCI
 	  ISDN card.
@@ -365,6 +365,8 @@ config HISAX_DEBUG
 	  the ST5481 USB driver currently. 
 	  If in doubt, say yes.
 
+comment "HiSax PCMCIA card service modules"
+
 config HISAX_SEDLBAUER_CS
 	tristate "Sedlbauer PCMCIA cards"
 	depends on PCMCIA && HISAX_SEDLBAUER
@@ -374,18 +376,26 @@ config HISAX_SEDLBAUER_CS
 
 config HISAX_ELSA_CS
 	tristate "ELSA PCMCIA MicroLink cards"
-	depends on PCMCIA
+	depends on PCMCIA && HISAX_ELSA
 	help
 	  This enables the PCMCIA client driver for the Elsa PCMCIA MicroLink
 	  card.
 
 config HISAX_AVM_A1_CS
 	tristate "AVM A1 PCMCIA cards"
-	depends on PCMCIA
+	depends on PCMCIA && ISDN_DRV_HISAX
 	help
 	  This enables the PCMCIA client driver for the AVM A1 / Fritz!Card
 	  PCMCIA cards.
 
+config HISAX_TELES_CS
+	tristate "TELES PCMCIA cards"
+	depends on PCMCIA && HISAX_16_3
+	help
+	  This enables the PCMCIA client driver for the Teles PCMCIA cards.
+
+comment "HiSax sub driver modules"
+
 config HISAX_ST5481
 	tristate "ST5481 USB ISDN modem (EXPERIMENTAL)"
 	depends on USB && EXPERIMENTAL
@@ -393,6 +403,12 @@ config HISAX_ST5481
 	  This enables the driver for ST5481 based USB ISDN adapters,
 	  e.g. the BeWan Gazel 128 USB
 
+config HISAX_HFCUSB
+	tristate "HFC USB based ISDN modems (EXPERIMENTAL)"
+	depends on USB && EXPERIMENTAL
+	help
+	  This enables the driver for HFC USB based ISDN modems.
+
 config HISAX_FRITZ_PCIPNP
 	tristate "AVM Fritz!Card PCI/PCIv2/PnP support (EXPERIMENTAL)"
 	depends on EXPERIMENTAL
@@ -402,18 +418,15 @@ config HISAX_FRITZ_PCIPNP
 	  (the latter also needs you to select "ISA Plug and Play support"
 	  from the menu "Plug and Play configuration")
 
-config HISAX_FRITZ_CLASSIC
-	tristate "AVM Fritz!Card classic support (EXPERIMENTAL)"
-	depends on ISA && EXPERIMENTAL
-	help
-	  This enables the driver for the AVM Fritz!Card classic, formerly
-	  known as AVM A1.
-
-config HISAX_HFCPCI
-	tristate "HFC PCI support (EXPERIMENTAL)"
-	depends on PCI && EXPERIMENTAL
-	help
-	  This enables the driver for CCD HFC PCI based cards.
+config HISAX_HDLC
+	bool
+	depends on HISAX_ST5481
+	default y
+
+config HISAX_AVM_A1_PCMCIA
+	bool
+	depends on HISAX_AVM_A1_CS
+	default y
 
 endif
 
--- diff/drivers/isdn/hisax/Makefile	2003-09-17 12:28:06.000000000 +0100
+++ source/drivers/isdn/hisax/Makefile	2004-02-23 13:56:42.000000000 +0000
@@ -1,19 +1,23 @@
 # Makefile for the hisax ISDN device driver
 
+# The target object and module list name.
+
 # Define maximum number of cards
 
 EXTRA_CFLAGS      += -DHISAX_MAX_CARDS=$(CONFIG_HISAX_MAX_CARDS)
 
-# Each configuration option enables a list of files.
-
 obj-$(CONFIG_ISDN_DRV_HISAX)		+= hisax.o
 obj-$(CONFIG_HISAX_SEDLBAUER_CS)	+= sedlbauer_cs.o
 obj-$(CONFIG_HISAX_ELSA_CS)		+= elsa_cs.o
 obj-$(CONFIG_HISAX_AVM_A1_CS)		+= avma1_cs.o
+obj-$(CONFIG_HISAX_TELES_CS)		+= teles_cs.o
 obj-$(CONFIG_HISAX_ST5481)		+= hisax_st5481.o
+obj-$(CONFIG_HISAX_HFCUSB)		+= hfc_usb.o
 obj-$(CONFIG_HISAX_FRITZ_PCIPNP)        += hisax_isac.o hisax_fcpcipnp.o
-obj-$(CONFIG_HISAX_FRITZ_CLASSIC)       += hisax_isac.o hisax_hscx.o hisax_fcclassic.o
-obj-$(CONFIG_HISAX_FRITZ_PCIPNP)        += hisax_hfcpci.o
+
+ifdef CONFIG_HISAX_HDLC
+obj-$(CONFIG_ISDN_DRV_HISAX)		+= isdnhdlc.o
+endif
 
 # Multipart objects.
 
@@ -21,7 +25,7 @@ hisax_st5481-y 				:= st5481_init.o st54
 					   st5481_b.o st5481_hdlc.o
 
 hisax-y	  				:= config.o isdnl1.o tei.o isdnl2.o isdnl3.o \
-		     			   lmgr.o q931.o callc.o fsm.o cert.o
+		     			   lmgr.o q931.o callc.o fsm.o
 hisax-$(CONFIG_HISAX_EURO)		+= l3dss1.o
 hisax-$(CONFIG_HISAX_NI1)		+= l3ni1.o
 hisax-$(CONFIG_HISAX_1TR6)		+= l3_1tr6.o
@@ -33,12 +37,12 @@ hisax-$(CONFIG_HISAX_S0BOX)		+= s0box.o 
 hisax-$(CONFIG_HISAX_AVM_A1)		+= avm_a1.o isac.o arcofi.o hscx.o
 hisax-$(CONFIG_HISAX_AVM_A1_PCMCIA)	+= avm_a1p.o isac.o arcofi.o hscx.o
 hisax-$(CONFIG_HISAX_FRITZPCI)		+= avm_pci.o isac.o arcofi.o
-hisax-$(CONFIG_HISAX_ELSA)		+= elsa.o isac.o arcofi.o hscx.o ipac.o
+hisax-$(CONFIG_HISAX_ELSA)		+= elsa.o isac.o arcofi.o hscx.o
 hisax-$(CONFIG_HISAX_IX1MICROR2)	+= ix1_micro.o isac.o arcofi.o hscx.o
-hisax-$(CONFIG_HISAX_DIEHLDIVA)		+= diva.o isac.o arcofi.o hscx.o ipac.o ipacx.o 
-hisax-$(CONFIG_HISAX_ASUSCOM)		+= asuscom.o isac.o arcofi.o hscx.o ipac.o
+hisax-$(CONFIG_HISAX_DIEHLDIVA)		+= diva.o isac.o arcofi.o hscx.o ipacx.o 
+hisax-$(CONFIG_HISAX_ASUSCOM)		+= asuscom.o isac.o arcofi.o hscx.o
 hisax-$(CONFIG_HISAX_TELEINT)		+= teleint.o isac.o arcofi.o hfc_2bs0.o
-hisax-$(CONFIG_HISAX_SEDLBAUER)		+= sedlbauer.o isac.o arcofi.o hscx.o ipac.o \
+hisax-$(CONFIG_HISAX_SEDLBAUER)		+= sedlbauer.o isac.o arcofi.o hscx.o \
 					   isar.o
 hisax-$(CONFIG_HISAX_SPORTSTER)		+= sportster.o isac.o arcofi.o hscx.o
 hisax-$(CONFIG_HISAX_MIC)		+= mic.o isac.o arcofi.o hscx.o
@@ -51,11 +55,9 @@ hisax-$(CONFIG_HISAX_NICCY)		+= niccy.o 
 hisax-$(CONFIG_HISAX_ISURF)		+= isurf.o isac.o arcofi.o isar.o
 hisax-$(CONFIG_HISAX_HSTSAPHIR)		+= saphir.o isac.o arcofi.o hscx.o
 hisax-$(CONFIG_HISAX_BKM_A4T)		+= bkm_a4t.o isac.o arcofi.o jade.o
-hisax-$(CONFIG_HISAX_SCT_QUADRO)	+= bkm_a8.o isac.o arcofi.o hscx.o ipac.o
-hisax-$(CONFIG_HISAX_GAZEL)		+= gazel.o isac.o arcofi.o hscx.o ipac.o
+hisax-$(CONFIG_HISAX_SCT_QUADRO)	+= bkm_a8.o isac.o arcofi.o hscx.o
+hisax-$(CONFIG_HISAX_GAZEL)		+= gazel.o isac.o arcofi.o hscx.o
 hisax-$(CONFIG_HISAX_W6692)		+= w6692.o
 hisax-$(CONFIG_HISAX_ENTERNOW_PCI)	+= enternow_pci.o amd7930_fn.o
 #hisax-$(CONFIG_HISAX_TESTEMU)		+= testemu.o
 
-CERT = $(shell cd $(src); md5sum -c md5sums.asc > /dev/null 2> /dev/null ;echo $$?)
-CFLAGS_cert.o = -DCERTIFICATION=$(CERT)
--- diff/drivers/isdn/hisax/amd7930_fn.c	2003-09-17 12:28:06.000000000 +0100
+++ source/drivers/isdn/hisax/amd7930_fn.c	2004-02-23 13:56:42.000000000 +0000
@@ -62,42 +62,53 @@
 
 static void Amd7930_new_ph(struct IsdnCardState *cs);
 
-static inline u8
-HIBYTE(u16 w)
-{
-	return (w >> 8) & 0xff;
-}
+static WORD initAMD[] = {
+	0x0100,
 
-static inline u8
-LOBYTE(u16 w)
-{
-	return w & 0xff;
-}
+	0x00A5, 3, 0x01, 0x40, 0x58,				// LPR, LMR1, LMR2
+	0x0086, 1, 0x0B,					// DMR1 (D-Buffer TH-Interrupts on)
+	0x0087, 1, 0xFF,					// DMR2
+	0x0092, 1, 0x03,					// EFCR (extended mode d-channel-fifo on)
+	0x0090, 4, 0xFE, 0xFF, 0x02, 0x0F,			// FRAR4, SRAR4, DMR3, DMR4 (address recognition )
+	0x0084, 2, 0x80, 0x00,					// DRLR
+	0x00C0, 1, 0x47,					// PPCR1
+	0x00C8, 1, 0x01,					// PPCR2
 
-static inline u8
-rByteAMD(struct IsdnCardState *cs, u8 reg)
-{
-	return cs->dc_hw_ops->read_reg(cs, reg);
-}
+	0x0102,
+	0x0107,
+	0x01A1, 1,
+	0x0121, 1,
+	0x0189, 2,
 
-static inline void
-wByteAMD(struct IsdnCardState *cs, u8 reg, u8 val)
-{
-	cs->dc_hw_ops->write_reg(cs, reg, val);
-}
+	0x0045, 4, 0x61, 0x72, 0x00, 0x00,			// MCR1, MCR2, MCR3, MCR4
+	0x0063, 2, 0x08, 0x08,					// GX
+	0x0064, 2, 0x08, 0x08,					// GR
+	0x0065, 2, 0x99, 0x00,					// GER
+	0x0066, 2, 0x7C, 0x8B,					// STG
+	0x0067, 2, 0x00, 0x00,					// FTGR1, FTGR2
+	0x0068, 2, 0x20, 0x20,					// ATGR1, ATGR2
+	0x0069, 1, 0x4F,					// MMR1
+	0x006A, 1, 0x00,					// MMR2
+	0x006C, 1, 0x40,					// MMR3
+	0x0021, 1, 0x02,					// INIT
+	0x00A3, 1, 0x40,					// LMR1
 
-static void
-wWordAMD(struct IsdnCardState *cs, u8 reg, u16 val)
+	0xFFFF
+};
+
+
+void /* macro wWordAMD */
+WriteWordAmd7930(struct IsdnCardState *cs, BYTE reg, WORD val)
 {
         wByteAMD(cs, 0x00, reg);
         wByteAMD(cs, 0x01, LOBYTE(val));
         wByteAMD(cs, 0x01, HIBYTE(val));
 }
 
-static u16
-rWordAMD(struct IsdnCardState *cs, u8 reg)
+WORD /* macro rWordAMD */
+ReadWordAmd7930(struct IsdnCardState *cs, BYTE reg)
 {
-        u16 res;
+        WORD res;
         /* direct access register */
         if(reg < 8) {
         	res = rByteAMD(cs, reg);
@@ -112,20 +123,9 @@ rWordAMD(struct IsdnCardState *cs, u8 re
 	return (res);
 }
 
-static inline void
-AmdIrqOff(struct IsdnCardState *cs)
-{
-	cs->dc.amd7930.setIrqMask(cs, 0);
-}
-
-static inline void
-AmdIrqOn(struct IsdnCardState *cs)
-{
-	cs->dc.amd7930.setIrqMask(cs, 1);
-}
 
 static void
-Amd7930_ph_command(struct IsdnCardState *cs, u8 command, char *s)
+Amd7930_ph_command(struct IsdnCardState *cs, u_char command, char *s)
 {
 	if (cs->debug & L1_DEB_ISAC)
 		debugl1(cs, "AMD7930: %s: ph_command 0x%02X", s, command);
@@ -136,7 +136,7 @@ Amd7930_ph_command(struct IsdnCardState 
 
 
 
-static u8 i430States[] = {
+static BYTE i430States[] = {
 // to   reset  F3    F4    F5    F6    F7    F8    AR     from
         0x01, 0x02, 0x00, 0x00, 0x00, 0x07, 0x05, 0x00,   // init
         0x01, 0x02, 0x00, 0x00, 0x00, 0x07, 0x05, 0x00,   // reset
@@ -150,14 +150,14 @@ static u8 i430States[] = {
 
 
 /*                    Row     init    -   reset  F3    F4    F5    F6    F7    F8    AR */
-static u8 stateHelper[] = { 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08 };
+static BYTE stateHelper[] = { 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08 };
 
 
 
 
 static void
 Amd7930_get_state(struct IsdnCardState *cs) {
-        u8 lsr = rByteAMD(cs, 0xA1);
+        BYTE lsr = rByteAMD(cs, 0xA1);
         cs->dc.amd7930.ph_state = (lsr & 0x7) + 2;
         Amd7930_new_ph(cs);
 }
@@ -167,8 +167,8 @@ Amd7930_get_state(struct IsdnCardState *
 static void
 Amd7930_new_ph(struct IsdnCardState *cs)
 {
-        u8 index = stateHelper[cs->dc.amd7930.old_state]*8 + stateHelper[cs->dc.amd7930.ph_state]-1;
-        u8 message = i430States[index];
+        u_char index = stateHelper[cs->dc.amd7930.old_state]*8 + stateHelper[cs->dc.amd7930.ph_state]-1;
+        u_char message = i430States[index];
 
         if (cs->debug & L1_DEB_ISAC)
 		debugl1(cs, "AMD7930: new_ph %d, old_ph %d, message %d, index %d",
@@ -176,7 +176,7 @@ Amd7930_new_ph(struct IsdnCardState *cs)
 
         cs->dc.amd7930.old_state = cs->dc.amd7930.ph_state;
 
-        /* abort transmit if necessary */
+        /* abort transmit if nessesary */
         if ((message & 0xf0) && (cs->tx_skb)) {
                 wByteAMD(cs, 0x21, 0xC2);
                 wByteAMD(cs, 0x21, 0x02);
@@ -232,9 +232,9 @@ Amd7930_new_ph(struct IsdnCardState *cs)
 
 
 static void
-Amd7930_bh(void *data)
+Amd7930_bh(struct IsdnCardState *cs)
 {
-	struct IsdnCardState *cs = data;
+
         struct PStack *stptr;
 
 	if (!cs)
@@ -244,7 +244,7 @@ Amd7930_bh(void *data)
 			debugl1(cs, "Amd7930: bh, D-Channel Busy cleared");
 		stptr = cs->stlist;
 		while (stptr != NULL) {
-			stptr->l2.l1l2(stptr, PH_PAUSE | CONFIRM, NULL);
+			stptr->l1.l1l2(stptr, PH_PAUSE | CONFIRM, NULL);
 			stptr = stptr->next;
 		}
 	}
@@ -267,13 +267,12 @@ Amd7930_bh(void *data)
         }
 }
 
-
 static void
 Amd7930_empty_Dfifo(struct IsdnCardState *cs, int flag)
 {
 
-        u8 stat, der;
-	u8 *ptr;
+        BYTE stat, der;
+	BYTE *ptr;
 	struct sk_buff *skb;
 
 
@@ -317,7 +316,7 @@ Amd7930_empty_Dfifo(struct IsdnCardState
 								QuickHex(t, cs->rcvbuf, cs->rcvidx);
 								debugl1(cs, cs->dlog);
 							}
-                                                        /* moves received data in sk-buffer */
+                                                        /* moves recieved data in sk-buffer */
 							memcpy(skb_put(skb, cs->rcvidx), cs->rcvbuf, cs->rcvidx);
 							skb_queue_tail(&cs->rq, skb);
 						}
@@ -327,10 +326,10 @@ Amd7930_empty_Dfifo(struct IsdnCardState
                                 /* throw damaged packets away, reset recieve-buffer, indicate RX */
 				ptr = cs->rcvbuf;
 				cs->rcvidx = 0;
-				sched_d_event(cs, D_RCVBUFREADY);
+				schedule_event(cs, D_RCVBUFREADY);
 			}
                 }
-		/* Packet too long, overflow */
+		/* Packet to long, overflow */
 		if(cs->rcvidx >= MAX_DFRAME_LEN_L1) {
 			if (cs->debug & L1_DEB_WARN)
 			        debugl1(cs, "AMD7930: empty_Dfifo L2-Framelength overrun");
@@ -346,9 +345,9 @@ static void
 Amd7930_fill_Dfifo(struct IsdnCardState *cs)
 {
 
-        u16 dtcrr, dtcrw, len, count;
-        u8 txstat, dmr3;
-        u8 *ptr, *deb_ptr;
+        WORD dtcrr, dtcrw, len, count;
+        BYTE txstat, dmr3;
+        BYTE *ptr, *deb_ptr;
 
 	if ((cs->debug & L1_DEB_ISAC) && !(cs->debug & L1_DEB_ISAC_FIFO))
 		debugl1(cs, "Amd7930: fill_Dfifo");
@@ -414,10 +413,10 @@ Amd7930_fill_Dfifo(struct IsdnCardState 
 }
 
 
-void Amd7930_interrupt(struct IsdnCardState *cs, u8 irflags)
+void Amd7930_interrupt(struct IsdnCardState *cs, BYTE irflags)
 {
-	u8 dsr1, dsr2, lsr;
-        u16 der;
+	BYTE dsr1, dsr2, lsr;
+        WORD der;
 
  while (irflags)
  {
@@ -443,7 +442,7 @@ void Amd7930_interrupt(struct IsdnCardSt
 			if (test_and_clear_bit(FLG_DBUSY_TIMER, &cs->HW_Flags))
 				del_timer(&cs->dbusytimer);
 			if (test_and_clear_bit(FLG_L1_DBUSY, &cs->HW_Flags))
-				sched_d_event(cs, D_CLEARBUSY);
+				schedule_event(cs, D_CLEARBUSY);
                         /* restart frame */
                         if (cs->tx_skb) {
 				skb_push(cs->tx_skb, cs->tx_cnt);
@@ -461,7 +460,7 @@ void Amd7930_interrupt(struct IsdnCardSt
 		if (test_and_clear_bit(FLG_DBUSY_TIMER, &cs->HW_Flags))
 			del_timer(&cs->dbusytimer);
 		if (test_and_clear_bit(FLG_L1_DBUSY, &cs->HW_Flags))
-			sched_d_event(cs, D_CLEARBUSY);
+			schedule_event(cs, D_CLEARBUSY);
                 /* restart TX-Frame */
                 if (cs->tx_skb) {
 			skb_push(cs->tx_skb, cs->tx_cnt);
@@ -482,7 +481,7 @@ void Amd7930_interrupt(struct IsdnCardSt
                 if (test_and_clear_bit(FLG_DBUSY_TIMER, &cs->HW_Flags))
 			del_timer(&cs->dbusytimer);
 		if (test_and_clear_bit(FLG_L1_DBUSY, &cs->HW_Flags))
-			sched_d_event(cs, D_CLEARBUSY);
+			schedule_event(cs, D_CLEARBUSY);
 		if (cs->tx_skb) {
 			if (cs->tx_skb->len)
 				Amd7930_fill_Dfifo(cs);
@@ -511,7 +510,7 @@ void Amd7930_interrupt(struct IsdnCardSt
                 if (test_and_clear_bit(FLG_DBUSY_TIMER, &cs->HW_Flags))
 			del_timer(&cs->dbusytimer);
 		if (test_and_clear_bit(FLG_L1_DBUSY, &cs->HW_Flags))
-			sched_d_event(cs, D_CLEARBUSY);
+			schedule_event(cs, D_CLEARBUSY);
 
                 if (cs->tx_skb) {
         		if (cs->debug & L1_DEB_ISAC)
@@ -529,7 +528,7 @@ void Amd7930_interrupt(struct IsdnCardSt
 			Amd7930_fill_Dfifo(cs);
 		}
                 else
-			sched_d_event(cs, D_XMTBUFREADY);
+			schedule_event(cs, D_XMTBUFREADY);
 		/* AMD interrupts on */
                 AmdIrqOn(cs);
         }
@@ -544,7 +543,7 @@ void Amd7930_interrupt(struct IsdnCardSt
 
 		cs->dc.amd7930.ph_state = (lsr & 0x7) + 2;
 
-		sched_d_event(cs, D_L1STATECHANGE);
+		schedule_event(cs, D_L1STATECHANGE);
 		/* AMD interrupts on */
                 AmdIrqOn(cs);
 	}
@@ -560,6 +559,7 @@ Amd7930_l1hw(struct PStack *st, int pr, 
 {
         struct IsdnCardState *cs = (struct IsdnCardState *) st->l1.hardware;
 	struct sk_buff *skb = arg;
+	u_long flags;
 
         if (cs->debug & L1_DEB_ISAC)
 		debugl1(cs, "Amd7930: l1hw called, pr: 0x%04X", pr);
@@ -570,6 +570,7 @@ Amd7930_l1hw(struct PStack *st, int pr, 
 				LogFrame(cs, skb->data, skb->len);
 			if (cs->debug & DEB_DLOG_VERBOSE)
 				dlogframe(cs, skb, 0);
+			spin_lock_irqsave(&cs->lock, flags);
 			if (cs->tx_skb) {
 				skb_queue_tail(&cs->sq, skb);
 #ifdef L2FRAME_DEBUG		/* psa */
@@ -586,8 +587,10 @@ Amd7930_l1hw(struct PStack *st, int pr, 
 #endif
 				Amd7930_fill_Dfifo(cs);
 			}
+			spin_unlock_irqrestore(&cs->lock, flags);
 			break;
 		case (PH_PULL | INDICATION):
+			spin_lock_irqsave(&cs->lock, flags);
 			if (cs->tx_skb) {
 				if (cs->debug & L1_DEB_WARN)
 					debugl1(cs, "Amd7930: l1hw: l2l1 tx_skb exist this shouldn't happen");
@@ -606,6 +609,7 @@ Amd7930_l1hw(struct PStack *st, int pr, 
 				Logl2Frame(cs, skb, "Amd7930: l1hw: PH_DATA_PULLED", 0);
 #endif
 			Amd7930_fill_Dfifo(cs);
+			spin_unlock_irqrestore(&cs->lock, flags);
 			break;
 		case (PH_PULL | REQUEST):
 #ifdef L2FRAME_DEBUG		/* psa */
@@ -614,21 +618,23 @@ Amd7930_l1hw(struct PStack *st, int pr, 
 #endif
 			if (!cs->tx_skb) {
 				test_and_clear_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
-				st->l2.l1l2(st, PH_PULL | CONFIRM, NULL);
+				st->l1.l1l2(st, PH_PULL | CONFIRM, NULL);
 			} else
 				test_and_set_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
 			break;
 		case (HW_RESET | REQUEST):
-
-                        if ((cs->dc.amd7930.ph_state == 8))
-                                /* b-channels off, PH-AR cleared
-                                 * change to F3 */
-                                Amd7930_ph_command(cs, 0x20, "HW_RESET REQEST"); //LMR1 bit 5
-			else {
-                                Amd7930_ph_command(cs, 0x40, "HW_RESET REQUEST");
-                                cs->dc.amd7930.ph_state = 2;
-                                Amd7930_new_ph(cs);
-                        }
+			spin_lock_irqsave(&cs->lock, flags);
+			if ((cs->dc.amd7930.ph_state == 8)) {
+				/* b-channels off, PH-AR cleared
+				 * change to F3 */
+				Amd7930_ph_command(cs, 0x20, "HW_RESET REQEST"); //LMR1 bit 5
+				spin_unlock_irqrestore(&cs->lock, flags);
+			} else {
+				Amd7930_ph_command(cs, 0x40, "HW_RESET REQUEST");
+				cs->dc.amd7930.ph_state = 2;
+				spin_unlock_irqrestore(&cs->lock, flags);
+				Amd7930_new_ph(cs);
+			}
 			break;
 		case (HW_ENABLE | REQUEST):
                         cs->dc.amd7930.ph_state = 9;
@@ -650,7 +656,7 @@ Amd7930_l1hw(struct PStack *st, int pr, 
 			if (test_and_clear_bit(FLG_DBUSY_TIMER, &cs->HW_Flags))
 				del_timer(&cs->dbusytimer);
 			if (test_and_clear_bit(FLG_L1_DBUSY, &cs->HW_Flags))
-				sched_d_event(cs, D_CLEARBUSY);
+				schedule_event(cs, D_CLEARBUSY);
 			break;
 		default:
 			if (cs->debug & L1_DEB_WARN)
@@ -659,7 +665,7 @@ Amd7930_l1hw(struct PStack *st, int pr, 
 	}
 }
 
-static int
+void
 setstack_Amd7930(struct PStack *st, struct IsdnCardState *cs)
 {
 
@@ -667,21 +673,30 @@ setstack_Amd7930(struct PStack *st, stru
 		debugl1(cs, "Amd7930: setstack called");
 
         st->l1.l1hw = Amd7930_l1hw;
-	return 0;
 }
 
+
+void
+DC_Close_Amd7930(struct IsdnCardState *cs) {
+        if (cs->debug & L1_DEB_ISAC)
+		debugl1(cs, "Amd7930: DC_Close called");
+}
+
+
 static void
 dbusy_timer_handler(struct IsdnCardState *cs)
 {
+	u_long flags;
 	struct PStack *stptr;
-        u16 dtcr, der;
-        u8 dsr1, dsr2;
+        WORD dtcr, der;
+        BYTE dsr1, dsr2;
 
 
         if (cs->debug & L1_DEB_ISAC)
 		debugl1(cs, "Amd7930: dbusy_timer expired!");
 
 	if (test_bit(FLG_DBUSY_TIMER, &cs->HW_Flags)) {
+		spin_lock_irqsave(&cs->lock, flags);
                 /* D Transmit Byte Count Register:
                  * Counts down packet's number of Bytes, 0 if packet ready */
                 dtcr = rWordAMD(cs, 0x85);
@@ -689,14 +704,15 @@ dbusy_timer_handler(struct IsdnCardState
                 dsr2 = rByteAMD(cs, 0x07);
                 der  = rWordAMD(cs, 0x03);
 
-        if (cs->debug & L1_DEB_ISAC)
-		debugl1(cs, "Amd7930: dbusy_timer_handler: DSR1=0x%02X, DSR2=0x%02X, DER=0x%04X, cs->tx_skb->len=%u, tx_stat=%u, dtcr=%u, cs->tx_cnt=%u", dsr1, dsr2, der, cs->tx_skb->len, cs->dc.amd7930.tx_xmtlen, dtcr, cs->tx_cnt);
+	        if (cs->debug & L1_DEB_ISAC)
+			debugl1(cs, "Amd7930: dbusy_timer_handler: DSR1=0x%02X, DSR2=0x%02X, DER=0x%04X, cs->tx_skb->len=%u, tx_stat=%u, dtcr=%u, cs->tx_cnt=%u", dsr1, dsr2, der, cs->tx_skb->len, cs->dc.amd7930.tx_xmtlen, dtcr, cs->tx_cnt);
 
-		if ((int)(cs->dc.amd7930.tx_xmtlen - dtcr) < cs->tx_cnt) {	/* D-Channel Busy */
+		if ((cs->dc.amd7930.tx_xmtlen - dtcr) < cs->tx_cnt) {	/* D-Channel Busy */
 			test_and_set_bit(FLG_L1_DBUSY, &cs->HW_Flags);
 			stptr = cs->stlist;
+			spin_unlock_irqrestore(&cs->lock, flags);
 			while (stptr != NULL) {
-				stptr->l2.l1l2(stptr, PH_PAUSE | INDICATION, NULL);
+				stptr->l1.l1l2(stptr, PH_PAUSE | INDICATION, NULL);
 				stptr = stptr->next;
 			}
 
@@ -716,7 +732,8 @@ dbusy_timer_handler(struct IsdnCardState
 			/* Transmitter reset, abort transmit */
 			wByteAMD(cs, 0x21, 0x82);
 			wByteAMD(cs, 0x21, 0x02);
-			cs->card_ops->irq_func(cs->irq, cs, NULL); /* FIXME? */
+			spin_unlock_irqrestore(&cs->lock, flags);
+			cs->irq_func(cs->irq, cs, NULL);
 
                         if (cs->debug & L1_DEB_ISAC)
 				debugl1(cs, "Amd7930: dbusy_timer_handler: Transmitter reset");
@@ -724,59 +741,23 @@ dbusy_timer_handler(struct IsdnCardState
 	}
 }
 
-static u16 initAMD[] = {
-	0x0100,
 
-	0x00A5, 3, 0x01, 0x40, 0x58,				// LPR, LMR1, LMR2
-	0x0086, 1, 0x0B,					// DMR1 (D-Buffer TH-Interrupts on)
-	0x0087, 1, 0xFF,					// DMR2
-	0x0092, 1, 0x03,					// EFCR (extended mode d-channel-fifo on)
-	0x0090, 4, 0xFE, 0xFF, 0x02, 0x0F,			// FRAR4, SRAR4, DMR3, DMR4 (address recognition )
-	0x0084, 2, 0x80, 0x00,					// DRLR
-	0x00C0, 1, 0x47,					// PPCR1
-	0x00C8, 1, 0x01,					// PPCR2
-
-	0x0102,
-	0x0107,
-	0x01A1, 1,
-	0x0121, 1,
-	0x0189, 2,
-
-	0x0045, 4, 0x61, 0x72, 0x00, 0x00,			// MCR1, MCR2, MCR3, MCR4
-	0x0063, 2, 0x08, 0x08,					// GX
-	0x0064, 2, 0x08, 0x08,					// GR
-	0x0065, 2, 0x99, 0x00,					// GER
-	0x0066, 2, 0x7C, 0x8B,					// STG
-	0x0067, 2, 0x00, 0x00,					// FTGR1, FTGR2
-	0x0068, 2, 0x20, 0x20,					// ATGR1, ATGR2
-	0x0069, 1, 0x4F,					// MMR1
-	0x006A, 1, 0x00,					// MMR2
-	0x006C, 1, 0x40,					// MMR3
-	0x0021, 1, 0x02,					// INIT
-	0x00A3, 1, 0x40,					// LMR1
-
-	0xFFFF};
-
-static struct dc_l1_ops amd7930_l1_ops = {
-	.open       = setstack_Amd7930,
-	.bh_func    = Amd7930_bh,
-	.dbusy_func = dbusy_timer_handler,
-};
 
 void __devinit
 Amd7930_init(struct IsdnCardState *cs)
 {
-	u16 *ptr;
-	u8 cmd, cnt;
+    WORD *ptr;
+    BYTE cmd, cnt;
 
         if (cs->debug & L1_DEB_ISAC)
 		debugl1(cs, "Amd7930: initamd called");
 
-	dc_l1_init(cs, &amd7930_l1_ops);
         cs->dc.amd7930.tx_xmtlen = 0;
         cs->dc.amd7930.old_state = 0;
         cs->dc.amd7930.lmr1 = 0x40;
         cs->dc.amd7930.ph_command = Amd7930_ph_command;
+	cs->setstack_d = setstack_Amd7930;
+	cs->DC_Close = DC_Close_Amd7930;
 
 	/* AMD Initialisation */
 	for (ptr = initAMD; *ptr != 0xFFFF; ) {
@@ -805,11 +786,11 @@ Amd7930_init(struct IsdnCardState *cs)
 	}
 }
 
-int
-amd7930_setup(struct IsdnCardState *cs, struct dc_hw_ops *amd7930_ops,
-	      void (*set_irq_mask)(struct IsdnCardState *, u8 val))
-{
-	cs->dc_hw_ops = amd7930_ops;
-        cs->dc.amd7930.setIrqMask = set_irq_mask;
-	return 0;
+void __devinit
+setup_Amd7930(struct IsdnCardState *cs)
+{
+        INIT_WORK(&cs->tqueue, (void *)(void *) Amd7930_bh, cs);
+	cs->dbusytimer.function = (void *) dbusy_timer_handler;
+	cs->dbusytimer.data = (long) cs;
+	init_timer(&cs->dbusytimer);
 }
--- diff/drivers/isdn/hisax/amd7930_fn.h	2003-01-16 11:30:36.000000000 +0000
+++ source/drivers/isdn/hisax/amd7930_fn.h	2004-02-23 13:56:42.000000000 +0000
@@ -12,13 +12,26 @@
  */
 
 
+
+
+#define BYTE							unsigned char
+#define WORD							unsigned int
+#define rByteAMD(cs, reg)					cs->readisac(cs, reg)
+#define wByteAMD(cs, reg, val)					cs->writeisac(cs, reg, val)
+#define rWordAMD(cs, reg)					ReadWordAmd7930(cs, reg)
+#define wWordAMD(cs, reg, val)					WriteWordAmd7930(cs, reg, val)
+#define HIBYTE(w)						((unsigned char)((w & 0xff00) / 256))
+#define LOBYTE(w)						((unsigned char)(w & 0x00ff))
+
+#define AmdIrqOff(cs)						cs->dc.amd7930.setIrqMask(cs, 0)
+#define AmdIrqOn(cs)						cs->dc.amd7930.setIrqMask(cs, 1)
+
 #define AMD_CR		0x00
 #define AMD_DR		0x01
 
 
 #define DBUSY_TIMER_VALUE 80
 
-void Amd7930_interrupt(struct IsdnCardState *cs, unsigned char irflags);
-void Amd7930_init(struct IsdnCardState *cs);
-int  amd7930_setup(struct IsdnCardState *cs, struct dc_hw_ops *amd7930_ops,
-		   void (*set_irq_mask)(struct IsdnCardState *, u8 val));
+extern void Amd7930_interrupt(struct IsdnCardState *, unsigned char);
+extern void Amd7930_init(struct IsdnCardState *);
+extern void setup_Amd7930(struct IsdnCardState *);
--- diff/drivers/isdn/hisax/arcofi.c	2003-01-13 14:18:15.000000000 +0000
+++ source/drivers/isdn/hisax/arcofi.c	2004-02-23 13:56:42.000000000 +0000
@@ -1,4 +1,4 @@
-/* $Id: arcofi.c,v 1.12.6.2 2001/09/23 22:24:46 kai Exp $
+/* $Id: arcofi.c,v 1.14.2.3 2004/01/13 14:31:24 keil Exp $
  *
  * Ansteuerung ARCOFI 2165
  *
@@ -17,19 +17,6 @@
 
 #define ARCOFI_TIMER_VALUE	20
 
-
-static inline u8
-isac_read(struct IsdnCardState *cs, u8 addr)
-{
-	return cs->dc_hw_ops->read_reg(cs, addr);
-}
-
-static inline void
-isac_write(struct IsdnCardState *cs, u8 addr, u8 val)
-{
-	cs->dc_hw_ops->write_reg(cs, addr, val);
-}
-
 static void
 add_arcofi_timer(struct IsdnCardState *cs) {
 	if (test_and_set_bit(FLG_ARCOFI_TIMER, &cs->HW_Flags)) {
@@ -42,7 +29,7 @@ add_arcofi_timer(struct IsdnCardState *c
 
 static void
 send_arcofi(struct IsdnCardState *cs) {
-	u8 val;
+	u_char val;
 	
 	add_arcofi_timer(cs);
 	cs->dc.isac.mon_txp = 0;
@@ -56,11 +43,11 @@ send_arcofi(struct IsdnCardState *cs) {
 	}
 	cs->dc.isac.mocr &= 0x0f;
 	cs->dc.isac.mocr |= 0xa0;
-	isac_write(cs, ISAC_MOCR, cs->dc.isac.mocr);
-	val = isac_read(cs, ISAC_MOSR);
-	isac_write(cs, ISAC_MOX1, cs->dc.isac.mon_tx[cs->dc.isac.mon_txp++]);
+	cs->writeisac(cs, ISAC_MOCR, cs->dc.isac.mocr);
+	val = cs->readisac(cs, ISAC_MOSR);
+	cs->writeisac(cs, ISAC_MOX1, cs->dc.isac.mon_tx[cs->dc.isac.mon_txp++]);
 	cs->dc.isac.mocr |= 0x10;
-	isac_write(cs, ISAC_MOCR, cs->dc.isac.mocr);
+	cs->writeisac(cs, ISAC_MOCR, cs->dc.isac.mocr);
 }
 
 int
--- diff/drivers/isdn/hisax/asuscom.c	2003-05-21 11:49:50.000000000 +0100
+++ source/drivers/isdn/hisax/asuscom.c	2004-02-23 13:56:42.000000000 +0000
@@ -1,4 +1,4 @@
-/* $Id: asuscom.c,v 1.11.6.3 2001/09/23 22:24:46 kai Exp $
+/* $Id: asuscom.c,v 1.14.2.4 2004/01/13 23:48:39 keil Exp $
  *
  * low level stuff for ASUSCOM NETWORK INC. ISDNLink cards
  *
@@ -22,9 +22,8 @@
 
 extern const char *CardType[];
 
-const char *Asuscom_revision = "$Revision: 1.11.6.3 $";
+const char *Asuscom_revision = "$Revision: 1.14.2.4 $";
 
-static spinlock_t asuscom_lock = SPIN_LOCK_UNLOCKED;
 #define byteout(addr,val) outb(val,addr)
 #define bytein(addr) inb(addr)
 
@@ -43,237 +42,258 @@ static spinlock_t asuscom_lock = SPIN_LO
 /* CARD_ADR (Write) */
 #define ASUS_RESET      0x80	/* Bit 7 Reset-Leitung */
 
-static inline u8
-readreg(struct IsdnCardState *cs, unsigned int adr, u8 off)
+static inline u_char
+readreg(unsigned int ale, unsigned int adr, u_char off)
 {
-	u8 ret;
-	unsigned long flags;
+	register u_char ret;
 
-	spin_lock_irqsave(&asuscom_lock, flags);
-	byteout(cs->hw.asus.adr, off);
+	byteout(ale, off);
 	ret = bytein(adr);
-	spin_unlock_irqrestore(&asuscom_lock, flags);
-	return ret;
+	return (ret);
 }
 
 static inline void
-writereg(struct IsdnCardState *cs, unsigned int adr, u8 off, u8 data)
+readfifo(unsigned int ale, unsigned int adr, u_char off, u_char * data, int size)
 {
-	unsigned long flags;
-
-	spin_lock_irqsave(&asuscom_lock, flags);
-	byteout(cs->hw.asus.adr, off);
-	byteout(adr, data);
-	spin_unlock_irqrestore(&asuscom_lock, flags);
+	byteout(ale, off);
+	insb(adr, data, size);
 }
 
+
 static inline void
-readfifo(struct IsdnCardState *cs, unsigned int adr, u8 off, u8 * data, int size)
+writereg(unsigned int ale, unsigned int adr, u_char off, u_char data)
 {
-	byteout(cs->hw.asus.adr, off);
-	insb(adr, data, size);
+	byteout(ale, off);
+	byteout(adr, data);
 }
 
-
 static inline void
-writefifo(struct IsdnCardState *cs, unsigned int adr, u8 off, u8 * data, int size)
+writefifo(unsigned int ale, unsigned int adr, u_char off, u_char * data, int size)
 {
-	byteout(cs->hw.asus.adr, off);
+	byteout(ale, off);
 	outsb(adr, data, size);
 }
 
-static u8
-isac_read(struct IsdnCardState *cs, u8 offset)
+/* Interface functions */
+
+static u_char
+ReadISAC(struct IsdnCardState *cs, u_char offset)
 {
-	return readreg(cs, cs->hw.asus.isac, offset);
+	return (readreg(cs->hw.asus.adr, cs->hw.asus.isac, offset));
 }
 
 static void
-isac_write(struct IsdnCardState *cs, u8 offset, u8 value)
+WriteISAC(struct IsdnCardState *cs, u_char offset, u_char value)
 {
-	writereg(cs, cs->hw.asus.isac, offset, value);
+	writereg(cs->hw.asus.adr, cs->hw.asus.isac, offset, value);
 }
 
 static void
-isac_read_fifo(struct IsdnCardState *cs, u8 * data, int size)
+ReadISACfifo(struct IsdnCardState *cs, u_char * data, int size)
 {
-	readfifo(cs, cs->hw.asus.isac, 0, data, size);
+	readfifo(cs->hw.asus.adr, cs->hw.asus.isac, 0, data, size);
 }
 
 static void
-isac_write_fifo(struct IsdnCardState *cs, u8 * data, int size)
+WriteISACfifo(struct IsdnCardState *cs, u_char * data, int size)
 {
-	writefifo(cs, cs->hw.asus.isac, 0, data, size);
+	writefifo(cs->hw.asus.adr, cs->hw.asus.isac, 0, data, size);
 }
 
-static struct dc_hw_ops isac_ops = {
-	.read_reg   = isac_read,
-	.write_reg  = isac_write,
-	.read_fifo  = isac_read_fifo,
-	.write_fifo = isac_write_fifo,
-};
-
-static u8
-hscx_read(struct IsdnCardState *cs, int hscx, u8 offset)
+static u_char
+ReadISAC_IPAC(struct IsdnCardState *cs, u_char offset)
 {
-	return readreg(cs, cs->hw.asus.hscx, offset + (hscx ? 0x40 : 0));
+	return (readreg(cs->hw.asus.adr, cs->hw.asus.isac, offset|0x80));
 }
 
 static void
-hscx_write(struct IsdnCardState *cs, int hscx, u8 offset, u8 value)
+WriteISAC_IPAC(struct IsdnCardState *cs, u_char offset, u_char value)
 {
-	writereg(cs, cs->hw.asus.hscx, offset + (hscx ? 0x40 : 0), value);
+	writereg(cs->hw.asus.adr, cs->hw.asus.isac, offset|0x80, value);
 }
 
 static void
-hscx_read_fifo(struct IsdnCardState *cs, int hscx, u8 *data, int size)
+ReadISACfifo_IPAC(struct IsdnCardState *cs, u_char * data, int size)
 {
-	readfifo(cs, cs->hw.asus.hscx, hscx ? 0x40 : 0, data, size);
+	readfifo(cs->hw.asus.adr, cs->hw.asus.isac, 0x80, data, size);
 }
 
 static void
-hscx_write_fifo(struct IsdnCardState *cs, int hscx, u8 *data, int size)
+WriteISACfifo_IPAC(struct IsdnCardState *cs, u_char * data, int size)
 {
-	writefifo(cs, cs->hw.asus.hscx, hscx ? 0x40 : 0, data, size);
+	writefifo(cs->hw.asus.adr, cs->hw.asus.isac, 0x80, data, size);
 }
 
-static struct bc_hw_ops hscx_ops = {
-	.read_reg   = hscx_read,
-	.write_reg  = hscx_write,
-	.read_fifo  = hscx_read_fifo,
-	.write_fifo = hscx_write_fifo,
-};
-
-static inline u8
-ipac_read(struct IsdnCardState *cs, u8 off)
+static u_char
+ReadHSCX(struct IsdnCardState *cs, int hscx, u_char offset)
 {
-	u8 ret;
-	unsigned long flags;
-
-	spin_lock_irqsave(&asuscom_lock, flags);
-	byteout(cs->hw.asus.adr, off);
-	ret = bytein(cs->hw.asus.isac);
-	spin_unlock_irqrestore(&asuscom_lock, flags);
-	return ret;
+	return (readreg(cs->hw.asus.adr,
+			cs->hw.asus.hscx, offset + (hscx ? 0x40 : 0)));
 }
 
-static inline void
-ipac_write(struct IsdnCardState *cs, u8 off, u8 data)
-{
-	unsigned long flags;
-
-	spin_lock_irqsave(&asuscom_lock, flags);
-	byteout(cs->hw.asus.adr, off);
-	byteout(cs->hw.asus.isac, data);
-	spin_unlock_irqrestore(&asuscom_lock, flags);
-}
-
-static inline void
-ipac_readfifo(struct IsdnCardState *cs, u8 off, u8 * data, int size)
+static void
+WriteHSCX(struct IsdnCardState *cs, int hscx, u_char offset, u_char value)
 {
-	byteout(cs->hw.asus.adr, off);
-	insb(cs->hw.asus.isac, data, size);
+	writereg(cs->hw.asus.adr,
+		 cs->hw.asus.hscx, offset + (hscx ? 0x40 : 0), value);
 }
 
+/*
+ * fast interrupt HSCX stuff goes here
+ */
 
-static inline void
-ipac_writefifo(struct IsdnCardState *cs, u8 off, u8 * data, int size)
-{
-	byteout(cs->hw.asus.adr, off);
-	outsb(cs->hw.asus.isac, data, size);
+#define READHSCX(cs, nr, reg) readreg(cs->hw.asus.adr, \
+		cs->hw.asus.hscx, reg + (nr ? 0x40 : 0))
+#define WRITEHSCX(cs, nr, reg, data) writereg(cs->hw.asus.adr, \
+		cs->hw.asus.hscx, reg + (nr ? 0x40 : 0), data)
+
+#define READHSCXFIFO(cs, nr, ptr, cnt) readfifo(cs->hw.asus.adr, \
+		cs->hw.asus.hscx, (nr ? 0x40 : 0), ptr, cnt)
+
+#define WRITEHSCXFIFO(cs, nr, ptr, cnt) writefifo(cs->hw.asus.adr, \
+		cs->hw.asus.hscx, (nr ? 0x40 : 0), ptr, cnt)
+
+#include "hscx_irq.c"
+
+static irqreturn_t
+asuscom_interrupt(int intno, void *dev_id, struct pt_regs *regs)
+{
+	struct IsdnCardState *cs = dev_id;
+	u_char val;
+	u_long flags;
+
+	spin_lock_irqsave(&cs->lock, flags);
+	val = readreg(cs->hw.asus.adr, cs->hw.asus.hscx, HSCX_ISTA + 0x40);
+      Start_HSCX:
+	if (val)
+		hscx_int_main(cs, val);
+	val = readreg(cs->hw.asus.adr, cs->hw.asus.isac, ISAC_ISTA);
+      Start_ISAC:
+	if (val)
+		isac_interrupt(cs, val);
+	val = readreg(cs->hw.asus.adr, cs->hw.asus.hscx, HSCX_ISTA + 0x40);
+	if (val) {
+		if (cs->debug & L1_DEB_HSCX)
+			debugl1(cs, "HSCX IntStat after IntRoutine");
+		goto Start_HSCX;
+	}
+	val = readreg(cs->hw.asus.adr, cs->hw.asus.isac, ISAC_ISTA);
+	if (val) {
+		if (cs->debug & L1_DEB_ISAC)
+			debugl1(cs, "ISAC IntStat after IntRoutine");
+		goto Start_ISAC;
+	}
+	writereg(cs->hw.asus.adr, cs->hw.asus.hscx, HSCX_MASK, 0xFF);
+	writereg(cs->hw.asus.adr, cs->hw.asus.hscx, HSCX_MASK + 0x40, 0xFF);
+	writereg(cs->hw.asus.adr, cs->hw.asus.isac, ISAC_MASK, 0xFF);
+	writereg(cs->hw.asus.adr, cs->hw.asus.isac, ISAC_MASK, 0x0);
+	writereg(cs->hw.asus.adr, cs->hw.asus.hscx, HSCX_MASK, 0x0);
+	writereg(cs->hw.asus.adr, cs->hw.asus.hscx, HSCX_MASK + 0x40, 0x0);
+	spin_unlock_irqrestore(&cs->lock, flags);
+	return IRQ_HANDLED;
+}
+
+static irqreturn_t
+asuscom_interrupt_ipac(int intno, void *dev_id, struct pt_regs *regs)
+{
+	struct IsdnCardState *cs = dev_id;
+	u_char ista, val, icnt = 5;
+	u_long flags;
+
+	spin_lock_irqsave(&cs->lock, flags);
+	ista = readreg(cs->hw.asus.adr, cs->hw.asus.isac, IPAC_ISTA);
+Start_IPAC:
+	if (cs->debug & L1_DEB_IPAC)
+		debugl1(cs, "IPAC ISTA %02X", ista);
+	if (ista & 0x0f) {
+		val = readreg(cs->hw.asus.adr, cs->hw.asus.hscx, HSCX_ISTA + 0x40);
+		if (ista & 0x01)
+			val |= 0x01;
+		if (ista & 0x04)
+			val |= 0x02;
+		if (ista & 0x08)
+			val |= 0x04;
+		if (val)
+			hscx_int_main(cs, val);
+	}
+	if (ista & 0x20) {
+		val = 0xfe & readreg(cs->hw.asus.adr, cs->hw.asus.isac, ISAC_ISTA | 0x80);
+		if (val) {
+			isac_interrupt(cs, val);
+		}
+	}
+	if (ista & 0x10) {
+		val = 0x01;
+		isac_interrupt(cs, val);
+	}
+	ista  = readreg(cs->hw.asus.adr, cs->hw.asus.isac, IPAC_ISTA);
+	if ((ista & 0x3f) && icnt) {
+		icnt--;
+		goto Start_IPAC;
+	}
+	if (!icnt)
+		printk(KERN_WARNING "ASUS IRQ LOOP\n");
+	writereg(cs->hw.asus.adr, cs->hw.asus.isac, IPAC_MASK, 0xFF);
+	writereg(cs->hw.asus.adr, cs->hw.asus.isac, IPAC_MASK, 0xC0);
+	spin_unlock_irqrestore(&cs->lock, flags);
+	return IRQ_HANDLED;
 }
 
-/* This will generate ipac_dc_ops and ipac_bc_ops using the functions
- * above */
+void
+release_io_asuscom(struct IsdnCardState *cs)
+{
+	int bytecnt = 8;
 
-BUILD_IPAC_OPS(ipac);
+	if (cs->hw.asus.cfg_reg)
+		release_region(cs->hw.asus.cfg_reg, bytecnt);
+}
 
-static int
-asuscom_reset(struct IsdnCardState *cs)
+static void
+reset_asuscom(struct IsdnCardState *cs)
 {
-	byteout(cs->hw.asus.adr, ASUS_RESET);	/* Reset On */
-	set_current_state(TASK_UNINTERRUPTIBLE);
-	schedule_timeout((10*HZ)/1000);
-	byteout(cs->hw.asus.adr, 0);	/* Reset Off */
-	set_current_state(TASK_UNINTERRUPTIBLE);
-	schedule_timeout((10*HZ)/1000);
-	return 0;
+	if (cs->subtyp == ASUS_IPAC)
+		writereg(cs->hw.asus.adr, cs->hw.asus.isac, IPAC_POTA2, 0x20);
+	else
+		byteout(cs->hw.asus.adr, ASUS_RESET);	/* Reset On */
+	mdelay(10);
+	if (cs->subtyp == ASUS_IPAC)
+		writereg(cs->hw.asus.adr, cs->hw.asus.isac, IPAC_POTA2, 0x0);
+	else
+		byteout(cs->hw.asus.adr, 0);	/* Reset Off */
+	mdelay(10);
+	if (cs->subtyp == ASUS_IPAC) {
+		writereg(cs->hw.asus.adr, cs->hw.asus.isac, IPAC_CONF, 0x0);
+		writereg(cs->hw.asus.adr, cs->hw.asus.isac, IPAC_ACFG, 0xff);
+		writereg(cs->hw.asus.adr, cs->hw.asus.isac, IPAC_AOE, 0x0);
+		writereg(cs->hw.asus.adr, cs->hw.asus.isac, IPAC_MASK, 0xc0);
+		writereg(cs->hw.asus.adr, cs->hw.asus.isac, IPAC_PCFG, 0x12);
+	}
 }
 
 static int
-asuscom_ipac_reset(struct IsdnCardState *cs)
+Asus_card_msg(struct IsdnCardState *cs, int mt, void *arg)
 {
-	writereg(cs, cs->hw.asus.isac, IPAC_POTA2, 0x20);
-	set_current_state(TASK_UNINTERRUPTIBLE);
-	schedule_timeout((10*HZ)/1000);
-	writereg(cs, cs->hw.asus.isac, IPAC_POTA2, 0x0);
-	set_current_state(TASK_UNINTERRUPTIBLE);
-	schedule_timeout((10*HZ)/1000);
-	writereg(cs, cs->hw.asus.isac, IPAC_CONF, 0x0);
-	writereg(cs, cs->hw.asus.isac, IPAC_ACFG, 0xff);
-	writereg(cs, cs->hw.asus.isac, IPAC_AOE, 0x0);
-	writereg(cs, cs->hw.asus.isac, IPAC_MASK, 0xc0);
-	writereg(cs, cs->hw.asus.isac, IPAC_PCFG, 0x12);
-	return 0;
-}
-
-static struct card_ops asuscom_ops = {
-	.init     = inithscxisac,
-	.reset    = asuscom_reset,
-	.release  = hisax_release_resources,
-	.irq_func = hscxisac_irq,
-};
-
-static struct card_ops asuscom_ipac_ops = {
-	.init     = ipac_init,
-	.reset    = asuscom_ipac_reset,
-	.release  = hisax_release_resources,
-	.irq_func = ipac_irq,
-};
+	u_long flags;
 
-static int __init
-asuscom_probe(struct IsdnCardState *cs, struct IsdnCard *card)
-{
-	int rc;
-	u8 val;
-
-	printk(KERN_INFO "ISDNLink: defined at %#lx IRQ %lu\n",
-	       card->para[1], card->para[0]);
-
-	cs->hw.asus.cfg_reg = card->para[1];
-	cs->irq = card->para[0];
-
-	rc = -EBUSY;
-	if (!request_io(&cs->rs, cs->hw.asus.cfg_reg, 8, "asuscom isdn"))
-		goto err;
-
-	rc = -ENODEV;
-	cs->hw.asus.adr = cs->hw.asus.cfg_reg + ASUS_IPAC_ALE;
-	val = readreg(cs, cs->hw.asus.cfg_reg + ASUS_IPAC_DATA, IPAC_ID);
-	if ((val == 1) || (val == 2)) {
-		cs->subtyp = ASUS_IPAC;
-		cs->card_ops = &asuscom_ipac_ops;
-		cs->hw.asus.isac = cs->hw.asus.cfg_reg + ASUS_IPAC_DATA;
-		if (ipac_setup(cs, &ipac_dc_ops, &ipac_bc_ops))
-			goto err;
-	} else {
-		cs->subtyp = ASUS_ISACHSCX;
-		cs->card_ops = &asuscom_ops;
-		cs->hw.asus.adr = cs->hw.asus.cfg_reg + ASUS_ADR;
-		cs->hw.asus.isac = cs->hw.asus.cfg_reg + ASUS_ISAC;
-		cs->hw.asus.hscx = cs->hw.asus.cfg_reg + ASUS_HSCX;
-		cs->hw.asus.u7 = cs->hw.asus.cfg_reg + ASUS_CTRL_U7;
-		cs->hw.asus.pots = cs->hw.asus.cfg_reg + ASUS_CTRL_POTS;
-		if (hscxisac_setup(cs, &isac_ops, &hscx_ops))
-			goto err;
+	switch (mt) {
+		case CARD_RESET:
+			spin_lock_irqsave(&cs->lock, flags);
+			reset_asuscom(cs);
+			spin_unlock_irqrestore(&cs->lock, flags);
+			return(0);
+		case CARD_RELEASE:
+			release_io_asuscom(cs);
+			return(0);
+		case CARD_INIT:
+			spin_lock_irqsave(&cs->lock, flags);
+			cs->debug |= L1_DEB_IPAC;
+			inithscxisac(cs, 3);
+			spin_unlock_irqrestore(&cs->lock, flags);
+			return(0);
+		case CARD_TEST:
+			return(0);
 	}
-	printk(KERN_INFO "ISDNLink: resetting card\n");
-	cs->card_ops->reset(cs);
-	return 0;
-
- err:
-	hisax_release_resources(cs);
-	return rc;
+	return(0);
 }
 
 #ifdef __ISAPNP__
@@ -293,66 +313,115 @@ static struct isapnp_device_id asus_ids[
 	{ 0, }
 };
 
-static struct isapnp_device_id *adev = &asus_ids[0];
+static struct isapnp_device_id *ipid __initdata = &asus_ids[0];
 static struct pnp_card *pnp_c __devinitdata = NULL;
 #endif
 
 int __init
 setup_asuscom(struct IsdnCard *card)
 {
+	int bytecnt;
+	struct IsdnCardState *cs = card->cs;
+	u_char val;
 	char tmp[64];
 
 	strcpy(tmp, Asuscom_revision);
 	printk(KERN_INFO "HiSax: Asuscom ISDNLink driver Rev. %s\n", HiSax_getrev(tmp));
+	if (cs->typ != ISDN_CTYPE_ASUSCOM)
+		return (0);
 #ifdef __ISAPNP__
 	if (!card->para[1] && isapnp_present()) {
-		struct pnp_card *pb;
-		struct pnp_dev *pd;
+		struct pnp_dev *pnp_d;
+		while(ipid->card_vendor) {
+			if ((pnp_c = pnp_find_card(ipid->card_vendor,
+				ipid->card_device, pnp_c))) {
+				pnp_d = NULL;
+				if ((pnp_d = pnp_find_dev(pnp_c,
+					ipid->vendor, ipid->function, pnp_d))) {
+					int err;
 
-		while(adev->card_vendor) {
-			if ((pb = pnp_find_card(adev->card_vendor,
-						adev->card_device,
-						pnp_c))) {
-				pnp_c = pb;
-				pd = NULL;
-				if ((pd = pnp_find_dev(pnp_c,
-						       adev->vendor,
-						       adev->function,
-						       pd))) {
 					printk(KERN_INFO "HiSax: %s detected\n",
-						(char *)adev->driver_data);
-					if (pnp_device_attach(pd) < 0) {
-						printk(KERN_ERR "AsusPnP: attach failed\n");
-						return 0;
-					}
-					if (pnp_activate_dev(pd) < 0) {
-						printk(KERN_ERR "AsusPnP: activate failed\n");
-						pnp_device_detach(pd);
-						return 0;
+						(char *)ipid->driver_data);
+					pnp_disable_dev(pnp_d);
+					err = pnp_activate_dev(pnp_d);
+					if (err<0) {
+						printk(KERN_WARNING "%s: pnp_activate_dev ret(%d)\n",
+							__FUNCTION__, err);
+						return(0);
 					}
-					if (!pnp_irq_valid(pd, 0) || !pnp_port_valid(pd, 0)) {
+					card->para[1] = pnp_port_start(pnp_d, 0);
+					card->para[0] = pnp_irq(pnp_d, 0);
+					if (!card->para[0] || !card->para[1]) {
 						printk(KERN_ERR "AsusPnP:some resources are missing %ld/%lx\n",
-							pnp_irq(pd, 0), pnp_port_start(pd, 0));
-						pnp_device_detach(pd);
+							card->para[0], card->para[1]);
+						pnp_disable_dev(pnp_d);
 						return(0);
 					}
-					card->para[1] = pnp_port_start(pd, 0);
-					card->para[0] = pnp_irq(pd, 0);
 					break;
 				} else {
 					printk(KERN_ERR "AsusPnP: PnP error card found, no device\n");
 				}
 			}
-			adev++;
-			pnp_c=NULL;
+			ipid++;
+			pnp_c = NULL;
 		} 
-		if (!adev->card_vendor) {
+		if (!ipid->card_vendor) {
 			printk(KERN_INFO "AsusPnP: no ISAPnP card found\n");
 			return(0);
 		}
 	}
 #endif
-	if (asuscom_probe(card->cs, card) < 0)
-		return 0;
-	return 1;
+	bytecnt = 8;
+	cs->hw.asus.cfg_reg = card->para[1];
+	cs->irq = card->para[0];
+	if (!request_region(cs->hw.asus.cfg_reg, bytecnt, "asuscom isdn")) {
+		printk(KERN_WARNING
+		       "HiSax: %s config port %x-%x already in use\n",
+		       CardType[card->typ],
+		       cs->hw.asus.cfg_reg,
+		       cs->hw.asus.cfg_reg + bytecnt);
+		return (0);
+	}
+	printk(KERN_INFO "ISDNLink: defined at 0x%x IRQ %d\n",
+		cs->hw.asus.cfg_reg, cs->irq);
+	setup_isac(cs);
+	cs->BC_Read_Reg = &ReadHSCX;
+	cs->BC_Write_Reg = &WriteHSCX;
+	cs->BC_Send_Data = &hscx_fill_fifo;
+	cs->cardmsg = &Asus_card_msg;
+	val = readreg(cs->hw.asus.cfg_reg + ASUS_IPAC_ALE, 
+		cs->hw.asus.cfg_reg + ASUS_IPAC_DATA, IPAC_ID);
+	if ((val == 1) || (val == 2)) {
+		cs->subtyp = ASUS_IPAC;
+		cs->hw.asus.adr  = cs->hw.asus.cfg_reg + ASUS_IPAC_ALE;
+		cs->hw.asus.isac = cs->hw.asus.cfg_reg + ASUS_IPAC_DATA;
+		cs->hw.asus.hscx = cs->hw.asus.cfg_reg + ASUS_IPAC_DATA;
+		test_and_set_bit(HW_IPAC, &cs->HW_Flags);
+		cs->readisac = &ReadISAC_IPAC;
+		cs->writeisac = &WriteISAC_IPAC;
+		cs->readisacfifo = &ReadISACfifo_IPAC;
+		cs->writeisacfifo = &WriteISACfifo_IPAC;
+		cs->irq_func = &asuscom_interrupt_ipac;
+		printk(KERN_INFO "Asus: IPAC version %x\n", val);
+	} else {
+		cs->subtyp = ASUS_ISACHSCX;
+		cs->hw.asus.adr = cs->hw.asus.cfg_reg + ASUS_ADR;
+		cs->hw.asus.isac = cs->hw.asus.cfg_reg + ASUS_ISAC;
+		cs->hw.asus.hscx = cs->hw.asus.cfg_reg + ASUS_HSCX;
+		cs->hw.asus.u7 = cs->hw.asus.cfg_reg + ASUS_CTRL_U7;
+		cs->hw.asus.pots = cs->hw.asus.cfg_reg + ASUS_CTRL_POTS;
+		cs->readisac = &ReadISAC;
+		cs->writeisac = &WriteISAC;
+		cs->readisacfifo = &ReadISACfifo;
+		cs->writeisacfifo = &WriteISACfifo;
+		cs->irq_func = &asuscom_interrupt;
+		ISACVersion(cs, "ISDNLink:");
+		if (HscxVersion(cs, "ISDNLink:")) {
+			printk(KERN_WARNING
+		     	"ISDNLink: wrong HSCX versions check IO address\n");
+			release_io_asuscom(cs);
+			return (0);
+		}
+	}
+	return (1);
 }
--- diff/drivers/isdn/hisax/avm_a1.c	2003-05-21 11:50:15.000000000 +0100
+++ source/drivers/isdn/hisax/avm_a1.c	2004-02-23 13:56:42.000000000 +0000
@@ -1,4 +1,4 @@
-/* $Id: avm_a1.c,v 2.13.6.2 2001/09/23 22:24:46 kai Exp $
+/* $Id: avm_a1.c,v 2.15.2.4 2004/01/13 21:46:03 keil Exp $
  *
  * low level stuff for AVM A1 (Fritz) isdn cards
  *
@@ -17,7 +17,7 @@
 #include "isdnl1.h"
 
 extern const char *CardType[];
-static const char *avm_revision = "$Revision: 2.13.6.2 $";
+static const char *avm_revision = "$Revision: 2.15.2.4 $";
 
 #define	 AVM_A1_STAT_ISAC	0x01
 #define	 AVM_A1_STAT_HSCX	0x02
@@ -26,172 +26,237 @@ static const char *avm_revision = "$Revi
 #define byteout(addr,val) outb(val,addr)
 #define bytein(addr) inb(addr)
 
-static inline u8
-readreg(unsigned int adr, u8 off)
+static inline u_char
+readreg(unsigned int adr, u_char off)
 {
 	return (bytein(adr + off));
 }
 
 static inline void
-writereg(unsigned int adr, u8 off, u8 data)
+writereg(unsigned int adr, u_char off, u_char data)
 {
 	byteout(adr + off, data);
 }
 
 
 static inline void
-read_fifo(unsigned int adr, u8 * data, int size)
+read_fifo(unsigned int adr, u_char * data, int size)
 {
 	insb(adr, data, size);
 }
 
 static void
-write_fifo(unsigned int adr, u8 * data, int size)
+write_fifo(unsigned int adr, u_char * data, int size)
 {
 	outsb(adr, data, size);
 }
 
-static u8
-isac_read(struct IsdnCardState *cs, u8 offset)
+/* Interface functions */
+
+static u_char
+ReadISAC(struct IsdnCardState *cs, u_char offset)
 {
-	return readreg(cs->hw.avm.isac, offset);
+	return (readreg(cs->hw.avm.isac, offset));
 }
 
 static void
-isac_write(struct IsdnCardState *cs, u8 offset, u8 value)
+WriteISAC(struct IsdnCardState *cs, u_char offset, u_char value)
 {
 	writereg(cs->hw.avm.isac, offset, value);
 }
 
 static void
-isac_read_fifo(struct IsdnCardState *cs, u8 * data, int size)
+ReadISACfifo(struct IsdnCardState *cs, u_char * data, int size)
 {
 	read_fifo(cs->hw.avm.isacfifo, data, size);
 }
 
 static void
-isac_write_fifo(struct IsdnCardState *cs, u8 * data, int size)
+WriteISACfifo(struct IsdnCardState *cs, u_char * data, int size)
 {
 	write_fifo(cs->hw.avm.isacfifo, data, size);
 }
 
-static struct dc_hw_ops isac_ops = {
-	.read_reg   = isac_read,
-	.write_reg  = isac_write,
-	.read_fifo  = isac_read_fifo,
-	.write_fifo = isac_write_fifo,
-};
-
-static u8
-hscx_read(struct IsdnCardState *cs, int hscx, u8 offset)
+static u_char
+ReadHSCX(struct IsdnCardState *cs, int hscx, u_char offset)
 {
 	return (readreg(cs->hw.avm.hscx[hscx], offset));
 }
 
 static void
-hscx_write(struct IsdnCardState *cs, int hscx, u8 offset, u8 value)
+WriteHSCX(struct IsdnCardState *cs, int hscx, u_char offset, u_char value)
 {
 	writereg(cs->hw.avm.hscx[hscx], offset, value);
 }
 
-static void
-hscx_read_fifo(struct IsdnCardState *cs, int hscx, u8 *data, int size)
-{
-	read_fifo(cs->hw.avm.hscxfifo[hscx], data, size);
-}
+/*
+ * fast interrupt HSCX stuff goes here
+ */
 
-static void
-hscx_write_fifo(struct IsdnCardState *cs, int hscx, u8 *data, int size)
-{
-	write_fifo(cs->hw.avm.hscxfifo[hscx], data, size);
-}
+#define READHSCX(cs, nr, reg) readreg(cs->hw.avm.hscx[nr], reg)
+#define WRITEHSCX(cs, nr, reg, data) writereg(cs->hw.avm.hscx[nr], reg, data)
+#define READHSCXFIFO(cs, nr, ptr, cnt) read_fifo(cs->hw.avm.hscxfifo[nr], ptr, cnt)
+#define WRITEHSCXFIFO(cs, nr, ptr, cnt) write_fifo(cs->hw.avm.hscxfifo[nr], ptr, cnt)
 
-static struct bc_hw_ops hscx_ops = {
-	.read_reg   = hscx_read,
-	.write_reg  = hscx_write,
-	.read_fifo  = hscx_read_fifo,
-	.write_fifo = hscx_write_fifo,
-};
+#include "hscx_irq.c"
 
 static irqreturn_t
 avm_a1_interrupt(int intno, void *dev_id, struct pt_regs *regs)
 {
 	struct IsdnCardState *cs = dev_id;
-	u8 val, sval;
-	int handled = 0;
+	u_char val, sval;
+	u_long flags;
 
-	spin_lock(&cs->lock);
+	spin_lock_irqsave(&cs->lock, flags);
 	while (((sval = bytein(cs->hw.avm.cfg_reg)) & 0xf) != 0x7) {
-		handled = 1;
 		if (!(sval & AVM_A1_STAT_TIMER)) {
 			byteout(cs->hw.avm.cfg_reg, 0x1E);
 			sval = bytein(cs->hw.avm.cfg_reg);
 		} else if (cs->debug & L1_DEB_INTSTAT)
 			debugl1(cs, "avm IntStatus %x", sval);
 		if (!(sval & AVM_A1_STAT_HSCX)) {
-			val = hscx_read(cs, 1, HSCX_ISTA);
+			val = readreg(cs->hw.avm.hscx[1], HSCX_ISTA);
 			if (val)
 				hscx_int_main(cs, val);
 		}
 		if (!(sval & AVM_A1_STAT_ISAC)) {
-			val = isac_read(cs, ISAC_ISTA);
+			val = readreg(cs->hw.avm.isac, ISAC_ISTA);
 			if (val)
 				isac_interrupt(cs, val);
 		}
 	}
-	hscx_write(cs, 0, HSCX_MASK, 0xFF);
-	hscx_write(cs, 1, HSCX_MASK, 0xFF);
-	isac_write(cs, ISAC_MASK, 0xFF);
-	isac_write(cs, ISAC_MASK, 0x0);
-	hscx_write(cs, 0, HSCX_MASK, 0x0);
-	hscx_write(cs, 1, HSCX_MASK, 0x0);
-	spin_unlock(&cs->lock);
-	return IRQ_RETVAL(handled);
+	writereg(cs->hw.avm.hscx[0], HSCX_MASK, 0xFF);
+	writereg(cs->hw.avm.hscx[1], HSCX_MASK, 0xFF);
+	writereg(cs->hw.avm.isac, ISAC_MASK, 0xFF);
+	writereg(cs->hw.avm.isac, ISAC_MASK, 0x0);
+	writereg(cs->hw.avm.hscx[0], HSCX_MASK, 0x0);
+	writereg(cs->hw.avm.hscx[1], HSCX_MASK, 0x0);
+	spin_unlock_irqrestore(&cs->lock, flags);
+	return IRQ_HANDLED;
+}
+
+inline static void
+release_ioregs(struct IsdnCardState *cs, int mask)
+{
+	release_region(cs->hw.avm.cfg_reg, 8);
+	if (mask & 1)
+		release_region(cs->hw.avm.isac + 32, 32);
+	if (mask & 2)
+		release_region(cs->hw.avm.isacfifo, 1);
+	if (mask & 4)
+		release_region(cs->hw.avm.hscx[0] + 32, 32);
+	if (mask & 8)
+		release_region(cs->hw.avm.hscxfifo[0], 1);
+	if (mask & 0x10)
+		release_region(cs->hw.avm.hscx[1] + 32, 32);
+	if (mask & 0x20)
+		release_region(cs->hw.avm.hscxfifo[1], 1);
+}
+
+static int
+AVM_card_msg(struct IsdnCardState *cs, int mt, void *arg)
+{
+	u_long flags;
+
+	switch (mt) {
+		case CARD_RESET:
+			return(0);
+		case CARD_RELEASE:
+			release_ioregs(cs, 0x3f);
+			return(0);
+		case CARD_INIT:
+			spin_lock_irqsave(&cs->lock, flags);
+			inithscxisac(cs, 1);
+			byteout(cs->hw.avm.cfg_reg, 0x16);
+			byteout(cs->hw.avm.cfg_reg, 0x1E);
+			inithscxisac(cs, 2);
+			spin_unlock_irqrestore(&cs->lock, flags);
+			return(0);
+		case CARD_TEST:
+			return(0);
+	}
+	return(0);
 }
 
-static void
-avm_a1_init(struct IsdnCardState *cs)
+int __init
+setup_avm_a1(struct IsdnCard *card)
 {
-	byteout(cs->hw.avm.cfg_reg, 0x16);
-	byteout(cs->hw.avm.cfg_reg, 0x1E);
-	inithscxisac(cs);
-}
-
-static struct card_ops avm_a1_ops = {
-	.init     = avm_a1_init,
-	.release  = hisax_release_resources,
-	.irq_func = avm_a1_interrupt,
-};
-
-static int __init
-avm_a1_probe(struct IsdnCardState *cs, struct IsdnCard *card)
-{
-	int rc;
-	u8 val;
-
-	printk(KERN_INFO "AVM A1: defined at %#lx IRQ %lu\n",
-	       card->para[1], card->para[0]);
-
-	rc = -EBUSY;
-	cs->hw.avm.cfg_reg     = request_io(&cs->rs, card->para[1] + 0x1800,  8, "avm cfg");
-	if (!cs->hw.avm.cfg_reg) goto err;
-	cs->hw.avm.isac        = request_io(&cs->rs, card->para[1] + 0x1400, 32, "HiSax isac");
-	if (!cs->hw.avm.isac) goto err;
-	cs->hw.avm.isacfifo    = request_io(&cs->rs, card->para[1] + 0x1000,  1, "HiSax isac fifo");
-	if (!cs->hw.avm.isacfifo) goto err;
-	cs->hw.avm.hscx[0]     = request_io(&cs->rs, card->para[1] + 0x400,  32, "HiSax hscx A");
-	if (!cs->hw.avm.hscx[0]) goto err;
-	cs->hw.avm.hscxfifo[0] = request_io(&cs->rs, card->para[1],           1, "HiSax hscx A fifo");
-	if (!cs->hw.avm.hscxfifo[0]) goto err;
-	cs->hw.avm.hscx[1]     = request_io(&cs->rs, card->para[1] + 0xc00,  32, "HiSax hscx B");
-	if (!cs->hw.avm.hscx[1]) goto err;
-	cs->hw.avm.hscxfifo[1] = request_io(&cs->rs, card->para[1] + 0x800,   1, "HiSax hscx B fifo");
-	if (!cs->hw.avm.hscxfifo[1]) goto err;
-	cs->hw.avm.isac    -= 0x20;
-	cs->hw.avm.hscx[0] -= 0x20;
-	cs->hw.avm.hscx[1] -= 0x20;
-	cs->irq = card->para[0];
+	u_char val;
+	struct IsdnCardState *cs = card->cs;
+	char tmp[64];
+
+	strcpy(tmp, avm_revision);
+	printk(KERN_INFO "HiSax: AVM driver Rev. %s\n", HiSax_getrev(tmp));
+	if (cs->typ != ISDN_CTYPE_A1)
+		return (0);
 
+	cs->hw.avm.cfg_reg = card->para[1] + 0x1800;
+	cs->hw.avm.isac = card->para[1] + 0x1400 - 0x20;
+	cs->hw.avm.hscx[0] = card->para[1] + 0x400 - 0x20;
+	cs->hw.avm.hscx[1] = card->para[1] + 0xc00 - 0x20;
+	cs->hw.avm.isacfifo = card->para[1] + 0x1000;
+	cs->hw.avm.hscxfifo[0] = card->para[1];
+	cs->hw.avm.hscxfifo[1] = card->para[1] + 0x800;
+	cs->irq = card->para[0];
+	if (!request_region(cs->hw.avm.cfg_reg, 8, "avm cfg")) {
+		printk(KERN_WARNING
+		       "HiSax: %s config port %x-%x already in use\n",
+		       CardType[card->typ],
+		       cs->hw.avm.cfg_reg,
+		       cs->hw.avm.cfg_reg + 8);
+		return (0);
+	}
+	if (!request_region(cs->hw.avm.isac + 32, 32, "HiSax isac")) {
+		printk(KERN_WARNING
+		       "HiSax: %s isac ports %x-%x already in use\n",
+		       CardType[cs->typ],
+		       cs->hw.avm.isac + 32,
+		       cs->hw.avm.isac + 64);
+		release_ioregs(cs, 0);
+		return (0);
+	}
+	if (!request_region(cs->hw.avm.isacfifo, 1, "HiSax isac fifo")) {
+		printk(KERN_WARNING
+		       "HiSax: %s isac fifo port %x already in use\n",
+		       CardType[cs->typ],
+		       cs->hw.avm.isacfifo);
+		release_ioregs(cs, 1);
+		return (0);
+	}
+	if (!request_region(cs->hw.avm.hscx[0] + 32, 32, "HiSax hscx A")) {
+		printk(KERN_WARNING
+		       "HiSax: %s hscx A ports %x-%x already in use\n",
+		       CardType[cs->typ],
+		       cs->hw.avm.hscx[0] + 32,
+		       cs->hw.avm.hscx[0] + 64);
+		release_ioregs(cs, 3);
+		return (0);
+	}
+	if (!request_region(cs->hw.avm.hscxfifo[0], 1, "HiSax hscx A fifo")) {
+		printk(KERN_WARNING
+		       "HiSax: %s hscx A fifo port %x already in use\n",
+		       CardType[cs->typ],
+		       cs->hw.avm.hscxfifo[0]);
+		release_ioregs(cs, 7);
+		return (0);
+	}
+	if (!request_region(cs->hw.avm.hscx[1] + 32, 32, "HiSax hscx B")) {
+		printk(KERN_WARNING
+		       "HiSax: %s hscx B ports %x-%x already in use\n",
+		       CardType[cs->typ],
+		       cs->hw.avm.hscx[1] + 32,
+		       cs->hw.avm.hscx[1] + 64);
+		release_ioregs(cs, 0xf);
+		return (0);
+	}
+	if (!request_region(cs->hw.avm.hscxfifo[1], 1, "HiSax hscx B fifo")) {
+		printk(KERN_WARNING
+		       "HiSax: %s hscx B fifo port %x already in use\n",
+		       CardType[cs->typ],
+		       cs->hw.avm.hscxfifo[1]);
+		release_ioregs(cs, 0x1f);
+		return (0);
+	}
 	byteout(cs->hw.avm.cfg_reg, 0x0);
 	HZDELAY(HZ / 5 + 1);
 	byteout(cs->hw.avm.cfg_reg, 0x1);
@@ -219,24 +284,34 @@ avm_a1_probe(struct IsdnCardState *cs, s
 	printk(KERN_INFO "AVM A1: Byte at %x is %x\n",
 	       cs->hw.avm.cfg_reg, val);
 
-	cs->card_ops = &avm_a1_ops;
-	if (hscxisac_setup(cs, &isac_ops, &hscx_ops))
-		goto err;
-	return 0;
- err:
-	hisax_release_resources(cs);
-	return rc;
-}
-
-int __init
-setup_avm_a1(struct IsdnCard *card)
-{
-	char tmp[64];
-
-	strcpy(tmp, avm_revision);
-	printk(KERN_INFO "HiSax: AVM driver Rev. %s\n", HiSax_getrev(tmp));
-
-	if (avm_a1_probe(card->cs, card) < 0)
-		return 0;
-	return 1;
+	printk(KERN_INFO
+	       "HiSax: %s config irq:%d cfg:0x%X\n",
+	       CardType[cs->typ], cs->irq,
+	       cs->hw.avm.cfg_reg);
+	printk(KERN_INFO
+	       "HiSax: isac:0x%X/0x%X\n",
+	       cs->hw.avm.isac + 32, cs->hw.avm.isacfifo);
+	printk(KERN_INFO
+	       "HiSax: hscx A:0x%X/0x%X  hscx B:0x%X/0x%X\n",
+	       cs->hw.avm.hscx[0] + 32, cs->hw.avm.hscxfifo[0],
+	       cs->hw.avm.hscx[1] + 32, cs->hw.avm.hscxfifo[1]);
+
+	cs->readisac = &ReadISAC;
+	cs->writeisac = &WriteISAC;
+	cs->readisacfifo = &ReadISACfifo;
+	cs->writeisacfifo = &WriteISACfifo;
+	cs->BC_Read_Reg = &ReadHSCX;
+	cs->BC_Write_Reg = &WriteHSCX;
+	cs->BC_Send_Data = &hscx_fill_fifo;
+	setup_isac(cs);
+	cs->cardmsg = &AVM_card_msg;
+	cs->irq_func = &avm_a1_interrupt;
+	ISACVersion(cs, "AVM A1:");
+	if (HscxVersion(cs, "AVM A1:")) {
+		printk(KERN_WARNING
+		       "AVM A1: wrong HSCX versions check IO address\n");
+		release_ioregs(cs, 0x3f);
+		return (0);
+	}
+	return (1);
 }
--- diff/drivers/isdn/hisax/avm_a1p.c	2003-05-21 11:50:15.000000000 +0100
+++ source/drivers/isdn/hisax/avm_a1p.c	2004-02-23 13:56:42.000000000 +0000
@@ -1,4 +1,4 @@
-/* $Id: avm_a1p.c,v 2.7.6.2 2001/09/23 22:24:46 kai Exp $
+/* $Id: avm_a1p.c,v 2.9.2.5 2004/01/24 20:47:19 keil Exp $
  *
  * low level stuff for the following AVM cards:
  * A1 PCMCIA
@@ -56,176 +56,182 @@
 #define byteout(addr,val) outb(val,addr)
 #define bytein(addr) inb(addr)
 
-static const char *avm_revision = "$Revision: 2.7.6.2 $";
-static spinlock_t avm_a1p_lock = SPIN_LOCK_UNLOCKED;
+static const char *avm_revision = "$Revision: 2.9.2.5 $";
 
-static inline u8
-readreg(struct IsdnCardState *cs, int offset, u8 adr)
+static inline u_char
+ReadISAC(struct IsdnCardState *cs, u_char offset)
 {
-	unsigned long flags;
-        u8 ret;
+        u_char ret;
 
-	spin_lock_irqsave(&avm_a1p_lock, flags);
-        byteout(cs->hw.avm.cfg_reg + ADDRREG_OFFSET, offset + adr - 0x20);
-	ret = bytein(cs->hw.avm.cfg_reg + DATAREG_OFFSET);
-	spin_unlock_irqrestore(&avm_a1p_lock, flags);
+        offset -= 0x20;
+        byteout(cs->hw.avm.cfg_reg+ADDRREG_OFFSET,ISAC_REG_OFFSET+offset);
+	ret = bytein(cs->hw.avm.cfg_reg+DATAREG_OFFSET);
 	return ret;
 }
 
 static inline void
-writereg(struct IsdnCardState *cs, int offset, u8 adr, u8 value)
+WriteISAC(struct IsdnCardState *cs, u_char offset, u_char value)
 {
-	unsigned long flags;
-
-	spin_lock_irqsave(&avm_a1p_lock, flags);
-        byteout(cs->hw.avm.cfg_reg+ADDRREG_OFFSET, offset + adr - 0x20);
+        offset -= 0x20;
+        byteout(cs->hw.avm.cfg_reg+ADDRREG_OFFSET,ISAC_REG_OFFSET+offset);
 	byteout(cs->hw.avm.cfg_reg+DATAREG_OFFSET, value);
-	spin_unlock_irqrestore(&avm_a1p_lock, flags);
 }
 
 static inline void
-readfifo(struct IsdnCardState *cs, int offset, u8 *data, int size)
+ReadISACfifo(struct IsdnCardState *cs, u_char * data, int size)
 {
-        byteout(cs->hw.avm.cfg_reg + ADDRREG_OFFSET, offset);
-	insb(cs->hw.avm.cfg_reg + DATAREG_OFFSET, data, size);
+	byteout(cs->hw.avm.cfg_reg+ADDRREG_OFFSET,ISAC_FIFO_OFFSET);
+	insb(cs->hw.avm.cfg_reg+DATAREG_OFFSET, data, size);
 }
 
 static inline void
-writefifo(struct IsdnCardState *cs, int offset, u8 *data, int size)
+WriteISACfifo(struct IsdnCardState *cs, u_char * data, int size)
 {
-	byteout(cs->hw.avm.cfg_reg+ADDRREG_OFFSET, offset);
+	byteout(cs->hw.avm.cfg_reg+ADDRREG_OFFSET,ISAC_FIFO_OFFSET);
 	outsb(cs->hw.avm.cfg_reg+DATAREG_OFFSET, data, size);
 }
 
-static u8
-isac_read(struct IsdnCardState *cs, u8 adr)
-{
-	return readreg(cs, ISAC_REG_OFFSET, adr);
-}
-
-static void
-isac_write(struct IsdnCardState *cs, u8 adr, u8 value)
+static inline u_char
+ReadHSCX(struct IsdnCardState *cs, int hscx, u_char offset)
 {
-	writereg(cs, ISAC_REG_OFFSET, adr, value);
-}
+	u_char ret;
 
-static void
-isac_read_fifo(struct IsdnCardState *cs, u8 *data, int size)
-{
-	readfifo(cs, ISAC_FIFO_OFFSET, data, size);
+        offset -= 0x20;
+	byteout(cs->hw.avm.cfg_reg+ADDRREG_OFFSET,
+			HSCX_REG_OFFSET+hscx*HSCX_CH_DIFF+offset);
+	ret = bytein(cs->hw.avm.cfg_reg+DATAREG_OFFSET);
+	return ret;
 }
 
-static void
-isac_write_fifo(struct IsdnCardState *cs, u8 *data, int size)
+static inline void
+WriteHSCX(struct IsdnCardState *cs, int hscx, u_char offset, u_char value)
 {
-	writefifo(cs, ISAC_FIFO_OFFSET, data, size);
+        offset -= 0x20;
+	byteout(cs->hw.avm.cfg_reg+ADDRREG_OFFSET,
+			HSCX_REG_OFFSET+hscx*HSCX_CH_DIFF+offset);
+	byteout(cs->hw.avm.cfg_reg+DATAREG_OFFSET, value);
 }
 
-static struct dc_hw_ops isac_ops = {
-	.read_reg   = isac_read,
-	.write_reg  = isac_write,
-	.read_fifo  = isac_read_fifo,
-	.write_fifo = isac_write_fifo,
-};
-
-static u8
-hscx_read(struct IsdnCardState *cs, int hscx, u8 adr)
+static inline void
+ReadHSCXfifo(struct IsdnCardState *cs, int hscx, u_char * data, int size)
 {
-	return readreg(cs, HSCX_REG_OFFSET + hscx*HSCX_CH_DIFF, adr);
+	byteout(cs->hw.avm.cfg_reg+ADDRREG_OFFSET,
+			HSCX_FIFO_OFFSET+hscx*HSCX_CH_DIFF);
+	insb(cs->hw.avm.cfg_reg+DATAREG_OFFSET, data, size);
 }
 
-static void
-hscx_write(struct IsdnCardState *cs, int hscx, u8 adr, u8 value)
+static inline void
+WriteHSCXfifo(struct IsdnCardState *cs, int hscx, u_char * data, int size)
 {
-	writereg(cs, HSCX_REG_OFFSET + hscx*HSCX_CH_DIFF, adr, value);
+	byteout(cs->hw.avm.cfg_reg+ADDRREG_OFFSET,
+			HSCX_FIFO_OFFSET+hscx*HSCX_CH_DIFF);
+	outsb(cs->hw.avm.cfg_reg+DATAREG_OFFSET, data, size);
 }
 
-static void
-hscx_read_fifo(struct IsdnCardState *cs, int hscx, u8 *data, int size)
-{
-	return readfifo(cs, HSCX_FIFO_OFFSET + hscx*HSCX_CH_DIFF, data, size);
-}
+/*
+ * fast interrupt HSCX stuff goes here
+ */
 
-static void
-hscx_write_fifo(struct IsdnCardState *cs, int hscx, u8 *data, int size)
-{
-	writefifo(cs, HSCX_FIFO_OFFSET + hscx*HSCX_CH_DIFF, data, size);
-}
+#define READHSCX(cs, nr, reg) ReadHSCX(cs, nr, reg)
+#define WRITEHSCX(cs, nr, reg, data) WriteHSCX(cs, nr, reg, data)
+#define READHSCXFIFO(cs, nr, ptr, cnt) ReadHSCXfifo(cs, nr, ptr, cnt) 
+#define WRITEHSCXFIFO(cs, nr, ptr, cnt) WriteHSCXfifo(cs, nr, ptr, cnt)
 
-static struct bc_hw_ops hscx_ops = {
-	.read_reg   = hscx_read,
-	.write_reg  = hscx_write,
-	.read_fifo  = hscx_read_fifo,
-	.write_fifo = hscx_write_fifo,
-};
+#include "hscx_irq.c"
 
 static irqreturn_t
 avm_a1p_interrupt(int intno, void *dev_id, struct pt_regs *regs)
 {
 	struct IsdnCardState *cs = dev_id;
-	u8 val, sval;
+	u_char val, sval;
+	u_long flags;
 
-	spin_lock(&cs->lock);
+	spin_lock_irqsave(&cs->lock, flags);
 	while ((sval = (~bytein(cs->hw.avm.cfg_reg+ASL0_OFFSET) & ASL0_R_IRQPENDING))) {
 		if (cs->debug & L1_DEB_INTSTAT)
 			debugl1(cs, "avm IntStatus %x", sval);
 		if (sval & ASL0_R_HSCX) {
-                        val = hscx_read(cs, 1, HSCX_ISTA);
+                        val = ReadHSCX(cs, 1, HSCX_ISTA);
 			if (val)
 				hscx_int_main(cs, val);
 		}
 		if (sval & ASL0_R_ISAC) {
-			val = isac_read(cs, ISAC_ISTA);
+			val = ReadISAC(cs, ISAC_ISTA);
 			if (val)
 				isac_interrupt(cs, val);
 		}
 	}
-	hscx_write(cs, 0, HSCX_MASK, 0xFF);
-	hscx_write(cs, 1, HSCX_MASK, 0xFF);
-	isac_write(cs, ISAC_MASK, 0xFF);
-	isac_write(cs, ISAC_MASK, 0x0);
-	hscx_write(cs, 0, HSCX_MASK, 0x0);
-	hscx_write(cs, 1, HSCX_MASK, 0x0);
-	spin_unlock(&cs->lock);
+	WriteHSCX(cs, 0, HSCX_MASK, 0xff);
+	WriteHSCX(cs, 1, HSCX_MASK, 0xff);
+	WriteISAC(cs, ISAC_MASK, 0xff);
+	WriteISAC(cs, ISAC_MASK, 0x00);
+	WriteHSCX(cs, 0, HSCX_MASK, 0x00);
+	WriteHSCX(cs, 1, HSCX_MASK, 0x00);
+	spin_unlock_irqrestore(&cs->lock, flags);
 	return IRQ_HANDLED;
 }
 
-static void
-avm_a1p_init(struct IsdnCardState *cs)
-{
-	byteout(cs->hw.avm.cfg_reg+ASL0_OFFSET,
-		ASL0_W_TDISABLE|ASL0_W_TRESET|ASL0_W_IRQENABLE);
-	inithscxisac(cs);
-}
-
 static int
-avm_a1p_reset(struct IsdnCardState *cs)
+AVM_card_msg(struct IsdnCardState *cs, int mt, void *arg)
 {
-	byteout(cs->hw.avm.cfg_reg+ASL0_OFFSET,0x00);
-	HZDELAY(HZ / 5 + 1);
-	byteout(cs->hw.avm.cfg_reg+ASL0_OFFSET,ASL0_W_RESET);
-	HZDELAY(HZ / 5 + 1);
-	byteout(cs->hw.avm.cfg_reg+ASL0_OFFSET,0x00);
+	u_long flags;
 
+	switch (mt) {
+		case CARD_RESET:
+			spin_lock_irqsave(&cs->lock, flags);
+			byteout(cs->hw.avm.cfg_reg+ASL0_OFFSET,0x00);
+			HZDELAY(HZ / 5 + 1);
+			byteout(cs->hw.avm.cfg_reg+ASL0_OFFSET,ASL0_W_RESET);
+			HZDELAY(HZ / 5 + 1);
+			byteout(cs->hw.avm.cfg_reg+ASL0_OFFSET,0x00);
+			spin_unlock_irqrestore(&cs->lock, flags);
+			return 0;
+
+		case CARD_RELEASE:
+			/* free_irq is done in HiSax_closecard(). */
+		        /* free_irq(cs->irq, cs); */
+			return 0;
+
+		case CARD_INIT:
+			spin_lock_irqsave(&cs->lock, flags);
+			byteout(cs->hw.avm.cfg_reg+ASL0_OFFSET,ASL0_W_TDISABLE|ASL0_W_TRESET|ASL0_W_IRQENABLE);
+			clear_pending_isac_ints(cs);
+			clear_pending_hscx_ints(cs);
+			inithscxisac(cs, 1);
+			inithscxisac(cs, 2);
+			spin_unlock_irqrestore(&cs->lock, flags);
+			return 0;
+
+		case CARD_TEST:
+			/* we really don't need it for the PCMCIA Version */
+			return 0;
+
+		default:
+			/* all card drivers ignore others, so we do the same */
+			return 0;
+	}
 	return 0;
 }
 
-static struct card_ops avm_a1p_ops = {
-	.init     = avm_a1p_init,
-	.reset    = avm_a1p_reset,
-	.irq_func = avm_a1p_interrupt,
-};
-
-static int __init
-avm_a1p_probe(struct IsdnCardState *cs, struct IsdnCard *card)
+int
+setup_avm_a1_pcmcia(struct IsdnCard *card)
 {
-	u8 model, vers;
+	u_char model, vers;
+	struct IsdnCardState *cs = card->cs;
+	char tmp[64];
+
+
+	strcpy(tmp, avm_revision);
+	printk(KERN_INFO "HiSax: AVM A1 PCMCIA driver Rev. %s\n",
+						 HiSax_getrev(tmp));
+	if (cs->typ != ISDN_CTYPE_A1_PCMCIA)
+		return (0);
 
-	cs->irq = card->para[0];
 	cs->hw.avm.cfg_reg = card->para[1];
+	cs->irq = card->para[0];
 
-	outb(cs->hw.avm.cfg_reg+ASL1_OFFSET, ASL1_W_ENABLE_S0);
 
+	outb(cs->hw.avm.cfg_reg+ASL1_OFFSET, ASL1_W_ENABLE_S0);
 	byteout(cs->hw.avm.cfg_reg+ASL0_OFFSET,0x00);
 	HZDELAY(HZ / 5 + 1);
 	byteout(cs->hw.avm.cfg_reg+ASL0_OFFSET,ASL0_W_RESET);
@@ -238,26 +244,25 @@ avm_a1p_probe(struct IsdnCardState *cs, 
 	vers = bytein(cs->hw.avm.cfg_reg+VERREG_OFFSET);
 
 	printk(KERN_INFO "AVM A1 PCMCIA: io 0x%x irq %d model %d version %d\n",
-	       cs->hw.avm.cfg_reg, cs->irq, model, vers);
-
-	cs->card_ops = &avm_a1p_ops;
-	if (hscxisac_setup(cs, &isac_ops, &hscx_ops))
-		goto err;
-	return 0;
- err:
-	hisax_release_resources(cs);
-	return -EBUSY;
-}
-
-int __devinit
-setup_avm_a1_pcmcia(struct IsdnCard *card)
-{
-	char tmp[64];
+				cs->hw.avm.cfg_reg, cs->irq, model, vers);
 
-	strcpy(tmp, avm_revision);
-	printk(KERN_INFO "HiSax: AVM A1 PCMCIA driver Rev. %s\n",
-	       HiSax_getrev(tmp));
-	if (avm_a1p_probe(card->cs, card))
-		return 0;
-	return 1;
+	setup_isac(cs);
+	cs->readisac = &ReadISAC;
+	cs->writeisac = &WriteISAC;
+	cs->readisacfifo = &ReadISACfifo;
+	cs->writeisacfifo = &WriteISACfifo;
+	cs->BC_Read_Reg = &ReadHSCX;
+	cs->BC_Write_Reg = &WriteHSCX;
+	cs->BC_Send_Data = &hscx_fill_fifo;
+	cs->cardmsg = &AVM_card_msg;
+	cs->irq_flags = SA_SHIRQ;
+	cs->irq_func = &avm_a1p_interrupt;
+
+	ISACVersion(cs, "AVM A1 PCMCIA:");
+	if (HscxVersion(cs, "AVM A1 PCMCIA:")) {
+		printk(KERN_WARNING
+		       "AVM A1 PCMCIA: wrong HSCX versions check IO address\n");
+		return (0);
+	}
+	return (1);
 }
--- diff/drivers/isdn/hisax/avm_pci.c	2003-08-20 14:16:09.000000000 +0100
+++ source/drivers/isdn/hisax/avm_pci.c	2004-02-23 13:56:42.000000000 +0000
@@ -1,4 +1,4 @@
-/* $Id: avm_pci.c,v 1.22.6.6 2001/09/23 22:24:46 kai Exp $
+/* $Id: avm_pci.c,v 1.29.2.4 2004/02/11 13:21:32 keil Exp $
  *
  * low level stuff for AVM Fritz!PCI and ISA PnP isdn cards
  *
@@ -22,8 +22,7 @@
 #include <linux/interrupt.h>
 
 extern const char *CardType[];
-static const char *avm_pci_rev = "$Revision: 1.22.6.6 $";
-static spinlock_t avm_pci_lock = SPIN_LOCK_UNLOCKED;
+static const char *avm_pci_rev = "$Revision: 1.29.2.4 $";
 
 #define  AVM_FRITZ_PCI		1
 #define  AVM_FRITZ_PNP		2
@@ -76,137 +75,91 @@ static spinlock_t avm_pci_lock = SPIN_LO
 
 /* Interface functions */
 
-static u8
-ReadISAC(struct IsdnCardState *cs, u8 offset)
+static u_char
+ReadISAC(struct IsdnCardState *cs, u_char offset)
 {
-	u8 idx = (offset > 0x2f) ? AVM_ISAC_REG_HIGH : AVM_ISAC_REG_LOW;
-	u8 val;
-	unsigned long flags;
+	register u_char idx = (offset > 0x2f) ? AVM_ISAC_REG_HIGH : AVM_ISAC_REG_LOW;
+	register u_char val;
 
-	spin_lock_irqsave(&avm_pci_lock, flags);
 	outb(idx, cs->hw.avm.cfg_reg + 4);
 	val = inb(cs->hw.avm.isac + (offset & 0xf));
-	spin_unlock_irqrestore(&avm_pci_lock, flags);
 	return (val);
 }
 
 static void
-WriteISAC(struct IsdnCardState *cs, u8 offset, u8 value)
+WriteISAC(struct IsdnCardState *cs, u_char offset, u_char value)
 {
-	u8 idx = (offset > 0x2f) ? AVM_ISAC_REG_HIGH : AVM_ISAC_REG_LOW;
-	unsigned long flags;
+	register u_char idx = (offset > 0x2f) ? AVM_ISAC_REG_HIGH : AVM_ISAC_REG_LOW;
 
-	spin_lock_irqsave(&avm_pci_lock, flags);
 	outb(idx, cs->hw.avm.cfg_reg + 4);
 	outb(value, cs->hw.avm.isac + (offset & 0xf));
-	spin_unlock_irqrestore(&avm_pci_lock, flags);
 }
 
 static void
-ReadISACfifo(struct IsdnCardState *cs, u8 * data, int size)
+ReadISACfifo(struct IsdnCardState *cs, u_char * data, int size)
 {
 	outb(AVM_ISAC_FIFO, cs->hw.avm.cfg_reg + 4);
 	insb(cs->hw.avm.isac, data, size);
 }
 
 static void
-WriteISACfifo(struct IsdnCardState *cs, u8 * data, int size)
+WriteISACfifo(struct IsdnCardState *cs, u_char * data, int size)
 {
 	outb(AVM_ISAC_FIFO, cs->hw.avm.cfg_reg + 4);
 	outsb(cs->hw.avm.isac, data, size);
 }
 
-static struct dc_hw_ops isac_ops = {
-	.read_reg   = ReadISAC,
-	.write_reg  = WriteISAC,
-	.read_fifo  = ReadISACfifo,
-	.write_fifo = WriteISACfifo,
-};
-
 static inline u_int
-ReadHDLCPCI(struct IsdnCardState *cs, int chan, u8 offset)
+ReadHDLCPCI(struct IsdnCardState *cs, int chan, u_char offset)
 {
-	u_int idx = chan ? AVM_HDLC_2 : AVM_HDLC_1;
-	u_int val;
-	unsigned long flags;
+	register u_int idx = chan ? AVM_HDLC_2 : AVM_HDLC_1;
+	register u_int val;
 
-	spin_lock_irqsave(&avm_pci_lock, flags);
 	outl(idx, cs->hw.avm.cfg_reg + 4);
 	val = inl(cs->hw.avm.isac + offset);
-	spin_unlock_irqrestore(&avm_pci_lock, flags);
 	return (val);
 }
 
 static inline void
-WriteHDLCPCI(struct IsdnCardState *cs, int chan, u8 offset, u_int value)
+WriteHDLCPCI(struct IsdnCardState *cs, int chan, u_char offset, u_int value)
 {
-	u_int idx = chan ? AVM_HDLC_2 : AVM_HDLC_1;
-	unsigned long flags;
+	register u_int idx = chan ? AVM_HDLC_2 : AVM_HDLC_1;
 
-	spin_lock_irqsave(&avm_pci_lock, flags);
 	outl(idx, cs->hw.avm.cfg_reg + 4);
 	outl(value, cs->hw.avm.isac + offset);
-	spin_unlock_irqrestore(&avm_pci_lock, flags);
 }
 
-static inline u8
-ReadHDLCPnP(struct IsdnCardState *cs, int chan, u8 offset)
+static inline u_char
+ReadHDLCPnP(struct IsdnCardState *cs, int chan, u_char offset)
 {
-	u8 idx = chan ? AVM_HDLC_2 : AVM_HDLC_1;
-	u8 val;
-	unsigned long flags;
+	register u_char idx = chan ? AVM_HDLC_2 : AVM_HDLC_1;
+	register u_char val;
 
-	spin_lock_irqsave(&avm_pci_lock, flags);
 	outb(idx, cs->hw.avm.cfg_reg + 4);
 	val = inb(cs->hw.avm.isac + offset);
-	spin_unlock_irqrestore(&avm_pci_lock, flags);
 	return (val);
 }
 
 static inline void
-WriteHDLCPnP(struct IsdnCardState *cs, int chan, u8 offset, u8 value)
+WriteHDLCPnP(struct IsdnCardState *cs, int chan, u_char offset, u_char value)
 {
-	u8 idx = chan ? AVM_HDLC_2 : AVM_HDLC_1;
-	unsigned long flags;
+	register u_char idx = chan ? AVM_HDLC_2 : AVM_HDLC_1;
 
-	spin_lock_irqsave(&avm_pci_lock, flags);
 	outb(idx, cs->hw.avm.cfg_reg + 4);
 	outb(value, cs->hw.avm.isac + offset);
-	spin_unlock_irqrestore(&avm_pci_lock, flags);
 }
 
-static void
-hdlc_read_fifo(struct IsdnCardState *cs, int hscx, u8 *data, int len)
+static u_char
+ReadHDLC_s(struct IsdnCardState *cs, int chan, u_char offset)
 {
-	u8 idx = hscx ? AVM_HDLC_2 : AVM_HDLC_1;
-	int i;
-
-	if (cs->subtyp == AVM_FRITZ_PCI) {
-		u32 *ptr = (u32 *) data;
-
-		outl(idx, cs->hw.avm.cfg_reg + 4);
-		for (i = 0; i < len; i += 4) {
-#ifdef __powerpc__
-#ifdef CONFIG_APUS
-			*ptr++ = in_le32((u32 *)(cs->hw.avm.isac +_IO_BASE));
-#else
-			*ptr++ = in_be32((u32 *)(cs->hw.avm.isac +_IO_BASE));
-#endif /* CONFIG_APUS */
-#else
-			*ptr++ = inl(cs->hw.avm.isac);
-#endif /* __powerpc__ */
-		}
-	} else {
-		outb(idx, cs->hw.avm.cfg_reg + 4);
-		for (i = 0; i < len; i++) {
-			*data++ = inb(cs->hw.avm.isac);
-		}
-	}
+	return(0xff & ReadHDLCPCI(cs, chan, offset));
 }
 
-static struct bc_hw_ops hdlc_hw_ops = {
-	.read_fifo  = hdlc_read_fifo,
-};
+static void
+WriteHDLC_s(struct IsdnCardState *cs, int chan, u_char offset, u_char value)
+{
+	WriteHDLCPCI(cs, chan, offset, value);
+}
 
 static inline
 struct BCState *Sel_BCS(struct IsdnCardState *cs, int channel)
@@ -273,7 +226,7 @@ modehdlc(struct BCState *bcs, int mode, 
 			bcs->hw.hdlc.ctrl.sr.cmd = HDLC_CMD_XRS;
 			write_ctrl(bcs, 1);
 			bcs->hw.hdlc.ctrl.sr.cmd = 0;
-			sched_b_event(bcs, B_XMTBUFREADY);
+			schedule_event(bcs, B_XMTBUFREADY);
 			break;
 		case (L1_MODE_HDLC):
 			bcs->mode = mode;
@@ -284,7 +237,7 @@ modehdlc(struct BCState *bcs, int mode, 
 			bcs->hw.hdlc.ctrl.sr.cmd = HDLC_CMD_XRS;
 			write_ctrl(bcs, 1);
 			bcs->hw.hdlc.ctrl.sr.cmd = 0;
-			sched_b_event(bcs, B_XMTBUFREADY);
+			schedule_event(bcs, B_XMTBUFREADY);
 			break;
 	}
 }
@@ -292,31 +245,89 @@ modehdlc(struct BCState *bcs, int mode, 
 static inline void
 hdlc_empty_fifo(struct BCState *bcs, int count)
 {
-	recv_empty_fifo_b(bcs, count);
+	register u_int *ptr;
+	u_char *p;
+	u_char idx = bcs->channel ? AVM_HDLC_2 : AVM_HDLC_1;
+	int cnt=0;
+	struct IsdnCardState *cs = bcs->cs;
+
+	if ((cs->debug & L1_DEB_HSCX) && !(cs->debug & L1_DEB_HSCX_FIFO))
+		debugl1(cs, "hdlc_empty_fifo %d", count);
+	if (bcs->hw.hdlc.rcvidx + count > HSCX_BUFMAX) {
+		if (cs->debug & L1_DEB_WARN)
+			debugl1(cs, "hdlc_empty_fifo: incoming packet too large");
+		return;
+	}
+	p = bcs->hw.hdlc.rcvbuf + bcs->hw.hdlc.rcvidx;
+	ptr = (u_int *)p;
+	bcs->hw.hdlc.rcvidx += count;
+	if (cs->subtyp == AVM_FRITZ_PCI) {
+		outl(idx, cs->hw.avm.cfg_reg + 4);
+		while (cnt < count) {
+#ifdef __powerpc__
+#ifdef CONFIG_APUS
+			*ptr++ = in_le32((unsigned *)(cs->hw.avm.isac +_IO_BASE));
+#else
+			*ptr++ = in_be32((unsigned *)(cs->hw.avm.isac +_IO_BASE));
+#endif /* CONFIG_APUS */
+#else
+			*ptr++ = inl(cs->hw.avm.isac);
+#endif /* __powerpc__ */
+			cnt += 4;
+		}
+	} else {
+		outb(idx, cs->hw.avm.cfg_reg + 4);
+		while (cnt < count) {
+			*p++ = inb(cs->hw.avm.isac);
+			cnt++;
+		}
+	}
+	if (cs->debug & L1_DEB_HSCX_FIFO) {
+		char *t = bcs->blog;
+
+		if (cs->subtyp == AVM_FRITZ_PNP)
+			p = (u_char *) ptr;
+		t += sprintf(t, "hdlc_empty_fifo %c cnt %d",
+			     bcs->channel ? 'B' : 'A', count);
+		QuickHex(t, p, count);
+		debugl1(cs, bcs->blog);
+	}
 }
 
-static void
+static inline void
 hdlc_fill_fifo(struct BCState *bcs)
 {
 	struct IsdnCardState *cs = bcs->cs;
-	int count, more, cnt =0;
+	int count, cnt =0;
 	int fifo_size = 32;
-	unsigned char *p;
-	unsigned int *ptr;
+	u_char *p;
+	u_int *ptr;
 
-	p = xmit_fill_fifo_b(bcs, fifo_size, &count, &more);
-	if (!p)
+	if ((cs->debug & L1_DEB_HSCX) && !(cs->debug & L1_DEB_HSCX_FIFO))
+		debugl1(cs, "hdlc_fill_fifo");
+	if (!bcs->tx_skb)
+		return;
+	if (bcs->tx_skb->len <= 0)
 		return;
 
-	if (more)
-		bcs->hw.hdlc.ctrl.sr.cmd &= ~HDLC_CMD_XME;
-	else
-		bcs->hw.hdlc.ctrl.sr.cmd |= HDLC_CMD_XME;
-
+	bcs->hw.hdlc.ctrl.sr.cmd &= ~HDLC_CMD_XME;
+	if (bcs->tx_skb->len > fifo_size) {
+		count = fifo_size;
+	} else {
+		count = bcs->tx_skb->len;
+		if (bcs->mode != L1_MODE_TRANS)
+			bcs->hw.hdlc.ctrl.sr.cmd |= HDLC_CMD_XME;
+	}
+	if ((cs->debug & L1_DEB_HSCX) && !(cs->debug & L1_DEB_HSCX_FIFO))
+		debugl1(cs, "hdlc_fill_fifo %d/%ld", count, bcs->tx_skb->len);
+	p = bcs->tx_skb->data;
+	ptr = (u_int *)p;
+	skb_pull(bcs->tx_skb, count);
+	bcs->tx_cnt -= count;
+	bcs->hw.hdlc.count += count;
 	bcs->hw.hdlc.ctrl.sr.xml = ((count == fifo_size) ? 0 : count);
 	write_ctrl(bcs, 3);  /* sets the correct index too */
 	if (cs->subtyp == AVM_FRITZ_PCI) {
-		ptr = (unsigned int *) p;
 		while (cnt<count) {
 #ifdef __powerpc__
 #ifdef CONFIG_APUS
@@ -335,27 +346,25 @@ hdlc_fill_fifo(struct BCState *bcs)
 			cnt++;
 		}
 	}
-}
+	if (cs->debug & L1_DEB_HSCX_FIFO) {
+		char *t = bcs->blog;
 
-static void
-reset_xmit(struct BCState *bcs)
-{
-	bcs->hw.hdlc.ctrl.sr.xml = 0;
-	bcs->hw.hdlc.ctrl.sr.cmd |= HDLC_CMD_XRS;
-	write_ctrl(bcs, 1);
-	bcs->hw.hdlc.ctrl.sr.cmd &= ~HDLC_CMD_XRS;
-	write_ctrl(bcs, 1);
-	hdlc_fill_fifo(bcs);
+		if (cs->subtyp == AVM_FRITZ_PNP)
+			p = (u_char *) ptr;
+		t += sprintf(t, "hdlc_fill_fifo %c cnt %d",
+			     bcs->channel ? 'B' : 'A', count);
+		QuickHex(t, p, count);
+		debugl1(cs, bcs->blog);
+	}
 }
 
 static inline void
-HDLC_irq(struct BCState *bcs, u_int stat)
-{
+HDLC_irq(struct BCState *bcs, u_int stat) {
 	int len;
+	struct sk_buff *skb;
 
 	if (bcs->cs->debug & L1_DEB_HSCX)
 		debugl1(bcs->cs, "ch%d stat %#x", bcs->channel, stat);
-
 	if (stat & HDLC_INT_RPR) {
 		if (stat & HDLC_STAT_RDO) {
 			if (bcs->cs->debug & L1_DEB_HSCX)
@@ -367,7 +376,7 @@ HDLC_irq(struct BCState *bcs, u_int stat
 			write_ctrl(bcs, 1);
 			bcs->hw.hdlc.ctrl.sr.cmd &= ~HDLC_CMD_RRS;
 			write_ctrl(bcs, 1);
-			bcs->rcvidx = 0;
+			bcs->hw.hdlc.rcvidx = 0;
 		} else {
 			if (!(len = (stat & HDLC_STAT_RML_MASK)>>8))
 				len = 32;
@@ -375,21 +384,70 @@ HDLC_irq(struct BCState *bcs, u_int stat
 			if ((stat & HDLC_STAT_RME) || (bcs->mode == L1_MODE_TRANS)) {
 				if (((stat & HDLC_STAT_CRCVFRRAB)==HDLC_STAT_CRCVFR) ||
 					(bcs->mode == L1_MODE_TRANS)) {
-					recv_rme_b(bcs);
+					if (!(skb = dev_alloc_skb(bcs->hw.hdlc.rcvidx)))
+						printk(KERN_WARNING "HDLC: receive out of memory\n");
+					else {
+						memcpy(skb_put(skb, bcs->hw.hdlc.rcvidx),
+							bcs->hw.hdlc.rcvbuf, bcs->hw.hdlc.rcvidx);
+						skb_queue_tail(&bcs->rqueue, skb);
+					}
+					bcs->hw.hdlc.rcvidx = 0;
+					schedule_event(bcs, B_RCVBUFREADY);
 				} else {
 					if (bcs->cs->debug & L1_DEB_HSCX)
 						debugl1(bcs->cs, "invalid frame");
 					else
 						debugl1(bcs->cs, "ch%d invalid frame %#x", bcs->channel, stat);
-					bcs->rcvidx = 0;
+					bcs->hw.hdlc.rcvidx = 0;
 				}
 			}
 		}
 	}
 	if (stat & HDLC_INT_XDU) {
-		xmit_xdu_b(bcs, reset_xmit);
+		/* Here we lost an TX interrupt, so
+		 * restart transmitting the whole frame.
+		 */
+		if (bcs->tx_skb) {
+			skb_push(bcs->tx_skb, bcs->hw.hdlc.count);
+			bcs->tx_cnt += bcs->hw.hdlc.count;
+			bcs->hw.hdlc.count = 0;
+			if (bcs->cs->debug & L1_DEB_WARN)
+				debugl1(bcs->cs, "ch%d XDU", bcs->channel);
+		} else if (bcs->cs->debug & L1_DEB_WARN)
+			debugl1(bcs->cs, "ch%d XDU without skb", bcs->channel);
+		bcs->hw.hdlc.ctrl.sr.xml = 0;
+		bcs->hw.hdlc.ctrl.sr.cmd |= HDLC_CMD_XRS;
+		write_ctrl(bcs, 1);
+		bcs->hw.hdlc.ctrl.sr.cmd &= ~HDLC_CMD_XRS;
+		write_ctrl(bcs, 1);
+		hdlc_fill_fifo(bcs);
 	} else if (stat & HDLC_INT_XPR) {
-		xmit_xpr_b(bcs);
+		if (bcs->tx_skb) {
+			if (bcs->tx_skb->len) {
+				hdlc_fill_fifo(bcs);
+				return;
+			} else {
+				if (test_bit(FLG_LLI_L1WAKEUP,&bcs->st->lli.flag) &&
+					(PACKET_NOACK != bcs->tx_skb->pkt_type)) {
+					u_long	flags;
+					spin_lock_irqsave(&bcs->aclock, flags);
+					bcs->ackcnt += bcs->hw.hdlc.count;
+					spin_unlock_irqrestore(&bcs->aclock, flags);
+					schedule_event(bcs, B_ACKPENDING);
+				}
+				dev_kfree_skb_irq(bcs->tx_skb);
+				bcs->hw.hdlc.count = 0;
+				bcs->tx_skb = NULL;
+			}
+		}
+		if ((bcs->tx_skb = skb_dequeue(&bcs->squeue))) {
+			bcs->hw.hdlc.count = 0;
+			test_and_set_bit(BC_FLG_BUSY, &bcs->Flag);
+			hdlc_fill_fifo(bcs);
+		} else {
+			test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
+			schedule_event(bcs, B_XMTBUFREADY);
+		}
 	}
 }
 
@@ -399,7 +457,6 @@ HDLC_irq_main(struct IsdnCardState *cs)
 	u_int stat;
 	struct BCState *bcs;
 
-	spin_lock(&cs->lock);
 	if (cs->subtyp == AVM_FRITZ_PCI) {
 		stat = ReadHDLCPCI(cs, 0, HDLC_STATUS);
 	} else {
@@ -428,37 +485,64 @@ HDLC_irq_main(struct IsdnCardState *cs)
 		} else
 			HDLC_irq(bcs, stat);
 	}
-	spin_unlock(&cs->lock);
 }
 
 void
 hdlc_l2l1(struct PStack *st, int pr, void *arg)
 {
+	struct BCState *bcs = st->l1.bcs;
 	struct sk_buff *skb = arg;
+	u_long flags;
 
 	switch (pr) {
 		case (PH_DATA | REQUEST):
-			xmit_data_req_b(st->l1.bcs, skb);
+			spin_lock_irqsave(&bcs->cs->lock, flags);
+			if (bcs->tx_skb) {
+				skb_queue_tail(&bcs->squeue, skb);
+			} else {
+				bcs->tx_skb = skb;
+				test_and_set_bit(BC_FLG_BUSY, &bcs->Flag);
+				bcs->hw.hdlc.count = 0;
+				bcs->cs->BC_Send_Data(bcs);
+			}
+			spin_unlock_irqrestore(&bcs->cs->lock, flags);
 			break;
 		case (PH_PULL | INDICATION):
-			xmit_pull_ind_b(st->l1.bcs, skb);
+			spin_lock_irqsave(&bcs->cs->lock, flags);
+			if (bcs->tx_skb) {
+				printk(KERN_WARNING "hdlc_l2l1: this shouldn't happen\n");
+			} else {
+				test_and_set_bit(BC_FLG_BUSY, &bcs->Flag);
+				bcs->tx_skb = skb;
+				bcs->hw.hdlc.count = 0;
+				bcs->cs->BC_Send_Data(bcs);
+			}
+			spin_unlock_irqrestore(&bcs->cs->lock, flags);
 			break;
 		case (PH_PULL | REQUEST):
-			xmit_pull_req_b(st);
+			if (!bcs->tx_skb) {
+				test_and_clear_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
+				st->l1.l1l2(st, PH_PULL | CONFIRM, NULL);
+			} else
+				test_and_set_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
 			break;
 		case (PH_ACTIVATE | REQUEST):
-			test_and_set_bit(BC_FLG_ACTIV, &st->l1.bcs->Flag);
-			modehdlc(st->l1.bcs, st->l1.mode, st->l1.bc);
+			spin_lock_irqsave(&bcs->cs->lock, flags);
+			test_and_set_bit(BC_FLG_ACTIV, &bcs->Flag);
+			modehdlc(bcs, st->l1.mode, st->l1.bc);
+			spin_unlock_irqrestore(&bcs->cs->lock, flags);
 			l1_msg_b(st, pr, arg);
 			break;
 		case (PH_DEACTIVATE | REQUEST):
 			l1_msg_b(st, pr, arg);
 			break;
 		case (PH_DEACTIVATE | CONFIRM):
-			test_and_clear_bit(BC_FLG_ACTIV, &st->l1.bcs->Flag);
-			test_and_clear_bit(BC_FLG_BUSY, &st->l1.bcs->Flag);
-			modehdlc(st->l1.bcs, 0, st->l1.bc);
-			L1L2(st, PH_DEACTIVATE | CONFIRM, NULL);
+			spin_lock_irqsave(&bcs->cs->lock, flags);
+			test_and_clear_bit(BC_FLG_ACTIV, &bcs->Flag);
+			test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
+			modehdlc(bcs, 0, st->l1.bc);
+			spin_unlock_irqrestore(&bcs->cs->lock, flags);
+			st->l1.l1l2(st, PH_DEACTIVATE | CONFIRM, NULL);
 			break;
 	}
 }
@@ -467,38 +551,69 @@ void
 close_hdlcstate(struct BCState *bcs)
 {
 	modehdlc(bcs, 0, 0);
-	bc_close(bcs);
+	if (test_and_clear_bit(BC_FLG_INIT, &bcs->Flag)) {
+		if (bcs->hw.hdlc.rcvbuf) {
+			kfree(bcs->hw.hdlc.rcvbuf);
+			bcs->hw.hdlc.rcvbuf = NULL;
+		}
+		if (bcs->blog) {
+			kfree(bcs->blog);
+			bcs->blog = NULL;
+		}
+		skb_queue_purge(&bcs->rqueue);
+		skb_queue_purge(&bcs->squeue);
+		if (bcs->tx_skb) {
+			dev_kfree_skb_any(bcs->tx_skb);
+			bcs->tx_skb = NULL;
+			test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
+		}
+	}
 }
 
 int
 open_hdlcstate(struct IsdnCardState *cs, struct BCState *bcs)
 {
-	return bc_open(bcs);
+	if (!test_and_set_bit(BC_FLG_INIT, &bcs->Flag)) {
+		if (!(bcs->hw.hdlc.rcvbuf = kmalloc(HSCX_BUFMAX, GFP_ATOMIC))) {
+			printk(KERN_WARNING
+			       "HiSax: No memory for hdlc.rcvbuf\n");
+			return (1);
+		}
+		if (!(bcs->blog = kmalloc(MAX_BLOG_SPACE, GFP_ATOMIC))) {
+			printk(KERN_WARNING
+				"HiSax: No memory for bcs->blog\n");
+			test_and_clear_bit(BC_FLG_INIT, &bcs->Flag);
+			kfree(bcs->hw.hdlc.rcvbuf);
+			bcs->hw.hdlc.rcvbuf = NULL;
+			return (2);
+		}
+		skb_queue_head_init(&bcs->rqueue);
+		skb_queue_head_init(&bcs->squeue);
+	}
+	bcs->tx_skb = NULL;
+	test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
+	bcs->event = 0;
+	bcs->hw.hdlc.rcvidx = 0;
+	bcs->tx_cnt = 0;
+	return (0);
 }
 
 int
 setstack_hdlc(struct PStack *st, struct BCState *bcs)
 {
 	bcs->channel = st->l1.bc;
-	bcs->unit = bcs->channel;
 	if (open_hdlcstate(st->l1.hardware, bcs))
 		return (-1);
 	st->l1.bcs = bcs;
-	st->l1.l2l1 = hdlc_l2l1;
+	st->l2.l2l1 = hdlc_l2l1;
 	setstack_manager(st);
 	bcs->st = st;
 	setstack_l1_B(st);
 	return (0);
 }
 
-static struct bc_l1_ops hdlc_l1_ops = {
-	.fill_fifo = hdlc_fill_fifo,
-	.open      = setstack_hdlc,
-	.close     = close_hdlcstate,
-};
-
-static void __init
-inithdlc(struct IsdnCardState *cs)
+void __init
+clear_pending_hdlc_ints(struct IsdnCardState *cs)
 {
 	u_int val;
 
@@ -525,7 +640,15 @@ inithdlc(struct IsdnCardState *cs)
 		val = ReadHDLCPnP(cs, 1, HDLC_STATUS + 3);
 		debugl1(cs, "HDLC 2 VIN %x", val);
 	}
+}
 
+void __init
+inithdlc(struct IsdnCardState *cs)
+{
+	cs->bcs[0].BC_SetStack = setstack_hdlc;
+	cs->bcs[1].BC_SetStack = setstack_hdlc;
+	cs->bcs[0].BC_Close = close_hdlcstate;
+	cs->bcs[1].BC_Close = close_hdlcstate;
 	modehdlc(cs->bcs, -1, 0);
 	modehdlc(cs->bcs + 1, -1, 1);
 }
@@ -534,13 +657,17 @@ static irqreturn_t
 avm_pcipnp_interrupt(int intno, void *dev_id, struct pt_regs *regs)
 {
 	struct IsdnCardState *cs = dev_id;
-	u8 val;
-	u8 sval;
+	u_long flags;
+	u_char val;
+	u_char sval;
 
+	spin_lock_irqsave(&cs->lock, flags);
 	sval = inb(cs->hw.avm.cfg_reg + 2);
-	if ((sval & AVM_STATUS0_IRQ_MASK) == AVM_STATUS0_IRQ_MASK)
+	if ((sval & AVM_STATUS0_IRQ_MASK) == AVM_STATUS0_IRQ_MASK) {
 		/* possible a shared  IRQ reqest */
+		spin_unlock_irqrestore(&cs->lock, flags);
 		return IRQ_NONE;
+	}
 	if (!(sval & AVM_STATUS0_IRQ_ISAC)) {
 		val = ReadISAC(cs, ISAC_ISTA);
 		isac_interrupt(cs, val);
@@ -550,192 +677,187 @@ avm_pcipnp_interrupt(int intno, void *de
 	}
 	WriteISAC(cs, ISAC_MASK, 0xFF);
 	WriteISAC(cs, ISAC_MASK, 0x0);
+	spin_unlock_irqrestore(&cs->lock, flags);
 	return IRQ_HANDLED;
 }
 
-static int
-avm_pcipnp_reset(struct IsdnCardState *cs)
+static void
+reset_avmpcipnp(struct IsdnCardState *cs)
 {
 	printk(KERN_INFO "AVM PCI/PnP: reset\n");
 	outb(AVM_STATUS0_RESET | AVM_STATUS0_DIS_TIMER, cs->hw.avm.cfg_reg + 2);
-	set_current_state(TASK_UNINTERRUPTIBLE);
-	schedule_timeout((10*HZ)/1000); /* Timeout 10ms */
+	mdelay(10);
 	outb(AVM_STATUS0_DIS_TIMER | AVM_STATUS0_RES_TIMER | AVM_STATUS0_ENA_IRQ, cs->hw.avm.cfg_reg + 2);
 	outb(AVM_STATUS1_ENA_IOM | cs->irq, cs->hw.avm.cfg_reg + 3);
-	set_current_state(TASK_UNINTERRUPTIBLE);
-	schedule_timeout((10*HZ)/1000); /* Timeout 10ms */
+	mdelay(10);
 	printk(KERN_INFO "AVM PCI/PnP: S1 %x\n", inb(cs->hw.avm.cfg_reg + 3));
-	return 0;
-}
-
-static void
-avm_pcipnp_init(struct IsdnCardState *cs)
-{
-	initisac(cs);
-	inithdlc(cs);
-	outb(AVM_STATUS0_DIS_TIMER | AVM_STATUS0_RES_TIMER,
-	     cs->hw.avm.cfg_reg + 2);
-	outb(AVM_STATUS0_DIS_TIMER | AVM_STATUS0_RES_TIMER |
-	     AVM_STATUS0_ENA_IRQ, cs->hw.avm.cfg_reg + 2);
-}
-
-static void
-avm_pcipnp_release(struct IsdnCardState *cs)
-{
-	outb(0, cs->hw.avm.cfg_reg + 2);
-	hisax_release_resources(cs);
 }
 
-static struct card_ops avm_pci_ops = {
-	.init     = avm_pcipnp_init,
-	.reset    = avm_pcipnp_reset,
-	.release  = avm_pcipnp_release,
-	.irq_func = avm_pcipnp_interrupt,
-};
-
-static int __init
-avm_pcipnp_hw_init(struct IsdnCardState *cs)
-{
-	cs->bc_hw_ops = &hdlc_hw_ops;
-	cs->bc_l1_ops = &hdlc_l1_ops;
-	cs->card_ops = &avm_pci_ops;
-	avm_pcipnp_reset(cs);
-	return isac_setup(cs, &isac_ops);
-}
-
-static int __init
-avm_pci_probe(struct IsdnCardState *cs, struct pci_dev *pdev)
-{
-	int rc;
-	u32 val;
-
-	printk(KERN_INFO "AVM PCI: defined at %#lx IRQ %u\n",
-	       pci_resource_start(pdev, 1), pdev->irq);
-	
-	rc = -EBUSY;
-	if (pci_enable_device(pdev))
-		goto err;
-			
-	cs->subtyp = AVM_FRITZ_PCI;
-	cs->irq = pdev->irq;
-	cs->irq_flags |= SA_SHIRQ;
-	cs->hw.avm.cfg_reg = pci_resource_start(pdev, 1);
-	cs->hw.avm.isac = cs->hw.avm.cfg_reg + 0x10;
-	if (!request_io(&cs->rs, cs->hw.avm.cfg_reg, 32, "avm PCI"))
-		goto err;
-
-	val = inl(cs->hw.avm.cfg_reg);
-	printk(KERN_INFO "AVM PCI: stat %#x\n", val);
-	printk(KERN_INFO "AVM PCI: Class %X Rev %d\n",
-	       val & 0xff, (val>>8) & 0xff);
-
-	if (avm_pcipnp_hw_init(cs))
-		goto err;
-
-	return 0;
- err:
-	hisax_release_resources(cs);
-	return rc;
-}
-
-static int __init
-avm_pnp_probe(struct IsdnCardState *cs, struct IsdnCard *card)
+static int
+AVM_card_msg(struct IsdnCardState *cs, int mt, void *arg)
 {
-	int rc;
-	u8 val, ver;
+	u_long flags;
 
-	printk(KERN_INFO "AVM PnP: defined at %#lx IRQ %lu\n",
-	       card->para[1], card->para[0]);
-
-	cs->subtyp = AVM_FRITZ_PNP;
-	cs->irq = card->para[0];
-	cs->hw.avm.cfg_reg = card->para[1];
-	cs->hw.avm.isac = cs->hw.avm.cfg_reg + 0x10;
-
-	rc = -EBUSY;
-	if (!request_io(&cs->rs, cs->hw.avm.cfg_reg, 32, "avm PnP"))
-		goto err;
-	
-	val = inb(cs->hw.avm.cfg_reg);
-	ver = inb(cs->hw.avm.cfg_reg + 1);
-	printk(KERN_INFO "AVM PnP: Class %X Rev %d\n", val, ver);
-
-	if (avm_pcipnp_hw_init(cs))
-		goto err;
-
-	return 0;
- err:
-	hisax_release_resources(cs);
-	return rc;
+	switch (mt) {
+		case CARD_RESET:
+			spin_lock_irqsave(&cs->lock, flags);
+			reset_avmpcipnp(cs);
+			spin_unlock_irqrestore(&cs->lock, flags);
+			return(0);
+		case CARD_RELEASE:
+			outb(0, cs->hw.avm.cfg_reg + 2);
+			release_region(cs->hw.avm.cfg_reg, 32);
+			return(0);
+		case CARD_INIT:
+			spin_lock_irqsave(&cs->lock, flags);
+			reset_avmpcipnp(cs);
+			clear_pending_isac_ints(cs);
+			initisac(cs);
+			inithdlc(cs);
+			outb(AVM_STATUS0_DIS_TIMER | AVM_STATUS0_RES_TIMER,
+				cs->hw.avm.cfg_reg + 2);
+			WriteISAC(cs, ISAC_MASK, 0);
+			outb(AVM_STATUS0_DIS_TIMER | AVM_STATUS0_RES_TIMER |
+				AVM_STATUS0_ENA_IRQ, cs->hw.avm.cfg_reg + 2);
+			/* RESET Receiver and Transmitter */
+			WriteISAC(cs, ISAC_CMDR, 0x41);
+			spin_unlock_irqrestore(&cs->lock, flags);
+			return(0);
+		case CARD_TEST:
+			return(0);
+	}
+	return(0);
 }
 
 static struct pci_dev *dev_avm __initdata = NULL;
 #ifdef __ISAPNP__
-static struct pnp_card *card_avm __initdata = NULL;
-static struct pnp_dev *pnp_avm __initdata = NULL;
+static struct pnp_card *pnp_avm_c __initdata = NULL;
 #endif
 
 int __init
 setup_avm_pcipnp(struct IsdnCard *card)
 {
+	u_int val, ver;
+	struct IsdnCardState *cs = card->cs;
 	char tmp[64];
 
 	strcpy(tmp, avm_pci_rev);
 	printk(KERN_INFO "HiSax: AVM PCI driver Rev. %s\n", HiSax_getrev(tmp));
+	if (cs->typ != ISDN_CTYPE_FRITZPCI)
+		return (0);
 	if (card->para[1]) {
 		/* old manual method */
-		if (avm_pnp_probe(card->cs, card))
-			return 0;
-		return 1;
+		cs->hw.avm.cfg_reg = card->para[1];
+		cs->irq = card->para[0];
+		cs->subtyp = AVM_FRITZ_PNP;
 	} else {
 #ifdef __ISAPNP__
 		if (isapnp_present()) {
-			struct pnp_card *ba;
-			if ((ba = pnp_find_card(
+			struct pnp_dev *pnp_avm_d = NULL;
+			if ((pnp_avm_c = pnp_find_card(
 				ISAPNP_VENDOR('A', 'V', 'M'),
-				ISAPNP_FUNCTION(0x0900), card_avm))) {
-				card_avm = ba;
-				pnp_avm = NULL;
-				if ((pnp_avm = pnp_find_dev(card_avm,
+				ISAPNP_FUNCTION(0x0900), pnp_avm_c))) {
+				if ((pnp_avm_d = pnp_find_dev(pnp_avm_c,
 					ISAPNP_VENDOR('A', 'V', 'M'),
-					ISAPNP_FUNCTION(0x0900), pnp_avm))) {
-					if (pnp_device_attach(pnp_avm) < 0) {
-						printk(KERN_ERR "FritzPnP: attach failed\n");
-						return 0;
-					}
-					if (pnp_activate_dev(pnp_avm) < 0) {
-						printk(KERN_ERR "FritzPnP: activate failed\n");
-						pnp_device_detach(pnp_avm);
-						return 0;
+					ISAPNP_FUNCTION(0x0900), pnp_avm_d))) {
+					int err;
+
+					pnp_disable_dev(pnp_avm_d);
+					err = pnp_activate_dev(pnp_avm_d);
+					if (err<0) {
+						printk(KERN_WARNING "%s: pnp_activate_dev ret(%d)\n",
+							__FUNCTION__, err);
+						return(0);
 					}
-					if (!pnp_irq_valid(pnp_avm, 0)) {
+					cs->hw.avm.cfg_reg =
+						pnp_port_start(pnp_avm_d, 0);
+					cs->irq = pnp_irq(pnp_avm_d, 0);
+					if (!cs->irq) {
 						printk(KERN_ERR "FritzPnP:No IRQ\n");
-						pnp_device_detach(pnp_avm);
 						return(0);
 					}
-					if (!pnp_port_valid(pnp_avm, 0)) {
+					if (!cs->hw.avm.cfg_reg) {
 						printk(KERN_ERR "FritzPnP:No IO address\n");
-						pnp_device_detach(pnp_avm);
 						return(0);
 					}
-					card->para[1] = pnp_port_start(pnp_avm, 0);
-					card->para[0] = pnp_irq(pnp_avm, 0);
-					if (avm_pnp_probe(card->cs, card))
-						return 0;
-					return 1;
+					cs->subtyp = AVM_FRITZ_PNP;
+					goto ready;
 				}
 			}
+		} else {
+			printk(KERN_INFO "FritzPnP: no ISA PnP present\n");
 		}
 #endif
-#ifdef CONFIG_PCI
+#if CONFIG_PCI
 		if ((dev_avm = pci_find_device(PCI_VENDOR_ID_AVM,
 			PCI_DEVICE_ID_AVM_A1,  dev_avm))) {
-			if (avm_pci_probe(card->cs, dev_avm))
-				return 0;
-			return 1;
+			cs->irq = dev_avm->irq;
+			if (!cs->irq) {
+				printk(KERN_ERR "FritzPCI: No IRQ for PCI card found\n");
+				return(0);
+			}
+			if (pci_enable_device(dev_avm))
+				return(0);
+			cs->hw.avm.cfg_reg = pci_resource_start(dev_avm, 1);
+			if (!cs->hw.avm.cfg_reg) {
+				printk(KERN_ERR "FritzPCI: No IO-Adr for PCI card found\n");
+				return(0);
+			}
+			cs->subtyp = AVM_FRITZ_PCI;
+		} else {
+			printk(KERN_WARNING "FritzPCI: No PCI card found\n");
+			return(0);
 		}
+		cs->irq_flags |= SA_SHIRQ;
+#else
+		printk(KERN_WARNING "FritzPCI: NO_PCI_BIOS\n");
+		return (0);
 #endif /* CONFIG_PCI */
 	}
-	printk(KERN_WARNING "FritzPCI: No card found\n");
-	return 0;
+ready:
+	cs->hw.avm.isac = cs->hw.avm.cfg_reg + 0x10;
+	if (!request_region(cs->hw.avm.cfg_reg, 32,
+		(cs->subtyp == AVM_FRITZ_PCI) ? "avm PCI" : "avm PnP")) {
+		printk(KERN_WARNING
+		       "HiSax: %s config port %x-%x already in use\n",
+		       CardType[card->typ],
+		       cs->hw.avm.cfg_reg,
+		       cs->hw.avm.cfg_reg + 31);
+		return (0);
+	}
+	switch (cs->subtyp) {
+	  case AVM_FRITZ_PCI:
+		val = inl(cs->hw.avm.cfg_reg);
+		printk(KERN_INFO "AVM PCI: stat %#x\n", val);
+		printk(KERN_INFO "AVM PCI: Class %X Rev %d\n",
+			val & 0xff, (val>>8) & 0xff);
+		cs->BC_Read_Reg = &ReadHDLC_s;
+		cs->BC_Write_Reg = &WriteHDLC_s;
+		break;
+	  case AVM_FRITZ_PNP:
+		val = inb(cs->hw.avm.cfg_reg);
+		ver = inb(cs->hw.avm.cfg_reg + 1);
+		printk(KERN_INFO "AVM PnP: Class %X Rev %d\n", val, ver);
+		cs->BC_Read_Reg = &ReadHDLCPnP;
+		cs->BC_Write_Reg = &WriteHDLCPnP;
+		break;
+	  default:
+	  	printk(KERN_WARNING "AVM unknown subtype %d\n", cs->subtyp);
+	  	return(0);
+	}
+	printk(KERN_INFO "HiSax: %s config irq:%d base:0x%X\n",
+		(cs->subtyp == AVM_FRITZ_PCI) ? "AVM Fritz!PCI" : "AVM Fritz!PnP",
+		cs->irq, cs->hw.avm.cfg_reg);
+
+	setup_isac(cs);
+	cs->readisac = &ReadISAC;
+	cs->writeisac = &WriteISAC;
+	cs->readisacfifo = &ReadISACfifo;
+	cs->writeisacfifo = &WriteISACfifo;
+	cs->BC_Send_Data = &hdlc_fill_fifo;
+	cs->cardmsg = &AVM_card_msg;
+	cs->irq_func = &avm_pcipnp_interrupt;
+	cs->writeisac(cs, ISAC_MASK, 0xFF);
+	ISACVersion(cs, (cs->subtyp == AVM_FRITZ_PCI) ? "AVM PCI:" : "AVM PnP:");
+	return (1);
 }
--- diff/drivers/isdn/hisax/avma1_cs.c	2004-02-09 10:36:10.000000000 +0000
+++ source/drivers/isdn/hisax/avma1_cs.c	2004-02-23 13:56:42.000000000 +0000
@@ -26,15 +26,12 @@
 #include <pcmcia/cs.h>
 #include <pcmcia/cistpl.h>
 #include <pcmcia/ds.h>
+#include "hisax_cfg.h"
 
 MODULE_DESCRIPTION("ISDN4Linux: PCMCIA client driver for AVM A1/Fritz!PCMCIA cards");
 MODULE_AUTHOR("Carsten Paeth");
 MODULE_LICENSE("GPL");
 
-int avm_a1_init_pcmcia(void *pcm_iob, int pcm_irq, int *busy_flag, int prot);
-void HiSax_closecard(int cardnr);
-
-
 /*
    All the PCMCIA modules use PCMCIA_DEBUG to control debugging.  If
    you do not define PCMCIA_DEBUG at all, all the debug code will be
@@ -156,6 +153,15 @@ static dev_link_t *avma1cs_attach(void)
 	return NULL;
     memset(link, 0, sizeof(struct dev_link_t));
 
+    /* Allocate space for private device-specific data */
+    local = kmalloc(sizeof(local_info_t), GFP_KERNEL);
+    if (!local) {
+	kfree(link);
+	return NULL;
+    }
+    memset(local, 0, sizeof(local_info_t));
+    link->priv = local;
+
     /* The io structure describes IO port mapping */
     link->io.NumPorts1 = 16;
     link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
@@ -183,15 +189,6 @@ static dev_link_t *avma1cs_attach(void)
     link->conf.ConfigIndex = 1;
     link->conf.Present = PRESENT_OPTION;
 
-    /* Allocate space for private device-specific data */
-    local = kmalloc(sizeof(local_info_t), GFP_KERNEL);
-    if (!local) {
-	kfree(link);
-	return NULL;
-    }
-    memset(local, 0, sizeof(local_info_t));
-    link->priv = local;
-    
     /* Register with Card Services */
     link->next = dev_list;
     dev_list = link;
@@ -252,7 +249,7 @@ static void avma1cs_detach(dev_link_t *l
 
     /* Break the link with Card Services */
     if (link->handle)
-	pcmcia_deregister_client(link->handle);
+    	pcmcia_deregister_client(link->handle);
     
     /* Unlink device structure, free pieces */
     *linkp = link->next;
@@ -303,8 +300,9 @@ static void avma1cs_config(dev_link_t *l
     cistpl_cftable_entry_t *cf = &parse.cftable_entry;
     local_info_t *dev;
     int i;
-    u8 buf[64];
+    u_char buf[64];
     char devname[128];
+    IsdnCard_t	icard;
     int busy = 0;
     
     handle = link->handle;
@@ -365,9 +363,9 @@ static void avma1cs_config(dev_link_t *l
 		link->io.BasePort1 = cf->io.win[0].base;
 		link->io.NumPorts1 = cf->io.win[0].len;
 		link->io.NumPorts2 = 0;
-                printk(KERN_INFO "avma1_cs: testing i/o %#x-%#x\n",
+		printk(KERN_INFO "avma1_cs: testing i/o %#x-%#x\n",
 			link->io.BasePort1,
-		        link->io.BasePort1+link->io.NumPorts1 - 1);
+			link->io.BasePort1+link->io.NumPorts1 - 1);
 		i = pcmcia_request_io(link->handle, &link->io);
 		if (i == CS_SUCCESS) goto found_port;
 	    }
@@ -391,8 +389,8 @@ found_port:
 	}
 	
 	/*
-         * configure the PCMCIA socket
-	  */
+	 * configure the PCMCIA socket
+	 */
 	i = pcmcia_request_configuration(link->handle, &link->conf);
 	if (i != CS_SUCCESS) {
 	    cs_error(link->handle, RequestConfiguration, i);
@@ -421,15 +419,17 @@ found_port:
     printk(KERN_NOTICE "avma1_cs: checking at i/o %#x, irq %d\n",
 				link->io.BasePort1, link->irq.AssignedIRQ);
 
-    if (avm_a1_init_pcmcia((void *)(int)link->io.BasePort1,
-                           link->irq.AssignedIRQ,
-                           &busy, isdnprot) != 0) {
-       printk(KERN_ERR "avma1_cs: failed to initialize AVM A1 PCMCIA %d at i/o %#x\n", i, link->io.BasePort1);
-       return;
+    icard.para[0] = link->irq.AssignedIRQ;
+    icard.para[1] = link->io.BasePort1;
+    icard.protocol = isdnprot;
+    icard.typ = ISDN_CTYPE_A1_PCMCIA;
+    
+    i = hisax_init_pcmcia(link, &busy, &icard);
+    if (i < 0) {
+    	printk(KERN_ERR "avma1_cs: failed to initialize AVM A1 PCMCIA %d at i/o %#x\n", i, link->io.BasePort1);
+	avma1cs_release(link);
+	return;
     }
-
-    i = 0; /* no returncode for cardnr :-( */
-
     dev->node.minor = i;
 
 } /* avma1cs_config */
@@ -486,29 +486,28 @@ static int avma1cs_event(event_t event, 
     DEBUG(1, "avma1cs_event(0x%06x)\n", event);
     
     switch (event) {
-    case CS_EVENT_CARD_REMOVAL:
-	link->state &= ~DEV_PRESENT;
-	if (link->state & DEV_CONFIG)
+	case CS_EVENT_CARD_REMOVAL:
+	    if (link->state & DEV_CONFIG)
 		avma1cs_release(link);
-	break;
-    case CS_EVENT_CARD_INSERTION:
-	link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
-	avma1cs_config(link);
-	break;
-    case CS_EVENT_PM_SUSPEND:
-	link->state |= DEV_SUSPEND;
-	/* Fall through... */
-    case CS_EVENT_RESET_PHYSICAL:
-	if (link->state & DEV_CONFIG)
-	    pcmcia_release_configuration(link->handle);
-	break;
-    case CS_EVENT_PM_RESUME:
-	link->state &= ~DEV_SUSPEND;
-	/* Fall through... */
-    case CS_EVENT_CARD_RESET:
-	if (link->state & DEV_CONFIG)
-	    pcmcia_request_configuration(link->handle, &link->conf);
-	break;
+	    break;
+	case CS_EVENT_CARD_INSERTION:
+	    link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
+	    avma1cs_config(link);
+	    break;
+	case CS_EVENT_PM_SUSPEND:
+	    link->state |= DEV_SUSPEND;
+	    /* Fall through... */
+	case CS_EVENT_RESET_PHYSICAL:
+	    if (link->state & DEV_CONFIG)
+		pcmcia_release_configuration(link->handle);
+	    break;
+	case CS_EVENT_PM_RESUME:
+	    link->state &= ~DEV_SUSPEND;
+	    /* Fall through... */
+	case CS_EVENT_CARD_RESET:
+ 	    if (link->state & DEV_CONFIG)
+		pcmcia_request_configuration(link->handle, &link->conf);
+	    break;
     }
     return 0;
 } /* avma1cs_event */
@@ -521,10 +520,12 @@ static struct pcmcia_driver avma1cs_driv
 	.attach		= avma1cs_attach,
 	.detach		= avma1cs_detach,
 };
+ 
+/*====================================================================*/
 
 static int __init init_avma1_cs(void)
 {
-	return pcmcia_register_driver(&avma1cs_driver);
+	return(pcmcia_register_driver(&avma1cs_driver));
 }
 
 static void __exit exit_avma1_cs(void)
--- diff/drivers/isdn/hisax/bkm_a4t.c	2003-05-21 11:50:15.000000000 +0100
+++ source/drivers/isdn/hisax/bkm_a4t.c	2004-02-23 13:56:42.000000000 +0000
@@ -1,4 +1,4 @@
-/* $Id: bkm_a4t.c,v 1.13.6.6 2001/09/23 22:24:46 kai Exp $
+/* $Id: bkm_a4t.c,v 1.22.2.4 2004/01/14 16:04:48 keil Exp $
  *
  * low level stuff for T-Berkom A4T
  *
@@ -10,6 +10,7 @@
  *
  */
 
+
 #include <linux/config.h>
 #include <linux/init.h>
 #include "hisax.h"
@@ -21,51 +22,47 @@
 #include "bkm_ax.h"
 
 extern const char *CardType[];
-// FIXME needs per card lock
-static spinlock_t bkm_a4t_lock = SPIN_LOCK_UNLOCKED;
 
-const char *bkm_a4t_revision = "$Revision: 1.13.6.6 $";
+const char *bkm_a4t_revision = "$Revision: 1.22.2.4 $";
+
 
-static inline u8
-readreg(unsigned int ale, unsigned long adr, u8 off)
+static inline u_char
+readreg(unsigned int ale, unsigned long adr, u_char off)
 {
-	u_int ret;
-	unsigned long flags;
+	register u_int ret;
 	unsigned int *po = (unsigned int *) adr;	/* Postoffice */
-	spin_lock_irqsave(&bkm_a4t_lock, flags);
+
 	*po = (GCS_2 | PO_WRITE | off);
 	__WAITI20__(po);
 	*po = (ale | PO_READ);
 	__WAITI20__(po);
 	ret = *po;
-	spin_unlock_irqrestore(&bkm_a4t_lock, flags);
 	return ((unsigned char) ret);
 }
 
+
 static inline void
-writereg(unsigned int ale, unsigned long adr, u8 off, u8 data)
+readfifo(unsigned int ale, unsigned long adr, u_char off, u_char * data, int size)
+{
+	int i;
+	for (i = 0; i < size; i++)
+		*data++ = readreg(ale, adr, off);
+}
+
+
+static inline void
+writereg(unsigned int ale, unsigned long adr, u_char off, u_char data)
 {
-	unsigned long flags;
 	unsigned int *po = (unsigned int *) adr;	/* Postoffice */
-	spin_lock_irqsave(&bkm_a4t_lock, flags);
 	*po = (GCS_2 | PO_WRITE | off);
 	__WAITI20__(po);
 	*po = (ale | PO_WRITE | data);
 	__WAITI20__(po);
-	spin_unlock_irqrestore(&bkm_a4t_lock, flags);
 }
 
-static inline void
-readfifo(unsigned int ale, unsigned long adr, u8 off, u8 * data, int size)
-{
-	int i;
-
-	for (i = 0; i < size; i++)
-		*data++ = readreg(ale, adr, off);
-}
 
 static inline void
-writefifo(unsigned int ale, unsigned long adr, u8 off, u8 * data, int size)
+writefifo(unsigned int ale, unsigned long adr, u_char off, u_char * data, int size)
 {
 	int i;
 
@@ -73,84 +70,74 @@ writefifo(unsigned int ale, unsigned lon
 		writereg(ale, adr, off, *data++);
 }
 
-static u8
-isac_read(struct IsdnCardState *cs, u8 offset)
+
+/* Interface functions */
+
+static u_char
+ReadISAC(struct IsdnCardState *cs, u_char offset)
 {
 	return (readreg(cs->hw.ax.isac_ale, cs->hw.ax.isac_adr, offset));
 }
 
 static void
-isac_write(struct IsdnCardState *cs, u8 offset, u8 value)
+WriteISAC(struct IsdnCardState *cs, u_char offset, u_char value)
 {
 	writereg(cs->hw.ax.isac_ale, cs->hw.ax.isac_adr, offset, value);
 }
 
 static void
-isac_read_fifo(struct IsdnCardState *cs, u8 * data, int size)
+ReadISACfifo(struct IsdnCardState *cs, u_char * data, int size)
 {
 	readfifo(cs->hw.ax.isac_ale, cs->hw.ax.isac_adr, 0, data, size);
 }
 
 static void
-isac_write_fifo(struct IsdnCardState *cs, u8 * data, int size)
+WriteISACfifo(struct IsdnCardState *cs, u_char * data, int size)
 {
 	writefifo(cs->hw.ax.isac_ale, cs->hw.ax.isac_adr, 0, data, size);
 }
 
-static struct dc_hw_ops isac_ops = {
-	.read_reg   = isac_read,
-	.write_reg  = isac_write,
-	.read_fifo  = isac_read_fifo,
-	.write_fifo = isac_write_fifo,
-};
-
-static u8
-jade_read(struct IsdnCardState *cs, int jade, u8 offset)
+static u_char
+ReadJADE(struct IsdnCardState *cs, int jade, u_char offset)
 {
-	return readreg(cs->hw.ax.jade_ale, cs->hw.ax.jade_adr, offset + (jade == -1 ? 0 : (jade ? 0xC0 : 0x80)));
+	return (readreg(cs->hw.ax.jade_ale, cs->hw.ax.jade_adr, offset + (jade == -1 ? 0 : (jade ? 0xC0 : 0x80))));
 }
 
 static void
-jade_write(struct IsdnCardState *cs, int jade, u8 offset, u8 value)
+WriteJADE(struct IsdnCardState *cs, int jade, u_char offset, u_char value)
 {
 	writereg(cs->hw.ax.jade_ale, cs->hw.ax.jade_adr, offset + (jade == -1 ? 0 : (jade ? 0xC0 : 0x80)), value);
 }
 
-static void
-jade_read_fifo(struct IsdnCardState *cs, int hscx, u8 *data, int size)
-{
-	readfifo(cs->hw.ax.jade_ale, cs->hw.ax.jade_adr,
-		 (hscx == -1 ? 0 : (hscx ? 0xc0 : 0x80)), data, size);
-}
+/*
+ * fast interrupt JADE stuff goes here
+ */
 
-static void
-jade_write_fifo(struct IsdnCardState *cs, int hscx, u8 *data, int size)
-{
-	writefifo(cs->hw.ax.jade_ale, cs->hw.ax.jade_adr,
-		  (hscx == -1 ? 0 : (hscx ? 0xc0 : 0x80)), data, size);
-}
+#define READJADE(cs, nr, reg) readreg(cs->hw.ax.jade_ale,\
+ 		cs->hw.ax.jade_adr, reg + (nr == -1 ? 0 : (nr ? 0xC0 : 0x80)))
+#define WRITEJADE(cs, nr, reg, data) writereg(cs->hw.ax.jade_ale,\
+ 		cs->hw.ax.jade_adr, reg + (nr == -1 ? 0 : (nr ? 0xC0 : 0x80)), data)
+
+#define READJADEFIFO(cs, nr, ptr, cnt) readfifo(cs->hw.ax.jade_ale,\
+		cs->hw.ax.jade_adr, (nr == -1 ? 0 : (nr ? 0xC0 : 0x80)), ptr, cnt)
+#define WRITEJADEFIFO(cs, nr, ptr, cnt) writefifo( cs->hw.ax.jade_ale,\
+		cs->hw.ax.jade_adr, (nr == -1 ? 0 : (nr ? 0xC0 : 0x80)), ptr, cnt)
 
-static struct bc_hw_ops jade_ops = {
-	.read_reg   = jade_read,
-	.write_reg  = jade_write,
-	.read_fifo  = jade_read_fifo,
-	.write_fifo = jade_write_fifo,
-};
+#include "jade_irq.c"
 
 static irqreturn_t
 bkm_interrupt(int intno, void *dev_id, struct pt_regs *regs)
 {
 	struct IsdnCardState *cs = dev_id;
-	u8 val = 0;
+	u_char val = 0;
+	u_long flags;
 	I20_REGISTER_FILE *pI20_Regs;
-	int handled = 0;
 
-	spin_lock(&cs->lock);
+	spin_lock_irqsave(&cs->lock, flags);
 	pI20_Regs = (I20_REGISTER_FILE *) (cs->hw.ax.base);
 
 	/* ISDN interrupt pending? */
 	if (pI20_Regs->i20IntStatus & intISDN) {
-		handled = 1;
 		/* Reset the ISDN interrupt     */
 		pI20_Regs->i20IntStatus = intISDN;
 		/* Disable ISDN interrupt */
@@ -172,129 +159,101 @@ bkm_interrupt(int intno, void *dev_id, s
 		}
 		/* Reenable ISDN interrupt */
 		pI20_Regs->i20IntCtrl |= intISDN;
+		spin_unlock_irqrestore(&cs->lock, flags);
+		return IRQ_HANDLED;
+	} else {
+		spin_unlock_irqrestore(&cs->lock, flags);
+		return IRQ_NONE;
 	}
-	spin_unlock(&cs->lock);
-	return IRQ_RETVAL(handled);
 }
 
-static void
-enable_bkm_int(struct IsdnCardState *cs, unsigned bEnable)
+void
+release_io_bkm(struct IsdnCardState *cs)
 {
-	I20_REGISTER_FILE *pI20_Regs = (I20_REGISTER_FILE *) (cs->hw.ax.base);
-	if (bEnable)
-		pI20_Regs->i20IntCtrl |= (intISDN | intPCI);
-	else
-		/* CAUTION: This disables the video capture driver too */
-		pI20_Regs->i20IntCtrl &= ~(intISDN | intPCI);
+	if (cs->hw.ax.base) {
+		iounmap((void *) cs->hw.ax.base);
+		cs->hw.ax.base = 0;
+	}
 }
 
 static void
-reset_bkm(struct IsdnCardState *cs)
+enable_bkm_int(struct IsdnCardState *cs, unsigned bEnable)
 {
-	I20_REGISTER_FILE *pI20_Regs = (I20_REGISTER_FILE *) (cs->hw.ax.base);
-	/* Issue the I20 soft reset     */
-	pI20_Regs->i20SysControl = 0xFF;	/* all in */
-	set_current_state(TASK_UNINTERRUPTIBLE);
-	schedule_timeout((10 * HZ) / 1000);
-	/* Remove the soft reset */
-	pI20_Regs->i20SysControl = sysRESET | 0xFF;
-	set_current_state(TASK_UNINTERRUPTIBLE);
-	schedule_timeout((10 * HZ) / 1000);
-	/* Set our configuration */
-	pI20_Regs->i20SysControl = sysRESET | sysCFG;
-	/* Issue ISDN reset     */
-	pI20_Regs->i20GuestControl = guestWAIT_CFG |
-		g_A4T_JADE_RES |
-		g_A4T_ISAR_RES |
-		g_A4T_ISAC_RES |
-		g_A4T_JADE_BOOTR |
-		g_A4T_ISAR_BOOTR;
-	set_current_state(TASK_UNINTERRUPTIBLE);
-	schedule_timeout((10 * HZ) / 1000);
-
-	/* Remove RESET state from ISDN */
-	pI20_Regs->i20GuestControl &= ~(g_A4T_ISAC_RES |
-					g_A4T_JADE_RES |
-					g_A4T_ISAR_RES);
-	set_current_state(TASK_UNINTERRUPTIBLE);
-	schedule_timeout((10 * HZ) / 1000);
+	if (cs->typ == ISDN_CTYPE_BKM_A4T) {
+		I20_REGISTER_FILE *pI20_Regs = (I20_REGISTER_FILE *) (cs->hw.ax.base);
+		if (bEnable)
+			pI20_Regs->i20IntCtrl |= (intISDN | intPCI);
+		else
+			/* CAUTION: This disables the video capture driver too */
+			pI20_Regs->i20IntCtrl &= ~(intISDN | intPCI);
+	}
 }
 
 static void
-bkm_a4t_init(struct IsdnCardState *cs)
+reset_bkm(struct IsdnCardState *cs)
 {
-	initisac(cs);
-	initjade(cs);
-	/* Enable ints */
-	enable_bkm_int(cs, 1);
+	if (cs->typ == ISDN_CTYPE_BKM_A4T) {
+		I20_REGISTER_FILE *pI20_Regs = (I20_REGISTER_FILE *) (cs->hw.ax.base);
+		/* Issue the I20 soft reset     */
+		pI20_Regs->i20SysControl = 0xFF;	/* all in */
+		mdelay(10);
+		/* Remove the soft reset */
+		pI20_Regs->i20SysControl = sysRESET | 0xFF;
+		mdelay(10);
+		/* Set our configuration */
+		pI20_Regs->i20SysControl = sysRESET | sysCFG;
+		/* Issue ISDN reset     */
+		pI20_Regs->i20GuestControl = guestWAIT_CFG |
+		    g_A4T_JADE_RES |
+		    g_A4T_ISAR_RES |
+		    g_A4T_ISAC_RES |
+		    g_A4T_JADE_BOOTR |
+		    g_A4T_ISAR_BOOTR;
+		mdelay(10);
+
+		/* Remove RESET state from ISDN */
+		pI20_Regs->i20GuestControl &= ~(g_A4T_ISAC_RES |
+						g_A4T_JADE_RES |
+						g_A4T_ISAR_RES);
+		mdelay(10);
+	}
 }
 
 static int
-bkm_a4t_reset(struct IsdnCardState *cs)
+BKM_card_msg(struct IsdnCardState *cs, int mt, void *arg)
 {
-	/* Disable ints */
-	enable_bkm_int(cs, 0);
-	reset_bkm(cs);
-	return 0;
-}
-
-static void
-bkm_a4t_release(struct IsdnCardState *cs)
-{
-	reset_bkm(cs);
-	hisax_release_resources(cs);
-}
-
-static struct card_ops bkm_a4t_ops = {
-	.init     = bkm_a4t_init,
-	.reset    = bkm_a4t_reset,
-	.release  = bkm_a4t_release,
-	.irq_func = bkm_interrupt,
-};
+	u_long flags;
 
-static int __init
-bkm_a4t_probe(struct IsdnCardState *cs, struct pci_dev *pdev)
-{
-	I20_REGISTER_FILE *pI20_Regs;
-	int rc;
-
-	printk(KERN_INFO "BKM A4T: defined at %#lx IRQ %u\n",
-	       pci_resource_start(pdev, 0), pdev->irq);
-	
-	rc = -EBUSY;
-	if (pci_enable_device(pdev))
-		goto err;
-			
-	cs->irq = pdev->irq;
-	cs->irq_flags |= SA_SHIRQ;
-	cs->hw.avm.cfg_reg = pci_resource_start(pdev, 1);
-
-	cs->hw.ax.base = (unsigned long)request_mmio(&cs->rs, pci_resource_start(pdev, 0), 4096, "Telekom A4T");
-	if (!cs->hw.ax.base)
-		goto err;
-	
-	/* Check suspicious address */
-	// FIXME needs to use read[bl]
-	pI20_Regs = (I20_REGISTER_FILE *) (cs->hw.ax.base);
-	if ((pI20_Regs->i20IntStatus & 0x8EFFFFFF) != 0) {
-		printk(KERN_WARNING "HiSax: address %lx suspicious\n",
-		       cs->hw.ax.base);
-		goto err;
+	switch (mt) {
+		case CARD_RESET:
+			/* Disable ints */
+			spin_lock_irqsave(&cs->lock, flags);
+			enable_bkm_int(cs, 0);
+			reset_bkm(cs);
+			spin_unlock_irqrestore(&cs->lock, flags);
+			return (0);
+		case CARD_RELEASE:
+			/* Sanity */
+			spin_lock_irqsave(&cs->lock, flags);
+			enable_bkm_int(cs, 0);
+			reset_bkm(cs);
+			spin_unlock_irqrestore(&cs->lock, flags);
+			release_io_bkm(cs);
+			return (0);
+		case CARD_INIT:
+			spin_lock_irqsave(&cs->lock, flags);
+			clear_pending_isac_ints(cs);
+			clear_pending_jade_ints(cs);
+			initisac(cs);
+			initjade(cs);
+			/* Enable ints */
+			enable_bkm_int(cs, 1);
+			spin_unlock_irqrestore(&cs->lock, flags);
+			return (0);
+		case CARD_TEST:
+			return (0);
 	}
-	cs->hw.ax.isac_adr = cs->hw.ax.base + PO_OFFSET;
-	cs->hw.ax.jade_adr = cs->hw.ax.base + PO_OFFSET;
-	cs->hw.ax.isac_ale = GCS_1;
-	cs->hw.ax.jade_ale = GCS_3;
-
-	reset_bkm(cs);
-	cs->card_ops = &bkm_a4t_ops;
-	isac_setup(cs, &isac_ops);
-	jade_setup(cs, &jade_ops);
-	return 0;
-
- err:
-	hisax_release_resources(cs);
-	return rc;
+	return (0);
 }
 
 static struct pci_dev *dev_a4t __initdata = NULL;
@@ -302,10 +261,21 @@ static struct pci_dev *dev_a4t __initdat
 int __init
 setup_bkm_a4t(struct IsdnCard *card)
 {
+	struct IsdnCardState *cs = card->cs;
 	char tmp[64];
+	u_int pci_memaddr = 0, found = 0;
+	I20_REGISTER_FILE *pI20_Regs;
+#if CONFIG_PCI
+#endif
 
 	strcpy(tmp, bkm_a4t_revision);
 	printk(KERN_INFO "HiSax: T-Berkom driver Rev. %s\n", HiSax_getrev(tmp));
+	if (cs->typ == ISDN_CTYPE_BKM_A4T) {
+		cs->subtyp = BKM_A4T;
+	} else
+		return (0);
+
+#if CONFIG_PCI
 	while ((dev_a4t = pci_find_device(PCI_VENDOR_ID_ZORAN,
 		PCI_DEVICE_ID_ZORAN_36120, dev_a4t))) {
 		u16 sub_sys;
@@ -313,13 +283,62 @@ setup_bkm_a4t(struct IsdnCard *card)
 
 		sub_vendor = dev_a4t->subsystem_vendor;
 		sub_sys = dev_a4t->subsystem_device;
-		if (sub_sys == PCI_DEVICE_ID_BERKOM_A4T && 
-		    sub_vendor == PCI_VENDOR_ID_BERKOM) {
-			if (bkm_a4t_probe(card->cs, dev_a4t))
-				return 0;
-			return 1;
+		if ((sub_sys == PCI_DEVICE_ID_BERKOM_A4T) && (sub_vendor == PCI_VENDOR_ID_BERKOM)) {
+			if (pci_enable_device(dev_a4t))
+				return(0);
+			found = 1;
+			pci_memaddr = pci_resource_start(dev_a4t, 0);
+			cs->irq = dev_a4t->irq;
+			break;
 		}
 	}
-	printk(KERN_WARNING "HiSax: %s: Card not found\n", CardType[card->typ]);
-	return 0;
+	if (!found) {
+		printk(KERN_WARNING "HiSax: %s: Card not found\n", CardType[card->typ]);
+		return (0);
+	}
+	if (!cs->irq) {		/* IRQ range check ?? */
+		printk(KERN_WARNING "HiSax: %s: No IRQ\n", CardType[card->typ]);
+		return (0);
+	}
+	if (!pci_memaddr) {
+		printk(KERN_WARNING "HiSax: %s: No Memory base address\n", CardType[card->typ]);
+		return (0);
+	}
+	cs->hw.ax.base = (long) ioremap(pci_memaddr, 4096);
+	/* Check suspecious address */
+	pI20_Regs = (I20_REGISTER_FILE *) (cs->hw.ax.base);
+	if ((pI20_Regs->i20IntStatus & 0x8EFFFFFF) != 0) {
+		printk(KERN_WARNING "HiSax: %s address %lx-%lx suspecious\n",
+		       CardType[card->typ], cs->hw.ax.base, cs->hw.ax.base + 4096);
+		iounmap((void *) cs->hw.ax.base);
+		cs->hw.ax.base = 0;
+		return (0);
+	}
+	cs->hw.ax.isac_adr = cs->hw.ax.base + PO_OFFSET;
+	cs->hw.ax.jade_adr = cs->hw.ax.base + PO_OFFSET;
+	cs->hw.ax.isac_ale = GCS_1;
+	cs->hw.ax.jade_ale = GCS_3;
+#else
+	printk(KERN_WARNING "HiSax: %s: NO_PCI_BIOS\n", CardType[card->typ]);
+	printk(KERN_WARNING "HiSax: %s: unable to configure\n", CardType[card->typ]);
+	return (0);
+#endif				/* CONFIG_PCI */
+	printk(KERN_INFO "HiSax: %s: Card configured at 0x%lX IRQ %d\n",
+	       CardType[card->typ], cs->hw.ax.base, cs->irq);
+
+	setup_isac(cs);
+	cs->readisac = &ReadISAC;
+	cs->writeisac = &WriteISAC;
+	cs->readisacfifo = &ReadISACfifo;
+	cs->writeisacfifo = &WriteISACfifo;
+	cs->BC_Read_Reg = &ReadJADE;
+	cs->BC_Write_Reg = &WriteJADE;
+	cs->BC_Send_Data = &jade_fill_fifo;
+	cs->cardmsg = &BKM_card_msg;
+	cs->irq_func = &bkm_interrupt;
+	cs->irq_flags |= SA_SHIRQ;
+	ISACVersion(cs, "Telekom A4T:");
+	/* Jade version */
+	JadeVersion(cs, "Telekom A4T:");
+	return (1);
 }
--- diff/drivers/isdn/hisax/bkm_a8.c	2003-01-16 11:30:36.000000000 +0000
+++ source/drivers/isdn/hisax/bkm_a8.c	2004-02-23 13:56:42.000000000 +0000
@@ -1,4 +1,4 @@
-/* $Id: bkm_a8.c,v 1.14.6.7 2001/09/23 22:24:46 kai Exp $
+/* $Id: bkm_a8.c,v 1.22.2.4 2004/01/15 14:02:34 keil Exp $
  *
  * low level stuff for Scitel Quadro (4*S0, passive)
  *
@@ -10,6 +10,7 @@
  *
  */
 
+
 #include <linux/config.h>
 #include <linux/init.h>
 #include "hisax.h"
@@ -20,11 +21,13 @@
 #include <linux/pci.h>
 #include "bkm_ax.h"
 
+#if CONFIG_PCI
+
 #define	ATTEMPT_PCI_REMAPPING	/* Required for PLX rev 1 */
 
 extern const char *CardType[];
-static spinlock_t bkm_a8_lock = SPIN_LOCK_UNLOCKED;
-const char sct_quadro_revision[] = "$Revision: 1.14.6.7 $";
+
+const char sct_quadro_revision[] = "$Revision: 1.22.2.4 $";
 
 static const char *sct_quadro_subtypes[] =
 {
@@ -39,70 +42,174 @@ static const char *sct_quadro_subtypes[]
 #define wordout(addr,val) outw(val,addr)
 #define wordin(addr) inw(addr)
 
-static inline u8
-ipac_read(struct IsdnCardState *cs, u8 off)
+static inline u_char
+readreg(unsigned int ale, unsigned int adr, u_char off)
 {
-	u8 ret;
-	unsigned long flags;
-
-	spin_lock_irqsave(&bkm_a8_lock, flags);
-	wordout(cs->hw.ax.base, off);
-	ret = wordin(cs->hw.ax.data_adr) & 0xFF;
-	spin_unlock_irqrestore(&bkm_a8_lock, flags);
-	return ret;
+	register u_char ret;
+	wordout(ale, off);
+	ret = wordin(adr) & 0xFF;
+	return (ret);
 }
 
 static inline void
-ipac_write(struct IsdnCardState *cs, u8 off, u8 data)
+readfifo(unsigned int ale, unsigned int adr, u_char off, u_char * data, int size)
 {
-	unsigned long flags;
+	int i;
+	wordout(ale, off);
+	for (i = 0; i < size; i++)
+		data[i] = wordin(adr) & 0xFF;
+}
 
-	spin_lock_irqsave(&bkm_a8_lock, flags);
-	wordout(cs->hw.ax.base, off);
-	wordout(cs->hw.ax.data_adr, data);
-	spin_unlock_irqrestore(&bkm_a8_lock, flags);
+
+static inline void
+writereg(unsigned int ale, unsigned int adr, u_char off, u_char data)
+{
+	wordout(ale, off);
+	wordout(adr, data);
 }
 
 static inline void
-ipac_readfifo(struct IsdnCardState *cs, u8 off, u8 *data, int size)
+writefifo(unsigned int ale, unsigned int adr, u_char off, u_char * data, int size)
 {
 	int i;
-
-	wordout(cs->hw.ax.base, off);
+	wordout(ale, off);
 	for (i = 0; i < size; i++)
-		data[i] = wordin(cs->hw.ax.data_adr) & 0xFF;
+		wordout(adr, data[i]);
 }
 
-static inline void
-ipac_writefifo(struct IsdnCardState *cs, u8 off, u8 *data, int size)
+/* Interface functions */
+
+static u_char
+ReadISAC(struct IsdnCardState *cs, u_char offset)
 {
-	int i;
+	return (readreg(cs->hw.ax.base, cs->hw.ax.data_adr, offset | 0x80));
+}
 
-	wordout(cs->hw.ax.base, off);
-	for (i = 0; i < size; i++)
-		wordout(cs->hw.ax.data_adr, data[i]);
+static void
+WriteISAC(struct IsdnCardState *cs, u_char offset, u_char value)
+{
+	writereg(cs->hw.ax.base, cs->hw.ax.data_adr, offset | 0x80, value);
+}
+
+static void
+ReadISACfifo(struct IsdnCardState *cs, u_char * data, int size)
+{
+	readfifo(cs->hw.ax.base, cs->hw.ax.data_adr, 0x80, data, size);
+}
+
+static void
+WriteISACfifo(struct IsdnCardState *cs, u_char * data, int size)
+{
+	writefifo(cs->hw.ax.base, cs->hw.ax.data_adr, 0x80, data, size);
 }
 
-/* This will generate ipac_dc_ops and ipac_bc_ops using the functions
- * above */
 
-BUILD_IPAC_OPS(ipac);
-  
+static u_char
+ReadHSCX(struct IsdnCardState *cs, int hscx, u_char offset)
+{
+	return (readreg(cs->hw.ax.base, cs->hw.ax.data_adr, offset + (hscx ? 0x40 : 0)));
+}
+
+static void
+WriteHSCX(struct IsdnCardState *cs, int hscx, u_char offset, u_char value)
+{
+	writereg(cs->hw.ax.base, cs->hw.ax.data_adr, offset + (hscx ? 0x40 : 0), value);
+}
+
 /* Set the specific ipac to active */
 static void
 set_ipac_active(struct IsdnCardState *cs, u_int active)
 {
 	/* set irq mask */
-	ipac_write(cs, IPAC_MASK, active ? 0xc0 : 0xff);
+	writereg(cs->hw.ax.base, cs->hw.ax.data_adr, IPAC_MASK,
+		active ? 0xc0 : 0xff);
+}
+
+/*
+ * fast interrupt HSCX stuff goes here
+ */
+
+#define READHSCX(cs, nr, reg) readreg(cs->hw.ax.base, \
+	cs->hw.ax.data_adr, reg + (nr ? 0x40 : 0))
+#define WRITEHSCX(cs, nr, reg, data) writereg(cs->hw.ax.base, \
+	cs->hw.ax.data_adr, reg + (nr ? 0x40 : 0), data)
+#define READHSCXFIFO(cs, nr, ptr, cnt) readfifo(cs->hw.ax.base, \
+	cs->hw.ax.data_adr, (nr ? 0x40 : 0), ptr, cnt)
+#define WRITEHSCXFIFO(cs, nr, ptr, cnt) writefifo(cs->hw.ax.base, \
+	cs->hw.ax.data_adr, (nr ? 0x40 : 0), ptr, cnt)
+
+#include "hscx_irq.c"
+
+static irqreturn_t
+bkm_interrupt_ipac(int intno, void *dev_id, struct pt_regs *regs)
+{
+	struct IsdnCardState *cs = dev_id;
+	u_char ista, val, icnt = 5;
+	u_long flags;
+
+	spin_lock_irqsave(&cs->lock, flags);
+	ista = readreg(cs->hw.ax.base, cs->hw.ax.data_adr, IPAC_ISTA);
+	if (!(ista & 0x3f)) { /* not this IPAC */
+		spin_unlock_irqrestore(&cs->lock, flags);
+		return IRQ_NONE;
+	}
+      Start_IPAC:
+	if (cs->debug & L1_DEB_IPAC)
+		debugl1(cs, "IPAC ISTA %02X", ista);
+	if (ista & 0x0f) {
+		val = readreg(cs->hw.ax.base, cs->hw.ax.data_adr, HSCX_ISTA + 0x40);
+		if (ista & 0x01)
+			val |= 0x01;
+		if (ista & 0x04)
+			val |= 0x02;
+		if (ista & 0x08)
+			val |= 0x04;
+		if (val) {
+			hscx_int_main(cs, val);
+		}
+	}
+	if (ista & 0x20) {
+		val = 0xfe & readreg(cs->hw.ax.base, cs->hw.ax.data_adr, ISAC_ISTA | 0x80);
+		if (val) {
+			isac_interrupt(cs, val);
+		}
+	}
+	if (ista & 0x10) {
+		val = 0x01;
+		isac_interrupt(cs, val);
+	}
+	ista = readreg(cs->hw.ax.base, cs->hw.ax.data_adr, IPAC_ISTA);
+	if ((ista & 0x3f) && icnt) {
+		icnt--;
+		goto Start_IPAC;
+	}
+	if (!icnt)
+		printk(KERN_WARNING "HiSax: %s (%s) IRQ LOOP\n",
+		       CardType[cs->typ],
+		       sct_quadro_subtypes[cs->subtyp]);
+	writereg(cs->hw.ax.base, cs->hw.ax.data_adr, IPAC_MASK, 0xFF);
+	writereg(cs->hw.ax.base, cs->hw.ax.data_adr, IPAC_MASK, 0xC0);
+	spin_unlock_irqrestore(&cs->lock, flags);
+	return IRQ_HANDLED;
+}
+
+void
+release_io_sct_quadro(struct IsdnCardState *cs)
+{
+	release_region(cs->hw.ax.base & 0xffffffc0, 128);
+	if (cs->subtyp == SCT_1)
+		release_region(cs->hw.ax.plx_adr, 64);
 }
 
 static void
 enable_bkm_int(struct IsdnCardState *cs, unsigned bEnable)
 {
-	if (bEnable)
-		wordout(cs->hw.ax.plx_adr + 0x4C, (wordin(cs->hw.ax.plx_adr + 0x4C) | 0x41));
-	else
-		wordout(cs->hw.ax.plx_adr + 0x4C, (wordin(cs->hw.ax.plx_adr + 0x4C) & ~0x41));
+	if (cs->typ == ISDN_CTYPE_SCT_QUADRO) {
+		if (bEnable)
+			wordout(cs->hw.ax.plx_adr + 0x4C, (wordin(cs->hw.ax.plx_adr + 0x4C) | 0x41));
+		else
+			wordout(cs->hw.ax.plx_adr + 0x4C, (wordin(cs->hw.ax.plx_adr + 0x4C) & ~0x41));
+	}
 }
 
 static void
@@ -110,66 +217,88 @@ reset_bkm(struct IsdnCardState *cs)
 {
 	if (cs->subtyp == SCT_1) {
 		wordout(cs->hw.ax.plx_adr + 0x50, (wordin(cs->hw.ax.plx_adr + 0x50) & ~4));
-		set_current_state(TASK_UNINTERRUPTIBLE);
-		schedule_timeout((10 * HZ) / 1000);
+		mdelay(10);
 		/* Remove the soft reset */
 		wordout(cs->hw.ax.plx_adr + 0x50, (wordin(cs->hw.ax.plx_adr + 0x50) | 4));
-		set_current_state(TASK_UNINTERRUPTIBLE);
-		schedule_timeout((10 * HZ) / 1000);
+		mdelay(10);
 	}
 }
 
-static void
-bkm_a8_init(struct IsdnCardState *cs)
-{
-	cs->debug |= L1_DEB_IPAC;
-	set_ipac_active(cs, 1);
-	ipac_init(cs);
-	/* Enable ints */
-	enable_bkm_int(cs, 1);
-}
-
 static int
-bkm_a8_reset(struct IsdnCardState *cs)
+BKM_card_msg(struct IsdnCardState *cs, int mt, void *arg)
 {
-	/* Disable ints */
-	set_ipac_active(cs, 0);
-	enable_bkm_int(cs, 0);
-	reset_bkm(cs);
-	return 0;
+	u_long flags;
+
+	switch (mt) {
+		case CARD_RESET:
+			spin_lock_irqsave(&cs->lock, flags);
+			/* Disable ints */
+			set_ipac_active(cs, 0);
+			enable_bkm_int(cs, 0);
+			reset_bkm(cs);
+			spin_unlock_irqrestore(&cs->lock, flags);
+			return (0);
+		case CARD_RELEASE:
+			/* Sanity */
+			spin_lock_irqsave(&cs->lock, flags);
+			set_ipac_active(cs, 0);
+			enable_bkm_int(cs, 0);
+			spin_unlock_irqrestore(&cs->lock, flags);
+			release_io_sct_quadro(cs);
+			return (0);
+		case CARD_INIT:
+			spin_lock_irqsave(&cs->lock, flags);
+			cs->debug |= L1_DEB_IPAC;
+			set_ipac_active(cs, 1);
+			inithscxisac(cs, 3);
+			/* Enable ints */
+			enable_bkm_int(cs, 1);
+			spin_unlock_irqrestore(&cs->lock, flags);
+			return (0);
+		case CARD_TEST:
+			return (0);
+	}
+	return (0);
 }
 
-static void
-bkm_a8_release(struct IsdnCardState *cs)
+int __init
+sct_alloc_io(u_int adr, u_int len)
 {
-	set_ipac_active(cs, 0);
-	enable_bkm_int(cs, 0);
-	hisax_release_resources(cs);
+	if (!request_region(adr, len, "scitel")) {
+		printk(KERN_WARNING
+			"HiSax: Scitel port %#x-%#x already in use\n",
+			adr, adr + len);
+		return (1);
+	}
+	return(0);
 }
 
-static struct card_ops bkm_a8_ops = {
-	.init     = bkm_a8_init,
-	.reset    = bkm_a8_reset,
-	.release  = bkm_a8_release,
-	.irq_func = ipac_irq,
-};
-
 static struct pci_dev *dev_a8 __initdata = NULL;
 static u16  sub_vendor_id __initdata = 0;
 static u16  sub_sys_id __initdata = 0;
-static u8 pci_irq __initdata = 0;
+static u_char pci_bus __initdata = 0;
+static u_char pci_device_fn __initdata = 0;
+static u_char pci_irq __initdata = 0;
+
+#endif /* CONFIG_PCI */
 
 int __init
 setup_sct_quadro(struct IsdnCard *card)
 {
+#if CONFIG_PCI
 	struct IsdnCardState *cs = card->cs;
 	char tmp[64];
-	u8 pci_rev_id;
+	u_char pci_rev_id;
 	u_int found = 0;
 	u_int pci_ioaddr1, pci_ioaddr2, pci_ioaddr3, pci_ioaddr4, pci_ioaddr5;
 
 	strcpy(tmp, sct_quadro_revision);
 	printk(KERN_INFO "HiSax: T-Berkom driver Rev. %s\n", HiSax_getrev(tmp));
+	if (cs->typ == ISDN_CTYPE_SCT_QUADRO) {
+		cs->subtyp = SCT_1;	/* Preset */
+	} else
+		return (0);
+
 	/* Identify subtype by para[0] */
 	if (card->para[0] >= SCT_1 && card->para[0] <= SCT_4)
 		cs->subtyp = card->para[0];
@@ -193,6 +322,8 @@ setup_sct_quadro(struct IsdnCard *card)
 					return(0);
 				pci_ioaddr1 = pci_resource_start(dev_a8, 1);
 				pci_irq = dev_a8->irq;
+				pci_bus = dev_a8->bus->number;
+				pci_device_fn = dev_a8->devfn;
 				found = 1;
 				break;
 			}
@@ -253,31 +384,40 @@ setup_sct_quadro(struct IsdnCard *card)
 	cs->hw.ax.plx_adr = pci_ioaddr1;
 	/* Enter all ipac_base addresses */
 	switch(cs->subtyp) {
-	case 1:
-		cs->hw.ax.base = pci_ioaddr5 + 0x00;
-		if (!request_io(&cs->rs, pci_ioaddr1, 128, "scitel"))
-			goto err;
-		if (!request_io(&cs->rs, pci_ioaddr5, 64, "scitel"))
-			goto err;
-		break;
-	case 2:
-		cs->hw.ax.base = pci_ioaddr4 + 0x08;
-		if (!request_io(&cs->rs, pci_ioaddr4, 64, "scitel"))
-			goto err;
-		break;
-	case 3:
-		cs->hw.ax.base = pci_ioaddr3 + 0x10;
-		if (!request_io(&cs->rs, pci_ioaddr3, 64, "scitel"))
-			goto err;
-		break;
-	case 4:
-		cs->hw.ax.base = pci_ioaddr2 + 0x20;
-		if (!request_io(&cs->rs, pci_ioaddr2, 64, "scitel"))
-			goto err;
-		break;
+		case 1:
+			cs->hw.ax.base = pci_ioaddr5 + 0x00;
+			if (sct_alloc_io(pci_ioaddr1, 128))
+				return(0);
+			if (sct_alloc_io(pci_ioaddr5, 64))
+				return(0);
+			/* disable all IPAC */
+			writereg(pci_ioaddr5, pci_ioaddr5 + 4,
+				IPAC_MASK, 0xFF);
+			writereg(pci_ioaddr4 + 0x08, pci_ioaddr4 + 0x0c,
+				IPAC_MASK, 0xFF);
+			writereg(pci_ioaddr3 + 0x10, pci_ioaddr3 + 0x14,
+				IPAC_MASK, 0xFF);
+			writereg(pci_ioaddr2 + 0x20, pci_ioaddr2 + 0x24,
+				IPAC_MASK, 0xFF);
+			break;
+		case 2:
+			cs->hw.ax.base = pci_ioaddr4 + 0x08;
+			if (sct_alloc_io(pci_ioaddr4, 64))
+				return(0);
+			break;
+		case 3:
+			cs->hw.ax.base = pci_ioaddr3 + 0x10;
+			if (sct_alloc_io(pci_ioaddr3, 64))
+				return(0);
+			break;
+		case 4:
+			cs->hw.ax.base = pci_ioaddr2 + 0x20;
+			if (sct_alloc_io(pci_ioaddr2, 64))
+				return(0);
+			break;
 	}	
+	/* For isac and hscx data path */
 	cs->hw.ax.data_adr = cs->hw.ax.base + 4;
-	ipac_write(cs, IPAC_MASK, 0xFF);
 
 	printk(KERN_INFO "HiSax: %s (%s) configured at 0x%.4lX, 0x%.4lX, 0x%.4lX and IRQ %d\n",
 	       CardType[card->typ],
@@ -287,12 +427,25 @@ setup_sct_quadro(struct IsdnCard *card)
 	       cs->hw.ax.data_adr,
 	       cs->irq);
 
-	cs->card_ops = &bkm_a8_ops;
-	if (ipac_setup(cs, &ipac_dc_ops, &ipac_bc_ops))
-		goto err;
-
-	return 1;
- err:
-	hisax_release_resources(cs);
-	return 0;
+	test_and_set_bit(HW_IPAC, &cs->HW_Flags);
+
+	cs->readisac = &ReadISAC;
+	cs->writeisac = &WriteISAC;
+	cs->readisacfifo = &ReadISACfifo;
+	cs->writeisacfifo = &WriteISACfifo;
+
+	cs->BC_Read_Reg = &ReadHSCX;
+	cs->BC_Write_Reg = &WriteHSCX;
+	cs->BC_Send_Data = &hscx_fill_fifo;
+	cs->cardmsg = &BKM_card_msg;
+	cs->irq_func = &bkm_interrupt_ipac;
+
+	printk(KERN_INFO "HiSax: %s (%s): IPAC Version %d\n",
+		CardType[card->typ],
+		sct_quadro_subtypes[cs->subtyp],
+		readreg(cs->hw.ax.base, cs->hw.ax.data_adr, IPAC_ID));
+	return (1);
+#else
+	printk(KERN_ERR "HiSax: bkm_a8 only supported on PCI Systems\n");
+#endif /* CONFIG_PCI */
 }
--- diff/drivers/isdn/hisax/callc.c	2003-09-17 12:28:06.000000000 +0100
+++ source/drivers/isdn/hisax/callc.c	2004-02-23 13:56:42.000000000 +0000
@@ -1,4 +1,4 @@
-/* $Id: callc.c,v 2.51.6.6 2001/09/23 22:24:46 kai Exp $
+/* $Id: callc.c,v 2.59.2.4 2004/02/11 13:21:32 keil Exp $
  *
  * Author       Karsten Keil
  * Copyright    by Karsten Keil      <keil@isdn4linux.de>
@@ -21,8 +21,7 @@
 #include "hisax.h"
 #include <linux/isdn/capicmd.h>
 
-
-const char *lli_revision = "$Revision: 2.51.6.6 $";
+const char *lli_revision = "$Revision: 2.59.2.4 $";
 
 extern struct IsdnCard cards[];
 extern int nrcards;
@@ -32,7 +31,6 @@ static void release_b_st(struct Channel 
 
 static struct Fsm callcfsm;
 static int chancount;
-static spinlock_t callc_lock = SPIN_LOCK_UNLOCKED;
 
 /* experimental REJECT after ALERTING for CALLBACK to beat the 4s delay */
 #define ALERT_REJECT 0
@@ -205,49 +203,13 @@ lli_deliver_cause(struct Channel *chanp)
 }
 
 static inline void
-mdl_info_setup(struct Channel *chanp)
-{
-	if (chanp->chan)
-		chanp->cs->status |=  0x0200;
-	else
-		chanp->cs->status |=  0x0100;
-
-	if (chanp->cs->card_ops->led_handler)
-		chanp->cs->card_ops->led_handler(chanp->cs);
-}
-
-static inline void
-mdl_info_connect(struct Channel *chanp)
-{
-	if (chanp->chan)
-		chanp->cs->status |=  0x2000;
-	else
-		chanp->cs->status |=  0x1000;
-
-	if (chanp->cs->card_ops->led_handler)
-		chanp->cs->card_ops->led_handler(chanp->cs);
-}
-
-static inline void
-mdl_info_release(struct Channel *chanp)
-{
-	if (chanp->chan)
-		chanp->cs->status &=  ~0x2200;
-	else
-		chanp->cs->status &=  ~0x1100;
-
-	if (chanp->cs->card_ops->led_handler)
-		chanp->cs->card_ops->led_handler(chanp->cs);
-}
-
-static void
 lli_close(struct FsmInst *fi)
 {
 	struct Channel *chanp = fi->userdata;
 
 	FsmChangeState(fi, ST_NULL);
 	chanp->Flags = 0;
-	mdl_info_release(chanp);
+	chanp->cs->cardmsg(chanp->cs, MDL_INFO_REL, (void *) (long)chanp->chan);
 }
 
 static void
@@ -259,8 +221,7 @@ lli_leased_in(struct FsmInst *fi, int ev
 
 	if (!chanp->leased)
 		return;
-
-	mdl_info_setup(chanp);
+	chanp->cs->cardmsg(chanp->cs, MDL_INFO_SETUP, (void *) (long)chanp->chan);
 	FsmChangeState(fi, ST_IN_WAIT_LL);
 	if (chanp->debug & 1)
 		link_debug(chanp, 0, "STAT_ICALL_LEASED");
@@ -277,11 +238,12 @@ lli_leased_in(struct FsmInst *fi, int ev
 	if (chanp->debug & 1)
 		link_debug(chanp, 1, "statcallb ret=%d", ret);
 	if (!ret) {
-		mdl_info_release(chanp);
+		chanp->cs->cardmsg(chanp->cs, MDL_INFO_REL, (void *) (long)chanp->chan);
 		FsmChangeState(fi, ST_NULL);
 	}
 }
 
+
 /*
  * Dial out
  */
@@ -295,7 +257,7 @@ lli_init_bchan_out(struct FsmInst *fi, i
 		link_debug(chanp, 0, "STAT_DCONN");
 	HL_LL(chanp, ISDN_STAT_DCONN);
 	init_b_st(chanp, 0);
-	L4L3(chanp->b_st, DL_ESTABLISH | REQUEST, NULL);
+	chanp->b_st->lli.l4l3(chanp->b_st, DL_ESTABLISH | REQUEST, NULL);
 }
 
 static void
@@ -307,12 +269,12 @@ lli_prep_dialout(struct FsmInst *fi, int
 	FsmDelTimer(&chanp->dial_timer, 73);
 	chanp->l2_active_protocol = chanp->l2_protocol;
 	chanp->incoming = 0;
-	mdl_info_setup(chanp);
+	chanp->cs->cardmsg(chanp->cs, MDL_INFO_SETUP, (void *) (long)chanp->chan);
 	if (chanp->leased) {
 		lli_init_bchan_out(fi, event, arg);
 	} else {
 		FsmChangeState(fi, ST_OUT_DIAL);
-		L4L3(chanp->d_st, CC_SETUP | REQUEST, chanp);
+		chanp->d_st->lli.l4l3(chanp->d_st, CC_SETUP | REQUEST, chanp);
 	}
 }
 
@@ -325,12 +287,12 @@ lli_resume(struct FsmInst *fi, int event
 	FsmDelTimer(&chanp->dial_timer, 73);
 	chanp->l2_active_protocol = chanp->l2_protocol;
 	chanp->incoming = 0;
-	mdl_info_setup(chanp);
+	chanp->cs->cardmsg(chanp->cs, MDL_INFO_SETUP, (void *) (long)chanp->chan);
 	if (chanp->leased) {
 		lli_init_bchan_out(fi, event, arg);
 	} else {
 		FsmChangeState(fi, ST_OUT_DIAL);
-		L4L3(chanp->d_st, CC_RESUME | REQUEST, chanp);
+		chanp->d_st->lli.l4l3(chanp->d_st, CC_RESUME | REQUEST, chanp);
 	}
 }
 
@@ -353,7 +315,7 @@ lli_go_active(struct FsmInst *fi, int ev
 	ic.command = ISDN_STAT_BCONN;
 	ic.arg = chanp->chan;
 	chanp->cs->iif.statcallb(&ic);
-	mdl_info_connect(chanp);
+	chanp->cs->cardmsg(chanp->cs, MDL_INFO_CONN, (void *) (long)chanp->chan);
 }
 
 
@@ -370,7 +332,7 @@ lli_deliver_call(struct FsmInst *fi, int
 	isdn_ctrl ic;
 	int ret;
 
-	mdl_info_setup(chanp);
+	chanp->cs->cardmsg(chanp->cs, MDL_INFO_SETUP, (void *) (long)chanp->chan);
 	/*
 	 * Report incoming calls only once to linklevel, use CallFlags
 	 * which is set to 3 with each broadcast message in isdnl1.c
@@ -397,34 +359,34 @@ lli_deliver_call(struct FsmInst *fi, int
 			case 1:	/* OK, someone likes this call */
 				FsmDelTimer(&chanp->drel_timer, 61);
 				FsmChangeState(fi, ST_IN_ALERT_SENT);
-				L4L3(chanp->d_st, CC_ALERTING | REQUEST, chanp->proc);
+				chanp->d_st->lli.l4l3(chanp->d_st, CC_ALERTING | REQUEST, chanp->proc);
 				break;
 			case 5: /* direct redirect */
 			case 4: /* Proceeding desired */
 				FsmDelTimer(&chanp->drel_timer, 61);
 				FsmChangeState(fi, ST_IN_PROCEED_SEND);
-				L4L3(chanp->d_st, CC_PROCEED_SEND | REQUEST, chanp->proc);
+				chanp->d_st->lli.l4l3(chanp->d_st, CC_PROCEED_SEND | REQUEST, chanp->proc);
 				if (ret == 5) {
 					memcpy(&chanp->setup, &ic.parm.setup, sizeof(setup_parm));
-					L4L3(chanp->d_st, CC_REDIR | REQUEST, chanp->proc);
+					chanp->d_st->lli.l4l3(chanp->d_st, CC_REDIR | REQUEST, chanp->proc);
 				}
 				break;
 			case 2:	/* Rejecting Call */
 				break;
 			case 3:	/* incomplete number */
 				FsmDelTimer(&chanp->drel_timer, 61);
-				L4L3(chanp->d_st, CC_MORE_INFO | REQUEST, chanp->proc);
+				chanp->d_st->lli.l4l3(chanp->d_st, CC_MORE_INFO | REQUEST, chanp->proc);
 				break;
 			case 0:	/* OK, nobody likes this call */
 			default:	/* statcallb problems */
-				L4L3(chanp->d_st, CC_IGNORE | REQUEST, chanp->proc);
-				mdl_info_release(chanp);
+				chanp->d_st->lli.l4l3(chanp->d_st, CC_IGNORE | REQUEST, chanp->proc);
+				chanp->cs->cardmsg(chanp->cs, MDL_INFO_REL, (void *) (long)chanp->chan);
 				FsmChangeState(fi, ST_NULL);
 				break;
 		}
 	} else {
-		L4L3(chanp->d_st, CC_IGNORE | REQUEST, chanp->proc);
-		mdl_info_release(chanp);
+		chanp->d_st->lli.l4l3(chanp->d_st, CC_IGNORE | REQUEST, chanp->proc);
+		chanp->cs->cardmsg(chanp->cs, MDL_INFO_REL, (void *) (long)chanp->chan);
 	}
 }
 
@@ -434,7 +396,7 @@ lli_send_dconnect(struct FsmInst *fi, in
 	struct Channel *chanp = fi->userdata;
 
 	FsmChangeState(fi, ST_IN_WAIT_CONN_ACK);
-	L4L3(chanp->d_st, CC_SETUP | RESPONSE, chanp->proc);
+	chanp->d_st->lli.l4l3(chanp->d_st, CC_SETUP | RESPONSE, chanp->proc);
 }
 
 static void
@@ -443,7 +405,7 @@ lli_send_alert(struct FsmInst *fi, int e
 	struct Channel *chanp = fi->userdata;
 
 	FsmChangeState(fi, ST_IN_ALERT_SENT);
-	L4L3(chanp->d_st, CC_ALERTING | REQUEST, chanp->proc);
+	chanp->d_st->lli.l4l3(chanp->d_st, CC_ALERTING | REQUEST, chanp->proc);
 }
 
 static void
@@ -451,7 +413,7 @@ lli_send_redir(struct FsmInst *fi, int e
 {
 	struct Channel *chanp = fi->userdata;
 
-	L4L3(chanp->d_st, CC_REDIR | REQUEST, chanp->proc);
+	chanp->d_st->lli.l4l3(chanp->d_st, CC_REDIR | REQUEST, chanp->proc);
 }
 
 static void
@@ -466,7 +428,7 @@ lli_init_bchan_in(struct FsmInst *fi, in
 	chanp->l2_active_protocol = chanp->l2_protocol;
 	chanp->incoming = !0;
 	init_b_st(chanp, !0);
-	L4L3(chanp->b_st, DL_ESTABLISH | REQUEST, NULL);
+	chanp->b_st->lli.l4l3(chanp->b_st, DL_ESTABLISH | REQUEST, NULL);
 }
 
 static void
@@ -479,9 +441,9 @@ lli_setup_rsp(struct FsmInst *fi, int ev
 	} else {
 		FsmChangeState(fi, ST_IN_WAIT_CONN_ACK);
 #ifdef WANT_ALERT
-		L4L3(chanp->d_st, CC_ALERTING | REQUEST, chanp->proc);
+		chanp->d_st->lli.l4l3(chanp->d_st, CC_ALERTING | REQUEST, chanp->proc);
 #endif
-		L4L3(chanp->d_st, CC_SETUP | RESPONSE, chanp->proc);
+		chanp->d_st->lli.l4l3(chanp->d_st, CC_SETUP | RESPONSE, chanp->proc);
 	}
 }
 
@@ -492,7 +454,7 @@ lli_suspend(struct FsmInst *fi, int even
 {
 	struct Channel *chanp = fi->userdata;
 
-	L4L3(chanp->d_st, CC_SUSPEND | REQUEST, chanp->proc);
+	chanp->d_st->lli.l4l3(chanp->d_st, CC_SUSPEND | REQUEST, chanp->proc);
 }
 
 /* Call clearing */
@@ -524,7 +486,8 @@ lli_disconnect_req(struct FsmInst *fi, i
 		FsmChangeState(fi, ST_WAIT_DRELEASE);
 		if (chanp->proc)
 			chanp->proc->para.cause = 0x10;	/* Normal Call Clearing */
-		L4L3(chanp->d_st, CC_DISCONNECT | REQUEST, chanp->proc);
+		chanp->d_st->lli.l4l3(chanp->d_st, CC_DISCONNECT | REQUEST,
+			chanp->proc);
 	}
 }
 
@@ -539,7 +502,8 @@ lli_disconnect_reject(struct FsmInst *fi
 		FsmChangeState(fi, ST_WAIT_DRELEASE);
 		if (chanp->proc)
 			chanp->proc->para.cause = 0x15;	/* Call Rejected */
-		L4L3(chanp->d_st, CC_DISCONNECT | REQUEST, chanp->proc);
+		chanp->d_st->lli.l4l3(chanp->d_st, CC_DISCONNECT | REQUEST,
+			chanp->proc);
 	}
 }
 
@@ -571,12 +535,12 @@ lli_reject_req(struct FsmInst *fi, int e
 #ifndef ALERT_REJECT
 	if (chanp->proc)
 		chanp->proc->para.cause = 0x15;	/* Call Rejected */
-	L4L3(chanp->d_st, CC_REJECT | REQUEST, chanp->proc);
+	chanp->d_st->lli.l4l3(chanp->d_st, CC_REJECT | REQUEST, chanp->proc);
 	lli_dhup_close(fi, event, arg);
 #else
 	FsmRestartTimer(&chanp->drel_timer, 40, EV_HANGUP, NULL, 63);
 	FsmChangeState(fi, ST_IN_ALERT_SENT);
-	L4L3(chanp->d_st, CC_ALERTING | REQUEST, chanp->proc);
+	chanp->d_st->lli.l4l3(chanp->d_st, CC_ALERTING | REQUEST, chanp->proc);
 #endif
 }
 
@@ -587,7 +551,7 @@ lli_disconn_bchan(struct FsmInst *fi, in
 
 	chanp->data_open = 0;
 	FsmChangeState(fi, ST_WAIT_BRELEASE);
-	L4L3(chanp->b_st, DL_RELEASE | REQUEST, NULL);
+	chanp->b_st->lli.l4l3(chanp->b_st, DL_RELEASE | REQUEST, NULL);
 }
 
 static void
@@ -642,7 +606,7 @@ lli_release_bchan(struct FsmInst *fi, in
 
 	chanp->data_open = 0;
 	FsmChangeState(fi, ST_WAIT_BREL_DISC);
-	L4L3(chanp->b_st, DL_RELEASE | REQUEST, NULL);
+	chanp->b_st->lli.l4l3(chanp->b_st, DL_RELEASE | REQUEST, NULL);
 }
 
 
@@ -672,7 +636,7 @@ lli_abort(struct FsmInst *fi, int event,
 	struct Channel *chanp = fi->userdata;
 
 	chanp->data_open = 0;
-	L4L3(chanp->b_st, DL_RELEASE | REQUEST, NULL);
+	chanp->b_st->lli.l4l3(chanp->b_st, DL_RELEASE | REQUEST, NULL);
 	lli_bhup_dhup(fi, event, arg);
 }
  
@@ -685,7 +649,8 @@ lli_release_req(struct FsmInst *fi, int 
 		lli_leased_hup(fi, chanp);
 	} else {
 		FsmChangeState(fi, ST_WAIT_D_REL_CNF);
-		L4L3(chanp->d_st, CC_RELEASE | REQUEST,	chanp->proc);
+		chanp->d_st->lli.l4l3(chanp->d_st, CC_RELEASE | REQUEST,
+			chanp->proc);
 	}
 }
 
@@ -767,7 +732,7 @@ lli_failure_l(struct FsmInst *fi, int ev
 	chanp->cs->iif.statcallb(&ic);
 	HL_LL(chanp, ISDN_STAT_DHUP);
 	chanp->Flags = 0;
-	mdl_info_release(chanp);
+	chanp->cs->cardmsg(chanp->cs, MDL_INFO_REL, (void *) (long)chanp->chan);
 }
 
 static void
@@ -796,7 +761,7 @@ lli_failure_a(struct FsmInst *fi, int ev
 	struct Channel *chanp = fi->userdata;
 
 	chanp->data_open = 0;
-	L4L3(chanp->b_st, DL_RELEASE | REQUEST, NULL);
+	chanp->b_st->lli.l4l3(chanp->b_st, DL_RELEASE | REQUEST, NULL);
 	lli_bhup_fail(fi, event, arg);
 }
 
@@ -890,11 +855,10 @@ CallcFree(void)
 static void
 release_b_st(struct Channel *chanp)
 {
-	struct IsdnCardState *cs = chanp->cs;
 	struct PStack *st = chanp->b_st;
 
 	if(test_and_clear_bit(FLG_START_B, &chanp->Flags)) {
-		cs->bc_l1_ops->close(chanp->bcs);
+		chanp->bcs->BC_Close(chanp->bcs);
 		switch (chanp->l2_active_protocol) {
 			case (ISDN_PROTO_L2_X75I):
 				releasestack_isdnl2(st);
@@ -954,7 +918,7 @@ static void stat_redir_result(struct Isd
 	ic.driver = cs->myid;
 	ic.command = ISDN_STAT_REDIR;
 	ic.arg = chan; 
-	(ulong)(ic.parm.num[0]) = result;
+	ic.parm.num[0] = result;
 	cs->iif.statcallb(&ic);
 } /* stat_redir_result */
 
@@ -971,7 +935,7 @@ dchan_l3l4(struct PStack *st, int pr, vo
 	if (pr == (CC_SETUP | INDICATION)) {
 		if (!(chanp = selectfreechannel(pc->st, pc->para.bchannel))) {
 			pc->para.cause = 0x11;	/* User busy */
-			L4L3(pc->st, CC_REJECT | REQUEST, pc);
+			pc->st->lli.l4l3(pc->st, CC_REJECT | REQUEST, pc);
 		} else {
 			chanp->proc = pc;
 			pc->chan = chanp;
@@ -1054,16 +1018,16 @@ init_PStack(struct PStack **stp) {
 	if (!*stp)
 		return -ENOMEM;
 	(*stp)->next = NULL;
+	(*stp)->l1.l1l2 = dummy_pstack;
 	(*stp)->l1.l1hw = dummy_pstack;
 	(*stp)->l1.l1tei = dummy_pstack;
-	(*stp)->l1.l2l1 = dummy_pstack;
-	(*stp)->l2.l1l2 = dummy_pstack;
 	(*stp)->l2.l2tei = dummy_pstack;
-	(*stp)->l2.l3l2 = dummy_pstack;
-	(*stp)->l3.l2l3 = dummy_pstack;
+	(*stp)->l2.l2l1 = dummy_pstack;
+	(*stp)->l2.l2l3 = dummy_pstack;
+	(*stp)->l3.l3l2 = dummy_pstack;
 	(*stp)->l3.l3ml3 = dummy_pstack;
-	(*stp)->l3.l4l3 = dummy_pstack;
-	(*stp)->lli.l3l4 = dummy_pstack;
+	(*stp)->l3.l3l4 = dummy_pstack;
+	(*stp)->lli.l4l3 = dummy_pstack;
 	(*stp)->ma.layer = dummy_pstack;
 	return 0;
 }
@@ -1101,7 +1065,7 @@ init_d_st(struct Channel *chanp)
 	setstack_isdnl2(st, tmp);
 	setstack_l3dc(st, chanp);
 	st->lli.userdata = chanp;
-	st->lli.l3l4 = dchan_l3l4;
+	st->l3.l3l4 = dchan_l3l4;
 
 	return 0;
 }
@@ -1175,7 +1139,8 @@ CallcNewChan(struct IsdnCardState *csta)
 	printk(KERN_INFO "HiSax: MAX_WAITING_CALLS added\n");
 	if (test_bit(FLG_PTP, &csta->channel->d_st->l2.flag)) {
 		printk(KERN_INFO "LAYER2 WATCHING ESTABLISH\n");
-		L4L3(csta->channel->d_st, DL_ESTABLISH | REQUEST, NULL);
+		csta->channel->d_st->lli.l4l3(csta->channel->d_st,
+			DL_ESTABLISH | REQUEST, NULL);
 	}
 	return (0);
 }
@@ -1209,7 +1174,7 @@ CallcFreeChan(struct IsdnCardState *csta
 			kfree(csta->channel[i].b_st);
 			csta->channel[i].b_st = NULL;
 		} else
-			printk(KERN_WARNING "CallcFreeChan b_st ch%d already freed\n", i);
+			printk(KERN_WARNING "CallcFreeChan b_st ch%d allready freed\n", i);
 		if (i || test_bit(FLG_TWO_DCHAN, &csta->HW_Flags)) {
 			release_d_st(csta->channel + i);
 		} else
@@ -1218,30 +1183,13 @@ CallcFreeChan(struct IsdnCardState *csta
 }
 
 static void
-ll_writewakeup(struct Channel *chanp, struct sk_buff *skb)
-{
-	isdn_ctrl ic;
-
-	if (skb->pkt_type != PACKET_NOACK) {
-		if (chanp->debug & 0x800)
-			link_debug(chanp, 0, "llwakeup: %d", skb->truesize);
-		ic.driver = chanp->cs->myid;
-		ic.command = ISDN_STAT_BSENT;
-		ic.arg = chanp->chan;
-		ic.parm.length = skb->truesize;
-		chanp->cs->iif.statcallb(&ic);
-	}
-	dev_kfree_skb(skb);
-}
-
-static void
 lldata_handler(struct PStack *st, int pr, void *arg)
 {
 	struct Channel *chanp = (struct Channel *) st->lli.userdata;
 	struct sk_buff *skb = arg;
 
 	switch (pr) {
-		case (DL_DATA | INDICATION):
+		case (DL_DATA  | INDICATION):
 			if (chanp->data_open) {
 				if (chanp->debug & 0x800)
 					link_debug(chanp, 0, "lldata: %d", skb->len);
@@ -1251,9 +1199,6 @@ lldata_handler(struct PStack *st, int pr
 				dev_kfree_skb(skb);
 			}
 			break;
-		case (DL_DATA | CONFIRM):
-			ll_writewakeup(chanp, skb);
-			break;
 		case (DL_ESTABLISH | INDICATION):
 		case (DL_ESTABLISH | CONFIRM):
 			FsmEvent(&chanp->fi, EV_BC_EST, NULL);
@@ -1286,9 +1231,6 @@ lltrans_handler(struct PStack *st, int p
 				dev_kfree_skb(skb);
 			}
 			break;
-		case (PH_DATA | CONFIRM):
-			ll_writewakeup(chanp, skb);
-			break;
 		case (PH_ACTIVATE | INDICATION):
 		case (PH_ACTIVATE | CONFIRM):
 			FsmEvent(&chanp->fi, EV_BC_EST, NULL);
@@ -1304,6 +1246,21 @@ lltrans_handler(struct PStack *st, int p
 	}
 }
 
+void
+lli_writewakeup(struct PStack *st, int len)
+{
+	struct Channel *chanp = st->lli.userdata;
+	isdn_ctrl ic;
+
+	if (chanp->debug & 0x800)
+		link_debug(chanp, 0, "llwakeup: %d", len);
+	ic.driver = chanp->cs->myid;
+	ic.command = ISDN_STAT_BSENT;
+	ic.arg = chanp->chan;
+	ic.parm.length = len;
+	chanp->cs->iif.statcallb(&ic);
+}
+
 static int
 init_b_st(struct Channel *chanp, int incoming)
 {
@@ -1335,7 +1292,7 @@ init_b_st(struct Channel *chanp, int inc
 			break;
 	}
 	chanp->bcs->conmsg = NULL;
-	if (cs->bc_l1_ops->open(st, chanp->bcs))
+	if (chanp->bcs->BC_SetStack(st, chanp->bcs))
 		return (-1);
 	st->l2.flag = 0;
 	test_and_set_bit(FLG_LAPB, &st->l2.flag);
@@ -1352,8 +1309,10 @@ init_b_st(struct Channel *chanp, int inc
 			sprintf(tmp, "Ch%d X.75", chanp->chan);
 			setstack_isdnl2(st, tmp);
 			setstack_l3bc(st, chanp);
-			st->l3.l2l3 = lldata_handler;
+			st->l2.l2l3 = lldata_handler;
 			st->lli.userdata = chanp;
+			test_and_clear_bit(FLG_LLI_L1WAKEUP, &st->lli.flag);
+			test_and_set_bit(FLG_LLI_L2WAKEUP, &st->lli.flag);
 			st->l2.l2m.debug = chanp->debug & 16;
 			st->l2.debug = chanp->debug & 64;
 			break;
@@ -1362,8 +1321,10 @@ init_b_st(struct Channel *chanp, int inc
 		case (ISDN_PROTO_L2_TRANS):
 		case (ISDN_PROTO_L2_MODEM):
 		case (ISDN_PROTO_L2_FAX):
-			st->l2.l1l2 = lltrans_handler;
+			st->l1.l1l2 = lltrans_handler;
 			st->lli.userdata = chanp;
+			test_and_set_bit(FLG_LLI_L1WAKEUP, &st->lli.flag);
+			test_and_clear_bit(FLG_LLI_L2WAKEUP, &st->lli.flag);
 			setstack_transl2(st);
 			setstack_l3bc(st, chanp);
 			break;
@@ -1384,7 +1345,7 @@ leased_l4l3(struct PStack *st, int pr, v
 			dev_kfree_skb(skb);
 			break;
 		case (DL_ESTABLISH | REQUEST):
-			L2L1(st, PH_ACTIVATE | REQUEST, NULL);
+			st->l2.l2l1(st, PH_ACTIVATE | REQUEST, NULL);
 			break;
 		case (DL_RELEASE | REQUEST):
 			break;
@@ -1462,7 +1423,7 @@ capi_debug(struct Channel *chanp, capi_m
 {
 	char *t = tmpbuf;
 
-	t += QuickHex(t, (u8 *)cm, (cm->Length>50)? 50: cm->Length);
+	t += QuickHex(t, (u_char *)cm, (cm->Length>50)? 50: cm->Length);
 	t--;
 	*t= 0;
 	HiSax_putstatus(chanp->cs, "Ch", "%d CAPIMSG %s", chanp->chan, tmpbuf);
@@ -1478,11 +1439,11 @@ lli_got_fac_req(struct Channel *chanp, c
 		return;
 	switch(cm->para[3]) {
 		case 4: /* Suspend */
-			strlcpy(chanp->setup.phone, &cm->para[5], cm->para[5] +1);
+			strncpy(chanp->setup.phone, &cm->para[5], cm->para[5] +1);
 			FsmEvent(&chanp->fi, EV_SUSPEND, cm);
 			break;
 		case 5: /* Resume */
-			strlcpy(chanp->setup.phone, &cm->para[5], cm->para[5] +1);
+			strncpy(chanp->setup.phone, &cm->para[5], cm->para[5] +1);
 			if (chanp->fi.state == ST_NULL) {
 				FsmEvent(&chanp->fi, EV_RESUME, cm);
 			} else {
@@ -1495,8 +1456,12 @@ lli_got_fac_req(struct Channel *chanp, c
 
 void
 lli_got_manufacturer(struct Channel *chanp, struct IsdnCardState *cs, capi_msg *cm) {
-	if (cs->card_ops->aux_ind)
-		cs->card_ops->aux_ind(cs, cm->para);
+	if ((cs->typ == ISDN_CTYPE_ELSA) || (cs->typ == ISDN_CTYPE_ELSA_PNP) ||
+		(cs->typ == ISDN_CTYPE_ELSA_PCI)) {
+		if (cs->hw.elsa.MFlag) {
+			cs->cardmsg(cs, CARD_AUX_IND, cm->para);
+		}
+	}
 }
 
 
@@ -1654,15 +1619,16 @@ HiSax_command(isdn_ctrl * ic)
 						HiSax_putstatus(csta, "Card",
 							"%d channel %d set leased mode\n",
 							csta->cardnr + 1, num + 1);
-						chanp->d_st->l2.l1l2 = leased_l1l2;
-						chanp->d_st->l3.l4l3 = leased_l4l3;
-						L4L3(chanp->d_st, DL_ESTABLISH | REQUEST, NULL);
+						chanp->d_st->l1.l1l2 = leased_l1l2;
+						chanp->d_st->lli.l4l3 = leased_l4l3;
+						chanp->d_st->lli.l4l3(chanp->d_st,
+							DL_ESTABLISH | REQUEST, NULL);
 					}
 					break;
 				case (6):	/* set B-channel test loop */
 					num = *(unsigned int *) ic->parm.num;
 					if (csta->stlist)
-						csta->stlist->l1.l2l1(csta->stlist,
+						csta->stlist->l2.l2l1(csta->stlist,
 							PH_TESTLOOP | REQUEST, (void *) (long)num);
 					break;
 				case (7):	/* set card in PTP mode */
@@ -1676,7 +1642,8 @@ HiSax_command(isdn_ctrl * ic)
 						HiSax_putstatus(csta, "set card ", "in PTP mode");
 						printk(KERN_DEBUG "HiSax: set card in PTP mode\n");
 						printk(KERN_INFO "LAYER2 WATCHING ESTABLISH\n");
-						L4L3(csta->channel[0].d_st, DL_ESTABLISH | REQUEST, NULL);
+						csta->channel[0].d_st->lli.l4l3(csta->channel[0].d_st,
+							DL_ESTABLISH | REQUEST, NULL);
 					} else {
 						test_and_clear_bit(FLG_PTP, &csta->channel[0].d_st->l2.flag);
 						test_and_clear_bit(FLG_FIXED_TEI, &csta->channel[0].d_st->l2.flag);
@@ -1700,7 +1667,8 @@ HiSax_command(isdn_ctrl * ic)
 						printk(KERN_DEBUG "HiSax: set card in FIXED TEI (%d) mode\n",
 							num);
 					}
-					L4L3(chanp->d_st, DL_ESTABLISH | REQUEST, NULL);
+					chanp->d_st->lli.l4l3(chanp->d_st,
+						DL_ESTABLISH | REQUEST, NULL);
 					break;
 				case (11):
 					num = csta->debug & DEB_DLOG_HEX;
@@ -1758,8 +1726,8 @@ HiSax_command(isdn_ctrl * ic)
 		/* protocol specific io commands */
 		case (ISDN_CMD_PROT_IO):
 			for (st = csta->stlist; st; st = st->next)
-				if ((u_int)st->protocol == (ic->arg & 0xFF))
-					return(st->l3.l4l3_proto(st, ic));
+				if (st->protocol == (ic->arg & 0xFF))
+					return(st->lli.l4l3_proto(st, ic));
 			return(-EINVAL);
 			break;
 		default:
@@ -1777,7 +1745,6 @@ HiSax_writebuf_skb(int id, int chan, int
 	struct Channel *chanp;
 	struct PStack *st;
 	int len = skb->len;
-	unsigned long flags;
 	struct sk_buff *nskb;
 
 	if (!csta) {
@@ -1807,22 +1774,20 @@ HiSax_writebuf_skb(int id, int chan, int
 			return 0;
 		} else if (chanp->debug & 0x800)
 			link_debug(chanp, 1, "writebuf %d/%d/%d", len, chanp->bcs->tx_cnt,MAX_DATA_MEM);
-		spin_lock_irqsave(&callc_lock, flags);
 		nskb = skb_clone(skb, GFP_ATOMIC);
 		if (nskb) {
 			nskb->truesize = nskb->len;
 			if (!ack)
 				nskb->pkt_type = PACKET_NOACK;
 			if (chanp->l2_active_protocol == ISDN_PROTO_L2_X75I)
-				L3L2(st, DL_DATA | REQUEST, nskb);
+				st->l3.l3l2(st, DL_DATA | REQUEST, nskb);
 			else {
 				chanp->bcs->tx_cnt += len;
-				st->l1.l2l1(st, PH_DATA | REQUEST, nskb);
+				st->l2.l2l1(st, PH_DATA | REQUEST, nskb);
 			}
 			dev_kfree_skb(skb);
 		} else
 			len = 0;
-		spin_unlock_irqrestore(&callc_lock, flags);
 	}
 	return (len);
 }
--- diff/drivers/isdn/hisax/config.c	2003-09-30 15:46:14.000000000 +0100
+++ source/drivers/isdn/hisax/config.c	2004-02-23 13:56:42.000000000 +0000
@@ -1,4 +1,4 @@
-/* $Id: config.c,v 1.1.4.2.2.1 2001/12/09 20:18:40 kai Exp $
+/* $Id: config.c,v 2.84.2.5 2004/02/11 13:21:33 keil Exp $
  *
  * Author       Karsten Keil
  * Copyright    by Karsten Keil      <keil@isdn4linux.de>
@@ -24,7 +24,6 @@
 #include <linux/kernel_stat.h>
 #include <linux/workqueue.h>
 #include <linux/interrupt.h>
-#include "isdnl1.h"
 #define HISAX_STATUS_BUFSIZE 4096
 #define INCLUDE_INLINE_FUNCS
 
@@ -99,14 +98,9 @@ const char *CardType[] = {
 	"Hotplug", "Formula-n enter:now PCI a/b", 
 };
 
-void HiSax_closecard(int cardnr);
-static spinlock_t hisax_config_lock = SPIN_LOCK_UNLOCKED;
-
 #ifdef CONFIG_HISAX_ELSA
 #define DEFAULT_CARD ISDN_CTYPE_ELSA
 #define DEFAULT_CFG {0,0,0,0}
-int elsa_init_pcmcia(void *, int, int *, int);
-EXPORT_SYMBOL(elsa_init_pcmcia);
 #endif
 
 #ifdef CONFIG_HISAX_AVM_A1
@@ -121,8 +115,6 @@ EXPORT_SYMBOL(elsa_init_pcmcia);
 #undef DEFAULT_CFG
 #define DEFAULT_CARD ISDN_CTYPE_A1_PCMCIA
 #define DEFAULT_CFG {11,0x170,0,0}
-int avm_a1_init_pcmcia(void *, int, int *, int);
-EXPORT_SYMBOL(avm_a1_init_pcmcia);
 #endif
 
 #ifdef CONFIG_HISAX_FRITZPCI
@@ -193,8 +185,6 @@ EXPORT_SYMBOL(avm_a1_init_pcmcia);
 #undef DEFAULT_CFG
 #define DEFAULT_CARD ISDN_CTYPE_SEDLBAUER
 #define DEFAULT_CFG {11,0x270,0,0}
-int sedl_init_pcmcia(void *, int, int *, int);
-EXPORT_SYMBOL(sedl_init_pcmcia);
 #endif
 
 #ifdef CONFIG_HISAX_SPORTSTER
@@ -237,8 +227,6 @@ EXPORT_SYMBOL(sedl_init_pcmcia);
 #undef DEFAULT_CFG
 #define DEFAULT_CARD ISDN_CTYPE_HFC_SX
 #define DEFAULT_CFG {5,0x2E0,0,0}
-int hfc_init_pcmcia(void *, int, int *, int);
-EXPORT_SYMBOL(hfc_init_pcmcia);
 #endif
 
 
@@ -330,10 +318,6 @@ EXPORT_SYMBOL(hfc_init_pcmcia);
 #define DEFAULT_CFG {0,0,0,0}
 #endif
 
-int hisax_init_pcmcia(void *, int *, struct IsdnCard *);
-EXPORT_SYMBOL(hisax_init_pcmcia);
-EXPORT_SYMBOL(HiSax_closecard);
-
 #define FIRST_CARD { \
 	DEFAULT_CARD, \
 	DEFAULT_PROTO, \
@@ -346,14 +330,14 @@ struct IsdnCard cards[HISAX_MAX_CARDS] =
 };
 
 #define HISAX_IDSIZE (HISAX_MAX_CARDS*8)
-static char HiSaxID[HISAX_IDSIZE] __devinitdata = { 0, };
+static char HiSaxID[HISAX_IDSIZE] = { 0, };
 
-char *HiSax_id __devinitdata = HiSaxID;
+char *HiSax_id = HiSaxID;
 #ifdef MODULE
 /* Variables for insmod */
-static int type[HISAX_MAX_CARDS] __devinitdata = { 0, };
-static int protocol[HISAX_MAX_CARDS] __devinitdata = { 0, };
-static int io[HISAX_MAX_CARDS] __devinitdata = { 0, };
+static int type[HISAX_MAX_CARDS] = { 0, };
+static int protocol[HISAX_MAX_CARDS] = { 0, };
+static int io[HISAX_MAX_CARDS] = { 0, };
 #undef IO0_IO1
 #ifdef CONFIG_HISAX_16_3
 #define IO0_IO1
@@ -368,7 +352,7 @@ static int io1[HISAX_MAX_CARDS] __devini
 #endif
 static int irq[HISAX_MAX_CARDS] __devinitdata = { 0, };
 static int mem[HISAX_MAX_CARDS] __devinitdata = { 0, };
-static char *id __devinitdata = HiSaxID;
+static char *id = HiSaxID;
 
 #define PARM_PARA "1-" __MODULE_STRING(HISAX_MAX_CARDS) "i"
 
@@ -430,7 +414,6 @@ void __init HiSaxVersion(void)
 	strcpy(tmp, lli_revision);
 	printk(KERN_INFO "HiSax: LinkLayer Revision %s\n",
 	       HiSax_getrev(tmp));
-	certification_check(1);
 }
 
 #ifndef MODULE
@@ -490,36 +473,125 @@ static int __init HiSax_setup(char *line
 __setup("hisax=", HiSax_setup);
 #endif /* MODULES */
 
+#if CARD_TELES0
 extern int setup_teles0(struct IsdnCard *card);
+#endif
+
+#if CARD_TELES3
 extern int setup_teles3(struct IsdnCard *card);
+#endif
+
+#if CARD_S0BOX
 extern int setup_s0box(struct IsdnCard *card);
+#endif
+
+#if CARD_TELESPCI
 extern int setup_telespci(struct IsdnCard *card);
+#endif
+
+#if CARD_AVM_A1
 extern int setup_avm_a1(struct IsdnCard *card);
+#endif
+
+#if CARD_AVM_A1_PCMCIA
 extern int setup_avm_a1_pcmcia(struct IsdnCard *card);
+#endif
+
+#if CARD_FRITZPCI
 extern int setup_avm_pcipnp(struct IsdnCard *card);
+#endif
+
+#if CARD_ELSA
 extern int setup_elsa(struct IsdnCard *card);
+#endif
+
+#if CARD_IX1MICROR2
 extern int setup_ix1micro(struct IsdnCard *card);
+#endif
+
+#if CARD_DIEHLDIVA
 extern int setup_diva(struct IsdnCard *card);
+#endif
+
+#if CARD_ASUSCOM
 extern int setup_asuscom(struct IsdnCard *card);
+#endif
+
+#if CARD_TELEINT
 extern int setup_TeleInt(struct IsdnCard *card);
+#endif
+
+#if CARD_SEDLBAUER
 extern int setup_sedlbauer(struct IsdnCard *card);
+#endif
+
+#if CARD_SPORTSTER
 extern int setup_sportster(struct IsdnCard *card);
+#endif
+
+#if CARD_MIC
 extern int setup_mic(struct IsdnCard *card);
+#endif
+
+#if CARD_NETJET_S
 extern int setup_netjet_s(struct IsdnCard *card);
+#endif
+
+#if CARD_HFCS
 extern int setup_hfcs(struct IsdnCard *card);
+#endif
+
+#if CARD_HFC_PCI
 extern int setup_hfcpci(struct IsdnCard *card);
+#endif
+
+#if CARD_HFC_SX
 extern int setup_hfcsx(struct IsdnCard *card);
+#endif
+
+#if CARD_AMD7930
 extern int setup_amd7930(struct IsdnCard *card);
+#endif
+
+#if CARD_NICCY
 extern int setup_niccy(struct IsdnCard *card);
+#endif
+
+#if CARD_ISURF
 extern int setup_isurf(struct IsdnCard *card);
+#endif
+
+#if CARD_HSTSAPHIR
 extern int setup_saphir(struct IsdnCard *card);
+#endif
+
+#if CARD_TESTEMU
 extern int setup_testemu(struct IsdnCard *card);
+#endif
+
+#if CARD_BKM_A4T
 extern int setup_bkm_a4t(struct IsdnCard *card);
+#endif
+
+#if CARD_SCT_QUADRO
 extern int setup_sct_quadro(struct IsdnCard *card);
+#endif
+
+#if CARD_GAZEL
 extern int setup_gazel(struct IsdnCard *card);
+#endif
+
+#if CARD_W6692
 extern int setup_w6692(struct IsdnCard *card);
+#endif
+
+#if CARD_NETJET_U
 extern int setup_netjet_u(struct IsdnCard *card);
+#endif
+
+#if CARD_FN_ENTERNOW_PCI
 extern int setup_enternow_pci(struct IsdnCard *card);
+#endif
 
 /*
  * Find card with given driverId
@@ -546,10 +618,10 @@ struct IsdnCardState *hisax_get_card(int
 	return NULL;
 }
 
-int HiSax_readstatus(u8 * buf, int len, int user, int id, int channel)
+int HiSax_readstatus(u_char * buf, int len, int user, int id, int channel)
 {
 	int count, cnt;
-	u8 *p = buf;
+	u_char *p = buf;
 	struct IsdnCardState *cs = hisax_findcard(id);
 
 	if (cs) {
@@ -561,10 +633,9 @@ int HiSax_readstatus(u8 * buf, int len, 
 		count = cs->status_end - cs->status_read + 1;
 		if (count >= len)
 			count = len;
-		if (user) {
-			if (copy_to_user(p, cs->status_read, count))
-				return -EFAULT;
-		} else
+		if (user)
+			copy_to_user(p, cs->status_read, count);
+		else
 			memcpy(p, cs->status_read, count);
 		cs->status_read += count;
 		if (cs->status_read > cs->status_end)
@@ -576,10 +647,9 @@ int HiSax_readstatus(u8 * buf, int len, 
 				cnt = HISAX_STATUS_BUFSIZE;
 			else
 				cnt = count;
-			if (user) {
-				if (copy_to_user(p, cs->status_read, cnt))
-					return -EFAULT;
-			} else
+			if (user)
+				copy_to_user(p, cs->status_read, cnt);
+			else
 				memcpy(p, cs->status_read, cnt);
 			p += cnt;
 			cs->status_read += cnt % HISAX_STATUS_BUFSIZE;
@@ -614,20 +684,24 @@ int jiftime(char *s, long mark)
 	return 8;
 }
 
-static char tmpbuf[HISAX_STATUS_BUFSIZE];
+static u_char tmpbuf[HISAX_STATUS_BUFSIZE];
 
-void VHiSax_putstatus(struct IsdnCardState *cs, char *head, const char *fmt,
+void VHiSax_putstatus(struct IsdnCardState *cs, char *head, char *fmt,
 		      va_list args)
 {
 	/* if head == NULL the fmt contains the full info */
 
-	unsigned long flags;
-	int count, i;
-	char *p;
-	isdn_ctrl ic;
-	int len;
+	u_long		flags;
+	int		count, i;
+	u_char		*p;
+	isdn_ctrl	ic;
+	int		len;
 
-	spin_lock_irqsave(&hisax_config_lock, flags);
+	if (!cs) {
+		printk(KERN_WARNING "HiSax: No CardStatus for message");
+		return;
+	}
+	spin_lock_irqsave(&cs->statlock, flags);
 	p = tmpbuf;
 	if (head) {
 		p += jiftime(p, jiffies);
@@ -638,19 +712,13 @@ void VHiSax_putstatus(struct IsdnCardSta
 		len = p - tmpbuf;
 		p = tmpbuf;
 	} else {
-		p = (char *) fmt;
+		p = fmt;
 		len = strlen(fmt);
 	}
-	if (!cs) {
-		printk(KERN_WARNING "HiSax: No CardStatus for message %s",
-		       p);
-		spin_unlock_irqrestore(&hisax_config_lock, flags);
-		return;
-	}
 	if (len > HISAX_STATUS_BUFSIZE) {
+		spin_unlock_irqrestore(&cs->statlock, flags);
 		printk(KERN_WARNING "HiSax: status overflow %d/%d\n",
 		       len, HISAX_STATUS_BUFSIZE);
-		spin_unlock_irqrestore(&hisax_config_lock, flags);
 		return;
 	}
 	count = len;
@@ -679,7 +747,7 @@ void VHiSax_putstatus(struct IsdnCardSta
 		count++;
 	}
 #endif
-	spin_unlock_irqrestore(&hisax_config_lock, flags);
+	spin_unlock_irqrestore(&cs->statlock, flags);
 	if (count) {
 		ic.command = ISDN_STAT_STAVAIL;
 		ic.driver = cs->myid;
@@ -725,15 +793,22 @@ static void ll_unload(struct IsdnCardSta
 	ic.command = ISDN_STAT_UNLOAD;
 	ic.driver = cs->myid;
 	cs->iif.statcallb(&ic);
+	if (cs->status_buf)
+		kfree(cs->status_buf);
+	cs->status_read = NULL;
+	cs->status_write = NULL;
+	cs->status_end = NULL;
+	kfree(cs->dlog);
+	cs->dlog = NULL;
 }
 
 static void closecard(int cardnr)
 {
 	struct IsdnCardState *csta = cards[cardnr].cs;
 
-	if (csta->bc_l1_ops->close) {
-		csta->bc_l1_ops->close(csta->bcs + 1);
-		csta->bc_l1_ops->close(csta->bcs);
+	if (csta->bcs->BC_Close != NULL) {
+		csta->bcs->BC_Close(csta->bcs + 1);
+		csta->bcs->BC_Close(csta->bcs);
 	}
 
 	skb_queue_purge(&csta->rq);
@@ -746,32 +821,34 @@ static void closecard(int cardnr)
 		dev_kfree_skb(csta->tx_skb);
 		csta->tx_skb = NULL;
 	}
-	if (csta->dc_l1_ops->close)
-		csta->dc_l1_ops->close(csta);
-
-	if (csta->card_ops->release)
-		csta->card_ops->release(csta);
+	if (csta->DC_Close != NULL) {
+		csta->DC_Close(csta);
+	}
+	if (csta->cardmsg)
+		csta->cardmsg(csta, CARD_RELEASE, NULL);
 	if (csta->dbusytimer.function != NULL) // FIXME?
 		del_timer(&csta->dbusytimer);
 	ll_unload(csta);
 }
 
-static int __devinit init_card(struct IsdnCardState *cs)
+static int init_card(struct IsdnCardState *cs)
 {
-	int irq_cnt, cnt = 3;
-
-	cs->card_ops->init(cs);
+	int 	irq_cnt, cnt = 3, ret;
 
+	if (!cs->irq) {
+		ret = cs->cardmsg(cs, CARD_INIT, NULL);
+		return(ret);
+	}
 	irq_cnt = kstat_irqs(cs->irq);
 	printk(KERN_INFO "%s: IRQ %d count %d\n", CardType[cs->typ],
 	       cs->irq, irq_cnt);
-	if (request_irq(cs->irq, cs->card_ops->irq_func, cs->irq_flags, "HiSax", cs)) {
+	if (request_irq(cs->irq, cs->irq_func, cs->irq_flags, "HiSax", cs)) {
 		printk(KERN_WARNING "HiSax: couldn't get interrupt %d\n",
 		       cs->irq);
 		return 1;
 	}
 	while (cnt) {
-		cs->card_ops->init(cs);
+		cs->cardmsg(cs, CARD_INIT, NULL);
 		set_current_state(TASK_UNINTERRUPTIBLE);
 		/* Timeout 10ms */
 		schedule_timeout((10 * HZ) / 1000);
@@ -785,86 +862,74 @@ static int __devinit init_card(struct Is
 				free_irq(cs->irq, cs);
 				return 2;
 			} else {
-				if (cs->card_ops->reset)
-					cs->card_ops->reset(cs);
+				cs->cardmsg(cs, CARD_RESET, NULL);
 				cnt--;
 			}
 		} else {
-			if (cs->card_ops->test)
-				cs->card_ops->test(cs);
+			cs->cardmsg(cs, CARD_TEST, NULL);
 			return 0;
 		}
 	}
 	return 3;
 }
 
-static struct IsdnCardState *
-alloc_IsdnCardState(void)
+static int checkcard(int cardnr, char *id, int *busy_flag, struct module *lockowner)
 {
+	int ret = 0;
+	struct IsdnCard *card = cards + cardnr;
 	struct IsdnCardState *cs;
 
-	cs = kmalloc(sizeof(*cs), GFP_ATOMIC); // FIXME
-	if (!cs)
-		goto err;
-
-	memset(cs, 0, sizeof(*cs));
-
-	cs->dlog = kmalloc(MAX_DLOG_SPACE, GFP_ATOMIC);
-	if (!cs->dlog)
-		goto err_cs;
-
-	cs->status_buf = kmalloc(HISAX_STATUS_BUFSIZE, GFP_ATOMIC);
-	if (!cs->status_buf)
-		goto err_dlog;
-
-	cs->rcvbuf = kmalloc(MAX_DFRAME_LEN_L1, GFP_ATOMIC);
-	if (!cs->rcvbuf)
-		goto err_status_buf;
-
+	cs = kmalloc(sizeof(struct IsdnCardState), GFP_ATOMIC);
+	if (!cs) {
+		printk(KERN_WARNING
+		       "HiSax: No memory for IsdnCardState(card %d)\n",
+		       cardnr + 1);
+		goto out;
+	}
+	memset(cs, 0, sizeof(struct IsdnCardState));
+	card->cs = cs;
+	spin_lock_init(&cs->statlock);
+	spin_lock_init(&cs->lock);
 	cs->chanlimit = 2;	/* maximum B-channel number */
+	cs->logecho = 0;	/* No echo logging */
+	cs->cardnr = cardnr;
 	cs->debug = L1_DEB_WARN;
+	cs->HW_Flags = 0;
+	cs->busy_flag = busy_flag;
 	cs->irq_flags = I4L_IRQ_FLAG;
+#if TEI_PER_CARD
+	if (card->protocol == ISDN_PTYPE_NI1)
+		test_and_set_bit(FLG_TWO_DCHAN, &cs->HW_Flags);
+#else
+	test_and_set_bit(FLG_TWO_DCHAN, &cs->HW_Flags);
+#endif
+	cs->protocol = card->protocol;
+
+	if (card->typ <= 0 || card->typ > ISDN_CTYPE_COUNT) {
+		printk(KERN_WARNING
+		       "HiSax: Card Type %d out of range\n", card->typ);
+		goto outf_cs;
+	}
+	if (!(cs->dlog = kmalloc(MAX_DLOG_SPACE, GFP_ATOMIC))) {
+		printk(KERN_WARNING
+		       "HiSax: No memory for dlog(card %d)\n", cardnr + 1);
+		goto outf_cs;
+	}
+	if (!(cs->status_buf = kmalloc(HISAX_STATUS_BUFSIZE, GFP_ATOMIC))) {
+		printk(KERN_WARNING
+		       "HiSax: No memory for status_buf(card %d)\n",
+		       cardnr + 1);
+		goto outf_dlog;
+	}
 	cs->stlist = NULL;
 	cs->status_read = cs->status_buf;
 	cs->status_write = cs->status_buf;
 	cs->status_end = cs->status_buf + HISAX_STATUS_BUFSIZE - 1;
-	cs->rcvidx = 0;
-	cs->tx_skb = NULL;
-	cs->tx_cnt = 0;
-	cs->event = 0;
-
-	skb_queue_head_init(&cs->rq);
-	skb_queue_head_init(&cs->sq);
-
-	spin_lock_init(&cs->lock);
-	resources_init(&cs->rs);
-	return cs;
-
- err_status_buf:
-	kfree(cs->status_buf);
- err_dlog:
-	kfree(cs->dlog);
- err_cs:
-	kfree(cs);
- err:
-	return NULL;
-}
-
-static void
-free_IsdnCardState(struct IsdnCardState *cs)
-{
-	kfree(cs->rcvbuf);
-	kfree(cs->status_buf);
-	kfree(cs->dlog);
-	kfree(cs);
-}
-
-static void
-do_register_isdn(struct IsdnCardState *cs)
-{
-	if (!cs->iif.owner)
-		cs->iif.owner = THIS_MODULE;
-
+	cs->typ = card->typ;
+#ifdef MODULE
+	cs->iif.owner = lockowner;
+#endif
+	strcpy(cs->iif.id, id);
 	cs->iif.channels = 2;
 	cs->iif.maxbufsize = MAX_DATA_SIZE;
 	cs->iif.hl_hdrlen = MAX_HEADER_LEN;
@@ -892,72 +957,20 @@ do_register_isdn(struct IsdnCardState *c
 	register_isdn(&cs->iif);
 	cs->myid = cs->iif.channels;
 	printk(KERN_INFO
-	       "HiSax: Card %d Protocol %s Id=%s (%d)\n", cs->cardnr + 1,
-	       (cs->protocol == ISDN_PTYPE_1TR6) ? "1TR6" :
-	       (cs->protocol == ISDN_PTYPE_EURO) ? "EDSS1" :
-	       (cs->protocol == ISDN_PTYPE_LEASED) ? "LEASED" :
-	       (cs->protocol == ISDN_PTYPE_NI1) ? "NI1" :
+	       "HiSax: Card %d Protocol %s Id=%s (%d)\n", cardnr + 1,
+	       (card->protocol == ISDN_PTYPE_1TR6) ? "1TR6" :
+	       (card->protocol == ISDN_PTYPE_EURO) ? "EDSS1" :
+	       (card->protocol == ISDN_PTYPE_LEASED) ? "LEASED" :
+	       (card->protocol == ISDN_PTYPE_NI1) ? "NI1" :
 	       "NONE", cs->iif.id, cs->myid);
-}
-
-static int
-do_init(struct IsdnCardState *cs)
-{
-	int ret;
-	
-	init_tei(cs, cs->protocol);
-	ret = CallcNewChan(cs);
-	if (ret)
-		return -EIO;
-	
-	/* ISAR needs firmware download first */
-	if (!test_bit(HW_ISAR, &cs->HW_Flags))
-		ll_run(cs, 0);
-	
-	return 0;
-}
-
-
-static int __devinit checkcard(int cardnr, char *id, int *busy_flag)
-{
-	int ret = 0;
-	struct IsdnCard *card = cards + cardnr;
-	struct IsdnCardState *cs;
-
-	cs = alloc_IsdnCardState();
-	if (!cs) {
-		printk(KERN_WARNING
-		       "HiSax: No memory for IsdnCardState(card %d)\n",
-		       cardnr + 1);
-		goto out;
-	}
-	card->cs = cs;
-#if TEI_PER_CARD
-	if (card->protocol == ISDN_PTYPE_NI1)
-		test_and_set_bit(FLG_TWO_DCHAN, &cs->HW_Flags);
-#else
-	test_and_set_bit(FLG_TWO_DCHAN, &cs->HW_Flags);
-#endif
-	cs->cardnr = cardnr;
-	cs->protocol = card->protocol;
-	cs->typ = card->typ;
-	cs->busy_flag = busy_flag;
-
-	if (card->typ <= 0 || card->typ > ISDN_CTYPE_COUNT) {
-		printk(KERN_WARNING
-		       "HiSax: Card Type %d out of range\n", card->typ);
-		goto outf_cs;
-	}
-	strcpy(cs->iif.id, id);
-	do_register_isdn(cs);
 	switch (card->typ) {
-#ifdef CONFIG_HISAX_16_0
+#if CARD_TELES0
 	case ISDN_CTYPE_16_0:
 	case ISDN_CTYPE_8_0:
 		ret = setup_teles0(card);
 		break;
 #endif
-#ifdef CONFIG_HISAX_16_3
+#if CARD_TELES3
 	case ISDN_CTYPE_16_3:
 	case ISDN_CTYPE_PNP:
 	case ISDN_CTYPE_TELESPCMCIA:
@@ -965,32 +978,32 @@ static int __devinit checkcard(int cardn
 		ret = setup_teles3(card);
 		break;
 #endif
-#ifdef CONFIG_HISAX_S0BOX
+#if CARD_S0BOX
 	case ISDN_CTYPE_S0BOX:
 		ret = setup_s0box(card);
 		break;
 #endif
-#ifdef CONFIG_HISAX_TELESPCI
+#if CARD_TELESPCI
 	case ISDN_CTYPE_TELESPCI:
 		ret = setup_telespci(card);
 		break;
 #endif
-#ifdef CONFIG_HISAX_AVM_A1
+#if CARD_AVM_A1
 	case ISDN_CTYPE_A1:
 		ret = setup_avm_a1(card);
 		break;
 #endif
-#ifdef CONFIG_HISAX_AVM_A1_PCMCIA
+#if CARD_AVM_A1_PCMCIA
 	case ISDN_CTYPE_A1_PCMCIA:
 		ret = setup_avm_a1_pcmcia(card);
 		break;
 #endif
-#ifdef CONFIG_HISAX_FRITZPCI
+#if CARD_FRITZPCI
 	case ISDN_CTYPE_FRITZPCI:
 		ret = setup_avm_pcipnp(card);
 		break;
 #endif
-#ifdef CONFIG_HISAX_ELSA
+#if CARD_ELSA
 	case ISDN_CTYPE_ELSA:
 	case ISDN_CTYPE_ELSA_PNP:
 	case ISDN_CTYPE_ELSA_PCMCIA:
@@ -998,115 +1011,115 @@ static int __devinit checkcard(int cardn
 		ret = setup_elsa(card);
 		break;
 #endif
-#ifdef CONFIG_HISAX_IX1MICROR2
+#if CARD_IX1MICROR2
 	case ISDN_CTYPE_IX1MICROR2:
 		ret = setup_ix1micro(card);
 		break;
 #endif
-#ifdef CONFIG_HISAX_DIEHLDIVA
+#if CARD_DIEHLDIVA
 	case ISDN_CTYPE_DIEHLDIVA:
 		ret = setup_diva(card);
 		break;
 #endif
-#ifdef CONFIG_HISAX_ASUSCOM
+#if CARD_ASUSCOM
 	case ISDN_CTYPE_ASUSCOM:
 		ret = setup_asuscom(card);
 		break;
 #endif
-#ifdef CONFIG_HISAX_TELEINT
+#if CARD_TELEINT
 	case ISDN_CTYPE_TELEINT:
 		ret = setup_TeleInt(card);
 		break;
 #endif
-#ifdef CONFIG_HISAX_SEDLBAUER
+#if CARD_SEDLBAUER
 	case ISDN_CTYPE_SEDLBAUER:
 	case ISDN_CTYPE_SEDLBAUER_PCMCIA:
 	case ISDN_CTYPE_SEDLBAUER_FAX:
 		ret = setup_sedlbauer(card);
 		break;
 #endif
-#ifdef CONFIG_HISAX_SPORTSTER
+#if CARD_SPORTSTER
 	case ISDN_CTYPE_SPORTSTER:
 		ret = setup_sportster(card);
 		break;
 #endif
-#ifdef CONFIG_HISAX_MIC
+#if CARD_MIC
 	case ISDN_CTYPE_MIC:
 		ret = setup_mic(card);
 		break;
 #endif
-#ifdef CONFIG_HISAX_NETJET
+#if CARD_NETJET_S
 	case ISDN_CTYPE_NETJET_S:
 		ret = setup_netjet_s(card);
 		break;
 #endif
-#ifdef CONFIG_HISAX_HFCS
+#if CARD_HFCS
 	case ISDN_CTYPE_TELES3C:
 	case ISDN_CTYPE_ACERP10:
 		ret = setup_hfcs(card);
 		break;
 #endif
-#ifdef CONFIG_HISAX_HFC_PCI
+#if CARD_HFC_PCI
 	case ISDN_CTYPE_HFC_PCI:
 		ret = setup_hfcpci(card);
 		break;
 #endif
-#ifdef CONFIG_HISAX_HFC_SX
+#if CARD_HFC_SX
 	case ISDN_CTYPE_HFC_SX:
 		ret = setup_hfcsx(card);
 		break;
 #endif
-#ifdef CONFIG_HISAX_NICCY
+#if CARD_NICCY
 	case ISDN_CTYPE_NICCY:
 		ret = setup_niccy(card);
 		break;
 #endif
-#ifdef CONFIG_HISAX_AMD7930
+#if CARD_AMD7930
 	case ISDN_CTYPE_AMD7930:
 		ret = setup_amd7930(card);
 		break;
 #endif
-#ifdef CONFIG_HISAX_ISURF
+#if CARD_ISURF
 	case ISDN_CTYPE_ISURF:
 		ret = setup_isurf(card);
 		break;
 #endif
-#ifdef CONFIG_HISAX_HSTSAPHIR
+#if CARD_HSTSAPHIR
 	case ISDN_CTYPE_HSTSAPHIR:
 		ret = setup_saphir(card);
 		break;
 #endif
-#ifdef CONFIG_HISAX_TESTEMU
+#if CARD_TESTEMU
 	case ISDN_CTYPE_TESTEMU:
 		ret = setup_testemu(card);
 		break;
 #endif
-#ifdef CONFIG_HISAX_BKM_A4T
+#if	CARD_BKM_A4T
 	case ISDN_CTYPE_BKM_A4T:
 		ret = setup_bkm_a4t(card);
 		break;
 #endif
-#ifdef CONFIG_HISAX_SCT_QUADRO
+#if	CARD_SCT_QUADRO
 	case ISDN_CTYPE_SCT_QUADRO:
 		ret = setup_sct_quadro(card);
 		break;
 #endif
-#ifdef CONFIG_HISAX_GAZEL
+#if CARD_GAZEL
 	case ISDN_CTYPE_GAZEL:
 		ret = setup_gazel(card);
 		break;
 #endif
-#ifdef CONFIG_HISAX_W6692
+#if CARD_W6692
 	case ISDN_CTYPE_W6692:
 		ret = setup_w6692(card);
 		break;
 #endif
-#ifdef CONFIG_HISAX_NETJET_U
+#if CARD_NETJET_U
 	case ISDN_CTYPE_NETJET_U:
 		ret = setup_netjet_u(card);
 		break;
 #endif
-#ifdef CONFIG_HISAX_ENTERNOW_PCI
+#if CARD_FN_ENTERNOW_PCI
 	case ISDN_CTYPE_ENTERNOW:
 		ret = setup_enternow_pci(card);
 		break;
@@ -1125,40 +1138,62 @@ static int __devinit checkcard(int cardn
 		ll_unload(cs);
 		goto outf_cs;
 	}
+	if (!(cs->rcvbuf = kmalloc(MAX_DFRAME_LEN_L1, GFP_ATOMIC))) {
+		printk(KERN_WARNING "HiSax: No memory for isac rcvbuf\n");
+		ll_unload(cs);
+		goto outf_cs;
+	}
+	cs->rcvidx = 0;
+	cs->tx_skb = NULL;
+	cs->tx_cnt = 0;
+	cs->event = 0;
+	cs->tqueue.data = cs;
+
+	skb_queue_head_init(&cs->rq);
+	skb_queue_head_init(&cs->sq);
+
 	init_bcstate(cs, 0);
 	init_bcstate(cs, 1);
 
 	/* init_card only handles interrupts which are not */
 	/* used here for the loadable driver */
 	switch (card->typ) {
-	case ISDN_CTYPE_DYNAMIC:
-		ret = 0;
-		break;
-	default:
-		ret = init_card(cs);
-		break;
+		case ISDN_CTYPE_DYNAMIC:
+			ret = 0;
+			break;
+		default:
+			ret = init_card(cs);
+			break;
 	}
 	if (ret) {
 		closecard(cardnr);
 		ret = 0;
 		goto outf_cs;
 	}
-	if (do_init(cs)) {
+	init_tei(cs, cs->protocol);
+	ret = CallcNewChan(cs);
+	if (ret) {
 		closecard(cardnr);
 		ret = 0;
 		goto outf_cs;
 	}
+	/* ISAR needs firmware download first */
+	if (!test_bit(HW_ISAR, &cs->HW_Flags))
+		ll_run(cs, 0);
+
 	ret = 1;
 	goto out;
 
+ outf_dlog:
+	kfree(cs->dlog);
  outf_cs:
-	free_IsdnCardState(cs);
+	kfree(cs);
 	card->cs = NULL;
  out:
 	return ret;
 }
 
-void __devinit HiSax_shiftcards(int idx)
+void HiSax_shiftcards(int idx)
 {
 	int i;
 
@@ -1166,7 +1201,7 @@ void __devinit HiSax_shiftcards(int idx)
 		memcpy(&cards[i], &cards[i + 1], sizeof(cards[i]));
 }
 
-int __devinit HiSax_inithardware(int *busy_flag)
+int HiSax_inithardware(int *busy_flag)
 {
 	int foundcards = 0;
 	int i = 0;
@@ -1196,13 +1231,16 @@ int __devinit HiSax_inithardware(int *bu
 			else
 				sprintf(ids, "%s%d", id, i);
 		}
-		if (checkcard(i, ids, busy_flag)) {
+		if (checkcard(i, ids, busy_flag, THIS_MODULE)) {
 			foundcards++;
 			i++;
 		} else {
-			printk(KERN_WARNING
-			       "HiSax: Card type %d not installed !\n",
-			       cards[i].typ);
+			/* make sure we don't oops the module */
+			if (cards[i].typ > 0 && cards[i].typ <= ISDN_CTYPE_COUNT) {
+				printk(KERN_WARNING
+			       		"HiSax: Card %s not installed !\n",
+			       		CardType[cards[i].typ]);
+			}
 			HiSax_shiftcards(i);
 			nrcards--;
 		}
@@ -1214,7 +1252,7 @@ void HiSax_closecard(int cardnr)
 {
 	int i, last = nrcards - 1;
 
-	if (cardnr > last)
+	if (cardnr > last || cardnr < 0)
 		return;
 	if (cards[cardnr].cs) {
 		ll_stop(cards[cardnr].cs);
@@ -1492,182 +1530,9 @@ static void __exit HiSax_exit(void)
 	printk(KERN_INFO "HiSax module removed\n");
 }
 
-#ifdef CONFIG_HISAX_ELSA
-int elsa_init_pcmcia(void *pcm_iob, int pcm_irq, int *busy_flag, int prot)
-{
-#ifdef MODULE
-	int i;
-
-	nrcards = 0;
-	/* Initialize all structs, even though we only accept
-	   two pcmcia cards
-	*/
-	for (i = 0; i < HISAX_MAX_CARDS; i++) {
-		cards[i].para[0] = irq[i];
-		cards[i].para[1] = io[i];
-		cards[i].typ = type[i];
-		if (protocol[i]) {
-			cards[i].protocol = protocol[i];
-		} else {
-			cards[i].protocol = DEFAULT_PROTO;
-		}
-	}
-	cards[0].para[0] = pcm_irq;
-	cards[0].para[1] = (int) pcm_iob;
-	cards[0].protocol = prot;
-	cards[0].typ = ISDN_CTYPE_ELSA_PCMCIA;
-
-	if (!HiSax_id)
-		HiSax_id = HiSaxID;
-	if (!HiSaxID[0])
-		strcpy(HiSaxID, "HiSax");
-	for (i = 0; i < HISAX_MAX_CARDS; i++)
-		if (cards[i].typ > 0)
-			nrcards++;
-	printk(KERN_DEBUG "HiSax: Total %d card%s defined\n",
-	       nrcards, (nrcards > 1) ? "s" : "");
-
-	if (!HiSax_inithardware(busy_flag))
-		return -ENODEV;
-	printk(KERN_NOTICE "HiSax: module installed\n");
-#endif
-	return 0;
-}
-#endif
-
-#ifdef CONFIG_HISAX_HFC_SX
-int hfc_init_pcmcia(void *pcm_iob, int pcm_irq, int *busy_flag, int prot)
-{
-#ifdef MODULE
-	int i;
-
-	nrcards = 0;
-	/* Initialize all structs, even though we only accept
-	   two pcmcia cards
-	*/
-	for (i = 0; i < HISAX_MAX_CARDS; i++) {
-		cards[i].para[0] = irq[i];
-		cards[i].para[1] = io[i];
-		cards[i].typ = type[i];
-		if (protocol[i]) {
-			cards[i].protocol = protocol[i];
-		} else {
-			cards[i].protocol = DEFAULT_PROTO;
-		}
-	}
-	cards[0].para[0] = pcm_irq;
-	cards[0].para[1] = (int) pcm_iob;
-	cards[0].protocol = prot;
-	cards[0].typ = ISDN_CTYPE_HFC_SP_PCMCIA;
-
-	if (!HiSax_id)
-		HiSax_id = HiSaxID;
-	if (!HiSaxID[0])
-		strcpy(HiSaxID, "HiSax");
-	for (i = 0; i < HISAX_MAX_CARDS; i++)
-		if (cards[i].typ > 0)
-			nrcards++;
-	printk(KERN_DEBUG "HiSax: Total %d card%s defined\n",
-	       nrcards, (nrcards > 1) ? "s" : "");
-
-	if (!HiSax_inithardware(busy_flag))
-		return -ENODEV;
-	printk(KERN_NOTICE "HiSax: module installed\n");
-#endif
-	return 0;
-}
-#endif
-
-#ifdef CONFIG_HISAX_SEDLBAUER
-int sedl_init_pcmcia(void *pcm_iob, int pcm_irq, int *busy_flag, int prot)
+int hisax_init_pcmcia(void *pcm_iob, int *busy_flag, struct IsdnCard *card)
 {
-#ifdef MODULE
-	int i;
-
-	nrcards = 0;
-	/* Initialize all structs, even though we only accept
-	   two pcmcia cards
-	*/
-	for (i = 0; i < HISAX_MAX_CARDS; i++) {
-		cards[i].para[0] = irq[i];
-		cards[i].para[1] = io[i];
-		cards[i].typ = type[i];
-		if (protocol[i]) {
-			cards[i].protocol = protocol[i];
-		} else {
-			cards[i].protocol = DEFAULT_PROTO;
-		}
-	}
-	cards[0].para[0] = pcm_irq;
-	cards[0].para[1] = (int) pcm_iob;
-	cards[0].protocol = prot;
-	cards[0].typ = ISDN_CTYPE_SEDLBAUER_PCMCIA;
-
-	if (!HiSax_id)
-		HiSax_id = HiSaxID;
-	if (!HiSaxID[0])
-		strcpy(HiSaxID, "HiSax");
-	for (i = 0; i < HISAX_MAX_CARDS; i++)
-		if (cards[i].typ > 0)
-			nrcards++;
-	printk(KERN_DEBUG "HiSax: Total %d card%s defined\n",
-	       nrcards, (nrcards > 1) ? "s" : "");
-
-	if (!HiSax_inithardware(busy_flag))
-		return -ENODEV;
-	printk(KERN_NOTICE "HiSax: module installed\n");
-#endif
-	return 0;
-}
-#endif
-
-#ifdef CONFIG_HISAX_AVM_A1_PCMCIA
-int avm_a1_init_pcmcia(void *pcm_iob, int pcm_irq, int *busy_flag, int prot)
-{
-#ifdef MODULE
-	int i;
-
-	nrcards = 0;
-	/* Initialize all structs, even though we only accept
-	   two pcmcia cards
-	*/
-	for (i = 0; i < HISAX_MAX_CARDS; i++) {
-		cards[i].para[0] = irq[i];
-		cards[i].para[1] = io[i];
-		cards[i].typ = type[i];
-		if (protocol[i]) {
-			cards[i].protocol = protocol[i];
-		} else {
-			cards[i].protocol = DEFAULT_PROTO;
-		}
-	}
-	cards[0].para[0] = pcm_irq;
-	cards[0].para[1] = (int) pcm_iob;
-	cards[0].protocol = prot;
-	cards[0].typ = ISDN_CTYPE_A1_PCMCIA;
-
-	if (!HiSax_id)
-		HiSax_id = HiSaxID;
-	if (!HiSaxID[0])
-		strcpy(HiSaxID, "HiSax");
-	for (i = 0; i < HISAX_MAX_CARDS; i++)
-		if (cards[i].typ > 0)
-			nrcards++;
-	printk(KERN_DEBUG "HiSax: Total %d card%s defined\n",
-	       nrcards, (nrcards > 1) ? "s" : "");
-
-	if (!HiSax_inithardware(busy_flag))
-		return -ENODEV;
-	printk(KERN_NOTICE "HiSax: module installed\n");
-#endif
-	return 0;
-}
-#endif
-
-int __devinit hisax_init_pcmcia(void *pcm_iob, int *busy_flag,
-				struct IsdnCard *card)
-{
-	u8 ids[16];
+	u_char ids[16];
 	int ret = -1;
 
 	cards[nrcards] = *card;
@@ -1675,14 +1540,18 @@ int __devinit hisax_init_pcmcia(void *pc
 		sprintf(ids, "HiSax%d", nrcards);
 	else
 		sprintf(ids, "HiSax");
-	if (!checkcard(nrcards, ids, busy_flag)) {
-		return -1;
-	}
+	if (!checkcard(nrcards, ids, busy_flag, THIS_MODULE))
+		goto error;
+
 	ret = nrcards;
 	nrcards++;
+error:
 	return ret;
 }
 
+EXPORT_SYMBOL(hisax_init_pcmcia);
+EXPORT_SYMBOL(HiSax_closecard);
+
 #include "hisax_if.h"
 
 EXPORT_SYMBOL(hisax_register);
@@ -1692,68 +1561,47 @@ static void hisax_d_l1l2(struct hisax_if
 static void hisax_b_l1l2(struct hisax_if *ifc, int pr, void *arg);
 static void hisax_d_l2l1(struct PStack *st, int pr, void *arg);
 static void hisax_b_l2l1(struct PStack *st, int pr, void *arg);
+static int hisax_cardmsg(struct IsdnCardState *cs, int mt, void *arg);
 static int hisax_bc_setstack(struct PStack *st, struct BCState *bcs);
 static void hisax_bc_close(struct BCState *bcs);
-static void hisax_bh(void *data);
+static void hisax_bh(struct IsdnCardState *cs);
 static void EChannel_proc_rcv(struct hisax_d_if *d_if);
 
-static int
-hisax_l1_open(struct PStack *st, struct IsdnCardState *cs)
-{
-	st->l1.l2l1 = hisax_d_l2l1;
-	return 0;
-}
-
-static struct dc_l1_ops hisax_l1_ops = {
-	.open    = hisax_l1_open,
-	.bh_func = hisax_bh,
-};
-
-static struct bc_l1_ops hisax_bc_l1_ops = {
-	.open    = hisax_bc_setstack,
-	.close   = hisax_bc_close,
-};
-
 int hisax_register(struct hisax_d_if *hisax_d_if, struct hisax_b_if *b_if[],
 		   char *name, int protocol)
 {
-	int i;
+	int i, retval;
+	char id[20];
 	struct IsdnCardState *cs;
-	
+
 	for (i = 0; i < HISAX_MAX_CARDS; i++) {
 		if (!cards[i].typ)
 			break;
 	}
-	
+
 	if (i >= HISAX_MAX_CARDS)
 		return -EBUSY;
-	
-	nrcards++;
-
-	cs = alloc_IsdnCardState();
-	if (!cs)
-		return -ENOMEM;
-
-#if TEI_PER_CARD
-	if (protocol == ISDN_PTYPE_NI1)
-		test_and_set_bit(FLG_TWO_DCHAN, &cs->HW_Flags);
-#else
-	test_and_set_bit(FLG_TWO_DCHAN, &cs->HW_Flags);
-#endif
-	cs->cardnr = i;
-	cs->protocol = protocol;
-	cs->typ = ISDN_CTYPE_DYNAMIC;
-
-	sprintf(cs->iif.id, "%s%d", name, i);
-	do_register_isdn(cs);
 
+	cards[i].typ = ISDN_CTYPE_DYNAMIC;
+	cards[i].protocol = protocol;
+	sprintf(id, "%s%d", name, i);
+	nrcards++;
+	retval = checkcard(i, id, 0, hisax_d_if->owner);
+	if (retval == 0) { // yuck
+		cards[i].typ = 0;
+		nrcards--;
+		return retval;
+	}
+	cs = cards[i].cs;
 	hisax_d_if->cs = cs;
 	cs->hw.hisax_d_if = hisax_d_if;
-	cs->iif.owner = hisax_d_if->owner;
-	dc_l1_init(cs, &hisax_l1_ops);
-	cs->bc_l1_ops = &hisax_bc_l1_ops;
-
+	cs->cardmsg = hisax_cardmsg;
+	INIT_WORK(&cs->tqueue, (void *)(void *)hisax_bh, cs);
+	cs->channel[0].d_st->l2.l2l1 = hisax_d_l2l1;
 	for (i = 0; i < 2; i++) {
+		cs->bcs[i].BC_SetStack = hisax_bc_setstack;
+		cs->bcs[i].BC_Close = hisax_bc_close;
+
 		b_if[i]->ifc.l1l2 = hisax_b_l1l2;
 
 		hisax_d_if->b_if[i] = b_if[i];
@@ -1762,8 +1610,6 @@ int hisax_register(struct hisax_d_if *hi
 	skb_queue_head_init(&hisax_d_if->erq);
 	clear_bit(0, &hisax_d_if->ph_state);
 	
-	do_init(cs);
-
 	return 0;
 }
 
@@ -1776,9 +1622,14 @@ void hisax_unregister(struct hisax_d_if 
 
 #include "isdnl1.h"
 
-static void hisax_bh(void *data)
+static void hisax_sched_event(struct IsdnCardState *cs, int event)
+{
+	test_and_set_bit(event, &cs->event);
+	schedule_work(&cs->tqueue);
+}
+
+static void hisax_bh(struct IsdnCardState *cs)
 {
-	struct IsdnCardState *cs = data;
 	struct PStack *st;
 	int pr;
 
@@ -1792,11 +1643,17 @@ static void hisax_bh(void *data)
 		else
 			pr = PH_DEACTIVATE | INDICATION;
 		for (st = cs->stlist; st; st = st->next)
-			L1L2(st, pr, NULL);
+			st->l1.l1l2(st, pr, NULL);
 		
 	}
 }
 
+static void hisax_b_sched_event(struct BCState *bcs, int event)
+{
+	test_and_set_bit(event, &bcs->event);
+	schedule_work(&bcs->tqueue);
+}
+
 static inline void D_L2L1(struct hisax_d_if *d_if, int pr, void *arg)
 {
 	struct hisax_if *ifc = (struct hisax_if *) d_if;
@@ -1819,15 +1676,15 @@ static void hisax_d_l1l2(struct hisax_if
 	switch (pr) {
 	case PH_ACTIVATE | INDICATION:
 		set_bit(0, &d_if->ph_state);
-		sched_d_event(cs, D_L1STATECHANGE);
+		hisax_sched_event(cs, D_L1STATECHANGE);
 		break;
 	case PH_DEACTIVATE | INDICATION:
 		clear_bit(0, &d_if->ph_state);
-		sched_d_event(cs, D_L1STATECHANGE);
+		hisax_sched_event(cs, D_L1STATECHANGE);
 		break;
 	case PH_DATA | INDICATION:
 		skb_queue_tail(&cs->rq, arg);
-		sched_d_event(cs, D_RCVBUFREADY);
+		hisax_sched_event(cs, D_RCVBUFREADY);
 		break;
 	case PH_DATA | CONFIRM:
 		skb = skb_dequeue(&cs->sq);
@@ -1838,14 +1695,14 @@ static void hisax_d_l1l2(struct hisax_if
 		clear_bit(FLG_L1_DBUSY, &cs->HW_Flags);
 		for (st = cs->stlist; st; st = st->next) {
 			if (test_and_clear_bit(FLG_L1_PULL_REQ, &st->l1.Flags)) {
-				L1L2(st, PH_PULL | CONFIRM, NULL);
+				st->l1.l1l2(st, PH_PULL | CONFIRM, NULL);
 				break;
 			}
 		}
 		break;
 	case PH_DATA_E | INDICATION:
 		skb_queue_tail(&d_if->erq, arg);
-		sched_d_event(cs, E_RCVBUFREADY);
+		hisax_sched_event(cs, E_RCVBUFREADY);
 		break;
 	default:
 		printk("pr %#x\n", pr);
@@ -1863,22 +1720,27 @@ static void hisax_b_l1l2(struct hisax_if
 	// FIXME use isdnl1?
 	switch (pr) {
 	case PH_ACTIVATE | INDICATION:
-		L1L2(st, pr, NULL);
+		st->l1.l1l2(st, pr, NULL);
 		break;
 	case PH_DEACTIVATE | INDICATION:
-		L1L2(st, pr, NULL);
+		st->l1.l1l2(st, pr, NULL);
 		clear_bit(BC_FLG_BUSY, &bcs->Flag);
 		skb_queue_purge(&bcs->squeue);
 		bcs->hw.b_if = NULL;
 		break;
 	case PH_DATA | INDICATION:
 		skb_queue_tail(&bcs->rqueue, arg);
-		sched_b_event(bcs, B_RCVBUFREADY);
+		hisax_b_sched_event(bcs, B_RCVBUFREADY);
 		break;
 	case PH_DATA | CONFIRM:
-		skb = arg;
-		bcs->tx_cnt -= skb->truesize;
-		xmit_complete_b(bcs);
+		bcs->tx_cnt -= (int) arg;
+		if (test_bit(FLG_LLI_L1WAKEUP,&bcs->st->lli.flag)) {
+			u_long	flags;
+			spin_lock_irqsave(&bcs->aclock, flags);
+			bcs->ackcnt += (int) arg;
+			spin_unlock_irqrestore(&bcs->aclock, flags);
+			schedule_event(bcs, B_ACKPENDING);
+		}
 		skb = skb_dequeue(&bcs->squeue);
 		if (skb) {
 			B_L2L1(b_if, PH_DATA | REQUEST, skb);
@@ -1886,7 +1748,7 @@ static void hisax_b_l1l2(struct hisax_if
 		}
 		clear_bit(BC_FLG_BUSY, &bcs->Flag);
 		if (test_and_clear_bit(FLG_L1_PULL_REQ, &st->l1.Flags)) {
-			L1L2(st, PH_PULL | CONFIRM, NULL);
+			st->l1.l1l2(st, PH_PULL | CONFIRM, NULL);
 		}
 		break;
 	default:
@@ -1917,7 +1779,7 @@ static void hisax_d_l2l1(struct PStack *
 		break;
 	case PH_PULL | REQUEST:
 		if (!test_bit(FLG_L1_DBUSY, &cs->HW_Flags))
-			L1L2(st, PH_PULL | CONFIRM, NULL);
+			st->l1.l1l2(st, PH_PULL | CONFIRM, NULL);
 		else
 			set_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
 		break;
@@ -1927,6 +1789,11 @@ static void hisax_d_l2l1(struct PStack *
 	}
 }
 
+static int hisax_cardmsg(struct IsdnCardState *cs, int mt, void *arg)
+{
+	return 0;
+}
+
 static void hisax_b_l2l1(struct PStack *st, int pr, void *arg)
 {
 	struct BCState *bcs = st->l1.bcs;
@@ -1947,7 +1814,7 @@ static void hisax_b_l2l1(struct PStack *
 		break;
 	case PH_PULL | REQUEST:
 		if (!test_bit(BC_FLG_BUSY, &bcs->Flag))
-			L1L2(st, PH_PULL | CONFIRM, NULL);
+			st->l1.l1l2(st, PH_PULL | CONFIRM, NULL);
 		else
 			set_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
 		break;
@@ -1971,7 +1838,7 @@ static int hisax_bc_setstack(struct PSta
 	hisax_d_if->b_if[st->l1.bc]->bcs = bcs;
 
 	st->l1.bcs = bcs;
-	st->l1.l2l1 = hisax_b_l2l1;
+	st->l2.l2l1 = hisax_b_l2l1;
 	setstack_manager(st);
 	bcs->st = st;
 	setstack_l1_B(st);
@@ -1991,7 +1858,7 @@ static void hisax_bc_close(struct BCStat
 static void EChannel_proc_rcv(struct hisax_d_if *d_if)
 {
 	struct IsdnCardState *cs = d_if->cs;
-	u8 *ptr;
+	u_char *ptr;
 	struct sk_buff *skb;
 
 	while ((skb = skb_dequeue(&d_if->erq)) != NULL) {
@@ -2017,103 +1884,9 @@ static void EChannel_proc_rcv(struct his
 	}
 }
 
-void
-resources_init(struct resources *rs)
-{
-	INIT_LIST_HEAD(&rs->res_head);
-}
-
-void
-resources_release(struct resources *rs)
-{
-	struct res *r;
-
-	list_for_each_entry(r, &rs->res_head, node) {
-		if (r->flags & IORESOURCE_IO) {
-			release_region(r->start, r->end - r->start + 1);
-		}
-		if (r->flags & IORESOURCE_MEM) {
-			iounmap(r->r_u.ioremap_addr);
-			release_mem_region(r->start, r->end - r->start + 1);
-		}
-	}
-}
-
-unsigned long
-request_io(struct resources *rs, unsigned long start, int len,
-	   const char *name)
-{
-	struct res *r;
-
-	r = kmalloc(sizeof(*r), GFP_KERNEL);
-	if (!r) {
-		printk(KERN_WARNING "%s: out of memory\n", __FUNCTION__);
-		goto err;
-	}
-	if (!request_region(start, len, name)) {
-		printk(KERN_WARNING "%s: IO %#lx-%#lx already in use\n",
-		       __FUNCTION__, start, start + len - 1);
-		goto err_free;
-	}
-	r->flags = IORESOURCE_IO;
-	r->start = start;
-	r->end   = start + len - 1;
-	r->name  = name;
-	list_add_tail(&r->node, &rs->res_head);
-
-	return r->start;
-
- err_free:
-	kfree(r);
- err:
-	return 0;
-}
-
-void *
-request_mmio(struct resources *rs, unsigned long start, int len,
-	     const char *name)
-{
-	struct res *r;
-
-	r = kmalloc(sizeof(*r), GFP_KERNEL);
-	if (!r) {
-		printk(KERN_WARNING "%s: out of memory\n", __FUNCTION__);
-		goto err;
-	}
-	if (!request_mem_region(start, len, name)) {
-		printk(KERN_WARNING "%s: MMIO %#lx-%#lx already in use\n",
-		       __FUNCTION__, start, start + len - 1);
-		goto err_free;
-	}
-	r->flags            = IORESOURCE_MEM;
-	r->start            = start;
-	r->end              = start + len - 1;
-	r->name             = name;
-	r->r_u.ioremap_addr = ioremap(start, len);
-	if (!r->r_u.ioremap_addr)
-		goto err_release;
-
-	list_add_tail(&r->node, &rs->res_head);
-
-	return r->r_u.ioremap_addr;
-
- err_release:
-	release_mem_region(r->start, r->end - r->start + 1);
- err_free:
-	kfree(r);
- err:
-	return 0;
-}
-
-void
-hisax_release_resources(struct IsdnCardState *cs)
-{
-	resources_release(&cs->rs);
-}
-
 #include <linux/pci.h>
 
-static struct pci_device_id hisax_pci_tbl[] = {
+static struct pci_device_id hisax_pci_tbl[] __initdata = {
 #ifdef CONFIG_HISAX_FRITZPCI
 	{PCI_VENDOR_ID_AVM,      PCI_DEVICE_ID_AVM_A1,           PCI_ANY_ID, PCI_ANY_ID},
 #endif
@@ -2121,7 +1894,9 @@ static struct pci_device_id hisax_pci_tb
 	{PCI_VENDOR_ID_EICON,    PCI_DEVICE_ID_EICON_DIVA20,     PCI_ANY_ID, PCI_ANY_ID},
 	{PCI_VENDOR_ID_EICON,    PCI_DEVICE_ID_EICON_DIVA20_U,   PCI_ANY_ID, PCI_ANY_ID},
 	{PCI_VENDOR_ID_EICON,    PCI_DEVICE_ID_EICON_DIVA201,    PCI_ANY_ID, PCI_ANY_ID},
+//#########################################################################################	
 	{PCI_VENDOR_ID_EICON,    PCI_DEVICE_ID_EICON_DIVA202,    PCI_ANY_ID, PCI_ANY_ID},
+//#########################################################################################	
 #endif
 #ifdef CONFIG_HISAX_ELSA
 	{PCI_VENDOR_ID_ELSA,     PCI_DEVICE_ID_ELSA_MICROLINK,   PCI_ANY_ID, PCI_ANY_ID},
--- diff/drivers/isdn/hisax/diva.c	2003-09-17 12:28:06.000000000 +0100
+++ source/drivers/isdn/hisax/diva.c	2004-02-23 13:56:42.000000000 +0000
@@ -1,4 +1,4 @@
-/* $Id: diva.c,v 1.25.6.5 2001/09/23 22:24:47 kai Exp $
+/* $Id: diva.c,v 1.33.2.6 2004/02/11 13:21:33 keil Exp $
  *
  * low level stuff for Eicon.Diehl Diva Family ISDN cards
  *
@@ -28,8 +28,7 @@
 
 extern const char *CardType[];
 
-const char *Diva_revision = "$Revision: 1.25.6.5 $";
-static spinlock_t diva_lock = SPIN_LOCK_UNLOCKED;
+const char *Diva_revision = "$Revision: 1.33.2.6 $";
 
 #define byteout(addr,val) outb(val,addr)
 #define bytein(addr) inb(addr)
@@ -82,376 +81,715 @@ static spinlock_t diva_lock = SPIN_LOCK_
 #endif
 #define PITA_INT0_STATUS	0x02
 
-static inline u8
-readreg(unsigned int ale, unsigned int adr, u8 off)
+static inline u_char
+readreg(unsigned int ale, unsigned int adr, u_char off)
 {
-	u8 ret;
-	unsigned long flags;
+	register u_char ret;
 
-	spin_lock_irqsave(&diva_lock, flags);
 	byteout(ale, off);
 	ret = bytein(adr);
-	spin_unlock_irqrestore(&diva_lock, flags);
-	return ret;
+	return (ret);
 }
 
 static inline void
-writereg(unsigned int ale, unsigned int adr, u8 off, u8 data)
+readfifo(unsigned int ale, unsigned int adr, u_char off, u_char * data, int size)
 {
-	unsigned long flags;
-
-	spin_lock_irqsave(&diva_lock, flags);
 	byteout(ale, off);
-	byteout(adr, data);
-	spin_unlock_irqrestore(&diva_lock, flags);
+	insb(adr, data, size);
 }
 
+
 static inline void
-readfifo(unsigned int ale, unsigned int adr, u8 off, u8 * data, int size)
+writereg(unsigned int ale, unsigned int adr, u_char off, u_char data)
 {
 	byteout(ale, off);
-	insb(adr, data, size);
+	byteout(adr, data);
 }
 
 static inline void
-writefifo(unsigned int ale, unsigned int adr, u8 off, u8 *data, int size)
+writefifo(unsigned int ale, unsigned int adr, u_char off, u_char *data, int size)
 {
 	byteout(ale, off);
 	outsb(adr, data, size);
 }
 
-static inline u8
-memreadreg(unsigned long adr, u8 off)
+static inline u_char
+memreadreg(unsigned long adr, u_char off)
 {
-	return readb(((unsigned int *)adr) + off);
+	return(*((unsigned char *)
+		(((unsigned int *)adr) + off)));
 }
 
 static inline void
-memwritereg(unsigned long adr, u8 off, u8 data)
+memwritereg(unsigned long adr, u_char off, u_char data)
 {
-	writeb(data, ((unsigned int *)adr) + off);
+	register u_char *p;
+	
+	p = (unsigned char *)(((unsigned int *)adr) + off);
+	*p = data;
 }
 
-static u8
-isac_read(struct IsdnCardState *cs, u8 offset)
+/* Interface functions */
+
+static u_char
+ReadISAC(struct IsdnCardState *cs, u_char offset)
 {
-	return readreg(cs->hw.diva.isac_adr, cs->hw.diva.isac, offset);
+	return(readreg(cs->hw.diva.isac_adr, cs->hw.diva.isac, offset));
 }
 
 static void
-isac_write(struct IsdnCardState *cs, u8 offset, u8 value)
+WriteISAC(struct IsdnCardState *cs, u_char offset, u_char value)
 {
 	writereg(cs->hw.diva.isac_adr, cs->hw.diva.isac, offset, value);
 }
 
 static void
-isac_read_fifo(struct IsdnCardState *cs, u8 *data, int size)
+ReadISACfifo(struct IsdnCardState *cs, u_char *data, int size)
 {
 	readfifo(cs->hw.diva.isac_adr, cs->hw.diva.isac, 0, data, size);
 }
 
 static void
-isac_write_fifo(struct IsdnCardState *cs, u8 *data, int size)
+WriteISACfifo(struct IsdnCardState *cs, u_char *data, int size)
 {
 	writefifo(cs->hw.diva.isac_adr, cs->hw.diva.isac, 0, data, size);
 }
 
-static struct dc_hw_ops isac_ops = {
-	.read_reg   = isac_read,
-	.write_reg  = isac_write,
-	.read_fifo  = isac_read_fifo,
-	.write_fifo = isac_write_fifo,
-};
-
-static u8
-hscx_read(struct IsdnCardState *cs, int hscx, u8 offset)
+static u_char
+ReadISAC_IPAC(struct IsdnCardState *cs, u_char offset)
 {
-	return readreg(cs->hw.diva.hscx_adr, cs->hw.diva.hscx, 
-		       offset + (hscx ? 0x40 : 0));
+	return (readreg(cs->hw.diva.isac_adr, cs->hw.diva.isac, offset+0x80));
 }
 
 static void
-hscx_write(struct IsdnCardState *cs, int hscx, u8 offset, u8 value)
+WriteISAC_IPAC(struct IsdnCardState *cs, u_char offset, u_char value)
 {
-	writereg(cs->hw.diva.hscx_adr, cs->hw.diva.hscx,
-		 offset + (hscx ? 0x40 : 0), value);
+	writereg(cs->hw.diva.isac_adr, cs->hw.diva.isac, offset|0x80, value);
 }
 
 static void
-hscx_read_fifo(struct IsdnCardState *cs, int hscx, u8 *data, int size)
+ReadISACfifo_IPAC(struct IsdnCardState *cs, u_char * data, int size)
 {
-	readfifo(cs->hw.diva.hscx_adr, cs->hw.diva.hscx, hscx ? 0x40 : 0, data, size);
+	readfifo(cs->hw.diva.isac_adr, cs->hw.diva.isac, 0x80, data, size);
 }
 
 static void
-hscx_write_fifo(struct IsdnCardState *cs, int hscx, u8 *data, int size)
+WriteISACfifo_IPAC(struct IsdnCardState *cs, u_char * data, int size)
 {
-	writefifo(cs->hw.diva.hscx_adr, cs->hw.diva.hscx, hscx ? 0x40 : 0, data, size);
+	writefifo(cs->hw.diva.isac_adr, cs->hw.diva.isac, 0x80, data, size);
 }
 
-static struct bc_hw_ops hscx_ops = {
-	.read_reg  = hscx_read,
-	.write_reg = hscx_write,
-	.read_fifo  = hscx_read_fifo,
-	.write_fifo = hscx_write_fifo,
-};
-
-static inline u8
-ipac_read(struct IsdnCardState *cs, u8 offset)
+static u_char
+ReadHSCX(struct IsdnCardState *cs, int hscx, u_char offset)
 {
-	return readreg(cs->hw.diva.isac_adr, cs->hw.diva.isac, offset);
+	return(readreg(cs->hw.diva.hscx_adr,
+		cs->hw.diva.hscx, offset + (hscx ? 0x40 : 0)));
 }
 
-static inline void
-ipac_write(struct IsdnCardState *cs, u8 offset, u8 value)
+static void
+WriteHSCX(struct IsdnCardState *cs, int hscx, u_char offset, u_char value)
 {
-	writereg(cs->hw.diva.isac_adr, cs->hw.diva.isac, offset, value);
+	writereg(cs->hw.diva.hscx_adr,
+		cs->hw.diva.hscx, offset + (hscx ? 0x40 : 0), value);
 }
 
-static inline void
-ipac_readfifo(struct IsdnCardState *cs, u8 offset, u8 *data, int size)
+static u_char
+MemReadISAC_IPAC(struct IsdnCardState *cs, u_char offset)
 {
-	readfifo(cs->hw.diva.isac_adr, cs->hw.diva.isac, offset, data, size);
+	return (memreadreg(cs->hw.diva.cfg_reg, offset+0x80));
 }
 
-static inline void
-ipac_writefifo(struct IsdnCardState *cs, u8 offset, u8 *data, int size)
+static void
+MemWriteISAC_IPAC(struct IsdnCardState *cs, u_char offset, u_char value)
 {
-	writefifo(cs->hw.diva.isac_adr, cs->hw.diva.isac, offset, data, size);
+	memwritereg(cs->hw.diva.cfg_reg, offset|0x80, value);
 }
 
-/* This will generate ipac_dc_ops and ipac_bc_ops using the functions
- * above */
-
-BUILD_IPAC_OPS(ipac);
-
-static inline u8
-mem_ipac_read(struct IsdnCardState *cs, u8 offset)
+static void
+MemReadISACfifo_IPAC(struct IsdnCardState *cs, u_char * data, int size)
 {
-	return memreadreg(cs->hw.diva.cfg_reg, offset);
+	while(size--)
+		*data++ = memreadreg(cs->hw.diva.cfg_reg, 0x80);
 }
 
-static inline void
-mem_ipac_write(struct IsdnCardState *cs, u8 offset, u8 value)
+static void
+MemWriteISACfifo_IPAC(struct IsdnCardState *cs, u_char * data, int size)
 {
-	memwritereg(cs->hw.diva.cfg_reg, offset, value);
+	while(size--)
+		memwritereg(cs->hw.diva.cfg_reg, 0x80, *data++);
 }
 
-static inline void
-mem_ipac_readfifo(struct IsdnCardState *cs, u8 offset, u8 *data, int size)
+static u_char
+MemReadHSCX(struct IsdnCardState *cs, int hscx, u_char offset)
 {
-	while(size--)
-		*data++ = memreadreg(cs->hw.diva.cfg_reg, offset);
+	return(memreadreg(cs->hw.diva.cfg_reg, offset + (hscx ? 0x40 : 0)));
 }
 
-static inline void
-mem_ipac_writefifo(struct IsdnCardState *cs, u8 offset, u8 *data, int size)
+static void
+MemWriteHSCX(struct IsdnCardState *cs, int hscx, u_char offset, u_char value)
 {
-	while(size--)
-		memwritereg(cs->hw.diva.cfg_reg, offset, *data++);
+	memwritereg(cs->hw.diva.cfg_reg, offset + (hscx ? 0x40 : 0), value);
 }
 
-/* This will generate mem_ipac_dc_ops and mem_ipac_bc_ops using the functions
- * above */
-
-BUILD_IPAC_OPS(mem_ipac);
-
 /* IO-Functions for IPACX type cards */
-static u8
-ipacx_dc_read(struct IsdnCardState *cs, u8 offset)
+static u_char
+MemReadISAC_IPACX(struct IsdnCardState *cs, u_char offset)
 {
-	return memreadreg(cs->hw.diva.cfg_reg, offset);
+	return (memreadreg(cs->hw.diva.cfg_reg, offset));
 }
 
 static void
-ipacx_dc_write(struct IsdnCardState *cs, u8 offset, u8 value)
+MemWriteISAC_IPACX(struct IsdnCardState *cs, u_char offset, u_char value)
 {
 	memwritereg(cs->hw.diva.cfg_reg, offset, value);
 }
 
 static void
-ipacx_dc_read_fifo(struct IsdnCardState *cs, u8 *data, int size)
+MemReadISACfifo_IPACX(struct IsdnCardState *cs, u_char * data, int size)
 {
 	while(size--)
 		*data++ = memreadreg(cs->hw.diva.cfg_reg, 0);
 }
 
 static void
-ipacx_dc_write_fifo(struct IsdnCardState *cs, u8 *data, int size)
+MemWriteISACfifo_IPACX(struct IsdnCardState *cs, u_char * data, int size)
 {
 	while(size--)
 		memwritereg(cs->hw.diva.cfg_reg, 0, *data++);
 }
 
-static struct dc_hw_ops ipacx_dc_ops = {
-	.read_reg   = ipacx_dc_read,
-	.write_reg  = ipacx_dc_write,
-	.read_fifo  = ipacx_dc_read_fifo,
-	.write_fifo = ipacx_dc_write_fifo,
-};
-
-static u8
-ipacx_bc_read(struct IsdnCardState *cs, int hscx, u8 offset)
+static u_char
+MemReadHSCX_IPACX(struct IsdnCardState *cs, int hscx, u_char offset)
 {
-	return memreadreg(cs->hw.diva.cfg_reg, offset + 
-			  (hscx ? IPACX_OFF_B2 : IPACX_OFF_B1));
+	return(memreadreg(cs->hw.diva.cfg_reg, offset + 
+                    (hscx ? IPACX_OFF_B2 : IPACX_OFF_B1)));
 }
 
 static void
-ipacx_bc_write(struct IsdnCardState *cs, int hscx, u8 offset, u8 value)
+MemWriteHSCX_IPACX(struct IsdnCardState *cs, int hscx, u_char offset, u_char value)
 {
 	memwritereg(cs->hw.diva.cfg_reg, offset + 
               (hscx ? IPACX_OFF_B2 : IPACX_OFF_B1), value);
 }
 
-static void
-ipacx_bc_read_fifo(struct IsdnCardState *cs, int hscx, u8 *data, int len)
-{
-	int i;
+/*
+ * fast interrupt HSCX stuff goes here
+ */
 
-	for (i = 0; i < len ; i++)
-		*data++ = ipacx_bc_read(cs, hscx, IPACX_RFIFOB);
-}
+#define READHSCX(cs, nr, reg) readreg(cs->hw.diva.hscx_adr, \
+		cs->hw.diva.hscx, reg + (nr ? 0x40 : 0))
+#define WRITEHSCX(cs, nr, reg, data) writereg(cs->hw.diva.hscx_adr, \
+                cs->hw.diva.hscx, reg + (nr ? 0x40 : 0), data)
 
-static struct bc_hw_ops ipacx_bc_ops = {
-	.read_reg   = ipacx_bc_read,
-	.write_reg  = ipacx_bc_write,
-	.read_fifo  = ipacx_bc_read_fifo,
-};
+#define READHSCXFIFO(cs, nr, ptr, cnt) readfifo(cs->hw.diva.hscx_adr, \
+		cs->hw.diva.hscx, (nr ? 0x40 : 0), ptr, cnt)
+
+#define WRITEHSCXFIFO(cs, nr, ptr, cnt) writefifo(cs->hw.diva.hscx_adr, \
+		cs->hw.diva.hscx, (nr ? 0x40 : 0), ptr, cnt)
+
+#include "hscx_irq.c"
 
 static irqreturn_t
 diva_interrupt(int intno, void *dev_id, struct pt_regs *regs)
 {
 	struct IsdnCardState *cs = dev_id;
-	u8 sval;
+	u_char val, sval;
+	u_long flags;
 	int cnt=5;
 
+	spin_lock_irqsave(&cs->lock, flags);
 	while (((sval = bytein(cs->hw.diva.ctrl)) & DIVA_IRQ_REQ) && cnt) {
-		hscxisac_irq(intno, dev_id, regs);
+		val = readreg(cs->hw.diva.hscx_adr, cs->hw.diva.hscx, HSCX_ISTA + 0x40);
+		if (val)
+			hscx_int_main(cs, val);
+		val = readreg(cs->hw.diva.isac_adr, cs->hw.diva.isac, ISAC_ISTA);
+		if (val)
+			isac_interrupt(cs, val);
+		cnt--;
 	}
 	if (!cnt)
 		printk(KERN_WARNING "Diva: IRQ LOOP\n");
+	writereg(cs->hw.diva.hscx_adr, cs->hw.diva.hscx, HSCX_MASK, 0xFF);
+	writereg(cs->hw.diva.hscx_adr, cs->hw.diva.hscx, HSCX_MASK + 0x40, 0xFF);
+	writereg(cs->hw.diva.isac_adr, cs->hw.diva.isac, ISAC_MASK, 0xFF);
+	writereg(cs->hw.diva.isac_adr, cs->hw.diva.isac, ISAC_MASK, 0x0);
+	writereg(cs->hw.diva.hscx_adr, cs->hw.diva.hscx, HSCX_MASK, 0x0);
+	writereg(cs->hw.diva.hscx_adr, cs->hw.diva.hscx, HSCX_MASK + 0x40, 0x0);
+	spin_unlock_irqrestore(&cs->lock, flags);
 	return IRQ_HANDLED;
 }
 
 static irqreturn_t
-diva_ipac_pci_irq(int intno, void *dev_id, struct pt_regs *regs)
+diva_irq_ipac_isa(int intno, void *dev_id, struct pt_regs *regs)
 {
 	struct IsdnCardState *cs = dev_id;
-	u8 val;
+	u_char ista,val;
+	u_long flags;
+	int icnt=5;
+
+	spin_lock_irqsave(&cs->lock, flags);
+	ista = readreg(cs->hw.diva.isac_adr, cs->hw.diva.isac, IPAC_ISTA);
+Start_IPACISA:
+	if (cs->debug & L1_DEB_IPAC)
+		debugl1(cs, "IPAC ISTA %02X", ista);
+	if (ista & 0x0f) {
+		val = readreg(cs->hw.diva.isac_adr, cs->hw.diva.isac, HSCX_ISTA + 0x40);
+		if (ista & 0x01)
+			val |= 0x01;
+		if (ista & 0x04)
+			val |= 0x02;
+		if (ista & 0x08)
+			val |= 0x04;
+		if (val)
+			hscx_int_main(cs, val);
+	}
+	if (ista & 0x20) {
+		val = 0xfe & readreg(cs->hw.diva.isac_adr, cs->hw.diva.isac, ISAC_ISTA + 0x80);
+		if (val) {
+			isac_interrupt(cs, val);
+		}
+	}
+	if (ista & 0x10) {
+		val = 0x01;
+		isac_interrupt(cs, val);
+	}
+	ista  = readreg(cs->hw.diva.isac_adr, cs->hw.diva.isac, IPAC_ISTA);
+	if ((ista & 0x3f) && icnt) {
+		icnt--;
+		goto Start_IPACISA;
+	}
+	if (!icnt)
+		printk(KERN_WARNING "DIVA IPAC IRQ LOOP\n");
+	writereg(cs->hw.diva.isac_adr, cs->hw.diva.isac, IPAC_MASK, 0xFF);
+	writereg(cs->hw.diva.isac_adr, cs->hw.diva.isac, IPAC_MASK, 0xC0);
+	spin_unlock_irqrestore(&cs->lock, flags);
+	return IRQ_HANDLED;
+}
 
-	val = readb(cs->hw.diva.pci_cfg);
-	if (!(val & PITA_INT0_STATUS))
-		return IRQ_NONE; /* other shared IRQ */
-	writeb(PITA_INT0_STATUS, cs->hw.diva.pci_cfg); /* Reset pending INT0 */
+static inline void
+MemwaitforCEC(struct IsdnCardState *cs, int hscx)
+{
+	int to = 50;
 
-	return ipac_irq(intno, dev_id, regs);
+	while ((MemReadHSCX(cs, hscx, HSCX_STAR) & 0x04) && to) {
+		udelay(1);
+		to--;
+	}
+	if (!to)
+		printk(KERN_WARNING "HiSax: waitforCEC timeout\n");
 }
 
-static irqreturn_t
-diva_ipacx_pci_irq(int intno, void *dev_id, struct pt_regs *regs)
+
+static inline void
+MemwaitforXFW(struct IsdnCardState *cs, int hscx)
 {
-	struct IsdnCardState *cs = dev_id;
-	u8 val;
+	int to = 50;
 
-	val = readb(cs->hw.diva.pci_cfg);
-	if (!(val &PITA_INT0_STATUS))
-		return IRQ_NONE; // other shared IRQ
-	interrupt_ipacx(cs);      // handler for chip
-	writeb(PITA_INT0_STATUS, cs->hw.diva.pci_cfg);  // Reset PLX interrupt
-	return IRQ_HANDLED;
+	while ((!(MemReadHSCX(cs, hscx, HSCX_STAR) & 0x44) == 0x40) && to) {
+		udelay(1);
+		to--;
+	}
+	if (!to)
+		printk(KERN_WARNING "HiSax: waitforXFW timeout\n");
 }
 
-static void
-diva_release(struct IsdnCardState *cs)
+static inline void
+MemWriteHSCXCMDR(struct IsdnCardState *cs, int hscx, u_char data)
 {
-	del_timer_sync(&cs->hw.diva.tl);
-	if (cs->hw.diva.cfg_reg)
-		byteout(cs->hw.diva.ctrl, 0); /* LED off, Reset */
+	MemwaitforCEC(cs, hscx);
+	MemWriteHSCX(cs, hscx, HSCX_CMDR, data);
+}
 
-	hisax_release_resources(cs);
+static void
+Memhscx_empty_fifo(struct BCState *bcs, int count)
+{
+	u_char *ptr;
+	struct IsdnCardState *cs = bcs->cs;
+	int cnt;
+
+	if ((cs->debug & L1_DEB_HSCX) && !(cs->debug & L1_DEB_HSCX_FIFO))
+		debugl1(cs, "hscx_empty_fifo");
+
+	if (bcs->hw.hscx.rcvidx + count > HSCX_BUFMAX) {
+		if (cs->debug & L1_DEB_WARN)
+			debugl1(cs, "hscx_empty_fifo: incoming packet too large");
+		MemWriteHSCXCMDR(cs, bcs->hw.hscx.hscx, 0x80);
+		bcs->hw.hscx.rcvidx = 0;
+		return;
+	}
+	ptr = bcs->hw.hscx.rcvbuf + bcs->hw.hscx.rcvidx;
+	cnt = count;
+	while (cnt--)
+		*ptr++ = memreadreg(cs->hw.diva.cfg_reg, bcs->hw.hscx.hscx ? 0x40 : 0);
+	MemWriteHSCXCMDR(cs, bcs->hw.hscx.hscx, 0x80);
+	ptr = bcs->hw.hscx.rcvbuf + bcs->hw.hscx.rcvidx;
+	bcs->hw.hscx.rcvidx += count;
+	if (cs->debug & L1_DEB_HSCX_FIFO) {
+		char *t = bcs->blog;
+
+		t += sprintf(t, "hscx_empty_fifo %c cnt %d",
+			     bcs->hw.hscx.hscx ? 'B' : 'A', count);
+		QuickHex(t, ptr, count);
+		debugl1(cs, bcs->blog);
+	}
 }
 
 static void
-diva_ipac_pci_release(struct IsdnCardState *cs)
+Memhscx_fill_fifo(struct BCState *bcs)
 {
-	writel(0, cs->hw.diva.pci_cfg); /* disable INT0/1 */ 
-	writel(2, cs->hw.diva.pci_cfg); /* reset pending INT0 */
-	hisax_release_resources(cs);
+	struct IsdnCardState *cs = bcs->cs;
+	int more, count, cnt;
+	int fifo_size = test_bit(HW_IPAC, &cs->HW_Flags)? 64: 32;
+	u_char *ptr,*p;
+
+	if ((cs->debug & L1_DEB_HSCX) && !(cs->debug & L1_DEB_HSCX_FIFO))
+		debugl1(cs, "hscx_fill_fifo");
+
+	if (!bcs->tx_skb)
+		return;
+	if (bcs->tx_skb->len <= 0)
+		return;
+
+	more = (bcs->mode == L1_MODE_TRANS) ? 1 : 0;
+	if (bcs->tx_skb->len > fifo_size) {
+		more = !0;
+		count = fifo_size;
+	} else
+		count = bcs->tx_skb->len;
+	cnt = count;
+	MemwaitforXFW(cs, bcs->hw.hscx.hscx);
+	p = ptr = bcs->tx_skb->data;
+	skb_pull(bcs->tx_skb, count);
+	bcs->tx_cnt -= count;
+	bcs->hw.hscx.count += count;
+	while(cnt--)
+		memwritereg(cs->hw.diva.cfg_reg, bcs->hw.hscx.hscx ? 0x40 : 0,
+			*p++);
+	MemWriteHSCXCMDR(cs, bcs->hw.hscx.hscx, more ? 0x8 : 0xa);
+	if (cs->debug & L1_DEB_HSCX_FIFO) {
+		char *t = bcs->blog;
+
+		t += sprintf(t, "hscx_fill_fifo %c cnt %d",
+			     bcs->hw.hscx.hscx ? 'B' : 'A', count);
+		QuickHex(t, ptr, count);
+		debugl1(cs, bcs->blog);
+	}
 }
 
-static int
-diva_ipac_isa_reset(struct IsdnCardState *cs)
+static inline void
+Memhscx_interrupt(struct IsdnCardState *cs, u_char val, u_char hscx)
 {
-	writereg(cs->hw.diva.isac_adr, cs->hw.diva.isac, IPAC_POTA2, 0x20);
-	set_current_state(TASK_UNINTERRUPTIBLE);
-	schedule_timeout((10*HZ)/1000);
-	writereg(cs->hw.diva.isac_adr, cs->hw.diva.isac, IPAC_POTA2, 0x00);
-	set_current_state(TASK_UNINTERRUPTIBLE);
-	schedule_timeout((10*HZ)/1000);
-	writereg(cs->hw.diva.isac_adr, cs->hw.diva.isac, IPAC_MASK, 0xc0);
-	return 0;
+	u_char r;
+	struct BCState *bcs = cs->bcs + hscx;
+	struct sk_buff *skb;
+	int fifo_size = test_bit(HW_IPAC, &cs->HW_Flags)? 64: 32;
+	int count;
+
+	if (!test_bit(BC_FLG_INIT, &bcs->Flag))
+		return;
+
+	if (val & 0x80) {	/* RME */
+		r = MemReadHSCX(cs, hscx, HSCX_RSTA);
+		if ((r & 0xf0) != 0xa0) {
+			if (!(r & 0x80))
+				if (cs->debug & L1_DEB_WARN)
+					debugl1(cs, "HSCX invalid frame");
+			if ((r & 0x40) && bcs->mode)
+				if (cs->debug & L1_DEB_WARN)
+					debugl1(cs, "HSCX RDO mode=%d",
+						bcs->mode);
+			if (!(r & 0x20))
+				if (cs->debug & L1_DEB_WARN)
+					debugl1(cs, "HSCX CRC error");
+			MemWriteHSCXCMDR(cs, hscx, 0x80);
+		} else {
+			count = MemReadHSCX(cs, hscx, HSCX_RBCL) & (
+				test_bit(HW_IPAC, &cs->HW_Flags)? 0x3f: 0x1f);
+			if (count == 0)
+				count = fifo_size;
+			Memhscx_empty_fifo(bcs, count);
+			if ((count = bcs->hw.hscx.rcvidx - 1) > 0) {
+				if (cs->debug & L1_DEB_HSCX_FIFO)
+					debugl1(cs, "HX Frame %d", count);
+				if (!(skb = dev_alloc_skb(count)))
+					printk(KERN_WARNING "HSCX: receive out of memory\n");
+				else {
+					memcpy(skb_put(skb, count), bcs->hw.hscx.rcvbuf, count);
+					skb_queue_tail(&bcs->rqueue, skb);
+				}
+			}
+		}
+		bcs->hw.hscx.rcvidx = 0;
+		schedule_event(bcs, B_RCVBUFREADY);
+	}
+	if (val & 0x40) {	/* RPF */
+		Memhscx_empty_fifo(bcs, fifo_size);
+		if (bcs->mode == L1_MODE_TRANS) {
+			/* receive audio data */
+			if (!(skb = dev_alloc_skb(fifo_size)))
+				printk(KERN_WARNING "HiSax: receive out of memory\n");
+			else {
+				memcpy(skb_put(skb, fifo_size), bcs->hw.hscx.rcvbuf, fifo_size);
+				skb_queue_tail(&bcs->rqueue, skb);
+			}
+			bcs->hw.hscx.rcvidx = 0;
+			schedule_event(bcs, B_RCVBUFREADY);
+		}
+	}
+	if (val & 0x10) {	/* XPR */
+		if (bcs->tx_skb) {
+			if (bcs->tx_skb->len) {
+				Memhscx_fill_fifo(bcs);
+				return;
+			} else {
+				if (test_bit(FLG_LLI_L1WAKEUP,&bcs->st->lli.flag) &&
+					(PACKET_NOACK != bcs->tx_skb->pkt_type)) {
+					u_long	flags;
+					spin_lock_irqsave(&bcs->aclock, flags);
+					bcs->ackcnt += bcs->hw.hscx.count;
+					spin_unlock_irqrestore(&bcs->aclock, flags);
+					schedule_event(bcs, B_ACKPENDING);
+				}
+				dev_kfree_skb_irq(bcs->tx_skb);
+				bcs->hw.hscx.count = 0; 
+				bcs->tx_skb = NULL;
+			}
+		}
+		if ((bcs->tx_skb = skb_dequeue(&bcs->squeue))) {
+			bcs->hw.hscx.count = 0;
+			test_and_set_bit(BC_FLG_BUSY, &bcs->Flag);
+			Memhscx_fill_fifo(bcs);
+		} else {
+			test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
+			schedule_event(bcs, B_XMTBUFREADY);
+		}
+	}
 }
 
-static int
-diva_ipac_pci_reset(struct IsdnCardState *cs)
+static inline void
+Memhscx_int_main(struct IsdnCardState *cs, u_char val)
+{
+
+	u_char exval;
+	struct BCState *bcs;
+
+	if (val & 0x01) { // EXB
+		bcs = cs->bcs + 1;
+		exval = MemReadHSCX(cs, 1, HSCX_EXIR);
+		if (exval & 0x40) {
+			if (bcs->mode == 1)
+				Memhscx_fill_fifo(bcs);
+			else {
+				/* Here we lost an TX interrupt, so
+				   * restart transmitting the whole frame.
+				 */
+				if (bcs->tx_skb) {
+					skb_push(bcs->tx_skb, bcs->hw.hscx.count);
+					bcs->tx_cnt += bcs->hw.hscx.count;
+					bcs->hw.hscx.count = 0;
+				}
+				MemWriteHSCXCMDR(cs, bcs->hw.hscx.hscx, 0x01);
+				if (cs->debug & L1_DEB_WARN)
+					debugl1(cs, "HSCX B EXIR %x Lost TX", exval);
+			}
+		} else if (cs->debug & L1_DEB_HSCX)
+			debugl1(cs, "HSCX B EXIR %x", exval);
+	}
+	if (val & 0xf8) {
+		if (cs->debug & L1_DEB_HSCX)
+			debugl1(cs, "HSCX B interrupt %x", val);
+		Memhscx_interrupt(cs, val, 1);
+	}
+	if (val & 0x02) {	// EXA
+		bcs = cs->bcs;
+		exval = MemReadHSCX(cs, 0, HSCX_EXIR);
+		if (exval & 0x40) {
+			if (bcs->mode == L1_MODE_TRANS)
+				Memhscx_fill_fifo(bcs);
+			else {
+				/* Here we lost an TX interrupt, so
+				   * restart transmitting the whole frame.
+				 */
+				if (bcs->tx_skb) {
+					skb_push(bcs->tx_skb, bcs->hw.hscx.count);
+					bcs->tx_cnt += bcs->hw.hscx.count;
+					bcs->hw.hscx.count = 0;
+				}
+				MemWriteHSCXCMDR(cs, bcs->hw.hscx.hscx, 0x01);
+				if (cs->debug & L1_DEB_WARN)
+					debugl1(cs, "HSCX A EXIR %x Lost TX", exval);
+			}
+		} else if (cs->debug & L1_DEB_HSCX)
+			debugl1(cs, "HSCX A EXIR %x", exval);
+	}
+	if (val & 0x04) {	// ICA
+		exval = MemReadHSCX(cs, 0, HSCX_ISTA);
+		if (cs->debug & L1_DEB_HSCX)
+			debugl1(cs, "HSCX A interrupt %x", exval);
+		Memhscx_interrupt(cs, exval, 0);
+	}
+}
+
+static irqreturn_t
+diva_irq_ipac_pci(int intno, void *dev_id, struct pt_regs *regs)
 {
-	unsigned long misc_reg = cs->hw.diva.pci_cfg + PITA_MISC_REG;
+	struct IsdnCardState *cs = dev_id;
+	u_char ista,val;
+	int icnt=5;
+	u_char *cfg;
+	u_long flags;
+
+	spin_lock_irqsave(&cs->lock, flags);
+	cfg = (u_char *) cs->hw.diva.pci_cfg;
+	val = *cfg;
+	if (!(val & PITA_INT0_STATUS)) {
+		spin_unlock_irqrestore(&cs->lock, flags);
+		return IRQ_NONE; /* other shared IRQ */
+	}
+	*cfg = PITA_INT0_STATUS; /* Reset pending INT0 */
+	ista = memreadreg(cs->hw.diva.cfg_reg, IPAC_ISTA);
+Start_IPACPCI:
+	if (cs->debug & L1_DEB_IPAC)
+		debugl1(cs, "IPAC ISTA %02X", ista);
+	if (ista & 0x0f) {
+		val = memreadreg(cs->hw.diva.cfg_reg, HSCX_ISTA + 0x40);
+		if (ista & 0x01)
+			val |= 0x01;
+		if (ista & 0x04)
+			val |= 0x02;
+		if (ista & 0x08)
+			val |= 0x04;
+		if (val)
+			Memhscx_int_main(cs, val);
+	}
+	if (ista & 0x20) {
+		val = 0xfe & memreadreg(cs->hw.diva.cfg_reg, ISAC_ISTA + 0x80);
+		if (val) {
+			isac_interrupt(cs, val);
+		}
+	}
+	if (ista & 0x10) {
+		val = 0x01;
+		isac_interrupt(cs, val);
+	}
+	ista  = memreadreg(cs->hw.diva.cfg_reg, IPAC_ISTA);
+	if ((ista & 0x3f) && icnt) {
+		icnt--;
+		goto Start_IPACPCI;
+	}
+	if (!icnt)
+		printk(KERN_WARNING "DIVA IPAC PCI IRQ LOOP\n");
+	memwritereg(cs->hw.diva.cfg_reg, IPAC_MASK, 0xFF);
+	memwritereg(cs->hw.diva.cfg_reg, IPAC_MASK, 0xC0);
+	spin_unlock_irqrestore(&cs->lock, flags);
+	return IRQ_HANDLED;
+}
 
-	writel(PITA_PARA_SOFTRESET | PITA_PARA_MPX_MODE, misc_reg);
-	set_current_state(TASK_UNINTERRUPTIBLE);
-	schedule_timeout((10*HZ)/1000);
-	writel(PITA_PARA_MPX_MODE, misc_reg);
-	set_current_state(TASK_UNINTERRUPTIBLE);
-	schedule_timeout((10*HZ)/1000);
-	memwritereg(cs->hw.diva.cfg_reg, IPAC_MASK, 0xc0);
-	return 0;
+static irqreturn_t
+diva_irq_ipacx_pci(int intno, void *dev_id, struct pt_regs *regs)
+{
+	struct IsdnCardState *cs = dev_id;
+	u_char val;
+	u_char *cfg;
+	u_long flags;
+
+	spin_lock_irqsave(&cs->lock, flags);
+	cfg = (u_char *) cs->hw.diva.pci_cfg;
+	val = *cfg;
+	if (!(val &PITA_INT0_STATUS)) {
+		spin_unlock_irqrestore(&cs->lock, flags);
+		return IRQ_NONE; // other shared IRQ
+	}
+ 	interrupt_ipacx(cs);      // handler for chip
+	*cfg = PITA_INT0_STATUS;  // Reset PLX interrupt
+	spin_unlock_irqrestore(&cs->lock, flags);
+	return IRQ_HANDLED;
 }
 
-static int
-diva_ipacx_pci_reset(struct IsdnCardState *cs)
+void
+release_io_diva(struct IsdnCardState *cs)
 {
-	unsigned long misc_reg = cs->hw.diva.pci_cfg + PITA_MISC_REG;
+	int bytecnt;
 
-	writel(PITA_PARA_SOFTRESET | PITA_PARA_MPX_MODE, misc_reg);
-	set_current_state(TASK_UNINTERRUPTIBLE);
-	schedule_timeout((10*HZ)/1000);
-	writel(PITA_PARA_MPX_MODE | PITA_SER_SOFTRESET, misc_reg);
-	set_current_state(TASK_UNINTERRUPTIBLE);
-	schedule_timeout((10*HZ)/1000);
-	ipacx_dc_write(cs, IPACX_MASK, 0xff); // Interrupts off
-	return 0;
+	if ((cs->subtyp == DIVA_IPAC_PCI) || 
+	    (cs->subtyp == DIVA_IPACX_PCI)   ) {
+		u_int *cfg = (unsigned int *)cs->hw.diva.pci_cfg;
+
+		*cfg = 0; /* disable INT0/1 */ 
+		*cfg = 2; /* reset pending INT0 */
+		iounmap((void *)cs->hw.diva.cfg_reg);
+		iounmap((void *)cs->hw.diva.pci_cfg);
+		return;
+	} else if (cs->subtyp != DIVA_IPAC_ISA) {
+		del_timer(&cs->hw.diva.tl);
+		if (cs->hw.diva.cfg_reg)
+			byteout(cs->hw.diva.ctrl, 0); /* LED off, Reset */
+	}
+	if ((cs->subtyp == DIVA_ISA) || (cs->subtyp == DIVA_IPAC_ISA))
+		bytecnt = 8;
+	else
+		bytecnt = 32;
+	if (cs->hw.diva.cfg_reg) {
+		release_region(cs->hw.diva.cfg_reg, bytecnt);
+	}
 }
 
-static int
-diva_reset(struct IsdnCardState *cs)
+static void
+reset_diva(struct IsdnCardState *cs)
 {
-	/* DIVA 2.0 */
-	cs->hw.diva.ctrl_reg = 0;        /* Reset On */
-	byteout(cs->hw.diva.ctrl, cs->hw.diva.ctrl_reg);
-	set_current_state(TASK_UNINTERRUPTIBLE);
-	schedule_timeout((10*HZ)/1000);
-	cs->hw.diva.ctrl_reg |= DIVA_RESET;  /* Reset Off */
-	byteout(cs->hw.diva.ctrl, cs->hw.diva.ctrl_reg);
-	set_current_state(TASK_UNINTERRUPTIBLE);
-	schedule_timeout((10*HZ)/1000);
-	if (cs->subtyp == DIVA_ISA) {
-		cs->hw.diva.ctrl_reg |= DIVA_ISA_LED_A;
-	} else {
-		/* Workaround PCI9060 */
-		byteout(cs->hw.diva.pci_cfg + 0x69, 9);
-		cs->hw.diva.ctrl_reg |= DIVA_PCI_LED_A;
+	if (cs->subtyp == DIVA_IPAC_ISA) {
+		writereg(cs->hw.diva.isac_adr, cs->hw.diva.isac, IPAC_POTA2, 0x20);
+		mdelay(10);
+		writereg(cs->hw.diva.isac_adr, cs->hw.diva.isac, IPAC_POTA2, 0x00);
+		mdelay(10);
+		writereg(cs->hw.diva.isac_adr, cs->hw.diva.isac, IPAC_MASK, 0xc0);
+	} else if (cs->subtyp == DIVA_IPAC_PCI) {
+		unsigned int *ireg = (unsigned int *)(cs->hw.diva.pci_cfg +
+					PITA_MISC_REG);
+		*ireg = PITA_PARA_SOFTRESET | PITA_PARA_MPX_MODE;
+		mdelay(10);
+		*ireg = PITA_PARA_MPX_MODE;
+		mdelay(10);
+		memwritereg(cs->hw.diva.cfg_reg, IPAC_MASK, 0xc0);
+	} else if (cs->subtyp == DIVA_IPACX_PCI) {
+		unsigned int *ireg = (unsigned int *)(cs->hw.diva.pci_cfg +
+					PITA_MISC_REG);
+		*ireg = PITA_PARA_SOFTRESET | PITA_PARA_MPX_MODE;
+		mdelay(10);
+		*ireg = PITA_PARA_MPX_MODE | PITA_SER_SOFTRESET;
+		mdelay(10);
+		MemWriteISAC_IPACX(cs, IPACX_MASK, 0xff); // Interrupts off
+	} else { /* DIVA 2.0 */
+		cs->hw.diva.ctrl_reg = 0;        /* Reset On */
+		byteout(cs->hw.diva.ctrl, cs->hw.diva.ctrl_reg);
+		mdelay(10);
+		cs->hw.diva.ctrl_reg |= DIVA_RESET;  /* Reset Off */
+		byteout(cs->hw.diva.ctrl, cs->hw.diva.ctrl_reg);
+		mdelay(10);
+		if (cs->subtyp == DIVA_ISA)
+			cs->hw.diva.ctrl_reg |= DIVA_ISA_LED_A;
+		else {
+			/* Workaround PCI9060 */
+			byteout(cs->hw.diva.pci_cfg + 0x69, 9);
+			cs->hw.diva.ctrl_reg |= DIVA_PCI_LED_A;
+		}
+		byteout(cs->hw.diva.ctrl, cs->hw.diva.ctrl_reg);
 	}
-	byteout(cs->hw.diva.ctrl, cs->hw.diva.ctrl_reg);
-	return 0;
 }
 
+#define DIVA_ASSIGN 1
+
 static void
 diva_led_handler(struct IsdnCardState *cs)
 {
 	int blink = 0;
 
-	if (cs->status & 0x0001)
+	if ((cs->subtyp == DIVA_IPAC_ISA) ||
+	    (cs->subtyp == DIVA_IPAC_PCI) ||
+	    (cs->subtyp == DIVA_IPACX_PCI)   )
+		return;
+	del_timer(&cs->hw.diva.tl);
+	if (cs->hw.diva.status & DIVA_ASSIGN)
 		cs->hw.diva.ctrl_reg |= (DIVA_ISA == cs->subtyp) ?
 			DIVA_ISA_LED_A : DIVA_PCI_LED_A;
 	else {
@@ -459,10 +797,10 @@ diva_led_handler(struct IsdnCardState *c
 			DIVA_ISA_LED_A : DIVA_PCI_LED_A;
 		blink = 250;
 	}
-	if (cs->status & 0xf000)
+	if (cs->hw.diva.status & 0xf000)
 		cs->hw.diva.ctrl_reg |= (DIVA_ISA == cs->subtyp) ?
 			DIVA_ISA_LED_B : DIVA_PCI_LED_B;
-	else if (cs->status & 0x0f00) {
+	else if (cs->hw.diva.status & 0x0f00) {
 		cs->hw.diva.ctrl_reg ^= (DIVA_ISA == cs->subtyp) ?
 			DIVA_ISA_LED_B : DIVA_PCI_LED_B;
 		blink = 500;
@@ -471,212 +809,90 @@ diva_led_handler(struct IsdnCardState *c
 			DIVA_ISA_LED_B : DIVA_PCI_LED_B);
 
 	byteout(cs->hw.diva.ctrl, cs->hw.diva.ctrl_reg);
-	if (blink)
-		mod_timer(&cs->hw.diva.tl, jiffies + (blink * HZ) / 1000);
-}
-
-static void
-diva_ipacx_pci_init(struct IsdnCardState *cs)
-{
-	writel(PITA_INT0_ENABLE, cs->hw.diva.pci_cfg);
-	init_ipacx(cs, 3); // init chip and enable interrupts
-}
-
-static void
-diva_ipac_pci_init(struct IsdnCardState *cs)
-{
-	writel(PITA_INT0_ENABLE, cs->hw.diva.pci_cfg);
-	ipac_init(cs);
-}
-
-static struct card_ops diva_ops = {
-	.init        = inithscxisac,
-	.reset       = diva_reset,
-	.release     = diva_release,
-	.led_handler = diva_led_handler,
-	.irq_func    = diva_interrupt,
-};
-
-static struct card_ops diva_ipac_isa_ops = {
-	.init        = ipac_init,
-	.reset       = diva_ipac_isa_reset,
-	.release     = hisax_release_resources,
-	.irq_func    = ipac_irq,
-};
-
-static struct card_ops diva_ipac_pci_ops = {
-	.init        = diva_ipac_pci_init,
-	.reset       = diva_ipac_pci_reset,
-	.release     = diva_ipac_pci_release,
-	.irq_func    = diva_ipac_pci_irq,
-};
-
-static struct card_ops diva_ipacx_pci_ops = {
-	.init        = diva_ipacx_pci_init,
-	.reset       = diva_ipacx_pci_reset,
-	.release     = diva_ipac_pci_release,
-	.irq_func    = diva_ipacx_pci_irq,
-};
-
-static int __init
-diva_ipac_probe(struct IsdnCardState *cs)
-{
-	u8 val;
-
-	// request_io
-	val = readreg(cs->hw.diva.cfg_reg + DIVA_IPAC_ADR,
-		      cs->hw.diva.cfg_reg + DIVA_IPAC_DATA, IPAC_ID);
-	printk(KERN_INFO "Diva: IPAC version %x\n", val);
-	return (val == 1 || val == 2);
-}
-
-static int __init
-diva_ipac_isa_probe(struct IsdnCardState *cs, struct IsdnCard *card)
-{
-	cs->subtyp = DIVA_IPAC_ISA;
-	cs->irq = card->para[0];
-	cs->hw.diva.cfg_reg  = card->para[1];
-	cs->hw.diva.isac     = card->para[1] + DIVA_IPAC_DATA;
-	cs->hw.diva.isac_adr = card->para[1] + DIVA_IPAC_ADR;
-	printk(KERN_INFO "Diva: %s card configured at %#lx IRQ %d\n",
-	       "IPAC ISA", cs->hw.diva.cfg_reg, cs->irq);
-	if (!request_io(&cs->rs, cs->hw.diva.cfg_reg, 8, "diva isdn"))
-		goto err;
-	diva_ipac_isa_reset(cs);
-	cs->card_ops = &diva_ipac_isa_ops;
-	if (ipac_setup(cs, &ipac_dc_ops, &ipac_bc_ops))
-		goto err;
-	return 0;
- err:
-	hisax_release_resources(cs);
-	return -EBUSY;
-}
-
-static int __init
-diva_isac_isa_probe(struct IsdnCardState *cs, struct IsdnCard *card)
-{
-	cs->subtyp = DIVA_ISA;
-	cs->irq = card->para[0];
-	cs->hw.diva.cfg_reg  = card->para[1];
-	cs->hw.diva.ctrl     = card->para[1] + DIVA_ISA_CTRL;
-	cs->hw.diva.isac     = card->para[1] + DIVA_ISA_ISAC_DATA;
-	cs->hw.diva.hscx     = card->para[1] + DIVA_HSCX_DATA;
-	cs->hw.diva.isac_adr = card->para[1] + DIVA_ISA_ISAC_ADR;
-	cs->hw.diva.hscx_adr = card->para[1] + DIVA_HSCX_ADR;
-	printk(KERN_INFO "Diva: %s card configured at %#lx IRQ %d\n",
-	       "ISA", cs->hw.diva.cfg_reg, cs->irq);
-	if (!request_io(&cs->rs, cs->hw.diva.cfg_reg, 8, "diva isdn"))
-		goto err;
-	diva_reset(cs);
-	init_timer(&cs->hw.diva.tl);
-	cs->hw.diva.tl.function = (void *) diva_led_handler;
-	cs->hw.diva.tl.data = (long) cs;
-	cs->card_ops = &diva_ops;
-	if (hscxisac_setup(cs, &isac_ops, &hscx_ops))
-		goto err;
-	return 0;
- err:
-	hisax_release_resources(cs);
-	return -EBUSY;
-}
-
-static int __init
-diva_isa_probe(struct IsdnCardState *cs, struct IsdnCard *card)
-{
-	int is_ipac;
-	cs->hw.diva.cfg_reg  = card->para[1];
-	if (!request_io(&cs->rs, cs->hw.diva.cfg_reg, 8, "diva isdn"))
-		return -EBUSY;
-
-	is_ipac = diva_ipac_probe(cs);
-	hisax_release_resources(cs);
-
-	if (is_ipac)
-		return diva_ipac_isa_probe(cs, card);
-	else
-		return diva_isac_isa_probe(cs, card);
+	if (blink) {
+		init_timer(&cs->hw.diva.tl);
+		cs->hw.diva.tl.expires = jiffies + ((blink * HZ) / 1000);
+		add_timer(&cs->hw.diva.tl);
+	}
 }
 
-static int __init
-diva_pci_probe(struct IsdnCardState *cs, struct pci_dev *pdev)
+static int
+Diva_card_msg(struct IsdnCardState *cs, int mt, void *arg)
 {
-	if (pci_enable_device(pdev))
-		goto err;
+	u_int *ireg;
+	u_long flags;
 
-	cs->subtyp = DIVA_PCI;
-	cs->irq = pdev->irq;
-	cs->irq_flags |= SA_SHIRQ;
-	cs->hw.diva.cfg_reg  = pci_resource_start(pdev, 2);
-	cs->hw.diva.ctrl     = cs->hw.diva.cfg_reg + DIVA_PCI_CTRL;
-	cs->hw.diva.isac     = cs->hw.diva.cfg_reg + DIVA_PCI_ISAC_DATA;
-	cs->hw.diva.hscx     = cs->hw.diva.cfg_reg + DIVA_HSCX_DATA;
-	cs->hw.diva.isac_adr = cs->hw.diva.cfg_reg + DIVA_PCI_ISAC_ADR;
-	cs->hw.diva.hscx_adr = cs->hw.diva.cfg_reg + DIVA_HSCX_ADR;
-	printk(KERN_INFO "Diva: %s card configured at %#lx IRQ %d\n",
-	       "PCI", cs->hw.diva.cfg_reg, cs->irq);
-	printk(KERN_INFO "Diva: %s space at %#lx\n",
-	       "PCI", cs->hw.diva.pci_cfg);
-	if (!request_io(&cs->rs, cs->hw.diva.cfg_reg, 32, "diva isdn"))
-		goto err;
-	return 0;
- err:
-	hisax_release_resources(cs);
-	return -EBUSY;
-}
-
-static int __init
-diva_ipac_pci_probe(struct IsdnCardState *cs, struct pci_dev *pdev)
-{
-	if (pci_enable_device(pdev))
-		goto err;
-
-	cs->subtyp = DIVA_IPAC_PCI;
-	cs->irq = pdev->irq;
-	cs->irq_flags |= SA_SHIRQ;
-	cs->hw.diva.pci_cfg = (unsigned long)request_mmio(
-		&cs->rs, pci_resource_start(pdev, 0), 4096, "diva");
-	cs->hw.diva.cfg_reg = (unsigned long)request_mmio(
-		&cs->rs, pci_resource_start(pdev, 1), 4096, "diva");
-	printk(KERN_INFO "Diva: %s card configured at %#lx IRQ %d\n",
-	       "IPAC PCI", cs->hw.diva.cfg_reg, cs->irq);
-	printk(KERN_INFO "Diva: %s space at %#lx\n",
-	       "IPAC PCI", cs->hw.diva.pci_cfg);
-	diva_ipac_pci_reset(cs);
-	cs->card_ops = &diva_ipac_pci_ops;
-	if (ipac_setup(cs, &mem_ipac_dc_ops, &mem_ipac_bc_ops))
-		goto err;
-	return 0;
- err:
-	hisax_release_resources(cs);
-	return -EBUSY;
-}
-
-static int __init
-diva_ipacx_pci_probe(struct IsdnCardState *cs, struct pci_dev *pdev)
-{
-	if (pci_enable_device(pdev))
-		goto err;
-
-	cs->subtyp = DIVA_IPACX_PCI;
-	cs->irq = pdev->irq;
-	cs->irq_flags |= SA_SHIRQ;
-	printk(KERN_INFO "Diva: %s card configured at %#lx IRQ %d\n",
-	       "IPACX PCI", cs->hw.diva.cfg_reg, cs->irq);
-	printk(KERN_INFO "Diva: %s space at %#lx\n",
-	       "IPACX PCI", cs->hw.diva.pci_cfg);
-	diva_ipacx_pci_reset(cs);
-	cs->card_ops = &diva_ipacx_pci_ops;
-	if (ipacx_setup(cs, &ipacx_dc_ops, &ipacx_bc_ops))
-		goto err;
-	return 0;
- err:
-	hisax_release_resources(cs);
-	return -EBUSY;
+	switch (mt) {
+		case CARD_RESET:
+			spin_lock_irqsave(&cs->lock, flags);
+			reset_diva(cs);
+			spin_unlock_irqrestore(&cs->lock, flags);
+			return(0);
+		case CARD_RELEASE:
+			release_io_diva(cs);
+			return(0);
+		case CARD_INIT:
+			spin_lock_irqsave(&cs->lock, flags);
+			reset_diva(cs);
+			if (cs->subtyp == DIVA_IPACX_PCI) {
+				ireg = (unsigned int *)cs->hw.diva.pci_cfg;
+				*ireg = PITA_INT0_ENABLE;
+				init_ipacx(cs, 3); // init chip and enable interrupts
+				spin_unlock_irqrestore(&cs->lock, flags);
+				return (0);
+			}
+			if (cs->subtyp == DIVA_IPAC_PCI) {
+				ireg = (unsigned int *)cs->hw.diva.pci_cfg;
+				*ireg = PITA_INT0_ENABLE;
+			}
+			inithscxisac(cs, 3);
+			spin_unlock_irqrestore(&cs->lock, flags);
+			return(0);
+		case CARD_TEST:
+			return(0);
+		case (MDL_REMOVE | REQUEST):
+			cs->hw.diva.status = 0;
+			break;
+		case (MDL_ASSIGN | REQUEST):
+			cs->hw.diva.status |= DIVA_ASSIGN;
+			break;
+		case MDL_INFO_SETUP:
+			if ((long)arg)
+				cs->hw.diva.status |=  0x0200;
+			else
+				cs->hw.diva.status |=  0x0100;
+			break;
+		case MDL_INFO_CONN:
+			if ((long)arg)
+				cs->hw.diva.status |=  0x2000;
+			else
+				cs->hw.diva.status |=  0x1000;
+			break;
+		case MDL_INFO_REL:
+			if ((long)arg) {
+				cs->hw.diva.status &=  ~0x2000;
+				cs->hw.diva.status &=  ~0x0200;
+			} else {
+				cs->hw.diva.status &=  ~0x1000;
+				cs->hw.diva.status &=  ~0x0100;
+			}
+			break;
+	}
+	if ((cs->subtyp != DIVA_IPAC_ISA) && 
+	    (cs->subtyp != DIVA_IPAC_PCI) &&
+	    (cs->subtyp != DIVA_IPACX_PCI)) {
+	    	spin_lock_irqsave(&cs->lock, flags);
+		diva_led_handler(cs);
+		spin_unlock_irqrestore(&cs->lock, flags);
+	}
+	return(0);
 }
 
 static struct pci_dev *dev_diva __initdata = NULL;
 static struct pci_dev *dev_diva_u __initdata = NULL;
 static struct pci_dev *dev_diva201 __initdata = NULL;
+static struct pci_dev *dev_diva202 __initdata = NULL;
+
 #ifdef __ISAPNP__
 static struct isapnp_device_id diva_ids[] __initdata = {
 	{ ISAPNP_VENDOR('G', 'D', 'I'), ISAPNP_FUNCTION(0x51),
@@ -700,99 +916,268 @@ static struct isapnp_device_id diva_ids[
 	{ 0, }
 };
 
-static struct isapnp_device_id *pdev = &diva_ids[0];
+static struct isapnp_device_id *ipid __initdata = &diva_ids[0];
 static struct pnp_card *pnp_c __devinitdata = NULL;
 #endif
 
+
 int __init
 setup_diva(struct IsdnCard *card)
 {
+	int bytecnt = 8;
+	u_char val;
+	struct IsdnCardState *cs = card->cs;
 	char tmp[64];
 
 	strcpy(tmp, Diva_revision);
 	printk(KERN_INFO "HiSax: Eicon.Diehl Diva driver Rev. %s\n", HiSax_getrev(tmp));
+	if (cs->typ != ISDN_CTYPE_DIEHLDIVA)
+		return(0);
+	cs->hw.diva.status = 0;
 	if (card->para[1]) {
-		if (diva_isa_probe(card->cs, card) < 0)
-			return 0;
-		return 1;
-		
-	}
+		cs->hw.diva.ctrl_reg = 0;
+		cs->hw.diva.cfg_reg = card->para[1];
+		val = readreg(cs->hw.diva.cfg_reg + DIVA_IPAC_ADR,
+			cs->hw.diva.cfg_reg + DIVA_IPAC_DATA, IPAC_ID);
+		printk(KERN_INFO "Diva: IPAC version %x\n", val);
+		if ((val == 1) || (val==2)) {
+			cs->subtyp = DIVA_IPAC_ISA;
+			cs->hw.diva.ctrl = 0;
+			cs->hw.diva.isac = card->para[1] + DIVA_IPAC_DATA;
+			cs->hw.diva.hscx = card->para[1] + DIVA_IPAC_DATA;
+			cs->hw.diva.isac_adr = card->para[1] + DIVA_IPAC_ADR;
+			cs->hw.diva.hscx_adr = card->para[1] + DIVA_IPAC_ADR;
+			test_and_set_bit(HW_IPAC, &cs->HW_Flags);
+		} else {
+			cs->subtyp = DIVA_ISA;
+			cs->hw.diva.ctrl = card->para[1] + DIVA_ISA_CTRL;
+			cs->hw.diva.isac = card->para[1] + DIVA_ISA_ISAC_DATA;
+			cs->hw.diva.hscx = card->para[1] + DIVA_HSCX_DATA;
+			cs->hw.diva.isac_adr = card->para[1] + DIVA_ISA_ISAC_ADR;
+			cs->hw.diva.hscx_adr = card->para[1] + DIVA_HSCX_ADR;
+		}
+		cs->irq = card->para[0];
+	} else {
 #ifdef __ISAPNP__
-	if (isapnp_present()) {
-		struct pnp_card *pb;
-		struct pnp_dev *pd;
-		
-		while(pdev->card_vendor) {
-			if ((pb = pnp_find_card(pdev->card_vendor,
-						pdev->card_device, pnp_c))) {
-				pnp_c = pb;
-				pd = NULL;
-				if ((pd = pnp_find_dev(pnp_c,
-						       pdev->vendor,
-						       pdev->function,
-						       pd))) {
-					printk(KERN_INFO "HiSax: %s detected\n",
-					       (char *)pdev->driver_data);
-					if (pnp_device_attach(pd) < 0) {
-						printk(KERN_ERR "Diva PnP: attach failed\n");
-						return 0;
-					}
-					if (pnp_activate_dev(pd) < 0) {
-						printk(KERN_ERR "Diva PnP: activate failed\n");
-						pnp_device_detach(pd);
-						return 0;
-					}
-					if (!pnp_irq_valid(pd, 0) || !pnp_port_valid(pd, 0)) {
-						printk(KERN_ERR "Diva PnP:some resources are missing %ld/%lx\n",
-						       pnp_irq(pd, 0), pnp_port_start(pd, 0));
-						pnp_device_detach(pd);
-						return(0);
-					}
-					card->para[1] = pnp_port_start(pd, 0);
-					card->para[0] = pnp_irq(pd, 0);
-					if (pdev->function == ISAPNP_FUNCTION(0xA1)) {
-						if (diva_ipac_isa_probe(card->cs, card))
-							return 0;
-						return 1;
+		if (isapnp_present()) {
+			struct pnp_dev *pnp_d;
+			while(ipid->card_vendor) {
+				if ((pnp_c = pnp_find_card(ipid->card_vendor,
+					ipid->card_device, pnp_c))) {
+					pnp_d = NULL;
+					if ((pnp_d = pnp_find_dev(pnp_c,
+						ipid->vendor, ipid->function, pnp_d))) {
+						int err;
+
+						printk(KERN_INFO "HiSax: %s detected\n",
+							(char *)ipid->driver_data);
+						pnp_disable_dev(pnp_d);
+						err = pnp_activate_dev(pnp_d);
+						if (err<0) {
+							printk(KERN_WARNING "%s: pnp_activate_dev ret(%d)\n",
+								__FUNCTION__, err);
+							return(0);
+						}
+						card->para[1] = pnp_port_start(pnp_d, 0);
+						card->para[0] = pnp_irq(pnp_d, 0);
+						if (!card->para[0] || !card->para[1]) {
+							printk(KERN_ERR "Diva PnP:some resources are missing %ld/%lx\n",
+								card->para[0], card->para[1]);
+							pnp_disable_dev(pnp_d); 
+							return(0);
+						}
+						cs->hw.diva.cfg_reg  = card->para[1];
+						cs->irq = card->para[0];
+						if (ipid->function == ISAPNP_FUNCTION(0xA1)) {
+							cs->subtyp = DIVA_IPAC_ISA;
+							cs->hw.diva.ctrl = 0;
+							cs->hw.diva.isac =
+								card->para[1] + DIVA_IPAC_DATA;
+							cs->hw.diva.hscx =
+								card->para[1] + DIVA_IPAC_DATA;
+							cs->hw.diva.isac_adr =
+								card->para[1] + DIVA_IPAC_ADR;
+							cs->hw.diva.hscx_adr =
+								card->para[1] + DIVA_IPAC_ADR;
+							test_and_set_bit(HW_IPAC, &cs->HW_Flags);
+						} else {
+							cs->subtyp = DIVA_ISA;
+							cs->hw.diva.ctrl =
+								card->para[1] + DIVA_ISA_CTRL;
+							cs->hw.diva.isac =
+								card->para[1] + DIVA_ISA_ISAC_DATA;
+							cs->hw.diva.hscx =
+								card->para[1] + DIVA_HSCX_DATA;
+							cs->hw.diva.isac_adr =
+								card->para[1] + DIVA_ISA_ISAC_ADR;
+							cs->hw.diva.hscx_adr =
+								card->para[1] + DIVA_HSCX_ADR;
+						}
+						goto ready;
 					} else {
-						if (diva_isac_isa_probe(card->cs, card))
-							return 0;
-						return 1;
+						printk(KERN_ERR "Diva PnP: PnP error card found, no device\n");
+						return(0);
 					}
-				} else {
-					printk(KERN_ERR "Diva PnP: PnP error card found, no device\n");
-					return(0);
 				}
-				pdev++;
+				ipid++;
 				pnp_c=NULL;
 			} 
-			if (!pdev->card_vendor) {
+			if (!ipid->card_vendor) {
 				printk(KERN_INFO "Diva PnP: no ISAPnP card found\n");
 			}
 		}
-	}
 #endif
-#ifdef CONFIG_PCI
-	if ((dev_diva = pci_find_device(PCI_VENDOR_ID_EICON,
-					PCI_DEVICE_ID_EICON_DIVA20,
-					dev_diva))) {
-		if (diva_pci_probe(card->cs, dev_diva))
-			return 0;
-		return 1;
-	} else if ((dev_diva_u = pci_find_device(PCI_VENDOR_ID_EICON,
-						 PCI_DEVICE_ID_EICON_DIVA20_U,
-						 dev_diva_u))) {
-		if (diva_pci_probe(card->cs, dev_diva_u))
-			return 0;
-		return 1;
-	} else if ((dev_diva201 = pci_find_device(PCI_VENDOR_ID_EICON,
-						  PCI_DEVICE_ID_EICON_DIVA201,
-						  dev_diva201))) {
-		if (diva_ipac_pci_probe(card->cs, dev_diva201))
-			return 0;
-		return 1;
-	}
-	printk(KERN_WARNING "Diva: No PCI card found\n");
+#if CONFIG_PCI
+		cs->subtyp = 0;
+		if ((dev_diva = pci_find_device(PCI_VENDOR_ID_EICON,
+			PCI_DEVICE_ID_EICON_DIVA20, dev_diva))) {
+			if (pci_enable_device(dev_diva))
+				return(0);
+			cs->subtyp = DIVA_PCI;
+			cs->irq = dev_diva->irq;
+			cs->hw.diva.cfg_reg = pci_resource_start(dev_diva, 2);
+		} else if ((dev_diva_u = pci_find_device(PCI_VENDOR_ID_EICON,
+			PCI_DEVICE_ID_EICON_DIVA20_U, dev_diva_u))) {
+			if (pci_enable_device(dev_diva_u))
+				return(0);
+			cs->subtyp = DIVA_PCI;
+			cs->irq = dev_diva_u->irq;
+			cs->hw.diva.cfg_reg = pci_resource_start(dev_diva_u, 2);
+		} else if ((dev_diva201 = pci_find_device(PCI_VENDOR_ID_EICON,
+			PCI_DEVICE_ID_EICON_DIVA201, dev_diva201))) {
+			if (pci_enable_device(dev_diva201))
+				return(0);
+			cs->subtyp = DIVA_IPAC_PCI;
+			cs->irq = dev_diva201->irq;
+			cs->hw.diva.pci_cfg =
+				(ulong) ioremap(pci_resource_start(dev_diva201, 0), 4096);
+			cs->hw.diva.cfg_reg =
+				(ulong) ioremap(pci_resource_start(dev_diva201, 1), 4096);
+		} else if ((dev_diva202 = pci_find_device(PCI_VENDOR_ID_EICON,
+			PCI_DEVICE_ID_EICON_DIVA202, dev_diva202))) {
+			if (pci_enable_device(dev_diva202))
+				return(0);
+			cs->subtyp = DIVA_IPACX_PCI;
+			cs->irq = dev_diva202->irq;
+			cs->hw.diva.pci_cfg =
+				(ulong) ioremap(pci_resource_start(dev_diva202, 0), 4096);
+			cs->hw.diva.cfg_reg =
+				(ulong) ioremap(pci_resource_start(dev_diva202, 1), 4096);
+		} else {
+			printk(KERN_WARNING "Diva: No PCI card found\n");
+			return(0);
+		}
+
+		if (!cs->irq) {
+			printk(KERN_WARNING "Diva: No IRQ for PCI card found\n");
+			return(0);
+		}
+
+		if (!cs->hw.diva.cfg_reg) {
+			printk(KERN_WARNING "Diva: No IO-Adr for PCI card found\n");
+			return(0);
+		}
+		cs->irq_flags |= SA_SHIRQ;
+#else
+		printk(KERN_WARNING "Diva: cfgreg 0 and NO_PCI_BIOS\n");
+		printk(KERN_WARNING "Diva: unable to config DIVA PCI\n");
+		return (0);
 #endif /* CONFIG_PCI */
-	return 0;
+		if ((cs->subtyp == DIVA_IPAC_PCI) ||
+		    (cs->subtyp == DIVA_IPACX_PCI)   ) {
+			cs->hw.diva.ctrl = 0;
+			cs->hw.diva.isac = 0;
+			cs->hw.diva.hscx = 0;
+			cs->hw.diva.isac_adr = 0;
+			cs->hw.diva.hscx_adr = 0;
+			test_and_set_bit(HW_IPAC, &cs->HW_Flags);
+			bytecnt = 0;
+		} else {
+			cs->hw.diva.ctrl = cs->hw.diva.cfg_reg + DIVA_PCI_CTRL;
+			cs->hw.diva.isac = cs->hw.diva.cfg_reg + DIVA_PCI_ISAC_DATA;
+			cs->hw.diva.hscx = cs->hw.diva.cfg_reg + DIVA_HSCX_DATA;
+			cs->hw.diva.isac_adr = cs->hw.diva.cfg_reg + DIVA_PCI_ISAC_ADR;
+			cs->hw.diva.hscx_adr = cs->hw.diva.cfg_reg + DIVA_HSCX_ADR;
+			bytecnt = 32;
+		}
+	}
+ready:
+	printk(KERN_INFO
+		"Diva: %s card configured at %#lx IRQ %d\n",
+		(cs->subtyp == DIVA_PCI) ? "PCI" :
+		(cs->subtyp == DIVA_ISA) ? "ISA" : 
+		(cs->subtyp == DIVA_IPAC_ISA) ? "IPAC ISA" :
+		(cs->subtyp == DIVA_IPAC_PCI) ? "IPAC PCI" : "IPACX PCI",
+		cs->hw.diva.cfg_reg, cs->irq);
+	if ((cs->subtyp == DIVA_IPAC_PCI)  || 
+	    (cs->subtyp == DIVA_IPACX_PCI) || 
+	    (cs->subtyp == DIVA_PCI)         )
+		printk(KERN_INFO "Diva: %s space at %#lx\n",
+			(cs->subtyp == DIVA_PCI) ? "PCI" :
+			(cs->subtyp == DIVA_IPAC_PCI) ? "IPAC PCI" : "IPACX PCI",
+			cs->hw.diva.pci_cfg);
+	if ((cs->subtyp != DIVA_IPAC_PCI) &&
+	    (cs->subtyp != DIVA_IPACX_PCI)   ) {
+		if (!request_region(cs->hw.diva.cfg_reg, bytecnt, "diva isdn")) {
+			printk(KERN_WARNING
+			       "HiSax: %s config port %lx-%lx already in use\n",
+			       CardType[card->typ],
+			       cs->hw.diva.cfg_reg,
+			       cs->hw.diva.cfg_reg + bytecnt);
+			return (0);
+		}
+	}
+	cs->BC_Read_Reg  = &ReadHSCX;
+	cs->BC_Write_Reg = &WriteHSCX;
+	cs->BC_Send_Data = &hscx_fill_fifo;
+	cs->cardmsg = &Diva_card_msg;
+	setup_isac(cs);
+	if (cs->subtyp == DIVA_IPAC_ISA) {
+		cs->readisac  = &ReadISAC_IPAC;
+		cs->writeisac = &WriteISAC_IPAC;
+		cs->readisacfifo  = &ReadISACfifo_IPAC;
+		cs->writeisacfifo = &WriteISACfifo_IPAC;
+		cs->irq_func = &diva_irq_ipac_isa;
+		val = readreg(cs->hw.diva.isac_adr, cs->hw.diva.isac, IPAC_ID);
+		printk(KERN_INFO "Diva: IPAC version %x\n", val);
+	} else if (cs->subtyp == DIVA_IPAC_PCI) {
+		cs->readisac  = &MemReadISAC_IPAC;
+		cs->writeisac = &MemWriteISAC_IPAC;
+		cs->readisacfifo  = &MemReadISACfifo_IPAC;
+		cs->writeisacfifo = &MemWriteISACfifo_IPAC;
+		cs->BC_Read_Reg  = &MemReadHSCX;
+		cs->BC_Write_Reg = &MemWriteHSCX;
+		cs->BC_Send_Data = &Memhscx_fill_fifo;
+		cs->irq_func = &diva_irq_ipac_pci;
+		val = memreadreg(cs->hw.diva.cfg_reg, IPAC_ID);
+		printk(KERN_INFO "Diva: IPAC version %x\n", val);
+	} else if (cs->subtyp == DIVA_IPACX_PCI) {
+		cs->readisac  = &MemReadISAC_IPACX;
+		cs->writeisac = &MemWriteISAC_IPACX;
+		cs->readisacfifo  = &MemReadISACfifo_IPACX;
+		cs->writeisacfifo = &MemWriteISACfifo_IPACX;
+		cs->BC_Read_Reg  = &MemReadHSCX_IPACX;
+		cs->BC_Write_Reg = &MemWriteHSCX_IPACX;
+		cs->BC_Send_Data = 0; // function located in ipacx module
+		cs->irq_func = &diva_irq_ipacx_pci;
+		printk(KERN_INFO "Diva: IPACX Design Id: %x\n", 
+			MemReadISAC_IPACX(cs, IPACX_ID) &0x3F);
+	} else { /* DIVA 2.0 */
+		cs->hw.diva.tl.function = (void *) diva_led_handler;
+		cs->hw.diva.tl.data = (long) cs;
+		init_timer(&cs->hw.diva.tl);
+		cs->readisac  = &ReadISAC;
+		cs->writeisac = &WriteISAC;
+		cs->readisacfifo  = &ReadISACfifo;
+		cs->writeisacfifo = &WriteISACfifo;
+		cs->irq_func = &diva_interrupt;
+		ISACVersion(cs, "Diva:");
+		if (HscxVersion(cs, "Diva:")) {
+			printk(KERN_WARNING
+		       "Diva: wrong HSCX versions check IO address\n");
+			release_io_diva(cs);
+			return (0);
+		}
+	}
+	return (1);
 }
--- diff/drivers/isdn/hisax/elsa.c	2003-09-17 12:28:06.000000000 +0100
+++ source/drivers/isdn/hisax/elsa.c	2004-02-23 13:56:42.000000000 +0000
@@ -1,4 +1,4 @@
-/* $Id: elsa.c,v 2.26.6.6 2001/09/23 22:24:47 kai Exp $
+/* $Id: elsa.c,v 2.32.2.4 2004/01/24 20:47:21 keil Exp $
  *
  * low level stuff for Elsa isdn cards
  *
@@ -32,9 +32,8 @@
 #include <linux/serial_reg.h>
 
 extern const char *CardType[];
-static spinlock_t elsa_lock = SPIN_LOCK_UNLOCKED;
 
-const char *Elsa_revision = "$Revision: 2.26.6.6 $";
+const char *Elsa_revision = "$Revision: 2.32.2.4 $";
 const char *Elsa_Types[] =
 {"None", "PC", "PCC-8", "PCC-16", "PCF", "PCF-Pro",
  "PCMCIA", "QS 1000", "QS 3000", "Microlink PCI", "QS 3000 PCI", 
@@ -106,6 +105,7 @@ const char *ITACVer[] =
 /* Status Flags */
 #define ELSA_TIMER_AKTIV 1
 #define ELSA_BAD_PWR     2
+#define ELSA_ASSIGN      4
 
 #define RS_ISR_PASS_LIMIT 256
 #define _INLINE_ inline
@@ -141,163 +141,123 @@ static void set_arcofi(struct IsdnCardSt
 #include "elsa_ser.c"
 #endif /* ARCOFI_USE */
 
-static inline u8
-readreg(struct IsdnCardState *cs, unsigned int adr, u8 off)
+static inline u_char
+readreg(unsigned int ale, unsigned int adr, u_char off)
 {
-	u8 ret;
-	unsigned long flags;
+	register u_char ret;
 
-	spin_lock_irqsave(&elsa_lock, flags);
-	byteout(cs->hw.elsa.ale, off);
+	byteout(ale, off);
 	ret = bytein(adr);
-	spin_unlock_irqrestore(&elsa_lock, flags);
-	return ret;
+	return (ret);
 }
 
 static inline void
-writereg(struct IsdnCardState *cs, unsigned int adr, u8 off, u8 data)
+readfifo(unsigned int ale, unsigned int adr, u_char off, u_char * data, int size)
 {
-	unsigned long flags;
-
-	spin_lock_irqsave(&elsa_lock, flags);
-	byteout(cs->hw.elsa.ale, off);
-	byteout(adr, data);
-	spin_unlock_irqrestore(&elsa_lock, flags);
+	byteout(ale, off);
+	insb(adr, data, size);
 }
 
+
 static inline void
-readfifo(struct IsdnCardState *cs, unsigned int adr, u8 off, u8 * data, int size)
+writereg(unsigned int ale, unsigned int adr, u_char off, u_char data)
 {
-	byteout(cs->hw.elsa.ale, off);
-	insb(adr, data, size);
+	byteout(ale, off);
+	byteout(adr, data);
 }
 
 static inline void
-writefifo(struct IsdnCardState *cs, unsigned int adr, u8 off, u8 * data, int size)
+writefifo(unsigned int ale, unsigned int adr, u_char off, u_char * data, int size)
 {
-	byteout(cs->hw.elsa.ale, off);
+	byteout(ale, off);
 	outsb(adr, data, size);
 }
 
-static u8
-isac_read(struct IsdnCardState *cs, u8 offset)
+/* Interface functions */
+
+static u_char
+ReadISAC(struct IsdnCardState *cs, u_char offset)
 {
-	return readreg(cs, cs->hw.elsa.isac, offset);
+	return (readreg(cs->hw.elsa.ale, cs->hw.elsa.isac, offset));
 }
 
 static void
-isac_write(struct IsdnCardState *cs, u8 offset, u8 value)
+WriteISAC(struct IsdnCardState *cs, u_char offset, u_char value)
 {
-	writereg(cs, cs->hw.elsa.isac, offset, value);
+	writereg(cs->hw.elsa.ale, cs->hw.elsa.isac, offset, value);
 }
 
 static void
-isac_read_fifo(struct IsdnCardState *cs, u8 *data, int size)
+ReadISACfifo(struct IsdnCardState *cs, u_char * data, int size)
 {
-	readfifo(cs, cs->hw.elsa.isac, 0, data, size);
+	readfifo(cs->hw.elsa.ale, cs->hw.elsa.isac, 0, data, size);
 }
 
 static void
-isac_write_fifo(struct IsdnCardState *cs, u8 *data, int size)
+WriteISACfifo(struct IsdnCardState *cs, u_char * data, int size)
 {
-	writefifo(cs, cs->hw.elsa.isac, 0, data, size);
+	writefifo(cs->hw.elsa.ale, cs->hw.elsa.isac, 0, data, size);
 }
 
-static struct dc_hw_ops isac_ops = {
-	.read_reg   = isac_read,
-	.write_reg  = isac_write,
-	.read_fifo  = isac_read_fifo,
-	.write_fifo = isac_write_fifo,
-};
-
-static u8
-hscx_read(struct IsdnCardState *cs, int hscx, u8 offset)
+static u_char
+ReadISAC_IPAC(struct IsdnCardState *cs, u_char offset)
 {
-	return readreg(cs, cs->hw.elsa.hscx, offset + (hscx ? 0x40 : 0));
+	return (readreg(cs->hw.elsa.ale, cs->hw.elsa.isac, offset+0x80));
 }
 
 static void
-hscx_write(struct IsdnCardState *cs, int hscx, u8 offset, u8 value)
+WriteISAC_IPAC(struct IsdnCardState *cs, u_char offset, u_char value)
 {
-	writereg(cs, cs->hw.elsa.hscx, offset + (hscx ? 0x40 : 0), value);
+	writereg(cs->hw.elsa.ale, cs->hw.elsa.isac, offset|0x80, value);
 }
 
 static void
-hscx_read_fifo(struct IsdnCardState *cs, int hscx, u8 *data, int size)
+ReadISACfifo_IPAC(struct IsdnCardState *cs, u_char * data, int size)
 {
-	writefifo(cs, cs->hw.elsa.hscx, hscx ? 0x40 : 0, data, size);
+	readfifo(cs->hw.elsa.ale, cs->hw.elsa.isac, 0x80, data, size);
 }
 
 static void
-hscx_write_fifo(struct IsdnCardState *cs, int hscx, u8 *data, int size)
-{
-	writefifo(cs, cs->hw.elsa.hscx, hscx ? 0x40 : 0, data, size);
-}
-
-static struct bc_hw_ops hscx_ops = {
-	.read_reg   = hscx_read,
-	.write_reg  = hscx_write,
-	.read_fifo  = hscx_read_fifo,
-	.write_fifo = hscx_write_fifo,
-};
-
-static inline u8
-ipac_read(struct IsdnCardState *cs, u8 offset)
-{
-	return readreg(cs, cs->hw.elsa.isac, offset);
-}
-
-static inline void
-ipac_write(struct IsdnCardState *cs, u8 offset, u8 value)
+WriteISACfifo_IPAC(struct IsdnCardState *cs, u_char * data, int size)
 {
-	writereg(cs, cs->hw.elsa.isac, offset, value);
+	writefifo(cs->hw.elsa.ale, cs->hw.elsa.isac, 0x80, data, size);
 }
 
-static inline void
-ipac_readfifo(struct IsdnCardState *cs, u8 offset, u8 *data, int size)
+static u_char
+ReadHSCX(struct IsdnCardState *cs, int hscx, u_char offset)
 {
-	readfifo(cs, cs->hw.elsa.isac, offset, data, size);
+	return (readreg(cs->hw.elsa.ale,
+			cs->hw.elsa.hscx, offset + (hscx ? 0x40 : 0)));
 }
 
-static inline void
-ipac_writefifo(struct IsdnCardState *cs, u8 offset, u8 *data, int size)
+static void
+WriteHSCX(struct IsdnCardState *cs, int hscx, u_char offset, u_char value)
 {
-	writefifo(cs, cs->hw.elsa.isac, offset, data, size);
+	writereg(cs->hw.elsa.ale,
+		 cs->hw.elsa.hscx, offset + (hscx ? 0x40 : 0), value);
 }
 
-/* This will generate ipac_dc_ops and ipac_bc_ops using the functions
- * above */
-
-BUILD_IPAC_OPS(ipac);
-
-static inline u8
-readitac(struct IsdnCardState *cs, u8 off)
+static inline u_char
+readitac(struct IsdnCardState *cs, u_char off)
 {
-	u8 ret;
-	unsigned long flags;
+	register u_char ret;
 
-	spin_lock_irqsave(&elsa_lock, flags);
 	byteout(cs->hw.elsa.ale, off);
 	ret = bytein(cs->hw.elsa.itac);
-	spin_unlock_irqrestore(&elsa_lock, flags);
-	return ret;
+	return (ret);
 }
 
 static inline void
-writeitac(struct IsdnCardState *cs, u8 off, u8 data)
+writeitac(struct IsdnCardState *cs, u_char off, u_char data)
 {
-	unsigned long flags;
-
-	spin_lock_irqsave(&elsa_lock, flags);
 	byteout(cs->hw.elsa.ale, off);
 	byteout(cs->hw.elsa.itac, data);
-	spin_unlock_irqrestore(&elsa_lock, flags);
 }
 
 static inline int
 TimerRun(struct IsdnCardState *cs)
 {
-	register u8 v;
+	register u_char v;
 
 	v = bytein(cs->hw.elsa.cfg);
 	if ((cs->subtyp == ELSA_QS1000) || (cs->subtyp == ELSA_QS3000))
@@ -306,12 +266,30 @@ TimerRun(struct IsdnCardState *cs)
 		return (v & ELSA_TIMER_RUN_PCC8);
 	return (v & ELSA_TIMER_RUN);
 }
+/*
+ * fast interrupt HSCX stuff goes here
+ */
+
+#define READHSCX(cs, nr, reg) readreg(cs->hw.elsa.ale, \
+		cs->hw.elsa.hscx, reg + (nr ? 0x40 : 0))
+#define WRITEHSCX(cs, nr, reg, data) writereg(cs->hw.elsa.ale, \
+		cs->hw.elsa.hscx, reg + (nr ? 0x40 : 0), data)
+
+#define READHSCXFIFO(cs, nr, ptr, cnt) readfifo(cs->hw.elsa.ale, \
+		cs->hw.elsa.hscx, (nr ? 0x40 : 0), ptr, cnt)
+
+#define WRITEHSCXFIFO(cs, nr, ptr, cnt) writefifo(cs->hw.elsa.ale, \
+		cs->hw.elsa.hscx, (nr ? 0x40 : 0), ptr, cnt)
+
+#include "hscx_irq.c"
 
 static irqreturn_t
 elsa_interrupt(int intno, void *dev_id, struct pt_regs *regs)
 {
 	struct IsdnCardState *cs = dev_id;
-	u8 val;
+	u_long flags;
+	u_char val;
+	int icnt=5;
 
 	if ((cs->typ == ISDN_CTYPE_ELSA_PCMCIA) && (*cs->busy_flag == 1)) {
 	/* The card tends to generate interrupts while being removed
@@ -319,19 +297,45 @@ elsa_interrupt(int intno, void *dev_id, 
 		printk(KERN_WARNING "Elsa: card not available!\n");
 		return IRQ_NONE;
 	}
+	spin_lock_irqsave(&cs->lock, flags);
 #if ARCOFI_USE
 	if (cs->hw.elsa.MFlag) {
 		val = serial_inp(cs, UART_IIR);
 		if (!(val & UART_IIR_NO_INT)) {
 			debugl1(cs,"IIR %02x", val);
-			spin_lock(&cs->lock);
 			rs_interrupt_elsa(intno, cs);
-			spin_unlock(&cs->lock);
 		}
 	}
 #endif
-	hscxisac_irq(intno, dev_id, regs);
-
+	val = readreg(cs->hw.elsa.ale, cs->hw.elsa.hscx, HSCX_ISTA + 0x40);
+      Start_HSCX:
+	if (val) {
+		hscx_int_main(cs, val);
+	}
+	val = readreg(cs->hw.elsa.ale, cs->hw.elsa.isac, ISAC_ISTA);
+      Start_ISAC:
+	if (val) {
+		isac_interrupt(cs, val);
+	}
+	val = readreg(cs->hw.elsa.ale, cs->hw.elsa.hscx, HSCX_ISTA + 0x40);
+	if (val && icnt) {
+		if (cs->debug & L1_DEB_HSCX)
+			debugl1(cs, "HSCX IntStat after IntRoutine");
+		icnt--;
+		goto Start_HSCX;
+	}
+	val = readreg(cs->hw.elsa.ale, cs->hw.elsa.isac, ISAC_ISTA);
+	if (val && icnt) {
+		if (cs->debug & L1_DEB_ISAC)
+			debugl1(cs, "ISAC IntStat after IntRoutine");
+		icnt--;
+		goto Start_ISAC;
+	}
+	if (!icnt)
+		printk(KERN_WARNING"ELSA IRQ LOOP\n");
+	writereg(cs->hw.elsa.ale, cs->hw.elsa.hscx, HSCX_MASK, 0xFF);
+	writereg(cs->hw.elsa.ale, cs->hw.elsa.hscx, HSCX_MASK + 0x40, 0xFF);
+	writereg(cs->hw.elsa.ale, cs->hw.elsa.isac, ISAC_MASK, 0xFF);
 	if (cs->hw.elsa.status & ELSA_TIMER_AKTIV) {
 		if (!TimerRun(cs)) {
 			/* Timer Restart */
@@ -351,6 +355,10 @@ elsa_interrupt(int intno, void *dev_id, 
 #endif
 	if (cs->hw.elsa.trig)
 		byteout(cs->hw.elsa.trig, 0x00);
+	writereg(cs->hw.elsa.ale, cs->hw.elsa.hscx, HSCX_MASK, 0x0);
+	writereg(cs->hw.elsa.ale, cs->hw.elsa.hscx, HSCX_MASK + 0x40, 0x0);
+	writereg(cs->hw.elsa.ale, cs->hw.elsa.isac, ISAC_MASK, 0x0);
+	spin_unlock_irqrestore(&cs->lock, flags);
 	return IRQ_HANDLED;
 }
 
@@ -358,35 +366,70 @@ static irqreturn_t
 elsa_interrupt_ipac(int intno, void *dev_id, struct pt_regs *regs)
 {
 	struct IsdnCardState *cs = dev_id;
-	u8 val;
+	u_long flags;
+	u_char ista,val;
+	int icnt=5;
 
-	if (!cs) {
-		printk(KERN_WARNING "Elsa: Spurious interrupt!\n");
-		return IRQ_NONE;
-	}
+	spin_lock_irqsave(&cs->lock, flags);
 	if (cs->subtyp == ELSA_QS1000PCI || cs->subtyp == ELSA_QS3000PCI) {
 		val = bytein(cs->hw.elsa.cfg + 0x4c); /* PCI IRQ */
-		if (!test_bit(FLG_BUGGY_PLX9050, &cs->HW_Flags) && 
-		    !(val & ELSA_PCI_IRQ_MASK))
+		if (!(val & ELSA_PCI_IRQ_MASK)) {
+			spin_unlock_irqrestore(&cs->lock, flags);
 			return IRQ_NONE;
+		}
 	}
 #if ARCOFI_USE
 	if (cs->hw.elsa.MFlag) {
 		val = serial_inp(cs, UART_IIR);
 		if (!(val & UART_IIR_NO_INT)) {
 			debugl1(cs,"IIR %02x", val);
-			spin_lock(&cs->lock);
 			rs_interrupt_elsa(intno, cs);
-			spin_unlock(&cs->lock);
 		}
 	}
 #endif
-	return ipac_irq(intno, dev_id, regs);
+	ista = readreg(cs->hw.elsa.ale, cs->hw.elsa.isac, IPAC_ISTA);
+Start_IPAC:
+	if (cs->debug & L1_DEB_IPAC)
+		debugl1(cs, "IPAC ISTA %02X", ista);
+	if (ista & 0x0f) {
+		val = readreg(cs->hw.elsa.ale, cs->hw.elsa.hscx, HSCX_ISTA + 0x40);
+		if (ista & 0x01)
+			val |= 0x01;
+		if (ista & 0x04)
+			val |= 0x02;
+		if (ista & 0x08)
+			val |= 0x04;
+		if (val)
+			hscx_int_main(cs, val);
+	}
+	if (ista & 0x20) {
+		val = 0xfe & readreg(cs->hw.elsa.ale, cs->hw.elsa.isac, ISAC_ISTA + 0x80);
+		if (val) {
+			isac_interrupt(cs, val);
+		}
+	}
+	if (ista & 0x10) {
+		val = 0x01;
+		isac_interrupt(cs, val);
+	}
+	ista  = readreg(cs->hw.elsa.ale, cs->hw.elsa.isac, IPAC_ISTA);
+	if ((ista & 0x3f) && icnt) {
+		icnt--;
+		goto Start_IPAC;
+	}
+	if (!icnt)
+		printk(KERN_WARNING "ELSA IRQ LOOP\n");
+	writereg(cs->hw.elsa.ale, cs->hw.elsa.isac, IPAC_MASK, 0xFF);
+	writereg(cs->hw.elsa.ale, cs->hw.elsa.isac, IPAC_MASK, 0xC0);
+	spin_unlock_irqrestore(&cs->lock, flags);
+	return IRQ_HANDLED;
 }
 
-static void
-elsa_release(struct IsdnCardState *cs)
+void
+release_io_elsa(struct IsdnCardState *cs)
 {
+	int bytecnt = 8;
+
 	del_timer(&cs->hw.elsa.tl);
 #if ARCOFI_USE
 	clear_arcofi(cs);
@@ -395,28 +438,33 @@ elsa_release(struct IsdnCardState *cs)
 		byteout(cs->hw.elsa.ctrl, 0);	/* LEDs Out */
 	if (cs->subtyp == ELSA_QS1000PCI) {
 		byteout(cs->hw.elsa.cfg + 0x4c, 0x01);  /* disable IRQ */
-		writereg(cs, cs->hw.elsa.isac, IPAC_ATX, 0xff);
+		writereg(cs->hw.elsa.ale, cs->hw.elsa.isac, IPAC_ATX, 0xff);
+		bytecnt = 2;
+		release_region(cs->hw.elsa.cfg, 0x80);
 	}
 	if (cs->subtyp == ELSA_QS3000PCI) {
 		byteout(cs->hw.elsa.cfg + 0x4c, 0x03); /* disable ELSA PCI IRQ */
-		writereg(cs, cs->hw.elsa.isac, IPAC_ATX, 0xff);
+		writereg(cs->hw.elsa.ale, cs->hw.elsa.isac, IPAC_ATX, 0xff);
+		release_region(cs->hw.elsa.cfg, 0x80);
 	}
  	if (cs->subtyp == ELSA_PCMCIA_IPAC) {
-		writereg(cs, cs->hw.elsa.isac, IPAC_ATX, 0xff);
+		writereg(cs->hw.elsa.ale, cs->hw.elsa.isac, IPAC_ATX, 0xff);
  	}
-#if ARCOFI_USE
 	if ((cs->subtyp == ELSA_PCFPRO) ||
 		(cs->subtyp == ELSA_QS3000) ||
 		(cs->subtyp == ELSA_PCF) ||
 		(cs->subtyp == ELSA_QS3000PCI)) {
+		bytecnt = 16;
+#if ARCOFI_USE
 		release_modem(cs);
-	}
 #endif
-	hisax_release_resources(cs);
+	}
+	if (cs->hw.elsa.base)
+		release_region(cs->hw.elsa.base, bytecnt);
 }
 
-static int
-elsa_reset(struct IsdnCardState *cs)
+static void
+reset_elsa(struct IsdnCardState *cs)
 {
 	if (cs->hw.elsa.timer) {
 		/* Wait 1 Timer */
@@ -437,28 +485,25 @@ elsa_reset(struct IsdnCardState *cs)
 			byteout(cs->hw.elsa.trig, 0xff);
 	}
 	if ((cs->subtyp == ELSA_QS1000PCI) || (cs->subtyp == ELSA_QS3000PCI) || (cs->subtyp == ELSA_PCMCIA_IPAC)) {
-		writereg(cs, cs->hw.elsa.isac, IPAC_POTA2, 0x20);
-		set_current_state(TASK_UNINTERRUPTIBLE);
-		schedule_timeout((10*HZ)/1000); /* Timeout 10ms */
-		writereg(cs, cs->hw.elsa.isac, IPAC_POTA2, 0x00);
-		set_current_state(TASK_UNINTERRUPTIBLE);
-		writereg(cs, cs->hw.elsa.isac, IPAC_MASK, 0xc0);
-		schedule_timeout((10*HZ)/1000); /* Timeout 10ms */
+		writereg(cs->hw.elsa.ale, cs->hw.elsa.isac, IPAC_POTA2, 0x20);
+		mdelay(10);
+		writereg(cs->hw.elsa.ale, cs->hw.elsa.isac, IPAC_POTA2, 0x00);
+		writereg(cs->hw.elsa.ale, cs->hw.elsa.isac, IPAC_MASK, 0xc0);
+		mdelay(10);
 		if (cs->subtyp != ELSA_PCMCIA_IPAC) {
-			writereg(cs, cs->hw.elsa.isac, IPAC_ACFG, 0x0);
-			writereg(cs, cs->hw.elsa.isac, IPAC_AOE, 0x3c);
+			writereg(cs->hw.elsa.ale, cs->hw.elsa.isac, IPAC_ACFG, 0x0);
+			writereg(cs->hw.elsa.ale, cs->hw.elsa.isac, IPAC_AOE, 0x3c);
 		} else {
-			writereg(cs, cs->hw.elsa.isac, IPAC_PCFG, 0x10);
-			writereg(cs, cs->hw.elsa.isac, IPAC_ACFG, 0x4);
-			writereg(cs, cs->hw.elsa.isac, IPAC_AOE, 0xf8);
+			writereg(cs->hw.elsa.ale, cs->hw.elsa.isac, IPAC_PCFG, 0x10);
+			writereg(cs->hw.elsa.ale, cs->hw.elsa.isac, IPAC_ACFG, 0x4);
+			writereg(cs->hw.elsa.ale, cs->hw.elsa.isac, IPAC_AOE, 0xf8);
 		}
-		writereg(cs, cs->hw.elsa.isac, IPAC_ATX, 0xff);
+		writereg(cs->hw.elsa.ale, cs->hw.elsa.isac, IPAC_ATX, 0xff);
 		if (cs->subtyp == ELSA_QS1000PCI)
 			byteout(cs->hw.elsa.cfg + 0x4c, 0x41); /* enable ELSA PCI IRQ */
 		else if (cs->subtyp == ELSA_QS3000PCI)
 			byteout(cs->hw.elsa.cfg + 0x4c, 0x43); /* enable ELSA PCI IRQ */
 	}
-	return 0;
 }
 
 #if ARCOFI_USE
@@ -476,7 +521,7 @@ check_arcofi(struct IsdnCardState *cs)
 	int arcofi_present = 0;
 	char tmp[40];
 	char *t;
-	u8 *p;
+	u_char *p;
 
 	if (!cs->dc.isac.mon_tx)
 		if (!(cs->dc.isac.mon_tx=kmalloc(MAX_MON_FRAME, GFP_ATOMIC))) {
@@ -525,14 +570,28 @@ check_arcofi(struct IsdnCardState *cs)
 				"Elsa: %s detected modem at 0x%lx\n",
 				Elsa_Types[cs->subtyp],
 				cs->hw.elsa.base+8);
-			request_io(&cs->rs, cs->hw.elsa.base+8, 8, "elsa isdn modem");
+			release_region(cs->hw.elsa.base, 8);
+			if (!request_region(cs->hw.elsa.base, 16, "elsa isdn modem")) {
+				printk(KERN_WARNING
+					"HiSax: %s config port %lx-%lx already in use\n",
+					Elsa_Types[cs->subtyp],
+					cs->hw.elsa.base + 8,
+					cs->hw.elsa.base + 16);
+			}
 		} else if (cs->subtyp==ELSA_PCC16) {
 			cs->subtyp = ELSA_PCF;
 			printk(KERN_INFO
 				"Elsa: %s detected modem at 0x%lx\n",
 				Elsa_Types[cs->subtyp],
 				cs->hw.elsa.base+8);
-			request_io(&cs->rs, cs->hw.elsa.base+8, 8, "elsa isdn modem");
+			release_region(cs->hw.elsa.base, 8);
+			if (!request_region(cs->hw.elsa.base, 16, "elsa isdn modem")) {
+				printk(KERN_WARNING
+					"HiSax: %s config port %lx-%lx already in use\n",
+					Elsa_Types[cs->subtyp],
+					cs->hw.elsa.base + 8,
+					cs->hw.elsa.base + 16);
+			}
 		} else
 			printk(KERN_INFO
 				"Elsa: %s detected modem at 0x%lx\n",
@@ -553,15 +612,8 @@ elsa_led_handler(struct IsdnCardState *c
 
 	if (cs->subtyp == ELSA_PCMCIA || cs->subtyp == ELSA_PCMCIA_IPAC)
 		return;
-
-	if (cs->typ == ISDN_CTYPE_ELSA) {
-		int pwr = bytein(cs->hw.elsa.ale);
-		if (pwr & 0x08)
-			cs->hw.elsa.status |= ELSA_BAD_PWR;
-		else
-			cs->hw.elsa.status &= ~ELSA_BAD_PWR;
-	}
-	if (cs->status & 0x0001)
+	del_timer(&cs->hw.elsa.tl);
+	if (cs->hw.elsa.status & ELSA_ASSIGN)
 		cs->hw.elsa.ctrl_reg |= ELSA_STAT_LED;
 	else if (cs->hw.elsa.status & ELSA_BAD_PWR)
 		cs->hw.elsa.ctrl_reg &= ~ELSA_STAT_LED;
@@ -569,9 +621,9 @@ elsa_led_handler(struct IsdnCardState *c
 		cs->hw.elsa.ctrl_reg ^= ELSA_STAT_LED;
 		blink = 250;
 	}
-	if (cs->status & 0xf000)
+	if (cs->hw.elsa.status & 0xf000)
 		cs->hw.elsa.ctrl_reg |= ELSA_LINE_LED;
-	else if (cs->status & 0x0f00) {
+	else if (cs->hw.elsa.status & 0x0f00) {
 		cs->hw.elsa.ctrl_reg ^= ELSA_LINE_LED;
 		blink = 500;
 	} else
@@ -579,159 +631,148 @@ elsa_led_handler(struct IsdnCardState *c
 
 	if ((cs->subtyp == ELSA_QS1000PCI) ||
 		(cs->subtyp == ELSA_QS3000PCI)) {
-		u8 led = 0xff;
+		u_char led = 0xff;
 		if (cs->hw.elsa.ctrl_reg & ELSA_LINE_LED)
 			led ^= ELSA_IPAC_LINE_LED;
 		if (cs->hw.elsa.ctrl_reg & ELSA_STAT_LED)
 			led ^= ELSA_IPAC_STAT_LED;
-		writereg(cs, cs->hw.elsa.isac, IPAC_ATX, led);
+		writereg(cs->hw.elsa.ale, cs->hw.elsa.isac, IPAC_ATX, led);
 	} else
 		byteout(cs->hw.elsa.ctrl, cs->hw.elsa.ctrl_reg);
-
-	if (blink)
-		mod_timer(&cs->hw.elsa.tl, jiffies + (blink * HZ) / 1000);
-}
-
-#if ARCOFI_USE
-static void
-elsa_aux_ind(struct IsdnCardState *cs, void *arg)
-{
-	 if (cs->hw.elsa.MFlag) {
-		 int len;
-		 u8 *msg;
-		 
-		 if (!arg)
-			 return;
-		 msg = arg;
-		 len = *msg;
-		 msg++;
-		 modem_write_cmd(cs, msg, len);
-	 }
-}
-#else
-#define elsa_aux_ind NULL
-#endif
-
-static void
-elsa_init(struct IsdnCardState *cs)
-{
-	if (cs->subtyp == ELSA_QS1000 || cs->subtyp == ELSA_QS3000)
-		byteout(cs->hw.elsa.timer, 0);
-
-	if (cs->hw.elsa.trig)
-		byteout(cs->hw.elsa.trig, 0xff);
-
-	inithscxisac(cs);
+	if (blink) {
+		init_timer(&cs->hw.elsa.tl);
+		cs->hw.elsa.tl.expires = jiffies + ((blink * HZ) / 1000);
+		add_timer(&cs->hw.elsa.tl);
+	}
 }
 
-static void
-elsa_ipac_init(struct IsdnCardState *cs)
+static int
+Elsa_card_msg(struct IsdnCardState *cs, int mt, void *arg)
 {
-	if (cs->hw.elsa.trig)
-		byteout(cs->hw.elsa.trig, 0xff);
-
-	ipac_init(cs);
-}
+	int ret = 0;
+	u_long flags;
 
-static void
-elsa_test(struct IsdnCardState *cs)
-{
-	if ((cs->subtyp == ELSA_PCMCIA) ||
-	    (cs->subtyp == ELSA_PCMCIA_IPAC) ||
-	    (cs->subtyp == ELSA_QS1000PCI)) {
-		return;
-	} 
-	if (cs->subtyp != ELSA_QS3000PCI) {
-		cs->hw.elsa.counter = 0;
-		cs->hw.elsa.ctrl_reg |= ELSA_ENA_TIMER_INT;
-		cs->hw.elsa.status |= ELSA_TIMER_AKTIV;
-		byteout(cs->hw.elsa.ctrl, cs->hw.elsa.ctrl_reg);
-		byteout(cs->hw.elsa.timer, 0);
-		set_current_state(TASK_UNINTERRUPTIBLE);
-		schedule_timeout((110*HZ)/1000);
-		cs->hw.elsa.ctrl_reg &= ~ELSA_ENA_TIMER_INT;
-		byteout(cs->hw.elsa.ctrl, cs->hw.elsa.ctrl_reg);
-		cs->hw.elsa.status &= ~ELSA_TIMER_AKTIV;
-		printk(KERN_INFO "Elsa: %d timer tics in 110 msek\n",
-		       cs->hw.elsa.counter);
-		if ((cs->hw.elsa.counter > 10) &&
-		    (cs->hw.elsa.counter < 16)) {
-			printk(KERN_INFO "Elsa: timer and irq OK\n");
-		} else {
-			printk(KERN_WARNING
-			       "Elsa: timer tic problem (%d/12) maybe an IRQ(%d) conflict\n",
-			       cs->hw.elsa.counter, cs->irq);
-		}
-	}
+	switch (mt) {
+		case CARD_RESET:
+			spin_lock_irqsave(&cs->lock, flags);
+			reset_elsa(cs);
+			spin_unlock_irqrestore(&cs->lock, flags);
+			return(0);
+		case CARD_RELEASE:
+			release_io_elsa(cs);
+			return(0);
+		case CARD_INIT:
+			spin_lock_irqsave(&cs->lock, flags);
+			cs->debug |= L1_DEB_IPAC;
+			reset_elsa(cs);
+			inithscxisac(cs, 1);
+			if ((cs->subtyp == ELSA_QS1000) ||
+			    (cs->subtyp == ELSA_QS3000))
+			{
+				byteout(cs->hw.elsa.timer, 0);
+			}
+			if (cs->hw.elsa.trig)
+				byteout(cs->hw.elsa.trig, 0xff);
+			inithscxisac(cs, 2);
+			spin_unlock_irqrestore(&cs->lock, flags);
+			return(0);
+		case CARD_TEST:
+			if ((cs->subtyp == ELSA_PCMCIA) ||
+				(cs->subtyp == ELSA_PCMCIA_IPAC) ||
+				(cs->subtyp == ELSA_QS1000PCI)) {
+				return(0);
+			} else if (cs->subtyp == ELSA_QS3000PCI) {
+				ret = 0;
+			} else {
+				spin_lock_irqsave(&cs->lock, flags);
+				cs->hw.elsa.counter = 0;
+				cs->hw.elsa.ctrl_reg |= ELSA_ENA_TIMER_INT;
+				cs->hw.elsa.status |= ELSA_TIMER_AKTIV;
+				byteout(cs->hw.elsa.ctrl, cs->hw.elsa.ctrl_reg);
+				byteout(cs->hw.elsa.timer, 0);
+				spin_unlock_irqrestore(&cs->lock, flags);
+				set_current_state(TASK_UNINTERRUPTIBLE);
+				schedule_timeout((110*HZ)/1000);
+				spin_lock_irqsave(&cs->lock, flags);
+				cs->hw.elsa.ctrl_reg &= ~ELSA_ENA_TIMER_INT;
+				byteout(cs->hw.elsa.ctrl, cs->hw.elsa.ctrl_reg);
+				cs->hw.elsa.status &= ~ELSA_TIMER_AKTIV;
+				spin_unlock_irqrestore(&cs->lock, flags);
+				printk(KERN_INFO "Elsa: %d timer tics in 110 msek\n",
+				       cs->hw.elsa.counter);
+				if ((cs->hw.elsa.counter > 10) &&
+					(cs->hw.elsa.counter < 16)) {
+					printk(KERN_INFO "Elsa: timer and irq OK\n");
+					ret = 0;
+				} else {
+					printk(KERN_WARNING
+					       "Elsa: timer tic problem (%d/12) maybe an IRQ(%d) conflict\n",
+					       cs->hw.elsa.counter, cs->irq);
+					ret = 1;
+				}
+			}
 #if ARCOFI_USE
-	if (check_arcofi(cs)) {
-		init_modem(cs);
-	}
+			if (check_arcofi(cs)) {
+				init_modem(cs);
+			}
 #endif
-	elsa_led_handler(cs);
-}
-
-static struct card_ops elsa_ops = {
-	.init        = elsa_init,
-	.test        = elsa_test,
-	.reset       = elsa_reset,
-	.release     = elsa_release,
-	.aux_ind     = elsa_aux_ind,
-	.led_handler = elsa_led_handler,
-	.irq_func    = elsa_interrupt,
-};
-
-static struct card_ops elsa_ipac_ops = {
-	.init        = elsa_ipac_init,
-	.test        = elsa_test,
-	.reset       = elsa_reset,
-	.release     = elsa_release,
-	.aux_ind     = elsa_aux_ind,
-	.led_handler = elsa_led_handler,
-	.irq_func    = elsa_interrupt_ipac,
-};
-
-static void __init
-elsa_arcofi_init(struct IsdnCardState *cs)
-{
+			elsa_led_handler(cs);
+			return(ret);
+		case (MDL_REMOVE | REQUEST):
+			cs->hw.elsa.status &= 0;
+			break;
+		case (MDL_ASSIGN | REQUEST):
+			cs->hw.elsa.status |= ELSA_ASSIGN;
+			break;
+		case MDL_INFO_SETUP:
+			if ((long) arg)
+				cs->hw.elsa.status |= 0x0200;
+			else
+				cs->hw.elsa.status |= 0x0100;
+			break;
+		case MDL_INFO_CONN:
+			if ((long) arg)
+				cs->hw.elsa.status |= 0x2000;
+			else
+				cs->hw.elsa.status |= 0x1000;
+			break;
+		case MDL_INFO_REL:
+			if ((long) arg) {
+				cs->hw.elsa.status &= ~0x2000;
+				cs->hw.elsa.status &= ~0x0200;
+			} else {
+				cs->hw.elsa.status &= ~0x1000;
+				cs->hw.elsa.status &= ~0x0100;
+			}
+			break;
 #if ARCOFI_USE
-	init_arcofi(cs);
+		case CARD_AUX_IND:
+			if (cs->hw.elsa.MFlag) {
+				int len;
+				u_char *msg;
+
+				if (!arg)
+					return(0);
+				msg = arg;
+				len = *msg;
+				msg++;
+				modem_write_cmd(cs, msg, len);
+			}
+			break;
 #endif
-}
-
-static void __init
-elsa_timer_init(struct IsdnCardState *cs)
-{
-	cs->hw.elsa.tl.function = (void *) elsa_led_handler;
-	cs->hw.elsa.tl.data = (long) cs;
-	init_timer(&cs->hw.elsa.tl);
-}
-
-static int __init
-elsa_timer_test(struct IsdnCardState *cs)
-{
-	/* test timer */
-	byteout(cs->hw.elsa.trig, 0xff);
-	byteout(cs->hw.elsa.timer, 0);
-	if (!TimerRun(cs)) {
-		byteout(cs->hw.elsa.timer, 0);	/* second attempt */
-		if (!TimerRun(cs)) {
-			printk(KERN_WARNING "Elsa: timer does not start\n");
-			goto err;
-		}
 	}
-	HZDELAY(10 * HZ / 1000); /* wait >=10 ms */
-	if (TimerRun(cs)) {
-		printk(KERN_WARNING "Elsa: timer does not run\n");
-		goto err;
-	}
-	printk(KERN_INFO "Elsa: timer OK; resetting card\n");
-	return 0;
- err:
-	return -EBUSY;
+	if (cs->typ == ISDN_CTYPE_ELSA) {
+		int pwr = bytein(cs->hw.elsa.ale);
+		if (pwr & 0x08)
+			cs->hw.elsa.status |= ELSA_BAD_PWR;
+		else
+			cs->hw.elsa.status &= ~ELSA_BAD_PWR;
+	}
+	elsa_led_handler(cs);
+	return(ret);
 }
 
-static unsigned char __init
+static unsigned char
 probe_elsa_adr(unsigned int adr, int typ)
 {
 	int i, in1, in2, p16_1 = 0, p16_2 = 0, p8_1 = 0, p8_2 = 0, pc_1 = 0,
@@ -740,13 +781,18 @@ probe_elsa_adr(unsigned int adr, int typ
 	/* In case of the elsa pcmcia card, this region is in use,
 	   reserved for us by the card manager. So we do not check it
 	   here, it would fail. */
-	if (typ != ISDN_CTYPE_ELSA_PCMCIA && !request_region(adr, 8, "elsa")) {
-		printk(KERN_WARNING "Elsa: probing port 0x%x: in use\n",  adr);
-		return 0;
+	if (typ != ISDN_CTYPE_ELSA_PCMCIA) {
+		if (request_region(adr, 8, "elsa card")) {
+			release_region(adr, 8);
+		} else {
+			printk(KERN_WARNING
+			       "Elsa: Probing Port 0x%x: already in use\n", adr);
+			return (0);
+		}
 	}
 	for (i = 0; i < 16; i++) {
-		in1 = inb(adr + ELSA_CONFIG);	/* 'toggels' at */
-		in2 = inb(adr + ELSA_CONFIG);	/* each access  */
+		in1 = inb(adr + ELSA_CONFIG);	/* 'toggelt' bei */
+		in2 = inb(adr + ELSA_CONFIG);	/* jedem Zugriff */
 		p16_1 += 0x04 & in1;
 		p16_2 += 0x04 & in2;
 		p8_1 += 0x02 & in1;
@@ -756,7 +802,6 @@ probe_elsa_adr(unsigned int adr, int typ
 		pfp_1 += 0x40 & in1;
 		pfp_2 += 0x40 & in2;
 	}
-	release_region(adr, 8);
 	printk(KERN_INFO "Elsa: Probing IO 0x%x", adr);
 	if (65 == ++p16_1 * ++p16_2) {
 		printk(" PCC-16/PCF found\n");
@@ -776,227 +821,18 @@ probe_elsa_adr(unsigned int adr, int typ
 	}
 }
 
-static int __init
-elsa_probe(struct IsdnCardState *cs, struct IsdnCard *card)
+static unsigned int
+probe_elsa(struct IsdnCardState *cs)
 {
-	u8 val;
-	int i, bytecnt = 8;
-	unsigned int CARD_portlist[] = {0x160, 0x170, 0x260, 0x360, 0};
-
-	cs->hw.elsa.base = card->para[0];
-	printk(KERN_INFO "Elsa: Microlink IO probing\n");
-	if (cs->hw.elsa.base) {
-		cs->subtyp = probe_elsa_adr(cs->hw.elsa.base, cs->typ);
-		if (!cs->subtyp) {
-			printk(KERN_WARNING "Elsa: no Microlink at %#lx\n",
-			       cs->hw.elsa.base);
-			goto err;
-		}
-	} else {
-		for (i = 0; CARD_portlist[i]; i++) {
-			cs->subtyp = probe_elsa_adr(CARD_portlist[i], cs->typ);
-			if (cs->subtyp)
-				cs->hw.elsa.base = CARD_portlist[i];
-			break;
-		}
-	}
-	if (!cs->hw.elsa.base)
-		goto err;
-		
-	cs->hw.elsa.cfg   = cs->hw.elsa.base + ELSA_CONFIG;
-	cs->hw.elsa.ctrl  = cs->hw.elsa.base + ELSA_CONTROL;
-	cs->hw.elsa.ale   = cs->hw.elsa.base + ELSA_ALE;
-	cs->hw.elsa.isac  = cs->hw.elsa.base + ELSA_ISAC;
-	cs->hw.elsa.itac  = cs->hw.elsa.base + ELSA_ITAC;
-	cs->hw.elsa.hscx  = cs->hw.elsa.base + ELSA_HSCX;
-	cs->hw.elsa.trig  = cs->hw.elsa.base + ELSA_TRIG_IRQ;
-	cs->hw.elsa.timer = cs->hw.elsa.base + ELSA_START_TIMER;
-	val = bytein(cs->hw.elsa.cfg);
-	if (cs->subtyp == ELSA_PC) {
-		const u8 CARD_IrqTab[8] = {7, 3, 5, 9, 0, 0, 0, 0};
-		cs->irq = CARD_IrqTab[(val & ELSA_IRQ_IDX_PC) >> 2];
-	} else if (cs->subtyp == ELSA_PCC8) {
-		const u8 CARD_IrqTab[8] = {7, 3, 5, 9, 0, 0, 0, 0};
-		cs->irq = CARD_IrqTab[(val & ELSA_IRQ_IDX_PCC8) >> 4];
-	} else {
-		const u8 CARD_IrqTab[8] = {15, 10, 15, 3, 11, 5, 11, 9};
-		cs->irq = CARD_IrqTab[(val & ELSA_IRQ_IDX) >> 3];
-	}
-	val = bytein(cs->hw.elsa.ale) & ELSA_HW_RELEASE;
-	if (val < 3)
-		val |= 8;
-	val += 'A' - 3;
-	if (val == 'B' || val == 'C')
-		val ^= 1;
-	if ((cs->subtyp == ELSA_PCFPRO) && (val = 'G'))
-		val = 'C';
-	printk(KERN_INFO "Elsa: %s found at %#lx Rev.:%c IRQ %d\n",
-	       Elsa_Types[cs->subtyp], cs->hw.elsa.base, val, cs->irq);
-	val = bytein(cs->hw.elsa.ale) & ELSA_S0_POWER_BAD;
-	if (val) {
-		printk(KERN_WARNING "Elsa: Microlink S0 bus power bad\n");
-		cs->hw.elsa.status |= ELSA_BAD_PWR;
-	}
-	switch (cs->subtyp) {
-		case ELSA_PCFPRO: bytecnt = 16;	break;
-	}
-	if (!request_io(&cs->rs, cs->hw.elsa.base, bytecnt, "elsa isdn"))
-		goto err;
-	elsa_arcofi_init(cs);
-	elsa_timer_init(cs);
-	if (elsa_timer_test(cs))
-		goto err;
-	elsa_reset(cs);
-	cs->card_ops = &elsa_ops;
-	if (hscxisac_setup(cs, &isac_ops, &hscx_ops))
-		goto err;
-	if (cs->subtyp == ELSA_PC) {
-		val = readitac(cs, ITAC_SYS);
-		printk(KERN_INFO "Elsa: ITAC version %s\n", ITACVer[val & 7]);
-		writeitac(cs, ITAC_ISEN, 0);
-		writeitac(cs, ITAC_RFIE, 0);
-		writeitac(cs, ITAC_XFIE, 0);
-		writeitac(cs, ITAC_SCIE, 0);
-		writeitac(cs, ITAC_STIE, 0);
-	}
-	return 0;
- err:
-	elsa_release(cs);
-	return -EBUSY;
-}
-
-static int __init
-elsa_qs_probe(struct IsdnCardState *cs, struct IsdnCard *card)
-{
-	int bytecnt = 8;
+	int i;
+	unsigned int CARD_portlist[] =
+	{0x160, 0x170, 0x260, 0x360, 0};
 
-	cs->irq           = card->para[0];
-	cs->hw.elsa.base  = card->para[1];
-	cs->hw.elsa.cfg   = cs->hw.elsa.base + ELSA_CONFIG;
-	cs->hw.elsa.ale   = cs->hw.elsa.base + ELSA_ALE;
-	cs->hw.elsa.isac  = cs->hw.elsa.base + ELSA_ISAC;
-	cs->hw.elsa.hscx  = cs->hw.elsa.base + ELSA_HSCX;
-	cs->hw.elsa.trig  = cs->hw.elsa.base + ELSA_TRIG_IRQ;
-	cs->hw.elsa.timer = cs->hw.elsa.base + ELSA_START_TIMER;
-	cs->hw.elsa.ctrl  = cs->hw.elsa.base + ELSA_CONTROL;
-	printk(KERN_INFO "Elsa: %s defined at %#lx IRQ %d\n",
-	       Elsa_Types[cs->subtyp], cs->hw.elsa.base, cs->irq);
-	switch (cs->subtyp) {
-	case ELSA_QS3000: bytecnt = 16;	break;
-	}
-	if (!request_io(&cs->rs, cs->hw.elsa.base, bytecnt, "elsa isdn"))
-		goto err;
-	elsa_arcofi_init(cs);
-	elsa_timer_init(cs);
-	if (elsa_timer_test(cs))
-		goto err;
-	elsa_reset(cs);
-	cs->card_ops = &elsa_ops;
-	if (hscxisac_setup(cs, &isac_ops, &hscx_ops))
-		goto err;
-	return 0;
- err:
-	elsa_release(cs);
-	return -EBUSY;
-}
-
-static int __init
-elsa_qs1000_probe(struct IsdnCardState *cs, struct IsdnCard *card)
-{
-	cs->subtyp = ELSA_QS1000;
-	return elsa_qs_probe(cs, card);
-}
-
-static int __init
-elsa_qs3000_probe(struct IsdnCardState *cs, struct IsdnCard *card)
-{
-	cs->subtyp = ELSA_QS3000;
-	return elsa_qs_probe(cs, card);
-}
-
-static int __init
-elsa_pcmcia_probe(struct IsdnCardState *cs, struct IsdnCard *card)
-{
-	u8 val;
-
-	cs->irq = card->para[0];
-	cs->hw.elsa.base = card->para[1];
-	cs->hw.elsa.ale = cs->hw.elsa.base + 0;
-	val = readreg(cs, cs->hw.elsa.base + 2, IPAC_ID);
-	if ((val == 1) || (val == 2)) { /* IPAC version 1.1/1.2 */
-		cs->subtyp = ELSA_PCMCIA_IPAC;
-		cs->hw.elsa.isac = cs->hw.elsa.base + 2;
-	} else {
-		cs->subtyp = ELSA_PCMCIA;
-		cs->hw.elsa.ale = cs->hw.elsa.base + ELSA_ALE_PCM;
-		cs->hw.elsa.isac = cs->hw.elsa.base + ELSA_ISAC_PCM;
-		cs->hw.elsa.hscx = cs->hw.elsa.base + ELSA_HSCX;
-	}
-	cs->hw.elsa.timer = 0;
-	cs->hw.elsa.trig = 0;
-	cs->hw.elsa.ctrl = 0;
-	printk(KERN_INFO "Elsa: %s defined at %#lx IRQ %d\n",
-	       Elsa_Types[cs->subtyp], cs->hw.elsa.base, cs->irq);
-	elsa_arcofi_init(cs);
-	elsa_reset(cs);
-	if (cs->subtyp == ELSA_PCMCIA_IPAC) {
-		cs->card_ops = &elsa_ipac_ops;
-		if (ipac_setup(cs, &ipac_dc_ops, &ipac_bc_ops))
-			goto err;
-	} else {
-		cs->card_ops = &elsa_ops;
-		if (hscxisac_setup(cs, &isac_ops, &hscx_ops))
-			goto err;
-	}
-	return 0;
- err:
-	elsa_release(cs);
-	return -EBUSY;
-}
-
-static int __init
-elsa_qs_pci_probe(struct IsdnCardState *cs, struct pci_dev *pdev,
-		  int subtyp)
-{
-	int bytecnt = 2;
-	u8 pci_rev;
-
-	if (pci_enable_device(pdev))
-		goto err;
-
-	cs->subtyp = subtyp;
-	cs->irq = pdev->irq;
-	cs->irq_flags |= SA_SHIRQ;
-	cs->hw.elsa.cfg = pci_resource_start(pdev, 1);
-	cs->hw.elsa.base = pci_resource_start(pdev, 3);
-	pci_read_config_byte(pdev, PCI_REVISION_ID, &pci_rev);
-	if (cs->hw.elsa.cfg & 0x80 && pci_rev == 1) {
-		printk(KERN_INFO "Elsa: PLX9050 rev1 workaround activated\n");
-		__set_bit(FLG_BUGGY_PLX9050, &cs->HW_Flags);
-	}
-	cs->hw.elsa.ale  = cs->hw.elsa.base;
-	cs->hw.elsa.isac = cs->hw.elsa.base +1;
-	cs->hw.elsa.hscx = cs->hw.elsa.base +1; 
-	printk(KERN_INFO "Elsa: %s defined at %#lx/%#x IRQ %d\n",
-	       Elsa_Types[cs->subtyp], cs->hw.elsa.base, cs->hw.elsa.cfg,
-	       cs->irq);
-	switch (cs->subtyp) {
-	case ELSA_QS3000PCI: bytecnt = 16; break;
+	for (i = 0; CARD_portlist[i]; i++) {
+		if ((cs->subtyp = probe_elsa_adr(CARD_portlist[i], cs->typ)))
+			break;
 	}
-	if (!request_io(&cs->rs, cs->hw.elsa.base, bytecnt, "elsa isdn"))
-		goto err;
-	if (!request_io(&cs->rs, cs->hw.elsa.cfg, 0x80, "elsa isdn pci"))
-		goto err;
-	elsa_arcofi_init(cs);
-	elsa_timer_init(cs);
-	elsa_reset(cs);
-	cs->card_ops = &elsa_ipac_ops;
-	if (ipac_setup(cs, &ipac_dc_ops, &ipac_bc_ops))
-		goto err;
-	return 0;
- err:
-	elsa_release(cs);
-	return -EBUSY;
+	return (CARD_portlist[i]);
 }
 
 static 	struct pci_dev *dev_qs1000 __devinitdata = NULL;
@@ -1013,109 +849,343 @@ static struct isapnp_device_id elsa_ids[
 	{ 0, }
 };
 
-static struct isapnp_device_id *pdev = &elsa_ids[0];
+static struct isapnp_device_id *ipid __initdata = &elsa_ids[0];
 static struct pnp_card *pnp_c __devinitdata = NULL;
 #endif
 
 int __devinit
 setup_elsa(struct IsdnCard *card)
 {
+	int bytecnt;
+	u_char val;
+	struct IsdnCardState *cs = card->cs;
 	char tmp[64];
 
 	strcpy(tmp, Elsa_revision);
 	printk(KERN_INFO "HiSax: Elsa driver Rev. %s\n", HiSax_getrev(tmp));
-
-	if (card->typ == ISDN_CTYPE_ELSA) {
-		if (elsa_probe(card->cs, card))
-			return 0;
-		return 1;
-	} else if (card->typ == ISDN_CTYPE_ELSA_PNP) {
+	cs->hw.elsa.ctrl_reg = 0;
+	cs->hw.elsa.status = 0;
+	cs->hw.elsa.MFlag = 0;
+	cs->subtyp = 0;
+	if (cs->typ == ISDN_CTYPE_ELSA) {
+		cs->hw.elsa.base = card->para[0];
+		printk(KERN_INFO "Elsa: Microlink IO probing\n");
+		if (cs->hw.elsa.base) {
+			if (!(cs->subtyp = probe_elsa_adr(cs->hw.elsa.base,
+							  cs->typ))) {
+				printk(KERN_WARNING
+				       "Elsa: no Elsa Microlink at %#lx\n",
+				       cs->hw.elsa.base);
+				return (0);
+			}
+		} else
+			cs->hw.elsa.base = probe_elsa(cs);
+		if (cs->hw.elsa.base) {
+			cs->hw.elsa.cfg = cs->hw.elsa.base + ELSA_CONFIG;
+			cs->hw.elsa.ctrl = cs->hw.elsa.base + ELSA_CONTROL;
+			cs->hw.elsa.ale = cs->hw.elsa.base + ELSA_ALE;
+			cs->hw.elsa.isac = cs->hw.elsa.base + ELSA_ISAC;
+			cs->hw.elsa.itac = cs->hw.elsa.base + ELSA_ITAC;
+			cs->hw.elsa.hscx = cs->hw.elsa.base + ELSA_HSCX;
+			cs->hw.elsa.trig = cs->hw.elsa.base + ELSA_TRIG_IRQ;
+			cs->hw.elsa.timer = cs->hw.elsa.base + ELSA_START_TIMER;
+			val = bytein(cs->hw.elsa.cfg);
+			if (cs->subtyp == ELSA_PC) {
+				const u_char CARD_IrqTab[8] =
+				{7, 3, 5, 9, 0, 0, 0, 0};
+				cs->irq = CARD_IrqTab[(val & ELSA_IRQ_IDX_PC) >> 2];
+			} else if (cs->subtyp == ELSA_PCC8) {
+				const u_char CARD_IrqTab[8] =
+				{7, 3, 5, 9, 0, 0, 0, 0};
+				cs->irq = CARD_IrqTab[(val & ELSA_IRQ_IDX_PCC8) >> 4];
+			} else {
+				const u_char CARD_IrqTab[8] =
+				{15, 10, 15, 3, 11, 5, 11, 9};
+				cs->irq = CARD_IrqTab[(val & ELSA_IRQ_IDX) >> 3];
+			}
+			val = bytein(cs->hw.elsa.ale) & ELSA_HW_RELEASE;
+			if (val < 3)
+				val |= 8;
+			val += 'A' - 3;
+			if (val == 'B' || val == 'C')
+				val ^= 1;
+			if ((cs->subtyp == ELSA_PCFPRO) && (val = 'G'))
+				val = 'C';
+			printk(KERN_INFO
+			       "Elsa: %s found at %#lx Rev.:%c IRQ %d\n",
+			       Elsa_Types[cs->subtyp],
+			       cs->hw.elsa.base,
+			       val, cs->irq);
+			val = bytein(cs->hw.elsa.ale) & ELSA_S0_POWER_BAD;
+			if (val) {
+				printk(KERN_WARNING
+				   "Elsa: Microlink S0 bus power bad\n");
+				cs->hw.elsa.status |= ELSA_BAD_PWR;
+			}
+		} else {
+			printk(KERN_WARNING
+			       "No Elsa Microlink found\n");
+			return (0);
+		}
+	} else if (cs->typ == ISDN_CTYPE_ELSA_PNP) {
 #ifdef __ISAPNP__
 		if (!card->para[1] && isapnp_present()) {
-			struct pnp_card *pb;
-			struct pnp_dev *pd;
-			
-			while(pdev->card_vendor) {
-				if ((pb = pnp_find_card(pdev->card_vendor,
-							pdev->card_device,
-							pnp_c))) {
-					pnp_c = pb;
-					pd = NULL;
-					if ((pd = pnp_find_dev(pnp_c,
-							       pdev->vendor,
-							       pdev->function,
-							       pd))) {
+			struct pnp_dev *pnp_d;
+			while(ipid->card_vendor) {
+				if ((pnp_c = pnp_find_card(ipid->card_vendor,
+					ipid->card_device, pnp_c))) {
+					pnp_d = NULL;
+					if ((pnp_d = pnp_find_dev(pnp_c,
+						ipid->vendor, ipid->function, pnp_d))) {
+						int err;
+
 						printk(KERN_INFO "HiSax: %s detected\n",
-							(char *)pdev->driver_data);
-						if (pnp_device_attach(pd) < 0) {
-							printk(KERN_ERR "Elsa PnP: attach failed\n");
-							return 0;
-						}
-						if (pnp_activate_dev(pd) < 0) {
-							pnp_device_detach(pd);
-							printk(KERN_ERR "Elsa PnP: activate failed\n");
-							return 0;
+							(char *)ipid->driver_data);
+						pnp_disable_dev(pnp_d);
+						err = pnp_activate_dev(pnp_d);
+						if (err<0) {
+							printk(KERN_WARNING "%s: pnp_activate_dev ret(%d)\n",
+								__FUNCTION__, err);
+							return(0);
 						}
-						if (!pnp_port_valid(pd, 0) ||
-						    !pnp_irq_valid(pd, 0)) {
+						card->para[1] = pnp_port_start(pnp_d, 0);
+						card->para[0] = pnp_irq(pnp_d, 0);
+
+						if (!card->para[0] || !card->para[1]) {
 							printk(KERN_ERR "Elsa PnP:some resources are missing %ld/%lx\n",
-							       pnp_irq(pd, 0), pnp_port_start(pd, 0));
-							pnp_device_detach(pd);
+								card->para[0], card->para[1]);
+							pnp_disable_dev(pnp_d);
 							return(0);
 						}
-						card->para[1] = pnp_port_start(pd, 0);
-						card->para[0] = pnp_irq(pd, 0);
-						if (pdev->function == ISAPNP_FUNCTION(0x133)) {
-							if (elsa_qs1000_probe(card->cs, card))
-								return 0;
-							return 1;
-						} else {
-							if (elsa_qs3000_probe(card->cs, card))
-								return 0;
-							return 1;
-						}
+						if (ipid->function == ISAPNP_FUNCTION(0x133))
+							cs->subtyp = ELSA_QS1000;
+						else
+							cs->subtyp = ELSA_QS3000;
 						break;
 					} else {
 						printk(KERN_ERR "Elsa PnP: PnP error card found, no device\n");
 						return(0);
 					}
 				}
-				pdev++;
+				ipid++;
 				pnp_c=NULL;
 			} 
-			if (!pdev->card_vendor) {
+			if (!ipid->card_vendor) {
 				printk(KERN_INFO "Elsa PnP: no ISAPnP card found\n");
 				return(0);
 			}
 		}
 #endif
-		if (elsa_qs1000_probe(card->cs, card))
-			return 0;
-		return 1;
-
-	} else if (card->typ == ISDN_CTYPE_ELSA_PCMCIA) {
-		if (elsa_pcmcia_probe(card->cs, card))
-			return 0;
-		return 1;
-	} else if (card->typ == ISDN_CTYPE_ELSA_PCI) {
-#ifdef CONFIG_PCI
+		if (card->para[1] && card->para[0]) { 
+			cs->hw.elsa.base = card->para[1];
+			cs->irq = card->para[0];
+			if (!cs->subtyp)
+				cs->subtyp = ELSA_QS1000;
+		} else {
+			printk(KERN_ERR "Elsa PnP: no parameter\n");
+		}
+		cs->hw.elsa.cfg = cs->hw.elsa.base + ELSA_CONFIG;
+		cs->hw.elsa.ale = cs->hw.elsa.base + ELSA_ALE;
+		cs->hw.elsa.isac = cs->hw.elsa.base + ELSA_ISAC;
+		cs->hw.elsa.hscx = cs->hw.elsa.base + ELSA_HSCX;
+		cs->hw.elsa.trig = cs->hw.elsa.base + ELSA_TRIG_IRQ;
+		cs->hw.elsa.timer = cs->hw.elsa.base + ELSA_START_TIMER;
+		cs->hw.elsa.ctrl = cs->hw.elsa.base + ELSA_CONTROL;
+		printk(KERN_INFO
+		       "Elsa: %s defined at %#lx IRQ %d\n",
+		       Elsa_Types[cs->subtyp],
+		       cs->hw.elsa.base,
+		       cs->irq);
+	} else if (cs->typ == ISDN_CTYPE_ELSA_PCMCIA) {
+		cs->hw.elsa.base = card->para[1];
+		cs->irq = card->para[0];
+		val = readreg(cs->hw.elsa.base + 0, cs->hw.elsa.base + 2, IPAC_ID);
+		if ((val == 1) || (val == 2)) { /* IPAC version 1.1/1.2 */
+			cs->subtyp = ELSA_PCMCIA_IPAC;
+			cs->hw.elsa.ale = cs->hw.elsa.base + 0;
+			cs->hw.elsa.isac = cs->hw.elsa.base + 2;
+			cs->hw.elsa.hscx = cs->hw.elsa.base + 2;
+			test_and_set_bit(HW_IPAC, &cs->HW_Flags);
+		} else {
+			cs->subtyp = ELSA_PCMCIA;
+			cs->hw.elsa.ale = cs->hw.elsa.base + ELSA_ALE_PCM;
+			cs->hw.elsa.isac = cs->hw.elsa.base + ELSA_ISAC_PCM;
+			cs->hw.elsa.hscx = cs->hw.elsa.base + ELSA_HSCX;
+		}
+		cs->hw.elsa.timer = 0;
+		cs->hw.elsa.trig = 0;
+		cs->hw.elsa.ctrl = 0;
+		cs->irq_flags |= SA_SHIRQ;
+		printk(KERN_INFO
+		       "Elsa: %s defined at %#lx IRQ %d\n",
+		       Elsa_Types[cs->subtyp],
+		       cs->hw.elsa.base,
+		       cs->irq);
+	} else if (cs->typ == ISDN_CTYPE_ELSA_PCI) {
+#if CONFIG_PCI
+		cs->subtyp = 0;
 		if ((dev_qs1000 = pci_find_device(PCI_VENDOR_ID_ELSA,
 			PCI_DEVICE_ID_ELSA_MICROLINK, dev_qs1000))) {
-			if (elsa_qs_pci_probe(card->cs, dev_qs1000,
-					      ELSA_QS1000PCI))
-				return 0;
-			return 1;
+			if (pci_enable_device(dev_qs1000))
+				return(0);
+			cs->subtyp = ELSA_QS1000PCI;
+			cs->irq = dev_qs1000->irq;
+			cs->hw.elsa.cfg = pci_resource_start(dev_qs1000, 1);
+			cs->hw.elsa.base = pci_resource_start(dev_qs1000, 3);
 		} else if ((dev_qs3000 = pci_find_device(PCI_VENDOR_ID_ELSA,
 			PCI_DEVICE_ID_ELSA_QS3000, dev_qs3000))) {
-			if (elsa_qs_pci_probe(card->cs, dev_qs3000,
-					      ELSA_QS3000PCI))
-				return 0;
-			return 1;
+			if (pci_enable_device(dev_qs3000))
+				return(0);
+			cs->subtyp = ELSA_QS3000PCI;
+			cs->irq = dev_qs3000->irq;
+			cs->hw.elsa.cfg = pci_resource_start(dev_qs3000, 1);
+			cs->hw.elsa.base = pci_resource_start(dev_qs3000, 3);
 		} else {
 			printk(KERN_WARNING "Elsa: No PCI card found\n");
-			return 0;
+			return(0);
+		}
+		if (!cs->irq) {
+			printk(KERN_WARNING "Elsa: No IRQ for PCI card found\n");
+			return(0);
+		}
+
+		if (!(cs->hw.elsa.base && cs->hw.elsa.cfg)) {
+			printk(KERN_WARNING "Elsa: No IO-Adr for PCI card found\n");
+			return(0);
+		}
+		if ((cs->hw.elsa.cfg & 0xff) || (cs->hw.elsa.base & 0xf)) {
+			printk(KERN_WARNING "Elsa: You may have a wrong PCI bios\n");
+			printk(KERN_WARNING "Elsa: If your system hangs now, read\n");
+			printk(KERN_WARNING "Elsa: Documentation/isdn/README.HiSax\n");
 		}
+		cs->hw.elsa.ale  = cs->hw.elsa.base;
+		cs->hw.elsa.isac = cs->hw.elsa.base +1;
+		cs->hw.elsa.hscx = cs->hw.elsa.base +1; 
+		test_and_set_bit(HW_IPAC, &cs->HW_Flags);
+		cs->hw.elsa.timer = 0;
+		cs->hw.elsa.trig  = 0;
+		cs->irq_flags |= SA_SHIRQ;
+		printk(KERN_INFO
+		       "Elsa: %s defined at %#lx/0x%x IRQ %d\n",
+		       Elsa_Types[cs->subtyp],
+		       cs->hw.elsa.base,
+		       cs->hw.elsa.cfg,
+		       cs->irq);
+#else
+		printk(KERN_WARNING "Elsa: Elsa PCI and NO_PCI_BIOS\n");
+		printk(KERN_WARNING "Elsa: unable to config Elsa PCI\n");
+		return (0);
 #endif /* CONFIG_PCI */
+	} else 
+		return (0);
+
+	switch (cs->subtyp) {
+		case ELSA_PC:
+		case ELSA_PCC8:
+		case ELSA_PCC16:
+		case ELSA_QS1000:
+		case ELSA_PCMCIA:
+		case ELSA_PCMCIA_IPAC:
+			bytecnt = 8;
+			break;
+		case ELSA_PCFPRO:
+		case ELSA_PCF:
+		case ELSA_QS3000:
+		case ELSA_QS3000PCI:
+			bytecnt = 16;
+			break;
+		case ELSA_QS1000PCI:
+			bytecnt = 2;
+			break;
+		default:
+			printk(KERN_WARNING
+			       "Unknown ELSA subtype %d\n", cs->subtyp);
+			return (0);
+	}
+	/* In case of the elsa pcmcia card, this region is in use,
+	   reserved for us by the card manager. So we do not check it
+	   here, it would fail. */
+	if (cs->typ != ISDN_CTYPE_ELSA_PCMCIA && !request_region(cs->hw.elsa.base, bytecnt, "elsa isdn")) {
+		printk(KERN_WARNING
+		       "HiSax: %s config port %#lx-%#lx already in use\n",
+		       CardType[card->typ],
+		       cs->hw.elsa.base,
+		       cs->hw.elsa.base + bytecnt);
+		return (0);
+	}
+	if ((cs->subtyp == ELSA_QS1000PCI) || (cs->subtyp == ELSA_QS3000PCI)) {
+		if (!request_region(cs->hw.elsa.cfg, 0x80, "elsa isdn pci")) {
+			printk(KERN_WARNING
+			       "HiSax: %s pci port %x-%x already in use\n",
+				CardType[card->typ],
+				cs->hw.elsa.cfg,
+				cs->hw.elsa.cfg + 0x80);
+			release_region(cs->hw.elsa.base, bytecnt);
+			return (0);
+		}
+	}
+#if ARCOFI_USE
+	init_arcofi(cs);
+#endif
+	setup_isac(cs);
+	cs->hw.elsa.tl.function = (void *) elsa_led_handler;
+	cs->hw.elsa.tl.data = (long) cs;
+	init_timer(&cs->hw.elsa.tl);
+	/* Teste Timer */
+	if (cs->hw.elsa.timer) {
+		byteout(cs->hw.elsa.trig, 0xff);
+		byteout(cs->hw.elsa.timer, 0);
+		if (!TimerRun(cs)) {
+			byteout(cs->hw.elsa.timer, 0);	/* 2. Versuch */
+			if (!TimerRun(cs)) {
+				printk(KERN_WARNING
+				       "Elsa: timer do not start\n");
+				release_io_elsa(cs);
+				return (0);
+			}
+		}
+		HZDELAY((HZ/100) + 1);	/* wait >=10 ms */
+		if (TimerRun(cs)) {
+			printk(KERN_WARNING "Elsa: timer do not run down\n");
+			release_io_elsa(cs);
+			return (0);
+		}
+		printk(KERN_INFO "Elsa: timer OK; resetting card\n");
+	}
+	cs->BC_Read_Reg = &ReadHSCX;
+	cs->BC_Write_Reg = &WriteHSCX;
+	cs->BC_Send_Data = &hscx_fill_fifo;
+	cs->cardmsg = &Elsa_card_msg;
+	if ((cs->subtyp == ELSA_QS1000PCI) || (cs->subtyp == ELSA_QS3000PCI) || (cs->subtyp == ELSA_PCMCIA_IPAC)) {
+		cs->readisac = &ReadISAC_IPAC;
+		cs->writeisac = &WriteISAC_IPAC;
+		cs->readisacfifo = &ReadISACfifo_IPAC;
+		cs->writeisacfifo = &WriteISACfifo_IPAC;
+		cs->irq_func = &elsa_interrupt_ipac;
+		val = readreg(cs->hw.elsa.ale, cs->hw.elsa.isac, IPAC_ID);
+		printk(KERN_INFO "Elsa: IPAC version %x\n", val);
+	} else {
+		cs->readisac = &ReadISAC;
+		cs->writeisac = &WriteISAC;
+		cs->readisacfifo = &ReadISACfifo;
+		cs->writeisacfifo = &WriteISACfifo;
+		cs->irq_func = &elsa_interrupt;
+		ISACVersion(cs, "Elsa:");
+		if (HscxVersion(cs, "Elsa:")) {
+			printk(KERN_WARNING
+				"Elsa: wrong HSCX versions check IO address\n");
+			release_io_elsa(cs);
+			return (0);
+		}
+	}
+	if (cs->subtyp == ELSA_PC) {
+		val = readitac(cs, ITAC_SYS);
+		printk(KERN_INFO "Elsa: ITAC version %s\n", ITACVer[val & 7]);
+		writeitac(cs, ITAC_ISEN, 0);
+		writeitac(cs, ITAC_RFIE, 0);
+		writeitac(cs, ITAC_XFIE, 0);
+		writeitac(cs, ITAC_SCIE, 0);
+		writeitac(cs, ITAC_STIE, 0);
 	}
-	return 0;
+	return (1);
 }
--- diff/drivers/isdn/hisax/elsa_cs.c	2004-02-09 10:36:10.000000000 +0000
+++ source/drivers/isdn/hisax/elsa_cs.c	2004-02-23 13:56:42.000000000 +0000
@@ -53,6 +53,7 @@
 #include <pcmcia/cistpl.h>
 #include <pcmcia/cisreg.h>
 #include <pcmcia/ds.h>
+#include "hisax_cfg.h"
 
 MODULE_DESCRIPTION("ISDN4Linux: PCMCIA client driver for Elsa PCM cards");
 MODULE_AUTHOR("Klaus Lichtenwalder");
@@ -71,7 +72,7 @@ static int pc_debug = PCMCIA_DEBUG;
 MODULE_PARM(pc_debug, "i");
 #define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args);
 static char *version =
-"elsa_cs.c $Revision: 1.1.2.2 $ $Date: 2001/09/23 22:24:47 $ (K.Lichtenwalder)";
+"elsa_cs.c $Revision: 1.2.2.4 $ $Date: 2004/01/25 15:07:06 $ (K.Lichtenwalder)";
 #else
 #define DEBUG(n, args...)
 #endif
@@ -93,8 +94,6 @@ MODULE_PARM(irq_list, "1-4i");
 static int protocol = 2;        /* EURO-ISDN Default */
 MODULE_PARM(protocol, "i");
 
-extern int elsa_init_pcmcia(int, int, int*, int);
-
 /*====================================================================*/
 
 /*
@@ -168,6 +167,7 @@ typedef struct local_info_t {
     dev_link_t          link;
     dev_node_t          node;
     int                 busy;
+    int			cardnr;
 } local_info_t;
 
 /*======================================================================
@@ -188,7 +188,6 @@ static dev_link_t *elsa_cs_attach(void)
     dev_link_t *link;
     local_info_t *local;
     int ret, i;
-    void elsa_interrupt(int, void *, struct pt_regs *);
 
     DEBUG(0, "elsa_cs_attach()\n");
 
@@ -196,6 +195,7 @@ static dev_link_t *elsa_cs_attach(void)
     local = kmalloc(sizeof(local_info_t), GFP_KERNEL);
     if (!local) return NULL;
     memset(local, 0, sizeof(local_info_t));
+    local->cardnr = -1;
     link = &local->link; link->priv = local;
 
     /* Interrupt setup */
@@ -337,6 +337,7 @@ static void elsa_cs_config(dev_link_t *l
     int i, j, last_fn;
     u_short buf[128];
     cistpl_cftable_entry_t *cf = &parse.cftable_entry;
+    IsdnCard_t icard;
 
     DEBUG(0, "elsa_config(0x%p)\n", link);
     handle = link->handle;
@@ -430,9 +431,19 @@ static void elsa_cs_config(dev_link_t *l
 
     link->state &= ~DEV_CONFIG_PENDING;
 
-    elsa_init_pcmcia(link->io.BasePort1, link->irq.AssignedIRQ,
-                     &(((local_info_t*)link->priv)->busy),
-                     protocol);
+    icard.para[0] = link->irq.AssignedIRQ;
+    icard.para[1] = link->io.BasePort1;
+    icard.protocol = protocol;
+    icard.typ = ISDN_CTYPE_ELSA_PCMCIA;
+    
+    i = hisax_init_pcmcia(link, &(((local_info_t*)link->priv)->busy), &icard);
+    if (i < 0) {
+    	printk(KERN_ERR "elsa_cs: failed to initialize Elsa PCMCIA %d at i/o %#x\n",
+    		i, link->io.BasePort1);
+    	elsa_cs_release(link);
+    } else
+    	((local_info_t*)link->priv)->cardnr = i;
+
     return;
 cs_failed:
     cs_error(link->handle, last_fn, i);
@@ -449,9 +460,16 @@ cs_failed:
 
 static void elsa_cs_release(dev_link_t *link)
 {
+    local_info_t *local = link->priv;
 
     DEBUG(0, "elsa_cs_release(0x%p)\n", link);
 
+    if (local) {
+    	if (local->cardnr >= 0) {
+    	    /* no unregister function with hisax */
+	    HiSax_closecard(local->cardnr);
+	}
+    }
     /* Unlink the device chain */
     link->dev = NULL;
 
--- diff/drivers/isdn/hisax/elsa_ser.c	2003-09-17 12:28:06.000000000 +0100
+++ source/drivers/isdn/hisax/elsa_ser.c	2004-02-23 13:56:42.000000000 +0000
@@ -1,4 +1,4 @@
-/* $Id: elsa_ser.c,v 2.10.6.4 2001/09/23 22:24:47 kai Exp $
+/* $Id: elsa_ser.c,v 2.14.2.3 2004/02/11 13:21:33 keil Exp $
  *
  * stuff for the serial modem on ELSA cards
  *
@@ -26,11 +26,10 @@
 //#define SERIAL_DEBUG_REG 1
 
 #ifdef SERIAL_DEBUG_REG
-static u8 deb[32];
+static u_char deb[32];
 const char *ModemIn[] = {"RBR","IER","IIR","LCR","MCR","LSR","MSR","SCR"};
 const char *ModemOut[] = {"THR","IER","FCR","LCR","MCR","LSR","MSR","SCR"};
 #endif
-static spinlock_t elsa_ser_lock = SPIN_LOCK_UNLOCKED;
 
 static char *MInit_1 = "AT&F&C1E0&D2\r\0";
 static char *MInit_2 = "ATL2M1S64=13\r\0";
@@ -111,7 +110,6 @@ static void change_speed(struct IsdnCard
 	int	quot = 0, baud_base;
 	unsigned cval, fcr = 0;
 	int	bits;
-	unsigned long	flags;
 
 
 	/* byte size and parity */
@@ -135,23 +133,17 @@ static void change_speed(struct IsdnCard
 	serial_outp(cs, UART_IER, cs->hw.elsa.IER);
 
 	debugl1(cs,"modem quot=0x%x", quot);
-	spin_lock_irqsave(&elsa_ser_lock, flags);
 	serial_outp(cs, UART_LCR, cval | UART_LCR_DLAB);/* set DLAB */
 	serial_outp(cs, UART_DLL, quot & 0xff);		/* LS of divisor */
 	serial_outp(cs, UART_DLM, quot >> 8);		/* MS of divisor */
 	serial_outp(cs, UART_LCR, cval);		/* reset DLAB */
 	serial_inp(cs, UART_RX);
-	spin_unlock_irqrestore(&elsa_ser_lock, flags);
 }
 
 static int mstartup(struct IsdnCardState *cs)
 {
-	unsigned long flags;
 	int	retval=0;
 
-
-	spin_lock_irqsave(&elsa_ser_lock, flags);
-
 	/*
 	 * Clear the FIFO buffers and disable them
 	 * (they will be reenabled in change_speed())
@@ -207,7 +199,6 @@ static int mstartup(struct IsdnCardState
 	change_speed(cs, BASE_BAUD);
 	cs->hw.elsa.MFlag = 1;
 errout:
-	spin_unlock_irqrestore(&elsa_ser_lock, flags);
 	return retval;
 }
 
@@ -217,15 +208,11 @@ errout:
  */
 static void mshutdown(struct IsdnCardState *cs)
 {
-	unsigned long	flags;
-
 
 #ifdef SERIAL_DEBUG_OPEN
 	printk(KERN_DEBUG"Shutting down serial ....");
 #endif
 	
-	spin_lock_irqsave(&elsa_ser_lock, flags);  /* Disable interrupts */
-
 	/*
 	 * clear delta_msr_wait queue to avoid mem leaks: we may free the irq
 	 * here so the queue might never be waken up
@@ -245,7 +232,6 @@ static void mshutdown(struct IsdnCardSta
 	serial_outp(cs, UART_FCR, (UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT));
 	serial_inp(cs, UART_RX);    /* read data port to reset things */
 	
-	spin_unlock_irqrestore(&elsa_ser_lock, flags);
 #ifdef SERIAL_DEBUG_OPEN
 	printk(" done\n");
 #endif
@@ -255,14 +241,12 @@ inline int
 write_modem(struct BCState *bcs) {
 	int ret=0;
 	struct IsdnCardState *cs = bcs->cs;
-	u_int count, len, fp;
-	unsigned long flags;
+	int count, len, fp;
 	
 	if (!bcs->tx_skb)
 		return 0;
 	if (bcs->tx_skb->len <= 0)
 		return 0;
-	spin_lock_irqsave(&elsa_ser_lock, flags);
 	len = bcs->tx_skb->len;
 	if (len > MAX_MODEM_BUF - cs->hw.elsa.transcnt)
 		len = MAX_MODEM_BUF - cs->hw.elsa.transcnt;
@@ -288,14 +272,37 @@ write_modem(struct BCState *bcs) {
 			cs->hw.elsa.IER |= UART_IER_THRI;
 		serial_outp(cs, UART_IER, cs->hw.elsa.IER);
 	}
-	spin_unlock_irqrestore(&elsa_ser_lock, flags);
 	return(ret);
 }
 
-static void
-modem_fill(struct BCState *bcs)
-{
-	xmit_xpr_b(bcs);
+inline void
+modem_fill(struct BCState *bcs) {
+		
+	if (bcs->tx_skb) {
+		if (bcs->tx_skb->len) {
+			write_modem(bcs);
+			return;
+		} else {
+			if (test_bit(FLG_LLI_L1WAKEUP,&bcs->st->lli.flag) &&
+				(PACKET_NOACK != bcs->tx_skb->pkt_type)) {
+				u_long	flags;
+				spin_lock_irqsave(&bcs->aclock, flags);
+				bcs->ackcnt += bcs->hw.hscx.count;
+				spin_unlock_irqrestore(&bcs->aclock, flags);
+				schedule_event(bcs, B_ACKPENDING);
+			}
+			dev_kfree_skb_any(bcs->tx_skb);
+			bcs->tx_skb = NULL;
+		}
+	}
+	if ((bcs->tx_skb = skb_dequeue(&bcs->squeue))) {
+		bcs->hw.hscx.count = 0;
+		test_and_set_bit(BC_FLG_BUSY, &bcs->Flag);
+		write_modem(bcs);
+	} else {
+		test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
+		schedule_event(bcs, B_XMTBUFREADY);
+	}
 }
 
 static inline void receive_chars(struct IsdnCardState *cs,
@@ -329,7 +336,7 @@ static inline void receive_chars(struct 
 				cs->hw.elsa.rcvcnt);
 			skb_queue_tail(& cs->hw.elsa.bcs->rqueue, skb);
 		}
-		sched_b_event(cs->hw.elsa.bcs, B_RCVBUFREADY);
+		schedule_event(cs->hw.elsa.bcs, B_RCVBUFREADY);
 	} else {
 		char tmp[128];
 		char *t = tmp;
@@ -375,6 +382,7 @@ static inline void transmit_chars(struct
 	}
 }
 
+
 static void rs_interrupt_elsa(int irq, struct IsdnCardState *cs)
 {
 	int status, iir, msr;
@@ -419,10 +427,10 @@ close_elsastate(struct BCState *bcs)
 {
 	modehscx(bcs, 0, bcs->channel);
 	if (test_and_clear_bit(BC_FLG_INIT, &bcs->Flag)) {
-		if (bcs->rcvbuf) {
+		if (bcs->hw.hscx.rcvbuf) {
 			if (bcs->mode != L1_MODE_MODEM)
-				kfree(bcs->rcvbuf);
-			bcs->rcvbuf = NULL;
+				kfree(bcs->hw.hscx.rcvbuf);
+			bcs->hw.hscx.rcvbuf = NULL;
 		}
 		skb_queue_purge(&bcs->rqueue);
 		skb_queue_purge(&bcs->squeue);
@@ -435,16 +443,13 @@ close_elsastate(struct BCState *bcs)
 }
 
 void
-modem_write_cmd(struct IsdnCardState *cs, u8 *buf, u_int len) {
-	u_int count, fp;
-	u8 *msg = buf;
-	unsigned long flags;
+modem_write_cmd(struct IsdnCardState *cs, u_char *buf, int len) {
+	int count, fp;
+	u_char *msg = buf;
 	
 	if (!len)
 		return;
-	spin_lock_irqsave(&elsa_ser_lock, flags);
 	if (len > (MAX_MODEM_BUF - cs->hw.elsa.transcnt)) {
-		spin_unlock_irqrestore(&elsa_ser_lock, flags);
 		return;
 	}
 	fp = cs->hw.elsa.transcnt + cs->hw.elsa.transp;
@@ -465,16 +470,13 @@ modem_write_cmd(struct IsdnCardState *cs
 		cs->hw.elsa.IER |= UART_IER_THRI;
 		serial_outp(cs, UART_IER, cs->hw.elsa.IER);
 	}
-	spin_unlock_irqrestore(&elsa_ser_lock, flags);
 }
 
 void
 modem_set_init(struct IsdnCardState *cs) {
-	unsigned long flags;
 	int timeout;
 
 #define RCV_DELAY 20000	
-	spin_lock_irqsave(&elsa_ser_lock, flags);
 	modem_write_cmd(cs, MInit_1, strlen(MInit_1));
 	timeout = 1000;
 	while(timeout-- && cs->hw.elsa.transcnt)
@@ -517,16 +519,13 @@ modem_set_init(struct IsdnCardState *cs)
 		udelay(1000);
 	debugl1(cs, "msi tout=%d", timeout);
 	udelay(RCV_DELAY);
-	spin_unlock_irqrestore(&elsa_ser_lock, flags);
 }
 
 void
 modem_set_dial(struct IsdnCardState *cs, int outgoing) {
-	unsigned long flags;
 	int timeout;
 #define RCV_DELAY 20000	
 
-	spin_lock_irqsave(&elsa_ser_lock, flags);
 	modem_write_cmd(cs, MInit_speed28800, strlen(MInit_speed28800));
 	timeout = 1000;
 	while(timeout-- && cs->hw.elsa.transcnt)
@@ -542,40 +541,39 @@ modem_set_dial(struct IsdnCardState *cs,
 		udelay(1000);
 	debugl1(cs, "msi tout=%d", timeout);
 	udelay(RCV_DELAY);
-	spin_unlock_irqrestore(&elsa_ser_lock, flags);
 }
 
 void
 modem_l2l1(struct PStack *st, int pr, void *arg)
 {
+	struct BCState *bcs = st->l1.bcs;
 	struct sk_buff *skb = arg;
-	unsigned long flags;
+	u_long flags;
 
 	if (pr == (PH_DATA | REQUEST)) {
-		spin_lock_irqsave(&elsa_ser_lock, flags);
-		if (st->l1.bcs->tx_skb) {
-			skb_queue_tail(&st->l1.bcs->squeue, skb);
-			spin_unlock_irqrestore(&elsa_ser_lock, flags);
+		spin_lock_irqsave(&bcs->cs->lock, flags);
+		if (bcs->tx_skb) {
+			skb_queue_tail(&bcs->squeue, skb);
 		} else {
-			st->l1.bcs->tx_skb = skb;
-			test_and_set_bit(BC_FLG_BUSY, &st->l1.bcs->Flag);
-			st->l1.bcs->count = 0;
-			spin_unlock_irqrestore(&elsa_ser_lock, flags);
-			write_modem(st->l1.bcs);
+			bcs->tx_skb = skb;
+			test_and_set_bit(BC_FLG_BUSY, &bcs->Flag);
+			bcs->hw.hscx.count = 0;
+			write_modem(bcs);
 		}
+		spin_unlock_irqrestore(&bcs->cs->lock, flags);
 	} else if (pr == (PH_ACTIVATE | REQUEST)) {
-		test_and_set_bit(BC_FLG_ACTIV, &st->l1.bcs->Flag);
-		L1L2(st, PH_ACTIVATE | CONFIRM, NULL);
-		set_arcofi(st->l1.bcs->cs, st->l1.bc);
-		mstartup(st->l1.bcs->cs);
-		modem_set_dial(st->l1.bcs->cs, test_bit(FLG_ORIG, &st->l2.flag));
-		st->l1.bcs->cs->hw.elsa.MFlag=2;
+		test_and_set_bit(BC_FLG_ACTIV, &bcs->Flag);
+		st->l1.l1l2(st, PH_ACTIVATE | CONFIRM, NULL);
+		set_arcofi(bcs->cs, st->l1.bc);
+		mstartup(bcs->cs);
+		modem_set_dial(bcs->cs, test_bit(FLG_ORIG, &st->l2.flag));
+		bcs->cs->hw.elsa.MFlag=2;
 	} else if (pr == (PH_DEACTIVATE | REQUEST)) {
-		test_and_clear_bit(BC_FLG_ACTIV, &st->l1.bcs->Flag);
-		st->l1.bcs->cs->dc.isac.arcofi_bc = st->l1.bc;
-		arcofi_fsm(st->l1.bcs->cs, ARCOFI_START, &ARCOFI_XOP_0);
-		interruptible_sleep_on(&st->l1.bcs->cs->dc.isac.arcofi_wait);
-		st->l1.bcs->cs->hw.elsa.MFlag=1;
+		test_and_clear_bit(BC_FLG_ACTIV, &bcs->Flag);
+		bcs->cs->dc.isac.arcofi_bc = st->l1.bc;
+		arcofi_fsm(bcs->cs, ARCOFI_START, &ARCOFI_XOP_0);
+		interruptible_sleep_on(&bcs->cs->dc.isac.arcofi_wait);
+		bcs->cs->hw.elsa.MFlag=1;
 	} else {
 		printk(KERN_WARNING"ElsaSer: unknown pr %x\n", pr);
 	}
@@ -591,24 +589,22 @@ setstack_elsa(struct PStack *st, struct 
 		case L1_MODE_TRANS:
 			if (open_hscxstate(st->l1.hardware, bcs))
 				return (-1);
-			st->l1.l2l1 = hscx_l2l1;
-			// bcs->cs->BC_Send_Data = hscx_fill_fifo; FIXME
+			st->l2.l2l1 = hscx_l2l1;
 			break;
 		case L1_MODE_MODEM:
 			bcs->mode = L1_MODE_MODEM;
 			if (!test_and_set_bit(BC_FLG_INIT, &bcs->Flag)) {
-				bcs->rcvbuf = bcs->cs->hw.elsa.rcvbuf;
+				bcs->hw.hscx.rcvbuf = bcs->cs->hw.elsa.rcvbuf;
 				skb_queue_head_init(&bcs->rqueue);
 				skb_queue_head_init(&bcs->squeue);
 			}
 			bcs->tx_skb = NULL;
 			test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
 			bcs->event = 0;
-			bcs->rcvidx = 0;
+			bcs->hw.hscx.rcvidx = 0;
 			bcs->tx_cnt = 0;
 			bcs->cs->hw.elsa.bcs = bcs;
-			st->l1.l2l1 = modem_l2l1;
-//			bcs->cs->bc_l1_ops = &modem_l1_ops;
+			st->l2.l2l1 = modem_l2l1;
 			break;
 	}
 	st->l1.bcs = bcs;
@@ -618,17 +614,13 @@ setstack_elsa(struct PStack *st, struct 
 	return (0);
 }
 
-static struct bc_l1_ops modem_l1_ops = {
-	.fill_fifo = modem_fill,
-	.open      = setstack_elsa,
-	.close     = close_elsastate,
-};
-
 void
-init_modem(struct IsdnCardState *cs)
-{
-	cs->bc_l1_ops = &modem_l1_ops;
+init_modem(struct IsdnCardState *cs) {
 
+	cs->bcs[0].BC_SetStack = setstack_elsa;
+	cs->bcs[1].BC_SetStack = setstack_elsa;
+	cs->bcs[0].BC_Close = close_elsastate;
+	cs->bcs[1].BC_Close = close_elsastate;
 	if (!(cs->hw.elsa.rcvbuf = kmalloc(MAX_MODEM_BUF,
 		GFP_ATOMIC))) {
 		printk(KERN_WARNING
--- diff/drivers/isdn/hisax/enternow.h	2003-01-13 14:18:15.000000000 +0000
+++ source/drivers/isdn/hisax/enternow.h	2004-02-23 13:56:42.000000000 +0000
@@ -40,3 +40,12 @@
  * den TigerJet i/o-Raum gemappt
  * -> 0x01 des AMD bei hw.njet.base + 0C4 */
 #define TJ_AMD_PORT						0xC0
+
+
+
+/* ***************************************************************************************** *
+ * *************************************** Prototypen ************************************** *
+ * ***************************************************************************************** */
+
+BYTE ReadByteAmd7930(struct IsdnCardState *cs, BYTE offset);
+void WriteByteAmd7930(struct IsdnCardState *cs, BYTE offset, BYTE value);
--- diff/drivers/isdn/hisax/enternow_pci.c	2003-05-21 11:50:15.000000000 +0100
+++ source/drivers/isdn/hisax/enternow_pci.c	2004-02-23 13:56:42.000000000 +0000
@@ -74,13 +74,14 @@
 
 
 
-const char *enternow_pci_rev = "$Revision: 1.1.2.1 $";
+const char *enternow_pci_rev = "$Revision: 1.1.4.5 $";
+
 
 /* *************************** I/O-Interface functions ************************************* */
 
 
 /* cs->readisac, macro rByteAMD */
-static BYTE
+BYTE
 ReadByteAmd7930(struct IsdnCardState *cs, BYTE offset)
 {
 	/* direktes Register */
@@ -95,7 +96,7 @@ ReadByteAmd7930(struct IsdnCardState *cs
 }
 
 /* cs->writeisac, macro wByteAMD */
-static void
+void
 WriteByteAmd7930(struct IsdnCardState *cs, BYTE offset, BYTE value)
 {
 	/* direktes Register */
@@ -110,14 +111,8 @@ WriteByteAmd7930(struct IsdnCardState *c
 }
 
 
-static struct dc_hw_ops amd7930_ops = {
-	.read_reg   = ReadByteAmd7930,
-	.write_reg  = WriteByteAmd7930,
-};
-
-static void
-enpci_setIrqMask(struct IsdnCardState *cs, BYTE val)
-{
+void
+enpci_setIrqMask(struct IsdnCardState *cs, BYTE val) {
         if (!val)
 	        OutByte(cs->hw.njet.base+NETJET_IRQMASK1, 0x00);
         else
@@ -125,6 +120,17 @@ enpci_setIrqMask(struct IsdnCardState *c
 }
 
 
+static BYTE dummyrr(struct IsdnCardState *cs, int chan, BYTE off)
+{
+        return(5);
+}
+
+static void dummywr(struct IsdnCardState *cs, int chan, BYTE off, BYTE value)
+{
+
+}
+
+
 /* ******************************************************************************** */
 
 
@@ -137,15 +143,12 @@ reset_enpci(struct IsdnCardState *cs)
 	/* Reset on, (also for AMD) */
 	cs->hw.njet.ctrl_reg = 0x07;
 	OutByte(cs->hw.njet.base + NETJET_CTRL, cs->hw.njet.ctrl_reg);
-	set_current_state(TASK_UNINTERRUPTIBLE);
-	/* 80 ms delay */
-	schedule_timeout((80*HZ)/1000);
+	mdelay(20);
 	/* Reset off */
-	cs->hw.njet.ctrl_reg = 0x70;
+	cs->hw.njet.ctrl_reg = 0x30;
 	OutByte(cs->hw.njet.base + NETJET_CTRL, cs->hw.njet.ctrl_reg);
-	set_current_state(TASK_UNINTERRUPTIBLE);
-	/* 80ms delay */
-	schedule_timeout((80*HZ)/1000);
+	/* 20ms delay */
+	mdelay(20);
 	cs->hw.njet.auxd = 0;  // LED-status
 	cs->hw.njet.dmactrl = 0;
 	OutByte(cs->hw.njet.base + NETJET_AUXCTRL, ~TJ_AMD_IRQ);
@@ -153,96 +156,124 @@ reset_enpci(struct IsdnCardState *cs)
 	OutByte(cs->hw.njet.auxa, cs->hw.njet.auxd); // LED off
 }
 
-static void
-enpci_bc_activate(struct IsdnCardState *cs, int chan)
-{
-	if (cs->debug & L1_DEB_ISAC)
-		debugl1(cs, "enter:now PCI: assign phys. BC %d in AMD LMR1", chan);
-	
-	cs->dc.amd7930.ph_command(cs, (cs->dc.amd7930.lmr1 | (chan + 1)), "MDL_BC_ASSIGN");
-	/* at least one b-channel in use, LED 2 on */
-	cs->hw.njet.auxd |= TJ_AMD_IRQ << 2;
-	OutByte(cs->hw.njet.base + NETJET_AUXDATA, cs->hw.njet.auxd);
-}
 
-static void
-enpci_bc_deactivate(struct IsdnCardState *cs, int chan)
+static int
+enpci_card_msg(struct IsdnCardState *cs, int mt, void *arg)
 {
-	if (cs->debug & L1_DEB_ISAC)
-		debugl1(cs, "enter:now PCI: release phys. BC %d in Amd LMR1", chan);
-	
-	cs->dc.amd7930.ph_command(cs, (cs->dc.amd7930.lmr1 & ~(chan + 1)), "MDL_BC_RELEASE");
-	/* no b-channel active -> LED2 off */
-	if (!(cs->dc.amd7930.lmr1 & 3)) {
-		cs->hw.njet.auxd &= ~(TJ_AMD_IRQ << 2);
-		OutByte(cs->hw.njet.base + NETJET_AUXDATA, cs->hw.njet.auxd);
-	}
-}
+	u_long flags;
+        BYTE *chan;
 
-static void
-enpci_led_handler(struct IsdnCardState *cs)
-{
-	if (cs->status & 0x0001) {
-		/* TEI assigned, LED1 on */
-		cs->hw.njet.auxd = TJ_AMD_IRQ << 1;
-		OutByte(cs->hw.njet.base + NETJET_AUXDATA, cs->hw.njet.auxd);
-	} else {
-		/* TEI removed, LEDs off */
-		cs->hw.njet.auxd = 0;
-		OutByte(cs->hw.njet.base + NETJET_AUXDATA, 0x00);
-	}
-}
+	if (cs->debug & L1_DEB_ISAC)
+		debugl1(cs, "enter:now PCI: card_msg: 0x%04X", mt);
 
-static void
-enpci_init(struct IsdnCardState *cs)
-{
-	inittiger(cs);
-	Amd7930_init(cs);
-}
+        switch (mt) {
+		case CARD_RESET:
+			spin_lock_irqsave(&cs->lock, flags);
+			reset_enpci(cs);
+                        Amd7930_init(cs);
+                        spin_unlock_irqrestore(&cs->lock, flags);
+			break;
+		case CARD_RELEASE:
+			release_io_netjet(cs);
+			break;
+		case CARD_INIT:
+			reset_enpci(cs);
+			inittiger(cs);
+			/* irq must be on here */
+			Amd7930_init(cs);
+			break;
+		case CARD_TEST:
+			break;
+                case MDL_ASSIGN:
+                        /* TEI assigned, LED1 on */
+                        cs->hw.njet.auxd = TJ_AMD_IRQ << 1;
+                        OutByte(cs->hw.njet.base + NETJET_AUXDATA, cs->hw.njet.auxd);
+                        break;
+                case MDL_REMOVE:
+                        /* TEI removed, LEDs off */
+	                cs->hw.njet.auxd = 0;
+                        OutByte(cs->hw.njet.base + NETJET_AUXDATA, 0x00);
+                        break;
+                case MDL_BC_ASSIGN:
+                        /* activate B-channel */
+                        chan = (BYTE *)arg;
+
+                        if (cs->debug & L1_DEB_ISAC)
+		                debugl1(cs, "enter:now PCI: assign phys. BC %d in AMD LMR1", *chan);
+
+                        cs->dc.amd7930.ph_command(cs, (cs->dc.amd7930.lmr1 | (*chan + 1)), "MDL_BC_ASSIGN");
+                        /* at least one b-channel in use, LED 2 on */
+                        cs->hw.njet.auxd |= TJ_AMD_IRQ << 2;
+                        OutByte(cs->hw.njet.base + NETJET_AUXDATA, cs->hw.njet.auxd);
+                        break;
+                case MDL_BC_RELEASE:
+                        /* deactivate B-channel */
+                        chan = (BYTE *)arg;
+
+                        if (cs->debug & L1_DEB_ISAC)
+		                debugl1(cs, "enter:now PCI: release phys. BC %d in Amd LMR1", *chan);
+
+                        cs->dc.amd7930.ph_command(cs, (cs->dc.amd7930.lmr1 & ~(*chan + 1)), "MDL_BC_RELEASE");
+                        /* no b-channel active -> LED2 off */
+                        if (!(cs->dc.amd7930.lmr1 & 3)) {
+                                cs->hw.njet.auxd &= ~(TJ_AMD_IRQ << 2);
+                                OutByte(cs->hw.njet.base + NETJET_AUXDATA, cs->hw.njet.auxd);
+                        }
+                        break;
+                default:
+                        break;
 
-static int
-enpci_reset(struct IsdnCardState *cs)
-{
-	reset_enpci(cs);
-	Amd7930_init(cs);
-	return 0;
+	}
+	return(0);
 }
 
 static irqreturn_t
 enpci_interrupt(int intno, void *dev_id, struct pt_regs *regs)
 {
 	struct IsdnCardState *cs = dev_id;
-	BYTE sval, ir;
-
-	spin_lock(&cs->lock);
+	BYTE s0val, s1val, ir;
+	u_long flags;
 
-	sval = InByte(cs->hw.njet.base + NETJET_IRQSTAT1);
+	spin_lock_irqsave(&cs->lock, flags);
+	s1val = InByte(cs->hw.njet.base + NETJET_IRQSTAT1);
 
         /* AMD threw an interrupt */
-	if (!(sval & TJ_AMD_IRQ)) {
+	if (!(s1val & TJ_AMD_IRQ)) {
                 /* read and clear interrupt-register */
 		ir = ReadByteAmd7930(cs, 0x00);
 		Amd7930_interrupt(cs, ir);
-	}
+		s1val = 1;
+	} else
+		s1val = 0;
+	s0val = InByte(cs->hw.njet.base + NETJET_IRQSTAT0);
+	if ((s0val | s1val)==0) { // shared IRQ
+		spin_unlock_irqrestore(&cs->lock, flags);
+		return IRQ_NONE;
+	} 
+	if (s0val)
+		OutByte(cs->hw.njet.base + NETJET_IRQSTAT0, s0val);
 
 	/* DMA-Interrupt: B-channel-stuff */
 	/* set bits in sval to indicate which page is free */
-
-	/* set bits in sval to indicate which page is free */
 	if (inl(cs->hw.njet.base + NETJET_DMA_WRITE_ADR) <
 		inl(cs->hw.njet.base + NETJET_DMA_WRITE_IRQ))
 		/* the 2nd write page is free */
-		sval = 0x08;
+		s0val = 0x08;
 	else	/* the 1st write page is free */
-		sval = 0x04;
+		s0val = 0x04;
 	if (inl(cs->hw.njet.base + NETJET_DMA_READ_ADR) <
 		inl(cs->hw.njet.base + NETJET_DMA_READ_IRQ))
 		/* the 2nd read page is free */
-		sval = sval | 0x02;
+		s0val = s0val | 0x02;
 	else	/* the 1st read page is free */
-		sval = sval | 0x01;
-	if (sval != cs->hw.njet.last_is0) { /* we have a DMA interrupt */
-		cs->hw.njet.irqstat0 = sval;
+		s0val = s0val | 0x01;
+	if (s0val != cs->hw.njet.last_is0) /* we have a DMA interrupt */
+	{
+		if (test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) {
+			spin_unlock_irqrestore(&cs->lock, flags);
+			return IRQ_HANDLED;
+		}
+		cs->hw.njet.irqstat0 = s0val;
 		if ((cs->hw.njet.irqstat0 & NETJET_IRQM0_READ) !=
 			(cs->hw.njet.last_is0 & NETJET_IRQM0_READ))
 			/* we have a read dma int */
@@ -251,71 +282,12 @@ enpci_interrupt(int intno, void *dev_id,
 			(cs->hw.njet.last_is0 & NETJET_IRQM0_WRITE))
 			/* we have a write dma int */
 			write_tiger(cs);
+		test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);
 	}
-	spin_unlock(&cs->lock);
+	spin_unlock_irqrestore(&cs->lock, flags);
 	return IRQ_HANDLED;
 }
 
-static struct card_ops enpci_ops = {
-	.init        = enpci_init,
-	.reset       = enpci_reset,
-	.release     = netjet_release,
-	.led_handler = enpci_led_handler,
-	.irq_func    = enpci_interrupt,
-};
-
-static int __init
-enpci_probe(struct IsdnCardState *cs, struct pci_dev *pdev)
-{
-	if (pci_enable_device(pdev))
-		goto err;
-			
-	cs->irq = pdev->irq;
-	cs->irq_flags |= SA_SHIRQ;
-	cs->hw.njet.base = pci_resource_start(pdev, 0);
-	if (!request_io(&cs->rs, cs->hw.njet.base, 0x100, "Fn_ISDN"))
-		goto err;
-
-	cs->hw.njet.auxa = cs->hw.njet.base + NETJET_AUXDATA;
-	cs->hw.njet.isac = cs->hw.njet.base + 0xC0; // Fenster zum AMD
-
-	/* Reset an */
-	cs->hw.njet.ctrl_reg = 0x07;  // geändert von 0xff
-	OutByte(cs->hw.njet.base + NETJET_CTRL, cs->hw.njet.ctrl_reg);
-	
-	set_current_state(TASK_UNINTERRUPTIBLE);
-	/* 50 ms Pause */
-	schedule_timeout((50*HZ)/1000);
-	
-	cs->hw.njet.ctrl_reg = 0x30;  /* Reset Off and status read clear */
-	OutByte(cs->hw.njet.base + NETJET_CTRL, cs->hw.njet.ctrl_reg);
-	
-	set_current_state(TASK_UNINTERRUPTIBLE);
-	schedule_timeout((10*HZ)/1000);	/* Timeout 10ms */
-	
-	cs->hw.njet.auxd = 0x00; // war 0xc0
-	cs->hw.njet.dmactrl = 0;
-	
-	OutByte(cs->hw.njet.base + NETJET_AUXCTRL, ~TJ_AMD_IRQ);
-	OutByte(cs->hw.njet.base + NETJET_IRQMASK1, TJ_AMD_IRQ);
-	OutByte(cs->hw.njet.auxa, cs->hw.njet.auxd);
-	
-	printk(KERN_INFO
-	       "enter:now PCI: PCI card configured at 0x%lx IRQ %d\n",
-	       cs->hw.njet.base, cs->irq);
-	reset_enpci(cs);
-	cs->hw.njet.last_is0 = 0;
-	cs->hw.njet.bc_activate = enpci_bc_activate;
-	cs->hw.njet.bc_deactivate = enpci_bc_deactivate;
-	amd7930_setup(cs, &amd7930_ops, &enpci_setIrqMask);
-
-	cs->card_ops = &enpci_ops;
-
-	return 0;
- err:
-	hisax_release_resources(cs);
-	return -EBUSY;
-}
 
 static struct pci_dev *dev_netjet __initdata = NULL;
 
@@ -323,30 +295,105 @@ static struct pci_dev *dev_netjet __init
 int __init
 setup_enternow_pci(struct IsdnCard *card)
 {
+	int bytecnt;
+	struct IsdnCardState *cs = card->cs;
 	char tmp[64];
 
+#if CONFIG_PCI
 #ifdef __BIG_ENDIAN
 #error "not running on big endian machines now"
 #endif
         strcpy(tmp, enternow_pci_rev);
 	printk(KERN_INFO "HiSax: Formula-n Europe AG enter:now ISDN PCI driver Rev. %s\n", HiSax_getrev(tmp));
-
-	dev_netjet = pci_find_device(PCI_VENDOR_ID_TIGERJET,
-				     PCI_DEVICE_ID_TIGERJET_300, dev_netjet);
-	if (dev_netjet) {
-		if (dev_netjet->subsystem_vendor != 0x55 ||
-		    dev_netjet->subsystem_device != 0x02) {
-			printk(KERN_WARNING "enter:now: You tried to load "
-			       "this driver with an incompatible "
-			       "TigerJet-card\n");
-			printk(KERN_WARNING "Use type=20 for Traverse "
-			       "NetJet PCI Card.\n");
-			return 0;
+	if (cs->typ != ISDN_CTYPE_ENTERNOW)
+		return(0);
+	test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);
+
+	for ( ;; )
+	{
+		if ((dev_netjet = pci_find_device(PCI_VENDOR_ID_TIGERJET,
+			PCI_DEVICE_ID_TIGERJET_300,  dev_netjet))) {
+			if (pci_enable_device(dev_netjet))
+				return(0);
+			cs->irq = dev_netjet->irq;
+			if (!cs->irq) {
+				printk(KERN_WARNING "enter:now PCI: No IRQ for PCI card found\n");
+				return(0);
+			}
+			cs->hw.njet.base = pci_resource_start(dev_netjet, 0);
+			if (!cs->hw.njet.base) {
+				printk(KERN_WARNING "enter:now PCI: No IO-Adr for PCI card found\n");
+				return(0);
+			}
+                        /* checks Sub-Vendor ID because system crashes with Traverse-Card */
+			if ((dev_netjet->subsystem_vendor != 0x55) ||
+				(dev_netjet->subsystem_device != 0x02)) {
+				printk(KERN_WARNING "enter:now: You tried to load this driver with an incompatible TigerJet-card\n");
+                                printk(KERN_WARNING "Use type=20 for Traverse NetJet PCI Card.\n");
+                                return(0);
+                        }
+		} else {
+                        printk(KERN_WARNING "enter:now PCI: No PCI card found\n");
+			return(0);
 		}
-		if (enpci_probe(card->cs, dev_netjet))
-			return 1;
-		return 0;
+
+		cs->hw.njet.auxa = cs->hw.njet.base + NETJET_AUXDATA;
+		cs->hw.njet.isac = cs->hw.njet.base + 0xC0; // Fenster zum AMD
+
+		/* Reset an */
+		cs->hw.njet.ctrl_reg = 0x07;  // geändert von 0xff
+		OutByte(cs->hw.njet.base + NETJET_CTRL, cs->hw.njet.ctrl_reg);
+		/* 20 ms Pause */
+		mdelay(20);
+
+		cs->hw.njet.ctrl_reg = 0x30;  /* Reset Off and status read clear */
+		OutByte(cs->hw.njet.base + NETJET_CTRL, cs->hw.njet.ctrl_reg);
+		mdelay(10);
+
+		cs->hw.njet.auxd = 0x00; // war 0xc0
+		cs->hw.njet.dmactrl = 0;
+
+		OutByte(cs->hw.njet.base + NETJET_AUXCTRL, ~TJ_AMD_IRQ);
+		OutByte(cs->hw.njet.base + NETJET_IRQMASK1, TJ_AMD_IRQ);
+		OutByte(cs->hw.njet.auxa, cs->hw.njet.auxd);
+
+		break;
+	}
+#else
+
+	printk(KERN_WARNING "enter:now PCI: NO_PCI_BIOS\n");
+	printk(KERN_WARNING "enter:now PCI: unable to config Formula-n enter:now ISDN PCI ab\n");
+	return (0);
+
+#endif /* CONFIG_PCI */
+
+	bytecnt = 256;
+
+	printk(KERN_INFO
+		"enter:now PCI: PCI card configured at 0x%lx IRQ %d\n",
+		cs->hw.njet.base, cs->irq);
+	if (!request_region(cs->hw.njet.base, bytecnt, "Fn_ISDN")) {
+		printk(KERN_WARNING
+			   "HiSax: %s config port %lx-%lx already in use\n",
+			   CardType[card->typ],
+			   cs->hw.njet.base,
+			   cs->hw.njet.base + bytecnt);
+		return (0);
 	}
-	printk(KERN_WARNING "enter:now PCI: No PCI card found\n");
-	return 0;
+	setup_Amd7930(cs);
+	cs->hw.njet.last_is0 = 0;
+        /* macro rByteAMD */
+        cs->readisac = &ReadByteAmd7930;
+        /* macro wByteAMD */
+        cs->writeisac = &WriteByteAmd7930;
+        cs->dc.amd7930.setIrqMask = &enpci_setIrqMask;
+
+        cs->BC_Read_Reg  = &dummyrr;
+	cs->BC_Write_Reg = &dummywr;
+	cs->BC_Send_Data = &netjet_fill_dma;
+	cs->cardmsg = &enpci_card_msg;
+	cs->irq_func = &enpci_interrupt;
+	cs->irq_flags |= SA_SHIRQ;
+
+        return (1);
 }
--- diff/drivers/isdn/hisax/gazel.c	2003-05-21 11:49:50.000000000 +0100
+++ source/drivers/isdn/hisax/gazel.c	2004-02-23 13:56:42.000000000 +0000
@@ -1,4 +1,4 @@
-/* $Id: gazel.c,v 2.11.6.7 2001/09/23 22:24:47 kai Exp $
+/* $Id: gazel.c,v 2.19.2.4 2004/01/14 16:04:48 keil Exp $
  *
  * low level stuff for Gazel isdn cards
  *
@@ -21,8 +21,7 @@
 #include <linux/pci.h>
 
 extern const char *CardType[];
-const char *gazel_revision = "$Revision: 2.11.6.7 $";
-static spinlock_t gazel_lock = SPIN_LOCK_UNLOCKED;
+const char *gazel_revision = "$Revision: 2.19.2.4 $";
 
 #define R647      1
 #define R685      2
@@ -44,492 +43,642 @@ static spinlock_t gazel_lock = SPIN_LOCK
 #define byteout(addr,val) outb(val,addr)
 #define bytein(addr) inb(addr)
 
-static inline u8
+static inline u_char
 readreg(unsigned int adr, u_short off)
 {
 	return bytein(adr + off);
 }
 
 static inline void
-writereg(unsigned int adr, u_short off, u8 data)
+writereg(unsigned int adr, u_short off, u_char data)
 {
 	byteout(adr + off, data);
 }
 
 
 static inline void
-read_fifo(unsigned int adr, u8 * data, int size)
+read_fifo(unsigned int adr, u_char * data, int size)
 {
 	insb(adr, data, size);
 }
 
 static void
-write_fifo(unsigned int adr, u8 * data, int size)
+write_fifo(unsigned int adr, u_char * data, int size)
 {
 	outsb(adr, data, size);
 }
 
-static u8
-r685_isac_read(struct IsdnCardState *cs, u8 off)
+static inline u_char
+readreg_ipac(unsigned int adr, u_short off)
 {
-	return readreg(cs->hw.gazel.isac, off);
-}
+	register u_char ret;
 
-static u8
-r647_isac_read(struct IsdnCardState *cs, u8 off)
-{
-	return readreg(cs->hw.gazel.isac, (off << 8 & 0xf000) | (off & 0xf));
+	byteout(adr, off);
+	ret = bytein(adr + 4);
+	return ret;
 }
 
-static void
-r685_isac_write(struct IsdnCardState *cs, u8 off, u8 value)
+static inline void
+writereg_ipac(unsigned int adr, u_short off, u_char data)
 {
-	writereg(cs->hw.gazel.isac, off, value);
+	byteout(adr, off);
+	byteout(adr + 4, data);
 }
 
-static void
-r647_isac_write(struct IsdnCardState *cs, u8 off, u8 value)
-{
-	writereg(cs->hw.gazel.isac, (off << 8 & 0xf000) | (off & 0xf), value);
-}
 
-static void
-isac_read_fifo(struct IsdnCardState *cs, u8 * data, int size)
+static inline void
+read_fifo_ipac(unsigned int adr, u_short off, u_char * data, int size)
 {
-	read_fifo(cs->hw.gazel.isacfifo, data, size);
+	byteout(adr, off);
+	insb(adr + 4, data, size);
 }
 
 static void
-isac_write_fifo(struct IsdnCardState *cs, u8 * data, int size)
+write_fifo_ipac(unsigned int adr, u_short off, u_char * data, int size)
 {
-	write_fifo(cs->hw.gazel.isacfifo, data, size);
+	byteout(adr, off);
+	outsb(adr + 4, data, size);
 }
 
-static struct dc_hw_ops r685_isac_ops = {
-	.read_reg   = r685_isac_read,
-	.write_reg  = r685_isac_write,
-	.read_fifo  = isac_read_fifo,
-	.write_fifo = isac_write_fifo,
-};
+/* Interface functions */
 
-static struct dc_hw_ops r647_isac_ops = {
-	.read_reg   = r647_isac_read,
-	.write_reg  = r647_isac_write,
-	.read_fifo  = isac_read_fifo,
-	.write_fifo = isac_write_fifo,
-};
-  
-static u8
-r685_hscx_read(struct IsdnCardState *cs, int hscx, u8 off)
+static u_char
+ReadISAC(struct IsdnCardState *cs, u_char offset)
 {
-	return readreg(cs->hw.gazel.hscx[hscx], off);
+	u_short off2 = offset;
+
+	switch (cs->subtyp) {
+		case R647:
+			off2 = ((off2 << 8 & 0xf000) | (off2 & 0xf));
+		case R685:
+			return (readreg(cs->hw.gazel.isac, off2));
+		case R753:
+		case R742:
+			return (readreg_ipac(cs->hw.gazel.ipac, 0x80 + off2));
+	}
+	return 0;
 }
 
-static u8
-r647_hscx_read(struct IsdnCardState *cs, int hscx, u8 off)
+static void
+WriteISAC(struct IsdnCardState *cs, u_char offset, u_char value)
 {
-	return readreg(cs->hw.gazel.hscx[hscx],
-		       (off << 8 & 0xf000) | (off & 0xf));
+	u_short off2 = offset;
+
+	switch (cs->subtyp) {
+		case R647:
+			off2 = ((off2 << 8 & 0xf000) | (off2 & 0xf));
+		case R685:
+			writereg(cs->hw.gazel.isac, off2, value);
+			break;
+		case R753:
+		case R742:
+			writereg_ipac(cs->hw.gazel.ipac, 0x80 + off2, value);
+			break;
+	}
 }
 
 static void
-r685_hscx_write(struct IsdnCardState *cs, int hscx, u8 off, u8 value)
+ReadISACfifo(struct IsdnCardState *cs, u_char * data, int size)
 {
-	writereg(cs->hw.gazel.hscx[hscx], off, value);
+	switch (cs->subtyp) {
+		case R647:
+		case R685:
+			read_fifo(cs->hw.gazel.isacfifo, data, size);
+			break;
+		case R753:
+		case R742:
+			read_fifo_ipac(cs->hw.gazel.ipac, 0x80, data, size);
+			break;
+	}
 }
 
 static void
-r647_hscx_write(struct IsdnCardState *cs, int hscx, u8 off, u8 value)
+WriteISACfifo(struct IsdnCardState *cs, u_char * data, int size)
 {
-	writereg(cs->hw.gazel.hscx[hscx],
-		 (off << 8 & 0xf000) | (off & 0xf), value);
+	switch (cs->subtyp) {
+		case R647:
+		case R685:
+			write_fifo(cs->hw.gazel.isacfifo, data, size);
+			break;
+		case R753:
+		case R742:
+			write_fifo_ipac(cs->hw.gazel.ipac, 0x80, data, size);
+			break;
+	}
 }
 
 static void
-hscx_read_fifo(struct IsdnCardState *cs, int hscx, u8 * data, int size)
+ReadHSCXfifo(struct IsdnCardState *cs, int hscx, u_char * data, int size)
 {
-	read_fifo(cs->hw.gazel.hscxfifo[hscx], data, size);
+	switch (cs->subtyp) {
+		case R647:
+		case R685:
+			read_fifo(cs->hw.gazel.hscxfifo[hscx], data, size);
+			break;
+		case R753:
+		case R742:
+			read_fifo_ipac(cs->hw.gazel.ipac, hscx * 0x40, data, size);
+			break;
+	}
 }
 
 static void
-hscx_write_fifo(struct IsdnCardState *cs, int hscx, u8 * data, int size)
+WriteHSCXfifo(struct IsdnCardState *cs, int hscx, u_char * data, int size)
 {
-	write_fifo(cs->hw.gazel.hscxfifo[hscx], data, size);
+	switch (cs->subtyp) {
+		case R647:
+		case R685:
+			write_fifo(cs->hw.gazel.hscxfifo[hscx], data, size);
+			break;
+		case R753:
+		case R742:
+			write_fifo_ipac(cs->hw.gazel.ipac, hscx * 0x40, data, size);
+			break;
+	}
 }
 
-static struct bc_hw_ops r685_hscx_ops = {
-	.read_reg   = r685_hscx_read,
-	.write_reg  = r685_hscx_write,
-	.read_fifo  = hscx_read_fifo,
-	.write_fifo = hscx_write_fifo,
-};
-
-static struct bc_hw_ops r647_hscx_ops = {
-	.read_reg   = r647_hscx_read,
-	.write_reg  = r647_hscx_write,
-	.read_fifo  = hscx_read_fifo,
-	.write_fifo = hscx_write_fifo,
-};
-
-static inline u8
-ipac_read(struct IsdnCardState *cs, u_short off)
-{
-	register u8 ret;
-	unsigned long flags;
-
-	spin_lock_irqsave(&gazel_lock, flags);
-	byteout(cs->hw.gazel.ipac, off);
-	ret = bytein(cs->hw.gazel.ipac + 4);
-	spin_unlock_irqrestore(&gazel_lock, flags);
-	return ret;
+static u_char
+ReadHSCX(struct IsdnCardState *cs, int hscx, u_char offset)
+{
+	u_short off2 = offset;
+
+	switch (cs->subtyp) {
+		case R647:
+			off2 = ((off2 << 8 & 0xf000) | (off2 & 0xf));
+		case R685:
+			return (readreg(cs->hw.gazel.hscx[hscx], off2));
+		case R753:
+		case R742:
+			return (readreg_ipac(cs->hw.gazel.ipac, hscx * 0x40 + off2));
+	}
+	return 0;
 }
 
-static inline void
-ipac_write(struct IsdnCardState *cs, u_short off, u8 data)
+static void
+WriteHSCX(struct IsdnCardState *cs, int hscx, u_char offset, u_char value)
 {
-	unsigned long flags;
+	u_short off2 = offset;
 
-	spin_lock_irqsave(&gazel_lock, flags);
-	byteout(cs->hw.gazel.ipac, off);
-	byteout(cs->hw.gazel.ipac + 4, data);
-	spin_unlock_irqrestore(&gazel_lock, flags);
+	switch (cs->subtyp) {
+		case R647:
+			off2 = ((off2 << 8 & 0xf000) | (off2 & 0xf));
+		case R685:
+			writereg(cs->hw.gazel.hscx[hscx], off2, value);
+			break;
+		case R753:
+		case R742:
+			writereg_ipac(cs->hw.gazel.ipac, hscx * 0x40 + off2, value);
+			break;
+	}
 }
 
+/*
+ * fast interrupt HSCX stuff goes here
+ */
 
-static inline void
-ipac_readfifo(struct IsdnCardState *cs, u8 off, u8 * data, int size)
-{
-	byteout(cs->hw.gazel.ipac, off);
-	insb(cs->hw.gazel.ipac + 4, data, size);
+#define READHSCX(cs, nr, reg) ReadHSCX(cs, nr, reg)
+#define WRITEHSCX(cs, nr, reg, data) WriteHSCX(cs, nr, reg, data)
+#define READHSCXFIFO(cs, nr, ptr, cnt) ReadHSCXfifo(cs, nr, ptr, cnt)
+#define WRITEHSCXFIFO(cs, nr, ptr, cnt) WriteHSCXfifo(cs, nr, ptr, cnt)
+
+#include "hscx_irq.c"
+
+static irqreturn_t
+gazel_interrupt(int intno, void *dev_id, struct pt_regs *regs)
+{
+#define MAXCOUNT 5
+	struct IsdnCardState *cs = dev_id;
+	u_char valisac, valhscx;
+	int count = 0;
+	u_long flags;
+
+	spin_lock_irqsave(&cs->lock, flags);
+	do {
+		valhscx = ReadHSCX(cs, 1, HSCX_ISTA);
+		if (valhscx)
+			hscx_int_main(cs, valhscx);
+		valisac = ReadISAC(cs, ISAC_ISTA);
+		if (valisac)
+			isac_interrupt(cs, valisac);
+		count++;
+	} while ((valhscx || valisac) && (count < MAXCOUNT));
+
+	WriteHSCX(cs, 0, HSCX_MASK, 0xFF);
+	WriteHSCX(cs, 1, HSCX_MASK, 0xFF);
+	WriteISAC(cs, ISAC_MASK, 0xFF);
+	WriteISAC(cs, ISAC_MASK, 0x0);
+	WriteHSCX(cs, 0, HSCX_MASK, 0x0);
+	WriteHSCX(cs, 1, HSCX_MASK, 0x0);
+	spin_unlock_irqrestore(&cs->lock, flags);
+	return IRQ_HANDLED;
 }
 
-static inline void
-ipac_writefifo(struct IsdnCardState *cs, u8 off, u8 * data, int size)
-{
-	byteout(cs->hw.gazel.ipac, off);
-	outsb(cs->hw.gazel.ipac + 4, data, size);
-}
 
-/* This will generate ipac_dc_ops and ipac_bc_ops using the functions
- * above */
+static irqreturn_t
+gazel_interrupt_ipac(int intno, void *dev_id, struct pt_regs *regs)
+{
+	struct IsdnCardState *cs = dev_id;
+	u_char ista, val;
+	int count = 0;
+	u_long flags;
+	
+	spin_lock_irqsave(&cs->lock, flags);
+	ista = ReadISAC(cs, IPAC_ISTA - 0x80);
+	do {
+		if (ista & 0x0f) {
+			val = ReadHSCX(cs, 1, HSCX_ISTA);
+			if (ista & 0x01)
+				val |= 0x01;
+			if (ista & 0x04)
+				val |= 0x02;
+			if (ista & 0x08)
+				val |= 0x04;
+			if (val) {
+				hscx_int_main(cs, val);
+			}
+		}
+		if (ista & 0x20) {
+			val = 0xfe & ReadISAC(cs, ISAC_ISTA);
+			if (val) {
+				isac_interrupt(cs, val);
+			}
+		}
+		if (ista & 0x10) {
+			val = 0x01;
+			isac_interrupt(cs, val);
+		}
+		ista = ReadISAC(cs, IPAC_ISTA - 0x80);
+		count++;
+	}
+	while ((ista & 0x3f) && (count < MAXCOUNT));
 
-BUILD_IPAC_OPS(ipac);
+	WriteISAC(cs, IPAC_MASK - 0x80, 0xFF);
+	WriteISAC(cs, IPAC_MASK - 0x80, 0xC0);
+	spin_unlock_irqrestore(&cs->lock, flags);
+	return IRQ_HANDLED;
+}
+void
+release_io_gazel(struct IsdnCardState *cs)
+{
+	unsigned int i;
+
+	switch (cs->subtyp) {
+		case R647:
+			for (i = 0x0000; i < 0xC000; i += 0x1000)
+				release_region(i + cs->hw.gazel.hscx[0], 16);
+			release_region(0xC000 + cs->hw.gazel.hscx[0], 1);
+			break;
 
-static int
-r647_reset(struct IsdnCardState *cs)
-{
-	writereg(cs->hw.gazel.cfg_reg, 0, 0);
-	HZDELAY(10);
-	writereg(cs->hw.gazel.cfg_reg, 0, 1);
-	HZDELAY(2);
-	return 0;
+		case R685:
+			release_region(cs->hw.gazel.hscx[0], 0x100);
+			release_region(cs->hw.gazel.cfg_reg, 0x80);
+			break;
+
+		case R753:
+			release_region(cs->hw.gazel.ipac, 0x8);
+			release_region(cs->hw.gazel.cfg_reg, 0x80);
+			break;
+
+		case R742:
+			release_region(cs->hw.gazel.ipac, 8);
+			break;
+	}
 }
 
 static int
-r685_reset(struct IsdnCardState *cs)
+reset_gazel(struct IsdnCardState *cs)
 {
 	unsigned long plxcntrl, addr = cs->hw.gazel.cfg_reg;
 
-	plxcntrl = inl(addr + PLX_CNTRL);
-	plxcntrl |= (RESET_9050 + RESET_GAZEL);
-	outl(plxcntrl, addr + PLX_CNTRL);
-	plxcntrl &= ~(RESET_9050 + RESET_GAZEL);
-	HZDELAY(4);
-	outl(plxcntrl, addr + PLX_CNTRL);
-	HZDELAY(10);
-	outb(INT_ISAC_EN + INT_HSCX_EN + INT_PCI_EN, addr + PLX_INCSR);
-	return 0;
+	switch (cs->subtyp) {
+		case R647:
+			writereg(addr, 0, 0);
+			HZDELAY(10);
+			writereg(addr, 0, 1);
+			HZDELAY(2);
+			break;
+		case R685:
+			plxcntrl = inl(addr + PLX_CNTRL);
+			plxcntrl |= (RESET_9050 + RESET_GAZEL);
+			outl(plxcntrl, addr + PLX_CNTRL);
+			plxcntrl &= ~(RESET_9050 + RESET_GAZEL);
+			HZDELAY(4);
+			outl(plxcntrl, addr + PLX_CNTRL);
+			HZDELAY(10);
+			outb(INT_ISAC_EN + INT_HSCX_EN + INT_PCI_EN, addr + PLX_INCSR);
+			break;
+		case R753:
+			plxcntrl = inl(addr + PLX_CNTRL);
+			plxcntrl |= (RESET_9050 + RESET_GAZEL);
+			outl(plxcntrl, addr + PLX_CNTRL);
+			plxcntrl &= ~(RESET_9050 + RESET_GAZEL);
+			WriteISAC(cs, IPAC_POTA2 - 0x80, 0x20);
+			HZDELAY(4);
+			outl(plxcntrl, addr + PLX_CNTRL);
+			HZDELAY(10);
+			WriteISAC(cs, IPAC_POTA2 - 0x80, 0x00);
+			WriteISAC(cs, IPAC_ACFG - 0x80, 0xff);
+			WriteISAC(cs, IPAC_AOE - 0x80, 0x0);
+			WriteISAC(cs, IPAC_MASK - 0x80, 0xff);
+			WriteISAC(cs, IPAC_CONF - 0x80, 0x1);
+			outb(INT_IPAC_EN + INT_PCI_EN, addr + PLX_INCSR);
+			WriteISAC(cs, IPAC_MASK - 0x80, 0xc0);
+			break;
+		case R742:
+			WriteISAC(cs, IPAC_POTA2 - 0x80, 0x20);
+			HZDELAY(4);
+			WriteISAC(cs, IPAC_POTA2 - 0x80, 0x00);
+			WriteISAC(cs, IPAC_ACFG - 0x80, 0xff);
+			WriteISAC(cs, IPAC_AOE - 0x80, 0x0);
+			WriteISAC(cs, IPAC_MASK - 0x80, 0xff);
+			WriteISAC(cs, IPAC_CONF - 0x80, 0x1);
+			WriteISAC(cs, IPAC_MASK - 0x80, 0xc0);
+			break;
+	}
+	return (0);
 }
 
 static int
-r753_reset(struct IsdnCardState *cs)
+Gazel_card_msg(struct IsdnCardState *cs, int mt, void *arg)
 {
-	unsigned long plxcntrl, addr = cs->hw.gazel.cfg_reg;
+	u_long flags;
 
-	if (test_bit(FLG_BUGGY_PLX9050, &cs->HW_Flags))
-		/* we can't read, assume the default */
-		plxcntrl = 0x18784db6;
-	else
-		plxcntrl = inl(addr + PLX_CNTRL);
-	plxcntrl |= (RESET_9050 + RESET_GAZEL);
-	outl(plxcntrl, addr + PLX_CNTRL);
-	ipac_write(cs, IPAC_POTA2, 0x20);
-	HZDELAY(4);
-	plxcntrl &= ~(RESET_9050 + RESET_GAZEL);
-	outl(plxcntrl, addr + PLX_CNTRL);
-	HZDELAY(10);
-	ipac_write(cs, IPAC_POTA2, 0x00);
-	ipac_write(cs, IPAC_ACFG, 0xff);
-	ipac_write(cs, IPAC_AOE, 0x0);
-	ipac_write(cs, IPAC_MASK, 0xff);
-	ipac_write(cs, IPAC_CONF, 0x1);
-	outb(INT_IPAC_EN + INT_PCI_EN, addr + PLX_INCSR);
-	ipac_write(cs, IPAC_MASK, 0xc0);
-	return 0;
+	switch (mt) {
+		case CARD_RESET:
+			spin_lock_irqsave(&cs->lock, flags);
+			reset_gazel(cs);
+			spin_unlock_irqrestore(&cs->lock, flags);
+			return (0);
+		case CARD_RELEASE:
+			release_io_gazel(cs);
+			return (0);
+		case CARD_INIT:
+			spin_lock_irqsave(&cs->lock, flags);
+			inithscxisac(cs, 1);
+			if ((cs->subtyp==R647)||(cs->subtyp==R685)) {
+				int i;
+				for (i=0;i<(2+MAX_WAITING_CALLS);i++) {
+					cs->bcs[i].hw.hscx.tsaxr0 = 0x1f;
+					cs->bcs[i].hw.hscx.tsaxr1 = 0x23;
+				}
+			}
+			spin_unlock_irqrestore(&cs->lock, flags);
+			return (0);
+		case CARD_TEST:
+			return (0);
+	}
+	return (0);
 }
 
 static int
-r742_reset(struct IsdnCardState *cs)
+reserve_regions(struct IsdnCard *card, struct IsdnCardState *cs)
 {
-	ipac_write(cs, IPAC_POTA2, 0x20);
-	HZDELAY(4);
-	ipac_write(cs, IPAC_POTA2, 0x00);
-	ipac_write(cs, IPAC_ACFG, 0xff);
-	ipac_write(cs, IPAC_AOE, 0x0);
-	ipac_write(cs, IPAC_MASK, 0xff);
-	ipac_write(cs, IPAC_CONF, 0x1);
-	ipac_write(cs, IPAC_MASK, 0xc0);
-	return 0;
-}
+	unsigned int i, j, base = 0, adr = 0, len = 0;
 
-static void
-gazel_init(struct IsdnCardState *cs)
-{
-	int i;
+	switch (cs->subtyp) {
+		case R647:
+			base = cs->hw.gazel.hscx[0];
+			if (!request_region(adr = (0xC000 + base), len = 1, "gazel"))
+				goto error;
+			for (i = 0x0000; i < 0xC000; i += 0x1000) {
+				if (!request_region(adr = (i + base), len = 16, "gazel"))
+					goto error;
+			}
+			if (i != 0xC000) {
+				for (j = 0; j < i; j+= 0x1000)
+					release_region(j + base, 16);
+				release_region(0xC000 + base, 1);
+				goto error;
+			}
+			break;
+
+		case R685:
+			if (!request_region(adr = cs->hw.gazel.hscx[0], len = 0x100, "gazel"))
+				goto error;
+			if (!request_region(adr = cs->hw.gazel.cfg_reg, len = 0x80, "gazel")) {
+				release_region(cs->hw.gazel.hscx[0],0x100);
+				goto error;
+			}
+			break;
 
-	for (i = 0; i < 2; i++) {
-		cs->bcs[i].hw.hscx.tsaxr0 = 0x1f;
-		cs->bcs[i].hw.hscx.tsaxr1 = 0x23;
-	}
-	inithscxisac(cs);
-}
-
-static struct card_ops r647_ops = {
-	.init     = gazel_init,
-	.reset    = r647_reset,
-	.release  = hisax_release_resources,
-	.irq_func = hscxisac_irq,
-};
-
-static struct card_ops r685_ops = {
-	.init     = gazel_init,
-	.reset    = r685_reset,
-	.release  = hisax_release_resources,
-	.irq_func = hscxisac_irq,
-};
-
-static struct card_ops r742_ops = {
-	.init     = ipac_init,
-	.reset    = r742_reset,
-	.release  = hisax_release_resources,
-	.irq_func = ipac_irq,
-};
-
-static struct card_ops r753_ops = {
-	.init     = ipac_init,
-	.reset    = r753_reset,
-	.release  = hisax_release_resources,
-	.irq_func = ipac_irq,
-};
+		case R753:
+			if (!request_region(adr = cs->hw.gazel.ipac, len = 0x8, "gazel"))
+				goto error;
+			if (!request_region(adr = cs->hw.gazel.cfg_reg, len = 0x80, "gazel")) {
+				release_region(cs->hw.gazel.ipac, 8);
+				goto error;
+			}
+			break;
+
+		case R742:
+			if (!request_region(adr = cs->hw.gazel.ipac, len = 0x8, "gazel"))
+				goto error;
+			break;
+	}
+
+	return 0;
+
+      error:
+	printk(KERN_WARNING "Gazel: %s io ports 0x%x-0x%x already in use\n",
+	       CardType[cs->typ], adr, adr + len);
+	return 1;
+}
 
 static int __init
-gazel647_probe(struct IsdnCardState *cs, struct IsdnCard *card)
+setup_gazelisa(struct IsdnCard *card, struct IsdnCardState *cs)
 {
-	int i, base;
+	printk(KERN_INFO "Gazel: ISA PnP card automatic recognition\n");
+	// we got an irq parameter, assume it is an ISA card
+	// R742 decodes address even in not started...
+	// R647 returns FF if not present or not started
+	// eventually needs improvment
+	if (readreg_ipac(card->para[1], IPAC_ID) == 1)
+		cs->subtyp = R742;
+	else
+		cs->subtyp = R647;
 
-	cs->subtyp = R647;
-	cs->irq = card->para[0];
+	setup_isac(cs);
 	cs->hw.gazel.cfg_reg = card->para[1] + 0xC000;
-
-	printk(KERN_INFO "Gazel: Card ISA R647/R648 found\n");
-	cs->dc.isac.adf2 = 0x87;
-	printk(KERN_INFO "Gazel: config irq:%d isac:0x%X  cfg:0x%X\n",
-	       cs->irq, cs->hw.gazel.isac, cs->hw.gazel.cfg_reg);
-	printk(KERN_INFO
-	       "Gazel: hscx A:0x%X  hscx B:0x%X\n",
-	       cs->hw.gazel.hscx[0], cs->hw.gazel.hscx[1]);
-
+	cs->hw.gazel.ipac = card->para[1];
 	cs->hw.gazel.isac = card->para[1] + 0x8000;
 	cs->hw.gazel.hscx[0] = card->para[1];
 	cs->hw.gazel.hscx[1] = card->para[1] + 0x4000;
+	cs->irq = card->para[0];
 	cs->hw.gazel.isacfifo = cs->hw.gazel.isac;
 	cs->hw.gazel.hscxfifo[0] = cs->hw.gazel.hscx[0];
 	cs->hw.gazel.hscxfifo[1] = cs->hw.gazel.hscx[1];
 
-	base = cs->hw.gazel.hscx[0];
-	for (i = 0; i < 0xc000; i += 0x1000) {
-		if (!request_io(&cs->rs, base + i, 16, "gazel"))
-			goto err;
-	}
-	if (!request_io(&cs->rs, 0xc000 + base, 1, "gazel"))
-		goto err;
-
-	cs->card_ops = &r647_ops;
-	if (hscxisac_setup(cs, &r647_isac_ops, &r647_hscx_ops))
-		goto err;
-
-	cs->card_ops->reset(cs);
-	return 0;
- err:
-	hisax_release_resources(cs);
-	return -EBUSY;
-}
-
-static int __init
-gazel742_probe(struct IsdnCardState *cs, struct IsdnCard *card)
-{
-	cs->subtyp = R742;
-	cs->irq = card->para[0];
-	cs->hw.gazel.cfg_reg = card->para[1] + 0xC000;
+	switch (cs->subtyp) {
+		case R647:
+			printk(KERN_INFO "Gazel: Card ISA R647/R648 found\n");
+			cs->dc.isac.adf2 = 0x87;
+			printk(KERN_INFO
+				"Gazel: config irq:%d isac:0x%X  cfg:0x%X\n",
+				cs->irq, cs->hw.gazel.isac, cs->hw.gazel.cfg_reg);
+			printk(KERN_INFO
+				"Gazel: hscx A:0x%X  hscx B:0x%X\n",
+				cs->hw.gazel.hscx[0], cs->hw.gazel.hscx[1]);
 
-	printk(KERN_INFO "Gazel: Card ISA R742 found\n");
-	printk(KERN_INFO "Gazel: config irq:%d ipac:0x%X\n",
-	       cs->irq, cs->hw.gazel.ipac);
-
-	if (!request_io(&cs->rs, cs->hw.gazel.ipac, 0x8, "gazel"))
-		goto err;
-
-	cs->card_ops = &r742_ops;
-	if (ipac_setup(cs, &ipac_dc_ops, &ipac_bc_ops))
-		goto err;
+			break;
+		case R742:
+			printk(KERN_INFO "Gazel: Card ISA R742 found\n");
+			test_and_set_bit(HW_IPAC, &cs->HW_Flags);
+			printk(KERN_INFO
+			       "Gazel: config irq:%d ipac:0x%X\n",
+			       cs->irq, cs->hw.gazel.ipac);
+			break;
+	}
 
-	cs->card_ops->reset(cs);
-	return 0;
- err:
-	hisax_release_resources(cs);
-	return -EBUSY;
+	return (0);
 }
 
+static struct pci_dev *dev_tel __initdata = NULL;
+
 static int __init
-gazel685_probe(struct IsdnCardState *cs, struct pci_dev *pdev)
+setup_gazelpci(struct IsdnCardState *cs)
 {
-	if (pci_enable_device(pdev))
-		goto err;
-			
-	cs->subtyp               = R685;
-	cs->irq                  = pdev->irq;
-	cs->irq_flags           |= SA_SHIRQ;
-	cs->hw.gazel.cfg_reg     = pci_resource_start(pdev, 1);
-	cs->hw.gazel.isac        = pci_resource_start(pdev, 2) + 0x80;
-	cs->hw.gazel.hscx[0]     = pci_resource_start(pdev, 2);
-	cs->hw.gazel.hscx[1]     = pci_resource_start(pdev, 2) + 0x40;
-	cs->hw.gazel.isacfifo    = cs->hw.gazel.isac;
+	u_int pci_ioaddr0 = 0, pci_ioaddr1 = 0;
+	u_char pci_irq = 0, found;
+	u_int nbseek, seekcard;
+
+	printk(KERN_WARNING "Gazel: PCI card automatic recognition\n");
+
+	found = 0;
+	seekcard = PCI_DEVICE_ID_PLX_R685;
+	for (nbseek = 0; nbseek < 3; nbseek++) {
+		if ((dev_tel = pci_find_device(PCI_VENDOR_ID_PLX, seekcard, dev_tel))) {
+			if (pci_enable_device(dev_tel))
+				return 1;
+			pci_irq = dev_tel->irq;
+			pci_ioaddr0 = pci_resource_start(dev_tel, 1);
+			pci_ioaddr1 = pci_resource_start(dev_tel, 2);
+			found = 1;
+		}
+		if (found)
+			break;
+		else {
+			switch (seekcard) {
+				case PCI_DEVICE_ID_PLX_R685:
+					seekcard = PCI_DEVICE_ID_PLX_R753;
+					break;
+				case PCI_DEVICE_ID_PLX_R753:
+					seekcard = PCI_DEVICE_ID_PLX_DJINN_ITOO;
+					break;
+			}
+		}
+	}
+	if (!found) {
+		printk(KERN_WARNING "Gazel: No PCI card found\n");
+		return (1);
+	}
+	if (!pci_irq) {
+		printk(KERN_WARNING "Gazel: No IRQ for PCI card found\n");
+		return 1;
+	}
+	cs->hw.gazel.pciaddr[0] = pci_ioaddr0;
+	cs->hw.gazel.pciaddr[1] = pci_ioaddr1;
+	setup_isac(cs);
+	pci_ioaddr1 &= 0xfffe;
+	cs->hw.gazel.cfg_reg = pci_ioaddr0 & 0xfffe;
+	cs->hw.gazel.ipac = pci_ioaddr1;
+	cs->hw.gazel.isac = pci_ioaddr1 + 0x80;
+	cs->hw.gazel.hscx[0] = pci_ioaddr1;
+	cs->hw.gazel.hscx[1] = pci_ioaddr1 + 0x40;
+	cs->hw.gazel.isacfifo = cs->hw.gazel.isac;
 	cs->hw.gazel.hscxfifo[0] = cs->hw.gazel.hscx[0];
 	cs->hw.gazel.hscxfifo[1] = cs->hw.gazel.hscx[1];
-	cs->dc.isac.adf2 = 0x87;
-
-	if (!request_io(&cs->rs, cs->hw.gazel.hscx[0], 0x100, "gazel"))
-		goto err;
-	if (!request_io(&cs->rs, cs->hw.gazel.cfg_reg, 0x80, "gazel"))
-		goto err;
-
-	printk(KERN_INFO "Gazel: Card PCI R685 found\n");
-	printk(KERN_INFO "Gazel: config irq:%d isac:0x%X  cfg:0x%X\n",
-	       cs->irq, cs->hw.gazel.isac, cs->hw.gazel.cfg_reg);
-	printk(KERN_INFO "Gazel: hscx A:0x%X  hscx B:0x%X\n",
-	       cs->hw.gazel.hscx[0], cs->hw.gazel.hscx[1]);
-
-	cs->card_ops  = &r685_ops;
-	if (hscxisac_setup(cs, &r685_isac_ops, &r685_hscx_ops))
-		goto err;
+	cs->irq = pci_irq;
+	cs->irq_flags |= SA_SHIRQ;
 
-	cs->card_ops->reset(cs);
-	return 0;
- err:
-	hisax_release_resources(cs);
-	return -EBUSY;
-}
-
-static int __init
-gazel753_probe(struct IsdnCardState *cs, struct pci_dev *pdev)
-{
-	u8 pci_rev;
-
-	if (pci_enable_device(pdev))
-		goto err;
-			
-	cs->subtyp           = R753;
-	cs->irq              = pdev->irq;
-	cs->irq_flags       |= SA_SHIRQ;
-	cs->hw.gazel.cfg_reg = pci_resource_start(pdev, 1);
-	cs->hw.gazel.ipac    = pci_resource_start(pdev, 2);
-
-	if (!request_io(&cs->rs, cs->hw.gazel.ipac, 0x8, "gazel"))
-		goto err;
-	if (!request_io(&cs->rs, cs->hw.gazel.cfg_reg, 0x80, "gazel"))
-		goto err;
-
-	printk(KERN_INFO "Gazel: Card PCI R753 found\n");
-	printk(KERN_INFO "Gazel: config irq:%d ipac:0x%X  cfg:0x%X\n",
-	       cs->irq, cs->hw.gazel.ipac, cs->hw.gazel.cfg_reg);
-	/* 
-	 * Erratum for PLX9050, revision 1:
-	 * If bit 7 of BAR 0/1 is set, local config registers
-	 * can not be read (write is okay)
-	 */
-	if (cs->hw.gazel.cfg_reg & 0x80) {
-		pci_read_config_byte(pdev, PCI_REVISION_ID, &pci_rev);
-		if (pci_rev == 1) {
-			printk(KERN_INFO "Gazel: PLX9050 rev1 workaround "
-			       "activated\n");
-			__set_bit(FLG_BUGGY_PLX9050, &cs->HW_Flags);
-		}
+	switch (seekcard) {
+		case PCI_DEVICE_ID_PLX_R685:
+			printk(KERN_INFO "Gazel: Card PCI R685 found\n");
+			cs->subtyp = R685;
+			cs->dc.isac.adf2 = 0x87;
+			printk(KERN_INFO
+			    "Gazel: config irq:%d isac:0x%X  cfg:0x%X\n",
+			cs->irq, cs->hw.gazel.isac, cs->hw.gazel.cfg_reg);
+			printk(KERN_INFO
+			       "Gazel: hscx A:0x%X  hscx B:0x%X\n",
+			     cs->hw.gazel.hscx[0], cs->hw.gazel.hscx[1]);
+			break;
+		case PCI_DEVICE_ID_PLX_R753:
+		case PCI_DEVICE_ID_PLX_DJINN_ITOO:
+			printk(KERN_INFO "Gazel: Card PCI R753 found\n");
+			cs->subtyp = R753;
+			test_and_set_bit(HW_IPAC, &cs->HW_Flags);
+			printk(KERN_INFO
+			    "Gazel: config irq:%d ipac:0x%X  cfg:0x%X\n",
+			cs->irq, cs->hw.gazel.ipac, cs->hw.gazel.cfg_reg);
+			break;
 	}
-	cs->card_ops = &r753_ops;
-	if (ipac_setup(cs, &ipac_dc_ops, &ipac_bc_ops))
-		goto err;
 
-	cs->card_ops->reset(cs);
-	return 0;
- err:
-	hisax_release_resources(cs);
-	return -EBUSY;
+	return (0);
 }
 
-static struct pci_dev *dev_tel __initdata = NULL;
-static u16 __initdata dev_id = PCI_DEVICE_ID_PLX_R685;
-
 int __init
 setup_gazel(struct IsdnCard *card)
 {
+	struct IsdnCardState *cs = card->cs;
 	char tmp[64];
+	u_char val;
 
 	strcpy(tmp, gazel_revision);
 	printk(KERN_INFO "Gazel: Driver Revision %s\n", HiSax_getrev(tmp));
 
+	if (cs->typ != ISDN_CTYPE_GAZEL)
+		return (0);
+
 	if (card->para[0]) {
-		printk(KERN_INFO "Gazel: ISA card automatic recognition\n");
-		// we got an irq parameter, assume it is an ISA card
-		// R742 decodes address even in not started...
-		// R647 returns FF if not present or not started
-		// eventually needs improvment
-		card->cs->hw.gazel.ipac = card->para[1];
-		if (ipac_read(card->cs, IPAC_ID) == 1) {
-			if (gazel742_probe(card->cs, card))
-				return 0;
-		} else {
-			if (gazel647_probe(card->cs, card))
-				return 0;
-		}
-		return 1;
+		if (setup_gazelisa(card, cs))
+			return (0);
+	} else {
+
+#if CONFIG_PCI
+		if (setup_gazelpci(cs))
+			return (0);
+#else
+		printk(KERN_WARNING "Gazel: Card PCI requested and NO_PCI_BIOS, unable to config\n");
+		return (0);
+#endif				/* CONFIG_PCI */
 	}
 
-	for (;;) {
-		dev_tel = pci_find_device(PCI_VENDOR_ID_PLX, dev_id, dev_tel);
-		if (dev_tel) {
-			switch (dev_id) {
-			case PCI_DEVICE_ID_PLX_R685:
-				if (gazel685_probe(card->cs, dev_tel))
-					return 0;
-				return 1;
-			case PCI_DEVICE_ID_PLX_R753:
-			case PCI_DEVICE_ID_PLX_DJINN_ITOO:
-				if (gazel753_probe(card->cs, dev_tel))
-					return 0;
-				return 1;
+	if (reserve_regions(card, cs)) {
+		return (0);
+	}
+	if (reset_gazel(cs)) {
+		printk(KERN_WARNING "Gazel: wrong IRQ\n");
+		release_io_gazel(cs);
+		return (0);
+	}
+	cs->readisac = &ReadISAC;
+	cs->writeisac = &WriteISAC;
+	cs->readisacfifo = &ReadISACfifo;
+	cs->writeisacfifo = &WriteISACfifo;
+	cs->BC_Read_Reg = &ReadHSCX;
+	cs->BC_Write_Reg = &WriteHSCX;
+	cs->BC_Send_Data = &hscx_fill_fifo;
+	cs->cardmsg = &Gazel_card_msg;
+
+	switch (cs->subtyp) {
+		case R647:
+		case R685:
+			cs->irq_func = &gazel_interrupt;
+			ISACVersion(cs, "Gazel:");
+			if (HscxVersion(cs, "Gazel:")) {
+				printk(KERN_WARNING
+				       "Gazel: wrong HSCX versions check IO address\n");
+				release_io_gazel(cs);
+				return (0);
 			}
-		}
-		switch (dev_id) {
-		case PCI_DEVICE_ID_PLX_R685:
-			dev_id = PCI_DEVICE_ID_PLX_R753;
-		case PCI_DEVICE_ID_PLX_R753:
-			dev_id = PCI_DEVICE_ID_PLX_DJINN_ITOO;
-		default:
 			break;
-		}
+		case R742:
+		case R753:
+			cs->irq_func = &gazel_interrupt_ipac;
+			val = ReadISAC(cs, IPAC_ID - 0x80);
+			printk(KERN_INFO "Gazel: IPAC version %x\n", val);
+			break;
 	}
-	printk(KERN_WARNING "Gazel: No PCI card found\n");
-	return 0;
-}
-
 
+	return (1);
+}
--- diff/drivers/isdn/hisax/hfc_2bds0.c	2003-09-17 12:28:06.000000000 +0100
+++ source/drivers/isdn/hisax/hfc_2bds0.c	2004-02-23 13:56:42.000000000 +0000
@@ -1,4 +1,4 @@
-/* $Id: hfc_2bds0.c,v 1.15.6.3 2001/09/23 22:24:47 kai Exp $
+/* $Id: hfc_2bds0.c,v 1.18.2.6 2004/02/11 13:21:33 keil Exp $
  *
  * specific routines for CCD's HFC 2BDS0
  *
@@ -23,10 +23,16 @@
 #define byteout(addr,val) outb(val,addr)
 #define bytein(addr) inb(addr)
 
-static inline u8
-ReadReg(struct IsdnCardState *cs, int data, u8 reg)
+static void
+dummyf(struct IsdnCardState *cs, u_char * data, int size)
+{
+	printk(KERN_WARNING "HiSax: hfcd dummy fifo called\n");
+}
+
+static inline u_char
+ReadReg(struct IsdnCardState *cs, int data, u_char reg)
 {
-	register u8 ret;
+	register u_char ret;
 
 	if (data) {
 		if (cs->hw.hfcD.cip != reg) { 
@@ -44,7 +50,7 @@ ReadReg(struct IsdnCardState *cs, int da
 }
 
 static inline void
-WriteReg(struct IsdnCardState *cs, int data, u8 reg, u8 value)
+WriteReg(struct IsdnCardState *cs, int data, u_char reg, u_char value)
 {
 	if (cs->hw.hfcD.cip != reg) { 
 		cs->hw.hfcD.cip = reg;
@@ -58,31 +64,20 @@ WriteReg(struct IsdnCardState *cs, int d
 #endif
 }
 
-static struct bc_hw_ops hfcs_bc_ops = {
-	.read_reg  = ReadReg,
-	.write_reg = WriteReg,
-};
-
 /* Interface functions */
 
-static inline u8
-hfcs_read_reg(struct IsdnCardState *cs, u8 offset)
+static u_char
+readreghfcd(struct IsdnCardState *cs, u_char offset)
 {
-	return ReadReg(cs, HFCD_DATA, offset);
+	return(ReadReg(cs, HFCD_DATA, offset));
 }
 
-static inline void
-hfcs_write_reg(struct IsdnCardState *cs, u8 offset, u8 value)
+static void
+writereghfcd(struct IsdnCardState *cs, u_char offset, u_char value)
 {
 	WriteReg(cs, HFCD_DATA, offset, value);
 }
 
-void
-set_cs_func(struct IsdnCardState *cs)
-{
-	cs->bc_hw_ops = &hfcs_bc_ops;
-}
-
 static inline int
 WaitForBusy(struct IsdnCardState *cs)
 {
@@ -112,13 +107,12 @@ WaitNoBusy(struct IsdnCardState *cs)
 }
 
 static int
-SelFiFo(struct IsdnCardState *cs, u8 FiFo)
+SelFiFo(struct IsdnCardState *cs, u_char FiFo)
 {
-	u8 cip;
+	u_char cip;
 
 	if (cs->hw.hfcD.fifo == FiFo)
 		return(1);
-
 	switch(FiFo) {
 		case 0: cip = HFCB_FIFO | HFCB_Z1 | HFCB_SEND | HFCB_B1;
 			break;
@@ -138,10 +132,11 @@ SelFiFo(struct IsdnCardState *cs, u8 FiF
 	}
 	cs->hw.hfcD.fifo = FiFo;
 	WaitNoBusy(cs);
-	WriteReg(cs, HFCD_DATA, cip, 0);
+	cs->BC_Write_Reg(cs, HFCD_DATA, cip, 0);
 	WaitForBusy(cs);
 	return(2);
 }
+
 static int
 GetFreeFifoBytes_B(struct BCState *bcs)
 {
@@ -171,7 +166,7 @@ GetFreeFifoBytes_D(struct IsdnCardState 
 }
 
 static int
-ReadZReg(struct IsdnCardState *cs, u8 reg)
+ReadZReg(struct IsdnCardState *cs, u_char reg)
 {
 	int val;
 
@@ -185,12 +180,12 @@ ReadZReg(struct IsdnCardState *cs, u8 re
 static struct sk_buff
 *hfc_empty_fifo(struct BCState *bcs, int count)
 {
-	u8 *ptr;
+	u_char *ptr;
 	struct sk_buff *skb;
 	struct IsdnCardState *cs = bcs->cs;
 	int idx;
 	int chksum;
-	u8 stat, cip;
+	u_char stat, cip;
 	
 	if ((cs->debug & L1_DEB_HSCX) && !(cs->debug & L1_DEB_HSCX_FIFO))
 		debugl1(cs, "hfc_empty_fifo");
@@ -264,10 +259,9 @@ static void
 hfc_fill_fifo(struct BCState *bcs)
 {
 	struct IsdnCardState *cs = bcs->cs;
-	u_int idx;
-	int fcnt;
-	u_int count;
-	u8 cip;
+	int idx, fcnt;
+	int count;
+	u_char cip;
 
 	if (!bcs->tx_skb)
 		return;
@@ -320,7 +314,16 @@ hfc_fill_fifo(struct BCState *bcs)
 		printk(KERN_WARNING "HFC S FIFO channel %d BUSY Error\n", bcs->channel);
 	} else {
 		bcs->tx_cnt -= bcs->tx_skb->len;
-		xmit_complete_b(bcs);
+		if (test_bit(FLG_LLI_L1WAKEUP,&bcs->st->lli.flag) &&
+			(PACKET_NOACK != bcs->tx_skb->pkt_type)) {
+			u_long	flags;
+			spin_lock_irqsave(&bcs->aclock, flags);
+			bcs->ackcnt += bcs->tx_skb->len;
+			spin_unlock_irqrestore(&bcs->aclock, flags);
+			schedule_event(bcs, B_ACKPENDING);
+		}
+		dev_kfree_skb_any(bcs->tx_skb);
+		bcs->tx_skb = NULL;
 	}
 	WaitForBusy(cs);
 	WaitNoBusy(cs);
@@ -330,17 +333,33 @@ hfc_fill_fifo(struct BCState *bcs)
 	return;
 }
 
+static void
+hfc_send_data(struct BCState *bcs)
+{
+	struct IsdnCardState *cs = bcs->cs;
+	
+	if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) {
+		hfc_fill_fifo(bcs);
+		test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);
+	} else
+		debugl1(cs,"send_data %d blocked", bcs->channel);
+}
+
 void
 main_rec_2bds0(struct BCState *bcs)
 {
 	struct IsdnCardState *cs = bcs->cs;
 	int z1, z2, rcnt;
-	u8 f1, f2, cip;
+	u_char f1, f2, cip;
 	int receive, count = 5;
 	struct sk_buff *skb;
 
     Begin:
 	count--;
+	if (test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) {
+		debugl1(cs,"rec_data %d blocked", bcs->channel);
+		return;
+	}
 	SelFiFo(cs, HFCB_REC | HFCB_CHANNEL(bcs->channel));
 	cip = HFCB_FIFO | HFCB_F1 | HFCB_REC | HFCB_CHANNEL(bcs->channel);
 	WaitNoBusy(cs);
@@ -363,7 +382,7 @@ main_rec_2bds0(struct BCState *bcs)
 				bcs->channel, z1, z2, rcnt);
 		if ((skb = hfc_empty_fifo(bcs, rcnt))) {
 			skb_queue_tail(&bcs->rqueue, skb);
-			sched_b_event(bcs, B_RCVBUFREADY);
+			schedule_event(bcs, B_RCVBUFREADY);
 		}
 		rcnt = f1 -f2;
 		if (rcnt<0)
@@ -374,6 +393,7 @@ main_rec_2bds0(struct BCState *bcs)
 			receive = 0;
 	} else
 		receive = 0;
+	test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);
 	if (count && receive)
 		goto Begin;	
 	return;
@@ -430,31 +450,57 @@ mode_2bs0(struct BCState *bcs, int mode,
 static void
 hfc_l2l1(struct PStack *st, int pr, void *arg)
 {
+	struct BCState *bcs = st->l1.bcs;
 	struct sk_buff *skb = arg;
+	u_long flags;
 
 	switch (pr) {
 		case (PH_DATA | REQUEST):
-			xmit_data_req_b(st->l1.bcs, skb);
+			spin_lock_irqsave(&bcs->cs->lock, flags);
+			if (bcs->tx_skb) {
+				skb_queue_tail(&bcs->squeue, skb);
+			} else {
+				bcs->tx_skb = skb;
+//				test_and_set_bit(BC_FLG_BUSY, &bcs->Flag);
+				bcs->cs->BC_Send_Data(bcs);
+			}
+			spin_unlock_irqrestore(&bcs->cs->lock, flags);
 			break;
 		case (PH_PULL | INDICATION):
-			xmit_pull_ind_b(st->l1.bcs, skb);
+			spin_lock_irqsave(&bcs->cs->lock, flags);
+			if (bcs->tx_skb) {
+				printk(KERN_WARNING "hfc_l2l1: this shouldn't happen\n");
+			} else {
+//				test_and_set_bit(BC_FLG_BUSY, &bcs->Flag);
+				bcs->tx_skb = skb;
+				bcs->cs->BC_Send_Data(bcs);
+			}
+			spin_unlock_irqrestore(&bcs->cs->lock, flags);
 			break;
 		case (PH_PULL | REQUEST):
-			xmit_pull_req_b(st);
+			if (!bcs->tx_skb) {
+				test_and_clear_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
+				st->l1.l1l2(st, PH_PULL | CONFIRM, NULL);
+			} else
+				test_and_set_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
 			break;
 		case (PH_ACTIVATE | REQUEST):
-			test_and_set_bit(BC_FLG_ACTIV, &st->l1.bcs->Flag);
-			mode_2bs0(st->l1.bcs, st->l1.mode, st->l1.bc);
+			spin_lock_irqsave(&bcs->cs->lock, flags);
+			test_and_set_bit(BC_FLG_ACTIV, &bcs->Flag);
+			mode_2bs0(bcs, st->l1.mode, st->l1.bc);
+			spin_unlock_irqrestore(&bcs->cs->lock, flags);
 			l1_msg_b(st, pr, arg);
 			break;
 		case (PH_DEACTIVATE | REQUEST):
 			l1_msg_b(st, pr, arg);
 			break;
 		case (PH_DEACTIVATE | CONFIRM):
-			test_and_clear_bit(BC_FLG_ACTIV, &st->l1.bcs->Flag);
-			test_and_clear_bit(BC_FLG_BUSY, &st->l1.bcs->Flag);
-			mode_2bs0(st->l1.bcs, 0, st->l1.bc);
-			L1L2(st, PH_DEACTIVATE | CONFIRM, NULL);
+			spin_lock_irqsave(&bcs->cs->lock, flags);
+			test_and_clear_bit(BC_FLG_ACTIV, &bcs->Flag);
+			test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
+			mode_2bs0(bcs, 0, st->l1.bc);
+			spin_unlock_irqrestore(&bcs->cs->lock, flags);
+			st->l1.l1l2(st, PH_DEACTIVATE | CONFIRM, NULL);
 			break;
 	}
 }
@@ -495,7 +541,7 @@ setstack_2b(struct PStack *st, struct BC
 	if (open_hfcstate(st->l1.hardware, bcs))
 		return (-1);
 	st->l1.bcs = bcs;
-	st->l1.l2l1 = hfc_l2l1;
+	st->l2.l2l1 = hfc_l2l1;
 	setstack_manager(st);
 	bcs->st = st;
 	setstack_l1_B(st);
@@ -503,11 +549,8 @@ setstack_2b(struct PStack *st, struct BC
 }
 
 static void
-hfcd_bh(void *data)
+hfcd_bh(struct IsdnCardState *cs)
 {
-	struct IsdnCardState *cs = data;
-/*	struct PStack *stptr;
-*/
 	if (!cs)
 		return;
 	if (test_and_clear_bit(D_L1STATECHANGE, &cs->event)) {
@@ -543,18 +586,22 @@ int receive_dmsg(struct IsdnCardState *c
 	struct sk_buff *skb;
 	int idx;
 	int rcnt, z1, z2;
-	u8 stat, cip, f1, f2;
+	u_char stat, cip, f1, f2;
 	int chksum;
 	int count=5;
-	u8 *ptr;
+	u_char *ptr;
 
+	if (test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) {
+		debugl1(cs, "rec_dmsg blocked");
+		return(1);
+	}
 	SelFiFo(cs, 4 | HFCD_REC);
 	cip = HFCD_FIFO | HFCD_F1 | HFCD_REC;
 	WaitNoBusy(cs);
-	f1 = hfcs_read_reg(cs, cip) & 0xf;
+	f1 = cs->readisac(cs, cip) & 0xf;
 	cip = HFCD_FIFO | HFCD_F2 | HFCD_REC;
 	WaitNoBusy(cs);
-	f2 = hfcs_read_reg(cs, cip) & 0xf;
+	f2 = cs->readisac(cs, cip) & 0xf;
 	while ((f1 != f2) && count--) {
 		z1 = ReadZReg(cs, HFCD_FIFO | HFCD_Z1 | HFCD_REC);
 		z2 = ReadZReg(cs, HFCD_FIFO | HFCD_Z2 | HFCD_REC);
@@ -617,7 +664,7 @@ int receive_dmsg(struct IsdnCardState *c
 #endif
 				} else {
 					skb_queue_tail(&cs->rq, skb);
-					sched_d_event(cs, D_RCVBUFREADY);
+					schedule_event(cs, D_RCVBUFREADY);
 				}
 			}
 		} else
@@ -629,17 +676,18 @@ int receive_dmsg(struct IsdnCardState *c
 		WaitForBusy(cs);
 		cip = HFCD_FIFO | HFCD_F2 | HFCD_REC;
 		WaitNoBusy(cs);
-		f2 = hfcs_read_reg(cs, cip) & 0xf;
+		f2 = cs->readisac(cs, cip) & 0xf;
 	}
+	test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);
 	return(1);
 } 
 
 static void
 hfc_fill_dfifo(struct IsdnCardState *cs)
 {
-	int fcnt;
-	u_int idx, count;
-	u8 cip;
+	int idx, fcnt;
+	int count;
+	u_char cip;
 
 	if (!cs->tx_skb)
 		return;
@@ -711,26 +759,31 @@ struct BCState *Sel_BCS(struct IsdnCardS
 }
 
 void
-hfc2bds0_interrupt(struct IsdnCardState *cs, u8 val)
+hfc2bds0_interrupt(struct IsdnCardState *cs, u_char val)
 {
-       	u8 exval;
+       	u_char exval;
        	struct BCState *bcs;
 	int count=15;
 
 	if (cs->debug & L1_DEB_ISAC)
-		debugl1(cs, "HFCD irq %x", val);
-
+		debugl1(cs, "HFCD irq %x %s", val,
+			test_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags) ?
+			"locked" : "unlocked");
 	val &= cs->hw.hfcD.int_m1;
 	if (val & 0x40) { /* TE state machine irq */
-		exval = hfcs_read_reg(cs, HFCD_STATES) & 0xf;
+		exval = cs->readisac(cs, HFCD_STATES) & 0xf;
 		if (cs->debug & L1_DEB_ISAC)
 			debugl1(cs, "ph_state chg %d->%d", cs->dc.hfcd.ph_state,
 				exval);
 		cs->dc.hfcd.ph_state = exval;
-		sched_d_event(cs, D_L1STATECHANGE);
+		schedule_event(cs, D_L1STATECHANGE);
 		val &= ~0x40;
 	}
 	while (val) {
+		if (test_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) {
+			cs->hw.hfcD.int_s1 |= val;
+			return;
+		}
 		if (cs->hw.hfcD.int_s1 & 0x18) {
 			exval = val;
 			val =  cs->hw.hfcD.int_s1;
@@ -755,7 +808,23 @@ hfc2bds0_interrupt(struct IsdnCardState 
 				if (cs->debug)
 					debugl1(cs, "hfcd spurious 0x01 IRQ");
 			} else {
-				xmit_xpr_b(bcs);
+				if (bcs->tx_skb) {
+					if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) {
+						hfc_fill_fifo(bcs);
+						test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);
+					} else
+						debugl1(cs,"fill_data %d blocked", bcs->channel);
+				} else {
+					if ((bcs->tx_skb = skb_dequeue(&bcs->squeue))) {
+						if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) {
+							hfc_fill_fifo(bcs);
+							test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);
+						} else
+							debugl1(cs,"fill_data %d blocked", bcs->channel);
+					} else {
+						schedule_event(bcs, B_XMTBUFREADY);
+					}
+				}
 			}
 		}
 		if (val & 0x02) {
@@ -763,15 +832,60 @@ hfc2bds0_interrupt(struct IsdnCardState 
 				if (cs->debug)
 					debugl1(cs, "hfcd spurious 0x02 IRQ");
 			} else {
-				xmit_xpr_b(bcs);
+				if (bcs->tx_skb) {
+					if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) {
+						hfc_fill_fifo(bcs);
+						test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);
+					} else
+						debugl1(cs,"fill_data %d blocked", bcs->channel);
+				} else {
+					if ((bcs->tx_skb = skb_dequeue(&bcs->squeue))) {
+						if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) {
+							hfc_fill_fifo(bcs);
+							test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);
+						} else
+							debugl1(cs,"fill_data %d blocked", bcs->channel);
+					} else {
+						schedule_event(bcs, B_XMTBUFREADY);
+					}
+				}
 			}
 		}
 		if (val & 0x20) {	/* receive dframe */
 			receive_dmsg(cs);
 		}
 		if (val & 0x04) {	/* dframe transmitted */
-			xmit_xpr_d(cs);
+			if (test_and_clear_bit(FLG_DBUSY_TIMER, &cs->HW_Flags))
+				del_timer(&cs->dbusytimer);
+			if (test_and_clear_bit(FLG_L1_DBUSY, &cs->HW_Flags))
+				schedule_event(cs, D_CLEARBUSY);
+			if (cs->tx_skb) {
+				if (cs->tx_skb->len) {
+					if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) {
+						hfc_fill_dfifo(cs);
+						test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);
+					} else {
+						debugl1(cs, "hfc_fill_dfifo irq blocked");
+					}
+					goto afterXPR;
+				} else {
+					dev_kfree_skb_irq(cs->tx_skb);
+					cs->tx_cnt = 0;
+					cs->tx_skb = NULL;
+				}
+			}
+			if ((cs->tx_skb = skb_dequeue(&cs->sq))) {
+				cs->tx_cnt = 0;
+				if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) {
+					hfc_fill_dfifo(cs);
+					test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);
+				} else {
+					debugl1(cs, "hfc_fill_dfifo irq blocked");
+				}
+			} else
+				schedule_event(cs, D_XMTBUFREADY);
 		}
+      afterXPR:
 		if (cs->hw.hfcD.int_s1 && count--) {
 			val = cs->hw.hfcD.int_s1;
 			cs->hw.hfcD.int_s1 = 0;
@@ -787,36 +901,101 @@ HFCD_l1hw(struct PStack *st, int pr, voi
 {
 	struct IsdnCardState *cs = (struct IsdnCardState *) st->l1.hardware;
 	struct sk_buff *skb = arg;
+	u_long flags;
 	
 	switch (pr) {
 		case (PH_DATA | REQUEST):
-			xmit_data_req_d(cs, skb);
+			if (cs->debug & DEB_DLOG_HEX)
+				LogFrame(cs, skb->data, skb->len);
+			if (cs->debug & DEB_DLOG_VERBOSE)
+				dlogframe(cs, skb, 0);
+			spin_lock_irqsave(&cs->lock, flags);
+			if (cs->tx_skb) {
+				skb_queue_tail(&cs->sq, skb);
+#ifdef L2FRAME_DEBUG		/* psa */
+				if (cs->debug & L1_DEB_LAPD)
+					Logl2Frame(cs, skb, "PH_DATA Queued", 0);
+#endif
+			} else {
+				cs->tx_skb = skb;
+				cs->tx_cnt = 0;
+#ifdef L2FRAME_DEBUG		/* psa */
+				if (cs->debug & L1_DEB_LAPD)
+					Logl2Frame(cs, skb, "PH_DATA", 0);
+#endif
+				if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) {
+					hfc_fill_dfifo(cs);
+					test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);
+				} else
+					debugl1(cs, "hfc_fill_dfifo blocked");
+
+			}
+			spin_unlock_irqrestore(&cs->lock, flags);
 			break;
-		case (PH_PULL |INDICATION):
-			xmit_pull_ind_d(cs, skb);
+		case (PH_PULL | INDICATION):
+			spin_lock_irqsave(&cs->lock, flags);
+			if (cs->tx_skb) {
+				if (cs->debug & L1_DEB_WARN)
+					debugl1(cs, " l2l1 tx_skb exist this shouldn't happen");
+				skb_queue_tail(&cs->sq, skb);
+				spin_unlock_irqrestore(&cs->lock, flags);
+				break;
+			}
+			if (cs->debug & DEB_DLOG_HEX)
+				LogFrame(cs, skb->data, skb->len);
+			if (cs->debug & DEB_DLOG_VERBOSE)
+				dlogframe(cs, skb, 0);
+			cs->tx_skb = skb;
+			cs->tx_cnt = 0;
+#ifdef L2FRAME_DEBUG		/* psa */
+			if (cs->debug & L1_DEB_LAPD)
+				Logl2Frame(cs, skb, "PH_DATA_PULLED", 0);
+#endif
+			if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) {
+				hfc_fill_dfifo(cs);
+				test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);
+			} else
+				debugl1(cs, "hfc_fill_dfifo blocked");
+			spin_unlock_irqrestore(&cs->lock, flags);
 			break;
 		case (PH_PULL | REQUEST):
-			xmit_pull_req_d(st);
+#ifdef L2FRAME_DEBUG		/* psa */
+			if (cs->debug & L1_DEB_LAPD)
+				debugl1(cs, "-> PH_REQUEST_PULL");
+#endif
+			if (!cs->tx_skb) {
+				test_and_clear_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
+				st->l1.l1l2(st, PH_PULL | CONFIRM, NULL);
+			} else
+				test_and_set_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
 			break;
 		case (HW_RESET | REQUEST):
-			hfcs_write_reg(cs, HFCD_STATES, HFCD_LOAD_STATE | 3); /* HFC ST 3 */
+			spin_lock_irqsave(&cs->lock, flags);
+			cs->writeisac(cs, HFCD_STATES, HFCD_LOAD_STATE | 3); /* HFC ST 3 */
 			udelay(6);
-			hfcs_write_reg(cs, HFCD_STATES, 3); /* HFC ST 2 */
+			cs->writeisac(cs, HFCD_STATES, 3); /* HFC ST 2 */
 			cs->hw.hfcD.mst_m |= HFCD_MASTER;
-			hfcs_write_reg(cs, HFCD_MST_MODE, cs->hw.hfcD.mst_m);
-			hfcs_write_reg(cs, HFCD_STATES, HFCD_ACTIVATE | HFCD_DO_ACTION);
+			cs->writeisac(cs, HFCD_MST_MODE, cs->hw.hfcD.mst_m);
+			cs->writeisac(cs, HFCD_STATES, HFCD_ACTIVATE | HFCD_DO_ACTION);
+			spin_unlock_irqrestore(&cs->lock, flags);
 			l1_msg(cs, HW_POWERUP | CONFIRM, NULL);
 			break;
 		case (HW_ENABLE | REQUEST):
-			hfcs_write_reg(cs, HFCD_STATES, HFCD_ACTIVATE | HFCD_DO_ACTION);
+			spin_lock_irqsave(&cs->lock, flags);
+			cs->writeisac(cs, HFCD_STATES, HFCD_ACTIVATE | HFCD_DO_ACTION);
+			spin_unlock_irqrestore(&cs->lock, flags);
 			break;
 		case (HW_DEACTIVATE | REQUEST):
+			spin_lock_irqsave(&cs->lock, flags);
 			cs->hw.hfcD.mst_m &= ~HFCD_MASTER;
-			hfcs_write_reg(cs, HFCD_MST_MODE, cs->hw.hfcD.mst_m);
+			cs->writeisac(cs, HFCD_MST_MODE, cs->hw.hfcD.mst_m);
+			spin_unlock_irqrestore(&cs->lock, flags);
 			break;
 		case (HW_INFO3 | REQUEST):
+			spin_lock_irqsave(&cs->lock, flags);
 			cs->hw.hfcD.mst_m |= HFCD_MASTER;
-			hfcs_write_reg(cs, HFCD_MST_MODE, cs->hw.hfcD.mst_m);
+			cs->writeisac(cs, HFCD_MST_MODE, cs->hw.hfcD.mst_m);
+			spin_unlock_irqrestore(&cs->lock, flags);
 			break;
 		default:
 			if (cs->debug & L1_DEB_WARN)
@@ -825,11 +1004,10 @@ HFCD_l1hw(struct PStack *st, int pr, voi
 	}
 }
 
-static int
+void
 setstack_hfcd(struct PStack *st, struct IsdnCardState *cs)
 {
 	st->l1.l1hw = HFCD_l1hw;
-	return 0;
 }
 
 static void
@@ -852,30 +1030,21 @@ unsigned int __init
 	return(send);
 }
 
-static struct bc_l1_ops hfcd_bc_l1_ops = {
-	.fill_fifo = hfc_fill_fifo,
-	.open      = setstack_2b,
-	.close     = close_2bs0,
-};
-
-static struct dc_l1_ops hfcd_dc_l1_ops = {
-	.fill_fifo  = hfc_fill_dfifo,
-	.open       = setstack_hfcd,
-	.bh_func    = hfcd_bh,
-	.dbusy_func = hfc_dbusy_timer,
-};
-
 void __init
 init2bds0(struct IsdnCardState *cs)
 {
-	dc_l1_init(cs, &hfcd_dc_l1_ops);
-	cs->bc_l1_ops = &hfcd_bc_l1_ops;
+	cs->setstack_d = setstack_hfcd;
 	if (!cs->hw.hfcD.send)
 		cs->hw.hfcD.send = init_send_hfcd(16);
 	if (!cs->bcs[0].hw.hfc.send)
 		cs->bcs[0].hw.hfc.send = init_send_hfcd(32);
 	if (!cs->bcs[1].hw.hfc.send)
 		cs->bcs[1].hw.hfc.send = init_send_hfcd(32);
+	cs->BC_Send_Data = &hfc_send_data;
+	cs->bcs[0].BC_SetStack = setstack_2b;
+	cs->bcs[1].BC_SetStack = setstack_2b;
+	cs->bcs[0].BC_Close = close_2bs0;
+	cs->bcs[1].BC_Close = close_2bs0;
 	mode_2bs0(cs->bcs, 0, 0);
 	mode_2bs0(cs->bcs + 1, 0, 1);
 }
@@ -896,3 +1065,18 @@ release2bds0(struct IsdnCardState *cs)
 		cs->hw.hfcD.send = NULL;
 	}
 }
+
+void
+set_cs_func(struct IsdnCardState *cs)
+{
+	cs->readisac = &readreghfcd;
+	cs->writeisac = &writereghfcd;
+	cs->readisacfifo = &dummyf;
+	cs->writeisacfifo = &dummyf;
+	cs->BC_Read_Reg = &ReadReg;
+	cs->BC_Write_Reg = &WriteReg;
+	cs->dbusytimer.function = (void *) hfc_dbusy_timer;
+	cs->dbusytimer.data = (long) cs;
+	init_timer(&cs->dbusytimer);
+	INIT_WORK(&cs->tqueue, (void *)(void *) hfcd_bh, cs);
+}
--- diff/drivers/isdn/hisax/hfc_2bds0.h	2003-01-13 14:18:15.000000000 +0000
+++ source/drivers/isdn/hisax/hfc_2bds0.h	2004-02-23 13:56:42.000000000 +0000
@@ -1,4 +1,4 @@
-/* $Id: hfc_2bds0.h,v 1.4.6.2 2001/09/23 22:24:47 kai Exp $
+/* $Id: hfc_2bds0.h,v 1.6.2.2 2004/01/12 22:52:26 keil Exp $
  *
  * specific defines for CCD's HFC 2BDS0
  *
@@ -124,5 +124,5 @@
 extern void main_irq_2bds0(struct BCState *bcs);
 extern void init2bds0(struct IsdnCardState *cs);
 extern void release2bds0(struct IsdnCardState *cs);
-extern void hfc2bds0_interrupt(struct IsdnCardState *cs, u8 val);
+extern void hfc2bds0_interrupt(struct IsdnCardState *cs, u_char val);
 extern void set_cs_func(struct IsdnCardState *cs);
--- diff/drivers/isdn/hisax/hfc_2bs0.c	2003-09-17 12:28:06.000000000 +0100
+++ source/drivers/isdn/hisax/hfc_2bs0.c	2004-02-23 13:56:42.000000000 +0000
@@ -1,4 +1,4 @@
-/* $Id: hfc_2bs0.c,v 1.17.6.3 2001/09/23 22:24:47 kai Exp $
+/* $Id: hfc_2bs0.c,v 1.20.2.6 2004/02/11 13:21:33 keil Exp $
  *
  * specific routines for CCD's HFC 2BS0
  *
@@ -17,26 +17,14 @@
 #include "isdnl1.h"
 #include <linux/interrupt.h>
 
-static inline u8
-hfc_read_reg(struct IsdnCardState *cs, int data, u8 reg)
-{
-	return cs->bc_hw_ops->read_reg(cs, data, reg);
-}
-
-static inline void
-hfc_write_reg(struct IsdnCardState *cs, int data, u8 reg, u8 val)
-{
-	cs->bc_hw_ops->write_reg(cs, data, reg, val);
-}
-
 static inline int
 WaitForBusy(struct IsdnCardState *cs)
 {
 	int to = 130;
-	u8 val;
+	u_char val;
 
-	while (!(hfc_read_reg(cs, HFC_STATUS, 0) & HFC_BUSY) && to) {
-		val = hfc_read_reg(cs, HFC_DATA, HFC_CIP | HFC_F2 |
+	while (!(cs->BC_Read_Reg(cs, HFC_STATUS, 0) & HFC_BUSY) && to) {
+		val = cs->BC_Read_Reg(cs, HFC_DATA, HFC_CIP | HFC_F2 |
 				      (cs->hw.hfc.cip & 3));
 		udelay(1);
 		to--;
@@ -53,7 +41,7 @@ WaitNoBusy(struct IsdnCardState *cs)
 {
 	int to = 125;
 
-	while ((hfc_read_reg(cs, HFC_STATUS, 0) & HFC_BUSY) && to) {
+	while ((cs->BC_Read_Reg(cs, HFC_STATUS, 0) & HFC_BUSY) && to) {
 		udelay(1);
 		to--;
 	}
@@ -79,14 +67,14 @@ GetFreeFifoBytes(struct BCState *bcs)
 }
 
 int
-ReadZReg(struct BCState *bcs, u8 reg)
+ReadZReg(struct BCState *bcs, u_char reg)
 {
 	int val;
 
 	WaitNoBusy(bcs->cs);
-	val = 256 * hfc_read_reg(bcs->cs, HFC_DATA, reg | HFC_CIP | HFC_Z_HIGH);
+	val = 256 * bcs->cs->BC_Read_Reg(bcs->cs, HFC_DATA, reg | HFC_CIP | HFC_Z_HIGH);
 	WaitNoBusy(bcs->cs);
-	val += hfc_read_reg(bcs->cs, HFC_DATA, reg | HFC_CIP | HFC_Z_LOW);
+	val += bcs->cs->BC_Read_Reg(bcs->cs, HFC_DATA, reg | HFC_CIP | HFC_Z_LOW);
 	return (val);
 }
 
@@ -96,21 +84,20 @@ hfc_clear_fifo(struct BCState *bcs)
 	struct IsdnCardState *cs = bcs->cs;
 	int idx, cnt;
 	int rcnt, z1, z2;
-	u8 cip, f1, f2;
+	u_char cip, f1, f2;
 
 	if ((cs->debug & L1_DEB_HSCX) && !(cs->debug & L1_DEB_HSCX_FIFO))
 		debugl1(cs, "hfc_clear_fifo");
-
 	cip = HFC_CIP | HFC_F1 | HFC_REC | HFC_CHANNEL(bcs->channel);
 	if ((cip & 0xc3) != (cs->hw.hfc.cip & 0xc3)) {
-		hfc_write_reg(cs, HFC_STATUS, cip, cip);
+		cs->BC_Write_Reg(cs, HFC_STATUS, cip, cip);
 		WaitForBusy(cs);
 	}
 	WaitNoBusy(cs);
-	f1 = hfc_read_reg(cs, HFC_DATA, cip);
+	f1 = cs->BC_Read_Reg(cs, HFC_DATA, cip);
 	cip = HFC_CIP | HFC_F2 | HFC_REC | HFC_CHANNEL(bcs->channel);
 	WaitNoBusy(cs);
-	f2 = hfc_read_reg(cs, HFC_DATA, cip);
+	f2 = cs->BC_Read_Reg(cs, HFC_DATA, cip);
 	z1 = ReadZReg(bcs, HFC_Z1 | HFC_REC | HFC_CHANNEL(bcs->channel));
 	z2 = ReadZReg(bcs, HFC_Z2 | HFC_REC | HFC_CHANNEL(bcs->channel));
 	cnt = 32;
@@ -129,21 +116,21 @@ hfc_clear_fifo(struct BCState *bcs)
 		cip = HFC_CIP | HFC_FIFO_OUT | HFC_REC | HFC_CHANNEL(bcs->channel);
 		idx = 0;
 		while ((idx < rcnt) && WaitNoBusy(cs)) {
-			hfc_read_reg(cs, HFC_DATA_NODEB, cip);
+			cs->BC_Read_Reg(cs, HFC_DATA_NODEB, cip);
 			idx++;
 		}
 		if (f1 != f2) {
 			WaitNoBusy(cs);
-			hfc_read_reg(cs, HFC_DATA, HFC_CIP | HFC_F2_INC | HFC_REC |
+			cs->BC_Read_Reg(cs, HFC_DATA, HFC_CIP | HFC_F2_INC | HFC_REC |
 					HFC_CHANNEL(bcs->channel));
 			WaitForBusy(cs);
 		}
 		cip = HFC_CIP | HFC_F1 | HFC_REC | HFC_CHANNEL(bcs->channel);
 		WaitNoBusy(cs);
-		f1 = hfc_read_reg(cs, HFC_DATA, cip);
+		f1 = cs->BC_Read_Reg(cs, HFC_DATA, cip);
 		cip = HFC_CIP | HFC_F2 | HFC_REC | HFC_CHANNEL(bcs->channel);
 		WaitNoBusy(cs);
-		f2 = hfc_read_reg(cs, HFC_DATA, cip);
+		f2 = cs->BC_Read_Reg(cs, HFC_DATA, cip);
 		z1 = ReadZReg(bcs, HFC_Z1 | HFC_REC | HFC_CHANNEL(bcs->channel));
 		z2 = ReadZReg(bcs, HFC_Z2 | HFC_REC | HFC_CHANNEL(bcs->channel));
 	}
@@ -155,12 +142,12 @@ static struct sk_buff
 *
 hfc_empty_fifo(struct BCState *bcs, int count)
 {
-	u8 *ptr;
+	u_char *ptr;
 	struct sk_buff *skb;
 	struct IsdnCardState *cs = bcs->cs;
 	int idx;
 	int chksum;
-	u8 stat, cip;
+	u_char stat, cip;
 
 	if ((cs->debug & L1_DEB_HSCX) && !(cs->debug & L1_DEB_HSCX_FIFO))
 		debugl1(cs, "hfc_empty_fifo");
@@ -170,9 +157,9 @@ hfc_empty_fifo(struct BCState *bcs, int 
 			debugl1(cs, "hfc_empty_fifo: incoming packet too large");
 		cip = HFC_CIP | HFC_FIFO_OUT | HFC_REC | HFC_CHANNEL(bcs->channel);
 		while ((idx++ < count) && WaitNoBusy(cs))
-			hfc_read_reg(cs, HFC_DATA_NODEB, cip);
+			cs->BC_Read_Reg(cs, HFC_DATA_NODEB, cip);
 		WaitNoBusy(cs);
-		stat = hfc_read_reg(cs, HFC_DATA, HFC_CIP | HFC_F2_INC | HFC_REC |
+		stat = cs->BC_Read_Reg(cs, HFC_DATA, HFC_CIP | HFC_F2_INC | HFC_REC |
 				       HFC_CHANNEL(bcs->channel));
 		WaitForBusy(cs);
 		return (NULL);
@@ -182,9 +169,9 @@ hfc_empty_fifo(struct BCState *bcs, int 
 			debugl1(cs, "hfc_empty_fifo: incoming packet too small");
 		cip = HFC_CIP | HFC_FIFO_OUT | HFC_REC | HFC_CHANNEL(bcs->channel);
 		while ((idx++ < count) && WaitNoBusy(cs))
-			hfc_read_reg(cs, HFC_DATA_NODEB, cip);
+			cs->BC_Read_Reg(cs, HFC_DATA_NODEB, cip);
 		WaitNoBusy(cs);
-		stat = hfc_read_reg(cs, HFC_DATA, HFC_CIP | HFC_F2_INC | HFC_REC |
+		stat = cs->BC_Read_Reg(cs, HFC_DATA, HFC_CIP | HFC_F2_INC | HFC_REC |
 				       HFC_CHANNEL(bcs->channel));
 		WaitForBusy(cs);
 #ifdef ERROR_STATISTIC
@@ -203,7 +190,7 @@ hfc_empty_fifo(struct BCState *bcs, int 
 		idx = 0;
 		cip = HFC_CIP | HFC_FIFO_OUT | HFC_REC | HFC_CHANNEL(bcs->channel);
 		while ((idx < count) && WaitNoBusy(cs)) {
-			*ptr++ = hfc_read_reg(cs, HFC_DATA_NODEB, cip);
+			*ptr++ = cs->BC_Read_Reg(cs, HFC_DATA_NODEB, cip);
 			idx++;
 		}
 		if (idx != count) {
@@ -212,7 +199,7 @@ hfc_empty_fifo(struct BCState *bcs, int 
 			dev_kfree_skb_any(skb);
 			if (bcs->mode != L1_MODE_TRANS) {
 			  WaitNoBusy(cs);
-			  stat = hfc_read_reg(cs, HFC_DATA, HFC_CIP | HFC_F2_INC | HFC_REC |
+			  stat = cs->BC_Read_Reg(cs, HFC_DATA, HFC_CIP | HFC_F2_INC | HFC_REC |
 						 HFC_CHANNEL(bcs->channel));
 			  WaitForBusy(cs);
 			}
@@ -220,11 +207,11 @@ hfc_empty_fifo(struct BCState *bcs, int 
 		}
 		if (bcs->mode != L1_MODE_TRANS) {
 		  WaitNoBusy(cs);
-		  chksum = (hfc_read_reg(cs, HFC_DATA, cip) << 8);
+		  chksum = (cs->BC_Read_Reg(cs, HFC_DATA, cip) << 8);
 		  WaitNoBusy(cs);
-		  chksum += hfc_read_reg(cs, HFC_DATA, cip);
+		  chksum += cs->BC_Read_Reg(cs, HFC_DATA, cip);
 		  WaitNoBusy(cs);
-		  stat = hfc_read_reg(cs, HFC_DATA, cip);
+		  stat = cs->BC_Read_Reg(cs, HFC_DATA, cip);
 		  if (cs->debug & L1_DEB_HSCX)
 		    debugl1(cs, "hfc_empty_fifo %d chksum %x stat %x",
 			    bcs->channel, chksum, stat);
@@ -237,7 +224,7 @@ hfc_empty_fifo(struct BCState *bcs, int 
 #endif
 		  }
 		  WaitNoBusy(cs);
-		  stat = hfc_read_reg(cs, HFC_DATA, HFC_CIP | HFC_F2_INC | HFC_REC |
+		  stat = cs->BC_Read_Reg(cs, HFC_DATA, HFC_CIP | HFC_F2_INC | HFC_REC |
 					 HFC_CHANNEL(bcs->channel));
 		  WaitForBusy(cs);
 		}
@@ -249,10 +236,10 @@ static void
 hfc_fill_fifo(struct BCState *bcs)
 {
 	struct IsdnCardState *cs = bcs->cs;
-	int fcnt;
-	u_int idx, count;
+	int idx, fcnt;
+	int count;
 	int z1, z2;
-	u8 cip;
+	u_char cip;
 
 	if (!bcs->tx_skb)
 		return;
@@ -261,15 +248,15 @@ hfc_fill_fifo(struct BCState *bcs)
 
 	cip = HFC_CIP | HFC_F1 | HFC_SEND | HFC_CHANNEL(bcs->channel);
 	if ((cip & 0xc3) != (cs->hw.hfc.cip & 0xc3)) {
-	  hfc_write_reg(cs, HFC_STATUS, cip, cip);
+	  cs->BC_Write_Reg(cs, HFC_STATUS, cip, cip);
 	  WaitForBusy(cs);
 	}
 	WaitNoBusy(cs);
 	if (bcs->mode != L1_MODE_TRANS) {
-	  bcs->hw.hfc.f1 = hfc_read_reg(cs, HFC_DATA, cip);
+	  bcs->hw.hfc.f1 = cs->BC_Read_Reg(cs, HFC_DATA, cip);
 	  cip = HFC_CIP | HFC_F2 | HFC_SEND | HFC_CHANNEL(bcs->channel);
 	  WaitNoBusy(cs);
-	  bcs->hw.hfc.f2 = hfc_read_reg(cs, HFC_DATA, cip);
+	  bcs->hw.hfc.f2 = cs->BC_Read_Reg(cs, HFC_DATA, cip);
 	  bcs->hw.hfc.send[bcs->hw.hfc.f1] = ReadZReg(bcs, HFC_Z1 | HFC_SEND | HFC_CHANNEL(bcs->channel));
 	  if (cs->debug & L1_DEB_HSCX)
 	    debugl1(cs, "hfc_fill_fifo %d f1(%d) f2(%d) z1(%x)",
@@ -305,7 +292,7 @@ hfc_fill_fifo(struct BCState *bcs)
 	cip = HFC_CIP | HFC_FIFO_IN | HFC_SEND | HFC_CHANNEL(bcs->channel);
 	idx = 0;
 	while ((idx < bcs->tx_skb->len) && WaitNoBusy(cs))
-		hfc_write_reg(cs, HFC_DATA_NODEB, cip, bcs->tx_skb->data[idx++]);
+		cs->BC_Write_Reg(cs, HFC_DATA_NODEB, cip, bcs->tx_skb->data[idx++]);
 	if (idx != bcs->tx_skb->len) {
 		debugl1(cs, "FIFO Send BUSY error");
 		printk(KERN_WARNING "HFC S FIFO channel %d BUSY Error\n", bcs->channel);
@@ -314,12 +301,20 @@ hfc_fill_fifo(struct BCState *bcs)
 		bcs->tx_cnt -= count;
 		if (PACKET_NOACK == bcs->tx_skb->pkt_type)
 			count = -1;
-
-		xmit_complete_b(bcs);
+		dev_kfree_skb_any(bcs->tx_skb);
+		bcs->tx_skb = NULL;
 		if (bcs->mode != L1_MODE_TRANS) {
 		  WaitForBusy(cs);
 		  WaitNoBusy(cs);
-		  hfc_read_reg(cs, HFC_DATA, HFC_CIP | HFC_F1_INC | HFC_SEND | HFC_CHANNEL(bcs->channel));
+		  cs->BC_Read_Reg(cs, HFC_DATA, HFC_CIP | HFC_F1_INC | HFC_SEND | HFC_CHANNEL(bcs->channel));
+		}
+		if (test_bit(FLG_LLI_L1WAKEUP,&bcs->st->lli.flag) &&
+			(count >= 0)) {
+			u_long	flags;
+			spin_lock_irqsave(&bcs->aclock, flags);
+			bcs->ackcnt += count;
+			spin_unlock_irqrestore(&bcs->aclock, flags);
+			schedule_event(bcs, B_ACKPENDING);
 		}
 		test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
 	}
@@ -331,7 +326,7 @@ main_irq_hfc(struct BCState *bcs)
 {
 	struct IsdnCardState *cs = bcs->cs;
 	int z1, z2, rcnt;
-	u8 f1, f2, cip;
+	u_char f1, f2, cip;
 	int receive, transmit, count = 5;
 	struct sk_buff *skb;
 
@@ -339,16 +334,16 @@ main_irq_hfc(struct BCState *bcs)
 	count--;
 	cip = HFC_CIP | HFC_F1 | HFC_REC | HFC_CHANNEL(bcs->channel);
 	if ((cip & 0xc3) != (cs->hw.hfc.cip & 0xc3)) {
-		hfc_write_reg(cs, HFC_STATUS, cip, cip);
+		cs->BC_Write_Reg(cs, HFC_STATUS, cip, cip);
 		WaitForBusy(cs);
 	}
 	WaitNoBusy(cs);
 	receive = 0;
 	if (bcs->mode == L1_MODE_HDLC) {
-		f1 = hfc_read_reg(cs, HFC_DATA, cip);
+		f1 = cs->BC_Read_Reg(cs, HFC_DATA, cip);
 		cip = HFC_CIP | HFC_F2 | HFC_REC | HFC_CHANNEL(bcs->channel);
 		WaitNoBusy(cs);
-		f2 = hfc_read_reg(cs, HFC_DATA, cip);
+		f2 = cs->BC_Read_Reg(cs, HFC_DATA, cip);
 		if (f1 != f2) {
 			if (cs->debug & L1_DEB_HSCX)
 				debugl1(cs, "hfc rec %d f1(%d) f2(%d)",
@@ -368,14 +363,14 @@ main_irq_hfc(struct BCState *bcs)
 			if (cs->debug & L1_DEB_HSCX)
 				debugl1(cs, "hfc rec %d z1(%x) z2(%x) cnt(%d)",
 					bcs->channel, z1, z2, rcnt);
+			/*              sti(); */
 			if ((skb = hfc_empty_fifo(bcs, rcnt))) {
 				skb_queue_tail(&bcs->rqueue, skb);
-				sched_b_event(bcs, B_RCVBUFREADY);
+				schedule_event(bcs, B_RCVBUFREADY);
 			}
 		}
 		receive = 1;
 	}
-	udelay(1);
 	if (bcs->tx_skb) {
 		transmit = 1;
 		test_and_set_bit(BC_FLG_BUSY, &bcs->Flag);
@@ -391,7 +386,7 @@ main_irq_hfc(struct BCState *bcs)
 				transmit = 0;
 		} else {
 			transmit = 0;
-			sched_b_event(bcs, B_XMTBUFREADY);
+			schedule_event(bcs, B_XMTBUFREADY);
 		}
 	}
 	if ((receive || transmit) && count)
@@ -423,7 +418,7 @@ mode_hfc(struct BCState *bcs, int mode, 
 			break;
 		case (L1_MODE_TRANS):
 		        cs->hw.hfc.ctmt &= ~(1 << bc); /* set HDLC mode */ 
-			hfc_write_reg(cs, HFC_STATUS, cs->hw.hfc.ctmt, cs->hw.hfc.ctmt);
+			cs->BC_Write_Reg(cs, HFC_STATUS, cs->hw.hfc.ctmt, cs->hw.hfc.ctmt);
 			hfc_clear_fifo(bcs); /* complete fifo clear */ 
 			if (bc) {
 				cs->hw.hfc.ctmt |= 1;
@@ -447,8 +442,8 @@ mode_hfc(struct BCState *bcs, int mode, 
 			}
 			break;
 	}
-	hfc_write_reg(cs, HFC_STATUS, cs->hw.hfc.ctmt, cs->hw.hfc.ctmt);
-	cs->dc_hw_ops->write_reg(cs, ISAC_SPCR, cs->hw.hfc.isac_spcr);
+	cs->BC_Write_Reg(cs, HFC_STATUS, cs->hw.hfc.ctmt, cs->hw.hfc.ctmt);
+	cs->writeisac(cs, ISAC_SPCR, cs->hw.hfc.isac_spcr);
 	if (mode == L1_MODE_HDLC)
 		hfc_clear_fifo(bcs);
 }
@@ -456,31 +451,57 @@ mode_hfc(struct BCState *bcs, int mode, 
 static void
 hfc_l2l1(struct PStack *st, int pr, void *arg)
 {
-	struct sk_buff *skb = arg;
+	struct BCState	*bcs = st->l1.bcs;
+	struct sk_buff	*skb = arg;
+	u_long		flags;
 
 	switch (pr) {
 		case (PH_DATA | REQUEST):
-			xmit_data_req_b(st->l1.bcs, skb);
+			spin_lock_irqsave(&bcs->cs->lock, flags);
+			if (bcs->tx_skb) {
+				skb_queue_tail(&bcs->squeue, skb);
+			} else {
+				bcs->tx_skb = skb;
+				test_and_set_bit(BC_FLG_BUSY, &bcs->Flag);
+				bcs->cs->BC_Send_Data(bcs);
+			}
+			spin_unlock_irqrestore(&bcs->cs->lock, flags);
 			break;
 		case (PH_PULL | INDICATION):
-			xmit_pull_ind_b(st->l1.bcs, skb);
+			spin_lock_irqsave(&bcs->cs->lock, flags);
+			if (bcs->tx_skb) {
+				printk(KERN_WARNING "hfc_l2l1: this shouldn't happen\n");
+			} else {
+				test_and_set_bit(BC_FLG_BUSY, &bcs->Flag);
+				bcs->tx_skb = skb;
+				bcs->cs->BC_Send_Data(bcs);
+			}
+			spin_unlock_irqrestore(&bcs->cs->lock, flags);
 			break;
 		case (PH_PULL | REQUEST):
-			xmit_pull_req_b(st);
+			if (!bcs->tx_skb) {
+				test_and_clear_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
+				st->l1.l1l2(st, PH_PULL | CONFIRM, NULL);
+			} else
+				test_and_set_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
 			break;
 		case (PH_ACTIVATE | REQUEST):
-			test_and_set_bit(BC_FLG_ACTIV, &st->l1.bcs->Flag);
-			mode_hfc(st->l1.bcs, st->l1.mode, st->l1.bc);
+			spin_lock_irqsave(&bcs->cs->lock, flags);
+			test_and_set_bit(BC_FLG_ACTIV, &bcs->Flag);
+			mode_hfc(bcs, st->l1.mode, st->l1.bc);
+			spin_unlock_irqrestore(&bcs->cs->lock, flags);
 			l1_msg_b(st, pr, arg);
 			break;
 		case (PH_DEACTIVATE | REQUEST):
 			l1_msg_b(st, pr, arg);
 			break;
 		case (PH_DEACTIVATE | CONFIRM):
-			test_and_clear_bit(BC_FLG_ACTIV, &st->l1.bcs->Flag);
-			test_and_clear_bit(BC_FLG_BUSY, &st->l1.bcs->Flag);
-			mode_hfc(st->l1.bcs, 0, st->l1.bc);
-			L1L2(st, PH_DEACTIVATE | CONFIRM, NULL);
+			spin_lock_irqsave(&bcs->cs->lock, flags);
+			test_and_clear_bit(BC_FLG_ACTIV, &bcs->Flag);
+			test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
+			mode_hfc(bcs, 0, st->l1.bc);
+			spin_unlock_irqrestore(&bcs->cs->lock, flags);
+			st->l1.l1l2(st, PH_DEACTIVATE | CONFIRM, NULL);
 			break;
 	}
 }
@@ -523,7 +544,7 @@ setstack_hfc(struct PStack *st, struct B
 	if (open_hfcstate(st->l1.hardware, bcs))
 		return (-1);
 	st->l1.bcs = bcs;
-	st->l1.l2l1 = hfc_l2l1;
+	st->l2.l2l1 = hfc_l2l1;
 	setstack_manager(st);
 	bcs->st = st;
 	setstack_l1_B(st);
@@ -544,18 +565,16 @@ init_send(struct BCState *bcs)
 		bcs->hw.hfc.send[i] = 0x1fff;
 }
 
-static struct bc_l1_ops hfc_l1_ops = {
-	.fill_fifo = hfc_fill_fifo,
-	.open      = setstack_hfc,
-	.close     = close_hfcstate,
-};
-
 void __init
 inithfc(struct IsdnCardState *cs)
 {
 	init_send(&cs->bcs[0]);
 	init_send(&cs->bcs[1]);
-	cs->bc_l1_ops = &hfc_l1_ops;
+	cs->BC_Send_Data = &hfc_fill_fifo;
+	cs->bcs[0].BC_SetStack = setstack_hfc;
+	cs->bcs[1].BC_SetStack = setstack_hfc;
+	cs->bcs[0].BC_Close = close_hfcstate;
+	cs->bcs[1].BC_Close = close_hfcstate;
 	mode_hfc(cs->bcs, 0, 0);
 	mode_hfc(cs->bcs + 1, 0, 0);
 }
@@ -572,10 +591,3 @@ releasehfc(struct IsdnCardState *cs)
 		cs->bcs[1].hw.hfc.send = NULL;
 	}
 }
-
-int
-hfc_setup(struct IsdnCardState *cs, struct bc_hw_ops *hfc_ops)
-{
-	cs->bc_hw_ops = hfc_ops;
-	return 0;
-}
--- diff/drivers/isdn/hisax/hfc_2bs0.h	2003-01-16 11:30:36.000000000 +0000
+++ source/drivers/isdn/hisax/hfc_2bs0.h	2004-02-23 13:56:42.000000000 +0000
@@ -1,4 +1,4 @@
-/* $Id: hfc_2bs0.h,v 1.3.6.2 2001/09/23 22:24:47 kai Exp $
+/* $Id: hfc_2bs0.h,v 1.5.2.2 2004/01/12 22:52:26 keil Exp $
  *
  * specific defines for CCD's HFC 2BS0
  *
@@ -58,4 +58,3 @@
 extern void main_irq_hfc(struct BCState *bcs);
 extern void inithfc(struct IsdnCardState *cs);
 extern void releasehfc(struct IsdnCardState *cs);
-extern int  hfc_setup(struct IsdnCardState *cs, struct bc_hw_ops *hfc_ops);
--- diff/drivers/isdn/hisax/hfc_pci.c	2003-09-17 12:28:06.000000000 +0100
+++ source/drivers/isdn/hisax/hfc_pci.c	2004-02-23 13:56:42.000000000 +0000
@@ -1,4 +1,4 @@
-/* $Id: hfc_pci.c,v 1.34.6.8 2001/09/23 22:24:47 kai Exp $
+/* $Id: hfc_pci.c,v 1.48.2.4 2004/02/11 13:21:33 keil Exp $
  *
  * low level driver for CCD´s hfc-pci based cards
  *
@@ -25,7 +25,7 @@
 
 extern const char *CardType[];
 
-static const char *hfcpci_revision = "$Revision: 1.34.6.8 $";
+static const char *hfcpci_revision = "$Revision: 1.48.2.4 $";
 
 /* table entry in the PCI devices list */
 typedef struct {
@@ -65,45 +65,47 @@ static const PCI_ENTRY id_list[] =
 };
 
 
+#if CONFIG_PCI
+
 /******************************************/
 /* free hardware resources used by driver */
 /******************************************/
-static void
-hfcpci_release(struct IsdnCardState *cs)
+void
+release_io_hfcpci(struct IsdnCardState *cs)
 {
 	printk(KERN_INFO "HiSax: release hfcpci at %p\n",
 		cs->hw.hfcpci.pci_io);
-	cs->hw.hfcpci.int_m2 = 0;	/* interrupt output off ! */
+	cs->hw.hfcpci.int_m2 = 0;					/* interrupt output off ! */
 	Write_hfc(cs, HFCPCI_INT_M2, cs->hw.hfcpci.int_m2);
-	Write_hfc(cs, HFCPCI_CIRM, HFCPCI_RESET);	/* Reset On */
-	set_current_state(TASK_UNINTERRUPTIBLE);
-	schedule_timeout((30 * HZ) / 1000);	/* Timeout 30ms */
-	Write_hfc(cs, HFCPCI_CIRM, 0);	/* Reset Off */
-	pci_disable_device(cs->hw.hfcpci.pdev);
+	Write_hfc(cs, HFCPCI_CIRM, HFCPCI_RESET);			/* Reset On */
+	mdelay(10);
+	Write_hfc(cs, HFCPCI_CIRM, 0);					/* Reset Off */
+	mdelay(10);
+	Write_hfc(cs, HFCPCI_INT_M2, cs->hw.hfcpci.int_m2);
+	pci_write_config_word(cs->hw.hfcpci.dev, PCI_COMMAND, 0);	/* disable memory mapped ports + busmaster */
 	del_timer(&cs->hw.hfcpci.timer);
-	pci_free_consistent(cs->hw.hfcpci.pdev, 32768, cs->hw.hfcpci.fifos, cs->hw.hfcpci.fifos_dma);
-	hisax_release_resources(cs);
+	kfree(cs->hw.hfcpci.share_start);
+	cs->hw.hfcpci.share_start = NULL;
+	iounmap((void *)cs->hw.hfcpci.pci_io);
 }
 
 /********************************************************************************/
 /* function called to reset the HFC PCI chip. A complete software reset of chip */
 /* and fifos is done.                                                           */
 /********************************************************************************/
-static int
-hfcpci_reset(struct IsdnCardState *cs)
+static void
+reset_hfcpci(struct IsdnCardState *cs)
 {
-	pci_disable_device(cs->hw.hfcpci.pdev);
+	pci_write_config_word(cs->hw.hfcpci.dev, PCI_COMMAND, PCI_ENA_MEMIO);	/* enable memory mapped ports, disable busmaster */
 	cs->hw.hfcpci.int_m2 = 0;	/* interrupt output off ! */
 	Write_hfc(cs, HFCPCI_INT_M2, cs->hw.hfcpci.int_m2);
 
 	printk(KERN_INFO "HFC_PCI: resetting card\n");
-	pci_set_master(cs->hw.hfcpci.pdev);
+	pci_write_config_word(cs->hw.hfcpci.dev, PCI_COMMAND, PCI_ENA_MEMIO + PCI_ENA_MASTER);	/* enable memory ports + busmaster */
 	Write_hfc(cs, HFCPCI_CIRM, HFCPCI_RESET);	/* Reset On */
-	set_current_state(TASK_UNINTERRUPTIBLE);
-	schedule_timeout((30 * HZ) / 1000);	/* Timeout 30ms */
+	mdelay(10);
 	Write_hfc(cs, HFCPCI_CIRM, 0);	/* Reset Off */
-	set_current_state(TASK_UNINTERRUPTIBLE);
-	schedule_timeout((20 * HZ) / 1000);	/* Timeout 20ms */
+	mdelay(10);
 	if (Read_hfc(cs, HFCPCI_STATUS) & 2)
 		printk(KERN_WARNING "HFC-PCI init bit busy\n");
 
@@ -156,9 +158,7 @@ hfcpci_reset(struct IsdnCardState *cs)
 	/* Finally enable IRQ output */
 	cs->hw.hfcpci.int_m2 = HFCPCI_IRQ_ENABLE;
 	Write_hfc(cs, HFCPCI_INT_M2, cs->hw.hfcpci.int_m2);
-	if (Read_hfc(cs, HFCPCI_INT_S2));
-	
-	return 0;
+	if (Read_hfc(cs, HFCPCI_INT_S1));
 }
 
 /***************************************************/
@@ -174,6 +174,27 @@ hfcpci_Timer(struct IsdnCardState *cs)
  */
 }
 
+
+/*********************************/
+/* schedule a new D-channel task */
+/*********************************/
+static void
+sched_event_D_pci(struct IsdnCardState *cs, int event)
+{
+	test_and_set_bit(event, &cs->event);
+	schedule_work(&cs->tqueue);
+}
+
+/*********************************/
+/* schedule a new b_channel task */
+/*********************************/
+static void
+hfcpci_sched_event(struct BCState *bcs, int event)
+{
+	test_and_set_bit(event, &bcs->event);
+	schedule_work(&bcs->tqueue);
+}
+
 /************************************************/
 /* select a b-channel entry matching and active */
 /************************************************/
@@ -193,7 +214,7 @@ Sel_BCS(struct IsdnCardState *cs, int ch
 /* clear the desired B-channel rx fifo */
 /***************************************/
 static void hfcpci_clear_fifo_rx(struct IsdnCardState *cs, int fifo)
-{       u8 fifo_state;
+{       u_char fifo_state;
         bzfifo_type *bzr;
 
 	if (fifo) {
@@ -207,7 +228,7 @@ static void hfcpci_clear_fifo_rx(struct 
 	        cs->hw.hfcpci.fifo_en ^= fifo_state;
 	Write_hfc(cs, HFCPCI_FIFO_EN, cs->hw.hfcpci.fifo_en);
 	cs->hw.hfcpci.last_bfifo_cnt[fifo] = 0;
-	bzr->za[MAX_B_FRAMES].z1 = cpu_to_le16(B_FIFO_SIZE + B_SUB_VAL - 1);
+	bzr->za[MAX_B_FRAMES].z1 = B_FIFO_SIZE + B_SUB_VAL - 1;
 	bzr->za[MAX_B_FRAMES].z2 = bzr->za[MAX_B_FRAMES].z1;
 	bzr->f1 = MAX_B_FRAMES;
 	bzr->f2 = bzr->f1;	/* init F pointers to remain constant */
@@ -220,7 +241,7 @@ static void hfcpci_clear_fifo_rx(struct 
 /* clear the desired B-channel tx fifo */
 /***************************************/
 static void hfcpci_clear_fifo_tx(struct IsdnCardState *cs, int fifo)
-{       u8 fifo_state;
+{       u_char fifo_state;
         bzfifo_type *bzt;
 
 	if (fifo) {
@@ -233,7 +254,7 @@ static void hfcpci_clear_fifo_tx(struct 
 	if (fifo_state)
 	        cs->hw.hfcpci.fifo_en ^= fifo_state;
 	Write_hfc(cs, HFCPCI_FIFO_EN, cs->hw.hfcpci.fifo_en);
-	bzt->za[MAX_B_FRAMES].z1 = cpu_to_le16(B_FIFO_SIZE + B_SUB_VAL - 1);
+	bzt->za[MAX_B_FRAMES].z1 = B_FIFO_SIZE + B_SUB_VAL - 1;
 	bzt->za[MAX_B_FRAMES].z2 = bzt->za[MAX_B_FRAMES].z1;
 	bzt->f1 = MAX_B_FRAMES;
 	bzt->f2 = bzt->f1;	/* init F pointers to remain constant */
@@ -247,9 +268,9 @@ static void hfcpci_clear_fifo_tx(struct 
 /*********************************************/
 static struct sk_buff
 *
-hfcpci_empty_fifo(struct BCState *bcs, bzfifo_type * bz, u8 * bdata, int count)
+hfcpci_empty_fifo(struct BCState *bcs, bzfifo_type * bz, u_char * bdata, int count)
 {
-	u8 *ptr, *ptr1, new_f2;
+	u_char *ptr, *ptr1, new_f2;
 	struct sk_buff *skb;
 	struct IsdnCardState *cs = bcs->cs;
 	int total, maxlen, new_z2;
@@ -258,18 +279,18 @@ hfcpci_empty_fifo(struct BCState *bcs, b
 	if ((cs->debug & L1_DEB_HSCX) && !(cs->debug & L1_DEB_HSCX_FIFO))
 		debugl1(cs, "hfcpci_empty_fifo");
 	zp = &bz->za[bz->f2];	/* point to Z-Regs */
-	new_z2 = le16_to_cpu(zp->z2) + count;	/* new position in fifo */
+	new_z2 = zp->z2 + count;	/* new position in fifo */
 	if (new_z2 >= (B_FIFO_SIZE + B_SUB_VAL))
 		new_z2 -= B_FIFO_SIZE;	/* buffer wrap */
 	new_f2 = (bz->f2 + 1) & MAX_B_FRAMES;
 	if ((count > HSCX_BUFMAX + 3) || (count < 4) ||
-	    (*(bdata + (le16_to_cpu(zp->z1) - B_SUB_VAL)))) {
+	    (*(bdata + (zp->z1 - B_SUB_VAL)))) {
 		if (cs->debug & L1_DEB_WARN)
 			debugl1(cs, "hfcpci_empty_fifo: incoming packet invalid length %d or crc", count);
 #ifdef ERROR_STATISTIC
 		bcs->err_inv++;
 #endif
-		bz->za[new_f2].z2 = cpu_to_le16(new_z2);
+		bz->za[new_f2].z2 = new_z2;
 		bz->f2 = new_f2;	/* next buffer */
 		skb = NULL;
 	} else if (!(skb = dev_alloc_skb(count - 3)))
@@ -279,12 +300,12 @@ hfcpci_empty_fifo(struct BCState *bcs, b
 		count -= 3;
 		ptr = skb_put(skb, count);
 
-		if (le16_to_cpu(zp->z2) + count <= B_FIFO_SIZE + B_SUB_VAL)
+		if (zp->z2 + count <= B_FIFO_SIZE + B_SUB_VAL)
 			maxlen = count;		/* complete transfer */
 		else
-			maxlen = B_FIFO_SIZE + B_SUB_VAL - le16_to_cpu(zp->z2);	/* maximum */
+			maxlen = B_FIFO_SIZE + B_SUB_VAL - zp->z2;	/* maximum */
 
-		ptr1 = bdata + (le16_to_cpu(zp->z2) - B_SUB_VAL);	/* start of data */
+		ptr1 = bdata + (zp->z2 - B_SUB_VAL);	/* start of data */
 		memcpy(ptr, ptr1, maxlen);	/* copy data */
 		count -= maxlen;
 
@@ -293,7 +314,7 @@ hfcpci_empty_fifo(struct BCState *bcs, b
 			ptr1 = bdata;	/* start of buffer */
 			memcpy(ptr, ptr1, count);	/* rest */
 		}
-		bz->za[new_f2].z2 = cpu_to_le16(new_z2);
+		bz->za[new_f2].z2 = new_z2;
 		bz->f2 = new_f2;	/* next buffer */
 
 	}
@@ -311,41 +332,45 @@ receive_dmsg(struct IsdnCardState *cs)
 	int maxlen;
 	int rcnt, total;
 	int count = 5;
-	u8 *ptr, *ptr1;
+	u_char *ptr, *ptr1;
 	dfifo_type *df;
 	z_type *zp;
 
 	df = &((fifo_area *) (cs->hw.hfcpci.fifos))->d_chan.d_rx;
+	if (test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) {
+		debugl1(cs, "rec_dmsg blocked");
+		return (1);
+	}
 	while (((df->f1 & D_FREG_MASK) != (df->f2 & D_FREG_MASK)) && count--) {
 		zp = &df->za[df->f2 & D_FREG_MASK];
-		rcnt = le16_to_cpu(zp->z1) - le16_to_cpu(zp->z2);
+		rcnt = zp->z1 - zp->z2;
 		if (rcnt < 0)
 			rcnt += D_FIFO_SIZE;
 		rcnt++;
 		if (cs->debug & L1_DEB_ISAC)
 			debugl1(cs, "hfcpci recd f1(%d) f2(%d) z1(%x) z2(%x) cnt(%d)",
-				df->f1, df->f2, le16_to_cpu(zp->z1), le16_to_cpu(zp->z2), rcnt);
+				df->f1, df->f2, zp->z1, zp->z2, rcnt);
 
 		if ((rcnt > MAX_DFRAME_LEN + 3) || (rcnt < 4) ||
-		    (df->data[le16_to_cpu(zp->z1)])) {
+		    (df->data[zp->z1])) {
 			if (cs->debug & L1_DEB_WARN)
-				debugl1(cs, "empty_fifo hfcpci paket inv. len %d or crc %d", rcnt, df->data[le16_to_cpu(zp->z1)]);
+				debugl1(cs, "empty_fifo hfcpci paket inv. len %d or crc %d", rcnt, df->data[zp->z1]);
 #ifdef ERROR_STATISTIC
 			cs->err_rx++;
 #endif
 			df->f2 = ((df->f2 + 1) & MAX_D_FRAMES) | (MAX_D_FRAMES + 1);	/* next buffer */
-			df->za[df->f2 & D_FREG_MASK].z2 = cpu_to_le16((le16_to_cpu(zp->z2) + rcnt) & (D_FIFO_SIZE - 1));
+			df->za[df->f2 & D_FREG_MASK].z2 = (zp->z2 + rcnt) & (D_FIFO_SIZE - 1);
 		} else if ((skb = dev_alloc_skb(rcnt - 3))) {
 			total = rcnt;
 			rcnt -= 3;
 			ptr = skb_put(skb, rcnt);
 
-			if ((le16_to_cpu(zp->z2) + rcnt) <= D_FIFO_SIZE)
+			if (zp->z2 + rcnt <= D_FIFO_SIZE)
 				maxlen = rcnt;	/* complete transfer */
 			else
-				maxlen = D_FIFO_SIZE - le16_to_cpu(zp->z2);	/* maximum */
+				maxlen = D_FIFO_SIZE - zp->z2;	/* maximum */
 
-			ptr1 = df->data + le16_to_cpu(zp->z2);	/* start of data */
+			ptr1 = df->data + zp->z2;	/* start of data */
 			memcpy(ptr, ptr1, maxlen);	/* copy data */
 			rcnt -= maxlen;
 
@@ -355,13 +380,14 @@ receive_dmsg(struct IsdnCardState *cs)
 				memcpy(ptr, ptr1, rcnt);	/* rest */
 			}
 			df->f2 = ((df->f2 + 1) & MAX_D_FRAMES) | (MAX_D_FRAMES + 1);	/* next buffer */
-			df->za[df->f2 & D_FREG_MASK].z2 = cpu_to_le16((le16_to_cpu(zp->z2) + total) & (D_FIFO_SIZE - 1));
+			df->za[df->f2 & D_FREG_MASK].z2 = (zp->z2 + total) & (D_FIFO_SIZE - 1);
 
 			skb_queue_tail(&cs->rq, skb);
-			sched_d_event(cs, D_RCVBUFREADY);
+			sched_event_D_pci(cs, D_RCVBUFREADY);
 		} else
 			printk(KERN_WARNING "HFC-PCI: D receive out of memory\n");
 	}
+	test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);
 	return (1);
 }
 
@@ -369,17 +395,17 @@ receive_dmsg(struct IsdnCardState *cs)
 /* check for transparent receive data and read max one threshold size if avail */
 /*******************************************************************************/
 int
-hfcpci_empty_fifo_trans(struct BCState *bcs, bzfifo_type * bz, u8 * bdata)
+hfcpci_empty_fifo_trans(struct BCState *bcs, bzfifo_type * bz, u_char * bdata)
 {
 	unsigned short *z1r, *z2r;
 	int new_z2, fcnt, maxlen;
 	struct sk_buff *skb;
-	u8 *ptr, *ptr1;
+	u_char *ptr, *ptr1;
 
 	z1r = &bz->za[MAX_B_FRAMES].z1;		/* pointer to z reg */
 	z2r = z1r + 1;
 
-	if (!(fcnt = le16_to_cpu(*z1r) - le16_to_cpu(*z2r)))
+	if (!(fcnt = *z1r - *z2r))
 		return (0);	/* no data avail */
 
 	if (fcnt <= 0)
@@ -387,7 +413,7 @@ hfcpci_empty_fifo_trans(struct BCState *
 	if (fcnt > HFCPCI_BTRANS_THRESHOLD)
 		fcnt = HFCPCI_BTRANS_THRESHOLD;		/* limit size */
 
-	new_z2 = le16_to_cpu(*z2r) + fcnt;	/* new position in fifo */
+	new_z2 = *z2r + fcnt;	/* new position in fifo */
 	if (new_z2 >= (B_FIFO_SIZE + B_SUB_VAL))
 		new_z2 -= B_FIFO_SIZE;	/* buffer wrap */
 
@@ -395,12 +421,12 @@ hfcpci_empty_fifo_trans(struct BCState *
 		printk(KERN_WARNING "HFCPCI: receive out of memory\n");
 	else {
 		ptr = skb_put(skb, fcnt);
-		if (le16_to_cpu(*z2r) + fcnt <= B_FIFO_SIZE + B_SUB_VAL)
+		if (*z2r + fcnt <= B_FIFO_SIZE + B_SUB_VAL)
 			maxlen = fcnt;	/* complete transfer */
 		else
-			maxlen = B_FIFO_SIZE + B_SUB_VAL - le16_to_cpu(*z2r);	/* maximum */
+			maxlen = B_FIFO_SIZE + B_SUB_VAL - *z2r;	/* maximum */
 
-		ptr1 = bdata + (le16_to_cpu(*z2r) - B_SUB_VAL);	/* start of data */
+		ptr1 = bdata + (*z2r - B_SUB_VAL);	/* start of data */
 		memcpy(ptr, ptr1, maxlen);	/* copy data */
 		fcnt -= maxlen;
 
@@ -410,10 +436,10 @@ hfcpci_empty_fifo_trans(struct BCState *
 			memcpy(ptr, ptr1, fcnt);	/* rest */
 		}
 		skb_queue_tail(&bcs->rqueue, skb);
-		sched_b_event(bcs, B_RCVBUFREADY);
+		hfcpci_sched_event(bcs, B_RCVBUFREADY);
 	}
 
-	*z2r = cpu_to_le16(new_z2);		/* new position */
+	*z2r = new_z2;		/* new position */
 	return (1);
 }				/* hfcpci_empty_fifo_trans */
 
@@ -428,9 +454,10 @@ main_rec_hfcpci(struct BCState *bcs)
 	int receive, count = 5;
 	struct sk_buff *skb;
 	bzfifo_type *bz;
-	u8 *bdata;
+	u_char *bdata;
 	z_type *zp;
 
+
 	if ((bcs->channel) && (!cs->hw.hfcpci.bswapped)) {
 		bz = &((fifo_area *) (cs->hw.hfcpci.fifos))->b_chans.rxbz_b2;
 		bdata = ((fifo_area *) (cs->hw.hfcpci.fifos))->b_chans.rxdat_b2;
@@ -442,22 +469,26 @@ main_rec_hfcpci(struct BCState *bcs)
 	}
       Begin:
 	count--;
+	if (test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) {
+		debugl1(cs, "rec_data %d blocked", bcs->channel);
+		return;
+	}
 	if (bz->f1 != bz->f2) {
 		if (cs->debug & L1_DEB_HSCX)
 			debugl1(cs, "hfcpci rec %d f1(%d) f2(%d)",
 				bcs->channel, bz->f1, bz->f2);
 		zp = &bz->za[bz->f2];
 
-		rcnt = le16_to_cpu(zp->z1) - le16_to_cpu(zp->z2);
+		rcnt = zp->z1 - zp->z2;
 		if (rcnt < 0)
 			rcnt += B_FIFO_SIZE;
 		rcnt++;
 		if (cs->debug & L1_DEB_HSCX)
 			debugl1(cs, "hfcpci rec %d z1(%x) z2(%x) cnt(%d)",
-				bcs->channel, le16_to_cpu(zp->z1), le16_to_cpu(zp->z2), rcnt);
+				bcs->channel, zp->z1, zp->z2, rcnt);
 		if ((skb = hfcpci_empty_fifo(bcs, bz, bdata, rcnt))) {
 			skb_queue_tail(&bcs->rqueue, skb);
-			sched_b_event(bcs, B_RCVBUFREADY);
+			hfcpci_sched_event(bcs, B_RCVBUFREADY);
 		}
 		rcnt = bz->f1 - bz->f2;
 		if (rcnt < 0)
@@ -475,7 +506,7 @@ main_rec_hfcpci(struct BCState *bcs)
 		receive = hfcpci_empty_fifo_trans(bcs, bz, bdata);
 	else
 		receive = 0;
-
+	test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);
 	if (count && receive)
 		goto Begin;
 	return;
@@ -487,10 +518,10 @@ main_rec_hfcpci(struct BCState *bcs)
 static void
 hfcpci_fill_dfifo(struct IsdnCardState *cs)
 {
-	int fcnt, new_z1, maxlen;
-	u_int count;
+	int fcnt;
+	int count, new_z1, maxlen;
 	dfifo_type *df;
-	u8 *src, *dst, new_f1;
+	u_char *src, *dst, new_f1;
 
 	if (!cs->tx_skb)
 		return;
@@ -502,7 +533,7 @@ hfcpci_fill_dfifo(struct IsdnCardState *
 	if (cs->debug & L1_DEB_ISAC)
 		debugl1(cs, "hfcpci_fill_Dfifo f1(%d) f2(%d) z1(f1)(%x)",
 			df->f1, df->f2,
-			le16_to_cpu(df->za[df->f1 & D_FREG_MASK].z1));
+			df->za[df->f1 & D_FREG_MASK].z1);
 	fcnt = df->f1 - df->f2;	/* frame count actually buffered */
 	if (fcnt < 0)
 		fcnt += (MAX_D_FRAMES + 1);	/* if wrap around */
@@ -515,7 +546,7 @@ hfcpci_fill_dfifo(struct IsdnCardState *
 		return;
 	}
 	/* now determine free bytes in FIFO buffer */
-	count = le16_to_cpu(df->za[df->f1 & D_FREG_MASK].z2) - le16_to_cpu(df->za[df->f1 & D_FREG_MASK].z1);
+	count = df->za[df->f2 & D_FREG_MASK].z2 - df->za[df->f1 & D_FREG_MASK].z1 - 1;
 	if (count <= 0)
 		count += D_FIFO_SIZE;	/* count now contains available bytes */
 
@@ -528,12 +559,12 @@ hfcpci_fill_dfifo(struct IsdnCardState *
 		return;
 	}
 	count = cs->tx_skb->len;	/* get frame len */
-	new_z1 = (le16_to_cpu(df->za[df->f1 & D_FREG_MASK].z1) + count) & (D_FIFO_SIZE - 1);
+	new_z1 = (df->za[df->f1 & D_FREG_MASK].z1 + count) & (D_FIFO_SIZE - 1);
 	new_f1 = ((df->f1 + 1) & D_FREG_MASK) | (D_FREG_MASK + 1);
 	src = cs->tx_skb->data;	/* source pointer */
-	dst = df->data + le16_to_cpu(df->za[df->f1 & D_FREG_MASK].z1);
-	maxlen = D_FIFO_SIZE - le16_to_cpu(df->za[df->f1 & D_FREG_MASK].z1);		/* end fifo */
-	if (maxlen > (int)count)
+	dst = df->data + df->za[df->f1 & D_FREG_MASK].z1;
+	maxlen = D_FIFO_SIZE - df->za[df->f1 & D_FREG_MASK].z1;		/* end fifo */
+	if (maxlen > count)
 		maxlen = count;	/* limit size */
 	memcpy(dst, src, maxlen);	/* first copy */
 
@@ -543,8 +574,8 @@ hfcpci_fill_dfifo(struct IsdnCardState *
 		src += maxlen;	/* new position */
 		memcpy(dst, src, count);
 	}
-	df->za[new_f1 & D_FREG_MASK].z1 = cpu_to_le16(new_z1);	/* for next buffer */
-	df->za[df->f1 & D_FREG_MASK].z1 = cpu_to_le16(new_z1);	/* new pos actual buffer */
+	df->za[new_f1 & D_FREG_MASK].z1 = new_z1;	/* for next buffer */
+	df->za[df->f1 & D_FREG_MASK].z1 = new_z1;	/* new pos actual buffer */
 	df->f1 = new_f1;	/* next frame */
 
 	dev_kfree_skb_any(cs->tx_skb);
@@ -559,11 +590,11 @@ static void
 hfcpci_fill_fifo(struct BCState *bcs)
 {
 	struct IsdnCardState *cs = bcs->cs;
-	int maxlen, fcnt, new_z1;
-	u_int count;
+	int maxlen, fcnt;
+	int count, new_z1;
 	bzfifo_type *bz;
-	u8 *bdata;
-	u8 new_f1, *src, *dst;
+	u_char *bdata;
+	u_char new_f1, *src, *dst;
 	unsigned short *z1t, *z2t;
 
 	if (!bcs->tx_skb)
@@ -584,24 +615,24 @@ hfcpci_fill_fifo(struct BCState *bcs)
 		z2t = z1t + 1;
 		if (cs->debug & L1_DEB_HSCX)
 			debugl1(cs, "hfcpci_fill_fifo_trans %d z1(%x) z2(%x)",
-				bcs->channel, le16_to_cpu(*z1t), le16_to_cpu(*z2t));
-		fcnt = le16_to_cpu(*z2t) - le16_to_cpu(*z1t);
+				bcs->channel, *z1t, *z2t);
+		fcnt = *z2t - *z1t;
 		if (fcnt <= 0)
 			fcnt += B_FIFO_SIZE;	/* fcnt contains available bytes in fifo */
 		fcnt = B_FIFO_SIZE - fcnt;	/* remaining bytes to send */
 
 		while ((fcnt < 2 * HFCPCI_BTRANS_THRESHOLD) && (bcs->tx_skb)) {
-			if ((int)bcs->tx_skb->len < (B_FIFO_SIZE - fcnt)) {
+			if (bcs->tx_skb->len < B_FIFO_SIZE - fcnt) {
 				/* data is suitable for fifo */
 				count = bcs->tx_skb->len;
 
-				new_z1 = le16_to_cpu(*z1t) + count;	/* new buffer Position */
+				new_z1 = *z1t + count;	/* new buffer Position */
 				if (new_z1 >= (B_FIFO_SIZE + B_SUB_VAL))
 					new_z1 -= B_FIFO_SIZE;	/* buffer wrap */
 				src = bcs->tx_skb->data;	/* source pointer */
-				dst = bdata + (le16_to_cpu(*z1t) - B_SUB_VAL);
-				maxlen = (B_FIFO_SIZE + B_SUB_VAL) - le16_to_cpu(*z1t);	/* end of fifo */
-				if (maxlen > (int)count)
+				dst = bdata + (*z1t - B_SUB_VAL);
+				maxlen = (B_FIFO_SIZE + B_SUB_VAL) - *z1t;	/* end of fifo */
+				if (maxlen > count)
 					maxlen = count;		/* limit size */
 				memcpy(dst, src, maxlen);	/* first copy */
 
@@ -613,11 +644,20 @@ hfcpci_fill_fifo(struct BCState *bcs)
 				}
 				bcs->tx_cnt -= bcs->tx_skb->len;
 				fcnt += bcs->tx_skb->len;
-				*z1t = cpu_to_le16(new_z1);	/* now send data */
+				*z1t = new_z1;	/* now send data */
 			} else if (cs->debug & L1_DEB_HSCX)
 				debugl1(cs, "hfcpci_fill_fifo_trans %d frame length %d discarded",
 					bcs->channel, bcs->tx_skb->len);
 
+			if (test_bit(FLG_LLI_L1WAKEUP,&bcs->st->lli.flag) &&
+				(PACKET_NOACK != bcs->tx_skb->pkt_type)) {
+				u_long	flags;
+				spin_lock_irqsave(&bcs->aclock, flags);
+				bcs->ackcnt += bcs->tx_skb->len;
+				spin_unlock_irqrestore(&bcs->aclock, flags);
+				schedule_event(bcs, B_ACKPENDING);
+			}
+
 			dev_kfree_skb_any(bcs->tx_skb);
 			bcs->tx_skb = skb_dequeue(&bcs->squeue);	/* fetch next data */
 		}
@@ -627,7 +667,7 @@ hfcpci_fill_fifo(struct BCState *bcs)
 	if (cs->debug & L1_DEB_HSCX)
 		debugl1(cs, "hfcpci_fill_fifo_hdlc %d f1(%d) f2(%d) z1(f1)(%x)",
 			bcs->channel, bz->f1, bz->f2,
-			le16_to_cpu(bz->za[bz->f1].z1));
+			bz->za[bz->f1].z1);
 
 	fcnt = bz->f1 - bz->f2;	/* frame count actually buffered */
 	if (fcnt < 0)
@@ -638,7 +678,7 @@ hfcpci_fill_fifo(struct BCState *bcs)
 		return;
 	}
 	/* now determine free bytes in FIFO buffer */
-	count = le16_to_cpu(bz->za[bz->f1].z2) - le16_to_cpu(bz->za[bz->f1].z1);
+	count = bz->za[bz->f2].z2 - bz->za[bz->f1].z1 - 1;
 	if (count <= 0)
 		count += B_FIFO_SIZE;	/* count now contains available bytes */
 
@@ -653,15 +693,15 @@ hfcpci_fill_fifo(struct BCState *bcs)
 		return;
 	}
 	count = bcs->tx_skb->len;	/* get frame len */
-	new_z1 = le16_to_cpu(bz->za[bz->f1].z1) + count;	/* new buffer Position */
+	new_z1 = bz->za[bz->f1].z1 + count;	/* new buffer Position */
 	if (new_z1 >= (B_FIFO_SIZE + B_SUB_VAL))
 		new_z1 -= B_FIFO_SIZE;	/* buffer wrap */
 
 	new_f1 = ((bz->f1 + 1) & MAX_B_FRAMES);
 	src = bcs->tx_skb->data;	/* source pointer */
-	dst = bdata + (le16_to_cpu(bz->za[bz->f1].z1) - B_SUB_VAL);
-	maxlen = (B_FIFO_SIZE + B_SUB_VAL) - le16_to_cpu(bz->za[bz->f1].z1);		/* end fifo */
-	if (maxlen > (int)count)
+	dst = bdata + (bz->za[bz->f1].z1 - B_SUB_VAL);
+	maxlen = (B_FIFO_SIZE + B_SUB_VAL) - bz->za[bz->f1].z1;		/* end fifo */
+	if (maxlen > count)
 		maxlen = count;	/* limit size */
 	memcpy(dst, src, maxlen);	/* first copy */
 
@@ -672,11 +712,20 @@ hfcpci_fill_fifo(struct BCState *bcs)
 		memcpy(dst, src, count);
 	}
 	bcs->tx_cnt -= bcs->tx_skb->len;
-	xmit_complete_b(bcs);
+	if (test_bit(FLG_LLI_L1WAKEUP,&bcs->st->lli.flag) &&
+		(PACKET_NOACK != bcs->tx_skb->pkt_type)) {
+		u_long	flags;
+		spin_lock_irqsave(&bcs->aclock, flags);
+		bcs->ackcnt += bcs->tx_skb->len;
+		spin_unlock_irqrestore(&bcs->aclock, flags);
+		schedule_event(bcs, B_ACKPENDING);
+	}
 
-	bz->za[new_f1].z1 = cpu_to_le16(new_z1);	/* for next buffer */
+	bz->za[new_f1].z1 = new_z1;	/* for next buffer */
 	bz->f1 = new_f1;	/* next frame */
 
+	dev_kfree_skb_any(bcs->tx_skb);
+	bcs->tx_skb = NULL;
 	test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
 	return;
 }
@@ -696,7 +745,7 @@ dch_nt_l2l1(struct PStack *st, int pr, v
 			st->l1.l1hw(st, pr, arg);
 			break;
 		case (PH_ACTIVATE | REQUEST):
-			L1L2(st, PH_ACTIVATE | CONFIRM, NULL);
+			st->l1.l1l2(st, PH_ACTIVATE | CONFIRM, NULL);
 			break;
 		case (PH_TESTLOOP | REQUEST):
 			if (1 & (long) arg)
@@ -722,10 +771,12 @@ dch_nt_l2l1(struct PStack *st, int pr, v
 static int
 hfcpci_auxcmd(struct IsdnCardState *cs, isdn_ctrl * ic)
 {
-	int i = *(unsigned int *) ic->parm.num;
+	u_long	flags;
+	int	i = *(unsigned int *) ic->parm.num;
 
 	if ((ic->arg == 98) &&
 	    (!(cs->hw.hfcpci.int_m1 & (HFCPCI_INTS_B2TRANS + HFCPCI_INTS_B2REC + HFCPCI_INTS_B1TRANS + HFCPCI_INTS_B1REC)))) {
+	    	spin_lock_irqsave(&cs->lock, flags);
 		Write_hfc(cs, HFCPCI_CLKDEL, CLKDEL_NT); /* ST-Bit delay for NT-Mode */
 		Write_hfc(cs, HFCPCI_STATES, HFCPCI_LOAD_STATE | 0);	/* HFC ST G0 */
 		udelay(10);
@@ -738,7 +789,8 @@ hfcpci_auxcmd(struct IsdnCardState *cs, 
 		cs->dc.hfcpci.ph_state = 1;
 		cs->hw.hfcpci.nt_mode = 1;
 		cs->hw.hfcpci.nt_timer = 0;
-		cs->stlist->l1.l2l1 = dch_nt_l2l1;
+		cs->stlist->l2.l2l1 = dch_nt_l2l1;
+		spin_unlock_irqrestore(&cs->lock, flags);
 		debugl1(cs, "NT mode activated");
 		return (0);
 	}
@@ -746,6 +798,7 @@ hfcpci_auxcmd(struct IsdnCardState *cs, 
 	    (cs->hw.hfcpci.nt_mode) || (ic->arg != 12))
 		return (-EINVAL);
 
+	spin_lock_irqsave(&cs->lock, flags);
 	if (i) {
 		cs->logecho = 1;
 		cs->hw.hfcpci.trm |= 0x20;	/* enable echo chan */
@@ -768,6 +821,7 @@ hfcpci_auxcmd(struct IsdnCardState *cs, 
 	Write_hfc(cs, HFCPCI_TRM, cs->hw.hfcpci.trm);
 	Write_hfc(cs, HFCPCI_FIFO_EN, cs->hw.hfcpci.fifo_en);
 	Write_hfc(cs, HFCPCI_INT_M1, cs->hw.hfcpci.int_m1);
+	spin_unlock_irqrestore(&cs->lock, flags);
 	return (0);
 }				/* hfcpci_auxcmd */
 
@@ -780,50 +834,54 @@ receive_emsg(struct IsdnCardState *cs)
 	int rcnt;
 	int receive, count = 5;
 	bzfifo_type *bz;
-	u8 *bdata;
+	u_char *bdata;
 	z_type *zp;
-	u8 *ptr, *ptr1, new_f2;
+	u_char *ptr, *ptr1, new_f2;
 	int total, maxlen, new_z2;
-	u8 e_buffer[256];
+	u_char e_buffer[256];
 
 	bz = &((fifo_area *) (cs->hw.hfcpci.fifos))->b_chans.rxbz_b2;
 	bdata = ((fifo_area *) (cs->hw.hfcpci.fifos))->b_chans.rxdat_b2;
       Begin:
 	count--;
+	if (test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) {
+		debugl1(cs, "echo_rec_data blocked");
+		return;
+	}
 	if (bz->f1 != bz->f2) {
 		if (cs->debug & L1_DEB_ISAC)
 			debugl1(cs, "hfcpci e_rec f1(%d) f2(%d)",
 				bz->f1, bz->f2);
 		zp = &bz->za[bz->f2];
 
-		rcnt = le16_to_cpu(zp->z1) - le16_to_cpu(zp->z2);
+		rcnt = zp->z1 - zp->z2;
 		if (rcnt < 0)
 			rcnt += B_FIFO_SIZE;
 		rcnt++;
 		if (cs->debug & L1_DEB_ISAC)
 			debugl1(cs, "hfcpci e_rec z1(%x) z2(%x) cnt(%d)",
-				le16_to_cpu(zp->z1), le16_to_cpu(zp->z2), rcnt);
-		new_z2 = le16_to_cpu(zp->z2) + rcnt;		/* new position in fifo */
+				zp->z1, zp->z2, rcnt);
+		new_z2 = zp->z2 + rcnt;		/* new position in fifo */
 		if (new_z2 >= (B_FIFO_SIZE + B_SUB_VAL))
 			new_z2 -= B_FIFO_SIZE;	/* buffer wrap */
 		new_f2 = (bz->f2 + 1) & MAX_B_FRAMES;
 		if ((rcnt > 256 + 3) || (count < 4) ||
-		    (*(bdata + (le16_to_cpu(zp->z1) - B_SUB_VAL)))) {
+		    (*(bdata + (zp->z1 - B_SUB_VAL)))) {
 			if (cs->debug & L1_DEB_WARN)
 				debugl1(cs, "hfcpci_empty_echan: incoming packet invalid length %d or crc", rcnt);
-			bz->za[new_f2].z2 = cpu_to_le16(new_z2);
+			bz->za[new_f2].z2 = new_z2;
 			bz->f2 = new_f2;	/* next buffer */
 		} else {
 			total = rcnt;
 			rcnt -= 3;
 			ptr = e_buffer;
 
-			if (le16_to_cpu(zp->z2) <= (B_FIFO_SIZE + B_SUB_VAL))
+			if (zp->z2 <= B_FIFO_SIZE + B_SUB_VAL)
 				maxlen = rcnt;	/* complete transfer */
 			else
-				maxlen = B_FIFO_SIZE + B_SUB_VAL - le16_to_cpu(zp->z2);	/* maximum */
+				maxlen = B_FIFO_SIZE + B_SUB_VAL - zp->z2;	/* maximum */
 
-			ptr1 = bdata + (le16_to_cpu(zp->z2) - B_SUB_VAL);	/* start of data */
+			ptr1 = bdata + (zp->z2 - B_SUB_VAL);	/* start of data */
 			memcpy(ptr, ptr1, maxlen);	/* copy data */
 			rcnt -= maxlen;
 
@@ -832,7 +890,7 @@ receive_emsg(struct IsdnCardState *cs)
 				ptr1 = bdata;	/* start of buffer */
 				memcpy(ptr, ptr1, rcnt);	/* rest */
 			}
-			bz->za[new_f2].z2 = cpu_to_le16(new_z2);
+			bz->za[new_f2].z2 = new_z2;
 			bz->f2 = new_f2;	/* next buffer */
 			if (cs->debug & DEB_DLOG_HEX) {
 				ptr = cs->dlog;
@@ -861,6 +919,7 @@ receive_emsg(struct IsdnCardState *cs)
 			receive = 0;
 	} else
 		receive = 0;
+	test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);
 	if (count && receive)
 		goto Begin;
 	return;
@@ -872,28 +931,30 @@ receive_emsg(struct IsdnCardState *cs)
 static irqreturn_t
 hfcpci_interrupt(int intno, void *dev_id, struct pt_regs *regs)
 {
+	u_long flags;
 	struct IsdnCardState *cs = dev_id;
-	u8 exval;
+	u_char exval;
 	struct BCState *bcs;
 	int count = 15;
-	u8 val, stat;
+	u_char val, stat;
 
-	if (!cs) {
-		printk(KERN_WARNING "HFC-PCI: Spurious interrupt!\n");
-		return IRQ_NONE;
+	if (!(cs->hw.hfcpci.int_m2 & 0x08)) {
+		debugl1(cs, "HFC-PCI: int_m2 %x not initialised", cs->hw.hfcpci.int_m2);
+		return IRQ_NONE;	/* not initialised */
 	}
-	if (!(cs->hw.hfcpci.int_m2 & 0x08))
-		return IRQ_NONE;		/* not initialised */
-
+	spin_lock_irqsave(&cs->lock, flags);
 	if (HFCPCI_ANYINT & (stat = Read_hfc(cs, HFCPCI_STATUS))) {
 		val = Read_hfc(cs, HFCPCI_INT_S1);
 		if (cs->debug & L1_DEB_ISAC)
 			debugl1(cs, "HFC-PCI: stat(%02x) s1(%02x)", stat, val);
-	} else
+	} else {
+		spin_unlock_irqrestore(&cs->lock, flags);
 		return IRQ_NONE;
-
+	}
 	if (cs->debug & L1_DEB_ISAC)
-		debugl1(cs, "HFC-PCI irq %x", val);
+		debugl1(cs, "HFC-PCI irq %x %s", val,
+			test_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags) ?
+			"locked" : "unlocked");
 	val &= cs->hw.hfcpci.int_m1;
 	if (val & 0x40) {	/* state machine irq */
 		exval = Read_hfc(cs, HFCPCI_STATES) & 0xf;
@@ -901,18 +962,23 @@ hfcpci_interrupt(int intno, void *dev_id
 			debugl1(cs, "ph_state chg %d->%d", cs->dc.hfcpci.ph_state,
 				exval);
 		cs->dc.hfcpci.ph_state = exval;
-		sched_d_event(cs, D_L1STATECHANGE);
+		sched_event_D_pci(cs, D_L1STATECHANGE);
 		val &= ~0x40;
 	}
 	if (val & 0x80) {	/* timer irq */
 		if (cs->hw.hfcpci.nt_mode) {
 			if ((--cs->hw.hfcpci.nt_timer) < 0)
-				sched_d_event(cs, D_L1STATECHANGE);
+				sched_event_D_pci(cs, D_L1STATECHANGE);
 		}
 		val &= ~0x80;
 		Write_hfc(cs, HFCPCI_CTMT, cs->hw.hfcpci.ctmt | HFCPCI_CLTIMER);
 	}
 	while (val) {
+		if (test_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) {
+			cs->hw.hfcpci.int_s1 |= val;
+			spin_unlock_irqrestore(&cs->lock, flags);
+			return IRQ_HANDLED;
+		}
 		if (cs->hw.hfcpci.int_s1 & 0x18) {
 			exval = val;
 			val = cs->hw.hfcpci.int_s1;
@@ -939,7 +1005,23 @@ hfcpci_interrupt(int intno, void *dev_id
 				if (cs->debug)
 					debugl1(cs, "hfcpci spurious 0x01 IRQ");
 			} else {
-				xmit_xpr_b(bcs);
+				if (bcs->tx_skb) {
+					if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) {
+						hfcpci_fill_fifo(bcs);
+						test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);
+					} else
+						debugl1(cs, "fill_data %d blocked", bcs->channel);
+				} else {
+					if ((bcs->tx_skb = skb_dequeue(&bcs->squeue))) {
+						if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) {
+							hfcpci_fill_fifo(bcs);
+							test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);
+						} else
+							debugl1(cs, "fill_data %d blocked", bcs->channel);
+					} else {
+						hfcpci_sched_event(bcs, B_XMTBUFREADY);
+					}
+				}
 			}
 		}
 		if (val & 0x02) {
@@ -947,15 +1029,60 @@ hfcpci_interrupt(int intno, void *dev_id
 				if (cs->debug)
 					debugl1(cs, "hfcpci spurious 0x02 IRQ");
 			} else {
-				xmit_xpr_b(bcs);
+				if (bcs->tx_skb) {
+					if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) {
+						hfcpci_fill_fifo(bcs);
+						test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);
+					} else
+						debugl1(cs, "fill_data %d blocked", bcs->channel);
+				} else {
+					if ((bcs->tx_skb = skb_dequeue(&bcs->squeue))) {
+						if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) {
+							hfcpci_fill_fifo(bcs);
+							test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);
+						} else
+							debugl1(cs, "fill_data %d blocked", bcs->channel);
+					} else {
+						hfcpci_sched_event(bcs, B_XMTBUFREADY);
+					}
+				}
 			}
 		}
 		if (val & 0x20) {	/* receive dframe */
 			receive_dmsg(cs);
 		}
 		if (val & 0x04) {	/* dframe transmitted */
-			xmit_xpr_d(cs);
+			if (test_and_clear_bit(FLG_DBUSY_TIMER, &cs->HW_Flags))
+				del_timer(&cs->dbusytimer);
+			if (test_and_clear_bit(FLG_L1_DBUSY, &cs->HW_Flags))
+				sched_event_D_pci(cs, D_CLEARBUSY);
+			if (cs->tx_skb) {
+				if (cs->tx_skb->len) {
+					if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) {
+						hfcpci_fill_dfifo(cs);
+						test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);
+					} else {
+						debugl1(cs, "hfcpci_fill_dfifo irq blocked");
+					}
+					goto afterXPR;
+				} else {
+					dev_kfree_skb_irq(cs->tx_skb);
+					cs->tx_cnt = 0;
+					cs->tx_skb = NULL;
+				}
+			}
+			if ((cs->tx_skb = skb_dequeue(&cs->sq))) {
+				cs->tx_cnt = 0;
+				if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) {
+					hfcpci_fill_dfifo(cs);
+					test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);
+				} else {
+					debugl1(cs, "hfcpci_fill_dfifo irq blocked");
+				}
+			} else
+				sched_event_D_pci(cs, D_XMTBUFREADY);
 		}
+	      afterXPR:
 		if (cs->hw.hfcpci.int_s1 && count--) {
 			val = cs->hw.hfcpci.int_s1;
 			cs->hw.hfcpci.int_s1 = 0;
@@ -964,6 +1091,7 @@ hfcpci_interrupt(int intno, void *dev_id
 		} else
 			val = 0;
 	}
+	spin_unlock_irqrestore(&cs->lock, flags);
 	return IRQ_HANDLED;
 }
 
@@ -981,40 +1109,106 @@ hfcpci_dbusy_timer(struct IsdnCardState 
 static void
 HFCPCI_l1hw(struct PStack *st, int pr, void *arg)
 {
+	u_long flags;
 	struct IsdnCardState *cs = (struct IsdnCardState *) st->l1.hardware;
 	struct sk_buff *skb = arg;
 
 	switch (pr) {
 		case (PH_DATA | REQUEST):
-			xmit_data_req_d(cs, skb);
+			if (cs->debug & DEB_DLOG_HEX)
+				LogFrame(cs, skb->data, skb->len);
+			if (cs->debug & DEB_DLOG_VERBOSE)
+				dlogframe(cs, skb, 0);
+			spin_lock_irqsave(&cs->lock, flags);
+			if (cs->tx_skb) {
+				skb_queue_tail(&cs->sq, skb);
+#ifdef L2FRAME_DEBUG		/* psa */
+				if (cs->debug & L1_DEB_LAPD)
+					Logl2Frame(cs, skb, "PH_DATA Queued", 0);
+#endif
+			} else {
+				cs->tx_skb = skb;
+				cs->tx_cnt = 0;
+#ifdef L2FRAME_DEBUG		/* psa */
+				if (cs->debug & L1_DEB_LAPD)
+					Logl2Frame(cs, skb, "PH_DATA", 0);
+#endif
+				if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) {
+					hfcpci_fill_dfifo(cs);
+					test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);
+				} else
+					debugl1(cs, "hfcpci_fill_dfifo blocked");
+
+			}
+			spin_unlock_irqrestore(&cs->lock, flags);
 			break;
 		case (PH_PULL | INDICATION):
-			xmit_pull_ind_d(cs, skb);
+			spin_lock_irqsave(&cs->lock, flags);
+			if (cs->tx_skb) {
+				if (cs->debug & L1_DEB_WARN)
+					debugl1(cs, " l2l1 tx_skb exist this shouldn't happen");
+				skb_queue_tail(&cs->sq, skb);
+				spin_unlock_irqrestore(&cs->lock, flags);
+				break;
+			}
+			if (cs->debug & DEB_DLOG_HEX)
+				LogFrame(cs, skb->data, skb->len);
+			if (cs->debug & DEB_DLOG_VERBOSE)
+				dlogframe(cs, skb, 0);
+			cs->tx_skb = skb;
+			cs->tx_cnt = 0;
+#ifdef L2FRAME_DEBUG		/* psa */
+			if (cs->debug & L1_DEB_LAPD)
+				Logl2Frame(cs, skb, "PH_DATA_PULLED", 0);
+#endif
+			if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) {
+				hfcpci_fill_dfifo(cs);
+				test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);
+			} else
+				debugl1(cs, "hfcpci_fill_dfifo blocked");
+			spin_unlock_irqrestore(&cs->lock, flags);
 			break;
 		case (PH_PULL | REQUEST):
-			xmit_pull_req_d(st);
+#ifdef L2FRAME_DEBUG		/* psa */
+			if (cs->debug & L1_DEB_LAPD)
+				debugl1(cs, "-> PH_REQUEST_PULL");
+#endif
+			if (!cs->tx_skb) {
+				test_and_clear_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
+				st->l1.l1l2(st, PH_PULL | CONFIRM, NULL);
+			} else
+				test_and_set_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
 			break;
 		case (HW_RESET | REQUEST):
+			spin_lock_irqsave(&cs->lock, flags);
 			Write_hfc(cs, HFCPCI_STATES, HFCPCI_LOAD_STATE | 3);	/* HFC ST 3 */
 			udelay(6);
 			Write_hfc(cs, HFCPCI_STATES, 3);	/* HFC ST 2 */
 			cs->hw.hfcpci.mst_m |= HFCPCI_MASTER;
 			Write_hfc(cs, HFCPCI_MST_MODE, cs->hw.hfcpci.mst_m);
 			Write_hfc(cs, HFCPCI_STATES, HFCPCI_ACTIVATE | HFCPCI_DO_ACTION);
+			spin_unlock_irqrestore(&cs->lock, flags);
 			l1_msg(cs, HW_POWERUP | CONFIRM, NULL);
 			break;
 		case (HW_ENABLE | REQUEST):
+			spin_lock_irqsave(&cs->lock, flags);
 			Write_hfc(cs, HFCPCI_STATES, HFCPCI_DO_ACTION);
+			spin_unlock_irqrestore(&cs->lock, flags);
 			break;
 		case (HW_DEACTIVATE | REQUEST):
+			spin_lock_irqsave(&cs->lock, flags);
 			cs->hw.hfcpci.mst_m &= ~HFCPCI_MASTER;
 			Write_hfc(cs, HFCPCI_MST_MODE, cs->hw.hfcpci.mst_m);
+			spin_unlock_irqrestore(&cs->lock, flags);
 			break;
 		case (HW_INFO3 | REQUEST):
+			spin_lock_irqsave(&cs->lock, flags);
 			cs->hw.hfcpci.mst_m |= HFCPCI_MASTER;
 			Write_hfc(cs, HFCPCI_MST_MODE, cs->hw.hfcpci.mst_m);
+			spin_unlock_irqrestore(&cs->lock, flags);
 			break;
 		case (HW_TESTLOOP | REQUEST):
+			spin_lock_irqsave(&cs->lock, flags);
 			switch ((int) arg) {
 				case (1):
 					Write_hfc(cs, HFCPCI_B1_SSL, 0x80);	/* tx slot */
@@ -1031,12 +1225,14 @@ HFCPCI_l1hw(struct PStack *st, int pr, v
 					break;
 
 				default:
+					spin_unlock_irqrestore(&cs->lock, flags);
 					if (cs->debug & L1_DEB_WARN)
 						debugl1(cs, "hfcpci_l1hw loop invalid %4x", (int) arg);
 					return;
 			}
 			cs->hw.hfcpci.trm |= 0x80;	/* enable IOM-loop */
 			Write_hfc(cs, HFCPCI_TRM, cs->hw.hfcpci.trm);
+			spin_unlock_irqrestore(&cs->lock, flags);
 			break;
 		default:
 			if (cs->debug & L1_DEB_WARN)
@@ -1048,11 +1244,25 @@ HFCPCI_l1hw(struct PStack *st, int pr, v
 /***********************************************/
 /* called during init setting l1 stack pointer */
 /***********************************************/
-static int
+void
 setstack_hfcpci(struct PStack *st, struct IsdnCardState *cs)
 {
 	st->l1.l1hw = HFCPCI_l1hw;
-	return 0;
+}
+
+/**************************************/
+/* send B-channel data if not blocked */
+/**************************************/
+static void
+hfcpci_send_data(struct BCState *bcs)
+{
+	struct IsdnCardState *cs = bcs->cs;
+
+	if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) {
+		hfcpci_fill_fifo(bcs);
+		test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);
+	} else
+		debugl1(cs, "send_data %d blocked", bcs->channel);
 }
 
 /***************************************************************/
@@ -1182,31 +1392,58 @@ mode_hfcpci(struct BCState *bcs, int mod
 static void
 hfcpci_l2l1(struct PStack *st, int pr, void *arg)
 {
-	struct sk_buff *skb = arg;
+	struct BCState	*bcs = st->l1.bcs;
+	u_long		flags;
+	struct sk_buff	*skb = arg;
 
 	switch (pr) {
 		case (PH_DATA | REQUEST):
-			xmit_data_req_b(st->l1.bcs, skb);
+			spin_lock_irqsave(&bcs->cs->lock, flags);
+			if (bcs->tx_skb) {
+				skb_queue_tail(&bcs->squeue, skb);
+			} else {
+				bcs->tx_skb = skb;
+//				test_and_set_bit(BC_FLG_BUSY, &bcs->Flag);
+ 				bcs->cs->BC_Send_Data(bcs);
+			}
+			spin_unlock_irqrestore(&bcs->cs->lock, flags);
 			break;
 		case (PH_PULL | INDICATION):
-			xmit_pull_ind_b(st->l1.bcs, skb);
+			spin_lock_irqsave(&bcs->cs->lock, flags);
+			if (bcs->tx_skb) {
+				spin_unlock_irqrestore(&bcs->cs->lock, flags);
+				printk(KERN_WARNING "hfc_l2l1: this shouldn't happen\n");
+				break;
+			}
+//			test_and_set_bit(BC_FLG_BUSY, &bcs->Flag);
+			bcs->tx_skb = skb;
+			bcs->cs->BC_Send_Data(bcs);
+			spin_unlock_irqrestore(&bcs->cs->lock, flags);
 			break;
 		case (PH_PULL | REQUEST):
-			xmit_pull_req_b(st);
+			if (!bcs->tx_skb) {
+				test_and_clear_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
+				st->l1.l1l2(st, PH_PULL | CONFIRM, NULL);
+			} else
+				test_and_set_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
 			break;
 		case (PH_ACTIVATE | REQUEST):
-			test_and_set_bit(BC_FLG_ACTIV, &st->l1.bcs->Flag);
-			mode_hfcpci(st->l1.bcs, st->l1.mode, st->l1.bc);
+			spin_lock_irqsave(&bcs->cs->lock, flags);
+			test_and_set_bit(BC_FLG_ACTIV, &bcs->Flag);
+			mode_hfcpci(bcs, st->l1.mode, st->l1.bc);
+			spin_unlock_irqrestore(&bcs->cs->lock, flags);
 			l1_msg_b(st, pr, arg);
 			break;
 		case (PH_DEACTIVATE | REQUEST):
 			l1_msg_b(st, pr, arg);
 			break;
 		case (PH_DEACTIVATE | CONFIRM):
-			test_and_clear_bit(BC_FLG_ACTIV, &st->l1.bcs->Flag);
-			test_and_clear_bit(BC_FLG_BUSY, &st->l1.bcs->Flag);
-			mode_hfcpci(st->l1.bcs, 0, st->l1.bc);
-			L1L2(st, PH_DEACTIVATE | CONFIRM, NULL);
+			spin_lock_irqsave(&bcs->cs->lock, flags);
+			test_and_clear_bit(BC_FLG_ACTIV, &bcs->Flag);
+			test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
+			mode_hfcpci(bcs, 0, st->l1.bc);
+			spin_unlock_irqrestore(&bcs->cs->lock, flags);
+			st->l1.l1l2(st, PH_DEACTIVATE | CONFIRM, NULL);
 			break;
 	}
 }
@@ -1256,7 +1493,7 @@ setstack_2b(struct PStack *st, struct BC
 	if (open_hfcpcistate(st->l1.hardware, bcs))
 		return (-1);
 	st->l1.bcs = bcs;
-	st->l1.l2l1 = hfcpci_l2l1;
+	st->l2.l2l1 = hfcpci_l2l1;
 	setstack_manager(st);
 	bcs->st = st;
 	setstack_l1_B(st);
@@ -1267,11 +1504,11 @@ setstack_2b(struct PStack *st, struct BC
 /* handle L1 state changes */
 /***************************/
 static void
-hfcpci_bh(void *data)
+hfcpci_bh(struct IsdnCardState *cs)
 {
-	struct IsdnCardState *cs = data;
-/*      struct PStack *stptr;
- */
+	u_long	flags;
+//      struct PStack *stptr;
+
 	if (!cs)
 		return;
 	if (test_and_clear_bit(D_L1STATECHANGE, &cs->event)) {
@@ -1295,6 +1532,7 @@ hfcpci_bh(void *data)
 				default:
 					break;
 		} else {
+			spin_lock_irqsave(&cs->lock, flags);
 			switch (cs->dc.hfcpci.ph_state) {
 				case (2):
 					if (cs->hw.hfcpci.nt_timer < 0) {
@@ -1303,7 +1541,6 @@ hfcpci_bh(void *data)
 						Write_hfc(cs, HFCPCI_INT_M1, cs->hw.hfcpci.int_m1);
 						/* Clear already pending ints */
 						if (Read_hfc(cs, HFCPCI_INT_S1));
-
 						Write_hfc(cs, HFCPCI_STATES, 4 | HFCPCI_LOAD_STATE);
 						udelay(10);
 						Write_hfc(cs, HFCPCI_STATES, 4);
@@ -1329,6 +1566,7 @@ hfcpci_bh(void *data)
 				default:
 					break;
 			}
+			spin_unlock_irqrestore(&cs->lock, flags);
 		}
 	}
 	if (test_and_clear_bit(D_RCVBUFREADY, &cs->event))
@@ -1337,18 +1575,6 @@ hfcpci_bh(void *data)
 		DChannel_proc_xmt(cs);
 }
 
-static struct bc_l1_ops hfcpci_bc_l1_ops = {
-	.fill_fifo = hfcpci_fill_fifo,
-	.open      = setstack_2b,
-	.close     = close_hfcpci,
-};
-
-static struct dc_l1_ops hfcpci_dc_l1_ops = {
-	.fill_fifo  = hfcpci_fill_dfifo,
-	.open       = setstack_hfcpci,
-	.bh_func    = hfcpci_bh,
-	.dbusy_func = hfcpci_dbusy_timer,
-};
 
 /********************************/
 /* called for card init message */
@@ -1356,116 +1582,167 @@ static struct dc_l1_ops hfcpci_dc_l1_ops
 void __init
 inithfcpci(struct IsdnCardState *cs)
 {
-	dc_l1_init(cs, &hfcpci_dc_l1_ops);
-	cs->bc_l1_ops = &hfcpci_bc_l1_ops;
+	cs->bcs[0].BC_SetStack = setstack_2b;
+	cs->bcs[1].BC_SetStack = setstack_2b;
+	cs->bcs[0].BC_Close = close_hfcpci;
+	cs->bcs[1].BC_Close = close_hfcpci;
+	cs->dbusytimer.function = (void *) hfcpci_dbusy_timer;
+	cs->dbusytimer.data = (long) cs;
+	init_timer(&cs->dbusytimer);
 	mode_hfcpci(cs->bcs, 0, 0);
 	mode_hfcpci(cs->bcs + 1, 0, 1);
 }
 
-static void
-hfcpci_init(struct IsdnCardState *cs)
-{
-	inithfcpci(cs);
-	set_current_state(TASK_UNINTERRUPTIBLE);
-	schedule_timeout((80 * HZ) / 1000);	/* Timeout 80ms */
-	/* now switch timer interrupt off */
-	cs->hw.hfcpci.int_m1 &= ~HFCPCI_INTS_TIMER;
-	Write_hfc(cs, HFCPCI_INT_M1, cs->hw.hfcpci.int_m1);
-	/* reinit mode reg */
-	Write_hfc(cs, HFCPCI_MST_MODE, cs->hw.hfcpci.mst_m);
-}
 
-static struct card_ops hfcpci_ops = {
-	.init     = hfcpci_init,
-	.reset    = hfcpci_reset,
-	.release  = hfcpci_release,
-	.irq_func = hfcpci_interrupt,
-};
 
-
-static int __init
-niccy_pci_probe(struct IsdnCardState *cs, struct pci_dev *pdev, int i)
+/*******************************************/
+/* handle card messages from control layer */
+/*******************************************/
+static int
+hfcpci_card_msg(struct IsdnCardState *cs, int mt, void *arg)
 {
-	int rc;
-
-	rc = -EBUSY;
-	if (pci_enable_device(pdev))
-		goto err;
-
-	pci_set_master(pdev);
-
-	cs->irq = pdev->irq;
-	cs->irq_flags |= SA_SHIRQ;
-	cs->hw.hfcpci.pdev = pdev;
-
-	cs->hw.hfcpci.pci_io = request_mmio(&cs->rs, 
-					    pci_resource_start(pdev, 1), 128,
-					    "hfc_pci");
-	if (!cs->hw.hfcpci.pci_io)
-		goto err;
-	
-	/* Allocate memory for FIFOS */
-	rc = -ENOMEM;
-	cs->hw.hfcpci.fifos = pci_alloc_consistent(pdev, 32768, 
-						   &cs->hw.hfcpci.fifos_dma);
-	if (!cs->hw.hfcpci.fifos)
-		goto err;
-
-	pci_write_config_dword(cs->hw.hfcpci.pdev, 0x80,
-			       (u_int)cs->hw.hfcpci.fifos_dma);
-	printk(KERN_INFO "HiSax: HFC-PCI card manufacturer: %s name: %s\n",
-	       id_list[i].vendor_name, id_list[i].card_name);
-	printk(KERN_INFO "HFC-PCI: defined at mem %#x fifo %#x(%#x) IRQ %d\n",
-	       (u_int) cs->hw.hfcpci.pci_io, (u_int) cs->hw.hfcpci.fifos,
-	       (u_int) cs->hw.hfcpci.fifos_dma, cs->irq);
-	printk("ChipID: %x\n", Read_hfc(cs, HFCPCI_CHIP_ID));
-	cs->hw.hfcpci.int_m2 = 0;	/* disable alle interrupts */
-	cs->hw.hfcpci.int_m1 = 0;
-	Write_hfc(cs, HFCPCI_INT_M1, cs->hw.hfcpci.int_m1);
-	Write_hfc(cs, HFCPCI_INT_M2, cs->hw.hfcpci.int_m2);
-	/* At this point the needed PCI config is done */
-	/* fifos are still not enabled */
+	u_long flags;
 
-	init_timer(&cs->hw.hfcpci.timer);
-	cs->hw.hfcpci.timer.function = (void *) hfcpci_Timer;
-	cs->hw.hfcpci.timer.data = (long) cs;
-
-	hfcpci_reset(cs);
-	cs->auxcmd = &hfcpci_auxcmd;
-	cs->card_ops = &hfcpci_ops;
-	return 0;
- err:
-	hisax_release_resources(cs);
-	return -EBUSY;
+	if (cs->debug & L1_DEB_ISAC)
+		debugl1(cs, "HFCPCI: card_msg %x", mt);
+	switch (mt) {
+		case CARD_RESET:
+			spin_lock_irqsave(&cs->lock, flags);
+			reset_hfcpci(cs);
+			spin_unlock_irqrestore(&cs->lock, flags);
+			return (0);
+		case CARD_RELEASE:
+			release_io_hfcpci(cs);
+			return (0);
+		case CARD_INIT:
+			spin_lock_irqsave(&cs->lock, flags);
+			inithfcpci(cs);
+			reset_hfcpci(cs);
+			spin_unlock_irqrestore(&cs->lock, flags);
+			set_current_state(TASK_UNINTERRUPTIBLE);
+			schedule_timeout((80 * HZ) / 1000);	/* Timeout 80ms */
+			/* now switch timer interrupt off */
+			spin_lock_irqsave(&cs->lock, flags);
+			cs->hw.hfcpci.int_m1 &= ~HFCPCI_INTS_TIMER;
+			Write_hfc(cs, HFCPCI_INT_M1, cs->hw.hfcpci.int_m1);
+			/* reinit mode reg */
+			Write_hfc(cs, HFCPCI_MST_MODE, cs->hw.hfcpci.mst_m);
+			spin_unlock_irqrestore(&cs->lock, flags);
+			return (0);
+		case CARD_TEST:
+			return (0);
+	}
+	return (0);
 }
 
+
 /* this variable is used as card index when more than one cards are present */
 static struct pci_dev *dev_hfcpci __initdata = NULL;
 
+#endif				/* CONFIG_PCI */
+
 int __init
 setup_hfcpci(struct IsdnCard *card)
 {
+	u_long flags;
 	struct IsdnCardState *cs = card->cs;
 	char tmp[64];
 	int i;
 	struct pci_dev *tmp_hfcpci = NULL;
 
+#ifdef __BIG_ENDIAN
+#error "not running on big endian machines now"
+#endif
 	strcpy(tmp, hfcpci_revision);
 	printk(KERN_INFO "HiSax: HFC-PCI driver Rev. %s\n", HiSax_getrev(tmp));
+#if CONFIG_PCI
 	cs->hw.hfcpci.int_s1 = 0;
 	cs->dc.hfcpci.ph_state = 0;
 	cs->hw.hfcpci.fifo = 255;
+	if (cs->typ == ISDN_CTYPE_HFC_PCI) {
+		i = 0;
+		while (id_list[i].vendor_id) {
+			tmp_hfcpci = pci_find_device(id_list[i].vendor_id,
+						     id_list[i].device_id,
+						     dev_hfcpci);
+			i++;
+			if (tmp_hfcpci) {
+				if (pci_enable_device(tmp_hfcpci))
+					continue;
+				pci_set_master(tmp_hfcpci);
+				if ((card->para[0]) && (card->para[0] != (tmp_hfcpci->resource[ 0].start & PCI_BASE_ADDRESS_IO_MASK)))
+					continue;
+				else
+					break;
+			}
+		}
 
-	for (i = 0; id_list[i].vendor_id; i++) {
-		tmp_hfcpci = pci_find_device(id_list[i].vendor_id,
-					     id_list[i].device_id,
-					     dev_hfcpci);
-		if (!tmp_hfcpci)
-			continue;
-
-		if (niccy_pci_probe(card->cs, tmp_hfcpci, i) < 0)
+		if (tmp_hfcpci) {
+			i--;
+			dev_hfcpci = tmp_hfcpci;	/* old device */
+			cs->hw.hfcpci.dev = dev_hfcpci;
+			cs->irq = dev_hfcpci->irq;
+			if (!cs->irq) {
+				printk(KERN_WARNING "HFC-PCI: No IRQ for PCI card found\n");
+				return (0);
+			}
+			cs->hw.hfcpci.pci_io = (char *) dev_hfcpci->resource[ 1].start;
+			printk(KERN_INFO "HiSax: HFC-PCI card manufacturer: %s card name: %s\n", id_list[i].vendor_name, id_list[i].card_name);
+		} else {
+			printk(KERN_WARNING "HFC-PCI: No PCI card found\n");
+			return (0);
+		}
+		if (!cs->hw.hfcpci.pci_io) {
+			printk(KERN_WARNING "HFC-PCI: No IO-Mem for PCI card found\n");
+			return (0);
+		}
+		/* Allocate memory for FIFOS */
+		/* Because the HFC-PCI needs a 32K physical alignment, we */
+		/* need to allocate the double mem and align the address */
+		if (!(cs->hw.hfcpci.share_start = kmalloc(65536, GFP_KERNEL))) {
+			printk(KERN_WARNING "HFC-PCI: Error allocating memory for FIFO!\n");
 			return 0;
-		return 1;
-	}
-	return 0;
+		}
+		cs->hw.hfcpci.fifos = (void *)
+		    (((ulong) cs->hw.hfcpci.share_start) & ~0x7FFF) + 0x8000;
+		pci_write_config_dword(cs->hw.hfcpci.dev, 0x80, (u_int) virt_to_bus(cs->hw.hfcpci.fifos));
+		cs->hw.hfcpci.pci_io = ioremap((ulong) cs->hw.hfcpci.pci_io, 256);
+		printk(KERN_INFO
+		       "HFC-PCI: defined at mem %#x fifo %#x(%#x) IRQ %d HZ %d\n",
+		       (u_int) cs->hw.hfcpci.pci_io,
+		       (u_int) cs->hw.hfcpci.fifos,
+		       (u_int) virt_to_bus(cs->hw.hfcpci.fifos),
+		       cs->irq, HZ);
+		spin_lock_irqsave(&cs->lock, flags);
+		pci_write_config_word(cs->hw.hfcpci.dev, PCI_COMMAND, PCI_ENA_MEMIO);	/* enable memory mapped ports, disable busmaster */
+		cs->hw.hfcpci.int_m2 = 0;	/* disable alle interrupts */
+		cs->hw.hfcpci.int_m1 = 0;
+		Write_hfc(cs, HFCPCI_INT_M1, cs->hw.hfcpci.int_m1);
+		Write_hfc(cs, HFCPCI_INT_M2, cs->hw.hfcpci.int_m2);
+		/* At this point the needed PCI config is done */
+		/* fifos are still not enabled */
+		INIT_WORK(&cs->tqueue, (void *)(void *) hfcpci_bh, cs);
+		cs->setstack_d = setstack_hfcpci;
+		cs->BC_Send_Data = &hfcpci_send_data;
+		cs->readisac = NULL;
+		cs->writeisac = NULL;
+		cs->readisacfifo = NULL;
+		cs->writeisacfifo = NULL;
+		cs->BC_Read_Reg = NULL;
+		cs->BC_Write_Reg = NULL;
+		cs->irq_func = &hfcpci_interrupt;
+		cs->irq_flags |= SA_SHIRQ;
+		cs->hw.hfcpci.timer.function = (void *) hfcpci_Timer;
+		cs->hw.hfcpci.timer.data = (long) cs;
+		init_timer(&cs->hw.hfcpci.timer);
+		cs->cardmsg = &hfcpci_card_msg;
+		cs->auxcmd = &hfcpci_auxcmd;
+		spin_unlock_irqrestore(&cs->lock, flags);
+		return (1);
+	} else
+		return (0);	/* no valid card type */
+#else
+	printk(KERN_WARNING "HFC-PCI: NO_PCI_BIOS\n");
+	return (0);
+#endif				/* CONFIG_PCI */
 }
--- diff/drivers/isdn/hisax/hfc_pci.h	2003-01-13 14:18:15.000000000 +0000
+++ source/drivers/isdn/hisax/hfc_pci.h	2004-02-23 13:56:42.000000000 +0000
@@ -1,4 +1,4 @@
-/* $Id: hfc_pci.h,v 1.8.6.2 2001/09/23 22:24:48 kai Exp $
+/* $Id: hfc_pci.h,v 1.10.2.2 2004/01/12 22:52:26 keil Exp $
  *
  * specific defines for CCD's HFC 2BDS0 PCI chips
  *
@@ -185,53 +185,51 @@
 typedef struct {
     unsigned short z1;  /* Z1 pointer 16 Bit */
     unsigned short z2;  /* Z2 pointer 16 Bit */
-  } __attribute__((packed)) z_type;
+  } z_type;
 
 typedef struct {
-    u8 data[D_FIFO_SIZE]; /* FIFO data space */
-    u8 fill1[0x20A0-D_FIFO_SIZE]; /* reserved, do not use */
-    u8 f1,f2; /* f pointers */
-    u8 fill2[0x20C0-0x20A2]; /* reserved, do not use */
+    u_char data[D_FIFO_SIZE]; /* FIFO data space */
+    u_char fill1[0x20A0-D_FIFO_SIZE]; /* reserved, do not use */
+    u_char f1,f2; /* f pointers */
+    u_char fill2[0x20C0-0x20A2]; /* reserved, do not use */
     z_type za[MAX_D_FRAMES+1]; /* mask index with D_FREG_MASK for access */
-    u8 fill3[0x4000-0x2100]; /* align 16K */  
-  } __attribute__((packed)) dfifo_type;
+    u_char fill3[0x4000-0x2100]; /* align 16K */  
+  } dfifo_type;
 
 typedef struct {
     z_type za[MAX_B_FRAMES+1]; /* only range 0x0..0x1F allowed */ 
-    u8 f1,f2; /* f pointers */
-    u8 fill[0x2100-0x2082]; /* alignment */
-  } __attribute__((packed)) bzfifo_type;
+    u_char f1,f2; /* f pointers */
+    u_char fill[0x2100-0x2082]; /* alignment */
+  } bzfifo_type;
 
 
 typedef union {
     struct { 
       dfifo_type d_tx; /* D-send channel */
       dfifo_type d_rx; /* D-receive channel */
-    } __attribute__((packed)) d_chan; 
+    } d_chan; 
     struct {
-      u8 fill1[0x200];
-      u8 txdat_b1[B_FIFO_SIZE];
+      u_char fill1[0x200];
+      u_char txdat_b1[B_FIFO_SIZE];
       bzfifo_type txbz_b1;
 
       bzfifo_type txbz_b2;
-      u8 txdat_b2[B_FIFO_SIZE];
+      u_char txdat_b2[B_FIFO_SIZE];
 
-      u8 fill2[D_FIFO_SIZE];
+      u_char fill2[D_FIFO_SIZE];
 
-      u8 rxdat_b1[B_FIFO_SIZE];
+      u_char rxdat_b1[B_FIFO_SIZE];
       bzfifo_type rxbz_b1;
 
       bzfifo_type rxbz_b2;
-      u8 rxdat_b2[B_FIFO_SIZE];
-    } __attribute__((packed)) b_chans;  
-    u8 fill[32768]; 
-  } __attribute__((packed)) fifo_area;
+      u_char rxdat_b2[B_FIFO_SIZE];
+    } b_chans;  
+    u_char fill[32768]; 
+  } fifo_area;
 
 
-//#define Write_hfc(a,b,c) (*(((u8 *)a->hw.hfcpci.pci_io)+b) = c) 
-//#define Read_hfc(a,b) (*(((u8 *)a->hw.hfcpci.pci_io)+b))
-#define Write_hfc(a,b,c)	writeb(c, ((u8 *)a->hw.hfcpci.pci_io)+b)
-#define Read_hfc(a,b)		readb(((u8 *)a->hw.hfcpci.pci_io)+b)
+#define Write_hfc(a,b,c) (*(((u_char *)a->hw.hfcpci.pci_io)+b) = c) 
+#define Read_hfc(a,b) (*(((u_char *)a->hw.hfcpci.pci_io)+b))
 
 extern void main_irq_hcpci(struct BCState *bcs);
 extern void inithfcpci(struct IsdnCardState *cs);
--- diff/drivers/isdn/hisax/hfc_sx.c	2003-09-17 12:28:06.000000000 +0100
+++ source/drivers/isdn/hisax/hfc_sx.c	2004-02-23 13:56:42.000000000 +0000
@@ -1,6 +1,6 @@
-/* $Id: hfc_sx.c,v 1.9.6.3 2001/09/23 22:24:48 kai Exp $
+/* $Id: hfc_sx.c,v 1.12.2.5 2004/02/11 13:21:33 keil Exp $
  *
- * level driver for CCD´s hfc-s+/sp based cards
+ * level driver for Cologne Chip Designs hfc-s+/sp based cards
  *
  * Author       Werner Cornelius
  *              based on existing driver for CCD HFC PCI cards
@@ -20,7 +20,7 @@
 
 extern const char *CardType[];
 
-static const char *hfcsx_revision = "$Revision: 1.9.6.3 $";
+static const char *hfcsx_revision = "$Revision: 1.12.2.5 $";
 
 /***************************************/
 /* IRQ-table for CCDs demo board       */
@@ -43,11 +43,11 @@ static const char *hfcsx_revision = "$Re
 
 #undef CCD_DEMO_BOARD
 #ifdef CCD_DEMO_BOARD
-static u8 ccd_sp_irqtab[16] = {
+static u_char ccd_sp_irqtab[16] = {
   0,0,0,0,0,2,1,0,0,0,3,4,5,0,0,6
 };
 #else /* Teles 16.3c */
-static u8 ccd_sp_irqtab[16] = {
+static u_char ccd_sp_irqtab[16] = {
   0,0,0,7,0,1,0,0,0,2,3,4,5,0,0,6
 };
 #endif
@@ -60,17 +60,16 @@ static u8 ccd_sp_irqtab[16] = {
 /* In/Out access to registers */
 /******************************/
 static inline void
-Write_hfc(struct IsdnCardState *cs, u8 regnum, u8 val)
+Write_hfc(struct IsdnCardState *cs, u_char regnum, u_char val)
 {
-
         byteout(cs->hw.hfcsx.base+1, regnum);
 	byteout(cs->hw.hfcsx.base, val);
 } 
 
-static inline u8
-Read_hfc(struct IsdnCardState *cs, u8 regnum)
+static inline u_char
+Read_hfc(struct IsdnCardState *cs, u_char regnum)
 {
-        u8 ret; 
+        u_char ret; 
 
         byteout(cs->hw.hfcsx.base+1, regnum);
 	ret = bytein(cs->hw.hfcsx.base);
@@ -82,7 +81,7 @@ Read_hfc(struct IsdnCardState *cs, u8 re
 /* select a fifo and remember which one for reuse */
 /**************************************************/
 static void
-fifo_select(struct IsdnCardState *cs, u8 fifo)
+fifo_select(struct IsdnCardState *cs, u_char fifo)
 {
         if (fifo == cs->hw.hfcsx.last_fifo) 
 	  return; /* still valid */
@@ -97,10 +96,10 @@ fifo_select(struct IsdnCardState *cs, u8
 
 /******************************************/
 /* reset the specified fifo to defaults.  */
-/* If it's a send fifo init needed markers */
+/* If its a send fifo init needed markers */
 /******************************************/
 static void
-reset_fifo(struct IsdnCardState *cs, u8 fifo)
+reset_fifo(struct IsdnCardState *cs, u_char fifo)
 {
 	fifo_select(cs, fifo); /* first select the fifo */
 	byteout(cs->hw.hfcsx.base+1, HFCSX_CIRM);
@@ -116,10 +115,11 @@ reset_fifo(struct IsdnCardState *cs, u8 
 /* the skb is not released in any way.                       */
 /*************************************************************/
 static int
-write_fifo(struct IsdnCardState *cs, struct sk_buff *skb, u8 fifo, int trans_max)
-{       unsigned short *msp;
+write_fifo(struct IsdnCardState *cs, struct sk_buff *skb, u_char fifo, int trans_max)
+{
+       unsigned short *msp;
         int fifo_size, count, z1, z2;
-	u8 f_msk, f1, f2, *src;
+	u_char f_msk, f1, f2, *src;
 
 	if (skb->len <= 0) return(0);
         if (fifo & 1) return(0); /* no write fifo */
@@ -145,9 +145,9 @@ write_fifo(struct IsdnCardState *cs, str
 	  count = z2 - z1;
 	  if (count <= 0)
 	    count += fifo_size; /* free bytes */
-	  if (count < (int)(skb->len+1)) return(0); /* no room */
+	  if (count < skb->len+1) return(0); /* no room */
 	  count = fifo_size - count; /* bytes still not send */
-	  if (count > 2 * trans_max) return(0); /* delay too long */
+	  if (count > 2 * trans_max) return(0); /* delay to long */
 	  count = skb->len;
 	  src = skb->data;
 	  while (count--)
@@ -182,7 +182,7 @@ write_fifo(struct IsdnCardState *cs, str
 	if (cs->debug & L1_DEB_ISAC_FIFO)
 	  debugl1(cs, "hfcsx_write_fifo %d count(%ld/%d)",
 		  fifo, skb->len, count);
-	if (count < (int)skb->len) {
+	if (count < skb->len) {
 	  if (cs->debug & L1_DEB_ISAC_FIFO)
 	    debugl1(cs, "hfcsx_write_fifo %d no fifo mem", fifo);
 	  return(0);
@@ -205,9 +205,9 @@ write_fifo(struct IsdnCardState *cs, str
 /* the skb is not released in any way.                         */
 /***************************************************************/
 static struct sk_buff * 
-read_fifo(struct IsdnCardState *cs, u8 fifo, int trans_max)
+read_fifo(struct IsdnCardState *cs, u_char fifo, int trans_max)
 {       int fifo_size, count, z1, z2;
-	u8 f_msk, f1, f2, *dst;
+	u_char f_msk, f1, f2, *dst;
 	struct sk_buff *skb;
 
         if (!(fifo & 1)) return(NULL); /* no read fifo */
@@ -308,8 +308,8 @@ read_fifo(struct IsdnCardState *cs, u8 f
 /******************************************/
 /* free hardware resources used by driver */
 /******************************************/
-static void
-hfcsx_release(struct IsdnCardState *cs)
+void
+release_io_hfcsx(struct IsdnCardState *cs)
 {
 	cs->hw.hfcsx.int_m2 = 0;	/* interrupt output off ! */
 	Write_hfc(cs, HFCSX_INT_M2, cs->hw.hfcsx.int_m2);
@@ -318,7 +318,7 @@ hfcsx_release(struct IsdnCardState *cs)
 	schedule_timeout((30 * HZ) / 1000);	/* Timeout 30ms */
 	Write_hfc(cs, HFCSX_CIRM, 0);	/* Reset Off */
 	del_timer(&cs->hw.hfcsx.timer);
-	hisax_release_resources(cs);
+	release_region(cs->hw.hfcsx.base, 2); /* release IO-Block */
 	kfree(cs->hw.hfcsx.extra);
 	cs->hw.hfcsx.extra = NULL;
 }
@@ -347,8 +347,8 @@ static int set_fifo_size(struct IsdnCard
 /* function called to reset the HFC SX chip. A complete software reset of chip */
 /* and fifos is done.                                                           */
 /********************************************************************************/
-static int
-hfcsx_reset(struct IsdnCardState *cs)
+static void
+reset_hfcsx(struct IsdnCardState *cs)
 {
 	cs->hw.hfcsx.int_m2 = 0;	/* interrupt output off ! */
 	Write_hfc(cs, HFCSX_INT_M2, cs->hw.hfcsx.int_m2);
@@ -356,11 +356,9 @@ hfcsx_reset(struct IsdnCardState *cs)
 	printk(KERN_INFO "HFC_SX: resetting card\n");
 	while (1) {
 	  Write_hfc(cs, HFCSX_CIRM, HFCSX_RESET | cs->hw.hfcsx.cirm ); /* Reset */
-	  set_current_state(TASK_UNINTERRUPTIBLE);
-	  schedule_timeout((30 * HZ) / 1000);	/* Timeout 30ms */
+	  mdelay(30);
 	  Write_hfc(cs, HFCSX_CIRM, cs->hw.hfcsx.cirm); /* Reset Off */
-	  set_current_state(TASK_UNINTERRUPTIBLE);
-	  schedule_timeout((20 * HZ) / 1000);	/* Timeout 20ms */
+	  mdelay(20);
 	  if (Read_hfc(cs, HFCSX_STATUS) & 2)
 	    printk(KERN_WARNING "HFC-SX init bit busy\n");
 	  cs->hw.hfcsx.last_fifo = 0xff; /* invalidate */
@@ -415,7 +413,6 @@ hfcsx_reset(struct IsdnCardState *cs)
 	cs->hw.hfcsx.int_m2 = HFCSX_IRQ_ENABLE;
 	Write_hfc(cs, HFCSX_INT_M2, cs->hw.hfcsx.int_m2);
 	if (Read_hfc(cs, HFCSX_INT_S2));
-	return 0;
 }
 
 /***************************************************/
@@ -431,7 +428,6 @@ hfcsx_Timer(struct IsdnCardState *cs)
  */
 }
 
-
 /************************************************/
 /* select a b-channel entry matching and active */
 /************************************************/
@@ -450,20 +446,27 @@ Sel_BCS(struct IsdnCardState *cs, int ch
 /*******************************/
 /* D-channel receive procedure */
 /*******************************/
-static int
+static
+int
 receive_dmsg(struct IsdnCardState *cs)
 {
 	struct sk_buff *skb;
 	int count = 5;
 
+	if (test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) {
+		debugl1(cs, "rec_dmsg blocked");
+		return (1);
+	}
+
 	do {
 	  skb = read_fifo(cs, HFCSX_SEL_D_RX, 0);
 	  if (skb) {
 	    skb_queue_tail(&cs->rq, skb);
-	    sched_d_event(cs, D_RCVBUFREADY);
+	    schedule_event(cs, D_RCVBUFREADY);
 	  }
 	} while (--count && skb);
 
+	test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);
 	return (1);
 }
 
@@ -479,6 +482,10 @@ main_rec_hfcsx(struct BCState *bcs)
 
       Begin:
 	count--;
+	if (test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) {
+		debugl1(cs, "rec_data %d blocked", bcs->channel);
+		return;
+	}
 	skb = read_fifo(cs, ((bcs->channel) && (!cs->hw.hfcsx.bswapped)) ? 
 			HFCSX_SEL_B2_RX : HFCSX_SEL_B1_RX,
 			(bcs->mode == L1_MODE_TRANS) ? 
@@ -486,9 +493,10 @@ main_rec_hfcsx(struct BCState *bcs)
 
 	if (skb) {
 	  skb_queue_tail(&bcs->rqueue, skb);
-	  sched_b_event(bcs, B_RCVBUFREADY);
+	  schedule_event(bcs, B_RCVBUFREADY);
 	}
 
+	test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);
 	if (count && skb)
 		goto Begin;
 	return;
@@ -509,6 +517,7 @@ hfcsx_fill_dfifo(struct IsdnCardState *c
 	  dev_kfree_skb_any(cs->tx_skb);
 	  cs->tx_skb = NULL;
 	}
+	return;
 }
 
 /**************************/
@@ -530,9 +539,18 @@ hfcsx_fill_fifo(struct BCState *bcs)
 		       (bcs->mode == L1_MODE_TRANS) ? 
 		       HFCSX_BTRANS_THRESHOLD : 0)) {
 
-		bcs->tx_cnt -= bcs->tx_skb->len;
-		xmit_complete_b(bcs);
-		test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
+	  bcs->tx_cnt -= bcs->tx_skb->len;
+	  if (test_bit(FLG_LLI_L1WAKEUP,&bcs->st->lli.flag) &&
+		(PACKET_NOACK != bcs->tx_skb->pkt_type)) {
+		u_long	flags;
+		spin_lock_irqsave(&bcs->aclock, flags);
+		bcs->ackcnt += bcs->tx_skb->len;
+		spin_unlock_irqrestore(&bcs->aclock, flags);
+		schedule_event(bcs, B_ACKPENDING);
+	  }
+	  dev_kfree_skb_any(bcs->tx_skb);
+	  bcs->tx_skb = NULL;
+	  test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
 	}
 }
 
@@ -551,7 +569,7 @@ dch_nt_l2l1(struct PStack *st, int pr, v
 			st->l1.l1hw(st, pr, arg);
 			break;
 		case (PH_ACTIVATE | REQUEST):
-			L1L2(st, PH_ACTIVATE | CONFIRM, NULL);
+			st->l1.l1l2(st, PH_ACTIVATE | CONFIRM, NULL);
 			break;
 		case (PH_TESTLOOP | REQUEST):
 			if (1 & (long) arg)
@@ -577,10 +595,12 @@ dch_nt_l2l1(struct PStack *st, int pr, v
 static int
 hfcsx_auxcmd(struct IsdnCardState *cs, isdn_ctrl * ic)
 {
+	unsigned long flags;
 	int i = *(unsigned int *) ic->parm.num;
 
 	if ((ic->arg == 98) &&
 	    (!(cs->hw.hfcsx.int_m1 & (HFCSX_INTS_B2TRANS + HFCSX_INTS_B2REC + HFCSX_INTS_B1TRANS + HFCSX_INTS_B1REC)))) {
+	    	spin_lock_irqsave(&cs->lock, flags);
 		Write_hfc(cs, HFCSX_STATES, HFCSX_LOAD_STATE | 0);	/* HFC ST G0 */
 		udelay(10);
 		cs->hw.hfcsx.sctrl |= SCTRL_MODE_NT;
@@ -592,7 +612,8 @@ hfcsx_auxcmd(struct IsdnCardState *cs, i
 		cs->dc.hfcsx.ph_state = 1;
 		cs->hw.hfcsx.nt_mode = 1;
 		cs->hw.hfcsx.nt_timer = 0;
-		cs->stlist->l1.l2l1 = dch_nt_l2l1;
+		spin_unlock_irqrestore(&cs->lock, flags);
+		cs->stlist->l2.l2l1 = dch_nt_l2l1;
 		debugl1(cs, "NT mode activated");
 		return (0);
 	}
@@ -614,12 +635,14 @@ hfcsx_auxcmd(struct IsdnCardState *cs, i
 	cs->hw.hfcsx.sctrl &= ~SCTRL_B2_ENA;
 	cs->hw.hfcsx.conn |= 0x10;	/* B2-IOM -> B2-ST */
 	cs->hw.hfcsx.ctmt &= ~2;
+	spin_lock_irqsave(&cs->lock, flags);
 	Write_hfc(cs, HFCSX_CTMT, cs->hw.hfcsx.ctmt);
 	Write_hfc(cs, HFCSX_SCTRL_R, cs->hw.hfcsx.sctrl_r);
 	Write_hfc(cs, HFCSX_SCTRL, cs->hw.hfcsx.sctrl);
 	Write_hfc(cs, HFCSX_CONNECT, cs->hw.hfcsx.conn);
 	Write_hfc(cs, HFCSX_TRM, cs->hw.hfcsx.trm);
 	Write_hfc(cs, HFCSX_INT_M1, cs->hw.hfcsx.int_m1);
+	spin_unlock_irqrestore(&cs->lock, flags);
 	return (0);
 }				/* hfcsx_auxcmd */
 
@@ -630,9 +653,13 @@ static void
 receive_emsg(struct IsdnCardState *cs)
 {
 	int count = 5;
-	u8 *ptr;
+	u_char *ptr;
 	struct sk_buff *skb;
 
+	if (test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) {
+		debugl1(cs, "echo_rec_data blocked");
+		return;
+	}
 	do {
 	  skb = read_fifo(cs, HFCSX_SEL_B2_RX, 0);
 	  if (skb) {
@@ -655,6 +682,9 @@ receive_emsg(struct IsdnCardState *cs)
 	    dev_kfree_skb_any(skb);
 	  }
 	} while (--count && skb);
+
+	test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);
+	return;
 }				/* receive_emsg */
 
 
@@ -665,27 +695,28 @@ static irqreturn_t
 hfcsx_interrupt(int intno, void *dev_id, struct pt_regs *regs)
 {
 	struct IsdnCardState *cs = dev_id;
-	u8 exval;
+	u_char exval;
 	struct BCState *bcs;
 	int count = 15;
-	u8 val, stat;
+	u_long flags;
+	u_char val, stat;
 
-	if (!cs) {
-		printk(KERN_WARNING "HFC-SX: Spurious interrupt!\n");
-		return IRQ_NONE;
-	}
 	if (!(cs->hw.hfcsx.int_m2 & 0x08))
 		return IRQ_NONE;		/* not initialised */
 
+	spin_lock_irqsave(&cs->lock, flags);
 	if (HFCSX_ANYINT & (stat = Read_hfc(cs, HFCSX_STATUS))) {
 		val = Read_hfc(cs, HFCSX_INT_S1);
 		if (cs->debug & L1_DEB_ISAC)
 			debugl1(cs, "HFC-SX: stat(%02x) s1(%02x)", stat, val);
-	} else
+	} else {
+		spin_unlock_irqrestore(&cs->lock, flags);
 		return IRQ_NONE;
-
+	}
 	if (cs->debug & L1_DEB_ISAC)
-		debugl1(cs, "HFC-SX irq %x", val);
+		debugl1(cs, "HFC-SX irq %x %s", val,
+			test_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags) ?
+			"locked" : "unlocked");
 	val &= cs->hw.hfcsx.int_m1;
 	if (val & 0x40) {	/* state machine irq */
 		exval = Read_hfc(cs, HFCSX_STATES) & 0xf;
@@ -693,18 +724,23 @@ hfcsx_interrupt(int intno, void *dev_id,
 			debugl1(cs, "ph_state chg %d->%d", cs->dc.hfcsx.ph_state,
 				exval);
 		cs->dc.hfcsx.ph_state = exval;
-		sched_d_event(cs, D_L1STATECHANGE);
+		schedule_event(cs, D_L1STATECHANGE);
 		val &= ~0x40;
 	}
 	if (val & 0x80) {	/* timer irq */
 		if (cs->hw.hfcsx.nt_mode) {
 			if ((--cs->hw.hfcsx.nt_timer) < 0)
-				sched_d_event(cs, D_L1STATECHANGE);
+				schedule_event(cs, D_L1STATECHANGE);
 		}
 		val &= ~0x80;
 		Write_hfc(cs, HFCSX_CTMT, cs->hw.hfcsx.ctmt | HFCSX_CLTIMER);
 	}
 	while (val) {
+		if (test_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) {
+			cs->hw.hfcsx.int_s1 |= val;
+			spin_unlock_irqrestore(&cs->lock, flags);
+			return IRQ_HANDLED;
+		}
 		if (cs->hw.hfcsx.int_s1 & 0x18) {
 			exval = val;
 			val = cs->hw.hfcsx.int_s1;
@@ -731,7 +767,23 @@ hfcsx_interrupt(int intno, void *dev_id,
 				if (cs->debug)
 					debugl1(cs, "hfcsx spurious 0x01 IRQ");
 			} else {
-				xmit_xpr_b(bcs);
+				if (bcs->tx_skb) {
+					if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) {
+						hfcsx_fill_fifo(bcs);
+						test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);
+					} else
+						debugl1(cs, "fill_data %d blocked", bcs->channel);
+				} else {
+					if ((bcs->tx_skb = skb_dequeue(&bcs->squeue))) {
+						if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) {
+							hfcsx_fill_fifo(bcs);
+							test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);
+						} else
+							debugl1(cs, "fill_data %d blocked", bcs->channel);
+					} else {
+						schedule_event(bcs, B_XMTBUFREADY);
+					}
+				}
 			}
 		}
 		if (val & 0x02) {
@@ -739,15 +791,60 @@ hfcsx_interrupt(int intno, void *dev_id,
 				if (cs->debug)
 					debugl1(cs, "hfcsx spurious 0x02 IRQ");
 			} else {
-				xmit_xpr_b(bcs);
+				if (bcs->tx_skb) {
+					if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) {
+						hfcsx_fill_fifo(bcs);
+						test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);
+					} else
+						debugl1(cs, "fill_data %d blocked", bcs->channel);
+				} else {
+					if ((bcs->tx_skb = skb_dequeue(&bcs->squeue))) {
+						if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) {
+							hfcsx_fill_fifo(bcs);
+							test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);
+						} else
+							debugl1(cs, "fill_data %d blocked", bcs->channel);
+					} else {
+						schedule_event(bcs, B_XMTBUFREADY);
+					}
+				}
 			}
 		}
 		if (val & 0x20) {	/* receive dframe */
 			receive_dmsg(cs);
 		}
 		if (val & 0x04) {	/* dframe transmitted */
-			xmit_xpr_d(cs);
+			if (test_and_clear_bit(FLG_DBUSY_TIMER, &cs->HW_Flags))
+				del_timer(&cs->dbusytimer);
+			if (test_and_clear_bit(FLG_L1_DBUSY, &cs->HW_Flags))
+				schedule_event(cs, D_CLEARBUSY);
+			if (cs->tx_skb) {
+				if (cs->tx_skb->len) {
+					if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) {
+						hfcsx_fill_dfifo(cs);
+						test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);
+					} else {
+						debugl1(cs, "hfcsx_fill_dfifo irq blocked");
+					}
+					goto afterXPR;
+				} else {
+					dev_kfree_skb_irq(cs->tx_skb);
+					cs->tx_cnt = 0;
+					cs->tx_skb = NULL;
+				}
+			}
+			if ((cs->tx_skb = skb_dequeue(&cs->sq))) {
+				cs->tx_cnt = 0;
+				if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) {
+					hfcsx_fill_dfifo(cs);
+					test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);
+				} else {
+					debugl1(cs, "hfcsx_fill_dfifo irq blocked");
+				}
+			} else
+				schedule_event(cs, D_XMTBUFREADY);
 		}
+	      afterXPR:
 		if (cs->hw.hfcsx.int_s1 && count--) {
 			val = cs->hw.hfcsx.int_s1;
 			cs->hw.hfcsx.int_s1 = 0;
@@ -756,6 +853,7 @@ hfcsx_interrupt(int intno, void *dev_id,
 		} else
 			val = 0;
 	}
+	spin_unlock_irqrestore(&cs->lock, flags);
 	return IRQ_HANDLED;
 }
 
@@ -775,38 +873,104 @@ HFCSX_l1hw(struct PStack *st, int pr, vo
 {
 	struct IsdnCardState *cs = (struct IsdnCardState *) st->l1.hardware;
 	struct sk_buff *skb = arg;
+	u_long flags;
 
 	switch (pr) {
 		case (PH_DATA | REQUEST):
-			xmit_data_req_d(cs, skb);
+			if (cs->debug & DEB_DLOG_HEX)
+				LogFrame(cs, skb->data, skb->len);
+			if (cs->debug & DEB_DLOG_VERBOSE)
+				dlogframe(cs, skb, 0);
+			spin_lock_irqsave(&cs->lock, flags);
+			if (cs->tx_skb) {
+				skb_queue_tail(&cs->sq, skb);
+#ifdef L2FRAME_DEBUG		/* psa */
+				if (cs->debug & L1_DEB_LAPD)
+					Logl2Frame(cs, skb, "PH_DATA Queued", 0);
+#endif
+			} else {
+				cs->tx_skb = skb;
+				cs->tx_cnt = 0;
+#ifdef L2FRAME_DEBUG		/* psa */
+				if (cs->debug & L1_DEB_LAPD)
+					Logl2Frame(cs, skb, "PH_DATA", 0);
+#endif
+				if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) {
+				        hfcsx_fill_dfifo(cs); 
+					test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);
+				} else
+					debugl1(cs, "hfcsx_fill_dfifo blocked");
+
+			}
+			spin_unlock_irqrestore(&cs->lock, flags);
 			break;
-		case (PH_PULL |INDICATION):
-			xmit_pull_ind_d(cs, skb);
+		case (PH_PULL | INDICATION):
+			spin_lock_irqsave(&cs->lock, flags);
+			if (cs->tx_skb) {
+				if (cs->debug & L1_DEB_WARN)
+					debugl1(cs, " l2l1 tx_skb exist this shouldn't happen");
+				skb_queue_tail(&cs->sq, skb);
+				spin_unlock_irqrestore(&cs->lock, flags);
+				break;
+			}
+			if (cs->debug & DEB_DLOG_HEX)
+				LogFrame(cs, skb->data, skb->len);
+			if (cs->debug & DEB_DLOG_VERBOSE)
+				dlogframe(cs, skb, 0);
+			cs->tx_skb = skb;
+			cs->tx_cnt = 0;
+#ifdef L2FRAME_DEBUG		/* psa */
+			if (cs->debug & L1_DEB_LAPD)
+				Logl2Frame(cs, skb, "PH_DATA_PULLED", 0);
+#endif
+			if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) {
+				hfcsx_fill_dfifo(cs); 
+				test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);
+			} else
+				debugl1(cs, "hfcsx_fill_dfifo blocked");
+			spin_unlock_irqrestore(&cs->lock, flags);
 			break;
 		case (PH_PULL | REQUEST):
-			xmit_pull_req_d(st);
+#ifdef L2FRAME_DEBUG		/* psa */
+			if (cs->debug & L1_DEB_LAPD)
+				debugl1(cs, "-> PH_REQUEST_PULL");
+#endif
+			if (!cs->tx_skb) {
+				test_and_clear_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
+				st->l1.l1l2(st, PH_PULL | CONFIRM, NULL);
+			} else
+				test_and_set_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
 			break;
 		case (HW_RESET | REQUEST):
+			spin_lock_irqsave(&cs->lock, flags);
 			Write_hfc(cs, HFCSX_STATES, HFCSX_LOAD_STATE | 3);	/* HFC ST 3 */
 			udelay(6);
 			Write_hfc(cs, HFCSX_STATES, 3);	/* HFC ST 2 */
 			cs->hw.hfcsx.mst_m |= HFCSX_MASTER;
 			Write_hfc(cs, HFCSX_MST_MODE, cs->hw.hfcsx.mst_m);
 			Write_hfc(cs, HFCSX_STATES, HFCSX_ACTIVATE | HFCSX_DO_ACTION);
+			spin_unlock_irqrestore(&cs->lock, flags);
 			l1_msg(cs, HW_POWERUP | CONFIRM, NULL);
 			break;
 		case (HW_ENABLE | REQUEST):
+			spin_lock_irqsave(&cs->lock, flags);
 			Write_hfc(cs, HFCSX_STATES, HFCSX_ACTIVATE | HFCSX_DO_ACTION);
+			spin_unlock_irqrestore(&cs->lock, flags);
 			break;
 		case (HW_DEACTIVATE | REQUEST):
+			spin_lock_irqsave(&cs->lock, flags);
 			cs->hw.hfcsx.mst_m &= ~HFCSX_MASTER;
 			Write_hfc(cs, HFCSX_MST_MODE, cs->hw.hfcsx.mst_m);
+			spin_unlock_irqrestore(&cs->lock, flags);
 			break;
 		case (HW_INFO3 | REQUEST):
+			spin_lock_irqsave(&cs->lock, flags);
 			cs->hw.hfcsx.mst_m |= HFCSX_MASTER;
 			Write_hfc(cs, HFCSX_MST_MODE, cs->hw.hfcsx.mst_m);
+			spin_unlock_irqrestore(&cs->lock, flags);
 			break;
 		case (HW_TESTLOOP | REQUEST):
+			spin_lock_irqsave(&cs->lock, flags);
 			switch ((int) arg) {
 				case (1):
 					Write_hfc(cs, HFCSX_B1_SSL, 0x80);	/* tx slot */
@@ -814,21 +978,21 @@ HFCSX_l1hw(struct PStack *st, int pr, vo
 					cs->hw.hfcsx.conn = (cs->hw.hfcsx.conn & ~7) | 1;
 					Write_hfc(cs, HFCSX_CONNECT, cs->hw.hfcsx.conn);
 					break;
-
 				case (2):
 					Write_hfc(cs, HFCSX_B2_SSL, 0x81);	/* tx slot */
 					Write_hfc(cs, HFCSX_B2_RSL, 0x81);	/* rx slot */
 					cs->hw.hfcsx.conn = (cs->hw.hfcsx.conn & ~0x38) | 0x08;
 					Write_hfc(cs, HFCSX_CONNECT, cs->hw.hfcsx.conn);
 					break;
-
 				default:
+					spin_unlock_irqrestore(&cs->lock, flags);
 					if (cs->debug & L1_DEB_WARN)
 						debugl1(cs, "hfcsx_l1hw loop invalid %4x", (int) arg);
 					return;
 			}
 			cs->hw.hfcsx.trm |= 0x80;	/* enable IOM-loop */
 			Write_hfc(cs, HFCSX_TRM, cs->hw.hfcsx.trm);
+			spin_unlock_irqrestore(&cs->lock, flags);
 			break;
 		default:
 			if (cs->debug & L1_DEB_WARN)
@@ -840,11 +1004,25 @@ HFCSX_l1hw(struct PStack *st, int pr, vo
 /***********************************************/
 /* called during init setting l1 stack pointer */
 /***********************************************/
-static int
+void
 setstack_hfcsx(struct PStack *st, struct IsdnCardState *cs)
 {
 	st->l1.l1hw = HFCSX_l1hw;
-	return 0;
+}
+
+/**************************************/
+/* send B-channel data if not blocked */
+/**************************************/
+static void
+hfcsx_send_data(struct BCState *bcs)
+{
+	struct IsdnCardState *cs = bcs->cs;
+
+	if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) {
+	  hfcsx_fill_fifo(bcs);
+		test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);
+	} else
+		debugl1(cs, "send_data %d blocked", bcs->channel);
 }
 
 /***************************************************************/
@@ -963,31 +1141,57 @@ mode_hfcsx(struct BCState *bcs, int mode
 static void
 hfcsx_l2l1(struct PStack *st, int pr, void *arg)
 {
+	struct BCState *bcs = st->l1.bcs;
 	struct sk_buff *skb = arg;
+	u_long flags;
 
 	switch (pr) {
 		case (PH_DATA | REQUEST):
-			xmit_data_req_b(st->l1.bcs, skb);
+			spin_lock_irqsave(&bcs->cs->lock, flags);
+			if (bcs->tx_skb) {
+				skb_queue_tail(&bcs->squeue, skb);
+			} else {
+				bcs->tx_skb = skb;
+//                              test_and_set_bit(BC_FLG_BUSY, &bcs->Flag);
+				bcs->cs->BC_Send_Data(bcs);
+			}
+			spin_unlock_irqrestore(&bcs->cs->lock, flags);
 			break;
 		case (PH_PULL | INDICATION):
-			xmit_pull_ind_b(st->l1.bcs, skb);
+			spin_lock_irqsave(&bcs->cs->lock, flags);
+			if (bcs->tx_skb) {
+				printk(KERN_WARNING "hfc_l2l1: this shouldn't happen\n");
+			} else {
+//				test_and_set_bit(BC_FLG_BUSY, &bcs->Flag);
+				bcs->tx_skb = skb;
+				bcs->cs->BC_Send_Data(bcs);
+			}
+			spin_unlock_irqrestore(&bcs->cs->lock, flags);
 			break;
 		case (PH_PULL | REQUEST):
-			xmit_pull_req_b(st);
+			if (!bcs->tx_skb) {
+				test_and_clear_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
+				st->l1.l1l2(st, PH_PULL | CONFIRM, NULL);
+			} else
+				test_and_set_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
 			break;
 		case (PH_ACTIVATE | REQUEST):
-			test_and_set_bit(BC_FLG_ACTIV, &st->l1.bcs->Flag);
-			mode_hfcsx(st->l1.bcs, st->l1.mode, st->l1.bc);
+			spin_lock_irqsave(&bcs->cs->lock, flags);
+			test_and_set_bit(BC_FLG_ACTIV, &bcs->Flag);
+			mode_hfcsx(bcs, st->l1.mode, st->l1.bc);
+			spin_unlock_irqrestore(&bcs->cs->lock, flags);
 			l1_msg_b(st, pr, arg);
 			break;
 		case (PH_DEACTIVATE | REQUEST):
 			l1_msg_b(st, pr, arg);
 			break;
 		case (PH_DEACTIVATE | CONFIRM):
-			test_and_clear_bit(BC_FLG_ACTIV, &st->l1.bcs->Flag);
-			test_and_clear_bit(BC_FLG_BUSY, &st->l1.bcs->Flag);
-			mode_hfcsx(st->l1.bcs, 0, st->l1.bc);
-			L1L2(st, PH_DEACTIVATE | CONFIRM, NULL);
+			spin_lock_irqsave(&bcs->cs->lock, flags);
+			test_and_clear_bit(BC_FLG_ACTIV, &bcs->Flag);
+			test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
+			mode_hfcsx(bcs, 0, st->l1.bc);
+			spin_unlock_irqrestore(&bcs->cs->lock, flags);
+			st->l1.l1l2(st, PH_DEACTIVATE | CONFIRM, NULL);
 			break;
 	}
 }
@@ -1037,7 +1241,7 @@ setstack_2b(struct PStack *st, struct BC
 	if (open_hfcsxstate(st->l1.hardware, bcs))
 		return (-1);
 	st->l1.bcs = bcs;
-	st->l1.l2l1 = hfcsx_l2l1;
+	st->l2.l2l1 = hfcsx_l2l1;
 	setstack_manager(st);
 	bcs->st = st;
 	setstack_l1_B(st);
@@ -1048,10 +1252,12 @@ setstack_2b(struct PStack *st, struct BC
 /* handle L1 state changes */
 /***************************/
 static void
-hfcsx_bh(void *data)
+hfcsx_bh(struct IsdnCardState *cs)
 {
-	struct IsdnCardState *cs = data;
+	u_long flags;
 
+	if (!cs)
+		return;
 	if (test_and_clear_bit(D_L1STATECHANGE, &cs->event)) {
 		if (!cs->hw.hfcsx.nt_mode)
 			switch (cs->dc.hfcsx.ph_state) {
@@ -1075,6 +1281,7 @@ hfcsx_bh(void *data)
 		} else {
 			switch (cs->dc.hfcsx.ph_state) {
 				case (2):
+					spin_lock_irqsave(&cs->lock, flags);
 					if (cs->hw.hfcsx.nt_timer < 0) {
 						cs->hw.hfcsx.nt_timer = 0;
 						cs->hw.hfcsx.int_m1 &= ~HFCSX_INTS_TIMER;
@@ -1096,13 +1303,16 @@ hfcsx_bh(void *data)
 						cs->hw.hfcsx.nt_timer = NT_T1_COUNT;
 						Write_hfc(cs, HFCSX_STATES, 2 | HFCSX_NT_G2_G3);	/* allow G2 -> G3 transition */
 					}
+					spin_unlock_irqrestore(&cs->lock, flags);
 					break;
 				case (1):
 				case (3):
 				case (4):
+					spin_lock_irqsave(&cs->lock, flags);
 					cs->hw.hfcsx.nt_timer = 0;
 					cs->hw.hfcsx.int_m1 &= ~HFCSX_INTS_TIMER;
 					Write_hfc(cs, HFCSX_INT_M1, cs->hw.hfcsx.int_m1);
+					spin_unlock_irqrestore(&cs->lock, flags);
 					break;
 				default:
 					break;
@@ -1115,18 +1325,6 @@ hfcsx_bh(void *data)
 		DChannel_proc_xmt(cs);
 }
 
-static struct bc_l1_ops hfcsx_bc_l1_ops = {
-	.fill_fifo = hfcsx_fill_fifo,
-	.open      = setstack_2b,
-	.close     = close_hfcsx,
-};
-
-static struct dc_l1_ops hfcsx_dc_l1_ops = {
-	.fill_fifo  = hfcsx_fill_dfifo,
-	.open       = setstack_hfcsx,
-	.bh_func    = hfcsx_bh,
-	.dbusy_func = hfcsx_dbusy_timer,
-};
 
 /********************************/
 /* called for card init message */
@@ -1134,98 +1332,55 @@ static struct dc_l1_ops hfcsx_dc_l1_ops 
 void __devinit
 inithfcsx(struct IsdnCardState *cs)
 {
-	dc_l1_init(cs, &hfcsx_dc_l1_ops);
-	cs->bc_l1_ops = &hfcsx_bc_l1_ops;
+	cs->setstack_d = setstack_hfcsx;
+	cs->BC_Send_Data = &hfcsx_send_data;
+	cs->bcs[0].BC_SetStack = setstack_2b;
+	cs->bcs[1].BC_SetStack = setstack_2b;
+	cs->bcs[0].BC_Close = close_hfcsx;
+	cs->bcs[1].BC_Close = close_hfcsx;
 	mode_hfcsx(cs->bcs, 0, 0);
 	mode_hfcsx(cs->bcs + 1, 0, 1);
 }
 
-static void
-hfcsx_init(struct IsdnCardState *cs)
-{
-	inithfcsx(cs);
-	set_current_state(TASK_UNINTERRUPTIBLE);
-	schedule_timeout((80 * HZ) / 1000);	/* Timeout 80ms */
-	/* now switch timer interrupt off */
-	cs->hw.hfcsx.int_m1 &= ~HFCSX_INTS_TIMER;
-	Write_hfc(cs, HFCSX_INT_M1, cs->hw.hfcsx.int_m1);
-	/* reinit mode reg */
-	Write_hfc(cs, HFCSX_MST_MODE, cs->hw.hfcsx.mst_m);
-}
 
-static struct card_ops hfcsx_ops = {
-	.init     = hfcsx_init,
-	.reset    = hfcsx_reset,
-	.release  = hfcsx_release,
-	.irq_func = hfcsx_interrupt,
-};
 
-static int __init
-hfcsx_probe(struct IsdnCardState *cs, struct IsdnCard *card)
+/*******************************************/
+/* handle card messages from control layer */
+/*******************************************/
+static int
+hfcsx_card_msg(struct IsdnCardState *cs, int mt, void *arg)
 {
-	int rc;
-	char c;
+	u_long flags;
 
-	cs->irq = card->para[0];
-	cs->hw.hfcsx.base = card->para[1] & 0xfffe;
-
-	cs->hw.hfcsx.fifo = 255;
-	cs->hw.hfcsx.int_s1 = 0;
-	cs->dc.hfcsx.ph_state = 0;
-
-	rc = -EBUSY;
-	if (!request_io(&cs->rs, cs->hw.hfcsx.base, 2, "HFCSX isdn"))
-		goto err;
-
-	rc = -ENODEV;
-	byteout(cs->hw.hfcsx.base, cs->hw.hfcsx.base & 0xFF);
-	byteout(cs->hw.hfcsx.base + 1, ((cs->hw.hfcsx.base >> 8) & 3) | 0x54);
-	udelay(10);
-	cs->hw.hfcsx.chip = Read_hfc(cs,HFCSX_CHIP_ID);
-	switch (cs->hw.hfcsx.chip >> 4) {
-	case 1: 
-		c ='+';
-		break;
-	case 9: 
-		c ='P';
-		break;
-	default:
-		printk(KERN_WARNING "HFC-SX: invalid chip id 0x%x\n",
-		       cs->hw.hfcsx.chip >> 4);
-		goto err;
-	}  
-	if (!ccd_sp_irqtab[cs->irq & 0xF]) {
-		printk(KERN_WARNING "HFC_SX: invalid irq %d specified\n",
-		       cs->irq & 0xF);
-		goto err;
-	}
-	rc = -ENOMEM;
-	cs->hw.hfcsx.extra = kmalloc(sizeof(struct hfcsx_extra), GFP_ATOMIC);
-	if (!cs->hw.hfcsx.extra) {
-		printk(KERN_WARNING "HFC-SX: unable to allocate memory\n");
-		goto err;
+	if (cs->debug & L1_DEB_ISAC)
+		debugl1(cs, "HFCSX: card_msg %x", mt);
+	switch (mt) {
+		case CARD_RESET:
+			spin_lock_irqsave(&cs->lock, flags);
+			reset_hfcsx(cs);
+			spin_unlock_irqrestore(&cs->lock, flags);
+			return (0);
+		case CARD_RELEASE:
+			release_io_hfcsx(cs);
+			return (0);
+		case CARD_INIT:
+			spin_lock_irqsave(&cs->lock, flags);
+			inithfcsx(cs);
+			spin_unlock_irqrestore(&cs->lock, flags);
+			set_current_state(TASK_UNINTERRUPTIBLE);
+			schedule_timeout((80 * HZ) / 1000);	/* Timeout 80ms */
+			/* now switch timer interrupt off */
+			spin_lock_irqsave(&cs->lock, flags);
+			cs->hw.hfcsx.int_m1 &= ~HFCSX_INTS_TIMER;
+			Write_hfc(cs, HFCSX_INT_M1, cs->hw.hfcsx.int_m1);
+			/* reinit mode reg */
+			Write_hfc(cs, HFCSX_MST_MODE, cs->hw.hfcsx.mst_m);
+			spin_unlock_irqrestore(&cs->lock, flags);
+			return (0);
+		case CARD_TEST:
+			return (0);
 	}
-	printk(KERN_INFO "HFC-S%c chip detected at base 0x%x IRQ %d\n",
-	       c, (u_int) cs->hw.hfcsx.base, cs->irq);
-
-	cs->hw.hfcsx.int_m2 = 0;	/* disable alle interrupts */
-	cs->hw.hfcsx.int_m1 = 0;
-	Write_hfc(cs, HFCSX_INT_M1, cs->hw.hfcsx.int_m1);
-	Write_hfc(cs, HFCSX_INT_M2, cs->hw.hfcsx.int_m2);
-
-	init_timer(&cs->hw.hfcsx.timer);
-	cs->hw.hfcsx.timer.function = (void *) hfcsx_Timer;
-	cs->hw.hfcsx.timer.data = (long) cs;
-	cs->hw.hfcsx.b_fifo_size = 0; /* fifo size still unknown */
-	cs->hw.hfcsx.cirm = ccd_sp_irqtab[cs->irq & 0xF]; /* RAM not eval. */
-
-	hfcsx_reset(cs);
-	cs->auxcmd = &hfcsx_auxcmd;
-	cs->card_ops = &hfcsx_ops;
-	return 0;
- err:
-	hisax_release_resources(cs);
-	return rc;
+	return (0);
 }
 
 #ifdef __ISAPNP__
@@ -1236,66 +1391,133 @@ static struct isapnp_device_id hfc_ids[]
 	{ 0, }
 };
 
-static struct isapnp_device_id *hdev = &hfc_ids[0];
+static struct isapnp_device_id *ipid __initdata = &hfc_ids[0];
 static struct pnp_card *pnp_c __devinitdata = NULL;
 #endif
 
 int __devinit
 setup_hfcsx(struct IsdnCard *card)
 {
+	struct IsdnCardState *cs = card->cs;
 	char tmp[64];
 
 	strcpy(tmp, hfcsx_revision);
 	printk(KERN_INFO "HiSax: HFC-SX driver Rev. %s\n", HiSax_getrev(tmp));
 #ifdef __ISAPNP__
 	if (!card->para[1] && isapnp_present()) {
-		struct pnp_card *pb;
-		struct pnp_dev  *pd;
+		struct pnp_dev *pnp_d;
+		while(ipid->card_vendor) {
+			if ((pnp_c = pnp_find_card(ipid->card_vendor,
+				ipid->card_device, pnp_c))) {
+				pnp_d = NULL;
+				if ((pnp_d = pnp_find_dev(pnp_c,
+					ipid->vendor, ipid->function, pnp_d))) {
+					int err;
 
-		while(hdev->card_vendor) {
-			if ((pb = pnp_find_card(hdev->card_vendor,
-						hdev->card_device,
-						pnp_c))) {
-				pnp_c = pb;
-				pd = NULL;
-				if ((pd = pnp_find_dev(pnp_c,
-						       hdev->vendor,
-						       hdev->function,
-						       pd))) {
 					printk(KERN_INFO "HiSax: %s detected\n",
-						(char *)hdev->driver_data);
-					if (pnp_device_attach(pd) < 0) {
-						printk(KERN_ERR "HFC PnP: attach failed\n");
-						return 0;
-					}
-					if (pnp_activate_dev(pd) < 0) {
-						printk(KERN_ERR "HFC PnP: activate failed\n");
-						pnp_device_detach(pd);
-						return 0;
+						(char *)ipid->driver_data);
+					pnp_disable_dev(pnp_d);
+					err = pnp_activate_dev(pnp_d);
+					if (err<0) {
+						printk(KERN_WARNING "%s: pnp_activate_dev ret(%d)\n",
+							__FUNCTION__, err);
+						return(0);
 					}
-					if (!pnp_irq_valid(pd, 0) || !pnp_port_valid(pd, 0)) {
+					card->para[1] = pnp_port_start(pnp_d, 0);
+					card->para[0] = pnp_irq(pnp_d, 0);
+					if (!card->para[0] || !card->para[1]) {
 						printk(KERN_ERR "HFC PnP:some resources are missing %ld/%lx\n",
-							pnp_irq(pd, 0), pnp_port_start(pd, 0));
-						pnp_device_detach(pd);
+							card->para[0], card->para[1]);
+						pnp_disable_dev(pnp_d);
 						return(0);
 					}
-					card->para[1] = pnp_port_start(pd, 0);
-					card->para[0] = pnp_irq(pd, 0);
 					break;
 				} else {
 					printk(KERN_ERR "HFC PnP: PnP error card found, no device\n");
 				}
 			}
-			hdev++;
-			pnp_c=NULL;
+			ipid++;
+			pnp_c = NULL;
 		} 
-		if (!hdev->card_vendor) {
+		if (!ipid->card_vendor) {
 			printk(KERN_INFO "HFC PnP: no ISAPnP card found\n");
 			return(0);
 		}
 	}
 #endif
-	if (hfcsx_probe(card->cs, card) < 0)
-		return 0;
-	return 1;
+	cs->hw.hfcsx.base = card->para[1] & 0xfffe;
+	cs->irq = card->para[0];
+	cs->hw.hfcsx.int_s1 = 0;
+	cs->dc.hfcsx.ph_state = 0;
+	cs->hw.hfcsx.fifo = 255;
+	if ((cs->typ == ISDN_CTYPE_HFC_SX) || 
+	    (cs->typ == ISDN_CTYPE_HFC_SP_PCMCIA)) {
+	        if ((!cs->hw.hfcsx.base) || !request_region(cs->hw.hfcsx.base, 2, "HFCSX isdn")) {
+		  printk(KERN_WARNING
+			 "HiSax: HFC-SX io-base %#lx already in use\n",
+		          cs->hw.hfcsx.base);
+		  return(0);
+		}
+		byteout(cs->hw.hfcsx.base, cs->hw.hfcsx.base & 0xFF);
+		byteout(cs->hw.hfcsx.base + 1,
+			((cs->hw.hfcsx.base >> 8) & 3) | 0x54);
+		udelay(10);
+	        cs->hw.hfcsx.chip = Read_hfc(cs,HFCSX_CHIP_ID);
+                switch (cs->hw.hfcsx.chip >> 4) {
+		  case 1: 
+		    tmp[0] ='+';
+		    break;
+		  case 9: 
+		    tmp[0] ='P';
+		    break;
+		  default:
+		    printk(KERN_WARNING
+			   "HFC-SX: invalid chip id 0x%x\n",
+			   cs->hw.hfcsx.chip >> 4);
+		    release_region(cs->hw.hfcsx.base, 2);
+		    return(0);
+		}  
+		if (!ccd_sp_irqtab[cs->irq & 0xF]) {
+		  printk(KERN_WARNING 
+			 "HFC_SX: invalid irq %d specified\n",cs->irq & 0xF);
+		  release_region(cs->hw.hfcsx.base, 2);
+		  return(0);
+		}  
+		if (!(cs->hw.hfcsx.extra = (void *)
+		      kmalloc(sizeof(struct hfcsx_extra), GFP_ATOMIC))) {
+		  release_region(cs->hw.hfcsx.base, 2);
+		  printk(KERN_WARNING "HFC-SX: unable to allocate memory\n");
+		  return(0);
+		}
+		printk(KERN_INFO "HFC-S%c chip detected at base 0x%x IRQ %d HZ %d\n",
+			tmp[0], (u_int) cs->hw.hfcsx.base, cs->irq, HZ);
+		cs->hw.hfcsx.int_m2 = 0;	/* disable alle interrupts */
+		cs->hw.hfcsx.int_m1 = 0;
+		Write_hfc(cs, HFCSX_INT_M1, cs->hw.hfcsx.int_m1);
+		Write_hfc(cs, HFCSX_INT_M2, cs->hw.hfcsx.int_m2);
+	} else
+		return (0);	/* no valid card type */
+
+	cs->dbusytimer.function = (void *) hfcsx_dbusy_timer;
+	cs->dbusytimer.data = (long) cs;
+	init_timer(&cs->dbusytimer);
+	INIT_WORK(&cs->tqueue, (void *)(void *) hfcsx_bh, cs);
+	cs->readisac = NULL;
+	cs->writeisac = NULL;
+	cs->readisacfifo = NULL;
+	cs->writeisacfifo = NULL;
+	cs->BC_Read_Reg = NULL;
+	cs->BC_Write_Reg = NULL;
+	cs->irq_func = &hfcsx_interrupt;
+
+	cs->hw.hfcsx.timer.function = (void *) hfcsx_Timer;
+	cs->hw.hfcsx.timer.data = (long) cs;
+	cs->hw.hfcsx.b_fifo_size = 0; /* fifo size still unknown */
+	cs->hw.hfcsx.cirm = ccd_sp_irqtab[cs->irq & 0xF]; /* RAM not evaluated */
+	init_timer(&cs->hw.hfcsx.timer);
+
+	reset_hfcsx(cs);
+	cs->cardmsg = &hfcsx_card_msg;
+	cs->auxcmd = &hfcsx_auxcmd;
+	return (1);
 }
--- diff/drivers/isdn/hisax/hfcscard.c	2003-05-21 11:50:15.000000000 +0100
+++ source/drivers/isdn/hisax/hfcscard.c	2004-02-23 13:56:42.000000000 +0000
@@ -1,4 +1,4 @@
-/* $Id: hfcscard.c,v 1.8.6.2 2001/09/23 22:24:48 kai Exp $
+/* $Id: hfcscard.c,v 1.10.2.4 2004/01/14 16:04:48 keil Exp $
  *
  * low level stuff for hfcs based cards (Teles3c, ACER P10)
  *
@@ -18,33 +18,19 @@
 
 extern const char *CardType[];
 
-static const char *hfcs_revision = "$Revision: 1.8.6.2 $";
-
-static inline u8
-hfcs_read_reg(struct IsdnCardState *cs, int data, u8 reg)
-{
-	return cs->bc_hw_ops->read_reg(cs, data, reg);
-}
-
-static inline void
-hfcs_write_reg(struct IsdnCardState *cs, int data, u8 reg, u8 val)
-{
-	cs->bc_hw_ops->write_reg(cs, data, reg, val);
-}
+static const char *hfcs_revision = "$Revision: 1.10.2.4 $";
 
 static irqreturn_t
 hfcs_interrupt(int intno, void *dev_id, struct pt_regs *regs)
 {
 	struct IsdnCardState *cs = dev_id;
-	u8 val, stat;
+	u_char val, stat;
+	u_long flags;
 
-	if (!cs) {
-		printk(KERN_WARNING "HFCS: Spurious interrupt!\n");
-		return IRQ_NONE;
-	}
+	spin_lock_irqsave(&cs->lock, flags);
 	if ((HFCD_ANYINT | HFCD_BUSY_NBUSY) & 
-		(stat = hfcs_read_reg(cs, HFCD_DATA, HFCD_STAT))) {
-		val = hfcs_read_reg(cs, HFCD_DATA, HFCD_INT_S1);
+		(stat = cs->BC_Read_Reg(cs, HFCD_DATA, HFCD_STAT))) {
+		val = cs->BC_Read_Reg(cs, HFCD_DATA, HFCD_INT_S1);
 		if (cs->debug & L1_DEB_ISAC)
 			debugl1(cs, "HFCS: stat(%02x) s1(%02x)", stat, val);
 		hfc2bds0_interrupt(cs, val);
@@ -52,6 +38,7 @@ hfcs_interrupt(int intno, void *dev_id, 
 		if (cs->debug & L1_DEB_ISAC)
 			debugl1(cs, "HFCS: irq_no_irq stat(%02x)", stat);
 	}
+	spin_unlock_irqrestore(&cs->lock, flags);
 	return IRQ_HANDLED;
 }
 
@@ -65,117 +52,91 @@ hfcs_Timer(struct IsdnCardState *cs)
 */
 }
 
-static void
-hfcs_release(struct IsdnCardState *cs)
+void
+release_io_hfcs(struct IsdnCardState *cs)
 {
 	release2bds0(cs);
 	del_timer(&cs->hw.hfcD.timer);
-	hisax_release_resources(cs);
+	if (cs->hw.hfcD.addr)
+		release_region(cs->hw.hfcD.addr, 2);
 }
 
-static int
-hfcs_reset(struct IsdnCardState *cs)
+static void
+reset_hfcs(struct IsdnCardState *cs)
 {
 	printk(KERN_INFO "HFCS: resetting card\n");
 	cs->hw.hfcD.cirm = HFCD_RESET;
 	if (cs->typ == ISDN_CTYPE_TELES3C)
 		cs->hw.hfcD.cirm |= HFCD_MEM8K;
-	hfcs_write_reg(cs, HFCD_DATA, HFCD_CIRM, cs->hw.hfcD.cirm);	/* Reset On */
-	set_current_state(TASK_UNINTERRUPTIBLE);
-	schedule_timeout((30*HZ)/1000);
+	cs->BC_Write_Reg(cs, HFCD_DATA, HFCD_CIRM, cs->hw.hfcD.cirm);	/* Reset On */
+	mdelay(10);
 	cs->hw.hfcD.cirm = 0;
 	if (cs->typ == ISDN_CTYPE_TELES3C)
 		cs->hw.hfcD.cirm |= HFCD_MEM8K;
-	hfcs_write_reg(cs, HFCD_DATA, HFCD_CIRM, cs->hw.hfcD.cirm);	/* Reset Off */
-	set_current_state(TASK_UNINTERRUPTIBLE);
-	schedule_timeout((10*HZ)/1000);
+	cs->BC_Write_Reg(cs, HFCD_DATA, HFCD_CIRM, cs->hw.hfcD.cirm);	/* Reset Off */
+	mdelay(10);
 	if (cs->typ == ISDN_CTYPE_TELES3C)
 		cs->hw.hfcD.cirm |= HFCD_INTB;
 	else if (cs->typ == ISDN_CTYPE_ACERP10)
 		cs->hw.hfcD.cirm |= HFCD_INTA;
-	hfcs_write_reg(cs, HFCD_DATA, HFCD_CIRM, cs->hw.hfcD.cirm);
-	hfcs_write_reg(cs, HFCD_DATA, HFCD_CLKDEL, 0x0e);
-	hfcs_write_reg(cs, HFCD_DATA, HFCD_TEST, HFCD_AUTO_AWAKE); /* S/T Auto awake */
+	cs->BC_Write_Reg(cs, HFCD_DATA, HFCD_CIRM, cs->hw.hfcD.cirm);
+	cs->BC_Write_Reg(cs, HFCD_DATA, HFCD_CLKDEL, 0x0e);
+	cs->BC_Write_Reg(cs, HFCD_DATA, HFCD_TEST, HFCD_AUTO_AWAKE); /* S/T Auto awake */
 	cs->hw.hfcD.ctmt = HFCD_TIM25 | HFCD_AUTO_TIMER;
-	hfcs_write_reg(cs, HFCD_DATA, HFCD_CTMT, cs->hw.hfcD.ctmt);
+	cs->BC_Write_Reg(cs, HFCD_DATA, HFCD_CTMT, cs->hw.hfcD.ctmt);
 	cs->hw.hfcD.int_m2 = HFCD_IRQ_ENABLE;
 	cs->hw.hfcD.int_m1 = HFCD_INTS_B1TRANS | HFCD_INTS_B2TRANS |
 		HFCD_INTS_DTRANS | HFCD_INTS_B1REC | HFCD_INTS_B2REC |
 		HFCD_INTS_DREC | HFCD_INTS_L1STATE;
-	hfcs_write_reg(cs, HFCD_DATA, HFCD_INT_M1, cs->hw.hfcD.int_m1);
-	hfcs_write_reg(cs, HFCD_DATA, HFCD_INT_M2, cs->hw.hfcD.int_m2);
-	hfcs_write_reg(cs, HFCD_DATA, HFCD_STATES, HFCD_LOAD_STATE | 2); /* HFC ST 2 */
+	cs->BC_Write_Reg(cs, HFCD_DATA, HFCD_INT_M1, cs->hw.hfcD.int_m1);
+	cs->BC_Write_Reg(cs, HFCD_DATA, HFCD_INT_M2, cs->hw.hfcD.int_m2);
+	cs->BC_Write_Reg(cs, HFCD_DATA, HFCD_STATES, HFCD_LOAD_STATE | 2); /* HFC ST 2 */
 	udelay(10);
-	hfcs_write_reg(cs, HFCD_DATA, HFCD_STATES, 2); /* HFC ST 2 */
+	cs->BC_Write_Reg(cs, HFCD_DATA, HFCD_STATES, 2); /* HFC ST 2 */
 	cs->hw.hfcD.mst_m = HFCD_MASTER;
-	hfcs_write_reg(cs, HFCD_DATA, HFCD_MST_MODE, cs->hw.hfcD.mst_m); /* HFC Master */
+	cs->BC_Write_Reg(cs, HFCD_DATA, HFCD_MST_MODE, cs->hw.hfcD.mst_m); /* HFC Master */
 	cs->hw.hfcD.sctrl = 0;
-	hfcs_write_reg(cs, HFCD_DATA, HFCD_SCTRL, cs->hw.hfcD.sctrl);
-	return 0;
+	cs->BC_Write_Reg(cs, HFCD_DATA, HFCD_SCTRL, cs->hw.hfcD.sctrl);
 }
 
-static void
-hfcs_init(struct IsdnCardState *cs)
-{
-	cs->hw.hfcD.timer.expires = jiffies + 75;
-	add_timer(&cs->hw.hfcD.timer);
-	init2bds0(cs);
-	set_current_state(TASK_UNINTERRUPTIBLE);
-	schedule_timeout((80*HZ)/1000);
-	cs->hw.hfcD.ctmt |= HFCD_TIM800;
-	hfcs_write_reg(cs, HFCD_DATA, HFCD_CTMT, cs->hw.hfcD.ctmt); 
-	hfcs_write_reg(cs, HFCD_DATA, HFCD_MST_MODE, cs->hw.hfcD.mst_m);
-}
-
-static struct card_ops hfcs_ops = {
-	.init     = hfcs_init,
-	.reset    = hfcs_reset,
-	.release  = hfcs_release,
-	.irq_func = hfcs_interrupt,
-};
-
-static int __init
-hfcs_probe(struct IsdnCardState *cs, struct IsdnCard *card)
+static int
+hfcs_card_msg(struct IsdnCardState *cs, int mt, void *arg)
 {
-	cs->irq = card->para[0];
-	cs->hw.hfcD.addr = card->para[1];
+	u_long flags;
+	int delay;
 
-	if (!request_io(&cs->rs, cs->hw.hfcD.addr, 2, "HFCS isdn"))
-		goto err;
-
-	printk(KERN_INFO "HFCS: defined at 0x%x IRQ %d\n",
-	       cs->hw.hfcD.addr, cs->irq);
-
-	cs->hw.hfcD.cip = 0;
-	cs->hw.hfcD.int_s1 = 0;
-	cs->hw.hfcD.send = NULL;
-	cs->bcs[0].hw.hfc.send = NULL;
-	cs->bcs[1].hw.hfc.send = NULL;
-	cs->hw.hfcD.dfifosize = 512;
-	cs->dc.hfcd.ph_state = 0;
-	cs->hw.hfcD.fifo = 255;
-
-	if (cs->typ == ISDN_CTYPE_TELES3C) {
-		cs->hw.hfcD.bfifosize = 1024 + 512;
-		/* Teles 16.3c IO ADR is 0x200 | YY0U (YY Bit 15/14 address) */
-		outb(0x00, cs->hw.hfcD.addr);
-		outb(0x56, cs->hw.hfcD.addr | 1);
-	} else if (cs->typ == ISDN_CTYPE_ACERP10) {
-		cs->hw.hfcD.bfifosize = 7*1024 + 512;
-		/* Acer P10 IO ADR is 0x300 */
-		outb(0x00, cs->hw.hfcD.addr);
-		outb(0x57, cs->hw.hfcD.addr | 1);
+	if (cs->debug & L1_DEB_ISAC)
+		debugl1(cs, "HFCS: card_msg %x", mt);
+	switch (mt) {
+		case CARD_RESET:
+			spin_lock_irqsave(&cs->lock, flags);
+			reset_hfcs(cs);
+			spin_unlock_irqrestore(&cs->lock, flags);
+			return(0);
+		case CARD_RELEASE:
+			release_io_hfcs(cs);
+			return(0);
+		case CARD_INIT:
+			delay = (75*HZ)/100 +1;
+			cs->hw.hfcD.timer.expires = jiffies + delay;
+			add_timer(&cs->hw.hfcD.timer);
+			spin_lock_irqsave(&cs->lock, flags);
+			reset_hfcs(cs);
+			init2bds0(cs);
+			spin_unlock_irqrestore(&cs->lock, flags);
+			delay = (80*HZ)/1000 +1;
+			set_current_state(TASK_UNINTERRUPTIBLE);
+			schedule_timeout((80*HZ)/1000);
+			spin_lock_irqsave(&cs->lock, flags);
+			cs->hw.hfcD.ctmt |= HFCD_TIM800;
+			cs->BC_Write_Reg(cs, HFCD_DATA, HFCD_CTMT, cs->hw.hfcD.ctmt); 
+			cs->BC_Write_Reg(cs, HFCD_DATA, HFCD_MST_MODE, cs->hw.hfcD.mst_m);
+			spin_unlock_irqrestore(&cs->lock, flags);
+			return(0);
+		case CARD_TEST:
+			return(0);
 	}
-	set_cs_func(cs);
-	init_timer(&cs->hw.hfcD.timer);
-	cs->hw.hfcD.timer.function = (void *) hfcs_Timer;
-	cs->hw.hfcD.timer.data = (long) cs;
-	hfcs_reset(cs);
-	cs->card_ops = &hfcs_ops;
-	return 0;
- err:
-	hisax_release_resources(cs);
-	return -EBUSY;
+	return(0);
 }
 
 #ifdef __ISAPNP__
@@ -204,13 +165,14 @@ static struct isapnp_device_id hfc_ids[]
 	{ 0, }
 };
 
-static struct isapnp_device_id *hdev = &hfc_ids[0];
+static struct isapnp_device_id *ipid __initdata = &hfc_ids[0];
 static struct pnp_card *pnp_c __devinitdata = NULL;
 #endif
 
 int __init
 setup_hfcs(struct IsdnCard *card)
 {
+	struct IsdnCardState *cs = card->cs;
 	char tmp[64];
 
 	strcpy(tmp, hfcs_revision);
@@ -218,54 +180,88 @@ setup_hfcs(struct IsdnCard *card)
 
 #ifdef __ISAPNP__
 	if (!card->para[1] && isapnp_present()) {
-		struct pnp_card *pb;
-		struct pnp_dev *pd;
+		struct pnp_dev *pnp_d;
+		while(ipid->card_vendor) {
+			if ((pnp_c = pnp_find_card(ipid->card_vendor,
+				ipid->card_device, pnp_c))) {
+				pnp_d = NULL;
+				if ((pnp_d = pnp_find_dev(pnp_c,
+					ipid->vendor, ipid->function, pnp_d))) {
+					int err;
 
-		while(hdev->card_vendor) {
-			if ((pb = pnp_find_card(hdev->card_vendor,
-						hdev->card_device,
-						pnp_c))) {
-				pnp_c = pb;
-				pd = NULL;
-				if ((pd = pnp_find_dev(pnp_c,
-						       hdev->vendor,
-						       hdev->function,
-						       pd))) {
 					printk(KERN_INFO "HiSax: %s detected\n",
-						(char *)hdev->driver_data);
-					if (pnp_device_attach(pd) < 0) {
-						printk(KERN_ERR "HFC PnP: attach failed\n");
-						return 0;
-					}
-					if (pnp_activate_dev(pd) < 0) {
-						printk(KERN_ERR "HFC PnP: activate failed\n");
-						pnp_device_detach(pd);
-						return 0;
+						(char *)ipid->driver_data);
+					pnp_disable_dev(pnp_d);
+					err = pnp_activate_dev(pnp_d);
+					if (err<0) {
+						printk(KERN_WARNING "%s: pnp_activate_dev ret(%d)\n",
+							__FUNCTION__, err);
+						return(0);
 					}
-					if (!pnp_irq_valid(pd, 0) || !pnp_port_valid(pd, 0)) {
+					card->para[1] = pnp_port_start(pnp_d, 0);
+					card->para[0] = pnp_irq(pnp_d, 0);
+					if (!card->para[0] || !card->para[1]) {
 						printk(KERN_ERR "HFC PnP:some resources are missing %ld/%lx\n",
-							pnp_irq(pd, 0), pnp_port_start(pd, 0));
-						pnp_device_detach(pd);
+							card->para[0], card->para[1]);
+						pnp_disable_dev(pnp_d);
 						return(0);
 					}
-					card->para[1] = pnp_port_start(pd, 0);
-					card->para[0] = pnp_irq(pd, 0);
 					break;
 				} else {
 					printk(KERN_ERR "HFC PnP: PnP error card found, no device\n");
 				}
 			}
-			hdev++;
-			pnp_c=NULL;
+			ipid++;
+			pnp_c = NULL;
 		} 
-		if (!hdev->card_vendor) {
+		if (!ipid->card_vendor) {
 			printk(KERN_INFO "HFC PnP: no ISAPnP card found\n");
 			return(0);
 		}
 	}
 #endif
-	if (hfcs_probe(card->cs, card) < 0)
-		return 0;
-	return 1;
-	
+	cs->hw.hfcD.addr = card->para[1] & 0xfffe;
+	cs->irq = card->para[0];
+	cs->hw.hfcD.cip = 0;
+	cs->hw.hfcD.int_s1 = 0;
+	cs->hw.hfcD.send = NULL;
+	cs->bcs[0].hw.hfc.send = NULL;
+	cs->bcs[1].hw.hfc.send = NULL;
+	cs->hw.hfcD.dfifosize = 512;
+	cs->dc.hfcd.ph_state = 0;
+	cs->hw.hfcD.fifo = 255;
+	if (cs->typ == ISDN_CTYPE_TELES3C) {
+		cs->hw.hfcD.bfifosize = 1024 + 512;
+	} else if (cs->typ == ISDN_CTYPE_ACERP10) {
+		cs->hw.hfcD.bfifosize = 7*1024 + 512;
+	} else
+		return (0);
+	if (!request_region(cs->hw.hfcD.addr, 2, "HFCS isdn")) {
+		printk(KERN_WARNING
+		       "HiSax: %s config port %x-%x already in use\n",
+		       CardType[card->typ],
+		       cs->hw.hfcD.addr,
+		       cs->hw.hfcD.addr + 2);
+		return (0);
+	}
+	printk(KERN_INFO
+	       "HFCS: defined at 0x%x IRQ %d HZ %d\n",
+	       cs->hw.hfcD.addr,
+	       cs->irq, HZ);
+	if (cs->typ == ISDN_CTYPE_TELES3C) {
+		/* Teles 16.3c IO ADR is 0x200 | YY0U (YY Bit 15/14 address) */
+		outb(0x00, cs->hw.hfcD.addr);
+		outb(0x56, cs->hw.hfcD.addr | 1);
+	} else if (cs->typ == ISDN_CTYPE_ACERP10) {
+		/* Acer P10 IO ADR is 0x300 */
+		outb(0x00, cs->hw.hfcD.addr);
+		outb(0x57, cs->hw.hfcD.addr | 1);
+	}
+	set_cs_func(cs);
+	cs->hw.hfcD.timer.function = (void *) hfcs_Timer;
+	cs->hw.hfcD.timer.data = (long) cs;
+	init_timer(&cs->hw.hfcD.timer);
+	cs->cardmsg = &hfcs_card_msg;
+	cs->irq_func = &hfcs_interrupt;
+	return (1);
 }
--- diff/drivers/isdn/hisax/hisax.h	2003-09-17 12:28:06.000000000 +0100
+++ source/drivers/isdn/hisax/hisax.h	2004-02-23 13:56:42.000000000 +0000
@@ -1,4 +1,4 @@
-/* $Id: hisax.h,v 1.1.4.1.2.1 2001/12/09 20:18:40 kai Exp $
+/* $Id: hisax.h,v 2.64.2.4 2004/02/11 13:21:33 keil Exp $
  *
  * Basic declarations, defines and prototypes
  *
@@ -6,14 +6,11 @@
  * of the GNU General Public License, incorporated herein by reference.
  *
  */
-
-#ifndef __HISAX_H__
-#define __HISAX_H__
-
 #include <linux/config.h>
 #include <linux/errno.h>
 #include <linux/fs.h>
 #include <linux/major.h>
+#include <asm/segment.h>
 #include <asm/io.h>
 #include <linux/delay.h>
 #include <linux/kernel.h>
@@ -28,7 +25,6 @@
 #include <linux/tty.h>
 #include <linux/serial_reg.h>
 #include <linux/netdevice.h>
-#include <linux/interrupt.h>
 
 #define ERROR_STATISTIC
 
@@ -51,6 +47,11 @@
 #define HW_INFO4_P10	0x0048
 #define HW_RSYNC	0x0060
 #define HW_TESTLOOP	0x0070
+#define CARD_RESET	0x00F0
+#define CARD_INIT	0x00F2
+#define CARD_RELEASE	0x00F3
+#define CARD_TEST	0x00F4
+#define CARD_AUX_IND	0x00F5
 
 #define PH_ACTIVATE	0x0100
 #define PH_DEACTIVATE	0x0110
@@ -68,9 +69,14 @@
 #define DL_FLUSH	0x0224
 #define DL_UNIT_DATA	0x0230
 
+#define MDL_BC_RELEASE  0x0278  // Formula-n enter:now
+#define MDL_BC_ASSIGN   0x027C  // Formula-n enter:now
 #define MDL_ASSIGN	0x0280
 #define MDL_REMOVE	0x0284
 #define MDL_ERROR	0x0288
+#define MDL_INFO_SETUP	0x02E0
+#define MDL_INFO_CONN	0x02E4
+#define MDL_INFO_REL	0x02E8
 
 #define CC_SETUP	0x0300
 #define CC_RESUME	0x0304
@@ -145,35 +151,6 @@
 /* #define I4L_IRQ_FLAG SA_INTERRUPT */
 #define I4L_IRQ_FLAG    0
 
-struct res {
-	struct list_head node;
-	const char *name;
-	unsigned long start, end;
-	unsigned long flags;
-	union {
-		void *ioremap_addr;
-	} r_u;
-};
-
-struct resources {
-	struct list_head res_head;
-};
-
-void
-resources_init(struct resources *rs);
-
-void
-resources_release(struct resources *rs);
-
-unsigned long
-request_io(struct resources *rs, unsigned long start, int len,
-	   const char *name);
-
-void *
-request_mmio(struct resources *rs, unsigned long start, int len,
-	     const char *name);
-
-
 /*
  * Statemachine
  */
@@ -230,9 +207,9 @@ struct Layer1 {
 	long Flags;
 	struct FsmInst l1m;
 	struct FsmTimer	timer;
+	void (*l1l2) (struct PStack *, int, void *);
 	void (*l1hw) (struct PStack *, int, void *);
 	void (*l1tei) (struct PStack *, int, void *);
-	void (*l2l1) (struct PStack *, int, void *);
 	int mode, bc;
 	int delay;
 };
@@ -265,17 +242,18 @@ struct Layer1 {
 struct Layer2 {
 	int tei;
 	int sap;
-	u_int maxlen;
-	unsigned long flag;
-	unsigned int vs, va, vr;
+	int maxlen;
+	u_long flag;
+	spinlock_t lock;
+	u_int vs, va, vr;
 	int rc;
 	unsigned int window;
 	unsigned int sow;
 	struct sk_buff *windowar[MAX_WINDOW];
 	struct sk_buff_head i_queue;
 	struct sk_buff_head ui_queue;
-	void (*l3l2) (struct PStack *, int, void *);
-	void (*l1l2) (struct PStack *, int, void *);
+	void (*l2l1) (struct PStack *, int, void *);
+	void (*l2l3) (struct PStack *, int, void *);
 	void (*l2tei) (struct PStack *, int, void *);
 	struct FsmInst l2m;
 	struct FsmTimer t200, t203;
@@ -285,10 +263,9 @@ struct Layer2 {
 };
 
 struct Layer3 {
-	void (*l4l3) (struct PStack *, int, void *);
-        int  (*l4l3_proto) (struct PStack *, isdn_ctrl *);
+	void (*l3l4) (struct PStack *, int, void *);
         void (*l3ml3) (struct PStack *, int, void *);
-	void (*l2l3) (struct PStack *, int, void *);
+	void (*l3l2) (struct PStack *, int, void *);
 	struct FsmInst l3m;
         struct FsmTimer l3m_timer;
 	struct sk_buff_head squeue;
@@ -300,10 +277,14 @@ struct Layer3 {
 };
 
 struct LLInterface {
-	void (*l3l4) (struct PStack *, int, void *);
+	void (*l4l3) (struct PStack *, int, void *);
+        int  (*l4l3_proto) (struct PStack *, isdn_ctrl *);
 	void *userdata;
+	u_long flag;
 };
 
+#define	FLG_LLI_L1WAKEUP	1
+#define	FLG_LLI_L2WAKEUP	2
 
 struct Management {
 	int	ri;
@@ -316,14 +297,14 @@ struct Management {
 #define NO_CAUSE 254
 
 struct Param {
-	u8 cause;
-	u8 loc;
-	u8 diag[6];
+	u_char cause;
+	u_char loc;
+	u_char diag[6];
 	int bchannel;
 	int chargeinfo;
 	int spv;		/* SPV Flag */
 	setup_parm setup;	/* from isdnif.h numbers and Serviceindicator */
-	u8 moderate;	/* transfer mode and rate (bearer octet 4) */
+	u_char moderate;	/* transfer mode and rate (bearer octet 4) */
 };
 
 
@@ -338,7 +319,7 @@ struct PStack {
 
         /* protocol specific data fields */
         union
-	 { u8 uuuu; /* only as dummy */
+	 { u_char uuuu; /* only as dummy */
 #ifdef CONFIG_HISAX_EURO
            dss1_stk_priv dss1; /* private dss1 data */
 #endif /* CONFIG_HISAX_EURO */              
@@ -362,7 +343,7 @@ struct l3_process {
 
         /* protocol specific data fields */
         union 
-	 { u8 uuuu; /* only when euro not defined, avoiding empty union */
+	 { u_char uuuu; /* only when euro not defined, avoiding empty union */
 #ifdef CONFIG_HISAX_EURO 
            dss1_proc_priv dss1; /* private dss1 data */
 #endif /* CONFIG_HISAX_EURO */            
@@ -373,50 +354,58 @@ struct l3_process {
 };
 
 struct hscx_hw {
-	u8 tsaxr0;
-	u8 tsaxr1;
+	int hscx;
+	int rcvidx;
+	int count;              /* Current skb sent count */
+	u_char *rcvbuf;         /* B-Channel receive Buffer */
+	u_char tsaxr0;
+	u_char tsaxr1;
 };
 
 struct w6692B_hw {
 	int bchan;
+	int rcvidx;
+	int count;              /* Current skb sent count */
+	u_char *rcvbuf;         /* B-Channel receive Buffer */
 };
 
 struct isar_reg {
 	unsigned long Flags;
-	volatile u8 bstat;
-	volatile u8 iis;
-	volatile u8 cmsb;
-	volatile u8 clsb;
-	volatile u8 par[8];
+	volatile u_char bstat;
+	volatile u_char iis;
+	volatile u_char cmsb;
+	volatile u_char clsb;
+	volatile u_char par[8];
 };
 
 struct isar_hw {
 	int dpath;
 	int rcvidx;
+	int txcnt;
 	int mml;
-	u8 state;
-	u8 cmd;
-	u8 mod;
-	u8 newcmd;
-	u8 newmod;
+	u_char state;
+	u_char cmd;
+	u_char mod;
+	u_char newcmd;
+	u_char newmod;
 	char try_mod;
 	struct timer_list ftimer;
-	u8 *rcvbuf;         /* B-Channel receive Buffer */
-	u8 conmsg[16];
+	u_char *rcvbuf;         /* B-Channel receive Buffer */
+	u_char conmsg[16];
 	struct isar_reg *reg;
 };
 
 struct hdlc_stat_reg {
 #ifdef __BIG_ENDIAN
-	u8 fill __attribute__((packed));
-	u8 mode __attribute__((packed));
-	u8 xml  __attribute__((packed));
-	u8 cmd  __attribute__((packed));
-#else
-	u8 cmd  __attribute__((packed));
-	u8 xml  __attribute__((packed));
-	u8 mode __attribute__((packed));
-	u8 fill __attribute__((packed));
+	u_char fill __attribute__((packed));
+	u_char mode __attribute__((packed));
+	u_char xml  __attribute__((packed));
+	u_char cmd  __attribute__((packed));
+#else
+	u_char cmd  __attribute__((packed));
+	u_char xml  __attribute__((packed));
+	u_char mode __attribute__((packed));
+	u_char fill __attribute__((packed));
 #endif
 };
 
@@ -426,6 +415,9 @@ struct hdlc_hw {
 		struct hdlc_stat_reg sr;
 	} ctrl;
 	u_int stat;
+	int rcvidx;
+	int count;              /* Current skb sent count */
+	u_char *rcvbuf;         /* B-Channel receive Buffer */
 };
 
 struct hfcB_hw {
@@ -436,36 +428,35 @@ struct hfcB_hw {
 
 struct tiger_hw {
 	u_int *send;
-	dma_addr_t send_dma;
+	u_int *s_irq;
 	u_int *s_end;
 	u_int *sendp;
 	u_int *rec;
-	dma_addr_t rec_dma;
 	int free;
-	u8 *rcvbuf;
-	u8 *sendbuf;
-	u8 *sp;
+	u_char *rcvbuf;
+	u_char *sendbuf;
+	u_char *sp;
 	int sendcnt;
 	u_int s_tot;
 	u_int r_bitcnt;
 	u_int r_tot;
 	u_int r_err;
 	u_int r_fcs;
-	u8 r_state;
-	u8 r_one;
-	u8 r_val;
-	u8 s_state;
+	u_char r_state;
+	u_char r_one;
+	u_char r_val;
+	u_char s_state;
 };
 
 struct amd7930_hw {
-	u8 *tx_buff;
-	u8 *rv_buff;
+	u_char *tx_buff;
+	u_char *rv_buff;
 	int rv_buff_in;
 	int rv_buff_out;
 	struct sk_buff *rv_skb;
 	struct hdlc_state *hdlc_state;
-	struct work_struct rcv_work;
-	struct work_struct xmt_work;
+	struct work_struct tq_rcv;
+	struct work_struct tq_xmt;
 };
 
 #define BC_FLG_INIT	1
@@ -483,6 +474,8 @@ struct amd7930_hw {
 #define BC_FLG_FTI_RUN	13
 #define BC_FLG_LL_OK	14
 #define BC_FLG_LL_CONN	15
+#define BC_FLG_FTI_FTS	16
+#define BC_FLG_FRH_WAIT	17
 
 #define L1_MODE_NULL	0
 #define L1_MODE_TRANS	1
@@ -496,29 +489,28 @@ struct amd7930_hw {
 struct BCState {
 	int channel;
 	int mode;
-	long Flag;
+	u_long Flag;
 	struct IsdnCardState *cs;
-	int unit;                       /* first or second unit (e.g. HSCX) */
-	int rcvidx;
-	u8 *rcvbuf;                     /* B-Channel receive Buffer */
-	int tx_cnt;  		        /* B-Channel transmit counter */
-	struct sk_buff *tx_skb;         /* B-Channel transmit Buffer */
-	struct sk_buff_head rqueue;	/* B-Channel receive queue */
-	struct sk_buff_head squeue;	/* B-Channel send queue */
-	struct sk_buff_head cmpl_queue;	/* B-Channel send complete queue */
+	int tx_cnt;		/* B-Channel transmit counter */
+	struct sk_buff *tx_skb; /* B-Channel transmit Buffer */
+	struct sk_buff_head rqueue;	/* B-Channel receive Queue */
+	struct sk_buff_head squeue;	/* B-Channel send Queue */
+	int ackcnt;
+	spinlock_t aclock;
 	struct PStack *st;
-	u8 *blog;
-	u8 *conmsg;
+	u_char *blog;
+	u_char *conmsg;
 	struct timer_list transbusy;
-	struct work_struct work;
-	unsigned long event;
+	struct work_struct tqueue;
+	u_long event;
+	int  (*BC_SetStack) (struct PStack *, struct BCState *);
+	void (*BC_Close) (struct BCState *);
 #ifdef ERROR_STATISTIC
 	int err_crc;
 	int err_tx;
 	int err_rdo;
 	int err_inv;
 #endif
-	int count;
 	union {
 		struct hscx_hw hscx;
 		struct hdlc_hw hdlc;
@@ -545,12 +537,12 @@ struct Channel {
 	int data_open;
 	struct l3_process *proc;
 	setup_parm setup;	/* from isdnif.h numbers and Serviceindicator */
-	long Flags;		/* for remembering action done in l4 */
-				/* long req'd for set_bit --RR */
+	u_long Flags;		/* for remembering action done in l4 */
 	int leased;
 };
 
 struct elsa_hw {
+	struct pci_dev *dev;
 	unsigned long base;
 	unsigned int cfg;
 	unsigned int ctrl;
@@ -565,17 +557,17 @@ struct elsa_hw {
 	struct timer_list tl;
 	unsigned int MFlag;
 	struct BCState *bcs;
-	u8 *transbuf;
-	u8 *rcvbuf;
+	u_char *transbuf;
+	u_char *rcvbuf;
 	unsigned int transp;
 	unsigned int rcvp;
 	unsigned int transcnt;
 	unsigned int rcvcnt;
-	u8 IER;
-	u8 FCR;
-	u8 LCR;
-	u8 MCR;
-	u8 ctrl_reg;
+	u_char IER;
+	u_char FCR;
+	u_char LCR;
+	u_char MCR;
+	u_char ctrl_reg;
 };
 
 struct teles3_hw {
@@ -588,8 +580,8 @@ struct teles3_hw {
 
 struct teles0_hw {
 	unsigned int cfg_reg;
+	unsigned long membase;
 	unsigned long phymem;
-	void *membase;
 };
 
 struct avm_hw {
@@ -599,6 +591,7 @@ struct avm_hw {
 	unsigned int isacfifo;
 	unsigned int hscxfifo[2];
 	unsigned int counter;
+	struct pci_dev *dev;
 };
 
 struct ix1_hw {
@@ -617,8 +610,10 @@ struct diva_hw {
 	unsigned int isac;
 	unsigned long hscx_adr;
 	unsigned int hscx;
+	unsigned int status;
 	struct timer_list tl;
-	u8 ctrl_reg;
+	u_char ctrl_reg;
+	struct pci_dev *dev;
 };
 
 struct asus_hw {
@@ -637,9 +632,9 @@ struct hfc_hw {
 	unsigned char cirm;
 	unsigned char ctmt;
 	unsigned char cip;
-	u8 isac_spcr;
+	u_char isac_spcr;
 	struct timer_list timer;
-};
+};	
 
 struct sedl_hw {
 	unsigned int cfg_reg;
@@ -651,6 +646,7 @@ struct sedl_hw {
 	struct isar_reg isar;
 	unsigned int chip;
 	unsigned int bus;
+	struct pci_dev *dev;
 };
 
 struct spt_hw {
@@ -677,9 +673,7 @@ struct njet_hw {
 	unsigned char irqmask0;
 	unsigned char irqstat0;
 	unsigned char last_is0;
-	struct pci_dev *pdev;
-	void (*bc_activate)(struct IsdnCardState *cs, int bc);
-	void (*bc_deactivate)(struct IsdnCardState *cs, int bc);
+	struct pci_dev *dev;
 };
 
 struct hfcPCI_hw {
@@ -700,10 +694,10 @@ struct hfcPCI_hw {
         unsigned char bswapped;
         unsigned char nt_mode;
         int nt_timer;
+        struct pci_dev *dev;
         unsigned char *pci_io; /* start of PCI IO memory */
+        void *share_start; /* shared memory for Fifos start */
         void *fifos; /* FIFO memory */ 
-        dma_addr_t fifos_dma;
-        struct pci_dev* pdev;
         int last_bfifo_cnt[2]; /* marker saving last b-fifo frame count */
 	struct timer_list timer;
 };
@@ -756,12 +750,14 @@ struct hfcD_hw {
 
 struct isurf_hw {
 	unsigned int reset;
-	void *isac;
-	void *isar;
+	unsigned long phymem;
+	unsigned long isac;
+	unsigned long isar;
 	struct isar_reg isar_r;
 };
 
 struct saphir_hw {
+	struct pci_dev *dev;
 	unsigned int cfg_reg;
 	unsigned int ale;
 	unsigned int isac;
@@ -770,6 +766,7 @@ struct saphir_hw {
 };
 
 struct bkm_hw {
+	struct pci_dev *dev;
 	unsigned long base;
 	/* A4T stuff */
 	unsigned long isac_adr;
@@ -782,7 +779,9 @@ struct bkm_hw {
 };	
 
 struct gazel_hw {
+	struct pci_dev *dev;
 	unsigned int cfg_reg;
+	unsigned int pciaddr[2];
         signed   int ipac;
 	signed   int isac;
 	signed   int hscx[2];
@@ -793,6 +792,7 @@ struct gazel_hw {
 };
 
 struct w6692_hw {
+	struct pci_dev *dev;
 	unsigned int iobase;
 	struct timer_list timer;
 };
@@ -812,25 +812,25 @@ struct te_hw {
 
 struct arcofi_msg {
 	struct arcofi_msg *next;
-	u8 receive;
-	u8 len;
-	u8 msg[10];
+	u_char receive;
+	u_char len;
+	u_char msg[10];
 };
 
 struct isac_chip {
 	int ph_state;
-	u8 *mon_tx;
-	u8 *mon_rx;
+	u_char *mon_tx;
+	u_char *mon_rx;
 	int mon_txp;
 	int mon_txc;
 	int mon_rxp;
 	struct arcofi_msg *arcofi_list;
 	struct timer_list arcofitimer;
 	wait_queue_head_t arcofi_wait;
-	u8 arcofi_bc;
-	u8 arcofi_state;
-	u8 mocr;
-	u8 adf2;
+	u_char arcofi_bc;
+	u_char arcofi_state;
+	u_char mocr;
+	u_char adf2;
 };
 
 struct hfcd_chip {
@@ -850,80 +850,30 @@ struct w6692_chip {
 };
 
 struct amd7930_chip {
-	u8 lmr1;
-	u8 ph_state;
-	u8 old_state;
-	u8 flg_t3;
+	u_char lmr1;
+	u_char ph_state;
+	u_char old_state;
+	u_char flg_t3;
 	unsigned int tx_xmtlen;
 	struct timer_list timer3;
-	void (*ph_command) (struct IsdnCardState *, u8, char *);
-	void (*setIrqMask) (struct IsdnCardState *, u8);
+	void (*ph_command) (struct IsdnCardState *, u_char, char *);
+	void (*setIrqMask) (struct IsdnCardState *, u_char);
 };
 
 struct icc_chip {
 	int ph_state;
-	u8 *mon_tx;
-	u8 *mon_rx;
+	u_char *mon_tx;
+	u_char *mon_rx;
 	int mon_txp;
 	int mon_txc;
 	int mon_rxp;
 	struct arcofi_msg *arcofi_list;
 	struct timer_list arcofitimer;
 	wait_queue_head_t arcofi_wait;
-	u8 arcofi_bc;
-	u8 arcofi_state;
-	u8 mocr;
-	u8 adf2;
-};
-
-struct IsdnCardState;
-
-/* Methods provided by driver for a specific card */
-
-struct card_ops {
-	void   (*init)       (struct IsdnCardState *);
-	void   (*test)       (struct IsdnCardState *);
-	int    (*reset)      (struct IsdnCardState *);
-	void   (*release)    (struct IsdnCardState *);
-	void   (*aux_ind)    (struct IsdnCardState *, void *);
-	void   (*led_handler)(struct IsdnCardState *);
-	irqreturn_t (*irq_func)   (int, void *, struct pt_regs *);
-};
-
-/* Card specific drivers provide methods to access the
- * chips to the chip drivers */
-
-struct bc_hw_ops {
-	u8     (*read_reg)   (struct IsdnCardState *, int, u8);
-	void   (*write_reg)  (struct IsdnCardState *, int, u8, u8);
-	void   (*read_fifo)  (struct IsdnCardState *, int, u8 *, int);
-	void   (*write_fifo) (struct IsdnCardState *, int, u8 *, int);
-};
-
-struct dc_hw_ops {
-	u8     (*read_reg)   (struct IsdnCardState *, u8);
-	void   (*write_reg)  (struct IsdnCardState *, u8, u8);
-	void   (*read_fifo)  (struct IsdnCardState *, u8 *, int);
-	void   (*write_fifo) (struct IsdnCardState *, u8 *, int);
-};
-
-/* Methods provided to shared B-channel FIFO handling */
-
-struct bc_l1_ops {
-	void   (*fill_fifo)  (struct BCState *);
-	int    (*open)       (struct PStack *, struct BCState *);
-	void   (*close)      (struct BCState *);
-};
-
-/* Methods provided to shared D-channel FIFO handling */
-
-struct dc_l1_ops {
-	void   (*fill_fifo)  (struct IsdnCardState *);
-	int    (*open)       (struct PStack *, struct IsdnCardState *);
-	void   (*close)      (struct IsdnCardState *);
-
-	void   (*bh_func)    (void *);
-	void   (*dbusy_func) (struct IsdnCardState *);
+	u_char arcofi_bc;
+	u_char arcofi_state;
+	u_char mocr;
+	u_char adf2;
 };
 
 #define HW_IOM1			0
@@ -933,25 +883,22 @@ struct dc_l1_ops {
 #define FLG_TWO_DCHAN		4
 #define FLG_L1_DBUSY		5
 #define FLG_DBUSY_TIMER 	6
+#define FLG_LOCK_ATOMIC 	7
 #define FLG_ARCOFI_TIMER	8
 #define FLG_ARCOFI_ERROR	9
 #define FLG_HW_L1_UINT		10
-#define FLG_BUGGY_PLX9050       11
 
 struct IsdnCardState {
-	unsigned char typ;
-	unsigned char subtyp;
-	spinlock_t lock;
-	struct card_ops *card_ops;
-	int protocol;
-	struct resources rs;
-	unsigned int irq;
-	unsigned long irq_flags;
-	int status;
-	long HW_Flags;
-	int *busy_flag;
-        int chanlimit; /* limited number of B-chans to use */
-        int logecho; /* log echo if supported by card */
+	spinlock_t	lock;
+	u_char		typ;
+	u_char		subtyp;
+	int		protocol;
+	u_int		irq;
+	u_long		irq_flags;
+	u_long		HW_Flags;
+	int		*busy_flag;
+        int		chanlimit; /* limited number of B-chans to use */
+        int		logecho; /* log echo if supported by card */
 	union {
 		struct elsa_hw elsa;
 		struct teles0_hw teles0;
@@ -979,25 +926,32 @@ struct IsdnCardState {
 		struct w6692_hw w6692;
 		struct hisax_d_if *hisax_d_if;
 	} hw;
-	int myid;
-	isdn_if iif;
-	u8 *status_buf;
-	u8 *status_read;
-	u8 *status_write;
-	u8 *status_end;
-	struct dc_hw_ops *dc_hw_ops;
-	struct bc_hw_ops *bc_hw_ops;
-	struct dc_l1_ops *dc_l1_ops;
-	struct bc_l1_ops *bc_l1_ops;
-	int    (*cardmsg) (struct IsdnCardState *, int, void *);
-	int    (*auxcmd) (struct IsdnCardState *, isdn_ctrl *);
-	struct Channel channel[2+MAX_WAITING_CALLS];
-	struct BCState bcs[2+MAX_WAITING_CALLS];
-	struct PStack *stlist;
+	int		myid;
+	isdn_if		iif;
+	spinlock_t	statlock;
+	u_char		*status_buf;
+	u_char		*status_read;
+	u_char		*status_write;
+	u_char		*status_end;
+	u_char		(*readisac) (struct IsdnCardState *, u_char);
+	void		(*writeisac) (struct IsdnCardState *, u_char, u_char);
+	void		(*readisacfifo) (struct IsdnCardState *, u_char *, int);
+	void		(*writeisacfifo) (struct IsdnCardState *, u_char *, int);
+	u_char		(*BC_Read_Reg) (struct IsdnCardState *, int, u_char);
+	void		(*BC_Write_Reg) (struct IsdnCardState *, int, u_char, u_char);
+	void		(*BC_Send_Data) (struct BCState *);
+	int		(*cardmsg) (struct IsdnCardState *, int, void *);
+	void		(*setstack_d) (struct PStack *, struct IsdnCardState *);
+	void		(*DC_Close) (struct IsdnCardState *);
+	int		(*irq_func) (int, void *, struct pt_regs *);
+	int		(*auxcmd) (struct IsdnCardState *, isdn_ctrl *);
+	struct Channel	channel[2+MAX_WAITING_CALLS];
+	struct BCState	bcs[2+MAX_WAITING_CALLS];
+	struct PStack	*stlist;
 	struct sk_buff_head rq, sq; /* D-channel queues */
-	int cardnr;
-	char *dlog;
-	int debug;
+	int		cardnr;
+	char		*dlog;
+	int		debug;
 	union {
 		struct isac_chip isac;
 		struct hfcd_chip hfcd;
@@ -1007,83 +961,287 @@ struct IsdnCardState {
 		struct amd7930_chip amd7930;
 		struct icc_chip icc;
 	} dc;
-	u8 *rcvbuf;
-	int rcvidx;
-	struct sk_buff *tx_skb;
-	int tx_cnt;
-	long event;
-	struct work_struct work;
+	u_char		*rcvbuf;
+	int		rcvidx;
+	struct sk_buff	*tx_skb;
+	int		tx_cnt;
+	u_long		event;
+	struct work_struct tqueue;
 	struct timer_list dbusytimer;
 #ifdef ERROR_STATISTIC
-	int err_crc;
-	int err_tx;
-	int err_rx;
+	int		err_crc;
+	int		err_tx;
+	int		err_rx;
 #endif
 };
 
-void
-hisax_release_resources(struct IsdnCardState *cs);
+
+#define  schedule_event(s, ev)	do {test_and_set_bit(ev, &s->event);schedule_work(&s->tqueue); } while(0)
 
 #define  MON0_RX	1
 #define  MON1_RX	2
 #define  MON0_TX	4
 #define  MON1_TX	8
 
-#define  ISDN_CTYPE_16_0	1
-#define  ISDN_CTYPE_8_0		2
-#define  ISDN_CTYPE_16_3	3
-#define  ISDN_CTYPE_PNP		4
-#define  ISDN_CTYPE_A1		5
-#define  ISDN_CTYPE_ELSA	6
-#define  ISDN_CTYPE_ELSA_PNP	7
-#define  ISDN_CTYPE_TELESPCMCIA	8
-#define  ISDN_CTYPE_IX1MICROR2	9
-#define  ISDN_CTYPE_ELSA_PCMCIA	10
-#define  ISDN_CTYPE_DIEHLDIVA	11
-#define  ISDN_CTYPE_ASUSCOM	12
-#define  ISDN_CTYPE_TELEINT	13
-#define  ISDN_CTYPE_TELES3C	14
-#define  ISDN_CTYPE_SEDLBAUER	15
-#define  ISDN_CTYPE_SPORTSTER	16
-#define  ISDN_CTYPE_MIC		17
-#define  ISDN_CTYPE_ELSA_PCI	18
-#define  ISDN_CTYPE_COMPAQ_ISA	19
-#define  ISDN_CTYPE_NETJET_S	20
-#define  ISDN_CTYPE_TELESPCI	21
-#define  ISDN_CTYPE_SEDLBAUER_PCMCIA	22
-#define  ISDN_CTYPE_AMD7930	23
-#define  ISDN_CTYPE_NICCY	24
-#define  ISDN_CTYPE_S0BOX	25
-#define  ISDN_CTYPE_A1_PCMCIA	26
-#define  ISDN_CTYPE_FRITZPCI	27
-#define  ISDN_CTYPE_SEDLBAUER_FAX     28
-#define  ISDN_CTYPE_ISURF	29
-#define  ISDN_CTYPE_ACERP10	30
-#define  ISDN_CTYPE_HSTSAPHIR	31
-#define	 ISDN_CTYPE_BKM_A4T	32
-#define	 ISDN_CTYPE_SCT_QUADRO	33
-#define  ISDN_CTYPE_GAZEL	34
-#define  ISDN_CTYPE_HFC_PCI	35
-#define  ISDN_CTYPE_W6692	36
-#define  ISDN_CTYPE_HFC_SX      37
-#define  ISDN_CTYPE_NETJET_U	38
-#define  ISDN_CTYPE_HFC_SP_PCMCIA      39
-#define  ISDN_CTYPE_DYNAMIC     40
-#define  ISDN_CTYPE_ENTERNOW	41
-#define  ISDN_CTYPE_COUNT	41
 
+#ifdef ISDN_CHIP_ISAC
+#undef ISDN_CHIP_ISAC
+#endif
+
+#ifdef	CONFIG_HISAX_16_0
+#define  CARD_TELES0 1
+#ifndef ISDN_CHIP_ISAC
+#define ISDN_CHIP_ISAC 1
+#endif
+#else
+#define  CARD_TELES0  0
+#endif
+
+#ifdef	CONFIG_HISAX_16_3
+#define  CARD_TELES3 1
+#ifndef ISDN_CHIP_ISAC
+#define ISDN_CHIP_ISAC 1
+#endif
+#else
+#define  CARD_TELES3  0
+#endif
+
+#ifdef	CONFIG_HISAX_TELESPCI
+#define  CARD_TELESPCI 1
+#ifndef ISDN_CHIP_ISAC
+#define ISDN_CHIP_ISAC 1
+#endif
+#else
+#define  CARD_TELESPCI  0
+#endif
+
+#ifdef	CONFIG_HISAX_AVM_A1
+#define  CARD_AVM_A1 1
+#ifndef ISDN_CHIP_ISAC
+#define ISDN_CHIP_ISAC 1
+#endif
+#else
+#define  CARD_AVM_A1  0
+#endif
+
+#ifdef	CONFIG_HISAX_AVM_A1_PCMCIA
+#define  CARD_AVM_A1_PCMCIA 1
+#ifndef ISDN_CHIP_ISAC
+#define ISDN_CHIP_ISAC 1
+#endif
+#else
+#define  CARD_AVM_A1_PCMCIA  0
+#endif
+
+#ifdef	CONFIG_HISAX_FRITZPCI
+#define  CARD_FRITZPCI 1
+#ifndef ISDN_CHIP_ISAC
+#define ISDN_CHIP_ISAC 1
+#endif
+#else
+#define  CARD_FRITZPCI  0
+#endif
+
+#ifdef	CONFIG_HISAX_ELSA
+#define  CARD_ELSA 1
+#ifndef ISDN_CHIP_ISAC
+#define ISDN_CHIP_ISAC 1
+#endif
+#else
+#define  CARD_ELSA  0
+#endif
+
+#ifdef	CONFIG_HISAX_IX1MICROR2
+#define	CARD_IX1MICROR2 1
+#ifndef ISDN_CHIP_ISAC
+#define ISDN_CHIP_ISAC 1
+#endif
+#else
+#define CARD_IX1MICROR2 0
+#endif
+
+#ifdef  CONFIG_HISAX_DIEHLDIVA
+#define CARD_DIEHLDIVA 1
+#ifndef ISDN_CHIP_ISAC
+#define ISDN_CHIP_ISAC 1
+#endif
+#else
+#define CARD_DIEHLDIVA 0
+#endif
+
+#ifdef  CONFIG_HISAX_ASUSCOM
+#define CARD_ASUSCOM 1
+#ifndef ISDN_CHIP_ISAC
+#define ISDN_CHIP_ISAC 1
+#endif
+#else
+#define CARD_ASUSCOM 0
+#endif
+
+#ifdef  CONFIG_HISAX_TELEINT
+#define CARD_TELEINT 1
+#ifndef ISDN_CHIP_ISAC
+#define ISDN_CHIP_ISAC 1
+#endif
+#else
+#define CARD_TELEINT 0
+#endif
+
+#ifdef  CONFIG_HISAX_SEDLBAUER
+#define CARD_SEDLBAUER 1
+#ifndef ISDN_CHIP_ISAC
+#define ISDN_CHIP_ISAC 1
+#endif
+#else
+#define CARD_SEDLBAUER 0
+#endif
+
+#ifdef  CONFIG_HISAX_SPORTSTER
+#define CARD_SPORTSTER 1
+#ifndef ISDN_CHIP_ISAC
+#define ISDN_CHIP_ISAC 1
+#endif
+#else
+#define CARD_SPORTSTER 0
+#endif
+
+#ifdef  CONFIG_HISAX_MIC
+#define CARD_MIC 1
+#ifndef ISDN_CHIP_ISAC
+#define ISDN_CHIP_ISAC 1
+#endif
+#else
+#define CARD_MIC 0
+#endif
+
+#ifdef  CONFIG_HISAX_NETJET
+#define CARD_NETJET_S 1
+#ifndef ISDN_CHIP_ISAC
+#define ISDN_CHIP_ISAC 1
+#endif
+#else
+#define CARD_NETJET_S 0
+#endif
+
+#ifdef	CONFIG_HISAX_HFCS
+#define  CARD_HFCS 1
+#else
+#define  CARD_HFCS 0
+#endif
+
+#ifdef	CONFIG_HISAX_HFC_PCI
+#define  CARD_HFC_PCI 1
+#else
+#define  CARD_HFC_PCI 0
+#endif
+
+#ifdef	CONFIG_HISAX_HFC_SX
+#define  CARD_HFC_SX 1
+#else
+#define  CARD_HFC_SX 0
+#endif
+
+#ifdef  CONFIG_HISAX_AMD7930
+#define CARD_AMD7930 1
+#else
+#define CARD_AMD7930 0
+#endif
+
+#ifdef	CONFIG_HISAX_NICCY
+#define	CARD_NICCY 1
+#ifndef ISDN_CHIP_ISAC
+#define ISDN_CHIP_ISAC 1
+#endif
+#else
+#define CARD_NICCY 0
+#endif
+
+#ifdef	CONFIG_HISAX_ISURF
+#define	CARD_ISURF 1
+#ifndef ISDN_CHIP_ISAC
+#define ISDN_CHIP_ISAC 1
+#endif
+#else
+#define CARD_ISURF 0
+#endif
+
+#ifdef	CONFIG_HISAX_S0BOX
+#define	CARD_S0BOX 1
+#ifndef ISDN_CHIP_ISAC
+#define ISDN_CHIP_ISAC 1
+#endif
+#else
+#define CARD_S0BOX 0
+#endif
+
+#ifdef	CONFIG_HISAX_HSTSAPHIR
+#define	CARD_HSTSAPHIR 1
+#ifndef ISDN_CHIP_ISAC
+#define ISDN_CHIP_ISAC 1
+#endif
+#else
+#define CARD_HSTSAPHIR 0
+#endif
 
 #ifdef	CONFIG_HISAX_TESTEMU
+#define	CARD_TESTEMU 1
 #define ISDN_CTYPE_TESTEMU 99
 #undef ISDN_CTYPE_COUNT
 #define  ISDN_CTYPE_COUNT ISDN_CTYPE_TESTEMU
+#else
+#define CARD_TESTEMU 0
+#endif
+
+#ifdef	CONFIG_HISAX_BKM_A4T
+#define	CARD_BKM_A4T 1
+#ifndef ISDN_CHIP_ISAC
+#define ISDN_CHIP_ISAC 1
+#endif
+#else
+#define CARD_BKM_A4T 0
+#endif
+
+#ifdef	CONFIG_HISAX_SCT_QUADRO
+#define	CARD_SCT_QUADRO 1
+#ifndef ISDN_CHIP_ISAC
+#define ISDN_CHIP_ISAC 1
+#endif
+#else
+#define CARD_SCT_QUADRO 0
+#endif
+
+#ifdef	CONFIG_HISAX_GAZEL
+#define  CARD_GAZEL 1
+#ifndef ISDN_CHIP_ISAC
+#define ISDN_CHIP_ISAC 1
+#endif
+#else
+#define  CARD_GAZEL  0
+#endif
+
+#ifdef	CONFIG_HISAX_W6692
+#define	CARD_W6692	1
+#ifndef	ISDN_CHIP_W6692
+#define	ISDN_CHIP_W6692	1
+#endif
+#else
+#define	CARD_W6692	0
 #endif
 
 #ifdef  CONFIG_HISAX_NETJET_U
+#define CARD_NETJET_U 1
+#ifndef ISDN_CHIP_ICC
+#define ISDN_CHIP_ICC 1
+#endif
 #ifndef HISAX_UINTERFACE
 #define HISAX_UINTERFACE 1
 #endif
 #else
+#define CARD_NETJET_U 0
+#endif
+
+#ifdef CONFIG_HISAX_ENTERNOW_PCI
+#define CARD_FN_ENTERNOW_PCI 1
 #endif
 
 #define TEI_PER_CARD 1
@@ -1108,12 +1266,7 @@ hisax_release_resources(struct IsdnCardS
 extern void Logl2Frame(struct IsdnCardState *cs, struct sk_buff *skb, char *buf, int dir);
 #endif
 
-struct IsdnCard {
-	int typ;
-	int protocol;		/* EDSS1, 1TR6 or NI1 */
-	unsigned long para[4];
-	struct IsdnCardState *cs;
-};
+#include "hisax_cfg.h"
 
 void init_bcstate(struct IsdnCardState *cs, int bc);
 
@@ -1131,13 +1284,14 @@ void setstack_isdnl2(struct PStack *st, 
 void releasestack_isdnl2(struct PStack *st);
 void setstack_transl2(struct PStack *st);
 void releasestack_transl2(struct PStack *st);
+void lli_writewakeup(struct PStack *st, int len);
 
 void setstack_l3dc(struct PStack *st, struct Channel *chanp);
 void setstack_l3bc(struct PStack *st, struct Channel *chanp);
 void releasestack_isdnl3(struct PStack *st);
 
-u8 *findie(u8 * p, int size, u8 ie, int wanted_set);
-int getcallref(u8 * p);
+u_char *findie(u_char * p, int size, u_char ie, int wanted_set);
+int getcallref(u_char * p);
 int newcallref(void);
 
 int FsmNew(struct Fsm *fsm, struct FsmNode *fnlist, int fncount);
@@ -1155,12 +1309,15 @@ int jiftime(char *s, long mark);
 int HiSax_command(isdn_ctrl * ic);
 int HiSax_writebuf_skb(int id, int chan, int ack, struct sk_buff *skb);
 void HiSax_putstatus(struct IsdnCardState *cs, char *head, char *fmt, ...);
-void VHiSax_putstatus(struct IsdnCardState *cs, char *head, const char *fmt, va_list args);
+void VHiSax_putstatus(struct IsdnCardState *cs, char *head, char *fmt, va_list args);
 void HiSax_reportcard(int cardnr, int sel);
-int QuickHex(char *txt, u8 * p, int cnt);
-void LogFrame(struct IsdnCardState *cs, u8 * p, int size);
+int QuickHex(char *txt, u_char * p, int cnt);
+void LogFrame(struct IsdnCardState *cs, u_char * p, int size);
 void dlogframe(struct IsdnCardState *cs, struct sk_buff *skb, int dir);
-void iecpy(u8 * dest, u8 * iestart, int ieoffset);
+void iecpy(u_char * dest, u_char * iestart, int ieoffset);
+#ifdef ISDN_CHIP_ISAC
+void setstack_isac(struct PStack *st, struct IsdnCardState *cs);
+#endif	/* ISDN_CHIP_ISAC */
 #endif	/* __KERNEL__ */
 
 #define HZDELAY(jiffs) {int tout = jiffs; while (tout--) udelay(1000000/HZ);}
@@ -1182,43 +1339,3 @@ void release_tei(struct IsdnCardState *c
 char *HiSax_getrev(const char *revision);
 int TeiNew(void);
 void TeiFree(void);
-int certification_check(int output);
-
-static inline void
-L2L1(struct PStack *st, int pr, void *arg)
-{
-	st->l1.l2l1(st, pr, arg);
-}
-
-static inline void
-L1L2(struct PStack *st, int pr, void *arg)
-{
-	st->l2.l1l2(st, pr, arg);
-}
-
-static inline void
-L3L2(struct PStack *st, int pr, void *arg)
-{
-	st->l2.l3l2(st, pr, arg);
-}
-
-static inline void
-L2L3(struct PStack *st, int pr, void *arg)
-{
-	st->l3.l2l3(st, pr, arg);
-}
-
-static inline void
-L3L4(struct PStack *st, int pr, void *arg)
-{
-	st->lli.l3l4(st, pr, arg);
-}
-
-static inline void
-L4L3(struct PStack *st, int pr, void *arg)
-{
-	st->l3.l4l3(st, pr, arg);
-}
-
-
-#endif
--- diff/drivers/isdn/hisax/hisax_debug.h	2003-01-13 14:18:15.000000000 +0000
+++ source/drivers/isdn/hisax/hisax_debug.h	2004-02-23 13:56:42.000000000 +0000
@@ -39,7 +39,7 @@ printk(KERN_DEBUG "%s: " format "\n" , _
 
 
 static void __attribute__((unused))
-dump_packet(const char *name,const u8 *data,int pkt_len)
+dump_packet(const char *name,const u_char *data,int pkt_len)
 {
 #define DUMP_HDR_SIZE 20
 #define DUMP_TLR_SIZE 8
--- diff/drivers/isdn/hisax/hisax_fcpcipnp.c	2003-09-17 12:28:06.000000000 +0100
+++ source/drivers/isdn/hisax/hisax_fcpcipnp.c	2004-02-23 13:56:42.000000000 +0000
@@ -27,22 +27,26 @@
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/pci.h>
-#include <linux/pnp.h>
+#include <linux/isapnp.h>
 #include <linux/kmod.h>
 #include <linux/slab.h>
 #include <linux/skbuff.h>
 #include <linux/netdevice.h>
+#include <linux/delay.h>
+
+#include <asm/io.h>
+
 #include "hisax_fcpcipnp.h"
 
 // debugging cruft
 #define __debug_variable debug
 #include "hisax_debug.h"
 
-// #define CONFIG_PNP_CARD	1
-
 #ifdef CONFIG_HISAX_DEBUG
 static int debug = 0;
+/* static int hdlcfifosize = 32; */
 MODULE_PARM(debug, "i");
+/* MODULE_PARM(hdlcfifosize, "i"); */
 #endif
 
 MODULE_AUTHOR("Kai Germaschewski <kai.germaschewski@gmx.de>/Karsten Keil <kkeil@suse.de>");
@@ -65,6 +69,17 @@ static struct pci_device_id fcpci_ids[] 
 
 MODULE_DEVICE_TABLE(pci, fcpci_ids);
 
+#ifdef __ISAPNP__
+static struct pnp_device_id fcpnp_ids[] __devinitdata = {
+	{ 
+		.id		= "AVM0900",
+		.driver_data	= (unsigned long) "Fritz!Card PnP",
+	},
+};
+
+MODULE_DEVICE_TABLE(isapnp, fcpnp_ids);
+#endif
+
 static int protocol = 2;       /* EURO-ISDN Default */
 MODULE_PARM(protocol, "i");
 MODULE_LICENSE("GPL");
@@ -115,12 +130,12 @@ MODULE_LICENSE("GPL");
 #define  HDLC_STAT_RDO		0x10
 #define  HDLC_STAT_CRCVFRRAB	0x0E
 #define  HDLC_STAT_CRCVFR	0x06
-#define  HDLC_STAT_RML_MASK	0x3f00
+#define  HDLC_STAT_RML_MASK	0xff00
 
 #define  HDLC_CMD_XRS		0x80
 #define  HDLC_CMD_XME		0x01
 #define  HDLC_CMD_RRS		0x20
-#define  HDLC_CMD_XML_MASK	0x3f00
+#define  HDLC_CMD_XML_MASK	0xff00
 
 #define  AVM_HDLC_FIFO_1        0x10
 #define  AVM_HDLC_FIFO_2        0x18
@@ -367,8 +382,7 @@ static void hdlc_fill_fifo(struct fritz_
 {
 	struct fritz_adapter *adapter = bcs->adapter;
 	struct sk_buff *skb = bcs->tx_skb;
-	u_int count;
-	u_int fifo_size = 32;
+	int count;
 	unsigned long flags;
 	unsigned char *p;
 
@@ -378,8 +392,8 @@ static void hdlc_fill_fifo(struct fritz_
 		BUG();
 
 	bcs->ctrl.sr.cmd &= ~HDLC_CMD_XME;
-	if (bcs->tx_skb->len > fifo_size) {
-		count = fifo_size;
+	if (bcs->tx_skb->len > bcs->fifo_size) {
+		count = bcs->fifo_size;
 	} else {
 		count = bcs->tx_skb->len;
 		if (bcs->mode != L1_MODE_TRANS)
@@ -389,7 +403,7 @@ static void hdlc_fill_fifo(struct fritz_
 	p = bcs->tx_skb->data;
 	skb_pull(bcs->tx_skb, count);
 	bcs->tx_cnt += count;
-	bcs->ctrl.sr.xml = ((count == fifo_size) ? 0 : count);
+	bcs->ctrl.sr.xml = ((count == bcs->fifo_size) ? 0 : count);
 
 	switch (adapter->type) {
 	case AVM_FRITZ_PCI:
@@ -470,7 +484,7 @@ static inline void hdlc_rpr_irq(struct f
 
 	len = (stat & HDLC_STAT_RML_MASK) >> 8;
 	if (len == 0)
-		len = 32;
+		len = bcs->fifo_size;
 
 	hdlc_empty_fifo(bcs, len);
 
@@ -498,6 +512,7 @@ static inline void hdlc_rpr_irq(struct f
 static inline void hdlc_xdu_irq(struct fritz_bcs *bcs)
 {
 	struct fritz_adapter *adapter = bcs->adapter;
+	
 
 	/* Here we lost an TX interrupt, so
 	 * restart transmitting the whole frame.
@@ -506,14 +521,17 @@ static inline void hdlc_xdu_irq(struct f
 	bcs->ctrl.sr.cmd |= HDLC_CMD_XRS;
 	adapter->write_ctrl(bcs, 1);
 	bcs->ctrl.sr.cmd &= ~HDLC_CMD_XRS;
-	adapter->write_ctrl(bcs, 1);
 
 	if (!bcs->tx_skb) {
 		DBG(0x10, "XDU without skb");
+		adapter->write_ctrl(bcs, 1);
 		return;
 	}
-	skb_push(bcs->tx_skb, bcs->tx_cnt);
-	bcs->tx_cnt = 0;
+	/* only hdlc restarts the frame, transparent mode must continue */
+	if (bcs->mode == L1_MODE_HDLC) {
+		skb_push(bcs->tx_skb, bcs->tx_cnt);
+		bcs->tx_cnt = 0;
+	}
 }
 
 static inline void hdlc_xpr_irq(struct fritz_bcs *bcs)
@@ -530,7 +548,8 @@ static inline void hdlc_xpr_irq(struct f
 	}
 	bcs->tx_cnt = 0;
 	bcs->tx_skb = NULL;
-	B_L1L2(bcs, PH_DATA | CONFIRM, skb);
+	B_L1L2(bcs, PH_DATA | CONFIRM, (void *) skb->truesize);
+	dev_kfree_skb_irq(skb);
 }
 
 static void hdlc_irq_one(struct fritz_bcs *bcs, u32 stat)
@@ -543,6 +562,8 @@ static void hdlc_irq_one(struct fritz_bc
 	if (stat & HDLC_INT_XDU) {
 		DBG(0x10, "XDU");
 		hdlc_xdu_irq(bcs);
+		hdlc_xpr_irq(bcs);
+		return;
 	}
 	if (stat & HDLC_INT_XPR) {
 		DBG(0x10, "XPR");
@@ -573,6 +594,7 @@ static void modehdlc(struct fritz_bcs *b
 	if (bcs->mode == mode)
 		return;
 
+	bcs->fifo_size = 32;
 	bcs->ctrl.ctrl = 0;
 	bcs->ctrl.sr.cmd  = HDLC_CMD_XRS | HDLC_CMD_RRS;
 	switch (mode) {
@@ -585,10 +607,11 @@ static void modehdlc(struct fritz_bcs *b
 		bcs->rcvidx = 0;
 		bcs->tx_cnt = 0;
 		bcs->tx_skb = NULL;
-		if (mode == L1_MODE_TRANS)
+		if (mode == L1_MODE_TRANS) {
 			bcs->ctrl.sr.mode = HDLC_MODE_TRANS;
-		else
+		} else {
 			bcs->ctrl.sr.mode = HDLC_MODE_ITF_FLG;
+		}
 		adapter->write_ctrl(bcs, 5);
 		bcs->ctrl.sr.cmd = HDLC_CMD_XRS;
 		adapter->write_ctrl(bcs, 1);
@@ -631,7 +654,8 @@ static void fritz_b_l2l1(struct hisax_if
 
 // ----------------------------------------------------------------------
 
-static irqreturn_t fcpci2_irq(int intno, void *dev, struct pt_regs *regs)
+static irqreturn_t
+fcpci2_irq(int intno, void *dev, struct pt_regs *regs)
 {
 	struct fritz_adapter *adapter = dev;
 	unsigned char val;
@@ -643,13 +667,15 @@ static irqreturn_t fcpci2_irq(int intno,
 	DBG(2, "STATUS0 %#x", val);
 	if (val & AVM_STATUS0_IRQ_ISAC)
 		isacsx_irq(&adapter->isac);
-
 	if (val & AVM_STATUS0_IRQ_HDLC)
 		hdlc_irq(adapter);
+	if (val & AVM_STATUS0_IRQ_ISAC)
+		isacsx_irq(&adapter->isac);
 	return IRQ_HANDLED;
 }
 
-static irqreturn_t fcpci_irq(int intno, void *dev, struct pt_regs *regs)
+static irqreturn_t
+fcpci_irq(int intno, void *dev, struct pt_regs *regs)
 {
 	struct fritz_adapter *adapter = dev;
 	unsigned char sval;
@@ -683,8 +709,7 @@ static inline void fcpci_init(struct fri
 
 	outb(AVM_STATUS1_ENA_IOM | adapter->irq, 
 	     adapter->io + AVM_STATUS1);
-	set_current_state(TASK_UNINTERRUPTIBLE);
-	schedule_timeout(50*HZ / 1000); /* Timeout 50ms */
+	mdelay(10);
 }
 
 // ----------------------------------------------------------------------
@@ -767,14 +792,11 @@ static int __devinit fcpcipnp_setup(stru
 
 	// Reset
 	outb(0, adapter->io + AVM_STATUS0);
-	set_current_state(TASK_UNINTERRUPTIBLE);
-	schedule_timeout(50 * HZ / 1000); // 50 msec
+	mdelay(10);
 	outb(AVM_STATUS0_RESET, adapter->io + AVM_STATUS0);
-	set_current_state(TASK_UNINTERRUPTIBLE);
-	schedule_timeout(50 * HZ / 1000); // 50 msec
+	mdelay(10);
 	outb(0, adapter->io + AVM_STATUS0);
-	set_current_state(TASK_UNINTERRUPTIBLE);
-	schedule_timeout(10 * HZ / 1000); // 10 msec
+	mdelay(10);
 
 	switch (adapter->type) {
 	case AVM_FRITZ_PCIV2:
@@ -784,7 +806,7 @@ static int __devinit fcpcipnp_setup(stru
 	case AVM_FRITZ_PCI:
 	case AVM_FRITZ_PNP:
 		fcpci_init(adapter);
-		hisax_isac_setup(&adapter->isac);
+		isac_setup(&adapter->isac);
 		break;
 	}
 	val = adapter->read_hdlc_status(adapter, 0);
@@ -817,7 +839,7 @@ static void __devexit fcpcipnp_release(s
 // ----------------------------------------------------------------------
 
 static struct fritz_adapter * __devinit 
-new_adapter(struct pci_dev *pdev)
+new_adapter(void)
 {
 	struct fritz_adapter *adapter;
 	struct hisax_b_if *b_if[2];
@@ -840,8 +862,6 @@ new_adapter(struct pci_dev *pdev)
 		adapter->bcs[i].b_if.ifc.l2l1 = fritz_b_l2l1;
 	}
 
-	pci_set_drvdata(pdev, adapter);
-
 	for (i = 0; i < 2; i++)
 		b_if[i] = &adapter->bcs[i].b_if;
 
@@ -863,10 +883,12 @@ static int __devinit fcpci_probe(struct 
 	int retval;
 
 	retval = -ENOMEM;
-	adapter = new_adapter(pdev);
+	adapter = new_adapter();
 	if (!adapter)
 		goto err;
 
+	pci_set_drvdata(pdev, adapter);
+
 	if (pdev->device == PCI_DEVICE_ID_AVM_A1_V2) 
 		adapter->type = AVM_FRITZ_PCIV2;
 	else
@@ -880,7 +902,7 @@ static int __devinit fcpci_probe(struct 
 	adapter->irq = pdev->irq;
 
 	printk(KERN_INFO "hisax_fcpcipnp: found adapter %s at %s\n",
-	       (char *) ent->driver_data, pci_name(pdev));
+	       (char *) ent->driver_data, pdev->slot_name);
 
 	retval = fcpcipnp_setup(adapter);
 	if (retval)
@@ -894,91 +916,87 @@ static int __devinit fcpci_probe(struct 
 	return retval;
 }
 
-static void __devexit fcpci_remove(struct pci_dev *pdev)
-{
-	struct fritz_adapter *adapter = pci_get_drvdata(pdev);
-
-	fcpcipnp_release(adapter);
-	pci_disable_device(pdev);
-	delete_adapter(adapter);
-}
-
-static struct pci_driver fcpci_driver = {
-	.name     = "fcpci",
-	.probe    = fcpci_probe,
-	.remove   = __devexit_p(fcpci_remove),
-	.id_table = fcpci_ids,
-};
-
-#ifdef CONFIG_PNP_CARD
-
-static int __devinit fcpnp_probe(struct pnp_card *card,
-				 const struct pnp_card_device_id *card_id)
+#ifdef __ISAPNP__
+static int __devinit fcpnp_probe(struct pnp_dev *pdev, const struct pnp_device_id *dev_id)
 {
 	struct fritz_adapter *adapter;
-	struct pnp_dev *pnp_dev;
 	int retval;
 
-	retval = -ENODEV;
-	pnp_dev = pnp_request_card_device(card, card_id->devs[0].id, NULL);
-	if (!pnp_dev)
-		goto err;
-
-	if (!pnp_port_valid(pnp_dev, 0) || !pnp_irq_valid(pnp_dev, 0))
-		goto err;
+	if (!pdev)
+		return(-ENODEV);
 
 	retval = -ENOMEM;
-	adapter = new_adapter((struct pci_dev *)pnp_dev); // FIXME
+	adapter = new_adapter();
 	if (!adapter)
 		goto err;
-	
+
+	pnp_set_drvdata(pdev, adapter);
+
 	adapter->type = AVM_FRITZ_PNP;
-	adapter->io = pnp_port_start(pnp_dev, 0);
-	adapter->irq = pnp_irq(pnp_dev, 0);
-	
+
+	pnp_disable_dev(pdev);
+	retval = pnp_activate_dev(pdev);
+	if (retval < 0) {
+		printk(KERN_WARNING "%s: pnp_activate_dev(%s) ret(%d)\n", __FUNCTION__,
+			(char *)dev_id->driver_data, retval);
+		goto err_free;
+	}
+	adapter->io = pnp_port_start(pdev, 0);
+	adapter->irq = pnp_irq(pdev, 0);
+
 	printk(KERN_INFO "hisax_fcpcipnp: found adapter %s at IO %#x irq %d\n",
-	       (char *) card_id->driver_data, adapter->io, adapter->irq);
-	
+	       (char *) dev_id->driver_data, adapter->io, adapter->irq);
+
 	retval = fcpcipnp_setup(adapter);
 	if (retval)
-		goto err_delete;
-	
+		goto err_free;
+
 	return 0;
 	
- err_delete:
+ err_free:
 	delete_adapter(adapter);
  err:
 	return retval;
 }
 
-static void __devexit fcpnp_remove(struct pnp_card *pcard)
+static void __devexit fcpnp_remove(struct pnp_dev *pdev)
 {
-	struct fritz_adapter *adapter = pnpc_get_drvdata(pcard);
+	struct fritz_adapter *adapter = pnp_get_drvdata(pdev);
 
-	fcpcipnp_release(adapter);
-	delete_adapter(adapter);
+	if (adapter) {
+		fcpcipnp_release(adapter);
+		delete_adapter(adapter);
+	}
+	pnp_disable_dev(pdev);
 }
 
-static struct pnp_card_device_id fcpnp_ids[] __devinitdata = {
-	{ .id          = "AVM0900", 
-	  .driver_data = (unsigned long) "Fritz!Card PnP",
-	  .devs        = { { "AVM0900" } },
-	},
-	{}
+static struct pnp_driver fcpnp_driver = {
+	name:     "fcpnp",
+	probe:    fcpnp_probe,
+	remove:   __devexit_p(fcpnp_remove),
+	id_table: fcpnp_ids,
 };
+#endif
 
-static struct pnpc_driver fcpnp_driver = {
-	.name     = "fcpnp",
-	.probe    = fcpnp_probe,
-	.remove   = __devexit_p(fcpnp_remove),
-	.id_table = fcpnp_ids,
-};
+static void __devexit fcpci_remove(struct pci_dev *pdev)
+{
+	struct fritz_adapter *adapter = pci_get_drvdata(pdev);
 
-#endif
+	fcpcipnp_release(adapter);
+	pci_disable_device(pdev);
+	delete_adapter(adapter);
+}
+
+static struct pci_driver fcpci_driver = {
+	name:     "fcpci",
+	probe:    fcpci_probe,
+	remove:   __devexit_p(fcpci_remove),
+	id_table: fcpci_ids,
+};
 
 static int __init hisax_fcpcipnp_init(void)
 {
-	int retval = 0, pci_nr_found;
+	int retval, pci_nr_found;
 
 	printk(KERN_INFO "hisax_fcpcipnp: Fritz!Card PCI/PCIv2/PnP ISDN driver v0.0.1\n");
 
@@ -986,25 +1004,26 @@ static int __init hisax_fcpcipnp_init(vo
 	if (retval < 0)
 		goto out;
 	pci_nr_found = retval;
+	retval = 0;
 
-#ifdef CONFIG_PNP_CARD
-	retval = pnpc_register_driver(&fcpnp_driver);
-#endif
+#ifdef __ISAPNP__
+	retval = pnp_register_driver(&fcpnp_driver);
 	if (retval < 0)
 		goto out_unregister_pci;
+#endif
 
 #if !defined(CONFIG_HOTPLUG) || defined(MODULE)
 	if (pci_nr_found + retval == 0) {
 		retval = -ENODEV;
-		goto out_unregister_pnp;
+		goto out_unregister_isapnp;
 	}
 #endif
 	return 0;
 
 #if !defined(CONFIG_HOTPLUG) || defined(MODULE)
- out_unregister_pnp:
-#ifdef CONFIG_PNP_CARD
-	pnpc_unregister_driver(&fcpnp_driver);
+ out_unregister_isapnp:
+#ifdef __ISAPNP__
+	pnp_unregister_driver(&fcpnp_driver);
 #endif
 #endif
  out_unregister_pci:
@@ -1015,8 +1034,8 @@ static int __init hisax_fcpcipnp_init(vo
 
 static void __exit hisax_fcpcipnp_exit(void)
 {
-#ifdef CONFIG_PNP_CARD
-	pnpc_unregister_driver(&fcpnp_driver);
+#ifdef __ISAPNP__
+	pnp_unregister_driver(&fcpnp_driver);
 #endif
 	pci_unregister_driver(&fcpci_driver);
 }
--- diff/drivers/isdn/hisax/hisax_fcpcipnp.h	2003-01-13 14:18:15.000000000 +0000
+++ source/drivers/isdn/hisax/hisax_fcpcipnp.h	2004-02-23 13:56:42.000000000 +0000
@@ -12,15 +12,15 @@ enum {
 
 struct hdlc_stat_reg {
 #ifdef __BIG_ENDIAN
-	u8 fill __attribute__((packed));
-	u8 mode __attribute__((packed));
-	u8 xml  __attribute__((packed));
-	u8 cmd  __attribute__((packed));
+	u_char fill __attribute__((packed));
+	u_char mode __attribute__((packed));
+	u_char xml  __attribute__((packed));
+	u_char cmd  __attribute__((packed));
 #else
-	u8 cmd  __attribute__((packed));
-	u8 xml  __attribute__((packed));
-	u8 mode __attribute__((packed));
-	u8 fill __attribute__((packed));
+	u_char cmd  __attribute__((packed));
+	u_char xml  __attribute__((packed));
+	u_char mode __attribute__((packed));
+	u_char fill __attribute__((packed));
 #endif
 };
 
@@ -36,8 +36,9 @@ struct fritz_bcs {
 	} ctrl;
 	u_int stat;
 	int rcvidx;
-	u8 rcvbuf[HSCX_BUFMAX]; /* B-Channel receive Buffer */
-
+	int fifo_size;
+	u_char rcvbuf[HSCX_BUFMAX]; /* B-Channel receive Buffer */
+	
 	int tx_cnt;		    /* B-Channel transmit counter */
 	struct sk_buff *tx_skb;     /* B-Channel transmit Buffer */
 };
--- diff/drivers/isdn/hisax/hisax_isac.c	2003-05-21 11:49:50.000000000 +0100
+++ source/drivers/isdn/hisax/hisax_isac.c	2004-02-23 13:56:42.000000000 +0000
@@ -450,7 +450,7 @@ static void isac_empty_fifo(struct isac 
 {
 	// this also works for isacsx, since
 	// CMDR(D) register works the same
-	u8 *ptr;
+	u_char *ptr;
 
 	DBG(DBG_IRQ, "count %d", count);
 
@@ -474,7 +474,7 @@ static void isac_fill_fifo(struct isac *
 
 	int count;
 	unsigned char cmd;
-	u8 *ptr;
+	u_char *ptr;
 
 	if (!isac->tx_skb)
 		BUG();
@@ -770,7 +770,7 @@ void isac_init(struct isac *isac)
 	FsmInitTimer(&isac->l1m, &isac->timer);
 }
 
-void hisax_isac_setup(struct isac *isac)
+void isac_setup(struct isac *isac)
 {
 	int val, eval;
 
@@ -890,7 +890,7 @@ EXPORT_SYMBOL(isac_d_l2l1);
 EXPORT_SYMBOL(isacsx_setup);
 EXPORT_SYMBOL(isacsx_irq);
 
-EXPORT_SYMBOL(hisax_isac_setup);
+EXPORT_SYMBOL(isac_setup);
 EXPORT_SYMBOL(isac_irq);
 
 module_init(hisax_isac_init);
--- diff/drivers/isdn/hisax/hisax_isac.h	2003-05-21 11:49:50.000000000 +0100
+++ source/drivers/isdn/hisax/hisax_isac.h	2004-02-23 13:56:42.000000000 +0000
@@ -17,26 +17,26 @@ struct isac {
 	struct hisax_d_if hisax_d_if;
 	struct FsmInst l1m;
 	struct FsmTimer timer;
-	u8 mocr;
-	u8 adf2;
+	u_char mocr;
+	u_char adf2;
 	int    type;
 
-	u8 rcvbuf[MAX_DFRAME_LEN_L1];
+	u_char rcvbuf[MAX_DFRAME_LEN_L1];
 	int rcvidx;
 
 	struct sk_buff *tx_skb;
 	int tx_cnt;
 
-	u8 (*read_isac)      (struct isac *, u8);
-	void   (*write_isac)     (struct isac *, u8, u8);
-	void   (*read_isac_fifo) (struct isac *, u8 *, int);
-	void   (*write_isac_fifo)(struct isac *, u8 *, int);
+	u_char (*read_isac)      (struct isac *, u_char);
+	void   (*write_isac)     (struct isac *, u_char, u_char);
+	void   (*read_isac_fifo) (struct isac *, u_char *, int);
+	void   (*write_isac_fifo)(struct isac *, u_char *, int);
 };
 
 void isac_init(struct isac *isac);
 void isac_d_l2l1(struct hisax_if *hisax_d_if, int pr, void *arg);
 
-void hisax_isac_setup(struct isac *isac);
+void isac_setup(struct isac *isac);
 void isac_irq(struct isac *isac);
 
 void isacsx_setup(struct isac *isac);
--- diff/drivers/isdn/hisax/hscx.c	2003-01-16 11:30:36.000000000 +0000
+++ source/drivers/isdn/hisax/hscx.c	2004-02-23 13:56:42.000000000 +0000
@@ -1,4 +1,4 @@
-/* $Id: hscx.c,v 1.21.6.3 2001/09/23 22:24:48 kai Exp $
+/* $Id: hscx.c,v 1.24.2.4 2004/01/24 20:47:23 keil Exp $
  *
  * HSCX specific routines
  *
@@ -17,133 +17,136 @@
 #include "isdnl1.h"
 #include <linux/interrupt.h>
 
-static char *HSCXVer[] __initdata =
+static char *HSCXVer[] =
 {"A1", "?1", "A2", "?3", "A3", "V2.1", "?6", "?7",
  "?8", "?9", "?10", "?11", "?12", "?13", "?14", "???"};
 
-static inline u8
-hscx_read(struct BCState *bcs, u8 addr)
-{
-	struct IsdnCardState *cs = bcs->cs;
-
-	return cs->bc_hw_ops->read_reg(cs, bcs->unit, addr);
-}
-
-static inline void
-hscx_write(struct BCState *bcs, u8 addr, u8 val)
-{
-	struct IsdnCardState *cs = bcs->cs;
-
-	cs->bc_hw_ops->write_reg(cs, bcs->unit, addr, val);
-}
-
-static inline void
-hscx_write_fifo(struct BCState *bcs, u8 *p, int len)
-{
-	struct IsdnCardState *cs = bcs->cs;
-
-	cs->bc_hw_ops->write_fifo(cs, bcs->unit, p, len);
-}
-
-static int
+int
 HscxVersion(struct IsdnCardState *cs, char *s)
 {
 	int verA, verB;
 
-	verA = cs->bc_hw_ops->read_reg(cs, 0, HSCX_VSTR) & 0xf;
-	verB = cs->bc_hw_ops->read_reg(cs, 1, HSCX_VSTR) & 0xf;
+	verA = cs->BC_Read_Reg(cs, 0, HSCX_VSTR) & 0xf;
+	verB = cs->BC_Read_Reg(cs, 1, HSCX_VSTR) & 0xf;
 	printk(KERN_INFO "%s HSCX version A: %s  B: %s\n", s,
 	       HSCXVer[verA], HSCXVer[verB]);
 	if ((verA == 0) | (verA == 0xf) | (verB == 0) | (verB == 0xf))
-		return 1;
+		return (1);
 	else
-		return 0;
+		return (0);
 }
 
 void
 modehscx(struct BCState *bcs, int mode, int bc)
 {
 	struct IsdnCardState *cs = bcs->cs;
-	int hscx = bcs->unit;
+	int hscx = bcs->hw.hscx.hscx;
 
 	if (cs->debug & L1_DEB_HSCX)
 		debugl1(cs, "hscx %c mode %d ichan %d",
 			'A' + hscx, mode, bc);
 	bcs->mode = mode;
 	bcs->channel = bc;
-	hscx_write(bcs, HSCX_XAD1, 0xFF);
-	hscx_write(bcs, HSCX_XAD2, 0xFF);
-	hscx_write(bcs, HSCX_RAH2, 0xFF);
-	hscx_write(bcs, HSCX_XBCH, 0x0);
-	hscx_write(bcs, HSCX_RLCR, 0x0);
-	hscx_write(bcs, HSCX_CCR1,
+	cs->BC_Write_Reg(cs, hscx, HSCX_XAD1, 0xFF);
+	cs->BC_Write_Reg(cs, hscx, HSCX_XAD2, 0xFF);
+	cs->BC_Write_Reg(cs, hscx, HSCX_RAH2, 0xFF);
+	cs->BC_Write_Reg(cs, hscx, HSCX_XBCH, 0x0);
+	cs->BC_Write_Reg(cs, hscx, HSCX_RLCR, 0x0);
+	cs->BC_Write_Reg(cs, hscx, HSCX_CCR1,
 		test_bit(HW_IPAC, &cs->HW_Flags) ? 0x82 : 0x85);
-	hscx_write(bcs, HSCX_CCR2, 0x30);
-	hscx_write(bcs, HSCX_XCCR, 7);
-	hscx_write(bcs, HSCX_RCCR, 7);
+	cs->BC_Write_Reg(cs, hscx, HSCX_CCR2, 0x30);
+	cs->BC_Write_Reg(cs, hscx, HSCX_XCCR, 7);
+	cs->BC_Write_Reg(cs, hscx, HSCX_RCCR, 7);
 
 	/* Switch IOM 1 SSI */
 	if (test_bit(HW_IOM1, &cs->HW_Flags) && (hscx == 0))
 		bc = 1 - bc;
 
 	if (bc == 0) {
-		hscx_write(bcs, HSCX_TSAX,
+		cs->BC_Write_Reg(cs, hscx, HSCX_TSAX,
 			      test_bit(HW_IOM1, &cs->HW_Flags) ? 0x7 : bcs->hw.hscx.tsaxr0);
-		hscx_write(bcs, HSCX_TSAR,
+		cs->BC_Write_Reg(cs, hscx, HSCX_TSAR,
 			      test_bit(HW_IOM1, &cs->HW_Flags) ? 0x7 : bcs->hw.hscx.tsaxr0);
 	} else {
-		hscx_write(bcs, HSCX_TSAX, bcs->hw.hscx.tsaxr1);
-		hscx_write(bcs, HSCX_TSAR, bcs->hw.hscx.tsaxr1);
+		cs->BC_Write_Reg(cs, hscx, HSCX_TSAX, bcs->hw.hscx.tsaxr1);
+		cs->BC_Write_Reg(cs, hscx, HSCX_TSAR, bcs->hw.hscx.tsaxr1);
 	}
 	switch (mode) {
-	case L1_MODE_NULL:
-		hscx_write(bcs, HSCX_TSAX, 0x1f);
-		hscx_write(bcs, HSCX_TSAR, 0x1f);
-		hscx_write(bcs, HSCX_MODE, 0x84);
-		break;
-	case L1_MODE_TRANS:
-		hscx_write(bcs, HSCX_MODE, 0xe4);
-		break;
-	case L1_MODE_HDLC:
-		hscx_write(bcs, HSCX_CCR1,
-			       test_bit(HW_IPAC, &cs->HW_Flags) ? 0x8a : 0x8d);
-		hscx_write(bcs, HSCX_MODE, 0x8c);
-		break;
+		case (L1_MODE_NULL):
+			cs->BC_Write_Reg(cs, hscx, HSCX_TSAX, 0x1f);
+			cs->BC_Write_Reg(cs, hscx, HSCX_TSAR, 0x1f);
+			cs->BC_Write_Reg(cs, hscx, HSCX_MODE, 0x84);
+			break;
+		case (L1_MODE_TRANS):
+			cs->BC_Write_Reg(cs, hscx, HSCX_MODE, 0xe4);
+			break;
+		case (L1_MODE_HDLC):
+			cs->BC_Write_Reg(cs, hscx, HSCX_CCR1,
+				test_bit(HW_IPAC, &cs->HW_Flags) ? 0x8a : 0x8d);
+			cs->BC_Write_Reg(cs, hscx, HSCX_MODE, 0x8c);
+			break;
 	}
 	if (mode)
-		hscx_write(bcs, HSCX_CMDR, 0x41);
-
-	hscx_write(bcs, HSCX_ISTA, 0x00);
+		cs->BC_Write_Reg(cs, hscx, HSCX_CMDR, 0x41);
+	cs->BC_Write_Reg(cs, hscx, HSCX_ISTA, 0x00);
 }
 
 void
 hscx_l2l1(struct PStack *st, int pr, void *arg)
 {
+	struct BCState *bcs = st->l1.bcs;
+	u_long flags;
 	struct sk_buff *skb = arg;
 
 	switch (pr) {
 		case (PH_DATA | REQUEST):
-			xmit_data_req_b(st->l1.bcs, skb);
+			spin_lock_irqsave(&bcs->cs->lock, flags);
+			if (bcs->tx_skb) {
+				skb_queue_tail(&bcs->squeue, skb);
+			} else {
+				bcs->tx_skb = skb;
+				test_and_set_bit(BC_FLG_BUSY, &bcs->Flag);
+				bcs->hw.hscx.count = 0;
+				bcs->cs->BC_Send_Data(bcs);
+			}
+			spin_unlock_irqrestore(&bcs->cs->lock, flags);
 			break;
 		case (PH_PULL | INDICATION):
-			xmit_pull_ind_b(st->l1.bcs, skb);
+			spin_lock_irqsave(&bcs->cs->lock, flags);
+			if (bcs->tx_skb) {
+				printk(KERN_WARNING "hscx_l2l1: this shouldn't happen\n");
+			} else {
+				test_and_set_bit(BC_FLG_BUSY, &bcs->Flag);
+				bcs->tx_skb = skb;
+				bcs->hw.hscx.count = 0;
+				bcs->cs->BC_Send_Data(bcs);
+			}
+			spin_unlock_irqrestore(&bcs->cs->lock, flags);
 			break;
 		case (PH_PULL | REQUEST):
-			xmit_pull_req_b(st);
+			if (!bcs->tx_skb) {
+				test_and_clear_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
+				st->l1.l1l2(st, PH_PULL | CONFIRM, NULL);
+			} else
+				test_and_set_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
 			break;
 		case (PH_ACTIVATE | REQUEST):
-			test_and_set_bit(BC_FLG_ACTIV, &st->l1.bcs->Flag);
-			modehscx(st->l1.bcs, st->l1.mode, st->l1.bc);
+			spin_lock_irqsave(&bcs->cs->lock, flags);
+			test_and_set_bit(BC_FLG_ACTIV, &bcs->Flag);
+			modehscx(bcs, st->l1.mode, st->l1.bc);
+			spin_unlock_irqrestore(&bcs->cs->lock, flags);
 			l1_msg_b(st, pr, arg);
 			break;
 		case (PH_DEACTIVATE | REQUEST):
 			l1_msg_b(st, pr, arg);
 			break;
 		case (PH_DEACTIVATE | CONFIRM):
-			test_and_clear_bit(BC_FLG_ACTIV, &st->l1.bcs->Flag);
-			test_and_clear_bit(BC_FLG_BUSY, &st->l1.bcs->Flag);
-			modehscx(st->l1.bcs, 0, st->l1.bc);
-			L1L2(st, PH_DEACTIVATE | CONFIRM, NULL);
+			spin_lock_irqsave(&bcs->cs->lock, flags);
+			test_and_clear_bit(BC_FLG_ACTIV, &bcs->Flag);
+			test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
+			modehscx(bcs, 0, st->l1.bc);
+			spin_unlock_irqrestore(&bcs->cs->lock, flags);
+			st->l1.l1l2(st, PH_DEACTIVATE | CONFIRM, NULL);
 			break;
 	}
 }
@@ -152,17 +155,50 @@ void
 close_hscxstate(struct BCState *bcs)
 {
 	modehscx(bcs, 0, bcs->channel);
-	bc_close(bcs);
+	if (test_and_clear_bit(BC_FLG_INIT, &bcs->Flag)) {
+		if (bcs->hw.hscx.rcvbuf) {
+			kfree(bcs->hw.hscx.rcvbuf);
+			bcs->hw.hscx.rcvbuf = NULL;
+		}
+		if (bcs->blog) {
+			kfree(bcs->blog);
+			bcs->blog = NULL;
+		}
+		skb_queue_purge(&bcs->rqueue);
+		skb_queue_purge(&bcs->squeue);
+		if (bcs->tx_skb) {
+			dev_kfree_skb_any(bcs->tx_skb);
+			bcs->tx_skb = NULL;
+			test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
+		}
+	}
 }
 
 int
 open_hscxstate(struct IsdnCardState *cs, struct BCState *bcs)
 {
-	bc_open(bcs);
+	if (!test_and_set_bit(BC_FLG_INIT, &bcs->Flag)) {
+		if (!(bcs->hw.hscx.rcvbuf = kmalloc(HSCX_BUFMAX, GFP_ATOMIC))) {
+			printk(KERN_WARNING
+				"HiSax: No memory for hscx.rcvbuf\n");
+			test_and_clear_bit(BC_FLG_INIT, &bcs->Flag);
+			return (1);
+		}
+		if (!(bcs->blog = kmalloc(MAX_BLOG_SPACE, GFP_ATOMIC))) {
+			printk(KERN_WARNING
+				"HiSax: No memory for bcs->blog\n");
+			test_and_clear_bit(BC_FLG_INIT, &bcs->Flag);
+			kfree(bcs->hw.hscx.rcvbuf);
+			bcs->hw.hscx.rcvbuf = NULL;
+			return (2);
+		}
+		skb_queue_head_init(&bcs->rqueue);
+		skb_queue_head_init(&bcs->squeue);
+	}
 	bcs->tx_skb = NULL;
 	test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
 	bcs->event = 0;
-	bcs->rcvidx = 0;
+	bcs->hw.hscx.rcvidx = 0;
 	bcs->tx_cnt = 0;
 	return (0);
 }
@@ -174,80 +210,71 @@ setstack_hscx(struct PStack *st, struct 
 	if (open_hscxstate(st->l1.hardware, bcs))
 		return (-1);
 	st->l1.bcs = bcs;
-	st->l1.l2l1 = hscx_l2l1;
+	st->l2.l2l1 = hscx_l2l1;
 	setstack_manager(st);
 	bcs->st = st;
 	setstack_l1_B(st);
 	return (0);
 }
 
-static void hscx_fill_fifo(struct BCState *bcs);
-
-static struct bc_l1_ops hscx_l1_ops = {
-	.fill_fifo = hscx_fill_fifo,
-	.open      = setstack_hscx,
-	.close     = close_hscxstate,
-};
-
-void __init
-inithscx(struct IsdnCardState *cs)
+void
+clear_pending_hscx_ints(struct IsdnCardState *cs)
 {
 	int val, eval;
-	
-	cs->bc_l1_ops = &hscx_l1_ops;
-	cs->bcs[0].unit = 0;
-	cs->bcs[1].unit = 1;
-	cs->bcs[0].hw.hscx.tsaxr0 = 0x2f;
-	cs->bcs[0].hw.hscx.tsaxr1 = 3;
-	cs->bcs[1].hw.hscx.tsaxr0 = 0x2f;
-	cs->bcs[1].hw.hscx.tsaxr1 = 3;
 
-	val = hscx_read(&cs->bcs[1], HSCX_ISTA);
+	val = cs->BC_Read_Reg(cs, 1, HSCX_ISTA);
 	debugl1(cs, "HSCX B ISTA %x", val);
 	if (val & 0x01) {
-		eval = hscx_read(&cs->bcs[1], HSCX_EXIR);
+		eval = cs->BC_Read_Reg(cs, 1, HSCX_EXIR);
 		debugl1(cs, "HSCX B EXIR %x", eval);
 	}
 	if (val & 0x02) {
-		eval = hscx_read(&cs->bcs[0], HSCX_EXIR);
+		eval = cs->BC_Read_Reg(cs, 0, HSCX_EXIR);
 		debugl1(cs, "HSCX A EXIR %x", eval);
 	}
-	val = hscx_read(&cs->bcs[0], HSCX_ISTA);
+	val = cs->BC_Read_Reg(cs, 0, HSCX_ISTA);
 	debugl1(cs, "HSCX A ISTA %x", val);
-	val = hscx_read(&cs->bcs[1], HSCX_STAR);
+	val = cs->BC_Read_Reg(cs, 1, HSCX_STAR);
 	debugl1(cs, "HSCX B STAR %x", val);
-	val = hscx_read(&cs->bcs[0], HSCX_STAR);
+	val = cs->BC_Read_Reg(cs, 0, HSCX_STAR);
 	debugl1(cs, "HSCX A STAR %x", val);
 	/* disable all IRQ */
-	hscx_write(&cs->bcs[0], HSCX_MASK, 0xFF);
-	hscx_write(&cs->bcs[1], HSCX_MASK, 0xFF);
-
-	modehscx(&cs->bcs[0], 0, 0);
-	modehscx(&cs->bcs[1], 0, 0);
-
-	/* Reenable all IRQ */
-	hscx_write(&cs->bcs[0], HSCX_MASK, 0x0);
-	hscx_write(&cs->bcs[1], HSCX_MASK, 0x0);
+	cs->BC_Write_Reg(cs, 0, HSCX_MASK, 0xFF);
+	cs->BC_Write_Reg(cs, 1, HSCX_MASK, 0xFF);
 }
 
 void
-inithscxisac(struct IsdnCardState *cs)
+inithscx(struct IsdnCardState *cs)
 {
-	initisac(cs);
-	inithscx(cs);
+	cs->bcs[0].BC_SetStack = setstack_hscx;
+	cs->bcs[1].BC_SetStack = setstack_hscx;
+	cs->bcs[0].BC_Close = close_hscxstate;
+	cs->bcs[1].BC_Close = close_hscxstate;
+	cs->bcs[0].hw.hscx.hscx = 0;
+	cs->bcs[1].hw.hscx.hscx = 1;
+	cs->bcs[0].hw.hscx.tsaxr0 = 0x2f;
+	cs->bcs[0].hw.hscx.tsaxr1 = 3;
+	cs->bcs[1].hw.hscx.tsaxr0 = 0x2f;
+	cs->bcs[1].hw.hscx.tsaxr1 = 3;
+	modehscx(cs->bcs, 0, 0);
+	modehscx(cs->bcs + 1, 0, 0);
 }
 
-int
-hscxisac_setup(struct IsdnCardState *cs, struct dc_hw_ops *isac_ops,
-	       struct bc_hw_ops *hscx_ops)
+void
+inithscxisac(struct IsdnCardState *cs, int part)
 {
-	isac_setup(cs, isac_ops);
-	cs->bc_hw_ops = hscx_ops;
-	if (HscxVersion(cs, "HiSax:")) {
-		printk(KERN_WARNING "HiSax: invalid HSCX version\n");
-		return -ENODEV;
+	if (part & 1) {
+		clear_pending_isac_ints(cs);
+		clear_pending_hscx_ints(cs);
+		initisac(cs);
+		inithscx(cs);
+	}
+	if (part & 2) {
+		/* Reenable all IRQ */
+		cs->writeisac(cs, ISAC_MASK, 0);
+		cs->BC_Write_Reg(cs, 0, HSCX_MASK, 0);
+		cs->BC_Write_Reg(cs, 1, HSCX_MASK, 0);
+		/* RESET Receiver and Transmitter */
+		cs->writeisac(cs, ISAC_CMDR, 0x41);
 	}
-	return 0;
 }
-
-#include "hscx_irq.c"
--- diff/drivers/isdn/hisax/hscx.h	2003-05-21 11:50:15.000000000 +0100
+++ source/drivers/isdn/hisax/hscx.h	2004-02-23 13:56:42.000000000 +0000
@@ -1,4 +1,4 @@
-/* $Id: hscx.h,v 1.6.6.2 2001/09/23 22:24:48 kai Exp $
+/* $Id: hscx.h,v 1.8.2.2 2004/01/12 22:52:26 keil Exp $
  *
  * HSCX specific defines
  *
@@ -10,8 +10,6 @@
  *
  */
 
-#include <linux/interrupt.h>
-
 /* All Registers original Siemens Spec  */
 
 #define HSCX_ISTA 0x20
@@ -36,10 +34,8 @@
 #define HSCX_RLCR 0x2e
 #define HSCX_MASK 0x20
 
+extern int HscxVersion(struct IsdnCardState *cs, char *s);
 extern void modehscx(struct BCState *bcs, int mode, int bc);
-extern void inithscxisac(struct IsdnCardState *cs);
-extern void hscx_int_main(struct IsdnCardState *cs, u8 val);
-extern irqreturn_t hscxisac_irq(int intno, void *dev_id, struct pt_regs *regs);
-extern int  hscxisac_setup(struct IsdnCardState *cs,
-			   struct dc_hw_ops *isac_ops,
-			   struct bc_hw_ops *hscx_ops);
+extern void clear_pending_hscx_ints(struct IsdnCardState *cs);
+extern void inithscx(struct IsdnCardState *cs);
+extern void inithscxisac(struct IsdnCardState *cs, int part);
--- diff/drivers/isdn/hisax/hscx_irq.c	2003-05-21 11:50:15.000000000 +0100
+++ source/drivers/isdn/hisax/hscx_irq.c	2004-02-23 13:56:42.000000000 +0000
@@ -1,4 +1,4 @@
-/* $Id: hscx_irq.c,v 1.16.6.2 2001/09/23 22:24:48 kai Exp $
+/* $Id: hscx_irq.c,v 1.18.2.3 2004/02/11 13:21:34 keil Exp $
  *
  * low level b-channel stuff for Siemens HSCX
  *
@@ -12,12 +12,13 @@
  *
  */
 
-static void
-waitforCEC(struct BCState *bcs)
+
+static inline void
+waitforCEC(struct IsdnCardState *cs, int hscx)
 {
 	int to = 50;
 
-	while ((hscx_read(bcs, HSCX_STAR) & 0x04) && to) {
+	while ((READHSCX(cs, hscx, HSCX_STAR) & 0x04) && to) {
 		udelay(1);
 		to--;
 	}
@@ -26,12 +27,12 @@ waitforCEC(struct BCState *bcs)
 }
 
 
-static void
-waitforXFW(struct BCState *bcs)
+static inline void
+waitforXFW(struct IsdnCardState *cs, int hscx)
 {
 	int to = 50;
 
-	while ((!(hscx_read(bcs, HSCX_STAR) & 0x44) == 0x40) && to) {
+	while ((!(READHSCX(cs, hscx, HSCX_STAR) & 0x44) == 0x40) && to) {
 		udelay(1);
 		to--;
 	}
@@ -40,18 +41,42 @@ waitforXFW(struct BCState *bcs)
 }
 
 static inline void
-WriteHSCXCMDR(struct BCState *bcs, u8 data)
+WriteHSCXCMDR(struct IsdnCardState *cs, int hscx, u_char data)
 {
-	waitforCEC(bcs);
-	hscx_write(bcs, HSCX_CMDR, data);
+	waitforCEC(cs, hscx);
+	WRITEHSCX(cs, hscx, HSCX_CMDR, data);
 }
 
 
+
 static void
 hscx_empty_fifo(struct BCState *bcs, int count)
 {
-	recv_empty_fifo_b(bcs, count);
-	WriteHSCXCMDR(bcs, 0x80);
+	u_char *ptr;
+	struct IsdnCardState *cs = bcs->cs;
+
+	if ((cs->debug & L1_DEB_HSCX) && !(cs->debug & L1_DEB_HSCX_FIFO))
+		debugl1(cs, "hscx_empty_fifo");
+
+	if (bcs->hw.hscx.rcvidx + count > HSCX_BUFMAX) {
+		if (cs->debug & L1_DEB_WARN)
+			debugl1(cs, "hscx_empty_fifo: incoming packet too large");
+		WriteHSCXCMDR(cs, bcs->hw.hscx.hscx, 0x80);
+		bcs->hw.hscx.rcvidx = 0;
+		return;
+	}
+	ptr = bcs->hw.hscx.rcvbuf + bcs->hw.hscx.rcvidx;
+	bcs->hw.hscx.rcvidx += count;
+	READHSCXFIFO(cs, bcs->hw.hscx.hscx, ptr, count);
+	WriteHSCXCMDR(cs, bcs->hw.hscx.hscx, 0x80);
+	if (cs->debug & L1_DEB_HSCX_FIFO) {
+		char *t = bcs->blog;
+
+		t += sprintf(t, "hscx_empty_fifo %c cnt %d",
+			     bcs->hw.hscx.hscx ? 'B' : 'A', count);
+		QuickHex(t, ptr, count);
+		debugl1(cs, bcs->blog);
+	}
 }
 
 static void
@@ -60,22 +85,46 @@ hscx_fill_fifo(struct BCState *bcs)
 	struct IsdnCardState *cs = bcs->cs;
 	int more, count;
 	int fifo_size = test_bit(HW_IPAC, &cs->HW_Flags)? 64: 32;
-	u8 *p;
+	u_char *ptr;
 
-	p = xmit_fill_fifo_b(bcs, fifo_size, &count, &more);
-	if (!p)
+	if ((cs->debug & L1_DEB_HSCX) && !(cs->debug & L1_DEB_HSCX_FIFO))
+		debugl1(cs, "hscx_fill_fifo");
+
+	if (!bcs->tx_skb)
+		return;
+	if (bcs->tx_skb->len <= 0)
 		return;
 
-	waitforXFW(bcs);
-	hscx_write_fifo(bcs, p, count);
-	WriteHSCXCMDR(bcs, more ? 0x8 : 0xa);
+	more = (bcs->mode == L1_MODE_TRANS) ? 1 : 0;
+	if (bcs->tx_skb->len > fifo_size) {
+		more = !0;
+		count = fifo_size;
+	} else
+		count = bcs->tx_skb->len;
+
+	waitforXFW(cs, bcs->hw.hscx.hscx);
+	ptr = bcs->tx_skb->data;
+	skb_pull(bcs->tx_skb, count);
+	bcs->tx_cnt -= count;
+	bcs->hw.hscx.count += count;
+	WRITEHSCXFIFO(cs, bcs->hw.hscx.hscx, ptr, count);
+	WriteHSCXCMDR(cs, bcs->hw.hscx.hscx, more ? 0x8 : 0xa);
+	if (cs->debug & L1_DEB_HSCX_FIFO) {
+		char *t = bcs->blog;
+
+		t += sprintf(t, "hscx_fill_fifo %c cnt %d",
+			     bcs->hw.hscx.hscx ? 'B' : 'A', count);
+		QuickHex(t, ptr, count);
+		debugl1(cs, bcs->blog);
+	}
 }
 
 static inline void
-hscx_interrupt(struct IsdnCardState *cs, u8 val, u8 hscx)
+hscx_interrupt(struct IsdnCardState *cs, u_char val, u_char hscx)
 {
-	u8 r;
+	u_char r;
 	struct BCState *bcs = cs->bcs + hscx;
+	struct sk_buff *skb;
 	int fifo_size = test_bit(HW_IPAC, &cs->HW_Flags)? 64: 32;
 	int count;
 
@@ -83,7 +132,7 @@ hscx_interrupt(struct IsdnCardState *cs,
 		return;
 
 	if (val & 0x80) {	/* RME */
-		r = hscx_read(bcs, HSCX_RSTA);
+		r = READHSCX(cs, hscx, HSCX_RSTA);
 		if ((r & 0xf0) != 0xa0) {
 			if (!(r & 0x80)) {
 				if (cs->debug & L1_DEB_WARN)
@@ -107,46 +156,102 @@ hscx_interrupt(struct IsdnCardState *cs,
 				bcs->err_crc++;
 #endif
 			}
-			WriteHSCXCMDR(bcs, 0x80);
-			bcs->rcvidx = 0;
+			WriteHSCXCMDR(cs, hscx, 0x80);
 		} else {
-			count = hscx_read(bcs, HSCX_RBCL) & (fifo_size-1);
+			count = READHSCX(cs, hscx, HSCX_RBCL) & (
+				test_bit(HW_IPAC, &cs->HW_Flags)? 0x3f: 0x1f);
 			if (count == 0)
 				count = fifo_size;
-
 			hscx_empty_fifo(bcs, count);
-			recv_rme_b(bcs);
+			if ((count = bcs->hw.hscx.rcvidx - 1) > 0) {
+				if (cs->debug & L1_DEB_HSCX_FIFO)
+					debugl1(cs, "HX Frame %d", count);
+				if (!(skb = dev_alloc_skb(count)))
+					printk(KERN_WARNING "HSCX: receive out of memory\n");
+				else {
+					memcpy(skb_put(skb, count), bcs->hw.hscx.rcvbuf, count);
+					skb_queue_tail(&bcs->rqueue, skb);
+				}
+			}
 		}
+		bcs->hw.hscx.rcvidx = 0;
+		schedule_event(bcs, B_RCVBUFREADY);
 	}
 	if (val & 0x40) {	/* RPF */
 		hscx_empty_fifo(bcs, fifo_size);
-		recv_rpf_b(bcs);
+		if (bcs->mode == L1_MODE_TRANS) {
+			/* receive audio data */
+			if (!(skb = dev_alloc_skb(fifo_size)))
+				printk(KERN_WARNING "HiSax: receive out of memory\n");
+			else {
+				memcpy(skb_put(skb, fifo_size), bcs->hw.hscx.rcvbuf, fifo_size);
+				skb_queue_tail(&bcs->rqueue, skb);
+			}
+			bcs->hw.hscx.rcvidx = 0;
+			schedule_event(bcs, B_RCVBUFREADY);
+		}
 	}
-	if (val & 0x10) {
-		xmit_xpr_b(bcs);
+	if (val & 0x10) {	/* XPR */
+		if (bcs->tx_skb) {
+			if (bcs->tx_skb->len) {
+				hscx_fill_fifo(bcs);
+				return;
+			} else {
+				if (test_bit(FLG_LLI_L1WAKEUP,&bcs->st->lli.flag) &&
+					(PACKET_NOACK != bcs->tx_skb->pkt_type)) {
+					u_long	flags;
+					spin_lock_irqsave(&bcs->aclock, flags);
+					bcs->ackcnt += bcs->hw.hscx.count;
+					spin_unlock_irqrestore(&bcs->aclock, flags);
+					schedule_event(bcs, B_ACKPENDING);
+				}
+				dev_kfree_skb_irq(bcs->tx_skb);
+				bcs->hw.hscx.count = 0; 
+				bcs->tx_skb = NULL;
+			}
+		}
+		if ((bcs->tx_skb = skb_dequeue(&bcs->squeue))) {
+			bcs->hw.hscx.count = 0;
+			test_and_set_bit(BC_FLG_BUSY, &bcs->Flag);
+			hscx_fill_fifo(bcs);
+		} else {
+			test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
+			schedule_event(bcs, B_XMTBUFREADY);
+		}
 	}
 }
 
-static void
-reset_xmit(struct BCState *bcs)
+static inline void
+hscx_int_main(struct IsdnCardState *cs, u_char val)
 {
-	WriteHSCXCMDR(bcs, 0x01);
-}
 
-void
-hscx_int_main(struct IsdnCardState *cs, u8 val)
-{
-	u8 exval;
+	u_char exval;
 	struct BCState *bcs;
 
 	if (val & 0x01) {
 		bcs = cs->bcs + 1;
-		exval = hscx_read(bcs, HSCX_EXIR);
-		if (cs->debug & L1_DEB_HSCX)
-			debugl1(cs, "HSCX B EXIR %x", exval);
+		exval = READHSCX(cs, 1, HSCX_EXIR);
 		if (exval & 0x40) {
-			xmit_xdu_b(bcs, reset_xmit);
-		}
+			if (bcs->mode == 1)
+				hscx_fill_fifo(bcs);
+			else {
+#ifdef ERROR_STATISTIC
+				bcs->err_tx++;
+#endif
+				/* Here we lost an TX interrupt, so
+				   * restart transmitting the whole frame.
+				 */
+				if (bcs->tx_skb) {
+					skb_push(bcs->tx_skb, bcs->hw.hscx.count);
+					bcs->tx_cnt += bcs->hw.hscx.count;
+					bcs->hw.hscx.count = 0;
+				}
+				WriteHSCXCMDR(cs, bcs->hw.hscx.hscx, 0x01);
+				if (cs->debug & L1_DEB_WARN)
+					debugl1(cs, "HSCX B EXIR %x Lost TX", exval);
+			}
+		} else if (cs->debug & L1_DEB_HSCX)
+			debugl1(cs, "HSCX B EXIR %x", exval);
 	}
 	if (val & 0xf8) {
 		if (cs->debug & L1_DEB_HSCX)
@@ -155,72 +260,33 @@ hscx_int_main(struct IsdnCardState *cs, 
 	}
 	if (val & 0x02) {
 		bcs = cs->bcs;
-		exval = hscx_read(bcs, HSCX_EXIR);
-		if (cs->debug & L1_DEB_HSCX)
-			debugl1(cs, "HSCX A EXIR %x", exval);
+		exval = READHSCX(cs, 0, HSCX_EXIR);
 		if (exval & 0x40) {
-			xmit_xdu_b(bcs, reset_xmit);
-		}
+			if (bcs->mode == L1_MODE_TRANS)
+				hscx_fill_fifo(bcs);
+			else {
+				/* Here we lost an TX interrupt, so
+				   * restart transmitting the whole frame.
+				 */
+#ifdef ERROR_STATISTIC
+				bcs->err_tx++;
+#endif
+				if (bcs->tx_skb) {
+					skb_push(bcs->tx_skb, bcs->hw.hscx.count);
+					bcs->tx_cnt += bcs->hw.hscx.count;
+					bcs->hw.hscx.count = 0;
+				}
+				WriteHSCXCMDR(cs, bcs->hw.hscx.hscx, 0x01);
+				if (cs->debug & L1_DEB_WARN)
+					debugl1(cs, "HSCX A EXIR %x Lost TX", exval);
+			}
+		} else if (cs->debug & L1_DEB_HSCX)
+			debugl1(cs, "HSCX A EXIR %x", exval);
 	}
 	if (val & 0x04) {
-		bcs = cs->bcs;
-		exval = hscx_read(bcs, HSCX_ISTA);
+		exval = READHSCX(cs, 0, HSCX_ISTA);
 		if (cs->debug & L1_DEB_HSCX)
 			debugl1(cs, "HSCX A interrupt %x", exval);
 		hscx_interrupt(cs, exval, 0);
 	}
 }
-
-/* ====================================================================== */
-
-static inline u8
-isac_read(struct IsdnCardState *cs, u8 addr)
-{
-	return cs->dc_hw_ops->read_reg(cs, addr);
-}
-
-static inline void
-isac_write(struct IsdnCardState *cs, u8 addr, u8 val)
-{
-	cs->dc_hw_ops->write_reg(cs, addr, val);
-}
-
-irqreturn_t
-hscxisac_irq(int intno, void *dev_id, struct pt_regs *regs)
-{
-	struct IsdnCardState *cs = dev_id;
-	u8 val;
-	int count = 0;
-
-	spin_lock(&cs->lock);
-	val = hscx_read(&cs->bcs[1], HSCX_ISTA);
-      Start_HSCX:
-	if (val)
-		hscx_int_main(cs, val);
-	val = isac_read(cs, ISAC_ISTA);
-      Start_ISAC:
-	if (val)
-		isac_interrupt(cs, val);
-	count++;
-	val = hscx_read(&cs->bcs[1], HSCX_ISTA);
-	if (val && count < 5) {
-		if (cs->debug & L1_DEB_HSCX)
-			debugl1(cs, "HSCX IntStat after IntRoutine");
-		goto Start_HSCX;
-	}
-	val = isac_read(cs, ISAC_ISTA);
-	if (val && count < 5) {
-		if (cs->debug & L1_DEB_ISAC)
-			debugl1(cs, "ISAC IntStat after IntRoutine");
-		goto Start_ISAC;
-	}
-	hscx_write(&cs->bcs[0], HSCX_MASK, 0xFF);
-	hscx_write(&cs->bcs[1], HSCX_MASK, 0xFF);
-	isac_write(cs, ISAC_MASK, 0xFF);
-	isac_write(cs, ISAC_MASK, 0x0);
-	hscx_write(&cs->bcs[0], HSCX_MASK, 0x0);
-	hscx_write(&cs->bcs[1], HSCX_MASK, 0x0);
-	spin_unlock(&cs->lock);
-	return IRQ_HANDLED;
-}
-
--- diff/drivers/isdn/hisax/icc.c	2003-01-16 11:30:36.000000000 +0000
+++ source/drivers/isdn/hisax/icc.c	2004-02-23 13:56:42.000000000 +0000
@@ -1,4 +1,4 @@
-/* $Id: icc.c,v 1.5.6.4 2001/09/23 22:24:48 kai Exp $
+/* $Id: icc.c,v 1.8.2.3 2004/01/13 14:31:25 keil Exp $
  *
  * ICC specific routines
  *
@@ -24,39 +24,15 @@
 #define DBUSY_TIMER_VALUE 80
 #define ARCOFI_USE 0
 
-static inline u8
-icc_read_reg(struct IsdnCardState *cs, u8 addr)
-{
-	return cs->dc_hw_ops->read_reg(cs, addr);
-}
-
-static inline void
-icc_write_reg(struct IsdnCardState *cs, u8 addr, u8 val)
-{
-	cs->dc_hw_ops->write_reg(cs, addr, val);
-}
-
-static inline void
-icc_read_fifo(struct IsdnCardState *cs, u8 *p, int len)
-{
-	return cs->dc_hw_ops->read_fifo(cs, p, len);
-}
-
-static inline void
-icc_write_fifo(struct IsdnCardState *cs, u8 *p, int len)
-{
-	return cs->dc_hw_ops->write_fifo(cs, p, len);
-}
-
 static char *ICCVer[] __initdata =
 {"2070 A1/A3", "2070 B1", "2070 B2/B3", "2070 V2.4"};
 
-static void
+void
 ICCVersion(struct IsdnCardState *cs, char *s)
 {
 	int val;
 
-	val = icc_read_reg(cs, ICC_RBCH);
+	val = cs->readisac(cs, ICC_RBCH);
 	printk(KERN_INFO "%s ICC version (%x): %s\n", s, val, ICCVer[(val >> 5) & 3]);
 }
 
@@ -65,7 +41,7 @@ ph_command(struct IsdnCardState *cs, uns
 {
 	if (cs->debug & L1_DEB_ISAC)
 		debugl1(cs, "ph_command %x", command);
-	icc_write_reg(cs, ICC_CIX0, (command << 2) | 3);
+	cs->writeisac(cs, ICC_CIX0, (command << 2) | 3);
 }
 
 
@@ -101,9 +77,8 @@ icc_new_ph(struct IsdnCardState *cs)
 }
 
 static void
-icc_bh(void *data)
+icc_bh(struct IsdnCardState *cs)
 {
-	struct IsdnCardState *cs = data;
 	struct PStack *stptr;
 	
 	if (!cs)
@@ -113,7 +88,7 @@ icc_bh(void *data)
 			debugl1(cs, "D-Channel Busy cleared");
 		stptr = cs->stlist;
 		while (stptr != NULL) {
-			L1L2(stptr, PH_PAUSE | CONFIRM, NULL);
+			stptr->l1.l1l2(stptr, PH_PAUSE | CONFIRM, NULL);
 			stptr = stptr->next;
 		}
 	}
@@ -136,22 +111,58 @@ icc_bh(void *data)
 void
 icc_empty_fifo(struct IsdnCardState *cs, int count)
 {
-	recv_empty_fifo_d(cs, count);
-	icc_write_reg(cs, ICC_CMDR, 0x80);
+	u_char *ptr;
+
+	if ((cs->debug & L1_DEB_ISAC) && !(cs->debug & L1_DEB_ISAC_FIFO))
+		debugl1(cs, "icc_empty_fifo");
+
+	if ((cs->rcvidx + count) >= MAX_DFRAME_LEN_L1) {
+		if (cs->debug & L1_DEB_WARN)
+			debugl1(cs, "icc_empty_fifo overrun %d",
+				cs->rcvidx + count);
+		cs->writeisac(cs, ICC_CMDR, 0x80);
+		cs->rcvidx = 0;
+		return;
+	}
+	ptr = cs->rcvbuf + cs->rcvidx;
+	cs->rcvidx += count;
+	cs->readisacfifo(cs, ptr, count);
+	cs->writeisac(cs, ICC_CMDR, 0x80);
+	if (cs->debug & L1_DEB_ISAC_FIFO) {
+		char *t = cs->dlog;
+
+		t += sprintf(t, "icc_empty_fifo cnt %d", count);
+		QuickHex(t, ptr, count);
+		debugl1(cs, cs->dlog);
+	}
 }
 
 static void
 icc_fill_fifo(struct IsdnCardState *cs)
 {
 	int count, more;
-	unsigned char *p;
+	u_char *ptr;
+
+	if ((cs->debug & L1_DEB_ISAC) && !(cs->debug & L1_DEB_ISAC_FIFO))
+		debugl1(cs, "icc_fill_fifo");
 
-	p = xmit_fill_fifo_d(cs, 32, &count, &more);
-	if (!p)
+	if (!cs->tx_skb)
 		return;
 
-	icc_write_fifo(cs, p, count);
-	icc_write_reg(cs, ICC_CMDR, more ? 0x8 : 0xa);
+	count = cs->tx_skb->len;
+	if (count <= 0)
+		return;
+
+	more = 0;
+	if (count > 32) {
+		more = !0;
+		count = 32;
+	}
+	ptr = cs->tx_skb->data;
+	skb_pull(cs->tx_skb, count);
+	cs->tx_cnt += count;
+	cs->writeisacfifo(cs, ptr, count);
+	cs->writeisac(cs, ICC_CMDR, more ? 0x8 : 0xa);
 	if (test_and_set_bit(FLG_DBUSY_TIMER, &cs->HW_Flags)) {
 		debugl1(cs, "icc_fill_fifo dbusytimer running");
 		del_timer(&cs->dbusytimer);
@@ -159,18 +170,26 @@ icc_fill_fifo(struct IsdnCardState *cs)
 	init_timer(&cs->dbusytimer);
 	cs->dbusytimer.expires = jiffies + ((DBUSY_TIMER_VALUE * HZ)/1000);
 	add_timer(&cs->dbusytimer);
+	if (cs->debug & L1_DEB_ISAC_FIFO) {
+		char *t = cs->dlog;
+
+		t += sprintf(t, "icc_fill_fifo cnt %d", count);
+		QuickHex(t, ptr, count);
+		debugl1(cs, cs->dlog);
+	}
 }
 
 void
-icc_interrupt(struct IsdnCardState *cs, u8 val)
+icc_interrupt(struct IsdnCardState *cs, u_char val)
 {
-	u8 exval, v1;
+	u_char exval, v1;
+	struct sk_buff *skb;
 	unsigned int count;
 
 	if (cs->debug & L1_DEB_ISAC)
 		debugl1(cs, "ICC interrupt %x", val);
 	if (val & 0x80) {	/* RME */
-		exval = icc_read_reg(cs, ICC_RSTA);
+		exval = cs->readisac(cs, ICC_RSTA);
 		if ((exval & 0x70) != 0x20) {
 			if (exval & 0x40) {
 				if (cs->debug & L1_DEB_WARN)
@@ -186,15 +205,24 @@ icc_interrupt(struct IsdnCardState *cs, 
 				cs->err_crc++;
 #endif
 			}
-			icc_write_reg(cs, ICC_CMDR, 0x80);
-			cs->rcvidx = 0;
+			cs->writeisac(cs, ICC_CMDR, 0x80);
 		} else {
-			count = icc_read_reg(cs, ICC_RBCL) & 0x1f;
+			count = cs->readisac(cs, ICC_RBCL) & 0x1f;
 			if (count == 0)
 				count = 32;
 			icc_empty_fifo(cs, count);
-			recv_rme_d(cs);
+			if ((count = cs->rcvidx) > 0) {
+				cs->rcvidx = 0;
+				if (!(skb = alloc_skb(count, GFP_ATOMIC)))
+					printk(KERN_WARNING "HiSax: D receive out of memory\n");
+				else {
+					memcpy(skb_put(skb, count), cs->rcvbuf, count);
+					skb_queue_tail(&cs->rq, skb);
+				}
+			}
 		}
+		cs->rcvidx = 0;
+		schedule_event(cs, D_RCVBUFREADY);
 	}
 	if (val & 0x40) {	/* RPF */
 		icc_empty_fifo(cs, 32);
@@ -205,20 +233,39 @@ icc_interrupt(struct IsdnCardState *cs, 
 			debugl1(cs, "ICC RSC interrupt");
 	}
 	if (val & 0x10) {	/* XPR */
-		xmit_xpr_d(cs);
+		if (test_and_clear_bit(FLG_DBUSY_TIMER, &cs->HW_Flags))
+			del_timer(&cs->dbusytimer);
+		if (test_and_clear_bit(FLG_L1_DBUSY, &cs->HW_Flags))
+			schedule_event(cs, D_CLEARBUSY);
+		if (cs->tx_skb) {
+			if (cs->tx_skb->len) {
+				icc_fill_fifo(cs);
+				goto afterXPR;
+			} else {
+				dev_kfree_skb_irq(cs->tx_skb);
+				cs->tx_cnt = 0;
+				cs->tx_skb = NULL;
+			}
+		}
+		if ((cs->tx_skb = skb_dequeue(&cs->sq))) {
+			cs->tx_cnt = 0;
+			icc_fill_fifo(cs);
+		} else
+			schedule_event(cs, D_XMTBUFREADY);
 	}
+      afterXPR:
 	if (val & 0x04) {	/* CISQ */
-		exval = icc_read_reg(cs, ICC_CIR0);
+		exval = cs->readisac(cs, ICC_CIR0);
 		if (cs->debug & L1_DEB_ISAC)
 			debugl1(cs, "ICC CIR0 %02X", exval );
 		if (exval & 2) {
 			cs->dc.icc.ph_state = (exval >> 2) & 0xf;
 			if (cs->debug & L1_DEB_ISAC)
 				debugl1(cs, "ph_state change %x", cs->dc.icc.ph_state);
-			sched_d_event(cs, D_L1STATECHANGE);
+			schedule_event(cs, D_L1STATECHANGE);
 		}
 		if (exval & 1) {
-			exval = icc_read_reg(cs, ICC_CIR1);
+			exval = cs->readisac(cs, ICC_CIR1);
 			if (cs->debug & L1_DEB_ISAC)
 				debugl1(cs, "ICC CIR1 %02X", exval );
 		}
@@ -229,7 +276,7 @@ icc_interrupt(struct IsdnCardState *cs, 
 			debugl1(cs, "ICC SIN interrupt");
 	}
 	if (val & 0x01) {	/* EXI */
-		exval = icc_read_reg(cs, ICC_EXIR);
+		exval = cs->readisac(cs, ICC_EXIR);
 		if (cs->debug & L1_DEB_WARN)
 			debugl1(cs, "ICC EXIR %02x", exval);
 		if (exval & 0x80) {  /* XMR */
@@ -237,10 +284,26 @@ icc_interrupt(struct IsdnCardState *cs, 
 			printk(KERN_WARNING "HiSax: ICC XMR\n");
 		}
 		if (exval & 0x40) {  /* XDU */
-			xmit_xdu_d(cs, NULL);
+			debugl1(cs, "ICC XDU");
+			printk(KERN_WARNING "HiSax: ICC XDU\n");
+#ifdef ERROR_STATISTIC
+			cs->err_tx++;
+#endif
+			if (test_and_clear_bit(FLG_DBUSY_TIMER, &cs->HW_Flags))
+				del_timer(&cs->dbusytimer);
+			if (test_and_clear_bit(FLG_L1_DBUSY, &cs->HW_Flags))
+				schedule_event(cs, D_CLEARBUSY);
+			if (cs->tx_skb) { /* Restart frame */
+				skb_push(cs->tx_skb, cs->tx_cnt);
+				cs->tx_cnt = 0;
+				icc_fill_fifo(cs);
+			} else {
+				printk(KERN_WARNING "HiSax: ICC XDU no skb\n");
+				debugl1(cs, "ICC XDU no skb");
+			}
 		}
 		if (exval & 0x04) {  /* MOS */
-			v1 = icc_read_reg(cs, ICC_MOSR);
+			v1 = cs->readisac(cs, ICC_MOSR);
 			if (cs->debug & L1_DEB_MONITOR)
 				debugl1(cs, "ICC MOSR %02x", v1);
 #if ARCOFI_USE
@@ -251,7 +314,7 @@ icc_interrupt(struct IsdnCardState *cs, 
 							debugl1(cs, "ICC MON RX out of memory!");
 						cs->dc.icc.mocr &= 0xf0;
 						cs->dc.icc.mocr |= 0x0a;
-						icc_write_reg(cs, ICC_MOCR, cs->dc.icc.mocr);
+						cs->writeisac(cs, ICC_MOCR, cs->dc.icc.mocr);
 						goto afterMONR0;
 					} else
 						cs->dc.icc.mon_rxp = 0;
@@ -259,18 +322,18 @@ icc_interrupt(struct IsdnCardState *cs, 
 				if (cs->dc.icc.mon_rxp >= MAX_MON_FRAME) {
 					cs->dc.icc.mocr &= 0xf0;
 					cs->dc.icc.mocr |= 0x0a;
-					icc_write_reg(cs, ICC_MOCR, cs->dc.icc.mocr);
+					cs->writeisac(cs, ICC_MOCR, cs->dc.icc.mocr);
 					cs->dc.icc.mon_rxp = 0;
 					if (cs->debug & L1_DEB_WARN)
 						debugl1(cs, "ICC MON RX overflow!");
 					goto afterMONR0;
 				}
-				cs->dc.icc.mon_rx[cs->dc.icc.mon_rxp++] = icc_read_reg(cs, ICC_MOR0);
+				cs->dc.icc.mon_rx[cs->dc.icc.mon_rxp++] = cs->readisac(cs, ICC_MOR0);
 				if (cs->debug & L1_DEB_MONITOR)
 					debugl1(cs, "ICC MOR0 %02x", cs->dc.icc.mon_rx[cs->dc.icc.mon_rxp -1]);
 				if (cs->dc.icc.mon_rxp == 1) {
 					cs->dc.icc.mocr |= 0x04;
-					icc_write_reg(cs, ICC_MOCR, cs->dc.icc.mocr);
+					cs->writeisac(cs, ICC_MOCR, cs->dc.icc.mocr);
 				}
 			}
 		      afterMONR0:
@@ -281,7 +344,7 @@ icc_interrupt(struct IsdnCardState *cs, 
 							debugl1(cs, "ICC MON RX out of memory!");
 						cs->dc.icc.mocr &= 0x0f;
 						cs->dc.icc.mocr |= 0xa0;
-						icc_write_reg(cs, ICC_MOCR, cs->dc.icc.mocr);
+						cs->writeisac(cs, ICC_MOCR, cs->dc.icc.mocr);
 						goto afterMONR1;
 					} else
 						cs->dc.icc.mon_rxp = 0;
@@ -289,51 +352,51 @@ icc_interrupt(struct IsdnCardState *cs, 
 				if (cs->dc.icc.mon_rxp >= MAX_MON_FRAME) {
 					cs->dc.icc.mocr &= 0x0f;
 					cs->dc.icc.mocr |= 0xa0;
-					icc_write_reg(cs, ICC_MOCR, cs->dc.icc.mocr);
+					cs->writeisac(cs, ICC_MOCR, cs->dc.icc.mocr);
 					cs->dc.icc.mon_rxp = 0;
 					if (cs->debug & L1_DEB_WARN)
 						debugl1(cs, "ICC MON RX overflow!");
 					goto afterMONR1;
 				}
-				cs->dc.icc.mon_rx[cs->dc.icc.mon_rxp++] = icc_read_reg(cs, ICC_MOR1);
+				cs->dc.icc.mon_rx[cs->dc.icc.mon_rxp++] = cs->readisac(cs, ICC_MOR1);
 				if (cs->debug & L1_DEB_MONITOR)
 					debugl1(cs, "ICC MOR1 %02x", cs->dc.icc.mon_rx[cs->dc.icc.mon_rxp -1]);
 				cs->dc.icc.mocr |= 0x40;
-				icc_write_reg(cs, ICC_MOCR, cs->dc.icc.mocr);
+				cs->writeisac(cs, ICC_MOCR, cs->dc.icc.mocr);
 			}
 		      afterMONR1:
 			if (v1 & 0x04) {
 				cs->dc.icc.mocr &= 0xf0;
-				icc_write_reg(cs, ICC_MOCR, cs->dc.icc.mocr);
+				cs->writeisac(cs, ICC_MOCR, cs->dc.icc.mocr);
 				cs->dc.icc.mocr |= 0x0a;
-				icc_write_reg(cs, ICC_MOCR, cs->dc.icc.mocr);
-				sched_d_event(cs, D_RX_MON0);
+				cs->writeisac(cs, ICC_MOCR, cs->dc.icc.mocr);
+				schedule_event(cs, D_RX_MON0);
 			}
 			if (v1 & 0x40) {
 				cs->dc.icc.mocr &= 0x0f;
-				icc_write_reg(cs, ICC_MOCR, cs->dc.icc.mocr);
+				cs->writeisac(cs, ICC_MOCR, cs->dc.icc.mocr);
 				cs->dc.icc.mocr |= 0xa0;
-				icc_write_reg(cs, ICC_MOCR, cs->dc.icc.mocr);
-				sched_d_event(cs, D_RX_MON1);
+				cs->writeisac(cs, ICC_MOCR, cs->dc.icc.mocr);
+				schedule_event(cs, D_RX_MON1);
 			}
 			if (v1 & 0x02) {
 				if ((!cs->dc.icc.mon_tx) || (cs->dc.icc.mon_txc && 
 					(cs->dc.icc.mon_txp >= cs->dc.icc.mon_txc) && 
 					!(v1 & 0x08))) {
 					cs->dc.icc.mocr &= 0xf0;
-					icc_write_reg(cs, ICC_MOCR, cs->dc.icc.mocr);
+					cs->writeisac(cs, ICC_MOCR, cs->dc.icc.mocr);
 					cs->dc.icc.mocr |= 0x0a;
-					icc_write_reg(cs, ICC_MOCR, cs->dc.icc.mocr);
+					cs->writeisac(cs, ICC_MOCR, cs->dc.icc.mocr);
 					if (cs->dc.icc.mon_txc &&
 						(cs->dc.icc.mon_txp >= cs->dc.icc.mon_txc))
-						sched_d_event(cs, D_TX_MON0);
+						schedule_event(cs, D_TX_MON0);
 					goto AfterMOX0;
 				}
 				if (cs->dc.icc.mon_txc && (cs->dc.icc.mon_txp >= cs->dc.icc.mon_txc)) {
-					sched_d_event(cs, D_TX_MON0);
+					schedule_event(cs, D_TX_MON0);
 					goto AfterMOX0;
 				}
-				icc_write_reg(cs, ICC_MOX0,
+				cs->writeisac(cs, ICC_MOX0,
 					cs->dc.icc.mon_tx[cs->dc.icc.mon_txp++]);
 				if (cs->debug & L1_DEB_MONITOR)
 					debugl1(cs, "ICC %02x -> MOX0", cs->dc.icc.mon_tx[cs->dc.icc.mon_txp -1]);
@@ -344,19 +407,19 @@ icc_interrupt(struct IsdnCardState *cs, 
 					(cs->dc.icc.mon_txp >= cs->dc.icc.mon_txc) && 
 					!(v1 & 0x80))) {
 					cs->dc.icc.mocr &= 0x0f;
-					icc_write_reg(cs, ICC_MOCR, cs->dc.icc.mocr);
+					cs->writeisac(cs, ICC_MOCR, cs->dc.icc.mocr);
 					cs->dc.icc.mocr |= 0xa0;
-					icc_write_reg(cs, ICC_MOCR, cs->dc.icc.mocr);
+					cs->writeisac(cs, ICC_MOCR, cs->dc.icc.mocr);
 					if (cs->dc.icc.mon_txc &&
 						(cs->dc.icc.mon_txp >= cs->dc.icc.mon_txc))
-						sched_d_event(cs, D_TX_MON1);
+						schedule_event(cs, D_TX_MON1);
 					goto AfterMOX1;
 				}
 				if (cs->dc.icc.mon_txc && (cs->dc.icc.mon_txp >= cs->dc.icc.mon_txc)) {
-					sched_d_event(cs, D_TX_MON1);
+					schedule_event(cs, D_TX_MON1);
 					goto AfterMOX1;
 				}
-				icc_write_reg(cs, ICC_MOX1,
+				cs->writeisac(cs, ICC_MOX1,
 					cs->dc.icc.mon_tx[cs->dc.icc.mon_txp++]);
 				if (cs->debug & L1_DEB_MONITOR)
 					debugl1(cs, "ICC %02x -> MOX1", cs->dc.icc.mon_tx[cs->dc.icc.mon_txp -1]);
@@ -372,35 +435,91 @@ ICC_l1hw(struct PStack *st, int pr, void
 {
 	struct IsdnCardState *cs = (struct IsdnCardState *) st->l1.hardware;
 	struct sk_buff *skb = arg;
+	u_long flags;
 	int  val;
 
 	switch (pr) {
 		case (PH_DATA |REQUEST):
-			xmit_data_req_d(cs, skb);
+			if (cs->debug & DEB_DLOG_HEX)
+				LogFrame(cs, skb->data, skb->len);
+			if (cs->debug & DEB_DLOG_VERBOSE)
+				dlogframe(cs, skb, 0);
+			spin_lock_irqsave(&cs->lock, flags);
+			if (cs->tx_skb) {
+				skb_queue_tail(&cs->sq, skb);
+#ifdef L2FRAME_DEBUG		/* psa */
+				if (cs->debug & L1_DEB_LAPD)
+					Logl2Frame(cs, skb, "PH_DATA Queued", 0);
+#endif
+			} else {
+				cs->tx_skb = skb;
+				cs->tx_cnt = 0;
+#ifdef L2FRAME_DEBUG		/* psa */
+				if (cs->debug & L1_DEB_LAPD)
+					Logl2Frame(cs, skb, "PH_DATA", 0);
+#endif
+				icc_fill_fifo(cs);
+			}
+			spin_unlock_irqrestore(&cs->lock, flags);
 			break;
 		case (PH_PULL |INDICATION):
-			xmit_pull_ind_d(cs, skb);
+			spin_lock_irqsave(&cs->lock, flags);
+			if (cs->tx_skb) {
+				if (cs->debug & L1_DEB_WARN)
+					debugl1(cs, " l2l1 tx_skb exist this shouldn't happen");
+				skb_queue_tail(&cs->sq, skb);
+				break;
+			}
+			if (cs->debug & DEB_DLOG_HEX)
+				LogFrame(cs, skb->data, skb->len);
+			if (cs->debug & DEB_DLOG_VERBOSE)
+				dlogframe(cs, skb, 0);
+			cs->tx_skb = skb;
+			cs->tx_cnt = 0;
+#ifdef L2FRAME_DEBUG		/* psa */
+			if (cs->debug & L1_DEB_LAPD)
+				Logl2Frame(cs, skb, "PH_DATA_PULLED", 0);
+#endif
+			icc_fill_fifo(cs);
+			spin_unlock_irqrestore(&cs->lock, flags);
 			break;
 		case (PH_PULL | REQUEST):
-			xmit_pull_req_d(st);
+#ifdef L2FRAME_DEBUG		/* psa */
+			if (cs->debug & L1_DEB_LAPD)
+				debugl1(cs, "-> PH_REQUEST_PULL");
+#endif
+			if (!cs->tx_skb) {
+				test_and_clear_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
+				st->l1.l1l2(st, PH_PULL | CONFIRM, NULL);
+			} else
+				test_and_set_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
 			break;
 		case (HW_RESET | REQUEST):
+			spin_lock_irqsave(&cs->lock, flags);
 			if ((cs->dc.icc.ph_state == ICC_IND_EI1) ||
 				(cs->dc.icc.ph_state == ICC_IND_DR))
 			        ph_command(cs, ICC_CMD_DI);
 			else
 				ph_command(cs, ICC_CMD_RES);
+			spin_unlock_irqrestore(&cs->lock, flags);
 			break;
 		case (HW_ENABLE | REQUEST):
+			spin_lock_irqsave(&cs->lock, flags);
 			ph_command(cs, ICC_CMD_DI);
+			spin_unlock_irqrestore(&cs->lock, flags);
 			break;
 		case (HW_INFO1 | REQUEST):
+			spin_lock_irqsave(&cs->lock, flags);
 			ph_command(cs, ICC_CMD_AR);
+			spin_unlock_irqrestore(&cs->lock, flags);
 			break;
 		case (HW_INFO3 | REQUEST):
+			spin_lock_irqsave(&cs->lock, flags);
 			ph_command(cs, ICC_CMD_AI);
+			spin_unlock_irqrestore(&cs->lock, flags);
 			break;
 		case (HW_TESTLOOP | REQUEST):
+			spin_lock_irqsave(&cs->lock, flags);
 			val = 0;
 			if (1 & (long) arg)
 				val |= 0x0c;
@@ -409,20 +528,21 @@ ICC_l1hw(struct PStack *st, int pr, void
 			if (test_bit(HW_IOM1, &cs->HW_Flags)) {
 				/* IOM 1 Mode */
 				if (!val) {
-					icc_write_reg(cs, ICC_SPCR, 0xa);
-					icc_write_reg(cs, ICC_ADF1, 0x2);
+					cs->writeisac(cs, ICC_SPCR, 0xa);
+					cs->writeisac(cs, ICC_ADF1, 0x2);
 				} else {
-					icc_write_reg(cs, ICC_SPCR, val);
-					icc_write_reg(cs, ICC_ADF1, 0xa);
+					cs->writeisac(cs, ICC_SPCR, val);
+					cs->writeisac(cs, ICC_ADF1, 0xa);
 				}
 			} else {
 				/* IOM 2 Mode */
-				icc_write_reg(cs, ICC_SPCR, val);
+				cs->writeisac(cs, ICC_SPCR, val);
 				if (val)
-					icc_write_reg(cs, ICC_ADF1, 0x8);
+					cs->writeisac(cs, ICC_ADF1, 0x8);
 				else
-					icc_write_reg(cs, ICC_ADF1, 0x0);
+					cs->writeisac(cs, ICC_ADF1, 0x0);
 			}
+			spin_unlock_irqrestore(&cs->lock, flags);
 			break;
 		case (HW_DEACTIVATE | RESPONSE):
 			skb_queue_purge(&cs->rq);
@@ -434,7 +554,7 @@ ICC_l1hw(struct PStack *st, int pr, void
 			if (test_and_clear_bit(FLG_DBUSY_TIMER, &cs->HW_Flags))
 				del_timer(&cs->dbusytimer);
 			if (test_and_clear_bit(FLG_L1_DBUSY, &cs->HW_Flags))
-				sched_d_event(cs, D_CLEARBUSY);
+				schedule_event(cs, D_CLEARBUSY);
 			break;
 		default:
 			if (cs->debug & L1_DEB_WARN)
@@ -443,11 +563,10 @@ ICC_l1hw(struct PStack *st, int pr, void
 	}
 }
 
-static int
+void
 setstack_icc(struct PStack *st, struct IsdnCardState *cs)
 {
 	st->l1.l1hw = ICC_l1hw;
-	return 0;
 }
 
 void 
@@ -469,8 +588,8 @@ dbusy_timer_handler(struct IsdnCardState
 	int	rbch, star;
 
 	if (test_bit(FLG_DBUSY_TIMER, &cs->HW_Flags)) {
-		rbch = icc_read_reg(cs, ICC_RBCH);
-		star = icc_read_reg(cs, ICC_STAR);
+		rbch = cs->readisac(cs, ICC_RBCH);
+		star = cs->readisac(cs, ICC_STAR);
 		if (cs->debug) 
 			debugl1(cs, "D-Channel Busy RBCH %02x STAR %02x",
 				rbch, star);
@@ -478,7 +597,7 @@ dbusy_timer_handler(struct IsdnCardState
 			test_and_set_bit(FLG_L1_DBUSY, &cs->HW_Flags);
 			stptr = cs->stlist;
 			while (stptr != NULL) {
-				L1L2(stptr, PH_PAUSE | INDICATION, NULL);
+				stptr->l1.l1l2(stptr, PH_PAUSE | INDICATION, NULL);
 				stptr = stptr->next;
 			}
 		} else {
@@ -492,77 +611,75 @@ dbusy_timer_handler(struct IsdnCardState
 				printk(KERN_WARNING "HiSax: ICC D-Channel Busy no skb\n");
 				debugl1(cs, "D-Channel Busy no skb");
 			}
-			icc_write_reg(cs, ICC_CMDR, 0x01); /* Transmitter reset */
-			cs->card_ops->irq_func(cs->irq, cs, NULL); /* FIXME? */
+			cs->writeisac(cs, ICC_CMDR, 0x01); /* Transmitter reset */
+			cs->irq_func(cs->irq, cs, NULL);
 		}
 	}
 }
 
-static struct dc_l1_ops icc_l1_ops = {
-	.fill_fifo  = icc_fill_fifo,
-	.open       = setstack_icc,
-	.close      = DC_Close_icc,
-	.bh_func    = icc_bh,
-	.dbusy_func = dbusy_timer_handler,
-};
-
 void __init
 initicc(struct IsdnCardState *cs)
 {
-	int val, eval;
-
-	dc_l1_init(cs, &icc_l1_ops);
+	cs->setstack_d = setstack_icc;
+	cs->DC_Close = DC_Close_icc;
 	cs->dc.icc.mon_tx = NULL;
 	cs->dc.icc.mon_rx = NULL;
+  	cs->writeisac(cs, ICC_MASK, 0xff);
+  	cs->dc.icc.mocr = 0xaa;
+	if (test_bit(HW_IOM1, &cs->HW_Flags)) {
+		/* IOM 1 Mode */
+		cs->writeisac(cs, ICC_ADF2, 0x0);
+		cs->writeisac(cs, ICC_SPCR, 0xa);
+		cs->writeisac(cs, ICC_ADF1, 0x2);
+		cs->writeisac(cs, ICC_STCR, 0x70);
+		cs->writeisac(cs, ICC_MODE, 0xc9);
+	} else {
+		/* IOM 2 Mode */
+		if (!cs->dc.icc.adf2)
+			cs->dc.icc.adf2 = 0x80;
+		cs->writeisac(cs, ICC_ADF2, cs->dc.icc.adf2);
+		cs->writeisac(cs, ICC_SQXR, 0xa0);
+		cs->writeisac(cs, ICC_SPCR, 0x20);
+		cs->writeisac(cs, ICC_STCR, 0x70);
+		cs->writeisac(cs, ICC_MODE, 0xca);
+		cs->writeisac(cs, ICC_TIMR, 0x00);
+		cs->writeisac(cs, ICC_ADF1, 0x20);
+	}
+	ph_command(cs, ICC_CMD_RES);
+	cs->writeisac(cs, ICC_MASK, 0x0);
+	ph_command(cs, ICC_CMD_DI);
+}
+
+void __init
+clear_pending_icc_ints(struct IsdnCardState *cs)
+{
+	int val, eval;
 
-	val = icc_read_reg(cs, ICC_STAR);
+	val = cs->readisac(cs, ICC_STAR);
 	debugl1(cs, "ICC STAR %x", val);
-	val = icc_read_reg(cs, ICC_MODE);
+	val = cs->readisac(cs, ICC_MODE);
 	debugl1(cs, "ICC MODE %x", val);
-	val = icc_read_reg(cs, ICC_ADF2);
+	val = cs->readisac(cs, ICC_ADF2);
 	debugl1(cs, "ICC ADF2 %x", val);
-	val = icc_read_reg(cs, ICC_ISTA);
+	val = cs->readisac(cs, ICC_ISTA);
 	debugl1(cs, "ICC ISTA %x", val);
 	if (val & 0x01) {
-		eval = icc_read_reg(cs, ICC_EXIR);
+		eval = cs->readisac(cs, ICC_EXIR);
 		debugl1(cs, "ICC EXIR %x", eval);
 	}
-	val = icc_read_reg(cs, ICC_CIR0);
+	val = cs->readisac(cs, ICC_CIR0);
 	debugl1(cs, "ICC CIR0 %x", val);
 	cs->dc.icc.ph_state = (val >> 2) & 0xf;
-	sched_d_event(cs, D_L1STATECHANGE);
+	schedule_event(cs, D_L1STATECHANGE);
 	/* Disable all IRQ */
-	icc_write_reg(cs, ICC_MASK, 0xFF);
-
-  	cs->dc.icc.mocr = 0xaa;
-	if (test_bit(HW_IOM1, &cs->HW_Flags)) {
-		/* IOM 1 Mode */
-		icc_write_reg(cs, ICC_ADF2, 0x0);
-		icc_write_reg(cs, ICC_SPCR, 0xa);
-		icc_write_reg(cs, ICC_ADF1, 0x2);
-		icc_write_reg(cs, ICC_STCR, 0x70);
-		icc_write_reg(cs, ICC_MODE, 0xc9);
-	} else {
-		/* IOM 2 Mode */
-		if (!cs->dc.icc.adf2)
-			cs->dc.icc.adf2 = 0x80;
-		icc_write_reg(cs, ICC_ADF2, cs->dc.icc.adf2);
-		icc_write_reg(cs, ICC_SQXR, 0xa0);
-		icc_write_reg(cs, ICC_SPCR, 0x20);
-		icc_write_reg(cs, ICC_STCR, 0x70);
-		icc_write_reg(cs, ICC_MODE, 0xca);
-		icc_write_reg(cs, ICC_TIMR, 0x00);
-		icc_write_reg(cs, ICC_ADF1, 0x20);
-	}
-	ph_command(cs, ICC_CMD_RES);
-	icc_write_reg(cs, ICC_MASK, 0x0);
-	ph_command(cs, ICC_CMD_DI);
+	cs->writeisac(cs, ICC_MASK, 0xFF);
 }
 
-int
-icc_setup(struct IsdnCardState *cs, struct dc_hw_ops *icc_ops)
+void __devinit
+setup_icc(struct IsdnCardState *cs)
 {
-	cs->dc_hw_ops = icc_ops;
-	ICCVersion(cs, "HiSax:");
-	return 0;
+	INIT_WORK(&cs->tqueue, (void *)(void *) icc_bh, cs);
+	cs->dbusytimer.function = (void *) dbusy_timer_handler;
+	cs->dbusytimer.data = (long) cs;
+	init_timer(&cs->dbusytimer);
 }
--- diff/drivers/isdn/hisax/icc.h	2003-01-16 11:30:36.000000000 +0000
+++ source/drivers/isdn/hisax/icc.h	2004-02-23 13:56:42.000000000 +0000
@@ -1,4 +1,4 @@
-/* $Id: icc.h,v 1.2.6.3 2001/09/23 22:24:48 kai Exp $
+/* $Id: icc.h,v 1.4.2.2 2004/01/12 22:52:26 keil Exp $
  *
  * ICC specific routines
  *
@@ -65,6 +65,8 @@
 #define ICC_IND_AIL    0xE
 #define ICC_IND_DC     0xF
 
-extern int  icc_setup(struct IsdnCardState *cs, struct dc_hw_ops *icc_ops);
+extern void ICCVersion(struct IsdnCardState *cs, char *s);
 extern void initicc(struct IsdnCardState *cs);
-extern void icc_interrupt(struct IsdnCardState *cs, u8 val);
+extern void icc_interrupt(struct IsdnCardState *cs, u_char val);
+extern void clear_pending_icc_ints(struct IsdnCardState *cs);
+extern void setup_icc(struct IsdnCardState *);
--- diff/drivers/isdn/hisax/ipac.h	2003-05-21 11:50:15.000000000 +0100
+++ source/drivers/isdn/hisax/ipac.h	2004-02-23 13:56:42.000000000 +0000
@@ -1,4 +1,4 @@
-/* $Id: ipac.h,v 1.5.6.2 2001/09/23 22:24:49 kai Exp $
+/* $Id: ipac.h,v 1.7.2.2 2004/01/12 22:52:26 keil Exp $
  *
  * IPAC specific defines
  *
@@ -10,8 +10,6 @@
  *
  */
 
-#include <linux/interrupt.h>
-
 /* All Registers original Siemens Spec  */
 
 #define IPAC_CONF	0xC0
@@ -29,76 +27,3 @@
 #define IPAC_PCFG	0xCA
 #define IPAC_SCFG	0xCB
 #define IPAC_TIMR2	0xCC
-
-void ipac_init(struct IsdnCardState *cs);
-irqreturn_t ipac_irq(int intno, void *dev_id, struct pt_regs *regs);
-int  ipac_setup(struct IsdnCardState *cs, struct dc_hw_ops *ipac_dc_ops,
-		struct bc_hw_ops *ipac_bc_ops);
-
-/* Macro to build the needed D- and B-Channel access routines given
- * access functions for the IPAC */
-
-#define BUILD_IPAC_OPS(ipac)                                                  \
-                                                                              \
-static u8                                                                     \
-ipac ## _dc_read(struct IsdnCardState *cs, u8 offset)                         \
-{                                                                             \
-	return ipac ## _read(cs, offset+0x80);                                \
-}                                                                             \
-                                                                              \
-static void                                                                   \
-ipac ## _dc_write(struct IsdnCardState *cs, u8 offset, u8 value)              \
-{                                                                             \
-	ipac ## _write(cs, offset+0x80, value);                               \
-}                                                                             \
-                                                                              \
-static void                                                                   \
-ipac ## _dc_read_fifo(struct IsdnCardState *cs, u8 * data, int size)          \
-{                                                                             \
-	ipac ## _readfifo(cs, 0x80, data, size);                              \
-}                                                                             \
-                                                                              \
-static void                                                                   \
-ipac ## _dc_write_fifo(struct IsdnCardState *cs, u8 * data, int size)         \
-{                                                                             \
-	ipac ## _writefifo(cs, 0x80, data, size);                             \
-}                                                                             \
-                                                                              \
-static struct dc_hw_ops ipac ## _dc_ops = {                                   \
-	.read_reg   = ipac ## _dc_read,                                       \
-	.write_reg  = ipac ## _dc_write,                                      \
-	.read_fifo  = ipac ## _dc_read_fifo,                                  \
-	.write_fifo = ipac ## _dc_write_fifo,                                 \
-};                                                                            \
-                                                                              \
-static u8                                                                     \
-ipac ## _bc_read(struct IsdnCardState *cs, int hscx, u8 offset)               \
-{                                                                             \
-	return ipac ## _read(cs, offset + (hscx ? 0x40 : 0));                 \
-}                                                                             \
-                                                                              \
-static void                                                                   \
-ipac ## _bc_write(struct IsdnCardState *cs, int hscx, u8 offset, u8 value)    \
-{                                                                             \
-	ipac ## _write(cs, offset + (hscx ? 0x40 : 0), value);                \
-}                                                                             \
-                                                                              \
-static void                                                                   \
-ipac ## _bc_read_fifo(struct IsdnCardState *cs, int hscx, u8 *data, int size) \
-{                                                                             \
-	ipac ## _readfifo(cs, hscx ? 0x40 : 0, data, size);                   \
-}                                                                             \
-                                                                              \
-static void                                                                   \
-ipac ## _bc_write_fifo(struct IsdnCardState *cs, int hscx, u8 *data, int size)\
-{                                                                             \
-	ipac ## _writefifo(cs, hscx ? 0x40 : 0, data, size);                  \
-}                                                                             \
-                                                                              \
-static struct bc_hw_ops ipac ## _bc_ops = {                                   \
-	.read_reg   = ipac ## _bc_read,                                       \
-	.write_reg  = ipac ## _bc_write,                                      \
-	.read_fifo  = ipac ## _bc_read_fifo,                                  \
-	.write_fifo = ipac ## _bc_write_fifo,                                 \
-}
-
--- diff/drivers/isdn/hisax/ipacx.c	2003-09-17 12:28:06.000000000 +0100
+++ source/drivers/isdn/hisax/ipacx.c	2004-02-23 13:56:42.000000000 +0000
@@ -12,7 +12,6 @@
 #include <linux/kernel.h>
 #include <linux/config.h>
 #include <linux/init.h>
-#include <linux/workqueue.h>
 #include "hisax_if.h"
 #include "hisax.h"
 #include "isdnl1.h"
@@ -24,6 +23,7 @@
 #define B_FIFO_SIZE       64
 #define D_FIFO_SIZE       32
 
+
 // ipacx interrupt mask values    
 #define _MASK_IMASK     0x2E  // global mask
 #define _MASKB_IMASK    0x0B
@@ -37,13 +37,16 @@ static inline void cic_int(struct IsdnCa
 static void dch_l2l1(struct PStack *st, int pr, void *arg);
 static void dbusy_timer_handler(struct IsdnCardState *cs);
 static void ipacx_new_ph(struct IsdnCardState *cs);
-static void dch_bh(void *data);
+static void dch_bh(struct IsdnCardState *cs);
 static void dch_empty_fifo(struct IsdnCardState *cs, int count);
 static void dch_fill_fifo(struct IsdnCardState *cs);
 static inline void dch_int(struct IsdnCardState *cs);
+static void __devinit dch_setstack(struct PStack *st, struct IsdnCardState *cs);
+static void __devinit dch_init(struct IsdnCardState *cs);
 static void bch_l2l1(struct PStack *st, int pr, void *arg);
-static void ipacx_bc_empty_fifo(struct BCState *bcs, int count);
-static void bch_int(struct IsdnCardState *cs, u8 hscx);
+static void bch_empty_fifo(struct BCState *bcs, int count);
+static void bch_fill_fifo(struct BCState *bcs);
+static void bch_int(struct IsdnCardState *cs, u_char hscx);
 static void bch_mode(struct BCState *bcs, int mode, int bc);
 static void bch_close_state(struct BCState *bcs);
 static int bch_open_state(struct IsdnCardState *cs, struct BCState *bcs);
@@ -51,45 +54,6 @@ static int bch_setstack(struct PStack *s
 static void __devinit bch_init(struct IsdnCardState *cs, int hscx);
 static void __init clear_pending_ints(struct IsdnCardState *cs);
 
-static inline u8
-ipacx_bc_read_reg(struct BCState *bcs, u8 addr)
-{
-	struct IsdnCardState *cs = bcs->cs;
-
-	return cs->bc_hw_ops->read_reg(cs, bcs->unit, addr);
-}
-
-static inline void
-ipacx_bc_write_reg(struct BCState *bcs, u8 addr, u8 val)
-{
-	struct IsdnCardState *cs = bcs->cs;
-
-	cs->bc_hw_ops->write_reg(cs, bcs->unit, addr, val);
-}
-
-static inline u8
-ipacx_read_reg(struct IsdnCardState *cs, u8 addr)
-{
-	return cs->dc_hw_ops->read_reg(cs, addr);
-}
-
-static inline void
-ipacx_write_reg(struct IsdnCardState *cs, u8 addr, u8 val)
-{
-	cs->dc_hw_ops->write_reg(cs, addr, val);
-}
-
-static inline void
-ipacx_read_fifo(struct IsdnCardState *cs, u8 *p, int len)
-{
-	return cs->dc_hw_ops->read_fifo(cs, p, len);
-}
-
-static inline void
-ipacx_write_fifo(struct IsdnCardState *cs, u8 *p, int len)
-{
-	return cs->dc_hw_ops->write_fifo(cs, p, len);
-}
 //----------------------------------------------------------
 // Issue Layer 1 command to chip
 //----------------------------------------------------------
@@ -99,7 +63,10 @@ ph_command(struct IsdnCardState *cs, uns
 	if (cs->debug &L1_DEB_ISAC)
 		debugl1(cs, "ph_command (%#x) in (%#x)", command,
 			cs->dc.isac.ph_state);
-	ipacx_write_reg(cs, IPACX_CIX0, (command << 4) | 0x0E);
+//###################################  
+//	printk(KERN_INFO "ph_command (%#x)\n", command);
+//###################################  
+	cs->writeisac(cs, IPACX_CIX0, (command << 4) | 0x0E);
 }
 
 //----------------------------------------------------------
@@ -108,12 +75,15 @@ ph_command(struct IsdnCardState *cs, uns
 static inline void 
 cic_int(struct IsdnCardState *cs)
 {
-	u8 event;
+	u_char event;
 
-	event = ipacx_read_reg(cs, IPACX_CIR0) >> 4;
+	event = cs->readisac(cs, IPACX_CIR0) >> 4;
 	if (cs->debug &L1_DEB_ISAC) debugl1(cs, "cic_int(event=%#x)", event);
-	cs->dc.isac.ph_state = event;
-	sched_d_event(cs, D_L1STATECHANGE);
+//#########################################  
+//	printk(KERN_INFO "cic_int(%x)\n", event);
+//#########################################  
+  cs->dc.isac.ph_state = event;
+  schedule_event(cs, D_L1STATECHANGE);
 }
 
 //==========================================================
@@ -128,21 +98,63 @@ dch_l2l1(struct PStack *st, int pr, void
 {
 	struct IsdnCardState *cs = (struct IsdnCardState *) st->l1.hardware;
 	struct sk_buff *skb = arg;
-  u8 cda1_cr, cda2_cr;
+  u_char cda1_cr, cda2_cr;
 
 	switch (pr) {
 		case (PH_DATA |REQUEST):
-			xmit_data_req_d(cs, skb);
+			if (cs->debug &DEB_DLOG_HEX)     LogFrame(cs, skb->data, skb->len);
+			if (cs->debug &DEB_DLOG_VERBOSE) dlogframe(cs, skb, 0);
+			if (cs->tx_skb) {
+				skb_queue_tail(&cs->sq, skb);
+#ifdef L2FRAME_DEBUG
+				if (cs->debug &L1_DEB_LAPD) Logl2Frame(cs, skb, "PH_DATA Queued", 0);
+#endif
+			} else {
+				cs->tx_skb = skb;
+				cs->tx_cnt = 0;
+#ifdef L2FRAME_DEBUG
+				if (cs->debug &L1_DEB_LAPD) Logl2Frame(cs, skb, "PH_DATA", 0);
+#endif
+				dch_fill_fifo(cs);
+			}
 			break;
+      
 		case (PH_PULL |INDICATION):
-			xmit_pull_ind_d(cs, skb);
+			if (cs->tx_skb) {
+				if (cs->debug & L1_DEB_WARN)
+					debugl1(cs, " l2l1 tx_skb exist this shouldn't happen");
+				skb_queue_tail(&cs->sq, skb);
+				break;
+			}
+			if (cs->debug & DEB_DLOG_HEX)     LogFrame(cs, skb->data, skb->len);
+			if (cs->debug & DEB_DLOG_VERBOSE) dlogframe(cs, skb, 0);
+			cs->tx_skb = skb;
+			cs->tx_cnt = 0;
+#ifdef L2FRAME_DEBUG
+			if (cs->debug & L1_DEB_LAPD) Logl2Frame(cs, skb, "PH_DATA_PULLED", 0);
+#endif
+			dch_fill_fifo(cs);
 			break;
+      
 		case (PH_PULL | REQUEST):
-			xmit_pull_req_d(st);
+#ifdef L2FRAME_DEBUG
+			if (cs->debug & L1_DEB_LAPD) debugl1(cs, "-> PH_REQUEST_PULL");
+#endif
+			if (!cs->tx_skb) {
+				clear_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
+				st->l1.l1l2(st, PH_PULL | CONFIRM, NULL);
+			} else
+				set_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
 			break;
+
 		case (HW_RESET | REQUEST):
 		case (HW_ENABLE | REQUEST):
-			ph_command(cs, IPACX_CMD_TIM);
+			if ((cs->dc.isac.ph_state == IPACX_IND_RES) ||
+				(cs->dc.isac.ph_state == IPACX_IND_DR) ||
+				(cs->dc.isac.ph_state == IPACX_IND_DC))
+			        ph_command(cs, IPACX_CMD_TIM);
+			else
+				ph_command(cs, IPACX_CMD_RES);
 			break;
 
 		case (HW_INFO3 | REQUEST):
@@ -150,21 +162,21 @@ dch_l2l1(struct PStack *st, int pr, void
 			break;
 
 		case (HW_TESTLOOP | REQUEST):
-      ipacx_write_reg(cs, IPACX_CDA_TSDP10, 0x80); // Timeslot 0 is B1
-      ipacx_write_reg(cs, IPACX_CDA_TSDP11, 0x81); // Timeslot 0 is B1
-      cda1_cr = ipacx_read_reg(cs, IPACX_CDA1_CR);
-      cda2_cr = ipacx_read_reg(cs, IPACX_CDA2_CR);
+      cs->writeisac(cs, IPACX_CDA_TSDP10, 0x80); // Timeslot 0 is B1
+      cs->writeisac(cs, IPACX_CDA_TSDP11, 0x81); // Timeslot 0 is B1
+      cda1_cr = cs->readisac(cs, IPACX_CDA1_CR);
+      cda2_cr = cs->readisac(cs, IPACX_CDA2_CR);
 			if ((long)arg &1) { // loop B1
-        ipacx_write_reg(cs, IPACX_CDA1_CR, cda1_cr |0x0a); 
+        cs->writeisac(cs, IPACX_CDA1_CR, cda1_cr |0x0a); 
       }
       else {  // B1 off
-        ipacx_write_reg(cs, IPACX_CDA1_CR, cda1_cr &~0x0a); 
+        cs->writeisac(cs, IPACX_CDA1_CR, cda1_cr &~0x0a); 
       }
 			if ((long)arg &2) { // loop B2
-        ipacx_write_reg(cs, IPACX_CDA1_CR, cda1_cr |0x14); 
+        cs->writeisac(cs, IPACX_CDA1_CR, cda1_cr |0x14); 
       }
       else {  // B2 off
-        ipacx_write_reg(cs, IPACX_CDA1_CR, cda1_cr &~0x14); 
+        cs->writeisac(cs, IPACX_CDA1_CR, cda1_cr &~0x14); 
       }
 			break;
 
@@ -194,14 +206,14 @@ dbusy_timer_handler(struct IsdnCardState
 	int	rbchd, stard;
 
 	if (test_bit(FLG_DBUSY_TIMER, &cs->HW_Flags)) {
-		rbchd = ipacx_read_reg(cs, IPACX_RBCHD);
-		stard = ipacx_read_reg(cs, IPACX_STARD);
+		rbchd = cs->readisac(cs, IPACX_RBCHD);
+		stard = cs->readisac(cs, IPACX_STARD);
 		if (cs->debug) 
       debugl1(cs, "D-Channel Busy RBCHD %02x STARD %02x", rbchd, stard);
 		if (!(stard &0x40)) { // D-Channel Busy
 			set_bit(FLG_L1_DBUSY, &cs->HW_Flags);
       for (st = cs->stlist; st; st = st->next) {
-				st->l2.l1l2(st, PH_PAUSE | INDICATION, NULL); // flow control on
+				st->l1.l1l2(st, PH_PAUSE | INDICATION, NULL); // flow control on
 			}
 		} else {
 			// seems we lost an interrupt; reset transceiver */
@@ -214,7 +226,7 @@ dbusy_timer_handler(struct IsdnCardState
 				printk(KERN_WARNING "HiSax: ISAC D-Channel Busy no skb\n");
 				debugl1(cs, "D-Channel Busy no skb");
 			}
-			ipacx_write_reg(cs, IPACX_CMDRD, 0x01); // Tx reset, generates XPR
+			cs->writeisac(cs, IPACX_CMDRD, 0x01); // Tx reset, generates XPR
 		}
 	}
 }
@@ -268,9 +280,8 @@ ipacx_new_ph(struct IsdnCardState *cs)
 // bottom half handler for D channel
 //----------------------------------------------------------
 static void
-dch_bh(void *data)
+dch_bh(struct IsdnCardState *cs)
 {
-	struct IsdnCardState *cs = data;
 	struct PStack *st;
 	
 	if (!cs) return;
@@ -278,7 +289,7 @@ dch_bh(void *data)
 	if (test_and_clear_bit(D_CLEARBUSY, &cs->event)) {
 		if (cs->debug) debugl1(cs, "D-Channel Busy cleared");
 		for (st = cs->stlist; st; st = st->next) {
-			st->l2.l1l2(st, PH_PAUSE | CONFIRM, NULL);
+			st->l1.l1l2(st, PH_PAUSE | CONFIRM, NULL);
 		}
 	}
   
@@ -301,8 +312,33 @@ dch_bh(void *data)
 static void 
 dch_empty_fifo(struct IsdnCardState *cs, int count)
 {
-	recv_empty_fifo_d(cs, count);
-	ipacx_write_reg(cs, IPACX_CMDRD, 0x80); // RMC
+	u_char *ptr;
+
+	if ((cs->debug &L1_DEB_ISAC) && !(cs->debug &L1_DEB_ISAC_FIFO))
+		debugl1(cs, "dch_empty_fifo()");
+
+  // message too large, remove
+	if ((cs->rcvidx + count) >= MAX_DFRAME_LEN_L1) {
+		if (cs->debug &L1_DEB_WARN)
+			debugl1(cs, "dch_empty_fifo() incoming message too large");
+	  cs->writeisac(cs, IPACX_CMDRD, 0x80); // RMC
+		cs->rcvidx = 0;
+		return;
+	}
+  
+	ptr = cs->rcvbuf + cs->rcvidx;
+	cs->rcvidx += count;
+  
+	cs->readisacfifo(cs, ptr, count);
+	cs->writeisac(cs, IPACX_CMDRD, 0x80); // RMC
+  
+	if (cs->debug &L1_DEB_ISAC_FIFO) {
+		char *t = cs->dlog;
+
+		t += sprintf(t, "dch_empty_fifo() cnt %d", count);
+		QuickHex(t, ptr, count);
+		debugl1(cs, cs->dlog);
+	}
 }
 
 //----------------------------------------------------------
@@ -311,21 +347,28 @@ dch_empty_fifo(struct IsdnCardState *cs,
 static void 
 dch_fill_fifo(struct IsdnCardState *cs)
 {
-	int count, more;
-	unsigned char cmd, *p;
+	int count;
+	u_char cmd, *ptr;
 
-	p = xmit_fill_fifo_d(cs, 32, &count, &more);
-	if (!p)
-		return;
+	if ((cs->debug &L1_DEB_ISAC) && !(cs->debug &L1_DEB_ISAC_FIFO))
+		debugl1(cs, "dch_fill_fifo()");
+    
+	if (!cs->tx_skb) return;
+	count = cs->tx_skb->len;
+	if (count <= 0) return;
 
-	if (more) {
+	if (count > D_FIFO_SIZE) {
+		count = D_FIFO_SIZE;
 		cmd   = 0x08; // XTF
 	} else {
 		cmd   = 0x0A; // XTF | XME
 	}
   
-	ipacx_write_fifo(cs, p, count);
-	ipacx_write_reg(cs, IPACX_CMDRD, cmd);
+	ptr = cs->tx_skb->data;
+	skb_pull(cs->tx_skb, count);
+	cs->tx_cnt += count;
+	cs->writeisacfifo(cs, ptr, count);
+	cs->writeisac(cs, IPACX_CMDRD, cmd);
   
   // set timeout for transmission contol
 	if (test_and_set_bit(FLG_DBUSY_TIMER, &cs->HW_Flags)) {
@@ -335,6 +378,14 @@ dch_fill_fifo(struct IsdnCardState *cs)
 	init_timer(&cs->dbusytimer);
 	cs->dbusytimer.expires = jiffies + ((DBUSY_TIMER_VALUE * HZ)/1000);
 	add_timer(&cs->dbusytimer);
+  
+	if (cs->debug &L1_DEB_ISAC_FIFO) {
+		char *t = cs->dlog;
+
+		t += sprintf(t, "dch_fill_fifo() cnt %d", count);
+		QuickHex(t, ptr, count);
+		debugl1(cs, cs->dlog);
+	}
 }
 
 //----------------------------------------------------------
@@ -343,35 +394,46 @@ dch_fill_fifo(struct IsdnCardState *cs)
 static inline void 
 dch_int(struct IsdnCardState *cs)
 {
-	u8 istad, rstad;
+	struct sk_buff *skb;
+	u_char istad, rstad;
 	int count;
 
-	istad = ipacx_read_reg(cs, IPACX_ISTAD);
+	istad = cs->readisac(cs, IPACX_ISTAD);
+//##############################################  
+//	printk(KERN_WARNING "dch_int(istad=%02x)\n", istad);
+//##############################################  
   
 	if (istad &0x80) {  // RME
-	  rstad = ipacx_read_reg(cs, IPACX_RSTAD);
+	  rstad = cs->readisac(cs, IPACX_RSTAD);
 		if ((rstad &0xf0) != 0xa0) { // !(VFR && !RDO && CRC && !RAB)
 			if (!(rstad &0x80))
 				if (cs->debug &L1_DEB_WARN) 
-					debugl1(cs, "dch_int(): invalid frame");
+          debugl1(cs, "dch_int(): invalid frame");
 			if ((rstad &0x40))
 				if (cs->debug &L1_DEB_WARN) 
-					debugl1(cs, "dch_int(): RDO");
+          debugl1(cs, "dch_int(): RDO");
 			if (!(rstad &0x20))
 				if (cs->debug &L1_DEB_WARN) 
-					debugl1(cs, "dch_int(): CRC error");
-			ipacx_write_reg(cs, IPACX_CMDRD, 0x80);  // RMC
-			cs->rcvidx = 0;
+          debugl1(cs, "dch_int(): CRC error");
+	    cs->writeisac(cs, IPACX_CMDRD, 0x80);  // RMC
 		} else {  // received frame ok
-			count = ipacx_read_reg(cs, IPACX_RBCLD);
-			// FIXME this looks flaky
-			if (count) count--; // RSTAB is last byte
+			count = cs->readisac(cs, IPACX_RBCLD);
+      if (count) count--; // RSTAB is last byte
 			count &= D_FIFO_SIZE-1;
-			if (count == 0)
-				count = D_FIFO_SIZE;
+			if (count == 0) count = D_FIFO_SIZE;
 			dch_empty_fifo(cs, count);
-			recv_rme_d(cs);
-		}
+			if ((count = cs->rcvidx) > 0) {
+	      cs->rcvidx = 0;
+				if (!(skb = dev_alloc_skb(count)))
+					printk(KERN_WARNING "HiSax dch_int(): receive out of memory\n");
+				else {
+					memcpy(skb_put(skb, count), cs->rcvbuf, count);
+					skb_queue_tail(&cs->rq, skb);
+				}
+			}
+    }
+	  cs->rcvidx = 0;
+		schedule_event(cs, D_RCVBUFREADY);
 	}
 
 	if (istad &0x40) {  // RPF
@@ -380,34 +442,56 @@ dch_int(struct IsdnCardState *cs)
 
 	if (istad &0x20) {  // RFO
 		if (cs->debug &L1_DEB_WARN) debugl1(cs, "dch_int(): RFO");
-	  ipacx_write_reg(cs, IPACX_CMDRD, 0x40); //RRES
+	  cs->writeisac(cs, IPACX_CMDRD, 0x40); //RRES
 	}
   
-	if (istad &0x10) {  // XPR
-		xmit_xpr_d(cs);
-	}  
+  if (istad &0x10) {  // XPR
+		if (test_and_clear_bit(FLG_DBUSY_TIMER, &cs->HW_Flags))
+			del_timer(&cs->dbusytimer);
+		if (test_and_clear_bit(FLG_L1_DBUSY, &cs->HW_Flags))
+			schedule_event(cs, D_CLEARBUSY);
+    if (cs->tx_skb) {
+      if (cs->tx_skb->len) {
+        dch_fill_fifo(cs);
+        goto afterXPR;
+      }
+      else {
+        dev_kfree_skb_irq(cs->tx_skb);
+        cs->tx_skb = NULL;
+        cs->tx_cnt = 0;
+      }
+    }
+    if ((cs->tx_skb = skb_dequeue(&cs->sq))) {
+      cs->tx_cnt = 0;
+      dch_fill_fifo(cs);
+    } 
+    else {
+      schedule_event(cs, D_XMTBUFREADY);
+    }  
+  }  
+  afterXPR:
 
 	if (istad &0x0C) {  // XDU or XMR
-		xmit_xdu_d(cs, NULL);
-	}
+		if (cs->debug &L1_DEB_WARN) debugl1(cs, "dch_int(): XDU");
+	  if (cs->tx_skb) {
+	    skb_push(cs->tx_skb, cs->tx_cnt); // retransmit
+	    cs->tx_cnt = 0;
+			dch_fill_fifo(cs);
+		} else {
+			printk(KERN_WARNING "HiSax: ISAC XDU no skb\n");
+			debugl1(cs, "ISAC XDU no skb");
+		}
+  }
 }
 
 //----------------------------------------------------------
 //----------------------------------------------------------
-static int
+static void __devinit
 dch_setstack(struct PStack *st, struct IsdnCardState *cs)
 {
 	st->l1.l1hw = dch_l2l1;
-	return 0;
 }
 
-static struct dc_l1_ops ipacx_dc_l1_ops = {
-	.fill_fifo  = dch_fill_fifo,
-	.open       = dch_setstack,
-	.bh_func    = dch_bh,
-	.dbusy_func = dbusy_timer_handler,
-};
-
 //----------------------------------------------------------
 //----------------------------------------------------------
 static void __devinit
@@ -415,12 +499,16 @@ dch_init(struct IsdnCardState *cs)
 {
 	printk(KERN_INFO "HiSax: IPACX ISDN driver v0.1.0\n");
 
-	dc_l1_init(cs, &ipacx_dc_l1_ops);
+	cs->setstack_d      = dch_setstack;
+  
+	cs->dbusytimer.function = (void *) dbusy_timer_handler;
+	cs->dbusytimer.data = (long) cs;
+	init_timer(&cs->dbusytimer);
 
-	ipacx_write_reg(cs, IPACX_TR_CONF0, 0x00);  // clear LDD
-	ipacx_write_reg(cs, IPACX_TR_CONF2, 0x00);  // enable transmitter
-	ipacx_write_reg(cs, IPACX_MODED,    0xC9);  // transparent mode 0, RAC, stop/go
-	ipacx_write_reg(cs, IPACX_MON_CR,   0x00);  // disable monitor channel
+  cs->writeisac(cs, IPACX_TR_CONF0, 0x00);  // clear LDD
+  cs->writeisac(cs, IPACX_TR_CONF2, 0x00);  // enable transmitter
+  cs->writeisac(cs, IPACX_MODED,    0xC9);  // transparent mode 0, RAC, stop/go
+  cs->writeisac(cs, IPACX_MON_CR,   0x00);  // disable monitor channel
 }
 
 
@@ -434,31 +522,59 @@ dch_init(struct IsdnCardState *cs)
 static void
 bch_l2l1(struct PStack *st, int pr, void *arg)
 {
+	struct BCState *bcs = st->l1.bcs;
 	struct sk_buff *skb = arg;
+	u_long flags;
 
 	switch (pr) {
 		case (PH_DATA | REQUEST):
-			xmit_data_req_b(st->l1.bcs, skb);
+			spin_lock_irqsave(&bcs->cs->lock, flags);
+			if (bcs->tx_skb) {
+				skb_queue_tail(&bcs->squeue, skb);
+			} else {
+				bcs->tx_skb = skb;
+				set_bit(BC_FLG_BUSY, &bcs->Flag);
+				bcs->hw.hscx.count = 0;
+				bch_fill_fifo(bcs);
+			}
+			spin_unlock_irqrestore(&bcs->cs->lock, flags);
 			break;
 		case (PH_PULL | INDICATION):
-			xmit_pull_ind_b(st->l1.bcs, skb);
+			spin_lock_irqsave(&bcs->cs->lock, flags);
+			if (bcs->tx_skb) {
+				printk(KERN_WARNING "HiSax bch_l2l1(): this shouldn't happen\n");
+			} else {
+				set_bit(BC_FLG_BUSY, &bcs->Flag);
+				bcs->tx_skb = skb;
+				bcs->hw.hscx.count = 0;
+				bch_fill_fifo(bcs);
+			}
+			spin_unlock_irqrestore(&bcs->cs->lock, flags);
 			break;
 		case (PH_PULL | REQUEST):
-			xmit_pull_req_b(st);
+			if (!bcs->tx_skb) {
+				clear_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
+				st->l1.l1l2(st, PH_PULL | CONFIRM, NULL);
+			} else
+				set_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
 			break;
 		case (PH_ACTIVATE | REQUEST):
-			set_bit(BC_FLG_ACTIV, &st->l1.bcs->Flag);
-			bch_mode(st->l1.bcs, st->l1.mode, st->l1.bc);
+			spin_lock_irqsave(&bcs->cs->lock, flags);
+			set_bit(BC_FLG_ACTIV, &bcs->Flag);
+			bch_mode(bcs, st->l1.mode, st->l1.bc);
+			spin_unlock_irqrestore(&bcs->cs->lock, flags);
 			l1_msg_b(st, pr, arg);
 			break;
 		case (PH_DEACTIVATE | REQUEST):
 			l1_msg_b(st, pr, arg);
 			break;
 		case (PH_DEACTIVATE | CONFIRM):
-			clear_bit(BC_FLG_ACTIV, &st->l1.bcs->Flag);
-			clear_bit(BC_FLG_BUSY, &st->l1.bcs->Flag);
-			bch_mode(st->l1.bcs, 0, st->l1.bc);
-			st->l2.l1l2(st, PH_DEACTIVATE | CONFIRM, NULL);
+			spin_lock_irqsave(&bcs->cs->lock, flags);
+			clear_bit(BC_FLG_ACTIV, &bcs->Flag);
+			clear_bit(BC_FLG_BUSY, &bcs->Flag);
+			bch_mode(bcs, 0, st->l1.bc);
+			spin_unlock_irqrestore(&bcs->cs->lock, flags);
+			st->l1.l1l2(st, PH_DEACTIVATE | CONFIRM, NULL);
 			break;
 	}
 }
@@ -467,94 +583,204 @@ bch_l2l1(struct PStack *st, int pr, void
 // Read B channel fifo to receive buffer
 //----------------------------------------------------------
 static void
-ipacx_bc_empty_fifo(struct BCState *bcs, int count)
+bch_empty_fifo(struct BCState *bcs, int count)
 {
-	recv_empty_fifo_b(bcs, count);
-	ipacx_bc_write_reg(bcs, IPACX_CMDRB, 0x80);  // RMC
+	u_char *ptr, hscx;
+	struct IsdnCardState *cs;
+	int cnt;
+
+	cs = bcs->cs;
+  hscx = bcs->hw.hscx.hscx;
+	if ((cs->debug &L1_DEB_HSCX) && !(cs->debug &L1_DEB_HSCX_FIFO))
+		debugl1(cs, "bch_empty_fifo()");
+
+  // message too large, remove
+	if (bcs->hw.hscx.rcvidx + count > HSCX_BUFMAX) {
+		if (cs->debug &L1_DEB_WARN)
+			debugl1(cs, "bch_empty_fifo() incoming packet too large");
+	  cs->BC_Write_Reg(cs, hscx, IPACX_CMDRB, 0x80);  // RMC
+		bcs->hw.hscx.rcvidx = 0;
+		return;
+	}
+  
+	ptr = bcs->hw.hscx.rcvbuf + bcs->hw.hscx.rcvidx;
+	cnt = count;
+	while (cnt--) *ptr++ = cs->BC_Read_Reg(cs, hscx, IPACX_RFIFOB); 
+	cs->BC_Write_Reg(cs, hscx, IPACX_CMDRB, 0x80);  // RMC
+  
+	ptr = bcs->hw.hscx.rcvbuf + bcs->hw.hscx.rcvidx;
+	bcs->hw.hscx.rcvidx += count;
+  
+	if (cs->debug &L1_DEB_HSCX_FIFO) {
+		char *t = bcs->blog;
+
+		t += sprintf(t, "bch_empty_fifo() B-%d cnt %d", hscx, count);
+		QuickHex(t, ptr, count);
+		debugl1(cs, bcs->blog);
+	}
 }
 
 //----------------------------------------------------------
 // Fill buffer to transmit FIFO
 //----------------------------------------------------------
 static void
-ipacx_bc_fill_fifo(struct BCState *bcs)
+bch_fill_fifo(struct BCState *bcs)
 {
-	int more, count;
-	unsigned char *p;
-
-	p = xmit_fill_fifo_b(bcs, B_FIFO_SIZE, &count, &more);
-	if (!p)
-		return;
-
-	while (count--)
-		ipacx_bc_write_reg(bcs, IPACX_XFIFOB, *p++); 
-
-	ipacx_bc_write_reg(bcs, IPACX_CMDRB, (more ? 0x08 : 0x0a));
+	struct IsdnCardState *cs;
+	int more, count, cnt;
+	u_char *ptr, *p, hscx;
+
+	cs = bcs->cs;
+	if ((cs->debug &L1_DEB_HSCX) && !(cs->debug &L1_DEB_HSCX_FIFO))
+		debugl1(cs, "bch_fill_fifo()");
+
+	if (!bcs->tx_skb)           return;
+	if (bcs->tx_skb->len <= 0)  return;
+
+	hscx = bcs->hw.hscx.hscx;
+	more = (bcs->mode == L1_MODE_TRANS) ? 1 : 0;
+	if (bcs->tx_skb->len > B_FIFO_SIZE) {
+		more  = 1;
+		count = B_FIFO_SIZE;
+	} else {
+		count = bcs->tx_skb->len;
+	}  
+	cnt = count;
+    
+	p = ptr = bcs->tx_skb->data;
+	skb_pull(bcs->tx_skb, count);
+	bcs->tx_cnt -= count;
+	bcs->hw.hscx.count += count;
+	while (cnt--) cs->BC_Write_Reg(cs, hscx, IPACX_XFIFOB, *p++); 
+	cs->BC_Write_Reg(cs, hscx, IPACX_CMDRB, (more ? 0x08 : 0x0a));
+  
+	if (cs->debug &L1_DEB_HSCX_FIFO) {
+		char *t = bcs->blog;
+
+		t += sprintf(t, "chb_fill_fifo() B-%d cnt %d", hscx, count);
+		QuickHex(t, ptr, count);
+		debugl1(cs, bcs->blog);
+	}
 }
 
 //----------------------------------------------------------
 // B channel interrupt handler
 //----------------------------------------------------------
-
-static void
-reset_xmit(struct BCState *bcs)
-{
-	ipacx_bc_write_reg(bcs, IPACX_CMDRB, 0x01);  // XRES
-}
-
 static void
-bch_int(struct IsdnCardState *cs, u8 hscx)
+bch_int(struct IsdnCardState *cs, u_char hscx)
 {
-	u8 istab;
+	u_char istab;
 	struct BCState *bcs;
+	struct sk_buff *skb;
 	int count;
-	u8 rstab;
+	u_char rstab;
 
 	bcs = cs->bcs + hscx;
-	istab = ipacx_bc_read_reg(bcs, IPACX_ISTAB);
+	istab = cs->BC_Read_Reg(cs, hscx, IPACX_ISTAB);
+//##############################################  
+//	printk(KERN_WARNING "bch_int(istab=%02x)\n", istab);
+//##############################################  
 	if (!test_bit(BC_FLG_INIT, &bcs->Flag)) return;
 
 	if (istab &0x80) {	// RME
-		rstab = ipacx_bc_read_reg(bcs, IPACX_RSTAB);
+		rstab = cs->BC_Read_Reg(cs, hscx, IPACX_RSTAB);
 		if ((rstab &0xf0) != 0xa0) { // !(VFR && !RDO && CRC && !RAB)
 			if (!(rstab &0x80))
 				if (cs->debug &L1_DEB_WARN) 
-					debugl1(cs, "bch_int() B-%d: invalid frame", hscx);
+          debugl1(cs, "bch_int() B-%d: invalid frame", hscx);
 			if ((rstab &0x40) && (bcs->mode != L1_MODE_NULL))
 				if (cs->debug &L1_DEB_WARN) 
-					debugl1(cs, "bch_int() B-%d: RDO mode=%d", hscx, bcs->mode);
+          debugl1(cs, "bch_int() B-%d: RDO mode=%d", hscx, bcs->mode);
 			if (!(rstab &0x20))
 				if (cs->debug &L1_DEB_WARN) 
-					debugl1(cs, "bch_int() B-%d: CRC error", hscx);
-			ipacx_bc_write_reg(bcs, IPACX_CMDRB, 0x80);  // RMC
-			bcs->rcvidx = 0;
-		}  else {  // received frame ok
-			count = ipacx_bc_read_reg(bcs, IPACX_RBCLB) &(B_FIFO_SIZE-1);
-			if (count == 0)
-				count = B_FIFO_SIZE;
-
-			ipacx_bc_empty_fifo(bcs, count);
-			recv_rme_b(bcs);
+          debugl1(cs, "bch_int() B-%d: CRC error", hscx);
+	    cs->BC_Write_Reg(cs, hscx, IPACX_CMDRB, 0x80);  // RMC
+		} 
+    else {  // received frame ok
+			count = cs->BC_Read_Reg(cs, hscx, IPACX_RBCLB) &(B_FIFO_SIZE-1);
+			if (count == 0) count = B_FIFO_SIZE;
+			bch_empty_fifo(bcs, count);
+			if ((count = bcs->hw.hscx.rcvidx - 1) > 0) {
+				if (cs->debug &L1_DEB_HSCX_FIFO)
+					debugl1(cs, "bch_int Frame %d", count);
+				if (!(skb = dev_alloc_skb(count)))
+					printk(KERN_WARNING "HiSax bch_int(): receive frame out of memory\n");
+				else {
+					memcpy(skb_put(skb, count), bcs->hw.hscx.rcvbuf, count);
+					skb_queue_tail(&bcs->rqueue, skb);
+				}
+			}
 		}
+		bcs->hw.hscx.rcvidx = 0;
+		schedule_event(bcs, B_RCVBUFREADY);
 	}
   
 	if (istab &0x40) {	// RPF
-		ipacx_bc_empty_fifo(bcs, B_FIFO_SIZE);
-		recv_rpf_b(bcs);
+		bch_empty_fifo(bcs, B_FIFO_SIZE);
+
+		if (bcs->mode == L1_MODE_TRANS) { // queue every chunk
+			// receive transparent audio data
+			if (!(skb = dev_alloc_skb(B_FIFO_SIZE)))
+				printk(KERN_WARNING "HiSax bch_int(): receive transparent out of memory\n");
+			else {
+				memcpy(skb_put(skb, B_FIFO_SIZE), bcs->hw.hscx.rcvbuf, B_FIFO_SIZE);
+				skb_queue_tail(&bcs->rqueue, skb);
+			}
+			bcs->hw.hscx.rcvidx = 0;
+			schedule_event(bcs, B_RCVBUFREADY);
+		}
 	}
   
 	if (istab &0x20) {	// RFO
 		if (cs->debug &L1_DEB_WARN) 
 			debugl1(cs, "bch_int() B-%d: RFO error", hscx);
-		ipacx_bc_write_reg(bcs, IPACX_CMDRB, 0x40);  // RRES
+		cs->BC_Write_Reg(cs, hscx, IPACX_CMDRB, 0x40);  // RRES
 	}
 
 	if (istab &0x10) {	// XPR
-		xmit_xpr_b(bcs);
+		if (bcs->tx_skb) {
+			if (bcs->tx_skb->len) {
+				bch_fill_fifo(bcs);
+				goto afterXPR;
+			} else {
+				if (test_bit(FLG_LLI_L1WAKEUP,&bcs->st->lli.flag) &&
+					(PACKET_NOACK != bcs->tx_skb->pkt_type)) {
+					u_long	flags;
+					spin_lock_irqsave(&bcs->aclock, flags);
+					bcs->ackcnt += bcs->hw.hscx.count;
+					spin_unlock_irqrestore(&bcs->aclock, flags);
+					schedule_event(bcs, B_ACKPENDING);
+				}
+			}
+			dev_kfree_skb_irq(bcs->tx_skb);
+			bcs->hw.hscx.count = 0;
+			bcs->tx_skb = NULL;
+    		}
+		if ((bcs->tx_skb = skb_dequeue(&bcs->squeue))) {
+			bcs->hw.hscx.count = 0;
+			set_bit(BC_FLG_BUSY, &bcs->Flag);
+			bch_fill_fifo(bcs);
+		} else {
+			clear_bit(BC_FLG_BUSY, &bcs->Flag);
+			schedule_event(bcs, B_XMTBUFREADY);
+		}
 	}
+  afterXPR:
 
 	if (istab &0x04) {	// XDU
-		xmit_xdu_b(bcs, reset_xmit);
+    if (bcs->mode == L1_MODE_TRANS) {
+			bch_fill_fifo(bcs);
+    }  
+    else {
+      if (bcs->tx_skb) {  // restart transmitting the whole frame
+        skb_push(bcs->tx_skb, bcs->hw.hscx.count);
+        bcs->tx_cnt += bcs->hw.hscx.count;
+        bcs->hw.hscx.count = 0;
+      }
+	    cs->BC_Write_Reg(cs, hscx, IPACX_CMDRB, 0x01);  // XRES
+      if (cs->debug &L1_DEB_WARN)
+        debugl1(cs, "bch_int() B-%d XDU error", hscx);
+    }
 	}
 }
 
@@ -564,7 +790,7 @@ static void
 bch_mode(struct BCState *bcs, int mode, int bc)
 {
 	struct IsdnCardState *cs = bcs->cs;
-	int hscx = bcs->unit;
+	int hscx = bcs->hw.hscx.hscx;
 
         bc = bc ? 1 : 0;  // in case bc is greater than 1
 	if (cs->debug & L1_DEB_HSCX)
@@ -575,33 +801,33 @@ bch_mode(struct BCState *bcs, int mode, 
   // map controller to according timeslot
   if (!hscx)
   {
-    ipacx_write_reg(cs, IPACX_BCHA_TSDP_BC1, 0x80 | bc);
-    ipacx_write_reg(cs, IPACX_BCHA_CR,       0x88); 
+    cs->writeisac(cs, IPACX_BCHA_TSDP_BC1, 0x80 | bc);
+    cs->writeisac(cs, IPACX_BCHA_CR,       0x88); 
   }
   else
   {
-    ipacx_write_reg(cs, IPACX_BCHB_TSDP_BC1, 0x80 | bc);
-    ipacx_write_reg(cs, IPACX_BCHB_CR,       0x88); 
+    cs->writeisac(cs, IPACX_BCHB_TSDP_BC1, 0x80 | bc);
+    cs->writeisac(cs, IPACX_BCHB_CR,       0x88); 
   }
 
 	switch (mode) {
 		case (L1_MODE_NULL):
-		    ipacx_bc_write_reg(bcs, IPACX_MODEB, 0xC0);  // rec off
-		    ipacx_bc_write_reg(bcs, IPACX_EXMB,  0x30);  // std adj.
-		    ipacx_bc_write_reg(bcs, IPACX_MASKB, 0xFF);  // ints off
-		    ipacx_bc_write_reg(bcs, IPACX_CMDRB, 0x41);  // validate adjustments
+		    cs->BC_Write_Reg(cs, hscx, IPACX_MODEB, 0xC0);  // rec off
+		    cs->BC_Write_Reg(cs, hscx, IPACX_EXMB,  0x30);  // std adj.
+		    cs->BC_Write_Reg(cs, hscx, IPACX_MASKB, 0xFF);  // ints off
+		    cs->BC_Write_Reg(cs, hscx, IPACX_CMDRB, 0x41);  // validate adjustments
 		    break;
 		case (L1_MODE_TRANS):
-		    ipacx_bc_write_reg(bcs, IPACX_MODEB, 0x88);  // ext transp mode
-		    ipacx_bc_write_reg(bcs, IPACX_EXMB,  0x00);  // xxx00000
-		    ipacx_bc_write_reg(bcs, IPACX_CMDRB, 0x41);  // validate adjustments
-		    ipacx_bc_write_reg(bcs, IPACX_MASKB, _MASKB_IMASK);
+		    cs->BC_Write_Reg(cs, hscx, IPACX_MODEB, 0x88);  // ext transp mode
+		    cs->BC_Write_Reg(cs, hscx, IPACX_EXMB,  0x00);  // xxx00000
+		    cs->BC_Write_Reg(cs, hscx, IPACX_CMDRB, 0x41);  // validate adjustments
+		    cs->BC_Write_Reg(cs, hscx, IPACX_MASKB, _MASKB_IMASK);
 		    break;
 		case (L1_MODE_HDLC):
-		    ipacx_bc_write_reg(bcs, IPACX_MODEB, 0xC8);  // transp mode 0
-		    ipacx_bc_write_reg(bcs, IPACX_EXMB,  0x01);  // idle=hdlc flags crc enabled
-		    ipacx_bc_write_reg(bcs, IPACX_CMDRB, 0x41);  // validate adjustments
-		    ipacx_bc_write_reg(bcs, IPACX_MASKB, _MASKB_IMASK);
+		    cs->BC_Write_Reg(cs, hscx, IPACX_MODEB, 0xC8);  // transp mode 0
+		    cs->BC_Write_Reg(cs, hscx, IPACX_EXMB,  0x01);  // idle=hdlc flags crc enabled
+		    cs->BC_Write_Reg(cs, hscx, IPACX_CMDRB, 0x41);  // validate adjustments
+		    cs->BC_Write_Reg(cs, hscx, IPACX_MASKB, _MASKB_IMASK);
 		    break;
 	}
 }
@@ -612,7 +838,23 @@ static void
 bch_close_state(struct BCState *bcs)
 {
 	bch_mode(bcs, 0, bcs->channel);
-	bc_close(bcs);
+	if (test_and_clear_bit(BC_FLG_INIT, &bcs->Flag)) {
+		if (bcs->hw.hscx.rcvbuf) {
+			kfree(bcs->hw.hscx.rcvbuf);
+			bcs->hw.hscx.rcvbuf = NULL;
+		}
+		if (bcs->blog) {
+			kfree(bcs->blog);
+			bcs->blog = NULL;
+		}
+		skb_queue_purge(&bcs->rqueue);
+		skb_queue_purge(&bcs->squeue);
+		if (bcs->tx_skb) {
+			dev_kfree_skb_any(bcs->tx_skb);
+			bcs->tx_skb = NULL;
+			clear_bit(BC_FLG_BUSY, &bcs->Flag);
+		}
+	}
 }
 
 //----------------------------------------------------------
@@ -620,7 +862,30 @@ bch_close_state(struct BCState *bcs)
 static int
 bch_open_state(struct IsdnCardState *cs, struct BCState *bcs)
 {
-	return bc_open(bcs);
+	if (!test_and_set_bit(BC_FLG_INIT, &bcs->Flag)) {
+		if (!(bcs->hw.hscx.rcvbuf = kmalloc(HSCX_BUFMAX, GFP_ATOMIC))) {
+			printk(KERN_WARNING
+				"HiSax open_bchstate(): No memory for hscx.rcvbuf\n");
+			clear_bit(BC_FLG_INIT, &bcs->Flag);
+			return (1);
+		}
+		if (!(bcs->blog = kmalloc(MAX_BLOG_SPACE, GFP_ATOMIC))) {
+			printk(KERN_WARNING
+				"HiSax open_bchstate: No memory for bcs->blog\n");
+			clear_bit(BC_FLG_INIT, &bcs->Flag);
+			kfree(bcs->hw.hscx.rcvbuf);
+			bcs->hw.hscx.rcvbuf = NULL;
+			return (2);
+		}
+		skb_queue_head_init(&bcs->rqueue);
+		skb_queue_head_init(&bcs->squeue);
+	}
+	bcs->tx_skb = NULL;
+	clear_bit(BC_FLG_BUSY, &bcs->Flag);
+	bcs->event = 0;
+	bcs->hw.hscx.rcvidx = 0;
+	bcs->tx_cnt = 0;
+	return (0);
 }
 
 //----------------------------------------------------------
@@ -631,7 +896,7 @@ bch_setstack(struct PStack *st, struct B
 	bcs->channel = st->l1.bc;
 	if (bch_open_state(st->l1.hardware, bcs)) return (-1);
 	st->l1.bcs = bcs;
-	st->l1.l2l1 = bch_l2l1;
+	st->l2.l2l1 = bch_l2l1;
 	setstack_manager(st);
 	bcs->st = st;
 	setstack_l1_B(st);
@@ -643,7 +908,9 @@ bch_setstack(struct PStack *st, struct B
 static void __devinit
 bch_init(struct IsdnCardState *cs, int hscx)
 {
-	cs->bcs[hscx].unit          = hscx;
+	cs->bcs[hscx].BC_SetStack   = bch_setstack;
+	cs->bcs[hscx].BC_Close      = bch_close_state;
+	cs->bcs[hscx].hw.hscx.hscx  = hscx;
 	cs->bcs[hscx].cs            = cs;
 	bch_mode(cs->bcs + hscx, 0, hscx);
 }
@@ -659,16 +926,18 @@ bch_init(struct IsdnCardState *cs, int h
 void 
 interrupt_ipacx(struct IsdnCardState *cs)
 {
-	u8 ista;
-	
-	spin_lock(&cs->lock);
-	while ((ista = ipacx_read_reg(cs, IPACX_ISTA))) {
-		if (ista &0x80) bch_int(cs, 0); // B channel interrupts
-		if (ista &0x40) bch_int(cs, 1);
-		if (ista &0x01) dch_int(cs);    // D channel
-		if (ista &0x10) cic_int(cs);    // Layer 1 state
-	}  
-	spin_unlock(&cs->lock);
+	u_char ista;
+  
+	while ((ista = cs->readisac(cs, IPACX_ISTA))) {
+//#################################################  
+//		printk(KERN_WARNING "interrupt_ipacx(ista=%02x)\n", ista);
+//#################################################  
+    if (ista &0x80) bch_int(cs, 0); // B channel interrupts
+    if (ista &0x40) bch_int(cs, 1);
+    
+    if (ista &0x01) dch_int(cs);    // D channel
+    if (ista &0x10) cic_int(cs);    // Layer 1 state
+  }  
 }
 
 //----------------------------------------------------------
@@ -680,23 +949,17 @@ clear_pending_ints(struct IsdnCardState 
 	int ista;
 
   // all interrupts off
-  ipacx_write_reg(cs, IPACX_MASK, 0xff);
-  ipacx_write_reg(cs, IPACX_MASKD, 0xff);
-  cs->bc_hw_ops->write_reg(cs, 0, IPACX_MASKB, 0xff);
-  cs->bc_hw_ops->write_reg(cs, 1, IPACX_MASKB, 0xff);
-  
-  ista = ipacx_read_reg(cs, IPACX_ISTA); 
-  if (ista &0x80) cs->bc_hw_ops->read_reg(cs, 0, IPACX_ISTAB);
-  if (ista &0x40) cs->bc_hw_ops->read_reg(cs, 1, IPACX_ISTAB);
-  if (ista &0x10) ipacx_read_reg(cs, IPACX_CIR0);
-  if (ista &0x01) ipacx_read_reg(cs, IPACX_ISTAD); 
-}
-
-static struct bc_l1_ops ipacx_bc_l1_ops = {
-	.fill_fifo = ipacx_bc_fill_fifo,
-	.open      = bch_setstack,
-	.close     = bch_close_state,
-};
+  cs->writeisac(cs, IPACX_MASK, 0xff);
+	cs->writeisac(cs, IPACX_MASKD, 0xff);
+	cs->BC_Write_Reg(cs, 0, IPACX_MASKB, 0xff);
+	cs->BC_Write_Reg(cs, 1, IPACX_MASKB, 0xff);
+  
+  ista = cs->readisac(cs, IPACX_ISTA); 
+  if (ista &0x80) cs->BC_Read_Reg(cs, 0, IPACX_ISTAB);
+  if (ista &0x40) cs->BC_Read_Reg(cs, 1, IPACX_ISTAB);
+  if (ista &0x10) cs->readisac(cs, IPACX_CIR0);
+  if (ista &0x01) cs->readisac(cs, IPACX_ISTAD); 
+}
 
 //----------------------------------------------------------
 // Does chip configuration work
@@ -706,36 +969,36 @@ void __init
 init_ipacx(struct IsdnCardState *cs, int part)
 {
 	if (part &1) {  // initialise chip
-		cs->bc_l1_ops = &ipacx_bc_l1_ops;
+//##################################################  
+//	printk(KERN_INFO "init_ipacx(%x)\n", part);
+//##################################################  
 		clear_pending_ints(cs);
 		bch_init(cs, 0);
 		bch_init(cs, 1);
 		dch_init(cs);
 	}
 	if (part &2) {  // reenable all interrupts and start chip
-		cs->bc_hw_ops->write_reg(cs, 0, IPACX_MASKB, _MASKB_IMASK);
-		cs->bc_hw_ops->write_reg(cs, 1, IPACX_MASKB, _MASKB_IMASK);
-		ipacx_write_reg(cs, IPACX_MASKD, _MASKD_IMASK);
-		ipacx_write_reg(cs, IPACX_MASK, _MASK_IMASK); // global mask register
-
-    // reset HDLC Transmitters/receivers
-		ipacx_write_reg(cs, IPACX_CMDRD, 0x41); 
-		cs->bc_hw_ops->write_reg(cs, 0, IPACX_CMDRB, 0x41);
-		cs->bc_hw_ops->write_reg(cs, 1, IPACX_CMDRB, 0x41);
+		cs->BC_Write_Reg(cs, 0, IPACX_MASKB, _MASKB_IMASK);
+		cs->BC_Write_Reg(cs, 1, IPACX_MASKB, _MASKB_IMASK);
+		cs->writeisac(cs, IPACX_MASKD, _MASKD_IMASK);
+		cs->writeisac(cs, IPACX_MASK, _MASK_IMASK); // global mask register
+
+		// reset HDLC Transmitters/receivers
+		cs->writeisac(cs, IPACX_CMDRD, 0x41); 
+		cs->BC_Write_Reg(cs, 0, IPACX_CMDRB, 0x41);
+		cs->BC_Write_Reg(cs, 1, IPACX_CMDRB, 0x41);
 		ph_command(cs, IPACX_CMD_RES);
 	}
 }
 
-int
-ipacx_setup(struct IsdnCardState *cs, struct dc_hw_ops *ipacx_dc_ops,
-	    struct bc_hw_ops *ipacx_bc_ops)
-{
-	u8 val;
-
-	cs->dc_hw_ops = ipacx_dc_ops;
-	cs->bc_hw_ops = ipacx_bc_ops;
-	val = ipacx_read_reg(cs, IPACX_ID) & 0x3f;
-	printk(KERN_INFO "HiSax: IPACX Design Id: %#x\n", val);
-	return 0;
+
+void __devinit
+setup_ipacx(struct IsdnCardState *cs)
+{
+	INIT_WORK(&cs->tqueue, (void *)(void *) dch_bh, cs);
+	cs->dbusytimer.function = (void *) dbusy_timer_handler;
+	cs->dbusytimer.data = (long) cs;
+	init_timer(&cs->dbusytimer);
 }
+//----------------- end of file -----------------------
 
--- diff/drivers/isdn/hisax/ipacx.h	2003-01-16 11:30:36.000000000 +0000
+++ source/drivers/isdn/hisax/ipacx.h	2004-02-23 13:56:42.000000000 +0000
@@ -155,10 +155,8 @@
 #define IPACX_IND_AIL    0xe
 #define IPACX_IND_DC     0xf
 
-extern void init_ipacx(struct IsdnCardState *cs, int part);
-extern void interrupt_ipacx(struct IsdnCardState *cs);
-extern int  ipacx_setup(struct IsdnCardState *cs,
-			struct dc_hw_ops *ipacx_dc_ops,
-			struct bc_hw_ops *ipacx_bc_ops);
+extern void init_ipacx(struct IsdnCardState *, int);
+extern void interrupt_ipacx(struct IsdnCardState *);
+extern void setup_isac(struct IsdnCardState *);
 
 #endif
--- diff/drivers/isdn/hisax/isac.c	2003-01-16 11:30:36.000000000 +0000
+++ source/drivers/isdn/hisax/isac.c	2004-02-23 13:56:42.000000000 +0000
@@ -1,4 +1,4 @@
-/* $Id: isac.c,v 1.28.6.3 2001/09/23 22:24:49 kai Exp $
+/* $Id: isac.c,v 1.31.2.3 2004/01/13 14:31:25 keil Exp $
  *
  * ISAC specific routines
  *
@@ -27,30 +27,12 @@ static char *ISACVer[] __devinitdata =
 {"2086/2186 V1.1", "2085 B1", "2085 B2",
  "2085 V2.3"};
 
-static inline u8
-isac_read(struct IsdnCardState *cs, u8 addr)
-{
-	return cs->dc_hw_ops->read_reg(cs, addr);
-}
-
-static inline void
-isac_write(struct IsdnCardState *cs, u8 addr, u8 val)
-{
-	cs->dc_hw_ops->write_reg(cs, addr, val);
-}
-
-static inline void
-isac_write_fifo(struct IsdnCardState *cs, u8 *p, int len)
-{
-	return cs->dc_hw_ops->write_fifo(cs, p, len);
-}
-
-static void
+void
 ISACVersion(struct IsdnCardState *cs, char *s)
 {
 	int val;
 
-	val = isac_read(cs, ISAC_RBCH);
+	val = cs->readisac(cs, ISAC_RBCH);
 	printk(KERN_INFO "%s ISAC version (%x): %s\n", s, val, ISACVer[(val >> 5) & 3]);
 }
 
@@ -59,7 +41,7 @@ ph_command(struct IsdnCardState *cs, uns
 {
 	if (cs->debug & L1_DEB_ISAC)
 		debugl1(cs, "ph_command %x", command);
-	isac_write(cs, ISAC_CIX0, (command << 2) | 3);
+	cs->writeisac(cs, ISAC_CIX0, (command << 2) | 3);
 }
 
 
@@ -99,9 +81,8 @@ isac_new_ph(struct IsdnCardState *cs)
 }
 
 static void
-isac_bh(void *data)
+isac_bh(struct IsdnCardState *cs)
 {
-	struct IsdnCardState *cs = data;
 	struct PStack *stptr;
 	
 	if (!cs)
@@ -111,7 +92,7 @@ isac_bh(void *data)
 			debugl1(cs, "D-Channel Busy cleared");
 		stptr = cs->stlist;
 		while (stptr != NULL) {
-			L1L2(stptr, PH_PAUSE | CONFIRM, NULL);
+			stptr->l1.l1l2(stptr, PH_PAUSE | CONFIRM, NULL);
 			stptr = stptr->next;
 		}
 	}
@@ -134,22 +115,58 @@ isac_bh(void *data)
 void
 isac_empty_fifo(struct IsdnCardState *cs, int count)
 {
-	recv_empty_fifo_d(cs, count);
-	isac_write(cs, ISAC_CMDR, 0x80);
+	u_char *ptr;
+
+	if ((cs->debug & L1_DEB_ISAC) && !(cs->debug & L1_DEB_ISAC_FIFO))
+		debugl1(cs, "isac_empty_fifo");
+
+	if ((cs->rcvidx + count) >= MAX_DFRAME_LEN_L1) {
+		if (cs->debug & L1_DEB_WARN)
+			debugl1(cs, "isac_empty_fifo overrun %d",
+				cs->rcvidx + count);
+		cs->writeisac(cs, ISAC_CMDR, 0x80);
+		cs->rcvidx = 0;
+		return;
+	}
+	ptr = cs->rcvbuf + cs->rcvidx;
+	cs->rcvidx += count;
+	cs->readisacfifo(cs, ptr, count);
+	cs->writeisac(cs, ISAC_CMDR, 0x80);
+	if (cs->debug & L1_DEB_ISAC_FIFO) {
+		char *t = cs->dlog;
+
+		t += sprintf(t, "isac_empty_fifo cnt %d", count);
+		QuickHex(t, ptr, count);
+		debugl1(cs, cs->dlog);
+	}
 }
 
 static void
 isac_fill_fifo(struct IsdnCardState *cs)
 {
 	int count, more;
-	unsigned char *p;
+	u_char *ptr;
+
+	if ((cs->debug & L1_DEB_ISAC) && !(cs->debug & L1_DEB_ISAC_FIFO))
+		debugl1(cs, "isac_fill_fifo");
+
+	if (!cs->tx_skb)
+		return;
 
-	p = xmit_fill_fifo_d(cs, 32, &count, &more);
-	if (!p)
+	count = cs->tx_skb->len;
+	if (count <= 0)
 		return;
 
-	isac_write_fifo(cs, p, count);
-	isac_write(cs, ISAC_CMDR, more ? 0x8 : 0xa);
+	more = 0;
+	if (count > 32) {
+		more = !0;
+		count = 32;
+	}
+	ptr = cs->tx_skb->data;
+	skb_pull(cs->tx_skb, count);
+	cs->tx_cnt += count;
+	cs->writeisacfifo(cs, ptr, count);
+	cs->writeisac(cs, ISAC_CMDR, more ? 0x8 : 0xa);
 	if (test_and_set_bit(FLG_DBUSY_TIMER, &cs->HW_Flags)) {
 		debugl1(cs, "isac_fill_fifo dbusytimer running");
 		del_timer(&cs->dbusytimer);
@@ -157,18 +174,26 @@ isac_fill_fifo(struct IsdnCardState *cs)
 	init_timer(&cs->dbusytimer);
 	cs->dbusytimer.expires = jiffies + ((DBUSY_TIMER_VALUE * HZ)/1000);
 	add_timer(&cs->dbusytimer);
+	if (cs->debug & L1_DEB_ISAC_FIFO) {
+		char *t = cs->dlog;
+
+		t += sprintf(t, "isac_fill_fifo cnt %d", count);
+		QuickHex(t, ptr, count);
+		debugl1(cs, cs->dlog);
+	}
 }
 
 void
-isac_interrupt(struct IsdnCardState *cs, u8 val)
+isac_interrupt(struct IsdnCardState *cs, u_char val)
 {
-	u8 exval, v1;
+	u_char exval, v1;
+	struct sk_buff *skb;
 	unsigned int count;
 
 	if (cs->debug & L1_DEB_ISAC)
 		debugl1(cs, "ISAC interrupt %x", val);
 	if (val & 0x80) {	/* RME */
-		exval = isac_read(cs, ISAC_RSTA);
+		exval = cs->readisac(cs, ISAC_RSTA);
 		if ((exval & 0x70) != 0x20) {
 			if (exval & 0x40) {
 				if (cs->debug & L1_DEB_WARN)
@@ -184,17 +209,24 @@ isac_interrupt(struct IsdnCardState *cs,
 				cs->err_crc++;
 #endif
 			}
-			isac_write(cs, ISAC_CMDR, 0x80);
-			cs->rcvidx = 0;
+			cs->writeisac(cs, ISAC_CMDR, 0x80);
 		} else {
-			count = isac_read(cs, ISAC_RBCL) & 0x1f;
+			count = cs->readisac(cs, ISAC_RBCL) & 0x1f;
 			if (count == 0)
 				count = 32;
 			isac_empty_fifo(cs, count);
- 			recv_rme_d(cs);
+			if ((count = cs->rcvidx) > 0) {
+				cs->rcvidx = 0;
+				if (!(skb = alloc_skb(count, GFP_ATOMIC)))
+					printk(KERN_WARNING "HiSax: D receive out of memory\n");
+				else {
+					memcpy(skb_put(skb, count), cs->rcvbuf, count);
+					skb_queue_tail(&cs->rq, skb);
+				}
+			}
 		}
 		cs->rcvidx = 0;
-		sched_d_event(cs, D_RCVBUFREADY);
+		schedule_event(cs, D_RCVBUFREADY);
 	}
 	if (val & 0x40) {	/* RPF */
 		isac_empty_fifo(cs, 32);
@@ -205,20 +237,39 @@ isac_interrupt(struct IsdnCardState *cs,
 			debugl1(cs, "ISAC RSC interrupt");
 	}
 	if (val & 0x10) {	/* XPR */
-		xmit_xpr_d(cs);
+		if (test_and_clear_bit(FLG_DBUSY_TIMER, &cs->HW_Flags))
+			del_timer(&cs->dbusytimer);
+		if (test_and_clear_bit(FLG_L1_DBUSY, &cs->HW_Flags))
+			schedule_event(cs, D_CLEARBUSY);
+		if (cs->tx_skb) {
+			if (cs->tx_skb->len) {
+				isac_fill_fifo(cs);
+				goto afterXPR;
+			} else {
+				dev_kfree_skb_irq(cs->tx_skb);
+				cs->tx_cnt = 0;
+				cs->tx_skb = NULL;
+			}
+		}
+		if ((cs->tx_skb = skb_dequeue(&cs->sq))) {
+			cs->tx_cnt = 0;
+			isac_fill_fifo(cs);
+		} else
+			schedule_event(cs, D_XMTBUFREADY);
 	}
+      afterXPR:
 	if (val & 0x04) {	/* CISQ */
-		exval = isac_read(cs, ISAC_CIR0);
+		exval = cs->readisac(cs, ISAC_CIR0);
 		if (cs->debug & L1_DEB_ISAC)
 			debugl1(cs, "ISAC CIR0 %02X", exval );
 		if (exval & 2) {
 			cs->dc.isac.ph_state = (exval >> 2) & 0xf;
 			if (cs->debug & L1_DEB_ISAC)
 				debugl1(cs, "ph_state change %x", cs->dc.isac.ph_state);
-			sched_d_event(cs, D_L1STATECHANGE);
+			schedule_event(cs, D_L1STATECHANGE);
 		}
 		if (exval & 1) {
-			exval = isac_read(cs, ISAC_CIR1);
+			exval = cs->readisac(cs, ISAC_CIR1);
 			if (cs->debug & L1_DEB_ISAC)
 				debugl1(cs, "ISAC CIR1 %02X", exval );
 		}
@@ -229,7 +280,7 @@ isac_interrupt(struct IsdnCardState *cs,
 			debugl1(cs, "ISAC SIN interrupt");
 	}
 	if (val & 0x01) {	/* EXI */
-		exval = isac_read(cs, ISAC_EXIR);
+		exval = cs->readisac(cs, ISAC_EXIR);
 		if (cs->debug & L1_DEB_WARN)
 			debugl1(cs, "ISAC EXIR %02x", exval);
 		if (exval & 0x80) {  /* XMR */
@@ -237,10 +288,26 @@ isac_interrupt(struct IsdnCardState *cs,
 			printk(KERN_WARNING "HiSax: ISAC XMR\n");
 		}
 		if (exval & 0x40) {  /* XDU */
-			xmit_xdu_d(cs, NULL);
+			debugl1(cs, "ISAC XDU");
+			printk(KERN_WARNING "HiSax: ISAC XDU\n");
+#ifdef ERROR_STATISTIC
+			cs->err_tx++;
+#endif
+			if (test_and_clear_bit(FLG_DBUSY_TIMER, &cs->HW_Flags))
+				del_timer(&cs->dbusytimer);
+			if (test_and_clear_bit(FLG_L1_DBUSY, &cs->HW_Flags))
+				schedule_event(cs, D_CLEARBUSY);
+			if (cs->tx_skb) { /* Restart frame */
+				skb_push(cs->tx_skb, cs->tx_cnt);
+				cs->tx_cnt = 0;
+				isac_fill_fifo(cs);
+			} else {
+				printk(KERN_WARNING "HiSax: ISAC XDU no skb\n");
+				debugl1(cs, "ISAC XDU no skb");
+			}
 		}
 		if (exval & 0x04) {  /* MOS */
-			v1 = isac_read(cs, ISAC_MOSR);
+			v1 = cs->readisac(cs, ISAC_MOSR);
 			if (cs->debug & L1_DEB_MONITOR)
 				debugl1(cs, "ISAC MOSR %02x", v1);
 #if ARCOFI_USE
@@ -251,7 +318,7 @@ isac_interrupt(struct IsdnCardState *cs,
 							debugl1(cs, "ISAC MON RX out of memory!");
 						cs->dc.isac.mocr &= 0xf0;
 						cs->dc.isac.mocr |= 0x0a;
-						isac_write(cs, ISAC_MOCR, cs->dc.isac.mocr);
+						cs->writeisac(cs, ISAC_MOCR, cs->dc.isac.mocr);
 						goto afterMONR0;
 					} else
 						cs->dc.isac.mon_rxp = 0;
@@ -259,18 +326,18 @@ isac_interrupt(struct IsdnCardState *cs,
 				if (cs->dc.isac.mon_rxp >= MAX_MON_FRAME) {
 					cs->dc.isac.mocr &= 0xf0;
 					cs->dc.isac.mocr |= 0x0a;
-					isac_write(cs, ISAC_MOCR, cs->dc.isac.mocr);
+					cs->writeisac(cs, ISAC_MOCR, cs->dc.isac.mocr);
 					cs->dc.isac.mon_rxp = 0;
 					if (cs->debug & L1_DEB_WARN)
 						debugl1(cs, "ISAC MON RX overflow!");
 					goto afterMONR0;
 				}
-				cs->dc.isac.mon_rx[cs->dc.isac.mon_rxp++] = isac_read(cs, ISAC_MOR0);
+				cs->dc.isac.mon_rx[cs->dc.isac.mon_rxp++] = cs->readisac(cs, ISAC_MOR0);
 				if (cs->debug & L1_DEB_MONITOR)
 					debugl1(cs, "ISAC MOR0 %02x", cs->dc.isac.mon_rx[cs->dc.isac.mon_rxp -1]);
 				if (cs->dc.isac.mon_rxp == 1) {
 					cs->dc.isac.mocr |= 0x04;
-					isac_write(cs, ISAC_MOCR, cs->dc.isac.mocr);
+					cs->writeisac(cs, ISAC_MOCR, cs->dc.isac.mocr);
 				}
 			}
 		      afterMONR0:
@@ -281,7 +348,7 @@ isac_interrupt(struct IsdnCardState *cs,
 							debugl1(cs, "ISAC MON RX out of memory!");
 						cs->dc.isac.mocr &= 0x0f;
 						cs->dc.isac.mocr |= 0xa0;
-						isac_write(cs, ISAC_MOCR, cs->dc.isac.mocr);
+						cs->writeisac(cs, ISAC_MOCR, cs->dc.isac.mocr);
 						goto afterMONR1;
 					} else
 						cs->dc.isac.mon_rxp = 0;
@@ -289,51 +356,51 @@ isac_interrupt(struct IsdnCardState *cs,
 				if (cs->dc.isac.mon_rxp >= MAX_MON_FRAME) {
 					cs->dc.isac.mocr &= 0x0f;
 					cs->dc.isac.mocr |= 0xa0;
-					isac_write(cs, ISAC_MOCR, cs->dc.isac.mocr);
+					cs->writeisac(cs, ISAC_MOCR, cs->dc.isac.mocr);
 					cs->dc.isac.mon_rxp = 0;
 					if (cs->debug & L1_DEB_WARN)
 						debugl1(cs, "ISAC MON RX overflow!");
 					goto afterMONR1;
 				}
-				cs->dc.isac.mon_rx[cs->dc.isac.mon_rxp++] = isac_read(cs, ISAC_MOR1);
+				cs->dc.isac.mon_rx[cs->dc.isac.mon_rxp++] = cs->readisac(cs, ISAC_MOR1);
 				if (cs->debug & L1_DEB_MONITOR)
 					debugl1(cs, "ISAC MOR1 %02x", cs->dc.isac.mon_rx[cs->dc.isac.mon_rxp -1]);
 				cs->dc.isac.mocr |= 0x40;
-				isac_write(cs, ISAC_MOCR, cs->dc.isac.mocr);
+				cs->writeisac(cs, ISAC_MOCR, cs->dc.isac.mocr);
 			}
 		      afterMONR1:
 			if (v1 & 0x04) {
 				cs->dc.isac.mocr &= 0xf0;
-				isac_write(cs, ISAC_MOCR, cs->dc.isac.mocr);
+				cs->writeisac(cs, ISAC_MOCR, cs->dc.isac.mocr);
 				cs->dc.isac.mocr |= 0x0a;
-				isac_write(cs, ISAC_MOCR, cs->dc.isac.mocr);
-				sched_d_event(cs, D_RX_MON0);
+				cs->writeisac(cs, ISAC_MOCR, cs->dc.isac.mocr);
+				schedule_event(cs, D_RX_MON0);
 			}
 			if (v1 & 0x40) {
 				cs->dc.isac.mocr &= 0x0f;
-				isac_write(cs, ISAC_MOCR, cs->dc.isac.mocr);
+				cs->writeisac(cs, ISAC_MOCR, cs->dc.isac.mocr);
 				cs->dc.isac.mocr |= 0xa0;
-				isac_write(cs, ISAC_MOCR, cs->dc.isac.mocr);
-				sched_d_event(cs, D_RX_MON1);
+				cs->writeisac(cs, ISAC_MOCR, cs->dc.isac.mocr);
+				schedule_event(cs, D_RX_MON1);
 			}
 			if (v1 & 0x02) {
 				if ((!cs->dc.isac.mon_tx) || (cs->dc.isac.mon_txc && 
 					(cs->dc.isac.mon_txp >= cs->dc.isac.mon_txc) && 
 					!(v1 & 0x08))) {
 					cs->dc.isac.mocr &= 0xf0;
-					isac_write(cs, ISAC_MOCR, cs->dc.isac.mocr);
+					cs->writeisac(cs, ISAC_MOCR, cs->dc.isac.mocr);
 					cs->dc.isac.mocr |= 0x0a;
-					isac_write(cs, ISAC_MOCR, cs->dc.isac.mocr);
+					cs->writeisac(cs, ISAC_MOCR, cs->dc.isac.mocr);
 					if (cs->dc.isac.mon_txc &&
 						(cs->dc.isac.mon_txp >= cs->dc.isac.mon_txc))
-						sched_d_event(cs, D_TX_MON0);
+						schedule_event(cs, D_TX_MON0);
 					goto AfterMOX0;
 				}
 				if (cs->dc.isac.mon_txc && (cs->dc.isac.mon_txp >= cs->dc.isac.mon_txc)) {
-					sched_d_event(cs, D_TX_MON0);
+					schedule_event(cs, D_TX_MON0);
 					goto AfterMOX0;
 				}
-				isac_write(cs, ISAC_MOX0,
+				cs->writeisac(cs, ISAC_MOX0,
 					cs->dc.isac.mon_tx[cs->dc.isac.mon_txp++]);
 				if (cs->debug & L1_DEB_MONITOR)
 					debugl1(cs, "ISAC %02x -> MOX0", cs->dc.isac.mon_tx[cs->dc.isac.mon_txp -1]);
@@ -344,19 +411,19 @@ isac_interrupt(struct IsdnCardState *cs,
 					(cs->dc.isac.mon_txp >= cs->dc.isac.mon_txc) && 
 					!(v1 & 0x80))) {
 					cs->dc.isac.mocr &= 0x0f;
-					isac_write(cs, ISAC_MOCR, cs->dc.isac.mocr);
+					cs->writeisac(cs, ISAC_MOCR, cs->dc.isac.mocr);
 					cs->dc.isac.mocr |= 0xa0;
-					isac_write(cs, ISAC_MOCR, cs->dc.isac.mocr);
+					cs->writeisac(cs, ISAC_MOCR, cs->dc.isac.mocr);
 					if (cs->dc.isac.mon_txc &&
 						(cs->dc.isac.mon_txp >= cs->dc.isac.mon_txc))
-						sched_d_event(cs, D_TX_MON1);
+						schedule_event(cs, D_TX_MON1);
 					goto AfterMOX1;
 				}
 				if (cs->dc.isac.mon_txc && (cs->dc.isac.mon_txp >= cs->dc.isac.mon_txc)) {
-					sched_d_event(cs, D_TX_MON1);
+					schedule_event(cs, D_TX_MON1);
 					goto AfterMOX1;
 				}
-				isac_write(cs, ISAC_MOX1,
+				cs->writeisac(cs, ISAC_MOX1,
 					cs->dc.isac.mon_tx[cs->dc.isac.mon_txp++]);
 				if (cs->debug & L1_DEB_MONITOR)
 					debugl1(cs, "ISAC %02x -> MOX1", cs->dc.isac.mon_tx[cs->dc.isac.mon_txp -1]);
@@ -372,33 +439,87 @@ ISAC_l1hw(struct PStack *st, int pr, voi
 {
 	struct IsdnCardState *cs = (struct IsdnCardState *) st->l1.hardware;
 	struct sk_buff *skb = arg;
+	u_long flags;
 	int  val;
 
 	switch (pr) {
 		case (PH_DATA |REQUEST):
-			xmit_data_req_d(cs, skb);
+			if (cs->debug & DEB_DLOG_HEX)
+				LogFrame(cs, skb->data, skb->len);
+			if (cs->debug & DEB_DLOG_VERBOSE)
+				dlogframe(cs, skb, 0);
+			spin_lock_irqsave(&cs->lock, flags);
+			if (cs->tx_skb) {
+				skb_queue_tail(&cs->sq, skb);
+#ifdef L2FRAME_DEBUG		/* psa */
+				if (cs->debug & L1_DEB_LAPD)
+					Logl2Frame(cs, skb, "PH_DATA Queued", 0);
+#endif
+			} else {
+				cs->tx_skb = skb;
+				cs->tx_cnt = 0;
+#ifdef L2FRAME_DEBUG		/* psa */
+				if (cs->debug & L1_DEB_LAPD)
+					Logl2Frame(cs, skb, "PH_DATA", 0);
+#endif
+				isac_fill_fifo(cs);
+			}
+			spin_unlock_irqrestore(&cs->lock, flags);
 			break;
 		case (PH_PULL |INDICATION):
-			xmit_pull_ind_d(cs, skb);
+			spin_lock_irqsave(&cs->lock, flags);
+			if (cs->tx_skb) {
+				if (cs->debug & L1_DEB_WARN)
+					debugl1(cs, " l2l1 tx_skb exist this shouldn't happen");
+				skb_queue_tail(&cs->sq, skb);
+			} else {
+				if (cs->debug & DEB_DLOG_HEX)
+					LogFrame(cs, skb->data, skb->len);
+				if (cs->debug & DEB_DLOG_VERBOSE)
+					dlogframe(cs, skb, 0);
+				cs->tx_skb = skb;
+				cs->tx_cnt = 0;
+#ifdef L2FRAME_DEBUG		/* psa */
+				if (cs->debug & L1_DEB_LAPD)
+					Logl2Frame(cs, skb, "PH_DATA_PULLED", 0);
+#endif
+				isac_fill_fifo(cs);
+			}
+			spin_unlock_irqrestore(&cs->lock, flags);
 			break;
 		case (PH_PULL | REQUEST):
-			xmit_pull_req_d(st);
+#ifdef L2FRAME_DEBUG		/* psa */
+			if (cs->debug & L1_DEB_LAPD)
+				debugl1(cs, "-> PH_REQUEST_PULL");
+#endif
+			if (!cs->tx_skb) {
+				test_and_clear_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
+				st->l1.l1l2(st, PH_PULL | CONFIRM, NULL);
+			} else
+				test_and_set_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
 			break;
 		case (HW_RESET | REQUEST):
+			spin_lock_irqsave(&cs->lock, flags);
 			if ((cs->dc.isac.ph_state == ISAC_IND_EI) ||
 				(cs->dc.isac.ph_state == ISAC_IND_DR) ||
 				(cs->dc.isac.ph_state == ISAC_IND_RS))
 			        ph_command(cs, ISAC_CMD_TIM);
 			else
 				ph_command(cs, ISAC_CMD_RS);
+			spin_unlock_irqrestore(&cs->lock, flags);
 			break;
 		case (HW_ENABLE | REQUEST):
+			spin_lock_irqsave(&cs->lock, flags);
 			ph_command(cs, ISAC_CMD_TIM);
+			spin_unlock_irqrestore(&cs->lock, flags);
 			break;
 		case (HW_INFO3 | REQUEST):
+			spin_lock_irqsave(&cs->lock, flags);
 			ph_command(cs, ISAC_CMD_AR8);
+			spin_unlock_irqrestore(&cs->lock, flags);
 			break;
 		case (HW_TESTLOOP | REQUEST):
+			spin_lock_irqsave(&cs->lock, flags);
 			val = 0;
 			if (1 & (long) arg)
 				val |= 0x0c;
@@ -407,20 +528,21 @@ ISAC_l1hw(struct PStack *st, int pr, voi
 			if (test_bit(HW_IOM1, &cs->HW_Flags)) {
 				/* IOM 1 Mode */
 				if (!val) {
-					isac_write(cs, ISAC_SPCR, 0xa);
-					isac_write(cs, ISAC_ADF1, 0x2);
+					cs->writeisac(cs, ISAC_SPCR, 0xa);
+					cs->writeisac(cs, ISAC_ADF1, 0x2);
 				} else {
-					isac_write(cs, ISAC_SPCR, val);
-					isac_write(cs, ISAC_ADF1, 0xa);
+					cs->writeisac(cs, ISAC_SPCR, val);
+					cs->writeisac(cs, ISAC_ADF1, 0xa);
 				}
 			} else {
 				/* IOM 2 Mode */
-				isac_write(cs, ISAC_SPCR, val);
+				cs->writeisac(cs, ISAC_SPCR, val);
 				if (val)
-					isac_write(cs, ISAC_ADF1, 0x8);
+					cs->writeisac(cs, ISAC_ADF1, 0x8);
 				else
-					isac_write(cs, ISAC_ADF1, 0x0);
+					cs->writeisac(cs, ISAC_ADF1, 0x0);
 			}
+			spin_unlock_irqrestore(&cs->lock, flags);
 			break;
 		case (HW_DEACTIVATE | RESPONSE):
 			skb_queue_purge(&cs->rq);
@@ -432,7 +554,7 @@ ISAC_l1hw(struct PStack *st, int pr, voi
 			if (test_and_clear_bit(FLG_DBUSY_TIMER, &cs->HW_Flags))
 				del_timer(&cs->dbusytimer);
 			if (test_and_clear_bit(FLG_L1_DBUSY, &cs->HW_Flags))
-				sched_d_event(cs, D_CLEARBUSY);
+				schedule_event(cs, D_CLEARBUSY);
 			break;
 		default:
 			if (cs->debug & L1_DEB_WARN)
@@ -441,14 +563,13 @@ ISAC_l1hw(struct PStack *st, int pr, voi
 	}
 }
 
-static int
+void
 setstack_isac(struct PStack *st, struct IsdnCardState *cs)
 {
 	st->l1.l1hw = ISAC_l1hw;
-	return 0;
 }
 
-static void 
+void 
 DC_Close_isac(struct IsdnCardState *cs) {
 	if (cs->dc.isac.mon_rx) {
 		kfree(cs->dc.isac.mon_rx);
@@ -467,8 +588,8 @@ dbusy_timer_handler(struct IsdnCardState
 	int	rbch, star;
 
 	if (test_bit(FLG_DBUSY_TIMER, &cs->HW_Flags)) {
-		rbch = isac_read(cs, ISAC_RBCH);
-		star = isac_read(cs, ISAC_STAR);
+		rbch = cs->readisac(cs, ISAC_RBCH);
+		star = cs->readisac(cs, ISAC_STAR);
 		if (cs->debug) 
 			debugl1(cs, "D-Channel Busy RBCH %02x STAR %02x",
 				rbch, star);
@@ -476,7 +597,7 @@ dbusy_timer_handler(struct IsdnCardState
 			test_and_set_bit(FLG_L1_DBUSY, &cs->HW_Flags);
 			stptr = cs->stlist;
 			while (stptr != NULL) {
-				L1L2(stptr, PH_PAUSE | INDICATION, NULL);
+				stptr->l1.l1l2(stptr, PH_PAUSE | INDICATION, NULL);
 				stptr = stptr->next;
 			}
 		} else {
@@ -490,80 +611,74 @@ dbusy_timer_handler(struct IsdnCardState
 				printk(KERN_WARNING "HiSax: ISAC D-Channel Busy no skb\n");
 				debugl1(cs, "D-Channel Busy no skb");
 			}
-			isac_write(cs, ISAC_CMDR, 0x01); /* Transmitter reset */
-			cs->card_ops->irq_func(cs->irq, cs, NULL);
+			cs->writeisac(cs, ISAC_CMDR, 0x01); /* Transmitter reset */
+			cs->irq_func(cs->irq, cs, NULL);
 		}
 	}
 }
 
-static struct dc_l1_ops isac_l1_ops = {
-	.fill_fifo  = isac_fill_fifo,
-	.open       = setstack_isac,
-	.close      = DC_Close_isac,
-	.bh_func    = isac_bh,
-	.dbusy_func = dbusy_timer_handler,
-};
-
 void __devinit
 initisac(struct IsdnCardState *cs)
 {
-	int val, eval;
-
-	dc_l1_init(cs, &isac_l1_ops);
-
-	val = isac_read(cs, ISAC_STAR);
-	debugl1(cs, "ISAC STAR %x", val);
-	val = isac_read(cs, ISAC_MODE);
-	debugl1(cs, "ISAC MODE %x", val);
-	val = isac_read(cs, ISAC_ADF2);
-	debugl1(cs, "ISAC ADF2 %x", val);
-	val = isac_read(cs, ISAC_ISTA);
-	debugl1(cs, "ISAC ISTA %x", val);
-	if (val & 0x01) {
-		eval = isac_read(cs, ISAC_EXIR);
-		debugl1(cs, "ISAC EXIR %x", eval);
-	}
-	/* Disable all IRQ */
-	isac_write(cs, ISAC_MASK, 0xFF);
-
+	cs->setstack_d = setstack_isac;
+	cs->DC_Close = DC_Close_isac;
 	cs->dc.isac.mon_tx = NULL;
 	cs->dc.isac.mon_rx = NULL;
+  	cs->writeisac(cs, ISAC_MASK, 0xff);
   	cs->dc.isac.mocr = 0xaa;
 	if (test_bit(HW_IOM1, &cs->HW_Flags)) {
 		/* IOM 1 Mode */
-		isac_write(cs, ISAC_ADF2, 0x0);
-		isac_write(cs, ISAC_SPCR, 0xa);
-		isac_write(cs, ISAC_ADF1, 0x2);
-		isac_write(cs, ISAC_STCR, 0x70);
-		isac_write(cs, ISAC_MODE, 0xc9);
+		cs->writeisac(cs, ISAC_ADF2, 0x0);
+		cs->writeisac(cs, ISAC_SPCR, 0xa);
+		cs->writeisac(cs, ISAC_ADF1, 0x2);
+		cs->writeisac(cs, ISAC_STCR, 0x70);
+		cs->writeisac(cs, ISAC_MODE, 0xc9);
 	} else {
 		/* IOM 2 Mode */
 		if (!cs->dc.isac.adf2)
 			cs->dc.isac.adf2 = 0x80;
-		isac_write(cs, ISAC_ADF2, cs->dc.isac.adf2);
-		isac_write(cs, ISAC_SQXR, 0x2f);
-		isac_write(cs, ISAC_SPCR, 0x00);
-		isac_write(cs, ISAC_STCR, 0x70);
-		isac_write(cs, ISAC_MODE, 0xc9);
-		isac_write(cs, ISAC_TIMR, 0x00);
-		isac_write(cs, ISAC_ADF1, 0x00);
+		cs->writeisac(cs, ISAC_ADF2, cs->dc.isac.adf2);
+		cs->writeisac(cs, ISAC_SQXR, 0x2f);
+		cs->writeisac(cs, ISAC_SPCR, 0x00);
+		cs->writeisac(cs, ISAC_STCR, 0x70);
+		cs->writeisac(cs, ISAC_MODE, 0xc9);
+		cs->writeisac(cs, ISAC_TIMR, 0x00);
+		cs->writeisac(cs, ISAC_ADF1, 0x00);
 	}
 	ph_command(cs, ISAC_CMD_RS);
-	isac_write(cs, ISAC_MASK, 0x0);
+	cs->writeisac(cs, ISAC_MASK, 0x0);
+}
 
-	val = isac_read(cs, ISAC_CIR0);
+void __devinit
+clear_pending_isac_ints(struct IsdnCardState *cs)
+{
+	int val, eval;
+
+	val = cs->readisac(cs, ISAC_STAR);
+	debugl1(cs, "ISAC STAR %x", val);
+	val = cs->readisac(cs, ISAC_MODE);
+	debugl1(cs, "ISAC MODE %x", val);
+	val = cs->readisac(cs, ISAC_ADF2);
+	debugl1(cs, "ISAC ADF2 %x", val);
+	val = cs->readisac(cs, ISAC_ISTA);
+	debugl1(cs, "ISAC ISTA %x", val);
+	if (val & 0x01) {
+		eval = cs->readisac(cs, ISAC_EXIR);
+		debugl1(cs, "ISAC EXIR %x", eval);
+	}
+	val = cs->readisac(cs, ISAC_CIR0);
 	debugl1(cs, "ISAC CIR0 %x", val);
 	cs->dc.isac.ph_state = (val >> 2) & 0xf;
-	sched_d_event(cs, D_L1STATECHANGE);
-
-	/* RESET Receiver and Transmitter */
-	isac_write(cs, ISAC_CMDR, 0x41);
+	schedule_event(cs, D_L1STATECHANGE);
+	/* Disable all IRQ */
+	cs->writeisac(cs, ISAC_MASK, 0xFF);
 }
 
-int
-isac_setup(struct IsdnCardState *cs, struct dc_hw_ops *isac_ops)
+void __devinit
+setup_isac(struct IsdnCardState *cs)
 {
-	cs->dc_hw_ops = isac_ops;
-	ISACVersion(cs, "HiSax:");
-	return 0;
+	INIT_WORK(&cs->tqueue, (void *)(void *) isac_bh, cs);
+	cs->dbusytimer.function = (void *) dbusy_timer_handler;
+	cs->dbusytimer.data = (long) cs;
+	init_timer(&cs->dbusytimer);
 }
--- diff/drivers/isdn/hisax/isac.h	2003-01-16 11:30:36.000000000 +0000
+++ source/drivers/isdn/hisax/isac.h	2004-02-23 13:56:42.000000000 +0000
@@ -1,4 +1,4 @@
-/* $Id: isac.h,v 1.7.6.2 2001/09/23 22:24:49 kai Exp $
+/* $Id: isac.h,v 1.9.2.2 2004/01/12 22:52:27 keil Exp $
  *
  * ISAC specific defines
  *
@@ -63,6 +63,8 @@
 #define ISAC_IND_AI10	0xD
 #define ISAC_IND_DID	0xF
 
-extern void initisac(struct IsdnCardState *cs);
-extern void isac_interrupt(struct IsdnCardState *cs, u8 val);
-extern int  isac_setup(struct IsdnCardState *cs, struct dc_hw_ops *isac_ops);
+extern void ISACVersion(struct IsdnCardState *, char *);
+extern void setup_isac(struct IsdnCardState *);
+extern void initisac(struct IsdnCardState *);
+extern void isac_interrupt(struct IsdnCardState *, u_char);
+extern void clear_pending_isac_ints(struct IsdnCardState *);
--- diff/drivers/isdn/hisax/isar.c	2003-09-30 15:46:14.000000000 +0100
+++ source/drivers/isdn/hisax/isar.c	2004-02-23 13:56:42.000000000 +0000
@@ -1,4 +1,4 @@
-/* $Id: isar.c,v 1.17.6.5 2001/09/23 11:51:33 keil Exp $
+/* $Id: isar.c,v 1.22.2.6 2004/02/11 13:21:34 keil Exp $
  *
  * isar.c   ISAR (Siemens PSB 7110) specific routines
  *
@@ -20,33 +20,22 @@
 #define DLE	0x10
 #define ETX	0x03
 
-
-const u8 faxmodulation_s[] = "3,24,48,72,73,74,96,97,98,121,122,145,146"; 
-const u8 faxmodulation[] = {3,24,48,72,73,74,96,97,98,121,122,145,146}; 
-#define FAXMODCNT 13
-
-static void __isar_setup(struct IsdnCardState *cs);
-static void isar_pump_cmd(struct BCState *bcs, u8 cmd, u8 para);
-static inline void ll_deliver_faxstat(struct BCState *bcs, u8 status);
-static spinlock_t isar_lock = SPIN_LOCK_UNLOCKED;
-
-static inline u8
-isar_read_reg(struct IsdnCardState *cs, int mode, u8 addr)
-{
-	return cs->bc_hw_ops->read_reg(cs, mode, addr);
-}
-
-static inline void
-isar_write_reg(struct IsdnCardState *cs, int mode, u8 addr, u8 val)
-{
-	cs->bc_hw_ops->write_reg(cs, mode, addr, val);
-}
+#define FAXMODCNT	13
+const	u_char	faxmodulation[] = {3,24,48,72,73,74,96,97,98,121,122,145,146};
+static	u_int	modmask = 0x1fff;
+static	int	frm_extra_delay = 2;
+static	int	para_TOA = 6;
+const   u_char  *FC1_CMD[] = {"FAE", "FTS", "FRS", "FTM", "FRM", "FTH", "FRH", "CTRL" };
+
+void isar_setup(struct IsdnCardState *cs);
+static void isar_pump_cmd(struct BCState *bcs, u_char cmd, u_char para);
+static void ll_deliver_faxstat(struct BCState *bcs, u_char status);
 
 static inline int
 waitforHIA(struct IsdnCardState *cs, int timeout)
 {
 
-	while ((isar_read_reg(cs, 0, ISAR_HIA) & 1) && timeout) {
+	while ((cs->BC_Read_Reg(cs, 0, ISAR_HIA) & 1) && timeout) {
 		udelay(1);
 		timeout--;
 	}
@@ -57,10 +46,9 @@ waitforHIA(struct IsdnCardState *cs, int
 
 
 int
-sendmsg(struct IsdnCardState *cs, u8 his, u8 creg, u8 len,
-	u8 *msg)
+sendmsg(struct IsdnCardState *cs, u_char his, u_char creg, u_char len,
+	u_char *msg)
 {
-	unsigned long flags;
 	int i;
 	
 	if (!waitforHIA(cs, 4000))
@@ -69,14 +57,13 @@ sendmsg(struct IsdnCardState *cs, u8 his
 	if (cs->debug & L1_DEB_HSCX)
 		debugl1(cs, "sendmsg(%02x,%02x,%d)", his, creg, len);
 #endif
-	spin_lock_irqsave(&isar_lock, flags);
-	isar_write_reg(cs, 0, ISAR_CTRL_H, creg);
-	isar_write_reg(cs, 0, ISAR_CTRL_L, len);
-	isar_write_reg(cs, 0, ISAR_WADR, 0);
+	cs->BC_Write_Reg(cs, 0, ISAR_CTRL_H, creg);
+	cs->BC_Write_Reg(cs, 0, ISAR_CTRL_L, len);
+	cs->BC_Write_Reg(cs, 0, ISAR_WADR, 0);
 	if (msg && len) {
-		isar_write_reg(cs, 1, ISAR_MBOX, msg[0]);
+		cs->BC_Write_Reg(cs, 1, ISAR_MBOX, msg[0]);
 		for (i=1; i<len; i++)
-			isar_write_reg(cs, 2, ISAR_MBOX, msg[i]);
+			cs->BC_Write_Reg(cs, 2, ISAR_MBOX, msg[i]);
 #if DUMP_MBOXFRAME>1
 		if (cs->debug & L1_DEB_HSCX_FIFO) {
 			char tmp[256], *t;
@@ -92,23 +79,22 @@ sendmsg(struct IsdnCardState *cs, u8 his
 		}
 #endif
 	}
-	isar_write_reg(cs, 1, ISAR_HIS, his);
-	spin_unlock_irqrestore(&isar_lock, flags);
+	cs->BC_Write_Reg(cs, 1, ISAR_HIS, his);
 	waitforHIA(cs, 10000);
 	return(1);
 }
 
 /* Call only with IRQ disabled !!! */
 inline void
-rcv_mbox(struct IsdnCardState *cs, struct isar_reg *ireg, u8 *msg)
+rcv_mbox(struct IsdnCardState *cs, struct isar_reg *ireg, u_char *msg)
 {
 	int i;
 
-	isar_write_reg(cs, 1, ISAR_RADR, 0);
+	cs->BC_Write_Reg(cs, 1, ISAR_RADR, 0);
 	if (msg && ireg->clsb) {
-		msg[0] = isar_read_reg(cs, 1, ISAR_MBOX);
+		msg[0] = cs->BC_Read_Reg(cs, 1, ISAR_MBOX);
 		for (i=1; i < ireg->clsb; i++)
-			 msg[i] = isar_read_reg(cs, 2, ISAR_MBOX);
+			 msg[i] = cs->BC_Read_Reg(cs, 2, ISAR_MBOX);
 #if DUMP_MBOXFRAME>1
 		if (cs->debug & L1_DEB_HSCX_FIFO) {
 			char tmp[256], *t;
@@ -124,85 +110,90 @@ rcv_mbox(struct IsdnCardState *cs, struc
 		}
 #endif
 	}
-	isar_write_reg(cs, 1, ISAR_IIA, 0);
+	cs->BC_Write_Reg(cs, 1, ISAR_IIA, 0);
 }
 
 /* Call only with IRQ disabled !!! */
 inline void
 get_irq_infos(struct IsdnCardState *cs, struct isar_reg *ireg)
 {
-	ireg->iis = isar_read_reg(cs, 1, ISAR_IIS);
-	ireg->cmsb = isar_read_reg(cs, 1, ISAR_CTRL_H);
-	ireg->clsb = isar_read_reg(cs, 1, ISAR_CTRL_L);
+	ireg->iis = cs->BC_Read_Reg(cs, 1, ISAR_IIS);
+	ireg->cmsb = cs->BC_Read_Reg(cs, 1, ISAR_CTRL_H);
+	ireg->clsb = cs->BC_Read_Reg(cs, 1, ISAR_CTRL_L);
 #if DUMP_MBOXFRAME
 	if (cs->debug & L1_DEB_HSCX)
-		debugl1(cs, "rcv_mbox(%02x,%02x,%d)", ireg->iis, ireg->cmsb,
+		debugl1(cs, "irq_stat(%02x,%02x,%d)", ireg->iis, ireg->cmsb,
 			ireg->clsb);
 #endif
 }
 
 int
-waitrecmsg(struct IsdnCardState *cs, u8 *len,
-	u8 *msg, int maxdelay)
+waitrecmsg(struct IsdnCardState *cs, u_char *len,
+	u_char *msg, int maxdelay)
 {
 	int timeout = 0;
-	unsigned long flags;
 	struct isar_reg *ir = cs->bcs[0].hw.isar.reg;
 	
 	
-	while((!(isar_read_reg(cs, 0, ISAR_IRQBIT) & ISAR_IRQSTA)) &&
+	while((!(cs->BC_Read_Reg(cs, 0, ISAR_IRQBIT) & ISAR_IRQSTA)) &&
 		(timeout++ < maxdelay))
 		udelay(1);
 	if (timeout >= maxdelay) {
 		printk(KERN_WARNING"isar recmsg IRQSTA timeout\n");
 		return(0);
 	}
-	spin_lock_irqsave(&isar_lock, flags);
 	get_irq_infos(cs, ir);
 	rcv_mbox(cs, ir, msg);
 	*len = ir->clsb;
-	spin_unlock_irqrestore(&isar_lock, flags);
 	return(1);
 }
 
-static int
+int
 ISARVersion(struct IsdnCardState *cs, char *s)
 {
 	int ver;
-	u8 msg[] = ISAR_MSG_HWVER;
-	u8 tmp[64];
-	u8 len;
+	u_char msg[] = ISAR_MSG_HWVER;
+	u_char tmp[64];
+	u_char len;
+	u_long flags;
 	int debug;
 
-	cs->card_ops->reset(cs);
+	cs->cardmsg(cs, CARD_RESET,  NULL);
+	spin_lock_irqsave(&cs->lock, flags);
 	/* disable ISAR IRQ */
-	isar_write_reg(cs, 0, ISAR_IRQBIT, 0);
+	cs->BC_Write_Reg(cs, 0, ISAR_IRQBIT, 0);
 	debug = cs->debug;
 	cs->debug &= ~(L1_DEB_HSCX | L1_DEB_HSCX_FIFO);
-	if (!sendmsg(cs, ISAR_HIS_VNR, 0, 3, msg))
+	if (!sendmsg(cs, ISAR_HIS_VNR, 0, 3, msg)) {
+		spin_unlock_irqrestore(&cs->lock, flags);
 		return(-1);
-	if (!waitrecmsg(cs, &len, tmp, 100000))
-		 return(-2);
+	}
+	if (!waitrecmsg(cs, &len, tmp, 100000)) {
+		spin_unlock_irqrestore(&cs->lock, flags);
+		return(-2);
+	}
 	cs->debug = debug;
 	if (cs->bcs[0].hw.isar.reg->iis == ISAR_IIS_VNR) {
 		if (len == 1) {
 			ver = tmp[0] & 0xf;
 			printk(KERN_INFO "%s ISAR version %d\n", s, ver);
-			return(ver);
-		}
-		return(-3);
-	}
-	return(-4);
+		} else
+			ver = -3;
+	} else
+		ver = -4;
+	spin_unlock_irqrestore(&cs->lock, flags);
+	return(ver);
 }
 
 int
-isar_load_firmware(struct IsdnCardState *cs, u8 *buf)
+isar_load_firmware(struct IsdnCardState *cs, u_char *buf)
 {
 	int ret, size, cnt, debug;
-	u8 len, nom, noc;
+	u_char len, nom, noc;
 	u_short sadr, left, *sp;
-	u8 *p = buf;
-	u8 *msg, *tmpmsg, *mp, tmp[64];
+	u_char *p = buf;
+	u_char *msg, *tmpmsg, *mp, tmp[64];
+	u_long flags;
 	struct isar_reg *ireg = cs->bcs[0].hw.isar.reg;
 	
 	struct {u_short sadr;
@@ -219,16 +210,16 @@ isar_load_firmware(struct IsdnCardState 
 #if DBG_LOADFIRM<2
 	cs->debug &= ~(L1_DEB_HSCX | L1_DEB_HSCX_FIFO);
 #endif
-	printk(KERN_DEBUG"isar_load_firmware buf %#lx\n", (u_long)buf);
+	
 	if ((ret = copy_from_user(&size, p, sizeof(int)))) {
 		printk(KERN_ERR"isar_load_firmware copy_from_user ret %d\n", ret);
-		return -EFAULT;
+		return ret;
 	}
 	p += sizeof(int);
 	printk(KERN_DEBUG"isar_load_firmware size: %d\n", size);
 	cnt = 0;
 	/* disable ISAR IRQ */
-	isar_write_reg(cs, 0, ISAR_IRQBIT, 0);
+	cs->BC_Write_Reg(cs, 0, ISAR_IRQBIT, 0);
 	if (!(msg = kmalloc(256, GFP_KERNEL))) {
 		printk(KERN_ERR"isar_load_firmware no buffer\n");
 		return (1);
@@ -238,10 +229,13 @@ isar_load_firmware(struct IsdnCardState 
 		kfree(msg);
 		return (1);
 	}
+	spin_lock_irqsave(&cs->lock, flags);
+	/* disable ISAR IRQ */
+	cs->BC_Write_Reg(cs, 0, ISAR_IRQBIT, 0);
+	spin_unlock_irqrestore(&cs->lock, flags);
 	while (cnt < size) {
 		if ((ret = copy_from_user(&blk_head, p, BLK_HEAD_SIZE))) {
 			printk(KERN_ERR"isar_load_firmware copy_from_user ret %d\n", ret);
-			ret = -EFAULT;
 			goto reterror;
 		}
 #ifdef __BIG_ENDIAN
@@ -258,19 +252,21 @@ isar_load_firmware(struct IsdnCardState 
 			blk_head.sadr, blk_head.len, blk_head.d_key & 0xff);
 		sadr = blk_head.sadr;
 		left = blk_head.len;
+		spin_lock_irqsave(&cs->lock, flags);
 		if (!sendmsg(cs, ISAR_HIS_DKEY, blk_head.d_key & 0xff, 0, NULL)) {
 			printk(KERN_ERR"isar sendmsg dkey failed\n");
-			ret = 1;goto reterror;
+			ret = 1;goto reterr_unlock;
 		}
 		if (!waitrecmsg(cs, &len, tmp, 100000)) {
 			printk(KERN_ERR"isar waitrecmsg dkey failed\n");
-			ret = 1;goto reterror;
+			ret = 1;goto reterr_unlock;
 		}
 		if ((ireg->iis != ISAR_IIS_DKEY) || ireg->cmsb || len) {
 			printk(KERN_ERR"isar wrong dkey response (%x,%x,%x)\n",
 				ireg->iis, ireg->cmsb, len);
-			ret = 1;goto reterror;
+			ret = 1;goto reterr_unlock;
 		}
+		spin_unlock_irqrestore(&cs->lock, flags);
 		while (left>0) {
 			if (left > 126)
 				noc = 126;
@@ -284,7 +280,6 @@ isar_load_firmware(struct IsdnCardState 
 			*mp++ = noc;
 			if ((ret = copy_from_user(tmpmsg, p, nom))) {
 				printk(KERN_ERR"isar_load_firmware copy_from_user ret %d\n", ret);
-				ret = -EFAULT;
 				goto reterror;
 			}
 			p += nom;
@@ -307,19 +302,21 @@ isar_load_firmware(struct IsdnCardState 
 				sp++;
 				noc--;
 			}
+			spin_lock_irqsave(&cs->lock, flags);
 			if (!sendmsg(cs, ISAR_HIS_FIRM, 0, nom, msg)) {
 				printk(KERN_ERR"isar sendmsg prog failed\n");
-				ret = 1;goto reterror;
+				ret = 1;goto reterr_unlock;
 			}
 			if (!waitrecmsg(cs, &len, tmp, 100000)) {
 				printk(KERN_ERR"isar waitrecmsg prog failed\n");
-				ret = 1;goto reterror;
+				ret = 1;goto reterr_unlock;
 			}
 			if ((ireg->iis != ISAR_IIS_FIRM) || ireg->cmsb || len) {
 				printk(KERN_ERR"isar wrong prog response (%x,%x,%x)\n",
 					ireg->iis, ireg->cmsb, len);
-				ret = 1;goto reterror;
+				ret = 1;goto reterr_unlock;
 			}
+			spin_unlock_irqrestore(&cs->lock, flags);
 		}
 		printk(KERN_DEBUG"isar firmware block %5d words loaded\n",
 			blk_head.len);
@@ -331,23 +328,25 @@ isar_load_firmware(struct IsdnCardState 
 	msg[0] = 0xff;
 	msg[1] = 0xfe;
 	ireg->bstat = 0;
+	spin_lock_irqsave(&cs->lock, flags);
 	if (!sendmsg(cs, ISAR_HIS_STDSP, 0, 2, msg)) {
 		printk(KERN_ERR"isar sendmsg start dsp failed\n");
-		ret = 1;goto reterror;
+		ret = 1;goto reterr_unlock;
 	}
 	if (!waitrecmsg(cs, &len, tmp, 100000)) {
 		printk(KERN_ERR"isar waitrecmsg start dsp failed\n");
-		ret = 1;goto reterror;
+		ret = 1;goto reterr_unlock;
 	}
 	if ((ireg->iis != ISAR_IIS_STDSP) || ireg->cmsb || len) {
 		printk(KERN_ERR"isar wrong start dsp response (%x,%x,%x)\n",
 			ireg->iis, ireg->cmsb, len);
-		ret = 1;goto reterror;
+		ret = 1;goto reterr_unlock;
 	} else
 		printk(KERN_DEBUG"isar start dsp success\n");
 	/* NORMAL mode entered */
 	/* Enable IRQs of ISAR */
-	isar_write_reg(cs, 0, ISAR_IRQBIT, ISAR_IRQSTA);
+	cs->BC_Write_Reg(cs, 0, ISAR_IRQBIT, ISAR_IRQSTA);
+	spin_unlock_irqrestore(&cs->lock, flags);
 	cnt = 1000; /* max 1s */
 	while ((!ireg->bstat) && cnt) {
 		udelay(1000);
@@ -364,12 +363,14 @@ isar_load_firmware(struct IsdnCardState 
 	cnt = 10;
 	while (cnt--)
 		udelay(1000);
+	spin_lock_irqsave(&cs->lock, flags);
 	ireg->iis = 0;
 	if (!sendmsg(cs, ISAR_HIS_DIAG, ISAR_CTRL_STST, 0, NULL)) {
 		printk(KERN_ERR"isar sendmsg self tst failed\n");
-		ret = 1;goto reterror;
+		ret = 1;goto reterr_unlock;
 	}
 	cnt = 10000; /* max 100 ms */
+	spin_unlock_irqrestore(&cs->lock, flags);
 	while ((ireg->iis != ISAR_IIS_DIAG) && cnt) {
 		udelay(10);
 		cnt--;
@@ -387,11 +388,13 @@ isar_load_firmware(struct IsdnCardState 
 			ireg->cmsb, ireg->clsb, ireg->par[0]);
 		ret = 1;goto reterror;
 	}
+	spin_lock_irqsave(&cs->lock, flags);
 	ireg->iis = 0;
 	if (!sendmsg(cs, ISAR_HIS_DIAG, ISAR_CTRL_SWVER, 0, NULL)) {
 		printk(KERN_ERR"isar RQST SVN failed\n");
-		ret = 1;goto reterror;
+		ret = 1;goto reterr_unlock;
 	}
+	spin_unlock_irqrestore(&cs->lock, flags);
 	cnt = 30000; /* max 300 ms */
 	while ((ireg->iis != ISAR_IIS_DIAG) && cnt) {
 		udelay(10);
@@ -411,26 +414,31 @@ isar_load_firmware(struct IsdnCardState 
 			ret = 1;goto reterror;
 		}
 	}
+	spin_lock_irqsave(&cs->lock, flags);
 	cs->debug = debug;
-	__isar_setup(cs);
+	isar_setup(cs);
+
 	ret = 0;
+reterr_unlock:
+	spin_unlock_irqrestore(&cs->lock, flags);
 reterror:
 	cs->debug = debug;
 	if (ret)
 		/* disable ISAR IRQ */
-		isar_write_reg(cs, 0, ISAR_IRQBIT, 0);
+		cs->BC_Write_Reg(cs, 0, ISAR_IRQBIT, 0);
 	kfree(msg);
 	kfree(tmpmsg);
 	return(ret);
 }
 
 extern void BChannel_bh(struct BCState *);
+#define B_LL_NOCARRIER	8
+#define B_LL_CONNECT	9
+#define B_LL_OK		10
 
 static void
-isar_bh(void *data)
+isar_bh(struct BCState *bcs)
 {
-	struct BCState *bcs = data;
-
 	BChannel_bh(bcs);
 	if (test_and_clear_bit(B_LL_NOCARRIER, &bcs->event))
 		ll_deliver_faxstat(bcs, ISDN_FAX_CLASS1_NOCARR);
@@ -440,16 +448,16 @@ isar_bh(void *data)
 		ll_deliver_faxstat(bcs, ISDN_FAX_CLASS1_OK);
 }
 
-static inline void
+static void
 send_DLE_ETX(struct BCState *bcs)
 {
-	u8 dleetx[2] = {DLE,ETX};
+	u_char dleetx[2] = {DLE,ETX};
 	struct sk_buff *skb;
 	
 	if ((skb = dev_alloc_skb(2))) {
 		memcpy(skb_put(skb, 2), dleetx, 2);
 		skb_queue_tail(&bcs->rqueue, skb);
-		sched_b_event(bcs, B_RCVBUFREADY);
+		schedule_event(bcs, B_RCVBUFREADY);
 	} else {
 		printk(KERN_WARNING "HiSax: skb out of memory\n");
 	}
@@ -476,16 +484,16 @@ insert_dle(unsigned char *dest, unsigned
 	}
 }
  
-static inline void
+static void
 isar_rcv_frame(struct IsdnCardState *cs, struct BCState *bcs)
 {
-	u8 *ptr;
+	u_char *ptr;
 	struct sk_buff *skb;
 	struct isar_reg *ireg = bcs->hw.isar.reg;
 	
 	if (!ireg->clsb) {
 		debugl1(cs, "isar zero len frame");
-		isar_write_reg(cs, 1, ISAR_IIA, 0);
+		cs->BC_Write_Reg(cs, 1, ISAR_IIA, 0);
 		return;
 	}
 	switch (bcs->mode) {
@@ -494,24 +502,24 @@ isar_rcv_frame(struct IsdnCardState *cs,
 			ireg->iis, ireg->cmsb, ireg->clsb);
 		printk(KERN_WARNING"isar mode 0 spurious IIS_RDATA %x/%x/%x\n",
 			ireg->iis, ireg->cmsb, ireg->clsb);
-		isar_write_reg(cs, 1, ISAR_IIA, 0);
+		cs->BC_Write_Reg(cs, 1, ISAR_IIA, 0);
 		break;
 	case L1_MODE_TRANS:
 	case L1_MODE_V32:
 		if ((skb = dev_alloc_skb(ireg->clsb))) {
-			rcv_mbox(cs, ireg, (u8 *)skb_put(skb, ireg->clsb));
+			rcv_mbox(cs, ireg, (u_char *)skb_put(skb, ireg->clsb));
 			skb_queue_tail(&bcs->rqueue, skb);
-			sched_b_event(bcs, B_RCVBUFREADY);
+			schedule_event(bcs, B_RCVBUFREADY);
 		} else {
 			printk(KERN_WARNING "HiSax: skb out of memory\n");
-			isar_write_reg(cs, 1, ISAR_IIA, 0);
+			cs->BC_Write_Reg(cs, 1, ISAR_IIA, 0);
 		}
 		break;
 	case L1_MODE_HDLC:
 		if ((bcs->hw.isar.rcvidx + ireg->clsb) > HSCX_BUFMAX) {
 			if (cs->debug & L1_DEB_WARN)
 				debugl1(cs, "isar_rcv_frame: incoming packet too large");
-			isar_write_reg(cs, 1, ISAR_IIA, 0);
+			cs->BC_Write_Reg(cs, 1, ISAR_IIA, 0);
 			bcs->hw.isar.rcvidx = 0;
 		} else if (ireg->cmsb & HDLC_ERROR) {
 			if (cs->debug & L1_DEB_WARN)
@@ -524,7 +532,7 @@ isar_rcv_frame(struct IsdnCardState *cs,
 				bcs->err_crc++;
 #endif
 			bcs->hw.isar.rcvidx = 0;
-			isar_write_reg(cs, 1, ISAR_IIA, 0);
+			cs->BC_Write_Reg(cs, 1, ISAR_IIA, 0);
 		} else {
 			if (ireg->cmsb & HDLC_FSD)
 				bcs->hw.isar.rcvidx = 0;
@@ -542,7 +550,7 @@ isar_rcv_frame(struct IsdnCardState *cs,
 					memcpy(skb_put(skb, bcs->hw.isar.rcvidx-2),
 						bcs->hw.isar.rcvbuf, bcs->hw.isar.rcvidx-2);
 					skb_queue_tail(&bcs->rqueue, skb);
-					sched_b_event(bcs, B_RCVBUFREADY);
+					schedule_event(bcs, B_RCVBUFREADY);
 				}
 				bcs->hw.isar.rcvidx = 0;
 			}
@@ -552,7 +560,7 @@ isar_rcv_frame(struct IsdnCardState *cs,
 		if (bcs->hw.isar.state != STFAX_ACTIV) {
 			if (cs->debug & L1_DEB_WARN)
 				debugl1(cs, "isar_rcv_frame: not ACTIV");
-			isar_write_reg(cs, 1, ISAR_IIA, 0);
+			cs->BC_Write_Reg(cs, 1, ISAR_IIA, 0);
 			bcs->hw.isar.rcvidx = 0;
 			break;
 		}
@@ -564,25 +572,23 @@ isar_rcv_frame(struct IsdnCardState *cs,
 				debugl1(cs, "isar_rcv_frame: raw(%d) dle(%d)",
 					ireg->clsb, bcs->hw.isar.rcvidx);
 			if ((skb = dev_alloc_skb(bcs->hw.isar.rcvidx))) {
-				insert_dle((u8 *)skb_put(skb, bcs->hw.isar.rcvidx),
+				insert_dle((u_char *)skb_put(skb, bcs->hw.isar.rcvidx),
 					bcs->hw.isar.rcvbuf, ireg->clsb);
 				skb_queue_tail(&bcs->rqueue, skb);
-				sched_b_event(bcs, B_RCVBUFREADY);
+				schedule_event(bcs, B_RCVBUFREADY);
 				if (ireg->cmsb & SART_NMD) { /* ABORT */
 					if (cs->debug & L1_DEB_WARN)
 						debugl1(cs, "isar_rcv_frame: no more data");
-					isar_write_reg(cs, 1, ISAR_IIA, 0);
 					bcs->hw.isar.rcvidx = 0;
 					send_DLE_ETX(bcs);
 					sendmsg(cs, SET_DPS(bcs->hw.isar.dpath) |
 						ISAR_HIS_PUMPCTRL, PCTRL_CMD_ESC,
 						0, NULL);
 					bcs->hw.isar.state = STFAX_ESCAPE;
-					sched_b_event(bcs, B_LL_NOCARRIER);
+					schedule_event(bcs, B_LL_NOCARRIER);
 				}
 			} else {
 				printk(KERN_WARNING "HiSax: skb out of memory\n");
-				isar_write_reg(cs, 1, ISAR_IIA, 0);
 			}
 			break;
 		}
@@ -590,7 +596,7 @@ isar_rcv_frame(struct IsdnCardState *cs,
 			if (cs->debug & L1_DEB_WARN)
 				debugl1(cs, "isar_rcv_frame: unknown fax mode %x",
 					bcs->hw.isar.cmd);
-			isar_write_reg(cs, 1, ISAR_IIA, 0);
+			cs->BC_Write_Reg(cs, 1, ISAR_IIA, 0);
 			bcs->hw.isar.rcvidx = 0;
 			break;
 		}
@@ -598,17 +604,18 @@ isar_rcv_frame(struct IsdnCardState *cs,
 		if ((bcs->hw.isar.rcvidx + ireg->clsb) > HSCX_BUFMAX) {
 			if (cs->debug & L1_DEB_WARN)
 				debugl1(cs, "isar_rcv_frame: incoming packet too large");
-			isar_write_reg(cs, 1, ISAR_IIA, 0);
+			cs->BC_Write_Reg(cs, 1, ISAR_IIA, 0);
 			bcs->hw.isar.rcvidx = 0;
 		} else if (ireg->cmsb & HDLC_ERROR) {
 			if (cs->debug & L1_DEB_WARN)
 				debugl1(cs, "isar frame error %x len %d",
 					ireg->cmsb, ireg->clsb);
 			bcs->hw.isar.rcvidx = 0;
-			isar_write_reg(cs, 1, ISAR_IIA, 0);
+			cs->BC_Write_Reg(cs, 1, ISAR_IIA, 0);
 		} else {
-			if (ireg->cmsb & HDLC_FSD)
+			if (ireg->cmsb & HDLC_FSD) {
 				bcs->hw.isar.rcvidx = 0;
+			}
 			ptr = bcs->hw.isar.rcvbuf + bcs->hw.isar.rcvidx;
 			bcs->hw.isar.rcvidx += ireg->clsb;
 			rcv_mbox(cs, ireg, ptr);
@@ -619,16 +626,19 @@ isar_rcv_frame(struct IsdnCardState *cs,
 					if (cs->debug & L1_DEB_WARN)
 						debugl1(cs, "isar frame to short %d",
 							bcs->hw.isar.rcvidx);
-				} else if (!(skb = dev_alloc_skb(bcs->hw.isar.rcvidx))) {
+					printk(KERN_WARNING "ISAR: frame to short %d\n",
+						bcs->hw.isar.rcvidx);
+				} else if (!(skb = dev_alloc_skb(len))) {
 					printk(KERN_WARNING "ISAR: receive out of memory\n");
 				} else {
-					insert_dle((u8 *)skb_put(skb, len),
+					insert_dle((u_char *)skb_put(skb, len),
 						bcs->hw.isar.rcvbuf,
 						bcs->hw.isar.rcvidx);
 					skb_queue_tail(&bcs->rqueue, skb);
-					sched_b_event(bcs, B_RCVBUFREADY);
+					schedule_event(bcs, B_RCVBUFREADY);
 					send_DLE_ETX(bcs);
-					sched_b_event(bcs, B_LL_OK);
+					schedule_event(bcs, B_LL_OK);
+					test_and_clear_bit(BC_FLG_FRH_WAIT, &bcs->Flag);
 				}
 				bcs->hw.isar.rcvidx = 0;
 			}
@@ -636,18 +646,19 @@ isar_rcv_frame(struct IsdnCardState *cs,
 		if (ireg->cmsb & SART_NMD) { /* ABORT */
 			if (cs->debug & L1_DEB_WARN)
 				debugl1(cs, "isar_rcv_frame: no more data");
-			isar_write_reg(cs, 1, ISAR_IIA, 0);
 			bcs->hw.isar.rcvidx = 0;
-			send_DLE_ETX(bcs);
 			sendmsg(cs, SET_DPS(bcs->hw.isar.dpath) |
 				ISAR_HIS_PUMPCTRL, PCTRL_CMD_ESC, 0, NULL);
 			bcs->hw.isar.state = STFAX_ESCAPE;
-			sched_b_event(bcs, B_LL_NOCARRIER);
+			if (test_and_clear_bit(BC_FLG_FRH_WAIT, &bcs->Flag)) {
+				send_DLE_ETX(bcs);
+				schedule_event(bcs, B_LL_NOCARRIER);
+			}
 		}
 		break;
 	default:
 		printk(KERN_ERR"isar_rcv_frame mode (%x)error\n", bcs->mode);
-		isar_write_reg(cs, 1, ISAR_IIA, 0);
+		cs->BC_Write_Reg(cs, 1, ISAR_IIA, 0);
 		break;
 	}
 }
@@ -657,8 +668,8 @@ isar_fill_fifo(struct BCState *bcs)
 {
 	struct IsdnCardState *cs = bcs->cs;
 	int count;
-	u8 msb;
-	u8 *ptr;
+	u_char msb;
+	u_char *ptr;
 
 	if ((cs->debug & L1_DEB_HSCX) && !(cs->debug & L1_DEB_HSCX_FIFO))
 		debugl1(cs, "isar_fill_fifo");
@@ -669,7 +680,7 @@ isar_fill_fifo(struct BCState *bcs)
 	if (!(bcs->hw.isar.reg->bstat & 
 		(bcs->hw.isar.dpath == 1 ? BSTAT_RDM1 : BSTAT_RDM2)))
 		return;
-	if (bcs->tx_skb->len > (u_int)bcs->hw.isar.mml) {
+	if (bcs->tx_skb->len > bcs->hw.isar.mml) {
 		msb = 0;
 		count = bcs->hw.isar.mml;
 	} else {
@@ -677,7 +688,7 @@ isar_fill_fifo(struct BCState *bcs)
 		msb = HDLC_FED;
 	}
 	ptr = bcs->tx_skb->data;
-	if (!bcs->count) {
+	if (!bcs->hw.isar.txcnt) {
 		msb |= HDLC_FST;
 		if ((bcs->mode == L1_MODE_FAX) &&
 			(bcs->hw.isar.cmd == PCTRL_CMD_FTH)) {
@@ -691,7 +702,7 @@ isar_fill_fifo(struct BCState *bcs)
 	}
 	skb_pull(bcs->tx_skb, count);
 	bcs->tx_cnt -= count;
-	bcs->count += count;
+	bcs->hw.isar.txcnt += count;
 	switch (bcs->mode) {
 		case L1_MODE_NULL:
 			printk(KERN_ERR"isar_fill_fifo wrong mode 0\n");
@@ -729,7 +740,7 @@ isar_fill_fifo(struct BCState *bcs)
 }
 
 inline
-struct BCState *sel_bcs_isar(struct IsdnCardState *cs, u8 dpath)
+struct BCState *sel_bcs_isar(struct IsdnCardState *cs, u_char dpath)
 {
 	if ((!dpath) || (dpath == 3))
 		return(NULL);
@@ -740,7 +751,7 @@ struct BCState *sel_bcs_isar(struct Isdn
 	return(NULL);
 }
 
-inline void
+void
 send_frames(struct BCState *bcs)
 {
 	if (bcs->tx_skb) {
@@ -748,7 +759,14 @@ send_frames(struct BCState *bcs)
 			isar_fill_fifo(bcs);
 			return;
 		} else {
-			xmit_complete_b(bcs);
+			if (test_bit(FLG_LLI_L1WAKEUP,&bcs->st->lli.flag) &&
+				(PACKET_NOACK != bcs->tx_skb->pkt_type)) {
+				u_long	flags;
+				spin_lock_irqsave(&bcs->aclock, flags);
+				bcs->ackcnt += bcs->hw.isar.txcnt;
+				spin_unlock_irqrestore(&bcs->aclock, flags);
+				schedule_event(bcs, B_ACKPENDING);
+			}
 			if (bcs->mode == L1_MODE_FAX) {
 				if (bcs->hw.isar.cmd == PCTRL_CMD_FTH) {
 					if (test_bit(BC_FLG_LASTDATA, &bcs->Flag)) {
@@ -761,33 +779,35 @@ send_frames(struct BCState *bcs)
 					}
 				}
 			}
-			bcs->count = 0; 
+			dev_kfree_skb_any(bcs->tx_skb);
+			bcs->hw.isar.txcnt = 0; 
+			bcs->tx_skb = NULL;
 		}
 	}
 	if ((bcs->tx_skb = skb_dequeue(&bcs->squeue))) {
-		bcs->count = 0;
+		bcs->hw.isar.txcnt = 0;
 		test_and_set_bit(BC_FLG_BUSY, &bcs->Flag);
 		isar_fill_fifo(bcs);
 	} else {
 		if (test_and_clear_bit(BC_FLG_DLEETX, &bcs->Flag)) {
 			if (test_and_clear_bit(BC_FLG_LASTDATA, &bcs->Flag)) {
 				if (test_and_clear_bit(BC_FLG_NMD_DATA, &bcs->Flag)) {
-					u8 dummy = 0;
+					u_char dummy = 0;
 					sendmsg(bcs->cs, SET_DPS(bcs->hw.isar.dpath) |
 						ISAR_HIS_SDATA, 0x01, 1, &dummy);
 				}
 				test_and_set_bit(BC_FLG_LL_OK, &bcs->Flag);
 			} else {
-				sched_b_event(bcs, B_LL_CONNECT);
+				schedule_event(bcs, B_LL_CONNECT);
 			}
 		}
 		test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
-		sched_b_event(bcs, B_XMTBUFREADY);
+		schedule_event(bcs, B_XMTBUFREADY);
 	}
 }
 
 inline void
-check_send(struct IsdnCardState *cs, u8 rdm)
+check_send(struct IsdnCardState *cs, u_char rdm)
 {
 	struct BCState *bcs;
 	
@@ -817,8 +837,8 @@ const char *dmrim[] = {"NO MOD", "NO DEF
 static void
 isar_pump_status_rsp(struct BCState *bcs, struct isar_reg *ireg) {
 	struct IsdnCardState *cs = bcs->cs;
-	u8 ril = ireg->par[0];
-	u8 rim;
+	u_char ril = ireg->par[0];
+	u_char rim;
 
 	if (!test_and_clear_bit(ISAR_RATE_REQ, &bcs->hw.isar.reg->Flags))
 		return; 
@@ -869,9 +889,9 @@ isar_pump_status_rsp(struct BCState *bcs
 }
 
 static void
-isar_pump_statev_modem(struct BCState *bcs, u8 devt) {
+isar_pump_statev_modem(struct BCState *bcs, u_char devt) {
 	struct IsdnCardState *cs = bcs->cs;
-	u8 dps = SET_DPS(bcs->hw.isar.dpath);
+	u_char dps = SET_DPS(bcs->hw.isar.dpath);
 
 	switch(devt) {
 		case PSEV_10MS_TIMER:
@@ -938,8 +958,8 @@ isar_pump_statev_modem(struct BCState *b
 	}
 }
 
-static inline void
-ll_deliver_faxstat(struct BCState *bcs, u8 status)
+static void
+ll_deliver_faxstat(struct BCState *bcs, u_char status)
 {
         isdn_ctrl ic;
 	struct Channel *chanp = (struct Channel *) bcs->st->lli.userdata;
@@ -954,10 +974,10 @@ ll_deliver_faxstat(struct BCState *bcs, 
 }
 
 static void
-isar_pump_statev_fax(struct BCState *bcs, u8 devt) {
+isar_pump_statev_fax(struct BCState *bcs, u_char devt) {
 	struct IsdnCardState *cs = bcs->cs;
-	u8 dps = SET_DPS(bcs->hw.isar.dpath);
-	u8 p1;
+	u_char dps = SET_DPS(bcs->hw.isar.dpath);
+	u_char p1;
 
 	switch(devt) {
 		case PSEV_10MS_TIMER:
@@ -1041,7 +1061,7 @@ isar_pump_statev_fax(struct BCState *bcs
 						&bcs->Flag);
 					add_timer(&bcs->hw.isar.ftimer);
 				} else {
-					sched_b_event(bcs, B_LL_CONNECT);
+					schedule_event(bcs, B_LL_CONNECT);
 				}
 			} else {
 				if (cs->debug & L1_DEB_WARN)
@@ -1057,19 +1077,22 @@ isar_pump_statev_fax(struct BCState *bcs
 			if (cs->debug & L1_DEB_HSCX)
 				debugl1(cs, "pump stev RSP_DISC");
 			if (bcs->hw.isar.state == STFAX_ESCAPE) {
+				p1 = 5;
 				switch(bcs->hw.isar.newcmd) {
 					case 0:
 						bcs->hw.isar.state = STFAX_READY;
 						break;
-					case PCTRL_CMD_FTH:
 					case PCTRL_CMD_FTM:
-						p1 = 10;
+						p1 = 2;
+					case PCTRL_CMD_FTH:
 						sendmsg(cs, dps | ISAR_HIS_PUMPCTRL,
 							PCTRL_CMD_SILON, 1, &p1);
 						bcs->hw.isar.state = STFAX_SILDET;
 						break;
-					case PCTRL_CMD_FRH:
 					case PCTRL_CMD_FRM:
+						if (frm_extra_delay)
+							mdelay(frm_extra_delay);
+					case PCTRL_CMD_FRH:
 						p1 = bcs->hw.isar.mod = bcs->hw.isar.newmod;
 						bcs->hw.isar.newmod = 0;
 						bcs->hw.isar.cmd = bcs->hw.isar.newcmd;
@@ -1086,10 +1109,10 @@ isar_pump_statev_fax(struct BCState *bcs
 				}
 			} else if (bcs->hw.isar.state == STFAX_ACTIV) {
 				if (test_and_clear_bit(BC_FLG_LL_OK, &bcs->Flag)) {
-					sched_b_event(bcs, B_LL_OK);
+					schedule_event(bcs, B_LL_OK);
 				} else if (bcs->hw.isar.cmd == PCTRL_CMD_FRM) {
 					send_DLE_ETX(bcs);
-					sched_b_event(bcs, B_LL_NOCARRIER);
+					schedule_event(bcs, B_LL_NOCARRIER);
 				} else {
 					ll_deliver_faxstat(bcs, ISDN_FAX_CLASS1_FCERROR);
 				}
@@ -1156,11 +1179,11 @@ isar_int_main(struct IsdnCardState *cs)
 			} else {
 				debugl1(cs, "isar spurious IIS_RDATA %x/%x/%x",
 					ireg->iis, ireg->cmsb, ireg->clsb);
-				isar_write_reg(cs, 1, ISAR_IIA, 0);
+				cs->BC_Write_Reg(cs, 1, ISAR_IIA, 0);
 			}
 			break;
 		case ISAR_IIS_GSTEV:
-			isar_write_reg(cs, 1, ISAR_IIA, 0);
+			cs->BC_Write_Reg(cs, 1, ISAR_IIA, 0);
 			ireg->bstat |= ireg->cmsb;
 			check_send(cs, ireg->cmsb);
 			break;
@@ -1176,15 +1199,18 @@ isar_int_main(struct IsdnCardState *cs)
 			if (cs->debug & L1_DEB_WARN)
 				debugl1(cs, "Buffer STEV dpath%d msb(%x)",
 					ireg->iis>>6, ireg->cmsb);
-			isar_write_reg(cs, 1, ISAR_IIA, 0);
+			cs->BC_Write_Reg(cs, 1, ISAR_IIA, 0);
 			break;
 		case ISAR_IIS_PSTEV:
 			if ((bcs = sel_bcs_isar(cs, ireg->iis >> 6))) {
-				rcv_mbox(cs, ireg, (u8 *)ireg->par);
+				rcv_mbox(cs, ireg, (u_char *)ireg->par);
 				if (bcs->mode == L1_MODE_V32) {
 					isar_pump_statev_modem(bcs, ireg->cmsb);
 				} else if (bcs->mode == L1_MODE_FAX) {
 					isar_pump_statev_fax(bcs, ireg->cmsb);
+				} else if (ireg->cmsb == PSEV_10MS_TIMER) {
+					if (cs->debug & L1_DEB_HSCX)
+						debugl1(cs, "pump stev TIMER");
 				} else {
 					if (cs->debug & L1_DEB_WARN)
 						debugl1(cs, "isar IIS_PSTEV pmode %d stat %x",
@@ -1193,30 +1219,30 @@ isar_int_main(struct IsdnCardState *cs)
 			} else {
 				debugl1(cs, "isar spurious IIS_PSTEV %x/%x/%x",
 					ireg->iis, ireg->cmsb, ireg->clsb);
-				isar_write_reg(cs, 1, ISAR_IIA, 0);
+				cs->BC_Write_Reg(cs, 1, ISAR_IIA, 0);
 			}
 			break;
 		case ISAR_IIS_PSTRSP:
 			if ((bcs = sel_bcs_isar(cs, ireg->iis >> 6))) {
-				rcv_mbox(cs, ireg, (u8 *)ireg->par);
+				rcv_mbox(cs, ireg, (u_char *)ireg->par);
 				isar_pump_status_rsp(bcs, ireg);
 			} else {
 				debugl1(cs, "isar spurious IIS_PSTRSP %x/%x/%x",
 					ireg->iis, ireg->cmsb, ireg->clsb);
-				isar_write_reg(cs, 1, ISAR_IIA, 0);
+				cs->BC_Write_Reg(cs, 1, ISAR_IIA, 0);
 			}
 			break;
 		case ISAR_IIS_DIAG:
 		case ISAR_IIS_BSTRSP:
 		case ISAR_IIS_IOM2RSP:
-			rcv_mbox(cs, ireg, (u8 *)ireg->par);
+			rcv_mbox(cs, ireg, (u_char *)ireg->par);
 			if ((cs->debug & (L1_DEB_HSCX | L1_DEB_HSCX_FIFO))
 				== L1_DEB_HSCX) {
-				u8 *tp=debbuf;
+				u_char *tp=debbuf;
 
 				tp += sprintf(debbuf, "msg iis(%x) msb(%x)",
 					ireg->iis, ireg->cmsb);
-				QuickHex(tp, (u8 *)ireg->par, ireg->clsb);
+				QuickHex(tp, (u_char *)ireg->par, ireg->clsb);
 				debugl1(cs, debbuf);
 			}
 			break;
@@ -1242,15 +1268,18 @@ ftimer_handler(struct BCState *bcs) {
 			bcs->Flag);
 	test_and_clear_bit(BC_FLG_FTI_RUN, &bcs->Flag);
 	if (test_and_clear_bit(BC_FLG_LL_CONN, &bcs->Flag)) {
-		sched_b_event(bcs, B_LL_CONNECT);
+		schedule_event(bcs, B_LL_CONNECT);
+	}
+	if (test_and_clear_bit(BC_FLG_FTI_FTS, &bcs->Flag)) {
+		schedule_event(bcs, B_LL_OK);
 	}
 }
 
 static void
 setup_pump(struct BCState *bcs) {
 	struct IsdnCardState *cs = bcs->cs;
-	u8 dps = SET_DPS(bcs->hw.isar.dpath);
-	u8 ctrl, param[6];
+	u_char dps = SET_DPS(bcs->hw.isar.dpath);
+	u_char ctrl, param[6];
 
 	switch (bcs->mode) {
 		case L1_MODE_NULL:
@@ -1266,7 +1295,7 @@ setup_pump(struct BCState *bcs) {
 			} else {
 				param[5] = PV32P6_ATN;
 			}
-			param[0] = 6; /* 6 db */
+			param[0] = para_TOA; /* 6 db */
 			param[1] = PV32P2_V23R | PV32P2_V22A | PV32P2_V22B |
 				   PV32P2_V22C | PV32P2_V21 | PV32P2_BEL; 
 			param[2] = PV32P3_AMOD | PV32P3_V32B | PV32P3_V23B;
@@ -1282,7 +1311,7 @@ setup_pump(struct BCState *bcs) {
 			} else {
 				param[1] = PFAXP2_ATN;
 			}
-			param[0] = 6; /* 6 db */
+			param[0] = para_TOA; /* 6 db */
 			sendmsg(cs, dps | ISAR_HIS_PUMPCFG, ctrl, 2, param);
 			bcs->hw.isar.state = STFAX_NULL;
 			bcs->hw.isar.newcmd = 0;
@@ -1298,8 +1327,8 @@ setup_pump(struct BCState *bcs) {
 static void
 setup_sart(struct BCState *bcs) {
 	struct IsdnCardState *cs = bcs->cs;
-	u8 dps = SET_DPS(bcs->hw.isar.dpath);
-	u8 ctrl, param[2];
+	u_char dps = SET_DPS(bcs->hw.isar.dpath);
+	u_char ctrl, param[2];
 	
 	switch (bcs->mode) {
 		case L1_MODE_NULL:
@@ -1311,7 +1340,6 @@ setup_sart(struct BCState *bcs) {
 				"\0\0");
 			break;
 		case L1_MODE_HDLC:
-		case L1_MODE_FAX:
 			param[0] = 0;
 			sendmsg(cs, dps | ISAR_HIS_SARTCFG, SMODE_HDLC, 1,
 				param);
@@ -1323,6 +1351,9 @@ setup_sart(struct BCState *bcs) {
 			sendmsg(cs, dps | ISAR_HIS_SARTCFG, ctrl, 2,
 				param);
 			break;
+		case L1_MODE_FAX:
+			/* SART must not configured with FAX */
+			break;
 	}
 	udelay(1000);
 	sendmsg(cs, dps | ISAR_HIS_BSTREQ, 0, 0, NULL);
@@ -1332,8 +1363,8 @@ setup_sart(struct BCState *bcs) {
 static void
 setup_iom2(struct BCState *bcs) {
 	struct IsdnCardState *cs = bcs->cs;
-	u8 dps = SET_DPS(bcs->hw.isar.dpath);
-	u8 cmsb = IOM_CTRL_ENA, msg[5] = {IOM_P1_TXD,0,0,0,0};
+	u_char dps = SET_DPS(bcs->hw.isar.dpath);
+	u_char cmsb = IOM_CTRL_ENA, msg[5] = {IOM_P1_TXD,0,0,0,0};
 	
 	if (bcs->channel)
 		msg[1] = msg[3] = 1;
@@ -1418,14 +1449,15 @@ modeisar(struct BCState *bcs, int mode, 
 }
 
 static void
-isar_pump_cmd(struct BCState *bcs, u8 cmd, u8 para) 
+isar_pump_cmd(struct BCState *bcs, u_char cmd, u_char para) 
 {
 	struct IsdnCardState *cs = bcs->cs;
-	u8 dps = SET_DPS(bcs->hw.isar.dpath);
-	u8 ctrl = 0, nom = 0, p1 = 0;
+	u_char dps = SET_DPS(bcs->hw.isar.dpath);
+	u_char ctrl = 0, nom = 0, p1 = 0;
 
 	switch(cmd) {
 		case ISDN_FAX_CLASS1_FTM:
+			test_and_clear_bit(BC_FLG_FRH_WAIT, &bcs->Flag);
 			if (bcs->hw.isar.state == STFAX_READY) {
 				p1 = para;
 				ctrl = PCTRL_CMD_FTM;
@@ -1449,6 +1481,7 @@ isar_pump_cmd(struct BCState *bcs, u8 cm
 			}
 			break;
 		case ISDN_FAX_CLASS1_FTH:
+			test_and_clear_bit(BC_FLG_FRH_WAIT, &bcs->Flag);
 			if (bcs->hw.isar.state == STFAX_READY) {
 				p1 = para;
 				ctrl = PCTRL_CMD_FTH;
@@ -1472,6 +1505,7 @@ isar_pump_cmd(struct BCState *bcs, u8 cm
 			}
 			break;
 		case ISDN_FAX_CLASS1_FRM:
+			test_and_clear_bit(BC_FLG_FRH_WAIT, &bcs->Flag);
 			if (bcs->hw.isar.state == STFAX_READY) {
 				p1 = para;
 				ctrl = PCTRL_CMD_FRM;
@@ -1495,6 +1529,7 @@ isar_pump_cmd(struct BCState *bcs, u8 cm
 			}
 			break;
 		case ISDN_FAX_CLASS1_FRH:
+			test_and_set_bit(BC_FLG_FRH_WAIT, &bcs->Flag);
 			if (bcs->hw.isar.state == STFAX_READY) {
 				p1 = para;
 				ctrl = PCTRL_CMD_FRH;
@@ -1517,15 +1552,20 @@ isar_pump_cmd(struct BCState *bcs, u8 cm
 				bcs->hw.isar.state = STFAX_ESCAPE; 
 			}
 			break;
+		case ISDN_FAXPUMP_HALT:
+			bcs->hw.isar.state = STFAX_NULL;
+			nom = 0;
+			ctrl = PCTRL_CMD_HALT;
+			break;
 	}
 	if (ctrl)
 		sendmsg(cs, dps | ISAR_HIS_PUMPCTRL, ctrl, nom, &p1);
 }
 
 void
-__isar_setup(struct IsdnCardState *cs)
+isar_setup(struct IsdnCardState *cs)
 {
-	u8 msg;
+	u_char msg;
 	int i;
 	
 	/* Dpath 1, 2 */
@@ -1538,57 +1578,105 @@ __isar_setup(struct IsdnCardState *cs)
 		cs->bcs[i].mode = 0;
 		cs->bcs[i].hw.isar.dpath = i + 1;
 		modeisar(&cs->bcs[i], 0, 0);
-		INIT_WORK(&cs->bcs[i].work, isar_bh, &cs->bcs[i]);
+		INIT_WORK(&cs->bcs[i].tqueue, (void *)(void *) isar_bh, &cs->bcs[i]);
 	}
 }
 
 void
 isar_l2l1(struct PStack *st, int pr, void *arg)
 {
+	struct BCState *bcs = st->l1.bcs;
 	struct sk_buff *skb = arg;
+	int ret;
+	u_long flags;
 
 	switch (pr) {
 		case (PH_DATA | REQUEST):
-			xmit_data_req_b(st->l1.bcs, skb);
+			spin_lock_irqsave(&bcs->cs->lock, flags);
+			if (bcs->tx_skb) {
+				skb_queue_tail(&bcs->squeue, skb);
+			} else {
+				bcs->tx_skb = skb;
+				test_and_set_bit(BC_FLG_BUSY, &bcs->Flag);
+				if (bcs->cs->debug & L1_DEB_HSCX)
+					debugl1(bcs->cs, "DRQ set BC_FLG_BUSY");
+				bcs->hw.isar.txcnt = 0;
+				bcs->cs->BC_Send_Data(bcs);
+			}
+			spin_unlock_irqrestore(&bcs->cs->lock, flags);
 			break;
 		case (PH_PULL | INDICATION):
-			xmit_pull_ind_b(st->l1.bcs, skb);
+			spin_lock_irqsave(&bcs->cs->lock, flags);
+			if (bcs->tx_skb) {
+				printk(KERN_WARNING "isar_l2l1: this shouldn't happen\n");
+			} else {
+				test_and_set_bit(BC_FLG_BUSY, &bcs->Flag);
+				if (bcs->cs->debug & L1_DEB_HSCX)
+					debugl1(bcs->cs, "PUI set BC_FLG_BUSY");
+				bcs->tx_skb = skb;
+				bcs->hw.isar.txcnt = 0;
+				bcs->cs->BC_Send_Data(bcs);
+			}
+			spin_unlock_irqrestore(&bcs->cs->lock, flags);
 			break;
 		case (PH_PULL | REQUEST):
-			xmit_pull_req_b(st);
+			if (!bcs->tx_skb) {
+				test_and_clear_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
+				st->l1.l1l2(st, PH_PULL | CONFIRM, NULL);
+			} else
+				test_and_set_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
 			break;
 		case (PH_ACTIVATE | REQUEST):
-			test_and_set_bit(BC_FLG_ACTIV, &st->l1.bcs->Flag);
-			st->l1.bcs->hw.isar.conmsg[0] = 0;
+			spin_lock_irqsave(&bcs->cs->lock, flags);
+			test_and_set_bit(BC_FLG_ACTIV, &bcs->Flag);
+			bcs->hw.isar.conmsg[0] = 0;
 			if (test_bit(FLG_ORIG, &st->l2.flag))
-				test_and_set_bit(BC_FLG_ORIG, &st->l1.bcs->Flag);
+				test_and_set_bit(BC_FLG_ORIG, &bcs->Flag);
 			else
-				test_and_clear_bit(BC_FLG_ORIG, &st->l1.bcs->Flag);
+				test_and_clear_bit(BC_FLG_ORIG, &bcs->Flag);
 			switch(st->l1.mode) {
 				case L1_MODE_TRANS:
 				case L1_MODE_HDLC:
-					if (modeisar(st->l1.bcs, st->l1.mode, st->l1.bc))
+					ret = modeisar(bcs, st->l1.mode, st->l1.bc);
+					spin_unlock_irqrestore(&bcs->cs->lock, flags);
+					if (ret)
 						l1_msg_b(st, PH_DEACTIVATE | REQUEST, arg);
 					else
 						l1_msg_b(st, PH_ACTIVATE | REQUEST, arg);
 					break;
 				case L1_MODE_V32:
 				case L1_MODE_FAX:
-					if (modeisar(st->l1.bcs, st->l1.mode, st->l1.bc))
+					ret = modeisar(bcs, st->l1.mode, st->l1.bc);
+					spin_unlock_irqrestore(&bcs->cs->lock, flags);
+					if (ret)
 						l1_msg_b(st, PH_DEACTIVATE | REQUEST, arg);
 					break;
+				default:
+					spin_unlock_irqrestore(&bcs->cs->lock, flags);
+					break;
 			}
 			break;
 		case (PH_DEACTIVATE | REQUEST):
 			l1_msg_b(st, pr, arg);
 			break;
 		case (PH_DEACTIVATE | CONFIRM):
-			test_and_clear_bit(BC_FLG_ACTIV, &st->l1.bcs->Flag);
-			test_and_clear_bit(BC_FLG_BUSY, &st->l1.bcs->Flag);
-			if (st->l1.bcs->cs->debug & L1_DEB_HSCX)
-				debugl1(st->l1.bcs->cs, "PDAC clear BC_FLG_BUSY");
-			modeisar(st->l1.bcs, 0, st->l1.bc);
-			L1L2(st, PH_DEACTIVATE | CONFIRM, NULL);
+			spin_lock_irqsave(&bcs->cs->lock, flags);
+			switch(st->l1.mode) {
+				case L1_MODE_TRANS:
+				case L1_MODE_HDLC:
+				case L1_MODE_V32:
+					break;
+				case L1_MODE_FAX:
+					isar_pump_cmd(bcs, ISDN_FAXPUMP_HALT, 0);
+					break;
+			}
+			test_and_clear_bit(BC_FLG_ACTIV, &bcs->Flag);
+			test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
+			if (bcs->cs->debug & L1_DEB_HSCX)
+				debugl1(bcs->cs, "PDAC clear BC_FLG_BUSY");
+			modeisar(bcs, 0, st->l1.bc);
+			spin_unlock_irqrestore(&bcs->cs->lock, flags);
+			st->l1.l1l2(st, PH_DEACTIVATE | CONFIRM, NULL);
 			break;
 	}
 }
@@ -1634,9 +1722,6 @@ open_isarstate(struct IsdnCardState *cs,
 	bcs->event = 0;
 	bcs->hw.isar.rcvidx = 0;
 	bcs->tx_cnt = 0;
-	bcs->hw.isar.ftimer.function = (void *) ftimer_handler;
-	bcs->hw.isar.ftimer.data = (long) bcs;
-	init_timer(&bcs->hw.isar.ftimer);
 	return (0);
 }
 
@@ -1647,7 +1732,7 @@ setstack_isar(struct PStack *st, struct 
 	if (open_isarstate(st->l1.hardware, bcs))
 		return (-1);
 	st->l1.bcs = bcs;
-	st->l1.l2l1 = isar_l2l1;
+	st->l2.l2l1 = isar_l2l1;
 	setstack_manager(st);
 	bcs->st = st;
 	setstack_l1_B(st);
@@ -1674,6 +1759,51 @@ isar_auxcmd(struct IsdnCardState *cs, is
 						test_and_set_bit(BC_FLG_DLEETX,
 							&bcs->Flag);
 					break;
+				case ISDN_FAX_CLASS1_FTS:
+					if (ic->parm.aux.subcmd == AT_QUERY) {
+						ic->command = ISDN_STAT_FAXIND;
+						ic->parm.aux.cmd = ISDN_FAX_CLASS1_OK;
+						cs->iif.statcallb(ic);
+						return(0);
+					} else if (ic->parm.aux.subcmd == AT_EQ_QUERY) {
+						strcpy(ic->parm.aux.para, "0-255");
+						ic->command = ISDN_STAT_FAXIND;
+						ic->parm.aux.cmd = ISDN_FAX_CLASS1_QUERY;
+						cs->iif.statcallb(ic);
+						return(0);
+					} else if (ic->parm.aux.subcmd == AT_EQ_VALUE) {
+						if (cs->debug & L1_DEB_HSCX)
+							debugl1(cs, "isar_auxcmd %s=%d",
+								FC1_CMD[ic->parm.aux.cmd], ic->parm.aux.para[0]);
+						if (bcs->hw.isar.state == STFAX_READY) {
+							if (! ic->parm.aux.para[0]) {
+								ic->command = ISDN_STAT_FAXIND;
+								ic->parm.aux.cmd = ISDN_FAX_CLASS1_OK;
+								cs->iif.statcallb(ic);
+								return(0);
+							}
+							if (! test_and_set_bit(BC_FLG_FTI_RUN, &bcs->Flag)) {
+								/* n*10 ms */
+								bcs->hw.isar.ftimer.expires =
+									jiffies + ((ic->parm.aux.para[0] * 10 * HZ)/1000);
+								test_and_set_bit(BC_FLG_FTI_FTS, &bcs->Flag);
+								add_timer(&bcs->hw.isar.ftimer);
+								return(0);
+							} else {
+								if (cs->debug)
+									debugl1(cs, "isar FTS=%d and FTI busy",
+										ic->parm.aux.para[0]);
+							}
+						} else {
+							if (cs->debug)
+								debugl1(cs, "isar FTS=%d and isar.state not ready(%x)",
+									ic->parm.aux.para[0],bcs->hw.isar.state);
+						}
+						ic->command = ISDN_STAT_FAXIND;
+						ic->parm.aux.cmd = ISDN_FAX_CLASS1_ERROR;
+						cs->iif.statcallb(ic);
+					}
+					break;
 				case ISDN_FAX_CLASS1_FRM:
 				case ISDN_FAX_CLASS1_FRH:
 				case ISDN_FAX_CLASS1_FTM:
@@ -1686,16 +1816,24 @@ isar_auxcmd(struct IsdnCardState *cs, is
 						cs->iif.statcallb(ic);
 						return(0);
 					} else if (ic->parm.aux.subcmd == AT_EQ_QUERY) {
-						strcpy(ic->parm.aux.para, faxmodulation_s);
+						char *p = ic->parm.aux.para;
+						for(i=0;i<FAXMODCNT;i++)
+							if ((1<<i) & modmask)
+								p += sprintf(p, "%d,", faxmodulation[i]);
+						p--;
+						*p=0;
 						ic->command = ISDN_STAT_FAXIND;
 						ic->parm.aux.cmd = ISDN_FAX_CLASS1_QUERY;
 						cs->iif.statcallb(ic);
 						return(0);
 					} else if (ic->parm.aux.subcmd == AT_EQ_VALUE) {
+						if (cs->debug & L1_DEB_HSCX)
+							debugl1(cs, "isar_auxcmd %s=%d",
+								FC1_CMD[ic->parm.aux.cmd], ic->parm.aux.para[0]);
 						for(i=0;i<FAXMODCNT;i++)
 							if (faxmodulation[i]==ic->parm.aux.para[0])
 								break;
-						if ((FAXMODCNT > i) && 
+						if ((i < FAXMODCNT) && ((1<<i) & modmask) && 
 							test_bit(BC_FLG_INIT, &bcs->Flag)) {
 							isar_pump_cmd(bcs,
 								ic->parm.aux.cmd,
@@ -1713,16 +1851,36 @@ isar_auxcmd(struct IsdnCardState *cs, is
 			break;
 		case (ISDN_CMD_IOCTL):
 			switch (ic->arg) {
-				case (9): /* load firmware */
+				case 9: /* load firmware */
 					features = ISDN_FEATURE_L2_MODEM |
 						ISDN_FEATURE_L2_FAX |
 						ISDN_FEATURE_L3_FCLASS1;
 					memcpy(&adr, ic->parm.num, sizeof(ulong));
-					if (isar_load_firmware(cs, (u8 *)adr))
+					if (isar_load_firmware(cs, (u_char *)adr))
 						return(1);
 					else 
 						ll_run(cs, features);
 					break;
+				case 20:
+					features = *(unsigned int *) ic->parm.num;
+					printk(KERN_DEBUG "HiSax: max modulation old(%04x) new(%04x)\n",
+						modmask, features);
+					modmask = features;
+					break;
+				case 21:
+					features = *(unsigned int *) ic->parm.num;
+					printk(KERN_DEBUG "HiSax: FRM extra delay old(%d) new(%d) ms\n",
+						frm_extra_delay, features);
+					if (features >= 0)
+						frm_extra_delay = features;
+					break;
+				case 22:
+					features = *(unsigned int *) ic->parm.num;
+					printk(KERN_DEBUG "HiSax: TOA old(%d) new(%d) db\n",
+						para_TOA, features);
+					if (features >= 0 && features < 32)
+						para_TOA = features;
+					break;
 				default:
 					printk(KERN_DEBUG "HiSax: invalid ioctl %d\n",
 					       (int) ic->arg);
@@ -1735,21 +1893,17 @@ isar_auxcmd(struct IsdnCardState *cs, is
 	return(0);
 }
 
-static struct bc_l1_ops isar_l1_ops = {
-	.fill_fifo = isar_fill_fifo,
-	.open      = setstack_isar,
-	.close     = close_isarstate,
-};
-
 void __devinit
 initisar(struct IsdnCardState *cs)
 {
-	cs->bc_l1_ops = &isar_l1_ops;
-}
-
-int
-isar_setup(struct IsdnCardState *cs, struct bc_hw_ops *isar_ops)
-{
-	cs->bc_hw_ops = isar_ops;
-	return ISARVersion(cs, "HiSax:");
+	cs->bcs[0].BC_SetStack = setstack_isar;
+	cs->bcs[1].BC_SetStack = setstack_isar;
+	cs->bcs[0].BC_Close = close_isarstate;
+	cs->bcs[1].BC_Close = close_isarstate;
+	cs->bcs[0].hw.isar.ftimer.function = (void *) ftimer_handler;
+	cs->bcs[0].hw.isar.ftimer.data = (long) &cs->bcs[0];
+	init_timer(&cs->bcs[0].hw.isar.ftimer);
+	cs->bcs[1].hw.isar.ftimer.function = (void *) ftimer_handler;
+	cs->bcs[1].hw.isar.ftimer.data = (long) &cs->bcs[1];
+	init_timer(&cs->bcs[1].hw.isar.ftimer);
 }
--- diff/drivers/isdn/hisax/isar.h	2003-01-16 11:30:36.000000000 +0000
+++ source/drivers/isdn/hisax/isar.h	2004-02-23 13:56:42.000000000 +0000
@@ -1,4 +1,4 @@
-/* $Id: isar.h,v 1.9.6.2 2001/09/23 22:24:49 kai Exp $
+/* $Id: isar.h,v 1.11.2.2 2004/01/12 22:52:27 keil Exp $
  *
  * ISAR (Siemens PSB 7110) specific defines
  *
@@ -28,6 +28,8 @@
 #define ISAR_HIS_FIRM		0x1e
 #define ISAR_HIS_STDSP		0x08
 #define ISAR_HIS_DIAG		0x05
+#define ISAR_HIS_WAITSTATE	0x27
+#define ISAR_HIS_TIMERIRQ	0x25
 #define ISAR_HIS_P0CFG		0x3c
 #define ISAR_HIS_P12CFG		0x24
 #define ISAR_HIS_SARTCFG	0x25	
@@ -43,6 +45,10 @@
 #define ISAR_HIS_DPS2		0x80
 #define SET_DPS(x)		((x<<6) & 0xc0)
 
+#define ISAR_CMD_TIMERIRQ_OFF	0x20
+#define ISAR_CMD_TIMERIRQ_ON	0x21
+
+
 #define ISAR_IIS_MSCMSD		0x3f
 #define ISAR_IIS_VNR		0x15
 #define ISAR_IIS_DKEY		0x03
@@ -207,8 +213,10 @@
 #define STFAX_ESCAPE	5
 #define STFAX_SILDET	6
 
+#define ISDN_FAXPUMP_HALT	100
+
+extern int ISARVersion(struct IsdnCardState *cs, char *s);
 extern void isar_int_main(struct IsdnCardState *cs);
 extern void initisar(struct IsdnCardState *cs);
 extern void isar_fill_fifo(struct BCState *bcs);
 extern int isar_auxcmd(struct IsdnCardState *cs, isdn_ctrl *ic);
-extern int isar_setup(struct IsdnCardState *cs, struct bc_hw_ops *isar_ops);
--- diff/drivers/isdn/hisax/isdnl1.c	2003-05-21 11:49:50.000000000 +0100
+++ source/drivers/isdn/hisax/isdnl1.c	2004-02-23 13:56:42.000000000 +0000
@@ -1,4 +1,4 @@
-/* $Id: isdnl1.c,v 2.41.6.5 2001/09/23 22:24:49 kai Exp $
+/* $Id: isdnl1.c,v 2.46.2.5 2004/02/11 13:21:34 keil Exp $
  *
  * common low level stuff for Siemens Chipsetbased isdn cards
  *
@@ -18,7 +18,7 @@
  *
  */
 
-const char *l1_revision = "$Revision: 2.41.6.5 $";
+const char *l1_revision = "$Revision: 2.46.2.5 $";
 
 #include <linux/init.h>
 #include "hisax.h"
@@ -126,7 +126,7 @@ static char *strL1Event[] =
 };
 
 void
-debugl1(struct IsdnCardState *cs, const char *fmt, ...)
+debugl1(struct IsdnCardState *cs, char *fmt, ...)
 {
 	va_list args;
 	char tmp[8];
@@ -159,9 +159,9 @@ L1activated(struct IsdnCardState *cs)
 	st = cs->stlist;
 	while (st) {
 		if (test_and_clear_bit(FLG_L1_ACTIVATING, &st->l1.Flags))
-			L1L2(st, PH_ACTIVATE | CONFIRM, NULL);
+			st->l1.l1l2(st, PH_ACTIVATE | CONFIRM, NULL);
 		else
-			L1L2(st, PH_ACTIVATE | INDICATION, NULL);
+			st->l1.l1l2(st, PH_ACTIVATE | INDICATION, NULL);
 		st = st->next;
 	}
 }
@@ -174,8 +174,8 @@ L1deactivated(struct IsdnCardState *cs)
 	st = cs->stlist;
 	while (st) {
 		if (test_bit(FLG_L1_DBUSY, &cs->HW_Flags))
-			L1L2(st, PH_PAUSE | CONFIRM, NULL);
-		L1L2(st, PH_DEACTIVATE | INDICATION, NULL);
+			st->l1.l1l2(st, PH_PAUSE | CONFIRM, NULL);
+		st->l1.l1l2(st, PH_DEACTIVATE | INDICATION, NULL);
 		st = st->next;
 	}
 	test_and_clear_bit(FLG_L1_DBUSY, &cs->HW_Flags);
@@ -190,12 +190,13 @@ DChannel_proc_xmt(struct IsdnCardState *
 		return;
 
 	stptr = cs->stlist;
-	while (stptr != NULL)
+	while (stptr != NULL) {
 		if (test_and_clear_bit(FLG_L1_PULL_REQ, &stptr->l1.Flags)) {
-			L1L2(stptr, PH_PULL | CONFIRM, NULL);
+			stptr->l1.l1l2(stptr, PH_PULL | CONFIRM, NULL);
 			break;
 		} else
 			stptr = stptr->next;
+	}
 }
 
 void
@@ -234,7 +235,7 @@ DChannel_proc_rcv(struct IsdnCardState *
 			if (sapi == CTRL_SAPI) { /* sapi 0 */
 				while (stptr != NULL) {
 					if ((nskb = skb_clone(skb, GFP_ATOMIC)))
-						L1L2(stptr, PH_DATA | INDICATION, nskb);
+						stptr->l1.l1l2(stptr, PH_DATA | INDICATION, nskb);
 					else
 						printk(KERN_WARNING "HiSax: isdn broadcast buffer shortage\n");
 					stptr = stptr->next;
@@ -253,7 +254,7 @@ DChannel_proc_rcv(struct IsdnCardState *
 			found = 0;
 			while (stptr != NULL)
 				if (tei == stptr->l2.tei) {
-					L1L2(stptr, PH_DATA | INDICATION, skb);
+					stptr->l1.l1l2(stptr, PH_DATA | INDICATION, skb);
 					found = !0;
 					break;
 				} else
@@ -276,10 +277,10 @@ BChannel_proc_xmt(struct BCState *bcs)
 	}
 
 	if (test_and_clear_bit(FLG_L1_PULL_REQ, &st->l1.Flags))
-		L1L2(st, PH_PULL | CONFIRM, NULL);
+		st->l1.l1l2(st, PH_PULL | CONFIRM, NULL);
 	if (!test_bit(BC_FLG_ACTIV, &bcs->Flag)) {
 		if (!test_bit(BC_FLG_BUSY, &bcs->Flag) && (!skb_queue_len(&bcs->squeue))) {
-			L2L1(st, PH_DEACTIVATE | CONFIRM, NULL);
+			st->l2.l2l1(st, PH_DEACTIVATE | CONFIRM, NULL);
 		}
 	}
 }
@@ -294,31 +295,35 @@ BChannel_proc_rcv(struct BCState *bcs)
 		FsmEvent(&bcs->st->l1.l1m, EV_TIMER_ACT, NULL);
 	}
 	while ((skb = skb_dequeue(&bcs->rqueue))) {
-		L1L2(bcs->st, PH_DATA | INDICATION, skb);
+		bcs->st->l1.l1l2(bcs->st, PH_DATA | INDICATION, skb);
 	}
 }
 
 static void
-BChannel_proc_cmpl(struct BCState *bcs)
+BChannel_proc_ack(struct BCState *bcs)
 {
-	struct sk_buff *skb;
+	u_long	flags;
+	int	ack;
 
-	while ((skb = skb_dequeue(&bcs->cmpl_queue))) {
-		L1L2(bcs->st, PH_DATA | CONFIRM, skb);
-	}
+	spin_lock_irqsave(&bcs->aclock, flags);
+	ack = bcs->ackcnt;
+	bcs->ackcnt = 0;
+	spin_unlock_irqrestore(&bcs->aclock, flags);
+	if (ack)
+		lli_writewakeup(bcs->st, ack);
 }
 
 void
-BChannel_bh(void *data)
+BChannel_bh(struct BCState *bcs)
 {
-	struct BCState *bcs = data;
-
+	if (!bcs)
+		return;
 	if (test_and_clear_bit(B_RCVBUFREADY, &bcs->event))
 		BChannel_proc_rcv(bcs);
 	if (test_and_clear_bit(B_XMTBUFREADY, &bcs->event))
 		BChannel_proc_xmt(bcs);
-	if (test_and_clear_bit(B_CMPLREADY, &bcs->event))
-		BChannel_proc_cmpl(bcs);
+	if (test_and_clear_bit(B_ACKPENDING, &bcs->event))
+		BChannel_proc_ack(bcs);
 }
 
 void
@@ -350,21 +355,23 @@ HiSax_rmlist(struct IsdnCardState *cs,
 }
 
 void
-init_bcstate(struct IsdnCardState *cs,
-	     int bc)
+init_bcstate(struct IsdnCardState *cs, int bc)
 {
 	struct BCState *bcs = cs->bcs + bc;
 
 	bcs->cs = cs;
 	bcs->channel = bc;
-	INIT_WORK(&bcs->work, BChannel_bh, bcs);
+	INIT_WORK(&bcs->tqueue, (void *)(void *) BChannel_bh, bcs);
+	spin_lock_init(&bcs->aclock);
+	bcs->BC_SetStack = NULL;
+	bcs->BC_Close = NULL;
 	bcs->Flag = 0;
 }
 
 #ifdef L2FRAME_DEBUG		/* psa */
 
 char *
-l2cmd(u8 cmd)
+l2cmd(u_char cmd)
 {
 	switch (cmd & ~0x10) {
 		case 1:
@@ -398,7 +405,7 @@ l2cmd(u8 cmd)
 static char tmpdeb[32];
 
 char *
-l2frames(u8 * ptr)
+l2frames(u_char * ptr)
 {
 	switch (ptr[2] & ~0x10) {
 		case 1:
@@ -430,7 +437,7 @@ l2frames(u8 * ptr)
 void
 Logl2Frame(struct IsdnCardState *cs, struct sk_buff *skb, char *buf, int dir)
 {
-	u8 *ptr;
+	u_char *ptr;
 
 	ptr = skb->data;
 
@@ -724,7 +731,7 @@ l1b_timer_act(struct FsmInst *fi, int ev
 	struct PStack *st = fi->userdata;
 
 	FsmChangeState(fi, ST_L1_ACTIV);
-	L1L2(st, PH_ACTIVATE | CONFIRM, NULL);
+	st->l1.l1l2(st, PH_ACTIVATE | CONFIRM, NULL);
 }
 
 static void
@@ -733,7 +740,7 @@ l1b_timer_deact(struct FsmInst *fi, int 
 	struct PStack *st = fi->userdata;
 
 	FsmChangeState(fi, ST_L1_NULL);
-	L2L1(st, PH_DEACTIVATE | CONFIRM, NULL);
+	st->l2.l2l1(st, PH_DEACTIVATE | CONFIRM, NULL);
 }
 
 static struct FsmNode L1BFnList[] __initdata =
@@ -808,7 +815,7 @@ dch_l2l1(struct PStack *st, int pr, void
 				debugl1(cs, "PH_ACTIVATE_REQ %s",
 					st->l1.l1m.fsm->strState[st->l1.l1m.state]);
 			if (test_bit(FLG_L1_ACTIVATED, &st->l1.Flags))
-				L1L2(st, PH_ACTIVATE | CONFIRM, NULL);
+				st->l1.l1l2(st, PH_ACTIVATE | CONFIRM, NULL);
 			else {
 				test_and_set_bit(FLG_L1_ACTIVATING, &st->l1.Flags);
 				FsmEvent(&st->l1.l1m, EV_PH_ACTIVATE, arg);
@@ -904,19 +911,9 @@ setstack_HiSax(struct PStack *st, struct
 	setstack_tei(st);
 	setstack_manager(st);
 	st->l1.stlistp = &(cs->stlist);
-	st->l1.l2l1  = dch_l2l1;
-	if (cs->dc_l1_ops->open)
-		cs->dc_l1_ops->open(st, cs);
-}
-
-void
-dc_l1_init(struct IsdnCardState *cs, struct dc_l1_ops *ops)
-{
-	cs->dc_l1_ops = ops;
-	INIT_WORK(&cs->work, ops->bh_func, cs);
-	init_timer(&cs->dbusytimer);
-	cs->dbusytimer.function = (void *)(unsigned long) ops->dbusy_func;
-	cs->dbusytimer.data = (unsigned long) cs;
+	st->l2.l2l1  = dch_l2l1;
+	if (cs->setstack_d)
+		cs->setstack_d(st, cs);
 }
 
 void
--- diff/drivers/isdn/hisax/isdnl1.h	2003-09-17 12:28:06.000000000 +0100
+++ source/drivers/isdn/hisax/isdnl1.h	2004-02-23 13:56:42.000000000 +0000
@@ -1,4 +1,4 @@
-/* $Id: isdnl1.h,v 2.9.6.3 2001/09/23 22:24:49 kai Exp $
+/* $Id: isdnl1.h,v 2.12.2.3 2004/02/11 13:21:34 keil Exp $
  *
  * Layer 1 defines
  *
@@ -7,9 +7,6 @@
  *
  */
 
-#ifndef __ISDNL1_H__
-#define __ISDNL1_H__
-
 #define D_RCVBUFREADY	0
 #define D_XMTBUFREADY	1
 #define D_L1STATECHANGE	2
@@ -20,578 +17,16 @@
 #define D_TX_MON1	7
 #define E_RCVBUFREADY	8
 
-#define B_RCVBUFREADY   0
-#define B_XMTBUFREADY   1
-#define B_CMPLREADY     2
-
-#define B_LL_NOCARRIER	8
-#define B_LL_CONNECT	9
-#define B_LL_OK		10
+#define B_RCVBUFREADY	0
+#define B_XMTBUFREADY	1
+#define B_ACKPENDING	2
 
-extern void debugl1(struct IsdnCardState *cs, const char *fmt, ...);
+extern void debugl1(struct IsdnCardState *cs, char *fmt, ...);
 extern void DChannel_proc_xmt(struct IsdnCardState *cs);
 extern void DChannel_proc_rcv(struct IsdnCardState *cs);
 extern void l1_msg(struct IsdnCardState *cs, int pr, void *arg);
 extern void l1_msg_b(struct PStack *st, int pr, void *arg);
 
-void dc_l1_init(struct IsdnCardState *cs, struct dc_l1_ops *ops);
-
-static inline void
-fill_fifo_b(struct BCState *bcs)
-{
-	bcs->cs->bc_l1_ops->fill_fifo(bcs);
-}
-
-static inline void
-fill_fifo_d(struct IsdnCardState *cs)
-{
-	cs->dc_l1_ops->fill_fifo(cs);
-}
-
 #ifdef L2FRAME_DEBUG
 extern void Logl2Frame(struct IsdnCardState *cs, struct sk_buff *skb, char *buf, int dir);
 #endif
-
-static inline void
-sched_b_event(struct BCState *bcs, int event)
-{
-	set_bit(event, &bcs->event);
-	schedule_work(&bcs->work);
-}
-
-static inline void
-sched_d_event(struct IsdnCardState *cs, int event)
-{
-	set_bit(event, &cs->event);
-	schedule_work(&cs->work);
-}
-
-/* called with the card lock held */
-static inline void
-xmit_complete_b(struct BCState *bcs)
-{
-	skb_queue_tail(&bcs->cmpl_queue, bcs->tx_skb);
-	sched_b_event(bcs, B_CMPLREADY);
-	bcs->tx_skb = NULL;
-}
-
-/* called with the card lock held */
-static inline void
-xmit_complete_d(struct IsdnCardState *cs)
-{
-	dev_kfree_skb_irq(cs->tx_skb);
-	cs->tx_skb = NULL;
-}
-
-/* called with the card lock held */
-static inline void
-xmit_ready_b(struct BCState *bcs)
-{
-	bcs->tx_skb = skb_dequeue(&bcs->squeue);
-	if (bcs->tx_skb) {
-		bcs->count = 0;
-		set_bit(BC_FLG_BUSY, &bcs->Flag);
-		fill_fifo_b(bcs);
-	} else {
-		clear_bit(BC_FLG_BUSY, &bcs->Flag);
-		sched_b_event(bcs, B_XMTBUFREADY);
-	}
-}
-
-/* called with the card lock held */
-static inline void
-xmit_ready_d(struct IsdnCardState *cs)
-{
-	cs->tx_skb = skb_dequeue(&cs->sq);
-	if (cs->tx_skb) {
-		cs->tx_cnt = 0;
-		fill_fifo_d(cs);
-	} else {
-		sched_d_event(cs, D_XMTBUFREADY);
-	}
-}
-
-static inline void
-xmit_data_req_b(struct BCState *bcs, struct sk_buff *skb)
-{
-	struct IsdnCardState *cs = bcs->cs;
-	unsigned long flags;
-
-	spin_lock_irqsave(&cs->lock, flags);
-	if (bcs->tx_skb) {
-		skb_queue_tail(&bcs->squeue, skb);
-	} else {
-		set_bit(BC_FLG_BUSY, &bcs->Flag);
-		bcs->tx_skb = skb;
-		bcs->count = 0;
-		fill_fifo_b(bcs);
-	}
-	spin_unlock_irqrestore(&cs->lock, flags);
-}
-
-static inline void
-xmit_data_req_d(struct IsdnCardState *cs, struct sk_buff *skb)
-{
-	unsigned long flags;
-
-	spin_lock_irqsave(&cs->lock, flags);
-	if (cs->debug & DEB_DLOG_HEX)
-		LogFrame(cs, skb->data, skb->len);
-	if (cs->debug & DEB_DLOG_VERBOSE)
-		dlogframe(cs, skb, 0);
-	if (cs->tx_skb) {
-		skb_queue_tail(&cs->sq, skb);
-#ifdef L2FRAME_DEBUG
-		if (cs->debug & L1_DEB_LAPD)
-			Logl2Frame(cs, skb, "PH_DATA Queued", 0);
-#endif
-	} else {
-		cs->tx_skb = skb;
-		cs->tx_cnt = 0;
-#ifdef L2FRAME_DEBUG
-		if (cs->debug & L1_DEB_LAPD)
-			Logl2Frame(cs, skb, "PH_DATA", 0);
-#endif
-		fill_fifo_d(cs);
-	}
-	spin_unlock_irqrestore(&cs->lock, flags);
-}
-
-static inline void
-xmit_pull_ind_b(struct BCState *bcs, struct sk_buff *skb)
-{
-	struct IsdnCardState *cs = bcs->cs;
-	unsigned long flags;
-
-	spin_lock_irqsave(&cs->lock, flags);
-	if (bcs->tx_skb) {
-		WARN_ON(1);
-	} else {
-		set_bit(BC_FLG_BUSY, &bcs->Flag);
-		bcs->tx_skb = skb;
-		bcs->count = 0;
-		fill_fifo_b(bcs);
-	}
-	spin_unlock_irqrestore(&cs->lock, flags);
-}
-
-static inline void
-xmit_pull_ind_d(struct IsdnCardState *cs, struct sk_buff *skb)
-{
-	unsigned long flags;
-
-	spin_lock_irqsave(&cs->lock, flags);
-	if (cs->tx_skb) {
-		WARN_ON(1);
-	} else {
-		if (cs->debug & DEB_DLOG_HEX)
-			LogFrame(cs, skb->data, skb->len);
-		if (cs->debug & DEB_DLOG_VERBOSE)
-			dlogframe(cs, skb, 0);
-#ifdef L2FRAME_DEBUG
-		if (cs->debug & L1_DEB_LAPD)
-			Logl2Frame(cs, skb, "PH_DATA_PULLED", 0);
-#endif
-		cs->tx_skb = skb;
-		cs->tx_cnt = 0;
-		fill_fifo_d(cs);
-	}
-	spin_unlock_irqrestore(&cs->lock, flags);
-}
-
-/* If busy, the PH_PULL | CONFIRM scheduling is handled under
- * the card lock by xmit_ready_b() above, so no race */
-static inline void
-xmit_pull_req_b(struct PStack *st)
-{
-	struct BCState *bcs = st->l1.bcs;
-	struct IsdnCardState *cs = bcs->cs;
-	unsigned long flags;
-	int busy = 0;
-
-	spin_lock_irqsave(&cs->lock, flags);
-	if (bcs->tx_skb) {
-		set_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
-		busy = 1;
-	}
-	spin_unlock_irqrestore(&cs->lock, flags);
-	if (!busy)
-		L1L2(st, PH_PULL | CONFIRM, NULL);
-}
-
-/* If busy, the PH_PULL | CONFIRM scheduling is handled under
- * the card lock by xmit_ready_d() above, so no race */
-static inline void
-xmit_pull_req_d(struct PStack *st)
-{
-	struct IsdnCardState *cs = st->l1.hardware;
-	unsigned long flags;
-	int busy = 0;
-
-#ifdef L2FRAME_DEBUG
-	if (cs->debug & L1_DEB_LAPD)
-		debugl1(cs, "-> PH_REQUEST_PULL");
-#endif
-	spin_lock_irqsave(&cs->lock, flags);
-	if (cs->tx_skb) {
-		set_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
-		busy = 1;
-	}
-	spin_unlock_irqrestore(&cs->lock, flags);
-	if (!busy)
-		L1L2(st, PH_PULL | CONFIRM, NULL);
-}
-
-/* called with the card lock held */
-static inline void
-xmit_restart_b(struct BCState *bcs)
-{
-#ifdef ERROR_STATISTIC
-	bcs->err_tx++;
-#endif
-	if (!bcs->tx_skb) {
-		WARN_ON(1);
-		return;
-	}
-	skb_push(bcs->tx_skb, bcs->count);
-	bcs->tx_cnt += bcs->count;
-	bcs->count = 0;
-}
-
-/* called with the card lock held */
-static inline void
-xmit_restart_d(struct IsdnCardState *cs)
-{
-#ifdef ERROR_STATISTIC
-	cs->err_tx++;
-#endif
-	if (!cs->tx_skb) {
-		WARN_ON(1);
-		return;
-	}
-	skb_push(cs->tx_skb, cs->tx_cnt);
-	cs->tx_cnt = 0;
-}
-
-/* Useful for HSCX/ISAC work-alike's */
-/* ---------------------------------------------------------------------- */
-
-/* XPR - transmit pool ready */
-/* called with the card lock held */
-static inline void
-xmit_xpr_b(struct BCState *bcs)
-{
-	/* current frame? */
-	if (bcs->tx_skb) {
-		/* last frame not done yet? */
-		if (bcs->tx_skb->len) {
-			fill_fifo_b(bcs);
-			return;
-		}
-		xmit_complete_b(bcs);
-		bcs->count = 0;
-	}
-	xmit_ready_b(bcs);
-}
-
-/* XPR - transmit pool ready */
-/* called with the card lock held */
-static inline void
-xmit_xpr_d(struct IsdnCardState *cs)
-{
-	if (test_and_clear_bit(FLG_DBUSY_TIMER, &cs->HW_Flags))
-		del_timer(&cs->dbusytimer);
-	if (test_and_clear_bit(FLG_L1_DBUSY, &cs->HW_Flags))
-		sched_d_event(cs, D_CLEARBUSY);
-	/* current frame? */
-	if (cs->tx_skb) {
-		/* last frame not done yet? */
-		if (cs->tx_skb->len) {
-			fill_fifo_d(cs);
-			return;
-		}
-		xmit_complete_d(cs);
-		cs->tx_cnt = 0;
-	}
-	xmit_ready_d(cs);
-}
-
-/* XDU - transmit data underrun */
-/* called with the card lock held */
-static inline void
-xmit_xdu_b(struct BCState *bcs, void (*reset_xmit)(struct BCState *bcs))
-{
-	struct IsdnCardState *cs = bcs->cs;
-
-	if (cs->debug & L1_DEB_WARN)
-		debugl1(cs, "HSCX %c EXIR XDU", 'A' + bcs->channel);
-
-	if (bcs->mode == L1_MODE_TRANS) {
-		fill_fifo_b(bcs);
-	} else {
-		xmit_restart_b(bcs);
-		reset_xmit(bcs);
-	}
-}
-
-/* XDU - transmit data underrun */
-/* called with the card lock held */
-static inline void
-xmit_xdu_d(struct IsdnCardState *cs, void (*reset_xmit)(struct IsdnCardState *cs))
-{
-	printk(KERN_WARNING "HiSax: D XDU\n");
-	if (cs->debug & L1_DEB_WARN)
-		debugl1(cs, "D XDU");
-
-	if (test_and_clear_bit(FLG_DBUSY_TIMER, &cs->HW_Flags))
-		del_timer(&cs->dbusytimer);
-	if (test_and_clear_bit(FLG_L1_DBUSY, &cs->HW_Flags))
-		sched_d_event(cs, D_CLEARBUSY);
-
-	xmit_restart_d(cs);
-	if (reset_xmit)
-		reset_xmit(cs);
-}
-
-static inline unsigned char *
-xmit_fill_fifo_b(struct BCState *bcs, u_int fifo_size, int *count, int *more)
-{
-	struct IsdnCardState *cs = bcs->cs;
-	unsigned char *p;
-
-	if ((cs->debug & L1_DEB_HSCX) && !(cs->debug & L1_DEB_HSCX_FIFO))
-		debugl1(cs, __FUNCTION__);
-
-	if (!bcs->tx_skb || bcs->tx_skb->len <= 0) {
-		WARN_ON(1);
-		return NULL;
-	}
-
-	*more = (bcs->mode == L1_MODE_TRANS);
-	if (bcs->tx_skb->len > fifo_size) {
-		*more = 1;
-		*count = fifo_size;
-	} else {
-		*count = bcs->tx_skb->len;
-	}
-	p = bcs->tx_skb->data;
-	skb_pull(bcs->tx_skb, *count);
-	bcs->tx_cnt -= *count;
-	bcs->count += *count;
-
-	if (cs->debug & L1_DEB_HSCX_FIFO) {
-		char *t = bcs->blog;
-
-		t += sprintf(t, "%s %c cnt %d", __FUNCTION__,
-			     bcs->unit ? 'B' : 'A', *count);
-		QuickHex(t, p, *count);
-		debugl1(cs, bcs->blog);
-	}
-	return p;
-}
-
-static inline unsigned char *
-xmit_fill_fifo_d(struct IsdnCardState *cs, u_int fifo_size, int *count, int *more)
-{
-	unsigned char *p;
-
-	if ((cs->debug & L1_DEB_ISAC) && !(cs->debug & L1_DEB_ISAC_FIFO))
-		debugl1(cs, __FUNCTION__);
-
-	if (!cs->tx_skb || cs->tx_skb->len <= 0) {
-		WARN_ON(1);
-		return NULL;
-	}
-
-	*more = 0;
-	if (cs->tx_skb->len > fifo_size) {
-		*more = 1;
-		*count = fifo_size;
-	} else {
-		*count = cs->tx_skb->len;
-	}
-
-	p = cs->tx_skb->data;
-	skb_pull(cs->tx_skb, *count);
-	cs->tx_cnt += *count;
-
-	if (cs->debug & L1_DEB_ISAC_FIFO) {
-		char *t = cs->dlog;
-
-		t += sprintf(t, "%s cnt %d", __FUNCTION__, *count);
-		QuickHex(t, p, *count);
-		debugl1(cs, cs->dlog);
-	}
-	return p;
-}
-
-static inline void
-recv_empty_fifo_d(struct IsdnCardState *cs, int count)
-{
-	u8 *p;
-
-	if ((cs->debug & L1_DEB_ISAC) && !(cs->debug & L1_DEB_ISAC_FIFO))
-		debugl1(cs, __FUNCTION__);
-
-	if (cs->rcvidx + count > MAX_DFRAME_LEN_L1) {
-		if (cs->debug & L1_DEB_WARN)
-			debugl1(cs, "%s: incoming packet too large", __FUNCTION__);
-		cs->rcvidx = 0;
-		return;
-	}
-	p = cs->rcvbuf + cs->rcvidx;
-	cs->rcvidx += count;
-	cs->dc_hw_ops->read_fifo(cs, p, count);
-
-	if (cs->debug & L1_DEB_ISAC_FIFO) {
-		char *t = cs->dlog;
-
-		t += sprintf(t, "%s cnt %d", __FUNCTION__, count);
-		QuickHex(t, p, count);
-		debugl1(cs, cs->dlog);
-	}
-}
-
-static inline void
-recv_empty_fifo_b(struct BCState *bcs, int count)
-{
-	u8 *p;
-	struct IsdnCardState *cs = bcs->cs;
-
-	if ((cs->debug & L1_DEB_HSCX) && !(cs->debug & L1_DEB_HSCX_FIFO))
-		debugl1(cs, __FUNCTION__);
-
-	if (bcs->rcvidx + count > HSCX_BUFMAX) {
-		if (cs->debug & L1_DEB_WARN)
-			debugl1(cs, "%s: incoming packet too large", __FUNCTION__);
-		bcs->rcvidx = 0;
-		return;
-	}
-	p = bcs->rcvbuf + bcs->rcvidx;
-	bcs->rcvidx += count;
-	cs->bc_hw_ops->read_fifo(cs, bcs->unit, p, count);
-
-	if (cs->debug & L1_DEB_HSCX_FIFO) {
-		char *t = bcs->blog;
-
-		t += sprintf(t, "%s %c cnt %d", __FUNCTION__,
-			     bcs->unit ? 'B' : 'A', count);
-		QuickHex(t, p, count);
-		debugl1(cs, bcs->blog);
-	}
-}
-
-/* RME - receive message end */
-static inline void
-recv_rme_d(struct IsdnCardState *cs)
-{
-	struct sk_buff *skb;
-	int count;
-
-	count = cs->rcvidx - 1;
-	cs->rcvidx = 0;
-	if (count == 0)
-		return;
-
-	skb = dev_alloc_skb(count);
-	if (!skb) {
-		printk(KERN_WARNING "HiSax: %s: out of memory\n", __FUNCTION__);
-		return;
-	}
-	memcpy(skb_put(skb, count), cs->rcvbuf, count);
-	skb_queue_tail(&cs->rq, skb);
-	sched_d_event(cs, D_RCVBUFREADY);
-}
-
-static inline void
-recv_rme_b(struct BCState *bcs)
-{
-	struct IsdnCardState *cs = bcs->cs;
-	struct sk_buff *skb;
-	int count;
-
-	count = bcs->rcvidx - 1;
-	bcs->rcvidx = 0;
-	if (count == 0)
-		return;
-
-	if (cs->debug & L1_DEB_HSCX_FIFO)
-		debugl1(cs, "HX Frame %d", count);
-
-	skb = dev_alloc_skb(count);
-	if (!skb) {
-		printk(KERN_WARNING "HiSax: %s: out of memory\n", __FUNCTION__);
-		return;
-	}
-	memcpy(skb_put(skb, count), bcs->rcvbuf, count);
-	skb_queue_tail(&bcs->rqueue, skb);
-	sched_b_event(bcs, B_RCVBUFREADY);
-}
-
-/* RPF - receive pull full */
-static inline void
-recv_rpf_b(struct BCState *bcs)
-{
-	if (bcs->mode != L1_MODE_TRANS)
-		return;
-
-	recv_rme_b(bcs);
-}
-	
-static inline int
-bc_open(struct BCState *bcs)
-{
-	if (test_and_set_bit(BC_FLG_INIT, &bcs->Flag))
-		return 0;
-
-	bcs->rcvbuf = kmalloc(HSCX_BUFMAX, GFP_ATOMIC);
-	if (!bcs->rcvbuf)
-		goto err;
-
-	bcs->blog = kmalloc(MAX_BLOG_SPACE, GFP_ATOMIC);
-	if (!bcs->blog)
-		goto err_rcvbuf;
-	
-	skb_queue_head_init(&bcs->rqueue);
-	skb_queue_head_init(&bcs->squeue);
-	skb_queue_head_init(&bcs->cmpl_queue);
-
-	clear_bit(BC_FLG_BUSY, &bcs->Flag);
-	bcs->tx_skb = NULL;
-	bcs->rcvidx = 0;
-	bcs->tx_cnt = 0;
-	bcs->event = 0;
-
-	return 0;
-
- err_rcvbuf:
-	kfree(bcs->rcvbuf);
- err:
-	clear_bit(BC_FLG_INIT, &bcs->Flag);
-	printk(KERN_WARNING "HiSax: %s: out of memory\n", __FUNCTION__);
-	return -ENOMEM;;
-}
-
-static inline void
-bc_close(struct BCState *bcs)
-{
-	if (!test_and_clear_bit(BC_FLG_INIT, &bcs->Flag))
-		return;
-
-	kfree(bcs->rcvbuf);
-	bcs->rcvbuf = NULL;
-
-	kfree(bcs->blog);
-	bcs->blog = NULL;
-
-	skb_queue_purge(&bcs->rqueue);
-	skb_queue_purge(&bcs->squeue);
-	skb_queue_purge(&bcs->cmpl_queue);
-	if (bcs->tx_skb) {
-		dev_kfree_skb_any(bcs->tx_skb);
-		bcs->tx_skb = NULL;
-		clear_bit(BC_FLG_BUSY, &bcs->Flag);
-	}
-}
-
-#endif
--- diff/drivers/isdn/hisax/isdnl2.c	2003-09-17 12:28:06.000000000 +0100
+++ source/drivers/isdn/hisax/isdnl2.c	2004-02-23 13:56:42.000000000 +0000
@@ -1,4 +1,4 @@
-/* $Id: isdnl2.c,v 2.25.6.4 2001/09/23 22:24:49 kai Exp $
+/* $Id: isdnl2.c,v 2.30.2.4 2004/02/11 13:21:34 keil Exp $
  *
  * Author       Karsten Keil
  *              based on the teles driver from Jan den Ouden
@@ -19,21 +19,21 @@
 #include "hisax.h"
 #include "isdnl2.h"
 
-const char *l2_revision = "$Revision: 2.25.6.4 $";
-static spinlock_t isdnl2_lock = SPIN_LOCK_UNLOCKED;
+const char *l2_revision = "$Revision: 2.30.2.4 $";
+
 static void l2m_debug(struct FsmInst *fi, char *fmt, ...);
 
 static struct Fsm l2fsm;
 
 enum {
-	ST_L2_1, /* TEI unassigned */
-	ST_L2_2, /* Assign awaiting TEI */
-	ST_L2_3, /* Establish awaiting TEI */
-	ST_L2_4, /* TEI assigned */
-	ST_L2_5, /* Awaiting establishment */
-	ST_L2_6, /* Awaiting release */
-	ST_L2_7, /* Multiple frame established */
-	ST_L2_8, /* Timer recovery */
+	ST_L2_1,
+	ST_L2_2,
+	ST_L2_3,
+	ST_L2_4,
+	ST_L2_5,
+	ST_L2_6,
+	ST_L2_7,
+	ST_L2_8,
 };
 
 #define L2_STATE_COUNT (ST_L2_8+1)
@@ -103,7 +103,7 @@ static char *strL2Event[] =
 	"EV_L2_FRAME_ERROR",
 };
 
-static u_int l2addrsize(struct Layer2 *l2);
+static int l2addrsize(struct Layer2 *l2);
 
 static void
 set_peer_busy(struct Layer2 *l2) {
@@ -178,23 +178,23 @@ clear_exception(struct Layer2 *l2)
 	clear_peer_busy(l2);
 }
 
-inline u_int
+inline int
 l2headersize(struct Layer2 *l2, int ui)
 {
 	return (((test_bit(FLG_MOD128, &l2->flag) && (!ui)) ? 2 : 1) +
 		(test_bit(FLG_LAPD, &l2->flag) ? 2 : 1));
 }
 
-inline u_int
+inline int
 l2addrsize(struct Layer2 *l2)
 {
 	return (test_bit(FLG_LAPD, &l2->flag) ? 2 : 1);
 }
 
 static int
-sethdraddr(struct Layer2 *l2, u8 * header, int rsp)
+sethdraddr(struct Layer2 *l2, u_char * header, int rsp)
 {
-	u8 *ptr = header;
+	u_char *ptr = header;
 	int crbit = rsp;
 
 	if (test_bit(FLG_LAPD, &l2->flag)) {
@@ -218,37 +218,37 @@ enqueue_super(struct PStack *st,
 {
 	if (test_bit(FLG_LAPB, &st->l2.flag))
 		st->l1.bcs->tx_cnt += skb->len;
-	L2L1(st, PH_DATA | REQUEST, skb);
+	st->l2.l2l1(st, PH_DATA | REQUEST, skb);
 }
 
 #define enqueue_ui(a, b) enqueue_super(a, b)
 
 inline int
-IsUI(u8 * data)
+IsUI(u_char * data)
 {
 	return ((data[0] & 0xef) == UI);
 }
 
 inline int
-IsUA(u8 * data)
+IsUA(u_char * data)
 {
 	return ((data[0] & 0xef) == UA);
 }
 
 inline int
-IsDM(u8 * data)
+IsDM(u_char * data)
 {
 	return ((data[0] & 0xef) == DM);
 }
 
 inline int
-IsDISC(u8 * data)
+IsDISC(u_char * data)
 {
 	return ((data[0] & 0xef) == DISC);
 }
 
 inline int
-IsRR(u8 * data, struct PStack *st)
+IsRR(u_char * data, struct PStack *st)
 {
 	if (test_bit(FLG_MOD128, &st->l2.flag))
 		return (data[0] == RR);
@@ -257,9 +257,9 @@ IsRR(u8 * data, struct PStack *st)
 }
 
 inline int
-IsSFrame(u8 * data, struct PStack *st)
+IsSFrame(u_char * data, struct PStack *st)
 {
-	register u8 d = *data;
+	register u_char d = *data;
 	
 	if (!test_bit(FLG_MOD128, &st->l2.flag))
 		d &= 0xf;
@@ -267,27 +267,27 @@ IsSFrame(u8 * data, struct PStack *st)
 }
 
 inline int
-IsSABME(u8 * data, struct PStack *st)
+IsSABME(u_char * data, struct PStack *st)
 {
-	u8 d = data[0] & ~0x10;
+	u_char d = data[0] & ~0x10;
 
 	return (test_bit(FLG_MOD128, &st->l2.flag) ? d == SABME : d == SABM);
 }
 
 inline int
-IsREJ(u8 * data, struct PStack *st)
+IsREJ(u_char * data, struct PStack *st)
 {
 	return (test_bit(FLG_MOD128, &st->l2.flag) ? data[0] == REJ : (data[0] & 0xf) == REJ);
 }
 
 inline int
-IsFRMR(u8 * data)
+IsFRMR(u_char * data)
 {
 	return ((data[0] & 0xef) == FRMR);
 }
 
 inline int
-IsRNR(u8 * data, struct PStack *st)
+IsRNR(u_char * data, struct PStack *st)
 {
 	return (test_bit(FLG_MOD128, &st->l2.flag) ? data[0] == RNR : (data[0] & 0xf) == RNR);
 }
@@ -295,7 +295,7 @@ IsRNR(u8 * data, struct PStack *st)
 int
 iframe_error(struct PStack *st, struct sk_buff *skb)
 {
-	u_int i = l2addrsize(&st->l2) + (test_bit(FLG_MOD128, &st->l2.flag) ? 2 : 1);
+	int i = l2addrsize(&st->l2) + (test_bit(FLG_MOD128, &st->l2.flag) ? 2 : 1);
 	int rsp = *skb->data & 0x2;
 
 	if (test_bit(FLG_ORIG, &st->l2.flag))
@@ -360,8 +360,8 @@ UI_error(struct PStack *st, struct sk_bu
 int
 FRMR_error(struct PStack *st, struct sk_buff *skb)
 {
-	u_int headers = l2addrsize(&st->l2) + 1;
-	u8 *datap = skb->data + headers;
+	int headers = l2addrsize(&st->l2) + 1;
+	u_char *datap = skb->data + headers;
 	int rsp = *skb->data & 0x2;
 
 	if (test_bit(FLG_ORIG, &st->l2.flag))
@@ -403,27 +403,35 @@ static void
 setva(struct PStack *st, unsigned int nr)
 {
 	struct Layer2 *l2 = &st->l2;
-	struct sk_buff *skb;
+	int len;
+	u_long flags;
 
+	spin_lock_irqsave(&l2->lock, flags);
 	while (l2->va != nr) {
 		(l2->va)++;
 		if(test_bit(FLG_MOD128, &l2->flag))
 			l2->va %= 128;
 		else
 			l2->va %= 8;
-		skb = l2->windowar[l2->sow];
+		len = l2->windowar[l2->sow]->len;
+		if (PACKET_NOACK == l2->windowar[l2->sow]->pkt_type)
+			len = -1;
+		dev_kfree_skb(l2->windowar[l2->sow]);
 		l2->windowar[l2->sow] = NULL;
 		l2->sow = (l2->sow + 1) % l2->window;
-		
-		L2L3(st, DL_DATA | CONFIRM, skb);
+		spin_unlock_irqrestore(&l2->lock, flags);
+		if (test_bit(FLG_LLI_L2WAKEUP, &st->lli.flag) && (len >=0))
+			lli_writewakeup(st, len);
+		spin_lock_irqsave(&l2->lock, flags);
 	}
+	spin_unlock_irqrestore(&l2->lock, flags);
 }
 
 static void
-send_uframe(struct PStack *st, u8 cmd, u8 cr)
+send_uframe(struct PStack *st, u_char cmd, u_char cr)
 {
 	struct sk_buff *skb;
-	u8 tmp[MAX_HEADER_LEN];
+	u_char tmp[MAX_HEADER_LEN];
 	int i;
 
 	i = sethdraddr(&st->l2, tmp, cr);
@@ -436,7 +444,7 @@ send_uframe(struct PStack *st, u8 cmd, u
 	enqueue_super(st, skb);
 }
 
-inline u8
+inline u_char
 get_PollFlag(struct PStack * st, struct sk_buff * skb)
 {
 	return (skb->data[l2addrsize(&(st->l2))] & 0x10);
@@ -449,10 +457,10 @@ FreeSkb(struct sk_buff *skb)
 }
 
 
-inline u8
+inline u_char
 get_PollFlagFree(struct PStack *st, struct sk_buff *skb)
 {
-	u8 PF;
+	u_char PF;
 
 	PF = get_PollFlag(st, skb);
 	FreeSkb(skb);
@@ -490,22 +498,22 @@ st5_dl_release_l2l3(struct PStack *st)
 		else
 			pr = DL_RELEASE | INDICATION;
 
-		L2L3(st, pr, NULL);
+		st->l2.l2l3(st, pr, NULL);
 }
 
 inline void
 lapb_dl_release_l2l3(struct PStack *st, int f)
 {
 		if (test_bit(FLG_LAPB, &st->l2.flag))
-			L2L1(st, PH_DEACTIVATE | REQUEST, NULL);
-		L2L3(st, DL_RELEASE | f, NULL);
+			st->l2.l2l1(st, PH_DEACTIVATE | REQUEST, NULL);
+		st->l2.l2l3(st, DL_RELEASE | f, NULL);
 }
 
 static void
 establishlink(struct FsmInst *fi)
 {
 	struct PStack *st = fi->userdata;
-	u8 cmd;
+	u_char cmd;
 
 	clear_exception(&st->l2);
 	st->l2.rc = 0;
@@ -599,7 +607,7 @@ static void
 tx_ui(struct PStack *st)
 {
 	struct sk_buff *skb;
-	u8 header[MAX_HEADER_LEN];
+	u_char header[MAX_HEADER_LEN];
 	int i;
 
 	i = sethdraddr(&(st->l2), header, CMD);
@@ -627,7 +635,7 @@ l2_got_ui(struct FsmInst *fi, int event,
 	struct sk_buff *skb = arg;
 
 	skb_pull(skb, l2headersize(&st->l2, 1));
-	L2L3(st, DL_UNIT_DATA | INDICATION, skb);
+	st->l2.l2l3(st, DL_UNIT_DATA | INDICATION, skb);
 /*	^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  *		in states 1-3 for broadcast
  */
@@ -669,7 +677,7 @@ l2_release(struct FsmInst *fi, int event
 {
 	struct PStack *st = fi->userdata;
 
-	L2L3(st, DL_RELEASE | CONFIRM, NULL);
+	st->l2.l2l3(st, DL_RELEASE | CONFIRM, NULL);
 }
 
 static void
@@ -710,7 +718,7 @@ l2_start_multi(struct FsmInst *fi, int e
 	FsmChangeState(fi, ST_L2_7);
 	FsmAddTimer(&st->l2.t203, st->l2.T203, EV_L2_T203, NULL, 3);
 
-	L2L3(st, DL_ESTABLISH | INDICATION, NULL);
+	st->l2.l2l3(st, DL_ESTABLISH | INDICATION, NULL);
 }
 
 static void
@@ -759,11 +767,11 @@ l2_restart_multi(struct FsmInst *fi, int
 	FsmRestartTimer(&st->l2.t203, st->l2.T203, EV_L2_T203, NULL, 3);
 
 	if (est)
-		L2L3(st, DL_ESTABLISH | INDICATION, NULL);
+		st->l2.l2l3(st, DL_ESTABLISH | INDICATION, NULL);
 
 	if ((ST_L2_7==state) || (ST_L2_8 == state))
 		if (skb_queue_len(&st->l2.i_queue) && cansend(st))
-			L2L1(st, PH_PULL | REQUEST, NULL);
+			st->l2.l2l1(st, PH_PULL | REQUEST, NULL);
 }
 
 static void
@@ -816,10 +824,10 @@ l2_connected(struct FsmInst *fi, int eve
 	FsmAddTimer(&st->l2.t203, st->l2.T203, EV_L2_T203, NULL, 4);
 
 	if (pr != -1)
-		L2L3(st, pr, NULL);
+		st->l2.l2l3(st, pr, NULL);
 
 	if (skb_queue_len(&st->l2.i_queue) && cansend(st))
-		L2L1(st, PH_PULL | REQUEST, NULL);
+		st->l2.l2l1(st, PH_PULL | REQUEST, NULL);
 }
 
 static void
@@ -862,7 +870,7 @@ l2_st5_dm_release(struct FsmInst *fi, in
 	 	if (!test_bit(FLG_L3_INIT, &st->l2.flag))
 			skb_queue_purge(&st->l2.i_queue);
 		if (test_bit(FLG_LAPB, &st->l2.flag))
-			L2L1(st, PH_DEACTIVATE | REQUEST, NULL);
+			st->l2.l2l1(st, PH_DEACTIVATE | REQUEST, NULL);
 		st5_dl_release_l2l3(st);
 		FsmChangeState(fi, ST_L2_4);
 	}
@@ -882,11 +890,11 @@ l2_st6_dm_release(struct FsmInst *fi, in
 }
 
 inline void
-enquiry_cr(struct PStack *st, u8 typ, u8 cr, u8 pf)
+enquiry_cr(struct PStack *st, u_char typ, u_char cr, u_char pf)
 {
 	struct sk_buff *skb;
 	struct Layer2 *l2;
-	u8 tmp[MAX_HEADER_LEN];
+	u_char tmp[MAX_HEADER_LEN];
 	int i;
 
 	l2 = &st->l2;
@@ -940,8 +948,10 @@ static void
 invoke_retransmission(struct PStack *st, unsigned int nr)
 {
 	struct Layer2 *l2 = &st->l2;
-	unsigned int p1;
+	u_int p1;
+	u_long flags;
 
+	spin_lock_irqsave(&l2->lock, flags);
 	if (l2->vs != nr) {
 		while (l2->vs != nr) {
 			(l2->vs)--;
@@ -958,8 +968,11 @@ invoke_retransmission(struct PStack *st,
 			skb_queue_head(&l2->i_queue, l2->windowar[p1]);
 			l2->windowar[p1] = NULL;
 		}
-		L2L1(st, PH_PULL | REQUEST, NULL);
+		spin_unlock_irqrestore(&l2->lock, flags);
+		st->l2.l2l1(st, PH_PULL | REQUEST, NULL);
+		return;
 	}
+	spin_unlock_irqrestore(&l2->lock, flags);
 }
 
 static void
@@ -1018,7 +1031,7 @@ l2_st7_got_super(struct FsmInst *fi, int
 			restart_t200(st, 12);
 		}
 		if (skb_queue_len(&st->l2.i_queue) && (typ == RR))
-			L2L1(st, PH_PULL | REQUEST, NULL);
+			st->l2.l2l1(st, PH_PULL | REQUEST, NULL);
 	} else
 		nrerrorrecovery(fi);
 }
@@ -1046,7 +1059,7 @@ l2_feed_i_pull(struct FsmInst *fi, int e
 	if (test_bit(FLG_LAPB, &st->l2.flag))
 		st->l1.bcs->tx_cnt += skb->len + l2headersize(&st->l2, 0);
 	skb_queue_tail(&st->l2.i_queue, skb);
-	L2L1(st, PH_PULL | REQUEST, NULL);
+	st->l2.l2l1(st, PH_PULL | REQUEST, NULL);
 }
 
 static void
@@ -1066,8 +1079,8 @@ l2_got_iframe(struct FsmInst *fi, int ev
 	struct PStack *st = fi->userdata;
 	struct sk_buff *skb = arg;
 	struct Layer2 *l2 = &(st->l2);
-	int PollFlag, i;
-	unsigned int nr, ns;
+	int PollFlag, ns, i;
+	unsigned int nr;
 
 	i = l2addrsize(l2);
 	if (test_bit(FLG_MOD128, &l2->flag)) {
@@ -1095,7 +1108,7 @@ l2_got_iframe(struct FsmInst *fi, int ev
 		else
 			test_and_set_bit(FLG_ACK_PEND, &l2->flag);
 		skb_pull(skb, l2headersize(l2, 0));
-		L2L3(st, DL_DATA | INDICATION, skb);
+		st->l2.l2l3(st, DL_DATA | INDICATION, skb);
 	} else {
 		/* n(s)!=v(r) */
 		FreeSkb(skb);
@@ -1124,7 +1137,7 @@ l2_got_iframe(struct FsmInst *fi, int ev
 	}
 
 	if (skb_queue_len(&st->l2.i_queue) && (fi->state == ST_L2_7))
-		L2L1(st, PH_PULL | REQUEST, NULL);
+		st->l2.l2l1(st, PH_PULL | REQUEST, NULL);
 	if (test_and_clear_bit(FLG_ACK_PEND, &st->l2.flag))
 		enquiry_cr(st, RR, RSP, 0);
 }
@@ -1159,7 +1172,7 @@ l2_st5_tout_200(struct FsmInst *fi, int 
 		skb_queue_purge(&st->l2.i_queue);
 		st->ma.layer(st, MDL_ERROR | INDICATION, (void *) 'G');
 		if (test_bit(FLG_LAPB, &st->l2.flag))
-			L2L1(st, PH_DEACTIVATE | REQUEST, NULL);
+			st->l2.l2l1(st, PH_DEACTIVATE | REQUEST, NULL);
 		st5_dl_release_l2l3(st);
 	} else {
 		st->l2.rc++;
@@ -1250,9 +1263,10 @@ l2_pull_iqueue(struct FsmInst *fi, int e
 	struct PStack *st = fi->userdata;
 	struct sk_buff *skb, *oskb;
 	struct Layer2 *l2 = &st->l2;
-	u8 header[MAX_HEADER_LEN];
-	int unsigned p1, i;
-	unsigned long flags;
+	u_char header[MAX_HEADER_LEN];
+	int i;
+	int unsigned p1;
+	u_long flags;
 
 	if (!cansend(st))
 		return;
@@ -1261,7 +1275,7 @@ l2_pull_iqueue(struct FsmInst *fi, int e
 	if (!skb)
 		return;
 
-	spin_lock_irqsave(&isdnl2_lock, flags);
+	spin_lock_irqsave(&l2->lock, flags);
 	if(test_bit(FLG_MOD128, &l2->flag))
 		p1 = (l2->vs - l2->va) % 128;
 	else
@@ -1284,8 +1298,7 @@ l2_pull_iqueue(struct FsmInst *fi, int e
 		header[i++] = (l2->vr << 5) | (l2->vs << 1);
 		l2->vs = (l2->vs + 1) % 8;
 	}
-	spin_unlock_irqrestore(&isdnl2_lock, flags);
-
+	spin_unlock_irqrestore(&l2->lock, flags);
 	p1 = skb->data - skb->head;
 	if (p1 >= i)
 		memcpy(skb_push(skb, i), header, i);
@@ -1298,14 +1311,14 @@ l2_pull_iqueue(struct FsmInst *fi, int e
 		memcpy(skb_put(skb, oskb->len), oskb->data, oskb->len);
 		FreeSkb(oskb);
 	}
-	L2L1(st, PH_PULL | INDICATION, skb);
+	st->l2.l2l1(st, PH_PULL | INDICATION, skb);
 	test_and_clear_bit(FLG_ACK_PEND, &st->l2.flag);
 	if (!test_and_set_bit(FLG_T200_RUN, &st->l2.flag)) {
 		FsmDelTimer(&st->l2.t203, 13);
 		FsmAddTimer(&st->l2.t200, st->l2.T200, EV_L2_T200, NULL, 11);
 	}
 	if (skb_queue_len(&l2->i_queue) && cansend(st))
-		L2L1(st, PH_PULL | REQUEST, NULL);
+		st->l2.l2l1(st, PH_PULL | REQUEST, NULL);
 }
 
 static void
@@ -1351,7 +1364,7 @@ l2_st8_got_super(struct FsmInst *fi, int
 			invoke_retransmission(st, nr);
 			FsmChangeState(fi, ST_L2_7);
 			if (skb_queue_len(&l2->i_queue) && cansend(st))
-				L2L1(st, PH_PULL | REQUEST, NULL);
+				st->l2.l2l1(st, PH_PULL | REQUEST, NULL);
 		} else
 			nrerrorrecovery(fi);
 	} else {
@@ -1398,7 +1411,7 @@ l2_st3_tei_remove(struct FsmInst *fi, in
 
 	skb_queue_purge(&st->l2.ui_queue);
 	st->l2.tei = -1;
-	L2L3(st, DL_RELEASE | INDICATION, NULL);
+	st->l2.l2l3(st, DL_RELEASE | INDICATION, NULL);
 	FsmChangeState(fi, ST_L2_1);
 }
 
@@ -1424,7 +1437,7 @@ l2_st6_tei_remove(struct FsmInst *fi, in
 	skb_queue_purge(&st->l2.ui_queue);
 	st->l2.tei = -1;
 	stop_t200(st, 18);
-	L2L3(st, DL_RELEASE | CONFIRM, NULL);
+	st->l2.l2l3(st, DL_RELEASE | CONFIRM, NULL);
 	FsmChangeState(fi, ST_L2_1);
 }
 
@@ -1439,23 +1452,23 @@ l2_tei_remove(struct FsmInst *fi, int ev
 	st->l2.tei = -1;
 	stop_t200(st, 17);
 	FsmDelTimer(&st->l2.t203, 19);
-	L2L3(st, DL_RELEASE | INDICATION, NULL);
+	st->l2.l2l3(st, DL_RELEASE | INDICATION, NULL);
 	FsmChangeState(fi, ST_L2_1);
 }
 
 static void
-l2_st14_persistent_da(struct FsmInst *fi, int event, void *arg)
+l2_st14_persistant_da(struct FsmInst *fi, int event, void *arg)
 {
 	struct PStack *st = fi->userdata;
 	
 	skb_queue_purge(&st->l2.i_queue);
 	skb_queue_purge(&st->l2.ui_queue);
 	if (test_and_clear_bit(FLG_ESTAB_PEND, &st->l2.flag))
-		L2L3(st, DL_RELEASE | INDICATION, NULL);
+		st->l2.l2l3(st, DL_RELEASE | INDICATION, NULL);
 }
 
 static void
-l2_st5_persistent_da(struct FsmInst *fi, int event, void *arg)
+l2_st5_persistant_da(struct FsmInst *fi, int event, void *arg)
 {
 	struct PStack *st = fi->userdata;
 
@@ -1468,18 +1481,18 @@ l2_st5_persistent_da(struct FsmInst *fi,
 }
 
 static void
-l2_st6_persistent_da(struct FsmInst *fi, int event, void *arg)
+l2_st6_persistant_da(struct FsmInst *fi, int event, void *arg)
 {
 	struct PStack *st = fi->userdata;
 
 	skb_queue_purge(&st->l2.ui_queue);
 	stop_t200(st, 20);
-	L2L3(st, DL_RELEASE | CONFIRM, NULL);
+	st->l2.l2l3(st, DL_RELEASE | CONFIRM, NULL);
 	FsmChangeState(fi, ST_L2_4);
 }
 
 static void
-l2_persistent_da(struct FsmInst *fi, int event, void *arg)
+l2_persistant_da(struct FsmInst *fi, int event, void *arg)
 {
 	struct PStack *st = fi->userdata;
 
@@ -1488,7 +1501,7 @@ l2_persistent_da(struct FsmInst *fi, int
 	freewin(st);
 	stop_t200(st, 19);
 	FsmDelTimer(&st->l2.t203, 19);
-	L2L3(st, DL_RELEASE | INDICATION, NULL);
+	st->l2.l2l3(st, DL_RELEASE | INDICATION, NULL);
 	FsmChangeState(fi, ST_L2_4);
 }
 
@@ -1614,14 +1627,14 @@ static struct FsmNode L2FnList[] __initd
 	{ST_L2_6, EV_L2_FRAME_ERROR, l2_frame_error},
 	{ST_L2_7, EV_L2_FRAME_ERROR, l2_frame_error_reest},
 	{ST_L2_8, EV_L2_FRAME_ERROR, l2_frame_error_reest},
-	{ST_L2_1, EV_L1_DEACTIVATE, l2_st14_persistent_da},
+	{ST_L2_1, EV_L1_DEACTIVATE, l2_st14_persistant_da},
 	{ST_L2_2, EV_L1_DEACTIVATE, l2_st24_tei_remove},
 	{ST_L2_3, EV_L1_DEACTIVATE, l2_st3_tei_remove},
-	{ST_L2_4, EV_L1_DEACTIVATE, l2_st14_persistent_da},
-	{ST_L2_5, EV_L1_DEACTIVATE, l2_st5_persistent_da},
-	{ST_L2_6, EV_L1_DEACTIVATE, l2_st6_persistent_da},
-	{ST_L2_7, EV_L1_DEACTIVATE, l2_persistent_da},
-	{ST_L2_8, EV_L1_DEACTIVATE, l2_persistent_da},
+	{ST_L2_4, EV_L1_DEACTIVATE, l2_st14_persistant_da},
+	{ST_L2_5, EV_L1_DEACTIVATE, l2_st5_persistant_da},
+	{ST_L2_6, EV_L1_DEACTIVATE, l2_st6_persistant_da},
+	{ST_L2_7, EV_L1_DEACTIVATE, l2_persistant_da},
+	{ST_L2_8, EV_L1_DEACTIVATE, l2_persistant_da},
 };
 
 #define L2_FN_COUNT (sizeof(L2FnList)/sizeof(struct FsmNode))
@@ -1630,8 +1643,8 @@ static void
 isdnl2_l1l2(struct PStack *st, int pr, void *arg)
 {
 	struct sk_buff *skb = arg;
-	u8 *datap;
-	u_int ret = 1, len;
+	u_char *datap;
+	int ret = 1, len;
 	int c = 0;
 
 	switch (pr) {
@@ -1682,9 +1695,6 @@ isdnl2_l1l2(struct PStack *st, int pr, v
 			if (ret)
 				FreeSkb(skb);
 			break;
-		case (PH_DATA | CONFIRM):
-			dev_kfree_skb(skb);
-			break;
 		case (PH_PULL | CONFIRM):
 			FsmEvent(&st->l2.l2m, EV_L2_ACK_PULL, arg);
 			break;
@@ -1736,12 +1746,12 @@ isdnl2_l3l2(struct PStack *st, int pr, v
 					test_bit(FLG_ORIG, &st->l2.flag)) {
 					test_and_set_bit(FLG_ESTAB_PEND, &st->l2.flag);
 				}
-				L2L1(st, PH_ACTIVATE, NULL);
+				st->l2.l2l1(st, PH_ACTIVATE, NULL);
 			}
 			break;
 		case (DL_RELEASE | REQUEST):
 			if (test_bit(FLG_LAPB, &st->l2.flag)) {
-				L2L1(st, PH_DEACTIVATE, NULL);
+				st->l2.l2l1(st, PH_DEACTIVATE, NULL);
 			}
 			FsmEvent(&st->l2.l2m, EV_L2_DL_RELEASE_REQ, arg);
 			break;
@@ -1781,8 +1791,9 @@ l2m_debug(struct FsmInst *fi, char *fmt,
 void
 setstack_isdnl2(struct PStack *st, char *debug_id)
 {
-	st->l2.l1l2 = isdnl2_l1l2;
-	st->l2.l3l2 = isdnl2_l3l2;
+	spin_lock_init(&st->l2.lock);
+	st->l1.l1l2 = isdnl2_l1l2;
+	st->l3.l3l2 = isdnl2_l3l2;
 
 	skb_queue_head_init(&st->l2.i_queue);
 	skb_queue_head_init(&st->l2.ui_queue);
@@ -1810,13 +1821,13 @@ transl2_l3l2(struct PStack *st, int pr, 
 	switch (pr) {
 		case (DL_DATA | REQUEST):
 		case (DL_UNIT_DATA | REQUEST):
-			L2L1(st, PH_DATA | REQUEST, arg);
+			st->l2.l2l1(st, PH_DATA | REQUEST, arg);
 			break;
 		case (DL_ESTABLISH | REQUEST):
-			L2L1(st, PH_ACTIVATE | REQUEST, NULL);
+			st->l2.l2l1(st, PH_ACTIVATE | REQUEST, NULL);
 			break;
 		case (DL_RELEASE | REQUEST):
-			L2L1(st, PH_DEACTIVATE | REQUEST, NULL);
+			st->l2.l2l1(st, PH_DEACTIVATE | REQUEST, NULL);
 			break;
 	}
 }
@@ -1824,7 +1835,7 @@ transl2_l3l2(struct PStack *st, int pr, 
 void
 setstack_transl2(struct PStack *st)
 {
-	st->l2.l3l2 = transl2_l3l2;
+	st->l3.l3l2 = transl2_l3l2;
 }
 
 void
--- diff/drivers/isdn/hisax/isdnl3.c	2003-01-13 14:18:15.000000000 +0000
+++ source/drivers/isdn/hisax/isdnl3.c	2004-02-23 13:56:42.000000000 +0000
@@ -1,4 +1,4 @@
-/* $Id: isdnl3.c,v 2.17.6.5 2001/09/23 22:24:49 kai Exp $
+/* $Id: isdnl3.c,v 2.22.2.3 2004/01/13 14:31:25 keil Exp $
  *
  * Author       Karsten Keil
  *              based on the teles driver from Jan den Ouden
@@ -20,7 +20,7 @@
 #include "isdnl3.h"
 #include <linux/config.h>
 
-const char *l3_revision = "$Revision: 2.17.6.5 $";
+const char *l3_revision = "$Revision: 2.22.2.3 $";
 
 static struct Fsm l3fsm;
 
@@ -77,11 +77,11 @@ l3m_debug(struct FsmInst *fi, char *fmt,
 	va_end(args);
 }
 
-u8 *
-findie(u8 * p, int size, u8 ie, int wanted_set)
+u_char *
+findie(u_char * p, int size, u_char ie, int wanted_set)
 {
 	int l, codeset, maincodeset;
-	u8 *pend = p + size;
+	u_char *pend = p + size;
 
 	/* skip protocol discriminator, callref and message type */
 	p++;
@@ -123,7 +123,7 @@ findie(u8 * p, int size, u8 ie, int want
 }
 
 int
-getcallref(u8 * p)
+getcallref(u_char * p)
 {
 	int l, cr = 0;
 
@@ -162,7 +162,7 @@ newl3state(struct l3_process *pc, int st
 static void
 L3ExpireTimer(struct L3Timer *t)
 {
-	t->pc->st->l3.l4l3(t->pc->st, t->event, t->pc);
+	t->pc->st->lli.l4l3(t->pc->st, t->event, t->pc);
 }
 
 void
@@ -354,7 +354,7 @@ setstack_l3dc(struct PStack *st, struct 
 	st->l3.l3m.printdebug = l3m_debug;
         FsmInitTimer(&st->l3.l3m, &st->l3.l3m_timer);
 	strcpy(st->l3.debug_id, "L3DC ");
-	st->l3.l4l3_proto = no_l3_proto_spec;
+	st->lli.l4l3_proto = no_l3_proto_spec;
 
 #ifdef	CONFIG_HISAX_EURO
 	if (st->protocol == ISDN_PTYPE_EURO) {
@@ -372,13 +372,13 @@ setstack_l3dc(struct PStack *st, struct 
 	} else
 #endif
 	if (st->protocol == ISDN_PTYPE_LEASED) {
-		st->l3.l4l3 = no_l3_proto;
-		st->l3.l2l3 = no_l3_proto;
+		st->lli.l4l3 = no_l3_proto;
+		st->l2.l2l3 = no_l3_proto;
                 st->l3.l3ml3 = no_l3_proto;
 		printk(KERN_INFO "HiSax: Leased line mode\n");
 	} else {
-		st->l3.l4l3 = no_l3_proto;
-		st->l3.l2l3 = no_l3_proto;
+		st->lli.l4l3 = no_l3_proto;
+		st->l2.l2l3 = no_l3_proto;
                 st->l3.l3ml3 = no_l3_proto;
 		sprintf(tmp, "protocol %s not supported",
 			(st->protocol == ISDN_PTYPE_1TR6) ? "1tr6" :
@@ -392,7 +392,7 @@ setstack_l3dc(struct PStack *st, struct 
 
 void
 isdnl3_trans(struct PStack *st, int pr, void *arg) {
-	L3L2(st, pr, arg);
+	st->l3.l3l2(st, pr, arg);
 }
 
 void
@@ -423,7 +423,7 @@ setstack_l3bc(struct PStack *st, struct 
 	st->l3.l3m.userint = 0;
 	st->l3.l3m.printdebug = l3m_debug;
 	strcpy(st->l3.debug_id, "L3BC ");
-	st->l3.l4l3 = isdnl3_trans;
+	st->lli.l4l3 = isdnl3_trans;
 }
 
 #define DREL_TIMER_VALUE 40000
@@ -434,7 +434,7 @@ lc_activate(struct FsmInst *fi, int even
 	struct PStack *st = fi->userdata;
 
 	FsmChangeState(fi, ST_L3_LC_ESTAB_WAIT);
-	L3L2(st, DL_ESTABLISH | REQUEST, NULL);
+	st->l3.l3l2(st, DL_ESTABLISH | REQUEST, NULL);
 }
 
 static void
@@ -446,7 +446,7 @@ lc_connect(struct FsmInst *fi, int event
 
 	FsmChangeState(fi, ST_L3_LC_ESTAB);
 	while ((skb = skb_dequeue(&st->l3.squeue))) {
-		L3L2(st, DL_DATA | REQUEST, skb);
+		st->l3.l3l2(st, DL_DATA | REQUEST, skb);
 		dequeued++;
 	}
 	if ((!st->l3.proc) &&  dequeued) {
@@ -467,7 +467,7 @@ lc_connected(struct FsmInst *fi, int eve
 	FsmDelTimer(&st->l3.l3m_timer, 51);
 	FsmChangeState(fi, ST_L3_LC_ESTAB);
 	while ((skb = skb_dequeue(&st->l3.squeue))) {
-		L3L2(st, DL_DATA | REQUEST, skb);
+		st->l3.l3l2(st, DL_DATA | REQUEST, skb);
 		dequeued++;
 	}
 	if ((!st->l3.proc) &&  dequeued) {
@@ -511,7 +511,7 @@ lc_release_req(struct FsmInst *fi, int e
 		FsmAddTimer(&st->l3.l3m_timer, DREL_TIMER_VALUE, EV_TIMEOUT, NULL, 51);
 	} else {
 		FsmChangeState(fi, ST_L3_LC_REL_WAIT);
-		L3L2(st, DL_RELEASE | REQUEST, NULL);
+		st->l3.l3l2(st, DL_RELEASE | REQUEST, NULL);
 	}
 }
 
@@ -564,7 +564,7 @@ l3_msg(struct PStack *st, int pr, void *
 	switch (pr) {
 		case (DL_DATA | REQUEST):
 			if (st->l3.l3m.state == ST_L3_LC_ESTAB) {
-				L3L2(st, pr, arg);
+				st->l3.l3l2(st, pr, arg);
 			} else {
 				struct sk_buff *skb = arg;
 
--- diff/drivers/isdn/hisax/isurf.c	2003-07-22 18:54:27.000000000 +0100
+++ source/drivers/isdn/hisax/isurf.c	2004-02-23 13:56:42.000000000 +0000
@@ -1,4 +1,4 @@
-/* $Id: isurf.c,v 1.10.6.2 2001/09/23 22:24:49 kai Exp $
+/* $Id: isurf.c,v 1.12.2.4 2004/01/13 21:46:03 keil Exp $
  *
  * low level stuff for Siemens I-Surf/I-Talk cards
  *
@@ -19,7 +19,7 @@
 
 extern const char *CardType[];
 
-static const char *ISurf_revision = "$Revision: 1.10.6.2 $";
+static const char *ISurf_revision = "$Revision: 1.12.2.4 $";
 
 #define byteout(addr,val) outb(val,addr)
 #define bytein(addr) inb(addr)
@@ -35,20 +35,20 @@ static const char *ISurf_revision = "$Re
 #define ISURF_IOMEM_SIZE	0x400
 /* Interface functions */
 
-static u8
-ReadISAC(struct IsdnCardState *cs, u8 offset)
+static u_char
+ReadISAC(struct IsdnCardState *cs, u_char offset)
 {
 	return (readb(cs->hw.isurf.isac + offset));
 }
 
 static void
-WriteISAC(struct IsdnCardState *cs, u8 offset, u8 value)
+WriteISAC(struct IsdnCardState *cs, u_char offset, u_char value)
 {
 	writeb(value, cs->hw.isurf.isac + offset); mb();
 }
 
 static void
-ReadISACfifo(struct IsdnCardState *cs, u8 * data, int size)
+ReadISACfifo(struct IsdnCardState *cs, u_char * data, int size)
 {
 	register int i;
 	for (i = 0; i < size; i++)
@@ -56,7 +56,7 @@ ReadISACfifo(struct IsdnCardState *cs, u
 }
 
 static void
-WriteISACfifo(struct IsdnCardState *cs, u8 * data, int size)
+WriteISACfifo(struct IsdnCardState *cs, u_char * data, int size)
 {
 	register int i;
 	for (i = 0; i < size; i++){
@@ -64,44 +64,33 @@ WriteISACfifo(struct IsdnCardState *cs, 
 	}
 }
 
-static struct dc_hw_ops isac_ops = {
-	.read_reg   = ReadISAC,
-	.write_reg  = WriteISAC,
-	.read_fifo  = ReadISACfifo,
-	.write_fifo = WriteISACfifo,
-};
-
 /* ISAR access routines
  * mode = 0 access with IRQ on
  * mode = 1 access with IRQ off
  * mode = 2 access with IRQ off and using last offset
  */
   
-static u8
-ReadISAR(struct IsdnCardState *cs, int mode, u8 offset)
+static u_char
+ReadISAR(struct IsdnCardState *cs, int mode, u_char offset)
 {	
 	return(readb(cs->hw.isurf.isar + offset));
 }
 
 static void
-WriteISAR(struct IsdnCardState *cs, int mode, u8 offset, u8 value)
+WriteISAR(struct IsdnCardState *cs, int mode, u_char offset, u_char value)
 {
 	writeb(value, cs->hw.isurf.isar + offset);mb();
 }
 
-static struct bc_hw_ops isar_ops = {
-	.read_reg  = ReadISAR,
-	.write_reg = WriteISAR,
-};
-
 static irqreturn_t
 isurf_interrupt(int intno, void *dev_id, struct pt_regs *regs)
 {
 	struct IsdnCardState *cs = dev_id;
-	u8 val;
+	u_char val;
 	int cnt = 5;
+	u_long flags;
 
-	spin_lock(&cs->lock);
+	spin_lock_irqsave(&cs->lock, flags);
 	val = readb(cs->hw.isurf.isar + ISAR_IRQBIT);
       Start_ISAR:
 	if (val & ISAR_IRQSTA)
@@ -129,151 +118,190 @@ isurf_interrupt(int intno, void *dev_id,
 	writeb(0xFF, cs->hw.isurf.isac + ISAC_MASK);mb();
 	writeb(0, cs->hw.isurf.isac + ISAC_MASK);mb();
 	writeb(ISAR_IRQMSK, cs->hw.isurf.isar + ISAR_IRQBIT); mb();
-	spin_unlock(&cs->lock);
+	spin_unlock_irqrestore(&cs->lock, flags);
 	return IRQ_HANDLED;
 }
 
+void
+release_io_isurf(struct IsdnCardState *cs)
+{
+	release_region(cs->hw.isurf.reset, 1);
+	iounmap((unsigned char *)cs->hw.isurf.isar);
+	release_mem_region(cs->hw.isurf.phymem, ISURF_IOMEM_SIZE);
+}
+
 static void
-reset_isurf(struct IsdnCardState *cs, u8 chips)
+reset_isurf(struct IsdnCardState *cs, u_char chips)
 {
 	printk(KERN_INFO "ISurf: resetting card\n");
 
 	byteout(cs->hw.isurf.reset, chips); /* Reset On */
-	set_current_state(TASK_UNINTERRUPTIBLE);
-	schedule_timeout((10*HZ)/1000);
+	mdelay(10);
 	byteout(cs->hw.isurf.reset, ISURF_ISAR_EA); /* Reset Off */
-	set_current_state(TASK_UNINTERRUPTIBLE);
-	schedule_timeout((10*HZ)/1000);
+	mdelay(10);
+}
+
+static int
+ISurf_card_msg(struct IsdnCardState *cs, int mt, void *arg)
+{
+	u_long flags;
+
+	switch (mt) {
+		case CARD_RESET:
+			spin_lock_irqsave(&cs->lock, flags);
+			reset_isurf(cs, ISURF_RESET);
+			spin_unlock_irqrestore(&cs->lock, flags);
+			return(0);
+		case CARD_RELEASE:
+			release_io_isurf(cs);
+			return(0);
+		case CARD_INIT:
+			spin_lock_irqsave(&cs->lock, flags);
+			reset_isurf(cs, ISURF_RESET);
+			clear_pending_isac_ints(cs);
+			writeb(0, cs->hw.isurf.isar+ISAR_IRQBIT);mb();
+			initisac(cs);
+			initisar(cs);
+			/* Reenable ISAC IRQ */
+			cs->writeisac(cs, ISAC_MASK, 0);
+			/* RESET Receiver and Transmitter */
+			cs->writeisac(cs, ISAC_CMDR, 0x41);
+			spin_unlock_irqrestore(&cs->lock, flags);
+			return(0);
+		case CARD_TEST:
+			return(0);
+	}
+	return(0);
 }
 
 static int
 isurf_auxcmd(struct IsdnCardState *cs, isdn_ctrl *ic) {
 	int ret;
+	u_long flags;
 
 	if ((ic->command == ISDN_CMD_IOCTL) && (ic->arg == 9)) {
 		ret = isar_auxcmd(cs, ic);
+		spin_lock_irqsave(&cs->lock, flags);
 		if (!ret) {
 			reset_isurf(cs, ISURF_ISAR_EA | ISURF_ISAC_RESET |
 				ISURF_ARCOFI_RESET);
 			initisac(cs);
+			cs->writeisac(cs, ISAC_MASK, 0);
+			cs->writeisac(cs, ISAC_CMDR, 0x41);
 		}
+		spin_unlock_irqrestore(&cs->lock, flags);
 		return(ret);
 	}
 	return(isar_auxcmd(cs, ic));
 }
 
-static void
-isurf_init(struct IsdnCardState *cs)
-{
-	writeb(0, cs->hw.isurf.isar + ISAR_IRQBIT);
-	initisac(cs);
-	initisar(cs);
-}
-
-static int
-isurf_reset(struct IsdnCardState *cs)
-{
-	reset_isurf(cs, ISURF_RESET);
-	return 0;
-}
-
-static struct card_ops isurf_ops = {
-	.init     = isurf_init,
-	.reset    = isurf_reset,
-	.release  = hisax_release_resources,
-	.irq_func = isurf_interrupt,
-};
-
 #ifdef __ISAPNP__
-static struct pnp_card *pnp_surf __devinitdata = NULL;
+static struct pnp_card *pnp_c __initdata = NULL;
 #endif
 
-static int __init
-isurf_probe(struct IsdnCardState *cs, struct IsdnCard *card)
-{
-	unsigned long phymem;
-
-	phymem = card->para[2];
-	cs->hw.isurf.reset = card->para[1];
-	cs->irq = card->para[0];
-
-	if (!request_io(&cs->rs, cs->hw.isurf.reset, 1, "isurf isdn"))
-		goto err;
-
-	cs->hw.isurf.isar = request_mmio(&cs->rs, phymem, ISURF_IOMEM_SIZE,
-					 "isurf iomem");
-	if (!cs->hw.isurf.isar)
-		goto err;
-
-	cs->hw.isurf.isac = cs->hw.isurf.isar + ISURF_ISAC_OFFSET;
-	printk(KERN_INFO "ISurf: defined at 0x%x 0x%lx IRQ %d\n",
-	       cs->hw.isurf.reset, phymem, cs->irq);
-
-	cs->auxcmd = &isurf_auxcmd;
-	cs->card_ops = &isurf_ops;
-	cs->bcs[0].hw.isar.reg = &cs->hw.isurf.isar_r;
-	cs->bcs[1].hw.isar.reg = &cs->hw.isurf.isar_r;
-	reset_isurf(cs, ISURF_RESET);
-	__set_bit(HW_ISAR, &cs->HW_Flags);
-	isac_setup(cs, &isac_ops);
-	if (isar_setup(cs, &isar_ops))
-		goto err;
-	return 0;
- err:
-	hisax_release_resources(cs);
-	return -EBUSY;
-}
-
 int __init
 setup_isurf(struct IsdnCard *card)
 {
+	int ver;
+	struct IsdnCardState *cs = card->cs;
 	char tmp[64];
 
 	strcpy(tmp, ISurf_revision);
 	printk(KERN_INFO "HiSax: ISurf driver Rev. %s\n", HiSax_getrev(tmp));
 	
+ 	if (cs->typ != ISDN_CTYPE_ISURF)
+ 		return(0);
+	if (card->para[1] && card->para[2]) {
+		cs->hw.isurf.reset = card->para[1];
+		cs->hw.isurf.phymem = card->para[2];
+		cs->irq = card->para[0];
+	} else {
 #ifdef __ISAPNP__
-	if (!card->para[1] || !card->para[2]) {
-		struct pnp_card *pb;
-		struct pnp_dev *pd;
-	
-		card->cs->subtyp = 0;
-		if ((pb = pnp_find_card(
-			     ISAPNP_VENDOR('S', 'I', 'E'),
-			     ISAPNP_FUNCTION(0x0010), pnp_surf))) {
-			pnp_surf = pb;
-			pd = NULL;
-			if (!(pd = pnp_find_dev(pnp_surf,
-						ISAPNP_VENDOR('S', 'I', 'E'),
-						ISAPNP_FUNCTION(0x0010), pd))) {
-				printk(KERN_ERR "ISurfPnP: PnP error card found, no device\n");
-				return (0);
-			}
-			if (pnp_device_attach(pd) < 0) {
-				printk(KERN_ERR "ISurfPnP: attach failed\n");
-				return 0;
-			}
-			if (pnp_activate_dev(pd) < 0) {
-				printk(KERN_ERR "ISurfPnP: activate failed\n");
-				pnp_device_detach(pd);
-				return 0;
-			}
-			if (!pnp_irq_valid(pd, 0) || !pnp_port_valid(pd, 0) || !pnp_port_valid(pd, 1)) {
-				printk(KERN_ERR "ISurfPnP:some resources are missing %ld/%lx/%lx\n",
-				       pnp_irq(pd, 0), pnp_port_start(pd, 0), pnp_port_start(pd, 1));
-				pnp_device_detach(pd);
+		if (isapnp_present()) {
+			struct pnp_dev *pnp_d = NULL;
+			int err;
+
+			cs->subtyp = 0;
+			if ((pnp_c = pnp_find_card(
+				ISAPNP_VENDOR('S', 'I', 'E'),
+				ISAPNP_FUNCTION(0x0010), pnp_c))) {
+				if (!(pnp_d = pnp_find_dev(pnp_c,
+					ISAPNP_VENDOR('S', 'I', 'E'),
+					ISAPNP_FUNCTION(0x0010), pnp_d))) {
+					printk(KERN_ERR "ISurfPnP: PnP error card found, no device\n");
+					return (0);
+				}
+				pnp_disable_dev(pnp_d);
+				err = pnp_activate_dev(pnp_d);
+				cs->hw.isurf.reset = pnp_port_start(pnp_d, 0);
+				cs->hw.isurf.phymem = pnp_mem_start(pnp_d, 1);
+				cs->irq = pnp_irq(pnp_d, 0);
+				if (!cs->irq || !cs->hw.isurf.reset || !cs->hw.isurf.phymem) {
+					printk(KERN_ERR "ISurfPnP:some resources are missing %d/%x/%lx\n",
+						cs->irq, cs->hw.isurf.reset, cs->hw.isurf.phymem);
+					pnp_disable_dev(pnp_d);
+					return(0);
+				}
+			} else {
+				printk(KERN_INFO "ISurfPnP: no ISAPnP card found\n");
 				return(0);
 			}
-			card->para[1] = pnp_port_start(pd, 0);
-			card->para[2] = pnp_port_start(pd, 1);
-			card->para[0] = pnp_irq(pd, 0);
 		} else {
-			printk(KERN_INFO "ISurfPnP: no ISAPnP card found\n");
-			return 0;
+			printk(KERN_INFO "ISurfPnP: no ISAPnP bus found\n");
+			return(0);
 		}
-	}
+#else
+		printk(KERN_WARNING "HiSax: %s port/mem not set\n",
+			CardType[card->typ]);
+		return (0);
 #endif
-	if (isurf_probe(card->cs, card) < 0)
-		return 0;
-	return 1;
+	}
+	if (!request_region(cs->hw.isurf.reset, 1, "isurf isdn")) {
+		printk(KERN_WARNING
+			"HiSax: %s config port %x already in use\n",
+			CardType[card->typ],
+			cs->hw.isurf.reset);
+			return (0);
+	}
+	if (!request_region(cs->hw.isurf.phymem, ISURF_IOMEM_SIZE, "isurf iomem")) {
+		printk(KERN_WARNING
+			"HiSax: %s memory region %lx-%lx already in use\n",
+			CardType[card->typ],
+			cs->hw.isurf.phymem,
+			cs->hw.isurf.phymem + ISURF_IOMEM_SIZE);
+		release_region(cs->hw.isurf.reset, 1);
+		return (0);
+	}
+	cs->hw.isurf.isar =
+		(unsigned long) ioremap(cs->hw.isurf.phymem, ISURF_IOMEM_SIZE);
+	cs->hw.isurf.isac = cs->hw.isurf.isar + ISURF_ISAC_OFFSET;
+	printk(KERN_INFO
+	       "ISurf: defined at 0x%x 0x%lx IRQ %d\n",
+	       cs->hw.isurf.reset,
+	       cs->hw.isurf.phymem,
+	       cs->irq);
+
+	setup_isac(cs);
+	cs->cardmsg = &ISurf_card_msg;
+	cs->irq_func = &isurf_interrupt;
+	cs->auxcmd = &isurf_auxcmd;
+	cs->readisac = &ReadISAC;
+	cs->writeisac = &WriteISAC;
+	cs->readisacfifo = &ReadISACfifo;
+	cs->writeisacfifo = &WriteISACfifo;
+	cs->bcs[0].hw.isar.reg = &cs->hw.isurf.isar_r;
+	cs->bcs[1].hw.isar.reg = &cs->hw.isurf.isar_r;
+	test_and_set_bit(HW_ISAR, &cs->HW_Flags);
+	ISACVersion(cs, "ISurf:");
+	cs->BC_Read_Reg = &ReadISAR;
+	cs->BC_Write_Reg = &WriteISAR;
+	cs->BC_Send_Data = &isar_fill_fifo;
+	ver = ISARVersion(cs, "ISurf:");
+	if (ver < 0) {
+		printk(KERN_WARNING
+			"ISurf: wrong ISAR version (ret = %d)\n", ver);
+		release_io_isurf(cs);
+		return (0);
+	}
+	return (1);
 }
--- diff/drivers/isdn/hisax/ix1_micro.c	2003-05-21 11:49:50.000000000 +0100
+++ source/drivers/isdn/hisax/ix1_micro.c	2004-02-23 13:56:42.000000000 +0000
@@ -1,4 +1,4 @@
-/* $Id: ix1_micro.c,v 2.10.6.2 2001/09/23 22:24:49 kai Exp $
+/* $Id: ix1_micro.c,v 2.12.2.4 2004/01/13 23:48:39 keil Exp $
  *
  * low level stuff for ITK ix1-micro Rev.2 isdn cards
  * derived from the original file teles3.c from Karsten Keil
@@ -25,8 +25,7 @@
 #include "isdnl1.h"
 
 extern const char *CardType[];
-const char *ix1_revision = "$Revision: 2.10.6.2 $";
-static spinlock_t ix1_micro_lock = SPIN_LOCK_UNLOCKED;
+const char *ix1_revision = "$Revision: 2.12.2.4 $";
 
 #define byteout(addr,val) outb(val,addr)
 #define bytein(addr) inb(addr)
@@ -40,107 +39,137 @@ static spinlock_t ix1_micro_lock = SPIN_
 
 #define TIMEOUT 50
 
-static inline u8
-readreg(struct IsdnCardState *cs, unsigned int adr, u8 off)
+static inline u_char
+readreg(unsigned int ale, unsigned int adr, u_char off)
 {
-	u8 ret;
-	unsigned long flags;
+	register u_char ret;
 
-	spin_lock_irqsave(&ix1_micro_lock, flags);
-	byteout(cs->hw.ix1.isac_ale, off);
+	byteout(ale, off);
 	ret = bytein(adr);
-	spin_unlock_irqrestore(&ix1_micro_lock, flags);
 	return (ret);
 }
 
 static inline void
-writereg(struct IsdnCardState *cs, unsigned int adr, u8 off, u8 data)
+readfifo(unsigned int ale, unsigned int adr, u_char off, u_char * data, int size)
 {
-	unsigned long flags;
-
-	spin_lock_irqsave(&ix1_micro_lock, flags);
-	byteout(cs->hw.ix1.isac_ale, off);
-	byteout(adr, data);
-	spin_unlock_irqrestore(&ix1_micro_lock, flags);
+	byteout(ale, off);
+	insb(adr, data, size);
 }
 
+
 static inline void
-readfifo(struct IsdnCardState *cs, unsigned int adr, u8 off, u8 * data, int size)
+writereg(unsigned int ale, unsigned int adr, u_char off, u_char data)
 {
-	byteout(cs->hw.ix1.isac_ale, off);
-	insb(adr, data, size);
+	byteout(ale, off);
+	byteout(adr, data);
 }
 
 static inline void
-writefifo(struct IsdnCardState *cs, unsigned int adr, u8 off, u8 * data, int size)
+writefifo(unsigned int ale, unsigned int adr, u_char off, u_char * data, int size)
 {
-	byteout(cs->hw.ix1.isac_ale, off);
+	byteout(ale, off);
 	outsb(adr, data, size);
 }
 
-static u8
-isac_read(struct IsdnCardState *cs, u8 offset)
+/* Interface functions */
+
+static u_char
+ReadISAC(struct IsdnCardState *cs, u_char offset)
 {
-	return readreg(cs, cs->hw.ix1.isac, offset);
+	return (readreg(cs->hw.ix1.isac_ale, cs->hw.ix1.isac, offset));
 }
 
 static void
-isac_write(struct IsdnCardState *cs, u8 offset, u8 value)
+WriteISAC(struct IsdnCardState *cs, u_char offset, u_char value)
 {
-	writereg(cs, cs->hw.ix1.isac, offset, value);
+	writereg(cs->hw.ix1.isac_ale, cs->hw.ix1.isac, offset, value);
 }
 
 static void
-isac_read_fifo(struct IsdnCardState *cs, u8 * data, int size)
+ReadISACfifo(struct IsdnCardState *cs, u_char * data, int size)
 {
-	readfifo(cs, cs->hw.ix1.isac, 0, data, size);
+	readfifo(cs->hw.ix1.isac_ale, cs->hw.ix1.isac, 0, data, size);
 }
 
 static void
-isac_write_fifo(struct IsdnCardState *cs, u8 * data, int size)
+WriteISACfifo(struct IsdnCardState *cs, u_char * data, int size)
 {
-	writefifo(cs, cs->hw.ix1.isac, 0, data, size);
+	writefifo(cs->hw.ix1.isac_ale, cs->hw.ix1.isac, 0, data, size);
 }
 
-static struct dc_hw_ops isac_ops = {
-	.read_reg   = isac_read,
-	.write_reg  = isac_write,
-	.read_fifo  = isac_read_fifo,
-	.write_fifo = isac_write_fifo,
-};
-
-static u8
-hscx_read(struct IsdnCardState *cs, int hscx, u8 offset)
+static u_char
+ReadHSCX(struct IsdnCardState *cs, int hscx, u_char offset)
 {
-	return readreg(cs, cs->hw.ix1.hscx, offset + (hscx ? 0x40 : 0));
+	return (readreg(cs->hw.ix1.hscx_ale,
+			cs->hw.ix1.hscx, offset + (hscx ? 0x40 : 0)));
 }
 
 static void
-hscx_write(struct IsdnCardState *cs, int hscx, u8 offset, u8 value)
+WriteHSCX(struct IsdnCardState *cs, int hscx, u_char offset, u_char value)
 {
-	writereg(cs, cs->hw.ix1.hscx, offset + (hscx ? 0x40 : 0), value);
+	writereg(cs->hw.ix1.hscx_ale,
+		 cs->hw.ix1.hscx, offset + (hscx ? 0x40 : 0), value);
 }
 
-static void
-hscx_read_fifo(struct IsdnCardState *cs, int hscx, u8 *data, int size)
-{
-	readfifo(cs, cs->hw.ix1.hscx, hscx ? 0x40 : 0, data, size);
+#define READHSCX(cs, nr, reg) readreg(cs->hw.ix1.hscx_ale, \
+		cs->hw.ix1.hscx, reg + (nr ? 0x40 : 0))
+#define WRITEHSCX(cs, nr, reg, data) writereg(cs->hw.ix1.hscx_ale, \
+		cs->hw.ix1.hscx, reg + (nr ? 0x40 : 0), data)
+
+#define READHSCXFIFO(cs, nr, ptr, cnt) readfifo(cs->hw.ix1.hscx_ale, \
+		cs->hw.ix1.hscx, (nr ? 0x40 : 0), ptr, cnt)
+
+#define WRITEHSCXFIFO(cs, nr, ptr, cnt) writefifo(cs->hw.ix1.hscx_ale, \
+		cs->hw.ix1.hscx, (nr ? 0x40 : 0), ptr, cnt)
+
+#include "hscx_irq.c"
+
+static irqreturn_t
+ix1micro_interrupt(int intno, void *dev_id, struct pt_regs *regs)
+{
+	struct IsdnCardState *cs = dev_id;
+	u_char val;
+	u_long flags;
+
+	spin_lock_irqsave(&cs->lock, flags);
+	val = readreg(cs->hw.ix1.hscx_ale, cs->hw.ix1.hscx, HSCX_ISTA + 0x40);
+      Start_HSCX:
+	if (val)
+		hscx_int_main(cs, val);
+	val = readreg(cs->hw.ix1.isac_ale, cs->hw.ix1.isac, ISAC_ISTA);
+      Start_ISAC:
+	if (val)
+		isac_interrupt(cs, val);
+	val = readreg(cs->hw.ix1.hscx_ale, cs->hw.ix1.hscx, HSCX_ISTA + 0x40);
+	if (val) {
+		if (cs->debug & L1_DEB_HSCX)
+			debugl1(cs, "HSCX IntStat after IntRoutine");
+		goto Start_HSCX;
+	}
+	val = readreg(cs->hw.ix1.isac_ale, cs->hw.ix1.isac, ISAC_ISTA);
+	if (val) {
+		if (cs->debug & L1_DEB_ISAC)
+			debugl1(cs, "ISAC IntStat after IntRoutine");
+		goto Start_ISAC;
+	}
+	writereg(cs->hw.ix1.hscx_ale, cs->hw.ix1.hscx, HSCX_MASK, 0xFF);
+	writereg(cs->hw.ix1.hscx_ale, cs->hw.ix1.hscx, HSCX_MASK + 0x40, 0xFF);
+	writereg(cs->hw.ix1.isac_ale, cs->hw.ix1.isac, ISAC_MASK, 0xFF);
+	writereg(cs->hw.ix1.isac_ale, cs->hw.ix1.isac, ISAC_MASK, 0);
+	writereg(cs->hw.ix1.hscx_ale, cs->hw.ix1.hscx, HSCX_MASK, 0);
+	writereg(cs->hw.ix1.hscx_ale, cs->hw.ix1.hscx, HSCX_MASK + 0x40, 0);
+	spin_unlock_irqrestore(&cs->lock, flags);
+	return IRQ_HANDLED;
 }
 
-static void
-hscx_write_fifo(struct IsdnCardState *cs, int hscx, u8 *data, int size)
+void
+release_io_ix1micro(struct IsdnCardState *cs)
 {
-	writefifo(cs, cs->hw.ix1.hscx, hscx ? 0x40 : 0, data, size);
+	if (cs->hw.ix1.cfg_reg)
+		release_region(cs->hw.ix1.cfg_reg, 4);
 }
 
-static struct bc_hw_ops hscx_ops = {
-	.read_reg   = hscx_read,
-	.write_reg  = hscx_write,
-	.read_fifo  = hscx_read_fifo,
-	.write_fifo = hscx_write_fifo,
-};
-
-static int
+static void
 ix1_reset(struct IsdnCardState *cs)
 {
 	int cnt;
@@ -152,37 +181,32 @@ ix1_reset(struct IsdnCardState *cs)
 		HZDELAY(1);	/* wait >=10 ms */
 	}
 	byteout(cs->hw.ix1.cfg_reg + SPECIAL_PORT_OFFSET, 0);
-	return 0;
 }
 
-static struct card_ops ix1_ops = {
-	.init     = inithscxisac,
-	.reset    = ix1_reset,
-	.release  = hisax_release_resources,
-	.irq_func = hscxisac_irq,
-};
-
-static int __init
-ix1_probe(struct IsdnCardState *cs, struct IsdnCard *card)
+static int
+ix1_card_msg(struct IsdnCardState *cs, int mt, void *arg)
 {
-	cs->irq             = card->para[0];
-	cs->hw.ix1.isac_ale = card->para[1] + ISAC_COMMAND_OFFSET;
-	cs->hw.ix1.isac     = card->para[1] + ISAC_DATA_OFFSET;
-	cs->hw.ix1.hscx     = card->para[1] + HSCX_DATA_OFFSET;
-	cs->hw.ix1.cfg_reg  = card->para[1];
-	if (!request_io(&cs->rs, cs->hw.ix1.cfg_reg, 4, "ix1micro cfg"))
-		goto err;
-	
-	printk(KERN_INFO "HiSax: %s config irq:%d io:0x%X\n",
-	       CardType[cs->typ], cs->irq, cs->hw.ix1.cfg_reg);
-	ix1_reset(cs);
-	cs->card_ops = &ix1_ops;
-	if (hscxisac_setup(cs, &isac_ops, &hscx_ops))
-		goto err;
-	return 0;
- err:
-	hisax_release_resources(cs);
-	return -EBUSY;
+	u_long flags;
+
+	switch (mt) {
+		case CARD_RESET:
+			spin_lock_irqsave(&cs->lock, flags);
+			ix1_reset(cs);
+			spin_unlock_irqrestore(&cs->lock, flags);
+			return(0);
+		case CARD_RELEASE:
+			release_io_ix1micro(cs);
+			return(0);
+		case CARD_INIT:
+			spin_lock_irqsave(&cs->lock, flags);
+			ix1_reset(cs);
+			inithscxisac(cs, 3);
+			spin_unlock_irqrestore(&cs->lock, flags);
+			return(0);
+		case CARD_TEST:
+			return(0);
+	}
+	return(0);
 }
 
 #ifdef __ISAPNP__
@@ -196,7 +220,7 @@ static struct isapnp_device_id itk_ids[]
 	{ 0, }
 };
 
-static struct isapnp_device_id *idev = &itk_ids[0];
+static struct isapnp_device_id *ipid __initdata = &itk_ids[0];
 static struct pnp_card *pnp_c __devinitdata = NULL;
 #endif
 
@@ -204,64 +228,91 @@ static struct pnp_card *pnp_c __devinitd
 int __init
 setup_ix1micro(struct IsdnCard *card)
 {
+	struct IsdnCardState *cs = card->cs;
 	char tmp[64];
 
 	strcpy(tmp, ix1_revision);
 	printk(KERN_INFO "HiSax: ITK IX1 driver Rev. %s\n", HiSax_getrev(tmp));
+	if (cs->typ != ISDN_CTYPE_IX1MICROR2)
+		return (0);
 
-	if (card->para[1]) {
-		if (ix1_probe(card->cs, card))
-			return 0;
-		return 1;
-	}
 #ifdef __ISAPNP__
-	if (isapnp_present()) {
-		struct pnp_card *pb;
-		struct pnp_dev *pd;
-
-		while(idev->card_vendor) {
-			if ((pb = pnp_find_card(idev->card_vendor,
-						idev->card_device,
-						pnp_c))) {
-				pnp_c = pb;
-				pd = NULL;
-				if ((pd = pnp_find_dev(pnp_c,
-						       idev->vendor,
-						       idev->function,
-						       pd))) {
+	if (!card->para[1] && isapnp_present()) {
+		struct pnp_dev *pnp_d;
+		while(ipid->card_vendor) {
+			if ((pnp_c = pnp_find_card(ipid->card_vendor,
+				ipid->card_device, pnp_c))) {
+				pnp_d = NULL;
+				if ((pnp_d = pnp_find_dev(pnp_c,
+					ipid->vendor, ipid->function, pnp_d))) {
+					int err;
+
 					printk(KERN_INFO "HiSax: %s detected\n",
-						(char *)idev->driver_data);
-					if (pnp_device_attach(pd) < 0) {
-						printk(KERN_ERR "ITK PnP: attach failed\n");
-						return 0;
-					}
-					if (pnp_activate_dev(pd) < 0) {
-						printk(KERN_ERR "ITK PnP: activate failed\n");
-						pnp_device_detach(pd);
-						return 0;
+						(char *)ipid->driver_data);
+					pnp_disable_dev(pnp_d);
+					err = pnp_activate_dev(pnp_d);
+					if (err<0) {
+						printk(KERN_WARNING "%s: pnp_activate_dev ret(%d)\n",
+							__FUNCTION__, err);
+						return(0);
 					}
-					if (!pnp_port_valid(pd, 0) || !pnp_irq_valid(pd, 0)) {
+					card->para[1] = pnp_port_start(pnp_d, 0);
+					card->para[0] = pnp_irq(pnp_d, 0);
+					if (!card->para[0] || !card->para[1]) {
 						printk(KERN_ERR "ITK PnP:some resources are missing %ld/%lx\n",
-							pnp_irq(pd, 0), pnp_port_start(pd, 0));
-						pnp_device_detach(pd);
+							card->para[0], card->para[1]);
+						pnp_disable_dev(pnp_d);
 						return(0);
 					}
-					card->para[1] = pnp_port_start(pd, 0);
-					card->para[0] = pnp_irq(pd, 0);
-					if (ix1_probe(card->cs, card))
-						return 0;
-					return 1;
+					break;
 				} else {
 					printk(KERN_ERR "ITK PnP: PnP error card found, no device\n");
 				}
 			}
-			idev++;
-			pnp_c=NULL;
+			ipid++;
+			pnp_c = NULL;
 		} 
-		if (!idev->card_vendor) {
+		if (!ipid->card_vendor) {
 			printk(KERN_INFO "ITK PnP: no ISAPnP card found\n");
+			return(0);
 		}
 	}
 #endif
-	return 0;
+	/* IO-Ports */
+	cs->hw.ix1.isac_ale = card->para[1] + ISAC_COMMAND_OFFSET;
+	cs->hw.ix1.hscx_ale = card->para[1] + HSCX_COMMAND_OFFSET;
+	cs->hw.ix1.isac = card->para[1] + ISAC_DATA_OFFSET;
+	cs->hw.ix1.hscx = card->para[1] + HSCX_DATA_OFFSET;
+	cs->hw.ix1.cfg_reg = card->para[1];
+	cs->irq = card->para[0];
+	if (cs->hw.ix1.cfg_reg) {
+		if (!request_region(cs->hw.ix1.cfg_reg, 4, "ix1micro cfg")) {
+			printk(KERN_WARNING
+			  "HiSax: %s config port %x-%x already in use\n",
+			       CardType[card->typ],
+			       cs->hw.ix1.cfg_reg,
+			       cs->hw.ix1.cfg_reg + 4);
+			return (0);
+		}
+	}
+	printk(KERN_INFO "HiSax: %s config irq:%d io:0x%X\n",
+		CardType[cs->typ], cs->irq, cs->hw.ix1.cfg_reg);
+	setup_isac(cs);
+	cs->readisac = &ReadISAC;
+	cs->writeisac = &WriteISAC;
+	cs->readisacfifo = &ReadISACfifo;
+	cs->writeisacfifo = &WriteISACfifo;
+	cs->BC_Read_Reg = &ReadHSCX;
+	cs->BC_Write_Reg = &WriteHSCX;
+	cs->BC_Send_Data = &hscx_fill_fifo;
+	cs->cardmsg = &ix1_card_msg;
+	cs->irq_func = &ix1micro_interrupt;
+	ISACVersion(cs, "ix1-Micro:");
+	if (HscxVersion(cs, "ix1-Micro:")) {
+		printk(KERN_WARNING
+		    "ix1-Micro: wrong HSCX versions check IO address\n");
+		release_io_ix1micro(cs);
+		return (0);
+	}
+	return (1);
 }
--- diff/drivers/isdn/hisax/jade.c	2003-01-16 11:30:36.000000000 +0000
+++ source/drivers/isdn/hisax/jade.c	2004-02-23 13:56:42.000000000 +0000
@@ -1,4 +1,4 @@
-/* $Id: jade.c,v 1.6.6.3 2001/09/23 22:24:49 kai Exp $
+/* $Id: jade.c,v 1.9.2.4 2004/01/14 16:04:48 keil Exp $
  *
  * JADE stuff (derived from original hscx.c)
  *
@@ -18,38 +18,17 @@
 #include "isdnl1.h"
 #include <linux/interrupt.h>
 
-static spinlock_t jade_lock = SPIN_LOCK_UNLOCKED;
 
-static inline u8
-jade_read_reg(struct IsdnCardState *cs, int jade, u8 addr)
-{
-	return cs->bc_hw_ops->read_reg(cs, jade, addr);
-}
-
-static inline void
-jade_write_reg(struct IsdnCardState *cs, int jade, u8 addr, u8 val)
-{
-	cs->bc_hw_ops->write_reg(cs, jade, addr, val);
-}
-
-static inline void
-jade_write_fifo(struct BCState *bcs, u8 *p, int len)
-{
-	struct IsdnCardState *cs = bcs->cs;
-
-	cs->bc_hw_ops->write_fifo(cs, bcs->unit, p, len);
-}
-
-static int
+int __init
 JadeVersion(struct IsdnCardState *cs, char *s)
 {
     int ver,i;
     int to = 50;
-    jade_write_reg(cs, -1, 0x50, 0x19);
+    cs->BC_Write_Reg(cs, -1, 0x50, 0x19);
     i=0;
     while (to) {
     	udelay(1);
-	ver = jade_read_reg(cs, -1, 0x60);
+	ver = cs->BC_Read_Reg(cs, -1, 0x60);
 	to--;
 	if (ver)
     	    break;
@@ -61,39 +40,36 @@ JadeVersion(struct IsdnCardState *cs, ch
     /* Wait for the JADE */
     udelay(10);
     /* Read version */
-    ver = jade_read_reg(cs, -1, 0x60);
+    ver = cs->BC_Read_Reg(cs, -1, 0x60);
     printk(KERN_INFO "%s JADE version: %d\n", s, ver);
     return (1);
 }
 
 /* Write to indirect accessible jade register set */
 static void
-jade_write_indirect(struct IsdnCardState *cs, u8 reg, u8 value)
+jade_write_indirect(struct IsdnCardState *cs, u_char reg, u_char value)
 {
     int to = 50;
-    unsigned long flags;
-    u8 ret;
-    spin_lock_irqsave(&jade_lock, flags);
+    u_char ret;
+
     /* Write the data */
-    jade_write_reg(cs, -1, COMM_JADE+1, value);
+    cs->BC_Write_Reg(cs, -1, COMM_JADE+1, value);
     /* Say JADE we wanna write indirect reg 'reg' */
-    jade_write_reg(cs, -1, COMM_JADE, reg);
+    cs->BC_Write_Reg(cs, -1, COMM_JADE, reg);
     to = 50;
     /* Wait for RDY goes high */
     while (to) {
     	udelay(1);
-	ret = jade_read_reg(cs, -1, COMM_JADE);
+	ret = cs->BC_Read_Reg(cs, -1, COMM_JADE);
 	to--;
 	if (ret & 1)
 	    /* Got acknowledge */
 	    break;
 	if (!to) {
-	    spin_unlock_irqrestore(&jade_lock, flags);
     	    printk(KERN_INFO "Can not see ready bit from JADE DSP (reg=0x%X, value=0x%X)\n", reg, value);
 	    return;
 	}
     }
-    spin_unlock_irqrestore(&jade_lock, flags);
 }
 
 
@@ -102,7 +78,7 @@ void
 modejade(struct BCState *bcs, int mode, int bc)
 {
     struct IsdnCardState *cs = bcs->cs;
-    int jade = bcs->unit;
+    int jade = bcs->hw.hscx.hscx;
 
     if (cs->debug & L1_DEB_HSCX) {
 	char tmp[40];
@@ -113,75 +89,103 @@ modejade(struct BCState *bcs, int mode, 
     bcs->mode = mode;
     bcs->channel = bc;
 	
-    jade_write_reg(cs, jade, jade_HDLC_MODE, (mode == L1_MODE_TRANS ? jadeMODE_TMO:0x00));
-    jade_write_reg(cs, jade, jade_HDLC_CCR0, (jadeCCR0_PU|jadeCCR0_ITF));
-    jade_write_reg(cs, jade, jade_HDLC_CCR1, 0x00);
+    cs->BC_Write_Reg(cs, jade, jade_HDLC_MODE, (mode == L1_MODE_TRANS ? jadeMODE_TMO:0x00));
+    cs->BC_Write_Reg(cs, jade, jade_HDLC_CCR0, (jadeCCR0_PU|jadeCCR0_ITF));
+    cs->BC_Write_Reg(cs, jade, jade_HDLC_CCR1, 0x00);
 
     jade_write_indirect(cs, jade_HDLC1SERRXPATH, 0x08);
     jade_write_indirect(cs, jade_HDLC2SERRXPATH, 0x08);
     jade_write_indirect(cs, jade_HDLC1SERTXPATH, 0x00);
     jade_write_indirect(cs, jade_HDLC2SERTXPATH, 0x00);
 
-    jade_write_reg(cs, jade, jade_HDLC_XCCR, 0x07);
-    jade_write_reg(cs, jade, jade_HDLC_RCCR, 0x07);
+    cs->BC_Write_Reg(cs, jade, jade_HDLC_XCCR, 0x07);
+    cs->BC_Write_Reg(cs, jade, jade_HDLC_RCCR, 0x07);
 
     if (bc == 0) {
-	jade_write_reg(cs, jade, jade_HDLC_TSAX, 0x00);
-	jade_write_reg(cs, jade, jade_HDLC_TSAR, 0x00);
+	cs->BC_Write_Reg(cs, jade, jade_HDLC_TSAX, 0x00);
+	cs->BC_Write_Reg(cs, jade, jade_HDLC_TSAR, 0x00);
     } else {
-	jade_write_reg(cs, jade, jade_HDLC_TSAX, 0x04);
-	jade_write_reg(cs, jade, jade_HDLC_TSAR, 0x04);
+	cs->BC_Write_Reg(cs, jade, jade_HDLC_TSAX, 0x04);
+	cs->BC_Write_Reg(cs, jade, jade_HDLC_TSAR, 0x04);
     }
     switch (mode) {
 	case (L1_MODE_NULL):
-		jade_write_reg(cs, jade, jade_HDLC_MODE, jadeMODE_TMO);
+		cs->BC_Write_Reg(cs, jade, jade_HDLC_MODE, jadeMODE_TMO);
 		break;
 	case (L1_MODE_TRANS):
-		jade_write_reg(cs, jade, jade_HDLC_MODE, (jadeMODE_TMO|jadeMODE_RAC|jadeMODE_XAC));
+		cs->BC_Write_Reg(cs, jade, jade_HDLC_MODE, (jadeMODE_TMO|jadeMODE_RAC|jadeMODE_XAC));
 		break;
 	case (L1_MODE_HDLC):
-		jade_write_reg(cs, jade, jade_HDLC_MODE, (jadeMODE_RAC|jadeMODE_XAC));
+		cs->BC_Write_Reg(cs, jade, jade_HDLC_MODE, (jadeMODE_RAC|jadeMODE_XAC));
 		break;
     }
     if (mode) {
-	jade_write_reg(cs, jade, jade_HDLC_RCMD, (jadeRCMD_RRES|jadeRCMD_RMC));
-	jade_write_reg(cs, jade, jade_HDLC_XCMD, jadeXCMD_XRES);
+	cs->BC_Write_Reg(cs, jade, jade_HDLC_RCMD, (jadeRCMD_RRES|jadeRCMD_RMC));
+	cs->BC_Write_Reg(cs, jade, jade_HDLC_XCMD, jadeXCMD_XRES);
 	/* Unmask ints */
-	jade_write_reg(cs, jade, jade_HDLC_IMR, 0xF8);
+	cs->BC_Write_Reg(cs, jade, jade_HDLC_IMR, 0xF8);
     }
     else
 	/* Mask ints */
-	jade_write_reg(cs, jade, jade_HDLC_IMR, 0x00);
+	cs->BC_Write_Reg(cs, jade, jade_HDLC_IMR, 0x00);
 }
 
 static void
 jade_l2l1(struct PStack *st, int pr, void *arg)
 {
+    struct BCState *bcs = st->l1.bcs;
     struct sk_buff *skb = arg;
+    u_long flags;
 
     switch (pr) {
 	case (PH_DATA | REQUEST):
-		xmit_data_req_b(st->l1.bcs, skb);
+		spin_lock_irqsave(&bcs->cs->lock, flags);
+		if (bcs->tx_skb) {
+			skb_queue_tail(&bcs->squeue, skb);
+		} else {
+			bcs->tx_skb = skb;
+			test_and_set_bit(BC_FLG_BUSY, &bcs->Flag);
+			bcs->hw.hscx.count = 0;
+			bcs->cs->BC_Send_Data(bcs);
+		}
+		spin_unlock_irqrestore(&bcs->cs->lock, flags);
 		break;
 	case (PH_PULL | INDICATION):
-		xmit_pull_ind_b(st->l1.bcs, skb);
+		spin_lock_irqsave(&bcs->cs->lock, flags);
+		if (bcs->tx_skb) {
+			printk(KERN_WARNING "jade_l2l1: this shouldn't happen\n");
+		} else {
+			test_and_set_bit(BC_FLG_BUSY, &bcs->Flag);
+			bcs->tx_skb = skb;
+			bcs->hw.hscx.count = 0;
+			bcs->cs->BC_Send_Data(bcs);
+		}
+		spin_unlock_irqrestore(&bcs->cs->lock, flags);
 		break;
 	case (PH_PULL | REQUEST):
-		xmit_pull_req_b(st);
+		if (!bcs->tx_skb) {
+		    test_and_clear_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
+		    st->l1.l1l2(st, PH_PULL | CONFIRM, NULL);
+		} else
+		    test_and_set_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
 		break;
 	case (PH_ACTIVATE | REQUEST):
-		test_and_set_bit(BC_FLG_ACTIV, &st->l1.bcs->Flag);
-		modejade(st->l1.bcs, st->l1.mode, st->l1.bc);
+		spin_lock_irqsave(&bcs->cs->lock, flags);
+		test_and_set_bit(BC_FLG_ACTIV, &bcs->Flag);
+		modejade(bcs, st->l1.mode, st->l1.bc);
+		spin_unlock_irqrestore(&bcs->cs->lock, flags);
 		l1_msg_b(st, pr, arg);
 		break;
 	case (PH_DEACTIVATE | REQUEST):
 		l1_msg_b(st, pr, arg);
 		break;
 	case (PH_DEACTIVATE | CONFIRM):
-		test_and_clear_bit(BC_FLG_ACTIV, &st->l1.bcs->Flag);
-		test_and_clear_bit(BC_FLG_BUSY, &st->l1.bcs->Flag);
-		modejade(st->l1.bcs, 0, st->l1.bc);
-		L1L2(st, PH_DEACTIVATE | CONFIRM, NULL);
+		spin_lock_irqsave(&bcs->cs->lock, flags);
+		test_and_clear_bit(BC_FLG_ACTIV, &bcs->Flag);
+		test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
+		modejade(bcs, 0, st->l1.bc);
+		spin_unlock_irqrestore(&bcs->cs->lock, flags);
+		st->l1.l1l2(st, PH_DEACTIVATE | CONFIRM, NULL);
 		break;
     }
 }
@@ -189,14 +193,53 @@ jade_l2l1(struct PStack *st, int pr, voi
 void
 close_jadestate(struct BCState *bcs)
 {
-	modejade(bcs, 0, bcs->channel);
-	bc_close(bcs);
+    modejade(bcs, 0, bcs->channel);
+    if (test_and_clear_bit(BC_FLG_INIT, &bcs->Flag)) {
+	if (bcs->hw.hscx.rcvbuf) {
+		kfree(bcs->hw.hscx.rcvbuf);
+		bcs->hw.hscx.rcvbuf = NULL;
+	}
+	if (bcs->blog) {
+		kfree(bcs->blog);
+		bcs->blog = NULL;
+	}
+	skb_queue_purge(&bcs->rqueue);
+	skb_queue_purge(&bcs->squeue);
+	if (bcs->tx_skb) {
+		dev_kfree_skb_any(bcs->tx_skb);
+		bcs->tx_skb = NULL;
+		test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
+	}
+    }
 }
 
 static int
 open_jadestate(struct IsdnCardState *cs, struct BCState *bcs)
 {
-	return bc_open(bcs);;
+	if (!test_and_set_bit(BC_FLG_INIT, &bcs->Flag)) {
+		if (!(bcs->hw.hscx.rcvbuf = kmalloc(HSCX_BUFMAX, GFP_ATOMIC))) {
+			printk(KERN_WARNING
+			       "HiSax: No memory for hscx.rcvbuf\n");
+			test_and_clear_bit(BC_FLG_INIT, &bcs->Flag);
+			return (1);
+		}
+		if (!(bcs->blog = kmalloc(MAX_BLOG_SPACE, GFP_ATOMIC))) {
+			printk(KERN_WARNING
+				"HiSax: No memory for bcs->blog\n");
+			test_and_clear_bit(BC_FLG_INIT, &bcs->Flag);
+			kfree(bcs->hw.hscx.rcvbuf);
+			bcs->hw.hscx.rcvbuf = NULL;
+			return (2);
+		}
+		skb_queue_head_init(&bcs->rqueue);
+		skb_queue_head_init(&bcs->squeue);
+	}
+	bcs->tx_skb = NULL;
+	test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
+	bcs->event = 0;
+	bcs->hw.hscx.rcvidx = 0;
+	bcs->tx_cnt = 0;
+	return (0);
 }
 
 
@@ -207,74 +250,69 @@ setstack_jade(struct PStack *st, struct 
 	if (open_jadestate(st->l1.hardware, bcs))
 		return (-1);
 	st->l1.bcs = bcs;
-	st->l1.l2l1 = jade_l2l1;
+	st->l2.l2l1 = jade_l2l1;
 	setstack_manager(st);
 	bcs->st = st;
 	setstack_l1_B(st);
 	return (0);
 }
 
-static void jade_fill_fifo(struct BCState *bcs);
-
-static struct bc_l1_ops jade_l1_ops = {
-	.fill_fifo = jade_fill_fifo,
-	.open      = setstack_jade,
-	.close     = close_jadestate,
-};
-
 void __init
-initjade(struct IsdnCardState *cs)
+clear_pending_jade_ints(struct IsdnCardState *cs)
 {
 	int val;
+	char tmp[64];
 
-	cs->bc_l1_ops = &jade_l1_ops;
-	cs->bcs[0].unit = 0;
-	cs->bcs[1].unit = 1;
-
-	jade_write_reg(cs, 0, jade_HDLC_IMR, 0x00);
-	jade_write_reg(cs, 1, jade_HDLC_IMR, 0x00);
-
-	val = jade_read_reg(cs, 1, jade_HDLC_ISR);
-	debugl1(cs, "jade B ISTA %x", val);
-	val = jade_read_reg(cs, 0, jade_HDLC_ISR);
-	debugl1(cs, "jade A ISTA %x", val);
-	val = jade_read_reg(cs, 1, jade_HDLC_STAR);
-	debugl1(cs, "jade B STAR %x", val);
-	val = jade_read_reg(cs, 0, jade_HDLC_STAR);
-	debugl1(cs, "jade A STAR %x", val);
+	cs->BC_Write_Reg(cs, 0, jade_HDLC_IMR, 0x00);
+	cs->BC_Write_Reg(cs, 1, jade_HDLC_IMR, 0x00);
 
+	val = cs->BC_Read_Reg(cs, 1, jade_HDLC_ISR);
+	sprintf(tmp, "jade B ISTA %x", val);
+	debugl1(cs, tmp);
+	val = cs->BC_Read_Reg(cs, 0, jade_HDLC_ISR);
+	sprintf(tmp, "jade A ISTA %x", val);
+	debugl1(cs, tmp);
+	val = cs->BC_Read_Reg(cs, 1, jade_HDLC_STAR);
+	sprintf(tmp, "jade B STAR %x", val);
+	debugl1(cs, tmp);
+	val = cs->BC_Read_Reg(cs, 0, jade_HDLC_STAR);
+	sprintf(tmp, "jade A STAR %x", val);
+	debugl1(cs, tmp);
 	/* Unmask ints */
-	jade_write_reg(cs, 0, jade_HDLC_IMR, 0xF8);
-	jade_write_reg(cs, 1, jade_HDLC_IMR, 0xF8);
+	cs->BC_Write_Reg(cs, 0, jade_HDLC_IMR, 0xF8);
+	cs->BC_Write_Reg(cs, 1, jade_HDLC_IMR, 0xF8);
+}
+
+void __init
+initjade(struct IsdnCardState *cs)
+{
+	cs->bcs[0].BC_SetStack = setstack_jade;
+	cs->bcs[1].BC_SetStack = setstack_jade;
+	cs->bcs[0].BC_Close = close_jadestate;
+	cs->bcs[1].BC_Close = close_jadestate;
+	cs->bcs[0].hw.hscx.hscx = 0;
+	cs->bcs[1].hw.hscx.hscx = 1;
 
 	/* Stop DSP audio tx/rx */
 	jade_write_indirect(cs, 0x11, 0x0f);
 	jade_write_indirect(cs, 0x17, 0x2f);
 
 	/* Transparent Mode, RxTx inactive, No Test, No RFS/TFS */
-	jade_write_reg(cs, 0, jade_HDLC_MODE, jadeMODE_TMO);
-	jade_write_reg(cs, 1, jade_HDLC_MODE, jadeMODE_TMO);
+	cs->BC_Write_Reg(cs, 0, jade_HDLC_MODE, jadeMODE_TMO);
+	cs->BC_Write_Reg(cs, 1, jade_HDLC_MODE, jadeMODE_TMO);
 	/* Power down, 1-Idle, RxTx least significant bit first */
-	jade_write_reg(cs, 0, jade_HDLC_CCR0, 0x00);
-	jade_write_reg(cs, 1, jade_HDLC_CCR0, 0x00);
+	cs->BC_Write_Reg(cs, 0, jade_HDLC_CCR0, 0x00);
+	cs->BC_Write_Reg(cs, 1, jade_HDLC_CCR0, 0x00);
 	/* Mask all interrupts */
-	jade_write_reg(cs, 0, jade_HDLC_IMR,  0x00);
-	jade_write_reg(cs, 1, jade_HDLC_IMR,  0x00);
+	cs->BC_Write_Reg(cs, 0, jade_HDLC_IMR,  0x00);
+	cs->BC_Write_Reg(cs, 1, jade_HDLC_IMR,  0x00);
 	/* Setup host access to hdlc controller */
 	jade_write_indirect(cs, jade_HDLCCNTRACCESS, (jadeINDIRECT_HAH1|jadeINDIRECT_HAH2));
 	/* Unmask HDLC int (don´t forget DSP int later on)*/
-	jade_write_reg(cs, -1,jade_INT, (jadeINT_HDLC1|jadeINT_HDLC2));
+	cs->BC_Write_Reg(cs, -1,jade_INT, (jadeINT_HDLC1|jadeINT_HDLC2));
 
 	/* once again TRANSPARENT */	
 	modejade(cs->bcs, 0, 0);
 	modejade(cs->bcs + 1, 0, 0);
 }
 
-int
-jade_setup(struct IsdnCardState *cs, struct bc_hw_ops *jade_ops)
-{
-	cs->bc_hw_ops = jade_ops;
-	return JadeVersion(cs, "HiSax:");
-}
-
-#include "jade_irq.c"
--- diff/drivers/isdn/hisax/jade.h	2003-01-16 11:30:36.000000000 +0000
+++ source/drivers/isdn/hisax/jade.h	2004-02-23 13:56:42.000000000 +0000
@@ -1,4 +1,4 @@
-/* $Id: jade.h,v 1.3.6.2 2001/09/23 22:24:49 kai Exp $
+/* $Id: jade.h,v 1.5.2.3 2004/01/14 16:04:48 keil Exp $
  *
  * JADE specific defines
  *
@@ -127,10 +127,9 @@
 #define	jade_TXAUDIOCH1CFG				0x17
 #define	jade_TXAUDIOCH2CFG				0x1A
 
-extern void jade_sched_event(struct BCState *bcs, int event);
+extern int JadeVersion(struct IsdnCardState *cs, char *s);
 extern void modejade(struct BCState *bcs, int mode, int bc);
+extern void clear_pending_jade_ints(struct IsdnCardState *cs);
 extern void initjade(struct IsdnCardState *cs);
-extern void jade_int_main(struct IsdnCardState *cs, u8 val, int jade);
-extern int  jade_setup(struct IsdnCardState *cs, struct bc_hw_ops *jade_ops);
 
 #endif	/* __JADE_H__ */
--- diff/drivers/isdn/hisax/jade_irq.c	2003-01-16 11:30:36.000000000 +0000
+++ source/drivers/isdn/hisax/jade_irq.c	2004-02-23 13:56:42.000000000 +0000
@@ -1,4 +1,4 @@
-/* $Id: jade_irq.c,v 1.5.6.2 2001/09/23 22:24:49 kai Exp $
+/* $Id: jade_irq.c,v 1.7.2.4 2004/02/11 13:21:34 keil Exp $
  *
  * Low level JADE IRQ stuff (derived from original hscx_irq.c)
  *
@@ -15,7 +15,7 @@ waitforCEC(struct IsdnCardState *cs, int
 {
   	int to = 50;
   	int mask = (reg == jade_HDLC_XCMD ? jadeSTAR_XCEC : jadeSTAR_RCEC);
-  	while ((jade_read_reg(cs, jade, jade_HDLC_STAR) & mask) && to) {
+  	while ((READJADE(cs, jade, jade_HDLC_STAR) & mask) && to) {
   		udelay(1);
   		to--;
   	}
@@ -25,17 +25,16 @@ waitforCEC(struct IsdnCardState *cs, int
 
 
 static inline void
-waitforXFW(struct BCState *bcs)
+waitforXFW(struct IsdnCardState *cs, int jade)
 {
+  	/* Does not work on older jade versions, don't care */
 }
 
 static inline void
-WriteJADECMDR(struct BCState *bcs, int reg, u8 data)
+WriteJADECMDR(struct IsdnCardState *cs, int jade, int reg, u_char data)
 {
-	int jade = bcs->unit;
-
-	waitforCEC(bcs->cs, jade, reg);
-	jade_write_reg(bcs->cs, jade, reg, data);
+	waitforCEC(cs, jade, reg);
+	WRITEJADE(cs, jade, reg, data);
 }
 
 
@@ -43,33 +42,80 @@ WriteJADECMDR(struct BCState *bcs, int r
 static void
 jade_empty_fifo(struct BCState *bcs, int count)
 {
-	recv_empty_fifo_b(bcs, count);
-	WriteJADECMDR(bcs, jade_HDLC_RCMD, jadeRCMD_RMC);
+	u_char *ptr;
+	struct IsdnCardState *cs = bcs->cs;
+
+	if ((cs->debug & L1_DEB_HSCX) && !(cs->debug & L1_DEB_HSCX_FIFO))
+		debugl1(cs, "jade_empty_fifo");
+
+	if (bcs->hw.hscx.rcvidx + count > HSCX_BUFMAX) {
+		if (cs->debug & L1_DEB_WARN)
+			debugl1(cs, "jade_empty_fifo: incoming packet too large");
+		WriteJADECMDR(cs, bcs->hw.hscx.hscx, jade_HDLC_RCMD, jadeRCMD_RMC);
+		bcs->hw.hscx.rcvidx = 0;
+		return;
+	}
+	ptr = bcs->hw.hscx.rcvbuf + bcs->hw.hscx.rcvidx;
+	bcs->hw.hscx.rcvidx += count;
+	READJADEFIFO(cs, bcs->hw.hscx.hscx, ptr, count);
+	WriteJADECMDR(cs, bcs->hw.hscx.hscx, jade_HDLC_RCMD, jadeRCMD_RMC);
+	if (cs->debug & L1_DEB_HSCX_FIFO) {
+		char *t = bcs->blog;
+
+		t += sprintf(t, "jade_empty_fifo %c cnt %d",
+			     bcs->hw.hscx.hscx ? 'B' : 'A', count);
+		QuickHex(t, ptr, count);
+		debugl1(cs, bcs->blog);
+	}
 }
 
 static void
 jade_fill_fifo(struct BCState *bcs)
 {
+	struct IsdnCardState *cs = bcs->cs;
 	int more, count;
 	int fifo_size = 32;
-	unsigned char *p;
+	u_char *ptr;
+
+	if ((cs->debug & L1_DEB_HSCX) && !(cs->debug & L1_DEB_HSCX_FIFO))
+		debugl1(cs, "jade_fill_fifo");
 
-	p = xmit_fill_fifo_b(bcs, fifo_size, &count, &more);
-	if (!p)
+	if (!bcs->tx_skb)
+		return;
+	if (bcs->tx_skb->len <= 0)
 		return;
 
-	waitforXFW(bcs);
-	jade_write_fifo(bcs, p, count);
-	WriteJADECMDR(bcs, jade_HDLC_XCMD,
-		      more ? jadeXCMD_XF : (jadeXCMD_XF|jadeXCMD_XME));
+	more = (bcs->mode == L1_MODE_TRANS) ? 1 : 0;
+	if (bcs->tx_skb->len > fifo_size) {
+		more = !0;
+		count = fifo_size;
+	} else
+		count = bcs->tx_skb->len;
+
+	waitforXFW(cs, bcs->hw.hscx.hscx);
+	ptr = bcs->tx_skb->data;
+	skb_pull(bcs->tx_skb, count);
+	bcs->tx_cnt -= count;
+	bcs->hw.hscx.count += count;
+	WRITEJADEFIFO(cs, bcs->hw.hscx.hscx, ptr, count);
+	WriteJADECMDR(cs, bcs->hw.hscx.hscx, jade_HDLC_XCMD, more ? jadeXCMD_XF : (jadeXCMD_XF|jadeXCMD_XME));
+	if (cs->debug & L1_DEB_HSCX_FIFO) {
+		char *t = bcs->blog;
+
+		t += sprintf(t, "jade_fill_fifo %c cnt %d",
+			     bcs->hw.hscx.hscx ? 'B' : 'A', count);
+		QuickHex(t, ptr, count);
+		debugl1(cs, bcs->blog);
+	}
 }
 
 
 static inline void
-jade_interrupt(struct IsdnCardState *cs, u8 val, u8 jade)
+jade_interrupt(struct IsdnCardState *cs, u_char val, u_char jade)
 {
-	u8 r;
+	u_char r;
 	struct BCState *bcs = cs->bcs + jade;
+	struct sk_buff *skb;
 	int fifo_size = 32;
 	int count;
 	int i_jade = (int) jade; /* To satisfy the compiler */
@@ -78,7 +124,7 @@ jade_interrupt(struct IsdnCardState *cs,
 		return;
 
 	if (val & 0x80) {	/* RME */
-		r = jade_read_reg(cs, i_jade, jade_HDLC_RSTA);
+		r = READJADE(cs, i_jade, jade_HDLC_RSTA);
 		if ((r & 0xf0) != 0xa0) {
 			if (!(r & 0x80))
 				if (cs->debug & L1_DEB_WARN)
@@ -89,34 +135,72 @@ jade_interrupt(struct IsdnCardState *cs,
 			if (!(r & 0x20))
 				if (cs->debug & L1_DEB_WARN)
 					debugl1(cs, "JADE %c CRC error", 'A'+jade);
-			WriteJADECMDR(bcs, jade_HDLC_RCMD, jadeRCMD_RMC);
-			bcs->rcvidx = 0;
+			WriteJADECMDR(cs, jade, jade_HDLC_RCMD, jadeRCMD_RMC);
 		} else {
-			count = jade_read_reg(cs, i_jade, jade_HDLC_RBCL) & 0x1F;
+			count = READJADE(cs, i_jade, jade_HDLC_RBCL) & 0x1F;
 			if (count == 0)
 				count = fifo_size;
-
 			jade_empty_fifo(bcs, count);
-			recv_rme_b(bcs);
+			if ((count = bcs->hw.hscx.rcvidx - 1) > 0) {
+				if (cs->debug & L1_DEB_HSCX_FIFO)
+					debugl1(cs, "HX Frame %d", count);
+				if (!(skb = dev_alloc_skb(count)))
+					printk(KERN_WARNING "JADE %s receive out of memory\n", (jade ? "B":"A"));
+				else {
+					memcpy(skb_put(skb, count), bcs->hw.hscx.rcvbuf, count);
+					skb_queue_tail(&bcs->rqueue, skb);
+				}
+			}
 		}
+		bcs->hw.hscx.rcvidx = 0;
+		schedule_event(bcs, B_RCVBUFREADY);
 	}
 	if (val & 0x40) {	/* RPF */
 		jade_empty_fifo(bcs, fifo_size);
-		recv_rpf_b(bcs);
+		if (bcs->mode == L1_MODE_TRANS) {
+			/* receive audio data */
+			if (!(skb = dev_alloc_skb(fifo_size)))
+				printk(KERN_WARNING "HiSax: receive out of memory\n");
+			else {
+				memcpy(skb_put(skb, fifo_size), bcs->hw.hscx.rcvbuf, fifo_size);
+				skb_queue_tail(&bcs->rqueue, skb);
+			}
+			bcs->hw.hscx.rcvidx = 0;
+			schedule_event(bcs, B_RCVBUFREADY);
+		}
 	}
 	if (val & 0x10) {	/* XPR */
-		xmit_xpr_b(bcs);
+		if (bcs->tx_skb) {
+			if (bcs->tx_skb->len) {
+				jade_fill_fifo(bcs);
+				return;
+			} else {
+				if (test_bit(FLG_LLI_L1WAKEUP,&bcs->st->lli.flag) &&
+					(PACKET_NOACK != bcs->tx_skb->pkt_type)) {
+					u_long	flags;
+					spin_lock_irqsave(&bcs->aclock, flags);
+					bcs->ackcnt += bcs->hw.hscx.count;
+					spin_unlock_irqrestore(&bcs->aclock, flags);
+					schedule_event(bcs, B_ACKPENDING);
+				}
+				dev_kfree_skb_irq(bcs->tx_skb);
+				bcs->hw.hscx.count = 0;
+				bcs->tx_skb = NULL;
+			}
+		}
+		if ((bcs->tx_skb = skb_dequeue(&bcs->squeue))) {
+			bcs->hw.hscx.count = 0;
+			test_and_set_bit(BC_FLG_BUSY, &bcs->Flag);
+			jade_fill_fifo(bcs);
+		} else {
+			test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
+			schedule_event(bcs, B_XMTBUFREADY);
+		}
 	}
 }
 
-static void
-reset_xmit(struct BCState *bcs)
-{
-	WriteJADECMDR(bcs, jade_HDLC_XCMD, jadeXCMD_XRES);
-}
-
-void
-jade_int_main(struct IsdnCardState *cs, u8 val, int jade)
+static inline void
+jade_int_main(struct IsdnCardState *cs, u_char val, int jade)
 {
 	struct BCState *bcs;
 	bcs = cs->bcs + jade;
@@ -126,7 +210,23 @@ jade_int_main(struct IsdnCardState *cs, 
 		val &= ~jadeISR_RFO;
 	}
 	if (val & jadeISR_XDU) {
-		xmit_xdu_b(bcs, reset_xmit);
+		/* relevant in HDLC mode only */
+		/* don't reset XPR here */
+		if (bcs->mode == 1)
+			jade_fill_fifo(bcs);
+		else {
+			/* Here we lost an TX interrupt, so
+			   * restart transmitting the whole frame.
+			 */
+			if (bcs->tx_skb) {
+			   	skb_push(bcs->tx_skb, bcs->hw.hscx.count);
+				bcs->tx_cnt += bcs->hw.hscx.count;
+				bcs->hw.hscx.count = 0;
+			}
+			WriteJADECMDR(cs, bcs->hw.hscx.hscx, jade_HDLC_XCMD, jadeXCMD_XRES);
+			if (cs->debug & L1_DEB_WARN)
+				debugl1(cs, "JADE %c EXIR %x Lost TX", 'A'+jade, val);
+		}
 	}
 	if (val & (jadeISR_RME|jadeISR_RPF|jadeISR_XPR)) {
 		if (cs->debug & L1_DEB_HSCX)
--- diff/drivers/isdn/hisax/l3_1tr6.c	2003-09-17 12:28:06.000000000 +0100
+++ source/drivers/isdn/hisax/l3_1tr6.c	2004-02-23 13:56:42.000000000 +0000
@@ -1,4 +1,4 @@
-/* $Id: l3_1tr6.c,v 2.13.6.2 2001/09/23 22:24:49 kai Exp $
+/* $Id: l3_1tr6.c,v 2.15.2.3 2004/01/13 14:31:25 keil Exp $
  *
  * German 1TR6 D-channel protocol
  *
@@ -19,7 +19,7 @@
 #include <linux/ctype.h>
 
 extern char *HiSax_getrev(const char *revision);
-const char *l3_1tr6_revision = "$Revision: 2.13.6.2 $";
+const char *l3_1tr6_revision = "$Revision: 2.15.2.3 $";
 
 #define MsgHead(ptr, cref, mty, dis) \
 	*ptr++ = dis; \
@@ -28,10 +28,10 @@ const char *l3_1tr6_revision = "$Revisio
 	*ptr++ = mty
 
 static void
-l3_1TR6_message(struct l3_process *pc, u8 mt, u8 pd)
+l3_1TR6_message(struct l3_process *pc, u_char mt, u_char pd)
 {
 	struct sk_buff *skb;
-	u8 *p;
+	u_char *p;
 
 	if (!(skb = l3_alloc_skb(4)))
 		return;
@@ -41,7 +41,7 @@ l3_1TR6_message(struct l3_process *pc, u
 }
 
 static void
-l3_1tr6_release_req(struct l3_process *pc, u8 pr, void *arg)
+l3_1tr6_release_req(struct l3_process *pc, u_char pr, void *arg)
 {
 	StopAllL3Timer(pc);
 	newl3state(pc, 19);
@@ -50,7 +50,7 @@ l3_1tr6_release_req(struct l3_process *p
 }
 
 static void
-l3_1tr6_invalid(struct l3_process *pc, u8 pr, void *arg)
+l3_1tr6_invalid(struct l3_process *pc, u_char pr, void *arg)
 {
 	struct sk_buff *skb = arg;
 
@@ -59,7 +59,7 @@ l3_1tr6_invalid(struct l3_process *pc, u
 }
 
 static void
-l3_1tr6_error(struct l3_process *pc, u8 *msg, struct sk_buff *skb)
+l3_1tr6_error(struct l3_process *pc, u_char *msg, struct sk_buff *skb)
 {
 	dev_kfree_skb(skb);
 	if (pc->st->l3.debug & L3_DEB_WARN)
@@ -68,14 +68,14 @@ l3_1tr6_error(struct l3_process *pc, u8 
 }
 
 static void
-l3_1tr6_setup_req(struct l3_process *pc, u8 pr, void *arg)
+l3_1tr6_setup_req(struct l3_process *pc, u_char pr, void *arg)
 {
 	struct sk_buff *skb;
-	u8 tmp[128];
-	u8 *p = tmp;
-	u8 *teln;
-	u8 *eaz;
-	u8 channel = 0;
+	u_char tmp[128];
+	u_char *p = tmp;
+	u_char *teln;
+	u_char *eaz;
+	u_char channel = 0;
 	int l;
 
 	MsgHead(p, pc->callref, MT_N1_SETUP, PROTO_DIS_N1);
@@ -157,9 +157,9 @@ l3_1tr6_setup_req(struct l3_process *pc,
 }
 
 static void
-l3_1tr6_setup(struct l3_process *pc, u8 pr, void *arg)
+l3_1tr6_setup(struct l3_process *pc, u_char pr, void *arg)
 {
-	u8 *p;
+	u_char *p;
 	int bcfound = 0;
 	char tmp[80];
 	struct sk_buff *skb = arg;
@@ -222,15 +222,15 @@ l3_1tr6_setup(struct l3_process *pc, u8 
 			l3_debug(pc->st, tmp);
 		}
 		newl3state(pc, 6);
-		L3L4(pc->st, CC_SETUP | INDICATION, pc);
+		pc->st->l3.l3l4(pc->st, CC_SETUP | INDICATION, pc);
 	} else
 		release_l3_process(pc);
 }
 
 static void
-l3_1tr6_setup_ack(struct l3_process *pc, u8 pr, void *arg)
+l3_1tr6_setup_ack(struct l3_process *pc, u_char pr, void *arg)
 {
-	u8 *p;
+	u_char *p;
 	struct sk_buff *skb = arg;
 
 	L3DelTimer(&pc->timer);
@@ -252,13 +252,13 @@ l3_1tr6_setup_ack(struct l3_process *pc,
 	}
 	dev_kfree_skb(skb);
 	L3AddTimer(&pc->timer, T304, CC_T304);
-	L3L4(pc->st, CC_MORE_INFO | INDICATION, pc);
+	pc->st->l3.l3l4(pc->st, CC_MORE_INFO | INDICATION, pc);
 }
 
 static void
-l3_1tr6_call_sent(struct l3_process *pc, u8 pr, void *arg)
+l3_1tr6_call_sent(struct l3_process *pc, u_char pr, void *arg)
 {
-	u8 *p;
+	u_char *p;
 	struct sk_buff *skb = arg;
 
 	L3DelTimer(&pc->timer);
@@ -284,26 +284,25 @@ l3_1tr6_call_sent(struct l3_process *pc,
 	dev_kfree_skb(skb);
 	L3AddTimer(&pc->timer, T310, CC_T310);
 	newl3state(pc, 3);
-	L3L4(pc->st, CC_PROCEEDING | INDICATION, pc);
+	pc->st->l3.l3l4(pc->st, CC_PROCEEDING | INDICATION, pc);
 }
 
 static void
-l3_1tr6_alert(struct l3_process *pc, u8 pr, void *arg)
+l3_1tr6_alert(struct l3_process *pc, u_char pr, void *arg)
 {
 	struct sk_buff *skb = arg;
 
 	dev_kfree_skb(skb);
 	L3DelTimer(&pc->timer);	/* T304 */
 	newl3state(pc, 4);
-	L3L4(pc->st, CC_ALERTING | INDICATION, pc);
+	pc->st->l3.l3l4(pc->st, CC_ALERTING | INDICATION, pc);
 }
 
 static void
-l3_1tr6_info(struct l3_process *pc, u8 pr, void *arg)
+l3_1tr6_info(struct l3_process *pc, u_char pr, void *arg)
 {
-	u8 *p;
-	u_int i;
-	int tmpcharge = 0;
+	u_char *p;
+	int i, tmpcharge = 0;
 	char a_charge[8], tmp[32];
 	struct sk_buff *skb = arg;
 
@@ -316,7 +315,7 @@ l3_1tr6_info(struct l3_process *pc, u8 p
 		}
 		if (tmpcharge > pc->para.chargeinfo) {
 			pc->para.chargeinfo = tmpcharge;
-			L3L4(pc->st, CC_CHARGE | INDICATION, pc);
+			pc->st->l3.l3l4(pc->st, CC_CHARGE | INDICATION, pc);
 		}
 		if (pc->st->l3.debug & L3_DEB_CHARGE) {
 			sprintf(tmp, "charging info %d", pc->para.chargeinfo);
@@ -329,7 +328,7 @@ l3_1tr6_info(struct l3_process *pc, u8 p
 }
 
 static void
-l3_1tr6_info_s2(struct l3_process *pc, u8 pr, void *arg)
+l3_1tr6_info_s2(struct l3_process *pc, u_char pr, void *arg)
 {
 	struct sk_buff *skb = arg;
 
@@ -337,7 +336,7 @@ l3_1tr6_info_s2(struct l3_process *pc, u
 }
 
 static void
-l3_1tr6_connect(struct l3_process *pc, u8 pr, void *arg)
+l3_1tr6_connect(struct l3_process *pc, u_char pr, void *arg)
 {
 	struct sk_buff *skb = arg;
 
@@ -349,14 +348,14 @@ l3_1tr6_connect(struct l3_process *pc, u
 	newl3state(pc, 10);
 	dev_kfree_skb(skb);
 	pc->para.chargeinfo = 0;
-	L3L4(pc->st, CC_SETUP | CONFIRM, pc);
+	pc->st->l3.l3l4(pc->st, CC_SETUP | CONFIRM, pc);
 }
 
 static void
-l3_1tr6_rel(struct l3_process *pc, u8 pr, void *arg)
+l3_1tr6_rel(struct l3_process *pc, u_char pr, void *arg)
 {
 	struct sk_buff *skb = arg;
-	u8 *p;
+	u_char *p;
 
 	p = skb->data;
 	if ((p = findie(p, skb->len, WE0_cause, 0))) {
@@ -379,12 +378,12 @@ l3_1tr6_rel(struct l3_process *pc, u8 pr
 	StopAllL3Timer(pc);
 	newl3state(pc, 0);
 	l3_1TR6_message(pc, MT_N1_REL_ACK, PROTO_DIS_N1);
-	L3L4(pc->st, CC_RELEASE | INDICATION, pc);
+	pc->st->l3.l3l4(pc->st, CC_RELEASE | INDICATION, pc);
 	release_l3_process(pc);
 }
 
 static void
-l3_1tr6_rel_ack(struct l3_process *pc, u8 pr, void *arg)
+l3_1tr6_rel_ack(struct l3_process *pc, u_char pr, void *arg)
 {
 	struct sk_buff *skb = arg;
 
@@ -392,17 +391,16 @@ l3_1tr6_rel_ack(struct l3_process *pc, u
 	StopAllL3Timer(pc);
 	newl3state(pc, 0);
 	pc->para.cause = NO_CAUSE;
-	L3L4(pc->st, CC_RELEASE | CONFIRM, pc);
+	pc->st->l3.l3l4(pc->st, CC_RELEASE | CONFIRM, pc);
 	release_l3_process(pc);
 }
 
 static void
-l3_1tr6_disc(struct l3_process *pc, u8 pr, void *arg)
+l3_1tr6_disc(struct l3_process *pc, u_char pr, void *arg)
 {
 	struct sk_buff *skb = arg;
-	u8 *p;
-	u_int i;
-	int tmpcharge = 0;
+	u_char *p;
+	int i, tmpcharge = 0;
 	char a_charge[8], tmp[32];
 
 	StopAllL3Timer(pc);
@@ -415,7 +413,7 @@ l3_1tr6_disc(struct l3_process *pc, u8 p
 		}
 		if (tmpcharge > pc->para.chargeinfo) {
 			pc->para.chargeinfo = tmpcharge;
-			L3L4(pc->st, CC_CHARGE | INDICATION, pc);
+			pc->st->l3.l3l4(pc->st, CC_CHARGE | INDICATION, pc);
 		}
 		if (pc->st->l3.debug & L3_DEB_CHARGE) {
 			sprintf(tmp, "charging info %d", pc->para.chargeinfo);
@@ -448,12 +446,12 @@ l3_1tr6_disc(struct l3_process *pc, u8 p
 	}
 	dev_kfree_skb(skb);
 	newl3state(pc, 12);
-	L3L4(pc->st, CC_DISCONNECT | INDICATION, pc);
+	pc->st->l3.l3l4(pc->st, CC_DISCONNECT | INDICATION, pc);
 }
 
 
 static void
-l3_1tr6_connect_ack(struct l3_process *pc, u8 pr, void *arg)
+l3_1tr6_connect_ack(struct l3_process *pc, u_char pr, void *arg)
 {
 	struct sk_buff *skb = arg;
 
@@ -465,22 +463,22 @@ l3_1tr6_connect_ack(struct l3_process *p
 	newl3state(pc, 10);
 	pc->para.chargeinfo = 0;
 	L3DelTimer(&pc->timer);
-	L3L4(pc->st, CC_SETUP_COMPL | INDICATION, pc);
+	pc->st->l3.l3l4(pc->st, CC_SETUP_COMPL | INDICATION, pc);
 }
 
 static void
-l3_1tr6_alert_req(struct l3_process *pc, u8 pr, void *arg)
+l3_1tr6_alert_req(struct l3_process *pc, u_char pr, void *arg)
 {
 	newl3state(pc, 7);
 	l3_1TR6_message(pc, MT_N1_ALERT, PROTO_DIS_N1);
 }
 
 static void
-l3_1tr6_setup_rsp(struct l3_process *pc, u8 pr, void *arg)
+l3_1tr6_setup_rsp(struct l3_process *pc, u_char pr, void *arg)
 {
 	struct sk_buff *skb;
-	u8 tmp[24];
-	u8 *p = tmp;
+	u_char tmp[24];
+	u_char *p = tmp;
 	int l;
 
 	MsgHead(p, pc->callref, MT_N1_CONN, PROTO_DIS_N1);
@@ -510,20 +508,20 @@ l3_1tr6_setup_rsp(struct l3_process *pc,
 }
 
 static void
-l3_1tr6_reset(struct l3_process *pc, u8 pr, void *arg)
+l3_1tr6_reset(struct l3_process *pc, u_char pr, void *arg)
 {
 	release_l3_process(pc);
 }
 
 static void
-l3_1tr6_disconnect_req(struct l3_process *pc, u8 pr, void *arg)
+l3_1tr6_disconnect_req(struct l3_process *pc, u_char pr, void *arg)
 {
 	struct sk_buff *skb;
-	u8 tmp[16];
-	u8 *p = tmp;
+	u_char tmp[16];
+	u_char *p = tmp;
 	int l;
-	u8 cause = 0x10;
-	u8 clen = 1;
+	u_char cause = 0x10;
+	u_char clen = 1;
 
 	if (pc->para.cause > 0)
 		cause = pc->para.cause;
@@ -555,7 +553,7 @@ l3_1tr6_disconnect_req(struct l3_process
 }
 
 static void
-l3_1tr6_t303(struct l3_process *pc, u8 pr, void *arg)
+l3_1tr6_t303(struct l3_process *pc, u_char pr, void *arg)
 {
 	if (pc->N303 > 0) {
 		pc->N303--;
@@ -569,23 +567,23 @@ l3_1tr6_t303(struct l3_process *pc, u8 p
 }
 
 static void
-l3_1tr6_t304(struct l3_process *pc, u8 pr, void *arg)
+l3_1tr6_t304(struct l3_process *pc, u_char pr, void *arg)
 {
 	L3DelTimer(&pc->timer);
 	pc->para.cause = 0xE6;
 	l3_1tr6_disconnect_req(pc, pr, NULL);
-	L3L4(pc->st, CC_SETUP_ERR, pc);
+	pc->st->l3.l3l4(pc->st, CC_SETUP_ERR, pc);
 }
 
 static void
-l3_1tr6_t305(struct l3_process *pc, u8 pr, void *arg)
+l3_1tr6_t305(struct l3_process *pc, u_char pr, void *arg)
 {
 	struct sk_buff *skb;
-	u8 tmp[16];
-	u8 *p = tmp;
+	u_char tmp[16];
+	u_char *p = tmp;
 	int l;
-	u8 cause = 0x90;
-	u8 clen = 1;
+	u_char cause = 0x90;
+	u_char clen = 1;
 
 	L3DelTimer(&pc->timer);
 	if (pc->para.cause != NO_CAUSE)
@@ -614,25 +612,25 @@ l3_1tr6_t305(struct l3_process *pc, u8 p
 }
 
 static void
-l3_1tr6_t310(struct l3_process *pc, u8 pr, void *arg)
+l3_1tr6_t310(struct l3_process *pc, u_char pr, void *arg)
 {
 	L3DelTimer(&pc->timer);
 	pc->para.cause = 0xE6;
 	l3_1tr6_disconnect_req(pc, pr, NULL);
-	L3L4(pc->st, CC_SETUP_ERR, pc);
+	pc->st->l3.l3l4(pc->st, CC_SETUP_ERR, pc);
 }
 
 static void
-l3_1tr6_t313(struct l3_process *pc, u8 pr, void *arg)
+l3_1tr6_t313(struct l3_process *pc, u_char pr, void *arg)
 {
 	L3DelTimer(&pc->timer);
 	pc->para.cause = 0xE6;
 	l3_1tr6_disconnect_req(pc, pr, NULL);
-	L3L4(pc->st, CC_CONNECT_ERR, pc);
+	pc->st->l3.l3l4(pc->st, CC_CONNECT_ERR, pc);
 }
 
 static void
-l3_1tr6_t308_1(struct l3_process *pc, u8 pr, void *arg)
+l3_1tr6_t308_1(struct l3_process *pc, u_char pr, void *arg)
 {
 	L3DelTimer(&pc->timer);
 	l3_1TR6_message(pc, MT_N1_REL, PROTO_DIS_N1);
@@ -641,28 +639,28 @@ l3_1tr6_t308_1(struct l3_process *pc, u8
 }
 
 static void
-l3_1tr6_t308_2(struct l3_process *pc, u8 pr, void *arg)
+l3_1tr6_t308_2(struct l3_process *pc, u_char pr, void *arg)
 {
 	L3DelTimer(&pc->timer);
-	L3L4(pc->st, CC_RELEASE_ERR, pc);
+	pc->st->l3.l3l4(pc->st, CC_RELEASE_ERR, pc);
 	release_l3_process(pc);
 }
 
 static void
-l3_1tr6_dl_reset(struct l3_process *pc, u8 pr, void *arg)
+l3_1tr6_dl_reset(struct l3_process *pc, u_char pr, void *arg)
 {
         pc->para.cause = CAUSE_LocalProcErr;
         l3_1tr6_disconnect_req(pc, pr, NULL);
-        L3L4(pc->st, CC_SETUP_ERR, pc);
+        pc->st->l3.l3l4(pc->st, CC_SETUP_ERR, pc);
 }
 
 static void
-l3_1tr6_dl_release(struct l3_process *pc, u8 pr, void *arg)
+l3_1tr6_dl_release(struct l3_process *pc, u_char pr, void *arg)
 {
         newl3state(pc, 0);
         pc->para.cause = 0x1b;          /* Destination out of order */
         pc->para.loc = 0;
-        L3L4(pc->st, CC_RELEASE | INDICATION, pc);
+        pc->st->l3.l3l4(pc->st, CC_RELEASE | INDICATION, pc);
         release_l3_process(pc);
 }
 
@@ -755,8 +753,7 @@ static struct stateentry manstatelist[] 
 static void
 up1tr6(struct PStack *st, int pr, void *arg)
 {
-	u_int i;
-	int mt, cr;
+	int i, mt, cr;
 	struct l3_process *proc;
 	struct sk_buff *skb = arg;
 	char tmp[80];
@@ -871,8 +868,7 @@ up1tr6(struct PStack *st, int pr, void *
 static void
 down1tr6(struct PStack *st, int pr, void *arg)
 {
-	u_int i;
-	int cr;
+	int i, cr;
 	struct l3_process *proc;
 	struct Channel *chan;
 	char tmp[80];
@@ -919,7 +915,7 @@ down1tr6(struct PStack *st, int pr, void
 static void
 man1tr6(struct PStack *st, int pr, void *arg)
 {
-        u_int i;
+        int i;
         struct l3_process *proc = arg;
  
         if (!proc) {
@@ -949,8 +945,8 @@ setstack_1tr6(struct PStack *st)
 {
 	char tmp[64];
 
-	st->l3.l4l3 = down1tr6;
-	st->l3.l2l3 = up1tr6;
+	st->lli.l4l3 = down1tr6;
+	st->l2.l2l3 = up1tr6;
 	st->l3.l3ml3 = man1tr6;
 	st->l3.N303 = 0;
 
--- diff/drivers/isdn/hisax/l3dss1.c	2003-09-17 12:28:06.000000000 +0100
+++ source/drivers/isdn/hisax/l3dss1.c	2004-02-23 13:56:42.000000000 +0000
@@ -1,4 +1,4 @@
-/* $Id: l3dss1.c,v 2.30.6.2 2001/09/23 22:24:49 kai Exp $
+/* $Id: l3dss1.c,v 2.32.2.3 2004/01/13 14:31:25 keil Exp $
  *
  * EURO/DSS1 D-channel protocol
  *
@@ -26,8 +26,7 @@
 #include <linux/config.h>
 
 extern char *HiSax_getrev(const char *revision);
-const char *dss1_revision = "$Revision: 2.30.6.2 $";
-static spinlock_t l3dss1_lock = SPIN_LOCK_UNLOCKED;
+const char *dss1_revision = "$Revision: 2.32.2.3 $";
 
 #define EXT_BEARER_CAPS 1
 
@@ -49,13 +48,10 @@ static spinlock_t l3dss1_lock = SPIN_LOC
 static unsigned char new_invoke_id(struct PStack *p)
 {
 	unsigned char retval;
-	unsigned long flags;
 	int i;
   
 	i = 32; /* maximum search depth */
 
-	spin_lock_irqsave(&l3dss1_lock, flags);
-
 	retval = p->prot.dss1.last_invoke_id + 1; /* try new id */
 	while ((i) && (p->prot.dss1.invoke_used[retval >> 3] == 0xFF)) {
 		p->prot.dss1.last_invoke_id = (retval & 0xF8) + 8;
@@ -68,8 +64,6 @@ static unsigned char new_invoke_id(struc
 		retval = 0;
 	p->prot.dss1.last_invoke_id = retval;
 	p->prot.dss1.invoke_used[retval >> 3] |= (1 << (retval & 7));
-	spin_unlock_irqrestore(&l3dss1_lock, flags);
-
 	return(retval);  
 } /* new_invoke_id */
 
@@ -77,13 +71,11 @@ static unsigned char new_invoke_id(struc
 /* free a used invoke id */
 /*************************/
 static void free_invoke_id(struct PStack *p, unsigned char id)
-{ unsigned long flags;
+{
 
   if (!id) return; /* 0 = invalid value */
 
-  spin_lock_irqsave(&l3dss1_lock, flags);
   p->prot.dss1.invoke_used[id >> 3] &= ~(1 << (id & 7));
-  spin_unlock_irqrestore(&l3dss1_lock, flags);
 } /* free_invoke_id */  
 
 
@@ -136,7 +128,7 @@ l3dss1_search_dummy_proc(struct PStack *
 /* and a return result is delivered. id specifies the invoke id.   */
 /*******************************************************************/ 
 static void 
-l3dss1_dummy_return_result(struct PStack *st, int id, u8 *p, u8 nlen)
+l3dss1_dummy_return_result(struct PStack *st, int id, u_char *p, u_char nlen)
 { isdn_ctrl ic;
   struct IsdnCardState *cs;
   struct l3_process *pc = NULL; 
@@ -203,7 +195,7 @@ l3dss1_dummy_error_return(struct PStack 
 /*******************************************************************/ 
 static void 
 l3dss1_dummy_invoke(struct PStack *st, int cr, int id, 
-                    int ident, u8 *p, u8 nlen)
+                    int ident, u_char *p, u_char nlen)
 { isdn_ctrl ic;
   struct IsdnCardState *cs;
   
@@ -227,7 +219,7 @@ l3dss1_dummy_invoke(struct PStack *st, i
 
 static void
 l3dss1_parse_facility(struct PStack *st, struct l3_process *pc,
-                      int cr, u8 * p)
+                      int cr, u_char * p)
 {
 	int qd_len = 0;
 	unsigned char nlen = 0, ilen, cp_tag;
@@ -447,7 +439,7 @@ l3dss1_parse_facility(struct PStack *st,
                             pc->prot.dss1.remote_result = 0; /* success */     
                             pc->prot.dss1.invoke_id = 0;
                             pc->redir_result = pc->prot.dss1.remote_result; 
-                            L3L4(st, CC_REDIR | INDICATION, pc);                                  } /* Diversion successful */
+                            st->l3.l3l4(st, CC_REDIR | INDICATION, pc);                                  } /* Diversion successful */
                         else
                           l3_debug(st,"return error unknown identifier");
 			break;
@@ -492,7 +484,7 @@ l3dss1_parse_facility(struct PStack *st,
                             pc->prot.dss1.remote_result = err_ret; /* result */
                             pc->prot.dss1.invoke_id = 0; 
                             pc->redir_result = pc->prot.dss1.remote_result; 
-                            L3L4(st, CC_REDIR | INDICATION, pc);  
+                            st->l3.l3l4(st, CC_REDIR | INDICATION, pc);  
                           } /* Deflection error */
                         else
                           l3_debug(st,"return result unknown identifier");
@@ -504,10 +496,10 @@ l3dss1_parse_facility(struct PStack *st,
 }
 
 static void
-l3dss1_message(struct l3_process *pc, u8 mt)
+l3dss1_message(struct l3_process *pc, u_char mt)
 {
 	struct sk_buff *skb;
-	u8 *p;
+	u_char *p;
 
 	if (!(skb = l3_alloc_skb(4)))
 		return;
@@ -517,11 +509,11 @@ l3dss1_message(struct l3_process *pc, u8
 }
 
 static void
-l3dss1_message_cause(struct l3_process *pc, u8 mt, u8 cause)
+l3dss1_message_cause(struct l3_process *pc, u_char mt, u_char cause)
 {
 	struct sk_buff *skb;
-	u8 tmp[16];
-	u8 *p = tmp;
+	u_char tmp[16];
+	u_char *p = tmp;
 	int l;
 
 	MsgHead(p, pc->callref, mt);
@@ -538,10 +530,10 @@ l3dss1_message_cause(struct l3_process *
 }
 
 static void
-l3dss1_status_send(struct l3_process *pc, u8 pr, void *arg)
+l3dss1_status_send(struct l3_process *pc, u_char pr, void *arg)
 {
-	u8 tmp[16];
-	u8 *p = tmp;
+	u_char tmp[16];
+	u_char *p = tmp;
 	int l;
 	struct sk_buff *skb;
 
@@ -564,14 +556,14 @@ l3dss1_status_send(struct l3_process *pc
 }
 
 static void
-l3dss1_msg_without_setup(struct l3_process *pc, u8 pr, void *arg)
+l3dss1_msg_without_setup(struct l3_process *pc, u_char pr, void *arg)
 {
 	/* This routine is called if here was no SETUP made (checks in dss1up and in
 	 * l3dss1_setup) and a RELEASE_COMPLETE have to be sent with an error code
 	 * MT_STATUS_ENQUIRE in the NULL state is handled too
 	 */
-	u8 tmp[16];
-	u8 *p = tmp;
+	u_char tmp[16];
+	u_char *p = tmp;
 	int l;
 	struct sk_buff *skb;
 
@@ -690,7 +682,7 @@ struct ie_len max_ie_len[] = {
 };
 
 static int
-getmax_ie_len(u8 ie) {
+getmax_ie_len(u_char ie) {
 	int i = 0;
 	while (max_ie_len[i].ie != -1) {
 		if (max_ie_len[i].ie == ie)
@@ -701,7 +693,7 @@ getmax_ie_len(u8 ie) {
 }
 
 static int
-ie_in_set(struct l3_process *pc, u8 ie, int *checklist) {
+ie_in_set(struct l3_process *pc, u_char ie, int *checklist) {
 	int ret = 1;
 
 	while (*checklist != -1) {
@@ -721,13 +713,13 @@ static int
 check_infoelements(struct l3_process *pc, struct sk_buff *skb, int *checklist)
 {
 	int *cl = checklist;
-	u8 mt;
-	u8 *p, ie;
+	u_char mt;
+	u_char *p, ie;
 	int l, newpos, oldpos;
 	int err_seq = 0, err_len = 0, err_compr = 0, err_ureg = 0;
-	u8 codeset = 0;
-	u8 old_codeset = 0;
-	u8 codelock = 1;
+	u_char codeset = 0;
+	u_char old_codeset = 0;
+	u_char codelock = 1;
 	
 	p = skb->data;
 	/* skip cr */
@@ -736,7 +728,7 @@ check_infoelements(struct l3_process *pc
 	p += l;
 	mt = *p++;
 	oldpos = 0;
-	while ((p - skb->data) < (int)skb->len) {
+	while ((p - skb->data) < skb->len) {
 		if ((*p & 0xf0) == 0x90) { /* shift codeset */
 			old_codeset = codeset;
 			codeset = *p & 7;
@@ -870,7 +862,7 @@ l3dss1_std_ie_err(struct l3_process *pc,
 
 static int
 l3dss1_get_channel_id(struct l3_process *pc, struct sk_buff *skb) {
-	u8 *p;
+	u_char *p;
 
 	p = skb->data;
 	if ((p = findie(p, skb->len, IE_CHANNEL_ID, 0))) {
@@ -893,8 +885,8 @@ l3dss1_get_channel_id(struct l3_process 
 
 static int
 l3dss1_get_cause(struct l3_process *pc, struct sk_buff *skb) {
-	u8 l, i=0;
-	u8 *p;
+	u_char l, i=0;
+	u_char *p;
 
 	p = skb->data;
 	pc->para.cause = 31;
@@ -931,11 +923,11 @@ l3dss1_get_cause(struct l3_process *pc, 
 }
 
 static void
-l3dss1_msg_with_uus(struct l3_process *pc, u8 cmd)
+l3dss1_msg_with_uus(struct l3_process *pc, u_char cmd)
 {
 	struct sk_buff *skb;
-	u8 tmp[16+40];
-	u8 *p = tmp;
+	u_char tmp[16+40];
+	u_char *p = tmp;
 	int l;
 
 	MsgHead(p, pc->callref, cmd);
@@ -957,7 +949,7 @@ l3dss1_msg_with_uus(struct l3_process *p
 } /* l3dss1_msg_with_uus */
 
 static void
-l3dss1_release_req(struct l3_process *pc, u8 pr, void *arg)
+l3dss1_release_req(struct l3_process *pc, u_char pr, void *arg)
 {
 	StopAllL3Timer(pc);
 	newl3state(pc, 19);
@@ -969,7 +961,7 @@ l3dss1_release_req(struct l3_process *pc
 }
 
 static void
-l3dss1_release_cmpl(struct l3_process *pc, u8 pr, void *arg)
+l3dss1_release_cmpl(struct l3_process *pc, u_char pr, void *arg)
 {
 	struct sk_buff *skb = arg;
 	int ret;
@@ -981,14 +973,14 @@ l3dss1_release_cmpl(struct l3_process *p
 		pc->para.cause = NO_CAUSE;
 	StopAllL3Timer(pc);
 	newl3state(pc, 0);
-	L3L4(pc->st, CC_RELEASE | CONFIRM, pc);
+	pc->st->l3.l3l4(pc->st, CC_RELEASE | CONFIRM, pc);
 	dss1_release_l3_process(pc);
 }
 
 #if EXT_BEARER_CAPS
 
-static u8 *
-EncodeASyncParams(u8 * p, u8 si2)
+static u_char *
+EncodeASyncParams(u_char * p, u_char si2)
 {				// 7c 06 88  90 21 42 00 bb
 
 	p[0] = 0;
@@ -1052,8 +1044,8 @@ EncodeASyncParams(u8 * p, u8 si2)
 	return p + 3;
 }
 
-static  u8
-EncodeSyncParams(u8 si2, u8 ai)
+static  u_char
+EncodeSyncParams(u_char si2, u_char ai)
 {
 
 	switch (si2) {
@@ -1097,10 +1089,10 @@ EncodeSyncParams(u8 si2, u8 ai)
 }
 
 
-static u8
-DecodeASyncParams(u8 si2, u8 * p)
+static u_char
+DecodeASyncParams(u_char si2, u_char * p)
 {
-	u8 info;
+	u_char info;
 
 	switch (p[5]) {
 		case 66:	// 1200 bit/s
@@ -1154,8 +1146,8 @@ DecodeASyncParams(u8 si2, u8 * p)
 }
 
 
-static u8
-DecodeSyncParams(u8 si2, u8 info)
+static u_char
+DecodeSyncParams(u_char si2, u_char info)
 {
 	info &= 0x7f;
 	switch (info) {
@@ -1195,10 +1187,10 @@ DecodeSyncParams(u8 si2, u8 info)
 	}
 }
 
-static u8
+static u_char
 DecodeSI2(struct sk_buff *skb)
 {
-	u8 *p;		//, *pend=skb->data + skb->len;
+	u_char *p;		//, *pend=skb->data + skb->len;
 
 	if ((p = findie(skb->data, skb->len, 0x7c, 0))) {
 		switch (p[4] & 0x0f) {
@@ -1225,20 +1217,20 @@ DecodeSI2(struct sk_buff *skb)
 
 
 static void
-l3dss1_setup_req(struct l3_process *pc, u8 pr,
+l3dss1_setup_req(struct l3_process *pc, u_char pr,
 		 void *arg)
 {
 	struct sk_buff *skb;
-	u8 tmp[128];
-	u8 *p = tmp;
-	u8 channel = 0;
-
-        u8 send_keypad;
-	u8 screen = 0x80;
-	u8 *teln;
-	u8 *msn;
-	u8 *sub;
-	u8 *sp;
+	u_char tmp[128];
+	u_char *p = tmp;
+	u_char channel = 0;
+
+        u_char send_keypad;
+	u_char screen = 0x80;
+	u_char *teln;
+	u_char *msn;
+	u_char *sub;
+	u_char *sp;
 	int l;
 
 	MsgHead(p, pc->callref, MT_SETUP);
@@ -1436,7 +1428,7 @@ l3dss1_setup_req(struct l3_process *pc, 
 }
 
 static void
-l3dss1_call_proc(struct l3_process *pc, u8 pr, void *arg)
+l3dss1_call_proc(struct l3_process *pc, u_char pr, void *arg)
 {
 	struct sk_buff *skb = arg;
 	int id, ret;
@@ -1471,11 +1463,11 @@ l3dss1_call_proc(struct l3_process *pc, 
 	L3AddTimer(&pc->timer, T310, CC_T310);
 	if (ret) /* STATUS for none mandatory IE errors after actions are taken */
 		l3dss1_std_ie_err(pc, ret);
-	L3L4(pc->st, CC_PROCEEDING | INDICATION, pc);
+	pc->st->l3.l3l4(pc->st, CC_PROCEEDING | INDICATION, pc);
 }
 
 static void
-l3dss1_setup_ack(struct l3_process *pc, u8 pr, void *arg)
+l3dss1_setup_ack(struct l3_process *pc, u_char pr, void *arg)
 {
 	struct sk_buff *skb = arg;
 	int id, ret;
@@ -1510,16 +1502,16 @@ l3dss1_setup_ack(struct l3_process *pc, 
 	L3AddTimer(&pc->timer, T304, CC_T304);
 	if (ret) /* STATUS for none mandatory IE errors after actions are taken */
 		l3dss1_std_ie_err(pc, ret);
-	L3L4(pc->st, CC_MORE_INFO | INDICATION, pc);
+	pc->st->l3.l3l4(pc->st, CC_MORE_INFO | INDICATION, pc);
 }
 
 static void
-l3dss1_disconnect(struct l3_process *pc, u8 pr, void *arg)
+l3dss1_disconnect(struct l3_process *pc, u_char pr, void *arg)
 {
 	struct sk_buff *skb = arg;
-	u8 *p;
+	u_char *p;
 	int ret;
-	u8 cause = 0;
+	u_char cause = 0;
 
 	StopAllL3Timer(pc);
 	if ((ret = l3dss1_get_cause(pc, skb))) {
@@ -1542,7 +1534,7 @@ l3dss1_disconnect(struct l3_process *pc,
 	if (cause)
 		newl3state(pc, 19);
        	if (11 != ret)
-		L3L4(pc->st, CC_DISCONNECT | INDICATION, pc);
+		pc->st->l3.l3l4(pc->st, CC_DISCONNECT | INDICATION, pc);
        	else if (!cause)
 		   l3dss1_release_req(pc, pr, NULL);
 	if (cause) {
@@ -1552,7 +1544,7 @@ l3dss1_disconnect(struct l3_process *pc,
 }
 
 static void
-l3dss1_connect(struct l3_process *pc, u8 pr, void *arg)
+l3dss1_connect(struct l3_process *pc, u_char pr, void *arg)
 {
 	struct sk_buff *skb = arg;
 	int ret;
@@ -1568,11 +1560,11 @@ l3dss1_connect(struct l3_process *pc, u8
 	/* here should inserted COLP handling KKe */
 	if (ret)
 		l3dss1_std_ie_err(pc, ret);
-	L3L4(pc->st, CC_SETUP | CONFIRM, pc);
+	pc->st->l3.l3l4(pc->st, CC_SETUP | CONFIRM, pc);
 }
 
 static void
-l3dss1_alerting(struct l3_process *pc, u8 pr, void *arg)
+l3dss1_alerting(struct l3_process *pc, u_char pr, void *arg)
 {
 	struct sk_buff *skb = arg;
 	int ret;
@@ -1586,13 +1578,13 @@ l3dss1_alerting(struct l3_process *pc, u
 	newl3state(pc, 4);
 	if (ret)
 		l3dss1_std_ie_err(pc, ret);
-	L3L4(pc->st, CC_ALERTING | INDICATION, pc);
+	pc->st->l3.l3l4(pc->st, CC_ALERTING | INDICATION, pc);
 }
 
 static void
-l3dss1_setup(struct l3_process *pc, u8 pr, void *arg)
+l3dss1_setup(struct l3_process *pc, u_char pr, void *arg)
 {
-	u8 *p;
+	u_char *p;
 	int bcfound = 0;
 	char tmp[80];
 	struct sk_buff *skb = arg;
@@ -1603,7 +1595,7 @@ l3dss1_setup(struct l3_process *pc, u8 p
 	 * Bearer Capabilities
 	 */
 	p = skb->data;
-	/* only the first occurrence 'll be detected ! */
+	/* only the first occurence 'll be detected ! */
 	if ((p = findie(p, skb->len, 0x04, 0))) {
 		if ((p[1] < 2) || (p[1] > 11))
 			err = 1;
@@ -1752,23 +1744,23 @@ l3dss1_setup(struct l3_process *pc, u8 p
 	newl3state(pc, 6);
 	if (err) /* STATUS for none mandatory IE errors after actions are taken */
 		l3dss1_std_ie_err(pc, err);
-	L3L4(pc->st, CC_SETUP | INDICATION, pc);
+	pc->st->l3.l3l4(pc->st, CC_SETUP | INDICATION, pc);
 }
 
 static void
-l3dss1_reset(struct l3_process *pc, u8 pr, void *arg)
+l3dss1_reset(struct l3_process *pc, u_char pr, void *arg)
 {
 	dss1_release_l3_process(pc);
 }
 
 static void
-l3dss1_disconnect_req(struct l3_process *pc, u8 pr, void *arg)
+l3dss1_disconnect_req(struct l3_process *pc, u_char pr, void *arg)
 {
 	struct sk_buff *skb;
-	u8 tmp[16+40];
-	u8 *p = tmp;
+	u_char tmp[16+40];
+	u_char *p = tmp;
 	int l;
-	u8 cause = 16;
+	u_char cause = 16;
 
 	if (pc->para.cause != NO_CAUSE)
 		cause = pc->para.cause;
@@ -1801,7 +1793,7 @@ l3dss1_disconnect_req(struct l3_process 
 }
 
 static void
-l3dss1_setup_rsp(struct l3_process *pc, u8 pr,
+l3dss1_setup_rsp(struct l3_process *pc, u_char pr,
 		 void *arg)
 {
         if (!pc->para.bchannel) 
@@ -1817,7 +1809,7 @@ l3dss1_setup_rsp(struct l3_process *pc, 
 }
 
 static void
-l3dss1_connect_ack(struct l3_process *pc, u8 pr, void *arg)
+l3dss1_connect_ack(struct l3_process *pc, u_char pr, void *arg)
 {
 	struct sk_buff *skb = arg;
 	int ret;
@@ -1831,17 +1823,17 @@ l3dss1_connect_ack(struct l3_process *pc
 	L3DelTimer(&pc->timer);
 	if (ret)
 		l3dss1_std_ie_err(pc, ret);
-	L3L4(pc->st, CC_SETUP_COMPL | INDICATION, pc);
+	pc->st->l3.l3l4(pc->st, CC_SETUP_COMPL | INDICATION, pc);
 }
 
 static void
-l3dss1_reject_req(struct l3_process *pc, u8 pr, void *arg)
+l3dss1_reject_req(struct l3_process *pc, u_char pr, void *arg)
 {
 	struct sk_buff *skb;
-	u8 tmp[16];
-	u8 *p = tmp;
+	u_char tmp[16];
+	u_char *p = tmp;
 	int l;
-	u8 cause = 21;
+	u_char cause = 21;
 
 	if (pc->para.cause != NO_CAUSE)
 		cause = pc->para.cause;
@@ -1858,16 +1850,16 @@ l3dss1_reject_req(struct l3_process *pc,
 		return;
 	memcpy(skb_put(skb, l), tmp, l);
 	l3_msg(pc->st, DL_DATA | REQUEST, skb);
-	L3L4(pc->st, CC_RELEASE | INDICATION, pc);
+	pc->st->l3.l3l4(pc->st, CC_RELEASE | INDICATION, pc);
 	newl3state(pc, 0);
 	dss1_release_l3_process(pc);
 }
 
 static void
-l3dss1_release(struct l3_process *pc, u8 pr, void *arg)
+l3dss1_release(struct l3_process *pc, u_char pr, void *arg)
 {
 	struct sk_buff *skb = arg;
-	u8 *p;
+	u_char *p;
 	int ret, cause=0;
 
 	StopAllL3Timer(pc);
@@ -1892,13 +1884,13 @@ l3dss1_release(struct l3_process *pc, u8
 		l3dss1_message_cause(pc, MT_RELEASE_COMPLETE, cause);
 	else
 		l3dss1_message(pc, MT_RELEASE_COMPLETE);
-	L3L4(pc->st, CC_RELEASE | INDICATION, pc);
+	pc->st->l3.l3l4(pc->st, CC_RELEASE | INDICATION, pc);
 	newl3state(pc, 0);
 	dss1_release_l3_process(pc);
 }
 
 static void
-l3dss1_alert_req(struct l3_process *pc, u8 pr,
+l3dss1_alert_req(struct l3_process *pc, u_char pr,
 		 void *arg)
 {
 	newl3state(pc, 7);
@@ -1909,16 +1901,16 @@ l3dss1_alert_req(struct l3_process *pc, 
 }
 
 static void
-l3dss1_proceed_req(struct l3_process *pc, u8 pr,
+l3dss1_proceed_req(struct l3_process *pc, u_char pr,
 		   void *arg)
 {
 	newl3state(pc, 9);
 	l3dss1_message(pc, MT_CALL_PROCEEDING);
-	L3L4(pc->st, CC_PROCEED_SEND | INDICATION, pc); 
+	pc->st->l3.l3l4(pc->st, CC_PROCEED_SEND | INDICATION, pc); 
 }
 
 static void
-l3dss1_setup_ack_req(struct l3_process *pc, u8 pr,
+l3dss1_setup_ack_req(struct l3_process *pc, u_char pr,
 		   void *arg)
 {
 	newl3state(pc, 25);
@@ -1931,8 +1923,8 @@ l3dss1_setup_ack_req(struct l3_process *
 /* deliver a incoming display message to HL */
 /********************************************/
 static void
-l3dss1_deliver_display(struct l3_process *pc, int pr, u8 *infp)
-{       u8 len;
+l3dss1_deliver_display(struct l3_process *pc, int pr, u_char *infp)
+{       u_char len;
         isdn_ctrl ic; 
 	struct IsdnCardState *cs;
         char *p; 
@@ -1954,11 +1946,11 @@ l3dss1_deliver_display(struct l3_process
 
 
 static void
-l3dss1_progress(struct l3_process *pc, u8 pr, void *arg)
+l3dss1_progress(struct l3_process *pc, u_char pr, void *arg)
 {
 	struct sk_buff *skb = arg;
 	int err = 0;
-	u8 *p;
+	u_char *p;
 
 	if ((p = findie(skb->data, skb->len, IE_PROGRESS, 0))) {
 		if (p[1] != 2) {
@@ -2007,15 +1999,15 @@ l3dss1_progress(struct l3_process *pc, u
 	if (err)
 		l3dss1_std_ie_err(pc, err);
 	if (ERR_IE_COMPREHENSION != err)
-		L3L4(pc->st, CC_PROGRESS | INDICATION, pc);
+		pc->st->l3.l3l4(pc->st, CC_PROGRESS | INDICATION, pc);
 }
 
 static void
-l3dss1_notify(struct l3_process *pc, u8 pr, void *arg)
+l3dss1_notify(struct l3_process *pc, u_char pr, void *arg)
 {
 	struct sk_buff *skb = arg;
 	int err = 0;
-	u8 *p;
+	u_char *p;
 
 	if ((p = findie(skb->data, skb->len, IE_NOTIFY, 0))) {
 		if (p[1] != 1) {
@@ -2048,11 +2040,11 @@ l3dss1_notify(struct l3_process *pc, u8 
 	if (err)
 		l3dss1_std_ie_err(pc, err);
 	if (ERR_IE_COMPREHENSION != err)
-		L3L4(pc->st, CC_NOTIFY | INDICATION, pc);
+		pc->st->l3.l3l4(pc->st, CC_NOTIFY | INDICATION, pc);
 }
 
 static void
-l3dss1_status_enq(struct l3_process *pc, u8 pr, void *arg)
+l3dss1_status_enq(struct l3_process *pc, u_char pr, void *arg)
 {
 	int ret;
 	struct sk_buff *skb = arg;
@@ -2064,11 +2056,11 @@ l3dss1_status_enq(struct l3_process *pc,
 }
 
 static void
-l3dss1_information(struct l3_process *pc, u8 pr, void *arg)
+l3dss1_information(struct l3_process *pc, u_char pr, void *arg)
 {
 	int ret;
 	struct sk_buff *skb = arg;
-	u8 *p;
+	u_char *p;
 	char tmp[32];
 
 	ret = check_infoelements(pc, skb, ie_INFORMATION);
@@ -2080,7 +2072,7 @@ l3dss1_information(struct l3_process *pc
 		if ((p = findie(p, skb->len, 0x70, 0))) {
 			iecpy(tmp, p, 1);
 			strcat(pc->para.setup.eazmsn, tmp);
-			L3L4(pc->st, CC_MORE_INFO | INDICATION, pc);
+			pc->st->l3.l3l4(pc->st, CC_MORE_INFO | INDICATION, pc);
 		}
 		L3AddTimer(&pc->timer, T302, CC_T302);
 	}
@@ -2089,14 +2081,14 @@ l3dss1_information(struct l3_process *pc
 /******************************/
 /* handle deflection requests */
 /******************************/
-static void l3dss1_redir_req(struct l3_process *pc, u8 pr, void *arg)
+static void l3dss1_redir_req(struct l3_process *pc, u_char pr, void *arg)
 {
 	struct sk_buff *skb;
-	u8 tmp[128];
-	u8 *p = tmp;
-        u8 *subp;
-        u8 len_phone = 0;
-        u8 len_sub = 0;
+	u_char tmp[128];
+	u_char *p = tmp;
+        u_char *subp;
+        u_char len_phone = 0;
+        u_char len_sub = 0;
 	int l; 
 
 
@@ -2161,7 +2153,7 @@ static void l3dss1_redir_req(struct l3_p
 /********************************************/
 /* handle deflection request in early state */
 /********************************************/
-static void l3dss1_redir_req_early(struct l3_process *pc, u8 pr, void *arg)
+static void l3dss1_redir_req_early(struct l3_process *pc, u_char pr, void *arg)
 {
   l3dss1_proceed_req(pc,pr,arg);
   l3dss1_redir_req(pc,pr,arg);
@@ -2169,13 +2161,13 @@ static void l3dss1_redir_req_early(struc
 
 /***********************************************/
 /* handle special commands for this protocol.  */
-/* Examples are call independent services like */
+/* Examples are call independant services like */
 /* remote operations with dummy  callref.      */
 /***********************************************/
 static int l3dss1_cmd_global(struct PStack *st, isdn_ctrl *ic)
-{ u8 id;
-  u8 temp[265];
-  u8 *p = temp;
+{ u_char id;
+  u_char temp[265];
+  u_char *p = temp;
   int i, l, proc_len; 
   struct sk_buff *skb;
   struct l3_process *pc = NULL;
@@ -2279,9 +2271,9 @@ l3dss1_io_timer(struct l3_process *pc)
 } /* l3dss1_io_timer */
 
 static void
-l3dss1_release_ind(struct l3_process *pc, u8 pr, void *arg)
+l3dss1_release_ind(struct l3_process *pc, u_char pr, void *arg)
 {
-	u8 *p;
+	u_char *p;
 	struct sk_buff *skb = arg;
 	int callState = 0;
 	p = skb->data;
@@ -2295,31 +2287,31 @@ l3dss1_release_ind(struct l3_process *pc
 		/* ETS 300-104 7.6.1, 8.6.1, 10.6.1... and 16.1
 		 * set down layer 3 without sending any message
 		 */
-		L3L4(pc->st, CC_RELEASE | INDICATION, pc);
+		pc->st->l3.l3l4(pc->st, CC_RELEASE | INDICATION, pc);
 		newl3state(pc, 0);
 		dss1_release_l3_process(pc);
 	} else {
-		L3L4(pc->st, CC_IGNORE | INDICATION, pc);
+		pc->st->l3.l3l4(pc->st, CC_IGNORE | INDICATION, pc);
 	}
 }
 
 static void
-l3dss1_dummy(struct l3_process *pc, u8 pr, void *arg)
+l3dss1_dummy(struct l3_process *pc, u_char pr, void *arg)
 {
 }
 
 static void
-l3dss1_t302(struct l3_process *pc, u8 pr, void *arg)
+l3dss1_t302(struct l3_process *pc, u_char pr, void *arg)
 {
 	L3DelTimer(&pc->timer);
 	pc->para.loc = 0;
 	pc->para.cause = 28; /* invalid number */
 	l3dss1_disconnect_req(pc, pr, NULL);
-	L3L4(pc->st, CC_SETUP_ERR, pc);
+	pc->st->l3.l3l4(pc->st, CC_SETUP_ERR, pc);
 }
 
 static void
-l3dss1_t303(struct l3_process *pc, u8 pr, void *arg)
+l3dss1_t303(struct l3_process *pc, u_char pr, void *arg)
 {
 	if (pc->N303 > 0) {
 		pc->N303--;
@@ -2328,30 +2320,30 @@ l3dss1_t303(struct l3_process *pc, u8 pr
 	} else {
 		L3DelTimer(&pc->timer);
 		l3dss1_message_cause(pc, MT_RELEASE_COMPLETE, 102);
-		L3L4(pc->st, CC_NOSETUP_RSP, pc);
+		pc->st->l3.l3l4(pc->st, CC_NOSETUP_RSP, pc);
 		dss1_release_l3_process(pc);
 	}
 }
 
 static void
-l3dss1_t304(struct l3_process *pc, u8 pr, void *arg)
+l3dss1_t304(struct l3_process *pc, u_char pr, void *arg)
 {
 	L3DelTimer(&pc->timer);
 	pc->para.loc = 0;
 	pc->para.cause = 102;
 	l3dss1_disconnect_req(pc, pr, NULL);
-	L3L4(pc->st, CC_SETUP_ERR, pc);
+	pc->st->l3.l3l4(pc->st, CC_SETUP_ERR, pc);
 
 }
 
 static void
-l3dss1_t305(struct l3_process *pc, u8 pr, void *arg)
+l3dss1_t305(struct l3_process *pc, u_char pr, void *arg)
 {
-	u8 tmp[16];
-	u8 *p = tmp;
+	u_char tmp[16];
+	u_char *p = tmp;
 	int l;
 	struct sk_buff *skb;
-	u8 cause = 16;
+	u_char cause = 16;
 
 	L3DelTimer(&pc->timer);
 	if (pc->para.cause != NO_CAUSE)
@@ -2374,27 +2366,27 @@ l3dss1_t305(struct l3_process *pc, u8 pr
 }
 
 static void
-l3dss1_t310(struct l3_process *pc, u8 pr, void *arg)
+l3dss1_t310(struct l3_process *pc, u_char pr, void *arg)
 {
 	L3DelTimer(&pc->timer);
 	pc->para.loc = 0;
 	pc->para.cause = 102;
 	l3dss1_disconnect_req(pc, pr, NULL);
-	L3L4(pc->st, CC_SETUP_ERR, pc);
+	pc->st->l3.l3l4(pc->st, CC_SETUP_ERR, pc);
 }
 
 static void
-l3dss1_t313(struct l3_process *pc, u8 pr, void *arg)
+l3dss1_t313(struct l3_process *pc, u_char pr, void *arg)
 {
 	L3DelTimer(&pc->timer);
 	pc->para.loc = 0;
 	pc->para.cause = 102;
 	l3dss1_disconnect_req(pc, pr, NULL);
-	L3L4(pc->st, CC_CONNECT_ERR, pc);
+	pc->st->l3.l3l4(pc->st, CC_CONNECT_ERR, pc);
 }
 
 static void
-l3dss1_t308_1(struct l3_process *pc, u8 pr, void *arg)
+l3dss1_t308_1(struct l3_process *pc, u_char pr, void *arg)
 {
 	newl3state(pc, 19);
 	L3DelTimer(&pc->timer);
@@ -2403,50 +2395,50 @@ l3dss1_t308_1(struct l3_process *pc, u8 
 }
 
 static void
-l3dss1_t308_2(struct l3_process *pc, u8 pr, void *arg)
+l3dss1_t308_2(struct l3_process *pc, u_char pr, void *arg)
 {
 	L3DelTimer(&pc->timer);
-	L3L4(pc->st, CC_RELEASE_ERR, pc);
+	pc->st->l3.l3l4(pc->st, CC_RELEASE_ERR, pc);
 	dss1_release_l3_process(pc);
 }
 
 static void
-l3dss1_t318(struct l3_process *pc, u8 pr, void *arg)
+l3dss1_t318(struct l3_process *pc, u_char pr, void *arg)
 {
 	L3DelTimer(&pc->timer);
 	pc->para.cause = 102;	/* Timer expiry */
 	pc->para.loc = 0;	/* local */
-	L3L4(pc->st, CC_RESUME_ERR, pc);
+	pc->st->l3.l3l4(pc->st, CC_RESUME_ERR, pc);
 	newl3state(pc, 19);
 	l3dss1_message(pc, MT_RELEASE);
 	L3AddTimer(&pc->timer, T308, CC_T308_1);
 }
 
 static void
-l3dss1_t319(struct l3_process *pc, u8 pr, void *arg)
+l3dss1_t319(struct l3_process *pc, u_char pr, void *arg)
 {
 	L3DelTimer(&pc->timer);
 	pc->para.cause = 102;	/* Timer expiry */
 	pc->para.loc = 0;	/* local */
-	L3L4(pc->st, CC_SUSPEND_ERR, pc);
+	pc->st->l3.l3l4(pc->st, CC_SUSPEND_ERR, pc);
 	newl3state(pc, 10);
 }
 
 static void
-l3dss1_restart(struct l3_process *pc, u8 pr, void *arg)
+l3dss1_restart(struct l3_process *pc, u_char pr, void *arg)
 {
 	L3DelTimer(&pc->timer);
-	L3L4(pc->st, CC_RELEASE | INDICATION, pc);
+	pc->st->l3.l3l4(pc->st, CC_RELEASE | INDICATION, pc);
 	dss1_release_l3_process(pc);
 }
 
 static void
-l3dss1_status(struct l3_process *pc, u8 pr, void *arg)
+l3dss1_status(struct l3_process *pc, u_char pr, void *arg)
 {
-	u8 *p;
+	u_char *p;
 	struct sk_buff *skb = arg;
 	int ret; 
-	u8 cause = 0, callState = 0;
+	u_char cause = 0, callState = 0;
 	
 	if ((ret = l3dss1_get_cause(pc, skb))) {
 		if (pc->debug & L3_DEB_WARN)
@@ -2474,7 +2466,7 @@ l3dss1_status(struct l3_process *pc, u8 
 			cause = 99;
 	}
 	if (cause) {
-		u8 tmp;
+		u_char tmp;
 		
 		if (pc->debug & L3_DEB_WARN)
 			l3_debug(pc->st, "STATUS error(%d/%d)",ret,cause);
@@ -2492,14 +2484,14 @@ l3dss1_status(struct l3_process *pc, u8 
 		 * if received MT_STATUS with cause == 111 and call
 		 * state == 0, then we must set down layer 3
 		 */
-		L3L4(pc->st, CC_RELEASE | INDICATION, pc);
+		pc->st->l3.l3l4(pc->st, CC_RELEASE | INDICATION, pc);
 		newl3state(pc, 0);
 		dss1_release_l3_process(pc);
 	}
 }
 
 static void
-l3dss1_facility(struct l3_process *pc, u8 pr, void *arg)
+l3dss1_facility(struct l3_process *pc, u_char pr, void *arg)
 {
 	struct sk_buff *skb = arg;
 	int ret;
@@ -2507,20 +2499,20 @@ l3dss1_facility(struct l3_process *pc, u
 	ret = check_infoelements(pc, skb, ie_FACILITY);
 	l3dss1_std_ie_err(pc, ret);
  	  {
-		u8 *p;
+		u_char *p;
 		if ((p = findie(skb->data, skb->len, IE_FACILITY, 0)))
 			l3dss1_parse_facility(pc->st, pc, pc->callref, p);
 	}
 }
 
 static void
-l3dss1_suspend_req(struct l3_process *pc, u8 pr, void *arg)
+l3dss1_suspend_req(struct l3_process *pc, u_char pr, void *arg)
 {
 	struct sk_buff *skb;
-	u8 tmp[32];
-	u8 *p = tmp;
-	u8 i, l;
-	u8 *msg = pc->chan->setup.phone;
+	u_char tmp[32];
+	u_char *p = tmp;
+	u_char i, l;
+	u_char *msg = pc->chan->setup.phone;
 
 	MsgHead(p, pc->callref, MT_SUSPEND);
 	l = *msg++;
@@ -2543,7 +2535,7 @@ l3dss1_suspend_req(struct l3_process *pc
 }
 
 static void
-l3dss1_suspend_ack(struct l3_process *pc, u8 pr, void *arg)
+l3dss1_suspend_ack(struct l3_process *pc, u_char pr, void *arg)
 {
 	struct sk_buff *skb = arg;
 	int ret;
@@ -2551,7 +2543,7 @@ l3dss1_suspend_ack(struct l3_process *pc
 	L3DelTimer(&pc->timer);
 	newl3state(pc, 0);
 	pc->para.cause = NO_CAUSE;
-	L3L4(pc->st, CC_SUSPEND | CONFIRM, pc);
+	pc->st->l3.l3l4(pc->st, CC_SUSPEND | CONFIRM, pc);
 	/* We don't handle suspend_ack for IE errors now */
 	if ((ret = check_infoelements(pc, skb, ie_SUSPEND_ACKNOWLEDGE)))
 		if (pc->debug & L3_DEB_WARN)
@@ -2560,7 +2552,7 @@ l3dss1_suspend_ack(struct l3_process *pc
 }
 
 static void
-l3dss1_suspend_rej(struct l3_process *pc, u8 pr, void *arg)
+l3dss1_suspend_rej(struct l3_process *pc, u_char pr, void *arg)
 {
 	struct sk_buff *skb = arg;
 	int ret;
@@ -2581,20 +2573,20 @@ l3dss1_suspend_rej(struct l3_process *pc
 		return;
 	}
 	L3DelTimer(&pc->timer);
-	L3L4(pc->st, CC_SUSPEND_ERR, pc);
+	pc->st->l3.l3l4(pc->st, CC_SUSPEND_ERR, pc);
 	newl3state(pc, 10);
 	if (ret) /* STATUS for none mandatory IE errors after actions are taken */
 		l3dss1_std_ie_err(pc, ret);
 }
 
 static void
-l3dss1_resume_req(struct l3_process *pc, u8 pr, void *arg)
+l3dss1_resume_req(struct l3_process *pc, u_char pr, void *arg)
 {
 	struct sk_buff *skb;
-	u8 tmp[32];
-	u8 *p = tmp;
-	u8 i, l;
-	u8 *msg = pc->para.setup.phone;
+	u_char tmp[32];
+	u_char *p = tmp;
+	u_char i, l;
+	u_char *msg = pc->para.setup.phone;
 
 	MsgHead(p, pc->callref, MT_RESUME);
 
@@ -2618,7 +2610,7 @@ l3dss1_resume_req(struct l3_process *pc,
 }
 
 static void
-l3dss1_resume_ack(struct l3_process *pc, u8 pr, void *arg)
+l3dss1_resume_ack(struct l3_process *pc, u_char pr, void *arg)
 {
 	struct sk_buff *skb = arg;
 	int id, ret;
@@ -2645,14 +2637,14 @@ l3dss1_resume_ack(struct l3_process *pc,
 		return;
 	}
 	L3DelTimer(&pc->timer);
-	L3L4(pc->st, CC_RESUME | CONFIRM, pc);
+	pc->st->l3.l3l4(pc->st, CC_RESUME | CONFIRM, pc);
 	newl3state(pc, 10);
 	if (ret) /* STATUS for none mandatory IE errors after actions are taken */
 		l3dss1_std_ie_err(pc, ret);
 }
 
 static void
-l3dss1_resume_rej(struct l3_process *pc, u8 pr, void *arg)
+l3dss1_resume_rej(struct l3_process *pc, u_char pr, void *arg)
 {
 	struct sk_buff *skb = arg;
 	int ret;
@@ -2673,7 +2665,7 @@ l3dss1_resume_rej(struct l3_process *pc,
 		return;
 	}
 	L3DelTimer(&pc->timer);
-	L3L4(pc->st, CC_RESUME_ERR, pc);
+	pc->st->l3.l3l4(pc->st, CC_RESUME_ERR, pc);
 	newl3state(pc, 0);
 	if (ret) /* STATUS for none mandatory IE errors after actions are taken */
 		l3dss1_std_ie_err(pc, ret);
@@ -2681,11 +2673,11 @@ l3dss1_resume_rej(struct l3_process *pc,
 }
 
 static void
-l3dss1_global_restart(struct l3_process *pc, u8 pr, void *arg)
+l3dss1_global_restart(struct l3_process *pc, u_char pr, void *arg)
 {
-	u8 tmp[32];
-	u8 *p;
-	u8 ri, ch = 0, chan = 0;
+	u_char tmp[32];
+	u_char *p;
+	u_char ri, ch = 0, chan = 0;
 	int l;
 	struct sk_buff *skb = arg;
 	struct l3_process *up;
@@ -2711,9 +2703,9 @@ l3dss1_global_restart(struct l3_process 
 	up = pc->st->l3.proc;
 	while (up) {
 		if ((ri & 7) == 7)
-			L4L3(up->st, CC_RESTART | REQUEST, up);
+			up->st->lli.l4l3(up->st, CC_RESTART | REQUEST, up);
 		else if (up->para.bchannel == chan)
-			L4L3(up->st, CC_RESTART | REQUEST, up);
+			up->st->lli.l4l3(up->st, CC_RESTART | REQUEST, up);
 		up = up->next;
 	}
 	p = tmp;
@@ -2735,26 +2727,26 @@ l3dss1_global_restart(struct l3_process 
 }
 
 static void
-l3dss1_dl_reset(struct l3_process *pc, u8 pr, void *arg)
+l3dss1_dl_reset(struct l3_process *pc, u_char pr, void *arg)
 {
         pc->para.cause = 0x29;          /* Temporary failure */
         pc->para.loc = 0;
         l3dss1_disconnect_req(pc, pr, NULL);
-        L3L4(pc->st, CC_SETUP_ERR, pc);
+        pc->st->l3.l3l4(pc->st, CC_SETUP_ERR, pc);
 }
 
 static void
-l3dss1_dl_release(struct l3_process *pc, u8 pr, void *arg)
+l3dss1_dl_release(struct l3_process *pc, u_char pr, void *arg)
 {
         newl3state(pc, 0);
         pc->para.cause = 0x1b;          /* Destination out of order */
         pc->para.loc = 0;
-        L3L4(pc->st, CC_RELEASE | INDICATION, pc);
+        pc->st->l3.l3l4(pc->st, CC_RELEASE | INDICATION, pc);
         release_l3_process(pc);
 }
 
 static void
-l3dss1_dl_reestablish(struct l3_process *pc, u8 pr, void *arg)
+l3dss1_dl_reestablish(struct l3_process *pc, u_char pr, void *arg)
 {
         L3DelTimer(&pc->timer);
         L3AddTimer(&pc->timer, T309, CC_T309);
@@ -2762,7 +2754,7 @@ l3dss1_dl_reestablish(struct l3_process 
 }
  
 static void
-l3dss1_dl_reest_status(struct l3_process *pc, u8 pr, void *arg)
+l3dss1_dl_reest_status(struct l3_process *pc, u_char pr, void *arg)
 {
 	L3DelTimer(&pc->timer);
  
@@ -2920,10 +2912,10 @@ static struct stateentry manstatelist[] 
 static void
 global_handler(struct PStack *st, int mt, struct sk_buff *skb)
 {
-	u8 tmp[16];
-	u8 *p = tmp;
+	u_char tmp[16];
+	u_char *p = tmp;
 	int l;
-	u_int i;
+	int i;
 	struct l3_process *proc = st->l3.global;
 
 	proc->callref = skb->data[2]; /* cr flag */
@@ -2961,10 +2953,9 @@ global_handler(struct PStack *st, int mt
 static void
 dss1up(struct PStack *st, int pr, void *arg)
 {
-	u_int i;
-	int mt, cr, cause, callState;
+	int i, mt, cr, cause, callState;
 	char *ptr;
-	u8 *p;
+	u_char *p;
 	struct sk_buff *skb = arg;
 	struct l3_process *proc;
 
@@ -2999,7 +2990,7 @@ dss1up(struct PStack *st, int pr, void *
 		return;
 	}
 	cr = getcallref(skb->data);
-	if (skb->len < (u_int)((skb->data[1] & 0x0f) + 3)) {
+	if (skb->len < ((skb->data[1] & 0x0f) + 3)) {
 		l3_debug(st, "dss1up frame too short(%d)", skb->len);
 		dev_kfree_skb(skb);
 		return;
@@ -3136,8 +3127,7 @@ dss1up(struct PStack *st, int pr, void *
 static void
 dss1down(struct PStack *st, int pr, void *arg)
 {
-	u_int i;
-	int cr;
+	int i, cr;
 	struct l3_process *proc;
 	struct Channel *chan;
 
@@ -3188,29 +3178,29 @@ dss1down(struct PStack *st, int pr, void
 static void
 dss1man(struct PStack *st, int pr, void *arg)
 {
-	u_int i;
-	struct l3_process *proc = arg;
-
-	if (!proc) {
-		printk(KERN_ERR "HiSax dss1man without proc pr=%04x\n", pr);
-		return;
-	}
-	for (i = 0; i < MANSLLEN; i++)
+        int i;
+        struct l3_process *proc = arg;
+ 
+        if (!proc) {
+                printk(KERN_ERR "HiSax dss1man without proc pr=%04x\n", pr);
+                return;
+        }
+        for (i = 0; i < MANSLLEN; i++)
                 if ((pr == manstatelist[i].primitive) &&
-			((1 << proc->state) & manstatelist[i].state))
-			break;
-	if (i == MANSLLEN) {
-		if (st->l3.debug & L3_DEB_STATE) {
-			l3_debug(st, "cr %d dss1man state %d prim %#x unhandled",
-				proc->callref & 0x7f, proc->state, pr);
-		}
-	} else {
-		if (st->l3.debug & L3_DEB_STATE) {
-			l3_debug(st, "cr %d dss1man state %d prim %#x",
-				proc->callref & 0x7f, proc->state, pr);
-		}
-		manstatelist[i].rout(proc, pr, arg);
-	}
+                    ((1 << proc->state) & manstatelist[i].state))
+                        break;
+        if (i == MANSLLEN) {
+                if (st->l3.debug & L3_DEB_STATE) {
+                        l3_debug(st, "cr %d dss1man state %d prim %#x unhandled",
+                                proc->callref & 0x7f, proc->state, pr);
+                }
+        } else {
+                if (st->l3.debug & L3_DEB_STATE) {
+                        l3_debug(st, "cr %d dss1man state %d prim %#x",
+                                proc->callref & 0x7f, proc->state, pr);
+                }
+                manstatelist[i].rout(proc, pr, arg);
+        }
 }
  
 void
@@ -3219,9 +3209,9 @@ setstack_dss1(struct PStack *st)
 	char tmp[64];
 	int i;
 
-	st->l3.l4l3 = dss1down;
-	st->l3.l4l3_proto = l3dss1_cmd_global;
-	st->l3.l2l3 = dss1up;
+	st->lli.l4l3 = dss1down;
+	st->lli.l4l3_proto = l3dss1_cmd_global;
+	st->l2.l2l3 = dss1up;
 	st->l3.l3ml3 = dss1man;
 	st->l3.N303 = 1;
 	st->prot.dss1.last_invoke_id = 0;
--- diff/drivers/isdn/hisax/l3ni1.c	2003-09-17 12:28:06.000000000 +0100
+++ source/drivers/isdn/hisax/l3ni1.c	2004-02-23 13:56:42.000000000 +0000
@@ -1,4 +1,4 @@
-/* $Id: l3ni1.c,v 2.5.6.3 2001/09/23 22:24:50 kai Exp $
+/* $Id: l3ni1.c,v 2.8.2.3 2004/01/13 14:31:25 keil Exp $
  *
  * NI1 D-channel protocol
  *
@@ -24,8 +24,7 @@
 #include <linux/ctype.h>
 
 extern char *HiSax_getrev(const char *revision);
-const char *ni1_revision = "$Revision: 2.5.6.3 $";
-static spinlock_t l3ni1_lock = SPIN_LOCK_UNLOCKED;
+const char *ni1_revision = "$Revision: 2.8.2.3 $";
 
 #define EXT_BEARER_CAPS 1
 
@@ -47,13 +46,10 @@ static spinlock_t l3ni1_lock = SPIN_LOCK
 static unsigned char new_invoke_id(struct PStack *p)
 {
 	unsigned char retval;
-	unsigned long flags;
 	int i;
   
 	i = 32; /* maximum search depth */
 
-	spin_lock_irqsave(&l3ni1_lock, flags);
-
 	retval = p->prot.ni1.last_invoke_id + 1; /* try new id */
 	while ((i) && (p->prot.ni1.invoke_used[retval >> 3] == 0xFF)) {
 		p->prot.ni1.last_invoke_id = (retval & 0xF8) + 8;
@@ -66,8 +62,6 @@ static unsigned char new_invoke_id(struc
 		retval = 0;
 	p->prot.ni1.last_invoke_id = retval;
 	p->prot.ni1.invoke_used[retval >> 3] |= (1 << (retval & 7));
-	spin_unlock_irqrestore(&l3ni1_lock, flags);
-
 	return(retval);  
 } /* new_invoke_id */
 
@@ -75,13 +69,11 @@ static unsigned char new_invoke_id(struc
 /* free a used invoke id */
 /*************************/
 static void free_invoke_id(struct PStack *p, unsigned char id)
-{ unsigned long flags;
+{
 
   if (!id) return; /* 0 = invalid value */
 
-  spin_lock_irqsave(&l3ni1_lock, flags);
   p->prot.ni1.invoke_used[id >> 3] &= ~(1 << (id & 7));
-  spin_unlock_irqrestore(&l3ni1_lock, flags);
 } /* free_invoke_id */  
 
 
@@ -134,7 +126,7 @@ l3ni1_search_dummy_proc(struct PStack *s
 /* and a return result is delivered. id specifies the invoke id.   */
 /*******************************************************************/ 
 static void 
-l3ni1_dummy_return_result(struct PStack *st, int id, u8 *p, u8 nlen)
+l3ni1_dummy_return_result(struct PStack *st, int id, u_char *p, u_char nlen)
 { isdn_ctrl ic;
   struct IsdnCardState *cs;
   struct l3_process *pc = NULL; 
@@ -201,7 +193,7 @@ l3ni1_dummy_error_return(struct PStack *
 /*******************************************************************/ 
 static void 
 l3ni1_dummy_invoke(struct PStack *st, int cr, int id, 
-                    int ident, u8 *p, u8 nlen)
+                    int ident, u_char *p, u_char nlen)
 { isdn_ctrl ic;
   struct IsdnCardState *cs;
 
@@ -225,7 +217,7 @@ l3ni1_dummy_invoke(struct PStack *st, in
 
 static void
 l3ni1_parse_facility(struct PStack *st, struct l3_process *pc,
-                      int cr, u8 * p)
+                      int cr, u_char * p)
 {
 	int qd_len = 0;
 	unsigned char nlen = 0, ilen, cp_tag;
@@ -375,7 +367,7 @@ l3ni1_parse_facility(struct PStack *st, 
                             pc->prot.ni1.remote_result = 0; /* success */     
                             pc->prot.ni1.invoke_id = 0;
                             pc->redir_result = pc->prot.ni1.remote_result; 
-                            L3L4(st, CC_REDIR | INDICATION, pc);                                  } /* Diversion successful */
+                            st->l3.l3l4(st, CC_REDIR | INDICATION, pc);                                  } /* Diversion successful */
                         else
                           l3_debug(st,"return error unknown identifier");
 			break;
@@ -420,7 +412,7 @@ l3ni1_parse_facility(struct PStack *st, 
                             pc->prot.ni1.remote_result = err_ret; /* result */
                             pc->prot.ni1.invoke_id = 0; 
                             pc->redir_result = pc->prot.ni1.remote_result; 
-                            L3L4(st, CC_REDIR | INDICATION, pc);  
+                            st->l3.l3l4(st, CC_REDIR | INDICATION, pc);  
                           } /* Deflection error */
                         else
                           l3_debug(st,"return result unknown identifier");
@@ -432,10 +424,10 @@ l3ni1_parse_facility(struct PStack *st, 
 }
 
 static void
-l3ni1_message(struct l3_process *pc, u8 mt)
+l3ni1_message(struct l3_process *pc, u_char mt)
 {
 	struct sk_buff *skb;
-	u8 *p;
+	u_char *p;
 
 	if (!(skb = l3_alloc_skb(4)))
 		return;
@@ -445,15 +437,15 @@ l3ni1_message(struct l3_process *pc, u8 
 }
 
 static void
-l3ni1_message_plus_chid(struct l3_process *pc, u8 mt)
+l3ni1_message_plus_chid(struct l3_process *pc, u_char mt)
 /* sends an l3 messages plus channel id -  added GE 05/09/00 */
 {
 	struct sk_buff *skb;
-	u8 tmp[16];
-	u8 *p = tmp;
-	u8 chid;
+	u_char tmp[16];
+	u_char *p = tmp;
+	u_char chid;
 
-	chid = (u8)(pc->para.bchannel & 0x03) | 0x88;
+	chid = (u_char)(pc->para.bchannel & 0x03) | 0x88;
 	MsgHead(p, pc->callref, mt);
 	*p++ = IE_CHANNEL_ID;
 	*p++ = 0x01;
@@ -466,11 +458,11 @@ l3ni1_message_plus_chid(struct l3_proces
 }
 
 static void
-l3ni1_message_cause(struct l3_process *pc, u8 mt, u8 cause)
+l3ni1_message_cause(struct l3_process *pc, u_char mt, u_char cause)
 {
 	struct sk_buff *skb;
-	u8 tmp[16];
-	u8 *p = tmp;
+	u_char tmp[16];
+	u_char *p = tmp;
 	int l;
 
 	MsgHead(p, pc->callref, mt);
@@ -487,10 +479,10 @@ l3ni1_message_cause(struct l3_process *p
 }
 
 static void
-l3ni1_status_send(struct l3_process *pc, u8 pr, void *arg)
+l3ni1_status_send(struct l3_process *pc, u_char pr, void *arg)
 {
-	u8 tmp[16];
-	u8 *p = tmp;
+	u_char tmp[16];
+	u_char *p = tmp;
 	int l;
 	struct sk_buff *skb;
 
@@ -513,14 +505,14 @@ l3ni1_status_send(struct l3_process *pc,
 }
 
 static void
-l3ni1_msg_without_setup(struct l3_process *pc, u8 pr, void *arg)
+l3ni1_msg_without_setup(struct l3_process *pc, u_char pr, void *arg)
 {
 	/* This routine is called if here was no SETUP made (checks in ni1up and in
 	 * l3ni1_setup) and a RELEASE_COMPLETE have to be sent with an error code
 	 * MT_STATUS_ENQUIRE in the NULL state is handled too
 	 */
-	u8 tmp[16];
-	u8 *p = tmp;
+	u_char tmp[16];
+	u_char *p = tmp;
 	int l;
 	struct sk_buff *skb;
 
@@ -639,7 +631,7 @@ struct ie_len max_ie_len[] = {
 };
 
 static int
-getmax_ie_len(u8 ie) {
+getmax_ie_len(u_char ie) {
 	int i = 0;
 	while (max_ie_len[i].ie != -1) {
 		if (max_ie_len[i].ie == ie)
@@ -650,7 +642,7 @@ getmax_ie_len(u8 ie) {
 }
 
 static int
-ie_in_set(struct l3_process *pc, u8 ie, int *checklist) {
+ie_in_set(struct l3_process *pc, u_char ie, int *checklist) {
 	int ret = 1;
 
 	while (*checklist != -1) {
@@ -670,13 +662,13 @@ static int
 check_infoelements(struct l3_process *pc, struct sk_buff *skb, int *checklist)
 {
 	int *cl = checklist;
-	u8 mt;
-	u8 *p, ie;
+	u_char mt;
+	u_char *p, ie;
 	int l, newpos, oldpos;
 	int err_seq = 0, err_len = 0, err_compr = 0, err_ureg = 0;
-	u8 codeset = 0;
-	u8 old_codeset = 0;
-	u8 codelock = 1;
+	u_char codeset = 0;
+	u_char old_codeset = 0;
+	u_char codelock = 1;
 	
 	p = skb->data;
 	/* skip cr */
@@ -685,7 +677,7 @@ check_infoelements(struct l3_process *pc
 	p += l;
 	mt = *p++;
 	oldpos = 0;
-	while ((u_int)(p - skb->data) < skb->len) {
+	while ((p - skb->data) < skb->len) {
 		if ((*p & 0xf0) == 0x90) { /* shift codeset */
 			old_codeset = codeset;
 			codeset = *p & 7;
@@ -819,7 +811,7 @@ l3ni1_std_ie_err(struct l3_process *pc, 
 
 static int
 l3ni1_get_channel_id(struct l3_process *pc, struct sk_buff *skb) {
-	u8 *p;
+	u_char *p;
 
 	p = skb->data;
 	if ((p = findie(p, skb->len, IE_CHANNEL_ID, 0))) {
@@ -842,8 +834,8 @@ l3ni1_get_channel_id(struct l3_process *
 
 static int
 l3ni1_get_cause(struct l3_process *pc, struct sk_buff *skb) {
-	u8 l, i=0;
-	u8 *p;
+	u_char l, i=0;
+	u_char *p;
 
 	p = skb->data;
 	pc->para.cause = 31;
@@ -880,11 +872,11 @@ l3ni1_get_cause(struct l3_process *pc, s
 }
 
 static void
-l3ni1_msg_with_uus(struct l3_process *pc, u8 cmd)
+l3ni1_msg_with_uus(struct l3_process *pc, u_char cmd)
 {
 	struct sk_buff *skb;
-	u8 tmp[16+40];
-	u8 *p = tmp;
+	u_char tmp[16+40];
+	u_char *p = tmp;
 	int l;
 
 	MsgHead(p, pc->callref, cmd);
@@ -906,7 +898,7 @@ l3ni1_msg_with_uus(struct l3_process *pc
 } /* l3ni1_msg_with_uus */
 
 static void
-l3ni1_release_req(struct l3_process *pc, u8 pr, void *arg)
+l3ni1_release_req(struct l3_process *pc, u_char pr, void *arg)
 {
 	StopAllL3Timer(pc);
 	newl3state(pc, 19);
@@ -918,7 +910,7 @@ l3ni1_release_req(struct l3_process *pc,
 }
 
 static void
-l3ni1_release_cmpl(struct l3_process *pc, u8 pr, void *arg)
+l3ni1_release_cmpl(struct l3_process *pc, u_char pr, void *arg)
 {
 	struct sk_buff *skb = arg;
 	int ret;
@@ -930,14 +922,14 @@ l3ni1_release_cmpl(struct l3_process *pc
 		pc->para.cause = NO_CAUSE;
 	StopAllL3Timer(pc);
 	newl3state(pc, 0);
-	L3L4(pc->st, CC_RELEASE | CONFIRM, pc);
+	pc->st->l3.l3l4(pc->st, CC_RELEASE | CONFIRM, pc);
 	ni1_release_l3_process(pc);
 }
 
 #if EXT_BEARER_CAPS
 
-static u8 *
-EncodeASyncParams(u8 * p, u8 si2)
+static u_char *
+EncodeASyncParams(u_char * p, u_char si2)
 {				// 7c 06 88  90 21 42 00 bb
 
 	p[0] = 0;
@@ -1001,8 +993,8 @@ EncodeASyncParams(u8 * p, u8 si2)
 	return p + 3;
 }
 
-static u8
-EncodeSyncParams(u8 si2, u8 ai)
+static u_char
+EncodeSyncParams(u_char si2, u_char ai)
 {
 
 	switch (si2) {
@@ -1046,10 +1038,10 @@ EncodeSyncParams(u8 si2, u8 ai)
 }
 
 
-static u8
-DecodeASyncParams(u8 si2, u8 * p)
+static u_char
+DecodeASyncParams(u_char si2, u_char * p)
 {
-	u8 info;
+	u_char info;
 
 	switch (p[5]) {
 		case 66:	// 1200 bit/s
@@ -1103,8 +1095,8 @@ DecodeASyncParams(u8 si2, u8 * p)
 }
 
 
-static u8
-DecodeSyncParams(u8 si2, u8 info)
+static u_char
+DecodeSyncParams(u_char si2, u_char info)
 {
 	info &= 0x7f;
 	switch (info) {
@@ -1144,10 +1136,10 @@ DecodeSyncParams(u8 si2, u8 info)
 	}
 }
 
-static u8
+static u_char
 DecodeSI2(struct sk_buff *skb)
 {
-	u8 *p;		//, *pend=skb->data + skb->len;
+	u_char *p;		//, *pend=skb->data + skb->len;
 
 	if ((p = findie(skb->data, skb->len, 0x7c, 0))) {
 		switch (p[4] & 0x0f) {
@@ -1174,16 +1166,16 @@ DecodeSI2(struct sk_buff *skb)
 
 
 static void
-l3ni1_setup_req(struct l3_process *pc, u8 pr,
+l3ni1_setup_req(struct l3_process *pc, u_char pr,
 		 void *arg)
 {
 	struct sk_buff *skb;
-	u8 tmp[128];
-	u8 *p = tmp;
+	u_char tmp[128];
+	u_char *p = tmp;
 
-	u8 *teln;
-	u8 *sub;
-	u8 *sp;
+	u_char *teln;
+	u_char *sub;
+	u_char *sp;
 	int l;
 
 	MsgHead(p, pc->callref, MT_SETUP);
@@ -1289,7 +1281,7 @@ l3ni1_setup_req(struct l3_process *pc, u
 }
 
 static void
-l3ni1_call_proc(struct l3_process *pc, u8 pr, void *arg)
+l3ni1_call_proc(struct l3_process *pc, u_char pr, void *arg)
 {
 	struct sk_buff *skb = arg;
 	int id, ret;
@@ -1324,11 +1316,11 @@ l3ni1_call_proc(struct l3_process *pc, u
 	L3AddTimer(&pc->timer, T310, CC_T310);
 	if (ret) /* STATUS for none mandatory IE errors after actions are taken */
 		l3ni1_std_ie_err(pc, ret);
-	L3L4(pc->st, CC_PROCEEDING | INDICATION, pc);
+	pc->st->l3.l3l4(pc->st, CC_PROCEEDING | INDICATION, pc);
 }
 
 static void
-l3ni1_setup_ack(struct l3_process *pc, u8 pr, void *arg)
+l3ni1_setup_ack(struct l3_process *pc, u_char pr, void *arg)
 {
 	struct sk_buff *skb = arg;
 	int id, ret;
@@ -1363,16 +1355,16 @@ l3ni1_setup_ack(struct l3_process *pc, u
 	L3AddTimer(&pc->timer, T304, CC_T304);
 	if (ret) /* STATUS for none mandatory IE errors after actions are taken */
 		l3ni1_std_ie_err(pc, ret);
-	L3L4(pc->st, CC_MORE_INFO | INDICATION, pc);
+	pc->st->l3.l3l4(pc->st, CC_MORE_INFO | INDICATION, pc);
 }
 
 static void
-l3ni1_disconnect(struct l3_process *pc, u8 pr, void *arg)
+l3ni1_disconnect(struct l3_process *pc, u_char pr, void *arg)
 {
 	struct sk_buff *skb = arg;
-	u8 *p;
+	u_char *p;
 	int ret;
-	u8 cause = 0;
+	u_char cause = 0;
 
 	StopAllL3Timer(pc);
 	if ((ret = l3ni1_get_cause(pc, skb))) {
@@ -1395,7 +1387,7 @@ l3ni1_disconnect(struct l3_process *pc, 
 	if (cause)
 		newl3state(pc, 19);
        	if (11 != ret)
-		L3L4(pc->st, CC_DISCONNECT | INDICATION, pc);
+		pc->st->l3.l3l4(pc->st, CC_DISCONNECT | INDICATION, pc);
        	else if (!cause)
 		   l3ni1_release_req(pc, pr, NULL);
 	if (cause) {
@@ -1405,7 +1397,7 @@ l3ni1_disconnect(struct l3_process *pc, 
 }
 
 static void
-l3ni1_connect(struct l3_process *pc, u8 pr, void *arg)
+l3ni1_connect(struct l3_process *pc, u_char pr, void *arg)
 {
 	struct sk_buff *skb = arg;
 	int ret;
@@ -1421,11 +1413,11 @@ l3ni1_connect(struct l3_process *pc, u8 
 	/* here should inserted COLP handling KKe */
 	if (ret)
 		l3ni1_std_ie_err(pc, ret);
-	L3L4(pc->st, CC_SETUP | CONFIRM, pc);
+	pc->st->l3.l3l4(pc->st, CC_SETUP | CONFIRM, pc);
 }
 
 static void
-l3ni1_alerting(struct l3_process *pc, u8 pr, void *arg)
+l3ni1_alerting(struct l3_process *pc, u_char pr, void *arg)
 {
 	struct sk_buff *skb = arg;
 	int ret;
@@ -1439,13 +1431,13 @@ l3ni1_alerting(struct l3_process *pc, u8
 	newl3state(pc, 4);
 	if (ret)
 		l3ni1_std_ie_err(pc, ret);
-	L3L4(pc->st, CC_ALERTING | INDICATION, pc);
+	pc->st->l3.l3l4(pc->st, CC_ALERTING | INDICATION, pc);
 }
 
 static void
-l3ni1_setup(struct l3_process *pc, u8 pr, void *arg)
+l3ni1_setup(struct l3_process *pc, u_char pr, void *arg)
 {
-	u8 *p;
+	u_char *p;
 	int bcfound = 0;
 	char tmp[80];
 	struct sk_buff *skb = arg;
@@ -1456,7 +1448,7 @@ l3ni1_setup(struct l3_process *pc, u8 pr
 	 * Bearer Capabilities
 	 */
 	p = skb->data;
-	/* only the first occurrence 'll be detected ! */
+	/* only the first occurence 'll be detected ! */
 	if ((p = findie(p, skb->len, 0x04, 0))) {
 		if ((p[1] < 2) || (p[1] > 11))
 			err = 1;
@@ -1605,23 +1597,23 @@ l3ni1_setup(struct l3_process *pc, u8 pr
 	newl3state(pc, 6);
 	if (err) /* STATUS for none mandatory IE errors after actions are taken */
 		l3ni1_std_ie_err(pc, err);
-	L3L4(pc->st, CC_SETUP | INDICATION, pc);
+	pc->st->l3.l3l4(pc->st, CC_SETUP | INDICATION, pc);
 }
 
 static void
-l3ni1_reset(struct l3_process *pc, u8 pr, void *arg)
+l3ni1_reset(struct l3_process *pc, u_char pr, void *arg)
 {
 	ni1_release_l3_process(pc);
 }
 
 static void
-l3ni1_disconnect_req(struct l3_process *pc, u8 pr, void *arg)
+l3ni1_disconnect_req(struct l3_process *pc, u_char pr, void *arg)
 {
 	struct sk_buff *skb;
-	u8 tmp[16+40];
-	u8 *p = tmp;
+	u_char tmp[16+40];
+	u_char *p = tmp;
 	int l;
-	u8 cause = 16;
+	u_char cause = 16;
 
 	if (pc->para.cause != NO_CAUSE)
 		cause = pc->para.cause;
@@ -1654,7 +1646,7 @@ l3ni1_disconnect_req(struct l3_process *
 }
 
 static void
-l3ni1_setup_rsp(struct l3_process *pc, u8 pr,
+l3ni1_setup_rsp(struct l3_process *pc, u_char pr,
 		 void *arg)
 {
         if (!pc->para.bchannel) 
@@ -1672,7 +1664,7 @@ l3ni1_setup_rsp(struct l3_process *pc, u
 }
 
 static void
-l3ni1_connect_ack(struct l3_process *pc, u8 pr, void *arg)
+l3ni1_connect_ack(struct l3_process *pc, u_char pr, void *arg)
 {
 	struct sk_buff *skb = arg;
 	int ret;
@@ -1686,17 +1678,17 @@ l3ni1_connect_ack(struct l3_process *pc,
 	L3DelTimer(&pc->timer);
 	if (ret)
 		l3ni1_std_ie_err(pc, ret);
-	L3L4(pc->st, CC_SETUP_COMPL | INDICATION, pc);
+	pc->st->l3.l3l4(pc->st, CC_SETUP_COMPL | INDICATION, pc);
 }
 
 static void
-l3ni1_reject_req(struct l3_process *pc, u8 pr, void *arg)
+l3ni1_reject_req(struct l3_process *pc, u_char pr, void *arg)
 {
 	struct sk_buff *skb;
-	u8 tmp[16];
-	u8 *p = tmp;
+	u_char tmp[16];
+	u_char *p = tmp;
 	int l;
-	u8 cause = 21;
+	u_char cause = 21;
 
 	if (pc->para.cause != NO_CAUSE)
 		cause = pc->para.cause;
@@ -1713,16 +1705,16 @@ l3ni1_reject_req(struct l3_process *pc, 
 		return;
 	memcpy(skb_put(skb, l), tmp, l);
 	l3_msg(pc->st, DL_DATA | REQUEST, skb);
-	L3L4(pc->st, CC_RELEASE | INDICATION, pc);
+	pc->st->l3.l3l4(pc->st, CC_RELEASE | INDICATION, pc);
 	newl3state(pc, 0);
 	ni1_release_l3_process(pc);
 }
 
 static void
-l3ni1_release(struct l3_process *pc, u8 pr, void *arg)
+l3ni1_release(struct l3_process *pc, u_char pr, void *arg)
 {
 	struct sk_buff *skb = arg;
-	u8 *p;
+	u_char *p;
 	int ret, cause=0;
 
 	StopAllL3Timer(pc);
@@ -1747,13 +1739,13 @@ l3ni1_release(struct l3_process *pc, u8 
 		l3ni1_message_cause(pc, MT_RELEASE_COMPLETE, cause);
 	else
 		l3ni1_message(pc, MT_RELEASE_COMPLETE);
-	L3L4(pc->st, CC_RELEASE | INDICATION, pc);
+	pc->st->l3.l3l4(pc->st, CC_RELEASE | INDICATION, pc);
 	newl3state(pc, 0);
 	ni1_release_l3_process(pc);
 }
 
 static void
-l3ni1_alert_req(struct l3_process *pc, u8 pr,
+l3ni1_alert_req(struct l3_process *pc, u_char pr,
 		 void *arg)
 {
 	newl3state(pc, 7);
@@ -1764,16 +1756,16 @@ l3ni1_alert_req(struct l3_process *pc, u
 }
 
 static void
-l3ni1_proceed_req(struct l3_process *pc, u8 pr,
+l3ni1_proceed_req(struct l3_process *pc, u_char pr,
 		   void *arg)
 {
 	newl3state(pc, 9);
 	l3ni1_message(pc, MT_CALL_PROCEEDING);
-	L3L4(pc->st, CC_PROCEED_SEND | INDICATION, pc); 
+	pc->st->l3.l3l4(pc->st, CC_PROCEED_SEND | INDICATION, pc); 
 }
 
 static void
-l3ni1_setup_ack_req(struct l3_process *pc, u8 pr,
+l3ni1_setup_ack_req(struct l3_process *pc, u_char pr,
 		   void *arg)
 {
 	newl3state(pc, 25);
@@ -1786,8 +1778,8 @@ l3ni1_setup_ack_req(struct l3_process *p
 /* deliver a incoming display message to HL */
 /********************************************/
 static void
-l3ni1_deliver_display(struct l3_process *pc, int pr, u8 *infp)
-{       u8 len;
+l3ni1_deliver_display(struct l3_process *pc, int pr, u_char *infp)
+{       u_char len;
         isdn_ctrl ic; 
 	struct IsdnCardState *cs;
         char *p; 
@@ -1809,11 +1801,11 @@ l3ni1_deliver_display(struct l3_process 
 
 
 static void
-l3ni1_progress(struct l3_process *pc, u8 pr, void *arg)
+l3ni1_progress(struct l3_process *pc, u_char pr, void *arg)
 {
 	struct sk_buff *skb = arg;
 	int err = 0;
-	u8 *p;
+	u_char *p;
 
 	if ((p = findie(skb->data, skb->len, IE_PROGRESS, 0))) {
 		if (p[1] != 2) {
@@ -1862,15 +1854,15 @@ l3ni1_progress(struct l3_process *pc, u8
 	if (err)
 		l3ni1_std_ie_err(pc, err);
 	if (ERR_IE_COMPREHENSION != err)
-		L3L4(pc->st, CC_PROGRESS | INDICATION, pc);
+		pc->st->l3.l3l4(pc->st, CC_PROGRESS | INDICATION, pc);
 }
 
 static void
-l3ni1_notify(struct l3_process *pc, u8 pr, void *arg)
+l3ni1_notify(struct l3_process *pc, u_char pr, void *arg)
 {
 	struct sk_buff *skb = arg;
 	int err = 0;
-	u8 *p;
+	u_char *p;
 
 	if ((p = findie(skb->data, skb->len, IE_NOTIFY, 0))) {
 		if (p[1] != 1) {
@@ -1903,11 +1895,11 @@ l3ni1_notify(struct l3_process *pc, u8 p
 	if (err)
 		l3ni1_std_ie_err(pc, err);
 	if (ERR_IE_COMPREHENSION != err)
-		L3L4(pc->st, CC_NOTIFY | INDICATION, pc);
+		pc->st->l3.l3l4(pc->st, CC_NOTIFY | INDICATION, pc);
 }
 
 static void
-l3ni1_status_enq(struct l3_process *pc, u8 pr, void *arg)
+l3ni1_status_enq(struct l3_process *pc, u_char pr, void *arg)
 {
 	int ret;
 	struct sk_buff *skb = arg;
@@ -1919,11 +1911,11 @@ l3ni1_status_enq(struct l3_process *pc, 
 }
 
 static void
-l3ni1_information(struct l3_process *pc, u8 pr, void *arg)
+l3ni1_information(struct l3_process *pc, u_char pr, void *arg)
 {
 	int ret;
 	struct sk_buff *skb = arg;
-	u8 *p;
+	u_char *p;
 	char tmp[32];
 
 	ret = check_infoelements(pc, skb, ie_INFORMATION);
@@ -1935,7 +1927,7 @@ l3ni1_information(struct l3_process *pc,
 		if ((p = findie(p, skb->len, 0x70, 0))) {
 			iecpy(tmp, p, 1);
 			strcat(pc->para.setup.eazmsn, tmp);
-			L3L4(pc->st, CC_MORE_INFO | INDICATION, pc);
+			pc->st->l3.l3l4(pc->st, CC_MORE_INFO | INDICATION, pc);
 		}
 		L3AddTimer(&pc->timer, T302, CC_T302);
 	}
@@ -1944,14 +1936,14 @@ l3ni1_information(struct l3_process *pc,
 /******************************/
 /* handle deflection requests */
 /******************************/
-static void l3ni1_redir_req(struct l3_process *pc, u8 pr, void *arg)
+static void l3ni1_redir_req(struct l3_process *pc, u_char pr, void *arg)
 {
 	struct sk_buff *skb;
-	u8 tmp[128];
-	u8 *p = tmp;
-        u8 *subp;
-        u8 len_phone = 0;
-        u8 len_sub = 0;
+	u_char tmp[128];
+	u_char *p = tmp;
+        u_char *subp;
+        u_char len_phone = 0;
+        u_char len_sub = 0;
 	int l; 
 
 
@@ -2016,7 +2008,7 @@ static void l3ni1_redir_req(struct l3_pr
 /********************************************/
 /* handle deflection request in early state */
 /********************************************/
-static void l3ni1_redir_req_early(struct l3_process *pc, u8 pr, void *arg)
+static void l3ni1_redir_req_early(struct l3_process *pc, u_char pr, void *arg)
 {
   l3ni1_proceed_req(pc,pr,arg);
   l3ni1_redir_req(pc,pr,arg);
@@ -2024,13 +2016,13 @@ static void l3ni1_redir_req_early(struct
 
 /***********************************************/
 /* handle special commands for this protocol.  */
-/* Examples are call independent services like */
+/* Examples are call independant services like */
 /* remote operations with dummy  callref.      */
 /***********************************************/
 static int l3ni1_cmd_global(struct PStack *st, isdn_ctrl *ic)
-{ u8 id;
-  u8 temp[265];
-  u8 *p = temp;
+{ u_char id;
+  u_char temp[265];
+  u_char *p = temp;
   int i, l, proc_len; 
   struct sk_buff *skb;
   struct l3_process *pc = NULL;
@@ -2134,9 +2126,9 @@ l3ni1_io_timer(struct l3_process *pc)
 } /* l3ni1_io_timer */
 
 static void
-l3ni1_release_ind(struct l3_process *pc, u8 pr, void *arg)
+l3ni1_release_ind(struct l3_process *pc, u_char pr, void *arg)
 {
-	u8 *p;
+	u_char *p;
 	struct sk_buff *skb = arg;
 	int callState = 0;
 	p = skb->data;
@@ -2150,31 +2142,31 @@ l3ni1_release_ind(struct l3_process *pc,
 		/* ETS 300-104 7.6.1, 8.6.1, 10.6.1... and 16.1
 		 * set down layer 3 without sending any message
 		 */
-		L3L4(pc->st, CC_RELEASE | INDICATION, pc);
+		pc->st->l3.l3l4(pc->st, CC_RELEASE | INDICATION, pc);
 		newl3state(pc, 0);
 		ni1_release_l3_process(pc);
 	} else {
-		L3L4(pc->st, CC_IGNORE | INDICATION, pc);
+		pc->st->l3.l3l4(pc->st, CC_IGNORE | INDICATION, pc);
 	}
 }
 
 static void
-l3ni1_dummy(struct l3_process *pc, u8 pr, void *arg)
+l3ni1_dummy(struct l3_process *pc, u_char pr, void *arg)
 {
 }
 
 static void
-l3ni1_t302(struct l3_process *pc, u8 pr, void *arg)
+l3ni1_t302(struct l3_process *pc, u_char pr, void *arg)
 {
 	L3DelTimer(&pc->timer);
 	pc->para.loc = 0;
 	pc->para.cause = 28; /* invalid number */
 	l3ni1_disconnect_req(pc, pr, NULL);
-	L3L4(pc->st, CC_SETUP_ERR, pc);
+	pc->st->l3.l3l4(pc->st, CC_SETUP_ERR, pc);
 }
 
 static void
-l3ni1_t303(struct l3_process *pc, u8 pr, void *arg)
+l3ni1_t303(struct l3_process *pc, u_char pr, void *arg)
 {
 	if (pc->N303 > 0) {
 		pc->N303--;
@@ -2183,30 +2175,30 @@ l3ni1_t303(struct l3_process *pc, u8 pr,
 	} else {
 		L3DelTimer(&pc->timer);
 		l3ni1_message_cause(pc, MT_RELEASE_COMPLETE, 102);
-		L3L4(pc->st, CC_NOSETUP_RSP, pc);
+		pc->st->l3.l3l4(pc->st, CC_NOSETUP_RSP, pc);
 		ni1_release_l3_process(pc);
 	}
 }
 
 static void
-l3ni1_t304(struct l3_process *pc, u8 pr, void *arg)
+l3ni1_t304(struct l3_process *pc, u_char pr, void *arg)
 {
 	L3DelTimer(&pc->timer);
 	pc->para.loc = 0;
 	pc->para.cause = 102;
 	l3ni1_disconnect_req(pc, pr, NULL);
-	L3L4(pc->st, CC_SETUP_ERR, pc);
+	pc->st->l3.l3l4(pc->st, CC_SETUP_ERR, pc);
 
 }
 
 static void
-l3ni1_t305(struct l3_process *pc, u8 pr, void *arg)
+l3ni1_t305(struct l3_process *pc, u_char pr, void *arg)
 {
-	u8 tmp[16];
-	u8 *p = tmp;
+	u_char tmp[16];
+	u_char *p = tmp;
 	int l;
 	struct sk_buff *skb;
-	u8 cause = 16;
+	u_char cause = 16;
 
 	L3DelTimer(&pc->timer);
 	if (pc->para.cause != NO_CAUSE)
@@ -2229,27 +2221,27 @@ l3ni1_t305(struct l3_process *pc, u8 pr,
 }
 
 static void
-l3ni1_t310(struct l3_process *pc, u8 pr, void *arg)
+l3ni1_t310(struct l3_process *pc, u_char pr, void *arg)
 {
 	L3DelTimer(&pc->timer);
 	pc->para.loc = 0;
 	pc->para.cause = 102;
 	l3ni1_disconnect_req(pc, pr, NULL);
-	L3L4(pc->st, CC_SETUP_ERR, pc);
+	pc->st->l3.l3l4(pc->st, CC_SETUP_ERR, pc);
 }
 
 static void
-l3ni1_t313(struct l3_process *pc, u8 pr, void *arg)
+l3ni1_t313(struct l3_process *pc, u_char pr, void *arg)
 {
 	L3DelTimer(&pc->timer);
 	pc->para.loc = 0;
 	pc->para.cause = 102;
 	l3ni1_disconnect_req(pc, pr, NULL);
-	L3L4(pc->st, CC_CONNECT_ERR, pc);
+	pc->st->l3.l3l4(pc->st, CC_CONNECT_ERR, pc);
 }
 
 static void
-l3ni1_t308_1(struct l3_process *pc, u8 pr, void *arg)
+l3ni1_t308_1(struct l3_process *pc, u_char pr, void *arg)
 {
 	newl3state(pc, 19);
 	L3DelTimer(&pc->timer);
@@ -2258,50 +2250,50 @@ l3ni1_t308_1(struct l3_process *pc, u8 p
 }
 
 static void
-l3ni1_t308_2(struct l3_process *pc, u8 pr, void *arg)
+l3ni1_t308_2(struct l3_process *pc, u_char pr, void *arg)
 {
 	L3DelTimer(&pc->timer);
-	L3L4(pc->st, CC_RELEASE_ERR, pc);
+	pc->st->l3.l3l4(pc->st, CC_RELEASE_ERR, pc);
 	ni1_release_l3_process(pc);
 }
 
 static void
-l3ni1_t318(struct l3_process *pc, u8 pr, void *arg)
+l3ni1_t318(struct l3_process *pc, u_char pr, void *arg)
 {
 	L3DelTimer(&pc->timer);
 	pc->para.cause = 102;	/* Timer expiry */
 	pc->para.loc = 0;	/* local */
-	L3L4(pc->st, CC_RESUME_ERR, pc);
+	pc->st->l3.l3l4(pc->st, CC_RESUME_ERR, pc);
 	newl3state(pc, 19);
 	l3ni1_message(pc, MT_RELEASE);
 	L3AddTimer(&pc->timer, T308, CC_T308_1);
 }
 
 static void
-l3ni1_t319(struct l3_process *pc, u8 pr, void *arg)
+l3ni1_t319(struct l3_process *pc, u_char pr, void *arg)
 {
 	L3DelTimer(&pc->timer);
 	pc->para.cause = 102;	/* Timer expiry */
 	pc->para.loc = 0;	/* local */
-	L3L4(pc->st, CC_SUSPEND_ERR, pc);
+	pc->st->l3.l3l4(pc->st, CC_SUSPEND_ERR, pc);
 	newl3state(pc, 10);
 }
 
 static void
-l3ni1_restart(struct l3_process *pc, u8 pr, void *arg)
+l3ni1_restart(struct l3_process *pc, u_char pr, void *arg)
 {
 	L3DelTimer(&pc->timer);
-	L3L4(pc->st, CC_RELEASE | INDICATION, pc);
+	pc->st->l3.l3l4(pc->st, CC_RELEASE | INDICATION, pc);
 	ni1_release_l3_process(pc);
 }
 
 static void
-l3ni1_status(struct l3_process *pc, u8 pr, void *arg)
+l3ni1_status(struct l3_process *pc, u_char pr, void *arg)
 {
-	u8 *p;
+	u_char *p;
 	struct sk_buff *skb = arg;
 	int ret; 
-	u8 cause = 0, callState = 0;
+	u_char cause = 0, callState = 0;
 	
 	if ((ret = l3ni1_get_cause(pc, skb))) {
 		if (pc->debug & L3_DEB_WARN)
@@ -2329,7 +2321,7 @@ l3ni1_status(struct l3_process *pc, u8 p
 			cause = 99;
 	}
 	if (cause) {
-		u8 tmp;
+		u_char tmp;
 		
 		if (pc->debug & L3_DEB_WARN)
 			l3_debug(pc->st, "STATUS error(%d/%d)",ret,cause);
@@ -2347,14 +2339,14 @@ l3ni1_status(struct l3_process *pc, u8 p
 		 * if received MT_STATUS with cause == 111 and call
 		 * state == 0, then we must set down layer 3
 		 */
-		L3L4(pc->st, CC_RELEASE | INDICATION, pc);
+		pc->st->l3.l3l4(pc->st, CC_RELEASE | INDICATION, pc);
 		newl3state(pc, 0);
 		ni1_release_l3_process(pc);
 	}
 }
 
 static void
-l3ni1_facility(struct l3_process *pc, u8 pr, void *arg)
+l3ni1_facility(struct l3_process *pc, u_char pr, void *arg)
 {
 	struct sk_buff *skb = arg;
 	int ret;
@@ -2362,20 +2354,20 @@ l3ni1_facility(struct l3_process *pc, u8
 	ret = check_infoelements(pc, skb, ie_FACILITY);
 	l3ni1_std_ie_err(pc, ret);
  	  {
-		u8 *p;
+		u_char *p;
 		if ((p = findie(skb->data, skb->len, IE_FACILITY, 0)))
 			l3ni1_parse_facility(pc->st, pc, pc->callref, p);
 	}
 }
 
 static void
-l3ni1_suspend_req(struct l3_process *pc, u8 pr, void *arg)
+l3ni1_suspend_req(struct l3_process *pc, u_char pr, void *arg)
 {
 	struct sk_buff *skb;
-	u8 tmp[32];
-	u8 *p = tmp;
-	u8 i, l;
-	u8 *msg = pc->chan->setup.phone;
+	u_char tmp[32];
+	u_char *p = tmp;
+	u_char i, l;
+	u_char *msg = pc->chan->setup.phone;
 
 	MsgHead(p, pc->callref, MT_SUSPEND);
 	l = *msg++;
@@ -2398,7 +2390,7 @@ l3ni1_suspend_req(struct l3_process *pc,
 }
 
 static void
-l3ni1_suspend_ack(struct l3_process *pc, u8 pr, void *arg)
+l3ni1_suspend_ack(struct l3_process *pc, u_char pr, void *arg)
 {
 	struct sk_buff *skb = arg;
 	int ret;
@@ -2406,7 +2398,7 @@ l3ni1_suspend_ack(struct l3_process *pc,
 	L3DelTimer(&pc->timer);
 	newl3state(pc, 0);
 	pc->para.cause = NO_CAUSE;
-	L3L4(pc->st, CC_SUSPEND | CONFIRM, pc);
+	pc->st->l3.l3l4(pc->st, CC_SUSPEND | CONFIRM, pc);
 	/* We don't handle suspend_ack for IE errors now */
 	if ((ret = check_infoelements(pc, skb, ie_SUSPEND_ACKNOWLEDGE)))
 		if (pc->debug & L3_DEB_WARN)
@@ -2415,7 +2407,7 @@ l3ni1_suspend_ack(struct l3_process *pc,
 }
 
 static void
-l3ni1_suspend_rej(struct l3_process *pc, u8 pr, void *arg)
+l3ni1_suspend_rej(struct l3_process *pc, u_char pr, void *arg)
 {
 	struct sk_buff *skb = arg;
 	int ret;
@@ -2436,20 +2428,20 @@ l3ni1_suspend_rej(struct l3_process *pc,
 		return;
 	}
 	L3DelTimer(&pc->timer);
-	L3L4(pc->st, CC_SUSPEND_ERR, pc);
+	pc->st->l3.l3l4(pc->st, CC_SUSPEND_ERR, pc);
 	newl3state(pc, 10);
 	if (ret) /* STATUS for none mandatory IE errors after actions are taken */
 		l3ni1_std_ie_err(pc, ret);
 }
 
 static void
-l3ni1_resume_req(struct l3_process *pc, u8 pr, void *arg)
+l3ni1_resume_req(struct l3_process *pc, u_char pr, void *arg)
 {
 	struct sk_buff *skb;
-	u8 tmp[32];
-	u8 *p = tmp;
-	u8 i, l;
-	u8 *msg = pc->para.setup.phone;
+	u_char tmp[32];
+	u_char *p = tmp;
+	u_char i, l;
+	u_char *msg = pc->para.setup.phone;
 
 	MsgHead(p, pc->callref, MT_RESUME);
 
@@ -2473,7 +2465,7 @@ l3ni1_resume_req(struct l3_process *pc, 
 }
 
 static void
-l3ni1_resume_ack(struct l3_process *pc, u8 pr, void *arg)
+l3ni1_resume_ack(struct l3_process *pc, u_char pr, void *arg)
 {
 	struct sk_buff *skb = arg;
 	int id, ret;
@@ -2500,14 +2492,14 @@ l3ni1_resume_ack(struct l3_process *pc, 
 		return;
 	}
 	L3DelTimer(&pc->timer);
-	L3L4(pc->st, CC_RESUME | CONFIRM, pc);
+	pc->st->l3.l3l4(pc->st, CC_RESUME | CONFIRM, pc);
 	newl3state(pc, 10);
 	if (ret) /* STATUS for none mandatory IE errors after actions are taken */
 		l3ni1_std_ie_err(pc, ret);
 }
 
 static void
-l3ni1_resume_rej(struct l3_process *pc, u8 pr, void *arg)
+l3ni1_resume_rej(struct l3_process *pc, u_char pr, void *arg)
 {
 	struct sk_buff *skb = arg;
 	int ret;
@@ -2528,7 +2520,7 @@ l3ni1_resume_rej(struct l3_process *pc, 
 		return;
 	}
 	L3DelTimer(&pc->timer);
-	L3L4(pc->st, CC_RESUME_ERR, pc);
+	pc->st->l3.l3l4(pc->st, CC_RESUME_ERR, pc);
 	newl3state(pc, 0);
 	if (ret) /* STATUS for none mandatory IE errors after actions are taken */
 		l3ni1_std_ie_err(pc, ret);
@@ -2536,11 +2528,11 @@ l3ni1_resume_rej(struct l3_process *pc, 
 }
 
 static void
-l3ni1_global_restart(struct l3_process *pc, u8 pr, void *arg)
+l3ni1_global_restart(struct l3_process *pc, u_char pr, void *arg)
 {
-	u8 tmp[32];
-	u8 *p;
-	u8 ri, ch = 0, chan = 0;
+	u_char tmp[32];
+	u_char *p;
+	u_char ri, ch = 0, chan = 0;
 	int l;
 	struct sk_buff *skb = arg;
 	struct l3_process *up;
@@ -2566,9 +2558,9 @@ l3ni1_global_restart(struct l3_process *
 	up = pc->st->l3.proc;
 	while (up) {
 		if ((ri & 7) == 7)
-			L4L3(up->st, CC_RESTART | REQUEST, up);
+			up->st->lli.l4l3(up->st, CC_RESTART | REQUEST, up);
 		else if (up->para.bchannel == chan)
-			L4L3(up->st, CC_RESTART | REQUEST, up);
+			up->st->lli.l4l3(up->st, CC_RESTART | REQUEST, up);
 		
 		up = up->next;
 	}
@@ -2591,26 +2583,26 @@ l3ni1_global_restart(struct l3_process *
 }
 
 static void
-l3ni1_dl_reset(struct l3_process *pc, u8 pr, void *arg)
+l3ni1_dl_reset(struct l3_process *pc, u_char pr, void *arg)
 {
         pc->para.cause = 0x29;          /* Temporary failure */
         pc->para.loc = 0;
         l3ni1_disconnect_req(pc, pr, NULL);
-        L3L4(pc->st, CC_SETUP_ERR, pc);
+        pc->st->l3.l3l4(pc->st, CC_SETUP_ERR, pc);
 }
 
 static void
-l3ni1_dl_release(struct l3_process *pc, u8 pr, void *arg)
+l3ni1_dl_release(struct l3_process *pc, u_char pr, void *arg)
 {
         newl3state(pc, 0);
         pc->para.cause = 0x1b;          /* Destination out of order */
         pc->para.loc = 0;
-        L3L4(pc->st, CC_RELEASE | INDICATION, pc);
+        pc->st->l3.l3l4(pc->st, CC_RELEASE | INDICATION, pc);
         release_l3_process(pc);
 }
 
 static void
-l3ni1_dl_reestablish(struct l3_process *pc, u8 pr, void *arg)
+l3ni1_dl_reestablish(struct l3_process *pc, u_char pr, void *arg)
 {
         L3DelTimer(&pc->timer);
         L3AddTimer(&pc->timer, T309, CC_T309);
@@ -2618,7 +2610,7 @@ l3ni1_dl_reestablish(struct l3_process *
 }
  
 static void
-l3ni1_dl_reest_status(struct l3_process *pc, u8 pr, void *arg)
+l3ni1_dl_reest_status(struct l3_process *pc, u_char pr, void *arg)
 {
 	L3DelTimer(&pc->timer);
  
@@ -2626,9 +2618,9 @@ l3ni1_dl_reest_status(struct l3_process 
 	l3ni1_status_send(pc, 0, NULL);
 }
 
-static void l3ni1_SendSpid( struct l3_process *pc, u8 pr, struct sk_buff *skb, int iNewState )
+static void l3ni1_SendSpid( struct l3_process *pc, u_char pr, struct sk_buff *skb, int iNewState )
 {
-	u8         * p;
+	u_char         * p;
 	char           * pSPID;
 	struct Channel * pChan = pc->st->lli.userdata;
 	int              l;
@@ -2640,7 +2632,7 @@ static void l3ni1_SendSpid( struct l3_pr
 	{
 		printk( KERN_ERR "SPID not supplied in EAZMSN %s\n", pChan->setup.eazmsn );
 		newl3state( pc, 0 );
-		L3L2( pc->st, DL_RELEASE | REQUEST, NULL );
+		pc->st->l3.l3l2( pc->st, DL_RELEASE | REQUEST, NULL );
 		return;
 	}
 
@@ -2665,15 +2657,15 @@ static void l3ni1_SendSpid( struct l3_pr
 	L3DelTimer( &pc->timer );
 	L3AddTimer( &pc->timer, TSPID, CC_TSPID );
 
-	L3L2( pc->st, DL_DATA | REQUEST, skb );
+	pc->st->l3.l3l2( pc->st, DL_DATA | REQUEST, skb );
 }
 
-static void l3ni1_spid_send( struct l3_process *pc, u8 pr, void *arg )
+static void l3ni1_spid_send( struct l3_process *pc, u_char pr, void *arg )
 {
 	l3ni1_SendSpid( pc, pr, arg, 20 );
 }
 
-void l3ni1_spid_epid( struct l3_process *pc, u8 pr, void *arg )
+void l3ni1_spid_epid( struct l3_process *pc, u_char pr, void *arg )
 {
 	struct sk_buff *skb = arg;
 
@@ -2687,7 +2679,7 @@ void l3ni1_spid_epid( struct l3_process 
 	dev_kfree_skb( skb);
 }
 
-static void l3ni1_spid_tout( struct l3_process *pc, u8 pr, void *arg )
+static void l3ni1_spid_tout( struct l3_process *pc, u_char pr, void *arg )
 {
 	if ( pc->state < 22 )
 		l3ni1_SendSpid( pc, pr, arg, pc->state+1 );
@@ -2698,7 +2690,7 @@ static void l3ni1_spid_tout( struct l3_p
 
 		printk( KERN_ERR "SPID not accepted\n" );
 		newl3state( pc, 0 );
-		L3L2( pc->st, DL_RELEASE | REQUEST, NULL );
+		pc->st->l3.l3l2( pc->st, DL_RELEASE | REQUEST, NULL );
 	}
 }
 
@@ -2856,10 +2848,10 @@ static struct stateentry manstatelist[] 
 static void
 global_handler(struct PStack *st, int mt, struct sk_buff *skb)
 {
-	u8 tmp[16];
-	u8 *p = tmp;
+	u_char tmp[16];
+	u_char *p = tmp;
 	int l;
-	u_int i;
+	int i;
 	struct l3_process *proc = st->l3.global;
 
 	if ( skb )	
@@ -2900,10 +2892,9 @@ global_handler(struct PStack *st, int mt
 static void
 ni1up(struct PStack *st, int pr, void *arg)
 {
-	u_int i; 
-	int mt, cr, cause, callState;
+	int i, mt, cr, cause, callState;
 	char *ptr;
-	u8 *p;
+	u_char *p;
 	struct sk_buff *skb = arg;
 	struct l3_process *proc;
 
@@ -2942,7 +2933,7 @@ ni1up(struct PStack *st, int pr, void *a
 		return;
 	}
 	cr = getcallref(skb->data);
-	if (skb->len < (u_int)((skb->data[1] & 0x0f) + 3)) {
+	if (skb->len < ((skb->data[1] & 0x0f) + 3)) {
 		l3_debug(st, "ni1up frame too short(%d)", skb->len);
 		dev_kfree_skb(skb);
 		return;
@@ -3087,8 +3078,7 @@ ni1up(struct PStack *st, int pr, void *a
 static void
 ni1down(struct PStack *st, int pr, void *arg)
 {
-	u_int i;
-	int cr;
+	int i, cr;
 	struct l3_process *proc;
 	struct Channel *chan;
 
@@ -3139,7 +3129,7 @@ ni1down(struct PStack *st, int pr, void 
 static void
 ni1man(struct PStack *st, int pr, void *arg)
 {
-        u_int i;
+        int i;
         struct l3_process *proc = arg;
 
         if (!proc) {
@@ -3170,9 +3160,9 @@ setstack_ni1(struct PStack *st)
 	char tmp[64];
 	int i;
 
-	st->l3.l4l3 = ni1down;
-	st->l3.l4l3_proto = l3ni1_cmd_global;
-	st->l3.l2l3 = ni1up;
+	st->lli.l4l3 = ni1down;
+	st->lli.l4l3_proto = l3ni1_cmd_global;
+	st->l2.l2l3 = ni1up;
 	st->l3.l3ml3 = ni1man;
 	st->l3.N303 = 1;
 	st->prot.ni1.last_invoke_id = 0;
--- diff/drivers/isdn/hisax/mic.c	2003-05-21 11:49:50.000000000 +0100
+++ source/drivers/isdn/hisax/mic.c	2004-02-23 13:56:42.000000000 +0000
@@ -1,4 +1,4 @@
-/* $Id: mic.c,v 1.10.6.2 2001/09/23 22:24:50 kai Exp $
+/* $Id: mic.c,v 1.12.2.4 2004/01/13 23:48:39 keil Exp $
  *
  * low level stuff for mic cards
  *
@@ -18,8 +18,7 @@
 
 extern const char *CardType[];
 
-const char *mic_revision = "$Revision: 1.10.6.2 $";
-static spinlock_t mic_lock = SPIN_LOCK_UNLOCKED;
+const char *mic_revision = "$Revision: 1.12.2.4 $";
 
 #define byteout(addr,val) outb(val,addr)
 #define bytein(addr) inb(addr)
@@ -31,146 +30,210 @@ static spinlock_t mic_lock = SPIN_LOCK_U
 /* CARD_ADR (Write) */
 #define MIC_RESET      0x3	/* same as DOS driver */
 
-static inline u8
-readreg(struct IsdnCardState *cs, unsigned int adr, u8 off)
+static inline u_char
+readreg(unsigned int ale, unsigned int adr, u_char off)
 {
-	u8 ret;
-	unsigned long flags;
+	register u_char ret;
 
-	spin_lock_irqsave(&mic_lock, flags);
-	byteout(cs->hw.mic.adr, off);
+	byteout(ale, off);
 	ret = bytein(adr);
-	spin_unlock_irqrestore(&mic_lock, flags);
-
 	return (ret);
 }
 
 static inline void
-writereg(struct IsdnCardState *cs, unsigned int adr, u8 off, u8 data)
+readfifo(unsigned int ale, unsigned int adr, u_char off, u_char * data, int size)
 {
-	unsigned long flags;
-
-	spin_lock_irqsave(&mic_lock, flags);
-	byteout(cs->hw.mic.adr, off);
-	byteout(adr, data);
-	spin_unlock_irqrestore(&mic_lock, flags);
+	byteout(ale, off);
+	insb(adr, data, size);
 }
 
+
 static inline void
-readfifo(struct IsdnCardState *cs, unsigned int adr, u8 off, u8 * data, int size)
+writereg(unsigned int ale, unsigned int adr, u_char off, u_char data)
 {
-	byteout(cs->hw.mic.adr, off);
-	insb(adr, data, size);
+	byteout(ale, off);
+	byteout(adr, data);
 }
 
 static inline void
-writefifo(struct IsdnCardState *cs, unsigned int adr, u8 off, u8 * data, int size)
+writefifo(unsigned int ale, unsigned int adr, u_char off, u_char * data, int size)
 {
-	byteout(cs->hw.mic.adr, off);
+	byteout(ale, off);
 	outsb(adr, data, size);
 }
 
-static u8
-isac_read(struct IsdnCardState *cs, u8 offset)
-{
-	return readreg(cs, cs->hw.mic.isac, offset);
-}
+/* Interface functions */
 
-static void
-isac_write(struct IsdnCardState *cs, u8 offset, u8 value)
+static u_char
+ReadISAC(struct IsdnCardState *cs, u_char offset)
 {
-	writereg(cs, cs->hw.mic.isac, offset, value);
+	return (readreg(cs->hw.mic.adr, cs->hw.mic.isac, offset));
 }
 
 static void
-isac_read_fifo(struct IsdnCardState *cs, u8 * data, int size)
+WriteISAC(struct IsdnCardState *cs, u_char offset, u_char value)
 {
-	readfifo(cs, cs->hw.mic.isac, 0, data, size);
+	writereg(cs->hw.mic.adr, cs->hw.mic.isac, offset, value);
 }
 
 static void
-isac_write_fifo(struct IsdnCardState *cs, u8 * data, int size)
-{
-	writefifo(cs, cs->hw.mic.isac, 0, data, size);
-}
-
-static struct dc_hw_ops isac_ops = {
-	.read_reg   = isac_read,
-	.write_reg  = isac_write,
-	.read_fifo  = isac_read_fifo,
-	.write_fifo = isac_write_fifo,
-};
-
-static u8
-hscx_read(struct IsdnCardState *cs, int hscx, u8 offset)
+ReadISACfifo(struct IsdnCardState *cs, u_char * data, int size)
 {
-	return readreg(cs, cs->hw.mic.hscx, offset + (hscx ? 0x40 : 0));
+	readfifo(cs->hw.mic.adr, cs->hw.mic.isac, 0, data, size);
 }
 
 static void
-hscx_write(struct IsdnCardState *cs, int hscx, u8 offset, u8 value)
+WriteISACfifo(struct IsdnCardState *cs, u_char * data, int size)
 {
-	writereg(cs, cs->hw.mic.hscx, offset + (hscx ? 0x40 : 0), value);
+	writefifo(cs->hw.mic.adr, cs->hw.mic.isac, 0, data, size);
 }
 
-static void
-hscx_read_fifo(struct IsdnCardState *cs, int hscx, u8 *data, int size)
+static u_char
+ReadHSCX(struct IsdnCardState *cs, int hscx, u_char offset)
 {
-	readfifo(cs, cs->hw.mic.hscx, hscx ? 0x40 : 0, data, size);
+	return (readreg(cs->hw.mic.adr,
+			cs->hw.mic.hscx, offset + (hscx ? 0x40 : 0)));
 }
 
 static void
-hscx_write_fifo(struct IsdnCardState *cs, int hscx, u8 *data, int size)
+WriteHSCX(struct IsdnCardState *cs, int hscx, u_char offset, u_char value)
 {
-	writefifo(cs, cs->hw.mic.hscx, hscx ? 0x40 : 0, data, size);
+	writereg(cs->hw.mic.adr,
+		 cs->hw.mic.hscx, offset + (hscx ? 0x40 : 0), value);
 }
 
-static struct bc_hw_ops hscx_ops = {
-	.read_reg   = hscx_read,
-	.write_reg  = hscx_write,
-	.read_fifo  = hscx_read_fifo,
-	.write_fifo = hscx_write_fifo,
-};
-
-static struct card_ops mic_ops = {
-	.init     = inithscxisac,
-	.release  = hisax_release_resources,
-	.irq_func = hscxisac_irq,
-};
-
-static int __init
-mic_probe(struct IsdnCardState *cs, struct IsdnCard *card)
-{
-	cs->irq = card->para[0];
-	cs->hw.mic.cfg_reg = card->para[1];
-	cs->hw.mic.adr = cs->hw.mic.cfg_reg + MIC_ADR;
-	cs->hw.mic.isac = cs->hw.mic.cfg_reg + MIC_ISAC;
-	cs->hw.mic.hscx = cs->hw.mic.cfg_reg + MIC_HSCX;
-
-	if (!request_io(&cs->rs, cs->hw.mic.cfg_reg, 8, "mic isdn"))
-		goto err;
-  
-	printk(KERN_INFO "mic: defined at 0x%x IRQ %d\n",
-	       cs->hw.mic.cfg_reg, cs->irq);
+/*
+ * fast interrupt HSCX stuff goes here
+ */
 
-	cs->card_ops = &mic_ops;
-	if (hscxisac_setup(cs, &isac_ops, &hscx_ops))
-		goto err;
-	return 0;
- err:
-	hisax_release_resources(cs);
-	return -EBUSY;
+#define READHSCX(cs, nr, reg) readreg(cs->hw.mic.adr, \
+		cs->hw.mic.hscx, reg + (nr ? 0x40 : 0))
+#define WRITEHSCX(cs, nr, reg, data) writereg(cs->hw.mic.adr, \
+		cs->hw.mic.hscx, reg + (nr ? 0x40 : 0), data)
+
+#define READHSCXFIFO(cs, nr, ptr, cnt) readfifo(cs->hw.mic.adr, \
+		cs->hw.mic.hscx, (nr ? 0x40 : 0), ptr, cnt)
+
+#define WRITEHSCXFIFO(cs, nr, ptr, cnt) writefifo(cs->hw.mic.adr, \
+		cs->hw.mic.hscx, (nr ? 0x40 : 0), ptr, cnt)
+
+#include "hscx_irq.c"
+
+static irqreturn_t
+mic_interrupt(int intno, void *dev_id, struct pt_regs *regs)
+{
+	struct IsdnCardState *cs = dev_id;
+	u_char val;
+	u_long flags;
+
+	spin_lock_irqsave(&cs->lock, flags);
+	val = readreg(cs->hw.mic.adr, cs->hw.mic.hscx, HSCX_ISTA + 0x40);
+      Start_HSCX:
+	if (val)
+		hscx_int_main(cs, val);
+	val = readreg(cs->hw.mic.adr, cs->hw.mic.isac, ISAC_ISTA);
+      Start_ISAC:
+	if (val)
+		isac_interrupt(cs, val);
+	val = readreg(cs->hw.mic.adr, cs->hw.mic.hscx, HSCX_ISTA + 0x40);
+	if (val) {
+		if (cs->debug & L1_DEB_HSCX)
+			debugl1(cs, "HSCX IntStat after IntRoutine");
+		goto Start_HSCX;
+	}
+	val = readreg(cs->hw.mic.adr, cs->hw.mic.isac, ISAC_ISTA);
+	if (val) {
+		if (cs->debug & L1_DEB_ISAC)
+			debugl1(cs, "ISAC IntStat after IntRoutine");
+		goto Start_ISAC;
+	}
+	writereg(cs->hw.mic.adr, cs->hw.mic.hscx, HSCX_MASK, 0xFF);
+	writereg(cs->hw.mic.adr, cs->hw.mic.hscx, HSCX_MASK + 0x40, 0xFF);
+	writereg(cs->hw.mic.adr, cs->hw.mic.isac, ISAC_MASK, 0xFF);
+	writereg(cs->hw.mic.adr, cs->hw.mic.isac, ISAC_MASK, 0x0);
+	writereg(cs->hw.mic.adr, cs->hw.mic.hscx, HSCX_MASK, 0x0);
+	writereg(cs->hw.mic.adr, cs->hw.mic.hscx, HSCX_MASK + 0x40, 0x0);
+	spin_unlock_irqrestore(&cs->lock, flags);
+	return IRQ_HANDLED;
+}
+
+void
+release_io_mic(struct IsdnCardState *cs)
+{
+	int bytecnt = 8;
+
+	if (cs->hw.mic.cfg_reg)
+		release_region(cs->hw.mic.cfg_reg, bytecnt);
+}
+
+static int
+mic_card_msg(struct IsdnCardState *cs, int mt, void *arg)
+{
+	u_long flags;
+
+	switch (mt) {
+		case CARD_RESET:
+			return(0);
+		case CARD_RELEASE:
+			release_io_mic(cs);
+			return(0);
+		case CARD_INIT:
+			spin_lock_irqsave(&cs->lock, flags);
+			inithscx(cs); /* /RTSA := ISAC RST */
+			inithscxisac(cs, 3);
+			spin_unlock_irqrestore(&cs->lock, flags);
+			return(0);
+		case CARD_TEST:
+			return(0);
+	}
+	return(0);
 }
 
 int __init
 setup_mic(struct IsdnCard *card)
 {
+	int bytecnt;
+	struct IsdnCardState *cs = card->cs;
 	char tmp[64];
 
 	strcpy(tmp, mic_revision);
 	printk(KERN_INFO "HiSax: mic driver Rev. %s\n", HiSax_getrev(tmp));
+	if (cs->typ != ISDN_CTYPE_MIC)
+		return (0);
+
+	bytecnt = 8;
+	cs->hw.mic.cfg_reg = card->para[1];
+	cs->irq = card->para[0];
+	cs->hw.mic.adr = cs->hw.mic.cfg_reg + MIC_ADR;
+	cs->hw.mic.isac = cs->hw.mic.cfg_reg + MIC_ISAC;
+	cs->hw.mic.hscx = cs->hw.mic.cfg_reg + MIC_HSCX;
 
-	if (mic_probe(card->cs, card) < 0)
-		return 0;
-	return 1;
+	if (!request_region(cs->hw.mic.cfg_reg, bytecnt, "mic isdn")) {
+		printk(KERN_WARNING
+		       "HiSax: %s config port %x-%x already in use\n",
+		       CardType[card->typ],
+		       cs->hw.mic.cfg_reg,
+		       cs->hw.mic.cfg_reg + bytecnt);
+		return (0);
+	}
+	printk(KERN_INFO "mic: defined at 0x%x IRQ %d\n",
+		cs->hw.mic.cfg_reg, cs->irq);
+	setup_isac(cs);
+	cs->readisac = &ReadISAC;
+	cs->writeisac = &WriteISAC;
+	cs->readisacfifo = &ReadISACfifo;
+	cs->writeisacfifo = &WriteISACfifo;
+	cs->BC_Read_Reg = &ReadHSCX;
+	cs->BC_Write_Reg = &WriteHSCX;
+	cs->BC_Send_Data = &hscx_fill_fifo;
+	cs->cardmsg = &mic_card_msg;
+	cs->irq_func = &mic_interrupt;
+	ISACVersion(cs, "mic:");
+	if (HscxVersion(cs, "mic:")) {
+		printk(KERN_WARNING
+		    "mic: wrong HSCX versions check IO address\n");
+		release_io_mic(cs);
+		return (0);
+	}
+	return (1);
 }
--- diff/drivers/isdn/hisax/netjet.c	2003-09-17 12:28:06.000000000 +0100
+++ source/drivers/isdn/hisax/netjet.c	2004-02-23 13:56:42.000000000 +0000
@@ -1,4 +1,4 @@
-/* $Id: netjet.c,v 1.24.6.6 2001/09/23 22:24:50 kai Exp $
+/* $Id: netjet.c,v 1.29.2.4 2004/02/11 13:21:34 keil Exp $
  *
  * low level stuff for Traverse Technologie NETJet ISDN cards
  *
@@ -25,63 +25,40 @@
 #include <asm/io.h>
 #include "netjet.h"
 
-const char *NETjet_revision = "$Revision: 1.24.6.6 $";
-static spinlock_t netjet_lock = SPIN_LOCK_UNLOCKED;
+const char *NETjet_revision = "$Revision: 1.29.2.4 $";
 
 /* Interface functions */
 
-u8
-NETjet_ReadIC(struct IsdnCardState *cs, u8 offset)
+u_char
+NETjet_ReadIC(struct IsdnCardState *cs, u_char offset)
 {
-	unsigned long flags;
-	u8 ret;
+	u_char ret;
 	
-	spin_lock_irqsave(&netjet_lock, flags);
 	cs->hw.njet.auxd &= 0xfc;
 	cs->hw.njet.auxd |= (offset>>4) & 3;
 	byteout(cs->hw.njet.auxa, cs->hw.njet.auxd);
 	ret = bytein(cs->hw.njet.isac + ((offset & 0xf)<<2));
-	spin_unlock_irqrestore(&netjet_lock, flags);
 	return(ret);
 }
 
 void
-NETjet_WriteIC(struct IsdnCardState *cs, u8 offset, u8 value)
+NETjet_WriteIC(struct IsdnCardState *cs, u_char offset, u_char value)
 {
-	unsigned long flags;
-	
-	spin_lock_irqsave(&netjet_lock, flags);
 	cs->hw.njet.auxd &= 0xfc;
 	cs->hw.njet.auxd |= (offset>>4) & 3;
 	byteout(cs->hw.njet.auxa, cs->hw.njet.auxd);
 	byteout(cs->hw.njet.isac + ((offset & 0xf)<<2), value);
-	spin_unlock_irqrestore(&netjet_lock, flags);
 }
 
 void
-NETjet_ReadICfifo(struct IsdnCardState *cs, u8 *data, int size)
+NETjet_ReadICfifo(struct IsdnCardState *cs, u_char *data, int size)
 {
 	cs->hw.njet.auxd &= 0xfc;
 	byteout(cs->hw.njet.auxa, cs->hw.njet.auxd);
 	insb(cs->hw.njet.isac, data, size);
 }
 
-void 
-NETjet_WriteICfifo(struct IsdnCardState *cs, u8 *data, int size)
-{
-	cs->hw.njet.auxd &= 0xfc;
-	byteout(cs->hw.njet.auxa, cs->hw.njet.auxd);
-	outsb(cs->hw.njet.isac, data, size);
-}
-
-struct dc_hw_ops netjet_dc_ops = {
-	.read_reg   = NETjet_ReadIC,
-	.write_reg  = NETjet_WriteIC,
-	.read_fifo  = NETjet_ReadICfifo,
-	.write_fifo = NETjet_WriteICfifo,
-};
-
-static u16 fcstab[256] =
+__u16 fcstab[256] =
 {
 	0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf,
 	0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7,
@@ -117,7 +94,15 @@ static u16 fcstab[256] =
 	0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78
 };
 
-void fill_mem(struct BCState *bcs, u_int *pos, u_int cnt, int chan, u8 fill)
+void 
+NETjet_WriteICfifo(struct IsdnCardState *cs, u_char *data, int size)
+{
+	cs->hw.njet.auxd &= 0xfc;
+	byteout(cs->hw.njet.auxa, cs->hw.njet.auxd);
+	outsb(cs->hw.njet.isac, data, size);
+}
+
+void fill_mem(struct BCState *bcs, u_int *pos, u_int cnt, int chan, u_char fill)
 {
 	u_int mask=0x000000ff, val = 0, *p=pos;
 	u_int i;
@@ -140,7 +125,7 @@ void
 mode_tiger(struct BCState *bcs, int mode, int bc)
 {
 	struct IsdnCardState *cs = bcs->cs;
-        u8 led;
+        u_char led;
 
 	if (cs->debug & L1_DEB_HSCX)
 		debugl1(cs, "Tiger mode %d bchan %d/%d",
@@ -216,11 +201,11 @@ mode_tiger(struct BCState *bcs, int mode
 			bytein(cs->hw.njet.base + NETJET_PULSE_CNT));
 }
 
-static void printframe(struct IsdnCardState *cs, u8 *buf, int count, char *s) {
+static void printframe(struct IsdnCardState *cs, u_char *buf, int count, char *s) {
 	char tmp[128];
 	char *t = tmp;
 	int i=count,j;
-	u8 *p = buf;
+	u_char *p = buf;
 
 	t += sprintf(t, "tiger %s(%4d)", s, count);
 	while (i>0) {
@@ -269,11 +254,11 @@ static void printframe(struct IsdnCardSt
 static int make_raw_data(struct BCState *bcs) {
 // this make_raw is for 64k
 	register u_int i,s_cnt=0;
-	register u8 j;
-	register u8 val;
-	register u8 s_one = 0;
-	register u8 s_val = 0;
-	register u8 bitcnt = 0;
+	register u_char j;
+	register u_char val;
+	register u_char s_one = 0;
+	register u_char s_val = 0;
+	register u_char bitcnt = 0;
 	u_int fcs;
 	
 	if (!bcs->tx_skb) {
@@ -359,11 +344,11 @@ static int make_raw_data(struct BCState 
 static int make_raw_data_56k(struct BCState *bcs) {
 // this make_raw is for 56k
 	register u_int i,s_cnt=0;
-	register u8 j;
-	register u8 val;
-	register u8 s_one = 0;
-	register u8 s_val = 0;
-	register u8 bitcnt = 0;
+	register u_char j;
+	register u_char val;
+	register u_char s_one = 0;
+	register u_char s_val = 0;
+	register u_char bitcnt = 0;
 	u_int fcs;
 	
 	if (!bcs->tx_skb) {
@@ -439,7 +424,8 @@ static void got_frame(struct BCState *bc
 		memcpy(skb_put(skb, count), bcs->hw.tiger.rcvbuf, count);
 		skb_queue_tail(&bcs->rqueue, skb);
 	}
-	sched_b_event(bcs, B_RCVBUFREADY);
+	test_and_set_bit(B_RCVBUFREADY, &bcs->event);
+	schedule_work(&bcs->tqueue);
 	
 	if (bcs->cs->debug & L1_DEB_RECEIVE_FRAME)
 		printframe(bcs->cs, bcs->hw.tiger.rcvbuf, count, "rec");
@@ -449,16 +435,16 @@ static void got_frame(struct BCState *bc
 
 static void read_raw(struct BCState *bcs, u_int *buf, int cnt){
 	int i;
-	register u8 j;
-	register u8 val;
+	register u_char j;
+	register u_char val;
 	u_int  *pend = bcs->hw.tiger.rec +NETJET_DMA_RXSIZE -1;
-	register u8 state = bcs->hw.tiger.r_state;
-	register u8 r_one = bcs->hw.tiger.r_one;
-	register u8 r_val = bcs->hw.tiger.r_val;
+	register u_char state = bcs->hw.tiger.r_state;
+	register u_char r_one = bcs->hw.tiger.r_one;
+	register u_char r_val = bcs->hw.tiger.r_val;
 	register u_int bitcnt = bcs->hw.tiger.r_bitcnt;
 	u_int *p = buf;
 	int bits;
-	u8 mask;
+	u_char mask;
 
         if (bcs->mode == L1_MODE_HDLC) { // it's 64k
 		mask = 0xff;
@@ -682,9 +668,7 @@ void netjet_fill_dma(struct BCState *bcs
 	if (test_and_clear_bit(BC_FLG_NOFRAME, &bcs->Flag)) {
 		write_raw(bcs, bcs->hw.tiger.sendp, bcs->hw.tiger.free);
 	} else if (test_and_clear_bit(BC_FLG_HALF, &bcs->Flag)) {
-		p = inl(bcs->cs->hw.njet.base + NETJET_DMA_READ_ADR)
-			- bcs->hw.tiger.send_dma
-			+ bcs->hw.tiger.send;
+		p = bus_to_virt(inl(bcs->cs->hw.njet.base + NETJET_DMA_READ_ADR));
 		sp = bcs->hw.tiger.sendp;
 		if (p == bcs->hw.tiger.s_end)
 			p = bcs->hw.tiger.send -1;
@@ -705,9 +689,7 @@ void netjet_fill_dma(struct BCState *bcs
 			write_raw(bcs, p, bcs->hw.tiger.free - cnt);
 		}
 	} else if (test_and_clear_bit(BC_FLG_EMPTY, &bcs->Flag)) {
-		p = inl(bcs->cs->hw.njet.base + NETJET_DMA_READ_ADR) 
-			- bcs->hw.tiger.send_dma
-			+ bcs->hw.tiger.send;
+		p = bus_to_virt(inl(bcs->cs->hw.njet.base + NETJET_DMA_READ_ADR));
 		cnt = bcs->hw.tiger.s_end - p;
 		if (cnt < 2) {
 			p = bcs->hw.tiger.send + 1;
@@ -729,7 +711,7 @@ void netjet_fill_dma(struct BCState *bcs
 
 static void write_raw(struct BCState *bcs, u_int *buf, int cnt) {
 	u_int mask, val, *p=buf;
-	int i, s_cnt;
+	u_int i, s_cnt;
         
         if (cnt <= 0)
         	return;
@@ -766,7 +748,16 @@ static void write_raw(struct BCState *bc
 			if (!bcs->tx_skb) {
 				debugl1(bcs->cs,"tiger write_raw: NULL skb s_cnt %d", s_cnt);
 			} else {
-				xmit_complete_b(bcs);
+				if (test_bit(FLG_LLI_L1WAKEUP,&bcs->st->lli.flag) &&
+					(PACKET_NOACK != bcs->tx_skb->pkt_type)) {
+					u_long	flags;
+					spin_lock_irqsave(&bcs->aclock, flags);
+					bcs->ackcnt += bcs->tx_skb->len;
+					spin_unlock_irqrestore(&bcs->aclock, flags);
+					schedule_event(bcs, B_ACKPENDING);
+				}
+				dev_kfree_skb_any(bcs->tx_skb);
+				bcs->tx_skb = NULL;
 			}
 			test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
 			bcs->hw.tiger.free = cnt - s_cnt;
@@ -790,7 +781,8 @@ static void write_raw(struct BCState *bc
 						debugl1(bcs->cs, "tiger write_raw: fill rest %d",
 							cnt - s_cnt);
 				}
-				sched_b_event(bcs, B_XMTBUFREADY);
+				test_and_set_bit(B_XMTBUFREADY, &bcs->event);
+				schedule_work(&bcs->tqueue);
 			}
 		}
 	} else if (test_and_clear_bit(BC_FLG_NOFRAME, &bcs->Flag)) {
@@ -838,36 +830,59 @@ void write_tiger(struct IsdnCardState *c
 static void
 tiger_l2l1(struct PStack *st, int pr, void *arg)
 {
+	struct BCState *bcs = st->l1.bcs;
 	struct sk_buff *skb = arg;
-	struct IsdnCardState *cs = st->l1.bcs->cs;
+	u_long flags;
 
 	switch (pr) {
 		case (PH_DATA | REQUEST):
-			xmit_data_req_b(st->l1.bcs, skb);
+			spin_lock_irqsave(&bcs->cs->lock, flags);
+			if (bcs->tx_skb) {
+				skb_queue_tail(&bcs->squeue, skb);
+			} else {
+				bcs->tx_skb = skb;
+				bcs->cs->BC_Send_Data(bcs);
+			}
+			spin_unlock_irqrestore(&bcs->cs->lock, flags);
 			break;
 		case (PH_PULL | INDICATION):
-			xmit_pull_ind_b(st->l1.bcs, skb);
+			spin_lock_irqsave(&bcs->cs->lock, flags);
+			if (bcs->tx_skb) {
+				printk(KERN_WARNING "tiger_l2l1: this shouldn't happen\n");
+			} else {
+				bcs->tx_skb = skb;
+				bcs->cs->BC_Send_Data(bcs);
+			}
+			spin_unlock_irqrestore(&bcs->cs->lock, flags);
 			break;
 		case (PH_PULL | REQUEST):
-			xmit_pull_req_b(st);
+			if (!bcs->tx_skb) {
+				test_and_clear_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
+				st->l1.l1l2(st, PH_PULL | CONFIRM, NULL);
+			} else
+				test_and_set_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
 			break;
 		case (PH_ACTIVATE | REQUEST):
-			test_and_set_bit(BC_FLG_ACTIV, &st->l1.bcs->Flag);
-			mode_tiger(st->l1.bcs, st->l1.mode, st->l1.bc);
-			if (cs->hw.njet.bc_activate)
-				(cs->hw.njet.bc_activate)(cs, st->l1.bc);
+			spin_lock_irqsave(&bcs->cs->lock, flags);
+			test_and_set_bit(BC_FLG_ACTIV, &bcs->Flag);
+			mode_tiger(bcs, st->l1.mode, st->l1.bc);
+			/* 2001/10/04 Christoph Ersfeld, Formula-n Europe AG */
+			spin_unlock_irqrestore(&bcs->cs->lock, flags);
+			bcs->cs->cardmsg(bcs->cs, MDL_BC_ASSIGN, (void *)(&st->l1.bc));
 			l1_msg_b(st, pr, arg);
 			break;
 		case (PH_DEACTIVATE | REQUEST):
-			if (cs->hw.njet.bc_deactivate)
-				(cs->hw.njet.bc_deactivate)(cs, st->l1.bc);
+			/* 2001/10/04 Christoph Ersfeld, Formula-n Europe AG */
+			bcs->cs->cardmsg(bcs->cs, MDL_BC_RELEASE, (void *)(&st->l1.bc));
 			l1_msg_b(st, pr, arg);
 			break;
 		case (PH_DEACTIVATE | CONFIRM):
-			test_and_clear_bit(BC_FLG_ACTIV, &st->l1.bcs->Flag);
-			test_and_clear_bit(BC_FLG_BUSY, &st->l1.bcs->Flag);
-			mode_tiger(st->l1.bcs, 0, st->l1.bc);
-			L1L2(st, PH_DEACTIVATE | CONFIRM, NULL);
+			spin_lock_irqsave(&bcs->cs->lock, flags);
+			test_and_clear_bit(BC_FLG_ACTIV, &bcs->Flag);
+			test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
+			mode_tiger(bcs, 0, st->l1.bc);
+			spin_unlock_irqrestore(&bcs->cs->lock, flags);
+			st->l1.l1l2(st, PH_DEACTIVATE | CONFIRM, NULL);
 			break;
 	}
 }
@@ -928,7 +943,7 @@ setstack_tiger(struct PStack *st, struct
 	if (open_tigerstate(st->l1.hardware, bcs))
 		return (-1);
 	st->l1.bcs = bcs;
-	st->l1.l2l1 = tiger_l2l1;
+	st->l2.l2l1 = tiger_l2l1;
 	setstack_manager(st);
 	bcs->st = st;
 	setstack_l1_B(st);
@@ -936,47 +951,32 @@ setstack_tiger(struct PStack *st, struct
 }
 
  
-static struct bc_l1_ops netjet_l1_ops = {
-	.fill_fifo = netjet_fill_dma,
-	.open      = setstack_tiger,
-	.close     = close_tigerstate,
-};
-
 void __init
 inittiger(struct IsdnCardState *cs)
 {
-	cs->bc_l1_ops = &netjet_l1_ops;
-
-	cs->bcs[0].hw.tiger.send = 
-		pci_alloc_consistent(cs->hw.njet.pdev,
-				     NETJET_DMA_TXSIZE * sizeof(unsigned int),
-				     &cs->bcs[0].hw.tiger.send_dma);
-	if (!cs->bcs[0].hw.tiger.send) {
+	if (!(cs->bcs[0].hw.tiger.send = kmalloc(NETJET_DMA_TXSIZE * sizeof(unsigned int),
+		GFP_KERNEL | GFP_DMA))) {
 		printk(KERN_WARNING
 		       "HiSax: No memory for tiger.send\n");
 		return;
 	}
-	cs->bcs[0].hw.tiger.s_end     = cs->bcs[0].hw.tiger.send     + NETJET_DMA_TXSIZE - 1;
-
-	cs->bcs[1].hw.tiger.send      = cs->bcs[0].hw.tiger.send;
-	cs->bcs[1].hw.tiger.send_dma  = cs->bcs[0].hw.tiger.send_dma;
-	cs->bcs[1].hw.tiger.s_end     = cs->bcs[0].hw.tiger.s_end;
+	cs->bcs[0].hw.tiger.s_irq = cs->bcs[0].hw.tiger.send + NETJET_DMA_TXSIZE/2 - 1;
+	cs->bcs[0].hw.tiger.s_end = cs->bcs[0].hw.tiger.send + NETJET_DMA_TXSIZE - 1;
+	cs->bcs[1].hw.tiger.send = cs->bcs[0].hw.tiger.send;
+	cs->bcs[1].hw.tiger.s_irq = cs->bcs[0].hw.tiger.s_irq;
+	cs->bcs[1].hw.tiger.s_end = cs->bcs[0].hw.tiger.s_end;
 	
 	memset(cs->bcs[0].hw.tiger.send, 0xff, NETJET_DMA_TXSIZE * sizeof(unsigned int));
 	debugl1(cs, "tiger: send buf %x - %x", (u_int)cs->bcs[0].hw.tiger.send,
 		(u_int)(cs->bcs[0].hw.tiger.send + NETJET_DMA_TXSIZE - 1));
-	outl(cs->bcs[0].hw.tiger.send_dma,
+	outl(virt_to_bus(cs->bcs[0].hw.tiger.send),
 		cs->hw.njet.base + NETJET_DMA_READ_START);
-	outl(cs->bcs[0].hw.tiger.send_dma + NETJET_DMA_TXSIZE/2 - 1,
+	outl(virt_to_bus(cs->bcs[0].hw.tiger.s_irq),
 		cs->hw.njet.base + NETJET_DMA_READ_IRQ);
-	outl(cs->bcs[0].hw.tiger.send_dma + NETJET_DMA_TXSIZE - 1,
+	outl(virt_to_bus(cs->bcs[0].hw.tiger.s_end),
 		cs->hw.njet.base + NETJET_DMA_READ_END);
-
-	cs->bcs[0].hw.tiger.rec = 
-		pci_alloc_consistent(cs->hw.njet.pdev,
-				     NETJET_DMA_RXSIZE * sizeof(unsigned int),
-				     &cs->bcs[0].hw.tiger.rec_dma);
-	if (!cs->bcs[0].hw.tiger.rec) {
+	if (!(cs->bcs[0].hw.tiger.rec = kmalloc(NETJET_DMA_RXSIZE * sizeof(unsigned int),
+		GFP_KERNEL | GFP_DMA))) {
 		printk(KERN_WARNING
 		       "HiSax: No memory for tiger.rec\n");
 		return;
@@ -984,39 +984,36 @@ inittiger(struct IsdnCardState *cs)
 	debugl1(cs, "tiger: rec buf %x - %x", (u_int)cs->bcs[0].hw.tiger.rec,
 		(u_int)(cs->bcs[0].hw.tiger.rec + NETJET_DMA_RXSIZE - 1));
 	cs->bcs[1].hw.tiger.rec = cs->bcs[0].hw.tiger.rec;
-	cs->bcs[1].hw.tiger.rec_dma = cs->bcs[0].hw.tiger.rec_dma;
 	memset(cs->bcs[0].hw.tiger.rec, 0xff, NETJET_DMA_RXSIZE * sizeof(unsigned int));
-	outl(cs->bcs[0].hw.tiger.rec_dma,
+	outl(virt_to_bus(cs->bcs[0].hw.tiger.rec),
 		cs->hw.njet.base + NETJET_DMA_WRITE_START);
-	outl(cs->bcs[0].hw.tiger.rec_dma + NETJET_DMA_RXSIZE/2 - 1,
+	outl(virt_to_bus(cs->bcs[0].hw.tiger.rec + NETJET_DMA_RXSIZE/2 - 1),
 		cs->hw.njet.base + NETJET_DMA_WRITE_IRQ);
-	outl(cs->bcs[0].hw.tiger.rec_dma + NETJET_DMA_RXSIZE - 1,
+	outl(virt_to_bus(cs->bcs[0].hw.tiger.rec + NETJET_DMA_RXSIZE - 1),
 		cs->hw.njet.base + NETJET_DMA_WRITE_END);
 	debugl1(cs, "tiger: dmacfg  %x/%x  pulse=%d",
 		inl(cs->hw.njet.base + NETJET_DMA_WRITE_ADR),
 		inl(cs->hw.njet.base + NETJET_DMA_READ_ADR),
 		bytein(cs->hw.njet.base + NETJET_PULSE_CNT));
 	cs->hw.njet.last_is0 = 0;
+	cs->bcs[0].BC_SetStack = setstack_tiger;
+	cs->bcs[1].BC_SetStack = setstack_tiger;
+	cs->bcs[0].BC_Close = close_tigerstate;
+	cs->bcs[1].BC_Close = close_tigerstate;
 }
 
-static void
+void
 releasetiger(struct IsdnCardState *cs)
 {
 	if (cs->bcs[0].hw.tiger.send) {
-		pci_free_consistent(cs->hw.njet.pdev,
-				    NETJET_DMA_TXSIZE * sizeof(unsigned int),
-				    cs->bcs[0].hw.tiger.send,
-				    cs->bcs[0].hw.tiger.send_dma);
+		kfree(cs->bcs[0].hw.tiger.send);
 		cs->bcs[0].hw.tiger.send = NULL;
 	}
 	if (cs->bcs[1].hw.tiger.send) {
 		cs->bcs[1].hw.tiger.send = NULL;
 	}
 	if (cs->bcs[0].hw.tiger.rec) {
-		pci_free_consistent(cs->hw.njet.pdev,
-				    NETJET_DMA_RXSIZE * sizeof(unsigned int),
-				    cs->bcs[0].hw.tiger.rec,
-				    cs->bcs[0].hw.tiger.rec_dma);
+		kfree(cs->bcs[0].hw.tiger.rec);
 		cs->bcs[0].hw.tiger.rec = NULL;
 	}
 	if (cs->bcs[1].hw.tiger.rec) {
@@ -1025,11 +1022,11 @@ releasetiger(struct IsdnCardState *cs)
 }
 
 void
-netjet_release(struct IsdnCardState *cs)
+release_io_netjet(struct IsdnCardState *cs)
 {
 	byteout(cs->hw.njet.base + NETJET_IRQMASK0, 0);
 	byteout(cs->hw.njet.base + NETJET_IRQMASK1, 0);
 	releasetiger(cs);
-	hisax_release_resources(cs);
+	release_region(cs->hw.njet.base, 256);
 }
 
--- diff/drivers/isdn/hisax/netjet.h	2003-01-16 11:30:36.000000000 +0000
+++ source/drivers/isdn/hisax/netjet.h	2004-02-23 13:56:42.000000000 +0000
@@ -1,4 +1,4 @@
-/* $Id: netjet.h,v 2.5.6.3 2001/09/23 22:24:50 kai Exp $
+/* $Id: netjet.h,v 2.8.2.2 2004/01/12 22:52:28 keil Exp $
  *
  * NETjet common header file
  *
@@ -57,12 +57,10 @@ extern const char *CardType[];
 
 #define HDLC_FLAG_VALUE	0x7e
 
-extern struct dc_hw_ops netjet_dc_ops;
-
-u8 NETjet_ReadIC(struct IsdnCardState *cs, u8 offset);
-void NETjet_WriteIC(struct IsdnCardState *cs, u8 offset, u8 value);
-void NETjet_ReadICfifo(struct IsdnCardState *cs, u8 *data, int size);
-void NETjet_WriteICfifo(struct IsdnCardState *cs, u8 *data, int size);
+u_char NETjet_ReadIC(struct IsdnCardState *cs, u_char offset);
+void NETjet_WriteIC(struct IsdnCardState *cs, u_char offset, u_char value);
+void NETjet_ReadICfifo(struct IsdnCardState *cs, u_char *data, int size);
+void NETjet_WriteICfifo(struct IsdnCardState *cs, u_char *data, int size);
 
 void read_tiger(struct IsdnCardState *cs);
 void write_tiger(struct IsdnCardState *cs);
@@ -70,5 +68,5 @@ void write_tiger(struct IsdnCardState *c
 void netjet_fill_dma(struct BCState *bcs);
 void netjet_interrupt(int intno, void *dev_id, struct pt_regs *regs);
 void inittiger(struct IsdnCardState *cs);
-void netjet_release(struct IsdnCardState *cs);
+void release_io_netjet(struct IsdnCardState *cs);
 
--- diff/drivers/isdn/hisax/niccy.c	2003-06-09 14:18:18.000000000 +0100
+++ source/drivers/isdn/hisax/niccy.c	2004-02-23 13:56:42.000000000 +0000
@@ -1,4 +1,4 @@
-/* $Id: niccy.c,v 1.15.6.6 2001/10/20 22:08:24 kai Exp $
+/* $Id: niccy.c,v 1.21.2.4 2004/01/13 23:48:39 keil Exp $
  *
  * low level stuff for Dr. Neuhaus NICCY PnP and NICCY PCI and
  * compatible (SAGEM cybermodem)
@@ -24,8 +24,7 @@
 #include <linux/isapnp.h>
 
 extern const char *CardType[];
-const char *niccy_revision = "$Revision: 1.15.6.6 $";
-static spinlock_t niccy_lock = SPIN_LOCK_UNLOCKED;
+const char *niccy_revision = "$Revision: 1.21.2.4 $";
 
 #define byteout(addr,val) outb(val,addr)
 #define bytein(addr) inb(addr)
@@ -47,127 +46,140 @@ static spinlock_t niccy_lock = SPIN_LOCK
 #define PCI_IRQ_DISABLE		0xff0000
 #define PCI_IRQ_ASSERT		0x800000
 
-static inline u8
-readreg(unsigned int ale, unsigned int adr, u8 off)
+static inline u_char
+readreg(unsigned int ale, unsigned int adr, u_char off)
 {
-	u8 ret;
-	unsigned long flags;
+	register u_char ret;
 
-	spin_lock_irqsave(&niccy_lock, flags);
 	byteout(ale, off);
 	ret = bytein(adr);
-	spin_unlock_irqrestore(&niccy_lock, flags);
-	return ret;
+	return (ret);
 }
 
 static inline void
-writereg(unsigned int ale, unsigned int adr, u8 off, u8 data)
+readfifo(unsigned int ale, unsigned int adr, u_char off, u_char * data, int size)
 {
-	unsigned long flags;
-
-	spin_lock_irqsave(&niccy_lock, flags);
 	byteout(ale, off);
-	byteout(adr, data);
-	spin_unlock_irqrestore(&niccy_lock, flags);
+	insb(adr, data, size);
 }
 
+
 static inline void
-readfifo(unsigned int ale, unsigned int adr, u8 off, u8 * data, int size)
+writereg(unsigned int ale, unsigned int adr, u_char off, u_char data)
 {
 	byteout(ale, off);
-	insb(adr, data, size);
+	byteout(adr, data);
 }
 
 static inline void
-writefifo(unsigned int ale, unsigned int adr, u8 off, u8 * data, int size)
+writefifo(unsigned int ale, unsigned int adr, u_char off, u_char * data, int size)
 {
 	byteout(ale, off);
 	outsb(adr, data, size);
 }
 
-static u8
-isac_read(struct IsdnCardState *cs, u8 offset)
+/* Interface functions */
+
+static u_char
+ReadISAC(struct IsdnCardState *cs, u_char offset)
 {
-	return readreg(cs->hw.niccy.isac_ale, cs->hw.niccy.isac, offset);
+	return (readreg(cs->hw.niccy.isac_ale, cs->hw.niccy.isac, offset));
 }
 
 static void
-isac_write(struct IsdnCardState *cs, u8 offset, u8 value)
+WriteISAC(struct IsdnCardState *cs, u_char offset, u_char value)
 {
 	writereg(cs->hw.niccy.isac_ale, cs->hw.niccy.isac, offset, value);
 }
 
 static void
-isac_read_fifo(struct IsdnCardState *cs, u8 *data, int size)
+ReadISACfifo(struct IsdnCardState *cs, u_char * data, int size)
 {
 	readfifo(cs->hw.niccy.isac_ale, cs->hw.niccy.isac, 0, data, size);
 }
 
 static void
-isac_write_fifo(struct IsdnCardState *cs, u8 *data, int size)
+WriteISACfifo(struct IsdnCardState *cs, u_char * data, int size)
 {
 	writefifo(cs->hw.niccy.isac_ale, cs->hw.niccy.isac, 0, data, size);
 }
 
-static struct dc_hw_ops isac_ops = {
-	.read_reg   = isac_read,
-	.write_reg  = isac_write,
-	.read_fifo  = isac_read_fifo,
-	.write_fifo = isac_write_fifo,
-};
-
-static u8
-hscx_read(struct IsdnCardState *cs, int hscx, u8 offset)
+static u_char
+ReadHSCX(struct IsdnCardState *cs, int hscx, u_char offset)
 {
-	return readreg(cs->hw.niccy.hscx_ale,
-		       cs->hw.niccy.hscx, offset + (hscx ? 0x40 : 0));
+	return (readreg(cs->hw.niccy.hscx_ale,
+			cs->hw.niccy.hscx, offset + (hscx ? 0x40 : 0)));
 }
 
 static void
-hscx_write(struct IsdnCardState *cs, int hscx, u8 offset, u8 value)
+WriteHSCX(struct IsdnCardState *cs, int hscx, u_char offset, u_char value)
 {
 	writereg(cs->hw.niccy.hscx_ale,
 		 cs->hw.niccy.hscx, offset + (hscx ? 0x40 : 0), value);
 }
 
-static void
-hscx_read_fifo(struct IsdnCardState *cs, int hscx, u8 *data, int size)
-{
-	readfifo(cs->hw.niccy.hscx_ale, cs->hw.niccy.hscx,
-		 hscx ? 0x40 : 0, data, size);
-}
+#define READHSCX(cs, nr, reg) readreg(cs->hw.niccy.hscx_ale, \
+		cs->hw.niccy.hscx, reg + (nr ? 0x40 : 0))
+#define WRITEHSCX(cs, nr, reg, data) writereg(cs->hw.niccy.hscx_ale, \
+		cs->hw.niccy.hscx, reg + (nr ? 0x40 : 0), data)
 
-static void
-hscx_write_fifo(struct IsdnCardState *cs, int hscx, u8 *data, int size)
-{
-	writefifo(cs->hw.niccy.hscx_ale, cs->hw.niccy.hscx,
-		  hscx ? 0x40 : 0, data, size);
-}
+#define READHSCXFIFO(cs, nr, ptr, cnt) readfifo(cs->hw.niccy.hscx_ale, \
+		cs->hw.niccy.hscx, (nr ? 0x40 : 0), ptr, cnt)
 
-static struct bc_hw_ops hscx_ops = {
-	.read_reg  = hscx_read,
-	.write_reg = hscx_write,
-	.read_fifo  = hscx_read_fifo,
-	.write_fifo = hscx_write_fifo,
-};
+#define WRITEHSCXFIFO(cs, nr, ptr, cnt) writefifo(cs->hw.niccy.hscx_ale, \
+		cs->hw.niccy.hscx, (nr ? 0x40 : 0), ptr, cnt)
+
+#include "hscx_irq.c"
 
 static irqreturn_t
 niccy_interrupt(int intno, void *dev_id, struct pt_regs *regs)
 {
 	struct IsdnCardState *cs = dev_id;
-	
+	u_char val;
+	u_long flags;
+
+	spin_lock_irqsave(&cs->lock, flags);
 	if (cs->subtyp == NICCY_PCI) {
 		int ival;
 		ival = inl(cs->hw.niccy.cfg_reg + PCI_IRQ_CTRL_REG);
-		if (!(ival & PCI_IRQ_ASSERT)) /* IRQ not for us (shared) */
+		if (!(ival & PCI_IRQ_ASSERT)) { /* IRQ not for us (shared) */
+			spin_unlock_irqrestore(&cs->lock, flags);
 			return IRQ_NONE;
+		}
 		outl(ival, cs->hw.niccy.cfg_reg + PCI_IRQ_CTRL_REG);
 	}
-	return hscxisac_irq(intno, dev_id, regs);
+	val = readreg(cs->hw.niccy.hscx_ale, cs->hw.niccy.hscx, HSCX_ISTA + 0x40);
+      Start_HSCX:
+	if (val)
+		hscx_int_main(cs, val);
+	val = readreg(cs->hw.niccy.isac_ale, cs->hw.niccy.isac, ISAC_ISTA);
+      Start_ISAC:
+	if (val)
+		isac_interrupt(cs, val);
+	val = readreg(cs->hw.niccy.hscx_ale, cs->hw.niccy.hscx, HSCX_ISTA + 0x40);
+	if (val) {
+		if (cs->debug & L1_DEB_HSCX)
+			debugl1(cs, "HSCX IntStat after IntRoutine");
+		goto Start_HSCX;
+	}
+	val = readreg(cs->hw.niccy.isac_ale, cs->hw.niccy.isac, ISAC_ISTA);
+	if (val) {
+		if (cs->debug & L1_DEB_ISAC)
+			debugl1(cs, "ISAC IntStat after IntRoutine");
+		goto Start_ISAC;
+	}
+	writereg(cs->hw.niccy.hscx_ale, cs->hw.niccy.hscx, HSCX_MASK, 0xFF);
+	writereg(cs->hw.niccy.hscx_ale, cs->hw.niccy.hscx, HSCX_MASK + 0x40, 0xFF);
+	writereg(cs->hw.niccy.isac_ale, cs->hw.niccy.isac, ISAC_MASK, 0xFF);
+	writereg(cs->hw.niccy.isac_ale, cs->hw.niccy.isac, ISAC_MASK, 0);
+	writereg(cs->hw.niccy.hscx_ale, cs->hw.niccy.hscx, HSCX_MASK, 0);
+	writereg(cs->hw.niccy.hscx_ale, cs->hw.niccy.hscx, HSCX_MASK + 0x40, 0);
+	spin_unlock_irqrestore(&cs->lock, flags);
+	return IRQ_HANDLED;
 }
 
 void
-niccy_release(struct IsdnCardState *cs)
+release_io_niccy(struct IsdnCardState *cs)
 {
 	if (cs->subtyp == NICCY_PCI) {
 		int val;
@@ -175,11 +187,15 @@ niccy_release(struct IsdnCardState *cs)
 		val = inl(cs->hw.niccy.cfg_reg + PCI_IRQ_CTRL_REG);
 		val &= PCI_IRQ_DISABLE;
 		outl(val, cs->hw.niccy.cfg_reg + PCI_IRQ_CTRL_REG);
+		release_region(cs->hw.niccy.cfg_reg, 0x40);
+		release_region(cs->hw.niccy.isac, 4);
+	} else {
+		release_region(cs->hw.niccy.isac, 2);
+		release_region(cs->hw.niccy.isac_ale, 2);
 	}
-	hisax_release_resources(cs);
 }
 
-static int
+static void
 niccy_reset(struct IsdnCardState *cs)
 {
 	if (cs->subtyp == NICCY_PCI) {
@@ -189,78 +205,32 @@ niccy_reset(struct IsdnCardState *cs)
 		val |= PCI_IRQ_ENABLE;
 		outl(val, cs->hw.niccy.cfg_reg + PCI_IRQ_CTRL_REG);
 	}
-	return 0;
+	inithscxisac(cs, 3);
 }
 
-static struct card_ops niccy_ops = {
-	.init     = inithscxisac,
-	.reset    = niccy_reset,
-	.release  = niccy_release,
-	.irq_func = niccy_interrupt,
-};
-
-static int __init
-niccy_probe(struct IsdnCardState *cs)
+static int
+niccy_card_msg(struct IsdnCardState *cs, int mt, void *arg)
 {
-	printk(KERN_INFO "HiSax: %s %s config irq:%d data:0x%X ale:0x%X\n",
-	       CardType[cs->typ], (cs->subtyp==1) ? "PnP":"PCI",
-	       cs->irq, cs->hw.niccy.isac, cs->hw.niccy.isac_ale);
-	cs->card_ops = &niccy_ops;
-	if (hscxisac_setup(cs, &isac_ops, &hscx_ops))
-		return -EBUSY;
-	return 0;
-}
-
-static int __init
-niccy_pnp_probe(struct IsdnCardState *cs, struct IsdnCard *card)
-{
-	cs->subtyp = NICCY_PNP;
-	cs->irq = card->para[0];
-	cs->hw.niccy.isac = card->para[1] + ISAC_PNP;
-	cs->hw.niccy.hscx = card->para[1] + HSCX_PNP;
-	cs->hw.niccy.isac_ale = card->para[2] + ISAC_PNP;
-	cs->hw.niccy.hscx_ale = card->para[2] + HSCX_PNP;
-	cs->hw.niccy.cfg_reg = 0;
-
-	if (!request_io(&cs->rs, cs->hw.niccy.isac, 2, "niccy data"))
-		goto err;
-	if (!request_io(&cs->rs, cs->hw.niccy.isac_ale, 2, "niccy addr"))
-		goto err;
-	if (niccy_probe(cs) < 0)
-		goto err;
-	return 0;
- err:
-	hisax_release_resources(cs);
-	return -EBUSY;
-}
-
-static int __init
-niccy_pci_probe(struct IsdnCardState *cs, struct pci_dev *pdev)
-{
-	u32 pci_ioaddr;
-
-	if (pci_enable_device(pdev))
-		goto err;
-
-	cs->subtyp = NICCY_PCI;
-	cs->irq = pdev->irq;
-	cs->irq_flags |= SA_SHIRQ;
-	cs->hw.niccy.cfg_reg = pci_resource_start(pdev, 0);
-	pci_ioaddr = pci_resource_start(pdev, 1);
-	cs->hw.niccy.isac = pci_ioaddr + ISAC_PCI_DATA;
-	cs->hw.niccy.isac_ale = pci_ioaddr + ISAC_PCI_ADDR;
-	cs->hw.niccy.hscx = pci_ioaddr + HSCX_PCI_DATA;
-	cs->hw.niccy.hscx_ale = pci_ioaddr + HSCX_PCI_ADDR;
-	if (!request_io(&cs->rs, cs->hw.niccy.isac, 4, "niccy"))
-		goto err;
-	if (!request_io(&cs->rs, cs->hw.niccy.cfg_reg, 0x40, "niccy pci"))
-		goto err;
-	if (niccy_probe(cs) < 0)
-		goto err;
-	return 0;
- err:
-	hisax_release_resources(cs);
-	return -EBUSY;
+	u_long flags;
+
+	switch (mt) {
+		case CARD_RESET:
+			spin_lock_irqsave(&cs->lock, flags);
+			niccy_reset(cs);
+			spin_unlock_irqrestore(&cs->lock, flags);
+			return(0);
+		case CARD_RELEASE:
+			release_io_niccy(cs);
+			return(0);
+		case CARD_INIT:
+			spin_lock_irqsave(&cs->lock, flags);
+			niccy_reset(cs);
+			spin_unlock_irqrestore(&cs->lock, flags);
+			return(0);
+		case CARD_TEST:
+			return(0);
+	}
+	return(0);
 }
 
 static struct pci_dev *niccy_dev __initdata = NULL;
@@ -271,62 +241,149 @@ static struct pnp_card *pnp_c __devinitd
 int __init
 setup_niccy(struct IsdnCard *card)
 {
+	struct IsdnCardState *cs = card->cs;
 	char tmp[64];
 
 	strcpy(tmp, niccy_revision);
 	printk(KERN_INFO "HiSax: Niccy driver Rev. %s\n", HiSax_getrev(tmp));
+	if (cs->typ != ISDN_CTYPE_NICCY)
+		return (0);
 #ifdef __ISAPNP__
 	if (!card->para[1] && isapnp_present()) {
-		struct pnp_card *pb;
-		struct pnp_dev  *pd;
+		struct pnp_dev *pnp_d = NULL;
+		int err;
 
-		if ((pb = pnp_find_card(
+		if ((pnp_c = pnp_find_card(
 			ISAPNP_VENDOR('S', 'D', 'A'),
 			ISAPNP_FUNCTION(0x0150), pnp_c))) {
-			pnp_c = pb;
-			pd = NULL;
-			if (!(pd = pnp_find_dev(pnp_c,
+			if (!(pnp_d = pnp_find_dev(pnp_c,
 				ISAPNP_VENDOR('S', 'D', 'A'),
-				ISAPNP_FUNCTION(0x0150), pd))) {
+				ISAPNP_FUNCTION(0x0150), pnp_d))) {
 				printk(KERN_ERR "NiccyPnP: PnP error card found, no device\n");
 				return (0);
 			}
-			if (pnp_device_attach(pd) < 0) {
-				printk(KERN_ERR "NiccyPnP: attach failed\n");
-				return 0;
-			}
-			if (pnp_activate_dev(pd) < 0) {
-				printk(KERN_ERR "NiccyPnP: activate failed\n");
-				pnp_device_detach(pd);
-				return 0;
+			pnp_disable_dev(pnp_d);
+			err = pnp_activate_dev(pnp_d);
+			if (err<0) {
+				printk(KERN_WARNING "%s: pnp_activate_dev ret(%d)\n",
+					__FUNCTION__, err);
+				return(0);
 			}
-			if (!pnp_irq_valid(pd, 0) || !pnp_port_valid(pd, 0) || !pnp_port_valid(pd, 1)) {
+			card->para[1] = pnp_port_start(pnp_d, 0);
+			card->para[2] = pnp_port_start(pnp_d, 1);
+			card->para[0] = pnp_irq(pnp_d, 0);;
+			if (!card->para[0] || !card->para[1] || !card->para[2]) {
 				printk(KERN_ERR "NiccyPnP:some resources are missing %ld/%lx/%lx\n",
-					pnp_irq(pd, 0), pnp_port_start(pd, 0), pnp_port_start(pd, 1));
-				pnp_device_detach(pd);
+					card->para[0], card->para[1], card->para[2]);
+				pnp_disable_dev(pnp_d);
 				return(0);
 			}
-			card->para[1] = pnp_port_start(pd, 0);
-			card->para[2] = pnp_port_start(pd, 1);
-			card->para[0] = pnp_irq(pd, 0);
 		} else {
 			printk(KERN_INFO "NiccyPnP: no ISAPnP card found\n");
 		}
 	}
 #endif
 	if (card->para[1]) {
-		if (niccy_pnp_probe(card->cs, card) < 0)
-			return 0;
-		return 1;
+		cs->hw.niccy.isac = card->para[1] + ISAC_PNP;
+		cs->hw.niccy.hscx = card->para[1] + HSCX_PNP;
+		cs->hw.niccy.isac_ale = card->para[2] + ISAC_PNP;
+		cs->hw.niccy.hscx_ale = card->para[2] + HSCX_PNP;
+		cs->hw.niccy.cfg_reg = 0;
+		cs->subtyp = NICCY_PNP;
+		cs->irq = card->para[0];
+		if (!request_region(cs->hw.niccy.isac, 2, "niccy data")) {
+			printk(KERN_WARNING
+				"HiSax: %s data port %x-%x already in use\n",
+				CardType[card->typ],
+				cs->hw.niccy.isac,
+				cs->hw.niccy.isac + 1);
+			return (0);
+		}
+		if (!request_region(cs->hw.niccy.isac_ale, 2, "niccy addr")) {
+			printk(KERN_WARNING
+				"HiSax: %s address port %x-%x already in use\n",
+				CardType[card->typ],
+				cs->hw.niccy.isac_ale,
+				cs->hw.niccy.isac_ale + 1);
+			release_region(cs->hw.niccy.isac, 2);
+			return (0);
+		}
 	} else {
-#ifdef CONFIG_PCI
+#if CONFIG_PCI
+		u_int pci_ioaddr;
+		cs->subtyp = 0;
 		if ((niccy_dev = pci_find_device(PCI_VENDOR_ID_SATSAGEM,
 			PCI_DEVICE_ID_SATSAGEM_NICCY, niccy_dev))) {
-			if (niccy_pci_probe(card->cs, niccy_dev) < 0)
-				return 0;
-			return 1;
+			if (pci_enable_device(niccy_dev))
+				return(0);
+			/* get IRQ */
+			if (!niccy_dev->irq) {
+				printk(KERN_WARNING "Niccy: No IRQ for PCI card found\n");
+				return(0);
+			}
+			cs->irq = niccy_dev->irq;
+			cs->hw.niccy.cfg_reg = pci_resource_start(niccy_dev, 0);
+			if (!cs->hw.niccy.cfg_reg) {
+				printk(KERN_WARNING "Niccy: No IO-Adr for PCI cfg found\n");
+				return(0);
+			}
+			pci_ioaddr = pci_resource_start(niccy_dev, 1);
+			if (!pci_ioaddr) {
+				printk(KERN_WARNING "Niccy: No IO-Adr for PCI card found\n");
+				return(0);
+			}
+			cs->subtyp = NICCY_PCI;
+		} else {
+			printk(KERN_WARNING "Niccy: No PCI card found\n");
+			return(0);
+		}
+		cs->irq_flags |= SA_SHIRQ;
+		cs->hw.niccy.isac = pci_ioaddr + ISAC_PCI_DATA;
+		cs->hw.niccy.isac_ale = pci_ioaddr + ISAC_PCI_ADDR;
+		cs->hw.niccy.hscx = pci_ioaddr + HSCX_PCI_DATA;
+		cs->hw.niccy.hscx_ale = pci_ioaddr + HSCX_PCI_ADDR;
+		if (!request_region(cs->hw.niccy.isac, 4, "niccy")) {
+			printk(KERN_WARNING
+				"HiSax: %s data port %x-%x already in use\n",
+				CardType[card->typ],
+				cs->hw.niccy.isac,
+				cs->hw.niccy.isac + 4);
+			return (0);
+		}
+		if (!request_region(cs->hw.niccy.cfg_reg, 0x40, "niccy pci")) {
+			printk(KERN_WARNING
+			       "HiSax: %s pci port %x-%x already in use\n",
+				CardType[card->typ],
+				cs->hw.niccy.cfg_reg,
+				cs->hw.niccy.cfg_reg + 0x40);
+			release_region(cs->hw.niccy.isac, 4);
+			return (0);
 		}
+#else
+		printk(KERN_WARNING "Niccy: io0 0 and NO_PCI_BIOS\n");
+		printk(KERN_WARNING "Niccy: unable to config NICCY PCI\n");
+		return (0);
 #endif /* CONFIG_PCI */
 	}
-	return 0;
+	printk(KERN_INFO "HiSax: %s %s config irq:%d data:0x%X ale:0x%X\n",
+		CardType[cs->typ], (cs->subtyp==1) ? "PnP":"PCI",
+		cs->irq, cs->hw.niccy.isac, cs->hw.niccy.isac_ale);
+	setup_isac(cs);
+	cs->readisac = &ReadISAC;
+	cs->writeisac = &WriteISAC;
+	cs->readisacfifo = &ReadISACfifo;
+	cs->writeisacfifo = &WriteISACfifo;
+	cs->BC_Read_Reg = &ReadHSCX;
+	cs->BC_Write_Reg = &WriteHSCX;
+	cs->BC_Send_Data = &hscx_fill_fifo;
+	cs->cardmsg = &niccy_card_msg;
+	cs->irq_func = &niccy_interrupt;
+	ISACVersion(cs, "Niccy:");
+	if (HscxVersion(cs, "Niccy:")) {
+		printk(KERN_WARNING
+		    "Niccy: wrong HSCX versions check IO address\n");
+		release_io_niccy(cs);
+		return (0);
+	}
+	return (1);
 }
--- diff/drivers/isdn/hisax/nj_s.c	2003-05-21 11:50:15.000000000 +0100
+++ source/drivers/isdn/hisax/nj_s.c	2004-02-23 13:56:42.000000000 +0000
@@ -1,4 +1,4 @@
-/* $Id: nj_s.c,v 2.7.6.6 2001/09/23 22:24:50 kai Exp $
+/* $Id: nj_s.c,v 2.13.2.4 2004/01/16 01:53:48 keil Exp $
  *
  * This software may be used and distributed according to the terms
  * of the GNU General Public License, incorporated herein by reference.
@@ -15,43 +15,74 @@
 #include <linux/ppp_defs.h>
 #include "netjet.h"
 
-const char *NETjet_S_revision = "$Revision: 2.7.6.6 $";
+const char *NETjet_S_revision = "$Revision: 2.13.2.4 $";
+
+static u_char dummyrr(struct IsdnCardState *cs, int chan, u_char off)
+{
+	return(5);
+}
+
+static void dummywr(struct IsdnCardState *cs, int chan, u_char off, u_char value)
+{
+}
 
 static irqreturn_t
-nj_s_interrupt(int intno, void *dev_id, struct pt_regs *regs)
+netjet_s_interrupt(int intno, void *dev_id, struct pt_regs *regs)
 {
 	struct IsdnCardState *cs = dev_id;
-	u8 val, sval;
+	u_char val, s1val, s0val;
+	u_long flags;
 
-	spin_lock(&cs->lock);
-	if (!((sval = bytein(cs->hw.njet.base + NETJET_IRQSTAT1)) &
-		NETJET_ISACIRQ)) {
+	spin_lock_irqsave(&cs->lock, flags);
+	s1val = bytein(cs->hw.njet.base + NETJET_IRQSTAT1);
+	if (!(s1val & NETJET_ISACIRQ)) {
 		val = NETjet_ReadIC(cs, ISAC_ISTA);
 		if (cs->debug & L1_DEB_ISAC)
-			debugl1(cs, "tiger: i1 %x %x", sval, val);
+			debugl1(cs, "tiger: i1 %x %x", s1val, val);
 		if (val) {
 			isac_interrupt(cs, val);
 			NETjet_WriteIC(cs, ISAC_MASK, 0xFF);
 			NETjet_WriteIC(cs, ISAC_MASK, 0x0);
 		}
-	}
+		s1val = 1;
+	} else
+		s1val = 0;
+	/* 
+	 * read/write stat0 is better, because lower IRQ rate
+	 * Note the IRQ is on for 125 us if a condition match
+	 * thats long on modern CPU and so the IRQ is reentered
+	 * all the time.
+	 */
+	s0val = bytein(cs->hw.njet.base + NETJET_IRQSTAT0);
+	if ((s0val | s1val)==0) { // shared IRQ
+		spin_unlock_irqrestore(&cs->lock, flags);
+		return IRQ_NONE;
+	} 
+	if (s0val)
+		byteout(cs->hw.njet.base + NETJET_IRQSTAT0, s0val);
 	/* start new code 13/07/00 GE */
 	/* set bits in sval to indicate which page is free */
 	if (inl(cs->hw.njet.base + NETJET_DMA_WRITE_ADR) <
 		inl(cs->hw.njet.base + NETJET_DMA_WRITE_IRQ))
 		/* the 2nd write page is free */
-		sval = 0x08;
+		s0val = 0x08;
 	else	/* the 1st write page is free */
-		sval = 0x04;	
+		s0val = 0x04;	
 	if (inl(cs->hw.njet.base + NETJET_DMA_READ_ADR) <
 		inl(cs->hw.njet.base + NETJET_DMA_READ_IRQ))
 		/* the 2nd read page is free */
-		sval = sval | 0x02;
+		s0val |= 0x02;
 	else	/* the 1st read page is free */
-		sval = sval | 0x01;	
-	if (sval != cs->hw.njet.last_is0) /* we have a DMA interrupt */
+		s0val |= 0x01;	
+	if (s0val != cs->hw.njet.last_is0) /* we have a DMA interrupt */
 	{
-		cs->hw.njet.irqstat0 = sval;
+		if (test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) {
+			printk(KERN_WARNING "nj LOCK_ATOMIC s0val %x->%x\n",
+				cs->hw.njet.last_is0, s0val);
+			spin_unlock_irqrestore(&cs->lock, flags);
+			return IRQ_HANDLED;;
+		}
+		cs->hw.njet.irqstat0 = s0val;
 		if ((cs->hw.njet.irqstat0 & NETJET_IRQM0_READ) != 
 			(cs->hw.njet.last_is0 & NETJET_IRQM0_READ))
 			/* we have a read dma int */
@@ -61,112 +92,58 @@ nj_s_interrupt(int intno, void *dev_id, 
 			/* we have a write dma int */
 			write_tiger(cs);
 		/* end new code 13/07/00 GE */
+		test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);
 	}
-/*	if (!testcnt--) {
-		cs->hw.njet.dmactrl = 0;
-		byteout(cs->hw.njet.base + NETJET_DMACTRL,
-			cs->hw.njet.dmactrl);
-		byteout(cs->hw.njet.base + NETJET_IRQMASK0, 0);
-	}
-*/
-	spin_unlock(&cs->lock);
+	spin_unlock_irqrestore(&cs->lock, flags);
 	return IRQ_HANDLED;
 }
 
-static int
-nj_s_reset(struct IsdnCardState *cs)
+static void
+reset_netjet_s(struct IsdnCardState *cs)
 {
 	cs->hw.njet.ctrl_reg = 0xff;  /* Reset On */
 	byteout(cs->hw.njet.base + NETJET_CTRL, cs->hw.njet.ctrl_reg);
-	set_current_state(TASK_UNINTERRUPTIBLE);
-	schedule_timeout((10*HZ)/1000);	/* Timeout 10ms */
-	cs->hw.njet.ctrl_reg = 0x40;  /* Reset Off and status read clear */
+	mdelay(10);
+	cs->hw.njet.ctrl_reg = 0x00;  /* Reset Off and status read clear */
 	/* now edge triggered for TJ320 GE 13/07/00 */
+	/* see comment in IRQ function */
 	byteout(cs->hw.njet.base + NETJET_CTRL, cs->hw.njet.ctrl_reg);
-	set_current_state(TASK_UNINTERRUPTIBLE);
-	schedule_timeout((10*HZ)/1000);	/* Timeout 10ms */
+	mdelay(10);
 	cs->hw.njet.auxd = 0;
 	cs->hw.njet.dmactrl = 0;
 	byteout(cs->hw.njet.base + NETJET_AUXCTRL, ~NETJET_ISACIRQ);
 	byteout(cs->hw.njet.base + NETJET_IRQMASK1, NETJET_ISACIRQ);
 	byteout(cs->hw.njet.auxa, cs->hw.njet.auxd);
-	return 0;
 }
 
-static void
-nj_s_init(struct IsdnCardState *cs)
-{
-	inittiger(cs);
-	initisac(cs);
-}
-
-static struct card_ops nj_s_ops = {
-	.init     = nj_s_init,
-	.reset    = nj_s_reset,
-	.release  = netjet_release,
-	.irq_func = nj_s_interrupt,
-};
-
-static int __init
-nj_s_probe(struct IsdnCardState *cs, struct pci_dev *pdev)
+static int
+NETjet_S_card_msg(struct IsdnCardState *cs, int mt, void *arg)
 {
-	if (pci_enable_device(pdev))
-		goto err;
-			
-	pci_set_master(pdev);
+	u_long flags;
 
-	cs->irq = pdev->irq;
-	cs->irq_flags |= SA_SHIRQ;
-	cs->hw.njet.pdev = pdev;
-	cs->hw.njet.base = pci_resource_start(pdev, 0);
-	if (!request_io(&cs->rs, cs->hw.njet.base, 0x100, "netjet-s isdn"))
-		return 0;
-	
-	cs->hw.njet.auxa = cs->hw.njet.base + NETJET_AUXDATA;
-	cs->hw.njet.isac = cs->hw.njet.base | NETJET_ISAC_OFF;
-	
-	cs->hw.njet.ctrl_reg = 0xff;  /* Reset On */
-	byteout(cs->hw.njet.base + NETJET_CTRL, cs->hw.njet.ctrl_reg);
-
-	set_current_state(TASK_UNINTERRUPTIBLE);
-	schedule_timeout((10*HZ)/1000);	/* Timeout 10ms */
-	
-	cs->hw.njet.ctrl_reg = 0x00;  /* Reset Off and status read clear */
-	byteout(cs->hw.njet.base + NETJET_CTRL, cs->hw.njet.ctrl_reg);
-	
-	set_current_state(TASK_UNINTERRUPTIBLE);
-	schedule_timeout((10*HZ)/1000);	/* Timeout 10ms */
-	
-	cs->hw.njet.auxd = 0xC0;
-	cs->hw.njet.dmactrl = 0;
-	
-	byteout(cs->hw.njet.auxa, 0);
-	byteout(cs->hw.njet.base + NETJET_AUXCTRL, ~NETJET_ISACIRQ);
-	byteout(cs->hw.njet.base + NETJET_IRQMASK1, NETJET_ISACIRQ);
-	byteout(cs->hw.njet.auxa, cs->hw.njet.auxd);
-
-	switch ((NETjet_ReadIC(cs, ISAC_RBCH) >> 5) & 3) {
-	case 0 :
-		break;
-	case 3 :
-		printk(KERN_WARNING "NETjet-S: NETspider-U PCI card found\n" );
-		goto err;
-	default :
-		printk(KERN_WARNING "NETjet-S: No PCI card found\n" );
-		goto err;
+	switch (mt) {
+		case CARD_RESET:
+			spin_lock_irqsave(&cs->lock, flags);
+			reset_netjet_s(cs);
+			spin_unlock_irqrestore(&cs->lock, flags);
+			return(0);
+		case CARD_RELEASE:
+			release_io_netjet(cs);
+			return(0);
+		case CARD_INIT:
+			reset_netjet_s(cs);
+			inittiger(cs);
+			spin_lock_irqsave(&cs->lock, flags);
+			clear_pending_isac_ints(cs);
+			initisac(cs);
+			/* Reenable all IRQ */
+			cs->writeisac(cs, ISAC_MASK, 0);
+			spin_unlock_irqrestore(&cs->lock, flags);
+			return(0);
+		case CARD_TEST:
+			return(0);
 	}
-	printk(KERN_INFO
-		"NETjet-S: PCI card configured at %#lx IRQ %d\n",
-		cs->hw.njet.base, cs->irq);
-	
-	nj_s_reset(cs);
-	cs->irq_flags |= SA_SHIRQ;
-	cs->card_ops = &nj_s_ops;
-	isac_setup(cs, &netjet_dc_ops);
-	return 0;
- err:
-	hisax_release_resources(cs);
-	return -EBUSY;
+	return(0);
 }
 
 static struct pci_dev *dev_netjet __initdata = NULL;
@@ -174,32 +151,116 @@ static struct pci_dev *dev_netjet __init
 int __init
 setup_netjet_s(struct IsdnCard *card)
 {
+	int bytecnt;
+	struct IsdnCardState *cs = card->cs;
 	char tmp[64];
 
 #ifdef __BIG_ENDIAN
 #error "not running on big endian machines now"
 #endif
 	strcpy(tmp, NETjet_S_revision);
-	printk(KERN_INFO "HiSax: Traverse Tech. NETjet-S driver Rev. %s\n",
-	       HiSax_getrev(tmp));
+	printk(KERN_INFO "HiSax: Traverse Tech. NETjet-S driver Rev. %s\n", HiSax_getrev(tmp));
+	if (cs->typ != ISDN_CTYPE_NETJET_S)
+		return(0);
+	test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);
+
+#if CONFIG_PCI
 
-	dev_netjet = pci_find_device(PCI_VENDOR_ID_TIGERJET,
-				     PCI_DEVICE_ID_TIGERJET_300, dev_netjet);
-	if (dev_netjet) {
-		/* 2001/10/04 Christoph Ersfeld, Formula-n Europe AG www.formula-n.com */
-		if (dev_netjet->subsystem_vendor == 0x55 &&
-		    dev_netjet->subsystem_device == 0x02) {
-			printk(KERN_WARNING "Netjet: You tried to load this "
-			       "driver with an incompatible TigerJet-card\n");
-			printk(KERN_WARNING "Use type=41 for Formula-n "
-			       "enter:now ISDN PCI and compatible\n");
-			return 0;
+	for ( ;; )
+	{
+		if ((dev_netjet = pci_find_device(PCI_VENDOR_ID_TIGERJET,
+			PCI_DEVICE_ID_TIGERJET_300,  dev_netjet))) {
+			if (pci_enable_device(dev_netjet))
+				return(0);
+			pci_set_master(dev_netjet);
+			cs->irq = dev_netjet->irq;
+			if (!cs->irq) {
+				printk(KERN_WARNING "NETjet-S: No IRQ for PCI card found\n");
+				return(0);
+			}
+			cs->hw.njet.base = pci_resource_start(dev_netjet, 0);
+			if (!cs->hw.njet.base) {
+				printk(KERN_WARNING "NETjet-S: No IO-Adr for PCI card found\n");
+				return(0);
+			}
+			/* 2001/10/04 Christoph Ersfeld, Formula-n Europe AG www.formula-n.com */
+			if ((dev_netjet->subsystem_vendor == 0x55) &&
+				(dev_netjet->subsystem_device == 0x02)) {
+				printk(KERN_WARNING "Netjet: You tried to load this driver with an incompatible TigerJet-card\n");
+				printk(KERN_WARNING "Use type=41 for Formula-n enter:now ISDN PCI and compatible\n");
+				return(0);
+			}
+			/* end new code */
+		} else {
+			printk(KERN_WARNING "NETjet-S: No PCI card found\n");
+			return(0);
 		}
-		if (nj_s_probe(card->cs, dev_netjet))
-			return 1;
-		return 0;
+
+		cs->hw.njet.auxa = cs->hw.njet.base + NETJET_AUXDATA;
+		cs->hw.njet.isac = cs->hw.njet.base | NETJET_ISAC_OFF;
+
+		cs->hw.njet.ctrl_reg = 0xff;  /* Reset On */
+		byteout(cs->hw.njet.base + NETJET_CTRL, cs->hw.njet.ctrl_reg);
+		mdelay(10);
+
+		cs->hw.njet.ctrl_reg = 0x00;  /* Reset Off and status read clear */
+		byteout(cs->hw.njet.base + NETJET_CTRL, cs->hw.njet.ctrl_reg);
+		mdelay(10);
+
+		cs->hw.njet.auxd = 0xC0;
+		cs->hw.njet.dmactrl = 0;
+
+		byteout(cs->hw.njet.base + NETJET_AUXCTRL, ~NETJET_ISACIRQ);
+		byteout(cs->hw.njet.base + NETJET_IRQMASK1, NETJET_ISACIRQ);
+		byteout(cs->hw.njet.auxa, cs->hw.njet.auxd);
+
+		switch ( ( ( NETjet_ReadIC( cs, ISAC_RBCH ) >> 5 ) & 3 ) )
+		{
+			case 0 :
+				break;
+
+			case 3 :
+				printk( KERN_WARNING "NETjet-S: NETspider-U PCI card found\n" );
+				continue;
+
+			default :
+				printk( KERN_WARNING "NETjet-S: No PCI card found\n" );
+				return 0;
+                }
+                break;
 	}
-	printk(KERN_WARNING "NETjet-S: No PCI card found\n");
-	return 0;
-}
+#else
+
+	printk(KERN_WARNING "NETjet-S: NO_PCI_BIOS\n");
+	printk(KERN_WARNING "NETjet-S: unable to config NETJET-S PCI\n");
+	return (0);
+
+#endif /* CONFIG_PCI */
+
+	bytecnt = 256;
 
+	printk(KERN_INFO
+		"NETjet-S: PCI card configured at %#lx IRQ %d\n",
+		cs->hw.njet.base, cs->irq);
+	if (!request_region(cs->hw.njet.base, bytecnt, "netjet-s isdn")) {
+		printk(KERN_WARNING
+		       "HiSax: %s config port %#lx-%#lx already in use\n",
+		       CardType[card->typ],
+		       cs->hw.njet.base,
+		       cs->hw.njet.base + bytecnt);
+		return (0);
+	}
+	cs->readisac  = &NETjet_ReadIC;
+	cs->writeisac = &NETjet_WriteIC;
+	cs->readisacfifo  = &NETjet_ReadICfifo;
+	cs->writeisacfifo = &NETjet_WriteICfifo;
+	cs->BC_Read_Reg  = &dummyrr;
+	cs->BC_Write_Reg = &dummywr;
+	cs->BC_Send_Data = &netjet_fill_dma;
+	setup_isac(cs);
+	cs->cardmsg = &NETjet_S_card_msg;
+	cs->irq_func = &netjet_s_interrupt;
+	cs->irq_flags |= SA_SHIRQ;
+	ISACVersion(cs, "NETjet-S:");
+	return (1);
+}
--- diff/drivers/isdn/hisax/nj_u.c	2003-05-21 11:50:15.000000000 +0100
+++ source/drivers/isdn/hisax/nj_u.c	2004-02-23 13:56:42.000000000 +0000
@@ -1,4 +1,4 @@
-/* $Id: nj_u.c,v 2.8.6.6 2001/09/23 22:24:50 kai Exp $ 
+/* $Id: nj_u.c,v 2.14.2.3 2004/01/13 14:31:26 keil Exp $ 
  *
  * This software may be used and distributed according to the terms
  * of the GNU General Public License, incorporated herein by reference.
@@ -15,15 +15,25 @@
 #include <linux/ppp_defs.h>
 #include "netjet.h"
 
-const char *NETjet_U_revision = "$Revision: 2.8.6.6 $";
+const char *NETjet_U_revision = "$Revision: 2.14.2.3 $";
+
+static u_char dummyrr(struct IsdnCardState *cs, int chan, u_char off)
+{
+	return(5);
+}
+
+static void dummywr(struct IsdnCardState *cs, int chan, u_char off, u_char value)
+{
+}
 
 static irqreturn_t
-nj_u_interrupt(int intno, void *dev_id, struct pt_regs *regs)
+netjet_u_interrupt(int intno, void *dev_id, struct pt_regs *regs)
 {
 	struct IsdnCardState *cs = dev_id;
-	u8 val, sval;
+	u_char val, sval;
+	u_long flags;
 
-	spin_lock(&cs->lock);
+	spin_lock_irqsave(&cs->lock, flags);
 	if (!((sval = bytein(cs->hw.njet.base + NETJET_IRQSTAT1)) &
 		NETJET_ISACIRQ)) {
 		val = NETjet_ReadIC(cs, ICC_ISTA);
@@ -51,6 +61,10 @@ nj_u_interrupt(int intno, void *dev_id, 
 		sval = sval | 0x01;	
 	if (sval != cs->hw.njet.last_is0) /* we have a DMA interrupt */
 	{
+		if (test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) {
+			spin_unlock_irqrestore(&cs->lock, flags);
+			return IRQ_HANDLED;
+		}
 		cs->hw.njet.irqstat0 = sval;
 		if ((cs->hw.njet.irqstat0 & NETJET_IRQM0_READ) != 
 			(cs->hw.njet.last_is0 & NETJET_IRQM0_READ))
@@ -61,113 +75,58 @@ nj_u_interrupt(int intno, void *dev_id, 
 			/* we have a write dma int */
 			write_tiger(cs);
 		/* end new code 13/07/00 GE */
+		test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);
 	}
-/*	if (!testcnt--) {
-		cs->hw.njet.dmactrl = 0;
-		byteout(cs->hw.njet.base + NETJET_DMACTRL,
-			cs->hw.njet.dmactrl);
-		byteout(cs->hw.njet.base + NETJET_IRQMASK0, 0);
-	}
-*/
-	spin_unlock(&cs->lock);
+	spin_unlock_irqrestore(&cs->lock, flags);
 	return IRQ_HANDLED;
 }
 
-static int
-nj_u_reset(struct IsdnCardState *cs)
+static void
+reset_netjet_u(struct IsdnCardState *cs)
 {
 	cs->hw.njet.ctrl_reg = 0xff;  /* Reset On */
 	byteout(cs->hw.njet.base + NETJET_CTRL, cs->hw.njet.ctrl_reg);
-	set_current_state(TASK_UNINTERRUPTIBLE);
-	schedule_timeout((10*HZ)/1000);	/* Timeout 10ms */
+	mdelay(10);
 	cs->hw.njet.ctrl_reg = 0x40;  /* Reset Off and status read clear */
 	/* now edge triggered for TJ320 GE 13/07/00 */
 	byteout(cs->hw.njet.base + NETJET_CTRL, cs->hw.njet.ctrl_reg);
-	set_current_state(TASK_UNINTERRUPTIBLE);
-	schedule_timeout((10*HZ)/1000);	/* Timeout 10ms */
-
+	mdelay(10);
 	cs->hw.njet.auxd = 0xC0;
 	cs->hw.njet.dmactrl = 0;
 	byteout(cs->hw.njet.auxa, 0);
 	byteout(cs->hw.njet.base + NETJET_AUXCTRL, ~NETJET_ISACIRQ);
 	byteout(cs->hw.njet.base + NETJET_IRQMASK1, NETJET_ISACIRQ);
 	byteout(cs->hw.njet.auxa, cs->hw.njet.auxd);
-	return 0;
 }
 
-static void
-nj_u_init(struct IsdnCardState *cs)
+static int
+NETjet_U_card_msg(struct IsdnCardState *cs, int mt, void *arg)
 {
-	inittiger(cs);
-	initicc(cs);
-	/* Reenable all IRQ */
-	NETjet_WriteIC(cs, ICC_MASK, 0);
-}
-
-static struct card_ops nj_u_ops = {
-	.init     = nj_u_init,
-	.reset    = nj_u_reset,
-	.release  = netjet_release,
-	.irq_func = nj_u_interrupt,
-};
-
-static int __init
-nj_u_probe(struct IsdnCardState *cs, struct pci_dev *pdev)
-{
-	if (pci_enable_device(pdev))
-		goto err;
-			
-	pci_set_master(pdev);
-
-	cs->irq = pdev->irq;
-	cs->irq_flags |= SA_SHIRQ;
-	cs->hw.njet.pdev = pdev;
-	cs->hw.njet.base = pci_resource_start(pdev, 0);
-	if (!request_io(&cs->rs, cs->hw.njet.base, 0x100, "netspider-u isdn"))
-		goto err;
-	
-	cs->hw.njet.auxa = cs->hw.njet.base + NETJET_AUXDATA;
-	cs->hw.njet.isac = cs->hw.njet.base | NETJET_ISAC_OFF;
-
-	cs->hw.njet.ctrl_reg = 0xff;  /* Reset On */
-	byteout(cs->hw.njet.base + NETJET_CTRL, cs->hw.njet.ctrl_reg);
-	
-	set_current_state(TASK_UNINTERRUPTIBLE);
-	schedule_timeout((10*HZ)/1000);	/* Timeout 10ms */
-	
-	cs->hw.njet.ctrl_reg = 0x00;  /* Reset Off and status read clear */
-	byteout(cs->hw.njet.base + NETJET_CTRL, cs->hw.njet.ctrl_reg);
-	
-	set_current_state(TASK_UNINTERRUPTIBLE);
-	schedule_timeout((10*HZ)/1000);	/* Timeout 10ms */
-	
-	cs->hw.njet.auxd = 0xC0;
-	cs->hw.njet.dmactrl = 0;
-	
-	byteout(cs->hw.njet.base + NETJET_AUXCTRL, ~NETJET_ISACIRQ);
-	byteout(cs->hw.njet.base + NETJET_IRQMASK1, NETJET_ISACIRQ);
-	byteout(cs->hw.njet.auxa, cs->hw.njet.auxd);
+	u_long flags;
 
-	switch ((NETjet_ReadIC(cs, ICC_RBCH) >> 5) & 3)	{
-	case 3:
-		break;
-	case 0:
-		printk(KERN_WARNING "NETspider-U: NETjet-S PCI card found\n" );
-		goto err;
-	default:
-		printk(KERN_WARNING "NETspider-U: No PCI card found\n" );
-		goto err;
+	switch (mt) {
+		case CARD_RESET:
+			spin_lock_irqsave(&cs->lock, flags);
+			reset_netjet_u(cs);
+			spin_unlock_irqrestore(&cs->lock, flags);
+			return(0);
+		case CARD_RELEASE:
+			release_io_netjet(cs);
+			return(0);
+		case CARD_INIT:
+			spin_lock_irqsave(&cs->lock, flags);
+			inittiger(cs);
+			reset_netjet_u(cs);
+			clear_pending_icc_ints(cs);
+			initicc(cs);
+			/* Reenable all IRQ */
+			cs->writeisac(cs, ICC_MASK, 0);
+			spin_unlock_irqrestore(&cs->lock, flags);
+			return(0);
+		case CARD_TEST:
+			return(0);
 	}
-	printk(KERN_INFO "NETspider-U: PCI card configured at %#lx IRQ %d\n",
-	       cs->hw.njet.base, cs->irq);
-
-	nj_u_reset(cs);
-	cs->card_ops = &nj_u_ops;
-	icc_setup(cs, &netjet_dc_ops);
-	return 0;
- err:
-	hisax_release_resources(cs);
-	return -EBUSY;
+	return(0);
 }
 
 static struct pci_dev *dev_netjet __initdata = NULL;
@@ -175,21 +134,111 @@ static struct pci_dev *dev_netjet __init
 int __init
 setup_netjet_u(struct IsdnCard *card)
 {
+	int bytecnt;
+	struct IsdnCardState *cs = card->cs;
 	char tmp[64];
+#if CONFIG_PCI
+#endif
 #ifdef __BIG_ENDIAN
 #error "not running on big endian machines now"
 #endif
 	strcpy(tmp, NETjet_U_revision);
-	printk(KERN_INFO "HiSax: Traverse Tech. NETspider-U driver Rev. %s\n",
-	       HiSax_getrev(tmp));
-	
-	dev_netjet = pci_find_device(PCI_VENDOR_ID_TIGERJET,
-				     PCI_DEVICE_ID_TIGERJET_300, dev_netjet);
-	if (dev_netjet) {
-		if (nj_u_probe(card->cs, dev_netjet))
-			return 1;
-		return 0;
+	printk(KERN_INFO "HiSax: Traverse Tech. NETspider-U driver Rev. %s\n", HiSax_getrev(tmp));
+	if (cs->typ != ISDN_CTYPE_NETJET_U)
+		return(0);
+	test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);
+
+#if CONFIG_PCI
+
+	for ( ;; )
+	{
+		if ((dev_netjet = pci_find_device(PCI_VENDOR_ID_TIGERJET,
+			PCI_DEVICE_ID_TIGERJET_300,  dev_netjet))) {
+			if (pci_enable_device(dev_netjet))
+				return(0);
+			pci_set_master(dev_netjet);
+			cs->irq = dev_netjet->irq;
+			if (!cs->irq) {
+				printk(KERN_WARNING "NETspider-U: No IRQ for PCI card found\n");
+				return(0);
+			}
+			cs->hw.njet.base = pci_resource_start(dev_netjet, 0);
+			if (!cs->hw.njet.base) {
+				printk(KERN_WARNING "NETspider-U: No IO-Adr for PCI card found\n");
+				return(0);
+			}
+		} else {
+			printk(KERN_WARNING "NETspider-U: No PCI card found\n");
+			return(0);
+		}
+
+		cs->hw.njet.auxa = cs->hw.njet.base + NETJET_AUXDATA;
+		cs->hw.njet.isac = cs->hw.njet.base | NETJET_ISAC_OFF;
+		mdelay(10);
+
+		cs->hw.njet.ctrl_reg = 0xff;  /* Reset On */
+		byteout(cs->hw.njet.base + NETJET_CTRL, cs->hw.njet.ctrl_reg);
+		mdelay(10);
+
+		cs->hw.njet.ctrl_reg = 0x00;  /* Reset Off and status read clear */
+		byteout(cs->hw.njet.base + NETJET_CTRL, cs->hw.njet.ctrl_reg);
+		mdelay(10);
+
+		cs->hw.njet.auxd = 0xC0;
+		cs->hw.njet.dmactrl = 0;
+
+		byteout(cs->hw.njet.auxa, 0);
+		byteout(cs->hw.njet.base + NETJET_AUXCTRL, ~NETJET_ISACIRQ);
+		byteout(cs->hw.njet.base + NETJET_IRQMASK1, NETJET_ISACIRQ);
+		byteout(cs->hw.njet.auxa, cs->hw.njet.auxd);
+
+		switch ( ( ( NETjet_ReadIC( cs, ICC_RBCH ) >> 5 ) & 3 ) )
+		{
+			case 3 :
+				break;
+
+			case 0 :
+				printk( KERN_WARNING "NETspider-U: NETjet-S PCI card found\n" );
+				continue;
+
+			default :
+				printk( KERN_WARNING "NETspider-U: No PCI card found\n" );
+				return 0;
+                }
+                break;
+	}
+#else
+
+	printk(KERN_WARNING "NETspider-U: NO_PCI_BIOS\n");
+	printk(KERN_WARNING "NETspider-U: unable to config NETspider-U PCI\n");
+	return (0);
+
+#endif /* CONFIG_PCI */
+
+	bytecnt = 256;
+
+	printk(KERN_INFO
+		"NETspider-U: PCI card configured at %#lx IRQ %d\n",
+		cs->hw.njet.base, cs->irq);
+	if (!request_region(cs->hw.njet.base, bytecnt, "netspider-u isdn")) {
+		printk(KERN_WARNING
+		       "HiSax: %s config port %#lx-%#lx already in use\n",
+		       CardType[card->typ],
+		       cs->hw.njet.base,
+		       cs->hw.njet.base + bytecnt);
+		return (0);
 	}
-	printk(KERN_WARNING "NETspider-U: No PCI card found\n");
-	return 0;
+	setup_icc(cs);
+	cs->readisac  = &NETjet_ReadIC;
+	cs->writeisac = &NETjet_WriteIC;
+	cs->readisacfifo  = &NETjet_ReadICfifo;
+	cs->writeisacfifo = &NETjet_WriteICfifo;
+	cs->BC_Read_Reg  = &dummyrr;
+	cs->BC_Write_Reg = &dummywr;
+	cs->BC_Send_Data = &netjet_fill_dma;
+	cs->cardmsg = &NETjet_U_card_msg;
+	cs->irq_func = &netjet_u_interrupt;
+	cs->irq_flags |= SA_SHIRQ;
+	ICCVersion(cs, "NETspider-U:");
+	return (1);
 }
--- diff/drivers/isdn/hisax/q931.c	2003-09-17 12:28:06.000000000 +0100
+++ source/drivers/isdn/hisax/q931.c	2004-02-23 13:56:42.000000000 +0000
@@ -1,4 +1,4 @@
-/* $Id: q931.c,v 1.10.6.3 2001/09/23 22:24:50 kai Exp $
+/* $Id: q931.c,v 1.12.2.3 2004/01/13 14:31:26 keil Exp $
  *
  * code to decode ITU Q.931 call control messages
  *
@@ -21,9 +21,9 @@
 #include "l3_1tr6.h"
 
 void
-iecpy(u8 * dest, u8 * iestart, int ieoffset)
+iecpy(u_char * dest, u_char * iestart, int ieoffset)
 {
-	u8 *p;
+	u_char *p;
 	int l;
 
 	p = iestart + ieoffset + 2;
@@ -38,7 +38,7 @@ iecpy(u8 * dest, u8 * iestart, int ieoff
  */
 static
 struct MessageType {
-	u8 nr;
+	u_char nr;
 	char *descr;
 } mtlist[] = {
 
@@ -198,7 +198,7 @@ struct MessageType mt_n1[] =
 
 
 static int
-prbits(char *dest, u8 b, int start, int len)
+prbits(char *dest, u_char b, int start, int len)
 {
 	char *dp = dest;
 
@@ -214,8 +214,8 @@ prbits(char *dest, u8 b, int start, int 
 }
 
 static
-u8 *
-skipext(u8 * p)
+u_char *
+skipext(u_char * p)
 {
 	while (!(*p++ & 0x80));
 	return (p);
@@ -230,7 +230,7 @@ skipext(u8 * p)
 
 static
 struct CauseValue {
-	u8 nr;
+	u_char nr;
 	char *edescr;
 	char *ddescr;
 } cvlist[] = {
@@ -442,11 +442,11 @@ struct CauseValue {
 
 static
 int
-prcause(char *dest, u8 * p)
+prcause(char *dest, u_char * p)
 {
-	u8 *end;
+	u_char *end;
 	char *dp = dest;
-	u_int i, cause;
+	int i, cause;
 
 	end = p + p[1] + 1;
 	p += 2;
@@ -519,7 +519,7 @@ struct MessageType cause_1tr6[] =
 int cause_1tr6_len = (sizeof(cause_1tr6) / sizeof(struct MessageType));
 
 static int
-prcause_1tr6(char *dest, u8 * p)
+prcause_1tr6(char *dest, u_char * p)
 {
 	char *dp = dest;
 	int i, cause;
@@ -554,7 +554,7 @@ prcause_1tr6(char *dest, u8 * p)
 }
 
 static int
-prchident(char *dest, u8 * p)
+prchident(char *dest, u_char * p)
 {
 	char *dp = dest;
 
@@ -566,7 +566,7 @@ prchident(char *dest, u8 * p)
 }
 
 static int
-prcalled(char *dest, u8 * p)
+prcalled(char *dest, u_char * p)
 {
 	int l;
 	char *dp = dest;
@@ -583,7 +583,7 @@ prcalled(char *dest, u8 * p)
 	return (dp - dest);
 }
 static int
-prcalling(char *dest, u8 * p)
+prcalling(char *dest, u_char * p)
 {
 	int l;
 	char *dp = dest;
@@ -610,7 +610,7 @@ prcalling(char *dest, u8 * p)
 
 static
 int
-prbearer(char *dest, u8 * p)
+prbearer(char *dest, u_char * p)
 {
 	char *dp = dest, ch;
 
@@ -658,10 +658,10 @@ prbearer(char *dest, u8 * p)
 
 static
 int
-prbearer_ni1(char *dest, u8 * p)
+prbearer_ni1(char *dest, u_char * p)
 {
 	char *dp = dest;
-	u8 len;
+	u_char len;
 
 	p++;
 	len = *p++;
@@ -715,7 +715,7 @@ prbearer_ni1(char *dest, u8 * p)
 }
 
 static int
-general(char *dest, u8 * p)
+general(char *dest, u_char * p)
 {
 	char *dp = dest;
 	char ch = ' ';
@@ -742,7 +742,7 @@ general(char *dest, u8 * p)
 }
 
 static int
-general_ni1(char *dest, u8 * p)
+general_ni1(char *dest, u_char * p)
 {
 	char *dp = dest;
 	char ch = ' ';
@@ -769,7 +769,7 @@ general_ni1(char *dest, u8 * p)
 }
 
 static int
-prcharge(char *dest, u8 * p)
+prcharge(char *dest, u_char * p)
 {
 	char *dp = dest;
 	int l;
@@ -786,7 +786,7 @@ prcharge(char *dest, u8 * p)
 	return (dp - dest);
 }
 static int
-prtext(char *dest, u8 * p)
+prtext(char *dest, u_char * p)
 {
 	char *dp = dest;
 	int l;
@@ -802,7 +802,7 @@ prtext(char *dest, u8 * p)
 }
 
 static int
-prfeatureind(char *dest, u8 * p)
+prfeatureind(char *dest, u_char * p)
 {
 	char *dp = dest;
 
@@ -839,7 +839,7 @@ prfeatureind(char *dest, u8 * p)
 
 static
 struct DTag { /* Display tags */
-	u8 nr;
+	u_char nr;
 	char *descr;
 } dtaglist[] = {
 	{ 0x82, "Continuation" },
@@ -868,11 +868,10 @@ struct DTag { /* Display tags */
 #define DTAGSIZE sizeof(dtaglist)/sizeof(struct DTag)
 
 static int
-disptext_ni1(char *dest, u8 * p)
+disptext_ni1(char *dest, u_char * p)
 {
 	char *dp = dest;
-	int l, tag, len;
-	u_int i;
+	int l, tag, len, i;
 
 	p++;
 	l = *p++ - 1;
@@ -908,7 +907,7 @@ disptext_ni1(char *dest, u8 * p)
 	return (dp - dest);
 }
 static int
-display(char *dest, u8 * p)
+display(char *dest, u_char * p)
 {
 	char *dp = dest;
 	char ch = ' ';
@@ -937,7 +936,7 @@ display(char *dest, u8 * p)
 }
 
 int
-prfacility(char *dest, u8 * p)
+prfacility(char *dest, u_char * p)
 {
 	char *dp = dest;
 	int l, l2;
@@ -968,9 +967,9 @@ prfacility(char *dest, u8 * p)
 
 static
 struct InformationElement {
-	u8 nr;
+	u_char nr;
 	char *descr;
-	int (*f) (char *, u8 *);
+	int (*f) (char *, u_char *);
 } ielist[] = {
 
 	{
@@ -1149,11 +1148,11 @@ static struct InformationElement we_6[] 
 #define WE_6_LEN (sizeof(we_6) / sizeof(struct InformationElement))
 
 int
-QuickHex(char *txt, u8 * p, int cnt)
+QuickHex(char *txt, u_char * p, int cnt)
 {
 	register int i;
 	register char *t = txt;
-	register u8 w;
+	register u_char w;
 
 	for (i = 0; i < cnt; i++) {
 		*t++ = ' ';
@@ -1173,7 +1172,7 @@ QuickHex(char *txt, u8 * p, int cnt)
 }
 
 void
-LogFrame(struct IsdnCardState *cs, u8 * buf, int size)
+LogFrame(struct IsdnCardState *cs, u_char * buf, int size)
 {
 	char *dp;
 
@@ -1197,11 +1196,11 @@ LogFrame(struct IsdnCardState *cs, u8 * 
 void
 dlogframe(struct IsdnCardState *cs, struct sk_buff *skb, int dir)
 {
-	u8 *bend, *buf;
+	u_char *bend, *buf;
 	char *dp;
 	unsigned char pd, cr_l, cr, mt;
 	unsigned char sapi, tei, ftyp;
-	u_int i, cset = 0, cs_old = 0, cs_fest = 0;
+	int i, cset = 0, cs_old = 0, cs_fest = 0;
 	int size, finish = 0;
 
 	if (skb->len < 3)
--- diff/drivers/isdn/hisax/s0box.c	2003-05-21 11:49:50.000000000 +0100
+++ source/drivers/isdn/hisax/s0box.c	2004-02-23 13:56:42.000000000 +0000
@@ -1,4 +1,4 @@
-/* $Id: s0box.c,v 2.4.6.2 2001/09/23 22:24:51 kai Exp $
+/* $Id: s0box.c,v 2.6.2.4 2004/01/13 23:48:39 keil Exp $
  *
  * low level stuff for Creatix S0BOX
  *
@@ -17,16 +17,10 @@
 #include "isdnl1.h"
 
 extern const char *CardType[];
-const char *s0box_revision = "$Revision: 2.4.6.2 $";
-static spinlock_t s0box_lock = SPIN_LOCK_UNLOCKED;
+const char *s0box_revision = "$Revision: 2.6.2.4 $";
 
 static inline void
-writereg(struct IsdnCardState *cs, int addr, u8 off, u8 val)
-{
-	unsigned long flags;
-	unsigned long padr = cs->hw.teles3.cfg_reg;
-
-	spin_lock_irqsave(&s0box_lock, flags);
+writereg(unsigned int padr, signed int addr, u_char off, u_char val) {
 	outb_p(0x1c,padr+2);
 	outb_p(0x14,padr+2);
 	outb_p((addr+off)&0x7f,padr);
@@ -35,21 +29,16 @@ writereg(struct IsdnCardState *cs, int a
 	outb_p(0x17,padr+2);
 	outb_p(0x14,padr+2);
 	outb_p(0x1c,padr+2);
-	spin_unlock_irqrestore(&s0box_lock, flags);
 }
 
-static u8 nibtab[] = { 1, 9, 5, 0xd, 3, 0xb, 7, 0xf,
+static u_char nibtab[] = { 1, 9, 5, 0xd, 3, 0xb, 7, 0xf,
 			 0, 0, 0, 0, 0, 0, 0, 0,
 			 0, 8, 4, 0xc, 2, 0xa, 6, 0xe } ;
 
-static inline u8
-readreg(struct IsdnCardState *cs, int addr, u8 off)
-{
-	u8 n1, n2;
-	unsigned long flags;
-	unsigned long padr = cs->hw.teles3.cfg_reg;
+static inline u_char
+readreg(unsigned int padr, signed int addr, u_char off) {
+	register u_char n1, n2;
 
-	spin_lock_irqsave(&s0box_lock, flags);
 	outb_p(0x1c,padr+2);
 	outb_p(0x14,padr+2);
 	outb_p((addr+off)|0x80,padr);
@@ -60,16 +49,14 @@ readreg(struct IsdnCardState *cs, int ad
 	n2 = (inb_p(padr+1) >> 3) & 0x17;
 	outb_p(0x14,padr+2);
 	outb_p(0x1c,padr+2);
-	spin_unlock_irqrestore(&s0box_lock, flags);
 	return nibtab[n1] | (nibtab[n2] << 4);
 }
 
 static inline void
-read_fifo(struct IsdnCardState *cs, signed int adr, u8 * data, int size)
+read_fifo(unsigned int padr, signed int adr, u_char * data, int size)
 {
 	int i;
-	u8 n1, n2;
-	unsigned long padr = cs->hw.teles3.cfg_reg;
+	register u_char n1, n2;
 	
 	outb_p(0x1c, padr+2);
 	outb_p(0x14, padr+2);
@@ -84,14 +71,13 @@ read_fifo(struct IsdnCardState *cs, sign
 	}
 	outb_p(0x14,padr+2);
 	outb_p(0x1c,padr+2);
+	return;
 }
 
 static inline void
-write_fifo(struct IsdnCardState *cs, signed int adr, u8 * data, int size)
+write_fifo(unsigned int padr, signed int adr, u_char * data, int size)
 {
 	int i;
-	unsigned long padr = cs->hw.teles3.cfg_reg;
-
 	outb_p(0x1c, padr+2);
 	outb_p(0x14, padr+2);
 	outb_p(adr&0x7f, padr);
@@ -102,79 +88,140 @@ write_fifo(struct IsdnCardState *cs, sig
 	}
 	outb_p(0x14,padr+2);
 	outb_p(0x1c,padr+2);
+	return;
 }
 
-static u8
-isac_read(struct IsdnCardState *cs, u8 offset)
+/* Interface functions */
+
+static u_char
+ReadISAC(struct IsdnCardState *cs, u_char offset)
 {
-	return readreg(cs, cs->hw.teles3.isac, offset);
+	return (readreg(cs->hw.teles3.cfg_reg, cs->hw.teles3.isac, offset));
 }
 
 static void
-isac_write(struct IsdnCardState *cs, u8 offset, u8 value)
+WriteISAC(struct IsdnCardState *cs, u_char offset, u_char value)
 {
-	writereg(cs, cs->hw.teles3.isac, offset, value);
+	writereg(cs->hw.teles3.cfg_reg, cs->hw.teles3.isac, offset, value);
 }
 
 static void
-isac_read_fifo(struct IsdnCardState *cs, u8 * data, int size)
+ReadISACfifo(struct IsdnCardState *cs, u_char * data, int size)
 {
-	read_fifo(cs, cs->hw.teles3.isacfifo, data, size);
+	read_fifo(cs->hw.teles3.cfg_reg, cs->hw.teles3.isacfifo, data, size);
 }
 
 static void
-isac_write_fifo(struct IsdnCardState *cs, u8 * data, int size)
+WriteISACfifo(struct IsdnCardState *cs, u_char * data, int size)
 {
-	write_fifo(cs, cs->hw.teles3.isacfifo, data, size);
+	write_fifo(cs->hw.teles3.cfg_reg, cs->hw.teles3.isacfifo, data, size);
 }
 
-static struct dc_hw_ops isac_ops = {
-	.read_reg   = isac_read,
-	.write_reg  = isac_write,
-	.read_fifo  = isac_read_fifo,
-	.write_fifo = isac_write_fifo,
-};
-
-static u8
-hscx_read(struct IsdnCardState *cs, int hscx, u8 offset)
+static u_char
+ReadHSCX(struct IsdnCardState *cs, int hscx, u_char offset)
 {
-	return readreg(cs, cs->hw.teles3.hscx[hscx], offset);
+	return (readreg(cs->hw.teles3.cfg_reg, cs->hw.teles3.hscx[hscx], offset));
 }
 
 static void
-hscx_write(struct IsdnCardState *cs, int hscx, u8 offset, u8 value)
+WriteHSCX(struct IsdnCardState *cs, int hscx, u_char offset, u_char value)
 {
-	writereg(cs, cs->hw.teles3.hscx[hscx], offset, value);
+	writereg(cs->hw.teles3.cfg_reg, cs->hw.teles3.hscx[hscx], offset, value);
 }
 
-static void
-hscx_read_fifo(struct IsdnCardState *cs, int hscx, u8 *data, int size)
-{
-	read_fifo(cs, cs->hw.teles3.hscxfifo[hscx], data, size);
+/*
+ * fast interrupt HSCX stuff goes here
+ */
+
+#define READHSCX(cs, nr, reg) readreg(cs->hw.teles3.cfg_reg, cs->hw.teles3.hscx[nr], reg)
+#define WRITEHSCX(cs, nr, reg, data) writereg(cs->hw.teles3.cfg_reg, cs->hw.teles3.hscx[nr], reg, data)
+#define READHSCXFIFO(cs, nr, ptr, cnt) read_fifo(cs->hw.teles3.cfg_reg, cs->hw.teles3.hscxfifo[nr], ptr, cnt)
+#define WRITEHSCXFIFO(cs, nr, ptr, cnt) write_fifo(cs->hw.teles3.cfg_reg, cs->hw.teles3.hscxfifo[nr], ptr, cnt)
+
+#include "hscx_irq.c"
+
+static irqreturn_t
+s0box_interrupt(int intno, void *dev_id, struct pt_regs *regs)
+{
+#define MAXCOUNT 5
+	struct IsdnCardState *cs = dev_id;
+	u_char val;
+	u_long flags;
+	int count = 0;
+
+	spin_lock_irqsave(&cs->lock, flags);
+	val = readreg(cs->hw.teles3.cfg_reg, cs->hw.teles3.hscx[1], HSCX_ISTA);
+      Start_HSCX:
+	if (val)
+		hscx_int_main(cs, val);
+	val = readreg(cs->hw.teles3.cfg_reg, cs->hw.teles3.isac, ISAC_ISTA);
+      Start_ISAC:
+	if (val)
+		isac_interrupt(cs, val);
+	count++;
+	val = readreg(cs->hw.teles3.cfg_reg, cs->hw.teles3.hscx[1], HSCX_ISTA);
+	if (val && count < MAXCOUNT) {
+		if (cs->debug & L1_DEB_HSCX)
+			debugl1(cs, "HSCX IntStat after IntRoutine");
+		goto Start_HSCX;
+	}
+	val = readreg(cs->hw.teles3.cfg_reg, cs->hw.teles3.isac, ISAC_ISTA);
+	if (val && count < MAXCOUNT) {
+		if (cs->debug & L1_DEB_ISAC)
+			debugl1(cs, "ISAC IntStat after IntRoutine");
+		goto Start_ISAC;
+	}
+	if (count >= MAXCOUNT)
+		printk(KERN_WARNING "S0Box: more than %d loops in s0box_interrupt\n", count);
+	writereg(cs->hw.teles3.cfg_reg, cs->hw.teles3.hscx[0], HSCX_MASK, 0xFF);
+	writereg(cs->hw.teles3.cfg_reg, cs->hw.teles3.hscx[1], HSCX_MASK, 0xFF);
+	writereg(cs->hw.teles3.cfg_reg, cs->hw.teles3.isac, ISAC_MASK, 0xFF);
+	writereg(cs->hw.teles3.cfg_reg, cs->hw.teles3.isac, ISAC_MASK, 0x0);
+	writereg(cs->hw.teles3.cfg_reg, cs->hw.teles3.hscx[0], HSCX_MASK, 0x0);
+	writereg(cs->hw.teles3.cfg_reg, cs->hw.teles3.hscx[1], HSCX_MASK, 0x0);
+	spin_unlock_irqrestore(&cs->lock, flags);
+	return IRQ_HANDLED;
+}
+
+void
+release_io_s0box(struct IsdnCardState *cs)
+{
+	release_region(cs->hw.teles3.cfg_reg, 8);
+}
+
+static int
+S0Box_card_msg(struct IsdnCardState *cs, int mt, void *arg)
+{
+	u_long flags;
+
+	switch (mt) {
+		case CARD_RESET:
+			break;
+		case CARD_RELEASE:
+			release_io_s0box(cs);
+			break;
+		case CARD_INIT:
+			spin_lock_irqsave(&cs->lock, flags);
+			inithscxisac(cs, 3);
+			spin_unlock_irqrestore(&cs->lock, flags);
+			break;
+		case CARD_TEST:
+			break;
+	}
+	return(0);
 }
 
-static void
-hscx_write_fifo(struct IsdnCardState *cs, int hscx, u8 *data, int size)
+int __init
+setup_s0box(struct IsdnCard *card)
 {
-	write_fifo(cs, cs->hw.teles3.hscxfifo[hscx], data, size);
-}
+	struct IsdnCardState *cs = card->cs;
+	char tmp[64];
 
-static struct bc_hw_ops hscx_ops = {
-	.read_reg   = hscx_read,
-	.write_reg  = hscx_write,
-	.read_fifo  = hscx_read_fifo,
-	.write_fifo = hscx_write_fifo,
-};
- 
-static struct card_ops s0box_ops = {
-	.init     = inithscxisac,
-	.release  = hisax_release_resources,
-	.irq_func = hscxisac_irq,
-};
+	strcpy(tmp, s0box_revision);
+	printk(KERN_INFO "HiSax: S0Box IO driver Rev. %s\n", HiSax_getrev(tmp));
+	if (cs->typ != ISDN_CTYPE_S0BOX)
+		return (0);
 
-static int __init
-s0box_probe(struct IsdnCardState *cs, struct IsdnCard *card)
-{
 	cs->hw.teles3.cfg_reg = card->para[1];
 	cs->hw.teles3.hscx[0] = -0x20;
 	cs->hw.teles3.hscx[1] = 0x0;
@@ -183,32 +230,37 @@ s0box_probe(struct IsdnCardState *cs, st
 	cs->hw.teles3.hscxfifo[0] = cs->hw.teles3.hscx[0] + 0x3e;
 	cs->hw.teles3.hscxfifo[1] = cs->hw.teles3.hscx[1] + 0x3e;
 	cs->irq = card->para[0];
-	if (!request_io(&cs->rs, cs->hw.teles3.cfg_reg, 8, "S0Box parallel I/O"))
-		goto err;
+	if (!request_region(cs->hw.teles3.cfg_reg,8, "S0Box parallel I/O")) {
+		printk(KERN_WARNING
+		       "HiSax: %s ports %x-%x already in use\n",
+		       CardType[cs->typ],
+                       cs->hw.teles3.cfg_reg,
+                       cs->hw.teles3.cfg_reg + 7);
+		return 0;
+	}
 	printk(KERN_INFO
-	       "HiSax: %s config irq:%d isac:0x%x  cfg:0x%x\n",
-	       CardType[cs->typ], cs->irq,
-	       cs->hw.teles3.isac, cs->hw.teles3.cfg_reg);
+		"HiSax: %s config irq:%d isac:0x%x  cfg:0x%x\n",
+		CardType[cs->typ], cs->irq,
+		cs->hw.teles3.isac, cs->hw.teles3.cfg_reg);
 	printk(KERN_INFO
-	       "HiSax: hscx A:0x%x  hscx B:0x%x\n",
-	       cs->hw.teles3.hscx[0], cs->hw.teles3.hscx[1]);
-	cs->card_ops = &s0box_ops;
-	if (hscxisac_setup(cs, &isac_ops, &hscx_ops))
-		goto err;
-	return 0;
- err:
-	hisax_release_resources(cs);
-	return -EBUSY;
-}
-
-int __init
-setup_s0box(struct IsdnCard *card)
-{
-	char tmp[64];
-
-	strcpy(tmp, s0box_revision);
-	printk(KERN_INFO "HiSax: S0Box IO driver Rev. %s\n", HiSax_getrev(tmp));
-	if (s0box_probe(card->cs, card))
-		return 0;
-	return 1;
+		"HiSax: hscx A:0x%x  hscx B:0x%x\n",
+		cs->hw.teles3.hscx[0], cs->hw.teles3.hscx[1]);
+	setup_isac(cs);
+	cs->readisac = &ReadISAC;
+	cs->writeisac = &WriteISAC;
+	cs->readisacfifo = &ReadISACfifo;
+	cs->writeisacfifo = &WriteISACfifo;
+	cs->BC_Read_Reg = &ReadHSCX;
+	cs->BC_Write_Reg = &WriteHSCX;
+	cs->BC_Send_Data = &hscx_fill_fifo;
+	cs->cardmsg = &S0Box_card_msg;
+	cs->irq_func = &s0box_interrupt;
+	ISACVersion(cs, "S0Box:");
+	if (HscxVersion(cs, "S0Box:")) {
+		printk(KERN_WARNING
+		       "S0Box: wrong HSCX versions check IO address\n");
+		release_io_s0box(cs);
+		return (0);
+	}
+	return (1);
 }
--- diff/drivers/isdn/hisax/saphir.c	2003-05-21 11:50:15.000000000 +0100
+++ source/drivers/isdn/hisax/saphir.c	2004-02-23 13:56:42.000000000 +0000
@@ -1,4 +1,4 @@
-/* $Id: saphir.c,v 1.8.6.2 2001/09/23 22:24:51 kai Exp $
+/* $Id: saphir.c,v 1.10.2.4 2004/01/13 23:48:39 keil Exp $
  *
  * low level stuff for HST Saphir 1
  *
@@ -19,8 +19,7 @@
 #include "isdnl1.h"
 
 extern const char *CardType[];
-static char *saphir_rev = "$Revision: 1.8.6.2 $";
-static spinlock_t saphir_lock = SPIN_LOCK_UNLOCKED;
+static char *saphir_rev = "$Revision: 1.10.2.4 $";
 
 #define byteout(addr,val) outb(val,addr)
 #define bytein(addr) inb(addr)
@@ -32,138 +31,160 @@ static spinlock_t saphir_lock = SPIN_LOC
 #define SPARE_REG	4
 #define RESET_REG	5
 
-static inline u8
-readreg(struct IsdnCardState *cs, unsigned int adr, u8 off)
+static inline u_char
+readreg(unsigned int ale, unsigned int adr, u_char off)
 {
-	u8 ret;
-	unsigned long flags;
+	register u_char ret;
 
-	spin_lock_irqsave(&saphir_lock, flags);
-	byteout(cs->hw.saphir.ale, off);
+	byteout(ale, off);
 	ret = bytein(adr);
-	spin_unlock_irqrestore(&saphir_lock, flags);
-	return ret;
+	return (ret);
 }
 
 static inline void
-writereg(struct IsdnCardState *cs, unsigned int adr, u8 off, u8 data)
+readfifo(unsigned int ale, unsigned int adr, u_char off, u_char * data, int size)
 {
-	unsigned long flags;
-
-	spin_lock_irqsave(&saphir_lock, flags);
-	byteout(cs->hw.saphir.ale, off);
-	byteout(adr, data);
-	spin_unlock_irqrestore(&saphir_lock, flags);
+	byteout(ale, off);
+	insb(adr, data, size);
 }
 
+
 static inline void
-readfifo(struct IsdnCardState *cs, unsigned int adr, u8 off, u8 *data, int size)
+writereg(unsigned int ale, unsigned int adr, u_char off, u_char data)
 {
-	byteout(cs->hw.saphir.ale, off);
-	insb(adr, data, size);
+	byteout(ale, off);
+	byteout(adr, data);
 }
 
 static inline void
-writefifo(struct IsdnCardState *cs, unsigned int adr, u8 off, u8 *data, int size)
+writefifo(unsigned int ale, unsigned int adr, u_char off, u_char * data, int size)
 {
-	byteout(cs->hw.saphir.ale, off);
+	byteout(ale, off);
 	outsb(adr, data, size);
 }
 
-static u8
-isac_read(struct IsdnCardState *cs, u8 offset)
+/* Interface functions */
+
+static u_char
+ReadISAC(struct IsdnCardState *cs, u_char offset)
 {
-	return readreg(cs, cs->hw.saphir.isac, offset);
+	return (readreg(cs->hw.saphir.ale, cs->hw.saphir.isac, offset));
 }
 
 static void
-isac_write(struct IsdnCardState *cs, u8 offset, u8 value)
+WriteISAC(struct IsdnCardState *cs, u_char offset, u_char value)
 {
-	writereg(cs, cs->hw.saphir.isac, offset, value);
+	writereg(cs->hw.saphir.ale, cs->hw.saphir.isac, offset, value);
 }
 
 static void
-isac_read_fifo(struct IsdnCardState *cs, u8 * data, int size)
+ReadISACfifo(struct IsdnCardState *cs, u_char * data, int size)
 {
-	readfifo(cs, cs->hw.saphir.isac, 0, data, size);
+	readfifo(cs->hw.saphir.ale, cs->hw.saphir.isac, 0, data, size);
 }
 
 static void
-isac_write_fifo(struct IsdnCardState *cs, u8 * data, int size)
+WriteISACfifo(struct IsdnCardState *cs, u_char * data, int size)
 {
-	writefifo(cs, cs->hw.saphir.isac, 0, data, size);
+	writefifo(cs->hw.saphir.ale, cs->hw.saphir.isac, 0, data, size);
 }
 
-static struct dc_hw_ops isac_ops = {
-	.read_reg   = isac_read,
-	.write_reg  = isac_write,
-	.read_fifo  = isac_read_fifo,
-	.write_fifo = isac_write_fifo,
-};
-
-static u8
-hscx_read(struct IsdnCardState *cs, int hscx, u8 offset)
+static u_char
+ReadHSCX(struct IsdnCardState *cs, int hscx, u_char offset)
 {
-	return readreg(cs, cs->hw.saphir.hscx, offset + (hscx ? 0x40 : 0));
+	return (readreg(cs->hw.saphir.ale, cs->hw.saphir.hscx,
+		offset + (hscx ? 0x40 : 0)));
 }
 
 static void
-hscx_write(struct IsdnCardState *cs, int hscx, u8 offset, u8 value)
+WriteHSCX(struct IsdnCardState *cs, int hscx, u_char offset, u_char value)
 {
-	writereg(cs, cs->hw.saphir.hscx, offset + (hscx ? 0x40 : 0), value);
+	writereg(cs->hw.saphir.ale, cs->hw.saphir.hscx,
+		offset + (hscx ? 0x40 : 0), value);
 }
 
-static void
-hscx_read_fifo(struct IsdnCardState *cs, int hscx, u8 *data, int size)
-{
-	readfifo(cs, cs->hw.saphir.hscx, hscx ? 0x40 : 0, data, size);
-}
+#define READHSCX(cs, nr, reg) readreg(cs->hw.saphir.ale, \
+		cs->hw.saphir.hscx, reg + (nr ? 0x40 : 0))
+#define WRITEHSCX(cs, nr, reg, data) writereg(cs->hw.saphir.ale, \
+		cs->hw.saphir.hscx, reg + (nr ? 0x40 : 0), data)
 
-static void
-hscx_write_fifo(struct IsdnCardState *cs, int hscx, u8 *data, int size)
-{
-	writefifo(cs, cs->hw.saphir.hscx, hscx ? 0x40 : 0, data, size);
-}
+#define READHSCXFIFO(cs, nr, ptr, cnt) readfifo(cs->hw.saphir.ale, \
+		cs->hw.saphir.hscx, (nr ? 0x40 : 0), ptr, cnt)
+
+#define WRITEHSCXFIFO(cs, nr, ptr, cnt) writefifo(cs->hw.saphir.ale, \
+		cs->hw.saphir.hscx, (nr ? 0x40 : 0), ptr, cnt)
 
-static struct bc_hw_ops hscx_ops = {
-	.read_reg   = hscx_read,
-	.write_reg  = hscx_write,
-	.read_fifo  = hscx_read_fifo,
-	.write_fifo = hscx_write_fifo,
-};
+#include "hscx_irq.c"
 
 static irqreturn_t
 saphir_interrupt(int intno, void *dev_id, struct pt_regs *regs)
 {
 	struct IsdnCardState *cs = dev_id;
-	irqreturn_t ret;
+	u_char val;
+	u_long flags;
 
-	ret = hscxisac_irq(intno, dev_id, regs);
-	mod_timer(&cs->hw.saphir.timer, jiffies+1*HZ);
-	return ret;
+	spin_lock_irqsave(&cs->lock, flags);
+	val = readreg(cs->hw.saphir.ale, cs->hw.saphir.hscx, HSCX_ISTA + 0x40);
+      Start_HSCX:
+	if (val)
+		hscx_int_main(cs, val);
+	val = readreg(cs->hw.saphir.ale, cs->hw.saphir.isac, ISAC_ISTA);
+      Start_ISAC:
+	if (val)
+		isac_interrupt(cs, val);
+	val = readreg(cs->hw.saphir.ale, cs->hw.saphir.hscx, HSCX_ISTA + 0x40);
+	if (val) {
+		if (cs->debug & L1_DEB_HSCX)
+			debugl1(cs, "HSCX IntStat after IntRoutine");
+		goto Start_HSCX;
+	}
+	val = readreg(cs->hw.saphir.ale, cs->hw.saphir.isac, ISAC_ISTA);
+	if (val) {
+		if (cs->debug & L1_DEB_ISAC)
+			debugl1(cs, "ISAC IntStat after IntRoutine");
+		goto Start_ISAC;
+	}
+	/* Watchdog */
+	if (cs->hw.saphir.timer.function) 
+		mod_timer(&cs->hw.saphir.timer, jiffies+1*HZ);
+	else
+		printk(KERN_WARNING "saphir: Spurious timer!\n");
+	writereg(cs->hw.saphir.ale, cs->hw.saphir.hscx, HSCX_MASK, 0xFF);
+	writereg(cs->hw.saphir.ale, cs->hw.saphir.hscx, HSCX_MASK + 0x40, 0xFF);
+	writereg(cs->hw.saphir.ale, cs->hw.saphir.isac, ISAC_MASK, 0xFF);
+	writereg(cs->hw.saphir.ale, cs->hw.saphir.isac, ISAC_MASK, 0);
+	writereg(cs->hw.saphir.ale, cs->hw.saphir.hscx, HSCX_MASK, 0);
+	writereg(cs->hw.saphir.ale, cs->hw.saphir.hscx, HSCX_MASK + 0x40, 0);
+	spin_unlock_irqrestore(&cs->lock, flags);
+	return IRQ_HANDLED;
 }
 
 static void
 SaphirWatchDog(struct IsdnCardState *cs)
 {
+	u_long flags;
+
+	spin_lock_irqsave(&cs->lock, flags);
         /* 5 sec WatchDog, so read at least every 4 sec */
-	isac_read(cs, ISAC_RBCH);
+	cs->readisac(cs, ISAC_RBCH);
+	spin_unlock_irqrestore(&cs->lock, flags);
 	mod_timer(&cs->hw.saphir.timer, jiffies+1*HZ);
 }
 
-static void
-saphir_release(struct IsdnCardState *cs)
+void
+release_io_saphir(struct IsdnCardState *cs)
 {
 	byteout(cs->hw.saphir.cfg_reg + IRQ_REG, 0xff);
-	del_timer_sync(&cs->hw.saphir.timer);
+	del_timer(&cs->hw.saphir.timer);
 	cs->hw.saphir.timer.function = NULL;
-	hisax_release_resources(cs);
+	if (cs->hw.saphir.cfg_reg)
+		release_region(cs->hw.saphir.cfg_reg, 6);
 }
 
 static int
 saphir_reset(struct IsdnCardState *cs)
 {
-	u8 irq_val;
+	u_char irq_val;
 
 	switch(cs->irq) {
 		case 5: irq_val = 0;
@@ -186,66 +207,94 @@ saphir_reset(struct IsdnCardState *cs)
 	}
 	byteout(cs->hw.saphir.cfg_reg + IRQ_REG, irq_val);
 	byteout(cs->hw.saphir.cfg_reg + RESET_REG, 1);
-	set_current_state(TASK_UNINTERRUPTIBLE);
-	schedule_timeout((30*HZ)/1000);	/* Timeout 30ms */
+	mdelay(10);
 	byteout(cs->hw.saphir.cfg_reg + RESET_REG, 0);
-	set_current_state(TASK_UNINTERRUPTIBLE);
-	schedule_timeout((30*HZ)/1000);	/* Timeout 30ms */
+	mdelay(10);
 	byteout(cs->hw.saphir.cfg_reg + IRQ_REG, irq_val);
 	byteout(cs->hw.saphir.cfg_reg + SPARE_REG, 0x02);
 	return (0);
 }
 
-static struct card_ops saphir_ops = {
-	.init     = inithscxisac,
-	.reset    = saphir_reset,
-	.release  = saphir_release,
-	.irq_func = saphir_interrupt,
-};
+static int
+saphir_card_msg(struct IsdnCardState *cs, int mt, void *arg)
+{
+	u_long flags;
+
+	switch (mt) {
+		case CARD_RESET:
+			spin_lock_irqsave(&cs->lock, flags);
+			saphir_reset(cs);
+			spin_unlock_irqrestore(&cs->lock, flags);
+			return(0);
+		case CARD_RELEASE:
+			release_io_saphir(cs);
+			return(0);
+		case CARD_INIT:
+			spin_lock_irqsave(&cs->lock, flags);
+			inithscxisac(cs, 3);
+			spin_unlock_irqrestore(&cs->lock, flags);
+			return(0);
+		case CARD_TEST:
+			return(0);
+	}
+	return(0);
+}
 
-static int __init
-saphir_probe(struct IsdnCardState *cs, struct IsdnCard *card)
+
+int __init
+setup_saphir(struct IsdnCard *card)
 {
+	struct IsdnCardState *cs = card->cs;
+	char tmp[64];
+
+	strcpy(tmp, saphir_rev);
+	printk(KERN_INFO "HiSax: HST Saphir driver Rev. %s\n", HiSax_getrev(tmp));
+	if (cs->typ != ISDN_CTYPE_HSTSAPHIR)
+		return (0);
+
+	/* IO-Ports */
 	cs->hw.saphir.cfg_reg = card->para[1];
 	cs->hw.saphir.isac = card->para[1] + ISAC_DATA;
 	cs->hw.saphir.hscx = card->para[1] + HSCX_DATA;
 	cs->hw.saphir.ale = card->para[1] + ADDRESS_REG;
 	cs->irq = card->para[0];
-
-	if (!request_io(&cs->rs, cs->hw.saphir.cfg_reg, 6, "saphir"))
-		goto err;
+	if (!request_region(cs->hw.saphir.cfg_reg, 6, "saphir")) {
+		printk(KERN_WARNING
+			"HiSax: %s config port %x-%x already in use\n",
+			CardType[card->typ],
+			cs->hw.saphir.cfg_reg,
+			cs->hw.saphir.cfg_reg + 5);
+		return (0);
+	}
 
 	printk(KERN_INFO "HiSax: %s config irq:%d io:0x%X\n",
-	       CardType[cs->typ], cs->irq, cs->hw.saphir.cfg_reg);
+		CardType[cs->typ], cs->irq, cs->hw.saphir.cfg_reg);
 
-	if (saphir_reset(cs))
-		goto err;
-
-	cs->card_ops = &saphir_ops;
-	if (hscxisac_setup(cs, &isac_ops, &hscx_ops))
-		goto err;
-
-	init_timer(&cs->hw.saphir.timer);
+	setup_isac(cs);
 	cs->hw.saphir.timer.function = (void *) SaphirWatchDog;
 	cs->hw.saphir.timer.data = (long) cs;
+	init_timer(&cs->hw.saphir.timer);
 	cs->hw.saphir.timer.expires = jiffies + 4*HZ;
 	add_timer(&cs->hw.saphir.timer);
-	return 0;
- err:
-	hisax_release_resources(cs);
-	return -EBUSY;
-}
-
-int __init
-setup_saphir(struct IsdnCard *card)
-{
-	char tmp[64];
-
-	strcpy(tmp, saphir_rev);
-	printk(KERN_INFO "HiSax: HST Saphir driver Rev. %s\n",
-	       HiSax_getrev(tmp));
-
-	if (saphir_probe(card->cs, card) < 0)
-		return 0;
-	return 1;
+	if (saphir_reset(cs)) {
+		release_io_saphir(cs);
+		return (0);
+	}
+	cs->readisac = &ReadISAC;
+	cs->writeisac = &WriteISAC;
+	cs->readisacfifo = &ReadISACfifo;
+	cs->writeisacfifo = &WriteISACfifo;
+	cs->BC_Read_Reg = &ReadHSCX;
+	cs->BC_Write_Reg = &WriteHSCX;
+	cs->BC_Send_Data = &hscx_fill_fifo;
+	cs->cardmsg = &saphir_card_msg;
+	cs->irq_func = &saphir_interrupt;
+	ISACVersion(cs, "saphir:");
+	if (HscxVersion(cs, "saphir:")) {
+		printk(KERN_WARNING
+		    "saphir: wrong HSCX versions check IO address\n");
+		release_io_saphir(cs);
+		return (0);
+	}
+	return (1);
 }
--- diff/drivers/isdn/hisax/sedlbauer.c	2003-09-17 12:28:06.000000000 +0100
+++ source/drivers/isdn/hisax/sedlbauer.c	2004-02-23 13:56:42.000000000 +0000
@@ -1,4 +1,4 @@
-/* $Id: sedlbauer.c,v 1.25.6.6 2001/09/23 22:24:51 kai Exp $
+/* $Id: sedlbauer.c,v 1.34.2.6 2004/01/24 20:47:24 keil Exp $
  *
  * low level stuff for Sedlbauer cards
  * includes support for the Sedlbauer speed star (speed star II),
@@ -50,16 +50,16 @@
 #include <linux/isapnp.h>
 
 extern const char *CardType[];
-static spinlock_t sedlbauer_lock = SPIN_LOCK_UNLOCKED; 
 
-const char *Sedlbauer_revision = "$Revision: 1.25.6.6 $";
+const char *Sedlbauer_revision = "$Revision: 1.34.2.6 $";
 
 const char *Sedlbauer_Types[] =
 	{"None", "speed card/win", "speed star", "speed fax+",
 	"speed win II / ISDN PC/104", "speed star II", "speed pci",
-	"speed fax+ pyramid", "speed fax+ pci"};
+	"speed fax+ pyramid", "speed fax+ pci", "HST Saphir III"};
 
 #define PCI_SUBVENDOR_SPEEDFAX_PYRAMID	0x51
+#define PCI_SUBVENDOR_HST_SAPHIR3	0x52
 #define PCI_SUBVENDOR_SEDLBAUER_PCI	0x53
 #define PCI_SUBVENDOR_SPEEDFAX_PCI	0x54
 #define PCI_SUB_ID_SEDLBAUER		0x01
@@ -72,7 +72,9 @@ const char *Sedlbauer_Types[] =
 #define SEDL_SPEED_PCI   	6
 #define SEDL_SPEEDFAX_PYRAMID	7
 #define SEDL_SPEEDFAX_PCI	8
+#define HST_SAPHIR3		9
 
+#define SEDL_CHIP_TEST		0
 #define SEDL_CHIP_ISAC_HSCX	1
 #define SEDL_CHIP_ISAC_ISAR	2
 #define SEDL_CHIP_IPAC		3
@@ -117,209 +119,264 @@ const char *Sedlbauer_Types[] =
 
 #define SEDL_RESET      0x3	/* same as DOS driver */
 
-static inline u8
-readreg(struct IsdnCardState *cs, unsigned int adr, u8 off)
+static inline u_char
+readreg(unsigned int ale, unsigned int adr, u_char off)
 {
-	u8 ret;
-	unsigned long flags;
+	register u_char ret;
 
-	spin_lock_irqsave(&sedlbauer_lock, flags);
-	byteout(cs->hw.sedl.adr, off);
+	byteout(ale, off);
 	ret = bytein(adr);
-	spin_unlock_irqrestore(&sedlbauer_lock, flags);
-	return ret;
+	return (ret);
 }
 
 static inline void
-readfifo(struct IsdnCardState *cs, unsigned int adr, u8 off, u8 * data, int size)
+readfifo(unsigned int ale, unsigned int adr, u_char off, u_char * data, int size)
 {
-	unsigned long flags;
-
-	spin_lock_irqsave(&sedlbauer_lock, flags);
-	byteout(cs->hw.sedl.adr, off);
+	byteout(ale, off);
 	insb(adr, data, size);
-	spin_unlock_irqrestore(&sedlbauer_lock, flags);
 }
 
 
 static inline void
-writereg(struct IsdnCardState *cs, unsigned int adr, u8 off, u8 data)
+writereg(unsigned int ale, unsigned int adr, u_char off, u_char data)
 {
-	byteout(cs->hw.sedl.adr, off);
+	byteout(ale, off);
 	byteout(adr, data);
 }
 
 static inline void
-writefifo(struct IsdnCardState *cs, unsigned int adr, u8 off, u8 * data, int size)
+writefifo(unsigned int ale, unsigned int adr, u_char off, u_char * data, int size)
 {
-	byteout(cs->hw.sedl.adr, off);
+	byteout(ale, off);
 	outsb(adr, data, size);
 }
 
-static u8
-isac_read(struct IsdnCardState *cs, u8 offset)
+/* Interface functions */
+
+static u_char
+ReadISAC(struct IsdnCardState *cs, u_char offset)
 {
-	return readreg(cs, cs->hw.sedl.isac, offset);
+	return (readreg(cs->hw.sedl.adr, cs->hw.sedl.isac, offset));
 }
 
 static void
-isac_write(struct IsdnCardState *cs, u8 offset, u8 value)
+WriteISAC(struct IsdnCardState *cs, u_char offset, u_char value)
 {
-	writereg(cs, cs->hw.sedl.isac, offset, value);
+	writereg(cs->hw.sedl.adr, cs->hw.sedl.isac, offset, value);
 }
 
 static void
-isac_read_fifo(struct IsdnCardState *cs, u8 * data, int size)
+ReadISACfifo(struct IsdnCardState *cs, u_char * data, int size)
 {
-	readfifo(cs, cs->hw.sedl.isac, 0, data, size);
+	readfifo(cs->hw.sedl.adr, cs->hw.sedl.isac, 0, data, size);
 }
 
 static void
-isac_write_fifo(struct IsdnCardState *cs, u8 * data, int size)
+WriteISACfifo(struct IsdnCardState *cs, u_char * data, int size)
 {
-	writefifo(cs, cs->hw.sedl.isac, 0, data, size);
+	writefifo(cs->hw.sedl.adr, cs->hw.sedl.isac, 0, data, size);
 }
 
-static struct dc_hw_ops isac_ops = {
-	.read_reg   = isac_read,
-	.write_reg  = isac_write,
-	.read_fifo  = isac_read_fifo,
-	.write_fifo = isac_write_fifo,
-};
-
-static u8
-hscx_read(struct IsdnCardState *cs, int hscx, u8 offset)
+static u_char
+ReadISAC_IPAC(struct IsdnCardState *cs, u_char offset)
 {
-	return readreg(cs, cs->hw.sedl.hscx, offset + (hscx ? 0x40 : 0));
+	return (readreg(cs->hw.sedl.adr, cs->hw.sedl.isac, offset|0x80));
 }
 
 static void
-hscx_write(struct IsdnCardState *cs, int hscx, u8 offset, u8 value)
+WriteISAC_IPAC(struct IsdnCardState *cs, u_char offset, u_char value)
 {
-	writereg(cs, cs->hw.sedl.hscx, offset + (hscx ? 0x40 : 0), value);
+	writereg(cs->hw.sedl.adr, cs->hw.sedl.isac, offset|0x80, value);
 }
 
 static void
-hscx_read_fifo(struct IsdnCardState *cs, int hscx, u8 *data, int size)
+ReadISACfifo_IPAC(struct IsdnCardState *cs, u_char * data, int size)
 {
-	readfifo(cs, cs->hw.sedl.hscx, hscx ? 0x40 : 0, data, size);
+	readfifo(cs->hw.sedl.adr, cs->hw.sedl.isac, 0x80, data, size);
 }
 
 static void
-hscx_write_fifo(struct IsdnCardState *cs, int hscx, u8 *data, int size)
+WriteISACfifo_IPAC(struct IsdnCardState *cs, u_char * data, int size)
 {
-	writefifo(cs, cs->hw.sedl.hscx, hscx ? 0x40 : 0, data, size);
+	writefifo(cs->hw.sedl.adr, cs->hw.sedl.isac, 0x80, data, size);
 }
 
-static struct bc_hw_ops hscx_ops = {
-	.read_reg   = hscx_read,
-	.write_reg  = hscx_write,
-	.read_fifo  = hscx_read_fifo,
-	.write_fifo = hscx_write_fifo,
-};
-
-static inline u8
-ipac_read(struct IsdnCardState *cs, u8 offset)
+static u_char
+ReadHSCX(struct IsdnCardState *cs, int hscx, u_char offset)
 {
-	return readreg(cs, cs->hw.sedl.isac, offset);
+	return (readreg(cs->hw.sedl.adr,
+			cs->hw.sedl.hscx, offset + (hscx ? 0x40 : 0)));
 }
 
-static inline void
-ipac_write(struct IsdnCardState *cs, u8 offset, u8 value)
-{
-	writereg(cs, cs->hw.sedl.isac, offset, value);
-}
-
-static inline void
-ipac_readfifo(struct IsdnCardState *cs, u8 offset, u8 *data, int size)
-{
-	readfifo(cs, cs->hw.sedl.isac, offset, data, size);
-}
-
-static inline void
-ipac_writefifo(struct IsdnCardState *cs, u8 offset, u8 *data, int size)
+static void
+WriteHSCX(struct IsdnCardState *cs, int hscx, u_char offset, u_char value)
 {
-	writefifo(cs, cs->hw.sedl.isac, offset, data, size);
+	writereg(cs->hw.sedl.adr,
+		 cs->hw.sedl.hscx, offset + (hscx ? 0x40 : 0), value);
 }
 
-/* This will generate ipac_dc_ops and ipac_bc_ops using the functions
- * above */
-
-BUILD_IPAC_OPS(ipac);
-
-
 /* ISAR access routines
  * mode = 0 access with IRQ on
  * mode = 1 access with IRQ off
  * mode = 2 access with IRQ off and using last offset
  */
 
-static u8
-isar_read(struct IsdnCardState *cs, int mode, u8 offset)
+static u_char
+ReadISAR(struct IsdnCardState *cs, int mode, u_char offset)
 {	
 	if (mode == 0)
-		return readreg(cs, cs->hw.sedl.hscx, offset);
-
-	if (mode == 1)
+		return (readreg(cs->hw.sedl.adr, cs->hw.sedl.hscx, offset));
+	else if (mode == 1)
 		byteout(cs->hw.sedl.adr, offset);
-
-	return bytein(cs->hw.sedl.hscx);
+	return(bytein(cs->hw.sedl.hscx));
 }
 
 static void
-isar_write(struct IsdnCardState *cs, int mode, u8 offset, u8 value)
+WriteISAR(struct IsdnCardState *cs, int mode, u_char offset, u_char value)
 {
 	if (mode == 0)
-		return writereg(cs, cs->hw.sedl.hscx, offset, value);
+		writereg(cs->hw.sedl.adr, cs->hw.sedl.hscx, offset, value);
+	else {
+		if (mode == 1)
+			byteout(cs->hw.sedl.adr, offset);
+		byteout(cs->hw.sedl.hscx, value);
+	}
+}
 
-	if (mode == 1)
-		byteout(cs->hw.sedl.adr, offset);
+/*
+ * fast interrupt HSCX stuff goes here
+ */
 
-	byteout(cs->hw.sedl.hscx, value);
-}
+#define READHSCX(cs, nr, reg) readreg(cs->hw.sedl.adr, \
+		cs->hw.sedl.hscx, reg + (nr ? 0x40 : 0))
+#define WRITEHSCX(cs, nr, reg, data) writereg(cs->hw.sedl.adr, \
+		cs->hw.sedl.hscx, reg + (nr ? 0x40 : 0), data)
 
-static struct bc_hw_ops isar_ops = {
-	.read_reg   = isar_read,
-	.write_reg  = isar_write,
-};
+#define READHSCXFIFO(cs, nr, ptr, cnt) readfifo(cs->hw.sedl.adr, \
+		cs->hw.sedl.hscx, (nr ? 0x40 : 0), ptr, cnt)
+
+#define WRITEHSCXFIFO(cs, nr, ptr, cnt) writefifo(cs->hw.sedl.adr, \
+		cs->hw.sedl.hscx, (nr ? 0x40 : 0), ptr, cnt)
+
+#include "hscx_irq.c"
 
 static irqreturn_t
 sedlbauer_interrupt(int intno, void *dev_id, struct pt_regs *regs)
 {
 	struct IsdnCardState *cs = dev_id;
+	u_char val;
+	u_long flags;
 
+	spin_lock_irqsave(&cs->lock, flags);
 	if ((cs->hw.sedl.bus == SEDL_BUS_PCMCIA) && (*cs->busy_flag == 1)) {
 		/* The card tends to generate interrupts while being removed
 		   causing us to just crash the kernel. bad. */
+		spin_unlock_irqrestore(&cs->lock, flags);
 		printk(KERN_WARNING "Sedlbauer: card not available!\n");
 		return IRQ_NONE;
 	}
-	return hscxisac_irq(intno, dev_id, regs);
+
+	val = readreg(cs->hw.sedl.adr, cs->hw.sedl.hscx, HSCX_ISTA + 0x40);
+      Start_HSCX:
+	if (val)
+		hscx_int_main(cs, val);
+	val = readreg(cs->hw.sedl.adr, cs->hw.sedl.isac, ISAC_ISTA);
+      Start_ISAC:
+	if (val)
+		isac_interrupt(cs, val);
+	val = readreg(cs->hw.sedl.adr, cs->hw.sedl.hscx, HSCX_ISTA + 0x40);
+	if (val) {
+		if (cs->debug & L1_DEB_HSCX)
+			debugl1(cs, "HSCX IntStat after IntRoutine");
+		goto Start_HSCX;
+	}
+	val = readreg(cs->hw.sedl.adr, cs->hw.sedl.isac, ISAC_ISTA);
+	if (val) {
+		if (cs->debug & L1_DEB_ISAC)
+			debugl1(cs, "ISAC IntStat after IntRoutine");
+		goto Start_ISAC;
+	}
+	writereg(cs->hw.sedl.adr, cs->hw.sedl.hscx, HSCX_MASK, 0xFF);
+	writereg(cs->hw.sedl.adr, cs->hw.sedl.hscx, HSCX_MASK + 0x40, 0xFF);
+	writereg(cs->hw.sedl.adr, cs->hw.sedl.isac, ISAC_MASK, 0xFF);
+	writereg(cs->hw.sedl.adr, cs->hw.sedl.isac, ISAC_MASK, 0x0);
+	writereg(cs->hw.sedl.adr, cs->hw.sedl.hscx, HSCX_MASK, 0x0);
+	writereg(cs->hw.sedl.adr, cs->hw.sedl.hscx, HSCX_MASK + 0x40, 0x0);
+	spin_unlock_irqrestore(&cs->lock, flags);
+	return IRQ_HANDLED;
+}
+
+static irqreturn_t
+sedlbauer_interrupt_ipac(int intno, void *dev_id, struct pt_regs *regs)
+{
+	struct IsdnCardState *cs = dev_id;
+	u_char ista, val, icnt = 5;
+	u_long flags;
+
+	spin_lock_irqsave(&cs->lock, flags);
+	ista = readreg(cs->hw.sedl.adr, cs->hw.sedl.isac, IPAC_ISTA);
+Start_IPAC:
+	if (cs->debug & L1_DEB_IPAC)
+		debugl1(cs, "IPAC ISTA %02X", ista);
+	if (ista & 0x0f) {
+		val = readreg(cs->hw.sedl.adr, cs->hw.sedl.hscx, HSCX_ISTA + 0x40);
+		if (ista & 0x01)
+			val |= 0x01;
+		if (ista & 0x04)
+			val |= 0x02;
+		if (ista & 0x08)
+			val |= 0x04;
+		if (val)
+			hscx_int_main(cs, val);
+	}
+	if (ista & 0x20) {
+		val = 0xfe & readreg(cs->hw.sedl.adr, cs->hw.sedl.isac, ISAC_ISTA | 0x80);
+		if (val) {
+			isac_interrupt(cs, val);
+		}
+	}
+	if (ista & 0x10) {
+		val = 0x01;
+		isac_interrupt(cs, val);
+	}
+	ista  = readreg(cs->hw.sedl.adr, cs->hw.sedl.isac, IPAC_ISTA);
+	if ((ista & 0x3f) && icnt) {
+		icnt--;
+		goto Start_IPAC;
+	}
+	if (!icnt)
+		if (cs->debug & L1_DEB_ISAC)
+			debugl1(cs, "Sedlbauer IRQ LOOP");
+	writereg(cs->hw.sedl.adr, cs->hw.sedl.isac, IPAC_MASK, 0xFF);
+	writereg(cs->hw.sedl.adr, cs->hw.sedl.isac, IPAC_MASK, 0xC0);
+	spin_unlock_irqrestore(&cs->lock, flags);
+	return IRQ_HANDLED;
 }
 
 static irqreturn_t
-sedlbauer_isar_interrupt(int intno, void *dev_id, struct pt_regs *regs)
+sedlbauer_interrupt_isar(int intno, void *dev_id, struct pt_regs *regs)
 {
 	struct IsdnCardState *cs = dev_id;
-	u8 val;
+	u_char val;
 	int cnt = 5;
+	u_long flags;
 
-	spin_lock(&cs->lock);
-	val = isar_read(cs, 0, ISAR_IRQBIT);
+	spin_lock_irqsave(&cs->lock, flags);
+	val = readreg(cs->hw.sedl.adr, cs->hw.sedl.hscx, ISAR_IRQBIT);
       Start_ISAR:
 	if (val & ISAR_IRQSTA)
 		isar_int_main(cs);
-	val = isac_read(cs, ISAC_ISTA);
+	val = readreg(cs->hw.sedl.adr, cs->hw.sedl.isac, ISAC_ISTA);
       Start_ISAC:
 	if (val)
 		isac_interrupt(cs, val);
-	val = isar_read(cs, 0, ISAR_IRQBIT);
+	val = readreg(cs->hw.sedl.adr, cs->hw.sedl.hscx, ISAR_IRQBIT);
 	if ((val & ISAR_IRQSTA) && --cnt) {
 		if (cs->debug & L1_DEB_HSCX)
 			debugl1(cs, "ISAR IntStat after IntRoutine");
 		goto Start_ISAR;
 	}
-	val = isac_read(cs, ISAC_ISTA);
+	val = readreg(cs->hw.sedl.adr, cs->hw.sedl.isac, ISAC_ISTA);
 	if (val && --cnt) {
 		if (cs->debug & L1_DEB_ISAC)
 			debugl1(cs, "ISAC IntStat after IntRoutine");
@@ -329,362 +386,131 @@ sedlbauer_isar_interrupt(int intno, void
 		if (cs->debug & L1_DEB_ISAC)
 			debugl1(cs, "Sedlbauer IRQ LOOP");
 
-	isar_write(cs, 0, ISAR_IRQBIT, 0);
-	isac_write(cs, ISAC_MASK, 0xFF);
-	isac_write(cs, ISAC_MASK, 0x0);
-	isar_write(cs, 0, ISAR_IRQBIT, ISAR_IRQMSK);
-	spin_unlock(&cs->lock);
+	writereg(cs->hw.sedl.adr, cs->hw.sedl.hscx, ISAR_IRQBIT, 0);
+	writereg(cs->hw.sedl.adr, cs->hw.sedl.isac, ISAC_MASK, 0xFF);
+	writereg(cs->hw.sedl.adr, cs->hw.sedl.isac, ISAC_MASK, 0x0);
+	writereg(cs->hw.sedl.adr, cs->hw.sedl.hscx, ISAR_IRQBIT, ISAR_IRQMSK);
+	spin_unlock_irqrestore(&cs->lock, flags);
 	return IRQ_HANDLED;
 }
 
-static int
-sedlbauer_ipac_reset(struct IsdnCardState *cs)
+void
+release_io_sedlbauer(struct IsdnCardState *cs)
 {
-	writereg(cs, cs->hw.sedl.isac, IPAC_POTA2, 0x20);
-	set_current_state(TASK_UNINTERRUPTIBLE);
-	schedule_timeout((10*HZ)/1000);
-	writereg(cs, cs->hw.sedl.isac, IPAC_POTA2, 0x0);
-	set_current_state(TASK_UNINTERRUPTIBLE);
-	schedule_timeout((10*HZ)/1000);
-	writereg(cs, cs->hw.sedl.isac, IPAC_CONF, 0x0);
-	writereg(cs, cs->hw.sedl.isac, IPAC_ACFG, 0xff);
-	writereg(cs, cs->hw.sedl.isac, IPAC_AOE, 0x0);
-	writereg(cs, cs->hw.sedl.isac, IPAC_MASK, 0xc0);
-	writereg(cs, cs->hw.sedl.isac, IPAC_PCFG, 0x12);
-	return 0;
-}
+	int bytecnt = 8;
 
-static int
-sedlbauer_isar_pci_reset(struct IsdnCardState *cs)
-{
-	byteout(cs->hw.sedl.cfg_reg +3, cs->hw.sedl.reset_on);
-	current->state = TASK_UNINTERRUPTIBLE;
-	schedule_timeout((20*HZ)/1000);
-	byteout(cs->hw.sedl.cfg_reg +3, cs->hw.sedl.reset_off);
-	current->state = TASK_UNINTERRUPTIBLE;
-	schedule_timeout((20*HZ)/1000);
-	return 0;
-}
-
-static int
-sedlbauer_reset(struct IsdnCardState *cs)
-{
-	printk(KERN_INFO "Sedlbauer: resetting card\n");
-	if (cs->hw.sedl.bus == SEDL_BUS_PCMCIA &&
-	   cs->hw.sedl.chip == SEDL_CHIP_ISAC_HSCX)
-		return 0;
-
-	if (cs->hw.sedl.chip == SEDL_CHIP_IPAC) {
-		return sedlbauer_ipac_reset(cs);
-	} else if ((cs->hw.sedl.chip == SEDL_CHIP_ISAC_ISAR) &&
-		   (cs->hw.sedl.bus == SEDL_BUS_PCI)) {
-		return sedlbauer_isar_pci_reset(cs);
-	} else {		
-		byteout(cs->hw.sedl.reset_on, SEDL_RESET);	/* Reset On */
-		set_current_state(TASK_UNINTERRUPTIBLE);
-		schedule_timeout((10*HZ)/1000);
-		byteout(cs->hw.sedl.reset_off, 0);	/* Reset Off */
-		set_current_state(TASK_UNINTERRUPTIBLE);
-		schedule_timeout((10*HZ)/1000);
+	if (cs->subtyp == SEDL_SPEED_FAX) {
+		bytecnt = 16;
+	} else if (cs->hw.sedl.bus == SEDL_BUS_PCI) {
+		bytecnt = 256;
 	}
-	return 0;
+	if (cs->hw.sedl.cfg_reg)
+		release_region(cs->hw.sedl.cfg_reg, bytecnt);
 }
 
 static void
-sedlbauer_isar_release(struct IsdnCardState *cs)
+reset_sedlbauer(struct IsdnCardState *cs)
 {
-	isar_write(cs, 0, ISAR_IRQBIT, 0);
-	isac_write(cs, ISAC_MASK, 0xFF);
-	sedlbauer_reset(cs);
-	isar_write(cs, 0, ISAR_IRQBIT, 0);
-	isac_write(cs, ISAC_MASK, 0xFF);
-	hisax_release_resources(cs);
-}
-
-static void
-sedlbauer_led_handler(struct IsdnCardState *cs)
-{
-	if (cs->subtyp != SEDL_SPEEDFAX_PYRAMID)
-		return;
-
-	if (cs->status & 0x2000)
-		cs->hw.sedl.reset_off &= ~SEDL_ISAR_PCI_LED2;
-	else
-		cs->hw.sedl.reset_off |=  SEDL_ISAR_PCI_LED2;
-
-	if (cs->status & 0x1000)
-		cs->hw.sedl.reset_off &= ~SEDL_ISAR_PCI_LED1;
-	else
-		cs->hw.sedl.reset_off |=  SEDL_ISAR_PCI_LED1;
-
-	byteout(cs->hw.sedl.cfg_reg +3, cs->hw.sedl.reset_off);
-}
-
-static void
-sedlbauer_isar_init(struct IsdnCardState *cs)
-{
-	isar_write(cs, 0, ISAR_IRQBIT, 0);
-	initisac(cs);
-	initisar(cs);
-}
-
-static struct card_ops sedlbauer_ops = {
-	.init        = inithscxisac,
-	.reset       = sedlbauer_reset,
-	.release     = hisax_release_resources,
-	.led_handler = sedlbauer_led_handler,
-	.irq_func    = sedlbauer_interrupt,
-};
-
-static struct card_ops sedlbauer_ipac_ops = {
-	.init        = ipac_init,
-	.reset       = sedlbauer_reset,
-	.release     = hisax_release_resources,
-	.led_handler = sedlbauer_led_handler,
-	.irq_func    = ipac_irq,
-};
-
-static struct card_ops sedlbauer_isar_ops = {
-	.init        = sedlbauer_isar_init,
-	.reset       = sedlbauer_reset,
-	.release     = sedlbauer_isar_release,
-	.led_handler = sedlbauer_led_handler,
-	.irq_func    = sedlbauer_isar_interrupt,
-};
-
-static int __init
-sedl_ipac_probe(struct IsdnCardState *cs)
-{
-	u8 val;
-
-	cs->hw.sedl.adr = cs->hw.sedl.cfg_reg + SEDL_IPAC_ANY_ADR;
-	val = readreg(cs, cs->hw.sedl.cfg_reg + SEDL_IPAC_ANY_IPAC, IPAC_ID);
-	printk(KERN_DEBUG "Sedlbauer: testing IPAC version %x\n", val);
-	return (val == 1 || val == 2);
-}
-
-static int __init
-sedl_ipac_init(struct IsdnCardState *cs)
-{
-	cs->card_ops = &sedlbauer_ipac_ops;
-	if (ipac_setup(cs, &ipac_dc_ops, &ipac_bc_ops))
-		return -ENODEV;
-	sedlbauer_reset(cs);
-	return 0;
-}
-
-static int __init
-sedl_isac_isar_init(struct IsdnCardState *cs)
-{
-	cs->bcs[0].hw.isar.reg = &cs->hw.sedl.isar;
-	cs->bcs[1].hw.isar.reg = &cs->hw.sedl.isar;
-	__set_bit(HW_ISAR, &cs->HW_Flags);
-	cs->card_ops = &sedlbauer_isar_ops;
-	cs->auxcmd = &isar_auxcmd;
-	isac_setup(cs, &isac_ops);
-	return isar_setup(cs, &isar_ops);
-}
+	printk(KERN_INFO "Sedlbauer: resetting card\n");
 
-static int __init
-sedl_isac_hscx_init(struct IsdnCardState *cs)
-{
-	cs->card_ops = &sedlbauer_ops;
-	if (hscxisac_setup(cs, &isac_ops, &hscx_ops))
-		return -ENODEV;
-	sedlbauer_reset(cs);
-	return 0;
+	if (!((cs->hw.sedl.bus == SEDL_BUS_PCMCIA) &&
+	   (cs->hw.sedl.chip == SEDL_CHIP_ISAC_HSCX))) {
+		if (cs->hw.sedl.chip == SEDL_CHIP_IPAC) {
+			writereg(cs->hw.sedl.adr, cs->hw.sedl.isac, IPAC_POTA2, 0x20);
+			mdelay(2);
+			writereg(cs->hw.sedl.adr, cs->hw.sedl.isac, IPAC_POTA2, 0x0);
+			mdelay(10);
+			writereg(cs->hw.sedl.adr, cs->hw.sedl.isac, IPAC_CONF, 0x0);
+			writereg(cs->hw.sedl.adr, cs->hw.sedl.isac, IPAC_ACFG, 0xff);
+			writereg(cs->hw.sedl.adr, cs->hw.sedl.isac, IPAC_AOE, 0x0);
+			writereg(cs->hw.sedl.adr, cs->hw.sedl.isac, IPAC_MASK, 0xc0);
+			writereg(cs->hw.sedl.adr, cs->hw.sedl.isac, IPAC_PCFG, 0x12);
+		} else if ((cs->hw.sedl.chip == SEDL_CHIP_ISAC_ISAR) &&
+			(cs->hw.sedl.bus == SEDL_BUS_PCI)) {
+			byteout(cs->hw.sedl.cfg_reg +3, cs->hw.sedl.reset_on);
+			mdelay(2);
+			byteout(cs->hw.sedl.cfg_reg +3, cs->hw.sedl.reset_off);
+			mdelay(10);
+		} else {		
+			byteout(cs->hw.sedl.reset_on, SEDL_RESET);	/* Reset On */
+			mdelay(2);
+			byteout(cs->hw.sedl.reset_off, 0);	/* Reset Off */
+			mdelay(10);
+		}
+	}
 }
 
-static int __init
-sedl_card_win_probe(struct IsdnCardState *cs, struct IsdnCard *card)
+static int
+Sedl_card_msg(struct IsdnCardState *cs, int mt, void *arg)
 {
-	cs->irq = card->para[0];
-	cs->hw.sedl.cfg_reg = card->para[1];
-	cs->hw.sedl.bus = SEDL_BUS_ISA;
-	if (!request_io(&cs->rs, cs->hw.sedl.cfg_reg, 8, "sedlbauer isdn"))
-		goto err;
+	u_long flags;
 
-	if (sedl_ipac_probe(cs)) {
-		cs->subtyp = SEDL_SPEED_WIN2_PC104;
-		cs->hw.sedl.chip = SEDL_CHIP_IPAC;
-		cs->hw.sedl.adr  = cs->hw.sedl.cfg_reg + SEDL_IPAC_ANY_ADR;
-		cs->hw.sedl.isac = cs->hw.sedl.cfg_reg + SEDL_IPAC_ANY_IPAC;
-		if (sedl_ipac_init(cs))
-			goto err;
-	} else {
-		cs->subtyp = SEDL_SPEED_CARD_WIN;
-		cs->hw.sedl.chip = SEDL_CHIP_ISAC_HSCX;
-		cs->hw.sedl.adr = cs->hw.sedl.cfg_reg + SEDL_HSCX_ISA_ADR;
-		cs->hw.sedl.isac = cs->hw.sedl.cfg_reg + SEDL_HSCX_ISA_ISAC;
-		cs->hw.sedl.hscx = cs->hw.sedl.cfg_reg + SEDL_HSCX_ISA_HSCX;
-		cs->hw.sedl.reset_on = cs->hw.sedl.cfg_reg + SEDL_HSCX_ISA_RESET_ON;
-		cs->hw.sedl.reset_off = cs->hw.sedl.cfg_reg + SEDL_HSCX_ISA_RESET_OFF;
-		if (sedl_isac_hscx_init(cs))
-			goto err;
-	}
-	printk(KERN_INFO "Sedlbauer %s: defined at 0x%x-0x%x IRQ %d\n",
-	       Sedlbauer_Types[cs->subtyp],
-	       cs->hw.sedl.cfg_reg, cs->hw.sedl.cfg_reg + 8, cs->irq);
-
-	return 0;
- err:
-	hisax_release_resources(cs);
-	return -EBUSY;
-}
-
-static int __init
-sedl_star_probe(struct IsdnCardState *cs, struct IsdnCard *card)
-{
-	cs->hw.sedl.bus = SEDL_BUS_PCMCIA;
-	if (sedl_ipac_probe(cs)) {
-		cs->subtyp = SEDL_SPEED_STAR2;
-		cs->hw.sedl.chip = SEDL_CHIP_IPAC;
-		cs->hw.sedl.adr  = cs->hw.sedl.cfg_reg + SEDL_IPAC_ANY_ADR;
-		cs->hw.sedl.isac = cs->hw.sedl.cfg_reg + SEDL_IPAC_ANY_IPAC;
-		if (sedl_ipac_init(cs))
-			goto err;
-	} else {
-		cs->subtyp = SEDL_SPEED_STAR;
-		cs->hw.sedl.chip = SEDL_CHIP_ISAC_HSCX;
-		cs->hw.sedl.adr = cs->hw.sedl.cfg_reg + SEDL_HSCX_PCMCIA_ADR;
-		cs->hw.sedl.isac = cs->hw.sedl.cfg_reg + SEDL_HSCX_PCMCIA_ISAC;
-		cs->hw.sedl.hscx = cs->hw.sedl.cfg_reg + SEDL_HSCX_PCMCIA_HSCX;
-		cs->hw.sedl.reset_on = cs->hw.sedl.cfg_reg + SEDL_HSCX_PCMCIA_RESET;
-		cs->hw.sedl.reset_off = cs->hw.sedl.cfg_reg + SEDL_HSCX_PCMCIA_RESET;
-		if (sedl_isac_hscx_init(cs))
-			goto err;
-	}
-	printk(KERN_INFO "Sedlbauer %s: defined at 0x%x-0x%x IRQ %d\n",
-	       Sedlbauer_Types[cs->subtyp],
-	       cs->hw.sedl.cfg_reg, cs->hw.sedl.cfg_reg + 8, cs->irq);
-
-	return 0;
- err:
-	hisax_release_resources(cs);
-	return -EBUSY;
-}
-
-static int __init
-sedl_fax_probe(struct IsdnCardState *cs, struct IsdnCard *card)
-{
-	cs->subtyp = SEDL_SPEED_FAX;
-	cs->hw.sedl.bus = SEDL_BUS_ISA;
-	cs->hw.sedl.chip = SEDL_CHIP_ISAC_ISAR;
-	if (!request_io(&cs->rs, cs->hw.sedl.cfg_reg, 16, "sedlbauer isdn"))
-		goto err;
-
-	printk(KERN_INFO "Sedlbauer %s: defined at 0x%x-0x%x IRQ %d\n",
-	       Sedlbauer_Types[cs->subtyp],
-	       cs->hw.sedl.cfg_reg, cs->hw.sedl.cfg_reg + 16, cs->irq);
-
-	cs->hw.sedl.adr = cs->hw.sedl.cfg_reg  + SEDL_ISAR_ISA_ADR;
-	cs->hw.sedl.isac = cs->hw.sedl.cfg_reg + SEDL_ISAR_ISA_ISAC;
-	cs->hw.sedl.hscx = cs->hw.sedl.cfg_reg + SEDL_ISAR_ISA_ISAR;
-	cs->hw.sedl.reset_on = cs->hw.sedl.cfg_reg + SEDL_ISAR_ISA_ISAR_RESET_ON;
-	cs->hw.sedl.reset_off = cs->hw.sedl.cfg_reg + SEDL_ISAR_ISA_ISAR_RESET_OFF;
-	if (sedl_isac_isar_init(cs))
-		goto err;
-
-	return 0;
- err:
-	hisax_release_resources(cs);
-	return -EBUSY;
-}
-
-static int __init
-sedl_pci_init(struct IsdnCardState *cs, struct pci_dev *pdev)
-{
-	cs->irq = pdev->irq;
-	cs->irq_flags |= SA_SHIRQ;
-	cs->hw.sedl.cfg_reg = pci_resource_start(pdev, 0);
-	cs->hw.sedl.bus = SEDL_BUS_PCI;
-
-	if (!request_io(&cs->rs, cs->hw.sedl.cfg_reg, 256, "sedlbauer isdn"))
-		return -EBUSY;
-
-	printk(KERN_INFO "Sedlbauer %s: defined at 0x%x-0x%x IRQ %d\n",
-	       Sedlbauer_Types[cs->subtyp],
-	       cs->hw.sedl.cfg_reg, cs->hw.sedl.cfg_reg + 256, cs->irq);
-
-	cs->hw.sedl.reset_on = SEDL_ISAR_PCI_ISAR_RESET_ON;
-	cs->hw.sedl.reset_off = SEDL_ISAR_PCI_ISAR_RESET_OFF;
-	byteout(cs->hw.sedl.cfg_reg, 0xff);
-	byteout(cs->hw.sedl.cfg_reg, 0x00);
-	byteout(cs->hw.sedl.cfg_reg+ 2, 0xdd);
-	byteout(cs->hw.sedl.cfg_reg+ 5, 0x02);
-	byteout(cs->hw.sedl.cfg_reg +3, cs->hw.sedl.reset_on);
-	current->state = TASK_UNINTERRUPTIBLE;
-	schedule_timeout((10*HZ)/1000);
-	byteout(cs->hw.sedl.cfg_reg +3, cs->hw.sedl.reset_off);
-	return 0;
-}
-
-static int __init
-sedl_fax_pyramid_probe(struct IsdnCardState *cs, struct pci_dev *pdev)
-{
-	if (pci_enable_device(pdev))
-		goto err;
-
-	cs->subtyp = SEDL_SPEEDFAX_PYRAMID;
-	cs->hw.sedl.chip = SEDL_CHIP_ISAC_ISAR;
-	if (sedl_pci_init(cs, pdev))
-		goto err;
-
-	cs->hw.sedl.adr  = cs->hw.sedl.cfg_reg + SEDL_ISAR_PCI_ADR;
-	cs->hw.sedl.isac = cs->hw.sedl.cfg_reg + SEDL_ISAR_PCI_ISAC;
-	cs->hw.sedl.hscx = cs->hw.sedl.cfg_reg + SEDL_ISAR_PCI_ISAR;
-	if (sedl_isac_isar_init(cs))
-		goto err;
-
-	return 0;
- err:
-	hisax_release_resources(cs);
-	return -EBUSY;
-}
-
-static int __init
-sedl_fax_pci_probe(struct IsdnCardState *cs, struct pci_dev *pdev)
-{
-	if (pci_enable_device(pdev))
-		goto err;
-
-	cs->subtyp = SEDL_SPEEDFAX_PCI;
-	cs->hw.sedl.chip = SEDL_CHIP_ISAC_ISAR;
-
-	if (sedl_pci_init(cs, pdev))
-		goto err;
-
-	cs->hw.sedl.adr  = cs->hw.sedl.cfg_reg + SEDL_ISAR_PCI_ADR;
-	cs->hw.sedl.isac = cs->hw.sedl.cfg_reg + SEDL_ISAR_PCI_ISAC;
-	cs->hw.sedl.hscx = cs->hw.sedl.cfg_reg + SEDL_ISAR_PCI_ISAR;
-	if (sedl_isac_isar_init(cs))
-		goto err;
-
-	return 0;
- err:
-	hisax_release_resources(cs);
-	return -EBUSY;
-}
-
-static int __init
-sedl_pci_probe(struct IsdnCardState *cs, struct pci_dev *pdev)
-{
-	if (pci_enable_device(pdev))
-		goto err;
-
-	cs->subtyp = SEDL_SPEED_PCI;
-	cs->hw.sedl.chip = SEDL_CHIP_IPAC;
-	if (sedl_pci_init(cs, pdev))
-		goto err;
-
-	cs->hw.sedl.adr  = cs->hw.sedl.cfg_reg + SEDL_IPAC_PCI_ADR;
-	cs->hw.sedl.isac = cs->hw.sedl.cfg_reg + SEDL_IPAC_PCI_IPAC;
-	if (sedl_ipac_init(cs))
-		goto err;
-	return 0;
- err:
-	hisax_release_resources(cs);
-	return -EBUSY;
+	switch (mt) {
+		case CARD_RESET:
+			spin_lock_irqsave(&cs->lock, flags);
+			reset_sedlbauer(cs);
+			spin_unlock_irqrestore(&cs->lock, flags);
+			return(0);
+		case CARD_RELEASE:
+			if (cs->hw.sedl.chip == SEDL_CHIP_ISAC_ISAR) {
+				spin_lock_irqsave(&cs->lock, flags);
+				writereg(cs->hw.sedl.adr, cs->hw.sedl.hscx,
+					ISAR_IRQBIT, 0);
+				writereg(cs->hw.sedl.adr, cs->hw.sedl.isac,
+					ISAC_MASK, 0xFF);
+				reset_sedlbauer(cs);
+				writereg(cs->hw.sedl.adr, cs->hw.sedl.hscx,
+					ISAR_IRQBIT, 0);
+				writereg(cs->hw.sedl.adr, cs->hw.sedl.isac,
+					ISAC_MASK, 0xFF);
+				spin_unlock_irqrestore(&cs->lock, flags);
+			}
+			release_io_sedlbauer(cs);
+			return(0);
+		case CARD_INIT:
+			spin_lock_irqsave(&cs->lock, flags);
+			reset_sedlbauer(cs);
+			if (cs->hw.sedl.chip == SEDL_CHIP_ISAC_ISAR) {
+				clear_pending_isac_ints(cs);
+				writereg(cs->hw.sedl.adr, cs->hw.sedl.hscx,
+					ISAR_IRQBIT, 0);
+				initisac(cs);
+				initisar(cs);
+				/* Reenable all IRQ */
+				cs->writeisac(cs, ISAC_MASK, 0);
+				/* RESET Receiver and Transmitter */
+				cs->writeisac(cs, ISAC_CMDR, 0x41);
+			} else {
+				inithscxisac(cs, 3);
+			}
+			spin_unlock_irqrestore(&cs->lock, flags);
+			return(0);
+		case CARD_TEST:
+			return(0);
+		case MDL_INFO_CONN:
+			if (cs->subtyp != SEDL_SPEEDFAX_PYRAMID)
+				return(0);
+			spin_lock_irqsave(&cs->lock, flags);
+			if ((long) arg)
+				cs->hw.sedl.reset_off &= ~SEDL_ISAR_PCI_LED2;
+			else
+				cs->hw.sedl.reset_off &= ~SEDL_ISAR_PCI_LED1;
+			byteout(cs->hw.sedl.cfg_reg +3, cs->hw.sedl.reset_off);
+			spin_unlock_irqrestore(&cs->lock, flags);
+			break;
+		case MDL_INFO_REL:
+			if (cs->subtyp != SEDL_SPEEDFAX_PYRAMID)
+				return(0);
+			spin_lock_irqsave(&cs->lock, flags);
+			if ((long) arg)
+				cs->hw.sedl.reset_off |= SEDL_ISAR_PCI_LED2;
+			else
+				cs->hw.sedl.reset_off |= SEDL_ISAR_PCI_LED1;
+			byteout(cs->hw.sedl.cfg_reg +3, cs->hw.sedl.reset_off);
+			spin_unlock_irqrestore(&cs->lock, flags);
+			break;
+	}
+	return(0);
 }
 
 static struct pci_dev *dev_sedl __devinitdata = NULL;
@@ -700,124 +526,308 @@ static struct isapnp_device_id sedl_ids[
 	{ 0, }
 };
 
-static struct isapnp_device_id *pdev = &sedl_ids[0];
+static struct isapnp_device_id *ipid __initdata = &sedl_ids[0];
 static struct pnp_card *pnp_c __devinitdata = NULL;
 #endif
 
 int __devinit
 setup_sedlbauer(struct IsdnCard *card)
 {
+	int bytecnt, ver, val;
 	struct IsdnCardState *cs = card->cs;
 	char tmp[64];
 	u16 sub_vendor_id, sub_id;
 
 	strcpy(tmp, Sedlbauer_revision);
-	printk(KERN_INFO "HiSax: Sedlbauer driver Rev. %s\n",
-	       HiSax_getrev(tmp));
+	printk(KERN_INFO "HiSax: Sedlbauer driver Rev. %s\n", HiSax_getrev(tmp));
 	
+ 	if (cs->typ == ISDN_CTYPE_SEDLBAUER) {
+ 		cs->subtyp = SEDL_SPEED_CARD_WIN;
+		cs->hw.sedl.bus = SEDL_BUS_ISA;
+		cs->hw.sedl.chip = SEDL_CHIP_TEST;
+ 	} else if (cs->typ == ISDN_CTYPE_SEDLBAUER_PCMCIA) {	
+ 		cs->subtyp = SEDL_SPEED_STAR;
+		cs->hw.sedl.bus = SEDL_BUS_PCMCIA;
+		cs->hw.sedl.chip = SEDL_CHIP_TEST;
+ 	} else if (cs->typ == ISDN_CTYPE_SEDLBAUER_FAX) {	
+ 		cs->subtyp = SEDL_SPEED_FAX;
+		cs->hw.sedl.bus = SEDL_BUS_ISA;
+		cs->hw.sedl.chip = SEDL_CHIP_ISAC_ISAR;
+ 	} else
+		return (0);
+
+	bytecnt = 8;
 	if (card->para[1]) {
-		if (cs->typ == ISDN_CTYPE_SEDLBAUER) {
-			if (sedl_card_win_probe(card->cs, card) < 0)
-				return 0;
-			return 1;
-		} else if (cs->typ == ISDN_CTYPE_SEDLBAUER_PCMCIA) {	
-			if (sedl_star_probe(card->cs, card) < 0)
-				return 0;
-			return 1;
-		} else if (cs->typ == ISDN_CTYPE_SEDLBAUER_FAX) {	
-			if (sedl_fax_probe(card->cs, card) < 0)
-				return 0;
-			return 1;
+		cs->hw.sedl.cfg_reg = card->para[1];
+		cs->irq = card->para[0];
+		if (cs->hw.sedl.chip == SEDL_CHIP_ISAC_ISAR) {
+			bytecnt = 16;
 		}
-	}
+	} else {
 #ifdef __ISAPNP__
-	if (isapnp_present()) {
-		struct pnp_card *pb;
-		struct pnp_dev *pd;
-		
-		while(pdev->card_vendor) {
-			if ((pb = pnp_find_card(pdev->card_vendor,
-						pdev->card_device,
-						pnp_c))) {
-				pnp_c = pb;
-				pd = NULL;
-				if ((pd = pnp_find_dev(pnp_c,
-						       pdev->vendor,
-						       pdev->function,
-						       pd))) {
-					printk(KERN_INFO "HiSax: %s detected\n",
-					       (char *)pdev->driver_data);
-					if (pnp_device_attach(pd) < 0) {
-						printk(KERN_ERR "Sedlbauer PnP: attach failed\n");
-						return 0;
-					}
-					if (pnp_activate_dev(pd) < 0) {
-						printk(KERN_ERR "Sedlbauer PnP: activate failed\n");
-						pnp_device_detach(pd);
-						return 0;
-					}
-					if (!pnp_irq_valid(pd, 0) || !pnp_port_valid(pd, 0)) {
-						printk(KERN_ERR "Sedlbauer PnP:some resources are missing %ld/%lx\n",
-						       pnp_irq(pd, 0), pnp_port_start(pd, 0));
-						pnp_device_detach(pd);
-						return 0;
-					}
-					card->para[1] = pnp_port_start(pd, 0);
-					card->para[0] = pnp_irq(pd, 0);
-					cs->hw.sedl.cfg_reg = card->para[1];
-					cs->irq = card->para[0];
-					if (pdev->function == ISAPNP_FUNCTION(0x2)) {
-						if (sedl_fax_probe(card->cs, card))
-							return 0;
-						return 1;
+		if (isapnp_present()) {
+			struct pnp_dev *pnp_d;
+			while(ipid->card_vendor) {
+				if ((pnp_c = pnp_find_card(ipid->card_vendor,
+					ipid->card_device, pnp_c))) {
+					pnp_d = NULL;
+					if ((pnp_d = pnp_find_dev(pnp_c,
+						ipid->vendor, ipid->function, pnp_d))) {
+						int err;
+
+						printk(KERN_INFO "HiSax: %s detected\n",
+							(char *)ipid->driver_data);
+						pnp_disable_dev(pnp_d);
+						err = pnp_activate_dev(pnp_d);
+						if (err<0) {
+							printk(KERN_WARNING "%s: pnp_activate_dev ret(%d)\n",
+								__FUNCTION__, err);
+							return(0);
+						}
+						card->para[1] = pnp_port_start(pnp_d, 0);
+						card->para[0] = pnp_irq(pnp_d, 0);
+
+						if (!card->para[0] || !card->para[1]) {
+							printk(KERN_ERR "Sedlbauer PnP:some resources are missing %ld/%lx\n",
+								card->para[0], card->para[1]);
+							pnp_disable_dev(pnp_d);
+							return(0);
+						}
+						cs->hw.sedl.cfg_reg = card->para[1];
+						cs->irq = card->para[0];
+						if (ipid->function == ISAPNP_FUNCTION(0x2)) {
+							cs->subtyp = SEDL_SPEED_FAX;
+							cs->hw.sedl.chip = SEDL_CHIP_ISAC_ISAR;
+							bytecnt = 16;
+						} else {
+							cs->subtyp = SEDL_SPEED_CARD_WIN;
+							cs->hw.sedl.chip = SEDL_CHIP_TEST;
+						}
+						goto ready;
 					} else {
-						if (sedl_card_win_probe(card->cs, card))
-							return 0;
-						return 1;
+						printk(KERN_ERR "Sedlbauer PnP: PnP error card found, no device\n");
+						return(0);
 					}
-				} else {
-					printk(KERN_ERR "Sedlbauer PnP: PnP error card found, no device\n");
-					return 0;
 				}
+				ipid++;
+				pnp_c = NULL;
+			} 
+			if (!ipid->card_vendor) {
+				printk(KERN_INFO "Sedlbauer PnP: no ISAPnP card found\n");
 			}
-			pdev++;
-			pnp_c=NULL;
-		} 
-		if (!pdev->card_vendor) {
-			printk(KERN_INFO "Sedlbauer PnP: no ISAPnP card found\n");
 		}
-	}
 #endif
 /* Probe for Sedlbauer speed pci */
-#ifdef CONFIG_PCI
-	dev_sedl = pci_find_device(PCI_VENDOR_ID_TIGERJET,
-				   PCI_DEVICE_ID_TIGERJET_100, dev_sedl);
-	if (dev_sedl) {
+#if CONFIG_PCI
+		if ((dev_sedl = pci_find_device(PCI_VENDOR_ID_TIGERJET,
+				PCI_DEVICE_ID_TIGERJET_100, dev_sedl))) {
+			if (pci_enable_device(dev_sedl))
+				return(0);
+			cs->irq = dev_sedl->irq;
+			if (!cs->irq) {
+				printk(KERN_WARNING "Sedlbauer: No IRQ for PCI card found\n");
+				return(0);
+			}
+			cs->hw.sedl.cfg_reg = pci_resource_start(dev_sedl, 0);
+		} else {
+			printk(KERN_WARNING "Sedlbauer: No PCI card found\n");
+			return(0);
+		}
+		cs->irq_flags |= SA_SHIRQ;
+		cs->hw.sedl.bus = SEDL_BUS_PCI;
 		sub_vendor_id = dev_sedl->subsystem_vendor;
 		sub_id = dev_sedl->subsystem_device;
 		printk(KERN_INFO "Sedlbauer: PCI subvendor:%x subid %x\n",
-		       sub_vendor_id, sub_id);
+			sub_vendor_id, sub_id);
+		printk(KERN_INFO "Sedlbauer: PCI base adr %#x\n",
+			cs->hw.sedl.cfg_reg);
 		if (sub_id != PCI_SUB_ID_SEDLBAUER) {
 			printk(KERN_ERR "Sedlbauer: unknown sub id %#x\n", sub_id);
-			return 0;
+			return(0);
 		}
 		if (sub_vendor_id == PCI_SUBVENDOR_SPEEDFAX_PYRAMID) {
-			if (sedl_fax_pyramid_probe(cs, dev_sedl))
-				return 0;
-			return 1;
+			cs->hw.sedl.chip = SEDL_CHIP_ISAC_ISAR;
+			cs->subtyp = SEDL_SPEEDFAX_PYRAMID;
 		} else if (sub_vendor_id == PCI_SUBVENDOR_SPEEDFAX_PCI) {
-			if (sedl_fax_pci_probe(cs, dev_sedl))
-				return 0;
-			return 1;
+			cs->hw.sedl.chip = SEDL_CHIP_ISAC_ISAR;
+			cs->subtyp = SEDL_SPEEDFAX_PCI;
+		} else if (sub_vendor_id == PCI_SUBVENDOR_HST_SAPHIR3) {
+			cs->hw.sedl.chip = SEDL_CHIP_IPAC;
+			cs->subtyp = HST_SAPHIR3;
 		} else if (sub_vendor_id == PCI_SUBVENDOR_SEDLBAUER_PCI) {
-			if (sedl_pci_probe(cs, dev_sedl))
-				return 0;
-			return 1;
+			cs->hw.sedl.chip = SEDL_CHIP_IPAC;
+			cs->subtyp = SEDL_SPEED_PCI;
+		} else {
+			printk(KERN_ERR "Sedlbauer: unknown sub vendor id %#x\n",
+				sub_vendor_id);
+			return(0);
 		}
-		printk(KERN_ERR "Sedlbauer: unknown sub vendor id %#x\n",
-		       sub_vendor_id);
-		return 0;
-	}
+		bytecnt = 256;
+		cs->hw.sedl.reset_on = SEDL_ISAR_PCI_ISAR_RESET_ON;
+		cs->hw.sedl.reset_off = SEDL_ISAR_PCI_ISAR_RESET_OFF;
+		byteout(cs->hw.sedl.cfg_reg, 0xff);
+		byteout(cs->hw.sedl.cfg_reg, 0x00);
+		byteout(cs->hw.sedl.cfg_reg+ 2, 0xdd);
+		byteout(cs->hw.sedl.cfg_reg+ 5, 0x02);
+		byteout(cs->hw.sedl.cfg_reg +3, cs->hw.sedl.reset_on);
+		mdelay(2);
+		byteout(cs->hw.sedl.cfg_reg +3, cs->hw.sedl.reset_off);
+		mdelay(10);
+#else
+		printk(KERN_WARNING "Sedlbauer: NO_PCI_BIOS\n");
+		return (0);
 #endif /* CONFIG_PCI */
-	return 0;
+	}	
+ready:	
+	/* In case of the sedlbauer pcmcia card, this region is in use,
+	 * reserved for us by the card manager. So we do not check it
+	 * here, it would fail.
+	 */
+	if (cs->hw.sedl.bus != SEDL_BUS_PCMCIA &&
+		!request_region(cs->hw.sedl.cfg_reg, bytecnt, "sedlbauer isdn")) {
+		printk(KERN_WARNING
+			"HiSax: %s config port %x-%x already in use\n",
+			CardType[card->typ],
+			cs->hw.sedl.cfg_reg,
+			cs->hw.sedl.cfg_reg + bytecnt);
+			return (0);
+	}
+
+	printk(KERN_INFO
+	       "Sedlbauer: defined at 0x%x-0x%x IRQ %d\n",
+	       cs->hw.sedl.cfg_reg,
+	       cs->hw.sedl.cfg_reg + bytecnt,
+	       cs->irq);
+
+	cs->BC_Read_Reg = &ReadHSCX;
+	cs->BC_Write_Reg = &WriteHSCX;
+	cs->BC_Send_Data = &hscx_fill_fifo;
+	cs->cardmsg = &Sedl_card_msg;
+
+/*
+ * testing ISA and PCMCIA Cards for IPAC, default is ISAC
+ * do not test for PCI card, because ports are different
+ * and PCI card uses only IPAC (for the moment)
+ */	
+	if (cs->hw.sedl.bus != SEDL_BUS_PCI) {
+		val = readreg(cs->hw.sedl.cfg_reg + SEDL_IPAC_ANY_ADR,
+			cs->hw.sedl.cfg_reg + SEDL_IPAC_ANY_IPAC, IPAC_ID);
+		printk(KERN_DEBUG "Sedlbauer: testing IPAC version %x\n", val);
+	        if ((val == 1) || (val == 2)) {
+			/* IPAC */
+			cs->subtyp = SEDL_SPEED_WIN2_PC104;
+			if (cs->hw.sedl.bus == SEDL_BUS_PCMCIA) {
+				cs->subtyp = SEDL_SPEED_STAR2;
+			}
+			cs->hw.sedl.chip = SEDL_CHIP_IPAC;
+		} else {
+			/* ISAC_HSCX oder ISAC_ISAR */
+			if (cs->hw.sedl.chip == SEDL_CHIP_TEST) {
+				cs->hw.sedl.chip = SEDL_CHIP_ISAC_HSCX;
+			}
+		}
+	}
+
+/*
+ * hw.sedl.chip is now properly set
+ */
+	printk(KERN_INFO "Sedlbauer: %s detected\n",
+		Sedlbauer_Types[cs->subtyp]);
+
+	setup_isac(cs);
+	if (cs->hw.sedl.chip == SEDL_CHIP_IPAC) {
+		if (cs->hw.sedl.bus == SEDL_BUS_PCI) {
+	                cs->hw.sedl.adr  = cs->hw.sedl.cfg_reg + SEDL_IPAC_PCI_ADR;
+			cs->hw.sedl.isac = cs->hw.sedl.cfg_reg + SEDL_IPAC_PCI_IPAC;
+			cs->hw.sedl.hscx = cs->hw.sedl.cfg_reg + SEDL_IPAC_PCI_IPAC;
+		} else {
+	                cs->hw.sedl.adr  = cs->hw.sedl.cfg_reg + SEDL_IPAC_ANY_ADR;
+			cs->hw.sedl.isac = cs->hw.sedl.cfg_reg + SEDL_IPAC_ANY_IPAC;
+			cs->hw.sedl.hscx = cs->hw.sedl.cfg_reg + SEDL_IPAC_ANY_IPAC;
+		}
+		test_and_set_bit(HW_IPAC, &cs->HW_Flags);
+		cs->readisac = &ReadISAC_IPAC;
+		cs->writeisac = &WriteISAC_IPAC;
+		cs->readisacfifo = &ReadISACfifo_IPAC;
+		cs->writeisacfifo = &WriteISACfifo_IPAC;
+		cs->irq_func = &sedlbauer_interrupt_ipac;
+		val = readreg(cs->hw.sedl.adr, cs->hw.sedl.isac, IPAC_ID);
+		printk(KERN_INFO "Sedlbauer: IPAC version %x\n", val);
+	} else {
+		/* ISAC_HSCX oder ISAC_ISAR */
+		cs->readisac = &ReadISAC;
+		cs->writeisac = &WriteISAC;
+		cs->readisacfifo = &ReadISACfifo;
+		cs->writeisacfifo = &WriteISACfifo;
+		if (cs->hw.sedl.chip == SEDL_CHIP_ISAC_ISAR) {
+			if (cs->hw.sedl.bus == SEDL_BUS_PCI) {
+				cs->hw.sedl.adr = cs->hw.sedl.cfg_reg +
+							SEDL_ISAR_PCI_ADR;
+				cs->hw.sedl.isac = cs->hw.sedl.cfg_reg +
+							SEDL_ISAR_PCI_ISAC;
+				cs->hw.sedl.hscx = cs->hw.sedl.cfg_reg +
+							SEDL_ISAR_PCI_ISAR;
+			} else {
+				cs->hw.sedl.adr = cs->hw.sedl.cfg_reg +
+							SEDL_ISAR_ISA_ADR;
+				cs->hw.sedl.isac = cs->hw.sedl.cfg_reg +
+							SEDL_ISAR_ISA_ISAC;
+				cs->hw.sedl.hscx = cs->hw.sedl.cfg_reg +
+							SEDL_ISAR_ISA_ISAR;
+				cs->hw.sedl.reset_on = cs->hw.sedl.cfg_reg +
+							SEDL_ISAR_ISA_ISAR_RESET_ON;
+				cs->hw.sedl.reset_off = cs->hw.sedl.cfg_reg +
+							SEDL_ISAR_ISA_ISAR_RESET_OFF;
+			}
+			cs->bcs[0].hw.isar.reg = &cs->hw.sedl.isar;
+			cs->bcs[1].hw.isar.reg = &cs->hw.sedl.isar;
+			test_and_set_bit(HW_ISAR, &cs->HW_Flags);
+			cs->irq_func = &sedlbauer_interrupt_isar;
+			cs->auxcmd = &isar_auxcmd;
+			ISACVersion(cs, "Sedlbauer:");
+			cs->BC_Read_Reg = &ReadISAR;
+			cs->BC_Write_Reg = &WriteISAR;
+			cs->BC_Send_Data = &isar_fill_fifo;
+			bytecnt = 3;
+			while (bytecnt) {
+				ver = ISARVersion(cs, "Sedlbauer:");
+				if (ver < 0)
+					printk(KERN_WARNING
+						"Sedlbauer: wrong ISAR version (ret = %d)\n", ver);
+				else
+					break;
+				reset_sedlbauer(cs);
+				bytecnt--;
+			}
+			if (!bytecnt) {
+				release_io_sedlbauer(cs);
+				return (0);
+			}
+		} else {
+			if (cs->hw.sedl.bus == SEDL_BUS_PCMCIA) {
+				cs->hw.sedl.adr = cs->hw.sedl.cfg_reg + SEDL_HSCX_PCMCIA_ADR;
+				cs->hw.sedl.isac = cs->hw.sedl.cfg_reg + SEDL_HSCX_PCMCIA_ISAC;
+				cs->hw.sedl.hscx = cs->hw.sedl.cfg_reg + SEDL_HSCX_PCMCIA_HSCX;
+				cs->hw.sedl.reset_on = cs->hw.sedl.cfg_reg + SEDL_HSCX_PCMCIA_RESET;
+				cs->hw.sedl.reset_off = cs->hw.sedl.cfg_reg + SEDL_HSCX_PCMCIA_RESET;
+				cs->irq_flags |= SA_SHIRQ;
+			} else {
+				cs->hw.sedl.adr = cs->hw.sedl.cfg_reg + SEDL_HSCX_ISA_ADR;
+				cs->hw.sedl.isac = cs->hw.sedl.cfg_reg + SEDL_HSCX_ISA_ISAC;
+				cs->hw.sedl.hscx = cs->hw.sedl.cfg_reg + SEDL_HSCX_ISA_HSCX;
+				cs->hw.sedl.reset_on = cs->hw.sedl.cfg_reg + SEDL_HSCX_ISA_RESET_ON;
+				cs->hw.sedl.reset_off = cs->hw.sedl.cfg_reg + SEDL_HSCX_ISA_RESET_OFF;
+			}
+			cs->irq_func = &sedlbauer_interrupt;
+			ISACVersion(cs, "Sedlbauer:");
+		
+			if (HscxVersion(cs, "Sedlbauer:")) {
+				printk(KERN_WARNING
+					"Sedlbauer: wrong HSCX versions check IO address\n");
+				release_io_sedlbauer(cs);
+				return (0);
+			}
+		}
+	}
+	return (1);
 }
--- diff/drivers/isdn/hisax/sedlbauer_cs.c	2004-02-09 10:36:10.000000000 +0000
+++ source/drivers/isdn/hisax/sedlbauer_cs.c	2004-02-23 13:56:42.000000000 +0000
@@ -53,6 +53,7 @@
 #include <pcmcia/cistpl.h>
 #include <pcmcia/cisreg.h>
 #include <pcmcia/ds.h>
+#include "hisax_cfg.h"
 
 MODULE_DESCRIPTION("ISDN4Linux: PCMCIA client driver for Sedlbauer cards");
 MODULE_AUTHOR("Marcus Niemann");
@@ -93,8 +94,6 @@ MODULE_PARM(irq_list, "1-4i");
 static int protocol = 2;        /* EURO-ISDN Default */
 MODULE_PARM(protocol, "i");
 
-extern int sedl_init_pcmcia(int, int, int*, int);
-
 /*====================================================================*/
 
 /*
@@ -176,6 +175,7 @@ typedef struct local_info_t {
     dev_link_t		link;
     dev_node_t		node;
     int			stop;
+    int			cardnr;
 } local_info_t;
 
 /*======================================================================
@@ -203,6 +203,7 @@ static dev_link_t *sedlbauer_attach(void
     local = kmalloc(sizeof(local_info_t), GFP_KERNEL);
     if (!local) return NULL;
     memset(local, 0, sizeof(local_info_t));
+    local->cardnr = -1;
     link = &local->link; link->priv = local;
     
     /* Interrupt setup */
@@ -324,7 +325,7 @@ static void sedlbauer_config(dev_link_t 
     config_info_t conf;
     win_req_t req;
     memreq_t map;
-    
+    IsdnCard_t  icard;
 
     DEBUG(0, "sedlbauer_config(0x%p)\n", link);
 
@@ -509,10 +510,19 @@ static void sedlbauer_config(dev_link_t 
     printk("\n");
     
     link->state &= ~DEV_CONFIG_PENDING;
- 
-    sedl_init_pcmcia(link->io.BasePort1, link->irq.AssignedIRQ,
-                     &(((local_info_t*)link->priv)->stop),
-                     protocol);
+
+    icard.para[0] = link->irq.AssignedIRQ;
+    icard.para[1] = link->io.BasePort1;
+    icard.protocol = protocol;
+    icard.typ = ISDN_CTYPE_SEDLBAUER_PCMCIA;
+    
+    last_ret = hisax_init_pcmcia(link, &(((local_info_t*)link->priv)->stop), &icard);
+    if (last_ret < 0) {
+    	printk(KERN_ERR "sedlbauer_cs: failed to initialize SEDLBAUER PCMCIA %d at i/o %#x\n",
+    		last_ret, link->io.BasePort1);
+    	sedlbauer_release(link);
+    } else
+    	((local_info_t*)link->priv)->cardnr = last_ret;
 
     return;
 
@@ -532,8 +542,15 @@ cs_failed:
 
 static void sedlbauer_release(dev_link_t *link)
 {
+    local_info_t *local = link->priv;
     DEBUG(0, "sedlbauer_release(0x%p)\n", link);
 
+    if (local) {
+    	if (local->cardnr >= 0) {
+    	    /* no unregister function with hisax */
+	    HiSax_closecard(local->cardnr);
+	}
+    }
     /* Unlink the device chain */
     link->dev = NULL;
 
--- diff/drivers/isdn/hisax/sportster.c	2003-05-21 11:50:15.000000000 +0100
+++ source/drivers/isdn/hisax/sportster.c	2004-02-23 13:56:42.000000000 +0000
@@ -1,4 +1,4 @@
-/* $Id: sportster.c,v 1.14.6.2 2001/09/23 22:24:51 kai Exp $
+/* $Id: sportster.c,v 1.16.2.4 2004/01/13 23:48:39 keil Exp $
  *
  * low level stuff for USR Sportster internal TA
  *
@@ -19,7 +19,7 @@
 #include "isdnl1.h"
 
 extern const char *CardType[];
-const char *sportster_revision = "$Revision: 1.14.6.2 $";
+const char *sportster_revision = "$Revision: 1.16.2.4 $";
 
 #define byteout(addr,val) outb(val,addr)
 #define bytein(addr) inb(addr)
@@ -38,91 +38,102 @@ calc_off(unsigned int base, unsigned int
 }
 
 static inline void
-read_fifo(unsigned int adr, u8 * data, int size)
+read_fifo(unsigned int adr, u_char * data, int size)
 {
 	insb(adr, data, size);
 }
 
 static void
-write_fifo(unsigned int adr, u8 * data, int size)
+write_fifo(unsigned int adr, u_char * data, int size)
 {
 	outsb(adr, data, size);
 }
 
-static u8
-isac_read(struct IsdnCardState *cs, u8 offset)
+/* Interface functions */
+
+static u_char
+ReadISAC(struct IsdnCardState *cs, u_char offset)
 {
-	return bytein(calc_off(cs->hw.spt.isac, offset));
+	return (bytein(calc_off(cs->hw.spt.isac, offset)));
 }
 
 static void
-isac_write(struct IsdnCardState *cs, u8 offset, u8 value)
+WriteISAC(struct IsdnCardState *cs, u_char offset, u_char value)
 {
 	byteout(calc_off(cs->hw.spt.isac, offset), value);
 }
 
 static void
-isac_read_fifo(struct IsdnCardState *cs, u8 * data, int size)
+ReadISACfifo(struct IsdnCardState *cs, u_char * data, int size)
 {
 	read_fifo(cs->hw.spt.isac, data, size);
 }
 
 static void
-isac_write_fifo(struct IsdnCardState *cs, u8 * data, int size)
+WriteISACfifo(struct IsdnCardState *cs, u_char * data, int size)
 {
 	write_fifo(cs->hw.spt.isac, data, size);
 }
 
-static struct dc_hw_ops isac_ops = {
-	.read_reg   = isac_read,
-	.write_reg  = isac_write,
-	.read_fifo  = isac_read_fifo,
-	.write_fifo = isac_write_fifo,
-};
-
-static u8
-hscx_read(struct IsdnCardState *cs, int hscx, u8 offset)
+static u_char
+ReadHSCX(struct IsdnCardState *cs, int hscx, u_char offset)
 {
-	return bytein(calc_off(cs->hw.spt.hscx[hscx], offset));
+	return (bytein(calc_off(cs->hw.spt.hscx[hscx], offset)));
 }
 
 static void
-hscx_write(struct IsdnCardState *cs, int hscx, u8 offset, u8 value)
+WriteHSCX(struct IsdnCardState *cs, int hscx, u_char offset, u_char value)
 {
 	byteout(calc_off(cs->hw.spt.hscx[hscx], offset), value);
 }
 
-static void
-hscx_read_fifo(struct IsdnCardState *cs, int hscx, u8 *data, int size)
-{
-	read_fifo(cs->hw.spt.hscx[hscx], data, size);
-}
+/*
+ * fast interrupt HSCX stuff goes here
+ */
 
-static void
-hscx_write_fifo(struct IsdnCardState *cs, int hscx, u8 *data, int size)
-{
-	write_fifo(cs->hw.spt.hscx[hscx], data, size);
-}
+#define READHSCX(cs, nr, reg) bytein(calc_off(cs->hw.spt.hscx[nr], reg))
+#define WRITEHSCX(cs, nr, reg, data) byteout(calc_off(cs->hw.spt.hscx[nr], reg), data)
+#define READHSCXFIFO(cs, nr, ptr, cnt) read_fifo(cs->hw.spt.hscx[nr], ptr, cnt)
+#define WRITEHSCXFIFO(cs, nr, ptr, cnt) write_fifo(cs->hw.spt.hscx[nr], ptr, cnt)
 
-static struct bc_hw_ops hscx_ops = {
-	.read_reg   = hscx_read,
-	.write_reg  = hscx_write,
-	.read_fifo  = hscx_read_fifo,
-	.write_fifo = hscx_write_fifo,
-};
+#include "hscx_irq.c"
 
 static irqreturn_t
 sportster_interrupt(int intno, void *dev_id, struct pt_regs *regs)
 {
 	struct IsdnCardState *cs = dev_id;
+	u_char val;
+	u_long flags;
 
-	hscxisac_irq(intno, dev_id, regs);
+	spin_lock_irqsave(&cs->lock, flags);
+	val = READHSCX(cs, 1, HSCX_ISTA);
+      Start_HSCX:
+	if (val)
+		hscx_int_main(cs, val);
+	val = ReadISAC(cs, ISAC_ISTA);
+      Start_ISAC:
+	if (val)
+		isac_interrupt(cs, val);
+	val = READHSCX(cs, 1, HSCX_ISTA);
+	if (val) {
+		if (cs->debug & L1_DEB_HSCX)
+			debugl1(cs, "HSCX IntStat after IntRoutine");
+		goto Start_HSCX;
+	}
+	val = ReadISAC(cs, ISAC_ISTA);
+	if (val) {
+		if (cs->debug & L1_DEB_ISAC)
+			debugl1(cs, "ISAC IntStat after IntRoutine");
+		goto Start_ISAC;
+	}
+	/* get a new irq impulse if there any pending */
 	bytein(cs->hw.spt.cfg_reg + SPORTSTER_RES_IRQ +1);
+	spin_unlock_irqrestore(&cs->lock, flags);
 	return IRQ_HANDLED;
 }
 
-static void
-sportster_release(struct IsdnCardState *cs)
+void
+release_io_sportster(struct IsdnCardState *cs)
 {
 	int i, adr;
 
@@ -133,45 +144,50 @@ sportster_release(struct IsdnCardState *
 	}
 }
 
-static int
-sportster_reset(struct IsdnCardState *cs)
+void
+reset_sportster(struct IsdnCardState *cs)
 {
 	cs->hw.spt.res_irq |= SPORTSTER_RESET; /* Reset On */
 	byteout(cs->hw.spt.cfg_reg + SPORTSTER_RES_IRQ, cs->hw.spt.res_irq);
-	set_current_state(TASK_UNINTERRUPTIBLE);
-	schedule_timeout((10*HZ)/1000);
+	mdelay(10);
 	cs->hw.spt.res_irq &= ~SPORTSTER_RESET; /* Reset Off */
 	byteout(cs->hw.spt.cfg_reg + SPORTSTER_RES_IRQ, cs->hw.spt.res_irq);
-	set_current_state(TASK_UNINTERRUPTIBLE);
-	schedule_timeout((10*HZ)/1000);
-	return 0;
+	mdelay(10);
 }
 
 static int
 Sportster_card_msg(struct IsdnCardState *cs, int mt, void *arg)
 {
-	return(0);
-}
+	u_long flags;
 
-static void
-sportster_init(struct IsdnCardState *cs)
-{
-	inithscxisac(cs);
-	cs->hw.spt.res_irq |= SPORTSTER_INTE; /* IRQ On */
-	byteout(cs->hw.spt.cfg_reg + SPORTSTER_RES_IRQ, cs->hw.spt.res_irq);
+	switch (mt) {
+		case CARD_RESET:
+			spin_lock_irqsave(&cs->lock, flags);
+			reset_sportster(cs);
+			spin_unlock_irqrestore(&cs->lock, flags);
+			return(0);
+		case CARD_RELEASE:
+			release_io_sportster(cs);
+			return(0);
+		case CARD_INIT:
+			spin_lock_irqsave(&cs->lock, flags);
+			reset_sportster(cs);
+			inithscxisac(cs, 1);
+			cs->hw.spt.res_irq |= SPORTSTER_INTE; /* IRQ On */
+			byteout(cs->hw.spt.cfg_reg + SPORTSTER_RES_IRQ, cs->hw.spt.res_irq);
+			inithscxisac(cs, 2);
+			spin_unlock_irqrestore(&cs->lock, flags);
+			return(0);
+		case CARD_TEST:
+			return(0);
+	}
+	return(0);
 }
 
-static struct card_ops sportster_ops = {
-	.init     = sportster_init,
-	.reset    = sportster_reset,
-	.release  = sportster_release,
-	.irq_func = sportster_interrupt,
-};
-
 static int __init
 get_io_range(struct IsdnCardState *cs)
 {
-	int i, adr;
+	int i, j, adr;
 	
 	for (i=0;i<64;i++) {
 		adr = cs->hw.spt.cfg_reg + i *1024;
@@ -179,65 +195,76 @@ get_io_range(struct IsdnCardState *cs)
 			printk(KERN_WARNING
 				"HiSax: %s config port %x-%x already in use\n",
 				CardType[cs->typ], adr, adr + 8);
-			goto err;
-		}
+			break;
+		} 
 	}
-	return 1;
- err:
-	for (i=i-1; i >= 0; i--) {
-		adr = cs->hw.spt.cfg_reg + i *1024;
-		release_region(adr, 8);
+	if (i==64)
+		return(1);
+	else {
+		for (j=0; j<i; j++) {
+			adr = cs->hw.spt.cfg_reg + j *1024;
+			release_region(adr, 8);
+		}
+		return(0);
 	}
-	return 0;
 }
 
-static int __init
-sportster_probe(struct IsdnCardState *cs, struct IsdnCard *card)
+int __init
+setup_sportster(struct IsdnCard *card)
 {
-	cs->irq = card->para[0];
+	struct IsdnCardState *cs = card->cs;
+	char tmp[64];
+
+	strcpy(tmp, sportster_revision);
+	printk(KERN_INFO "HiSax: USR Sportster driver Rev. %s\n", HiSax_getrev(tmp));
+	if (cs->typ != ISDN_CTYPE_SPORTSTER)
+		return (0);
+
 	cs->hw.spt.cfg_reg = card->para[1];
+	cs->irq = card->para[0];
 	if (!get_io_range(cs))
-		return -EBUSY;
+		return (0);
 	cs->hw.spt.isac = cs->hw.spt.cfg_reg + SPORTSTER_ISAC;
 	cs->hw.spt.hscx[0] = cs->hw.spt.cfg_reg + SPORTSTER_HSCXA;
 	cs->hw.spt.hscx[1] = cs->hw.spt.cfg_reg + SPORTSTER_HSCXB;
 	
 	switch(cs->irq) {
-	case 5:	cs->hw.spt.res_irq = 1;	break;
-	case 7:	cs->hw.spt.res_irq = 2;	break;
-	case 10:cs->hw.spt.res_irq = 3;	break;
-	case 11:cs->hw.spt.res_irq = 4;	break;
-	case 12:cs->hw.spt.res_irq = 5;	break;
-	case 14:cs->hw.spt.res_irq = 6;	break;
-	case 15:cs->hw.spt.res_irq = 7;	break;
-	default:
-		printk(KERN_WARNING "Sportster: wrong IRQ\n");
-		goto err;
+		case 5:	cs->hw.spt.res_irq = 1;
+			break;
+		case 7:	cs->hw.spt.res_irq = 2;
+			break;
+		case 10:cs->hw.spt.res_irq = 3;
+			break;
+		case 11:cs->hw.spt.res_irq = 4;
+			break;
+		case 12:cs->hw.spt.res_irq = 5;
+			break;
+		case 14:cs->hw.spt.res_irq = 6;
+			break;
+		case 15:cs->hw.spt.res_irq = 7;
+			break;
+		default:release_io_sportster(cs);
+			printk(KERN_WARNING "Sportster: wrong IRQ\n");
+			return(0);
 	}
-	sportster_reset(cs);
 	printk(KERN_INFO "HiSax: %s config irq:%d cfg:0x%X\n",
-	       CardType[cs->typ], cs->irq, cs->hw.spt.cfg_reg);
-
+		CardType[cs->typ], cs->irq, cs->hw.spt.cfg_reg);
+	setup_isac(cs);
+	cs->readisac = &ReadISAC;
+	cs->writeisac = &WriteISAC;
+	cs->readisacfifo = &ReadISACfifo;
+	cs->writeisacfifo = &WriteISACfifo;
+	cs->BC_Read_Reg = &ReadHSCX;
+	cs->BC_Write_Reg = &WriteHSCX;
+	cs->BC_Send_Data = &hscx_fill_fifo;
 	cs->cardmsg = &Sportster_card_msg;
-	cs->card_ops = &sportster_ops;
-	if (hscxisac_setup(cs, &isac_ops, &hscx_ops))
-		goto err;
-	return 0;
- err:
-	sportster_release(cs);
-	return -EBUSY;
-}
-
-int __init
-setup_sportster(struct IsdnCard *card)
-{
-	char tmp[64];
-
-	strcpy(tmp, sportster_revision);
-	printk(KERN_INFO "HiSax: USR Sportster driver Rev. %s\n",
-	       HiSax_getrev(tmp));
-
-	if (sportster_probe(card->cs, card) < 0)
-		return 0;
-	return 1;
+	cs->irq_func = &sportster_interrupt;
+	ISACVersion(cs, "Sportster:");
+	if (HscxVersion(cs, "Sportster:")) {
+		printk(KERN_WARNING
+		       "Sportster: wrong HSCX versions check IO address\n");
+		release_io_sportster(cs);
+		return (0);
+	}
+	return (1);
 }
--- diff/drivers/isdn/hisax/st5481.h	2003-01-13 14:18:15.000000000 +0000
+++ source/drivers/isdn/hisax/st5481.h	2004-02-23 13:56:42.000000000 +0000
@@ -219,15 +219,15 @@ enum {
 #define L1_EVENT_COUNT (EV_TIMER3 + 1)
 
 #define ERR(format, arg...) \
-printk(KERN_ERR __FILE__ ": %s: " format "\n" , __FUNCTION__ , ## arg)
+printk(KERN_ERR "%s:%s: " format "\n" , __FILE__,  __FUNCTION__ , ## arg)
 
 #define WARN(format, arg...) \
-printk(KERN_WARNING __FILE__ ": %s: " format "\n" , __FUNCTION__ , ## arg)
+printk(KERN_WARNING "%s:%s: " format "\n" , __FILE__,  __FUNCTION__ , ## arg)
 
 #define INFO(format, arg...) \
-printk(KERN_INFO __FILE__ ": %s: " format "\n" , __FUNCTION__ , ## arg)
+printk(KERN_INFO "%s:%s: " format "\n" , __FILE__,  __FUNCTION__ , ## arg)
 
-#include "st5481_hdlc.h"
+#include "isdnhdlc.h"
 #include "fsm.h"
 #include "hisax_if.h"
 #include <linux/skbuff.h>
@@ -236,9 +236,9 @@ printk(KERN_INFO __FILE__ ": %s: " forma
  * FIFO handling
  */
 
-/* Generic FIFO structure */ 
+/* Generic FIFO structure */
 struct fifo {
-	u8 r,w,count,size;
+	u_char r,w,count,size;
 	spinlock_t lock;
 };
 
@@ -270,7 +270,7 @@ static inline int fifo_add(struct fifo *
 		index = -1;
 	} else {
 		// Return index where to get the next data to add to the FIFO
-		index = fifo->w++ & (fifo->size-1); 
+		index = fifo->w++ & (fifo->size-1);
 		fifo->count++;
 	}
 	spin_unlock_irqrestore(&fifo->lock, flags);
@@ -289,13 +289,13 @@ static inline int fifo_remove(struct fif
 		return -1;
 	}
 
-	spin_lock_irqsave(&fifo->lock, flags);		
+	spin_lock_irqsave(&fifo->lock, flags);
 	if (!fifo->count) {
 		// FIFO empty
 		index = -1;
 	} else {
 		// Return index where to get the next data from the FIFO
-		index = fifo->r++ & (fifo->size-1); 
+		index = fifo->r++ & (fifo->size-1);
 		fifo->count--;
 	}
 	spin_unlock_irqrestore(&fifo->lock, flags);
@@ -336,7 +336,7 @@ struct st5481_intr {
 };
 
 struct st5481_d_out {
-	struct hdlc_vars hdlc_state;
+	struct isdnhdlc_vars hdlc_state;
 	struct urb *urb[2]; /* double buffering */
 	unsigned long busy;
 	struct sk_buff *tx_skb;
@@ -344,15 +344,15 @@ struct st5481_d_out {
 };
 
 struct st5481_b_out {
-	struct hdlc_vars hdlc_state;
+	struct isdnhdlc_vars hdlc_state;
 	struct urb *urb[2]; /* double buffering */
-	u8 flow_event;
+	u_char flow_event;
 	u_long busy;
 	struct sk_buff *tx_skb;
 };
 
 struct st5481_in {
-	struct hdlc_vars hdlc_state;
+	struct isdnhdlc_vars hdlc_state;
 	struct urb *urb[2]; /* double buffering */
 	int mode;
 	int bufsize;
@@ -452,7 +452,7 @@ void st5481_release_isocpipes(struct urb
 
 int  st5481_isoc_flatten(struct urb *urb);
 void st5481_usb_pipe_reset(struct st5481_adapter *adapter,
-		    u8 pipe, ctrl_complete_t complete, void *context);
+		    u_char pipe, ctrl_complete_t complete, void *context);
 void st5481_usb_ctrl_msg(struct st5481_adapter *adapter,
 		  u8 request, u8 requesttype, u16 value, u16 index,
 		  ctrl_complete_t complete, void *context);
@@ -482,7 +482,7 @@ dump_iso_packet(const char *name, struct
 {
 	int i,j;
 	int len,ofs;
-	u8 *data;
+	u_char *data;
 
 	printk(KERN_DEBUG "%s: packets=%d,errors=%d\n",
 	       name,urb->number_of_packets,urb->error_count);
--- diff/drivers/isdn/hisax/st5481_b.c	2003-09-17 12:28:06.000000000 +0100
+++ source/drivers/isdn/hisax/st5481_b.c	2004-02-23 13:56:42.000000000 +0000
@@ -31,9 +31,9 @@ static void usb_b_out(struct st5481_bcs 
 	struct st5481_b_out *b_out = &bcs->b_out;
 	struct st5481_adapter *adapter = bcs->adapter;
 	struct urb *urb;
-	u_int packet_size, bytes_sent;
-	int len, offset, buf_size;
-	u_int i;
+	unsigned int packet_size,offset;
+	int len,buf_size,bytes_sent;
+	int i;
 	struct sk_buff *skb;
 	
 	if (test_and_set_bit(buf_nr, &b_out->busy)) {
@@ -67,22 +67,31 @@ static void usb_b_out(struct st5481_bcs 
 				bytes_sent = buf_size - len;
 				if (skb->len < bytes_sent)
 					bytes_sent = skb->len;
-
-				memcpy(urb->transfer_buffer+len, skb->data, bytes_sent);
-				
+				{	/* swap tx bytes to get hearable audio data */
+					register unsigned char *src  = skb->data;
+					register unsigned char *dest = urb->transfer_buffer+len;
+					register unsigned int count;
+					for (count = 0; count < bytes_sent; count++)
+						*dest++ = isdnhdlc_bit_rev_tab[*src++];
+				}
 				len += bytes_sent;
 			} else {
-				len += hdlc_encode(&b_out->hdlc_state, 
-						   skb->data, skb->len, &bytes_sent,
-						   urb->transfer_buffer+len, buf_size-len);
+				len += isdnhdlc_encode(&b_out->hdlc_state,
+						       skb->data, skb->len, &bytes_sent,
+						       urb->transfer_buffer+len, buf_size-len);
 			}
 
 			skb_pull(skb, bytes_sent);
-			
+
 			if (!skb->len) {
 				// Frame sent
 				b_out->tx_skb = NULL;
-				B_L1L2(bcs, PH_DATA | CONFIRM, skb);
+				B_L1L2(bcs, PH_DATA | CONFIRM, (void *) skb->truesize);
+				dev_kfree_skb_any(skb);
+
+/* 				if (!(bcs->tx_skb = skb_dequeue(&bcs->sq))) { */
+/* 					st5481B_sched_event(bcs, B_XMTBUFREADY); */
+/* 				} */
 			}
 		} else {
 			if (bcs->mode == L1_MODE_TRANS) {
@@ -90,9 +99,9 @@ static void usb_b_out(struct st5481_bcs 
 				len = buf_size;
 			} else {
 				// Send flags
-				len += hdlc_encode(&b_out->hdlc_state, 
-						   NULL, 0, &bytes_sent,
-						   urb->transfer_buffer+len, buf_size-len);
+				len += isdnhdlc_encode(&b_out->hdlc_state,
+						       NULL, 0, &bytes_sent,
+						       urb->transfer_buffer+len, buf_size-len);
 			}
 		}	
 	}
@@ -136,7 +145,7 @@ static void st5481B_start_xfer(void *con
  */
 static void led_blink(struct st5481_adapter *adapter)
 {
-	u8 leds = adapter->leds;
+	u_char leds = adapter->leds;
 
 	// 50 frames/sec for each channel
 	if (++adapter->led_counter % 50) {
@@ -204,7 +213,7 @@ static void st5481B_mode(struct st5481_b
 	if (bcs->mode != L1_MODE_NULL) {
 		// Open the B channel
 		if (bcs->mode != L1_MODE_TRANS) {
-			hdlc_out_init(&b_out->hdlc_state, 0, bcs->mode == L1_MODE_HDLC_56K);
+			isdnhdlc_out_init(&b_out->hdlc_state, 0, bcs->mode == L1_MODE_HDLC_56K);
 		}
 		st5481_usb_pipe_reset(adapter, (bcs->channel+1)*2, NULL, NULL);
 	
@@ -260,7 +269,7 @@ static int st5481_setup_b_out(struct st5
 	endpoint = &altsetting->endpoint[EP_B1_OUT - 1 + bcs->channel * 2];
 
 	DBG(4,"endpoint address=%02x,packet size=%d",
-	    endpoint->desc.bEndpointAddress,endpoint->desc.wMaxPacketSize);
+	    endpoint->desc.bEndpointAddress, endpoint->desc.wMaxPacketSize);
 
 	// Allocate memory for 8000bytes/sec + extra bytes if underrun
 	return st5481_setup_isocpipes(b_out->urb, dev, 
--- diff/drivers/isdn/hisax/st5481_d.c	2003-09-17 12:28:06.000000000 +0100
+++ source/drivers/isdn/hisax/st5481_d.c	2004-02-23 13:56:42.000000000 +0000
@@ -294,8 +294,8 @@ static void usb_d_out(struct st5481_adap
 {
 	struct st5481_d_out *d_out = &adapter->d_out;
 	struct urb *urb;
-	unsigned int num_packets;
-	int len, buf_size, bytes_sent, packet_offset;
+	unsigned int num_packets, packet_offset;
+	int len, buf_size, bytes_sent;
 	struct sk_buff *skb;
 	struct usb_iso_packet_descriptor *desc;
 
@@ -313,15 +313,15 @@ static void usb_d_out(struct st5481_adap
 	buf_size = NUM_ISO_PACKETS_D * SIZE_ISO_PACKETS_D_OUT;
 	
 	if (skb) {
-		len = hdlc_encode(&d_out->hdlc_state, 
-				  skb->data, skb->len, &bytes_sent,
-				  urb->transfer_buffer, buf_size);
+		len = isdnhdlc_encode(&d_out->hdlc_state,
+				      skb->data, skb->len, &bytes_sent,
+				      urb->transfer_buffer, buf_size);
 		skb_pull(skb,bytes_sent);
 	} else {
 		// Send flags or idle
-		len = hdlc_encode(&d_out->hdlc_state, 
-				  NULL, 0, &bytes_sent,
-				  urb->transfer_buffer, buf_size);
+		len = isdnhdlc_encode(&d_out->hdlc_state,
+				      NULL, 0, &bytes_sent,
+				      urb->transfer_buffer, buf_size);
 	}
 	
 	if (len < buf_size) {
@@ -341,7 +341,7 @@ static void usb_d_out(struct st5481_adap
 		desc = &urb->iso_frame_desc[num_packets];
 		desc->offset = packet_offset;
 		desc->length = SIZE_ISO_PACKETS_D_OUT;
-		if (len - packet_offset < (int)desc->length)
+		if (len - packet_offset < desc->length)
 			desc->length = len - packet_offset;
 		num_packets++;
 		packet_offset += desc->length;
@@ -413,7 +413,7 @@ static void dout_start_xmit(struct FsmIn
 
 	DBG(2,"len=%d",skb->len);
 
-	hdlc_out_init(&d_out->hdlc_state, 1, 0);
+	isdnhdlc_out_init(&d_out->hdlc_state, 1, 0);
 
 	if (test_and_set_bit(buf_nr, &d_out->busy)) {
 		WARN("ep %d urb %d busy %#lx", EP_D_OUT, buf_nr, d_out->busy);
@@ -422,9 +422,9 @@ static void dout_start_xmit(struct FsmIn
 	urb = d_out->urb[buf_nr];
 
 	DBG_SKB(0x10, skb);
-	len = hdlc_encode(&d_out->hdlc_state, 
-			  skb->data, skb->len, &bytes_sent,
-			  urb->transfer_buffer, 16);
+	len = isdnhdlc_encode(&d_out->hdlc_state,
+			      skb->data, skb->len, &bytes_sent,
+			      urb->transfer_buffer, 16);
 	skb_pull(skb, bytes_sent);
 
 	if(len < 16)
@@ -664,7 +664,7 @@ static int __devinit st5481_setup_d_out(
 	endpoint = &altsetting->endpoint[EP_D_OUT-1];
 
 	DBG(2,"endpoint address=%02x,packet size=%d",
-	    endpoint->desc.bEndpointAddress,endpoint->desc.wMaxPacketSize);
+	    endpoint->desc.bEndpointAddress, endpoint->desc.wMaxPacketSize);
 
 	return st5481_setup_isocpipes(d_out->urb, dev, 
 				      usb_sndisocpipe(dev, endpoint->desc.bEndpointAddress),
--- diff/drivers/isdn/hisax/st5481_init.c	2003-08-20 14:16:09.000000000 +0100
+++ source/drivers/isdn/hisax/st5481_init.c	2004-02-23 13:56:42.000000000 +0000
@@ -14,7 +14,6 @@
  * TODO:
  *
  * b layer1 delay?
- * hdlc as module
  * hotplug / unregister issues
  * mod_inc/dec_use_count
  * unify parts of d/b channel usb handling
@@ -59,8 +58,8 @@ static LIST_HEAD(adapter_list);
  * This function will be called when the adapter is plugged
  * into the USB bus.
  */
-static int probe_st5481(struct usb_interface *intf,
-			const struct usb_device_id *id)
+static int __devinit probe_st5481(struct usb_interface *intf,
+				     const struct usb_device_id *id)
 {
 	struct usb_device *dev = interface_to_usbdev(intf);
 	struct st5481_adapter *adapter;
@@ -140,7 +139,7 @@ static void disconnect_st5481(struct usb
 	usb_set_intfdata(intf, NULL);
 	if (!adapter)
 		return;
-
+	
 	list_del(&adapter->list);
 
 	st5481_stop(adapter);
@@ -196,7 +195,7 @@ static int __init st5481_usb_init(void)
 	st5481_debug = debug;
 #endif
 
-	printk(KERN_INFO "hisax_st5481: ST5481 USB ISDN driver v0.1.0\n");
+	printk(KERN_INFO "hisax_st5481: ST5481 USB ISDN driver $Revision: 2.4.2.3 $\n");
 
 	retval = st5481_d_init();
 	if (retval < 0)
--- diff/drivers/isdn/hisax/st5481_usb.c	2003-08-26 10:00:52.000000000 +0100
+++ source/drivers/isdn/hisax/st5481_usb.c	2004-02-23 13:56:42.000000000 +0000
@@ -96,7 +96,7 @@ void st5481_usb_device_ctrl_msg(struct s
  * Asynchronous pipe reset (async version of usb_clear_halt).
  */
 void st5481_usb_pipe_reset(struct st5481_adapter *adapter,
-		    u8 pipe,
+		    u_char pipe,
 		    ctrl_complete_t complete, void *context)
 {
 	DBG(1,"pipe=%02x",pipe);
@@ -500,8 +500,8 @@ static void usb_in_complete(struct urb *
 			status = len;
 			len = 0;
 		} else {
-			status = hdlc_decode(&in->hdlc_state, ptr, len, &count,
-					     in->rcvbuf, in->bufsize);
+			status = isdnhdlc_decode(&in->hdlc_state, ptr, len, &count,
+				in->rcvbuf, in->bufsize);
 			ptr += count;
 			len -= count;
 		}
@@ -633,8 +633,8 @@ void st5481_in_mode(struct st5481_in *in
 
 	if (in->mode != L1_MODE_NULL) {
 		if (in->mode != L1_MODE_TRANS)
-			hdlc_rcv_init(&in->hdlc_state,
-				      in->mode == L1_MODE_HDLC_56K);
+			isdnhdlc_rcv_init(&in->hdlc_state,
+				in->mode == L1_MODE_HDLC_56K);
 		
 		st5481_usb_pipe_reset(in->adapter, in->ep, NULL, NULL);
 		st5481_usb_device_ctrl_msg(in->adapter, in->counter,
--- diff/drivers/isdn/hisax/tei.c	2003-06-09 14:18:18.000000000 +0100
+++ source/drivers/isdn/hisax/tei.c	2004-02-23 13:56:42.000000000 +0000
@@ -1,4 +1,4 @@
-/* $Id: tei.c,v 2.17.6.3 2001/09/23 22:24:51 kai Exp $
+/* $Id: tei.c,v 2.20.2.3 2004/01/13 14:31:26 keil Exp $
  *
  * Author       Karsten Keil
  *              based on the teles driver from Jan den Ouden
@@ -20,7 +20,7 @@
 #include <linux/init.h>
 #include <linux/random.h>
 
-const char *tei_revision = "$Revision: 2.17.6.3 $";
+const char *tei_revision = "$Revision: 2.20.2.3 $";
 
 #define ID_REQUEST	1
 #define ID_ASSIGNED	2
@@ -34,7 +34,7 @@ const char *tei_revision = "$Revision: 2
 
 static struct Fsm teifsm;
 
-void tei_handler(struct PStack *st, u8 pr, struct sk_buff *skb);
+void tei_handler(struct PStack *st, u_char pr, struct sk_buff *skb);
 
 enum {
 	ST_TEI_NOP,
@@ -74,22 +74,6 @@ static char *strTeiEvent[] =
 	"EV_T202",
 };
 
-static inline void
-mdl_assign(struct IsdnCardState *cs)
-{
-	cs->status |= 0x0001;
-	if (cs->card_ops->led_handler)
-		cs->card_ops->led_handler(cs);
-}
-
-static inline void
-mdl_remove(struct IsdnCardState *cs)
-{
-	cs->status = 0;
-	if (cs->card_ops->led_handler)
-		cs->card_ops->led_handler(cs);
-}
-
 unsigned int
 random_ri(void)
 {
@@ -116,10 +100,10 @@ findtei(struct PStack *st, int tei)
 }
 
 static void
-put_tei_msg(struct PStack *st, u8 m_id, unsigned int ri, u8 tei)
+put_tei_msg(struct PStack *st, u_char m_id, unsigned int ri, u_char tei)
 {
 	struct sk_buff *skb;
-	u8 *bp;
+	u_char *bp;
 
 	if (!(skb = alloc_skb(8, GFP_ATOMIC))) {
 		printk(KERN_WARNING "HiSax: No skb for TEI manager\n");
@@ -135,7 +119,7 @@ put_tei_msg(struct PStack *st, u8 m_id, 
 	bp[2] = ri & 0xff;
 	bp[3] = m_id;
 	bp[4] = (tei << 1) | 1;
-	L2L1(st, PH_DATA | REQUEST, skb);
+	st->l2.l2l1(st, PH_DATA | REQUEST, skb);
 }
 
 static void
@@ -145,7 +129,7 @@ tei_id_request(struct FsmInst *fi, int e
 
 	if (st->l2.tei != -1) {
 		st->ma.tei_m.printdebug(&st->ma.tei_m,
-			"assign request for already assigned tei %d",
+			"assign request for allready asigned tei %d",
 			st->l2.tei);
 		return;
 	}
@@ -181,9 +165,9 @@ tei_id_assign(struct FsmInst *fi, int ev
 	} else if (ri == st->ma.ri) {
 		FsmDelTimer(&st->ma.t202, 1);
 		FsmChangeState(&st->ma.tei_m, ST_TEI_NOP);
-		L3L2(st, MDL_ASSIGN | REQUEST, (void *) (long) tei);
+		st->l3.l3l2(st, MDL_ASSIGN | REQUEST, (void *) (long) tei);
 		cs = (struct IsdnCardState *) st->l1.hardware;
-		mdl_assign(cs);
+		cs->cardmsg(cs, MDL_ASSIGN | REQUEST, NULL);
 	}
 }
 
@@ -255,9 +239,9 @@ tei_id_remove(struct FsmInst *fi, int ev
 	if ((st->l2.tei != -1) && ((tei == GROUP_TEI) || (tei == st->l2.tei))) {
 		FsmDelTimer(&st->ma.t202, 5);
 		FsmChangeState(&st->ma.tei_m, ST_TEI_NOP);
-		L3L2(st, MDL_REMOVE | REQUEST, 0);
+		st->l3.l3l2(st, MDL_REMOVE | REQUEST, 0);
 		cs = (struct IsdnCardState *) st->l1.hardware;
-		mdl_remove(cs);
+		cs->cardmsg(cs, MDL_REMOVE | REQUEST, NULL);
 	}
 }
 
@@ -291,9 +275,9 @@ tei_id_req_tout(struct FsmInst *fi, int 
 		FsmAddTimer(&st->ma.t202, st->ma.T202, EV_T202, NULL, 3);
 	} else {
 		st->ma.tei_m.printdebug(&st->ma.tei_m, "assign req failed");
-		L3L2(st, MDL_ERROR | RESPONSE, 0);
+		st->l3.l3l2(st, MDL_ERROR | RESPONSE, 0);
 		cs = (struct IsdnCardState *) st->l1.hardware;
-		mdl_remove(cs);
+		cs->cardmsg(cs, MDL_REMOVE | REQUEST, NULL);
 		FsmChangeState(fi, ST_TEI_NOP);
 	}
 }
@@ -314,9 +298,9 @@ tei_id_ver_tout(struct FsmInst *fi, int 
 	} else {
 		st->ma.tei_m.printdebug(&st->ma.tei_m,
 			"verify req for tei %d failed", st->l2.tei);
-		L3L2(st, MDL_REMOVE | REQUEST, 0);
+		st->l3.l3l2(st, MDL_REMOVE | REQUEST, 0);
 		cs = (struct IsdnCardState *) st->l1.hardware;
-		mdl_remove(cs);
+		cs->cardmsg(cs, MDL_REMOVE | REQUEST, NULL);
 		FsmChangeState(fi, ST_TEI_NOP);
 	}
 }
@@ -387,9 +371,9 @@ tei_l2tei(struct PStack *st, int pr, voi
 			if (st->ma.debug)
 				st->ma.tei_m.printdebug(&st->ma.tei_m,
 					"fixed assign tei %d", st->l2.tei);
-			L3L2(st, MDL_ASSIGN | REQUEST, (void *) (long) st->l2.tei);
+			st->l3.l3l2(st, MDL_ASSIGN | REQUEST, (void *) (long) st->l2.tei);
 			cs = (struct IsdnCardState *) st->l1.hardware;
-			mdl_assign(cs);
+			cs->cardmsg(cs, MDL_ASSIGN | REQUEST, NULL);
 		}
 		return;
 	}
--- diff/drivers/isdn/hisax/teleint.c	2003-06-09 14:18:18.000000000 +0100
+++ source/drivers/isdn/hisax/teleint.c	2004-02-23 13:56:42.000000000 +0000
@@ -1,4 +1,4 @@
-/* $Id: teleint.c,v 1.14.6.2 2001/09/23 22:24:52 kai Exp $
+/* $Id: teleint.c,v 1.16.2.5 2004/01/19 15:31:50 keil Exp $
  *
  * low level stuff for TeleInt isdn cards
  *
@@ -18,38 +18,33 @@
 
 extern const char *CardType[];
 
-const char *TeleInt_revision = "$Revision: 1.14.6.2 $";
-static spinlock_t teleint_lock = SPIN_LOCK_UNLOCKED;
+const char *TeleInt_revision = "$Revision: 1.16.2.5 $";
 
 #define byteout(addr,val) outb(val,addr)
 #define bytein(addr) inb(addr)
 
-static inline u8
-readreg(unsigned int ale, unsigned int adr, u8 off)
+static inline u_char
+readreg(unsigned int ale, unsigned int adr, u_char off)
 {
-	register u8 ret;
+	register u_char ret;
 	int max_delay = 2000;
-	unsigned long flags;
 
-	spin_lock_irqsave(&teleint_lock, flags);
 	byteout(ale, off);
 	ret = HFC_BUSY & bytein(ale);
 	while (ret && --max_delay)
 		ret = HFC_BUSY & bytein(ale);
 	if (!max_delay) {
 		printk(KERN_WARNING "TeleInt Busy not inactive\n");
-		spin_unlock_irqrestore(&teleint_lock, flags);
 		return (0);
 	}
 	ret = bytein(adr);
-	spin_unlock_irqrestore(&teleint_lock, flags);
 	return (ret);
 }
 
 static inline void
-readfifo(unsigned int ale, unsigned int adr, u8 off, u8 * data, int size)
+readfifo(unsigned int ale, unsigned int adr, u_char off, u_char * data, int size)
 {
-	register u8 ret;
+	register u_char ret;
 	register int max_delay = 20000;
 	register int i;
 	
@@ -68,34 +63,29 @@ readfifo(unsigned int ale, unsigned int 
 
 
 static inline void
-writereg(unsigned int ale, unsigned int adr, u8 off, u8 data)
+writereg(unsigned int ale, unsigned int adr, u_char off, u_char data)
 {
-	register u8 ret;
+	register u_char ret;
 	int max_delay = 2000;
-	unsigned long flags;
 
-	spin_lock_irqsave(&teleint_lock, flags);
 	byteout(ale, off);
 	ret = HFC_BUSY & bytein(ale);
 	while (ret && --max_delay)
 		ret = HFC_BUSY & bytein(ale);
 	if (!max_delay) {
 		printk(KERN_WARNING "TeleInt Busy not inactive\n");
-		spin_unlock_irqrestore(&teleint_lock, flags);
 		return;
 	}
 	byteout(adr, data);
-	spin_unlock_irqrestore(&teleint_lock, flags);
 }
 
 static inline void
-writefifo(unsigned int ale, unsigned int adr, u8 off, u8 * data, int size)
+writefifo(unsigned int ale, unsigned int adr, u_char off, u_char * data, int size)
 {
-	register u8 ret;
+	register u_char ret;
 	register int max_delay = 20000;
 	register int i;
 	
-	/* fifo write without cli because it's already done  */
 	byteout(ale, off);
 	for (i = 0; i<size; i++) {
 		ret = HFC_BUSY & bytein(ale);
@@ -111,45 +101,38 @@ writefifo(unsigned int ale, unsigned int
 
 /* Interface functions */
 
-static u8
-ReadISAC(struct IsdnCardState *cs, u8 offset)
+static u_char
+ReadISAC(struct IsdnCardState *cs, u_char offset)
 {
 	cs->hw.hfc.cip = offset;
 	return (readreg(cs->hw.hfc.addr | 1, cs->hw.hfc.addr, offset));
 }
 
 static void
-WriteISAC(struct IsdnCardState *cs, u8 offset, u8 value)
+WriteISAC(struct IsdnCardState *cs, u_char offset, u_char value)
 {
 	cs->hw.hfc.cip = offset;
 	writereg(cs->hw.hfc.addr | 1, cs->hw.hfc.addr, offset, value);
 }
 
 static void
-ReadISACfifo(struct IsdnCardState *cs, u8 * data, int size)
+ReadISACfifo(struct IsdnCardState *cs, u_char * data, int size)
 {
 	cs->hw.hfc.cip = 0;
 	readfifo(cs->hw.hfc.addr | 1, cs->hw.hfc.addr, 0, data, size);
 }
 
 static void
-WriteISACfifo(struct IsdnCardState *cs, u8 * data, int size)
+WriteISACfifo(struct IsdnCardState *cs, u_char * data, int size)
 {
 	cs->hw.hfc.cip = 0;
 	writefifo(cs->hw.hfc.addr | 1, cs->hw.hfc.addr, 0, data, size);
 }
 
-static struct dc_hw_ops isac_ops = {
-	.read_reg   = ReadISAC,
-	.write_reg  = WriteISAC,
-	.read_fifo  = ReadISACfifo,
-	.write_fifo = WriteISACfifo,
-};
-
-static u8
-ReadHFC(struct IsdnCardState *cs, int data, u8 reg)
+static u_char
+ReadHFC(struct IsdnCardState *cs, int data, u_char reg)
 {
-	register u8 ret;
+	register u_char ret;
 
 	if (data) {
 		cs->hw.hfc.cip = reg;
@@ -163,7 +146,7 @@ ReadHFC(struct IsdnCardState *cs, int da
 }
 
 static void
-WriteHFC(struct IsdnCardState *cs, int data, u8 reg, u8 value)
+WriteHFC(struct IsdnCardState *cs, int data, u_char reg, u_char value)
 {
 	byteout(cs->hw.hfc.addr | 1, reg);
 	cs->hw.hfc.cip = reg;
@@ -173,18 +156,14 @@ WriteHFC(struct IsdnCardState *cs, int d
 		debugl1(cs, "hfc W%c %02x %02x", data ? 'D' : 'C', reg, value);
 }
 
-static struct bc_hw_ops hfc_ops = {
-	.read_reg  = ReadHFC,
-	.write_reg = WriteHFC,
-};
-
 static irqreturn_t
-teleint_interrupt(int intno, void *dev_id, struct pt_regs *regs)
+TeleInt_interrupt(int intno, void *dev_id, struct pt_regs *regs)
 {
 	struct IsdnCardState *cs = dev_id;
-	u8 val;
+	u_char val;
+	u_long flags;
 
-	spin_lock(&cs->lock);
+	spin_lock_irqsave(&cs->lock, flags);
 	val = readreg(cs->hw.hfc.addr | 1, cs->hw.hfc.addr, ISAC_ISTA);
       Start_ISAC:
 	if (val)
@@ -197,7 +176,7 @@ teleint_interrupt(int intno, void *dev_i
 	}
 	writereg(cs->hw.hfc.addr | 1, cs->hw.hfc.addr, ISAC_MASK, 0xFF);
 	writereg(cs->hw.hfc.addr | 1, cs->hw.hfc.addr, ISAC_MASK, 0x0);
-	spin_unlock(&cs->lock);
+	spin_unlock_irqrestore(&cs->lock, flags);
 	return IRQ_HANDLED;
 }
 
@@ -205,7 +184,9 @@ static void
 TeleInt_Timer(struct IsdnCardState *cs)
 {
 	int stat = 0;
-
+	u_long flags;
+	
+	spin_lock_irqsave(&cs->lock, flags);
 	if (cs->bcs[0].mode) {
 		stat |= 1;
 		main_irq_hfc(&cs->bcs[0]);
@@ -214,52 +195,83 @@ TeleInt_Timer(struct IsdnCardState *cs)
 		stat |= 2;
 		main_irq_hfc(&cs->bcs[1]);
 	}
-	cs->hw.hfc.timer.expires = jiffies + 1;
+	spin_unlock_irqrestore(&cs->lock, flags);
+	stat = HZ/100;
+	if (!stat)
+		stat = 1;
+	cs->hw.hfc.timer.expires = jiffies + stat;
 	add_timer(&cs->hw.hfc.timer);
 }
 
-static void
-teleint_release(struct IsdnCardState *cs)
+void
+release_io_TeleInt(struct IsdnCardState *cs)
 {
 	del_timer(&cs->hw.hfc.timer);
 	releasehfc(cs);
-	hisax_release_resources(cs);
+	if (cs->hw.hfc.addr)
+		release_region(cs->hw.hfc.addr, 2);
 }
 
-static int
-teleint_reset(struct IsdnCardState *cs)
+static void
+reset_TeleInt(struct IsdnCardState *cs)
 {
 	printk(KERN_INFO "TeleInt: resetting card\n");
 	cs->hw.hfc.cirm |= HFC_RESET;
 	byteout(cs->hw.hfc.addr | 1, cs->hw.hfc.cirm);	/* Reset On */
-	set_current_state(TASK_UNINTERRUPTIBLE);
-	schedule_timeout((30*HZ)/1000);
+	mdelay(10);
 	cs->hw.hfc.cirm &= ~HFC_RESET;
 	byteout(cs->hw.hfc.addr | 1, cs->hw.hfc.cirm);	/* Reset Off */
-	set_current_state(TASK_UNINTERRUPTIBLE);
-	schedule_timeout((10*HZ)/1000);
-	return 0;
+	mdelay(10);
 }
 
-static void
-teleint_init(struct IsdnCardState *cs)
+static int
+TeleInt_card_msg(struct IsdnCardState *cs, int mt, void *arg)
 {
-	inithfc(cs);
-	initisac(cs);
-	cs->hw.hfc.timer.expires = jiffies + 1;
-	add_timer(&cs->hw.hfc.timer);
-}
+	u_long flags;
+	int delay;
 
-static struct card_ops teleint_ops = {
-	.init     = teleint_init,
-	.reset    = teleint_reset,
-	.release  = teleint_release,
-	.irq_func = teleint_interrupt,
-};
+	switch (mt) {
+		case CARD_RESET:
+			spin_lock_irqsave(&cs->lock, flags);
+			reset_TeleInt(cs);
+			spin_unlock_irqrestore(&cs->lock, flags);
+			return(0);
+		case CARD_RELEASE:
+			release_io_TeleInt(cs);
+			return(0);
+		case CARD_INIT:
+			spin_lock_irqsave(&cs->lock, flags);
+			reset_TeleInt(cs);
+			inithfc(cs);
+			clear_pending_isac_ints(cs);
+			initisac(cs);
+			/* Reenable all IRQ */
+			cs->writeisac(cs, ISAC_MASK, 0);
+			cs->writeisac(cs, ISAC_CMDR, 0x41);
+			spin_unlock_irqrestore(&cs->lock, flags);
+			delay = HZ/100;
+			if (!delay)
+				delay = 1;
+			cs->hw.hfc.timer.expires = jiffies + delay;
+			add_timer(&cs->hw.hfc.timer);
+			return(0);
+		case CARD_TEST:
+			return(0);
+	}
+	return(0);
+}
 
-static int __init
-teleint_probe(struct IsdnCardState *cs, struct IsdnCard *card)
+int __init
+setup_TeleInt(struct IsdnCard *card)
 {
+	struct IsdnCardState *cs = card->cs;
+	char tmp[64];
+
+	strcpy(tmp, TeleInt_revision);
+	printk(KERN_INFO "HiSax: TeleInt driver Rev. %s\n", HiSax_getrev(tmp));
+	if (cs->typ != ISDN_CTYPE_TELEINT)
+		return (0);
+
 	cs->hw.hfc.addr = card->para[1] & 0x3fe;
 	cs->irq = card->para[0];
 	cs->hw.hfc.cirm = HFC_CIRM;
@@ -272,61 +284,56 @@ teleint_probe(struct IsdnCardState *cs, 
 	cs->hw.hfc.timer.function = (void *) TeleInt_Timer;
 	cs->hw.hfc.timer.data = (long) cs;
 	init_timer(&cs->hw.hfc.timer);
-	if (!request_io(&cs->rs, cs->hw.hfc.addr, 2, "TeleInt isdn"))
-		goto err;
-	
+	if (!request_region(cs->hw.hfc.addr, 2, "TeleInt isdn")) {
+		printk(KERN_WARNING
+		       "HiSax: %s config port %x-%x already in use\n",
+		       CardType[card->typ],
+		       cs->hw.hfc.addr,
+		       cs->hw.hfc.addr + 2);
+		return (0);
+	}
 	/* HW IO = IO */
 	byteout(cs->hw.hfc.addr, cs->hw.hfc.addr & 0xff);
 	byteout(cs->hw.hfc.addr | 1, ((cs->hw.hfc.addr & 0x300) >> 8) | 0x54);
 	switch (cs->irq) {
-	case 3:
-		cs->hw.hfc.cirm |= HFC_INTA;
-		break;
-	case 4:
-		cs->hw.hfc.cirm |= HFC_INTB;
-		break;
-	case 5:
-		cs->hw.hfc.cirm |= HFC_INTC;
-		break;
-	case 7:
-		cs->hw.hfc.cirm |= HFC_INTD;
-		break;
-	case 10:
-		cs->hw.hfc.cirm |= HFC_INTE;
-		break;
-	case 11:
-		cs->hw.hfc.cirm |= HFC_INTF;
-		break;
-	default:
-		printk(KERN_WARNING "TeleInt: wrong IRQ\n");
-		goto err;
+		case 3:
+			cs->hw.hfc.cirm |= HFC_INTA;
+			break;
+		case 4:
+			cs->hw.hfc.cirm |= HFC_INTB;
+			break;
+		case 5:
+			cs->hw.hfc.cirm |= HFC_INTC;
+			break;
+		case 7:
+			cs->hw.hfc.cirm |= HFC_INTD;
+			break;
+		case 10:
+			cs->hw.hfc.cirm |= HFC_INTE;
+			break;
+		case 11:
+			cs->hw.hfc.cirm |= HFC_INTF;
+			break;
+		default:
+			printk(KERN_WARNING "TeleInt: wrong IRQ\n");
+			release_io_TeleInt(cs);
+			return (0);
 	}
 	byteout(cs->hw.hfc.addr | 1, cs->hw.hfc.cirm);
 	byteout(cs->hw.hfc.addr | 1, cs->hw.hfc.ctmt);
 
 	printk(KERN_INFO "TeleInt: defined at 0x%x IRQ %d\n",
-	       cs->hw.hfc.addr, cs->irq);
-
-	cs->card_ops = &teleint_ops;
-	teleint_reset(cs);
-	isac_setup(cs, &isac_ops);
-	hfc_setup(cs, &hfc_ops);
-	return 0;
-
- err:
-	hisax_release_resources(cs);
-	return -EBUSY;
-}
-
-int __init
-setup_TeleInt(struct IsdnCard *card)
-{
-	char tmp[64];
-
-	strcpy(tmp, TeleInt_revision);
-	printk(KERN_INFO "HiSax: TeleInt driver Rev. %s\n", HiSax_getrev(tmp));
+		cs->hw.hfc.addr, cs->irq);
 
-	if (teleint_probe(card->cs, card) < 0)
-		return 0;
-	return 1;
+	setup_isac(cs);
+	cs->readisac = &ReadISAC;
+	cs->writeisac = &WriteISAC;
+	cs->readisacfifo = &ReadISACfifo;
+	cs->writeisacfifo = &WriteISACfifo;
+	cs->BC_Read_Reg = &ReadHFC;
+	cs->BC_Write_Reg = &WriteHFC;
+	cs->cardmsg = &TeleInt_card_msg;
+	cs->irq_func = &TeleInt_interrupt;
+	ISACVersion(cs, "TeleInt:");
+	return (1);
 }
--- diff/drivers/isdn/hisax/teles0.c	2003-05-21 11:49:50.000000000 +0100
+++ source/drivers/isdn/hisax/teles0.c	2004-02-23 13:56:42.000000000 +0000
@@ -1,4 +1,4 @@
-/* $Id: teles0.c,v 2.13.6.2 2001/09/23 22:24:52 kai Exp $
+/* $Id: teles0.c,v 2.15.2.4 2004/01/13 23:48:39 keil Exp $
  *
  * low level stuff for Teles Memory IO isdn cards
  *
@@ -23,97 +23,179 @@
 
 extern const char *CardType[];
 
-const char *teles0_revision = "$Revision: 2.13.6.2 $";
+const char *teles0_revision = "$Revision: 2.15.2.4 $";
 
 #define TELES_IOMEM_SIZE	0x400
 #define byteout(addr,val) outb(val,addr)
 #define bytein(addr) inb(addr)
 
-static u8
-isac_read(struct IsdnCardState *cs, u8 off)
+static inline u_char
+readisac(unsigned long adr, u_char off)
 {
-	return readb(cs->hw.teles0.membase + 
-		     ((off & 1) ? 0x2ff : 0x100) + off);
+	return readb(adr + ((off & 1) ? 0x2ff : 0x100) + off);
 }
 
-static void
-isac_write(struct IsdnCardState *cs, u8 off, u8 data)
+static inline void
+writeisac(unsigned long adr, u_char off, u_char data)
 {
-	writeb(data, cs->hw.teles0.membase + 
-	       ((off & 1) ? 0x2ff : 0x100) + off); mb();
+	writeb(data, adr + ((off & 1) ? 0x2ff : 0x100) + off); mb();
 }
 
 
-static void
-isac_read_fifo(struct IsdnCardState *cs, u8 * data, int size)
+static inline u_char
+readhscx(unsigned long adr, int hscx, u_char off)
 {
-	int i;
-	void *ad = cs->hw.teles0.membase + 0x100;
+	return readb(adr + (hscx ? 0x1c0 : 0x180) +
+		     ((off & 1) ? 0x1ff : 0) + off);
+}
+
+static inline void
+writehscx(unsigned long adr, int hscx, u_char off, u_char data)
+{
+	writeb(data, adr + (hscx ? 0x1c0 : 0x180) +
+	       ((off & 1) ? 0x1ff : 0) + off); mb();
+}
+
+static inline void
+read_fifo_isac(unsigned long adr, u_char * data, int size)
+{
+	register int i;
+	register u_char *ad = (u_char *)adr + 0x100;
 	for (i = 0; i < size; i++)
 		data[i] = readb(ad);
 }
 
-static void
-isac_write_fifo(struct IsdnCardState *cs, u8 * data, int size)
+static inline void
+write_fifo_isac(unsigned long adr, u_char * data, int size)
+{
+	register int i;
+	register u_char *ad = (u_char *)adr + 0x100;
+	for (i = 0; i < size; i++) {
+		writeb(data[i], ad); mb();
+	}
+}
+
+static inline void
+read_fifo_hscx(unsigned long adr, int hscx, u_char * data, int size)
+{
+	register int i;
+	register u_char *ad = (u_char *) (adr + (hscx ? 0x1c0 : 0x180));
+	for (i = 0; i < size; i++)
+		data[i] = readb(ad);
+}
+
+static inline void
+write_fifo_hscx(unsigned long adr, int hscx, u_char * data, int size)
 {
 	int i;
-	void *ad = cs->hw.teles0.membase + 0x100;
+	register u_char *ad = (u_char *) (adr + (hscx ? 0x1c0 : 0x180));
 	for (i = 0; i < size; i++) {
 		writeb(data[i], ad); mb();
 	}
 }
 
-static struct dc_hw_ops isac_ops = {
-	.read_reg   = isac_read,
-	.write_reg  = isac_write,
-	.read_fifo  = isac_read_fifo,
-	.write_fifo = isac_write_fifo,
-};
+/* Interface functions */
 
-static u8
-hscx_read(struct IsdnCardState *cs, int hscx, u8 off)
+static u_char
+ReadISAC(struct IsdnCardState *cs, u_char offset)
 {
-	return readb(cs->hw.teles0.membase + (hscx ? 0x1c0 : 0x180) +
-		     ((off & 1) ? 0x1ff : 0) + off);
+	return (readisac(cs->hw.teles0.membase, offset));
 }
 
 static void
-hscx_write(struct IsdnCardState *cs, int hscx, u8 off, u8 data)
+WriteISAC(struct IsdnCardState *cs, u_char offset, u_char value)
 {
-	writeb(data, cs->hw.teles0.membase + (hscx ? 0x1c0 : 0x180) +
-	       ((off & 1) ? 0x1ff : 0) + off); mb();
+	writeisac(cs->hw.teles0.membase, offset, value);
 }
 
 static void
-hscx_read_fifo(struct IsdnCardState *cs, int hscx, u8 *data, int size)
+ReadISACfifo(struct IsdnCardState *cs, u_char * data, int size)
 {
-	int i;
-	void *ad = cs->hw.teles0.membase + (hscx ? 0x1c0 : 0x180);
-	for (i = 0; i < size; i++)
-		data[i] = readb(ad);
+	read_fifo_isac(cs->hw.teles0.membase, data, size);
 }
 
 static void
-hscx_write_fifo(struct IsdnCardState *cs, int hscx, u8 *data, int size)
+WriteISACfifo(struct IsdnCardState *cs, u_char * data, int size)
 {
-	int i;
-	void *ad = cs->hw.teles0.membase + (hscx ? 0x1c0 : 0x180);
-	for (i = 0; i < size; i++) {
-		writeb(data[i], ad);
-	}
+	write_fifo_isac(cs->hw.teles0.membase, data, size);
 }
 
-static struct bc_hw_ops hscx_ops = {
-	.read_reg   = hscx_read,
-	.write_reg  = hscx_write,
-	.read_fifo  = hscx_read_fifo,
-	.write_fifo = hscx_write_fifo,
-};
+static u_char
+ReadHSCX(struct IsdnCardState *cs, int hscx, u_char offset)
+{
+	return (readhscx(cs->hw.teles0.membase, hscx, offset));
+}
+
+static void
+WriteHSCX(struct IsdnCardState *cs, int hscx, u_char offset, u_char value)
+{
+	writehscx(cs->hw.teles0.membase, hscx, offset, value);
+}
+
+/*
+ * fast interrupt HSCX stuff goes here
+ */
+
+#define READHSCX(cs, nr, reg) readhscx(cs->hw.teles0.membase, nr, reg)
+#define WRITEHSCX(cs, nr, reg, data) writehscx(cs->hw.teles0.membase, nr, reg, data)
+#define READHSCXFIFO(cs, nr, ptr, cnt) read_fifo_hscx(cs->hw.teles0.membase, nr, ptr, cnt)
+#define WRITEHSCXFIFO(cs, nr, ptr, cnt) write_fifo_hscx(cs->hw.teles0.membase, nr, ptr, cnt)
+
+#include "hscx_irq.c"
+
+static irqreturn_t
+teles0_interrupt(int intno, void *dev_id, struct pt_regs *regs)
+{
+	struct IsdnCardState *cs = dev_id;
+	u_char val;
+	u_long flags;
+	int count = 0;
+
+	spin_lock_irqsave(&cs->lock, flags);
+	val = readhscx(cs->hw.teles0.membase, 1, HSCX_ISTA);
+      Start_HSCX:
+	if (val)
+		hscx_int_main(cs, val);
+	val = readisac(cs->hw.teles0.membase, ISAC_ISTA);
+      Start_ISAC:
+	if (val)
+		isac_interrupt(cs, val);
+	count++;
+	val = readhscx(cs->hw.teles0.membase, 1, HSCX_ISTA);
+	if (val && count < 5) {
+		if (cs->debug & L1_DEB_HSCX)
+			debugl1(cs, "HSCX IntStat after IntRoutine");
+		goto Start_HSCX;
+	}
+	val = readisac(cs->hw.teles0.membase, ISAC_ISTA);
+	if (val && count < 5) {
+		if (cs->debug & L1_DEB_ISAC)
+			debugl1(cs, "ISAC IntStat after IntRoutine");
+		goto Start_ISAC;
+	}
+	writehscx(cs->hw.teles0.membase, 0, HSCX_MASK, 0xFF);
+	writehscx(cs->hw.teles0.membase, 1, HSCX_MASK, 0xFF);
+	writeisac(cs->hw.teles0.membase, ISAC_MASK, 0xFF);
+	writeisac(cs->hw.teles0.membase, ISAC_MASK, 0x0);
+	writehscx(cs->hw.teles0.membase, 0, HSCX_MASK, 0x0);
+	writehscx(cs->hw.teles0.membase, 1, HSCX_MASK, 0x0);
+	spin_unlock_irqrestore(&cs->lock, flags);
+	return IRQ_HANDLED;
+}
+
+void
+release_io_teles0(struct IsdnCardState *cs)
+{
+	if (cs->hw.teles0.cfg_reg)
+		release_region(cs->hw.teles0.cfg_reg, 8);
+	iounmap((unsigned char *)cs->hw.teles0.membase);
+	release_mem_region(cs->hw.teles0.phymem, TELES_IOMEM_SIZE);
+}
 
 static int
-teles0_reset(struct IsdnCardState *cs)
+reset_teles0(struct IsdnCardState *cs)
 {
-	u8 cfval;
+	u_char cfval;
 
 	if (cs->hw.teles0.cfg_reg) {
 		switch (cs->irq) {
@@ -158,102 +240,129 @@ teles0_reset(struct IsdnCardState *cs)
 	return(0);
 }
 
-static struct card_ops teles0_ops = {
-	.init     = inithscxisac,
-	.reset    = teles0_reset,
-	.release  = hisax_release_resources,
-	.irq_func = hscxisac_irq,
-};
-
-static int __init
-teles0_probe(struct IsdnCardState *cs, struct IsdnCard *card)
-{
-	cs->irq = card->para[0];
-	/* 16.0 and 8.0 designed for IOM1 */
-	test_and_set_bit(HW_IOM1, &cs->HW_Flags);
-	cs->hw.teles0.phymem = card->para[1];
-	cs->hw.teles0.membase = request_mmio(&cs->rs, cs->hw.teles0.phymem,
-					     TELES_IOMEM_SIZE, "teles iomem");
-	if (!cs->hw.teles0.membase)
-		return -EBUSY;
-
-	if (teles0_reset(cs)) {
-		printk(KERN_WARNING "Teles0: wrong IRQ\n");
-		return -EBUSY;
-	}
-	cs->card_ops = &teles0_ops;
-	if (hscxisac_setup(cs, &isac_ops, &hscx_ops))
-		return -EBUSY;
-
-	return 0;
-}
-
-static int __init
-teles16_0_probe(struct IsdnCardState *cs, struct IsdnCard *card)
+static int
+Teles_card_msg(struct IsdnCardState *cs, int mt, void *arg)
 {
-	u8 val;
+	u_long flags;
 
-	cs->hw.teles0.cfg_reg = card->para[2];
-	if (!request_io(&cs->rs, cs->hw.teles0.cfg_reg, 8, "teles cfg"))
-		goto err;
-		
-	if ((val = bytein(cs->hw.teles0.cfg_reg + 0)) != 0x51) {
-		printk(KERN_WARNING "Teles0: 16.0 Byte at %x is %x\n",
-		       cs->hw.teles0.cfg_reg + 0, val);
-		goto err;
-	}
-	if ((val = bytein(cs->hw.teles0.cfg_reg + 1)) != 0x93) {
-		printk(KERN_WARNING "Teles0: 16.0 Byte at %x is %x\n",
-		       cs->hw.teles0.cfg_reg + 1, val);
-		goto err;
+	switch (mt) {
+		case CARD_RESET:
+			spin_lock_irqsave(&cs->lock, flags);
+			reset_teles0(cs);
+			spin_unlock_irqrestore(&cs->lock, flags);
+			return(0);
+		case CARD_RELEASE:
+			release_io_teles0(cs);
+			return(0);
+		case CARD_INIT:
+			spin_lock_irqsave(&cs->lock, flags);
+			inithscxisac(cs, 3);
+			spin_unlock_irqrestore(&cs->lock, flags);
+			return(0);
+		case CARD_TEST:
+			return(0);
 	}
-	val = bytein(cs->hw.teles0.cfg_reg + 2);/* 0x1e=without AB
-						 * 0x1f=with AB
-						 * 0x1c 16.3 ???
-						 */
-	if (val != 0x1e && val != 0x1f) {
-		printk(KERN_WARNING "Teles0: 16.0 Byte at %x is %x\n",
-		       cs->hw.teles0.cfg_reg + 2, val);
-		goto err;
-	}
-	if (teles0_probe(cs, card) < 0)
-		goto err;
-
-	return 0;
- err:
-	hisax_release_resources(cs);
-	return -EBUSY;
-}
-
-static int __init
-teles8_0_probe(struct IsdnCardState *cs, struct IsdnCard *card)
-{
-	cs->hw.teles0.cfg_reg = 0;
-
-	if (teles0_probe(cs, card) < 0)
-		goto err;
-
-	return 0;
- err:
-	hisax_release_resources(cs);
-	return -EBUSY;
+	return(0);
 }
 
 int __init
 setup_teles0(struct IsdnCard *card)
 {
+	u_char val;
+	struct IsdnCardState *cs = card->cs;
 	char tmp[64];
 
 	strcpy(tmp, teles0_revision);
-	printk(KERN_INFO "HiSax: Teles 8.0/16.0 driver Rev. %s\n",
-	       HiSax_getrev(tmp));
-
-	if (card->cs->typ == ISDN_CTYPE_16_0) {
-		if (teles16_0_probe(card->cs, card) < 0)
-			return 0;
-	} else {
-		if (teles8_0_probe(card->cs, card) < 0)
-			return 0;
+	printk(KERN_INFO "HiSax: Teles 8.0/16.0 driver Rev. %s\n", HiSax_getrev(tmp));
+	if ((cs->typ != ISDN_CTYPE_16_0) && (cs->typ != ISDN_CTYPE_8_0))
+		return (0);
+
+	if (cs->typ == ISDN_CTYPE_16_0)
+		cs->hw.teles0.cfg_reg = card->para[2];
+	else			/* 8.0 */
+		cs->hw.teles0.cfg_reg = 0;
+
+	if (card->para[1] < 0x10000) {
+		card->para[1] <<= 4;
+		printk(KERN_INFO
+		   "Teles0: membase configured DOSish, assuming 0x%lx\n",
+		       (unsigned long) card->para[1]);
+	}
+	cs->irq = card->para[0];
+	if (cs->hw.teles0.cfg_reg) {
+		if (!request_region(cs->hw.teles0.cfg_reg, 8, "teles cfg")) {
+			printk(KERN_WARNING
+			  "HiSax: %s config port %x-%x already in use\n",
+			       CardType[card->typ],
+			       cs->hw.teles0.cfg_reg,
+			       cs->hw.teles0.cfg_reg + 8);
+			return (0);
+		}
+	}
+	if (cs->hw.teles0.cfg_reg) {
+		if ((val = bytein(cs->hw.teles0.cfg_reg + 0)) != 0x51) {
+			printk(KERN_WARNING "Teles0: 16.0 Byte at %x is %x\n",
+			       cs->hw.teles0.cfg_reg + 0, val);
+			release_region(cs->hw.teles0.cfg_reg, 8);
+			return (0);
+		}
+		if ((val = bytein(cs->hw.teles0.cfg_reg + 1)) != 0x93) {
+			printk(KERN_WARNING "Teles0: 16.0 Byte at %x is %x\n",
+			       cs->hw.teles0.cfg_reg + 1, val);
+			release_region(cs->hw.teles0.cfg_reg, 8);
+			return (0);
+		}
+		val = bytein(cs->hw.teles0.cfg_reg + 2);	/* 0x1e=without AB
+								   * 0x1f=with AB
+								   * 0x1c 16.3 ???
+								 */
+		if (val != 0x1e && val != 0x1f) {
+			printk(KERN_WARNING "Teles0: 16.0 Byte at %x is %x\n",
+			       cs->hw.teles0.cfg_reg + 2, val);
+			release_region(cs->hw.teles0.cfg_reg, 8);
+			return (0);
+		}
+	}
+	/* 16.0 and 8.0 designed for IOM1 */
+	test_and_set_bit(HW_IOM1, &cs->HW_Flags);
+	cs->hw.teles0.phymem = card->para[1];
+	if (!request_mem_region(cs->hw.teles0.phymem, TELES_IOMEM_SIZE, "teles iomem")) {
+		printk(KERN_WARNING
+			"HiSax: %s memory region %lx-%lx already in use\n",
+			CardType[card->typ],
+			cs->hw.teles0.phymem,
+			cs->hw.teles0.phymem + TELES_IOMEM_SIZE);
+		if (cs->hw.teles0.cfg_reg)
+			release_region(cs->hw.teles0.cfg_reg, 8);
+		return (0);
+	}
+	cs->hw.teles0.membase =
+		(unsigned long) ioremap(cs->hw.teles0.phymem, TELES_IOMEM_SIZE);
+	printk(KERN_INFO
+	       "HiSax: %s config irq:%d mem:0x%lX cfg:0x%X\n",
+	       CardType[cs->typ], cs->irq,
+	       cs->hw.teles0.membase, cs->hw.teles0.cfg_reg);
+	if (reset_teles0(cs)) {
+		printk(KERN_WARNING "Teles0: wrong IRQ\n");
+		release_io_teles0(cs);
+		return (0);
+	}
+	setup_isac(cs);
+	cs->readisac = &ReadISAC;
+	cs->writeisac = &WriteISAC;
+	cs->readisacfifo = &ReadISACfifo;
+	cs->writeisacfifo = &WriteISACfifo;
+	cs->BC_Read_Reg = &ReadHSCX;
+	cs->BC_Write_Reg = &WriteHSCX;
+	cs->BC_Send_Data = &hscx_fill_fifo;
+	cs->cardmsg = &Teles_card_msg;
+	cs->irq_func = &teles0_interrupt;
+	ISACVersion(cs, "Teles0:");
+	if (HscxVersion(cs, "Teles0:")) {
+		printk(KERN_WARNING
+		 "Teles0: wrong HSCX versions check IO/MEM addresses\n");
+		release_io_teles0(cs);
+		return (0);
 	}
-	return 1;
+	return (1);
 }
--- diff/drivers/isdn/hisax/teles3.c	2003-05-21 11:49:50.000000000 +0100
+++ source/drivers/isdn/hisax/teles3.c	2004-02-23 13:56:42.000000000 +0000
@@ -1,4 +1,4 @@
-/* $Id: teles3.c,v 2.17.6.2 2001/09/23 22:24:52 kai Exp $
+/* $Id: teles3.c,v 2.19.2.4 2004/01/13 23:48:39 keil Exp $
  *
  * low level stuff for Teles 16.3 & PNP isdn cards
  *
@@ -21,102 +21,160 @@
 #include "isdnl1.h"
 
 extern const char *CardType[];
-const char *teles3_revision = "$Revision: 2.17.6.2 $";
+const char *teles3_revision = "$Revision: 2.19.2.4 $";
 
 #define byteout(addr,val) outb(val,addr)
 #define bytein(addr) inb(addr)
 
-static inline u8
-readreg(unsigned int adr, u8 off)
+static inline u_char
+readreg(unsigned int adr, u_char off)
 {
 	return (bytein(adr + off));
 }
 
 static inline void
-writereg(unsigned int adr, u8 off, u8 data)
+writereg(unsigned int adr, u_char off, u_char data)
 {
 	byteout(adr + off, data);
 }
 
 
 static inline void
-read_fifo(unsigned int adr, u8 * data, int size)
+read_fifo(unsigned int adr, u_char * data, int size)
 {
 	insb(adr, data, size);
 }
 
 static void
-write_fifo(unsigned int adr, u8 * data, int size)
+write_fifo(unsigned int adr, u_char * data, int size)
 {
 	outsb(adr, data, size);
 }
 
-static u8
-isac_read(struct IsdnCardState *cs, u8 offset)
+/* Interface functions */
+
+static u_char
+ReadISAC(struct IsdnCardState *cs, u_char offset)
 {
-	return readreg(cs->hw.teles3.isac, offset);
+	return (readreg(cs->hw.teles3.isac, offset));
 }
 
 static void
-isac_write(struct IsdnCardState *cs, u8 offset, u8 value)
+WriteISAC(struct IsdnCardState *cs, u_char offset, u_char value)
 {
 	writereg(cs->hw.teles3.isac, offset, value);
 }
 
 static void
-isac_read_fifo(struct IsdnCardState *cs, u8 * data, int size)
+ReadISACfifo(struct IsdnCardState *cs, u_char * data, int size)
 {
 	read_fifo(cs->hw.teles3.isacfifo, data, size);
 }
 
 static void
-isac_write_fifo(struct IsdnCardState *cs, u8 * data, int size)
+WriteISACfifo(struct IsdnCardState *cs, u_char * data, int size)
 {
 	write_fifo(cs->hw.teles3.isacfifo, data, size);
 }
 
-static struct dc_hw_ops isac_ops = {
-	.read_reg   = isac_read,
-	.write_reg  = isac_write,
-	.read_fifo  = isac_read_fifo,
-	.write_fifo = isac_write_fifo,
-};
-
-static u8
-hscx_read(struct IsdnCardState *cs, int hscx, u8 offset)
+static u_char
+ReadHSCX(struct IsdnCardState *cs, int hscx, u_char offset)
 {
-	return readreg(cs->hw.teles3.hscx[hscx], offset);
+	return (readreg(cs->hw.teles3.hscx[hscx], offset));
 }
 
 static void
-hscx_write(struct IsdnCardState *cs, int hscx, u8 offset, u8 value)
+WriteHSCX(struct IsdnCardState *cs, int hscx, u_char offset, u_char value)
 {
 	writereg(cs->hw.teles3.hscx[hscx], offset, value);
 }
 
-static void
-hscx_read_fifo(struct IsdnCardState *cs, int hscx, u8 *data, int size)
-{
-	read_fifo(cs->hw.teles3.hscxfifo[hscx], data, size);
-}
+/*
+ * fast interrupt HSCX stuff goes here
+ */
 
-static void
-hscx_write_fifo(struct IsdnCardState *cs, int hscx, u8 *data, int size)
-{
-	write_fifo(cs->hw.teles3.hscxfifo[hscx], data, size);
+#define READHSCX(cs, nr, reg) readreg(cs->hw.teles3.hscx[nr], reg)
+#define WRITEHSCX(cs, nr, reg, data) writereg(cs->hw.teles3.hscx[nr], reg, data)
+#define READHSCXFIFO(cs, nr, ptr, cnt) read_fifo(cs->hw.teles3.hscxfifo[nr], ptr, cnt)
+#define WRITEHSCXFIFO(cs, nr, ptr, cnt) write_fifo(cs->hw.teles3.hscxfifo[nr], ptr, cnt)
+
+#include "hscx_irq.c"
+
+static irqreturn_t
+teles3_interrupt(int intno, void *dev_id, struct pt_regs *regs)
+{
+#define MAXCOUNT 5
+	struct IsdnCardState *cs = dev_id;
+	u_char val;
+	u_long flags;
+	int count = 0;
+
+	spin_lock_irqsave(&cs->lock, flags);
+	val = readreg(cs->hw.teles3.hscx[1], HSCX_ISTA);
+      Start_HSCX:
+	if (val)
+		hscx_int_main(cs, val);
+	val = readreg(cs->hw.teles3.isac, ISAC_ISTA);
+      Start_ISAC:
+	if (val)
+		isac_interrupt(cs, val);
+	count++;
+	val = readreg(cs->hw.teles3.hscx[1], HSCX_ISTA);
+	if (val && count < MAXCOUNT) {
+		if (cs->debug & L1_DEB_HSCX)
+			debugl1(cs, "HSCX IntStat after IntRoutine");
+		goto Start_HSCX;
+	}
+	val = readreg(cs->hw.teles3.isac, ISAC_ISTA);
+	if (val && count < MAXCOUNT) {
+		if (cs->debug & L1_DEB_ISAC)
+			debugl1(cs, "ISAC IntStat after IntRoutine");
+		goto Start_ISAC;
+	}
+	if (count >= MAXCOUNT)
+		printk(KERN_WARNING "Teles3: more than %d loops in teles3_interrupt\n", count);
+	writereg(cs->hw.teles3.hscx[0], HSCX_MASK, 0xFF);
+	writereg(cs->hw.teles3.hscx[1], HSCX_MASK, 0xFF);
+	writereg(cs->hw.teles3.isac, ISAC_MASK, 0xFF);
+	writereg(cs->hw.teles3.isac, ISAC_MASK, 0x0);
+	writereg(cs->hw.teles3.hscx[0], HSCX_MASK, 0x0);
+	writereg(cs->hw.teles3.hscx[1], HSCX_MASK, 0x0);
+	spin_unlock_irqrestore(&cs->lock, flags);
+	return IRQ_HANDLED;
+}
+
+inline static void
+release_ioregs(struct IsdnCardState *cs, int mask)
+{
+	if (mask & 1)
+		release_region(cs->hw.teles3.isac + 32, 32);
+	if (mask & 2)
+		release_region(cs->hw.teles3.hscx[0] + 32, 32);
+	if (mask & 4)
+		release_region(cs->hw.teles3.hscx[1] + 32, 32);
+}
+
+void
+release_io_teles3(struct IsdnCardState *cs)
+{
+	if (cs->typ == ISDN_CTYPE_TELESPCMCIA) {
+		release_region(cs->hw.teles3.hscx[1], 96);
+	} else {
+		if (cs->hw.teles3.cfg_reg) {
+			if (cs->typ == ISDN_CTYPE_COMPAQ_ISA) {
+				release_region(cs->hw.teles3.cfg_reg, 1);
+			} else {
+				release_region(cs->hw.teles3.cfg_reg, 8);
+			}
+		}
+		release_ioregs(cs, 0x7);
+	}
 }
 
-static struct bc_hw_ops hscx_ops = {
-	.read_reg   = hscx_read,
-	.write_reg  = hscx_write,
-	.read_fifo  = hscx_read_fifo,
-	.write_fifo = hscx_write_fifo,
-};
-
 static int
-teles3_reset(struct IsdnCardState *cs)
+reset_teles3(struct IsdnCardState *cs)
 {
-	u8 irqcfg;
+	u_char irqcfg;
 
 	if (cs->typ != ISDN_CTYPE_TELESPCMCIA) {
 		if ((cs->hw.teles3.cfg_reg) && (cs->typ != ISDN_CTYPE_COMPAQ_ISA)) {
@@ -169,160 +227,33 @@ teles3_reset(struct IsdnCardState *cs)
 	return(0);
 }
 
-static struct card_ops teles3_ops = {
-	.init     = inithscxisac,
-	.reset    = teles3_reset,
-	.release  = hisax_release_resources,
-	.irq_func = hscxisac_irq,
-};
-
 static int
-teles_hw_init(struct IsdnCardState *cs)
+Teles_card_msg(struct IsdnCardState *cs, int mt, void *arg)
 {
-	
-	printk(KERN_INFO "HiSax: %s config irq:%d isac:0x%X  cfg:0x%X\n",
-	       CardType[cs->typ], cs->irq,
-	       cs->hw.teles3.isac + 32, cs->hw.teles3.cfg_reg);
-	printk(KERN_INFO "HiSax: hscx A:0x%X  hscx B:0x%X\n",
-	       cs->hw.teles3.hscx[0] + 32, cs->hw.teles3.hscx[1] + 32);
+	u_long flags;
 
-	if (teles3_reset(cs)) {
-		printk(KERN_WARNING "Teles3: wrong IRQ\n");
-		return -EBUSY;
+	switch (mt) {
+		case CARD_RESET:
+			spin_lock_irqsave(&cs->lock, flags);
+			reset_teles3(cs);
+			spin_unlock_irqrestore(&cs->lock, flags);
+			return(0);
+		case CARD_RELEASE:
+			release_io_teles3(cs);
+			return(0);
+		case CARD_INIT:
+			spin_lock_irqsave(&cs->lock, flags);
+			inithscxisac(cs, 3);
+			spin_unlock_irqrestore(&cs->lock, flags);
+			return(0);
+		case CARD_TEST:
+			return(0);
 	}
-	cs->card_ops = &teles3_ops;
-	if (hscxisac_setup(cs, &isac_ops, &hscx_ops))
-		return -EBUSY;
-	return 0;
-}
-
-static void __init
-teles_setup_io(struct IsdnCardState *cs, struct IsdnCard *card)
-{
-	cs->irq = card->para[0];
-	cs->hw.teles3.isacfifo = cs->hw.teles3.isac + 0x3e;
-	cs->hw.teles3.hscxfifo[0] = cs->hw.teles3.hscx[0] + 0x3e;
-	cs->hw.teles3.hscxfifo[1] = cs->hw.teles3.hscx[1] + 0x3e;
-}
-
-static int __init
-telespcmcia_probe(struct IsdnCardState *cs, struct IsdnCard *card)
-{
-	cs->hw.teles3.cfg_reg = 0;
-	cs->hw.teles3.hscx[0] = card->para[1] - 0x20;
-	cs->hw.teles3.hscx[1] = card->para[1];
-	cs->hw.teles3.isac = card->para[1] + 0x20;
-	teles_setup_io(cs, card);
-	if (!request_io(&cs->rs, cs->hw.teles3.hscx[1], 96, 
-			"HiSax Teles PCMCIA"))
-		goto err;
-	if (teles_hw_init(cs) < 0)
-		goto err;
-	return 0;
- err:
-	hisax_release_resources(cs);
-	return -EBUSY;
-}
-
-static int __init
-teles_request_io(struct IsdnCardState *cs)
-{
-	if (!request_io(&cs->rs, cs->hw.teles3.isac + 32, 32, "HiSax isac"))
-		return -EBUSY;
-	if (!request_io(&cs->rs, cs->hw.teles3.hscx[0]+32, 32, "HiSax hscx A"))
-		return -EBUSY;
-	if (!request_io(&cs->rs, cs->hw.teles3.hscx[1]+32, 32, "HiSax hscx B"))
-		return -EBUSY;
-	return 0;
-}
-
-static int __init
-teles16_3_probe(struct IsdnCardState *cs, struct IsdnCard *card)
-{
-	u8 val;
-
-	cs->hw.teles3.cfg_reg = card->para[1];
-	switch (cs->hw.teles3.cfg_reg) {
-	case 0x180:
-	case 0x280:
-	case 0x380:
-		cs->hw.teles3.cfg_reg |= 0xc00;
-		break;
-	}
-	cs->hw.teles3.isac = cs->hw.teles3.cfg_reg - 0x420;
-	cs->hw.teles3.hscx[0] = cs->hw.teles3.cfg_reg - 0xc20;
-	cs->hw.teles3.hscx[1] = cs->hw.teles3.cfg_reg - 0x820;
-	teles_setup_io(cs, card);
-	if (!request_io(&cs->rs, cs->hw.teles3.cfg_reg, 8, "teles3 cfg"))
-		goto err;
-	if (teles_request_io(cs) < 0)
-		goto err;
-	if ((val = bytein(cs->hw.teles3.cfg_reg + 0)) != 0x51) {
-		printk(KERN_WARNING "Teles: 16.3 Byte at %x is %x\n",
-		       cs->hw.teles3.cfg_reg + 0, val);
-		goto err;
-	}
-	if ((val = bytein(cs->hw.teles3.cfg_reg + 1)) != 0x93) {
-		printk(KERN_WARNING "Teles: 16.3 Byte at %x is %x\n",
-		       cs->hw.teles3.cfg_reg + 1, val);
-		goto err;
-	}
-	/* 0x1e without AB, 0x1f with AB,  0x1c 16.3 ???, 
-	 * 0x39 16.3 1.1,   0x38 16.3 1.3, 0x46 16.3 with AB + Video */
-	val = bytein(cs->hw.teles3.cfg_reg + 2);
-	if (val != 0x46 && val != 0x39 && val != 0x38 && 
-	    val != 0x1c && val != 0x1e && val != 0x1f) {
-		printk(KERN_WARNING "Teles: 16.3 Byte at %x is %x\n",
-		       cs->hw.teles3.cfg_reg + 2, val);
-		goto err;
-	}
-	if (teles_hw_init(cs) < 0)
-		goto err;
-	return 0;
- err:
-	hisax_release_resources(cs);
-	return -EBUSY;
-}
-
-static int __init
-compaq_probe(struct IsdnCardState *cs, struct IsdnCard *card)
-{
-	cs->hw.teles3.cfg_reg = card->para[3];
-	cs->hw.teles3.isac = card->para[2] - 32;
-	cs->hw.teles3.hscx[0] = card->para[1] - 32;
-	cs->hw.teles3.hscx[1] = card->para[1];
-	teles_setup_io(cs, card);
-	if (!request_io(&cs->rs, cs->hw.teles3.cfg_reg, 1, "teles3 cfg"))
-		goto err;
-	if (teles_request_io(cs) < 0)
-		goto err;
-	if (teles_hw_init(cs) < 0)
-		goto err;
-	return 0;
- err:
-	hisax_release_resources(cs);
-	return -EBUSY;
-}
-
-static int __init
-telespnp_probe(struct IsdnCardState *cs, struct IsdnCard *card)
-{
-	cs->hw.teles3.cfg_reg = 0;
-	cs->hw.teles3.isac = card->para[1] - 32;
-	cs->hw.teles3.hscx[0] = card->para[2] - 32;
-	cs->hw.teles3.hscx[1] = card->para[2];
-	teles_setup_io(cs, card);
-	if (teles_request_io(cs) < 0)
-		goto err;
-	if (teles_hw_init(cs) < 0)
-		goto err;
-	return 0;
- err:
-	hisax_release_resources(cs);
-	return -EBUSY;
+	return(0);
 }
 
 #ifdef __ISAPNP__
+
 static struct isapnp_device_id teles_ids[] __initdata = {
 	{ ISAPNP_VENDOR('T', 'A', 'G'), ISAPNP_FUNCTION(0x2110),
 	  ISAPNP_VENDOR('T', 'A', 'G'), ISAPNP_FUNCTION(0x2110), 
@@ -336,80 +267,233 @@ static struct isapnp_device_id teles_ids
 	{ 0, }
 };
 
-static struct isapnp_device_id *tdev = &teles_ids[0];
+static struct isapnp_device_id *ipid __initdata = &teles_ids[0];
 static struct pnp_card *pnp_c __devinitdata = NULL;
 #endif
 
 int __devinit
 setup_teles3(struct IsdnCard *card)
 {
+	u_char val;
+	struct IsdnCardState *cs = card->cs;
 	char tmp[64];
 
 	strcpy(tmp, teles3_revision);
 	printk(KERN_INFO "HiSax: Teles IO driver Rev. %s\n", HiSax_getrev(tmp));
+	if ((cs->typ != ISDN_CTYPE_16_3) && (cs->typ != ISDN_CTYPE_PNP)
+	    && (cs->typ != ISDN_CTYPE_TELESPCMCIA) && (cs->typ != ISDN_CTYPE_COMPAQ_ISA))
+		return (0);
+
 #ifdef __ISAPNP__
 	if (!card->para[1] && isapnp_present()) {
-		struct pnp_card *pnp_card;
-		struct pnp_dev *pnp_dev;
+		struct pnp_dev *pnp_d;
+		while(ipid->card_vendor) {
+			if ((pnp_c = pnp_find_card(ipid->card_vendor,
+				ipid->card_device, pnp_c))) {
+				pnp_d = NULL;
+				if ((pnp_d = pnp_find_dev(pnp_c,
+					ipid->vendor, ipid->function, pnp_d))) {
+					int err;
 
-		while(tdev->card_vendor) {
-			if ((pnp_card = pnp_find_card(tdev->card_vendor,
-						      tdev->card_device, pnp_c))) {
-				pnp_c = pnp_card;
-				pnp_dev = NULL;
-				if ((pnp_dev = pnp_find_dev(pnp_card,
-							    tdev->vendor,
-							    tdev->function,
-							    pnp_dev))) {
 					printk(KERN_INFO "HiSax: %s detected\n",
-						(char *)tdev->driver_data);
-					if (pnp_device_attach(pnp_dev) < 0) {
-						printk(KERN_ERR "Teles PnP: attach failed\n");
-						return 0;
-					}
-					if (pnp_activate_dev(pnp_dev) < 0) {
-						printk(KERN_ERR "Teles PnP: activate failed\n");
-						pnp_device_detach(pnp_dev);
-						return 0;
+						(char *)ipid->driver_data);
+					pnp_disable_dev(pnp_d);
+					err = pnp_activate_dev(pnp_d);
+					if (err<0) {
+						printk(KERN_WARNING "%s: pnp_activate_dev ret(%d)\n",
+							__FUNCTION__, err);
+						return(0);
 					}
-					if (!pnp_irq_valid(pnp_dev, 0) ||
-					    !pnp_port_valid(pnp_dev, 0) ||
-					    !pnp_port_valid(pnp_dev, 1)) {
-						printk(KERN_ERR "Teles PnP: some resources are missing %ld/%lx/%lx\n",
-							pnp_irq(pnp_dev, 0), pnp_port_start(pnp_dev, 0), pnp_port_start(pnp_dev, 1));
-						pnp_device_detach(pnp_dev);
-						return 0;
+					card->para[3] = pnp_port_start(pnp_d, 2);
+					card->para[2] = pnp_port_start(pnp_d, 1);
+					card->para[1] = pnp_port_start(pnp_d, 0);
+					card->para[0] = pnp_irq(pnp_d, 0);
+					if (!card->para[0] || !card->para[1] || !card->para[2]) {
+						printk(KERN_ERR "Teles PnP:some resources are missing %ld/%lx/%lx\n",
+							card->para[0], card->para[1], card->para[2]);
+						pnp_disable_dev(pnp_d);
+						return(0);
 					}
-					card->para[3] = pnp_port_start(pnp_dev, 2);
-					card->para[2] = pnp_port_start(pnp_dev, 1);
-					card->para[1] = pnp_port_start(pnp_dev, 0);
-					card->para[0] = pnp_irq(pnp_dev, 0);
 					break;
 				} else {
 					printk(KERN_ERR "Teles PnP: PnP error card found, no device\n");
 				}
 			}
-			tdev++;
-			pnp_c=NULL;
+			ipid++;
+			pnp_c = NULL;
 		} 
-		if (!tdev->card_vendor) {
+		if (!ipid->card_vendor) {
 			printk(KERN_INFO "Teles PnP: no ISAPnP card found\n");
 			return(0);
 		}
 	}
 #endif
-	if (card->cs->typ == ISDN_CTYPE_16_3) {
-		if (teles16_3_probe(card->cs, card) < 0)
-			return 0;
-	} else if (card->cs->typ == ISDN_CTYPE_TELESPCMCIA) {
-		if (telespcmcia_probe(card->cs, card) < 0)
-			return 0;
-	} else if (card->cs->typ == ISDN_CTYPE_COMPAQ_ISA) {
-		if (compaq_probe(card->cs, card) < 0)
-			return 0;
+	if (cs->typ == ISDN_CTYPE_16_3) {
+		cs->hw.teles3.cfg_reg = card->para[1];
+		switch (cs->hw.teles3.cfg_reg) {
+			case 0x180:
+			case 0x280:
+			case 0x380:
+				cs->hw.teles3.cfg_reg |= 0xc00;
+				break;
+		}
+		cs->hw.teles3.isac = cs->hw.teles3.cfg_reg - 0x420;
+		cs->hw.teles3.hscx[0] = cs->hw.teles3.cfg_reg - 0xc20;
+		cs->hw.teles3.hscx[1] = cs->hw.teles3.cfg_reg - 0x820;
+	} else if (cs->typ == ISDN_CTYPE_TELESPCMCIA) {
+		cs->hw.teles3.cfg_reg = 0;
+		cs->hw.teles3.hscx[0] = card->para[1] - 0x20;
+		cs->hw.teles3.hscx[1] = card->para[1];
+		cs->hw.teles3.isac = card->para[1] + 0x20;
+	} else if (cs->typ == ISDN_CTYPE_COMPAQ_ISA) {
+		cs->hw.teles3.cfg_reg = card->para[3];
+		cs->hw.teles3.isac = card->para[2] - 32;
+		cs->hw.teles3.hscx[0] = card->para[1] - 32;
+		cs->hw.teles3.hscx[1] = card->para[1];
 	} else {	/* PNP */
-		if (telespnp_probe(card->cs, card) < 0)
-			return 0;
+		cs->hw.teles3.cfg_reg = 0;
+		cs->hw.teles3.isac = card->para[1] - 32;
+		cs->hw.teles3.hscx[0] = card->para[2] - 32;
+		cs->hw.teles3.hscx[1] = card->para[2];
+	}
+	cs->irq = card->para[0];
+	cs->hw.teles3.isacfifo = cs->hw.teles3.isac + 0x3e;
+	cs->hw.teles3.hscxfifo[0] = cs->hw.teles3.hscx[0] + 0x3e;
+	cs->hw.teles3.hscxfifo[1] = cs->hw.teles3.hscx[1] + 0x3e;
+	if (cs->typ == ISDN_CTYPE_TELESPCMCIA) {
+		if (!request_region(cs->hw.teles3.hscx[1], 96, "HiSax Teles PCMCIA")) {
+			printk(KERN_WARNING
+			       "HiSax: %s ports %x-%x already in use\n",
+			       CardType[cs->typ],
+			       cs->hw.teles3.hscx[1],
+			       cs->hw.teles3.hscx[1] + 96);
+			return (0);
+		}
+	} else {
+		if (cs->hw.teles3.cfg_reg) {
+			if (cs->typ == ISDN_CTYPE_COMPAQ_ISA) {
+				if (!request_region(cs->hw.teles3.cfg_reg, 1, "teles3 cfg")) {
+					printk(KERN_WARNING
+						"HiSax: %s config port %x already in use\n",
+						CardType[card->typ],
+						cs->hw.teles3.cfg_reg);
+					return (0);
+				}
+			} else {
+				if (!request_region(cs->hw.teles3.cfg_reg, 8, "teles3 cfg")) {
+					printk(KERN_WARNING
+					       "HiSax: %s config port %x-%x already in use\n",
+					       CardType[card->typ],
+					       cs->hw.teles3.cfg_reg,
+						cs->hw.teles3.cfg_reg + 8);
+					return (0);
+				}
+			}
+		}
+		if (!request_region(cs->hw.teles3.isac + 32, 32, "HiSax isac")) {
+			printk(KERN_WARNING
+			   "HiSax: %s isac ports %x-%x already in use\n",
+			       CardType[cs->typ],
+			       cs->hw.teles3.isac + 32,
+			       cs->hw.teles3.isac + 64);
+			if (cs->hw.teles3.cfg_reg) {
+				if (cs->typ == ISDN_CTYPE_COMPAQ_ISA) {
+					release_region(cs->hw.teles3.cfg_reg, 1);
+				} else {
+					release_region(cs->hw.teles3.cfg_reg, 8);
+				}
+			}
+			return (0);
+		}
+		if (!request_region(cs->hw.teles3.hscx[0] + 32, 32, "HiSax hscx A")) {
+			printk(KERN_WARNING
+			 "HiSax: %s hscx A ports %x-%x already in use\n",
+			       CardType[cs->typ],
+			       cs->hw.teles3.hscx[0] + 32,
+			       cs->hw.teles3.hscx[0] + 64);
+			if (cs->hw.teles3.cfg_reg) {
+				if (cs->typ == ISDN_CTYPE_COMPAQ_ISA) {
+					release_region(cs->hw.teles3.cfg_reg, 1);
+				} else {
+					release_region(cs->hw.teles3.cfg_reg, 8);
+				}
+			}
+			release_ioregs(cs, 1);
+			return (0);
+		}
+		if (!request_region(cs->hw.teles3.hscx[1] + 32, 32, "HiSax hscx B")) {
+			printk(KERN_WARNING
+			 "HiSax: %s hscx B ports %x-%x already in use\n",
+			       CardType[cs->typ],
+			       cs->hw.teles3.hscx[1] + 32,
+			       cs->hw.teles3.hscx[1] + 64);
+			if (cs->hw.teles3.cfg_reg) {
+				if (cs->typ == ISDN_CTYPE_COMPAQ_ISA) {
+					release_region(cs->hw.teles3.cfg_reg, 1);
+				} else {
+					release_region(cs->hw.teles3.cfg_reg, 8);
+				}
+			}
+			release_ioregs(cs, 3);
+			return (0);
+		}
+	}
+	if ((cs->hw.teles3.cfg_reg) && (cs->typ != ISDN_CTYPE_COMPAQ_ISA)) {
+		if ((val = bytein(cs->hw.teles3.cfg_reg + 0)) != 0x51) {
+			printk(KERN_WARNING "Teles: 16.3 Byte at %x is %x\n",
+			       cs->hw.teles3.cfg_reg + 0, val);
+			release_io_teles3(cs);
+			return (0);
+		}
+		if ((val = bytein(cs->hw.teles3.cfg_reg + 1)) != 0x93) {
+			printk(KERN_WARNING "Teles: 16.3 Byte at %x is %x\n",
+			       cs->hw.teles3.cfg_reg + 1, val);
+			release_io_teles3(cs);
+			return (0);
+		}
+		val = bytein(cs->hw.teles3.cfg_reg + 2);/* 0x1e=without AB
+							 * 0x1f=with AB
+							 * 0x1c 16.3 ???
+							 * 0x39 16.3 1.1
+							 * 0x38 16.3 1.3
+							 * 0x46 16.3 with AB + Video (Teles-Vision)
+							 */
+		if (val != 0x46 && val != 0x39 && val != 0x38 && val != 0x1c && val != 0x1e && val != 0x1f) {
+			printk(KERN_WARNING "Teles: 16.3 Byte at %x is %x\n",
+			       cs->hw.teles3.cfg_reg + 2, val);
+			release_io_teles3(cs);
+			return (0);
+		}
+	}
+	printk(KERN_INFO
+	       "HiSax: %s config irq:%d isac:0x%X  cfg:0x%X\n",
+	       CardType[cs->typ], cs->irq,
+	       cs->hw.teles3.isac + 32, cs->hw.teles3.cfg_reg);
+	printk(KERN_INFO
+	       "HiSax: hscx A:0x%X  hscx B:0x%X\n",
+	       cs->hw.teles3.hscx[0] + 32, cs->hw.teles3.hscx[1] + 32);
+
+	setup_isac(cs);
+	if (reset_teles3(cs)) {
+		printk(KERN_WARNING "Teles3: wrong IRQ\n");
+		release_io_teles3(cs);
+		return (0);
+	}
+	cs->readisac = &ReadISAC;
+	cs->writeisac = &WriteISAC;
+	cs->readisacfifo = &ReadISACfifo;
+	cs->writeisacfifo = &WriteISACfifo;
+	cs->BC_Read_Reg = &ReadHSCX;
+	cs->BC_Write_Reg = &WriteHSCX;
+	cs->BC_Send_Data = &hscx_fill_fifo;
+	cs->cardmsg = &Teles_card_msg;
+	cs->irq_func = &teles3_interrupt;
+	ISACVersion(cs, "Teles3:");
+	if (HscxVersion(cs, "Teles3:")) {
+		printk(KERN_WARNING
+		       "Teles3: wrong HSCX versions check IO address\n");
+		release_io_teles3(cs);
+		return (0);
 	}
-	return 1;
+	return (1);
 }
--- diff/drivers/isdn/hisax/telespci.c	2003-05-21 11:50:15.000000000 +0100
+++ source/drivers/isdn/hisax/telespci.c	2004-02-23 13:56:42.000000000 +0000
@@ -1,4 +1,4 @@
-/* $Id: telespci.c,v 2.16.6.5 2001/09/23 22:24:52 kai Exp $
+/* $Id: telespci.c,v 2.23.2.3 2004/01/13 14:31:26 keil Exp $
  *
  * low level stuff for Teles PCI isdn cards
  *
@@ -21,7 +21,7 @@
 #include <linux/pci.h>
 
 extern const char *CardType[];
-const char *telespci_revision = "$Revision: 2.16.6.5 $";
+const char *telespci_revision = "$Revision: 2.23.2.3 $";
 
 #define ZORAN_PO_RQ_PEN	0x02000000
 #define ZORAN_PO_WR	0x00800000
@@ -39,233 +39,250 @@ const char *telespci_revision = "$Revisi
 #define WRITE_DATA_HSCX	(ZORAN_PO_WR | ZORAN_PO_GID1 | ZORAN_PO_GREG1)
 
 #define ZORAN_WAIT_NOBUSY	do { \
-					portdata = readl(adr); \
+					portdata = readl(adr + 0x200); \
 				} while (portdata & ZORAN_PO_RQ_PEN)
 
-static u8
-isac_read(struct IsdnCardState *cs, u8 off)
+static inline u_char
+readisac(unsigned long adr, u_char off)
 {
-	void *adr = cs->hw.teles0.membase + 0x200;
-	unsigned int portdata;
+	register unsigned int portdata;
 
 	ZORAN_WAIT_NOBUSY;
 	
 	/* set address for ISAC */
-	writel(WRITE_ADDR_ISAC | off, adr);
+	writel(WRITE_ADDR_ISAC | off, adr + 0x200);
 	ZORAN_WAIT_NOBUSY;
 	
 	/* read data from ISAC */
-	writel(READ_DATA_ISAC, adr);
+	writel(READ_DATA_ISAC, adr + 0x200);
 	ZORAN_WAIT_NOBUSY;
-	return((u8)(portdata & ZORAN_PO_DMASK));
+	return((u_char)(portdata & ZORAN_PO_DMASK));
 }
 
-static void
-isac_write(struct IsdnCardState *cs, u8 off, u8 data)
+static inline void
+writeisac(unsigned long adr, u_char off, u_char data)
 {
-	void *adr = cs->hw.teles0.membase + 0x200;
-	unsigned int portdata;
+	register unsigned int portdata;
 
 	ZORAN_WAIT_NOBUSY;
 	
 	/* set address for ISAC */
-	writel(WRITE_ADDR_ISAC | off, adr);
+	writel(WRITE_ADDR_ISAC | off, adr + 0x200);
 	ZORAN_WAIT_NOBUSY;
 
 	/* write data to ISAC */
-	writel(WRITE_DATA_ISAC | data, adr);
+	writel(WRITE_DATA_ISAC | data, adr + 0x200);
 	ZORAN_WAIT_NOBUSY;
 }
 
-static void
-isac_read_fifo(struct IsdnCardState *cs, u8 *data, int size)
+static inline u_char
+readhscx(unsigned long adr, int hscx, u_char off)
 {
-	void *adr = cs->hw.teles0.membase + 0x200;
-	unsigned int portdata;
-	int i;
+	register unsigned int portdata;
+
+	ZORAN_WAIT_NOBUSY;
+	/* set address for HSCX */
+	writel(WRITE_ADDR_HSCX | ((hscx ? 0x40:0) + off), adr + 0x200);
+	ZORAN_WAIT_NOBUSY;
+	
+	/* read data from HSCX */
+	writel(READ_DATA_HSCX, adr + 0x200);
+	ZORAN_WAIT_NOBUSY;
+	return ((u_char)(portdata & ZORAN_PO_DMASK));
+}
+
+static inline void
+writehscx(unsigned long adr, int hscx, u_char off, u_char data)
+{
+	register unsigned int portdata;
+
+	ZORAN_WAIT_NOBUSY;
+	/* set address for HSCX */
+	writel(WRITE_ADDR_HSCX | ((hscx ? 0x40:0) + off), adr + 0x200);
+	ZORAN_WAIT_NOBUSY;
+
+	/* write data to HSCX */
+	writel(WRITE_DATA_HSCX | data, adr + 0x200);
+	ZORAN_WAIT_NOBUSY;
+}
+
+static inline void
+read_fifo_isac(unsigned long adr, u_char * data, int size)
+{
+	register unsigned int portdata;
+	register int i;
 
 	ZORAN_WAIT_NOBUSY;
 	/* read data from ISAC */
 	for (i = 0; i < size; i++) {
 		/* set address for ISAC fifo */
-		writel(WRITE_ADDR_ISAC | 0x1E, adr);
+		writel(WRITE_ADDR_ISAC | 0x1E, adr + 0x200);
 		ZORAN_WAIT_NOBUSY;
-		writel(READ_DATA_ISAC, adr);
+		writel(READ_DATA_ISAC, adr + 0x200);
 		ZORAN_WAIT_NOBUSY;
-		data[i] = (u8)(portdata & ZORAN_PO_DMASK);
+		data[i] = (u_char)(portdata & ZORAN_PO_DMASK);
 	}
 }
 
 static void
-isac_write_fifo(struct IsdnCardState *cs, u8 *data, int size)
+write_fifo_isac(unsigned long adr, u_char * data, int size)
 {
-	void *adr = cs->hw.teles0.membase + 0x200;
-	unsigned int portdata;
-	int i;
+	register unsigned int portdata;
+	register int i;
 
 	ZORAN_WAIT_NOBUSY;
 	/* write data to ISAC */
 	for (i = 0; i < size; i++) {
 		/* set address for ISAC fifo */
-		writel(WRITE_ADDR_ISAC | 0x1E, adr);
+		writel(WRITE_ADDR_ISAC | 0x1E, adr + 0x200);
 		ZORAN_WAIT_NOBUSY;
-		writel(WRITE_DATA_ISAC | data[i], adr);
+		writel(WRITE_DATA_ISAC | data[i], adr + 0x200);
 		ZORAN_WAIT_NOBUSY;
 	}
 }
 
-static struct dc_hw_ops isac_ops = {
-	.read_reg   = isac_read,
-	.write_reg  = isac_write,
-	.read_fifo  = isac_read_fifo,
-	.write_fifo = isac_write_fifo,
-};
-
-static u8
-hscx_read(struct IsdnCardState *cs, int hscx, u8 off)
-{
-	void *adr = cs->hw.teles0.membase + 0x200;
-	unsigned int portdata;
-
-	ZORAN_WAIT_NOBUSY;
-	/* set address for HSCX */
-	writel(WRITE_ADDR_HSCX | ((hscx ? 0x40:0) + off), adr);
-	ZORAN_WAIT_NOBUSY;
-	
-	/* read data from HSCX */
-	writel(READ_DATA_HSCX, adr);
-	ZORAN_WAIT_NOBUSY;
-	return ((u8)(portdata & ZORAN_PO_DMASK));
-}
-
-static void
-hscx_write(struct IsdnCardState *cs, int hscx, u8 off, u8 data)
+static inline void
+read_fifo_hscx(unsigned long adr, int hscx, u_char * data, int size)
 {
-	void *adr = cs->hw.teles0.membase + 0x200;
-	unsigned int portdata;
-
-	ZORAN_WAIT_NOBUSY;
-	/* set address for HSCX */
-	writel(WRITE_ADDR_HSCX | ((hscx ? 0x40:0) + off), adr);
-	ZORAN_WAIT_NOBUSY;
-
-	/* write data to HSCX */
-	writel(WRITE_DATA_HSCX | data, adr);
-	ZORAN_WAIT_NOBUSY;
-}
-
-static void
-hscx_read_fifo(struct IsdnCardState *cs, int hscx, u8 * data, int size)
-{
-	void *adr = cs->hw.teles0.membase + 0x200;
-	unsigned int portdata;
-	int i;
+	register unsigned int portdata;
+	register int i;
 
 	ZORAN_WAIT_NOBUSY;
 	/* read data from HSCX */
 	for (i = 0; i < size; i++) {
 		/* set address for HSCX fifo */
-		writel(WRITE_ADDR_HSCX |(hscx ? 0x5F:0x1F), adr);
+		writel(WRITE_ADDR_HSCX |(hscx ? 0x5F:0x1F), adr + 0x200);
 		ZORAN_WAIT_NOBUSY;
-		writel(READ_DATA_HSCX, adr);
+		writel(READ_DATA_HSCX, adr + 0x200);
 		ZORAN_WAIT_NOBUSY;
-		data[i] = (u8) (portdata & ZORAN_PO_DMASK);
+		data[i] = (u_char) (portdata & ZORAN_PO_DMASK);
 	}
 }
 
-static void
-hscx_write_fifo(struct IsdnCardState *cs, int hscx, u8 * data, int size)
+static inline void
+write_fifo_hscx(unsigned long adr, int hscx, u_char * data, int size)
 {
-	void *adr = cs->hw.teles0.membase + 0x200;
 	unsigned int portdata;
-	int i;
+	register int i;
 
 	ZORAN_WAIT_NOBUSY;
 	/* write data to HSCX */
 	for (i = 0; i < size; i++) {
 		/* set address for HSCX fifo */
-		writel(WRITE_ADDR_HSCX |(hscx ? 0x5F:0x1F), adr);
+		writel(WRITE_ADDR_HSCX |(hscx ? 0x5F:0x1F), adr + 0x200);
 		ZORAN_WAIT_NOBUSY;
-		writel(WRITE_DATA_HSCX | data[i], adr);
+		writel(WRITE_DATA_HSCX | data[i], adr + 0x200);
 		ZORAN_WAIT_NOBUSY;
 		udelay(10);
 	}
 }
 
-static struct bc_hw_ops hscx_ops = {
-	.read_reg   = hscx_read,
-	.write_reg  = hscx_write,
-	.read_fifo  = hscx_read_fifo,
-	.write_fifo = hscx_write_fifo,
-};
+/* Interface functions */
+
+static u_char
+ReadISAC(struct IsdnCardState *cs, u_char offset)
+{
+	return (readisac(cs->hw.teles0.membase, offset));
+}
+
+static void
+WriteISAC(struct IsdnCardState *cs, u_char offset, u_char value)
+{
+	writeisac(cs->hw.teles0.membase, offset, value);
+}
+
+static void
+ReadISACfifo(struct IsdnCardState *cs, u_char * data, int size)
+{
+	read_fifo_isac(cs->hw.teles0.membase, data, size);
+}
+
+static void
+WriteISACfifo(struct IsdnCardState *cs, u_char * data, int size)
+{
+	write_fifo_isac(cs->hw.teles0.membase, data, size);
+}
+
+static u_char
+ReadHSCX(struct IsdnCardState *cs, int hscx, u_char offset)
+{
+	return (readhscx(cs->hw.teles0.membase, hscx, offset));
+}
+
+static void
+WriteHSCX(struct IsdnCardState *cs, int hscx, u_char offset, u_char value)
+{
+	writehscx(cs->hw.teles0.membase, hscx, offset, value);
+}
+
+/*
+ * fast interrupt HSCX stuff goes here
+ */
+
+#define READHSCX(cs, nr, reg) readhscx(cs->hw.teles0.membase, nr, reg)
+#define WRITEHSCX(cs, nr, reg, data) writehscx(cs->hw.teles0.membase, nr, reg, data)
+#define READHSCXFIFO(cs, nr, ptr, cnt) read_fifo_hscx(cs->hw.teles0.membase, nr, ptr, cnt)
+#define WRITEHSCXFIFO(cs, nr, ptr, cnt) write_fifo_hscx(cs->hw.teles0.membase, nr, ptr, cnt)
+
+#include "hscx_irq.c"
 
 static irqreturn_t
 telespci_interrupt(int intno, void *dev_id, struct pt_regs *regs)
 {
-#define MAXCOUNT 20
 	struct IsdnCardState *cs = dev_id;
-	u8 val;
+	u_char hval, ival;
+	u_long flags;
 
-	spin_lock(&cs->lock);
-	val = hscx_read(cs, 1, HSCX_ISTA);
-	if (val)
-		hscx_int_main(cs, val);
-	val = isac_read(cs, ISAC_ISTA);
-	if (val)
-		isac_interrupt(cs, val);
+	spin_lock_irqsave(&cs->lock, flags);
+	hval = readhscx(cs->hw.teles0.membase, 1, HSCX_ISTA);
+	if (hval)
+		hscx_int_main(cs, hval);
+	ival = readisac(cs->hw.teles0.membase, ISAC_ISTA);
+	if ((hval | ival) == 0) {
+		spin_unlock_irqrestore(&cs->lock, flags);
+		return IRQ_NONE;
+	}
+	if (ival)
+		isac_interrupt(cs, ival);
 	/* Clear interrupt register for Zoran PCI controller */
 	writel(0x70000000, cs->hw.teles0.membase + 0x3C);
 
-	hscx_write(cs, 0, HSCX_MASK, 0xFF);
-	hscx_write(cs, 1, HSCX_MASK, 0xFF);
-	isac_write(cs, ISAC_MASK, 0xFF);
-	isac_write(cs, ISAC_MASK, 0x0);
-	hscx_write(cs, 0, HSCX_MASK, 0x0);
-	hscx_write(cs, 1, HSCX_MASK, 0x0);
-	spin_unlock(&cs->lock);
+	writehscx(cs->hw.teles0.membase, 0, HSCX_MASK, 0xFF);
+	writehscx(cs->hw.teles0.membase, 1, HSCX_MASK, 0xFF);
+	writeisac(cs->hw.teles0.membase, ISAC_MASK, 0xFF);
+	writeisac(cs->hw.teles0.membase, ISAC_MASK, 0x0);
+	writehscx(cs->hw.teles0.membase, 0, HSCX_MASK, 0x0);
+	writehscx(cs->hw.teles0.membase, 1, HSCX_MASK, 0x0);
+	spin_unlock_irqrestore(&cs->lock, flags);
 	return IRQ_HANDLED;
 }
 
-static struct card_ops telespci_ops = {
-	.init     = inithscxisac,
-	.release  = hisax_release_resources,
-	.irq_func = telespci_interrupt,
-};
-
-static int __init
-telespci_probe(struct IsdnCardState *cs, struct pci_dev *pdev)
+void
+release_io_telespci(struct IsdnCardState *cs)
 {
-	int rc;
-
-	printk(KERN_INFO "TelesPCI: defined at %#lx IRQ %d\n",
-	       pci_resource_start(pdev, 0), pdev->irq);
-	
-	rc = -EBUSY;
-	if (pci_enable_device(pdev))
-		goto err;
-			
-	cs->irq = pdev->irq;
-	cs->irq_flags |= SA_SHIRQ;
-	cs->hw.teles0.membase = request_mmio(&cs->rs, pci_resource_start(pdev, 0), 4096, "telespci");
-	if (!cs->hw.teles0.membase)
-		goto err;
-
-	/* Initialize Zoran PCI controller */
-	writel(0x00000000, cs->hw.teles0.membase + 0x28);
-	writel(0x01000000, cs->hw.teles0.membase + 0x28);
-	writel(0x01000000, cs->hw.teles0.membase + 0x28);
-	writel(0x7BFFFFFF, cs->hw.teles0.membase + 0x2C);
-	writel(0x70000000, cs->hw.teles0.membase + 0x3C);
-	writel(0x61000000, cs->hw.teles0.membase + 0x40);
-	/* writel(0x00800000, cs->hw.teles0.membase + 0x200); */
+	iounmap((void *)cs->hw.teles0.membase);
+}
 
-	cs->card_ops = &telespci_ops;
-	if (hscxisac_setup(cs, &isac_ops, &hscx_ops))
-		goto err;
-	return 0;
- err:
-	hisax_release_resources(cs);
-	return rc;
+static int
+TelesPCI_card_msg(struct IsdnCardState *cs, int mt, void *arg)
+{
+	u_long flags;
+
+	switch (mt) {
+		case CARD_RESET:
+			return(0);
+		case CARD_RELEASE:
+			release_io_telespci(cs);
+			return(0);
+		case CARD_INIT:
+			spin_lock_irqsave(&cs->lock, flags);
+			inithscxisac(cs, 3);
+			spin_unlock_irqrestore(&cs->lock, flags);
+			return(0);
+		case CARD_TEST:
+			return(0);
+	}
+	return(0);
 }
 
 static struct pci_dev *dev_tel __initdata = NULL;
@@ -273,21 +290,70 @@ static struct pci_dev *dev_tel __initdat
 int __init
 setup_telespci(struct IsdnCard *card)
 {
+	struct IsdnCardState *cs = card->cs;
 	char tmp[64];
 
 #ifdef __BIG_ENDIAN
 #error "not running on big endian machines now"
 #endif
 	strcpy(tmp, telespci_revision);
-	printk(KERN_INFO "HiSax: Teles/PCI driver Rev. %s\n",
-	       HiSax_getrev(tmp));
-	dev_tel = pci_find_device(PCI_VENDOR_ID_ZORAN, 
-				  PCI_DEVICE_ID_ZORAN_36120, dev_tel);
-	if (dev_tel) {
-		if (telespci_probe(card->cs, dev_tel) < 0)
-			return 0;
-		return 1;
+	printk(KERN_INFO "HiSax: Teles/PCI driver Rev. %s\n", HiSax_getrev(tmp));
+	if (cs->typ != ISDN_CTYPE_TELESPCI)
+		return (0);
+#if CONFIG_PCI
+	if ((dev_tel = pci_find_device (PCI_VENDOR_ID_ZORAN, PCI_DEVICE_ID_ZORAN_36120, dev_tel))) {
+		if (pci_enable_device(dev_tel))
+			return(0);
+		cs->irq = dev_tel->irq;
+		if (!cs->irq) {
+			printk(KERN_WARNING "Teles: No IRQ for PCI card found\n");
+			return(0);
+		}
+		cs->hw.teles0.membase = (u_long) ioremap(pci_resource_start(dev_tel, 0),
+			PAGE_SIZE);
+		printk(KERN_INFO "Found: Zoran, base-address: 0x%lx, irq: 0x%x\n",
+			pci_resource_start(dev_tel, 0), dev_tel->irq);
+	} else {
+		printk(KERN_WARNING "TelesPCI: No PCI card found\n");
+		return(0);
+	}
+#else
+	printk(KERN_WARNING "HiSax: Teles/PCI and NO_PCI_BIOS\n");
+	printk(KERN_WARNING "HiSax: Teles/PCI unable to config\n");
+	return (0);
+#endif /* CONFIG_PCI */
+
+	/* Initialize Zoran PCI controller */
+	writel(0x00000000, cs->hw.teles0.membase + 0x28);
+	writel(0x01000000, cs->hw.teles0.membase + 0x28);
+	writel(0x01000000, cs->hw.teles0.membase + 0x28);
+	writel(0x7BFFFFFF, cs->hw.teles0.membase + 0x2C);
+	writel(0x70000000, cs->hw.teles0.membase + 0x3C);
+	writel(0x61000000, cs->hw.teles0.membase + 0x40);
+	/* writel(0x00800000, cs->hw.teles0.membase + 0x200); */
+
+	printk(KERN_INFO
+	       "HiSax: %s config irq:%d mem:%lx\n",
+	       CardType[cs->typ], cs->irq,
+	       cs->hw.teles0.membase);
+
+	setup_isac(cs);
+	cs->readisac = &ReadISAC;
+	cs->writeisac = &WriteISAC;
+	cs->readisacfifo = &ReadISACfifo;
+	cs->writeisacfifo = &WriteISACfifo;
+	cs->BC_Read_Reg = &ReadHSCX;
+	cs->BC_Write_Reg = &WriteHSCX;
+	cs->BC_Send_Data = &hscx_fill_fifo;
+	cs->cardmsg = &TelesPCI_card_msg;
+	cs->irq_func = &telespci_interrupt;
+	cs->irq_flags |= SA_SHIRQ;
+	ISACVersion(cs, "TelesPCI:");
+	if (HscxVersion(cs, "TelesPCI:")) {
+		printk(KERN_WARNING
+		 "TelesPCI: wrong HSCX versions check IO/MEM addresses\n");
+		release_io_telespci(cs);
+		return (0);
 	}
-	printk(KERN_WARNING "TelesPCI: No PCI card found\n");
-	return 0;
+	return (1);
 }
--- diff/drivers/isdn/hisax/w6692.c	2003-05-21 11:50:15.000000000 +0100
+++ source/drivers/isdn/hisax/w6692.c	2004-02-23 13:56:42.000000000 +0000
@@ -1,4 +1,4 @@
-/* $Id: w6692.c,v 1.12.6.6 2001/09/23 22:24:52 kai Exp $
+/* $Id: w6692.c,v 1.18.2.4 2004/02/11 13:21:34 keil Exp $
  *
  * Winbond W6692 specific routines
  *
@@ -41,60 +41,10 @@ static const PCI_ENTRY id_list[] =
 
 extern const char *CardType[];
 
-const char *w6692_revision = "$Revision: 1.12.6.6 $";
+const char *w6692_revision = "$Revision: 1.18.2.4 $";
 
 #define DBUSY_TIMER_VALUE 80
 
-static inline u8
-w6692_read_reg(struct IsdnCardState *cs, u8 offset)
-{
-	return (inb(cs->hw.w6692.iobase + offset));
-}
-
-static inline void
-w6692_write_reg(struct IsdnCardState *cs, u8 offset, u8 value)
-{
-	outb(value, cs->hw.w6692.iobase + offset);
-}
-
-static void
-w6692_read_fifo(struct IsdnCardState *cs, u8 * data, int size)
-{
-	insb(cs->hw.w6692.iobase + W_D_RFIFO, data, size);
-}
-
-static inline void
-w6692_write_fifo(struct IsdnCardState *cs, u8 * data, int size)
-{
-	outsb(cs->hw.w6692.iobase + W_D_XFIFO, data, size);
-}
-
-static struct dc_hw_ops w6692_dc_hw_ops = {
-	.read_fifo = w6692_read_fifo,
-};
-
-static inline u8
-w6692_bc_read_reg(struct IsdnCardState *cs, int bchan, u8 offset)
-{
-	return (inb(cs->hw.w6692.iobase + (bchan ? 0x40 : 0) + offset));
-}
-
-static inline void
-w6692_bc_write_reg(struct IsdnCardState *cs, int bchan, u8 offset, u8 value)
-{
-	outb(value, cs->hw.w6692.iobase + (bchan ? 0x40 : 0) + offset);
-}
-
-static void
-w6692_bc_read_fifo(struct IsdnCardState *cs, int bchan, u8 *data, int len)
-{
-	insb(cs->hw.w6692.iobase + W_B_RFIFO + (bchan ? 0x40:0), data, len);
-}
-
-static struct bc_hw_ops w6692_bc_hw_ops = {
-	.read_fifo  = w6692_bc_read_fifo,
-};
-
 static char *W6692Ver[] __initdata =
 {"W6692 V00", "W6692 V01", "W6692 V10",
  "W6692 V11"};
@@ -104,7 +54,7 @@ W6692Version(struct IsdnCardState *cs, c
 {
 	int val;
 
-	val = w6692_read_reg(cs, W_D_RBCH);
+	val = cs->readW6692(cs, W_D_RBCH);
 	printk(KERN_INFO "%s Winbond W6692 version (%x): %s\n", s, val, W6692Ver[(val >> 6) & 3]);
 }
 
@@ -113,7 +63,7 @@ ph_command(struct IsdnCardState *cs, uns
 {
 	if (cs->debug & L1_DEB_ISAC)
 		debugl1(cs, "ph_command %x", command);
-	w6692_write_reg(cs, W_CIX, command);
+	cs->writeisac(cs, W_CIX, command);
 }
 
 
@@ -152,9 +102,8 @@ W6692_new_ph(struct IsdnCardState *cs)
 }
 
 static void
-W6692_bh(void *data)
+W6692_bh(struct IsdnCardState *cs)
 {
-	struct IsdnCardState *cs = data;
 	struct PStack *stptr;
 
 	if (!cs)
@@ -164,7 +113,7 @@ W6692_bh(void *data)
 			debugl1(cs, "D-Channel Busy cleared");
 		stptr = cs->stlist;
 		while (stptr != NULL) {
-			L1L2(stptr, PH_PAUSE | CONFIRM, NULL);
+			stptr->l1.l1l2(stptr, PH_PAUSE | CONFIRM, NULL);
 			stptr = stptr->next;
 		}
 	}
@@ -185,22 +134,58 @@ W6692_bh(void *data)
 static void
 W6692_empty_fifo(struct IsdnCardState *cs, int count)
 {
-	recv_empty_fifo_d(cs, count);
-	w6692_write_reg(cs, W_D_CMDR, W_D_CMDR_RACK);
+	u_char *ptr;
+
+	if ((cs->debug & L1_DEB_ISAC) && !(cs->debug & L1_DEB_ISAC_FIFO))
+		debugl1(cs, "W6692_empty_fifo");
+
+	if ((cs->rcvidx + count) >= MAX_DFRAME_LEN_L1) {
+		if (cs->debug & L1_DEB_WARN)
+			debugl1(cs, "W6692_empty_fifo overrun %d",
+				cs->rcvidx + count);
+		cs->writeW6692(cs, W_D_CMDR, W_D_CMDR_RACK);
+		cs->rcvidx = 0;
+		return;
+	}
+	ptr = cs->rcvbuf + cs->rcvidx;
+	cs->rcvidx += count;
+	cs->readW6692fifo(cs, ptr, count);
+	cs->writeW6692(cs, W_D_CMDR, W_D_CMDR_RACK);
+	if (cs->debug & L1_DEB_ISAC_FIFO) {
+		char *t = cs->dlog;
+
+		t += sprintf(t, "W6692_empty_fifo cnt %d", count);
+		QuickHex(t, ptr, count);
+		debugl1(cs, cs->dlog);
+	}
 }
 
 static void
 W6692_fill_fifo(struct IsdnCardState *cs)
 {
 	int count, more;
-	unsigned char *p;
+	u_char *ptr;
+
+	if ((cs->debug & L1_DEB_ISAC) && !(cs->debug & L1_DEB_ISAC_FIFO))
+		debugl1(cs, "W6692_fill_fifo");
 
-	p = xmit_fill_fifo_d(cs, W_D_FIFO_THRESH, &count, &more);
-	if (!p)
+	if (!cs->tx_skb)
 		return;
 
-	w6692_write_fifo(cs, p, count);
-	w6692_write_reg(cs, W_D_CMDR, more ? W_D_CMDR_XMS : (W_D_CMDR_XMS | W_D_CMDR_XME));
+	count = cs->tx_skb->len;
+	if (count <= 0)
+		return;
+
+	more = 0;
+	if (count > W_D_FIFO_THRESH) {
+		more = !0;
+		count = W_D_FIFO_THRESH;
+	}
+	ptr = cs->tx_skb->data;
+	skb_pull(cs->tx_skb, count);
+	cs->tx_cnt += count;
+	cs->writeW6692fifo(cs, ptr, count);
+	cs->writeW6692(cs, W_D_CMDR, more ? W_D_CMDR_XMS : (W_D_CMDR_XMS | W_D_CMDR_XME));
 	if (test_and_set_bit(FLG_DBUSY_TIMER, &cs->HW_Flags)) {
 		debugl1(cs, "W6692_fill_fifo dbusytimer running");
 		del_timer(&cs->dbusytimer);
@@ -208,13 +193,43 @@ W6692_fill_fifo(struct IsdnCardState *cs
 	init_timer(&cs->dbusytimer);
 	cs->dbusytimer.expires = jiffies + ((DBUSY_TIMER_VALUE * HZ) / 1000);
 	add_timer(&cs->dbusytimer);
+	if (cs->debug & L1_DEB_ISAC_FIFO) {
+		char *t = cs->dlog;
+
+		t += sprintf(t, "W6692_fill_fifo cnt %d", count);
+		QuickHex(t, ptr, count);
+		debugl1(cs, cs->dlog);
+	}
 }
 
 static void
 W6692B_empty_fifo(struct BCState *bcs, int count)
 {
-	recv_empty_fifo_b(bcs, count);
-	w6692_bc_write_reg(bcs->cs, bcs->channel, W_B_CMDR, W_B_CMDR_RACK | W_B_CMDR_RACT);
+	u_char *ptr;
+	struct IsdnCardState *cs = bcs->cs;
+
+	if ((cs->debug & L1_DEB_HSCX) && !(cs->debug & L1_DEB_HSCX_FIFO))
+		debugl1(cs, "W6692B_empty_fifo");
+
+	if (bcs->hw.w6692.rcvidx + count > HSCX_BUFMAX) {
+		if (cs->debug & L1_DEB_WARN)
+			debugl1(cs, "W6692B_empty_fifo: incoming packet too large");
+		cs->BC_Write_Reg(cs, bcs->channel, W_B_CMDR, W_B_CMDR_RACK | W_B_CMDR_RACT);
+		bcs->hw.w6692.rcvidx = 0;
+		return;
+	}
+	ptr = bcs->hw.w6692.rcvbuf + bcs->hw.w6692.rcvidx;
+	bcs->hw.w6692.rcvidx += count;
+	READW6692BFIFO(cs, bcs->channel, ptr, count);
+	cs->BC_Write_Reg(cs, bcs->channel, W_B_CMDR, W_B_CMDR_RACK | W_B_CMDR_RACT);
+	if (cs->debug & L1_DEB_HSCX_FIFO) {
+		char *t = bcs->blog;
+
+		t += sprintf(t, "W6692B_empty_fifo %c cnt %d",
+			     bcs->channel + '1', count);
+		QuickHex(t, ptr, count);
+		debugl1(cs, bcs->blog);
+	}
 }
 
 static void
@@ -222,33 +237,50 @@ W6692B_fill_fifo(struct BCState *bcs)
 {
 	struct IsdnCardState *cs = bcs->cs;
 	int more, count;
-	unsigned char *p;
+	u_char *ptr;
 
-	p = xmit_fill_fifo_b(bcs, W_B_FIFO_THRESH, &count, &more);
-	if (!p)
+	if (!bcs->tx_skb)
+		return;
+	if (bcs->tx_skb->len <= 0)
 		return;
 
-	WRITEW6692BFIFO(cs, bcs->channel, p, count);
-	w6692_bc_write_reg(cs, bcs->channel, W_B_CMDR, W_B_CMDR_RACT | W_B_CMDR_XMS | (more ? 0 : W_B_CMDR_XME));
-}
-
-static void
-reset_xmit(struct BCState *bcs)
-{
-	w6692_bc_write_reg(bcs->cs, bcs->channel, W_B_CMDR,
-			   W_B_CMDR_XRST | W_B_CMDR_RACT);
+	more = (bcs->mode == L1_MODE_TRANS) ? 1 : 0;
+	if (bcs->tx_skb->len > W_B_FIFO_THRESH) {
+		more = 1;
+		count = W_B_FIFO_THRESH;
+	} else
+		count = bcs->tx_skb->len;
+
+	if ((cs->debug & L1_DEB_HSCX) && !(cs->debug & L1_DEB_HSCX_FIFO))
+		debugl1(cs, "W6692B_fill_fifo%s%d", (more ? " ": " last "), count);
+
+	ptr = bcs->tx_skb->data;
+	skb_pull(bcs->tx_skb, count);
+	bcs->tx_cnt -= count;
+	bcs->hw.w6692.count += count;
+	WRITEW6692BFIFO(cs, bcs->channel, ptr, count);
+	cs->BC_Write_Reg(cs, bcs->channel, W_B_CMDR, W_B_CMDR_RACT | W_B_CMDR_XMS | (more ? 0 : W_B_CMDR_XME));
+	if (cs->debug & L1_DEB_HSCX_FIFO) {
+		char *t = bcs->blog;
+
+		t += sprintf(t, "W6692B_fill_fifo %c cnt %d",
+			     bcs->channel + '1', count);
+		QuickHex(t, ptr, count);
+		debugl1(cs, bcs->blog);
+	}
 }
 
 static void
-W6692B_interrupt(struct IsdnCardState *cs, u8 bchan)
+W6692B_interrupt(struct IsdnCardState *cs, u_char bchan)
 {
-	u8 val;
-	u8 r;
+	u_char val;
+	u_char r;
 	struct BCState *bcs;
+	struct sk_buff *skb;
 	int count;
 
 	bcs = (cs->bcs->channel == bchan) ? cs->bcs : (cs->bcs+1);
-	val = w6692_bc_read_reg(cs, bchan, W_B_EXIR);
+	val = cs->BC_Read_Reg(cs, bchan, W_B_EXIR);
 	debugl1(cs, "W6692B chan %d B_EXIR 0x%02X", bchan, val);
 
 	if (!test_bit(BC_FLG_INIT, &bcs->Flag)) {
@@ -256,8 +288,10 @@ W6692B_interrupt(struct IsdnCardState *c
 		return;
 	}
 	if (val & W_B_EXI_RME) {	/* RME */
-		r = w6692_bc_read_reg(cs, bchan, W_B_STAR);
-		if (r & (W_B_STAR_RDOV | W_B_STAR_CRCE | W_B_STAR_RMB | W_B_STAR_XDOW)) {
+		r = cs->BC_Read_Reg(cs, bchan, W_B_STAR);
+		if (r & (W_B_STAR_RDOV | W_B_STAR_CRCE | W_B_STAR_RMB)) {
+			if (cs->debug & L1_DEB_WARN)
+				debugl1(cs, "W6692 B STAR %x", r);
 			if ((r & W_B_STAR_RDOV) && bcs->mode)
 				if (cs->debug & L1_DEB_WARN)
 					debugl1(cs, "W6692 B RDOV mode=%d",
@@ -265,46 +299,129 @@ W6692B_interrupt(struct IsdnCardState *c
 			if (r & W_B_STAR_CRCE)
 				if (cs->debug & L1_DEB_WARN)
 					debugl1(cs, "W6692 B CRC error");
-			w6692_bc_write_reg(cs, bchan, W_B_CMDR, W_B_CMDR_RACK | W_B_CMDR_RRST | W_B_CMDR_RACT);
-			bcs->rcvidx = 0;
+			cs->BC_Write_Reg(cs, bchan, W_B_CMDR, W_B_CMDR_RACK | W_B_CMDR_RRST | W_B_CMDR_RACT);
 		} else {
-			count = w6692_bc_read_reg(cs, bchan, W_B_RBCL) & (W_B_FIFO_THRESH - 1);
+			count = cs->BC_Read_Reg(cs, bchan, W_B_RBCL) & (W_B_FIFO_THRESH - 1);
 			if (count == 0)
 				count = W_B_FIFO_THRESH;
 			W6692B_empty_fifo(bcs, count);
-			recv_rme_b(bcs);
+			if ((count = bcs->hw.w6692.rcvidx) > 0) {
+				if (cs->debug & L1_DEB_HSCX_FIFO)
+					debugl1(cs, "W6692 Bchan Frame %d", count);
+				if (!(skb = dev_alloc_skb(count)))
+					printk(KERN_WARNING "W6692: Bchan receive out of memory\n");
+				else {
+					memcpy(skb_put(skb, count), bcs->hw.w6692.rcvbuf, count);
+					skb_queue_tail(&bcs->rqueue, skb);
+				}
+			}
 		}
+		bcs->hw.w6692.rcvidx = 0;
+		schedule_event(bcs, B_RCVBUFREADY);
 	}
 	if (val & W_B_EXI_RMR) {	/* RMR */
 		W6692B_empty_fifo(bcs, W_B_FIFO_THRESH);
-		recv_rpf_b(bcs);
-	}
-	if (val & W_B_EXI_XFR) {	/* XFR */
-		xmit_xpr_b(bcs);
+		r = cs->BC_Read_Reg(cs, bchan, W_B_STAR);
+		if (r & W_B_STAR_RDOV) {
+			if (cs->debug & L1_DEB_WARN)
+				debugl1(cs, "W6692 B RDOV(RMR) mode=%d",bcs->mode);
+			cs->BC_Write_Reg(cs, bchan, W_B_CMDR, W_B_CMDR_RACK | W_B_CMDR_RRST | W_B_CMDR_RACT);
+			if (bcs->mode != L1_MODE_TRANS)
+				bcs->hw.w6692.rcvidx = 0;
+		}
+		if (bcs->mode == L1_MODE_TRANS) {
+			/* receive audio data */
+			if (!(skb = dev_alloc_skb(W_B_FIFO_THRESH)))
+				printk(KERN_WARNING "HiSax: receive out of memory\n");
+			else {
+				memcpy(skb_put(skb, W_B_FIFO_THRESH), bcs->hw.w6692.rcvbuf, W_B_FIFO_THRESH);
+				skb_queue_tail(&bcs->rqueue, skb);
+			}
+			bcs->hw.w6692.rcvidx = 0;
+			schedule_event(bcs, B_RCVBUFREADY);
+		}
 	}
 	if (val & W_B_EXI_XDUN) {	/* XDUN */
-		xmit_xdu_b(bcs, reset_xmit);
+		cs->BC_Write_Reg(cs, bchan, W_B_CMDR, W_B_CMDR_XRST | W_B_CMDR_RACT);
+		if (cs->debug & L1_DEB_WARN)
+			debugl1(cs, "W6692 B EXIR %x Lost TX", val);
+		if (bcs->mode == 1)
+			W6692B_fill_fifo(bcs);
+		else {
+			/* Here we lost an TX interrupt, so
+			   * restart transmitting the whole frame.
+			 */
+			if (bcs->tx_skb) {
+				skb_push(bcs->tx_skb, bcs->hw.w6692.count);
+				bcs->tx_cnt += bcs->hw.w6692.count;
+				bcs->hw.w6692.count = 0;
+			}
+		}
+		return;
+	}
+	if (val & W_B_EXI_XFR) {	/* XFR */
+		r = cs->BC_Read_Reg(cs, bchan, W_B_STAR);
+		if (r & W_B_STAR_XDOW) {
+			if (cs->debug & L1_DEB_WARN)
+				debugl1(cs, "W6692 B STAR %x XDOW", r);
+			cs->BC_Write_Reg(cs, bchan, W_B_CMDR, W_B_CMDR_XRST | W_B_CMDR_RACT);
+			if (bcs->tx_skb && (bcs->mode != 1)) {
+				skb_push(bcs->tx_skb, bcs->hw.w6692.count);
+				bcs->tx_cnt += bcs->hw.w6692.count;
+				bcs->hw.w6692.count = 0;
+			}
+		}
+		if (bcs->tx_skb) {
+			if (bcs->tx_skb->len) {
+				W6692B_fill_fifo(bcs);
+				return;
+			} else {
+				if (test_bit(FLG_LLI_L1WAKEUP,&bcs->st->lli.flag) &&
+					(PACKET_NOACK != bcs->tx_skb->pkt_type)) {
+					u_long	flags;
+					spin_lock_irqsave(&bcs->aclock, flags);
+					bcs->ackcnt += bcs->hw.w6692.count;
+					spin_unlock_irqrestore(&bcs->aclock, flags);
+					schedule_event(bcs, B_ACKPENDING);
+				}
+				dev_kfree_skb_irq(bcs->tx_skb);
+				bcs->hw.w6692.count = 0;
+				bcs->tx_skb = NULL;
+			}
+		}
+		if ((bcs->tx_skb = skb_dequeue(&bcs->squeue))) {
+			bcs->hw.w6692.count = 0;
+			test_and_set_bit(BC_FLG_BUSY, &bcs->Flag);
+			W6692B_fill_fifo(bcs);
+		} else {
+			test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
+			schedule_event(bcs, B_XMTBUFREADY);
+		}
 	}
 }
 
 static irqreturn_t
-w6692_interrupt(int intno, void *dev_id, struct pt_regs *regs)
+W6692_interrupt(int intno, void *dev_id, struct pt_regs *regs)
 {
-	struct IsdnCardState *cs = dev_id;
-	u8 val, exval, v1;
-	unsigned int count;
-	int icnt = 5;
-
-	spin_lock(&cs->lock);
-
-	val = w6692_read_reg(cs, W_ISTA);
-
+	struct IsdnCardState	*cs = dev_id;
+	u_char			val, exval, v1;
+	struct sk_buff		*skb;
+	u_int			count;
+	u_long			flags;
+	int			icnt = 5;
+
+	spin_lock_irqsave(&cs->lock, flags);
+	val = cs->readW6692(cs, W_ISTA);
+	if (!val) {
+		spin_unlock_irqrestore(&cs->lock, flags);
+		return IRQ_NONE;
+	}
       StartW6692:
 	if (cs->debug & L1_DEB_ISAC)
 		debugl1(cs, "W6692 ISTA %x", val);
 
 	if (val & W_INT_D_RME) {	/* RME */
-		exval = w6692_read_reg(cs, W_D_RSTA);
+		exval = cs->readW6692(cs, W_D_RSTA);
 		if (exval & (W_D_RSTA_RDOV | W_D_RSTA_CRCE | W_D_RSTA_RMB)) {
 			if (exval & W_D_RSTA_RDOV)
 				if (cs->debug & L1_DEB_WARN)
@@ -315,58 +432,100 @@ w6692_interrupt(int intno, void *dev_id,
 			if (exval & W_D_RSTA_RMB)
 				if (cs->debug & L1_DEB_WARN)
 					debugl1(cs, "W6692 D-channel ABORT");
-			w6692_write_reg(cs, W_D_CMDR, W_D_CMDR_RACK | W_D_CMDR_RRST);
-			cs->rcvidx = 0;
+			cs->writeW6692(cs, W_D_CMDR, W_D_CMDR_RACK | W_D_CMDR_RRST);
 		} else {
-			count = w6692_read_reg(cs, W_D_RBCL) & (W_D_FIFO_THRESH - 1);
+			count = cs->readW6692(cs, W_D_RBCL) & (W_D_FIFO_THRESH - 1);
 			if (count == 0)
 				count = W_D_FIFO_THRESH;
 			W6692_empty_fifo(cs, count);
-			recv_rme_d(cs);
+			if ((count = cs->rcvidx) > 0) {
+				cs->rcvidx = 0;
+				if (!(skb = alloc_skb(count, GFP_ATOMIC)))
+					printk(KERN_WARNING "HiSax: D receive out of memory\n");
+				else {
+					memcpy(skb_put(skb, count), cs->rcvbuf, count);
+					skb_queue_tail(&cs->rq, skb);
+				}
+			}
 		}
+		cs->rcvidx = 0;
+		schedule_event(cs, D_RCVBUFREADY);
 	}
 	if (val & W_INT_D_RMR) {	/* RMR */
 		W6692_empty_fifo(cs, W_D_FIFO_THRESH);
 	}
 	if (val & W_INT_D_XFR) {	/* XFR */
-		xmit_xpr_d(cs);
+		if (test_and_clear_bit(FLG_DBUSY_TIMER, &cs->HW_Flags))
+			del_timer(&cs->dbusytimer);
+		if (test_and_clear_bit(FLG_L1_DBUSY, &cs->HW_Flags))
+			schedule_event(cs, D_CLEARBUSY);
+		if (cs->tx_skb) {
+			if (cs->tx_skb->len) {
+				W6692_fill_fifo(cs);
+				goto afterXFR;
+			} else {
+				dev_kfree_skb_irq(cs->tx_skb);
+				cs->tx_cnt = 0;
+				cs->tx_skb = NULL;
+			}
+		}
+		if ((cs->tx_skb = skb_dequeue(&cs->sq))) {
+			cs->tx_cnt = 0;
+			W6692_fill_fifo(cs);
+		} else
+			schedule_event(cs, D_XMTBUFREADY);
 	}
+      afterXFR:
 	if (val & (W_INT_XINT0 | W_INT_XINT1)) {	/* XINT0/1 - never */
 		if (cs->debug & L1_DEB_ISAC)
 			debugl1(cs, "W6692 spurious XINT!");
 	}
 	if (val & W_INT_D_EXI) {	/* EXI */
-		exval = w6692_read_reg(cs, W_D_EXIR);
+		exval = cs->readW6692(cs, W_D_EXIR);
 		if (cs->debug & L1_DEB_WARN)
 			debugl1(cs, "W6692 D_EXIR %02x", exval);
 		if (exval & (W_D_EXI_XDUN | W_D_EXI_XCOL)) {	/* Transmit underrun/collision */
-			xmit_xdu_d(cs, NULL);
+			debugl1(cs, "W6692 D-chan underrun/collision");
+			printk(KERN_WARNING "HiSax: W6692 XDUN/XCOL\n");
+			if (test_and_clear_bit(FLG_DBUSY_TIMER, &cs->HW_Flags))
+				del_timer(&cs->dbusytimer);
+			if (test_and_clear_bit(FLG_L1_DBUSY, &cs->HW_Flags))
+				schedule_event(cs, D_CLEARBUSY);
+			if (cs->tx_skb) {	/* Restart frame */
+				skb_push(cs->tx_skb, cs->tx_cnt);
+				cs->tx_cnt = 0;
+				W6692_fill_fifo(cs);
+			} else {
+				printk(KERN_WARNING "HiSax: W6692 XDUN/XCOL no skb\n");
+				debugl1(cs, "W6692 XDUN/XCOL no skb");
+				cs->writeW6692(cs, W_D_CMDR, W_D_CMDR_XRST);
+			}
 		}
 		if (exval & W_D_EXI_RDOV) {	/* RDOV */
 			debugl1(cs, "W6692 D-channel RDOV");
 			printk(KERN_WARNING "HiSax: W6692 D-RDOV\n");
-			w6692_write_reg(cs, W_D_CMDR, W_D_CMDR_RRST);
+			cs->writeW6692(cs, W_D_CMDR, W_D_CMDR_RRST);
 		}
 		if (exval & W_D_EXI_TIN2) {	/* TIN2 - never */
 			debugl1(cs, "W6692 spurious TIN2 interrupt");
 		}
 		if (exval & W_D_EXI_MOC) {	/* MOC - not supported */
 			debugl1(cs, "W6692 spurious MOC interrupt");
-			v1 = w6692_read_reg(cs, W_MOSR);
+			v1 = cs->readW6692(cs, W_MOSR);
 			debugl1(cs, "W6692 MOSR %02x", v1);
 		}
 		if (exval & W_D_EXI_ISC) {	/* ISC - Level1 change */
-			v1 = w6692_read_reg(cs, W_CIR);
+			v1 = cs->readW6692(cs, W_CIR);
 			if (cs->debug & L1_DEB_ISAC)
 				debugl1(cs, "W6692 ISC CIR=0x%02X", v1);
 			if (v1 & W_CIR_ICC) {
 				cs->dc.w6692.ph_state = v1 & W_CIR_COD_MASK;
 				if (cs->debug & L1_DEB_ISAC)
 					debugl1(cs, "ph_state_change %x", cs->dc.w6692.ph_state);
-				sched_d_event(cs, D_L1STATECHANGE);
+				schedule_event(cs, D_L1STATECHANGE);
 			}
 			if (v1 & W_CIR_SCC) {
-				v1 = w6692_read_reg(cs, W_SQR);
+				v1 = cs->readW6692(cs, W_SQR);
 				debugl1(cs, "W6692 SCC SQR=0x%02X", v1);
 			}
 		}
@@ -385,16 +544,16 @@ w6692_interrupt(int intno, void *dev_id,
 		debugl1(cs, "W6692 B channel 2 interrupt");
 		W6692B_interrupt(cs, 1);
 	}
-	val = w6692_read_reg(cs, W_ISTA);
+	val = cs->readW6692(cs, W_ISTA);
 	if (val && icnt) {
 		icnt--;
 		goto StartW6692;
 	}
 	if (!icnt) {
 		printk(KERN_WARNING "W6692 IRQ LOOP\n");
-		w6692_write_reg(cs, W_IMASK, 0xff);
+		cs->writeW6692(cs, W_IMASK, 0xff);
 	}
-	spin_unlock(&cs->lock);
+	spin_unlock_irqrestore(&cs->lock, flags);
 	return IRQ_HANDLED;
 }
 
@@ -403,32 +562,87 @@ W6692_l1hw(struct PStack *st, int pr, vo
 {
 	struct IsdnCardState *cs = (struct IsdnCardState *) st->l1.hardware;
 	struct sk_buff *skb = arg;
+	u_long flags;
 	int val;
 
 	switch (pr) {
 		case (PH_DATA | REQUEST):
-			xmit_data_req_d(cs, skb);
+			if (cs->debug & DEB_DLOG_HEX)
+				LogFrame(cs, skb->data, skb->len);
+			if (cs->debug & DEB_DLOG_VERBOSE)
+				dlogframe(cs, skb, 0);
+			spin_lock_irqsave(&cs->lock, flags);
+			if (cs->tx_skb) {
+				skb_queue_tail(&cs->sq, skb);
+#ifdef L2FRAME_DEBUG		/* psa */
+				if (cs->debug & L1_DEB_LAPD)
+					Logl2Frame(cs, skb, "PH_DATA Queued", 0);
+#endif
+			} else {
+				cs->tx_skb = skb;
+				cs->tx_cnt = 0;
+#ifdef L2FRAME_DEBUG		/* psa */
+				if (cs->debug & L1_DEB_LAPD)
+					Logl2Frame(cs, skb, "PH_DATA", 0);
+#endif
+				W6692_fill_fifo(cs);
+			}
+			spin_unlock_irqrestore(&cs->lock, flags);
 			break;
-		case (PH_PULL |INDICATION):
-			xmit_pull_ind_d(cs, skb);
+		case (PH_PULL | INDICATION):
+			spin_lock_irqsave(&cs->lock, flags);
+			if (cs->tx_skb) {
+				if (cs->debug & L1_DEB_WARN)
+					debugl1(cs, " l2l1 tx_skb exist this shouldn't happen");
+				skb_queue_tail(&cs->sq, skb);
+				spin_unlock_irqrestore(&cs->lock, flags);
+				break;
+			}
+			if (cs->debug & DEB_DLOG_HEX)
+				LogFrame(cs, skb->data, skb->len);
+			if (cs->debug & DEB_DLOG_VERBOSE)
+				dlogframe(cs, skb, 0);
+			cs->tx_skb = skb;
+			cs->tx_cnt = 0;
+#ifdef L2FRAME_DEBUG		/* psa */
+			if (cs->debug & L1_DEB_LAPD)
+				Logl2Frame(cs, skb, "PH_DATA_PULLED", 0);
+#endif
+			W6692_fill_fifo(cs);
+			spin_unlock_irqrestore(&cs->lock, flags);
 			break;
 		case (PH_PULL | REQUEST):
-			xmit_pull_req_d(st);
+#ifdef L2FRAME_DEBUG		/* psa */
+			if (cs->debug & L1_DEB_LAPD)
+				debugl1(cs, "-> PH_REQUEST_PULL");
+#endif
+			if (!cs->tx_skb) {
+				test_and_clear_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
+				st->l1.l1l2(st, PH_PULL | CONFIRM, NULL);
+			} else
+				test_and_set_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
 			break;
 		case (HW_RESET | REQUEST):
-			if ((cs->dc.w6692.ph_state == W_L1IND_DRD))
+			spin_lock_irqsave(&cs->lock, flags);
+			if ((cs->dc.w6692.ph_state == W_L1IND_DRD)) {
 				ph_command(cs, W_L1CMD_ECK);
-			else {
+				spin_unlock_irqrestore(&cs->lock, flags);
+			} else {
 				ph_command(cs, W_L1CMD_RST);
 				cs->dc.w6692.ph_state = W_L1CMD_RST;
+				spin_unlock_irqrestore(&cs->lock, flags);
 				W6692_new_ph(cs);
 			}
 			break;
 		case (HW_ENABLE | REQUEST):
+			spin_lock_irqsave(&cs->lock, flags);
 			ph_command(cs, W_L1CMD_ECK);
+			spin_unlock_irqrestore(&cs->lock, flags);
 			break;
 		case (HW_INFO3 | REQUEST):
+			spin_lock_irqsave(&cs->lock, flags);
 			ph_command(cs, W_L1CMD_AR8);
+			spin_unlock_irqrestore(&cs->lock, flags);
 			break;
 		case (HW_TESTLOOP | REQUEST):
 			val = 0;
@@ -448,7 +662,7 @@ W6692_l1hw(struct PStack *st, int pr, vo
 			if (test_and_clear_bit(FLG_DBUSY_TIMER, &cs->HW_Flags))
 				del_timer(&cs->dbusytimer);
 			if (test_and_clear_bit(FLG_L1_DBUSY, &cs->HW_Flags))
-				sched_d_event(cs, D_CLEARBUSY);
+				schedule_event(cs, D_CLEARBUSY);
 			break;
 		default:
 			if (cs->debug & L1_DEB_WARN)
@@ -457,11 +671,15 @@ W6692_l1hw(struct PStack *st, int pr, vo
 	}
 }
 
-static int
+static void
 setstack_W6692(struct PStack *st, struct IsdnCardState *cs)
 {
 	st->l1.l1hw = W6692_l1hw;
-	return 0;
+}
+
+static void
+DC_Close_W6692(struct IsdnCardState *cs)
+{
 }
 
 static void
@@ -469,10 +687,12 @@ dbusy_timer_handler(struct IsdnCardState
 {
 	struct PStack *stptr;
 	int rbch, star;
+	u_long flags;
 
+	spin_lock_irqsave(&cs->lock, flags);
 	if (test_bit(FLG_DBUSY_TIMER, &cs->HW_Flags)) {
-		rbch = w6692_read_reg(cs, W_D_RBCH);
-		star = w6692_read_reg(cs, W_D_STAR);
+		rbch = cs->readW6692(cs, W_D_RBCH);
+		star = cs->readW6692(cs, W_D_STAR);
 		if (cs->debug)
 			debugl1(cs, "D-Channel Busy D_RBCH %02x D_STAR %02x",
 				rbch, star);
@@ -480,7 +700,7 @@ dbusy_timer_handler(struct IsdnCardState
 			test_and_set_bit(FLG_L1_DBUSY, &cs->HW_Flags);
 			stptr = cs->stlist;
 			while (stptr != NULL) {
-				L1L2(stptr, PH_PAUSE | INDICATION, NULL);
+				stptr->l1.l1l2(stptr, PH_PAUSE | INDICATION, NULL);
 				stptr = stptr->next;
 			}
 		} else {
@@ -494,10 +714,13 @@ dbusy_timer_handler(struct IsdnCardState
 				printk(KERN_WARNING "HiSax: W6692 D-Channel Busy no skb\n");
 				debugl1(cs, "D-Channel Busy no skb");
 			}
-			w6692_write_reg(cs, W_D_CMDR, W_D_CMDR_XRST);	/* Transmitter reset */
-			cs->card_ops->irq_func(cs->irq, cs, NULL); /* FIXME? */
+			cs->writeW6692(cs, W_D_CMDR, W_D_CMDR_XRST);	/* Transmitter reset */
+			spin_unlock_irqrestore(&cs->lock, flags);
+			cs->irq_func(cs->irq, cs, NULL);
+			return;
 		}
 	}
+	spin_unlock_irqrestore(&cs->lock, flags);
 }
 
 static void
@@ -514,51 +737,79 @@ W6692Bmode(struct BCState *bcs, int mode
 
 	switch (mode) {
 		case (L1_MODE_NULL):
-			w6692_bc_write_reg(cs, bchan, W_B_MODE, 0);
+			cs->BC_Write_Reg(cs, bchan, W_B_MODE, 0);
 			break;
 		case (L1_MODE_TRANS):
-			w6692_bc_write_reg(cs, bchan, W_B_MODE, W_B_MODE_MMS);
+			cs->BC_Write_Reg(cs, bchan, W_B_MODE, W_B_MODE_MMS);
 			break;
 		case (L1_MODE_HDLC):
-			w6692_bc_write_reg(cs, bchan, W_B_MODE, W_B_MODE_ITF);
-			w6692_bc_write_reg(cs, bchan, W_B_ADM1, 0xff);
-			w6692_bc_write_reg(cs, bchan, W_B_ADM2, 0xff);
+			cs->BC_Write_Reg(cs, bchan, W_B_MODE, W_B_MODE_ITF);
+			cs->BC_Write_Reg(cs, bchan, W_B_ADM1, 0xff);
+			cs->BC_Write_Reg(cs, bchan, W_B_ADM2, 0xff);
 			break;
 	}
 	if (mode)
-		w6692_bc_write_reg(cs, bchan, W_B_CMDR, W_B_CMDR_RRST |
+		cs->BC_Write_Reg(cs, bchan, W_B_CMDR, W_B_CMDR_RRST |
 				 W_B_CMDR_RACT | W_B_CMDR_XRST);
-	w6692_bc_write_reg(cs, bchan, W_B_EXIM, 0x00);
+	cs->BC_Write_Reg(cs, bchan, W_B_EXIM, 0x00);
 }
 
 static void
 W6692_l2l1(struct PStack *st, int pr, void *arg)
 {
 	struct sk_buff *skb = arg;
+	struct BCState *bcs = st->l1.bcs; 
+	u_long flags;
 
 	switch (pr) {
 		case (PH_DATA | REQUEST):
-			xmit_data_req_b(st->l1.bcs, skb);
+			spin_lock_irqsave(&bcs->cs->lock, flags);
+			if (bcs->tx_skb) {
+				skb_queue_tail(&bcs->squeue, skb);
+			} else {
+				bcs->tx_skb = skb;
+				test_and_set_bit(BC_FLG_BUSY, &bcs->Flag);
+				bcs->hw.w6692.count = 0;
+				bcs->cs->BC_Send_Data(bcs);
+			}
+			spin_unlock_irqrestore(&bcs->cs->lock, flags);
 			break;
 		case (PH_PULL | INDICATION):
-			xmit_pull_ind_b(st->l1.bcs, skb);
+			if (bcs->tx_skb) {
+				printk(KERN_WARNING "W6692_l2l1: this shouldn't happen\n");
+				break;
+			}
+			spin_lock_irqsave(&bcs->cs->lock, flags);
+			test_and_set_bit(BC_FLG_BUSY, &bcs->Flag);
+			bcs->tx_skb = skb;
+			bcs->hw.w6692.count = 0;
+			bcs->cs->BC_Send_Data(bcs);
+			spin_unlock_irqrestore(&bcs->cs->lock, flags);
 			break;
 		case (PH_PULL | REQUEST):
-			xmit_pull_req_b(st);
+			if (!bcs->tx_skb) {
+				test_and_clear_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
+				st->l1.l1l2(st, PH_PULL | CONFIRM, NULL);
+			} else
+				test_and_set_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
 			break;
 		case (PH_ACTIVATE | REQUEST):
-			test_and_set_bit(BC_FLG_ACTIV, &st->l1.bcs->Flag);
-			W6692Bmode(st->l1.bcs, st->l1.mode, st->l1.bc);
+			spin_lock_irqsave(&bcs->cs->lock, flags);
+			test_and_set_bit(BC_FLG_ACTIV, &bcs->Flag);
+			W6692Bmode(bcs, st->l1.mode, st->l1.bc);
+			spin_unlock_irqrestore(&bcs->cs->lock, flags);
 			l1_msg_b(st, pr, arg);
 			break;
 		case (PH_DEACTIVATE | REQUEST):
 			l1_msg_b(st, pr, arg);
 			break;
 		case (PH_DEACTIVATE | CONFIRM):
-			test_and_clear_bit(BC_FLG_ACTIV, &st->l1.bcs->Flag);
-			test_and_clear_bit(BC_FLG_BUSY, &st->l1.bcs->Flag);
-			W6692Bmode(st->l1.bcs, 0, st->l1.bc);
-			L1L2(st, PH_DEACTIVATE | CONFIRM, NULL);
+			spin_lock_irqsave(&bcs->cs->lock, flags);
+			test_and_clear_bit(BC_FLG_ACTIV, &bcs->Flag);
+			test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
+			W6692Bmode(bcs, 0, st->l1.bc);
+			spin_unlock_irqrestore(&bcs->cs->lock, flags);
+			st->l1.l1l2(st, PH_DEACTIVATE | CONFIRM, NULL);
 			break;
 	}
 }
@@ -567,13 +818,52 @@ static void
 close_w6692state(struct BCState *bcs)
 {
 	W6692Bmode(bcs, 0, bcs->channel);
-	bc_close(bcs);
+	if (test_and_clear_bit(BC_FLG_INIT, &bcs->Flag)) {
+		if (bcs->hw.w6692.rcvbuf) {
+			kfree(bcs->hw.w6692.rcvbuf);
+			bcs->hw.w6692.rcvbuf = NULL;
+		}
+		if (bcs->blog) {
+			kfree(bcs->blog);
+			bcs->blog = NULL;
+		}
+		skb_queue_purge(&bcs->rqueue);
+		skb_queue_purge(&bcs->squeue);
+		if (bcs->tx_skb) {
+			dev_kfree_skb_any(bcs->tx_skb);
+			bcs->tx_skb = NULL;
+			test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
+		}
+	}
 }
 
 static int
 open_w6692state(struct IsdnCardState *cs, struct BCState *bcs)
 {
-	return bc_open(bcs);
+	if (!test_and_set_bit(BC_FLG_INIT, &bcs->Flag)) {
+		if (!(bcs->hw.w6692.rcvbuf = kmalloc(HSCX_BUFMAX, GFP_ATOMIC))) {
+			printk(KERN_WARNING
+			       "HiSax: No memory for w6692.rcvbuf\n");
+			test_and_clear_bit(BC_FLG_INIT, &bcs->Flag);
+			return (1);
+		}
+		if (!(bcs->blog = kmalloc(MAX_BLOG_SPACE, GFP_ATOMIC))) {
+			printk(KERN_WARNING
+			       "HiSax: No memory for bcs->blog\n");
+			test_and_clear_bit(BC_FLG_INIT, &bcs->Flag);
+			kfree(bcs->hw.w6692.rcvbuf);
+			bcs->hw.w6692.rcvbuf = NULL;
+			return (2);
+		}
+		skb_queue_head_init(&bcs->rqueue);
+		skb_queue_head_init(&bcs->squeue);
+	}
+	bcs->tx_skb = NULL;
+	test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
+	bcs->event = 0;
+	bcs->hw.w6692.rcvidx = 0;
+	bcs->tx_cnt = 0;
+	return (0);
 }
 
 static int
@@ -583,166 +873,224 @@ setstack_w6692(struct PStack *st, struct
 	if (open_w6692state(st->l1.hardware, bcs))
 		return (-1);
 	st->l1.bcs = bcs;
-	st->l1.l2l1 = W6692_l2l1;
+	st->l2.l2l1 = W6692_l2l1;
 	setstack_manager(st);
 	bcs->st = st;
 	setstack_l1_B(st);
 	return (0);
 }
 
-static int
-w6692_reset(struct IsdnCardState *cs)
+void resetW6692(struct IsdnCardState *cs)
 {
-	w6692_write_reg(cs, W_D_CTL, W_D_CTL_SRST);
-	schedule_timeout((10*HZ)/1000);
-	w6692_write_reg(cs, W_D_CTL, 0x00);
-	schedule_timeout((10*HZ)/1000);
-	w6692_write_reg(cs, W_IMASK, 0xff);
-	w6692_write_reg(cs, W_D_SAM, 0xff);
-	w6692_write_reg(cs, W_D_TAM, 0xff);
-	w6692_write_reg(cs, W_D_EXIM, 0x00);
-	w6692_write_reg(cs, W_D_MODE, W_D_MODE_RACT);
-	w6692_write_reg(cs, W_IMASK, 0x18);
+	cs->writeW6692(cs, W_D_CTL, W_D_CTL_SRST);
+	mdelay(10);
+	cs->writeW6692(cs, W_D_CTL, 0x00);
+	mdelay(10);
+	cs->writeW6692(cs, W_IMASK, 0xff);
+	cs->writeW6692(cs, W_D_SAM, 0xff);
+	cs->writeW6692(cs, W_D_TAM, 0xff);
+	cs->writeW6692(cs, W_D_EXIM, 0x00);
+	cs->writeW6692(cs, W_D_MODE, W_D_MODE_RACT);
+	cs->writeW6692(cs, W_IMASK, 0x18);
 	if (cs->subtyp == W6692_USR) {
 		/* seems that USR implemented some power control features
 		 * Pin 79 is connected to the oscilator circuit so we
 		 * have to handle it here
 		 */
-		w6692_write_reg(cs, W_PCTL, 0x80);
-		w6692_write_reg(cs, W_XDATA, 0x00);
+		cs->writeW6692(cs, W_PCTL, 0x80);
+		cs->writeW6692(cs, W_XDATA, 0x00);
 	}
-	return 0;
 }
 
-static void
-w6692_init(struct IsdnCardState *cs)
+void __init initW6692(struct IsdnCardState *cs, int part)
 {
-	w6692_reset(cs);
-	ph_command(cs, W_L1CMD_RST);
-	cs->dc.w6692.ph_state = W_L1CMD_RST;
-	W6692_new_ph(cs);
-	ph_command(cs, W_L1CMD_ECK);
-	
-	W6692Bmode(cs->bcs, 0, 0);
-	W6692Bmode(cs->bcs + 1, 0, 0);
+	if (part & 1) {
+		cs->setstack_d = setstack_W6692;
+		cs->DC_Close = DC_Close_W6692;
+		cs->dbusytimer.function = (void *) dbusy_timer_handler;
+		cs->dbusytimer.data = (long) cs;
+		init_timer(&cs->dbusytimer);
+		resetW6692(cs);
+		ph_command(cs, W_L1CMD_RST);
+		cs->dc.w6692.ph_state = W_L1CMD_RST;
+		W6692_new_ph(cs);
+		ph_command(cs, W_L1CMD_ECK);
 
-	/* Reenable all IRQ */
-	w6692_write_reg(cs, W_IMASK, 0x18);
-	w6692_write_reg(cs, W_D_EXIM, 0x00);
-	w6692_bc_write_reg(cs, 0, W_B_EXIM, 0x00);
-	w6692_bc_write_reg(cs, 1, W_B_EXIM, 0x00);
-	/* Reset D-chan receiver and transmitter */
-	w6692_write_reg(cs, W_D_CMDR, W_D_CMDR_RRST | W_D_CMDR_XRST);
+		cs->bcs[0].BC_SetStack = setstack_w6692;
+		cs->bcs[1].BC_SetStack = setstack_w6692;
+		cs->bcs[0].BC_Close = close_w6692state;
+		cs->bcs[1].BC_Close = close_w6692state;
+		W6692Bmode(cs->bcs, 0, 0);
+		W6692Bmode(cs->bcs + 1, 0, 0);
+	}
+	if (part & 2) {
+		/* Reenable all IRQ */
+		cs->writeW6692(cs, W_IMASK, 0x18);
+		cs->writeW6692(cs, W_D_EXIM, 0x00);
+		cs->BC_Write_Reg(cs, 0, W_B_EXIM, 0x00);
+		cs->BC_Write_Reg(cs, 1, W_B_EXIM, 0x00);
+		/* Reset D-chan receiver and transmitter */
+		cs->writeW6692(cs, W_D_CMDR, W_D_CMDR_RRST | W_D_CMDR_XRST);
+	}
 }
 
+/* Interface functions */
 
-static void
-w6692_release(struct IsdnCardState *cs)
+static u_char
+ReadW6692(struct IsdnCardState *cs, u_char offset)
 {
-	w6692_write_reg(cs, W_IMASK, 0xff);
-	if (cs->subtyp == W6692_USR)
-		w6692_write_reg(cs, W_XDATA, 0x04);
-	hisax_release_resources(cs);
+	return (inb(cs->hw.w6692.iobase + offset));
 }
 
-static struct card_ops w6692_ops = {
-	.init     = w6692_init,
-	.reset    = w6692_reset,
-	.release  = w6692_release,
-	.irq_func = w6692_interrupt,
-};
-
-static struct dc_l1_ops w6692_dc_l1_ops = {
-	.fill_fifo  = W6692_fill_fifo,
-	.open       = setstack_W6692,
-	.bh_func    = W6692_bh,
-	.dbusy_func = dbusy_timer_handler,
-};
-
-static struct bc_l1_ops w6692_bc_l1_ops = {
-	.fill_fifo = W6692B_fill_fifo,
-	.open      = setstack_w6692,
-	.close     = close_w6692state,
-};
+static void
+WriteW6692(struct IsdnCardState *cs, u_char offset, u_char value)
+{
+	outb(value, cs->hw.w6692.iobase + offset);
+}
 
-static int id_idx ;
+static void
+ReadISACfifo(struct IsdnCardState *cs, u_char * data, int size)
+{
+	insb(cs->hw.w6692.iobase + W_D_RFIFO, data, size);
+}
 
-static struct pci_dev *dev_w6692 __initdata = NULL;
+static void
+WriteISACfifo(struct IsdnCardState *cs, u_char * data, int size)
+{
+	outsb(cs->hw.w6692.iobase + W_D_XFIFO, data, size);
+}
 
-static int
-w6692_hw_init(struct IsdnCardState *cs)
+static u_char
+ReadW6692B(struct IsdnCardState *cs, int bchan, u_char offset)
 {
-	cs->card_ops = &w6692_ops;
-	cs->dc_hw_ops = &w6692_dc_hw_ops, 
-	cs->bc_hw_ops = &w6692_bc_hw_ops;
-	dc_l1_init(cs, &w6692_dc_l1_ops);
-	cs->bc_l1_ops = &w6692_bc_l1_ops;
-	W6692Version(cs, "W6692:");
-	printk(KERN_INFO "W6692 ISTA=0x%X\n", w6692_read_reg(cs, W_ISTA));
-	printk(KERN_INFO "W6692 IMASK=0x%X\n", w6692_read_reg(cs, W_IMASK));
-	printk(KERN_INFO "W6692 D_EXIR=0x%X\n", w6692_read_reg(cs, W_D_EXIR));
-	printk(KERN_INFO "W6692 D_EXIM=0x%X\n", w6692_read_reg(cs, W_D_EXIM));
-	printk(KERN_INFO "W6692 D_RSTA=0x%X\n", w6692_read_reg(cs, W_D_RSTA));
-	return 0;
+	return (inb(cs->hw.w6692.iobase + (bchan ? 0x40 : 0) + offset));
 }
 
-static int __init
-w6692_probe(struct IsdnCardState *cs, struct pci_dev *pdev)
+static void
+WriteW6692B(struct IsdnCardState *cs, int bchan, u_char offset, u_char value)
 {
-	int rc;
+	outb(value, cs->hw.w6692.iobase + (bchan ? 0x40 : 0) + offset);
+}
 
-	printk(KERN_INFO "W6692: %s %s at %#lx IRQ %d\n",
-	       id_list[cs->subtyp].vendor_name, id_list[cs->subtyp].card_name,
-	       pci_resource_start(pdev, 1), pdev->irq);
-	
-	rc = -EBUSY;
-	if (pci_enable_device(pdev))
-		goto err;
-			
-	/* USR ISDN PCI card TA need some special handling */
-	if (cs->subtyp == W6692_WINBOND) {
-		if (pdev->subsystem_vendor == W6692_SV_USR  &&
-		    pdev->subsystem_device == W6692_SD_USR) {
-			cs->subtyp = W6692_USR;
-		}
+static int
+w6692_card_msg(struct IsdnCardState *cs, int mt, void *arg)
+{
+	switch (mt) {
+		case CARD_RESET:
+			resetW6692(cs);
+			return (0);
+		case CARD_RELEASE:
+			cs->writeW6692(cs, W_IMASK, 0xff);
+			release_region(cs->hw.w6692.iobase, 256);
+			if (cs->subtyp == W6692_USR) {
+				cs->writeW6692(cs, W_XDATA, 0x04);
+			}
+			return (0);
+		case CARD_INIT:
+			initW6692(cs, 3);
+			return (0);
+		case CARD_TEST:
+			return (0);
 	}
-	cs->irq = pdev->irq;
-	cs->irq_flags |= SA_SHIRQ;
-	cs->hw.w6692.iobase = pci_resource_start(pdev, 1);
-	
-	if (!request_io(&cs->rs, cs->hw.w6692.iobase, 0x100,
-			id_list[cs->subtyp].card_name))
-		goto err;
-
-	w6692_hw_init(cs);
-	return 0;
- err:
-	hisax_release_resources(cs);
-	return rc;
+	return (0);
 }
 
+static int id_idx ;
+
+static struct pci_dev *dev_w6692 __initdata = NULL;
+
 int __init 
 setup_w6692(struct IsdnCard *card)
 {
+	struct IsdnCardState *cs = card->cs;
 	char tmp[64];
+	u_char found = 0;
+	u_char pci_irq = 0;
+	u_int pci_ioaddr = 0;
 
-#ifdef __BIG_ENDIAN
-#error "not running on big endian machines now"
-#endif
 	strcpy(tmp, w6692_revision);
 	printk(KERN_INFO "HiSax: W6692 driver Rev. %s\n", HiSax_getrev(tmp));
+	if (cs->typ != ISDN_CTYPE_W6692)
+		return (0);
+#if CONFIG_PCI
 	while (id_list[id_idx].vendor_id) {
 		dev_w6692 = pci_find_device(id_list[id_idx].vendor_id,
 					    id_list[id_idx].device_id,
 					    dev_w6692);
 		if (dev_w6692) {
-			card->cs->subtyp = id_idx;
-			if (w6692_probe(card->cs, dev_w6692) < 0)
-				return 0;
-			return 1;
+			if (pci_enable_device(dev_w6692))
+				continue;
+			cs->subtyp = id_idx;
+			break;
 		}
 		id_idx++;
 	}
-	printk(KERN_WARNING "W6692: No PCI card found\n");
-	return 0;
+	if (dev_w6692) {
+		found = 1;
+		pci_irq = dev_w6692->irq;
+		/* I think address 0 is allways the configuration area */
+		/* and address 1 is the real IO space KKe 03.09.99 */
+		pci_ioaddr = pci_resource_start(dev_w6692, 1);
+		/* USR ISDN PCI card TA need some special handling */
+		if (cs->subtyp == W6692_WINBOND) {
+			if ((W6692_SV_USR == dev_w6692->subsystem_vendor) &&
+			    (W6692_SD_USR == dev_w6692->subsystem_device)) {
+				cs->subtyp = W6692_USR;
+			}
+		}
+	}
+	if (!found) {
+		printk(KERN_WARNING "W6692: No PCI card found\n");
+		return (0);
+	}
+	cs->irq = pci_irq;
+	if (!cs->irq) {
+		printk(KERN_WARNING "W6692: No IRQ for PCI card found\n");
+		return (0);
+	}
+	if (!pci_ioaddr) {
+		printk(KERN_WARNING "W6692: NO I/O Base Address found\n");
+		return (0);
+	}
+	cs->hw.w6692.iobase = pci_ioaddr;
+	printk(KERN_INFO "Found: %s %s, I/O base: 0x%x, irq: %d\n",
+	       id_list[cs->subtyp].vendor_name, id_list[cs->subtyp].card_name,
+	       pci_ioaddr, pci_irq);
+	if (!request_region(cs->hw.w6692.iobase, 256, id_list[cs->subtyp].card_name)) {
+		printk(KERN_WARNING
+		       "HiSax: %s I/O ports %x-%x already in use\n",
+		       id_list[cs->subtyp].card_name,
+		       cs->hw.w6692.iobase,
+		       cs->hw.w6692.iobase + 255);
+		return (0);
+	}
+#else
+	printk(KERN_WARNING "HiSax: W6692 and NO_PCI_BIOS\n");
+	printk(KERN_WARNING "HiSax: W6692 unable to config\n");
+	return (0);
+#endif				/* CONFIG_PCI */
+
+	printk(KERN_INFO
+	       "HiSax: %s config irq:%d I/O:%x\n",
+	       id_list[cs->subtyp].card_name, cs->irq,
+	       cs->hw.w6692.iobase);
+
+	INIT_WORK(&cs->tqueue, (void *)(void *) W6692_bh, cs);
+	cs->readW6692 = &ReadW6692;
+	cs->writeW6692 = &WriteW6692;
+	cs->readisacfifo = &ReadISACfifo;
+	cs->writeisacfifo = &WriteISACfifo;
+	cs->BC_Read_Reg = &ReadW6692B;
+	cs->BC_Write_Reg = &WriteW6692B;
+	cs->BC_Send_Data = &W6692B_fill_fifo;
+	cs->cardmsg = &w6692_card_msg;
+	cs->irq_func = &W6692_interrupt;
+	cs->irq_flags |= SA_SHIRQ;
+	W6692Version(cs, "W6692:");
+	printk(KERN_INFO "W6692 ISTA=0x%X\n", ReadW6692(cs, W_ISTA));
+	printk(KERN_INFO "W6692 IMASK=0x%X\n", ReadW6692(cs, W_IMASK));
+	printk(KERN_INFO "W6692 D_EXIR=0x%X\n", ReadW6692(cs, W_D_EXIR));
+	printk(KERN_INFO "W6692 D_EXIM=0x%X\n", ReadW6692(cs, W_D_EXIM));
+	printk(KERN_INFO "W6692 D_RSTA=0x%X\n", ReadW6692(cs, W_D_RSTA));
+	return (1);
 }
--- diff/drivers/isdn/hisax/w6692.h	2003-01-16 11:30:36.000000000 +0000
+++ source/drivers/isdn/hisax/w6692.h	2004-02-23 13:56:42.000000000 +0000
@@ -1,4 +1,4 @@
-/* $Id: w6692.h,v 1.2.6.2 2001/09/23 22:24:52 kai Exp $
+/* $Id: w6692.h,v 1.4.2.2 2004/01/12 22:52:29 keil Exp $
  *
  * Winbond W6692 specific defines
  *
@@ -18,6 +18,9 @@
 
 /* B-channel FIFO read/write routines */
 
+#define READW6692BFIFO(cs,bchan,ptr,count) \
+	insb(cs->hw.w6692.iobase+W_B_RFIFO+(bchan?0x40:0),ptr,count)
+
 #define WRITEW6692BFIFO(cs,bchan,ptr,count) \
 	outsb(cs->hw.w6692.iobase+W_B_XFIFO+(bchan?0x40:0),ptr,count)
 
--- diff/drivers/isdn/hysdn/Kconfig	2003-02-13 11:46:52.000000000 +0000
+++ source/drivers/isdn/hysdn/Kconfig	2004-02-23 13:56:42.000000000 +0000
@@ -3,7 +3,7 @@
 #
 config HYSDN
 	tristate "Hypercope HYSDN cards (Champ, Ergo, Metro) support (module only)"
-	depends on m && PROC_FS
+	depends on m && PROC_FS && BROKEN_ON_SMP
 	help
 	  Say Y here if you have one of Hypercope's active PCI ISDN cards
 	  Champ, Ergo and Metro. You will then get a module called hysdn.
--- diff/drivers/isdn/hysdn/hysdn_proclog.c	2003-06-30 10:07:33.000000000 +0100
+++ source/drivers/isdn/hysdn/hysdn_proclog.c	2004-02-23 13:56:42.000000000 +0000
@@ -233,7 +233,7 @@ hysdn_log_read(struct file *file, char *
 		return (0);
 
 	inf->usage_cnt--;	/* new usage count */
-	(struct log_data **) file->private_data = &inf->next;	/* next structure */
+	file->private_data = &inf->next;	/* next structure */
 	if ((len = strlen(inf->log_start)) <= count) {
 		if (copy_to_user(buf, inf->log_start, len))
 			return -EFAULT;
@@ -276,9 +276,9 @@ hysdn_log_open(struct inode *ino, struct
 		cli();
 		pd->if_used++;
 		if (pd->log_head)
-			(struct log_data **) filep->private_data = &(pd->log_tail->next);
+			filep->private_data = &pd->log_tail->next;
 		else
-			(struct log_data **) filep->private_data = &(pd->log_head);
+			filep->private_data = &pd->log_head;
 		restore_flags(flags);
 	} else {		/* simultaneous read/write access forbidden ! */
 		unlock_kernel();
--- diff/drivers/isdn/i4l/Kconfig	2003-09-17 12:28:06.000000000 +0100
+++ source/drivers/isdn/i4l/Kconfig	2004-02-23 13:56:43.000000000 +0000
@@ -2,25 +2,6 @@
 # Old ISDN4Linux config
 #
 
-config ISDN_NET_SIMPLE
-	bool '  Support raw-IP and other simple protocols'
-	depends on INET
-	help
-	  This options enables 'raw IP over ISDN', 'ethernet over ISDN',
-	  'raw IP with UI header' and 'IP + type field' encapsulations.
-	  
-	  If you never heard of any of those, you probably want to say N.
-
-config ISDN_NET_CISCO
-	bool '  Support CISCO router protocols'
-	depends on INET
-	help
-	  This options enables 'CISCO HDLC' encapsulation with
-	  optional support for CISCO keep-alive frames.
-	  
-	  Unless you want to connect to a Cisco Router in HDLC mode,
-	  you probably want to say N.
-
 config ISDN_PPP
 	bool "Support synchronous PPP"
 	depends on INET
@@ -85,7 +66,7 @@ config ISDN_TTY_FAX
 
 config ISDN_X25
 	bool "X.25 PLP on top of ISDN"
-	depends on X25 && BROKEN
+	depends on X25
 	help
 	  This feature provides the X.25 protocol over ISDN connections.
 	  See <file:Documentation/isdn/README.x25> for more information
@@ -97,6 +78,7 @@ menu "ISDN feature submodules"
 
 config ISDN_DRV_LOOP
 	tristate "isdnloop support"
+	depends on BROKEN_ON_SMP
 	help
 	  This driver provides a virtual ISDN card. Its primary purpose is
 	  testing of linklevel features or configuration without getting
@@ -106,7 +88,7 @@ config ISDN_DRV_LOOP
 
 config ISDN_DIVERSION
 	tristate "Support isdn diversion services"
-	depends on BROKEN
+	depends on BROKEN && BROKEN_ON_SMP
 	help
 	  This option allows you to use some supplementary diversion
 	  services in conjunction with the HiSax driver on an EURO/DSS1
@@ -124,3 +106,27 @@ config ISDN_DIVERSION
 	  Please read the file <file:Documentation/isdn/README.diversion>.
 
 endmenu
+
+comment "ISDN4Linux hardware drivers"
+	depends on NET && ISDN && ISDN_I4L
+
+source "drivers/isdn/hisax/Kconfig"
+
+
+menu "Active cards"
+	depends on NET && ISDN && ISDN_I4L!=n
+
+source "drivers/isdn/icn/Kconfig"
+
+source "drivers/isdn/pcbit/Kconfig"
+
+source "drivers/isdn/sc/Kconfig"
+
+source "drivers/isdn/act2000/Kconfig"
+
+source "drivers/isdn/tpam/Kconfig"
+
+source "drivers/isdn/hysdn/Kconfig"
+
+endmenu
+
--- diff/drivers/isdn/i4l/Makefile	2003-06-30 10:07:33.000000000 +0100
+++ source/drivers/isdn/i4l/Makefile	2004-02-23 13:56:43.000000000 +0000
@@ -2,18 +2,17 @@
 
 # Each configuration option enables a list of files.
 
-obj-$(CONFIG_ISDN)		+= isdn.o
+obj-$(CONFIG_ISDN_I4L)		+= isdn.o
 obj-$(CONFIG_ISDN_PPP_BSDCOMP)	+= isdn_bsdcomp.o
 
 # Multipart objects.
 
-isdn-y				:= isdn_net_lib.o isdn_fsm.o isdn_tty.o \
-				   isdn_v110.o isdn_common.o
-isdn-$(CONFIG_ISDN_NET_SIMPLE)	+= isdn_net.o
-isdn-$(CONFIG_ISDN_NET_CISCO)	+= isdn_ciscohdlck.o
-isdn-$(CONFIG_ISDN_PPP)		+= isdn_ppp.o isdn_ppp_ccp.o
-isdn-$(CONFIG_ISDN_PPP_VJ)	+= isdn_ppp_vj.o
-isdn-$(CONFIG_ISDN_MPP)		+= isdn_ppp_mp.o
+isdn-y				:= isdn_net.o isdn_tty.o isdn_v110.o isdn_common.o
+
+# Optional parts of multipart objects.
+
+isdn-$(CONFIG_ISDN_PPP)		+= isdn_ppp.o
 isdn-$(CONFIG_ISDN_X25)		+= isdn_concap.o isdn_x25iface.o
-isdn-$(CONFIG_ISDN_AUDIO)	+= isdn_audio.o
+isdn-$(CONFIG_ISDN_AUDIO)		+= isdn_audio.o
 isdn-$(CONFIG_ISDN_TTY_FAX)	+= isdn_ttyfax.o
+
--- diff/drivers/isdn/i4l/isdn_audio.c	2003-09-17 12:28:06.000000000 +0100
+++ source/drivers/isdn/i4l/isdn_audio.c	2004-02-23 13:56:42.000000000 +0000
@@ -1,20 +1,21 @@
-/* Linux ISDN subsystem, audio conversion and compression
+/* $Id: isdn_audio.c,v 1.1.2.2 2004/01/12 22:37:18 keil Exp $
+ *
+ * Linux ISDN subsystem, audio conversion and compression (linklevel).
  *
  * Copyright 1994-1999 by Fritz Elfert (fritz@isdn4linux.de)
- *           1996      by Christian Mock (cm@tahina.priv.at)
- *           1998      by Armin Schindler (mac@gismo.telekom.de)
+ * DTMF code (c) 1996 by Christian Mock (cm@kukuruz.ping.at)
+ * Silence detection (c) 1998 by Armin Schindler (mac@gismo.telekom.de)
  *
  * This software may be used and distributed according to the terms
  * of the GNU General Public License, incorporated herein by reference.
  *
- * DTMF code         by Christian Mock
- * Silence detection by Armin Schindler
  */
 
 #include <linux/isdn.h>
 #include "isdn_audio.h"
 #include "isdn_common.h"
-#include "isdn_tty.h"
+
+char *isdn_audio_revision = "$Revision: 1.1.2.2 $";
 
 /*
  * Misc. lookup-tables.
@@ -168,39 +169,19 @@ static char isdn_audio_ulaw_to_alaw[] =
 	0x8a, 0x8a, 0x6a, 0x6a, 0xea, 0xea, 0x2a, 0x2a
 };
 
-#define NCOEFF           16     /* number of frequencies to be analyzed       */
-#define DTMF_TRESH    25000     /* above this is dtmf                         */
+#define NCOEFF            8     /* number of frequencies to be analyzed       */
+#define DTMF_TRESH     4000     /* above this is dtmf                         */
 #define SILENCE_TRESH   200     /* below this is silence                      */
-#define H2_TRESH      20000     /* 2nd harmonic                               */
 #define AMP_BITS          9     /* bits per sample, reduced to avoid overflow */
 #define LOGRP             0
 #define HIGRP             1
 
-typedef struct {
-	int grp;                /* low/high group     */
-	int k;                  /* k                  */
-	int k2;                 /* k fuer 2. harmonic */
-} dtmf_t;
-
 /* For DTMF recognition:
  * 2 * cos(2 * PI * k / N) precalculated for all k
  */
 static int cos2pik[NCOEFF] =
 {
-	55812, 29528, 53603, 24032, 51193, 14443, 48590, 6517,
-	38113, -21204, 33057, -32186, 25889, -45081, 18332, -55279
-};
-
-static dtmf_t dtmf_tones[8] =
-{
-	{LOGRP, 0, 1},          /*  697 Hz */
-	{LOGRP, 2, 3},          /*  770 Hz */
-	{LOGRP, 4, 5},          /*  852 Hz */
-	{LOGRP, 6, 7},          /*  941 Hz */
-	{HIGRP, 8, 9},          /* 1209 Hz */
-	{HIGRP, 10, 11},        /* 1336 Hz */
-	{HIGRP, 12, 13},        /* 1477 Hz */
-	{HIGRP, 14, 15}         /* 1633 Hz */
+	55813, 53604, 51193, 48591, 38114, 33057, 25889, 18332
 };
 
 static char dtmf_matrix[4][4] =
@@ -226,10 +207,8 @@ isdn_audio_tlookup(const u_char *table, 
 	:	"0"((long) table), "1"(n), "2"((long) buff), "3"((long) buff)
 	:	"memory", "ax");
 #else
-	while (n--) {
-		*buff = table[*buff];
-		buff++;
-	}
+	while (n--)
+		*buff = table[*(unsigned char *)buff], buff++;
 #endif
 }
 
@@ -500,13 +479,25 @@ isdn_audio_goertzel(int *sample, modem_i
 			sk2 = sk1;
 			sk1 = sk;
 		}
+		/* Avoid overflows */
+		sk >>= 1;
+		sk2 >>= 1;
+		/* compute |X(k)|**2 */
+		/* report overflows. This should not happen. */
+		/* Comment this out if desired */
+		if (sk < -32768 || sk > 32767)
+			printk(KERN_DEBUG
+			       "isdn_audio: dtmf goertzel overflow, sk=%d\n", sk);
+		if (sk2 < -32768 || sk2 > 32767)
+			printk(KERN_DEBUG
+			       "isdn_audio: dtmf goertzel overflow, sk2=%d\n", sk2);
 		result[k] =
 		    ((sk * sk) >> AMP_BITS) -
 		    ((((cos2pik[k] * sk) >> 15) * sk2) >> AMP_BITS) +
 		    ((sk2 * sk2) >> AMP_BITS);
 	}
 	skb_queue_tail(&info->dtmf_queue, skb);
-	mod_timer(&info->read_timer, jiffies + 4);
+	isdn_timer_ctrl(ISDN_TIMER_MODEMREAD, 1);
 }
 
 void
@@ -517,31 +508,63 @@ isdn_audio_eval_dtmf(modem_info * info)
 	dtmf_state *s;
 	int silence;
 	int i;
+	int di;
+	int ch;
 	int grp[2];
 	char what;
 	char *p;
+	int thresh;
 
 	while ((skb = skb_dequeue(&info->dtmf_queue))) {
 		result = (int *) skb->data;
 		s = info->dtmf_state;
-		grp[LOGRP] = grp[HIGRP] = -2;
+		grp[LOGRP] = grp[HIGRP] = -1;
 		silence = 0;
-		for (i = 0; i < 8; i++) {
-			if ((result[dtmf_tones[i].k] > DTMF_TRESH) &&
-			    (result[dtmf_tones[i].k2] < H2_TRESH))
-				grp[dtmf_tones[i].grp] = (grp[dtmf_tones[i].grp] == -2) ? i : -1;
-			else if ((result[dtmf_tones[i].k] < SILENCE_TRESH) &&
-			      (result[dtmf_tones[i].k2] < SILENCE_TRESH))
+		thresh = 0;
+		for (i = 0; i < NCOEFF; i++) {
+			if (result[i] > DTMF_TRESH) {
+				if (result[i] > thresh)
+					thresh = result[i];
+			}
+			else if (result[i] < SILENCE_TRESH)
 				silence++;
 		}
-		if (silence == 8)
+		if (silence == NCOEFF)
 			what = ' ';
 		else {
-			if ((grp[LOGRP] >= 0) && (grp[HIGRP] >= 0)) {
-				what = dtmf_matrix[grp[LOGRP]][grp[HIGRP] - 4];
-				if (s->last != ' ' && s->last != '.')
-					s->last = what;	/* min. 1 non-DTMF between DTMF */
-			} else
+			if (thresh > 0)	{
+				thresh = thresh >> 4;  /* touchtones must match within 12 dB */
+				for (i = 0; i < NCOEFF; i++) {
+					if (result[i] < thresh)
+						continue;  /* ignore */
+					/* good level found. This is allowed only one time per group */
+					if (i < NCOEFF / 2) {
+						/* lowgroup*/
+						if (grp[LOGRP] >= 0) {
+							// Bad. Another tone found. */
+							grp[LOGRP] = -1;
+							break;
+						}
+						else
+							grp[LOGRP] = i;
+					}
+					else { /* higroup */
+						if (grp[HIGRP] >= 0) { // Bad. Another tone found. */
+							grp[HIGRP] = -1;
+							break;
+						}
+						else
+							grp[HIGRP] = i - NCOEFF/2;
+					}
+				}
+				if ((grp[LOGRP] >= 0) && (grp[HIGRP] >= 0)) {
+					what = dtmf_matrix[grp[LOGRP]][grp[HIGRP]];
+					if (s->last != ' ' && s->last != '.')
+						s->last = what;	/* min. 1 non-DTMF between DTMF */
+				} else
+					what = '.';
+			}
+			else
 				what = '.';
 		}
 		if ((what != s->last) && (what != ' ') && (what != '.')) {
@@ -550,17 +573,16 @@ isdn_audio_eval_dtmf(modem_info * info)
 			*p++ = 0x10;
 			*p = what;
 			skb_trim(skb, 2);
-			if ((size_t)skb_headroom(skb) < sizeof(isdnaudio_header)) {
-				printk(KERN_WARNING
-				       "isdn_audio: insufficient skb_headroom, dropping\n");
-				kfree_skb(skb);
-				return;
-			}
 			ISDN_AUDIO_SKB_DLECOUNT(skb) = 0;
 			ISDN_AUDIO_SKB_LOCK(skb) = 0;
-			isdn_tty_queue_tail(info, skb, 2);
-			if (((get_isdn_dev())->modempoll) && (info->rcvsched))
-				mod_timer(&info->read_timer, jiffies + 4);
+			di = info->isdn_driver;
+			ch = info->isdn_channel;
+			__skb_queue_tail(&dev->drv[di]->rpqueue[ch], skb);
+			dev->drv[di]->rcvcount[ch] += 2;
+			/* Schedule dequeuing */
+			if ((dev->modempoll) && (info->rcvsched))
+				isdn_timer_ctrl(ISDN_TIMER_MODEMREAD, 1);
+			wake_up_interruptible(&dev->drv[di]->rcv_waitq[ch]);
 		} else
 			kfree_skb(skb);
 		s->last = what;
@@ -648,6 +670,8 @@ void
 isdn_audio_put_dle_code(modem_info * info, u_char code)
 {
 	struct sk_buff *skb;
+	int di;
+	int ch;
 	char *p;
 
 	skb = dev_alloc_skb(2);
@@ -660,18 +684,16 @@ isdn_audio_put_dle_code(modem_info * inf
 	p = (char *) skb_put(skb, 2);
 	p[0] = 0x10;
 	p[1] = code;
-	if ((size_t)skb_headroom(skb) < sizeof(isdnaudio_header)) {
-		printk(KERN_WARNING
-		       "isdn_audio: insufficient skb_headroom, dropping\n");
-		kfree_skb(skb);
-		return;
-	}
 	ISDN_AUDIO_SKB_DLECOUNT(skb) = 0;
 	ISDN_AUDIO_SKB_LOCK(skb) = 0;
-	isdn_tty_queue_tail(info, skb, 2);
+	di = info->isdn_driver;
+	ch = info->isdn_channel;
+	__skb_queue_tail(&dev->drv[di]->rpqueue[ch], skb);
+	dev->drv[di]->rcvcount[ch] += 2;
 	/* Schedule dequeuing */
-	if (((get_isdn_dev())->modempoll) && (info->rcvsched))
-		mod_timer(&info->read_timer, jiffies + 4);
+	if ((dev->modempoll) && (info->rcvsched))
+		isdn_timer_ctrl(ISDN_TIMER_MODEMREAD, 1);
+	wake_up_interruptible(&dev->drv[di]->rcv_waitq[ch]);
 }
 
 void
@@ -682,7 +704,7 @@ isdn_audio_eval_silence(modem_info * inf
 
 	what = ' ';
 
-	if (s->idx > (u_int)(info->emu.vpar[2] * 800)) { 
+	if (s->idx > (info->emu.vpar[2] * 800)) { 
 		s->idx = 0;
 		if (!s->state) {	/* silence from beginning of rec */ 
 			what = 's';
@@ -690,9 +712,9 @@ isdn_audio_eval_silence(modem_info * inf
 			what = 'q';
 		}
 	}
-	if ((what == 's') || (what == 'q')) {
-		printk(KERN_DEBUG "ttyI%d: %s\n", info->line,
-			(what=='s') ? "silence":"quiet");
-		isdn_audio_put_dle_code(info, what);
-	} 
+		if ((what == 's') || (what == 'q')) {
+			printk(KERN_DEBUG "ttyI%d: %s\n", info->line,
+				(what=='s') ? "silence":"quiet");
+			isdn_audio_put_dle_code(info, what);
+		} 
 }
--- diff/drivers/isdn/i4l/isdn_audio.h	2002-11-11 11:09:36.000000000 +0000
+++ source/drivers/isdn/i4l/isdn_audio.h	2004-02-23 13:56:42.000000000 +0000
@@ -1,4 +1,6 @@
-/* Linux ISDN subsystem, audio conversion and compression
+/* $Id: isdn_audio.h,v 1.1.2.2 2004/01/12 22:37:18 keil Exp $
+ *
+ * Linux ISDN subsystem, audio conversion and compression (linklevel).
  *
  * Copyright 1994-1999 by Fritz Elfert (fritz@isdn4linux.de)
  *
@@ -18,6 +20,7 @@ typedef struct adpcm_state {
 
 typedef struct dtmf_state {
 	char last;
+	char llast;
 	int idx;
 	int buf[DTMF_NPOINTS];
 } dtmf_state;
--- diff/drivers/isdn/i4l/isdn_common.c	2003-10-09 09:47:34.000000000 +0100
+++ source/drivers/isdn/i4l/isdn_common.c	2004-02-23 13:56:42.000000000 +0000
@@ -1,4 +1,6 @@
-/* Linux ISDN subsystem, common used functions
+/* $Id: isdn_common.c,v 1.1.2.3 2004/02/10 01:07:13 keil Exp $
+ *
+ * Linux ISDN subsystem, common used functions (linklevel).
  *
  * Copyright 1994-1999  by Fritz Elfert (fritz@isdn4linux.de)
  * Copyright 1995,96    Thinking Objects Software GmbH Wuerzburg
@@ -6,6 +8,7 @@
  *
  * This software may be used and distributed according to the terms
  * of the GNU General Public License, incorporated herein by reference.
+ *
  */
 
 #include <linux/config.h>
@@ -16,811 +19,463 @@
 #include <linux/vmalloc.h>
 #include <linux/isdn.h>
 #include <linux/smp_lock.h>
-#include <linux/ctype.h>
 #include "isdn_common.h"
-#include "isdn_net_lib.h"
-#include "isdn_net.h"
 #include "isdn_tty.h"
+#include "isdn_net.h"
 #include "isdn_ppp.h"
 #ifdef CONFIG_ISDN_AUDIO
 #include "isdn_audio.h"
 #endif
+#ifdef CONFIG_ISDN_DIVERSION_MODULE
+#define CONFIG_ISDN_DIVERSION
+#endif
+#ifdef CONFIG_ISDN_DIVERSION
 #include <linux/isdn_divertif.h>
-#include <linux/devfs_fs_kernel.h>
+#endif /* CONFIG_ISDN_DIVERSION */
+#include "isdn_v110.h"
+
+/* Debugflags */
+#undef ISDN_DEBUG_STATCALLB
 
 MODULE_DESCRIPTION("ISDN4Linux: link layer");
 MODULE_AUTHOR("Fritz Elfert");
 MODULE_LICENSE("GPL");
 
-static isdn_dev_t *isdndev;
+isdn_dev *dev;
 
-isdn_dev_t *
-get_isdn_dev(void) {
-	return(isdndev);
-}
-
-/* Description of hardware-level-driver */
-typedef struct isdn_driver {
-	int                 di;
-	char                id[20];
-	atomic_t            refcnt;
-	unsigned long       flags;            /* Misc driver Flags           */
-	unsigned long       features;
-	int                 channels;         /* Number of channels          */
-	wait_queue_head_t   st_waitq;         /* Wait-Queue for status-reads */
-	int                 maxbufsize;       /* Maximum Buffersize supported*/
-	int                 stavail;          /* Chars avail on Status-device*/
-	isdn_if            *interface;        /* Interface to driver         */
-	char                msn2eaz[10][ISDN_MSNLEN];  /*  MSN->EAZ          */
-	spinlock_t          lock;
-	struct isdn_slot   *slots; 
-	struct fsm_inst     fi;
-} isdn_driver_t;
-
-static spinlock_t	drivers_lock = SPIN_LOCK_UNLOCKED;
-static isdn_driver_t	*drivers[ISDN_MAX_DRIVERS];
-
-static void isdn_lock_driver(struct isdn_driver *drv);
-static void isdn_unlock_driver(struct isdn_driver *drv);
-
-/* ====================================================================== */
-
-static void drv_destroy(struct isdn_driver *drv);
-
-static inline struct isdn_driver *
-get_drv(struct isdn_driver *drv)
-{
-	printk("get_drv %d: %d -> %d\n", drv->di, atomic_read(&drv->refcnt), 
-	       atomic_read(&drv->refcnt) + 1); 
-	atomic_inc(&drv->refcnt);
-	return drv;
-}
+static char *isdn_revision = "$Revision: 1.1.2.3 $";
 
-static inline void
-put_drv(struct isdn_driver *drv)
-{
-	printk("put_drv %d: %d -> %d\n", drv->di, atomic_read(&drv->refcnt),
-	       atomic_read(&drv->refcnt) - 1); 
-	if (atomic_dec_and_test(&drv->refcnt)) {
-		drv_destroy(drv);
-	}
-}
+extern char *isdn_net_revision;
+extern char *isdn_tty_revision;
+#ifdef CONFIG_ISDN_PPP
+extern char *isdn_ppp_revision;
+#else
+static char *isdn_ppp_revision = ": none $";
+#endif
+#ifdef CONFIG_ISDN_AUDIO
+extern char *isdn_audio_revision;
+#else
+static char *isdn_audio_revision = ": none $";
+#endif
+extern char *isdn_v110_revision;
 
-/* ====================================================================== */
-
-static struct fsm slot_fsm;
-static void slot_debug(struct fsm_inst *fi, char *fmt, ...);
-
-static char *slot_st_str[] = {
-	"ST_SLOT_NULL",
-	"ST_SLOT_BOUND",
-	"ST_SLOT_IN",
-	"ST_SLOT_WAIT_DCONN",
-	"ST_SLOT_DCONN",
-	"ST_SLOT_WAIT_BCONN",
-	"ST_SLOT_ACTIVE",
-	"ST_SLOT_WAIT_BHUP",
-	"ST_SLOT_WAIT_DHUP",
-};
+#ifdef CONFIG_ISDN_DIVERSION
+static isdn_divert_if *divert_if; /* = NULL */
+#endif /* CONFIG_ISDN_DIVERSION */
 
-static char *ev_str[] = {
-	"EV_DRV_REGISTER",
-	"EV_STAT_RUN",
-	"EV_STAT_STOP",
-	"EV_STAT_UNLOAD",
-	"EV_STAT_STAVAIL",
-	"EV_STAT_ADDCH",
-	"EV_STAT_ICALL",
-	"EV_STAT_DCONN",
-	"EV_STAT_BCONN",
-	"EV_STAT_BHUP",
-	"EV_STAT_DHUP",
-	"EV_STAT_BSENT",
-	"EV_STAT_CINF",
-	"EV_STAT_CAUSE",
-	"EV_STAT_DISPLAY",
-	"EV_STAT_FAXIND",
-	"EV_STAT_AUDIO",
-	"EV_CMD_CLREAZ",
-	"EV_CMD_SETEAZ",
-	"EV_CMD_SETL2",
-	"EV_CMD_SETL3",
-	"EV_CMD_DIAL",
-	"EV_CMD_ACCEPTD",
-	"EV_CMD_ACCEPTB",
-	"EV_CMD_HANGUP",
-	"EV_DATA_REQ",
-	"EV_DATA_IND",
-	"EV_SLOT_BIND",
-	"EV_SLOT_UNBIND",
-};
 
-static int __slot_command(struct isdn_slot *slot, isdn_ctrl *cmd);
+static int isdn_writebuf_stub(int, int, const u_char *, int, int);
+static void set_global_features(void);
+static int isdn_wildmat(char *s, char *p);
 
-static void isdn_v110_setl2(struct isdn_slot *slot, isdn_ctrl *cmd);
-static void __isdn_v110_open(struct isdn_slot *slot);
-static void __isdn_v110_close(struct isdn_slot *slot);
-static void __isdn_v110_bsent(struct isdn_slot *slot, int pr, isdn_ctrl *cmd);
-static int  isdn_v110_data_ind(struct isdn_slot *slot, struct sk_buff *skb);
-static int  isdn_v110_data_req(struct isdn_slot *slot, struct sk_buff *skb);
 
-static inline int
-do_event_cb(struct isdn_slot *slot, int pr, void *arg)
+static inline void
+isdn_lock_driver(isdn_driver_t *drv)
 {
-	if (slot->event_cb)
-		return slot->event_cb(slot, pr, arg);
-
-	return -ENXIO;
+	try_module_get(drv->interface->owner);
+	drv->locks++;
 }
 
-static int
-slot_bind(struct fsm_inst *fi, int pr, void *arg)
+void
+isdn_lock_drivers(void)
 {
-	struct isdn_slot *slot = fi->userdata;
-	
-	isdn_lock_driver(slot->drv);
-	fsm_change_state(fi, ST_SLOT_BOUND);
+	int i;
 
-	return 0;
+	for (i = 0; i < ISDN_MAX_DRIVERS; i++) {
+		if (!dev->drv[i])
+			continue;
+		isdn_lock_driver(dev->drv[i]);
+	}
 }
 
-/* just pass through command */
-static int
-slot_command(struct fsm_inst *fi, int pr, void *arg)
+static inline void
+isdn_unlock_driver(isdn_driver_t *drv)
 {
-	struct isdn_slot *slot = fi->userdata;
-	isdn_ctrl *c = arg;
-
-	return __slot_command(slot, c);
+	if (drv->locks > 0) {
+		drv->locks--;
+		module_put(drv->interface->owner);
+	}
 }
 
-/* just pass through status */
-static int
-slot_stat(struct fsm_inst *fi, int pr, void *arg)
+void
+isdn_unlock_drivers(void)
 {
-	struct isdn_slot *slot = fi->userdata;
+	int i;
 
-	do_event_cb(slot, pr, arg);
-	return 0;
+	for (i = 0; i < ISDN_MAX_DRIVERS; i++) {
+		if (!dev->drv[i])
+			continue;
+		isdn_unlock_driver(dev->drv[i]);
+	}
 }
 
-/* just pass through command */
-static int
-slot_setl2(struct fsm_inst *fi, int pr, void *arg)
+#if defined(ISDN_DEBUG_NET_DUMP) || defined(ISDN_DEBUG_MODEM_DUMP)
+void
+isdn_dumppkt(char *s, u_char * p, int len, int dumplen)
 {
-	struct isdn_slot *slot = fi->userdata;
-	isdn_ctrl *c = arg;
-
-	isdn_v110_setl2(slot, c);
+	int dumpc;
 
-	return __slot_command(slot, c);
+	printk(KERN_DEBUG "%s(%d) ", s, len);
+	for (dumpc = 0; (dumpc < dumplen) && (len); len--, dumpc++)
+		printk(" %02x", *p++);
+	printk("\n");
 }
+#endif
 
+/*
+ * I picked the pattern-matching-functions from an old GNU-tar version (1.10)
+ * It was originally written and put to PD by rs@mirror.TMC.COM (Rich Salz)
+ */
 static int
-slot_dial(struct fsm_inst *fi, int pr, void *arg)
+isdn_star(char *s, char *p)
 {
-	struct isdn_slot *slot = fi->userdata;
-	isdn_ctrl *ctrl = arg;
-	int retval;
-
-	retval = __slot_command(slot, ctrl);
-	if (retval >= 0)
-		fsm_change_state(fi, ST_SLOT_WAIT_DCONN);
-
-	return retval;
+	while (isdn_wildmat(s, p)) {
+		if (*++s == '\0')
+			return (2);
+	}
+	return (0);
 }
 
-static int
-slot_acceptd(struct fsm_inst *fi, int pr, void *arg)
-{
-	struct isdn_slot *slot = fi->userdata;
-	isdn_ctrl *ctrl = arg;
-	int retval;
-
-	retval = __slot_command(slot, ctrl);
-	if (retval >= 0)
-		fsm_change_state(fi, ST_SLOT_WAIT_DCONN);
-
-	return retval;
-}
+/*
+ * Shell-type Pattern-matching for incoming caller-Ids
+ * This function gets a string in s and checks, if it matches the pattern
+ * given in p.
+ *
+ * Return:
+ *   0 = match.
+ *   1 = no match.
+ *   2 = no match. Would eventually match, if s would be longer.
+ *
+ * Possible Patterns:
+ *
+ * '?'     matches one character
+ * '*'     matches zero or more characters
+ * [xyz]   matches the set of characters in brackets.
+ * [^xyz]  matches any single character not in the set of characters
+ */
 
 static int
-slot_acceptb(struct fsm_inst *fi, int pr, void *arg)
+isdn_wildmat(char *s, char *p)
 {
-	struct isdn_slot *slot = fi->userdata;
-	isdn_ctrl *ctrl = arg;
-	int retval;
-
-	retval = __slot_command(slot, ctrl);
-	if (retval >= 0)
-		fsm_change_state(fi, ST_SLOT_WAIT_BCONN);
+	register int last;
+	register int matched;
+	register int reverse;
+	register int nostar = 1;
 
-	return retval;
+	if (!(*s) && !(*p))
+		return(1);
+	for (; *p; s++, p++)
+		switch (*p) {
+			case '\\':
+				/*
+				 * Literal match with following character,
+				 * fall through.
+				 */
+				p++;
+			default:
+				if (*s != *p)
+					return (*s == '\0')?2:1;
+				continue;
+			case '?':
+				/* Match anything. */
+				if (*s == '\0')
+					return (2);
+				continue;
+			case '*':
+				nostar = 0;	
+				/* Trailing star matches everything. */
+				return (*++p ? isdn_star(s, p) : 0);
+			case '[':
+				/* [^....] means inverse character class. */
+				if ((reverse = (p[1] == '^')))
+					p++;
+				for (last = 0, matched = 0; *++p && (*p != ']'); last = *p)
+					/* This next line requires a good C compiler. */
+					if (*p == '-' ? *s <= *++p && *s >= last : *s == *p)
+						matched = 1;
+				if (matched == reverse)
+					return (1);
+				continue;
+		}
+	return (*s == '\0')?0:nostar;
 }
 
-static int
-slot_actv_hangup(struct fsm_inst *fi, int pr, void *arg)
+int isdn_msncmp( const char * msn1, const char * msn2 )
 {
-	struct isdn_slot *slot = fi->userdata;
-	isdn_ctrl *ctrl = arg;
-	int retval;
+	char TmpMsn1[ ISDN_MSNLEN ];
+	char TmpMsn2[ ISDN_MSNLEN ];
+	char *p;
 
-	retval = __slot_command(slot, ctrl);
-	if (retval >= 0) {
-		fsm_change_state(fi, ST_SLOT_WAIT_BHUP);
-	}
-	return retval;
-}
+	for ( p = TmpMsn1; *msn1 && *msn1 != ':'; )  // Strip off a SPID
+		*p++ = *msn1++;
+	*p = '\0';
 
-static int
-slot_dconn(struct fsm_inst *fi, int pr, void *arg)
-{
-	struct isdn_slot *slot = fi->userdata;
+	for ( p = TmpMsn2; *msn2 && *msn2 != ':'; )  // Strip off a SPID
+		*p++ = *msn2++;
+	*p = '\0';
 
-	fsm_change_state(fi, ST_SLOT_DCONN);
-	do_event_cb(slot, pr, arg);
-	return 0;
+	return isdn_wildmat( TmpMsn1, TmpMsn2 );
 }
 
-static int
-slot_bconn(struct fsm_inst *fi, int pr, void *arg)
+int
+isdn_dc2minor(int di, int ch)
 {
-	struct isdn_slot *slot = fi->userdata;
-
-	fsm_change_state(fi, ST_SLOT_ACTIVE);
-	__isdn_v110_open(slot);
-
-	isdn_info_update();
-
-	do_event_cb(slot, pr, arg);
-	return 0;
+	int i;
+	for (i = 0; i < ISDN_MAX_CHANNELS; i++)
+		if (dev->chanmap[i] == ch && dev->drvmap[i] == di)
+			return i;
+	return -1;
 }
 
-static int
-slot_bhup(struct fsm_inst *fi, int pr, void *arg)
-{
-	struct isdn_slot *slot = fi->userdata;
-
-	__isdn_v110_close(slot);
-	fsm_change_state(fi, ST_SLOT_WAIT_DHUP);
+static int isdn_timer_cnt1 = 0;
+static int isdn_timer_cnt2 = 0;
+static int isdn_timer_cnt3 = 0;
 
-	do_event_cb(slot, pr, arg);
-	return 0;
-}
-
-static int
-slot_dhup(struct fsm_inst *fi, int pr, void *arg)
+static void
+isdn_timer_funct(ulong dummy)
 {
-	struct isdn_slot *slot = fi->userdata;
-
-	fsm_change_state(fi, ST_SLOT_BOUND);
-
-	do_event_cb(slot, pr, arg);
-	return 0;
+	int tf = dev->tflags;
+	if (tf & ISDN_TIMER_FAST) {
+		if (tf & ISDN_TIMER_MODEMREAD)
+			isdn_tty_readmodem();
+		if (tf & ISDN_TIMER_MODEMPLUS)
+			isdn_tty_modem_escape();
+		if (tf & ISDN_TIMER_MODEMXMIT)
+			isdn_tty_modem_xmit();
+	}
+	if (tf & ISDN_TIMER_SLOW) {
+		if (++isdn_timer_cnt1 >= ISDN_TIMER_02SEC) {
+			isdn_timer_cnt1 = 0;
+			if (tf & ISDN_TIMER_NETDIAL)
+				isdn_net_dial();
+		}
+		if (++isdn_timer_cnt2 >= ISDN_TIMER_1SEC) {
+			isdn_timer_cnt2 = 0;
+			if (tf & ISDN_TIMER_NETHANGUP)
+				isdn_net_autohup();
+			if (++isdn_timer_cnt3 >= ISDN_TIMER_RINGING) {
+				isdn_timer_cnt3 = 0;
+				if (tf & ISDN_TIMER_MODEMRING)
+					isdn_tty_modem_ring();
+			}
+			if (tf & ISDN_TIMER_CARRIER)
+				isdn_tty_carrier_timeout();
+		}
+	}
+	if (tf) 
+		mod_timer(&dev->timer, jiffies+ISDN_TIMER_RES);
 }
 
-static int
-slot_data_req(struct fsm_inst *fi, int pr, void *arg)
+void
+isdn_timer_ctrl(int tf, int onoff)
 {
-	struct isdn_slot *slot = fi->userdata;
-	struct sk_buff *skb = arg;
+	unsigned long flags;
+	int old_tflags;
 
-	return isdn_v110_data_req(slot, skb);
+	spin_lock_irqsave(&dev->timerlock, flags);
+	if ((tf & ISDN_TIMER_SLOW) && (!(dev->tflags & ISDN_TIMER_SLOW))) {
+		/* If the slow-timer wasn't activated until now */
+		isdn_timer_cnt1 = 0;
+		isdn_timer_cnt2 = 0;
+	}
+	old_tflags = dev->tflags;
+	if (onoff)
+		dev->tflags |= tf;
+	else
+		dev->tflags &= ~tf;
+	if (dev->tflags && !old_tflags)
+		mod_timer(&dev->timer, jiffies+ISDN_TIMER_RES);
+	spin_unlock_irqrestore(&dev->timerlock, flags);
 }
 
-static int
-slot_data_ind(struct fsm_inst *fi, int pr, void *arg)
+/*
+ * Receive a packet from B-Channel. (Called from low-level-module)
+ */
+static void
+isdn_receive_skb_callback(int di, int channel, struct sk_buff *skb)
 {
-	struct isdn_slot *slot = fi->userdata;
-	struct sk_buff *skb = arg;
+	int i;
 
+	if ((i = isdn_dc2minor(di, channel)) == -1) {
+		dev_kfree_skb(skb);
+		return;
+	}
 	/* Update statistics */
-	slot->ibytes += skb->len;
-
-	return isdn_v110_data_ind(slot, skb);
-}
-
-static int
-slot_bsent(struct fsm_inst *fi, int pr, void *arg)
-{
-	struct isdn_slot *slot = fi->userdata;
-	isdn_ctrl *ctrl = arg;
-
-	__isdn_v110_bsent(slot, pr, ctrl);
-	return 0;
-}
-
-static int
-slot_icall(struct fsm_inst *fi, int pr, void *arg)
-{
-	struct isdn_slot *slot = fi->userdata;
-	isdn_ctrl *ctrl = arg;
-	int retval;
-
-	isdn_lock_driver(slot->drv);
-	fsm_change_state(fi, ST_SLOT_IN);
-	slot_debug(fi, "ICALL: %s\n", ctrl->parm.num);
-	if (isdndev->global_flags & ISDN_GLOBAL_STOPPED)
-		return 0;
+	dev->ibytes[i] += skb->len;
 	
-	strcpy(slot->num, ctrl->parm.setup.phone);
-	/* Try to find a network-interface which will accept incoming call */
-	retval = isdn_net_find_icall(slot, &ctrl->parm.setup);
-
-	/* already taken by net now? */
-	if (fi->state != ST_SLOT_IN)
-		goto out;
+	/* First, try to deliver data to network-device */
+	if (isdn_net_rcv_skb(i, skb))
+		return;
 
-	retval = isdn_tty_find_icall(slot, &ctrl->parm.setup);
- out:
-	return 0;
+	/* V.110 handling
+	 * makes sense for async streams only, so it is
+	 * called after possible net-device delivery.
+	 */
+	if (dev->v110[i]) {
+		atomic_inc(&dev->v110use[i]);
+		skb = isdn_v110_decode(dev->v110[i], skb);
+		atomic_dec(&dev->v110use[i]);
+		if (!skb)
+			return;
+	}
+
+	/* No network-device found, deliver to tty or raw-channel */
+	if (skb->len) {
+		if (isdn_tty_rcv_skb(i, di, channel, skb))
+			return;
+		wake_up_interruptible(&dev->drv[di]->rcv_waitq[channel]);
+	} else
+		dev_kfree_skb(skb);
 }
 
-/* should become broadcast later */
-static int
-slot_in_dhup(struct fsm_inst *fi, int pr, void *arg)
+/*
+ * Intercept command from Linklevel to Lowlevel.
+ * If layer 2 protocol is V.110 and this is not supported by current
+ * lowlevel-driver, use driver's transparent mode and handle V.110 in
+ * linklevel instead.
+ */
+int
+isdn_command(isdn_ctrl *cmd)
 {
-	struct isdn_slot *slot = fi->userdata;
-
-	isdn_unlock_driver(slot->drv);
-	fsm_change_state(fi, ST_SLOT_NULL);
-	do_event_cb(slot, pr, arg);
-	return 0;
+	if (cmd->driver == -1) {
+		printk(KERN_WARNING "isdn_command command(%x) driver -1\n", cmd->command);
+		return(1);
+	}
+	if (cmd->command == ISDN_CMD_SETL2) {
+		int idx = isdn_dc2minor(cmd->driver, cmd->arg & 255);
+		unsigned long l2prot = (cmd->arg >> 8) & 255;
+		unsigned long features = (dev->drv[cmd->driver]->interface->features
+						>> ISDN_FEATURE_L2_SHIFT) &
+						ISDN_FEATURE_L2_MASK;
+		unsigned long l2_feature = (1 << l2prot);
+
+		switch (l2prot) {
+			case ISDN_PROTO_L2_V11096:
+			case ISDN_PROTO_L2_V11019:
+			case ISDN_PROTO_L2_V11038:
+			/* If V.110 requested, but not supported by
+			 * HL-driver, set emulator-flag and change
+			 * Layer-2 to transparent
+			 */
+				if (!(features & l2_feature)) {
+					dev->v110emu[idx] = l2prot;
+					cmd->arg = (cmd->arg & 255) |
+						(ISDN_PROTO_L2_TRANS << 8);
+				} else
+					dev->v110emu[idx] = 0;
+		}
+	}
+	return dev->drv[cmd->driver]->interface->command(cmd);
 }
 
-static int
-slot_unbind(struct fsm_inst *fi, int pr, void *arg)
+void
+isdn_all_eaz(int di, int ch)
 {
-	struct isdn_slot *slot = fi->userdata;
 	isdn_ctrl cmd;
 
-	isdn_unlock_driver(slot->drv);
-	fsm_change_state(fi, ST_SLOT_NULL);
-	strcpy(slot->num, "???");
+	if (di < 0)
+		return;
+	cmd.driver = di;
+	cmd.arg = ch;
+	cmd.command = ISDN_CMD_SETEAZ;
 	cmd.parm.num[0] = '\0';
-	isdn_slot_command(slot, ISDN_CMD_SETEAZ, &cmd);
-	slot->ibytes = 0;
-	slot->obytes = 0;
-	slot->usage = ISDN_USAGE_NONE;
-	put_drv(slot->drv);
-	isdn_info_update();
-	return 0;
+	isdn_command(&cmd);
 }
 
-static struct fsm_node slot_fn_tbl[] = {
-	{ ST_SLOT_NULL,          EV_SLOT_BIND,   slot_bind        },
-	{ ST_SLOT_NULL,          EV_STAT_ICALL,  slot_icall       },
-
-	{ ST_SLOT_BOUND,         EV_CMD_CLREAZ,  slot_command     },
-	{ ST_SLOT_BOUND,         EV_CMD_SETEAZ,  slot_command     },
-	{ ST_SLOT_BOUND,         EV_CMD_SETL2,   slot_setl2       },
-	{ ST_SLOT_BOUND,         EV_CMD_SETL3,   slot_command     },
-	{ ST_SLOT_BOUND,         EV_CMD_DIAL,    slot_dial        },
-	{ ST_SLOT_BOUND,         EV_SLOT_UNBIND, slot_unbind      },
-
-	{ ST_SLOT_IN,            EV_CMD_SETL2,   slot_setl2       },
-	{ ST_SLOT_IN,            EV_CMD_SETL3,   slot_command     },
-	{ ST_SLOT_IN,            EV_CMD_ACCEPTD, slot_acceptd     },
-	{ ST_SLOT_IN,            EV_STAT_DHUP,   slot_in_dhup     },
-
-	{ ST_SLOT_WAIT_DCONN,    EV_STAT_DCONN,  slot_dconn       },
-	{ ST_SLOT_WAIT_DCONN,    EV_STAT_DHUP,   slot_dhup        },
-
-	{ ST_SLOT_DCONN,         EV_CMD_ACCEPTB, slot_acceptb     },
-	{ ST_SLOT_DCONN,         EV_STAT_BCONN,  slot_bconn       },
-
-	{ ST_SLOT_WAIT_BCONN,    EV_STAT_BCONN,  slot_bconn       },
-
-	{ ST_SLOT_ACTIVE,        EV_DATA_REQ,    slot_data_req    },
-	{ ST_SLOT_ACTIVE,        EV_DATA_IND,    slot_data_ind    },
-	{ ST_SLOT_ACTIVE,        EV_CMD_HANGUP,  slot_actv_hangup },
-	{ ST_SLOT_ACTIVE,        EV_STAT_BSENT,  slot_bsent       },
-	{ ST_SLOT_ACTIVE,        EV_STAT_BHUP,   slot_bhup        },
-	{ ST_SLOT_ACTIVE,        EV_STAT_FAXIND, slot_stat        },
-	{ ST_SLOT_ACTIVE,        EV_STAT_AUDIO,  slot_stat        },
-
-	{ ST_SLOT_WAIT_BHUP,     EV_STAT_BHUP,   slot_bhup        },
-
-	{ ST_SLOT_WAIT_DHUP,     EV_STAT_DHUP,   slot_dhup        },
-};
-
-static struct fsm slot_fsm = {
-	.st_cnt = ARRAY_SIZE(slot_st_str),
-	.st_str = slot_st_str,
-	.ev_cnt = ARRAY_SIZE(ev_str),
-	.ev_str = ev_str,
-	.fn_cnt = ARRAY_SIZE(slot_fn_tbl),
-	.fn_tbl = slot_fn_tbl,
-};
-
-static void slot_debug(struct fsm_inst *fi, char *fmt, ...)
-{
-	va_list args;
-	struct isdn_slot *slot = fi->userdata;
-	char buf[128];
-	char *p = buf;
+/*
+ * Begin of a CAPI like LL<->HL interface, currently used only for 
+ * supplementary service (CAPI 2.0 part III)
+ */
+#include <linux/isdn//capicmd.h>
 
-	va_start(args, fmt);
-	p += sprintf(p, "slot (%d:%d): ", slot->di, slot->ch);
-	p += vsprintf(p, fmt, args);
-	va_end(args);
-	printk(KERN_DEBUG "%s\n", buf);
+int
+isdn_capi_rec_hl_msg(capi_msg *cm) {
+	
+	int di;
+	int ch;
+	
+	di = (cm->adr.Controller & 0x7f) -1;
+	ch = isdn_dc2minor(di, (cm->adr.Controller>>8)& 0x7f);
+	switch(cm->Command) {
+		case CAPI_FACILITY:
+			/* in the moment only handled in tty */
+			return(isdn_tty_capi_facility(cm));
+		default:
+			return(-1);
+	}
 }
 
-/* ====================================================================== */
-
-static spinlock_t stat_lock = SPIN_LOCK_UNLOCKED;
-
-static struct fsm drv_fsm;
+static int
+isdn_status_callback(isdn_ctrl * c)
+{
+	int di;
+	u_long flags;
+	int i;
+	int r;
+	int retval = 0;
+	isdn_ctrl cmd;
+	isdn_net_dev *p;
 
-enum {
-	ST_DRV_NULL,
-	ST_DRV_LOADED,
-	ST_DRV_RUNNING,
-};
-
-static char *drv_st_str[] = {
-	"ST_DRV_NULL",
-	"ST_DRV_LOADED",
-	"ST_DRV_RUNNING",
-};
-
-#define DRV_FLAG_REJBUS  1
-
-static int __drv_command(struct isdn_driver *drv, isdn_ctrl *cmd);
-
-static int
-isdn_writebuf_skb(struct isdn_slot *slot, struct sk_buff *skb)
-{
-	struct sk_buff *skb2;
-	struct isdn_driver *drv = slot->drv;
-	int hl = drv->interface->hl_hdrlen;
-	int retval;
-
-	if (skb_headroom(skb) >= hl) {
-		retval = drv->interface->writebuf_skb(slot->di, slot->ch, 1, skb);
-		goto out;
-	}
-	skb2 = skb_realloc_headroom(skb, hl);
-	if (!skb2) {
-		retval = -ENOMEM;
-		goto out;
-	}
-	retval = drv->interface->writebuf_skb(slot->di, slot->ch, 1, skb2);
-	if (retval < 0)
-		kfree_skb(skb2);
-	else
-		kfree_skb(skb);
-
- out:
-	if (retval > 0)
-		slot->obytes += retval;
-
-	return retval;
-}
-
-int
-__isdn_drv_lookup(char *drvid)
-{
-	int drvidx;
-
-	for (drvidx = 0; drvidx < ISDN_MAX_DRIVERS; drvidx++) {
-		if (!drivers[drvidx])
-			continue;
-
-		if (strcmp(drivers[drvidx]->id, drvid) == 0)
-			return drvidx;
-	}
-	return -1;
-}
-
-int
-isdn_drv_lookup(char *drvid)
-{
-	unsigned long flags;
-	int drvidx;
-
-	spin_lock_irqsave(&drivers_lock, flags);
-	drvidx = __isdn_drv_lookup(drvid);
-	spin_unlock_irqrestore(&drivers_lock, flags);
-	return drvidx;
-}
-
-static void
-drv_destroy(struct isdn_driver *drv)
-{
-	kfree(drv->slots);
-	kfree(drv);
-}
-
-static struct isdn_driver *
-get_drv_by_nr(int di)
-{
-	unsigned long flags;
-	struct isdn_driver *drv;
-	
-	BUG_ON(di < 0 || di >= ISDN_MAX_DRIVERS);
-
-	spin_lock_irqsave(&drivers_lock, flags);
-	drv = drivers[di];
-	if (drv)
-		get_drv(drv);
-	spin_unlock_irqrestore(&drivers_lock, flags);
-	return drv;
-}
-
-char *
-isdn_drv_drvid(int di)
-{
-	if (!drivers[di]) {
-		isdn_BUG();
-		return "";
-	}
-	return drivers[di]->id;
-}
-
-/* 
- * Helper keeping track of the features the drivers support
- */
-static void
-set_global_features(void)
-{
-	unsigned long flags;
-	int drvidx;
-
-	isdndev->global_features = 0;
-	spin_lock_irqsave(&drivers_lock, flags);
-	for (drvidx = 0; drvidx < ISDN_MAX_DRIVERS; drvidx++) {
-		if (!drivers[drvidx])
-			continue;
-		if (drivers[drvidx]->fi.state != ST_DRV_RUNNING)
-			continue;
-		isdndev->global_features |= drivers[drvidx]->features;
-	}
-	spin_unlock_irqrestore(&drivers_lock, flags);
-}
-
-/*
- * driver state machine
- */
-static int  isdn_add_channels(struct isdn_driver *, int);
-static void isdn_receive_skb_callback(int di, int ch, struct sk_buff *skb);
-static int  isdn_status_callback(isdn_ctrl * c);
-
-static void isdn_v110_add_features(struct isdn_driver *drv);
-
-static int
-drv_register(struct fsm_inst *fi, int pr, void *arg)
-{
-	struct isdn_driver *drv = fi->userdata;
-	isdn_if *iif = arg;
-	
-	fsm_change_state(fi, ST_DRV_LOADED);
-	drv->maxbufsize = iif->maxbufsize;
-	drv->interface = iif;
-	iif->channels = drv->di;
-	iif->rcvcallb_skb = isdn_receive_skb_callback;
-	iif->statcallb = isdn_status_callback;
-
-	isdn_info_update();
-	return(0);
-}
-
-static int
-drv_stat_run(struct fsm_inst *fi, int pr, void *arg)
-{
-	struct isdn_driver *drv = fi->userdata;
-	fsm_change_state(fi, ST_DRV_RUNNING);
-
-	drv->features = drv->interface->features;
-	isdn_v110_add_features(drv);
-	set_global_features();
-	return(0);
-}
-
-static int
-drv_stat_stop(struct fsm_inst *fi, int pr, void *arg)
-{
-	fsm_change_state(fi, ST_DRV_LOADED);
-	set_global_features();
-	return(0);
-}
-
-static int
-drv_stat_unload(struct fsm_inst *fi, int pr, void *arg)
-{
-	struct isdn_driver *drv = fi->userdata;
-	unsigned long flags;
-
-	spin_lock_irqsave(&drivers_lock, flags);
-	drivers[drv->di] = NULL;
-	spin_unlock_irqrestore(&drivers_lock, flags);
-	put_drv(drv);
-
-	isdndev->channels -= drv->channels;
-
-	isdn_info_update();
-	return 0;
-}
-
-static int
-drv_stat_stavail(struct fsm_inst *fi, int pr, void *arg)
-{
-	struct isdn_driver *drv = fi->userdata;
-	unsigned long flags;
-	isdn_ctrl *c = arg;
-	
-	spin_lock_irqsave(&stat_lock, flags);
-	drv->stavail += c->arg;
-	spin_unlock_irqrestore(&stat_lock, flags);
-	wake_up_interruptible(&drv->st_waitq);
-	return 0;
-}
-
-static int
-drv_to_slot(struct fsm_inst *fi, int pr, void *arg)
-{
-	struct isdn_driver *drv = fi->userdata;
-	isdn_ctrl *c = arg;
-	int ch = c->arg & 0xff;
-
-	return fsm_event(&drv->slots[ch].fi, pr, arg);
-}
-
-static struct fsm_node drv_fn_tbl[] = {
-	{ ST_DRV_NULL,    EV_DRV_REGISTER, drv_register     },
-
-	{ ST_DRV_LOADED,  EV_STAT_RUN,     drv_stat_run     },
-	{ ST_DRV_LOADED,  EV_STAT_STAVAIL, drv_stat_stavail },
-	{ ST_DRV_LOADED,  EV_STAT_UNLOAD,  drv_stat_unload  },
-
-	{ ST_DRV_RUNNING, EV_STAT_STOP,    drv_stat_stop    },
-	{ ST_DRV_RUNNING, EV_STAT_STAVAIL, drv_stat_stavail },
-	{ ST_DRV_RUNNING, EV_STAT_ICALL,   drv_to_slot      },
-	{ ST_DRV_RUNNING, EV_STAT_DCONN,   drv_to_slot      },
-	{ ST_DRV_RUNNING, EV_STAT_BCONN,   drv_to_slot      },
-	{ ST_DRV_RUNNING, EV_STAT_BHUP,    drv_to_slot      },
-	{ ST_DRV_RUNNING, EV_STAT_DHUP,    drv_to_slot      },
-	{ ST_DRV_RUNNING, EV_STAT_BSENT,   drv_to_slot      },
-	{ ST_DRV_RUNNING, EV_STAT_CINF,    drv_to_slot      },
-	{ ST_DRV_RUNNING, EV_STAT_CAUSE,   drv_to_slot      },
-	{ ST_DRV_RUNNING, EV_STAT_DISPLAY, drv_to_slot      },
-	{ ST_DRV_RUNNING, EV_STAT_FAXIND,  drv_to_slot      },
-	{ ST_DRV_RUNNING, EV_STAT_AUDIO,   drv_to_slot      },
-};
-
-static struct fsm drv_fsm = {
-	.st_cnt = ARRAY_SIZE(drv_st_str),
-	.st_str = drv_st_str,
-	.ev_cnt = ARRAY_SIZE(ev_str),
-	.ev_str = ev_str,
-	.fn_cnt = ARRAY_SIZE(drv_fn_tbl),
-	.fn_tbl = drv_fn_tbl,
-};
-
-static void drv_debug(struct fsm_inst *fi, char *fmt, ...)
-{
-	va_list args;
-	struct isdn_driver *drv = fi->userdata;
-	char buf[128];
-	char *p = buf;
-
-	va_start(args, fmt);
-	p += sprintf(p, "%s: ", drv->id);
-	p += vsprintf(p, fmt, args);
-	va_end(args);
-	printk(KERN_DEBUG "%s\n", buf);
-}
-
-/* ====================================================================== */
-/* callbacks from hardware driver                                         */
-/* ====================================================================== */
-
-/* Receive a packet from B-Channel. */
-static void
-isdn_receive_skb_callback(int di, int ch, struct sk_buff *skb)
-{
-	struct isdn_driver *drv;
-
-	drv = get_drv_by_nr(di);
-	if (!drv) {
-		/* hardware driver is buggy - driver isn't registered */
-		isdn_BUG();
-		goto out;
-	}
-	/* we short-cut here instead of going through the driver fsm */
-	if (drv->fi.state != ST_DRV_RUNNING) {
-		/* hardware driver is buggy - driver isn't running */
-		isdn_BUG();
-		goto out;
-	}
-	if (fsm_event(&drv->slots[ch].fi, EV_DATA_IND, skb))
-		dev_kfree_skb(skb);
- out:
-	put_drv(drv);
-}
-
-/* Receive status indications */
-static int
-isdn_status_callback(isdn_ctrl *c)
-{
-	struct isdn_driver *drv;
-	int rc;
-
-	drv = get_drv_by_nr(c->driver);
-	if (!drv) {
-		/* hardware driver is buggy - driver isn't registered */
-		isdn_BUG();
-		return 1;
-	}
-	
+	di = c->driver;
+	i = isdn_dc2minor(di, c->arg);
 	switch (c->command) {
+		case ISDN_STAT_BSENT:
+			if (i < 0)
+				return -1;
+			if (dev->global_flags & ISDN_GLOBAL_STOPPED)
+				return 0;
+			if (isdn_net_stat_callback(i, c))
+				return 0;
+			if (isdn_v110_stat_callback(i, c))
+				return 0;
+			if (isdn_tty_stat_callback(i, c))
+				return 0;
+			wake_up_interruptible(&dev->drv[di]->snd_waitq[c->arg]);
+			break;
 		case ISDN_STAT_STAVAIL:
-			rc = fsm_event(&drv->fi, EV_STAT_STAVAIL, c);
+			dev->drv[di]->stavail += c->arg;
+			wake_up_interruptible(&dev->drv[di]->st_waitq);
 			break;
 		case ISDN_STAT_RUN:
-			rc = fsm_event(&drv->fi, EV_STAT_RUN, c);
+			dev->drv[di]->flags |= DRV_FLAG_RUNNING;
+			for (i = 0; i < ISDN_MAX_CHANNELS; i++)
+				if (dev->drvmap[i] == di)
+					isdn_all_eaz(di, dev->chanmap[i]);
+			set_global_features();
 			break;
 		case ISDN_STAT_STOP:
-			rc = fsm_event(&drv->fi, EV_STAT_STOP, c);
-			break;
-		case ISDN_STAT_UNLOAD:
-			rc = fsm_event(&drv->fi, EV_STAT_UNLOAD, c);
-			break;
-		case ISDN_STAT_ADDCH:
-			rc = fsm_event(&drv->fi, EV_STAT_ADDCH, c);
+			dev->drv[di]->flags &= ~DRV_FLAG_RUNNING;
 			break;
 		case ISDN_STAT_ICALL:
-			rc = fsm_event(&drv->fi, EV_STAT_ICALL, c);
-			break;
-		case ISDN_STAT_DCONN:
-			rc = fsm_event(&drv->fi, EV_STAT_DCONN, c);
-			break;
-		case ISDN_STAT_BCONN:
-			rc = fsm_event(&drv->fi, EV_STAT_BCONN, c);
-			break;
-		case ISDN_STAT_BHUP:
-			rc = fsm_event(&drv->fi, EV_STAT_BHUP, c);
-			break;
-		case ISDN_STAT_DHUP:
-			rc = fsm_event(&drv->fi, EV_STAT_DHUP, c);
-			break;
-		case ISDN_STAT_BSENT:
-			rc = fsm_event(&drv->fi, EV_STAT_BSENT, c);
-			break;
-		case ISDN_STAT_CINF:
-			rc = fsm_event(&drv->fi, EV_STAT_CINF, c);
-			break;
-		case ISDN_STAT_CAUSE:
-			rc = fsm_event(&drv->fi, EV_STAT_CAUSE, c);
-			break;
-		case ISDN_STAT_DISPLAY:
-			rc = fsm_event(&drv->fi, EV_STAT_DISPLAY, c);
-			break;
-		case ISDN_STAT_FAXIND:
-			rc = fsm_event(&drv->fi, EV_STAT_FAXIND, c);
-			break;
-		case ISDN_STAT_AUDIO:
-			rc = fsm_event(&drv->fi, EV_STAT_AUDIO, c);
-			break;
-#warning FIXME divert interface
-#if 0
-		case ISDN_STAT_ICALL:
-			/* Find any ttyI, waiting for D-channel setup */
-			if (isdn_tty_stat_callback(i, c)) {
+			if (i < 0)
+				return -1;
+#ifdef ISDN_DEBUG_STATCALLB
+			printk(KERN_DEBUG "ICALL (net): %d %ld %s\n", di, c->arg, c->parm.num);
+#endif
+			if (dev->global_flags & ISDN_GLOBAL_STOPPED) {
 				cmd.driver = di;
 				cmd.arg = c->arg;
-				cmd.command = ISDN_CMD_ACCEPTB;
+				cmd.command = ISDN_CMD_HANGUP;
 				isdn_command(&cmd);
-				break;
+				return 0;
 			}
-			break;
+			/* Try to find a network-interface which will accept incoming call */
+			r = ((c->command == ISDN_STAT_ICALLW) ? 0 : isdn_net_find_icall(di, c->arg, i, &c->parm.setup));
 			switch (r) {
 				case 0:
+					/* No network-device replies.
+					 * Try ttyI's.
+					 * These return 0 on no match, 1 on match and
+					 * 3 on eventually match, if CID is longer.
+					 */
+                                        if (c->command == ISDN_STAT_ICALL)
+					  if ((retval = isdn_tty_find_icall(di, c->arg, &c->parm.setup))) return(retval);
+#ifdef CONFIG_ISDN_DIVERSION 
                                          if (divert_if)
-						 if ((retval = divert_if->stat_callback(c))) 
-							 return(retval); /* processed */
-					if ((!retval) && (drivers[di]->flags & DRV_FLAG_REJBUS)) {
+                 	                  if ((retval = divert_if->stat_callback(c))) 
+					    return(retval); /* processed */
+#endif /* CONFIG_ISDN_DIVERSION */                       
+					if ((!retval) && (dev->drv[di]->flags & DRV_FLAG_REJBUS)) {
 						/* No tty responding */
 						cmd.driver = di;
 						cmd.arg = c->arg;
@@ -829,7 +484,21 @@ isdn_status_callback(isdn_ctrl *c)
 						retval = 2;
 					}
 					break;
-				case 1: /* incoming call accepted by net interface */
+				case 1:
+					/* Schedule connection-setup */
+					isdn_net_dial();
+					cmd.driver = di;
+					cmd.arg = c->arg;
+					cmd.command = ISDN_CMD_ACCEPTD;
+					for ( p = dev->netdev; p; p = p->next )
+						if ( p->local->isdn_channel == cmd.arg )
+						{
+							strcpy( cmd.parm.setup.eazmsn, p->local->msn );
+							isdn_command(&cmd);
+							retval = 1;
+							break;
+						}
+					break;
 
 				case 2:	/* For calling back, first reject incoming call ... */
 				case 3:	/* Interface found, but down, reject call actively  */
@@ -844,730 +513,716 @@ isdn_status_callback(isdn_ctrl *c)
 					/* Fall through */
 				case 4:
 					/* ... then start callback. */
+					isdn_net_dial();
 					break;
 				case 5:
 					/* Number would eventually match, if longer */
 					retval = 3;
 					break;
 			}
-			dbg_statcallb("ICALL: ret=%d\n", retval);
+#ifdef ISDN_DEBUG_STATCALLB
+			printk(KERN_DEBUG "ICALL: ret=%d\n", retval);
+#endif
 			return retval;
 			break;
+		case ISDN_STAT_CINF:
+			if (i < 0)
+				return -1;
+#ifdef ISDN_DEBUG_STATCALLB
+			printk(KERN_DEBUG "CINF: %ld %s\n", c->arg, c->parm.num);
+#endif
+			if (dev->global_flags & ISDN_GLOBAL_STOPPED)
+				return 0;
+			if (strcmp(c->parm.num, "0"))
+				isdn_net_stat_callback(i, c);
+			isdn_tty_stat_callback(i, c);
+			break;
+		case ISDN_STAT_CAUSE:
+#ifdef ISDN_DEBUG_STATCALLB
+			printk(KERN_DEBUG "CAUSE: %ld %s\n", c->arg, c->parm.num);
+#endif
+			printk(KERN_INFO "isdn: %s,ch%ld cause: %s\n",
+			       dev->drvid[di], c->arg, c->parm.num);
+			isdn_tty_stat_callback(i, c);
+#ifdef CONFIG_ISDN_DIVERSION
+                        if (divert_if)
+                         divert_if->stat_callback(c); 
+#endif /* CONFIG_ISDN_DIVERSION */
+			break;
+		case ISDN_STAT_DISPLAY:
+#ifdef ISDN_DEBUG_STATCALLB
+			printk(KERN_DEBUG "DISPLAY: %ld %s\n", c->arg, c->parm.display);
+#endif
+			isdn_tty_stat_callback(i, c);
+#ifdef CONFIG_ISDN_DIVERSION
+                        if (divert_if)
+                         divert_if->stat_callback(c); 
+#endif /* CONFIG_ISDN_DIVERSION */
+			break;
+		case ISDN_STAT_DCONN:
+			if (i < 0)
+				return -1;
+#ifdef ISDN_DEBUG_STATCALLB
+			printk(KERN_DEBUG "DCONN: %ld\n", c->arg);
+#endif
+			if (dev->global_flags & ISDN_GLOBAL_STOPPED)
+				return 0;
+			/* Find any net-device, waiting for D-channel setup */
+			if (isdn_net_stat_callback(i, c))
+				break;
+			isdn_v110_stat_callback(i, c);
+			/* Find any ttyI, waiting for D-channel setup */
+			if (isdn_tty_stat_callback(i, c)) {
+				cmd.driver = di;
+				cmd.arg = c->arg;
+				cmd.command = ISDN_CMD_ACCEPTB;
+				isdn_command(&cmd);
+				break;
+			}
+			break;
 		case ISDN_STAT_DHUP:
+			if (i < 0)
+				return -1;
+#ifdef ISDN_DEBUG_STATCALLB
+			printk(KERN_DEBUG "DHUP: %ld\n", c->arg);
+#endif
+			if (dev->global_flags & ISDN_GLOBAL_STOPPED)
+				return 0;
+			dev->drv[di]->online &= ~(1 << (c->arg));
+			isdn_info_update();
+			/* Signal hangup to network-devices */
+			if (isdn_net_stat_callback(i, c))
+				break;
+			isdn_v110_stat_callback(i, c);
+			if (isdn_tty_stat_callback(i, c))
+				break;
+#ifdef CONFIG_ISDN_DIVERSION
                         if (divert_if)
-				divert_if->stat_callback(c); 
+                         divert_if->stat_callback(c); 
+#endif /* CONFIG_ISDN_DIVERSION */
+			break;
+			break;
+		case ISDN_STAT_BCONN:
+			if (i < 0)
+				return -1;
+#ifdef ISDN_DEBUG_STATCALLB
+			printk(KERN_DEBUG "BCONN: %ld\n", c->arg);
+#endif
+			/* Signal B-channel-connect to network-devices */
+			if (dev->global_flags & ISDN_GLOBAL_STOPPED)
+				return 0;
+			dev->drv[di]->online |= (1 << (c->arg));
+			isdn_info_update();
+			if (isdn_net_stat_callback(i, c))
+				break;
+			isdn_v110_stat_callback(i, c);
+			if (isdn_tty_stat_callback(i, c))
+				break;
+			break;
+		case ISDN_STAT_BHUP:
+			if (i < 0)
+				return -1;
+#ifdef ISDN_DEBUG_STATCALLB
+			printk(KERN_DEBUG "BHUP: %ld\n", c->arg);
+#endif
+			if (dev->global_flags & ISDN_GLOBAL_STOPPED)
+				return 0;
+			dev->drv[di]->online &= ~(1 << (c->arg));
+			isdn_info_update();
+#ifdef CONFIG_ISDN_X25
+			/* Signal hangup to network-devices */
+			if (isdn_net_stat_callback(i, c))
+				break;
+#endif
+			isdn_v110_stat_callback(i, c);
+			if (isdn_tty_stat_callback(i, c))
+				break;
+			break;
+		case ISDN_STAT_NODCH:
+			if (i < 0)
+				return -1;
+#ifdef ISDN_DEBUG_STATCALLB
+			printk(KERN_DEBUG "NODCH: %ld\n", c->arg);
+#endif
+			if (dev->global_flags & ISDN_GLOBAL_STOPPED)
+				return 0;
+			if (isdn_net_stat_callback(i, c))
+				break;
+			if (isdn_tty_stat_callback(i, c))
+				break;
+			break;
+		case ISDN_STAT_ADDCH:
+			spin_lock_irqsave(&dev->lock, flags);
+			if (isdn_add_channels(dev->drv[di], di, c->arg, 1)) {
+				spin_unlock_irqrestore(&dev->lock, flags);
+				return -1;
+			}
+			spin_unlock_irqrestore(&dev->lock, flags);
+			isdn_info_update();
 			break;
 		case ISDN_STAT_DISCH:
-			save_flags(flags);
-			cli();
+			spin_lock_irqsave(&dev->lock, flags);
 			for (i = 0; i < ISDN_MAX_CHANNELS; i++)
-				if ((slots[i].di == di) &&
-				    (slots[i].ch == c->arg)) {
-					if (c->parm.num[0])
-						slots[i].usage &= ~ISDN_USAGE_DISABLED;
-					else if (USG_NONE(isdn_slot_usage(i)))
-						slots[i].usage |= ISDN_USAGE_DISABLED;
-					else 
-						retval = -1;
-					break;
+				if ((dev->drvmap[i] == di) &&
+				    (dev->chanmap[i] == c->arg)) {
+				    if (c->parm.num[0])
+				      dev->usage[i] &= ~ISDN_USAGE_DISABLED;
+				    else
+				      if (USG_NONE(dev->usage[i])) {
+					dev->usage[i] |= ISDN_USAGE_DISABLED;
+				      }
+				      else 
+					retval = -1;
+				    break;
 				}
-			restore_flags(flags);
+			spin_unlock_irqrestore(&dev->lock, flags);
+			isdn_info_update();
+			break;
+		case ISDN_STAT_UNLOAD:
+			while (dev->drv[di]->locks > 0) {
+				isdn_unlock_driver(dev->drv[di]);
+			}
+			spin_lock_irqsave(&dev->lock, flags);
+			isdn_tty_stat_callback(i, c);
+			for (i = 0; i < ISDN_MAX_CHANNELS; i++)
+				if (dev->drvmap[i] == di) {
+					dev->drvmap[i] = -1;
+					dev->chanmap[i] = -1;
+					dev->usage[i] &= ~ISDN_USAGE_DISABLED;
+				}
+			dev->drivers--;
+			dev->channels -= dev->drv[di]->channels;
+			kfree(dev->drv[di]->rcverr);
+			kfree(dev->drv[di]->rcvcount);
+			for (i = 0; i < dev->drv[di]->channels; i++)
+				skb_queue_purge(&dev->drv[di]->rpqueue[i]);
+			kfree(dev->drv[di]->rpqueue);
+			kfree(dev->drv[di]->rcv_waitq);
+			kfree(dev->drv[di]);
+			dev->drv[di] = NULL;
+			dev->drvid[di][0] = '\0';
+			isdn_info_update();
+			set_global_features();
+			spin_unlock_irqrestore(&dev->lock, flags);
+			return 0;
+		case ISDN_STAT_L1ERR:
 			break;
 		case CAPI_PUT_MESSAGE:
 			return(isdn_capi_rec_hl_msg(&c->parm.cmsg));
+#ifdef CONFIG_ISDN_TTY_FAX
+		case ISDN_STAT_FAXIND:
+			isdn_tty_stat_callback(i, c);
+			break;
+#endif
+#ifdef CONFIG_ISDN_AUDIO
+		case ISDN_STAT_AUDIO:
+			isdn_tty_stat_callback(i, c);
+			break;
+#endif
+#ifdef CONFIG_ISDN_DIVERSION
 	        case ISDN_STAT_PROT:
 	        case ISDN_STAT_REDIR:
                         if (divert_if)
-				return(divert_if->stat_callback(c));
-#endif
+                          return(divert_if->stat_callback(c));
+#endif /* CONFIG_ISDN_DIVERSION */
 		default:
-			rc = 1;
+			return -1;
 	}
-	put_drv(drv);
-	return rc;
+	return 0;
 }
 
-/* ====================================================================== */
-
 /*
- * Register a new ISDN interface
+ * Get integer from char-pointer, set pointer to end of number
  */
 int
-register_isdn(isdn_if *iif)
-{
-	struct isdn_driver *drv;
-	unsigned long flags;
-	int drvidx;
-
-	drv = kmalloc(sizeof(*drv), GFP_ATOMIC);
-	if (!drv) {
-		printk(KERN_WARNING "register_isdn: out of mem\n");
-		goto fail;
-	}
-	memset(drv, 0, sizeof(*drv));
-
-	atomic_set(&drv->refcnt, 0);
-	spin_lock_init(&drv->lock);
-	init_waitqueue_head(&drv->st_waitq);
-	drv->fi.fsm = &drv_fsm;
-	drv->fi.state = ST_DRV_NULL;
-	drv->fi.debug = 1;
-	drv->fi.userdata = drv;
-	drv->fi.printdebug = drv_debug;
-
-	spin_lock_irqsave(&drivers_lock, flags);
-	for (drvidx = 0; drvidx < ISDN_MAX_DRIVERS; drvidx++)
-		if (!drivers[drvidx])
-			break;
-
-	if (drvidx == ISDN_MAX_DRIVERS)
-		goto fail_unlock;
-
-	if (!strlen(iif->id))
-		sprintf(iif->id, "line%d", drvidx);
-
-	if (__isdn_drv_lookup(iif->id) >= 0)
-		goto fail_unlock;
-
-	strcpy(drv->id, iif->id);
-	if (isdn_add_channels(drv, iif->channels))
-		goto fail_unlock;
-
-	drv->di = drvidx;
-	drivers[drvidx] = get_drv(drv);
-	spin_unlock_irqrestore(&drivers_lock, flags);
-
-	fsm_event(&drv->fi, EV_DRV_REGISTER, iif);
-	return 1;
-	
- fail_unlock:
-	spin_unlock_irqrestore(&drivers_lock, flags);
-	kfree(drv);
- fail:
-	return 0;
-}
-
-/* ====================================================================== */
-
-#if defined(CONFIG_ISDN_DIVERSION) || defined(CONFIG_ISDN_DIVERSION_MODULE)
-static isdn_divert_if *divert_if; /* = NULL */
-#else
-#define divert_if ((isdn_divert_if *) NULL)
-#endif
-
-static int isdn_wildmat(char *s, char *p);
-
-static void
-isdn_lock_driver(struct isdn_driver *drv)
-{
-	// FIXME don't ignore return value
-	try_module_get(drv->interface->owner);
-}
-
-static void
-isdn_unlock_driver(struct isdn_driver *drv)
-{
-	module_put(drv->interface->owner);
-}
-
-#if defined(ISDN_DEBUG_NET_DUMP) || defined(ISDN_DEBUG_MODEM_DUMP)
-void
-isdn_dumppkt(char *s, u_char * p, int len, int dumplen)
+isdn_getnum(char **p)
 {
-	int dumpc;
+	int v = -1;
 
-	printk(KERN_DEBUG "%s(%d) ", s, len);
-	for (dumpc = 0; (dumpc < dumplen) && (len); len--, dumpc++)
-		printk(" %02x", *p++);
-	printk("\n");
+	while (*p[0] >= '0' && *p[0] <= '9')
+		v = ((v < 0) ? 0 : (v * 10)) + (int) ((*p[0]++) - '0');
+	return v;
 }
-#endif
 
-/*
- * I picked the pattern-matching-functions from an old GNU-tar version (1.10)
- * It was originally written and put to PD by rs@mirror.TMC.COM (Rich Salz)
- */
-static int
-isdn_star(char *s, char *p)
-{
-	while (isdn_wildmat(s, p)) {
-		if (*++s == '\0')
-			return (2);
-	}
-	return (0);
-}
+#define DLE 0x10
 
 /*
- * Shell-type Pattern-matching for incoming caller-Ids
- * This function gets a string in s and checks, if it matches the pattern
- * given in p.
+ * isdn_readbchan() tries to get data from the read-queue.
+ * It MUST be called with interrupts off.
  *
- * Return:
- *   0 = match.
- *   1 = no match.
- *   2 = no match. Would eventually match, if s would be longer.
- *
- * Possible Patterns:
- *
- * '?'     matches one character
- * '*'     matches zero or more characters
- * [xyz]   matches the set of characters in brackets.
- * [^xyz]  matches any single character not in the set of characters
+ * Be aware that this is not an atomic operation when sleep != 0, even though 
+ * interrupts are turned off! Well, like that we are currently only called
+ * on behalf of a read system call on raw device files (which are documented
+ * to be dangerous and for for debugging purpose only). The inode semaphore
+ * takes care that this is not called for the same minor device number while
+ * we are sleeping, but access is not serialized against simultaneous read()
+ * from the corresponding ttyI device. Can other ugly events, like changes
+ * of the mapping (di,ch)<->minor, happen during the sleep? --he 
  */
-
-static int
-isdn_wildmat(char *s, char *p)
+int
+isdn_readbchan(int di, int channel, u_char * buf, u_char * fp, int len, wait_queue_head_t *sleep)
 {
-	register int last;
-	register int matched;
-	register int reverse;
-	register int nostar = 1;
+	int count;
+	int count_pull;
+	int count_put;
+	int dflag;
+	struct sk_buff *skb;
+	u_char *cp;
 
-	if (!(*s) && !(*p))
-		return(1);
-	for (; *p; s++, p++)
-		switch (*p) {
-			case '\\':
-				/*
-				 * Literal match with following character,
-				 * fall through.
-				 */
-				p++;
-			default:
-				if (*s != *p)
-					return (*s == '\0')?2:1;
-				continue;
-			case '?':
-				/* Match anything. */
-				if (*s == '\0')
-					return (2);
-				continue;
-			case '*':
-				nostar = 0;	
-				/* Trailing star matches everything. */
-				return (*++p ? isdn_star(s, p) : 0);
-			case '[':
-				/* [^....] means inverse character class. */
-				if ((reverse = (p[1] == '^')))
+	if (!dev->drv[di])
+		return 0;
+	if (skb_queue_empty(&dev->drv[di]->rpqueue[channel])) {
+		if (sleep)
+			interruptible_sleep_on(sleep);
+		else
+			return 0;
+	}
+	if (len > dev->drv[di]->rcvcount[channel])
+		len = dev->drv[di]->rcvcount[channel];
+	cp = buf;
+	count = 0;
+	while (len) {
+		if (!(skb = skb_peek(&dev->drv[di]->rpqueue[channel])))
+			break;
+#ifdef CONFIG_ISDN_AUDIO
+		if (ISDN_AUDIO_SKB_LOCK(skb))
+			break;
+		ISDN_AUDIO_SKB_LOCK(skb) = 1;
+		if ((ISDN_AUDIO_SKB_DLECOUNT(skb)) || (dev->drv[di]->DLEflag & (1 << channel))) {
+			char *p = skb->data;
+			unsigned long DLEmask = (1 << channel);
+
+			dflag = 0;
+			count_pull = count_put = 0;
+			while ((count_pull < skb->len) && (len > 0)) {
+				len--;
+				if (dev->drv[di]->DLEflag & DLEmask) {
+					*cp++ = DLE;
+					dev->drv[di]->DLEflag &= ~DLEmask;
+				} else {
+					*cp++ = *p;
+					if (*p == DLE) {
+						dev->drv[di]->DLEflag |= DLEmask;
+						(ISDN_AUDIO_SKB_DLECOUNT(skb))--;
+					}
 					p++;
-				for (last = 0, matched = 0; *++p && (*p != ']'); last = *p)
-					/* This next line requires a good C compiler. */
-					if (*p == '-' ? *s <= *++p && *s >= last : *s == *p)
-						matched = 1;
-				if (matched == reverse)
-					return (1);
-				continue;
+					count_pull++;
+				}
+				count_put++;
+			}
+			if (count_pull >= skb->len)
+				dflag = 1;
+		} else {
+#endif
+			/* No DLE's in buff, so simply copy it */
+			dflag = 1;
+			if ((count_pull = skb->len) > len) {
+				count_pull = len;
+				dflag = 0;
+			}
+			count_put = count_pull;
+			memcpy(cp, skb->data, count_put);
+			cp += count_put;
+			len -= count_put;
+#ifdef CONFIG_ISDN_AUDIO
 		}
-	return (*s == '\0')?0:nostar;
-}
-
-int isdn_msncmp( const char * msn1, const char * msn2 )
-{
-	char TmpMsn1[ ISDN_MSNLEN ];
-	char TmpMsn2[ ISDN_MSNLEN ];
-	char *p;
-
-	for ( p = TmpMsn1; *msn1 && *msn1 != ':'; )  // Strip off a SPID
-		*p++ = *msn1++;
-	*p = '\0';
-
-	for ( p = TmpMsn2; *msn2 && *msn2 != ':'; )  // Strip off a SPID
-		*p++ = *msn2++;
-	*p = '\0';
-
-	return isdn_wildmat( TmpMsn1, TmpMsn2 );
-}
-
-static int
-__drv_command(struct isdn_driver *drv, isdn_ctrl *c)
-{
-#ifdef ISDN_DEBUG_COMMAND
-	switch (c->command) {
-	case ISDN_CMD_SETL2: 
-		printk(KERN_DEBUG "ISDN_CMD_SETL2 %d/%ld\n", c->driver, c->arg & 0xff); break;
-	case ISDN_CMD_SETL3: 
-		printk(KERN_DEBUG "ISDN_CMD_SETL3 %d/%ld\n", c->driver, c->arg & 0xff); break;
-	case ISDN_CMD_DIAL: 
-		printk(KERN_DEBUG "ISDN_CMD_DIAL %d/%ld\n", c->driver, c->arg & 0xff); break;
-	case ISDN_CMD_ACCEPTD: 
-		printk(KERN_DEBUG "ISDN_CMD_ACCEPTD %d/%ld\n", c->driver, c->arg & 0xff); break;
-	case ISDN_CMD_ACCEPTB: 
-		printk(KERN_DEBUG "ISDN_CMD_ACCEPTB %d/%ld\n", c->driver, c->arg & 0xff); break;
-	case ISDN_CMD_HANGUP: 
-		printk(KERN_DEBUG "ISDN_CMD_HANGUP %d/%ld\n", c->driver, c->arg & 0xff); break;
-	case ISDN_CMD_CLREAZ: 
-		printk(KERN_DEBUG "ISDN_CMD_CLREAZ %d/%ld\n", c->driver, c->arg & 0xff); break;
-	case ISDN_CMD_SETEAZ: 
-		printk(KERN_DEBUG "ISDN_CMD_SETEAZ %d/%ld\n", c->driver, c->arg & 0xff); break;
-	default:
-		printk(KERN_DEBUG "%s: cmd = %d\n", __FUNCTION__, c->command);
-	}
 #endif
-	return drv->interface->command(c);
-}
-
-static int
-__slot_command(struct isdn_slot *slot, isdn_ctrl *cmd)
-{
-	struct isdn_driver *drv = slot->drv;
-
-	return __drv_command(drv, cmd);
-}
-
-/*
- * Begin of a CAPI like LL<->HL interface, currently used only for 
- * supplementary service (CAPI 2.0 part III)
- */
-#include <linux/isdn/capicmd.h>
-
-int
-isdn_capi_rec_hl_msg(capi_msg *cm)
-{
-	switch(cm->Command) {
-	case CAPI_FACILITY:
-		/* in the moment only handled in tty */
-		return isdn_tty_capi_facility(cm);
-	default:
-		return -1;
+		count += count_put;
+		if (fp) {
+			memset(fp, 0, count_put);
+			fp += count_put;
+		}
+		if (dflag) {
+			/* We got all the data in this buff.
+			 * Now we can dequeue it.
+			 */
+			if (fp)
+				*(fp - 1) = 0xff;
+#ifdef CONFIG_ISDN_AUDIO
+			ISDN_AUDIO_SKB_LOCK(skb) = 0;
+#endif
+			skb = skb_dequeue(&dev->drv[di]->rpqueue[channel]);
+			dev_kfree_skb(skb);
+		} else {
+			/* Not yet emptied this buff, so it
+			 * must stay in the queue, for further calls
+			 * but we pull off the data we got until now.
+			 */
+			skb_pull(skb, count_pull);
+#ifdef CONFIG_ISDN_AUDIO
+			ISDN_AUDIO_SKB_LOCK(skb) = 0;
+#endif
+		}
+		dev->drv[di]->rcvcount[channel] -= count_put;
 	}
+	return count;
 }
 
-/*
- * Get integer from char-pointer, set pointer to end of number
- */
-int
-isdn_getnum(char **p)
+static __inline int
+isdn_minor2drv(int minor)
 {
-	int v = -1;
-
-	while (*p[0] >= '0' && *p[0] <= '9')
-		v = ((v < 0) ? 0 : (v * 10)) + (int) ((*p[0]++) - '0');
-	return v;
+	return (dev->drvmap[minor]);
 }
 
-static struct isdn_slot *
-get_slot_by_minor(int minor)
+static __inline int
+isdn_minor2chan(int minor)
 {
-	int di, ch;
-	struct isdn_driver *drv;
-
-	for (di = 0; di < ISDN_MAX_DRIVERS; di++) {
-		drv = get_drv_by_nr(di);
-		if (!drv)
-			continue;
-
-		for (ch = 0; ch < drv->channels; ch++) {
-			if (minor-- == 0)
-				goto found;
-		}
-		put_drv(drv);
-	}
-	return NULL;
-
- found:
-	return drv->slots + ch;
-}
-
-static inline void
-put_slot(struct isdn_slot *slot)
-{
-	put_drv(slot->drv);
+	return (dev->chanmap[minor]);
 }
 
 static char *
 isdn_statstr(void)
 {
 	static char istatbuf[2048];
-	struct isdn_slot *slot;
 	char *p;
 	int i;
 
 	sprintf(istatbuf, "idmap:\t");
 	p = istatbuf + strlen(istatbuf);
 	for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
-		slot = get_slot_by_minor(i);
-		if (slot) {
-			sprintf(p, "%s ", slot->drv->id);
-			put_slot(slot);
-		} else {
-			sprintf(p, "- ");
-		}
+		sprintf(p, "%s ", (dev->drvmap[i] < 0) ? "-" : dev->drvid[dev->drvmap[i]]);
 		p = istatbuf + strlen(istatbuf);
 	}
 	sprintf(p, "\nchmap:\t");
 	p = istatbuf + strlen(istatbuf);
 	for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
-		slot = get_slot_by_minor(i);
-		if (slot) {
-			sprintf(p, "%d ", slot->ch);
-			put_slot(slot);
-		} else {
-			sprintf(p, "-1 ");
-		}
+		sprintf(p, "%d ", dev->chanmap[i]);
 		p = istatbuf + strlen(istatbuf);
 	}
 	sprintf(p, "\ndrmap:\t");
 	p = istatbuf + strlen(istatbuf);
 	for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
-		slot = get_slot_by_minor(i);
-		if (slot) {
-			sprintf(p, "%d ", slot->di);
-			put_slot(slot);
-		} else {
-			sprintf(p, "-1 ");
-		}
+		sprintf(p, "%d ", dev->drvmap[i]);
+		p = istatbuf + strlen(istatbuf);
 	}
 	sprintf(p, "\nusage:\t");
 	p = istatbuf + strlen(istatbuf);
 	for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
-		slot = get_slot_by_minor(i);
-		if (slot) {
-			sprintf(p, "%d ", slot->usage);
-			put_slot(slot);
-		} else {
-			sprintf(p, "0 ");
-		}
+		sprintf(p, "%d ", dev->usage[i]);
 		p = istatbuf + strlen(istatbuf);
 	}
 	sprintf(p, "\nflags:\t");
 	p = istatbuf + strlen(istatbuf);
 	for (i = 0; i < ISDN_MAX_DRIVERS; i++) {
-		slot = get_slot_by_minor(i);
-		if (slot) {
-			sprintf(p, "0 ");
-			put_slot(slot);
+		if (dev->drv[i]) {
+			sprintf(p, "%ld ", dev->drv[i]->online);
+			p = istatbuf + strlen(istatbuf);
 		} else {
 			sprintf(p, "? ");
+			p = istatbuf + strlen(istatbuf);
 		}
-		p = istatbuf + strlen(istatbuf);
 	}
 	sprintf(p, "\nphone:\t");
 	p = istatbuf + strlen(istatbuf);
 	for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
-		slot = get_slot_by_minor(i);
-		if (slot) {
-			sprintf(p, "%s ", slot->num);
-			put_slot(slot);
-		} else {
-			sprintf(p, " ");
-		}
+		sprintf(p, "%s ", dev->num[i]);
 		p = istatbuf + strlen(istatbuf);
 	}
 	sprintf(p, "\n");
 	return istatbuf;
 }
 
-/* 
- * /dev/isdninfo
- */
+/* Module interface-code */
 
 void
 isdn_info_update(void)
 {
-	infostruct *p = isdndev->infochain;
-
-	while (p) {
-		*(p->private) = 1;
-		p = (infostruct *) p->next;
-	}
-	wake_up_interruptible(&(isdndev->info_waitq));
-}
-
-static int
-isdn_status_open(struct inode *ino, struct file *filep)
-{
-	infostruct *p;
-	
-	p = kmalloc(sizeof(infostruct), GFP_KERNEL);
-	if (!p)
-		return -ENOMEM;
-
-	p->next = (char *) isdndev->infochain;
-	p->private = (char *) &(filep->private_data);
-	isdndev->infochain = p;
-	/* At opening we allow a single update */
-	filep->private_data = (char *) 1;
-
-	return 0;
-}
-
-static int
-isdn_status_release(struct inode *ino, struct file *filep)
-{
-	infostruct *p = isdndev->infochain;
-	infostruct *q = NULL;
-	
-	lock_kernel();
-
-	while (p) {
-		if (p->private == (char *) &(filep->private_data)) {
-			if (q)
-				q->next = p->next;
-			else
-				isdndev->infochain = (infostruct *) (p->next);
-			kfree(p);
-			goto out;
-		}
-		q = p;
-		p = (infostruct *) (p->next);
-	}
-	printk(KERN_WARNING "isdn: No private data while closing isdnctrl\n");
+	infostruct *p = dev->infochain;
 
- out:
-	unlock_kernel();
-	return 0;
+	while (p) {
+		*(p->private) = 1;
+		p = (infostruct *) p->next;
+	}
+	wake_up_interruptible(&(dev->info_waitq));
 }
 
 static ssize_t
-isdn_status_read(struct file *file, char *buf, size_t count, loff_t * off)
+isdn_read(struct file *file, char *buf, size_t count, loff_t * off)
 {
+	uint minor = MINOR(file->f_dentry->d_inode->i_rdev);
+	int len = 0;
+	int drvidx;
+	int chidx;
 	int retval;
-	size_t len = 0;
 	char *p;
 
 	if (off != &file->f_pos)
 		return -ESPIPE;
 
-	if (!file->private_data) {
-		if (file->f_flags & O_NONBLOCK)
-			return  -EAGAIN;
-		interruptible_sleep_on(&(isdndev->info_waitq));
-	}
 	lock_kernel();
-	p = isdn_statstr();
-	file->private_data = 0;
-	if ((len = strlen(p)) <= count) {
-		if (copy_to_user(buf, p, len)) {
-			retval = -EFAULT;
+	if (minor == ISDN_MINOR_STATUS) {
+		if (!file->private_data) {
+			if (file->f_flags & O_NONBLOCK) {
+				retval = -EAGAIN;
+				goto out;
+			}
+			interruptible_sleep_on(&(dev->info_waitq));
+		}
+		p = isdn_statstr();
+		file->private_data = 0;
+		if ((len = strlen(p)) <= count) {
+			if (copy_to_user(buf, p, len)) {
+				retval = -EFAULT;
+				goto out;
+			}
+			*off += len;
+			retval = len;
+			goto out;
+		}
+		retval = 0;
+		goto out;
+	}
+	if (!dev->drivers) {
+		retval = -ENODEV;
+		goto out;
+	}
+	if (minor <= ISDN_MINOR_BMAX) {
+		printk(KERN_WARNING "isdn_read minor %d obsolete!\n", minor);
+		drvidx = isdn_minor2drv(minor);
+		if (drvidx < 0) {
+			retval = -ENODEV;
+			goto out;
+		}
+		if (!(dev->drv[drvidx]->flags & DRV_FLAG_RUNNING)) {
+			retval = -ENODEV;
 			goto out;
 		}
+		chidx = isdn_minor2chan(minor);
+		if (!(p = kmalloc(count, GFP_KERNEL))) {
+			retval = -ENOMEM;
+			goto out;
+		}
+		len = isdn_readbchan(drvidx, chidx, p, 0, count,
+				     &dev->drv[drvidx]->rcv_waitq[chidx]);
 		*off += len;
+		if (copy_to_user(buf,p,len)) 
+			len = -EFAULT;
+		kfree(p);
 		retval = len;
 		goto out;
 	}
-	retval = 0;
-	goto out;
-
+	if (minor <= ISDN_MINOR_CTRLMAX) {
+		drvidx = isdn_minor2drv(minor - ISDN_MINOR_CTRL);
+		if (drvidx < 0) {
+			retval = -ENODEV;
+			goto out;
+		}
+		if (!dev->drv[drvidx]->stavail) {
+			if (file->f_flags & O_NONBLOCK) {
+				retval = -EAGAIN;
+				goto out;
+			}
+			interruptible_sleep_on(&(dev->drv[drvidx]->st_waitq));
+		}
+		if (dev->drv[drvidx]->interface->readstat) {
+			if (count > dev->drv[drvidx]->stavail)
+				count = dev->drv[drvidx]->stavail;
+			len = dev->drv[drvidx]->interface->
+				readstat(buf, count, 1, drvidx,
+					 isdn_minor2chan(minor));
+		} else {
+			len = 0;
+		}
+		if (len)
+			dev->drv[drvidx]->stavail -= len;
+		else
+			dev->drv[drvidx]->stavail = 0;
+		*off += len;
+		retval = len;
+		goto out;
+	}
+#ifdef CONFIG_ISDN_PPP
+	if (minor <= ISDN_MINOR_PPPMAX) {
+		retval = isdn_ppp_read(minor - ISDN_MINOR_PPP, file, buf, count);
+		goto out;
+	}
+#endif
+	retval = -ENODEV;
  out:
 	unlock_kernel();
 	return retval;
 }
 
 static ssize_t
-isdn_status_write(struct file *file, const char *buf, size_t count, loff_t *off)
-{
-	return -EPERM;
-}
-
-static unsigned int
-isdn_status_poll(struct file *file, poll_table *wait)
-{
-	unsigned int mask = 0;
-
-	poll_wait(file, &(isdndev->info_waitq), wait);
-	lock_kernel();
-	if (file->private_data)
-		mask |= POLLIN | POLLRDNORM;
-	unlock_kernel();
-	return mask;
-}
-
-static int
-isdn_status_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg)
-{
-	static unsigned long zero_ul = 0UL;
-	int ret;
-	struct isdn_slot *slot;
-
-	switch (cmd) {
-	case IIOCGETDVR:
-		return (TTY_DV +
-			(NET_DV << 8) +
-			(INF_DV << 16));
-	case IIOCGETCPS:
-		if (arg) {
-			ulong *p = (ulong *) arg;
-			int i;
-			if ((ret = verify_area(VERIFY_WRITE, (void *) arg,
-					       sizeof(ulong) * ISDN_MAX_CHANNELS * 2)))
-				return ret;
-			for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
-				slot = get_slot_by_minor(i);
-				if (slot) {
-					put_user(slot->ibytes, p++);
-					put_user(slot->obytes, p++);
-					put_slot(slot);
-				} else {
-					put_user(zero_ul, p++);
-					put_user(zero_ul, p++);
-				}
-			}
-			return 0;
-		} else
-			return -EINVAL;
-		break;
-	case IIOCNETGPN:
-		return isdn_net_ioctl(inode, file, cmd, arg);
-	default:
-		return -EINVAL;
-	}
-}
-
-static struct file_operations isdn_status_fops =
-{
-	.owner		= THIS_MODULE,
-	.llseek		= no_llseek,
-	.read		= isdn_status_read,
-	.write		= isdn_status_write,
-	.poll		= isdn_status_poll,
-	.ioctl		= isdn_status_ioctl,
-	.open		= isdn_status_open,
-	.release	= isdn_status_release,
-};
-
-/*
- * /dev/isdnctrlX
- */
-
-static int
-isdn_ctrl_open(struct inode *ino, struct file *file)
-{
-	unsigned int minor = iminor(ino);
-	struct isdn_slot *slot = get_slot_by_minor(minor - ISDN_MINOR_CTRL);
-
-	if (!slot)
-		return -ENODEV;
-
-	isdn_lock_driver(slot->drv);
-	file->private_data = slot;
-
-	return 0;
-}
-
-static int
-isdn_ctrl_release(struct inode *ino, struct file *file)
-{
-	struct isdn_slot *slot = file->private_data;
-
-	if (isdndev->profd == current)
-		isdndev->profd = NULL;
-
-	isdn_unlock_driver(slot->drv);
-	put_slot(slot);
-
-	return 0;
-}
-
-static ssize_t
-isdn_ctrl_read(struct file *file, char *buf, size_t count, loff_t * off)
+isdn_write(struct file *file, const char *buf, size_t count, loff_t * off)
 {
-	struct isdn_slot *slot = file->private_data;
-	DECLARE_WAITQUEUE(wait, current);
-	unsigned long flags;
-	size_t len = 0;
+	uint minor = MINOR(file->f_dentry->d_inode->i_rdev);
+	int drvidx;
+	int chidx;
+	int retval;
 
 	if (off != &file->f_pos)
 		return -ESPIPE;
 
-	if (!slot->drv->interface->readstat) {
-		isdn_BUG();
-		return 0;
-	}
- 	add_wait_queue(&slot->drv->st_waitq, &wait);
-	for (;;) {
-		spin_lock_irqsave(&stat_lock, flags);
-		len = slot->drv->stavail;
-		spin_unlock_irqrestore(&stat_lock, flags);
-		if (len > 0)
-			break;
-		if (signal_pending(current)) {
-			len = -ERESTARTSYS;
-			break;
+	if (minor == ISDN_MINOR_STATUS)
+		return -EPERM;
+	if (!dev->drivers)
+		return -ENODEV;
+
+	lock_kernel();
+	if (minor <= ISDN_MINOR_BMAX) {
+		printk(KERN_WARNING "isdn_write minor %d obsolete!\n", minor);
+		drvidx = isdn_minor2drv(minor);
+		if (drvidx < 0) {
+			retval = -ENODEV;
+			goto out;
 		}
-		if (file->f_flags & O_NONBLOCK) {
-			len = -EAGAIN;
-			break;
+		if (!(dev->drv[drvidx]->flags & DRV_FLAG_RUNNING)) {
+			retval = -ENODEV;
+			goto out;
 		}
-		schedule();
-	}
-	__set_current_state(TASK_RUNNING);
-	remove_wait_queue(&slot->drv->st_waitq, &wait);
-	
-	if (len < 0)
-		return len;
-	
-	if (count > len)
-		count = len;
-		
-	len = slot->drv->interface->readstat(buf, count, 1, slot->di, 
-					     slot->ch);
-
-	spin_lock_irqsave(&stat_lock, flags);
-	if (len) {
-		slot->drv->stavail -= len;
-	} else {
-		isdn_BUG();
-		slot->drv->stavail = 0;
+		chidx = isdn_minor2chan(minor);
+		while (isdn_writebuf_stub(drvidx, chidx, buf, count, 1) != count)
+			interruptible_sleep_on(&dev->drv[drvidx]->snd_waitq[chidx]);
+		retval = count;
+		goto out;
 	}
-	spin_unlock_irqrestore(&stat_lock, flags);
-
-	*off += len;
-	return len;
-}
-
-static ssize_t
-isdn_ctrl_write(struct file *file, const char *buf, size_t count, loff_t *off)
-{
-	struct isdn_slot *slot = file->private_data;
-	int retval;
-
-	if (off != &file->f_pos) {
-		retval = -ESPIPE;
+	if (minor <= ISDN_MINOR_CTRLMAX) {
+		drvidx = isdn_minor2drv(minor - ISDN_MINOR_CTRL);
+		if (drvidx < 0) {
+			retval = -ENODEV;
+			goto out;
+		}
+		/*
+		 * We want to use the isdnctrl device to load the firmware
+		 *
+		 if (!(dev->drv[drvidx]->flags & DRV_FLAG_RUNNING))
+		 return -ENODEV;
+		 */
+		if (dev->drv[drvidx]->interface->writecmd)
+			retval = dev->drv[drvidx]->interface->
+				writecmd(buf, count, 1, drvidx, isdn_minor2chan(minor));
+		else
+			retval = count;
 		goto out;
 	}
-	if (!slot->drv->interface->writecmd) {
-		retval = -EINVAL;
+#ifdef CONFIG_ISDN_PPP
+	if (minor <= ISDN_MINOR_PPPMAX) {
+		retval = isdn_ppp_write(minor - ISDN_MINOR_PPP, file, buf, count);
 		goto out;
 	}
-	retval = slot->drv->interface->writecmd(buf, count, 1, slot->di, 
-						slot->ch);
-
+#endif
+	retval = -ENODEV;
  out:
+	unlock_kernel();
 	return retval;
 }
 
 static unsigned int
-isdn_ctrl_poll(struct file *file, poll_table *wait)
+isdn_poll(struct file *file, poll_table * wait)
 {
-	struct isdn_slot *slot = file->private_data;
 	unsigned int mask = 0;
+	unsigned int minor = MINOR(file->f_dentry->d_inode->i_rdev);
+	int drvidx = isdn_minor2drv(minor - ISDN_MINOR_CTRL);
 
-	poll_wait(file, &slot->drv->st_waitq, wait);
-	mask = POLLOUT | POLLWRNORM;
-	if (slot->drv->stavail)
-		mask |= POLLIN | POLLRDNORM;
-
+	lock_kernel();
+	if (minor == ISDN_MINOR_STATUS) {
+		poll_wait(file, &(dev->info_waitq), wait);
+		/* mask = POLLOUT | POLLWRNORM; */
+		if (file->private_data) {
+			mask |= POLLIN | POLLRDNORM;
+		}
+		goto out;
+	}
+	if (minor >= ISDN_MINOR_CTRL && minor <= ISDN_MINOR_CTRLMAX) {
+		if (drvidx < 0) {
+			/* driver deregistered while file open */
+			mask = POLLHUP;
+			goto out;
+		}
+		poll_wait(file, &(dev->drv[drvidx]->st_waitq), wait);
+		mask = POLLOUT | POLLWRNORM;
+		if (dev->drv[drvidx]->stavail) {
+			mask |= POLLIN | POLLRDNORM;
+		}
+		goto out;
+	}
+#ifdef CONFIG_ISDN_PPP
+	if (minor <= ISDN_MINOR_PPPMAX) {
+		mask = isdn_ppp_poll(file, wait);
+		goto out;
+	}
+#endif
+	mask = POLLERR;
+ out:
+	unlock_kernel();
 	return mask;
 }
 
 
 static int
-isdn_ctrl_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg)
+isdn_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg)
 {
+	uint minor = MINOR(inode->i_rdev);
 	isdn_ctrl c;
 	int drvidx;
+	int chidx;
 	int ret;
 	int i;
 	char *p;
-	/* save stack space */
-	union {
-		char bname[20];
+	char *s;
+	union iocpar {
+		char name[10];
+		char bname[22];
 		isdn_ioctl_struct iocts;
+		isdn_net_ioctl_phone phone;
+		isdn_net_ioctl_cfg cfg;
 	} iocpar;
 
-#define iocts iocpar.iocts
+#define name  iocpar.name
 #define bname iocpar.bname
+#define iocts iocpar.iocts
+#define phone iocpar.phone
+#define cfg   iocpar.cfg
 
+	if (minor == ISDN_MINOR_STATUS) {
+		switch (cmd) {
+			case IIOCGETDVR:
+				return (TTY_DV +
+					(NET_DV << 8) +
+					(INF_DV << 16));
+			case IIOCGETCPS:
+				if (arg) {
+					ulong *p = (ulong *) arg;
+					int i;
+					if ((ret = verify_area(VERIFY_WRITE, (void *) arg,
+							       sizeof(ulong) * ISDN_MAX_CHANNELS * 2)))
+						return ret;
+					for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
+						put_user(dev->ibytes[i], p++);
+						put_user(dev->obytes[i], p++);
+					}
+					return 0;
+				} else
+					return -EINVAL;
+				break;
+#ifdef CONFIG_NETDEVICES
+			case IIOCNETGPN:
+				/* Get peer phone number of a connected 
+				 * isdn network interface */
+				if (arg) {
+					if (copy_from_user((char *) &phone, (char *) arg, sizeof(phone)))
+						return -EFAULT;
+					return isdn_net_getpeer(&phone, (isdn_net_ioctl_phone *) arg);
+				} else
+					return -EINVAL;
+#endif
+			default:
+				return -EINVAL;
+		}
+	}
+	if (!dev->drivers)
+		return -ENODEV;
+	if (minor <= ISDN_MINOR_BMAX) {
+		drvidx = isdn_minor2drv(minor);
+		if (drvidx < 0)
+			return -ENODEV;
+		chidx = isdn_minor2chan(minor);
+		if (!(dev->drv[drvidx]->flags & DRV_FLAG_RUNNING))
+			return -ENODEV;
+		return 0;
+	}
+	if (minor <= ISDN_MINOR_CTRLMAX) {
 /*
  * isdn net devices manage lots of configuration variables as linked lists.
  * Those lists must only be manipulated from user space. Some of the ioctl's
@@ -1575,257 +1230,497 @@ isdn_ctrl_ioctl(struct inode *inode, str
  * manipulating the lists and ioctl's sleeping while accessing the lists
  * are serialized by means of a semaphore.
  */
-	switch (cmd) {
-	case IIOCNETAIF:
-	case IIOCNETASL:
-	case IIOCNETDIF:
-	case IIOCNETSCF:
-	case IIOCNETGCF:
-	case IIOCNETANM:
-	case IIOCNETGNM:
-	case IIOCNETDNM:
-	case IIOCNETDIL:
-	case IIOCNETALN:
-	case IIOCNETDLN:
-	case IIOCNETHUP:
-		return isdn_net_ioctl(inode, file, cmd, arg);
-	case IIOCSETVER:
-		isdndev->net_verbose = arg;
-		printk(KERN_INFO "isdn: Verbose-Level is %d\n", isdndev->net_verbose);
-		return 0;
-	case IIOCSETGST:
-		if (arg) {
-			isdndev->global_flags |= ISDN_GLOBAL_STOPPED;
-			isdn_net_hangup_all();
-		} else {
-			isdndev->global_flags &= ~ISDN_GLOBAL_STOPPED;
-		}
-		return 0;
-	case IIOCSETBRJ:
-		drvidx = -1;
-		if (arg) {
-			char *p;
-			if (copy_from_user((char *) &iocts, (char *) arg,
-					   sizeof(isdn_ioctl_struct)))
-				return -EFAULT;
-			if (strlen(iocts.drvid)) {
-				if ((p = strchr(iocts.drvid, ',')))
-					*p = 0;
-				drvidx = isdn_drv_lookup(iocts.drvid);
-			}
-		}
-		if (drvidx == -1)
-			return -ENODEV;
-		if (iocts.arg)
-			drivers[drvidx]->flags |= DRV_FLAG_REJBUS;
-		else
-			drivers[drvidx]->flags &= ~DRV_FLAG_REJBUS;
-		return 0;
-	case IIOCSIGPRF:
-		isdndev->profd = current;
-		return 0;
-		break;
-	case IIOCGETPRF:
-		/* Get all Modem-Profiles */
-		if (arg) {
-			char *p = (char *) arg;
-			int i;
-
-			for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
-				if (copy_to_user(p, isdn_mdm.info[i].emu.profile,
-						 ISDN_MODEM_NUMREG))
-					return -EFAULT;
-				p += ISDN_MODEM_NUMREG;
-				if (copy_to_user(p, isdn_mdm.info[i].emu.pmsn, ISDN_MSNLEN))
-					return -EFAULT;
-				p += ISDN_MSNLEN;
-				if (copy_to_user(p, isdn_mdm.info[i].emu.plmsn, ISDN_LMSNLEN))
-					return -EFAULT;
-				p += ISDN_LMSNLEN;
-			}
-			return (ISDN_MODEM_NUMREG + ISDN_MSNLEN + ISDN_LMSNLEN) * ISDN_MAX_CHANNELS;
-		} else
-			return -EINVAL;
-		break;
-	case IIOCSETPRF:
-		/* Set all Modem-Profiles */
-		if (arg) {
-			char *p = (char *) arg;
-			int i;
-
-			for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
-				if (copy_from_user(isdn_mdm.info[i].emu.profile, p,
-						   ISDN_MODEM_NUMREG))
+		switch (cmd) {
+			case IIOCNETDWRSET:
+				printk(KERN_INFO "INFO: ISDN_DW_ABC_EXTENSION not enabled\n");
+				return(-EINVAL);
+			case IIOCNETLCR:
+				printk(KERN_INFO "INFO: ISDN_ABC_LCR_SUPPORT not enabled\n");
+				return -ENODEV;
+#ifdef CONFIG_NETDEVICES
+			case IIOCNETAIF:
+				/* Add a network-interface */
+				if (arg) {
+					if (copy_from_user(name, (char *) arg, sizeof(name)))
+						return -EFAULT;
+					s = name;
+				} else {
+					s = NULL;
+				}
+				ret = down_interruptible(&dev->sem);
+				if( ret ) return ret;
+				if ((s = isdn_net_new(s, NULL))) {
+					if (copy_to_user((char *) arg, s, strlen(s) + 1)){
+						ret = -EFAULT;
+					} else {
+						ret = 0;
+					}
+				} else
+					ret = -ENODEV;
+				up(&dev->sem);
+				return ret;
+			case IIOCNETASL:
+				/* Add a slave to a network-interface */
+				if (arg) {
+					if (copy_from_user(bname, (char *) arg, sizeof(bname) - 1))
+						return -EFAULT;
+				} else
+					return -EINVAL;
+				ret = down_interruptible(&dev->sem);
+				if( ret ) return ret;
+				if ((s = isdn_net_newslave(bname))) {
+					if (copy_to_user((char *) arg, s, strlen(s) + 1)){
+						ret = -EFAULT;
+					} else {
+						ret = 0;
+					}
+				} else
+					ret = -ENODEV;
+				up(&dev->sem);
+				return ret;
+			case IIOCNETDIF:
+				/* Delete a network-interface */
+				if (arg) {
+					if (copy_from_user(name, (char *) arg, sizeof(name)))
+						return -EFAULT;
+					ret = down_interruptible(&dev->sem);
+					if( ret ) return ret;
+					ret = isdn_net_rm(name);
+					up(&dev->sem);
+					return ret;
+				} else
+					return -EINVAL;
+			case IIOCNETSCF:
+				/* Set configurable parameters of a network-interface */
+				if (arg) {
+					if (copy_from_user((char *) &cfg, (char *) arg, sizeof(cfg)))
+						return -EFAULT;
+					return isdn_net_setcfg(&cfg);
+				} else
+					return -EINVAL;
+			case IIOCNETGCF:
+				/* Get configurable parameters of a network-interface */
+				if (arg) {
+					if (copy_from_user((char *) &cfg, (char *) arg, sizeof(cfg)))
+						return -EFAULT;
+					if (!(ret = isdn_net_getcfg(&cfg))) {
+						if (copy_to_user((char *) arg, (char *) &cfg, sizeof(cfg)))
+							return -EFAULT;
+					}
+					return ret;
+				} else
+					return -EINVAL;
+			case IIOCNETANM:
+				/* Add a phone-number to a network-interface */
+				if (arg) {
+					if (copy_from_user((char *) &phone, (char *) arg, sizeof(phone)))
+						return -EFAULT;
+					ret = down_interruptible(&dev->sem);
+					if( ret ) return ret;
+					ret = isdn_net_addphone(&phone);
+					up(&dev->sem);
+					return ret;
+				} else
+					return -EINVAL;
+			case IIOCNETGNM:
+				/* Get list of phone-numbers of a network-interface */
+				if (arg) {
+					if (copy_from_user((char *) &phone, (char *) arg, sizeof(phone)))
+						return -EFAULT;
+					ret = down_interruptible(&dev->sem);
+					if( ret ) return ret;
+					ret = isdn_net_getphones(&phone, (char *) arg);
+					up(&dev->sem);
+					return ret;
+				} else
+					return -EINVAL;
+			case IIOCNETDNM:
+				/* Delete a phone-number of a network-interface */
+				if (arg) {
+					if (copy_from_user((char *) &phone, (char *) arg, sizeof(phone)))
+						return -EFAULT;
+					ret = down_interruptible(&dev->sem);
+					if( ret ) return ret;
+					ret = isdn_net_delphone(&phone);
+					up(&dev->sem);
+					return ret;
+				} else
+					return -EINVAL;
+			case IIOCNETDIL:
+				/* Force dialing of a network-interface */
+				if (arg) {
+					if (copy_from_user(name, (char *) arg, sizeof(name)))
+						return -EFAULT;
+					return isdn_net_force_dial(name);
+				} else
+					return -EINVAL;
+#ifdef CONFIG_ISDN_PPP
+			case IIOCNETALN:
+				if (!arg)
+					return -EINVAL;
+				if (copy_from_user(name, (char *) arg, sizeof(name)))
 					return -EFAULT;
-				p += ISDN_MODEM_NUMREG;
-				if (copy_from_user(isdn_mdm.info[i].emu.plmsn, p, ISDN_LMSNLEN))
+				return isdn_ppp_dial_slave(name);
+			case IIOCNETDLN:
+				if (!arg)
+					return -EINVAL;
+				if (copy_from_user(name, (char *) arg, sizeof(name)))
 					return -EFAULT;
-				p += ISDN_LMSNLEN;
-				if (copy_from_user(isdn_mdm.info[i].emu.pmsn, p, ISDN_MSNLEN))
+				return isdn_ppp_hangup_slave(name);
+#endif
+			case IIOCNETHUP:
+				/* Force hangup of a network-interface */
+				if (!arg)
+					return -EINVAL;
+				if (copy_from_user(name, (char *) arg, sizeof(name)))
 					return -EFAULT;
-				p += ISDN_MSNLEN;
-			}
-			return 0;
-		} else
-			return -EINVAL;
-		break;
-	case IIOCSETMAP:
-	case IIOCGETMAP:
-		/* Set/Get MSN->EAZ-Mapping for a driver */
-		if (arg) {
-
-			if (copy_from_user((char *) &iocts,
-					   (char *) arg,
-					   sizeof(isdn_ioctl_struct)))
-				return -EFAULT;
-			drvidx = isdn_drv_lookup(iocts.drvid);
-			if (drvidx == -1)
-				return -ENODEV;
-			if (cmd == IIOCSETMAP) {
-				int loop = 1;
-
-				p = (char *) iocts.arg;
-				i = 0;
-				while (loop) {
-					int j = 0;
-
-					while (1) {
-						if ((ret = get_user(bname[j], p++)))
-							return ret;
-						switch (bname[j]) {
-						case '\0':
-							loop = 0;
-							/* Fall through */
-						case ',':
-							bname[j] = '\0';
-							strcpy(drivers[drvidx]->msn2eaz[i], bname);
-							j = ISDN_MSNLEN;
-							break;
-						default:
-							j++;
-						}
-						if (j >= ISDN_MSNLEN)
-							break;
+				return isdn_net_force_hangup(name);
+				break;
+#endif                          /* CONFIG_NETDEVICES */
+			case IIOCSETVER:
+				dev->net_verbose = arg;
+				printk(KERN_INFO "isdn: Verbose-Level is %d\n", dev->net_verbose);
+				return 0;
+			case IIOCSETGST:
+				if (arg)
+					dev->global_flags |= ISDN_GLOBAL_STOPPED;
+				else
+					dev->global_flags &= ~ISDN_GLOBAL_STOPPED;
+				printk(KERN_INFO "isdn: Global Mode %s\n",
+				       (dev->global_flags & ISDN_GLOBAL_STOPPED) ? "stopped" : "running");
+				return 0;
+			case IIOCSETBRJ:
+				drvidx = -1;
+				if (arg) {
+					int i;
+					char *p;
+					if (copy_from_user((char *) &iocts, (char *) arg,
+					     sizeof(isdn_ioctl_struct)))
+						return -EFAULT;
+					if (strlen(iocts.drvid)) {
+						if ((p = strchr(iocts.drvid, ',')))
+							*p = 0;
+						drvidx = -1;
+						for (i = 0; i < ISDN_MAX_DRIVERS; i++)
+							if (!(strcmp(dev->drvid[i], iocts.drvid))) {
+								drvidx = i;
+								break;
+							}
 					}
-					if (++i > 9)
-						break;
 				}
-			} else {
-				p = (char *) iocts.arg;
-				for (i = 0; i < 10; i++) {
-					sprintf(bname, "%s%s",
-						strlen(drivers[drvidx]->msn2eaz[i]) ?
-						drivers[drvidx]->msn2eaz[i] : "_",
-						(i < 9) ? "," : "\0");
-					if (copy_to_user(p, bname, strlen(bname) + 1))
+				if (drvidx == -1)
+					return -ENODEV;
+				if (iocts.arg)
+					dev->drv[drvidx]->flags |= DRV_FLAG_REJBUS;
+				else
+					dev->drv[drvidx]->flags &= ~DRV_FLAG_REJBUS;
+				return 0;
+			case IIOCSIGPRF:
+				dev->profd = current;
+				return 0;
+				break;
+			case IIOCGETPRF:
+				/* Get all Modem-Profiles */
+				if (arg) {
+					char *p = (char *) arg;
+					int i;
+
+					if ((ret = verify_area(VERIFY_WRITE, (void *) arg,
+					(ISDN_MODEM_NUMREG + ISDN_MSNLEN + ISDN_LMSNLEN)
+						   * ISDN_MAX_CHANNELS)))
+						return ret;
+
+					for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
+						if (copy_to_user(p, dev->mdm.info[i].emu.profile,
+						      ISDN_MODEM_NUMREG))
+							return -EFAULT;
+						p += ISDN_MODEM_NUMREG;
+						if (copy_to_user(p, dev->mdm.info[i].emu.pmsn, ISDN_MSNLEN))
+							return -EFAULT;
+						p += ISDN_MSNLEN;
+						if (copy_to_user(p, dev->mdm.info[i].emu.plmsn, ISDN_LMSNLEN))
+							return -EFAULT;
+						p += ISDN_LMSNLEN;
+					}
+					return (ISDN_MODEM_NUMREG + ISDN_MSNLEN + ISDN_LMSNLEN) * ISDN_MAX_CHANNELS;
+				} else
+					return -EINVAL;
+				break;
+			case IIOCSETPRF:
+				/* Set all Modem-Profiles */
+				if (arg) {
+					char *p = (char *) arg;
+					int i;
+
+					if ((ret = verify_area(VERIFY_READ, (void *) arg,
+					(ISDN_MODEM_NUMREG + ISDN_MSNLEN + ISDN_LMSNLEN)
+						   * ISDN_MAX_CHANNELS)))
+						return ret;
+
+					for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
+						if (copy_from_user(dev->mdm.info[i].emu.profile, p,
+						     ISDN_MODEM_NUMREG))
+							return -EFAULT;
+						p += ISDN_MODEM_NUMREG;
+						if (copy_from_user(dev->mdm.info[i].emu.plmsn, p, ISDN_LMSNLEN))
+							return -EFAULT;
+						p += ISDN_LMSNLEN;
+						if (copy_from_user(dev->mdm.info[i].emu.pmsn, p, ISDN_MSNLEN))
+							return -EFAULT;
+						p += ISDN_MSNLEN;
+					}
+					return 0;
+				} else
+					return -EINVAL;
+				break;
+			case IIOCSETMAP:
+			case IIOCGETMAP:
+				/* Set/Get MSN->EAZ-Mapping for a driver */
+				if (arg) {
+
+					if (copy_from_user((char *) &iocts,
+							    (char *) arg,
+					     sizeof(isdn_ioctl_struct)))
 						return -EFAULT;
-					p += strlen(bname);
-				}
-			}
-			return 0;
-		} else
-			return -EINVAL;
-	case IIOCDBGVAR:
-		if (arg) {
-			if (copy_to_user((char *) arg, (char *) &isdndev, sizeof(ulong)))
-				return -EFAULT;
-			return 0;
-		} else
-			return -EINVAL;
-		break;
-	default:
-		if ((cmd & IIOCDRVCTL) == IIOCDRVCTL)
-			cmd = ((cmd >> _IOC_NRSHIFT) & _IOC_NRMASK) & ISDN_DRVIOCTL_MASK;
-		else
-			return -EINVAL;
-		if (arg) {
-			if (copy_from_user((char *) &iocts, (char *) arg, sizeof(isdn_ioctl_struct)))
-				return -EFAULT;
-			drvidx = isdn_drv_lookup(iocts.drvid);
-			if (drvidx == -1)
-				return -ENODEV;
-			if ((ret = verify_area(VERIFY_WRITE, (void *) arg,
-					       sizeof(isdn_ioctl_struct))))
-				return ret;
-			c.driver = drvidx;
-			c.command = ISDN_CMD_IOCTL;
-			c.arg = cmd;
-			memcpy(c.parm.num, (char *) &iocts.arg, sizeof(ulong));
-			ret = __drv_command(drivers[drvidx], &c);
-			memcpy((char *) &iocts.arg, c.parm.num, sizeof(ulong));
-			if (copy_to_user((char *) arg, &iocts, sizeof(isdn_ioctl_struct)))
-				return -EFAULT;
-			return ret;
-		} else
-			return -EINVAL;
+					if (strlen(iocts.drvid)) {
+						drvidx = -1;
+						for (i = 0; i < ISDN_MAX_DRIVERS; i++)
+							if (!(strcmp(dev->drvid[i], iocts.drvid))) {
+								drvidx = i;
+								break;
+							}
+					} else
+						drvidx = 0;
+					if (drvidx == -1)
+						return -ENODEV;
+					if (cmd == IIOCSETMAP) {
+						int loop = 1;
+
+						p = (char *) iocts.arg;
+						i = 0;
+						while (loop) {
+							int j = 0;
+
+							while (1) {
+								if ((ret = verify_area(VERIFY_READ, p, 1)))
+									return ret;
+								get_user(bname[j], p++);
+								switch (bname[j]) {
+									case '\0':
+										loop = 0;
+										/* Fall through */
+									case ',':
+										bname[j] = '\0';
+										strcpy(dev->drv[drvidx]->msn2eaz[i], bname);
+										j = ISDN_MSNLEN;
+										break;
+									default:
+										j++;
+								}
+								if (j >= ISDN_MSNLEN)
+									break;
+							}
+							if (++i > 9)
+								break;
+						}
+					} else {
+						p = (char *) iocts.arg;
+						for (i = 0; i < 10; i++) {
+							sprintf(bname, "%s%s",
+								strlen(dev->drv[drvidx]->msn2eaz[i]) ?
+								dev->drv[drvidx]->msn2eaz[i] : "_",
+								(i < 9) ? "," : "\0");
+							if (copy_to_user(p, bname, strlen(bname) + 1))
+								return -EFAULT;
+							p += strlen(bname);
+						}
+					}
+					return 0;
+				} else
+					return -EINVAL;
+			case IIOCDBGVAR:
+				if (arg) {
+					if (copy_to_user((char *) arg, (char *) &dev, sizeof(ulong)))
+						return -EFAULT;
+					return 0;
+				} else
+					return -EINVAL;
+				break;
+			default:
+				if ((cmd & IIOCDRVCTL) == IIOCDRVCTL)
+					cmd = ((cmd >> _IOC_NRSHIFT) & _IOC_NRMASK) & ISDN_DRVIOCTL_MASK;
+				else
+					return -EINVAL;
+				if (arg) {
+					int i;
+					char *p;
+					if (copy_from_user((char *) &iocts, (char *) arg, sizeof(isdn_ioctl_struct)))
+						return -EFAULT;
+					if (strlen(iocts.drvid)) {
+						if ((p = strchr(iocts.drvid, ',')))
+							*p = 0;
+						drvidx = -1;
+						for (i = 0; i < ISDN_MAX_DRIVERS; i++)
+							if (!(strcmp(dev->drvid[i], iocts.drvid))) {
+								drvidx = i;
+								break;
+							}
+					} else
+						drvidx = 0;
+					if (drvidx == -1)
+						return -ENODEV;
+					if ((ret = verify_area(VERIFY_WRITE, (void *) arg,
+					     sizeof(isdn_ioctl_struct))))
+						return ret;
+					c.driver = drvidx;
+					c.command = ISDN_CMD_IOCTL;
+					c.arg = cmd;
+					memcpy(c.parm.num, (char *) &iocts.arg, sizeof(ulong));
+					ret = isdn_command(&c);
+					memcpy((char *) &iocts.arg, c.parm.num, sizeof(ulong));
+					if (copy_to_user((char *) arg, &iocts, sizeof(isdn_ioctl_struct)))
+						return -EFAULT;
+					return ret;
+				} else
+					return -EINVAL;
+		}
 	}
-#undef iocts
+#ifdef CONFIG_ISDN_PPP
+	if (minor <= ISDN_MINOR_PPPMAX)
+		return (isdn_ppp_ioctl(minor - ISDN_MINOR_PPP, file, cmd, arg));
+#endif
+	return -ENODEV;
+
+#undef name
 #undef bname
+#undef iocts
+#undef phone
+#undef cfg
 }
 
-static struct file_operations isdn_ctrl_fops =
-{
-	.owner		= THIS_MODULE,
-	.llseek		= no_llseek,
-	.read		= isdn_ctrl_read,
-	.write		= isdn_ctrl_write,
-	.poll		= isdn_ctrl_poll,
-	.ioctl		= isdn_ctrl_ioctl,
-	.open		= isdn_ctrl_open,
-	.release	= isdn_ctrl_release,
-};
-
-
 /*
- * file_operations for major 45, /dev/isdn*
- * stolen from drivers/char/misc.c
+ * Open the device code.
  */
-
 static int
-isdn_open(struct inode * inode, struct file * file)
+isdn_open(struct inode *ino, struct file *filep)
 {
-	int minor = iminor(inode);
-	int err = -ENODEV;
-	struct file_operations *old_fops, *new_fops = NULL;
-	
-	if (minor >= ISDN_MINOR_CTRL && minor <= ISDN_MINOR_CTRLMAX)
-		new_fops = fops_get(&isdn_ctrl_fops);
+	uint minor = MINOR(ino->i_rdev);
+	int drvidx;
+	int chidx;
+	int retval = -ENODEV;
+
+
+	if (minor == ISDN_MINOR_STATUS) {
+		infostruct *p;
+
+		if ((p = kmalloc(sizeof(infostruct), GFP_KERNEL))) {
+			p->next = (char *) dev->infochain;
+			p->private = (char *) &(filep->private_data);
+			dev->infochain = p;
+			/* At opening we allow a single update */
+			filep->private_data = (char *) 1;
+			retval = 0;
+			goto out;
+		} else {
+			retval = -ENOMEM;
+			goto out;
+		}
+	}
+	if (!dev->channels)
+		goto out;
+	if (minor <= ISDN_MINOR_BMAX) {
+		printk(KERN_WARNING "isdn_open minor %d obsolete!\n", minor);
+		drvidx = isdn_minor2drv(minor);
+		if (drvidx < 0)
+			goto out;
+		chidx = isdn_minor2chan(minor);
+		if (!(dev->drv[drvidx]->flags & DRV_FLAG_RUNNING))
+			goto out;
+		if (!(dev->drv[drvidx]->online & (1 << chidx)))
+			goto out;
+		isdn_lock_drivers();
+		retval = 0;
+		goto out;
+	}
+	if (minor <= ISDN_MINOR_CTRLMAX) {
+		drvidx = isdn_minor2drv(minor - ISDN_MINOR_CTRL);
+		if (drvidx < 0)
+			goto out;
+		isdn_lock_drivers();
+		retval = 0;
+		goto out;
+	}
 #ifdef CONFIG_ISDN_PPP
-	else if (minor >= ISDN_MINOR_PPP && minor <= ISDN_MINOR_PPPMAX)
-		new_fops = fops_get(&isdn_ppp_fops);
+	if (minor <= ISDN_MINOR_PPPMAX) {
+		retval = isdn_ppp_open(minor - ISDN_MINOR_PPP, filep);
+		if (retval == 0)
+			isdn_lock_drivers();
+		goto out;
+	}
 #endif
-	else if (minor == ISDN_MINOR_STATUS)
-		new_fops = fops_get(&isdn_status_fops);
+ out:
+	return retval;
+}
 
-	if (!new_fops)
-		goto out;
+static int
+isdn_close(struct inode *ino, struct file *filep)
+{
+	uint minor = MINOR(ino->i_rdev);
 
-	err = 0;
-	old_fops = file->f_op;
-	file->f_op = new_fops;
-	if (file->f_op->open) {
-		err = file->f_op->open(inode,file);
-		if (err) {
-			fops_put(file->f_op);
-			file->f_op = fops_get(old_fops);
+	lock_kernel();
+	if (minor == ISDN_MINOR_STATUS) {
+		infostruct *p = dev->infochain;
+		infostruct *q = NULL;
+
+		while (p) {
+			if (p->private == (char *) &(filep->private_data)) {
+				if (q)
+					q->next = p->next;
+				else
+					dev->infochain = (infostruct *) (p->next);
+				kfree(p);
+				goto out;
+			}
+			q = p;
+			p = (infostruct *) (p->next);
 		}
+		printk(KERN_WARNING "isdn: No private data while closing isdnctrl\n");
+		goto out;
+	}
+	isdn_unlock_drivers();
+	if (minor <= ISDN_MINOR_BMAX)
+		goto out;
+	if (minor <= ISDN_MINOR_CTRLMAX) {
+		if (dev->profd == current)
+			dev->profd = NULL;
+		goto out;
 	}
-	fops_put(old_fops);
-	
+#ifdef CONFIG_ISDN_PPP
+	if (minor <= ISDN_MINOR_PPPMAX)
+		isdn_ppp_release(minor - ISDN_MINOR_PPP, filep);
+#endif
+
  out:
-	return err;
+	unlock_kernel();
+	return 0;
 }
 
 static struct file_operations isdn_fops =
 {
-	.owner		= THIS_MODULE,
-	.open		= isdn_open,
+	owner:		THIS_MODULE,
+	llseek:		no_llseek,
+	read:		isdn_read,
+	write:		isdn_write,
+	poll:		isdn_poll,
+	ioctl:		isdn_ioctl,
+	open:		isdn_open,
+	release:	isdn_close,
 };
 
 char *
 isdn_map_eaz2msn(char *msn, int di)
 {
-	struct isdn_driver *this = drivers[di];
+	isdn_driver_t *this = dev->drv[di];
 	int i;
 
 	if (strlen(msn) == 1) {
@@ -1841,118 +1736,281 @@ isdn_map_eaz2msn(char *msn, int di)
  * Find an unused ISDN-channel, whose feature-flags match the
  * given L2- and L3-protocols.
  */
-struct isdn_slot *
-isdn_get_free_slot(int usage, int l2_proto, int l3_proto,
-		   int pre_dev, int pre_chan, char *msn)
-{
-	struct isdn_driver *drv;
-	struct isdn_slot *slot;
-	int di, ch;
-	unsigned long flags;
-	unsigned long features;
-
-	features = ((1 << l2_proto) | (0x10000 << l3_proto));
-
-	for (di = 0; di < ISDN_MAX_DRIVERS; di++) {
-		if (pre_dev >= 0 && pre_dev != di)
-			continue;
-
-		drv = get_drv_by_nr(di);
-		if (!drv)
-			continue;
-
-		if (drv->fi.state != ST_DRV_RUNNING)
-			goto put;
-
-		if ((drv->features & features) != features)
-			goto put;
-
-		spin_lock_irqsave(&drv->lock, flags);
-		for (ch = 0; ch < drv->channels; ch++) {
-			if (pre_chan >= 0 && pre_chan != ch)
-				continue;
+#define L2V (~(ISDN_FEATURE_L2_V11096|ISDN_FEATURE_L2_V11019|ISDN_FEATURE_L2_V11038))
 
-			slot = &drv->slots[ch];
+/*
+ * This function must be called with holding the dev->lock.
+ */
+int
+isdn_get_free_channel(int usage, int l2_proto, int l3_proto, int pre_dev
+		      ,int pre_chan, char *msn)
+{
+	int i;
+	ulong features;
+	ulong vfeatures;
 
-			if (!USG_NONE(slot->usage))
+	features = ((1 << l2_proto) | (0x10000 << l3_proto));
+	vfeatures = (((1 << l2_proto) | (0x10000 << l3_proto)) &
+		     ~(ISDN_FEATURE_L2_V11096|ISDN_FEATURE_L2_V11019|ISDN_FEATURE_L2_V11038));
+	/* If Layer-2 protocol is V.110, accept drivers with
+	 * transparent feature even if these don't support V.110
+	 * because we can emulate this in linklevel.
+	 */
+	for (i = 0; i < ISDN_MAX_CHANNELS; i++)
+		if (USG_NONE(dev->usage[i]) &&
+		    (dev->drvmap[i] != -1)) {
+			int d = dev->drvmap[i];
+			if ((dev->usage[i] & ISDN_USAGE_EXCLUSIVE) &&
+			((pre_dev != d) || (pre_chan != dev->chanmap[i])))
 				continue;
-
-			if (slot->usage & ISDN_USAGE_DISABLED)
+			if (!strcmp(isdn_map_eaz2msn(msn, d), "-"))
 				continue;
+			if (dev->usage[i] & ISDN_USAGE_DISABLED)
+			        continue; /* usage not allowed */
+			if (dev->drv[d]->flags & DRV_FLAG_RUNNING) {
+				if (((dev->drv[d]->interface->features & features) == features) ||
+				    (((dev->drv[d]->interface->features & vfeatures) == vfeatures) &&
+				     (dev->drv[d]->interface->features & ISDN_FEATURE_L2_TRANS))) {
+					if ((pre_dev < 0) || (pre_chan < 0)) {
+						dev->usage[i] &= ISDN_USAGE_EXCLUSIVE;
+						dev->usage[i] |= usage;
+						isdn_info_update();
+						return i;
+					} else {
+						if ((pre_dev == d) && (pre_chan == dev->chanmap[i])) {
+							dev->usage[i] &= ISDN_USAGE_EXCLUSIVE;
+							dev->usage[i] |= usage;
+							isdn_info_update();
+							return i;
+						}
+					}
+				}
+			}
+		}
+	return -1;
+}
 
-			if (strcmp(isdn_map_eaz2msn(msn, drv->di), "-") == 0)
-				continue;
+/*
+ * Set state of ISDN-channel to 'unused'
+ */
+void
+isdn_free_channel(int di, int ch, int usage)
+{
+	int i;
 
-			goto found;
-			
+	for (i = 0; i < ISDN_MAX_CHANNELS; i++)
+		if (((!usage) || ((dev->usage[i] & ISDN_USAGE_MASK) == usage)) &&
+		    (dev->drvmap[i] == di) &&
+		    (dev->chanmap[i] == ch)) {
+			dev->usage[i] &= (ISDN_USAGE_NONE | ISDN_USAGE_EXCLUSIVE);
+			strcpy(dev->num[i], "???");
+			dev->ibytes[i] = 0;
+			dev->obytes[i] = 0;
+// 20.10.99 JIM, try to reinitialize v110 !
+			dev->v110emu[i] = 0;
+			atomic_set(&(dev->v110use[i]), 0);
+			isdn_v110_close(dev->v110[i]);
+			dev->v110[i] = NULL;
+// 20.10.99 JIM, try to reinitialize v110 !
+			isdn_info_update();
+			skb_queue_purge(&dev->drv[di]->rpqueue[ch]);
 		}
-		spin_unlock_irqrestore(&drv->lock, flags);
-
-	put:
-		put_drv(drv);
-	}
-	return NULL;
+}
 
- found:
-	slot->usage = usage;
-	spin_unlock_irqrestore(&drv->lock, flags);
+/*
+ * Cancel Exclusive-Flag for ISDN-channel
+ */
+void
+isdn_unexclusive_channel(int di, int ch)
+{
+	int i;
 
-	isdn_info_update();
-	fsm_event(&slot->fi, EV_SLOT_BIND, NULL);
-	return slot;
+	for (i = 0; i < ISDN_MAX_CHANNELS; i++)
+		if ((dev->drvmap[i] == di) &&
+		    (dev->chanmap[i] == ch)) {
+			dev->usage[i] &= ~ISDN_USAGE_EXCLUSIVE;
+			isdn_info_update();
+			return;
+		}
 }
 
 /*
- * Set state of ISDN-channel to 'unused'
+ *  writebuf replacement for SKB_ABLE drivers
  */
-void
-isdn_slot_free(struct isdn_slot *slot)
+static int
+isdn_writebuf_stub(int drvidx, int chan, const u_char * buf, int len,
+		   int user)
 {
-	fsm_event(&slot->fi, EV_SLOT_UNBIND, NULL);
+	int ret;
+	int hl = dev->drv[drvidx]->interface->hl_hdrlen;
+	struct sk_buff *skb = alloc_skb(hl + len, GFP_ATOMIC);
+
+	if (!skb)
+		return 0;
+	skb_reserve(skb, hl);
+	if (user)
+		copy_from_user(skb_put(skb, len), buf, len);
+	else
+		memcpy(skb_put(skb, len), buf, len);
+	ret = dev->drv[drvidx]->interface->writebuf_skb(drvidx, chan, 1, skb);
+	if (ret <= 0)
+		dev_kfree_skb(skb);
+	if (ret > 0)
+		dev->obytes[isdn_dc2minor(drvidx, chan)] += ret;
+	return ret;
 }
 
 /*
  * Return: length of data on success, -ERRcode on failure.
  */
 int
-isdn_slot_write(struct isdn_slot *slot, struct sk_buff *skb)
+isdn_writebuf_skb_stub(int drvidx, int chan, int ack, struct sk_buff *skb)
 {
-	return fsm_event(&slot->fi, EV_DATA_REQ, skb);
+	int ret;
+	struct sk_buff *nskb = NULL;
+	int v110_ret = skb->len;
+	int idx = isdn_dc2minor(drvidx, chan);
+
+	if (dev->v110[idx]) {
+		atomic_inc(&dev->v110use[idx]);
+		nskb = isdn_v110_encode(dev->v110[idx], skb);
+		atomic_dec(&dev->v110use[idx]);
+		if (!nskb)
+			return 0;
+		v110_ret = *((int *)nskb->data);
+		skb_pull(nskb, sizeof(int));
+		if (!nskb->len) {
+			dev_kfree_skb(nskb);
+			return v110_ret;
+		}
+		/* V.110 must always be acknowledged */
+		ack = 1;
+		ret = dev->drv[drvidx]->interface->writebuf_skb(drvidx, chan, ack, nskb);
+	} else {
+		int hl = dev->drv[drvidx]->interface->hl_hdrlen;
+
+		if( skb_headroom(skb) < hl ){
+			/* 
+			 * This should only occur when new HL driver with
+			 * increased hl_hdrlen was loaded after netdevice
+			 * was created and connected to the new driver.
+			 *
+			 * The V.110 branch (re-allocates on its own) does
+			 * not need this
+			 */
+			struct sk_buff * skb_tmp;
+
+			skb_tmp = skb_realloc_headroom(skb, hl);
+			printk(KERN_DEBUG "isdn_writebuf_skb_stub: reallocating headroom%s\n", skb_tmp ? "" : " failed");
+			if (!skb_tmp) return -ENOMEM; /* 0 better? */
+			ret = dev->drv[drvidx]->interface->writebuf_skb(drvidx, chan, ack, skb_tmp);
+			if( ret > 0 ){
+				dev_kfree_skb(skb);
+			} else {
+				dev_kfree_skb(skb_tmp);
+			}
+		} else {
+			ret = dev->drv[drvidx]->interface->writebuf_skb(drvidx, chan, ack, skb);
+		}
+	}
+	if (ret > 0) {
+		dev->obytes[idx] += ret;
+		if (dev->v110[idx]) {
+			atomic_inc(&dev->v110use[idx]);
+			dev->v110[idx]->skbuser++;
+			atomic_dec(&dev->v110use[idx]);
+			/* For V.110 return unencoded data length */
+			ret = v110_ret;
+			/* if the complete frame was send we free the skb;
+			   if not upper function will requeue the skb */ 
+			if (ret == skb->len)
+				dev_kfree_skb(skb);
+		}
+	} else
+		if (dev->v110[idx])
+			dev_kfree_skb(nskb);
+	return ret;
 }
 
-static int
-isdn_add_channels(struct isdn_driver *drv, int n)
+int
+isdn_add_channels(isdn_driver_t *d, int drvidx, int n, int adding)
 {
-	struct isdn_slot *slot;
-	int ch;
+	int j, k, m;
 
-       	if (n < 1)
-		return 0;
+	init_waitqueue_head(&d->st_waitq);
+	if (d->flags & DRV_FLAG_RUNNING)
+		return -1;
+       	if (n < 1) return 0;
 
-	if (isdndev->channels + n > ISDN_MAX_CHANNELS) {
+	m = (adding) ? d->channels + n : n;
+
+	if (dev->channels + n > ISDN_MAX_CHANNELS) {
 		printk(KERN_WARNING "register_isdn: Max. %d channels supported\n",
 		       ISDN_MAX_CHANNELS);
-		return -EBUSY;
+		return -1;
 	}
-	isdndev->channels += n;
-	drv->slots = kmalloc(sizeof(struct isdn_slot) * n, GFP_ATOMIC);
-	if (!drv->slots)
-		return -ENOMEM;
-	memset(drv->slots, 0, sizeof(struct isdn_slot) * n);
-	for (ch = 0; ch < n; ch++) {
-		slot = drv->slots + ch;
-
-		slot->ch = ch;
-		slot->di = drv->di;
-		slot->drv = drv;
-		strcpy(slot->num, "???");
-		slot->fi.fsm = &slot_fsm;
-		slot->fi.state = ST_SLOT_NULL;
-		slot->fi.debug = 1;
-		slot->fi.userdata = slot;
-		slot->fi.printdebug = slot_debug;
+
+	if ((adding) && (d->rcverr))
+		kfree(d->rcverr);
+	if (!(d->rcverr = kmalloc(sizeof(int) * m, GFP_ATOMIC))) {
+		printk(KERN_WARNING "register_isdn: Could not alloc rcverr\n");
+		return -1;
+	}
+	memset((char *) d->rcverr, 0, sizeof(int) * m);
+
+	if ((adding) && (d->rcvcount))
+		kfree(d->rcvcount);
+	if (!(d->rcvcount = kmalloc(sizeof(int) * m, GFP_ATOMIC))) {
+		printk(KERN_WARNING "register_isdn: Could not alloc rcvcount\n");
+		if (!adding) kfree(d->rcverr);
+		return -1;
+	}
+	memset((char *) d->rcvcount, 0, sizeof(int) * m);
+
+	if ((adding) && (d->rpqueue)) {
+		for (j = 0; j < d->channels; j++)
+			skb_queue_purge(&d->rpqueue[j]);
+		kfree(d->rpqueue);
+	}
+	if (!(d->rpqueue = kmalloc(sizeof(struct sk_buff_head) * m, GFP_ATOMIC))) {
+		printk(KERN_WARNING "register_isdn: Could not alloc rpqueue\n");
+		if (!adding) {
+			kfree(d->rcvcount);
+			kfree(d->rcverr);
+		}
+		return -1; 
 	}
-	drv->channels = n;
+	for (j = 0; j < m; j++) {
+		skb_queue_head_init(&d->rpqueue[j]);
+	}
+
+	if ((adding) && (d->rcv_waitq))
+		kfree(d->rcv_waitq);
+	d->rcv_waitq = kmalloc(sizeof(wait_queue_head_t) * 2 * m, GFP_ATOMIC);
+	if (!d->rcv_waitq) {
+		printk(KERN_WARNING "register_isdn: Could not alloc rcv_waitq\n");
+		if (!adding) {
+			kfree(d->rpqueue);
+			kfree(d->rcvcount);
+			kfree(d->rcverr);
+		}
+		return -1;
+	}
+	d->snd_waitq = d->rcv_waitq + m;
+	for (j = 0; j < m; j++) {
+		init_waitqueue_head(&d->rcv_waitq[j]);
+		init_waitqueue_head(&d->snd_waitq[j]);
+	}
+
+	dev->channels += n;
+	for (j = d->channels; j < m; j++)
+		for (k = 0; k < ISDN_MAX_CHANNELS; k++)
+			if (dev->chanmap[k] < 0) {
+				dev->chanmap[k] = j;
+				dev->drvmap[k] = drvidx;
+				break;
+			}
+	d->channels = m;
 	return 0;
 }
 
@@ -1960,63 +2018,68 @@ isdn_add_channels(struct isdn_driver *dr
  * Low-level-driver registration
  */
 
-#if defined(CONFIG_ISDN_DIVERSION) || defined(CONFIG_ISDN_DIVERSION_MODULE)
+static void
+set_global_features(void)
+{
+	int drvidx;
+
+	dev->global_features = 0;
+	for (drvidx = 0; drvidx < ISDN_MAX_DRIVERS; drvidx++) {
+		if (!dev->drv[drvidx])
+			continue;
+		if (dev->drv[drvidx]->interface)
+			dev->global_features |= dev->drv[drvidx]->interface->features;
+	}
+}
+
+#ifdef CONFIG_ISDN_DIVERSION
 
-/*
- * map_drvname
- */
 static char *map_drvname(int di)
 {
-	if ((di < 0) || (di >= ISDN_MAX_DRIVERS)) 
-		return(NULL);
-	return(isdndev->drvid[di]); /* driver name */
-}
+  if ((di < 0) || (di >= ISDN_MAX_DRIVERS)) 
+    return(NULL);
+  return(dev->drvid[di]); /* driver name */
+} /* map_drvname */
 
-/*
- * map_namedrv
- */
 static int map_namedrv(char *id)
-{
-	int i;
+{  int i;
 
-	for (i = 0; i < ISDN_MAX_DRIVERS; i++) {
-		if (!strcmp(dev->drvid[i],id)) 
-			return(i);
-	}
-	return(-1);
-}
+   for (i = 0; i < ISDN_MAX_DRIVERS; i++)
+    { if (!strcmp(dev->drvid[i],id)) 
+        return(i);
+    }
+   return(-1);
+} /* map_namedrv */
 
-/*
- * DIVERT_REG_NAME
- */
 int DIVERT_REG_NAME(isdn_divert_if *i_div)
 {
-	if (i_div->if_magic != DIVERT_IF_MAGIC) 
-		return(DIVERT_VER_ERR);
-	switch (i_div->cmd) {
-		case DIVERT_CMD_REL:
-			if (divert_if != i_div) 
-				return(DIVERT_REL_ERR);
-			divert_if = NULL; /* free interface */
-			MOD_DEC_USE_COUNT;
-			return(DIVERT_NO_ERR);
-		case DIVERT_CMD_REG:
-			if (divert_if) 
-				return(DIVERT_REG_ERR);
-			i_div->ll_cmd = isdn_command; /* set command function */
-			i_div->drv_to_name = map_drvname; 
-			i_div->name_to_drv = map_namedrv; 
-			MOD_INC_USE_COUNT;
-			divert_if = i_div; /* remember interface */
-			return(DIVERT_NO_ERR);
-		default:
-			return(DIVERT_CMD_ERR);   
-	}
-}
+  if (i_div->if_magic != DIVERT_IF_MAGIC) 
+    return(DIVERT_VER_ERR);
+  switch (i_div->cmd)
+    {
+      case DIVERT_CMD_REL:
+        if (divert_if != i_div) 
+          return(DIVERT_REL_ERR);
+        divert_if = NULL; /* free interface */
+        return(DIVERT_NO_ERR);
+
+      case DIVERT_CMD_REG:
+        if (divert_if) 
+          return(DIVERT_REG_ERR);
+        i_div->ll_cmd = isdn_command; /* set command function */
+        i_div->drv_to_name = map_drvname; 
+        i_div->name_to_drv = map_namedrv; 
+        divert_if = i_div; /* remember interface */
+        return(DIVERT_NO_ERR);
+
+      default:
+        return(DIVERT_CMD_ERR);   
+    }
+} /* DIVERT_REG_NAME */
 
 EXPORT_SYMBOL(DIVERT_REG_NAME);
 
-#endif
+#endif /* CONFIG_ISDN_DIVERSION */
 
 
 EXPORT_SYMBOL(register_isdn);
@@ -2026,159 +2089,80 @@ EXPORT_SYMBOL(isdn_ppp_unregister_compre
 #endif
 
 int
-isdn_slot_maxbufsize(struct isdn_slot *slot)
-{
-	return slot->drv->maxbufsize;
-}
-
-int
-isdn_slot_hdrlen(struct isdn_slot *slot)
-{
-	return slot->drv->interface->hl_hdrlen;
-}
-
-char *
-isdn_slot_map_eaz2msn(struct isdn_slot *slot, char *msn)
-{
-	return isdn_map_eaz2msn(msn, slot->di);
-}
-
-int
-isdn_slot_command(struct isdn_slot *slot, int cmd, isdn_ctrl *ctrl)
+register_isdn(isdn_if * i)
 {
-	ctrl->command = cmd;
-	ctrl->driver = slot->di;
+	isdn_driver_t *d;
+	int j;
+	ulong flags;
+	int drvidx;
 
-	switch (cmd) {
-	case ISDN_CMD_SETL2:
-	case ISDN_CMD_SETL3:
-	case ISDN_CMD_PROT_IO:
-		ctrl->arg &= ~0xff; ctrl->arg |= slot->ch;
-		break;
-	case ISDN_CMD_DIAL:
-		if (isdndev->global_flags & ISDN_GLOBAL_STOPPED)
-			return -EBUSY;
-
-		/* fall through */
-	default:
-		ctrl->arg = slot->ch;
-		break;
-	}
-	switch (cmd) {
-	case ISDN_CMD_CLREAZ:
-		return fsm_event(&slot->fi, EV_CMD_CLREAZ, ctrl);
-	case ISDN_CMD_SETEAZ:
-		return fsm_event(&slot->fi, EV_CMD_SETEAZ, ctrl);
-	case ISDN_CMD_SETL2:
-		return fsm_event(&slot->fi, EV_CMD_SETL2, ctrl);
-	case ISDN_CMD_SETL3:
-		return fsm_event(&slot->fi, EV_CMD_SETL3, ctrl);
-	case ISDN_CMD_DIAL:
-		return fsm_event(&slot->fi, EV_CMD_DIAL, ctrl);
-	case ISDN_CMD_ACCEPTD:
-		return fsm_event(&slot->fi, EV_CMD_ACCEPTD, ctrl);
-	case ISDN_CMD_ACCEPTB:
-		return fsm_event(&slot->fi, EV_CMD_ACCEPTB, ctrl);
-	case ISDN_CMD_HANGUP:
-		return fsm_event(&slot->fi, EV_CMD_HANGUP, ctrl);
+	if (dev->drivers >= ISDN_MAX_DRIVERS) {
+		printk(KERN_WARNING "register_isdn: Max. %d drivers supported\n",
+		       ISDN_MAX_DRIVERS);
+		return 0;
 	}
-	HERE;
-	return -1;
-}
-
-int
-isdn_slot_dial(struct isdn_slot *slot, struct dial_info *dial)
-{
-	isdn_ctrl cmd;
-	int retval;
-	char *msn = isdn_slot_map_eaz2msn(slot, dial->msn);
-
-	/* check for DOV */
-	if (dial->si1 == 7 && tolower(dial->phone[0]) == 'v') { /* DOV call */
-		dial->si1 = 1;
-		dial->phone++; /* skip v/V */
+	if (!i->writebuf_skb) {
+		printk(KERN_WARNING "register_isdn: No write routine given.\n");
+		return 0;
 	}
+	if (!(d = kmalloc(sizeof(isdn_driver_t), GFP_KERNEL))) {
+		printk(KERN_WARNING "register_isdn: Could not alloc driver-struct\n");
+		return 0;
+	}
+	memset((char *) d, 0, sizeof(isdn_driver_t));
 
-	strcpy(slot->num, dial->phone);
-	slot->usage |= ISDN_USAGE_OUTGOING;
-	isdn_info_update();
-
-	retval = isdn_slot_command(slot, ISDN_CMD_CLREAZ, &cmd);
-	if (retval)
-		return retval;
-
-	strcpy(cmd.parm.num, msn);
-	retval = isdn_slot_command(slot, ISDN_CMD_SETEAZ, &cmd);
-
-	cmd.arg = dial->l2_proto << 8;
-	cmd.parm.fax = dial->fax;
-	retval = isdn_slot_command(slot, ISDN_CMD_SETL2, &cmd);
-	if (retval)
-		return retval;
-
-	cmd.arg = dial->l3_proto << 8;
-	retval = isdn_slot_command(slot, ISDN_CMD_SETL3, &cmd);
-	if (retval)
-		return retval;
-
-	cmd.parm.setup.si1 = dial->si1;
-	cmd.parm.setup.si2 = dial->si2;
-	strcpy(cmd.parm.setup.eazmsn, msn);
-	strcpy(cmd.parm.setup.phone, dial->phone);
-
-	printk(KERN_INFO "ISDN: Dialing %s -> %s (SI %d/%d) (B %d/%d)\n",
-	       cmd.parm.setup.eazmsn, cmd.parm.setup.phone,
-	       cmd.parm.setup.si1, cmd.parm.setup.si2,
-	       dial->l2_proto, dial->l3_proto);
-
-	return isdn_slot_command(slot, ISDN_CMD_DIAL, &cmd);
-}
-
-int
-isdn_hard_header_len(void)
-{
-	int drvidx;
-	int max = 0;
-	
-	for (drvidx = 0; drvidx < ISDN_MAX_DRIVERS; drvidx++) {
-		if (drivers[drvidx] && 
-		    max < drivers[drvidx]->interface->hl_hdrlen) {
-			max = drivers[drvidx]->interface->hl_hdrlen;
-		}
+	d->maxbufsize = i->maxbufsize;
+	d->pktcount = 0;
+	d->stavail = 0;
+	d->flags = DRV_FLAG_LOADED;
+	d->online = 0;
+	d->interface = i;
+	d->channels = 0;
+	spin_lock_irqsave(&dev->lock, flags);
+	for (drvidx = 0; drvidx < ISDN_MAX_DRIVERS; drvidx++)
+		if (!dev->drv[drvidx])
+			break;
+	if (isdn_add_channels(d, drvidx, i->channels, 0)) {
+		spin_unlock_irqrestore(&dev->lock, flags);
+		kfree(d);
+		return 0;
 	}
-	return max;
+	i->channels = drvidx;
+	i->rcvcallb_skb = isdn_receive_skb_callback;
+	i->statcallb = isdn_status_callback;
+	if (!strlen(i->id))
+		sprintf(i->id, "line%d", drvidx);
+	for (j = 0; j < drvidx; j++)
+		if (!strcmp(i->id, dev->drvid[j]))
+			sprintf(i->id, "line%d", drvidx);
+	dev->drv[drvidx] = d;
+	strcpy(dev->drvid[drvidx], i->id);
+	isdn_info_update();
+	dev->drivers++;
+	set_global_features();
+	spin_unlock_irqrestore(&dev->lock, flags);
+	return 1;
 }
 
-static void isdn_init_devfs(void)
-{
-	devfs_mk_dir("isdn");
+/*
+ *****************************************************************************
+ * And now the modules code.
+ *****************************************************************************
+ */
 
-#ifdef CONFIG_ISDN_PPP
+static char *
+isdn_getrev(const char *revision)
 {
-	int i;
-
-	for (i = 0; i < ISDN_MAX_CHANNELS; i++)
-		devfs_mk_cdev(MKDEV(ISDN_MAJOR, ISDN_MINOR_PPP + i),
-				0600 | S_IFCHR, "isdn/ippp%d", i);
-}
-#endif
-
-	devfs_mk_cdev(MKDEV(ISDN_MAJOR, ISDN_MINOR_STATUS),
-			0600 | S_IFCHR, "isdn/isdninfo");
-	devfs_mk_cdev(MKDEV(ISDN_MAJOR, ISDN_MINOR_CTRL),
-			0600 | S_IFCHR, "isdn/isdnctrl");
-}
+	char *rev;
+	char *p;
 
-static void isdn_cleanup_devfs(void)
-{
-#ifdef CONFIG_ISDN_PPP
-	int i;
-	for (i = 0; i < ISDN_MAX_CHANNELS; i++) 
-		devfs_remove("isdn/ippp%d", i);
-#endif
-	devfs_remove("isdn/isdninfo");
-	devfs_remove("isdn/isdnctrl");
-	devfs_remove("isdn");
+	if ((p = strchr(revision, ':'))) {
+		rev = p + 2;
+		p = strchr(rev, '$');
+		*--p = 0;
+	} else
+		rev = "???";
+	return rev;
 }
 
 /*
@@ -2186,64 +2170,72 @@ static void isdn_cleanup_devfs(void)
  */
 static int __init isdn_init(void)
 {
-	int retval;
-
-	retval = fsm_new(&slot_fsm);
-	if (retval)
-		goto err;
-
-	retval = fsm_new(&drv_fsm);
-	if (retval)
-		goto err_slot_fsm;
-
-	isdndev = vmalloc(sizeof(*isdndev));
-	if (!isdndev) {
-		retval = -ENOMEM;
-		goto err_drv_fsm;
-	}
-	memset(isdndev, 0, sizeof(*isdndev));
-	init_MUTEX(&isdndev->sem);
-	init_waitqueue_head(&isdndev->info_waitq);
+	int i;
+	char tmprev[50];
 
-	retval = register_chrdev(ISDN_MAJOR, "isdn", &isdn_fops);
-	if (retval) {
+	if (!(dev = (isdn_dev *) vmalloc(sizeof(isdn_dev)))) {
+		printk(KERN_WARNING "isdn: Could not allocate device-struct.\n");
+		return -EIO;
+	}
+	memset((char *) dev, 0, sizeof(isdn_dev));
+	init_timer(&dev->timer);
+	dev->timer.function = isdn_timer_funct;
+	spin_lock_init(&dev->lock);
+	spin_lock_init(&dev->timerlock);
+#ifdef MODULE
+	dev->owner = THIS_MODULE;
+#endif
+	init_MUTEX(&dev->sem);
+	init_waitqueue_head(&dev->info_waitq);
+	for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
+		dev->drvmap[i] = -1;
+		dev->chanmap[i] = -1;
+		dev->m_idx[i] = -1;
+		strcpy(dev->num[i], "???");
+		init_waitqueue_head(&dev->mdm.info[i].open_wait);
+		init_waitqueue_head(&dev->mdm.info[i].close_wait);
+	}
+	if (register_chrdev(ISDN_MAJOR, "isdn", &isdn_fops)) {
 		printk(KERN_WARNING "isdn: Could not register control devices\n");
-		goto err_vfree;
+		vfree(dev);
+		return -EIO;
 	}
-	isdn_init_devfs();
-	retval = isdn_tty_init();
-	if (retval < 0) {
+	if ((isdn_tty_modem_init()) < 0) {
 		printk(KERN_WARNING "isdn: Could not register tty devices\n");
-		goto err_cleanup_devfs;
+		vfree(dev);
+		unregister_chrdev(ISDN_MAJOR, "isdn");
+		return -EIO;
 	}
 #ifdef CONFIG_ISDN_PPP
-	retval = isdn_ppp_init();
-	if (retval < 0) {
+	if (isdn_ppp_init() < 0) {
 		printk(KERN_WARNING "isdn: Could not create PPP-device-structs\n");
-		goto err_tty_modem;
+		isdn_tty_exit();
+		unregister_chrdev(ISDN_MAJOR, "isdn");
+		vfree(dev);
+		return -EIO;
 	}
 #endif                          /* CONFIG_ISDN_PPP */
 
-	isdn_net_lib_init();
-	printk(KERN_NOTICE "ISDN subsystem initialized\n");
-	isdn_info_update();
-	return 0;
+	strcpy(tmprev, isdn_revision);
+	printk(KERN_NOTICE "ISDN subsystem Rev: %s/", isdn_getrev(tmprev));
+	strcpy(tmprev, isdn_tty_revision);
+	printk("%s/", isdn_getrev(tmprev));
+	strcpy(tmprev, isdn_net_revision);
+	printk("%s/", isdn_getrev(tmprev));
+	strcpy(tmprev, isdn_ppp_revision);
+	printk("%s/", isdn_getrev(tmprev));
+	strcpy(tmprev, isdn_audio_revision);
+	printk("%s/", isdn_getrev(tmprev));
+	strcpy(tmprev, isdn_v110_revision);
+	printk("%s", isdn_getrev(tmprev));
 
-#ifdef CONFIG_ISDN_PPP
- err_tty_modem:
-	isdn_tty_exit();
+#ifdef MODULE
+	printk(" loaded\n");
+#else
+	printk("\n");
 #endif
- err_cleanup_devfs:
-	isdn_cleanup_devfs();
-	unregister_chrdev(ISDN_MAJOR, "isdn");
- err_vfree:
-	vfree(isdndev);
- err_drv_fsm:
-	fsm_free(&drv_fsm);
- err_slot_fsm:
-	fsm_free(&slot_fsm);
- err:
-	return retval;
+	isdn_info_update();
+	return 0;
 }
 
 /*
@@ -2254,141 +2246,17 @@ static void __exit isdn_exit(void)
 #ifdef CONFIG_ISDN_PPP
 	isdn_ppp_cleanup();
 #endif
-	isdn_net_lib_exit();
-
+	if (isdn_net_rmall() < 0) {
+		printk(KERN_WARNING "isdn: net-device busy, remove cancelled\n");
+		return;
+	}
 	isdn_tty_exit();
 	unregister_chrdev(ISDN_MAJOR, "isdn");
-	isdn_cleanup_devfs();
-	vfree(isdndev);
-	fsm_free(&drv_fsm);
-	fsm_free(&slot_fsm);
+	del_timer(&dev->timer);
+	/* call vfree with interrupts enabled, else it will hang */
+	vfree(dev);
+	printk(KERN_NOTICE "ISDN-subsystem unloaded\n");
 }
 
 module_init(isdn_init);
 module_exit(isdn_exit);
-
-static void
-isdn_v110_add_features(struct isdn_driver *drv)
-{
-	unsigned long features = drv->features >> ISDN_FEATURE_L2_SHIFT;
-
-	if (features & ISDN_FEATURE_L2_TRANS)
-		drv->features |= (ISDN_FEATURE_L2_V11096|
-				  ISDN_FEATURE_L2_V11019|
-				  ISDN_FEATURE_L2_V11038) << 
-			ISDN_FEATURE_L2_SHIFT;
-}
-
-static void
-__isdn_v110_open(struct isdn_slot *slot)
-{
-	if (!slot->iv110.v110emu)
-		return;
-
-	isdn_v110_open(slot, &slot->iv110);
-}
-
-static void
-__isdn_v110_close(struct isdn_slot *slot)
-{
-	if (!slot->iv110.v110emu)
-		return;
-
-	isdn_v110_close(slot, &slot->iv110);
-}
-
-static void
-__isdn_v110_bsent(struct isdn_slot *slot, int pr, isdn_ctrl *c)
-{
-	if (!slot->iv110.v110emu) {
-		do_event_cb(slot, pr, c);
-		return;
-	}
-	isdn_v110_bsent(slot, &slot->iv110);
-}
-
-/*
- * Intercept command from Linklevel to Lowlevel.
- * If layer 2 protocol is V.110 and this is not supported by current
- * lowlevel-driver, use driver's transparent mode and handle V.110 in
- * linklevel instead.
- */
-static void
-isdn_v110_setl2(struct isdn_slot *slot, isdn_ctrl *cmd)
-{
-	struct isdn_driver *drv = slot->drv;
-
-	unsigned long l2prot = (cmd->arg >> 8) & 255;
-	unsigned long l2_feature = 1 << l2prot;
-	unsigned long features = drv->interface->features >> 
-		ISDN_FEATURE_L2_SHIFT;
-	
-	switch (l2prot) {
-	case ISDN_PROTO_L2_V11096:
-	case ISDN_PROTO_L2_V11019:
-	case ISDN_PROTO_L2_V11038:
-		/* If V.110 requested, but not supported by
-		 * HL-driver, set emulator-flag and change
-		 * Layer-2 to transparent
-		 */
-		if (!(features & l2_feature)) {
-			slot->iv110.v110emu = l2prot;
-			cmd->arg = (cmd->arg & 255) |
-				(ISDN_PROTO_L2_TRANS << 8);
-		} else
-			slot->iv110.v110emu = 0;
-	}
-}
-
-static int
-isdn_v110_data_ind(struct isdn_slot *slot, struct sk_buff *skb)
-{
-	if (!slot->iv110.v110emu)
-		goto recv;
-		
-	skb = isdn_v110_decode(slot->iv110.v110, skb);
-	if (!skb)
-		return 0;
-
-recv:
-	if (slot->event_cb)
-		slot->event_cb(slot, EV_DATA_IND, skb);
-	return 0;
-}
-
-static int
-isdn_v110_data_req(struct isdn_slot *slot, struct sk_buff *skb)
-{
-	int retval, v110_ret;
-	struct sk_buff *nskb = NULL;
-
-	if (!slot->iv110.v110emu)
-		return isdn_writebuf_skb(slot, skb);
-
-	atomic_inc(&slot->iv110.v110use);
-	nskb = isdn_v110_encode(slot->iv110.v110, skb);
-	atomic_dec(&slot->iv110.v110use);
-	if (!nskb)
-		return -ENOMEM;
-
-	v110_ret = *(int *)nskb->data;
-	skb_pull(nskb, sizeof(int));
-	if (!nskb->len) {
-		dev_kfree_skb(nskb);
-		return v110_ret;
-	}
-	
-	retval = isdn_writebuf_skb(slot, nskb);
-	if (retval <= 0) {
-		dev_kfree_skb(nskb);
-		return retval;
-	}
-	dev_kfree_skb(skb);
-
-	atomic_inc(&slot->iv110.v110use);
-	slot->iv110.v110->skbuser++;
-	atomic_dec(&slot->iv110.v110use);
-
-	/* For V.110 return unencoded data length */
-	return v110_ret;
-}
--- diff/drivers/isdn/i4l/isdn_common.h	2002-11-11 11:09:36.000000000 +0000
+++ source/drivers/isdn/i4l/isdn_common.h	2004-02-23 13:56:42.000000000 +0000
@@ -1,4 +1,7 @@
-/* Linux ISDN subsystem, common used functions and debugging-switches
+/* $Id: isdn_common.h,v 1.1.2.2 2004/01/12 22:37:19 keil Exp $
+ *
+ * header for Linux ISDN subsystem
+ * common used functions and debugging-switches (linklevel).
  *
  * Copyright 1994-1999  by Fritz Elfert (fritz@isdn4linux.de)
  * Copyright 1995,96    by Thinking Objects Software GmbH Wuerzburg
@@ -9,9 +12,6 @@
  *
  */
 
-#include <linux/isdn.h>
-#include "isdn_v110.h"
-
 #undef  ISDN_DEBUG_MODEM_OPEN
 #undef  ISDN_DEBUG_MODEM_IOCTL
 #undef  ISDN_DEBUG_MODEM_WAITSENT
@@ -21,129 +21,27 @@
 #undef  ISDN_DEBUG_MODEM_VOICE
 #undef  ISDN_DEBUG_AT
 #undef  ISDN_DEBUG_NET_DUMP
-#define  ISDN_DEBUG_NET_DIAL
-#define  ISDN_DEBUG_NET_ICALL
-#define  ISDN_DEBUG_STATCALLB
-#define  ISDN_DEBUG_COMMAND
-
-#ifdef ISDN_DEBUG_NET_DIAL
-#define dbg_net_dial(arg...) printk(KERN_DEBUG arg)
-#else
-#define dbg_net_dial(arg...) do {} while (0)
-#endif
-
-#ifdef ISDN_DEBUG_NET_ICALL
-#define dbg_net_icall(arg...) printk(KERN_DEBUG arg)
-#else
-#define dbg_net_icall(arg...) do {} while (0)
-#endif
-
-#ifdef ISDN_DEBUG_STATCALLB
-#define dbg_statcallb(arg...) printk(KERN_DEBUG arg)
-#else
-#define dbg_statcallb(arg...) do {} while (0)
-#endif
-
-#define isdn_BUG() \
-do { printk(KERN_WARNING "ISDN BUG at %s:%d\n", __FILE__, __LINE__); \
-} while(0)
-
-#define HERE printk("%s:%d (%s)\n", __FILE__, __LINE__, __FUNCTION__)
-
-extern struct list_head isdn_net_devs;
+#undef  ISDN_DEBUG_NET_DIAL
+#undef  ISDN_DEBUG_NET_ICALL
 
 /* Prototypes */
-extern void isdn_MOD_INC_USE_COUNT(void);
-extern void isdn_MOD_DEC_USE_COUNT(void);
 extern void isdn_lock_drivers(void);
 extern void isdn_unlock_drivers(void);
+extern void isdn_free_channel(int di, int ch, int usage);
+extern void isdn_all_eaz(int di, int ch);
+extern int  isdn_command(isdn_ctrl *);
+extern int  isdn_dc2minor(int di, int ch);
 extern void isdn_info_update(void);
 extern char *isdn_map_eaz2msn(char *msn, int di);
-extern int isdn_getnum(char **);
-extern int isdn_msncmp( const char *,  const char *);
+extern void isdn_timer_ctrl(int tf, int onoff);
+extern void isdn_unexclusive_channel(int di, int ch);
+extern int  isdn_getnum(char **);
+extern int  isdn_readbchan(int, int, u_char *, u_char *, int, wait_queue_head_t *);
+extern int  isdn_get_free_channel(int, int, int, int, int, char *);
+extern int  isdn_writebuf_skb_stub(int, int, int, struct sk_buff *);
+extern int  register_isdn(isdn_if * i);
+extern int  isdn_msncmp( const char *,  const char *);
+extern int  isdn_add_channels(isdn_driver_t *, int, int, int);
 #if defined(ISDN_DEBUG_NET_DUMP) || defined(ISDN_DEBUG_MODEM_DUMP)
 extern void isdn_dumppkt(char *, u_char *, int, int);
-#else
-static inline void isdn_dumppkt(char *s, u_char *d, int l, int m) { }
 #endif
-
-struct isdn_slot {
-	int               di;                  /* driver index               */
-	struct isdn_driver *drv;               /* driver                     */
-	int               ch;                  /* channel index (per driver) */
-	int               usage;               /* how is it used             */
-	char              num[ISDN_MSNLEN];    /* the current phone number   */
-	unsigned long     ibytes;              /* Statistics incoming bytes  */
-	unsigned long     obytes;              /* Statistics outgoing bytes  */
-	struct isdn_v110  iv110;               /* For V.110                  */
-	void             *priv;                /* pointer to isdn_net_dev    */
-	int             (*event_cb)(struct isdn_slot *, int pr, void *arg);
-	struct fsm_inst   fi;
-};
-
-struct dial_info {
-	int            l2_proto;
-	int            l3_proto;
-	struct T30_s  *fax;
-	unsigned char  si1;
-	unsigned char  si2;
-	unsigned char *msn;
-	unsigned char *phone;
-};
-
-struct isdn_slot *isdn_get_free_slot(int, int, int, int, int, char *);
-void  isdn_slot_free(struct isdn_slot *);
-int   isdn_slot_command(struct isdn_slot *, int cmd, isdn_ctrl *);
-int   isdn_slot_dial(struct isdn_slot *, struct dial_info *dial);
-char *isdn_slot_map_eaz2msn(struct isdn_slot *, char *msn);
-int   isdn_slot_write(struct isdn_slot *, struct sk_buff *);
-int   isdn_slot_hdrlen(struct isdn_slot *);
-int   isdn_slot_maxbufsize(struct isdn_slot *);
-int   isdn_hard_header_len(void);
-
-int   isdn_drv_lookup(char *drvid);
-char *isdn_drv_drvid(int di);
-
-enum {
-	ST_SLOT_NULL,
-	ST_SLOT_BOUND,
-	ST_SLOT_IN,
-	ST_SLOT_WAIT_DCONN,
-	ST_SLOT_DCONN,
-	ST_SLOT_WAIT_BCONN,
-	ST_SLOT_ACTIVE,
-	ST_SLOT_WAIT_BHUP,
-	ST_SLOT_WAIT_DHUP,
-};
-
-enum {
-	EV_DRV_REGISTER,
-	EV_STAT_RUN,
-	EV_STAT_STOP,
-	EV_STAT_UNLOAD,
-	EV_STAT_STAVAIL,
-	EV_STAT_ADDCH,
-	EV_STAT_ICALL,
-	EV_STAT_DCONN,
-	EV_STAT_BCONN,
-	EV_STAT_BHUP,
-	EV_STAT_DHUP,
-	EV_STAT_BSENT,
-	EV_STAT_CINF,
-	EV_STAT_CAUSE,
-	EV_STAT_DISPLAY,
-	EV_STAT_FAXIND,
-	EV_STAT_AUDIO,
-	EV_CMD_CLREAZ,
-	EV_CMD_SETEAZ,
-	EV_CMD_SETL2,
-	EV_CMD_SETL3,
-	EV_CMD_DIAL,
-	EV_CMD_ACCEPTD,
-	EV_CMD_ACCEPTB,
-	EV_CMD_HANGUP,
-	EV_DATA_REQ,
-	EV_DATA_IND,
-	EV_SLOT_BIND,
-	EV_SLOT_UNBIND,
-};
--- diff/drivers/isdn/i4l/isdn_concap.c	2002-11-11 11:09:36.000000000 +0000
+++ source/drivers/isdn/i4l/isdn_concap.c	2004-02-23 13:56:42.000000000 +0000
@@ -1,12 +1,16 @@
-/* Linux ISDN subsystem, protocol encapsulation
+/* $Id: isdn_concap.c,v 1.1.2.2 2004/01/12 22:37:19 keil Exp $
+ * 
+ * Linux ISDN subsystem, protocol encapsulation
  *
  * This software may be used and distributed according to the terms
  * of the GNU General Public License, incorporated herein by reference.
+ *
  */
 
 /* Stuff to support the concap_proto by isdn4linux. isdn4linux - specific
  * stuff goes here. Stuff that depends only on the concap protocol goes to
  * another -- protocol specific -- source file.
+ *
  */
 
 
@@ -15,7 +19,7 @@
 #include "isdn_net.h"
 #include <linux/concap.h>
 #include "isdn_concap.h"
-#include <linux/if_arp.h>
+
 
 /* The following set of device service operations are for encapsulation
    protocols that require for reliable datalink semantics. That means:
@@ -35,8 +39,7 @@
    */
 
 
-static int
-isdn_concap_dl_data_req(struct concap_proto *concap, struct sk_buff *skb)
+int isdn_concap_dl_data_req(struct concap_proto *concap, struct sk_buff *skb)
 {
 	struct net_device *ndev = concap -> net_dev;
 	isdn_net_dev *nd = ((isdn_net_local *) ndev->priv)->netdev;
@@ -55,8 +58,7 @@ isdn_concap_dl_data_req(struct concap_pr
 }
 
 
-static int
-isdn_concap_dl_connect_req(struct concap_proto *concap)
+int isdn_concap_dl_connect_req(struct concap_proto *concap)
 {
 	struct net_device *ndev = concap -> net_dev;
 	isdn_net_local *lp = (isdn_net_local *) ndev->priv;
@@ -69,8 +71,7 @@ isdn_concap_dl_connect_req(struct concap
 	return ret;
 }
 
-static int
-isdn_concap_dl_disconn_req(struct concap_proto *concap)
+int isdn_concap_dl_disconn_req(struct concap_proto *concap)
 {
 	IX25DEBUG( "isdn_concap_dl_disconn_req: %s \n", concap -> net_dev -> name);
 
@@ -97,8 +98,7 @@ struct concap_device_ops isdn_concap_dem
    this sourcefile does not need to include any protocol specific header
    files. For now:
    */
-struct concap_proto *
-isdn_concap_new( int encap )
+struct concap_proto * isdn_concap_new( int encap )
 {
 	switch ( encap ) {
 	case ISDN_NET_ENCAP_X25IFACE:
@@ -106,146 +106,3 @@ isdn_concap_new( int encap )
 	}
 	return NULL;
 }
-
-static int
-isdn_x25_open(isdn_net_local *lp)
-{
-	struct net_device * dev = & lp -> netdev -> dev;
-	struct concap_proto * cprot = lp -> netdev -> ind_priv;
-	struct concap_proto * dops = lp -> inl_priv;
-	unsigned long flags;
-
-	save_flags(flags);
-	cli();                  /* Avoid glitch on writes to CMD regs */
-	if( cprot -> pops && dops )
-		cprot -> pops -> restart ( cprot, dev, dops );
-	restore_flags(flags);
-	return 0;
-}
-
-static void
-isdn_x25_close(isdn_net_local *lp)
-{
-	struct concap_proto * cprot = lp -> netdev -> ind_priv;
-
-	if( cprot && cprot -> pops ) cprot -> pops -> close( cprot );
-}
-
-static void
-isdn_x25_connected(isdn_net_local *lp)
-{
-	struct concap_proto *cprot = lp -> netdev -> ind_priv;
-	struct concap_proto_ops *pops = cprot ? cprot -> pops : 0;
-
-	/* try if there are generic concap receiver routines */
-	if( pops )
-		if( pops->connect_ind)
-			pops->connect_ind(cprot);
-
-	isdn_net_device_wake_queue(lp);
-}
-
-static void
-isdn_x25_disconnected(isdn_net_local *lp)
-{
-	struct concap_proto *cprot = lp -> netdev -> ind_priv;
-	struct concap_proto_ops *pops = cprot ? cprot -> pops : 0;
-
-	/* try if there are generic encap protocol
-	   receiver routines and signal the closure of
-	   the link */
-	if( pops  &&  pops -> disconn_ind )
-		pops -> disconn_ind(cprot);
-}
-
-static int
-isdn_x25_start_xmit(struct sk_buff *skb, struct net_device *dev)
-{
-/* At this point hard_start_xmit() passes control to the encapsulation
-   protocol (if present).
-   For X.25 auto-dialing is completly bypassed because:
-   - It does not conform with the semantics of a reliable datalink
-     service as needed by X.25 PLP.
-   - I don't want that the interface starts dialing when the network layer
-     sends a message which requests to disconnect the lapb link (or if it
-     sends any other message not resulting in data transmission).
-   Instead, dialing will be initiated by the encapsulation protocol entity
-   when a dl_establish request is received from the upper layer.
-*/
-	isdn_net_local *lp = (isdn_net_local *) dev->priv;
-	struct concap_proto * cprot = lp -> netdev -> ind_priv;
-	int ret = cprot -> pops -> encap_and_xmit ( cprot , skb);
-
-	if (ret)
-		netif_stop_queue(dev);
-		
-	return ret;
-}
-
-static void 
-isdn_x25_receive(isdn_net_dev *p, isdn_net_local *olp, struct sk_buff *skb)
-{
-	isdn_net_local *lp = &p->local;
-	struct concap_proto *cprot = lp -> netdev -> ind_priv;
-
-	/* try if there are generic sync_device receiver routines */
-	if(cprot) 
-		if(cprot -> pops)
-			if( cprot -> pops -> data_ind) {
-				cprot -> pops -> data_ind(cprot,skb);
-				return;
-			}
-}
-
-static void
-isdn_x25_init(struct net_device *dev)
-{
-	unsigned long flags;
-
-	isdn_net_local *lp = dev->priv;
-
-	/* ... ,  prepare for configuration of new one ... */
-	switch ( lp->p_encap ){
-	case ISDN_NET_ENCAP_X25IFACE:
-		lp -> inl_priv = &isdn_concap_reliable_dl_dops;
-	}
-	/* ... and allocate new one ... */
-	p -> cprot = isdn_concap_new( cfg -> p_encap );
-	/* p -> cprot == NULL now if p_encap is not supported
-	   by means of the concap_proto mechanism */
-	if (!p->cprot)
-		return -EINVAL;
-
-	return 0;
-}
-
-static void
-isdn_x25_cleanup(isdn_net_dev *p)
-{
-	isdn_net_local *lp = &p->local;
-	struct concap_proto * cprot = p -> cprot;
-	unsigned long flags;
-	
-	/* delete old encapsulation protocol if present ... */
-	save_flags(flags);
-	cli(); /* avoid races with incoming events trying to
-		  call cprot->pops methods */
-	if( cprot && cprot -> pops )
-		cprot -> pops -> proto_del ( cprot );
-	p -> cprot = NULL;
-	lp -> inl_priv = NULL;
-	restore_flags(flags);
-}
-
-struct isdn_netif_ops isdn_x25_ops = {
-	.hard_start_xmit     = isdn_x25_start_xmit,
-	.flags               = IFF_NOARP | IFF_POINTOPOINT,
-	.type                = ARPHRD_X25,
-	.receive             = isdn_x25_receive,
-	.connected           = isdn_x25_connected,
-	.disconnected        = isdn_x25_disconnected,
-	.init                = isdn_x25_init,
-	.cleanup             = isdn_x25_cleanup,
-	.open                = isdn_x25_open,
-	.close               = isdn_x25_close,
-};
--- diff/drivers/isdn/i4l/isdn_concap.h	2002-11-11 11:09:36.000000000 +0000
+++ source/drivers/isdn/i4l/isdn_concap.h	2004-02-23 13:56:42.000000000 +0000
@@ -1,12 +1,14 @@
-/* Linux ISDN subsystem, protocol encapsulation
+/* $Id: isdn_concap.h,v 1.1.2.2 2004/01/12 22:37:19 keil Exp $
+ *
+ * Linux ISDN subsystem, protocol encapsulation
  *
  * This software may be used and distributed according to the terms
  * of the GNU General Public License, incorporated herein by reference.
+ *
  */
 
 extern struct concap_device_ops isdn_concap_reliable_dl_dops;
 extern struct concap_device_ops isdn_concap_demand_dial_dops;
+extern struct concap_proto * isdn_concap_new( int );
 
-struct concap_proto *isdn_concap_new(int);
 
-extern struct isdn_netif_ops isdn_x25_ops;
--- diff/drivers/isdn/i4l/isdn_net.c	2002-11-11 11:09:36.000000000 +0000
+++ source/drivers/isdn/i4l/isdn_net.c	2004-02-23 13:56:42.000000000 +0000
@@ -1,150 +1,3223 @@
-/* Linux ISDN subsystem, network interfaces and related functions (linklevel).
+/* $Id: isdn_net.c,v 1.1.2.2 2004/01/12 22:37:19 keil Exp $
+ *
+ * Linux ISDN subsystem, network interfaces and related functions (linklevel).
  *
  * Copyright 1994-1998  by Fritz Elfert (fritz@isdn4linux.de)
- *           1995,96    by Thinking Objects Software GmbH Wuerzburg
- *           1995,96    by Michael Hipp (Michael.Hipp@student.uni-tuebingen.de)
- *           1999-2002  by Kai Germaschewski <kai@germaschewski.name>
+ * Copyright 1995,96    by Thinking Objects Software GmbH Wuerzburg
+ * Copyright 1995,96    by Michael Hipp (Michael.Hipp@student.uni-tuebingen.de)
  *
  * This software may be used and distributed according to the terms
  * of the GNU General Public License, incorporated herein by reference.
+ *
+ * Data Over Voice (DOV) support added - Guy Ellis 23-Mar-02 
+ *                                       guy@traverse.com.au
+ * Outgoing calls - looks for a 'V' in first char of dialed number
+ * Incoming calls - checks first character of eaz as follows:
+ *   Numeric - accept DATA only - original functionality
+ *   'V'     - accept VOICE (DOV) only
+ *   'B'     - accept BOTH DATA and DOV types
+ *
+ * Jan 2001: fix CISCO HDLC      Bjoern A. Zeeb <i4l@zabbadoz.net>
+ *           for info on the protocol, see 
+ *           http://i4l.zabbadoz.net/i4l/cisco-hdlc.txt
  */
 
+#include <linux/config.h>
 #include <linux/isdn.h>
-#include <linux/inetdevice.h>
 #include <net/arp.h>
+#include <net/dst.h>
+#include <net/pkt_sched.h>
+#include <linux/inetdevice.h>
 #include "isdn_common.h"
-#include "isdn_net_lib.h"
 #include "isdn_net.h"
+#ifdef CONFIG_ISDN_PPP
+#include "isdn_ppp.h"
+#endif
+#ifdef CONFIG_ISDN_X25
+#include <linux/concap.h>
+#include "isdn_concap.h"
+#endif
+
+
+/*
+ * Outline of new tbusy handling: 
+ *
+ * Old method, roughly spoken, consisted of setting tbusy when entering
+ * isdn_net_start_xmit() and at several other locations and clearing
+ * it from isdn_net_start_xmit() thread when sending was successful.
+ *
+ * With 2.3.x multithreaded network core, to prevent problems, tbusy should
+ * only be set by the isdn_net_start_xmit() thread and only when a tx-busy
+ * condition is detected. Other threads (in particular isdn_net_stat_callb())
+ * are only allowed to clear tbusy.
+ *
+ * -HE
+ */
+
+/*
+ * About SOFTNET:
+ * Most of the changes were pretty obvious and basically done by HE already.
+ *
+ * One problem of the isdn net device code is that is uses struct net_device
+ * for masters and slaves. However, only master interface are registered to 
+ * the network layer, and therefore, it only makes sense to call netif_* 
+ * functions on them.
+ *
+ * --KG
+ */
+
+/* 
+ * Find out if the netdevice has been ifup-ed yet.
+ * For slaves, look at the corresponding master.
+ */
+static __inline__ int isdn_net_device_started(isdn_net_dev *n)
+{
+	isdn_net_local *lp = n->local;
+	struct net_device *dev;
+	
+	if (lp->master) 
+		dev = lp->master;
+	else
+		dev = &n->dev;
+	return netif_running(dev);
+}
+
+/*
+ * wake up the network -> net_device queue.
+ * For slaves, wake the corresponding master interface.
+ */
+static __inline__ void isdn_net_device_wake_queue(isdn_net_local *lp)
+{
+	if (lp->master) 
+		netif_wake_queue(lp->master);
+	else
+		netif_wake_queue(&lp->netdev->dev);
+}
+
+/*
+ * stop the network -> net_device queue.
+ * For slaves, stop the corresponding master interface.
+ */
+static __inline__ void isdn_net_device_stop_queue(isdn_net_local *lp)
+{
+	if (lp->master)
+		netif_stop_queue(lp->master);
+	else
+		netif_stop_queue(&lp->netdev->dev);
+}
+
+/*
+ * find out if the net_device which this lp belongs to (lp can be
+ * master or slave) is busy. It's busy iff all (master and slave) 
+ * queues are busy
+ */
+static __inline__ int isdn_net_device_busy(isdn_net_local *lp)
+{
+	isdn_net_local *nlp;
+	isdn_net_dev *nd;
+	unsigned long flags;
+
+	if (!isdn_net_lp_busy(lp))
+		return 0;
+
+	if (lp->master)
+		nd = ((isdn_net_local *) lp->master->priv)->netdev;
+	else
+		nd = lp->netdev;
+	
+	spin_lock_irqsave(&nd->queue_lock, flags);
+	nlp = lp->next;
+	while (nlp != lp) {
+		if (!isdn_net_lp_busy(nlp)) {
+			spin_unlock_irqrestore(&nd->queue_lock, flags);
+			return 0;
+		}
+		nlp = nlp->next;
+	}
+	spin_unlock_irqrestore(&nd->queue_lock, flags);
+	return 1;
+}
+
+static __inline__ void isdn_net_inc_frame_cnt(isdn_net_local *lp)
+{
+	atomic_inc(&lp->frame_cnt);
+	if (isdn_net_device_busy(lp))
+		isdn_net_device_stop_queue(lp);
+}
+
+static __inline__ void isdn_net_dec_frame_cnt(isdn_net_local *lp)
+{
+	atomic_dec(&lp->frame_cnt);
+
+	if (!(isdn_net_device_busy(lp))) {
+		if (!skb_queue_empty(&lp->super_tx_queue)) {
+			schedule_work(&lp->tqueue);
+		} else {
+			isdn_net_device_wake_queue(lp);
+		}
+       }                                                                      
+}
+
+static __inline__ void isdn_net_zero_frame_cnt(isdn_net_local *lp)
+{
+	atomic_set(&lp->frame_cnt, 0);
+}
+
+/* For 2.2.x we leave the transmitter busy timeout at 2 secs, just 
+ * to be safe.
+ * For 2.3.x we push it up to 20 secs, because call establishment
+ * (in particular callback) may take such a long time, and we 
+ * don't want confusing messages in the log. However, there is a slight
+ * possibility that this large timeout will break other things like MPPP,
+ * which might rely on the tx timeout. If so, we'll find out this way...
+ */
+
+#define ISDN_NET_TX_TIMEOUT (20*HZ) 
+
+/* Prototypes */
+
+int isdn_net_force_dial_lp(isdn_net_local *);
+static int isdn_net_start_xmit(struct sk_buff *, struct net_device *);
+
+static void isdn_net_ciscohdlck_connected(isdn_net_local *lp);
+static void isdn_net_ciscohdlck_disconnected(isdn_net_local *lp);
+
+char *isdn_net_revision = "$Revision: 1.1.2.2 $";
 
-// ISDN_NET_ENCAP_IPTYP
-// ethernet type field
-// ======================================================================
+ /*
+  * Code for raw-networking over ISDN
+  */
 
+static void
+isdn_net_unreachable(struct net_device *dev, struct sk_buff *skb, char *reason)
+{
+	if(skb) {
+
+		u_short proto = ntohs(skb->protocol);
+
+		printk(KERN_DEBUG "isdn_net: %s: %s, signalling dst_link_failure %s\n",
+		       dev->name,
+		       (reason != NULL) ? reason : "unknown",
+		       (proto != ETH_P_IP) ? "Protocol != ETH_P_IP" : "");
+		
+		dst_link_failure(skb);
+	}
+	else {  /* dial not triggered by rawIP packet */
+		printk(KERN_DEBUG "isdn_net: %s: %s\n",
+			   dev->name,
+			   (reason != NULL) ? reason : "reason unknown");
+	}
+}
+
+static void
+isdn_net_reset(struct net_device *dev)
+{
+#ifdef CONFIG_ISDN_X25
+	struct concap_device_ops * dops =
+		( (isdn_net_local *) dev->priv ) -> dops;
+	struct concap_proto * cprot =
+		( (isdn_net_local *) dev->priv ) -> netdev -> cprot;
+#endif
+#ifdef CONFIG_ISDN_X25
+	if( cprot && cprot -> pops && dops )
+		cprot -> pops -> restart ( cprot, dev, dops );
+#endif
+}
+
+/* Open/initialize the board. */
 static int
-isdn_iptyp_header(struct sk_buff *skb, struct net_device *dev,
-		   unsigned short type, void *daddr, void *saddr, 
-		   unsigned plen)
+isdn_net_open(struct net_device *dev)
+{
+	int i;
+	struct net_device *p;
+	struct in_device *in_dev;
+
+	/* moved here from isdn_net_reset, because only the master has an
+	   interface associated which is supposed to be started. BTW:
+	   we need to call netif_start_queue, not netif_wake_queue here */
+	netif_start_queue(dev);
+
+	isdn_net_reset(dev);
+	/* Fill in the MAC-level header (not needed, but for compatibility... */
+	for (i = 0; i < ETH_ALEN - sizeof(u32); i++)
+		dev->dev_addr[i] = 0xfc;
+	if ((in_dev = dev->ip_ptr) != NULL) {
+		/*
+		 *      Any address will do - we take the first
+		 */
+		struct in_ifaddr *ifa = in_dev->ifa_list;
+		if (ifa != NULL)
+			memcpy(dev->dev_addr+2, &ifa->ifa_local, 4);
+	}
+
+	/* If this interface has slaves, start them also */
+
+	if ((p = (((isdn_net_local *) dev->priv)->slave))) {
+		while (p) {
+			isdn_net_reset(p);
+			p = (((isdn_net_local *) p->priv)->slave);
+		}
+	}
+	isdn_lock_drivers();
+	return 0;
+}
+
+/*
+ * Assign an ISDN-channel to a net-interface
+ */
+static void
+isdn_net_bind_channel(isdn_net_local * lp, int idx)
 {
-	put_u16(skb_push(skb, 2), type);
-	return 2;
+	lp->flags |= ISDN_NET_CONNECTED;
+	lp->isdn_device = dev->drvmap[idx];
+	lp->isdn_channel = dev->chanmap[idx];
+	dev->rx_netdev[idx] = lp->netdev;
+	dev->st_netdev[idx] = lp->netdev;
 }
 
+/*
+ * unbind a net-interface (resets interface after an error)
+ */
 static void
-isdn_iptyp_receive(isdn_net_local *lp, isdn_net_dev *idev, 
-		   struct sk_buff *skb)
+isdn_net_unbind_channel(isdn_net_local * lp)
+{
+	skb_queue_purge(&lp->super_tx_queue);
+
+	if (!lp->master) {	/* reset only master device */
+		/* Moral equivalent of dev_purge_queues():
+		   BEWARE! This chunk of code cannot be called from hardware
+		   interrupt handler. I hope it is true. --ANK
+		 */
+		qdisc_reset(lp->netdev->dev.qdisc);
+	}
+	lp->dialstate = 0;
+	dev->rx_netdev[isdn_dc2minor(lp->isdn_device, lp->isdn_channel)] = NULL;
+	dev->st_netdev[isdn_dc2minor(lp->isdn_device, lp->isdn_channel)] = NULL;
+	isdn_free_channel(lp->isdn_device, lp->isdn_channel, ISDN_USAGE_NET);
+	lp->flags &= ~ISDN_NET_CONNECTED;
+	lp->isdn_device = -1;
+	lp->isdn_channel = -1;
+}
+
+/*
+ * Perform auto-hangup and cps-calculation for net-interfaces.
+ *
+ * auto-hangup:
+ * Increment idle-counter (this counter is reset on any incoming or
+ * outgoing packet), if counter exceeds configured limit either do a
+ * hangup immediately or - if configured - wait until just before the next
+ * charge-info.
+ *
+ * cps-calculation (needed for dynamic channel-bundling):
+ * Since this function is called every second, simply reset the
+ * byte-counter of the interface after copying it to the cps-variable.
+ */
+unsigned long last_jiffies = -HZ;
+
+void
+isdn_net_autohup()
 {
-	u16 protocol;
+	isdn_net_dev *p = dev->netdev;
+	int anymore;
+
+	anymore = 0;
+	while (p) {
+		isdn_net_local *l = p->local;
+		if (jiffies == last_jiffies)
+			l->cps = l->transcount;
+		else
+			l->cps = (l->transcount * HZ) / (jiffies - last_jiffies);
+		l->transcount = 0;
+		if (dev->net_verbose > 3)
+			printk(KERN_DEBUG "%s: %d bogocps\n", l->name, l->cps);
+		if ((l->flags & ISDN_NET_CONNECTED) && (!l->dialstate)) {
+			anymore = 1;
+			l->huptimer++;
+			/*
+			 * if there is some dialmode where timeout-hangup
+			 * should _not_ be done, check for that here
+			 */
+			if ((l->onhtime) &&
+			    (l->huptimer > l->onhtime))
+			{
+				if (l->hupflags & ISDN_MANCHARGE &&
+				    l->hupflags & ISDN_CHARGEHUP) {
+					while (time_after(jiffies, l->chargetime + l->chargeint))
+						l->chargetime += l->chargeint;
+					if (time_after(jiffies, l->chargetime + l->chargeint - 2 * HZ))
+						if (l->outgoing || l->hupflags & ISDN_INHUP)
+							isdn_net_hangup(&p->dev);
+				} else if (l->outgoing) {
+					if (l->hupflags & ISDN_CHARGEHUP) {
+						if (l->hupflags & ISDN_WAITCHARGE) {
+							printk(KERN_DEBUG "isdn_net: Hupflags of %s are %X\n",
+							       l->name, l->hupflags);
+							isdn_net_hangup(&p->dev);
+						} else if (time_after(jiffies, l->chargetime + l->chargeint)) {
+							printk(KERN_DEBUG
+							       "isdn_net: %s: chtime = %lu, chint = %d\n",
+							       l->name, l->chargetime, l->chargeint);
+							isdn_net_hangup(&p->dev);
+						}
+					} else
+						isdn_net_hangup(&p->dev);
+				} else if (l->hupflags & ISDN_INHUP)
+					isdn_net_hangup(&p->dev);
+			}
+
+			if(dev->global_flags & ISDN_GLOBAL_STOPPED || (ISDN_NET_DIALMODE(*l) == ISDN_NET_DM_OFF)) {
+				isdn_net_hangup(&p->dev);
+				break;
+			}
+		}
+		p = (isdn_net_dev *) p->next;
+	}
+	last_jiffies = jiffies;
+	isdn_timer_ctrl(ISDN_TIMER_NETHANGUP, anymore);
+}
 
-	get_u16(skb->data, &protocol);
-	skb_pull(skb, 2);
-	isdn_netif_rx(idev, skb, protocol);
+static void isdn_net_lp_disconnected(isdn_net_local *lp)
+{
+	isdn_net_rm_from_bundle(lp);
 }
 
-struct isdn_netif_ops isdn_iptyp_ops = {
-	.hard_start_xmit     = isdn_net_start_xmit,
-	.hard_header         = isdn_iptyp_header,
-	.flags               = IFF_NOARP | IFF_POINTOPOINT,
-	.type                = ARPHRD_PPP,
-	.addr_len            = 2,
-	.receive             = isdn_iptyp_receive,
-};
+/*
+ * Handle status-messages from ISDN-interfacecard.
+ * This function is called from within the main-status-dispatcher
+ * isdn_status_callback, which itself is called from the low-level driver.
+ * Return: 1 = Event handled, 0 = not for us or unknown Event.
+ */
+int
+isdn_net_stat_callback(int idx, isdn_ctrl *c)
+{
+	isdn_net_dev *p = dev->st_netdev[idx];
+	int cmd = c->command;
 
-// ISDN_NET_ENCAP_UIHDLC
-// HDLC with UI-Frames (for ispa with -h1 option) */
-// ======================================================================
+	if (p) {
+		isdn_net_local *lp = p->local;
+#ifdef CONFIG_ISDN_X25
+		struct concap_proto *cprot = lp -> netdev -> cprot;
+		struct concap_proto_ops *pops = cprot ? cprot -> pops : 0;
+#endif
+		switch (cmd) {
+			case ISDN_STAT_BSENT:
+				/* A packet has successfully been sent out */
+				if ((lp->flags & ISDN_NET_CONNECTED) &&
+				    (!lp->dialstate)) {
+					isdn_net_dec_frame_cnt(lp);
+					lp->stats.tx_packets++;
+					lp->stats.tx_bytes += c->parm.length;
+				}
+				return 1;
+			case ISDN_STAT_DCONN:
+				/* D-Channel is up */
+				switch (lp->dialstate) {
+					case 4:
+					case 7:
+					case 8:
+						lp->dialstate++;
+						return 1;
+					case 12:
+						lp->dialstate = 5;
+						return 1;
+				}
+				break;
+			case ISDN_STAT_DHUP:
+				/* Either D-Channel-hangup or error during dialout */
+#ifdef CONFIG_ISDN_X25
+				/* If we are not connencted then dialing had
+				   failed. If there are generic encap protocol
+				   receiver routines signal the closure of
+				   the link*/
+
+				if( !(lp->flags & ISDN_NET_CONNECTED)
+				    && pops && pops -> disconn_ind )
+					pops -> disconn_ind(cprot);
+#endif /* CONFIG_ISDN_X25 */
+				if ((!lp->dialstate) && (lp->flags & ISDN_NET_CONNECTED)) {
+					if (lp->p_encap == ISDN_NET_ENCAP_CISCOHDLCK)
+						isdn_net_ciscohdlck_disconnected(lp);
+#ifdef CONFIG_ISDN_PPP
+					if (lp->p_encap == ISDN_NET_ENCAP_SYNCPPP)
+						isdn_ppp_free(lp);
+#endif
+					isdn_net_lp_disconnected(lp);
+					isdn_all_eaz(lp->isdn_device, lp->isdn_channel);
+					printk(KERN_INFO "%s: remote hangup\n", lp->name);
+					printk(KERN_INFO "%s: Chargesum is %d\n", lp->name,
+					       lp->charge);
+					isdn_net_unbind_channel(lp);
+					return 1;
+				}
+				break;
+#ifdef CONFIG_ISDN_X25
+			case ISDN_STAT_BHUP:
+				/* B-Channel-hangup */
+				/* try if there are generic encap protocol
+				   receiver routines and signal the closure of
+				   the link */
+				if( pops  &&  pops -> disconn_ind ){
+						pops -> disconn_ind(cprot);
+						return 1;
+					}
+				break;
+#endif /* CONFIG_ISDN_X25 */
+			case ISDN_STAT_BCONN:
+				/* B-Channel is up */
+				isdn_net_zero_frame_cnt(lp);
+				switch (lp->dialstate) {
+					case 5:
+					case 6:
+					case 7:
+					case 8:
+					case 9:
+					case 10:
+					case 12:
+						if (lp->dialstate <= 6) {
+							dev->usage[idx] |= ISDN_USAGE_OUTGOING;
+							isdn_info_update();
+						} else
+							dev->rx_netdev[idx] = p;
+						lp->dialstate = 0;
+						isdn_timer_ctrl(ISDN_TIMER_NETHANGUP, 1);
+						if (lp->p_encap == ISDN_NET_ENCAP_CISCOHDLCK)
+							isdn_net_ciscohdlck_connected(lp);
+						if (lp->p_encap != ISDN_NET_ENCAP_SYNCPPP) {
+							if (lp->master) { /* is lp a slave? */
+								isdn_net_dev *nd = ((isdn_net_local *)lp->master->priv)->netdev;
+								isdn_net_add_to_bundle(nd, lp);
+							}
+						}
+						printk(KERN_INFO "isdn_net: %s connected\n", lp->name);
+						/* If first Chargeinfo comes before B-Channel connect,
+						 * we correct the timestamp here.
+						 */
+						lp->chargetime = jiffies;
+
+						/* reset dial-timeout */
+						lp->dialstarted = 0;
+						lp->dialwait_timer = 0;
+
+#ifdef CONFIG_ISDN_PPP
+						if (lp->p_encap == ISDN_NET_ENCAP_SYNCPPP)
+							isdn_ppp_wakeup_daemon(lp);
+#endif
+#ifdef CONFIG_ISDN_X25
+						/* try if there are generic concap receiver routines */
+						if( pops )
+							if( pops->connect_ind)
+								pops->connect_ind(cprot);
+#endif /* CONFIG_ISDN_X25 */
+						/* ppp needs to do negotiations first */
+						if (lp->p_encap != ISDN_NET_ENCAP_SYNCPPP)
+							isdn_net_device_wake_queue(lp);
+						return 1;
+				}
+				break;
+			case ISDN_STAT_NODCH:
+				/* No D-Channel avail. */
+				if (lp->dialstate == 4) {
+					lp->dialstate--;
+					return 1;
+				}
+				break;
+			case ISDN_STAT_CINF:
+				/* Charge-info from TelCo. Calculate interval between
+				 * charge-infos and set timestamp for last info for
+				 * usage by isdn_net_autohup()
+				 */
+				lp->charge++;
+				if (lp->hupflags & ISDN_HAVECHARGE) {
+					lp->hupflags &= ~ISDN_WAITCHARGE;
+					lp->chargeint = jiffies - lp->chargetime - (2 * HZ);
+				}
+				if (lp->hupflags & ISDN_WAITCHARGE)
+					lp->hupflags |= ISDN_HAVECHARGE;
+				lp->chargetime = jiffies;
+				printk(KERN_DEBUG "isdn_net: Got CINF chargetime of %s now %lu\n",
+				       lp->name, lp->chargetime);
+				return 1;
+		}
+	}
+	return 0;
+}
 
+/*
+ * Perform dialout for net-interfaces and timeout-handling for
+ * D-Channel-up and B-Channel-up Messages.
+ * This function is initially called from within isdn_net_start_xmit() or
+ * or isdn_net_find_icall() after initializing the dialstate for an
+ * interface. If further calls are needed, the function schedules itself
+ * for a timer-callback via isdn_timer_function().
+ * The dialstate is also affected by incoming status-messages from
+ * the ISDN-Channel which are handled in isdn_net_stat_callback() above.
+ */
+void
+isdn_net_dial(void)
+{
+	isdn_net_dev *p = dev->netdev;
+	int anymore = 0;
+	int i;
+	isdn_ctrl cmd;
+        u_char *phone_number;
+
+	while (p) {
+		isdn_net_local *lp = p->local;
+
+#ifdef ISDN_DEBUG_NET_DIAL
+		if (lp->dialstate)
+			printk(KERN_DEBUG "%s: dialstate=%d\n", lp->name, lp->dialstate);
+#endif
+		switch (lp->dialstate) {
+			case 0:
+				/* Nothing to do for this interface */
+				break;
+			case 1:
+				/* Initiate dialout. Set phone-number-pointer to first number
+				 * of interface.
+				 */
+				lp->dial = lp->phone[1];
+				if (!lp->dial) {
+					printk(KERN_WARNING "%s: phone number deleted?\n",
+					       lp->name);
+					isdn_net_hangup(&p->dev);
+					break;
+				}
+				anymore = 1;
+
+				if(lp->dialtimeout > 0)
+					if(lp->dialstarted == 0 || time_after(jiffies, lp->dialstarted + lp->dialtimeout + lp->dialwait)) {
+						lp->dialstarted = jiffies;
+						lp->dialwait_timer = 0;
+					}
+
+				lp->dialstate++;
+				/* Fall through */
+			case 2:
+				/* Prepare dialing. Clear EAZ, then set EAZ. */
+				cmd.driver = lp->isdn_device;
+				cmd.arg = lp->isdn_channel;
+				cmd.command = ISDN_CMD_CLREAZ;
+				isdn_command(&cmd);
+				sprintf(cmd.parm.num, "%s", isdn_map_eaz2msn(lp->msn, cmd.driver));
+				cmd.command = ISDN_CMD_SETEAZ;
+				isdn_command(&cmd);
+				lp->dialretry = 0;
+				anymore = 1;
+				lp->dialstate++;
+				/* Fall through */
+			case 3:
+				/* Setup interface, dial current phone-number, switch to next number.
+				 * If list of phone-numbers is exhausted, increment
+				 * retry-counter.
+				 */
+				if(dev->global_flags & ISDN_GLOBAL_STOPPED || (ISDN_NET_DIALMODE(*lp) == ISDN_NET_DM_OFF)) {
+					char *s;
+					if (dev->global_flags & ISDN_GLOBAL_STOPPED)
+						s = "dial suppressed: isdn system stopped";
+					else
+						s = "dial suppressed: dialmode `off'";
+					isdn_net_unreachable(&p->dev, 0, s);
+					isdn_net_hangup(&p->dev);
+					break;
+				}
+				cmd.driver = lp->isdn_device;
+				cmd.command = ISDN_CMD_SETL2;
+				cmd.arg = lp->isdn_channel + (lp->l2_proto << 8);
+				isdn_command(&cmd);
+				cmd.driver = lp->isdn_device;
+				cmd.command = ISDN_CMD_SETL3;
+				cmd.arg = lp->isdn_channel + (lp->l3_proto << 8);
+				isdn_command(&cmd);
+				cmd.driver = lp->isdn_device;
+				cmd.arg = lp->isdn_channel;
+				if (!lp->dial) {
+					printk(KERN_WARNING "%s: phone number deleted?\n",
+					       lp->name);
+					isdn_net_hangup(&p->dev);
+					break;
+				}
+				if (!strncmp(lp->dial->num, "LEASED", strlen("LEASED"))) {
+					lp->dialstate = 4;
+					printk(KERN_INFO "%s: Open leased line ...\n", lp->name);
+				} else {
+					if(lp->dialtimeout > 0)
+						if (time_after(jiffies, lp->dialstarted + lp->dialtimeout)) {
+							lp->dialwait_timer = jiffies + lp->dialwait;
+							lp->dialstarted = 0;
+							isdn_net_unreachable(&p->dev, 0, "dial: timed out");
+							isdn_net_hangup(&p->dev);
+							break;
+						}
+
+					cmd.driver = lp->isdn_device;
+					cmd.command = ISDN_CMD_DIAL;
+					cmd.parm.setup.si2 = 0;
+
+                                        /* check for DOV */
+                                        phone_number = lp->dial->num;
+                                        if ((*phone_number == 'v') ||
+					    (*phone_number == 'V')) { /* DOV call */
+                                                cmd.parm.setup.si1 = 1;
+                                        } else { /* DATA call */
+                                                cmd.parm.setup.si1 = 7;
+					}
+
+					strcpy(cmd.parm.setup.phone, phone_number);
+					/*
+					 * Switch to next number or back to start if at end of list.
+					 */
+					if (!(lp->dial = (isdn_net_phone *) lp->dial->next)) {
+						lp->dial = lp->phone[1];
+						lp->dialretry++;
+
+						if (lp->dialretry > lp->dialmax) {
+							if (lp->dialtimeout == 0) {
+								lp->dialwait_timer = jiffies + lp->dialwait;
+								lp->dialstarted = 0;
+								isdn_net_unreachable(&p->dev, 0, "dial: tried all numbers dialmax times");
+							}
+							isdn_net_hangup(&p->dev);
+							break;
+						}
+					}
+					sprintf(cmd.parm.setup.eazmsn, "%s",
+						isdn_map_eaz2msn(lp->msn, cmd.driver));
+					i = isdn_dc2minor(lp->isdn_device, lp->isdn_channel);
+					if (i >= 0) {
+						strcpy(dev->num[i], cmd.parm.setup.phone);
+						dev->usage[i] |= ISDN_USAGE_OUTGOING;
+						isdn_info_update();
+					}
+					printk(KERN_INFO "%s: dialing %d %s... %s\n", lp->name,
+					       lp->dialretry, cmd.parm.setup.phone,
+					       (cmd.parm.setup.si1 == 1) ? "DOV" : "");
+					lp->dtimer = 0;
+#ifdef ISDN_DEBUG_NET_DIAL
+					printk(KERN_DEBUG "dial: d=%d c=%d\n", lp->isdn_device,
+					       lp->isdn_channel);
+#endif
+					isdn_command(&cmd);
+				}
+				lp->huptimer = 0;
+				lp->outgoing = 1;
+				if (lp->chargeint) {
+					lp->hupflags |= ISDN_HAVECHARGE;
+					lp->hupflags &= ~ISDN_WAITCHARGE;
+				} else {
+					lp->hupflags |= ISDN_WAITCHARGE;
+					lp->hupflags &= ~ISDN_HAVECHARGE;
+				}
+				anymore = 1;
+				lp->dialstate =
+				    (lp->cbdelay &&
+				     (lp->flags & ISDN_NET_CBOUT)) ? 12 : 4;
+				break;
+			case 4:
+				/* Wait for D-Channel-connect.
+				 * If timeout, switch back to state 3.
+				 * Dialmax-handling moved to state 3.
+				 */
+				if (lp->dtimer++ > ISDN_TIMER_DTIMEOUT10)
+					lp->dialstate = 3;
+				anymore = 1;
+				break;
+			case 5:
+				/* Got D-Channel-Connect, send B-Channel-request */
+				cmd.driver = lp->isdn_device;
+				cmd.arg = lp->isdn_channel;
+				cmd.command = ISDN_CMD_ACCEPTB;
+				anymore = 1;
+				lp->dtimer = 0;
+				lp->dialstate++;
+				isdn_command(&cmd);
+				break;
+			case 6:
+				/* Wait for B- or D-Channel-connect. If timeout,
+				 * switch back to state 3.
+				 */
+#ifdef ISDN_DEBUG_NET_DIAL
+				printk(KERN_DEBUG "dialtimer2: %d\n", lp->dtimer);
+#endif
+				if (lp->dtimer++ > ISDN_TIMER_DTIMEOUT10)
+					lp->dialstate = 3;
+				anymore = 1;
+				break;
+			case 7:
+				/* Got incoming Call, setup L2 and L3 protocols,
+				 * then wait for D-Channel-connect
+				 */
+#ifdef ISDN_DEBUG_NET_DIAL
+				printk(KERN_DEBUG "dialtimer4: %d\n", lp->dtimer);
+#endif
+				cmd.driver = lp->isdn_device;
+				cmd.command = ISDN_CMD_SETL2;
+				cmd.arg = lp->isdn_channel + (lp->l2_proto << 8);
+				isdn_command(&cmd);
+				cmd.driver = lp->isdn_device;
+				cmd.command = ISDN_CMD_SETL3;
+				cmd.arg = lp->isdn_channel + (lp->l3_proto << 8);
+				isdn_command(&cmd);
+				if (lp->dtimer++ > ISDN_TIMER_DTIMEOUT15)
+					isdn_net_hangup(&p->dev);
+				else {
+					anymore = 1;
+					lp->dialstate++;
+				}
+				break;
+			case 9:
+				/* Got incoming D-Channel-Connect, send B-Channel-request */
+				cmd.driver = lp->isdn_device;
+				cmd.arg = lp->isdn_channel;
+				cmd.command = ISDN_CMD_ACCEPTB;
+				isdn_command(&cmd);
+				anymore = 1;
+				lp->dtimer = 0;
+				lp->dialstate++;
+				break;
+			case 8:
+			case 10:
+				/*  Wait for B- or D-channel-connect */
+#ifdef ISDN_DEBUG_NET_DIAL
+				printk(KERN_DEBUG "dialtimer4: %d\n", lp->dtimer);
+#endif
+				if (lp->dtimer++ > ISDN_TIMER_DTIMEOUT10)
+					isdn_net_hangup(&p->dev);
+				else
+					anymore = 1;
+				break;
+			case 11:
+				/* Callback Delay */
+				if (lp->dtimer++ > lp->cbdelay)
+					lp->dialstate = 1;
+				anymore = 1;
+				break;
+			case 12:
+				/* Remote does callback. Hangup after cbdelay, then wait for incoming
+				 * call (in state 4).
+				 */
+				if (lp->dtimer++ > lp->cbdelay)
+				{
+					printk(KERN_INFO "%s: hangup waiting for callback ...\n", lp->name);
+					lp->dtimer = 0;
+					lp->dialstate = 4;
+					cmd.driver = lp->isdn_device;
+					cmd.command = ISDN_CMD_HANGUP;
+					cmd.arg = lp->isdn_channel;
+					isdn_command(&cmd);
+					isdn_all_eaz(lp->isdn_device, lp->isdn_channel);
+				}
+				anymore = 1;
+				break;
+			default:
+				printk(KERN_WARNING "isdn_net: Illegal dialstate %d for device %s\n",
+				       lp->dialstate, lp->name);
+		}
+		p = (isdn_net_dev *) p->next;
+	}
+	isdn_timer_ctrl(ISDN_TIMER_NETDIAL, anymore);
+}
+
+/*
+ * Perform hangup for a net-interface.
+ */
+void
+isdn_net_hangup(struct net_device *d)
+{
+	isdn_net_local *lp = (isdn_net_local *) d->priv;
+	isdn_ctrl cmd;
+#ifdef CONFIG_ISDN_X25
+	struct concap_proto *cprot = lp -> netdev -> cprot;
+	struct concap_proto_ops *pops = cprot ? cprot -> pops : 0;
+#endif
+
+	if (lp->flags & ISDN_NET_CONNECTED) {
+		if (lp->slave != NULL) {
+			isdn_net_local *slp = (isdn_net_local *)lp->slave->priv;
+			if (slp->flags & ISDN_NET_CONNECTED) {
+				printk(KERN_INFO
+					"isdn_net: hang up slave %s before %s\n",
+					slp->name, lp->name);
+				isdn_net_hangup(lp->slave);
+			}
+		}
+		printk(KERN_INFO "isdn_net: local hangup %s\n", lp->name);
+#ifdef CONFIG_ISDN_PPP
+		if (lp->p_encap == ISDN_NET_ENCAP_SYNCPPP)
+			isdn_ppp_free(lp);
+#endif
+		isdn_net_lp_disconnected(lp);
+#ifdef CONFIG_ISDN_X25
+		/* try if there are generic encap protocol
+		   receiver routines and signal the closure of
+		   the link */
+		if( pops && pops -> disconn_ind )
+		  pops -> disconn_ind(cprot);
+#endif /* CONFIG_ISDN_X25 */
+
+		cmd.driver = lp->isdn_device;
+		cmd.command = ISDN_CMD_HANGUP;
+		cmd.arg = lp->isdn_channel;
+		isdn_command(&cmd);
+		printk(KERN_INFO "%s: Chargesum is %d\n", lp->name, lp->charge);
+		isdn_all_eaz(lp->isdn_device, lp->isdn_channel);
+	}
+	isdn_net_unbind_channel(lp);
+}
+
+typedef struct {
+	unsigned short source;
+	unsigned short dest;
+} ip_ports;
+
+static void
+isdn_net_log_skb(struct sk_buff * skb, isdn_net_local * lp)
+{
+	u_char *p = skb->nh.raw; /* hopefully, this was set correctly */
+	unsigned short proto = ntohs(skb->protocol);
+	int data_ofs;
+	ip_ports *ipp;
+	char addinfo[100];
+
+	addinfo[0] = '\0';
+	/* This check stolen from 2.1.72 dev_queue_xmit_nit() */
+	if (skb->nh.raw < skb->data || skb->nh.raw >= skb->tail) {
+		/* fall back to old isdn_net_log_packet method() */
+		char * buf = skb->data;
+
+		printk(KERN_DEBUG "isdn_net: protocol %04x is buggy, dev %s\n", skb->protocol, lp->name);
+		p = buf;
+		proto = ETH_P_IP;
+		switch (lp->p_encap) {
+			case ISDN_NET_ENCAP_IPTYP:
+				proto = ntohs(*(unsigned short *) &buf[0]);
+				p = &buf[2];
+				break;
+			case ISDN_NET_ENCAP_ETHER:
+				proto = ntohs(*(unsigned short *) &buf[12]);
+				p = &buf[14];
+				break;
+			case ISDN_NET_ENCAP_CISCOHDLC:
+				proto = ntohs(*(unsigned short *) &buf[2]);
+				p = &buf[4];
+				break;
+#ifdef CONFIG_ISDN_PPP
+			case ISDN_NET_ENCAP_SYNCPPP:
+				proto = ntohs(skb->protocol);
+				p = &buf[IPPP_MAX_HEADER];
+				break;
+#endif
+		}
+	}
+	data_ofs = ((p[0] & 15) * 4);
+	switch (proto) {
+		case ETH_P_IP:
+			switch (p[9]) {
+				case 1:
+					strcpy(addinfo, " ICMP");
+					break;
+				case 2:
+					strcpy(addinfo, " IGMP");
+					break;
+				case 4:
+					strcpy(addinfo, " IPIP");
+					break;
+				case 6:
+					ipp = (ip_ports *) (&p[data_ofs]);
+					sprintf(addinfo, " TCP, port: %d -> %d", ntohs(ipp->source),
+						ntohs(ipp->dest));
+					break;
+				case 8:
+					strcpy(addinfo, " EGP");
+					break;
+				case 12:
+					strcpy(addinfo, " PUP");
+					break;
+				case 17:
+					ipp = (ip_ports *) (&p[data_ofs]);
+					sprintf(addinfo, " UDP, port: %d -> %d", ntohs(ipp->source),
+						ntohs(ipp->dest));
+					break;
+				case 22:
+					strcpy(addinfo, " IDP");
+					break;
+			}
+			printk(KERN_INFO
+				"OPEN: %d.%d.%d.%d -> %d.%d.%d.%d%s\n",
+
+			       p[12], p[13], p[14], p[15],
+			       p[16], p[17], p[18], p[19],
+			       addinfo);
+			break;
+		case ETH_P_ARP:
+			printk(KERN_INFO
+				"OPEN: ARP %d.%d.%d.%d -> *.*.*.* ?%d.%d.%d.%d\n",
+			       p[14], p[15], p[16], p[17],
+			       p[24], p[25], p[26], p[27]);
+			break;
+	}
+}
+
+/*
+ * this function is used to send supervisory data, i.e. data which was
+ * not received from the network layer, but e.g. frames from ipppd, CCP
+ * reset frames etc.
+ */
+void isdn_net_write_super(isdn_net_local *lp, struct sk_buff *skb)
+{
+	if (in_irq()) {
+		// we can't grab the lock from irq context, 
+		// so we just queue the packet
+		skb_queue_tail(&lp->super_tx_queue, skb);
+		schedule_work(&lp->tqueue);
+		return;
+	}
+
+	spin_lock_bh(&lp->xmit_lock);
+	if (!isdn_net_lp_busy(lp)) {
+		isdn_net_writebuf_skb(lp, skb);
+	} else {
+		skb_queue_tail(&lp->super_tx_queue, skb);
+	}
+	spin_unlock_bh(&lp->xmit_lock);
+}
+
+/*
+ * called from tq_immediate
+ */
+static void isdn_net_softint(void *private)
+{
+	isdn_net_local *lp = private;
+	struct sk_buff *skb;
+
+	spin_lock_bh(&lp->xmit_lock);
+	while (!isdn_net_lp_busy(lp)) {
+		skb = skb_dequeue(&lp->super_tx_queue);
+		if (!skb)
+			break;
+		isdn_net_writebuf_skb(lp, skb);                                
+	}
+	spin_unlock_bh(&lp->xmit_lock);
+}
+
+/* 
+ * all frames sent from the (net) LL to a HL driver should go via this function
+ * it's serialized by the caller holding the lp->xmit_lock spinlock
+ */
+void isdn_net_writebuf_skb(isdn_net_local *lp, struct sk_buff *skb)
+{
+	int ret;
+	int len = skb->len;     /* save len */
+
+	/* before obtaining the lock the caller should have checked that
+	   the lp isn't busy */
+	if (isdn_net_lp_busy(lp)) {
+		printk("isdn BUG at %s:%d!\n", __FILE__, __LINE__);
+		goto error;
+	}
+
+	if (!(lp->flags & ISDN_NET_CONNECTED)) {
+		printk("isdn BUG at %s:%d!\n", __FILE__, __LINE__);
+		goto error;
+	}
+	ret = isdn_writebuf_skb_stub(lp->isdn_device, lp->isdn_channel, 1, skb);
+	if (ret != len) {
+		/* we should never get here */
+		printk(KERN_WARNING "%s: HL driver queue full\n", lp->name);
+		goto error;
+	}
+	
+	lp->transcount += len;
+	isdn_net_inc_frame_cnt(lp);
+	return;
+
+ error:
+	dev_kfree_skb(skb);
+	lp->stats.tx_errors++;
+
+}
+
+
+/*
+ *  Helper function for isdn_net_start_xmit.
+ *  When called, the connection is already established.
+ *  Based on cps-calculation, check if device is overloaded.
+ *  If so, and if a slave exists, trigger dialing for it.
+ *  If any slave is online, deliver packets using a simple round robin
+ *  scheme.
+ *
+ *  Return: 0 on success, !0 on failure.
+ */
+
+static int
+isdn_net_xmit(struct net_device *ndev, struct sk_buff *skb)
+{
+	isdn_net_dev *nd;
+	isdn_net_local *slp;
+	isdn_net_local *lp = (isdn_net_local *) ndev->priv;
+	int retv = 0;
+
+	if (((isdn_net_local *) (ndev->priv))->master) {
+		printk("isdn BUG at %s:%d!\n", __FILE__, __LINE__);
+		dev_kfree_skb(skb);
+		return 0;
+	}
+
+	/* For the other encaps the header has already been built */
+#ifdef CONFIG_ISDN_PPP
+	if (lp->p_encap == ISDN_NET_ENCAP_SYNCPPP) {
+		return isdn_ppp_xmit(skb, ndev);
+	}
+#endif
+	nd = ((isdn_net_local *) ndev->priv)->netdev;
+	lp = isdn_net_get_locked_lp(nd);
+	if (!lp) {
+		printk(KERN_WARNING "%s: all channels busy - requeuing!\n", ndev->name);
+		return 1;
+	}
+	/* we have our lp locked from now on */
+
+	/* Reset hangup-timeout */
+	lp->huptimer = 0; // FIXME?
+	isdn_net_writebuf_skb(lp, skb);
+	spin_unlock_bh(&lp->xmit_lock);
+
+	/* the following stuff is here for backwards compatibility.
+	 * in future, start-up and hangup of slaves (based on current load)
+	 * should move to userspace and get based on an overall cps
+	 * calculation
+	 */
+	if (lp->cps > lp->triggercps) {
+		if (lp->slave) {
+			if (!lp->sqfull) {
+				/* First time overload: set timestamp only */
+				lp->sqfull = 1;
+				lp->sqfull_stamp = jiffies;
+			} else {
+				/* subsequent overload: if slavedelay exceeded, start dialing */
+				if (time_after(jiffies, lp->sqfull_stamp + lp->slavedelay)) {
+					slp = lp->slave->priv;
+					if (!(slp->flags & ISDN_NET_CONNECTED)) {
+						isdn_net_force_dial_lp((isdn_net_local *) lp->slave->priv);
+					}
+				}
+			}
+		}
+	} else {
+		if (lp->sqfull && time_after(jiffies, lp->sqfull_stamp + lp->slavedelay + (10 * HZ))) {
+			lp->sqfull = 0;
+		}
+		/* this is a hack to allow auto-hangup for slaves on moderate loads */
+		nd->queue = nd->local;
+	}
+
+	return retv;
+
+}
+
+static void
+isdn_net_adjust_hdr(struct sk_buff *skb, struct net_device *dev)
+{
+	isdn_net_local *lp = (isdn_net_local *) dev->priv;
+	if (!skb)
+		return;
+	if (lp->p_encap == ISDN_NET_ENCAP_ETHER) {
+		int pullsize = (ulong)skb->nh.raw - (ulong)skb->data - ETH_HLEN;
+		if (pullsize > 0) {
+			printk(KERN_DEBUG "isdn_net: Pull junk %d\n", pullsize);
+			skb_pull(skb, pullsize);
+		}
+	}
+}
+
+
+void isdn_net_tx_timeout(struct net_device * ndev)
+{
+	isdn_net_local *lp = (isdn_net_local *) ndev->priv;
+
+	printk(KERN_WARNING "isdn_tx_timeout dev %s dialstate %d\n", ndev->name, lp->dialstate);
+	if (!lp->dialstate){
+		lp->stats.tx_errors++;
+                /*
+		 * There is a certain probability that this currently
+		 * works at all because if we always wake up the interface,
+		 * then upper layer will try to send the next packet
+		 * immediately. And then, the old clean_up logic in the
+		 * driver will hopefully continue to work as it used to do.
+		 *
+		 * This is rather primitive right know, we better should
+		 * clean internal queues here, in particular for multilink and
+		 * ppp, and reset HL driver's channel, too.   --HE
+		 *
+		 * actually, this may not matter at all, because ISDN hardware
+		 * should not see transmitter hangs at all IMO
+		 * changed KERN_DEBUG to KERN_WARNING to find out if this is 
+		 * ever called   --KG
+		 */
+	}
+	ndev->trans_start = jiffies;
+	netif_wake_queue(ndev);
+}
+
+/*
+ * Try sending a packet.
+ * If this interface isn't connected to a ISDN-Channel, find a free channel,
+ * and start dialing.
+ */
+static int
+isdn_net_start_xmit(struct sk_buff *skb, struct net_device *ndev)
+{
+	isdn_net_local *lp = (isdn_net_local *) ndev->priv;
+#ifdef CONFIG_ISDN_X25
+	struct concap_proto * cprot = lp -> netdev -> cprot;
+/* At this point hard_start_xmit() passes control to the encapsulation
+   protocol (if present).
+   For X.25 auto-dialing is completly bypassed because:
+   - It does not conform with the semantics of a reliable datalink
+     service as needed by X.25 PLP.
+   - I don't want that the interface starts dialing when the network layer
+     sends a message which requests to disconnect the lapb link (or if it
+     sends any other message not resulting in data transmission).
+   Instead, dialing will be initiated by the encapsulation protocol entity
+   when a dl_establish request is received from the upper layer.
+*/
+	if (cprot && cprot -> pops) {
+		int ret = cprot -> pops -> encap_and_xmit ( cprot , skb);
+
+		if (ret)
+			netif_stop_queue(ndev);
+		return ret;
+	} else
+#endif
+	/* auto-dialing xmit function */
+	{
+#ifdef ISDN_DEBUG_NET_DUMP
+		u_char *buf;
+#endif
+		isdn_net_adjust_hdr(skb, ndev);
+#ifdef ISDN_DEBUG_NET_DUMP
+		buf = skb->data;
+		isdn_dumppkt("S:", buf, skb->len, 40);
+#endif
+
+		if (!(lp->flags & ISDN_NET_CONNECTED)) {
+			int chi;
+			/* only do autodial if allowed by config */
+			if (!(ISDN_NET_DIALMODE(*lp) == ISDN_NET_DM_AUTO)) {
+				isdn_net_unreachable(ndev, skb, "dial rejected: interface not in dialmode `auto'");
+				dev_kfree_skb(skb);
+				return 0;
+			}
+			if (lp->phone[1]) {
+				ulong flags;
+
+				if(lp->dialwait_timer <= 0)
+					if(lp->dialstarted > 0 && lp->dialtimeout > 0 && time_before(jiffies, lp->dialstarted + lp->dialtimeout + lp->dialwait))
+						lp->dialwait_timer = lp->dialstarted + lp->dialtimeout + lp->dialwait;
+
+				if(lp->dialwait_timer > 0) {
+					if(time_before(jiffies, lp->dialwait_timer)) {
+						isdn_net_unreachable(ndev, skb, "dial rejected: retry-time not reached");
+						dev_kfree_skb(skb);
+						return 0;
+					} else
+						lp->dialwait_timer = 0;
+				}
+				/* Grab a free ISDN-Channel */
+				spin_lock_irqsave(&dev->lock, flags);
+				if (((chi =
+				     isdn_get_free_channel(
+					 		ISDN_USAGE_NET,
+							lp->l2_proto,
+							lp->l3_proto,
+							lp->pre_device,
+						 	lp->pre_channel,
+							lp->msn)
+							) < 0) &&
+					((chi =
+				     isdn_get_free_channel(
+					 		ISDN_USAGE_NET,
+							lp->l2_proto,
+							lp->l3_proto,
+							lp->pre_device,
+							lp->pre_channel^1,
+							lp->msn)
+							) < 0)) {
+					spin_unlock_irqrestore(&dev->lock, flags);
+					isdn_net_unreachable(ndev, skb,
+							   "No channel");
+					dev_kfree_skb(skb);
+					return 0;
+				}
+				/* Log packet, which triggered dialing */
+				if (dev->net_verbose)
+					isdn_net_log_skb(skb, lp);
+				lp->dialstate = 1;
+				/* Connect interface with channel */
+				isdn_net_bind_channel(lp, chi);
+#ifdef CONFIG_ISDN_PPP
+				if (lp->p_encap == ISDN_NET_ENCAP_SYNCPPP) {
+					/* no 'first_skb' handling for syncPPP */
+					if (isdn_ppp_bind(lp) < 0) {
+						dev_kfree_skb(skb);
+						isdn_net_unbind_channel(lp);
+						spin_unlock_irqrestore(&dev->lock, flags);
+						return 0;	/* STN (skb to nirvana) ;) */
+					}
+#ifdef CONFIG_IPPP_FILTER
+					if (isdn_ppp_autodial_filter(skb, lp)) {
+						isdn_ppp_free(lp);
+						isdn_net_unbind_channel(lp);
+						spin_unlock_irqrestore(&dev->lock, flags);
+						isdn_net_unreachable(ndev, skb, "dial rejected: packet filtered");
+						dev_kfree_skb(skb);
+						return 0;
+					}
+#endif
+					spin_unlock_irqrestore(&dev->lock, flags);
+					isdn_net_dial();	/* Initiate dialing */
+					netif_stop_queue(ndev);
+					return 1;	/* let upper layer requeue skb packet */
+				}
+#endif
+				/* Initiate dialing */
+				spin_unlock_irqrestore(&dev->lock, flags);
+				isdn_net_dial();
+				isdn_net_device_stop_queue(lp);
+				return 1;
+			} else {
+				isdn_net_unreachable(ndev, skb,
+						     "No phone number");
+				dev_kfree_skb(skb);
+				return 0;
+			}
+		} else {
+			/* Device is connected to an ISDN channel */ 
+			ndev->trans_start = jiffies;
+			if (!lp->dialstate) {
+				/* ISDN connection is established, try sending */
+				int ret;
+				ret = (isdn_net_xmit(ndev, skb));
+				if(ret) netif_stop_queue(ndev);
+				return ret;
+			} else
+				netif_stop_queue(ndev);
+		}
+	}
+	return 1;
+}
+
+/*
+ * Shutdown a net-interface.
+ */
 static int
-isdn_uihdlc_header(struct sk_buff *skb, struct net_device *dev,
-		   unsigned short type, void *daddr, void *saddr, 
-		   unsigned plen)
+isdn_net_close(struct net_device *dev)
+{
+	struct net_device *p;
+#ifdef CONFIG_ISDN_X25
+	struct concap_proto * cprot =
+		( (isdn_net_local *) dev->priv ) -> netdev -> cprot;
+	/* printk(KERN_DEBUG "isdn_net_close %s\n" , dev-> name ); */
+#endif
+
+#ifdef CONFIG_ISDN_X25
+	if( cprot && cprot -> pops ) cprot -> pops -> close( cprot );
+#endif
+	netif_stop_queue(dev);
+	if ((p = (((isdn_net_local *) dev->priv)->slave))) {
+		/* If this interface has slaves, stop them also */
+		while (p) {
+#ifdef CONFIG_ISDN_X25
+			cprot = ( (isdn_net_local *) p->priv )
+				-> netdev -> cprot;
+			if( cprot && cprot -> pops )
+				cprot -> pops -> close( cprot );
+#endif
+			isdn_net_hangup(p);
+			p = (((isdn_net_local *) p->priv)->slave);
+		}
+	}
+	isdn_net_hangup(dev);
+	isdn_unlock_drivers();
+	return 0;
+}
+
+/*
+ * Get statistics
+ */
+static struct net_device_stats *
+isdn_net_get_stats(struct net_device *dev)
+{
+	isdn_net_local *lp = (isdn_net_local *) dev->priv;
+	return &lp->stats;
+}
+
+/*      This is simply a copy from std. eth.c EXCEPT we pull ETH_HLEN
+ *      instead of dev->hard_header_len off. This is done because the
+ *      lowlevel-driver has already pulled off its stuff when we get
+ *      here and this routine only gets called with p_encap == ETHER.
+ *      Determine the packet's protocol ID. The rule here is that we
+ *      assume 802.3 if the type field is short enough to be a length.
+ *      This is normal practice and works for any 'now in use' protocol.
+ */
+
+static unsigned short
+isdn_net_type_trans(struct sk_buff *skb, struct net_device *dev)
+{
+	struct ethhdr *eth;
+	unsigned char *rawp;
+
+	skb->mac.raw = skb->data;
+	skb_pull(skb, ETH_HLEN);
+	eth = skb->mac.ethernet;
+
+	if (*eth->h_dest & 1) {
+		if (memcmp(eth->h_dest, dev->broadcast, ETH_ALEN) == 0)
+			skb->pkt_type = PACKET_BROADCAST;
+		else
+			skb->pkt_type = PACKET_MULTICAST;
+	}
+	/*
+	 *      This ALLMULTI check should be redundant by 1.4
+	 *      so don't forget to remove it.
+	 */
+
+	else if (dev->flags & (IFF_PROMISC /*| IFF_ALLMULTI*/)) {
+		if (memcmp(eth->h_dest, dev->dev_addr, ETH_ALEN))
+			skb->pkt_type = PACKET_OTHERHOST;
+	}
+	if (ntohs(eth->h_proto) >= 1536)
+		return eth->h_proto;
+
+	rawp = skb->data;
+
+	/*
+	 *      This is a magic hack to spot IPX packets. Older Novell breaks
+	 *      the protocol design and runs IPX over 802.3 without an 802.2 LLC
+	 *      layer. We look for FFFF which isn't a used 802.2 SSAP/DSAP. This
+	 *      won't work for fault tolerant netware but does for the rest.
+	 */
+	if (*(unsigned short *) rawp == 0xFFFF)
+		return htons(ETH_P_802_3);
+	/*
+	 *      Real 802.2 LLC
+	 */
+	return htons(ETH_P_802_2);
+}
+
+
+/* 
+ * CISCO HDLC keepalive specific stuff
+ */
+static struct sk_buff*
+isdn_net_ciscohdlck_alloc_skb(isdn_net_local *lp, int len)
 {
-	put_u16(skb_push(skb, 2), 0x0103);
-	return 2;
+	unsigned short hl = dev->drv[lp->isdn_device]->interface->hl_hdrlen;
+	struct sk_buff *skb;
+
+	skb = alloc_skb(hl + len, GFP_ATOMIC);
+	if (!skb) {
+		printk("isdn out of mem at %s:%d!\n", __FILE__, __LINE__);
+		return 0;
+	}
+	skb_reserve(skb, hl);
+	return skb;
+}
+
+/* cisco hdlck device private ioctls */
+int
+isdn_ciscohdlck_dev_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
+{
+	isdn_net_local *lp = (isdn_net_local *) dev->priv;
+	unsigned long len = 0;
+	unsigned long expires = 0;
+	int tmp = 0;
+	int period = lp->cisco_keepalive_period;
+	char debserint = lp->cisco_debserint;
+	int rc = 0;
+
+	if (lp->p_encap != ISDN_NET_ENCAP_CISCOHDLCK)
+		return -EINVAL;
+
+	switch (cmd) {
+		/* get/set keepalive period */
+		case SIOCGKEEPPERIOD:
+			len = (unsigned long)sizeof(lp->cisco_keepalive_period);
+			if (copy_to_user((char *)ifr->ifr_ifru.ifru_data,
+				(int *)&lp->cisco_keepalive_period, len))
+				rc = -EFAULT;
+			break;
+		case SIOCSKEEPPERIOD:
+			tmp = lp->cisco_keepalive_period;
+			len = (unsigned long)sizeof(lp->cisco_keepalive_period);
+			if (copy_from_user((int *)&period,
+				(char *)ifr->ifr_ifru.ifru_data, len))
+				rc = -EFAULT;
+			if ((period > 0) && (period <= 32767))
+				lp->cisco_keepalive_period = period;
+			else
+				rc = -EINVAL;
+			if (!rc && (tmp != lp->cisco_keepalive_period)) {
+				expires = (unsigned long)(jiffies +
+					lp->cisco_keepalive_period * HZ);
+				mod_timer(&lp->cisco_timer, expires);
+				printk(KERN_INFO "%s: Keepalive period set "
+					"to %d seconds.\n",
+					lp->name, lp->cisco_keepalive_period);
+			}
+			break;
+
+		/* get/set debugging */
+		case SIOCGDEBSERINT:
+			len = (unsigned long)sizeof(lp->cisco_debserint);
+			if (copy_to_user((char *)ifr->ifr_ifru.ifru_data,
+				(char *)&lp->cisco_debserint, len))
+				rc = -EFAULT;
+			break;
+		case SIOCSDEBSERINT:
+			len = (unsigned long)sizeof(lp->cisco_debserint);
+			if (copy_from_user((char *)&debserint,
+				(char *)ifr->ifr_ifru.ifru_data, len))
+				rc = -EFAULT;
+			if ((debserint >= 0) && (debserint <= 64))
+				lp->cisco_debserint = debserint;
+			else
+				rc = -EINVAL;
+			break;
+
+		default:
+			rc = -EINVAL;
+			break;
+	}
+	return (rc);
 }
 
+/* called via cisco_timer.function */
 static void
-isdn_uihdlc_receive(isdn_net_local *lp, isdn_net_dev *idev, 
-		    struct sk_buff *skb)
+isdn_net_ciscohdlck_slarp_send_keepalive(unsigned long data)
 {
-	skb_pull(skb, 2);
-	isdn_netif_rx(idev, skb, htons(ETH_P_IP));
+	isdn_net_local *lp = (isdn_net_local *) data;
+	struct sk_buff *skb;
+	unsigned char *p;
+	unsigned long last_cisco_myseq = lp->cisco_myseq;
+	int myseq_diff = 0;
+
+	if (!(lp->flags & ISDN_NET_CONNECTED) || lp->dialstate) {
+		printk("isdn BUG at %s:%d!\n", __FILE__, __LINE__);
+		return;
+	}
+	lp->cisco_myseq++;
+
+	myseq_diff = (lp->cisco_myseq - lp->cisco_mineseen);
+	if ((lp->cisco_line_state) && ((myseq_diff >= 3)||(myseq_diff <= -3))) {
+		/* line up -> down */
+		lp->cisco_line_state = 0;
+		printk (KERN_WARNING
+				"UPDOWN: Line protocol on Interface %s,"
+				" changed state to down\n", lp->name);
+		/* should stop routing higher-level data accross */
+	} else if ((!lp->cisco_line_state) &&
+		(myseq_diff >= 0) && (myseq_diff <= 2)) {
+		/* line down -> up */
+		lp->cisco_line_state = 1;
+		printk (KERN_WARNING
+				"UPDOWN: Line protocol on Interface %s,"
+				" changed state to up\n", lp->name);
+		/* restart routing higher-level data accross */
+	}
+
+	if (lp->cisco_debserint)
+		printk (KERN_DEBUG "%s: HDLC "
+			"myseq %lu, mineseen %lu%c, yourseen %lu, %s\n",
+			lp->name, last_cisco_myseq, lp->cisco_mineseen,
+			((last_cisco_myseq == lp->cisco_mineseen) ? '*' : 040),
+			lp->cisco_yourseq,
+			((lp->cisco_line_state) ? "line up" : "line down"));
+
+	skb = isdn_net_ciscohdlck_alloc_skb(lp, 4 + 14);
+	if (!skb)
+		return;
+
+	p = skb_put(skb, 4 + 14);
+
+	/* cisco header */
+	p += put_u8 (p, CISCO_ADDR_UNICAST);
+	p += put_u8 (p, CISCO_CTRL);
+	p += put_u16(p, CISCO_TYPE_SLARP);
+
+	/* slarp keepalive */
+	p += put_u32(p, CISCO_SLARP_KEEPALIVE);
+	p += put_u32(p, lp->cisco_myseq);
+	p += put_u32(p, lp->cisco_yourseq);
+	p += put_u16(p, 0xffff); // reliablity, always 0xffff
+
+	isdn_net_write_super(lp, skb);
+
+	lp->cisco_timer.expires = jiffies + lp->cisco_keepalive_period * HZ;
+	
+	add_timer(&lp->cisco_timer);
 }
 
-struct isdn_netif_ops isdn_uihdlc_ops = {
-	.hard_start_xmit     = isdn_net_start_xmit,
-	.hard_header         = isdn_uihdlc_header,
-	.flags               = IFF_NOARP | IFF_POINTOPOINT,
-	.type                = ARPHRD_HDLC,
-	.addr_len            = 2,
-	.receive             = isdn_uihdlc_receive,
-};
+static void
+isdn_net_ciscohdlck_slarp_send_request(isdn_net_local *lp)
+{
+	struct sk_buff *skb;
+	unsigned char *p;
 
-// ISDN_NET_ENCAP_RAWIP
-// RAW-IP without MAC-Header
-// ======================================================================
+	skb = isdn_net_ciscohdlck_alloc_skb(lp, 4 + 14);
+	if (!skb)
+		return;
+
+	p = skb_put(skb, 4 + 14);
+
+	/* cisco header */
+	p += put_u8 (p, CISCO_ADDR_UNICAST);
+	p += put_u8 (p, CISCO_CTRL);
+	p += put_u16(p, CISCO_TYPE_SLARP);
+
+	/* slarp request */
+	p += put_u32(p, CISCO_SLARP_REQUEST);
+	p += put_u32(p, 0); // address
+	p += put_u32(p, 0); // netmask
+	p += put_u16(p, 0); // unused
+
+	isdn_net_write_super(lp, skb);
+}
+
+static void 
+isdn_net_ciscohdlck_connected(isdn_net_local *lp)
+{
+	lp->cisco_myseq = 0;
+	lp->cisco_mineseen = 0;
+	lp->cisco_yourseq = 0;
+	lp->cisco_keepalive_period = ISDN_TIMER_KEEPINT;
+	lp->cisco_last_slarp_in = 0;
+	lp->cisco_line_state = 0;
+	lp->cisco_debserint = 0;
+
+	/* send slarp request because interface/seq.no.s reset */
+	isdn_net_ciscohdlck_slarp_send_request(lp);
+
+	init_timer(&lp->cisco_timer);
+	lp->cisco_timer.data = (unsigned long) lp;
+	lp->cisco_timer.function = isdn_net_ciscohdlck_slarp_send_keepalive;
+	lp->cisco_timer.expires = jiffies + lp->cisco_keepalive_period * HZ;
+	add_timer(&lp->cisco_timer);
+}
+
+static void 
+isdn_net_ciscohdlck_disconnected(isdn_net_local *lp)
+{
+	del_timer(&lp->cisco_timer);
+}
 
 static void
-isdn_rawip_receive(isdn_net_local *lp, isdn_net_dev *idev, 
-		   struct sk_buff *skb)
+isdn_net_ciscohdlck_slarp_send_reply(isdn_net_local *lp)
 {
-	idev->huptimer = 0;
-	skb->protocol = htons(ETH_P_IP);
+	struct sk_buff *skb;
+	unsigned char *p;
+	struct in_device *in_dev = NULL;
+	u32 addr = 0;		/* local ipv4 address */
+	u32 mask = 0;		/* local netmask */
+
+	if ((in_dev = lp->netdev->dev.ip_ptr) != NULL) {
+		/* take primary(first) address of interface */
+		struct in_ifaddr *ifa = in_dev->ifa_list;
+		if (ifa != NULL) {
+			addr = ifa->ifa_local;
+			mask = ifa->ifa_mask;
+		}
+	}
+
+	skb = isdn_net_ciscohdlck_alloc_skb(lp, 4 + 14);
+	if (!skb)
+		return;
+
+	p = skb_put(skb, 4 + 14);
+
+	/* cisco header */
+	p += put_u8 (p, CISCO_ADDR_UNICAST);
+	p += put_u8 (p, CISCO_CTRL);
+	p += put_u16(p, CISCO_TYPE_SLARP);
+
+	/* slarp reply, send own ip/netmask; if values are nonsense remote
+	 * should think we are unable to provide it with an address via SLARP */
+	p += put_u32(p, CISCO_SLARP_REPLY);
+	p += put_u32(p, addr);	// address
+	p += put_u32(p, mask);	// netmask
+	p += put_u16(p, 0);	// unused
+
+	isdn_net_write_super(lp, skb);
+}
+
+static void
+isdn_net_ciscohdlck_slarp_in(isdn_net_local *lp, struct sk_buff *skb)
+{
+	unsigned char *p;
+	int period;
+	u32 code;
+	u32 my_seq, addr;
+	u32 your_seq, mask;
+	u32 local;
+	u16 unused;
+
+	if (skb->len < 14)
+		return;
+
+	p = skb->data;
+	p += get_u32(p, &code);
+	
+	switch (code) {
+	case CISCO_SLARP_REQUEST:
+		lp->cisco_yourseq = 0;
+		isdn_net_ciscohdlck_slarp_send_reply(lp);
+		break;
+	case CISCO_SLARP_REPLY:
+		addr = ntohl(*(u32 *)p);
+		mask = ntohl(*(u32 *)(p+4));
+		if (mask != 0xfffffffc)
+			goto slarp_reply_out;
+		if ((addr & 3) == 0 || (addr & 3) == 3)
+			goto slarp_reply_out;
+		local = addr ^ 3;
+		printk(KERN_INFO "%s: got slarp reply: "
+			"remote ip: %d.%d.%d.%d, "
+			"local ip: %d.%d.%d.%d "
+			"mask: %d.%d.%d.%d\n",
+		       lp->name,
+		       HIPQUAD(addr),
+		       HIPQUAD(local),
+		       HIPQUAD(mask));
+		break;
+  slarp_reply_out:
+		 printk(KERN_INFO "%s: got invalid slarp "
+				 "reply (%d.%d.%d.%d/%d.%d.%d.%d) "
+				 "- ignored\n", lp->name,
+				 HIPQUAD(addr), HIPQUAD(mask));
+		break;
+	case CISCO_SLARP_KEEPALIVE:
+		period = (int)((jiffies - lp->cisco_last_slarp_in
+				+ HZ/2 - 1) / HZ);
+		if (lp->cisco_debserint &&
+				(period != lp->cisco_keepalive_period) &&
+				lp->cisco_last_slarp_in) {
+			printk(KERN_DEBUG "%s: Keepalive period mismatch - "
+				"is %d but should be %d.\n",
+				lp->name, period, lp->cisco_keepalive_period);
+		}
+		lp->cisco_last_slarp_in = jiffies;
+		p += get_u32(p, &my_seq);
+		p += get_u32(p, &your_seq);
+		p += get_u16(p, &unused);
+		lp->cisco_yourseq = my_seq;
+		lp->cisco_mineseen = your_seq;
+		break;
+	}
+}
+
+static void
+isdn_net_ciscohdlck_receive(isdn_net_local *lp, struct sk_buff *skb)
+{
+	unsigned char *p;
+ 	u8 addr;
+ 	u8 ctrl;
+ 	u16 type;
+	
+	if (skb->len < 4)
+		goto out_free;
+
+	p = skb->data;
+	p += get_u8 (p, &addr);
+	p += get_u8 (p, &ctrl);
+	p += get_u16(p, &type);
+	skb_pull(skb, 4);
+	
+	if (addr != CISCO_ADDR_UNICAST && addr != CISCO_ADDR_BROADCAST) {
+		printk(KERN_WARNING "%s: Unknown Cisco addr 0x%02x\n",
+		       lp->name, addr);
+		goto out_free;
+	}
+	if (ctrl != CISCO_CTRL) {
+		printk(KERN_WARNING "%s: Unknown Cisco ctrl 0x%02x\n",
+		       lp->name, ctrl);
+		goto out_free;
+	}
+
+	switch (type) {
+	case CISCO_TYPE_SLARP:
+		isdn_net_ciscohdlck_slarp_in(lp, skb);
+		goto out_free;
+	case CISCO_TYPE_CDP:
+		if (lp->cisco_debserint)
+			printk(KERN_DEBUG "%s: Received CDP packet. use "
+				"\"no cdp enable\" on cisco.\n", lp->name);
+		goto out_free;
+	default:
+		/* no special cisco protocol */
+		skb->protocol = htons(type);
+		netif_rx(skb);
+		return;
+	}
+
+ out_free:
+	kfree_skb(skb);
+}
+
+/*
+ * Got a packet from ISDN-Channel.
+ */
+static void
+isdn_net_receive(struct net_device *ndev, struct sk_buff *skb)
+{
+	isdn_net_local *lp = (isdn_net_local *) ndev->priv;
+	isdn_net_local *olp = lp;	/* original 'lp' */
+#ifdef CONFIG_ISDN_X25
+	struct concap_proto *cprot = lp -> netdev -> cprot;
+#endif
+	lp->transcount += skb->len;
+
+	lp->stats.rx_packets++;
+	lp->stats.rx_bytes += skb->len;
+	if (lp->master) {
+		/* Bundling: If device is a slave-device, deliver to master, also
+		 * handle master's statistics and hangup-timeout
+		 */
+		ndev = lp->master;
+		lp = (isdn_net_local *) ndev->priv;
+		lp->stats.rx_packets++;
+		lp->stats.rx_bytes += skb->len;
+	}
+	skb->dev = ndev;
+	skb->pkt_type = PACKET_HOST;
+	skb->mac.raw = skb->data;
+#ifdef ISDN_DEBUG_NET_DUMP
+	isdn_dumppkt("R:", skb->data, skb->len, 40);
+#endif
+	switch (lp->p_encap) {
+		case ISDN_NET_ENCAP_ETHER:
+			/* Ethernet over ISDN */
+			olp->huptimer = 0;
+			lp->huptimer = 0;
+			skb->protocol = isdn_net_type_trans(skb, ndev);
+			break;
+		case ISDN_NET_ENCAP_UIHDLC:
+			/* HDLC with UI-frame (for ispa with -h1 option) */
+			olp->huptimer = 0;
+			lp->huptimer = 0;
+			skb_pull(skb, 2);
+			/* Fall through */
+		case ISDN_NET_ENCAP_RAWIP:
+			/* RAW-IP without MAC-Header */
+			olp->huptimer = 0;
+			lp->huptimer = 0;
+			skb->protocol = htons(ETH_P_IP);
+			break;
+		case ISDN_NET_ENCAP_CISCOHDLCK:
+			isdn_net_ciscohdlck_receive(lp, skb);
+			return;
+		case ISDN_NET_ENCAP_CISCOHDLC:
+			/* CISCO-HDLC IP with type field and  fake I-frame-header */
+			skb_pull(skb, 2);
+			/* Fall through */
+		case ISDN_NET_ENCAP_IPTYP:
+			/* IP with type field */
+			olp->huptimer = 0;
+			lp->huptimer = 0;
+			skb->protocol = *(unsigned short *) &(skb->data[0]);
+			skb_pull(skb, 2);
+			if (*(unsigned short *) skb->data == 0xFFFF)
+				skb->protocol = htons(ETH_P_802_3);
+			break;
+#ifdef CONFIG_ISDN_PPP
+		case ISDN_NET_ENCAP_SYNCPPP:
+			/* huptimer is done in isdn_ppp_push_higher */
+			isdn_ppp_receive(lp->netdev, olp, skb);
+			return;
+#endif
+
+		default:
+#ifdef CONFIG_ISDN_X25
+		  /* try if there are generic sync_device receiver routines */
+			if(cprot) if(cprot -> pops)
+				if( cprot -> pops -> data_ind){
+					cprot -> pops -> data_ind(cprot,skb);
+					return;
+				};
+#endif /* CONFIG_ISDN_X25 */
+			printk(KERN_WARNING "%s: unknown encapsulation, dropping\n",
+			       lp->name);
+			kfree_skb(skb);
+			return;
+	}
+
 	netif_rx(skb);
+	return;
 }
 
-struct isdn_netif_ops isdn_rawip_ops = {
-	.hard_start_xmit     = isdn_net_start_xmit,
-	.flags               = IFF_NOARP | IFF_POINTOPOINT,
-	.type                = ARPHRD_PPP,
-	.receive             = isdn_rawip_receive,
-};
+/*
+ * A packet arrived via ISDN. Search interface-chain for a corresponding
+ * interface. If found, deliver packet to receiver-function and return 1,
+ * else return 0.
+ */
+int
+isdn_net_rcv_skb(int idx, struct sk_buff *skb)
+{
+	isdn_net_dev *p = dev->rx_netdev[idx];
+
+	if (p) {
+		isdn_net_local *lp = p->local;
+		if ((lp->flags & ISDN_NET_CONNECTED) &&
+		    (!lp->dialstate)) {
+			isdn_net_receive(&p->dev, skb);
+			return 1;
+		}
+	}
+	return 0;
+}
+
+static int
+my_eth_header(struct sk_buff *skb, struct net_device *dev, unsigned short type,
+	      void *daddr, void *saddr, unsigned len)
+{
+	struct ethhdr *eth = (struct ethhdr *) skb_push(skb, ETH_HLEN);
+
+	/*
+	 * Set the protocol type. For a packet of type ETH_P_802_3 we
+	 * put the length here instead. It is up to the 802.2 layer to
+	 * carry protocol information.
+	 */
+
+	if (type != ETH_P_802_3)
+		eth->h_proto = htons(type);
+	else
+		eth->h_proto = htons(len);
+
+	/*
+	 * Set the source hardware address.
+	 */
+	if (saddr)
+		memcpy(eth->h_source, saddr, dev->addr_len);
+	else
+		memcpy(eth->h_source, dev->dev_addr, dev->addr_len);
+
+	/*
+	 * Anyway, the loopback-device should never use this function...
+	 */
+
+	if (dev->flags & (IFF_LOOPBACK | IFF_NOARP)) {
+		memset(eth->h_dest, 0, dev->addr_len);
+		return ETH_HLEN /*(dev->hard_header_len)*/;
+	}
+	if (daddr) {
+		memcpy(eth->h_dest, daddr, dev->addr_len);
+		return ETH_HLEN /*dev->hard_header_len*/;
+	}
+	return -ETH_HLEN /*dev->hard_header_len*/;
+}
+
+/*
+ *  build an header
+ *  depends on encaps that is being used.
+ */
+
+static int
+isdn_net_header(struct sk_buff *skb, struct net_device *dev, unsigned short type,
+		void *daddr, void *saddr, unsigned plen)
+{
+	isdn_net_local *lp = dev->priv;
+	unsigned char *p;
+	ushort len = 0;
+
+	switch (lp->p_encap) {
+		case ISDN_NET_ENCAP_ETHER:
+			len = my_eth_header(skb, dev, type, daddr, saddr, plen);
+			break;
+#ifdef CONFIG_ISDN_PPP
+		case ISDN_NET_ENCAP_SYNCPPP:
+			/* stick on a fake header to keep fragmentation code happy. */
+			len = IPPP_MAX_HEADER;
+			skb_push(skb,len);
+			break;
+#endif
+		case ISDN_NET_ENCAP_RAWIP:
+			printk(KERN_WARNING "isdn_net_header called with RAW_IP!\n");
+			len = 0;
+			break;
+		case ISDN_NET_ENCAP_IPTYP:
+			/* ethernet type field */
+			*((ushort *) skb_push(skb, 2)) = htons(type);
+			len = 2;
+			break;
+		case ISDN_NET_ENCAP_UIHDLC:
+			/* HDLC with UI-Frames (for ispa with -h1 option) */
+			*((ushort *) skb_push(skb, 2)) = htons(0x0103);
+			len = 2;
+			break;
+		case ISDN_NET_ENCAP_CISCOHDLC:
+		case ISDN_NET_ENCAP_CISCOHDLCK:
+			p = skb_push(skb, 4);
+			p += put_u8 (p, CISCO_ADDR_UNICAST);
+			p += put_u8 (p, CISCO_CTRL);
+			p += put_u16(p, type);
+			len = 4;
+			break;
+#ifdef CONFIG_ISDN_X25
+		default:
+		  /* try if there are generic concap protocol routines */
+			if( lp-> netdev -> cprot ){
+				printk(KERN_WARNING "isdn_net_header called with concap_proto!\n");
+				len = 0;
+				break;
+			}
+			break;
+#endif /* CONFIG_ISDN_X25 */
+	}
+	return len;
+}
+
+/* We don't need to send arp, because we have point-to-point connections. */
+static int
+isdn_net_rebuild_header(struct sk_buff *skb)
+{
+	struct net_device *dev = skb->dev;
+	isdn_net_local *lp = dev->priv;
+	int ret = 0;
+
+	if (lp->p_encap == ISDN_NET_ENCAP_ETHER) {
+		struct ethhdr *eth = (struct ethhdr *) skb->data;
+
+		/*
+		 *      Only ARP/IP is currently supported
+		 */
+
+		if (eth->h_proto != htons(ETH_P_IP)) {
+			printk(KERN_WARNING
+			       "isdn_net: %s don't know how to resolve type %d addresses?\n",
+			       dev->name, (int) eth->h_proto);
+			memcpy(eth->h_source, dev->dev_addr, dev->addr_len);
+			return 0;
+		}
+		/*
+		 *      Try to get ARP to resolve the header.
+		 */
+#ifdef CONFIG_INET
+		ret = arp_find(eth->h_dest, skb);
+#endif
+	}
+	return ret;
+}
 
-// ISDN_NET_ENCAP_ETHER
-// Ethernet over ISDN
-// ======================================================================
+/*
+ * Interface-setup. (just after registering a new interface)
+ */
+static int
+isdn_net_init(struct net_device *ndev)
+{
+	ushort max_hlhdr_len = 0;
+	isdn_net_local *lp = (isdn_net_local *) ndev->priv;
+	int drvidx, i;
+
+	ether_setup(ndev);
+	lp->org_hhc = ndev->hard_header_cache;
+	lp->org_hcu = ndev->header_cache_update;
+
+	/* Setup the generic properties */
+
+	ndev->hard_header = NULL;
+	ndev->hard_header_cache = NULL;
+	ndev->header_cache_update = NULL;
+	ndev->mtu = 1500;
+	ndev->flags = IFF_NOARP|IFF_POINTOPOINT;
+	ndev->type = ARPHRD_ETHER;
+	ndev->addr_len = ETH_ALEN;
+
+	/* for clients with MPPP maybe higher values better */
+	ndev->tx_queue_len = 30;
+
+	for (i = 0; i < ETH_ALEN; i++)
+		ndev->broadcast[i] = 0xff;
+
+	/* The ISDN-specific entries in the device structure. */
+	ndev->open = &isdn_net_open;
+	ndev->hard_start_xmit = &isdn_net_start_xmit;
+
+	/*
+	 *  up till binding we ask the protocol layer to reserve as much
+	 *  as we might need for HL layer
+	 */
+
+	for (drvidx = 0; drvidx < ISDN_MAX_DRIVERS; drvidx++)
+		if (dev->drv[drvidx])
+			if (max_hlhdr_len < dev->drv[drvidx]->interface->hl_hdrlen)
+				max_hlhdr_len = dev->drv[drvidx]->interface->hl_hdrlen;
+
+	ndev->hard_header_len = ETH_HLEN + max_hlhdr_len;
+	ndev->stop = &isdn_net_close;
+	ndev->get_stats = &isdn_net_get_stats;
+	ndev->rebuild_header = &isdn_net_rebuild_header;
+	ndev->do_ioctl = NULL;
+	return 0;
+}
+
+static void
+isdn_net_swapbind(int drvidx)
+{
+	isdn_net_dev *p;
+
+#ifdef ISDN_DEBUG_NET_ICALL
+	printk(KERN_DEBUG "n_fi: swapping ch of %d\n", drvidx);
+#endif
+	p = dev->netdev;
+	while (p) {
+		if (p->local->pre_device == drvidx)
+			switch (p->local->pre_channel) {
+				case 0:
+					p->local->pre_channel = 1;
+					break;
+				case 1:
+					p->local->pre_channel = 0;
+					break;
+			}
+		p = (isdn_net_dev *) p->next;
+	}
+}
 
 static void
-isdn_ether_receive(isdn_net_local *lp, isdn_net_dev *idev, 
-		   struct sk_buff *skb)
+isdn_net_swap_usage(int i1, int i2)
+{
+	int u1 = dev->usage[i1] & ISDN_USAGE_EXCLUSIVE;
+	int u2 = dev->usage[i2] & ISDN_USAGE_EXCLUSIVE;
+
+#ifdef ISDN_DEBUG_NET_ICALL
+	printk(KERN_DEBUG "n_fi: usage of %d and %d\n", i1, i2);
+#endif
+	dev->usage[i1] &= ~ISDN_USAGE_EXCLUSIVE;
+	dev->usage[i1] |= u2;
+	dev->usage[i2] &= ~ISDN_USAGE_EXCLUSIVE;
+	dev->usage[i2] |= u1;
+	isdn_info_update();
+}
+
+/*
+ * An incoming call-request has arrived.
+ * Search the interface-chain for an appropriate interface.
+ * If found, connect the interface to the ISDN-channel and initiate
+ * D- and B-Channel-setup. If secure-flag is set, accept only
+ * configured phone-numbers. If callback-flag is set, initiate
+ * callback-dialing.
+ *
+ * Return-Value: 0 = No appropriate interface for this call.
+ *               1 = Call accepted
+ *               2 = Reject call, wait cbdelay, then call back
+ *               3 = Reject call
+ *               4 = Wait cbdelay, then call back
+ *               5 = No appropriate interface for this call,
+ *                   would eventually match if CID was longer.
+ */
+
+int
+isdn_net_find_icall(int di, int ch, int idx, setup_parm *setup)
 {
-	isdn_netif_rx(idev, skb, eth_type_trans(skb, &lp->dev));
+	char *eaz;
+	int si1;
+	int si2;
+	int ematch;
+	int wret;
+	int swapped;
+	int sidx = 0;
+	u_long flags;
+	isdn_net_dev *p;
+	isdn_net_phone *n;
+	char nr[32];
+	char *my_eaz;
+
+	/* Search name in netdev-chain */
+	if (!setup->phone[0]) {
+		nr[0] = '0';
+		nr[1] = '\0';
+		printk(KERN_INFO "isdn_net: Incoming call without OAD, assuming '0'\n");
+	} else
+		strcpy(nr, setup->phone);
+	si1 = (int) setup->si1;
+	si2 = (int) setup->si2;
+	if (!setup->eazmsn[0]) {
+		printk(KERN_WARNING "isdn_net: Incoming call without CPN, assuming '0'\n");
+		eaz = "0";
+	} else
+		eaz = setup->eazmsn;
+	if (dev->net_verbose > 1)
+		printk(KERN_INFO "isdn_net: call from %s,%d,%d -> %s\n", nr, si1, si2, eaz);
+	/* Accept DATA and VOICE calls at this stage
+	 * local eaz is checked later for allowed call types
+	 */
+	if ((si1 != 7) && (si1 != 1)) {
+		if (dev->net_verbose > 1)
+			printk(KERN_INFO "isdn_net: Service-Indicator not 1 or 7, ignored\n");
+		return 0;
+	}
+	n = (isdn_net_phone *) 0;
+	p = dev->netdev;
+	ematch = wret = swapped = 0;
+#ifdef ISDN_DEBUG_NET_ICALL
+	printk(KERN_DEBUG "n_fi: di=%d ch=%d idx=%d usg=%d\n", di, ch, idx,
+		dev->usage[idx]);
+#endif
+	while (p) {
+		int matchret;
+		isdn_net_local *lp = p->local;
+
+		/* If last check has triggered as binding-swap, revert it */
+		switch (swapped) {
+			case 2:
+				isdn_net_swap_usage(idx, sidx);
+				/* fall through */
+			case 1:
+				isdn_net_swapbind(di);
+				break;
+		}
+		swapped = 0;
+                /* check acceptable call types for DOV */
+                my_eaz = isdn_map_eaz2msn(lp->msn, di);
+                if (si1 == 1) { /* it's a DOV call, check if we allow it */
+                        if (*my_eaz == 'v' || *my_eaz == 'V' ||
+			    *my_eaz == 'b' || *my_eaz == 'B')
+                                my_eaz++; /* skip to allow a match */
+                        else
+                                my_eaz = 0; /* force non match */
+                } else { /* it's a DATA call, check if we allow it */
+                        if (*my_eaz == 'b' || *my_eaz == 'B')
+                                my_eaz++; /* skip to allow a match */
+                }
+                if (my_eaz)
+                        matchret = isdn_msncmp(eaz, my_eaz);
+                else
+                        matchret = 1;
+                if (!matchret)
+                        ematch = 1;
+
+		/* Remember if more numbers eventually can match */
+		if (matchret > wret)
+			wret = matchret;
+#ifdef ISDN_DEBUG_NET_ICALL
+		printk(KERN_DEBUG "n_fi: if='%s', l.msn=%s, l.flags=%d, l.dstate=%d\n",
+		       lp->name, lp->msn, lp->flags, lp->dialstate);
+#endif
+		if ((!matchret) &&                                        /* EAZ is matching   */
+		    (((!(lp->flags & ISDN_NET_CONNECTED)) &&              /* but not connected */
+		      (USG_NONE(dev->usage[idx]))) ||                     /* and ch. unused or */
+		     ((((lp->dialstate == 4) || (lp->dialstate == 12)) && /* if dialing        */
+		       (!(lp->flags & ISDN_NET_CALLBACK)))                /* but no callback   */
+		     )))
+			 {
+#ifdef ISDN_DEBUG_NET_ICALL
+			printk(KERN_DEBUG "n_fi: match1, pdev=%d pch=%d\n",
+			       lp->pre_device, lp->pre_channel);
+#endif
+			if (dev->usage[idx] & ISDN_USAGE_EXCLUSIVE) {
+				if ((lp->pre_channel != ch) ||
+				    (lp->pre_device != di)) {
+					/* Here we got a problem:
+					 * If using an ICN-Card, an incoming call is always signaled on
+					 * on the first channel of the card, if both channels are
+					 * down. However this channel may be bound exclusive. If the
+					 * second channel is free, this call should be accepted.
+					 * The solution is horribly but it runs, so what:
+					 * We exchange the exclusive bindings of the two channels, the
+					 * corresponding variables in the interface-structs.
+					 */
+					if (ch == 0) {
+						sidx = isdn_dc2minor(di, 1);
+#ifdef ISDN_DEBUG_NET_ICALL
+						printk(KERN_DEBUG "n_fi: ch is 0\n");
+#endif
+						if (USG_NONE(dev->usage[sidx])) {
+							/* Second Channel is free, now see if it is bound
+							 * exclusive too. */
+							if (dev->usage[sidx] & ISDN_USAGE_EXCLUSIVE) {
+#ifdef ISDN_DEBUG_NET_ICALL
+								printk(KERN_DEBUG "n_fi: 2nd channel is down and bound\n");
+#endif
+								/* Yes, swap bindings only, if the original
+								 * binding is bound to channel 1 of this driver */
+								if ((lp->pre_device == di) &&
+								    (lp->pre_channel == 1)) {
+									isdn_net_swapbind(di);
+									swapped = 1;
+								} else {
+									/* ... else iterate next device */
+									p = (isdn_net_dev *) p->next;
+									continue;
+								}
+							} else {
+#ifdef ISDN_DEBUG_NET_ICALL
+								printk(KERN_DEBUG "n_fi: 2nd channel is down and unbound\n");
+#endif
+								/* No, swap always and swap excl-usage also */
+								isdn_net_swap_usage(idx, sidx);
+								isdn_net_swapbind(di);
+								swapped = 2;
+							}
+							/* Now check for exclusive binding again */
+#ifdef ISDN_DEBUG_NET_ICALL
+							printk(KERN_DEBUG "n_fi: final check\n");
+#endif
+							if ((dev->usage[idx] & ISDN_USAGE_EXCLUSIVE) &&
+							    ((lp->pre_channel != ch) ||
+							     (lp->pre_device != di))) {
+#ifdef ISDN_DEBUG_NET_ICALL
+								printk(KERN_DEBUG "n_fi: final check failed\n");
+#endif
+								p = (isdn_net_dev *) p->next;
+								continue;
+							}
+						}
+					} else {
+						/* We are already on the second channel, so nothing to do */
+#ifdef ISDN_DEBUG_NET_ICALL
+						printk(KERN_DEBUG "n_fi: already on 2nd channel\n");
+#endif
+					}
+				}
+			}
+#ifdef ISDN_DEBUG_NET_ICALL
+			printk(KERN_DEBUG "n_fi: match2\n");
+#endif
+			n = lp->phone[0];
+			if (lp->flags & ISDN_NET_SECURE) {
+				while (n) {
+					if (!isdn_msncmp(nr, n->num))
+						break;
+					n = (isdn_net_phone *) n->next;
+				}
+			}
+			if (n || (!(lp->flags & ISDN_NET_SECURE))) {
+#ifdef ISDN_DEBUG_NET_ICALL
+				printk(KERN_DEBUG "n_fi: match3\n");
+#endif
+				/* matching interface found */
+
+				/*
+				 * Is the state STOPPED?
+				 * If so, no dialin is allowed,
+				 * so reject actively.
+				 * */
+				if (ISDN_NET_DIALMODE(*lp) == ISDN_NET_DM_OFF) {
+					printk(KERN_INFO "incoming call, interface %s `stopped' -> rejected\n",
+					       lp->name);
+					return 3;
+				}
+				/*
+				 * Is the interface up?
+				 * If not, reject the call actively.
+				 */
+				if (!isdn_net_device_started(p)) {
+					printk(KERN_INFO "%s: incoming call, interface down -> rejected\n",
+					       lp->name);
+					return 3;
+				}
+				/* Interface is up, now see if it's a slave. If so, see if
+				 * it's master and parent slave is online. If not, reject the call.
+				 */
+				if (lp->master) {
+					isdn_net_local *mlp = (isdn_net_local *) lp->master->priv;
+					printk(KERN_DEBUG "ICALLslv: %s\n", lp->name);
+					printk(KERN_DEBUG "master=%s\n", mlp->name);
+					if (mlp->flags & ISDN_NET_CONNECTED) {
+						printk(KERN_DEBUG "master online\n");
+						/* Master is online, find parent-slave (master if first slave) */
+						while (mlp->slave) {
+							if ((isdn_net_local *) mlp->slave->priv == lp)
+								break;
+							mlp = (isdn_net_local *) mlp->slave->priv;
+						}
+					} else
+						printk(KERN_DEBUG "master offline\n");
+					/* Found parent, if it's offline iterate next device */
+					printk(KERN_DEBUG "mlpf: %d\n", mlp->flags & ISDN_NET_CONNECTED);
+					if (!(mlp->flags & ISDN_NET_CONNECTED)) {
+						p = (isdn_net_dev *) p->next;
+						continue;
+					}
+				} 
+				if (lp->flags & ISDN_NET_CALLBACK) {
+					int chi;
+					/*
+					 * Is the state MANUAL?
+					 * If so, no callback can be made,
+					 * so reject actively.
+					 * */
+					if (ISDN_NET_DIALMODE(*lp) == ISDN_NET_DM_OFF) {
+						printk(KERN_INFO "incoming call for callback, interface %s `off' -> rejected\n",
+						       lp->name);
+						return 3;
+					}
+					printk(KERN_DEBUG "%s: call from %s -> %s, start callback\n",
+					       lp->name, nr, eaz);
+					if (lp->phone[1]) {
+						/* Grab a free ISDN-Channel */
+						spin_lock_irqsave(&dev->lock, flags);
+						if ((chi = 
+							isdn_get_free_channel(
+								ISDN_USAGE_NET,
+								lp->l2_proto,
+								lp->l3_proto,
+							  	lp->pre_device,
+						 		lp->pre_channel,
+						 		lp->msn)
+								) < 0) {
+
+							printk(KERN_WARNING "isdn_net_find_icall: No channel for %s\n", lp->name);
+							spin_unlock_irqrestore(&dev->lock, flags);
+							return 0;
+						}
+						/* Setup dialstate. */
+						lp->dtimer = 0;
+						lp->dialstate = 11;
+						/* Connect interface with channel */
+						isdn_net_bind_channel(lp, chi);
+#ifdef CONFIG_ISDN_PPP
+						if (lp->p_encap == ISDN_NET_ENCAP_SYNCPPP)
+							if (isdn_ppp_bind(lp) < 0) {
+								spin_unlock_irqrestore(&dev->lock, flags);
+								isdn_net_unbind_channel(lp);
+								return 0;
+							}
+#endif
+						spin_unlock_irqrestore(&dev->lock, flags);
+						/* Initiate dialing by returning 2 or 4 */
+						return (lp->flags & ISDN_NET_CBHUP) ? 2 : 4;
+					} else
+						printk(KERN_WARNING "isdn_net: %s: No phone number\n", lp->name);
+					return 0;
+				} else {
+					printk(KERN_DEBUG "%s: call from %s -> %s accepted\n", lp->name, nr,
+					       eaz);
+					/* if this interface is dialing, it does it probably on a different
+					   device, so free this device */
+					if ((lp->dialstate == 4) || (lp->dialstate == 12)) {
+#ifdef CONFIG_ISDN_PPP
+						if (lp->p_encap == ISDN_NET_ENCAP_SYNCPPP)
+							isdn_ppp_free(lp);
+#endif
+						isdn_net_lp_disconnected(lp);
+						isdn_free_channel(lp->isdn_device, lp->isdn_channel,
+							 ISDN_USAGE_NET);
+					}
+					spin_lock_irqsave(&dev->lock, flags);
+					dev->usage[idx] &= ISDN_USAGE_EXCLUSIVE;
+					dev->usage[idx] |= ISDN_USAGE_NET;
+					strcpy(dev->num[idx], nr);
+					isdn_info_update();
+					dev->st_netdev[idx] = lp->netdev;
+					lp->isdn_device = di;
+					lp->isdn_channel = ch;
+					lp->ppp_slot = -1;
+					lp->flags |= ISDN_NET_CONNECTED;
+					lp->dialstate = 7;
+					lp->dtimer = 0;
+					lp->outgoing = 0;
+					lp->huptimer = 0;
+					lp->hupflags |= ISDN_WAITCHARGE;
+					lp->hupflags &= ~ISDN_HAVECHARGE;
+#ifdef CONFIG_ISDN_PPP
+					if (lp->p_encap == ISDN_NET_ENCAP_SYNCPPP) {
+						if (isdn_ppp_bind(lp) < 0) {
+							isdn_net_unbind_channel(lp);
+							spin_unlock_irqrestore(&dev->lock, flags);
+							return 0;
+						}
+					}
+#endif
+					spin_unlock_irqrestore(&dev->lock, flags);
+					return 1;
+				}
+			}
+		}
+		p = (isdn_net_dev *) p->next;
+	}
+	/* If none of configured EAZ/MSN matched and not verbose, be silent */
+	if (!ematch || dev->net_verbose)
+		printk(KERN_INFO "isdn_net: call from %s -> %d %s ignored\n", nr, di, eaz);
+	return (wret == 2)?5:0;
 }
 
+/*
+ * Search list of net-interfaces for an interface with given name.
+ */
+isdn_net_dev *
+isdn_net_findif(char *name)
+{
+	isdn_net_dev *p = dev->netdev;
+
+	while (p) {
+		if (!strcmp(p->local->name, name))
+			return p;
+		p = (isdn_net_dev *) p->next;
+	}
+	return (isdn_net_dev *) NULL;
+}
+
+/*
+ * Force a net-interface to dial out.
+ * This is called from the userlevel-routine below or
+ * from isdn_net_start_xmit().
+ */
+int
+isdn_net_force_dial_lp(isdn_net_local * lp)
+{
+	if ((!(lp->flags & ISDN_NET_CONNECTED)) && !lp->dialstate) {
+		int chi;
+		if (lp->phone[1]) {
+			ulong flags;
+
+			/* Grab a free ISDN-Channel */
+			spin_lock_irqsave(&dev->lock, flags);
+			if ((chi = isdn_get_free_channel(
+					ISDN_USAGE_NET,
+					lp->l2_proto,
+					lp->l3_proto,
+					lp->pre_device,
+					lp->pre_channel,
+					lp->msn)) < 0) {
+				printk(KERN_WARNING "isdn_net_force_dial: No channel for %s\n", lp->name);
+				spin_unlock_irqrestore(&dev->lock, flags);
+				return -EAGAIN;
+			}
+			lp->dialstate = 1;
+			/* Connect interface with channel */
+			isdn_net_bind_channel(lp, chi);
+#ifdef CONFIG_ISDN_PPP
+			if (lp->p_encap == ISDN_NET_ENCAP_SYNCPPP)
+				if (isdn_ppp_bind(lp) < 0) {
+					isdn_net_unbind_channel(lp);
+					spin_unlock_irqrestore(&dev->lock, flags);
+					return -EAGAIN;
+				}
+#endif
+			/* Initiate dialing */
+			spin_unlock_irqrestore(&dev->lock, flags);
+			isdn_net_dial();
+			return 0;
+		} else
+			return -EINVAL;
+	} else
+		return -EBUSY;
+}
+
+/*
+ * This is called from certain upper protocol layers (multilink ppp
+ * and x25iface encapsulation module) that want to initiate dialing
+ * themselves.
+ */
+int
+isdn_net_dial_req(isdn_net_local * lp)
+{
+	/* is there a better error code? */
+	if (!(ISDN_NET_DIALMODE(*lp) == ISDN_NET_DM_AUTO)) return -EBUSY;
+
+	return isdn_net_force_dial_lp(lp);
+}
+
+/*
+ * Force a net-interface to dial out.
+ * This is always called from within userspace (ISDN_IOCTL_NET_DIAL).
+ */
+int
+isdn_net_force_dial(char *name)
+{
+	isdn_net_dev *p = isdn_net_findif(name);
+
+	if (!p)
+		return -ENODEV;
+	return (isdn_net_force_dial_lp(p->local));
+}
+
+/*
+ * Allocate a new network-interface and initialize its data structures.
+ */
+char *
+isdn_net_new(char *name, struct net_device *master)
+{
+	isdn_net_dev *netdev;
+
+	/* Avoid creating an existing interface */
+	if (isdn_net_findif(name)) {
+		printk(KERN_WARNING "isdn_net: interface %s already exists\n", name);
+		return NULL;
+	}
+	if (!(netdev = (isdn_net_dev *) kmalloc(sizeof(isdn_net_dev), GFP_KERNEL))) {
+		printk(KERN_WARNING "isdn_net: Could not allocate net-device\n");
+		return NULL;
+	}
+	memset(netdev, 0, sizeof(isdn_net_dev));
+	if (!(netdev->local = (isdn_net_local *) kmalloc(sizeof(isdn_net_local), GFP_KERNEL))) {
+		printk(KERN_WARNING "isdn_net: Could not allocate device locals\n");
+		kfree(netdev);
+		return NULL;
+	}
+	memset(netdev->local, 0, sizeof(isdn_net_local));
+	if (name == NULL)
+		strcpy(netdev->local->name, "         ");
+	else
+		strcpy(netdev->local->name, name);
+	strcpy(netdev->dev.name, netdev->local->name);
+	netdev->dev.priv = netdev->local;
+	netdev->dev.init = isdn_net_init;
+	netdev->local->p_encap = ISDN_NET_ENCAP_RAWIP;
+	if (master) {
+		/* Device shall be a slave */
+		struct net_device *p = (((isdn_net_local *) master->priv)->slave);
+		struct net_device *q = master;
+
+		netdev->local->master = master;
+		/* Put device at end of slave-chain */
+		while (p) {
+			q = p;
+			p = (((isdn_net_local *) p->priv)->slave);
+		}
+		((isdn_net_local *) q->priv)->slave = &(netdev->dev);
+	} else {
+		/* Device shall be a master */
+		/*
+		 * Watchdog timer (currently) for master only.
+		 */
+		netdev->dev.tx_timeout = isdn_net_tx_timeout;
+		netdev->dev.watchdog_timeo = ISDN_NET_TX_TIMEOUT;
+		if (register_netdev(&netdev->dev) != 0) {
+			printk(KERN_WARNING "isdn_net: Could not register net-device\n");
+			kfree(netdev->local);
+			kfree(netdev);
+			return NULL;
+		}
+	}
+	netdev->local->magic = ISDN_NET_MAGIC;
+
+	netdev->queue = netdev->local;
+	spin_lock_init(&netdev->queue_lock);
+
+	netdev->local->last = netdev->local;
+	netdev->local->netdev = netdev;
+	netdev->local->next = netdev->local;
+
+	INIT_WORK(&netdev->local->tqueue, (void *)(void *) isdn_net_softint, netdev->local);
+	spin_lock_init(&netdev->local->xmit_lock);
+
+	netdev->local->isdn_device = -1;
+	netdev->local->isdn_channel = -1;
+	netdev->local->pre_device = -1;
+	netdev->local->pre_channel = -1;
+	netdev->local->exclusive = -1;
+	netdev->local->ppp_slot = -1;
+	netdev->local->pppbind = -1;
+	skb_queue_head_init(&netdev->local->super_tx_queue);
+	netdev->local->l2_proto = ISDN_PROTO_L2_X75I;
+	netdev->local->l3_proto = ISDN_PROTO_L3_TRANS;
+	netdev->local->triggercps = 6000;
+	netdev->local->slavedelay = 10 * HZ;
+	netdev->local->hupflags = ISDN_INHUP;	/* Do hangup even on incoming calls */
+	netdev->local->onhtime = 10;	/* Default hangup-time for saving costs
+	   of those who forget configuring this */
+	netdev->local->dialmax = 1;
+	netdev->local->flags = ISDN_NET_CBHUP | ISDN_NET_DM_MANUAL;	/* Hangup before Callback, manual dial */
+	netdev->local->cbdelay = 25;	/* Wait 5 secs before Callback */
+	netdev->local->dialtimeout = -1;  /* Infinite Dial-Timeout */
+	netdev->local->dialwait = 5 * HZ; /* Wait 5 sec. after failed dial */
+	netdev->local->dialstarted = 0;   /* Jiffies of last dial-start */
+	netdev->local->dialwait_timer = 0;  /* Jiffies of earliest next dial-start */
+
+	/* Put into to netdev-chain */
+	netdev->next = (void *) dev->netdev;
+	dev->netdev = netdev;
+	return netdev->dev.name;
+}
+
+char *
+isdn_net_newslave(char *parm)
+{
+	char *p = strchr(parm, ',');
+	isdn_net_dev *n;
+	char newname[10];
+
+	if (p) {
+		/* Slave-Name MUST not be empty */
+		if (!strlen(p + 1))
+			return NULL;
+		strcpy(newname, p + 1);
+		*p = 0;
+		/* Master must already exist */
+		if (!(n = isdn_net_findif(parm)))
+			return NULL;
+		/* Master must be a real interface, not a slave */
+		if (n->local->master)
+			return NULL;
+		/* Master must not be started yet */
+		if (isdn_net_device_started(n)) 
+			return NULL;
+		return (isdn_net_new(newname, &(n->dev)));
+	}
+	return NULL;
+}
+
+/*
+ * Set interface-parameters.
+ * Always set all parameters, so the user-level application is responsible
+ * for not overwriting existing setups. It has to get the current
+ * setup first, if only selected parameters are to be changed.
+ */
+int
+isdn_net_setcfg(isdn_net_ioctl_cfg * cfg)
+{
+	isdn_net_dev *p = isdn_net_findif(cfg->name);
+	ulong features;
+	int i;
+	int drvidx;
+	int chidx;
+	char drvid[25];
+
+	if (p) {
+		isdn_net_local *lp = p->local;
+
+		/* See if any registered driver supports the features we want */
+		features = ((1 << cfg->l2_proto) << ISDN_FEATURE_L2_SHIFT) |
+			((1 << cfg->l3_proto) << ISDN_FEATURE_L3_SHIFT);
+		for (i = 0; i < ISDN_MAX_DRIVERS; i++)
+			if (dev->drv[i])
+				if ((dev->drv[i]->interface->features & features) == features)
+					break;
+		if (i == ISDN_MAX_DRIVERS) {
+			printk(KERN_WARNING "isdn_net: No driver with selected features\n");
+			return -ENODEV;
+		}
+		if (lp->p_encap != cfg->p_encap){
+#ifdef CONFIG_ISDN_X25
+			struct concap_proto * cprot = p -> cprot;
+#endif
+			if (isdn_net_device_started(p)) {
+				printk(KERN_WARNING "%s: cannot change encap when if is up\n",
+				       lp->name);
+				return -EBUSY;
+			}
+#ifdef CONFIG_ISDN_X25
+			if( cprot && cprot -> pops )
+				cprot -> pops -> proto_del ( cprot );
+			p -> cprot = NULL;
+			lp -> dops = NULL;
+			/* ... ,  prepare for configuration of new one ... */
+			switch ( cfg -> p_encap ){
+			case ISDN_NET_ENCAP_X25IFACE:
+				lp -> dops = &isdn_concap_reliable_dl_dops;
+			}
+			/* ... and allocate new one ... */
+			p -> cprot = isdn_concap_new( cfg -> p_encap );
+			/* p -> cprot == NULL now if p_encap is not supported
+			   by means of the concap_proto mechanism */
+			/* the protocol is not configured yet; this will
+			   happen later when isdn_net_reset() is called */
+#endif
+		}
+		switch ( cfg->p_encap ) {
+		case ISDN_NET_ENCAP_SYNCPPP:
+#ifndef CONFIG_ISDN_PPP
+			printk(KERN_WARNING "%s: SyncPPP support not configured\n",
+			       lp->name);
+			return -EINVAL;
+#else
+			p->dev.type = ARPHRD_PPP;	/* change ARP type */
+			p->dev.addr_len = 0;
+			p->dev.do_ioctl = isdn_ppp_dev_ioctl;
+#endif
+			break;
+		case ISDN_NET_ENCAP_X25IFACE:
+#ifndef CONFIG_ISDN_X25
+			printk(KERN_WARNING "%s: isdn-x25 support not configured\n",
+			       p->local->name);
+			return -EINVAL;
+#else
+			p->dev.type = ARPHRD_X25;	/* change ARP type */
+			p->dev.addr_len = 0;
+#endif
+			break;
+		case ISDN_NET_ENCAP_CISCOHDLCK:
+			p->dev.do_ioctl = isdn_ciscohdlck_dev_ioctl;
+			break;
+		default:
+			if( cfg->p_encap >= 0 &&
+			    cfg->p_encap <= ISDN_NET_ENCAP_MAX_ENCAP )
+				break;
+			printk(KERN_WARNING
+			       "%s: encapsulation protocol %d not supported\n",
+			       p->local->name, cfg->p_encap);
+			return -EINVAL;
+		}
+		if (strlen(cfg->drvid)) {
+			/* A bind has been requested ... */
+			char *c,
+			*e;
+
+			drvidx = -1;
+			chidx = -1;
+			strcpy(drvid, cfg->drvid);
+			if ((c = strchr(drvid, ','))) {
+				/* The channel-number is appended to the driver-Id with a comma */
+				chidx = (int) simple_strtoul(c + 1, &e, 10);
+				if (e == c)
+					chidx = -1;
+				*c = '\0';
+			}
+			for (i = 0; i < ISDN_MAX_DRIVERS; i++)
+				/* Lookup driver-Id in array */
+				if (!(strcmp(dev->drvid[i], drvid))) {
+					drvidx = i;
+					break;
+				}
+			if ((drvidx == -1) || (chidx == -1))
+				/* Either driver-Id or channel-number invalid */
+				return -ENODEV;
+		} else {
+			/* Parameters are valid, so get them */
+			drvidx = lp->pre_device;
+			chidx = lp->pre_channel;
+		}
+		if (cfg->exclusive > 0) {
+			unsigned long flags;
+
+			/* If binding is exclusive, try to grab the channel */
+			spin_lock_irqsave(&dev->lock, flags);
+			if ((i = isdn_get_free_channel(ISDN_USAGE_NET,
+				lp->l2_proto, lp->l3_proto, drvidx,
+				chidx, lp->msn)) < 0) {
+				/* Grab failed, because desired channel is in use */
+				lp->exclusive = -1;
+				spin_unlock_irqrestore(&dev->lock, flags);
+				return -EBUSY;
+			}
+			/* All went ok, so update isdninfo */
+			dev->usage[i] = ISDN_USAGE_EXCLUSIVE;
+			isdn_info_update();
+			spin_unlock_irqrestore(&dev->lock, flags);
+			lp->exclusive = i;
+		} else {
+			/* Non-exclusive binding or unbind. */
+			lp->exclusive = -1;
+			if ((lp->pre_device != -1) && (cfg->exclusive == -1)) {
+				isdn_unexclusive_channel(lp->pre_device, lp->pre_channel);
+				isdn_free_channel(lp->pre_device, lp->pre_channel, ISDN_USAGE_NET);
+				drvidx = -1;
+				chidx = -1;
+			}
+		}
+		strcpy(lp->msn, cfg->eaz);
+		lp->pre_device = drvidx;
+		lp->pre_channel = chidx;
+		lp->onhtime = cfg->onhtime;
+		lp->charge = cfg->charge;
+		lp->l2_proto = cfg->l2_proto;
+		lp->l3_proto = cfg->l3_proto;
+		lp->cbdelay = cfg->cbdelay;
+		lp->dialmax = cfg->dialmax;
+		lp->triggercps = cfg->triggercps;
+		lp->slavedelay = cfg->slavedelay * HZ;
+		lp->pppbind = cfg->pppbind;
+		lp->dialtimeout = cfg->dialtimeout >= 0 ? cfg->dialtimeout * HZ : -1;
+		lp->dialwait = cfg->dialwait * HZ;
+		if (cfg->secure)
+			lp->flags |= ISDN_NET_SECURE;
+		else
+			lp->flags &= ~ISDN_NET_SECURE;
+		if (cfg->cbhup)
+			lp->flags |= ISDN_NET_CBHUP;
+		else
+			lp->flags &= ~ISDN_NET_CBHUP;
+		switch (cfg->callback) {
+			case 0:
+				lp->flags &= ~(ISDN_NET_CALLBACK | ISDN_NET_CBOUT);
+				break;
+			case 1:
+				lp->flags |= ISDN_NET_CALLBACK;
+				lp->flags &= ~ISDN_NET_CBOUT;
+				break;
+			case 2:
+				lp->flags |= ISDN_NET_CBOUT;
+				lp->flags &= ~ISDN_NET_CALLBACK;
+				break;
+		}
+		lp->flags &= ~ISDN_NET_DIALMODE_MASK;	/* first all bits off */
+		if (cfg->dialmode && !(cfg->dialmode & ISDN_NET_DIALMODE_MASK)) {
+			/* old isdnctrl version, where only 0 or 1 is given */
+			printk(KERN_WARNING
+			     "Old isdnctrl version detected! Please update.\n");
+			lp->flags |= ISDN_NET_DM_OFF; /* turn on `off' bit */
+		}
+		else {
+			lp->flags |= cfg->dialmode;  /* turn on selected bits */
+		}
+		if (cfg->chargehup)
+			lp->hupflags |= ISDN_CHARGEHUP;
+		else
+			lp->hupflags &= ~ISDN_CHARGEHUP;
+		if (cfg->ihup)
+			lp->hupflags |= ISDN_INHUP;
+		else
+			lp->hupflags &= ~ISDN_INHUP;
+		if (cfg->chargeint > 10) {
+			lp->hupflags |= ISDN_CHARGEHUP | ISDN_HAVECHARGE | ISDN_MANCHARGE;
+			lp->chargeint = cfg->chargeint * HZ;
+		}
+		if (cfg->p_encap != lp->p_encap) {
+			if (cfg->p_encap == ISDN_NET_ENCAP_RAWIP) {
+				p->dev.hard_header = NULL;
+				p->dev.hard_header_cache = NULL;
+				p->dev.header_cache_update = NULL;
+				p->dev.flags = IFF_NOARP|IFF_POINTOPOINT;
+			} else {
+				p->dev.hard_header = isdn_net_header;
+				if (cfg->p_encap == ISDN_NET_ENCAP_ETHER) {
+					p->dev.hard_header_cache = lp->org_hhc;
+					p->dev.header_cache_update = lp->org_hcu;
+					p->dev.flags = IFF_BROADCAST | IFF_MULTICAST;
+				} else {
+					p->dev.hard_header_cache = NULL;
+					p->dev.header_cache_update = NULL;
+					p->dev.flags = IFF_NOARP|IFF_POINTOPOINT;
+				}
+			}
+		}
+		lp->p_encap = cfg->p_encap;
+		return 0;
+	}
+	return -ENODEV;
+}
+
+/*
+ * Perform get-interface-parameters.ioctl
+ */
+int
+isdn_net_getcfg(isdn_net_ioctl_cfg * cfg)
+{
+	isdn_net_dev *p = isdn_net_findif(cfg->name);
+
+	if (p) {
+		isdn_net_local *lp = p->local;
+
+		strcpy(cfg->eaz, lp->msn);
+		cfg->exclusive = lp->exclusive;
+		if (lp->pre_device >= 0) {
+			sprintf(cfg->drvid, "%s,%d", dev->drvid[lp->pre_device],
+				lp->pre_channel);
+		} else
+			cfg->drvid[0] = '\0';
+		cfg->onhtime = lp->onhtime;
+		cfg->charge = lp->charge;
+		cfg->l2_proto = lp->l2_proto;
+		cfg->l3_proto = lp->l3_proto;
+		cfg->p_encap = lp->p_encap;
+		cfg->secure = (lp->flags & ISDN_NET_SECURE) ? 1 : 0;
+		cfg->callback = 0;
+		if (lp->flags & ISDN_NET_CALLBACK)
+			cfg->callback = 1;
+		if (lp->flags & ISDN_NET_CBOUT)
+			cfg->callback = 2;
+		cfg->cbhup = (lp->flags & ISDN_NET_CBHUP) ? 1 : 0;
+		cfg->dialmode = lp->flags & ISDN_NET_DIALMODE_MASK;
+		cfg->chargehup = (lp->hupflags & 4) ? 1 : 0;
+		cfg->ihup = (lp->hupflags & 8) ? 1 : 0;
+		cfg->cbdelay = lp->cbdelay;
+		cfg->dialmax = lp->dialmax;
+		cfg->triggercps = lp->triggercps;
+		cfg->slavedelay = lp->slavedelay / HZ;
+		cfg->chargeint = (lp->hupflags & ISDN_CHARGEHUP) ?
+		    (lp->chargeint / HZ) : 0;
+		cfg->pppbind = lp->pppbind;
+		cfg->dialtimeout = lp->dialtimeout >= 0 ? lp->dialtimeout / HZ : -1;
+		cfg->dialwait = lp->dialwait / HZ;
+		if (lp->slave)
+			strcpy(cfg->slave, ((isdn_net_local *) lp->slave->priv)->name);
+		else
+			cfg->slave[0] = '\0';
+		if (lp->master)
+			strcpy(cfg->master, ((isdn_net_local *) lp->master->priv)->name);
+		else
+			cfg->master[0] = '\0';
+		return 0;
+	}
+	return -ENODEV;
+}
+
+/*
+ * Add a phone-number to an interface.
+ */
+int
+isdn_net_addphone(isdn_net_ioctl_phone * phone)
+{
+	isdn_net_dev *p = isdn_net_findif(phone->name);
+	isdn_net_phone *n;
+
+	if (p) {
+		if (!(n = (isdn_net_phone *) kmalloc(sizeof(isdn_net_phone), GFP_KERNEL)))
+			return -ENOMEM;
+		strcpy(n->num, phone->phone);
+		n->next = p->local->phone[phone->outgoing & 1];
+		p->local->phone[phone->outgoing & 1] = n;
+		return 0;
+	}
+	return -ENODEV;
+}
+
+/*
+ * Copy a string of all phone-numbers of an interface to user space.
+ * This might sleep and must be called with the isdn semaphore down.
+ */
+int
+isdn_net_getphones(isdn_net_ioctl_phone * phone, char *phones)
+{
+	isdn_net_dev *p = isdn_net_findif(phone->name);
+	int inout = phone->outgoing & 1;
+	int more = 0;
+	int count = 0;
+	isdn_net_phone *n;
+
+	if (!p)
+		return -ENODEV;
+	inout &= 1;
+	for (n = p->local->phone[inout]; n; n = n->next) {
+		if (more) {
+			put_user(' ', phones++);
+			count++;
+		}
+		if (copy_to_user(phones, n->num, strlen(n->num) + 1)) {
+			return -EFAULT;
+		}
+		phones += strlen(n->num);
+		count += strlen(n->num);
+		more = 1;
+	}
+	put_user(0, phones);
+	count++;
+	return count;
+}
+
+/*
+ * Copy a string containing the peer's phone number of a connected interface
+ * to user space.
+ */
+int
+isdn_net_getpeer(isdn_net_ioctl_phone *phone, isdn_net_ioctl_phone *peer)
+{
+	isdn_net_dev *p = isdn_net_findif(phone->name);
+	int ch, dv, idx;
+
+	if (!p) return -ENODEV;
+	/*
+	 * Theoretical race: while this executes, the remote number might
+	 * become invalid (hang up) or change (new connection), resulting
+         * in (partially) wrong number copied to user. This race
+	 * currently ignored.
+	 */
+	ch = p->local->isdn_channel;
+	dv = p->local->isdn_device;
+	if(ch<0 && dv<0) return -ENOTCONN;
+	idx = isdn_dc2minor(dv, ch);
+	if (idx<0) return -ENODEV;
+	/* for pre-bound channels, we need this extra check */
+	if ( strncmp(dev->num[idx],"???",3) == 0 ) return -ENOTCONN;
+	strncpy(phone->phone,dev->num[idx],ISDN_MSNLEN);
+	phone->outgoing=USG_OUTGOING(dev->usage[idx]);
+	if ( copy_to_user(peer,phone,sizeof(*peer)) ) return -EFAULT;
+	return 0;
+}
+/*
+ * Delete a phone-number from an interface.
+ */
+int
+isdn_net_delphone(isdn_net_ioctl_phone * phone)
+{
+	isdn_net_dev *p = isdn_net_findif(phone->name);
+	int inout = phone->outgoing & 1;
+	isdn_net_phone *n;
+	isdn_net_phone *m;
+
+	if (p) {
+		n = p->local->phone[inout];
+		m = NULL;
+		while (n) {
+			if (!strcmp(n->num, phone->phone)) {
+				if (p->local->dial == n)
+					p->local->dial = n->next;
+				if (m)
+					m->next = n->next;
+				else
+					p->local->phone[inout] = n->next;
+				kfree(n);
+				return 0;
+			}
+			m = n;
+			n = (isdn_net_phone *) n->next;
+		}
+		return -EINVAL;
+	}
+	return -ENODEV;
+}
+
+/*
+ * Delete all phone-numbers of an interface.
+ */
 static int
-isdn_ether_open(isdn_net_local *lp)
+isdn_net_rmallphone(isdn_net_dev * p)
 {
-	struct net_device *dev = &lp->dev;
-	struct in_device *in_dev;
+	isdn_net_phone *n;
+	isdn_net_phone *m;
 	int i;
 
-	/* Fill in the MAC-level header ... */
-	for (i = 0; i < ETH_ALEN; i++)
-		dev->dev_addr[i] = 0xfc;
-	in_dev = dev->ip_ptr;
-	if (in_dev) {
-		/* any address will do - we take the first */
-		struct in_ifaddr *ifa = in_dev->ifa_list;
-		if (ifa)
-			memcpy(dev->dev_addr+2, &ifa->ifa_local, 4);
+	for (i = 0; i < 2; i++) {
+		n = p->local->phone[i];
+		while (n) {
+			m = n->next;
+			kfree(n);
+			n = m;
+		}
+		p->local->phone[i] = NULL;
 	}
+	p->local->dial = NULL;
 	return 0;
 }
 
+/*
+ * Force a hangup of a network-interface.
+ */
+int
+isdn_net_force_hangup(char *name)
+{
+	isdn_net_dev *p = isdn_net_findif(name);
+	struct net_device *q;
+
+	if (p) {
+		if (p->local->isdn_device < 0)
+			return 1;
+		q = p->local->slave;
+		/* If this interface has slaves, do a hangup for them also. */
+		while (q) {
+			isdn_net_hangup(q);
+			q = (((isdn_net_local *) q->priv)->slave);
+		}
+		isdn_net_hangup(&p->dev);
+		return 0;
+	}
+	return -ENODEV;
+}
+
+/*
+ * Helper-function for isdn_net_rm: Do the real work.
+ */
 static int
-isdn_ether_init(isdn_net_local *lp)
+isdn_net_realrm(isdn_net_dev * p, isdn_net_dev * q)
 {
-	struct net_device *dev = &lp->dev;
+	u_long flags;
 
-	ether_setup(dev);
-	dev->tx_queue_len = 10;
-	dev->hard_header_len += isdn_hard_header_len();
+	if (isdn_net_device_started(p)) {
+		return -EBUSY;
+	}
+#ifdef CONFIG_ISDN_X25
+	if( p -> cprot && p -> cprot -> pops )
+		p -> cprot -> pops -> proto_del ( p -> cprot );
+#endif
+	/* Free all phone-entries */
+	isdn_net_rmallphone(p);
+	/* If interface is bound exclusive, free channel-usage */
+	if (p->local->exclusive != -1)
+		isdn_unexclusive_channel(p->local->pre_device, p->local->pre_channel);
+	if (p->local->master) {
+		/* It's a slave-device, so update master's slave-pointer if necessary */
+		if (((isdn_net_local *) (p->local->master->priv))->slave == &p->dev)
+			((isdn_net_local *) (p->local->master->priv))->slave = p->local->slave;
+	} else {
+		/* Unregister only if it's a master-device */
+		p->dev.hard_header_cache = p->local->org_hhc;
+		p->dev.header_cache_update = p->local->org_hcu;
+		unregister_netdev(&p->dev);
+	}
+	/* Unlink device from chain */
+	spin_lock_irqsave(&dev->lock, flags);
+	if (q)
+		q->next = p->next;
+	else
+		dev->netdev = p->next;
+	if (p->local->slave) {
+		/* If this interface has a slave, remove it also */
+		char *slavename = ((isdn_net_local *) (p->local->slave->priv))->name;
+		isdn_net_dev *n = dev->netdev;
+		q = NULL;
+		while (n) {
+			if (!strcmp(n->local->name, slavename)) {
+				spin_unlock_irqrestore(&dev->lock, flags);
+				isdn_net_realrm(n, q);
+				spin_lock_irqsave(&dev->lock, flags);
+				break;
+			}
+			q = n;
+			n = (isdn_net_dev *) n->next;
+		}
+	}
+	spin_unlock_irqrestore(&dev->lock, flags);
+	/* If no more net-devices remain, disable auto-hangup timer */
+	if (dev->netdev == NULL)
+		isdn_timer_ctrl(ISDN_TIMER_NETHANGUP, 0);
+	kfree(p->local);
+	kfree(p);
 
 	return 0;
 }
 
-struct isdn_netif_ops isdn_ether_ops = {
-	.hard_start_xmit     = isdn_net_start_xmit,
-	.receive             = isdn_ether_receive,
-	.init                = isdn_ether_init,
-	.open                = isdn_ether_open,
-};
+/*
+ * Remove a single network-interface.
+ */
+int
+isdn_net_rm(char *name)
+{
+	u_long flags;
+	isdn_net_dev *p;
+	isdn_net_dev *q;
+
+	/* Search name in netdev-chain */
+	spin_lock_irqsave(&dev->lock, flags);
+	p = dev->netdev;
+	q = NULL;
+	while (p) {
+		if (!strcmp(p->local->name, name)) {
+			spin_unlock_irqrestore(&dev->lock, flags);
+			return (isdn_net_realrm(p, q));
+		}
+		q = p;
+		p = (isdn_net_dev *) p->next;
+	}
+	spin_unlock_irqrestore(&dev->lock, flags);
+	/* If no more net-devices remain, disable auto-hangup timer */
+	if (dev->netdev == NULL)
+		isdn_timer_ctrl(ISDN_TIMER_NETHANGUP, 0);
+	return -ENODEV;
+}
+
+/*
+ * Remove all network-interfaces
+ */
+int
+isdn_net_rmall(void)
+{
+	u_long flags;
+	int ret;
+
+	/* Walk through netdev-chain */
+	spin_lock_irqsave(&dev->lock, flags);
+	while (dev->netdev) {
+		if (!dev->netdev->local->master) {
+			/* Remove master-devices only, slaves get removed with their master */
+			spin_unlock_irqrestore(&dev->lock, flags);
+			if ((ret = isdn_net_realrm(dev->netdev, NULL))) {
+				return ret;
+			}
+			spin_lock_irqsave(&dev->lock, flags);
+		}
+	}
+	dev->netdev = NULL;
+	spin_unlock_irqrestore(&dev->lock, flags);
+	return 0;
+}
--- diff/drivers/isdn/i4l/isdn_net.h	2002-11-11 11:09:36.000000000 +0000
+++ source/drivers/isdn/i4l/isdn_net.h	2004-02-23 13:56:42.000000000 +0000
@@ -1,15 +1,189 @@
-/* Linux ISDN subsystem, network related functions
+/* $Id: isdn_net.h,v 1.1.2.2 2004/01/12 22:37:19 keil Exp $
+ *
+ * header for Linux ISDN subsystem, network related functions (linklevel).
  *
  * Copyright 1994-1999  by Fritz Elfert (fritz@isdn4linux.de)
- *           1995,96    by Thinking Objects Software GmbH Wuerzburg
- *           1995,96    by Michael Hipp (Michael.Hipp@student.uni-tuebingen.de)
- *           1999-2002  by Kai Germaschewski <kai@germaschewski.name>
+ * Copyright 1995,96    by Thinking Objects Software GmbH Wuerzburg
+ * Copyright 1995,96    by Michael Hipp (Michael.Hipp@student.uni-tuebingen.de)
  *
  * This software may be used and distributed according to the terms
  * of the GNU General Public License, incorporated herein by reference.
+ *
+ */
+
+			      /* Definitions for hupflags:                */
+#define ISDN_WAITCHARGE  1      /* did not get a charge info yet            */
+#define ISDN_HAVECHARGE  2      /* We know a charge info                    */
+#define ISDN_CHARGEHUP   4      /* We want to use the charge mechanism      */
+#define ISDN_INHUP       8      /* Even if incoming, close after huptimeout */
+#define ISDN_MANCHARGE  16      /* Charge Interval manually set             */
+
+/*
+ * Definitions for Cisco-HDLC header.
+ */
+
+#define CISCO_ADDR_UNICAST    0x0f
+#define CISCO_ADDR_BROADCAST  0x8f
+#define CISCO_CTRL            0x00
+#define CISCO_TYPE_CDP        0x2000
+#define CISCO_TYPE_SLARP      0x8035
+#define CISCO_SLARP_REQUEST   0
+#define CISCO_SLARP_REPLY     1
+#define CISCO_SLARP_KEEPALIVE 2
+
+extern char *isdn_net_new(char *, struct net_device *);
+extern char *isdn_net_newslave(char *);
+extern int isdn_net_rm(char *);
+extern int isdn_net_rmall(void);
+extern int isdn_net_stat_callback(int, isdn_ctrl *);
+extern int isdn_net_setcfg(isdn_net_ioctl_cfg *);
+extern int isdn_net_getcfg(isdn_net_ioctl_cfg *);
+extern int isdn_net_addphone(isdn_net_ioctl_phone *);
+extern int isdn_net_getphones(isdn_net_ioctl_phone *, char *);
+extern int isdn_net_getpeer(isdn_net_ioctl_phone *, isdn_net_ioctl_phone *);
+extern int isdn_net_delphone(isdn_net_ioctl_phone *);
+extern int isdn_net_find_icall(int, int, int, setup_parm *);
+extern void isdn_net_hangup(struct net_device *);
+extern void isdn_net_dial(void);
+extern void isdn_net_autohup(void);
+extern int isdn_net_force_hangup(char *);
+extern int isdn_net_force_dial(char *);
+extern isdn_net_dev *isdn_net_findif(char *);
+extern int isdn_net_rcv_skb(int, struct sk_buff *);
+extern int isdn_net_dial_req(isdn_net_local *);
+extern void isdn_net_writebuf_skb(isdn_net_local *lp, struct sk_buff *skb);
+extern void isdn_net_write_super(isdn_net_local *lp, struct sk_buff *skb);
+
+#define ISDN_NET_MAX_QUEUE_LENGTH 2
+
+/*
+ * is this particular channel busy?
+ */
+static __inline__ int isdn_net_lp_busy(isdn_net_local *lp)
+{
+	if (atomic_read(&lp->frame_cnt) < ISDN_NET_MAX_QUEUE_LENGTH)
+		return 0;
+	else 
+		return 1;
+}
+
+/*
+ * For the given net device, this will get a non-busy channel out of the
+ * corresponding bundle. The returned channel is locked.
+ */
+static __inline__ isdn_net_local * isdn_net_get_locked_lp(isdn_net_dev *nd)
+{
+	unsigned long flags;
+	isdn_net_local *lp;
+
+	spin_lock_irqsave(&nd->queue_lock, flags);
+	lp = nd->queue;         /* get lp on top of queue */
+	spin_lock_bh(&nd->queue->xmit_lock);
+	while (isdn_net_lp_busy(nd->queue)) {
+		spin_unlock_bh(&nd->queue->xmit_lock);
+		nd->queue = nd->queue->next;
+		if (nd->queue == lp) { /* not found -- should never happen */
+			lp = NULL;
+			goto errout;
+		}
+		spin_lock_bh(&nd->queue->xmit_lock);
+	}
+	lp = nd->queue;
+	nd->queue = nd->queue->next;
+errout:
+	spin_unlock_irqrestore(&nd->queue_lock, flags);
+	return lp;
+}
+
+/*
+ * add a channel to a bundle
  */
+static __inline__ void isdn_net_add_to_bundle(isdn_net_dev *nd, isdn_net_local *nlp)
+{
+	isdn_net_local *lp;
+	unsigned long flags;
+
+	spin_lock_irqsave(&nd->queue_lock, flags);
+
+	lp = nd->queue;
+//	printk(KERN_DEBUG __FUNCTION__": lp:%s(%p) nlp:%s(%p) last(%p)\n",
+//		lp->name, lp, nlp->name, nlp, lp->last); 
+	nlp->last = lp->last;
+	lp->last->next = nlp;
+	lp->last = nlp;
+	nlp->next = lp;
+	nd->queue = nlp;
+
+	spin_unlock_irqrestore(&nd->queue_lock, flags);
+}
+/*
+ * remove a channel from the bundle it belongs to
+ */
+static __inline__ void isdn_net_rm_from_bundle(isdn_net_local *lp)
+{
+	isdn_net_local *master_lp = lp;
+	unsigned long flags;
+
+	if (lp->master)
+		master_lp = (isdn_net_local *) lp->master->priv;
+
+//	printk(KERN_DEBUG __FUNCTION__": lp:%s(%p) mlp:%s(%p) last(%p) next(%p) mndq(%p)\n",
+//		lp->name, lp, master_lp->name, master_lp, lp->last, lp->next, master_lp->netdev->queue); 
+	spin_lock_irqsave(&master_lp->netdev->queue_lock, flags);
+	lp->last->next = lp->next;
+	lp->next->last = lp->last;
+	if (master_lp->netdev->queue == lp) {
+		master_lp->netdev->queue = lp->next;
+		if (lp->next == lp) { /* last in queue */
+			master_lp->netdev->queue = master_lp->netdev->local;
+		}
+	}
+	lp->next = lp->last = lp;	/* (re)set own pointers */
+//	printk(KERN_DEBUG __FUNCTION__": mndq(%p)\n",
+//		master_lp->netdev->queue); 
+	spin_unlock_irqrestore(&master_lp->netdev->queue_lock, flags);
+}
+
+static inline int
+put_u8(unsigned char *p, u8 x)
+{
+	*p = x;
+	return 1;
+}
+
+static inline int
+put_u16(unsigned char *p, u16 x)
+{
+	*((u16 *)p) = htons(x);
+	return 2;
+}
+
+static inline int
+put_u32(unsigned char *p, u32 x)
+{
+	*((u32 *)p) = htonl(x);
+	return 4;
+}
+
+static inline int
+get_u8(unsigned char *p, u8 *x)
+{
+	*x = *p;
+	return 1;
+}
+
+static inline int
+get_u16(unsigned char *p, u16 *x)
+{
+	*x = ntohs(*((u16 *)p));
+	return 2;
+}
+
+static inline int
+get_u32(unsigned char *p, u32 *x)
+{
+	*x = ntohl(*((u32 *)p));
+	return 4;
+}
+
 
-extern struct isdn_netif_ops isdn_iptyp_ops;
-extern struct isdn_netif_ops isdn_uihdlc_ops;
-extern struct isdn_netif_ops isdn_rawip_ops;
-extern struct isdn_netif_ops isdn_ether_ops;
--- diff/drivers/isdn/i4l/isdn_ppp.c	2003-09-17 12:28:06.000000000 +0100
+++ source/drivers/isdn/i4l/isdn_ppp.c	2004-02-23 13:56:43.000000000 +0000
@@ -1,803 +1,843 @@
-/* Linux ISDN subsystem, functions for synchronous PPP (linklevel).
+/* $Id: isdn_ppp.c,v 1.1.2.3 2004/02/10 01:07:13 keil Exp $
  *
- * Copyright 1995,96    by Michael Hipp (Michael.Hipp@student.uni-tuebingen.de)
- *           1999-2002  by Kai Germaschewski <kai@germaschewski.name>
+ * Linux ISDN subsystem, functions for synchronous PPP (linklevel).
+ *
+ * Copyright 1995,96 by Michael Hipp (Michael.Hipp@student.uni-tuebingen.de)
  *
  * This software may be used and distributed according to the terms
  * of the GNU General Public License, incorporated herein by reference.
+ *
  */
 
-#include <linux/module.h>
+#include <linux/config.h>
 #include <linux/isdn.h>
-#include <linux/smp_lock.h>
 #include <linux/poll.h>
 #include <linux/ppp-comp.h>
-#include <linux/if_arp.h>
+#ifdef CONFIG_IPPP_FILTER
+#include <linux/filter.h>
+#endif
 
 #include "isdn_common.h"
-#include "isdn_net_lib.h"
 #include "isdn_ppp.h"
-#include "isdn_ppp_ccp.h"
-#include "isdn_ppp_vj.h"
-#include "isdn_ppp_mp.h"
+#include "isdn_net.h"
 
-/* ====================================================================== */
+#ifndef PPP_IPX
+#define PPP_IPX 0x002b
+#endif
 
-#define IPPP_MAX_RQ_LEN 8 /* max #frames queued for ipppd to read */
+/* Prototypes */
+static int isdn_ppp_fill_rq(unsigned char *buf, int len, int proto, int slot);
+static int isdn_ppp_closewait(int slot);
+static void isdn_ppp_push_higher(isdn_net_dev * net_dev, isdn_net_local * lp,
+				 struct sk_buff *skb, int proto);
+static int isdn_ppp_if_get_unit(char *namebuf);
+static int isdn_ppp_set_compressor(struct ippp_struct *is,struct isdn_ppp_comp_data *);
+static struct sk_buff *isdn_ppp_decompress(struct sk_buff *,
+				struct ippp_struct *,struct ippp_struct *,int *proto);
+static void isdn_ppp_receive_ccp(isdn_net_dev * net_dev, isdn_net_local * lp,
+				struct sk_buff *skb,int proto);
+static struct sk_buff *isdn_ppp_compress(struct sk_buff *skb_in,int *proto,
+	struct ippp_struct *is,struct ippp_struct *master,int type);
+static void isdn_ppp_send_ccp(isdn_net_dev *net_dev, isdn_net_local *lp,
+	 struct sk_buff *skb);
 
-static int
-isdn_ppp_set_compressor(isdn_net_dev *idev, struct isdn_ppp_comp_data *);
+/* New CCP stuff */
+static void isdn_ppp_ccp_kickup(struct ippp_struct *is);
+static void isdn_ppp_ccp_xmit_reset(struct ippp_struct *is, int proto,
+				    unsigned char code, unsigned char id,
+				    unsigned char *data, int len);
+static struct ippp_ccp_reset *isdn_ppp_ccp_reset_alloc(struct ippp_struct *is);
+static void isdn_ppp_ccp_reset_free(struct ippp_struct *is);
+static void isdn_ppp_ccp_reset_free_state(struct ippp_struct *is,
+					  unsigned char id);
+static void isdn_ppp_ccp_timer_callback(unsigned long closure);
+static struct ippp_ccp_reset_state *isdn_ppp_ccp_reset_alloc_state(struct ippp_struct *is,
+						      unsigned char id);
+static void isdn_ppp_ccp_reset_trans(struct ippp_struct *is,
+				     struct isdn_ppp_resetparams *rp);
+static void isdn_ppp_ccp_reset_ack_rcvd(struct ippp_struct *is,
+					unsigned char id);
 
-/* ====================================================================== */
-/* IPPPD handling                                                         */
-/* ====================================================================== */
-
-/* We use reference counting for struct ipppd. It is alloced on
- * open() on /dev/ipppX and saved into file->private, making for one
- * reference. release() will release this reference, after all other
- * references are gone, the destructor frees it.
- *
- * Another reference is taken by isdn_ppp_bind() and freed by
- * isdn_ppp_unbind(). The callbacks from isdn_net_lib.c happen only
- * between isdn_ppp_bind() and isdn_ppp_unbind(), i.e. access to 
- * idev->ipppd is safe without further locking.
- */
 
-#undef IPPPD_DEBUG
-
-#ifdef IPPPD_DEBUG
-#define ipppd_debug(i, fmt, arg...) \
-        printk(KERN_DEBUG "ipppd %p minor %d state %#x %s: " fmt "\n", (i), \
-               (i)->minor, (i)->state, __FUNCTION__ , ## arg)
-#else
-#define ipppd_debug(...) do { } while (0)
-#endif
 
-/* ipppd::flags */
-enum {
-	IPPPD_FL_HUP    = 0x01,
-	IPPPD_FL_WAKEUP = 0x02,
-};
-
-/* ipppd::state */
-enum {
-	IPPPD_ST_OPEN,
-	IPPPD_ST_ASSIGNED,
-	IPPPD_ST_CONNECTED,
-};
-
-struct ipppd {
-	struct list_head ipppds;
-	int state;
-	int flags;
-	struct sk_buff_head rq;
-	wait_queue_head_t wq;
-	struct isdn_net_dev_s *idev;
-	int unit;
-	int minor;
-	unsigned long debug;
-	atomic_t refcnt;
-};
+#ifdef CONFIG_ISDN_MPP
+static ippp_bundle * isdn_ppp_bundle_arr = NULL;
+ 
+static int isdn_ppp_mp_bundle_array_init(void);
+static int isdn_ppp_mp_init( isdn_net_local * lp, ippp_bundle * add_to );
+static void isdn_ppp_mp_receive(isdn_net_dev * net_dev, isdn_net_local * lp, 
+							struct sk_buff *skb);
+static void isdn_ppp_mp_cleanup( isdn_net_local * lp );
+
+static int isdn_ppp_bundle(struct ippp_struct *, int unit);
+#endif	/* CONFIG_ISDN_MPP */
+  
+char *isdn_ppp_revision = "$Revision: 1.1.2.3 $";
 
-/* ====================================================================== */
+static struct ippp_struct *ippp_table[ISDN_MAX_CHANNELS];
 
-static spinlock_t ipppds_lock = SPIN_LOCK_UNLOCKED;
-static LIST_HEAD(ipppds);
+static struct isdn_ppp_compressor *ipc_head = NULL;
 
+/*
+ * frame log (debug)
+ */
 static void
-ipppd_destroy(struct ipppd *ipppd)
+isdn_ppp_frame_log(char *info, char *data, int len, int maxlen,int unit,int slot)
 {
-	HERE;
+	int cnt,
+	 j,
+	 i;
+	char buf[80];
 
-	skb_queue_purge(&ipppd->rq);
-	kfree(ipppd);
-}
+	if (len < maxlen)
+		maxlen = len;
 
-static inline struct ipppd *
-ipppd_get(struct ipppd *ipppd)
-{
-	atomic_inc(&ipppd->refcnt);
-	printk("%s: %d\n", __FUNCTION__, atomic_read(&ipppd->refcnt));
-	return ipppd;
+	for (i = 0, cnt = 0; cnt < maxlen; i++) {
+		for (j = 0; j < 16 && cnt < maxlen; j++, cnt++)
+			sprintf(buf + j * 3, "%02x ", (unsigned char) data[cnt]);
+		printk(KERN_DEBUG "[%d/%d].%s[%d]: %s\n",unit,slot, info, i, buf);
+	}
 }
 
-static inline void 
-ipppd_put(struct ipppd *ipppd)
+/*
+ * unbind isdn_net_local <=> ippp-device
+ * note: it can happen, that we hangup/free the master before the slaves
+ *       in this case we bind another lp to the master device
+ */
+int
+isdn_ppp_free(isdn_net_local * lp)
 {
-	printk("%s: %d\n", __FUNCTION__, atomic_read(&ipppd->refcnt));
-
-	if (atomic_dec_and_test(&ipppd->refcnt))
-		ipppd_destroy(ipppd);
-}
-
-/* ====================================================================== */
-/* char dev ops                                                           */
-
-/* --- open ------------------------------------------------------------- */
+	struct ippp_struct *is;
 
-static int
-ipppd_open(struct inode *ino, struct file *file)
-{
-	unsigned long flags;
-	unsigned int minor = iminor(ino) - ISDN_MINOR_PPP;
-	struct ipppd *ipppd;
+	if (lp->ppp_slot < 0 || lp->ppp_slot > ISDN_MAX_CHANNELS) {
+		printk(KERN_ERR "%s: ppp_slot(%d) out of range\n",
+			__FUNCTION__, lp->ppp_slot);
+		return 0;
+	}
 
-	ipppd = kmalloc(sizeof(*ipppd), GFP_KERNEL);
-	if (!ipppd)
-		return -ENOMEM;
+#ifdef CONFIG_ISDN_MPP
+	spin_lock(&lp->netdev->pb->lock);
+#endif
+	isdn_net_rm_from_bundle(lp);
+#ifdef CONFIG_ISDN_MPP
+	if (lp->netdev->pb->ref_ct == 1)	/* last link in queue? */
+		isdn_ppp_mp_cleanup(lp);
+
+	lp->netdev->pb->ref_ct--;
+	spin_unlock(&lp->netdev->pb->lock);
+#endif /* CONFIG_ISDN_MPP */
+	if (lp->ppp_slot < 0 || lp->ppp_slot > ISDN_MAX_CHANNELS) {
+		printk(KERN_ERR "%s: ppp_slot(%d) now invalid\n",
+			__FUNCTION__, lp->ppp_slot);
+		return 0;
+	}
+	is = ippp_table[lp->ppp_slot];
+	if ((is->state & IPPP_CONNECT))
+		isdn_ppp_closewait(lp->ppp_slot);	/* force wakeup on ippp device */
+	else if (is->state & IPPP_ASSIGNED)
+		is->state = IPPP_OPEN;	/* fallback to 'OPEN but not ASSIGNED' state */
 
-	memset(ipppd, 0, sizeof(*ipppd));
-	atomic_set(&ipppd->refcnt, 0);
-	
-	/* file->private_data holds a reference */
-	file->private_data = ipppd_get(ipppd);
+	if (is->debug & 0x1)
+		printk(KERN_DEBUG "isdn_ppp_free %d %lx %lx\n", lp->ppp_slot, (long) lp, (long) is->lp);
 
-	ipppd->unit = -1;          /* set by isdn_ppp_bind */
-	ipppd->minor = minor;
-	ipppd->state = IPPPD_ST_OPEN;
-	init_waitqueue_head(&ipppd->wq);
-	skb_queue_head_init(&ipppd->rq);
-
-	spin_lock_irqsave(&ipppds_lock, flags);
-	list_add(&ipppd->ipppds, &ipppds);
-	spin_unlock_irqrestore(&ipppds_lock, flags);
-	
-	ipppd_debug(ipppd, "minor %d", minor);
+	is->lp = NULL;          /* link is down .. set lp to NULL */
+	lp->ppp_slot = -1;      /* is this OK ?? */
 
 	return 0;
 }
 
-/* --- release  --------------------------------------------------------- */
-
-static int
-ipppd_release(struct inode *ino, struct file *file)
+/*
+ * bind isdn_net_local <=> ippp-device
+ *
+ * This function is allways called with holding dev->lock so
+ * no additional lock is needed
+ */
+int
+isdn_ppp_bind(isdn_net_local * lp)
 {
-	unsigned long flags;
-	struct ipppd *ipppd = file->private_data;
-
-	ipppd_debug(ipppd, "");
+	int i;
+	int unit = 0;
+	struct ippp_struct *is;
+	int retval;
 
-	if (ipppd->state == IPPPD_ST_CONNECTED)
-		isdn_net_hangup(ipppd->idev);
+	if (lp->pppbind < 0) {  /* device bounded to ippp device ? */
+		isdn_net_dev *net_dev = dev->netdev;
+		char exclusive[ISDN_MAX_CHANNELS];	/* exclusive flags */
+		memset(exclusive, 0, ISDN_MAX_CHANNELS);
+		while (net_dev) {	/* step through net devices to find exclusive minors */
+			isdn_net_local *lp = net_dev->local;
+			if (lp->pppbind >= 0)
+				exclusive[lp->pppbind] = 1;
+			net_dev = net_dev->next;
+		}
+		/*
+		 * search a free device / slot
+		 */
+		for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
+			if (ippp_table[i]->state == IPPP_OPEN && !exclusive[ippp_table[i]->minor]) {	/* OPEN, but not connected! */
+				break;
+			}
+		}
+	} else {
+		for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
+			if (ippp_table[i]->minor == lp->pppbind &&
+			    (ippp_table[i]->state & IPPP_OPEN) == IPPP_OPEN)
+				break;
+		}
+	}
 
-	spin_lock_irqsave(&ipppds_lock, flags);
-	list_del(&ipppd->ipppds);
-	spin_unlock_irqrestore(&ipppds_lock, flags);
+	if (i >= ISDN_MAX_CHANNELS) {
+		printk(KERN_WARNING "isdn_ppp_bind: Can't find a (free) connection to the ipppd daemon.\n");
+		retval = -1;
+		goto out;
+	}
+	unit = isdn_ppp_if_get_unit(lp->name);	/* get unit number from interface name .. ugly! */
+	if (unit < 0) {
+		printk(KERN_ERR "isdn_ppp_bind: illegal interface name %s.\n", lp->name);
+		retval = -1;
+		goto out;
+	}
+	
+	lp->ppp_slot = i;
+	is = ippp_table[i];
+	is->lp = lp;
+	is->unit = unit;
+	is->state = IPPP_OPEN | IPPP_ASSIGNED;	/* assigned to a netdevice but not connected */
+#ifdef CONFIG_ISDN_MPP
+	retval = isdn_ppp_mp_init(lp, NULL);
+	if (retval < 0)
+		goto out;
+#endif /* CONFIG_ISDN_MPP */
 
-	ipppd_put(ipppd);
+	retval = lp->ppp_slot;
 
-	return 0;
+ out:
+	return retval;
 }
 
-/* --- read ------------------------------------------------------------- */
+/*
+ * kick the ipppd on the device
+ * (wakes up daemon after B-channel connect)
+ */
 
-/* read() is always non blocking */
-static ssize_t
-ipppd_read(struct file *file, char *buf, size_t count, loff_t *off)
+void
+isdn_ppp_wakeup_daemon(isdn_net_local * lp)
 {
-	struct ipppd *is;
-	struct sk_buff *skb;
-	int retval;
+	if (lp->ppp_slot < 0 || lp->ppp_slot >= ISDN_MAX_CHANNELS) {
+		printk(KERN_ERR "%s: ppp_slot(%d) out of range\n",
+			__FUNCTION__, lp->ppp_slot);
+		return;
+	}
+	ippp_table[lp->ppp_slot]->state = IPPP_OPEN | IPPP_CONNECT | IPPP_NOBLOCK;
+	wake_up_interruptible(&ippp_table[lp->ppp_slot]->wq);
+}
 
-	if (off != &file->f_pos)
-		return -ESPIPE;
-	
-	is = file->private_data;
+/*
+ * there was a hangup on the netdevice
+ * force wakeup of the ippp device
+ * go into 'device waits for release' state
+ */
+static int
+isdn_ppp_closewait(int slot)
+{
+	struct ippp_struct *is;
 
-	skb = skb_dequeue(&is->rq);
-	if (!skb) {
-		retval = -EAGAIN;
-		goto out;
-	}
-	if (skb->len > count) {
-		retval = -EMSGSIZE;
-		goto out_free;
-	}
-	if (copy_to_user(buf, skb->data, skb->len)) {
-		retval = -EFAULT;
-		goto out_free;
+	if (slot < 0 || slot >= ISDN_MAX_CHANNELS) {
+		printk(KERN_ERR "%s: slot(%d) out of range\n",
+			__FUNCTION__, slot);
+		return 0;
 	}
-	retval = skb->len;
-
- out_free:
-	dev_kfree_skb(skb);
- out:
-	return retval;
+	is = ippp_table[slot];
+	if (is->state)
+		wake_up_interruptible(&is->wq);
+	is->state = IPPP_CLOSEWAIT;
+	return 1;
 }
 
-/* --- write ------------------------------------------------------------ */
+/*
+ * isdn_ppp_find_slot / isdn_ppp_free_slot
+ */
 
-/* write() is always non blocking */
-static ssize_t
-ipppd_write(struct file *file, const char *buf, size_t count, loff_t *off)
-{
-	isdn_net_dev *idev;
-	struct inl_ppp *inl_ppp;
-	struct ind_ppp *ind_ppp;
-	struct ipppd *ipppd;
-	struct sk_buff *skb;
-	char *p;
-	int retval;
-	u16 proto;
+static int
+isdn_ppp_get_slot(void)
+{
+	int i;
+	for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
+		if (!ippp_table[i]->state)
+			return i;
+	}
+	return -1;
+}
 
-	if (off != &file->f_pos)
-		return -ESPIPE;
+/*
+ * isdn_ppp_open
+ */
 
-	ipppd = file->private_data;
-	ipppd_debug(ipppd, "count = %d", count);
+int
+isdn_ppp_open(int min, struct file *file)
+{
+	int slot;
+	struct ippp_struct *is;
 
-	if (ipppd->state != IPPPD_ST_CONNECTED) {
-		retval = -ENOTCONN;
-		goto out;
-	}
+	if (min < 0 || min > ISDN_MAX_CHANNELS)
+		return -ENODEV;
 
-	idev = ipppd->idev;
-	if (!idev) {
-		isdn_BUG();
-		retval = -ENODEV;
-		goto out;
-	}
-	ind_ppp = idev->ind_priv;
-	inl_ppp = idev->mlp->inl_priv;
-	/* Daemon needs to send at least full header, AC + proto */
-	if (count < 4) {
-		retval = -EMSGSIZE;
-		goto out;
-	}
-	skb = isdn_ppp_dev_alloc_skb(idev, count, GFP_KERNEL);
-	if (!skb) {
-		retval = -ENOMEM;
-		goto out;
+	slot = isdn_ppp_get_slot();
+	if (slot < 0) {
+		return -EBUSY;
 	}
-	p = skb_put(skb, count);
-	if (copy_from_user(p, buf, count)) {
-		kfree_skb(skb);
-		retval = -EFAULT;
-		goto out;
-	}
-	/* Don't reset huptimer for LCP packets. (Echo requests). */
-	proto = PPP_PROTOCOL(p);
-	if (proto != PPP_LCP)
-		idev->huptimer = 0;
+	is = file->private_data = ippp_table[slot];
 	
-	/* Keeps CCP/compression states in sync */
-	switch (proto) {
-	case PPP_CCP:
-		ippp_ccp_send_ccp(inl_ppp->ccp, skb);
-		break;
-	case PPP_CCPFRAG:
-		ippp_ccp_send_ccp(ind_ppp->ccp, skb);
-		break;
-	}
-	/* FIXME: Somewhere we need protection against the
-	 * queue growing too large */
-	isdn_net_write_super(idev, skb);
+	printk(KERN_DEBUG "ippp, open, slot: %d, minor: %d, state: %04x\n",
+	       slot, min, is->state);
 
-	retval = count;
-	
- out:
-	return retval;
-}
+	/* compression stuff */
+	is->link_compressor   = is->compressor = NULL;
+	is->link_decompressor = is->decompressor = NULL;
+	is->link_comp_stat    = is->comp_stat = NULL;
+	is->link_decomp_stat  = is->decomp_stat = NULL;
+	is->compflags = 0;
+
+	is->reset = isdn_ppp_ccp_reset_alloc(is);
+
+	is->lp = NULL;
+	is->mp_seqno = 0;       /* MP sequence number */
+	is->pppcfg = 0;         /* ppp configuration */
+	is->mpppcfg = 0;        /* mppp configuration */
+	is->last_link_seqno = -1;	/* MP: maybe set to Bundle-MIN, when joining a bundle ?? */
+	is->unit = -1;          /* set, when we have our interface */
+	is->mru = 1524;         /* MRU, default 1524 */
+	is->maxcid = 16;        /* VJ: maxcid */
+	is->tk = current;
+	init_waitqueue_head(&is->wq);
+	is->first = is->rq + NUM_RCV_BUFFS - 1;	/* receive queue */
+	is->last = is->rq;
+	is->minor = min;
+#ifdef CONFIG_ISDN_PPP_VJ
+	/*
+	 * VJ header compression init
+	 */
+	is->slcomp = slhc_init(16, 16);	/* not necessary for 2. link in bundle */
+#endif
+#ifdef CONFIG_IPPP_FILTER
+	is->pass_filter.filter = NULL;
+	is->active_filter.filter = NULL;
+#endif
+	is->state = IPPP_OPEN;
 
-/* --- poll ------------------------------------------------------------- */
+	return 0;
+}
 
-static unsigned int
-ipppd_poll(struct file *file, poll_table * wait)
+/*
+ * release ippp device
+ */
+void
+isdn_ppp_release(int min, struct file *file)
 {
-	unsigned int mask;
-	struct ipppd *is;
+	int i;
+	struct ippp_struct *is;
 
+	if (min < 0 || min >= ISDN_MAX_CHANNELS)
+		return;
 	is = file->private_data;
 
-	ipppd_debug(is, "");
+	if (!is) {
+		printk(KERN_ERR "%s: no file->private_data\n", __FUNCTION__);
+		return;
+	}
+	if (is->debug & 0x1)
+		printk(KERN_DEBUG "ippp: release, minor: %d %lx\n", min, (long) is->lp);
 
-	/* just registers wait_queue hook. This doesn't really wait. */
-	poll_wait(file, &is->wq, wait);
+	if (is->lp) {           /* a lp address says: this link is still up */
+		isdn_net_dev *p = is->lp->netdev;
 
-	if (is->flags & IPPPD_FL_HUP) {
-		mask = POLLHUP;
-		goto out;
+		if (!p) {
+			printk(KERN_ERR "%s: no lp->netdev\n", __FUNCTION__);
+			return;
+		}
+		is->state &= ~IPPP_CONNECT;	/* -> effect: no call of wakeup */
+		/*
+		 * isdn_net_hangup() calls isdn_ppp_free()
+		 * isdn_ppp_free() sets is->lp to NULL and lp->ppp_slot to -1
+		 * removing the IPPP_CONNECT flag omits calling of isdn_ppp_wakeup_daemon()
+		 */
+		isdn_net_hangup(&p->dev);
 	}
-	/* we're always ready to send .. */
-	mask = POLLOUT | POLLWRNORM;
+	for (i = 0; i < NUM_RCV_BUFFS; i++) {
+		if (is->rq[i].buf) {
+			kfree(is->rq[i].buf);
+			is->rq[i].buf = NULL;
+		}
+	}
+	is->first = is->rq + NUM_RCV_BUFFS - 1;	/* receive queue */
+	is->last = is->rq;
 
-	/*
-	 * if IPPP_FL_WAKEUP is set we return even if we have nothing to read
-	 */
-	if (!skb_queue_empty(&is->rq) || is->flags & IPPPD_FL_WAKEUP) {
-		is->flags &= ~IPPPD_FL_WAKEUP;
-		mask |= POLLIN | POLLRDNORM;
+#ifdef CONFIG_ISDN_PPP_VJ
+/* TODO: if this was the previous master: link the slcomp to the new master */
+	slhc_free(is->slcomp);
+	is->slcomp = NULL;
+#endif
+#ifdef CONFIG_IPPP_FILTER
+	if (is->pass_filter.filter) {
+		kfree(is->pass_filter.filter);
+		is->pass_filter.filter = NULL;
+	}
+	if (is->active_filter.filter) {
+		kfree(is->active_filter.filter);
+		is->active_filter.filter = NULL;
 	}
+#endif
 
- out:
-	return mask;
-}
+/* TODO: if this was the previous master: link the stuff to the new master */
+	if(is->comp_stat)
+		is->compressor->free(is->comp_stat);
+	if(is->link_comp_stat)
+		is->link_compressor->free(is->link_comp_stat);
+	if(is->link_decomp_stat)
+		is->link_decompressor->free(is->link_decomp_stat);
+	if(is->decomp_stat)
+		is->decompressor->free(is->decomp_stat);
+        is->compressor   = is->link_compressor   = NULL;
+        is->decompressor = is->link_decompressor = NULL;
+	is->comp_stat    = is->link_comp_stat    = NULL;
+        is->decomp_stat  = is->link_decomp_stat  = NULL;
+
+	/* Clean up if necessary */
+	if(is->reset)
+		isdn_ppp_ccp_reset_free(is);
 
-/* --- ioctl ------------------------------------------------------------ */
+	/* this slot is ready for new connections */
+	is->state = 0;
+}
 
-/* get_arg .. ioctl helper */
+/*
+ * get_arg .. ioctl helper
+ */
 static int
-get_arg(unsigned long arg, void *val, int len)
+get_arg(void *b, void *val, int len)
 {
-	if (copy_from_user((void *) val, (void *) arg, len))
+	if (len <= 0)
+		len = sizeof(void *);
+	if (copy_from_user((void *) val, b, len))
 		return -EFAULT;
 	return 0;
 }
 
-/* set arg .. ioctl helper */
+/*
+ * set arg .. ioctl helper
+ */
 static int
-set_arg(unsigned long arg, void *val,int len)
+set_arg(void *b, void *val,int len)
 {
-	if (copy_to_user((void *) arg, (void *) val, len))
+	if(len <= 0)
+		len = sizeof(void *);
+	if (copy_to_user(b, (void *) val, len))
 		return -EFAULT;
 	return 0;
 }
 
-static int
-ipppd_ioctl(struct inode *ino, struct file *file, unsigned int cmd,
-	    unsigned long arg)
+/*
+ * ippp device ioctl
+ */
+int
+isdn_ppp_ioctl(int min, struct file *file, unsigned int cmd, unsigned long arg)
 {
-	isdn_net_dev *idev;
-	struct ind_ppp *ind_ppp = NULL;
-	struct inl_ppp *inl_ppp = NULL;
 	unsigned long val;
-	int r;
-	struct ipppd *is;
+	int r,i,j;
+	struct ippp_struct *is;
+	isdn_net_local *lp;
 	struct isdn_ppp_comp_data data;
-	unsigned int cfg;
 
-	is = file->private_data;
-
-	ipppd_debug(is, "cmd %#x", cmd);
-
-	// FIXME that needs locking?
-	idev = is->idev;
-	if (idev) {
-		ind_ppp = idev->ind_priv;
-		inl_ppp = idev->mlp->inl_priv;
-	}
-	switch (cmd) {
-	case PPPIOCGUNIT:	/* get ppp/isdn unit number */
-		r = set_arg(arg, &is->unit, sizeof(is->unit));
-		break;
-	case PPPIOCGDEBUG:
-		r = set_arg(arg, &is->debug, sizeof(is->debug));
-		break;
-	case PPPIOCSDEBUG:
-		r = get_arg(arg, &val, sizeof(val));
-		if (r)
-			break;
-		is->debug = val;
-		if (idev) {
-			ind_ppp->debug = val;
-			inl_ppp->debug = val;
-		}
-		break;
-	case PPPIOCGCOMPRESSORS:
-	{
-		unsigned long protos[8];
-		ippp_ccp_get_compressors(protos);
-		r = set_arg(arg, protos, sizeof(protos));
-		break;
-	}
-	default:
-		r = -ENOTTY;
-		break;
-	}
+	is = (struct ippp_struct *) file->private_data;
+	lp = is->lp;
 
-	if (r != -ENOTTY)
-		goto out;
+	if (is->debug & 0x1)
+		printk(KERN_DEBUG "isdn_ppp_ioctl: minor: %d cmd: %x state: %x\n", min, cmd, is->state);
 
-	if (!idev) {
-		r = -ENODEV;
-		goto out;
-	}
+	if (!(is->state & IPPP_OPEN))
+		return -EINVAL;
 
 	switch (cmd) {
-	case PPPIOCBUNDLE:
-		r = get_arg(arg, &val, sizeof(val));
-		if (r)
+		case PPPIOCBUNDLE:
+#ifdef CONFIG_ISDN_MPP
+			if (!(is->state & IPPP_CONNECT))
+				return -EINVAL;
+			if ((r = get_arg((void *) arg, &val, sizeof(val) )))
+				return r;
+			printk(KERN_DEBUG "iPPP-bundle: minor: %d, slave unit: %d, master unit: %d\n",
+			       (int) min, (int) is->unit, (int) val);
+			return isdn_ppp_bundle(is, val);
+#else
+			return -1;
+#endif
 			break;
-
-		r = ippp_mp_bundle(idev, val);
-		break;
-	case PPPIOCGIFNAME:
-		r = set_arg(arg, idev->name, strlen(idev->name)+1);
-		break;
-	case PPPIOCGMPFLAGS:	/* get configuration flags */
-		r = set_arg(arg, &inl_ppp->mp_cfg, sizeof(inl_ppp->mp_cfg));
-		break;
-	case PPPIOCSMPFLAGS:	/* set configuration flags */
-		r = get_arg(arg, &val, sizeof(val));
-		if (r)
+		case PPPIOCGUNIT:	/* get ppp/isdn unit number */
+			if ((r = set_arg((void *) arg, &is->unit, sizeof(is->unit) )))
+				return r;
 			break;
-		inl_ppp->mp_cfg = val;
-		break;
-	case PPPIOCGFLAGS:	/* get configuration flags */
-		cfg = ind_ppp->pppcfg | ippp_ccp_get_flags(ind_ppp->ccp);
-		r = set_arg(arg, &cfg, sizeof(cfg));
-		break;
-	case PPPIOCSFLAGS:	/* set configuration flags */
-		r = get_arg(arg, &val, sizeof(val));
-		if (r)
+		case PPPIOCGIFNAME:
+			if(!lp)
+				return -EINVAL;
+			if ((r = set_arg((void *) arg, lp->name, strlen(lp->name))))
+				return r;
 			break;
-		if ((val & SC_ENABLE_IP) && !(ind_ppp->pppcfg & SC_ENABLE_IP)) {
-			ind_ppp->pppcfg = val;
-			/* OK .. we are ready to send buffers */
-			isdn_net_online(idev);
+		case PPPIOCGMPFLAGS:	/* get configuration flags */
+			if ((r = set_arg((void *) arg, &is->mpppcfg, sizeof(is->mpppcfg) )))
+				return r;
 			break;
-		}
-		ind_ppp->pppcfg = val;
-		break;
-	case PPPIOCGIDLE:	/* get idle time information */
-	{
-		struct ppp_idle pidle;
-		pidle.xmit_idle = pidle.recv_idle = idev->huptimer;
-		r = set_arg(arg, &pidle,sizeof(pidle));
-		break;
-	}
-	case PPPIOCSMRU:	/* set receive unit size for PPP */
-		r = get_arg(arg, &val, sizeof(val));
-		if (r)
+		case PPPIOCSMPFLAGS:	/* set configuration flags */
+			if ((r = get_arg((void *) arg, &val, sizeof(val) )))
+				return r;
+			is->mpppcfg = val;
 			break;
-		r = ippp_ccp_set_mru(ind_ppp->ccp, val);
-		break;
-	case PPPIOCSMPMRU:
-		break;
-	case PPPIOCSMPMTU:
-		break;
-	case PPPIOCSMAXCID:	/* set the maximum compression slot id */
-		r = get_arg(arg, &val, sizeof(val));
-		if (r)
+		case PPPIOCGFLAGS:	/* get configuration flags */
+			if ((r = set_arg((void *) arg, &is->pppcfg,sizeof(is->pppcfg) )))
+				return r;
 			break;
-		r = ippp_vj_set_maxcid(idev, val);
-		break;
-	case PPPIOCSCOMPRESSOR:
-		r = get_arg(arg, &data, sizeof(data));
-		if (r)
+		case PPPIOCSFLAGS:	/* set configuration flags */
+			if ((r = get_arg((void *) arg, &val, sizeof(val) ))) {
+				return r;
+			}
+			if (val & SC_ENABLE_IP && !(is->pppcfg & SC_ENABLE_IP) && (is->state & IPPP_CONNECT)) {
+				if (lp) {
+					/* OK .. we are ready to send buffers */
+					is->pppcfg = val; /* isdn_ppp_xmit test for SC_ENABLE_IP !!! */
+					netif_wake_queue(&lp->netdev->dev);
+					break;
+				}
+			}
+			is->pppcfg = val;
 			break;
-		r = isdn_ppp_set_compressor(idev, &data);
-		break;
-	case PPPIOCGCALLINFO:
-	{
-		isdn_net_local *mlp;
-		struct isdn_net_phone *phone;
-		struct pppcallinfo pci;
-		int i;
-		memset(&pci, 0, sizeof(pci));
-
-		mlp = idev->mlp;
-		strlcpy(pci.local_num, mlp->msn, sizeof(pci.local_num));
-		i = 0;
-		list_for_each_entry(phone, &mlp->phone[1], list) {
-			if (i++ == idev->dial) {
-				strlcpy(pci.remote_num,phone->num,sizeof(pci.remote_num));
-				break;
+		case PPPIOCGIDLE:	/* get idle time information */
+			if (lp) {
+				struct ppp_idle pidle;
+				pidle.xmit_idle = pidle.recv_idle = lp->huptimer;
+				if ((r = set_arg((void *) arg, &pidle,sizeof(struct ppp_idle))))
+					 return r;
 			}
-		}
-		pci.charge_units = idev->charge;
-		if (idev->outgoing)
-			pci.calltype = CALLTYPE_OUTGOING;
-		else
-			pci.calltype = CALLTYPE_INCOMING;
-		if (mlp->flags & ISDN_NET_CALLBACK)
-			pci.calltype |= CALLTYPE_CALLBACK;
-		r = set_arg(arg, &pci, sizeof(pci));
-		break;
-	}
-	default:
-		r = -ENOTTY;
-		break;
-	}
- out:
-	return r;
-}
-
-/* --- fops ------------------------------------------------------------- */
-
-struct file_operations isdn_ppp_fops =
-{
-	.owner		= THIS_MODULE,
-	.llseek		= no_llseek,
-	.read		= ipppd_read,
-	.write		= ipppd_write,
-	.poll		= ipppd_poll,
-	.ioctl		= ipppd_ioctl,
-	.open		= ipppd_open,
-	.release	= ipppd_release,
-};
-
-/* --- ipppd_queue_read ------------------------------------------------- */
-
-/* Queue packets for ipppd to read(). */
-
-static int
-ipppd_queue_read(struct ipppd *is, u16 proto, unsigned char *buf, int len)
-{
-	struct sk_buff *skb;
-	unsigned char *p;
-	int retval;
-
-	if (is->state != IPPPD_ST_CONNECTED) {
-		printk(KERN_DEBUG "ippp: device not connected.\n");
-		retval = -ENOTCONN;
-		goto out;
-	}
-	if (skb_queue_len(&is->rq) > IPPP_MAX_RQ_LEN) {
-		printk(KERN_WARNING "ippp: Queue is full\n");
-		retval = -EBUSY;
-		goto out;
-	}
-	skb = dev_alloc_skb(len + 4);
-	if (!skb) {
-		printk(KERN_WARNING "ippp: Can't alloc buf\n");
-		retval = -ENOMEM;
-		goto out;
-	}
-	p = skb_put(skb, 4);
-	p += put_u8(p, PPP_ALLSTATIONS);
-	p += put_u8(p, PPP_UI);
-	p += put_u16(p, proto);
-	memcpy(skb_put(skb, len), buf, len);
-
-	skb_queue_tail(&is->rq, skb);
-	wake_up(&is->wq);
-
-	retval = len;
- out:
-	return retval;
-}
-
-/* ====================================================================== */
-/* interface to isdn_net_lib                                            */
-/* ====================================================================== */
-
-
-/* Prototypes */
-static int
-isdn_ppp_if_get_unit(char *namebuf);
-
-static void
-isdn_ppp_dev_xmit(void *priv, struct sk_buff *skb, u16 proto);
-
-static struct sk_buff *
-isdn_ppp_lp_alloc_skb(void *priv, int len, int gfp_mask);
-
-/* New CCP stuff */
-static void
-isdn_ppp_dev_kick_up(void *priv);
-
-/*
- * frame log (debug)
- */
-void
-isdn_ppp_frame_log(char *info, char *data, int len, int maxlen,int unit,int slot)
-{
-	int cnt,
-	 j,
-	 i;
-	char buf[80];
-
-	if (len < maxlen)
-		maxlen = len;
-
-	for (i = 0, cnt = 0; cnt < maxlen; i++) {
-		for (j = 0; j < 16 && cnt < maxlen; j++, cnt++)
-			sprintf(buf + j * 3, "%02x ", (unsigned char) data[cnt]);
-		printk(KERN_DEBUG "[%d/%d].%s[%d]: %s\n",unit,slot, info, i, buf);
+			break;
+		case PPPIOCSMRU:	/* set receive unit size for PPP */
+			if ((r = get_arg((void *) arg, &val, sizeof(val) )))
+				return r;
+			is->mru = val;
+			break;
+		case PPPIOCSMPMRU:
+			break;
+		case PPPIOCSMPMTU:
+			break;
+		case PPPIOCSMAXCID:	/* set the maximum compression slot id */
+			if ((r = get_arg((void *) arg, &val, sizeof(val) )))
+				return r;
+			val++;
+			if (is->maxcid != val) {
+#ifdef CONFIG_ISDN_PPP_VJ
+				struct slcompress *sltmp;
+#endif
+				if (is->debug & 0x1)
+					printk(KERN_DEBUG "ippp, ioctl: changed MAXCID to %ld\n", val);
+				is->maxcid = val;
+#ifdef CONFIG_ISDN_PPP_VJ
+				sltmp = slhc_init(16, val);
+				if (!sltmp) {
+					printk(KERN_ERR "ippp, can't realloc slhc struct\n");
+					return -ENOMEM;
+				}
+				if (is->slcomp)
+					slhc_free(is->slcomp);
+				is->slcomp = sltmp;
+#endif
+			}
+			break;
+		case PPPIOCGDEBUG:
+			if ((r = set_arg((void *) arg, &is->debug, sizeof(is->debug) )))
+				return r;
+			break;
+		case PPPIOCSDEBUG:
+			if ((r = get_arg((void *) arg, &val, sizeof(val) )))
+				return r;
+			is->debug = val;
+			break;
+		case PPPIOCGCOMPRESSORS:
+			{
+				unsigned long protos[8] = {0,};
+				struct isdn_ppp_compressor *ipc = ipc_head;
+				while(ipc) {
+					j = ipc->num / (sizeof(long)*8);
+					i = ipc->num % (sizeof(long)*8);
+					if(j < 8)
+						protos[j] |= (0x1<<i);
+					ipc = ipc->next;
+				}
+				if ((r = set_arg((void *) arg,protos,8*sizeof(long) )))
+					return r;
+			}
+			break;
+		case PPPIOCSCOMPRESSOR:
+			if ((r = get_arg((void *) arg, &data, sizeof(struct isdn_ppp_comp_data))))
+				return r;
+			return isdn_ppp_set_compressor(is, &data);
+		case PPPIOCGCALLINFO:
+			{
+				struct pppcallinfo pci;
+				memset((char *) &pci,0,sizeof(struct pppcallinfo));
+				if(lp)
+				{
+					strncpy(pci.local_num,lp->msn,63);
+					if(lp->dial) {
+						strncpy(pci.remote_num,lp->dial->num,63);
+					}
+					pci.charge_units = lp->charge;
+					if(lp->outgoing)
+						pci.calltype = CALLTYPE_OUTGOING;
+					else
+						pci.calltype = CALLTYPE_INCOMING;
+					if(lp->flags & ISDN_NET_CALLBACK)
+						pci.calltype |= CALLTYPE_CALLBACK;
+				}
+				return set_arg((void *)arg,&pci,sizeof(struct pppcallinfo));
+			}
+#ifdef CONFIG_IPPP_FILTER
+		case PPPIOCSPASS:
+		case PPPIOCSACTIVE:
+			{
+				struct sock_fprog uprog, *filtp;
+				struct sock_filter *code = NULL;
+				int len, err;
+
+				if (copy_from_user(&uprog, (void *) arg, sizeof(uprog)))
+					return -EFAULT;
+				if (uprog.len > 0 && uprog.len < 65536) {
+					len = uprog.len * sizeof(struct sock_filter);
+					code = kmalloc(len, GFP_KERNEL);
+					if (code == NULL)
+						return -ENOMEM;
+					if (copy_from_user(code, uprog.filter, len)) {
+						kfree(code);
+						return -EFAULT;
+					}
+					err = sk_chk_filter(code, uprog.len);
+					if (err) {
+						kfree(code);
+						return err;
+					}
+				}
+				filtp = (cmd == PPPIOCSPASS) ? &is->pass_filter : &is->active_filter;
+				if (filtp->filter)
+					kfree(filtp->filter);
+				filtp->filter = code;
+				filtp->len = uprog.len;
+				break;
+			}
+#endif /* CONFIG_IPPP_FILTER */
+		default:
+			break;
 	}
+	return 0;
 }
 
-void
-ippp_push_proto(struct ind_ppp *ind_ppp, struct sk_buff *skb, u16 proto)
+unsigned int
+isdn_ppp_poll(struct file *file, poll_table * wait)
 {
-	if (skb_headroom(skb) < 2) {
-		isdn_BUG();
-		return;
-	}
-	if ((ind_ppp->pppcfg & SC_COMP_PROT) && proto <= 0xff)
-		put_u8(skb_push(skb, 1), proto);
-	else
-		put_u16(skb_push(skb, 2), proto);
+	u_int mask;
+	struct ippp_buf_queue *bf, *bl;
+	u_long flags;
+	struct ippp_struct *is;
 
-}
+	is = file->private_data;
 
-static void
-ippp_push_ac(struct ind_ppp *ind_ppp, struct sk_buff *skb)
-{
-	unsigned char *p;
+	if (is->debug & 0x2)
+		printk(KERN_DEBUG "isdn_ppp_poll: minor: %d\n",
+				MINOR(file->f_dentry->d_inode->i_rdev));
 
-	if (skb_headroom(skb) < 2) {
-		isdn_BUG();
-		return;
+	/* just registers wait_queue hook. This doesn't really wait. */
+	poll_wait(file, &is->wq, wait);
+
+	if (!(is->state & IPPP_OPEN)) {
+		if(is->state == IPPP_CLOSEWAIT)
+			return POLLHUP;
+		printk(KERN_DEBUG "isdn_ppp: device not open\n");
+		return POLLERR;
 	}
-	if (ind_ppp->pppcfg & SC_COMP_AC)
-		return;
+	/* we're always ready to send .. */
+	mask = POLLOUT | POLLWRNORM;
 
-	p = skb_push(skb, 2);	
-	p += put_u8(p, PPP_ALLSTATIONS);
-	p += put_u8(p, PPP_UI);
+	spin_lock_irqsave(&is->buflock, flags);
+	bl = is->last;
+	bf = is->first;
+	/*
+	 * if IPPP_NOBLOCK is set we return even if we have nothing to read
+	 */
+	if (bf->next != bl || (is->state & IPPP_NOBLOCK)) {
+		is->state &= ~IPPP_NOBLOCK;
+		mask |= POLLIN | POLLRDNORM;
+	}
+	spin_unlock_irqrestore(&is->buflock, flags);
+	return mask;
 }
 
 /*
- * unbind isdn_net_local <=> ippp-device
- * note: it can happen, that we hangup/free the master before the slaves
- *       in this case we bind another lp to the master device
+ *  fill up isdn_ppp_read() queue ..
  */
-static void
-isdn_ppp_unbind(isdn_net_dev *idev)
-{
-	struct ind_ppp *ind_ppp = idev->ind_priv;
-	struct ipppd *is = ind_ppp->ipppd;
-	
-	if (!is) {
-		isdn_BUG();
-		return;
-	}
-	ipppd_debug(is, "");
-
-	if (is->state != IPPPD_ST_ASSIGNED)
-		isdn_BUG();
 
-	is->state = IPPPD_ST_OPEN;
-
-	/* is->idev will be invalid shortly */
-	ippp_ccp_free(ind_ppp->ccp);
-
-	is->idev = NULL;
-	/* lose the reference we took on isdn_ppp_bind */
-	ipppd_put(is); 
-	ind_ppp->ipppd = NULL;
+static int
+isdn_ppp_fill_rq(unsigned char *buf, int len, int proto, int slot)
+{
+	struct ippp_buf_queue *bf, *bl;
+	u_long flags;
+	u_char *nbuf;
+	struct ippp_struct *is;
 
-	kfree(ind_ppp);
-	idev->ind_priv = NULL;
+	if (slot < 0 || slot >= ISDN_MAX_CHANNELS) {
+		printk(KERN_WARNING "ippp: illegal slot(%d).\n", slot);
+		return 0;
+	}
+	is = ippp_table[slot];
 
-	return;
+	if (!(is->state & IPPP_CONNECT)) {
+		printk(KERN_DEBUG "ippp: device not activated.\n");
+		return 0;
+	}
+	nbuf = (unsigned char *) kmalloc(len + 4, GFP_ATOMIC);
+	if (!nbuf) {
+		printk(KERN_WARNING "ippp: Can't alloc buf\n");
+		return 0;
+	}
+	nbuf[0] = PPP_ALLSTATIONS;
+	nbuf[1] = PPP_UI;
+	nbuf[2] = proto >> 8;
+	nbuf[3] = proto & 0xff;
+	memcpy(nbuf + 4, buf, len);
+
+	spin_lock_irqsave(&is->buflock, flags);
+	bf = is->first;
+	bl = is->last;
+
+	if (bf == bl) {
+		printk(KERN_WARNING "ippp: Queue is full; discarding first buffer\n");
+		bf = bf->next;
+		kfree(bf->buf);
+		is->first = bf;
+	}
+	bl->buf = (char *) nbuf;
+	bl->len = len + 4;
+
+	is->last = bl->next;
+	spin_unlock_irqrestore(&is->buflock, flags);
+	wake_up_interruptible(&is->wq);
+	return len;
 }
 
 /*
- * bind isdn_net_local <=> ippp-device
+ * read() .. non-blocking: ipppd calls it only after select()
+ *           reports, that there is data
  */
+
 int
-isdn_ppp_bind(isdn_net_dev *idev)
+isdn_ppp_read(int min, struct file *file, char *buf, int count)
 {
-	struct ind_ppp *ind_ppp;
-	int unit = 0;
-	unsigned long flags;
-	int retval = 0;
-	struct ipppd *ipppd;
-
-	if (idev->ind_priv) {
-		isdn_BUG();
-		return -EIO;
-	}
-	ind_ppp = kmalloc(sizeof(struct ind_ppp), GFP_KERNEL);
-	if (!ind_ppp)
-		return -ENOMEM;
-
-	spin_lock_irqsave(&ipppds_lock, flags);
-	if (idev->pppbind < 0) {  /* device not bound to ippp device ? */
-		struct list_head *l;
-		char exclusive[ISDN_MAX_CHANNELS];	/* exclusive flags */
-		memset(exclusive, 0, ISDN_MAX_CHANNELS);
-		/* step through net devices to find exclusive minors */
-		list_for_each(l, &isdn_net_devs) {
-			isdn_net_dev *p = list_entry(l, isdn_net_dev, global_list);
-			if (p->pppbind >= 0 && p->pppbind < ISDN_MAX_CHANNELS)
-				exclusive[p->pppbind] = 1;
-		}
-		/*
-		 * search a free device / slot
-		 */
-		list_for_each_entry(ipppd, &ipppds, ipppds) {
-			if (!ipppd)
-				continue;
-			if (ipppd->state != IPPPD_ST_OPEN)
-				continue;
-			if (!exclusive[ipppd->minor])
-				goto found;
-		}
-	} else {
-		list_for_each_entry(ipppd, &ipppds, ipppds) {
-			if (!ipppd)
-				continue;
-			if (ipppd->state != IPPPD_ST_OPEN)
-				continue;
-			if (ipppd->minor == idev->pppbind)
-				goto found;
-		}
-	}
+	struct ippp_struct *is;
+	struct ippp_buf_queue *b;
+	int r;
+	u_long flags;
+	u_char *save_buf;
 
-	printk(KERN_INFO "isdn_ppp_bind: no ipppd\n");
-	retval = -ESRCH;
-	goto err;
+	is = file->private_data;
 
- found:
-	unit = isdn_ppp_if_get_unit(idev->name);	/* get unit number from interface name .. ugly! */
-	if (unit < 0) {
-		printk(KERN_INFO "isdn_ppp_bind: invalid interface name %s.\n", idev->name);
-		retval = -ENODEV;
-		goto err;
-	}
-	
-	ipppd->unit = unit;
-	ipppd->state = IPPPD_ST_ASSIGNED;
-	ipppd->idev = idev;
-	/* we hold a reference until isdn_ppp_unbind() */
-	ipppd_get(ipppd);
-	spin_unlock_irqrestore(&ipppds_lock, flags);
-
-	idev->ind_priv = ind_ppp;
-	ind_ppp->pppcfg = 0;         /* config flags */
-	ind_ppp->ipppd = ipppd;
-	ind_ppp->ccp = ippp_ccp_alloc();
-	if (!ind_ppp->ccp) {
-		retval = -ENOMEM;
-		goto out;
-	}
-	ind_ppp->ccp->proto       = PPP_COMPFRAG;
-	ind_ppp->ccp->priv        = idev;
-	ind_ppp->ccp->alloc_skb   = isdn_ppp_dev_alloc_skb;
-	ind_ppp->ccp->xmit        = isdn_ppp_dev_xmit;
-	ind_ppp->ccp->kick_up     = isdn_ppp_dev_kick_up;
+	if (!(is->state & IPPP_OPEN))
+		return 0;
 
-	retval = ippp_mp_bind(idev);
-	if (retval)
-		goto out;
-	
-	return 0;
+	if ((r = verify_area(VERIFY_WRITE, (void *) buf, count)))
+		return r;
 
- out:
-	ipppd->state = IPPPD_ST_OPEN;
-	ipppd_put(ipppd);
-	ind_ppp->ipppd = NULL;
-	kfree(ind_ppp);
-	idev->ind_priv = NULL;
-	return retval;
+	spin_lock_irqsave(&is->buflock, flags);
+	b = is->first->next;
+	save_buf = b->buf;
+	if (!save_buf) {
+		spin_unlock_irqrestore(&is->buflock, flags);
+		return -EAGAIN;
+	}
+	if (b->len < count)
+		count = b->len;
+	b->buf = NULL;
+	is->first = b;
+
+	spin_unlock_irqrestore(&is->buflock, flags);
+	copy_to_user(buf, save_buf, count);
+	kfree(save_buf);
 
- err:
-	spin_unlock_irqrestore(&ipppds_lock, flags);
-	kfree(ind_ppp);
-	return retval;
+	return count;
 }
 
 /*
- * kick the ipppd on the device
- * (wakes up daemon after B-channel connect)
+ * ipppd wanna write a packet to the card .. non-blocking
  */
 
-static void
-isdn_ppp_connected(isdn_net_dev *idev)
+int
+isdn_ppp_write(int min, struct file *file, const char *buf, int count)
 {
-	struct ind_ppp *ind_ppp = idev->ind_priv;
-	struct ipppd *ipppd = ind_ppp->ipppd;
+	isdn_net_local *lp;
+	struct ippp_struct *is;
+	int proto;
+	unsigned char protobuf[4];
 
-	ipppd_debug(ipppd, "");
+	is = file->private_data;
 
-	ipppd->state  = IPPPD_ST_CONNECTED;
-	ipppd->flags |= IPPPD_FL_WAKEUP;
-	wake_up(&ipppd->wq);
-}
+	if (!(is->state & IPPP_CONNECT))
+		return 0;
 
-static void
-isdn_ppp_disconnected(isdn_net_dev *idev)
-{
-	struct ind_ppp *ind_ppp = idev->ind_priv;
-	struct ipppd *ipppd = ind_ppp->ipppd;
+	lp = is->lp;
 
-	ipppd_debug(ipppd, "");
+	/* -> push it directly to the lowlevel interface */
 
-	if (ind_ppp->pppcfg & SC_ENABLE_IP)
-		isdn_net_offline(idev);
+	if (!lp)
+		printk(KERN_DEBUG "isdn_ppp_write: lp == NULL\n");
+	else {
+		/*
+		 * Don't reset huptimer for
+		 * LCP packets. (Echo requests).
+		 */
+		if (copy_from_user(protobuf, buf, 4))
+			return -EFAULT;
+		proto = PPP_PROTOCOL(protobuf);
+		if (proto != PPP_LCP)
+			lp->huptimer = 0;
+
+		if (lp->isdn_device < 0 || lp->isdn_channel < 0)
+			return 0;
+
+		if ((dev->drv[lp->isdn_device]->flags & DRV_FLAG_RUNNING) &&
+			lp->dialstate == 0 &&
+		    (lp->flags & ISDN_NET_CONNECTED)) {
+			unsigned short hl;
+			struct sk_buff *skb;
+			/*
+			 * we need to reserve enought space in front of
+			 * sk_buff. old call to dev_alloc_skb only reserved
+			 * 16 bytes, now we are looking what the driver want
+			 */
+			hl = dev->drv[lp->isdn_device]->interface->hl_hdrlen;
+			skb = alloc_skb(hl+count, GFP_ATOMIC);
+			if (!skb) {
+				printk(KERN_WARNING "isdn_ppp_write: out of memory!\n");
+				return count;
+			}
+			skb_reserve(skb, hl);
+			if (copy_from_user(skb_put(skb, count), buf, count))
+			{
+				kfree_skb(skb);
+				return -EFAULT;
+			}
+			if (is->debug & 0x40) {
+				printk(KERN_DEBUG "ppp xmit: len %d\n", (int) skb->len);
+				isdn_ppp_frame_log("xmit", skb->data, skb->len, 32,is->unit,lp->ppp_slot);
+			}
 
-	if (ipppd->state != IPPPD_ST_CONNECTED)
-		isdn_BUG();
-	
-	ipppd->state  = IPPPD_ST_ASSIGNED;
-	ipppd->flags |= IPPPD_FL_HUP;
-	wake_up(&ipppd->wq);
+			isdn_ppp_send_ccp(lp->netdev,lp,skb); /* keeps CCP/compression states in sync */
 
-	ippp_mp_disconnected(idev);
+			isdn_net_write_super(lp, skb);
+		}
+	}
+	return count;
 }
 
 /*
@@ -807,44 +847,76 @@ isdn_ppp_disconnected(isdn_net_dev *idev
 int
 isdn_ppp_init(void)
 {
+	int i,
+	 j;
+	 
+#ifdef CONFIG_ISDN_MPP
+	if( isdn_ppp_mp_bundle_array_init() < 0 )
+		return -ENOMEM;
+#endif /* CONFIG_ISDN_MPP */
+
+	for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
+		if (!(ippp_table[i] = (struct ippp_struct *)
+		      kmalloc(sizeof(struct ippp_struct), GFP_KERNEL))) {
+			printk(KERN_WARNING "isdn_ppp_init: Could not alloc ippp_table\n");
+			for (j = 0; j < i; j++)
+				kfree(ippp_table[j]);
+			return -1;
+		}
+		memset((char *) ippp_table[i], 0, sizeof(struct ippp_struct));
+		spin_lock_init(&ippp_table[i]->buflock);
+		ippp_table[i]->state = 0;
+		ippp_table[i]->first = ippp_table[i]->rq + NUM_RCV_BUFFS - 1;
+		ippp_table[i]->last = ippp_table[i]->rq;
+
+		for (j = 0; j < NUM_RCV_BUFFS; j++) {
+			ippp_table[i]->rq[j].buf = NULL;
+			ippp_table[i]->rq[j].last = ippp_table[i]->rq +
+			    (NUM_RCV_BUFFS + j - 1) % NUM_RCV_BUFFS;
+			ippp_table[i]->rq[j].next = ippp_table[i]->rq + (j + 1) % NUM_RCV_BUFFS;
+		}
+	}
 	return 0;
 }
 
 void
 isdn_ppp_cleanup(void)
 {
+	int i;
+
+	for (i = 0; i < ISDN_MAX_CHANNELS; i++)
+		kfree(ippp_table[i]);
+
+#ifdef CONFIG_ISDN_MPP
+	if (isdn_ppp_bundle_arr)
+		kfree(isdn_ppp_bundle_arr);
+#endif /* CONFIG_ISDN_MPP */
+
 }
 
 /*
  * check for address/control field and skip if allowed
  * retval != 0 -> discard packet silently
  */
-static int
-isdn_ppp_skip_ac(struct ind_ppp *ind_ppp, struct sk_buff *skb) 
+static int isdn_ppp_skip_ac(struct ippp_struct *is, struct sk_buff *skb) 
 {
-	u8 val;
-
 	if (skb->len < 1)
-		return -EINVAL;
-
-	get_u8(skb->data, &val);
-	if (val != PPP_ALLSTATIONS) {
-		/* if AC compression was not negotiated, but no AC present,
-		   discard packet */
-		if (ind_ppp->pppcfg & SC_REJ_COMP_AC)
-			return -EINVAL;
+		return -1;
 
-		return 0;
-	}
-	if (skb->len < 2)
-		return -EINVAL;
+	if (skb->data[0] == 0xff) {
+		if (skb->len < 2)
+			return -1;
 
-	get_u8(skb->data + 1, &val);
-	if (val != PPP_UI)
-		return -EINVAL;
+		if (skb->data[1] != 0x03)
+			return -1;
 
-	/* skip address/control (AC) field */
-	skb_pull(skb, 2);
+		// skip address/control (AC) field
+		skb_pull(skb, 2);
+	} else { 
+		if (is->pppcfg & SC_REJ_COMP_AC)
+			// if AC compression was not negotiated, but used, discard packet
+			return -1;
+	}
 	return 0;
 }
 
@@ -852,127 +924,262 @@ isdn_ppp_skip_ac(struct ind_ppp *ind_ppp
  * get the PPP protocol header and pull skb
  * retval < 0 -> discard packet silently
  */
-int
-isdn_ppp_strip_proto(struct sk_buff *skb, u16 *proto) 
+static int isdn_ppp_strip_proto(struct sk_buff *skb) 
 {
-	u8 val;
-
+	int proto;
+	
 	if (skb->len < 1)
-		return -EINVAL;
+		return -1;
 
-	get_u8(skb->data, &val);
-	if (val & 0x1) {
-		/* protocol field is compressed */
-		*proto = val;
+	if (skb->data[0] & 0x1) {
+		// protocol field is compressed
+		proto = skb->data[0];
 		skb_pull(skb, 1);
 	} else {
 		if (skb->len < 2)
-			return -EINVAL;
-		get_u16(skb->data, proto);
+			return -1;
+		proto = ((int) skb->data[0] << 8) + skb->data[1];
 		skb_pull(skb, 2);
 	}
-	return 0;
+	return proto;
 }
 
+
 /*
  * handler for incoming packets on a syncPPP interface
  */
-static void
-isdn_ppp_receive(isdn_net_local *lp, isdn_net_dev *idev, struct sk_buff *skb)
+void isdn_ppp_receive(isdn_net_dev * net_dev, isdn_net_local * lp, struct sk_buff *skb)
 {
-	struct ind_ppp *ind_ppp = idev->ind_priv;
-	struct ipppd *is = ind_ppp->ipppd;
-	u16 proto;
-
-	if (!is) 
-		goto err;
-
-	if (is->debug & 0x4) {
-		printk(KERN_DEBUG "ippp_receive: is:%p lp:%p unit:%d len:%d\n",
-		       is, lp, is->unit, skb->len);
-		isdn_ppp_frame_log("receive", skb->data, skb->len, 32,is->unit,-1);
+	struct ippp_struct *is;
+	int slot;
+	int proto;
+
+	if (net_dev->local->master)
+		BUG(); // we're called with the master device always
+
+	slot = lp->ppp_slot;
+	if (slot < 0 || slot > ISDN_MAX_CHANNELS) {
+		printk(KERN_ERR "isdn_ppp_receive: lp->ppp_slot(%d)\n",
+			lp->ppp_slot);
+		kfree_skb(skb);
+		return;
 	}
+	is = ippp_table[slot];
 
- 	if (isdn_ppp_skip_ac(ind_ppp, skb) < 0)
-		goto err;
-
-  	if (isdn_ppp_strip_proto(skb, &proto))
-		goto err;
-
-	ippp_mp_receive(idev, skb, proto);
-	return;
-
- err:
-	lp->stats.rx_dropped++;
-	kfree_skb(skb);
+	if (is->debug & 0x4) {
+		printk(KERN_DEBUG "ippp_receive: is:%08lx lp:%08lx slot:%d unit:%d len:%d\n",
+		       (long)is,(long)lp,lp->ppp_slot,is->unit,(int) skb->len);
+		isdn_ppp_frame_log("receive", skb->data, skb->len, 32,is->unit,lp->ppp_slot);
+	}
+
+ 	if (isdn_ppp_skip_ac(is, skb) < 0) {
+ 		kfree_skb(skb);
+ 		return;
+ 	}
+  	proto = isdn_ppp_strip_proto(skb);
+ 	if (proto < 0) {
+ 		kfree_skb(skb);
+ 		return;
+ 	}
+  
+#ifdef CONFIG_ISDN_MPP
+ 	if (is->compflags & SC_LINK_DECOMP_ON) {
+ 		skb = isdn_ppp_decompress(skb, is, NULL, &proto);
+ 		if (!skb) // decompression error
+ 			return;
+ 	}
+	
+ 	if (!(is->mpppcfg & SC_REJ_MP_PROT)) { // we agreed to receive MPPP
+  		if (proto == PPP_MP) {
+  			isdn_ppp_mp_receive(net_dev, lp, skb);
+ 			return;
+ 		}
+ 	} 
+#endif
+ 	isdn_ppp_push_higher(net_dev, lp, skb, proto);
 }
 
 /*
+ * we receive a reassembled frame, MPPP has been taken care of before.
  * address/control and protocol have been stripped from the skb
+ * note: net_dev has to be master net_dev
  */
-void
-ippp_receive(isdn_net_dev *idev, struct sk_buff *skb, u16 proto)
+static void
+isdn_ppp_push_higher(isdn_net_dev * net_dev, isdn_net_local * lp, struct sk_buff *skb, int proto)
 {
-	isdn_net_local *lp = idev->mlp;
-	struct inl_ppp *inl_ppp = lp->inl_priv;
-	struct ind_ppp *ind_ppp = idev->ind_priv;
- 	struct ipppd *is = ind_ppp->ipppd;
+	struct net_device *dev = &net_dev->dev;
+ 	struct ippp_struct *is, *mis;
+	isdn_net_local *mlp = NULL;
+	int slot;
+
+	slot = lp->ppp_slot;
+	if (slot < 0 || slot > ISDN_MAX_CHANNELS) {
+		printk(KERN_ERR "isdn_ppp_push_higher: lp->ppp_slot(%d)\n",
+			lp->ppp_slot);
+		goto drop_packet;
+	}
+	is = ippp_table[slot];
+ 	
+ 	if (lp->master) { // FIXME?
+		mlp = (isdn_net_local *) lp->master->priv;
+ 		slot = mlp->ppp_slot;
+ 		if (slot < 0 || slot > ISDN_MAX_CHANNELS) {
+ 			printk(KERN_ERR "isdn_ppp_push_higher: master->ppp_slot(%d)\n",
+ 				lp->ppp_slot);
+			goto drop_packet;
+ 		}
+ 	}
+ 	mis = ippp_table[slot];
 
 	if (is->debug & 0x10) {
 		printk(KERN_DEBUG "push, skb %d %04x\n", (int) skb->len, proto);
-		isdn_ppp_frame_log("rpush", skb->data, skb->len, 256, is->unit, -1);
+		isdn_ppp_frame_log("rpush", skb->data, skb->len, 32,is->unit,lp->ppp_slot);
 	}
-	/* all packets need to be passed through the compressor */
-	skb = ippp_ccp_decompress(inl_ppp->ccp, skb, &proto);
-	if (!skb) /* decompression error */
-		goto error;
-
+	if (mis->compflags & SC_DECOMP_ON) {
+		skb = isdn_ppp_decompress(skb, is, mis, &proto);
+		if (!skb) // decompression error
+  			return;
+  	}
 	switch (proto) {
 		case PPP_IPX:  /* untested */
 			if (is->debug & 0x20)
 				printk(KERN_DEBUG "isdn_ppp: IPX\n");
-			isdn_netif_rx(idev, skb, htons(ETH_P_IPX));
+			skb->protocol = htons(ETH_P_IPX);
 			break;
 		case PPP_IP:
 			if (is->debug & 0x20)
 				printk(KERN_DEBUG "isdn_ppp: IP\n");
-			isdn_netif_rx(idev, skb, htons(ETH_P_IP));
+			skb->protocol = htons(ETH_P_IP);
 			break;
 		case PPP_COMP:
 		case PPP_COMPFRAG:
 			printk(KERN_INFO "isdn_ppp: unexpected compressed frame dropped\n");
-			goto drop;
+			goto drop_packet;
+#ifdef CONFIG_ISDN_PPP_VJ
 		case PPP_VJC_UNCOMP:
+			if (is->debug & 0x20)
+				printk(KERN_DEBUG "isdn_ppp: VJC_UNCOMP\n");
+			if (net_dev->local->ppp_slot < 0) {
+				printk(KERN_ERR "%s: net_dev->local->ppp_slot(%d) out of range\n",
+					__FUNCTION__, net_dev->local->ppp_slot);
+				goto drop_packet;
+			}
+			if (slhc_remember(ippp_table[net_dev->local->ppp_slot]->slcomp, skb->data, skb->len) <= 0) {
+				printk(KERN_WARNING "isdn_ppp: received illegal VJC_UNCOMP frame!\n");
+				goto drop_packet;
+			}
+			skb->protocol = htons(ETH_P_IP);
+			break;
 		case PPP_VJC_COMP:
-			ippp_vj_decompress(idev, skb, proto);
+			if (is->debug & 0x20)
+				printk(KERN_DEBUG "isdn_ppp: VJC_COMP\n");
+			{
+				struct sk_buff *skb_old = skb;
+				int pkt_len;
+				skb = dev_alloc_skb(skb_old->len + 128);
+
+				if (!skb) {
+					printk(KERN_WARNING "%s: Memory squeeze, dropping packet.\n", dev->name);
+					skb = skb_old;
+					goto drop_packet;
+				}
+				skb_put(skb, skb_old->len + 128);
+				memcpy(skb->data, skb_old->data, skb_old->len);
+				if (net_dev->local->ppp_slot < 0) {
+					printk(KERN_ERR "%s: net_dev->local->ppp_slot(%d) out of range\n",
+						__FUNCTION__, net_dev->local->ppp_slot);
+					goto drop_packet;
+				}
+				pkt_len = slhc_uncompress(ippp_table[net_dev->local->ppp_slot]->slcomp,
+						skb->data, skb_old->len);
+				kfree_skb(skb_old);
+				if (pkt_len < 0)
+					goto drop_packet;
+
+				skb_trim(skb, pkt_len);
+				skb->protocol = htons(ETH_P_IP);
+			}
 			break;
-		case PPP_CCPFRAG:
-			ippp_ccp_receive_ccp(ind_ppp->ccp, skb);
-			goto ccp;
+#endif
 		case PPP_CCP:
-			ippp_ccp_receive_ccp(inl_ppp->ccp, skb);
-	ccp:
+		case PPP_CCPFRAG:
+			isdn_ppp_receive_ccp(net_dev,lp,skb,proto);
 			/* Dont pop up ResetReq/Ack stuff to the daemon any
 			   longer - the job is done already */
 			if(skb->data[0] == CCP_RESETREQ ||
 			   skb->data[0] == CCP_RESETACK)
-				goto free;
+				break;
 			/* fall through */
 		default:
-			// FIXME use skb directly
-			ipppd_queue_read(is, proto, skb->data, skb->len);
-			goto free;
+			isdn_ppp_fill_rq(skb->data, skb->len, proto, lp->ppp_slot);	/* push data to pppd device */
+			kfree_skb(skb);
+			return;
+	}
+
+#ifdef CONFIG_IPPP_FILTER
+	/* check if the packet passes the pass and active filters
+	 * the filter instructions are constructed assuming
+	 * a four-byte PPP header on each packet (which is still present) */
+	skb_push(skb, 4);
+	skb->data[0] = 0;	/* indicate inbound */
+
+	if (is->pass_filter.filter
+	    && sk_run_filter(skb, is->pass_filter.filter,
+	                    is->pass_filter.len) == 0) {
+		if (is->debug & 0x2)
+			printk(KERN_DEBUG "IPPP: inbound frame filtered.\n");
+		kfree_skb(skb);
+		return;
 	}
+	if (!(is->active_filter.filter
+	      && sk_run_filter(skb, is->active_filter.filter,
+	                       is->active_filter.len) == 0)) {
+		if (is->debug & 0x2)
+			printk(KERN_DEBUG "IPPP: link-active filter: reseting huptimer.\n");
+		lp->huptimer = 0;
+		if (mlp)
+			mlp->huptimer = 0;
+	}
+	skb_pull(skb, 4);
+#else /* CONFIG_IPPP_FILTER */
+	lp->huptimer = 0;
+	if (mlp)
+		mlp->huptimer = 0;
+#endif /* CONFIG_IPPP_FILTER */
+	skb->dev = dev;
+	skb->mac.raw = skb->data;
+	netif_rx(skb);
+	/* net_dev->local->stats.rx_packets++; done in isdn_net.c */
 	return;
 
- drop:
-	lp->stats.rx_dropped++;
- free:
+ drop_packet:
+	net_dev->local->stats.rx_dropped++;
 	kfree_skb(skb);
-	return;
+}
+
+/*
+ * isdn_ppp_skb_push ..
+ * checks whether we have enough space at the beginning of the skb
+ * and allocs a new SKB if necessary
+ */
+static unsigned char *isdn_ppp_skb_push(struct sk_buff **skb_p,int len)
+{
+	struct sk_buff *skb = *skb_p;
+
+	if(skb_headroom(skb) < len) {
+		struct sk_buff *nskb = skb_realloc_headroom(skb, len);
 
- error:
-	lp->stats.rx_dropped++;
+		if (!nskb) {
+			printk(KERN_ERR "isdn_ppp_skb_push: can't realloc headroom!\n");
+			dev_kfree_skb(skb);
+			return NULL;
+		}
+		printk(KERN_DEBUG "isdn_ppp_skb_push:under %d %d\n",skb_headroom(skb),len);
+		dev_kfree_skb(skb);
+		*skb_p = nskb;
+		return skb_push(nskb, len);
+	}
+	return skb_push(skb,len);
 }
 
 /*
@@ -983,99 +1190,773 @@ ippp_receive(isdn_net_dev *idev, struct 
  * skb isn't allowed!!
  */
 
-static int
-isdn_ppp_start_xmit(struct sk_buff *skb, struct net_device *ndev)
+int
+isdn_ppp_xmit(struct sk_buff *skb, struct net_device *netdev)
+{
+	isdn_net_local *lp,*mlp;
+	isdn_net_dev *nd;
+	unsigned int proto = PPP_IP;     /* 0x21 */
+	struct ippp_struct *ipt,*ipts;
+	int slot, retval = 0;
+
+	mlp = (isdn_net_local *) (netdev->priv);
+	nd = mlp->netdev;       /* get master lp */
+
+	slot = mlp->ppp_slot;
+	if (slot < 0 || slot > ISDN_MAX_CHANNELS) {
+		printk(KERN_ERR "isdn_ppp_xmit: lp->ppp_slot(%d)\n",
+			mlp->ppp_slot);
+		kfree_skb(skb);
+		goto out;
+	}
+	ipts = ippp_table[slot];
+
+	if (!(ipts->pppcfg & SC_ENABLE_IP)) {	/* PPP connected ? */
+		if (ipts->debug & 0x1)
+			printk(KERN_INFO "%s: IP frame delayed.\n", netdev->name);
+		retval = 1;
+		goto out;
+	}
+
+	switch (ntohs(skb->protocol)) {
+		case ETH_P_IP:
+			proto = PPP_IP;
+			break;
+		case ETH_P_IPX:
+			proto = PPP_IPX;	/* untested */
+			break;
+		default:
+			printk(KERN_ERR "isdn_ppp: skipped unsupported protocol: %#x.\n", 
+			       skb->protocol);
+			dev_kfree_skb(skb);
+			goto out;
+	}
+
+	lp = isdn_net_get_locked_lp(nd);
+	if (!lp) {
+		printk(KERN_WARNING "%s: all channels busy - requeuing!\n", netdev->name);
+		retval = 1;
+		goto out;
+	}
+	/* we have our lp locked from now on */
+
+	slot = lp->ppp_slot;
+	if (slot < 0 || slot > ISDN_MAX_CHANNELS) {
+		printk(KERN_ERR "isdn_ppp_xmit: lp->ppp_slot(%d)\n",
+			lp->ppp_slot);
+		kfree_skb(skb);
+		goto unlock;
+	}
+	ipt = ippp_table[slot];
+
+	/*
+	 * after this line .. requeueing in the device queue is no longer allowed!!!
+	 */
+
+	/* Pull off the fake header we stuck on earlier to keep
+	 * the fragmentation code happy.
+	 */
+	skb_pull(skb,IPPP_MAX_HEADER);
+
+#ifdef CONFIG_IPPP_FILTER
+	/* check if we should pass this packet
+	 * the filter instructions are constructed assuming
+	 * a four-byte PPP header on each packet */
+	skb_push(skb, 4);
+	skb->data[0] = 1;	/* indicate outbound */
+	*(u_int16_t *)(skb->data + 2) = htons(proto);
+
+	if (ipt->pass_filter.filter 
+	    && sk_run_filter(skb, ipt->pass_filter.filter,
+		             ipt->pass_filter.len) == 0) {
+		if (ipt->debug & 0x4)
+			printk(KERN_DEBUG "IPPP: outbound frame filtered.\n");
+		kfree_skb(skb);
+		goto unlock;
+	}
+	if (!(ipt->active_filter.filter
+	      && sk_run_filter(skb, ipt->active_filter.filter,
+		               ipt->active_filter.len) == 0)) {
+		if (ipt->debug & 0x4)
+			printk(KERN_DEBUG "IPPP: link-active filter: reseting huptimer.\n");
+		lp->huptimer = 0;
+	}
+	skb_pull(skb, 4);
+#else /* CONFIG_IPPP_FILTER */
+	lp->huptimer = 0;
+#endif /* CONFIG_IPPP_FILTER */
+
+	if (ipt->debug & 0x4)
+		printk(KERN_DEBUG "xmit skb, len %d\n", (int) skb->len);
+        if (ipts->debug & 0x40)
+                isdn_ppp_frame_log("xmit0", skb->data, skb->len, 32,ipts->unit,lp->ppp_slot);
+
+#ifdef CONFIG_ISDN_PPP_VJ
+	if (proto == PPP_IP && ipts->pppcfg & SC_COMP_TCP) {	/* ipts here? probably yes, but check this again */
+		struct sk_buff *new_skb;
+	        unsigned short hl;
+		/*
+		 * we need to reserve enought space in front of
+		 * sk_buff. old call to dev_alloc_skb only reserved
+		 * 16 bytes, now we are looking what the driver want.
+		 */
+		hl = dev->drv[lp->isdn_device]->interface->hl_hdrlen + IPPP_MAX_HEADER;
+		/* 
+		 * Note: hl might still be insufficient because the method
+		 * above does not account for a possibible MPPP slave channel
+		 * which had larger HL header space requirements than the
+		 * master.
+		 */
+		new_skb = alloc_skb(hl+skb->len, GFP_ATOMIC);
+		if (new_skb) {
+			u_char *buf;
+			int pktlen;
+
+			skb_reserve(new_skb, hl);
+			new_skb->dev = skb->dev;
+			skb_put(new_skb, skb->len);
+			buf = skb->data;
+
+			pktlen = slhc_compress(ipts->slcomp, skb->data, skb->len, new_skb->data,
+				 &buf, !(ipts->pppcfg & SC_NO_TCP_CCID));
+
+			if (buf != skb->data) {	
+				if (new_skb->data != buf)
+					printk(KERN_ERR "isdn_ppp: FATAL error after slhc_compress!!\n");
+				dev_kfree_skb(skb);
+				skb = new_skb;
+			} else {
+				dev_kfree_skb(new_skb);
+			}
+
+			skb_trim(skb, pktlen);
+			if (skb->data[0] & SL_TYPE_COMPRESSED_TCP) {	/* cslip? style -> PPP */
+				proto = PPP_VJC_COMP;
+				skb->data[0] ^= SL_TYPE_COMPRESSED_TCP;
+			} else {
+				if (skb->data[0] >= SL_TYPE_UNCOMPRESSED_TCP)
+					proto = PPP_VJC_UNCOMP;
+				skb->data[0] = (skb->data[0] & 0x0f) | 0x40;
+			}
+		}
+	}
+#endif
+
+	/*
+	 * normal (single link) or bundle compression
+	 */
+	if(ipts->compflags & SC_COMP_ON) {
+		/* We send compressed only if both down- und upstream
+		   compression is negotiated, that means, CCP is up */
+		if(ipts->compflags & SC_DECOMP_ON) {
+			skb = isdn_ppp_compress(skb,&proto,ipt,ipts,0);
+		} else {
+			printk(KERN_DEBUG "isdn_ppp: CCP not yet up - sending as-is\n");
+		}
+	}
+
+	if (ipt->debug & 0x24)
+		printk(KERN_DEBUG "xmit2 skb, len %d, proto %04x\n", (int) skb->len, proto);
+
+#ifdef CONFIG_ISDN_MPP
+	if (ipt->mpppcfg & SC_MP_PROT) {
+		/* we get mp_seqno from static isdn_net_local */
+		long mp_seqno = ipts->mp_seqno;
+		ipts->mp_seqno++;
+		if (ipt->mpppcfg & SC_OUT_SHORT_SEQ) {
+			unsigned char *data = isdn_ppp_skb_push(&skb, 3);
+			if(!data)
+				goto unlock;
+			mp_seqno &= 0xfff;
+			data[0] = MP_BEGIN_FRAG | MP_END_FRAG | ((mp_seqno >> 8) & 0xf);	/* (B)egin & (E)ndbit .. */
+			data[1] = mp_seqno & 0xff;
+			data[2] = proto;	/* PID compression */
+		} else {
+			unsigned char *data = isdn_ppp_skb_push(&skb, 5);
+			if(!data)
+				goto unlock;
+			data[0] = MP_BEGIN_FRAG | MP_END_FRAG;	/* (B)egin & (E)ndbit .. */
+			data[1] = (mp_seqno >> 16) & 0xff;	/* sequence number: 24bit */
+			data[2] = (mp_seqno >> 8) & 0xff;
+			data[3] = (mp_seqno >> 0) & 0xff;
+			data[4] = proto;	/* PID compression */
+		}
+		proto = PPP_MP; /* MP Protocol, 0x003d */
+	}
+#endif
+
+	/*
+	 * 'link in bundle' compression  ...
+	 */
+	if(ipt->compflags & SC_LINK_COMP_ON)
+		skb = isdn_ppp_compress(skb,&proto,ipt,ipts,1);
+
+	if( (ipt->pppcfg & SC_COMP_PROT) && (proto <= 0xff) ) {
+		unsigned char *data = isdn_ppp_skb_push(&skb,1);
+		if(!data)
+			goto unlock;
+		data[0] = proto & 0xff;
+	}
+	else {
+		unsigned char *data = isdn_ppp_skb_push(&skb,2);
+		if(!data)
+			goto unlock;
+		data[0] = (proto >> 8) & 0xff;
+		data[1] = proto & 0xff;
+	}
+	if(!(ipt->pppcfg & SC_COMP_AC)) {
+		unsigned char *data = isdn_ppp_skb_push(&skb,2);
+		if(!data)
+			goto unlock;
+		data[0] = 0xff;    /* All Stations */
+		data[1] = 0x03;    /* Unnumbered information */
+	}
+
+	/* tx-stats are now updated via BSENT-callback */
+
+	if (ipts->debug & 0x40) {
+		printk(KERN_DEBUG "skb xmit: len: %d\n", (int) skb->len);
+		isdn_ppp_frame_log("xmit", skb->data, skb->len, 32,ipt->unit,lp->ppp_slot);
+	}
+	
+	isdn_net_writebuf_skb(lp, skb);
+
+ unlock:
+	spin_unlock_bh(&lp->xmit_lock);
+ out:
+	return retval;
+}
+
+#ifdef CONFIG_IPPP_FILTER
+/*
+ * check if this packet may trigger auto-dial.
+ */
+
+int isdn_ppp_autodial_filter(struct sk_buff *skb, isdn_net_local *lp)
+{
+	struct ippp_struct *is = ippp_table[lp->ppp_slot];
+	u_int16_t proto;
+	int drop = 0;
+
+	switch (ntohs(skb->protocol)) {
+	case ETH_P_IP:
+		proto = PPP_IP;
+		break;
+	case ETH_P_IPX:
+		proto = PPP_IPX;
+		break;
+	default:
+		printk(KERN_ERR "isdn_ppp_autodial_filter: unsupported protocol 0x%x.\n",
+		       skb->protocol);
+		return 1;
+	}
+
+	/* the filter instructions are constructed assuming
+	 * a four-byte PPP header on each packet. we have to
+	 * temporarily remove part of the fake header stuck on
+	 * earlier.
+	 */
+	skb_pull(skb, IPPP_MAX_HEADER - 4);
+	skb->data[0] = 1;	/* indicate outbound */
+	*(u_int16_t *)(skb->data + 2) = htons(proto);
+	
+	drop |= is->pass_filter.filter
+	        && sk_run_filter(skb, is->pass_filter.filter,
+	                         is->pass_filter.len) == 0;
+	drop |= is->active_filter.filter
+	        && sk_run_filter(skb, is->active_filter.filter,
+	                         is->active_filter.len) == 0;
+	
+	skb_push(skb, IPPP_MAX_HEADER - 4);
+	return drop;
+}
+#endif
+#ifdef CONFIG_ISDN_MPP
+
+/* this is _not_ rfc1990 header, but something we convert both short and long
+ * headers to for convinience's sake:
+ * 	byte 0 is flags as in rfc1990
+ *	bytes 1...4 is 24-bit seqence number converted to host byte order 
+ */
+#define MP_HEADER_LEN	5
+
+#define MP_LONGSEQ_MASK		0x00ffffff
+#define MP_SHORTSEQ_MASK	0x00000fff
+#define MP_LONGSEQ_MAX		MP_LONGSEQ_MASK
+#define MP_SHORTSEQ_MAX		MP_SHORTSEQ_MASK
+#define MP_LONGSEQ_MAXBIT	((MP_LONGSEQ_MASK+1)>>1)
+#define MP_SHORTSEQ_MAXBIT	((MP_SHORTSEQ_MASK+1)>>1)
+
+/* sequence-wrap safe comparisions (for long sequence)*/ 
+#define MP_LT(a,b)	((a-b)&MP_LONGSEQ_MAXBIT)
+#define MP_LE(a,b) 	!((b-a)&MP_LONGSEQ_MAXBIT)
+#define MP_GT(a,b) 	((b-a)&MP_LONGSEQ_MAXBIT)
+#define MP_GE(a,b)	!((a-b)&MP_LONGSEQ_MAXBIT)
+
+#define MP_SEQ(f)	((*(u32*)(f->data+1)))
+#define MP_FLAGS(f)	(f->data[0])
+
+static int isdn_ppp_mp_bundle_array_init(void)
+{
+	int i;
+	int sz = ISDN_MAX_CHANNELS*sizeof(ippp_bundle);
+	if( (isdn_ppp_bundle_arr = (ippp_bundle*)kmalloc(sz, 
+							GFP_KERNEL)) == NULL )
+		return -ENOMEM;
+	memset(isdn_ppp_bundle_arr, 0, sz);
+	for( i = 0; i < ISDN_MAX_CHANNELS; i++ )
+		spin_lock_init(&isdn_ppp_bundle_arr[i].lock);
+	return 0;
+}
+
+static ippp_bundle * isdn_ppp_mp_bundle_alloc(void)
 {
-	isdn_net_local *mlp = ndev->priv;
-	struct inl_ppp *inl_ppp = mlp->inl_priv;
-	struct ind_ppp *ind_ppp;
-	isdn_net_dev *idev = list_entry(mlp->online.next, isdn_net_dev, online);
-	u16 proto = PPP_IP;     /* 0x21 */
-	struct ipppd *ipppd;
+	int i;
+	for( i = 0; i < ISDN_MAX_CHANNELS; i++ )
+		if (isdn_ppp_bundle_arr[i].ref_ct <= 0)
+			return (isdn_ppp_bundle_arr + i);
+	return NULL;
+}
+
+static int isdn_ppp_mp_init( isdn_net_local * lp, ippp_bundle * add_to )
+{
+	struct ippp_struct * is;
+
+	if (lp->ppp_slot < 0) {
+		printk(KERN_ERR "%s: lp->ppp_slot(%d) out of range\n",
+			__FUNCTION__, lp->ppp_slot);
+		return(-EINVAL);
+	}
+
+	is = ippp_table[lp->ppp_slot];
+	if (add_to) {
+		if( lp->netdev->pb )
+			lp->netdev->pb->ref_ct--;
+		lp->netdev->pb = add_to;
+	} else {		/* first link in a bundle */
+		is->mp_seqno = 0;
+		if ((lp->netdev->pb = isdn_ppp_mp_bundle_alloc()) == NULL)
+			return -ENOMEM;
+		lp->next = lp->last = lp;	/* nobody else in a queue */
+		lp->netdev->pb->frags = NULL;
+		lp->netdev->pb->frames = 0;
+		lp->netdev->pb->seq = LONG_MAX;
+	}
+	lp->netdev->pb->ref_ct++;
+	
+	is->last_link_seqno = 0;
+	return 0;
+}
 
-	ndev->trans_start = jiffies;
+static u32 isdn_ppp_mp_get_seq( int short_seq, 
+					struct sk_buff * skb, u32 last_seq );
+static struct sk_buff * isdn_ppp_mp_discard( ippp_bundle * mp,
+			struct sk_buff * from, struct sk_buff * to );
+static void isdn_ppp_mp_reassembly( isdn_net_dev * net_dev, isdn_net_local * lp,
+				struct sk_buff * from, struct sk_buff * to );
+static void isdn_ppp_mp_free_skb( ippp_bundle * mp, struct sk_buff * skb );
+static void isdn_ppp_mp_print_recv_pkt( int slot, struct sk_buff * skb );
+
+static void isdn_ppp_mp_receive(isdn_net_dev * net_dev, isdn_net_local * lp, 
+							struct sk_buff *skb)
+{
+	struct ippp_struct *is;
+	isdn_net_local * lpq;
+	ippp_bundle * mp;
+	isdn_mppp_stats * stats;
+	struct sk_buff * newfrag, * frag, * start, *nextf;
+	u32 newseq, minseq, thisseq;
+	unsigned long flags;
+	int slot;
 
-	if (list_empty(&mlp->online))
-		return isdn_net_autodial(skb, ndev);
+	spin_lock_irqsave(&net_dev->pb->lock, flags);
+    	mp = net_dev->pb;
+        stats = &mp->stats;
+	slot = lp->ppp_slot;
+	if (slot < 0 || slot > ISDN_MAX_CHANNELS) {
+		printk(KERN_ERR "%s: lp->ppp_slot(%d)\n",
+			__FUNCTION__, lp->ppp_slot);
+		stats->frame_drops++;
+		dev_kfree_skb(skb);
+		spin_unlock_irqrestore(&mp->lock, flags);
+		return;
+	}
+	is = ippp_table[slot];
+    	if( ++mp->frames > stats->max_queue_len )
+		stats->max_queue_len = mp->frames;
+	
+	if (is->debug & 0x8)
+		isdn_ppp_mp_print_recv_pkt(lp->ppp_slot, skb);
 
-	switch (ntohs(skb->protocol)) {
-		case ETH_P_IP:
-			proto = PPP_IP;
-			break;
-		case ETH_P_IPX:
-			proto = PPP_IPX;	/* untested */
+	newseq = isdn_ppp_mp_get_seq(is->mpppcfg & SC_IN_SHORT_SEQ, 
+						skb, is->last_link_seqno);
+
+
+	/* if this packet seq # is less than last already processed one,
+	 * toss it right away, but check for sequence start case first 
+	 */
+	if( mp->seq > MP_LONGSEQ_MAX && (newseq & MP_LONGSEQ_MAXBIT) ) {
+		mp->seq = newseq;	/* the first packet: required for
+					 * rfc1990 non-compliant clients --
+					 * prevents constant packet toss */
+	} else if( MP_LT(newseq, mp->seq) ) {
+		stats->frame_drops++;
+		isdn_ppp_mp_free_skb(mp, skb);
+		spin_unlock_irqrestore(&mp->lock, flags);
+		return;
+	}
+	
+	/* find the minimum received sequence number over all links */
+	is->last_link_seqno = minseq = newseq;
+	for (lpq = net_dev->queue;;) {
+		slot = lpq->ppp_slot;
+		if (slot < 0 || slot > ISDN_MAX_CHANNELS) {
+			printk(KERN_ERR "%s: lpq->ppp_slot(%d)\n",
+				__FUNCTION__, lpq->ppp_slot);
+		} else {
+			u32 lls = ippp_table[slot]->last_link_seqno;
+			if (MP_LT(lls, minseq))
+				minseq = lls;
+		}
+		if ((lpq = lpq->next) == net_dev->queue)
 			break;
-		default:
-			printk(KERN_INFO "isdn_ppp: skipped unsupported protocol: %#x.\n", 
-			       skb->protocol);
-			goto drop;
 	}
+	if (MP_LT(minseq, mp->seq))
+		minseq = mp->seq;	/* can't go beyond already processed
+					 * packets */
+	newfrag = skb;
+
+  	/* if this new fragment is before the first one, then enqueue it now. */
+  	if ((frag = mp->frags) == NULL || MP_LT(newseq, MP_SEQ(frag))) {
+		newfrag->next = frag;
+    		mp->frags = frag = newfrag;
+    		newfrag = NULL;
+  	}
+
+  	start = MP_FLAGS(frag) & MP_BEGIN_FRAG &&
+				MP_SEQ(frag) == mp->seq ? frag : NULL;
+
+	/* 
+	 * main fragment traversing loop
+	 *
+	 * try to accomplish several tasks:
+	 * - insert new fragment into the proper sequence slot (once that's done
+	 *   newfrag will be set to NULL)
+	 * - reassemble any complete fragment sequence (non-null 'start'
+	 *   indicates there is a continguous sequence present)
+	 * - discard any incomplete sequences that are below minseq -- due
+	 *   to the fact that sender always increment sequence number, if there
+	 *   is an incomplete sequence below minseq, no new fragments would
+	 *   come to complete such sequence and it should be discarded
+	 *
+	 * loop completes when we accomplished the following tasks:
+	 * - new fragment is inserted in the proper sequence ('newfrag' is 
+	 *   set to NULL)
+	 * - we hit a gap in the sequence, so no reassembly/processing is 
+	 *   possible ('start' would be set to NULL)
+	 *
+	 * algorightm for this code is derived from code in the book
+	 * 'PPP Design And Debugging' by James Carlson (Addison-Wesley)
+	 */
+  	while (start != NULL || newfrag != NULL) {
+
+    		thisseq = MP_SEQ(frag);
+    		nextf = frag->next;
+
+    		/* drop any duplicate fragments */
+    		if (newfrag != NULL && thisseq == newseq) {
+      			isdn_ppp_mp_free_skb(mp, newfrag);
+      			newfrag = NULL;
+    		}
+
+    		/* insert new fragment before next element if possible. */
+    		if (newfrag != NULL && (nextf == NULL || 
+						MP_LT(newseq, MP_SEQ(nextf)))) {
+      			newfrag->next = nextf;
+      			frag->next = nextf = newfrag;
+      			newfrag = NULL;
+    		}
+
+    		if (start != NULL) {
+	    		/* check for misplaced start */
+      			if (start != frag && (MP_FLAGS(frag) & MP_BEGIN_FRAG)) {
+				printk(KERN_WARNING"isdn_mppp(seq %d): new "
+				      "BEGIN flag with no prior END", thisseq);
+				stats->seqerrs++;
+				stats->frame_drops++;
+				start = isdn_ppp_mp_discard(mp, start,frag);
+				nextf = frag->next;
+      			}
+    		} else if (MP_LE(thisseq, minseq)) {		
+      			if (MP_FLAGS(frag) & MP_BEGIN_FRAG)
+				start = frag;
+      			else {
+				if (MP_FLAGS(frag) & MP_END_FRAG)
+	  				stats->frame_drops++;
+				if( mp->frags == frag )
+					mp->frags = nextf;	
+				isdn_ppp_mp_free_skb(mp, frag);
+				frag = nextf;
+				continue;
+      			}
+		}
+		
+		/* if start is non-null and we have end fragment, then
+		 * we have full reassembly sequence -- reassemble 
+		 * and process packet now
+		 */
+    		if (start != NULL && (MP_FLAGS(frag) & MP_END_FRAG)) {
+      			minseq = mp->seq = (thisseq+1) & MP_LONGSEQ_MASK;
+      			/* Reassemble the packet then dispatch it */
+			isdn_ppp_mp_reassembly(net_dev, lp, start, nextf);
+      
+      			start = NULL;
+      			frag = NULL;
+
+      			mp->frags = nextf;
+    		}
+
+		/* check if need to update start pointer: if we just
+		 * reassembled the packet and sequence is contiguous
+		 * then next fragment should be the start of new reassembly
+		 * if sequence is contiguous, but we haven't reassembled yet,
+		 * keep going.
+		 * if sequence is not contiguous, either clear everyting
+		 * below low watermark and set start to the next frag or
+		 * clear start ptr.
+		 */ 
+    		if (nextf != NULL && 
+		    ((thisseq+1) & MP_LONGSEQ_MASK) == MP_SEQ(nextf)) {
+      			/* if we just reassembled and the next one is here, 
+			 * then start another reassembly. */
+
+      			if (frag == NULL) {
+				if (MP_FLAGS(nextf) & MP_BEGIN_FRAG)
+	  				start = nextf;
+				else
+				{
+	  				printk(KERN_WARNING"isdn_mppp(seq %d):"
+						" END flag with no following "
+						"BEGIN", thisseq);
+					stats->seqerrs++;
+				}
+			}
 
-	idev = isdn_net_get_xmit_dev(mlp);
-	if (!idev) {
-		printk(KERN_INFO "%s: IP frame delayed.\n", ndev->name);
-		goto stop;
+    		} else {
+			if ( nextf != NULL && frag != NULL &&
+						MP_LT(thisseq, minseq)) {
+				/* we've got a break in the sequence
+				 * and we not at the end yet
+				 * and we did not just reassembled
+				 *(if we did, there wouldn't be anything before)
+				 * and we below the low watermark 
+			 	 * discard all the frames below low watermark 
+				 * and start over */
+				stats->frame_drops++;
+				mp->frags = isdn_ppp_mp_discard(mp,start,nextf);
+			}
+			/* break in the sequence, no reassembly */
+      			start = NULL;
+    		}
+	  			
+    		frag = nextf;
+  	}	/* while -- main loop */
+	
+  	if (mp->frags == NULL)
+    		mp->frags = frag;
+		
+	/* rather straighforward way to deal with (not very) possible 
+	 * queue overflow */
+	if (mp->frames > MP_MAX_QUEUE_LEN) {
+		stats->overflows++;
+		while (mp->frames > MP_MAX_QUEUE_LEN) {
+			frag = mp->frags->next;
+			isdn_ppp_mp_free_skb(mp, mp->frags);
+			mp->frags = frag;
+		}
 	}
-	ind_ppp = idev->ind_priv;
-	if (!(ind_ppp->pppcfg & SC_ENABLE_IP)) {	/* PPP connected ? */
-		isdn_BUG();
-		goto stop;
+	spin_unlock_irqrestore(&mp->lock, flags);
+}
+
+static void isdn_ppp_mp_cleanup( isdn_net_local * lp )
+{
+	struct sk_buff * frag = lp->netdev->pb->frags;
+	struct sk_buff * nextfrag;
+    	while( frag ) {
+		nextfrag = frag->next;
+		isdn_ppp_mp_free_skb(lp->netdev->pb, frag);
+		frag = nextfrag;
 	}
-	ipppd = ind_ppp->ipppd;
-	idev->huptimer = 0;
+	lp->netdev->pb->frags = NULL;
+}
 
-        if (ipppd->debug & 0x40)
-                isdn_ppp_frame_log("xmit0", skb->data, skb->len, 256, ipppd->unit, -1);
+static u32 isdn_ppp_mp_get_seq( int short_seq, 
+					struct sk_buff * skb, u32 last_seq )
+{
+	u32 seq;
+	int flags = skb->data[0] & (MP_BEGIN_FRAG | MP_END_FRAG);
+   
+   	if( !short_seq )
+	{
+		seq = ntohl(*(u32*)skb->data) & MP_LONGSEQ_MASK;
+		skb_push(skb,1);
+	}
+	else
+	{
+		/* convert 12-bit short seq number to 24-bit long one 
+	 	*/
+		seq = ntohs(*(u16*)skb->data) & MP_SHORTSEQ_MASK;
+	
+		/* check for seqence wrap */
+		if( !(seq &  MP_SHORTSEQ_MAXBIT) && 
+		     (last_seq &  MP_SHORTSEQ_MAXBIT) && 
+		     (unsigned long)last_seq <= MP_LONGSEQ_MAX )
+			seq |= (last_seq + MP_SHORTSEQ_MAX+1) & 
+					(~MP_SHORTSEQ_MASK & MP_LONGSEQ_MASK);
+		else
+			seq |= last_seq & (~MP_SHORTSEQ_MASK & MP_LONGSEQ_MASK);
+		
+		skb_push(skb, 3);	/* put converted seqence back in skb */
+	}
+	*(u32*)(skb->data+1) = seq; 	/* put seqence back in _host_ byte
+					 * order */
+	skb->data[0] = flags;	        /* restore flags */
+	return seq;
+}
+
+struct sk_buff * isdn_ppp_mp_discard( ippp_bundle * mp,
+			struct sk_buff * from, struct sk_buff * to )
+{
+	if( from )
+		while (from != to) {
+	  		struct sk_buff * next = from->next;
+			isdn_ppp_mp_free_skb(mp, from);
+	  		from = next;
+		}
+	return from;
+}
 
-	/* after this line,requeueing is no longer allowed! */
-	skb = ippp_vj_compress(idev, skb, &proto);
+void isdn_ppp_mp_reassembly( isdn_net_dev * net_dev, isdn_net_local * lp,
+				struct sk_buff * from, struct sk_buff * to )
+{
+	ippp_bundle * mp = net_dev->pb;
+	int proto;
+	struct sk_buff * skb;
+	unsigned int tot_len;
 
-	/* normal (single link) or bundle compression */
-	skb = ippp_ccp_compress(inl_ppp->ccp, skb, &proto);
+	if (lp->ppp_slot < 0 || lp->ppp_slot > ISDN_MAX_CHANNELS) {
+		printk(KERN_ERR "%s: lp->ppp_slot(%d) out of range\n",
+			__FUNCTION__, lp->ppp_slot);
+		return;
+	}
+	if( MP_FLAGS(from) == (MP_BEGIN_FRAG | MP_END_FRAG) ) {
+		if( ippp_table[lp->ppp_slot]->debug & 0x40 )
+			printk(KERN_DEBUG "isdn_mppp: reassembly: frame %d, "
+					"len %d\n", MP_SEQ(from), from->len );
+		skb = from;
+		skb_pull(skb, MP_HEADER_LEN);
+		mp->frames--;	
+	} else {
+		struct sk_buff * frag;
+		int n;
 
-	if (ipppd->debug & 0x40)
-                isdn_ppp_frame_log("xmit1", skb->data, skb->len, 32, ipppd->unit, -1);
+		for(tot_len=n=0, frag=from; frag != to; frag=frag->next, n++)
+			tot_len += frag->len - MP_HEADER_LEN;
 
-	ippp_push_proto(ind_ppp, skb, proto);
-	ippp_mp_xmit(idev, skb);
-	return 0;
+		if( ippp_table[lp->ppp_slot]->debug & 0x40 )
+			printk(KERN_DEBUG"isdn_mppp: reassembling frames %d "
+				"to %d, len %d\n", MP_SEQ(from), 
+				(MP_SEQ(from)+n-1) & MP_LONGSEQ_MASK, tot_len );
+		if( (skb = dev_alloc_skb(tot_len)) == NULL ) {
+			printk(KERN_ERR "isdn_mppp: cannot allocate sk buff "
+					"of size %d\n", tot_len);
+			isdn_ppp_mp_discard(mp, from, to);
+			return;
+		}
 
- drop:
-	kfree_skb(skb);
-	mlp->stats.tx_dropped++;
-	return 0;
+		while( from != to ) {
+			unsigned int len = from->len - MP_HEADER_LEN;
 
- stop:
-	netif_stop_queue(ndev);
-	return 1;
+			memcpy(skb_put(skb,len), from->data+MP_HEADER_LEN, len);
+			frag = from->next;
+			isdn_ppp_mp_free_skb(mp, from);
+			from = frag; 
+		}
+	}
+   	proto = isdn_ppp_strip_proto(skb);
+	isdn_ppp_push_higher(net_dev, lp, skb, proto);
 }
 
-void
-ippp_xmit(isdn_net_dev *idev, struct sk_buff *skb)
+static void isdn_ppp_mp_free_skb(ippp_bundle * mp, struct sk_buff * skb)
+{
+	dev_kfree_skb(skb);
+	mp->frames--;
+}
+
+static void isdn_ppp_mp_print_recv_pkt( int slot, struct sk_buff * skb )
 {
-	struct ind_ppp *ind_ppp = idev->ind_priv;
-	struct ipppd *ipppd = ind_ppp->ipppd;
+	printk(KERN_DEBUG "mp_recv: %d/%d -> %02x %02x %02x %02x %02x %02x\n", 
+		slot, (int) skb->len, 
+		(int) skb->data[0], (int) skb->data[1], (int) skb->data[2],
+		(int) skb->data[3], (int) skb->data[4], (int) skb->data[5]);
+}
 
-	ippp_push_ac(ind_ppp, skb);
+static int
+isdn_ppp_bundle(struct ippp_struct *is, int unit)
+{
+	char ifn[IFNAMSIZ + 1];
+	isdn_net_dev *p;
+	isdn_net_local *lp, *nlp;
+	int rc;
+	unsigned long flags;
 
-	if (ipppd->debug & 0x40) {
-		isdn_ppp_frame_log("xmit3", skb->data, skb->len, 32, ipppd->unit, -1);
+	sprintf(ifn, "ippp%d", unit);
+	p = isdn_net_findif(ifn);
+	if (!p) {
+		printk(KERN_ERR "ippp_bundle: cannot find %s\n", ifn);
+		return -EINVAL;
 	}
-	
-	isdn_net_writebuf_skb(idev, skb);
-}
 
+    	spin_lock_irqsave(&p->pb->lock, flags);
+
+	nlp = is->lp;
+	lp = p->queue;
+	if( nlp->ppp_slot < 0 || nlp->ppp_slot >= ISDN_MAX_CHANNELS ||
+		lp->ppp_slot < 0 || lp->ppp_slot >= ISDN_MAX_CHANNELS ) {
+		printk(KERN_ERR "ippp_bundle: binding to invalid slot %d\n",
+			nlp->ppp_slot < 0 || nlp->ppp_slot >= ISDN_MAX_CHANNELS ? 
+			nlp->ppp_slot : lp->ppp_slot );
+		rc = -EINVAL;
+		goto out;
+ 	}
+
+	isdn_net_add_to_bundle(p, nlp);
+
+	ippp_table[nlp->ppp_slot]->unit = ippp_table[lp->ppp_slot]->unit;
+
+	/* maybe also SC_CCP stuff */
+	ippp_table[nlp->ppp_slot]->pppcfg |= ippp_table[lp->ppp_slot]->pppcfg &
+		(SC_ENABLE_IP | SC_NO_TCP_CCID | SC_REJ_COMP_TCP);
+	ippp_table[nlp->ppp_slot]->mpppcfg |= ippp_table[lp->ppp_slot]->mpppcfg &
+		(SC_MP_PROT | SC_REJ_MP_PROT | SC_OUT_SHORT_SEQ | SC_IN_SHORT_SEQ);
+	rc = isdn_ppp_mp_init(nlp, p->pb);
+out:
+	spin_unlock_irqrestore(&p->pb->lock, flags);
+	return rc;
+}
+  
+#endif /* CONFIG_ISDN_MPP */
+  
 /*
  * network device ioctl handlers
  */
 
 static int
-isdn_ppp_dev_ioctl_stats(struct ifreq *ifr, struct net_device *dev)
+isdn_ppp_dev_ioctl_stats(int slot, struct ifreq *ifr, struct net_device *dev)
 {
-	struct ppp_stats *res, t;
+	struct ppp_stats *res,
+	 t;
 	isdn_net_local *lp = (isdn_net_local *) dev->priv;
-	struct inl_ppp *inl_ppp = lp->inl_priv;
-	struct slcompress *slcomp;
 	int err;
 
 	res = (struct ppp_stats *) ifr->ifr_ifru.ifru_data;
@@ -1095,8 +1976,8 @@ isdn_ppp_dev_ioctl_stats(struct ifreq *i
 		t.p.ppp_obytes = lp->stats.tx_bytes;
 		t.p.ppp_oerrors = lp->stats.tx_errors;
 #ifdef CONFIG_ISDN_PPP_VJ
-		slcomp = inl_ppp->slcomp;
-		if (slcomp) {
+		if (slot >= 0 && ippp_table[slot]->slcomp) {
+			struct slcompress *slcomp = ippp_table[slot]->slcomp;
 			t.vj.vjs_packets = slcomp->sls_o_compressed + slcomp->sls_o_uncompressed;
 			t.vj.vjs_compressed = slcomp->sls_o_compressed;
 			t.vj.vjs_searches = slcomp->sls_o_searches;
@@ -1125,18 +2006,20 @@ isdn_ppp_dev_ioctl(struct net_device *de
 		return -EINVAL;
 
 	switch (cmd) {
-	case SIOCGPPPVER:
-		r = (char *) ifr->ifr_ifru.ifru_data;
-		len = strlen(PPP_VERSION) + 1;
-		if (copy_to_user(r, PPP_VERSION, len))
-			error = -EFAULT;
-		break;
-	case SIOCGPPPSTATS:
-		error = isdn_ppp_dev_ioctl_stats(ifr, dev);
-		break;
-	default:
-		error = -EINVAL;
-		break;
+#define PPP_VERSION "2.3.7"
+		case SIOCGPPPVER:
+			r = (char *) ifr->ifr_ifru.ifru_data;
+			len = strlen(PPP_VERSION) + 1;
+			if (copy_to_user(r, PPP_VERSION, len))
+				error = -EFAULT;
+			break;
+
+		case SIOCGPPPSTATS:
+			error = isdn_ppp_dev_ioctl_stats(lp->ppp_slot, ifr, dev);
+			break;
+		default:
+			error = -EINVAL;
+			break;
 	}
 	return error;
 }
@@ -1167,6 +2050,76 @@ isdn_ppp_if_get_unit(char *name)
 	return unit;
 }
 
+
+int
+isdn_ppp_dial_slave(char *name)
+{
+#ifdef CONFIG_ISDN_MPP
+	isdn_net_dev *ndev;
+	isdn_net_local *lp;
+	struct net_device *sdev;
+
+	if (!(ndev = isdn_net_findif(name)))
+		return 1;
+	lp = ndev->local;
+	if (!(lp->flags & ISDN_NET_CONNECTED))
+		return 5;
+
+	sdev = lp->slave;
+	while (sdev) {
+		isdn_net_local *mlp = (isdn_net_local *) sdev->priv;
+		if (!(mlp->flags & ISDN_NET_CONNECTED))
+			break;
+		sdev = mlp->slave;
+	}
+	if (!sdev)
+		return 2;
+
+	isdn_net_dial_req((isdn_net_local *) sdev->priv);
+	return 0;
+#else
+	return -1;
+#endif
+}
+
+int
+isdn_ppp_hangup_slave(char *name)
+{
+#ifdef CONFIG_ISDN_MPP
+	isdn_net_dev *ndev;
+	isdn_net_local *lp;
+	struct net_device *sdev;
+
+	if (!(ndev = isdn_net_findif(name)))
+		return 1;
+	lp = ndev->local;
+	if (!(lp->flags & ISDN_NET_CONNECTED))
+		return 5;
+
+	sdev = lp->slave;
+	while (sdev) {
+		isdn_net_local *mlp = (isdn_net_local *) sdev->priv;
+
+		if (mlp->slave) { /* find last connected link in chain */
+			isdn_net_local *nlp = (isdn_net_local *) mlp->slave->priv;
+
+			if (!(nlp->flags & ISDN_NET_CONNECTED))
+				break;
+		} else if (mlp->flags & ISDN_NET_CONNECTED)
+			break;
+		
+		sdev = mlp->slave;
+	}
+	if (!sdev)
+		return 2;
+
+	isdn_net_hangup(sdev);
+	return 0;
+#else
+	return -1;
+#endif
+}
+
 /*
  * PPP compression stuff
  */
@@ -1175,172 +2128,860 @@ isdn_ppp_if_get_unit(char *name)
 /* Push an empty CCP Data Frame up to the daemon to wake it up and let it
    generate a CCP Reset-Request or tear down CCP altogether */
 
-static void isdn_ppp_dev_kick_up(void *priv)
+static void isdn_ppp_ccp_kickup(struct ippp_struct *is)
 {
-	isdn_net_dev *idev = priv;
-	struct ind_ppp *ind_ppp = idev->ind_priv;
-
-	ipppd_queue_read(ind_ppp->ipppd, PPP_COMPFRAG, NULL, 0);
+	isdn_ppp_fill_rq(NULL, 0, PPP_COMP, is->lp->ppp_slot);
 }
 
-static void isdn_ppp_lp_kick_up(void *priv)
+/* In-kernel handling of CCP Reset-Request and Reset-Ack is necessary,
+   but absolutely nontrivial. The most abstruse problem we are facing is
+   that the generation, reception and all the handling of timeouts and
+   resends including proper request id management should be entirely left
+   to the (de)compressor, but indeed is not covered by the current API to
+   the (de)compressor. The API is a prototype version from PPP where only
+   some (de)compressors have yet been implemented and all of them are
+   rather simple in their reset handling. Especially, their is only one
+   outstanding ResetAck at a time with all of them and ResetReq/-Acks do
+   not have parameters. For this very special case it was sufficient to
+   just return an error code from the decompressor and have a single
+   reset() entry to communicate all the necessary information between
+   the framework and the (de)compressor. Bad enough, LZS is different
+   (and any other compressor may be different, too). It has multiple
+   histories (eventually) and needs to Reset each of them independently
+   and thus uses multiple outstanding Acks and history numbers as an
+   additional parameter to Reqs/Acks.
+   All that makes it harder to port the reset state engine into the
+   kernel because it is not just the same simple one as in (i)pppd but
+   it must be able to pass additional parameters and have multiple out-
+   standing Acks. We are trying to achieve the impossible by handling
+   reset transactions independent by their id. The id MUST change when
+   the data portion changes, thus any (de)compressor who uses more than
+   one resettable state must provide and recognize individual ids for
+   each individual reset transaction. The framework itself does _only_
+   differentiate them by id, because it has no other semantics like the
+   (de)compressor might.
+   This looks like a major redesign of the interface would be nice,
+   but I don't have an idea how to do it better. */
+
+/* Send a CCP Reset-Request or Reset-Ack directly from the kernel. This is
+   getting that lengthy because there is no simple "send-this-frame-out"
+   function above but every wrapper does a bit different. Hope I guess
+   correct in this hack... */
+
+static void isdn_ppp_ccp_xmit_reset(struct ippp_struct *is, int proto,
+				    unsigned char code, unsigned char id,
+				    unsigned char *data, int len)
 {
-	isdn_net_local *lp = priv;
-	isdn_net_dev *idev;
-	struct ind_ppp *ind_ppp;
-
-	if (list_empty(&lp->online)) {
-		isdn_BUG();
+	struct sk_buff *skb;
+	unsigned char *p;
+	int hl;
+	int cnt = 0;
+	isdn_net_local *lp = is->lp;
+
+	/* Alloc large enough skb */
+	hl = dev->drv[lp->isdn_device]->interface->hl_hdrlen;
+	skb = alloc_skb(len + hl + 16,GFP_ATOMIC);
+	if(!skb) {
+		printk(KERN_WARNING
+		       "ippp: CCP cannot send reset - out of memory\n");
 		return;
 	}
-	idev = list_entry(lp->online.next, isdn_net_dev, online);
-	ind_ppp = idev->ind_priv;
-	ipppd_queue_read(ind_ppp->ipppd, PPP_COMP, NULL, 0);
-}
+	skb_reserve(skb, hl);
 
-/* Send a CCP Reset-Request or Reset-Ack directly from the kernel. */
+	/* We may need to stuff an address and control field first */
+	if(!(is->pppcfg & SC_COMP_AC)) {
+		p = skb_put(skb, 2);
+		*p++ = 0xff;
+		*p++ = 0x03;
+	}
+
+	/* Stuff proto, code, id and length */
+	p = skb_put(skb, 6);
+	*p++ = (proto >> 8);
+	*p++ = (proto & 0xff);
+	*p++ = code;
+	*p++ = id;
+	cnt = 4 + len;
+	*p++ = (cnt >> 8);
+	*p++ = (cnt & 0xff);
+
+	/* Now stuff remaining bytes */
+	if(len) {
+		p = skb_put(skb, len);
+		memcpy(p, data, len);
+	}
+
+	/* skb is now ready for xmit */
+	printk(KERN_DEBUG "Sending CCP Frame:\n");
+	isdn_ppp_frame_log("ccp-xmit", skb->data, skb->len, 32, is->unit,lp->ppp_slot);
+
+	isdn_net_write_super(lp, skb);
+}
+
+/* Allocate the reset state vector */
+static struct ippp_ccp_reset *isdn_ppp_ccp_reset_alloc(struct ippp_struct *is)
+{
+	struct ippp_ccp_reset *r;
+	r = kmalloc(sizeof(struct ippp_ccp_reset), GFP_KERNEL);
+	if(!r) {
+		printk(KERN_ERR "ippp_ccp: failed to allocate reset data"
+		       " structure - no mem\n");
+		return NULL;
+	}
+	memset(r, 0, sizeof(struct ippp_ccp_reset));
+	printk(KERN_DEBUG "ippp_ccp: allocated reset data structure %p\n", r);
+	is->reset = r;
+	return r;
+}
 
-static struct sk_buff *
-__isdn_ppp_alloc_skb(isdn_net_dev *idev, int len, unsigned int gfp_mask)
+/* Destroy the reset state vector. Kill all pending timers first. */
+static void isdn_ppp_ccp_reset_free(struct ippp_struct *is)
 {
-	int hl = IPPP_MAX_HEADER + isdn_slot_hdrlen(idev->isdn_slot); 
-	struct sk_buff *skb;
+	unsigned int id;
 
-	skb = alloc_skb(hl + len, gfp_mask);
-	if (!skb)
-		return NULL;
+	printk(KERN_DEBUG "ippp_ccp: freeing reset data structure %p\n",
+	       is->reset);
+	for(id = 0; id < 256; id++) {
+		if(is->reset->rs[id]) {
+			isdn_ppp_ccp_reset_free_state(is, (unsigned char)id);
+		}
+	}
+	kfree(is->reset);
+	is->reset = NULL;
+}
 
-	skb_reserve(skb, hl);
-	return skb;
+/* Free a given state and clear everything up for later reallocation */
+static void isdn_ppp_ccp_reset_free_state(struct ippp_struct *is,
+					  unsigned char id)
+{
+	struct ippp_ccp_reset_state *rs;
+
+	if(is->reset->rs[id]) {
+		printk(KERN_DEBUG "ippp_ccp: freeing state for id %d\n", id);
+		rs = is->reset->rs[id];
+		/* Make sure the kernel will not call back later */
+		if(rs->ta)
+			del_timer(&rs->timer);
+		is->reset->rs[id] = NULL;
+		kfree(rs);
+	} else {
+		printk(KERN_WARNING "ippp_ccp: id %d is not allocated\n", id);
+	}
 }
 
-struct sk_buff *
-isdn_ppp_dev_alloc_skb(void *priv, int len, int gfp_mask)
+/* The timer callback function which is called when a ResetReq has timed out,
+   aka has never been answered by a ResetAck */
+static void isdn_ppp_ccp_timer_callback(unsigned long closure)
 {
-	isdn_net_dev *idev = priv;
+	struct ippp_ccp_reset_state *rs =
+		(struct ippp_ccp_reset_state *)closure;
 
-	return __isdn_ppp_alloc_skb(idev, len, gfp_mask);
+	if(!rs) {
+		printk(KERN_ERR "ippp_ccp: timer cb with zero closure.\n");
+		return;
+	}
+	if(rs->ta && rs->state == CCPResetSentReq) {
+		/* We are correct here */
+		if(!rs->expra) {
+			/* Hmm, there is no Ack really expected. We can clean
+			   up the state now, it will be reallocated if the
+			   decompressor insists on another reset */
+			rs->ta = 0;
+			isdn_ppp_ccp_reset_free_state(rs->is, rs->id);
+			return;
+		}
+		printk(KERN_DEBUG "ippp_ccp: CCP Reset timed out for id %d\n",
+		       rs->id);
+		/* Push it again */
+		isdn_ppp_ccp_xmit_reset(rs->is, PPP_CCP, CCP_RESETREQ, rs->id,
+					rs->data, rs->dlen);
+		/* Restart timer */
+		rs->timer.expires = jiffies + HZ*5;
+		add_timer(&rs->timer);
+	} else {
+		printk(KERN_WARNING "ippp_ccp: timer cb in wrong state %d\n",
+		       rs->state);
+	}
 }
 
-static struct sk_buff *
-isdn_ppp_lp_alloc_skb(void *priv, int len, int gfp_mask)
+/* Allocate a new reset transaction state */
+static struct ippp_ccp_reset_state *isdn_ppp_ccp_reset_alloc_state(struct ippp_struct *is,
+						      unsigned char id)
 {
-	isdn_net_local *lp = priv;
-	isdn_net_dev *idev;
-
-	if (list_empty(&lp->online)) {
-		isdn_BUG();
+	struct ippp_ccp_reset_state *rs;
+	if(is->reset->rs[id]) {
+		printk(KERN_WARNING "ippp_ccp: old state exists for id %d\n",
+		       id);
 		return NULL;
+	} else {
+		rs = kmalloc(sizeof(struct ippp_ccp_reset_state), GFP_KERNEL);
+		if(!rs)
+			return NULL;
+		memset(rs, 0, sizeof(struct ippp_ccp_reset_state));
+		rs->state = CCPResetIdle;
+		rs->is = is;
+		rs->id = id;
+		rs->timer.data = (unsigned long)rs;
+		rs->timer.function = isdn_ppp_ccp_timer_callback;
+		is->reset->rs[id] = rs;
+	}
+	return rs;
+}
+
+
+/* A decompressor wants a reset with a set of parameters - do what is
+   necessary to fulfill it */
+static void isdn_ppp_ccp_reset_trans(struct ippp_struct *is,
+				     struct isdn_ppp_resetparams *rp)
+{
+	struct ippp_ccp_reset_state *rs;
+
+	if(rp->valid) {
+		/* The decompressor defines parameters by itself */
+		if(rp->rsend) {
+			/* And he wants us to send a request */
+			if(!(rp->idval)) {
+				printk(KERN_ERR "ippp_ccp: decompressor must"
+				       " specify reset id\n");
+				return;
+			}
+			if(is->reset->rs[rp->id]) {
+				/* There is already a transaction in existence
+				   for this id. May be still waiting for a
+				   Ack or may be wrong. */
+				rs = is->reset->rs[rp->id];
+				if(rs->state == CCPResetSentReq && rs->ta) {
+					printk(KERN_DEBUG "ippp_ccp: reset"
+					       " trans still in progress"
+					       " for id %d\n", rp->id);
+				} else {
+					printk(KERN_WARNING "ippp_ccp: reset"
+					       " trans in wrong state %d for"
+					       " id %d\n", rs->state, rp->id);
+				}
+			} else {
+				/* Ok, this is a new transaction */
+				printk(KERN_DEBUG "ippp_ccp: new trans for id"
+				       " %d to be started\n", rp->id);
+				rs = isdn_ppp_ccp_reset_alloc_state(is, rp->id);
+				if(!rs) {
+					printk(KERN_ERR "ippp_ccp: out of mem"
+					       " allocing ccp trans\n");
+					return;
+				}
+				rs->state = CCPResetSentReq;
+				rs->expra = rp->expra;
+				if(rp->dtval) {
+					rs->dlen = rp->dlen;
+					memcpy(rs->data, rp->data, rp->dlen);
+				}
+				/* HACK TODO - add link comp here */
+				isdn_ppp_ccp_xmit_reset(is, PPP_CCP,
+							CCP_RESETREQ, rs->id,
+							rs->data, rs->dlen);
+				/* Start the timer */
+				rs->timer.expires = jiffies + 5*HZ;
+				add_timer(&rs->timer);
+				rs->ta = 1;
+			}
+		} else {
+			printk(KERN_DEBUG "ippp_ccp: no reset sent\n");
+		}
+	} else {
+		/* The reset params are invalid. The decompressor does not
+		   care about them, so we just send the minimal requests
+		   and increase ids only when an Ack is received for a
+		   given id */
+		if(is->reset->rs[is->reset->lastid]) {
+			/* There is already a transaction in existence
+			   for this id. May be still waiting for a
+			   Ack or may be wrong. */
+			rs = is->reset->rs[is->reset->lastid];
+			if(rs->state == CCPResetSentReq && rs->ta) {
+				printk(KERN_DEBUG "ippp_ccp: reset"
+				       " trans still in progress"
+				       " for id %d\n", rp->id);
+			} else {
+				printk(KERN_WARNING "ippp_ccp: reset"
+				       " trans in wrong state %d for"
+				       " id %d\n", rs->state, rp->id);
+			}
+		} else {
+			printk(KERN_DEBUG "ippp_ccp: new trans for id"
+			       " %d to be started\n", is->reset->lastid);
+			rs = isdn_ppp_ccp_reset_alloc_state(is,
+							    is->reset->lastid);
+			if(!rs) {
+				printk(KERN_ERR "ippp_ccp: out of mem"
+				       " allocing ccp trans\n");
+				return;
+			}
+			rs->state = CCPResetSentReq;
+			/* We always expect an Ack if the decompressor doesn't
+			   know	better */
+			rs->expra = 1;
+			rs->dlen = 0;
+			/* HACK TODO - add link comp here */
+			isdn_ppp_ccp_xmit_reset(is, PPP_CCP, CCP_RESETREQ,
+						rs->id, NULL, 0);
+			/* Start the timer */
+			rs->timer.expires = jiffies + 5*HZ;
+			add_timer(&rs->timer);
+			rs->ta = 1;
+		}
 	}
-	idev = list_entry(lp->online.next, isdn_net_dev, online);
-	return __isdn_ppp_alloc_skb(idev, len, gfp_mask);
 }
 
-static void
-isdn_ppp_dev_xmit(void *priv, struct sk_buff *skb, u16 proto)
-{
-	isdn_net_dev *idev = priv;
-	struct ind_ppp *ind_ppp = idev->ind_priv;
+/* An Ack was received for this id. This means we stop the timer and clean
+   up the state prior to calling the decompressors reset routine. */
+static void isdn_ppp_ccp_reset_ack_rcvd(struct ippp_struct *is,
+					unsigned char id)
+{
+	struct ippp_ccp_reset_state *rs = is->reset->rs[id];
+
+	if(rs) {
+		if(rs->ta && rs->state == CCPResetSentReq) {
+			/* Great, we are correct */
+			if(!rs->expra)
+				printk(KERN_DEBUG "ippp_ccp: ResetAck received"
+				       " for id %d but not expected\n", id);
+		} else {
+			printk(KERN_INFO "ippp_ccp: ResetAck received out of"
+			       "sync for id %d\n", id);
+		}
+		if(rs->ta) {
+			rs->ta = 0;
+			del_timer(&rs->timer);
+		}
+		isdn_ppp_ccp_reset_free_state(is, id);
+	} else {
+		printk(KERN_INFO "ippp_ccp: ResetAck received for unknown id"
+		       " %d\n", id);
+	}
+	/* Make sure the simple reset stuff uses a new id next time */
+	is->reset->lastid++;
+}
+
+/* 
+ * decompress packet
+ *
+ * if master = 0, we're trying to uncompress an per-link compressed packet,
+ * as opposed to an compressed reconstructed-from-MPPP packet.
+ * proto is updated to protocol field of uncompressed packet.
+ *
+ * retval: decompressed packet,
+ *         same packet if uncompressed,
+ *	   NULL if decompression error
+ */
 
-	ippp_push_proto(ind_ppp, skb, proto);
-	ippp_push_ac(ind_ppp, skb);
-	isdn_net_write_super(idev, skb);
+static struct sk_buff *isdn_ppp_decompress(struct sk_buff *skb,struct ippp_struct *is,struct ippp_struct *master,
+	int *proto)
+{
+	void *stat = NULL;
+	struct isdn_ppp_compressor *ipc = NULL;
+	struct sk_buff *skb_out;
+	int len;
+	struct ippp_struct *ri;
+	struct isdn_ppp_resetparams rsparm;
+	unsigned char rsdata[IPPP_RESET_MAXDATABYTES];
+
+	if(!master) {
+		// per-link decompression 
+		stat = is->link_decomp_stat;
+		ipc = is->link_decompressor;
+		ri = is;
+	} else {
+		stat = master->decomp_stat;
+		ipc = master->decompressor;
+		ri = master;
+	}
+
+	if (!ipc) {
+		// no decompressor -> we can't decompress.
+		printk(KERN_DEBUG "ippp: no decompressor defined!\n");
+		return skb;
+	}
+	if (!stat) // if we have a compressor, stat has been set as well
+		BUG();
+
+	if((master && *proto == PPP_COMP) || (!master && *proto == PPP_COMPFRAG) ) {
+		// compressed packets are compressed by their protocol type
+
+		// Set up reset params for the decompressor
+  		memset(&rsparm, 0, sizeof(rsparm));
+  		rsparm.data = rsdata;
+  		rsparm.maxdlen = IPPP_RESET_MAXDATABYTES;
+  
+  		skb_out = dev_alloc_skb(is->mru + PPP_HDRLEN);
+		len = ipc->decompress(stat, skb, skb_out, &rsparm);
+		kfree_skb(skb);
+		if (len <= 0) {
+			switch(len) {
+			case DECOMP_ERROR:
+				printk(KERN_INFO "ippp: decomp wants reset %s params\n",
+				       rsparm.valid ? "with" : "without");
+				
+				isdn_ppp_ccp_reset_trans(ri, &rsparm);
+				break;
+			case DECOMP_FATALERROR:
+				ri->pppcfg |= SC_DC_FERROR;
+				/* Kick ipppd to recognize the error */
+				isdn_ppp_ccp_kickup(ri);
+				break;
+			}
+			kfree_skb(skb_out);
+			return NULL;
+		}
+		*proto = isdn_ppp_strip_proto(skb_out);
+		if (*proto < 0) {
+			kfree_skb(skb_out);
+			return NULL;
+		}
+		return skb_out;
+	} else { 
+		// uncompressed packets are fed through the decompressor to
+		// update the decompressor state
+		ipc->incomp(stat, skb, *proto);
+		return skb;
+	}
 }
 
-static void
-isdn_ppp_lp_xmit(void *priv, struct sk_buff *skb, u16 proto)
+/*
+ * compress a frame 
+ *   type=0: normal/bundle compression
+ *       =1: link compression
+ * returns original skb if we haven't compressed the frame
+ * and a new skb pointer if we've done it
+ */
+static struct sk_buff *isdn_ppp_compress(struct sk_buff *skb_in,int *proto,
+	struct ippp_struct *is,struct ippp_struct *master,int type)
 {
-	isdn_net_local *lp = priv;
-	isdn_net_dev *idev;
-	struct ind_ppp *ind_ppp;
+    int ret;
+    int new_proto;
+    struct isdn_ppp_compressor *compressor;
+    void *stat;
+    struct sk_buff *skb_out;
+
+	/* we do not compress control protocols */
+    if(*proto < 0 || *proto > 0x3fff) {
+	    return skb_in;
+    }
+
+	if(type) { /* type=1 => Link compression */
+		return skb_in;
+	}
+	else {
+		if(!master) {
+			compressor = is->compressor;
+			stat = is->comp_stat;
+		}
+		else {
+			compressor = master->compressor;
+			stat = master->comp_stat;
+		}
+		new_proto = PPP_COMP;
+	}
 
-	if (list_empty(&lp->online)) {
-		isdn_BUG();
-		return;
+	if(!compressor) {
+		printk(KERN_ERR "isdn_ppp: No compressor set!\n");
+		return skb_in;
+	}
+	if(!stat) {
+		printk(KERN_ERR "isdn_ppp: Compressor not initialized?\n");
+		return skb_in;
 	}
-	idev = list_entry(lp->online.next, isdn_net_dev, online);
-	ind_ppp = idev->ind_priv;
-	ippp_push_proto(ind_ppp, skb, proto);
-	ippp_push_ac(ind_ppp, skb);
-	isdn_net_write_super(idev, skb);
+
+	/* Allow for at least 150 % expansion (for now) */
+	skb_out = alloc_skb(skb_in->len + skb_in->len/2 + 32 +
+		skb_headroom(skb_in), GFP_ATOMIC);
+	if(!skb_out)
+		return skb_in;
+	skb_reserve(skb_out, skb_headroom(skb_in));
+
+	ret = (compressor->compress)(stat,skb_in,skb_out,*proto);
+	if(!ret) {
+		dev_kfree_skb(skb_out);
+		return skb_in;
+	}
+	
+	dev_kfree_skb(skb_in);
+	*proto = new_proto;
+	return skb_out;
 }
 
-static int
-isdn_ppp_set_compressor(isdn_net_dev *idev, struct isdn_ppp_comp_data *data)
+/*
+ * we received a CCP frame .. 
+ * not a clean solution, but we MUST handle a few cases in the kernel
+ */
+static void isdn_ppp_receive_ccp(isdn_net_dev *net_dev, isdn_net_local *lp,
+	 struct sk_buff *skb,int proto)
 {
-	struct ippp_ccp *ccp;
-	struct inl_ppp *inl_ppp = idev->mlp->inl_priv;
-	struct ind_ppp *ind_ppp = idev->ind_priv;
+	struct ippp_struct *is;
+	struct ippp_struct *mis;
+	int len;
+	struct isdn_ppp_resetparams rsparm;
+	unsigned char rsdata[IPPP_RESET_MAXDATABYTES];	
 
-	if (data->flags & IPPP_COMP_FLAG_LINK)
-		ccp = ind_ppp->ccp;
-	else
-		ccp = inl_ppp->ccp;
+	printk(KERN_DEBUG "Received CCP frame from peer slot(%d)\n",
+		lp->ppp_slot);
+	if (lp->ppp_slot < 0 || lp->ppp_slot > ISDN_MAX_CHANNELS) {
+		printk(KERN_ERR "%s: lp->ppp_slot(%d) out of range\n",
+			__FUNCTION__, lp->ppp_slot);
+		return;
+	}
+	is = ippp_table[lp->ppp_slot];
+	isdn_ppp_frame_log("ccp-rcv", skb->data, skb->len, 32, is->unit,lp->ppp_slot);
+
+	if(lp->master) {
+		int slot = ((isdn_net_local *) (lp->master->priv))->ppp_slot;
+		if (slot < 0 || slot > ISDN_MAX_CHANNELS) {
+			printk(KERN_ERR "%s: slot(%d) out of range\n",
+				__FUNCTION__, slot);
+			return;
+		}	
+		mis = ippp_table[slot];
+	} else
+		mis = is;
+
+	switch(skb->data[0]) {
+	case CCP_CONFREQ:
+		if(is->debug & 0x10)
+			printk(KERN_DEBUG "Disable compression here!\n");
+		if(proto == PPP_CCP)
+			mis->compflags &= ~SC_COMP_ON;		
+		else
+			is->compflags &= ~SC_LINK_COMP_ON;		
+		break;
+	case CCP_TERMREQ:
+	case CCP_TERMACK:
+		if(is->debug & 0x10)
+			printk(KERN_DEBUG "Disable (de)compression here!\n");
+		if(proto == PPP_CCP)
+			mis->compflags &= ~(SC_DECOMP_ON|SC_COMP_ON);		
+		else
+			is->compflags &= ~(SC_LINK_DECOMP_ON|SC_LINK_COMP_ON);		
+		break;
+	case CCP_CONFACK:
+		/* if we RECEIVE an ackowledge we enable the decompressor */
+		if(is->debug & 0x10)
+			printk(KERN_DEBUG "Enable decompression here!\n");
+		if(proto == PPP_CCP) {
+			if (!mis->decompressor)
+				break;
+			mis->compflags |= SC_DECOMP_ON;
+		} else {
+			if (!is->decompressor)
+				break;
+			is->compflags |= SC_LINK_DECOMP_ON;
+		}
+		break;
+
+	case CCP_RESETACK:
+		printk(KERN_DEBUG "Received ResetAck from peer\n");
+		len = (skb->data[2] << 8) | skb->data[3];
+		len -= 4;
+
+		if(proto == PPP_CCP) {
+			/* If a reset Ack was outstanding for this id, then
+			   clean up the state engine */
+			isdn_ppp_ccp_reset_ack_rcvd(mis, skb->data[1]);
+			if(mis->decompressor && mis->decomp_stat)
+				mis->decompressor->
+					reset(mis->decomp_stat,
+					      skb->data[0],
+					      skb->data[1],
+					      len ? &skb->data[4] : NULL,
+					      len, NULL);
+			/* TODO: This is not easy to decide here */
+			mis->compflags &= ~SC_DECOMP_DISCARD;
+		}
+		else {
+			isdn_ppp_ccp_reset_ack_rcvd(is, skb->data[1]);
+			if(is->link_decompressor && is->link_decomp_stat)
+				is->link_decompressor->
+					reset(is->link_decomp_stat,
+					      skb->data[0],
+					      skb->data[1],
+					      len ? &skb->data[4] : NULL,
+					      len, NULL);
+			/* TODO: neither here */
+			is->compflags &= ~SC_LINK_DECOMP_DISCARD;
+		}
+		break;
 
-	return ippp_ccp_set_compressor(ccp, ind_ppp->ipppd->unit, data);
+	case CCP_RESETREQ:
+		printk(KERN_DEBUG "Received ResetReq from peer\n");
+		/* Receiving a ResetReq means we must reset our compressor */
+		/* Set up reset params for the reset entry */
+		memset(&rsparm, 0, sizeof(rsparm));
+		rsparm.data = rsdata;
+		rsparm.maxdlen = IPPP_RESET_MAXDATABYTES; 
+		/* Isolate data length */
+		len = (skb->data[2] << 8) | skb->data[3];
+		len -= 4;
+		if(proto == PPP_CCP) {
+			if(mis->compressor && mis->comp_stat)
+				mis->compressor->
+					reset(mis->comp_stat,
+					      skb->data[0],
+					      skb->data[1],
+					      len ? &skb->data[4] : NULL,
+					      len, &rsparm);
+		}
+		else {
+			if(is->link_compressor && is->link_comp_stat)
+				is->link_compressor->
+					reset(is->link_comp_stat,
+					      skb->data[0],
+					      skb->data[1],
+					      len ? &skb->data[4] : NULL,
+					      len, &rsparm);
+		}
+		/* Ack the Req as specified by rsparm */
+		if(rsparm.valid) {
+			/* Compressor reset handler decided how to answer */
+			if(rsparm.rsend) {
+				/* We should send a Frame */
+				isdn_ppp_ccp_xmit_reset(is, proto, CCP_RESETACK,
+							rsparm.idval ? rsparm.id
+							: skb->data[1],
+							rsparm.dtval ?
+							rsparm.data : NULL,
+							rsparm.dtval ?
+							rsparm.dlen : 0);
+			} else {
+				printk(KERN_DEBUG "ResetAck suppressed\n");
+			}
+		} else {
+			/* We answer with a straight reflected Ack */
+			isdn_ppp_ccp_xmit_reset(is, proto, CCP_RESETACK,
+						skb->data[1],
+						len ? &skb->data[4] : NULL,
+						len);
+		}
+		break;
+	}
 }
 
-// ISDN_NET_ENCAP_SYNCPPP
-// ======================================================================
 
-static int
-isdn_ppp_open(isdn_net_local *lp)
+/*
+ * Daemon sends a CCP frame ...
+ */
+
+/* TODO: Clean this up with new Reset semantics */
+
+/* I believe the CCP handling as-is is done wrong. Compressed frames
+ * should only be sent/received after CCP reaches UP state, which means
+ * both sides have sent CONF_ACK. Currently, we handle both directions
+ * independently, which means we may accept compressed frames too early
+ * (supposedly not a problem), but may also mean we send compressed frames
+ * too early, which may turn out to be a problem.
+ * This part of state machine should actually be handled by (i)pppd, but
+ * that's too big of a change now. --kai
+ */
+
+/* Actually, we might turn this into an advantage: deal with the RFC in
+ * the old tradition of beeing generous on what we accept, but beeing
+ * strict on what we send. Thus we should just
+ * - accept compressed frames as soon as decompression is negotiated
+ * - send compressed frames only when decomp *and* comp are negotiated
+ * - drop rx compressed frames if we cannot decomp (instead of pushing them
+ *   up to ipppd)
+ * and I tried to modify this file according to that. --abp
+ */
+
+static void isdn_ppp_send_ccp(isdn_net_dev *net_dev, isdn_net_local *lp, struct sk_buff *skb)
 {
-	struct inl_ppp *inl_ppp;
+	struct ippp_struct *mis,*is;
+	int proto, slot = lp->ppp_slot;
+	unsigned char *data;
 
-	inl_ppp = kmalloc(sizeof(*inl_ppp), GFP_KERNEL);
-	if (!inl_ppp)
-		return -ENOMEM;
+	if(!skb || skb->len < 3)
+		return;
+	if (slot < 0 || slot > ISDN_MAX_CHANNELS) {
+		printk(KERN_ERR "%s: lp->ppp_slot(%d) out of range\n",
+			__FUNCTION__, slot);
+		return;
+	}	
+	is = ippp_table[slot];
+	/* Daemon may send with or without address and control field comp */
+	data = skb->data;
+	if(!(is->pppcfg & SC_COMP_AC) && data[0] == 0xff && data[1] == 0x03) {
+		data += 2;
+		if(skb->len < 5)
+			return;
+	}
+
+	proto = ((int)data[0]<<8)+data[1];
+	if(proto != PPP_CCP && proto != PPP_CCPFRAG)
+		return;
 
-	lp->inl_priv = inl_ppp;
+	printk(KERN_DEBUG "Received CCP frame from daemon:\n");
+	isdn_ppp_frame_log("ccp-xmit", skb->data, skb->len, 32, is->unit,lp->ppp_slot);
 
-	inl_ppp->slcomp = ippp_vj_alloc();
-	if (!inl_ppp->slcomp)
-		goto err;
-
-	inl_ppp->ccp = ippp_ccp_alloc();
-	if (!inl_ppp->ccp)
-		goto err_vj;
-
-	inl_ppp->ccp->proto       = PPP_COMP;
-	inl_ppp->ccp->priv        = lp;
-	inl_ppp->ccp->alloc_skb   = isdn_ppp_lp_alloc_skb;
-	inl_ppp->ccp->xmit        = isdn_ppp_lp_xmit;
-	inl_ppp->ccp->kick_up     = isdn_ppp_lp_kick_up;
+	if (lp->master) {
+		slot = ((isdn_net_local *) (lp->master->priv))->ppp_slot;
+		if (slot < 0 || slot > ISDN_MAX_CHANNELS) {
+			printk(KERN_ERR "%s: slot(%d) out of range\n",
+				__FUNCTION__, slot);
+			return;
+		}	
+		mis = ippp_table[slot];
+	} else
+		mis = is;
+	if (mis != is)
+		printk(KERN_DEBUG "isdn_ppp: Ouch! Master CCP sends on slave slot!\n");
 	
-	return 0;
-
- err_vj:
-	ippp_vj_free(inl_ppp->slcomp);
- err:
-	kfree(inl_ppp);
-	lp->inl_priv = NULL;
-	return -ENOMEM;
+        switch(data[2]) {
+	case CCP_CONFREQ:
+		if(is->debug & 0x10)
+			printk(KERN_DEBUG "Disable decompression here!\n");
+		if(proto == PPP_CCP)
+			is->compflags &= ~SC_DECOMP_ON;
+		else
+			is->compflags &= ~SC_LINK_DECOMP_ON;
+		break;
+	case CCP_TERMREQ:
+	case CCP_TERMACK:
+		if(is->debug & 0x10)
+			printk(KERN_DEBUG "Disable (de)compression here!\n");
+		if(proto == PPP_CCP)
+			is->compflags &= ~(SC_DECOMP_ON|SC_COMP_ON);
+		else
+			is->compflags &= ~(SC_LINK_DECOMP_ON|SC_LINK_COMP_ON);
+		break;
+	case CCP_CONFACK:
+		/* if we SEND an ackowledge we can/must enable the compressor */
+		if(is->debug & 0x10)
+			printk(KERN_DEBUG "Enable compression here!\n");
+		if(proto == PPP_CCP) {
+			if (!is->compressor)
+				break;
+			is->compflags |= SC_COMP_ON;
+		} else {
+			if (!is->compressor)
+				break;
+			is->compflags |= SC_LINK_COMP_ON;
+		}
+		break;
+	case CCP_RESETACK:
+		/* If we send a ACK we should reset our compressor */
+		if(is->debug & 0x10)
+			printk(KERN_DEBUG "Reset decompression state here!\n");
+		printk(KERN_DEBUG "ResetAck from daemon passed by\n");
+		if(proto == PPP_CCP) {
+			/* link to master? */
+			if(is->compressor && is->comp_stat)
+				is->compressor->reset(is->comp_stat, 0, 0,
+						      NULL, 0, NULL);
+			is->compflags &= ~SC_COMP_DISCARD;	
+		}
+		else {
+			if(is->link_compressor && is->link_comp_stat)
+				is->link_compressor->reset(is->link_comp_stat,
+							   0, 0, NULL, 0, NULL);
+			is->compflags &= ~SC_LINK_COMP_DISCARD;	
+		}
+		break;
+	case CCP_RESETREQ:
+		/* Just let it pass by */
+		printk(KERN_DEBUG "ResetReq from daemon passed by\n");
+		break;
+	}
 }
 
-static void
-isdn_ppp_close(isdn_net_local *lp)
+int isdn_ppp_register_compressor(struct isdn_ppp_compressor *ipc)
 {
-	struct inl_ppp *inl_ppp = lp->inl_priv;
-	
-	ippp_ccp_free(inl_ppp->ccp);
-	ippp_vj_free(inl_ppp->slcomp);
+	ipc->next = ipc_head;
+	ipc->prev = NULL;
+	if(ipc_head) {
+		ipc_head->prev = ipc;
+	}
+	ipc_head = ipc;
+	return 0;
+}
 
-	kfree(inl_ppp);
-	lp->inl_priv = NULL;
+int isdn_ppp_unregister_compressor(struct isdn_ppp_compressor *ipc)
+{
+	if(ipc->prev)
+		ipc->prev->next = ipc->next;
+	else
+		ipc_head = ipc->next;
+	if(ipc->next)
+		ipc->next->prev = ipc->prev;
+	ipc->prev = ipc->next = NULL;
+	return 0;
 }
 
-struct isdn_netif_ops isdn_ppp_ops = {
-	.hard_start_xmit     = isdn_ppp_start_xmit,
-	.do_ioctl            = isdn_ppp_dev_ioctl,
-	.flags               = IFF_NOARP | IFF_POINTOPOINT,
-	.type                = ARPHRD_PPP,
-	.receive             = isdn_ppp_receive,
-	.connected           = isdn_ppp_connected,
-	.disconnected        = isdn_ppp_disconnected,
-	.bind                = isdn_ppp_bind,
-	.unbind              = isdn_ppp_unbind,
-	.open                = isdn_ppp_open,
-	.close               = isdn_ppp_close,
-};
+static int isdn_ppp_set_compressor(struct ippp_struct *is, struct isdn_ppp_comp_data *data)
+{
+	struct isdn_ppp_compressor *ipc = ipc_head;
+	int ret;
+	void *stat;
+	int num = data->num;
+
+	if(is->debug & 0x10)
+		printk(KERN_DEBUG "[%d] Set %s type %d\n",is->unit,
+			(data->flags&IPPP_COMP_FLAG_XMIT)?"compressor":"decompressor",num);
+
+	/* If is has no valid reset state vector, we cannot allocate a
+	   decompressor. The decompressor would cause reset transactions
+	   sooner or later, and they need that vector. */
+
+	if(!(data->flags & IPPP_COMP_FLAG_XMIT) && !is->reset) {
+		printk(KERN_ERR "ippp_ccp: no reset data structure - can't"
+		       " allow decompression.\n");
+		return -ENOMEM;
+	}
+
+	while(ipc) {
+		if(ipc->num == num) {
+			stat = ipc->alloc(data);
+			if(stat) {
+				ret = ipc->init(stat,data,is->unit,0);
+				if(!ret) {
+					printk(KERN_ERR "Can't init (de)compression!\n");
+					ipc->free(stat);
+					stat = NULL;
+					break;
+				}
+			}
+			else {
+				printk(KERN_ERR "Can't alloc (de)compression!\n");
+				break;
+			}
 
+                        if(data->flags & IPPP_COMP_FLAG_XMIT) {
+				if(data->flags & IPPP_COMP_FLAG_LINK) {
+					if(is->link_comp_stat)
+						is->link_compressor->free(is->link_comp_stat);
+					is->link_comp_stat = stat;
+                                	is->link_compressor = ipc;
+				}
+				else {
+					if(is->comp_stat)
+						is->compressor->free(is->comp_stat);
+					is->comp_stat = stat;
+                                	is->compressor = ipc;
+				}
+			}
+                        else {
+				if(data->flags & IPPP_COMP_FLAG_LINK) {
+					if(is->link_decomp_stat)
+						is->link_decompressor->free(is->link_decomp_stat);
+					is->link_decomp_stat = stat;
+        	                        is->link_decompressor = ipc;
+				}
+				else {
+					if(is->decomp_stat)
+						is->decompressor->free(is->decomp_stat);
+					is->decomp_stat = stat;
+        	                        is->decompressor = ipc;
+				}
+			}
+			return 0;
+		}
+		ipc = ipc->next;
+	}
+	return -EINVAL;
+}
--- diff/drivers/isdn/i4l/isdn_ppp.h	2002-11-11 11:09:36.000000000 +0000
+++ source/drivers/isdn/i4l/isdn_ppp.h	2004-02-23 13:56:43.000000000 +0000
@@ -1,57 +1,43 @@
-/* Linux ISDN subsystem, functions for synchronous PPP (linklevel).
+/* $Id: isdn_ppp.h,v 1.1.2.2 2004/01/12 22:37:19 keil Exp $
+ *
+ * header for Linux ISDN subsystem, functions for synchronous PPP (linklevel).
  *
  * Copyright 1995,96 by Michael Hipp (Michael.Hipp@student.uni-tuebingen.de)
- *           1999-2002  by Kai Germaschewski <kai@germaschewski.name>
  *
  * This software may be used and distributed according to the terms
  * of the GNU General Public License, incorporated herein by reference.
+ *
  */
 
-#include "isdn_net_lib.h"
-
-extern struct file_operations isdn_ppp_fops;
-extern struct isdn_netif_ops isdn_ppp_ops;
+#include <linux/ppp_defs.h>     /* for PPP_PROTOCOL */
+#include <linux/isdn_ppp.h>	/* for isdn_ppp info */
 
-int isdn_ppp_init(void);
-void isdn_ppp_cleanup(void);
-int isdn_ppp_dial_slave(char *);
-int isdn_ppp_hangup_slave(char *);
-
-struct inl_ppp {
-	unsigned long debug;
-	struct slcompress *slcomp;
-	struct ippp_ccp *ccp;         /* CCP for this channel */
-	unsigned int mp_cfg;
-	struct sk_buff_head mp_frags; /* fragments list */
-	u32 mp_rxseq;                 /* last processed packet seq # */
-	u32 mp_txseq;                 /* current tx seq # */
-};
-
-struct ind_ppp {
-	struct ipppd *ipppd;          /* /dev/ipppX which controls us */
-	unsigned int pppcfg;
-	unsigned long debug;
-	struct ippp_ccp *ccp;         /* CCP for this channel (multilink) */
-	u32 mp_rxseq;                 /* last seq no seen on this channel */
-};
-
-void
-isdn_ppp_frame_log(char *info, char *data, int len, int maxlen, 
-		   int unit, int slot);
-
-int
-isdn_ppp_strip_proto(struct sk_buff *skb, u16 *proto);
-
-void
-ippp_push_proto(struct ind_ppp *ind_ppp, struct sk_buff *skb, u16 proto);
+extern int isdn_ppp_read(int, struct file *, char *, int);
+extern int isdn_ppp_write(int, struct file *, const char *, int);
+extern int isdn_ppp_open(int, struct file *);
+extern int isdn_ppp_init(void);
+extern void isdn_ppp_cleanup(void);
+extern int isdn_ppp_free(isdn_net_local *);
+extern int isdn_ppp_bind(isdn_net_local *);
+extern int isdn_ppp_autodial_filter(struct sk_buff *, isdn_net_local *);
+extern int isdn_ppp_xmit(struct sk_buff *, struct net_device *);
+extern void isdn_ppp_receive(isdn_net_dev *, isdn_net_local *, struct sk_buff *);
+extern int isdn_ppp_dev_ioctl(struct net_device *, struct ifreq *, int);
+extern unsigned int isdn_ppp_poll(struct file *, struct poll_table_struct *);
+extern int isdn_ppp_ioctl(int, struct file *, unsigned int, unsigned long);
+extern void isdn_ppp_release(int, struct file *);
+extern int isdn_ppp_dial_slave(char *);
+extern void isdn_ppp_wakeup_daemon(isdn_net_local *);
+
+extern int isdn_ppp_register_compressor(struct isdn_ppp_compressor *ipc);
+extern int isdn_ppp_unregister_compressor(struct isdn_ppp_compressor *ipc);
+
+#define IPPP_OPEN	0x01
+#define IPPP_CONNECT	0x02
+#define IPPP_CLOSEWAIT	0x04
+#define IPPP_NOBLOCK	0x08
+#define IPPP_ASSIGNED	0x10
 
-void
-ippp_xmit(isdn_net_dev *idev, struct sk_buff *skb);
-
-void
-ippp_receive(isdn_net_dev *idev, struct sk_buff *skb, u16 proto);
+#define IPPP_MAX_HEADER 10
 
-struct sk_buff *
-isdn_ppp_dev_alloc_skb(void *priv, int len, int gfp_mask);
 
-#define IPPP_MAX_HEADER 10
--- diff/drivers/isdn/i4l/isdn_tty.c	2003-09-30 15:46:14.000000000 +0100
+++ source/drivers/isdn/i4l/isdn_tty.c	2004-02-23 13:56:43.000000000 +0000
@@ -1,20 +1,17 @@
-/* Linux ISDN subsystem, tty functions and AT-command emulator
+/* $Id: isdn_tty.c,v 1.1.2.3 2004/02/10 01:07:13 keil Exp $
+ *
+ * Linux ISDN subsystem, tty functions and AT-command emulator (linklevel).
  *
  * Copyright 1994-1999  by Fritz Elfert (fritz@isdn4linux.de)
  * Copyright 1995,96    by Thinking Objects Software GmbH Wuerzburg
  *
  * This software may be used and distributed according to the terms
  * of the GNU General Public License, incorporated herein by reference.
+ *
  */
+#undef ISDN_TTY_STAT_DEBUG
 
-#define ISDN_TTY_STAT_DEBUG
-#define ISDN_DEBUG_MODEM_HUP
-#define ISDN_DEBUG_MODEM_VOICE
-#define ISDN_DEBUG_MODEM_OPEN
-#define ISDN_DEBUG_MODEM_IOCTL
-#define ISDN_DEBUG_MODEM_ICALL
-
-#include <linux/module.h>
+#include <linux/config.h>
 #include <linux/isdn.h>
 #include "isdn_common.h"
 #include "isdn_tty.h"
@@ -24,51 +21,33 @@
 #define VBUFX (VBUF/16)
 #endif
 
-#define RING_TIMEOUT     (5*HZ)  /* repeat RING every 5 secs */
 #define FIX_FILE_TRANSFER
 #define	DUMMY_HAYES_AT
 
 /* Prototypes */
 
-static void isdn_tty_modem_xmit(struct modem_info *info);
 static int isdn_tty_edit_at(const char *, int, modem_info *, int);
-static void isdn_tty_escape_timer(unsigned long data);
-static void isdn_tty_ring_timer(unsigned long data);
-static void isdn_tty_connect_timer(unsigned long data);
-static void isdn_tty_check_esc(struct modem_info *info, 
-			       const unsigned char *p, int count);
+static void isdn_tty_check_esc(const u_char *, u_char, int, int *, u_long *, int);
 static void isdn_tty_modem_reset_regs(modem_info *, int);
 static void isdn_tty_cmd_ATA(modem_info *);
 static void isdn_tty_flush_buffer(struct tty_struct *);
 static void isdn_tty_modem_result(int, modem_info *);
-static int isdn_tty_stat_callback(struct isdn_slot *slot, isdn_ctrl *c);
-static int isdn_tty_rcv_skb(struct isdn_slot *slot, struct sk_buff *skb);
 #ifdef CONFIG_ISDN_AUDIO
 static int isdn_tty_countDLE(unsigned char *, int);
 #endif
 
-static int
-isdn_tty_event_callback(struct isdn_slot *slot, int pr, void *arg)
-{
-	switch (pr) {
-	case EV_DATA_IND:
-		return isdn_tty_rcv_skb(slot, arg);
-	default:
-		return isdn_tty_stat_callback(slot, arg);
-	}
-}
-
 /* Leave this unchanged unless you know what you do! */
 #define MODEM_PARANOIA_CHECK
 #define MODEM_DO_RESTART
 
-struct isdn_modem isdn_mdm;
-
 static int bit2si[8] =
 {1, 5, 7, 7, 7, 7, 7, 7};
 static int si2bit[8] =
 {4, 1, 4, 4, 4, 4, 4, 4};
 
+char *isdn_tty_revision = "$Revision: 1.1.2.3 $";
+
+
 /* isdn_tty_try_read() is called from within isdn_tty_rcv_skb()
  * to stuff incoming data directly into a tty's flip-buffer. This
  * is done to speed up tty-receiving if the receive-queue is empty.
@@ -124,166 +103,78 @@ isdn_tty_try_read(modem_info * info, str
 	return 0;
 }
 
-/*
- * isdn_slot_readbchan() tries to get data from the read-queue.
- * It MUST be called with interrupts off.
- */
-static int
-isdn_tty_readbchan(struct modem_info *info, u_char * buf, u_char * fp, int len)
-{
-	int count;
-	u_int count_pull;
-	int count_put;
-	int dflag;
-	struct sk_buff *skb;
-	u_char *cp;
-
-	if (skb_queue_empty(&info->rpqueue))
-		return 0;
-
-	if (len > info->rcvcount)
-		len = info->rcvcount;
-	cp = buf;
-	count = 0;
-	while (len) {
-		if (!(skb = skb_peek(&info->rpqueue)))
-			break;
-#ifdef CONFIG_ISDN_AUDIO
-		if (ISDN_AUDIO_SKB_LOCK(skb))
-			break;
-		ISDN_AUDIO_SKB_LOCK(skb) = 1;
-		if (ISDN_AUDIO_SKB_DLECOUNT(skb) || info->DLEflag) {
-			char *p = skb->data;
-
-			dflag = 0;
-			count_pull = count_put = 0;
-			while ((count_pull < skb->len) && (len > 0)) {
-				len--;
-				if (info->DLEflag) {
-					*cp++ = DLE;
-					info->DLEflag = 0;
-				} else {
-					*cp++ = *p;
-					if (*p == DLE) {
-						info->DLEflag = 1;
-						(ISDN_AUDIO_SKB_DLECOUNT(skb))--;
-					}
-					p++;
-					count_pull++;
-				}
-				count_put++;
-			}
-			if (count_pull >= skb->len)
-				dflag = 1;
-		} else {
-#endif
-			/* No DLE's in buff, so simply copy it */
-			dflag = 1;
-			if ((int)(count_pull = skb->len) > len) {
-				count_pull = len;
-				dflag = 0;
-			}
-			count_put = count_pull;
-			memcpy(cp, skb->data, count_put);
-			cp += count_put;
-			len -= count_put;
-#ifdef CONFIG_ISDN_AUDIO
-		}
-#endif
-		count += count_put;
-		if (fp) {
-			memset(fp, 0, count_put);
-			fp += count_put;
-		}
-		if (dflag) {
-			/* We got all the data in this buff.
-			 * Now we can dequeue it.
-			 */
-			if (fp)
-				*(fp - 1) = 0xff;
-#ifdef CONFIG_ISDN_AUDIO
-			ISDN_AUDIO_SKB_LOCK(skb) = 0;
-#endif
-			skb = skb_dequeue(&info->rpqueue);
-			dev_kfree_skb(skb);
-		} else {
-			/* Not yet emptied this buff, so it
-			 * must stay in the queue, for further calls
-			 * but we pull off the data we got until now.
-			 */
-			skb_pull(skb, count_pull);
-#ifdef CONFIG_ISDN_AUDIO
-			ISDN_AUDIO_SKB_LOCK(skb) = 0;
-#endif
-		}
-		info->rcvcount -= count_put;
-	}
-	return count;
-}
-
 /* isdn_tty_readmodem() is called periodically from within timer-interrupt.
  * It tries getting received data from the receive queue an stuff it into
  * the tty's flip-buffer.
  */
-static void
-isdn_tty_readmodem(unsigned long data)
+void
+isdn_tty_readmodem(void)
 {
-	struct modem_info *info = (struct modem_info *) data;
+	int resched = 0;
+	int midx;
+	int i;
 	int c;
 	int r;
-	ulong flags;
 	struct tty_struct *tty;
+	modem_info *info;
 
-	if (!info->online)
-		return;
-
-	r = 0;
-#ifdef CONFIG_ISDN_AUDIO
-	isdn_audio_eval_dtmf(info);
-	if ((info->vonline & 1) && (info->emu.vpar[1]))
-		isdn_audio_eval_silence(info);
-#endif
-	if ((tty = info->tty)) {
-		if (info->mcr & UART_MCR_RTS) {
-			c = TTY_FLIPBUF_SIZE - tty->flip.count;
-			if (c > 0) {
-				save_flags(flags);
-				cli();
-				r = isdn_tty_readbchan(info,
-						       tty->flip.char_buf_ptr,
-						       tty->flip.flag_buf_ptr, c);
-				/* CISCO AsyncPPP Hack */
-				if (!(info->emu.mdmreg[REG_CPPP] & BIT_CPPP))
-					memset(tty->flip.flag_buf_ptr, 0, r);
-				tty->flip.count += r;
-				tty->flip.flag_buf_ptr += r;
-				tty->flip.char_buf_ptr += r;
-				if (r)
-					schedule_delayed_work(&tty->flip.work, 1);
-				restore_flags(flags);
+	for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
+		if ((midx = dev->m_idx[i]) >= 0) {
+			info = &dev->mdm.info[midx];
+			if (info->online) {
+				r = 0;
+#ifdef CONFIG_ISDN_AUDIO
+				isdn_audio_eval_dtmf(info);
+				if ((info->vonline & 1) && (info->emu.vpar[1]))
+					isdn_audio_eval_silence(info);
+#endif
+				if ((tty = info->tty)) {
+					if (info->mcr & UART_MCR_RTS) {
+						c = TTY_FLIPBUF_SIZE - tty->flip.count;
+						if (c > 0) {
+							r = isdn_readbchan(info->isdn_driver, info->isdn_channel,
+									   tty->flip.char_buf_ptr,
+									   tty->flip.flag_buf_ptr, c, 0);
+							/* CISCO AsyncPPP Hack */
+							if (!(info->emu.mdmreg[REG_CPPP] & BIT_CPPP))
+								memset(tty->flip.flag_buf_ptr, 0, r);
+							tty->flip.count += r;
+							tty->flip.flag_buf_ptr += r;
+							tty->flip.char_buf_ptr += r;
+							if (r)
+								schedule_delayed_work(&tty->flip.work, 1);
+						}
+					} else
+						r = 1;
+				} else
+					r = 1;
+				if (r) {
+					info->rcvsched = 0;
+					resched = 1;
+				} else
+					info->rcvsched = 1;
 			}
-		} else
-			r = 1;
-	} else
-		r = 1;
-
-	if (r) {
-		info->rcvsched = 0;
-		mod_timer(&info->read_timer, jiffies + 4);
-	} else
-		info->rcvsched = 1;
+		}
+	}
+	if (!resched)
+		isdn_timer_ctrl(ISDN_TIMER_MODEMREAD, 0);
 }
 
-static int
-isdn_tty_rcv_skb(struct isdn_slot *slot, struct sk_buff *skb)
+int
+isdn_tty_rcv_skb(int i, int di, int channel, struct sk_buff *skb)
 {
 	ulong flags;
+	int midx;
 #ifdef CONFIG_ISDN_AUDIO
 	int ifmt;
 #endif
 	modem_info *info;
 
-	info = slot->priv;
+	if ((midx = dev->m_idx[i]) < 0) {
+		/* if midx is invalid, packet is not for tty */
+		return 0;
+	}
+	info = &dev->mdm.info[midx];
 #ifdef CONFIG_ISDN_AUDIO
 	ifmt = 1;
 	
@@ -315,12 +206,6 @@ isdn_tty_rcv_skb(struct isdn_slot *slot,
 				skb_pull(skb, 4);
 	}
 #ifdef CONFIG_ISDN_AUDIO
-	if ((size_t)skb_headroom(skb) < sizeof(isdnaudio_header)) {
-		printk(KERN_WARNING
-		       "isdn_audio: insufficient skb_headroom, dropping\n");
-		kfree_skb(skb);
-		return 1;
-	}
 	ISDN_AUDIO_SKB_DLECOUNT(skb) = 0;
 	ISDN_AUDIO_SKB_LOCK(skb) = 0;
 	if (info->vonline & 1) {
@@ -364,53 +249,49 @@ isdn_tty_rcv_skb(struct isdn_slot *slot,
 #endif
 #endif
 	/* Try to deliver directly via tty-flip-buf if queue is empty */
-	save_flags(flags);
-	cli();
-	if (skb_queue_empty(&info->rpqueue))
+	spin_lock_irqsave(&info->readlock, flags);
+	if (skb_queue_empty(&dev->drv[di]->rpqueue[channel]))
 		if (isdn_tty_try_read(info, skb)) {
-			restore_flags(flags);
+			spin_unlock_irqrestore(&info->readlock, flags);
 			return 1;
 		}
 	/* Direct deliver failed or queue wasn't empty.
 	 * Queue up for later dequeueing via timer-irq.
 	 */
-	isdn_tty_queue_tail(info, skb, skb->len
+	__skb_queue_tail(&dev->drv[di]->rpqueue[channel], skb);
+	dev->drv[di]->rcvcount[channel] +=
+		(skb->len
 #ifdef CONFIG_ISDN_AUDIO
 		 + ISDN_AUDIO_SKB_DLECOUNT(skb)
 #endif
-			    );
-	restore_flags(flags);
+			);
+	spin_unlock_irqrestore(&info->readlock, flags);
 	/* Schedule dequeuing */
-	if ((get_isdn_dev())->modempoll && info->rcvsched)
-		mod_timer(&info->read_timer, jiffies + 4);
+	if ((dev->modempoll) && (info->rcvsched))
+		isdn_timer_ctrl(ISDN_TIMER_MODEMREAD, 1);
 	return 1;
 }
 
 void
 isdn_tty_cleanup_xmit(modem_info * info)
 {
-	unsigned long flags;
-
-	save_flags(flags);
-	cli();
 	skb_queue_purge(&info->xmit_queue);
 #ifdef CONFIG_ISDN_AUDIO
 	skb_queue_purge(&info->dtmf_queue);
 #endif
-	restore_flags(flags);
 }
 
 static void
 isdn_tty_tint(modem_info * info)
 {
 	struct sk_buff *skb = skb_dequeue(&info->xmit_queue);
-	int len,
-	 slen;
+	int len, slen;
 
 	if (!skb)
 		return;
 	len = skb->len;
-	if ((slen = isdn_slot_write(info->isdn_slot, skb)) == len) {
+	if ((slen = isdn_writebuf_skb_stub(info->isdn_driver,
+					   info->isdn_channel, 1, skb)) == len) {
 		struct tty_struct *tty = info->tty;
 		info->send_outstanding++;
 		info->msr &= ~UART_MSR_CTS;
@@ -573,11 +454,11 @@ isdn_tty_senddown(modem_info * info)
 	atomic_inc(&info->xmit_lock);
 	if (!(atomic_dec_and_test(&info->xmit_lock)))
 		return;
-	if (info->isdn_slot < 0) {
+	if (info->isdn_driver < 0) {
 		info->xmit_count = 0;
 		return;
 	}
-	skb_res = isdn_slot_hdrlen(info->isdn_slot);
+	skb_res = dev->drv[info->isdn_driver]->interface->hl_hdrlen + 4;
 #ifdef CONFIG_ISDN_AUDIO
 	if (info->vonline & 2)
 		audio_len = buflen * voice_cf[info->emu.vpar[3]];
@@ -677,8 +558,6 @@ isdn_tty_modem_ncarrier(modem_info * inf
 {
 	if (info->ncarrier) {
 		info->nc_timer.expires = jiffies + HZ;
-		info->nc_timer.function = isdn_tty_modem_do_ncarrier;
-		info->nc_timer.data = (unsigned long) info;
 		add_timer(&info->nc_timer);
 	}
 }
@@ -721,8 +600,9 @@ isdn_tty_dial(char *n, modem_info * info
 	int usg = ISDN_USAGE_MODEM;
 	int si = 7;
 	int l2 = m->mdmreg[REG_L2PROT];
-	ulong flags;
-	struct isdn_slot *slot;
+	u_long flags;
+	isdn_ctrl cmd;
+	int i;
 	int j;
 
 	for (j = 7; j >= 0; j--)
@@ -743,39 +623,58 @@ isdn_tty_dial(char *n, modem_info * info
 	}
 #endif
 	m->mdmreg[REG_SI1I] = si2bit[si];
-	save_flags(flags);
-	cli();
-	slot = isdn_get_free_slot(usg, l2, m->mdmreg[REG_L3PROT], -1, -1, m->msn);
-	if (!slot) {
-		restore_flags(flags);
+	spin_lock_irqsave(&dev->lock, flags);
+	i = isdn_get_free_channel(usg, l2, m->mdmreg[REG_L3PROT], -1, -1, m->msn);
+	if (i < 0) {
+		spin_unlock_irqrestore(&dev->lock, flags);
 		isdn_tty_modem_result(RESULT_NO_DIALTONE, info);
 	} else {
-		struct dial_info dial = {
-			.l2_proto = l2,
-			.l3_proto = m->mdmreg[REG_L3PROT],
-			.si1      = si,
-			.si2      = m->mdmreg[REG_SI2],
-			.msn      = m->msn,
-			.phone    = n,
-		};
-
-		info->isdn_slot = slot;
-		slot->usage |= ISDN_USAGE_MODEM;
-		slot->priv = info;
-		slot->event_cb = isdn_tty_event_callback;
+		info->isdn_driver = dev->drvmap[i];
+		info->isdn_channel = dev->chanmap[i];
+		info->drv_index = i;
+		dev->m_idx[i] = info->line;
+		dev->usage[i] |= ISDN_USAGE_OUTGOING;
 		info->last_dir = 1;
-		info->last_l2 = l2;
 		strcpy(info->last_num, n);
-		restore_flags(flags);
+		isdn_info_update();
+		spin_unlock_irqrestore(&dev->lock, flags);
+		cmd.driver = info->isdn_driver;
+		cmd.arg = info->isdn_channel;
+		cmd.command = ISDN_CMD_CLREAZ;
+		isdn_command(&cmd);
+		strcpy(cmd.parm.num, isdn_map_eaz2msn(m->msn, info->isdn_driver));
+		cmd.driver = info->isdn_driver;
+		cmd.command = ISDN_CMD_SETEAZ;
+		isdn_command(&cmd);
+		cmd.driver = info->isdn_driver;
+		cmd.command = ISDN_CMD_SETL2;
+		info->last_l2 = l2;
+		cmd.arg = info->isdn_channel + (l2 << 8);
+		isdn_command(&cmd);
+		cmd.driver = info->isdn_driver;
+		cmd.command = ISDN_CMD_SETL3;
+		cmd.arg = info->isdn_channel + (m->mdmreg[REG_L3PROT] << 8);
 #ifdef CONFIG_ISDN_TTY_FAX
 		if (l2 == ISDN_PROTO_L2_FAX) {
-			dial.fax = info->fax;
+			cmd.parm.fax = info->fax;
 			info->fax->direction = ISDN_TTY_FAX_CONN_OUT;
 		}
 #endif
+		isdn_command(&cmd);
+		cmd.driver = info->isdn_driver;
+		cmd.arg = info->isdn_channel;
+		sprintf(cmd.parm.setup.phone, "%s", n);
+		sprintf(cmd.parm.setup.eazmsn, "%s",
+			isdn_map_eaz2msn(m->msn, info->isdn_driver));
+		cmd.parm.setup.si1 = si;
+		cmd.parm.setup.si2 = m->mdmreg[REG_SI2];
+		cmd.command = ISDN_CMD_DIAL;
 		info->dialing = 1;
-		isdn_slot_dial(info->isdn_slot, &dial);
-		mod_timer(&info->connect_timer, jiffies + info->emu.mdmreg[REG_WAITC] * HZ); 
+		info->emu.carrierwait = 0;
+		strcpy(dev->num[i], n);
+		isdn_info_update();
+		isdn_command(&cmd);
+		isdn_timer_ctrl(ISDN_TIMER_CARRIER, 1);
 	}
 }
 
@@ -787,15 +686,19 @@ void
 isdn_tty_modem_hup(modem_info * info, int local)
 {
 	isdn_ctrl cmd;
-	struct isdn_slot *slot;
+	int di, ch;
 
 	if (!info)
 		return;
 
-	slot = info->isdn_slot;
-	if (!slot)
+	di = info->isdn_driver;
+	ch = info->isdn_channel;
+	if (di < 0 || ch < 0)
 		return;
 
+	info->isdn_driver = -1;
+	info->isdn_channel = -1;
+
 #ifdef ISDN_DEBUG_MODEM_HUP
 	printk(KERN_DEBUG "Mhup ttyI%d\n", info->line);
 #endif
@@ -837,15 +740,21 @@ isdn_tty_modem_hup(modem_info * info, in
 	info->msr &= ~(UART_MSR_DCD | UART_MSR_RI);
 	info->lsr |= UART_LSR_TEMT;
 
-	if (local)
-		isdn_slot_command(slot, ISDN_CMD_HANGUP, &cmd);
+	if (local) {
+		cmd.driver = di;
+		cmd.command = ISDN_CMD_HANGUP;
+		cmd.arg = ch;
+		isdn_command(&cmd);
+	}
 
+	isdn_all_eaz(di, ch);
 	info->emu.mdmreg[REG_RINGCNT] = 0;
-	skb_queue_purge(&info->rpqueue);
-	slot->priv = NULL;
-	slot->event_cb = NULL;
-	isdn_slot_free(slot);
-	info->isdn_slot = NULL;
+	isdn_free_channel(di, ch, 0);
+
+	if (info->drv_index >= 0) {
+		dev->m_idx[info->drv_index] = -1;
+		info->drv_index = -1;
+	}
 }
 
 /*
@@ -875,10 +784,11 @@ isdn_tty_suspend(char *id, modem_info * 
 	printk(KERN_DEBUG "Msusp ttyI%d\n", info->line);
 #endif
 	l = strlen(id);
-	if ((info->isdn_slot >= 0)) {
+	if ((info->isdn_driver >= 0)) {
 		cmd.parm.cmsg.Length = l+18;
 		cmd.parm.cmsg.Command = CAPI_FACILITY;
 		cmd.parm.cmsg.Subcommand = CAPI_REQ;
+		cmd.parm.cmsg.adr.Controller = info->isdn_driver + 1;
 		cmd.parm.cmsg.para[0] = 3; /* 16 bit 0x0003 suplementary service */
 		cmd.parm.cmsg.para[1] = 0;
 		cmd.parm.cmsg.para[2] = l + 3;
@@ -886,7 +796,10 @@ isdn_tty_suspend(char *id, modem_info * 
 		cmd.parm.cmsg.para[4] = 0;
 		cmd.parm.cmsg.para[5] = l;
 		strncpy(&cmd.parm.cmsg.para[6], id, l);
-		isdn_slot_command(info->isdn_slot, CAPI_PUT_MESSAGE, &cmd);
+		cmd.command = CAPI_PUT_MESSAGE;
+		cmd.driver = info->isdn_driver;
+		cmd.arg = info->isdn_channel;
+		isdn_command(&cmd);
 	}
 }
 
@@ -905,7 +818,7 @@ isdn_tty_resume(char *id, modem_info * i
 	int l2 = m->mdmreg[REG_L2PROT];
 	isdn_ctrl cmd;
 	ulong flags;
-	struct isdn_slot *slot;
+	int i;
 	int j;
 	int l;
 
@@ -928,28 +841,44 @@ isdn_tty_resume(char *id, modem_info * i
 	}
 #endif
 	m->mdmreg[REG_SI1I] = si2bit[si];
-	save_flags(flags);
-	cli();
-	slot = isdn_get_free_slot(usg, l2, m->mdmreg[REG_L3PROT], -1, -1, m->msn);
-	if (!slot) {
-		restore_flags(flags);
+	spin_lock_irqsave(&dev->lock, flags);
+	i = isdn_get_free_channel(usg, l2, m->mdmreg[REG_L3PROT], -1, -1, m->msn);
+	if (i < 0) {
+		spin_unlock_irqrestore(&dev->lock, flags);
 		isdn_tty_modem_result(RESULT_NO_DIALTONE, info);
 	} else {
-		info->isdn_slot = slot;
-		slot->usage |= ISDN_USAGE_MODEM;
-		slot->priv = info;
-		slot->event_cb = isdn_tty_event_callback;
+		info->isdn_driver = dev->drvmap[i];
+		info->isdn_channel = dev->chanmap[i];
+		info->drv_index = i;
+		dev->m_idx[i] = info->line;
+		dev->usage[i] |= ISDN_USAGE_OUTGOING;
 		info->last_dir = 1;
 //		strcpy(info->last_num, n);
-		restore_flags(flags);
+		isdn_info_update();
+		spin_unlock_irqrestore(&dev->lock, flags);
+		cmd.driver = info->isdn_driver;
+		cmd.arg = info->isdn_channel;
+		cmd.command = ISDN_CMD_CLREAZ;
+		isdn_command(&cmd);
+		strcpy(cmd.parm.num, isdn_map_eaz2msn(m->msn, info->isdn_driver));
+		cmd.driver = info->isdn_driver;
+		cmd.command = ISDN_CMD_SETEAZ;
+		isdn_command(&cmd);
+		cmd.driver = info->isdn_driver;
+		cmd.command = ISDN_CMD_SETL2;
 		info->last_l2 = l2;
-		cmd.arg = l2 << 8;
-		isdn_slot_command(info->isdn_slot, ISDN_CMD_SETL2, &cmd);
-		cmd.arg = m->mdmreg[REG_L3PROT] << 8;
-		isdn_slot_command(info->isdn_slot, ISDN_CMD_SETL3, &cmd);
+		cmd.arg = info->isdn_channel + (l2 << 8);
+		isdn_command(&cmd);
+		cmd.driver = info->isdn_driver;
+		cmd.command = ISDN_CMD_SETL3;
+		cmd.arg = info->isdn_channel + (m->mdmreg[REG_L3PROT] << 8);
+		isdn_command(&cmd);
+		cmd.driver = info->isdn_driver;
+		cmd.arg = info->isdn_channel;
 		cmd.parm.cmsg.Length = l+18;
 		cmd.parm.cmsg.Command = CAPI_FACILITY;
 		cmd.parm.cmsg.Subcommand = CAPI_REQ;
+		cmd.parm.cmsg.adr.Controller = info->isdn_driver + 1;
 		cmd.parm.cmsg.para[0] = 3; /* 16 bit 0x0003 suplementary service */
 		cmd.parm.cmsg.para[1] = 0;
 		cmd.parm.cmsg.para[2] = l+3;
@@ -957,11 +886,12 @@ isdn_tty_resume(char *id, modem_info * i
 		cmd.parm.cmsg.para[4] = 0;
 		cmd.parm.cmsg.para[5] = l;
 		strncpy(&cmd.parm.cmsg.para[6], id, l);
+		cmd.command =CAPI_PUT_MESSAGE;
 		info->dialing = 1;
 //		strcpy(dev->num[i], n);
 		isdn_info_update();
-		isdn_slot_command(info->isdn_slot, CAPI_PUT_MESSAGE, &cmd);
-		mod_timer(&info->connect_timer, jiffies + info->emu.mdmreg[REG_WAITC] * HZ); 
+		isdn_command(&cmd);
+		isdn_timer_ctrl(ISDN_TIMER_CARRIER, 1);
 	}
 }
 
@@ -977,7 +907,7 @@ isdn_tty_send_msg(modem_info * info, ate
 	int l2 = m->mdmreg[REG_L2PROT];
 	isdn_ctrl cmd;
 	ulong flags;
-	struct isdn_slot *slot;
+	int i;
 	int j;
 	int l;
 
@@ -1004,45 +934,62 @@ isdn_tty_send_msg(modem_info * info, ate
 	}
 #endif
 	m->mdmreg[REG_SI1I] = si2bit[si];
-	save_flags(flags);
-	cli();
-	slot = isdn_get_free_slot(usg, l2, m->mdmreg[REG_L3PROT], -1, -1, m->msn);
-	if (!slot) {
-		restore_flags(flags);
+	spin_lock_irqsave(&dev->lock, flags);
+	i = isdn_get_free_channel(usg, l2, m->mdmreg[REG_L3PROT], -1, -1, m->msn);
+	if (i < 0) {
+		spin_unlock_irqrestore(&dev->lock, flags);
 		isdn_tty_modem_result(RESULT_NO_DIALTONE, info);
 	} else {
-		info->isdn_slot = slot;
-		slot->usage |= ISDN_USAGE_MODEM;
-		slot->priv = info;
-		slot->event_cb = isdn_tty_event_callback;
+		info->isdn_driver = dev->drvmap[i];
+		info->isdn_channel = dev->chanmap[i];
+		info->drv_index = i;
+		dev->m_idx[i] = info->line;
+		dev->usage[i] |= ISDN_USAGE_OUTGOING;
 		info->last_dir = 1;
-		restore_flags(flags);
+		isdn_info_update();
+		spin_unlock_irqrestore(&dev->lock, flags);
+		cmd.driver = info->isdn_driver;
+		cmd.arg = info->isdn_channel;
+		cmd.command = ISDN_CMD_CLREAZ;
+		isdn_command(&cmd);
+		strcpy(cmd.parm.num, isdn_map_eaz2msn(m->msn, info->isdn_driver));
+		cmd.driver = info->isdn_driver;
+		cmd.command = ISDN_CMD_SETEAZ;
+		isdn_command(&cmd);
+		cmd.driver = info->isdn_driver;
+		cmd.command = ISDN_CMD_SETL2;
 		info->last_l2 = l2;
-		cmd.arg = l2 << 8;
-		isdn_slot_command(info->isdn_slot, ISDN_CMD_SETL2, &cmd);
-		cmd.arg = m->mdmreg[REG_L3PROT] << 8;
-		isdn_slot_command(info->isdn_slot, ISDN_CMD_SETL3, &cmd);
+		cmd.arg = info->isdn_channel + (l2 << 8);
+		isdn_command(&cmd);
+		cmd.driver = info->isdn_driver;
+		cmd.command = ISDN_CMD_SETL3;
+		cmd.arg = info->isdn_channel + (m->mdmreg[REG_L3PROT] << 8);
+		isdn_command(&cmd);
+		cmd.driver = info->isdn_driver;
+		cmd.arg = info->isdn_channel;
 		cmd.parm.cmsg.Length = l+14;
 		cmd.parm.cmsg.Command = CAPI_MANUFACTURER;
 		cmd.parm.cmsg.Subcommand = CAPI_REQ;
+		cmd.parm.cmsg.adr.Controller = info->isdn_driver + 1;
 		cmd.parm.cmsg.para[0] = l+1;
 		strncpy(&cmd.parm.cmsg.para[1], msg, l);
 		cmd.parm.cmsg.para[l+1] = 0xd;
+		cmd.command =CAPI_PUT_MESSAGE;
 /*		info->dialing = 1;
 		strcpy(dev->num[i], n);
 		isdn_info_update();
 */
-		isdn_slot_command(info->isdn_slot, CAPI_PUT_MESSAGE, &cmd);
+		isdn_command(&cmd);
 	}
 }
 
 static inline int
-isdn_tty_paranoia_check(modem_info * info, char *name, const char *routine)
+isdn_tty_paranoia_check(modem_info *info, char *name, const char *routine)
 {
 #ifdef MODEM_PARANOIA_CHECK
 	if (!info) {
 		printk(KERN_WARNING "isdn_tty: null info_struct for %s in %s\n",
-		       name, routine);
+			name, routine);
 		return 1;
 	}
 	if (info->magic != ISDN_ASYNC_MAGIC) {
@@ -1119,12 +1066,9 @@ isdn_tty_change_speed(modem_info * info)
 static int
 isdn_tty_startup(modem_info * info)
 {
-	ulong flags;
-
 	if (info->flags & ISDN_ASYNC_INITIALIZED)
 		return 0;
-	save_flags(flags);
-	cli();
+	isdn_lock_drivers();
 #ifdef ISDN_DEBUG_MODEM_OPEN
 	printk(KERN_DEBUG "starting up ttyi%d ...\n", info->line);
 #endif
@@ -1142,7 +1086,6 @@ isdn_tty_startup(modem_info * info)
 	info->flags |= ISDN_ASYNC_INITIALIZED;
 	info->msr |= (UART_MSR_DSR | UART_MSR_CTS);
 	info->send_outstanding = 0;
-	restore_flags(flags);
 	return 0;
 }
 
@@ -1153,15 +1096,12 @@ isdn_tty_startup(modem_info * info)
 static void
 isdn_tty_shutdown(modem_info * info)
 {
-	ulong flags;
-
 	if (!(info->flags & ISDN_ASYNC_INITIALIZED))
 		return;
 #ifdef ISDN_DEBUG_MODEM_OPEN
 	printk(KERN_DEBUG "Shutting down isdnmodem port %d ....\n", info->line);
 #endif
-	save_flags(flags);
-	cli();                  /* Disable interrupts */
+	isdn_unlock_drivers();
 	info->msr &= ~UART_MSR_RI;
 	if (!info->tty || (info->tty->termios->c_cflag & HUPCL)) {
 		info->mcr &= ~(UART_MCR_DTR | UART_MCR_RTS);
@@ -1177,7 +1117,6 @@ isdn_tty_shutdown(modem_info * info)
 		set_bit(TTY_IO_ERROR, &info->tty->flags);
 
 	info->flags &= ~ISDN_ASYNC_INITIALIZED;
-	restore_flags(flags);
 }
 
 /* isdn_tty_write() is the main send-routine. It is called from the upper
@@ -1207,8 +1146,8 @@ isdn_tty_write(struct tty_struct *tty, i
 		c = count;
 		if (c > info->xmit_size - info->xmit_count)
 			c = info->xmit_size - info->xmit_count;
-		if (info->isdn_slot && c > isdn_slot_maxbufsize(info->isdn_slot))
-			c = isdn_slot_maxbufsize(info->isdn_slot);
+		if (info->isdn_driver >= 0 && c > dev->drv[info->isdn_driver]->maxbufsize)
+			c = dev->drv[info->isdn_driver]->maxbufsize;
 		if (c <= 0)
 			break;
 		if ((info->online > 1)
@@ -1216,17 +1155,17 @@ isdn_tty_write(struct tty_struct *tty, i
 		    || (info->vonline & 3)
 #endif
 			) {
-			if (from_user) {
-				if (copy_from_user(&(info->xmit_buf[info->xmit_count]), buf, c)) {
-					total = -EFAULT;
-					goto out;
-				}
-			} else
-				memcpy(&(info->xmit_buf[info->xmit_count]), buf, c);
 #ifdef CONFIG_ISDN_AUDIO
 			if (!info->vonline)
 #endif
-				isdn_tty_check_esc(info, &info->xmit_buf[info->xmit_count], c);
+				isdn_tty_check_esc(buf, m->mdmreg[REG_ESC], c,
+						   &(m->pluscount),
+						   &(m->lastplus),
+						   from_user);
+			if (from_user)
+				copy_from_user(&(info->xmit_buf[info->xmit_count]), buf, c);
+			else
+				memcpy(&(info->xmit_buf[info->xmit_count]), buf, c);
 #ifdef CONFIG_ISDN_AUDIO
 			if (info->vonline) {
 				int cc = isdn_tty_handleDLEdown(info, m, c);
@@ -1265,9 +1204,12 @@ isdn_tty_write(struct tty_struct *tty, i
 				if (info->vonline & 4) { /* ETX seen */
 					isdn_ctrl c;
 
+					c.command = ISDN_CMD_FAXCMD;
+					c.driver = info->isdn_driver;
+					c.arg = info->isdn_channel;
 					c.parm.aux.cmd = ISDN_FAX_CLASS1_CTRL;
 					c.parm.aux.subcmd = ETX;
-					isdn_slot_command(info->isdn_slot, ISDN_CMD_FAXCMD, &c);
+					isdn_command(&c);
 				}
 				info->vonline = 0;
 #ifdef ISDN_DEBUG_MODEM_VOICE
@@ -1296,9 +1238,12 @@ isdn_tty_write(struct tty_struct *tty, i
 	}
 	atomic_dec(&info->xmit_lock);
 	if ((info->xmit_count) || (skb_queue_len(&info->xmit_queue))) {
-		isdn_tty_modem_xmit(info);
+		if (m->mdmreg[REG_DXMT] & BIT_DXMT) {
+			isdn_tty_senddown(info);
+			isdn_tty_tint(info);
+		}
+		isdn_timer_ctrl(ISDN_TIMER_MODEMXMIT, 1);
 	}
-out:
 	if (from_user)
 		up(&info->write_sem);
 	return total;
@@ -1334,22 +1279,16 @@ static void
 isdn_tty_flush_buffer(struct tty_struct *tty)
 {
 	modem_info *info;
-	unsigned long flags;
 
-	save_flags(flags);
-	cli();
 	if (!tty) {
-		restore_flags(flags);
 		return;
 	}
 	info = (modem_info *) tty->driver_data;
 	if (isdn_tty_paranoia_check(info, tty->name, "isdn_tty_flush_buffer")) {
-		restore_flags(flags);
 		return;
 	}
 	isdn_tty_cleanup_xmit(info);
 	info->xmit_count = 0;
-	restore_flags(flags);
 	wake_up_interruptible(&tty->write_wait);
 	if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
 	    tty->ldisc.write_wakeup)
@@ -1364,7 +1303,7 @@ isdn_tty_flush_chars(struct tty_struct *
 	if (isdn_tty_paranoia_check(info, tty->name, "isdn_tty_flush_chars"))
 		return;
 	if ((info->xmit_count) || (skb_queue_len(&info->xmit_queue)))
-		isdn_tty_modem_xmit(info);
+		isdn_timer_ctrl(ISDN_TIMER_MODEMXMIT, 1);
 }
 
 /*
@@ -1424,105 +1363,73 @@ isdn_tty_get_lsr_info(modem_info * info,
 {
 	u_char status;
 	uint result;
-	ulong flags;
 
-	save_flags(flags);
-	cli();
 	status = info->lsr;
-	restore_flags(flags);
 	result = ((status & UART_LSR_TEMT) ? TIOCSER_TEMT : 0);
 	return put_user(result, (uint *) value);
 }
 
 
 static int
-isdn_tty_get_modem_info(modem_info * info, uint * value)
+isdn_tty_tiocmget(struct tty_struct *tty, struct file *file)
 {
-	u_char control,
-	 status;
-	uint result;
-	ulong flags;
+	modem_info *info = (modem_info *) tty->driver_data;
+	u_char control, status;
+
+	if (isdn_tty_paranoia_check(info, tty->name, __FUNCTION__))
+		return -ENODEV;
+	if (tty->flags & (1 << TTY_IO_ERROR))
+		return -EIO;
+
+#ifdef ISDN_DEBUG_MODEM_IOCTL
+	printk(KERN_DEBUG "ttyI%d ioctl TIOCMGET\n", info->line);
+#endif
 
 	control = info->mcr;
-	save_flags(flags);
-	cli();
 	status = info->msr;
-	restore_flags(flags);
-	result = ((control & UART_MCR_RTS) ? TIOCM_RTS : 0)
+	return ((control & UART_MCR_RTS) ? TIOCM_RTS : 0)
 	    | ((control & UART_MCR_DTR) ? TIOCM_DTR : 0)
 	    | ((status & UART_MSR_DCD) ? TIOCM_CAR : 0)
 	    | ((status & UART_MSR_RI) ? TIOCM_RNG : 0)
 	    | ((status & UART_MSR_DSR) ? TIOCM_DSR : 0)
 	    | ((status & UART_MSR_CTS) ? TIOCM_CTS : 0);
-	return put_user(result, (uint *) value);
 }
 
 static int
-isdn_tty_set_modem_info(modem_info * info, uint cmd, uint * value)
+isdn_tty_tiocmset(struct tty_struct *tty, struct file *file,
+		unsigned int set, unsigned int clear)
 {
-	uint arg;
-	int pre_dtr;
+	modem_info *info = (modem_info *) tty->driver_data;
+
+	if (isdn_tty_paranoia_check(info, tty->name, __FUNCTION__))
+		return -ENODEV;
+	if (tty->flags & (1 << TTY_IO_ERROR))
+		return -EIO;
 
-	if (get_user(arg, (uint *) value))
-		return -EFAULT;
-	switch (cmd) {
-		case TIOCMBIS:
-#ifdef ISDN_DEBUG_MODEM_IOCTL
-			printk(KERN_DEBUG "ttyI%d ioctl TIOCMBIS\n", info->line);
-#endif
-			if (arg & TIOCM_RTS) {
-				info->mcr |= UART_MCR_RTS;
-			}
-			if (arg & TIOCM_DTR) {
-				info->mcr |= UART_MCR_DTR;
-				isdn_tty_modem_ncarrier(info);
-			}
-			break;
-		case TIOCMBIC:
-#ifdef ISDN_DEBUG_MODEM_IOCTL
-			printk(KERN_DEBUG "ttyI%d ioctl TIOCMBIC\n", info->line);
-#endif
-			if (arg & TIOCM_RTS) {
-				info->mcr &= ~UART_MCR_RTS;
-			}
-			if (arg & TIOCM_DTR) {
-				info->mcr &= ~UART_MCR_DTR;
-				if (info->emu.mdmreg[REG_DTRHUP] & BIT_DTRHUP) {
-					isdn_tty_modem_reset_regs(info, 0);
-#ifdef ISDN_DEBUG_MODEM_HUP
-					printk(KERN_DEBUG "Mhup in TIOCMBIC\n");
-#endif
-					if (info->online)
-						info->ncarrier = 1;
-					isdn_tty_modem_hup(info, 1);
-				}
-			}
-			break;
-		case TIOCMSET:
 #ifdef ISDN_DEBUG_MODEM_IOCTL
-			printk(KERN_DEBUG "ttyI%d ioctl TIOCMSET\n", info->line);
+	printk(KERN_DEBUG "ttyI%d ioctl TIOCMxxx: %x %x\n", info->line, set, clear);
 #endif
-			pre_dtr = (info->mcr & UART_MCR_DTR);
-			info->mcr = ((info->mcr & ~(UART_MCR_RTS | UART_MCR_DTR))
-				 | ((arg & TIOCM_RTS) ? UART_MCR_RTS : 0)
-			       | ((arg & TIOCM_DTR) ? UART_MCR_DTR : 0));
-			if (pre_dtr |= (info->mcr & UART_MCR_DTR)) {
-				if (!(info->mcr & UART_MCR_DTR)) {
-					if (info->emu.mdmreg[REG_DTRHUP] & BIT_DTRHUP) {
-						isdn_tty_modem_reset_regs(info, 0);
+
+	if (set & TIOCM_RTS)
+		info->mcr |= UART_MCR_RTS;
+	if (set & TIOCM_DTR) {
+		info->mcr |= UART_MCR_DTR;
+		isdn_tty_modem_ncarrier(info);
+	}
+
+	if (clear & TIOCM_RTS)
+		info->mcr &= ~UART_MCR_RTS;
+	if (clear & TIOCM_DTR) {
+		info->mcr &= ~UART_MCR_DTR;
+		if (info->emu.mdmreg[REG_DTRHUP] & BIT_DTRHUP) {
+			isdn_tty_modem_reset_regs(info, 0);
 #ifdef ISDN_DEBUG_MODEM_HUP
-						printk(KERN_DEBUG "Mhup in TIOCMSET\n");
+			printk(KERN_DEBUG "Mhup in TIOCMSET\n");
 #endif
-						if (info->online)
-							info->ncarrier = 1;
-						isdn_tty_modem_hup(info, 1);
-					}
-				} else
-					isdn_tty_modem_ncarrier(info);
-			}
-			break;
-		default:
-			return -EINVAL;
+			if (info->online)
+				info->ncarrier = 1;
+			isdn_tty_modem_hup(info, 1);
+		}
 	}
 	return 0;
 }
@@ -1572,15 +1479,6 @@ isdn_tty_ioctl(struct tty_struct *tty, s
 			    ((tty->termios->c_cflag & ~CLOCAL) |
 			     (arg ? CLOCAL : 0));
 			return 0;
-		case TIOCMGET:
-#ifdef ISDN_DEBUG_MODEM_IOCTL
-			printk(KERN_DEBUG "ttyI%d ioctl TIOCMGET\n", info->line);
-#endif
-			return isdn_tty_get_modem_info(info, (uint *) arg);
-		case TIOCMBIS:
-		case TIOCMBIC:
-		case TIOCMSET:
-			return isdn_tty_set_modem_info(info, cmd, (uint *) arg);
 		case TIOCSERGETLSR:	/* Get line status register */
 #ifdef ISDN_DEBUG_MODEM_IOCTL
 			printk(KERN_DEBUG "ttyI%d ioctl TIOCSERGETLSR\n", info->line);
@@ -1623,7 +1521,6 @@ isdn_tty_block_til_ready(struct tty_stru
 {
 	DECLARE_WAITQUEUE(wait, NULL);
 	int do_clocal = 0;
-	unsigned long flags;
 	int retval;
 
 	/*
@@ -1649,11 +1546,18 @@ isdn_tty_block_til_ready(struct tty_stru
 	 */
 	if ((filp->f_flags & O_NONBLOCK) ||
 	    (tty->flags & (1 << TTY_IO_ERROR))) {
+		if (info->flags & ISDN_ASYNC_CALLOUT_ACTIVE)
+			return -EBUSY;
 		info->flags |= ISDN_ASYNC_NORMAL_ACTIVE;
 		return 0;
 	}
-	if (tty->termios->c_cflag & CLOCAL)
-		do_clocal = 1;
+	if (info->flags & ISDN_ASYNC_CALLOUT_ACTIVE) {
+		if (info->normal_termios.c_cflag & CLOCAL)
+			do_clocal = 1;
+	} else {
+		if (tty->termios->c_cflag & CLOCAL)
+			do_clocal = 1;
+	}
 	/*
 	 * Block waiting for the carrier detect and the line to become
 	 * free (i.e., not in use by the callout).  While we are in
@@ -1667,11 +1571,8 @@ isdn_tty_block_til_ready(struct tty_stru
 	printk(KERN_DEBUG "isdn_tty_block_til_ready before block: ttyi%d, count = %d\n",
 	       info->line, info->count);
 #endif
-	save_flags(flags);
-	cli();
 	if (!(tty_hung_up_p(filp)))
 		info->count--;
-	restore_flags(flags);
 	info->blocked_open++;
 	while (1) {
 		set_current_state(TASK_INTERRUPTIBLE);
@@ -1687,7 +1588,8 @@ isdn_tty_block_til_ready(struct tty_stru
 #endif
 			break;
 		}
-		if (!(info->flags & ISDN_ASYNC_CLOSING) &&
+		if (!(info->flags & ISDN_ASYNC_CALLOUT_ACTIVE) &&
+		    !(info->flags & ISDN_ASYNC_CLOSING) &&
 		    (do_clocal || (info->msr & UART_MSR_DCD))) {
 			break;
 		}
@@ -1728,11 +1630,10 @@ isdn_tty_open(struct tty_struct *tty, st
 	modem_info *info;
 	int retval, line;
 
-
 	line = tty->index;
 	if (line < 0 || line > ISDN_MAX_CHANNELS)
 		return -ENODEV;
-	info = &isdn_mdm.info[line];
+	info = &dev->mdm.info[line];
 	if (isdn_tty_paranoia_check(info, tty->name, "isdn_tty_open"))
 		return -ENODEV;
 	if (!try_module_get(info->owner)) {
@@ -1740,7 +1641,7 @@ isdn_tty_open(struct tty_struct *tty, st
 		return -ENODEV;
 	}
 #ifdef ISDN_DEBUG_MODEM_OPEN
-	printk(KERN_DEBUG "isdn_tty_open %s, count = %d\n", tty->name,
+	printk(KERN_DEBUG "isdn_tty_open %s, count = %d\n", tty->name, 
 	       info->count);
 #endif
 	info->count++;
@@ -1768,7 +1669,7 @@ isdn_tty_open(struct tty_struct *tty, st
 #ifdef ISDN_DEBUG_MODEM_OPEN
 	printk(KERN_DEBUG "isdn_tty_open ttyi%d successful...\n", info->line);
 #endif
-	(get_isdn_dev())->modempoll++;
+	dev->modempoll++;
 #ifdef ISDN_DEBUG_MODEM_OPEN
 	printk(KERN_DEBUG "isdn_tty_open normal exit\n");
 #endif
@@ -1779,23 +1680,15 @@ static void
 isdn_tty_close(struct tty_struct *tty, struct file *filp)
 {
 	modem_info *info = (modem_info *) tty->driver_data;
-	ulong flags;
 	ulong timeout;
 
-	if (!info)
+	if (!info || isdn_tty_paranoia_check(info, tty->name, "isdn_tty_close"))
 		return;
-	if (isdn_tty_paranoia_check(info, tty->name, "isdn_tty_close"))
-		goto out;
-
-	#warning need fixing /kkeil
-	save_flags(flags);
-	cli();
 	if (tty_hung_up_p(filp)) {
-		restore_flags(flags);
 #ifdef ISDN_DEBUG_MODEM_OPEN
 		printk(KERN_DEBUG "isdn_tty_close return after tty_hung_up_p\n");
 #endif
-		goto out;
+		return;
 	}
 	if ((tty->count == 1) && (info->count != 1)) {
 		/*
@@ -1815,13 +1708,21 @@ isdn_tty_close(struct tty_struct *tty, s
 		info->count = 0;
 	}
 	if (info->count) {
-		restore_flags(flags);
 #ifdef ISDN_DEBUG_MODEM_OPEN
 		printk(KERN_DEBUG "isdn_tty_close after info->count != 0\n");
 #endif
-		goto out;
+		return;
 	}
 	info->flags |= ISDN_ASYNC_CLOSING;
+	/*
+	 * Save the termios structure, since this port may have
+	 * separate termios for callout and dialin.
+	 */
+	if (info->flags & ISDN_ASYNC_NORMAL_ACTIVE)
+		info->normal_termios = *tty->termios;
+	if (info->flags & ISDN_ASYNC_CALLOUT_ACTIVE)
+		info->callout_termios = *tty->termios;
+
 	tty->closing = 1;
 	/*
 	 * At this point we stop accepting input.  To do this, we
@@ -1830,7 +1731,7 @@ isdn_tty_close(struct tty_struct *tty, s
 	 * line status register.
 	 */
 	if (info->flags & ISDN_ASYNC_INITIALIZED) {
-		tty_wait_until_sent(tty, 30 * HZ);	/* 30 seconds timeout */
+		tty_wait_until_sent(tty, 3000);	/* 30 seconds timeout */
 		/*
 		 * Before we drop DTR, make sure the UART transmitter
 		 * has completely drained; this is especially
@@ -1844,7 +1745,7 @@ isdn_tty_close(struct tty_struct *tty, s
 				break;
 		}
 	}
-	(get_isdn_dev())->modempoll--;
+	dev->modempoll--;
 	isdn_tty_shutdown(info);
 	if (tty->driver->flush_buffer)
 		tty->driver->flush_buffer(tty);
@@ -1853,6 +1754,7 @@ isdn_tty_close(struct tty_struct *tty, s
 	info->tty = 0;
 	info->ncarrier = 0;
 	tty->closing = 0;
+	module_put(info->owner);
 	if (info->blocked_open) {
 		set_current_state(TASK_INTERRUPTIBLE);
 		schedule_timeout(HZ/2);
@@ -1860,12 +1762,9 @@ isdn_tty_close(struct tty_struct *tty, s
 	}
 	info->flags &= ~(ISDN_ASYNC_NORMAL_ACTIVE | ISDN_ASYNC_CLOSING);
 	wake_up_interruptible(&info->close_wait);
-	restore_flags(flags);
 #ifdef ISDN_DEBUG_MODEM_OPEN
 	printk(KERN_DEBUG "isdn_tty_close normal exit\n");
 #endif
- out:
-	module_put(info->owner);
 }
 
 /*
@@ -1880,7 +1779,7 @@ isdn_tty_hangup(struct tty_struct *tty)
 		return;
 	isdn_tty_shutdown(info);
 	info->count = 0;
-	info->flags &= ~ISDN_ASYNC_NORMAL_ACTIVE;
+	info->flags &= ~(ISDN_ASYNC_NORMAL_ACTIVE | ISDN_ASYNC_CALLOUT_ACTIVE);
 	info->tty = 0;
 	wake_up_interruptible(&info->open_wait);
 }
@@ -1988,13 +1887,12 @@ modem_write_profile(atemu * m)
 	memcpy(m->profile, m->mdmreg, ISDN_MODEM_NUMREG);
 	memcpy(m->pmsn, m->msn, ISDN_MSNLEN);
 	memcpy(m->plmsn, m->lmsn, ISDN_LMSNLEN);
-	if ((get_isdn_dev())->profd)
-		kill_pg_info(SIGIO, SEND_SIG_PRIV,
-			process_group((get_isdn_dev())->profd));
+	if (dev->profd)
+		send_sig(SIGIO, dev->profd, 1);
 }
 
 static struct tty_operations modem_ops = {
-	.open = isdn_tty_open,
+        .open = isdn_tty_open,
 	.close = isdn_tty_close,
 	.write = isdn_tty_write,
 	.flush_chars = isdn_tty_flush_chars,
@@ -2006,16 +1904,18 @@ static struct tty_operations modem_ops =
 	.unthrottle = isdn_tty_unthrottle,
 	.set_termios = isdn_tty_set_termios,
 	.hangup = isdn_tty_hangup,
+	.tiocmget = isdn_tty_tiocmget,
+	.tiocmset = isdn_tty_tiocmset,
 };
 
 int
-isdn_tty_init(void)
+isdn_tty_modem_init(void)
 {
-	struct isdn_modem *m;
-	int i, retval;
-	modem_info *info;
+	isdn_modem_t	*m;
+	int		i, retval;
+	modem_info	*info;
 
-	m = &isdn_mdm;
+	m = &dev->mdm;
 	m->tty_modem = alloc_tty_driver(ISDN_MAX_CHANNELS);
 	if (!m->tty_modem)
 		return -ENOMEM;
@@ -2027,7 +1927,7 @@ isdn_tty_init(void)
 	m->tty_modem->subtype = SERIAL_TYPE_NORMAL;
 	m->tty_modem->init_termios = tty_std_termios;
 	m->tty_modem->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL;
-	m->tty_modem->flags = TTY_DRIVER_REAL_RAW;
+	m->tty_modem->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_NO_DEVFS;
 	m->tty_modem->driver_name = "isdn_tty";
 	tty_set_operations(m->tty_modem, &modem_ops);
 	retval = tty_register_driver(m->tty_modem);
@@ -2040,10 +1940,14 @@ isdn_tty_init(void)
 #ifdef CONFIG_ISDN_TTY_FAX
 		if (!(info->fax = kmalloc(sizeof(T30_s), GFP_KERNEL))) {
 			printk(KERN_ERR "Could not allocate fax t30-buffer\n");
-			return -3;
+			retval = -ENOMEM;
+			goto err_unregister;
 		}
 #endif
+#ifdef MODULE
 		info->owner = THIS_MODULE;
+#endif
+		spin_lock_init(&info->readlock);
 		init_MUTEX(&info->write_sem);
 		sprintf(info->last_cause, "0000");
 		sprintf(info->last_num, "none");
@@ -2061,41 +1965,27 @@ isdn_tty_init(void)
 		info->blocked_open = 0;
 		init_waitqueue_head(&info->open_wait);
 		init_waitqueue_head(&info->close_wait);
-		info->isdn_slot = NULL;
-		init_timer(&info->escape_timer);
-		info->escape_timer.data = (unsigned long) info;
-		info->escape_timer.function = isdn_tty_escape_timer;
-		init_timer(&info->ring_timer);
-		info->ring_timer.data = (unsigned long) info;
-		info->ring_timer.function = isdn_tty_ring_timer;
-		init_timer(&info->connect_timer);
-		info->connect_timer.data = (unsigned long) info;
-		info->connect_timer.function = isdn_tty_connect_timer;
-		init_timer(&info->read_timer);
-		info->read_timer.data = (unsigned long) info;
-		info->read_timer.function = isdn_tty_readmodem;
-		init_waitqueue_head(&info->open_wait);
-		init_waitqueue_head(&info->close_wait);
-		skb_queue_head_init(&info->rpqueue);
+		info->isdn_driver = -1;
+		info->isdn_channel = -1;
+		info->drv_index = -1;
 		info->xmit_size = ISDN_SERIAL_XMIT_SIZE;
+		init_timer(&info->nc_timer);
+		info->nc_timer.function = isdn_tty_modem_do_ncarrier;
+		info->nc_timer.data = (unsigned long) info;
 		skb_queue_head_init(&info->xmit_queue);
 #ifdef CONFIG_ISDN_AUDIO
 		skb_queue_head_init(&info->dtmf_queue);
 #endif
-		info->xmit_buf = kmalloc(ISDN_SERIAL_XMIT_MAX + 5, GFP_KERNEL);
-		if (!info->xmit_buf) {
+		if (!(info->xmit_buf = kmalloc(ISDN_SERIAL_XMIT_MAX + 5, GFP_KERNEL))) {
 			printk(KERN_ERR "Could not allocate modem xmit-buffer\n");
-#ifdef CONFIG_ISDN_TTY_FAX
-			kfree(info->fax);
-#endif
-			goto err_unregister_cua;
+			retval = -ENOMEM;
+			goto err_unregister;
 		}
 		/* Make room for T.70 header */
 		info->xmit_buf += 4;
 	}
 	return 0;
-
- err_unregister_cua:
+err_unregister:
 	for (i--; i >= 0; i--) {
 		info = &m->info[i];
 #ifdef CONFIG_ISDN_TTY_FAX
@@ -2117,19 +2007,19 @@ isdn_tty_exit(void)
 	int i;
 
 	for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
-		info = &isdn_mdm.info[i];
+		info = &dev->mdm.info[i];
 		isdn_tty_cleanup_xmit(info);
-		skb_queue_purge(&info->rpqueue);
 #ifdef CONFIG_ISDN_TTY_FAX
 		kfree(info->fax);
 #endif
 		kfree(info->xmit_buf - 4);
 	}
-	tty_unregister_driver(isdn_mdm.tty_modem);
-	put_tty_driver(isdn_mdm.tty_modem);
-	isdn_mdm.tty_modem = NULL;
+	tty_unregister_driver(dev->mdm.tty_modem);
+	put_tty_driver(dev->mdm.tty_modem);
+	dev->mdm.tty_modem = NULL;
 }
 
+
 /*
  * isdn_tty_match_icall(char *MSN, atemu *tty_emulator, int dev_idx)
  *      match the MSN against the MSNs (glob patterns) defined for tty_emulator,
@@ -2193,11 +2083,12 @@ isdn_tty_match_icall(char *cid, atemu *e
  *      CID is longer.
  */
 int
-isdn_tty_find_icall(struct isdn_slot *slot, setup_parm *setup)
+isdn_tty_find_icall(int di, int ch, setup_parm *setup)
 {
 	char *eaz;
 	int i;
 	int wret;
+	int idx;
 	int si1;
 	int si2;
 	char *nr;
@@ -2219,69 +2110,76 @@ isdn_tty_find_icall(struct isdn_slot *sl
 	printk(KERN_DEBUG "m_fi: eaz=%s si1=%d si2=%d\n", eaz, si1, si2);
 #endif
 	wret = 0;
-	save_flags(flags);
-	cli();
+	spin_lock_irqsave(&dev->lock, flags);
 	for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
-		modem_info *info = &isdn_mdm.info[i];
+		modem_info *info = &dev->mdm.info[i];
 
                 if (info->count == 0)
                     continue;
 		if ((info->emu.mdmreg[REG_SI1] & si2bit[si1]) &&  /* SI1 is matching */
 		    (info->emu.mdmreg[REG_SI2] == si2))	{         /* SI2 is matching */
+			idx = isdn_dc2minor(di, ch);
 #ifdef ISDN_DEBUG_MODEM_ICALL
 			printk(KERN_DEBUG "m_fi: match1 wret=%d\n", wret);
-			printk(KERN_DEBUG "m_fi: sl=%d flags=%08lx drv=%d ch=%d usg=%d\n", sl,
+			printk(KERN_DEBUG "m_fi: idx=%d flags=%08lx drv=%d ch=%d usg=%d\n", idx,
 			       info->flags, info->isdn_driver, info->isdn_channel,
-			       slot->usage);
+			       dev->usage[idx]);
 #endif
 			if (
 #ifndef FIX_FILE_TRANSFER
 				(info->flags & ISDN_ASYNC_NORMAL_ACTIVE) &&
 #endif
-				(!info->isdn_slot)) {
+				(info->isdn_driver == -1) &&
+				(info->isdn_channel == -1) &&
+				(USG_NONE(dev->usage[idx]))) {
 				int matchret;
 
-				if ((matchret = isdn_tty_match_icall(eaz, &info->emu, slot->di)) > wret)
+				if ((matchret = isdn_tty_match_icall(eaz, &info->emu, di)) > wret)
 					wret = matchret;
 				if (!matchret) {                  /* EAZ is matching */
-					info->isdn_slot = slot;
-					slot->usage |= isdn_calc_usage(si1, info->emu.mdmreg[REG_L2PROT]);
-					slot->priv = info;
-					slot->event_cb = isdn_tty_event_callback;
-					strcpy(slot->num, nr);
+					info->isdn_driver = di;
+					info->isdn_channel = ch;
+					info->drv_index = idx;
+					dev->m_idx[idx] = info->line;
+					dev->usage[idx] &= ISDN_USAGE_EXCLUSIVE;
+					dev->usage[idx] |= isdn_calc_usage(si1, info->emu.mdmreg[REG_L2PROT]); 
+					strcpy(dev->num[idx], nr);
 					strcpy(info->emu.cpn, eaz);
 					info->emu.mdmreg[REG_SI1I] = si2bit[si1];
 					info->emu.mdmreg[REG_PLAN] = setup->plan;
 					info->emu.mdmreg[REG_SCREEN] = setup->screen;
-					restore_flags(flags);
+					isdn_info_update();
+					spin_unlock_irqrestore(&dev->lock, flags);
 					printk(KERN_INFO "isdn_tty: call from %s, -> RING on ttyI%d\n", nr,
 					       info->line);
 					info->msr |= UART_MSR_RI;
 					isdn_tty_modem_result(RESULT_RING, info);
-					mod_timer(&info->ring_timer, jiffies + RING_TIMEOUT);
+					isdn_timer_ctrl(ISDN_TIMER_MODEMRING, 1);
 					return 1;
 				}
 			}
 		}
 	}
-	restore_flags(flags);
+	spin_unlock_irqrestore(&dev->lock, flags);
 	printk(KERN_INFO "isdn_tty: call from %s -> %s %s\n", nr, eaz,
-	       (wret != 2)? "rejected" : "ignored");
+	       ((dev->drv[di]->flags & DRV_FLAG_REJBUS) && (wret != 2))? "rejected" : "ignored");
 	return (wret == 2)?3:0;
 }
 
 #define TTY_IS_ACTIVE(info) \
-	(info->flags & ISDN_ASYNC_NORMAL_ACTIVE)
+	(info->flags & (ISDN_ASYNC_NORMAL_ACTIVE | ISDN_ASYNC_CALLOUT_ACTIVE))
 
-static int
-isdn_tty_stat_callback(struct isdn_slot *slot, isdn_ctrl *c)
+int
+isdn_tty_stat_callback(int i, isdn_ctrl *c)
 {
-	isdn_ctrl cmd;
+	int mi;
 	modem_info *info;
 	char *e;
 
-	info = slot->priv;
-	if (1) {
+	if (i < 0)
+		return 0;
+	if ((mi = dev->m_idx[i]) >= 0) {
+		info = &dev->mdm.info[mi];
 		switch (c->command) {
                         case ISDN_STAT_CINF:
                                 printk(KERN_DEBUG "CHARGEINFO on ttyI%d: %ld %s\n", info->line, c->arg, c->parm.num);
@@ -2294,12 +2192,16 @@ isdn_tty_stat_callback(struct isdn_slot 
 #ifdef ISDN_TTY_STAT_DEBUG
 				printk(KERN_DEBUG "tty_STAT_BSENT ttyI%d\n", info->line);
 #endif
-				info->msr |= UART_MSR_CTS;
-				if (info->send_outstanding)
-					if (!(--info->send_outstanding))
-						info->lsr |= UART_LSR_TEMT;
-				isdn_tty_tint(info);
-				return 1;
+				if ((info->isdn_driver == c->driver) &&
+				    (info->isdn_channel == c->arg)) {
+					info->msr |= UART_MSR_CTS;
+					if (info->send_outstanding)
+						if (!(--info->send_outstanding))
+							info->lsr |= UART_LSR_TEMT;
+					isdn_tty_tint(info);
+					return 1;
+				}
+				break;
 			case ISDN_STAT_CAUSE:
 #ifdef ISDN_TTY_STAT_DEBUG
 				printk(KERN_DEBUG "tty_STAT_CAUSE ttyI%d\n", info->line);
@@ -2326,7 +2228,6 @@ isdn_tty_stat_callback(struct isdn_slot 
 #endif
 				if (TTY_IS_ACTIVE(info)) {
 					if (info->dialing == 1) {
-						isdn_slot_command(info->isdn_slot, ISDN_CMD_ACCEPTB, &cmd);
 						info->dialing = 2;
 						return 1;
 					}
@@ -2376,14 +2277,14 @@ isdn_tty_stat_callback(struct isdn_slot 
 						info->last_dir = 0;
 					info->dialing = 0;
 					info->rcvsched = 1;
-					if (USG_MODEM(slot->usage)) {
+					if (USG_MODEM(dev->usage[i])) {
 						if (info->emu.mdmreg[REG_L2PROT] == ISDN_PROTO_L2_MODEM) {
 							strcpy(info->emu.connmsg, c->parm.num);
 							isdn_tty_modem_result(RESULT_CONNECT, info);
 						} else
 							isdn_tty_modem_result(RESULT_CONNECT64000, info);
 					}
-					if (USG_VOICE(slot->usage))
+					if (USG_VOICE(dev->usage[i]))
 						isdn_tty_modem_result(RESULT_VCON, info);
 					return 1;
 				}
@@ -2400,6 +2301,34 @@ isdn_tty_stat_callback(struct isdn_slot 
 					return 1;
 				}
 				break;
+			case ISDN_STAT_NODCH:
+#ifdef ISDN_TTY_STAT_DEBUG
+				printk(KERN_DEBUG "tty_STAT_NODCH ttyI%d\n", info->line);
+#endif
+				if (TTY_IS_ACTIVE(info)) {
+					if (info->dialing) {
+						info->dialing = 0;
+						info->last_l2 = -1;
+						info->last_si = 0;
+						sprintf(info->last_cause, "0000");
+						isdn_tty_modem_result(RESULT_NO_DIALTONE, info);
+					}
+					isdn_tty_modem_hup(info, 0);
+					return 1;
+				}
+				break;
+			case ISDN_STAT_UNLOAD:
+#ifdef ISDN_TTY_STAT_DEBUG
+				printk(KERN_DEBUG "tty_STAT_UNLOAD ttyI%d\n", info->line);
+#endif
+				for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
+					info = &dev->mdm.info[i];
+					if (info->isdn_driver == c->driver) {
+						if (info->online)
+							isdn_tty_modem_hup(info, 1);
+					}
+				}
+				return 1;
 #ifdef CONFIG_ISDN_TTY_FAX
 			case ISDN_STAT_FAXIND:
 				if (TTY_IS_ACTIVE(info)) {
@@ -2443,7 +2372,7 @@ isdn_tty_at_cout(char *msg, modem_info *
 	atemu *m = &info->emu;
 	char *p;
 	char c;
-	ulong flags;
+	u_long flags;
 	struct sk_buff *skb = 0;
 	char *sp = 0;
 
@@ -2451,30 +2380,22 @@ isdn_tty_at_cout(char *msg, modem_info *
 		printk(KERN_WARNING "isdn_tty: Null-Message in isdn_tty_at_cout\n");
 		return;
 	}
-	save_flags(flags);
-	cli();
+	spin_lock_irqsave(&info->readlock, flags);
 	tty = info->tty;
 	if ((info->flags & ISDN_ASYNC_CLOSING) || (!tty)) {
-		restore_flags(flags);
+		spin_unlock_irqrestore(&info->readlock, flags);
 		return;
 	}
 
 	/* use queue instead of direct flip, if online and */
 	/* data is in queue or flip buffer is full */
 	if ((info->online) && (((tty->flip.count + strlen(msg)) >= TTY_FLIPBUF_SIZE) ||
-	    (!skb_queue_empty(&info->rpqueue)))) {
-		skb = alloc_skb(strlen(msg)
-#ifdef CONFIG_ISDN_AUDIO
-			+ sizeof(isdnaudio_header)
-#endif
-			, GFP_ATOMIC);
+	    (!skb_queue_empty(&dev->drv[info->isdn_driver]->rpqueue[info->isdn_channel])))) {
+		skb = alloc_skb(strlen(msg), GFP_ATOMIC);
 		if (!skb) {
-			restore_flags(flags);
+			spin_unlock_irqrestore(&info->readlock, flags);
 			return;
 		}
-#ifdef CONFIG_ISDN_AUDIO
-		skb_reserve(skb, sizeof(isdnaudio_header));
-#endif
 		sp = skb_put(skb, strlen(msg));
 #ifdef CONFIG_ISDN_AUDIO
 		ISDN_AUDIO_SKB_DLECOUNT(skb) = 0;
@@ -2505,13 +2426,15 @@ isdn_tty_at_cout(char *msg, modem_info *
 		}
 	}
 	if (skb) {
-		isdn_tty_queue_tail(info, skb, skb->len);
-		restore_flags(flags);
+		__skb_queue_tail(&dev->drv[info->isdn_driver]->rpqueue[info->isdn_channel], skb);
+		dev->drv[info->isdn_driver]->rcvcount[info->isdn_channel] += skb->len;
+		spin_unlock_irqrestore(&info->readlock, flags);
 		/* Schedule dequeuing */
-		if ((get_isdn_dev())->modempoll && info->rcvsched)
-			mod_timer(&info->read_timer, jiffies + 4);
+		if ((dev->modempoll) && (info->rcvsched))
+			isdn_timer_ctrl(ISDN_TIMER_MODEMREAD, 1);
+
 	} else {
-		restore_flags(flags);
+		spin_unlock_irqrestore(&info->readlock, flags);
 		schedule_delayed_work(&tty->flip.work, 1);
 	}
 }
@@ -2522,7 +2445,7 @@ isdn_tty_at_cout(char *msg, modem_info *
 static void
 isdn_tty_on_hook(modem_info * info)
 {
-	if (info->isdn_slot) {
+	if (info->isdn_channel >= 0) {
 #ifdef ISDN_DEBUG_MODEM_HUP
 		printk(KERN_DEBUG "Mhup in isdn_tty_on_hook\n");
 #endif
@@ -2539,56 +2462,54 @@ isdn_tty_off_hook(void)
 #define PLUSWAIT1 (HZ/2)        /* 0.5 sec. */
 #define PLUSWAIT2 (HZ*3/2)      /* 1.5 sec */
 
-static void
-isdn_tty_escape_timer(unsigned long data)
-{
-	struct modem_info *info = (struct modem_info *) data;
-
-	if (!info->online)
-		return;
-	
-	info->emu.pluscount = 0;
-	info->online = 0;
-	isdn_tty_modem_result(RESULT_OK, info);
-}
-
 /*
  * Check Buffer for Modem-escape-sequence, activate timer-callback to
  * isdn_tty_modem_escape() if sequence found.
+ *
+ * Parameters:
+ *   p          pointer to databuffer
+ *   plus       escape-character
+ *   count      length of buffer
+ *   pluscount  count of valid escape-characters so far
+ *   lastplus   timestamp of last character
  */
-static void isdn_tty_check_esc(struct modem_info *info, 
-			       const unsigned char *p, int count)
+static void
+isdn_tty_check_esc(const u_char * p, u_char plus, int count, int *pluscount,
+		   u_long *lastplus, int from_user)
 {
-	unsigned char plus = info->emu.mdmreg[REG_ESC];
+	char cbuf[3];
 
 	if (plus > 127)
 		return;
-
 	if (count > 3) {
 		p += count - 3;
 		count = 3;
-		info->emu.pluscount = 0;
-		info->emu.lastplus = jiffies;
+		*pluscount = 0;
 	}
-	for (; count > 0; info->emu.lastplus = jiffies, count--) {
-		if (*(p++) != plus) {
-			info->emu.pluscount = 0;
-			continue;
-		}
-		if (info->emu.pluscount == 0) {
-			if (time_after(jiffies, info->emu.lastplus + PLUSWAIT2))
-				info->emu.pluscount = 1;
-		} else {
-			if (time_after(jiffies, info->emu.lastplus + PLUSWAIT1))
-				info->emu.pluscount = 1;
-			else
-				info->emu.pluscount++;
-		}
+	if (from_user) {
+		copy_from_user(cbuf, p, count);
+		p = cbuf;
+	}
+	while (count > 0) {
+		if (*(p++) == plus) {
+			if ((*pluscount)++) {
+				/* Time since last '+' > 0.5 sec. ? */
+				if (time_after(jiffies, *lastplus + PLUSWAIT1))
+					*pluscount = 1;
+			} else {
+				/* Time since last non-'+' < 1.5 sec. ? */
+				if (time_before(jiffies, *lastplus + PLUSWAIT2))
+					*pluscount = 0;
+			}
+			if ((*pluscount == 3) && (count == 1))
+				isdn_timer_ctrl(ISDN_TIMER_MODEMPLUS, 1);
+			if (*pluscount > 3)
+				*pluscount = 1;
+		} else
+			*pluscount = 0;
+		*lastplus = jiffies;
+		count--;
 	}
-	if (info->emu.pluscount == 3)
-		mod_timer(&info->escape_timer, jiffies + PLUSWAIT2);
-	else
-		del_timer(&info->escape_timer);
 }
 
 /*
@@ -2606,7 +2527,6 @@ isdn_tty_modem_result(int code, modem_in
 	{"OK", "CONNECT", "RING", "NO CARRIER", "ERROR",
 	 "CONNECT 64000", "NO DIALTONE", "BUSY", "NO ANSWER",
 	 "RINGING", "NO MSN/EAZ", "VCON", "RUNG"};
-	ulong flags;
 	char s[ISDN_MSNLEN+10];
 
 	switch (code) {
@@ -2622,16 +2542,12 @@ isdn_tty_modem_result(int code, modem_in
 			       (info->flags & ISDN_ASYNC_CLOSING),
 			       (!info->tty));
 #endif
-			save_flags(flags);
-			cli();
 			m->mdmreg[REG_RINGCNT] = 0;
 			del_timer(&info->nc_timer);
 			info->ncarrier = 0;
 			if ((info->flags & ISDN_ASYNC_CLOSING) || (!info->tty)) {
-				restore_flags(flags);
 				return;
 			}
-			restore_flags(flags);
 #ifdef CONFIG_ISDN_AUDIO
 			if (info->vonline & 1) {
 #ifdef ISDN_DEBUG_MODEM_VOICE
@@ -2683,7 +2599,7 @@ isdn_tty_modem_result(int code, modem_in
 			    /* print CID, _before_ _every_ ring */
 			    if (!(m->mdmreg[REG_CIDONCE] & BIT_CIDONCE)) {
 				    isdn_tty_at_cout("\r\nCALLER NUMBER: ", info);
-				    isdn_tty_at_cout(info->isdn_slot->num, info);
+				    isdn_tty_at_cout(dev->num[info->drv_index], info);
 				    if (m->mdmreg[REG_CDN] & BIT_CDN) {
 					    isdn_tty_at_cout("\r\nCALLED NUMBER: ", info);
 					    isdn_tty_at_cout(info->emu.cpn, info);
@@ -2712,7 +2628,7 @@ isdn_tty_modem_result(int code, modem_in
 					    (m->mdmreg[REG_RINGCNT] == 1)) {
 						isdn_tty_at_cout("\r\n", info);
 						isdn_tty_at_cout("CALLER NUMBER: ", info);
-						isdn_tty_at_cout(info->isdn_slot->num, info);
+						isdn_tty_at_cout(dev->num[info->drv_index], info);
 						if (m->mdmreg[REG_CDN] & BIT_CDN) {
 							isdn_tty_at_cout("\r\nCALLED NUMBER: ", info);
 							isdn_tty_at_cout(info->emu.cpn, info);
@@ -2762,18 +2678,16 @@ isdn_tty_modem_result(int code, modem_in
 		}
 	}
 	if (code == RESULT_NO_CARRIER) {
-		save_flags(flags);
-		cli();
 		if ((info->flags & ISDN_ASYNC_CLOSING) || (!info->tty)) {
-			restore_flags(flags);
 			return;
 		}
 		if (info->tty->ldisc.flush_buffer)
 			info->tty->ldisc.flush_buffer(info->tty);
-		if (info->flags & ISDN_ASYNC_CHECK_CD) {
+		if ((info->flags & ISDN_ASYNC_CHECK_CD) &&
+		    (!((info->flags & ISDN_ASYNC_CALLOUT_ACTIVE) &&
+		       (info->flags & ISDN_ASYNC_CALLOUT_NOHUP)))) {
 			tty_hangup(info->tty);
 		}
-		restore_flags(flags);
 	}
 }
 
@@ -3222,7 +3136,7 @@ isdn_tty_cmd_ATA(modem_info * info)
 	if (info->msr & UART_MSR_RI) {
 		/* Accept incoming call */
 		info->last_dir = 0;
-		strcpy(info->last_num, info->isdn_slot->num);
+		strcpy(info->last_num, dev->num[info->drv_index]);
 		m->mdmreg[REG_RINGCNT] = 0;
 		info->msr &= ~UART_MSR_RI;
 		l2 = m->mdmreg[REG_L2PROT];
@@ -3236,20 +3150,28 @@ isdn_tty_cmd_ATA(modem_info * info)
 				l2 = ISDN_PROTO_L2_X75I;
 		}
 #endif
-		cmd.arg = l2 << 8;
+		cmd.driver = info->isdn_driver;
+		cmd.command = ISDN_CMD_SETL2;
+		cmd.arg = info->isdn_channel + (l2 << 8);
 		info->last_l2 = l2;
-		isdn_slot_command(info->isdn_slot, ISDN_CMD_SETL2, &cmd);
-		cmd.arg = m->mdmreg[REG_L3PROT] << 8;
+		isdn_command(&cmd);
+		cmd.driver = info->isdn_driver;
+		cmd.command = ISDN_CMD_SETL3;
+		cmd.arg = info->isdn_channel + (m->mdmreg[REG_L3PROT] << 8);
 #ifdef CONFIG_ISDN_TTY_FAX
 		if (l2 == ISDN_PROTO_L2_FAX) {
 			cmd.parm.fax = info->fax;
 			info->fax->direction = ISDN_TTY_FAX_CONN_IN;
 		}
 #endif
-		isdn_slot_command(info->isdn_slot, ISDN_CMD_SETL3, &cmd);
+		isdn_command(&cmd);
+		cmd.driver = info->isdn_driver;
+		cmd.arg = info->isdn_channel;
+		cmd.command = ISDN_CMD_ACCEPTD;
 		info->dialing = 16;
-		isdn_slot_command(info->isdn_slot, ISDN_CMD_ACCEPTD, &cmd);
-		mod_timer(&info->connect_timer, jiffies + info->emu.mdmreg[REG_WAITC] * HZ); 
+		info->emu.carrierwait = 0;
+		isdn_command(&cmd);
+		isdn_timer_ctrl(ISDN_TIMER_CARRIER, 1);
 	} else
 		isdn_tty_modem_result(RESULT_NO_ANSWER, info);
 }
@@ -3293,7 +3215,7 @@ isdn_tty_cmd_PLUSF(char **p, modem_info 
 #ifdef CONFIG_ISDN_TTY_FAX
 					case '1':
 						p[0]++;
-						if (!((get_isdn_dev())->global_features &
+						if (!(dev->global_features &
 							ISDN_FEATURE_L3_FCLASS1))
 							PARSE_ERROR1;
 						m->mdmreg[REG_SI1] = 1;
@@ -3304,7 +3226,7 @@ isdn_tty_cmd_PLUSF(char **p, modem_info 
 						break;
 					case '2':
 						p[0]++;
-						if (!((get_isdn_dev())->global_features &
+						if (!(dev->global_features &
 							ISDN_FEATURE_L3_FCLASS2))
 							PARSE_ERROR1;
 						m->mdmreg[REG_SI1] = 1;
@@ -3326,10 +3248,10 @@ isdn_tty_cmd_PLUSF(char **p, modem_info 
 						p[0]++;
 						strcpy(rs, "\r\n0,");
 #ifdef CONFIG_ISDN_TTY_FAX
-						if ((get_isdn_dev())->global_features &
+						if (dev->global_features &
 							ISDN_FEATURE_L3_FCLASS1)
 							strcat(rs, "1,");
-						if ((get_isdn_dev())->global_features &
+						if (dev->global_features &
 							ISDN_FEATURE_L3_FCLASS2)
 							strcat(rs, "2,");
 #endif
@@ -3604,10 +3526,12 @@ isdn_tty_cmd_PLUSV(char **p, modem_info 
 							PARSE_ERROR1;
 						m->vpar[4] = par1;
 						m->vpar[5] = par2;
-						cmd.arg = ISDN_AUDIO_SETDD << 8;
+						cmd.driver = info->isdn_driver;
+						cmd.command = ISDN_CMD_AUDIO;
+						cmd.arg = info->isdn_channel + (ISDN_AUDIO_SETDD << 8);
 						cmd.parm.num[0] = par1;
 						cmd.parm.num[1] = par2;
-						isdn_slot_command(info->isdn_slot, ISDN_CMD_AUDIO, &cmd);
+						isdn_command(&cmd);
 						break;
 					} else
 					if (*p[0] == '?') {
@@ -3919,34 +3843,99 @@ isdn_tty_edit_at(const char *p, int coun
 	return total;
 }
 
-static void
-isdn_tty_ring_timer(unsigned long data)
+/*
+ * Switch all modem-channels who are online and got a valid
+ * escape-sequence 1.5 seconds ago, to command-mode.
+ * This function is called every second via timer-interrupt from within
+ * timer-dispatcher isdn_timer_function()
+ */
+void
+isdn_tty_modem_escape(void)
 {
-	struct modem_info *info = (struct modem_info *) data;
-
-	if (!(info->msr & UART_MSR_RI))
-		return;
+	int ton = 0;
+	int i;
+	int midx;
 
-	isdn_tty_modem_result(RESULT_RING, info);
-	mod_timer(&info->ring_timer, jiffies + RING_TIMEOUT);
+	for (i = 0; i < ISDN_MAX_CHANNELS; i++)
+		if (USG_MODEM(dev->usage[i]))
+			if ((midx = dev->m_idx[i]) >= 0) {
+				modem_info *info = &dev->mdm.info[midx];
+				if (info->online) {
+					ton = 1;
+					if ((info->emu.pluscount == 3) &&
+					    time_after(jiffies , info->emu.lastplus + PLUSWAIT2)) {
+						info->emu.pluscount = 0;
+						info->online = 0;
+						isdn_tty_modem_result(RESULT_OK, info);
+					}
+				}
+			}
+	isdn_timer_ctrl(ISDN_TIMER_MODEMPLUS, ton);
 }
-	
-static void
-isdn_tty_modem_xmit(struct modem_info *info)
+
+/*
+ * Put a RING-message to all modem-channels who have the RI-bit set.
+ * This function is called every second via timer-interrupt from within
+ * timer-dispatcher isdn_timer_function()
+ */
+void
+isdn_tty_modem_ring(void)
 {
-	isdn_tty_senddown(info);
-	isdn_tty_tint(info);
+	int ton = 0;
+	int i;
+
+	for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
+		modem_info *info = &dev->mdm.info[i];
+		if (info->msr & UART_MSR_RI) {
+			ton = 1;
+			isdn_tty_modem_result(RESULT_RING, info);
+		}
+	}
+	isdn_timer_ctrl(ISDN_TIMER_MODEMRING, ton);
 }
 
-static void
-isdn_tty_connect_timer(unsigned long data)
+/*
+ * For all online tty's, try sending data to
+ * the lower levels.
+ */
+void
+isdn_tty_modem_xmit(void)
 {
-	struct modem_info *info = (struct modem_info *) data;
+	int ton = 1;
+	int i;
 
-	if (info->dialing) {
-		info->dialing = 0;
-		isdn_tty_modem_result(RESULT_NO_CARRIER, info);
-		isdn_tty_modem_hup(info, 1);
+	for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
+		modem_info *info = &dev->mdm.info[i];
+		if (info->online) {
+			ton = 1;
+			isdn_tty_senddown(info);
+			isdn_tty_tint(info);
+		}
 	}
+	isdn_timer_ctrl(ISDN_TIMER_MODEMXMIT, ton);
 }
 
+/*
+ * Check all channels if we have a 'no carrier' timeout.
+ * Timeout value is set by Register S7.
+ */
+void
+isdn_tty_carrier_timeout(void)
+{
+	int ton = 0;
+	int i;
+
+	for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
+		modem_info *info = &dev->mdm.info[i];
+		if (info->dialing) {
+			if (info->emu.carrierwait++ > info->emu.mdmreg[REG_WAITC]) {
+				info->dialing = 0;
+				isdn_tty_modem_result(RESULT_NO_CARRIER, info);
+				isdn_tty_modem_hup(info, 1);
+			}
+			else
+				ton = 1;
+		}
+	}
+	isdn_timer_ctrl(ISDN_TIMER_CARRIER, ton);
+}
--- diff/drivers/isdn/i4l/isdn_tty.h	2003-06-30 10:07:21.000000000 +0100
+++ source/drivers/isdn/i4l/isdn_tty.h	2004-02-23 13:56:43.000000000 +0000
@@ -1,10 +1,13 @@
-/* Linux ISDN subsystem, tty related functions
+/* $Id: isdn_tty.h,v 1.1.2.2 2004/01/12 22:37:19 keil Exp $
+ *
+ * header for Linux ISDN subsystem, tty related functions (linklevel).
  *
  * Copyright 1994-1999  by Fritz Elfert (fritz@isdn4linux.de)
  * Copyright 1995,96    by Thinking Objects Software GmbH Wuerzburg
  *
  * This software may be used and distributed according to the terms
  * of the GNU General Public License, incorporated herein by reference.
+ *
  */
 
 #include <linux/config.h>
@@ -98,31 +101,22 @@
 	((info->emu.mdmreg[REG_L2PROT] == ISDN_PROTO_L2_FAX) && \
 	 (info->emu.mdmreg[REG_L3PROT] == ISDN_PROTO_L3_FCLASS2))
 
-extern int isdn_tty_init(void);
-extern int isdn_tty_find_icall(struct isdn_slot *slot, setup_parm *setup);
+extern void isdn_tty_modem_escape(void);
+extern void isdn_tty_modem_ring(void);
+extern void isdn_tty_carrier_timeout(void);
+extern void isdn_tty_modem_xmit(void);
+extern int  isdn_tty_modem_init(void);
+extern void isdn_tty_exit(void);
+extern void isdn_tty_readmodem(void);
+extern int  isdn_tty_find_icall(int, int, setup_parm *);
 extern void isdn_tty_cleanup_xmit(modem_info *);
-extern int isdn_tty_capi_facility(capi_msg *cm); 
+extern int  isdn_tty_stat_callback(int, isdn_ctrl *);
+extern int  isdn_tty_rcv_skb(int, int, int, struct sk_buff *);
+extern int  isdn_tty_capi_facility(capi_msg *cm); 
 extern void isdn_tty_at_cout(char *, modem_info *);
 extern void isdn_tty_modem_hup(modem_info *, int);
 #ifdef CONFIG_ISDN_TTY_FAX
-extern int isdn_tty_cmd_PLUSF_FAX(char **, modem_info *);
-extern int isdn_tty_fax_command(modem_info *, isdn_ctrl *);
+extern int  isdn_tty_cmd_PLUSF_FAX(char **, modem_info *);
+extern int  isdn_tty_fax_command(modem_info *, isdn_ctrl *);
 extern void isdn_tty_fax_bitorder(modem_info *, struct sk_buff *);
 #endif
-
-extern int isdn_tty_init(void);
-extern void isdn_tty_exit(void);
-
-struct isdn_modem {
-  struct tty_driver  *tty_modem;		   /* tty-device             */
-  modem_info         info[ISDN_MAX_CHANNELS];	   /* Private data           */
-};
-
-extern struct isdn_modem isdn_mdm;
-
-static inline void
-isdn_tty_queue_tail(modem_info *info, struct sk_buff *skb, int len)
-{
-	__skb_queue_tail(&info->rpqueue, skb);
-	info->rcvcount += len;
-}
--- diff/drivers/isdn/i4l/isdn_ttyfax.c	2003-09-17 12:28:06.000000000 +0100
+++ source/drivers/isdn/i4l/isdn_ttyfax.c	2004-02-23 13:56:43.000000000 +0000
@@ -1,4 +1,6 @@
-/* Linux ISDN subsystem, tty_fax AT-command emulator
+/* $Id: isdn_ttyfax.c,v 1.1.2.2 2004/01/12 22:37:19 keil Exp $
+ *
+ * Linux ISDN subsystem, tty_fax AT-command emulator (linklevel).
  *
  * Copyright 1999    by Armin Schindler (mac@melware.de)
  * Copyright 1999    by Ralf Spachmann (mel@melware.de)
@@ -6,6 +8,7 @@
  *
  * This software may be used and distributed according to the terms
  * of the GNU General Public License, incorporated herein by reference.
+ *
  */
 
 #undef ISDN_TTY_FAX_STAT_DEBUG
@@ -16,8 +19,26 @@
 #include "isdn_tty.h"
 #include "isdn_ttyfax.h"
 
+
+static char *isdn_tty_fax_revision = "$Revision: 1.1.2.2 $";
+
 #define PARSE_ERROR1 { isdn_tty_fax_modem_result(1, info); return 1; }
 
+static char *
+isdn_getrev(const char *revision)
+{
+	char *rev;
+	char *p;
+
+	if ((p = strchr(revision, ':'))) {
+		rev = p + 2;
+		p = strchr(rev, '$');
+		*--p = 0;
+	} else
+		rev = "???";
+	return rev;
+}
+
 /*
  * Fax Class 2 Modem results
  *
@@ -53,7 +74,7 @@ isdn_tty_fax_modem_result(int code, mode
 		case 2:	/* +FCON */
 			/* Append CPN, if enabled */
 			if ((m->mdmreg[REG_CPNFCON] & BIT_CPNFCON) &&
-				(!(info->isdn_slot->usage & ISDN_USAGE_OUTGOING))) {
+				(!(dev->usage[info->isdn_channel] & ISDN_USAGE_OUTGOING))) {
 				sprintf(rs, "/%s", m->cpn);
 				isdn_tty_at_cout(rs, info);
 			}
@@ -265,7 +286,7 @@ isdn_tty_fax_bitorder(modem_info * info,
 	__u8 RightMask;
 	__u8 fBit;
 	__u8 Data;
-	u_int i;
+	int i;
 
 	if (!info->fax->bor) {
 		for (i = 0; i < skb->len; i++) {
@@ -301,9 +322,8 @@ isdn_tty_cmd_FCLASS1(char **p, modem_inf
 	static char *cmd[] =
 	{"AE", "TS", "RS", "TM", "RM", "TH", "RH"};
 	isdn_ctrl c;
-	int par;
-	struct isdn_slot *slot;
-	unsigned long flags;
+	int par, i;
+	u_long flags;
 
 	for (c.parm.aux.cmd = 0; c.parm.aux.cmd < 7; c.parm.aux.cmd++)
 		if (!strncmp(p[0], cmd[c.parm.aux.cmd], 2))
@@ -340,32 +360,46 @@ isdn_tty_cmd_FCLASS1(char **p, modem_inf
 		default:
 			PARSE_ERROR1;
 	}
+	c.command = ISDN_CMD_FAXCMD;
 #ifdef ISDN_TTY_FAX_CMD_DEBUG
 	printk(KERN_DEBUG "isdn_tty_cmd_FCLASS1 %d/%d/%d)\n",
 	       c.parm.aux.cmd, c.parm.aux.subcmd, c.parm.aux.para[0]);
 #endif
-	if (!info->isdn_slot) {
-		save_flags(flags);
-		cli();
+	if (info->isdn_driver < 0) {
 		if ((c.parm.aux.subcmd == AT_EQ_VALUE) ||
 		    (c.parm.aux.subcmd == AT_COMMAND)) {
-			restore_flags(flags);
 			PARSE_ERROR1;
 		}
+		spin_lock_irqsave(&dev->lock, flags);
 		/* get a temporary connection to the first free fax driver */
-		slot = isdn_get_free_slot(ISDN_USAGE_FAX, ISDN_PROTO_L2_FAX,
-				       ISDN_PROTO_L3_FCLASS1, -1, -1, "00");
-		if (!slot) {
-			restore_flags(flags);
+		i = isdn_get_free_channel(ISDN_USAGE_FAX, ISDN_PROTO_L2_FAX,
+					  ISDN_PROTO_L3_FCLASS1, -1, -1, "00");
+		if (i < 0) {
+			spin_unlock_irqrestore(&dev->lock, flags);
 			PARSE_ERROR1;
 		}
-		info->isdn_slot = slot;
-		isdn_slot_command(slot, ISDN_CMD_FAXCMD, &c);
-		isdn_slot_free(slot);
-		info->isdn_slot = NULL;
-		restore_flags(flags);
+		info->isdn_driver = dev->drvmap[i];
+		info->isdn_channel = dev->chanmap[i];
+		info->drv_index = i;
+		dev->m_idx[i] = info->line;
+		spin_unlock_irqrestore(&dev->lock, flags);
+		c.driver = info->isdn_driver;
+		c.arg = info->isdn_channel;
+		isdn_command(&c);
+		spin_lock_irqsave(&dev->lock, flags);
+		isdn_free_channel(info->isdn_driver, info->isdn_channel,
+				  ISDN_USAGE_FAX);
+		info->isdn_driver = -1;
+		info->isdn_channel = -1;
+		if (info->drv_index >= 0) {
+			dev->m_idx[info->drv_index] = -1;
+			info->drv_index = -1;
+		}
+		spin_unlock_irqrestore(&dev->lock, flags);
 	} else {
-		isdn_slot_command(info->isdn_slot, ISDN_CMD_FAXCMD, &c);
+		c.driver = info->isdn_driver;
+		c.arg = info->isdn_channel;
+		isdn_command(&c);
 	}
 	return 1;
 }
@@ -766,7 +800,10 @@ isdn_tty_cmd_FCLASS2(char **p, modem_inf
 			printk(KERN_DEBUG "isdn_tty: Fax FDR\n");
 #endif
 			f->code = ISDN_TTY_FAX_DR;
-			isdn_slot_command(info->isdn_slot, ISDN_CMD_FAXCMD, &cmd);
+			cmd.driver = info->isdn_driver;
+			cmd.arg = info->isdn_channel;
+			cmd.command = ISDN_CMD_FAXCMD;
+			isdn_command(&cmd);
 			if (f->phase == ISDN_FAX_PHASE_B) {
 				f->phase = ISDN_FAX_PHASE_C;
 			} else if (f->phase == ISDN_FAX_PHASE_D) {
@@ -818,7 +855,10 @@ isdn_tty_cmd_FCLASS2(char **p, modem_inf
 #endif
 		if ((f->phase == ISDN_FAX_PHASE_B) || (f->phase == ISDN_FAX_PHASE_D)) {
 			f->code = ISDN_TTY_FAX_DT;
-			isdn_slot_command(info->isdn_slot, ISDN_CMD_FAXCMD, &cmd);
+			cmd.driver = info->isdn_driver;
+			cmd.arg = info->isdn_channel;
+			cmd.command = ISDN_CMD_FAXCMD;
+			isdn_command(&cmd);
 			if (f->phase == ISDN_FAX_PHASE_D) {
 				f->phase = ISDN_FAX_PHASE_C;
 				isdn_tty_fax_modem_result(7, info);	/* CONNECT */
@@ -873,7 +913,10 @@ isdn_tty_cmd_FCLASS2(char **p, modem_inf
 				PARSE_ERROR1;
 			f->fet = par;
 			f->code = ISDN_TTY_FAX_ET;
-			isdn_slot_command(info->isdn_slot, ISDN_CMD_FAXCMD, &cmd);
+			cmd.driver = info->isdn_driver;
+			cmd.arg = info->isdn_channel;
+			cmd.command = ISDN_CMD_FAXCMD;
+			isdn_command(&cmd);
 #ifdef ISDN_TTY_FAX_STAT_DEBUG
 			printk(KERN_DEBUG "isdn_tty: Fax FET=%d\n", par);
 #endif
@@ -1043,7 +1086,8 @@ isdn_tty_cmd_FCLASS2(char **p, modem_inf
 #ifdef ISDN_TTY_FAX_STAT_DEBUG
 		printk(KERN_DEBUG "isdn_tty: FREV?\n");
 #endif
-		sprintf(rs, "\r\nRev: 1.0");
+		strcpy(rss, isdn_tty_fax_revision);
+		sprintf(rs, "\r\nRev: %s", isdn_getrev(rss));
 		isdn_tty_at_cout(rs, info);
 		return 0;
 	}
--- diff/drivers/isdn/i4l/isdn_ttyfax.h	2002-11-11 11:09:36.000000000 +0000
+++ source/drivers/isdn/i4l/isdn_ttyfax.h	2004-02-23 13:56:43.000000000 +0000
@@ -1,4 +1,6 @@
-/* Linux ISDN subsystem, tty_fax related functions
+/* $Id: isdn_ttyfax.h,v 1.1.2.2 2004/01/12 22:37:19 keil Exp $
+ *
+ * header for Linux ISDN subsystem, tty_fax related functions (linklevel).
  *
  * Copyright 1999   by Armin Schindler (mac@melware.de)
  * Copyright 1999   by Ralf Spachmann (mel@melware.de)
@@ -6,6 +8,7 @@
  *
  * This software may be used and distributed according to the terms
  * of the GNU General Public License, incorporated herein by reference.
+ *
  */
 
 
--- diff/drivers/isdn/i4l/isdn_v110.c	2002-11-11 11:09:36.000000000 +0000
+++ source/drivers/isdn/i4l/isdn_v110.c	2004-02-23 13:56:43.000000000 +0000
@@ -1,22 +1,27 @@
-/* Linux ISDN subsystem, V.110
+/* $Id: isdn_v110.c,v 1.1.2.2 2004/01/12 22:37:19 keil Exp $
+ *
+ * Linux ISDN subsystem, V.110 related functions (linklevel).
  *
  * Copyright by Thomas Pfeiffer (pfeiffer@pds.de)
  *
  * This software may be used and distributed according to the terms
  * of the GNU General Public License, incorporated herein by reference.
+ *
  */
 
 #include <linux/string.h>
 #include <linux/kernel.h>
 #include <linux/slab.h>
 #include <linux/mm.h>
+#include <linux/delay.h>
 
 #include <linux/isdn.h>
 #include "isdn_v110.h"
-#include "isdn_common.h"
 
 #undef ISDN_V110_DEBUG
 
+char *isdn_v110_revision = "$Revision: 1.1.2.2 $";
+
 #define V110_38400 255
 #define V110_19200  15
 #define V110_9600    3
@@ -82,7 +87,7 @@ FlipBits(unsigned char c, int keylen)
  * structures and returns a pointer to these.
  */
 static isdn_v110_stream *
-do_isdn_v110_open(unsigned char key, int hdrlen, int maxsize)
+isdn_v110_open(unsigned char key, int hdrlen, int maxsize)
 {
 	int i;
 	isdn_v110_stream *v;
@@ -127,8 +132,8 @@ do_isdn_v110_open(unsigned char key, int
 }
 
 /* isdn_v110_close frees private V.110 data structures */
-static void
-do_isdn_v110_close(isdn_v110_stream * v)
+void
+isdn_v110_close(isdn_v110_stream * v)
 {
 	if (v == NULL)
 		return;
@@ -510,94 +515,103 @@ buffer_full:
 	return nskb;
 }
 
-
-void
-isdn_v110_open(struct isdn_slot *slot, struct isdn_v110 *iv110)
-{	
-	isdn_v110_stream *v;
-	int hdrlen = isdn_slot_hdrlen(slot);
-	int maxsize = isdn_slot_maxbufsize(slot);
-
-	atomic_inc(&iv110->v110use);
-	switch (iv110->v110emu) {
-	case ISDN_PROTO_L2_V11096:
-		iv110->v110 = do_isdn_v110_open(V110_9600, hdrlen, maxsize);
-		break;
-	case ISDN_PROTO_L2_V11019:
-		iv110->v110 = do_isdn_v110_open(V110_19200, hdrlen, maxsize);
-		break;
-	case ISDN_PROTO_L2_V11038:
-		iv110->v110 = do_isdn_v110_open(V110_38400, hdrlen, maxsize);
-		break;
-	}
-	if ((v = iv110->v110)) {
-		while (v->SyncInit) {
-			struct sk_buff *skb = isdn_v110_sync(v);
-			if (isdn_slot_write(slot, skb) <= 0) {
-				dev_kfree_skb(skb);
-				/* Unable to send, try later */
-				break;
-			}
-			v->SyncInit--;
-			v->skbidle++;
-		}
-	} else
-		printk(KERN_WARNING "isdn_v110: Couldn't open stream\n");
-	atomic_dec(&iv110->v110use);
-}
-
-void
-isdn_v110_close(struct isdn_slot *slot, struct isdn_v110 *iv110)
-{
-	while (1) {
-		atomic_inc(&iv110->v110use);
-		if (atomic_dec_and_test(&iv110->v110use)) {
-			do_isdn_v110_close(iv110->v110);
-			iv110->v110 = NULL;
-			break;
-		}
-	}
-}
-
 int
-isdn_v110_bsent(struct isdn_slot *slot, struct isdn_v110 *iv110)
+isdn_v110_stat_callback(int idx, isdn_ctrl * c)
 {
-	isdn_v110_stream *v = iv110->v110;
-	int i, ret;
+	isdn_v110_stream *v = NULL;
+	int i;
+	int ret;
 
-	/* Keep the send-queue of the driver filled
-	 * with frames:
-	 * If number of outstanding frames < 3,
-	 * send down an Idle-Frame (or an Sync-Frame, if
-	 * v->SyncInit != 0). 
-	 */
-	atomic_inc(&iv110->v110use);
-	if (v->skbidle > 0) {
-		v->skbidle--;
-		ret = 1;
-	} else {
-		if (v->skbuser > 0)
-			v->skbuser--;
-		ret = 0;
-	}
-	for (i = v->skbuser + v->skbidle; i < 2; i++) {
-		struct sk_buff *skb;
-		if (v->SyncInit > 0)
-			skb = isdn_v110_sync(v);
-		else
-			skb = isdn_v110_idle(v);
-		if (skb) {
-			if (isdn_slot_write(slot, skb) <= 0) {
-				dev_kfree_skb(skb);
-				break;
-			} else {
-				if (v->SyncInit)
-					v->SyncInit--;
-				v->skbidle++;
+	if (idx < 0)
+		return 0;
+	switch (c->command) {
+		case ISDN_STAT_BSENT:
+                        /* Keep the send-queue of the driver filled
+			 * with frames:
+			 * If number of outstanding frames < 3,
+			 * send down an Idle-Frame (or an Sync-Frame, if
+			 * v->SyncInit != 0). 
+			 */
+			if (!(v = dev->v110[idx]))
+				return 0;
+			atomic_inc(&dev->v110use[idx]);
+			for (i=0; i * v->framelen < c->parm.length; i++) {
+				if (v->skbidle > 0) {
+					v->skbidle--;
+					ret = 1;
+				} else {
+					if (v->skbuser > 0)
+						v->skbuser--;
+					ret = 0;
+				}
+			}
+			for (i = v->skbuser + v->skbidle; i < 2; i++) {
+				struct sk_buff *skb;
+				if (v->SyncInit > 0)
+					skb = isdn_v110_sync(v);
+				else
+					skb = isdn_v110_idle(v);
+				if (skb) {
+					if (dev->drv[c->driver]->interface->writebuf_skb(c->driver, c->arg, 1, skb) <= 0) {
+						dev_kfree_skb(skb);
+						break;
+					} else {
+						if (v->SyncInit)
+							v->SyncInit--;
+						v->skbidle++;
+					}
+				} else
+					break;
+			}
+			atomic_dec(&dev->v110use[idx]);
+			return ret;
+		case ISDN_STAT_DHUP:
+		case ISDN_STAT_BHUP:
+			while (1) {
+				atomic_inc(&dev->v110use[idx]);
+				if (atomic_dec_and_test(&dev->v110use[idx])) {
+					isdn_v110_close(dev->v110[idx]);
+					dev->v110[idx] = NULL;
+					break;
+				}
+				mdelay(1);
 			}
-		} else
 			break;
+		case ISDN_STAT_BCONN:
+			if (dev->v110emu[idx] && (dev->v110[idx] == NULL)) {
+				int hdrlen = dev->drv[c->driver]->interface->hl_hdrlen;
+				int maxsize = dev->drv[c->driver]->interface->maxbufsize;
+				atomic_inc(&dev->v110use[idx]);
+				switch (dev->v110emu[idx]) {
+					case ISDN_PROTO_L2_V11096:
+						dev->v110[idx] = isdn_v110_open(V110_9600, hdrlen, maxsize);
+						break;
+					case ISDN_PROTO_L2_V11019:
+						dev->v110[idx] = isdn_v110_open(V110_19200, hdrlen, maxsize);
+						break;
+					case ISDN_PROTO_L2_V11038:
+						dev->v110[idx] = isdn_v110_open(V110_38400, hdrlen, maxsize);
+						break;
+					default:;
+				}
+				if ((v = dev->v110[idx])) {
+					while (v->SyncInit) {
+						struct sk_buff *skb = isdn_v110_sync(v);
+						if (dev->drv[c->driver]->interface->writebuf_skb(c->driver, c->arg, 1, skb) <= 0) {
+							dev_kfree_skb(skb);
+							/* Unable to send, try later */
+							break;
+						}
+						v->SyncInit--;
+						v->skbidle++;
+					}
+				} else
+					printk(KERN_WARNING "isdn_v110: Couldn't open stream for chan %d\n", idx);
+				atomic_dec(&dev->v110use[idx]);
+			}
+			break;
+		default:
+			return 0;
 	}
-	atomic_dec(&iv110->v110use);
-	return ret;
+	return 0;
 }
--- diff/drivers/isdn/i4l/isdn_v110.h	2002-11-11 11:09:36.000000000 +0000
+++ source/drivers/isdn/i4l/isdn_v110.h	2004-02-23 13:56:43.000000000 +0000
@@ -1,19 +1,16 @@
-/* Linux ISDN subsystem, V.110 related functions
+/* $Id: isdn_v110.h,v 1.1.2.2 2004/01/12 22:37:19 keil Exp $
+ *
+ * Linux ISDN subsystem, V.110 related functions (linklevel).
  *
  * Copyright by Thomas Pfeiffer (pfeiffer@pds.de)
  *
  * This software may be used and distributed according to the terms
  * of the GNU General Public License, incorporated herein by reference.
+ *
  */
 
-#ifndef ISDN_V110_H
-#define ISDN_V110_H
-
-struct isdn_v110 {
-  int               v110emu;             /* V.110 emulator-mode 0=none */
-  atomic_t          v110use;             /* Usage-Semaphore for stream */
-  isdn_v110_stream  *v110;               /* V.110 private data         */
-};
+#ifndef _isdn_v110_h_
+#define _isdn_v110_h_
 
 /* 
  * isdn_v110_encode will take raw data and encode it using V.110 
@@ -26,10 +23,7 @@ extern struct sk_buff *isdn_v110_encode(
  */
 extern struct sk_buff *isdn_v110_decode(isdn_v110_stream *, struct sk_buff *);
 
-extern void isdn_v110_open(struct isdn_slot *slot, struct isdn_v110 *iv110);
-
-extern void isdn_v110_close(struct isdn_slot *slot, struct isdn_v110 *iv110);
-
-extern int  isdn_v110_bsent(struct isdn_slot *slot, struct isdn_v110 *iv110);
+extern int isdn_v110_stat_callback(int, isdn_ctrl *);
+extern void isdn_v110_close(isdn_v110_stream * v);
 
 #endif
--- diff/drivers/isdn/i4l/isdn_x25iface.c	2003-08-20 14:16:28.000000000 +0100
+++ source/drivers/isdn/i4l/isdn_x25iface.c	2004-02-23 13:56:43.000000000 +0000
@@ -1,10 +1,10 @@
-/* * Linux ISDN subsystem, X.25 related functions
+/* $Id: isdn_x25iface.c,v 1.1.2.2 2004/01/12 22:37:19 keil Exp $
+ *
+ * Linux ISDN subsystem, X.25 related functions
  *
  * This software may be used and distributed according to the terms
  * of the GNU General Public License, incorporated herein by reference.
- */
-
-/*
+ *
  * stuff needed to support the Linux X.25 PLP code on top of devices that
  * can provide a lab_b service using the concap_proto mechanism.
  * This module supports a network interface wich provides lapb_sematics
@@ -17,6 +17,7 @@
  *
  */
 
+/* #include <linux/isdn.h> */
 #include <linux/netdevice.h>
 #include <linux/concap.h>
 #include <linux/wanrouter.h>
@@ -63,7 +64,7 @@ static struct concap_proto_ops ix25_pops
 /* error message helper function */
 static void illegal_state_warn( unsigned state, unsigned char firstbyte) 
 {
-	printk( KERN_WARNING "isdn_x25iface: firstbyte %x invalid in"
+	printk( KERN_WARNING "isdn_x25iface: firstbyte %x illegal in"
 		"current state %d\n",firstbyte, state );
 }
 
@@ -72,7 +73,7 @@ static int pdata_is_bad( ix25_pdata_t * 
 
 	if( pda  &&  pda -> magic == ISDN_X25IFACE_MAGIC ) return 0;
 	printk( KERN_WARNING
-		"isdn_x25iface_xxx: invalid pointer to proto data\n" );
+		"isdn_x25iface_xxx: illegal pointer to proto data\n" );
 	return 1;
 }
 
@@ -87,6 +88,7 @@ struct concap_proto * isdn_x25iface_prot
 		tmp -> state = WAN_UNCONFIGURED;
 		/* private data space used to hold the concap_proto data.
 		   Only to be accessed via the returned pointer */
+		spin_lock_init(&tmp->priv.lock);
 		tmp -> priv.dops       = NULL;
 		tmp -> priv.net_dev    = NULL;
 		tmp -> priv.pops       = &ix25_pops;
@@ -111,9 +113,7 @@ int isdn_x25iface_proto_close(struct con
 		return -1;
 	}
 	IX25DEBUG( "isdn_x25iface_proto_close %s \n", MY_DEVNAME(cprot -> net_dev) );
-	save_flags(flags);
-	cli();  /* avoid races with incoming events calling pops methods while
-		 cprot members are inconsistent */  
+	spin_lock_irqsave(&cprot->lock, flags);
 	cprot -> dops    = NULL;
 	cprot -> net_dev = NULL;
 	tmp = cprot -> proto_data;
@@ -122,8 +122,7 @@ int isdn_x25iface_proto_close(struct con
 	} else {
 		tmp -> state = WAN_UNCONFIGURED;
 	}
-	restore_flags(flags);
-
+	spin_unlock_irqrestore(&cprot->lock, flags);
 	return ret;
 }
 
@@ -176,14 +175,12 @@ int isdn_x25iface_proto_restart(struct c
 		isdn_x25iface_proto_close(cprot);
 		return -1;
 	}
-	save_flags(flags);
-	cli();  /* avoid races with incoming events calling pops methods while
-		 cprot members are inconsistent */  
+	spin_lock_irqsave(&cprot->lock, flags);
 	cprot -> net_dev = ndev;
 	cprot -> pops = &ix25_pops;
 	cprot -> dops = dops;
 	pda -> state = WAN_DISCONNECTED;
-	restore_flags(flags);
+	spin_unlock_irqrestore(&cprot->lock, flags);
 	return 0;
 }
 
@@ -222,8 +219,6 @@ int isdn_x25iface_connect_ind(struct con
 		printk(KERN_WARNING 
 		       "isdn_x25iface_connect_ind while unconfigured %s\n"
 		       , MY_DEVNAME(cprot->net_dev) );
-		if (skb)
-			dev_kfree_skb(skb);
 		return -1;
 	}
 	*state_p = WAN_CONNECTED;
@@ -334,7 +329,7 @@ int isdn_x25iface_xmit(struct concap_pro
 		       " options not yet supported\n");
 		break;
 	default:
-		printk(KERN_WARNING "isdn_x25iface_xmit: frame with invalid"
+		printk(KERN_WARNING "isdn_x25iface_xmit: frame with illegal"
 		       " first byte %x ignored:\n", firstbyte);
 	}
 	dev_kfree_skb(skb);
--- diff/drivers/isdn/i4l/isdn_x25iface.h	2002-11-11 11:09:36.000000000 +0000
+++ source/drivers/isdn/i4l/isdn_x25iface.h	2004-02-23 13:56:43.000000000 +0000
@@ -1,16 +1,17 @@
-/* Linux ISDN subsystem, x.25 related functions
+/* $Id: isdn_x25iface.h,v 1.1.2.2 2004/01/12 22:37:19 keil Exp $
+ *
+ * header for Linux ISDN subsystem, x.25 related functions
  *
  * This software may be used and distributed according to the terms
  * of the GNU General Public License, incorporated herein by reference.
+ *
  */
 
 #ifndef _LINUX_ISDN_X25IFACE_H
 #define _LINUX_ISDN_X25IFACE_H
 
 #define ISDN_X25IFACE_MAGIC 0x1e75a2b9
-
-#undef DEBUG_ISDN_X25
-
+/* #define DEBUG_ISDN_X25 if you want isdn_x25 debugging messages */
 #ifdef DEBUG_ISDN_X25
 #   define IX25DEBUG(fmt,args...) printk(KERN_DEBUG fmt , ## args)
 #else
@@ -25,6 +26,8 @@
 extern struct concap_proto_ops * isdn_x25iface_concap_proto_ops_pt;
 extern struct concap_proto     * isdn_x25iface_proto_new(void);
 
+
+
 #endif
 
 
--- diff/drivers/isdn/icn/Kconfig	2002-11-11 11:09:36.000000000 +0000
+++ source/drivers/isdn/icn/Kconfig	2004-02-23 13:56:43.000000000 +0000
@@ -3,7 +3,7 @@
 #
 config ISDN_DRV_ICN
 	tristate "ICN 2B and 4B support"
-	depends on ISDN && ISA
+	depends on ISDN_I4L && ISA
 	help
 	  This enables support for two kinds of ISDN-cards made by a German
 	  company called ICN.  2B is the standard version for a single ISDN
--- diff/drivers/isdn/pcbit/Kconfig	2002-11-11 11:09:36.000000000 +0000
+++ source/drivers/isdn/pcbit/Kconfig	2004-02-23 13:56:43.000000000 +0000
@@ -3,7 +3,7 @@
 #
 config ISDN_DRV_PCBIT
 	tristate "PCBIT-D support"
-	depends on ISDN && ISA
+	depends on ISDN_I4L && ISA
 	help
 	  This enables support for the PCBIT ISDN-card.  This card is
 	  manufactured in Portugal by Octal.  For running this card,
--- diff/drivers/isdn/pcbit/drv.c	2003-10-09 09:47:34.000000000 +0100
+++ source/drivers/isdn/pcbit/drv.c	2004-02-23 13:56:43.000000000 +0000
@@ -84,6 +84,7 @@ int pcbit_init_dev(int board, int mem_ba
 	dev_pcbit[board] = dev;
 	memset(dev, 0, sizeof(struct pcbit_dev));
 	init_waitqueue_head(&dev->set_running_wq);
+	spin_lock_init(&dev->lock);
 
 	if (mem_base >= 0xA0000 && mem_base <= 0xFFFFF ) {
 		dev->ph_mem = mem_base;
--- diff/drivers/isdn/pcbit/edss1.c	2002-10-16 04:27:13.000000000 +0100
+++ source/drivers/isdn/pcbit/edss1.c	2004-02-23 13:56:43.000000000 +0000
@@ -278,9 +278,7 @@ void pcbit_fsm_event(struct pcbit_dev *d
 	struct fsm_timer_entry *tentry;
 	unsigned long flags;
 
-	save_flags(flags);
-	cli();
-
+	spin_lock_irqsave(&dev->lock, flags);
 
         for (action = fsm_table; action->init != 0xff; action++)
                 if (action->init == chan->fsm_state && action->event == event)
@@ -288,9 +286,9 @@ void pcbit_fsm_event(struct pcbit_dev *d
   
 	if (action->init == 0xff) {
 		
+		spin_unlock_irqrestore(&dev->lock, flags);
 		printk(KERN_DEBUG "fsm error: event %x on state %x\n", 
                        event, chan->fsm_state);
-		restore_flags(flags);
 		return;
 	}
 
@@ -315,7 +313,7 @@ void pcbit_fsm_event(struct pcbit_dev *d
                 add_timer(&chan->fsm_timer);
         }
 
-	restore_flags(flags);
+	spin_unlock_irqrestore(&dev->lock, flags);
 
 	if (action->callb)
 		action->callb(dev, chan, data);
--- diff/drivers/isdn/pcbit/layer2.c	2003-05-21 11:50:15.000000000 +0100
+++ source/drivers/isdn/pcbit/layer2.c	2004-02-23 13:56:43.000000000 +0000
@@ -121,18 +121,17 @@ pcbit_l2_write(struct pcbit_dev *dev, ul
 
 	frame->next = NULL;
 
-	save_flags(flags);
-	cli();
+	spin_lock_irqsave(&dev->lock, flags);
 
 	if (dev->write_queue == NULL) {
 		dev->write_queue = frame;
-		restore_flags(flags);
+		spin_unlock_irqrestore(&dev->lock, flags);
 		pcbit_transmit(dev);
 	} else {
 		for (ptr = dev->write_queue; ptr->next; ptr = ptr->next);
 		ptr->next = frame;
 
-		restore_flags(flags);
+		spin_unlock_irqrestore(&dev->lock, flags);
 	}
 	return 0;
 }
@@ -174,15 +173,14 @@ pcbit_transmit(struct pcbit_dev *dev)
 
 	unacked = (dev->send_seq + (8 - dev->unack_seq)) & 0x07;
 
-	save_flags(flags);
-	cli();
+	spin_lock_irqsave(&dev->lock, flags);
 
 	if (dev->free > 16 && dev->write_queue && unacked < 7) {
 
 		if (!dev->w_busy)
 			dev->w_busy = 1;
 		else {
-			restore_flags(flags);
+			spin_unlock_irqrestore(&dev->lock, flags);
 			return;
 		}
 
@@ -190,7 +188,7 @@ pcbit_transmit(struct pcbit_dev *dev)
 		frame = dev->write_queue;
 		free = dev->free;
 
-		restore_flags(flags);
+		spin_unlock_irqrestore(&dev->lock, flags);
 
 		if (frame->copied == 0) {
 
@@ -271,9 +269,7 @@ pcbit_transmit(struct pcbit_dev *dev)
 		dev->free -= flen;
 		pcbit_tx_update(dev, flen);
 
-		save_flags(flags);
-		cli();
-
+		spin_lock_irqsave(&dev->lock, flags);
 
 		if (frame->skb == NULL || frame->copied == frame->skb->len) {
 
@@ -286,9 +282,9 @@ pcbit_transmit(struct pcbit_dev *dev)
 			kfree(frame);
 		}
 		dev->w_busy = 0;
-		restore_flags(flags);
+		spin_unlock_irqrestore(&dev->lock, flags);
 	} else {
-		restore_flags(flags);
+		spin_unlock_irqrestore(&dev->lock, flags);
 #ifdef DEBUG
 		printk(KERN_DEBUG "unacked %d free %d write_queue %s\n",
 		     unacked, dev->free, dev->write_queue ? "not empty" :
@@ -309,12 +305,11 @@ pcbit_deliver(void *data)
 	unsigned long flags, msg;
 	struct pcbit_dev *dev = (struct pcbit_dev *) data;
 
-	save_flags(flags);
-	cli();
+	spin_lock_irqsave(&dev->lock, flags);
 
 	while ((frame = dev->read_queue)) {
 		dev->read_queue = frame->next;
-		restore_flags(flags);
+		spin_unlock_irqrestore(&dev->lock, flags);
 
 		SET_MSG_CPU(msg, 0);
 		SET_MSG_PROC(msg, 0);
@@ -331,11 +326,10 @@ pcbit_deliver(void *data)
 
 		kfree(frame);
 
-		save_flags(flags);
-		cli();
+		spin_lock_irqsave(&dev->lock, flags);
 	}
 
-	restore_flags(flags);
+	spin_unlock_irqrestore(&dev->lock, flags);
 }
 
 /*
@@ -460,12 +454,9 @@ pcbit_receive(struct pcbit_dev *dev)
 	memcpy_frompcbit(dev, skb_put(frame->skb, tt), tt);
 
 	frame->copied += tt;
-
+	spin_lock_irqsave(&dev->lock, flags);
 	if (frame->copied == frame->hdr_len + frame->dt_len) {
 
-		save_flags(flags);
-		cli();
-
 		if (type1) {
 			dev->read_frame = NULL;
 		}
@@ -476,14 +467,10 @@ pcbit_receive(struct pcbit_dev *dev)
 		} else
 			dev->read_queue = frame;
 
-		restore_flags(flags);
-
 	} else {
-		save_flags(flags);
-		cli();
 		dev->read_frame = frame;
-		restore_flags(flags);
 	}
+	spin_unlock_irqrestore(&dev->lock, flags);
 }
 
 /*
--- diff/drivers/isdn/pcbit/pcbit.h	2002-10-16 04:27:15.000000000 +0100
+++ source/drivers/isdn/pcbit/pcbit.h	2004-02-23 13:56:43.000000000 +0000
@@ -51,7 +51,7 @@ struct pcbit_dev {
 	unsigned int id;
 	unsigned int interrupt;			/* set during interrupt 
 						   processing */
-	
+	spinlock_t lock;
 	/* isdn4linux */
 
 	struct msn_entry * msn_list;		/* ISDN address list */
--- diff/drivers/isdn/sc/Kconfig	2003-09-30 15:46:14.000000000 +0100
+++ source/drivers/isdn/sc/Kconfig	2004-02-23 13:56:43.000000000 +0000
@@ -3,7 +3,7 @@
 #
 config ISDN_DRV_SC
 	tristate "Spellcaster support"
-	depends on ISDN && ISA
+	depends on ISDN_I4L && ISA
 	help
 	  This enables support for the Spellcaster BRI ISDN boards.  This
 	  driver currently builds only in a modularized version.
--- diff/drivers/isdn/sc/command.c	2003-09-17 12:28:06.000000000 +0100
+++ source/drivers/isdn/sc/command.c	2004-02-23 13:56:43.000000000 +0000
@@ -32,7 +32,7 @@ int setl3(int card, unsigned long arg);
 int acceptb(int card, unsigned long channel);
 
 extern int cinst;
-extern board *adapter[];
+extern board *sc_adapter[];
 
 extern int sc_ioctl(int, scs_ioctl *);
 extern int setup_buffers(int, int, unsigned int);
@@ -84,7 +84,7 @@ int get_card_from_id(int driver)
 	int i;
 
 	for(i = 0 ; i < cinst ; i++) {
-		if(adapter[i]->driverId == driver)
+		if(sc_adapter[i]->driverId == driver)
 			return i;
 	}
 	return -ENODEV;
@@ -105,7 +105,7 @@ int command(isdn_ctrl *cmd)
 	}
 
 	pr_debug("%s: Received %s command from Link Layer\n",
-		adapter[card]->devicename, commands[cmd->command]);
+		sc_adapter[card]->devicename, commands[cmd->command]);
 
 	/*
 	 * Dispatch the command
@@ -120,7 +120,7 @@ int command(isdn_ctrl *cmd)
 		if (copy_from_user(&ioc, (scs_ioctl *)cmdptr,
 				   sizeof(scs_ioctl))) {
 			pr_debug("%s: Failed to verify user space 0x%x\n",
-				adapter[card]->devicename, cmdptr);
+				sc_adapter[card]->devicename, cmdptr);
 			return -EFAULT;
 		}
 		return sc_ioctl(card, &ioc);
@@ -163,8 +163,8 @@ int loopback(int card) 
 		return -ENODEV;
 	}
 
-	pr_debug("%s: Sending loopback message\n", adapter[card]->devicename);
-	
+	pr_debug("%s: Sending loopback message\n",
+		sc_adapter[card]->devicename);
 
 	/*
 	 * Send the loopback message to confirm that memory transfer is
@@ -181,17 +181,17 @@ int loopback(int card) 
 
 	if (!status) {
 		pr_debug("%s: Loopback message successfully sent\n",
-			adapter[card]->devicename);
+			sc_adapter[card]->devicename);
 		if(strcmp(rspmsg.msg_data.byte_array, testmsg)) {
 			pr_debug("%s: Loopback return != sent\n",
-				adapter[card]->devicename);
+				sc_adapter[card]->devicename);
 			return -EIO;
 		}
 		return 0;
 	}
 	else {
 		pr_debug("%s: Send loopback message failed\n",
-			adapter[card]->devicename);
+			sc_adapter[card]->devicename);
 		return -EIO;
 	}
 
@@ -216,7 +216,7 @@ int startproc(int card) 
 			  cmReqClass0,
 			  cmReqStartProc,
 			  0,0,0);
-	pr_debug("%s: Sent startProc\n", adapter[card]->devicename);
+	pr_debug("%s: Sent startProc\n", sc_adapter[card]->devicename);
 	
 	return status;
 }
@@ -253,7 +253,7 @@ int dial(int card, unsigned long channel
 				(unsigned int *) Phone);
 
 	pr_debug("%s: Dialing %s on channel %d\n",
-		adapter[card]->devicename, Phone, channel+1);
+		sc_adapter[card]->devicename, Phone, channel+1);
 	
 	return status;
 }
@@ -275,7 +275,7 @@ int answer(int card, unsigned long chann
 
 	indicate_status(card, ISDN_STAT_BCONN,channel,NULL);
 	pr_debug("%s: Answered incoming call on channel %s\n",
-		adapter[card]->devicename, channel+1);
+		sc_adapter[card]->devicename, channel+1);
 	return 0;
 }
 
@@ -298,7 +298,7 @@ int hangup(int card, unsigned long chann
 						 0,
 						 NULL);
 	pr_debug("%s: Sent HANGUP message to channel %d\n",
-		adapter[card]->devicename, channel+1);
+		sc_adapter[card]->devicename, channel+1);
 	return status;
 }
 
@@ -316,15 +316,16 @@ int setl2(int card, unsigned long arg) 
 	}
 	protocol = arg >> 8;
 	channel = arg & 0xff;
-	adapter[card]->channel[channel].l2_proto = protocol;
+	sc_adapter[card]->channel[channel].l2_proto = protocol;
 	pr_debug("%s: Level 2 protocol for channel %d set to %s from %d\n",
-		adapter[card]->devicename, channel+1,l2protos[adapter[card]->channel[channel].l2_proto],protocol);
+		sc_adapter[card]->devicename, channel+1,
+		l2protos[sc_adapter[card]->channel[channel].l2_proto],protocol);
 
 	/*
 	 * check that the adapter is also set to the correct protocol
 	 */
 	pr_debug("%s: Sending GetFrameFormat for channel %d\n",
-		adapter[card]->devicename, channel+1);
+		sc_adapter[card]->devicename, channel+1);
 	status = sendmessage(card, CEPID, ceReqTypeCall,
  				ceReqClass0,
  				ceReqCallGetFrameFormat,
@@ -348,9 +349,9 @@ int setl3(int card, unsigned long channe
 		return -ENODEV;
 	}
 
-	adapter[card]->channel[channel].l3_proto = protocol;
+	sc_adapter[card]->channel[channel].l3_proto = protocol;
 	pr_debug("%s: Level 3 protocol for channel %d set to %s\n",
-		adapter[card]->devicename, channel+1, l3protos[protocol]);
+		sc_adapter[card]->devicename, channel+1, l3protos[protocol]);
 	return 0;
 }
 
@@ -368,7 +369,7 @@ int acceptb(int card, unsigned long chan
 	}
 
 	pr_debug("%s: B-Channel connection accepted on channel %d\n",
-		adapter[card]->devicename, channel+1);
+		sc_adapter[card]->devicename, channel+1);
 	indicate_status(card, ISDN_STAT_BCONN, channel, NULL);
 	return 0;
 }
@@ -380,10 +381,10 @@ int clreaz(int card, unsigned long arg)
 		return -ENODEV;
 	}
 
-	strcpy(adapter[card]->channel[arg].eazlist, "");
-	adapter[card]->channel[arg].eazclear = 1;
+	strcpy(sc_adapter[card]->channel[arg].eazlist, "");
+	sc_adapter[card]->channel[arg].eazclear = 1;
 	pr_debug("%s: EAZ List cleared for channel %d\n",
-		adapter[card]->devicename, arg+1);
+		sc_adapter[card]->devicename, arg+1);
 	return 0;
 }
 
@@ -394,11 +395,11 @@ int seteaz(int card, unsigned long arg, 
 		return -ENODEV;
 	}
 
-	strcpy(adapter[card]->channel[arg].eazlist, num);
-	adapter[card]->channel[arg].eazclear = 0;
+	strcpy(sc_adapter[card]->channel[arg].eazlist, num);
+	sc_adapter[card]->channel[arg].eazclear = 0;
 	pr_debug("%s: EAZ list for channel %d set to: %s\n",
-		adapter[card]->devicename, arg+1,
-		adapter[card]->channel[arg].eazlist);
+		sc_adapter[card]->devicename, arg+1,
+		sc_adapter[card]->channel[arg].eazlist);
 	return 0;
 }
 
@@ -413,28 +414,28 @@ int reset(int card)
 
 	indicate_status(card, ISDN_STAT_STOP, 0, NULL);
 
-	if(adapter[card]->EngineUp) {
-		del_timer(&adapter[card]->stat_timer);	
+	if(sc_adapter[card]->EngineUp) {
+		del_timer(&sc_adapter[card]->stat_timer);
 	}
 
-	adapter[card]->EngineUp = 0;
+	sc_adapter[card]->EngineUp = 0;
 
-	spin_lock_irqsave(&adapter[card]->lock, flags);
-	init_timer(&adapter[card]->reset_timer);
-	adapter[card]->reset_timer.function = check_reset;
-	adapter[card]->reset_timer.data = card;
-	adapter[card]->reset_timer.expires = jiffies + CHECKRESET_TIME;
-	add_timer(&adapter[card]->reset_timer);
-	spin_unlock_irqrestore(&adapter[card]->lock, flags);
+	spin_lock_irqsave(&sc_adapter[card]->lock, flags);
+	init_timer(&sc_adapter[card]->reset_timer);
+	sc_adapter[card]->reset_timer.function = check_reset;
+	sc_adapter[card]->reset_timer.data = card;
+	sc_adapter[card]->reset_timer.expires = jiffies + CHECKRESET_TIME;
+	add_timer(&sc_adapter[card]->reset_timer);
+	spin_unlock_irqrestore(&sc_adapter[card]->lock, flags);
 
-	outb(0x1,adapter[card]->ioport[SFT_RESET]); 
+	outb(0x1,sc_adapter[card]->ioport[SFT_RESET]);
 
-	pr_debug("%s: Adapter Reset\n", adapter[card]->devicename);
+	pr_debug("%s: Adapter Reset\n", sc_adapter[card]->devicename);
 	return 0;
 }
 
 void flushreadfifo (int card)
 {
-	while(inb(adapter[card]->ioport[FIFO_STATUS]) & RF_HAS_DATA)
-		inb(adapter[card]->ioport[FIFO_READ]);
+	while(inb(sc_adapter[card]->ioport[FIFO_STATUS]) & RF_HAS_DATA)
+		inb(sc_adapter[card]->ioport[FIFO_READ]);
 }
--- diff/drivers/isdn/sc/event.c	2002-10-16 04:28:24.000000000 +0100
+++ source/drivers/isdn/sc/event.c	2004-02-23 13:56:43.000000000 +0000
@@ -21,7 +21,7 @@
 #include "card.h"
 
 extern int cinst;
-extern board *adapter[];
+extern board *sc_adapter[];
 
 #ifdef DEBUG
 static char *events[] = { "ISDN_STAT_STAVAIL",
@@ -46,9 +46,9 @@ int indicate_status(int card, int event,
 	isdn_ctrl cmd;
 
 	pr_debug("%s: Indicating event %s on Channel %d\n",
-		adapter[card]->devicename, events[event-256], Channel);
+		sc_adapter[card]->devicename, events[event-256], Channel);
 	if (Data != NULL){
-		pr_debug("%s: Event data: %s\n", adapter[card]->devicename,
+		pr_debug("%s: Event data: %s\n", sc_adapter[card]->devicename,
 			Data);
 		switch (event) {
 			case ISDN_STAT_BSENT:
@@ -63,7 +63,7 @@ int indicate_status(int card, int event,
 	}
 
 	cmd.command = event;
-	cmd.driver = adapter[card]->driverId;
+	cmd.driver = sc_adapter[card]->driverId;
 	cmd.arg = Channel;
-	return adapter[card]->card->statcallb(&cmd);
+	return sc_adapter[card]->card->statcallb(&cmd);
 }
--- diff/drivers/isdn/sc/hardware.h	2002-10-16 04:29:04.000000000 +0100
+++ source/drivers/isdn/sc/hardware.h	2004-02-23 13:56:43.000000000 +0000
@@ -108,6 +108,6 @@
 #define milliseconds(x)	(x/(1000/HZ))
 
 /* Determine if a channel number is valid for the adapter */
-#define IS_VALID_CHANNEL(y,x)	((x>0) && (x <= adapter[y]->channels))
+#define IS_VALID_CHANNEL(y,x)	((x>0) && (x <= sc_adapter[y]->channels))
 
 #endif
--- diff/drivers/isdn/sc/init.c	2003-09-17 12:28:06.000000000 +0100
+++ source/drivers/isdn/sc/init.c	2004-02-23 13:56:43.000000000 +0000
@@ -19,7 +19,7 @@ MODULE_PARM(irq, "1-" __MODULE_STRING(MA
 MODULE_PARM(ram, "1-" __MODULE_STRING(MAX_CARDS) "i");
 MODULE_PARM(do_reset, "i");
 
-board *adapter[MAX_CARDS];
+board *sc_adapter[MAX_CARDS];
 int cinst;
 
 static char devname[] = "scX";
@@ -305,78 +305,84 @@ static int __init sc_init(void)
 		/*
 		 * Allocate the board structure
 		 */
-		adapter[cinst] = kmalloc(sizeof(board), GFP_KERNEL);
-		if (adapter[cinst] == NULL) {
+		sc_adapter[cinst] = kmalloc(sizeof(board), GFP_KERNEL);
+		if (sc_adapter[cinst] == NULL) {
 			/*
 			 * Oops, can't alloc memory for the board
 			 */
 			kfree(interface);
 			continue;
 		}
-		memset(adapter[cinst], 0, sizeof(board));
-		spin_lock_init(&adapter[cinst]->lock);
+		memset(sc_adapter[cinst], 0, sizeof(board));
+		spin_lock_init(&sc_adapter[cinst]->lock);
 
 		if(!register_isdn(interface)) {
 			/*
 			 * Oops, couldn't register for some reason
 			 */
 			kfree(interface);
-			kfree(adapter[cinst]);
+			kfree(sc_adapter[cinst]);
 			continue;
 		}
 
-		adapter[cinst]->card = interface;
-		adapter[cinst]->driverId = interface->channels;
-		strcpy(adapter[cinst]->devicename, interface->id);
-		adapter[cinst]->nChannels = channels;
-		adapter[cinst]->ramsize = memsize;
-		adapter[cinst]->shmem_magic = magic;
-		adapter[cinst]->shmem_pgport = pgport;
-		adapter[cinst]->StartOnReset = 1;
+		sc_adapter[cinst]->card = interface;
+		sc_adapter[cinst]->driverId = interface->channels;
+		strcpy(sc_adapter[cinst]->devicename, interface->id);
+		sc_adapter[cinst]->nChannels = channels;
+		sc_adapter[cinst]->ramsize = memsize;
+		sc_adapter[cinst]->shmem_magic = magic;
+		sc_adapter[cinst]->shmem_pgport = pgport;
+		sc_adapter[cinst]->StartOnReset = 1;
 
 		/*
 		 * Allocate channels status structures
 		 */
-		adapter[cinst]->channel = kmalloc(sizeof(bchan) * channels, GFP_KERNEL);
-		if (adapter[cinst]->channel == NULL) {
+		sc_adapter[cinst]->channel = kmalloc(sizeof(bchan) * channels, GFP_KERNEL);
+		if (sc_adapter[cinst]->channel == NULL) {
 			/*
 			 * Oops, can't alloc memory for the channels
 			 */
 			indicate_status(cinst, ISDN_STAT_UNLOAD, 0, NULL);	/* Fix me */
 			kfree(interface);
-			kfree(adapter[cinst]);
+			kfree(sc_adapter[cinst]);
 			continue;
 		}
-		memset(adapter[cinst]->channel, 0, sizeof(bchan) * channels);
+		memset(sc_adapter[cinst]->channel, 0, sizeof(bchan) * channels);
 
 		/*
 		 * Lock down the hardware resources
 		 */
-		adapter[cinst]->interrupt = irq[b];
-		if (request_irq(adapter[cinst]->interrupt, interrupt_handler, SA_INTERRUPT, 
-			interface->id, NULL))
+		sc_adapter[cinst]->interrupt = irq[b];
+		if (request_irq(sc_adapter[cinst]->interrupt, interrupt_handler,
+				SA_INTERRUPT, interface->id, NULL))
 		{
-			kfree(adapter[cinst]->channel);
+			kfree(sc_adapter[cinst]->channel);
 			indicate_status(cinst, ISDN_STAT_UNLOAD, 0, NULL);	/* Fix me */
 			kfree(interface);
-			kfree(adapter[cinst]);
+			kfree(sc_adapter[cinst]);
 			continue;
 			
 		}
-		adapter[cinst]->iobase = io[b];
+		sc_adapter[cinst]->iobase = io[b];
 		for(i = 0 ; i < MAX_IO_REGS - 1 ; i++) {
-			adapter[cinst]->ioport[i] = io[b] + i * 0x400;
-			request_region(adapter[cinst]->ioport[i], 1, interface->id);
-			pr_debug("Requesting I/O Port %#x\n", adapter[cinst]->ioport[i]);
-		}
-		adapter[cinst]->ioport[IRQ_SELECT] = io[b] + 0x2;
-		request_region(adapter[cinst]->ioport[IRQ_SELECT], 1, interface->id);
-		pr_debug("Requesting I/O Port %#x\n", adapter[cinst]->ioport[IRQ_SELECT]);
-		adapter[cinst]->rambase = ram[b];
-		request_region(adapter[cinst]->rambase, SRAM_PAGESIZE, interface->id);
+			sc_adapter[cinst]->ioport[i] = io[b] + i * 0x400;
+			request_region(sc_adapter[cinst]->ioport[i], 1,
+					interface->id);
+			pr_debug("Requesting I/O Port %#x\n",
+				sc_adapter[cinst]->ioport[i]);
+		}
+		sc_adapter[cinst]->ioport[IRQ_SELECT] = io[b] + 0x2;
+		request_region(sc_adapter[cinst]->ioport[IRQ_SELECT], 1,
+				interface->id);
+		pr_debug("Requesting I/O Port %#x\n",
+				sc_adapter[cinst]->ioport[IRQ_SELECT]);
+		sc_adapter[cinst]->rambase = ram[b];
+		request_region(sc_adapter[cinst]->rambase, SRAM_PAGESIZE,
+				interface->id);
 
 		pr_info("  %s (%d) - %s %d channels IRQ %d, I/O Base 0x%x, RAM Base 0x%lx\n", 
-			adapter[cinst]->devicename, adapter[cinst]->driverId, 
+			sc_adapter[cinst]->devicename,
+			sc_adapter[cinst]->driverId,
 			boardname[model], channels, irq[b], io[b], ram[b]);
 		
 		/*
@@ -401,8 +407,8 @@ static void __exit sc_exit(void)
 		/*
 		 * kill the timers
 		 */
-		del_timer(&(adapter[i]->reset_timer));
-		del_timer(&(adapter[i]->stat_timer));
+		del_timer(&(sc_adapter[i]->reset_timer));
+		del_timer(&(sc_adapter[i]->stat_timer));
 
 		/*
 		 * Tell I4L we're toast
@@ -413,34 +419,36 @@ static void __exit sc_exit(void)
 		/*
 		 * Release shared RAM
 		 */
-		release_region(adapter[i]->rambase, SRAM_PAGESIZE);
+		release_region(sc_adapter[i]->rambase, SRAM_PAGESIZE);
 
 		/*
 		 * Release the IRQ
 		 */
-		FREE_IRQ(adapter[i]->interrupt, NULL);
+		FREE_IRQ(sc_adapter[i]->interrupt, NULL);
 
 		/*
 		 * Reset for a clean start
 		 */
-		outb(0xFF, adapter[i]->ioport[SFT_RESET]);
+		outb(0xFF, sc_adapter[i]->ioport[SFT_RESET]);
 
 		/*
 		 * Release the I/O Port regions
 		 */
 		for(j = 0 ; j < MAX_IO_REGS - 1; j++) {
-			release_region(adapter[i]->ioport[j], 1);
-			pr_debug("Releasing I/O Port %#x\n", adapter[i]->ioport[j]);
-		}
-		release_region(adapter[i]->ioport[IRQ_SELECT], 1);
-		pr_debug("Releasing I/O Port %#x\n", adapter[i]->ioport[IRQ_SELECT]);
+			release_region(sc_adapter[i]->ioport[j], 1);
+			pr_debug("Releasing I/O Port %#x\n",
+				sc_adapter[i]->ioport[j]);
+		}
+		release_region(sc_adapter[i]->ioport[IRQ_SELECT], 1);
+		pr_debug("Releasing I/O Port %#x\n",
+			sc_adapter[i]->ioport[IRQ_SELECT]);
 
 		/*
 		 * Release any memory we alloced
 		 */
-		kfree(adapter[i]->channel);
-		kfree(adapter[i]->card);
-		kfree(adapter[i]);
+		kfree(sc_adapter[i]->channel);
+		kfree(sc_adapter[i]->card);
+		kfree(sc_adapter[i]);
 	}
 	pr_info("SpellCaster ISA ISDN Adapter Driver Unloaded.\n");
 }
--- diff/drivers/isdn/sc/interrupt.c	2003-05-21 11:50:15.000000000 +0100
+++ source/drivers/isdn/sc/interrupt.c	2004-02-23 13:56:43.000000000 +0000
@@ -29,14 +29,14 @@ extern int sendmessage(int, unsigned int
 extern void rcvpkt(int, RspMessage *);
 
 extern int cinst;
-extern board *adapter[];
+extern board *sc_adapter[];
 
 int get_card_from_irq(int irq)
 {
 	int i;
 
 	for(i = 0 ; i < cinst ; i++) {
-		if(adapter[i]->interrupt == irq)
+		if(sc_adapter[i]->interrupt == irq)
 			return i;
 	}
 	return -1;
@@ -59,7 +59,8 @@ irqreturn_t interrupt_handler(int interr
 		return IRQ_NONE;
 	}
 
-	pr_debug("%s: Entered Interrupt handler\n", adapter[card]->devicename);
+	pr_debug("%s: Entered Interrupt handler\n",
+			sc_adapter[card]->devicename);
 	
  	/*
 	 * Pull all of the waiting messages off the response queue
@@ -69,8 +70,9 @@ irqreturn_t interrupt_handler(int interr
 		 * Push the message to the adapter structure for
 		 * send_and_receive to snoop
 		 */
-		if(adapter[card]->want_async_messages)
-			memcpy(&(adapter[card]->async_msg), &rcvmsg, sizeof(RspMessage));
+		if(sc_adapter[card]->want_async_messages)
+			memcpy(&(sc_adapter[card]->async_msg),
+					&rcvmsg, sizeof(RspMessage));
 
 		channel = (unsigned int) rcvmsg.phy_link_no;
 		
@@ -79,7 +81,8 @@ irqreturn_t interrupt_handler(int interr
 		 */
 		if(IS_CM_MESSAGE(rcvmsg, 0, 0, Invalid)) {
 			pr_debug("%s: Invalid request Message, rsp_status = %d\n", 
-				adapter[card]->devicename, rcvmsg.rsp_status);
+				sc_adapter[card]->devicename,
+				rcvmsg.rsp_status);
 			break;	
 		}
 		
@@ -89,7 +92,7 @@ irqreturn_t interrupt_handler(int interr
 		if (IS_CE_MESSAGE(rcvmsg, Lnk, 1, Read))
 		{
 			pr_debug("%s: Received packet 0x%x bytes long at 0x%x\n",
-						adapter[card]->devicename,
+						sc_adapter[card]->devicename,
 						rcvmsg.msg_data.response.msg_len,
 						rcvmsg.msg_data.response.buff_offset);
 			rcvpkt(card, &rcvmsg);
@@ -101,9 +104,10 @@ irqreturn_t interrupt_handler(int interr
 		 * Handle a write acknoledgement
 		 */
 		if(IS_CE_MESSAGE(rcvmsg, Lnk, 1, Write)) {
-			pr_debug("%s: Packet Send ACK on channel %d\n", adapter[card]->devicename,
+			pr_debug("%s: Packet Send ACK on channel %d\n",
+				sc_adapter[card]->devicename,
 				rcvmsg.phy_link_no);
-			adapter[card]->channel[rcvmsg.phy_link_no-1].free_sendbufs++;
+			sc_adapter[card]->channel[rcvmsg.phy_link_no-1].free_sendbufs++;
 			continue;
 		}
 
@@ -115,7 +119,7 @@ irqreturn_t interrupt_handler(int interr
 			unsigned int callid;
 			setup_parm setup;	
 			pr_debug("%s: Connect message: line %d: status %d: cause 0x%x\n",
-						adapter[card]->devicename,
+						sc_adapter[card]->devicename,
 						rcvmsg.phy_link_no,
 						rcvmsg.rsp_status,
 						rcvmsg.msg_data.byte_array[2]);
@@ -123,16 +127,19 @@ irqreturn_t interrupt_handler(int interr
 			memcpy(&callid,rcvmsg.msg_data.byte_array,sizeof(int));
 			if(callid>=0x8000 && callid<=0xFFFF)
 			{		
-				pr_debug("%s: Got Dial-Out Rsp\n", adapter[card]->devicename);	
+				pr_debug("%s: Got Dial-Out Rsp\n",
+					sc_adapter[card]->devicename);
 				indicate_status(card, ISDN_STAT_DCONN,
 						(unsigned long)rcvmsg.phy_link_no-1,NULL);
 				
 			}
 			else if(callid>=0x0000 && callid<=0x7FFF)
 			{
-				pr_debug("%s: Got Incoming Call\n", adapter[card]->devicename);	
+				pr_debug("%s: Got Incoming Call\n",
+						sc_adapter[card]->devicename);
 				strcpy(setup.phone,&(rcvmsg.msg_data.byte_array[4]));
-				strcpy(setup.eazmsn,adapter[card]->channel[rcvmsg.phy_link_no-1].dn);
+				strcpy(setup.eazmsn,
+					sc_adapter[card]->channel[rcvmsg.phy_link_no-1].dn);
 				setup.si1 = 7;
 				setup.si2 = 0;
 				setup.plan = 0;
@@ -150,7 +157,7 @@ irqreturn_t interrupt_handler(int interr
 		if (IS_CE_MESSAGE(rcvmsg, Phy, 1, Disconnect)) 
 		{
 			pr_debug("%s: disconnect message: line %d: status %d: cause 0x%x\n",
-						adapter[card]->devicename,
+						sc_adapter[card]->devicename,
 						rcvmsg.phy_link_no,
 						rcvmsg.rsp_status,
 					 	rcvmsg.msg_data.byte_array[2]);
@@ -165,15 +172,16 @@ irqreturn_t interrupt_handler(int interr
 		 * Handle a startProc engine up message
 		 */
 		if (IS_CM_MESSAGE(rcvmsg, 5, 0, MiscEngineUp)) {
-			pr_debug("%s: Received EngineUp message\n", adapter[card]->devicename);
-			adapter[card]->EngineUp = 1;
+			pr_debug("%s: Received EngineUp message\n",
+				sc_adapter[card]->devicename);
+			sc_adapter[card]->EngineUp = 1;
 			sendmessage(card, CEPID,ceReqTypeCall,ceReqClass0,ceReqCallGetMyNumber,1,0,NULL);
 			sendmessage(card, CEPID,ceReqTypeCall,ceReqClass0,ceReqCallGetMyNumber,2,0,NULL);
-			init_timer(&adapter[card]->stat_timer);
-			adapter[card]->stat_timer.function = check_phystat;
-			adapter[card]->stat_timer.data = card;
-			adapter[card]->stat_timer.expires = jiffies + CHECKSTAT_TIME;
-			add_timer(&adapter[card]->stat_timer);
+			init_timer(&sc_adapter[card]->stat_timer);
+			sc_adapter[card]->stat_timer.function = check_phystat;
+			sc_adapter[card]->stat_timer.data = card;
+			sc_adapter[card]->stat_timer.expires = jiffies + CHECKSTAT_TIME;
+			add_timer(&sc_adapter[card]->stat_timer);
 			continue;
 		}
 
@@ -181,7 +189,8 @@ irqreturn_t interrupt_handler(int interr
 		 * Start proc response
 		 */
 		if (IS_CM_MESSAGE(rcvmsg, 2, 0, StartProc)) {
-			pr_debug("%s: StartProc Response Status %d\n", adapter[card]->devicename,
+			pr_debug("%s: StartProc Response Status %d\n",
+				sc_adapter[card]->devicename,
 				rcvmsg.rsp_status);
 			continue;
 		}
@@ -190,7 +199,7 @@ irqreturn_t interrupt_handler(int interr
 		 * Handle a GetMyNumber Rsp
 		 */
 		if (IS_CE_MESSAGE(rcvmsg,Call,0,GetMyNumber)){
-			strcpy(adapter[card]->channel[rcvmsg.phy_link_no-1].dn,rcvmsg.msg_data.byte_array);
+			strcpy(sc_adapter[card]->channel[rcvmsg.phy_link_no-1].dn,rcvmsg.msg_data.byte_array);
 			continue;
 		}
 			
@@ -206,9 +215,10 @@ irqreturn_t interrupt_handler(int interr
 			b1stat = (unsigned int) rcvmsg.msg_data.byte_array[0];
 			b2stat = (unsigned int) rcvmsg.msg_data.byte_array[1];
 
-			adapter[card]->nphystat = (b2stat >> 8) | b1stat; /* endian?? */
-			pr_debug("%s: PhyStat is 0x%2x\n", adapter[card]->devicename,
-				adapter[card]->nphystat);
+			sc_adapter[card]->nphystat = (b2stat >> 8) | b1stat; /* endian?? */
+			pr_debug("%s: PhyStat is 0x%2x\n",
+				sc_adapter[card]->devicename,
+				sc_adapter[card]->nphystat);
 			continue;
 		}
 
@@ -223,7 +233,7 @@ irqreturn_t interrupt_handler(int interr
 				 * Set board format to HDLC if it wasn't already
 				 */
 				pr_debug("%s: current frame format: 0x%x, will change to HDLC\n",
-						adapter[card]->devicename,
+						sc_adapter[card]->devicename,
 					rcvmsg.msg_data.byte_array[0]);
 				sendmessage(card, CEPID, ceReqTypeCall,
 						ceReqClass0,
@@ -238,11 +248,13 @@ irqreturn_t interrupt_handler(int interr
 		 * Hmm...
 		 */
 		pr_debug("%s: Received unhandled message (%d,%d,%d) link %d\n",
-			adapter[card]->devicename, rcvmsg.type, rcvmsg.class, rcvmsg.code, 
+			sc_adapter[card]->devicename,
+			rcvmsg.type, rcvmsg.class, rcvmsg.code,
 			rcvmsg.phy_link_no);
 
 	}	/* while */
 
-	pr_debug("%s: Exiting Interrupt Handler\n", adapter[card]->devicename);
+	pr_debug("%s: Exiting Interrupt Handler\n",
+			sc_adapter[card]->devicename);
 	return IRQ_HANDLED;
 }
--- diff/drivers/isdn/sc/ioctl.c	2002-10-16 04:28:23.000000000 +0100
+++ source/drivers/isdn/sc/ioctl.c	2004-02-23 13:56:43.000000000 +0000
@@ -20,7 +20,7 @@ extern int send_and_receive(int, unsigne
 		unsigned char,unsigned char, 
 		unsigned char, unsigned char *, RspMessage *, int);
 
-extern board *adapter[];
+extern board *sc_adapter[];
 
 
 int GetStatus(int card, boardInfo *);
@@ -33,8 +33,9 @@ int sc_ioctl(int card, scs_ioctl *data)
 	switch(data->command) {
 	case SCIOCRESET:	/* Perform a hard reset of the adapter */
 	{
-		pr_debug("%s: SCIOCRESET: ioctl received\n", adapter[card]->devicename);
-		adapter[card]->StartOnReset = 0;
+		pr_debug("%s: SCIOCRESET: ioctl received\n",
+			sc_adapter[card]->devicename);
+		sc_adapter[card]->StartOnReset = 0;
 		return (reset(card));
 	}
 
@@ -44,10 +45,11 @@ int sc_ioctl(int card, scs_ioctl *data)
 		char		srec[SCIOC_SRECSIZE];
 		int		status;
 
-		pr_debug("%s: SCIOLOAD: ioctl received\n", adapter[card]->devicename);
-		if(adapter[card]->EngineUp) {
+		pr_debug("%s: SCIOLOAD: ioctl received\n",
+				sc_adapter[card]->devicename);
+		if(sc_adapter[card]->EngineUp) {
 			pr_debug("%s: SCIOCLOAD: command failed, LoadProc while engine running.\n",
-				adapter[card]->devicename);
+				sc_adapter[card]->devicename);
 			return -1;
 		}
 
@@ -61,25 +63,27 @@ int sc_ioctl(int card, scs_ioctl *data)
 				0, sizeof(srec), srec, &rcvmsg, SAR_TIMEOUT);
 		if(status) {
 			pr_debug("%s: SCIOCLOAD: command failed, status = %d\n", 
-				adapter[card]->devicename, status);
+				sc_adapter[card]->devicename, status);
 			return -1;
 		}
 		else {
-			pr_debug("%s: SCIOCLOAD: command successful\n", adapter[card]->devicename);
+			pr_debug("%s: SCIOCLOAD: command successful\n",
+					sc_adapter[card]->devicename);
 			return 0;
 		}
 	}
 
 	case SCIOCSTART:
 	{
-		pr_debug("%s: SCIOSTART: ioctl received\n", adapter[card]->devicename);
-		if(adapter[card]->EngineUp) {
+		pr_debug("%s: SCIOSTART: ioctl received\n",
+				sc_adapter[card]->devicename);
+		if(sc_adapter[card]->EngineUp) {
 			pr_debug("%s: SCIOCSTART: command failed, engine already running.\n",
-				adapter[card]->devicename);
+				sc_adapter[card]->devicename);
 			return -1;
 		}
 
-		adapter[card]->StartOnReset = 1;
+		sc_adapter[card]->StartOnReset = 1;
 		startproc(card);
 		return 0;
 	}
@@ -90,7 +94,8 @@ int sc_ioctl(int card, scs_ioctl *data)
 		char		switchtype;
 		int 		status;
 
-		pr_debug("%s: SCIOSETSWITCH: ioctl received\n", adapter[card]->devicename);
+		pr_debug("%s: SCIOSETSWITCH: ioctl received\n",
+				sc_adapter[card]->devicename);
 
 		/*
 		 * Get the switch type from user space
@@ -99,17 +104,19 @@ int sc_ioctl(int card, scs_ioctl *data)
 				   sizeof(char)))
 			return -EFAULT;
 
-		pr_debug("%s: SCIOCSETSWITCH: setting switch type to %d\n", adapter[card]->devicename,
+		pr_debug("%s: SCIOCSETSWITCH: setting switch type to %d\n",
+			sc_adapter[card]->devicename,
 			switchtype);
 		status = send_and_receive(card, CEPID, ceReqTypeCall, ceReqClass0, ceReqCallSetSwitchType,
 						0, sizeof(char),&switchtype,&rcvmsg, SAR_TIMEOUT);
 		if(!status && !rcvmsg.rsp_status) {
-			pr_debug("%s: SCIOCSETSWITCH: command successful\n", adapter[card]->devicename);
+			pr_debug("%s: SCIOCSETSWITCH: command successful\n",
+				sc_adapter[card]->devicename);
 			return 0;
 		}
 		else {
 			pr_debug("%s: SCIOCSETSWITCH: command failed (status = %d)\n",
-				adapter[card]->devicename, status);
+				sc_adapter[card]->devicename, status);
 			return status;
 		}
 	}
@@ -120,7 +127,8 @@ int sc_ioctl(int card, scs_ioctl *data)
 		char		switchtype;
 		int		status;
 
-		pr_debug("%s: SCIOGETSWITCH: ioctl received\n", adapter[card]->devicename);
+		pr_debug("%s: SCIOGETSWITCH: ioctl received\n",
+				sc_adapter[card]->devicename);
 
 		/*
 		 * Get the switch type from the board
@@ -128,11 +136,12 @@ int sc_ioctl(int card, scs_ioctl *data)
 		status = send_and_receive(card, CEPID, ceReqTypeCall, ceReqClass0, 
 			ceReqCallGetSwitchType, 0, 0, 0, &rcvmsg, SAR_TIMEOUT);
 		if (!status && !rcvmsg.rsp_status) {
-			pr_debug("%s: SCIOCGETSWITCH: command successful\n", adapter[card]->devicename);
+			pr_debug("%s: SCIOCGETSWITCH: command successful\n",
+					sc_adapter[card]->devicename);
 		}
 		else {
 			pr_debug("%s: SCIOCGETSWITCH: command failed (status = %d)\n",
-				adapter[card]->devicename, status);
+				sc_adapter[card]->devicename, status);
 			return status;
 		}
 
@@ -154,7 +163,8 @@ int sc_ioctl(int card, scs_ioctl *data)
 		char		spid[SCIOC_SPIDSIZE];
 		int		status;
 
-		pr_debug("%s: SCIOGETSPID: ioctl received\n", adapter[card]->devicename);
+		pr_debug("%s: SCIOGETSPID: ioctl received\n",
+				sc_adapter[card]->devicename);
 
 		/*
 		 * Get the spid from the board
@@ -162,11 +172,12 @@ int sc_ioctl(int card, scs_ioctl *data)
 		status = send_and_receive(card, CEPID, ceReqTypeCall, ceReqClass0, ceReqCallGetSPID,
 					data->channel, 0, 0, &rcvmsg, SAR_TIMEOUT);
 		if (!status) {
-			pr_debug("%s: SCIOCGETSPID: command successful\n", adapter[card]->devicename);
+			pr_debug("%s: SCIOCGETSPID: command successful\n",
+					sc_adapter[card]->devicename);
 		}
 		else {
 			pr_debug("%s: SCIOCGETSPID: command failed (status = %d)\n",
-				adapter[card]->devicename, status);
+				sc_adapter[card]->devicename, status);
 			return status;
 		}
 		strcpy(spid, rcvmsg.msg_data.byte_array);
@@ -186,7 +197,8 @@ int sc_ioctl(int card, scs_ioctl *data)
 		char		spid[SCIOC_SPIDSIZE];
 		int 		status;
 
-		pr_debug("%s: DCBIOSETSPID: ioctl received\n", adapter[card]->devicename);
+		pr_debug("%s: DCBIOSETSPID: ioctl received\n",
+				sc_adapter[card]->devicename);
 
 		/*
 		 * Get the spid from user space
@@ -195,18 +207,18 @@ int sc_ioctl(int card, scs_ioctl *data)
 			return -EFAULT;
 
 		pr_debug("%s: SCIOCSETSPID: setting channel %d spid to %s\n", 
-			adapter[card]->devicename, data->channel, spid);
+			sc_adapter[card]->devicename, data->channel, spid);
 		status = send_and_receive(card, CEPID, ceReqTypeCall, 
 			ceReqClass0, ceReqCallSetSPID, data->channel, 
 			strlen(spid), spid, &rcvmsg, SAR_TIMEOUT);
 		if(!status && !rcvmsg.rsp_status) {
 			pr_debug("%s: SCIOCSETSPID: command successful\n", 
-				adapter[card]->devicename);
+				sc_adapter[card]->devicename);
 			return 0;
 		}
 		else {
 			pr_debug("%s: SCIOCSETSPID: command failed (status = %d)\n",
-				adapter[card]->devicename, status);
+				sc_adapter[card]->devicename, status);
 			return status;
 		}
 	}
@@ -217,7 +229,8 @@ int sc_ioctl(int card, scs_ioctl *data)
 		char		dn[SCIOC_DNSIZE];
 		int		status;
 
-		pr_debug("%s: SCIOGETDN: ioctl received\n", adapter[card]->devicename);
+		pr_debug("%s: SCIOGETDN: ioctl received\n",
+				sc_adapter[card]->devicename);
 
 		/*
 		 * Get the dn from the board
@@ -225,11 +238,12 @@ int sc_ioctl(int card, scs_ioctl *data)
 		status = send_and_receive(card, CEPID, ceReqTypeCall, ceReqClass0, ceReqCallGetMyNumber,
 					data->channel, 0, 0, &rcvmsg, SAR_TIMEOUT);
 		if (!status) {
-			pr_debug("%s: SCIOCGETDN: command successful\n", adapter[card]->devicename);
+			pr_debug("%s: SCIOCGETDN: command successful\n",
+					sc_adapter[card]->devicename);
 		}
 		else {
 			pr_debug("%s: SCIOCGETDN: command failed (status = %d)\n",
-				adapter[card]->devicename, status);
+				sc_adapter[card]->devicename, status);
 			return status;
 		}
 
@@ -250,7 +264,8 @@ int sc_ioctl(int card, scs_ioctl *data)
 		char		dn[SCIOC_DNSIZE];
 		int 		status;
 
-		pr_debug("%s: SCIOSETDN: ioctl received\n", adapter[card]->devicename);
+		pr_debug("%s: SCIOSETDN: ioctl received\n",
+				sc_adapter[card]->devicename);
 
 		/*
 		 * Get the spid from user space
@@ -259,35 +274,38 @@ int sc_ioctl(int card, scs_ioctl *data)
 			return -EFAULT;
 
 		pr_debug("%s: SCIOCSETDN: setting channel %d dn to %s\n", 
-			adapter[card]->devicename, data->channel, dn);
+			sc_adapter[card]->devicename, data->channel, dn);
 		status = send_and_receive(card, CEPID, ceReqTypeCall, 
 			ceReqClass0, ceReqCallSetMyNumber, data->channel, 
 			strlen(dn),dn,&rcvmsg, SAR_TIMEOUT);
 		if(!status && !rcvmsg.rsp_status) {
 			pr_debug("%s: SCIOCSETDN: command successful\n", 
-				adapter[card]->devicename);
+				sc_adapter[card]->devicename);
 			return 0;
 		}
 		else {
 			pr_debug("%s: SCIOCSETDN: command failed (status = %d)\n",
-				adapter[card]->devicename, status);
+				sc_adapter[card]->devicename, status);
 			return status;
 		}
 	}
 
 	case SCIOCTRACE:
 
-		pr_debug("%s: SCIOTRACE: ioctl received\n", adapter[card]->devicename);
-/*		adapter[card]->trace = !adapter[card]->trace; 
-		pr_debug("%s: SCIOCTRACE: tracing turned %s\n", adapter[card]->devicename,
-			adapter[card]->trace ? "ON" : "OFF"); */
+		pr_debug("%s: SCIOTRACE: ioctl received\n",
+				sc_adapter[card]->devicename);
+/*		sc_adapter[card]->trace = !sc_adapter[card]->trace;
+		pr_debug("%s: SCIOCTRACE: tracing turned %s\n",
+				sc_adapter[card]->devicename,
+			sc_adapter[card]->trace ? "ON" : "OFF"); */
 		break;
 
 	case SCIOCSTAT:
 	{
 		boardInfo bi;
 
-		pr_debug("%s: SCIOSTAT: ioctl received\n", adapter[card]->devicename);
+		pr_debug("%s: SCIOSTAT: ioctl received\n",
+				sc_adapter[card]->devicename);
 		GetStatus(card, &bi);
 		
 		if (copy_to_user((boardInfo *)data->dataptr, &bi,
@@ -303,7 +321,8 @@ int sc_ioctl(int card, scs_ioctl *data)
 		char		speed;
 		int		status;
 
-		pr_debug("%s: SCIOGETSPEED: ioctl received\n", adapter[card]->devicename);
+		pr_debug("%s: SCIOGETSPEED: ioctl received\n",
+				sc_adapter[card]->devicename);
 
 		/*
 		 * Get the speed from the board
@@ -312,11 +331,11 @@ int sc_ioctl(int card, scs_ioctl *data)
 			ceReqCallGetCallType, data->channel, 0, 0, &rcvmsg, SAR_TIMEOUT);
 		if (!status && !rcvmsg.rsp_status) {
 			pr_debug("%s: SCIOCGETSPEED: command successful\n",
-				adapter[card]->devicename);
+				sc_adapter[card]->devicename);
 		}
 		else {
 			pr_debug("%s: SCIOCGETSPEED: command failed (status = %d)\n",
-				adapter[card]->devicename, status);
+				sc_adapter[card]->devicename, status);
 			return status;
 		}
 
@@ -332,11 +351,13 @@ int sc_ioctl(int card, scs_ioctl *data)
 	}
 
 	case SCIOCSETSPEED:
-		pr_debug("%s: SCIOCSETSPEED: ioctl received\n", adapter[card]->devicename);
+		pr_debug("%s: SCIOCSETSPEED: ioctl received\n",
+				sc_adapter[card]->devicename);
 		break;
 
 	case SCIOCLOOPTST:
-		pr_debug("%s: SCIOCLOOPTST: ioctl received\n", adapter[card]->devicename);
+		pr_debug("%s: SCIOCLOOPTST: ioctl received\n",
+				sc_adapter[card]->devicename);
 		break;
 
 	default:
@@ -354,16 +375,16 @@ int GetStatus(int card, boardInfo *bi)
 	/*
 	 * Fill in some of the basic info about the board
 	 */
-	bi->modelid = adapter[card]->model;
-	strcpy(bi->serial_no, adapter[card]->hwconfig.serial_no);
-	strcpy(bi->part_no, adapter[card]->hwconfig.part_no);
-	bi->iobase = adapter[card]->iobase;
-	bi->rambase = adapter[card]->rambase;
-	bi->irq = adapter[card]->interrupt;
-	bi->ramsize = adapter[card]->hwconfig.ram_size;
-	bi->interface = adapter[card]->hwconfig.st_u_sense;
-	strcpy(bi->load_ver, adapter[card]->load_ver);
-	strcpy(bi->proc_ver, adapter[card]->proc_ver);
+	bi->modelid = sc_adapter[card]->model;
+	strcpy(bi->serial_no, sc_adapter[card]->hwconfig.serial_no);
+	strcpy(bi->part_no, sc_adapter[card]->hwconfig.part_no);
+	bi->iobase = sc_adapter[card]->iobase;
+	bi->rambase = sc_adapter[card]->rambase;
+	bi->irq = sc_adapter[card]->interrupt;
+	bi->ramsize = sc_adapter[card]->hwconfig.ram_size;
+	bi->interface = sc_adapter[card]->hwconfig.st_u_sense;
+	strcpy(bi->load_ver, sc_adapter[card]->load_ver);
+	strcpy(bi->proc_ver, sc_adapter[card]->proc_ver);
 
 	/*
 	 * Get the current PhyStats and LnkStats
@@ -371,7 +392,7 @@ int GetStatus(int card, boardInfo *bi)
 	status = send_and_receive(card, CEPID, ceReqTypePhy, ceReqClass2,
 		ceReqPhyStatus, 0, 0, NULL, &rcvmsg, SAR_TIMEOUT);
 	if(!status) {
-		if(adapter[card]->model < PRI_BOARD) {
+		if(sc_adapter[card]->model < PRI_BOARD) {
 			bi->l1_status = rcvmsg.msg_data.byte_array[2];
 			for(i = 0 ; i < BRI_CHANNELS ; i++)
 				bi->status.bristats[i].phy_stat =
@@ -389,11 +410,11 @@ int GetStatus(int card, boardInfo *bi)
 	/*
 	 * Get the call types for each channel
 	 */
-	for (i = 0 ; i < adapter[card]->nChannels ; i++) {
+	for (i = 0 ; i < sc_adapter[card]->nChannels ; i++) {
 		status = send_and_receive(card, CEPID, ceReqTypeCall, ceReqClass0,
 			ceReqCallGetCallType, 0, 0, NULL, &rcvmsg, SAR_TIMEOUT);
 		if(!status) {
-			if (adapter[card]->model == PRI_BOARD) {
+			if (sc_adapter[card]->model == PRI_BOARD) {
 				bi->status.pristats[i].call_type = 
 					rcvmsg.msg_data.byte_array[0];
 			}
@@ -407,7 +428,7 @@ int GetStatus(int card, boardInfo *bi)
 	/*
 	 * If PRI, get the call states and service states for each channel
 	 */
-	if (adapter[card]->model == PRI_BOARD) {
+	if (sc_adapter[card]->model == PRI_BOARD) {
 		/*
 		 * Get the call states
 		 */
--- diff/drivers/isdn/sc/message.c	2003-09-17 12:28:06.000000000 +0100
+++ source/drivers/isdn/sc/message.c	2004-02-23 13:56:43.000000000 +0000
@@ -22,7 +22,7 @@
 #include "message.h"
 #include "card.h"
 
-extern board *adapter[];
+extern board *sc_adapter[];
 extern unsigned int cinst;
 
 /*
@@ -46,31 +46,32 @@ int receivemessage(int card, RspMessage 
 		return -EINVAL;
 	}
 	
-	pr_debug("%s: Entered receivemessage\n",adapter[card]->devicename);
+	pr_debug("%s: Entered receivemessage\n",
+			sc_adapter[card]->devicename);
 
 	/*
 	 * See if there are messages waiting
 	 */
-	if (inb(adapter[card]->ioport[FIFO_STATUS]) & RF_HAS_DATA) {
+	if (inb(sc_adapter[card]->ioport[FIFO_STATUS]) & RF_HAS_DATA) {
 		/*
 		 * Map in the DPM to the base page and copy the message
 		 */
-		spin_lock_irqsave(&adapter[card]->lock, flags);
-		outb((adapter[card]->shmem_magic >> 14) | 0x80,
-			adapter[card]->ioport[adapter[card]->shmem_pgport]); 
-		dpm = (DualPortMemory *) adapter[card]->rambase;
+		spin_lock_irqsave(&sc_adapter[card]->lock, flags);
+		outb((sc_adapter[card]->shmem_magic >> 14) | 0x80,
+			sc_adapter[card]->ioport[sc_adapter[card]->shmem_pgport]);
+		dpm = (DualPortMemory *) sc_adapter[card]->rambase;
 		memcpy_fromio(rspmsg, &(dpm->rsp_queue[dpm->rsp_tail]), 
 			MSG_LEN);
 		dpm->rsp_tail = (dpm->rsp_tail+1) % MAX_MESSAGES;
-		inb(adapter[card]->ioport[FIFO_READ]);
-		spin_unlock_irqrestore(&adapter[card]->lock, flags);
+		inb(sc_adapter[card]->ioport[FIFO_READ]);
+		spin_unlock_irqrestore(&sc_adapter[card]->lock, flags);
 		/*
 		 * Tell the board that the message is received
 		 */
 		pr_debug("%s: Received Message seq:%d pid:%d time:%d cmd:%d "
 				"cnt:%d (type,class,code):(%d,%d,%d) "
 				"link:%d stat:0x%x\n",
-					adapter[card]->devicename,
+					sc_adapter[card]->devicename,
 					rspmsg->sequence_no,
 					rspmsg->process_id,
 					rspmsg->time_stamp,
@@ -112,15 +113,15 @@ int sendmessage(int card,
 	 * Make sure we only send CEPID messages when the engine is up
 	 * and CMPID messages when it is down
 	 */
-	if(adapter[card]->EngineUp && procid == CMPID) {
+	if(sc_adapter[card]->EngineUp && procid == CMPID) {
 		pr_debug("%s: Attempt to send CM message with engine up\n",
-			adapter[card]->devicename);
+			sc_adapter[card]->devicename);
 		return -ESRCH;
 	}
 
-	if(!adapter[card]->EngineUp && procid == CEPID) {
+	if(!sc_adapter[card]->EngineUp && procid == CEPID) {
 		pr_debug("%s: Attempt to send CE message with engine down\n",
-			adapter[card]->devicename);
+			sc_adapter[card]->devicename);
 		return -ESRCH;
 	}
 
@@ -139,30 +140,30 @@ int sendmessage(int card,
 	}
 
 	sndmsg.process_id = procid;
-	sndmsg.sequence_no = adapter[card]->seq_no++ % 256;
+	sndmsg.sequence_no = sc_adapter[card]->seq_no++ % 256;
 
 	/*
 	 * wait for an empty slot in the queue
 	 */
-	while (!(inb(adapter[card]->ioport[FIFO_STATUS]) & WF_NOT_FULL))
+	while (!(inb(sc_adapter[card]->ioport[FIFO_STATUS]) & WF_NOT_FULL))
 		udelay(1);
 
 	/*
 	 * Disable interrupts and map in shared memory
 	 */
-	spin_lock_irqsave(&adapter[card]->lock, flags);
-	outb((adapter[card]->shmem_magic >> 14) | 0x80,
-		adapter[card]->ioport[adapter[card]->shmem_pgport]); 
-	dpm = (DualPortMemory *) adapter[card]->rambase;	/* Fix me */
+	spin_lock_irqsave(&sc_adapter[card]->lock, flags);
+	outb((sc_adapter[card]->shmem_magic >> 14) | 0x80,
+		sc_adapter[card]->ioport[sc_adapter[card]->shmem_pgport]);
+	dpm = (DualPortMemory *) sc_adapter[card]->rambase;	/* Fix me */
 	memcpy_toio(&(dpm->req_queue[dpm->req_head]),&sndmsg,MSG_LEN);
 	dpm->req_head = (dpm->req_head+1) % MAX_MESSAGES;
-	outb(sndmsg.sequence_no, adapter[card]->ioport[FIFO_WRITE]);
-	spin_unlock_irqrestore(&adapter[card]->lock, flags);
+	outb(sndmsg.sequence_no, sc_adapter[card]->ioport[FIFO_WRITE]);
+	spin_unlock_irqrestore(&sc_adapter[card]->lock, flags);
 		
 	pr_debug("%s: Sent Message seq:%d pid:%d time:%d "
 			"cnt:%d (type,class,code):(%d,%d,%d) "
 			"link:%d\n ",
-				adapter[card]->devicename,
+				sc_adapter[card]->devicename,
 				sndmsg.sequence_no,
 				sndmsg.process_id,
 				sndmsg.time_stamp,
@@ -194,14 +195,14 @@ int send_and_receive(int card,
 		return -EINVAL;
 	}
 
-	adapter[card]->want_async_messages = 1;
+	sc_adapter[card]->want_async_messages = 1;
 	retval = sendmessage(card, procid, type, class, code, link, 
 			data_len, (unsigned int *) data);
   
 	if (retval) {
 		pr_debug("%s: SendMessage failed in SAR\n",
-			adapter[card]->devicename);
-		adapter[card]->want_async_messages = 0;
+			sc_adapter[card]->devicename);
+		sc_adapter[card]->want_async_messages = 0;
 		return -EIO;
 	}
 
@@ -216,26 +217,26 @@ int send_and_receive(int card,
 		/*
 		 * See if we got our message back
 		 */
-		if ((adapter[card]->async_msg.type == type) &&
-		    (adapter[card]->async_msg.class == class) &&
-		    (adapter[card]->async_msg.code == code) &&
-		    (adapter[card]->async_msg.phy_link_no == link)) {
+		if ((sc_adapter[card]->async_msg.type == type) &&
+		    (sc_adapter[card]->async_msg.class == class) &&
+		    (sc_adapter[card]->async_msg.code == code) &&
+		    (sc_adapter[card]->async_msg.phy_link_no == link)) {
 
 			/*
 			 * Got it!
 			 */
 			pr_debug("%s: Got ASYNC message\n",
-				adapter[card]->devicename);
-			memcpy(mesgdata, &(adapter[card]->async_msg), 
+				sc_adapter[card]->devicename);
+			memcpy(mesgdata, &(sc_adapter[card]->async_msg),
 				sizeof(RspMessage));
-			adapter[card]->want_async_messages = 0;
+			sc_adapter[card]->want_async_messages = 0;
 			return 0;
 		}
 
    		tries++;
 	}
 
-	pr_debug("%s: SAR message timeout\n", adapter[card]->devicename);
-	adapter[card]->want_async_messages = 0;
+	pr_debug("%s: SAR message timeout\n", sc_adapter[card]->devicename);
+	sc_adapter[card]->want_async_messages = 0;
 	return -ETIME;
 }
--- diff/drivers/isdn/sc/packet.c	2002-10-16 04:29:06.000000000 +0100
+++ source/drivers/isdn/sc/packet.c	2004-02-23 13:56:43.000000000 +0000
@@ -20,7 +20,7 @@
 #include "message.h"
 #include "card.h"
 
-extern board *adapter[];
+extern board *sc_adapter[];
 extern unsigned int cinst;
 
 extern int get_card_from_id(int);
@@ -45,26 +45,29 @@ int sndpkt(int devId, int channel, struc
 	}
 
 	pr_debug("%s: sndpkt: frst = 0x%x nxt = %d  f = %d n = %d\n",
-		adapter[card]->devicename,
-		adapter[card]->channel[channel].first_sendbuf,
-		adapter[card]->channel[channel].next_sendbuf,
-		adapter[card]->channel[channel].free_sendbufs,
-		adapter[card]->channel[channel].num_sendbufs);
-
-	if(!adapter[card]->channel[channel].free_sendbufs) {
-		pr_debug("%s: out of TX buffers\n", adapter[card]->devicename);
+		sc_adapter[card]->devicename,
+		sc_adapter[card]->channel[channel].first_sendbuf,
+		sc_adapter[card]->channel[channel].next_sendbuf,
+		sc_adapter[card]->channel[channel].free_sendbufs,
+		sc_adapter[card]->channel[channel].num_sendbufs);
+
+	if(!sc_adapter[card]->channel[channel].free_sendbufs) {
+		pr_debug("%s: out of TX buffers\n",
+				sc_adapter[card]->devicename);
 		return -EINVAL;
 	}
 
 	if(data->len > BUFFER_SIZE) {
-		pr_debug("%s: data overflows buffer size (data > buffer)\n", adapter[card]->devicename);
+		pr_debug("%s: data overflows buffer size (data > buffer)\n",
+			sc_adapter[card]->devicename);
 		return -EINVAL;
 	}
 
-	ReqLnkWrite.buff_offset = adapter[card]->channel[channel].next_sendbuf *
-		BUFFER_SIZE + adapter[card]->channel[channel].first_sendbuf;
+	ReqLnkWrite.buff_offset = sc_adapter[card]->channel[channel].next_sendbuf *
+		BUFFER_SIZE + sc_adapter[card]->channel[channel].first_sendbuf;
 	ReqLnkWrite.msg_len = data->len; /* sk_buff size */
-	pr_debug("%s: writing %d bytes to buffer offset 0x%x\n", adapter[card]->devicename,
+	pr_debug("%s: writing %d bytes to buffer offset 0x%x\n",
+			sc_adapter[card]->devicename,
 			ReqLnkWrite.msg_len, ReqLnkWrite.buff_offset);
 	memcpy_toshmem(card, (char *)ReqLnkWrite.buff_offset, data->data, ReqLnkWrite.msg_len);
 
@@ -72,24 +75,25 @@ int sndpkt(int devId, int channel, struc
 	 * sendmessage
 	 */
 	pr_debug("%s: sndpkt size=%d, buf_offset=0x%x buf_indx=%d\n",
-		adapter[card]->devicename,
+		sc_adapter[card]->devicename,
 		ReqLnkWrite.msg_len, ReqLnkWrite.buff_offset,
-		adapter[card]->channel[channel].next_sendbuf);
+		sc_adapter[card]->channel[channel].next_sendbuf);
 
 	status = sendmessage(card, CEPID, ceReqTypeLnk, ceReqClass1, ceReqLnkWrite,
 				channel+1, sizeof(LLData), (unsigned int*)&ReqLnkWrite);
 	len = data->len;
 	if(status) {
-		pr_debug("%s: failed to send packet, status = %d\n", adapter[card]->devicename, status);
+		pr_debug("%s: failed to send packet, status = %d\n",
+				sc_adapter[card]->devicename, status);
 		return -1;
 	}
 	else {
-		adapter[card]->channel[channel].free_sendbufs--;
-		adapter[card]->channel[channel].next_sendbuf =
-			++adapter[card]->channel[channel].next_sendbuf ==
-			adapter[card]->channel[channel].num_sendbufs ? 0 :
-			adapter[card]->channel[channel].next_sendbuf;
-			pr_debug("%s: packet sent successfully\n", adapter[card]->devicename);
+		sc_adapter[card]->channel[channel].free_sendbufs--;
+		sc_adapter[card]->channel[channel].next_sendbuf =
+			++sc_adapter[card]->channel[channel].next_sendbuf ==
+			sc_adapter[card]->channel[channel].num_sendbufs ? 0 :
+			sc_adapter[card]->channel[channel].next_sendbuf;
+			pr_debug("%s: packet sent successfully\n", sc_adapter[card]->devicename);
 		dev_kfree_skb(data);
 		indicate_status(card,ISDN_STAT_BSENT,channel, (char *)&len);
 	}
@@ -110,33 +114,37 @@ void rcvpkt(int card, RspMessage *rcvmsg
 	case 0x01:
 	case 0x02:
 	case 0x70:
-		pr_debug("%s: error status code: 0x%x\n", adapter[card]->devicename, rcvmsg->rsp_status);
+		pr_debug("%s: error status code: 0x%x\n",
+			sc_adapter[card]->devicename, rcvmsg->rsp_status);
 		return;
 	case 0x00: 
 	    if (!(skb = dev_alloc_skb(rcvmsg->msg_data.response.msg_len))) {
 			printk(KERN_WARNING "%s: rcvpkt out of memory, dropping packet\n",
-				adapter[card]->devicename);
+				sc_adapter[card]->devicename);
 			return;
 		}
 		skb_put(skb, rcvmsg->msg_data.response.msg_len);
 		pr_debug("%s: getting data from offset: 0x%x\n",
-			adapter[card]->devicename,rcvmsg->msg_data.response.buff_offset);
+			sc_adapter[card]->devicename,
+			rcvmsg->msg_data.response.buff_offset);
 		memcpy_fromshmem(card,
 			skb_put(skb, rcvmsg->msg_data.response.msg_len),
 		 	(char *)rcvmsg->msg_data.response.buff_offset,
 			rcvmsg->msg_data.response.msg_len);
-		adapter[card]->card->rcvcallb_skb(adapter[card]->driverId,
+		sc_adapter[card]->card->rcvcallb_skb(sc_adapter[card]->driverId,
 			rcvmsg->phy_link_no-1, skb);
 
 	case 0x03:
 		/*
 	 	 * Recycle the buffer
 	 	 */
-		pr_debug("%s: buffer size : %d\n", adapter[card]->devicename, BUFFER_SIZE);
+		pr_debug("%s: buffer size : %d\n",
+				sc_adapter[card]->devicename, BUFFER_SIZE);
 /*		memset_shmem(card, rcvmsg->msg_data.response.buff_offset, 0, BUFFER_SIZE); */
 		newll.buff_offset = rcvmsg->msg_data.response.buff_offset;
 		newll.msg_len = BUFFER_SIZE;
-		pr_debug("%s: recycled buffer at offset 0x%x size %d\n", adapter[card]->devicename,
+		pr_debug("%s: recycled buffer at offset 0x%x size %d\n",
+			sc_adapter[card]->devicename,
 			newll.buff_offset, newll.msg_len);
 		sendmessage(card, CEPID, ceReqTypeLnk, ceReqClass1, ceReqLnkRead,
 			rcvmsg->phy_link_no, sizeof(LLData), (unsigned int *)&newll);
@@ -158,40 +166,45 @@ int setup_buffers(int card, int c)
 	/*
 	 * Calculate the buffer offsets (send/recv/send/recv)
 	 */
-	pr_debug("%s: setting up channel buffer space in shared RAM\n", adapter[card]->devicename);
+	pr_debug("%s: setting up channel buffer space in shared RAM\n",
+			sc_adapter[card]->devicename);
 	buffer_size = BUFFER_SIZE;
-	nBuffers = ((adapter[card]->ramsize - BUFFER_BASE) / buffer_size) / 2;
+	nBuffers = ((sc_adapter[card]->ramsize - BUFFER_BASE) / buffer_size) / 2;
 	nBuffers = nBuffers > BUFFERS_MAX ? BUFFERS_MAX : nBuffers;
-	pr_debug("%s: calculating buffer space: %d buffers, %d big\n", adapter[card]->devicename,
+	pr_debug("%s: calculating buffer space: %d buffers, %d big\n",
+		sc_adapter[card]->devicename,
 		nBuffers, buffer_size);
 	if(nBuffers < 2) {
-		pr_debug("%s: not enough buffer space\n", adapter[card]->devicename);
+		pr_debug("%s: not enough buffer space\n",
+			sc_adapter[card]->devicename);
 		return -1;
 	}
 	cBase = (nBuffers * buffer_size) * (c - 1);
-	pr_debug("%s: channel buffer offset from shared RAM: 0x%x\n", adapter[card]->devicename, cBase);
-	adapter[card]->channel[c-1].first_sendbuf = BUFFER_BASE + cBase;
-	adapter[card]->channel[c-1].num_sendbufs = nBuffers / 2;
-	adapter[card]->channel[c-1].free_sendbufs = nBuffers / 2;
-	adapter[card]->channel[c-1].next_sendbuf = 0;
+	pr_debug("%s: channel buffer offset from shared RAM: 0x%x\n",
+			sc_adapter[card]->devicename, cBase);
+	sc_adapter[card]->channel[c-1].first_sendbuf = BUFFER_BASE + cBase;
+	sc_adapter[card]->channel[c-1].num_sendbufs = nBuffers / 2;
+	sc_adapter[card]->channel[c-1].free_sendbufs = nBuffers / 2;
+	sc_adapter[card]->channel[c-1].next_sendbuf = 0;
 	pr_debug("%s: send buffer setup complete: first=0x%x n=%d f=%d, nxt=%d\n",
-				adapter[card]->devicename,
-				adapter[card]->channel[c-1].first_sendbuf,
-				adapter[card]->channel[c-1].num_sendbufs,
-				adapter[card]->channel[c-1].free_sendbufs,
-				adapter[card]->channel[c-1].next_sendbuf);
+				sc_adapter[card]->devicename,
+				sc_adapter[card]->channel[c-1].first_sendbuf,
+				sc_adapter[card]->channel[c-1].num_sendbufs,
+				sc_adapter[card]->channel[c-1].free_sendbufs,
+				sc_adapter[card]->channel[c-1].next_sendbuf);
 
 	/*
 	 * Prep the receive buffers
 	 */
-	pr_debug("%s: adding %d RecvBuffers:\n", adapter[card]->devicename, nBuffers /2);
+	pr_debug("%s: adding %d RecvBuffers:\n",
+			sc_adapter[card]->devicename, nBuffers /2);
 	for (i = 0 ; i < nBuffers / 2; i++) {
 		RcvBuffOffset.buff_offset = 
-			((adapter[card]->channel[c-1].first_sendbuf +
+			((sc_adapter[card]->channel[c-1].first_sendbuf +
 			(nBuffers / 2) * buffer_size) + (buffer_size * i));
 		RcvBuffOffset.msg_len = buffer_size;
 		pr_debug("%s: adding RcvBuffer #%d offset=0x%x sz=%d bufsz:%d\n",
-				adapter[card]->devicename,
+				sc_adapter[card]->devicename,
 				i + 1, RcvBuffOffset.buff_offset, 
 				RcvBuffOffset.msg_len,buffer_size);
 		sendmessage(card, CEPID, ceReqTypeLnk, ceReqClass1, ceReqLnkRead,
@@ -202,11 +215,11 @@ int setup_buffers(int card, int c)
 
 int print_skb(int card,char *skb_p, int len){
 	int i,data;
-	pr_debug("%s: data at 0x%x len: 0x%x\n",adapter[card]->devicename,
+	pr_debug("%s: data at 0x%x len: 0x%x\n", sc_adapter[card]->devicename,
 			skb_p,len);
 	for(i=1;i<=len;i++,skb_p++){
 		data = (int) (0xff & (*skb_p));
-		pr_debug("%s: data =  0x%x",adapter[card]->devicename,data);
+		pr_debug("%s: data =  0x%x", sc_adapter[card]->devicename,data);
 		if(!(i%4))
 			pr_debug(" ");
 		if(!(i%32))
--- diff/drivers/isdn/sc/shmem.c	2003-09-17 12:28:06.000000000 +0100
+++ source/drivers/isdn/sc/shmem.c	2004-02-23 13:56:43.000000000 +0000
@@ -24,7 +24,7 @@
 /*
  * Main adapter array
  */
-extern board *adapter[];
+extern board *sc_adapter[];
 extern int cinst;
 
 /*
@@ -49,21 +49,23 @@ void *memcpy_toshmem(int card, void *des
 	 * determine the page to load from the address
 	 */
 	ch = (unsigned long) dest / SRAM_PAGESIZE;
-	pr_debug("%s: loaded page %d\n",adapter[card]->devicename,ch);
+	pr_debug("%s: loaded page %d\n", sc_adapter[card]->devicename,ch);
 	/*
 	 * Block interrupts and load the page
 	 */
-	spin_lock_irqsave(&adapter[card]->lock, flags);
+	spin_lock_irqsave(&sc_adapter[card]->lock, flags);
 
-	outb(((adapter[card]->shmem_magic + ch * SRAM_PAGESIZE) >> 14) | 0x80,
-		adapter[card]->ioport[adapter[card]->shmem_pgport]);
-	ret = memcpy_toio(adapter[card]->rambase + 
+	outb(((sc_adapter[card]->shmem_magic + ch * SRAM_PAGESIZE) >> 14) | 0x80,
+		sc_adapter[card]->ioport[sc_adapter[card]->shmem_pgport]);
+	ret = memcpy_toio(sc_adapter[card]->rambase +
 		((unsigned long) dest % 0x4000), src, n);
-	spin_unlock_irqrestore(&adapter[card]->lock, flags);
-	pr_debug("%s: set page to %#x\n",adapter[card]->devicename,
-		((adapter[card]->shmem_magic + ch * SRAM_PAGESIZE)>>14)|0x80);
-	pr_debug("%s: copying %d bytes from %#x to %#x\n",adapter[card]->devicename, n,
-		 (unsigned long) src, adapter[card]->rambase + ((unsigned long) dest %0x4000));
+	spin_unlock_irqrestore(&sc_adapter[card]->lock, flags);
+	pr_debug("%s: set page to %#x\n",sc_adapter[card]->devicename,
+		((sc_adapter[card]->shmem_magic + ch * SRAM_PAGESIZE)>>14)|0x80);
+	pr_debug("%s: copying %d bytes from %#x to %#x\n",
+		sc_adapter[card]->devicename, n,
+		(unsigned long) src,
+		sc_adapter[card]->rambase + ((unsigned long) dest %0x4000));
 
 	return ret;
 }
@@ -90,24 +92,24 @@ void *memcpy_fromshmem(int card, void *d
 	 * determine the page to load from the address
 	 */
 	ch = (unsigned long) src / SRAM_PAGESIZE;
-	pr_debug("%s: loaded page %d\n",adapter[card]->devicename,ch);
+	pr_debug("%s: loaded page %d\n", sc_adapter[card]->devicename,ch);
 	
 	
 	/*
 	 * Block interrupts and load the page
 	 */
-	spin_lock_irqsave(&adapter[card]->lock, flags);
+	spin_lock_irqsave(&sc_adapter[card]->lock, flags);
 
-	outb(((adapter[card]->shmem_magic + ch * SRAM_PAGESIZE) >> 14) | 0x80,
-		adapter[card]->ioport[adapter[card]->shmem_pgport]);
-	ret = memcpy_fromio(dest,(void *)(adapter[card]->rambase + 
+	outb(((sc_adapter[card]->shmem_magic + ch * SRAM_PAGESIZE) >> 14) | 0x80,
+		sc_adapter[card]->ioport[sc_adapter[card]->shmem_pgport]);
+	ret = memcpy_fromio(dest,(void *)(sc_adapter[card]->rambase +
 		((unsigned long) src % 0x4000)), n);
-	spin_unlock_irqrestore(&adapter[card]->lock, flags);
-	pr_debug("%s: set page to %#x\n",adapter[card]->devicename,
-		((adapter[card]->shmem_magic + ch * SRAM_PAGESIZE)>>14)|0x80);
+	spin_unlock_irqrestore(&sc_adapter[card]->lock, flags);
+	pr_debug("%s: set page to %#x\n",sc_adapter[card]->devicename,
+		((sc_adapter[card]->shmem_magic + ch * SRAM_PAGESIZE)>>14)|0x80);
 /*	pr_debug("%s: copying %d bytes from %#x to %#x\n",
-		adapter[card]->devicename, n,
-		adapter[card]->rambase + ((unsigned long) src %0x4000), (unsigned long) dest); */
+		sc_adapter[card]->devicename, n,
+		sc_adapter[card]->rambase + ((unsigned long) src %0x4000), (unsigned long) dest); */
 
 	return ret;
 }
@@ -131,20 +133,20 @@ void *memset_shmem(int card, void *dest,
 	 * determine the page to load from the address
 	 */
 	ch = (unsigned long) dest / SRAM_PAGESIZE;
-	pr_debug("%s: loaded page %d\n",adapter[card]->devicename,ch);
+	pr_debug("%s: loaded page %d\n",sc_adapter[card]->devicename,ch);
 
 	/*
 	 * Block interrupts and load the page
 	 */
-	spin_lock_irqsave(&adapter[card]->lock, flags);
+	spin_lock_irqsave(&sc_adapter[card]->lock, flags);
 
-	outb(((adapter[card]->shmem_magic + ch * SRAM_PAGESIZE) >> 14) | 0x80,
-		adapter[card]->ioport[adapter[card]->shmem_pgport]);
-	ret = memset_io(adapter[card]->rambase + 
+	outb(((sc_adapter[card]->shmem_magic + ch * SRAM_PAGESIZE) >> 14) | 0x80,
+		sc_adapter[card]->ioport[sc_adapter[card]->shmem_pgport]);
+	ret = memset_io(sc_adapter[card]->rambase +
 		((unsigned long) dest % 0x4000), c, n);
-	pr_debug("%s: set page to %#x\n",adapter[card]->devicename,
-		((adapter[card]->shmem_magic + ch * SRAM_PAGESIZE)>>14)|0x80);
-	spin_unlock_irqrestore(&adapter[card]->lock, flags);
+	pr_debug("%s: set page to %#x\n",sc_adapter[card]->devicename,
+		((sc_adapter[card]->shmem_magic + ch * SRAM_PAGESIZE)>>14)|0x80);
+	spin_unlock_irqrestore(&sc_adapter[card]->lock, flags);
 
 	return ret;
 }
--- diff/drivers/isdn/sc/timer.c	2003-09-17 12:28:06.000000000 +0100
+++ source/drivers/isdn/sc/timer.c	2004-02-23 13:56:43.000000000 +0000
@@ -20,7 +20,7 @@
 #include "message.h"
 #include "card.h"
 
-extern board *adapter[];
+extern board *sc_adapter[];
 
 extern void flushreadfifo(int);
 extern int  startproc(int);
@@ -35,11 +35,11 @@ extern int  sendmessage(int, unsigned in
 void setup_ports(int card)
 {
 
-	outb((adapter[card]->rambase >> 12), adapter[card]->ioport[EXP_BASE]);
+	outb((sc_adapter[card]->rambase >> 12), sc_adapter[card]->ioport[EXP_BASE]);
 
 	/* And the IRQ */
-	outb((adapter[card]->interrupt | 0x80), 
-		adapter[card]->ioport[IRQ_SELECT]);
+	outb((sc_adapter[card]->interrupt | 0x80),
+		sc_adapter[card]->ioport[IRQ_SELECT]);
 }
 
 /*
@@ -57,28 +57,29 @@ void check_reset(unsigned long data)
 	unsigned long sig;
 	int card = (unsigned int) data;
 
-	pr_debug("%s: check_timer timer called\n", adapter[card]->devicename);
+	pr_debug("%s: check_timer timer called\n",
+		sc_adapter[card]->devicename);
 
 	/* Setup the io ports */
 	setup_ports(card);
 
-	spin_lock_irqsave(&adapter[card]->lock, flags);
-	outb(adapter[card]->ioport[adapter[card]->shmem_pgport],
-		(adapter[card]->shmem_magic>>14) | 0x80);	
-	sig = (unsigned long) *((unsigned long *)(adapter[card]->rambase + SIG_OFFSET));	
+	spin_lock_irqsave(&sc_adapter[card]->lock, flags);
+	outb(sc_adapter[card]->ioport[sc_adapter[card]->shmem_pgport],
+		(sc_adapter[card]->shmem_magic>>14) | 0x80);
+	sig = (unsigned long) *((unsigned long *)(sc_adapter[card]->rambase + SIG_OFFSET));
 
 	/* check the signature */
 	if(sig == SIGNATURE) {
 		flushreadfifo(card);
-		spin_unlock_irqrestore(&adapter[card]->lock, flags);
+		spin_unlock_irqrestore(&sc_adapter[card]->lock, flags);
 		/* See if we need to do a startproc */
-		if (adapter[card]->StartOnReset)
+		if (sc_adapter[card]->StartOnReset)
 			startproc(card);
 	} else  {
 		pr_debug("%s: No signature yet, waiting another %d jiffies.\n", 
-			adapter[card]->devicename, CHECKRESET_TIME);
-		mod_timer(&adapter[card]->reset_timer, jiffies+CHECKRESET_TIME);
-		spin_unlock_irqrestore(&adapter[card]->lock, flags);
+			sc_adapter[card]->devicename, CHECKRESET_TIME);
+		mod_timer(&sc_adapter[card]->reset_timer, jiffies+CHECKRESET_TIME);
+		spin_unlock_irqrestore(&sc_adapter[card]->lock, flags);
 	}
 }
 
@@ -87,7 +88,7 @@ void check_reset(unsigned long data)
  * Must be very fast as this function runs in the context of
  * an interrupt handler.
  *
- * Send check adapter->phystat to see if the channels are up
+ * Send check sc_adapter->phystat to see if the channels are up
  * If they are, tell ISDN4Linux that the board is up. If not,
  * tell IADN4Linux that it is up. Always reset the timer to
  * fire again (endless loop).
@@ -97,31 +98,31 @@ void check_phystat(unsigned long data)
 	unsigned long flags;
 	int card = (unsigned int) data;
 
-	pr_debug("%s: Checking status...\n", adapter[card]->devicename);
+	pr_debug("%s: Checking status...\n", sc_adapter[card]->devicename);
 	/* 
 	 * check the results of the last PhyStat and change only if
 	 * has changed drastically
 	 */
-	if (adapter[card]->nphystat && !adapter[card]->phystat) {   /* All is well */
+	if (sc_adapter[card]->nphystat && !sc_adapter[card]->phystat) {   /* All is well */
 		pr_debug("PhyStat transition to RUN\n");
 		pr_info("%s: Switch contacted, transmitter enabled\n", 
-			adapter[card]->devicename);
+			sc_adapter[card]->devicename);
 		indicate_status(card, ISDN_STAT_RUN, 0, NULL);
 	}
-	else if (!adapter[card]->nphystat && adapter[card]->phystat) {   /* All is not well */
+	else if (!sc_adapter[card]->nphystat && sc_adapter[card]->phystat) {   /* All is not well */
 		pr_debug("PhyStat transition to STOP\n");
 		pr_info("%s: Switch connection lost, transmitter disabled\n", 
-			adapter[card]->devicename);
+			sc_adapter[card]->devicename);
 
 		indicate_status(card, ISDN_STAT_STOP, 0, NULL);
 	}
 
-	adapter[card]->phystat = adapter[card]->nphystat;
+	sc_adapter[card]->phystat = sc_adapter[card]->nphystat;
 
 	/* Reinitialize the timer */
-	spin_lock_irqsave(&adapter[card]->lock, flags);
-	mod_timer(&adapter[card]->stat_timer, jiffies+CHECKSTAT_TIME);
-	spin_unlock_irqrestore(&adapter[card]->lock, flags);
+	spin_lock_irqsave(&sc_adapter[card]->lock, flags);
+	mod_timer(&sc_adapter[card]->stat_timer, jiffies+CHECKSTAT_TIME);
+	spin_unlock_irqrestore(&sc_adapter[card]->lock, flags);
 
 	/* Send a new cePhyStatus message */
 	sendmessage(card, CEPID,ceReqTypePhy,ceReqClass2,
--- diff/drivers/isdn/tpam/Kconfig	2002-11-11 11:09:36.000000000 +0000
+++ source/drivers/isdn/tpam/Kconfig	2004-02-23 13:56:43.000000000 +0000
@@ -3,7 +3,7 @@
 #
 config ISDN_DRV_TPAM
 	tristate "Auvertech TurboPAM support (EXPERIMENTAL)"
-	depends on EXPERIMENTAL && ISDN && PCI
+	depends on EXPERIMENTAL && ISDN_I4L && PCI
 	help
 	  This enables support for the Auvertech TurboPAM ISDN-card.
 	  For running this card, additional firmware is necessary, which has
--- diff/drivers/macintosh/apm_emu.c	2003-06-30 10:07:21.000000000 +0100
+++ source/drivers/macintosh/apm_emu.c	2004-02-23 13:56:43.000000000 +0000
@@ -440,7 +440,7 @@ static int apm_emu_get_info(char *buf, c
 	char *		p = buf;
 	char		charging       = 0;
 	long		charge	       = -1;
-	long		current        = 0;
+	long		amperage       = 0;
 	unsigned long	btype          = 0;
 
 	ac_line_status = ((pmu_power_flags & PMU_PWR_AC_PRESENT) != 0);
@@ -453,7 +453,7 @@ static int apm_emu_get_info(char *buf, c
 			percentage += (pmu_batteries[i].charge * 100) /
 				pmu_batteries[i].max_charge;
 			charge += pmu_batteries[i].charge;
-			current += pmu_batteries[i].current;
+			amperage += pmu_batteries[i].amperage;
 			if (btype == 0)
 				btype = (pmu_batteries[i].flags & PMU_BATT_TYPE_MASK);
 			real_count++;
@@ -462,11 +462,11 @@ static int apm_emu_get_info(char *buf, c
 		}
 	}
 	if (real_count) {
-		if (current < 0) {
+		if (amperage < 0) {
 			if (btype == PMU_BATT_TYPE_SMART)
-				time_units = (charge * 59) / (current * -1);
+				time_units = (charge * 59) / (amperage * -1);
 			else
-				time_units = (charge * 16440) / (current * -60);
+				time_units = (charge * 16440) / (amperage * -60);
 		}
 		percentage /= real_count;
 		if (charging > 0) {
--- diff/drivers/macintosh/macserial.c	2003-09-30 15:46:14.000000000 +0100
+++ source/drivers/macintosh/macserial.c	2004-02-23 13:56:43.000000000 +0000
@@ -1777,47 +1777,65 @@ static int get_lsr_info(struct mac_seria
 	return put_user(status,value);
 }
 
-static int get_modem_info(struct mac_serial *info, unsigned int *value)
+static int rs_tiocmget(struct tty_struct *tty, struct file *file)
 {
+	struct mac_serial * info = (struct mac_serial *)tty->driver_data;
 	unsigned char control, status;
-	unsigned int result;
 	unsigned long flags;
 
+#ifdef CONFIG_KGDB
+	if (info->kgdb_channel)
+		return -ENODEV;
+#endif
+	if (serial_paranoia_check(info, tty->name, __FUNCTION__))
+		return -ENODEV;
+
+	if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) &&
+	    (cmd != TIOCSERCONFIG) && (cmd != TIOCSERGSTRUCT)) {
+		if (tty->flags & (1 << TTY_IO_ERROR))
+		    return -EIO;
+	}
+
 	spin_lock_irqsave(&info->lock, flags);
 	control = info->curregs[5];
 	status = read_zsreg(info->zs_channel, 0);
 	spin_unlock_irqrestore(&info->lock, flags);
-	result =  ((control & RTS) ? TIOCM_RTS: 0)
+	return    ((control & RTS) ? TIOCM_RTS: 0)
 		| ((control & DTR) ? TIOCM_DTR: 0)
 		| ((status  & DCD) ? TIOCM_CAR: 0)
 		| ((status  & CTS) ? 0: TIOCM_CTS);
-	return put_user(result,value);
 }
 
-static int set_modem_info(struct mac_serial *info, unsigned int cmd,
-			  unsigned int *value)
+static int rs_tiocmset(struct tty_struct *tty, struct file *file,
+		       unsigned int set, unsigned int clear)
 {
+	struct mac_serial * info = (struct mac_serial *)tty->driver_data;
 	unsigned int arg, bits;
 	unsigned long flags;
 
-	if (get_user(arg, value))
-		return -EFAULT;
-	bits = (arg & TIOCM_RTS? RTS: 0) + (arg & TIOCM_DTR? DTR: 0);
-	spin_lock_irqsave(&info->lock, flags);
-	switch (cmd) {
-	case TIOCMBIS:
-		info->curregs[5] |= bits;
-		break;
-	case TIOCMBIC:
-		info->curregs[5] &= ~bits;
-		break;
-	case TIOCMSET:
-		info->curregs[5] = (info->curregs[5] & ~(DTR | RTS)) | bits;
-		break;
-	default:
-		spin_unlock_irqrestore(&info->lock, flags);
-		return -EINVAL;
+#ifdef CONFIG_KGDB
+	if (info->kgdb_channel)
+		return -ENODEV;
+#endif
+	if (serial_paranoia_check(info, tty->name, __FUNCTION__))
+		return -ENODEV;
+
+	if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) &&
+	    (cmd != TIOCSERCONFIG) && (cmd != TIOCSERGSTRUCT)) {
+		if (tty->flags & (1 << TTY_IO_ERROR))
+		    return -EIO;
 	}
+
+	spin_lock_irqsave(&info->lock, flags);
+	if (set & TIOCM_RTS)
+		info->curregs[5] |= RTS;
+	if (set & TIOCM_DTR)
+		info->curregs[5] |= DTR;
+	if (clear & TIOCM_RTS)
+		info->curregs[5] &= ~RTS;
+	if (clear & TIOCM_DTR)
+		info->curregs[5] &= ~DTR;
+
 	info->pendregs[5] = info->curregs[5];
 	write_zsreg(info->zs_channel, 5, info->curregs[5]);
 	spin_unlock_irqrestore(&info->lock, flags);
@@ -1863,12 +1881,6 @@ static int rs_ioctl(struct tty_struct *t
 	}
 
 	switch (cmd) {
-		case TIOCMGET:
-			return get_modem_info(info, (unsigned int *) arg);
-		case TIOCMBIS:
-		case TIOCMBIC:
-		case TIOCMSET:
-			return set_modem_info(info, cmd, (unsigned int *) arg);
 		case TIOCGSERIAL:
 			return get_serial_info(info,
 					(struct serial_struct __user *) arg);
@@ -2488,6 +2500,8 @@ static struct tty_operations serial_ops 
 	.break_ctl = rs_break,
 	.wait_until_sent = rs_wait_until_sent,
 	.read_proc = macserial_read_proc,
+	.tiocmget = rs_tiocmget,
+	.tiocmset = rs_tiocmset,
 };
 
 static int macserial_init(void)
--- diff/drivers/macintosh/via-pmu.c	2004-02-18 08:54:09.000000000 +0000
+++ source/drivers/macintosh/via-pmu.c	2004-02-23 13:56:43.000000000 +0000
@@ -44,6 +44,7 @@
 #include <linux/interrupt.h>
 #include <linux/device.h>
 #include <linux/suspend.h>
+#include <linux/syscalls.h>
 #include <asm/prom.h>
 #include <asm/machdep.h>
 #include <asm/io.h>
@@ -649,7 +650,7 @@ done_battery_state_ohare(struct adb_requ
 	unsigned int bat_flags = PMU_BATT_TYPE_HOOPER;
 	long pcharge, charge, vb, vmax, lmax;
 	long vmax_charging, vmax_charged;
-	long current, voltage, time, max;
+	long amperage, voltage, time, max;
 	int mb = pmac_call_feature(PMAC_FTR_GET_MB_INFO,
 			NULL, PMAC_MB_INFO_MODEL, 0);
 
@@ -676,10 +677,10 @@ done_battery_state_ohare(struct adb_requ
 			bat_flags |= PMU_BATT_CHARGING;
 		vb = (req->reply[1] << 8) | req->reply[2];
 		voltage = (vb * 265 + 72665) / 10;
-		current = req->reply[5];
+		amperage = req->reply[5];
 		if ((req->reply[0] & 0x01) == 0) {
-			if (current > 200)
-				vb += ((current - 200) * 15)/100;
+			if (amperage > 200)
+				vb += ((amperage - 200) * 15)/100;
 		} else if (req->reply[0] & 0x02) {
 			vb = (vb * 97) / 100;
 			vmax = vmax_charging;
@@ -694,19 +695,19 @@ done_battery_state_ohare(struct adb_requ
 			if (pcharge < charge)
 				charge = pcharge;
 		}
-		if (current > 0)
-			time = (charge * 16440) / current;
+		if (amperage > 0)
+			time = (charge * 16440) / amperage;
 		else
 			time = 0;
 		max = 100;
-		current = -current;
+		amperage = -amperage;
 	} else
-		charge = max = current = voltage = time = 0;
+		charge = max = amperage = voltage = time = 0;
 
 	pmu_batteries[pmu_cur_battery].flags = bat_flags;
 	pmu_batteries[pmu_cur_battery].charge = charge;
 	pmu_batteries[pmu_cur_battery].max_charge = max;
-	pmu_batteries[pmu_cur_battery].current = current;
+	pmu_batteries[pmu_cur_battery].amperage = amperage;
 	pmu_batteries[pmu_cur_battery].voltage = voltage;
 	pmu_batteries[pmu_cur_battery].time_remaining = time;
 }
@@ -734,7 +735,7 @@ done_battery_state_smart(struct adb_requ
 	 */
 	 
 	unsigned int bat_flags = PMU_BATT_TYPE_SMART;
-	int current;
+	int amperage;
 	unsigned int capa, max, voltage;
 	
 	if (req->reply[1] & 0x01)
@@ -749,12 +750,12 @@ done_battery_state_smart(struct adb_requ
 			case 3:
 			case 4: capa = req->reply[2];
 				max = req->reply[3];
-				current = *((signed char *)&req->reply[4]);
+				amperage = *((signed char *)&req->reply[4]);
 				voltage = req->reply[5];
 				break;
 			case 5: capa = (req->reply[2] << 8) | req->reply[3];
 				max = (req->reply[4] << 8) | req->reply[5];
-				current = *((signed short *)&req->reply[6]);
+				amperage = *((signed short *)&req->reply[6]);
 				voltage = (req->reply[8] << 8) | req->reply[9];
 				break;
 			default:
@@ -763,23 +764,23 @@ done_battery_state_smart(struct adb_requ
 				break;
 		}
 	} else
-		capa = max = current = voltage = 0;
+		capa = max = amperage = voltage = 0;
 
-	if ((req->reply[1] & 0x01) && (current > 0))
+	if ((req->reply[1] & 0x01) && (amperage > 0))
 		bat_flags |= PMU_BATT_CHARGING;
 
 	pmu_batteries[pmu_cur_battery].flags = bat_flags;
 	pmu_batteries[pmu_cur_battery].charge = capa;
 	pmu_batteries[pmu_cur_battery].max_charge = max;
-	pmu_batteries[pmu_cur_battery].current = current;
+	pmu_batteries[pmu_cur_battery].amperage = amperage;
 	pmu_batteries[pmu_cur_battery].voltage = voltage;
-	if (current) {
-		if ((req->reply[1] & 0x01) && (current > 0))
+	if (amperage) {
+		if ((req->reply[1] & 0x01) && (amperage > 0))
 			pmu_batteries[pmu_cur_battery].time_remaining
-				= ((max-capa) * 3600) / current;
+				= ((max-capa) * 3600) / amperage;
 		else
 			pmu_batteries[pmu_cur_battery].time_remaining
-				= (capa * 3600) / (-current);
+				= (capa * 3600) / (-amperage);
 	} else
 		pmu_batteries[pmu_cur_battery].time_remaining = 0;
 
@@ -861,7 +862,7 @@ proc_get_batt(char *page, char **start, 
 	p += sprintf(p, "max_charge : %d\n",
 		pmu_batteries[batnum].max_charge);
 	p += sprintf(p, "current    : %d\n",
-		pmu_batteries[batnum].current);
+		pmu_batteries[batnum].amperage);
 	p += sprintf(p, "voltage    : %d\n",
 		pmu_batteries[batnum].voltage);
 	p += sprintf(p, "time rem.  : %d\n",
@@ -2292,8 +2293,6 @@ restore_via_state(void)
 	out_8(&via[IER], IER_SET | SR_INT | CB1_INT);
 }
 
-extern long sys_sync(void);
-
 static int __pmac
 pmac_suspend_devices(void)
 {
--- diff/drivers/md/Kconfig	2004-02-09 10:36:10.000000000 +0000
+++ source/drivers/md/Kconfig	2004-02-23 13:56:43.000000000 +0000
@@ -162,13 +162,28 @@ config BLK_DEV_DM
 
 	  If unsure, say N.
 
-config DM_IOCTL_V4
-	bool "ioctl interface version 4"
-	depends on BLK_DEV_DM
-	default y
+config DM_CRYPT
+	tristate "Crypt target support"
+	depends on BLK_DEV_DM && EXPERIMENTAL
+	select CRYPTO
 	---help---
-	  Recent tools use a new version of the ioctl interface, only
-          select this option if you intend using such tools.
+	  This device-mapper target allows you to create a device that
+	  transparently encrypts the data on it. You'll need to activate
+	  the ciphers you're going to use in the cryptoapi configuration.
 
-endmenu
+	  Information on how to use dm-crypt can be found on
+
+	  http://www.saout.de/misc/dm-crypt/
 
+	  To compile this code as a module, choose M here: the module will
+	  be called dm-crypt.
+
+	  If unsure, say N.
+
+config DM_MULTIPATH
+       tristate "Multipath target (EXPERIMENTAL)"
+       depends on BLK_DEV_DM && EXPERIMENTAL
+       ---help---
+         Allow volume managers to support multipath hardware.
+
+endmenu
--- diff/drivers/md/Makefile	2004-02-18 08:54:09.000000000 +0000
+++ source/drivers/md/Makefile	2004-02-23 13:56:43.000000000 +0000
@@ -4,6 +4,7 @@
 
 dm-mod-objs	:= dm.o dm-table.o dm-target.o dm-linear.o dm-stripe.o \
 		   dm-ioctl.o
+dm-multipath-objs := dm-path-selector.o dm-mpath.o
 raid6-objs	:= raid6main.o raid6algos.o raid6recov.o raid6tables.o \
 		   raid6int1.o raid6int2.o raid6int4.o \
 		   raid6int8.o raid6int16.o raid6int32.o \
@@ -23,6 +24,8 @@ obj-$(CONFIG_MD_RAID6)		+= raid6.o xor.o
 obj-$(CONFIG_MD_MULTIPATH)	+= multipath.o
 obj-$(CONFIG_BLK_DEV_MD)	+= md.o
 obj-$(CONFIG_BLK_DEV_DM)	+= dm-mod.o
+obj-$(CONFIG_DM_CRYPT)		+= dm-crypt.o
+obj-$(CONFIG_DM_MULTIPATH)	+= dm-multipath.o
 
 quiet_cmd_unroll = UNROLL  $@
       cmd_unroll = $(PERL) $(srctree)/$(src)/unroll.pl $(UNROLL) \
--- diff/drivers/md/dm-ioctl.c	2003-08-20 14:16:09.000000000 +0100
+++ source/drivers/md/dm-ioctl.c	2004-02-23 13:56:43.000000000 +0000
@@ -1,13 +1,1343 @@
 /*
- * Copyright (C) 2003 Sistina Software (UK) Limited.
+ * Copyright (C) 2001, 2002 Sistina Software (UK) Limited.
  *
  * This file is released under the GPL.
  */
 
+#include "dm.h"
+
+#include <linux/module.h>
+#include <linux/vmalloc.h>
+#include <linux/miscdevice.h>
+#include <linux/init.h>
+#include <linux/wait.h>
+#include <linux/slab.h>
+#include <linux/devfs_fs_kernel.h>
 #include <linux/dm-ioctl.h>
 
-#ifdef CONFIG_DM_IOCTL_V4
-#include "dm-ioctl-v4.c"
-#else
-#include "dm-ioctl-v1.c"
-#endif
+#include <asm/uaccess.h>
+
+#define DM_DRIVER_EMAIL "dm@uk.sistina.com"
+
+/*-----------------------------------------------------------------
+ * The ioctl interface needs to be able to look up devices by
+ * name or uuid.
+ *---------------------------------------------------------------*/
+struct hash_cell {
+	struct list_head name_list;
+	struct list_head uuid_list;
+
+	char *name;
+	char *uuid;
+	struct mapped_device *md;
+	struct dm_table *new_map;
+};
+
+struct vers_iter {
+    size_t param_size;
+    struct dm_target_versions *vers, *old_vers;
+    char *end;
+    uint32_t flags;
+};
+
+
+#define NUM_BUCKETS 64
+#define MASK_BUCKETS (NUM_BUCKETS - 1)
+static struct list_head _name_buckets[NUM_BUCKETS];
+static struct list_head _uuid_buckets[NUM_BUCKETS];
+
+void dm_hash_remove_all(void);
+
+/*
+ * Guards access to both hash tables.
+ */
+static DECLARE_RWSEM(_hash_lock);
+
+static void init_buckets(struct list_head *buckets)
+{
+	unsigned int i;
+
+	for (i = 0; i < NUM_BUCKETS; i++)
+		INIT_LIST_HEAD(buckets + i);
+}
+
+int dm_hash_init(void)
+{
+	init_buckets(_name_buckets);
+	init_buckets(_uuid_buckets);
+	devfs_mk_dir(DM_DIR);
+	return 0;
+}
+
+void dm_hash_exit(void)
+{
+	dm_hash_remove_all();
+	devfs_remove(DM_DIR);
+}
+
+/*-----------------------------------------------------------------
+ * Hash function:
+ * We're not really concerned with the str hash function being
+ * fast since it's only used by the ioctl interface.
+ *---------------------------------------------------------------*/
+static unsigned int hash_str(const char *str)
+{
+	const unsigned int hash_mult = 2654435387U;
+	unsigned int h = 0;
+
+	while (*str)
+		h = (h + (unsigned int) *str++) * hash_mult;
+
+	return h & MASK_BUCKETS;
+}
+
+/*-----------------------------------------------------------------
+ * Code for looking up a device by name
+ *---------------------------------------------------------------*/
+static struct hash_cell *__get_name_cell(const char *str)
+{
+	struct hash_cell *hc;
+	unsigned int h = hash_str(str);
+
+	list_for_each_entry (hc, _name_buckets + h, name_list)
+		if (!strcmp(hc->name, str))
+			return hc;
+
+	return NULL;
+}
+
+static struct hash_cell *__get_uuid_cell(const char *str)
+{
+	struct hash_cell *hc;
+	unsigned int h = hash_str(str);
+
+	list_for_each_entry (hc, _uuid_buckets + h, uuid_list)
+		if (!strcmp(hc->uuid, str))
+			return hc;
+
+	return NULL;
+}
+
+/*-----------------------------------------------------------------
+ * Inserting, removing and renaming a device.
+ *---------------------------------------------------------------*/
+static inline char *kstrdup(const char *str)
+{
+	char *r = kmalloc(strlen(str) + 1, GFP_KERNEL);
+	if (r)
+		strcpy(r, str);
+	return r;
+}
+
+static struct hash_cell *alloc_cell(const char *name, const char *uuid,
+				    struct mapped_device *md)
+{
+	struct hash_cell *hc;
+
+	hc = kmalloc(sizeof(*hc), GFP_KERNEL);
+	if (!hc)
+		return NULL;
+
+	hc->name = kstrdup(name);
+	if (!hc->name) {
+		kfree(hc);
+		return NULL;
+	}
+
+	if (!uuid)
+		hc->uuid = NULL;
+
+	else {
+		hc->uuid = kstrdup(uuid);
+		if (!hc->uuid) {
+			kfree(hc->name);
+			kfree(hc);
+			return NULL;
+		}
+	}
+
+	INIT_LIST_HEAD(&hc->name_list);
+	INIT_LIST_HEAD(&hc->uuid_list);
+	hc->md = md;
+	hc->new_map = NULL;
+	return hc;
+}
+
+static void free_cell(struct hash_cell *hc)
+{
+	if (hc) {
+		kfree(hc->name);
+		kfree(hc->uuid);
+		kfree(hc);
+	}
+}
+
+/*
+ * devfs stuff.
+ */
+static int register_with_devfs(struct hash_cell *hc)
+{
+	struct gendisk *disk = dm_disk(hc->md);
+
+	devfs_mk_bdev(MKDEV(disk->major, disk->first_minor),
+		      S_IFBLK | S_IRUSR | S_IWUSR | S_IRGRP,
+		      DM_DIR "/%s", hc->name);
+	return 0;
+}
+
+static int unregister_with_devfs(struct hash_cell *hc)
+{
+	devfs_remove(DM_DIR"/%s", hc->name);
+	return 0;
+}
+
+/*
+ * The kdev_t and uuid of a device can never change once it is
+ * initially inserted.
+ */
+int dm_hash_insert(const char *name, const char *uuid, struct mapped_device *md)
+{
+	struct hash_cell *cell;
+
+	/*
+	 * Allocate the new cells.
+	 */
+	cell = alloc_cell(name, uuid, md);
+	if (!cell)
+		return -ENOMEM;
+
+	/*
+	 * Insert the cell into both hash tables.
+	 */
+	down_write(&_hash_lock);
+	if (__get_name_cell(name))
+		goto bad;
+
+	list_add(&cell->name_list, _name_buckets + hash_str(name));
+
+	if (uuid) {
+		if (__get_uuid_cell(uuid)) {
+			list_del(&cell->name_list);
+			goto bad;
+		}
+		list_add(&cell->uuid_list, _uuid_buckets + hash_str(uuid));
+	}
+	register_with_devfs(cell);
+	dm_get(md);
+	up_write(&_hash_lock);
+
+	return 0;
+
+ bad:
+	up_write(&_hash_lock);
+	free_cell(cell);
+	return -EBUSY;
+}
+
+void __hash_remove(struct hash_cell *hc)
+{
+	/* remove from the dev hash */
+	list_del(&hc->uuid_list);
+	list_del(&hc->name_list);
+	unregister_with_devfs(hc);
+	dm_put(hc->md);
+	if (hc->new_map)
+		dm_table_put(hc->new_map);
+	free_cell(hc);
+}
+
+void dm_hash_remove_all(void)
+{
+	int i;
+	struct hash_cell *hc;
+	struct list_head *tmp, *n;
+
+	down_write(&_hash_lock);
+	for (i = 0; i < NUM_BUCKETS; i++) {
+		list_for_each_safe (tmp, n, _name_buckets + i) {
+			hc = list_entry(tmp, struct hash_cell, name_list);
+			__hash_remove(hc);
+		}
+	}
+	up_write(&_hash_lock);
+}
+
+int dm_hash_rename(const char *old, const char *new)
+{
+	char *new_name, *old_name;
+	struct hash_cell *hc;
+
+	/*
+	 * duplicate new.
+	 */
+	new_name = kstrdup(new);
+	if (!new_name)
+		return -ENOMEM;
+
+	down_write(&_hash_lock);
+
+	/*
+	 * Is new free ?
+	 */
+	hc = __get_name_cell(new);
+	if (hc) {
+		DMWARN("asked to rename to an already existing name %s -> %s",
+		       old, new);
+		up_write(&_hash_lock);
+		kfree(new_name);
+		return -EBUSY;
+	}
+
+	/*
+	 * Is there such a device as 'old' ?
+	 */
+	hc = __get_name_cell(old);
+	if (!hc) {
+		DMWARN("asked to rename a non existent device %s -> %s",
+		       old, new);
+		up_write(&_hash_lock);
+		kfree(new_name);
+		return -ENXIO;
+	}
+
+	/*
+	 * rename and move the name cell.
+	 */
+	unregister_with_devfs(hc);
+
+	list_del(&hc->name_list);
+	old_name = hc->name;
+	hc->name = new_name;
+	list_add(&hc->name_list, _name_buckets + hash_str(new_name));
+
+	/* rename the device node in devfs */
+	register_with_devfs(hc);
+
+	up_write(&_hash_lock);
+	kfree(old_name);
+	return 0;
+}
+
+/*-----------------------------------------------------------------
+ * Implementation of the ioctl commands
+ *---------------------------------------------------------------*/
+/*
+ * All the ioctl commands get dispatched to functions with this
+ * prototype.
+ */
+typedef int (*ioctl_fn)(struct dm_ioctl *param, size_t param_size);
+
+static int remove_all(struct dm_ioctl *param, size_t param_size)
+{
+	dm_hash_remove_all();
+	param->data_size = 0;
+	return 0;
+}
+
+/*
+ * Round up the ptr to an 8-byte boundary.
+ */
+#define ALIGN_MASK 7
+static inline void *align_ptr(void *ptr)
+{
+	return (void *) (((size_t) (ptr + ALIGN_MASK)) & ~ALIGN_MASK);
+}
+
+/*
+ * Retrieves the data payload buffer from an already allocated
+ * struct dm_ioctl.
+ */
+static void *get_result_buffer(struct dm_ioctl *param, size_t param_size,
+			       size_t *len)
+{
+	param->data_start = align_ptr(param + 1) - (void *) param;
+
+	if (param->data_start < param_size)
+		*len = param_size - param->data_start;
+	else
+		*len = 0;
+
+	return ((void *) param) + param->data_start;
+}
+
+static int list_devices(struct dm_ioctl *param, size_t param_size)
+{
+	unsigned int i;
+	struct hash_cell *hc;
+	size_t len, needed = 0;
+	struct gendisk *disk;
+	struct dm_name_list *nl, *old_nl = NULL;
+
+	down_write(&_hash_lock);
+
+	/*
+	 * Loop through all the devices working out how much
+	 * space we need.
+	 */
+	for (i = 0; i < NUM_BUCKETS; i++) {
+		list_for_each_entry (hc, _name_buckets + i, name_list) {
+			needed += sizeof(struct dm_name_list);
+			needed += strlen(hc->name);
+			needed += ALIGN_MASK;
+		}
+	}
+
+	/*
+	 * Grab our output buffer.
+	 */
+	nl = get_result_buffer(param, param_size, &len);
+	if (len < needed) {
+		param->flags |= DM_BUFFER_FULL_FLAG;
+		goto out;
+	}
+	param->data_size = param->data_start + needed;
+
+	nl->dev = 0;	/* Flags no data */
+
+	/*
+	 * Now loop through filling out the names.
+	 */
+	for (i = 0; i < NUM_BUCKETS; i++) {
+		list_for_each_entry (hc, _name_buckets + i, name_list) {
+			if (old_nl)
+				old_nl->next = (uint32_t) ((void *) nl -
+							   (void *) old_nl);
+			disk = dm_disk(hc->md);
+			nl->dev = huge_encode_dev(MKDEV(disk->major, disk->first_minor));
+			nl->next = 0;
+			strcpy(nl->name, hc->name);
+
+			old_nl = nl;
+			nl = align_ptr(((void *) ++nl) + strlen(hc->name) + 1);
+		}
+	}
+
+ out:
+	up_write(&_hash_lock);
+	return 0;
+}
+
+static void list_version_get_needed(struct target_type *tt, void *param)
+{
+    int *needed = param;
+
+    *needed += strlen(tt->name);
+    *needed += sizeof(tt->version);
+    *needed += ALIGN_MASK;
+}
+
+static void list_version_get_info(struct target_type *tt, void *param)
+{
+    struct vers_iter *info = param;
+
+    /* Check space - it might have changed since the first iteration */
+    if ((char *)info->vers + sizeof(tt->version) + strlen(tt->name) + 1 >
+	info->end) {
+
+	info->flags = DM_BUFFER_FULL_FLAG;
+	return;
+    }
+
+    if (info->old_vers)
+	info->old_vers->next = (uint32_t) ((void *)info->vers -
+					   (void *)info->old_vers);
+    info->vers->version[0] = tt->version[0];
+    info->vers->version[1] = tt->version[1];
+    info->vers->version[2] = tt->version[2];
+    info->vers->next = 0;
+    strcpy(info->vers->name, tt->name);
+
+    info->old_vers = info->vers;
+    info->vers = align_ptr(((void *) ++info->vers) + strlen(tt->name) + 1);
+}
+
+static int list_versions(struct dm_ioctl *param, size_t param_size)
+{
+	size_t len, needed = 0;
+	struct dm_target_versions *vers;
+	struct vers_iter iter_info;
+
+	/*
+	 * Loop through all the devices working out how much
+	 * space we need.
+	 */
+	dm_target_iterate(list_version_get_needed, &needed);
+
+	/*
+	 * Grab our output buffer.
+	 */
+	vers = get_result_buffer(param, param_size, &len);
+	if (len < needed) {
+		param->flags |= DM_BUFFER_FULL_FLAG;
+		goto out;
+	}
+	param->data_size = param->data_start + needed;
+
+	iter_info.param_size = param_size;
+	iter_info.old_vers = NULL;
+	iter_info.vers = vers;
+	iter_info.flags = 0;
+	iter_info.end = (char *)vers+len;
+
+	/*
+	 * Now loop through filling out the names & versions.
+	 */
+	dm_target_iterate(list_version_get_info, &iter_info);
+	param->flags |= iter_info.flags;
+
+ out:
+	return 0;
+}
+
+
+
+static int check_name(const char *name)
+{
+	if (strchr(name, '/')) {
+		DMWARN("invalid device name");
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+/*
+ * Fills in a dm_ioctl structure, ready for sending back to
+ * userland.
+ */
+static int __dev_status(struct mapped_device *md, struct dm_ioctl *param)
+{
+	struct gendisk *disk = dm_disk(md);
+	struct dm_table *table;
+	struct block_device *bdev;
+
+	param->flags &= ~(DM_SUSPEND_FLAG | DM_READONLY_FLAG |
+			  DM_ACTIVE_PRESENT_FLAG);
+
+	if (dm_suspended(md))
+		param->flags |= DM_SUSPEND_FLAG;
+
+	bdev = bdget_disk(disk, 0);
+	if (!bdev)
+		return -ENXIO;
+
+	param->dev = huge_encode_dev(MKDEV(disk->major, disk->first_minor));
+
+	/*
+	 * Yes, this will be out of date by the time it gets back
+	 * to userland, but it is still very useful ofr
+	 * debugging.
+	 */
+	param->open_count = bdev->bd_openers;
+	bdput(bdev);
+
+	if (disk->policy)
+		param->flags |= DM_READONLY_FLAG;
+
+	param->event_nr = dm_get_event_nr(md);
+
+	table = dm_get_table(md);
+	if (table) {
+		param->flags |= DM_ACTIVE_PRESENT_FLAG;
+		param->target_count = dm_table_get_num_targets(table);
+		dm_table_put(table);
+	} else
+		param->target_count = 0;
+
+	return 0;
+}
+
+static int dev_create(struct dm_ioctl *param, size_t param_size)
+{
+	int r;
+	struct mapped_device *md;
+
+	r = check_name(param->name);
+	if (r)
+		return r;
+
+	if (param->flags & DM_PERSISTENT_DEV_FLAG)
+		r = dm_create_with_minor(MINOR(huge_decode_dev(param->dev)), &md);
+	else
+		r = dm_create(&md);
+
+	if (r)
+		return r;
+
+	r = dm_hash_insert(param->name, *param->uuid ? param->uuid : NULL, md);
+	if (r) {
+		dm_put(md);
+		return r;
+	}
+
+	param->flags &= ~DM_INACTIVE_PRESENT_FLAG;
+
+	r = __dev_status(md, param);
+	dm_put(md);
+
+	return r;
+}
+
+/*
+ * Always use UUID for lookups if it's present, otherwise use name.
+ */
+static inline struct hash_cell *__find_device_hash_cell(struct dm_ioctl *param)
+{
+	return *param->uuid ?
+	    __get_uuid_cell(param->uuid) : __get_name_cell(param->name);
+}
+
+static inline struct mapped_device *find_device(struct dm_ioctl *param)
+{
+	struct hash_cell *hc;
+	struct mapped_device *md = NULL;
+
+	down_read(&_hash_lock);
+	hc = __find_device_hash_cell(param);
+	if (hc) {
+		md = hc->md;
+
+		/*
+		 * Sneakily write in both the name and the uuid
+		 * while we have the cell.
+		 */
+		strncpy(param->name, hc->name, sizeof(param->name));
+		if (hc->uuid)
+			strncpy(param->uuid, hc->uuid, sizeof(param->uuid)-1);
+		else
+			param->uuid[0] = '\0';
+
+		if (hc->new_map)
+			param->flags |= DM_INACTIVE_PRESENT_FLAG;
+		else
+			param->flags &= ~DM_INACTIVE_PRESENT_FLAG;
+
+		dm_get(md);
+	}
+	up_read(&_hash_lock);
+
+	return md;
+}
+
+static int dev_remove(struct dm_ioctl *param, size_t param_size)
+{
+	struct hash_cell *hc;
+
+	down_write(&_hash_lock);
+	hc = __find_device_hash_cell(param);
+
+	if (!hc) {
+		DMWARN("device doesn't appear to be in the dev hash table.");
+		up_write(&_hash_lock);
+		return -ENXIO;
+	}
+
+	__hash_remove(hc);
+	up_write(&_hash_lock);
+	param->data_size = 0;
+	return 0;
+}
+
+/*
+ * Check a string doesn't overrun the chunk of
+ * memory we copied from userland.
+ */
+static int invalid_str(char *str, void *end)
+{
+	while ((void *) str < end)
+		if (!*str++)
+			return 0;
+
+	return -EINVAL;
+}
+
+static int dev_rename(struct dm_ioctl *param, size_t param_size)
+{
+	int r;
+	char *new_name = (char *) param + param->data_start;
+
+	if (new_name < (char *) (param + 1) ||
+	    invalid_str(new_name, (void *) param + param_size)) {
+		DMWARN("Invalid new logical volume name supplied.");
+		return -EINVAL;
+	}
+
+	r = check_name(new_name);
+	if (r)
+		return r;
+
+	param->data_size = 0;
+	return dm_hash_rename(param->name, new_name);
+}
+
+static int do_suspend(struct dm_ioctl *param)
+{
+	int r = 0;
+	struct mapped_device *md;
+
+	md = find_device(param);
+	if (!md)
+		return -ENXIO;
+
+	if (!dm_suspended(md))
+		r = dm_suspend(md);
+
+	if (!r)
+		r = __dev_status(md, param);
+
+	dm_put(md);
+	return r;
+}
+
+static int do_resume(struct dm_ioctl *param)
+{
+	int r = 0;
+	struct hash_cell *hc;
+	struct mapped_device *md;
+	struct dm_table *new_map;
+
+	down_write(&_hash_lock);
+
+	hc = __find_device_hash_cell(param);
+	if (!hc) {
+		DMWARN("device doesn't appear to be in the dev hash table.");
+		up_write(&_hash_lock);
+		return -ENXIO;
+	}
+
+	md = hc->md;
+	dm_get(md);
+
+	new_map = hc->new_map;
+	hc->new_map = NULL;
+	param->flags &= ~DM_INACTIVE_PRESENT_FLAG;
+
+	up_write(&_hash_lock);
+
+	/* Do we need to load a new map ? */
+	if (new_map) {
+		/* Suspend if it isn't already suspended */
+		if (!dm_suspended(md))
+			dm_suspend(md);
+
+		r = dm_swap_table(md, new_map);
+		if (r) {
+			dm_put(md);
+			dm_table_put(new_map);
+			return r;
+		}
+
+		if (dm_table_get_mode(new_map) & FMODE_WRITE)
+			set_disk_ro(dm_disk(md), 0);
+		else
+			set_disk_ro(dm_disk(md), 1);
+
+		dm_table_put(new_map);
+	}
+
+	if (dm_suspended(md))
+		r = dm_resume(md);
+
+	if (!r)
+		r = __dev_status(md, param);
+
+	dm_put(md);
+	return r;
+}
+
+/*
+ * Set or unset the suspension state of a device.
+ * If the device already is in the requested state we just return its status.
+ */
+static int dev_suspend(struct dm_ioctl *param, size_t param_size)
+{
+	if (param->flags & DM_SUSPEND_FLAG)
+		return do_suspend(param);
+
+	return do_resume(param);
+}
+
+/*
+ * Copies device info back to user space, used by
+ * the create and info ioctls.
+ */
+static int dev_status(struct dm_ioctl *param, size_t param_size)
+{
+	int r;
+	struct mapped_device *md;
+
+	md = find_device(param);
+	if (!md)
+		return -ENXIO;
+
+	r = __dev_status(md, param);
+	dm_put(md);
+	return r;
+}
+
+/*
+ * Build up the status struct for each target
+ */
+static void retrieve_status(struct dm_table *table,
+			    struct dm_ioctl *param, size_t param_size)
+{
+	unsigned int i, num_targets;
+	struct dm_target_spec *spec;
+	char *outbuf, *outptr;
+	status_type_t type;
+	size_t remaining, len, used = 0;
+
+	outptr = outbuf = get_result_buffer(param, param_size, &len);
+
+	if (param->flags & DM_STATUS_TABLE_FLAG)
+		type = STATUSTYPE_TABLE;
+	else
+		type = STATUSTYPE_INFO;
+
+	/* Get all the target info */
+	num_targets = dm_table_get_num_targets(table);
+	for (i = 0; i < num_targets; i++) {
+		struct dm_target *ti = dm_table_get_target(table, i);
+
+		remaining = len - (outptr - outbuf);
+		if (remaining < sizeof(struct dm_target_spec)) {
+			param->flags |= DM_BUFFER_FULL_FLAG;
+			break;
+		}
+
+		spec = (struct dm_target_spec *) outptr;
+
+		spec->status = 0;
+		spec->sector_start = ti->begin;
+		spec->length = ti->len;
+		strncpy(spec->target_type, ti->type->name,
+			sizeof(spec->target_type));
+
+		outptr += sizeof(struct dm_target_spec);
+		remaining = len - (outptr - outbuf);
+
+		/* Get the status/table string from the target driver */
+		if (ti->type->status) {
+			if (ti->type->status(ti, type, outptr, remaining)) {
+				param->flags |= DM_BUFFER_FULL_FLAG;
+				break;
+			}
+		} else
+			outptr[0] = '\0';
+
+		outptr += strlen(outptr) + 1;
+		used = param->data_start + (outptr - outbuf);
+
+		align_ptr(outptr);
+		spec->next = outptr - outbuf;
+	}
+
+	if (used)
+		param->data_size = used;
+
+	param->target_count = num_targets;
+}
+
+/*
+ * Wait for a device to report an event
+ */
+static int dev_wait(struct dm_ioctl *param, size_t param_size)
+{
+	int r;
+	struct mapped_device *md;
+	struct dm_table *table;
+	DECLARE_WAITQUEUE(wq, current);
+
+	md = find_device(param);
+	if (!md)
+		return -ENXIO;
+
+	/*
+	 * Wait for a notification event
+	 */
+	set_current_state(TASK_INTERRUPTIBLE);
+	if (!dm_add_wait_queue(md, &wq, param->event_nr)) {
+		schedule();
+		dm_remove_wait_queue(md, &wq);
+	}
+ 	set_current_state(TASK_RUNNING);
+
+	/*
+	 * The userland program is going to want to know what
+	 * changed to trigger the event, so we may as well tell
+	 * him and save an ioctl.
+	 */
+	r = __dev_status(md, param);
+	if (r)
+		goto out;
+
+	table = dm_get_table(md);
+	if (table) {
+		retrieve_status(table, param, param_size);
+		dm_table_put(table);
+	}
+
+ out:
+	dm_put(md);
+	return r;
+}
+
+static inline int get_mode(struct dm_ioctl *param)
+{
+	int mode = FMODE_READ | FMODE_WRITE;
+
+	if (param->flags & DM_READONLY_FLAG)
+		mode = FMODE_READ;
+
+	return mode;
+}
+
+static int next_target(struct dm_target_spec *last, uint32_t next, void *end,
+		       struct dm_target_spec **spec, char **target_params)
+{
+	*spec = (struct dm_target_spec *) ((unsigned char *) last + next);
+	*target_params = (char *) (*spec + 1);
+
+	if (*spec < (last + 1))
+		return -EINVAL;
+
+	return invalid_str(*target_params, end);
+}
+
+static int populate_table(struct dm_table *table,
+			  struct dm_ioctl *param, size_t param_size)
+{
+	int r;
+	unsigned int i = 0;
+	struct dm_target_spec *spec = (struct dm_target_spec *) param;
+	uint32_t next = param->data_start;
+	void *end = (void *) param + param_size;
+	char *target_params;
+
+	if (!param->target_count) {
+		DMWARN("populate_table: no targets specified");
+		return -EINVAL;
+	}
+
+	for (i = 0; i < param->target_count; i++) {
+
+		r = next_target(spec, next, end, &spec, &target_params);
+		if (r) {
+			DMWARN("unable to find target");
+			return r;
+		}
+
+		r = dm_table_add_target(table, spec->target_type,
+					(sector_t) spec->sector_start,
+					(sector_t) spec->length,
+					target_params);
+		if (r) {
+			DMWARN("error adding target to table");
+			return r;
+		}
+
+		next = spec->next;
+	}
+
+	return dm_table_complete(table);
+}
+
+static int table_load(struct dm_ioctl *param, size_t param_size)
+{
+	int r;
+	struct hash_cell *hc;
+	struct dm_table *t;
+
+	r = dm_table_create(&t, get_mode(param), param->target_count);
+	if (r)
+		return r;
+
+	r = populate_table(t, param, param_size);
+	if (r) {
+		dm_table_put(t);
+		return r;
+	}
+
+	down_write(&_hash_lock);
+	hc = __find_device_hash_cell(param);
+	if (!hc) {
+		DMWARN("device doesn't appear to be in the dev hash table.");
+		up_write(&_hash_lock);
+		return -ENXIO;
+	}
+
+	if (hc->new_map)
+		dm_table_put(hc->new_map);
+	hc->new_map = t;
+	param->flags |= DM_INACTIVE_PRESENT_FLAG;
+
+	r = __dev_status(hc->md, param);
+	up_write(&_hash_lock);
+	return r;
+}
+
+static int table_clear(struct dm_ioctl *param, size_t param_size)
+{
+	int r;
+	struct hash_cell *hc;
+
+	down_write(&_hash_lock);
+
+	hc = __find_device_hash_cell(param);
+	if (!hc) {
+		DMWARN("device doesn't appear to be in the dev hash table.");
+		up_write(&_hash_lock);
+		return -ENXIO;
+	}
+
+	if (hc->new_map) {
+		dm_table_put(hc->new_map);
+		hc->new_map = NULL;
+	}
+
+	param->flags &= ~DM_INACTIVE_PRESENT_FLAG;
+
+	r = __dev_status(hc->md, param);
+	up_write(&_hash_lock);
+	return r;
+}
+
+/*
+ * Retrieves a list of devices used by a particular dm device.
+ */
+static void retrieve_deps(struct dm_table *table,
+			  struct dm_ioctl *param, size_t param_size)
+{
+	unsigned int count = 0;
+	struct list_head *tmp;
+	size_t len, needed;
+	struct dm_dev *dd;
+	struct dm_target_deps *deps;
+
+	deps = get_result_buffer(param, param_size, &len);
+
+	/*
+	 * Count the devices.
+	 */
+	list_for_each (tmp, dm_table_get_devices(table))
+		count++;
+
+	/*
+	 * Check we have enough space.
+	 */
+	needed = sizeof(*deps) + (sizeof(*deps->dev) * count);
+	if (len < needed) {
+		param->flags |= DM_BUFFER_FULL_FLAG;
+		return;
+	}
+
+	/*
+	 * Fill in the devices.
+	 */
+	deps->count = count;
+	count = 0;
+	list_for_each_entry (dd, dm_table_get_devices(table), list)
+		deps->dev[count++] = huge_encode_dev(dd->bdev->bd_dev);
+
+	param->data_size = param->data_start + needed;
+}
+
+static int table_deps(struct dm_ioctl *param, size_t param_size)
+{
+	int r = 0;
+	struct mapped_device *md;
+	struct dm_table *table;
+
+	md = find_device(param);
+	if (!md)
+		return -ENXIO;
+
+	r = __dev_status(md, param);
+	if (r)
+		goto out;
+
+	table = dm_get_table(md);
+	if (table) {
+		retrieve_deps(table, param, param_size);
+		dm_table_put(table);
+	}
+
+ out:
+	dm_put(md);
+	return r;
+}
+
+/*
+ * Return the status of a device as a text string for each
+ * target.
+ */
+static int table_status(struct dm_ioctl *param, size_t param_size)
+{
+	int r;
+	struct mapped_device *md;
+	struct dm_table *table;
+
+	md = find_device(param);
+	if (!md)
+		return -ENXIO;
+
+	r = __dev_status(md, param);
+	if (r)
+		goto out;
+
+	table = dm_get_table(md);
+	if (table) {
+		retrieve_status(table, param, param_size);
+		dm_table_put(table);
+	}
+
+ out:
+	dm_put(md);
+	return r;
+}
+
+/*-----------------------------------------------------------------
+ * Implementation of open/close/ioctl on the special char
+ * device.
+ *---------------------------------------------------------------*/
+static ioctl_fn lookup_ioctl(unsigned int cmd)
+{
+	static struct {
+		int cmd;
+		ioctl_fn fn;
+	} _ioctls[] = {
+		{DM_VERSION_CMD, NULL},	/* version is dealt with elsewhere */
+		{DM_REMOVE_ALL_CMD, remove_all},
+		{DM_LIST_DEVICES_CMD, list_devices},
+
+		{DM_DEV_CREATE_CMD, dev_create},
+		{DM_DEV_REMOVE_CMD, dev_remove},
+		{DM_DEV_RENAME_CMD, dev_rename},
+		{DM_DEV_SUSPEND_CMD, dev_suspend},
+		{DM_DEV_STATUS_CMD, dev_status},
+		{DM_DEV_WAIT_CMD, dev_wait},
+
+		{DM_TABLE_LOAD_CMD, table_load},
+		{DM_TABLE_CLEAR_CMD, table_clear},
+		{DM_TABLE_DEPS_CMD, table_deps},
+		{DM_TABLE_STATUS_CMD, table_status},
+
+		{DM_LIST_VERSIONS_CMD, list_versions}
+	};
+
+	return (cmd >= ARRAY_SIZE(_ioctls)) ? NULL : _ioctls[cmd].fn;
+}
+
+/*
+ * As well as checking the version compatibility this always
+ * copies the kernel interface version out.
+ */
+static int check_version(unsigned int cmd, struct dm_ioctl *user)
+{
+	uint32_t version[3];
+	int r = 0;
+
+	if (copy_from_user(version, user->version, sizeof(version)))
+		return -EFAULT;
+
+	if ((DM_VERSION_MAJOR != version[0]) ||
+	    (DM_VERSION_MINOR < version[1])) {
+		DMWARN("ioctl interface mismatch: "
+		       "kernel(%u.%u.%u), user(%u.%u.%u), cmd(%d)",
+		       DM_VERSION_MAJOR, DM_VERSION_MINOR,
+		       DM_VERSION_PATCHLEVEL,
+		       version[0], version[1], version[2], cmd);
+		r = -EINVAL;
+	}
+
+	/*
+	 * Fill in the kernel version.
+	 */
+	version[0] = DM_VERSION_MAJOR;
+	version[1] = DM_VERSION_MINOR;
+	version[2] = DM_VERSION_PATCHLEVEL;
+	if (copy_to_user(user->version, version, sizeof(version)))
+		return -EFAULT;
+
+	return r;
+}
+
+static void free_params(struct dm_ioctl *param)
+{
+	vfree(param);
+}
+
+static int copy_params(struct dm_ioctl *user, struct dm_ioctl **param)
+{
+	struct dm_ioctl tmp, *dmi;
+
+	if (copy_from_user(&tmp, user, sizeof(tmp)))
+		return -EFAULT;
+
+	if (tmp.data_size < sizeof(tmp))
+		return -EINVAL;
+
+	dmi = (struct dm_ioctl *) vmalloc(tmp.data_size);
+	if (!dmi)
+		return -ENOMEM;
+
+	if (copy_from_user(dmi, user, tmp.data_size)) {
+		vfree(dmi);
+		return -EFAULT;
+	}
+
+	*param = dmi;
+	return 0;
+}
+
+static int validate_params(uint cmd, struct dm_ioctl *param)
+{
+	/* Always clear this flag */
+	param->flags &= ~DM_BUFFER_FULL_FLAG;
+
+	/* Ignores parameters */
+	if (cmd == DM_REMOVE_ALL_CMD ||
+	    cmd == DM_LIST_DEVICES_CMD ||
+	    cmd == DM_LIST_VERSIONS_CMD)
+		return 0;
+
+	/* Unless creating, either name or uuid but not both */
+	if (cmd != DM_DEV_CREATE_CMD) {
+		if ((!*param->uuid && !*param->name) ||
+		    (*param->uuid && *param->name)) {
+			DMWARN("one of name or uuid must be supplied, cmd(%u)",
+			       cmd);
+			return -EINVAL;
+		}
+	}
+
+	/* Ensure strings are terminated */
+	param->name[DM_NAME_LEN - 1] = '\0';
+	param->uuid[DM_UUID_LEN - 1] = '\0';
+
+	return 0;
+}
+
+static int ctl_ioctl(struct inode *inode, struct file *file,
+		     uint command, ulong u)
+{
+	int r = 0;
+	unsigned int cmd;
+	struct dm_ioctl *param;
+	struct dm_ioctl *user = (struct dm_ioctl *) u;
+	ioctl_fn fn = NULL;
+	size_t param_size;
+
+	/* only root can play with this */
+	if (!capable(CAP_SYS_ADMIN))
+		return -EACCES;
+
+	if (_IOC_TYPE(command) != DM_IOCTL)
+		return -ENOTTY;
+
+	cmd = _IOC_NR(command);
+
+	/*
+	 * Check the interface version passed in.  This also
+	 * writes out the kernel's interface version.
+	 */
+	r = check_version(cmd, user);
+	if (r)
+		return r;
+
+	/*
+	 * Nothing more to do for the version command.
+	 */
+	if (cmd == DM_VERSION_CMD)
+		return 0;
+
+	fn = lookup_ioctl(cmd);
+	if (!fn) {
+		DMWARN("dm_ctl_ioctl: unknown command 0x%x", command);
+		return -ENOTTY;
+	}
+
+	/*
+	 * Trying to avoid low memory issues when a device is
+	 * suspended.
+	 */
+	current->flags |= PF_MEMALLOC;
+
+	/*
+	 * Copy the parameters into kernel space.
+	 */
+	r = copy_params(user, &param);
+	if (r) {
+		current->flags &= ~PF_MEMALLOC;
+		return r;
+	}
+
+	/*
+	 * FIXME: eventually we will remove the PF_MEMALLOC flag
+	 * here.  However the tools still do nasty things like
+	 * 'load' while a device is suspended.
+	 */
+
+	r = validate_params(cmd, param);
+	if (r)
+		goto out;
+
+	param_size = param->data_size;
+	param->data_size = sizeof(*param);
+	r = fn(param, param_size);
+
+	/*
+	 * Copy the results back to userland.
+	 */
+	if (!r && copy_to_user(user, param, param->data_size))
+		r = -EFAULT;
+
+ out:
+	free_params(param);
+	current->flags &= ~PF_MEMALLOC;
+	return r;
+}
+
+static struct file_operations _ctl_fops = {
+	.ioctl	 = ctl_ioctl,
+	.owner	 = THIS_MODULE,
+};
+
+static struct miscdevice _dm_misc = {
+	.minor 		= MISC_DYNAMIC_MINOR,
+	.name  		= DM_NAME,
+	.devfs_name 	= "mapper/control",
+	.fops  		= &_ctl_fops
+};
+
+/*
+ * Create misc character device and link to DM_DIR/control.
+ */
+int __init dm_interface_init(void)
+{
+	int r;
+
+	r = dm_hash_init();
+	if (r)
+		return r;
+
+	r = misc_register(&_dm_misc);
+	if (r) {
+		DMERR("misc_register failed for control device");
+		dm_hash_exit();
+		return r;
+	}
+
+	DMINFO("%d.%d.%d%s initialised: %s", DM_VERSION_MAJOR,
+	       DM_VERSION_MINOR, DM_VERSION_PATCHLEVEL, DM_VERSION_EXTRA,
+	       DM_DRIVER_EMAIL);
+	return 0;
+}
+
+void dm_interface_exit(void)
+{
+	if (misc_deregister(&_dm_misc) < 0)
+		DMERR("misc_deregister failed for control device");
+
+	dm_hash_exit();
+}
--- diff/drivers/md/dm-linear.c	2003-09-30 15:46:14.000000000 +0100
+++ source/drivers/md/dm-linear.c	2004-02-23 13:56:43.000000000 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2001 Sistina Software (UK) Limited.
+ * Copyright (C) 2001-2003 Sistina Software (UK) Limited.
  *
  * This file is released under the GPL.
  */
@@ -65,7 +65,8 @@ static void linear_dtr(struct dm_target 
 	kfree(lc);
 }
 
-static int linear_map(struct dm_target *ti, struct bio *bio)
+static int linear_map(struct dm_target *ti, struct bio *bio,
+		      union map_info *map_context)
 {
 	struct linear_c *lc = (struct linear_c *) ti->private;
 
@@ -96,6 +97,7 @@ static int linear_status(struct dm_targe
 
 static struct target_type linear_target = {
 	.name   = "linear",
+	.version= {1, 0, 1},
 	.module = THIS_MODULE,
 	.ctr    = linear_ctr,
 	.dtr    = linear_dtr,
--- diff/drivers/md/dm-stripe.c	2003-09-30 15:46:14.000000000 +0100
+++ source/drivers/md/dm-stripe.c	2004-02-23 13:56:43.000000000 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2001 Sistina Software (UK) Limited.
+ * Copyright (C) 2001-2003 Sistina Software (UK) Limited.
  *
  * This file is released under the GPL.
  */
@@ -166,7 +166,8 @@ static void stripe_dtr(struct dm_target 
 	kfree(sc);
 }
 
-static int stripe_map(struct dm_target *ti, struct bio *bio)
+static int stripe_map(struct dm_target *ti, struct bio *bio,
+		      union map_info *map_context)
 {
 	struct stripe_c *sc = (struct stripe_c *) ti->private;
 
@@ -195,12 +196,12 @@ static int stripe_status(struct dm_targe
 		break;
 
 	case STATUSTYPE_TABLE:
-		offset = snprintf(result, maxlen, "%d " SECTOR_FORMAT,
+		offset = scnprintf(result, maxlen, "%d " SECTOR_FORMAT,
 				  sc->stripes, sc->chunk_mask + 1);
 		for (i = 0; i < sc->stripes; i++) {
 			format_dev_t(buffer, sc->stripe[i].dev->bdev->bd_dev);
 			offset +=
-			    snprintf(result + offset, maxlen - offset,
+			    scnprintf(result + offset, maxlen - offset,
 				     " %s " SECTOR_FORMAT, buffer,
 				     sc->stripe[i].physical_start);
 		}
@@ -211,6 +212,7 @@ static int stripe_status(struct dm_targe
 
 static struct target_type stripe_target = {
 	.name   = "striped",
+	.version= {1, 0, 1},
 	.module = THIS_MODULE,
 	.ctr    = stripe_ctr,
 	.dtr    = stripe_dtr,
--- diff/drivers/md/dm-table.c	2004-01-19 10:22:56.000000000 +0000
+++ source/drivers/md/dm-table.c	2004-02-23 13:56:43.000000000 +0000
@@ -149,7 +149,7 @@ static int setup_btree_index(unsigned in
 	return 0;
 }
 
-static void *dm_vcalloc(unsigned long nmemb, unsigned long elem_size)
+void *dm_vcalloc(unsigned long nmemb, unsigned long elem_size)
 {
 	unsigned long size;
 	void *addr;
@@ -205,7 +205,7 @@ static int alloc_targets(struct dm_table
 
 int dm_table_create(struct dm_table **result, int mode, unsigned num_targets)
 {
-	struct dm_table *t = kmalloc(sizeof(*t), GFP_NOIO);
+	struct dm_table *t = kmalloc(sizeof(*t), GFP_KERNEL);
 
 	if (!t)
 		return -ENOMEM;
@@ -329,13 +329,11 @@ static int lookup_device(const char *pat
  */
 static struct dm_dev *find_device(struct list_head *l, dev_t dev)
 {
-	struct list_head *tmp;
+	struct dm_dev *dd;
 
-	list_for_each(tmp, l) {
-		struct dm_dev *dd = list_entry(tmp, struct dm_dev, list);
+	list_for_each_entry (dd, l, list)
 		if (dd->bdev->bd_dev == dev)
 			return dd;
-	}
 
 	return NULL;
 }
@@ -353,12 +351,12 @@ static int open_dev(struct dm_dev *d, de
 	if (d->bdev)
 		BUG();
 
-	bdev = open_by_devnum(dev, d->mode, BDEV_RAW);
+	bdev = open_by_devnum(dev, d->mode);
 	if (IS_ERR(bdev))
 		return PTR_ERR(bdev);
 	r = bd_claim(bdev, _claim_ptr);
 	if (r)
-		blkdev_put(bdev, BDEV_RAW);
+		blkdev_put(bdev);
 	else
 		d->bdev = bdev;
 	return r;
@@ -373,7 +371,7 @@ static void close_dev(struct dm_dev *d)
 		return;
 
 	bd_release(d->bdev);
-	blkdev_put(d->bdev, BDEV_RAW);
+	blkdev_put(d->bdev);
 	d->bdev = NULL;
 }
 
@@ -631,14 +629,20 @@ static int split_args(int *argc, char **
 	return 0;
 }
 
-static void set_default_limits(struct io_restrictions *rs)
+static void check_for_valid_limits(struct io_restrictions *rs)
 {
-	rs->max_sectors = MAX_SECTORS;
-	rs->max_phys_segments = MAX_PHYS_SEGMENTS;
-	rs->max_hw_segments = MAX_HW_SEGMENTS;
-	rs->hardsect_size = 1 << SECTOR_SHIFT;
-	rs->max_segment_size = MAX_SEGMENT_SIZE;
-	rs->seg_boundary_mask = -1;
+	if (!rs->max_sectors)
+		rs->max_sectors = MAX_SECTORS;
+	if (!rs->max_phys_segments)
+		rs->max_phys_segments = MAX_PHYS_SEGMENTS;
+	if (!rs->max_hw_segments)
+		rs->max_hw_segments = MAX_HW_SEGMENTS;
+	if (!rs->hardsect_size)
+		rs->hardsect_size = 1 << SECTOR_SHIFT;
+	if (!rs->max_segment_size)
+		rs->max_segment_size = MAX_SEGMENT_SIZE;
+	if (!rs->seg_boundary_mask)
+		rs->seg_boundary_mask = -1;
 }
 
 int dm_table_add_target(struct dm_table *t, const char *type,
@@ -653,7 +657,11 @@ int dm_table_add_target(struct dm_table 
 
 	tgt = t->targets + t->num_targets;
 	memset(tgt, 0, sizeof(*tgt));
-	set_default_limits(&tgt->limits);
+
+	if (!len) {
+		tgt->error = "zero-length target";
+		return -EINVAL;
+	}
 
 	tgt->type = dm_get_target_type(type);
 	if (!tgt->type) {
@@ -733,6 +741,8 @@ int dm_table_complete(struct dm_table *t
 	int r = 0;
 	unsigned int leaf_nodes;
 
+	check_for_valid_limits(&t->limits);
+
 	/* how many indexes will the btree have ? */
 	leaf_nodes = dm_div_up(t->num_targets, KEYS_PER_NODE);
 	t->depth = 1 + int_log(leaf_nodes, CHILDREN_PER_NODE);
@@ -858,6 +868,7 @@ void dm_table_resume_targets(struct dm_t
 }
 
 
+EXPORT_SYMBOL(dm_vcalloc);
 EXPORT_SYMBOL(dm_get_device);
 EXPORT_SYMBOL(dm_put_device);
 EXPORT_SYMBOL(dm_table_event);
--- diff/drivers/md/dm-target.c	2003-06-30 10:07:21.000000000 +0100
+++ source/drivers/md/dm-target.c	2004-02-23 13:56:43.000000000 +0000
@@ -25,15 +25,11 @@ static DECLARE_RWSEM(_lock);
 
 static inline struct tt_internal *__find_target_type(const char *name)
 {
-	struct list_head *tih;
 	struct tt_internal *ti;
 
-	list_for_each(tih, &_targets) {
-		ti = list_entry(tih, struct tt_internal, list);
-
+	list_for_each_entry (ti, &_targets, list)
 		if (!strcmp(name, ti->tt.name))
 			return ti;
-	}
 
 	return NULL;
 }
@@ -100,6 +96,20 @@ static struct tt_internal *alloc_target(
 	return ti;
 }
 
+
+int dm_target_iterate(void (*iter_func)(struct target_type *tt,
+					void *param), void *param)
+{
+	struct tt_internal *ti;
+
+	down_read(&_lock);
+	list_for_each_entry (ti, &_targets, list)
+		iter_func(&ti->tt, param);
+	up_read(&_lock);
+
+	return 0;
+}
+
 int dm_register_target(struct target_type *t)
 {
 	int rv = 0;
@@ -157,13 +167,15 @@ static void io_err_dtr(struct dm_target 
 	/* empty */
 }
 
-static int io_err_map(struct dm_target *ti, struct bio *bio)
+static int io_err_map(struct dm_target *ti, struct bio *bio,
+		      union map_info *map_context)
 {
 	return -EIO;
 }
 
 static struct target_type error_target = {
 	.name = "error",
+	.version = {1, 0, 1},
 	.ctr  = io_err_ctr,
 	.dtr  = io_err_dtr,
 	.map  = io_err_map,
--- diff/drivers/md/dm.c	2004-02-18 08:54:09.000000000 +0000
+++ source/drivers/md/dm.c	2004-02-23 13:56:43.000000000 +0000
@@ -5,6 +5,7 @@
  */
 
 #include "dm.h"
+#include "dm-bio-list.h"
 
 #include <linux/init.h>
 #include <linux/module.h>
@@ -20,6 +21,9 @@ static const char *_name = DM_NAME;
 static unsigned int major = 0;
 static unsigned int _major = 0;
 
+/*
+ * One of these is allocated per bio.
+ */
 struct dm_io {
 	struct mapped_device *md;
 	int error;
@@ -27,9 +31,19 @@ struct dm_io {
 	atomic_t io_count;
 };
 
-struct deferred_io {
-	struct bio *bio;
-	struct deferred_io *next;
+/*
+ * One of these is allocated per target within a bio.  Hopefully
+ * this will be simplified out one day.
+ */
+struct target_io {
+	struct dm_io *io;
+	struct dm_target *ti;
+	union map_info info;
+
+	sector_t bi_sector;
+	struct block_device *bi_bdev;
+	unsigned int bi_size;
+	unsigned short bi_idx;
 };
 
 /*
@@ -52,7 +66,7 @@ struct mapped_device {
 	 */
 	atomic_t pending;
 	wait_queue_head_t wait;
-	struct deferred_io *deferred;
+ 	struct bio_list deferred;
 
 	/*
 	 * The current mapping.
@@ -63,6 +77,7 @@ struct mapped_device {
 	 * io objects are allocated from here.
 	 */
 	mempool_t *io_pool;
+	mempool_t *tio_pool;
 
 	/*
 	 * Event handling.
@@ -73,6 +88,7 @@ struct mapped_device {
 
 #define MIN_IOS 256
 static kmem_cache_t *_io_cache;
+static kmem_cache_t *_tio_cache;
 
 static __init int local_init(void)
 {
@@ -84,9 +100,18 @@ static __init int local_init(void)
 	if (!_io_cache)
 		return -ENOMEM;
 
+	/* allocate a slab for the target ios */
+	_tio_cache = kmem_cache_create("dm_tio", sizeof(struct target_io),
+				       0, 0, NULL, NULL);
+	if (!_tio_cache) {
+		kmem_cache_destroy(_io_cache);
+		return -ENOMEM;
+	}
+
 	_major = major;
 	r = register_blkdev(_major, _name);
 	if (r < 0) {
+		kmem_cache_destroy(_tio_cache);
 		kmem_cache_destroy(_io_cache);
 		return r;
 	}
@@ -99,6 +124,7 @@ static __init int local_init(void)
 
 static void local_exit(void)
 {
+	kmem_cache_destroy(_tio_cache);
 	kmem_cache_destroy(_io_cache);
 
 	if (unregister_blkdev(_major, _name) < 0)
@@ -188,14 +214,14 @@ static inline void free_io(struct mapped
 	mempool_free(io, md->io_pool);
 }
 
-static inline struct deferred_io *alloc_deferred(void)
+static inline struct target_io *alloc_tio(struct mapped_device *md)
 {
-	return kmalloc(sizeof(struct deferred_io), GFP_NOIO);
+	return mempool_alloc(md->tio_pool, GFP_NOIO);
 }
 
-static inline void free_deferred(struct deferred_io *di)
+static inline void free_tio(struct mapped_device *md, struct target_io *tio)
 {
-	kfree(di);
+	mempool_free(tio, md->tio_pool);
 }
 
 /*
@@ -203,23 +229,14 @@ static inline void free_deferred(struct 
  */
 static int queue_io(struct mapped_device *md, struct bio *bio)
 {
-	struct deferred_io *di;
-
-	di = alloc_deferred();
-	if (!di)
-		return -ENOMEM;
-
 	down_write(&md->lock);
 
 	if (!test_bit(DMF_BLOCK_IO, &md->flags)) {
 		up_write(&md->lock);
-		free_deferred(di);
 		return 1;
 	}
 
-	di->bio = bio;
-	di->next = md->deferred;
-	md->deferred = di;
+	bio_list_add(&md->deferred, bio);
 
 	up_write(&md->lock);
 	return 0;		/* deferred successfully */
@@ -233,15 +250,6 @@ static int queue_io(struct mapped_device
  *   interests of getting something for people to use I give
  *   you this clearly demarcated crap.
  *---------------------------------------------------------------*/
-static inline sector_t to_sector(unsigned int bytes)
-{
-	return bytes >> SECTOR_SHIFT;
-}
-
-static inline unsigned int to_bytes(sector_t sector)
-{
-	return sector << SECTOR_SHIFT;
-}
 
 /*
  * Decrements the number of outstanding ios that a bio has been
@@ -249,14 +257,8 @@ static inline unsigned int to_bytes(sect
  */
 static inline void dec_pending(struct dm_io *io, int error)
 {
-	static spinlock_t _uptodate_lock = SPIN_LOCK_UNLOCKED;
-	unsigned long flags;
-
-	if (error) {
-		spin_lock_irqsave(&_uptodate_lock, flags);
+	if (error)
 		io->error = error;
-		spin_unlock_irqrestore(&_uptodate_lock, flags);
-	}
 
 	if (atomic_dec_and_test(&io->io_count)) {
 		if (atomic_dec_and_test(&io->md->pending))
@@ -270,17 +272,36 @@ static inline void dec_pending(struct dm
 
 static int clone_endio(struct bio *bio, unsigned int done, int error)
 {
-	struct dm_io *io = bio->bi_private;
+	int r = 0;
+	struct target_io *tio = bio->bi_private;
+	struct dm_io *io = tio->io;
+	dm_endio_fn endio = tio->ti->type->end_io;
 
 	if (bio->bi_size)
 		return 1;
 
+	if (endio) {
+		/* Restore bio fields. */
+		bio->bi_sector = tio->bi_sector;
+		bio->bi_bdev = tio->bi_bdev;
+		bio->bi_size = tio->bi_size;
+		bio->bi_idx = tio->bi_idx;
+
+		r = endio(tio->ti, bio, error, &tio->info);
+		if (r < 0)
+			error = r;
+
+		else if (r > 0)
+			/* the target wants another shot at the io */
+			return 1;
+	}
+
+	free_tio(io->md, tio);
 	dec_pending(io, error);
 	bio_put(bio);
-	return 0;
+	return r;
 }
 
-
 static sector_t max_io_len(struct mapped_device *md,
 			   sector_t sector, struct dm_target *ti)
 {
@@ -301,7 +322,8 @@ static sector_t max_io_len(struct mapped
 	return len;
 }
 
-static void __map_bio(struct dm_target *ti, struct bio *clone, struct dm_io *io)
+static void __map_bio(struct dm_target *ti, struct bio *clone,
+		      struct target_io *tio)
 {
 	int r;
 
@@ -311,22 +333,32 @@ static void __map_bio(struct dm_target *
 	BUG_ON(!clone->bi_size);
 
 	clone->bi_end_io = clone_endio;
-	clone->bi_private = io;
+	clone->bi_private = tio;
 
 	/*
 	 * Map the clone.  If r == 0 we don't need to do
 	 * anything, the target has assumed ownership of
 	 * this io.
 	 */
-	atomic_inc(&io->io_count);
-	r = ti->type->map(ti, clone);
-	if (r > 0)
+	atomic_inc(&tio->io->io_count);
+	r = ti->type->map(ti, clone, &tio->info);
+	if (r > 0) {
+		/* Save the bio info so we can restore it during endio. */
+		tio->bi_sector = clone->bi_sector;
+		tio->bi_bdev = clone->bi_bdev;
+		tio->bi_size = clone->bi_size;
+		tio->bi_idx = clone->bi_idx;
+
 		/* the bio has been remapped so dispatch it */
 		generic_make_request(clone);
+	}
 
-	else if (r < 0)
+	else if (r < 0) {
 		/* error the io and bail out */
+		struct dm_io *io = tio->io;
+		free_tio(tio->io->md, tio);
 		dec_pending(io, -EIO);
+	}
 }
 
 struct clone_info {
@@ -376,6 +408,7 @@ static struct bio *clone_bio(struct bio 
 	clone->bi_idx = idx;
 	clone->bi_vcnt = idx + bv_count;
 	clone->bi_size = to_bytes(len);
+	clone->bi_flags &= ~(1 << BIO_SEG_VALID);
 
 	return clone;
 }
@@ -385,6 +418,15 @@ static void __clone_and_map(struct clone
 	struct bio *clone, *bio = ci->bio;
 	struct dm_target *ti = dm_table_find_target(ci->md->map, ci->sector);
 	sector_t len = 0, max = max_io_len(ci->md, ci->sector, ti);
+	struct target_io *tio;
+
+	/*
+	 * Allocate a target io object.
+	 */
+	tio = alloc_tio(ci->md);
+	tio->io = ci->io;
+	tio->ti = ti;
+	memset(&tio->info, 0, sizeof(tio->info));
 
 	if (ci->sector_count <= max) {
 		/*
@@ -393,7 +435,7 @@ static void __clone_and_map(struct clone
 		 */
 		clone = clone_bio(bio, ci->sector, ci->idx,
 				  bio->bi_vcnt - ci->idx, ci->sector_count);
-		__map_bio(ti, clone, ci->io);
+		__map_bio(ti, clone, tio);
 		ci->sector_count = 0;
 
 	} else if (to_sector(bio->bi_io_vec[ci->idx].bv_len) <= max) {
@@ -416,7 +458,7 @@ static void __clone_and_map(struct clone
 		}
 
 		clone = clone_bio(bio, ci->sector, ci->idx, i - ci->idx, len);
-		__map_bio(ti, clone, ci->io);
+		__map_bio(ti, clone, tio);
 
 		ci->sector += len;
 		ci->sector_count -= len;
@@ -431,7 +473,7 @@ static void __clone_and_map(struct clone
 
 		clone = split_bvec(bio, ci->sector, ci->idx,
 				   bv->bv_offset, max);
-		__map_bio(ti, clone, ci->io);
+		__map_bio(ti, clone, tio);
 
 		ci->sector += max;
 		ci->sector_count -= max;
@@ -440,7 +482,11 @@ static void __clone_and_map(struct clone
 		len = to_sector(bv->bv_len) - max;
 		clone = split_bvec(bio, ci->sector, ci->idx,
 				   bv->bv_offset + to_bytes(max), len);
-		__map_bio(ti, clone, ci->io);
+		tio = alloc_tio(ci->md);
+		tio->io = ci->io;
+		tio->ti = ti;
+		memset(&tio->info, 0, sizeof(tio->info));
+		__map_bio(ti, clone, tio);
 
 		ci->sector += len;
 		ci->sector_count -= len;
@@ -478,6 +524,16 @@ static void __split_bio(struct mapped_de
  *---------------------------------------------------------------*/
 
 
+static inline void __dm_request(struct mapped_device *md, struct bio *bio)
+{
+	if (!md->map) {
+		bio_io_error(bio, bio->bi_size);
+		return;
+	}
+
+	__split_bio(md, bio);
+}
+
 /*
  * The request function that just remaps the bio built up by
  * dm_merge_bvec.
@@ -516,12 +572,7 @@ static int dm_request(request_queue_t *q
 		down_read(&md->lock);
 	}
 
-	if (!md->map) {
-		bio_io_error(bio, bio->bi_size);
-		return 0;
-	}
-
-	__split_bio(md, bio);
+	__dm_request(md, bio);
 	up_read(&md->lock);
 	return 0;
 }
@@ -592,41 +643,33 @@ static struct mapped_device *alloc_dev(u
 
 	/* get a minor number for the dev */
 	r = persistent ? specific_minor(minor) : next_free_minor(&minor);
-	if (r < 0) {
-		kfree(md);
-		return NULL;
-	}
+	if (r < 0)
+		goto bad1;
 
 	memset(md, 0, sizeof(*md));
 	init_rwsem(&md->lock);
 	atomic_set(&md->holders, 1);
 
 	md->queue = blk_alloc_queue(GFP_KERNEL);
-	if (!md->queue) {
-		kfree(md);
-		return NULL;
-	}
+	if (!md->queue)
+		goto bad1;
 
 	md->queue->queuedata = md;
 	blk_queue_make_request(md->queue, dm_request);
 
 	md->io_pool = mempool_create(MIN_IOS, mempool_alloc_slab,
 				     mempool_free_slab, _io_cache);
-	if (!md->io_pool) {
-		free_minor(minor);
-		blk_put_queue(md->queue);
-		kfree(md);
-		return NULL;
-	}
+ 	if (!md->io_pool)
+ 		goto bad2;
+
+	md->tio_pool = mempool_create(MIN_IOS, mempool_alloc_slab,
+				      mempool_free_slab, _tio_cache);
+	if (!md->tio_pool)
+		goto bad3;
 
 	md->disk = alloc_disk(1);
-	if (!md->disk) {
-		mempool_destroy(md->io_pool);
-		free_minor(minor);
-		blk_put_queue(md->queue);
-		kfree(md);
-		return NULL;
-	}
+	if (!md->disk)
+		goto bad4;
 
 	md->disk->major = _major;
 	md->disk->first_minor = minor;
@@ -641,11 +684,23 @@ static struct mapped_device *alloc_dev(u
 	init_waitqueue_head(&md->eventq);
 
 	return md;
+
+ bad4:
+	mempool_destroy(md->tio_pool);
+ bad3:
+	mempool_destroy(md->io_pool);
+ bad2:
+	blk_put_queue(md->queue);
+	free_minor(minor);
+ bad1:
+	kfree(md);
+	return NULL;
 }
 
 static void free_dev(struct mapped_device *md)
 {
 	free_minor(md->disk->first_minor);
+	mempool_destroy(md->tio_pool);
 	mempool_destroy(md->io_pool);
 	del_gendisk(md->disk);
 	put_disk(md->disk);
@@ -684,13 +739,13 @@ static int __bind(struct mapped_device *
 {
 	request_queue_t *q = md->queue;
 	sector_t size;
-	md->map = t;
 
 	size = dm_table_get_size(t);
 	__set_size(md->disk, size);
 	if (size == 0)
 		return 0;
 
+	md->map = t;
 	dm_table_event_callback(md->map, event_callback, md);
 
 	dm_table_get(t);
@@ -750,16 +805,16 @@ void dm_put(struct mapped_device *md)
 }
 
 /*
- * Requeue the deferred bios by calling generic_make_request.
+ * Process the deferred bios
  */
-static void flush_deferred_io(struct deferred_io *c)
+static void __flush_deferred_io(struct mapped_device *md, struct bio *c)
 {
-	struct deferred_io *n;
+	struct bio *n;
 
 	while (c) {
-		n = c->next;
-		generic_make_request(c->bio);
-		free_deferred(c);
+		n = c->bi_next;
+		c->bi_next = NULL;
+		__dm_request(md, c);
 		c = n;
 	}
 }
@@ -841,7 +896,7 @@ int dm_suspend(struct mapped_device *md)
 
 int dm_resume(struct mapped_device *md)
 {
-	struct deferred_io *def;
+	struct bio *def;
 
 	down_write(&md->lock);
 	if (!md->map ||
@@ -854,11 +909,11 @@ int dm_resume(struct mapped_device *md)
 	dm_table_resume_targets(md->map);
 	clear_bit(DMF_SUSPENDED, &md->flags);
 	clear_bit(DMF_BLOCK_IO, &md->flags);
-	def = md->deferred;
-	md->deferred = NULL;
+
+	def = bio_list_get(&md->deferred);
+	__flush_deferred_io(md, def);
 	up_write(&md->lock);
 
-	flush_deferred_io(def);
 	blk_run_queues();
 
 	return 0;
--- diff/drivers/md/dm.h	2004-01-19 10:22:56.000000000 +0000
+++ source/drivers/md/dm.h	2004-02-23 13:56:43.000000000 +0000
@@ -123,6 +123,8 @@ int dm_target_init(void);
 void dm_target_exit(void);
 struct target_type *dm_get_target_type(const char *name);
 void dm_put_target_type(struct target_type *t);
+int dm_target_iterate(void (*iter_func)(struct target_type *tt,
+					void *param), void *param);
 
 
 /*-----------------------------------------------------------------
@@ -151,6 +153,16 @@ static inline unsigned long dm_div_up(un
 	return dm_round_up(n, size) / size;
 }
 
+static inline sector_t to_sector(unsigned long n)
+{
+	return (n >> 9);
+}
+
+static inline unsigned long to_bytes(sector_t n)
+{
+	return (n << 9);
+}
+
 /*
  * The device-mapper can be driven through one of two interfaces;
  * ioctl or filesystem, depending which patch you have applied.
@@ -167,4 +179,6 @@ void dm_linear_exit(void);
 int dm_stripe_init(void);
 void dm_stripe_exit(void);
 
+void *dm_vcalloc(unsigned long nmemb, unsigned long elem_size);
+
 #endif
--- diff/drivers/md/md.c	2004-02-18 08:54:09.000000000 +0000
+++ source/drivers/md/md.c	2004-02-23 13:56:43.000000000 +0000
@@ -52,6 +52,9 @@
 #define MAJOR_NR MD_MAJOR
 #define MD_DRIVER
 
+/* 63 partitions with the alternate major number (mdp) */
+#define MdpMinorShift 6
+
 #define DEBUG 0
 #define dprintk(x...) ((void)(DEBUG && printk(x)))
 
@@ -178,14 +181,14 @@ static void mddev_put(mddev_t *mddev)
 	spin_unlock(&all_mddevs_lock);
 }
 
-static mddev_t * mddev_find(int unit)
+static mddev_t * mddev_find(dev_t unit)
 {
 	mddev_t *mddev, *new = NULL;
 
  retry:
 	spin_lock(&all_mddevs_lock);
 	list_for_each_entry(mddev, &all_mddevs, all_mddevs)
-		if (mdidx(mddev) == unit) {
+		if (mddev->unit == unit) {
 			mddev_get(mddev);
 			spin_unlock(&all_mddevs_lock);
 			if (new)
@@ -206,7 +209,12 @@ static mddev_t * mddev_find(int unit)
 
 	memset(new, 0, sizeof(*new));
 
-	new->__minor = unit;
+	new->unit = unit;
+	if (MAJOR(unit) == MD_MAJOR)
+		new->md_minor = MINOR(unit);
+	else
+		new->md_minor = MINOR(unit) >> MdpMinorShift;
+
 	init_MUTEX(&new->reconfig_sem);
 	INIT_LIST_HEAD(&new->disks);
 	INIT_LIST_HEAD(&new->all_mddevs);
@@ -660,7 +668,7 @@ static void super_90_sync(mddev_t *mddev
 	sb->level = mddev->level;
 	sb->size  = mddev->size;
 	sb->raid_disks = mddev->raid_disks;
-	sb->md_minor = mddev->__minor;
+	sb->md_minor = mddev->md_minor;
 	sb->not_persistent = !mddev->persistent;
 	sb->utime = mddev->utime;
 	sb->state = 0;
@@ -1045,12 +1053,12 @@ static int lock_rdev(mdk_rdev_t *rdev, d
 	int err = 0;
 	struct block_device *bdev;
 
-	bdev = open_by_devnum(dev, FMODE_READ|FMODE_WRITE, BDEV_RAW);
+	bdev = open_by_devnum(dev, FMODE_READ|FMODE_WRITE);
 	if (IS_ERR(bdev))
 		return PTR_ERR(bdev);
 	err = bd_claim(bdev, rdev);
 	if (err) {
-		blkdev_put(bdev, BDEV_RAW);
+		blkdev_put(bdev);
 		return err;
 	}
 	rdev->bdev = bdev;
@@ -1064,7 +1072,7 @@ static void unlock_rdev(mdk_rdev_t *rdev
 	if (!bdev)
 		MD_BUG();
 	bd_release(bdev);
-	blkdev_put(bdev, BDEV_RAW);
+	blkdev_put(bdev);
 }
 
 void md_autodetect_dev(dev_t dev);
@@ -1442,13 +1450,16 @@ abort:
 	return 1;
 }
 
+static int mdp_major = 0;
 
 static struct kobject *md_probe(dev_t dev, int *part, void *data)
 {
 	static DECLARE_MUTEX(disks_sem);
-	int unit = *part;
-	mddev_t *mddev = mddev_find(unit);
+	mddev_t *mddev = mddev_find(dev);
 	struct gendisk *disk;
+	int partitioned = (MAJOR(dev) != MD_MAJOR);
+	int shift = partitioned ? MdpMinorShift : 0;
+	int unit = MINOR(dev) >> shift;
 
 	if (!mddev)
 		return NULL;
@@ -1459,15 +1470,18 @@ static struct kobject *md_probe(dev_t de
 		mddev_put(mddev);
 		return NULL;
 	}
-	disk = alloc_disk(1);
+	disk = alloc_disk(1 << shift);
 	if (!disk) {
 		up(&disks_sem);
 		mddev_put(mddev);
 		return NULL;
 	}
-	disk->major = MD_MAJOR;
-	disk->first_minor = mdidx(mddev);
-	sprintf(disk->disk_name, "md%d", mdidx(mddev));
+	disk->major = MAJOR(dev);
+	disk->first_minor = unit << shift;
+	if (partitioned)
+		sprintf(disk->disk_name, "md_d%d", unit);
+	else
+		sprintf(disk->disk_name, "md%d", unit);
 	disk->fops = &md_fops;
 	disk->private_data = mddev;
 	disk->queue = mddev->queue;
@@ -1496,7 +1510,6 @@ static int do_md_run(mddev_t * mddev)
 	mdk_rdev_t *rdev;
 	struct gendisk *disk;
 	char b[BDEVNAME_SIZE];
-	int unit;
 
 	if (list_empty(&mddev->disks)) {
 		MD_BUG();
@@ -1588,8 +1601,7 @@ static int do_md_run(mddev_t * mddev)
 		invalidate_bdev(rdev->bdev, 0);
 	}
 
-	unit = mdidx(mddev);
-	md_probe(0, &unit, NULL);
+	md_probe(mddev->unit, NULL, NULL);
 	disk = mddev->gendisk;
 	if (!disk)
 		return -ENOMEM;
@@ -1636,6 +1648,7 @@ static int do_md_run(mddev_t * mddev)
 	mddev->queue->queuedata = mddev;
 	mddev->queue->make_request_fn = mddev->pers->make_request;
 
+	mddev->changed = 1;
 	return 0;
 }
 
@@ -1735,6 +1748,7 @@ static int do_md_stop(mddev_t * mddev, i
 		disk = mddev->gendisk;
 		if (disk)
 			set_capacity(disk, 0);
+		mddev->changed = 1;
 	} else
 		printk(KERN_INFO "md: %s switched to read-only mode.\n",
 			mdname(mddev));
@@ -1791,6 +1805,7 @@ static void autorun_devices(void)
 
 	printk(KERN_INFO "md: autorun ...\n");
 	while (!list_empty(&pending_raid_disks)) {
+		dev_t dev;
 		rdev0 = list_entry(pending_raid_disks.next,
 					 mdk_rdev_t, same_set);
 
@@ -1808,8 +1823,14 @@ static void autorun_devices(void)
 		 * mostly sane superblocks. It's time to allocate the
 		 * mddev.
 		 */
-
-		mddev = mddev_find(rdev0->preferred_minor);
+		if (rdev0->preferred_minor < 0 || rdev0->preferred_minor >= MAX_MD_DEVS) {
+			printk(KERN_INFO "md: unit number in %s is bad: %d\n",
+			       bdevname(rdev0->bdev, b), rdev0->preferred_minor);
+			break;
+		}
+		dev = MKDEV(MD_MAJOR, rdev0->preferred_minor);
+		md_probe(dev, NULL, NULL);
+		mddev = mddev_find(dev);
 		if (!mddev) {
 			printk(KERN_ERR 
 				"md: cannot allocate memory for md drive.\n");
@@ -1824,7 +1845,7 @@ static void autorun_devices(void)
 				"md: %s already running, cannot run %s\n",
 				mdname(mddev), bdevname(rdev0->bdev,b));
 			mddev_unlock(mddev);
-		} else if (rdev0->preferred_minor >= 0 && rdev0->preferred_minor < MAX_MD_DEVS) {
+		} else {
 			printk(KERN_INFO "md: created %s\n", mdname(mddev));
 			ITERATE_RDEV_GENERIC(candidates,rdev,tmp) {
 				list_del_init(&rdev->same_set);
@@ -1833,9 +1854,7 @@ static void autorun_devices(void)
 			}
 			autorun_array(mddev);
 			mddev_unlock(mddev);
-		} else
-			printk(KERN_WARNING "md: %s had invalid preferred minor %d\n",
-			       bdevname(rdev->bdev, b), rdev0->preferred_minor);
+		}
 		/* on success, candidates will be empty, on error
 		 * it won't...
 		 */
@@ -1955,7 +1974,7 @@ static int get_array_info(mddev_t * mdde
 	info.size          = mddev->size;
 	info.nr_disks      = nr;
 	info.raid_disks    = mddev->raid_disks;
-	info.md_minor      = mddev->__minor;
+	info.md_minor      = mddev->md_minor;
 	info.not_persistent= !mddev->persistent;
 
 	info.utime         = mddev->utime;
@@ -2326,7 +2345,7 @@ static int set_array_info(mddev_t * mdde
 	mddev->level         = info->level;
 	mddev->size          = info->size;
 	mddev->raid_disks    = info->raid_disks;
-	/* don't set __minor, it is determined by which /dev/md* was
+	/* don't set md_minor, it is determined by which /dev/md* was
 	 * openned
 	 */
 	if (info->state & (1<<MD_SB_CLEAN))
@@ -2366,7 +2385,6 @@ static int md_ioctl(struct inode *inode,
 			unsigned int cmd, unsigned long arg)
 {
 	char b[BDEVNAME_SIZE];
-	unsigned int minor = iminor(inode);
 	int err = 0;
 	struct hd_geometry *loc = (struct hd_geometry *) arg;
 	mddev_t *mddev = NULL;
@@ -2374,11 +2392,6 @@ static int md_ioctl(struct inode *inode,
 	if (!capable(CAP_SYS_ADMIN))
 		return -EACCES;
 
-	if (minor >= MAX_MD_DEVS) {
-		MD_BUG();
-		return -EINVAL;
-	}
-
 	/*
 	 * Commands dealing with the RAID driver but not any
 	 * particular array:
@@ -2419,6 +2432,14 @@ static int md_ioctl(struct inode *inode,
 		/* START_ARRAY doesn't need to lock the array as autostart_array
 		 * does the locking, and it could even be a different array
 		 */
+		static int cnt = 3;
+		if (cnt > 0 ) {
+			printk(KERN_WARNING
+			       "md: %s(pid %d) used deprecated START_ARRAY ioctl. "
+			       "This will not be supported beyond 2.6\n",
+			       current->comm, current->pid);
+			cnt--;
+		}
 		err = autostart_array(new_decode_dev(arg));
 		if (err) {
 			printk(KERN_WARNING "md: autostart %s failed!\n",
@@ -2612,6 +2633,7 @@ static int md_open(struct inode *inode, 
 	mddev_get(mddev);
 	mddev_unlock(mddev);
 
+	check_disk_change(inode->i_bdev);
  out:
 	return err;
 }
@@ -2627,12 +2649,28 @@ static int md_release(struct inode *inod
 	return 0;
 }
 
+static int md_media_changed(struct gendisk *disk)
+{
+	mddev_t *mddev = disk->private_data;
+
+	return mddev->changed;
+}
+
+static int md_revalidate(struct gendisk *disk)
+{
+	mddev_t *mddev = disk->private_data;
+
+	mddev->changed = 0;
+	return 0;
+}
 static struct block_device_operations md_fops =
 {
 	.owner		= THIS_MODULE,
 	.open		= md_open,
 	.release	= md_release,
 	.ioctl		= md_ioctl,
+	.media_changed	= md_media_changed,
+	.revalidate_disk= md_revalidate,
 };
 
 int md_thread(void * arg)
@@ -3497,16 +3535,26 @@ int __init md_init(void)
 
 	if (register_blkdev(MAJOR_NR, "md"))
 		return -1;
-
+	if ((mdp_major=register_blkdev(0, "mdp"))<=0) {
+		unregister_blkdev(MAJOR_NR, "md");
+		return -1;
+	}
 	devfs_mk_dir("md");
 	blk_register_region(MKDEV(MAJOR_NR, 0), MAX_MD_DEVS, THIS_MODULE,
 				md_probe, NULL, NULL);
+	blk_register_region(MKDEV(mdp_major, 0), MAX_MD_DEVS<<MdpMinorShift, THIS_MODULE,
+			    md_probe, NULL, NULL);
 
-	for (minor=0; minor < MAX_MD_DEVS; ++minor) {
+	for (minor=0; minor < MAX_MD_DEVS; ++minor)
 		devfs_mk_bdev(MKDEV(MAJOR_NR, minor),
 				S_IFBLK|S_IRUSR|S_IWUSR,
 				"md/%d", minor);
-	}
+
+	for (minor=0; minor < MAX_MD_DEVS; ++minor)
+		devfs_mk_bdev(MKDEV(mdp_major, minor<<MdpMinorShift),
+			      S_IFBLK|S_IRUSR|S_IWUSR,
+			      "md/d%d", minor);
+
 
 	register_reboot_notifier(&md_notifier);
 	raid_table_header = register_sysctl_table(raid_root_table, 1);
@@ -3568,11 +3616,16 @@ static __exit void md_exit(void)
 	struct list_head *tmp;
 	int i;
 	blk_unregister_region(MKDEV(MAJOR_NR,0), MAX_MD_DEVS);
+	blk_unregister_region(MKDEV(mdp_major,0), MAX_MD_DEVS << MdpMinorShift);
 	for (i=0; i < MAX_MD_DEVS; i++)
 		devfs_remove("md/%d", i);
+	for (i=0; i < MAX_MD_DEVS; i++)
+		devfs_remove("md/d%d", i);
+
 	devfs_remove("md");
 
 	unregister_blkdev(MAJOR_NR,"md");
+	unregister_blkdev(mdp_major, "mdp");
 	unregister_reboot_notifier(&md_notifier);
 	unregister_sysctl_table(raid_table_header);
 	remove_proc_entry("mdstat", NULL);
--- diff/drivers/md/raid1.c	2004-02-18 08:54:09.000000000 +0000
+++ source/drivers/md/raid1.c	2004-02-23 13:56:43.000000000 +0000
@@ -42,7 +42,7 @@ static void * r1bio_pool_alloc(int gfp_f
 	mddev_t *mddev = data;
 	r1bio_t *r1_bio;
 
-	/* allocate a r1bio with room for raid_disks entries in the write_bios array */
+	/* allocate a r1bio with room for raid_disks entries in the bios array */
 	r1_bio = kmalloc(sizeof(r1bio_t) + sizeof(struct bio*)*mddev->raid_disks,
 			 gfp_flags);
 	if (r1_bio)
@@ -56,8 +56,8 @@ static void r1bio_pool_free(void *r1_bio
 	kfree(r1_bio);
 }
 
-//#define RESYNC_BLOCK_SIZE (64*1024)
-#define RESYNC_BLOCK_SIZE PAGE_SIZE
+#define RESYNC_BLOCK_SIZE (64*1024)
+//#define RESYNC_BLOCK_SIZE PAGE_SIZE
 #define RESYNC_SECTORS (RESYNC_BLOCK_SIZE >> 9)
 #define RESYNC_PAGES ((RESYNC_BLOCK_SIZE + PAGE_SIZE-1) / PAGE_SIZE)
 #define RESYNC_WINDOW (2048*1024)
@@ -73,38 +73,39 @@ static void * r1buf_pool_alloc(int gfp_f
 	r1_bio = r1bio_pool_alloc(gfp_flags, conf->mddev);
 	if (!r1_bio)
 		return NULL;
-	bio = bio_alloc(gfp_flags, RESYNC_PAGES);
-	if (!bio)
-		goto out_free_r1_bio;
 
+	/*
+	 * Allocate bios : 1 for reading, n-1 for writing
+	 */
+	for (j = conf->raid_disks ; j-- ; ) {
+		bio = bio_alloc(gfp_flags, RESYNC_PAGES);
+		if (!bio)
+			goto out_free_bio;
+		r1_bio->bios[j] = bio;
+	}
+	/*
+	 * Allocate RESYNC_PAGES data pages and attach them to
+	 * the first bio;
+	 */
+	bio = r1_bio->bios[0];
 	for (i = 0; i < RESYNC_PAGES; i++) {
 		page = alloc_page(gfp_flags);
 		if (unlikely(!page))
 			goto out_free_pages;
 
 		bio->bi_io_vec[i].bv_page = page;
-		bio->bi_io_vec[i].bv_len = PAGE_SIZE;
-		bio->bi_io_vec[i].bv_offset = 0;
 	}
 
-	/*
-	 * Allocate a single data page for this iovec.
-	 */
-	bio->bi_vcnt = RESYNC_PAGES;
-	bio->bi_idx = 0;
-	bio->bi_size = RESYNC_BLOCK_SIZE;
-	bio->bi_end_io = NULL;
-	atomic_set(&bio->bi_cnt, 1);
-
 	r1_bio->master_bio = bio;
 
 	return r1_bio;
 
 out_free_pages:
-	for (j = 0; j < i; j++)
-		__free_page(bio->bi_io_vec[j].bv_page);
-	bio_put(bio);
-out_free_r1_bio:
+	for ( ; i > 0 ; i--)
+		__free_page(bio->bi_io_vec[i-1].bv_page);
+out_free_bio:
+	while ( j < conf->raid_disks )
+		bio_put(r1_bio->bios[++j]);
 	r1bio_pool_free(r1_bio, conf->mddev);
 	return NULL;
 }
@@ -114,17 +115,15 @@ static void r1buf_pool_free(void *__r1_b
 	int i;
 	conf_t *conf = data;
 	r1bio_t *r1bio = __r1_bio;
-	struct bio *bio = r1bio->master_bio;
+	struct bio *bio = r1bio->bios[0];
 
-	if (atomic_read(&bio->bi_cnt) != 1)
-		BUG();
 	for (i = 0; i < RESYNC_PAGES; i++) {
 		__free_page(bio->bi_io_vec[i].bv_page);
 		bio->bi_io_vec[i].bv_page = NULL;
 	}
-	if (atomic_read(&bio->bi_cnt) != 1)
-		BUG();
-	bio_put(bio);
+	for (i=0 ; i < conf->raid_disks; i++)
+		bio_put(r1bio->bios[i]);
+
 	r1bio_pool_free(r1bio, conf->mddev);
 }
 
@@ -132,19 +131,10 @@ static void put_all_bios(conf_t *conf, r
 {
 	int i;
 
-	if (r1_bio->read_bio) {
-		if (atomic_read(&r1_bio->read_bio->bi_cnt) != 1)
-			BUG();
-		bio_put(r1_bio->read_bio);
-		r1_bio->read_bio = NULL;
-	}
 	for (i = 0; i < conf->raid_disks; i++) {
-		struct bio **bio = r1_bio->write_bios + i;
-		if (*bio) {
-			if (atomic_read(&(*bio)->bi_cnt) != 1)
-				BUG();
+		struct bio **bio = r1_bio->bios + i;
+		if (*bio)
 			bio_put(*bio);
-		}
 		*bio = NULL;
 	}
 }
@@ -173,15 +163,8 @@ static inline void free_r1bio(r1bio_t *r
 static inline void put_buf(r1bio_t *r1_bio)
 {
 	conf_t *conf = mddev_to_conf(r1_bio->mddev);
-	struct bio *bio = r1_bio->master_bio;
 	unsigned long flags;
 
-	/*
-	 * undo any possible partial request fixup magic:
-	 */
-	if (bio->bi_size != RESYNC_BLOCK_SIZE)
-		bio->bi_io_vec[bio->bi_vcnt-1].bv_len = PAGE_SIZE;
-	put_all_bios(conf, r1_bio);
 	mempool_free(r1_bio, conf->r1buf_pool);
 
 	spin_lock_irqsave(&conf->resync_lock, flags);
@@ -258,10 +241,10 @@ static inline void update_head_pos(int d
 	conf_t *conf = mddev_to_conf(r1_bio->mddev);
 
 	conf->mirrors[disk].head_position =
-		r1_bio->sector + (r1_bio->master_bio->bi_size >> 9);
+		r1_bio->sector + (r1_bio->sectors);
 }
 
-static int raid1_end_request(struct bio *bio, unsigned int bytes_done, int error)
+static int raid1_end_read_request(struct bio *bio, unsigned int bytes_done, int error)
 {
 	int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags);
 	r1bio_t * r1_bio = (r1bio_t *)(bio->bi_private);
@@ -271,13 +254,7 @@ static int raid1_end_request(struct bio 
 	if (bio->bi_size)
 		return 1;
 	
-	if (r1_bio->cmd == READ || r1_bio->cmd == READA)
-		mirror = r1_bio->read_disk;
-	else {
-		for (mirror = 0; mirror < conf->raid_disks; mirror++)
-			if (r1_bio->write_bios[mirror] == bio)
-				break;
-	}
+	mirror = r1_bio->read_disk;
 	/*
 	 * this branch is our 'one mirror IO has finished' event handler:
 	 */
@@ -296,42 +273,74 @@ static int raid1_end_request(struct bio 
 		set_bit(R1BIO_Uptodate, &r1_bio->state);
 
 	update_head_pos(mirror, r1_bio);
-	if ((r1_bio->cmd == READ) || (r1_bio->cmd == READA)) {
-		if (!r1_bio->read_bio)
-			BUG();
+
+	/*
+	 * we have only one bio on the read side
+	 */
+	if (uptodate)
+		raid_end_bio_io(r1_bio);
+	else {
 		/*
-		 * we have only one bio on the read side
+		 * oops, read error:
 		 */
-		if (uptodate)
-			raid_end_bio_io(r1_bio);
-		else {
-			/*
-			 * oops, read error:
-			 */
-			char b[BDEVNAME_SIZE];
-			printk(KERN_ERR "raid1: %s: rescheduling sector %llu\n",
-				bdevname(conf->mirrors[mirror].rdev->bdev,b), (unsigned long long)r1_bio->sector);
-			reschedule_retry(r1_bio);
-		}
-	} else {
+		char b[BDEVNAME_SIZE];
+		printk(KERN_ERR "raid1: %s: rescheduling sector %llu\n",
+		       bdevname(conf->mirrors[mirror].rdev->bdev,b), (unsigned long long)r1_bio->sector);
+		reschedule_retry(r1_bio);
+	}
 
-		if (r1_bio->read_bio)
-			BUG();
+	atomic_dec(&conf->mirrors[mirror].rdev->nr_pending);
+	return 0;
+}
+
+static int raid1_end_write_request(struct bio *bio, unsigned int bytes_done, int error)
+{
+	int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags);
+	r1bio_t * r1_bio = (r1bio_t *)(bio->bi_private);
+	int mirror;
+	conf_t *conf = mddev_to_conf(r1_bio->mddev);
+
+	if (bio->bi_size)
+		return 1;
+
+	for (mirror = 0; mirror < conf->raid_disks; mirror++)
+		if (r1_bio->bios[mirror] == bio)
+			break;
+
+	/*
+	 * this branch is our 'one mirror IO has finished' event handler:
+	 */
+	if (!uptodate)
+		md_error(r1_bio->mddev, conf->mirrors[mirror].rdev);
+	else
 		/*
-		 * WRITE:
+		 * Set R1BIO_Uptodate in our master bio, so that
+		 * we will return a good error code for to the higher
+		 * levels even if IO on some other mirrored buffer fails.
 		 *
-		 * Let's see if all mirrored write operations have finished
-		 * already.
+		 * The 'master' represents the composite IO operation to
+		 * user-side. So if something waits for IO, then it will
+		 * wait for the 'master' bio.
 		 */
-		if (atomic_dec_and_test(&r1_bio->remaining)) {
-			md_write_end(r1_bio->mddev);
-			raid_end_bio_io(r1_bio);
-		}	
+		set_bit(R1BIO_Uptodate, &r1_bio->state);
+
+	update_head_pos(mirror, r1_bio);
+
+	/*
+	 *
+	 * Let's see if all mirrored write operations have finished
+	 * already.
+	 */
+	if (atomic_dec_and_test(&r1_bio->remaining)) {
+		md_write_end(r1_bio->mddev);
+		raid_end_bio_io(r1_bio);
 	}
+
 	atomic_dec(&conf->mirrors[mirror].rdev->nr_pending);
 	return 0;
 }
 
+
 /*
  * This routine returns the disk from which the requested read should
  * be done. There is a per-array 'next expected sequential IO' sector
@@ -490,26 +499,25 @@ static int make_request(request_queue_t 
 	r1_bio = mempool_alloc(conf->r1bio_pool, GFP_NOIO);
 
 	r1_bio->master_bio = bio;
+	r1_bio->sectors = bio->bi_size >> 9;
 
 	r1_bio->mddev = mddev;
 	r1_bio->sector = bio->bi_sector;
-	r1_bio->cmd = bio_data_dir(bio);
 
-	if (r1_bio->cmd == READ) {
+	if (bio_data_dir(bio) == READ) {
 		/*
 		 * read balancing logic:
 		 */
 		mirror = conf->mirrors + read_balance(conf, bio, r1_bio);
 
 		read_bio = bio_clone(bio, GFP_NOIO);
-		if (r1_bio->read_bio)
-			BUG();
-		r1_bio->read_bio = read_bio;
+
+		r1_bio->bios[r1_bio->read_disk] = read_bio;
 
 		read_bio->bi_sector = r1_bio->sector + mirror->rdev->data_offset;
 		read_bio->bi_bdev = mirror->rdev->bdev;
-		read_bio->bi_end_io = raid1_end_request;
-		read_bio->bi_rw = r1_bio->cmd;
+		read_bio->bi_end_io = raid1_end_read_request;
+		read_bio->bi_rw = READ;
 		read_bio->bi_private = r1_bio;
 
 		generic_make_request(read_bio);
@@ -521,16 +529,16 @@ static int make_request(request_queue_t 
 	 */
 	/* first select target devices under spinlock and
 	 * inc refcount on their rdev.  Record them by setting
-	 * write_bios[x] to bio
+	 * bios[x] to bio
 	 */
 	spin_lock_irq(&conf->device_lock);
 	for (i = 0;  i < disks; i++) {
 		if (conf->mirrors[i].rdev &&
 		    !conf->mirrors[i].rdev->faulty) {
 			atomic_inc(&conf->mirrors[i].rdev->nr_pending);
-			r1_bio->write_bios[i] = bio;
+			r1_bio->bios[i] = bio;
 		} else
-			r1_bio->write_bios[i] = NULL;
+			r1_bio->bios[i] = NULL;
 	}
 	spin_unlock_irq(&conf->device_lock);
 
@@ -538,16 +546,16 @@ static int make_request(request_queue_t 
 	md_write_start(mddev);
 	for (i = 0; i < disks; i++) {
 		struct bio *mbio;
-		if (!r1_bio->write_bios[i])
+		if (!r1_bio->bios[i])
 			continue;
 
 		mbio = bio_clone(bio, GFP_NOIO);
-		r1_bio->write_bios[i] = mbio;
+		r1_bio->bios[i] = mbio;
 
 		mbio->bi_sector	= r1_bio->sector + conf->mirrors[i].rdev->data_offset;
 		mbio->bi_bdev = conf->mirrors[i].rdev->bdev;
-		mbio->bi_end_io	= raid1_end_request;
-		mbio->bi_rw = r1_bio->cmd;
+		mbio->bi_end_io	= raid1_end_write_request;
+		mbio->bi_rw = WRITE;
 		mbio->bi_private = r1_bio;
 
 		atomic_inc(&r1_bio->remaining);
@@ -744,7 +752,7 @@ static int end_sync_read(struct bio *bio
 	if (bio->bi_size)
 		return 1;
 
-	if (r1_bio->read_bio != bio)
+	if (r1_bio->bios[r1_bio->read_disk] != bio)
 		BUG();
 	update_head_pos(r1_bio->read_disk, r1_bio);
 	/*
@@ -775,7 +783,7 @@ static int end_sync_write(struct bio *bi
 		return 1;
 
 	for (i = 0; i < conf->raid_disks; i++)
-		if (r1_bio->write_bios[i] == bio) {
+		if (r1_bio->bios[i] == bio) {
 			mirror = i;
 			break;
 		}
@@ -784,7 +792,7 @@ static int end_sync_write(struct bio *bi
 	update_head_pos(mirror, r1_bio);
 
 	if (atomic_dec_and_test(&r1_bio->remaining)) {
-		md_done_sync(mddev, r1_bio->master_bio->bi_size >> 9, uptodate);
+		md_done_sync(mddev, r1_bio->sectors, uptodate);
 		put_buf(r1_bio);
 	}
 	atomic_dec(&conf->mirrors[mirror].rdev->nr_pending);
@@ -796,12 +804,11 @@ static void sync_request_write(mddev_t *
 	conf_t *conf = mddev_to_conf(mddev);
 	int i;
 	int disks = conf->raid_disks;
-	struct bio *bio, *mbio;
+	struct bio *bio, *wbio;
 
-	bio = r1_bio->master_bio;
+	bio = r1_bio->bios[r1_bio->read_disk];
 
 	/*
-	 * have to allocate lots of bio structures and
 	 * schedule writes
 	 */
 	if (!test_bit(R1BIO_Uptodate, &r1_bio->state)) {
@@ -814,52 +821,25 @@ static void sync_request_write(mddev_t *
 			" for block %llu\n",
 			bdevname(bio->bi_bdev,b), 
 			(unsigned long long)r1_bio->sector);
-		md_done_sync(mddev, r1_bio->master_bio->bi_size >> 9, 0);
+		md_done_sync(mddev, r1_bio->sectors, 0);
 		put_buf(r1_bio);
 		return;
 	}
 
-	spin_lock_irq(&conf->device_lock);
-	for (i = 0; i < disks ; i++) {
-		r1_bio->write_bios[i] = NULL;
-		if (!conf->mirrors[i].rdev || 
-		    conf->mirrors[i].rdev->faulty)
-			continue;
-		if (conf->mirrors[i].rdev->bdev == bio->bi_bdev)
-			/*
-			 * we read from here, no need to write
-			 */
-			continue;
-		if (conf->mirrors[i].rdev->in_sync && 
-			r1_bio->sector + (bio->bi_size>>9) <= mddev->recovery_cp)
-			/*
-			 * don't need to write this we are just rebuilding
-			 */
-			continue;
-		atomic_inc(&conf->mirrors[i].rdev->nr_pending);
-		r1_bio->write_bios[i] = bio;
-	}
-	spin_unlock_irq(&conf->device_lock);
-
 	atomic_set(&r1_bio->remaining, 1);
-	for (i = disks; i-- ; ) {
-		if (!r1_bio->write_bios[i])
+	for (i = 0; i < disks ; i++) {
+		wbio = r1_bio->bios[i];
+		if (wbio->bi_end_io != end_sync_write)
 			continue;
-		mbio = bio_clone(bio, GFP_NOIO);
-		r1_bio->write_bios[i] = mbio;
-		mbio->bi_bdev = conf->mirrors[i].rdev->bdev;
-		mbio->bi_sector = r1_bio->sector + conf->mirrors[i].rdev->data_offset;
-		mbio->bi_end_io	= end_sync_write;
-		mbio->bi_rw = WRITE;
-		mbio->bi_private = r1_bio;
 
+		atomic_inc(&conf->mirrors[i].rdev->nr_pending);
 		atomic_inc(&r1_bio->remaining);
-		md_sync_acct(conf->mirrors[i].rdev, mbio->bi_size >> 9);
-		generic_make_request(mbio);
+		md_sync_acct(conf->mirrors[i].rdev, wbio->bi_size >> 9);
+		generic_make_request(wbio);
 	}
 
 	if (atomic_dec_and_test(&r1_bio->remaining)) {
-		md_done_sync(mddev, r1_bio->master_bio->bi_size >> 9, 1);
+		md_done_sync(mddev, r1_bio->sectors, 1);
 		put_buf(r1_bio);
 	}
 }
@@ -896,30 +876,26 @@ static void raid1d(mddev_t *mddev)
 		mddev = r1_bio->mddev;
 		conf = mddev_to_conf(mddev);
 		bio = r1_bio->master_bio;
-		switch(r1_bio->cmd) {
-		case SPECIAL:
+		if (test_bit(R1BIO_IsSync, &r1_bio->state)) {
 			sync_request_write(mddev, r1_bio);
-			break;
-		case READ:
-		case READA:
+		} else {
 			if (map(mddev, &rdev) == -1) {
 				printk(KERN_ALERT "raid1: %s: unrecoverable I/O"
-				" read error for block %llu\n",
-				bdevname(bio->bi_bdev,b),
-				(unsigned long long)r1_bio->sector);
+				       " read error for block %llu\n",
+				       bdevname(bio->bi_bdev,b),
+				       (unsigned long long)r1_bio->sector);
 				raid_end_bio_io(r1_bio);
-				break;
-			}
-			printk(KERN_ERR "raid1: %s: redirecting sector %llu to"
-				" another mirror\n",
-				bdevname(rdev->bdev,b),
-				(unsigned long long)r1_bio->sector);
-			bio->bi_bdev = rdev->bdev;
-			bio->bi_sector = r1_bio->sector + rdev->data_offset;
-			bio->bi_rw = r1_bio->cmd;
+			} else {
+				printk(KERN_ERR "raid1: %s: redirecting sector %llu to"
+				       " another mirror\n",
+				       bdevname(rdev->bdev,b),
+				       (unsigned long long)r1_bio->sector);
+				bio->bi_bdev = rdev->bdev;
+				bio->bi_sector = r1_bio->sector + rdev->data_offset;
+				bio->bi_rw = READ;
 
-			generic_make_request(bio);
-			break;
+				generic_make_request(bio);
+			}
 		}
 	}
 	spin_unlock_irqrestore(&retry_list_lock, flags);
@@ -955,9 +931,10 @@ static int sync_request(mddev_t *mddev, 
 	conf_t *conf = mddev_to_conf(mddev);
 	mirror_info_t *mirror;
 	r1bio_t *r1_bio;
-	struct bio *read_bio, *bio;
+	struct bio *bio;
 	sector_t max_sector, nr_sectors;
-	int disk, partial;
+	int disk;
+	int i;
 
 	if (!conf->r1buf_pool)
 		if (init_resync(conf))
@@ -1007,38 +984,77 @@ static int sync_request(mddev_t *mddev, 
 
 	r1_bio->mddev = mddev;
 	r1_bio->sector = sector_nr;
-	r1_bio->cmd = SPECIAL;
+	set_bit(R1BIO_IsSync, &r1_bio->state);
 	r1_bio->read_disk = disk;
 
-	bio = r1_bio->master_bio;
-	nr_sectors = RESYNC_BLOCK_SIZE >> 9;
-	if (max_sector - sector_nr < nr_sectors)
-		nr_sectors = max_sector - sector_nr;
-	bio->bi_size = nr_sectors << 9;
-	bio->bi_vcnt = (bio->bi_size + PAGE_SIZE-1) / PAGE_SIZE;
-	/*
-	 * Is there a partial page at the end of the request?
-	 */
-	partial = bio->bi_size % PAGE_SIZE;
-	if (partial)
-		bio->bi_io_vec[bio->bi_vcnt-1].bv_len = partial;
-
+	for (i=0; i < conf->raid_disks; i++) {
+		bio = r1_bio->bios[i];
 
-	read_bio = bio_clone(r1_bio->master_bio, GFP_NOIO);
-
-	read_bio->bi_sector = sector_nr + mirror->rdev->data_offset;
-	read_bio->bi_bdev = mirror->rdev->bdev;
-	read_bio->bi_end_io = end_sync_read;
-	read_bio->bi_rw = READ;
-	read_bio->bi_private = r1_bio;
-
-	if (r1_bio->read_bio)
-		BUG();
-	r1_bio->read_bio = read_bio;
+		/* take from bio_init */
+		bio->bi_next = NULL;
+		bio->bi_flags |= 1 << BIO_UPTODATE;
+		bio->bi_rw = 0;
+		bio->bi_vcnt = 0;
+		bio->bi_idx = 0;
+		bio->bi_phys_segments = 0;
+		bio->bi_hw_segments = 0;
+		bio->bi_size = 0;
+		bio->bi_end_io = NULL;
+		bio->bi_private = NULL;
+
+		if (i == disk) {
+			bio->bi_rw = READ;
+			bio->bi_end_io = end_sync_read;
+		} else if (conf->mirrors[i].rdev &&
+			   !conf->mirrors[i].rdev->faulty &&
+			   (!conf->mirrors[i].rdev->in_sync ||
+			    sector_nr + RESYNC_SECTORS > mddev->recovery_cp)) {
+			bio->bi_rw = WRITE;
+			bio->bi_end_io = end_sync_write;
+		} else
+			continue;
+		bio->bi_sector = sector_nr + conf->mirrors[i].rdev->data_offset;
+		bio->bi_bdev = conf->mirrors[i].rdev->bdev;
+		bio->bi_private = r1_bio;
+	}
+	nr_sectors = 0;
+	do {
+		struct page *page;
+		int len = PAGE_SIZE;
+		if (sector_nr + (len>>9) > max_sector)
+			len = (max_sector - sector_nr) << 9;
+		if (len == 0)
+			break;
+		for (i=0 ; i < conf->raid_disks; i++) {
+			bio = r1_bio->bios[i];
+			if (bio->bi_end_io) {
+				page = r1_bio->bios[0]->bi_io_vec[bio->bi_vcnt].bv_page;
+				if (bio_add_page(bio, page, len, 0) == 0) {
+					/* stop here */
+					r1_bio->bios[0]->bi_io_vec[bio->bi_vcnt].bv_page = page;
+					while (i > 0) {
+						i--;
+						bio = r1_bio->bios[i];
+						if (bio->bi_end_io==NULL) continue;
+						/* remove last page from this bio */
+						bio->bi_vcnt--;
+						bio->bi_size -= len;
+						bio->bi_flags &= ~(1<< BIO_SEG_VALID);
+					}
+					goto bio_full;
+				}
+			}
+		}
+		nr_sectors += len>>9;
+		sector_nr += len>>9;
+	} while (r1_bio->bios[disk]->bi_vcnt < RESYNC_PAGES);
+ bio_full:
+	bio = r1_bio->bios[disk];
+	r1_bio->sectors = nr_sectors;
 
 	md_sync_acct(mirror->rdev, nr_sectors);
 
-	generic_make_request(read_bio);
+	generic_make_request(bio);
 
 	return nr_sectors;
 }
--- diff/drivers/md/raid5.c	2004-02-18 08:54:09.000000000 +0000
+++ source/drivers/md/raid5.c	2004-02-23 13:56:43.000000000 +0000
@@ -284,7 +284,7 @@ static int grow_stripes(raid5_conf_t *co
 	kmem_cache_t *sc;
 	int devs = conf->raid_disks;
 
-	sprintf(conf->cache_name, "md/raid5-%d", conf->mddev->__minor);
+	sprintf(conf->cache_name, "raid5/%s", mdname(conf->mddev));
 
 	sc = kmem_cache_create(conf->cache_name, 
 			       sizeof(struct stripe_head)+(devs-1)*sizeof(struct r5dev),
--- diff/drivers/md/raid6main.c	2004-02-18 08:54:09.000000000 +0000
+++ source/drivers/md/raid6main.c	2004-02-23 13:56:43.000000000 +0000
@@ -303,7 +303,7 @@ static int grow_stripes(raid6_conf_t *co
 	kmem_cache_t *sc;
 	int devs = conf->raid_disks;
 
-	sprintf(conf->cache_name, "md/raid6-%d", conf->mddev->__minor);
+	sprintf(conf->cache_name, "raid6/%s", mdname(conf->mddev));
 
 	sc = kmem_cache_create(conf->cache_name,
 			       sizeof(struct stripe_head)+(devs-1)*sizeof(struct r5dev),
--- diff/drivers/media/dvb/Kconfig	2004-01-19 10:22:57.000000000 +0000
+++ source/drivers/media/dvb/Kconfig	2004-02-23 13:56:43.000000000 +0000
@@ -18,11 +18,12 @@ config DVB
 	  Please report problems regarding this driver to the LinuxDVB 
 	  mailing list.
 
-	  You might want add the following lines to your /etc/modules.conf:
+	  You might want add the following lines to your /etc/modprobe.conf:
 	  	
 	  	alias char-major-250 dvb
 	  	alias dvb dvb-ttpci
-	  	below dvb-ttpci alps_bsru6 alps_bsrv2 \
+	  	install dvb-ttpci /sbin/modprobe --first-time -i dvb-ttpci && \
+			/sbin/modprobe -a alps_bsru6 alps_bsrv2 \
 	  			grundig_29504-401 grundig_29504-491 \
 	  			ves1820
 
--- diff/drivers/media/dvb/dvb-core/dvb_net.c	2003-10-09 09:47:34.000000000 +0100
+++ source/drivers/media/dvb/dvb-core/dvb_net.c	2004-02-23 13:56:43.000000000 +0000
@@ -523,7 +523,8 @@ static int dvb_net_add_if(struct dvb_net
         net->base_addr = pid;
                 
 	if ((result = register_netdev(net)) < 0) {
-		kfree(net);
+		dvbnet->device[if_num] = NULL;
+		free_netdev(net);
 		return result;
 	}
 
@@ -545,6 +546,7 @@ static int dvb_net_remove_if(struct dvb_
 	flush_scheduled_work();
         unregister_netdev(net);
 	dvbnet->state[num]=0;
+	dvbnet->device[num] = NULL;
 	free_netdev(net);
 
 	return 0;
--- diff/drivers/media/dvb/frontends/alps_tdlb7.c	2003-10-27 09:20:37.000000000 +0000
+++ source/drivers/media/dvb/frontends/alps_tdlb7.c	2004-02-23 13:56:43.000000000 +0000
@@ -35,6 +35,7 @@
 #include <linux/init.h>
 #include <linux/vmalloc.h>
 #include <linux/fs.h>
+#include <linux/syscalls.h>
 #include <linux/unistd.h>
 #include <linux/delay.h>
 
--- diff/drivers/media/dvb/frontends/dst.c	2004-02-18 08:54:09.000000000 +0000
+++ source/drivers/media/dvb/frontends/dst.c	2004-02-23 13:56:43.000000000 +0000
@@ -1149,8 +1149,8 @@ static int dst_attach (struct dvb_i2c_bu
 	}
 
 	dst_init (dst);
-	dprintk("%s: register dst %8.8x bt %8.8x i2c %8.8x\n", __FUNCTION__, 
-			(u32)dst, (u32)(dst->bt), (u32)(dst->i2c));
+	dprintk("%s: register dst %p bt %p i2c %p\n", __FUNCTION__, 
+		dst, dst->bt, dst->i2c);
 
 	info = &dst_info_sat;
 	if (dst->dst_type == DST_TYPE_IS_TERR)
@@ -1166,7 +1166,7 @@ static int dst_attach (struct dvb_i2c_bu
 static void dst_detach (struct dvb_i2c_bus *i2c, void *data)
 {
 	dvb_unregister_frontend (dst_ioctl, i2c);
-	dprintk("%s: unregister dst %8.8x\n", __FUNCTION__, (u32)(data));
+	dprintk("%s: unregister dst %p\n", __FUNCTION__, data);
 	if (data)
 		kfree(data);
 }
--- diff/drivers/media/dvb/frontends/sp887x.c	2004-01-19 10:22:57.000000000 +0000
+++ source/drivers/media/dvb/frontends/sp887x.c	2004-02-23 13:56:43.000000000 +0000
@@ -19,6 +19,7 @@
 #include <linux/init.h>
 #include <linux/string.h>
 #include <linux/slab.h>
+#include <linux/syscalls.h>
 #include <linux/fs.h>
 #include <linux/unistd.h>
 #include <linux/fcntl.h>
--- diff/drivers/media/dvb/frontends/tda1004x.c	2004-01-19 10:22:57.000000000 +0000
+++ source/drivers/media/dvb/frontends/tda1004x.c	2004-02-23 13:56:43.000000000 +0000
@@ -37,6 +37,7 @@
 #include <linux/init.h>
 #include <linux/string.h>
 #include <linux/slab.h>
+#include <linux/syscalls.h>
 #include <linux/fs.h>
 #include <linux/unistd.h>
 #include <linux/fcntl.h>
--- diff/drivers/media/dvb/ttusb-dec/ttusb_dec.c	2004-02-18 08:54:09.000000000 +0000
+++ source/drivers/media/dvb/ttusb-dec/ttusb_dec.c	2004-02-23 13:56:43.000000000 +0000
@@ -1186,7 +1186,7 @@ static int ttusb_dec_boot_dsp(struct ttu
 	firmware_size = fw_entry->size;
 
 	if (firmware_size < 60) {
-		printk("%s: firmware size too small for DSP code (%u < 60).\n",
+		printk("%s: firmware size too small for DSP code (%zu < 60).\n",
 			__FUNCTION__, firmware_size);
 		return -1;
 	}
--- diff/drivers/media/radio/Kconfig	2003-09-30 15:46:15.000000000 +0100
+++ source/drivers/media/radio/Kconfig	2004-02-23 13:56:43.000000000 +0000
@@ -223,6 +223,20 @@ config RADIO_SF16FMI
 	  To compile this driver as a module, choose M here: the
 	  module will be called radio-sf16fmi.
 
+config RADIO_SF16FMR2
+	tristate "SF16FMR2 Radio"
+	depends on ISA && VIDEO_DEV
+	---help---
+	  Choose Y here if you have one of these FM radio cards.
+
+	  In order to control your radio card, you will need to use programs
+	  that are compatible with the Video For Linux API.  Information on
+	  this API and pointers to "v4l" programs may be found on the WWW at
+	  <http://roadrunner.swansea.uk.linux.org/v4l.shtml>.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called radio-sf16fmr2.
+
 config RADIO_TERRATEC
 	tristate "TerraTec ActiveRadio ISA Standalone"
 	depends on ISA && VIDEO_DEV
--- diff/drivers/media/radio/Makefile	2003-02-13 11:46:52.000000000 +0000
+++ source/drivers/media/radio/Makefile	2004-02-23 13:56:43.000000000 +0000
@@ -7,6 +7,7 @@ miropcm20-objs	:= miropcm20-rds-core.o m
 obj-$(CONFIG_RADIO_AZTECH) += radio-aztech.o
 obj-$(CONFIG_RADIO_RTRACK2) += radio-rtrack2.o
 obj-$(CONFIG_RADIO_SF16FMI) += radio-sf16fmi.o
+obj-$(CONFIG_RADIO_SF16FMR2) += radio-sf16fmr2.o
 obj-$(CONFIG_RADIO_CADET) += radio-cadet.o
 obj-$(CONFIG_RADIO_TYPHOON) += radio-typhoon.o
 obj-$(CONFIG_RADIO_TERRATEC) += radio-terratec.o
--- diff/drivers/media/video/c-qcam.c	2003-10-09 09:47:34.000000000 +0100
+++ source/drivers/media/video/c-qcam.c	2004-02-23 13:56:43.000000000 +0000
@@ -818,10 +818,9 @@ static void cq_detach(struct parport *po
 }
 
 static struct parport_driver cqcam_driver = {
-	"cqcam",
-	cq_attach,
-	cq_detach,
-	NULL
+	.name = "cqcam",
+	.attach = cq_attach,
+	.detach = cq_detach,
 };
 
 static int __init cqcam_init (void)
--- diff/drivers/media/video/cpia_pp.c	2003-10-09 09:47:34.000000000 +0100
+++ source/drivers/media/video/cpia_pp.c	2004-02-23 13:56:43.000000000 +0000
@@ -803,10 +803,9 @@ static void cpia_pp_attach (struct parpo
 }
 
 static struct parport_driver cpia_pp_driver = {
-	"cpia_pp",
-	cpia_pp_attach,
-	cpia_pp_detach,
-	NULL
+	.name = "cpia_pp",
+	.attach = cpia_pp_attach,
+	.detach = cpia_pp_detach,
 };
 
 int cpia_pp_init(void)
@@ -853,11 +852,6 @@ int init_module(void)
 			}
 		}
 	}
-#if defined(CONFIG_KMOD) && defined(CONFIG_PNP_PARPORT_MODULE)
-	if(parport_enumerate() && !parport_enumerate()->probe_info.model) {
-		request_module("parport_probe");
-	}
-#endif
 	return cpia_pp_init();
 }
 
--- diff/drivers/media/video/saa5249.c	2003-11-25 15:24:57.000000000 +0000
+++ source/drivers/media/video/saa5249.c	2004-02-23 13:56:43.000000000 +0000
@@ -122,10 +122,6 @@ struct saa5249_device
 #define FALSE 0
 #define TRUE 1
 #endif
-#ifndef MIN
-#define MIN(a, b) ((a) < (b) ? (a) : (b))
-#define MAX(a, b) ((a) > (b) ? (a) : (b))
-#endif
 
 #define RESCHED do { cond_resched(); } while(0)
 
@@ -518,8 +514,8 @@ static int do_saa5249_ioctl(struct inode
 			{
 				int len;
 				char buf[16];  
-				start = MAX(req->start, 32);
-				end = MIN(req->end, 39);
+				start = max(req->start, 32);
+				end = min(req->end, 39);
 				len=end-start+1;
 				if (i2c_senddata(t, 8, 0, 0, start, -1) ||
 					i2c_getdata(t, len, buf))
@@ -532,8 +528,8 @@ static int do_saa5249_ioctl(struct inode
 			{
 				char buf[32];
 				int len;
-				start = MAX(req->start, 7);
-				end = MIN(req->end, 31);
+				start = max(req->start, 7);
+				end = min(req->end, 31);
 				len=end-start+1;
 				if (i2c_senddata(t, 8, 0, 0, start, -1) ||
 					i2c_getdata(t, len, buf))
--- diff/drivers/media/video/tuner.c	2004-02-18 08:54:10.000000000 +0000
+++ source/drivers/media/video/tuner.c	2004-02-23 13:56:43.000000000 +0000
@@ -234,6 +234,12 @@ static struct tunertype tuners[] = {
 	  16*157.25,16*454.00,0xa0,0x90,0x30,0x8e,732},
         { "Philips NTSC MK3 (FM1236MK3 or FM1236/F)", Philips, NTSC,
           16*160.00,16*442.00,0x01,0x02,0x04,0x8,732},
+
+        { "Philips 4 in 1 (ATI TV Wonder Pro/Conexant)", Philips, NTSC,
+          16*160.00,16*442.00,0x01,0x02,0x04,0x8e,732},
+	{ "Microtune 4049 FM5",Microtune,PAL,
+	  16*141.00,16*464.00,0xa0,0x90,0x30,0x8e,623},
+
 };
 #define TUNERS ARRAY_SIZE(tuners)
 
@@ -984,19 +990,22 @@ static void set_radio_freq(struct i2c_cl
 	t->radio_freq(c,freq);
 }
 
-static void set_type(struct i2c_client *c, unsigned int type)
+static void set_type(struct i2c_client *c, unsigned int type, char *source)
 {
 	struct tuner *t = i2c_get_clientdata(c);
 
 	if (t->type != UNSET) {
-		printk("tuner: type already set (%d)\n",t->type);
+		if (t->type != type)
+			printk("tuner: type already set to %d, "
+			       "ignoring request for %d\n", t->type, type);
 		return;
 	}
 	if (type >= TUNERS)
 		return;
 
 	t->type = type;
-	printk("tuner: type set to %d (%s)\n", t->type,tuners[t->type].name);
+	printk("tuner: type set to %d (%s) by %s\n",
+	       t->type,tuners[t->type].name, source);
 	strlcpy(c->name, tuners[t->type].name, sizeof(c->name));
 
 	switch (t->type) {
@@ -1024,7 +1033,8 @@ static int tuner_attach(struct i2c_adapt
         client_template.adapter = adap;
         client_template.addr = addr;
 
-        printk("tuner: chip found @ 0x%x\n", addr<<1);
+        printk("tuner: chip found at addr 0x%x i2c-bus %s\n",
+	       addr<<1, adap->name);
 
         if (NULL == (client = kmalloc(sizeof(struct i2c_client), GFP_KERNEL)))
                 return -ENOMEM;
@@ -1040,12 +1050,8 @@ static int tuner_attach(struct i2c_adapt
 	t->radio_if2  = 10700*1000; // 10.7MHz - FM radio
 
         i2c_attach_client(client);
-	if (type < TUNERS) {
- 		t->type = type;
-		printk("tuner: type forced to %d (%s) [insmod]\n",
-		       t->type,tuners[t->type].name);
-		set_type(client,type);
-	}
+	if (type < TUNERS)
+		set_type(client, type, "insmod option");
 	return 0;
 }
 
@@ -1094,7 +1100,7 @@ tuner_command(struct i2c_client *client,
 
 	/* --- configuration --- */
 	case TUNER_SET_TYPE:
-		set_type(client,*iarg);
+		set_type(client,*iarg,client->adapter->name);
 		break;
 	case AUDC_SET_RADIO:
 		if (!t->radio) {
--- diff/drivers/media/video/videocodec.c	2003-10-09 09:47:34.000000000 +0100
+++ source/drivers/media/video/videocodec.c	2004-02-23 13:56:43.000000000 +0000
@@ -108,13 +108,17 @@ videocodec_attach (struct videocodec_mas
 		if ((master->flags & h->codec->flags) == master->flags) {
 			dprintk(4, "videocodec_attach: try '%s'\n",
 				h->codec->name);
+
+			if (!try_module_get(h->codec->owner))
+				return NULL;
+
 			codec =
 			    kmalloc(sizeof(struct videocodec), GFP_KERNEL);
 			if (!codec) {
 				dprintk(1,
 					KERN_ERR
 					"videocodec_attach: no mem\n");
-				return NULL;
+				goto out_module_put;
 			}
 			memcpy(codec, h->codec, sizeof(struct videocodec));
 
@@ -132,26 +136,12 @@ videocodec_attach (struct videocodec_mas
 					dprintk(1,
 						KERN_ERR
 						"videocodec_attach: no memory\n");
-					kfree(codec);
-					return NULL;
+					goto out_kfree;
 				}
 				memset(ptr, 0,
 				       sizeof(struct attached_list));
 				ptr->codec = codec;
 
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
-				MOD_INC_USE_COUNT;
-#else
-				if (!try_module_get(THIS_MODULE)) {
-					dprintk(1,
-						KERN_ERR
-						"videocodec: failed to increment usecount\n");
-					kfree(codec);
-					kfree(ptr);
-					return NULL;
-				}
-#endif
-
 				a = h->list;
 				if (!a) {
 					h->list = ptr;
@@ -177,6 +167,12 @@ videocodec_attach (struct videocodec_mas
 
 	dprintk(1, KERN_ERR "videocodec_attach: no codec found!\n");
 	return NULL;
+
+ out_module_put:
+	module_put(h->codec->owner);
+ out_kfree:
+	kfree(codec);
+	return NULL;
 }
 
 int
@@ -228,16 +224,10 @@ videocodec_detach (struct videocodec *co
 					dprintk(4,
 						"videocodec: delete middle\n");
 				}
+				module_put(a->codec->owner);
 				kfree(a->codec);
 				kfree(a);
 				h->attached -= 1;
-
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
-				MOD_DEC_USE_COUNT;
-#else
-				module_put(THIS_MODULE);
-#endif
-
 				return 0;
 			}
 			prev = a;
@@ -274,18 +264,6 @@ videocodec_register (const struct videoc
 	memset(ptr, 0, sizeof(struct codec_list));
 	ptr->codec = codec;
 
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
-	MOD_INC_USE_COUNT;
-#else
-	if (!try_module_get(THIS_MODULE)) {
-		dprintk(1,
-			KERN_ERR
-			"videocodec: failed to increment module count\n");
-		kfree(ptr);
-		return -ENODEV;
-	}
-#endif
-
 	if (!h) {
 		codeclist_top = ptr;
 		dprintk(4, "videocodec: hooked in as first element\n");
@@ -342,13 +320,6 @@ videocodec_unregister (const struct vide
 					"videocodec: delete middle element\n");
 			}
 			kfree(h);
-
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
-			MOD_DEC_USE_COUNT;
-#else
-			module_put(THIS_MODULE);
-#endif
-
 			return 0;
 		}
 		prev = h;
@@ -392,15 +363,15 @@ videocodec_build_table (void)
 	videocodec_buf = (char *) kmalloc(size, GFP_KERNEL);
 
 	i = 0;
-	i += snprintf(videocodec_buf + i, size - 1,
+	i += scnprintf(videocodec_buf + i, size - 1,
 		      "<S>lave or attached <M>aster name  type flags    magic    ");
-	i += snprintf(videocodec_buf + i, size - 1, "(connected as)\n");
+	i += scnprintf(videocodec_buf + i, size -i - 1, "(connected as)\n");
 
 	h = codeclist_top;
 	while (h) {
 		if (i > (size - LINESIZE))
 			break;	// security check
-		i += snprintf(videocodec_buf + i, size,
+		i += scnprintf(videocodec_buf + i, size -i -1,
 			      "S %32s %04x %08lx %08lx (TEMPLATE)\n",
 			      h->codec->name, h->codec->type,
 			      h->codec->flags, h->codec->magic);
@@ -408,7 +379,7 @@ videocodec_build_table (void)
 		while (a) {
 			if (i > (size - LINESIZE))
 				break;	// security check
-			i += snprintf(videocodec_buf + i, size,
+			i += scnprintf(videocodec_buf + i, size -i -1,
 				      "M %32s %04x %08lx %08lx (%s)\n",
 				      a->codec->master_data->name,
 				      a->codec->master_data->type,
--- diff/drivers/media/video/videocodec.h	2003-08-26 10:00:52.000000000 +0100
+++ source/drivers/media/video/videocodec.h	2004-02-23 13:56:43.000000000 +0000
@@ -249,6 +249,7 @@ struct tvnorm {
 };
 
 struct videocodec {
+	struct module *owner;
 	/* -- filled in by slave device during register -- */
 	char name[32];
 	unsigned long magic;	/* may be used for client<->master attaching */
--- diff/drivers/media/video/w9966.c	2004-02-09 10:36:10.000000000 +0000
+++ source/drivers/media/video/w9966.c	2004-02-23 13:56:43.000000000 +0000
@@ -959,10 +959,9 @@ static void w9966_detach(struct parport 
 
 
 static struct parport_driver w9966_ppd = {
-	W9966_DRIVERNAME,
-	w9966_attach,
-	w9966_detach,
-	NULL
+	.name = W9966_DRIVERNAME,
+	.attach = w9966_attach,
+	.detach = w9966_detach,
 };
 
 // Module entry point
--- diff/drivers/media/video/zr36016.c	2003-08-26 10:00:52.000000000 +0100
+++ source/drivers/media/video/zr36016.c	2004-02-23 13:56:43.000000000 +0000
@@ -422,12 +422,6 @@ zr36016_unset (struct videocodec *codec)
 		codec->data = NULL;
 
 		zr36016_codecs--;
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
-		MOD_DEC_USE_COUNT;
-#else
-		module_put(THIS_MODULE);
-#endif
-
 		return 0;
 	}
 
@@ -470,19 +464,6 @@ zr36016_setup (struct videocodec *codec)
 	ptr->num = zr36016_codecs++;
 	ptr->codec = codec;
 
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
-	MOD_INC_USE_COUNT;
-#else
-	if (!try_module_get(THIS_MODULE)) {
-		dprintk(1,
-			KERN_ERR
-			"zr36016: failed to increase module use count\n");
-		kfree(ptr);
-		zr36016_codecs--;
-		return -ENODEV;
-	}
-#endif
-
 	//testing
 	res = zr36016_basic_test(ptr);
 	if (res < 0) {
@@ -504,6 +485,7 @@ zr36016_setup (struct videocodec *codec)
 }
 
 static const struct videocodec zr36016_codec = {
+	.owner = THIS_MODULE,
 	.name = "zr36016",
 	.magic = 0L,		// magic not used
 	.flags =
--- diff/drivers/media/video/zr36050.c	2003-08-26 10:00:52.000000000 +0100
+++ source/drivers/media/video/zr36050.c	2004-02-23 13:56:43.000000000 +0000
@@ -737,12 +737,6 @@ zr36050_unset (struct videocodec *codec)
 		codec->data = NULL;
 
 		zr36050_codecs--;
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
-		MOD_DEC_USE_COUNT;
-#else
-		module_put(THIS_MODULE);
-#endif
-
 		return 0;
 	}
 
@@ -785,19 +779,6 @@ zr36050_setup (struct videocodec *codec)
 	ptr->num = zr36050_codecs++;
 	ptr->codec = codec;
 
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
-	MOD_INC_USE_COUNT;
-#else
-	if (!try_module_get(THIS_MODULE)) {
-		dprintk(1,
-			KERN_ERR
-			"zr36050: failed to increase module use count\n");
-		kfree(ptr);
-		zr36050_codecs--;
-		return -ENODEV;
-	}
-#endif
-
 	//testing
 	res = zr36050_basic_test(ptr);
 	if (res < 0) {
@@ -826,6 +807,7 @@ zr36050_setup (struct videocodec *codec)
 }
 
 static const struct videocodec zr36050_codec = {
+	.owner = THIS_MODULE,
 	.name = "zr36050",
 	.magic = 0L,		// magic not used
 	.flags =
--- diff/drivers/media/video/zr36060.c	2003-08-26 10:00:52.000000000 +0100
+++ source/drivers/media/video/zr36060.c	2004-02-23 13:56:43.000000000 +0000
@@ -868,12 +868,6 @@ zr36060_unset (struct videocodec *codec)
 		codec->data = NULL;
 
 		zr36060_codecs--;
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
-		MOD_DEC_USE_COUNT;
-#else
-		module_put(THIS_MODULE);
-#endif
-
 		return 0;
 	}
 
@@ -916,19 +910,6 @@ zr36060_setup (struct videocodec *codec)
 	ptr->num = zr36060_codecs++;
 	ptr->codec = codec;
 
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
-	MOD_INC_USE_COUNT;
-#else
-	if (!try_module_get(THIS_MODULE)) {
-		dprintk(1,
-			KERN_ERR
-			"zr36060: failed to increase module use count\n");
-		kfree(ptr);
-		zr36060_codecs--;
-		return -ENODEV;
-	}
-#endif
-
 	//testing
 	res = zr36060_basic_test(ptr);
 	if (res < 0) {
@@ -958,6 +939,7 @@ zr36060_setup (struct videocodec *codec)
 }
 
 static const struct videocodec zr36060_codec = {
+	.owner = THIS_MODULE,
 	.name = "zr36060",
 	.magic = 0L,		// magic not used
 	.flags =
--- diff/drivers/message/fusion/mptbase.c	2004-02-18 08:54:10.000000000 +0000
+++ source/drivers/message/fusion/mptbase.c	2004-02-23 13:56:43.000000000 +0000
@@ -714,6 +714,7 @@ mpt_register(MPT_CALLBACK cbfunc, MPT_DR
 			MptCallbacks[i] = cbfunc;
 			MptDriverClass[i] = dclass;
 			MptEvHandlers[i] = NULL;
+			MptDeviceDriverHandlers[i] = NULL;
 			last_drv_idx = i;
 			if (cbfunc != mpt_base_reply) {
 				mpt_inc_use_count();
@@ -838,11 +839,28 @@ mpt_reset_deregister(int cb_idx)
 int
 mpt_device_driver_register(struct mpt_pci_driver * dd_cbfunc, int cb_idx)
 {
-	if (cb_idx < 1 || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS)
-		return -1;
+	MPT_ADAPTER	*ioc;
+	int 		error=0;
+
+	if (cb_idx < 1 || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS) {
+		error= -EINVAL;
+		return error;
+	}
 
 	MptDeviceDriverHandlers[cb_idx] = dd_cbfunc;
-	return 0;
+
+	/* call per pci device probe entry point */
+	for(ioc = mpt_adapter_find_first(); ioc != NULL;
+	  ioc = mpt_adapter_find_next(ioc)) {
+		if(dd_cbfunc->probe) {
+			error = dd_cbfunc->probe(ioc->pcidev,
+			  ioc->pcidev->driver->id_table);
+			if(error != 0)
+				return error;
+  		}
+	 }
+
+	return error;
 }
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
@@ -1502,9 +1520,14 @@ mptbase_probe(struct pci_dev *pdev, cons
 				ioc->name, r);
 	}
 
-	if(r != 0 )
+	if(r != 0 ) {
+		Q_DEL_ITEM(ioc);
+		mpt_adapters[ioc->id] = NULL;
+		free_irq(ioc->pci_irq, ioc);
+		iounmap(mem);
+		kfree(ioc);
 		return r;
-
+	}
 
 	/* call per device driver probe entry point */
 	for(ii=0; ii<MPT_MAX_PROTOCOL_DRIVERS; ii++) {
--- diff/drivers/message/fusion/mptbase.h	2004-02-18 08:54:10.000000000 +0000
+++ source/drivers/message/fusion/mptbase.h	2004-02-23 13:56:43.000000000 +0000
@@ -80,8 +80,8 @@
 #define COPYRIGHT	"Copyright (c) 1999-2003 " MODULEAUTHOR
 #endif
 
-#define MPT_LINUX_VERSION_COMMON	"3.00.02"
-#define MPT_LINUX_PACKAGE_NAME		"@(#)mptlinux-3.00.02"
+#define MPT_LINUX_VERSION_COMMON	"3.00.03"
+#define MPT_LINUX_PACKAGE_NAME		"@(#)mptlinux-3.00.03"
 #define WHAT_MAGIC_STRING		"@" "(" "#" ")"
 
 #define show_mptmod_ver(s,ver)  \
--- diff/drivers/message/fusion/mptlan.c	2004-01-19 10:22:57.000000000 +0000
+++ source/drivers/message/fusion/mptlan.c	2004-02-23 13:56:43.000000000 +0000
@@ -1437,7 +1437,7 @@ mpt_register_lan_device (MPT_ADAPTER *mp
 	SET_MODULE_OWNER(dev);
 
 	if (register_netdev(dev) != 0) {
-		kfree(dev);
+		free_netdev(dev);
 		dev = NULL;
 	}
 	return dev;
--- diff/drivers/message/fusion/mptscsih.c	2004-02-18 08:54:10.000000000 +0000
+++ source/drivers/message/fusion/mptscsih.c	2004-02-23 13:56:43.000000000 +0000
@@ -197,8 +197,8 @@ static void	mptscsih_fillbuf(char *buffe
 static int	mptscsih_setup(char *str);
 
 /* module entry point */
-static int  __init    mptscsih_init  (void);
-static void    mptscsih_exit  (void);
+static int  __init   mptscsih_init  (void);
+static void __exit   mptscsih_exit  (void);
 
 static int  __devinit mptscsih_probe (struct pci_dev *, const struct pci_device_id *);
 static void __devexit mptscsih_remove(struct pci_dev *);
@@ -1418,6 +1418,7 @@ mptscsih_probe(struct pci_dev *pdev, con
 	int			 numSGE = 0;
 	int			 scale;
 	u8			*mem;
+	int			error=0;
 
 	for (portnum=0; portnum < ioc->facts.NumberOfPorts; portnum++) {
 
@@ -1542,8 +1543,10 @@ mptscsih_probe(struct pci_dev *pdev, con
 			 */
 			sz = hd->ioc->req_depth * sizeof(void *);
 			mem = kmalloc(sz, GFP_ATOMIC);
-			if (mem == NULL)
+			if (mem == NULL) {
+				error = -ENOMEM;
 				goto mptscsih_probe_failed;
+			}
 
 			memset(mem, 0, sz);
 			hd->ScsiLookup = (struct scsi_cmnd **) mem;
@@ -1551,15 +1554,19 @@ mptscsih_probe(struct pci_dev *pdev, con
 			dprintk((MYIOC_s_INFO_FMT "ScsiLookup @ %p, sz=%d\n",
 				 ioc->name, hd->ScsiLookup, sz));
 
-			if (mptscsih_initChainBuffers(hd, 1) < 0)
+			if (mptscsih_initChainBuffers(hd, 1) < 0) {
+				error = -EINVAL;
 				goto mptscsih_probe_failed;
+			}
 
 			/* Allocate memory for free and doneQ's
 			 */
 			sz = sh->can_queue * sizeof(MPT_DONE_Q);
 			mem = kmalloc(sz, GFP_ATOMIC);
-			if (mem == NULL)
+			if (mem == NULL) {
+				error = -ENOMEM;
 				goto mptscsih_probe_failed;
+			}
 
 			memset(mem, 0xFF, sz);
 			hd->memQ = mem;
@@ -1591,8 +1598,10 @@ mptscsih_probe(struct pci_dev *pdev, con
 			 */
 			sz = sh->max_id * sizeof(void *);
 			mem = kmalloc(sz, GFP_ATOMIC);
-			if (mem == NULL)
+			if (mem == NULL) {
+				error = -ENOMEM;
 				goto mptscsih_probe_failed;
+			}
 
 			memset(mem, 0, sz);
 			hd->Targets = (VirtDevice **) mem;
@@ -1683,7 +1692,8 @@ mptscsih_probe(struct pci_dev *pdev, con
 
 			mpt_scsi_hosts++;
 
-			if(scsi_add_host (sh, &ioc->pcidev->dev)) {
+			error = scsi_add_host (sh, &ioc->pcidev->dev);
+			if(error) {
 				dprintk((KERN_ERR MYNAM,
 				  "scsi_add_host failed\n"));
 				goto mptscsih_probe_failed;
@@ -1691,7 +1701,6 @@ mptscsih_probe(struct pci_dev *pdev, con
 
 			scsi_scan_host(sh);
 			return 0;
-
 		} /* scsi_host_alloc */
 
 	} /* for each adapter port */
@@ -1699,8 +1708,7 @@ mptscsih_probe(struct pci_dev *pdev, con
 mptscsih_probe_failed:
 
 	mptscsih_remove(pdev);
-	return -ENODEV;
-
+	return error;
 }
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
@@ -1828,6 +1836,7 @@ mptscsih_remove(struct pci_dev *pdev)
 	}
 
 	scsi_host_put(host);
+	mpt_scsi_hosts--;
 
 }
 
@@ -1928,10 +1937,9 @@ static struct mpt_pci_driver mptscsih_dr
  *
  *	Returns 0 for success, non-zero for failure.
  */
-static int
-__init mptscsih_init(void)
+static int __init
+mptscsih_init(void)
 {
-	MPT_ADAPTER		*ioc;
 
 	show_mptmod_ver(my_NAME, my_VERSION);
 
@@ -1939,12 +1947,6 @@ __init mptscsih_init(void)
 	ScsiTaskCtx = mpt_register(mptscsih_taskmgmt_complete, MPTSCSIH_DRIVER);
 	ScsiScanDvCtx = mpt_register(mptscsih_scandv_complete, MPTSCSIH_DRIVER);
 
-	if(mpt_device_driver_register(&mptscsih_driver,
-	  MPTSCSIH_DRIVER) != 0 ) {
-		dprintk((KERN_INFO MYNAM
-		": failed to register dd callbacks\n"));
-	}
-
 	if (mpt_event_register(ScsiDoneCtx, mptscsih_event_process) == 0) {
 		dprintk((KERN_INFO MYNAM
 		  ": Registered for IOC event notifications\n"));
@@ -1961,20 +1963,13 @@ __init mptscsih_init(void)
 		mptscsih_setup(mptscsih);
 #endif
 
-	/* probing for devices */
-	for(ioc = mpt_adapter_find_first(); ioc != NULL;
-	  ioc = mpt_adapter_find_next(ioc)) {
-		if(mptscsih_probe(ioc->pcidev, ioc->pcidev->driver->id_table)) {
-			dprintk((KERN_INFO MYNAM ": probe failed\n"));
-			return -ENODEV;
-		}
+	if(mpt_device_driver_register(&mptscsih_driver,
+	  MPTSCSIH_DRIVER) != 0 ) {
+		dprintk((KERN_INFO MYNAM
+		": failed to register dd callbacks\n"));
 	}
 
-	if (mpt_scsi_hosts > 0)
-		return 0;
-
-	mptscsih_exit();
-	return -ENODEV;
+	return 0;
 
 }
 
@@ -1984,7 +1979,7 @@ __init mptscsih_init(void)
  *	mptscsih_exit - Unregisters MPT adapter(s)
  *
  */
-static void
+static void __exit
 mptscsih_exit(void)
 {
 	MPT_ADAPTER	*ioc;
--- diff/drivers/mtd/devices/blkmtd.c	2003-08-26 10:00:52.000000000 +0100
+++ source/drivers/mtd/devices/blkmtd.c	2004-02-23 13:56:43.000000000 +0000
@@ -550,7 +550,7 @@ static void free_device(struct blkmtd_de
 
 		if(dev->blkdev) {
 			invalidate_inode_pages(dev->blkdev->bd_inode->i_mapping);
-			close_bdev_excl(dev->blkdev, BDEV_RAW);
+			close_bdev_excl(dev->blkdev);
 		}
 		kfree(dev);
 	}
@@ -637,10 +637,10 @@ static struct blkmtd_dev *add_device(cha
 
 #ifdef MODULE
 	mode = (readonly) ? O_RDONLY : O_RDWR;
-	bdev = open_bdev_excl(devname, mode, BDEV_RAW, NULL);
+	bdev = open_bdev_excl(devname, mode, NULL);
 #else
 	mode = (readonly) ? FMODE_READ : FMODE_WRITE;
-	bdev = open_by_devnum(name_to_dev_t(devname), mode, BDEV_RAW);
+	bdev = open_by_devnum(name_to_dev_t(devname), mode);
 #endif
 	if(IS_ERR(bdev)) {
 		err("error: cannot open device %s", devname);
@@ -653,13 +653,13 @@ static struct blkmtd_dev *add_device(cha
 
 	if(MAJOR(bdev->bd_dev) == MTD_BLOCK_MAJOR) {
 		err("attempting to use an MTD device as a block device");
-		blkdev_put(bdev, BDEV_RAW);
+		blkdev_put(bdev);
 		return NULL;
 	}
 
 	dev = kmalloc(sizeof(struct blkmtd_dev), GFP_KERNEL);
 	if(dev == NULL) {
-		blkdev_put(bdev, BDEV_RAW);
+		blkdev_put(bdev);
 		return NULL;
 	}
 
--- diff/drivers/mtd/maps/solutionengine.c	2003-06-30 10:07:21.000000000 +0100
+++ source/drivers/mtd/maps/solutionengine.c	2004-02-23 13:56:43.000000000 +0000
@@ -97,7 +97,7 @@ static int __init init_soleng_maps(void)
 
 	nr_parts = parse_mtd_partitions(flash_mtd, probes, &parsed_parts, 0);
 
-#if CONFIG_MTD_SUPERH_RESERVE
+#ifdef CONFIG_MTD_SUPERH_RESERVE
 	if (nr_parts <= 0) {
 		printk(KERN_NOTICE "Using configured partition at 0x%08x.\n",
 		       CONFIG_MTD_SUPERH_RESERVE);
--- diff/drivers/net/3c503.c	2004-02-18 08:54:10.000000000 +0000
+++ source/drivers/net/3c503.c	2004-02-23 13:56:43.000000000 +0000
@@ -337,6 +337,9 @@ el2_probe1(struct net_device *dev, int i
     dev->open = &el2_open;
     dev->stop = &el2_close;
     dev->ethtool_ops = &netdev_ethtool_ops;
+#ifdef CONFIG_NET_POLL_CONTROLLER
+    dev->poll_controller = ei_poll;
+#endif
 
     if (dev->mem_start)
 	printk("%s: %s - %dkB RAM, 8kB shared mem window at %#6lx-%#6lx.\n",
--- diff/drivers/net/3c509.c	2003-11-25 15:24:57.000000000 +0000
+++ source/drivers/net/3c509.c	2004-02-23 13:56:43.000000000 +0000
@@ -678,6 +678,8 @@ static int __init el3_mca_probe(struct d
 		err = el3_common_init(dev);
 
 		if (err) {
+			device->driver_data = NULL;
+			free_netdev(dev);
 			return -ENOMEM;
 		}
 
@@ -737,6 +739,8 @@ static int __init el3_eisa_probe (struct
 	err = el3_common_init(dev);
 
 	if (err) {
+		eisa_set_drvdata (edev, NULL);
+		free_netdev(dev);
 		return err;
 	}
 
--- diff/drivers/net/3c59x.c	2004-02-09 10:36:10.000000000 +0000
+++ source/drivers/net/3c59x.c	2004-02-23 13:56:43.000000000 +0000
@@ -291,6 +291,8 @@ MODULE_PARM(global_full_duplex, "i");
 MODULE_PARM(full_duplex, "1-" __MODULE_STRING(8) "i");
 MODULE_PARM(hw_checksums, "1-" __MODULE_STRING(8) "i");
 MODULE_PARM(flow_ctrl, "1-" __MODULE_STRING(8) "i");
+MODULE_PARM(global_enable_wol, "i");
+MODULE_PARM(enable_wol, "1-" __MODULE_STRING(8) "i");
 MODULE_PARM(rx_copybreak, "i");
 MODULE_PARM(max_interrupt_work, "i");
 MODULE_PARM(compaq_ioaddr, "i");
@@ -304,6 +306,8 @@ MODULE_PARM_DESC(full_duplex, "3c59x ful
 MODULE_PARM_DESC(global_full_duplex, "3c59x: same as full_duplex, but applies to all NICs if options is unset");
 MODULE_PARM_DESC(hw_checksums, "3c59x Hardware checksum checking by adapter(s) (0-1)");
 MODULE_PARM_DESC(flow_ctrl, "3c59x 802.3x flow control usage (PAUSE only) (0-1)");
+MODULE_PARM_DESC(enable_wol, "3c59x: Turn on Wake-on-LAN for adapter(s) (0-1)");
+MODULE_PARM_DESC(global_enable_wol, "3c59x: same as enable_wol, but applies to all NICs if options is unset");
 MODULE_PARM_DESC(rx_copybreak, "3c59x copy breakpoint for copy-only-tiny-frames");
 MODULE_PARM_DESC(max_interrupt_work, "3c59x maximum events handled per interrupt");
 MODULE_PARM_DESC(compaq_ioaddr, "3c59x PCI I/O base address (Compaq BIOS problem workaround)");
@@ -813,6 +817,7 @@ struct vortex_private {
 		flow_ctrl:1,					/* Use 802.3x flow control (PAUSE only) */
 		partner_flow_ctrl:1,			/* Partner supports flow control */
 		has_nway:1,
+		enable_wol:1,					/* Wake-on-LAN is enabled */
 		pm_state_valid:1,				/* power_state[] has sane contents */
 		open:1,
 		medialock:1,
@@ -909,8 +914,10 @@ static int options[MAX_UNITS] = { -1, -1
 static int full_duplex[MAX_UNITS] = {-1, -1, -1, -1, -1, -1, -1, -1};
 static int hw_checksums[MAX_UNITS] = {-1, -1, -1, -1, -1, -1, -1, -1};
 static int flow_ctrl[MAX_UNITS] = {-1, -1, -1, -1, -1, -1, -1, -1};
+static int enable_wol[MAX_UNITS] = {-1, -1, -1, -1, -1, -1, -1, -1};
 static int global_options = -1;
 static int global_full_duplex = -1;
+static int global_enable_wol = -1;
 
 /* #define dev_alloc_skb dev_alloc_skb_debug */
 
@@ -920,6 +927,18 @@ static struct net_device *compaq_net_dev
 
 static int vortex_cards_found;
 
+#ifdef CONFIG_NET_POLL_CONTROLLER
+static void poll_vortex(struct net_device *dev)
+{
+	struct vortex_private *vp = (struct vortex_private *)dev->priv;
+	unsigned long flags;
+	local_save_flags(flags);
+	local_irq_disable();
+	(vp->full_bus_master_rx ? boomerang_interrupt:vortex_interrupt)(dev->irq,dev,NULL);
+	local_irq_restore(flags);
+} 
+#endif
+
 #ifdef CONFIG_PM
 
 static int vortex_suspend (struct pci_dev *pdev, u32 state)
@@ -1130,6 +1149,8 @@ static int __devinit vortex_probe1(struc
 			vortex_debug = 7;
 		if (option & 0x4000)
 			vortex_debug = 2;
+		if (option & 0x0400)
+			vp->enable_wol = 1;
 	}
 
 	print_info = (vortex_debug > 1);
@@ -1217,12 +1238,16 @@ static int __devinit vortex_probe1(struc
 
 	if (global_full_duplex > 0)
 		vp->full_duplex = 1;
+	if (global_enable_wol > 0)
+		vp->enable_wol = 1;
 
 	if (card_idx < MAX_UNITS) {
 		if (full_duplex[card_idx] > 0)
 			vp->full_duplex = 1;
 		if (flow_ctrl[card_idx] > 0)
 			vp->flow_ctrl = 1;
+		if (enable_wol[card_idx] > 0)
+			vp->enable_wol = 1;
 	}
 
 	vp->force_fd = vp->full_duplex;
@@ -1450,7 +1475,10 @@ static int __devinit vortex_probe1(struc
 	dev->set_multicast_list = set_rx_mode;
 	dev->tx_timeout = vortex_tx_timeout;
 	dev->watchdog_timeo = (watchdog * HZ) / 1000;
-	if (pdev) {
+#ifdef CONFIG_NET_POLL_CONTROLLER
+	dev->poll_controller = poll_vortex; 
+#endif
+	if (pdev && vp->enable_wol) {
 		vp->pm_state_valid = 1;
  		pci_save_state(VORTEX_PCI(vp), vp->power_state);
  		acpi_set_WOL(dev);
@@ -1507,7 +1535,7 @@ vortex_up(struct net_device *dev)
 	unsigned int config;
 	int i;
 
-	if (VORTEX_PCI(vp)) {
+	if (VORTEX_PCI(vp) && vp->enable_wol) {
 		pci_set_power_state(VORTEX_PCI(vp), 0);	/* Go active */
 		pci_restore_state(VORTEX_PCI(vp), vp->power_state);
 	}
@@ -2656,7 +2684,7 @@ vortex_down(struct net_device *dev)
 	if (vp->full_bus_master_tx)
 		outl(0, ioaddr + DownListPtr);
 
-	if (VORTEX_PCI(vp)) {
+	if (VORTEX_PCI(vp) && vp->enable_wol) {
 		pci_save_state(VORTEX_PCI(vp), vp->power_state);
 		acpi_set_WOL(dev);
 	}
@@ -3033,7 +3061,7 @@ static void __devexit vortex_remove_one 
 	/* Should really use issue_and_wait() here */
 	outw(TotalReset|0x14, dev->base_addr + EL3_CMD);
 
-	if (VORTEX_PCI(vp)) {
+	if (VORTEX_PCI(vp) && vp->enable_wol) {
 		pci_set_power_state(VORTEX_PCI(vp), 0);	/* Go active */
 		if (vp->pm_state_valid)
 			pci_restore_state(VORTEX_PCI(vp), vp->power_state);
--- diff/drivers/net/8390.c	2004-02-18 08:54:10.000000000 +0000
+++ source/drivers/net/8390.c	2004-02-23 13:56:43.000000000 +0000
@@ -516,6 +516,15 @@ irqreturn_t ei_interrupt(int irq, void *
 	return IRQ_HANDLED;
 }
 
+#ifdef CONFIG_NET_POLL_CONTROLLER
+void ei_poll(struct net_device *dev)
+{
+	disable_irq(dev->irq);
+	ei_interrupt(dev->irq, dev, NULL);
+	enable_irq(dev->irq);
+}
+#endif
+
 /**
  * ei_tx_err - handle transmitter error
  * @dev: network device which threw the exception
@@ -1124,6 +1133,9 @@ static void NS8390_trigger_send(struct n
 EXPORT_SYMBOL(ei_open);
 EXPORT_SYMBOL(ei_close);
 EXPORT_SYMBOL(ei_interrupt);
+#ifdef CONFIG_NET_POLL_CONTROLLER
+EXPORT_SYMBOL(ei_poll);
+#endif
 EXPORT_SYMBOL(ei_tx_timeout);
 EXPORT_SYMBOL(NS8390_init);
 EXPORT_SYMBOL(__alloc_ei_netdev);
--- diff/drivers/net/8390.h	2004-02-18 08:54:10.000000000 +0000
+++ source/drivers/net/8390.h	2004-02-23 13:56:43.000000000 +0000
@@ -39,6 +39,10 @@ extern int ei_debug;
 #define ei_debug 1
 #endif
 
+#ifdef CONFIG_NET_POLL_CONTROLLER
+extern void ei_poll(struct net_device *dev);
+#endif
+
 extern void NS8390_init(struct net_device *dev, int startp);
 extern int ei_open(struct net_device *dev);
 extern int ei_close(struct net_device *dev);
--- diff/drivers/net/Kconfig	2004-02-18 08:54:10.000000000 +0000
+++ source/drivers/net/Kconfig	2004-02-23 13:56:43.000000000 +0000
@@ -1354,8 +1354,9 @@ config EEPRO100_PIO
 	  say N.
 
 config E100
-	tristate "EtherExpressPro/100 support (e100, Alternate Intel driver)"
+	tristate "Intel(R) PRO/100+ support"
 	depends on NET_PCI && PCI
+	select MII
 	---help---
 	  This driver supports Intel(R) PRO/100 family of adapters, which 
 	  includes:
@@ -1428,6 +1429,10 @@ config E100
 	  <file:Documentation/networking/net-modules.txt>.  The module
 	  will be called e100.
 
+config E100_NAPI
+	bool "Use Rx Polling (NAPI)"
+	depends on E100
+
 config LNE390
 	tristate "Mylex EISA LNE390A/B support (EXPERIMENTAL)"
 	depends on NET_PCI && EISA && EXPERIMENTAL
@@ -1715,7 +1720,8 @@ config NET_POCKET
 	  <file:Documentation/Changes>) and you can say N here.
 
 	  Laptop users should read the Linux Laptop home page at
-	  <http://www.linux-on-laptops.com/>.
+	  <http://www.linux-on-laptops.com/> or
+	  Tuxmobil - Linux on Mobile Computers at <http://www.tuxmobil.org/>.
 
 	  Note that the answer to this question doesn't directly affect the
 	  kernel: saying N will just cause the configurator to skip all
@@ -1984,6 +1990,7 @@ config SK98LIN
 	    - Allied Telesyn AT-2970TX/2TX Gigabit Ethernet Adapter
 	    - Allied Telesyn AT-2971SX Gigabit Ethernet Adapter
 	    - Allied Telesyn AT-2971T Gigabit Ethernet Adapter
+	    - Belkin Gigabit Desktop Card 10/100/1000Base-T Adapter, Copper RJ-45
 	    - DGE-530T Gigabit Ethernet Adapter
 	    - EG1032 v2 Instant Gigabit Network Adapter
 	    - EG1064 v2 Instant Gigabit Network Adapter
@@ -1995,6 +2002,7 @@ config SK98LIN
 	    - Marvell 88E8001 Gigabit LOM Ethernet Adapter (Foxconn)
 	    - Marvell 88E8001 Gigabit LOM Ethernet Adapter (Gigabyte)
 	    - Marvell 88E8001 Gigabit LOM Ethernet Adapter (Iwill)
+	    - Marvell 88E8050 Gigabit LOM Ethernet Adapter (Intel)
 	    - Marvell RDK-8001 Adapter
 	    - Marvell RDK-8002 Adapter
 	    - Marvell RDK-8003 Adapter
@@ -2006,6 +2014,7 @@ config SK98LIN
 	    - Marvell RDK-8010 Adapter
 	    - Marvell RDK-8011 Adapter
 	    - Marvell RDK-8012 Adapter
+	    - Marvell RDK-8052 Adapter
 	    - Marvell Yukon Gigabit Ethernet 10/100/1000Base-T Adapter (32 bit)
 	    - Marvell Yukon Gigabit Ethernet 10/100/1000Base-T Adapter (64 bit)
 	    - N-Way PCI-Bus Giga-Card 1000/100/10Mbps(L)
@@ -2476,6 +2485,13 @@ config SHAPER
 	  To compile this driver as a module, choose M here: the module
 	  will be called shaper.  If unsure, say N.
 
+config NETCONSOLE
+	tristate "Network console logging support (EXPERIMENTAL)"
+	depends on NETDEVICES && EXPERIMENTAL
+	---help---
+	If you want to log kernel messages over the network, enable this.
+	See Documentation/networking/netconsole.txt for details.
+
 source "drivers/net/wan/Kconfig"
 
 source "drivers/net/pcmcia/Kconfig"
--- diff/drivers/net/Makefile	2004-02-18 08:54:10.000000000 +0000
+++ source/drivers/net/Makefile	2004-02-23 13:56:43.000000000 +0000
@@ -8,7 +8,6 @@ ifeq ($(CONFIG_ISDN_PPP),y)
   obj-$(CONFIG_ISDN) += slhc.o
 endif
 
-obj-$(CONFIG_E100) += e100/
 obj-$(CONFIG_E1000) += e1000/
 obj-$(CONFIG_IXGB) += ixgb/
 obj-$(CONFIG_BONDING) += bonding/
@@ -39,13 +38,13 @@ obj-$(CONFIG_TYPHOON) += typhoon.o
 obj-$(CONFIG_NE2K_PCI) += ne2k-pci.o 8390.o
 obj-$(CONFIG_PCNET32) += pcnet32.o
 obj-$(CONFIG_EEPRO100) += eepro100.o
+obj-$(CONFIG_E100) += e100.o
 obj-$(CONFIG_TLAN) += tlan.o
 obj-$(CONFIG_EPIC100) += epic100.o
 obj-$(CONFIG_SIS190) += sis190.o
 obj-$(CONFIG_SIS900) += sis900.o
 obj-$(CONFIG_YELLOWFIN) += yellowfin.o
 obj-$(CONFIG_ACENIC) += acenic.o
-obj-$(CONFIG_VETH) += veth.o
 obj-$(CONFIG_NATSEMI) += natsemi.o
 obj-$(CONFIG_NS83820) += ns83820.o
 obj-$(CONFIG_STNIC) += stnic.o 8390.o
@@ -188,3 +187,6 @@ obj-$(CONFIG_NET_TULIP) += tulip/
 obj-$(CONFIG_HAMRADIO) += hamradio/
 obj-$(CONFIG_IRDA) += irda/
 
+# Must come after all NICs that might use them
+obj-$(CONFIG_NETCONSOLE) += netconsole.o
+obj-$(CONFIG_KGDB) += kgdb_eth.o
--- diff/drivers/net/a2065.c	2004-02-18 08:54:10.000000000 +0000
+++ source/drivers/net/a2065.c	2004-02-23 13:56:43.000000000 +0000
@@ -1,7 +1,7 @@
 /*
  * Amiga Linux/68k A2065 Ethernet Driver
  *
- * (C) Copyright 1995 by Geert Uytterhoeven <geert@linux-m68k.org>
+ * (C) Copyright 1995-2003 by Geert Uytterhoeven <geert@linux-m68k.org>
  *
  * Fixes and tips by:
  *	- Janos Farkas (CHEXUM@sparta.banki.hu)
@@ -130,14 +130,8 @@ struct lance_private {
 	int burst_sizes;	      /* ledma SBus burst sizes */
 #endif
 	struct timer_list         multicast_timer;
-	struct net_device *dev;		/* Backpointer */
-	struct lance_private *next_module;
 };
 
-#ifdef MODULE
-static struct lance_private *root_a2065_dev;
-#endif
-
 #define TX_BUFFS_AVAIL ((lp->tx_old<=lp->tx_new)?\
 			lp->tx_old+lp->tx_ring_mod_mask-lp->tx_new:\
 			lp->tx_old - lp->tx_new-1)
@@ -704,133 +698,141 @@ static void lance_set_multicast (struct 
 	netif_wake_queue(dev);
 }
 
-static int __init a2065_probe(void)
+static int __devinit a2065_init_one(struct zorro_dev *z,
+				    const struct zorro_device_id *ent);
+static void __devexit a2065_remove_one(struct zorro_dev *z);
+
+
+static struct zorro_device_id a2065_zorro_tbl[] __devinitdata = {
+	{ ZORRO_PROD_CBM_A2065_1 },
+	{ ZORRO_PROD_CBM_A2065_2 },
+	{ ZORRO_PROD_AMERISTAR_A2065 },
+	{ 0 }
+};
+
+static struct zorro_driver a2065_driver = {
+	.name		= "a2065",
+	.id_table	= a2065_zorro_tbl,
+	.probe		= a2065_init_one,
+	.remove		= __devexit_p(a2065_remove_one),
+};
+
+static int __devinit a2065_init_one(struct zorro_dev *z,
+				    const struct zorro_device_id *ent)
 {
-	struct zorro_dev *z = NULL;
 	struct net_device *dev;
 	struct lance_private *priv;
-	int res = -ENODEV;
-
-	while ((z = zorro_find_device(ZORRO_WILDCARD, z))) {
-		unsigned long board, base_addr, mem_start;
-		struct resource *r1, *r2;
-		int is_cbm;
-
-		if (z->id == ZORRO_PROD_CBM_A2065_1 ||
-		    z->id == ZORRO_PROD_CBM_A2065_2)
-			is_cbm = 1;
-		else if (z->id == ZORRO_PROD_AMERISTAR_A2065)
-			is_cbm = 0;
-		else
-			continue;
-
-		board = z->resource.start;
-		base_addr = board+A2065_LANCE;
-		mem_start = board+A2065_RAM;
-
-		r1 = request_mem_region(base_addr, sizeof(struct lance_regs),
-					"Am7990");
-		if (!r1) continue;
-		r2 = request_mem_region(mem_start, A2065_RAM_SIZE, "RAM");
-		if (!r2) {
-			release_resource(r1);
-			continue;
-		}
+	unsigned long board, base_addr, mem_start;
+	struct resource *r1, *r2;
+	int err;
+
+	board = z->resource.start;
+	base_addr = board+A2065_LANCE;
+	mem_start = board+A2065_RAM;
+
+	r1 = request_mem_region(base_addr, sizeof(struct lance_regs),
+				"Am7990");
+	if (!r1)
+		return -EBUSY;
+	r2 = request_mem_region(mem_start, A2065_RAM_SIZE, "RAM");
+	if (!r2) {
+		release_resource(r1);
+		return -EBUSY;
+	}
+
+	dev = alloc_etherdev(sizeof(struct lance_private));
+	if (dev == NULL) {
+		release_resource(r1);
+		release_resource(r2);
+		return -ENOMEM;
+	}
+
+	SET_MODULE_OWNER(dev);
+	priv = dev->priv;
+
+	r1->name = dev->name;
+	r2->name = dev->name;
+
+	dev->dev_addr[0] = 0x00;
+	if (z->id != ZORRO_PROD_AMERISTAR_A2065) {	/* Commodore */
+		dev->dev_addr[1] = 0x80;
+		dev->dev_addr[2] = 0x10;
+	} else {					/* Ameristar */
+		dev->dev_addr[1] = 0x00;
+		dev->dev_addr[2] = 0x9f;
+	}
+	dev->dev_addr[3] = (z->rom.er_SerialNumber>>16) & 0xff;
+	dev->dev_addr[4] = (z->rom.er_SerialNumber>>8) & 0xff;
+	dev->dev_addr[5] = z->rom.er_SerialNumber & 0xff;
+	printk("%s: A2065 at 0x%08lx, Ethernet Address "
+	       "%02x:%02x:%02x:%02x:%02x:%02x\n", dev->name, board,
+	       dev->dev_addr[0], dev->dev_addr[1], dev->dev_addr[2],
+	       dev->dev_addr[3], dev->dev_addr[4], dev->dev_addr[5]);
+
+	dev->base_addr = ZTWO_VADDR(base_addr);
+	dev->mem_start = ZTWO_VADDR(mem_start);
+	dev->mem_end = dev->mem_start+A2065_RAM_SIZE;
+
+	priv->ll = (volatile struct lance_regs *)dev->base_addr;
+	priv->init_block = (struct lance_init_block *)dev->mem_start;
+	priv->lance_init_block = (struct lance_init_block *)A2065_RAM;
+	priv->auto_select = 0;
+	priv->busmaster_regval = LE_C3_BSWP;
+
+	priv->lance_log_rx_bufs = LANCE_LOG_RX_BUFFERS;
+	priv->lance_log_tx_bufs = LANCE_LOG_TX_BUFFERS;
+	priv->rx_ring_mod_mask = RX_RING_MOD_MASK;
+	priv->tx_ring_mod_mask = TX_RING_MOD_MASK;
+
+	dev->open = &lance_open;
+	dev->stop = &lance_close;
+	dev->hard_start_xmit = &lance_start_xmit;
+	dev->tx_timeout = &lance_tx_timeout;
+	dev->watchdog_timeo = 5*HZ;
+	dev->get_stats = &lance_get_stats;
+	dev->set_multicast_list = &lance_set_multicast;
+	dev->dma = 0;
+
+	init_timer(&priv->multicast_timer);
+	priv->multicast_timer.data = (unsigned long) dev;
+	priv->multicast_timer.function =
+		(void (*)(unsigned long)) &lance_set_multicast;
+
+	err = register_netdev(dev);
+	if (err) {
+		release_resource(r1);
+		release_resource(r2);
+		free_netdev(dev);
+		return err;
+	}
+	zorro_set_drvdata(z, dev);
 
-		dev = alloc_etherdev(sizeof(struct lance_private));
+	return 0;
+}
 
-		if (dev == NULL) {
-			release_resource(r1);
-			release_resource(r2);
-			return -ENOMEM;
-		}
-		SET_MODULE_OWNER(dev);
-		priv = dev->priv;
 
-		r1->name = dev->name;
-		r2->name = dev->name;
+static void __devexit a2065_remove_one(struct zorro_dev *z)
+{
+	struct net_device *dev = zorro_get_drvdata(z);
 
-		priv->dev = dev;
-		dev->dev_addr[0] = 0x00;
-		if (is_cbm) {				/* Commodore */
-			dev->dev_addr[1] = 0x80;
-			dev->dev_addr[2] = 0x10;
-		} else {				/* Ameristar */
-			dev->dev_addr[1] = 0x00;
-			dev->dev_addr[2] = 0x9f;
-		}
-		dev->dev_addr[3] = (z->rom.er_SerialNumber>>16) & 0xff;
-		dev->dev_addr[4] = (z->rom.er_SerialNumber>>8) & 0xff;
-		dev->dev_addr[5] = z->rom.er_SerialNumber & 0xff;
-		printk("%s: A2065 at 0x%08lx, Ethernet Address "
-		       "%02x:%02x:%02x:%02x:%02x:%02x\n", dev->name, board,
-		       dev->dev_addr[0], dev->dev_addr[1], dev->dev_addr[2],
-		       dev->dev_addr[3], dev->dev_addr[4], dev->dev_addr[5]);
-
-		dev->base_addr = ZTWO_VADDR(base_addr);
-		dev->mem_start = ZTWO_VADDR(mem_start);
-		dev->mem_end = dev->mem_start+A2065_RAM_SIZE;
-
-		priv->ll = (volatile struct lance_regs *)dev->base_addr;
-		priv->init_block = (struct lance_init_block *)dev->mem_start;
-		priv->lance_init_block = (struct lance_init_block *)A2065_RAM;
-		priv->auto_select = 0;
-		priv->busmaster_regval = LE_C3_BSWP;
-
-		priv->lance_log_rx_bufs = LANCE_LOG_RX_BUFFERS;
-		priv->lance_log_tx_bufs = LANCE_LOG_TX_BUFFERS;
-		priv->rx_ring_mod_mask = RX_RING_MOD_MASK;
-		priv->tx_ring_mod_mask = TX_RING_MOD_MASK;
-
-		dev->open = &lance_open;
-		dev->stop = &lance_close;
-		dev->hard_start_xmit = &lance_start_xmit;
-		dev->tx_timeout = &lance_tx_timeout;
-		dev->watchdog_timeo = 5*HZ;
-		dev->get_stats = &lance_get_stats;
-		dev->set_multicast_list = &lance_set_multicast;
-		dev->dma = 0;
-
-		init_timer(&priv->multicast_timer);
-		priv->multicast_timer.data = (unsigned long) dev;
-		priv->multicast_timer.function =
-			(void (*)(unsigned long)) &lance_set_multicast;
-
-		res = register_netdev(dev);
-		if (res) {
-			release_resource(r1);
-			release_resource(r2);
-			free_netdev(dev);
-			break;
-		}
-#ifdef MODULE
-		priv->next_module = root_a2065_dev;
-		root_a2065_dev = priv;
-#endif
-	}
-	return res;
+	unregister_netdev(dev);
+	release_mem_region(ZTWO_PADDR(dev->base_addr),
+			   sizeof(struct lance_regs));
+	release_mem_region(ZTWO_PADDR(dev->mem_start), A2065_RAM_SIZE);
+	free_netdev(dev);
 }
 
-
-static void __exit a2065_cleanup(void)
+static int __init a2065_init_module(void)
 {
-#ifdef MODULE
-	struct lance_private *next;
-	struct net_device *dev;
+	return zorro_module_init(&a2065_driver);
+}
 
-	while (root_a2065_dev) {
-		next = root_a2065_dev->next_module;
-		dev = root_a2065_dev->dev;
-		unregister_netdev(dev);
-		release_mem_region(ZTWO_PADDR(dev->base_addr),
-				   sizeof(struct lance_regs));
-		release_mem_region(ZTWO_PADDR(dev->mem_start), A2065_RAM_SIZE);
-		free_netdev(dev);
-		root_a2065_dev = next;
-	}
-#endif
+static void __exit a2065_cleanup_module(void)
+{
+	zorro_unregister_driver(&a2065_driver);
 }
 
-module_init(a2065_probe);
-module_exit(a2065_cleanup);
+module_init(a2065_init_module);
+module_exit(a2065_cleanup_module);
+
 MODULE_LICENSE("GPL");
--- diff/drivers/net/ac3200.c	2004-02-18 08:54:10.000000000 +0000
+++ source/drivers/net/ac3200.c	2004-02-23 13:56:43.000000000 +0000
@@ -276,6 +276,9 @@ static int __init ac_probe1(int ioaddr, 
 
 	dev->open = &ac_open;
 	dev->stop = &ac_close_card;
+#ifdef CONFIG_NET_POLL_CONTROLLER
+	dev->poll_controller = ei_poll;
+#endif
 	NS8390_init(dev, 0);
 	return 0;
 out1:
--- diff/drivers/net/acenic.c	2004-02-18 08:54:10.000000000 +0000
+++ source/drivers/net/acenic.c	2004-02-23 13:56:43.000000000 +0000
@@ -731,12 +731,6 @@ int __devinit acenic_probe (ACE_PROBE_AR
 			break;
 		}
 
-		if (register_netdev(dev)) {
-			printk(KERN_ERR "acenic: device registration failed\n");
-			free_netdev(dev);
-			continue;
-		}
-
 		switch(pdev->vendor) {
 		case PCI_VENDOR_ID_ALTEON:
 			if (pdev->device == PCI_DEVICE_ID_FARALLON_PN9100T) {
@@ -824,6 +818,13 @@ int __devinit acenic_probe (ACE_PROBE_AR
 			continue;
 		}
 
+		if (register_netdev(dev)) {
+			printk(KERN_ERR "acenic: device registration failed\n");
+			ace_init_cleanup(dev);
+			free_netdev(dev);
+			continue;
+		}
+
 		if (ap->pci_using_dac)
 			dev->features |= NETIF_F_HIGHDMA;
 
@@ -874,6 +875,7 @@ static void __exit ace_module_cleanup(vo
 	while (root_dev) {
 		ap = root_dev->priv;
 		next = ap->next;
+		unregister_netdev(root_dev);
 
 		regs = ap->regs;
 
@@ -1133,7 +1135,6 @@ static void ace_init_cleanup(struct net_
 	if (dev->irq)
 		free_irq(dev->irq, dev);
 
-	unregister_netdev(dev);
 	iounmap(ap->regs);
 }
 
--- diff/drivers/net/amd8111e.c	2003-10-27 09:20:38.000000000 +0000
+++ source/drivers/net/amd8111e.c	2004-02-23 13:56:43.000000000 +0000
@@ -91,7 +91,7 @@ Revision History:
 
 #include "amd8111e.h"
 #define MODULE_NAME	"amd8111e"
-#define MODULE_VERSION	"3.0.3"
+#define MODULE_VERS	"3.0.3"
 MODULE_AUTHOR("Advanced Micro Devices, Inc.");
 MODULE_DESCRIPTION ("AMD8111 based 10/100 Ethernet Controller. Driver Version 3.0.3");
 MODULE_LICENSE("GPL");
@@ -1153,6 +1153,17 @@ err_no_interrupt:
 	return IRQ_RETVAL(handled);
 }
 
+#ifdef CONFIG_NET_POLL_CONTROLLER
+static void amd8111e_poll(struct net_device *dev)
+{ 
+	unsigned long flags;
+	local_save_flags(flags); 
+	local_irq_disable();
+	amd8111e_interrupt(0, dev, NULL);
+	local_irq_restore(flags); 
+} 
+#endif
+
 /*
 This function closes the network interface and updates the statistics so that most recent statistics will be available after the interface is down.
 */
@@ -1402,7 +1413,7 @@ static int amd8111e_ethtool_ioctl(struct
 	case ETHTOOL_GDRVINFO:{
 		struct ethtool_drvinfo info = { ETHTOOL_GDRVINFO };
 		strcpy (info.driver, MODULE_NAME);
-		strcpy (info.version, MODULE_VERSION);
+		strcpy (info.version, MODULE_VERS);
 		memset(&info.fw_version, 0, sizeof(info.fw_version));
 		sprintf(info.fw_version,"%u",chip_version);
 		strcpy (info.bus_info, pci_name(pci_dev));
@@ -1884,6 +1895,9 @@ static int __devinit amd8111e_probe_one(
 	dev->irq =pdev->irq;
 	dev->tx_timeout = amd8111e_tx_timeout; 
 	dev->watchdog_timeo = AMD8111E_TX_TIMEOUT; 
+#ifdef CONFIG_NET_POLL_CONTROLLER
+	dev->poll_controller = amd8111e_poll; 
+#endif
 
 #if AMD8111E_VLAN_TAG_USED
 	dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX;
@@ -1917,7 +1931,7 @@ static int __devinit amd8111e_probe_one(
 	/*  display driver and device information */
 
     	chip_version = (readl(lp->mmio + CHIPID) & 0xf0000000)>>28;
-    	printk(KERN_INFO "%s: AMD-8111e Driver Version: %s\n",								 dev->name,MODULE_VERSION);
+    	printk(KERN_INFO "%s: AMD-8111e Driver Version: %s\n",								 dev->name,MODULE_VERS);
     	printk(KERN_INFO "%s: [ Rev %x ] PCI 10/100BaseT Ethernet ",							dev->name, chip_version);
     	for (i = 0; i < 6; i++)
 		printk("%2.2x%c",dev->dev_addr[i],i == 5 ? ' ' : ':');
--- diff/drivers/net/apne.c	2004-02-18 08:54:10.000000000 +0000
+++ source/drivers/net/apne.c	2004-02-23 13:56:43.000000000 +0000
@@ -333,6 +333,9 @@ static int __init apne_probe1(struct net
     ei_status.get_8390_hdr = &apne_get_8390_hdr;
     dev->open = &apne_open;
     dev->stop = &apne_close;
+#ifdef CONFIG_NET_POLL_CONTROLLER
+    dev->poll_controller = ei_poll;
+#endif
     NS8390_init(dev, 0);
 
     pcmcia_ack_int(pcmcia_get_intreq());		/* ack PCMCIA int req */
@@ -580,6 +583,8 @@ void cleanup_module(void)
 
 	pcmcia_reset();
 
+	release_region(IOBASE, 0x20);
+
 	free_netdev(apne_dev);
 }
 
--- diff/drivers/net/appletalk/cops.c	2003-09-17 12:28:07.000000000 +0100
+++ source/drivers/net/appletalk/cops.c	2004-02-23 13:56:43.000000000 +0000
@@ -262,7 +262,7 @@ struct net_device * __init cops_probe(in
 out1:
 	cleanup_card(dev);
 out:
-	kfree(dev);
+	free_netdev(dev);
 	return ERR_PTR(err);
 }
 
--- diff/drivers/net/ariadne.c	2004-02-18 08:54:10.000000000 +0000
+++ source/drivers/net/ariadne.c	2004-02-23 13:56:43.000000000 +0000
@@ -1,9 +1,8 @@
 /*
  *  Amiga Linux/m68k Ariadne Ethernet Driver
  *
- *  © Copyright 1995 by Geert Uytterhoeven (geert@linux-m68k.org)
- *			Peter De Schrijver
- *		       (Peter.DeSchrijver@linux.cc.kuleuven.ac.be)
+ *  © Copyright 1995-2003 by Geert Uytterhoeven (geert@linux-m68k.org)
+ *			     Peter De Schrijver (p2@mind.be)
  *
  *  ---------------------------------------------------------------------------
  *
@@ -101,8 +100,6 @@ struct ariadne_private {
     int dirty_tx;			/* The ring entries to be free()ed. */
     struct net_device_stats stats;
     char tx_full;
-    struct net_device *dev;		/* Backpointer */
-    struct ariadne_private *next_module;
 };
 
 
@@ -117,10 +114,6 @@ struct lancedata {
     u_short rx_buff[RX_RING_SIZE][PKT_BUF_SIZE/sizeof(u_short)];
 };
 
-#ifdef MODULE
-static struct ariadne_private *root_ariadne_dev;
-#endif
-
 static int ariadne_open(struct net_device *dev);
 static void ariadne_init_ring(struct net_device *dev);
 static int ariadne_start_xmit(struct sk_buff *skb, struct net_device *dev);
@@ -146,78 +139,89 @@ static void memcpyw(volatile u_short *de
 }
 
 
-static int __init ariadne_probe(void)
-{
-    struct zorro_dev *z = NULL;
-    struct net_device *dev;
-    struct ariadne_private *priv;
-    int res = -ENODEV;
+static int __devinit ariadne_init_one(struct zorro_dev *z,
+				      const struct zorro_device_id *ent);
+static void __devexit ariadne_remove_one(struct zorro_dev *z);
 
-    while ((z = zorro_find_device(ZORRO_PROD_VILLAGE_TRONIC_ARIADNE, z))) {
-	unsigned long board = z->resource.start;
-	unsigned long base_addr = board+ARIADNE_LANCE;
-	unsigned long mem_start = board+ARIADNE_RAM;
-	struct resource *r1, *r2;
-
-	r1 = request_mem_region(base_addr, sizeof(struct Am79C960),
-		    		"Am79C960");
-	if (!r1) continue;
-	r2 = request_mem_region(mem_start, ARIADNE_RAM_SIZE, "RAM");
-	if (!r2) {
-	    release_resource(r1);
-	    continue;
-	}
 
-	dev = alloc_etherdev(sizeof(struct ariadne_private));
+static struct zorro_device_id ariadne_zorro_tbl[] __devinitdata = {
+    { ZORRO_PROD_VILLAGE_TRONIC_ARIADNE },
+    { 0 }
+};
 
-	if (dev == NULL) {
-	    release_resource(r1);
-	    release_resource(r2);
-	    return -ENOMEM;
-	}
-	SET_MODULE_OWNER(dev);
-	priv = dev->priv;
+static struct zorro_driver ariadne_driver = {
+    .name	= "ariadne",
+    .id_table	= ariadne_zorro_tbl,
+    .probe	= ariadne_init_one,
+    .remove	= __devexit_p(ariadne_remove_one),
+};
 
-	r1->name = dev->name;
-	r2->name = dev->name;
+static int __devinit ariadne_init_one(struct zorro_dev *z,
+				      const struct zorro_device_id *ent)
+{
+    unsigned long board = z->resource.start;
+    unsigned long base_addr = board+ARIADNE_LANCE;
+    unsigned long mem_start = board+ARIADNE_RAM;
+    struct resource *r1, *r2;
+    struct net_device *dev;
+    struct ariadne_private *priv;
+    int err;
 
-	priv->dev = dev;
-	dev->dev_addr[0] = 0x00;
-	dev->dev_addr[1] = 0x60;
-	dev->dev_addr[2] = 0x30;
-	dev->dev_addr[3] = (z->rom.er_SerialNumber>>16) & 0xff;
-	dev->dev_addr[4] = (z->rom.er_SerialNumber>>8) & 0xff;
-	dev->dev_addr[5] = z->rom.er_SerialNumber & 0xff;
-	printk("%s: Ariadne at 0x%08lx, Ethernet Address "
-	       "%02x:%02x:%02x:%02x:%02x:%02x\n", dev->name, board,
-	       dev->dev_addr[0], dev->dev_addr[1], dev->dev_addr[2],
-	       dev->dev_addr[3], dev->dev_addr[4], dev->dev_addr[5]);
-
-	dev->base_addr = ZTWO_VADDR(base_addr);
-	dev->mem_start = ZTWO_VADDR(mem_start);
-	dev->mem_end = dev->mem_start+ARIADNE_RAM_SIZE;
-
-	dev->open = &ariadne_open;
-	dev->stop = &ariadne_close;
-	dev->hard_start_xmit = &ariadne_start_xmit;
-	dev->tx_timeout = &ariadne_tx_timeout;
-	dev->watchdog_timeo = 5*HZ;
-	dev->get_stats = &ariadne_get_stats;
-	dev->set_multicast_list = &set_multicast_list;
-
-	res = register_netdev(dev);
-	if (res) {
-	    release_resource(r1);
-	    release_resource(r2);
-	    free_netdev(dev);
-	    break;
-	}
-#ifdef MODULE
-	priv->next_module = root_ariadne_dev;
-	root_ariadne_dev = priv;
-#endif
+    r1 = request_mem_region(base_addr, sizeof(struct Am79C960), "Am79C960");
+    if (!r1)
+	return -EBUSY;
+    r2 = request_mem_region(mem_start, ARIADNE_RAM_SIZE, "RAM");
+    if (!r2) {
+	release_resource(r1);
+	return -EBUSY;
+    }
+
+    dev = alloc_etherdev(sizeof(struct ariadne_private));
+    if (dev == NULL) {
+	release_resource(r1);
+	release_resource(r2);
+	return -ENOMEM;
+    }
+
+    SET_MODULE_OWNER(dev);
+    priv = dev->priv;
+
+    r1->name = dev->name;
+    r2->name = dev->name;
+
+    dev->dev_addr[0] = 0x00;
+    dev->dev_addr[1] = 0x60;
+    dev->dev_addr[2] = 0x30;
+    dev->dev_addr[3] = (z->rom.er_SerialNumber>>16) & 0xff;
+    dev->dev_addr[4] = (z->rom.er_SerialNumber>>8) & 0xff;
+    dev->dev_addr[5] = z->rom.er_SerialNumber & 0xff;
+    printk("%s: Ariadne at 0x%08lx, Ethernet Address "
+	   "%02x:%02x:%02x:%02x:%02x:%02x\n", dev->name, board,
+	   dev->dev_addr[0], dev->dev_addr[1], dev->dev_addr[2],
+	   dev->dev_addr[3], dev->dev_addr[4], dev->dev_addr[5]);
+
+    dev->base_addr = ZTWO_VADDR(base_addr);
+    dev->mem_start = ZTWO_VADDR(mem_start);
+    dev->mem_end = dev->mem_start+ARIADNE_RAM_SIZE;
+
+    dev->open = &ariadne_open;
+    dev->stop = &ariadne_close;
+    dev->hard_start_xmit = &ariadne_start_xmit;
+    dev->tx_timeout = &ariadne_tx_timeout;
+    dev->watchdog_timeo = 5*HZ;
+    dev->get_stats = &ariadne_get_stats;
+    dev->set_multicast_list = &set_multicast_list;
+
+    err = register_netdev(dev);
+    if (err) {
+	release_resource(r1);
+	release_resource(r2);
+	free_netdev(dev);
+	return err;
     }
-    return res;
+    zorro_set_drvdata(z, dev);
+
+    return 0;
 }
 
 
@@ -846,25 +850,27 @@ static void set_multicast_list(struct ne
 }
 
 
-static void __exit ariadne_cleanup(void)
+static void __devexit ariadne_remove_one(struct zorro_dev *z)
 {
-#ifdef MODULE
-    struct ariadne_private *next;
-    struct net_device *dev;
+    struct net_device *dev = zorro_get_drvdata(z);
 
-    while (root_ariadne_dev) {
-	next = root_ariadne_dev->next_module;
-	dev = root_ariadne_dev->dev;
-	unregister_netdev(dev);
-	release_mem_region(ZTWO_PADDR(dev->base_addr), sizeof(struct Am79C960));
-	release_mem_region(ZTWO_PADDR(dev->mem_start), ARIADNE_RAM_SIZE);
-	free_netdev(dev);
-	root_ariadne_dev = next;
-    }
-#endif
+    unregister_netdev(dev);
+    release_mem_region(ZTWO_PADDR(dev->base_addr), sizeof(struct Am79C960));
+    release_mem_region(ZTWO_PADDR(dev->mem_start), ARIADNE_RAM_SIZE);
+    free_netdev(dev);
+}
+
+static int __init ariadne_init_module(void)
+{
+    return zorro_module_init(&ariadne_driver);
+}
+
+static void __exit ariadne_cleanup_module(void)
+{
+    zorro_unregister_driver(&ariadne_driver);
 }
 
-module_init(ariadne_probe);
-module_exit(ariadne_cleanup);
+module_init(ariadne_init_module);
+module_exit(ariadne_cleanup_module);
 
 MODULE_LICENSE("GPL");
--- diff/drivers/net/arm/am79c961a.c	2004-02-18 08:54:10.000000000 +0000
+++ source/drivers/net/arm/am79c961a.c	2004-02-23 13:56:43.000000000 +0000
@@ -672,6 +672,10 @@ static int __init am79c961_init(void)
 	dev->base_addr = 0x220;
 	dev->irq = IRQ_EBSA110_ETHERNET;
 
+    	ret = -ENODEV;
+	if (!request_region(dev->base_addr, 0x18, dev->name))
+		goto nodev;
+
 	/*
 	 * Reset the device.
 	 */
@@ -682,14 +686,10 @@ static int __init am79c961_init(void)
 	 * Check the manufacturer part of the
 	 * ether address.
 	 */
-    	ret = -ENODEV;
 	if (inb(dev->base_addr) != 0x08 ||
 	    inb(dev->base_addr + 2) != 0x00 ||
 	    inb(dev->base_addr + 4) != 0x2b)
-	    	goto nodev;
-
-	if (!request_region(dev->base_addr, 0x18, dev->name))
-		goto nodev;
+	    	goto release;
 
 	am79c961_banner();
 	printk(KERN_INFO "%s: ether address ", dev->name);
--- diff/drivers/net/atari_pamsnet.c	2004-02-18 08:54:10.000000000 +0000
+++ source/drivers/net/atari_pamsnet.c	2004-02-23 13:56:43.000000000 +0000
@@ -484,7 +484,7 @@ static HADDR
 	    !acsi_wait_for_IRQ(TIMEOUTDMA) ||
 	    get_status())
 		goto bad;
-	ret = phys_to_virt(&(((DMAHWADDR *)buffer)->hwaddr));
+	ret = phys_to_virt((unsigned long)&(((DMAHWADDR *)buffer)->hwaddr));
 	dma_cache_maintenance((unsigned long)buffer, 512, 0);
 bad:
 	return (ret);
--- diff/drivers/net/bonding/bond_3ad.c	2004-02-18 08:54:10.000000000 +0000
+++ source/drivers/net/bonding/bond_3ad.c	2004-02-23 13:56:43.000000000 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright(c) 1999 - 2003 Intel Corporation. All rights reserved.
+ * Copyright(c) 1999 - 2004 Intel Corporation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
@@ -48,7 +48,7 @@
  *	  problem on very high Tx traffic load where packets may get dropped
  *	  by the slave.
  *
- * 2003/09/24 - Shmulik Hen <shmulik.hen at intel dot com>
+ * 2003/12/01 - Shmulik Hen <shmulik.hen at intel dot com>
  *	- Code cleanup and style changes
  */
 
@@ -2362,6 +2362,7 @@ int bond_3ad_xmit_xor(struct sk_buff *sk
 	int agg_id;
 	int i;
 	struct ad_info ad_info;
+	int res = 1;
 
 	/* make sure that the slaves list will
 	 * not change during tx
@@ -2369,12 +2370,12 @@ int bond_3ad_xmit_xor(struct sk_buff *sk
 	read_lock(&bond->lock);
 
 	if (!BOND_IS_OK(bond)) {
-		goto free_out;
+		goto out;
 	}
 
 	if (bond_3ad_get_active_agg_info(bond, &ad_info)) {
 		printk(KERN_DEBUG "ERROR: bond_3ad_get_active_agg_info failed\n");
-		goto free_out;
+		goto out;
 	}
 
 	slaves_in_agg = ad_info.ports;
@@ -2383,7 +2384,7 @@ int bond_3ad_xmit_xor(struct sk_buff *sk
 	if (slaves_in_agg == 0) {
 		/*the aggregator is empty*/
 		printk(KERN_DEBUG "ERROR: active aggregator is empty\n");
-		goto free_out;
+		goto out;
 	}
 
 	slave_agg_no = (data->h_dest[5]^bond->dev->dev_addr[5]) % slaves_in_agg;
@@ -2401,7 +2402,7 @@ int bond_3ad_xmit_xor(struct sk_buff *sk
 
 	if (slave_agg_no >= 0) {
 		printk(KERN_ERR DRV_NAME ": Error: Couldn't find a slave to tx on for aggregator ID %d\n", agg_id);
-		goto free_out;
+		goto out;
 	}
 
 	start_at = slave;
@@ -2414,24 +2415,19 @@ int bond_3ad_xmit_xor(struct sk_buff *sk
 			slave_agg_id = agg->aggregator_identifier;
 		}
 
-		if (SLAVE_IS_OK(slave) && 
-		    agg && (slave_agg_id == agg_id)) {
-			skb->dev = slave->dev;			
-			skb->priority = 1;
-			dev_queue_xmit(skb);
-
-			goto out;
+		if (SLAVE_IS_OK(slave) && agg && (slave_agg_id == agg_id)) {
+			res = bond_dev_queue_xmit(bond, skb, slave->dev);
+			break;
 		}
 	}
 
 out:
+	if (res) {
+		/* no suitable interface, frame not sent */
+		dev_kfree_skb(skb);
+	}
 	read_unlock(&bond->lock);
 	return 0;
-
-free_out:
-	/* no suitable interface, frame not sent */
-	dev_kfree_skb(skb);
-	goto out;
 }
 
 int bond_3ad_lacpdu_recv(struct sk_buff *skb, struct net_device *dev, struct packet_type* ptype)
--- diff/drivers/net/bonding/bond_3ad.h	2004-02-18 08:54:10.000000000 +0000
+++ source/drivers/net/bonding/bond_3ad.h	2004-02-23 13:56:43.000000000 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright(c) 1999 - 2003 Intel Corporation. All rights reserved.
+ * Copyright(c) 1999 - 2004 Intel Corporation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
@@ -29,7 +29,7 @@
  *	- Renamed bond_3ad_link_status_changed() to
  *	  bond_3ad_handle_link_change() for compatibility with TLB.
  *
- * 2003/09/24 - Shmulik Hen <shmulik.hen at intel dot com>
+ * 2003/12/01 - Shmulik Hen <shmulik.hen at intel dot com>
  *	- Code cleanup and style changes
  */
 
--- diff/drivers/net/bonding/bond_alb.c	2004-02-18 08:54:10.000000000 +0000
+++ source/drivers/net/bonding/bond_alb.c	2004-02-23 13:56:43.000000000 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright(c) 1999 - 2003 Intel Corporation. All rights reserved.
+ * Copyright(c) 1999 - 2004 Intel Corporation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the
@@ -29,8 +29,14 @@
  *	- Add support for setting bond's MAC address with special
  *	  handling required for ALB/TLB.
  *
- * 2003/09/24 - Shmulik Hen <shmulik.hen at intel dot com>
+ * 2003/12/01 - Shmulik Hen <shmulik.hen at intel dot com>
  *	- Code cleanup and style changes
+ *
+ * 2003/12/30 - Amir Noam <amir.noam at intel dot com>
+ *	- Fixed: Cannot remove and re-enslave the original active slave.
+ *
+ * 2004/01/14 - Shmulik Hen <shmulik.hen at intel dot com>
+ *	- Add capability to tag self generated packets in ALB/TLB modes.
  */
 
 //#define BONDING_DEBUG 1
@@ -47,6 +53,7 @@
 #include <linux/if_arp.h>
 #include <linux/if_ether.h>
 #include <linux/if_bonding.h>
+#include <linux/if_vlan.h>
 #include <net/ipx.h>
 #include <net/arp.h>
 #include <asm/byteorder.h>
@@ -76,7 +83,7 @@
 
 
 #define TLB_NULL_INDEX		0xffffffff
-#define MAX_LP_RETRY		3
+#define MAX_LP_BURST		3
 
 /* rlb defs */
 #define RLB_HASH_TABLE_SIZE	256
@@ -495,13 +502,33 @@ static void rlb_update_client(struct rlb
 	}
 
 	for (i = 0; i < RLB_ARP_BURST_SIZE; i++) {
-		arp_send(ARPOP_REPLY, ETH_P_ARP,
-			 client_info->ip_dst,
-			 client_info->slave->dev,
-			 client_info->ip_src,
-			 client_info->mac_dst,
-			 client_info->slave->dev->dev_addr,
-			 client_info->mac_dst);
+		struct sk_buff *skb;
+
+		skb = arp_create(ARPOP_REPLY, ETH_P_ARP,
+				 client_info->ip_dst,
+				 client_info->slave->dev,
+				 client_info->ip_src,
+				 client_info->mac_dst,
+				 client_info->slave->dev->dev_addr,
+				 client_info->mac_dst);
+		if (!skb) {
+			printk(KERN_ERR DRV_NAME
+			       ": Error: failed to create an ARP packet\n");
+			continue;
+		}
+
+		skb->dev = client_info->slave->dev;
+
+		if (client_info->tag) {
+			skb = vlan_put_tag(skb, client_info->vlan_id);
+			if (!skb) {
+				printk(KERN_ERR DRV_NAME
+				       ": Error: failed to insert VLAN tag\n");
+				continue;
+			}
+		}
+
+		arp_xmit(skb);
 	}
 }
 
@@ -600,9 +627,10 @@ static void rlb_req_update_subnet_client
 }
 
 /* Caller must hold both bond and ptr locks for read */
-struct slave *rlb_choose_channel(struct bonding *bond, struct arp_pkt *arp)
+struct slave *rlb_choose_channel(struct sk_buff *skb, struct bonding *bond)
 {
 	struct alb_bond_info *bond_info = &(BOND_ALB_INFO(bond));
+	struct arp_pkt *arp = (struct arp_pkt *)skb->nh.raw;
 	struct slave *assigned_slave;
 	struct rlb_client_info *client_info;
 	u32 hash_index = 0;
@@ -658,6 +686,15 @@ struct slave *rlb_choose_channel(struct 
 			client_info->ntt = 0;
 		}
 
+		if (!list_empty(&bond->vlan_list)) {
+			unsigned short vlan_id;
+			int res = vlan_get_tag(skb, &vlan_id);
+			if (!res) {
+				client_info->tag = 1;
+				client_info->vlan_id = vlan_id;
+			}
+		}
+
 		if (!client_info->assigned) {
 			u32 prev_tbl_head = bond_info->rx_hashtbl_head;
 			bond_info->rx_hashtbl_head = hash_index;
@@ -688,7 +725,7 @@ static struct slave *rlb_arp_xmit(struct
 		/* the arp must be sent on the selected
 		* rx channel
 		*/
-		tx_slave = rlb_choose_channel(bond, arp);
+		tx_slave = rlb_choose_channel(skb, bond);
 		if (tx_slave) {
 			memcpy(arp->mac_src,tx_slave->dev->dev_addr, ETH_ALEN);
 		}
@@ -699,7 +736,7 @@ static struct slave *rlb_arp_xmit(struct
 		 * When the arp reply is received the entry will be updated
 		 * with the correct unicast address of the client.
 		 */
-		rlb_choose_channel(bond, arp);
+		rlb_choose_channel(skb, bond);
 
 		/* The ARP relpy packets must be delayed so that
 		 * they can cancel out the influence of the ARP request.
@@ -805,6 +842,40 @@ static void rlb_deinitialize(struct bond
 
 	kfree(bond_info->rx_hashtbl);
 	bond_info->rx_hashtbl = NULL;
+	bond_info->rx_hashtbl_head = RLB_NULL_INDEX;
+
+	_unlock_rx_hashtbl(bond);
+}
+
+static void rlb_clear_vlan(struct bonding *bond, unsigned short vlan_id)
+{
+	struct alb_bond_info *bond_info = &(BOND_ALB_INFO(bond));
+	u32 curr_index;
+
+	_lock_rx_hashtbl(bond);
+
+	curr_index = bond_info->rx_hashtbl_head;
+	while (curr_index != RLB_NULL_INDEX) {
+		struct rlb_client_info *curr = &(bond_info->rx_hashtbl[curr_index]);
+		u32 next_index = bond_info->rx_hashtbl[curr_index].next;
+		u32 prev_index = bond_info->rx_hashtbl[curr_index].prev;
+
+		if (curr->tag && (curr->vlan_id == vlan_id)) {
+			if (curr_index == bond_info->rx_hashtbl_head) {
+				bond_info->rx_hashtbl_head = next_index;
+			}
+			if (prev_index != RLB_NULL_INDEX) {
+				bond_info->rx_hashtbl[prev_index].next = next_index;
+			}
+			if (next_index != RLB_NULL_INDEX) {
+				bond_info->rx_hashtbl[next_index].prev = prev_index;
+			}
+
+			rlb_init_table_entry(curr);
+		}
+
+		curr_index = next_index;
+	}
 
 	_unlock_rx_hashtbl(bond);
 }
@@ -813,6 +884,7 @@ static void rlb_deinitialize(struct bond
 
 static void alb_send_learning_packets(struct slave *slave, u8 mac_addr[])
 {
+	struct bonding *bond = bond_get_bond_by_slave(slave);
 	struct learning_pkt pkt;
 	int size = sizeof(struct learning_pkt);
 	int i;
@@ -822,7 +894,7 @@ static void alb_send_learning_packets(st
 	memcpy(pkt.mac_src, mac_addr, ETH_ALEN);
 	pkt.type = __constant_htons(ETH_P_LOOP);
 
-	for (i = 0; i < MAX_LP_RETRY; i++) {
+	for (i = 0; i < MAX_LP_BURST; i++) {
 		struct sk_buff *skb;
 		char *data;
 
@@ -840,6 +912,26 @@ static void alb_send_learning_packets(st
 		skb->priority = TC_PRIO_CONTROL;
 		skb->dev = slave->dev;
 
+		if (!list_empty(&bond->vlan_list)) {
+			struct vlan_entry *vlan;
+
+			vlan = bond_next_vlan(bond,
+					      bond->alb_info.current_alb_vlan);
+
+			bond->alb_info.current_alb_vlan = vlan;
+			if (!vlan) {
+				kfree_skb(skb);
+				continue;
+			}
+
+			skb = vlan_put_tag(skb, vlan->vlan_id);
+			if (!skb) {
+				printk(KERN_ERR DRV_NAME
+				       ": Error: failed to insert VLAN tag\n");
+				continue;
+			}
+		}
+
 		dev_queue_xmit(skb);
 	}
 }
@@ -992,6 +1084,7 @@ static void alb_change_hw_addr_on_detach
 static int alb_handle_addr_collision_on_attach(struct bonding *bond, struct slave *slave)
 {
 	struct slave *tmp_slave1, *tmp_slave2, *free_mac_slave;
+	struct slave *has_bond_addr = bond->curr_active_slave;
 	int i, j, found = 0;
 
 	if (bond->slave_cnt == 0) {
@@ -1049,6 +1142,15 @@ static int alb_handle_addr_collision_on_
 			free_mac_slave = tmp_slave1;
 			break;
 		}
+
+		if (!has_bond_addr) {
+			if (!memcmp(tmp_slave1->dev->dev_addr,
+				    bond->dev->dev_addr,
+				    ETH_ALEN)) {
+
+				has_bond_addr = tmp_slave1;
+			}
+		}
 	}
 
 	if (free_mac_slave) {
@@ -1059,7 +1161,8 @@ static int alb_handle_addr_collision_on_
 		       ": Warning: the hw address of slave %s is in use by "
 		       "the bond; giving it the hw address of %s\n",
 		       slave->dev->name, free_mac_slave->dev->name);
-	} else {
+
+	} else if (has_bond_addr) {
 		printk(KERN_ERR DRV_NAME
 		       ": Error: the hw address of slave %s is in use by the "
 		       "bond; couldn't find a slave with a free hw address to "
@@ -1171,7 +1274,7 @@ void bond_alb_deinitialize(struct bondin
 int bond_alb_xmit(struct sk_buff *skb, struct net_device *bond_dev)
 {
 	struct bonding *bond = bond_dev->priv;
-	struct ethhdr *eth_data = (struct ethhdr *)skb->mac.raw = skb->data;
+	struct ethhdr *eth_data;
 	struct alb_bond_info *bond_info = &(BOND_ALB_INFO(bond));
 	struct slave *tx_slave = NULL;
 	static u32 ip_bcast = 0xffffffff;
@@ -1179,6 +1282,10 @@ int bond_alb_xmit(struct sk_buff *skb, s
 	int do_tx_balance = 1;
 	u32 hash_index = 0;
 	u8 *hash_start = NULL;
+	int res = 1;
+
+	skb->mac.raw = (unsigned char *)skb->data;
+	eth_data = (struct ethhdr *)skb->data;
 
 	/* make sure that the curr_active_slave and the slaves list do
 	 * not change during tx
@@ -1187,7 +1294,7 @@ int bond_alb_xmit(struct sk_buff *skb, s
 	read_lock(&bond->curr_slave_lock);
 
 	if (!BOND_IS_OK(bond)) {
-		goto free_out;
+		goto out;
 	}
 
 	switch (ntohs(skb->protocol)) {
@@ -1217,8 +1324,7 @@ int bond_alb_xmit(struct sk_buff *skb, s
 			break;
 		}
 
-		if (ipx_hdr(skb)->ipx_type !=
-		    __constant_htons(IPX_TYPE_NCP)) {
+		if (ipx_hdr(skb)->ipx_type != IPX_TYPE_NCP) {
 			/* The only protocol worth balancing in
 			 * this family since it has an "ARP" like
 			 * mechanism
@@ -1253,29 +1359,27 @@ int bond_alb_xmit(struct sk_buff *skb, s
 	}
 
 	if (tx_slave && SLAVE_IS_OK(tx_slave)) {
-		skb->dev = tx_slave->dev;
 		if (tx_slave != bond->curr_active_slave) {
 			memcpy(eth_data->h_source,
 			       tx_slave->dev->dev_addr,
 			       ETH_ALEN);
 		}
-		dev_queue_xmit(skb);
+
+		res = bond_dev_queue_xmit(bond, skb, tx_slave->dev);
 	} else {
-		/* no suitable interface, frame not sent */
 		if (tx_slave) {
 			tlb_clear_slave(bond, tx_slave, 0);
 		}
-		goto free_out;
 	}
 
 out:
+	if (res) {
+		/* no suitable interface, frame not sent */
+		dev_kfree_skb(skb);
+	}
 	read_unlock(&bond->curr_slave_lock);
 	read_unlock(&bond->lock);
 	return 0;
-
-free_out:
-	dev_kfree_skb(skb);
-	goto out;
 }
 
 void bond_alb_monitor(struct bonding *bond)
@@ -1576,3 +1680,15 @@ int bond_alb_set_mac_address(struct net_
 	return 0;
 }
 
+void bond_alb_clear_vlan(struct bonding *bond, unsigned short vlan_id)
+{
+	if (bond->alb_info.current_alb_vlan &&
+	    (bond->alb_info.current_alb_vlan->vlan_id == vlan_id)) {
+		bond->alb_info.current_alb_vlan = NULL;
+	}
+
+	if (bond->alb_info.rlb_enabled) {
+		rlb_clear_vlan(bond, vlan_id);
+	}
+}
+
--- diff/drivers/net/bonding/bond_alb.h	2004-02-18 08:54:10.000000000 +0000
+++ source/drivers/net/bonding/bond_alb.h	2004-02-23 13:56:43.000000000 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright(c) 1999 - 2003 Intel Corporation. All rights reserved.
+ * Copyright(c) 1999 - 2004 Intel Corporation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the
@@ -25,7 +25,7 @@
  *	- Add support for setting bond's MAC address with special
  *	  handling required for ALB/TLB.
  *
- * 2003/09/24 - Shmulik Hen <shmulik.hen at intel dot com>
+ * 2003/12/01 - Shmulik Hen <shmulik.hen at intel dot com>
  *	- Code cleanup and style changes
  */
 
@@ -77,6 +77,8 @@ struct rlb_client_info {
 	u8  assigned;		/* checking whether this entry is assigned */
 	u8  ntt;		/* flag - need to transmit client info */
 	struct slave *slave;	/* the slave assigned to this client */
+	u8 tag;			/* flag - need to tag skb */
+	unsigned short vlan_id;	/* VLAN tag associated with IP address */
 };
 
 struct tlb_slave_info {
@@ -122,6 +124,7 @@ struct alb_bond_info {
 						 * rx traffic should be
 						 * rebalanced
 						 */
+	struct vlan_entry	*current_alb_vlan;
 };
 
 int bond_alb_initialize(struct bonding *bond, int rlb_enabled);
@@ -133,6 +136,6 @@ void bond_alb_handle_active_change(struc
 int bond_alb_xmit(struct sk_buff *skb, struct net_device *bond_dev);
 void bond_alb_monitor(struct bonding *bond);
 int bond_alb_set_mac_address(struct net_device *bond_dev, void *addr);
-
+void bond_alb_clear_vlan(struct bonding *bond, unsigned short vlan_id);
 #endif /* __BOND_ALB_H__ */
 
--- diff/drivers/net/bonding/bond_main.c	2004-02-18 08:54:10.000000000 +0000
+++ source/drivers/net/bonding/bond_main.c	2004-02-23 13:56:43.000000000 +0000
@@ -452,6 +452,23 @@
  *	  o Change struct member names and types.
  *	  o Chomp trailing spaces, remove empty lines, fix indentations.
  *	  o Re-organize code according to context.
+ *
+ * 2003/12/30 - Amir Noam <amir.noam at intel dot com>
+ *	- Fixed: Cannot remove and re-enslave the original active slave.
+ *	- Fixed: Releasing the original active slave causes mac address
+ *		 duplication.
+ *	- Add support for slaves that use ethtool_ops.
+ *	  Set version to 2.5.3.
+ *
+ * 2004/01/05 - Amir Noam <amir.noam at intel dot com>
+ *	- Save bonding parameters per bond instead of using the global values.
+ *	  Set version to 2.5.4.
+ *
+ * 2004/01/14 - Shmulik Hen <shmulik.hen at intel dot com>
+ *	- Enhance VLAN support:
+ *	  * Add support for VLAN hardware acceleration capable slaves.
+ *	  * Add capability to tag self generated packets in ALB/TLB modes.
+ *	  Set version to 2.6.0.
  */
 
 //#define BONDING_DEBUG 1
@@ -493,6 +510,7 @@
 #include <net/arp.h>
 #include <linux/mii.h>
 #include <linux/ethtool.h>
+#include <linux/if_vlan.h>
 #include <linux/if_bonding.h>
 #include "bonding.h"
 #include "bond_3ad.h"
@@ -503,7 +521,6 @@
 /* monitor all links that often (in milliseconds). <=0 disables monitoring */
 #define BOND_LINK_MON_INTERV	0
 #define BOND_LINK_ARP_INTERV	0
-#define MAX_ARP_IP_TARGETS	16
 
 static int max_bonds	= BOND_DEFAULT_MAX_BONDS;
 static int miimon	= BOND_LINK_MON_INTERV;
@@ -514,7 +531,7 @@ static char *mode	= NULL;
 static char *primary	= NULL;
 static char *lacp_rate	= NULL;
 static int arp_interval = BOND_LINK_ARP_INTERV;
-static char *arp_ip_target[MAX_ARP_IP_TARGETS] = { NULL, };
+static char *arp_ip_target[BOND_MAX_ARP_TARGETS] = { NULL, };
 
 MODULE_PARM(max_bonds, "i");
 MODULE_PARM_DESC(max_bonds, "Max number of bonded devices");
@@ -534,7 +551,7 @@ MODULE_PARM(lacp_rate, "s");
 MODULE_PARM_DESC(lacp_rate, "LACPDU tx rate to request from 802.3ad partner (slow/fast)");
 MODULE_PARM(arp_interval, "i");
 MODULE_PARM_DESC(arp_interval, "arp interval in milliseconds");
-MODULE_PARM(arp_ip_target, "1-" __MODULE_STRING(MAX_ARP_IP_TARGETS) "s");
+MODULE_PARM(arp_ip_target, "1-" __MODULE_STRING(BOND_MAX_ARP_TARGETS) "s");
 MODULE_PARM_DESC(arp_ip_target, "arp targets in n.n.n.n form");
 
 /*----------------------------- Global variables ----------------------------*/
@@ -548,7 +565,7 @@ static LIST_HEAD(bond_dev_list);
 static struct proc_dir_entry *bond_proc_dir = NULL;
 #endif
 
-static u32 arp_target[MAX_ARP_IP_TARGETS] = { 0, } ;
+static u32 arp_target[BOND_MAX_ARP_TARGETS] = { 0, } ;
 static int arp_ip_count	= 0;
 static u32 my_ip	= 0;
 static int bond_mode	= BOND_MODE_ROUNDROBIN;
@@ -584,11 +601,15 @@ static struct bond_parm_tbl bond_mode_tb
 {	NULL,			-1},
 };
 
+/*-------------------------- Forward declarations ---------------------------*/
+
+static inline void bond_set_mode_ops(struct net_device *bond_dev, int mode);
+
 /*---------------------------- General routines -----------------------------*/
 
-static const char *bond_mode_name(void)
+static const char *bond_mode_name(int mode)
 {
-	switch (bond_mode) {
+	switch (mode) {
 	case BOND_MODE_ROUNDROBIN :
 		return "load balancing (round-robin)";
 	case BOND_MODE_ACTIVEBACKUP :
@@ -608,6 +629,371 @@ static const char *bond_mode_name(void)
 	}
 }
 
+/*---------------------------------- VLAN -----------------------------------*/
+
+/**
+ * bond_add_vlan - add a new vlan id on bond
+ * @bond: bond that got the notification
+ * @vlan_id: the vlan id to add
+ *
+ * Returns -ENOMEM if allocation failed.
+ */
+static int bond_add_vlan(struct bonding *bond, unsigned short vlan_id)
+{
+	struct vlan_entry *vlan;
+
+	dprintk("bond: %s, vlan id %d\n",
+		(bond ? bond->dev->name: "None"), vlan_id);
+
+	vlan = kmalloc(sizeof(struct vlan_entry), GFP_KERNEL);
+	if (!vlan) {
+		return -ENOMEM;
+	}
+
+	INIT_LIST_HEAD(&vlan->vlan_list);
+	vlan->vlan_id = vlan_id;
+
+	write_lock_bh(&bond->lock);
+
+	list_add_tail(&vlan->vlan_list, &bond->vlan_list);
+
+	write_unlock_bh(&bond->lock);
+
+	dprintk("added VLAN ID %d on bond %s\n", vlan_id, bond->dev->name);
+
+	return 0;
+}
+
+/**
+ * bond_del_vlan - delete a vlan id from bond
+ * @bond: bond that got the notification
+ * @vlan_id: the vlan id to delete
+ *
+ * returns -ENODEV if @vlan_id was not found in @bond.
+ */
+static int bond_del_vlan(struct bonding *bond, unsigned short vlan_id)
+{
+	struct vlan_entry *vlan, *next;
+	int res = -ENODEV;
+
+	dprintk("bond: %s, vlan id %d\n", bond->dev->name, vlan_id);
+
+	write_lock_bh(&bond->lock);
+
+	list_for_each_entry_safe(vlan, next, &bond->vlan_list, vlan_list) {
+		if (vlan->vlan_id == vlan_id) {
+			list_del(&vlan->vlan_list);
+
+			if ((bond->params.mode == BOND_MODE_TLB) ||
+			    (bond->params.mode == BOND_MODE_ALB)) {
+				bond_alb_clear_vlan(bond, vlan_id);
+			}
+
+			dprintk("removed VLAN ID %d from bond %s\n", vlan_id,
+				bond->dev->name);
+
+			kfree(vlan);
+
+			if (list_empty(&bond->vlan_list) &&
+			    (bond->slave_cnt == 0)) {
+				/* Last VLAN removed and no slaves, so
+				 * restore block on adding VLANs. This will
+				 * be removed once new slaves that are not
+				 * VLAN challenged will be added.
+				 */
+				bond->dev->features |= NETIF_F_VLAN_CHALLENGED;
+			}
+
+			res = 0;
+			goto out;
+		}
+	}
+
+	dprintk("couldn't find VLAN ID %d in bond %s\n", vlan_id,
+		bond->dev->name);
+
+out:
+	write_unlock_bh(&bond->lock);
+	return res;
+}
+
+/**
+ * bond_has_challenged_slaves
+ * @bond: the bond we're working on
+ *
+ * Searches the slave list. Returns 1 if a vlan challenged slave
+ * was found, 0 otherwise.
+ *
+ * Assumes bond->lock is held.
+ */
+static int bond_has_challenged_slaves(struct bonding *bond)
+{
+	struct slave *slave;
+	int i;
+
+	bond_for_each_slave(bond, slave, i) {
+		if (slave->dev->features & NETIF_F_VLAN_CHALLENGED) {
+			dprintk("found VLAN challenged slave - %s\n",
+				slave->dev->name);
+			return 1;
+		}
+	}
+
+	dprintk("no VLAN challenged slaves found\n");
+	return 0;
+}
+
+/**
+ * bond_next_vlan - safely skip to the next item in the vlans list.
+ * @bond: the bond we're working on
+ * @curr: item we're advancing from
+ *
+ * Returns %NULL if list is empty, bond->next_vlan if @curr is %NULL,
+ * or @curr->next otherwise (even if it is @curr itself again).
+ * 
+ * Caller must hold bond->lock
+ */
+struct vlan_entry *bond_next_vlan(struct bonding *bond, struct vlan_entry *curr)
+{
+	struct vlan_entry *next, *last;
+
+	if (list_empty(&bond->vlan_list)) {
+		return NULL;
+	}
+
+	if (!curr) {
+		next = list_entry(bond->vlan_list.next,
+				  struct vlan_entry, vlan_list);
+	} else {
+		last = list_entry(bond->vlan_list.prev,
+				  struct vlan_entry, vlan_list);
+		if (last == curr) {
+			next = list_entry(bond->vlan_list.next,
+					  struct vlan_entry, vlan_list);
+		} else {
+			next = list_entry(curr->vlan_list.next,
+					  struct vlan_entry, vlan_list);
+		}
+	}
+
+	return next;
+}
+
+/**
+ * bond_dev_queue_xmit - Prepare skb for xmit.
+ * 
+ * @bond: bond device that got this skb for tx.
+ * @skb: hw accel VLAN tagged skb to transmit
+ * @slave_dev: slave that is supposed to xmit this skbuff
+ * 
+ * When the bond gets an skb to tarnsmit that is
+ * already hardware accelerated VLAN tagged, and it
+ * needs to relay this skb to a slave that is not
+ * hw accel capable, the skb needs to be "unaccelerated",
+ * i.e. strip the hwaccel tag and re-insert it as part
+ * of the payload.
+ * 
+ * Assumption - once a VLAN device is created over the bond device, all
+ * packets are going to be hardware accelerated VLAN tagged since the IP
+ * binding is done over the VLAN device
+ */
+int bond_dev_queue_xmit(struct bonding *bond, struct sk_buff *skb, struct net_device *slave_dev)
+{
+	unsigned short vlan_id;
+	int res;
+
+	if (!list_empty(&bond->vlan_list) &&
+	    !(slave_dev->features & NETIF_F_HW_VLAN_TX)) {
+		res = vlan_get_tag(skb, &vlan_id);
+		if (res) {
+			return -EINVAL;
+		}
+
+		skb->dev = slave_dev;
+		skb = vlan_put_tag(skb, vlan_id);
+		if (!skb) {
+			/* vlan_put_tag() frees the skb in case of error,
+			 * so return success here so the calling functions
+			 * won't attempt to free is again.
+			 */
+			return 0;
+		}
+	} else {
+		skb->dev = slave_dev;
+	}
+
+	skb->priority = 1;
+	dev_queue_xmit(skb);
+
+	return 0;
+}
+
+/*
+ * In the following 3 functions, bond_vlan_rx_register(), bond_vlan_rx_add_vid
+ * and bond_vlan_rx_kill_vid, We don't protect the slave list iteration with a
+ * lock because:
+ * a. This operation is performed in IOCTL context,
+ * b. The operation is protected by the RTNL semaphore in the 8021q code,
+ * c. Holding a lock with BH disabled while directly calling a base driver
+ *    entry point is generally a BAD idea.
+ * 
+ * The design of synchronization/protection for this operation in the 8021q
+ * module is good for one or more VLAN devices over a single physical device
+ * and cannot be extended for a teaming solution like bonding, so there is a
+ * potential race condition here where a net device from the vlan group might
+ * be referenced (either by a base driver or the 8021q code) while it is being
+ * removed from the system. However, it turns out we're not making matters
+ * worse, and if it works for regular VLAN usage it will work here too.
+*/
+
+/**
+ * bond_vlan_rx_register - Propagates registration to slaves
+ * @bond_dev: bonding net device that got called
+ * @grp: vlan group being registered
+ */
+static void bond_vlan_rx_register(struct net_device *bond_dev, struct vlan_group *grp)
+{
+	struct bonding *bond = bond_dev->priv;
+	struct slave *slave;
+	int i;
+
+	bond->vlgrp = grp;
+
+	bond_for_each_slave(bond, slave, i) {
+		struct net_device *slave_dev = slave->dev;
+
+		if ((slave_dev->features & NETIF_F_HW_VLAN_RX) &&
+		    slave_dev->vlan_rx_register) {
+			slave_dev->vlan_rx_register(slave_dev, grp);
+		}
+	}
+}
+
+/**
+ * bond_vlan_rx_add_vid - Propagates adding an id to slaves
+ * @bond_dev: bonding net device that got called
+ * @vid: vlan id being added
+ */
+static void bond_vlan_rx_add_vid(struct net_device *bond_dev, uint16_t vid)
+{
+	struct bonding *bond = bond_dev->priv;
+	struct slave *slave;
+	int i, res;
+
+	bond_for_each_slave(bond, slave, i) {
+		struct net_device *slave_dev = slave->dev;
+
+		if ((slave_dev->features & NETIF_F_HW_VLAN_FILTER) &&
+		    slave_dev->vlan_rx_add_vid) {
+			slave_dev->vlan_rx_add_vid(slave_dev, vid);
+		}
+	}
+
+	res = bond_add_vlan(bond, vid);
+	if (res) {
+		printk(KERN_ERR DRV_NAME
+		       ": %s: Failed to add vlan id %d\n",
+		       bond_dev->name, vid);
+	}
+}
+
+/**
+ * bond_vlan_rx_kill_vid - Propagates deleting an id to slaves
+ * @bond_dev: bonding net device that got called
+ * @vid: vlan id being removed
+ */
+static void bond_vlan_rx_kill_vid(struct net_device *bond_dev, uint16_t vid)
+{
+	struct bonding *bond = bond_dev->priv;
+	struct slave *slave;
+	struct net_device *vlan_dev;
+	int i, res;
+
+	bond_for_each_slave(bond, slave, i) {
+		struct net_device *slave_dev = slave->dev;
+
+		if ((slave_dev->features & NETIF_F_HW_VLAN_FILTER) &&
+		    slave_dev->vlan_rx_kill_vid) {
+			/* Save and then restore vlan_dev in the grp array,
+			 * since the slave's driver might clear it.
+			 */
+			vlan_dev = bond->vlgrp->vlan_devices[vid];
+			slave_dev->vlan_rx_kill_vid(slave_dev, vid);
+			bond->vlgrp->vlan_devices[vid] = vlan_dev;
+		}
+	}
+
+	res = bond_del_vlan(bond, vid);
+	if (res) {
+		printk(KERN_ERR DRV_NAME
+		       ": %s: Failed to remove vlan id %d\n",
+		       bond_dev->name, vid);
+	}
+}
+
+static void bond_add_vlans_on_slave(struct bonding *bond, struct net_device *slave_dev)
+{
+	struct vlan_entry *vlan;
+
+	write_lock_bh(&bond->lock);
+
+	if (list_empty(&bond->vlan_list)) {
+		goto out;
+	}
+
+	if ((slave_dev->features & NETIF_F_HW_VLAN_RX) &&
+	    slave_dev->vlan_rx_register) {
+		slave_dev->vlan_rx_register(slave_dev, bond->vlgrp);
+	}
+
+	if (!(slave_dev->features & NETIF_F_HW_VLAN_FILTER) ||
+	    !(slave_dev->vlan_rx_add_vid)) {
+		goto out;
+	}
+
+	list_for_each_entry(vlan, &bond->vlan_list, vlan_list) {
+		slave_dev->vlan_rx_add_vid(slave_dev, vlan->vlan_id);
+	}
+
+out:
+	write_unlock_bh(&bond->lock);
+}
+
+static void bond_del_vlans_from_slave(struct bonding *bond, struct net_device *slave_dev)
+{
+	struct vlan_entry *vlan;
+	struct net_device *vlan_dev;
+
+	write_lock_bh(&bond->lock);
+
+	if (list_empty(&bond->vlan_list)) {
+		goto out;
+	}
+
+	if (!(slave_dev->features & NETIF_F_HW_VLAN_FILTER) ||
+	    !(slave_dev->vlan_rx_kill_vid)) {
+		goto unreg;
+	}
+
+	list_for_each_entry(vlan, &bond->vlan_list, vlan_list) {
+		/* Save and then restore vlan_dev in the grp array,
+		 * since the slave's driver might clear it.
+		 */
+		vlan_dev = bond->vlgrp->vlan_devices[vlan->vlan_id];
+		slave_dev->vlan_rx_kill_vid(slave_dev, vlan->vlan_id);
+		bond->vlgrp->vlan_devices[vlan->vlan_id] = vlan_dev;
+	}
+
+unreg:
+	if ((slave_dev->features & NETIF_F_HW_VLAN_RX) &&
+	    slave_dev->vlan_rx_register) {
+		slave_dev->vlan_rx_register(slave_dev, NULL);
+	}
+
+out:
+	write_unlock_bh(&bond->lock);
+}
+
 /*------------------------------- Link status -------------------------------*/
 
 /*
@@ -623,44 +1009,55 @@ static int bond_update_speed_duplex(stru
 	struct ifreq ifr;
 	struct ethtool_cmd etool;
 
-	ioctl = slave_dev->do_ioctl;
-	if (ioctl) {
-		etool.cmd = ETHTOOL_GSET;
-		ifr.ifr_data = (char*)&etool;
-		if (IOCTL(slave_dev, &ifr, SIOCETHTOOL) == 0) {
-			slave->speed = etool.speed;
-			slave->duplex = etool.duplex;
-		} else {
-			goto err_out;
+	/* Fake speed and duplex */
+	slave->speed = SPEED_100;
+	slave->duplex = DUPLEX_FULL;
+
+	if (slave_dev->ethtool_ops) {
+		u32 res;
+
+		if (!slave_dev->ethtool_ops->get_settings) {
+			return -1;
 		}
-	} else {
-		goto err_out;
+
+		res = slave_dev->ethtool_ops->get_settings(slave_dev, &etool);
+		if (res < 0) {
+			return -1;
+		}
+
+		goto verify;
+	}
+
+	ioctl = slave_dev->do_ioctl;
+	strncpy(ifr.ifr_name, slave_dev->name, IFNAMSIZ);
+	etool.cmd = ETHTOOL_GSET;
+	ifr.ifr_data = (char*)&etool;
+	if (!ioctl || (IOCTL(slave_dev, &ifr, SIOCETHTOOL) < 0)) {
+		return -1;
 	}
 
-	switch (slave->speed) {
+verify:
+	switch (etool.speed) {
 	case SPEED_10:
 	case SPEED_100:
 	case SPEED_1000:
 		break;
 	default:
-		goto err_out;
+		return -1;
 	}
 
-	switch (slave->duplex) {
+	switch (etool.duplex) {
 	case DUPLEX_FULL:
 	case DUPLEX_HALF:
 		break;
 	default:
-		goto err_out;
+		return -1;
 	}
 
-	return 0;
+	slave->speed = etool.speed;
+	slave->duplex = etool.duplex;
 
-err_out:
-	/* Fake speed and duplex */
-	slave->speed = SPEED_100;
-	slave->duplex = DUPLEX_FULL;
-	return -1;
+	return 0;
 }
 
 /*
@@ -679,14 +1076,14 @@ err_out:
  * It'd be nice if there was a good way to tell if a driver supports
  * netif_carrier, but there really isn't.
  */
-static int bond_check_dev_link(struct net_device *slave_dev, int reporting)
+static int bond_check_dev_link(struct bonding *bond, struct net_device *slave_dev, int reporting)
 {
 	static int (* ioctl)(struct net_device *, struct ifreq *, int);
 	struct ifreq ifr;
 	struct mii_ioctl_data *mii;
 	struct ethtool_value etool;
 
-	if (use_carrier) {
+	if (bond->params.use_carrier) {
 		return netif_carrier_ok(slave_dev) ? BMSR_LSTATUS : 0;
 	}
 
@@ -705,6 +1102,7 @@ static int bond_check_dev_link(struct ne
 		 */
 
 		/* Yes, the mii is overlaid on the ifreq.ifr_ifru */
+		strncpy(ifr.ifr_name, slave_dev->name, IFNAMSIZ);
 		mii = (struct mii_ioctl_data *)&ifr.ifr_data;
 		if (IOCTL(slave_dev, &ifr, SIOCGMIIPHY) == 0) {
 			mii->reg_num = MII_BMSR;
@@ -712,10 +1110,23 @@ static int bond_check_dev_link(struct ne
 				return (mii->val_out & BMSR_LSTATUS);
 			}
 		}
+	}
 
-		/* try SIOCETHTOOL ioctl, some drivers cache ETHTOOL_GLINK */
-		/* for a period of time so we attempt to get link status   */
-		/* from it last if the above MII ioctls fail...            */
+	/* try SIOCETHTOOL ioctl, some drivers cache ETHTOOL_GLINK */
+	/* for a period of time so we attempt to get link status   */
+	/* from it last if the above MII ioctls fail...            */
+	if (slave_dev->ethtool_ops) {
+		if (slave_dev->ethtool_ops->get_link) {
+			u32 link;
+
+			link = slave_dev->ethtool_ops->get_link(slave_dev);
+
+			return link ? BMSR_LSTATUS : 0;
+		}
+	}
+
+	if (ioctl) {
+		strncpy(ifr.ifr_name, slave_dev->name, IFNAMSIZ);
 		etool.cmd = ETHTOOL_GLINK;
 		ifr.ifr_data = (char*)&etool;
 		if (IOCTL(slave_dev, &ifr, SIOCETHTOOL) == 0) {
@@ -769,7 +1180,7 @@ static struct dev_mc_list *bond_mc_list_
  */
 static void bond_set_promiscuity(struct bonding *bond, int inc)
 {
-	if (USES_PRIMARY(bond_mode)) {
+	if (USES_PRIMARY(bond->params.mode)) {
 		/* write lock already acquired */
 		if (bond->curr_active_slave) {
 			dev_set_promiscuity(bond->curr_active_slave->dev, inc);
@@ -788,7 +1199,7 @@ static void bond_set_promiscuity(struct 
  */
 static void bond_set_allmulti(struct bonding *bond, int inc)
 {
-	if (USES_PRIMARY(bond_mode)) {
+	if (USES_PRIMARY(bond->params.mode)) {
 		/* write lock already acquired */
 		if (bond->curr_active_slave) {
 			dev_set_allmulti(bond->curr_active_slave->dev, inc);
@@ -808,7 +1219,7 @@ static void bond_set_allmulti(struct bon
  */
 static void bond_mc_add(struct bonding *bond, void *addr, int alen)
 {
-	if (USES_PRIMARY(bond_mode)) {
+	if (USES_PRIMARY(bond->params.mode)) {
 		/* write lock already acquired */
 		if (bond->curr_active_slave) {
 			dev_mc_add(bond->curr_active_slave->dev, addr, alen, 0);
@@ -828,7 +1239,7 @@ static void bond_mc_add(struct bonding *
  */
 static void bond_mc_delete(struct bonding *bond, void *addr, int alen)
 {
-	if (USES_PRIMARY(bond_mode)) {
+	if (USES_PRIMARY(bond->params.mode)) {
 		/* write lock already acquired */
 		if (bond->curr_active_slave) {
 			dev_mc_delete(bond->curr_active_slave->dev, addr, alen, 0);
@@ -888,13 +1299,14 @@ static int bond_mc_list_copy(struct dev_
  */
 static void bond_mc_list_flush(struct net_device *bond_dev, struct net_device *slave_dev)
 {
+	struct bonding *bond = bond_dev->priv;
 	struct dev_mc_list *dmi;
 
 	for (dmi = bond_dev->mc_list; dmi; dmi = dmi->next) {
 		dev_mc_delete(slave_dev, dmi->dmi_addr, dmi->dmi_addrlen, 0);
 	}
 
-	if (bond_mode == BOND_MODE_8023AD) {
+	if (bond->params.mode == BOND_MODE_8023AD) {
 		/* del lacpdu mc addr from mc list */
 		u8 lacpdu_multicast[ETH_ALEN] = MULTICAST_LACPDU_ADDR;
 
@@ -913,7 +1325,7 @@ static void bond_mc_swap(struct bonding 
 {
 	struct dev_mc_list *dmi;
 
-	if (!USES_PRIMARY(bond_mode)) {
+	if (!USES_PRIMARY(bond->params.mode)) {
 		/* nothing to do -  mc list is already up-to-date on
 		 * all slaves
 		 */
@@ -959,7 +1371,7 @@ static struct slave *bond_find_best_slav
 {
 	struct slave *new_active, *old_active;
 	struct slave *bestslave = NULL;
-	int mintime;
+	int mintime = bond->params.updelay;
 	int i;
 
 	new_active = old_active = bond->curr_active_slave;
@@ -972,15 +1384,13 @@ static struct slave *bond_find_best_slav
 		}
 	}
 
-	mintime = updelay;
-
 	/* first try the primary link; if arping, a link must tx/rx traffic
 	 * before it can be considered the curr_active_slave - also, we would skip
 	 * slaves between the curr_active_slave and primary_slave that may be up
 	 * and able to arp
 	 */
 	if ((bond->primary_slave) &&
-	    (!arp_interval) &&
+	    (!bond->params.arp_interval) &&
 	    (IS_UP(bond->primary_slave->dev))) {
 		new_active = bond->primary_slave;
 	}
@@ -1030,28 +1440,28 @@ static void bond_change_active_slave(str
 
 	if (new_active) {
 		if (new_active->link == BOND_LINK_BACK) {
-			if (USES_PRIMARY(bond_mode)) {
+			if (USES_PRIMARY(bond->params.mode)) {
 				printk(KERN_INFO DRV_NAME
 				       ": %s: making interface %s the new "
 				       "active one %d ms earlier.\n",
 				       bond->dev->name, new_active->dev->name,
-				       (updelay - new_active->delay) * miimon);
+				       (bond->params.updelay - new_active->delay) * bond->params.miimon);
 			}
 
 			new_active->delay = 0;
 			new_active->link = BOND_LINK_UP;
 			new_active->jiffies = jiffies;
 
-			if (bond_mode == BOND_MODE_8023AD) {
+			if (bond->params.mode == BOND_MODE_8023AD) {
 				bond_3ad_handle_link_change(new_active, BOND_LINK_UP);
 			}
 
-			if ((bond_mode == BOND_MODE_TLB) ||
-			    (bond_mode == BOND_MODE_ALB)) {
+			if ((bond->params.mode == BOND_MODE_TLB) ||
+			    (bond->params.mode == BOND_MODE_ALB)) {
 				bond_alb_handle_link_change(bond, new_active, BOND_LINK_UP);
 			}
 		} else {
-			if (USES_PRIMARY(bond_mode)) {
+			if (USES_PRIMARY(bond->params.mode)) {
 				printk(KERN_INFO DRV_NAME
 				       ": %s: making interface %s the new "
 				       "active one.\n",
@@ -1060,7 +1470,7 @@ static void bond_change_active_slave(str
 		}
 	}
 
-	if (bond_mode == BOND_MODE_ACTIVEBACKUP) {
+	if (bond->params.mode == BOND_MODE_ACTIVEBACKUP) {
 		if (old_active) {
 			bond_set_slave_inactive_flags(old_active);
 		}
@@ -1070,12 +1480,12 @@ static void bond_change_active_slave(str
 		}
 	}
 
-	if (USES_PRIMARY(bond_mode)) {
+	if (USES_PRIMARY(bond->params.mode)) {
 		bond_mc_swap(bond, new_active, old_active);
 	}
 
-	if ((bond_mode == BOND_MODE_TLB) ||
-	    (bond_mode == BOND_MODE_ALB)) {
+	if ((bond->params.mode == BOND_MODE_TLB) ||
+	    (bond->params.mode == BOND_MODE_ALB)) {
 		bond_alb_handle_active_change(bond, new_active);
 	} else {
 		bond->curr_active_slave = new_active;
@@ -1178,6 +1588,7 @@ static int bond_enslave(struct net_devic
 	struct dev_mc_list *dmi;
 	struct sockaddr addr;
 	int link_reporting;
+	int old_features = bond_dev->features;
 	int res = 0;
 
 	if (slave_dev->do_ioctl == NULL) {
@@ -1198,6 +1609,36 @@ static int bond_enslave(struct net_devic
 		return -EBUSY;
 	}
 
+	/* vlan challenged mutual exclusion */
+	/* no need to lock since we're protected by rtnl_lock */
+	if (slave_dev->features & NETIF_F_VLAN_CHALLENGED) {
+		dprintk("%s: NETIF_F_VLAN_CHALLENGED\n", slave_dev->name);
+		if (!list_empty(&bond->vlan_list)) {
+			printk(KERN_ERR DRV_NAME
+			       ": Error: cannot enslave VLAN "
+			       "challenged slave %s on VLAN enabled "
+			       "bond %s\n", slave_dev->name,
+			       bond_dev->name);
+			return -EPERM;
+		} else {
+			printk(KERN_WARNING DRV_NAME
+			       ": Warning: enslaved VLAN challenged "
+			       "slave %s. Adding VLANs will be blocked as "
+			       "long as %s is part of bond %s\n",
+			       slave_dev->name, slave_dev->name,
+			       bond_dev->name);
+			bond_dev->features |= NETIF_F_VLAN_CHALLENGED;
+		}
+	} else {
+		dprintk("%s: ! NETIF_F_VLAN_CHALLENGED\n", slave_dev->name);
+		if (bond->slave_cnt == 0) {
+			/* First slave, and it is not VLAN challenged,
+			 * so remove the block of adding VLANs over the bond.
+			 */
+			bond_dev->features &= ~NETIF_F_VLAN_CHALLENGED;
+		}
+	}
+
 	if (app_abi_ver >= 1) {
 		/* The application is using an ABI, which requires the
 		 * slave interface to be closed.
@@ -1206,7 +1647,8 @@ static int bond_enslave(struct net_devic
 			printk(KERN_ERR DRV_NAME
 			       ": Error: %s is up\n",
 			       slave_dev->name);
-			return -EPERM;
+			res = -EPERM;
+			goto err_undo_flags;
 		}
 
 		if (slave_dev->set_mac_address == NULL) {
@@ -1217,7 +1659,8 @@ static int bond_enslave(struct net_devic
 			       "Your kernel likely does not support slave "
 			       "devices.\n");
 
-			return -EOPNOTSUPP;
+			res = -EOPNOTSUPP;
+			goto err_undo_flags;
 		}
 	} else {
 		/* The application is not using an ABI, which requires the
@@ -1227,23 +1670,26 @@ static int bond_enslave(struct net_devic
 			printk(KERN_ERR DRV_NAME
 			       ": Error: %s is not running\n",
 			       slave_dev->name);
-			return -EINVAL;
+			res = -EINVAL;
+			goto err_undo_flags;
 		}
 
-		if ((bond_mode == BOND_MODE_8023AD) ||
-		    (bond_mode == BOND_MODE_TLB)    ||
-		    (bond_mode == BOND_MODE_ALB)) {
+		if ((bond->params.mode == BOND_MODE_8023AD) ||
+		    (bond->params.mode == BOND_MODE_TLB)    ||
+		    (bond->params.mode == BOND_MODE_ALB)) {
 			printk(KERN_ERR DRV_NAME
 			       ": Error: to use %s mode, you must upgrade "
 			       "ifenslave.\n",
-			       bond_mode_name());
-			return -EOPNOTSUPP;
+			       bond_mode_name(bond->params.mode));
+			res = -EOPNOTSUPP;
+			goto err_undo_flags;
 		}
 	}
 
 	new_slave = kmalloc(sizeof(struct slave), GFP_KERNEL);
 	if (!new_slave) {
-		return -ENOMEM;
+		res = -ENOMEM;
+		goto err_undo_flags;
 	}
 
 	memset(new_slave, 0, sizeof(struct slave));
@@ -1292,8 +1738,8 @@ static int bond_enslave(struct net_devic
 
 	new_slave->dev = slave_dev;
 
-	if ((bond_mode == BOND_MODE_TLB) ||
-	    (bond_mode == BOND_MODE_ALB)) {
+	if ((bond->params.mode == BOND_MODE_TLB) ||
+	    (bond->params.mode == BOND_MODE_ALB)) {
 		/* bond_alb_init_slave() must be called before all other stages since
 		 * it might fail and we do not want to have to undo everything
 		 */
@@ -1308,7 +1754,7 @@ static int bond_enslave(struct net_devic
 	 * curr_active_slave, and that is taken care of later when calling
 	 * bond_change_active()
 	 */
-	if (!USES_PRIMARY(bond_mode)) {
+	if (!USES_PRIMARY(bond->params.mode)) {
 		/* set promiscuity level to new slave */
 		if (bond_dev->flags & IFF_PROMISC) {
 			dev_set_promiscuity(slave_dev, 1);
@@ -1325,13 +1771,15 @@ static int bond_enslave(struct net_devic
 		}
 	}
 
-	if (bond_mode == BOND_MODE_8023AD) {
+	if (bond->params.mode == BOND_MODE_8023AD) {
 		/* add lacpdu mc addr to mc list */
 		u8 lacpdu_multicast[ETH_ALEN] = MULTICAST_LACPDU_ADDR;
 
 		dev_mc_add(slave_dev, lacpdu_multicast, ETH_ALEN, 0);
 	}
 
+	bond_add_vlans_on_slave(bond, slave_dev);
+
 	write_lock_bh(&bond->lock);
 
 	bond_attach_slave(bond, new_slave);
@@ -1339,10 +1787,10 @@ static int bond_enslave(struct net_devic
 	new_slave->delay = 0;
 	new_slave->link_failure_count = 0;
 
-	if (miimon && !use_carrier) {
-		link_reporting = bond_check_dev_link(slave_dev, 1);
+	if (bond->params.miimon && !bond->params.use_carrier) {
+		link_reporting = bond_check_dev_link(bond, slave_dev, 1);
 
-		if ((link_reporting == -1) && !arp_interval) {
+		if ((link_reporting == -1) && !bond->params.arp_interval) {
 			/*
 			 * miimon is set but a bonded network driver
 			 * does not support ETHTOOL/MII and
@@ -1372,13 +1820,13 @@ static int bond_enslave(struct net_devic
 	}
 
 	/* check for initial state */
-	if (!miimon ||
-	    (bond_check_dev_link(slave_dev, 0) == BMSR_LSTATUS)) {
-		if (updelay) {
+	if (!bond->params.miimon ||
+	    (bond_check_dev_link(bond, slave_dev, 0) == BMSR_LSTATUS)) {
+		if (bond->params.updelay) {
 			dprintk("Initial state of slave_dev is "
 				"BOND_LINK_BACK\n");
 			new_slave->link  = BOND_LINK_BACK;
-			new_slave->delay = updelay;
+			new_slave->delay = bond->params.updelay;
 		} else {
 			dprintk("Initial state of slave_dev is "
 				"BOND_LINK_UP\n");
@@ -1398,7 +1846,7 @@ static int bond_enslave(struct net_devic
 		       "forced to 100Mbps, duplex forced to Full.\n",
 		       new_slave->dev->name);
 
-		if (bond_mode == BOND_MODE_8023AD) {
+		if (bond->params.mode == BOND_MODE_8023AD) {
 			printk(KERN_WARNING
 			       "Operation of 802.3ad mode requires ETHTOOL "
 			       "support in base driver for proper aggregator "
@@ -1406,14 +1854,14 @@ static int bond_enslave(struct net_devic
 		}
 	}
 
-	if (USES_PRIMARY(bond_mode) && primary) {
+	if (USES_PRIMARY(bond->params.mode) && bond->params.primary[0]) {
 		/* if there is a primary slave, remember it */
-		if (strcmp(primary, new_slave->dev->name) == 0) {
+		if (strcmp(bond->params.primary, new_slave->dev->name) == 0) {
 			bond->primary_slave = new_slave;
 		}
 	}
 
-	switch (bond_mode) {
+	switch (bond->params.mode) {
 	case BOND_MODE_ACTIVEBACKUP:
 		/* if we're in active-backup mode, we need one and only one active
 		 * interface. The backup interfaces will have their NOARP flag set
@@ -1447,7 +1895,7 @@ static int bond_enslave(struct net_devic
 			 * can be called only after the mac address of the bond is set
 			 */
 			bond_3ad_initialize(bond, 1000/AD_TIMER_INTERVAL,
-					    lacp_fast);
+					    bond->params.lacp_fast);
 		} else {
 			SLAVE_AD_INFO(new_slave).id =
 				SLAVE_AD_INFO(new_slave->prev).id + 1;
@@ -1540,6 +1988,10 @@ err_restore_mac:
 
 err_free:
 	kfree(new_slave);
+
+err_undo_flags:
+	bond_dev->features = old_features;
+
 	return res;
 }
 
@@ -1557,7 +2009,7 @@ err_free:
 static int bond_release(struct net_device *bond_dev, struct net_device *slave_dev)
 {
 	struct bonding *bond = bond_dev->priv;
-	struct slave *slave;
+	struct slave *slave, *oldcurrent;
 	struct sockaddr addr;
 	int mac_addr_differ;
 
@@ -1603,7 +2055,7 @@ static int bond_release(struct net_devic
 	}
 
 	/* Inform AD package of unbinding of slave. */
-	if (bond_mode == BOND_MODE_8023AD) {
+	if (bond->params.mode == BOND_MODE_8023AD) {
 		/* must be called before the slave is
 		 * detached from the list
 		 */
@@ -1617,6 +2069,8 @@ static int bond_release(struct net_devic
 	       ? "active" : "backup",
 	       slave_dev->name);
 
+	oldcurrent = bond->curr_active_slave;
+
 	bond->current_arp_slave = NULL;
 
 	/* release the slave from its bond */
@@ -1626,34 +2080,67 @@ static int bond_release(struct net_devic
 		bond->primary_slave = NULL;
 	}
 
-	if (bond->curr_active_slave == slave) {
+	if (oldcurrent == slave) {
 		bond_change_active_slave(bond, NULL);
-		bond_select_active_slave(bond);
-	}
-
-	if (!bond->curr_active_slave) {
-		printk(KERN_INFO DRV_NAME
-		       ": %s: now running without any active "
-		       "interface !\n",
-		       bond_dev->name);
 	}
 
-	if ((bond_mode == BOND_MODE_TLB) ||
-	    (bond_mode == BOND_MODE_ALB)) {
-		/* must be called only after the slave has been
+	if ((bond->params.mode == BOND_MODE_TLB) ||
+	    (bond->params.mode == BOND_MODE_ALB)) {
+		/* Must be called only after the slave has been
 		 * detached from the list and the curr_active_slave
-		 * has been replaced (if our_slave == old_current)
+		 * has been cleared (if our_slave == old_current),
+		 * but before a new active slave is selected.
 		 */
 		bond_alb_deinit_slave(bond, slave);
 	}
 
+	if (oldcurrent == slave) {
+		bond_select_active_slave(bond);
+
+		if (!bond->curr_active_slave) {
+			printk(KERN_INFO DRV_NAME
+			       ": %s: now running without any active "
+			       "interface !\n",
+			       bond_dev->name);
+		}
+	}
+
+	if (bond->slave_cnt == 0) {
+		/* if the last slave was removed, zero the mac address
+		 * of the master so it will be set by the application
+		 * to the mac address of the first slave
+		 */
+		memset(bond_dev->dev_addr, 0, bond_dev->addr_len);
+
+		if (list_empty(&bond->vlan_list)) {
+			bond_dev->features |= NETIF_F_VLAN_CHALLENGED;
+		} else {
+			printk(KERN_WARNING DRV_NAME
+			       ": Warning: clearing HW address of %s while it "
+			       "still has VLANs.\n",
+			       bond_dev->name);
+			printk(KERN_WARNING DRV_NAME
+			       ": When re-adding slaves, make sure the bond's "
+			       "HW address matches its VLANs'.\n");
+		}
+	} else if ((bond_dev->features & NETIF_F_VLAN_CHALLENGED) &&
+		   !bond_has_challenged_slaves(bond)) {
+		printk(KERN_INFO DRV_NAME
+		       ": last VLAN challenged slave %s "
+		       "left bond %s. VLAN blocking is removed\n",
+		       slave_dev->name, bond_dev->name);
+		bond_dev->features &= ~NETIF_F_VLAN_CHALLENGED;
+	}
+
 	write_unlock_bh(&bond->lock);
 
+	bond_del_vlans_from_slave(bond, slave_dev);
+
 	/* If the mode USES_PRIMARY, then we should only remove its
 	 * promisc and mc settings if it was the curr_active_slave, but that was
 	 * already taken care of above when we detached the slave
 	 */
-	if (!USES_PRIMARY(bond_mode)) {
+	if (!USES_PRIMARY(bond->params.mode)) {
 		/* unset promiscuity level from slave */
 		if (bond_dev->flags & IFF_PROMISC) {
 			dev_set_promiscuity(slave_dev, -1);
@@ -1690,14 +2177,6 @@ static int bond_release(struct net_devic
 
 	kfree(slave);
 
-	/* if the last slave was removed, zero the mac address
-	 * of the master so it will be set by the application
-	 * to the mac address of the first slave
-	 */
-	if (bond->slave_cnt == 0) {
-		memset(bond_dev->dev_addr, 0, bond_dev->addr_len);
-	}
-
 	return 0;  /* deletion OK */
 }
 
@@ -1725,15 +2204,15 @@ static int bond_release_all(struct net_d
 		/* Inform AD package of unbinding of slave
 		 * before slave is detached from the list.
 		 */
-		if (bond_mode == BOND_MODE_8023AD) {
+		if (bond->params.mode == BOND_MODE_8023AD) {
 			bond_3ad_unbind_slave(slave);
 		}
 
 		slave_dev = slave->dev;
 		bond_detach_slave(bond, slave);
 
-		if ((bond_mode == BOND_MODE_TLB) ||
-		    (bond_mode == BOND_MODE_ALB)) {
+		if ((bond->params.mode == BOND_MODE_TLB) ||
+		    (bond->params.mode == BOND_MODE_ALB)) {
 			/* must be called only after the slave
 			 * has been detached from the list
 			 */
@@ -1746,11 +2225,13 @@ static int bond_release_all(struct net_d
 		 */
 		write_unlock_bh(&bond->lock);
 
+		bond_del_vlans_from_slave(bond, slave_dev);
+
 		/* If the mode USES_PRIMARY, then we should only remove its
 		 * promisc and mc settings if it was the curr_active_slave, but that was
 		 * already taken care of above when we detached the slave
 		 */
-		if (!USES_PRIMARY(bond_mode)) {
+		if (!USES_PRIMARY(bond->params.mode)) {
 			/* unset promiscuity level from slave */
 			if (bond_dev->flags & IFF_PROMISC) {
 				dev_set_promiscuity(slave_dev, -1);
@@ -1796,6 +2277,18 @@ static int bond_release_all(struct net_d
 	 */
 	memset(bond_dev->dev_addr, 0, bond_dev->addr_len);
 
+	if (list_empty(&bond->vlan_list)) {
+		bond_dev->features |= NETIF_F_VLAN_CHALLENGED;
+	} else {
+		printk(KERN_WARNING DRV_NAME
+		       ": Warning: clearing HW address of %s while it "
+		       "still has VLANs.\n",
+		       bond_dev->name);
+		printk(KERN_WARNING DRV_NAME
+		       ": When re-adding slaves, make sure the bond's "
+		       "HW address matches its VLANs'.\n");
+	}
+
 	printk(KERN_INFO DRV_NAME
 	       ": %s: released all slaves\n",
 	       bond_dev->name);
@@ -1824,6 +2317,10 @@ static int bond_ioctl_change_active(stru
 	struct slave *new_active = NULL;
 	int res = 0;
 
+	if (!USES_PRIMARY(bond->params.mode)) {
+		return -EINVAL;
+	}
+
 	/* Verify that master_dev is indeed the master of slave_dev */
 	if (!(slave_dev->flags & IFF_SLAVE) ||
 	    (slave_dev->master != bond_dev)) {
@@ -1912,8 +2409,8 @@ static int bond_info_query(struct net_de
 {
 	struct bonding *bond = bond_dev->priv;
 
-	info->bond_mode = bond_mode;
-	info->miimon = miimon;
+	info->bond_mode = bond->params.mode;
+	info->miimon = bond->params.miimon;
 
 	read_lock_bh(&bond->lock);
 	info->num_slaves = bond->slave_cnt;
@@ -1963,11 +2460,13 @@ static void bond_mii_monitor(struct net_
 	struct bonding *bond = bond_dev->priv;
 	struct slave *slave, *oldcurrent;
 	int do_failover = 0;
-	int delta_in_ticks = (miimon * HZ) / 1000;
+	int delta_in_ticks;
 	int i;
 
 	read_lock(&bond->lock);
 
+	delta_in_ticks = (bond->params.miimon * HZ) / 1000;
+
 	if (bond->kill_timers) {
 		goto out;
 	}
@@ -1992,7 +2491,7 @@ static void bond_mii_monitor(struct net_
 		u16 old_speed = slave->speed;
 		u8 old_duplex = slave->duplex;
 
-		link_state = bond_check_dev_link(slave_dev, 0);
+		link_state = bond_check_dev_link(bond, slave_dev, 0);
 
 		switch (slave->link) {
 		case BOND_LINK_UP:	/* the link was up */
@@ -2001,26 +2500,26 @@ static void bond_mii_monitor(struct net_
 				break;
 			} else { /* link going down */
 				slave->link  = BOND_LINK_FAIL;
-				slave->delay = downdelay;
+				slave->delay = bond->params.downdelay;
 
 				if (slave->link_failure_count < UINT_MAX) {
 					slave->link_failure_count++;
 				}
 
-				if (downdelay) {
+				if (bond->params.downdelay) {
 					printk(KERN_INFO DRV_NAME
 					       ": %s: link status down for %s "
 					       "interface %s, disabling it in "
 					       "%d ms.\n",
 					       bond_dev->name,
 					       IS_UP(slave_dev)
-					       ? ((bond_mode == BOND_MODE_ACTIVEBACKUP)
+					       ? ((bond->params.mode == BOND_MODE_ACTIVEBACKUP)
 						  ? ((slave == oldcurrent)
 						     ? "active " : "backup ")
 						  : "")
 					       : "idle ",
 					       slave_dev->name,
-					       downdelay * miimon);
+					       bond->params.downdelay * bond->params.miimon);
 				}
 			}
 			/* no break ! fall through the BOND_LINK_FAIL test to
@@ -2036,8 +2535,8 @@ static void bond_mii_monitor(struct net_
 					/* in active/backup mode, we must
 					 * completely disable this interface
 					 */
-					if ((bond_mode == BOND_MODE_ACTIVEBACKUP) ||
-					    (bond_mode == BOND_MODE_8023AD)) {
+					if ((bond->params.mode == BOND_MODE_ACTIVEBACKUP) ||
+					    (bond->params.mode == BOND_MODE_8023AD)) {
 						bond_set_slave_inactive_flags(slave);
 					}
 
@@ -2049,12 +2548,12 @@ static void bond_mii_monitor(struct net_
 					       slave_dev->name);
 
 					/* notify ad that the link status has changed */
-					if (bond_mode == BOND_MODE_8023AD) {
+					if (bond->params.mode == BOND_MODE_8023AD) {
 						bond_3ad_handle_link_change(slave, BOND_LINK_DOWN);
 					}
 
-					if ((bond_mode == BOND_MODE_TLB) ||
-					    (bond_mode == BOND_MODE_ALB)) {
+					if ((bond->params.mode == BOND_MODE_TLB) ||
+					    (bond->params.mode == BOND_MODE_ALB)) {
 						bond_alb_handle_link_change(bond, slave, BOND_LINK_DOWN);
 					}
 
@@ -2072,7 +2571,7 @@ static void bond_mii_monitor(struct net_
 				       ": %s: link status up again after %d "
 				       "ms for interface %s.\n",
 				       bond_dev->name,
-				       (downdelay - slave->delay) * miimon,
+				       (bond->params.downdelay - slave->delay) * bond->params.miimon,
 				       slave_dev->name);
 			}
 			break;
@@ -2082,9 +2581,9 @@ static void bond_mii_monitor(struct net_
 				break;
 			} else {	/* link going up */
 				slave->link  = BOND_LINK_BACK;
-				slave->delay = updelay;
+				slave->delay = bond->params.updelay;
 
-				if (updelay) {
+				if (bond->params.updelay) {
 					/* if updelay == 0, no need to
 					   advertise about a 0 ms delay */
 					printk(KERN_INFO DRV_NAME
@@ -2093,7 +2592,7 @@ static void bond_mii_monitor(struct net_
 					       "in %d ms.\n",
 					       bond_dev->name,
 					       slave_dev->name,
-					       updelay * miimon);
+					       bond->params.updelay * bond->params.miimon);
 				}
 			}
 			/* no break ! fall through the BOND_LINK_BACK state in
@@ -2108,7 +2607,7 @@ static void bond_mii_monitor(struct net_
 				       ": %s: link status down again after %d "
 				       "ms for interface %s.\n",
 				       bond_dev->name,
-				       (updelay - slave->delay) * miimon,
+				       (bond->params.updelay - slave->delay) * bond->params.miimon,
 				       slave_dev->name);
 			} else {
 				/* link stays up */
@@ -2117,10 +2616,10 @@ static void bond_mii_monitor(struct net_
 					slave->link = BOND_LINK_UP;
 					slave->jiffies = jiffies;
 
-					if (bond_mode == BOND_MODE_8023AD) {
+					if (bond->params.mode == BOND_MODE_8023AD) {
 						/* prevent it from being the active one */
 						slave->state = BOND_STATE_BACKUP;
-					} else if (bond_mode != BOND_MODE_ACTIVEBACKUP) {
+					} else if (bond->params.mode != BOND_MODE_ACTIVEBACKUP) {
 						/* make it immediately active */
 						slave->state = BOND_STATE_ACTIVE;
 					} else if (slave != bond->primary_slave) {
@@ -2135,12 +2634,12 @@ static void bond_mii_monitor(struct net_
 					       slave_dev->name);
 
 					/* notify ad that the link status has changed */
-					if (bond_mode == BOND_MODE_8023AD) {
+					if (bond->params.mode == BOND_MODE_8023AD) {
 						bond_3ad_handle_link_change(slave, BOND_LINK_UP);
 					}
 
-					if ((bond_mode == BOND_MODE_TLB) ||
-					    (bond_mode == BOND_MODE_ALB)) {
+					if ((bond->params.mode == BOND_MODE_TLB) ||
+					    (bond->params.mode == BOND_MODE_ALB)) {
 						bond_alb_handle_link_change(bond, slave, BOND_LINK_UP);
 					}
 
@@ -2162,7 +2661,7 @@ static void bond_mii_monitor(struct net_
 
 		bond_update_speed_duplex(slave);
 
-		if (bond_mode == BOND_MODE_8023AD) {
+		if (bond->params.mode == BOND_MODE_8023AD) {
 			if (old_speed != slave->speed) {
 				bond_3ad_adapter_speed_changed(slave);
 			}
@@ -2190,17 +2689,20 @@ static void bond_mii_monitor(struct net_
 	}
 
 re_arm:
-	mod_timer(&bond->mii_timer, jiffies + delta_in_ticks);
+	if (bond->params.miimon) {
+		mod_timer(&bond->mii_timer, jiffies + delta_in_ticks);
+	}
 out:
 	read_unlock(&bond->lock);
 }
 
-static void bond_arp_send_all(struct slave *slave)
+static void bond_arp_send_all(struct bonding *bond, struct slave *slave)
 {
 	int i;
+	u32 *targets = bond->params.arp_targets;
 
-	for (i = 0; (i<MAX_ARP_IP_TARGETS) && arp_target[i]; i++) {
-		arp_send(ARPOP_REQUEST, ETH_P_ARP, arp_target[i], slave->dev,
+	for (i = 0; (i < BOND_MAX_ARP_TARGETS) && targets[i]; i++) {
+		arp_send(ARPOP_REQUEST, ETH_P_ARP, targets[i], slave->dev,
 			 my_ip, NULL, slave->dev->dev_addr,
 			 NULL);
 	}
@@ -2218,11 +2720,13 @@ static void bond_loadbalance_arp_mon(str
 	struct bonding *bond = bond_dev->priv;
 	struct slave *slave, *oldcurrent;
 	int do_failover = 0;
-	int delta_in_ticks = (arp_interval * HZ) / 1000;
+	int delta_in_ticks;
 	int i;
 
 	read_lock(&bond->lock);
 
+	delta_in_ticks = (bond->params.arp_interval * HZ) / 1000;
+
 	if (bond->kill_timers) {
 		goto out;
 	}
@@ -2307,7 +2811,7 @@ static void bond_loadbalance_arp_mon(str
 		 * to be unstable during low/no traffic periods
 		 */
 		if (IS_UP(slave->dev)) {
-			bond_arp_send_all(slave);
+			bond_arp_send_all(bond, slave);
 		}
 	}
 
@@ -2327,7 +2831,9 @@ static void bond_loadbalance_arp_mon(str
 	}
 
 re_arm:
-	mod_timer(&bond->arp_timer, jiffies + delta_in_ticks);
+	if (bond->params.arp_interval) {
+		mod_timer(&bond->arp_timer, jiffies + delta_in_ticks);
+	}
 out:
 	read_unlock(&bond->lock);
 }
@@ -2351,11 +2857,13 @@ static void bond_activebackup_arp_mon(st
 {
 	struct bonding *bond = bond_dev->priv;
 	struct slave *slave;
-	int delta_in_ticks = (arp_interval * HZ) / 1000;
+	int delta_in_ticks;
 	int i;
 
 	read_lock(&bond->lock);
 
+	delta_in_ticks = (bond->params.arp_interval * HZ) / 1000;
+
 	if (bond->kill_timers) {
 		goto out;
 	}
@@ -2514,7 +3022,7 @@ static void bond_activebackup_arp_mon(st
 		 * rx traffic
 		 */
 		if (slave && my_ip) {
-			bond_arp_send_all(slave);
+			bond_arp_send_all(bond, slave);
 		}
 	}
 
@@ -2535,7 +3043,7 @@ static void bond_activebackup_arp_mon(st
 				if (IS_UP(slave->dev)) {
 					slave->link = BOND_LINK_BACK;
 					bond_set_slave_active_flags(slave);
-					bond_arp_send_all(slave);
+					bond_arp_send_all(bond, slave);
 					slave->jiffies = jiffies;
 					bond->current_arp_slave = slave;
 					break;
@@ -2567,7 +3075,9 @@ static void bond_activebackup_arp_mon(st
 	}
 
 re_arm:
-	mod_timer(&bond->arp_timer, jiffies + delta_in_ticks);
+	if (bond->params.arp_interval) {
+		mod_timer(&bond->arp_timer, jiffies + delta_in_ticks);
+	}
 out:
 	read_unlock(&bond->lock);
 }
@@ -2625,33 +3135,40 @@ static void bond_info_seq_stop(struct se
 	read_unlock(&dev_base_lock);
 }
 
-static void bond_info_show_master(struct seq_file *seq, struct bonding *bond)
+static void bond_info_show_master(struct seq_file *seq)
 {
+	struct bonding *bond = seq->private;
 	struct slave *curr;
 
 	read_lock(&bond->curr_slave_lock);
 	curr = bond->curr_active_slave;
 	read_unlock(&bond->curr_slave_lock);
 
-	seq_printf(seq, "Bonding Mode: %s\n", bond_mode_name());
+	seq_printf(seq, "Bonding Mode: %s\n",
+		   bond_mode_name(bond->params.mode));
 
-	if (USES_PRIMARY(bond_mode)) {
-		if (curr) {
-			seq_printf(seq,
-				   "Currently Active Slave: %s\n",
-				   curr->dev->name);
-		}
+	if (USES_PRIMARY(bond->params.mode)) {
+		seq_printf(seq, "Primary Slave: %s\n",
+			   (bond->params.primary[0]) ?
+			   	bond->params.primary : "None");
+
+		seq_printf(seq, "Currently Active Slave: %s\n",
+			   (curr) ? curr->dev->name : "None");
 	}
 
 	seq_printf(seq, "MII Status: %s\n", (curr) ? "up" : "down");
-	seq_printf(seq, "MII Polling Interval (ms): %d\n", miimon);
-	seq_printf(seq, "Up Delay (ms): %d\n", updelay * miimon);
-	seq_printf(seq, "Down Delay (ms): %d\n", downdelay * miimon);
+	seq_printf(seq, "MII Polling Interval (ms): %d\n", bond->params.miimon);
+	seq_printf(seq, "Up Delay (ms): %d\n",
+		   bond->params.updelay * bond->params.miimon);
+	seq_printf(seq, "Down Delay (ms): %d\n",
+		   bond->params.downdelay * bond->params.miimon);
 
-	if (bond_mode == BOND_MODE_8023AD) {
+	if (bond->params.mode == BOND_MODE_8023AD) {
 		struct ad_info ad_info;
 
 		seq_puts(seq, "\n802.3ad info\n");
+		seq_printf(seq, "LACP rate: %s\n",
+			   (bond->params.lacp_fast) ? "fast" : "slow");
 
 		if (bond_3ad_get_active_agg_info(bond, &ad_info)) {
 			seq_printf(seq, "bond %s has no active aggregator\n",
@@ -2680,6 +3197,8 @@ static void bond_info_show_master(struct
 
 static void bond_info_show_slave(struct seq_file *seq, const struct slave *slave)
 {
+	struct bonding *bond = seq->private;
+
 	seq_printf(seq, "\nSlave Interface: %s\n", slave->dev->name);
 	seq_printf(seq, "MII Status: %s\n",
 		   (slave->link == BOND_LINK_UP) ?  "up" : "down");
@@ -2697,7 +3216,7 @@ static void bond_info_show_slave(struct 
 			   slave->perm_hwaddr[5]);
 	}
 
-	if (bond_mode == BOND_MODE_8023AD) {
+	if (bond->params.mode == BOND_MODE_8023AD) {
 		const struct aggregator *agg
 			= SLAVE_AD_INFO(slave).port.aggregator;
 
@@ -2714,7 +3233,7 @@ static int bond_info_seq_show(struct seq
 {
 	if (v == SEQ_START_TOKEN) {
 		seq_printf(seq, "%s\n", version);
-		bond_info_show_master(seq, seq->private);
+		bond_info_show_master(seq);
 	} else {
 		bond_info_show_slave(seq, v);
 	}
@@ -2989,14 +3508,14 @@ static int bond_open(struct net_device *
 
 	bond->kill_timers = 0;
 
-	if ((bond_mode == BOND_MODE_TLB) ||
-	    (bond_mode == BOND_MODE_ALB)) {
+	if ((bond->params.mode == BOND_MODE_TLB) ||
+	    (bond->params.mode == BOND_MODE_ALB)) {
 		struct timer_list *alb_timer = &(BOND_ALB_INFO(bond).alb_timer);
 
 		/* bond_alb_initialize must be called before the timer
 		 * is started.
 		 */
-		if (bond_alb_initialize(bond, (bond_mode == BOND_MODE_ALB))) {
+		if (bond_alb_initialize(bond, (bond->params.mode == BOND_MODE_ALB))) {
 			/* something went wrong - fail the open operation */
 			return -1;
 		}
@@ -3008,7 +3527,7 @@ static int bond_open(struct net_device *
 		add_timer(alb_timer);
 	}
 
-	if (miimon) {  /* link check interval, in milliseconds. */
+	if (bond->params.miimon) {  /* link check interval, in milliseconds. */
 		init_timer(mii_timer);
 		mii_timer->expires  = jiffies + 1;
 		mii_timer->data     = (unsigned long)bond_dev;
@@ -3016,11 +3535,11 @@ static int bond_open(struct net_device *
 		add_timer(mii_timer);
 	}
 
-	if (arp_interval) {  /* arp interval, in milliseconds. */
+	if (bond->params.arp_interval) {  /* arp interval, in milliseconds. */
 		init_timer(arp_timer);
 		arp_timer->expires  = jiffies + 1;
 		arp_timer->data     = (unsigned long)bond_dev;
-		if (bond_mode == BOND_MODE_ACTIVEBACKUP) {
+		if (bond->params.mode == BOND_MODE_ACTIVEBACKUP) {
 			arp_timer->function = (void *)&bond_activebackup_arp_mon;
 		} else {
 			arp_timer->function = (void *)&bond_loadbalance_arp_mon;
@@ -3028,7 +3547,7 @@ static int bond_open(struct net_device *
 		add_timer(arp_timer);
 	}
 
-	if (bond_mode == BOND_MODE_8023AD) {
+	if (bond->params.mode == BOND_MODE_8023AD) {
 		struct timer_list *ad_timer = &(BOND_AD_INFO(bond).ad_timer);
 		init_timer(ad_timer);
 		ad_timer->expires  = jiffies + 1;
@@ -3051,7 +3570,7 @@ static int bond_close(struct net_device 
 
 	bond_mc_list_destroy(bond);
 
-	if (bond_mode == BOND_MODE_8023AD) {
+	if (bond->params.mode == BOND_MODE_8023AD) {
 		/* Unregister the receive of LACPDUs */
 		bond_unregister_lacpdu(bond);
 	}
@@ -3065,15 +3584,15 @@ static int bond_close(struct net_device 
 	 * because a running timer might be trying to hold it too
 	 */
 
-	if (miimon) {  /* link check interval, in milliseconds. */
+	if (bond->params.miimon) {  /* link check interval, in milliseconds. */
 		del_timer_sync(&bond->mii_timer);
 	}
 
-	if (arp_interval) {  /* arp interval, in milliseconds. */
+	if (bond->params.arp_interval) {  /* arp interval, in milliseconds. */
 		del_timer_sync(&bond->arp_timer);
 	}
 
-	switch (bond_mode) {
+	switch (bond->params.mode) {
 	case BOND_MODE_8023AD:
 		del_timer_sync(&(BOND_AD_INFO(bond).ad_timer));
 		break;
@@ -3088,8 +3607,8 @@ static int bond_close(struct net_device 
 	/* Release the bonded slaves */
 	bond_release_all(bond_dev);
 
-	if ((bond_mode == BOND_MODE_TLB) ||
-	    (bond_mode == BOND_MODE_ALB)) {
+	if ((bond->params.mode == BOND_MODE_TLB) ||
+	    (bond->params.mode == BOND_MODE_ALB)) {
 		/* Must be called only after all
 		 * slaves have been released
 		 */
@@ -3269,11 +3788,7 @@ static int bond_do_ioctl(struct net_devi
 			break;
 		case BOND_CHANGE_ACTIVE_OLD:
 		case SIOCBONDCHANGEACTIVE:
-			if (USES_PRIMARY(bond_mode)) {
-				res = bond_ioctl_change_active(bond_dev, slave_dev);
-			} else {
-				res = -EINVAL;
-			}
+			res = bond_ioctl_change_active(bond_dev, slave_dev);
 			break;
 		default:
 			res = -EOPNOTSUPP;
@@ -3505,11 +4020,12 @@ static int bond_xmit_roundrobin(struct s
 	struct bonding *bond = bond_dev->priv;
 	struct slave *slave, *start_at;
 	int i;
+	int res = 1;
 
 	read_lock(&bond->lock);
 
 	if (!BOND_IS_OK(bond)) {
-		goto free_out;
+		goto out;
 	}
 
 	read_lock(&bond->curr_slave_lock);
@@ -3517,33 +4033,31 @@ static int bond_xmit_roundrobin(struct s
 	read_unlock(&bond->curr_slave_lock);
 
 	if (!slave) {
-		goto free_out;
+		goto out;
 	}
 
 	bond_for_each_slave_from(bond, slave, i, start_at) {
 		if (IS_UP(slave->dev) &&
 		    (slave->link == BOND_LINK_UP) &&
 		    (slave->state == BOND_STATE_ACTIVE)) {
-			skb->dev = slave->dev;
-			skb->priority = 1;
-			dev_queue_xmit(skb);
+			res = bond_dev_queue_xmit(bond, skb, slave->dev);
 
 			write_lock(&bond->curr_slave_lock);
 			bond->curr_active_slave = slave->next;
 			write_unlock(&bond->curr_slave_lock);
 
-			goto out;
+			break;
 		}
 	}
 
+
 out:
+	if (res) {
+		/* no suitable interface, frame not sent */
+		dev_kfree_skb(skb);
+	}
 	read_unlock(&bond->lock);
 	return 0;
-
-free_out:
-	/* no suitable interface, frame not sent */
-	dev_kfree_skb(skb);
-	goto out;
 }
 
 /*
@@ -3553,10 +4067,11 @@ free_out:
 static int bond_xmit_activebackup(struct sk_buff *skb, struct net_device *bond_dev)
 {
 	struct bonding *bond = bond_dev->priv;
+	int res = 1;
 
 	/* if we are sending arp packets, try to at least
 	   identify our own ip address */
-	if (arp_interval && !my_ip &&
+	if (bond->params.arp_interval && !my_ip &&
 		(skb->protocol == __constant_htons(ETH_P_ARP))) {
 		char *the_ip = (char *)skb->data +
 				sizeof(struct ethhdr) +
@@ -3569,26 +4084,21 @@ static int bond_xmit_activebackup(struct
 	read_lock(&bond->curr_slave_lock);
 
 	if (!BOND_IS_OK(bond)) {
-		goto free_out;
+		goto out;
 	}
 
 	if (bond->curr_active_slave) { /* one usable interface */
-		skb->dev = bond->curr_active_slave->dev;
-		skb->priority = 1;
-		dev_queue_xmit(skb);
-		goto out;
-	} else {
-		goto free_out;
+		res = bond_dev_queue_xmit(bond, skb, bond->curr_active_slave->dev);
 	}
+
 out:
+	if (res) {
+		/* no suitable interface, frame not sent */
+		dev_kfree_skb(skb);
+	}
 	read_unlock(&bond->curr_slave_lock);
 	read_unlock(&bond->lock);
 	return 0;
-
-free_out:
-	/* no suitable interface, frame not sent */
-	dev_kfree_skb(skb);
-	goto out;
 }
 
 /*
@@ -3603,11 +4113,12 @@ static int bond_xmit_xor(struct sk_buff 
 	struct slave *slave, *start_at;
 	int slave_no;
 	int i;
+	int res = 1;
 
 	read_lock(&bond->lock);
 
 	if (!BOND_IS_OK(bond)) {
-		goto free_out;
+		goto out;
 	}
 
 	slave_no = (data->h_dest[5]^bond_dev->dev_addr[5]) % bond->slave_cnt;
@@ -3625,22 +4136,18 @@ static int bond_xmit_xor(struct sk_buff 
 		if (IS_UP(slave->dev) &&
 		    (slave->link == BOND_LINK_UP) &&
 		    (slave->state == BOND_STATE_ACTIVE)) {
-			skb->dev = slave->dev;
-			skb->priority = 1;
-			dev_queue_xmit(skb);
-
-			goto out;
+			res = bond_dev_queue_xmit(bond, skb, slave->dev);
+			break;
 		}
 	}
 
 out:
+	if (res) {
+		/* no suitable interface, frame not sent */
+		dev_kfree_skb(skb);
+	}
 	read_unlock(&bond->lock);
 	return 0;
-
-free_out:
-	/* no suitable interface, frame not sent */
-	dev_kfree_skb(skb);
-	goto out;
 }
 
 /*
@@ -3652,11 +4159,12 @@ static int bond_xmit_broadcast(struct sk
 	struct slave *slave, *start_at;
 	struct net_device *tx_dev = NULL;
 	int i;
+	int res = 1;
 
 	read_lock(&bond->lock);
 
 	if (!BOND_IS_OK(bond)) {
-		goto free_out;
+		goto out;
 	}
 
 	read_lock(&bond->curr_slave_lock);
@@ -3664,7 +4172,7 @@ static int bond_xmit_broadcast(struct sk
 	read_unlock(&bond->curr_slave_lock);
 
 	if (!start_at) {
-		goto free_out;
+		goto out;
 	}
 
 	bond_for_each_slave_from(bond, slave, i, start_at) {
@@ -3680,31 +4188,28 @@ static int bond_xmit_broadcast(struct sk
 					continue;
 				}
 
-				skb2->dev = tx_dev;
-				skb2->priority = 1;
-				dev_queue_xmit(skb2);
+				res = bond_dev_queue_xmit(bond, skb2, tx_dev);
+				if (res) {
+					dev_kfree_skb(skb2);
+					continue;
+				}
 			}
 			tx_dev = slave->dev;
 		}
 	}
 
 	if (tx_dev) {
-		skb->dev = tx_dev;
-		skb->priority = 1;
-		dev_queue_xmit(skb);
-	} else {
-		goto free_out;
+		res = bond_dev_queue_xmit(bond, skb, tx_dev);
 	}
 
 out:
+	if (res) {
+		/* no suitable interface, frame not sent */
+		dev_kfree_skb(skb);
+	}
 	/* frame sent to all suitable interfaces */
 	read_unlock(&bond->lock);
 	return 0;
-
-free_out:
-	/* no suitable interface, frame not sent */
-	dev_kfree_skb(skb);
-	goto out;
 }
 
 #ifdef CONFIG_NET_FASTROUTE
@@ -3717,13 +4222,47 @@ static int bond_accept_fastpath(struct n
 /*------------------------- Device initialization ---------------------------*/
 
 /*
+ * set bond mode specific net device operations
+ */
+static inline void bond_set_mode_ops(struct net_device *bond_dev, int mode)
+{
+	switch (mode) {
+	case BOND_MODE_ROUNDROBIN:
+		bond_dev->hard_start_xmit = bond_xmit_roundrobin;
+		break;
+	case BOND_MODE_ACTIVEBACKUP:
+		bond_dev->hard_start_xmit = bond_xmit_activebackup;
+		break;
+	case BOND_MODE_XOR:
+		bond_dev->hard_start_xmit = bond_xmit_xor;
+		break;
+	case BOND_MODE_BROADCAST:
+		bond_dev->hard_start_xmit = bond_xmit_broadcast;
+		break;
+	case BOND_MODE_8023AD:
+		bond_dev->hard_start_xmit = bond_3ad_xmit_xor;
+		break;
+	case BOND_MODE_TLB:
+	case BOND_MODE_ALB:
+		bond_dev->hard_start_xmit = bond_alb_xmit;
+		bond_dev->set_mac_address = bond_alb_set_mac_address;
+		break;
+	default:
+		/* Should never happen, mode already checked */
+		printk(KERN_ERR DRV_NAME
+		       ": Error: Unknown bonding mode %d\n",
+		       mode);
+		break;
+	}
+}
+
+/*
  * Does not allocate but creates a /proc entry.
  * Allowed to fail.
  */
-static int __init bond_init(struct net_device *bond_dev)
+static int __init bond_init(struct net_device *bond_dev, struct bond_params *params)
 {
 	struct bonding *bond = bond_dev->priv;
-	int count;
 
 	dprintk("Begin bond_init for %s\n", bond_dev->name);
 
@@ -3731,12 +4270,15 @@ static int __init bond_init(struct net_d
 	rwlock_init(&bond->lock);
 	rwlock_init(&bond->curr_slave_lock);
 
+	bond->params = *params; /* copy params struct */
+
 	/* Initialize pointers */
 	bond->first_slave = NULL;
 	bond->curr_active_slave = NULL;
 	bond->current_arp_slave = NULL;
 	bond->primary_slave = NULL;
 	bond->dev = bond_dev;
+	INIT_LIST_HEAD(&bond->vlan_list);
 
 	/* Initialize the device entry points */
 	bond_dev->open = bond_open;
@@ -3747,33 +4289,7 @@ static int __init bond_init(struct net_d
 	bond_dev->change_mtu = bond_change_mtu;
 	bond_dev->set_mac_address = bond_set_mac_address;
 
-	switch (bond_mode) {
-	case BOND_MODE_ROUNDROBIN:
-		bond_dev->hard_start_xmit = bond_xmit_roundrobin;
-		break;
-	case BOND_MODE_ACTIVEBACKUP:
-		bond_dev->hard_start_xmit = bond_xmit_activebackup;
-		break;
-	case BOND_MODE_XOR:
-		bond_dev->hard_start_xmit = bond_xmit_xor;
-		break;
-	case BOND_MODE_BROADCAST:
-		bond_dev->hard_start_xmit = bond_xmit_broadcast;
-		break;
-	case BOND_MODE_8023AD:
-		bond_dev->hard_start_xmit = bond_3ad_xmit_xor; /* extern */
-		break;
-	case BOND_MODE_TLB:
-	case BOND_MODE_ALB:
-		bond_dev->hard_start_xmit = bond_alb_xmit; /* extern */
-		bond_dev->set_mac_address = bond_alb_set_mac_address; /* extern */
-		break;
-	default:
-		printk(KERN_ERR DRV_NAME
-		       ": Error: Unknown bonding mode %d\n",
-		       bond_mode);
-		return -EINVAL;
-	}
+	bond_set_mode_ops(bond_dev, bond->params.mode);
 
 	bond_dev->destructor = free_netdev;
 #ifdef CONFIG_NET_FASTROUTE
@@ -3784,27 +4300,25 @@ static int __init bond_init(struct net_d
 	bond_dev->tx_queue_len = 0;
 	bond_dev->flags |= IFF_MASTER|IFF_MULTICAST;
 
-	printk(KERN_INFO DRV_NAME ": %s registered with", bond_dev->name);
-	if (miimon) {
-		printk(" MII link monitoring set to %d ms", miimon);
-		updelay /= miimon;
-		downdelay /= miimon;
-	} else {
-		printk("out MII link monitoring");
-	}
-	printk(", in %s mode.\n", bond_mode_name());
+	/* At first, we block adding VLANs. That's the only way to
+	 * prevent problems that occur when adding VLANs over an
+	 * empty bond. The block will be removed once non-challenged
+	 * slaves are enslaved.
+	 */
+	bond_dev->features |= NETIF_F_VLAN_CHALLENGED;
 
-	printk(KERN_INFO DRV_NAME ": %s registered with", bond_dev->name);
-	if (arp_interval > 0) {
-		printk(" ARP monitoring set to %d ms with %d target(s):",
-		       arp_interval, arp_ip_count);
-		for (count=0 ; count<arp_ip_count ; count++) {
-			printk(" %s", arp_ip_target[count]);
-		}
-		printk("\n");
-	} else {
-		printk("out ARP monitoring\n");
-	}
+	/* By default, we declare the bond to be fully
+	 * VLAN hardware accelerated capable. Special
+	 * care is taken in the various xmit functions
+	 * when there are slaves that are not hw accel
+	 * capable
+	 */
+	bond_dev->vlan_rx_register = bond_vlan_rx_register;
+	bond_dev->vlan_rx_add_vid  = bond_vlan_rx_add_vid;
+	bond_dev->vlan_rx_kill_vid = bond_vlan_rx_kill_vid;
+	bond_dev->features |= (NETIF_F_HW_VLAN_TX |
+			       NETIF_F_HW_VLAN_RX |
+			       NETIF_F_HW_VLAN_FILTER);
 
 #ifdef CONFIG_PROC_FS
 	bond_create_proc_entry(bond);
@@ -3870,7 +4384,7 @@ static inline int bond_parse_parm(char *
 	return -1;
 }
 
-static int bond_check_params(void)
+static int bond_check_params(struct bond_params *params)
 {
 	/*
 	 * Convert string parameters.
@@ -3889,7 +4403,7 @@ static int bond_check_params(void)
 		if (bond_mode != BOND_MODE_8023AD) {
 			printk(KERN_INFO DRV_NAME
 			       ": lacp_rate param is irrelevant in mode %s\n",
-			       bond_mode_name());
+			       bond_mode_name(bond_mode));
 		} else {
 			lacp_fast = bond_parse_parm(lacp_rate, bond_lacp_tbl);
 			if (lacp_fast == -1) {
@@ -3933,17 +4447,17 @@ static int bond_check_params(void)
 		downdelay = 0;
 	}
 
+	if ((use_carrier != 0) && (use_carrier != 1)) {
+		printk(KERN_WARNING DRV_NAME
+		       ": Warning: use_carrier module parameter (%d), "
+		       "not of valid value (0/1), so it was set to 1\n",
+		       use_carrier);
+		use_carrier = 1;
+	}
+
 	/* reset values for 802.3ad */
 	if (bond_mode == BOND_MODE_8023AD) {
-		if (arp_interval) {
-			printk(KERN_WARNING DRV_NAME
-			       ": Warning: ARP monitoring can't be used "
-			       "simultaneously with 802.3ad, disabling ARP "
-			       "monitoring\n");
-			arp_interval = 0;
-		}
-
-		if (miimon) {
+		if (!miimon) {
 			printk(KERN_WARNING DRV_NAME
 			       ": Warning: miimon must be specified, "
 			       "otherwise bonding will not detect link "
@@ -4002,25 +4516,23 @@ static int bond_check_params(void)
 		}
 
 		if ((updelay % miimon) != 0) {
-			/* updelay will be rounded in bond_init() when it
-			 * is divided by miimon, we just inform user here
-			 */
 			printk(KERN_WARNING DRV_NAME
 			       ": Warning: updelay (%d) is not a multiple "
 			       "of miimon (%d), updelay rounded to %d ms\n",
 			       updelay, miimon, (updelay / miimon) * miimon);
 		}
 
+		updelay /= miimon;
+
 		if ((downdelay % miimon) != 0) {
-			/* downdelay will be rounded in bond_init() when it
-			 * is divided by miimon, we just inform user here
-			 */
 			printk(KERN_WARNING DRV_NAME
 			       ": Warning: downdelay (%d) is not a multiple "
 			       "of miimon (%d), downdelay rounded to %d ms\n",
 			       downdelay, miimon,
 			       (downdelay / miimon) * miimon);
 		}
+
+		downdelay /= miimon;
 	}
 
 	if (arp_interval < 0) {
@@ -4032,7 +4544,7 @@ static int bond_check_params(void)
 	}
 
 	for (arp_ip_count = 0;
-	     (arp_ip_count < MAX_ARP_IP_TARGETS) && arp_ip_target[arp_ip_count];
+	     (arp_ip_count < BOND_MAX_ARP_TARGETS) && arp_ip_target[arp_ip_count];
 	     arp_ip_count++) {
 		/* not complete check, but should be good enough to
 		   catch mistakes */
@@ -4058,7 +4570,23 @@ static int bond_check_params(void)
 		arp_interval = 0;
 	}
 
-	if (!miimon && !arp_interval) {
+	if (miimon) {
+		printk(KERN_INFO DRV_NAME
+		       ": MII link monitoring set to %d ms\n",
+		       miimon);
+	} else if (arp_interval) {
+		int i;
+
+		printk(KERN_INFO DRV_NAME
+		       ": ARP monitoring set to %d ms with %d target(s):",
+		       arp_interval, arp_ip_count);
+
+		for (i = 0; i < arp_ip_count; i++)
+			printk (" %s", arp_ip_target[i]);
+
+		printk("\n");
+
+	} else {
 		/* miimon and arp_interval not set, we need one so things
 		 * work as expected, see bonding.txt for details
 		 */
@@ -4076,21 +4604,39 @@ static int bond_check_params(void)
 		printk(KERN_WARNING DRV_NAME
 		       ": Warning: %s primary device specified but has no "
 		       "effect in %s mode\n",
-		       primary, bond_mode_name());
+		       primary, bond_mode_name(bond_mode));
 		primary = NULL;
 	}
 
+	/* fill params struct with the proper values */
+	params->mode = bond_mode;
+	params->miimon = miimon;
+	params->arp_interval = arp_interval;
+	params->updelay = updelay;
+	params->downdelay = downdelay;
+	params->use_carrier = use_carrier;
+	params->lacp_fast = lacp_fast;
+	params->primary[0] = 0;
+
+	if (primary) {
+		strncpy(params->primary, primary, IFNAMSIZ);
+		params->primary[IFNAMSIZ - 1] = 0;
+	}
+
+	memcpy(params->arp_targets, arp_target, sizeof(arp_target));
+
 	return 0;
 }
 
 static int __init bonding_init(void)
 {
+	struct bond_params params;
 	int i;
 	int res;
 
 	printk(KERN_INFO "%s", version);
 
-	res = bond_check_params();
+	res = bond_check_params(&params);
 	if (res) {
 		return res;
 	}
@@ -4120,7 +4666,7 @@ static int __init bonding_init(void)
 		 * /proc files), but before register_netdevice(), because we
 		 * need to set function pointers.
 		 */
-		res = bond_init(bond_dev);
+		res = bond_init(bond_dev, &params);
 		if (res < 0) {
 			free_netdev(bond_dev);
 			goto out_err;
--- diff/drivers/net/bonding/bonding.h	2004-02-18 08:54:10.000000000 +0000
+++ source/drivers/net/bonding/bonding.h	2004-02-23 13:56:43.000000000 +0000
@@ -23,7 +23,7 @@
  * 2003/05/01 - Shmulik Hen <shmulik.hen at intel dot com>
  *	- Added support for Transmit load balancing mode.
  *
- * 2003/09/24 - Shmulik Hen <shmulik.hen at intel dot com>
+ * 2003/12/01 - Shmulik Hen <shmulik.hen at intel dot com>
  *	- Code cleanup and style changes
  */
 
@@ -36,11 +36,13 @@
 #include "bond_3ad.h"
 #include "bond_alb.h"
 
-#define DRV_VERSION	"2.5.0"
-#define DRV_RELDATE	"December 1, 2003"
+#define DRV_VERSION	"2.6.0"
+#define DRV_RELDATE	"January 14, 2004"
 #define DRV_NAME	"bonding"
 #define DRV_DESCRIPTION	"Ethernet Channel Bonding Driver"
 
+#define BOND_MAX_ARP_TARGETS	16
+
 #ifdef BONDING_DEBUG
 #define dprintk(fmt, args...) \
 	printk(KERN_DEBUG     \
@@ -133,6 +135,23 @@
 		bond_for_each_slave_from(bond, pos, cnt, (bond)->first_slave)
 
 
+struct bond_params {
+	int mode;
+	int miimon;
+	int arp_interval;
+	int use_carrier;
+	int updelay;
+	int downdelay;
+	int lacp_fast;
+	char primary[IFNAMSIZ];
+	u32 arp_targets[BOND_MAX_ARP_TARGETS];
+};
+
+struct vlan_entry {
+	struct list_head vlan_list;
+	unsigned short vlan_id;
+};
+
 struct slave {
 	struct net_device *dev; /* first - usefull for panic debug */
 	struct slave *next;
@@ -181,6 +200,9 @@ struct bonding {
 	u16      flags;
 	struct   ad_bond_info ad_info;
 	struct   alb_bond_info alb_info;
+	struct   bond_params params;
+	struct   list_head vlan_list;
+	struct   vlan_group *vlgrp;
 };
 
 /**
@@ -223,5 +245,8 @@ extern inline void bond_set_slave_active
 	slave->dev->flags &= ~IFF_NOARP;
 }
 
+struct vlan_entry *bond_next_vlan(struct bonding *bond, struct vlan_entry *curr);
+int bond_dev_queue_xmit(struct bonding *bond, struct sk_buff *skb, struct net_device *slave_dev);
+
 #endif /* _LINUX_BONDING_H */
 
--- diff/drivers/net/bsd_comp.c	2003-05-21 11:50:15.000000000 +0100
+++ source/drivers/net/bsd_comp.c	2004-02-23 13:56:43.000000000 +0000
@@ -1176,3 +1176,4 @@ void __exit bsdcomp_cleanup(void)
 module_init(bsdcomp_init);
 module_exit(bsdcomp_cleanup);
 MODULE_LICENSE("Dual BSD/GPL");
+MODULE_ALIAS("ppp-compress-" __stringify(CI_BSD_COMPRESS));
--- diff/drivers/net/depca.c	2004-02-18 08:54:10.000000000 +0000
+++ source/drivers/net/depca.c	2004-02-23 13:56:43.000000000 +0000
@@ -1461,7 +1461,7 @@ static int __init depca_mca_probe(struct
  out_unclaim:
 	mca_device_set_claim(mdev, 0);
 
-	return err;;
+	return err;
 }
 #endif
 
@@ -2086,7 +2086,7 @@ static int __init depca_module_init (voi
 {
         int err = 0;
 
-#if CONFIG_MCA
+#ifdef CONFIG_MCA
         err = mca_register_driver (&depca_mca_driver);
 #endif
 #ifdef CONFIG_EISA
@@ -2101,7 +2101,7 @@ static int __init depca_module_init (voi
 static void __exit depca_module_exit (void)
 {
 	int i;
-#if CONFIG_MCA
+#ifdef CONFIG_MCA
         mca_unregister_driver (&depca_mca_driver);
 #endif
 #ifdef CONFIG_EISA
--- diff/drivers/net/dgrs.c	2003-09-30 15:46:15.000000000 +0100
+++ source/drivers/net/dgrs.c	2004-02-23 13:56:43.000000000 +0000
@@ -121,11 +121,22 @@ typedef unsigned int bool;
 #include "dgrs_asstruct.h"
 #include "dgrs_bcomm.h"
 
+#ifdef CONFIG_PCI
 static struct pci_device_id dgrs_pci_tbl[] = {
 	{ SE6_PCI_VENDOR_ID, SE6_PCI_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID, },
 	{ }			/* Terminating entry */
 };
 MODULE_DEVICE_TABLE(pci, dgrs_pci_tbl);
+#endif
+
+#ifdef CONFIG_EISA
+static struct eisa_device_id dgrs_eisa_tbl[] = {
+	{ "DBI0A01" },
+	{ }
+};
+MODULE_DEVICE_TABLE(eisa, dgrs_eisa_tbl);
+#endif
+
 MODULE_LICENSE("GPL");
 
 
@@ -179,11 +190,6 @@ static __u32	dgrs_ipxnet = -1;
 static int	dgrs_nicmode;
 
 /*
- *	Chain of device structures
- */
-static struct net_device *dgrs_root_dev;
-
-/*
  *	Private per-board data structure (dev->priv)
  */
 typedef struct
@@ -191,7 +197,6 @@ typedef struct
 	/*
 	 *	Stuff for generic ethercard I/F
 	 */
-	struct net_device		*next_dev;
 	struct net_device_stats	stats;
 
 	/*
@@ -1187,7 +1192,7 @@ dgrs_probe1(struct net_device *dev)
 	priv->intrcnt = 0;
 	for (i = jiffies + 2*HZ + HZ/2; time_after(i, jiffies); )
 	{
-		barrier();		/* gcc 2.95 needs this */
+		cpu_relax();
 		if (priv->intrcnt >= 2)
 			break;
 	}
@@ -1200,16 +1205,6 @@ dgrs_probe1(struct net_device *dev)
 	}
 
 	/*
-	 *	Register the /proc/ioports information...
-	 */
-	if (!request_region(dev->base_addr, 256, "RightSwitch")) {
-		printk(KERN_ERR "%s: io 0x%3lX, which is busy.\n", dev->name,
-				dev->base_addr);
-		rc = -EBUSY;
-		goto err_free_irq;
-	}
-	
-	/*
 	 *	Entry points...
 	 */
 	dev->open = &dgrs_open;
@@ -1242,22 +1237,23 @@ dgrs_initclone(struct net_device *dev)
 	return (0);
 }
 
-static int __init 
+static struct net_device * __init 
 dgrs_found_device(
 	int		io,
 	ulong		mem,
 	int		irq,
 	ulong		plxreg,
-	ulong		plxdma
+	ulong		plxdma,
+	struct device   *pdev
 )
 {
-	DGRS_PRIV	*priv;
-	struct net_device *dev, *aux;
-	int i, ret;
+	DGRS_PRIV *priv;
+	struct net_device *dev;
+	int i, ret = -ENOMEM;
 
 	dev = alloc_etherdev(sizeof(DGRS_PRIV));
 	if (!dev)
-		return -ENOMEM;
+		goto err0;
 
 	priv = (DGRS_PRIV *)dev->priv;
 
@@ -1272,19 +1268,19 @@ dgrs_found_device(
 	priv->chan = 1;
 	priv->devtbl[0] = dev;
 
-	dev->init = dgrs_probe1;
 	SET_MODULE_OWNER(dev);
-
-	if (register_netdev(dev) != 0) {
-		free_netdev(dev);
-		return -EIO;
-	}
-
-	priv->next_dev = dgrs_root_dev;
-	dgrs_root_dev = dev;
+	SET_NETDEV_DEV(dev, pdev);
+	
+	ret = dgrs_probe1(dev);
+	if (ret) 
+		goto err1;
+
+	ret = register_netdev(dev);
+	if (ret)
+		goto err2;
 
 	if ( !dgrs_nicmode )
-		return (0);	/* Switch mode, we are done */
+		return dev;	/* Switch mode, we are done */
 
 	/*
 	 * Operating card as N separate NICs
@@ -1302,8 +1298,7 @@ dgrs_found_device(
 		if (!devN) 
 			goto fail;
 
-		/* Make it an exact copy of dev[0]... */
-		*devN = *dev;
+		/* Don't copy the network device structure! */
 
 		/* copy the priv structure of dev[0] */
 		privN = (DGRS_PRIV *)devN->priv;
@@ -1316,123 +1311,211 @@ dgrs_found_device(
 		devN->irq = 0;
 			/* ... and base MAC address off address of 1st port */
 		devN->dev_addr[5] += i;
-			/* ... choose a new name */
-		strncpy(devN->name, "eth%d", IFNAMSIZ);
-		devN->init = dgrs_initclone;
+
+		ret = dgrs_initclone(devN);
+		if (ret)
+			goto fail;
+
 		SET_MODULE_OWNER(devN);
+		SET_NETDEV_DEV(dev, pdev);
 
-		ret = -EIO;
-		if (register_netdev(devN)) {
+		ret = register_netdev(devN);
+		if (ret) {
 			free_netdev(devN);
 			goto fail;
 		}
 		privN->chan = i+1;
 		priv->devtbl[i] = devN;
-		privN->next_dev = dgrs_root_dev;
-		dgrs_root_dev = devN;
 	}
-	return 0;
-fail:	aux = priv->next_dev;
-	while (dgrs_root_dev != aux) {
-		struct net_device *d = dgrs_root_dev;
-		
-		dgrs_root_dev = ((DGRS_PRIV *)d->priv)->next_dev;
+	return dev;
+
+ fail:	
+	while (i >= 0) {
+		struct net_device *d = priv->devtbl[i--];
 		unregister_netdev(d);
 		free_netdev(d);
 	}
-	return ret;
+
+ err2:
+	free_irq(dev->irq, dev);
+ err1:
+	free_netdev(dev);
+ err0:
+	return ERR_PTR(ret);
 }
 
-/*
- *	Scan for all boards
- */
-static int is2iv[8] __initdata = { 0, 3, 5, 7, 10, 11, 12, 15 };
+static void __devexit dgrs_remove(struct net_device *dev)
+{
+	DGRS_PRIV *priv = dev->priv;
+	int i;
 
-static int __init  dgrs_scan(void)
+	unregister_netdev(dev);
+
+	for (i = 1; i < priv->nports; ++i) {
+		struct net_device *d = priv->devtbl[i];
+		if (d) {
+			unregister_netdev(d);
+			free_netdev(d);
+		}
+	}
+
+	proc_reset(priv->devtbl[0], 1);
+
+	if (priv->vmem)
+		iounmap(priv->vmem);
+	if (priv->vplxdma)
+		iounmap((uchar *) priv->vplxdma);
+
+	if (dev->irq)
+		free_irq(dev->irq, dev);
+
+	for (i = 1; i < priv->nports; ++i) {
+		if (priv->devtbl[i])
+			unregister_netdev(priv->devtbl[i]);
+	}
+}
+
+#ifdef CONFIG_PCI
+static int __init dgrs_pci_probe(struct pci_dev *pdev,
+				 const struct pci_device_id *ent)
 {
-	int	cards_found = 0;
+	struct net_device *dev;
+	int err;
 	uint	io;
 	uint	mem;
 	uint	irq;
 	uint	plxreg;
 	uint	plxdma;
-	struct pci_dev *pdev = NULL;
 
 	/*
-	 *	First, check for PCI boards
-	 */
-	while ((pdev = pci_find_device(SE6_PCI_VENDOR_ID, SE6_PCI_DEVICE_ID, pdev)) != NULL)
-	{
-		/*
-		 * Get and check the bus-master and latency values.
-		 * Some PCI BIOSes fail to set the master-enable bit,
-		 * and the latency timer must be set to the maximum
-		 * value to avoid data corruption that occurs when the
-		 * timer expires during a transfer.  Yes, it's a bug.
-		 */
-		if (pci_enable_device(pdev))
-			continue;
-		pci_set_master(pdev);
-
-		plxreg = pci_resource_start (pdev, 0);
-		io = pci_resource_start (pdev, 1);
-		mem = pci_resource_start (pdev, 2);
-		pci_read_config_dword(pdev, 0x30, &plxdma);
-		irq = pdev->irq;
-		plxdma &= ~15;
+	 * Get and check the bus-master and latency values.
+	 * Some PCI BIOSes fail to set the master-enable bit,
+	 * and the latency timer must be set to the maximum
+	 * value to avoid data corruption that occurs when the
+	 * timer expires during a transfer.  Yes, it's a bug.
+	 */
+	err = pci_enable_device(pdev);
+	if (err)
+		return err;
+	err = pci_request_regions(pdev, "RightSwitch");
+	if (err)
+		return err;
+
+	pci_set_master(pdev);
+
+	plxreg = pci_resource_start (pdev, 0);
+	io = pci_resource_start (pdev, 1);
+	mem = pci_resource_start (pdev, 2);
+	pci_read_config_dword(pdev, 0x30, &plxdma);
+	irq = pdev->irq;
+	plxdma &= ~15;
+
+	/*
+	 * On some BIOSES, the PLX "expansion rom" (used for DMA)
+	 * address comes up as "0".  This is probably because
+	 * the BIOS doesn't see a valid 55 AA ROM signature at
+	 * the "ROM" start and zeroes the address.  To get
+	 * around this problem the SE-6 is configured to ask
+	 * for 4 MB of space for the dual port memory.  We then
+	 * must set its range back to 2 MB, and use the upper
+	 * half for DMA register access
+	 */
+	OUTL(io + PLX_SPACE0_RANGE, 0xFFE00000L);
+	if (plxdma == 0)
+		plxdma = mem + (2048L * 1024L);
+	pci_write_config_dword(pdev, 0x30, plxdma + 1);
+	pci_read_config_dword(pdev, 0x30, &plxdma);
+	plxdma &= ~15;
+
+	dev = dgrs_found_device(io, mem, irq, plxreg, plxdma, &pdev->dev);
+	if (IS_ERR(dev)) {
+		pci_release_regions(pdev);
+		return PTR_ERR(dev);
+	}
 
-		/*
-		 * On some BIOSES, the PLX "expansion rom" (used for DMA)
-		 * address comes up as "0".  This is probably because
-		 * the BIOS doesn't see a valid 55 AA ROM signature at
-		 * the "ROM" start and zeroes the address.  To get
-		 * around this problem the SE-6 is configured to ask
-		 * for 4 MB of space for the dual port memory.  We then
-		 * must set its range back to 2 MB, and use the upper
-		 * half for DMA register access
-		 */
-		OUTL(io + PLX_SPACE0_RANGE, 0xFFE00000L);
-		if (plxdma == 0)
-			plxdma = mem + (2048L * 1024L);
-		pci_write_config_dword(pdev, 0x30, plxdma + 1);
-		pci_read_config_dword(pdev, 0x30, &plxdma);
-		plxdma &= ~15;
+	pci_set_drvdata(pdev, dev);
+	return 0;
+}
 
-		dgrs_found_device(io, mem, irq, plxreg, plxdma);
+static void __devexit dgrs_pci_remove(struct pci_dev *pdev)
+{
+	struct net_device *dev = pci_get_drvdata(pdev);
 
-		cards_found++;
-	}
+	dgrs_remove(dev);
+	pci_release_regions(pdev);
+	free_netdev(dev);
+}
 
-	/*
-	 *	Second, check for EISA boards
-	 */
-	if (EISA_bus)
-	{
-		for (io = 0x1000; io < 0x9000; io += 0x1000)
-		{
-			if (inb(io+ES4H_MANUFmsb) != 0x10
-				|| inb(io+ES4H_MANUFlsb) != 0x49
-				|| inb(io+ES4H_PRODUCT) != ES4H_PRODUCT_CODE)
-				continue;
+static struct pci_driver dgrs_pci_driver = {
+	.name = "dgrs",
+	.id_table = dgrs_pci_tbl,
+	.probe = dgrs_pci_probe,
+	.remove = __devexit_p(dgrs_pci_remove),
+};
+#endif
 
-			if ( ! (inb(io+ES4H_EC) & ES4H_EC_ENABLE) )
-				continue; /* Not EISA configured */
 
-			mem = (inb(io+ES4H_AS_31_24) << 24)
-				+ (inb(io+ES4H_AS_23_16) << 16);
+#ifdef CONFIG_EISA
+static int is2iv[8] __initdata = { 0, 3, 5, 7, 10, 11, 12, 15 };
 
-			irq = is2iv[ inb(io+ES4H_IS) & ES4H_IS_INTMASK ];
+static int __init dgrs_eisa_probe (struct device *gendev)
+{
+	struct net_device *dev;
+	struct eisa_device *edev = to_eisa_device(gendev);
+	uint	io = edev->base_addr;
+	uint	mem;
+	uint	irq;
+	int 	rc = -ENODEV; /* Not EISA configured */
 
-			dgrs_found_device(io, mem, irq, 0L, 0L);
+	if (!request_region(io, 256, "RightSwitch")) {
+		printk(KERN_ERR "dgrs: eisa io 0x%x, which is busy.\n", io);
+		return -EBUSY;
+	}
 
-			++cards_found;
-		}
+	if ( ! (inb(io+ES4H_EC) & ES4H_EC_ENABLE) ) 
+		goto err_out;
+
+	mem = (inb(io+ES4H_AS_31_24) << 24)
+		+ (inb(io+ES4H_AS_23_16) << 16);
+
+	irq = is2iv[ inb(io+ES4H_IS) & ES4H_IS_INTMASK ];
+
+	dev = dgrs_found_device(io, mem, irq, 0L, 0L, gendev);
+	if (IS_ERR(dev)) {
+		rc = PTR_ERR(dev);
+		goto err_out;
 	}
 
-	return cards_found;
+	gendev->driver_data = dev;
+	return 0;
+ err_out:
+	release_region(io, 256);
+	return rc;
+}
+
+static int __devexit dgrs_eisa_remove(struct device *gendev)
+{
+	struct net_device *dev = gendev->driver_data;
+	
+	dgrs_remove(dev);
+
+	release_region(dev->base_addr, 256);
+		
+	free_netdev(dev);
+	return 0;
 }
 
 
+static struct eisa_driver dgrs_eisa_driver = {
+	.id_table = dgrs_eisa_tbl,
+	.driver = {
+		.name = "dgrs",
+		.probe = dgrs_eisa_probe,
+		.remove = __devexit_p(dgrs_eisa_remove),
+	}
+};
+#endif
+
 /*
  *	Variables that can be overriden from module command line
  */
@@ -1459,8 +1542,8 @@ MODULE_PARM_DESC(nicmode, "Digi RightSwi
 
 static int __init dgrs_init_module (void)
 {
-	int	cards_found;
 	int	i;
+	int eisacount = 0, pcicount = 0;
 
 	/*
 	 *	Command line variable overrides
@@ -1501,38 +1584,27 @@ static int __init dgrs_init_module (void
 	/*
 	 *	Find and configure all the cards
 	 */
-	dgrs_root_dev = NULL;
-	cards_found = dgrs_scan();
-
-	return cards_found ? 0 : -ENODEV;
+#ifdef CONFIG_EISA
+	eisacount = eisa_driver_register(&dgrs_eisa_driver);
+	if (eisacount < 0)
+		return eisacount;
+#endif
+#ifdef CONFIG_PCI
+	pcicount = pci_register_driver(&dgrs_pci_driver);
+	if (pcicount < 0)
+		return pcicount;
+#endif
+	return (eisacount + pcicount) == 0 ? -ENODEV : 0;
 }
 
 static void __exit dgrs_cleanup_module (void)
 {
-        while (dgrs_root_dev)
-	{
-		struct net_device	*next_dev;
-		DGRS_PRIV	*priv;
-
-		priv = (DGRS_PRIV *) dgrs_root_dev->priv;
-                next_dev = priv->next_dev;
-                unregister_netdev(dgrs_root_dev);
-
-		proc_reset(priv->devtbl[0], 1);
-
-		if (priv->vmem)
-			iounmap(priv->vmem);
-		if (priv->vplxdma)
-			iounmap((uchar *) priv->vplxdma);
-
-		release_region(dgrs_root_dev->base_addr, 256);
-
-		if (dgrs_root_dev->irq)
-			free_irq(dgrs_root_dev->irq, dgrs_root_dev);
-
-                free_netdev(dgrs_root_dev);
-                dgrs_root_dev = next_dev;
-        }
+#ifdef CONFIG_EISA
+	eisa_driver_unregister (&dgrs_eisa_driver);
+#endif
+#ifdef CONFIG_PCI
+	pci_unregister_driver (&dgrs_pci_driver);
+#endif
 }
 
 module_init(dgrs_init_module);
--- diff/drivers/net/e2100.c	2004-02-18 08:54:10.000000000 +0000
+++ source/drivers/net/e2100.c	2004-02-23 13:56:43.000000000 +0000
@@ -269,6 +269,9 @@ static int __init e21_probe1(struct net_
 	ei_status.get_8390_hdr = &e21_get_8390_hdr;
 	dev->open = &e21_open;
 	dev->stop = &e21_close;
+#ifdef CONFIG_NET_POLL_CONTROLLER
+	dev->poll_controller = ei_poll;
+#endif
 	NS8390_init(dev, 0);
 
 	return 0;
--- diff/drivers/net/eepro100.c	2003-10-09 09:47:16.000000000 +0100
+++ source/drivers/net/eepro100.c	2004-02-23 13:56:43.000000000 +0000
@@ -654,6 +654,23 @@ err_out_none:
 	return -ENODEV;
 }
 
+#ifdef CONFIG_NET_POLL_CONTROLLER
+/*
+ * Polling 'interrupt' - used by things like netconsole to send skbs
+ * without having to re-enable interrupts. It's not called while
+ * the interrupt routine is executing.
+ */
+
+static void poll_speedo (struct net_device *dev)
+{
+	/* disable_irq is not very nice, but with the funny lockless design
+	   we have no other choice. */
+	disable_irq(dev->irq);
+	speedo_interrupt (dev->irq, dev, NULL);
+	enable_irq(dev->irq);
+}
+#endif
+
 static int __devinit speedo_found1(struct pci_dev *pdev,
 		long ioaddr, int card_idx, int acpi_idle_state)
 {
@@ -885,6 +902,9 @@ static int __devinit speedo_found1(struc
 	dev->get_stats = &speedo_get_stats;
 	dev->set_multicast_list = &set_rx_mode;
 	dev->do_ioctl = &speedo_ioctl;
+#ifdef CONFIG_NET_POLL_CONTROLLER
+	dev->poll_controller = &poll_speedo;
+#endif
 
 	if (register_netdevice(dev))
 		goto err_free_unlock;
--- diff/drivers/net/es3210.c	2004-02-18 08:54:10.000000000 +0000
+++ source/drivers/net/es3210.c	2004-02-23 13:56:43.000000000 +0000
@@ -298,6 +298,9 @@ static int __init es_probe1(struct net_d
 
 	dev->open = &es_open;
 	dev->stop = &es_close;
+#ifdef CONFIG_NET_POLL_CONTROLLER
+	dev->poll_controller = ei_poll;
+#endif
 	NS8390_init(dev, 0);
 	return 0;
 out1:
--- diff/drivers/net/fc/iph5526.c	2004-02-18 08:54:10.000000000 +0000
+++ source/drivers/net/fc/iph5526.c	2004-02-23 13:56:43.000000000 +0000
@@ -4501,7 +4501,7 @@ static int __init iph5526_init(void)
 		iph5526_probe_pci(dev);
 		err = register_netdev(dev);
 		if (err < 0) {
-			kfree(dev);
+			free_netdev(dev);
 			printk("iph5526.c: init_fcdev failed for card #%d\n", i+1);
 			break;
 		}
--- diff/drivers/net/fec.c	2003-06-09 14:18:19.000000000 +0100
+++ source/drivers/net/fec.c	2004-02-23 13:56:43.000000000 +0000
@@ -1638,9 +1638,12 @@ fec_set_mac_address(struct net_device *d
 
 /* Initialize the FEC Ethernet on 860T (or ColdFire 5272).
  */
+ /*
+  * XXX:  We need to clean up on failure exits here.
+  */
 int __init fec_enet_init(struct net_device *dev)
 {
-	struct fec_enet_private *fep;
+	struct fec_enet_private *fep = dev->priv;
 	unsigned long	mem_addr;
 	volatile cbd_t	*bdp;
 	cbd_t		*cbd_base;
@@ -1651,13 +1654,6 @@ int __init fec_enet_init(struct net_devi
 	if (found)
 		return(-ENXIO);
 
-	/* Allocate some private information.
-	*/
-	fep = (struct fec_enet_private *)kmalloc(sizeof(*fep), GFP_KERNEL);
-	if (!fep)
-		return -ENOMEM;
-	memset(fep, 0, sizeof(*fep));
-
 	/* Create an Ethernet device instance.
 	*/
 	fecp = fec_hwp;
@@ -1694,6 +1690,7 @@ int __init fec_enet_init(struct net_devi
 	}
 	mem_addr = __get_free_page(GFP_KERNEL);
 	cbd_base = (cbd_t *)mem_addr;
+	/* XXX: missing check for allocation failure */
 
 	fec_uncache(mem_addr);
 
@@ -1715,6 +1712,7 @@ int __init fec_enet_init(struct net_devi
 		/* Allocate a page.
 		*/
 		mem_addr = __get_free_page(GFP_KERNEL);
+		/* XXX: missing check for allocation failure */
 
 		fec_uncache(mem_addr);
 
@@ -1761,9 +1759,6 @@ int __init fec_enet_init(struct net_devi
 	fec_request_intrs(dev, fecp);
 
 	dev->base_addr = (unsigned long)fecp;
-	dev->priv = fep;
-
-	ether_setup(dev);
 
 	/* The FEC Ethernet specific entries in the device structure. */
 	dev->open = fec_enet_open;
@@ -1949,14 +1944,28 @@ fec_stop(struct net_device *dev)
 	fecp->fec_mii_speed = fep->phy_speed;
 }
 
-static struct net_device fec_dev = {
-	.init = fec_enet_init,
-};
+static struct net_device *fec_dev;
 
 static int __init fec_enet_module_init(void)
 {
-	if (register_netdev(&fec_dev) != 0)
+	struct net_device *dev;
+	int err;
+
+	dev = alloc_etherdev(sizeof(struct fec_enet_private));
+	if (!dev)
+		return -ENOMEM;
+	err = fec_enet_init(dev);
+	if (err) {
+		free_netdev(dev);
+		return err;
+	}
+
+	if (register_netdev(dev) != 0) {
+		/* XXX: missing cleanup here */
+		free_netdev(dev);
 		return -EIO;
+	}
+	fec_dev = dev;
 	return(0);
 }
 
--- diff/drivers/net/gt96100eth.c	2004-02-18 08:54:10.000000000 +0000
+++ source/drivers/net/gt96100eth.c	2004-02-23 13:56:43.000000000 +0000
@@ -661,9 +661,9 @@ int gt96100_init_module(void)
 	pcibios_read_config_word(0, 0, PCI_VENDOR_ID, &vendor_id);
 	pcibios_read_config_word(0, 0, PCI_DEVICE_ID, &device_id);
     
-	if (vendor_id != PCI_VENDOR_ID_GALILEO ||
-	    (device_id != PCI_DEVICE_ID_GALILEO_GT96100 &&
-	     device_id != PCI_DEVICE_ID_GALILEO_GT96100A)) {
+	if (vendor_id != PCI_VENDOR_ID_MARVELL ||
+	    (device_id != PCI_DEVICE_ID_MARVELL_GT96100 &&
+	     device_id != PCI_DEVICE_ID_MARVELL_GT96100A)) {
 		printk(KERN_ERR __FILE__ ": GT96100 not found!\n");
 		return -ENODEV;
 	}
--- diff/drivers/net/hamradio/6pack.c	2004-02-18 08:54:10.000000000 +0000
+++ source/drivers/net/hamradio/6pack.c	2004-02-23 13:56:43.000000000 +0000
@@ -178,17 +178,17 @@ static inline struct sixpack *sp_alloc(v
 	    (sixpack_ctrls[i] = (sixpack_ctrl_t *)kmalloc(sizeof(sixpack_ctrl_t),
 						    GFP_KERNEL)) != NULL) {
 		spp = sixpack_ctrls[i];
-		memset(spp, 0, sizeof(sixpack_ctrl_t));
-
-		/* Initialize channel control data */
-		set_bit(SIXPF_INUSE, &spp->ctrl.flags);
-		spp->ctrl.tty         = NULL;
-		sprintf(spp->dev.name, "sp%d", i);
-		spp->dev.base_addr    = i;
-		spp->dev.priv         = (void *) &spp->ctrl;
-		spp->dev.next         = NULL;
-		spp->dev.init         = sixpack_init;
 	}
+	memset(spp, 0, sizeof(sixpack_ctrl_t));
+
+	/* Initialize channel control data */
+	set_bit(SIXPF_INUSE, &spp->ctrl.flags);
+	spp->ctrl.tty         = NULL;
+	sprintf(spp->dev.name, "sp%d", i);
+	spp->dev.base_addr    = i;
+	spp->dev.priv         = (void *) &spp->ctrl;
+	spp->dev.next         = NULL;
+	spp->dev.init         = sixpack_init;
 
 	if (spp != NULL) {
 		/* register device so that it can be ifconfig'ed       */
--- diff/drivers/net/hamradio/Kconfig	2003-10-27 09:20:38.000000000 +0000
+++ source/drivers/net/hamradio/Kconfig	2004-02-23 13:56:43.000000000 +0000
@@ -72,8 +72,8 @@ config DMASCC
 	  certain parameters, such as channel access timing, clock mode, and
 	  DMA channel. This is accomplished with a small utility program,
 	  dmascc_cfg, available at
-	  <http://www.nt.tuwien.ac.at/~kkudielk/Linux/>. Please be sure to get
-	  at least version 1.27 of dmascc_cfg, as older versions will not
+	  <http://cacofonix.nt.tuwien.ac.at/~oe1kib/Linux/>. Please be sure to
+	  get at least version 1.27 of dmascc_cfg, as older versions will not
 	  work with the current driver.
 
 config SCC
@@ -96,8 +96,9 @@ config SCC_DELAY
 	help
 	  Say Y here if you experience problems with the SCC driver not
 	  working properly; please read
-	  <file:Documentation/networking/z8530drv.txt> for details. If unsure,
-	  say N.
+	  <file:Documentation/networking/z8530drv.txt> for details.
+
+	  If unsure, say N.
 
 config SCC_TRXECHO
 	bool "support for TRX that feedback the tx signal to rx"
@@ -105,7 +106,9 @@ config SCC_TRXECHO
 	help
 	  Some transmitters feed the transmitted signal back to the receive
 	  line.  Say Y here to foil this by explicitly disabling the receiver
-	  during data transmission.  If in doubt, say Y.
+	  during data transmission.
+
+	  If in doubt, say Y.
 
 config BAYCOM_SER_FDX
 	tristate "BAYCOM ser12 fullduplex driver for AX.25"
--- diff/drivers/net/hp-plus.c	2004-02-18 08:54:10.000000000 +0000
+++ source/drivers/net/hp-plus.c	2004-02-23 13:56:43.000000000 +0000
@@ -236,6 +236,9 @@ static int __init hpp_probe1(struct net_
 
 	dev->open = &hpp_open;
 	dev->stop = &hpp_close;
+#ifdef CONFIG_NET_POLL_CONTROLLER
+	dev->poll_controller = ei_poll;
+#endif
 
 	ei_status.name = name;
 	ei_status.word16 = 0;		/* Agggghhhhh! Debug time: 2 days! */
--- diff/drivers/net/hp.c	2004-02-18 08:54:10.000000000 +0000
+++ source/drivers/net/hp.c	2004-02-23 13:56:43.000000000 +0000
@@ -207,6 +207,9 @@ static int __init hp_probe1(struct net_d
 	dev->base_addr = ioaddr + NIC_OFFSET;
 	dev->open = &hp_open;
 	dev->stop = &hp_close;
+#ifdef CONFIG_NET_POLL_CONTROLLER
+	dev->poll_controller = ei_poll;
+#endif
 
 	ei_status.name = name;
 	ei_status.word16 = wordmode;
--- diff/drivers/net/hp100.c	2004-02-18 08:54:10.000000000 +0000
+++ source/drivers/net/hp100.c	2004-02-23 13:56:43.000000000 +0000
@@ -3043,14 +3043,27 @@ static int __init hp100_module_init(void
 	int err;
 
 	err = hp100_isa_init();
-
+	if (err && err != -ENODEV)
+		goto out;
 #ifdef CONFIG_EISA
-	err |= eisa_driver_register(&hp100_eisa_driver);
+	err = eisa_driver_register(&hp100_eisa_driver);
+	if (err && err != -ENODEV) 
+		goto out2;
 #endif
 #ifdef CONFIG_PCI
-	err |= pci_module_init(&hp100_pci_driver);
+	err = pci_module_init(&hp100_pci_driver);
+	if (err && err != -ENODEV) 
+		goto out3;
 #endif
+ out:
 	return err;
+ out3:
+#ifdef CONFIG_EISA
+	eisa_driver_unregister (&hp100_eisa_driver);
+ out2:
+#endif
+	hp100_isa_cleanup();
+	goto out;
 }
 
 
--- diff/drivers/net/hydra.c	2004-02-18 08:54:10.000000000 +0000
+++ source/drivers/net/hydra.c	2004-02-23 13:56:43.000000000 +0000
@@ -44,10 +44,10 @@
 
 #define WORDSWAP(a)     ((((a)>>8)&0xff) | ((a)<<8))
 
-static struct net_device *root_hydra_dev;
 
-static int __init hydra_probe(void);
-static int __init hydra_init(unsigned long board);
+static int __devinit hydra_init_one(struct zorro_dev *z,
+				    const struct zorro_device_id *ent);
+static int __devinit hydra_init(struct zorro_dev *z);
 static int hydra_open(struct net_device *dev);
 static int hydra_close(struct net_device *dev);
 static void hydra_reset_8390(struct net_device *dev);
@@ -57,34 +57,38 @@ static void hydra_block_input(struct net
 			      struct sk_buff *skb, int ring_offset);
 static void hydra_block_output(struct net_device *dev, int count,
 			       const unsigned char *buf, int start_page);
-static void __exit hydra_cleanup(void);
+static void __devexit hydra_remove_one(struct zorro_dev *z);
 
-static int __init hydra_probe(void)
-{
-    struct zorro_dev *z = NULL;
-    unsigned long board;
-    int err = -ENODEV;
-
-    while ((z = zorro_find_device(ZORRO_PROD_HYDRA_SYSTEMS_AMIGANET, z))) {
-	board = z->resource.start;
-	if (!request_mem_region(board, 0x10000, "Hydra"))
-	    continue;
-	if ((err = hydra_init(ZTWO_VADDR(board)))) {
-	    release_mem_region(board, 0x10000);
-	    return err;
-	}
-	err = 0;
-    }
+static struct zorro_device_id hydra_zorro_tbl[] __devinitdata = {
+    { ZORRO_PROD_HYDRA_SYSTEMS_AMIGANET },
+    { 0 }
+};
+
+static struct zorro_driver hydra_driver = {
+    .name	= "hydra",
+    .id_table	= hydra_zorro_tbl,
+    .probe	= hydra_init_one,
+    .remove	= __devexit_p(hydra_remove_one),
+};
 
-    if (err == -ENODEV)
-	printk("No Hydra ethernet card found.\n");
+static int __devinit hydra_init_one(struct zorro_dev *z,
+				    const struct zorro_device_id *ent)
+{
+    int err;
 
-    return err;
+    if (!request_mem_region(z->resource.start, 0x10000, "Hydra"))
+	return -EBUSY;
+    if ((err = hydra_init(z))) {
+	release_mem_region(z->resource.start, 0x10000);
+	return -EBUSY;
+    }
+    return 0;
 }
 
-static int __init hydra_init(unsigned long board)
+static int __devinit hydra_init(struct zorro_dev *z)
 {
     struct net_device *dev;
+    unsigned long board = ZTWO_VADDR(z->resource.start);
     unsigned long ioaddr = board+HYDRA_NIC_BASE;
     const char name[] = "NE2000";
     int start_page, stop_page;
@@ -119,7 +123,7 @@ static int __init hydra_init(unsigned lo
 	return -EAGAIN;
     }
 
-    printk("%s: hydra at 0x%08lx, address %02x:%02x:%02x:%02x:%02x:%02x (hydra.c " HYDRA_VERSION ")\n", dev->name, ZTWO_PADDR(board),
+    printk("%s: hydra at 0x%08lx, address %02x:%02x:%02x:%02x:%02x:%02x (hydra.c " HYDRA_VERSION ")\n", dev->name, z->resource.start,
 	dev->dev_addr[0], dev->dev_addr[1], dev->dev_addr[2],
 	dev->dev_addr[3], dev->dev_addr[4], dev->dev_addr[5]);
 
@@ -138,18 +142,24 @@ static int __init hydra_init(unsigned lo
     ei_status.reg_offset = hydra_offsets;
     dev->open = &hydra_open;
     dev->stop = &hydra_close;
+#ifdef CONFIG_NET_POLL_CONTROLLER
+    dev->poll_controller = ei_poll;
+#endif
 #ifdef MODULE
     ei_status.priv = (unsigned long)root_hydra_dev;
     root_hydra_dev = dev;
 #endif
     NS8390_init(dev, 0);
+
     err = register_netdev(dev);
-    if (!err)
-	return 0;
+    if (err) {
+	free_irq(IRQ_AMIGA_PORTS, dev);
+	free_netdev(dev);
+	return err;
+    }
 
-    free_irq(IRQ_AMIGA_PORTS, dev);
-    free_netdev(dev);
-    return err;
+    zorro_set_drvdata(z, dev);
+    return 0;
 }
 
 static int hydra_open(struct net_device *dev)
@@ -220,20 +230,27 @@ static void hydra_block_output(struct ne
     z_memcpy_toio(mem_base+((start_page - NESM_START_PG)<<8), buf, count);
 }
 
-static void __exit hydra_cleanup(void)
+static void __devexit hydra_remove_one(struct zorro_dev *z)
 {
-    struct net_device *dev, *next;
+    struct net_device *dev = zorro_get_drvdata(z);
 
-    while ((dev = root_hydra_dev)) {
-	next = (struct net_device *)(ei_status.priv);
-	unregister_netdev(dev);
-	free_irq(IRQ_AMIGA_PORTS, dev);
-	release_mem_region(ZTWO_PADDR(dev->base_addr)-HYDRA_NIC_BASE, 0x10000);
-	free_netdev(dev);
-	root_hydra_dev = next;
-    }
+    unregister_netdev(dev);
+    free_irq(IRQ_AMIGA_PORTS, dev);
+    release_mem_region(ZTWO_PADDR(dev->base_addr)-HYDRA_NIC_BASE, 0x10000);
+    free_netdev(dev);
 }
 
-module_init(hydra_probe);
-module_exit(hydra_cleanup);
+static int __init hydra_init_module(void)
+{
+    return zorro_module_init(&hydra_driver);
+}
+
+static void __exit hydra_cleanup_module(void)
+{
+    zorro_unregister_driver(&hydra_driver);
+}
+
+module_init(hydra_init_module);
+module_exit(hydra_cleanup_module);
+
 MODULE_LICENSE("GPL");
--- diff/drivers/net/irda/Kconfig	2004-02-09 10:36:10.000000000 +0000
+++ source/drivers/net/irda/Kconfig	2004-02-23 13:56:43.000000000 +0000
@@ -269,7 +269,7 @@ config MA600_DONGLE_OLD
 	  information, download the following tar gzip file.
 
 	  There is a pre-compiled module on
-	  <http://engsvr.ust.hk/~eetwl95/download/ma600-2.4.x.tar.gz>
+	  <http://engsvr.ust.hk/~eetwl95/ma600.html>
 
 config EP7211_IR
 	tristate "EP7211 I/R support"
@@ -292,6 +292,22 @@ config USB_IRDA
 	  Please note that the driver is still experimental.  And of course,
 	  you will need both USB and IrDA support in your kernel...
 
+config SIGMATEL_FIR
+	tristate "SigmaTel STIr4200 bridge (EXPERIMENTAL)"
+	depends on IRDA && USB && EXPERIMENTAL
+	select CRC32
+	---help---
+	  Say Y here if you want to build support for the SigmaTel STIr4200
+	  USB IrDA FIR bridge device driver.  
+
+	  USB bridge based on the SigmaTel STIr4200 don't conform to the
+	  IrDA-USB device class specification, and therefore need their
+	  own specific driver. Those dongles support SIR and FIR (4Mbps)
+	  speeds. 
+
+	  To compile it as a module, choose M here: the module will be called
+	  stir4200.
+
 config NSC_FIR
 	tristate "NSC PC87108/PC87338"
 	depends on IRDA && ISA
--- diff/drivers/net/irda/Makefile	2004-02-09 10:36:10.000000000 +0000
+++ source/drivers/net/irda/Makefile	2004-02-23 13:56:43.000000000 +0000
@@ -9,6 +9,7 @@
 obj-$(CONFIG_IRPORT_SIR)	+= 		irport.o
 # FIR drivers
 obj-$(CONFIG_USB_IRDA)		+= irda-usb.o
+obj-$(CONFIG_SIGMATEL_FIR)	+= stir4200.o
 obj-$(CONFIG_NSC_FIR)		+= nsc-ircc.o
 obj-$(CONFIG_WINBOND_FIR)	+= w83977af_ir.o
 obj-$(CONFIG_SA1100_FIR)	+= sa1100_ir.o
--- diff/drivers/net/isa-skeleton.c	2003-05-21 11:50:15.000000000 +0100
+++ source/drivers/net/isa-skeleton.c	2004-02-23 13:56:43.000000000 +0000
@@ -104,8 +104,6 @@ struct net_local {
 
 /* Index to functions, as function prototypes. */
 
-extern int netcard_probe(struct net_device *dev);
-
 static int	netcard_probe1(struct net_device *dev, int ioaddr);
 static int	net_open(struct net_device *dev);
 static int	net_send_packet(struct sk_buff *skb, struct net_device *dev);
@@ -129,11 +127,11 @@ static void 	chipset_init(struct net_dev
  * If dev->base_addr == 2, allocate space for the device and return success
  * (detachable devices only).
  */
-int __init 
-netcard_probe(struct net_device *dev)
+static int __init do_netcard_probe(struct net_device *dev)
 {
 	int i;
 	int base_addr = dev->base_addr;
+	int irq = dev->irq;
 
 	SET_MODULE_OWNER(dev);
 
@@ -144,14 +142,49 @@ netcard_probe(struct net_device *dev)
 
 	for (i = 0; netcard_portlist[i]; i++) {
 		int ioaddr = netcard_portlist[i];
-		if (check_region(ioaddr, NETCARD_IO_EXTENT))
-			continue;
 		if (netcard_probe1(dev, ioaddr) == 0)
 			return 0;
+		dev->irq = irq;
 	}
 
 	return -ENODEV;
 }
+ 
+static void cleanup_card(struct net_device *dev)
+{
+#ifdef jumpered_dma
+	free_dma(dev->dma);
+#endif
+#ifdef jumpered_interrupts
+	free_irq(dev->irq, dev);
+#endif
+	release_region(dev->base_addr, NETCARD_IO_EXTENT);
+}
+
+struct net_device * __init netcard_probe(int unit)
+{
+	struct net_device *dev = alloc_etherdev(sizeof(struct net_local));
+	int err;
+
+	if (!dev)
+		return ERR_PTR(-ENOMEM);
+
+	sprintf(dev->name, "eth%d", unit);
+	netdev_boot_setup_check(dev);
+
+	err = do_netcard_probe(dev);
+	if (err)
+		goto out;
+	err = register_netdev(dev);
+	if (err)
+		goto out1;
+	return dev;
+out1:
+	cleanup_card(dev);
+out:
+	free_netdev(dev);
+	return ERR_PTR(err);
+}
 
 /*
  * This is the real probe routine. Linux has a history of friendly device
@@ -163,6 +196,11 @@ static int __init netcard_probe1(struct 
 	struct net_local *np;
 	static unsigned version_printed;
 	int i;
+	int err = -ENODEV;
+
+	/* Grab the region so that no one else tries to probe our ioports. */
+	if (!request_region(ioaddr, NETCARD_IO_EXTENT, cardname))
+		return -EBUSY;
 
 	/*
 	 * For ethernet adaptors the first three octets of the station address 
@@ -171,9 +209,8 @@ static int __init netcard_probe1(struct 
 	 */ 
 	if (inb(ioaddr + 0) != SA_ADDR0
 		||	 inb(ioaddr + 1) != SA_ADDR1
-		||	 inb(ioaddr + 2) != SA_ADDR2) {
-		return -ENODEV;
-	}
+		||	 inb(ioaddr + 2) != SA_ADDR2)
+		goto out;
 
 	if (net_debug  &&  version_printed++ == 0)
 		printk(KERN_DEBUG "%s", version);
@@ -187,6 +224,7 @@ static int __init netcard_probe1(struct 
 	for (i = 0; i < 6; i++)
 		printk(" %2.2x", dev->dev_addr[i] = inb(ioaddr + i));
 
+	err = -EAGAIN;
 #ifdef jumpered_interrupts
 	/*
 	 * If this board has jumpered interrupts, allocate the interrupt
@@ -217,7 +255,7 @@ static int __init netcard_probe1(struct 
 		if (irqval) {
 			printk("%s: unable to get IRQ %d (irqval=%d).\n",
 				   dev->name, dev->irq, irqval);
-			return -EAGAIN;
+			goto out;
 		}
 	}
 #endif	/* jumpered interrupt */
@@ -229,7 +267,7 @@ static int __init netcard_probe1(struct 
 	if (dev->dma == 0) {
 		if (request_dma(dev->dma, cardname)) {
 			printk("DMA %d allocation failed.\n", dev->dma);
-			return -EAGAIN;
+			goto out1;
 		} else
 			printk(", assigned DMA %d.\n", dev->dma);
 	} else {
@@ -256,30 +294,18 @@ static int __init netcard_probe1(struct 
 			}
 		if (i <= 0) {
 			printk("DMA probe failed.\n");
-			return -EAGAIN;
+			goto out1;
 		} 
 		if (request_dma(dev->dma, cardname)) {
 			printk("probed DMA %d allocation failed.\n", dev->dma);
-			return -EAGAIN;
+			goto out1;
 		}
 	}
 #endif	/* jumpered DMA */
 
-	/* Initialize the device structure. */
-	if (dev->priv == NULL) {
-		dev->priv = kmalloc(sizeof(struct net_local), GFP_KERNEL);
-		if (dev->priv == NULL)
-			return -ENOMEM;
-	}
-
-	memset(dev->priv, 0, sizeof(struct net_local));
-
 	np = (struct net_local *)dev->priv;
 	spin_lock_init(&np->lock);
 
-	/* Grab the region so that no one else tries to probe our ioports. */
-	request_region(ioaddr, NETCARD_IO_EXTENT, cardname);
-
 	dev->open		= net_open;
 	dev->stop		= net_close;
 	dev->hard_start_xmit	= net_send_packet;
@@ -288,11 +314,14 @@ static int __init netcard_probe1(struct 
 
         dev->tx_timeout		= &net_tx_timeout;
         dev->watchdog_timeo	= MY_TX_TIMEOUT; 
-
-	/* Fill in the fields of the device structure with ethernet values. */
-	ether_setup(dev);
-
 	return 0;
+out1:
+#ifdef jumpered_interrupts
+	free_irq(dev->irq, dev);
+#endif
+out:
+	release_region(base_addr, NETCARD_IO_EXTENT);
+	return err;
 }
 
 static void net_tx_timeout(struct net_device *dev)
@@ -635,7 +664,7 @@ set_multicast_list(struct net_device *de
 
 #ifdef MODULE
 
-static struct net_device this_device;
+static struct net_device *this_device;
 static int io = 0x300;
 static int irq;
 static int dma;
@@ -644,42 +673,38 @@ MODULE_LICENSE("GPL");
 
 int init_module(void)
 {
+	struct net_device *dev;
 	int result;
 
 	if (io == 0)
 		printk(KERN_WARNING "%s: You shouldn't use auto-probing with insmod!\n",
 			   cardname);
+	dev = alloc_etherdev(sizeof(struct net_local));
+	if (!dev)
+		return -ENOMEM;
 
 	/* Copy the parameters from insmod into the device structure. */
-	this_device.base_addr = io;
-	this_device.irq       = irq;
-	this_device.dma       = dma;
-	this_device.mem_start = mem;
-	this_device.init      = netcard_probe;
-
-	if ((result = register_netdev(&this_device)) != 0)
-		return result;
-
-	return 0;
+	dev->base_addr = io;
+	dev->irq       = irq;
+	dev->dma       = dma;
+	dev->mem_start = mem;
+	if (do_netcard_probe(dev) == 0) {
+		if (register_netdev(dev) == 0)
+			this_device = dev;
+			return 0;
+		}
+		cleanup_card(dev);
+	}
+	free_netdev(dev);
+	return -ENXIO;
 }
 
 void
 cleanup_module(void)
 {
-	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
-	 * allocate them in net_probe1().
-	 */
-	/*
-	   free_irq(this_device.irq, dev);
-	   free_dma(this_device.dma);
-	*/
-	release_region(this_device.base_addr, NETCARD_IO_EXTENT);
-
-	if (this_device.priv)
-		kfree(this_device.priv);
+	unregister_netdev(this_device);
+	cleanup_card(this_device);
+	free_netdev(this_device);
 }
 
 #endif /* MODULE */
--- diff/drivers/net/lne390.c	2004-02-18 08:54:10.000000000 +0000
+++ source/drivers/net/lne390.c	2004-02-23 13:56:43.000000000 +0000
@@ -299,6 +299,9 @@ static int __init lne390_probe1(struct n
 
 	dev->open = &lne390_open;
 	dev->stop = &lne390_close;
+#ifdef CONFIG_NET_POLL_CONTROLLER
+	dev->poll_controller = ei_poll;
+#endif
 	NS8390_init(dev, 0);
 	return 0;
 cleanup:
--- diff/drivers/net/loopback.c	2003-10-27 09:20:38.000000000 +0000
+++ source/drivers/net/loopback.c	2004-02-23 13:56:43.000000000 +0000
@@ -173,7 +173,7 @@ struct net_device loopback_dev = {
 	.rebuild_header		= eth_rebuild_header,
 	.flags			= IFF_LOOPBACK,
 	.features 		= NETIF_F_SG|NETIF_F_FRAGLIST
-				  |NETIF_F_NO_CSUM|NETIF_F_HIGHDMA|NETIF_F_TSO,
+				  |NETIF_F_NO_CSUM|NETIF_F_HIGHDMA,
 };
 
 /* Setup and register the of the LOOPBACK device. */
--- diff/drivers/net/mac8390.c	2004-02-18 08:54:10.000000000 +0000
+++ source/drivers/net/mac8390.c	2004-02-23 13:56:43.000000000 +0000
@@ -442,6 +442,9 @@ static int __init mac8390_initdev(struct
 	/* Now fill in our stuff */
 	dev->open = &mac8390_open;
 	dev->stop = &mac8390_close;
+#ifdef CONFIG_NET_POLL_CONTROLLER
+	dev->poll_controller = ei_poll;
+#endif
 
 	/* GAR, ei_status is actually a macro even though it looks global */
 	ei_status.name = cardname[type];
--- diff/drivers/net/ne.c	2004-02-18 08:54:10.000000000 +0000
+++ source/drivers/net/ne.c	2004-02-23 13:56:43.000000000 +0000
@@ -496,6 +496,9 @@ static int __init ne_probe1(struct net_d
 	ei_status.priv = 0;
 	dev->open = &ne_open;
 	dev->stop = &ne_close;
+#ifdef CONFIG_NET_POLL_CONTROLLER
+	dev->poll_controller = ei_poll;
+#endif
 	NS8390_init(dev, 0);
 	return 0;
 
--- diff/drivers/net/ne2.c	2004-02-18 08:54:10.000000000 +0000
+++ source/drivers/net/ne2.c	2004-02-23 13:56:43.000000000 +0000
@@ -509,6 +509,9 @@ static int __init ne2_probe1(struct net_
 	
 	dev->open = &ne_open;
 	dev->stop = &ne_close;
+#ifdef CONFIG_NET_POLL_CONTROLLER
+	dev->poll_controller = ei_poll;
+#endif
 	NS8390_init(dev, 0);
 	return 0;
 out:
--- diff/drivers/net/ne2k-pci.c	2004-02-18 08:54:10.000000000 +0000
+++ source/drivers/net/ne2k-pci.c	2004-02-23 13:56:43.000000000 +0000
@@ -359,6 +359,9 @@ static int __devinit ne2k_pci_init_one (
 	dev->open = &ne2k_pci_open;
 	dev->stop = &ne2k_pci_close;
 	dev->ethtool_ops = &ne2k_pci_ethtool_ops;
+#ifdef CONFIG_NET_POLL_CONTROLLER
+	dev->poll_controller = ei_poll;
+#endif
 	NS8390_init(dev, 0);
 
 	i = register_netdev(dev);
--- diff/drivers/net/ne2k_cbus.c	2004-02-18 08:54:10.000000000 +0000
+++ source/drivers/net/ne2k_cbus.c	2004-02-23 13:56:43.000000000 +0000
@@ -534,6 +534,9 @@ static int __init ne_probe1(struct net_d
 	ei_status.priv = 0;
 	dev->open = &ne_open;
 	dev->stop = &ne_close;
+#ifdef CONFIG_NET_POLL_CONTROLLER
+	dev->poll_controller = ei_poll;
+#endif
 	NS8390_init(dev, 0);
 	return 0;
 
--- diff/drivers/net/ne3210.c	2004-02-18 08:54:10.000000000 +0000
+++ source/drivers/net/ne3210.c	2004-02-23 13:56:43.000000000 +0000
@@ -205,6 +205,9 @@ static int __init ne3210_eisa_probe (str
 
 	dev->open = &ne3210_open;
 	dev->stop = &ne3210_close;
+#ifdef CONFIG_NET_POLL_CONTROLLER
+	dev->poll_controller = ei_poll;
+#endif
 	dev->if_port = ifmap_val[port_index];
 
 	if ((retval = register_netdev (dev)))
--- diff/drivers/net/oaknet.c	2004-02-18 08:54:10.000000000 +0000
+++ source/drivers/net/oaknet.c	2004-02-23 13:56:43.000000000 +0000
@@ -192,6 +192,9 @@ static int __init oaknet_init(void)
 
 	dev->open = oaknet_open;
 	dev->stop = oaknet_close;
+#ifdef CONFIG_NET_POLL_CONTROLLER
+	dev->poll_controller = ei_poll;
+#endif
 
 	NS8390_init(dev, FALSE);
 	ret = register_netdev(dev);
--- diff/drivers/net/pcnet32.c	2004-02-18 08:54:10.000000000 +0000
+++ source/drivers/net/pcnet32.c	2004-02-23 13:56:43.000000000 +0000
@@ -456,6 +456,14 @@ static struct pcnet32_access pcnet32_dwi
     .reset	= pcnet32_dwio_reset
 };
 
+#ifdef CONFIG_NET_POLL_CONTROLLER
+static void pcnet32_poll_controller(struct net_device *dev)
+{ 
+	disable_irq(dev->irq);
+	pcnet32_interrupt(0, dev, NULL);
+	enable_irq(dev->irq);
+} 
+#endif
 
 
 /* only probes for non-PCI devices, the rest are handled by 
@@ -720,6 +728,8 @@ pcnet32_probe1(unsigned long ioaddr, uns
     lp->name = chipname;
     lp->shared_irq = shared;
     lp->mii_if.full_duplex = fdx;
+    lp->mii_if.phy_id_mask = 0x1f;
+    lp->mii_if.reg_num_mask = 0x1f;
     lp->dxsuflo = dxsuflo;
     lp->ltint = ltint;
     lp->mii = mii;
@@ -806,6 +816,10 @@ pcnet32_probe1(unsigned long ioaddr, uns
     dev->tx_timeout = pcnet32_tx_timeout;
     dev->watchdog_timeo = (5*HZ);
 
+#ifdef CONFIG_NET_POLL_CONTROLLER
+    dev->poll_controller = pcnet32_poll_controller;
+#endif    
+
     /* Fill in the generic fields of the device structure. */
     if (register_netdev(dev))
 	goto err_free_consistent;
@@ -1006,9 +1020,10 @@ pcnet32_init_ring(struct net_device *dev
 	}
 
 	if (lp->rx_dma_addr[i] == 0)
-		lp->rx_dma_addr[i] = pci_map_single(lp->pci_dev, rx_skbuff->tail, rx_skbuff->len, PCI_DMA_FROMDEVICE);
+		lp->rx_dma_addr[i] = pci_map_single(lp->pci_dev,
+			rx_skbuff->tail, PKT_BUF_SZ-2, PCI_DMA_FROMDEVICE);
 	lp->rx_ring[i].base = (u32)le32_to_cpu(lp->rx_dma_addr[i]);
-	lp->rx_ring[i].buf_length = le16_to_cpu(-PKT_BUF_SZ);
+	lp->rx_ring[i].buf_length = le16_to_cpu(2-PKT_BUF_SZ);
 	lp->rx_ring[i].status = le16_to_cpu(0x8000);
     }
     /* The Tx buffer address is filled in as needed, but we do need to clear
@@ -1079,7 +1094,7 @@ pcnet32_tx_timeout (struct net_device *d
 	pcnet32_restart(dev, 0x0042);
 
 	dev->trans_start = jiffies;
-	netif_start_queue(dev);
+	netif_wake_queue(dev);
 
 	spin_unlock_irqrestore(&lp->lock, flags);
 }
@@ -1105,9 +1120,10 @@ pcnet32_start_xmit(struct sk_buff *skb, 
      * interrupt when that option is available to us.
      */
     status = 0x8300;
+    entry = (lp->cur_tx - lp->dirty_tx) & TX_RING_MOD_MASK;
     if ((lp->ltint) &&
-	((lp->cur_tx - lp->dirty_tx == TX_RING_SIZE/2) ||
-	 (lp->cur_tx - lp->dirty_tx >= TX_RING_SIZE-2)))
+	((entry == TX_RING_SIZE/2) ||
+	 (entry >= TX_RING_SIZE-2)))
     {
 	/* Enable Successful-TxDone interrupt if we have
 	 * 1/2 of, or nearly all of, our ring buffer Tx'd
@@ -1122,7 +1138,7 @@ pcnet32_start_xmit(struct sk_buff *skb, 
     /* Mask to ring buffer boundary. */
     entry = lp->cur_tx & TX_RING_MOD_MASK;
   
-    /* Caution: the write order is important here, set the base address
+    /* Caution: the write order is important here, set the status
        with the "ownership" bits last. */
 
     lp->tx_ring[entry].length = le16_to_cpu(-skb->len);
@@ -1144,7 +1160,7 @@ pcnet32_start_xmit(struct sk_buff *skb, 
     dev->trans_start = jiffies;
 
     if (lp->tx_ring[(entry+1) & TX_RING_MOD_MASK].base == 0)
-	netif_start_queue(dev);
+	netif_wake_queue(dev);
     else {
 	lp->tx_full = 1;
 	netif_stop_queue(dev);
@@ -1191,8 +1207,9 @@ pcnet32_interrupt(int irq, void *dev_id,
 
 	if (csr0 & 0x0200) {		/* Tx-done interrupt */
 	    unsigned int dirty_tx = lp->dirty_tx;
+	    int delta;
 
-	    while (dirty_tx < lp->cur_tx) {
+	    while (dirty_tx != lp->cur_tx) {
 		int entry = dirty_tx & TX_RING_MOD_MASK;
 		int status = (short)le16_to_cpu(lp->tx_ring[entry].status);
 			
@@ -1246,15 +1263,17 @@ pcnet32_interrupt(int irq, void *dev_id,
 		dirty_tx++;
 	    }
 
-	    if (lp->cur_tx - dirty_tx >= TX_RING_SIZE) {
+	    delta = (lp->cur_tx - dirty_tx) & (TX_RING_MOD_MASK + TX_RING_SIZE);
+	    if (delta >= TX_RING_SIZE) {
 		printk(KERN_ERR "%s: out-of-sync dirty pointer, %d vs. %d, full=%d.\n",
 			dev->name, dirty_tx, lp->cur_tx, lp->tx_full);
 		dirty_tx += TX_RING_SIZE;
+		delta -= TX_RING_SIZE;
 	    }
 
 	    if (lp->tx_full &&
 		netif_queue_stopped(dev) &&
-		dirty_tx > lp->cur_tx - TX_RING_SIZE + 2) {
+		delta < TX_RING_SIZE - 2) {
 		/* The ring is no longer full, clear tbusy. */
 		lp->tx_full = 0;
 		netif_wake_queue (dev);
@@ -1344,13 +1363,14 @@ pcnet32_rx(struct net_device *dev)
 		    if ((newskb = dev_alloc_skb (PKT_BUF_SZ))) {
 			skb_reserve (newskb, 2);
 			skb = lp->rx_skbuff[entry];
-			pci_unmap_single(lp->pci_dev, lp->rx_dma_addr[entry], skb->len, PCI_DMA_FROMDEVICE);
+			pci_unmap_single(lp->pci_dev, lp->rx_dma_addr[entry],
+				PKT_BUF_SZ-2, PCI_DMA_FROMDEVICE);
 			skb_put (skb, pkt_len);
 			lp->rx_skbuff[entry] = newskb;
 			newskb->dev = dev;
                         lp->rx_dma_addr[entry] = 
 				pci_map_single(lp->pci_dev, newskb->tail,
-					newskb->len, PCI_DMA_FROMDEVICE);
+					PKT_BUF_SZ-2, PCI_DMA_FROMDEVICE);
 			lp->rx_ring[entry].base = le32_to_cpu(lp->rx_dma_addr[entry]);
 			rx_in_place = 1;
 		    } else
@@ -1379,7 +1399,7 @@ pcnet32_rx(struct net_device *dev)
 		    skb_put(skb,pkt_len);	/* Make room */
 		    pci_dma_sync_single(lp->pci_dev,
 		                        lp->rx_dma_addr[entry],
-		                        PKT_BUF_SZ,
+		                        PKT_BUF_SZ-2,
 		                        PCI_DMA_FROMDEVICE);
 		    eth_copy_and_sum(skb,
 				     (unsigned char *)(lp->rx_skbuff[entry]->tail),
@@ -1396,7 +1416,7 @@ pcnet32_rx(struct net_device *dev)
 	 * The docs say that the buffer length isn't touched, but Andrew Boyd
 	 * of QNX reports that some revs of the 79C965 clear it.
 	 */
-	lp->rx_ring[entry].buf_length = le16_to_cpu(-PKT_BUF_SZ);
+	lp->rx_ring[entry].buf_length = le16_to_cpu(2-PKT_BUF_SZ);
 	lp->rx_ring[entry].status |= le16_to_cpu(0x8000);
 	entry = (++lp->cur_rx) & RX_RING_MOD_MASK;
     }
@@ -1436,7 +1456,8 @@ pcnet32_close(struct net_device *dev)
     for (i = 0; i < RX_RING_SIZE; i++) {
 	lp->rx_ring[i].status = 0;			    
 	if (lp->rx_skbuff[i]) {
-            pci_unmap_single(lp->pci_dev, lp->rx_dma_addr[i], lp->rx_skbuff[i]->len, PCI_DMA_FROMDEVICE);
+            pci_unmap_single(lp->pci_dev, lp->rx_dma_addr[i], PKT_BUF_SZ-2,
+		    PCI_DMA_FROMDEVICE);
 	    dev_kfree_skb(lp->rx_skbuff[i]);
         }
 	lp->rx_skbuff[i] = NULL;
@@ -1625,12 +1646,18 @@ static int pcnet32_ethtool_ioctl (struct
 	}
 	/* restart autonegotiation */
 	case ETHTOOL_NWAY_RST: {
-		return mii_nway_restart(&lp->mii_if);
+		int r;
+		spin_lock_irq(&lp->lock);
+		r = mii_nway_restart(&lp->mii_if);
+		spin_unlock_irq(&lp->lock);
+		return r;
 	}
 	/* get link status */
 	case ETHTOOL_GLINK: {
 		struct ethtool_value edata = {ETHTOOL_GLINK};
+		spin_lock_irq(&lp->lock);
 		edata.data = mii_link_ok(&lp->mii_if);
+		spin_unlock_irq(&lp->lock);
 		if (copy_to_user(useraddr, &edata, sizeof(edata)))
 			return -EFAULT;
 		return 0;
@@ -1661,45 +1688,37 @@ static int pcnet32_ethtool_ioctl (struct
 
 static int pcnet32_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
 {
-    unsigned long ioaddr = dev->base_addr;
     struct pcnet32_private *lp = dev->priv;	 
     struct mii_ioctl_data *data = (struct mii_ioctl_data *)&rq->ifr_data;
-    int phyaddr = lp->a.read_bcr (ioaddr, 33);
+    int rc;
+    unsigned long flags;
 
     if (cmd == SIOCETHTOOL)
 	return pcnet32_ethtool_ioctl(dev, (void *) rq->ifr_data);
 
+    /* SIOC[GS]MIIxxx ioctls */
     if (lp->mii) {
-	switch(cmd) {
-	case SIOCGMIIPHY:		/* Get address of MII PHY in use. */
-	    data->phy_id = (phyaddr >> 5) & 0x1f;
-	    /* Fall Through */
-	case SIOCGMIIREG:		/* Read MII PHY register. */
-	    lp->a.write_bcr (ioaddr, 33, ((data->phy_id & 0x1f) << 5) | (data->reg_num & 0x1f));
-	    data->val_out = lp->a.read_bcr (ioaddr, 34);
-	    lp->a.write_bcr (ioaddr, 33, phyaddr);
-	    return 0;
-	case SIOCSMIIREG:		/* Write MII PHY register. */
-	    if (!capable(CAP_NET_ADMIN))
-		return -EPERM;
-	    lp->a.write_bcr (ioaddr, 33, ((data->phy_id & 0x1f) << 5) | (data->reg_num & 0x1f));
-	    lp->a.write_bcr (ioaddr, 34, data->val_in);
-	    lp->a.write_bcr (ioaddr, 33, phyaddr);
-	    return 0;
-	default:
-	    return -EOPNOTSUPP;
-	}
+	spin_lock_irqsave(&lp->lock, flags);
+	rc = generic_mii_ioctl(&lp->mii_if, data, cmd, NULL);
+	spin_unlock_irqrestore(&lp->lock, flags);
+    } else {
+	rc = -EOPNOTSUPP;
     }
-    return -EOPNOTSUPP;
+
+    return rc;
 }
 
 static void pcnet32_watchdog(struct net_device *dev)
 {
     struct pcnet32_private *lp = dev->priv;
+    unsigned long flags;
 
     /* Print the link status if it has changed */
-    if (lp->mii)
+    if (lp->mii) {
+	spin_lock_irqsave(&lp->lock, flags);
 	mii_check_media (&lp->mii_if, 1, 0);
+	spin_unlock_irqrestore(&lp->lock, flags);
+    }
 
     mod_timer (&(lp->watchdog_timer), PCNET32_WATCHDOG_TIMEOUT);
 }
--- diff/drivers/net/ppp_deflate.c	2004-02-18 08:54:10.000000000 +0000
+++ source/drivers/net/ppp_deflate.c	2004-02-23 13:56:43.000000000 +0000
@@ -655,3 +655,5 @@ void __exit deflate_cleanup(void)
 module_init(deflate_init);
 module_exit(deflate_cleanup);
 MODULE_LICENSE("Dual BSD/GPL");
+MODULE_ALIAS("ppp-compress-" __stringify(CI_DEFLATE));
+MODULE_ALIAS("ppp-compress-" __stringify(CI_DEFLATE_DRAFT));
--- diff/drivers/net/ppp_generic.c	2004-02-18 08:54:10.000000000 +0000
+++ source/drivers/net/ppp_generic.c	2004-02-23 13:56:43.000000000 +0000
@@ -675,20 +675,25 @@ static int ppp_ioctl(struct inode *inode
 
 		if (copy_from_user(&uprog, (void __user *) arg, sizeof(uprog)))
 			break;
-		err = -ENOMEM;
-		len = uprog.len * sizeof(struct sock_filter);
-		code = kmalloc(len, GFP_KERNEL);
-		if (code == 0)
-			break;
-		err = -EFAULT;
-		if (copy_from_user(code, (void __user *) uprog.filter, len)) {
-			kfree(code);
-			break;
-		}
-		err = sk_chk_filter(code, uprog.len);
-		if (err) {
-			kfree(code);
+		err = -EINVAL;
+		if (uprog.len > BPF_MAXINSNS)
 			break;
+		err = -ENOMEM;
+		if (uprog.len > 0) {
+			len = uprog.len * sizeof(struct sock_filter);
+			code = kmalloc(len, GFP_KERNEL);
+			if (code == NULL)
+				break;
+			err = -EFAULT;
+			if (copy_from_user(code, (void __user *) uprog.filter, len)) {
+				kfree(code);
+				break;
+			}
+			err = sk_chk_filter(code, uprog.len);
+			if (err) {
+				kfree(code);
+				break;
+			}
 		}
 		filtp = (cmd == PPPIOCSPASS)? &ppp->pass_filter: &ppp->active_filter;
 		ppp_lock(ppp);
@@ -2668,3 +2673,4 @@ EXPORT_SYMBOL(all_ppp_units); /* for deb
 EXPORT_SYMBOL(all_channels); /* for debugging */
 MODULE_LICENSE("GPL");
 MODULE_ALIAS_CHARDEV_MAJOR(PPP_MAJOR);
+MODULE_ALIAS("/dev/ppp");
--- diff/drivers/net/pppoe.c	2004-02-18 08:54:10.000000000 +0000
+++ source/drivers/net/pppoe.c	2004-02-23 13:56:43.000000000 +0000
@@ -67,7 +67,6 @@
 #include <linux/ppp_channel.h>
 #include <linux/ppp_defs.h>
 #include <linux/if_ppp.h>
-#include <linux/if_pppvar.h>
 #include <linux/notifier.h>
 #include <linux/file.h>
 #include <linux/proc_fs.h>
--- diff/drivers/net/r8169.c	2003-12-19 09:51:11.000000000 +0000
+++ source/drivers/net/r8169.c	2004-02-23 13:56:43.000000000 +0000
@@ -56,9 +56,11 @@ VERSION 1.2	<2002/11/30>
 	        printk( "Assertion failed! %s,%s,%s,line=%d\n",	\
         	#expr,__FILE__,__FUNCTION__,__LINE__);		\
         }
+#define dprintk(fmt, args...)	do { printk(PFX fmt, ## args) } while (0)
 #else
 #define assert(expr) do {} while (0)
-#endif
+#define dprintk(fmt, args...)	do {} while (0)
+#endif /* RTL8169_DEBUG */
 
 /* media options */
 #define MAX_UNITS 8
@@ -89,9 +91,12 @@ static int multicast_filter_limit = 32;
 #define NUM_TX_DESC	64	/* Number of Tx descriptor registers */
 #define NUM_RX_DESC	64	/* Number of Rx descriptor registers */
 #define RX_BUF_SIZE	1536	/* Rx Buffer size */
+#define R8169_TX_RING_BYTES	(NUM_TX_DESC * sizeof(struct TxDesc))
+#define R8169_RX_RING_BYTES	(NUM_RX_DESC * sizeof(struct RxDesc))
 
 #define RTL_MIN_IO_SIZE 0x80
-#define TX_TIMEOUT  (6*HZ)
+#define RTL8169_TX_TIMEOUT	(6*HZ)
+#define RTL8169_PHY_TIMEOUT	(HZ) 
 
 /* write/read MMIO register */
 #define RTL_W8(reg, val8)	writeb ((val8), ioaddr + (reg))
@@ -101,11 +106,35 @@ static int multicast_filter_limit = 32;
 #define RTL_R16(reg)		readw (ioaddr + (reg))
 #define RTL_R32(reg)		((unsigned long) readl (ioaddr + (reg)))
 
-static struct {
+enum mac_version {
+	RTL_GIGA_MAC_VER_B = 0x00,
+	/* RTL_GIGA_MAC_VER_C = 0x03, */
+	RTL_GIGA_MAC_VER_D = 0x01,
+	RTL_GIGA_MAC_VER_E = 0x02
+};
+
+enum phy_version {
+	RTL_GIGA_PHY_VER_C = 0x03, /* PHY Reg 0x03 bit0-3 == 0x0000 */
+	RTL_GIGA_PHY_VER_D = 0x04, /* PHY Reg 0x03 bit0-3 == 0x0000 */
+	RTL_GIGA_PHY_VER_E = 0x05, /* PHY Reg 0x03 bit0-3 == 0x0000 */
+	RTL_GIGA_PHY_VER_F = 0x06, /* PHY Reg 0x03 bit0-3 == 0x0001 */
+	RTL_GIGA_PHY_VER_G = 0x07, /* PHY Reg 0x03 bit0-3 == 0x0002 */
+};
+
+
+#define _R(NAME,MAC,MASK) \
+	{ .name = NAME, .mac_version = MAC, .RxConfigMask = MASK }
+
+const static struct {
 	const char *name;
-} board_info[] __devinitdata = {
-	{
-"RealTek RTL8169 Gigabit Ethernet"},};
+	u8 mac_version;
+	u32 RxConfigMask;	/* Clears the bits supported by this chip */
+} rtl_chip_info[] = {
+	_R("RTL8169",		RTL_GIGA_MAC_VER_B, 0xff7e1880),
+	_R("RTL8169s/8110s",	RTL_GIGA_MAC_VER_D, 0xff7e1880),
+	_R("RTL8169s/8110s",	RTL_GIGA_MAC_VER_E, 0xff7e1880)
+};
+#undef _R
 
 static struct pci_device_id rtl8169_pci_tbl[] = {
 	{0x10ec, 0x8169, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
@@ -114,6 +143,8 @@ static struct pci_device_id rtl8169_pci_
 
 MODULE_DEVICE_TABLE(pci, rtl8169_pci_tbl);
 
+static int rx_copybreak = 200;
+
 enum RTL8169_registers {
 	MAC0 = 0,		/* Ethernet hardware address. */
 	MAR0 = 8,		/* Multicast filter. */
@@ -242,14 +273,6 @@ enum RTL8169_register_content {
 	TBILinkOK = 0x02000000,
 };
 
-const static struct {
-	const char *name;
-	u8 version;		/* depend on RTL8169 docs */
-	u32 RxConfigMask;	/* should clear the bits supported by this chip */
-} rtl_chip_info[] = {
-	{
-"RTL-8169", 0x00, 0xff7e1880,},};
-
 enum _DescStatusBit {
 	OWNbit = 0x80000000,
 	EORbit = 0x40000000,
@@ -257,6 +280,8 @@ enum _DescStatusBit {
 	LSbit = 0x10000000,
 };
 
+#define RsvdMask	0x3fffc000
+
 struct TxDesc {
 	u32 status;
 	u32 vlan_tag;
@@ -277,28 +302,33 @@ struct rtl8169_private {
 	struct net_device_stats stats;	/* statistics of net device */
 	spinlock_t lock;	/* spin lock flag */
 	int chipset;
-	unsigned long cur_rx;	/* Index into the Rx descriptor buffer of next Rx pkt. */
-	unsigned long cur_tx;	/* Index into the Tx descriptor buffer of next Rx pkt. */
-	unsigned long dirty_tx;
-	unsigned char *TxDescArrays;	/* Index of Tx Descriptor buffer */
-	unsigned char *RxDescArrays;	/* Index of Rx Descriptor buffer */
+	int mac_version;
+	int phy_version;
+	u32 cur_rx; /* Index into the Rx descriptor buffer of next Rx pkt. */
+	u32 cur_tx; /* Index into the Tx descriptor buffer of next Rx pkt. */
+	u32 dirty_rx;
+	u32 dirty_tx;
 	struct TxDesc *TxDescArray;	/* Index of 256-alignment Tx Descriptor buffer */
 	struct RxDesc *RxDescArray;	/* Index of 256-alignment Rx Descriptor buffer */
-	unsigned char *RxBufferRings;	/* Index of Rx Buffer  */
-	unsigned char *RxBufferRing[NUM_RX_DESC];	/* Index of Rx Buffer array */
+	dma_addr_t TxPhyAddr;
+	dma_addr_t RxPhyAddr;
+	struct sk_buff *Rx_skbuff[NUM_RX_DESC];	/* Rx data buffers */
 	struct sk_buff *Tx_skbuff[NUM_TX_DESC];	/* Index of Transmit data buffer */
+	struct timer_list timer;
+	unsigned long phy_link_down_cnt;
 };
 
 MODULE_AUTHOR("Realtek");
 MODULE_DESCRIPTION("RealTek RTL-8169 Gigabit Ethernet driver");
 MODULE_PARM(media, "1-" __MODULE_STRING(MAX_UNITS) "i");
+MODULE_PARM(rx_copybreak, "i");
 MODULE_LICENSE("GPL");
 
 static int rtl8169_open(struct net_device *dev);
 static int rtl8169_start_xmit(struct sk_buff *skb, struct net_device *dev);
 static irqreturn_t rtl8169_interrupt(int irq, void *dev_instance,
 			      struct pt_regs *regs);
-static void rtl8169_init_ring(struct net_device *dev);
+static int rtl8169_init_ring(struct net_device *dev);
 static void rtl8169_hw_start(struct net_device *dev);
 static int rtl8169_close(struct net_device *dev);
 static void rtl8169_set_rx_mode(struct net_device *dev);
@@ -306,11 +336,15 @@ static void rtl8169_tx_timeout(struct ne
 static struct net_device_stats *rtl8169_get_stats(struct net_device *netdev);
 
 static const u16 rtl8169_intr_mask =
-    SYSErr | PCSTimeout | RxUnderrun | RxOverflow | RxFIFOOver | TxErr | TxOK |
-    RxErr | RxOK;
+    RxUnderrun | RxOverflow | RxFIFOOver | TxErr | TxOK | RxErr | RxOK;
 static const unsigned int rtl8169_rx_config =
     (RX_FIFO_THRESH << RxCfgFIFOShift) | (RX_DMA_BURST << RxCfgDMAShift);
 
+#define PHY_Cap_10_Half_Or_Less PHY_Cap_10_Half
+#define PHY_Cap_10_Full_Or_Less PHY_Cap_10_Full | PHY_Cap_10_Half_Or_Less
+#define PHY_Cap_100_Half_Or_Less PHY_Cap_100_Half | PHY_Cap_10_Full_Or_Less
+#define PHY_Cap_100_Full_Or_Less PHY_Cap_100_Full | PHY_Cap_100_Half_Or_Less
+
 void
 mdio_write(void *ioaddr, int RegAddr, int value)
 {
@@ -342,13 +376,258 @@ mdio_read(void *ioaddr, int RegAddr)
 		if (RTL_R32(PHYAR) & 0x80000000) {
 			value = (int) (RTL_R32(PHYAR) & 0xFFFF);
 			break;
-		} else {
-			udelay(100);
 		}
+		udelay(100);
 	}
 	return value;
 }
 
+static void rtl8169_write_gmii_reg_bit(void *ioaddr, int reg, int bitnum,
+				       int bitval)
+{
+	int val;
+
+	val = mdio_read(ioaddr, reg);
+	val = (bitval == 1) ?
+		val | (bitval << bitnum) :  val & ~(0x0001 << bitnum);
+	mdio_write(ioaddr, reg, val & 0xffff); 
+}
+
+static void rtl8169_get_mac_version(struct rtl8169_private *tp, void *ioaddr)
+{
+	const struct {
+		u32 mask;
+		int mac_version;
+	} mac_info[] = {
+		{ 0x1 << 26,	RTL_GIGA_MAC_VER_E },
+		{ 0x1 << 23,	RTL_GIGA_MAC_VER_D }, 
+		{ 0x00000000,	RTL_GIGA_MAC_VER_B } /* Catch-all */
+	}, *p = mac_info;
+	u32 reg;
+
+	reg = RTL_R32(TxConfig) & 0x7c800000;
+	while ((reg & p->mask) != p->mask)
+		p++;
+	tp->mac_version = p->mac_version;
+}
+
+static void rtl8169_print_mac_version(struct rtl8169_private *tp)
+{
+	struct {
+		int version;
+		char *msg;
+	} mac_print[] = {
+		{ RTL_GIGA_MAC_VER_E, "RTL_GIGA_MAC_VER_E" },
+		{ RTL_GIGA_MAC_VER_D, "RTL_GIGA_MAC_VER_D" },
+		{ RTL_GIGA_MAC_VER_B, "RTL_GIGA_MAC_VER_B" },
+		{ 0, NULL }
+	}, *p;
+
+	for (p = mac_print; p->msg; p++) {
+		if (tp->mac_version == p->version) {
+			dprintk("mac_version == %s (%04d)\n", p->msg,
+				  p->version);
+			return;
+		}
+	}
+	dprintk("mac_version == Unknown\n");
+}
+
+static void rtl8169_get_phy_version(struct rtl8169_private *tp, void *ioaddr)
+{
+	const struct {
+		u16 mask;
+		u16 set;
+		int phy_version;
+	} phy_info[] = {
+		{ 0x000f, 0x0002, RTL_GIGA_PHY_VER_G },
+		{ 0x000f, 0x0001, RTL_GIGA_PHY_VER_F },
+		{ 0x000f, 0x0000, RTL_GIGA_PHY_VER_E },
+		{ 0x0000, 0x0000, RTL_GIGA_PHY_VER_D } /* Catch-all */
+	}, *p = phy_info;
+	u16 reg;
+
+	reg = mdio_read(ioaddr, 3) & 0xffff;
+	while ((reg & p->mask) != p->set)
+		p++;
+	tp->phy_version = p->phy_version;
+}
+
+static void rtl8169_print_phy_version(struct rtl8169_private *tp)
+{
+	struct {
+		int version;
+		char *msg;
+		u32 reg;
+	} phy_print[] = {
+		{ RTL_GIGA_PHY_VER_G, "RTL_GIGA_PHY_VER_G", 0x0002 },
+		{ RTL_GIGA_PHY_VER_F, "RTL_GIGA_PHY_VER_F", 0x0001 },
+		{ RTL_GIGA_PHY_VER_E, "RTL_GIGA_PHY_VER_E", 0x0000 },
+		{ RTL_GIGA_PHY_VER_D, "RTL_GIGA_PHY_VER_D", 0x0000 },
+		{ 0, NULL, 0x0000 }
+	}, *p;
+
+	for (p = phy_print; p->msg; p++) {
+		if (tp->phy_version == p->version) {
+			dprintk("phy_version == %s (%04x)\n", p->msg, p->reg);
+			return;
+		}
+	}
+	dprintk("phy_version == Unknown\n");
+}
+
+static void rtl8169_hw_phy_config(struct net_device *dev)
+{
+	struct rtl8169_private *tp = dev->priv;
+	void *ioaddr = tp->mmio_addr;
+	struct {
+		u16 regs[5]; /* Beware of bit-sign propagation */
+	} phy_magic[5] = { {
+		{ 0x0000,	//w 4 15 12 0
+		  0x00a1,	//w 3 15 0 00a1
+		  0x0008,	//w 2 15 0 0008
+		  0x1020,	//w 1 15 0 1020
+		  0x1000 } },{	//w 0 15 0 1000
+		{ 0x7000,	//w 4 15 12 7
+		  0xff41,	//w 3 15 0 ff41
+		  0xde60,	//w 2 15 0 de60
+		  0x0140,	//w 1 15 0 0140
+		  0x0077 } },{	//w 0 15 0 0077
+		{ 0xa000,	//w 4 15 12 a
+		  0xdf01,	//w 3 15 0 df01
+		  0xdf20,	//w 2 15 0 df20
+		  0xff95,	//w 1 15 0 ff95
+		  0xfa00 } },{	//w 0 15 0 fa00
+		{ 0xb000,	//w 4 15 12 b
+		  0xff41,	//w 3 15 0 ff41
+		  0xde20,	//w 2 15 0 de20
+		  0x0140,	//w 1 15 0 0140
+		  0x00bb } },{	//w 0 15 0 00bb
+		{ 0xf000,	//w 4 15 12 f
+		  0xdf01,	//w 3 15 0 df01
+		  0xdf20,	//w 2 15 0 df20
+		  0xff95,	//w 1 15 0 ff95
+		  0xbf00 }	//w 0 15 0 bf00
+		}
+	}, *p = phy_magic;
+	int i;
+
+	rtl8169_print_mac_version(tp);
+	rtl8169_print_phy_version(tp);
+
+	if (tp->mac_version <= RTL_GIGA_MAC_VER_B)
+		return;
+	if (tp->phy_version >= RTL_GIGA_PHY_VER_F) 
+		return;
+
+	dprintk("MAC version != 0 && PHY version == 0 or 1\n");
+	dprintk("Do final_reg2.cfg\n");
+
+	/* Shazam ! */
+
+	// phy config for RTL8169s mac_version C chip
+	mdio_write(ioaddr, 31, 0x0001);			//w 31 2 0 1
+	mdio_write(ioaddr, 21, 0x1000);			//w 21 15 0 1000
+	mdio_write(ioaddr, 24, 0x65c7);			//w 24 15 0 65c7
+	rtl8169_write_gmii_reg_bit(ioaddr, 4, 11, 0);	//w 4 11 11 0
+
+	for (i = 0; i < ARRAY_SIZE(phy_magic); i++, p++) {
+		int val, pos = 4;
+
+		val = (mdio_read(ioaddr, pos) & 0x0fff) | (p->regs[0] & 0xffff);
+		mdio_write(ioaddr, pos, val);
+		while (--pos >= 0)
+			mdio_write(ioaddr, pos, p->regs[4 - pos] & 0xffff);
+		rtl8169_write_gmii_reg_bit(ioaddr, 4, 11, 1); //w 4 11 11 1
+		rtl8169_write_gmii_reg_bit(ioaddr, 4, 11, 0); //w 4 11 11 0
+	}
+	mdio_write(ioaddr, 31, 0x0000); //w 31 2 0 0
+}
+
+static void rtl8169_hw_phy_reset(struct net_device *dev)
+{
+	struct rtl8169_private *tp = dev->priv;
+	void *ioaddr = tp->mmio_addr;
+	int i, val;
+
+	printk(KERN_WARNING PFX "%s: Reset RTL8169s PHY\n", dev->name);
+
+	val = (mdio_read(ioaddr, 0) | 0x8000) & 0xffff;
+	mdio_write(ioaddr, 0, val);
+
+	for (i = 50; i >= 0; i--) {
+		if (!(mdio_read(ioaddr, 0) & 0x8000))
+			break;
+		udelay(100); /* Gross */
+	}
+
+	if (i < 0) {
+		printk(KERN_WARNING PFX "%s: no PHY Reset ack. Giving up.\n",
+		       dev->name);
+	}
+}
+
+static void rtl8169_phy_timer(unsigned long __opaque)
+{
+	struct net_device *dev = (struct net_device *)__opaque;
+	struct rtl8169_private *tp = dev->priv;
+	struct timer_list *timer = &tp->timer;
+	void *ioaddr = tp->mmio_addr;
+
+	assert(tp->mac_version > RTL_GIGA_MAC_VER_B);
+	assert(tp->phy_version < RTL_GIGA_PHY_VER_G);
+
+	if (RTL_R8(PHYstatus) & LinkStatus)
+		tp->phy_link_down_cnt = 0;
+	else {
+		tp->phy_link_down_cnt++;
+		if (tp->phy_link_down_cnt >= 12) {
+			int reg;
+
+			// If link on 1000, perform phy reset.
+			reg = mdio_read(ioaddr, PHY_1000_CTRL_REG);
+			if (reg & PHY_Cap_1000_Full) 
+				rtl8169_hw_phy_reset(dev);
+
+			tp->phy_link_down_cnt = 0;
+		}
+	}
+
+	mod_timer(timer, RTL8169_PHY_TIMEOUT);
+}
+
+static inline void rtl8169_delete_timer(struct net_device *dev)
+{
+	struct rtl8169_private *tp = dev->priv;
+	struct timer_list *timer = &tp->timer;
+
+	if ((tp->mac_version <= RTL_GIGA_MAC_VER_B) ||
+	    (tp->phy_version >= RTL_GIGA_PHY_VER_G))
+		return;
+
+	del_timer_sync(timer);
+
+	tp->phy_link_down_cnt = 0;
+}
+
+static inline void rtl8169_request_timer(struct net_device *dev)
+{
+	struct rtl8169_private *tp = dev->priv;
+	struct timer_list *timer = &tp->timer;
+
+	if ((tp->mac_version <= RTL_GIGA_MAC_VER_B) ||
+	    (tp->phy_version >= RTL_GIGA_PHY_VER_G))
+		return;
+
+	tp->phy_link_down_cnt = 0;
+
+	init_timer(timer);
+	timer->expires = jiffies + RTL8169_PHY_TIMEOUT;
+	timer->data = (unsigned long)(dev);
+	timer->function = rtl8169_phy_timer;
+	add_timer(timer);
+}
+
 static int __devinit
 rtl8169_init_board(struct pci_dev *pdev, struct net_device **dev_out,
 		   void **ioaddr_out)
@@ -356,9 +635,9 @@ rtl8169_init_board(struct pci_dev *pdev,
 	void *ioaddr = NULL;
 	struct net_device *dev;
 	struct rtl8169_private *tp;
-	int rc, i;
 	unsigned long mmio_start, mmio_end, mmio_flags, mmio_len;
-	u32 tmp;
+	int rc, i, acpi_idle_state = 0, pm_cap;
+
 
 	assert(pdev != NULL);
 	assert(ioaddr_out != NULL);
@@ -379,8 +658,22 @@ rtl8169_init_board(struct pci_dev *pdev,
 
 	// enable device (incl. PCI PM wakeup and hotplug setup)
 	rc = pci_enable_device(pdev);
-	if (rc)
+	if (rc) {
+		printk(KERN_ERR PFX "%s: unable to enable device\n", pdev->slot_name);
 		goto err_out;
+	}
+
+	/* save power state before pci_enable_device overwrites it */
+	pm_cap = pci_find_capability(pdev, PCI_CAP_ID_PM);
+	if (pm_cap) {
+		u16 pwr_command;
+
+		pci_read_config_word(pdev, pm_cap + PCI_PM_CTRL, &pwr_command);
+		acpi_idle_state = pwr_command & PCI_PM_CTRL_STATE_MASK;
+	} else {
+		printk(KERN_ERR PFX "Cannot find PowerManagement capability, aborting.\n");
+		goto err_out_free_res;
+	}
 
 	mmio_start = pci_resource_start(pdev, 1);
 	mmio_end = pci_resource_end(pdev, 1);
@@ -402,8 +695,10 @@ rtl8169_init_board(struct pci_dev *pdev,
 	}
 
 	rc = pci_request_regions(pdev, dev->name);
-	if (rc)
+	if (rc) {
+		printk(KERN_ERR PFX "%s: Could not request regions.\n", pdev->slot_name);
 		goto err_out_disable;
+	}
 
 	// enable PCI bus-mastering
 	pci_set_master(pdev);
@@ -420,30 +715,32 @@ rtl8169_init_board(struct pci_dev *pdev,
 	RTL_W8(ChipCmd, CmdReset);
 
 	// Check that the chip has finished the reset.
-	for (i = 1000; i > 0; i--)
+	for (i = 1000; i > 0; i--) {
 		if ((RTL_R8(ChipCmd) & CmdReset) == 0)
 			break;
-		else
-			udelay(10);
+		udelay(10);
+	}
 
-	// identify chip attached to board
-	tmp = RTL_R32(TxConfig);
-	tmp = ((tmp & 0x7c000000) + ((tmp & 0x00800000) << 2)) >> 24;
-
-	for (i = ARRAY_SIZE(rtl_chip_info) - 1; i >= 0; i--)
-		if (tmp == rtl_chip_info[i].version) {
-			tp->chipset = i;
-			goto match;
-		}
-	//if unknown chip, assume array element #0, original RTL-8169 in this case
-	printk(KERN_DEBUG PFX
-	       "PCI device %s: unknown chip version, assuming RTL-8169\n",
-	       pci_name(pdev));
-	printk(KERN_DEBUG PFX "PCI device %s: TxConfig = 0x%lx\n",
-	       pci_name(pdev), (unsigned long) RTL_R32(TxConfig));
-	tp->chipset = 0;
+	// Identify chip attached to board
+	rtl8169_get_mac_version(tp, ioaddr);
+	rtl8169_get_phy_version(tp, ioaddr);
+
+	rtl8169_print_mac_version(tp);
+	rtl8169_print_phy_version(tp);
+
+	for (i = ARRAY_SIZE(rtl_chip_info) - 1; i >= 0; i--) {
+		if (tp->mac_version == rtl_chip_info[i].mac_version)
+			break;
+	}
+	if (i < 0) {
+		/* Unknown chip: assume array element #0, original RTL-8169 */
+		printk(KERN_DEBUG PFX
+		       "PCI device %s: unknown chip version, assuming %s\n",
+		       pci_name(pdev), rtl_chip_info[0].name);
+		i++;
+	}
+	tp->chipset = i;
 
-match:
 	*ioaddr_out = ioaddr;
 	*dev_out = dev;
 	return 0;
@@ -499,7 +796,7 @@ rtl8169_init_one(struct pci_dev *pdev, c
 	dev->stop = rtl8169_close;
 	dev->tx_timeout = rtl8169_tx_timeout;
 	dev->set_multicast_list = rtl8169_set_rx_mode;
-	dev->watchdog_timeo = TX_TIMEOUT;
+	dev->watchdog_timeo = RTL8169_TX_TIMEOUT;
 	dev->irq = pdev->irq;
 	dev->base_addr = (unsigned long) ioaddr;
 //      dev->do_ioctl           = mii_ioctl;
@@ -528,12 +825,29 @@ rtl8169_init_one(struct pci_dev *pdev, c
 	       "%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x, "
 	       "IRQ %d\n",
 	       dev->name,
-	       board_info[ent->driver_data].name,
+	       rtl_chip_info[ent->driver_data].name,
 	       dev->base_addr,
 	       dev->dev_addr[0], dev->dev_addr[1],
 	       dev->dev_addr[2], dev->dev_addr[3],
 	       dev->dev_addr[4], dev->dev_addr[5], dev->irq);
 
+	rtl8169_hw_phy_config(dev);
+
+	dprintk("Set MAC Reg C+CR Offset 0x82h = 0x01h\n");
+	RTL_W8(0x82, 0x01);
+
+	if (tp->mac_version < RTL_GIGA_MAC_VER_E) {
+		dprintk("Set PCI Latency=0x40\n");
+		pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 0x40);
+	}
+
+	if (tp->mac_version == RTL_GIGA_MAC_VER_D) {
+		dprintk("Set MAC Reg C+CR Offset 0x82h = 0x01h\n");
+		RTL_W8(0x82, 0x01);
+		dprintk("Set PHY Reg 0x0bh = 0x00h\n");
+		mdio_write(ioaddr, 0x0b, 0x0000); //w 0x0b 15 0 0
+	}
+
 	// if TBI is not endbled
 	if (!(RTL_R8(PHYstatus) & TBI_Enable)) {
 		int val = mdio_read(ioaddr, PHY_AUTO_NEGO_REG);
@@ -546,23 +860,23 @@ rtl8169_init_one(struct pci_dev *pdev, c
 			Cap10_100 = 0, Cap1000 = 0;
 			switch (option) {
 			case _10_Half:
-				Cap10_100 = PHY_Cap_10_Half;
+				Cap10_100 = PHY_Cap_10_Half_Or_Less;
 				Cap1000 = PHY_Cap_Null;
 				break;
 			case _10_Full:
-				Cap10_100 = PHY_Cap_10_Full;
+				Cap10_100 = PHY_Cap_10_Full_Or_Less;
 				Cap1000 = PHY_Cap_Null;
 				break;
 			case _100_Half:
-				Cap10_100 = PHY_Cap_100_Half;
+				Cap10_100 = PHY_Cap_100_Half_Or_Less;
 				Cap1000 = PHY_Cap_Null;
 				break;
 			case _100_Full:
-				Cap10_100 = PHY_Cap_100_Full;
+				Cap10_100 = PHY_Cap_100_Full_Or_Less;
 				Cap1000 = PHY_Cap_Null;
 				break;
 			case _1000_Full:
-				Cap10_100 = PHY_Cap_Null;
+				Cap10_100 = PHY_Cap_100_Full_Or_Less;
 				Cap1000 = PHY_Cap_1000_Full;
 				break;
 			default:
@@ -576,9 +890,7 @@ rtl8169_init_one(struct pci_dev *pdev, c
 
 			// enable 10/100 Full/Half Mode, leave PHY_AUTO_NEGO_REG bit4:0 unchanged
 			mdio_write(ioaddr, PHY_AUTO_NEGO_REG,
-				   PHY_Cap_10_Half | PHY_Cap_10_Full |
-				   PHY_Cap_100_Half | PHY_Cap_100_Full | (val &
-									  0x1F));
+				   PHY_Cap_100_Full_Or_Less | (val & 0x1f));
 
 			// enable 1000 Full Mode
 			mdio_write(ioaddr, PHY_1000_CTRL_REG,
@@ -647,56 +959,96 @@ rtl8169_remove_one(struct pci_dev *pdev)
 	pci_set_drvdata(pdev, NULL);
 }
 
+#ifdef CONFIG_PM
+
+static int rtl8169_suspend(struct pci_dev *pdev, u32 state)
+{
+	struct net_device *dev = pci_get_drvdata(pdev);
+	struct rtl8169_private *tp = dev->priv;
+	void *ioaddr = tp->mmio_addr;
+	unsigned long flags;
+
+	if (!netif_running(dev))
+		return 0;
+	
+	netif_device_detach(dev);
+	netif_stop_queue(dev);
+	spin_lock_irqsave(&tp->lock, flags);
+
+	/* Disable interrupts, stop Rx and Tx */
+	RTL_W16(IntrMask, 0);
+	RTL_W8(ChipCmd, 0);
+		
+	/* Update the error counts. */
+	tp->stats.rx_missed_errors += RTL_R32(RxMissed);
+	RTL_W32(RxMissed, 0);
+	spin_unlock_irqrestore(&tp->lock, flags);
+	
+	return 0;
+}
+
+static int rtl8169_resume(struct pci_dev *pdev)
+{
+	struct net_device *dev = pci_get_drvdata(pdev);
+
+	if (!netif_running(dev))
+	    return 0;
+
+	netif_device_attach(dev);
+	rtl8169_hw_start(dev);
+
+	return 0;
+}
+                                                                                
+#endif /* CONFIG_PM */
+
 static int
 rtl8169_open(struct net_device *dev)
 {
 	struct rtl8169_private *tp = dev->priv;
+	struct pci_dev *pdev = tp->pci_dev;
 	int retval;
-	u8 diff;
-	u32 TxPhyAddr, RxPhyAddr;
 
 	retval =
 	    request_irq(dev->irq, rtl8169_interrupt, SA_SHIRQ, dev->name, dev);
-	if (retval) {
-		return retval;
-	}
+	if (retval < 0)
+		goto out;
 
-	tp->TxDescArrays =
-	    kmalloc(NUM_TX_DESC * sizeof (struct TxDesc) + 256, GFP_KERNEL);
-	// Tx Desscriptor needs 256 bytes alignment;
-	TxPhyAddr = virt_to_bus(tp->TxDescArrays);
-	diff = 256 - (TxPhyAddr - ((TxPhyAddr >> 8) << 8));
-	TxPhyAddr += diff;
-	tp->TxDescArray = (struct TxDesc *) (tp->TxDescArrays + diff);
-
-	tp->RxDescArrays =
-	    kmalloc(NUM_RX_DESC * sizeof (struct RxDesc) + 256, GFP_KERNEL);
-	// Rx Desscriptor needs 256 bytes alignment;
-	RxPhyAddr = virt_to_bus(tp->RxDescArrays);
-	diff = 256 - (RxPhyAddr - ((RxPhyAddr >> 8) << 8));
-	RxPhyAddr += diff;
-	tp->RxDescArray = (struct RxDesc *) (tp->RxDescArrays + diff);
+	retval = -ENOMEM;
 
-	if (tp->TxDescArrays == NULL || tp->RxDescArrays == NULL) {
-		printk(KERN_INFO
-		       "Allocate RxDescArray or TxDescArray failed\n");
-		free_irq(dev->irq, dev);
-		if (tp->TxDescArrays)
-			kfree(tp->TxDescArrays);
-		if (tp->RxDescArrays)
-			kfree(tp->RxDescArrays);
-		return -ENOMEM;
-	}
-	tp->RxBufferRings = kmalloc(RX_BUF_SIZE * NUM_RX_DESC, GFP_KERNEL);
-	if (tp->RxBufferRings == NULL) {
-		printk(KERN_INFO "Allocate RxBufferRing failed\n");
-	}
+	/*
+	 * Rx and Tx desscriptors needs 256 bytes alignment.
+	 * pci_alloc_consistent provides more.
+	 */
+	tp->TxDescArray = pci_alloc_consistent(pdev, R8169_TX_RING_BYTES,
+					       &tp->TxPhyAddr);
+	if (!tp->TxDescArray)
+		goto err_free_irq;
+
+	tp->RxDescArray = pci_alloc_consistent(pdev, R8169_RX_RING_BYTES,
+					       &tp->RxPhyAddr);
+	if (!tp->RxDescArray)
+		goto err_free_tx;
+
+	retval = rtl8169_init_ring(dev);
+	if (retval < 0)
+		goto err_free_rx;
 
-	rtl8169_init_ring(dev);
 	rtl8169_hw_start(dev);
 
-	return 0;
-
+	rtl8169_request_timer(dev);
+out:
+	return retval;
+
+err_free_rx:
+	pci_free_consistent(pdev, R8169_RX_RING_BYTES, tp->RxDescArray,
+			    tp->RxPhyAddr);
+err_free_tx:
+	pci_free_consistent(pdev, R8169_TX_RING_BYTES, tp->TxDescArray,
+			    tp->TxPhyAddr);
+err_free_irq:
+	free_irq(dev->irq, dev);
+	goto out;
 }
 
 static void
@@ -733,11 +1085,17 @@ rtl8169_hw_start(struct net_device *dev)
 	RTL_W32(TxConfig,
 		(TX_DMA_BURST << TxDMAShift) | (InterFrameGap <<
 						TxInterFrameGapShift));
+	RTL_W16(CPlusCmd, RTL_R16(CPlusCmd));
+
+	if (tp->mac_version == RTL_GIGA_MAC_VER_D) {
+		dprintk(KERN_INFO PFX "Set MAC Reg C+CR Offset 0xE0: bit-3 and bit-14 MUST be 1\n");
+		RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) | (1 << 14) | (1 << 3));
+	}
 
 	tp->cur_rx = 0;
 
-	RTL_W32(TxDescStartAddr, virt_to_bus(tp->TxDescArray));
-	RTL_W32(RxDescStartAddr, virt_to_bus(tp->RxDescArray));
+	RTL_W32(TxDescStartAddr, tp->TxPhyAddr);
+	RTL_W32(RxDescStartAddr, tp->RxPhyAddr);
 	RTL_W8(Cfg9346, Cfg9346_Lock);
 	udelay(10);
 
@@ -755,31 +1113,131 @@ rtl8169_hw_start(struct net_device *dev)
 
 }
 
-static void
-rtl8169_init_ring(struct net_device *dev)
+static inline void rtl8169_make_unusable_by_asic(struct RxDesc *desc)
+{
+	desc->buf_addr = 0xdeadbeef;
+	desc->status &= ~cpu_to_le32(OWNbit | RsvdMask);
+}
+
+static void rtl8169_free_rx_skb(struct pci_dev *pdev, struct sk_buff **sk_buff,
+				struct RxDesc *desc)
+{
+	pci_unmap_single(pdev, le32_to_cpu(desc->buf_addr), RX_BUF_SIZE,
+			 PCI_DMA_FROMDEVICE);
+	dev_kfree_skb(*sk_buff);
+	*sk_buff = NULL;
+	rtl8169_make_unusable_by_asic(desc);
+}
+
+static inline void rtl8169_return_to_asic(struct RxDesc *desc)
+{
+	desc->status |= cpu_to_le32(OWNbit + RX_BUF_SIZE);
+}
+
+static inline void rtl8169_give_to_asic(struct RxDesc *desc, dma_addr_t mapping)
+{
+	desc->buf_addr = cpu_to_le32(mapping);
+	desc->status |= cpu_to_le32(OWNbit + RX_BUF_SIZE);
+}
+
+static int rtl8169_alloc_rx_skb(struct pci_dev *pdev, struct net_device *dev,
+				struct sk_buff **sk_buff, struct RxDesc *desc)
+{
+	struct sk_buff *skb;
+	dma_addr_t mapping;
+	int ret = 0;
+
+	skb = dev_alloc_skb(RX_BUF_SIZE);
+	if (!skb)
+		goto err_out;
+
+	skb->dev = dev;
+	skb_reserve(skb, 2);
+	*sk_buff = skb;
+
+	mapping = pci_map_single(pdev, skb->tail, RX_BUF_SIZE,
+				 PCI_DMA_FROMDEVICE);
+
+	rtl8169_give_to_asic(desc, mapping);
+
+out:
+	return ret;
+
+err_out:
+	ret = -ENOMEM;
+	rtl8169_make_unusable_by_asic(desc);
+	goto out;
+}
+
+static void rtl8169_rx_clear(struct rtl8169_private *tp)
 {
-	struct rtl8169_private *tp = dev->priv;
 	int i;
 
-	tp->cur_rx = 0;
-	tp->cur_tx = 0;
-	tp->dirty_tx = 0;
+	for (i = 0; i < NUM_RX_DESC; i++) {
+		if (tp->Rx_skbuff[i]) {
+			rtl8169_free_rx_skb(tp->pci_dev, tp->Rx_skbuff + i,
+					    tp->RxDescArray + i);
+		}
+	}
+}
+
+static u32 rtl8169_rx_fill(struct rtl8169_private *tp, struct net_device *dev,
+			   u32 start, u32 end)
+{
+	u32 cur;
+	
+	for (cur = start; end - cur > 0; cur++) {
+		int ret, i = cur % NUM_RX_DESC;
+
+		if (tp->Rx_skbuff[i])
+			continue;
+			
+		ret = rtl8169_alloc_rx_skb(tp->pci_dev, dev, tp->Rx_skbuff + i,
+					   tp->RxDescArray + i);
+		if (ret < 0)
+			break;
+	}
+	return cur - start;
+}
+
+static inline void rtl8169_mark_as_last_descriptor(struct RxDesc *desc)
+{
+	desc->status |= cpu_to_le32(EORbit);
+}
+
+static int rtl8169_init_ring(struct net_device *dev)
+{
+	struct rtl8169_private *tp = dev->priv;
+
+	tp->cur_rx = tp->dirty_rx = 0;
+	tp->cur_tx = tp->dirty_tx = 0;
 	memset(tp->TxDescArray, 0x0, NUM_TX_DESC * sizeof (struct TxDesc));
 	memset(tp->RxDescArray, 0x0, NUM_RX_DESC * sizeof (struct RxDesc));
 
-	for (i = 0; i < NUM_TX_DESC; i++) {
-		tp->Tx_skbuff[i] = NULL;
-	}
-	for (i = 0; i < NUM_RX_DESC; i++) {
-		if (i == (NUM_RX_DESC - 1))
-			tp->RxDescArray[i].status =
-			    (OWNbit | EORbit) + RX_BUF_SIZE;
-		else
-			tp->RxDescArray[i].status = OWNbit + RX_BUF_SIZE;
+	memset(tp->Tx_skbuff, 0x0, NUM_TX_DESC * sizeof(struct sk_buff *));
+	memset(tp->Rx_skbuff, 0x0, NUM_RX_DESC * sizeof(struct sk_buff *));
 
-		tp->RxBufferRing[i] = &(tp->RxBufferRings[i * RX_BUF_SIZE]);
-		tp->RxDescArray[i].buf_addr = virt_to_bus(tp->RxBufferRing[i]);
-	}
+	if (rtl8169_rx_fill(tp, dev, 0, NUM_RX_DESC) != NUM_RX_DESC)
+		goto err_out;
+
+	rtl8169_mark_as_last_descriptor(tp->RxDescArray + NUM_RX_DESC - 1);
+
+	return 0;
+
+err_out:
+	rtl8169_rx_clear(tp);
+	return -ENOMEM;
+}
+
+static void rtl8169_unmap_tx_skb(struct pci_dev *pdev, struct sk_buff **sk_buff,
+				 struct TxDesc *desc)
+{
+	u32 len = sk_buff[0]->len;
+
+	pci_unmap_single(pdev, le32_to_cpu(desc->buf_addr),
+			 len < ETH_ZLEN ? ETH_ZLEN : len, PCI_DMA_TODEVICE);
+	desc->buf_addr = 0x00;
+	*sk_buff = NULL;
 }
 
 static void
@@ -789,9 +1247,12 @@ rtl8169_tx_clear(struct rtl8169_private 
 
 	tp->cur_tx = 0;
 	for (i = 0; i < NUM_TX_DESC; i++) {
-		if (tp->Tx_skbuff[i] != NULL) {
-			dev_kfree_skb(tp->Tx_skbuff[i]);
-			tp->Tx_skbuff[i] = NULL;
+		struct sk_buff *skb = tp->Tx_skbuff[i];
+
+		if (skb) {
+			rtl8169_unmap_tx_skb(tp->pci_dev, tp->Tx_skbuff + i,
+					     tp->TxDescArray + i);
+			dev_kfree_skb(skb);
 			tp->stats.tx_dropped++;
 		}
 	}
@@ -829,49 +1290,58 @@ rtl8169_start_xmit(struct sk_buff *skb, 
 	struct rtl8169_private *tp = dev->priv;
 	void *ioaddr = tp->mmio_addr;
 	int entry = tp->cur_tx % NUM_TX_DESC;
+	u32 len = skb->len;
 
-	if (skb->len < ETH_ZLEN) {
+	if (unlikely(skb->len < ETH_ZLEN)) {
 		skb = skb_padto(skb, ETH_ZLEN);
-		if (skb == NULL)
-			return 0;
+		if (!skb)
+			goto err_update_stats;
+		len = ETH_ZLEN;
 	}
 	
 	spin_lock_irq(&tp->lock);
 
-	if ((tp->TxDescArray[entry].status & OWNbit) == 0) {
+	if (!(le32_to_cpu(tp->TxDescArray[entry].status) & OWNbit)) {
+		dma_addr_t mapping;
+
+		mapping = pci_map_single(tp->pci_dev, skb->data, len,
+					 PCI_DMA_TODEVICE);
+
 		tp->Tx_skbuff[entry] = skb;
-		tp->TxDescArray[entry].buf_addr = virt_to_bus(skb->data);
-		if (entry != (NUM_TX_DESC - 1))
-			tp->TxDescArray[entry].status =
-			    (OWNbit | FSbit | LSbit) | ((skb->len > ETH_ZLEN) ?
-							skb->len : ETH_ZLEN);
-		else
-			tp->TxDescArray[entry].status =
-			    (OWNbit | EORbit | FSbit | LSbit) |
-			    ((skb->len > ETH_ZLEN) ? skb->len : ETH_ZLEN);
+		tp->TxDescArray[entry].buf_addr = cpu_to_le32(mapping);
 
+		tp->TxDescArray[entry].status = cpu_to_le32(OWNbit | FSbit |
+			LSbit | len | (EORbit * !((entry + 1) % NUM_TX_DESC)));
+			
 		RTL_W8(TxPoll, 0x40);	//set polling bit
 
 		dev->trans_start = jiffies;
 
 		tp->cur_tx++;
-	}
+	} else
+		goto err_drop;
 
-	spin_unlock_irq(&tp->lock);
 
 	if ((tp->cur_tx - NUM_TX_DESC) == tp->dirty_tx) {
 		netif_stop_queue(dev);
 	}
+out:
+	spin_unlock_irq(&tp->lock);
 
 	return 0;
+
+err_drop:
+	dev_kfree_skb(skb);
+err_update_stats:
+	tp->stats.tx_dropped++;
+	goto out;
 }
 
 static void
 rtl8169_tx_interrupt(struct net_device *dev, struct rtl8169_private *tp,
 		     void *ioaddr)
 {
-	unsigned long dirty_tx, tx_left = 0;
-	int entry = tp->cur_tx % NUM_TX_DESC;
+	unsigned long dirty_tx, tx_left;
 
 	assert(dev != NULL);
 	assert(tp != NULL);
@@ -881,14 +1351,21 @@ rtl8169_tx_interrupt(struct net_device *
 	tx_left = tp->cur_tx - dirty_tx;
 
 	while (tx_left > 0) {
-		if ((tp->TxDescArray[entry].status & OWNbit) == 0) {
-			dev_kfree_skb_irq(tp->
-					  Tx_skbuff[dirty_tx % NUM_TX_DESC]);
-			tp->Tx_skbuff[dirty_tx % NUM_TX_DESC] = NULL;
+		int entry = dirty_tx % NUM_TX_DESC;
+
+		if (!(le32_to_cpu(tp->TxDescArray[entry].status) & OWNbit)) {
+			struct sk_buff *skb = tp->Tx_skbuff[entry];
+
+			/* FIXME: is it really accurate for TxErr ? */
+			tp->stats.tx_bytes += skb->len >= ETH_ZLEN ?
+					      skb->len : ETH_ZLEN;
 			tp->stats.tx_packets++;
+			rtl8169_unmap_tx_skb(tp->pci_dev, tp->Tx_skbuff + entry,
+					     tp->TxDescArray + entry);
+			dev_kfree_skb_irq(skb);
+			tp->Tx_skbuff[entry] = NULL;
 			dirty_tx++;
 			tx_left--;
-			entry++;
 		}
 	}
 
@@ -899,70 +1376,102 @@ rtl8169_tx_interrupt(struct net_device *
 	}
 }
 
+static inline int rtl8169_try_rx_copy(struct sk_buff **sk_buff, int pkt_size,
+				      struct RxDesc *desc,
+				      struct net_device *dev)
+{
+	int ret = -1;
+
+	if (pkt_size < rx_copybreak) {
+		struct sk_buff *skb;
+
+		skb = dev_alloc_skb(pkt_size + 2);
+		if (skb) {
+			skb->dev = dev;
+			skb_reserve(skb, 2);
+			eth_copy_and_sum(skb, sk_buff[0]->tail, pkt_size, 0);
+			*sk_buff = skb;
+			rtl8169_return_to_asic(desc);
+			ret = 0;
+		}
+	}
+	return ret;
+}
+
 static void
 rtl8169_rx_interrupt(struct net_device *dev, struct rtl8169_private *tp,
 		     void *ioaddr)
 {
-	int cur_rx;
-	struct sk_buff *skb;
-	int pkt_size = 0;
+	unsigned long cur_rx, rx_left;
+	int delta;
 
 	assert(dev != NULL);
 	assert(tp != NULL);
 	assert(ioaddr != NULL);
 
 	cur_rx = tp->cur_rx;
+	rx_left = NUM_RX_DESC + tp->dirty_rx - cur_rx;
 
-	while ((tp->RxDescArray[cur_rx].status & OWNbit) == 0) {
+	while (rx_left > 0) {
+		int entry = cur_rx % NUM_RX_DESC;
+		u32 status = le32_to_cpu(tp->RxDescArray[entry].status);
 
-		if (tp->RxDescArray[cur_rx].status & RxRES) {
+		if (status & OWNbit)
+			break;
+		if (status & RxRES) {
 			printk(KERN_INFO "%s: Rx ERROR!!!\n", dev->name);
 			tp->stats.rx_errors++;
-			if (tp->RxDescArray[cur_rx].status & (RxRWT | RxRUNT))
+			if (status & (RxRWT | RxRUNT))
 				tp->stats.rx_length_errors++;
-			if (tp->RxDescArray[cur_rx].status & RxCRC)
+			if (status & RxCRC)
 				tp->stats.rx_crc_errors++;
 		} else {
-			pkt_size =
-			    (int) (tp->RxDescArray[cur_rx].
-				   status & 0x00001FFF) - 4;
-			skb = dev_alloc_skb(pkt_size + 2);
-			if (skb != NULL) {
-				skb->dev = dev;
-				skb_reserve(skb, 2);	// 16 byte align the IP fields. //
-				eth_copy_and_sum(skb, tp->RxBufferRing[cur_rx],
-						 pkt_size, 0);
-				skb_put(skb, pkt_size);
-				skb->protocol = eth_type_trans(skb, dev);
-				netif_rx(skb);
-
-				if (cur_rx == (NUM_RX_DESC - 1))
-					tp->RxDescArray[cur_rx].status =
-					    (OWNbit | EORbit) + RX_BUF_SIZE;
-				else
-					tp->RxDescArray[cur_rx].status =
-					    OWNbit + RX_BUF_SIZE;
-
-				tp->RxDescArray[cur_rx].buf_addr =
-				    virt_to_bus(tp->RxBufferRing[cur_rx]);
-				dev->last_rx = jiffies;
-				tp->stats.rx_bytes += pkt_size;
-				tp->stats.rx_packets++;
-			} else {
-				printk(KERN_WARNING
-				       "%s: Memory squeeze, deferring packet.\n",
-				       dev->name);
-				/* We should check that some rx space is free.
-				   If not, free one and mark stats->rx_dropped++. */
-				tp->stats.rx_dropped++;
+			struct RxDesc *desc = tp->RxDescArray + entry;
+			struct sk_buff *skb = tp->Rx_skbuff[entry];
+			int pkt_size = (status & 0x00001FFF) - 4;
+
+			pci_dma_sync_single(tp->pci_dev,
+					    le32_to_cpu(desc->buf_addr),
+					    RX_BUF_SIZE, PCI_DMA_FROMDEVICE);
+
+			if (rtl8169_try_rx_copy(&skb, pkt_size, desc, dev)) {
+				pci_unmap_single(tp->pci_dev,
+						 le32_to_cpu(desc->buf_addr),
+						 RX_BUF_SIZE,
+						 PCI_DMA_FROMDEVICE);
+				tp->Rx_skbuff[entry] = NULL;
 			}
-		}
-
-		cur_rx = (cur_rx + 1) % NUM_RX_DESC;
 
+			skb_put(skb, pkt_size);
+			skb->protocol = eth_type_trans(skb, dev);
+			netif_rx(skb);
+
+			dev->last_rx = jiffies;
+			tp->stats.rx_bytes += pkt_size;
+			tp->stats.rx_packets++;
+		}
+		
+		cur_rx++; 
+		rx_left--;
 	}
 
 	tp->cur_rx = cur_rx;
+
+	delta = rtl8169_rx_fill(tp, dev, tp->dirty_rx, tp->cur_rx);
+	if (delta > 0)
+		tp->dirty_rx += delta;
+	else if (delta < 0)
+		printk(KERN_INFO "%s: no Rx buffer allocated\n", dev->name);
+
+	/*
+	 * FIXME: until there is periodic timer to try and refill the ring,
+	 * a temporary shortage may definitely kill the Rx process.
+	 * - disable the asic to try and avoid an overflow and kick it again
+	 *   after refill ?
+	 * - how do others driver handle this condition (Uh oh...).
+	 */
+	if (tp->dirty_rx + NUM_RX_DESC == tp->cur_rx)
+		printk(KERN_EMERG "%s: Rx buffers exhausted\n", dev->name);
 }
 
 /* The interrupt handler does all of the Rx thread work and cleans up after the Tx thread. */
@@ -991,9 +1500,7 @@ rtl8169_interrupt(int irq, void *dev_ins
 		RTL_W16(IntrStatus,
 			(status & RxFIFOOver) ? (status | RxOverflow) : status);
 
-		if ((status &
-		     (SYSErr | PCSTimeout | RxUnderrun | RxOverflow | RxFIFOOver
-		      | TxErr | TxOK | RxErr | RxOK)) == 0)
+		if (!(status & rtl8169_intr_mask))
 			break;
 
 		// Rx interrupt 
@@ -1023,11 +1530,13 @@ static int
 rtl8169_close(struct net_device *dev)
 {
 	struct rtl8169_private *tp = dev->priv;
+	struct pci_dev *pdev = tp->pci_dev;
 	void *ioaddr = tp->mmio_addr;
-	int i;
 
 	netif_stop_queue(dev);
 
+	rtl8169_delete_timer(dev);
+
 	spin_lock_irq(&tp->lock);
 
 	/* Stop the chip's Tx and Rx DMA processes. */
@@ -1046,16 +1555,15 @@ rtl8169_close(struct net_device *dev)
 	free_irq(dev->irq, dev);
 
 	rtl8169_tx_clear(tp);
-	kfree(tp->TxDescArrays);
-	kfree(tp->RxDescArrays);
-	tp->TxDescArrays = NULL;
-	tp->RxDescArrays = NULL;
+
+	rtl8169_rx_clear(tp);
+
+	pci_free_consistent(pdev, R8169_RX_RING_BYTES, tp->RxDescArray,
+			    tp->RxPhyAddr);
+	pci_free_consistent(pdev, R8169_TX_RING_BYTES, tp->TxDescArray,
+			    tp->TxPhyAddr);
 	tp->TxDescArray = NULL;
 	tp->RxDescArray = NULL;
-	kfree(tp->RxBufferRings);
-	for (i = 0; i < NUM_RX_DESC; i++) {
-		tp->RxBufferRing[i] = NULL;
-	}
 
 	return 0;
 }
@@ -1109,11 +1617,26 @@ rtl8169_set_rx_mode(struct net_device *d
 	spin_unlock_irqrestore(&tp->lock, flags);
 }
 
+/**
+ *  rtl8169_get_stats - Get rtl8169 read/write statistics
+ *  @dev: The Ethernet Device to get statistics for
+ *
+ *  Get TX/RX statistics for rtl8169
+ */
 struct net_device_stats *
 rtl8169_get_stats(struct net_device *dev)
 {
 	struct rtl8169_private *tp = dev->priv;
+	void *ioaddr = tp->mmio_addr;
+	unsigned long flags;
 
+	if (netif_running(dev)) {
+		spin_lock_irqsave(&tp->lock, flags);
+		tp->stats.rx_missed_errors += RTL_R32(RxMissed);
+		RTL_W32(RxMissed, 0);
+		spin_unlock_irqrestore(&tp->lock, flags);
+	}
+		
 	return &tp->stats;
 }
 
@@ -1122,8 +1645,10 @@ static struct pci_driver rtl8169_pci_dri
 	.id_table	= rtl8169_pci_tbl,
 	.probe		= rtl8169_init_one,
 	.remove		= __devexit_p(rtl8169_remove_one),
-	.suspend	= NULL,
-	.resume		= NULL,
+#ifdef CONFIG_PM
+	.suspend	= rtl8169_suspend,
+	.resume		= rtl8169_resume,
+#endif
 };
 
 static int __init
--- diff/drivers/net/saa9730.c	2004-02-18 08:54:10.000000000 +0000
+++ source/drivers/net/saa9730.c	2004-02-23 13:56:43.000000000 +0000
@@ -1028,6 +1028,9 @@ static int lan_saa9730_init(struct net_d
 	 * Make certain the data structures used by the controller are aligned 
 	 * and DMAble. 
 	 */
+	/*
+	 *  XXX: that is obviously broken - kfree() won't be happy with us.
+	 */
 	lp = (struct lan_saa9730_private *) (((unsigned long)
 					      kmalloc(sizeof(*lp) + 7,
 						      GFP_DMA | GFP_KERNEL)
@@ -1095,7 +1098,6 @@ static int lan_saa9730_init(struct net_d
  out:
 	if (dev->priv)
 		kfree(dev->priv);
-	free_netdev(dev);
 	return ret;
 }
 
--- diff/drivers/net/shaper.c	2004-02-18 08:54:10.000000000 +0000
+++ source/drivers/net/shaper.c	2004-02-23 13:56:43.000000000 +0000
@@ -642,7 +642,6 @@ static void __init shaper_setup(struct n
 
 	dev->open		= shaper_open;
 	dev->stop		= shaper_close;
-	dev->destructor 	= free_netdev;
 	dev->hard_start_xmit 	= shaper_start_xmit;
 	dev->get_stats 		= shaper_get_stats;
 	dev->set_multicast_list = NULL;
--- diff/drivers/net/sis190.c	2003-12-19 09:51:11.000000000 +0000
+++ source/drivers/net/sis190.c	2004-02-23 13:56:43.000000000 +0000
@@ -954,8 +954,7 @@ static void
 SiS190_tx_interrupt(struct net_device *dev, struct sis190_private *tp,
 		    void *ioaddr)
 {
-	unsigned long dirty_tx, tx_left = 0;
-	int entry = tp->cur_tx % NUM_TX_DESC;
+	unsigned long dirty_tx, tx_left;
 
 	assert(dev != NULL);
 	assert(tp != NULL);
@@ -965,6 +964,8 @@ SiS190_tx_interrupt(struct net_device *d
 	tx_left = tp->cur_tx - dirty_tx;
 
 	while (tx_left > 0) {
+		int entry = dirty_tx % NUM_TX_DESC;
+
 		if ((le32_to_cpu(tp->TxDescArray[entry].status) & OWNbit) == 0) {
 			struct sk_buff *skb;
 
@@ -980,7 +981,6 @@ SiS190_tx_interrupt(struct net_device *d
 			tp->stats.tx_packets++;
 			dirty_tx++;
 			tx_left--;
-			entry++;
 		}
 	}
 
--- diff/drivers/net/sis900.c	2004-01-19 10:22:57.000000000 +0000
+++ source/drivers/net/sis900.c	2004-02-23 13:56:43.000000000 +0000
@@ -2093,7 +2093,7 @@ static void set_rx_mode(struct net_devic
 		     i++, mclist = mclist->next) {
 			unsigned int bit_nr =
 				sis900_mcast_bitnr(mclist->dmi_addr, revision);
-			mc_filter[bit_nr >> 4] |= (1 << bit_nr);
+			mc_filter[bit_nr >> 4] |= (1 << (bit_nr & 0xf));
 		}
 	}
 
--- diff/drivers/net/sk98lin/h/lm80.h	2004-02-18 08:54:10.000000000 +0000
+++ source/drivers/net/sk98lin/h/lm80.h	2004-02-23 13:56:43.000000000 +0000
@@ -2,6 +2,8 @@
  *
  * Name:	lm80.h	
  * Project:	Gigabit Ethernet Adapters, Common Modules
+ * Version:	$Revision: 1.6 $
+ * Date:	$Date: 2003/05/13 17:26:52 $
  * Purpose:	Contains all defines for the LM80 Chip
  *		(National Semiconductor).
  *
--- diff/drivers/net/sk98lin/h/skaddr.h	2004-02-18 08:54:10.000000000 +0000
+++ source/drivers/net/sk98lin/h/skaddr.h	2004-02-23 13:56:43.000000000 +0000
@@ -2,6 +2,8 @@
  *
  * Name:	skaddr.h
  * Project:	Gigabit Ethernet Adapters, ADDR-Modul
+ * Version:	$Revision: 1.29 $
+ * Date:	$Date: 2003/05/13 16:57:24 $
  * Purpose:	Header file for Address Management (MC, UC, Prom).
  *
  ******************************************************************************/
--- diff/drivers/net/sk98lin/h/skcsum.h	2004-02-18 08:54:10.000000000 +0000
+++ source/drivers/net/sk98lin/h/skcsum.h	2004-02-23 13:56:43.000000000 +0000
@@ -2,6 +2,8 @@
  *
  * Name:	skcsum.h
  * Project:	GEnesis - SysKonnect SK-NET Gigabit Ethernet (SK-98xx)
+ * Version:	$Revision: 1.10 $
+ * Date:	$Date: 2003/08/20 13:59:57 $
  * Purpose:	Store/verify Internet checksum in send/receive packets.
  *
  ******************************************************************************/
--- diff/drivers/net/sk98lin/h/skdebug.h	2004-02-18 08:54:10.000000000 +0000
+++ source/drivers/net/sk98lin/h/skdebug.h	2004-02-23 13:56:43.000000000 +0000
@@ -2,6 +2,8 @@
  *
  * Name:	skdebug.h
  * Project:	Gigabit Ethernet Adapters, Common Modules
+ * Version:	$Revision: 1.14 $
+ * Date:	$Date: 2003/05/13 17:26:00 $
  * Purpose:	SK specific DEBUG support
  *
  ******************************************************************************/
--- diff/drivers/net/sk98lin/h/skdrv1st.h	2004-02-18 08:54:10.000000000 +0000
+++ source/drivers/net/sk98lin/h/skdrv1st.h	2004-02-23 13:56:43.000000000 +0000
@@ -2,6 +2,8 @@
  *
  * Name:	skdrv1st.h
  * Project:	GEnesis, PCI Gigabit Ethernet Adapter
+ * Version:	$Revision: 1.4 $
+ * Date:	$Date: 2003/11/12 14:28:14 $
  * Purpose:	First header file for driver and all other modules
  *
  ******************************************************************************/
--- diff/drivers/net/sk98lin/h/skdrv2nd.h	2004-02-18 08:54:10.000000000 +0000
+++ source/drivers/net/sk98lin/h/skdrv2nd.h	2004-02-23 13:56:43.000000000 +0000
@@ -2,6 +2,8 @@
  *
  * Name:	skdrv2nd.h
  * Project:	GEnesis, PCI Gigabit Ethernet Adapter
+ * Version:	$Revision: 1.10 $
+ * Date:	$Date: 2003/12/11 16:04:45 $
  * Purpose:	Second header file for driver and all other modules
  *
  ******************************************************************************/
@@ -76,7 +78,13 @@
     /* Marvell (0x11ab) */     \
     } else if (pdev->vendor == 0x11ab) {     \
         /* Gigabit Ethernet Adapter (0x4320) */     \
-        if ((pdev->device == 0x4320)) { \
+        /* Gigabit Ethernet Adapter (0x4360) */     \
+        /* Gigabit Ethernet Adapter (0x4361) */     \
+        /* Belkin (0x5005) */     \
+        if ((pdev->device == 0x4320) || \
+            (pdev->device == 0x4360) || \
+            (pdev->device == 0x4361) || \
+            (pdev->device == 0x5005)) { \
             result = SK_TRUE;     \
         }     \
     /* CNet (0x1371) */     \
--- diff/drivers/net/sk98lin/h/skerror.h	2004-02-18 08:54:10.000000000 +0000
+++ source/drivers/net/sk98lin/h/skerror.h	2004-02-23 13:56:43.000000000 +0000
@@ -2,6 +2,8 @@
  *
  * Name:	skerror.h
  * Project:	Gigabit Ethernet Adapters, Common Modules
+ * Version:	$Revision: 1.7 $
+ * Date:	$Date: 2003/05/13 17:25:13 $
  * Purpose:	SK specific Error log support
  *
  ******************************************************************************/
--- diff/drivers/net/sk98lin/h/skgedrv.h	2004-02-18 08:54:10.000000000 +0000
+++ source/drivers/net/sk98lin/h/skgedrv.h	2004-02-23 13:56:43.000000000 +0000
@@ -2,6 +2,8 @@
  *
  * Name:	skgedrv.h
  * Project:	Gigabit Ethernet Adapters, Common Modules
+ * Version:	$Revision: 1.10 $
+ * Date:	$Date: 2003/07/04 12:25:01 $
  * Purpose:	Interface with the driver
  *
  ******************************************************************************/
--- diff/drivers/net/sk98lin/h/skgehw.h	2004-02-18 08:54:10.000000000 +0000
+++ source/drivers/net/sk98lin/h/skgehw.h	2004-02-23 13:56:43.000000000 +0000
@@ -2,6 +2,8 @@
  *
  * Name:	skgehw.h
  * Project:	Gigabit Ethernet Adapters, Common Modules
+ * Version:	$Revision: 1.56 $
+ * Date:	$Date: 2003/09/23 09:01:00 $
  * Purpose:	Defines and Macros for the Gigabit Ethernet Adapter Product Family
  *
  ******************************************************************************/
--- diff/drivers/net/sk98lin/h/skgehwt.h	2004-02-18 08:54:10.000000000 +0000
+++ source/drivers/net/sk98lin/h/skgehwt.h	2004-02-23 13:56:43.000000000 +0000
@@ -2,6 +2,8 @@
  *
  * Name:	skhwt.h
  * Project:	Gigabit Ethernet Adapters, Event Scheduler Module
+ * Version:	$Revision: 1.7 $
+ * Date:	$Date: 2003/09/16 12:55:08 $
  * Purpose:	Defines for the hardware timer functions
  *
  ******************************************************************************/
--- diff/drivers/net/sk98lin/h/skgei2c.h	2004-02-18 08:54:10.000000000 +0000
+++ source/drivers/net/sk98lin/h/skgei2c.h	2004-02-23 13:56:43.000000000 +0000
@@ -2,6 +2,8 @@
  *
  * Name:	skgei2c.h
  * Project:	Gigabit Ethernet Adapters, TWSI-Module
+ * Version:	$Revision: 1.25 $
+ * Date:	$Date: 2003/10/20 09:06:05 $
  * Purpose:	Special defines for TWSI
  *
  ******************************************************************************/
--- diff/drivers/net/sk98lin/h/skgeinit.h	2004-02-18 08:54:10.000000000 +0000
+++ source/drivers/net/sk98lin/h/skgeinit.h	2004-02-23 13:56:43.000000000 +0000
@@ -2,6 +2,8 @@
  *
  * Name:	skgeinit.h
  * Project:	Gigabit Ethernet Adapters, Common Modules
+ * Version:	$Revision: 1.83 $
+ * Date:	$Date: 2003/09/16 14:07:37 $
  * Purpose:	Structures and prototypes for the GE Init Module
  *
  ******************************************************************************/
--- diff/drivers/net/sk98lin/h/skgepnm2.h	2004-02-18 08:54:10.000000000 +0000
+++ source/drivers/net/sk98lin/h/skgepnm2.h	2004-02-23 13:56:43.000000000 +0000
@@ -2,6 +2,8 @@
  *
  * Name:	skgepnm2.h
  * Project:	GEnesis, PCI Gigabit Ethernet Adapter
+ * Version:	$Revision: 1.36 $
+ * Date:	$Date: 2003/05/23 12:45:13 $
  * Purpose:	Defines for Private Network Management Interface
  *
  ****************************************************************************/
--- diff/drivers/net/sk98lin/h/skgepnmi.h	2004-02-18 08:54:10.000000000 +0000
+++ source/drivers/net/sk98lin/h/skgepnmi.h	2004-02-23 13:56:43.000000000 +0000
@@ -2,6 +2,8 @@
  *
  * Name:	skgepnmi.h
  * Project:	GEnesis, PCI Gigabit Ethernet Adapter
+ * Version:	$Revision: 1.62 $
+ * Date:	$Date: 2003/08/15 12:31:52 $
  * Purpose:	Defines for Private Network Management Interface
  *
  ****************************************************************************/
--- diff/drivers/net/sk98lin/h/skgesirq.h	2004-02-18 08:54:10.000000000 +0000
+++ source/drivers/net/sk98lin/h/skgesirq.h	2004-02-23 13:56:43.000000000 +0000
@@ -2,6 +2,8 @@
  *
  * Name:	skgesirq.h
  * Project:	Gigabit Ethernet Adapters, Common Modules
+ * Version:	$Revision: 1.30 $
+ * Date:	$Date: 2003/07/04 12:34:13 $
  * Purpose:	SK specific Gigabit Ethernet special IRQ functions
  *
  ******************************************************************************/
--- diff/drivers/net/sk98lin/h/ski2c.h	2004-02-18 08:54:10.000000000 +0000
+++ source/drivers/net/sk98lin/h/ski2c.h	2004-02-23 13:56:43.000000000 +0000
@@ -2,6 +2,8 @@
  *
  * Name:	ski2c.h
  * Project:	Gigabit Ethernet Adapters, TWSI-Module
+ * Version:	$Revision: 1.35 $
+ * Date:	$Date: 2003/10/20 09:06:30 $
  * Purpose:	Defines to access Voltage and Temperature Sensor
  *
  ******************************************************************************/
--- diff/drivers/net/sk98lin/h/skqueue.h	2004-02-18 08:54:10.000000000 +0000
+++ source/drivers/net/sk98lin/h/skqueue.h	2004-02-23 13:56:43.000000000 +0000
@@ -2,6 +2,8 @@
  *
  * Name:	skqueue.h
  * Project:	Gigabit Ethernet Adapters, Event Scheduler Module
+ * Version:	$Revision: 1.16 $
+ * Date:	$Date: 2003/09/16 12:50:32 $
  * Purpose:	Defines for the Event queue
  *
  ******************************************************************************/
@@ -20,6 +22,10 @@
  *
  ******************************************************************************/
 
+/*
+ * SKQUEUE.H	contains all defines and types for the event queue
+ */
+
 #ifndef _SKQUEUE_H_
 #define _SKQUEUE_H_
 
--- diff/drivers/net/sk98lin/h/skrlmt.h	2004-02-18 08:54:10.000000000 +0000
+++ source/drivers/net/sk98lin/h/skrlmt.h	2004-02-23 13:56:43.000000000 +0000
@@ -2,6 +2,8 @@
  *
  * Name:	skrlmt.h
  * Project:	GEnesis, PCI Gigabit Ethernet Adapter
+ * Version:	$Revision: 1.37 $
+ * Date:	$Date: 2003/04/15 09:43:43 $
  * Purpose:	Header file for Redundant Link ManagemenT.
  *
  ******************************************************************************/
--- diff/drivers/net/sk98lin/h/sktimer.h	2004-02-18 08:54:10.000000000 +0000
+++ source/drivers/net/sk98lin/h/sktimer.h	2004-02-23 13:56:43.000000000 +0000
@@ -2,6 +2,8 @@
  *
  * Name:	sktimer.h
  * Project:	Gigabit Ethernet Adapters, Event Scheduler Module
+ * Version:	$Revision: 1.11 $
+ * Date:	$Date: 2003/09/16 12:58:18 $
  * Purpose:	Defines for the timer functions
  *
  ******************************************************************************/
--- diff/drivers/net/sk98lin/h/sktypes.h	2004-02-18 08:54:10.000000000 +0000
+++ source/drivers/net/sk98lin/h/sktypes.h	2004-02-23 13:56:43.000000000 +0000
@@ -2,6 +2,8 @@
  *
  * Name:	sktypes.h
  * Project:	GEnesis, PCI Gigabit Ethernet Adapter
+ * Version:	$Revision: 1.2 $
+ * Date:	$Date: 2003/10/07 08:16:51 $
  * Purpose:	Define data types for Linux
  *
  ******************************************************************************/
--- diff/drivers/net/sk98lin/h/skversion.h	2004-02-18 08:54:10.000000000 +0000
+++ source/drivers/net/sk98lin/h/skversion.h	2004-02-23 13:56:43.000000000 +0000
@@ -2,6 +2,8 @@
  *
  * Name:	version.h
  * Project:	GEnesis, PCI Gigabit Ethernet Adapter
+ * Version:	$Revision: 1.5 $
+ * Date:	$Date: 2003/10/07 08:16:51 $
  * Purpose:	SK specific Error log support
  *
  ******************************************************************************/
@@ -23,14 +25,14 @@
 #ifdef	lint
 static const char SysKonnectFileId[] = "@(#) (C) SysKonnect GmbH.";
 static const char SysKonnectBuildNumber[] =
-	"@(#)SK-BUILD: 6.22 PL: 01"; 
+	"@(#)SK-BUILD: 6.23 PL: 01"; 
 #endif	/* !defined(lint) */
 
-#define BOOT_STRING	"sk98lin: Network Device Driver v6.22\n" \
+#define BOOT_STRING	"sk98lin: Network Device Driver v6.23\n" \
 			"(C)Copyright 1999-2004 Marvell(R)."
 
-#define VER_STRING	"6.22"
+#define VER_STRING	"6.23"
 #define DRIVER_FILE_NAME	"sk98lin"
-#define DRIVER_REL_DATE		"Jan-30-2004"
+#define DRIVER_REL_DATE		"Feb-13-2004"
 
 
--- diff/drivers/net/sk98lin/h/skvpd.h	2004-02-18 08:54:10.000000000 +0000
+++ source/drivers/net/sk98lin/h/skvpd.h	2004-02-23 13:56:43.000000000 +0000
@@ -2,6 +2,8 @@
  *
  * Name:	skvpd.h
  * Project:	GEnesis, PCI Gigabit Ethernet Adapter
+ * Version:	$Revision: 1.15 $
+ * Date:	$Date: 2003/01/13 10:39:38 $
  * Purpose:	Defines and Macros for VPD handling
  *
  ******************************************************************************/
--- diff/drivers/net/sk98lin/h/xmac_ii.h	2004-02-18 08:54:10.000000000 +0000
+++ source/drivers/net/sk98lin/h/xmac_ii.h	2004-02-23 13:56:43.000000000 +0000
@@ -2,6 +2,8 @@
  *
  * Name:	xmac_ii.h
  * Project:	Gigabit Ethernet Adapters, Common Modules
+ * Version:	$Revision: 1.52 $
+ * Date:	$Date: 2003/10/02 16:35:50 $
  * Purpose:	Defines and Macros for Gigabit Ethernet Controller
  *
  ******************************************************************************/
--- diff/drivers/net/sk98lin/skaddr.c	2004-02-18 08:54:10.000000000 +0000
+++ source/drivers/net/sk98lin/skaddr.c	2004-02-23 13:56:43.000000000 +0000
@@ -2,6 +2,8 @@
  *
  * Name:	skaddr.c
  * Project:	Gigabit Ethernet Adapters, ADDR-Module
+ * Version:	$Revision: 1.52 $
+ * Date:	$Date: 2003/06/02 13:46:15 $
  * Purpose:	Manage Addresses (Multicast and Unicast) and Promiscuous Mode.
  *
  ******************************************************************************/
--- diff/drivers/net/sk98lin/skcsum.c	2004-02-18 08:54:10.000000000 +0000
+++ source/drivers/net/sk98lin/skcsum.c	2004-02-23 13:56:43.000000000 +0000
@@ -2,6 +2,8 @@
  *
  * Name:	skcsum.c
  * Project:	GEnesis, PCI Gigabit Ethernet Adapter
+ * Version:	$Revision: 1.12 $
+ * Date:	$Date: 2003/08/20 13:55:53 $
  * Purpose:	Store/verify Internet checksum in send/receive packets.
  *
  ******************************************************************************/
--- diff/drivers/net/sk98lin/skdim.c	2004-02-18 08:54:10.000000000 +0000
+++ source/drivers/net/sk98lin/skdim.c	2004-02-23 13:56:43.000000000 +0000
@@ -2,6 +2,8 @@
  *
  * Name:	skdim.c
  * Project:	GEnesis, PCI Gigabit Ethernet Adapter
+ * Version:	$Revision: 1.5 $
+ * Date:	$Date: 2003/11/28 12:55:40 $
  * Purpose:	All functions to maintain interrupt moderation
  *
  ******************************************************************************/
--- diff/drivers/net/sk98lin/skge.c	2004-02-18 08:54:10.000000000 +0000
+++ source/drivers/net/sk98lin/skge.c	2004-02-23 13:56:43.000000000 +0000
@@ -2,6 +2,8 @@
  *
  * Name:	skge.c
  * Project:	GEnesis, PCI Gigabit Ethernet Adapter
+ * Version:	$Revision: 1.45 $
+ * Date:       	$Date: 2004/02/12 14:41:02 $
  * Purpose:	The main driver source module
  *
  ******************************************************************************/
@@ -294,7 +296,6 @@ static int __init skge_probe (void)
 	SK_BOOL BootStringCount = SK_FALSE;
 	int			retval;
 #ifdef CONFIG_PROC_FS
-	int			proc_root_initialized = 0;
 	struct proc_dir_entry	*pProcFile;
 #endif
 
@@ -311,6 +312,12 @@ static int __init skge_probe (void)
 		dev = NULL;
 		pNet = NULL;
 
+		/* Don't handle Yukon2 cards at the moment */
+		/* 12-feb-2004 ---- mlindner@syskonnect.de */
+		if (pdev->vendor == 0x11ab) {
+			if ( (pdev->device == 0x4360) || (pdev->device == 0x4361) )
+				continue;
+		}
 
 		SK_PCI_ISCOMPLIANT(vendor_flag, pdev);
 		if (!vendor_flag)
--- diff/drivers/net/sk98lin/skgehwt.c	2004-02-18 08:54:10.000000000 +0000
+++ source/drivers/net/sk98lin/skgehwt.c	2004-02-23 13:56:43.000000000 +0000
@@ -2,6 +2,8 @@
  *
  * Name:	skgehwt.c
  * Project:	Gigabit Ethernet Adapters, Event Scheduler Module
+ * Version:	$Revision: 1.15 $
+ * Date:	$Date: 2003/09/16 13:41:23 $
  * Purpose:	Hardware Timer
  *
  ******************************************************************************/
--- diff/drivers/net/sk98lin/skgeinit.c	2004-02-18 08:54:10.000000000 +0000
+++ source/drivers/net/sk98lin/skgeinit.c	2004-02-23 13:56:43.000000000 +0000
@@ -2,6 +2,8 @@
  *
  * Name:	skgeinit.c
  * Project:	Gigabit Ethernet Adapters, Common Modules
+ * Version:	$Revision: 1.97 $
+ * Date:	$Date: 2003/10/02 16:45:31 $
  * Purpose:	Contains functions to initialize the adapter
  *
  ******************************************************************************/
@@ -20,7 +22,6 @@
  *
  ******************************************************************************/
 
-
 #include "h/skdrv1st.h"
 #include "h/skdrv2nd.h"
 
--- diff/drivers/net/sk98lin/skgemib.c	2004-02-18 08:54:10.000000000 +0000
+++ source/drivers/net/sk98lin/skgemib.c	2004-02-23 13:56:43.000000000 +0000
@@ -2,6 +2,8 @@
  *
  * Name:	skgemib.c
  * Project:	GEnesis, PCI Gigabit Ethernet Adapter
+ * Version:	$Revision: 1.11 $
+ * Date:	$Date: 2003/09/15 13:38:12 $
  * Purpose:	Private Network Management Interface Management Database
  *
  ****************************************************************************/
--- diff/drivers/net/sk98lin/skgepnmi.c	2004-02-18 08:54:10.000000000 +0000
+++ source/drivers/net/sk98lin/skgepnmi.c	2004-02-23 13:56:43.000000000 +0000
@@ -2,6 +2,8 @@
  *
  * Name:	skgepnmi.c
  * Project:	GEnesis, PCI Gigabit Ethernet Adapter
+ * Version:	$Revision: 1.111 $
+ * Date:	$Date: 2003/09/15 13:35:35 $
  * Purpose:	Private Network Management Interface
  *
  ****************************************************************************/
@@ -20,6 +22,7 @@
  *
  ******************************************************************************/
 
+
 #ifndef _lint
 static const char SysKonnectFileId[] =
 	"@(#) $Id: skgepnmi.c,v 1.111 2003/09/15 13:35:35 tschilli Exp $ (C) Marvell.";
--- diff/drivers/net/sk98lin/skgesirq.c	2004-02-18 08:54:10.000000000 +0000
+++ source/drivers/net/sk98lin/skgesirq.c	2004-02-23 13:56:43.000000000 +0000
@@ -2,6 +2,8 @@
  *
  * Name:	skgesirq.c
  * Project:	Gigabit Ethernet Adapters, Common Modules
+ * Version:	$Revision: 1.92 $
+ * Date:	$Date: 2003/09/16 14:37:07 $
  * Purpose:	Special IRQ module
  *
  ******************************************************************************/
--- diff/drivers/net/sk98lin/ski2c.c	2004-02-18 08:54:10.000000000 +0000
+++ source/drivers/net/sk98lin/ski2c.c	2004-02-23 13:56:43.000000000 +0000
@@ -2,6 +2,8 @@
  *
  * Name:	ski2c.c
  * Project:	Gigabit Ethernet Adapters, TWSI-Module
+ * Version:	$Revision: 1.59 $
+ * Date:	$Date: 2003/10/20 09:07:25 $
  * Purpose:	Functions to access Voltage and Temperature Sensor
  *
  ******************************************************************************/
--- diff/drivers/net/sk98lin/sklm80.c	2004-02-18 08:54:10.000000000 +0000
+++ source/drivers/net/sk98lin/sklm80.c	2004-02-23 13:56:43.000000000 +0000
@@ -2,6 +2,8 @@
  *
  * Name:	sklm80.c
  * Project:	Gigabit Ethernet Adapters, TWSI-Module
+ * Version:	$Revision: 1.22 $
+ * Date:	$Date: 2003/10/20 09:08:21 $
  * Purpose:	Functions to access Voltage and Temperature Sensor (LM80)
  *
  ******************************************************************************/
--- diff/drivers/net/sk98lin/skproc.c	2004-02-18 08:54:10.000000000 +0000
+++ source/drivers/net/sk98lin/skproc.c	2004-02-23 13:56:43.000000000 +0000
@@ -2,6 +2,8 @@
  *
  * Name:	skproc.c
  * Project:	GEnesis, PCI Gigabit Ethernet Adapter
+ * Version:	$Revision: 1.11 $
+ * Date:	$Date: 2003/12/11 16:03:57 $
  * Purpose:	Funktions to display statictic data
  *
  ******************************************************************************/
@@ -22,7 +24,6 @@
  *	The information in this file is provided "AS IS" without warranty.
  *
  ******************************************************************************/
-
 #include <linux/proc_fs.h>
 #include <linux/seq_file.h>
 
--- diff/drivers/net/sk98lin/skqueue.c	2004-02-18 08:54:10.000000000 +0000
+++ source/drivers/net/sk98lin/skqueue.c	2004-02-23 13:56:43.000000000 +0000
@@ -2,6 +2,8 @@
  *
  * Name:	skqueue.c
  * Project:	Gigabit Ethernet Adapters, Event Scheduler Module
+ * Version:	$Revision: 1.20 $
+ * Date:	$Date: 2003/09/16 13:44:00 $
  * Purpose:	Management of an event queue.
  *
  ******************************************************************************/
@@ -20,6 +22,7 @@
  *
  ******************************************************************************/
 
+
 /*
  *	Event queue and dispatcher
  */
--- diff/drivers/net/sk98lin/skrlmt.c	2004-02-18 08:54:10.000000000 +0000
+++ source/drivers/net/sk98lin/skrlmt.c	2004-02-23 13:56:43.000000000 +0000
@@ -2,6 +2,8 @@
  *
  * Name:	skrlmt.c
  * Project:	GEnesis, PCI Gigabit Ethernet Adapter
+ * Version:	$Revision: 1.69 $
+ * Date:	$Date: 2003/04/15 09:39:22 $
  * Purpose:	Manage links on SK-NET Adapters, esp. redundant ones.
  *
  ******************************************************************************/
--- diff/drivers/net/sk98lin/sktimer.c	2004-02-18 08:54:10.000000000 +0000
+++ source/drivers/net/sk98lin/sktimer.c	2004-02-23 13:56:43.000000000 +0000
@@ -2,6 +2,8 @@
  *
  * Name:	sktimer.c
  * Project:	Gigabit Ethernet Adapters, Event Scheduler Module
+ * Version:	$Revision: 1.14 $
+ * Date:	$Date: 2003/09/16 13:46:51 $
  * Purpose:	High level timer functions.
  *
  ******************************************************************************/
@@ -20,6 +22,7 @@
  *
  ******************************************************************************/
 
+
 /*
  *	Event queue and dispatcher
  */
--- diff/drivers/net/sk98lin/skvpd.c	2004-02-18 08:54:10.000000000 +0000
+++ source/drivers/net/sk98lin/skvpd.c	2004-02-23 13:56:43.000000000 +0000
@@ -2,6 +2,8 @@
  *
  * Name:	skvpd.c
  * Project:	GEnesis, PCI Gigabit Ethernet Adapter
+ * Version:	$Revision: 1.37 $
+ * Date:	$Date: 2003/01/13 10:42:45 $
  * Purpose:	Shared software to read and write VPD data
  *
  ******************************************************************************/
--- diff/drivers/net/sk98lin/skxmac2.c	2004-02-18 08:54:10.000000000 +0000
+++ source/drivers/net/sk98lin/skxmac2.c	2004-02-23 13:56:43.000000000 +0000
@@ -2,6 +2,8 @@
  *
  * Name:	skxmac2.c
  * Project:	Gigabit Ethernet Adapters, Common Modules
+ * Version:	$Revision: 1.102 $
+ * Date:	$Date: 2003/10/02 16:53:58 $
  * Purpose:	Contains functions to initialize the MACs and PHYs
  *
  ******************************************************************************/
--- diff/drivers/net/skfp/skfddi.c	2004-02-18 08:54:10.000000000 +0000
+++ source/drivers/net/skfp/skfddi.c	2004-02-23 13:56:43.000000000 +0000
@@ -217,7 +217,7 @@ static int skfp_init_one(struct pci_dev 
 {
 	struct net_device *dev;
 	struct s_smc *smc;	/* board pointer */
-	u32 port, len;
+	unsigned long port, len;
 	int err;
 
 	PRINTK(KERN_INFO "entering skfp_init_one\n");
@@ -240,7 +240,7 @@ static int skfp_init_one(struct pci_dev 
 	len = pci_resource_len(pdev, 0);
 
 	if (len < 0x4000) {
-		printk(KERN_ERR "skfp: Invalid PCI region size: %d\n", len);
+		printk(KERN_ERR "skfp: Invalid PCI region size: %lu\n", len);
 		err = -EIO;
 		goto err_out1;
 	}
--- diff/drivers/net/smc-mca.c	2004-02-18 08:54:10.000000000 +0000
+++ source/drivers/net/smc-mca.c	2004-02-23 13:56:43.000000000 +0000
@@ -324,6 +324,9 @@ int __init ultramca_probe(struct device 
 
 	dev->open = &ultramca_open;
 	dev->stop = &ultramca_close_card;
+#ifdef CONFIG_NET_POLL_CONTROLLER
+	dev->poll_controller = ei_poll;
+#endif
 
 	NS8390_init(dev, 0);
 
--- diff/drivers/net/smc-ultra.c	2004-02-18 08:54:10.000000000 +0000
+++ source/drivers/net/smc-ultra.c	2004-02-23 13:56:43.000000000 +0000
@@ -121,6 +121,14 @@ MODULE_DEVICE_TABLE(isapnp, ultra_device
 #define ULTRA_IO_EXTENT 32
 #define EN0_ERWCNT		0x08	/* Early receive warning count. */
 
+#ifdef CONFIG_NET_POLL_CONTROLLER
+static void ultra_poll(struct net_device *dev)
+{
+	disable_irq(dev->irq);
+	ei_interrupt(dev->irq, dev, NULL);
+	enable_irq(dev->irq);
+}
+#endif
 /*	Probe for the Ultra.  This looks like a 8013 with the station
 	address PROM at I/O ports <base>+8 to <base>+13, with a checksum
 	following.
@@ -134,6 +142,9 @@ static int __init do_ultra_probe(struct 
 
 	SET_MODULE_OWNER(dev);
 
+#ifdef CONFIG_NET_POLL_CONTROLLER
+	dev->poll_controller = &ultra_poll;
+#endif
 	if (base_addr > 0x1ff)		/* Check a single specified location. */
 		return ultra_probe1(dev, base_addr);
 	else if (base_addr != 0)	/* Don't probe at all. */
@@ -301,6 +312,9 @@ static int __init ultra_probe1(struct ne
 	ei_status.reset_8390 = &ultra_reset_8390;
 	dev->open = &ultra_open;
 	dev->stop = &ultra_close_card;
+#ifdef CONFIG_NET_POLL_CONTROLLER
+	dev->poll_controller = ei_poll;
+#endif
 	NS8390_init(dev, 0);
 
 	return 0;
--- diff/drivers/net/smc-ultra32.c	2004-02-18 08:54:10.000000000 +0000
+++ source/drivers/net/smc-ultra32.c	2004-02-23 13:56:43.000000000 +0000
@@ -268,6 +268,9 @@ static int __init ultra32_probe1(struct 
 	ei_status.reset_8390 = &ultra32_reset_8390;
 	dev->open = &ultra32_open;
 	dev->stop = &ultra32_close;
+#ifdef CONFIG_NET_POLL_CONTROLLER
+	dev->poll_controller = ei_poll;
+#endif
 	NS8390_init(dev, 0);
 
 	return 0;
--- diff/drivers/net/stnic.c	2004-02-18 08:54:10.000000000 +0000
+++ source/drivers/net/stnic.c	2004-02-23 13:56:43.000000000 +0000
@@ -124,6 +124,9 @@ static int __init stnic_probe(void)
   dev->irq = IRQ_STNIC;
   dev->open = &stnic_open;
   dev->stop = &stnic_close;
+#ifdef CONFIG_NET_POLL_CONTROLLER
+  dev->poll_controller = ei_poll;
+#endif
 
   /* Snarf the interrupt now.  There's no point in waiting since we cannot
      share and the board will usually be enabled. */
--- diff/drivers/net/sun3lance.c	2004-02-18 08:54:10.000000000 +0000
+++ source/drivers/net/sun3lance.c	2004-02-23 13:56:43.000000000 +0000
@@ -342,7 +342,7 @@ static int __init lance_probe( struct ne
 
 	REGA(CSR0) = CSR0_STOP; 
 
-	request_irq(LANCE_IRQ, lance_interrupt, 0, "SUN3 Lance", dev);
+	request_irq(LANCE_IRQ, lance_interrupt, SA_INTERRUPT, "SUN3 Lance", dev);
 	dev->irq = (unsigned short)LANCE_IRQ;
 
 
@@ -505,6 +505,9 @@ static int lance_start_xmit( struct sk_b
 	struct lance_tx_head *head;
 	unsigned long flags;
 
+	DPRINTK( 1, ( "%s: transmit start.\n",
+		      dev->name));
+
 	/* Transmitter timeout, serious problems. */
 	if (netif_queue_stopped(dev)) {
 		int tickssofar = jiffies - dev->trans_start;
--- diff/drivers/net/sundance.c	2004-02-18 08:54:10.000000000 +0000
+++ source/drivers/net/sundance.c	2004-02-23 13:56:43.000000000 +0000
@@ -987,7 +987,7 @@ static void tx_timeout(struct net_device
 		int i;
 		for (i=0; i<TX_RING_SIZE; i++) {
 			printk(KERN_DEBUG "%02x %08llx %08x %08x(%02x) %08x %08x\n", i,
-				(unsigned long long)np->tx_ring_dma + i*sizeof(*np->tx_ring),
+				(unsigned long long)(np->tx_ring_dma + i*sizeof(*np->tx_ring)),
 				le32_to_cpu(np->tx_ring[i].next_desc),
 				le32_to_cpu(np->tx_ring[i].status),
 				(le32_to_cpu(np->tx_ring[i].status) >> 2) & 0xff,
@@ -1673,7 +1673,7 @@ static int netdev_ioctl(struct net_devic
 		case SIOCDEVPRIVATE:
 		for (i=0; i<TX_RING_SIZE; i++) {
 			printk(KERN_DEBUG "%02x %08llx %08x %08x(%02x) %08x %08x\n", i,
-				(unsigned long long)np->tx_ring_dma + i*sizeof(*np->tx_ring),	
+				(unsigned long long)(np->tx_ring_dma + i*sizeof(*np->tx_ring)),	
 				le32_to_cpu(np->tx_ring[i].next_desc),
 				le32_to_cpu(np->tx_ring[i].status),
 				(le32_to_cpu(np->tx_ring[i].status) >> 2) 
--- diff/drivers/net/sungem.c	2004-02-18 08:54:10.000000000 +0000
+++ source/drivers/net/sungem.c	2004-02-23 13:56:43.000000000 +0000
@@ -654,6 +654,7 @@ static __inline__ void gem_post_rxds(str
 	cluster_start = curr = (gp->rx_new & ~(4 - 1));
 	count = 0;
 	kick = -1;
+	wmb();
 	while (curr != limit) {
 		curr = NEXT_RX(curr);
 		if (++count == 4) {
@@ -670,13 +671,16 @@ static __inline__ void gem_post_rxds(str
 			count = 0;
 		}
 	}
-	if (kick >= 0)
+	if (kick >= 0) {
+		mb();
 		writel(kick, gp->regs + RXDMA_KICK);
+	}
 }
 
 static void gem_rx(struct gem *gp)
 {
 	int entry, drops;
+	u32 done;
 
 	if (netif_msg_intr(gp))
 		printk(KERN_DEBUG "%s: rx interrupt, done: %d, rx_new: %d\n",
@@ -684,6 +688,7 @@ static void gem_rx(struct gem *gp)
 
 	entry = gp->rx_new;
 	drops = 0;
+	done = readl(gp->regs + RXDMA_DONE);
 	for (;;) {
 		struct gem_rxd *rxd = &gp->init_block->rxd[entry];
 		struct sk_buff *skb;
@@ -694,6 +699,19 @@ static void gem_rx(struct gem *gp)
 		if ((status & RXDCTRL_OWN) != 0)
 			break;
 
+		/* When writing back RX descriptor, GEM writes status
+		 * then buffer address, possibly in seperate transactions.
+		 * If we don't wait for the chip to write both, we could
+		 * post a new buffer to this descriptor then have GEM spam
+		 * on the buffer address.  We sync on the RX completion
+		 * register to prevent this from happening.
+		 */
+		if (entry == done) {
+			done = readl(gp->regs + RXDMA_DONE);
+			if (entry == done)
+				break;
+		}
+
 		skb = gp->rx_skbs[entry];
 
 		len = (status & RXDCTRL_BUFSZ) >> 16;
@@ -884,6 +902,7 @@ static int gem_start_xmit(struct sk_buff
 		if (gem_intme(entry))
 			ctrl |= TXDCTRL_INTME;
 		txd->buffer = cpu_to_le64(mapping);
+		wmb();
 		txd->control_word = cpu_to_le64(ctrl);
 		entry = NEXT_TX(entry);
 	} else {
@@ -923,6 +942,7 @@ static int gem_start_xmit(struct sk_buff
 			
 			txd = &gp->init_block->txd[entry];
 			txd->buffer = cpu_to_le64(mapping);
+			wmb();
 			txd->control_word = cpu_to_le64(this_ctrl | len);
 
 			if (gem_intme(entry))
@@ -932,6 +952,7 @@ static int gem_start_xmit(struct sk_buff
 		}
 		txd = &gp->init_block->txd[first_entry];
 		txd->buffer = cpu_to_le64(first_mapping);
+		wmb();
 		txd->control_word =
 			cpu_to_le64(ctrl | TXDCTRL_SOF | intme | first_len);
 	}
@@ -943,6 +964,7 @@ static int gem_start_xmit(struct sk_buff
 	if (netif_msg_tx_queued(gp))
 		printk(KERN_DEBUG "%s: tx queued, slot %d, skblen %d\n",
 		       dev->name, entry, skb->len);
+	mb();
 	writel(gp->tx_new, gp->regs + TXDMA_KICK);
 	spin_unlock_irq(&gp->lock);
 
@@ -1418,6 +1440,7 @@ static void gem_clean_rings(struct gem *
 			gp->rx_skbs[i] = NULL;
 		}
 		rxd->status_word = 0;
+		wmb();
 		rxd->buffer = 0;
 	}
 
@@ -1478,6 +1501,7 @@ static void gem_init_rings(struct gem *g
 					RX_BUF_ALLOC_SIZE(gp),
 					PCI_DMA_FROMDEVICE);
 		rxd->buffer = cpu_to_le64(dma_addr);
+		wmb();
 		rxd->status_word = cpu_to_le64(RXDCTRL_FRESH(gp));
 		skb_reserve(skb, RX_OFFSET);
 	}
@@ -1486,8 +1510,10 @@ static void gem_init_rings(struct gem *g
 		struct gem_txd *txd = &gb->txd[i];
 
 		txd->control_word = 0;
+		wmb();
 		txd->buffer = 0;
 	}
+	wmb();
 }
 
 /* Must be invoked under gp->lock. */
@@ -1825,9 +1851,9 @@ static void gem_init_pause_thresholds(st
 	/* If Infinite Burst didn't stick, then use different
 	 * thresholds (and Apple bug fixes don't exist)
 	 */
-	if (readl(gp->regs + GREG_CFG) & GREG_CFG_IBURST) {
+	if (!(readl(gp->regs + GREG_CFG) & GREG_CFG_IBURST)) {
 		cfg = ((2 << 1) & GREG_CFG_TXDMALIM);
-		cfg = ((8 << 6) & GREG_CFG_RXDMALIM);
+		cfg |= ((8 << 6) & GREG_CFG_RXDMALIM);
 		writel(cfg, gp->regs + GREG_CFG);
 	}	
 }
@@ -1961,7 +1987,6 @@ static void gem_init_hw(struct gem *gp, 
  */
 static void gem_apple_powerup(struct gem *gp)
 {
-	u16 cmd;
 	u32 mif_cfg;
 
 	mb();
--- diff/drivers/net/tg3.c	2004-02-18 08:54:10.000000000 +0000
+++ source/drivers/net/tg3.c	2004-02-23 13:56:44.000000000 +0000
@@ -56,8 +56,8 @@
 
 #define DRV_MODULE_NAME		"tg3"
 #define PFX DRV_MODULE_NAME	": "
-#define DRV_MODULE_VERSION	"2.6"
-#define DRV_MODULE_RELDATE	"February 3, 2004"
+#define DRV_MODULE_VERSION	"2.7"
+#define DRV_MODULE_RELDATE	"February 17, 2004"
 
 #define TG3_DEF_MAC_MODE	0
 #define TG3_DEF_RX_MODE		0
@@ -213,8 +213,30 @@ static void tg3_write_indirect_reg32(str
 	}
 }
 
+
+static inline void _tw32_rx_mbox(struct tg3 *tp, u32 off, u32 val)
+{
+	unsigned long mbox = tp->regs + off;
+	writel(val, mbox);
+	if (tp->tg3_flags & TG3_FLAG_MBOX_WRITE_REORDER)
+		readl(mbox);
+}
+
+static inline void _tw32_tx_mbox(struct tg3 *tp, u32 off, u32 val)
+{
+	unsigned long mbox = tp->regs + off;
+	writel(val, mbox);
+	if (tp->tg3_flags & TG3_FLAG_TXD_MBOX_HWBUG)
+		writel(val, mbox);
+	if (tp->tg3_flags & TG3_FLAG_MBOX_WRITE_REORDER)
+		readl(mbox);
+}
+
+#define tw32_mailbox(reg, val)  writel(((val) & 0xffffffff), tp->regs + (reg))
+#define tw32_rx_mbox(reg, val)  _tw32_rx_mbox(tp, reg, val)
+#define tw32_tx_mbox(reg, val)  _tw32_tx_mbox(tp, reg, val)
+
 #define tw32(reg,val)		tg3_write_indirect_reg32(tp,(reg),(val))
-#define tw32_mailbox(reg, val)	writel(((val) & 0xffffffff), tp->regs + (reg))
 #define tw16(reg,val)		writew(((val) & 0xffff), tp->regs + (reg))
 #define tw8(reg,val)		writeb(((val) & 0xff), tp->regs + (reg))
 #define tr32(reg)		readl(tp->regs + (reg))
@@ -656,6 +678,18 @@ static int tg3_phy_reset(struct tg3 *tp,
 		return err;
 
 out:
+	if (tp->tg3_flags2 & TG3_FLG2_PHY_ADC_BUG) {
+		tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x0c00);
+		tg3_writephy(tp, MII_TG3_DSP_ADDRESS, 0x201f);
+		tg3_writephy(tp, MII_TG3_DSP_RW_PORT, 0x2aaa);
+		tg3_writephy(tp, MII_TG3_DSP_ADDRESS, 0x000a);
+		tg3_writephy(tp, MII_TG3_DSP_RW_PORT, 0x0323);
+		tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x0400);
+	}
+	if (tp->tg3_flags2 & TG3_FLG2_PHY_5704_A0_BUG) {
+		tg3_writephy(tp, 0x1c, 0x8d68);
+		tg3_writephy(tp, 0x1c, 0x8d68);
+	}
 	tg3_phy_set_wirespeed(tp);
 	return 0;
 }
@@ -1211,9 +1245,13 @@ static int tg3_setup_copper_phy(struct t
 	u8 current_duplex;
 	int i, err;
 
+	tw32(MAC_EVENT, 0);
+
 	tw32(MAC_STATUS,
 	     (MAC_STATUS_SYNC_CHANGED |
-	      MAC_STATUS_CFG_CHANGED));
+	      MAC_STATUS_CFG_CHANGED |
+	      MAC_STATUS_MI_COMPLETION |
+	      MAC_STATUS_LNKSTATE_CHANGED));
 	tr32(MAC_STATUS);
 	udelay(40);
 
@@ -2325,25 +2363,19 @@ next_pkt_nopost:
 
 	/* ACK the status ring. */
 	tp->rx_rcb_ptr = rx_rcb_ptr;
-	tw32_mailbox(MAILBOX_RCVRET_CON_IDX_0 + TG3_64BIT_REG_LOW,
+	tw32_rx_mbox(MAILBOX_RCVRET_CON_IDX_0 + TG3_64BIT_REG_LOW,
 		     (rx_rcb_ptr % TG3_RX_RCB_RING_SIZE(tp)));
-	if (tp->tg3_flags & TG3_FLAG_MBOX_WRITE_REORDER)
-		tr32(MAILBOX_RCVRET_CON_IDX_0 + TG3_64BIT_REG_LOW);
 
 	/* Refill RX ring(s). */
 	if (work_mask & RXD_OPAQUE_RING_STD) {
 		sw_idx = tp->rx_std_ptr % TG3_RX_RING_SIZE;
-		tw32_mailbox(MAILBOX_RCV_STD_PROD_IDX + TG3_64BIT_REG_LOW,
+		tw32_rx_mbox(MAILBOX_RCV_STD_PROD_IDX + TG3_64BIT_REG_LOW,
 			     sw_idx);
-		if (tp->tg3_flags & TG3_FLAG_MBOX_WRITE_REORDER)
-			tr32(MAILBOX_RCV_STD_PROD_IDX + TG3_64BIT_REG_LOW);
 	}
 	if (work_mask & RXD_OPAQUE_RING_JUMBO) {
 		sw_idx = tp->rx_jumbo_ptr % TG3_RX_JUMBO_RING_SIZE;
-		tw32_mailbox(MAILBOX_RCV_JUMBO_PROD_IDX + TG3_64BIT_REG_LOW,
+		tw32_rx_mbox(MAILBOX_RCV_JUMBO_PROD_IDX + TG3_64BIT_REG_LOW,
 			     sw_idx);
-		if (tp->tg3_flags & TG3_FLAG_MBOX_WRITE_REORDER)
-			tr32(MAILBOX_RCV_JUMBO_PROD_IDX + TG3_64BIT_REG_LOW);
 	}
 
 	return received;
@@ -2479,6 +2511,13 @@ static irqreturn_t tg3_interrupt(int irq
 static int tg3_init_hw(struct tg3 *);
 static int tg3_halt(struct tg3 *);
 
+#ifdef CONFIG_NET_POLL_CONTROLLER
+static void tg3_poll_controller(struct net_device *dev)
+{
+	tg3_interrupt(dev->irq, dev, NULL);
+}
+#endif
+
 static void tg3_reset_task(void *_data)
 {
 	struct tg3 *tp = _data;
@@ -2795,32 +2834,17 @@ static int tg3_start_xmit_4gbug(struct s
 
 	/* Packets are ready, update Tx producer idx local and on card. */
 	if (tp->tg3_flags & TG3_FLAG_HOST_TXDS) {
-		tw32_mailbox((MAILBOX_SNDHOST_PROD_IDX_0 +
+		tw32_tx_mbox((MAILBOX_SNDHOST_PROD_IDX_0 +
 			      TG3_64BIT_REG_LOW), entry);
-		if (tp->tg3_flags & TG3_FLAG_TXD_MBOX_HWBUG)
-			tw32_mailbox((MAILBOX_SNDHOST_PROD_IDX_0 +
-				      TG3_64BIT_REG_LOW), entry);
-		if (tp->tg3_flags & TG3_FLAG_MBOX_WRITE_REORDER)
-			tr32(MAILBOX_SNDHOST_PROD_IDX_0 +
-			     TG3_64BIT_REG_LOW);
 	} else {
 		/* First, make sure tg3 sees last descriptor fully
 		 * in SRAM.
 		 */
 		if (tp->tg3_flags & TG3_FLAG_MBOX_WRITE_REORDER)
-			tr32(MAILBOX_SNDNIC_PROD_IDX_0 +
-			     TG3_64BIT_REG_LOW);
+			tr32(MAILBOX_SNDNIC_PROD_IDX_0 + TG3_64BIT_REG_LOW);
 
-		tw32_mailbox((MAILBOX_SNDNIC_PROD_IDX_0 +
+		tw32_tx_mbox((MAILBOX_SNDNIC_PROD_IDX_0 +
 			      TG3_64BIT_REG_LOW), entry);
-		if (tp->tg3_flags & TG3_FLAG_TXD_MBOX_HWBUG)
-			tw32_mailbox((MAILBOX_SNDNIC_PROD_IDX_0 +
-				      TG3_64BIT_REG_LOW), entry);
-
-		/* Now post the mailbox write itself.  */
-		if (tp->tg3_flags & TG3_FLAG_MBOX_WRITE_REORDER)
-			tr32(MAILBOX_SNDNIC_PROD_IDX_0 +
-			     TG3_64BIT_REG_LOW);
 	}
 
 	tp->tx_prod = entry;
@@ -2965,11 +2989,8 @@ static int tg3_start_xmit(struct sk_buff
 	 * the double-write bug tests.
 	 */
 	if (tp->tg3_flags & TG3_FLAG_HOST_TXDS) {
-		tw32_mailbox((MAILBOX_SNDHOST_PROD_IDX_0 +
+		tw32_tx_mbox((MAILBOX_SNDHOST_PROD_IDX_0 +
 			      TG3_64BIT_REG_LOW), entry);
-		if (tp->tg3_flags & TG3_FLAG_MBOX_WRITE_REORDER)
-			tr32(MAILBOX_SNDHOST_PROD_IDX_0 +
-			     TG3_64BIT_REG_LOW);
 	} else {
 		/* First, make sure tg3 sees last descriptor fully
 		 * in SRAM.
@@ -2978,13 +2999,8 @@ static int tg3_start_xmit(struct sk_buff
 			tr32(MAILBOX_SNDNIC_PROD_IDX_0 +
 			     TG3_64BIT_REG_LOW);
 
-		tw32_mailbox((MAILBOX_SNDNIC_PROD_IDX_0 +
+		tw32_tx_mbox((MAILBOX_SNDNIC_PROD_IDX_0 +
 			      TG3_64BIT_REG_LOW), entry);
-
-		/* Now post the mailbox write itself.  */
-		if (tp->tg3_flags & TG3_FLAG_MBOX_WRITE_REORDER)
-			tr32(MAILBOX_SNDNIC_PROD_IDX_0 +
-			     TG3_64BIT_REG_LOW);
 	}
 
 	tp->tx_prod = entry;
@@ -3420,7 +3436,10 @@ static int tg3_abort_hw(struct tg3 *tp)
 	if (err)
 		goto out;
 
-	memset(tp->hw_status, 0, TG3_HW_STATUS_SIZE);
+	if (tp->hw_status)
+		memset(tp->hw_status, 0, TG3_HW_STATUS_SIZE);
+	if (tp->hw_stats)
+		memset(tp->hw_stats, 0, sizeof(struct tg3_hw_stats));
 
 out:
 	return err;
@@ -4794,9 +4813,7 @@ static int tg3_reset_hw(struct tg3 *tp)
 	tp->tx_prod = 0;
 	tp->tx_cons = 0;
 	tw32_mailbox(MAILBOX_SNDHOST_PROD_IDX_0 + TG3_64BIT_REG_LOW, 0);
-	tw32_mailbox(MAILBOX_SNDNIC_PROD_IDX_0 + TG3_64BIT_REG_LOW, 0);
-	if (tp->tg3_flags & TG3_FLAG_MBOX_WRITE_REORDER)
-		tr32(MAILBOX_SNDNIC_PROD_IDX_0 + TG3_64BIT_REG_LOW);
+	tw32_tx_mbox(MAILBOX_SNDNIC_PROD_IDX_0 + TG3_64BIT_REG_LOW, 0);
 
 	if (tp->tg3_flags & TG3_FLAG_HOST_TXDS) {
 		tg3_set_bdinfo(tp, NIC_SRAM_SEND_RCB,
@@ -4823,9 +4840,7 @@ static int tg3_reset_hw(struct tg3 *tp)
 	}
 
 	tp->rx_rcb_ptr = 0;
-	tw32_mailbox(MAILBOX_RCVRET_CON_IDX_0 + TG3_64BIT_REG_LOW, 0);
-	if (tp->tg3_flags & TG3_FLAG_MBOX_WRITE_REORDER)
-		tr32(MAILBOX_RCVRET_CON_IDX_0 + TG3_64BIT_REG_LOW);
+	tw32_rx_mbox(MAILBOX_RCVRET_CON_IDX_0 + TG3_64BIT_REG_LOW, 0);
 
 	tg3_set_bdinfo(tp, NIC_SRAM_RCV_RET_RCB,
 		       tp->rx_rcb_mapping,
@@ -4834,19 +4849,13 @@ static int tg3_reset_hw(struct tg3 *tp)
 		       0);
 
 	tp->rx_std_ptr = tp->rx_pending;
-	tw32_mailbox(MAILBOX_RCV_STD_PROD_IDX + TG3_64BIT_REG_LOW,
+	tw32_rx_mbox(MAILBOX_RCV_STD_PROD_IDX + TG3_64BIT_REG_LOW,
 		     tp->rx_std_ptr);
-	if (tp->tg3_flags & TG3_FLAG_MBOX_WRITE_REORDER)
-		tr32(MAILBOX_RCV_STD_PROD_IDX + TG3_64BIT_REG_LOW);
 
-	if (tp->tg3_flags & TG3_FLAG_JUMBO_ENABLE)
-		tp->rx_jumbo_ptr = tp->rx_jumbo_pending;
-	else
-		tp->rx_jumbo_ptr = 0;
-	tw32_mailbox(MAILBOX_RCV_JUMBO_PROD_IDX + TG3_64BIT_REG_LOW,
+	tp->rx_jumbo_ptr = (tp->tg3_flags & TG3_FLAG_JUMBO_ENABLE) ?
+						tp->rx_jumbo_pending : 0;
+	tw32_rx_mbox(MAILBOX_RCV_JUMBO_PROD_IDX + TG3_64BIT_REG_LOW,
 		     tp->rx_jumbo_ptr);
-	if (tp->tg3_flags & TG3_FLAG_MBOX_WRITE_REORDER)
-		tr32(MAILBOX_RCV_JUMBO_PROD_IDX + TG3_64BIT_REG_LOW);
 
 	/* Initialize MAC address and backoff seed. */
 	__tg3_set_mac_addr(tp);
@@ -6919,6 +6928,12 @@ static int __devinit tg3_get_invariants(
 	     (tp->pci_chip_rev_id != CHIPREV_ID_5705_A1)))
 		tp->tg3_flags2 |= TG3_FLG2_NO_ETH_WIRE_SPEED;
 
+	if (GET_CHIP_REV(tp->pci_chip_rev_id) == CHIPREV_5703_AX ||
+	    GET_CHIP_REV(tp->pci_chip_rev_id) == CHIPREV_5704_AX)
+		tp->tg3_flags2 |= TG3_FLG2_PHY_ADC_BUG;
+	if (tp->pci_chip_rev_id == CHIPREV_ID_5704_A0)
+		tp->tg3_flags2 |= TG3_FLG2_PHY_5704_A0_BUG;
+
 	/* Only 5701 and later support tagged irq status mode.
 	 * Also, 5788 chips cannot use tagged irq status.
 	 *
@@ -7421,8 +7436,8 @@ static int __devinit tg3_test_dma(struct
 		for (i = 0; i < TEST_BUFFER_SIZE / sizeof(u32); i++) {
 			u32 val;
 			tg3_read_mem(tp, 0x2100 + (i*4), &val);
-			if (val != p[i]) {
-				printk( KERN_ERR "  tg3_test_dma()  Card buffer currupted on write! (%d != %d)\n", val, i);
+			if (le32_to_cpu(val) != p[i]) {
+				printk(KERN_ERR "  tg3_test_dma()  Card buffer corrupted on write! (%d != %d)\n", val, i);
 				/* ret = -ENODEV here? */
 			}
 			p[i] = 0;
@@ -7523,23 +7538,24 @@ static char * __devinit tg3_phy_string(s
 
 static struct pci_dev * __devinit tg3_find_5704_peer(struct tg3 *tp)
 {
-	struct pci_dev *peer = NULL;
-	unsigned int func;
-
-	for (func = 0; func < 7; func++) {
-		unsigned int devfn = tp->pdev->devfn;
-
-		devfn &= ~7;
-		devfn |= func;
+	struct pci_dev *peer;
+	unsigned int func, devnr = tp->pdev->devfn & ~7;
 
-		if (devfn == tp->pdev->devfn)
-			continue;
-		peer = pci_find_slot(tp->pdev->bus->number, devfn);
-		if (peer)
+	for (func = 0; func < 8; func++) {
+		peer = pci_get_slot(tp->pdev->bus, devnr | func);
+		if (peer && peer != tp->pdev)
 			break;
+		pci_dev_put(peer);
 	}
 	if (!peer || peer == tp->pdev)
 		BUG();
+
+	/*
+	 * We don't need to keep the refcount elevated; there's no way
+	 * to remove one half of this device without removing the other
+	 */
+	pci_dev_put(peer);
+
 	return peer;
 }
 
@@ -7696,6 +7712,9 @@ static int __devinit tg3_init_one(struct
 	dev->watchdog_timeo = TG3_TX_TIMEOUT;
 	dev->change_mtu = tg3_change_mtu;
 	dev->irq = pdev->irq;
+#ifdef CONFIG_NET_POLL_CONTROLLER
+	dev->poll_controller = tg3_poll_controller;
+#endif
 
 	err = tg3_get_invariants(tp);
 	if (err) {
@@ -7749,6 +7768,18 @@ static int __devinit tg3_init_one(struct
 		goto err_out_iounmap;
 	}
 
+	/*
+	 * Reset chip in case UNDI or EFI driver did not shutdown
+	 * DMA self test will enable WDMAC and we'll see (spurious)
+	 * pending DMA on the PCI bus at that point.
+	 */
+	if ((tr32(HOSTCC_MODE) & HOSTCC_MODE_ENABLE) ||
+	    (tr32(WDMAC_MODE) & WDMAC_MODE_ENABLE)) {
+		pci_save_state(tp->pdev, tp->pci_cfg_state);
+		tw32(MEMARB_MODE, MEMARB_MODE_ENABLE);
+		tg3_halt(tp);
+	}
+
 	err = tg3_test_dma(tp);
 	if (err) {
 		printk(KERN_ERR PFX "DMA engine test failed, aborting.\n");
--- diff/drivers/net/tg3.h	2003-09-17 12:28:08.000000000 +0100
+++ source/drivers/net/tg3.h	2004-02-23 13:56:44.000000000 +0000
@@ -129,6 +129,9 @@
 #define   CHIPREV_5700_BX		 0x71
 #define   CHIPREV_5700_CX		 0x72
 #define   CHIPREV_5701_AX		 0x00
+#define   CHIPREV_5703_AX		 0x10
+#define   CHIPREV_5704_AX		 0x20
+#define   CHIPREV_5704_BX		 0x21
 #define  GET_METAL_REV(CHIP_REV_ID)	((CHIP_REV_ID) & 0xff)
 #define   METAL_REV_A0			 0x00
 #define   METAL_REV_A1			 0x01
@@ -1889,7 +1892,11 @@ struct tg3 {
 #define TG3_FLAG_ENABLE_ASF		0x00000020
 #define TG3_FLAG_5701_REG_WRITE_BUG	0x00000040
 #define TG3_FLAG_POLL_SERDES		0x00000080
+#if defined(CONFIG_X86)
 #define TG3_FLAG_MBOX_WRITE_REORDER	0x00000100
+#else
+#define TG3_FLAG_MBOX_WRITE_REORDER	0	/* disables code too */
+#endif
 #define TG3_FLAG_PCIX_TARGET_HWBUG	0x00000200
 #define TG3_FLAG_WOL_SPEED_100MB	0x00000400
 #define TG3_FLAG_WOL_ENABLE		0x00000800
@@ -1920,6 +1927,8 @@ struct tg3 {
 #define TG3_FLG2_IS_5788		0x00000008
 #define TG3_FLG2_MAX_RXPEND_64		0x00000010
 #define TG3_FLG2_TSO_CAPABLE		0x00000020
+#define TG3_FLG2_PHY_ADC_BUG		0x00000040
+#define TG3_FLG2_PHY_5704_A0_BUG	0x00000080
 
 	u32				split_mode_max_reqs;
 #define SPLIT_MODE_5704_MAX_REQ		3
--- diff/drivers/net/tlan.c	2003-11-25 15:24:58.000000000 +0000
+++ source/drivers/net/tlan.c	2004-02-23 13:56:44.000000000 +0000
@@ -814,6 +814,14 @@ static void  __init TLan_EisaProbe (void
 
 } /* TLan_EisaProbe */
 
+#ifdef CONFIG_NET_POLL_CONTROLLER
+static void TLan_Poll(struct net_device *dev)
+{
+	disable_irq(dev->irq);
+	TLan_HandleInterrupt(dev->irq, dev, NULL);
+	enable_irq(dev->irq);
+}
+#endif
 
 	
 
@@ -893,6 +901,9 @@ static int TLan_Init( struct net_device 
 	dev->get_stats = &TLan_GetStats;
 	dev->set_multicast_list = &TLan_SetMulticastList;
 	dev->do_ioctl = &TLan_ioctl;
+#ifdef CONFIG_NET_POLL_CONTROLLER
+	dev->poll_controller = &TLan_Poll;
+#endif
 	dev->tx_timeout = &TLan_tx_timeout;
 	dev->watchdog_timeo = TX_TIMEOUT;
 
--- diff/drivers/net/tokenring/3c359.c	2004-02-18 08:54:10.000000000 +0000
+++ source/drivers/net/tokenring/3c359.c	2004-02-23 13:56:44.000000000 +0000
@@ -641,7 +641,20 @@ static int xl_open(struct net_device *de
 	 */
 	/* These MUST be on 8 byte boundaries */
 	xl_priv->xl_tx_ring = kmalloc((sizeof(struct xl_tx_desc) * XL_TX_RING_SIZE) + 7, GFP_DMA | GFP_KERNEL) ; 
+	if (xl_priv->xl_tx_ring == NULL) {
+		printk(KERN_WARNING "%s: Not enough memory to allocate rx buffers.\n",
+				     dev->name);
+		free_irq(dev->irq,dev);
+		return -ENOMEM;
+	}
 	xl_priv->xl_rx_ring = kmalloc((sizeof(struct xl_rx_desc) * XL_RX_RING_SIZE) +7, GFP_DMA | GFP_KERNEL) ; 
+	if (xl_priv->xl_tx_ring == NULL) {
+		printk(KERN_WARNING "%s: Not enough memory to allocate rx buffers.\n",
+				     dev->name);
+		free_irq(dev->irq,dev);
+		kfree(xl_priv->xl_tx_ring);
+		return -ENOMEM;
+	}
 	memset(xl_priv->xl_tx_ring,0,sizeof(struct xl_tx_desc) * XL_TX_RING_SIZE) ; 
 	memset(xl_priv->xl_rx_ring,0,sizeof(struct xl_rx_desc) * XL_RX_RING_SIZE) ; 
 
@@ -1129,7 +1142,7 @@ static irqreturn_t xl_interrupt(int irq,
 				xl_freemem(dev) ; 
 				free_irq(dev->irq,dev); 
 				unregister_netdev(dev) ; 
-				kfree(dev) ;  
+				free_netdev(dev) ;  
 				xl_reset(dev) ; 
 				writel(ACK_INTERRUPT | LATCH_ACK, xl_mmio + MMIO_COMMAND) ; 
 				spin_unlock(&xl_priv->xl_lock) ; 
--- diff/drivers/net/tulip/de4x5.c	2003-11-25 15:24:58.000000000 +0000
+++ source/drivers/net/tulip/de4x5.c	2004-02-23 13:56:44.000000000 +0000
@@ -474,9 +474,9 @@
 #include <asm/byteorder.h>
 #include <asm/unaligned.h>
 #include <asm/uaccess.h>
-#ifdef CONFIG_PPC
+#ifdef CONFIG_PPC_MULTIPLATFORM
 #include <asm/machdep.h>
-#endif /* CONFIG_PPC */
+#endif /* CONFIG_PPC_MULTIPLATFORM */
 
 #include "de4x5.h"
 
@@ -4146,12 +4146,12 @@ get_hw_addr(struct net_device *dev)
     /* If possible, try to fix a broken card - SMC only so far */
     srom_repair(dev, broken);
 
-#ifdef CONFIG_PPC
+#ifdef CONFIG_PPC_MULTIPLATFORM
     /* 
     ** If the address starts with 00 a0, we have to bit-reverse
     ** each byte of the address.
     */
-    if ( (ppc_md.ppc_machine & _MACH_Pmac) &&
+    if ( (_machine & _MACH_Pmac) &&
 	 (dev->dev_addr[0] == 0) &&
 	 (dev->dev_addr[1] == 0xa0) )
     {
@@ -4163,7 +4163,7 @@ get_hw_addr(struct net_device *dev)
 		    dev->dev_addr[i] = ((x & 0x55) << 1) + ((x & 0xaa) >> 1);
 	    }
     }
-#endif /* CONFIG_PPC */
+#endif /* CONFIG_PPC_MULTIPLATFORM */
 
     /* Test for a bad enet address */
     status = test_bad_enet(dev, status);
@@ -5745,7 +5745,7 @@ static int __init de4x5_module_init (voi
 {
 	int err = 0;
 
-#if CONFIG_PCI
+#ifdef CONFIG_PCI
 	err = pci_module_init (&de4x5_pci_driver);
 #endif
 #ifdef CONFIG_EISA
@@ -5757,7 +5757,7 @@ static int __init de4x5_module_init (voi
 
 static void __exit de4x5_module_exit (void)
 {
-#if CONFIG_PCI
+#ifdef CONFIG_PCI
 	pci_unregister_driver (&de4x5_pci_driver);
 #endif
 #ifdef CONFIG_EISA
--- diff/drivers/net/tulip/interrupt.c	2004-02-18 08:54:10.000000000 +0000
+++ source/drivers/net/tulip/interrupt.c	2004-02-23 13:56:44.000000000 +0000
@@ -211,10 +211,10 @@ int tulip_poll(struct net_device *dev, i
                                        if (tp->rx_buffers[entry].mapping !=
                                            le32_to_cpu(tp->rx_ring[entry].buffer1)) {
                                                printk(KERN_ERR "%s: Internal fault: The skbuff addresses "
-                                                      "do not match in tulip_rx: %08x vs. %08x %p / %p.\n",
+                                                      "do not match in tulip_rx: %08x vs. %08llx %p / %p.\n",
                                                       dev->name,
                                                       le32_to_cpu(tp->rx_ring[entry].buffer1),
-                                                      tp->rx_buffers[entry].mapping,
+                                                      (unsigned long long)tp->rx_buffers[entry].mapping,
                                                       skb->head, temp);
                                        }
 #endif
--- diff/drivers/net/tulip/tulip_core.c	2004-02-18 08:54:10.000000000 +0000
+++ source/drivers/net/tulip/tulip_core.c	2004-02-23 13:56:44.000000000 +0000
@@ -253,7 +253,7 @@ static void tulip_down(struct net_device
 static struct net_device_stats *tulip_get_stats(struct net_device *dev);
 static int private_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
 static void set_rx_mode(struct net_device *dev);
-
+static void poll_tulip(struct net_device *dev);
 
 
 static void tulip_set_power_state (struct tulip_private *tp,
@@ -1512,7 +1512,7 @@ static int __devinit tulip_init_one (str
 		}
 	}
 	/* Lite-On boards have the address byte-swapped. */
-	if ((dev->dev_addr[0] == 0xA0  ||  dev->dev_addr[0] == 0xC0)
+	if ((dev->dev_addr[0] == 0xA0  ||  dev->dev_addr[0] == 0xC0 || dev->dev_addr[0] == 0x02)
 		&&  dev->dev_addr[1] == 0x00)
 		for (i = 0; i < 6; i+=2) {
 			char tmp = dev->dev_addr[i];
@@ -1618,6 +1618,9 @@ static int __devinit tulip_init_one (str
 	dev->get_stats = tulip_get_stats;
 	dev->do_ioctl = private_ioctl;
 	dev->set_multicast_list = set_rx_mode;
+#ifdef CONFIG_NET_POLL_CONTROLLER
+	dev->poll_controller = &poll_tulip;
+#endif
 
 	if (register_netdev(dev))
 		goto err_out_free_ring;
@@ -1774,6 +1777,22 @@ static void __devexit tulip_remove_one (
 	/* pci_power_off (pdev, -1); */
 }
 
+#ifdef CONFIG_NET_POLL_CONTROLLER
+/*
+ * Polling 'interrupt' - used by things like netconsole to send skbs
+ * without having to re-enable interrupts. It's not called while
+ * the interrupt routine is executing.
+ */
+
+static void poll_tulip (struct net_device *dev)
+{
+	/* disable_irq here is not very nice, but with the lockless
+	   interrupt handler we have no other choice. */
+	disable_irq(dev->irq);
+	tulip_interrupt (dev->irq, dev, NULL);
+	enable_irq(dev->irq);
+}
+#endif
 
 static struct pci_driver tulip_driver = {
 	.name		= DRV_NAME,
--- diff/drivers/net/tun.c	2004-02-18 08:54:10.000000000 +0000
+++ source/drivers/net/tun.c	2004-02-23 13:56:44.000000000 +0000
@@ -118,12 +118,10 @@ static struct net_device_stats *tun_net_
 }
 
 /* Initialize net device. */
-int tun_net_init(struct net_device *dev)
+static void tun_net_init(struct net_device *dev)
 {
 	struct tun_struct *tun = (struct tun_struct *)dev->priv;
    
-	DBG(KERN_INFO "%s: tun_net_init\n", tun->dev->name);
-
 	switch (tun->flags & TUN_TYPE_MASK) {
 	case TUN_TUN_DEV:
 		/* Point-to-Point TUN Device */
@@ -147,9 +145,7 @@ int tun_net_init(struct net_device *dev)
 
 		ether_setup(dev);
 		break;
-	};
-
-	return 0;
+	}
 }
 
 /* Character device part */
@@ -351,7 +347,6 @@ static void tun_setup(struct net_device 
 	init_waitqueue_head(&tun->read_wait);
 
 	tun->owner = -1;
-	dev->init = tun_net_init;
 
 	SET_MODULE_OWNER(dev);
 	dev->open = tun_net_open;
@@ -422,6 +417,8 @@ static int tun_set_iff(struct file *file
 		tun->dev = dev;
 		tun->flags = flags;
 
+		tun_net_init(dev);
+
 		if (strchr(dev->name, '%')) {
 			err = dev_alloc_name(dev, dev->name);
 			if (err < 0)
--- diff/drivers/net/via-rhine.c	2003-09-17 12:28:08.000000000 +0100
+++ source/drivers/net/via-rhine.c	2004-02-23 13:56:44.000000000 +0000
@@ -615,6 +615,15 @@ static void __devinit reload_eeprom(long
 			break;
 }
 
+#ifdef CONFIG_NET_POLL_CONTROLLER
+static void via_rhine_poll(struct net_device *dev)
+{
+	disable_irq(dev->irq);
+	via_rhine_interrupt(dev->irq, (void *)dev, NULL);
+	enable_irq(dev->irq);
+}
+#endif
+
 static int __devinit via_rhine_init_one (struct pci_dev *pdev,
 					 const struct pci_device_id *ent)
 {
@@ -784,6 +793,9 @@ static int __devinit via_rhine_init_one 
 	dev->ethtool_ops = &netdev_ethtool_ops;
 	dev->tx_timeout = via_rhine_tx_timeout;
 	dev->watchdog_timeo = TX_TIMEOUT;
+#ifdef CONFIG_NET_POLL_CONTROLLER
+	dev->poll_controller = via_rhine_poll;
+#endif
 	if (np->drv_flags & ReqTxAlign)
 		dev->features |= NETIF_F_SG|NETIF_F_HW_CSUM;
 
--- diff/drivers/net/wan/Kconfig	2004-02-18 08:54:10.000000000 +0000
+++ source/drivers/net/wan/Kconfig	2004-02-23 13:56:44.000000000 +0000
@@ -8,17 +8,18 @@ menu "Wan interfaces"
 config WAN
 	bool "Wan interfaces support"
 	---help---
-	  Wide Area Networks (WANs), such as X.25, frame relay and leased
+	  Wide Area Networks (WANs), such as X.25, Frame Relay and leased
 	  lines, are used to interconnect Local Area Networks (LANs) over vast
 	  distances with data transfer rates significantly higher than those
 	  achievable with commonly used asynchronous modem connections.
+
 	  Usually, a quite expensive external device called a `WAN router' is
-	  needed to connect to a WAN.
+	  needed to connect to a WAN. As an alternative, a relatively
+	  inexpensive WAN interface card can allow your Linux box to directly
+	  connect to a WAN.
 
-	  As an alternative, a relatively inexpensive WAN interface card can
-	  allow your Linux box to directly connect to a WAN. If you have one
-	  of those cards and wish to use it under Linux, say Y here and also
-	  to the WAN driver for your card, below.
+	  If you have one of those cards and wish to use it under Linux,
+	  say Y here and also to the WAN driver for your card.
 
 	  If unsure, say N.
 
@@ -27,32 +28,34 @@ config HOSTESS_SV11
 	tristate "Comtrol Hostess SV-11 support"
 	depends on WAN && ISA && m
 	help
-	  This is a network card for low speed synchronous serial links, at
-	  up to 256Kbps. It supports both PPP and Cisco HDLC.
+	  Driver for Comtrol Hostess SV-11 network card which
+	  operates on low speed synchronous serial links at up to
+	  256Kbps, supporting PPP and Cisco HDLC.
 
-	  At this point, the driver can only be compiled as a module.
+	  The driver will be compiled as a module: the
+	  module will be called hostess_sv11.
 
 # The COSA/SRP driver has not been tested as non-modular yet.
 config COSA
 	tristate "COSA/SRP sync serial boards support"
 	depends on WAN && ISA && m
 	---help---
-	  This is a driver for COSA and SRP synchronous serial boards. These
-	  boards allow to connect synchronous serial devices (for example
+	  Driver for COSA and SRP synchronous serial boards.
+
+	  These boards allow to connect synchronous serial devices (for example
 	  base-band modems, or any other device with the X.21, V.24, V.35 or
 	  V.36 interface) to your Linux box. The cards can work as the
 	  character device, synchronous PPP network device, or the Cisco HDLC
 	  network device.
 
-	  To actually use the COSA or SRP board, you will need user-space
-	  utilities for downloading the firmware to the cards and to set them
-	  up. Look at the <http://www.fi.muni.cz/~kas/cosa/> for more
-	  information about the cards (including the pointer to the user-space
-	  utilities). You can also read the comment at the top of the
-	  <file:drivers/net/wan/cosa.c> for details about the cards and the driver
-	  itself.
+	  You will need user-space utilities COSA or SRP boards for downloading
+ 	  the firmware to the cards and to set them up. Look at the
+	  <http://www.fi.muni.cz/~kas/cosa/> for more information. You can also
+	  read the comment at the top of the <file:drivers/net/wan/cosa.c> for
+	  details about the cards and the driver itself.
 
-	  The driver will be compiled as a module: the module will be called cosa.
+	  The driver will be compiled as a module: the
+	  module will be called cosa.
 
 #
 # COMX drivers
@@ -62,16 +65,16 @@ config COMX
 	tristate "MultiGate (COMX) synchronous serial boards support"
 	depends on WAN && (ISA || PCI) && BROKEN
 	---help---
-	  Say Y if you want to use any board from the MultiGate (COMX) family.
-	  These boards are synchronous serial adapters for the PC,
-	  manufactured by ITConsult-Pro Co, Hungary.
-
-	  Read <file:Documentation/networking/comx.txt> for help on
-	  configuring and using COMX interfaces.  Further info on these cards
-	  can be found at <http://www.itc.hu/> or <info@itc.hu>.
+	  Drivers for the PC synchronous serial adapters by
+	  ITConsult-Pro Co, Hungary.
 
-	  You must say Y to "/proc file system support" (CONFIG_PROC_FS) to
-	  use this driver.
+	  Read <file:Documentation/networking/comx.txt> for help on configuring
+	  and using COMX interfaces. Further info on these cards can be found
+	  at <http://www.itc.hu/> or <info@itc.hu>.
+
+	  Say Y if you want to use any board from the MultiGate (COMX)
+	  family, you must also say Y to "/proc file system support"
+	  (CONFIG_PROC_FS) in order to use these drivers.
 
 	  To compile this driver as a module, choose M here: the
 	  module will be called comx.
@@ -80,12 +83,13 @@ config COMX_HW_COMX
 	tristate "Support for COMX/CMX/HiCOMX boards"
 	depends on COMX
 	help
-	  Hardware driver for the 'CMX', 'COMX' and 'HiCOMX' boards from the
-	  MultiGate family. Say Y if you have one of these.
+	  Driver for the 'CMX', 'COMX' and 'HiCOMX' boards.
 
 	  You will need additional firmware to use these cards, which are
 	  downloadable from <ftp://ftp.itc.hu/>.
 
+	  Say Y if you have a board like this.
+
 	  To compile this driver as a module, choose M here: the
 	  module will be called comx-hw-comx.
 
@@ -93,7 +97,8 @@ config COMX_HW_LOCOMX
 	tristate "Support for LoCOMX board"
 	depends on COMX
 	help
-	  Hardware driver for the 'LoCOMX' board from the MultiGate family.
+	  Driver for the 'LoCOMX' board.
+
 	  Say Y if you have a board like this.
 
 	  To compile this driver as a module, choose M here: the
@@ -103,8 +108,7 @@ config COMX_HW_MIXCOM
 	tristate "Support for MixCOM board"
 	depends on COMX
 	---help---
-	  Hardware driver for the 'MixCOM' board from the MultiGate family.
-	  Say Y if you have a board like this.
+	  Driver for the 'MixCOM' board.
 
 	  If you want to use the watchdog device on this card, you should
 	  select it in the Watchdog Cards section of the Character Devices
@@ -113,6 +117,8 @@ config COMX_HW_MIXCOM
 	  driver for the flash ROM of this card is available separately on
 	  <ftp://ftp.itc.hu/>.
 
+	  Say Y if you have a board like this.
+
 	  To compile this driver as a module, choose M here: the
 	  module will be called comx-hw-mixcom.
 
@@ -120,58 +126,63 @@ config COMX_HW_MUNICH
 	tristate "Support for MUNICH based boards: SliceCOM, PCICOM (WelCOM)"
 	depends on COMX
 	---help---
-	  Hardware driver for the 'SliceCOM' (channelized E1) and 'PciCOM'
-	  boards (X21) from the MultiGate family.
+	  Driver for the 'SliceCOM' (channelized E1) and 'PciCOM' (X21) boards.
+
+	  Read <file:Documentation/networking/slicecom.txt> for help on
+	  configuring and using SliceCOM interfaces. Further info on these
+	  cards can be found at <http://www.itc.hu> or <info@itc.hu>.
+
+	  Say Y if you have a board like this.
 
 	  To compile this driver as a module, choose M here: the
 	  module will be called comx-hw-munich.
 
-	  Read linux/Documentation/networking/slicecom.txt for help on
-	  configuring and using SliceCOM interfaces. Further info on these cards
-	  can be found at http://www.itc.hu or <info@itc.hu>.
-
 config COMX_PROTO_PPP
 	tristate "Support for HDLC and syncPPP protocols on MultiGate boards"
 	depends on COMX
 	help
-	  Cisco-HDLC and synchronous PPP protocol driver for all MultiGate
-	  boards. Say Y if you want to use either protocol on your MultiGate
-	  boards.
+	  Cisco-HDLC and synchronous PPP protocol driver.
 
-	  To compile this as a module, choose M here: the module will be called
-	  comx-proto-ppp.
+	  Say Y if you want to use either protocol.
+
+	  To compile this as a module, choose M here: the
+	  module will be called comx-proto-ppp.
 
 config COMX_PROTO_LAPB
 	tristate "Support for LAPB protocol on MultiGate boards"
 	depends on WAN && (COMX!=n && LAPB=m && LAPB || LAPB=y && COMX)
 	help
-	  LAPB protocol driver for all MultiGate boards. Say Y if you
-	  want to use this protocol on your MultiGate boards.
+	  LAPB protocol driver.
+
+	  Say Y if you want to use this protocol.
 
-	  To compile this as a module, choose M here: the module will be called
-	  comx-proto-lapb.
+	  To compile this as a module, choose M here: the
+	  module will be called comx-proto-lapb.
 
 config COMX_PROTO_FR
 	tristate "Support for Frame Relay on MultiGate boards"
 	depends on COMX
 	help
-	  Frame Relay protocol driver for all MultiGate boards. Say Y if you
-	  want to use this protocol on your MultiGate boards.
+	  Frame Relay protocol driver.
+
+	  Say Y if you want to use this protocol.
 
-	  To compile this as a module, choose M here: the module will be called
-	  comx-proto-fr.
+	  To compile this as a module, choose M here: the
+	  module will be called comx-proto-fr.
 
 config DSCC4
 	tristate "Etinc PCISYNC serial board support"
 	depends on WAN && PCI && m
 	help
-	  This is a driver for Etinc PCISYNC boards based on the Infineon
-	  (ex. Siemens) DSCC4 chipset. It is supposed to work with the four
-	  ports card. Take a look at <http://www.cogenit.fr/dscc4/>
-	  for further informations about the driver and his configuration.
+	  Driver for Etinc PCISYNC boards based on the Infineon (ex. Siemens)
+	  DSCC4 chipset.
 
-	  To compile this driver as a module, choose M here: the module
-	  will be called dscc4.
+	  This is supposed to work with the four port card. Take a look at
+	  <http://www.cogenit.fr/dscc4/> for further information about the
+	  driver.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called dscc4.
 
 config DSCC4_PCISYNC
 	bool "Etinc PCISYNC features"
@@ -188,13 +199,12 @@ config DSCC4_PCI_RST
 	bool "Hard reset support"
 	depends on DSCC4
 	help
-	  Various DSCC4 bugs forbid any reliable software reset of the asic.
+	  Various DSCC4 bugs forbid any reliable software reset of the ASIC.
 	  As a replacement, some vendors provide a way to assert the PCI #RST
 	  pin of DSCC4 through the GPIO port of the card. If you choose Y,
 	  the driver will make use of this feature before module removal
-	  (i.e. rmmod).
-	  The feature is known to be available on Commtech's cards.
-	  Contact your manufacturer for details.
+	  (i.e. rmmod). The feature is known to be available on Commtech's
+	  cards. Contact your manufacturer for details.
 
 	  Say Y if your card supports this feature.
 
@@ -205,27 +215,27 @@ config LANMEDIA
 	tristate "LanMedia Corp. SSI/V.35, T1/E1, HSSI, T3 boards"
 	depends on WAN && PCI
 	---help---
-	  This is a driver for the following Lan Media family of serial
-	  boards.
+	  Driver for the following Lan Media family of serial boards:
 
-	  LMC 1000 board allows you to connect synchronous serial devices (for
-	  example base-band modems, or any other device with the X.21, V.24,
-	  V.35 or V.36 interface) to your Linux box.
+	  - LMC 1000 board allows you to connect synchronous serial devices
+	  (for example base-band modems, or any other device with the X.21,
+	  V.24, V.35 or V.36 interface) to your Linux box.
 
-	  LMC 1200 with on board DSU board allows you to connect your Linux
+	  - LMC 1200 with on board DSU board allows you to connect your Linux
 	  box dirrectly to a T1 or E1 circuit.
 
-	  LMC 5200 board provides a HSSI interface capable of running up to
-	  52 mbits per second.
+	  - LMC 5200 board provides a HSSI interface capable of running up to
+	  52 Mbits per second.
 
-	  LMC 5245 board connects directly to a T3 circuit saving the
+	  - LMC 5245 board connects directly to a T3 circuit saving the
 	  additional external hardware.
 
-	  To change setting such as syncPPP vs cisco HDLC or clock source you
-	  will need lmcctl.  It is available at <ftp://ftp.lanmedia.com/>.
+	  To change setting such as syncPPP vs Cisco HDLC or clock source you
+	  will need lmcctl.  It is available at <ftp://ftp.lanmedia.com/>
+	  (broken link).
 
-	  To compile this driver as a module, choose M here: the module
-	  will be called lmc.
+	  To compile this driver as a module, choose M here: the
+	  module will be called lmc.
 
 # There is no way to detect a Sealevel board. Force it modular
 config SEALEVEL_4021
@@ -234,93 +244,89 @@ config SEALEVEL_4021
 	help
 	  This is a driver for the Sealevel Systems ACB 56 serial I/O adapter.
 
-	  This driver can only be compiled as a module ( = code which can be
-	  inserted in and removed from the running kernel whenever you want).
-	  If you want to do that, say M here. The module will be called
-	  sealevel.
+	  The driver will be compiled as a module: the
+	  module will be called sealevel.
 
 config SYNCLINK_SYNCPPP
 	tristate "SyncLink HDLC/SYNCPPP support"
 	depends on WAN
 	help
 	  Enables HDLC/SYNCPPP support for the SyncLink WAN driver.
-	  Normally the SyncLink WAN driver works with the main PPP
-	  driver (ppp.c) and pppd program. HDLC/SYNCPPP support allows use
-	  of the Cisco HDLC/PPP driver (syncppp.c).
-	  The SyncLink WAN driver (in character devices) must also be enabled.
+
+	  Normally the SyncLink WAN driver works with the main PPP driver
+	  <file:drivers/net/ppp_generic.c> and pppd program.
+	  HDLC/SYNCPPP support allows use of the Cisco HDLC/PPP driver
+	  <file:drivers/net/wan/syncppp.c>. The SyncLink WAN driver (in
+	  character devices) must also be enabled.
 
 # Generic HDLC
 config HDLC
 	tristate "Generic HDLC layer"
 	depends on WAN
 	help
-	  Say Y to this option if your Linux box contains a WAN card supported
-	  by this driver and you are planning to connect the box to a WAN
-	  ( = Wide Area Network). You will need supporting software from
-	  <http://hq.pm.waw.pl/hdlc/>.
+	  Say Y to this option if your Linux box contains a WAN (Wide Area
+	  Network) card supported by this driver and you are planning to
+	  connect the box to a WAN.
+
+	  You will need supporting software from <http://hq.pm.waw.pl/hdlc/>.
 	  Generic HDLC driver currently supports raw HDLC, Cisco HDLC, Frame
 	  Relay, synchronous Point-to-Point Protocol (PPP) and X.25.
 
- 	  To compile this driver as a module, choose M here: the module
-	  will be called hdlc.
+ 	  To compile this driver as a module, choose M here: the
+	  module will be called hdlc.
 
-	  If unsure, say N here.
+	  If unsure, say N.
 
 config HDLC_RAW
 	bool "Raw HDLC support"
 	depends on HDLC
 	help
-	  Say Y to this option if you want generic HDLC driver to support
-	  raw HDLC over WAN (Wide Area Network) connections.
+	  Generic HDLC driver supporting raw HDLC over WAN connections.
 
-	  If unsure, say N here.
+	  If unsure, say N.
 
 config HDLC_RAW_ETH
 	bool "Raw HDLC Ethernet device support"
 	depends on HDLC
 	help
-	  Say Y to this option if you want generic HDLC driver to support
-	  raw HDLC Ethernet device emulation over WAN (Wide Area Network)
-	  connections.
+	  Generic HDLC driver supporting raw HDLC Ethernet device emulation
+	  over WAN connections.
+
 	  You will need it for Ethernet over HDLC bridges.
 
-	  If unsure, say N here.
+	  If unsure, say N.
 
 config HDLC_CISCO
 	bool "Cisco HDLC support"
 	depends on HDLC
 	help
-	  Say Y to this option if you want generic HDLC driver to support
-	  Cisco HDLC over WAN (Wide Area Network) connections.
+	  Generic HDLC driver supporting Cisco HDLC over WAN connections.
 
-	  If unsure, say N here.
+	  If unsure, say N.
 
 config HDLC_FR
 	bool "Frame Relay support"
 	depends on HDLC
 	help
-	  Say Y to this option if you want generic HDLC driver to support
-	  Frame-Relay protocol over WAN (Wide Area Network) connections.
+	  Generic HDLC driver supporting Frame Relay over WAN connections.
 
-	  If unsure, say N here.
+	  If unsure, say N.
 
 config HDLC_PPP
 	bool "Synchronous Point-to-Point Protocol (PPP) support"
 	depends on HDLC
 	help
-	  Say Y to this option if you want generic HDLC driver to support
-	  PPP over WAN (Wide Area Network) connections.
+	  Generic HDLC driver supporting PPP over WAN connections.
 
-	  If unsure, say N here.
+	  If unsure, say N.
 
 config HDLC_X25
 	bool "X.25 protocol support"
 	depends on HDLC && (LAPB=m && HDLC=m || LAPB=y)
 	help
-	  Say Y to this option if you want generic HDLC driver to support
-	  X.25 protocol over WAN (Wide Area Network) connections.
+	  Generic HDLC driver supporting X.25 over WAN connections.
 
-	  If unsure, say N here.
+	  If unsure, say N.
 
 comment "X.25/LAPB support is disabled"
 	depends on WAN && HDLC && (LAPB!=m || HDLC!=m) && LAPB!=y
@@ -329,63 +335,61 @@ config PCI200SYN
 	tristate "Goramo PCI200SYN support"
 	depends on HDLC && PCI
 	help
-	  This driver is for PCI200SYN cards made by Goramo sp. j.
+	  Driver for PCI200SYN cards by Goramo sp. j.
+
 	  If you have such a card, say Y here and see
-	  <http://hq.pm.waw.pl/pub/hdlc/>
+	  <http://hq.pm.waw.pl/hdlc/>.
 
-	  If you want to compile the driver as a module ( = code which can be
-	  inserted in and removed from the running kernel whenever you want),
-	  say M here and read <file:Documentation/modules.txt>.  The module
-	  will be called pci200syn.
+	  To compile this as a module, choose M here: the
+	  module will be called pci200syn.
 
-	  If unsure, say N here.
+	  If unsure, say N.
 
 config WANXL
 	tristate "SBE Inc. wanXL support"
 	depends on HDLC && PCI
 	help
-	  This driver is for wanXL PCI cards made by SBE Inc.  If you have
-	  such a card, say Y here and see <http://hq.pm.waw.pl/pub/hdlc/>.
+	  Driver for wanXL PCI cards by SBE Inc.
+
+	  If you have such a card, say Y here and see
+	  <http://hq.pm.waw.pl/hdlc/>.
 
-	  If you want to compile the driver as a module ( = code which can be
-	  inserted in and removed from the running kernel whenever you want),
-	  say M here and read <file:Documentation/kbuild/modules.txt>.  The module
-	  will be called wanxl.
+	  To compile this as a module, choose M here: the
+	  module will be called wanxl.
 
-	  If unsure, say N here.
+	  If unsure, say N.
 
 config WANXL_BUILD_FIRMWARE
 	bool "rebuild wanXL firmware"
 	depends on WANXL
 	help
-	  This option allows you to rebuild firmware run by the QUICC
-	  processor. It requires as68k, ld68k and hexdump programs.
-	  You should never need this option.
+	  Allows you to rebuild firmware run by the QUICC processor.
+	  It requires as68k, ld68k and hexdump programs.
 
-	  If unsure, say N here.
+	  You should never need this option, say N.
 
 config PC300
 	tristate "Cyclades-PC300 support (RS-232/V.35, X.21, T1/E1 boards)"
 	depends on HDLC && PCI
 	---help---
-	  This is a driver for the Cyclades-PC300 synchronous communication
-	  boards. These boards provide synchronous serial interfaces to your
+	  Driver for the Cyclades-PC300 synchronous communication boards.
+
+	  These boards provide synchronous serial interfaces to your
 	  Linux box (interfaces currently available are RS-232/V.35, X.21 and
 	  T1/E1). If you wish to support Multilink PPP, please select the
-	  option below this one and read the file README.mlppp provided by PC300
+	  option later and read the file README.mlppp provided by PC300
 	  package.
 
-	  To compile this as a module, choose M here: the module will be
-	  called pc300.
+	  To compile this as a module, choose M here: the module
+	  will be called pc300.
 
-	  If you haven't heard about it, it's safe to say N.
+	  If unsure, say N.
 
 config PC300_MLPPP
 	bool "Cyclades-PC300 MLPPP support"
 	depends on PC300 && PPP_MULTILINK && PPP_SYNC_TTY && HDLC_PPP
 	help
-	  Say 'Y' to this option if you are planning to use Multilink PPP over the
-	  PC300 synchronous communication boards.
+	  Multilink PPP over the PC300 synchronous communication boards.
 
 comment "Cyclades-PC300 MLPPP support is disabled."
 	depends on WAN && HDLC && PC300 && (PPP=n || !PPP_MULTILINK || PPP_SYNC_TTY=n || !HDLC_PPP)
@@ -397,129 +401,141 @@ config N2
 	tristate "SDL RISCom/N2 support"
 	depends on HDLC && ISA
 	help
-	  This driver is for RISCom/N2 single or dual channel ISA cards
-	  made by SDL Communications Inc.  If you have such a card,
-	  say Y here and see <http://hq.pm.waw.pl/pub/hdlc/>.
+	  Driver for RISCom/N2 single or dual channel ISA cards by
+	  SDL Communications Inc.
+
+	  If you have such a card, say Y here and see
+	  <http://hq.pm.waw.pl/hdlc/>.
 
 	  Note that N2csu and N2dds cards are not supported by this driver.
 
 	  To compile this driver as a module, choose M here: the module
 	  will be called n2.
 
-	  If unsure, say N here.
+	  If unsure, say N.
 
 config C101
 	tristate "Moxa C101 support"
 	depends on HDLC && ISA
 	help
-	  This driver is for C101 SuperSync ISA cards made by Moxa
-	  Technologies Co., Ltd. If you have such a card,
-	  say Y here and see <http://hq.pm.waw.pl/pub/hdlc/>
+	  Driver for C101 SuperSync ISA cards by Moxa Technologies Co., Ltd.
 
-	  To compile this driver as a module, choose M here: the module
-	  will be called c101.
+	  If you have such a card, say Y here and see
+	  <http://hq.pm.waw.pl/pub/hdlc/>
 
-	  If unsure, say N here.
+	  To compile this driver as a module, choose M here: the
+	  module will be called c101.
+
+	  If unsure, say N.
 
 config FARSYNC
 	tristate "FarSync T-Series support"
 	depends on HDLC && PCI
 	---help---
-	  This driver supports the FarSync T-Series X.21 (and V.35/V.24) cards
-	  from FarSite Communications Ltd.
+	  Support for the FarSync T-Series X.21 (and V.35/V.24) cards by
+	  FarSite Communications Ltd.
+
 	  Synchronous communication is supported on all ports at speeds up to
 	  8Mb/s (128K on V.24) using synchronous PPP, Cisco HDLC, raw HDLC,
 	  Frame Relay or X.25/LAPB.
 
-	  To compile this driver as a module, choose M here: the module will be
-	  called farsync.  If you want the module to be automatically loaded
-	  when the interface is referenced then you should add
-	  "alias hdlcX farsync" to /etc/modules.conf for each interface, where
-	  X is 0, 1, 2, ...
+	  If you want the module to be automatically loaded when the interface
+	  is referenced then you should add "alias hdlcX farsync" to
+	  /etc/modprobe.conf for each interface, where X is 0, 1, 2, ..., or
+	  simply use "alias hdlc* farsync" to indicate all of them.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called farsync.
 
 config DLCI
-	tristate "Frame relay DLCI support"
+	tristate "Frame Relay DLCI support"
 	depends on WAN
 	---help---
-	  This is support for the frame relay protocol; frame relay is a fast
-	  low-cost way to connect to a remote Internet access provider or to
-	  form a private wide area network. The one physical line from your
-	  box to the local "switch" (i.e. the entry point to the frame relay
-	  network, usually at the phone company) can carry several logical
-	  point-to-point connections to other computers connected to the frame
-	  relay network. For a general explanation of the protocol, check out
-	  <http://www.frforum.com/> on the WWW. To use frame relay, you need
-	  supporting hardware (called FRAD) and certain programs from the
-	  net-tools package as explained in
+	  Support for the Frame Relay protocol.
+
+	  Frame Relay is a fast low-cost way to connect to a remote Internet
+	  access provider or to form a private wide area network. The one
+	  physical line from your box to the local "switch" (i.e. the entry
+	  point to the Frame Relay network, usually at the phone company) can
+	  carry several logical point-to-point connections to other computers
+	  connected to the Frame Relay network. For a general explanation of
+	  the protocol, check out <http://www.mplsforum.org/>.
+
+	  To use frame relay, you need supporting hardware (called FRAD) and
+	  certain programs from the net-tools package as explained in
 	  <file:Documentation/networking/framerelay.txt>.
 
-	  To compile this driver as a module, choose M here: the module will be
-	  called dlci.
+	  To compile this driver as a module, choose M here: the
+	  module will be called dlci.
 
 config DLCI_COUNT
 	int "Max open DLCI"
 	depends on DLCI
 	default "24"
 	help
-	  This is the maximal number of logical point-to-point frame relay
-	  connections (the identifiers of which are called DCLIs) that
-	  the driver can handle. The default is probably fine.
+	  Maximal number of logical point-to-point frame relay connections
+	  (the identifiers of which are called DCLIs) that the driver can
+	  handle.
+
+	  The default is probably fine.
 
 config DLCI_MAX
 	int "Max DLCI per device"
 	depends on DLCI
 	default "8"
 	help
-	  You can specify here how many logical point-to-point frame relay
-	  connections (the identifiers of which are called DCLIs) should be
-	  handled by each of your hardware frame relay access devices. Go with
-	  the default.
+	  How many logical point-to-point frame relay connections (the
+	  identifiers of which are called DCLIs) should be handled by each
+	  of your hardware frame relay access devices.
+
+	  Go with the default.
 
 config SDLA
 	tristate "SDLA (Sangoma S502/S508) support"
 	depends on DLCI && ISA
 	help
-	  Say Y here if you need a driver for the Sangoma S502A, S502E, and
-	  S508 Frame Relay Access Devices. These are multi-protocol cards, but
-	  only frame relay is supported by the driver at this time. Please
-	  read <file:Documentation/networking/framerelay.txt>.
+	  Driver for the Sangoma S502A, S502E, and S508 Frame Relay Access
+	  Devices.
+
+	  These are multi-protocol cards, but only Frame Relay is supported
+	  by the driver at this time. Please read
+	  <file:Documentation/networking/framerelay.txt>.
 
-	  To compile this driver as a module, choose M here: the module will be
-	  called sdla.
+	  To compile this driver as a module, choose M here: the
+	  module will be called sdla.
 
 # Wan router core.
 config WAN_ROUTER_DRIVERS
 	bool "WAN router drivers"
 	depends on WAN && WAN_ROUTER
 	---help---
-	  If you have a WAN interface card and you want your Linux box to act
-	  as a WAN router, thereby connecting you Local Area Network to the
-	  outside world over the WAN connection, say Y here and then to the
-	  driver for your card below. In addition, you need to say Y to "Wan
-	  Router".
+	  Connect LAN to WAN via Linux box.
 
+	  Select driver your card and remember to say Y to "Wan Router."
 	  You will need the wan-tools package which is available from
-	  <ftp://ftp.sangoma.com/>. Read
-	  <file:Documentation/networking/wan-router.txt> for more information.
+	  <ftp://ftp.sangoma.com/>. For more information read:
+	  <file:Documentation/networking/wan-router.txt>.
 
 	  Note that the answer to this question won't directly affect the
 	  kernel: saying N will just cause the configurator to skip all
-	  the questions about WAN router drivers. If unsure, say N.
+	  the questions about WAN router drivers.
+
+	  If unsure, say N.
 
 config VENDOR_SANGOMA
 	tristate "Sangoma WANPIPE(tm) multiprotocol cards"
 	depends on WAN_ROUTER_DRIVERS && WAN_ROUTER && (PCI || ISA) && BROKEN
 	---help---
-	  WANPIPE from Sangoma Technologies Inc. (<http://www.sangoma.com/>)
+	  Driver for S514-PCI/ISA Synchronous Data Link Adapters (SDLA).
+
+	  WANPIPE from Sangoma Technologies Inc. <http://www.sangoma.com/>
 	  is a family of intelligent multiprotocol WAN adapters with data
-	  transfer rates up to 4Mbps. They are also known as Synchronous
-	  Data Link Adapters (SDLA) and are designated as S514-PCI or
-	  S508-ISA.  These cards support
+	  transfer rates up to 4Mbps. Cards support:
 
 	  - X.25, Frame Relay, PPP, Cisco HDLC protocols.
 
-	  - API support for protocols like HDLC (LAPB),
-	  HDLC Streaming, X.25, Frame Relay and BiSync.
+	  - API for protocols like HDLC (LAPB), HDLC Streaming, X.25,
+	  Frame Relay and BiSync.
 
 	  - Ethernet Bridging over Frame Relay protocol.
 
@@ -527,88 +543,89 @@ config VENDOR_SANGOMA
 
 	  - Async PPP (Modem Dialup)
 
-	  If you have one or more of these cards, say M to this option; you
-	  may then also want to read the file
-	  <file:Documentation/networking/wanpipe.txt>.  The next questions
-	  will ask you about the protocols you want the driver to support.
+	  The next questions will ask you about the protocols you want
+	  the driver to support.
+
+	  If you have one or more of these cards, say M to this option;
+	  and read <file:Documentation/networking/wanpipe.txt>.
 
-	  To compile this driver as a module, choose M here: the module will
-	  be called wanpipe.
+	  To compile this driver as a module, choose M here: the
+	  module will be called wanpipe.
 
 config WANPIPE_CHDLC
 	bool "WANPIPE Cisco HDLC support"
 	depends on VENDOR_SANGOMA
 	---help---
-	  Say Y to this option if you are planning to connect a WANPIPE card
-	  to a leased line using the Cisco HDLC protocol. This now supports
-	  Dual Port Cisco HDLC on the S514-PCI/S508-ISA cards.
-	  This support also allows user to build applications using the
-	  HDLC streaming API.
-
-	  CHDLC Streaming driver also supports MULTILINK PPP
-	  support that can bind multiple WANPIPE T1 cards into
-	  a single logical channel.
-
-	  If you say  N, the Cisco HDLC support and
-	  HDLC streaming API and MULTILINK PPP will not be
-	  included in the driver.
+	  Connect a WANPIPE card to a leased line using the Cisco HDLC.
+
+	  - Supports Dual Port Cisco HDLC on the S514-PCI/S508-ISA cards
+	  which allows user to build applications using the HDLC streaming API.
+
+	  - CHDLC Streaming MULTILINK PPP that can bind multiple WANPIPE T1
+	  cards into a single logical channel.
+
+	  Say Y and the Cisco HDLC support, HDLC streaming API and
+	  MULTILINK PPP will be included in the driver.
 
 config WANPIPE_FR
 	bool "WANPIPE Frame Relay support"
 	depends on VENDOR_SANGOMA
 	help
-	  Say Y to this option if you are planning to connect a WANPIPE card
-	  to a frame relay network, or use frame relay API to develope
-	  custom applications over the Frame  Relay protocol.
-	  This feature also contains the Ethernet Bridging over Frame Relay,
-	  where a WANPIPE frame relay link can be directly connected to the
-	  Linux kernel bridge.  If you say N, the frame relay support will
-	  not be included in the driver. The Frame Relay option is
-	  supported on S514-PCI and S508-ISA cards.
+	  Connect a WANPIPE card to a Frame Relay network, or use Frame Felay
+	  API to develope custom applications.
+
+	  Contains the Ethernet Bridging over Frame Relay feature, where
+	  a WANPIPE frame relay link can be directly connected to the Linux
+	  kernel bridge. The Frame Relay option is supported on S514-PCI
+	  and S508-ISA cards.
+
+	  Say Y and the Frame Relay support will be included in the driver.
 
 config WANPIPE_X25
 	bool "WANPIPE X.25 support"
 	depends on VENDOR_SANGOMA
 	help
-	  Say Y to this option if you are planning to connect a WANPIPE card
-	  to an X.25 network.  Note, this feature also includes the X.25 API
-	  support used to develope custom applications over the X.25 protocol.
-	  If you say N, the X.25 support will not be included in the driver.
-	  The X.25 option is supported on S514-PCI and S508-ISA cards.
+	  Connect a WANPIPE card to an X.25 network.
+
+	  Includes the X.25 API support for custom applications over the
+	  X.25 protocol. The X.25 option is supported on S514-PCI and
+	  S508-ISA cards.
+
+	  Say Y and the X.25 support will be included in the driver.
 
 config WANPIPE_PPP
 	bool "WANPIPE PPP support"
 	depends on VENDOR_SANGOMA
 	help
-	  Say Y to this option if you are planning to connect a WANPIPE card
-	  to a leased line using Point-to-Point protocol (PPP). If you say N,
-	  the PPP support will not be included in the driver. The PPP option
-	  is supported on S514-PCI/S508-ISA cards.
+	  Connect a WANPIPE card to a leased line using Point-to-Point
+	  Protocol (PPP).
+
+	  The PPP option is supported on S514-PCI/S508-ISA cards.
+
+	  Say Y and the PPP support will be included in the driver.
 
 config WANPIPE_MULTPPP
 	bool "WANPIPE Multi-Port PPP support"
 	depends on VENDOR_SANGOMA
 	help
-	  Say Y to this option if you are planning to connect a WANPIPE card
-	  to a leased line using Point-to-Point protocol (PPP).  Note, the
-	  MultiPort PPP uses the Linux Kernel SyncPPP protocol over the
-	  Sangoma HDLC Streaming adapter.  In this case each Sangoma adapter
-	  port can support an independent PPP connection.  For example, a
-	  single Quad-Port PCI adapter can support up to four independent
-	  PPP links. If you say N,the PPP support will not be included in the
-	  driver.  The PPP option is supported on S514-PCI/S508-ISA cards.
+	  Connect a WANPIPE card to a leased line using Point-to-Point
+	  Protocol (PPP).
+
+	  Uses in-kernel SyncPPP protocol over the Sangoma HDLC Streaming
+	  adapter. In this case each Sangoma adapter port can support an
+	  independent PPP connection. For example, a single Quad-Port PCI
+	  adapter can support up to four independent PPP links. The PPP
+	  option is supported on S514-PCI/S508-ISA cards.
+
+	  Say Y and the Multi-Port PPP support will be included in the driver.
 
 config CYCLADES_SYNC
 	tristate "Cyclom 2X(tm) cards (EXPERIMENTAL)"
 	depends on WAN_ROUTER_DRIVERS && (PCI || ISA)
 	---help---
-	  Cyclom 2X from Cyclades Corporation (<http://www.cyclades.com/> and
-	  <http://www.cyclades.com.br/>) is an intelligent multiprotocol WAN
-	  adapter with data transfer rates up to 512 Kbps. These cards support
-	  the X.25 and SNA related protocols. If you have one or more of these
-	  cards, say Y to this option. The next questions will ask you about
-	  the protocols you want the driver to support (for now only X.25 is
-	  supported).
+	  Cyclom 2X from Cyclades Corporation <http://www.cyclades.com/> is an
+	  intelligent multiprotocol WAN adapter with data transfer rates up to
+	  512 Kbps. These cards support the X.25 and SNA related protocols.
 
 	  While no documentation is available at this time please grab the
 	  wanconfig tarball in
@@ -618,75 +635,85 @@ config CYCLADES_SYNC
 	  <ftp://ftp.sangoma.com/>).
 
 	  Feel free to contact me or the cycsyn-devel mailing list at
-	  acme@conectiva.com.br and cycsyn-devel@bazar.conectiva.com.br for
-	  additional details, I hope to have documentation available as soon
-	  as possible. (Cyclades Brazil is writing the Documentation).
+	  <acme@conectiva.com.br> and <cycsyn-devel@bazar.conectiva.com.br> for
+	  additional details, I hope to have documentation available as soon as
+	  possible. (Cyclades Brazil is writing the Documentation).
 
-	  To compile this driver as a module, choose M here: the module will be
-	  called cyclomx.
+	  The next questions will ask you about the protocols you want the
+	  driver to support (for now only X.25 is supported).
+
+	  If you have one or more of these cards, say Y to this option.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called cyclomx.
 
 config CYCLOMX_X25
 	bool "Cyclom 2X X.25 support (EXPERIMENTAL)"
 	depends on CYCLADES_SYNC
 	help
-	  Say Y to this option if you are planning to connect a Cyclom 2X card
-	  to an X.25 network.
+	  Connect a Cyclom 2X card to an X.25 network.
 
-	  If you say N, the X.25 support will not be included in the driver
-	  (saves about 11 KB of kernel memory).
+	  Enabling X.25 support will enlarge your kernel by about 11 kB.
 
 # X.25 network drivers
 config LAPBETHER
 	tristate "LAPB over Ethernet driver (EXPERIMENTAL)"
 	depends on WAN && LAPB && X25
 	---help---
-	  This is a driver for a pseudo device (typically called /dev/lapb0)
-	  which allows you to open an LAPB point-to-point connection to some
-	  other computer on your Ethernet network.  In order to do this, you
-	  need to say Y or M to the driver for your Ethernet card as well as
-	  to "LAPB Data Link Driver".
+	  Driver for a pseudo device (typically called /dev/lapb0) which allows
+	  you to open an LAPB point-to-point connection to some other computer
+	  on your Ethernet network.
 
-	  To compile this driver as a module, choose M here: the module
-	  will be called lapbether.  If unsure, say N.
+	  In order to do this, you need to say Y or M to the driver for your
+	  Ethernet card as well as to "LAPB Data Link Driver".
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called lapbether.
+
+	  If unsure, say N.
 
 config X25_ASY
 	tristate "X.25 async driver (EXPERIMENTAL)"
 	depends on WAN && LAPB && X25
 	---help---
-	  This is a driver for sending and receiving X.25 frames over regular
-	  asynchronous serial lines such as telephone lines equipped with
-	  ordinary modems.  Experts should note that this driver doesn't
-	  currently comply with the asynchronous HDLS framing protocols in
-	  CCITT recommendation X.25.
+	  Send and receive X.25 frames over regular asynchronous serial
+	  lines such as telephone lines equipped with ordinary modems.
 
-	  To compile this driver as a module, choose M here: the module
-	  will be called x25_asy.  If unsure, say N.
+	  Experts should note that this driver doesn't currently comply with
+	  the asynchronous HDLS framing protocols in CCITT recommendation X.25.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called x25_asy.
+
+	  If unsure, say N.
 
 config SBNI
 	tristate "Granch SBNI12 Leased Line adapter support"
 	depends on WAN && X86
 	---help---
-	  This is a driver for ISA SBNI12-xx cards which are low cost
-	  alternatives to leased line modems. Say Y if you want to insert
-	  the driver into the kernel or say M to compile it as a module (the
-	  module will be called sbni).
+	  Driver for ISA SBNI12-xx cards which are low cost alternatives to
+	  leased line modems.
 
 	  You can find more information and last versions of drivers and
 	  utilities at <http://www.granch.ru/>. If you have any question you
-	  can send email to sbni@granch.ru.
+	  can send email to <sbni@granch.ru>.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called sbni.
 
-	  Say N if unsure.
+	  If unsure, say N.
 
 config SBNI_MULTILINE
 	bool "Multiple line feature support"
 	depends on SBNI
 	help
 	  Schedule traffic for some parallel lines, via SBNI12 adapters.
+
 	  If you have two computers connected with two parallel lines it's
 	  possible to increase transfer rate nearly twice. You should have
 	  a program named 'sbniconfig' to configure adapters.
 
-	  Say N if unsure.
+	  If unsure, say N.
 
 endmenu
 
--- diff/drivers/net/wan/c101.c	2003-08-20 14:16:10.000000000 +0100
+++ source/drivers/net/wan/c101.c	2004-02-23 13:56:44.000000000 +0000
@@ -54,7 +54,7 @@ static char *hw;		/* pointer to hw=xxx c
 
 
 typedef struct card_s {
-	hdlc_device hdlc;	/* HDLC device struct - must be first */
+	struct net_device *dev;
 	spinlock_t lock;	/* TX lock */
 	u8 *win0base;		/* ISA window base address */
 	u32 phy_winbase;	/* ISA physical base address */
@@ -121,6 +121,7 @@ static inline void openwin(card_t *card,
 
 static void sca_msci_intr(port_t *port)
 {
+	struct net_device *dev = port_to_dev(port);
 	card_t* card = port_to_card(port);
 	u8 stat = sca_in(MSCI1_OFFSET + ST1, card); /* read MSCI ST1 status */
 
@@ -128,8 +129,9 @@ static void sca_msci_intr(port_t *port)
 	sca_out(stat & ST1_UDRN, MSCI0_OFFSET + ST1, card);
 
 	if (stat & ST1_UDRN) {
-		port->hdlc.stats.tx_errors++; /* TX Underrun error detected */
-		port->hdlc.stats.tx_fifo_errors++;
+		struct net_device_stats *stats = hdlc_stats(dev);
+		stats->tx_errors++; /* TX Underrun error detected */
+		stats->tx_fifo_errors++;
 	}
 
 	/* Reset MSCI CDCD status bit - uses ch#2 DCD input */
@@ -137,7 +139,7 @@ static void sca_msci_intr(port_t *port)
 
 	if (stat & ST1_CDCD)
 		hdlc_set_carrier(!(sca_in(MSCI1_OFFSET + ST3, card) & ST3_DCD),
-				 &port->hdlc);
+				 dev);
 }
 
 
@@ -177,22 +179,21 @@ static void c101_set_iface(port_t *port)
 
 static int c101_open(struct net_device *dev)
 {
-	hdlc_device *hdlc = dev_to_hdlc(dev);
-	port_t *port = hdlc_to_port(hdlc);
+	port_t *port = dev_to_port(dev);
 	int result;
 
-	result = hdlc_open(hdlc);
+	result = hdlc_open(dev);
 	if (result)
 		return result;
 
 	writeb(1, port->win0base + C101_DTR);
 	sca_out(0, MSCI1_OFFSET + CTL, port); /* RTS uses ch#2 output */
-	sca_open(hdlc);
+	sca_open(dev);
 	/* DCD is connected to port 2 !@#$%^& - disable MSCI0 CDCD interrupt */
 	sca_out(IE1_UDRN, MSCI0_OFFSET + IE1, port);
 	sca_out(IE0_TXINT, MSCI0_OFFSET + IE0, port);
 
-	hdlc_set_carrier(!(sca_in(MSCI1_OFFSET + ST3, port) & ST3_DCD), hdlc);
+	hdlc_set_carrier(!(sca_in(MSCI1_OFFSET + ST3, port) & ST3_DCD), dev);
 	printk(KERN_DEBUG "0x%X\n", sca_in(MSCI1_OFFSET + ST3, port));
 
 	/* enable MSCI1 CDCD interrupt */
@@ -206,13 +207,12 @@ static int c101_open(struct net_device *
 
 static int c101_close(struct net_device *dev)
 {
-	hdlc_device *hdlc = dev_to_hdlc(dev);
-	port_t *port = hdlc_to_port(hdlc);
+	port_t *port = dev_to_port(dev);
 
-	sca_close(hdlc);
+	sca_close(dev);
 	writeb(0, port->win0base + C101_DTR);
 	sca_out(CTL_NORTS, MSCI1_OFFSET + CTL, port);
-	hdlc_close(hdlc);
+	hdlc_close(dev);
 	return 0;
 }
 
@@ -221,12 +221,11 @@ static int c101_ioctl(struct net_device 
 {
 	const size_t size = sizeof(sync_serial_settings);
 	sync_serial_settings new_line, *line = ifr->ifr_settings.ifs_ifsu.sync;
-	hdlc_device *hdlc = dev_to_hdlc(dev);
-	port_t *port = hdlc_to_port(hdlc);
+	port_t *port = dev_to_port(dev);
 
 #ifdef DEBUG_RINGS
 	if (cmd == SIOCDEVPRIVATE) {
-		sca_dump_rings(hdlc);
+		sca_dump_rings(dev);
 		printk(KERN_DEBUG "MSCI1: ST: %02x %02x %02x %02x\n",
 		       sca_in(MSCI1_OFFSET + ST0, port),
 		       sca_in(MSCI1_OFFSET + ST1, port),
@@ -288,6 +287,8 @@ static void c101_destroy_card(card_t *ca
 		release_mem_region(card->phy_winbase, C101_MAPPED_RAM_SIZE);
 	}
 
+	free_netdev(card->dev);
+
 	kfree(card);
 }
 
@@ -296,6 +297,7 @@ static void c101_destroy_card(card_t *ca
 static int __init c101_run(unsigned long irq, unsigned long winbase)
 {
 	struct net_device *dev;
+	hdlc_device *hdlc;
 	card_t *card;
 	int result;
 
@@ -316,6 +318,13 @@ static int __init c101_run(unsigned long
 	}
 	memset(card, 0, sizeof(card_t));
 
+	card->dev = alloc_hdlcdev(card);
+	if (!card->dev) {
+		printk(KERN_ERR "c101: unable to allocate memory\n");
+		kfree(card);
+		return -ENOBUFS;
+	}
+
 	if (request_irq(irq, sca_intr, 0, devname, card)) {
 		printk(KERN_ERR "c101: could not allocate IRQ\n");
 		c101_destroy_card(card);
@@ -347,7 +356,8 @@ static int __init c101_run(unsigned long
 
 	sca_init(card, 0);
 
-	dev = hdlc_to_dev(&card->hdlc);
+	dev = port_to_dev(card);
+	hdlc = dev_to_hdlc(dev);
 
 	spin_lock_init(&card->lock);
 	SET_MODULE_OWNER(dev);
@@ -358,24 +368,25 @@ static int __init c101_run(unsigned long
 	dev->do_ioctl = c101_ioctl;
 	dev->open = c101_open;
 	dev->stop = c101_close;
-	card->hdlc.attach = sca_attach;
-	card->hdlc.xmit = sca_xmit;
+	hdlc->attach = sca_attach;
+	hdlc->xmit = sca_xmit;
 	card->settings.clock_type = CLOCK_EXT;
 
-	result = register_hdlc_device(&card->hdlc);
+	result = register_hdlc_device(dev);
 	if (result) {
 		printk(KERN_WARNING "c101: unable to register hdlc device\n");
 		c101_destroy_card(card);
 		return result;
 	}
 
+	/* XXX: are we OK with having that done when card is already up? */
+
 	sca_init_sync_port(card); /* Set up C101 memory */
-	hdlc_set_carrier(!(sca_in(MSCI1_OFFSET + ST3, card) & ST3_DCD),
-			 &card->hdlc);
+	hdlc_set_carrier(!(sca_in(MSCI1_OFFSET + ST3, card) & ST3_DCD), dev);
 
 	printk(KERN_INFO "%s: Moxa C101 on IRQ%u,"
 	       " using %u TX + %u RX packets rings\n",
-	       hdlc_to_name(&card->hdlc), card->irq,
+	       dev->name, card->irq,
 	       card->tx_ring_buffers, card->rx_ring_buffers);
 
 	*new_card = card;
@@ -424,7 +435,7 @@ static void __exit c101_cleanup(void)
 	while (card) {
 		card_t *ptr = card;
 		card = card->next_card;
-		unregister_hdlc_device(&ptr->hdlc);
+		unregister_hdlc_device(port_to_dev(ptr));
 		c101_destroy_card(ptr);
 	}
 }
--- diff/drivers/net/wan/comx-hw-munich.c	2003-10-09 09:47:34.000000000 +0100
+++ source/drivers/net/wan/comx-hw-munich.c	2004-02-23 13:56:44.000000000 +0000
@@ -2058,30 +2058,30 @@ static int MUNICH_minden(struct net_devi
     {
 	frs0 = readb(lbi + FRS0);
 	fmr2 = readb(lbi + FMR2);
-	len += snprintf(page + len, PAGE_SIZE - len, "Controller status:\n");
+	len += scnprintf(page + len, PAGE_SIZE - len, "Controller status:\n");
 	if (frs0 == 0)
-	    len += snprintf(page + len, PAGE_SIZE - len, "\tNo alarms\n");
+	    len += scnprintf(page + len, PAGE_SIZE - len, "\tNo alarms\n");
 	else
 	{
 	    if (frs0 & FRS0_LOS)
-	            len += snprintf(page + len, PAGE_SIZE - len, "\tLoss Of Signal\n");
+	            len += scnprintf(page + len, PAGE_SIZE - len, "\tLoss Of Signal\n");
 	    else
 	    {
 		if (frs0 & FRS0_AIS)
-		    len += snprintf(page + len, PAGE_SIZE - len,
+		    len += scnprintf(page + len, PAGE_SIZE - len,
 				 "\tAlarm Indication Signal\n");
 		else
 		{
 		    if (frs0 & FRS0_AUXP)
-			len += snprintf(page + len, PAGE_SIZE - len,
+			len += scnprintf(page + len, PAGE_SIZE - len,
 				     "\tAuxiliary Pattern Indication\n");
 		    if (frs0 & FRS0_LFA)
-			len += snprintf(page + len, PAGE_SIZE - len,
+			len += scnprintf(page + len, PAGE_SIZE - len,
 				     "\tLoss of Frame Alignment\n");
 		    else
 		    {
 			if (frs0 & FRS0_RRA)
-			    len += snprintf(page + len, PAGE_SIZE - len,
+			    len += scnprintf(page + len, PAGE_SIZE - len,
 					 "\tReceive Remote Alarm\n");
 
 			/* You can't set this framing with the /proc interface, but it  */
@@ -2089,11 +2089,11 @@ static int MUNICH_minden(struct net_devi
 
 			if ((board->framing == SLICECOM_FRAMING_CRC4) &&
 			    (frs0 & FRS0_LMFA))
-			    len += snprintf(page + len, PAGE_SIZE - len,
+			    len += scnprintf(page + len, PAGE_SIZE - len,
 					 "\tLoss of CRC4 Multiframe Alignment\n");
 
 			if (((fmr2 & 0xc0) == 0xc0) && (frs0 & FRS0_NMF))
-			    len += snprintf(page + len, PAGE_SIZE - len,
+			    len += scnprintf(page + len, PAGE_SIZE - len,
 				 "\tNo CRC4 Multiframe alignment Found after 400 msec\n");
 		    }
 		}
@@ -2102,27 +2102,27 @@ static int MUNICH_minden(struct net_devi
 
 	frs1 = readb(lbi + FRS1);
 	if (FRS1_XLS & frs1)
-	    len += snprintf(page + len, PAGE_SIZE - len,
+	    len += scnprintf(page + len, PAGE_SIZE - len,
 		 "\tTransmit Line Short\n");
 
 	/* debug Rx ring: DEL: - vagy meghagyni, de akkor legyen kicsit altalanosabb */
     }
 
-    len += snprintf(page + len, PAGE_SIZE - len, "Rx ring:\n");
-    len += snprintf(page + len, PAGE_SIZE - len, "\trafutott: %d\n", hw->rafutott);
-    len += snprintf(page + len, PAGE_SIZE - len,
+    len += scnprintf(page + len, PAGE_SIZE - len, "Rx ring:\n");
+    len += scnprintf(page + len, PAGE_SIZE - len, "\trafutott: %d\n", hw->rafutott);
+    len += scnprintf(page + len, PAGE_SIZE - len,
 		 "\tlastcheck: %ld, jiffies: %ld\n", board->lastcheck, jiffies);
-    len += snprintf(page + len, PAGE_SIZE - len, "\tbase: %08x\n",
+    len += scnprintf(page + len, PAGE_SIZE - len, "\tbase: %08x\n",
 	(u32) virt_to_phys(&hw->rx_desc[0]));
-    len += snprintf(page + len, PAGE_SIZE - len, "\trx_desc_ptr: %d\n",
+    len += scnprintf(page + len, PAGE_SIZE - len, "\trx_desc_ptr: %d\n",
 		 hw->rx_desc_ptr);
-    len += snprintf(page + len, PAGE_SIZE - len, "\trx_desc_ptr: %08x\n",
+    len += scnprintf(page + len, PAGE_SIZE - len, "\trx_desc_ptr: %08x\n",
 	(u32) virt_to_phys(&hw->rx_desc[hw->rx_desc_ptr]));
-    len += snprintf(page + len, PAGE_SIZE - len, "\thw_curr_ptr: %08x\n",
+    len += scnprintf(page + len, PAGE_SIZE - len, "\thw_curr_ptr: %08x\n",
 		 board->ccb->current_rx_desc[hw->channel]);
 
     for (i = 0; i < RX_DESC_MAX; i++)
-	len += snprintf(page + len, PAGE_SIZE - len, "\t%08x %08x %08x %08x\n",
+	len += scnprintf(page + len, PAGE_SIZE - len, "\t%08x %08x %08x %08x\n",
 		     *((u32 *) & hw->rx_desc[i] + 0),
 		     *((u32 *) & hw->rx_desc[i] + 1),
 		     *((u32 *) & hw->rx_desc[i] + 2),
@@ -2130,7 +2130,7 @@ static int MUNICH_minden(struct net_devi
 
     if (!board->isx21)
     {
-	len += snprintf(page + len, PAGE_SIZE - len,
+	len += scnprintf(page + len, PAGE_SIZE - len,
 		     "Interfaces using this board: (channel-group, interface, timeslots)\n");
 	for (i = 0; i < 32; i++)
 	{
@@ -2141,26 +2141,26 @@ static int MUNICH_minden(struct net_devi
 		    ((struct slicecom_privdata *)((struct comx_channel *)devp->
 						  priv)->HW_privdata)->
 		    timeslots;
-		len += snprintf(page + len, PAGE_SIZE - len, "\t%2d %s: ", i,
+		len += scnprintf(page + len, PAGE_SIZE - len, "\t%2d %s: ", i,
 			     devp->name);
 		for (j = 0; j < 32; j++)
 		    if ((1 << j) & timeslots)
-			len += snprintf(page + len, PAGE_SIZE - len, "%d ", j);
-		len += snprintf(page + len, PAGE_SIZE - len, "\n");
+			len += scnprintf(page + len, PAGE_SIZE - len, "%d ", j);
+		len += scnprintf(page + len, PAGE_SIZE - len, "\n");
 	    }
 	}
     }
 
-    len += snprintf(page + len, PAGE_SIZE - len, "Interrupt work histogram:\n");
+    len += scnprintf(page + len, PAGE_SIZE - len, "Interrupt work histogram:\n");
     for (i = 0; i < MAX_WORK; i++)
-	len += snprintf(page + len, PAGE_SIZE - len, "hist[%2d]: %8u%c", i,
+	len += scnprintf(page + len, PAGE_SIZE - len, "hist[%2d]: %8u%c", i,
 		     board->histogram[i], (i &&
 					   ((i + 1) % 4 == 0 ||
 					    i == MAX_WORK - 1)) ? '\n' : ' ');
 
-    len += snprintf(page + len, PAGE_SIZE - len, "Tx ring histogram:\n");
+    len += scnprintf(page + len, PAGE_SIZE - len, "Tx ring histogram:\n");
     for (i = 0; i < TX_DESC_MAX; i++)
-	len += snprintf(page + len, PAGE_SIZE - len, "hist[%2d]: %8u%c", i,
+	len += scnprintf(page + len, PAGE_SIZE - len, "hist[%2d]: %8u%c", i,
 		     hw->tx_ring_hist[i], (i &&
 					   ((i + 1) % 4 == 0 ||
 					    i ==
@@ -2196,72 +2196,72 @@ static int MUNICH_minden(struct net_devi
 		sump[j] += p[j];
 	}
 
-	len += snprintf(page + len, PAGE_SIZE - len,
+	len += scnprintf(page + len, PAGE_SIZE - len,
 		     "Data in current interval (%d seconds elapsed):\n",
 		     board->elapsed_seconds);
-	len += snprintf(page + len, PAGE_SIZE - len,
+	len += scnprintf(page + len, PAGE_SIZE - len,
 		     "   %d Line Code Violations, %d Path Code Violations, %d E-Bit Errors\n",
 		     curr_int->line_code_violations,
 		     curr_int->path_code_violations, curr_int->e_bit_errors);
-	len += snprintf(page + len, PAGE_SIZE - len,
+	len += scnprintf(page + len, PAGE_SIZE - len,
 		     "   %d Slip Secs, %d Fr Loss Secs, %d Line Err Secs, %d Degraded Mins\n",
 		     curr_int->slip_secs, curr_int->fr_loss_secs,
 		     curr_int->line_err_secs, curr_int->degraded_mins);
-	len += snprintf(page + len, PAGE_SIZE - len,
+	len += scnprintf(page + len, PAGE_SIZE - len,
 		     "   %d Errored Secs, %d Bursty Err Secs, %d Severely Err Secs, %d Unavail Secs\n",
 		     curr_int->errored_secs, curr_int->bursty_err_secs,
 		     curr_int->severely_err_secs, curr_int->unavail_secs);
 
-	len += snprintf(page + len, PAGE_SIZE - len,
+	len += scnprintf(page + len, PAGE_SIZE - len,
 		     "Data in Interval 1 (15 minutes):\n");
-	len += snprintf(page + len, PAGE_SIZE - len,
+	len += scnprintf(page + len, PAGE_SIZE - len,
 		     "   %d Line Code Violations, %d Path Code Violations, %d E-Bit Errors\n",
 		     prev_int->line_code_violations,
 		     prev_int->path_code_violations, prev_int->e_bit_errors);
-	len += snprintf(page + len, PAGE_SIZE - len,
+	len += scnprintf(page + len, PAGE_SIZE - len,
 		     "   %d Slip Secs, %d Fr Loss Secs, %d Line Err Secs, %d Degraded Mins\n",
 		     prev_int->slip_secs, prev_int->fr_loss_secs,
 		     prev_int->line_err_secs, prev_int->degraded_mins);
-	len += snprintf(page + len, PAGE_SIZE - len,
+	len += scnprintf(page + len, PAGE_SIZE - len,
 		     "   %d Errored Secs, %d Bursty Err Secs, %d Severely Err Secs, %d Unavail Secs\n",
 		     prev_int->errored_secs, prev_int->bursty_err_secs,
 		     prev_int->severely_err_secs, prev_int->unavail_secs);
 
-	len += snprintf(page + len, PAGE_SIZE - len,
+	len += scnprintf(page + len, PAGE_SIZE - len,
 		     "Data in last 4 intervals (1 hour):\n");
-	len += snprintf(page + len, PAGE_SIZE - len,
+	len += scnprintf(page + len, PAGE_SIZE - len,
 		     "   %d Line Code Violations, %d Path Code Violations, %d E-Bit Errors\n",
 		     last4.line_code_violations, last4.path_code_violations,
 		     last4.e_bit_errors);
-	len += snprintf(page + len, PAGE_SIZE - len,
+	len += scnprintf(page + len, PAGE_SIZE - len,
 		     "   %d Slip Secs, %d Fr Loss Secs, %d Line Err Secs, %d Degraded Mins\n",
 		     last4.slip_secs, last4.fr_loss_secs, last4.line_err_secs,
 		     last4.degraded_mins);
-	len += snprintf(page + len, PAGE_SIZE - len,
+	len += scnprintf(page + len, PAGE_SIZE - len,
 		     "   %d Errored Secs, %d Bursty Err Secs, %d Severely Err Secs, %d Unavail Secs\n",
 		     last4.errored_secs, last4.bursty_err_secs,
 		     last4.severely_err_secs, last4.unavail_secs);
 
-	len += snprintf(page + len, PAGE_SIZE - len,
+	len += scnprintf(page + len, PAGE_SIZE - len,
 		     "Data in last 96 intervals (24 hours):\n");
-	len += snprintf(page + len, PAGE_SIZE - len,
+	len += scnprintf(page + len, PAGE_SIZE - len,
 		     "   %d Line Code Violations, %d Path Code Violations, %d E-Bit Errors\n",
 		     last96.line_code_violations, last96.path_code_violations,
 		     last96.e_bit_errors);
-	len += snprintf(page + len, PAGE_SIZE - len,
+	len += scnprintf(page + len, PAGE_SIZE - len,
 		     "   %d Slip Secs, %d Fr Loss Secs, %d Line Err Secs, %d Degraded Mins\n",
 		     last96.slip_secs, last96.fr_loss_secs,
 		     last96.line_err_secs, last96.degraded_mins);
-	len += snprintf(page + len, PAGE_SIZE - len,
+	len += scnprintf(page + len, PAGE_SIZE - len,
 		     "   %d Errored Secs, %d Bursty Err Secs, %d Severely Err Secs, %d Unavail Secs\n",
 		     last96.errored_secs, last96.bursty_err_secs,
 		     last96.severely_err_secs, last96.unavail_secs);
 
     }
 
-//      len +=snprintf( page + len, PAGE_SIZE - len, "Special events:\n" );
-//      len +=snprintf( page + len, PAGE_SIZE - len, "\tstat_pri/missed: %u / %u\n", board->stat_pri_races, board->stat_pri_races_missed );
-//      len +=snprintf( page + len, PAGE_SIZE - len, "\tstat_pti/missed: %u / %u\n", board->stat_pti_races, board->stat_pti_races_missed );
+//      len +=scnprintf( page + len, PAGE_SIZE - len, "Special events:\n" );
+//      len +=scnprintf( page + len, PAGE_SIZE - len, "\tstat_pri/missed: %u / %u\n", board->stat_pri_races, board->stat_pri_races_missed );
+//      len +=scnprintf( page + len, PAGE_SIZE - len, "\tstat_pti/missed: %u / %u\n", board->stat_pti_races, board->stat_pti_races_missed );
     return len;
 }
 
@@ -2305,8 +2305,8 @@ static int munich_read_proc(char *page, 
     {
 	for (i = 0; i < 32; i++)
 	    if ((1 << i) & timeslots)
-		len += snprintf(page + len, PAGE_SIZE - len, "%d ", i);
-	len += snprintf(page + len, PAGE_SIZE - len, "\n");
+		len += scnprintf(page + len, PAGE_SIZE - len, "%d ", i);
+	len += scnprintf(page + len, PAGE_SIZE - len, "\n");
     }
     else if (!strcmp(file->name, FILENAME_FRAMING))
     {
@@ -2314,7 +2314,7 @@ static int munich_read_proc(char *page, 
 	while (slicecom_framings[i].value &&
 	       slicecom_framings[i].value != board->framing)
 	    i++;
-	len += snprintf(page + len, PAGE_SIZE - len, "%s\n",
+	len += scnprintf(page + len, PAGE_SIZE - len, "%s\n",
 		     slicecom_framings[i].name);
     }
     else if (!strcmp(file->name, FILENAME_LINECODE))
@@ -2323,7 +2323,7 @@ static int munich_read_proc(char *page, 
 	while (slicecom_linecodes[i].value &&
 	       slicecom_linecodes[i].value != board->linecode)
 	    i++;
-	len += snprintf(page + len, PAGE_SIZE - len, "%s\n",
+	len += scnprintf(page + len, PAGE_SIZE - len, "%s\n",
 		     slicecom_linecodes[i].name);
     }
     else if (!strcmp(file->name, FILENAME_CLOCK_SOURCE))
@@ -2333,7 +2333,7 @@ static int munich_read_proc(char *page, 
 	       slicecom_clock_sources[i].value != board->clock_source)
 	    i++;
 	len +=
-	    snprintf(page + len, PAGE_SIZE - len, "%s\n",
+	    scnprintf(page + len, PAGE_SIZE - len, "%s\n",
 		     slicecom_clock_sources[i].name);
     }
     else if (!strcmp(file->name, FILENAME_LOOPBACK))
@@ -2342,18 +2342,18 @@ static int munich_read_proc(char *page, 
 	while (slicecom_loopbacks[i].value &&
 	       slicecom_loopbacks[i].value != board->loopback)
 	    i++;
-	len += snprintf(page + len, PAGE_SIZE - len, "%s\n",
+	len += scnprintf(page + len, PAGE_SIZE - len, "%s\n",
 		     slicecom_loopbacks[i].name);
     }
     /* We set permissions to write-only for REG and LBIREG, but root can read them anyway: */
     else if (!strcmp(file->name, FILENAME_REG))
     {
-	len += snprintf(page + len, PAGE_SIZE - len,
+	len += scnprintf(page + len, PAGE_SIZE - len,
 		     "%s: " FILENAME_REG ": write-only file\n", dev->name);
     }
     else if (!strcmp(file->name, FILENAME_LBIREG))
     {
-	len += snprintf(page + len, PAGE_SIZE - len,
+	len += scnprintf(page + len, PAGE_SIZE - len,
 		     "%s: " FILENAME_LBIREG ": write-only file\n", dev->name);
     }
     else
--- diff/drivers/net/wan/comx-proto-lapb.c	2003-10-09 09:47:34.000000000 +0100
+++ source/drivers/net/wan/comx-proto-lapb.c	2004-02-23 13:56:44.000000000 +0000
@@ -44,7 +44,7 @@ static void comxlapb_rx(struct net_devic
 	if (!dev || !dev->priv) {
 		dev_kfree_skb(skb);
 	} else {
-		lapb_data_received(dev->priv, skb);
+		lapb_data_received(dev, skb);
 	}
 }
 
@@ -82,7 +82,7 @@ static int comxlapb_open(struct net_devi
 		return -ENODEV;
 	}
 
-	err = lapb_connect_request(ch);
+	err = lapb_connect_request(dev);
 
 	if (ch->debug_flags & DEBUG_COMX_LAPB) {
 		comx_debug(dev, "%s: lapb opened, error code: %d\n", 
@@ -108,7 +108,7 @@ static int comxlapb_close(struct net_dev
 		comx_debug(dev, "%s: lapb closed\n", dev->name);
 	}
 
-	lapb_disconnect_request(ch);
+	lapb_disconnect_request(dev);
 
 	ch->init_status &= ~LINE_OPEN;
 	ch->line_status &= ~PROTO_UP;
@@ -130,11 +130,11 @@ static int comxlapb_xmit(struct sk_buff 
 			case 0x00:	
 				break;	// transmit
 			case 0x01:	
-				lapb_connect_request(ch);
+				lapb_connect_request(dev);
 				kfree_skb(skb);
 				return 0;
 			case 0x02:	
-				lapb_disconnect_request(ch);
+				lapb_disconnect_request(dev);
 			default:
 				kfree_skb(skb);
 				return 0;
@@ -145,7 +145,7 @@ static int comxlapb_xmit(struct sk_buff 
 	netif_stop_queue(dev);
 	
 	if ((skb2 = skb_clone(skb, GFP_ATOMIC)) != NULL) {
-		lapb_data_request(ch, skb2);
+		lapb_data_request(dev, skb2);
 	}
 
 	return FRAME_ACCEPTED;
@@ -157,7 +157,7 @@ static int comxlapb_statistics(struct ne
 	int len = 0;
 
 	len += sprintf(page + len, "Line status: ");
-	if (lapb_getparms(dev->priv, &parms) != LAPB_OK) {
+	if (lapb_getparms(dev, &parms) != LAPB_OK) {
 		len += sprintf(page + len, "not initialized\n");
 		return len;
 	}
@@ -178,7 +178,7 @@ static int comxlapb_read_proc(char *page
 	struct lapb_parms_struct parms;
 	int len = 0;
 
-	if (lapb_getparms(dev->priv, &parms)) {
+	if (lapb_getparms(dev, &parms)) {
 		return -ENODEV;
 	}
 
@@ -223,7 +223,7 @@ static int comxlapb_write_proc(struct fi
 	unsigned long parm;
 	char *page;
 
-	if (lapb_getparms(dev->priv, &parms)) {
+	if (lapb_getparms(dev, &parms)) {
 		return -ENODEV;
 	}
 
@@ -243,23 +243,23 @@ static int comxlapb_write_proc(struct fi
 		parm=simple_strtoul(page,NULL,10);
 		if (parm > 0 && parm < 100) {
 			parms.t1=parm;
-			lapb_setparms(dev->priv, &parms);
+			lapb_setparms(dev, &parms);
 		}
 	} else if (strcmp(entry->name, FILENAME_T2) == 0) {
 		parm=simple_strtoul(page, NULL, 10);
 		if (parm > 0 && parm < 100) {
 			parms.t2=parm;
-			lapb_setparms(dev->priv, &parms);
+			lapb_setparms(dev, &parms);
 		}
 	} else if (strcmp(entry->name, FILENAME_N2) == 0) {
 		parm=simple_strtoul(page, NULL, 10);
 		if (parm > 0 && parm < 100) {
 			parms.n2=parm;
-			lapb_setparms(dev->priv, &parms);
+			lapb_setparms(dev, &parms);
 		}
 	} else if (strcmp(entry->name, FILENAME_WINDOW) == 0) {
 		parms.window = simple_strtoul(page, NULL, 10);
-		lapb_setparms(dev->priv, &parms);
+		lapb_setparms(dev, &parms);
 	} else if (strcmp(entry->name, FILENAME_MODE) == 0) {
 		if (comx_strcasecmp(page, "dte") == 0) {
 			parms.mode &= ~(LAPB_DCE | LAPB_DTE); 
@@ -276,7 +276,7 @@ static int comxlapb_write_proc(struct fi
 			parms.mode &= ~LAPB_STANDARD; 
 			parms.mode |= LAPB_EXTENDED;
 		}
-		lapb_setparms(dev->priv, &parms);
+		lapb_setparms(dev, &parms);
 	} else {
 		printk(KERN_ERR "comxlapb_write_proc: internal error, filename %s\n", 
 			entry->name);
@@ -287,9 +287,9 @@ static int comxlapb_write_proc(struct fi
 	return count;
 }
 
-static void comxlapb_connected(void *token, int reason)
+static void comxlapb_connected(struct net_device *dev, int reason)
 {
-	struct comx_channel *ch = token; 
+	struct comx_channel *ch = dev->priv; 
 	struct proc_dir_entry *comxdir = ch->procdir->subdir;
 
 	if (ch->debug_flags & DEBUG_COMX_LAPB) {
@@ -327,9 +327,9 @@ static void comxlapb_connected(void *tok
 	comx_status(ch->dev, ch->line_status);
 }
 
-static void comxlapb_disconnected(void *token, int reason)
+static void comxlapb_disconnected(struct net_device *dev, int reason)
 {
-	struct comx_channel *ch = token; 
+	struct comx_channel *ch = dev->priv; 
 	struct proc_dir_entry *comxdir = ch->procdir->subdir;
 
 	if (ch->debug_flags & DEBUG_COMX_LAPB) {
@@ -366,9 +366,9 @@ static void comxlapb_disconnected(void *
 	comx_status(ch->dev, ch->line_status);
 }
 
-static int comxlapb_data_indication(void *token, struct sk_buff *skb)
+static int comxlapb_data_indication(struct net_device *dev, struct sk_buff *skb)
 {
-	struct comx_channel *ch = token; 
+	struct comx_channel *ch = dev->priv; 
 
 	if (ch->dev->type == ARPHRD_X25) {
 		skb_push(skb, 1);
@@ -387,9 +387,9 @@ static int comxlapb_data_indication(void
 	return comx_rx(ch->dev, skb);
 }
 
-static void comxlapb_data_transmit(void *token, struct sk_buff *skb)
+static void comxlapb_data_transmit(struct net_device *dev, struct sk_buff *skb)
 {
-	struct comx_channel *ch = token; 
+	struct comx_channel *ch = dev->priv; 
 
 	if (ch->HW_send_packet) {
 		ch->HW_send_packet(ch->dev, skb);
@@ -417,7 +417,7 @@ static int comxlapb_exit(struct net_devi
 	if (ch->debug_flags & DEBUG_COMX_LAPB) {
 		comx_debug(dev, "%s: unregistering lapb\n", dev->name);
 	}
-	lapb_unregister(dev->priv);
+	lapb_unregister(dev);
 
 	remove_proc_entry(FILENAME_T1, ch->procdir);
 	remove_proc_entry(FILENAME_T2, ch->procdir);
@@ -453,7 +453,7 @@ static int comxlapb_init(struct net_devi
 	lapbreg.disconnect_indication = comxlapb_disconnected;
 	lapbreg.data_indication = comxlapb_data_indication;
 	lapbreg.data_transmit = comxlapb_data_transmit;
-	if (lapb_register(dev->priv, &lapbreg)) {
+	if (lapb_register(dev, &lapbreg)) {
 		return -ENOMEM;
 	}
 	if (ch->debug_flags & DEBUG_COMX_LAPB) {
--- diff/drivers/net/wan/dlci.c	2003-09-30 15:46:16.000000000 +0100
+++ source/drivers/net/wan/dlci.c	2004-02-23 13:56:44.000000000 +0000
@@ -414,7 +414,7 @@ static int dlci_add(struct dlci_add *dlc
 
  err2:
 	rtnl_unlock();
-	kfree(master);
+	free_netdev(master);
  err1:
 	dev_put(slave);
 	return(err);
--- diff/drivers/net/wan/dscc4.c	2003-10-09 09:47:34.000000000 +0100
+++ source/drivers/net/wan/dscc4.c	2004-02-23 13:56:44.000000000 +0000
@@ -228,7 +228,7 @@ struct dscc4_dev_priv {
 
 	unsigned short encoding;
 	unsigned short parity;
-	hdlc_device hdlc;
+	struct net_device *dev;
 	sync_serial_settings settings;
 	u32 __pad __attribute__ ((aligned (4)));
 };
@@ -364,7 +364,7 @@ static void dscc4_release_ring(struct ds
 static void dscc4_timer(unsigned long);
 static void dscc4_tx_timeout(struct net_device *);
 static irqreturn_t dscc4_irq(int irq, void *dev_id, struct pt_regs *ptregs);
-static int dscc4_hdlc_attach(hdlc_device *, unsigned short, unsigned short);
+static int dscc4_hdlc_attach(struct net_device *, unsigned short, unsigned short);
 static int dscc4_set_iface(struct dscc4_dev_priv *, struct net_device *);
 static inline int dscc4_set_quartz(struct dscc4_dev_priv *, int);
 #ifdef DSCC4_POLLING
@@ -373,7 +373,12 @@ static int dscc4_tx_poll(struct dscc4_de
 
 static inline struct dscc4_dev_priv *dscc4_priv(struct net_device *dev)
 {
-	return list_entry(dev, struct dscc4_dev_priv, hdlc.netdev);
+	return dev_to_hdlc(dev)->priv;
+}
+
+static inline struct net_device *dscc4_to_dev(struct dscc4_dev_priv *p)
+{
+	return p->dev;
 }
 
 static void scc_patchl(u32 mask, u32 value, struct dscc4_dev_priv *dpriv,
@@ -636,7 +641,7 @@ static inline void dscc4_rx_skb(struct d
 				struct net_device *dev)
 {
 	struct RxFD *rx_fd = dpriv->rx_fd + dpriv->rx_current%RX_RING_SIZE;
-	struct net_device_stats *stats = &dpriv->hdlc.stats;
+	struct net_device_stats *stats = hdlc_stats(dev);
 	struct pci_dev *pdev = dpriv->pci_priv->pdev;
 	struct sk_buff *skb;
 	int pkt_len;
@@ -689,10 +694,12 @@ static void dscc4_free1(struct pci_dev *
 	root = ppriv->root;
 
 	for (i = 0; i < dev_per_card; i++)
-		unregister_hdlc_device(&root[i].hdlc);
+		unregister_hdlc_device(dscc4_to_dev(&root[i]));
 
 	pci_set_drvdata(pdev, NULL);
 
+	for (i = 0; i < dev_per_card; i++)
+		free_netdev(root[i].dev);
 	kfree(root);
 	kfree(ppriv);
 }
@@ -874,17 +881,31 @@ static int dscc4_found1(struct pci_dev *
 	}
 	memset(root, 0, dev_per_card*sizeof(*root));
 
+	for (i = 0; i < dev_per_card; i++) {
+		root[i].dev = alloc_hdlcdev(root + i);
+		if (!root[i].dev) {
+			while (i--)
+				free_netdev(root[i].dev);
+			goto err_free_dev;
+		}
+	}
+
 	ppriv = (struct dscc4_pci_priv *) kmalloc(sizeof(*ppriv), GFP_KERNEL);
 	if (!ppriv) {
 		printk(KERN_ERR "%s: can't allocate private data\n", DRV_NAME);
-		goto err_free_dev;
+		goto err_free_dev2;
 	}
 	memset(ppriv, 0, sizeof(struct dscc4_pci_priv));
+	ret = dscc4_set_quartz(root, quartz);
+	if (ret < 0)
+		goto err_free_priv;
+	ppriv->root = root;
+	spin_lock_init(&ppriv->lock);
 
 	for (i = 0; i < dev_per_card; i++) {
 		struct dscc4_dev_priv *dpriv = root + i;
-		hdlc_device *hdlc = &dpriv->hdlc;
-		struct net_device *d = hdlc_to_dev(hdlc);
+		struct net_device *d = dscc4_to_dev(dpriv);
+		hdlc_device *hdlc = dev_to_hdlc(d);
 
 	        d->base_addr = ioaddr;
 		d->init = NULL;
@@ -905,36 +926,34 @@ static int dscc4_found1(struct pci_dev *
 		hdlc->xmit = dscc4_start_xmit;
 		hdlc->attach = dscc4_hdlc_attach;
 
-		ret = register_hdlc_device(hdlc);
-		if (ret < 0) {
-			printk(KERN_ERR "%s: unable to register\n", DRV_NAME);
-			goto err_unregister;
-	        }
-
 		dscc4_init_registers(dpriv, d);
 		dpriv->parity = PARITY_CRC16_PR0_CCITT;
 		dpriv->encoding = ENCODING_NRZ;
-
+	
 		ret = dscc4_init_ring(d);
+		if (ret < 0)
+			goto err_unregister;
+
+		ret = register_hdlc_device(d);
 		if (ret < 0) {
-			unregister_hdlc_device(hdlc);
+			printk(KERN_ERR "%s: unable to register\n", DRV_NAME);
+			dscc4_release_ring(dpriv);
 			goto err_unregister;
-		}
+	        }
 	}
-	ret = dscc4_set_quartz(root, quartz);
-	if (ret < 0)
-		goto err_unregister;
-	ppriv->root = root;
-	spin_lock_init(&ppriv->lock);
 	pci_set_drvdata(pdev, ppriv);
 	return ret;
 
 err_unregister:
 	while (--i >= 0) {
 		dscc4_release_ring(root + i);
-		unregister_hdlc_device(&root[i].hdlc);
+		unregister_hdlc_device(dscc4_to_dev(&root[i]));
 	}
+err_free_priv:
 	kfree(ppriv);
+err_free_dev2:
+	for (i = 0; i < dev_per_card; i++)
+		free_netdev(root[i].dev);
 err_free_dev:
 	kfree(root);
 err_out:
@@ -964,7 +983,7 @@ static int dscc4_loopback_check(struct d
 	sync_serial_settings *settings = &dpriv->settings;
 
 	if (settings->loopback && (settings->clock_type != CLOCK_INT)) {
-		struct net_device *dev = hdlc_to_dev(&dpriv->hdlc);
+		struct net_device *dev = dscc4_to_dev(dpriv);
 
 		printk(KERN_INFO "%s: loopback requires clock\n", dev->name);
 		return -1;
@@ -1015,14 +1034,13 @@ static void dscc4_pci_reset(struct pci_d
 static int dscc4_open(struct net_device *dev)
 {
 	struct dscc4_dev_priv *dpriv = dscc4_priv(dev);
-	hdlc_device *hdlc = &dpriv->hdlc;
 	struct dscc4_pci_priv *ppriv;
 	int ret = -EAGAIN;
 
 	if ((dscc4_loopback_check(dpriv) < 0) || !dev->hard_start_xmit)
 		goto err;
 
-	if ((ret = hdlc_open(hdlc)))
+	if ((ret = hdlc_open(dev)))
 		goto err;
 
 	ppriv = dpriv->pci_priv;
@@ -1103,7 +1121,7 @@ err_disable_scc_events:
 	scc_writel(0xffffffff, dpriv, dev, IMR);
 	scc_patchl(PowerUp | Vis, 0, dpriv, dev, CCR0);
 err_out:
-	hdlc_close(hdlc);
+	hdlc_close(dev);
 err:
 	return ret;
 }
@@ -1155,7 +1173,6 @@ static int dscc4_start_xmit(struct sk_bu
 static int dscc4_close(struct net_device *dev)
 {
 	struct dscc4_dev_priv *dpriv = dscc4_priv(dev);
-	hdlc_device *hdlc = dev_to_hdlc(dev);
 
 	del_timer_sync(&dpriv->timer);
 	netif_stop_queue(dev);
@@ -1166,7 +1183,7 @@ static int dscc4_close(struct net_device
 
 	dpriv->flags |= FakeReset;
 
-	hdlc_close(hdlc);
+	hdlc_close(dev);
 
 	return 0;
 }
@@ -1467,7 +1484,7 @@ static irqreturn_t dscc4_irq(int irq, vo
 	int i, handled = 1;
 
 	priv = root->pci_priv;
-	dev = hdlc_to_dev(&root->hdlc);
+	dev = dscc4_to_dev(root);
 
 	spin_lock_irqsave(&priv->lock, flags);
 
@@ -1518,7 +1535,7 @@ out:
 static inline void dscc4_tx_irq(struct dscc4_pci_priv *ppriv,
 				struct dscc4_dev_priv *dpriv)
 {
-	struct net_device *dev = hdlc_to_dev(&dpriv->hdlc);
+	struct net_device *dev = dscc4_to_dev(dpriv);
 	u32 state;
 	int cur, loop = 0;
 
@@ -1549,7 +1566,7 @@ try:
 
 	if (state & SccEvt) {
 		if (state & Alls) {
-			struct net_device_stats *stats = &dpriv->hdlc.stats;
+			struct net_device_stats *stats = hdlc_stats(dev);
 			struct sk_buff *skb;
 			struct TxFD *tx_fd;
 
@@ -1677,7 +1694,7 @@ try:
 		}
 		if (state & Err) {
 			printk(KERN_INFO "%s: Tx ERR\n", dev->name);
-			dev_to_hdlc(dev)->stats.tx_errors++;
+			hdlc_stats(dev)->tx_errors++;
 			state &= ~Err;
 		}
 	}
@@ -1687,7 +1704,7 @@ try:
 static inline void dscc4_rx_irq(struct dscc4_pci_priv *priv,
 				    struct dscc4_dev_priv *dpriv)
 {
-	struct net_device *dev = hdlc_to_dev(&dpriv->hdlc);
+	struct net_device *dev = dscc4_to_dev(dpriv);
 	u32 state;
 	int cur;
 
@@ -1813,7 +1830,7 @@ try:
 				if (!(rx_fd->state2 & DataComplete))
 					break;
 				if (rx_fd->state2 & FrameAborted) {
-					dev_to_hdlc(dev)->stats.rx_over_errors++;
+					hdlc_stats(dev)->rx_over_errors++;
 					rx_fd->state1 |= Hold;
 					rx_fd->state2 = 0x00000000;
 					rx_fd->end = 0xbabeface;
@@ -1961,7 +1978,7 @@ static void __devexit dscc4_remove_one(s
 	ppriv = pci_get_drvdata(pdev);
 	root = ppriv->root;
 
-	ioaddr = hdlc_to_dev(&root->hdlc)->base_addr;
+	ioaddr = dscc4_to_dev(root)->base_addr;
 
 	dscc4_pci_reset(pdev, ioaddr);
 
@@ -1988,10 +2005,9 @@ static void __devexit dscc4_remove_one(s
 			   pci_resource_len(pdev, 0));
 }
 
-static int dscc4_hdlc_attach(hdlc_device *hdlc, unsigned short encoding,
+static int dscc4_hdlc_attach(struct net_device *dev, unsigned short encoding,
 	unsigned short parity)
 {
-	struct net_device *dev = hdlc_to_dev(hdlc);
 	struct dscc4_dev_priv *dpriv = dscc4_priv(dev);
 
 	if (encoding != ENCODING_NRZ &&
--- diff/drivers/net/wan/farsync.c	2004-02-09 10:36:11.000000000 +0000
+++ source/drivers/net/wan/farsync.c	2004-02-23 13:56:44.000000000 +0000
@@ -328,7 +328,7 @@ struct buf_window {
 /*      Per port (line or channel) information
  */
 struct fst_port_info {
-        hdlc_device             hdlc;   /* HDLC device struct - must be first */
+        struct net_device      *dev;
         struct fst_card_info   *card;   /* Card we're associated with */
         int                     index;  /* Port index on the card */
         int                     hwif;   /* Line hardware (lineInterface copy) */
@@ -357,9 +357,8 @@ struct fst_card_info {
 };
 
 /* Convert an HDLC device pointer into a port info pointer and similar */
-#define hdlc_to_port(H) ((struct fst_port_info *)(H))
-#define dev_to_port(D)  hdlc_to_port(dev_to_hdlc(D))
-#define port_to_dev(P)  hdlc_to_dev(&(P)->hdlc)
+#define dev_to_port(D)  (dev_to_hdlc(D)->priv)
+#define port_to_dev(P)  ((P)->dev)
 
 
 /*
@@ -651,6 +650,8 @@ fst_intr_rx ( struct fst_card_info *card
         int rxp;
         unsigned short len;
         struct sk_buff *skb;
+	struct net_device *dev = port_to_dev(port);
+	struct net_device_stats *stats = hdlc_stats(dev);
         int i;
 
 
@@ -678,24 +679,24 @@ fst_intr_rx ( struct fst_card_info *card
                                         len );
         if ( dmabits != ( RX_STP | RX_ENP ) || len > LEN_RX_BUFFER - 2 )
         {
-                port->hdlc.stats.rx_errors++;
+                stats->rx_errors++;
 
                 /* Update error stats and discard buffer */
                 if ( dmabits & RX_OFLO )
                 {
-                        port->hdlc.stats.rx_fifo_errors++;
+                        stats->rx_fifo_errors++;
                 }
                 if ( dmabits & RX_CRC )
                 {
-                        port->hdlc.stats.rx_crc_errors++;
+                        stats->rx_crc_errors++;
                 }
                 if ( dmabits & RX_FRAM )
                 {
-                        port->hdlc.stats.rx_frame_errors++;
+                        stats->rx_frame_errors++;
                 }
                 if ( dmabits == ( RX_STP | RX_ENP ))
                 {
-                        port->hdlc.stats.rx_length_errors++;
+                        stats->rx_length_errors++;
                 }
 
                 /* Discard buffer descriptors until we see the end of packet
@@ -732,7 +733,7 @@ fst_intr_rx ( struct fst_card_info *card
         {
                 dbg ( DBG_RX,"intr_rx: can't allocate buffer\n");
 
-                port->hdlc.stats.rx_dropped++;
+                stats->rx_dropped++;
 
                 /* Return descriptor to card */
                 FST_WRB ( card, rxDescrRing[pi][rxp].bits, DMA_OWN );
@@ -756,16 +757,16 @@ fst_intr_rx ( struct fst_card_info *card
                 port->rxpos = rxp;
 
         /* Update stats */
-        port->hdlc.stats.rx_packets++;
-        port->hdlc.stats.rx_bytes += len;
+        stats->rx_packets++;
+        stats->rx_bytes += len;
 
         /* Push upstream */
         skb->mac.raw = skb->data;
-        skb->dev = hdlc_to_dev ( &port->hdlc );
+        skb->dev = dev;
         skb->protocol = hdlc_type_trans(skb, skb->dev);
         netif_rx ( skb );
 
-        port_to_dev ( port )->last_rx = jiffies;
+        dev->last_rx = jiffies;
 }
 
 
@@ -835,8 +836,8 @@ fst_intr ( int irq, void *dev_id, struct
                          * always load up the entire packet for DMA.
                          */
                         dbg ( DBG_TX,"Tx underflow port %d\n", event & 0x03 );
-                        port->hdlc.stats.tx_errors++;
-                        port->hdlc.stats.tx_fifo_errors++;
+                        hdlc_stats(port_to_dev(port))->tx_errors++;
+                        hdlc_stats(port_to_dev(port))->tx_fifo_errors++;
                         break;
 
                 case INIT_CPLT:
@@ -1309,7 +1310,7 @@ fst_open ( struct net_device *dev )
 {
         int err;
 
-        err = hdlc_open ( dev_to_hdlc ( dev ));
+        err = hdlc_open (dev);
         if ( err )
                 return err;
 
@@ -1323,12 +1324,12 @@ fst_close ( struct net_device *dev )
 {
         netif_stop_queue ( dev );
         fst_closeport ( dev_to_port ( dev ));
-        hdlc_close ( dev_to_hdlc  ( dev ));
+        hdlc_close ( dev );
         return 0;
 }
 
 static int
-fst_attach ( hdlc_device *hdlc, unsigned short encoding, unsigned short parity )
+fst_attach ( struct net_device *dev, unsigned short encoding, unsigned short parity )
 {
         /* Setting currently fixed in FarSync card so we check and forget */
         if ( encoding != ENCODING_NRZ || parity != PARITY_CRC16_PR1_CCITT )
@@ -1341,13 +1342,14 @@ static void
 fst_tx_timeout ( struct net_device *dev )
 {
         struct fst_port_info *port;
+	struct net_device_stats *stats = hdlc_stats(dev);
 
         dbg ( DBG_INTR | DBG_TX,"tx_timeout\n");
 
         port = dev_to_port ( dev );
 
-        port->hdlc.stats.tx_errors++;
-        port->hdlc.stats.tx_aborted_errors++;
+        stats->tx_errors++;
+        stats->tx_aborted_errors++;
 
         if ( port->txcnt > 0 )
                 fst_issue_cmd ( port, ABORTTX );
@@ -1360,6 +1362,7 @@ fst_tx_timeout ( struct net_device *dev 
 static int
 fst_start_xmit ( struct sk_buff *skb, struct net_device *dev )
 {
+	struct net_device_stats *stats = hdlc_stats(dev);
         struct fst_card_info *card;
         struct fst_port_info *port;
         unsigned char dmabits;
@@ -1374,8 +1377,8 @@ fst_start_xmit ( struct sk_buff *skb, st
         if ( ! netif_carrier_ok ( dev ))
         {
                 dev_kfree_skb ( skb );
-                port->hdlc.stats.tx_errors++;
-                port->hdlc.stats.tx_carrier_errors++;
+                stats->tx_errors++;
+                stats->tx_carrier_errors++;
                 return 0;
         }
 
@@ -1385,7 +1388,7 @@ fst_start_xmit ( struct sk_buff *skb, st
                 dbg ( DBG_TX,"Packet too large %d vs %d\n", skb->len,
                                                 LEN_TX_BUFFER );
                 dev_kfree_skb ( skb );
-                port->hdlc.stats.tx_errors++;
+                stats->tx_errors++;
                 return 0;
         }
 
@@ -1399,7 +1402,7 @@ fst_start_xmit ( struct sk_buff *skb, st
                 spin_unlock_irqrestore ( &card->card_lock, flags );
                 dbg ( DBG_TX,"Out of Tx buffers\n");
                 dev_kfree_skb ( skb );
-                port->hdlc.stats.tx_errors++;
+                stats->tx_errors++;
                 return 0;
         }
         if ( ++port->txpos >= NUM_TX_BUFFER )
@@ -1419,8 +1422,8 @@ fst_start_xmit ( struct sk_buff *skb, st
         FST_WRW ( card, txDescrRing[pi][txp].bcnt, cnv_bcnt ( skb->len ));
         FST_WRB ( card, txDescrRing[pi][txp].bits, DMA_OWN | TX_STP | TX_ENP );
 
-        port->hdlc.stats.tx_packets++;
-        port->hdlc.stats.tx_bytes += skb->len;
+        stats->tx_packets++;
+        stats->tx_bytes += skb->len;
 
         dev_kfree_skb ( skb );
 
@@ -1447,55 +1450,29 @@ fst_init_card ( struct fst_card_info *ca
 {
         int i;
         int err;
-        struct net_device *dev;
 
         /* We're working on a number of ports based on the card ID. If the
          * firmware detects something different later (should never happen)
          * we'll have to revise it in some way then.
          */
-        for ( i = 0 ; i < card->nports ; i++ )
-        {
-                card->ports[i].card   = card;
-                card->ports[i].index  = i;
-                card->ports[i].run    = 0;
-
-                dev = hdlc_to_dev ( &card->ports[i].hdlc );
-
-                /* Fill in the net device info */
-                                /* Since this is a PCI setup this is purely
-                                 * informational. Give them the buffer addresses
-                                 * and basic card I/O.
-                                 */
-                dev->mem_start   = card->phys_mem
-                                 + BUF_OFFSET ( txBuffer[i][0][0]);
-                dev->mem_end     = card->phys_mem
-                                 + BUF_OFFSET ( txBuffer[i][NUM_TX_BUFFER][0]);
-                dev->base_addr   = card->pci_conf;
-                dev->irq         = card->irq;
-
-                dev->tx_queue_len          = FST_TX_QUEUE_LEN;
-                dev->open                  = fst_open;
-                dev->stop                  = fst_close;
-                dev->do_ioctl              = fst_ioctl;
-                dev->watchdog_timeo        = FST_TX_TIMEOUT;
-                dev->tx_timeout            = fst_tx_timeout;
-                card->ports[i].hdlc.attach = fst_attach;
-                card->ports[i].hdlc.xmit   = fst_start_xmit;
-
-                if (( err = register_hdlc_device ( &card->ports[i].hdlc )) < 0 )
-                {
+        for ( i = 0 ; i < card->nports ; i++ ) {
+                err = register_hdlc_device(card->ports[i].dev);
+                if (err < 0) {
+			int j;
                         printk_err ("Cannot register HDLC device for port %d"
                                     " (errno %d)\n", i, -err );
+			for (j = i; j < card->nports; j++) {
+				free_netdev(card->ports[j].dev);
+				card->ports[j].dev = NULL;
+			}
                         card->nports = i;
                         break;
                 }
         }
 
-        spin_lock_init ( &card->card_lock );
-
         printk ( KERN_INFO "%s-%s: %s IRQ%d, %d ports\n",
-                        hdlc_to_dev(&card->ports[0].hdlc)->name,
-                        hdlc_to_dev(&card->ports[card->nports-1].hdlc)->name,
+                        port_to_dev(&card->ports[0])->name,
+                        port_to_dev(&card->ports[card->nports-1])->name,
                         type_strings[card->type], card->irq, card->nports );
 }
 
@@ -1510,6 +1487,7 @@ fst_add_one ( struct pci_dev *pdev, cons
         static int firsttime_done = 0;
         struct fst_card_info *card;
         int err = 0;
+	int i;
 
         if ( ! firsttime_done )
         {
@@ -1546,6 +1524,46 @@ fst_add_one ( struct pci_dev *pdev, cons
 
         card->state       = FST_UNINIT;
 
+        spin_lock_init ( &card->card_lock );
+
+        for ( i = 0 ; i < card->nports ; i++ ) {
+		struct net_device *dev = alloc_hdlcdev(&card->ports[i]);
+		hdlc_device *hdlc;
+		if (!dev) {
+			while (i--)
+				free_netdev(card->ports[i].dev);
+			printk_err ("FarSync: out of memory\n");
+			goto error_free_card;
+		}
+		card->ports[i].dev    = dev;
+                card->ports[i].card   = card;
+                card->ports[i].index  = i;
+                card->ports[i].run    = 0;
+
+		hdlc = dev_to_hdlc(dev);
+
+                /* Fill in the net device info */
+		/* Since this is a PCI setup this is purely
+		 * informational. Give them the buffer addresses
+		 * and basic card I/O.
+		 */
+                dev->mem_start   = card->phys_mem
+                                 + BUF_OFFSET ( txBuffer[i][0][0]);
+                dev->mem_end     = card->phys_mem
+                                 + BUF_OFFSET ( txBuffer[i][NUM_TX_BUFFER][0]);
+                dev->base_addr   = card->pci_conf;
+                dev->irq         = card->irq;
+
+                dev->tx_queue_len          = FST_TX_QUEUE_LEN;
+                dev->open                  = fst_open;
+                dev->stop                  = fst_close;
+                dev->do_ioctl              = fst_ioctl;
+                dev->watchdog_timeo        = FST_TX_TIMEOUT;
+                dev->tx_timeout            = fst_tx_timeout;
+                hdlc->attach = fst_attach;
+                hdlc->xmit   = fst_start_xmit;
+	}
+
         dbg ( DBG_PCI,"type %d nports %d irq %d\n", card->type,
                         card->nports, card->irq );
         dbg ( DBG_PCI,"conf %04x mem %08x ctlmem %08x\n",
@@ -1557,7 +1575,7 @@ fst_add_one ( struct pci_dev *pdev, cons
                 printk_err ("Unable to get config I/O @ 0x%04X\n",
                                                 card->pci_conf );
                 err = -ENODEV;
-                goto error_free_card;
+                goto error_free_ports;
         }
         if ( ! request_mem_region ( card->phys_mem, FST_MEMSIZE,"Shared RAM"))
         {
@@ -1628,6 +1646,9 @@ error_release_mem:
 error_release_io:
         release_region ( card->pci_conf, 0x80 );
 
+error_free_ports:
+	for (i = 0; i < card->nports; i++)
+		free_netdev(card->ports[i].dev);
 error_free_card:
         kfree ( card );
         return err;
@@ -1647,7 +1668,8 @@ fst_remove_one ( struct pci_dev *pdev )
 
         for ( i = 0 ; i < card->nports ; i++ )
         {
-                unregister_hdlc_device ( &card->ports[i].hdlc );
+		struct net_device *dev = port_to_dev(&card->ports[i]);
+                unregister_hdlc_device(dev);
         }
 
         fst_disable_intr ( card );
@@ -1660,6 +1682,9 @@ fst_remove_one ( struct pci_dev *pdev )
         release_mem_region ( card->phys_mem, FST_MEMSIZE );
         release_region ( card->pci_conf, 0x80 );
 
+	for (i = 0; i < card->nports; i++)
+		free_netdev(card->ports[i].dev);
+
         kfree ( card );
 }
 
--- diff/drivers/net/wan/hd6457x.c	2003-08-20 14:16:10.000000000 +0100
+++ source/drivers/net/wan/hd6457x.c	2004-02-23 13:56:44.000000000 +0000
@@ -73,6 +73,11 @@
 #define writea(value, ptr)		writel(value, ptr)
 #endif
 
+static inline struct net_device *port_to_dev(port_t *port)
+{
+	return port->dev;
+}
+
 static inline int sca_intr_status(card_t *card)
 {
 	u8 result = 0;
@@ -110,22 +115,11 @@ static inline int sca_intr_status(card_t
 	return result;
 }
 
-
-
-static inline port_t* hdlc_to_port(hdlc_device *hdlc)
-{
-	return (port_t*)hdlc;
-}
-
-
-
 static inline port_t* dev_to_port(struct net_device *dev)
 {
-	return hdlc_to_port(dev_to_hdlc(dev));
+	return dev_to_hdlc(dev)->priv;
 }
 
-
-
 static inline u16 next_desc(port_t *port, u16 desc, int transmit)
 {
 	return (desc + 1) % (transmit ? port_to_card(port)->tx_ring_buffers
@@ -245,7 +239,7 @@ static void sca_init_sync_port(port_t *p
 	}
 
 	hdlc_set_carrier(!(sca_in(get_msci(port) + ST3, card) & ST3_DCD),
-			 &port->hdlc);
+			 port_to_dev(port));
 }
 
 
@@ -262,13 +256,14 @@ static inline void sca_msci_intr(port_t 
 	sca_out(stat & (ST1_UDRN | ST1_CDCD), msci + ST1, card);
 
 	if (stat & ST1_UDRN) {
-		port->hdlc.stats.tx_errors++; /* TX Underrun error detected */
-		port->hdlc.stats.tx_fifo_errors++;
+		struct net_device_stats *stats = hdlc_stats(port_to_dev(port));
+		stats->tx_errors++; /* TX Underrun error detected */
+		stats->tx_fifo_errors++;
 	}
 
 	if (stat & ST1_CDCD)
 		hdlc_set_carrier(!(sca_in(msci + ST3, card) & ST3_DCD),
-				 &port->hdlc);
+				 port_to_dev(port));
 }
 #endif
 
@@ -276,6 +271,8 @@ static inline void sca_msci_intr(port_t 
 
 static inline void sca_rx(card_t *card, port_t *port, pkt_desc *desc, u16 rxin)
 {
+	struct net_device *dev = port_to_dev(port);
+	struct net_device_stats *stats = hdlc_stats(dev);
 	struct sk_buff *skb;
 	u16 len;
 	u32 buff;
@@ -287,7 +284,7 @@ static inline void sca_rx(card_t *card, 
 	len = readw(&desc->len);
 	skb = dev_alloc_skb(len);
 	if (!skb) {
-		port->hdlc.stats.rx_dropped++;
+		stats->rx_dropped++;
 		return;
 	}
 
@@ -313,15 +310,15 @@ static inline void sca_rx(card_t *card, 
 #endif
 	skb_put(skb, len);
 #ifdef DEBUG_PKT
-	printk(KERN_DEBUG "%s RX(%i):", hdlc_to_name(&port->hdlc), skb->len);
+	printk(KERN_DEBUG "%s RX(%i):", dev->name, skb->len);
 	debug_frame(skb);
 #endif
-	port->hdlc.stats.rx_packets++;
-	port->hdlc.stats.rx_bytes += skb->len;
+	stats->rx_packets++;
+	stats->rx_bytes += skb->len;
 	skb->mac.raw = skb->data;
-	skb->dev = hdlc_to_dev(&port->hdlc);
+	skb->dev = dev;
 	skb->dev->last_rx = jiffies;
-	skb->protocol = hdlc_type_trans(skb, hdlc_to_dev(&port->hdlc));
+	skb->protocol = hdlc_type_trans(skb, dev);
 	netif_rx(skb);
 }
 
@@ -333,7 +330,7 @@ static inline void sca_rx_intr(port_t *p
 	u16 dmac = get_dmac_rx(port);
 	card_t *card = port_to_card(port);
 	u8 stat = sca_in(DSR_RX(phy_node(port)), card); /* read DMA Status */
-	struct net_device_stats *stats = &port->hdlc.stats;
+	struct net_device_stats *stats = hdlc_stats(port_to_dev(port));
 
 	/* Reset DSR status bits */
 	sca_out((stat & (DSR_EOT | DSR_EOM | DSR_BOF | DSR_COF)) | DSR_DWE,
@@ -380,6 +377,8 @@ static inline void sca_rx_intr(port_t *p
 /* Transmit DMA interrupt service */
 static inline void sca_tx_intr(port_t *port)
 {
+	struct net_device *dev = port_to_dev(port);
+	struct net_device_stats *stats = hdlc_stats(dev);
 	u16 dmac = get_dmac_tx(port);
 	card_t* card = port_to_card(port);
 	u8 stat;
@@ -401,13 +400,13 @@ static inline void sca_tx_intr(port_t *p
 			break;	/* Transmitter is/will_be sending this frame */
 
 		desc = desc_address(port, port->txlast, 1);
-		port->hdlc.stats.tx_packets++;
-		port->hdlc.stats.tx_bytes += readw(&desc->len);
+		stats->tx_packets++;
+		stats->tx_bytes += readw(&desc->len);
 		writeb(0, &desc->stat);	/* Free descriptor */
 		port->txlast = next_desc(port, port->txlast, 1);
 	}
 
-	netif_wake_queue(hdlc_to_dev(&port->hdlc));
+	netif_wake_queue(dev);
 	spin_unlock(&port->lock);
 }
 
@@ -508,9 +507,9 @@ static void sca_set_port(port_t *port)
 
 
 
-static void sca_open(hdlc_device *hdlc)
+static void sca_open(struct net_device *dev)
 {
-	port_t *port = hdlc_to_port(hdlc);
+	port_t *port = dev_to_port(dev);
 	card_t* card = port_to_card(port);
 	u16 msci = get_msci(port);
 	u8 md0, md2;
@@ -569,7 +568,7 @@ static void sca_open(hdlc_device *hdlc)
    - all DMA interrupts
 */
 
-	hdlc_set_carrier(!(sca_in(msci + ST3, card) & ST3_DCD), hdlc);
+	hdlc_set_carrier(!(sca_in(msci + ST3, card) & ST3_DCD), dev);
 
 #ifdef __HD64570_H
 	/* MSCI TX INT and RX INT A IRQ enable */
@@ -600,18 +599,18 @@ static void sca_open(hdlc_device *hdlc)
 	sca_out(CMD_TX_ENABLE, msci + CMD, card);
 	sca_out(CMD_RX_ENABLE, msci + CMD, card);
 
-	netif_start_queue(hdlc_to_dev(hdlc));
+	netif_start_queue(dev);
 }
 
 
 
-static void sca_close(hdlc_device *hdlc)
+static void sca_close(struct net_device *dev)
 {
-	port_t *port = hdlc_to_port(hdlc);
+	port_t *port = dev_to_port(dev);
 	card_t* card = port_to_card(port);
 
 	/* reset channel */
-	netif_stop_queue(hdlc_to_dev(hdlc));
+	netif_stop_queue(dev);
 	sca_out(CMD_RESET, get_msci(port) + CMD, port_to_card(port));
 #ifdef __HD64570_H
 	/* disable MSCI interrupts */
@@ -629,7 +628,7 @@ static void sca_close(hdlc_device *hdlc)
 
 
 
-static int sca_attach(hdlc_device *hdlc, unsigned short encoding,
+static int sca_attach(struct net_device *dev, unsigned short encoding,
 		      unsigned short parity)
 {
 	if (encoding != ENCODING_NRZ &&
@@ -650,17 +649,17 @@ static int sca_attach(hdlc_device *hdlc,
 	    parity != PARITY_CRC16_PR1_CCITT)
 		return -EINVAL;
 
-	hdlc_to_port(hdlc)->encoding = encoding;
-	hdlc_to_port(hdlc)->parity = parity;
+	dev_to_port(dev)->encoding = encoding;
+	dev_to_port(dev)->parity = parity;
 	return 0;
 }
 
 
 
 #ifdef DEBUG_RINGS
-static void sca_dump_rings(hdlc_device *hdlc)
+static void sca_dump_rings(struct net_device *dev)
 {
-	port_t *port = hdlc_to_port(hdlc);
+	port_t *port = dev_to_port(dev);
 	card_t *card = port_to_card(port);
 	u16 cnt;
 #if !defined(PAGE0_ALWAYS_MAPPED) && !defined(ALL_PAGES_ALWAYS_MAPPED)
@@ -729,8 +728,7 @@ static void sca_dump_rings(hdlc_device *
 
 static int sca_xmit(struct sk_buff *skb, struct net_device *dev)
 {
-	hdlc_device *hdlc = dev_to_hdlc(dev);
-	port_t *port = hdlc_to_port(hdlc);
+	port_t *port = dev_to_port(dev);
 	card_t *card = port_to_card(port);
 	pkt_desc *desc;
 	u32 buff, len;
@@ -753,7 +751,7 @@ static int sca_xmit(struct sk_buff *skb,
 	}
 
 #ifdef DEBUG_PKT
-	printk(KERN_DEBUG "%s TX(%i):", hdlc_to_name(hdlc), skb->len);
+	printk(KERN_DEBUG "%s TX(%i):", dev->name, skb->len);
 	debug_frame(skb);
 #endif
 
@@ -790,7 +788,7 @@ static int sca_xmit(struct sk_buff *skb,
 
 	desc = desc_address(port, port->txin + 1, 1);
 	if (readb(&desc->stat)) /* allow 1 packet gap */
-		netif_stop_queue(hdlc_to_dev(&port->hdlc));
+		netif_stop_queue(dev);
 
 	spin_unlock_irq(&port->lock);
 
--- diff/drivers/net/wan/hdlc_cisco.c	2003-10-27 09:20:38.000000000 +0000
+++ source/drivers/net/wan/hdlc_cisco.c	2004-02-23 13:56:44.000000000 +0000
@@ -57,7 +57,7 @@ static int cisco_hard_header(struct sk_b
 
 
 
-static void cisco_keepalive_send(hdlc_device *hdlc, u32 type,
+static void cisco_keepalive_send(struct net_device *dev, u32 type,
 				 u32 par1, u32 par2)
 {
 	struct sk_buff *skb;
@@ -67,12 +67,11 @@ static void cisco_keepalive_send(hdlc_de
 	if (!skb) {
 		printk(KERN_WARNING
 		       "%s: Memory squeeze on cisco_keepalive_send()\n",
-		       hdlc_to_name(hdlc));
+		       dev->name);
 		return;
 	}
 	skb_reserve(skb, 4);
-	cisco_hard_header(skb, hdlc_to_dev(hdlc), CISCO_KEEPALIVE,
-			  NULL, NULL, 0);
+	cisco_hard_header(skb, dev, CISCO_KEEPALIVE, NULL, NULL, 0);
 	data = (cisco_packet*)skb->tail;
 
 	data->type = htonl(type);
@@ -84,7 +83,7 @@ static void cisco_keepalive_send(hdlc_de
 
 	skb_put(skb, sizeof(cisco_packet));
 	skb->priority = TC_PRIO_CONTROL;
-	skb->dev = hdlc_to_dev(hdlc);
+	skb->dev = dev;
 	skb->nh.raw = skb->data;
 
 	dev_queue_xmit(skb);
@@ -118,7 +117,8 @@ static unsigned short cisco_type_trans(s
 
 static int cisco_rx(struct sk_buff *skb)
 {
-	hdlc_device *hdlc = dev_to_hdlc(skb->dev);
+	struct net_device *dev = skb->dev;
+	hdlc_device *hdlc = dev_to_hdlc(dev);
 	hdlc_header *data = (hdlc_header*)skb->data;
 	cisco_packet *cisco_data;
 	struct in_device *in_dev;
@@ -142,7 +142,7 @@ static int cisco_rx(struct sk_buff *skb)
 		    skb->len != sizeof(hdlc_header) + CISCO_BIG_PACKET_LEN) {
 			printk(KERN_INFO "%s: Invalid length of Cisco "
 			       "control packet (%d bytes)\n",
-			       hdlc_to_name(hdlc), skb->len);
+			       dev->name, skb->len);
 			goto rx_error;
 		}
 
@@ -150,7 +150,7 @@ static int cisco_rx(struct sk_buff *skb)
 
 		switch(ntohl (cisco_data->type)) {
 		case CISCO_ADDR_REQ: /* Stolen from syncppp.c :-) */
-			in_dev = hdlc_to_dev(hdlc)->ip_ptr;
+			in_dev = dev->ip_ptr;
 			addr = 0;
 			mask = ~0; /* is the mask correct? */
 
@@ -158,7 +158,7 @@ static int cisco_rx(struct sk_buff *skb)
 				struct in_ifaddr **ifap = &in_dev->ifa_list;
 
 				while (*ifap != NULL) {
-					if (strcmp(hdlc_to_name(hdlc),
+					if (strcmp(dev->name,
 						   (*ifap)->ifa_label) == 0) {
 						addr = (*ifap)->ifa_local;
 						mask = (*ifap)->ifa_mask;
@@ -167,7 +167,7 @@ static int cisco_rx(struct sk_buff *skb)
 					ifap = &(*ifap)->ifa_next;
 				}
 
-				cisco_keepalive_send(hdlc, CISCO_ADDR_REPLY,
+				cisco_keepalive_send(dev, CISCO_ADDR_REPLY,
 						     addr, mask);
 			}
 			dev_kfree_skb_any(skb);
@@ -175,7 +175,7 @@ static int cisco_rx(struct sk_buff *skb)
 
 		case CISCO_ADDR_REPLY:
 			printk(KERN_INFO "%s: Unexpected Cisco IP address "
-			       "reply\n", hdlc_to_name(hdlc));
+			       "reply\n", dev->name);
 			goto rx_error;
 
 		case CISCO_KEEPALIVE_REQ:
@@ -190,7 +190,7 @@ static int cisco_rx(struct sk_buff *skb)
 					days = hrs / 24; hrs -= days * 24;
 					printk(KERN_INFO "%s: Link up (peer "
 					       "uptime %ud%uh%um%us)\n",
-					       hdlc_to_name(hdlc), days, hrs,
+					       dev->name, days, hrs,
 					       min, sec);
 				}
 				hdlc->state.cisco.up = 1;
@@ -201,7 +201,7 @@ static int cisco_rx(struct sk_buff *skb)
 		} /* switch(keepalive type) */
 	} /* switch(protocol) */
 
-	printk(KERN_INFO "%s: Unsupported protocol %x\n", hdlc_to_name(hdlc),
+	printk(KERN_INFO "%s: Unsupported protocol %x\n", dev->name,
 	       data->protocol);
 	dev_kfree_skb_any(skb);
 	return NET_RX_DROP;
@@ -216,17 +216,18 @@ static int cisco_rx(struct sk_buff *skb)
 
 static void cisco_timer(unsigned long arg)
 {
-	hdlc_device *hdlc = (hdlc_device*)arg;
+	struct net_device *dev = (struct net_device *)arg;
+	hdlc_device *hdlc = dev_to_hdlc(dev);
 
 	if (hdlc->state.cisco.up && jiffies - hdlc->state.cisco.last_poll >=
 	    hdlc->state.cisco.settings.timeout * HZ) {
 		hdlc->state.cisco.up = 0;
-		printk(KERN_INFO "%s: Link down\n", hdlc_to_name(hdlc));
-		if (netif_carrier_ok(&hdlc->netdev))
-			netif_carrier_off(&hdlc->netdev);
+		printk(KERN_INFO "%s: Link down\n", dev->name);
+		if (netif_carrier_ok(dev))
+			netif_carrier_off(dev);
 	}
 
-	cisco_keepalive_send(hdlc, CISCO_KEEPALIVE_REQ,
+	cisco_keepalive_send(dev, CISCO_KEEPALIVE_REQ,
 			     ++hdlc->state.cisco.txseq,
 			     hdlc->state.cisco.rxseq);
 	hdlc->state.cisco.timer.expires = jiffies +
@@ -238,8 +239,9 @@ static void cisco_timer(unsigned long ar
 
 
 
-static void cisco_start(hdlc_device *hdlc)
+static void cisco_start(struct net_device *dev)
 {
+	hdlc_device *hdlc = dev_to_hdlc(dev);
 	hdlc->state.cisco.last_poll = 0;
 	hdlc->state.cisco.up = 0;
 	hdlc->state.cisco.txseq = hdlc->state.cisco.rxseq = 0;
@@ -247,27 +249,27 @@ static void cisco_start(hdlc_device *hdl
 	init_timer(&hdlc->state.cisco.timer);
 	hdlc->state.cisco.timer.expires = jiffies + HZ; /*First poll after 1s*/
 	hdlc->state.cisco.timer.function = cisco_timer;
-	hdlc->state.cisco.timer.data = (unsigned long)hdlc;
+	hdlc->state.cisco.timer.data = (unsigned long)dev;
 	add_timer(&hdlc->state.cisco.timer);
 }
 
 
 
-static void cisco_stop(hdlc_device *hdlc)
+static void cisco_stop(struct net_device *dev)
 {
-	del_timer_sync(&hdlc->state.cisco.timer);
-	if (netif_carrier_ok(&hdlc->netdev))
-		netif_carrier_off(&hdlc->netdev);
+	del_timer_sync(&dev_to_hdlc(dev)->state.cisco.timer);
+	if (netif_carrier_ok(dev))
+		netif_carrier_off(dev);
 }
 
 
 
-int hdlc_cisco_ioctl(hdlc_device *hdlc, struct ifreq *ifr)
+int hdlc_cisco_ioctl(struct net_device *dev, struct ifreq *ifr)
 {
 	cisco_proto *cisco_s = ifr->ifr_settings.ifs_ifsu.cisco;
 	const size_t size = sizeof(cisco_proto);
 	cisco_proto new_settings;
-	struct net_device *dev = hdlc_to_dev(hdlc);
+	hdlc_device *hdlc = dev_to_hdlc(dev);
 	int result;
 
 	switch (ifr->ifr_settings.type) {
@@ -295,7 +297,7 @@ int hdlc_cisco_ioctl(hdlc_device *hdlc, 
 		    new_settings.timeout < 2)
 			return -EINVAL;
 
-		result=hdlc->attach(hdlc, ENCODING_NRZ,PARITY_CRC16_PR1_CCITT);
+		result=hdlc->attach(dev, ENCODING_NRZ,PARITY_CRC16_PR1_CCITT);
 
 		if (result)
 			return result;
--- diff/drivers/net/wan/hdlc_fr.c	2003-08-26 10:00:53.000000000 +0100
+++ source/drivers/net/wan/hdlc_fr.c	2004-02-23 13:56:44.000000000 +0000
@@ -146,8 +146,9 @@ static inline pvc_device* find_pvc(hdlc_
 }
 
 
-static inline pvc_device* add_pvc(hdlc_device *hdlc, u16 dlci)
+static inline pvc_device* add_pvc(struct net_device *dev, u16 dlci)
 {
+	hdlc_device *hdlc = dev_to_hdlc(dev);
 	pvc_device *pvc, **pvc_p = &hdlc->state.fr.first_pvc;
 
 	while (*pvc_p) {
@@ -164,7 +165,7 @@ static inline pvc_device* add_pvc(hdlc_d
 
 	memset(pvc, 0, sizeof(pvc_device));
 	pvc->dlci = dlci;
-	pvc->master = hdlc;
+	pvc->master = dev;
 	pvc->next = *pvc_p;	/* Put it in the chain */
 	*pvc_p = pvc;
 	return pvc;
@@ -311,15 +312,16 @@ static int pvc_open(struct net_device *d
 {
 	pvc_device *pvc = dev_to_pvc(dev);
 
-	if ((hdlc_to_dev(pvc->master)->flags & IFF_UP) == 0)
+	if ((pvc->master->flags & IFF_UP) == 0)
 		return -EIO;  /* Master must be UP in order to activate PVC */
 
 	if (pvc->open_count++ == 0) {
-		if (pvc->master->state.fr.settings.lmi == LMI_NONE)
-			pvc->state.active = pvc->master->carrier;
+		hdlc_device *hdlc = dev_to_hdlc(pvc->master);
+		if (hdlc->state.fr.settings.lmi == LMI_NONE)
+			pvc->state.active = hdlc->carrier;
 
 		pvc_carrier(pvc->state.active, pvc);
-		pvc->master->state.fr.dce_changed = 1;
+		hdlc->state.fr.dce_changed = 1;
 	}
 	return 0;
 }
@@ -331,11 +333,12 @@ static int pvc_close(struct net_device *
 	pvc_device *pvc = dev_to_pvc(dev);
 
 	if (--pvc->open_count == 0) {
-		if (pvc->master->state.fr.settings.lmi == LMI_NONE)
+		hdlc_device *hdlc = dev_to_hdlc(pvc->master);
+		if (hdlc->state.fr.settings.lmi == LMI_NONE)
 			pvc->state.active = 0;
 
-		if (pvc->master->state.fr.settings.dce) {
-			pvc->master->state.fr.dce_changed = 1;
+		if (hdlc->state.fr.settings.dce) {
+			hdlc->state.fr.dce_changed = 1;
 			pvc->state.active = 0;
 		}
 	}
@@ -362,7 +365,7 @@ int pvc_ioctl(struct net_device *dev, st
 		}
 
 		info.dlci = pvc->dlci;
-		memcpy(info.master, hdlc_to_name(pvc->master), IFNAMSIZ);
+		memcpy(info.master, pvc->master->name, IFNAMSIZ);
 		if (copy_to_user(ifr->ifr_settings.ifs_ifsu.fr_pvc_info,
 				 &info, sizeof(info)))
 			return -EFAULT;
@@ -375,8 +378,7 @@ int pvc_ioctl(struct net_device *dev, st
 
 static inline struct net_device_stats *pvc_get_stats(struct net_device *dev)
 {
-	return (struct net_device_stats *)
-		((char *)dev + sizeof(struct net_device));
+	return netdev_priv(dev);
 }
 
 
@@ -408,7 +410,7 @@ static int pvc_xmit(struct sk_buff *skb,
 			stats->tx_packets++;
 			if (pvc->state.fecn) /* TX Congestion counter */
 				stats->tx_compressed++;
-			skb->dev = hdlc_to_dev(pvc->master);
+			skb->dev = pvc->master;
 			dev_queue_xmit(skb);
 			return 0;
 		}
@@ -434,7 +436,7 @@ static int pvc_change_mtu(struct net_dev
 static inline void fr_log_dlci_active(pvc_device *pvc)
 {
 	printk(KERN_INFO "%s: DLCI %d [%s%s%s]%s %s\n",
-	       hdlc_to_name(pvc->master),
+	       pvc->master->name,
 	       pvc->dlci,
 	       pvc->main ? pvc->main->name : "",
 	       pvc->main && pvc->ether ? " " : "",
@@ -454,8 +456,9 @@ static inline u8 fr_lmi_nextseq(u8 x)
 
 
 
-static void fr_lmi_send(hdlc_device *hdlc, int fullrep)
+static void fr_lmi_send(struct net_device *dev, int fullrep)
 {
+	hdlc_device *hdlc = dev_to_hdlc(dev);
 	struct sk_buff *skb;
 	pvc_device *pvc = hdlc->state.fr.first_pvc;
 	int len = (hdlc->state.fr.settings.lmi == LMI_ANSI) ? LMI_ANSI_LENGTH
@@ -468,7 +471,7 @@ static void fr_lmi_send(hdlc_device *hdl
 		len += hdlc->state.fr.dce_pvc_count * (2 + stat_len);
 		if (len > HDLC_MAX_MRU) {
 			printk(KERN_WARNING "%s: Too many PVCs while sending "
-			       "LMI full report\n", hdlc_to_name(hdlc));
+			       "LMI full report\n", dev->name);
 			return;
 		}
 	}
@@ -476,7 +479,7 @@ static void fr_lmi_send(hdlc_device *hdl
 	skb = dev_alloc_skb(len);
 	if (!skb) {
 		printk(KERN_WARNING "%s: Memory squeeze on fr_lmi_send()\n",
-		       hdlc_to_name(hdlc));
+		       dev->name);
 		return;
 	}
 	memset(skb->data, 0, len);
@@ -529,7 +532,7 @@ static void fr_lmi_send(hdlc_device *hdl
 
 	skb_put(skb, i);
 	skb->priority = TC_PRIO_CONTROL;
-	skb->dev = hdlc_to_dev(hdlc);
+	skb->dev = dev;
 	skb->nh.raw = skb->data;
 
 	dev_queue_xmit(skb);
@@ -537,14 +540,15 @@ static void fr_lmi_send(hdlc_device *hdl
 
 
 
-static void fr_set_link_state(int reliable, hdlc_device *hdlc)
+static void fr_set_link_state(int reliable, struct net_device *dev)
 {
+	hdlc_device *hdlc = dev_to_hdlc(dev);
 	pvc_device *pvc = hdlc->state.fr.first_pvc;
 
 	hdlc->state.fr.reliable = reliable;
 	if (reliable) {
-		if (!netif_carrier_ok(&hdlc->netdev))
-			netif_carrier_on(&hdlc->netdev);
+		if (!netif_carrier_ok(dev))
+			netif_carrier_on(dev);
 
 		hdlc->state.fr.n391cnt = 0; /* Request full status */
 		hdlc->state.fr.dce_changed = 1;
@@ -558,8 +562,8 @@ static void fr_set_link_state(int reliab
 			}
 		}
 	} else {
-		if (netif_carrier_ok(&hdlc->netdev))
-			netif_carrier_off(&hdlc->netdev);
+		if (netif_carrier_ok(dev))
+			netif_carrier_off(dev);
 
 		while (pvc) {		/* Deactivate all PVCs */
 			pvc_carrier(0, pvc);
@@ -574,7 +578,8 @@ static void fr_set_link_state(int reliab
 
 static void fr_timer(unsigned long arg)
 {
-	hdlc_device *hdlc = (hdlc_device*)arg;
+	struct net_device *dev = (struct net_device *)arg;
+	hdlc_device *hdlc = dev_to_hdlc(dev);
 	int i, cnt = 0, reliable;
 	u32 list;
 
@@ -586,7 +591,7 @@ static void fr_timer(unsigned long arg)
 		if (hdlc->state.fr.request) {
 			if (hdlc->state.fr.reliable)
 				printk(KERN_INFO "%s: No LMI status reply "
-				       "received\n", hdlc_to_name(hdlc));
+				       "received\n", dev->name);
 			hdlc->state.fr.last_errors |= 1;
 		}
 
@@ -598,9 +603,9 @@ static void fr_timer(unsigned long arg)
 	}
 
 	if (hdlc->state.fr.reliable != reliable) {
-		printk(KERN_INFO "%s: Link %sreliable\n", hdlc_to_name(hdlc),
+		printk(KERN_INFO "%s: Link %sreliable\n", dev->name,
 		       reliable ? "" : "un");
-		fr_set_link_state(reliable, hdlc);
+		fr_set_link_state(reliable, dev);
 	}
 
 	if (hdlc->state.fr.settings.dce)
@@ -610,7 +615,7 @@ static void fr_timer(unsigned long arg)
 		if (hdlc->state.fr.n391cnt)
 			hdlc->state.fr.n391cnt--;
 
-		fr_lmi_send(hdlc, hdlc->state.fr.n391cnt == 0);
+		fr_lmi_send(dev, hdlc->state.fr.n391cnt == 0);
 
 		hdlc->state.fr.request = 1;
 		hdlc->state.fr.timer.expires = jiffies +
@@ -624,8 +629,9 @@ static void fr_timer(unsigned long arg)
 
 
 
-static int fr_lmi_recv(hdlc_device *hdlc, struct sk_buff *skb)
+static int fr_lmi_recv(struct net_device *dev, struct sk_buff *skb)
 {
+	hdlc_device *hdlc = dev_to_hdlc(dev);
 	int stat_len;
 	pvc_device *pvc;
 	int reptype = -1, error, no_ram;
@@ -634,14 +640,14 @@ static int fr_lmi_recv(hdlc_device *hdlc
 
 	if (skb->len < ((hdlc->state.fr.settings.lmi == LMI_ANSI)
 			? LMI_ANSI_LENGTH : LMI_LENGTH)) {
-		printk(KERN_INFO "%s: Short LMI frame\n", hdlc_to_name(hdlc));
+		printk(KERN_INFO "%s: Short LMI frame\n", dev->name);
 		return 1;
 	}
 
 	if (skb->data[5] != (!hdlc->state.fr.settings.dce ?
 			     LMI_STATUS : LMI_STATUS_ENQUIRY)) {
 		printk(KERN_INFO "%s: LMI msgtype=%x, Not LMI status %s\n",
-		       hdlc_to_name(hdlc), skb->data[2],
+		       dev->name, skb->data[2],
 		       hdlc->state.fr.settings.dce ? "enquiry" : "reply");
 		return 1;
 	}
@@ -652,7 +658,7 @@ static int fr_lmi_recv(hdlc_device *hdlc
 	    ((hdlc->state.fr.settings.lmi == LMI_CCITT)
 	     ? LMI_CCITT_REPTYPE : LMI_REPTYPE)) {
 		printk(KERN_INFO "%s: Not a report type=%x\n",
-		       hdlc_to_name(hdlc), skb->data[i]);
+		       dev->name, skb->data[i]);
 		return 1;
 	}
 	i++;
@@ -665,7 +671,7 @@ static int fr_lmi_recv(hdlc_device *hdlc
 	    ((hdlc->state.fr.settings.lmi == LMI_CCITT)
 	     ? LMI_CCITT_ALIVE : LMI_ALIVE)) {
 		printk(KERN_INFO "%s: Unsupported status element=%x\n",
-		       hdlc_to_name(hdlc), skb->data[i]);
+		       dev->name, skb->data[i]);
 		return 1;
 	}
 	i++;
@@ -680,7 +686,7 @@ static int fr_lmi_recv(hdlc_device *hdlc
 	if (hdlc->state.fr.settings.dce) {
 		if (reptype != LMI_FULLREP && reptype != LMI_INTEGRITY) {
 			printk(KERN_INFO "%s: Unsupported report type=%x\n",
-			       hdlc_to_name(hdlc), reptype);
+			       dev->name, reptype);
 			return 1;
 		}
 	}
@@ -716,7 +722,7 @@ static int fr_lmi_recv(hdlc_device *hdlc
 			hdlc->state.fr.dce_changed = 0;
 		}
 
-		fr_lmi_send(hdlc, reptype == LMI_FULLREP ? 1 : 0);
+		fr_lmi_send(dev, reptype == LMI_FULLREP ? 1 : 0);
 		return 0;
 	}
 
@@ -741,26 +747,26 @@ static int fr_lmi_recv(hdlc_device *hdlc
 		if (skb->data[i] != ((hdlc->state.fr.settings.lmi == LMI_CCITT)
 				     ? LMI_CCITT_PVCSTAT : LMI_PVCSTAT)) {
 			printk(KERN_WARNING "%s: Invalid PVCSTAT ID: %x\n",
-			       hdlc_to_name(hdlc), skb->data[i]);
+			       dev->name, skb->data[i]);
 			return 1;
 		}
 		i++;
 
 		if (skb->data[i] != stat_len) {
 			printk(KERN_WARNING "%s: Invalid PVCSTAT length: %x\n",
-			       hdlc_to_name(hdlc), skb->data[i]);
+			       dev->name, skb->data[i]);
 			return 1;
 		}
 		i++;
 
 		dlci = status_to_dlci(skb->data + i, &active, &new);
 
-		pvc = add_pvc(hdlc, dlci);
+		pvc = add_pvc(dev, dlci);
 
 		if (!pvc && !no_ram) {
 			printk(KERN_WARNING
 			       "%s: Memory squeeze on fr_lmi_recv()\n",
-			       hdlc_to_name(hdlc));
+			       dev->name);
 			no_ram = 1;
 		}
 
@@ -802,7 +808,8 @@ static int fr_lmi_recv(hdlc_device *hdlc
 
 static int fr_rx(struct sk_buff *skb)
 {
-	hdlc_device *hdlc = dev_to_hdlc(skb->dev);
+	struct net_device *ndev = skb->dev;
+	hdlc_device *hdlc = dev_to_hdlc(ndev);
 	fr_hdr *fh = (fr_hdr*)skb->data;
 	u8 *data = skb->data;
 	u16 dlci;
@@ -819,7 +826,7 @@ static int fr_rx(struct sk_buff *skb)
 			goto rx_error; /* LMI packet with no LMI? */
 
 		if (data[3] == LMI_PROTO) {
-			if (fr_lmi_recv(hdlc, skb))
+			if (fr_lmi_recv(ndev, skb))
 				goto rx_error;
 			else {
 				/* No request pending */
@@ -831,7 +838,7 @@ static int fr_rx(struct sk_buff *skb)
 		}
 
 		printk(KERN_INFO "%s: Received non-LMI frame with LMI DLCI\n",
-		       hdlc_to_name(hdlc));
+		       ndev->name);
 		goto rx_error;
 	}
 
@@ -839,7 +846,7 @@ static int fr_rx(struct sk_buff *skb)
 	if (!pvc) {
 #ifdef DEBUG_PKT
 		printk(KERN_INFO "%s: No PVC for received frame's DLCI %d\n",
-		       hdlc_to_name(hdlc), dlci);
+		       ndev->name, dlci);
 #endif
 		dev_kfree_skb_any(skb);
 		return NET_RX_DROP;
@@ -847,7 +854,7 @@ static int fr_rx(struct sk_buff *skb)
 
 	if (pvc->state.fecn != fh->fecn) {
 #ifdef DEBUG_ECN
-		printk(KERN_DEBUG "%s: DLCI %d FECN O%s\n", hdlc_to_name(pvc),
+		printk(KERN_DEBUG "%s: DLCI %d FECN O%s\n", ndev->name,
 		       dlci, fh->fecn ? "N" : "FF");
 #endif
 		pvc->state.fecn ^= 1;
@@ -855,7 +862,7 @@ static int fr_rx(struct sk_buff *skb)
 
 	if (pvc->state.becn != fh->becn) {
 #ifdef DEBUG_ECN
-		printk(KERN_DEBUG "%s: DLCI %d BECN O%s\n", hdlc_to_name(pvc),
+		printk(KERN_DEBUG "%s: DLCI %d BECN O%s\n", ndev->name,
 		       dlci, fh->becn ? "N" : "FF");
 #endif
 		pvc->state.becn ^= 1;
@@ -899,13 +906,13 @@ static int fr_rx(struct sk_buff *skb)
 
 		default:
 			printk(KERN_INFO "%s: Unsupported protocol, OUI=%x "
-			       "PID=%x\n", hdlc_to_name(hdlc), oui, pid);
+			       "PID=%x\n", ndev->name, oui, pid);
 			dev_kfree_skb_any(skb);
 			return NET_RX_DROP;
 		}
 	} else {
 		printk(KERN_INFO "%s: Unsupported protocol, NLPID=%x "
-		       "length = %i\n", hdlc_to_name(hdlc), data[3], skb->len);
+		       "length = %i\n", ndev->name, data[3], skb->len);
 		dev_kfree_skb_any(skb);
 		return NET_RX_DROP;
 	}
@@ -932,14 +939,15 @@ static int fr_rx(struct sk_buff *skb)
 
 
 
-static void fr_start(hdlc_device *hdlc)
+static void fr_start(struct net_device *dev)
 {
+	hdlc_device *hdlc = dev_to_hdlc(dev);
 #ifdef DEBUG_LINK
 	printk(KERN_DEBUG "fr_start\n");
 #endif
 	if (hdlc->state.fr.settings.lmi != LMI_NONE) {
-		if (netif_carrier_ok(&hdlc->netdev))
-			netif_carrier_off(&hdlc->netdev);
+		if (netif_carrier_ok(dev))
+			netif_carrier_off(dev);
 		hdlc->state.fr.last_poll = 0;
 		hdlc->state.fr.reliable = 0;
 		hdlc->state.fr.dce_changed = 1;
@@ -953,28 +961,30 @@ static void fr_start(hdlc_device *hdlc)
 		/* First poll after 1 s */
 		hdlc->state.fr.timer.expires = jiffies + HZ;
 		hdlc->state.fr.timer.function = fr_timer;
-		hdlc->state.fr.timer.data = (unsigned long)hdlc;
+		hdlc->state.fr.timer.data = (unsigned long)dev;
 		add_timer(&hdlc->state.fr.timer);
 	} else
-		fr_set_link_state(1, hdlc);
+		fr_set_link_state(1, dev);
 }
 
 
 
-static void fr_stop(hdlc_device *hdlc)
+static void fr_stop(struct net_device *dev)
 {
+	hdlc_device *hdlc = dev_to_hdlc(dev);
 #ifdef DEBUG_LINK
 	printk(KERN_DEBUG "fr_stop\n");
 #endif
 	if (hdlc->state.fr.settings.lmi != LMI_NONE)
 		del_timer_sync(&hdlc->state.fr.timer);
-	fr_set_link_state(0, hdlc);
+	fr_set_link_state(0, dev);
 }
 
 
 
-static void fr_close(hdlc_device *hdlc)
+static void fr_close(struct net_device *dev)
 {
+	hdlc_device *hdlc = dev_to_hdlc(dev);
 	pvc_device *pvc = hdlc->state.fr.first_pvc;
 
 	while (pvc) {		/* Shutdown all PVCs for this FRAD */
@@ -986,10 +996,17 @@ static void fr_close(hdlc_device *hdlc)
 	}
 }
 
+static void dlci_setup(struct net_device *dev)
+{
+	dev->type = ARPHRD_DLCI;
+	dev->flags = IFF_POINTOPOINT;
+	dev->hard_header_len = 10;
+	dev->addr_len = 2;
+}
 
-
-static int fr_add_pvc(hdlc_device *hdlc, unsigned int dlci, int type)
+static int fr_add_pvc(struct net_device *master, unsigned int dlci, int type)
 {
+	hdlc_device *hdlc = dev_to_hdlc(master);
 	pvc_device *pvc = NULL;
 	struct net_device *dev;
 	int result, used;
@@ -998,9 +1015,9 @@ static int fr_add_pvc(hdlc_device *hdlc,
 	if (type == ARPHRD_ETHER)
 		prefix = "pvceth%d";
 
-	if ((pvc = add_pvc(hdlc, dlci)) == NULL) {
+	if ((pvc = add_pvc(master, dlci)) == NULL) {
 		printk(KERN_WARNING "%s: Memory squeeze on fr_add_pvc()\n",
-		       hdlc_to_name(hdlc));
+		       master->name);
 		return -ENOBUFS;
 	}
 
@@ -1009,26 +1026,24 @@ static int fr_add_pvc(hdlc_device *hdlc,
 
 	used = pvc_is_used(pvc);
 
-	dev = kmalloc(sizeof(struct net_device) +
-		      sizeof(struct net_device_stats), GFP_KERNEL);
+	if (type == ARPHRD_ETHER)
+		dev = alloc_netdev(sizeof(struct net_device_stats),
+				   "pvceth%d", ether_setup);
+	else
+		dev = alloc_netdev(sizeof(struct net_device_stats),
+				   "pvc%d", dlci_setup);
+
 	if (!dev) {
 		printk(KERN_WARNING "%s: Memory squeeze on fr_pvc()\n",
-		       hdlc_to_name(hdlc));
+		       master->name);
 		delete_unused_pvcs(hdlc);
 		return -ENOBUFS;
 	}
-	memset(dev, 0, sizeof(struct net_device) +
-	       sizeof(struct net_device_stats));
 
 	if (type == ARPHRD_ETHER) {
-		ether_setup(dev);
 		memcpy(dev->dev_addr, "\x00\x01", 2);
                 get_random_bytes(dev->dev_addr + 2, ETH_ALEN - 2);
 	} else {
-		dev->type = ARPHRD_DLCI;
-		dev->flags = IFF_POINTOPOINT;
-		dev->hard_header_len = 10;
-		dev->addr_len = 2;
 		*(u16*)dev->dev_addr = htons(dlci);
 		dlci_to_q922(dev->broadcast, dlci);
 	}
@@ -1042,15 +1057,15 @@ static int fr_add_pvc(hdlc_device *hdlc,
 	dev->tx_queue_len = 0;
 	dev->priv = pvc;
 
-	result = dev_alloc_name(dev, prefix);
+	result = dev_alloc_name(dev, dev->name);
 	if (result < 0) {
-		kfree(dev);
+		free_netdev(dev);
 		delete_unused_pvcs(hdlc);
 		return result;
 	}
 
 	if (register_netdevice(dev) != 0) {
-		kfree(dev);
+		free_netdev(dev);
 		delete_unused_pvcs(hdlc);
 		return -EIO;
 	}
@@ -1080,7 +1095,7 @@ static int fr_del_pvc(hdlc_device *hdlc,
 	if (dev->flags & IFF_UP)
 		return -EBUSY;		/* PVC in use */
 
-	unregister_netdevice(dev); /* the destructor will kfree(dev) */
+	unregister_netdevice(dev); /* the destructor will free_netdev(dev) */
 	*get_dev_p(pvc, type) = NULL;
 
 	if (!pvc_is_used(pvc)) {
@@ -1104,7 +1119,8 @@ static void fr_destroy(hdlc_device *hdlc
 
 	while (pvc) {
 		pvc_device *next = pvc->next;
-		if (pvc->main)	/* the destructor will kfree(main + ether) */
+		/* destructors will free_netdev() main and ether */
+		if (pvc->main)
 			unregister_netdevice(pvc->main);
 
 		if (pvc->ether)
@@ -1117,12 +1133,12 @@ static void fr_destroy(hdlc_device *hdlc
 
 
 
-int hdlc_fr_ioctl(hdlc_device *hdlc, struct ifreq *ifr)
+int hdlc_fr_ioctl(struct net_device *dev, struct ifreq *ifr)
 {
 	fr_proto *fr_s = ifr->ifr_settings.ifs_ifsu.fr;
 	const size_t size = sizeof(fr_proto);
 	fr_proto new_settings;
-	struct net_device *dev = hdlc_to_dev(hdlc);
+	hdlc_device *hdlc = dev_to_hdlc(dev);
 	fr_proto_pvc pvc;
 	int result;
 
@@ -1163,7 +1179,7 @@ int hdlc_fr_ioctl(hdlc_device *hdlc, str
 		     new_settings.dce != 1))
 			return -EINVAL;
 
-		result=hdlc->attach(hdlc, ENCODING_NRZ,PARITY_CRC16_PR1_CCITT);
+		result=hdlc->attach(dev, ENCODING_NRZ,PARITY_CRC16_PR1_CCITT);
 		if (result)
 			return result;
 
@@ -1210,7 +1226,7 @@ int hdlc_fr_ioctl(hdlc_device *hdlc, str
 
 		if (ifr->ifr_settings.type == IF_PROTO_FR_ADD_PVC ||
 		    ifr->ifr_settings.type == IF_PROTO_FR_ADD_ETH_PVC)
-			return fr_add_pvc(hdlc, pvc.dlci, result);
+			return fr_add_pvc(dev, pvc.dlci, result);
 		else
 			return fr_del_pvc(hdlc, pvc.dlci, result);
 	}
--- diff/drivers/net/wan/hdlc_generic.c	2003-10-09 09:47:34.000000000 +0100
+++ source/drivers/net/wan/hdlc_generic.c	2004-02-23 13:56:44.000000000 +0000
@@ -50,7 +50,7 @@ static int hdlc_change_mtu(struct net_de
 
 static struct net_device_stats *hdlc_get_stats(struct net_device *dev)
 {
-	return &dev_to_hdlc(dev)->stats;
+	return hdlc_stats(dev);
 }
 
 
@@ -69,8 +69,9 @@ static int hdlc_rcv(struct sk_buff *skb,
 
 
 
-void hdlc_set_carrier(int on, hdlc_device *hdlc)
+void hdlc_set_carrier(int on, struct net_device *dev)
 {
+	hdlc_device *hdlc = dev_to_hdlc(dev);
 	on = on ? 1 : 0;
 
 #ifdef DEBUG_LINK
@@ -82,7 +83,7 @@ void hdlc_set_carrier(int on, hdlc_devic
 	if (hdlc->carrier == on)
 		goto carrier_exit; /* no change in DCD line level */
 
-	printk(KERN_INFO "%s: carrier %s\n", hdlc_to_name(hdlc),
+	printk(KERN_INFO "%s: carrier %s\n", dev->name,
 	       on ? "ON" : "off");
 	hdlc->carrier = on;
 
@@ -91,15 +92,15 @@ void hdlc_set_carrier(int on, hdlc_devic
 
 	if (hdlc->carrier) {
 		if (hdlc->proto.start)
-			hdlc->proto.start(hdlc);
-		else if (!netif_carrier_ok(&hdlc->netdev))
-			netif_carrier_on(&hdlc->netdev);
+			hdlc->proto.start(dev);
+		else if (!netif_carrier_ok(dev))
+			netif_carrier_on(dev);
 
 	} else { /* no carrier */
 		if (hdlc->proto.stop)
-			hdlc->proto.stop(hdlc);
-		else if (netif_carrier_ok(&hdlc->netdev))
-			netif_carrier_off(&hdlc->netdev);
+			hdlc->proto.stop(dev);
+		else if (netif_carrier_ok(dev))
+			netif_carrier_off(dev);
 	}
 
  carrier_exit:
@@ -108,8 +109,9 @@ void hdlc_set_carrier(int on, hdlc_devic
 
 
 /* Must be called by hardware driver when HDLC device is being opened */
-int hdlc_open(hdlc_device *hdlc)
+int hdlc_open(struct net_device *dev)
 {
+	hdlc_device *hdlc = dev_to_hdlc(dev);
 #ifdef DEBUG_LINK
 	printk(KERN_DEBUG "hdlc_open carrier %i open %i\n",
 	       hdlc->carrier, hdlc->open);
@@ -119,7 +121,7 @@ int hdlc_open(hdlc_device *hdlc)
 		return -ENOSYS;	/* no protocol attached */
 
 	if (hdlc->proto.open) {
-		int result = hdlc->proto.open(hdlc);
+		int result = hdlc->proto.open(dev);
 		if (result)
 			return result;
 	}
@@ -128,12 +130,12 @@ int hdlc_open(hdlc_device *hdlc)
 
 	if (hdlc->carrier) {
 		if (hdlc->proto.start)
-			hdlc->proto.start(hdlc);
-		else if (!netif_carrier_ok(&hdlc->netdev))
-			netif_carrier_on(&hdlc->netdev);
+			hdlc->proto.start(dev);
+		else if (!netif_carrier_ok(dev))
+			netif_carrier_on(dev);
 
-	} else if (netif_carrier_ok(&hdlc->netdev))
-		netif_carrier_off(&hdlc->netdev);
+	} else if (netif_carrier_ok(dev))
+		netif_carrier_off(dev);
 
 	hdlc->open = 1;
 
@@ -144,8 +146,9 @@ int hdlc_open(hdlc_device *hdlc)
 
 
 /* Must be called by hardware driver when HDLC device is being closed */
-void hdlc_close(hdlc_device *hdlc)
+void hdlc_close(struct net_device *dev)
 {
+	hdlc_device *hdlc = dev_to_hdlc(dev);
 #ifdef DEBUG_LINK
 	printk(KERN_DEBUG "hdlc_close carrier %i open %i\n",
 	       hdlc->carrier, hdlc->open);
@@ -155,38 +158,38 @@ void hdlc_close(hdlc_device *hdlc)
 
 	hdlc->open = 0;
 	if (hdlc->carrier && hdlc->proto.stop)
-		hdlc->proto.stop(hdlc);
+		hdlc->proto.stop(dev);
 
 	spin_unlock_irq(&hdlc->state_lock);
 
 	if (hdlc->proto.close)
-		hdlc->proto.close(hdlc);
+		hdlc->proto.close(dev);
 }
 
 
 
 #ifndef CONFIG_HDLC_RAW
-#define hdlc_raw_ioctl(hdlc, ifr)	-ENOSYS
+#define hdlc_raw_ioctl(dev, ifr)	-ENOSYS
 #endif
 
 #ifndef CONFIG_HDLC_RAW_ETH
-#define hdlc_raw_eth_ioctl(hdlc, ifr)	-ENOSYS
+#define hdlc_raw_eth_ioctl(dev, ifr)	-ENOSYS
 #endif
 
 #ifndef CONFIG_HDLC_PPP
-#define hdlc_ppp_ioctl(hdlc, ifr)	-ENOSYS
+#define hdlc_ppp_ioctl(dev, ifr)	-ENOSYS
 #endif
 
 #ifndef CONFIG_HDLC_CISCO
-#define hdlc_cisco_ioctl(hdlc, ifr)	-ENOSYS
+#define hdlc_cisco_ioctl(dev, ifr)	-ENOSYS
 #endif
 
 #ifndef CONFIG_HDLC_FR
-#define hdlc_fr_ioctl(hdlc, ifr)	-ENOSYS
+#define hdlc_fr_ioctl(dev, ifr)	-ENOSYS
 #endif
 
 #ifndef CONFIG_HDLC_X25
-#define hdlc_x25_ioctl(hdlc, ifr)	-ENOSYS
+#define hdlc_x25_ioctl(dev, ifr)	-ENOSYS
 #endif
 
 
@@ -213,22 +216,49 @@ int hdlc_ioctl(struct net_device *dev, s
 	}
 
 	switch(proto) {
-	case IF_PROTO_HDLC:	return hdlc_raw_ioctl(hdlc, ifr);
-	case IF_PROTO_HDLC_ETH:	return hdlc_raw_eth_ioctl(hdlc, ifr);
-	case IF_PROTO_PPP:	return hdlc_ppp_ioctl(hdlc, ifr);
-	case IF_PROTO_CISCO:	return hdlc_cisco_ioctl(hdlc, ifr);
-	case IF_PROTO_FR:	return hdlc_fr_ioctl(hdlc, ifr);
-	case IF_PROTO_X25:	return hdlc_x25_ioctl(hdlc, ifr);
+	case IF_PROTO_HDLC:	return hdlc_raw_ioctl(dev, ifr);
+	case IF_PROTO_HDLC_ETH:	return hdlc_raw_eth_ioctl(dev, ifr);
+	case IF_PROTO_PPP:	return hdlc_ppp_ioctl(dev, ifr);
+	case IF_PROTO_CISCO:	return hdlc_cisco_ioctl(dev, ifr);
+	case IF_PROTO_FR:	return hdlc_fr_ioctl(dev, ifr);
+	case IF_PROTO_X25:	return hdlc_x25_ioctl(dev, ifr);
 	default:		return -EINVAL;
 	}
 }
 
+static void hdlc_setup(struct net_device *dev)
+{
+	hdlc_device *hdlc = dev_to_hdlc(dev);
+
+	dev->get_stats = hdlc_get_stats;
+	dev->change_mtu = hdlc_change_mtu;
+	dev->mtu = HDLC_MAX_MTU;
+
+	dev->type = ARPHRD_RAWHDLC;
+	dev->hard_header_len = 16;
+
+	dev->flags = IFF_POINTOPOINT | IFF_NOARP;
+
+	hdlc->proto.id = -1;
+	hdlc->proto.detach = NULL;
+	hdlc->carrier = 1;
+	hdlc->open = 0;
+	spin_lock_init(&hdlc->state_lock);
+}
 
+struct net_device *alloc_hdlcdev(void *priv)
+{
+	struct net_device *dev;
+	dev = alloc_netdev(sizeof(hdlc_device), "hdlc%d", hdlc_setup);
+	if (dev)
+		dev_to_hdlc(dev)->priv = priv;
+	return dev;
+}
 
-int register_hdlc_device(hdlc_device *hdlc)
+int register_hdlc_device(struct net_device *dev)
 {
 	int result;
-	struct net_device *dev = hdlc_to_dev(hdlc);
+	hdlc_device *hdlc = dev_to_hdlc(dev);
 
 	dev->get_stats = hdlc_get_stats;
 	dev->change_mtu = hdlc_change_mtu;
@@ -258,11 +288,11 @@ int register_hdlc_device(hdlc_device *hd
 
 
 
-void unregister_hdlc_device(hdlc_device *hdlc)
+void unregister_hdlc_device(struct net_device *dev)
 {
 	rtnl_lock();
-	hdlc_proto_detach(hdlc);
-	unregister_netdevice(hdlc_to_dev(hdlc));
+	hdlc_proto_detach(dev_to_hdlc(dev));
+	unregister_netdevice(dev);
 	rtnl_unlock();
 }
 
@@ -276,6 +306,7 @@ EXPORT_SYMBOL(hdlc_open);
 EXPORT_SYMBOL(hdlc_close);
 EXPORT_SYMBOL(hdlc_set_carrier);
 EXPORT_SYMBOL(hdlc_ioctl);
+EXPORT_SYMBOL(alloc_hdlcdev);
 EXPORT_SYMBOL(register_hdlc_device);
 EXPORT_SYMBOL(unregister_hdlc_device);
 
--- diff/drivers/net/wan/hdlc_ppp.c	2003-08-20 14:16:10.000000000 +0100
+++ source/drivers/net/wan/hdlc_ppp.c	2004-02-23 13:56:44.000000000 +0000
@@ -24,9 +24,9 @@
 #include <linux/hdlc.h>
 
 
-static int ppp_open(hdlc_device *hdlc)
+static int ppp_open(struct net_device *dev)
 {
-	struct net_device *dev = hdlc_to_dev(hdlc);
+	hdlc_device *hdlc = dev_to_hdlc(dev);
 	void *old_ioctl;
 	int result;
 
@@ -52,9 +52,9 @@ static int ppp_open(hdlc_device *hdlc)
 
 
 
-static void ppp_close(hdlc_device *hdlc)
+static void ppp_close(struct net_device *dev)
 {
-	struct net_device *dev = hdlc_to_dev(hdlc);
+	hdlc_device *hdlc = dev_to_hdlc(dev);
 
 	sppp_close(dev);
 	sppp_detach(dev);
@@ -74,9 +74,9 @@ static unsigned short ppp_type_trans(str
 
 
 
-int hdlc_ppp_ioctl(hdlc_device *hdlc, struct ifreq *ifr)
+int hdlc_ppp_ioctl(struct net_device *dev, struct ifreq *ifr)
 {
-	struct net_device *dev = hdlc_to_dev(hdlc);
+	hdlc_device *hdlc = dev_to_hdlc(dev);
 	int result;
 
 	switch (ifr->ifr_settings.type) {
@@ -93,7 +93,7 @@ int hdlc_ppp_ioctl(hdlc_device *hdlc, st
 
 		/* no settable parameters */
 
-		result=hdlc->attach(hdlc, ENCODING_NRZ,PARITY_CRC16_PR1_CCITT);
+		result=hdlc->attach(dev, ENCODING_NRZ,PARITY_CRC16_PR1_CCITT);
 		if (result)
 			return result;
 
--- diff/drivers/net/wan/hdlc_raw.c	2003-08-20 14:16:10.000000000 +0100
+++ source/drivers/net/wan/hdlc_raw.c	2004-02-23 13:56:44.000000000 +0000
@@ -32,12 +32,12 @@ static unsigned short raw_type_trans(str
 
 
 
-int hdlc_raw_ioctl(hdlc_device *hdlc, struct ifreq *ifr)
+int hdlc_raw_ioctl(struct net_device *dev, struct ifreq *ifr)
 {
 	raw_hdlc_proto *raw_s = ifr->ifr_settings.ifs_ifsu.raw_hdlc;
 	const size_t size = sizeof(raw_hdlc_proto);
 	raw_hdlc_proto new_settings;
-	struct net_device *dev = hdlc_to_dev(hdlc);
+	hdlc_device *hdlc = dev_to_hdlc(dev);
 	int result;
 
 	switch (ifr->ifr_settings.type) {
@@ -67,7 +67,7 @@ int hdlc_raw_ioctl(hdlc_device *hdlc, st
 		if (new_settings.parity == PARITY_DEFAULT)
 			new_settings.parity = PARITY_CRC16_PR1_CCITT;
 
-		result = hdlc->attach(hdlc, new_settings.encoding,
+		result = hdlc->attach(dev, new_settings.encoding,
 				      new_settings.parity);
 		if (result)
 			return result;
--- diff/drivers/net/wan/hdlc_raw_eth.c	2003-08-20 14:16:10.000000000 +0100
+++ source/drivers/net/wan/hdlc_raw_eth.c	2004-02-23 13:56:44.000000000 +0000
@@ -33,7 +33,7 @@ static int eth_tx(struct sk_buff *skb, s
 		int len = skb->len;
 		if (skb_tailroom(skb) < pad)
 			if (pskb_expand_head(skb, 0, pad, GFP_ATOMIC)) {
-				dev_to_hdlc(dev)->stats.tx_dropped++;
+				hdlc_stats(dev)->tx_dropped++;
 				dev_kfree_skb(skb);
 				return 0;
 			}
@@ -44,12 +44,12 @@ static int eth_tx(struct sk_buff *skb, s
 }
 
 
-int hdlc_raw_eth_ioctl(hdlc_device *hdlc, struct ifreq *ifr)
+int hdlc_raw_eth_ioctl(struct net_device *dev, struct ifreq *ifr)
 {
 	raw_hdlc_proto *raw_s = ifr->ifr_settings.ifs_ifsu.raw_hdlc;
 	const size_t size = sizeof(raw_hdlc_proto);
 	raw_hdlc_proto new_settings;
-	struct net_device *dev = hdlc_to_dev(hdlc);
+	hdlc_device *hdlc = dev_to_hdlc(dev);
 	int result;
 	void *old_ch_mtu;
 	int old_qlen;
@@ -81,7 +81,7 @@ int hdlc_raw_eth_ioctl(hdlc_device *hdlc
 		if (new_settings.parity == PARITY_DEFAULT)
 			new_settings.parity = PARITY_CRC16_PR1_CCITT;
 
-		result = hdlc->attach(hdlc, new_settings.encoding,
+		result = hdlc->attach(dev, new_settings.encoding,
 				      new_settings.parity);
 		if (result)
 			return result;
--- diff/drivers/net/wan/hdlc_x25.c	2003-10-09 09:47:34.000000000 +0100
+++ source/drivers/net/wan/hdlc_x25.c	2004-02-23 13:56:44.000000000 +0000
@@ -25,21 +25,20 @@
 
 /* These functions are callbacks called by LAPB layer */
 
-static void x25_connect_disconnect(void *token, int reason, int code)
+static void x25_connect_disconnect(struct net_device *dev, int reason, int code)
 {
-	hdlc_device *hdlc = token;
 	struct sk_buff *skb;
 	unsigned char *ptr;
 
 	if ((skb = dev_alloc_skb(1)) == NULL) {
-		printk(KERN_ERR "%s: out of memory\n", hdlc_to_name(hdlc));
+		printk(KERN_ERR "%s: out of memory\n", dev->name);
 		return;
 	}
 
 	ptr = skb_put(skb, 1);
 	*ptr = code;
 
-	skb->dev = hdlc_to_dev(hdlc);
+	skb->dev = dev;
 	skb->protocol = htons(ETH_P_X25);
 	skb->mac.raw = skb->data;
 	skb->pkt_type = PACKET_HOST;
@@ -49,23 +48,22 @@ static void x25_connect_disconnect(void 
 
 
 
-static void x25_connected(void *token, int reason)
+static void x25_connected(struct net_device *dev, int reason)
 {
-	x25_connect_disconnect(token, reason, 1);
+	x25_connect_disconnect(dev, reason, 1);
 }
 
 
 
-static void x25_disconnected(void *token, int reason)
+static void x25_disconnected(struct net_device *dev, int reason)
 {
-	x25_connect_disconnect(token, reason, 2);
+	x25_connect_disconnect(dev, reason, 2);
 }
 
 
 
-static int x25_data_indication(void *token, struct sk_buff *skb)
+static int x25_data_indication(struct net_device *dev, struct sk_buff *skb)
 {
-	hdlc_device *hdlc = token;
 	unsigned char *ptr;
 
 	skb_push(skb, 1);
@@ -76,7 +74,7 @@ static int x25_data_indication(void *tok
 	ptr  = skb->data;
 	*ptr = 0;
 
-	skb->dev = hdlc_to_dev(hdlc);
+	skb->dev = dev;
 	skb->protocol = htons(ETH_P_X25);
 	skb->mac.raw = skb->data;
 	skb->pkt_type = PACKET_HOST;
@@ -86,17 +84,16 @@ static int x25_data_indication(void *tok
 
 
 
-static void x25_data_transmit(void *token, struct sk_buff *skb)
+static void x25_data_transmit(struct net_device *dev, struct sk_buff *skb)
 {
-	hdlc_device *hdlc = token;
-	hdlc->xmit(skb, hdlc_to_dev(hdlc)); /* Ignore return value :-( */
+	hdlc_device *hdlc = dev_to_hdlc(dev);
+	hdlc->xmit(skb, dev); /* Ignore return value :-( */
 }
 
 
 
 static int x25_xmit(struct sk_buff *skb, struct net_device *dev)
 {
-	hdlc_device *hdlc = dev_to_hdlc(dev);
 	int result;
 
 
@@ -104,31 +101,31 @@ static int x25_xmit(struct sk_buff *skb,
 	switch (skb->data[0]) {
 	case 0:		/* Data to be transmitted */
 		skb_pull(skb, 1);
-		if ((result = lapb_data_request(hdlc, skb)) != LAPB_OK)
+		if ((result = lapb_data_request(dev, skb)) != LAPB_OK)
 			dev_kfree_skb(skb);
 		return 0;
 
 	case 1:
-		if ((result = lapb_connect_request(hdlc))!= LAPB_OK) {
+		if ((result = lapb_connect_request(dev))!= LAPB_OK) {
 			if (result == LAPB_CONNECTED)
 				/* Send connect confirm. msg to level 3 */
-				x25_connected(hdlc, 0);
+				x25_connected(dev, 0);
 			else
 				printk(KERN_ERR "%s: LAPB connect request "
 				       "failed, error code = %i\n",
-				       hdlc_to_name(hdlc), result);
+				       dev->name, result);
 		}
 		break;
 
 	case 2:
-		if ((result = lapb_disconnect_request(hdlc)) != LAPB_OK) {
+		if ((result = lapb_disconnect_request(dev)) != LAPB_OK) {
 			if (result == LAPB_NOTCONNECTED)
 				/* Send disconnect confirm. msg to level 3 */
-				x25_disconnected(hdlc, 0);
+				x25_disconnected(dev, 0);
 			else
 				printk(KERN_ERR "%s: LAPB disconnect request "
 				       "failed, error code = %i\n",
-				       hdlc_to_name(hdlc), result);
+				       dev->name, result);
 		}
 		break;
 
@@ -142,7 +139,7 @@ static int x25_xmit(struct sk_buff *skb,
 
 
 
-static int x25_open(hdlc_device *hdlc)
+static int x25_open(struct net_device *dev)
 {
 	struct lapb_register_struct cb;
 	int result;
@@ -154,7 +151,7 @@ static int x25_open(hdlc_device *hdlc)
 	cb.data_indication = x25_data_indication;
 	cb.data_transmit = x25_data_transmit;
 
-	result = lapb_register(hdlc, &cb);
+	result = lapb_register(dev, &cb);
 	if (result != LAPB_OK)
 		return result;
 	return 0;
@@ -162,9 +159,9 @@ static int x25_open(hdlc_device *hdlc)
 
 
 
-static void x25_close(hdlc_device *hdlc)
+static void x25_close(struct net_device *dev)
 {
-	lapb_unregister(hdlc);
+	lapb_unregister(dev);
 }
 
 
@@ -178,7 +175,7 @@ static int x25_rx(struct sk_buff *skb)
 		return NET_RX_DROP;
 	}
 
-	if (lapb_data_received(hdlc, skb) == LAPB_OK)
+	if (lapb_data_received(skb->dev, skb) == LAPB_OK)
 		return NET_RX_SUCCESS;
 
 	hdlc->stats.rx_errors++;
@@ -188,9 +185,9 @@ static int x25_rx(struct sk_buff *skb)
 
 
 
-int hdlc_x25_ioctl(hdlc_device *hdlc, struct ifreq *ifr)
+int hdlc_x25_ioctl(struct net_device *dev, struct ifreq *ifr)
 {
-	struct net_device *dev = hdlc_to_dev(hdlc);
+	hdlc_device *hdlc = dev_to_hdlc(dev);
 	int result;
 
 	switch (ifr->ifr_settings.type) {
@@ -205,7 +202,7 @@ int hdlc_x25_ioctl(hdlc_device *hdlc, st
 		if(dev->flags & IFF_UP)
 			return -EBUSY;
 
-		result=hdlc->attach(hdlc, ENCODING_NRZ,PARITY_CRC16_PR1_CCITT);
+		result=hdlc->attach(dev, ENCODING_NRZ,PARITY_CRC16_PR1_CCITT);
 		if (result)
 			return result;
 
--- diff/drivers/net/wan/hostess_sv11.c	2003-10-27 09:20:38.000000000 +0000
+++ source/drivers/net/wan/hostess_sv11.c	2004-02-23 13:56:44.000000000 +0000
@@ -122,7 +122,6 @@ static int hostess_open(struct net_devic
 	 */
 
 	netif_start_queue(d);
-	MOD_INC_USE_COUNT;
 	return 0;
 }
 
@@ -154,7 +153,6 @@ static int hostess_close(struct net_devi
 			z8530_sync_txdma_close(d, &sv11->sync.chanA);
 			break;
 	}
-	MOD_DEC_USE_COUNT;
 	return 0;
 }
 
@@ -203,6 +201,16 @@ static int hostess_neigh_setup_dev(struc
 	return 0;
 }
 
+static void sv11_setup(struct net_device *dev)
+{	
+	dev->open = hostess_open;
+	dev->stop = hostess_close;
+	dev->hard_start_xmit = hostess_queue_xmit;
+	dev->get_stats = hostess_get_stats;
+	dev->do_ioctl = hostess_ioctl;
+	dev->neigh_setup = hostess_neigh_setup_dev;
+}
+
 /*
  *	Description block for a Comtrol Hostess SV11 card
  */
@@ -229,10 +237,12 @@ static struct sv11_device *sv11_init(int
 	memset(sv, 0, sizeof(*sv));
 	sv->if_ptr=&sv->netdev;
 	
-	sv->netdev.dev=(struct net_device *)kmalloc(sizeof(struct net_device), GFP_KERNEL);
+	sv->netdev.dev = alloc_netdev(0, "hdlc%d", sv11_setup);
 	if(!sv->netdev.dev)
 		goto fail2;
 
+	SET_MODULE_OWNER(sv->netdev.dev);
+
 	dev=&sv->sync;
 	
 	/*
@@ -326,23 +336,14 @@ static struct sv11_device *sv11_init(int
 		d->base_addr = iobase;
 		d->irq = irq;
 		d->priv = sv;
-		d->init = NULL;
-		
-		d->open = hostess_open;
-		d->stop = hostess_close;
-		d->hard_start_xmit = hostess_queue_xmit;
-		d->get_stats = hostess_get_stats;
-		d->set_multicast_list = NULL;
-		d->do_ioctl = hostess_ioctl;
-		d->neigh_setup = hostess_neigh_setup_dev;
-		d->set_mac_address = NULL;
 		
 		if(register_netdev(d))
 		{
 			printk(KERN_ERR "%s: unable to register device.\n",
 				d->name);
-			goto fail;
-		}				
+			sppp_detach(d);
+			goto dmafail2;
+		}
 
 		z8530_describe(dev, "I/O", iobase);
 		dev->active=1;
@@ -357,7 +358,7 @@ dmafail:
 fail:
 	free_irq(irq, dev);
 fail1:
-	kfree(sv->netdev.dev);
+	free_netdev(sv->netdev.dev);
 fail2:
 	kfree(sv);
 fail3:
@@ -368,8 +369,8 @@ fail3:
 static void sv11_shutdown(struct sv11_device *dev)
 {
 	sppp_detach(dev->netdev.dev);
-	z8530_shutdown(&dev->sync);
 	unregister_netdev(dev->netdev.dev);
+	z8530_shutdown(&dev->sync);
 	free_irq(dev->sync.irq, dev);
 	if(dma)
 	{
@@ -378,6 +379,8 @@ static void sv11_shutdown(struct sv11_de
 		free_dma(dev->sync.chanA.txdma);
 	}
 	release_region(dev->sync.chanA.ctrlio-1, 8);
+	free_netdev(dev->netdev.dev);
+	kfree(dev);
 }
 
 #ifdef MODULE
--- diff/drivers/net/wan/lapbether.c	2004-02-09 10:36:11.000000000 +0000
+++ source/drivers/net/wan/lapbether.c	2004-02-23 13:56:44.000000000 +0000
@@ -110,7 +110,7 @@ static int lapbeth_rcv(struct sk_buff *s
 	skb_pull(skb, 2);	/* Remove the length bytes */
 	skb_trim(skb, len);	/* Set the length of the data */
 
-	if ((err = lapb_data_received(lapbeth, skb)) != LAPB_OK) {
+	if ((err = lapb_data_received(lapbeth->axdev, skb)) != LAPB_OK) {
 		printk(KERN_DEBUG "lapbether: lapb_data_received err - %d\n", err);
 		goto drop_unlock;
 	}
@@ -125,9 +125,8 @@ drop:
 	return 0;
 }
 
-static int lapbeth_data_indication(void *token, struct sk_buff *skb)
+static int lapbeth_data_indication(struct net_device *dev, struct sk_buff *skb)
 {
-	struct lapbethdev *lapbeth = (struct lapbethdev *)token;
 	unsigned char *ptr;
 
 	skb_push(skb, 1);
@@ -138,7 +137,7 @@ static int lapbeth_data_indication(void 
 	ptr  = skb->data;
 	*ptr = 0x00;
 
-	skb->dev      = lapbeth->axdev;
+	skb->dev      = dev;
 	skb->protocol = htons(ETH_P_X25);
 	skb->mac.raw  = skb->data;
 	skb->pkt_type = PACKET_HOST;
@@ -152,7 +151,6 @@ static int lapbeth_data_indication(void 
  */
 static int lapbeth_xmit(struct sk_buff *skb, struct net_device *dev)
 {
-	struct lapbethdev *lapbeth = (struct lapbethdev *)dev->priv;
 	int err = -ENODEV;
 
 	/*
@@ -168,12 +166,12 @@ static int lapbeth_xmit(struct sk_buff *
 		err = 0;
 		break;
 	case 0x01:
-		if ((err = lapb_connect_request(lapbeth)) != LAPB_OK)
+		if ((err = lapb_connect_request(dev)) != LAPB_OK)
 			printk(KERN_ERR "lapbeth: lapb_connect_request "
 			       "error: %d\n", err);
 		goto drop_ok;
 	case 0x02:
-		if ((err = lapb_disconnect_request(lapbeth)) != LAPB_OK)
+		if ((err = lapb_disconnect_request(dev)) != LAPB_OK)
 			printk(KERN_ERR "lapbeth: lapb_disconnect_request "
 			       "err: %d\n", err);
 		/* Fall thru */
@@ -183,7 +181,7 @@ static int lapbeth_xmit(struct sk_buff *
 
 	skb_pull(skb, 1);
 
-	if ((err = lapb_data_request(lapbeth, skb)) != LAPB_OK) {
+	if ((err = lapb_data_request(dev, skb)) != LAPB_OK) {
 		printk(KERN_ERR "lapbeth: lapb_data_request error - %d\n", err);
 		err = -ENOMEM;
 		goto drop;
@@ -198,9 +196,9 @@ drop:
 	goto out;
 }
 
-static void lapbeth_data_transmit(void *token, struct sk_buff *skb)
+static void lapbeth_data_transmit(struct net_device *ndev, struct sk_buff *skb)
 {
-	struct lapbethdev *lapbeth = (struct lapbethdev *)token;
+	struct lapbethdev *lapbeth = ndev->priv;
 	unsigned char *ptr;
 	struct net_device *dev;
 	int size = skb->len;
@@ -222,9 +220,8 @@ static void lapbeth_data_transmit(void *
 	dev_queue_xmit(skb);
 }
 
-static void lapbeth_connected(void *token, int reason)
+static void lapbeth_connected(struct net_device *dev, int reason)
 {
-	struct lapbethdev *lapbeth = (struct lapbethdev *)token;
 	unsigned char *ptr;
 	struct sk_buff *skb = dev_alloc_skb(1);
 
@@ -236,7 +233,7 @@ static void lapbeth_connected(void *toke
 	ptr  = skb_put(skb, 1);
 	*ptr = 0x01;
 
-	skb->dev      = lapbeth->axdev;
+	skb->dev      = dev;
 	skb->protocol = htons(ETH_P_X25);
 	skb->mac.raw  = skb->data;
 	skb->pkt_type = PACKET_HOST;
@@ -245,9 +242,8 @@ static void lapbeth_connected(void *toke
 	netif_rx(skb);
 }
 
-static void lapbeth_disconnected(void *token, int reason)
+static void lapbeth_disconnected(struct net_device *dev, int reason)
 {
-	struct lapbethdev *lapbeth = (struct lapbethdev *)token;
 	unsigned char *ptr;
 	struct sk_buff *skb = dev_alloc_skb(1);
 
@@ -259,7 +255,7 @@ static void lapbeth_disconnected(void *t
 	ptr  = skb_put(skb, 1);
 	*ptr = 0x02;
 
-	skb->dev      = lapbeth->axdev;
+	skb->dev      = dev;
 	skb->protocol = htons(ETH_P_X25);
 	skb->mac.raw  = skb->data;
 	skb->pkt_type = PACKET_HOST;
@@ -303,11 +299,9 @@ static struct lapb_register_struct lapbe
  */
 static int lapbeth_open(struct net_device *dev)
 {
-	struct lapbethdev *lapbeth;
 	int err;
 
-	lapbeth = (struct lapbethdev *)dev->priv;
-	if ((err = lapb_register(lapbeth, &lapbeth_callbacks)) != LAPB_OK) {
+	if ((err = lapb_register(dev, &lapbeth_callbacks)) != LAPB_OK) {
 		printk(KERN_ERR "lapbeth: lapb_register error - %d\n", err);
 		return -ENODEV;
 	}
@@ -318,12 +312,11 @@ static int lapbeth_open(struct net_devic
 
 static int lapbeth_close(struct net_device *dev)
 {
-	struct lapbethdev *lapbeth = (struct lapbethdev *)dev->priv;
 	int err;
 
 	netif_stop_queue(dev);
 
-	if ((err = lapb_unregister(lapbeth)) != LAPB_OK)
+	if ((err = lapb_unregister(dev)) != LAPB_OK)
 		printk(KERN_ERR "lapbeth: lapb_unregister error - %d\n", err);
 
 	return 0;
@@ -382,6 +375,7 @@ out:
 	return rc;
 fail:
 	dev_put(dev);
+	free_netdev(ndev);
 	kfree(lapbeth);
 	goto out;
 }
--- diff/drivers/net/wan/n2.c	2003-08-20 14:16:10.000000000 +0100
+++ source/drivers/net/wan/n2.c	2004-02-23 13:56:44.000000000 +0000
@@ -92,7 +92,7 @@ static char *hw = NULL;	/* pointer to hw
 
 
 typedef struct port_s {
-	hdlc_device hdlc;	/* HDLC device struct - must be first */
+	struct net_device *dev;
 	struct card_s *card;
 	spinlock_t lock;	/* TX lock */
 	sync_serial_settings settings;
@@ -215,13 +215,12 @@ static void n2_set_iface(port_t *port)
 
 static int n2_open(struct net_device *dev)
 {
-	hdlc_device *hdlc = dev_to_hdlc(dev);
-	port_t *port = hdlc_to_port(hdlc);
+	port_t *port = dev_to_port(dev);
 	int io = port->card->io;
 	u8 mcr = inb(io + N2_MCR) | (port->phy_node ? TX422_PORT1:TX422_PORT0);
 	int result;
 
-	result = hdlc_open(hdlc);
+	result = hdlc_open(dev);
 	if (result)
 		return result;
 
@@ -230,7 +229,7 @@ static int n2_open(struct net_device *de
 
 	outb(inb(io + N2_PCR) | PCR_ENWIN, io + N2_PCR); /* open window */
 	outb(inb(io + N2_PSR) | PSR_DMAEN, io + N2_PSR); /* enable dma */
-	sca_open(hdlc);
+	sca_open(dev);
 	n2_set_iface(port);
 	return 0;
 }
@@ -239,15 +238,14 @@ static int n2_open(struct net_device *de
 
 static int n2_close(struct net_device *dev)
 {
-	hdlc_device *hdlc = dev_to_hdlc(dev);
-	port_t *port = hdlc_to_port(hdlc);
+	port_t *port = dev_to_port(dev);
 	int io = port->card->io;
 	u8 mcr = inb(io+N2_MCR) | (port->phy_node ? TX422_PORT1 : TX422_PORT0);
 
-	sca_close(hdlc);
+	sca_close(dev);
 	mcr |= port->phy_node ? DTR_PORT1 : DTR_PORT0; /* set DTR OFF */
 	outb(mcr, io + N2_MCR);
-	hdlc_close(hdlc);
+	hdlc_close(dev);
 	return 0;
 }
 
@@ -257,12 +255,11 @@ static int n2_ioctl(struct net_device *d
 {
 	const size_t size = sizeof(sync_serial_settings);
 	sync_serial_settings new_line, *line = ifr->ifr_settings.ifs_ifsu.sync;
-	hdlc_device *hdlc = dev_to_hdlc(dev);
-	port_t *port = hdlc_to_port(hdlc);
+	port_t *port = dev_to_port(dev);
 
 #ifdef DEBUG_RINGS
 	if (cmd == SIOCDEVPRIVATE) {
-		sca_dump_rings(hdlc);
+		sca_dump_rings(dev);
 		return 0;
 	}
 #endif
@@ -312,8 +309,10 @@ static void n2_destroy_card(card_t *card
 	int cnt;
 
 	for (cnt = 0; cnt < 2; cnt++)
-		if (card->ports[cnt].card)
-			unregister_hdlc_device(&card->ports[cnt].hdlc);
+		if (card->ports[cnt].card) {
+			struct net_device *dev = port_to_dev(&card->ports[cnt]);
+			unregister_hdlc_device(dev);
+		}
 
 	if (card->irq)
 		free_irq(card->irq, card);
@@ -325,6 +324,10 @@ static void n2_destroy_card(card_t *card
 
 	if (card->io)
 		release_region(card->io, N2_IOPORTS);
+	if (card->ports[0].dev)
+		free_netdev(card->ports[0].dev);
+	if (card->ports[1].dev)
+		free_netdev(card->ports[1].dev);
 	kfree(card);
 }
 
@@ -359,6 +362,14 @@ static int __init n2_run(unsigned long i
 	}
 	memset(card, 0, sizeof(card_t));
 
+	card->ports[0].dev = alloc_hdlcdev(&card->ports[0]);
+	card->ports[1].dev = alloc_hdlcdev(&card->ports[1]);
+	if (!card->ports[0].dev || !card->ports[1].dev) {
+		printk(KERN_ERR "n2: unable to allocate memory\n");
+		n2_destroy_card(card);
+		return -ENOMEM;
+	}
+
 	if (!request_region(io, N2_IOPORTS, devname)) {
 		printk(KERN_ERR "n2: I/O port region in use\n");
 		n2_destroy_card(card);
@@ -435,7 +446,8 @@ static int __init n2_run(unsigned long i
 	sca_init(card, 0);
 	for (cnt = 0; cnt < 2; cnt++) {
 		port_t *port = &card->ports[cnt];
-		struct net_device *dev = hdlc_to_dev(&port->hdlc);
+		struct net_device *dev = port_to_dev(port);
+		hdlc_device *hdlc = dev_to_hdlc(dev);
 
 		if ((cnt == 0 && !valid0) || (cnt == 1 && !valid1))
 			continue;
@@ -455,21 +467,22 @@ static int __init n2_run(unsigned long i
 		dev->do_ioctl = n2_ioctl;
 		dev->open = n2_open;
 		dev->stop = n2_close;
-		port->hdlc.attach = sca_attach;
-		port->hdlc.xmit = sca_xmit;
+		hdlc->attach = sca_attach;
+		hdlc->xmit = sca_xmit;
 		port->settings.clock_type = CLOCK_EXT;
+		port->card = card;
 
-		if (register_hdlc_device(&port->hdlc)) {
+		if (register_hdlc_device(dev)) {
 			printk(KERN_WARNING "n2: unable to register hdlc "
 			       "device\n");
+			port->card = NULL;
 			n2_destroy_card(card);
 			return -ENOBUFS;
 		}
-		port->card = card;
 		sca_init_sync_port(port); /* Set up SCA memory */
 
 		printk(KERN_INFO "%s: RISCom/N2 node %d\n",
-		       hdlc_to_name(&port->hdlc), port->phy_node);
+		       dev->name, port->phy_node);
 	}
 
 	*new_card = card;
--- diff/drivers/net/wan/pc300.h	2002-10-16 04:27:49.000000000 +0100
+++ source/drivers/net/wan/pc300.h	2004-02-23 13:56:44.000000000 +0000
@@ -331,7 +331,7 @@ typedef struct pc300dev {
 	uclong line_off;
 #ifdef __KERNEL__
 	char name[16];
-	hdlc_device *hdlc;
+	struct net_device *dev;
 
 	void *private;
 	struct sk_buff *tx_skb;
@@ -483,7 +483,7 @@ void rx_dma_start(pc300_t *, int);
 void tx_dma_stop(pc300_t *, int);
 void rx_dma_stop(pc300_t *, int);
 int cpc_queue_xmit(struct sk_buff *, struct net_device *);
-void cpc_net_rx(hdlc_device *);
+void cpc_net_rx(struct net_device *);
 void cpc_sca_status(pc300_t *, int);
 int cpc_change_mtu(struct net_device *, int);
 int cpc_ioctl(struct net_device *, struct ifreq *, int);
--- diff/drivers/net/wan/pc300_drv.c	2004-02-09 10:36:11.000000000 +0000
+++ source/drivers/net/wan/pc300_drv.c	2004-02-23 13:56:44.000000000 +0000
@@ -290,7 +290,7 @@ static int clock_rate_calc(uclong, uclon
 static uclong detect_ram(pc300_t *);
 static void plx_init(pc300_t *);
 static void cpc_trace(struct net_device *, struct sk_buff *, char);
-static int cpc_attach(hdlc_device *, unsigned short, unsigned short);
+static int cpc_attach(struct net_device *, unsigned short, unsigned short);
 
 #ifdef CONFIG_PC300_MLPPP
 void cpc_tty_init(pc300dev_t * dev);
@@ -1774,7 +1774,7 @@ void cpc_tx_timeout(struct net_device *d
 	pc300dev_t *d = (pc300dev_t *) dev->priv;
 	pc300ch_t *chan = (pc300ch_t *) d->chan;
 	pc300_t *card = (pc300_t *) chan->card;
-	struct net_device_stats *stats = &d->hdlc->stats;
+	struct net_device_stats *stats = hdlc_stats(dev);
 	int ch = chan->channel;
 	uclong flags;
 	ucchar ilar;
@@ -1802,7 +1802,7 @@ int cpc_queue_xmit(struct sk_buff *skb, 
 	pc300dev_t *d = (pc300dev_t *) dev->priv;
 	pc300ch_t *chan = (pc300ch_t *) d->chan;
 	pc300_t *card = (pc300_t *) chan->card;
-	struct net_device_stats *stats = &d->hdlc->stats;
+	struct net_device_stats *stats = hdlc_stats(dev);
 	int ch = chan->channel;
 	uclong flags;
 #ifdef PC300_DEBUG_TX
@@ -1880,13 +1880,12 @@ int cpc_queue_xmit(struct sk_buff *skb, 
 	return 0;
 }
 
-void cpc_net_rx(hdlc_device * hdlc)
+void cpc_net_rx(struct net_device *dev)
 {
-	struct net_device *dev = hdlc_to_dev(hdlc);
 	pc300dev_t *d = (pc300dev_t *) dev->priv;
 	pc300ch_t *chan = (pc300ch_t *) d->chan;
 	pc300_t *card = (pc300_t *) chan->card;
-	struct net_device_stats *stats = &d->hdlc->stats;
+	struct net_device_stats *stats = hdlc_stats(dev);
 	int ch = chan->channel;
 #ifdef PC300_DEBUG_RX
 	int i;
@@ -1975,7 +1974,7 @@ static void sca_tx_intr(pc300dev_t *dev)
 	pc300_t *card = (pc300_t *)chan->card; 
 	int ch = chan->channel; 
 	volatile pcsca_bd_t * ptdescr; 
-	struct net_device_stats *stats = &dev->hdlc->stats; 
+	struct net_device_stats *stats = hdlc_stats(dev->dev);
 
     /* Clean up descriptors from previous transmission */
 	ptdescr = (pcsca_bd_t *)(card->hw.rambase +
@@ -1999,7 +1998,7 @@ static void sca_tx_intr(pc300dev_t *dev)
 	} else {
 #endif
 	/* Tell the upper layer we are ready to transmit more packets */
-		netif_wake_queue((struct net_device*)dev->hdlc);
+		netif_wake_queue(dev->dev);
 #ifdef CONFIG_PC300_MLPPP
 	}
 #endif
@@ -2017,8 +2016,8 @@ static void sca_intr(pc300_t * card)
 		for (ch = 0; ch < card->hw.nchan; ch++) {
 			pc300ch_t *chan = &card->chan[ch];
 			pc300dev_t *d = &chan->d;
-			hdlc_device *hdlc = d->hdlc;
-			struct net_device *dev = hdlc_to_dev(hdlc);
+			struct net_device *dev = d->dev;
+			hdlc_device *hdlc = dev_to_hdlc(dev);
 
 			spin_lock(&card->card_lock);
 
@@ -2049,7 +2048,7 @@ static void sca_intr(pc300_t * card)
 							if ((cpc_readb(scabase + DSR_RX(ch)) & DSR_DE)) {
 								rx_dma_stop(card, ch);
 							}
-							cpc_net_rx(hdlc);
+							cpc_net_rx(dev);
 							/* Discard invalid frames */
 							hdlc->stats.rx_errors++;
 							hdlc->stats.rx_over_errors++;
@@ -2073,10 +2072,10 @@ static void sca_intr(pc300_t * card)
 							/* verify if driver is TTY */
 							cpc_tty_receive(d);
 						} else {
-							cpc_net_rx(hdlc);
+							cpc_net_rx(dev);
 						}
 #else
-						cpc_net_rx(hdlc);
+						cpc_net_rx(dev);
 #endif
 						if (card->hw.type == PC300_TE) {
 							cpc_writeb(card->hw.falcbase +
@@ -2829,12 +2828,7 @@ int cpc_ioctl(struct net_device *dev, st
 
 static struct net_device_stats *cpc_get_stats(struct net_device *dev)
 {
-	pc300dev_t *d = (pc300dev_t *) dev->priv;
-
-	if (d)
-		return &d->hdlc->stats;
-	else
-		return NULL;
+	return hdlc_stats(dev);
 }
 
 static int clock_rate_calc(uclong rate, uclong clock, int *br_io)
@@ -3075,10 +3069,9 @@ int tx_config(pc300dev_t * d)
 	return 0;
 }
 
-static int cpc_attach(hdlc_device * hdlc, unsigned short encoding,
+static int cpc_attach(struct net_device *dev, unsigned short encoding,
 		      unsigned short parity)
 {
-	struct net_device * dev = hdlc_to_dev(hdlc);
 	pc300dev_t *d = (pc300dev_t *)dev->priv;
 	pc300ch_t *chan = (pc300ch_t *)d->chan;
 	pc300_t *card = (pc300_t *)chan->card;
@@ -3168,7 +3161,7 @@ int cpc_open(struct net_device *dev)
 		d->if_ptr = &hdlc->state.ppp.pppdev;
 	}
 
-	result = hdlc_open(hdlc);
+	result = hdlc_open(dev);
 	if (hdlc->proto.id == IF_PROTO_PPP) {
 		dev->priv = d;
 	}
@@ -3200,7 +3193,7 @@ int cpc_close(struct net_device *dev)
 	cpc_closech(d);
 	CPC_UNLOCK(card, flags);
 
-	hdlc_close(hdlc);
+	hdlc_close(dev);
 	if (hdlc->proto.id == IF_PROTO_PPP) {
 		d->if_ptr = NULL;
 	}
@@ -3369,17 +3362,14 @@ static void cpc_init_card(pc300_t * card
 		d->line_on = 0;
 		d->line_off = 0;
 
-		d->hdlc = (hdlc_device *) kmalloc(sizeof(hdlc_device), GFP_KERNEL);
-		if (d->hdlc == NULL)
+		dev = alloc_hdlcdev(NULL);
+		if (dev == NULL)
 			continue;
-		memset(d->hdlc, 0, sizeof(hdlc_device));
 
-		hdlc = d->hdlc;
+		hdlc = dev_to_hdlc(dev);
 		hdlc->xmit = cpc_queue_xmit;
 		hdlc->attach = cpc_attach;
-
-		dev = hdlc_to_dev(hdlc);
-
+		d->dev = dev;
 		dev->mem_start = card->hw.ramphys;
 		dev->mem_end = card->hw.ramphys + card->hw.ramsize - 1;
 		dev->irq = card->hw.irq;
@@ -3397,7 +3387,7 @@ static void cpc_init_card(pc300_t * card
 		dev->change_mtu = cpc_change_mtu;
 		dev->do_ioctl = cpc_ioctl;
 
-		if (register_hdlc_device(hdlc) == 0) {
+		if (register_hdlc_device(dev) == 0) {
 			dev->priv = d;	/* We need 'priv', hdlc doesn't */
 			printk("%s: Cyclades-PC300/", dev->name);
 			switch (card->hw.type) {
@@ -3425,8 +3415,7 @@ static void cpc_init_card(pc300_t * card
 		} else {
 			printk ("Dev%d on card(0x%08lx): unable to allocate i/f name.\n",
 				 i + 1, card->hw.ramphys);
-			*(dev->name) = 0;
-			kfree(d->hdlc);
+			free_netdev(dev);
 			continue;
 		}
 	}
@@ -3658,7 +3647,7 @@ static void __devexit cpc_remove_one(str
 			   cpc_readw(card->hw.plxbase + card->hw.intctl_reg) & ~(0x0040));
 
 		for (i = 0; i < card->hw.nchan; i++) {
-			unregister_hdlc_device(card->chan[i].d.hdlc);
+			unregister_hdlc_device(card->chan[i].d.dev);
 		}
 		iounmap((void *) card->hw.plxbase);
 		iounmap((void *) card->hw.scabase);
@@ -3671,6 +3660,9 @@ static void __devexit cpc_remove_one(str
 			iounmap((void *) card->hw.falcbase);
 			release_mem_region(card->hw.falcphys, card->hw.falcsize);
 		}
+		for (i = 0; i < card->hw.nchan; i++)
+			if (card->chan[i].d.dev);
+				free_netdev(card->chan[i].d.dev);
 		if (card->hw.irq)
 			free_irq(card->hw.irq, card);
 		kfree(card);
--- diff/drivers/net/wan/pc300_tty.c	2004-02-18 08:54:10.000000000 +0000
+++ source/drivers/net/wan/pc300_tty.c	2004-02-23 13:56:44.000000000 +0000
@@ -155,7 +155,7 @@ static void cpc_tty_signal_off(pc300dev_
 	unsigned long flags; 
 
 	CPC_TTY_DBG("%s-tty: Clear signal %x\n",
-		((struct net_device*)(pc300dev->hdlc))->name, signal);
+		pc300dev->dev->name, signal);
 	CPC_TTY_LOCK(card, flags); 
 	cpc_writeb(card->hw.scabase + M_REG(CTL,ch), 
 		cpc_readb(card->hw.scabase+M_REG(CTL,ch))& signal);
@@ -173,7 +173,7 @@ static void cpc_tty_signal_on(pc300dev_t
 	unsigned long flags; 
 
 	CPC_TTY_DBG("%s-tty: Set signal %x\n",
-		((struct net_device*)(pc300dev->hdlc))->name, signal);
+		pc300dev->dev->name, signal);
 	CPC_TTY_LOCK(card, flags); 
 	cpc_writeb(card->hw.scabase + M_REG(CTL,ch), 
 		cpc_readb(card->hw.scabase+M_REG(CTL,ch))& ~signal);
@@ -196,17 +196,17 @@ void cpc_tty_init(pc300dev_t *pc300dev)
 	st_cpc_tty_area * cpc_tty;
 
 	/* hdlcX - X=interface number */
-	port = ((struct net_device*)(pc300dev->hdlc))->name[4] - '0';
+	port = pc300dev->dev->name[4] - '0';
 	if (port >= CPC_TTY_NPORTS) {
 		printk("%s-tty: invalid interface selected (0-%i): %i", 
-			((struct net_device*)(pc300dev->hdlc))->name,
+			pc300dev->dev->name,
 			CPC_TTY_NPORTS-1,port);
 		return;
 	}
 
 	if (cpc_tty_cnt == 0) { /* first TTY connection -> register driver */
 		CPC_TTY_DBG("%s-tty: driver init, major:%i, minor range:%i=%i\n",
-			((struct net_device*)(pc300dev->hdlc))->name,
+			pc300dev->dev->name,
 			CPC_TTY_MAJOR, CPC_TTY_MINOR_START,
 			CPC_TTY_MINOR_START+CPC_TTY_NPORTS);
 		/* initialize tty driver struct */
@@ -239,7 +239,7 @@ void cpc_tty_init(pc300dev_t *pc300dev)
 		/* register the TTY driver */
 		if (tty_register_driver(&serial_drv)) { 
 			printk("%s-tty: Failed to register serial driver! ",
-				((struct net_device*)(pc300dev->hdlc))->name);
+				pc300dev->dev->name);
 		   	return;
 		} 
 
@@ -251,7 +251,7 @@ void cpc_tty_init(pc300dev_t *pc300dev)
 	
 	if (cpc_tty->state != CPC_TTY_ST_IDLE) {
 		CPC_TTY_DBG("%s-tty: TTY port %i, already in use.\n",
-					((struct net_device*)(pc300dev->hdlc))->name,port);
+				pc300dev->dev->name, port);
 		return;
 	}
 
@@ -268,11 +268,11 @@ void cpc_tty_init(pc300dev_t *pc300dev)
 
 	pc300dev->cpc_tty = (void *)cpc_tty; 
 	
-	aux = strlen(((struct net_device*)(pc300dev->hdlc))->name);
-	memcpy(cpc_tty->name,((struct net_device*)(pc300dev->hdlc))->name,aux);
+	aux = strlen(pc300dev->dev->name);
+	memcpy(cpc_tty->name, pc300dev->dev->name, aux);
 	memcpy(&cpc_tty->name[aux], "-tty", 5);
 	
-	cpc_open((struct net_device *)pc300dev->hdlc);
+	cpc_open(pc300dev->dev);
 	cpc_tty_signal_off(pc300dev, CTL_DTR);
 
 	CPC_TTY_DBG("%s: Initializing TTY Sync Driver, tty major#%d minor#%i\n",
@@ -457,7 +457,7 @@ static int cpc_tty_write(struct tty_stru
 		(from_user)?"from user" : "from kernel",count);
 	
 	pc300chan = (pc300ch_t *)((pc300dev_t*)cpc_tty->pc300dev)->chan; 
-	stats = &((pc300dev_t*)cpc_tty->pc300dev)->hdlc->stats;
+	stats = hdlc_stats(((pc300dev_t*)cpc_tty->pc300dev)->dev);
 	card = (pc300_t *) pc300chan->card;
 	ch = pc300chan->channel; 
 
@@ -756,7 +756,7 @@ void cpc_tty_receive(pc300dev_t *pc300de
 	pc300_t *card = (pc300_t *)pc300chan->card; 
 	int ch = pc300chan->channel; 
 	volatile pcsca_bd_t * ptdescr; 
-	struct net_device_stats *stats = &pc300dev->hdlc->stats; 
+	struct net_device_stats *stats = hdlc_stats(pc300dev->dev);
 	int rx_len, rx_aux; 
 	volatile unsigned char status; 
 	unsigned short first_bd = pc300chan->rx_first_bd;
@@ -932,7 +932,7 @@ static int cpc_tty_send_to_card(pc300dev
 	pc300ch_t *chan = (pc300ch_t *)dev->chan; 
 	pc300_t *card = (pc300_t *)chan->card; 
 	int ch = chan->channel; 
-	struct net_device_stats *stats = &dev->hdlc->stats; 
+	struct net_device_stats *stats = hdlc_stats(dev->dev);
 	unsigned long flags; 
 	volatile pcsca_bd_t * ptdescr; 
 	int i, nchar;
@@ -1016,19 +1016,18 @@ static void cpc_tty_trace(pc300dev_t *de
 
 	if ((skb = dev_alloc_skb(10 + len)) == NULL) { 
 		/* out of memory */ 
-		CPC_TTY_DBG("%s: tty_trace - out of memory\n",
-			((struct net_device *)(dev->hdlc))->name);
+		CPC_TTY_DBG("%s: tty_trace - out of memory\n", dev->dev->name);
 		return; 
 	}
 
 	skb_put (skb, 10 + len); 
-	skb->dev = (struct net_device *) dev->hdlc; 
+	skb->dev = dev->dev; 
 	skb->protocol = htons(ETH_P_CUST); 
 	skb->mac.raw = skb->data; 
 	skb->pkt_type = PACKET_HOST; 
 	skb->len = 10 + len; 
 
-	memcpy(skb->data,((struct net_device *)(dev->hdlc))->name,5);
+	memcpy(skb->data,dev->dev->name,5);
 	skb->data[5] = '['; 
 	skb->data[6] = rxtx; 
 	skb->data[7] = ']'; 
@@ -1050,15 +1049,14 @@ void cpc_tty_unregister_service(pc300dev
 	int res;
 
 	if ((cpc_tty= (st_cpc_tty_area *) pc300dev->cpc_tty) == 0) { 
-		CPC_TTY_DBG("%s: interface is not TTY\n",
-			((struct net_device *)(pc300dev->hdlc))->name);
+		CPC_TTY_DBG("%s: interface is not TTY\n", pc300dev->dev->name);
 		return; 
 	}
 	CPC_TTY_DBG("%s: cpc_tty_unregister_service", cpc_tty->name);
 
 	if (cpc_tty->pc300dev != pc300dev) { 
 		CPC_TTY_DBG("%s: invalid tty ptr=%s\n", 
-		((struct net_device *)(pc300dev->hdlc))->name, cpc_tty->name);
+		pc300dev->dev->name, cpc_tty->name);
 		return; 
 	}
 
--- diff/drivers/net/wan/pci200syn.c	2004-02-09 10:36:11.000000000 +0000
+++ source/drivers/net/wan/pci200syn.c	2004-02-23 13:56:44.000000000 +0000
@@ -73,7 +73,7 @@ typedef struct {
 
 
 typedef struct port_s {
-	hdlc_device hdlc;	/* HDLC device struct - must be first */
+	struct net_device *dev;
 	struct card_s *card;
 	spinlock_t lock;	/* TX lock */
 	sync_serial_settings settings;
@@ -177,14 +177,13 @@ static void pci200_set_iface(port_t *por
 
 static int pci200_open(struct net_device *dev)
 {
-	hdlc_device *hdlc = dev_to_hdlc(dev);
-	port_t *port = hdlc_to_port(hdlc);
+	port_t *port = dev_to_port(dev);
 
-	int result = hdlc_open(hdlc);
+	int result = hdlc_open(dev);
 	if (result)
 		return result;
 
-	sca_open(hdlc);
+	sca_open(dev);
 	pci200_set_iface(port);
 	sca_flush(port_to_card(port));
 	return 0;
@@ -194,10 +193,9 @@ static int pci200_open(struct net_device
 
 static int pci200_close(struct net_device *dev)
 {
-	hdlc_device *hdlc = dev_to_hdlc(dev);
-	sca_close(hdlc);
+	sca_close(dev);
 	sca_flush(port_to_card(dev_to_port(dev)));
-	hdlc_close(hdlc);
+	hdlc_close(dev);
 	return 0;
 }
 
@@ -207,12 +205,11 @@ static int pci200_ioctl(struct net_devic
 {
 	const size_t size = sizeof(sync_serial_settings);
 	sync_serial_settings new_line, *line = ifr->ifr_settings.ifs_ifsu.sync;
-	hdlc_device *hdlc = dev_to_hdlc(dev);
-	port_t *port = hdlc_to_port(hdlc);
+	port_t *port = dev_to_port(dev);
 
 #ifdef DEBUG_RINGS
 	if (cmd == SIOCDEVPRIVATE) {
-		sca_dump_rings(hdlc);
+		sca_dump_rings(dev);
 		return 0;
 	}
 #endif
@@ -265,8 +262,10 @@ static void pci200_pci_remove_one(struct
 	card_t *card = pci_get_drvdata(pdev);
 
 	for(i = 0; i < 2; i++)
-		if (card->ports[i].card)
-			unregister_hdlc_device(&card->ports[i].hdlc);
+		if (card->ports[i].card) {
+			struct net_device *dev = port_to_dev(&card->ports[i]);
+			unregister_hdlc_device(dev);
+		}
 
 	if (card->irq)
 		free_irq(card->irq, card);
@@ -281,6 +280,10 @@ static void pci200_pci_remove_one(struct
 	pci_release_regions(pdev);
 	pci_disable_device(pdev);
 	pci_set_drvdata(pdev, NULL);
+	if (card->ports[0].dev)
+		free_netdev(card->ports[0].dev);
+	if (card->ports[1].dev)
+		free_netdev(card->ports[1].dev);
 	kfree(card);
 }
 
@@ -323,6 +326,13 @@ static int __devinit pci200_pci_init_one
 	}
 	memset(card, 0, sizeof(card_t));
 	pci_set_drvdata(pdev, card);
+	card->ports[0].dev = alloc_hdlcdev(&card->ports[0]);
+	card->ports[1].dev = alloc_hdlcdev(&card->ports[1]);
+	if (!card->ports[0].dev || !card->ports[1].dev) {
+		printk(KERN_ERR "pci200syn: unable to allocate memory\n");
+		pci200_pci_remove_one(pdev);
+		return -ENOMEM;
+	}
 
 	pci_read_config_byte(pdev, PCI_REVISION_ID, &rev_id);
 	if (pci_resource_len(pdev, 0) != PCI200SYN_PLX_SIZE ||
@@ -397,7 +407,8 @@ static int __devinit pci200_pci_init_one
 
 	for(i = 0; i < 2; i++) {
 		port_t *port = &card->ports[i];
-		struct net_device *dev = hdlc_to_dev(&port->hdlc);
+		struct net_device *dev = port_to_dev(port);
+		hdlc_device *hdlc = dev_to_hdlc(dev);
 		port->phy_node = i;
 
 		spin_lock_init(&port->lock);
@@ -409,20 +420,21 @@ static int __devinit pci200_pci_init_one
 		dev->do_ioctl = pci200_ioctl;
 		dev->open = pci200_open;
 		dev->stop = pci200_close;
-		port->hdlc.attach = sca_attach;
-		port->hdlc.xmit = sca_xmit;
+		hdlc->attach = sca_attach;
+		hdlc->xmit = sca_xmit;
 		port->settings.clock_type = CLOCK_EXT;
-		if(register_hdlc_device(&port->hdlc)) {
+		port->card = card;
+		if(register_hdlc_device(dev)) {
 			printk(KERN_ERR "pci200syn: unable to register hdlc "
 			       "device\n");
+			port->card = NULL;
 			pci200_pci_remove_one(pdev);
 			return -ENOBUFS;
 		}
-		port->card = card;
 		sca_init_sync_port(port);	/* Set up SCA memory */
 
 		printk(KERN_INFO "%s: PCI200SYN node %d\n",
-		       hdlc_to_name(&port->hdlc), port->phy_node);
+		       dev->name, port->phy_node);
 	}
 
 	sca_flush(card);
--- diff/drivers/net/wan/sbni.c	2003-10-09 09:47:34.000000000 +0100
+++ source/drivers/net/wan/sbni.c	2004-02-23 13:56:44.000000000 +0000
@@ -210,7 +210,6 @@ sbni_isa_probe( struct net_device  *dev 
 static void __init sbni_devsetup(struct net_device *dev)
 {
 	ether_setup( dev );
-	dev->init 		= &sbni_init;
 	dev->open		= &sbni_open;
 	dev->stop		= &sbni_close;
 	dev->hard_start_xmit	= &sbni_start_xmit;
@@ -234,8 +233,15 @@ int __init sbni_probe(int unit)
 	sprintf(dev->name, "sbni%d", unit);
 	netdev_boot_setup_check(dev);
 
+	err = sbni_init(dev);
+	if (err) {
+		free_netdev(dev);
+		return err;
+	}
+
 	err = register_netdev(dev);
 	if (err) {
+		release_region( dev->base_addr, SBNI_IO_EXTENT );
 		free_netdev(dev);
 		return err;
 	}
@@ -304,8 +310,13 @@ sbni_pci_probe( struct net_device  *dev 
 		/* Avoid already found cards from previous calls */
 		if( !request_region( pci_ioaddr, SBNI_IO_EXTENT, dev->name ) ) {
 			pci_read_config_word( pdev, PCI_SUBSYSTEM_ID, &subsys );
-			if( subsys != 2  ||	/* Dual adapter is present */
-			    check_region( pci_ioaddr += 4, SBNI_IO_EXTENT ) )
+
+			if (subsys != 2)
+				continue;
+
+			/* Dual adapter is present */
+			if (!request_region(pci_ioaddr += 4, SBNI_IO_EXTENT,
+							dev->name ) )
 				continue;
 		}
 
@@ -318,8 +329,10 @@ sbni_pci_probe( struct net_device  *dev 
 				pci_irq_line );
 
 		/* avoiding re-enable dual adapters */
-		if( (pci_ioaddr & 7) == 0  &&  pci_enable_device( pdev ) )
+		if( (pci_ioaddr & 7) == 0  &&  pci_enable_device( pdev ) ) {
+			release_region( pci_ioaddr, SBNI_IO_EXTENT );
 			return  -EIO;
+		}
 		if( sbni_probe1( dev, pci_ioaddr, pci_irq_line ) )
 			return  0;
 	}
@@ -1482,19 +1495,25 @@ int
 init_module( void )
 {
 	struct net_device  *dev;
+	int err;
 
 	while( num < SBNI_MAX_NUM_CARDS ) {
 		dev = alloc_netdev(sizeof(struct net_local), 
 				   "sbni%d", sbni_devsetup);
-		if( !dev) {
-			printk( KERN_ERR "sbni: unable to allocate device!\n" );
-			return  -ENOMEM;
-		}
+		if( !dev)
+			break;
 
 		sprintf( dev->name, "sbni%d", num );
 
+		err = sbni_init(dev);
+		if (err) {
+			free_netdev(dev);
+			break;
+		}
+
 		if( register_netdev( dev ) ) {
-			kfree( dev );
+			release_region( dev->base_addr, SBNI_IO_EXTENT );
+			free_netdev( dev );
 			break;
 		}
 	}
--- diff/drivers/net/wan/sdla.c	2003-09-30 15:46:16.000000000 +0100
+++ source/drivers/net/wan/sdla.c	2004-02-23 13:56:44.000000000 +0000
@@ -1339,6 +1339,8 @@ int sdla_set_config(struct net_device *d
 	struct frad_local *flp;
 	int               i;
 	char              byte;
+	unsigned base;
+	int err = -EINVAL;
 
 	flp = dev->priv;
 
@@ -1352,108 +1354,90 @@ int sdla_set_config(struct net_device *d
 	if (i == sizeof(valid_port) / sizeof(int))
 		return(-EINVAL);
 
-	dev->base_addr = map->base_addr;
-	if (!request_region(dev->base_addr, SDLA_IO_EXTENTS, dev->name)){
+	if (!request_region(map->base_addr, SDLA_IO_EXTENTS, dev->name)){
 		printk(KERN_WARNING "SDLA: io-port 0x%04lx in use \n", dev->base_addr);
 		return(-EINVAL);
 	}
+	base = map->base_addr;
+
 	/* test for card types, S502A, S502E, S507, S508                 */
 	/* these tests shut down the card completely, so clear the state */
 	flp->type = SDLA_UNKNOWN;
 	flp->state = 0;
    
 	for(i=1;i<SDLA_IO_EXTENTS;i++)
-		if (inb(dev->base_addr + i) != 0xFF)
+		if (inb(base + i) != 0xFF)
 			break;
 
-	if (i == SDLA_IO_EXTENTS)
-	{   
-		outb(SDLA_HALT, dev->base_addr + SDLA_REG_Z80_CONTROL);
-		if ((inb(dev->base_addr + SDLA_S502_STS) & 0x0F) == 0x08)
-		{
-			outb(SDLA_S502E_INTACK, dev->base_addr + SDLA_REG_CONTROL);
-			if ((inb(dev->base_addr + SDLA_S502_STS) & 0x0F) == 0x0C)
-			{
-				outb(SDLA_HALT, dev->base_addr + SDLA_REG_CONTROL);
+	if (i == SDLA_IO_EXTENTS) {   
+		outb(SDLA_HALT, base + SDLA_REG_Z80_CONTROL);
+		if ((inb(base + SDLA_S502_STS) & 0x0F) == 0x08) {
+			outb(SDLA_S502E_INTACK, base + SDLA_REG_CONTROL);
+			if ((inb(base + SDLA_S502_STS) & 0x0F) == 0x0C) {
+				outb(SDLA_HALT, base + SDLA_REG_CONTROL);
 				flp->type = SDLA_S502E;
+				goto got_type;
 			}
 		}
 	}
 
-	if (flp->type == SDLA_UNKNOWN)
-	{
-		for(byte=inb(dev->base_addr),i=0;i<SDLA_IO_EXTENTS;i++)
-			if (inb(dev->base_addr + i) != byte)
-				break;
+	for(byte=inb(base),i=0;i<SDLA_IO_EXTENTS;i++)
+		if (inb(base + i) != byte)
+			break;
 
-		if (i == SDLA_IO_EXTENTS)
-		{
-			outb(SDLA_HALT, dev->base_addr + SDLA_REG_CONTROL);
-			if ((inb(dev->base_addr + SDLA_S502_STS) & 0x7E) == 0x30)
-			{
-				outb(SDLA_S507_ENABLE, dev->base_addr + SDLA_REG_CONTROL);
-				if ((inb(dev->base_addr + SDLA_S502_STS) & 0x7E) == 0x32)
-				{
-					outb(SDLA_HALT, dev->base_addr + SDLA_REG_CONTROL);
-					flp->type = SDLA_S507;
-				}
+	if (i == SDLA_IO_EXTENTS) {
+		outb(SDLA_HALT, base + SDLA_REG_CONTROL);
+		if ((inb(base + SDLA_S502_STS) & 0x7E) == 0x30) {
+			outb(SDLA_S507_ENABLE, base + SDLA_REG_CONTROL);
+			if ((inb(base + SDLA_S502_STS) & 0x7E) == 0x32) {
+				outb(SDLA_HALT, base + SDLA_REG_CONTROL);
+				flp->type = SDLA_S507;
+				goto got_type;
 			}
 		}
 	}
 
-	if (flp->type == SDLA_UNKNOWN)
-	{
-		outb(SDLA_HALT, dev->base_addr + SDLA_REG_CONTROL);
-		if ((inb(dev->base_addr + SDLA_S508_STS) & 0x3F) == 0x00)
-		{
-			outb(SDLA_S508_INTEN, dev->base_addr + SDLA_REG_CONTROL);
-			if ((inb(dev->base_addr + SDLA_S508_STS) & 0x3F) == 0x10)
-			{
-				outb(SDLA_HALT, dev->base_addr + SDLA_REG_CONTROL);
-				flp->type = SDLA_S508;
-			}
+	outb(SDLA_HALT, base + SDLA_REG_CONTROL);
+	if ((inb(base + SDLA_S508_STS) & 0x3F) == 0x00) {
+		outb(SDLA_S508_INTEN, base + SDLA_REG_CONTROL);
+		if ((inb(base + SDLA_S508_STS) & 0x3F) == 0x10) {
+			outb(SDLA_HALT, base + SDLA_REG_CONTROL);
+			flp->type = SDLA_S508;
+			goto got_type;
 		}
 	}
 
-	if (flp->type == SDLA_UNKNOWN)
-	{
-		outb(SDLA_S502A_HALT, dev->base_addr + SDLA_REG_CONTROL);
-		if (inb(dev->base_addr + SDLA_S502_STS) == 0x40)
-		{
-			outb(SDLA_S502A_START, dev->base_addr + SDLA_REG_CONTROL);
-			if (inb(dev->base_addr + SDLA_S502_STS) == 0x40)
-			{
-				outb(SDLA_S502A_INTEN, dev->base_addr + SDLA_REG_CONTROL);
-				if (inb(dev->base_addr + SDLA_S502_STS) == 0x44)
-				{
-					outb(SDLA_S502A_START, dev->base_addr + SDLA_REG_CONTROL);
-					flp->type = SDLA_S502A;
-				}
+	outb(SDLA_S502A_HALT, base + SDLA_REG_CONTROL);
+	if (inb(base + SDLA_S502_STS) == 0x40) {
+		outb(SDLA_S502A_START, base + SDLA_REG_CONTROL);
+		if (inb(base + SDLA_S502_STS) == 0x40) {
+			outb(SDLA_S502A_INTEN, base + SDLA_REG_CONTROL);
+			if (inb(base + SDLA_S502_STS) == 0x44) {
+				outb(SDLA_S502A_START, base + SDLA_REG_CONTROL);
+				flp->type = SDLA_S502A;
+				goto got_type;
 			}
 		}
 	}
 
-	if (flp->type == SDLA_UNKNOWN)
-	{
-		printk(KERN_NOTICE "%s: Unknown card type\n", dev->name);
-		return(-ENODEV);
-	}
+	printk(KERN_NOTICE "%s: Unknown card type\n", dev->name);
+	err = -ENODEV;
+	goto fail;
 
-	switch(dev->base_addr)
-	{
+got_type:
+	switch(base) {
 		case 0x270:
 		case 0x280:
 		case 0x380: 
 		case 0x390:
-			if ((flp->type != SDLA_S508) && (flp->type != SDLA_S507))
-				return(-EINVAL);
+			if (flp->type != SDLA_S508 && flp->type != SDLA_S507)
+				goto fail;
 	}
 
-	switch (map->irq)
-	{
+	switch (map->irq) {
 		case 2:
 			if (flp->type != SDLA_S502E)
-				return(-EINVAL);
+				goto fail;
 			break;
 
 		case 10:
@@ -1461,28 +1445,26 @@ int sdla_set_config(struct net_device *d
 		case 12:
 		case 15:
 		case 4:
-			if ((flp->type != SDLA_S508) && (flp->type != SDLA_S507))
-				return(-EINVAL);
-
+			if (flp->type != SDLA_S508 && flp->type != SDLA_S507)
+				goto fail;
+			break;
 		case 3:
 		case 5:
 		case 7:
 			if (flp->type == SDLA_S502A)
-				return(-EINVAL);
+				goto fail;
 			break;
 
 		default:
-			return(-EINVAL);
+			goto fail;
 	}
-	dev->irq = map->irq;
 
+	err = -EAGAIN;
 	if (request_irq(dev->irq, &sdla_isr, 0, dev->name, dev)) 
-		return(-EAGAIN);
+		goto fail;
 
-	if (flp->type == SDLA_S507)
-	{
-		switch(dev->irq)
-		{
+	if (flp->type == SDLA_S507) {
+		switch(dev->irq) {
 			case 3:
 				flp->state = SDLA_S507_IRQ3;
 				break;
@@ -1514,35 +1496,25 @@ int sdla_set_config(struct net_device *d
 		if (valid_mem[i] == map->mem_start)
 			break;   
 
+	err = -EINVAL;
 	if (i == sizeof(valid_mem) / sizeof(int))
-	/*
-	 *	FIXME:
-	 *	BUG BUG BUG: MUST RELEASE THE IRQ WE ALLOCATED IN
-	 *	ALL THESE CASES
-	 *
-	 */
-		return(-EINVAL);
+		goto fail2;
 
-	if ((flp->type == SDLA_S502A) && (((map->mem_start & 0xF000) >> 12) == 0x0E))
-		return(-EINVAL);
-
-	if ((flp->type != SDLA_S507) && ((map->mem_start >> 16) == 0x0B))
-		return(-EINVAL);
+	if (flp->type == SDLA_S502A && (map->mem_start & 0xF000) >> 12 == 0x0E)
+		goto fail2;
 
-	if ((flp->type == SDLA_S507) && ((map->mem_start >> 16) == 0x0D))
-		return(-EINVAL);
+	if (flp->type != SDLA_S507 && map->mem_start >> 16 == 0x0B)
+		goto fail2;
 
-	dev->mem_start = map->mem_start;
-	dev->mem_end = dev->mem_start + 0x2000;
+	if (flp->type == SDLA_S507 && map->mem_start >> 16 == 0x0D)
+		goto fail2;
 
 	byte = flp->type != SDLA_S508 ? SDLA_8K_WINDOW : 0;
 	byte |= (map->mem_start & 0xF000) >> (12 + (flp->type == SDLA_S508 ? 1 : 0));
-	switch(flp->type)
-	{
+	switch(flp->type) {
 		case SDLA_S502A:
 		case SDLA_S502E:
-			switch (map->mem_start >> 16)
-			{
+			switch (map->mem_start >> 16) {
 				case 0x0A:
 					byte |= SDLA_S502_SEG_A;
 					break;
@@ -1558,8 +1530,7 @@ int sdla_set_config(struct net_device *d
 			}
 			break;
 		case SDLA_S507:
-			switch (map->mem_start >> 16)
-			{
+			switch (map->mem_start >> 16) {
 				case 0x0A:
 					byte |= SDLA_S507_SEG_A;
 					break;
@@ -1575,8 +1546,7 @@ int sdla_set_config(struct net_device *d
 			}
 			break;
 		case SDLA_S508:
-			switch (map->mem_start >> 16)
-			{
+			switch (map->mem_start >> 16) {
 				case 0x0A:
 					byte |= SDLA_S508_SEG_A;
 					break;
@@ -1594,7 +1564,7 @@ int sdla_set_config(struct net_device *d
 	}
 
 	/* set the memory bits, and enable access */
-	outb(byte, dev->base_addr + SDLA_REG_PC_WINDOW);
+	outb(byte, base + SDLA_REG_PC_WINDOW);
 
 	switch(flp->type)
 	{
@@ -1608,10 +1578,20 @@ int sdla_set_config(struct net_device *d
 			flp->state = SDLA_MEMEN;
 			break;
 	}
-	outb(flp->state, dev->base_addr + SDLA_REG_CONTROL);
+	outb(flp->state, base + SDLA_REG_CONTROL);
 
+	dev->irq = map->irq;
+	dev->base_addr = base;
+	dev->mem_start = map->mem_start;
+	dev->mem_end = dev->mem_start + 0x2000;
 	flp->initialized = 1;
-	return(0);
+	return 0;
+
+fail2:
+	free_irq(map->irq, dev);
+fail:
+	release_region(base, SDLA_IO_EXTENTS);
+	return err;
 }
  
 static struct net_device_stats *sdla_stats(struct net_device *dev)
@@ -1676,13 +1656,13 @@ static int __init init_sdla(void)
 
 static void __exit exit_sdla(void)
 {
-	struct frad_local *flp;
+	struct frad_local *flp = sdla->priv;
 
 	unregister_netdev(sdla);
-	if (sdla->irq)
+	if (flp->initialized) {
 		free_irq(sdla->irq, sdla);
-
-	flp = sdla->priv;
+		release_region(sdla->base_addr, SDLA_IO_EXTENTS);
+	}
 	del_timer_sync(&flp->timer);
 	free_netdev(sdla);
 }
--- diff/drivers/net/wan/sealevel.c	2003-10-27 09:20:38.000000000 +0000
+++ source/drivers/net/wan/sealevel.c	2004-02-23 13:56:44.000000000 +0000
@@ -420,6 +420,7 @@ static void __exit slvl_shutdown(struct 
 	/* DMA off on the card, drop DTR */
 	outb(0, b->iobase);
 	release_region(b->iobase, 8);
+	kfree(b);
 }
 
 
--- diff/drivers/net/wan/wanxl.c	2003-09-30 15:46:16.000000000 +0100
+++ source/drivers/net/wan/wanxl.c	2004-02-23 13:56:44.000000000 +0000
@@ -51,7 +51,7 @@ static const char* version = "wanXL seri
 
 
 typedef struct {
-	hdlc_device hdlc;	/* HDLC device struct - must be first */
+	struct net_device *dev;
 	struct card_t *card;
 	spinlock_t lock;	/* for wanxl_xmit */
         int node;		/* physical port #0 - 3 */
@@ -78,31 +78,26 @@ typedef struct card_t {
 	struct sk_buff *rx_skbs[RX_QUEUE_LENGTH];
 	card_status_t *status;	/* shared between host and card */
 	dma_addr_t status_address;
+	port_t __ports[0];
 }card_t;
 
 
 
-static inline port_t* hdlc_to_port(hdlc_device *hdlc)
-{
-        return (port_t*)hdlc;
-}
-
-
 static inline port_t* dev_to_port(struct net_device *dev)
 {
-        return hdlc_to_port(dev_to_hdlc(dev));
+        return (port_t *)dev_to_hdlc(dev)->priv;
 }
 
 
 static inline struct net_device *port_to_dev(port_t* port)
 {
-        return hdlc_to_dev(&port->hdlc);
+        return port->dev;
 }
 
 
 static inline const char* port_name(port_t *port)
 {
-	return hdlc_to_name((hdlc_device*)port);
+	return port_to_dev(port)->name;
 }
 
 
@@ -172,7 +167,7 @@ static inline void wanxl_cable_intr(port
 	printk(KERN_INFO "%s: %s%s module, %s cable%s%s\n",
 	       port_name(port), pm, dte, cable, dsr, dcd);
 
-	hdlc_set_carrier(value & STATUS_CABLE_DCD, &port->hdlc);
+	hdlc_set_carrier(value & STATUS_CABLE_DCD, port_to_dev(port));
 }
 
 
@@ -180,6 +175,8 @@ static inline void wanxl_cable_intr(port
 /* Transmit complete interrupt service */
 static inline void wanxl_tx_intr(port_t *port)
 {
+	struct net_device *dev = port_to_dev(port);
+	struct net_device_stats *stats = hdlc_stats(dev);
 	while (1) {
                 desc_t *desc = &get_status(port)->tx_descs[port->tx_in];
 		struct sk_buff *skb = port->tx_skbs[port->tx_in];
@@ -187,17 +184,17 @@ static inline void wanxl_tx_intr(port_t 
 		switch (desc->stat) {
 		case PACKET_FULL:
 		case PACKET_EMPTY:
-			netif_wake_queue(port_to_dev(port));
+			netif_wake_queue(dev);
 			return;
 
 		case PACKET_UNDERRUN:
-			port->hdlc.stats.tx_errors++;
-			port->hdlc.stats.tx_fifo_errors++;
+			stats->tx_errors++;
+			stats->tx_fifo_errors++;
 			break;
 
 		default:
-			port->hdlc.stats.tx_packets++;
-			port->hdlc.stats.tx_bytes += skb->len;
+			stats->tx_packets++;
+			stats->tx_bytes += skb->len;
 		}
                 desc->stat = PACKET_EMPTY; /* Free descriptor */
 		pci_unmap_single(port->card->pdev, desc->address, skb->len,
@@ -218,13 +215,14 @@ static inline void wanxl_rx_intr(card_t 
 		struct sk_buff *skb = card->rx_skbs[card->rx_in];
 		port_t *port = card->ports[desc->stat & PACKET_PORT_MASK];
 		struct net_device *dev = port_to_dev(port);
+		struct net_device_stats *stats = hdlc_stats(dev);
 
 		if ((desc->stat & PACKET_PORT_MASK) > card->n_ports)
 			printk(KERN_CRIT "wanXL %s: received packet for"
 			       " nonexistent port\n", card_name(card->pdev));
 
 		else if (!skb)
-			port->hdlc.stats.rx_dropped++;
+			stats->rx_dropped++;
 
 		else {
 			pci_unmap_single(card->pdev, desc->address,
@@ -236,8 +234,8 @@ static inline void wanxl_rx_intr(card_t 
 			       skb->len);
 			debug_frame(skb);
 #endif
-			port->hdlc.stats.rx_packets++;
-			port->hdlc.stats.rx_bytes += skb->len;
+			stats->rx_packets++;
+			stats->rx_bytes += skb->len;
 			skb->mac.raw = skb->data;
 			skb->dev = dev;
 			dev->last_rx = jiffies;
@@ -290,8 +288,7 @@ static irqreturn_t wanxl_intr(int irq, v
 
 static int wanxl_xmit(struct sk_buff *skb, struct net_device *dev)
 {
-	hdlc_device *hdlc = dev_to_hdlc(dev);
-        port_t *port = hdlc_to_port(hdlc);
+        port_t *port = dev_to_port(dev);
 	desc_t *desc;
 
         spin_lock(&port->lock);
@@ -338,10 +335,10 @@ static int wanxl_xmit(struct sk_buff *sk
 
 
 
-static int wanxl_attach(hdlc_device *hdlc, unsigned short encoding,
+static int wanxl_attach(struct net_device *dev, unsigned short encoding,
 			unsigned short parity)
 {
-	port_t *port = hdlc_to_port(hdlc);
+	port_t *port = dev_to_port(dev);
 
 	if (encoding != ENCODING_NRZ &&
 	    encoding != ENCODING_NRZI)
@@ -365,8 +362,7 @@ static int wanxl_ioctl(struct net_device
 {
 	const size_t size = sizeof(sync_serial_settings);
 	sync_serial_settings line;
-	hdlc_device *hdlc = dev_to_hdlc(dev);
-	port_t *port = hdlc_to_port(hdlc);
+	port_t *port = dev_to_port(dev);
 
 	if (cmd != SIOCWANDEV)
 		return hdlc_ioctl(dev, ifr, cmd);
@@ -415,8 +411,7 @@ static int wanxl_ioctl(struct net_device
 
 static int wanxl_open(struct net_device *dev)
 {
-	hdlc_device *hdlc = dev_to_hdlc(dev);
-	port_t *port = hdlc_to_port(hdlc);
+	port_t *port = dev_to_port(dev);
 	u8 *dbr = port->card->plx + PLX_DOORBELL_TO_CARD;
 	unsigned long timeout;
 	int i;
@@ -425,7 +420,7 @@ static int wanxl_open(struct net_device 
 		printk(KERN_ERR "%s: port already open\n", port_name(port));
 		return -EIO;
 	}
-	if ((i = hdlc_open(hdlc)) != 0)
+	if ((i = hdlc_open(dev)) != 0)
 		return i;
 
 	port->tx_in = port->tx_out = 0;
@@ -450,12 +445,11 @@ static int wanxl_open(struct net_device 
 
 static int wanxl_close(struct net_device *dev)
 {
-	hdlc_device *hdlc = dev_to_hdlc(dev);
-	port_t *port = hdlc_to_port(hdlc);
+	port_t *port = dev_to_port(dev);
 	unsigned long timeout;
 	int i;
 
-	hdlc_close(hdlc);
+	hdlc_close(dev);
 	/* signal the card */
 	writel(1 << (DOORBELL_TO_CARD_CLOSE_0 + port->node),
 	       port->card->plx + PLX_DOORBELL_TO_CARD);
@@ -487,14 +481,13 @@ static int wanxl_close(struct net_device
 
 static struct net_device_stats *wanxl_get_stats(struct net_device *dev)
 {
-	hdlc_device *hdlc = dev_to_hdlc(dev);
-	port_t *port = hdlc_to_port(hdlc);
+	struct net_device_stats *stats = hdlc_stats(dev);
+	port_t *port = dev_to_port(dev);
 
-	hdlc->stats.rx_over_errors = get_status(port)->rx_overruns;
-	hdlc->stats.rx_frame_errors = get_status(port)->rx_frame_errors;
-	hdlc->stats.rx_errors = hdlc->stats.rx_over_errors +
-		hdlc->stats.rx_frame_errors;
-        return &hdlc->stats;
+	stats->rx_over_errors = get_status(port)->rx_overruns;
+	stats->rx_frame_errors = get_status(port)->rx_frame_errors;
+	stats->rx_errors = stats->rx_over_errors + stats->rx_frame_errors;
+        return stats;
 }
 
 
@@ -535,14 +528,16 @@ static void wanxl_pci_remove_one(struct 
 	card_t *card = pci_get_drvdata(pdev);
 	int i;
 
+	for (i = 0; i < 4; i++)
+		if (card->ports[i]) {
+			struct net_device *dev = port_to_dev(card->ports[i]);
+			unregister_hdlc_device(dev);
+		}
+
 	/* unregister and free all host resources */
 	if (card->irq)
 		free_irq(card->irq, card);
 
-	for (i = 0; i < 4; i++)
-		if (card->ports[i])
-			unregister_hdlc_device(&card->ports[i]->hdlc);
-
 	wanxl_reset(card);
 
 	for (i = 0; i < RX_QUEUE_LENGTH; i++)
@@ -560,6 +555,10 @@ static void wanxl_pci_remove_one(struct 
 		pci_free_consistent(pdev, sizeof(card_status_t),
 				    card->status, card->status_address);
 
+	for (i = 0; i < card->n_ports; i++)
+		if (card->__ports[i].dev)
+			free_netdev(card->__ports[i].dev);
+
 	pci_set_drvdata(pdev, NULL);
 	kfree(card);
 	pci_release_regions(pdev);
@@ -628,6 +627,16 @@ static int __devinit wanxl_pci_init_one(
 	card->pdev = pdev;
 	card->n_ports = ports;
 
+	for (i = 0; i < ports; i++) {
+		card->__ports[i].dev = alloc_hdlcdev(&card->__ports[i]);
+		if (!card->__ports[i].dev) {
+			printk(KERN_ERR "wanXL %s: unable to allocate memory\n",
+			       card_name(pdev));
+			wanxl_pci_remove_one(pdev);
+			return -ENOMEM;
+		}
+	}
+
 	card->status = pci_alloc_consistent(pdev, sizeof(card_status_t),
 					    &card->status_address);
 	if (card->status == NULL) {
@@ -708,31 +717,6 @@ static int __devinit wanxl_pci_init_one(
 		return -ENODEV;
 	}
 
-	for (i = 0; i < ports; i++) {
-		port_t *port = (void *)card + sizeof(card_t) +
-			i * sizeof(port_t);
-		struct net_device *dev = hdlc_to_dev(&port->hdlc);
-		spin_lock_init(&port->lock);
-		SET_MODULE_OWNER(dev);
-		dev->tx_queue_len = 50;
-		dev->do_ioctl = wanxl_ioctl;
-		dev->open = wanxl_open;
-		dev->stop = wanxl_close;
-		port->hdlc.attach = wanxl_attach;
-		port->hdlc.xmit = wanxl_xmit;
-		if(register_hdlc_device(&port->hdlc)) {
-			printk(KERN_ERR "wanXL %s: unable to register hdlc"
-			       " device\n", card_name(pdev));
-			wanxl_pci_remove_one(pdev);
-			return -ENOBUFS;
-		}
-		card->ports[i] = port;
-		dev->get_stats = wanxl_get_stats;
-		port->card = card;
-		port->node = i;
-		get_status(port)->clocking = CLOCK_EXT;
-	}
-
 	for (i = 0; i < RX_QUEUE_LENGTH; i++) {
 		struct sk_buff *skb = dev_alloc_skb(BUFFER_LENGTH);
 		card->rx_skbs[i] = skb;
@@ -801,6 +785,32 @@ static int __devinit wanxl_pci_init_one(
 	}
 	card->irq = pdev->irq;
 
+	for (i = 0; i < ports; i++) {
+		port_t *port = &card->__ports[i];
+		struct net_device *dev = port_to_dev(port);
+		hdlc_device *hdlc = dev_to_hdlc(dev);
+		spin_lock_init(&port->lock);
+		SET_MODULE_OWNER(dev);
+		dev->tx_queue_len = 50;
+		dev->do_ioctl = wanxl_ioctl;
+		dev->open = wanxl_open;
+		dev->stop = wanxl_close;
+		hdlc->attach = wanxl_attach;
+		hdlc->xmit = wanxl_xmit;
+		card->ports[i] = port;
+		dev->get_stats = wanxl_get_stats;
+		port->card = card;
+		port->node = i;
+		get_status(port)->clocking = CLOCK_EXT;
+		if (register_hdlc_device(dev)) {
+			printk(KERN_ERR "wanXL %s: unable to register hdlc"
+			       " device\n", card_name(pdev));
+			card->ports[i] = NULL;
+			wanxl_pci_remove_one(pdev);
+			return -ENOBUFS;
+		}
+	}
+
 	return 0;
 }
 
--- diff/drivers/net/wan/x25_asy.c	2004-02-18 08:54:10.000000000 +0000
+++ source/drivers/net/wan/x25_asy.c	2004-02-23 13:56:44.000000000 +0000
@@ -213,7 +213,7 @@ static void x25_asy_bump(struct x25_asy 
 	memcpy(skb_put(skb,count), sl->rbuff, count);
 	skb->mac.raw=skb->data;
 	skb->protocol=htons(ETH_P_X25);
-	if((err=lapb_data_received(sl,skb))!=LAPB_OK)
+	if((err=lapb_data_received(skb->dev, skb))!=LAPB_OK)
 	{
 		kfree_skb(skb);
 		printk(KERN_DEBUG "x25_asy: data received err - %d\n",err);
@@ -324,12 +324,12 @@ static int x25_asy_xmit(struct sk_buff *
 	{
 		case 0x00:break;
 		case 0x01: /* Connection request .. do nothing */
-			if((err=lapb_connect_request(sl))!=LAPB_OK)
+			if((err=lapb_connect_request(dev))!=LAPB_OK)
 				printk(KERN_ERR "x25_asy: lapb_connect_request error - %d\n", err);
 			kfree_skb(skb);
 			return 0;
 		case 0x02: /* Disconnect request .. do nothing - hang up ?? */
-			if((err=lapb_disconnect_request(sl))!=LAPB_OK)
+			if((err=lapb_disconnect_request(dev))!=LAPB_OK)
 				printk(KERN_ERR "x25_asy: lapb_disconnect_request error - %d\n", err);
 		default:
 			kfree_skb(skb);
@@ -347,7 +347,7 @@ static int x25_asy_xmit(struct sk_buff *
 	 *        14 Oct 1994  Dmitry Gorodchanin.
 	 */
 	
-	if((err=lapb_data_request(sl,skb))!=LAPB_OK)
+	if((err=lapb_data_request(dev,skb))!=LAPB_OK)
 	{
 		printk(KERN_ERR "lapbeth: lapb_data_request error - %d\n", err);
 		kfree_skb(skb);
@@ -366,7 +366,7 @@ static int x25_asy_xmit(struct sk_buff *
  *	at the net layer.
  */
   
-static int x25_asy_data_indication(void *token, struct sk_buff *skb)
+static int x25_asy_data_indication(struct net_device *dev, struct sk_buff *skb)
 {
 	skb->dev->last_rx = jiffies;
 	return netif_rx(skb);
@@ -378,9 +378,9 @@ static int x25_asy_data_indication(void 
  *	perhaps lapb should allow us to bounce this ?
  */
  
-static void x25_asy_data_transmit(void *token, struct sk_buff *skb)
+static void x25_asy_data_transmit(struct net_device *dev, struct sk_buff *skb)
 {
-	struct x25_asy *sl=token;
+	struct x25_asy *sl=dev->priv;
 	
 	spin_lock(&sl->lock);
 	if (netif_queue_stopped(sl->dev) || sl->tty == NULL)
@@ -405,9 +405,9 @@ static void x25_asy_data_transmit(void *
  *	LAPB connection establish/down information.
  */
  
-static void x25_asy_connected(void *token, int reason)
+static void x25_asy_connected(struct net_device *dev, int reason)
 {
-	struct x25_asy *sl = token;
+	struct x25_asy *sl = dev->priv;
 	struct sk_buff *skb;
 	unsigned char *ptr;
 
@@ -428,9 +428,9 @@ static void x25_asy_connected(void *toke
 	sl->dev->last_rx = jiffies;
 }
 
-static void x25_asy_disconnected(void *token, int reason)
+static void x25_asy_disconnected(struct net_device *dev, int reason)
 {
-	struct x25_asy *sl = token;
+	struct x25_asy *sl = dev->priv;
 	struct sk_buff *skb;
 	unsigned char *ptr;
 
@@ -500,7 +500,7 @@ static int x25_asy_open(struct net_devic
 	/*
 	 *	Now attach LAPB
 	 */
-	if((err=lapb_register(sl, &x25_asy_callbacks))==LAPB_OK)
+	if((err=lapb_register(dev, &x25_asy_callbacks))==LAPB_OK)
 		return 0;
 
 	/* Cleanup */
@@ -525,7 +525,7 @@ static int x25_asy_close(struct net_devi
 	netif_stop_queue(dev);
 	sl->rcount = 0;
 	sl->xleft  = 0;
-	if((err=lapb_unregister(sl))!=LAPB_OK)
+	if((err=lapb_unregister(dev))!=LAPB_OK)
 		printk(KERN_ERR "x25_asy_close: lapb_unregister error -%d\n",err);
 	spin_unlock(&sl->lock);
 	return 0;
--- diff/drivers/net/wd.c	2004-02-18 08:54:10.000000000 +0000
+++ source/drivers/net/wd.c	2004-02-23 13:56:44.000000000 +0000
@@ -333,6 +333,9 @@ static int __init wd_probe1(struct net_d
 	ei_status.get_8390_hdr = &wd_get_8390_hdr;
 	dev->open = &wd_open;
 	dev->stop = &wd_close;
+#ifdef CONFIG_NET_POLL_CONTROLLER
+	dev->poll_controller = ei_poll;
+#endif
 	NS8390_init(dev, 0);
 
 #if 1
--- diff/drivers/net/wireless/Kconfig	2004-02-18 08:54:10.000000000 +0000
+++ source/drivers/net/wireless/Kconfig	2004-02-23 13:56:44.000000000 +0000
@@ -224,8 +224,8 @@ config PCI_HERMES
 config ATMEL
       tristate "Atmel at76c50x chipset  802.11b support"
       depends on NET_RADIO && EXPERIMENTAL
-      enable FW_LOADER
-      enable CRC32
+      select FW_LOADER
+      select CRC32
        ---help---
         A driver 802.11b wireless cards based on the Atmel fast-vnet
         chips. This driver supports standard Linux wireless extensions. 
--- diff/drivers/net/wireless/airo.c	2004-02-18 08:54:10.000000000 +0000
+++ source/drivers/net/wireless/airo.c	2004-02-23 13:56:44.000000000 +0000
@@ -2599,10 +2599,8 @@ static int mpi_map_card(struct airo_info
 	return rc;
 }
 
-static void wifi_setup(struct net_device *dev, struct net_device *ethdev)
+static void wifi_setup(struct net_device *dev)
 {
-	struct airo_info *ai = ethdev->priv;
-	dev->priv = ai;
 	dev->hard_header        = 0;
 	dev->rebuild_header     = 0;
 	dev->hard_header_cache  = 0;
@@ -2620,14 +2618,11 @@ static void wifi_setup(struct net_device
 	dev->change_mtu = &airo_change_mtu;
 	dev->open = &airo_open;
 	dev->stop = &airo_close;
-	dev->irq = ethdev->irq;
-	dev->base_addr = ethdev->base_addr;
 
 	dev->type               = ARPHRD_IEEE80211;
 	dev->hard_header_len    = ETH_HLEN;
 	dev->mtu                = 2312;
 	dev->addr_len           = ETH_ALEN;
-	memcpy(dev->dev_addr, ethdev->dev_addr, dev->addr_len);
 	dev->tx_queue_len       = 100; 
 
 	memset(dev->broadcast,0xFF, ETH_ALEN);
@@ -2639,17 +2634,17 @@ static struct net_device *init_wifidev(s
 					struct net_device *ethdev)
 {
 	int err;
-	struct net_device *dev = (struct net_device*)kmalloc(sizeof *dev,GFP_KERNEL);
-	if (!dev) return 0;
-	memset(dev, 0, sizeof(*dev));
-
-	strcpy(dev->name, "wifi%d");
-	dev->priv = ai;
-	wifi_setup(dev, ethdev);
+	struct net_device *dev = alloc_netdev(0, "wifi%d", wifi_setup);
+	if (!dev)
+		return NULL;
+	dev->priv = ethdev->priv;
+	dev->irq = ethdev->irq;
+	dev->base_addr = ethdev->base_addr;
+	memcpy(dev->dev_addr, ethdev->dev_addr, dev->addr_len);
 	err = register_netdev(dev);
 	if (err<0) {
-		kfree(dev);
-		return 0;
+		free_netdev(dev);
+		return NULL;
 	}
 	return dev;
 }
@@ -2809,7 +2804,7 @@ err_out_thr:
 	kill_proc(ai->thr_pid, SIGTERM, 1);
 	wait_for_completion(&ai->thr_exited);
 err_out_free:
-	kfree(dev);
+	free_netdev(dev);
 	return NULL;
 }
 
--- diff/drivers/net/wireless/orinoco.c	2003-09-30 15:46:16.000000000 +0100
+++ source/drivers/net/wireless/orinoco.c	2004-02-23 13:56:44.000000000 +0000
@@ -4129,6 +4129,8 @@ struct net_device *alloc_orinocodev(int 
 	struct orinoco_private *priv;
 
 	dev = alloc_etherdev(sizeof(struct orinoco_private) + sizeof_card);
+	if (!dev)
+		return NULL;
 	priv = (struct orinoco_private *)dev->priv;
 	priv->ndev = dev;
 	if (sizeof_card)
--- diff/drivers/net/wireless/wl3501_cs.c	2004-02-18 08:54:10.000000000 +0000
+++ source/drivers/net/wireless/wl3501_cs.c	2004-02-23 13:56:44.000000000 +0000
@@ -1580,7 +1580,7 @@ static void wl3501_detach(dev_link_t *li
 	*linkp = link->next;
 
 	if (link->priv)
-		kfree(link->priv);
+		free_netdev(link->priv);
 	kfree(link);
 out:
 	return;
--- diff/drivers/net/zorro8390.c	2004-02-18 08:54:10.000000000 +0000
+++ source/drivers/net/zorro8390.c	2004-02-23 13:56:44.000000000 +0000
@@ -59,9 +59,6 @@
 
 #define WORDSWAP(a)	((((a)>>8)&0xff) | ((a)<<8))
 
-#ifdef MODULE
-static struct net_device *root_zorro8390_dev;
-#endif
 
 static const struct card_info {
     zorro_id id;
@@ -72,9 +69,11 @@ static const struct card_info {
     { ZORRO_PROD_INDIVIDUAL_COMPUTERS_X_SURF, "X-Surf", 0x8600 },
 };
 
-static int __init zorro8390_probe(void);
-static int __init zorro8390_init(struct net_device *dev, unsigned long board,
-				 const char *name, unsigned long ioaddr);
+static int __devinit zorro8390_init_one(struct zorro_dev *z,
+					const struct zorro_device_id *ent);
+static int __devinit zorro8390_init(struct net_device *dev,
+				    unsigned long board, const char *name,
+				    unsigned long ioaddr);
 static int zorro8390_open(struct net_device *dev);
 static int zorro8390_close(struct net_device *dev);
 static void zorro8390_reset_8390(struct net_device *dev);
@@ -85,48 +84,54 @@ static void zorro8390_block_input(struct
 static void zorro8390_block_output(struct net_device *dev, const int count,
 				   const unsigned char *buf,
 				   const int start_page);
-static void __exit zorro8390_cleanup(void);
+static void __devexit zorro8390_remove_one(struct zorro_dev *z);
+
+static struct zorro_device_id zorro8390_zorro_tbl[] __devinitdata = {
+    { ZORRO_PROD_VILLAGE_TRONIC_ARIADNE2, },
+    { ZORRO_PROD_INDIVIDUAL_COMPUTERS_X_SURF, },
+    { 0 }
+};
 
-static int __init zorro8390_probe(void)
+static struct zorro_driver zorro8390_driver = {
+    .name	= "zorro8390",
+    .id_table	= zorro8390_zorro_tbl,
+    .probe	= zorro8390_init_one,
+    .remove	= __devexit_p(zorro8390_remove_one),
+};
+
+static int __devinit zorro8390_init_one(struct zorro_dev *z,
+					const struct zorro_device_id *ent)
 {
     struct net_device *dev;
-    struct zorro_dev *z = NULL;
     unsigned long board, ioaddr;
-    int err = -ENODEV;
-    int i;
+    int err, i;
 
-    while ((z = zorro_find_device(ZORRO_WILDCARD, z))) {
-	for (i = ARRAY_SIZE(cards)-1; i >= 0; i--)
-	    if (z->id == cards[i].id)
-		break;
-	if (i < 0)
-	    continue;
-	board = z->resource.start;
-	ioaddr = board+cards[i].offset;
-	dev = alloc_ei_netdev();
-	if (!dev)
-	    return -ENOMEM;
-	SET_MODULE_OWNER(dev);
-	if (!request_mem_region(ioaddr, NE_IO_EXTENT*2, dev->name)) {
-	    free_netdev(dev);
-	    continue;
-	}
-	if ((err = zorro8390_init(dev, board, cards[i].name,
-				  ZTWO_VADDR(ioaddr)))) {
-	    release_mem_region(ioaddr, NE_IO_EXTENT*2);
-	    free_netdev(dev);
-	    return err;
-	}
-	err = 0;
+    for (i = ARRAY_SIZE(cards)-1; i >= 0; i--)
+	if (z->id == cards[i].id)
+	    break;
+    board = z->resource.start;
+    ioaddr = board+cards[i].offset;
+    dev = alloc_ei_netdev();
+    if (!dev)
+	return -ENOMEM;
+    SET_MODULE_OWNER(dev);
+    if (!request_mem_region(ioaddr, NE_IO_EXTENT*2, dev->name)) {
+	free_netdev(dev);
+	return -EBUSY;
     }
-
-    if (err == -ENODEV)
-	printk("No Ariadne II or X-Surf ethernet card found.\n");
-    return err;
+    if ((err = zorro8390_init(dev, board, cards[i].name,
+			      ZTWO_VADDR(ioaddr)))) {
+	release_mem_region(ioaddr, NE_IO_EXTENT*2);
+	free_netdev(dev);
+	return err;
+    }
+    zorro_set_drvdata(z, dev);
+    return 0;
 }
 
-static int __init zorro8390_init(struct net_device *dev, unsigned long board,
-				 const char *name, unsigned long ioaddr)
+static int __devinit zorro8390_init(struct net_device *dev,
+				    unsigned long board, const char *name,
+				    unsigned long ioaddr)
 {
     int i;
     int err;
@@ -222,9 +227,8 @@ static int __init zorro8390_init(struct 
     ei_status.reg_offset = zorro8390_offsets;
     dev->open = &zorro8390_open;
     dev->stop = &zorro8390_close;
-#ifdef MODULE
-    ei_status.priv = (unsigned long)root_zorro8390_dev;
-    root_zorro8390_dev = dev;
+#ifdef CONFIG_NET_POLL_CONTROLLER
+    dev->poll_controller = ei_poll;
 #endif
     NS8390_init(dev, 0);
     err = register_netdev(dev);
@@ -401,23 +405,27 @@ static void zorro8390_block_output(struc
     return;
 }
 
-static void __exit zorro8390_cleanup(void)
+static void __devexit zorro8390_remove_one(struct zorro_dev *z)
 {
-#ifdef MODULE
-    struct net_device *dev, *next;
+    struct net_device *dev = zorro_get_drvdata(z);
 
-    while ((dev = root_zorro8390_dev)) {
-	next = (struct net_device *)(ei_status.priv);
-	unregister_netdev(dev);
-	free_irq(IRQ_AMIGA_PORTS, dev);
-	release_mem_region(ZTWO_PADDR(dev->base_addr), NE_IO_EXTENT*2);
-	free_netdev(dev);
-	root_zorro8390_dev = next;
-    }
-#endif
+    unregister_netdev(dev);
+    free_irq(IRQ_AMIGA_PORTS, dev);
+    release_mem_region(ZTWO_PADDR(dev->base_addr), NE_IO_EXTENT*2);
+    free_netdev(dev);
+}
+
+static int __init zorro8390_init_module(void)
+{
+    return zorro_module_init(&zorro8390_driver);
+}
+
+static void __exit zorro8390_cleanup_module(void)
+{
+    zorro_unregister_driver(&zorro8390_driver);
 }
 
-module_init(zorro8390_probe);
-module_exit(zorro8390_cleanup);
+module_init(zorro8390_init_module);
+module_exit(zorro8390_cleanup_module);
 
 MODULE_LICENSE("GPL");
--- diff/drivers/oprofile/timer_int.c	2003-05-21 11:50:15.000000000 +0100
+++ source/drivers/oprofile/timer_int.c	2004-02-23 13:56:44.000000000 +0000
@@ -10,7 +10,6 @@
 #include <linux/kernel.h>
 #include <linux/notifier.h>
 #include <linux/smp.h>
-#include <linux/irq.h>
 #include <linux/oprofile.h>
 #include <linux/profile.h>
 #include <linux/init.h>
--- diff/drivers/parisc/Kconfig	2004-02-18 08:54:10.000000000 +0000
+++ source/drivers/parisc/Kconfig	2004-02-23 13:56:44.000000000 +0000
@@ -143,24 +143,6 @@ config PDC_CHASSIS
 	  This has nothing to do with Chassis LCD and LED support.
 	  
 	  If unsure, say Y.
- 
-config HOTPLUG
-	bool "Support for hot-pluggable devices"
-	---help---
-	  Say Y here if you want to plug devices into your computer while
-	  the system is running, and be able to use them quickly.  In many
-	  cases, the devices can likewise be unplugged at any time too.
-
-	  One well known example of this is PCMCIA- or PC-cards, credit-card
-	  size devices such as network cards, modems or hard drives which are
-	  plugged into slots found on all modern laptop computers.  Another
-	  example, used on modern desktops as well as laptops, is USB.
-
-	  Enable HOTPLUG and KMOD, and build a modular kernel.  Get agent
-	  software (at <http://linux-hotplug.sourceforge.net/>) and install it.
-	  Then your kernel will automatically call out to a user mode "policy
-	  agent" (/sbin/hotplug) to load modules and set up software needed
-	  to use devices as you hotplug them.
 
 source "drivers/pcmcia/Kconfig"
 
--- diff/drivers/parisc/dino.c	2004-02-18 08:54:10.000000000 +0000
+++ source/drivers/parisc/dino.c	2004-02-23 13:56:44.000000000 +0000
@@ -475,7 +475,7 @@ dino_card_setup(struct pci_bus *bus, uns
 
 	res = &dino_dev->hba.lmmio_space;
 	res->flags = IORESOURCE_MEM;
-	size = snprintf(name, sizeof(name), "Dino LMMIO (%s)", bus->bridge->bus_id);
+	size = scnprintf(name, sizeof(name), "Dino LMMIO (%s)", bus->bridge->bus_id);
 	res->name = kmalloc(size+1, GFP_KERNEL);
 	if(res->name)
 		strcpy((char *)res->name, name);
--- diff/drivers/parport/Kconfig	2003-09-30 15:46:16.000000000 +0100
+++ source/drivers/parport/Kconfig	2004-02-23 13:56:44.000000000 +0000
@@ -102,7 +102,7 @@ config PARPORT_AMIGA
 
 config PARPORT_MFC3
 	tristate "Multiface III parallel port"
-	depends on AMIGA && ZORRO && PARPORT
+	depends on ZORRO && PARPORT
 	help
 	  Say Y here if you need parallel port support for the MFC3 card.
 	  This code is also available as a module (say M), called
--- diff/drivers/parport/Makefile	2003-02-13 11:46:53.000000000 +0000
+++ source/drivers/parport/Makefile	2004-02-23 13:56:44.000000000 +0000
@@ -2,7 +2,7 @@
 # Makefile for the kernel Parallel port device drivers.
 #
 
-parport-objs	:= share.o ieee1284.o ieee1284_ops.o init.o procfs.o
+parport-objs	:= share.o ieee1284.o ieee1284_ops.o procfs.o
 
 ifeq ($(CONFIG_PARPORT_1284),y)
 	parport-objs	+= daisy.o probe.o
--- diff/drivers/parport/daisy.c	2004-02-18 08:54:10.000000000 +0000
+++ source/drivers/parport/daisy.c	2004-02-23 13:56:44.000000000 +0000
@@ -19,6 +19,7 @@
  * published by the Free Software Foundation.
  */
 
+#include <linux/module.h>
 #include <linux/parport.h>
 #include <linux/delay.h>
 #include <linux/sched.h>
@@ -79,6 +80,7 @@ static struct parport *clone_parport (st
 		extra->portnum = real->portnum;
 		extra->physport = real;
 		extra->muxport = muxport;
+		real->slaves[muxport-1] = extra;
 	}
 
 	return extra;
@@ -93,7 +95,9 @@ int parport_daisy_init (struct parport *
 	static const char *th[] = { /*0*/"th", "st", "nd", "rd", "th" };
 	int num_ports;
 	int i;
+	int last_try = 0;
 
+again:
 	/* Because this is called before any other devices exist,
 	 * we don't have to claim exclusive access.  */
 
@@ -126,7 +130,7 @@ int parport_daisy_init (struct parport *
 			/* Analyse that port too.  We won't recurse
 			   forever because of the 'port->muxport < 0'
 			   test above. */
-			parport_announce_port (extra);
+			parport_daisy_init(extra);
 		}
 	}
 
@@ -148,6 +152,21 @@ int parport_daisy_init (struct parport *
 		kfree (deviceid);
 	}
 
+	if (!detected && !last_try) {
+		/* No devices were detected.  Perhaps they are in some
+                   funny state; let's try to reset them and see if
+                   they wake up. */
+		parport_daisy_fini (port);
+		parport_write_control (port, PARPORT_CONTROL_SELECT);
+		udelay (50);
+		parport_write_control (port,
+				       PARPORT_CONTROL_SELECT |
+				       PARPORT_CONTROL_INIT);
+		udelay (50);
+		last_try = 1;
+		goto again;
+	}
+
 	return detected;
 }
 
@@ -634,3 +653,13 @@ int parport_find_class (parport_device_c
 	spin_unlock(&topology_lock);
 	return res;
 }
+
+EXPORT_SYMBOL(parport_open);
+EXPORT_SYMBOL(parport_close);
+EXPORT_SYMBOL(parport_device_num);
+EXPORT_SYMBOL(parport_device_coords);
+EXPORT_SYMBOL(parport_daisy_deselect_all);
+EXPORT_SYMBOL(parport_daisy_select);
+EXPORT_SYMBOL(parport_daisy_init);
+EXPORT_SYMBOL(parport_find_device);
+EXPORT_SYMBOL(parport_find_class);
--- diff/drivers/parport/ieee1284.c	2003-05-21 11:49:50.000000000 +0100
+++ source/drivers/parport/ieee1284.c	2004-02-23 13:56:44.000000000 +0000
@@ -17,6 +17,7 @@
  */
 
 #include <linux/config.h>
+#include <linux/module.h>
 #include <linux/threads.h>
 #include <linux/parport.h>
 #include <linux/delay.h>
@@ -806,3 +807,15 @@ long parport_set_timeout (struct pardevi
 
 	return old;
 }
+
+/* Exported symbols for modules. */
+
+EXPORT_SYMBOL(parport_negotiate);
+EXPORT_SYMBOL(parport_write);
+EXPORT_SYMBOL(parport_read);
+EXPORT_SYMBOL(parport_ieee1284_wakeup);
+EXPORT_SYMBOL(parport_wait_peripheral);
+EXPORT_SYMBOL(parport_poll_peripheral);
+EXPORT_SYMBOL(parport_wait_event);
+EXPORT_SYMBOL(parport_set_timeout);
+EXPORT_SYMBOL(parport_ieee1284_interrupt);
--- diff/drivers/parport/ieee1284_ops.c	2003-05-21 11:49:50.000000000 +0100
+++ source/drivers/parport/ieee1284_ops.c	2004-02-23 13:56:44.000000000 +0000
@@ -15,6 +15,7 @@
 
 
 #include <linux/config.h>
+#include <linux/module.h>
 #include <linux/parport.h>
 #include <linux/delay.h>
 #include <linux/sched.h>
@@ -908,4 +909,13 @@ size_t parport_ieee1284_epp_read_addr (s
 	return ret;
 }
 
-
+EXPORT_SYMBOL(parport_ieee1284_ecp_write_data);
+EXPORT_SYMBOL(parport_ieee1284_ecp_read_data);
+EXPORT_SYMBOL(parport_ieee1284_ecp_write_addr);
+EXPORT_SYMBOL(parport_ieee1284_write_compat);
+EXPORT_SYMBOL(parport_ieee1284_read_nibble);
+EXPORT_SYMBOL(parport_ieee1284_read_byte);
+EXPORT_SYMBOL(parport_ieee1284_epp_write_data);
+EXPORT_SYMBOL(parport_ieee1284_epp_read_data);
+EXPORT_SYMBOL(parport_ieee1284_epp_write_addr);
+EXPORT_SYMBOL(parport_ieee1284_epp_read_addr);
--- diff/drivers/parport/parport_amiga.c	2003-06-09 14:18:19.000000000 +0100
+++ source/drivers/parport/parport_amiga.c	2004-02-23 13:56:44.000000000 +0000
@@ -234,7 +234,7 @@ static struct parport_operations pp_amig
 
 /* ----------- Initialisation code --------------------------------- */
 
-int __init parport_amiga_init(void)
+static int __init parport_amiga_init(void)
 {
 	struct parport *p;
 	int err;
@@ -262,26 +262,24 @@ int __init parport_amiga_init(void)
 	this_port = p;
 	printk(KERN_INFO "%s: Amiga built-in port using irq\n", p->name);
 	/* XXX: set operating mode */
-	parport_proc_register(p);
-
 	parport_announce_port(p);
 
 	return 0;
 
 out_irq:
-	parport_unregister_port(p);
+	parport_put_port(p);
 out_port:
 	release_mem_region(CIAA_PHYSADDR-1+0x100, 0x100);
 out_mem:
 	return err;
 }
 
-void __exit parport_amiga_exit(void)
+static void __exit parport_amiga_exit(void)
 {
+	parport_remove_port(this_port);
 	if (this_port->irq != PARPORT_IRQ_NONE)
 		free_irq(IRQ_AMIGA_CIAA_FLG, this_port);
-	parport_proc_unregister(this_port);
-	parport_unregister_port(this_port);
+	parport_put_port(this_port);
 	release_mem_region(CIAA_PHYSADDR-1+0x100, 0x100);
 }
 
--- diff/drivers/parport/parport_arc.c	2003-05-21 11:49:55.000000000 +0100
+++ source/drivers/parport/parport_arc.c	2004-02-23 13:56:44.000000000 +0000
@@ -104,7 +104,7 @@ static struct parport_operations parport
 
 /* --- Initialisation code -------------------------------- */
 
-int parport_arc_init(void)
+static int parport_arc_init(void)
 {
 	/* Archimedes hardware provides only one port, at a fixed address */
 	struct parport *p;
@@ -129,10 +129,11 @@ int parport_arc_init(void)
 
 	printk(KERN_INFO "%s: Archimedes on-board port, using irq %d\n",
 	       p->irq);
-	parport_proc_register(p);
 
 	/* Tell the high-level drivers about the port. */
 	parport_announce_port (p);
 
 	return 1;
 }
+
+module_init(parport_arc_init)
--- diff/drivers/parport/parport_atari.c	2003-06-09 14:18:19.000000000 +0100
+++ source/drivers/parport/parport_atari.c	2004-02-23 13:56:44.000000000 +0000
@@ -185,8 +185,7 @@ static struct parport_operations parport
 };
 
 
-int __init
-parport_atari_init(void)
+static int __init parport_atari_init(void)
 {
 	struct parport *p;
 	unsigned long flags;
@@ -208,43 +207,34 @@ parport_atari_init(void)
 					  IRQ_MFP_BUSY, PARPORT_DMA_NONE,
 					  &parport_atari_ops);
 		if (!p)
-			return 0;
+			return -ENODEV;
 		if (request_irq(IRQ_MFP_BUSY, parport_atari_interrupt,
 				IRQ_TYPE_SLOW, p->name, p)) {
-			parport_unregister_port (p);
-			return 0;
+			parport_put_port (p);
+			return -ENODEV;
 		}
 
 		this_port = p;
 		printk(KERN_INFO "%s: Atari built-in port using irq\n", p->name);
-		parport_proc_register(p);
-
 		parport_announce_port (p);
 
-		return 1;
+		return 0;
 	}
-	return 0;
+	return -ENODEV;
 }
 
-#ifdef MODULE
+static void __exit parport_atari_exit(void)
+{
+	parport_remove_port(this_port);
+	if (this_port->irq != PARPORT_IRQ_NONE)
+		free_irq(IRQ_MFP_BUSY, this_port);
+	parport_put_port(this_port);
+}
 
 MODULE_AUTHOR("Andreas Schwab");
 MODULE_DESCRIPTION("Parport Driver for Atari builtin Port");
 MODULE_SUPPORTED_DEVICE("Atari builtin Parallel Port");
 MODULE_LICENSE("GPL");
 
-int
-init_module(void)
-{
-	return parport_atari_init() ? 0 : -ENODEV;
-}
-
-void
-cleanup_module(void)
-{
-	if (this_port->irq != PARPORT_IRQ_NONE)
-		free_irq(IRQ_MFP_BUSY, this_port);
-	parport_proc_unregister(this_port);
-	parport_unregister_port(this_port);
-}
-#endif
+module_init(parport_atari_init)
+module_exit(parport_atari_exit)
--- diff/drivers/parport/parport_gsc.c	2004-02-18 08:54:10.000000000 +0000
+++ source/drivers/parport/parport_gsc.c	2004-02-23 13:56:44.000000000 +0000
@@ -412,7 +412,6 @@ struct parport *__devinit parport_gsc_pr
 	}
 #undef printmode
 	printk("]\n");
-	parport_proc_register(p);
 
 	if (p->irq != PARPORT_IRQ_NONE) {
 		if (request_irq (p->irq, parport_gsc_interrupt,
@@ -483,17 +482,17 @@ static void __devexit parport_remove_chi
 	if (p) {
 		struct parport_gsc_private *priv = p->private_data;
 		struct parport_operations *ops = p->ops;
+		parport_remove_port(p);
 		if (p->dma != PARPORT_DMA_NONE)
 			free_dma(p->dma);
 		if (p->irq != PARPORT_IRQ_NONE)
 			free_irq(p->irq, p);
-		parport_proc_unregister(p);
 		if (priv->dma_buf)
 			pci_free_consistent(priv->dev, PAGE_SIZE,
 					    priv->dma_buf,
 					    priv->dma_handle);
 		kfree (p->private_data);
-		parport_unregister_port(p);
+		parport_put_port(p);
 		kfree (ops); /* hope no-one cached it */
 	}
 }
--- diff/drivers/parport/parport_mfc3.c	2003-06-09 14:18:19.000000000 +0100
+++ source/drivers/parport/parport_mfc3.c	2004-02-23 13:56:44.000000000 +0000
@@ -320,7 +320,7 @@ static struct parport_operations pp_mfc3
 
 /* ----------- Initialisation code --------------------------------- */
 
-int __init parport_mfc3_init(void)
+static int __init parport_mfc3_init(void)
 {
 	struct parport *p;
 	int pias = 0;
@@ -360,7 +360,6 @@ int __init parport_mfc3_init(void)
 		this_port[pias++] = p;
 		printk(KERN_INFO "%s: Multiface III port using irq\n", p->name);
 		/* XXX: set operating mode */
-		parport_proc_register(p);
 
 		p->private_data = (void *)piabase;
 		parport_announce_port (p);
@@ -370,7 +369,7 @@ int __init parport_mfc3_init(void)
 		continue;
 
 	out_irq:
-		parport_unregister_port(p);
+		parport_put_port(p);
 	out_port:
 		release_mem_region(piabase, sizeof(struct pia));
 	}
@@ -378,20 +377,20 @@ int __init parport_mfc3_init(void)
 	return pias ? 0 : -ENODEV;
 }
 
-void __exit parport_mfc3_exit(void)
+static void __exit parport_mfc3_exit(void)
 {
 	int i;
 
 	for (i = 0; i < MAX_MFC; i++) {
 		if (!this_port[i])
 			continue;
+		parport_remove_port(this_port[i]);
 		if (!this_port[i]->irq != PARPORT_IRQ_NONE) {
 			if (--use_cnt == 0) 
 				free_irq(IRQ_AMIGA_PORTS, &pp_mfc3_ops);
 		}
-		parport_proc_unregister(this_port[i]);
-		parport_unregister_port(this_port[i]);
 		release_mem_region(ZTWO_PADDR(this_port[i]->private_data), sizeof(struct pia));
+		parport_put_port(this_port[i]);
 	}
 }
 
@@ -403,4 +402,3 @@ MODULE_LICENSE("GPL");
 
 module_init(parport_mfc3_init)
 module_exit(parport_mfc3_exit)
-
--- diff/drivers/parport/parport_pc.c	2004-02-18 08:54:10.000000000 +0000
+++ source/drivers/parport/parport_pc.c	2004-02-23 13:56:44.000000000 +0000
@@ -2107,6 +2107,9 @@ static int __devinit parport_dma_probe (
 
 /* --- Initialisation code -------------------------------- */
 
+static LIST_HEAD(ports_list);
+static spinlock_t ports_lock = SPIN_LOCK_UNLOCKED;
+
 struct parport *parport_pc_probe_port (unsigned long int base,
 				       unsigned long int base_hi,
 				       int irq, int dma,
@@ -2114,39 +2117,30 @@ struct parport *parport_pc_probe_port (u
 {
 	struct parport_pc_private *priv;
 	struct parport_operations *ops;
-	struct parport tmp;
-	struct parport *p = &tmp;
+	struct parport *p;
 	int probedirq = PARPORT_IRQ_NONE;
 	struct resource *base_res;
 	struct resource	*ECR_res = NULL;
 	struct resource	*EPP_res = NULL;
-	char *fake_name = "parport probe";
 
-	/*
-	 * Chicken and Egg problem.  request_region() wants the name of
-	 * the owner, but this instance will not know that name until
-	 * after the parport_register_port() call.  Give request_region()
-	 * a fake name until after parport_register_port(), then use
-	 * rename_region() to set correct name.
-	 */
-	base_res = request_region(base, 3, fake_name);
-	if (base_res == NULL)
-		return NULL;
+	ops = kmalloc(sizeof (struct parport_operations), GFP_KERNEL);
+	if (!ops)
+		goto out1;
+
 	priv = kmalloc (sizeof (struct parport_pc_private), GFP_KERNEL);
-	if (!priv) {
-		printk (KERN_DEBUG "parport (0x%lx): no memory!\n", base);
-		release_region(base, 3);
-		return NULL;
-	}
-	ops = kmalloc (sizeof (struct parport_operations), GFP_KERNEL);
-	if (!ops) {
-		printk (KERN_DEBUG "parport (0x%lx): no memory for ops!\n",
-			base);
-		release_region(base, 3);
-		kfree (priv);
-		return NULL;
-	}
-	memcpy (ops, &parport_pc_ops, sizeof (struct parport_operations));
+	if (!priv)
+		goto out2;
+
+	/* a misnomer, actually - it's allocate and reserve parport number */
+	p = parport_register_port(base, irq, dma, ops);
+	if (!p)
+		goto out3;
+
+	base_res = request_region(base, 3, p->name);
+	if (!base_res)
+		goto out4;
+
+	memcpy(ops, &parport_pc_ops, sizeof (struct parport_operations));
 	priv->ctr = 0xc;
 	priv->ctr_writable = ~0x10;
 	priv->ecr = 0;
@@ -2154,59 +2148,37 @@ struct parport *parport_pc_probe_port (u
 	priv->dma_buf = 0;
 	priv->dma_handle = 0;
 	priv->dev = dev;
-	p->base = base;
+	INIT_LIST_HEAD(&priv->list);
+	priv->port = p;
 	p->base_hi = base_hi;
-	p->irq = irq;
-	p->dma = dma;
 	p->modes = PARPORT_MODE_PCSPP | PARPORT_MODE_SAFEININT;
-	p->ops = ops;
 	p->private_data = priv;
-	p->physport = p;
 
 	if (base_hi) {
-		ECR_res = request_region(base_hi, 3, fake_name);
+		ECR_res = request_region(base_hi, 3, p->name);
 		if (ECR_res)
 			parport_ECR_present(p);
 	}
 
 	if (base != 0x3bc) {
-		EPP_res = request_region(base+0x3, 5, fake_name);
+		EPP_res = request_region(base+0x3, 5, p->name);
 		if (EPP_res)
 			if (!parport_EPP_supported(p))
 				parport_ECPEPP_supported(p);
 	}
 	if (!parport_SPP_supported (p))
 		/* No port. */
-		goto errout;
+		goto out5;
 	if (priv->ecr)
 		parport_ECPPS2_supported(p);
 	else
-		parport_PS2_supported (p);
+		parport_PS2_supported(p);
 
-	if (!(p = parport_register_port(base, PARPORT_IRQ_NONE,
-					PARPORT_DMA_NONE, ops)))
-		goto errout;
-
-	/*
-	 * Now the real name is known... Replace the fake name
-	 * in the resources with the correct one.
-	 */
-	rename_region(base_res, p->name);
-	if (ECR_res)
-		rename_region(ECR_res, p->name);
-	if (EPP_res)
-		rename_region(EPP_res, p->name);
-
-	p->base_hi = base_hi;
-	p->modes = tmp.modes;
 	p->size = (p->modes & PARPORT_MODE_EPP)?8:3;
-	p->private_data = priv;
 
 	printk(KERN_INFO "%s: PC-style at 0x%lx", p->name, p->base);
 	if (p->base_hi && priv->ecr)
 		printk(" (0x%lx)", p->base_hi);
-	p->irq = irq;
-	p->dma = dma;
 	if (p->irq == PARPORT_IRQ_AUTO) {
 		p->irq = PARPORT_IRQ_NONE;
 		parport_irq_probe(p);
@@ -2269,7 +2241,6 @@ struct parport *parport_pc_probe_port (u
 	printk("]\n");
 	if (probedirq != PARPORT_IRQ_NONE) 
 		printk(KERN_INFO "%s: irq %d detected\n", p->name, probedirq);
-	parport_proc_register(p);
 
 	/* If No ECP release the ports grabbed above. */
 	if (ECR_res && (p->modes & PARPORT_MODE_ECP) == 0) {
@@ -2330,28 +2301,40 @@ struct parport *parport_pc_probe_port (u
 	/* Now that we've told the sharing engine about the port, and
 	   found out its characteristics, let the high-level drivers
 	   know about it. */
+	spin_lock(&ports_lock);
+	list_add(&priv->list, &ports_list);
+	spin_unlock(&ports_lock);
 	parport_announce_port (p);
 
 	return p;
 
-errout:
-	release_region(p->base, 3);
+out5:
 	if (ECR_res)
 		release_region(base_hi, 3);
 	if (EPP_res)
 		release_region(base+0x3, 5);
-
+	release_region(base, 3);
+out4:
+	parport_put_port(p);
+out3:
 	kfree (priv);
+out2:
 	kfree (ops);
+out1:
 	return NULL;
 }
 
+EXPORT_SYMBOL (parport_pc_probe_port);
+
 void parport_pc_unregister_port (struct parport *p)
 {
-#ifdef CONFIG_PARPORT_PC_FIFO
 	struct parport_pc_private *priv = p->private_data;
-#endif /* CONFIG_PARPORT_PC_FIFO */
 	struct parport_operations *ops = p->ops;
+
+	parport_remove_port(p);
+	spin_lock(&ports_lock);
+	list_del_init(&priv->list);
+	spin_unlock(&ports_lock);
 	if (p->dma != PARPORT_DMA_NONE)
 		free_dma(p->dma);
 	if (p->irq != PARPORT_IRQ_NONE)
@@ -2361,7 +2344,6 @@ void parport_pc_unregister_port (struct 
 		release_region(p->base + 3, p->size - 3);
 	if (p->modes & PARPORT_MODE_ECP)
 		release_region(p->base_hi, 3);
-	parport_proc_unregister(p);
 #ifdef CONFIG_PARPORT_PC_FIFO
 	if (priv->dma_buf)
 		pci_free_consistent(priv->dev, PAGE_SIZE,
@@ -2369,10 +2351,12 @@ void parport_pc_unregister_port (struct 
 				    priv->dma_handle);
 #endif /* CONFIG_PARPORT_PC_FIFO */
 	kfree (p->private_data);
-	parport_unregister_port(p);
+	parport_put_port(p);
 	kfree (ops); /* hope no-one cached it */
 }
 
+EXPORT_SYMBOL (parport_pc_unregister_port);
+
 #ifdef CONFIG_PCI
 
 /* ITE support maintained by Rich Liu <richliu@poorman.org> */
@@ -2931,45 +2915,57 @@ static int __init parport_pc_find_ports 
 	return count;
 }
 
-int __init parport_pc_init (int *io, int *io_hi, int *irq, int *dma)
-{
-	int count = 0, i = 0;
-	/* try to activate any PnP parports first */
-	pnp_register_driver(&parport_pc_pnp_driver);
+/*
+ *	Piles of crap below pretend to be a parser for module and kernel
+ *	parameters.  Say "thank you" to whoever had come up with that
+ *	syntax and keep in mind that code below is a cleaned up version.
+ */
 
-	if (io && *io) {
-		/* Only probe the ports we were given. */
-		user_specified = 1;
-		do {
-			if ((*io_hi) == PARPORT_IOHI_AUTO)
-			       *io_hi = 0x400 + *io;
-			if (parport_pc_probe_port(*(io++), *(io_hi++),
-						  *(irq++), *(dma++), NULL))
-				count++;
-		} while (*io && (++i < PARPORT_PC_MAX_PORTS));
-	} else {
-		count += parport_pc_find_ports (irq[0], dma[0]);
+static int __initdata io[PARPORT_PC_MAX_PORTS+1] = { [0 ... PARPORT_PC_MAX_PORTS] = 0 };
+static int __initdata io_hi[PARPORT_PC_MAX_PORTS+1] =
+	{ [0 ... PARPORT_PC_MAX_PORTS] = PARPORT_IOHI_AUTO };
+static int __initdata dmaval[PARPORT_PC_MAX_PORTS] = { [0 ... PARPORT_PC_MAX_PORTS-1] = PARPORT_DMA_NONE };
+static int __initdata irqval[PARPORT_PC_MAX_PORTS] = { [0 ... PARPORT_PC_MAX_PORTS-1] = PARPORT_IRQ_PROBEONLY };
+
+static int __init parport_parse_param(const char *s, int *val,
+				int automatic, int none, int nofifo)
+{
+	if (!s)
+		return 0;
+	if (!strncmp(s, "auto", 4))
+		*val = automatic;
+	else if (!strncmp(s, "none", 4))
+		*val = none;
+	else if (nofifo && !strncmp(s, "nofifo", 4))
+		*val = nofifo;
+	else {
+		char *ep;
+		unsigned long r = simple_strtoul(s, &ep, 0);
+		if (ep != s)
+			*val = r;
+		else {
+			printk(KERN_ERR "parport: bad specifier `%s'\n", s);
+			return -1;
+		}
 	}
+	return 0;
+}
 
-	return count;
+static int __init parport_parse_irq(const char *irqstr, int *val)
+{
+	return parport_parse_param(irqstr, val, PARPORT_IRQ_AUTO,
+				     PARPORT_IRQ_NONE, 0);
 }
 
-/* Exported symbols. */
-EXPORT_SYMBOL (parport_pc_probe_port);
-EXPORT_SYMBOL (parport_pc_unregister_port);
+static int __init parport_parse_dma(const char *dmastr, int *val)
+{
+	return parport_parse_param(dmastr, val, PARPORT_DMA_AUTO,
+				     PARPORT_DMA_NONE, PARPORT_DMA_NOFIFO);
+}
 
 #ifdef MODULE
-static int io[PARPORT_PC_MAX_PORTS+1] = { [0 ... PARPORT_PC_MAX_PORTS] = 0 };
-static int io_hi[PARPORT_PC_MAX_PORTS+1] =
-	{ [0 ... PARPORT_PC_MAX_PORTS] = PARPORT_IOHI_AUTO };
-static int dmaval[PARPORT_PC_MAX_PORTS] = { [0 ... PARPORT_PC_MAX_PORTS-1] = PARPORT_DMA_NONE };
-static int irqval[PARPORT_PC_MAX_PORTS] = { [0 ... PARPORT_PC_MAX_PORTS-1] = PARPORT_IRQ_PROBEONLY };
-static const char *irq[PARPORT_PC_MAX_PORTS] = { NULL, };
-static const char *dma[PARPORT_PC_MAX_PORTS] = { NULL, };
-
-MODULE_AUTHOR("Phil Blundell, Tim Waugh, others");
-MODULE_DESCRIPTION("PC-style parallel port driver");
-MODULE_LICENSE("GPL");
+static const char *irq[PARPORT_PC_MAX_PORTS];
+static const char *dma[PARPORT_PC_MAX_PORTS];
 
 MODULE_PARM_DESC(io, "Base I/O address (SPP regs)");
 MODULE_PARM(io, "1-" __MODULE_STRING(PARPORT_PC_MAX_PORTS) "i");
@@ -2985,22 +2981,22 @@ MODULE_PARM_DESC(verbose_probing, "Log c
 MODULE_PARM(verbose_probing, "i");
 #endif
 
-int init_module(void)
-{	
-	/* Work out how many ports we have, then get parport_share to parse
-	   the irq values. */
+static int __init parse_parport_params(void)
+{
 	unsigned int i;
-	int ret;
-	for (i = 0; i < PARPORT_PC_MAX_PORTS && io[i]; i++);
-	if (i) {
-		if (parport_parse_irqs(i, irq, irqval)) return 1;
-		if (parport_parse_dmas(i, dma, dmaval)) return 1;
+	int val;
+
+	for (i = 0; i < PARPORT_PC_MAX_PORTS && io[i]; i++) {
+		if (parport_parse_irq(irq[i], &val))
+			return 1;
+		irqval[i] = val;
+		if (parport_parse_dma(dma[i], &val))
+			return 1;
+		dmaval[i] = val;
 	}
-	else {
+	if (!io[0]) {
 		/* The user can make us use any IRQs or DMAs we find. */
-		int val;
-
-		if (irq[0] && !parport_parse_irqs (1, irq, &val))
+		if (irq[0] && !parport_parse_irq(irq[0], &val))
 			switch (val) {
 			case PARPORT_IRQ_NONE:
 			case PARPORT_IRQ_AUTO:
@@ -3013,7 +3009,7 @@ int init_module(void)
 					"to specify one\n");
 			}
 
-		if (dma[0] && !parport_parse_dmas (1, dma, &val))
+		if (dma[0] && !parport_parse_dma(dma[0], &val))
 			switch (val) {
 			case PARPORT_DMA_NONE:
 			case PARPORT_DMA_AUTO:
@@ -3026,29 +3022,144 @@ int init_module(void)
 					"to specify one\n");
 			}
 	}
+	return 0;
+}
 
-	ret = !parport_pc_init (io, io_hi, irqval, dmaval);
-	if (ret && registered_parport)
-		pci_unregister_driver (&parport_pc_pci_driver);
+#else
 
-	return ret;
+static int parport_setup_ptr __initdata = 0;
+
+/*
+ * Acceptable parameters:
+ *
+ * parport=0
+ * parport=auto
+ * parport=0xBASE[,IRQ[,DMA]]
+ *
+ * IRQ/DMA may be numeric or 'auto' or 'none'
+ */
+static int __init parport_setup (char *str)
+{
+	char *endptr;
+	char *sep;
+	int val;
+
+	if (!str || !*str || (*str == '0' && !*(str+1))) {
+		/* Disable parport if "parport=0" in cmdline */
+		io[0] = PARPORT_DISABLE;
+		return 1;
+	}
+
+	if (!strncmp (str, "auto", 4)) {
+		irqval[0] = PARPORT_IRQ_AUTO;
+		dmaval[0] = PARPORT_DMA_AUTO;
+		return 1;
+	}
+
+	val = simple_strtoul (str, &endptr, 0);
+	if (endptr == str) {
+		printk (KERN_WARNING "parport=%s not understood\n", str);
+		return 1;
+	}
+
+	if (parport_setup_ptr == PARPORT_PC_MAX_PORTS) {
+		printk(KERN_ERR "parport=%s ignored, too many ports\n", str);
+		return 1;
+	}
+
+	io[parport_setup_ptr] = val;
+	irqval[parport_setup_ptr] = PARPORT_IRQ_NONE;
+	dmaval[parport_setup_ptr] = PARPORT_DMA_NONE;
+
+	sep = strchr(str, ',');
+	if (sep++) {
+		if (parport_parse_irq(sep, &val))
+			return 1;
+		irqval[parport_setup_ptr] = val;
+		sep = strchr(sep, ',');
+		if (sep++) {
+			if (parport_parse_dma(sep, &val))
+				return 1;
+			dmaval[parport_setup_ptr] = val;
+		}
+	}
+	parport_setup_ptr++;
+	return 1;
 }
 
-void cleanup_module(void)
+static int __init parse_parport_params(void)
 {
-	/* We ought to keep track of which ports are actually ours. */
-	struct parport *p = parport_enumerate(), *tmp;
+	return io[0] == PARPORT_DISABLE;
+}
 
-	if (!user_specified)
-		pci_unregister_driver (&parport_pc_pci_driver);
+__setup ("parport=", parport_setup);
+#endif
 
-	while (p) {
-		tmp = p->next;
-		if (p->modes & PARPORT_MODE_PCSPP)
-			parport_pc_unregister_port (p);
+/* "Parser" ends here */
 
-		p = tmp;
+static int __init parport_pc_init(void)
+{
+	int count = 0;
+
+	if (parse_parport_params())
+		return -EINVAL;
+
+	/* try to activate any PnP parports first */
+	pnp_register_driver(&parport_pc_pnp_driver);
+
+	if (io[0]) {
+		int i;
+		/* Only probe the ports we were given. */
+		user_specified = 1;
+		for (i = 0; i < PARPORT_PC_MAX_PORTS; i++) {
+			if (!io[i])
+				break;
+			if ((io_hi[i]) == PARPORT_IOHI_AUTO)
+			       io_hi[i] = 0x400 + io[i];
+			if (parport_pc_probe_port(io[i], io_hi[i],
+						  irqval[i], dmaval[i], NULL))
+				count++;
+		}
+	} else {
+		count += parport_pc_find_ports (irqval[0], dmaval[0]);
+		if (!count && registered_parport)
+			pci_unregister_driver (&parport_pc_pci_driver);
+	}
+
+	if (!count) {
+		pnp_unregister_driver (&parport_pc_pnp_driver);
+		return -ENODEV;
+	}
+
+	return 0;
+}
+
+static void __exit parport_pc_exit(void)
+{
+	if (registered_parport)
+		pci_unregister_driver (&parport_pc_pci_driver);
+
+	spin_lock(&ports_lock);
+	while (!list_empty(&ports_list)) {
+		struct parport_pc_private *priv;
+		struct parport *port;
+		priv = list_entry(ports_list.next,
+				  struct parport_pc_private, list);
+		port = priv->port;
+		spin_unlock(&ports_lock);
+		parport_pc_unregister_port(port);
+		spin_lock(&ports_lock);
 	}
+	spin_unlock(&ports_lock);
 	pnp_unregister_driver (&parport_pc_pnp_driver);
 }
-#endif
+
+
+MODULE_AUTHOR("Phil Blundell, Tim Waugh, others");
+MODULE_DESCRIPTION("PC-style parallel port driver");
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Phil Blundell, Tim Waugh, others");
+MODULE_DESCRIPTION("PC-style parallel port driver");
+MODULE_LICENSE("GPL");
+module_init(parport_pc_init)
+module_exit(parport_pc_exit)
--- diff/drivers/parport/parport_sunbpp.c	2004-01-19 10:22:58.000000000 +0000
+++ source/drivers/parport/parport_sunbpp.c	2004-02-23 13:56:44.000000000 +0000
@@ -286,39 +286,49 @@ static struct parport_operations parport
 	.owner		= THIS_MODULE,
 };
 
+typedef struct {
+	struct list_head list;
+	struct parport *port;
+} Node;
+/* no locks, everything's serialized */
+static LIST_HEAD(port_list);
+
 static int __init init_one_port(struct sbus_dev *sdev)
 {
 	struct parport *p;
 	/* at least in theory there may be a "we don't dma" case */
 	struct parport_operations *ops;
 	unsigned long base;
-	int irq, dma, err, size;
+	int irq, dma, err = 0, size;
 	struct bpp_regs *regs;
 	unsigned char value_tcr;
+	Node *node;
 
 	dprintk((KERN_DEBUG "init_one_port(%p): ranges, alloc_io, ", sdev));
+	node = kmalloc(sizeof(Node), GFP_KERNEL);
+	if (!node)
+		goto out0;
+
 	irq = sdev->irqs[0];
 	base = sbus_ioremap(&sdev->resource[0], 0,
 			    sdev->reg_addrs[0].reg_size, 
 			    "sunbpp");
+	if (!base)
+		goto out1;
+
 	size = sdev->reg_addrs[0].reg_size;
 	dma = PARPORT_DMA_NONE;
 
 	dprintk(("alloc(ppops), "));
 	ops = kmalloc (sizeof (struct parport_operations), GFP_KERNEL);
-        if (!ops) {
-		sbus_iounmap(base, size);
-		return 0;
-        }
+        if (!ops)
+		goto out2;
 
         memcpy (ops, &parport_sunbpp_ops, sizeof (struct parport_operations));
 
 	dprintk(("register_port\n"));
-	if (!(p = parport_register_port(base, irq, dma, ops))) {
-		kfree(ops);
-		sbus_iounmap(base, size);
-		return 0;
-	}
+	if (!(p = parport_register_port(base, irq, dma, ops)))
+		goto out3;
 
 	p->size = size;
 
@@ -327,14 +337,10 @@ static int __init init_one_port(struct s
 	if ((err = request_irq(p->irq, parport_sunbpp_interrupt,
 			       SA_SHIRQ, p->name, p)) != 0) {
 		dprintk(("ERROR %d\n", err));
-		parport_unregister_port(p);
-		kfree(ops);
-		sbus_iounmap(base, size);
-		return err;
-	} else {
-		dprintk(("OK\n"));
-		parport_sunbpp_enable_irq(p);
+		goto out4;
 	}
+	dprintk(("OK\n"));
+	parport_sunbpp_enable_irq(p);
 
 	regs = (struct bpp_regs *)p->base;
 	dprintk((KERN_DEBUG "forward\n"));
@@ -343,17 +349,25 @@ static int __init init_one_port(struct s
 	sbus_writeb(value_tcr, &regs->p_tcr);
 
 	printk(KERN_INFO "%s: sunbpp at 0x%lx\n", p->name, p->base);
-	parport_proc_register(p);
+	node->port = p;
+	list_add(&node->list, &port_list);
 	parport_announce_port (p);
 
 	return 1;
+
+out4:
+	parport_put_port(p);
+out3:
+	kfree(ops);
+out2:
+	sbus_iounmap(base, size);
+out1:
+	kfree(node);
+out0:
+	return err;
 }
 
-#ifdef MODULE
-int init_module(void)
-#else
-int __init parport_sunbpp_init(void)
-#endif
+static int __init parport_sunbpp_init(void)
 {
         struct sbus_bus *sbus;
         struct sbus_dev *sdev;
@@ -368,34 +382,30 @@ int __init parport_sunbpp_init(void)
 	return count ? 0 : -ENODEV;
 }
 
-#ifdef MODULE
-MODULE_AUTHOR("Derrick J Brashear");
-MODULE_DESCRIPTION("Parport Driver for Sparc bidirectional Port");
-MODULE_SUPPORTED_DEVICE("Sparc Bidirectional Parallel Port");
-
-void
-cleanup_module(void)
+static void __exit parport_sunbpp_exit(void)
 {
-	struct parport *p = parport_enumerate();
-
-	while (p) {
-		struct parport *next = p->next;
-
-		if (1/*p->modes & PARPORT_MODE_PCSPP*/) { 
-			struct parport_operations *ops = p->ops;
-
-			if (p->irq != PARPORT_IRQ_NONE) {
-				parport_sunbpp_disable_irq(p);
-				free_irq(p->irq, p);
-			}
-			sbus_iounmap(p->base, p->size);
-			parport_proc_unregister(p);
-			parport_unregister_port(p);
-			kfree (ops);
+	while (!list_empty(port_list)) {
+		Node *node = list_entry(port_list.next, Node, list);
+		struct parport *p = node->port;
+		struct parport_operations *ops = p->ops;
+		parport_remove_port(p);
+
+		if (p->irq != PARPORT_IRQ_NONE) {
+			parport_sunbpp_disable_irq(p);
+			free_irq(p->irq, p);
 		}
-		p = next;
+		sbus_iounmap(p->base, p->size);
+		parport_put_port(p);
+		kfree (ops);
+		list_del(&node->list);
+		kfree (node);
 	}
 }
-#endif
 
+MODULE_AUTHOR("Derrick J Brashear");
+MODULE_DESCRIPTION("Parport Driver for Sparc bidirectional Port");
+MODULE_SUPPORTED_DEVICE("Sparc Bidirectional Parallel Port");
 MODULE_LICENSE("GPL");
+
+module_init(parport_sunbpp_init)
+module_exit(parport_sunbpp_exit)
--- diff/drivers/parport/probe.c	2002-12-11 11:50:25.000000000 +0000
+++ source/drivers/parport/probe.c	2004-02-23 13:56:44.000000000 +0000
@@ -5,6 +5,7 @@
  *             Philip Blundell <Philip.Blundell@pobox.com>
  */
 
+#include <linux/module.h>
 #include <linux/parport.h>
 #include <linux/ctype.h>
 #include <linux/string.h>
@@ -212,3 +213,4 @@ ssize_t parport_device_id (int devnum, c
 	parport_close (dev);
 	return retval;
 }
+EXPORT_SYMBOL(parport_device_id);
--- diff/drivers/parport/procfs.c	2002-10-16 04:27:23.000000000 +0100
+++ source/drivers/parport/procfs.c	2004-02-23 13:56:44.000000000 +0000
@@ -14,6 +14,8 @@
 
 #include <linux/string.h>
 #include <linux/config.h>
+#include <linux/init.h>
+#include <linux/module.h>
 #include <linux/errno.h>
 #include <linux/kernel.h>
 #include <linux/slab.h>
@@ -479,21 +481,20 @@ int parport_device_proc_unregister(struc
 	return 0;
 }
 
-int parport_default_proc_register(void)
+static int __init parport_default_proc_register(void)
 {
 	parport_default_sysctl_table.sysctl_header =
 		register_sysctl_table(parport_default_sysctl_table.dev_dir, 0);
 	return 0;
 }
 
-int parport_default_proc_unregister(void)
+static void __exit parport_default_proc_unregister(void)
 {
 	if (parport_default_sysctl_table.sysctl_header) {
 		unregister_sysctl_table(parport_default_sysctl_table.
 					sysctl_header);
 		parport_default_sysctl_table.sysctl_header = NULL;
 	}
-	return 0;
 }
 
 #else /* no sysctl or no procfs*/
@@ -518,13 +519,19 @@ int parport_device_proc_unregister(struc
 	return 0;
 }
 
-int parport_default_proc_register (void)
+static int __init parport_default_proc_register (void)
 {
 	return 0;
 }
 
-int parport_default_proc_unregister (void)
+static void __exit parport_default_proc_unregister (void)
 {
 	return 0;
 }
 #endif
+
+EXPORT_SYMBOL(parport_device_proc_register);
+EXPORT_SYMBOL(parport_device_proc_unregister);
+
+module_init(parport_default_proc_register)
+module_exit(parport_default_proc_unregister)
--- diff/drivers/parport/share.c	2004-02-18 08:54:10.000000000 +0000
+++ source/drivers/parport/share.c	2004-02-23 13:56:44.000000000 +0000
@@ -41,14 +41,14 @@
 unsigned long parport_default_timeslice = PARPORT_DEFAULT_TIMESLICE;
 int parport_default_spintime =  DEFAULT_SPIN_TIME;
 
-static struct parport *portlist = NULL, *portlist_tail = NULL;
+static LIST_HEAD(portlist);
 static spinlock_t parportlist_lock = SPIN_LOCK_UNLOCKED;
 
 /* list of all allocated ports, sorted by ->number */
 static LIST_HEAD(all_ports);
 static spinlock_t full_list_lock = SPIN_LOCK_UNLOCKED;
 
-static struct parport_driver *driver_chain = NULL;
+static LIST_HEAD(drivers);
 
 static DECLARE_MUTEX(registration_lock);
 
@@ -105,16 +105,16 @@ static void attach_driver_chain(struct p
 {
 	/* caller has exclusive registration_lock */
 	struct parport_driver *drv;
-	for (drv = driver_chain; drv; drv = drv->next)
+	list_for_each_entry(drv, &drivers, list)
 		drv->attach(port);
 }
 
 /* Call detach(port) for each registered driver. */
 static void detach_driver_chain(struct parport *port)
 {
-	/* caller has exclusive registration_lock */
 	struct parport_driver *drv;
-	for (drv = driver_chain; drv; drv = drv->next)
+	/* caller has exclusive registration_lock */
+	list_for_each_entry(drv, &drivers, list)
 		drv->detach (port);
 }
 
@@ -155,22 +155,13 @@ int parport_register_driver (struct parp
 {
 	struct parport *port;
 
-	if (!portlist)
+	if (list_empty(&portlist))
 		get_lowlevel_driver ();
 
-	/* We have to take the portlist lock for this to be sure
-	 * that port is valid for the duration of the callback. */
-
-	/* This is complicated by the fact that attach must be allowed
-	 * to block, so we can't be holding any spinlocks when we call
-	 * it.  But we need to hold a spinlock to iterate over the
-	 * list of ports.. */
-
 	down(&registration_lock);
-	for (port = portlist; port; port = port->next)
+	list_for_each_entry(port, &portlist, list)
 		drv->attach(port);
-	drv->next = driver_chain;
-	driver_chain = drv;
+	list_add(&drv->list, &drivers);
 	up(&registration_lock);
 
 	return 0;
@@ -193,33 +184,14 @@ int parport_register_driver (struct parp
  *	finished by the time this function returns.
  **/
 
-void parport_unregister_driver (struct parport_driver *arg)
+void parport_unregister_driver (struct parport_driver *drv)
 {
-	struct parport_driver *drv, *olddrv = NULL;
+	struct parport *port;
 
 	down(&registration_lock);
-	drv = driver_chain;
-	while (drv) {
-		if (drv == arg) {
-			struct parport *port;
-
-			if (olddrv)
-				olddrv->next = drv->next;
-			else
-				driver_chain = drv->next;
-
-			/* Call the driver's detach routine for each
-			 * port to clean up any resources that the
-			 * attach routine acquired. */
-			for (port = portlist; port; port = port->next)
-				drv->detach (port);
-			up(&registration_lock);
-
-			return;
-		}
-		olddrv = drv;
-		drv = drv->next;
-	}
+	list_del_init(&drv->list);
+	list_for_each_entry(port, &portlist, list)
+		drv->detach(port);
 	up(&registration_lock);
 }
 
@@ -278,28 +250,6 @@ void parport_put_port (struct parport *p
 }
 
 /**
- *	parport_enumerate - return a list of the system's parallel ports
- *
- *	This returns the head of the list of parallel ports in the
- *	system, as a &struct parport.  The structure that is returned
- *	describes the first port in the list, and its 'next' member
- *	points to the next port, or %NULL if it's the last port.
- *
- *	If there are no parallel ports in the system,
- *	parport_enumerate() will return %NULL.
- **/
-
-struct parport *parport_enumerate(void)
-{
-	/* Don't use this: use parport_register_driver instead. */
-
-	if (!portlist)
-		get_lowlevel_driver ();
-
-	return portlist;
-}
-
-/**
  *	parport_register_port - register a parallel port
  *	@base: base I/O address
  *	@irq: IRQ line
@@ -322,7 +272,7 @@ struct parport *parport_enumerate(void)
  *	parport_announce_port().
  *
  *	The @ops structure is allocated by the caller, and must not be
- *	deallocated before calling parport_unregister_port().
+ *	deallocated before calling parport_remove_port().
  *
  *	If there is no memory to allocate a new parport structure,
  *	this function will return %NULL.
@@ -350,7 +300,7 @@ struct parport *parport_register_port(un
 	tmp->dma = dma;
 	tmp->muxport = tmp->daisy = tmp->muxsel = -1;
 	tmp->modes = 0;
- 	tmp->next = NULL;
+ 	INIT_LIST_HEAD(&tmp->list);
 	tmp->devices = tmp->cad = NULL;
 	tmp->flags = 0;
 	tmp->ops = ops;
@@ -413,49 +363,36 @@ struct parport *parport_register_port(un
 
 void parport_announce_port (struct parport *port)
 {
+	int i;
 
 #ifdef CONFIG_PARPORT_1284
 	/* Analyse the IEEE1284.3 topology of the port. */
-	if (parport_daisy_init (port) == 0) {
-		/* No devices were detected.  Perhaps they are in some
-                   funny state; let's try to reset them and see if
-                   they wake up. */
-		parport_daisy_fini (port);
-		parport_write_control (port, PARPORT_CONTROL_SELECT);
-		udelay (50);
-		parport_write_control (port,
-				       PARPORT_CONTROL_SELECT |
-				       PARPORT_CONTROL_INIT);
-		udelay (50);
-		parport_daisy_init (port);
-	}
+	parport_daisy_init(port);
 #endif
 
+	parport_proc_register(port);
 	down(&registration_lock);
-	/* We are locked against anyone else performing alterations, but
-	 * because of parport_enumerate people can still _read_ the list
-	 * while we are changing it; so be careful..
-	 *
-	 * It's okay to have portlist_tail a little bit out of sync
-	 * since it's only used for changing the list, not for reading
-	 * from it.
-	 */
-
 	spin_lock_irq(&parportlist_lock);
-	if (portlist_tail)
-		portlist_tail->next = port;
-	portlist_tail = port;
-	if (!portlist)
-		portlist = port;
+	list_add_tail(&port->list, &portlist);
+	for (i = 1; i < 3; i++) {
+		struct parport *slave = port->slaves[i-1];
+		if (slave)
+			list_add_tail(&slave->list, &portlist);
+	}
 	spin_unlock_irq(&parportlist_lock);
 
-	/* Let drivers know that a new port has arrived. */
+	/* Let drivers know that new port(s) has arrived. */
 	attach_driver_chain (port);
+	for (i = 1; i < 3; i++) {
+		struct parport *slave = port->slaves[i-1];
+		if (slave)
+			attach_driver_chain(slave);
+	}
 	up(&registration_lock);
 }
 
 /**
- *	parport_unregister_port - deregister a parallel port
+ *	parport_remove_port - deregister a parallel port
  *	@port: parallel port to deregister
  *
  *	When a parallel port driver is forcibly unloaded, or a
@@ -473,44 +410,46 @@ void parport_announce_port (struct parpo
  *	with @port as the parameter.
  **/
 
-void parport_unregister_port(struct parport *port)
+void parport_remove_port(struct parport *port)
 {
-	struct parport *p;
+	int i;
 
 	down(&registration_lock);
-	port->ops = &dead_ops;
 
 	/* Spread the word. */
 	detach_driver_chain (port);
 
 #ifdef CONFIG_PARPORT_1284
 	/* Forget the IEEE1284.3 topology of the port. */
-	parport_daisy_fini (port);
+	parport_daisy_fini(port);
+	for (i = 1; i < 3; i++) {
+		struct parport *slave = port->slaves[i-1];
+		if (!slave)
+			continue;
+		detach_driver_chain(slave);
+		parport_daisy_fini(slave);
+	}
 #endif
 
+	port->ops = &dead_ops;
 	spin_lock(&parportlist_lock);
-
-	/* We are protected from other people changing the list, but
-	 * they can still see it (using parport_enumerate).  So be
-	 * careful about the order of writes.. */
-	if (portlist == port) {
-		if ((portlist = port->next) == NULL)
-			portlist_tail = NULL;
-	} else {
-		for (p = portlist; (p != NULL) && (p->next != port); 
-		     p=p->next);
-		if (p) {
-			if ((p->next = port->next) == NULL)
-				portlist_tail = p;
-		}
-		else printk (KERN_WARNING
-			     "%s not found in port list!\n", port->name);
+	list_del_init(&port->list);
+	for (i = 1; i < 3; i++) {
+		struct parport *slave = port->slaves[i-1];
+		if (slave)
+			list_del_init(&slave->list);
 	}
 	spin_unlock(&parportlist_lock);
+
 	up(&registration_lock);
 
-	/* Yes, parport_enumerate _is_ unsafe.  Don't use it. */
-	parport_put_port (port);
+	parport_proc_unregister(port);
+
+	for (i = 1; i < 3; i++) {
+		struct parport *slave = port->slaves[i-1];
+		if (slave)
+			parport_put_port(slave);
+	}
 }
 
 /**
@@ -607,9 +546,8 @@ parport_register_device(struct parport *
 	/* We up our own module reference count, and that of the port
            on which a device is to be registered, to ensure that
            neither of us gets unloaded while we sleep in (e.g.)
-           kmalloc.  To be absolutely safe, we have to require that
-           our caller doesn't sleep in between parport_enumerate and
-           parport_register_device.. */
+           kmalloc.
+         */
 	if (!try_module_get(port->ops->owner)) {
 		return NULL;
 	}
@@ -751,11 +689,6 @@ void parport_unregister_device(struct pa
 
 	module_put(port->ops->owner);
 	parport_put_port (port);
-
-	/* Yes, that's right, someone _could_ still have a pointer to
-	 * port, if they used parport_enumerate.  That's why they
-	 * shouldn't use it (and use parport_register_driver instead)..
-	 */
 }
 
 /**
@@ -774,15 +707,16 @@ struct parport *parport_find_number (int
 {
 	struct parport *port, *result = NULL;
 
-	if (!portlist)
+	if (list_empty(&portlist))
 		get_lowlevel_driver ();
 
 	spin_lock (&parportlist_lock);
-	for (port = portlist; port; port = port->next)
+	list_for_each_entry(port, &portlist, list) {
 		if (port->number == number) {
 			result = parport_get_port (port);
 			break;
 		}
+	}
 	spin_unlock (&parportlist_lock);
 	return result;
 }
@@ -803,15 +737,16 @@ struct parport *parport_find_base (unsig
 {
 	struct parport *port, *result = NULL;
 
-	if (!portlist)
+	if (list_empty(&portlist))
 		get_lowlevel_driver ();
 
 	spin_lock (&parportlist_lock);
-	for (port = portlist; port; port = port->next)
+	list_for_each_entry(port, &portlist, list) {
 		if (port->base == base) {
 			result = parport_get_port (port);
 			break;
 		}
+	}
 	spin_unlock (&parportlist_lock);
 	return result;
 }
@@ -1060,41 +995,21 @@ void parport_release(struct pardevice *d
 	}
 }
 
-static int parport_parse_params (int nports, const char *str[], int val[],
-				 int automatic, int none, int nofifo)
-{
-	unsigned int i;
-	for (i = 0; i < nports && str[i]; i++) {
-		if (!strncmp(str[i], "auto", 4))
-			val[i] = automatic;
-		else if (!strncmp(str[i], "none", 4))
-			val[i] = none;
-		else if (nofifo && !strncmp(str[i], "nofifo", 4))
-			val[i] = nofifo;
-		else {
-			char *ep;
-			unsigned long r = simple_strtoul(str[i], &ep, 0);
-			if (ep != str[i])
-				val[i] = r;
-			else {
-				printk(KERN_ERR "parport: bad specifier `%s'\n", str[i]);
-				return -1;
-			}
-		}
-	}
-
-	return 0;
-}
+/* Exported symbols for modules. */
 
-int parport_parse_irqs(int nports, const char *irqstr[], int irqval[])
-{
-	return parport_parse_params (nports, irqstr, irqval, PARPORT_IRQ_AUTO,
-				     PARPORT_IRQ_NONE, 0);
-}
+EXPORT_SYMBOL(parport_claim);
+EXPORT_SYMBOL(parport_claim_or_block);
+EXPORT_SYMBOL(parport_release);
+EXPORT_SYMBOL(parport_register_port);
+EXPORT_SYMBOL(parport_announce_port);
+EXPORT_SYMBOL(parport_remove_port);
+EXPORT_SYMBOL(parport_register_driver);
+EXPORT_SYMBOL(parport_unregister_driver);
+EXPORT_SYMBOL(parport_register_device);
+EXPORT_SYMBOL(parport_unregister_device);
+EXPORT_SYMBOL(parport_get_port);
+EXPORT_SYMBOL(parport_put_port);
+EXPORT_SYMBOL(parport_find_number);
+EXPORT_SYMBOL(parport_find_base);
 
-int parport_parse_dmas(int nports, const char *dmastr[], int dmaval[])
-{
-	return parport_parse_params (nports, dmastr, dmaval, PARPORT_DMA_AUTO,
-				     PARPORT_DMA_NONE, PARPORT_DMA_NOFIFO);
-}
 MODULE_LICENSE("GPL");
--- diff/drivers/pci/hotplug.c	2004-02-18 08:54:10.000000000 +0000
+++ source/drivers/pci/hotplug.c	2004-02-23 13:56:44.000000000 +0000
@@ -29,7 +29,7 @@ int pci_hotplug (struct device *dev, cha
 
 	/* stuff we want to pass to /sbin/hotplug */
 	envp[i++] = scratch;
-	length += snprintf (scratch, buffer_size - length, "PCI_CLASS=%04X",
+	length += scnprintf (scratch, buffer_size - length, "PCI_CLASS=%04X",
 			    pdev->class);
 	if ((buffer_size - length <= 0) || (i >= num_envp))
 		return -ENOMEM;
@@ -37,7 +37,7 @@ int pci_hotplug (struct device *dev, cha
 	scratch += length;
 
 	envp[i++] = scratch;
-	length += snprintf (scratch, buffer_size - length, "PCI_ID=%04X:%04X",
+	length += scnprintf (scratch, buffer_size - length, "PCI_ID=%04X:%04X",
 			    pdev->vendor, pdev->device);
 	if ((buffer_size - length <= 0) || (i >= num_envp))
 		return -ENOMEM;
@@ -45,7 +45,7 @@ int pci_hotplug (struct device *dev, cha
 	scratch += length;
 
 	envp[i++] = scratch;
-	length += snprintf (scratch, buffer_size - length,
+	length += scnprintf (scratch, buffer_size - length,
 			    "PCI_SUBSYS_ID=%04X:%04X", pdev->subsystem_vendor,
 			    pdev->subsystem_device);
 	if ((buffer_size - length <= 0) || (i >= num_envp))
@@ -54,7 +54,7 @@ int pci_hotplug (struct device *dev, cha
 	scratch += length;
 
 	envp[i++] = scratch;
-	length += snprintf (scratch, buffer_size - length, "PCI_SLOT_NAME=%s",
+	length += scnprintf (scratch, buffer_size - length, "PCI_SLOT_NAME=%s",
 			    pci_name(pdev));
 	if ((buffer_size - length <= 0) || (i >= num_envp))
 		return -ENOMEM;
--- diff/drivers/pci/hotplug/Kconfig	2003-10-27 09:20:38.000000000 +0000
+++ source/drivers/pci/hotplug/Kconfig	2004-02-23 13:56:44.000000000 +0000
@@ -122,5 +122,95 @@ config HOTPLUG_PCI_CPCI_GENERIC
 
 	  When in doubt, say N.
 
+config HOTPLUG_PCI_PCIE
+	tristate "PCI Express Hotplug driver"
+	depends on HOTPLUG_PCI
+	help
+	  Say Y here if you have a motherboard that supports PCI Express Native
+	  Hotplug
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called pciehp.
+
+	  When in doubt, say N.
+
+config HOTPLUG_PCI_PCIE_POLL_EVENT_MODE
+	bool "Use polling mechanism for hot-plug events."
+	depends on HOTPLUG_PCI_PCIE
+	help
+	  Say Y here if you want to use the polling mechanism for hot-plug 
+	  events.
+	   
+	  When in doubt, say N.
+
+config HOTPLUG_PCI_PCIE_PHPRM_NONACPI
+	bool "Non-ACPI: Use $HPRT for resource/configuration"
+	depends on HOTPLUG_PCI_PCIE
+	help
+	  Say Y here if Hotplug resource/configuration information is provided
+	  by platform BIOS $HPRT or bridge resource information, not by ACPI.
+
+	  When in doubt, say N.
+
+config HOTPLUG_PCI_SHPC
+	tristate "SHPC PCI Hotplug driver"
+	depends on HOTPLUG_PCI
+	help
+	  Say Y here if you have a motherboard with a SHPC PCI Hotplug
+	  controller.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called shpchp.
+
+	  When in doubt, say N.
+
+config HOTPLUG_PCI_SHPC_POLL_EVENT_MODE
+	bool "Use polling mechanism for hot-plug events"
+	depends on HOTPLUG_PCI_SHPC
+	help
+	  Say Y here if you want to use the polling mechanism for hot-plug 
+	  events.
+
+	  When in doubt, say N.
+
+config HOTPLUG_PCI_SHPC_PHPRM_NONACPI
+	bool "Non-ACPI: Use $HPRT for resource/configuration"
+	depends on HOTPLUG_PCI_SHPC
+	help
+	  Say Y here if Hotplug resource/configuration information is provided
+	  by platform BIOS $HPRT or bridge resource information, not by ACPI.
+
+	  When in doubt, say N.
+
+config HOTPLUG_PCI_SHPC_PHPRM_LEGACY
+	bool "For AMD SHPC only: Use $HRT for resource/configuration"
+	depends on HOTPLUG_PCI_SHPC && HOTPLUG_PCI_SHPC_PHPRM_NONACPI
+	help
+	  Say Y here for AMD SHPC. You have to select this option if you are 
+	  using this driver on AMD platform with SHPC.
+
+config HOTPLUG_PCI_RPA
+	tristate "RPA PCI Hotplug driver"
+	depends on HOTPLUG_PCI && PPC_PSERIES && PPC64
+	help
+	  Say Y here if you have a a RPA system that supports PCI Hotplug.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called rpaphp.
+
+	  When in doubt, say N.
+
+config HOTPLUG_PCI_RPA_DLPAR
+	tristate "RPA Dynamic Logical Partitioning for I/O slots"
+	depends on HOTPLUG_PCI_RPA
+	help
+	  Say Y here if your system supports Dynamic Logical Partitioning
+	  for I/O slots.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called rpadlpar_io.
+ 
+ 	  When in doubt, say N.
+
 endmenu
 
--- diff/drivers/pci/hotplug/Makefile	2003-07-08 09:55:18.000000000 +0100
+++ source/drivers/pci/hotplug/Makefile	2004-02-23 13:56:44.000000000 +0000
@@ -9,6 +9,10 @@ obj-$(CONFIG_HOTPLUG_PCI_IBM)		+= ibmphp
 obj-$(CONFIG_HOTPLUG_PCI_ACPI)		+= acpiphp.o
 obj-$(CONFIG_HOTPLUG_PCI_CPCI_ZT5550)	+= cpcihp_zt5550.o
 obj-$(CONFIG_HOTPLUG_PCI_CPCI_GENERIC)	+= cpcihp_generic.o
+obj-$(CONFIG_HOTPLUG_PCI_PCIE)		+= pciehp.o
+obj-$(CONFIG_HOTPLUG_PCI_SHPC)		+= shpchp.o
+obj-$(CONFIG_HOTPLUG_PCI_RPA)		+= rpaphp.o
+obj-$(CONFIG_HOTPLUG_PCI_RPA_DLPAR)	+= rpadlpar_io.o
 
 pci_hotplug-objs	:=	pci_hotplug_core.o
 
@@ -33,6 +37,24 @@ acpiphp-objs		:=	acpiphp_core.o	\
 				acpiphp_pci.o	\
 				acpiphp_res.o
 
+rpaphp-objs		:=	rpaphp_core.o	\
+				rpaphp_pci.o	
+
+rpadlpar_io-objs	:=	rpadlpar_core.o \
+				rpadlpar_sysfs.o
+
+pciehp-objs		:=	pciehp_core.o	\
+				pciehp_ctrl.o	\
+				pciehp_pci.o	\
+				pciehp_sysfs.o	\
+				pciehp_hpc.o
+
+shpchp-objs		:=	shpchp_core.o	\
+				shpchp_ctrl.o	\
+				shpchp_pci.o	\
+				shpchp_sysfs.o	\
+				shpchp_hpc.o
+
 ifdef CONFIG_HOTPLUG_PCI_ACPI
   EXTRA_CFLAGS  += -D_LINUX -I$(TOPDIR)/drivers/acpi
   ifdef CONFIG_ACPI_DEBUG
@@ -43,3 +65,21 @@ endif
 ifeq ($(CONFIG_HOTPLUG_PCI_COMPAQ_NVRAM),y)
 	cpqphp-objs += cpqphp_nvram.o
 endif
+
+ifeq ($(CONFIG_HOTPLUG_PCI_PCIE_PHPRM_NONACPI),y)
+  pciehp-objs += pciehprm_nonacpi.o
+else
+  pciehp-objs += pciehprm_acpi.o
+  EXTRA_CFLAGS  += -D_LINUX -I$(TOPDIR)/drivers/acpi -I$(TOPDIR)/drivers/acpi/include 
+endif
+
+ifeq ($(CONFIG_HOTPLUG_PCI_SHPC_PHPRM_LEGACY),y)
+  shpchp-objs += shpchprm_legacy.o
+else
+   ifeq ($(CONFIG_HOTPLUG_PCI_SHPC_PHPRM_NONACPI),y)
+     shpchp-objs += shpchprm_nonacpi.o
+   else
+      shpchp-objs += shpchprm_acpi.o
+      EXTRA_CFLAGS  += -D_LINUX -I$(TOPDIR)/drivers/acpi 
+   endif
+endif
--- diff/drivers/pci/hotplug/cpqphp_sysfs.c	2003-09-30 15:46:16.000000000 +0100
+++ source/drivers/pci/hotplug/cpqphp_sysfs.c	2004-02-23 13:56:44.000000000 +0000
@@ -38,7 +38,7 @@
 
 /* A few routines that create sysfs entries for the hot plug controller */
 
-static int show_ctrl (struct device *dev, char *buf)
+static ssize_t show_ctrl (struct device *dev, char *buf)
 {
 	struct pci_dev *pci_dev;
 	struct controller *ctrl;
@@ -82,7 +82,7 @@ static int show_ctrl (struct device *dev
 }
 static DEVICE_ATTR (ctrl, S_IRUGO, show_ctrl, NULL);
 
-static int show_dev (struct device *dev, char *buf)
+static ssize_t show_dev (struct device *dev, char *buf)
 {
 	struct pci_dev *pci_dev;
 	struct controller *ctrl;
--- diff/drivers/pci/hotplug/pci_hotplug.h	2004-02-09 10:36:11.000000000 +0000
+++ source/drivers/pci/hotplug/pci_hotplug.h	2004-02-23 13:56:44.000000000 +0000
@@ -36,6 +36,9 @@ enum pci_bus_speed {
 	PCI_SPEED_66MHz_PCIX		= 0x02,
 	PCI_SPEED_100MHz_PCIX		= 0x03,
 	PCI_SPEED_133MHz_PCIX		= 0x04,
+	PCI_SPEED_66MHz_PCIX_ECC	= 0x05,
+	PCI_SPEED_100MHz_PCIX_ECC	= 0x06,
+	PCI_SPEED_133MHz_PCIX_ECC	= 0x07,
 	PCI_SPEED_66MHz_PCIX_266	= 0x09,
 	PCI_SPEED_100MHz_PCIX_266	= 0x0a,
 	PCI_SPEED_133MHz_PCIX_266	= 0x0b,
@@ -45,6 +48,24 @@ enum pci_bus_speed {
 	PCI_SPEED_UNKNOWN		= 0xff,
 };
 
+/* These values come from the PCI Express Spec */
+enum pcie_link_width {
+	PCIE_LNK_WIDTH_RESRV	= 0x00,
+	PCIE_LNK_X1		= 0x01,
+	PCIE_LNK_X2		= 0x02,
+	PCIE_LNK_X4		= 0x04,
+	PCIE_LNK_X8		= 0x08,
+	PCIE_LNK_X12		= 0x0C,
+	PCIE_LNK_X16		= 0x10,
+	PCIE_LNK_X32		= 0x20,
+	PCIE_LNK_WIDTH_UNKNOWN  = 0xFF,
+};
+
+enum pcie_link_speed {
+	PCIE_2PT5GB		= 0x14,
+	PCIE_LNK_SPEED_UNKNOWN	= 0xFF,
+};
+
 struct hotplug_slot;
 struct hotplug_slot_attribute {
 	struct attribute attr;
--- diff/drivers/pci/hotplug/pci_hotplug_core.c	2004-02-09 10:36:11.000000000 +0000
+++ source/drivers/pci/hotplug/pci_hotplug_core.c	2004-02-23 13:56:44.000000000 +0000
@@ -129,6 +129,7 @@ static char *pci_bus_speed_strings[] = {
 	"66 MHz PCIX 533",	/* 0x11 */
 	"100 MHz PCIX 533",	/* 0x12 */
 	"133 MHz PCIX 533",	/* 0x13 */
+	"25 GBps PCI-E",	/* 0x14 */
 };
 
 #ifdef CONFIG_HOTPLUG_PCI_CPCI
--- diff/drivers/pci/msi.c	2004-02-18 08:54:10.000000000 +0000
+++ source/drivers/pci/msi.c	2004-02-23 13:56:44.000000000 +0000
@@ -1,5 +1,9 @@
 /*
- * linux/drivers/pci/msi.c
+ * File:	msi.c
+ * Purpose:	PCI Message Signaled Interrupt (MSI)
+ *
+ * Copyright (C) 2003-2004 Intel
+ * Copyright (C) Tom Long Nguyen (tom.l.nguyen@intel.com)
  */
 
 #include <linux/mm.h>
--- diff/drivers/pci/msi.h	2004-02-18 08:54:10.000000000 +0000
+++ source/drivers/pci/msi.h	2004-02-23 13:56:44.000000000 +0000
@@ -1,6 +1,8 @@
 /*
- *	msi.h
+ * File:	msi.h
  *
+ * Copyright (C) 2003-2004 Intel
+ * Copyright (C) Tom Long Nguyen (tom.l.nguyen@intel.com)
  */
 
 #ifndef MSI_H
--- diff/drivers/pci/pci-sysfs.c	2004-02-18 08:54:10.000000000 +0000
+++ source/drivers/pci/pci-sysfs.c	2004-02-23 13:56:44.000000000 +0000
@@ -71,7 +71,7 @@ pci_read_config(struct kobject *kobj, ch
 
 	/* Several chips lock up trying to read undefined config space */
 	if (capable(CAP_SYS_ADMIN)) {
-		size = 256;
+		size = dev->cfg_size;
 	} else if (dev->hdr_type == PCI_HEADER_TYPE_CARDBUS) {
 		size = 128;
 	}
@@ -123,10 +123,10 @@ pci_write_config(struct kobject *kobj, c
 	unsigned int size = count;
 	loff_t init_off = off;
 
-	if (off > 256)
+	if (off > dev->cfg_size)
 		return 0;
-	if (off + count > 256) {
-		size = 256 - off;
+	if (off + count > dev->cfg_size) {
+		size = dev->cfg_size - off;
 		count = size;
 	}
 
@@ -167,6 +167,16 @@ static struct bin_attribute pci_config_a
 	.write = pci_write_config,
 };
 
+static struct bin_attribute pcie_config_attr = {
+	.attr =	{
+		.name = "config",
+		.mode = S_IRUGO | S_IWUSR,
+	},
+	.size = 4096,
+	.read = pci_read_config,
+	.write = pci_write_config,
+};
+
 void pci_create_sysfs_dev_files (struct pci_dev *pdev)
 {
 	struct device *dev = &pdev->dev;
@@ -179,7 +189,11 @@ void pci_create_sysfs_dev_files (struct 
 	device_create_file (dev, &dev_attr_class);
 	device_create_file (dev, &dev_attr_irq);
 	device_create_file (dev, &dev_attr_resource);
-	sysfs_create_bin_file(&dev->kobj, &pci_config_attr);
+	if (pdev->cfg_size < 4096) {
+		sysfs_create_bin_file(&dev->kobj, &pci_config_attr);
+	} else {
+		sysfs_create_bin_file(&dev->kobj, &pcie_config_attr);
+	}
 
 	/* add platform-specific attributes */
 	pcibios_add_platform_entries(pdev);
--- diff/drivers/pci/pci.c	2003-10-09 09:47:34.000000000 +0100
+++ source/drivers/pci/pci.c	2004-02-23 13:56:44.000000000 +0000
@@ -67,64 +67,64 @@ pci_max_busnr(void)
 	return max;
 }
 
-/**
- * pci_find_capability - query for devices' capabilities 
- * @dev: PCI device to query
- * @cap: capability code
- *
- * Tell if a device supports a given PCI capability.
- * Returns the address of the requested capability structure within the
- * device's PCI configuration space or 0 in case the device does not
- * support it.  Possible values for @cap:
- *
- *  %PCI_CAP_ID_PM           Power Management 
- *
- *  %PCI_CAP_ID_AGP          Accelerated Graphics Port 
- *
- *  %PCI_CAP_ID_VPD          Vital Product Data 
- *
- *  %PCI_CAP_ID_SLOTID       Slot Identification 
- *
- *  %PCI_CAP_ID_MSI          Message Signalled Interrupts
- *
- *  %PCI_CAP_ID_CHSWP        CompactPCI HotSwap 
- *
- *  %PCI_CAP_ID_PCIX         PCI-X
- */
-int
-pci_find_capability(struct pci_dev *dev, int cap)
+static int __pci_bus_find_cap(struct pci_bus *bus, unsigned int devfn, u8 hdr_type, int cap)
 {
 	u16 status;
 	u8 pos, id;
 	int ttl = 48;
 
-	pci_read_config_word(dev, PCI_STATUS, &status);
+	pci_bus_read_config_word(bus, devfn, PCI_STATUS, &status);
 	if (!(status & PCI_STATUS_CAP_LIST))
 		return 0;
-	switch (dev->hdr_type) {
+
+	switch (hdr_type) {
 	case PCI_HEADER_TYPE_NORMAL:
 	case PCI_HEADER_TYPE_BRIDGE:
-		pci_read_config_byte(dev, PCI_CAPABILITY_LIST, &pos);
+		pci_bus_read_config_byte(bus, devfn, PCI_CAPABILITY_LIST, &pos);
 		break;
 	case PCI_HEADER_TYPE_CARDBUS:
-		pci_read_config_byte(dev, PCI_CB_CAPABILITY_LIST, &pos);
+		pci_bus_read_config_byte(bus, devfn, PCI_CB_CAPABILITY_LIST, &pos);
 		break;
 	default:
 		return 0;
 	}
 	while (ttl-- && pos >= 0x40) {
 		pos &= ~3;
-		pci_read_config_byte(dev, pos + PCI_CAP_LIST_ID, &id);
+		pci_bus_read_config_byte(bus, devfn, pos + PCI_CAP_LIST_ID, &id);
 		if (id == 0xff)
 			break;
 		if (id == cap)
 			return pos;
-		pci_read_config_byte(dev, pos + PCI_CAP_LIST_NEXT, &pos);
+		pci_bus_read_config_byte(bus, devfn, pos + PCI_CAP_LIST_NEXT, &pos);
 	}
 	return 0;
 }
 
 /**
+ * pci_find_capability - query for devices' capabilities 
+ * @dev: PCI device to query
+ * @cap: capability code
+ *
+ * Tell if a device supports a given PCI capability.
+ * Returns the address of the requested capability structure within the
+ * device's PCI configuration space or 0 in case the device does not
+ * support it.  Possible values for @cap:
+ *
+ *  %PCI_CAP_ID_PM           Power Management 
+ *  %PCI_CAP_ID_AGP          Accelerated Graphics Port 
+ *  %PCI_CAP_ID_VPD          Vital Product Data 
+ *  %PCI_CAP_ID_SLOTID       Slot Identification 
+ *  %PCI_CAP_ID_MSI          Message Signalled Interrupts
+ *  %PCI_CAP_ID_CHSWP        CompactPCI HotSwap 
+ *  %PCI_CAP_ID_PCIX         PCI-X
+ *  %PCI_CAP_ID_EXP          PCI Express
+ */
+int pci_find_capability(struct pci_dev *dev, int cap)
+{
+	return __pci_bus_find_cap(dev->bus, dev->devfn, dev->hdr_type, cap);
+}
+
+/**
  * pci_bus_find_capability - query for devices' capabilities 
  * @bus:   the PCI bus to query
  * @devfn: PCI device to query
@@ -139,34 +139,58 @@ pci_find_capability(struct pci_dev *dev,
  */
 int pci_bus_find_capability(struct pci_bus *bus, unsigned int devfn, int cap)
 {
-	u16 status;
-	u8 pos, id;
-	int ttl = 48;
-	struct pci_dev *dev = bus->self;
+	u8 hdr_type;
 
-	pci_bus_read_config_word(bus, devfn, PCI_STATUS, &status);
-	if (!(status & PCI_STATUS_CAP_LIST))
+	pci_bus_read_config_byte(bus, devfn, PCI_HEADER_TYPE, &hdr_type);
+
+	return __pci_bus_find_cap(bus, devfn, hdr_type & 0x7f, cap);
+}
+
+/**
+ * pci_find_ext_capability - Find an extended capability
+ * @dev: PCI device to query
+ * @cap: capability code
+ *
+ * Returns the address of the requested extended capability structure
+ * within the device's PCI configuration space or 0 if the device does
+ * not support it.  Possible values for @cap:
+ *
+ *  %PCI_EXT_CAP_ID_ERR		Advanced Error Reporting
+ *  %PCI_EXT_CAP_ID_VC		Virtual Channel
+ *  %PCI_EXT_CAP_ID_DSN		Device Serial Number
+ *  %PCI_EXT_CAP_ID_PWR		Power Budgeting
+ */
+int pci_find_ext_capability(struct pci_dev *dev, int cap)
+{
+	u32 header;
+	int ttl = 480; /* 3840 bytes, minimum 8 bytes per capability */
+	int pos = 0x100;
+
+	if (dev->cfg_size <= 256)
 		return 0;
-	switch (dev->hdr_type) {
-	case PCI_HEADER_TYPE_NORMAL:
-	case PCI_HEADER_TYPE_BRIDGE:
-		pci_bus_read_config_byte(bus, devfn, PCI_CAPABILITY_LIST, &pos);
-		break;
-	case PCI_HEADER_TYPE_CARDBUS:
-		pci_bus_read_config_byte(bus, devfn, PCI_CB_CAPABILITY_LIST, &pos);
-		break;
-	default:
+
+	if (pci_read_config_dword(dev, pos, &header) != PCIBIOS_SUCCESSFUL)
 		return 0;
-	}
-	while (ttl-- && pos >= 0x40) {
-		pos &= ~3;
-		pci_bus_read_config_byte(bus, devfn, pos + PCI_CAP_LIST_ID, &id);
-		if (id == 0xff)
-			break;
-		if (id == cap)
+
+	/*
+	 * If we have no capabilities, this is indicated by cap ID,
+	 * cap version and next pointer all being 0.
+	 */
+	if (header == 0)
+		return 0;
+
+	while (ttl-- > 0) {
+		if ((header & 0x000ffff) == cap)
 			return pos;
-		pci_bus_read_config_byte(bus, devfn, pos + PCI_CAP_LIST_NEXT, &pos);
+
+		pos = (header >> 20) & ~3;
+		if (pos < 0x100)
+			break;
+
+		if (pci_read_config_dword(dev, pos, &header) != PCIBIOS_SUCCESSFUL)
+			break;
 	}
+
 	return 0;
 }
 
@@ -223,6 +247,8 @@ pci_set_power_state(struct pci_dev *dev,
 	int pm;
 	u16 pmcsr;
 
+	might_sleep();
+
 	/* bound the state we're entering */
 	if (state > 3) state = 3;
 
@@ -553,11 +579,6 @@ int pci_request_regions(struct pci_dev *
 	return 0;
 
 err_out:
-	printk (KERN_WARNING "PCI: Unable to reserve %s region #%d:%lx@%lx for device %s\n",
-		pci_resource_flags(pdev, i) & IORESOURCE_IO ? "I/O" : "mem",
-		i + 1, /* PCI BAR # */
-		pci_resource_len(pdev, i), pci_resource_start(pdev, i),
-		pci_name(pdev));
 	while(--i >= 0)
 		pci_release_region(pdev, i);
 		
--- diff/drivers/pci/probe.c	2004-02-18 08:54:10.000000000 +0000
+++ source/drivers/pci/probe.c	2004-02-23 13:56:44.000000000 +0000
@@ -18,6 +18,8 @@
 
 #define CARDBUS_LATENCY_TIMER	176	/* secondary latency timer */
 #define CARDBUS_RESERVE_BUSNR	3
+#define PCI_CFG_SPACE_SIZE	256
+#define PCI_CFG_SPACE_EXP_SIZE	4096
 
 /* Ugh.  Need to stop exporting this to modules. */
 LIST_HEAD(pci_root_buses);
@@ -55,7 +57,7 @@ static ssize_t pci_bus_show_cpuaffinity(
 	cpumask_t cpumask = pcibus_to_cpumask((to_pci_bus(class_dev))->number);
 	int ret;
 
-	ret = cpumask_snprintf(buf, PAGE_SIZE, cpumask);
+	ret = cpumask_scnprintf(buf, PAGE_SIZE, cpumask);
 	if (ret < PAGE_SIZE)
 		buf[ret++] = '\n';
 	return ret;
@@ -366,6 +368,8 @@ int __devinit pci_scan_bridge(struct pci
 		child = pci_alloc_child_bus(bus, dev, busnr);
 		child->primary = buses & 0xFF;
 		child->subordinate = (buses >> 16) & 0xFF;
+		child->bridge_ctl = bctl;
+
 		cmax = pci_scan_child_bus(child);
 		if (cmax > max) max = cmax;
 	} else {
@@ -400,6 +404,8 @@ int __devinit pci_scan_bridge(struct pci
 		pci_write_config_dword(dev, PCI_PRIMARY_BUS, buses);
 
 		if (!is_cardbus) {
+			child->bridge_ctl = PCI_BRIDGE_CTL_NO_ISA;
+
 			/* Now we can scan all subordinate buses... */
 			max = pci_scan_child_bus(child);
 		} else {
@@ -526,6 +532,31 @@ static void pci_release_dev(struct devic
 	kfree(pci_dev);
 }
 
+/**
+ * pci_cfg_space_size - get the configuration space size of the PCI device.
+ * Regular PCI devices have 256 bytes, but PCI-X 2 and PCI Express devices
+ * have 4096 bytes.
+ */
+static int pci_cfg_space_size(struct pci_dev *dev)
+{
+	int pos;
+
+	pos = pci_find_capability(dev, PCI_CAP_ID_EXP);
+	if (pos)
+		return PCI_CFG_SPACE_EXP_SIZE;
+
+	pos = pci_find_capability(dev, PCI_CAP_ID_PCIX);
+	if (pos) {
+		u32 status;
+		pci_read_config_dword(dev, pos + PCI_X_STATUS, &status);
+
+		if (status & (PCI_X_STATUS_266MHZ | PCI_X_STATUS_533MHZ))
+			return PCI_CFG_SPACE_EXP_SIZE;
+	}
+
+	return PCI_CFG_SPACE_SIZE;
+}
+
 /*
  * Read the config data for a PCI device, sanity-check it
  * and fill in the dev structure...
@@ -562,6 +593,7 @@ pci_scan_device(struct pci_bus *bus, int
 	dev->multifunction = !!(hdr_type & 0x80);
 	dev->vendor = l & 0xffff;
 	dev->device = (l >> 16) & 0xffff;
+	dev->cfg_size = pci_cfg_space_size(dev);
 
 	/* Assume 32-bit PCI; let 64-bit PCI cards (which are far rarer)
 	   set this higher, assuming the system even supports it.  */
--- diff/drivers/pci/proc.c	2004-01-19 10:22:58.000000000 +0000
+++ source/drivers/pci/proc.c	2004-02-23 13:56:44.000000000 +0000
@@ -16,16 +16,15 @@
 #include <asm/uaccess.h>
 #include <asm/byteorder.h>
 
-#define PCI_CFG_SPACE_SIZE 256
-
 static int proc_initialized;	/* = 0 */
 
 static loff_t
 proc_bus_pci_lseek(struct file *file, loff_t off, int whence)
 {
 	loff_t new = -1;
+	struct inode *inode = file->f_dentry->d_inode;
 
-	down(&file->f_dentry->d_inode->i_sem);
+	down(&inode->i_sem);
 	switch (whence) {
 	case 0:
 		new = off;
@@ -34,14 +33,14 @@ proc_bus_pci_lseek(struct file *file, lo
 		new = file->f_pos + off;
 		break;
 	case 2:
-		new = PCI_CFG_SPACE_SIZE + off;
+		new = inode->i_size + off;
 		break;
 	}
-	if (new < 0 || new > PCI_CFG_SPACE_SIZE)
+	if (new < 0 || new > inode->i_size)
 		new = -EINVAL;
 	else
 		file->f_pos = new;
-	up(&file->f_dentry->d_inode->i_sem);
+	up(&inode->i_sem);
 	return new;
 }
 
@@ -61,7 +60,7 @@ proc_bus_pci_read(struct file *file, cha
 	 */
 
 	if (capable(CAP_SYS_ADMIN))
-		size = PCI_CFG_SPACE_SIZE;
+		size = dev->cfg_size;
 	else if (dev->hdr_type == PCI_HEADER_TYPE_CARDBUS)
 		size = 128;
 	else
@@ -134,14 +133,15 @@ proc_bus_pci_write(struct file *file, co
 	const struct proc_dir_entry *dp = PDE(ino);
 	struct pci_dev *dev = dp->data;
 	int pos = *ppos;
+	int size = dev->cfg_size;
 	int cnt;
 
-	if (pos >= PCI_CFG_SPACE_SIZE)
+	if (pos >= size)
 		return 0;
-	if (nbytes >= PCI_CFG_SPACE_SIZE)
-		nbytes = PCI_CFG_SPACE_SIZE;
-	if (pos + nbytes > PCI_CFG_SPACE_SIZE)
-		nbytes = PCI_CFG_SPACE_SIZE - pos;
+	if (nbytes >= size)
+		nbytes = size;
+	if (pos + nbytes > size)
+		nbytes = size - pos;
 	cnt = nbytes;
 
 	if (!access_ok(VERIFY_READ, buf, cnt))
@@ -403,7 +403,7 @@ int pci_proc_attach_device(struct pci_de
 		return -ENOMEM;
 	e->proc_fops = &proc_bus_pci_operations;
 	e->data = dev;
-	e->size = PCI_CFG_SPACE_SIZE;
+	e->size = dev->cfg_size;
 
 	return 0;
 }
--- diff/drivers/pci/quirks.c	2004-02-09 10:36:11.000000000 +0000
+++ source/drivers/pci/quirks.c	2004-02-23 13:56:44.000000000 +0000
@@ -703,9 +703,12 @@ static void __init asus_hides_smbus_host
 	    	case 0x8088: /* P4B533 */
 			asus_hides_smbus = 1;
 		}
-	if ((dev->device == PCI_DEVICE_ID_INTEL_82845G_HB) &&
-	    (dev->subsystem_device == 0x80b2)) /* P4PE */
-		asus_hides_smbus = 1;
+	if (dev->device == PCI_DEVICE_ID_INTEL_82845G_HB)
+		switch(dev->subsystem_device) {
+		case 0x80b2: /* P4PE */
+ 		case 0x8093: /* P4B533-V */
+			asus_hides_smbus = 1;
+		}
 	if ((dev->device == PCI_DEVICE_ID_INTEL_82850_HB) &&
 	    (dev->subsystem_device == 0x8030)) /* P4T533 */
 		asus_hides_smbus = 1;
@@ -786,6 +789,29 @@ static void __init quirk_sis_96x_compati
 	sis_96x_compatible = 1;
 }
 
+#ifdef CONFIG_X86_IO_APIC
+static void __init quirk_alder_ioapic(struct pci_dev *pdev)
+{
+	int i;
+
+	if ((pdev->class >> 8) != 0xff00)
+		return;
+
+	/* the first BAR is the location of the IO APIC...we must
+	 * not touch this (and it's already covered by the fixmap), so
+	 * forcibly insert it into the resource tree */
+	if(pci_resource_start(pdev, 0) && pci_resource_len(pdev, 0))
+		insert_resource(&iomem_resource, &pdev->resource[0]);
+
+	/* The next five BARs all seem to be rubbish, so just clean
+	 * them out */
+	for(i=1; i < 6; i++) {
+		memset(&pdev->resource[i], 0, sizeof(pdev->resource[i]));
+	}
+
+}
+#endif
+
 #ifdef CONFIG_SCSI_SATA
 static void __init quirk_intel_ide_combined(struct pci_dev *pdev)
 {
@@ -911,6 +937,7 @@ static struct pci_fixup pci_fixups[] __d
 	{ PCI_FIXUP_FINAL,	PCI_VENDOR_ID_SI,	PCI_ANY_ID,			quirk_ioapic_rmw },
         { PCI_FIXUP_FINAL,      PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8131_APIC,
           quirk_amd_8131_ioapic }, 
+	{ PCI_FIXUP_HEADER,	PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_EESSC,	quirk_alder_ioapic },
 #endif
 	{ PCI_FIXUP_HEADER,	PCI_VENDOR_ID_VIA,	PCI_DEVICE_ID_VIA_82C586_3,	quirk_via_acpi },
 	{ PCI_FIXUP_HEADER,	PCI_VENDOR_ID_VIA,	PCI_DEVICE_ID_VIA_82C686_4,	quirk_via_acpi },
--- diff/drivers/pci/setup-bus.c	2003-11-25 15:24:58.000000000 +0000
+++ source/drivers/pci/setup-bus.c	2004-02-23 13:56:44.000000000 +0000
@@ -43,13 +43,15 @@
 #define CARDBUS_IO_SIZE		(4096)
 #define CARDBUS_MEM_SIZE	(32*1024*1024)
 
-static int __devinit
+static void __devinit
 pbus_assign_resources_sorted(struct pci_bus *bus)
 {
 	struct pci_dev *dev;
 	struct resource *res;
 	struct resource_list head, *list, *tmp;
-	int idx, found_vga = 0;
+	int idx;
+
+	bus->bridge_ctl &= ~PCI_BRIDGE_CTL_VGA;
 
 	head.next = NULL;
 	list_for_each_entry(dev, &bus->devices, bus_list) {
@@ -57,7 +59,7 @@ pbus_assign_resources_sorted(struct pci_
 
 		if (class == PCI_CLASS_DISPLAY_VGA
 				|| class == PCI_CLASS_NOT_DEFINED_VGA)
-			found_vga = 1;
+			bus->bridge_ctl |= PCI_BRIDGE_CTL_VGA;
 
 		pdev_sort_resources(dev, &head);
 	}
@@ -70,8 +72,6 @@ pbus_assign_resources_sorted(struct pci_
 		list = list->next;
 		kfree(tmp);
 	}
-
-	return found_vga;
 }
 
 static void __devinit
@@ -211,10 +211,7 @@ pci_setup_bridge(struct pci_bus *bus)
 	/* Clear out the upper 32 bits of PREF base. */
 	pci_write_config_dword(bridge, PCI_PREF_BASE_UPPER32, 0);
 
-	/* Check if we have VGA behind the bridge.
-	   Enable ISA in either case (FIXME!). */
-	l = (bus->resource[0]->flags & IORESOURCE_BUS_HAS_VGA) ? 0x0c : 0x04;
-	pci_write_config_word(bridge, PCI_BRIDGE_CONTROL, l);
+	pci_write_config_word(bridge, PCI_BRIDGE_CONTROL, bus->bridge_ctl);
 }
 
 /* Check whether the bridge supports optional I/O and
@@ -498,13 +495,14 @@ void __devinit
 pci_bus_assign_resources(struct pci_bus *bus)
 {
 	struct pci_bus *b;
-	int found_vga = pbus_assign_resources_sorted(bus);
 	struct pci_dev *dev;
 
-	if (found_vga) {
+	pbus_assign_resources_sorted(bus);
+
+	if (bus->bridge_ctl & PCI_BRIDGE_CTL_VGA) {
 		/* Propagate presence of the VGA to upstream bridges */
 		for (b = bus; b->parent; b = b->parent) {
-			b->resource[0]->flags |= IORESOURCE_BUS_HAS_VGA;
+			b->bridge_ctl |= PCI_BRIDGE_CTL_VGA;
 		}
 	}
 	list_for_each_entry(dev, &bus->devices, bus_list) {
--- diff/drivers/pci/setup-res.c	2004-01-19 10:22:58.000000000 +0000
+++ source/drivers/pci/setup-res.c	2004-02-23 13:56:44.000000000 +0000
@@ -143,8 +143,9 @@ int pci_assign_resource(struct pci_dev *
 	}
 
 	if (ret) {
-		printk(KERN_ERR "PCI: Failed to allocate resource %d(%lx-%lx) for %s\n",
-		       resno, res->start, res->end, pci_name(dev));
+		printk(KERN_ERR "PCI: Failed to allocate %s resource #%d:%lx@%lx for %s\n",
+		       res->flags & IORESOURCE_IO ? "I/O" : "mem",
+		       resno, size, res->start, pci_name(dev));
 	} else if (resno < PCI_BRIDGE_RESOURCES) {
 		pci_update_resource(dev, res, resno);
 	}
--- diff/drivers/pcmcia/au1000_generic.c	2003-10-09 09:47:34.000000000 +0100
+++ source/drivers/pcmcia/au1000_generic.c	2004-02-23 13:56:44.000000000 +0000
@@ -26,6 +26,7 @@
  * 
  */
 #include <linux/module.h>
+#include <linux/moduleparam.h>
 #include <linux/init.h>
 #include <linux/config.h>
 #include <linux/delay.h>
@@ -54,8 +55,17 @@
 #include <asm/au1000.h>
 #include <asm/au1000_pcmcia.h>
 
-#ifdef PCMCIA_DEBUG
+#ifdef DEBUG
 static int pc_debug;
+
+module_param(pc_debug, int, 0644);
+
+#define debug(lvl,fmt) do {			\
+	if (pc_debug > (lvl))			\
+		printk(KERN_DEBUG fmt);		\
+} while (0)
+#else
+#define debug(lvl,fmt) do { } while (0)
 #endif
 
 MODULE_LICENSE("GPL");
@@ -209,7 +219,7 @@ static int __init au1000_pcmcia_driver_i
 	 */
 	au1000_pcmcia_poll_event(0);
 
-	DEBUG(1, "au1000: initialization complete\n");
+	debug(1, "au1000: initialization complete\n");
 	return 0;
 
 }  /* au1000_pcmcia_driver_init() */
@@ -228,7 +238,7 @@ static void __exit au1000_pcmcia_driver_
 		if (pcmcia_socket[i].virt_io) 
 			iounmap((void *)pcmcia_socket[i].virt_io);
 	}
-	DEBUG(1, "au1000: shutdown complete\n");
+	debug(1, "au1000: shutdown complete\n");
 }
 
 module_exit(au1000_pcmcia_driver_shutdown);
@@ -249,14 +259,14 @@ au1000_pcmcia_events(struct pcmcia_state
 	unsigned int events=0;
 
 	if(state->detect!=prev_state->detect){
-		DEBUG(2, "%s(): card detect value %u\n", 
+		debug(2, "%s(): card detect value %u\n",
 				__FUNCTION__, state->detect);
 		events |= mask&SS_DETECT;
 	}
 
 
 	if(state->ready!=prev_state->ready){
-		DEBUG(2, "%s(): card ready value %u\n", 
+		debug(2, "%s(): card ready value %u\n",
 				__FUNCTION__, state->ready);
 		events |= mask&((flags&SS_IOCARD)?0:SS_READY);
 	}
@@ -429,7 +439,7 @@ au1000_pcmcia_get_status(unsigned int so
 
 	*status|=state.vs_Xv?SS_XVCARD:0;
 
-	DEBUG(2, "\tstatus: %s%s%s%s%s%s%s%s\n",
+	debug(2, "\tstatus: %s%s%s%s%s%s%s%s\n",
 	(*status&SS_DETECT)?"DETECT ":"",
 	(*status&SS_READY)?"READY ":"", 
 	(*status&SS_BATDEAD)?"BATDEAD ":"",
@@ -457,7 +467,7 @@ au1000_pcmcia_set_socket(unsigned int so
 {
 	struct pcmcia_configure configure;
 
-	DEBUG(2, "\tmask:  %s%s%s%s%s%s\n\tflags: %s%s%s%s%s%s\n"
+	debug(2, "\tmask:  %s%s%s%s%s%s\n\tflags: %s%s%s%s%s%s\n"
 	"\tVcc %d  Vpp %d  irq %d\n",
 	(state->csc_mask==0)?"<NONE>":"",
 	(state->csc_mask&SS_DETECT)?"DETECT ":"",
@@ -494,7 +504,7 @@ au1000_pcmcia_set_socket(unsigned int so
 static int 
 au1000_pcmcia_get_io_map(unsigned int sock, struct pccard_io_map *map)
 {
-	DEBUG(1, "au1000_pcmcia_get_io_map: sock %d\n", sock);
+	debug(1, "au1000_pcmcia_get_io_map: sock %d\n", sock);
 	if(map->map>=MAX_IO_WIN){
 		printk(KERN_ERR "%s(): map (%d) out of range\n", 
 				__FUNCTION__, map->map);
@@ -531,7 +541,7 @@ au1000_pcmcia_set_io_map(unsigned int so
 	map->start=pcmcia_socket[sock].virt_io;
 	map->stop=map->start+(map->stop-start);
 	pcmcia_socket[sock].io_map[map->map]=*map;
-	DEBUG(3, "set_io_map %d start %x stop %x\n", 
+	debug(3, "set_io_map %d start %x stop %x\n",
 			map->map, map->start, map->stop);
 	return 0;
 
@@ -595,7 +605,7 @@ au1000_pcmcia_set_mem_map(unsigned int s
 	map->sys_stop=map->sys_start+(map->sys_stop-start);
 	pcmcia_socket[sock].mem_map[map->map]=*map;
 	spin_unlock_irqrestore(&pcmcia_lock, flags);
-	DEBUG(3, "set_mem_map %d start %x stop %x card_start %x\n", 
+	debug(3, "set_mem_map %d start %x stop %x card_start %x\n",
 			map->map, map->sys_start, map->sys_stop, 
 			map->card_start);
 	return 0;
--- diff/drivers/pcmcia/au1000_pb1x00.c	2003-10-09 09:47:34.000000000 +0100
+++ source/drivers/pcmcia/au1000_pb1x00.c	2004-02-23 13:56:44.000000000 +0000
@@ -48,6 +48,8 @@
 #include <asm/au1000.h>
 #include <asm/au1000_pcmcia.h>
 
+#define debug(fmt, arg...) do { } while (0)
+
 #ifdef CONFIG_MIPS_PB1000
 #include <asm/pb1000.h>
 #define PCMCIA_IRQ AU1000_GPIO_15
@@ -213,7 +215,7 @@ pb1x00_pcmcia_configure_socket(const str
 	}
 
 	pcr &= ~PCR_SLOT_0_RST;
-	DEBUG(KERN_INFO "Vcc %dV Vpp %dV, pcr %x\n", 
+	debug("Vcc %dV Vpp %dV, pcr %x\n",
 			configure->vcc, configure->vpp, pcr);
 	switch(configure->vcc){
 		case 0:  /* Vcc 0 */
@@ -324,7 +326,7 @@ pb1x00_pcmcia_configure_socket(const str
 
 	pcr = au_readw(PB1100_MEM_PCMCIA) & ~0xf;
 
-	DEBUG(KERN_INFO "Vcc %dV Vpp %dV, pcr %x, reset %d\n", 
+	debug("Vcc %dV Vpp %dV, pcr %x, reset %d\n",
 			configure->vcc, configure->vpp, pcr, configure->reset);
 
 
--- diff/drivers/pcmcia/bulkmem.c	2004-02-18 08:54:10.000000000 +0000
+++ source/drivers/pcmcia/bulkmem.c	2004-02-23 13:56:44.000000000 +0000
@@ -48,6 +48,8 @@
 #include <pcmcia/cistpl.h>
 #include "cs_internal.h"
 
+static void retry_erase_list(erase_busy_t *list, u_int cause);
+
 /*======================================================================
 
     This function handles submitting an MTD request, and retrying
@@ -108,18 +110,18 @@ static int do_mtd_request(memory_handle_
 
 ======================================================================*/
 
-static void insert_queue(erase_busy_t *head, erase_busy_t *entry)
+static void insert_queue(struct pcmcia_socket *s, erase_busy_t *head, erase_busy_t *entry)
 {
-    DEBUG(2, "cs: adding 0x%p to queue 0x%p\n", entry, head);
+    cs_dbg(s, 2, "adding 0x%p to queue 0x%p\n", entry, head);
     entry->next = head;
     entry->prev = head->prev;
     head->prev->next = entry;
     head->prev = entry;
 }
 
-static void remove_queue(erase_busy_t *entry)
+static void remove_queue(struct pcmcia_socket *s, erase_busy_t *entry)
 {
-    DEBUG(2, "cs: unqueueing 0x%p\n", entry);
+    cs_dbg(s, 2, "unqueueing 0x%p\n", entry);
     entry->next->prev = entry->prev;
     entry->prev->next = entry->next;
 }
@@ -132,34 +134,35 @@ static void retry_erase(erase_busy_t *bu
     struct pcmcia_socket *s;
     int ret;
 
-    DEBUG(2, "cs: trying erase request 0x%p...\n", busy);
+    mtd = erase->Handle->mtd;
+    s = SOCKET(mtd);
+
+    cs_dbg(s, 2, "trying erase request 0x%p...\n", busy);
     if (busy->next)
-	remove_queue(busy);
+	remove_queue(s, busy);
     req.Function = MTD_REQ_ERASE | cause;
     req.TransferLength = erase->Size;
     req.DestCardOffset = erase->Offset + erase->Handle->info.CardOffset;
     req.MediaID = erase->Handle->MediaID;
-    mtd = erase->Handle->mtd;
-    s = SOCKET(mtd);
     mtd->event_callback_args.mtdrequest = &req;
     ret = EVENT(mtd, CS_EVENT_MTD_REQUEST, CS_EVENT_PRI_LOW);
     if (ret == CS_BUSY) {
-	DEBUG(2, "  Status = %d, requeueing.\n", req.Status);
+	cs_dbg(s, 2, "  Status = %d, requeueing.\n", req.Status);
 	switch (req.Status) {
 	case MTD_WAITREQ:
 	case MTD_WAITPOWER:
-	    insert_queue(&mtd->erase_busy, busy);
+	    insert_queue(s, &mtd->erase_busy, busy);
 	    break;
 	case MTD_WAITTIMER:
 	case MTD_WAITRDY:
 	    if (req.Status == MTD_WAITRDY)
-		insert_queue(&s->erase_busy, busy);
+		insert_queue(s, &s->erase_busy, busy);
 	    mod_timer(&busy->timeout, jiffies + req.Timeout*HZ/1000);
 	    break;
 	}
     } else {
 	/* update erase queue status */
-	DEBUG(2, "  Ret = %d\n", ret);
+	cs_dbg(s, 2, "  Ret = %d\n", ret);
 	switch (ret) {
 	case CS_SUCCESS:
 	    erase->State = ERASE_PASSED; break;
@@ -183,11 +186,11 @@ static void retry_erase(erase_busy_t *bu
     }
 } /* retry_erase */
 
-void retry_erase_list(erase_busy_t *list, u_int cause)
+static void retry_erase_list(erase_busy_t *list, u_int cause)
 {
     erase_busy_t tmp = *list;
 
-    DEBUG(2, "cs: rescanning erase queue list 0x%p\n", list);
+    cs_dbg(SOCKET(list->client), 2, "rescanning erase queue list 0x%p\n", list);
     if (list->next == list)
 	return;
     /* First, truncate the original list */
@@ -204,8 +207,9 @@ void retry_erase_list(erase_busy_t *list
 
 static void handle_erase_timeout(u_long arg)
 {
-    DEBUG(0, "cs: erase timeout for entry 0x%lx\n", arg);
-    retry_erase((erase_busy_t *)arg, MTD_REQ_TIMEOUT);
+    erase_busy_t *busy = (erase_busy_t *)arg;
+    cs_dbg(SOCKET(busy->client), 0, "erase timeout for entry 0x%lx\n", arg);
+    retry_erase(busy, MTD_REQ_TIMEOUT);
 }
 
 static void setup_erase_request(client_handle_t handle, eraseq_entry_t *erase)
@@ -333,8 +337,8 @@ static void setup_regions(client_handle_
     cistpl_device_geo_t geo;
     memory_handle_t r;
 
-    DEBUG(1, "cs: setup_regions(0x%p, %d, 0x%p)\n",
-	  handle, attr, list);
+    cs_dbg(SOCKET(handle), 1, "setup_regions(0x%p, %d, 0x%p)\n",
+	   handle, attr, list);
 
     code = (attr) ? CISTPL_DEVICE_A : CISTPL_DEVICE;
     if (read_tuple(handle, code, &device) != CS_SUCCESS)
@@ -342,17 +346,13 @@ static void setup_regions(client_handle_
     code = (attr) ? CISTPL_JEDEC_A : CISTPL_JEDEC_C;
     has_jedec = (read_tuple(handle, code, &jedec) == CS_SUCCESS);
     if (has_jedec && (device.ndev != jedec.nid)) {
-#ifdef PCMCIA_DEBUG
-	printk(KERN_DEBUG "cs: Device info does not match JEDEC info.\n");
-#endif
+	cs_dbg(SOCKET(handle), 0, "Device info does not match JEDEC info.\n");
 	has_jedec = 0;
     }
     code = (attr) ? CISTPL_DEVICE_GEO_A : CISTPL_DEVICE_GEO;
     has_geo = (read_tuple(handle, code, &geo) == CS_SUCCESS);
     if (has_geo && (device.ndev != geo.ngeo)) {
-#ifdef PCMCIA_DEBUG
-	printk(KERN_DEBUG "cs: Device info does not match geometry tuple.\n");
-#endif
+	cs_dbg(SOCKET(handle), 0, "Device info does not match geometry tuple.\n");
 	has_geo = 0;
     }
     
@@ -458,7 +458,7 @@ int pcmcia_register_mtd(client_handle_t 
 	list = s->a_region;
     else
 	list = s->c_region;
-    DEBUG(1, "cs: register_mtd(0x%p, '%s', 0x%x)\n",
+    cs_dbg(s, 1, "register_mtd(0x%p, '%s', 0x%x)\n",
 	  handle, handle->dev_info, reg->Offset);
     while (list) {
 	if (list->info.CardOffset == reg->Offset) break;
@@ -548,8 +548,8 @@ int pcmcia_open_memory(client_handle_t *
     }
     if (region && region->mtd) {
 	*mh = region;
-	DEBUG(1, "cs: open_memory(0x%p, 0x%x) = 0x%p\n",
-	      handle, open->Offset, region);
+	cs_dbg(s, 1, "open_memory(0x%p, 0x%x) = 0x%p\n",
+	       handle, open->Offset, region);
 	return CS_SUCCESS;
     } else
 	return CS_BAD_OFFSET;
@@ -565,7 +565,7 @@ int pcmcia_open_memory(client_handle_t *
 
 int pcmcia_close_memory(memory_handle_t handle)
 {
-    DEBUG(1, "cs: close_memory(0x%p)\n", handle);
+    cs_dbg(SOCKET(handle->mtd), 1, "cs: close_memory(0x%p)\n", handle);
     if (CHECK_REGION(handle))
 	return CS_BAD_HANDLE;
     return CS_SUCCESS;
--- diff/drivers/pcmcia/cardbus.c	2003-09-30 15:46:16.000000000 +0100
+++ source/drivers/pcmcia/cardbus.c	2004-02-23 13:56:44.000000000 +0000
@@ -58,10 +58,6 @@
 #include <pcmcia/cistpl.h>
 #include "cs_internal.h"
 
-#ifdef PCMCIA_DEBUG
-static int pc_debug = PCMCIA_DEBUG;
-#endif
-
 /*====================================================================*/
 
 #define FIND_FIRST_BIT(n)	((n) - ((n) & ((n)-1)))
@@ -119,7 +115,7 @@ static u_int xlate_rom_addr(u_char * b, 
 static void cb_release_cis_mem(struct pcmcia_socket * s)
 {
 	if (s->cb_cis_virt) {
-		DEBUG(1, "cs: cb_release_cis_mem()\n");
+		cs_dbg(s, 1, "cb_release_cis_mem()\n");
 		iounmap(s->cb_cis_virt);
 		s->cb_cis_virt = NULL;
 		s->cb_cis_res = 0;
@@ -160,7 +156,7 @@ int read_cb_mem(struct pcmcia_socket * s
 	struct pci_dev *dev;
 	struct resource *res;
 
-	DEBUG(3, "cs: read_cb_mem(%d, %#x, %u)\n", space, addr, len);
+	cs_dbg(s, 3, "read_cb_mem(%d, %#x, %u)\n", space, addr, len);
 
 	dev = pci_find_slot(s->cb_dev->subordinate->number, 0);
 	if (!dev)
--- diff/drivers/pcmcia/cistpl.c	2004-01-19 10:22:58.000000000 +0000
+++ source/drivers/pcmcia/cistpl.c	2004-02-23 13:56:44.000000000 +0000
@@ -143,7 +143,7 @@ int read_cis_mem(struct pcmcia_socket *s
 {
     u_char *sys, *end, *buf = ptr;
     
-    DEBUG(3, "cs: read_cis_mem(%d, %#x, %u)\n", attr, addr, len);
+    cs_dbg(s, 3, "read_cis_mem(%d, %#x, %u)\n", attr, addr, len);
 
     if (attr & IS_INDIRECT) {
 	/* Indirect accesses use a bunch of special registers at fixed
@@ -195,7 +195,7 @@ int read_cis_mem(struct pcmcia_socket *s
 	    addr = 0;
 	}
     }
-    DEBUG(3, "cs:  %#2.2x %#2.2x %#2.2x %#2.2x ...\n",
+    cs_dbg(s, 3, "  %#2.2x %#2.2x %#2.2x %#2.2x ...\n",
 	  *(u_char *)(ptr+0), *(u_char *)(ptr+1),
 	  *(u_char *)(ptr+2), *(u_char *)(ptr+3));
     return 0;
@@ -206,7 +206,7 @@ void write_cis_mem(struct pcmcia_socket 
 {
     u_char *sys, *end, *buf = ptr;
     
-    DEBUG(3, "cs: write_cis_mem(%d, %#x, %u)\n", attr, addr, len);
+    cs_dbg(s, 3, "write_cis_mem(%d, %#x, %u)\n", attr, addr, len);
 
     if (attr & IS_INDIRECT) {
 	/* Indirect accesses use a bunch of special registers at fixed
@@ -578,8 +578,7 @@ int pcmcia_get_next_tuple(client_handle_
 	ofs += link[1] + 2;
     }
     if (i == MAX_TUPLES) {
-	DEBUG(1, "cs: overrun in pcmcia_get_next_tuple for socket %d\n",
-	      handle->Socket);
+	cs_dbg(s, 1, "cs: overrun in pcmcia_get_next_tuple\n");
 	return CS_NO_MORE_ITEMS;
     }
     
--- diff/drivers/pcmcia/cs.c	2004-02-09 10:36:11.000000000 +0000
+++ source/drivers/pcmcia/cs.c	2004-02-23 13:56:44.000000000 +0000
@@ -32,6 +32,7 @@
 ======================================================================*/
 
 #include <linux/module.h>
+#include <linux/moduleparam.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/config.h>
@@ -110,12 +111,17 @@ INT_MODULE_PARM(cis_speed,	300);		/* ns 
 /* Access speed for IO windows */
 INT_MODULE_PARM(io_speed,	0);		/* ns */
 
-#ifdef PCMCIA_DEBUG
-INT_MODULE_PARM(pc_debug, PCMCIA_DEBUG);
-static const char *version =
-"cs.c 1.279 2001/10/13 00:08:28 (David Hinds)";
+#ifdef DEBUG
+static int pc_debug;
+
+module_param(pc_debug, int, 0644);
+
+int cs_debug_level(int level)
+{
+	return pc_debug > level;
+}
 #endif
- 
+
 /*====================================================================*/
 
 socket_state_t dead_socket = {
@@ -306,7 +312,7 @@ int pcmcia_register_socket(struct pcmcia
 	if (!socket || !socket->ops || !socket->dev.dev)
 		return -EINVAL;
 
-	DEBUG(0, "cs: pcmcia_register_socket(0x%p)\n", socket->ops);
+	cs_dbg(socket, 0, "pcmcia_register_socket(0x%p)\n", socket->ops);
 
 	/* try to obtain a socket number [yes, it gets ugly if we
 	 * register more than 2^sizeof(unsigned int) pcmcia 
@@ -377,7 +383,7 @@ void pcmcia_unregister_socket(struct pcm
 	if (!socket)
 		return;
 
-	DEBUG(0, "cs: pcmcia_unregister_socket(0x%p)\n", socket->ops);
+	cs_dbg(socket, 0, "pcmcia_unregister_socket(0x%p)\n", socket->ops);
 
 	if (socket->thread) {
 		init_completion(&socket->thread_done);
@@ -443,7 +449,7 @@ static void shutdown_socket(struct pcmci
 {
     client_t **c;
     
-    DEBUG(1, "cs: shutdown_socket(%p)\n", s);
+    cs_dbg(s, 1, "shutdown_socket\n");
 
     /* Blank out the socket state */
     s->state &= SOCKET_PRESENT|SOCKET_INUSE;
@@ -499,8 +505,8 @@ static int send_event(struct pcmcia_sock
 {
     client_t *client = s->clients;
     int ret;
-    DEBUG(1, "cs: send_event(sock %d, event %d, pri %d)\n",
-	  s->sock, event, priority);
+    cs_dbg(s, 1, "send_event(event %d, pri %d)\n",
+	   event, priority);
     ret = 0;
     if (s->state & SOCKET_CARDBUS)
 	    return 0;
@@ -516,26 +522,14 @@ static int send_event(struct pcmcia_sock
     return ret;
 } /* send_event */
 
-static void pcmcia_error(struct pcmcia_socket *skt, const char *fmt, ...)
-{
-	static char buf[128];
-	va_list ap;
-	int len;
-
-	va_start(ap, fmt);
-	len = vsnprintf(buf, sizeof(buf), fmt, ap);
-	va_end(ap);
-	buf[len] = '\0';
-
-	printk(KERN_ERR "PCMCIA: socket %p: %s", skt, buf);
-}
-
 #define cs_to_timeout(cs) (((cs) * HZ + 99) / 100)
 
 static void socket_remove_drivers(struct pcmcia_socket *skt)
 {
 	client_t *client;
 
+	cs_dbg(skt, 4, "remove_drivers\n");
+
 	send_event(skt, CS_EVENT_CARD_REMOVAL, CS_EVENT_PRI_HIGH);
 
 	for (client = skt->clients; client; client = client->next)
@@ -545,6 +539,8 @@ static void socket_remove_drivers(struct
 
 static void socket_shutdown(struct pcmcia_socket *skt)
 {
+	cs_dbg(skt, 4, "shutdown\n");
+
 	socket_remove_drivers(skt);
 	set_current_state(TASK_UNINTERRUPTIBLE);
 	schedule_timeout(cs_to_timeout(shutdown_delay));
@@ -556,6 +552,8 @@ static int socket_reset(struct pcmcia_so
 {
 	int status, i;
 
+	cs_dbg(skt, 4, "reset\n");
+
 	skt->socket.flags |= SS_OUTPUT_ENA | SS_RESET;
 	skt->ops->set_socket(skt, &skt->socket);
 	udelay((long)reset_time);
@@ -578,7 +576,7 @@ static int socket_reset(struct pcmcia_so
 		schedule_timeout(cs_to_timeout(unreset_check));
 	}
 
-	pcmcia_error(skt, "time out after reset.\n");
+	cs_err(skt, "time out after reset.\n");
 	return CS_GENERAL_FAILURE;
 }
 
@@ -586,6 +584,8 @@ static int socket_setup(struct pcmcia_so
 {
 	int status, i;
 
+	cs_dbg(skt, 4, "setup\n");
+
 	skt->ops->get_status(skt, &status);
 	if (!(status & SS_DETECT))
 		return CS_NO_CARD;
@@ -606,14 +606,14 @@ static int socket_setup(struct pcmcia_so
 	}
 
 	if (status & SS_PENDING) {
-		pcmcia_error(skt, "voltage interrogation timed out.\n");
+		cs_err(skt, "voltage interrogation timed out.\n");
 		return CS_GENERAL_FAILURE;
 	}
 
 	if (status & SS_CARDBUS) {
 		skt->state |= SOCKET_CARDBUS;
 #ifndef CONFIG_CARDBUS
-		pcmcia_error(skt, "cardbus cards are not supported.\n");
+		cs_err(skt, "cardbus cards are not supported.\n");
 		return CS_BAD_TYPE;
 #endif
 	}
@@ -626,7 +626,7 @@ static int socket_setup(struct pcmcia_so
 	else if (!(status & SS_XVCARD))
 		skt->socket.Vcc = skt->socket.Vpp = 50;
 	else {
-		pcmcia_error(skt, "unsupported voltage key.\n");
+		cs_err(skt, "unsupported voltage key.\n");
 		return CS_BAD_TYPE;
 	}
 	skt->socket.flags = 0;
@@ -640,7 +640,7 @@ static int socket_setup(struct pcmcia_so
 
 	skt->ops->get_status(skt, &status);
 	if (!(status & SS_POWERON)) {
-		pcmcia_error(skt, "unable to apply power.\n");
+		cs_err(skt, "unable to apply power.\n");
 		return CS_BAD_TYPE;
 	}
 
@@ -655,6 +655,8 @@ static int socket_insert(struct pcmcia_s
 {
 	int ret;
 
+	cs_dbg(skt, 4, "insert\n");
+
 	if (!cs_socket_get(skt))
 		return CS_NO_CARD;
 
@@ -667,6 +669,8 @@ static int socket_insert(struct pcmcia_s
 			skt->state |= SOCKET_CARDBUS_CONFIG;
 		}
 #endif
+		cs_dbg(skt, 4, "insert done\n");
+
 		send_event(skt, CS_EVENT_CARD_INSERTION, CS_EVENT_PRI_LOW);
 	} else {
 		socket_shutdown(skt);
@@ -832,6 +836,7 @@ static int pccardd(void *__skt)
  */
 void pcmcia_parse_events(struct pcmcia_socket *s, u_int events)
 {
+	cs_dbg(s, 4, "parse_events: events %08x\n", events);
 	if (s->thread) {
 		spin_lock(&s->thread_lock);
 		s->thread_events |= events;
@@ -857,15 +862,15 @@ static int alloc_io_space(struct pcmcia_
     align = (*base) ? (lines ? 1<<lines : 0) : 1;
     if (align && (align < num)) {
 	if (*base) {
-	    DEBUG(0, "odd IO request: num %04x align %04x\n",
-		  num, align);
+	    cs_dbg(s, 0, "odd IO request: num %04x align %04x\n",
+		   num, align);
 	    align = 0;
 	} else
 	    while (align && (align < num)) align <<= 1;
     }
     if (*base & ~(align-1)) {
-	DEBUG(0, "odd IO request: base %04x align %04x\n",
-	      *base, align);
+	cs_dbg(s, 0, "odd IO request: base %04x align %04x\n",
+	       *base, align);
 	align = 0;
     }
     if ((s->features & SS_CAP_STATIC_MAP) && s->io_offset) {
@@ -1010,8 +1015,8 @@ int pcmcia_bind_device(bind_req_t *req)
     init_waitqueue_head(&client->mtd_req);
     client->next = s->clients;
     s->clients = client;
-    DEBUG(1, "cs: bind_device(): client 0x%p, sock %p, dev %s\n",
-	  client, client->Socket, client->dev_info);
+    cs_dbg(s, 1, "bind_device(): client 0x%p, dev %s\n",
+	   client, client->dev_info);
     return CS_SUCCESS;
 } /* bind_device */
 
@@ -1046,8 +1051,8 @@ int pcmcia_bind_mtd(mtd_bind_t *req)
 	return CS_BAD_OFFSET;
     strlcpy(region->dev_info, (char *)req->dev_info, DEV_NAME_LEN);
     
-    DEBUG(1, "cs: bind_mtd(): attr 0x%x, offset 0x%x, dev %s\n",
-	  req->Attributes, req->CardOffset, (char *)req->dev_info);
+    cs_dbg(s, 1, "bind_mtd(): attr 0x%x, offset 0x%x, dev %s\n",
+	   req->Attributes, req->CardOffset, (char *)req->dev_info);
     return CS_SUCCESS;
 } /* bind_mtd */
 
@@ -1061,9 +1066,12 @@ int pcmcia_deregister_client(client_hand
     u_long flags;
     int i;
     
-    DEBUG(1, "cs: deregister_client(%p)\n", handle);
     if (CHECK_HANDLE(handle))
 	return CS_BAD_HANDLE;
+
+    s = SOCKET(handle);
+    cs_dbg(s, 1, "deregister_client(%p)\n", handle);
+
     if (handle->state &
 	(CLIENT_IRQ_REQ|CLIENT_IO_REQ|CLIENT_CONFIG_LOCKED))
 	return CS_IN_USE;
@@ -1072,7 +1080,6 @@ int pcmcia_deregister_client(client_hand
 	    return CS_IN_USE;
 
     /* Disconnect all MTD links */
-    s = SOCKET(handle);
     if (handle->mtd_count) {
 	for (region = s->a_region; region; region = region->info.next)
 	    if (region->mtd == handle) region->mtd = NULL;
@@ -1543,8 +1550,8 @@ int pcmcia_register_client(client_handle
 	memset(s->config, 0, sizeof(config_t) * s->functions);
     }
     
-    DEBUG(1, "cs: register_client(): client 0x%p, sock %p, dev %s\n",
-	  client, client->Socket, client->dev_info);
+    cs_dbg(s, 1, "register_client(): client 0x%p, dev %s\n",
+	   client, client->dev_info);
     if (client->EventMask & CS_EVENT_REGISTRATION_COMPLETE)
 	EVENT(client, CS_EVENT_REGISTRATION_COMPLETE, CS_EVENT_PRI_LOW);
 
@@ -2077,8 +2084,8 @@ int pcmcia_reset_card(client_handle_t ha
     
 	if (CHECK_HANDLE(handle))
 		return CS_BAD_HANDLE;
-	DEBUG(1, "cs: resetting socket %p\n", handle->Socket);
 	skt = SOCKET(handle);
+	cs_dbg(skt, 1, "resetting socket\n");
 
 	down(&skt->skt_sem);
 	do {
@@ -2126,8 +2133,8 @@ int pcmcia_suspend_card(client_handle_t 
     
 	if (CHECK_HANDLE(handle))
 		return CS_BAD_HANDLE;
-	DEBUG(1, "cs: suspending socket %p\n", handle->Socket);
 	skt = SOCKET(handle);
+	cs_dbg(skt, 1, "suspending socket\n");
 
 	down(&skt->skt_sem);
 	do {
@@ -2153,8 +2160,8 @@ int pcmcia_resume_card(client_handle_t h
     
 	if (CHECK_HANDLE(handle))
 		return CS_BAD_HANDLE;
-	DEBUG(1, "cs: waking up socket %p\n", handle->Socket);
 	skt = SOCKET(handle);
+	cs_dbg(skt, 1, "waking up socket\n");
 
 	down(&skt->skt_sem);
 	do {
@@ -2186,8 +2193,8 @@ int pcmcia_eject_card(client_handle_t ha
     
 	if (CHECK_HANDLE(handle))
 		return CS_BAD_HANDLE;
-	DEBUG(1, "cs: user eject request on socket %p\n", handle->Socket);
 	skt = SOCKET(handle);
+	cs_dbg(skt, 1, "user eject request\n");
 
 	down(&skt->skt_sem);
 	do {
@@ -2215,8 +2222,8 @@ int pcmcia_insert_card(client_handle_t h
 
 	if (CHECK_HANDLE(handle))
 		return CS_BAD_HANDLE;
-	DEBUG(1, "cs: user insert request on socket %p\n", handle->Socket);
 	skt = SOCKET(handle);
+	cs_dbg(skt, 1, "user insert request\n");
 
 	down(&skt->skt_sem);
 	do {
@@ -2360,7 +2367,6 @@ static int __init init_pcmcia_cs(void)
 {
     printk(KERN_INFO "%s\n", release);
     printk(KERN_INFO "  %s\n", options);
-    DEBUG(0, "%s\n", version);
     class_register(&pcmcia_socket_class);
 
     return 0;
--- diff/drivers/pcmcia/cs_internal.h	2003-09-30 15:46:16.000000000 +0100
+++ source/drivers/pcmcia/cs_internal.h	2004-02-23 13:56:44.000000000 +0000
@@ -167,7 +167,6 @@ int replace_cis(client_handle_t handle, 
 int read_tuple(client_handle_t handle, cisdata_t code, void *parse);
 
 /* In bulkmem.c */
-void retry_erase_list(struct erase_busy_t *list, u_int cause);
 int get_first_region(client_handle_t handle, region_info_t *rgn);
 int get_next_region(client_handle_t handle, region_info_t *rgn);
 int register_mtd(client_handle_t handle, mtd_reg_t *reg);
@@ -195,10 +194,19 @@ extern struct rw_semaphore pcmcia_socket
 extern struct list_head pcmcia_socket_list;
 
 #ifdef PCMCIA_DEBUG
-extern int pc_debug;
-#define DEBUG(n, args...) do { if (pc_debug>(n)) printk(KERN_DEBUG args); } while (0)
+extern int cs_debug_level(int);
+
+#define cs_dbg(skt, lvl, fmt, arg...) do {		\
+	if (cs_debug_level(lvl))			\
+		printk(KERN_DEBUG "cs: %s: " fmt, 	\
+		       (skt)->dev.class_id, ## arg);	\
+} while (0)
+
 #else
-#define DEBUG(n, args...) do { } while (0)
+#define cs_dbg(skt, lvl, fmt, arg...) do { } while (0)
 #endif
 
+#define cs_err(skt, fmt, arg...) \
+	printk(KERN_ERR "cs: %s: " fmt, (skt)->dev.class_id , ## arg)
+
 #endif /* _LINUX_CS_INTERNAL_H */
--- diff/drivers/pcmcia/ds.c	2004-02-09 10:36:11.000000000 +0000
+++ source/drivers/pcmcia/ds.c	2004-02-23 13:56:44.000000000 +0000
@@ -33,6 +33,7 @@
 
 #include <linux/config.h>
 #include <linux/module.h>
+#include <linux/moduleparam.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/major.h>
@@ -69,13 +70,17 @@ MODULE_AUTHOR("David Hinds <dahinds@user
 MODULE_DESCRIPTION("PCMCIA Driver Services");
 MODULE_LICENSE("Dual MPL/GPL");
 
-#define INT_MODULE_PARM(n, v) static int n = v; MODULE_PARM(n, "i")
+#ifdef DEBUG
+static int pc_debug;
 
-#ifdef PCMCIA_DEBUG
-INT_MODULE_PARM(pc_debug, PCMCIA_DEBUG);
-#define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args)
+module_param(pc_debug, int, 0644);
+
+#define debug(lvl, fmt, arg...) do {				\
+	if (pc_debug > (lvl))					\
+		printk(KERN_DEBUG "ds: " fmt, ## arg);		\
+} while (0)
 #else
-#define DEBUG(n, args...)
+#define debug(lvl, fmt, arg...) do { } while (0)
 #endif
 
 /*====================================================================*/
@@ -277,7 +282,7 @@ static int ds_event(event_t event, int p
 {
     struct pcmcia_bus_socket *s;
 
-    DEBUG(1, "ds: ds_event(0x%06x, %d, 0x%p)\n",
+    debug(1, "ds_event(0x%06x, %d, 0x%p)\n",
 	  event, priority, args->client_handle);
     s = args->client_data;
     
@@ -353,7 +358,7 @@ static int bind_request(struct pcmcia_bu
     if (!s)
 	    return -EINVAL;
 
-    DEBUG(2, "bind_request(%d, '%s')\n", s->parent->sock,
+    debug(2, "bind_request(%d, '%s')\n", s->parent->sock,
 	  (char *)bind_info->dev_info);
     driver = get_pcmcia_driver(&bind_info->dev_info);
     if (!driver)
@@ -484,7 +489,7 @@ static int unbind_request(struct pcmcia_
 {
     socket_bind_t **b, *c;
 
-    DEBUG(2, "unbind_request(%d, '%s')\n", s->parent->sock,
+    debug(2, "unbind_request(%d, '%s')\n", s->parent->sock,
 	  (char *)bind_info->dev_info);
     for (b = &s->bind; *b; b = &(*b)->next)
 	if ((strcmp((char *)(*b)->driver->drv.name,
@@ -518,7 +523,7 @@ static int ds_open(struct inode *inode, 
     struct pcmcia_bus_socket *s;
     user_info_t *user;
 
-    DEBUG(0, "ds_open(socket %d)\n", i);
+    debug(0, "ds_open(socket %d)\n", i);
 
     s = pcmcia_get_bus_socket(i);
     if (!s)
@@ -552,7 +557,7 @@ static int ds_release(struct inode *inod
     struct pcmcia_bus_socket *s;
     user_info_t *user, **link;
 
-    DEBUG(0, "ds_release(socket %d)\n", iminor(inode));
+    debug(0, "ds_release(socket %d)\n", iminor(inode));
 
     user = file->private_data;
     if (CHECK_USER(user))
@@ -588,7 +593,7 @@ static ssize_t ds_read(struct file *file
     user_info_t *user;
     int ret;
 
-    DEBUG(2, "ds_read(socket %d)\n", iminor(inode));
+    debug(2, "ds_read(socket %d)\n", iminor(file->f_dentry->d_inode));
     
     if (count < 4)
 	return -EINVAL;
@@ -616,7 +621,7 @@ static ssize_t ds_write(struct file *fil
     struct pcmcia_bus_socket *s;
     user_info_t *user;
 
-    DEBUG(2, "ds_write(socket %d)\n", iminor(inode));
+    debug(2, "ds_write(socket %d)\n", iminor(file->f_dentry->d_inode));
     
     if (count != 4)
 	return -EINVAL;
@@ -650,7 +655,7 @@ static u_int ds_poll(struct file *file, 
     struct pcmcia_bus_socket *s;
     user_info_t *user;
 
-    DEBUG(2, "ds_poll(socket %d)\n", iminor(inode));
+    debug(2, "ds_poll(socket %d)\n", iminor(file->f_dentry->d_inode));
     
     user = file->private_data;
     if (CHECK_USER(user))
@@ -677,7 +682,7 @@ static int ds_ioctl(struct inode * inode
     ds_ioctl_arg_t buf;
     user_info_t *user;
 
-    DEBUG(2, "ds_ioctl(socket %d, %#x, %#lx)\n", iminor(inode), cmd, arg);
+    debug(2, "ds_ioctl(socket %d, %#x, %#lx)\n", iminor(inode), cmd, arg);
     
     user = file->private_data;
     if (CHECK_USER(user))
@@ -697,14 +702,14 @@ static int ds_ioctl(struct inode * inode
     if (cmd & IOC_IN) {
 	err = verify_area(VERIFY_READ, (char *)arg, size);
 	if (err) {
-	    DEBUG(3, "ds_ioctl(): verify_read = %d\n", err);
+	    debug(3, "ds_ioctl(): verify_read = %d\n", err);
 	    return err;
 	}
     }
     if (cmd & IOC_OUT) {
 	err = verify_area(VERIFY_WRITE, (char *)arg, size);
 	if (err) {
-	    DEBUG(3, "ds_ioctl(): verify_write = %d\n", err);
+	    debug(3, "ds_ioctl(): verify_write = %d\n", err);
 	    return err;
 	}
     }
@@ -806,7 +811,7 @@ static int ds_ioctl(struct inode * inode
     }
     
     if ((err == 0) && (ret != CS_SUCCESS)) {
-	DEBUG(2, "ds_ioctl: ret = %d\n", ret);
+	debug(2, "ds_ioctl: ret = %d\n", ret);
 	switch (ret) {
 	case CS_BAD_SOCKET: case CS_NO_CARD:
 	    err = -ENODEV; break;
--- diff/drivers/pcmcia/i82365.c	2004-01-19 10:22:58.000000000 +0000
+++ source/drivers/pcmcia/i82365.c	2004-02-23 13:56:44.000000000 +0000
@@ -32,6 +32,7 @@
 ======================================================================*/
 
 #include <linux/module.h>
+#include <linux/moduleparam.h>
 #include <linux/init.h>
 #include <linux/config.h>
 #include <linux/types.h>
@@ -66,14 +67,20 @@
 #include "ricoh.h"
 #include "o2micro.h"
 
-#ifdef PCMCIA_DEBUG
-static int pc_debug = PCMCIA_DEBUG;
-MODULE_PARM(pc_debug, "i");
-#define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args)
+#ifdef DEBUG
 static const char *version =
 "i82365.c 1.265 1999/11/10 18:36:21 (David Hinds)";
+
+static int pc_debug;
+
+module_param(pc_debug, int, 0644);
+
+#define debug(lvl, fmt, arg...) do {				\
+	if (pc_debug > (lvl))					\
+		printk(KERN_DEBUG "i82365: " fmt, ## arg);	\
+} while (0)
 #else
-#define DEBUG(n, args...) do { } while (0)
+#define debug(lvl, fmt, arg...) do { } while (0)
 #endif
 
 static irqreturn_t i365_count_irq(int, void *, struct pt_regs *);
@@ -496,13 +503,13 @@ static irqreturn_t i365_count_irq(int ir
 {
     i365_get(irq_sock, I365_CSC);
     irq_hits++;
-    DEBUG(2, "-> hit on irq %d\n", irq);
+    debug(2, "-> hit on irq %d\n", irq);
     return IRQ_HANDLED;
 }
 
 static u_int __init test_irq(u_short sock, int irq)
 {
-    DEBUG(2, "  testing ISA irq %d\n", irq);
+    debug(2, "  testing ISA irq %d\n", irq);
     if (request_irq(irq, i365_count_irq, 0, "scan", i365_count_irq) != 0)
 	return 1;
     irq_hits = 0; irq_sock = sock;
@@ -510,7 +517,7 @@ static u_int __init test_irq(u_short soc
     schedule_timeout(HZ/100);
     if (irq_hits) {
 	free_irq(irq, i365_count_irq);
-	DEBUG(2, "    spurious hit!\n");
+	debug(2, "    spurious hit!\n");
 	return 1;
     }
 
@@ -523,7 +530,7 @@ static u_int __init test_irq(u_short soc
 
     /* mask all interrupts */
     i365_set(sock, I365_CSCINT, 0);
-    DEBUG(2, "    hits = %d\n", irq_hits);
+    debug(2, "    hits = %d\n", irq_hits);
     
     return (irq_hits != 1);
 }
@@ -850,7 +857,7 @@ static irqreturn_t pcic_interrupt(int ir
     u_long flags = 0;
     int handled = 0;
 
-    DEBUG(4, "i82365: pcic_interrupt(%d)\n", irq);
+    debug(4, "pcic_interrupt(%d)\n", irq);
 
     for (j = 0; j < 20; j++) {
 	active = 0;
@@ -874,7 +881,7 @@ static irqreturn_t pcic_interrupt(int ir
 		events |= (csc & I365_CSC_READY) ? SS_READY : 0;
 	    }
 	    ISA_UNLOCK(i, flags);
-	    DEBUG(2, "i82365: socket %d event 0x%02x\n", i, events);
+	    debug(2, "socket %d event 0x%02x\n", i, events);
 
 	    if (events)
 		pcmcia_parse_events(&socket[i].socket, events);
@@ -886,7 +893,7 @@ static irqreturn_t pcic_interrupt(int ir
     if (j == 20)
 	printk(KERN_NOTICE "i82365: infinite loop in interrupt handler\n");
 
-    DEBUG(4, "i82365: interrupt done\n");
+    debug(4, "interrupt done\n");
     return IRQ_RETVAL(handled);
 } /* pcic_interrupt */
 
@@ -928,7 +935,7 @@ static int i365_get_status(u_short sock,
 	}
     }
     
-    DEBUG(1, "i82365: GetStatus(%d) = %#4.4x\n", sock, *value);
+    debug(1, "GetStatus(%d) = %#4.4x\n", sock, *value);
     return 0;
 } /* i365_get_status */
 
@@ -998,7 +1005,7 @@ static int i365_get_socket(u_short sock,
 	state->csc_mask |= (reg & I365_CSC_READY) ? SS_READY : 0;
     }
     
-    DEBUG(1, "i82365: GetSocket(%d) = flags %#3.3x, Vcc %d, Vpp %d, "
+    debug(1, "GetSocket(%d) = flags %#3.3x, Vcc %d, Vpp %d, "
 	  "io_irq %d, csc_mask %#2.2x\n", sock, state->flags,
 	  state->Vcc, state->Vpp, state->io_irq, state->csc_mask);
     return 0;
@@ -1011,7 +1018,7 @@ static int i365_set_socket(u_short sock,
     struct i82365_socket *t = &socket[sock];
     u_char reg;
     
-    DEBUG(1, "i82365: SetSocket(%d, flags %#3.3x, Vcc %d, Vpp %d, "
+    debug(1, "SetSocket(%d, flags %#3.3x, Vcc %d, Vpp %d, "
 	  "io_irq %d, csc_mask %#2.2x)\n", sock, state->flags,
 	  state->Vcc, state->Vpp, state->io_irq, state->csc_mask);
     
@@ -1120,7 +1127,7 @@ static int i365_set_io_map(u_short sock,
 {
     u_char map, ioctl;
     
-    DEBUG(1, "i82365: SetIOMap(%d, %d, %#2.2x, %d ns, "
+    debug(1, "SetIOMap(%d, %d, %#2.2x, %d ns, "
 	  "%#4.4x-%#4.4x)\n", sock, io->map, io->flags,
 	  io->speed, io->start, io->stop);
     map = io->map;
@@ -1150,7 +1157,7 @@ static int i365_set_mem_map(u_short sock
     u_short base, i;
     u_char map;
     
-    DEBUG(1, "i82365: SetMemMap(%d, %d, %#2.2x, %d ns, %#5.5lx-%#5.5"
+    debug(1, "SetMemMap(%d, %d, %#2.2x, %d ns, %#5.5lx-%#5.5"
 	  "lx, %#5.5x)\n", sock, mem->map, mem->flags, mem->speed,
 	  mem->sys_start, mem->sys_stop, mem->card_start);
 
--- diff/drivers/pcmcia/sa11xx_core.c	2003-10-09 09:47:34.000000000 +0100
+++ source/drivers/pcmcia/sa11xx_core.c	2004-02-23 13:56:44.000000000 +0000
@@ -35,6 +35,7 @@
  */
 
 #include <linux/module.h>
+#include <linux/moduleparam.h>
 #include <linux/init.h>
 #include <linux/config.h>
 #include <linux/cpufreq.h>
@@ -54,8 +55,19 @@
 #include "sa11xx_core.h"
 #include "sa1100.h"
 
-#ifdef PCMCIA_DEBUG
+#ifdef DEBUG
 static int pc_debug;
+
+module_param(pc_debug, int, 0644);
+
+#define debug(skt, lvl, fmt, arg...) do {			\
+	if (pc_debug > (lvl))					\
+		printk(KERN_DEBUG "skt%u: %s: " fmt,		\
+		       (skt)->nr, __func__, ## arg);		\
+} while (0)
+
+#else
+#define debug(skt, lvl, fmt, arg...) do { } while (0)
 #endif
 
 /* This structure maintains housekeeping state for each socket, such
@@ -141,8 +153,8 @@ sa1100_pcmcia_set_mecr(struct sa1100_pcm
 
 	local_irq_restore(flags);
 
-	DEBUG(4, "%s(): sock %u FAST %X  BSM %X  BSA %X  BSIO %X\n",
-	      __FUNCTION__, skt->nr, MECR_FAST_GET(mecr, skt->nr),
+	debug(skt, 4, "FAST %X  BSM %X  BSA %X  BSIO %X\n",
+	      MECR_FAST_GET(mecr, skt->nr),
 	      MECR_BSM_GET(mecr, skt->nr), MECR_BSA_GET(mecr, skt->nr),
 	      MECR_BSIO_GET(mecr, skt->nr));
 
@@ -229,7 +241,7 @@ static int sa1100_pcmcia_sock_init(struc
 {
 	struct sa1100_pcmcia_socket *skt = to_sa1100_socket(sock);
 
-	DEBUG(2, "%s(): initializing socket %u\n", __FUNCTION__, skt->nr);
+	debug(skt, 2, "initializing socket\n");
 
 	skt->ops->socket_init(skt);
 	return 0;
@@ -250,7 +262,7 @@ static int sa1100_pcmcia_suspend(struct 
 	struct sa1100_pcmcia_socket *skt = to_sa1100_socket(sock);
 	int ret;
 
-	DEBUG(2, "%s(): suspending socket %u\n", __FUNCTION__, skt->nr);
+	debug(skt, 2, "suspending socket\n");
 
 	ret = sa1100_pcmcia_config_skt(skt, &dead_socket);
 	if (ret == 0)
@@ -268,7 +280,7 @@ static void sa1100_check_status(struct s
 {
 	unsigned int events;
 
-	DEBUG(4, "%s(): entering PCMCIA monitoring thread\n", __FUNCTION__);
+	debug(skt, 4, "entering PCMCIA monitoring thread\n");
 
 	do {
 		unsigned int status;
@@ -281,7 +293,7 @@ static void sa1100_check_status(struct s
 		skt->status = status;
 		spin_unlock_irqrestore(&status_lock, flags);
 
-		DEBUG(2, "events: %s%s%s%s%s%s\n",
+		debug(skt, 4, "events: %s%s%s%s%s%s\n",
 			events == 0         ? "<NONE>"   : "",
 			events & SS_DETECT  ? "DETECT "  : "",
 			events & SS_READY   ? "READY "   : "",
@@ -301,7 +313,7 @@ static void sa1100_check_status(struct s
 static void sa1100_pcmcia_poll_event(unsigned long dummy)
 {
 	struct sa1100_pcmcia_socket *skt = (struct sa1100_pcmcia_socket *)dummy;
-	DEBUG(4, "%s(): polling for events\n", __FUNCTION__);
+	debug(skt, 4, "polling for events\n");
 
 	mod_timer(&skt->poll_timer, jiffies + SA1100_PCMCIA_POLL_PERIOD);
 
@@ -322,7 +334,7 @@ static irqreturn_t sa1100_pcmcia_interru
 {
 	struct sa1100_pcmcia_socket *skt = dev;
 
-	DEBUG(3, "%s(): servicing IRQ %d\n", __FUNCTION__, irq);
+	debug(skt, 3, "servicing IRQ %d\n", irq);
 
 	sa1100_check_status(skt);
 
@@ -371,7 +383,7 @@ sa1100_pcmcia_get_socket(struct pcmcia_s
 {
   struct sa1100_pcmcia_socket *skt = to_sa1100_socket(sock);
 
-  DEBUG(2, "%s() for sock %u\n", __FUNCTION__, skt->nr);
+  debug(skt, 2, "\n");
 
   *state = skt->cs_state;
 
@@ -393,22 +405,19 @@ sa1100_pcmcia_set_socket(struct pcmcia_s
 {
   struct sa1100_pcmcia_socket *skt = to_sa1100_socket(sock);
 
-  DEBUG(2, "%s() for sock %u\n", __FUNCTION__, skt->nr);
-
-  DEBUG(3, "\tmask:  %s%s%s%s%s%s\n\tflags: %s%s%s%s%s%s\n",
-	(state->csc_mask==0)?"<NONE>":"",
+  debug(skt, 2, "mask: %s%s%s%s%s%sflags: %s%s%s%s%s%sVcc %d Vpp %d irq %d\n",
+	(state->csc_mask==0)?"<NONE> ":"",
 	(state->csc_mask&SS_DETECT)?"DETECT ":"",
 	(state->csc_mask&SS_READY)?"READY ":"",
 	(state->csc_mask&SS_BATDEAD)?"BATDEAD ":"",
 	(state->csc_mask&SS_BATWARN)?"BATWARN ":"",
 	(state->csc_mask&SS_STSCHG)?"STSCHG ":"",
-	(state->flags==0)?"<NONE>":"",
+	(state->flags==0)?"<NONE> ":"",
 	(state->flags&SS_PWR_AUTO)?"PWR_AUTO ":"",
 	(state->flags&SS_IOCARD)?"IOCARD ":"",
 	(state->flags&SS_RESET)?"RESET ":"",
 	(state->flags&SS_SPKR_ENA)?"SPKR_ENA ":"",
-	(state->flags&SS_OUTPUT_ENA)?"OUTPUT_ENA ":"");
-  DEBUG(3, "\tVcc %d  Vpp %d  irq %d\n",
+	(state->flags&SS_OUTPUT_ENA)?"OUTPUT_ENA ":"",
 	state->Vcc, state->Vpp, state->io_irq);
 
   return sa1100_pcmcia_config_skt(skt, state);
@@ -430,11 +439,9 @@ sa1100_pcmcia_set_io_map(struct pcmcia_s
 	struct sa1100_pcmcia_socket *skt = to_sa1100_socket(sock);
 	unsigned short speed = map->speed;
 
-	DEBUG(2, "%s() for sock %u\n", __FUNCTION__, skt->nr);
-
-	DEBUG(3, "\tmap %u  speed %u\n\tstart 0x%08x  stop 0x%08x\n",
+	debug(skt, 2, "map %u  speed %u start 0x%08x stop 0x%08x\n",
 		map->map, map->speed, map->start, map->stop);
-	DEBUG(3, "\tflags: %s%s%s%s%s%s%s%s\n",
+	debug(skt, 2, "flags: %s%s%s%s%s%s%s%s\n",
 		(map->flags==0)?"<NONE>":"",
 		(map->flags&MAP_ACTIVE)?"ACTIVE ":"",
 		(map->flags&MAP_16BIT)?"16BIT ":"",
@@ -487,11 +494,9 @@ sa1100_pcmcia_set_mem_map(struct pcmcia_
 	struct resource *res;
 	unsigned short speed = map->speed;
 
-	DEBUG(2, "%s() for sock %u\n", __FUNCTION__, skt->nr);
-
-	DEBUG(3, "\tmap %u speed %u card_start %08x\n",
+	debug(skt, 2, "map %u speed %u card_start %08x\n",
 		map->map, map->speed, map->card_start);
-	DEBUG(3, "\tflags: %s%s%s%s%s%s%s%s\n",
+	debug(skt, 2, "flags: %s%s%s%s%s%s%s%s\n",
 		(map->flags==0)?"<NONE>":"",
 		(map->flags&MAP_ACTIVE)?"ACTIVE ":"",
 		(map->flags&MAP_16BIT)?"16BIT ":"",
@@ -913,23 +918,13 @@ sa1100_pcmcia_notifier(struct notifier_b
 
 	switch (val) {
 	case CPUFREQ_PRECHANGE:
-		if (freqs->new > freqs->old) {
-			DEBUG(2, "%s(): new frequency %u.%uMHz > %u.%uMHz, "
-				"pre-updating\n", __FUNCTION__,
-			    freqs->new / 1000, (freqs->new / 100) % 10,
-			    freqs->old / 1000, (freqs->old / 100) % 10);
+		if (freqs->new > freqs->old)
 			sa1100_pcmcia_update_mecr(freqs->new);
-		}
 		break;
 
 	case CPUFREQ_POSTCHANGE:
-		if (freqs->new < freqs->old) {
-			DEBUG(2, "%s(): new frequency %u.%uMHz < %u.%uMHz, "
-				"post-updating\n", __FUNCTION__,
-			    freqs->new / 1000, (freqs->new / 100) % 10,
-			    freqs->old / 1000, (freqs->old / 100) % 10);
+		if (freqs->new < freqs->old)
 			sa1100_pcmcia_update_mecr(freqs->new);
-		}
 		break;
 	}
 
--- diff/drivers/pcmcia/tcic.c	2003-10-27 09:20:38.000000000 +0000
+++ source/drivers/pcmcia/tcic.c	2004-02-23 13:56:44.000000000 +0000
@@ -32,6 +32,7 @@
 ======================================================================*/
 
 #include <linux/module.h>
+#include <linux/moduleparam.h>
 #include <linux/init.h>
 #include <linux/types.h>
 #include <linux/fcntl.h>
@@ -55,14 +56,20 @@
 #include <pcmcia/ss.h>
 #include "tcic.h"
 
-#ifdef PCMCIA_DEBUG
-static int pc_debug = PCMCIA_DEBUG;
+#ifdef DEBUG
+static int pc_debug;
+
+module_param(pc_debug, int, 0644);
 MODULE_PARM(pc_debug, "i");
 static const char *version =
 "tcic.c 1.111 2000/02/15 04:13:12 (David Hinds)";
-#define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args)
+
+#define debug(lvl, fmt, arg...) do {				\
+	if (pc_debug > (lvl))					\
+		printk(KERN_DEBUG "tcic: " fmt, ## arg);	\
+} while (0)
 #else
-#define DEBUG(n, args...)
+#define debug(lvl, fmt, arg...) do { } while (0)
 #endif
 
 MODULE_AUTHOR("David Hinds <dahinds@users.sourceforge.net>");
@@ -133,7 +140,7 @@ static struct tcic_socket socket_table[2
    to map to irq 11, but is coded as 0 or 1 in the irq registers. */
 #define TCIC_IRQ(x) ((x) ? (((x) == 11) ? 1 : (x)) : 15)
 
-#ifdef PCMCIA_DEBUG_X
+#ifdef DEBUG_X
 static u_char tcic_getb(u_char reg)
 {
     u_char val = inb(tcic_base+reg);
@@ -168,7 +175,7 @@ static void tcic_setw(u_char reg, u_shor
 
 static void tcic_setl(u_char reg, u_int data)
 {
-#ifdef PCMCIA_DEBUG_X
+#ifdef DEBUG_X
     printk(KERN_DEBUG "tcic_setl(%#x, %#lx)\n", tcic_base+reg, data);
 #endif
     outw(data & 0xffff, tcic_base+reg);
@@ -573,7 +580,7 @@ static irqreturn_t tcic_interrupt(int ir
     } else
 	active = 1;
 
-    DEBUG(2, "tcic: tcic_interrupt()\n");
+    debug(2, "tcic_interrupt()\n");
     
     for (i = 0; i < sockets; i++) {
 	psock = socket_table[i].psock;
@@ -610,13 +617,13 @@ static irqreturn_t tcic_interrupt(int ir
     }
     active = 0;
     
-    DEBUG(2, "tcic: interrupt done\n");
+    debug(2, "interrupt done\n");
     return IRQ_HANDLED;
 } /* tcic_interrupt */
 
 static void tcic_timer(u_long data)
 {
-    DEBUG(2, "tcic: tcic_timer()\n");
+    debug(2, "tcic_timer()\n");
     tcic_timer_pending = 0;
     tcic_interrupt(0, NULL, NULL);
 } /* tcic_timer */
@@ -643,7 +650,7 @@ static int tcic_get_status(struct pcmcia
     reg = tcic_getb(TCIC_PWR);
     if (reg & (TCIC_PWR_VCC(psock)|TCIC_PWR_VPP(psock)))
 	*value |= SS_POWERON;
-    DEBUG(1, "tcic: GetStatus(%d) = %#2.2x\n", psock, *value);
+    debug(1, "GetStatus(%d) = %#2.2x\n", psock, *value);
     return 0;
 } /* tcic_get_status */
   
@@ -694,7 +701,7 @@ static int tcic_get_socket(struct pcmcia
 	state->csc_mask |= (scf2 & TCIC_SCF2_MRDY) ? 0 : SS_READY;
     }
 
-    DEBUG(1, "tcic: GetSocket(%d) = flags %#3.3x, Vcc %d, Vpp %d, "
+    debug(1, "GetSocket(%d) = flags %#3.3x, Vcc %d, Vpp %d, "
 	  "io_irq %d, csc_mask %#2.2x\n", psock, state->flags,
 	  state->Vcc, state->Vpp, state->io_irq, state->csc_mask);
     return 0;
@@ -708,7 +715,7 @@ static int tcic_set_socket(struct pcmcia
     u_char reg;
     u_short scf1, scf2;
 
-    DEBUG(1, "tcic: SetSocket(%d, flags %#3.3x, Vcc %d, Vpp %d, "
+    debug(1, "SetSocket(%d, flags %#3.3x, Vcc %d, Vpp %d, "
 	  "io_irq %d, csc_mask %#2.2x)\n", psock, state->flags,
 	  state->Vcc, state->Vpp, state->io_irq, state->csc_mask);
     tcic_setw(TCIC_ADDR+2, (psock << TCIC_SS_SHFT) | TCIC_ADR2_INDREG);
@@ -783,7 +790,7 @@ static int tcic_set_io_map(struct pcmcia
     u_int addr;
     u_short base, len, ioctl;
     
-    DEBUG(1, "tcic: SetIOMap(%d, %d, %#2.2x, %d ns, "
+    debug(1, "SetIOMap(%d, %d, %#2.2x, %d ns, "
 	  "%#4.4x-%#4.4x)\n", psock, io->map, io->flags,
 	  io->speed, io->start, io->stop);
     if ((io->map > 1) || (io->start > 0xffff) || (io->stop > 0xffff) ||
@@ -820,7 +827,7 @@ static int tcic_set_mem_map(struct pcmci
     u_short addr, ctl;
     u_long base, len, mmap;
 
-    DEBUG(1, "tcic: SetMemMap(%d, %d, %#2.2x, %d ns, "
+    debug(1, "SetMemMap(%d, %d, %#2.2x, %d ns, "
 	  "%#5.5lx-%#5.5lx, %#5.5x)\n", psock, mem->map, mem->flags,
 	  mem->speed, mem->sys_start, mem->sys_stop, mem->card_start);
     if ((mem->map > 3) || (mem->card_start > 0x3ffffff) ||
--- diff/drivers/pcmcia/yenta_socket.c	2004-01-19 10:22:58.000000000 +0000
+++ source/drivers/pcmcia/yenta_socket.c	2004-02-23 13:56:44.000000000 +0000
@@ -30,9 +30,9 @@
 
 
 #if 0
-#define DEBUG(x,args...)	printk(KERN_DEBUG "%s: " x, __FUNCTION__, ##args)
+#define debug(x,args...) printk(KERN_DEBUG "%s: " x, __FUNCTION__, ##args)
 #else
-#define DEBUG(x,args...)
+#define debug(x,args...)
 #endif
 
 /* Don't ask.. */
@@ -47,13 +47,13 @@
 static inline u32 cb_readl(struct yenta_socket *socket, unsigned reg)
 {
 	u32 val = readl(socket->base + reg);
-	DEBUG("%p %04x %08x\n", socket, reg, val);
+	debug("%p %04x %08x\n", socket, reg, val);
 	return val;
 }
 
 static inline void cb_writel(struct yenta_socket *socket, unsigned reg, u32 val)
 {
-	DEBUG("%p %04x %08x\n", socket, reg, val);
+	debug("%p %04x %08x\n", socket, reg, val);
 	writel(val, socket->base + reg);
 }
 
@@ -61,7 +61,7 @@ static inline u8 config_readb(struct yen
 {
 	u8 val;
 	pci_read_config_byte(socket->dev, offset, &val);
-	DEBUG("%p %04x %02x\n", socket, offset, val);
+	debug("%p %04x %02x\n", socket, offset, val);
 	return val;
 }
 
@@ -69,7 +69,7 @@ static inline u16 config_readw(struct ye
 {
 	u16 val;
 	pci_read_config_word(socket->dev, offset, &val);
-	DEBUG("%p %04x %04x\n", socket, offset, val);
+	debug("%p %04x %04x\n", socket, offset, val);
 	return val;
 }
 
@@ -77,32 +77,32 @@ static inline u32 config_readl(struct ye
 {
 	u32 val;
 	pci_read_config_dword(socket->dev, offset, &val);
-	DEBUG("%p %04x %08x\n", socket, offset, val);
+	debug("%p %04x %08x\n", socket, offset, val);
 	return val;
 }
 
 static inline void config_writeb(struct yenta_socket *socket, unsigned offset, u8 val)
 {
-	DEBUG("%p %04x %02x\n", socket, offset, val);
+	debug("%p %04x %02x\n", socket, offset, val);
 	pci_write_config_byte(socket->dev, offset, val);
 }
 
 static inline void config_writew(struct yenta_socket *socket, unsigned offset, u16 val)
 {
-	DEBUG("%p %04x %04x\n", socket, offset, val);
+	debug("%p %04x %04x\n", socket, offset, val);
 	pci_write_config_word(socket->dev, offset, val);
 }
 
 static inline void config_writel(struct yenta_socket *socket, unsigned offset, u32 val)
 {
-	DEBUG("%p %04x %08x\n", socket, offset, val);
+	debug("%p %04x %08x\n", socket, offset, val);
 	pci_write_config_dword(socket->dev, offset, val);
 }
 
 static inline u8 exca_readb(struct yenta_socket *socket, unsigned reg)
 {
 	u8 val = readb(socket->base + 0x800 + reg);
-	DEBUG("%p %04x %02x\n", socket, reg, val);
+	debug("%p %04x %02x\n", socket, reg, val);
 	return val;
 }
 
@@ -111,19 +111,19 @@ static inline u8 exca_readw(struct yenta
 	u16 val;
 	val = readb(socket->base + 0x800 + reg);
 	val |= readb(socket->base + 0x800 + reg + 1) << 8;
-	DEBUG("%p %04x %04x\n", socket, reg, val);
+	debug("%p %04x %04x\n", socket, reg, val);
 	return val;
 }
 
 static inline void exca_writeb(struct yenta_socket *socket, unsigned reg, u8 val)
 {
-	DEBUG("%p %04x %02x\n", socket, reg, val);
+	debug("%p %04x %02x\n", socket, reg, val);
 	writeb(val, socket->base + 0x800 + reg);
 }
 
 static void exca_writew(struct yenta_socket *socket, unsigned reg, u16 val)
 {
-	DEBUG("%p %04x %04x\n", socket, reg, val);
+	debug("%p %04x %04x\n", socket, reg, val);
 	writeb(val, socket->base + 0x800 + reg);
 	writeb(val >> 8, socket->base + 0x800 + reg + 1);
 }
--- diff/drivers/s390/Kconfig	2003-09-30 15:46:16.000000000 +0100
+++ source/drivers/s390/Kconfig	2004-02-23 13:56:45.000000000 +0000
@@ -164,25 +164,3 @@ config S390_TAPE_34XX
 	  It is safe to say "Y" here.
 
 endmenu
-
-
-config HOTPLUG
-	bool
-	default y
-	---help---
-	  Say Y here if you want to plug devices into your computer while
-	  the system is running, and be able to use them quickly.  In many
-	  cases, the devices can likewise be unplugged at any time too.
-
-	  One well known example of this is PCMCIA- or PC-cards, credit-card
-	  size devices such as network cards, modems or hard drives which are
-	  plugged into slots found on all modern laptop computers.  Another
-	  example, used on modern desktops as well as laptops, is USB.
-
-	  Enable HOTPLUG and KMOD, and build a modular kernel.  Get agent
-	  software (at <http://linux-hotplug.sourceforge.net/>) and install it.
-	  Then your kernel will automatically call out to a user mode "policy
-	  agent" (/sbin/hotplug) to load modules and set up software needed
-	  to use devices as you hotplug them.
-
-
--- diff/drivers/s390/block/Kconfig	2003-09-30 15:46:16.000000000 +0100
+++ source/drivers/s390/block/Kconfig	2004-02-23 13:56:45.000000000 +0000
@@ -11,6 +11,11 @@ config BLK_DEV_XPRAM
 	  This option is also available as a module which will be called
 	  xpram.  If unsure, say "N".
 
+config DCSSBLK
+	tristate "DCSSBLK support"
+	help
+	  Support for dcss block device
+
 config DASD
 	tristate "Support for DASD devices"
 	depends on CCW
@@ -47,3 +52,13 @@ config DASD_DIAG
 	  Select this option if you want to use CMS reserved Disks under VM
 	  with the Diagnose250 command.  If you are not running under VM or
 	  unsure what it is, say "N".
+
+config DASD_CMB
+	tristate "Compatibility interface for DASD channel measurement blocks"
+	depends on DASD
+	help
+	  This driver provides an additional interface to the channel measurement
+	  facility, which is normally accessed though sysfs, with a set of
+	  ioctl functions specific to the dasd driver.
+	  This is only needed if you want to use applications written for
+	  linux-2.4 dasd channel measurement facility interface.
--- diff/drivers/s390/block/Makefile	2003-02-13 11:46:53.000000000 +0000
+++ source/drivers/s390/block/Makefile	2004-02-23 13:56:45.000000000 +0000
@@ -12,4 +12,6 @@ obj-$(CONFIG_DASD) += dasd_mod.o
 obj-$(CONFIG_DASD_DIAG) += dasd_diag_mod.o
 obj-$(CONFIG_DASD_ECKD) += dasd_eckd_mod.o
 obj-$(CONFIG_DASD_FBA)  += dasd_fba_mod.o
+obj-$(CONFIG_DASD_CMB)  += dasd_cmb.o
 obj-$(CONFIG_BLK_DEV_XPRAM) += xpram.o
+obj-$(CONFIG_DCSSBLK) += dcssblk.o
--- diff/drivers/s390/block/dasd.c	2004-02-09 10:36:11.000000000 +0000
+++ source/drivers/s390/block/dasd.c	2004-02-23 13:56:44.000000000 +0000
@@ -7,7 +7,7 @@
  * Bugreports.to..: <Linux390@de.ibm.com>
  * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999-2001
  *
- * $Revision: 1.123 $
+ * $Revision: 1.129 $
  */
 
 #include <linux/config.h>
@@ -668,7 +668,7 @@ dasd_check_cqr(struct dasd_ccw_req *cqr)
 
 /*
  * Terminate the current i/o and set the request to failed.
- * ccw_device_halt/ccw_device_clear can fail if the i/o subsystem 
+ * ccw_device_clear can fail if the i/o subsystem
  * is in a bad mood.
  */
 int
@@ -684,10 +684,7 @@ dasd_term_IO(struct dasd_ccw_req * cqr)
 	retries = 0;
 	device = (struct dasd_device *) cqr->device;
 	while ((retries < 5) && (cqr->status == DASD_CQR_IN_IO)) {
-		if (retries < 2)
-			rc = ccw_device_halt(device->cdev, (long) cqr);
-		else
-			rc = ccw_device_clear(device->cdev, (long) cqr);
+		rc = ccw_device_clear(device->cdev, (long) cqr);
 		switch (rc) {
 		case 0:	/* termination successful */
 			cqr->status = DASD_CQR_FAILED;
@@ -736,6 +733,7 @@ dasd_start_IO(struct dasd_ccw_req * cqr)
 		return rc;
 	device = (struct dasd_device *) cqr->device;
 	cqr->startclk = get_clock();
+	cqr->starttime = jiffies;
 	rc = ccw_device_start(device->cdev, cqr->cpaddr, (long) cqr,
 			      cqr->lpm, 0);
 	switch (rc) {
@@ -788,14 +786,11 @@ dasd_timeout_device(unsigned long ptr)
 }
 
 /*
- * Setup timeout for a device.
+ * Setup timeout for a device in jiffies.
  */
 void
 dasd_set_timer(struct dasd_device *device, int expires)
 {
-	/* FIXME: timeouts are based on jiffies but the timeout
-	 * comparision in __dasd_check_expire is based on the
-	 * TOD clock. */
 	if (expires == 0) {
 		if (timer_pending(&device->timer))
 			del_timer(&device->timer);
@@ -1002,8 +997,7 @@ dasd_int_handler(struct ccw_device *cdev
 				"no memory for dstat...ignoring");
 #ifdef ERP_DEBUG
 		/* dump sense data */
-		if (device->discipline && device->discipline->dump_sense)
-			device->discipline->dump_sense(device, cqr);
+		dasd_log_sense(cqr, irb);
 #endif
 		switch (era) {
 		case dasd_era_fatal:
@@ -1079,8 +1073,11 @@ restart:
 				cqr->status = DASD_CQR_FAILED;
 				cqr->stopclk = get_clock();
 			} else {
-				erp_fn = device->discipline->erp_action(cqr);
-				erp_fn(cqr);
+				if (cqr->dstat->esw.esw0.erw.cons) {
+					erp_fn = device->discipline->erp_action(cqr);
+					erp_fn(cqr);
+				} else
+					dasd_default_erp_action(cqr);
 			}
 			goto restart;
 		}
@@ -1196,7 +1193,7 @@ __dasd_check_expire(struct dasd_device *
 	cqr = list_entry(device->ccw_queue.next, struct dasd_ccw_req, list);
 	if (cqr->status == DASD_CQR_IN_IO && cqr->expires != 0) {
 		now = get_clock();
-		if (cqr->expires * (TOD_SEC / HZ) + cqr->startclk < now) {
+		if (time_after_eq(jiffies, cqr->expires + cqr->starttime)) {
 			if (device->discipline->term_IO(cqr) != 0)
 				/* Hmpf, try again in 1/100 sec */
 				dasd_set_timer(device, 1);
@@ -1476,6 +1473,7 @@ _dasd_term_running_cqr(struct dasd_devic
 		/* termination successful */
 		cqr->status = DASD_CQR_QUEUED;
 		cqr->startclk = cqr->stopclk = 0;
+		cqr->starttime = 0;
 	}
 	return rc;
 }
@@ -1782,9 +1780,19 @@ dasd_generic_set_online (struct ccw_devi
 	if (IS_ERR(device))
 		return PTR_ERR(device);
 
-	if (device->use_diag_flag)
+	if (device->use_diag_flag) {
+	  	if (!dasd_diag_discipline_pointer) {
+		        printk (KERN_WARNING
+				"dasd_generic couldn't online device %s "
+				"- discipline DIAG not available\n",
+				cdev->dev.bus_id);
+			dasd_delete_device(device);
+			return -ENODEV;
+		}
 		discipline = dasd_diag_discipline_pointer;
+	}
 	device->discipline = discipline;
+
 	rc = discipline->check_device(device);
 	if (rc) {
 		printk (KERN_WARNING
@@ -1980,6 +1988,7 @@ EXPORT_SYMBOL(dasd_term_IO);
 
 EXPORT_SYMBOL_GPL(dasd_generic_probe);
 EXPORT_SYMBOL_GPL(dasd_generic_remove);
+EXPORT_SYMBOL_GPL(dasd_generic_notify);
 EXPORT_SYMBOL_GPL(dasd_generic_set_online);
 EXPORT_SYMBOL_GPL(dasd_generic_set_offline);
 EXPORT_SYMBOL_GPL(dasd_generic_auto_online);
--- diff/drivers/s390/block/dasd_3990_erp.c	2004-02-09 10:36:11.000000000 +0000
+++ source/drivers/s390/block/dasd_3990_erp.c	2004-02-23 13:56:44.000000000 +0000
@@ -5,7 +5,7 @@
  * Bugreports.to..: <Linux390@de.ibm.com>
  * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 2000, 2001
  *
- * $Revision: 1.26 $
+ * $Revision: 1.27 $
  */
 
 #include <linux/timer.h>
@@ -2129,13 +2129,10 @@ dasd_3990_erp_inspect_32(struct dasd_ccw
 		/* single program action codes (byte25 bit 0 == '0') */
 		switch (sense[25]) {
 
-		case 0x00:	/* success */
-			DEV_MESSAGE(KERN_DEBUG, device,
-				    "ERP called for successful request %p"
-				    " - NO ERP necessary", erp);
-
-			erp = dasd_3990_erp_cleanup(erp, DASD_CQR_DONE);
-
+		case 0x00:	/* success - use default ERP for retries */
+		        DEV_MESSAGE(KERN_DEBUG, device, "%s",
+				    "ERP called for successful request"
+				    " - just retry");
 			break;
 
 		case 0x01:	/* fatal error */
--- diff/drivers/s390/block/dasd_eckd.c	2004-02-09 10:36:11.000000000 +0000
+++ source/drivers/s390/block/dasd_eckd.c	2004-02-23 13:56:44.000000000 +0000
@@ -7,7 +7,7 @@
  * Bugreports.to..: <Linux390@de.ibm.com>
  * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999,2000
  *
- * $Revision: 1.49 $
+ * $Revision: 1.50 $
  */
 
 #include <linux/config.h>
@@ -1420,6 +1420,9 @@ dasd_eckd_dump_sense(struct dasd_device 
 				       "Exception class %x\n",
 				       irb->ecw[6] & 0x0f, irb->ecw[22] >> 4);
 		}
+	} else {
+	        len += sprintf(page + len, KERN_ERR PRINTK_HEADER
+			       "SORRY - NO VALID SENSE AVAILABLE\n");
 	}
 
 	MESSAGE(KERN_ERR, "Sense data:\n%s", page);
--- diff/drivers/s390/block/dasd_genhd.c	2004-02-09 10:36:11.000000000 +0000
+++ source/drivers/s390/block/dasd_genhd.c	2004-02-23 13:56:44.000000000 +0000
@@ -9,7 +9,7 @@
  *
  * gendisk related functions for the dasd driver.
  *
- * $Revision: 1.42 $
+ * $Revision: 1.44 $
  */
 
 #include <linux/config.h>
@@ -31,6 +31,7 @@ int
 dasd_gendisk_alloc(struct dasd_device *device)
 {
 	struct gendisk *gdp;
+	int len;
 
 	/* Make sure the minor for this device exists. */
 	if (device->devindex >= DASD_PER_MAJOR)
@@ -46,8 +47,28 @@ dasd_gendisk_alloc(struct dasd_device *d
 	gdp->fops = &dasd_device_operations;
 	gdp->driverfs_dev = &device->cdev->dev;
 
-	/* Set device name */
- 	sprintf(gdp->disk_name, "dasd_%s_", device->cdev->dev.bus_id);
+	/*
+	 * Set device name.
+	 *   dasda - dasdz : 26 devices
+	 *   dasdaa - dasdzz : 676 devices, added up = 702
+	 *   dasdaaa - dasdzzz : 17576 devices, added up = 18278
+	 *   dasdaaaa - dasdzzzz : 456976 devices, added up = 475252
+	 */
+	len = sprintf(gdp->disk_name, "dasd");
+	if (device->devindex > 25) {
+	        if (device->devindex > 701) {
+		        if (device->devindex > 18277)
+			        len += sprintf(gdp->disk_name + len, "%c",
+					       'a'+(((device->devindex-18278)
+						     /17576)%26));
+			len += sprintf(gdp->disk_name + len, "%c",
+				       'a'+(((device->devindex-702)/676)%26));
+		}
+		len += sprintf(gdp->disk_name + len, "%c",
+			       'a'+(((device->devindex-26)/26)%26));
+	}
+	len += sprintf(gdp->disk_name + len, "%c", 'a'+(device->devindex%26));
+
  	sprintf(gdp->devfs_name, "dasd/%s", device->cdev->dev.bus_id);
 
 	if (device->ro_flag)
@@ -85,10 +106,10 @@ dasd_scan_partitions(struct dasd_device 
 	/* See fs/partition/check.c:register_disk,rescan_partitions */
 	bdev = bdget_disk(device->gdp, 0);
 	if (bdev) {
-		if (blkdev_get(bdev, FMODE_READ, 1, BDEV_RAW) >= 0) {
+		if (blkdev_get(bdev, FMODE_READ, 1) >= 0) {
 			/* Can't call rescan_partitions directly. Use ioctl. */
 			ioctl_by_bdev(bdev, BLKRRPART, 0);
-			blkdev_put(bdev, BDEV_RAW);
+			blkdev_put(bdev);
 		}
 	}
 }
--- diff/drivers/s390/block/dasd_int.h	2004-02-09 10:36:11.000000000 +0000
+++ source/drivers/s390/block/dasd_int.h	2004-02-23 13:56:44.000000000 +0000
@@ -6,7 +6,7 @@
  * Bugreports.to..: <Linux390@de.ibm.com>
  * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999,2000
  *
- * $Revision: 1.52 $
+ * $Revision: 1.54 $
  */
 
 #ifndef DASD_INT_H
@@ -14,6 +14,10 @@
 
 #ifdef __KERNEL__
 
+/* erp debugging in dasd.c and dasd_3990_erp.c */
+#define ERP_DEBUG
+
+
 /* we keep old device allocation scheme; IOW, minors are still in 0..255 */
 #define DASD_PER_MAJOR (1U << (MINORBITS - DASD_PARTN_BITS))
 #define DASD_PARTN_MASK ((1 << DASD_PARTN_BITS) - 1)
@@ -157,6 +161,7 @@ struct dasd_ccw_req {
 	short retries;			/* A retry counter */
 
 	/* ... and how */
+	unsigned long starttime;	/* jiffies time of request start */
 	int expires;			/* expiration period in jiffies */
 	char lpm;               	/* logical path mask */
 	void *data;			/* pointer to data area */
@@ -166,6 +171,7 @@ struct dasd_ccw_req {
 	struct dasd_ccw_req *refers;	/* ERP-chain queueing. */
 	void *function; 		/* originating ERP action */
 
+	/* these are for statistics only */
 	unsigned long long buildclk;	/* TOD-clock of request generation */
 	unsigned long long startclk;	/* TOD-clock of request start */
 	unsigned long long stopclk;	/* TOD-clock of request interrupt */
--- diff/drivers/s390/block/dasd_ioctl.c	2003-09-30 15:46:16.000000000 +0100
+++ source/drivers/s390/block/dasd_ioctl.c	2004-02-23 13:56:44.000000000 +0000
@@ -147,6 +147,7 @@ dasd_ioctl_enable(struct block_device *b
 
 /*
  * Disable device.
+ * Used by dasdfmt. Disable I/O operations but allow ioctls.
  */
 static int
 dasd_ioctl_disable(struct block_device *bdev, int no, long args)
@@ -167,6 +168,13 @@ dasd_ioctl_disable(struct block_device *
 	 * device is DASD_STATE_BASIC that allows to do basic i/o.
 	 */
 	dasd_set_target_state(device, DASD_STATE_BASIC);
+	/*
+	 * Set i_size to zero, since read, write, etc. check against this
+	 * value.
+	 */
+	down(&bdev->bd_sem);
+	i_size_write(bdev->bd_inode, 0);
+	up(&bdev->bd_sem);
 	return 0;
 }
 
@@ -237,9 +245,9 @@ dasd_format(struct dasd_device * device,
 	if (device->discipline->format_device == NULL)
 		return -EPERM;
 
-	if (atomic_read(&device->open_count) > 1) {
+	if (device->state != DASD_STATE_BASIC) {
 		DEV_MESSAGE(KERN_WARNING, device, "%s",
-			    "dasd_format: device is open! ");
+			    "dasd_format: device is not disabled! ");
 		return -EBUSY;
 	}
 
@@ -248,6 +256,16 @@ dasd_format(struct dasd_device * device,
 		      fdata->start_unit,
 		      fdata->stop_unit, fdata->blksize, fdata->intensity);
 
+	/* Since dasdfmt keeps the device open after it was disabled,
+	 * there still exists an inode for this device. We must update i_blkbits,
+	 * otherwise we might get errors when enabling the device later.
+	 */
+	if (fdata->start_unit == 0) {
+		struct block_device *bdev = bdget_disk(device->gdp, 0);
+		bdev->bd_inode->i_blkbits = blksize_bits(fdata->blksize);
+		bdput(bdev);
+	}
+
 	while (fdata->start_unit <= fdata->stop_unit) {
 		cqr = device->discipline->format_device(device, fdata);
 		if (IS_ERR(cqr))
--- diff/drivers/s390/block/dasd_proc.c	2004-02-09 10:36:11.000000000 +0000
+++ source/drivers/s390/block/dasd_proc.c	2004-02-23 13:56:44.000000000 +0000
@@ -9,7 +9,7 @@
  *
  * /proc interface for the dasd driver.
  *
- * $Revision: 1.24 $
+ * $Revision: 1.26 $
  */
 
 #include <linux/config.h>
@@ -67,10 +67,15 @@ dasd_devices_show(struct seq_file *m, vo
 		seq_printf(m, "(none)");
 	/* Print kdev. */
 	if (device->gdp)
-		seq_printf(m, " at (%3d:%7d)",
+		seq_printf(m, " at (%3d:%6d)",
 			   device->gdp->major, device->gdp->first_minor);
 	else
-		seq_printf(m, "  at (???:???????)");
+		seq_printf(m, "  at (???:??????)");
+	/* Print device name. */
+	if (device->gdp)
+		seq_printf(m, " is %-8s", device->gdp->disk_name);
+	else
+		seq_printf(m, " is ????????");
 	/* Print devices features. */
 	substr = device->ro_flag ? "(ro)" : " ";
 	seq_printf(m, "%4s: ", substr);
--- diff/drivers/s390/block/xpram.c	2003-09-30 15:46:16.000000000 +0100
+++ source/drivers/s390/block/xpram.c	2004-02-23 13:56:45.000000000 +0000
@@ -492,7 +492,7 @@ static void __exit xpram_exit(void)
 	}
 	unregister_blkdev(XPRAM_MAJOR, XPRAM_NAME);
 	devfs_remove("slram");
-	sys_device_unregister(&xpram_sys_device);
+	sysdev_unregister(&xpram_sys_device);
 	sysdev_class_unregister(&xpram_sysclass);
 }
 
@@ -515,14 +515,14 @@ static int __init xpram_init(void)
 	if (rc)
 		return rc;
 
-	rc = sys_device_register(&xpram_sys_device);
+	rc = sysdev_register(&xpram_sys_device);
 	if (rc) {
 		sysdev_class_unregister(&xpram_sysclass);
 		return rc;
 	}
 	rc = xpram_setup_blkdev();
 	if (rc)
-		sys_device_unregister(&xpram_sys_device);
+		sysdev_unregister(&xpram_sys_device);
 	return rc;
 }
 
--- diff/drivers/s390/char/con3215.c	2004-02-09 10:36:11.000000000 +0000
+++ source/drivers/s390/char/con3215.c	2004-02-23 13:56:45.000000000 +0000
@@ -454,7 +454,7 @@ raw3215_irq(struct ccw_device *cdev, uns
 				memcpy(tty->flip.char_buf_ptr,
 				       raw->inbuf, count);
 				if (count < 2 ||
-				    (strncmp(raw->inbuf+count-2, "^n", 2) ||
+				    (strncmp(raw->inbuf+count-2, "^n", 2) &&
 				    strncmp(raw->inbuf+count-2, "\252n", 2)) ) {
 					/* don't add the auto \n */
 					tty->flip.char_buf_ptr[count] = '\n';
--- diff/drivers/s390/char/sclp_tty.c	2004-02-09 10:36:11.000000000 +0000
+++ source/drivers/s390/char/sclp_tty.c	2004-02-23 13:56:45.000000000 +0000
@@ -529,8 +529,8 @@ sclp_tty_input(unsigned char* buf, unsig
 		/* send (normal) input to line discipline */
 		memcpy(sclp_tty->flip.char_buf_ptr, buf, count);
 		if (count < 2 ||
-		    strncmp ((const char *) buf + count - 2, "^n", 2) ||
-		    strncmp ((const char *) buf + count - 2, "\0252n", 2)) {
+		    (strncmp ((const char *) buf + count - 2, "^n", 2) &&
+		     strncmp ((const char *) buf + count - 2, "\0252n", 2))) {
 			sclp_tty->flip.char_buf_ptr[count] = '\n';
 			count++;
 		} else
@@ -636,7 +636,7 @@ find_gds_vector(struct gds_vector *start
 {
 	struct gds_vector *vec;
 
-	for (vec = start; vec < end; (void *) vec += vec->length)
+	for (vec = start; vec < end; vec = (void *) vec + vec->length)
 		if (vec->gds_id == id)
 			return vec;
 	return NULL;
@@ -648,7 +648,8 @@ find_gds_subvector(struct gds_subvector 
 {
 	struct gds_subvector *subvec;
 
-	for (subvec = start; subvec < end; (void *) subvec += subvec->length)
+	for (subvec = start; subvec < end;
+	     subvec = (void *) subvec + subvec->length)
 		if (subvec->key == key)
 			return subvec;
 	return NULL;
@@ -667,7 +668,7 @@ sclp_eval_selfdeftextmsg(struct gds_subv
 			break;
 		sclp_get_input((unsigned char *)(subvec + 1),
 			       (unsigned char *) subvec + subvec->length);
-		(void *) subvec += subvec->length;
+		subvec = (void *) subvec + subvec->length;
 	}
 }
 
@@ -685,7 +686,7 @@ sclp_eval_textcmd(struct gds_subvector *
 			break;
 		sclp_eval_selfdeftextmsg((struct gds_subvector *)(subvec + 1),
 					 (void *)subvec + subvec->length);
-		(void *) subvec += subvec->length;
+		subvec = (void *) subvec + subvec->length;
 	}
 }
 
@@ -701,7 +702,7 @@ sclp_eval_cpmsu(struct gds_vector *start
 			break;
 		sclp_eval_textcmd((struct gds_subvector *)(vec + 1),
 				  (void *) vec + vec->length);
-		(void *) vec += vec->length;
+		vec = (void *) vec + vec->length;
 	}
 }
 
--- diff/drivers/s390/char/sclp_vt220.c	2003-09-30 15:46:16.000000000 +0100
+++ source/drivers/s390/char/sclp_vt220.c	2004-02-23 13:56:45.000000000 +0000
@@ -32,9 +32,10 @@
 #define SCLP_VT220_MAJOR		TTY_MAJOR
 #define SCLP_VT220_MINOR		65
 #define SCLP_VT220_DRIVER_NAME		"sclp_vt220"
-#define SCLP_VT220_DEVICE_NAME		"sclp_vt"
+#define SCLP_VT220_DEVICE_NAME		"ttysclp"
 #define SCLP_VT220_CONSOLE_NAME		"ttyS"
 #define SCLP_VT220_CONSOLE_INDEX	1	/* console=ttyS1 */
+#define SCLP_VT220_BUF_SIZE		80
 
 /* Representation of a single write request */
 struct sclp_vt220_request {
@@ -336,12 +337,11 @@ sclp_vt220_chars_stored(struct sclp_vt22
 
 /*
  * Add msg to buffer associated with request. Return the number of characters
- * added or -EFAULT on error.
+ * added.
  */
 static int
 sclp_vt220_add_msg(struct sclp_vt220_request *request,
-		   const unsigned char *msg, int count, int from_user,
-		   int convertlf)
+		   const unsigned char *msg, int count, int convertlf)
 {
 	struct sclp_vt220_sccb *sccb;
 	void *buffer;
@@ -363,11 +363,7 @@ sclp_vt220_add_msg(struct sclp_vt220_req
 		     (from < count) && (to < sclp_vt220_space_left(request));
 		     from++) {
 			/* Retrieve character */
-			if (from_user) {
-				if (get_user(c, msg + from) != 0)
-					return -EFAULT;
-			} else
-				c = msg[from];
+			c = msg[from];
 			/* Perform conversion */
 			if (c == 0x0a) {
 				if (to + 1 < sclp_vt220_space_left(request)) {
@@ -383,12 +379,7 @@ sclp_vt220_add_msg(struct sclp_vt220_req
 		sccb->evbuf.length += to;
 		return from;
 	} else {
-		if (from_user) {
-			if (copy_from_user(buffer, (void *) msg, count) != 0)
-				return -EFAULT;
-		}
-		else
-			memcpy(buffer, (const void *) msg, count);
+		memcpy(buffer, (const void *) msg, count);
 		sccb->header.length += count;
 		sccb->evbuf.length += count;
 		return count;
@@ -408,7 +399,7 @@ sclp_vt220_timeout(unsigned long data)
 
 /* 
  * Internal implementation of the write function. Write COUNT bytes of data
- * from memory at BUF which may reside in user space (specified by FROM_USER)
+ * from memory at BUF
  * to the SCLP interface. In case that the data does not fit into the current
  * write buffer, emit the current one and allocate a new one. If there are no
  * more empty buffers available, wait until one gets emptied. If DO_SCHEDULE
@@ -419,8 +410,8 @@ sclp_vt220_timeout(unsigned long data)
  * of bytes written.
  */
 static int
-__sclp_vt220_write(int from_user, const unsigned char *buf, int count,
-		   int do_schedule, int convertlf)
+__sclp_vt220_write(const unsigned char *buf, int count, int do_schedule,
+		   int convertlf)
 {
 	unsigned long flags;
 	void *page;
@@ -451,10 +442,9 @@ __sclp_vt220_write(int from_user, const 
 		}
 		/* Try to write the string to the current request buffer */
 		written = sclp_vt220_add_msg(sclp_vt220_current_request,
-				buf, count, from_user, convertlf);
-		if (written > 0)
-			overall_written += written;
-		if (written == -EFAULT || written == count)
+					     buf, count, convertlf);
+		overall_written += written;
+		if (written == count)
 			break;
 		/*
 		 * Not all characters could be written to the current
@@ -489,7 +479,29 @@ static int
 sclp_vt220_write(struct tty_struct *tty, int from_user,
 		 const unsigned char *buf, int count)
 {
-	return __sclp_vt220_write(from_user, buf, count, 1, 0);
+	int length;
+	int ret;
+
+	if (!from_user)
+		return __sclp_vt220_write(buf, count, 1, 0);
+	/* Use intermediate buffer to prevent calling copy_from_user() while
+	 * holding a lock. */
+	ret = 0;
+	while (count > 0) {
+		length = count < SCLP_VT220_BUF_SIZE ?
+			 count : SCLP_VT220_BUF_SIZE;
+		length -= copy_from_user(tty->driver_data, buf, length);
+		if (length == 0) {
+			if (!ret)
+				return -EFAULT;
+			break;
+		}
+		length = __sclp_vt220_write(tty->driver_data, length, 1, 0);
+		buf += length;
+		count -= length;
+		ret += length;
+	}
+	return ret;
 }
 
 #define SCLP_VT220_SESSION_ENDED	0x01
@@ -541,9 +553,13 @@ sclp_vt220_receiver_fn(struct evbuf_head
 static int
 sclp_vt220_open(struct tty_struct *tty, struct file *filp)
 {
-	sclp_vt220_tty = tty;
-	tty->driver_data = NULL;
-	tty->low_latency = 0;
+	if (tty->count == 1) {
+		sclp_vt220_tty = tty;
+		tty->driver_data = kmalloc(SCLP_VT220_BUF_SIZE, GFP_KERNEL);
+		if (tty->driver_data == NULL)
+			return -ENOMEM;
+		tty->low_latency = 0;
+	}
 	return 0;
 }
 
@@ -553,9 +569,11 @@ sclp_vt220_open(struct tty_struct *tty, 
 static void
 sclp_vt220_close(struct tty_struct *tty, struct file *filp)
 {
-	if (tty->count > 1)
-		return;
-	sclp_vt220_tty = NULL;
+	if (tty->count == 1) {
+		sclp_vt220_tty = NULL;
+		kfree(tty->driver_data);
+		tty->driver_data = NULL;
+	}
 }
 
 /*
@@ -571,7 +589,7 @@ sclp_vt220_close(struct tty_struct *tty,
 static void
 sclp_vt220_put_char(struct tty_struct *tty, unsigned char ch)
 {
-	__sclp_vt220_write(0, &ch, 1, 0, 0);
+	__sclp_vt220_write(&ch, 1, 0, 0);
 }
 
 /*
@@ -765,7 +783,7 @@ module_init(sclp_vt220_tty_init);
 static void
 sclp_vt220_con_write(struct console *con, const char *buf, unsigned int count)
 {
-	__sclp_vt220_write(0, (const unsigned char *) buf, count, 1, 1);
+	__sclp_vt220_write((const unsigned char *) buf, count, 1, 1);
 }
 
 static struct tty_driver *
--- diff/drivers/s390/char/tape_core.c	2004-02-09 10:36:11.000000000 +0000
+++ source/drivers/s390/char/tape_core.c	2004-02-23 13:56:45.000000000 +0000
@@ -81,7 +81,7 @@ tape_medium_state_show(struct device *de
 	struct tape_device *tdev;
 
 	tdev = (struct tape_device *) dev->driver_data;
-	return snprintf(buf, PAGE_SIZE, "%i\n", tdev->medium_state);
+	return scnprintf(buf, PAGE_SIZE, "%i\n", tdev->medium_state);
 }
 
 static
@@ -93,7 +93,7 @@ tape_first_minor_show(struct device *dev
 	struct tape_device *tdev;
 
 	tdev = (struct tape_device *) dev->driver_data;
-	return snprintf(buf, PAGE_SIZE, "%i\n", tdev->first_minor);
+	return scnprintf(buf, PAGE_SIZE, "%i\n", tdev->first_minor);
 }
 
 static
@@ -105,7 +105,7 @@ tape_state_show(struct device *dev, char
 	struct tape_device *tdev;
 
 	tdev = (struct tape_device *) dev->driver_data;
-	return snprintf(buf, PAGE_SIZE, "%s\n", (tdev->first_minor < 0) ?
+	return scnprintf(buf, PAGE_SIZE, "%s\n", (tdev->first_minor < 0) ?
 		"OFFLINE" : tape_state_verbose[tdev->tape_state]);
 }
 
@@ -120,17 +120,17 @@ tape_operation_show(struct device *dev, 
 
 	tdev = (struct tape_device *) dev->driver_data;
 	if (tdev->first_minor < 0)
-		return snprintf(buf, PAGE_SIZE, "N/A\n");
+		return scnprintf(buf, PAGE_SIZE, "N/A\n");
 
 	spin_lock_irq(get_ccwdev_lock(tdev->cdev));
 	if (list_empty(&tdev->req_queue))
-		rc = snprintf(buf, PAGE_SIZE, "---\n");
+		rc = scnprintf(buf, PAGE_SIZE, "---\n");
 	else {
 		struct tape_request *req;
 
 		req = list_entry(tdev->req_queue.next, struct tape_request,
 			list);
-		rc = snprintf(buf, PAGE_SIZE, "%s\n", tape_op_verbose[req->op]);
+		rc = scnprintf(buf,PAGE_SIZE, "%s\n", tape_op_verbose[req->op]);
 	}
 	spin_unlock_irq(get_ccwdev_lock(tdev->cdev));
 	return rc;
@@ -146,7 +146,7 @@ tape_blocksize_show(struct device *dev, 
 
 	tdev = (struct tape_device *) dev->driver_data;
 
-	return snprintf(buf, PAGE_SIZE, "%i\n", tdev->char_data.block_size);
+	return scnprintf(buf, PAGE_SIZE, "%i\n", tdev->char_data.block_size);
 }
 
 static
--- diff/drivers/s390/cio/Makefile	2003-02-13 11:46:53.000000000 +0000
+++ source/drivers/s390/cio/Makefile	2004-02-23 13:56:45.000000000 +0000
@@ -5,6 +5,6 @@
 obj-y += airq.o blacklist.o chsc.o cio.o css.o requestirq.o 
 ccw_device-objs += device.o device_fsm.o device_ops.o
 ccw_device-objs += device_id.o device_pgid.o device_status.o
-obj-y += ccw_device.o
+obj-y += ccw_device.o cmf.o
 obj-$(CONFIG_CCWGROUP) += ccwgroup.o
 obj-$(CONFIG_QDIO) += qdio.o
--- diff/drivers/s390/cio/blacklist.c	2004-02-09 10:36:11.000000000 +0000
+++ source/drivers/s390/cio/blacklist.c	2004-02-23 13:56:45.000000000 +0000
@@ -1,7 +1,7 @@
 /*
  *  drivers/s390/cio/blacklist.c
  *   S/390 common I/O routines -- blacklisting of specific devices
- *   $Revision: 1.27 $
+ *   $Revision: 1.29 $
  *
  *    Copyright (C) 1999-2002 IBM Deutschland Entwicklung GmbH,
  *			      IBM Corporation
@@ -18,9 +18,11 @@
 #include <linux/ctype.h>
 #include <linux/device.h>
 
+#include <asm/cio.h>
 #include <asm/uaccess.h>
 
 #include "blacklist.h"
+#include "cio.h"
 #include "cio_debug.h"
 #include "css.h"
 
@@ -199,8 +201,6 @@ is_blacklisted (int devno)
 }
 
 #ifdef CONFIG_PROC_FS
-
-extern void css_reiterate_subchannels(void);
 /*
  * Function: s390_redo_validation
  * Look for no longer blacklisted devices
@@ -208,9 +208,29 @@ extern void css_reiterate_subchannels(vo
 static inline void
 s390_redo_validation (void)
 {
-	CIO_TRACE_EVENT (0, "redoval");
+	unsigned int irq;
 
-	css_reiterate_subchannels();
+	CIO_TRACE_EVENT (0, "redoval");
+	for (irq = 0; irq <= __MAX_SUBCHANNELS; irq++) {
+		int ret;
+		struct subchannel *sch;
+
+		sch = get_subchannel_by_schid(irq);
+		if (sch) {
+			/* Already known. */
+			put_device(&sch->dev);
+			continue;
+		}
+		ret = css_probe_device(irq);
+		if (ret == -ENXIO)
+			break; /* We're through. */
+		if (ret == -ENOMEM)
+			/*
+			 * Stop validation for now. Bad, but no need for a
+			 * panic.
+			 */
+			break;
+	}
 }
 
 /*
--- diff/drivers/s390/cio/ccwgroup.c	2004-02-09 10:36:11.000000000 +0000
+++ source/drivers/s390/cio/ccwgroup.c	2004-02-23 13:56:45.000000000 +0000
@@ -1,7 +1,7 @@
 /*
  *  drivers/s390/cio/ccwgroup.c
  *  bus driver for ccwgroup
- *   $Revision: 1.19 $
+ *   $Revision: 1.23 $
  *
  *    Copyright (C) 2002 IBM Deutschland Entwicklung GmbH,
  *                       IBM Corporation
@@ -164,6 +164,7 @@ ccwgroup_create(struct device *root,
 		return -ENOMEM;
 
 	memset(gdev, 0, sizeof(*gdev) + argc*sizeof(gdev->cdev[0]));
+	atomic_set(&gdev->onoff, 0);
 
 	for (i = 0; i < argc; i++) {
 		gdev->cdev[i] = get_ccwdev_by_busid(cdrv, argv[i]);
@@ -242,18 +243,24 @@ ccwgroup_set_online(struct ccwgroup_devi
 	struct ccwgroup_driver *gdrv;
 	int ret;
 
-	if (gdev->state == CCWGROUP_ONLINE)
-		return 0;
-
-	if (!gdev->dev.driver)
-		return -EINVAL;
-
+	if (atomic_compare_and_swap(0, 1, &gdev->onoff))
+		return -EAGAIN;
+	if (gdev->state == CCWGROUP_ONLINE) {
+		ret = 0;
+		goto out;
+	}
+	if (!gdev->dev.driver) {
+		ret = -EINVAL;
+		goto out;
+	}
 	gdrv = to_ccwgroupdrv (gdev->dev.driver);
 	if ((ret = gdrv->set_online(gdev)))
-		return ret;
+		goto out;
 
 	gdev->state = CCWGROUP_ONLINE;
-	return 0;
+ out:
+	atomic_set(&gdev->onoff, 0);
+	return ret;
 }
 
 static int
@@ -262,18 +269,24 @@ ccwgroup_set_offline(struct ccwgroup_dev
 	struct ccwgroup_driver *gdrv;
 	int ret;
 
-	if (gdev->state == CCWGROUP_OFFLINE)
-		return 0;
-
-	if (!gdev->dev.driver)
-		return -EINVAL;
-
+	if (atomic_compare_and_swap(0, 1, &gdev->onoff))
+		return -EAGAIN;
+	if (gdev->state == CCWGROUP_OFFLINE) {
+		ret = 0;
+		goto out;
+	}
+	if (!gdev->dev.driver) {
+		ret = -EINVAL;
+		goto out;
+	}
 	gdrv = to_ccwgroupdrv (gdev->dev.driver);
 	if ((ret = gdrv->set_offline(gdev)))
-		return ret;
+		goto out;
 
 	gdev->state = CCWGROUP_OFFLINE;
-	return 0;
+ out:
+	atomic_set(&gdev->onoff, 0);
+	return ret;
 }
 
 static ssize_t
@@ -324,7 +337,7 @@ ccwgroup_probe (struct device *dev)
 	if ((ret = device_create_file(dev, &dev_attr_online)))
 		return ret;
 
-	pr_debug("%s: device %s\n", __func__, gdev->dev.name);
+	pr_debug("%s: device %s\n", __func__, gdev->dev.bus_id);
 	ret = gdrv->probe ? gdrv->probe(gdev) : -ENODEV;
 	if (ret)
 		device_remove_file(dev, &dev_attr_online);
@@ -341,7 +354,7 @@ ccwgroup_remove (struct device *dev)
 	gdev = to_ccwgroupdev(dev);
 	gdrv = to_ccwgroupdrv(dev->driver);
 
-	pr_debug("%s: device %s\n", __func__, gdev->dev.name);
+	pr_debug("%s: device %s\n", __func__, gdev->dev.bus_id);
 
 	device_remove_file(dev, &dev_attr_online);
 
--- diff/drivers/s390/cio/chsc.c	2004-02-09 10:36:11.000000000 +0000
+++ source/drivers/s390/cio/chsc.c	2004-02-23 13:56:45.000000000 +0000
@@ -1,7 +1,7 @@
 /*
  *  drivers/s390/cio/chsc.c
  *   S/390 common I/O routines -- channel subsystem call
- *   $Revision: 1.92 $
+ *   $Revision: 1.105 $
  *
  *    Copyright (C) 1999-2002 IBM Deutschland Entwicklung GmbH,
  *			      IBM Corporation
@@ -27,30 +27,20 @@
 #define CHPID_LONGS (256 / (8 * sizeof(long))) /* 256 chpids */
 static struct channel_path *chps[NR_CHPIDS];
 
-static int new_channel_path(int chpid, int status);
+static void *sei_page;
 
-static inline void
-set_chp_online(int chp, int onoff)
-{
-	chps[chp]->state.online = onoff;
-}
+static int new_channel_path(int chpid);
 
 static inline void
 set_chp_logically_online(int chp, int onoff)
 {
-	chps[chp]->state.logically_online = onoff;
+	chps[chp]->state = onoff;
 }
 
 static int
 get_chp_status(int chp)
 {
-	int ret;
-
-	if (!chps[chp])
-		return 0;
-	ret = chps[chp]->state.online ? CHP_ONLINE : CHP_STANDBY;
-	return (chps[chp]->state.logically_online ?
-		ret : ret | CHP_LOGICALLY_OFFLINE);
+	return (chps[chp] ? chps[chp]->state : -ENODEV);
 }
 
 void
@@ -60,13 +50,25 @@ chsc_validate_chpids(struct subchannel *
 
 	for (chp = 0; chp <= 7; chp++) {
 		mask = 0x80 >> chp;
-		if (get_chp_status(sch->schib.pmcw.chpid[chp])
-		    &  CHP_LOGICALLY_OFFLINE)
+		if (!get_chp_status(sch->schib.pmcw.chpid[chp]))
 			/* disable using this path */
 			sch->opm &= ~mask;
 	}
 }
 
+void
+chpid_is_actually_online(int chp)
+{
+	int state;
+
+	state = get_chp_status(chp);
+	if (state < 0)
+		new_channel_path(chp);
+	else
+		WARN_ON(!state);
+	/* FIXME: should notify other subchannels here */
+}
+
 /* FIXME: this is _always_ called for every subchannel. shouldn't we
  *	  process more than one at a time? */
 static int
@@ -204,8 +206,8 @@ css_get_ssd_info(struct subchannel *sch)
 		/* Allocate channel path structures, if needed. */
 		for (j = 0; j < 8; j++) {
 			chpid = sch->ssd_info.chpid[j];
-			if (chpid && !get_chp_status(chpid))
-			    new_channel_path(chpid, CHP_ONLINE);
+			if (chpid && (get_chp_status(chpid) < 0))
+			    new_channel_path(chpid);
 		}
 	}
 	return ret;
@@ -218,6 +220,7 @@ s390_subchannel_remove_chpid(struct devi
 	int mask;
 	struct subchannel *sch;
 	__u8 *chpid;
+	struct schib schib;
 
 	sch = to_subchannel(dev);
 	chpid = data;
@@ -230,7 +233,13 @@ s390_subchannel_remove_chpid(struct devi
 	mask = 0x80 >> j;
 	spin_lock(&sch->lock);
 
-	stsch(sch->irq, &sch->schib);
+	stsch(sch->irq, &schib);
+	if (!schib.pmcw.dnv)
+		goto out_unreg;
+	memcpy(&sch->schib, &schib, sizeof(struct schib));
+	/* Check for single path devices. */
+	if (sch->schib.pmcw.pim == 0x80)
+		goto out_unreg;
 	if (sch->vpm == mask)
 		goto out_unreg;
 
@@ -275,12 +284,9 @@ out_unlock:
 	return 0;
 out_unreg:
 	spin_unlock(&sch->lock);
-	if (sch->driver && sch->driver->notify &&
-	    sch->driver->notify(&sch->dev, CIO_NO_PATH))
-		return 0;
-	device_unregister(&sch->dev);
-	sch->schib.pmcw.intparm = 0;
-	cio_modify(sch);
+	sch->lpm = 0;
+	/* We can't block here. */
+	device_call_nopath_notify(sch);
 	return 0;
 }
 
@@ -292,10 +298,8 @@ s390_set_chpid_offline( __u8 chpid)
 	sprintf(dbf_txt, "chpr%x", chpid);
 	CIO_TRACE_EVENT(2, dbf_txt);
 
-	if (!get_chp_status(chpid))
-		return;	 /* we didn't know the chpid anyway */
-
-	set_chp_online(chpid, 0);
+	if (get_chp_status(chpid) <= 0)
+		return;
 
 	bus_for_each_dev(&css_bus_type, NULL, &chpid,
 			 s390_subchannel_remove_chpid);
@@ -303,16 +307,12 @@ s390_set_chpid_offline( __u8 chpid)
 
 static int
 s390_process_res_acc_sch(u8 chpid, __u16 fla, u32 fla_mask,
-			 struct subchannel *sch, void *page)
+			 struct subchannel *sch)
 {
 	int found;
 	int chp;
 	int ccode;
 	
-	/* Update our ssd_info */
-	if (chsc_get_sch_desc_irq(sch, page))
-		return 0;
-	
 	found = 0;
 	for (chp = 0; chp <= 7; chp++)
 		/*
@@ -340,14 +340,12 @@ s390_process_res_acc_sch(u8 chpid, __u16
 	return 0x80 >> chp;
 }
 
-static void
+static int
 s390_process_res_acc (u8 chpid, __u16 fla, u32 fla_mask)
 {
 	struct subchannel *sch;
-	int irq;
-	int ret;
+	int irq, rc;
 	char dbf_txt[15];
-	void *page;
 
 	sprintf(dbf_txt, "accpr%x", chpid);
 	CIO_TRACE_EVENT( 2, dbf_txt);
@@ -364,18 +362,17 @@ s390_process_res_acc (u8 chpid, __u16 fl
 	 * will we have to do.
 	 */
 
-	if (get_chp_status(chpid) & CHP_LOGICALLY_OFFLINE)
-		return; /* no need to do the rest */
-
-	page = (void *)get_zeroed_page(GFP_KERNEL | GFP_DMA);
-	if (!page)
-		return;
+	if (!get_chp_status(chpid))
+		return 0; /* no need to do the rest */
 
+	rc = 0;
 	for (irq = 0; irq < __MAX_SUBCHANNELS; irq++) {
-		int chp_mask;
+		int chp_mask, old_lpm;
 
 		sch = get_subchannel_by_schid(irq);
 		if (!sch) {
+			struct schib schib;
+			int ret;
 			/*
 			 * We don't know the device yet, but since a path
 			 * may be available now to the device we'll have
@@ -384,18 +381,29 @@ s390_process_res_acc (u8 chpid, __u16 fl
 			 * that beast may be on we'll have to do a stsch
 			 * on all devices, grr...
 			 */
-			ret = css_probe_device(irq);
-			if (ret == -ENXIO)
+			if (stsch(irq, &schib)) {
 				/* We're through */
+				if (need_rescan)
+					rc = -EAGAIN;
 				break;
+			}
+			if (need_rescan) {
+				rc = -EAGAIN;
+				continue;
+			}
+			/* Put it on the slow path. */
+			ret = css_enqueue_subchannel_slow(irq);
+			if (ret) {
+				css_clear_subchannel_slow_list();
+				need_rescan = 1;
+			}
+			rc = -EAGAIN;
 			continue;
 		}
 	
 		spin_lock_irq(&sch->lock);
 
-		chp_mask = s390_process_res_acc_sch(chpid, fla, fla_mask,
-						    sch, page);
-		clear_page(page);
+		chp_mask = s390_process_res_acc_sch(chpid, fla, fla_mask, sch);
 
 		if (chp_mask == 0) {
 
@@ -406,21 +414,22 @@ s390_process_res_acc (u8 chpid, __u16 fl
 			else
 				continue;
 		}
-
+		old_lpm = sch->lpm;
 		sch->lpm = ((sch->schib.pmcw.pim &
 			     sch->schib.pmcw.pam &
 			     sch->schib.pmcw.pom)
 			    | chp_mask) & sch->opm;
-
-		if (sch->driver && sch->driver->verify)
+		spin_unlock_irq(&sch->lock);
+		if (!old_lpm && sch->lpm)
+			device_trigger_reprobe(sch);
+		else if (sch->driver && sch->driver->verify)
 			sch->driver->verify(&sch->dev);
 
-		spin_unlock_irq(&sch->lock);
 		put_device(&sch->dev);
 		if (fla_mask != 0)
 			break;
 	}
-	free_page((unsigned long)page);
+	return rc;
 }
 
 static int
@@ -453,10 +462,10 @@ __get_chpid_from_lir(void *data)
 	return (u16) (lir->indesc[0]&0x000000ff);
 }
 
-void
+int
 chsc_process_crw(void)
 {
-	int chpid;
+	int chpid, ret;
 	struct {
 		struct chsc_header request;
 		u32 reserved1;
@@ -476,21 +485,20 @@ chsc_process_crw(void)
 		/* ccdf has to be big enough for a link-incident record */
 	} *sei_area;
 
+	if (!sei_page)
+		return 0;
 	/*
 	 * build the chsc request block for store event information
 	 * and do the call
+	 * This function is only called by the machine check handler thread,
+	 * so we don't need locking for the sei_page.
 	 */
-	sei_area = (void *)get_zeroed_page(GFP_KERNEL | GFP_DMA);
-
-	if (!sei_area) {
-		CIO_CRW_EVENT(0, "No memory for sei area!\n");
-		return;
-	}
+	sei_area = sei_page;
 
 	CIO_TRACE_EVENT( 2, "prcss");
-
+	ret = 0;
 	do {
-		int ccode;
+		int ccode, status;
 		memset(sei_area, 0, sizeof(*sei_area));
 
 		sei_area->request = (struct chsc_header) {
@@ -500,7 +508,7 @@ chsc_process_crw(void)
 
 		ccode = chsc(sei_area);
 		if (ccode > 0)
-			goto out;
+			return 0;
 
 		switch (sei_area->response.code) {
 			/* for debug purposes, check for problems */
@@ -511,19 +519,19 @@ chsc_process_crw(void)
 		case 0x0002:
 			CIO_CRW_EVENT(2,
 				      "chsc_process_crw: invalid command!\n");
-			goto out;
+			return 0;
 		case 0x0003:
 			CIO_CRW_EVENT(2, "chsc_process_crw: error in chsc "
 				      "request block!\n");
-			goto out;
+			return 0;
 		case 0x0005:
 			CIO_CRW_EVENT(2, "chsc_process_crw: no event "
 				      "information stored\n");
-			goto out;
+			return 0;
 		default:
 			CIO_CRW_EVENT(2, "chsc_process_crw: chsc response %d\n",
 				      sei_area->response.code);
-			goto out;
+			return 0;
 		}
 
 		/* Check if we might have lost some information. */
@@ -561,24 +569,27 @@ chsc_process_crw(void)
 			pr_debug("Validity flags: %x\n", sei_area->vf);
 			
 			/* allocate a new channel path structure, if needed */
-			if (chps[sei_area->rsid] == NULL)
-				new_channel_path(sei_area->rsid, CHP_ONLINE);
-			else
-				set_chp_online(sei_area->rsid, 1);
-			
+			status = get_chp_status(sei_area->rsid);
+			if (status < 0)
+				new_channel_path(sei_area->rsid);
+			else if (!status)
+				return 0;
 			if ((sei_area->vf & 0x80) == 0) {
 				pr_debug("chpid: %x\n", sei_area->rsid);
-				s390_process_res_acc(sei_area->rsid, 0, 0);
+				ret = s390_process_res_acc(sei_area->rsid,
+							   0, 0);
 			} else if ((sei_area->vf & 0xc0) == 0x80) {
 				pr_debug("chpid: %x link addr: %x\n",
 					 sei_area->rsid, sei_area->fla);
-				s390_process_res_acc(sei_area->rsid,
-						     sei_area->fla, 0xff00);
+				ret = s390_process_res_acc(sei_area->rsid,
+							   sei_area->fla,
+							   0xff00);
 			} else if ((sei_area->vf & 0xc0) == 0xc0) {
 				pr_debug("chpid: %x full link addr: %x\n",
 					 sei_area->rsid, sei_area->fla);
-				s390_process_res_acc(sei_area->rsid,
-						     sei_area->fla, 0xffff);
+				ret = s390_process_res_acc(sei_area->rsid,
+							   sei_area->fla,
+							   0xffff);
 			}
 			pr_debug("\n");
 			
@@ -590,33 +601,47 @@ chsc_process_crw(void)
 			break;
 		}
 	} while (sei_area->flags & 0x80);
-
-out:
-	free_page((unsigned long)sei_area);
+	return ret;
 }
 
-static void
+static int
 chp_add(int chpid)
 {
 	struct subchannel *sch;
-	int irq, ret;
+	int irq, ret, rc;
 	char dbf_txt[15];
 
-	if (get_chp_status(chpid) & CHP_LOGICALLY_OFFLINE)
-		return; /* no need to do the rest */
+	if (!get_chp_status(chpid))
+		return 0; /* no need to do the rest */
 	
 	sprintf(dbf_txt, "cadd%x", chpid);
 	CIO_TRACE_EVENT(2, dbf_txt);
 
+	rc = 0;
 	for (irq = 0; irq < __MAX_SUBCHANNELS; irq++) {
 		int i;
 
 		sch = get_subchannel_by_schid(irq);
 		if (!sch) {
-			ret = css_probe_device(irq);
-			if (ret == -ENXIO)
+			struct schib schib;
+
+			if (stsch(irq, &schib)) {
 				/* We're through */
-				return;
+				if (need_rescan)
+					rc = -EAGAIN;
+				break;
+			}
+			if (need_rescan) {
+				rc = -EAGAIN;
+				continue;
+			}
+			/* Put it on the slow path. */
+			ret = css_enqueue_subchannel_slow(irq);
+			if (ret) {
+				css_clear_subchannel_slow_list();
+				need_rescan = 1;
+			}
+			rc = -EAGAIN;
 			continue;
 		}
 	
@@ -626,13 +651,13 @@ chp_add(int chpid)
 				if (stsch(sch->irq, &sch->schib) != 0) {
 					/* Endgame. */
 					spin_unlock(&sch->lock);
-					return;
+					return rc;
 				}
 				break;
 			}
 		if (i==8) {
 			spin_unlock(&sch->lock);
-			return;
+			return rc;
 		}
 		sch->lpm = ((sch->schib.pmcw.pim &
 			     sch->schib.pmcw.pam &
@@ -645,70 +670,80 @@ chp_add(int chpid)
 		spin_unlock(&sch->lock);
 		put_device(&sch->dev);
 	}
+	return rc;
 }
 
 /* 
  * Handling of crw machine checks with channel path source.
  */
-void
+int
 chp_process_crw(int chpid, int on)
 {
 	if (on == 0) {
 		/* Path has gone. We use the link incident routine.*/
 		s390_set_chpid_offline(chpid);
-	} else {
-		/* 
-		 * Path has come. Allocate a new channel path structure,
-		 * if needed. 
-		 */
-		if (chps[chpid] == NULL)
-			new_channel_path(chpid, CHP_ONLINE);
-		else
-			set_chp_online(chpid, 1);
-		/* Avoid the extra overhead in process_rec_acc. */
-		chp_add(chpid);
+		return 0; /* De-register is async anyway. */
 	}
+	/*
+	 * Path has come. Allocate a new channel path structure,
+	 * if needed.
+	 */
+	if (get_chp_status(chpid) < 0)
+		new_channel_path(chpid);
+	/* Avoid the extra overhead in process_rec_acc. */
+	return chp_add(chpid);
 }
 
-static inline void
+static inline int
 __check_for_io_and_kill(struct subchannel *sch, int index)
 {
 	int cc;
 
 	cc = stsch(sch->irq, &sch->schib);
 	if (cc)
-		return;
-	if (sch->schib.scsw.actl && sch->schib.pmcw.lpum == (0x80 >> index))
+		return 0;
+	if (sch->schib.scsw.actl && sch->schib.pmcw.lpum == (0x80 >> index)) {
 		device_set_waiting(sch);
+		return 1;
+	}
+	return 0;
 }
 
 static inline void
 __s390_subchannel_vary_chpid(struct subchannel *sch, __u8 chpid, int on)
 {
-	int chp;
+	int chp, old_lpm;
 
 	if (!sch->ssd_info.valid)
 		return;
 	
+	old_lpm = sch->lpm;
 	for (chp = 0; chp < 8; chp++) {
-		if (sch->ssd_info.chpid[chp] == chpid) {
-			if (on) {
-				sch->opm |= (0x80 >> chp);
-				sch->lpm |= (0x80 >> chp);
-			} else {
-				sch->opm &= ~(0x80 >> chp);
-				sch->lpm &= ~(0x80 >> chp);
-				/*
-				 * Give running I/O a grace period in which it
-				 * can successfully terminate, even using the
-				 * just varied off path. Then kill it.
-				 */
-				__check_for_io_and_kill(sch, chp);
-			}
-			if (sch->driver && sch->driver->verify)
+		if (sch->ssd_info.chpid[chp] != chpid)
+			continue;
+
+		if (on) {
+			sch->opm |= (0x80 >> chp);
+			sch->lpm |= (0x80 >> chp);
+			if (!old_lpm)
+				device_trigger_reprobe(sch);
+			else if (sch->driver && sch->driver->verify)
+				sch->driver->verify(&sch->dev);
+		} else {
+			sch->opm &= ~(0x80 >> chp);
+			sch->lpm &= ~(0x80 >> chp);
+			/*
+			 * Give running I/O a grace period in which it
+			 * can successfully terminate, even using the
+			 * just varied off path. Then kill it.
+			 */
+			if (!__check_for_io_and_kill(sch, chp) && !sch->lpm)
+				/* Get over with it now. */
+				device_call_nopath_notify(sch);
+			else if (sch->driver && sch->driver->verify)
 				sch->driver->verify(&sch->dev);
-			break;
 		}
+		break;
 	}
 }
 
@@ -738,6 +773,11 @@ s390_subchannel_vary_chpid_on(struct dev
 	return 0;
 }
 
+extern void css_trigger_slow_path(void);
+typedef void (*workfunc)(void *);
+static DECLARE_WORK(varyonoff_work, (workfunc)css_trigger_slow_path,
+		    NULL);
+
 /*
  * Function: s390_vary_chpid
  * Varies the specified chpid online or offline
@@ -746,21 +786,20 @@ static int
 s390_vary_chpid( __u8 chpid, int on)
 {
 	char dbf_text[15];
-	int status;
+	int status, irq, ret;
+	struct subchannel *sch;
 
 	sprintf(dbf_text, on?"varyon%x":"varyoff%x", chpid);
 	CIO_TRACE_EVENT( 2, dbf_text);
 
 	status = get_chp_status(chpid);
-	if (!status) {
+	if (status < 0) {
 		printk(KERN_ERR "Can't vary unknown chpid %02X\n", chpid);
 		return -EINVAL;
 	}
 
-	if ((on && !(status & CHP_LOGICALLY_OFFLINE)) ||
-	    (!on && (status & CHP_LOGICALLY_OFFLINE))) {
-		printk(KERN_ERR "chpid %x is "
-		       "already %sline\n", chpid, on ? "on" : "off");
+	if (!on && !status) {
+		printk(KERN_ERR "chpid %x is already offline\n", chpid);
 		return -EINVAL;
 	}
 
@@ -773,6 +812,30 @@ s390_vary_chpid( __u8 chpid, int on)
 	bus_for_each_dev(&css_bus_type, NULL, &chpid, on ?
 			 s390_subchannel_vary_chpid_on :
 			 s390_subchannel_vary_chpid_off);
+	if (!on)
+		return 0;
+	/* Scan for new devices on varied on path. */
+	for (irq = 0; irq < __MAX_SUBCHANNELS; irq++) {
+		struct schib schib;
+
+		sch = get_subchannel_by_schid(irq);
+		if (sch)
+			continue;
+		if (stsch(irq, &schib))
+			/* We're through */
+			break;
+		if (need_rescan)
+			continue;
+		/* Put it on the slow path. */
+		ret = css_enqueue_subchannel_slow(irq);
+		if (ret) {
+			css_clear_subchannel_slow_list();
+			need_rescan = 1;
+		}
+		continue;
+	}
+	if (need_rescan || css_slow_subchannels_exist())
+		schedule_work(&varyonoff_work);
 	return 0;
 }
 
@@ -783,16 +846,11 @@ static ssize_t
 chp_status_show(struct device *dev, char *buf)
 {
 	struct channel_path *chp = container_of(dev, struct channel_path, dev);
-	int state;
 
 	if (!chp)
 		return 0;
-	state = get_chp_status(chp->id);
-	if (state & CHP_STANDBY)
-		return sprintf(buf, "n/a\n");
-	return (state & CHP_LOGICALLY_OFFLINE) ?
-		sprintf(buf, "logically offline\n") :
-		sprintf(buf, "online\n");
+	return (get_chp_status(chp->id) ? sprintf(buf, "online\n") :
+		sprintf(buf, "offline\n"));
 }
 
 static ssize_t
@@ -835,7 +893,7 @@ chp_release(struct device *dev)
  * This replaces /proc/chpids.
  */
 static int
-new_channel_path(int chpid, int status)
+new_channel_path(int chpid)
 {
 	struct channel_path *chp;
 	int ret;
@@ -849,19 +907,7 @@ new_channel_path(int chpid, int status)
 
 	/* fill in status, etc. */
 	chp->id = chpid;
-	switch (status) {
-	case CHP_STANDBY:
-		chp->state.online = 0;
-		chp->state.logically_online = 1;
-		break;
-	case CHP_LOGICALLY_OFFLINE:
-		chp->state.logically_online = 0;
-		chp->state.online = 1;
-		break;
-	case CHP_ONLINE:
-		chp->state.online = 1;
-		chp->state.logically_online = 1;
-	}
+	chp->state = 1;
 	chp->dev = (struct device) {
 		.parent  = &css_bus_device,
 		.release = chp_release,
@@ -882,3 +928,14 @@ new_channel_path(int chpid, int status)
 	return ret;
 }
 
+static int __init
+chsc_alloc_sei_area(void)
+{
+	sei_page = (void *)get_zeroed_page(GFP_KERNEL | GFP_DMA);
+	if (!sei_page)
+		printk(KERN_WARNING"Can't allocate page for processing of " \
+		       "chsc machine checks!\n");
+	return (sei_page ? 0 : -ENOMEM);
+}
+
+subsys_initcall(chsc_alloc_sei_area);
--- diff/drivers/s390/cio/chsc.h	2004-02-09 10:36:11.000000000 +0000
+++ source/drivers/s390/cio/chsc.h	2004-02-23 13:56:45.000000000 +0000
@@ -3,10 +3,6 @@
 
 #define NR_CHPIDS 256
 
-#define CHP_STANDBY 1
-#define CHP_LOGICALLY_OFFLINE 2
-#define CHP_ONLINE 4
-
 #define CHSC_SEI_ACC_CHPID        1
 #define CHSC_SEI_ACC_LINKADDR     2
 #define CHSC_SEI_ACC_FULLLINKADDR 3
@@ -18,10 +14,7 @@ struct chsc_header {
 
 struct channel_path {
 	int id;
-	struct {
-		unsigned int online:1;
-		unsigned int logically_online:1;
-	}__attribute__((packed)) state;
+	int state;
 	struct device dev;
 };
 
@@ -29,4 +22,6 @@ extern struct channel_path *chps[];
 
 extern void s390_process_css( void );
 extern void chsc_validate_chpids(struct subchannel *);
+extern void chpid_is_actually_online(int);
+extern int is_chpid_online(int);
 #endif
--- diff/drivers/s390/cio/cio.c	2004-02-09 10:36:11.000000000 +0000
+++ source/drivers/s390/cio/cio.c	2004-02-23 13:56:45.000000000 +0000
@@ -1,7 +1,7 @@
 /*
  *  drivers/s390/cio/cio.c
  *   S/390 common I/O routines -- low level i/o calls
- *   $Revision: 1.114 $
+ *   $Revision: 1.117 $
  *
  *    Copyright (C) 1999-2002 IBM Deutschland Entwicklung GmbH,
  *			      IBM Corporation
@@ -173,7 +173,7 @@ cio_start_handle_notoper(struct subchann
 	stsch (sch->irq, &sch->schib);
 
 	CIO_MSG_EVENT(0, "cio_start: 'not oper' status for "
-		      "subchannel %s!\n", sch->dev.bus_id);
+		      "subchannel %04x!\n", sch->irq);
 	sprintf(dbf_text, "no%s", sch->dev.bus_id);
 	CIO_TRACE_EVENT(0, dbf_text);
 	CIO_HEX_EVENT(0, &sch->schib, sizeof (struct schib));
@@ -572,9 +572,9 @@ cio_validate_subchannel (struct subchann
 		sch->opm;
 
 	CIO_DEBUG(KERN_INFO, 0,
-		  "Detected device %04X on subchannel %s"
+		  "Detected device %04X on subchannel %04X"
 		  " - PIM = %02X, PAM = %02X, POM = %02X\n",
-		  sch->schib.pmcw.dev, sch->dev.bus_id, sch->schib.pmcw.pim,
+		  sch->schib.pmcw.dev, sch->irq, sch->schib.pmcw.pim,
 		  sch->schib.pmcw.pam, sch->schib.pmcw.pom);
 
 	/*
@@ -607,6 +607,7 @@ do_IRQ (struct pt_regs *regs)
 	struct irb *irb;
 
 	irq_enter ();
+	asm volatile ("mc 0,0");
 	if (S390_lowcore.int_clock >= S390_lowcore.jiffy_timer)
 		account_ticks(regs);
 	/*
--- diff/drivers/s390/cio/cio.h	2004-02-09 10:36:11.000000000 +0000
+++ source/drivers/s390/cio/cio.h	2004-02-23 13:56:45.000000000 +0000
@@ -37,7 +37,9 @@ struct pmcw {
 	__u8  chpid[8];		/* CHPID 0-7 (if available) */
 	__u32 unused1 : 8;	/* reserved zeros */
 	__u32 st      : 3;	/* subchannel type */
-	__u32 unused2 : 20;	/* reserved zeros */
+	__u32 unused2 : 18;	/* reserved zeros */
+	__u32 mbfc    : 1;      /* measurement block format control */
+	__u32 xmwme   : 1;      /* extended measurement word mode enable */
 	__u32 csense  : 1;	/* concurrent sense; can be enabled ...*/
 				/*  ... per MSCH, however, if facility */
 				/*  ... is not installed, this results */
@@ -50,7 +52,8 @@ struct pmcw {
 struct schib {
 	struct pmcw pmcw;	 /* path management control word */
 	struct scsw scsw;	 /* subchannel status word */
-	__u8 mda[12];		 /* model dependent area */
+	__u64 mba;               /* measurement block address */
+	__u8 mda[4];		 /* model dependent area */
 } __attribute__ ((packed,aligned(4)));
 
 /*
--- diff/drivers/s390/cio/css.c	2004-02-09 10:36:11.000000000 +0000
+++ source/drivers/s390/cio/css.c	2004-02-23 13:56:45.000000000 +0000
@@ -1,7 +1,7 @@
 /*
  *  drivers/s390/cio/css.c
  *  driver for channel subsystem
- *   $Revision: 1.65 $
+ *   $Revision: 1.69 $
  *
  *    Copyright (C) 2002 IBM Deutschland Entwicklung GmbH,
  *			 IBM Corporation
@@ -13,6 +13,7 @@
 #include <linux/device.h>
 #include <linux/slab.h>
 #include <linux/errno.h>
+#include <linux/list.h>
 
 #include "css.h"
 #include "cio.h"
@@ -20,6 +21,7 @@
 #include "ioasm.h"
 
 unsigned int highest_subchannel;
+int need_rescan = 0;
 int css_init_done = 0;
 
 struct device css_bus_device = {
@@ -130,7 +132,7 @@ __get_subchannel_by_stsch(int irq)
 	struct schib schib;
 
 	cc = stsch(irq, &schib);
-	if (cc)
+	if (cc || !schib.pmcw.dnv)
 		return NULL;
 	sch = (struct subchannel *)(unsigned long)schib.pmcw.intparm;
 	if (!sch)
@@ -154,15 +156,18 @@ get_subchannel_by_schid(int irq)
 	sch = __get_subchannel_by_stsch(irq);
 	if (sch)
 		goto out;
-	if (!get_driver(&io_subchannel_driver.drv))
-		goto out;
 	down_read(&css_bus_type.subsys.rwsem);
 
-	list_for_each(entry, &io_subchannel_driver.drv.devices) {
+	list_for_each(entry, &css_bus_type.devices.list) {
 		dev = get_device(container_of(entry,
-					      struct device, driver_list));
+					      struct device, bus_list));
 		if (!dev)
 			continue;
+		/* Skip channel paths. */
+		if (dev->release != &css_subchannel_release) {
+			put_device(dev);
+			continue;
+		}
 		sch = to_subchannel(dev);
 		if (sch->irq == irq)
 			break;
@@ -170,7 +175,6 @@ get_subchannel_by_schid(int irq)
 		sch = NULL;
 	}
 	up_read(&css_bus_type.subsys.rwsem);
-	put_driver(&io_subchannel_driver.drv);
 out:
 	put_bus(&css_bus_type);
 
@@ -188,19 +192,24 @@ css_get_subchannel_status(struct subchan
 		return CIO_GONE;
 	if (!schib.pmcw.dnv)
 		return CIO_GONE;
-	if (sch && (schib.pmcw.dev != sch->schib.pmcw.dev))
+	if (sch && sch->schib.pmcw.dnv &&
+	    (schib.pmcw.dev != sch->schib.pmcw.dev))
 		return CIO_REVALIDATE;
 	return CIO_OPER;
 }
 	
 static inline int
-css_evaluate_subchannel(int irq)
+css_evaluate_subchannel(int irq, int slow)
 {
 	int event, ret, disc;
 	struct subchannel *sch;
 
 	sch = get_subchannel_by_schid(irq);
 	disc = sch ? device_is_disconnected(sch) : 0;
+	if (disc && slow)
+		return 0; /* Already processed. */
+	if (!disc && !slow)
+		return -EAGAIN; /* Will be done on the slow path. */
 	event = css_get_subchannel_status(sch, irq);
 	switch (event) {
 	case CIO_GONE:
@@ -252,18 +261,13 @@ css_evaluate_subchannel(int irq)
 	return ret;
 }
 
-/*
- * Rescan for new devices. FIXME: This is slow.
- * This function is called when we have lost CRWs due to overflows and we have
- * to do subchannel housekeeping.
- */
-void
-css_reiterate_subchannels(void)
+static void
+css_rescan_devices(void)
 {
 	int irq, ret;
 
 	for (irq = 0; irq <= __MAX_SUBCHANNELS; irq++) {
-		ret = css_evaluate_subchannel(irq);
+		ret = css_evaluate_subchannel(irq, 1);
 		/* No more memory. It doesn't make sense to continue. No
 		 * panic because this can happen in midflight and just
 		 * because we can't use a new device is no reason to crash
@@ -276,20 +280,61 @@ css_reiterate_subchannels(void)
 	}
 }
 
+static void
+css_evaluate_slow_subchannel(unsigned long schid)
+{
+	css_evaluate_subchannel(schid, 1);
+}
+
+void
+css_trigger_slow_path(void)
+{
+	if (need_rescan) {
+		need_rescan = 0;
+		css_rescan_devices();
+		return;
+	}
+	css_walk_subchannel_slow_list(css_evaluate_slow_subchannel);
+}
+
 /*
- * Called from the machine check handler for subchannel report words.
+ * Rescan for new devices. FIXME: This is slow.
+ * This function is called when we have lost CRWs due to overflows and we have
+ * to do subchannel housekeeping.
  */
 void
+css_reiterate_subchannels(void)
+{
+	css_clear_subchannel_slow_list();
+	need_rescan = 1;
+}
+
+/*
+ * Called from the machine check handler for subchannel report words.
+ */
+int
 css_process_crw(int irq)
 {
+	int ret;
+
 	CIO_CRW_EVENT(2, "source is subchannel %04X\n", irq);
 
+	if (need_rescan)
+		/* We need to iterate all subchannels anyway. */
+		return -EAGAIN;
 	/* 
 	 * Since we are always presented with IPI in the CRW, we have to
 	 * use stsch() to find out if the subchannel in question has come
 	 * or gone.
 	 */
-	css_evaluate_subchannel(irq);
+	ret = css_evaluate_subchannel(irq, 0);
+	if (ret == -EAGAIN) {
+		if (css_enqueue_subchannel_slow(irq)) {
+			css_clear_subchannel_slow_list();
+			need_rescan = 1;
+		}
+	}
+	return ret;
 }
 
 /*
@@ -412,6 +457,73 @@ s390_root_dev_unregister(struct device *
 		device_unregister(dev);
 }
 
+struct slow_subchannel {
+	struct list_head slow_list;
+	unsigned long schid;
+};
+
+static LIST_HEAD(slow_subchannels_head);
+static spinlock_t slow_subchannel_lock = SPIN_LOCK_UNLOCKED;
+
+int
+css_enqueue_subchannel_slow(unsigned long schid)
+{
+	struct slow_subchannel *new_slow_sch;
+	unsigned long flags;
+
+	new_slow_sch = kmalloc(sizeof(struct slow_subchannel), GFP_ATOMIC);
+	if (!new_slow_sch)
+		return -ENOMEM;
+	new_slow_sch->schid = schid;
+	spin_lock_irqsave(&slow_subchannel_lock, flags);
+	list_add_tail(&new_slow_sch->slow_list, &slow_subchannels_head);
+	spin_unlock_irqrestore(&slow_subchannel_lock, flags);
+	return 0;
+}
+
+void
+css_clear_subchannel_slow_list(void)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&slow_subchannel_lock, flags);
+	while (!list_empty(&slow_subchannels_head)) {
+		struct slow_subchannel *slow_sch =
+			list_entry(slow_subchannels_head.next,
+				   struct slow_subchannel, slow_list);
+
+		list_del_init(slow_subchannels_head.next);
+		kfree(slow_sch);
+	}
+	spin_unlock_irqrestore(&slow_subchannel_lock, flags);
+}
+
+void
+css_walk_subchannel_slow_list(void (*fn)(unsigned long))
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&slow_subchannel_lock, flags);
+	while (!list_empty(&slow_subchannels_head)) {
+		struct slow_subchannel *slow_sch =
+			list_entry(slow_subchannels_head.next,
+				   struct slow_subchannel, slow_list);
+
+		list_del_init(slow_subchannels_head.next);
+		spin_unlock_irqrestore(&slow_subchannel_lock, flags);
+		fn(slow_sch->schid);
+		spin_lock_irqsave(&slow_subchannel_lock, flags);
+		kfree(slow_sch);
+	}
+	spin_unlock_irqrestore(&slow_subchannel_lock, flags);
+}
+
+int
+css_slow_subchannels_exist(void)
+{
+	return (!list_empty(&slow_subchannels_head));
+}
+
 MODULE_LICENSE("GPL");
 EXPORT_SYMBOL(css_bus_type);
 EXPORT_SYMBOL(s390_root_dev_register);
--- diff/drivers/s390/cio/css.h	2004-02-09 10:36:11.000000000 +0000
+++ source/drivers/s390/cio/css.h	2004-02-23 13:56:45.000000000 +0000
@@ -65,6 +65,7 @@ struct senseid {
 
 struct ccw_device_private {
 	int state;		/* device state */
+	atomic_t onoff;
 	__u16 devno;		/* device number */
 	__u16 irq;		/* subchannel number */
 	__u8 imask;		/* lpm mask for SNID/SID/SPGID */
@@ -90,6 +91,10 @@ struct ccw_device_private {
 	struct work_struct kick_work;
 	wait_queue_head_t wait_q;
 	struct timer_list timer;
+	void *cmb;			/* measurement information */
+	struct list_head cmb_list;	/* list of measured devices */
+	u64 cmb_start_time;		/* clock value of cmb reset */
+	void *cmb_wait;			/* deferred cmb enable/disable */
 };
 
 /*
@@ -127,6 +132,14 @@ int device_is_disconnected(struct subcha
 void device_set_disconnected(struct subchannel *);
 void device_trigger_reprobe(struct subchannel *);
 
-/* Helper function for vary on/off. */
+/* Helper functions for vary on/off. */
 void device_set_waiting(struct subchannel *);
+void device_call_nopath_notify(struct subchannel *);
+
+/* Helper functions to build lists for the slow path. */
+int css_enqueue_subchannel_slow(unsigned long schid);
+void css_walk_subchannel_slow_list(void (*fn)(unsigned long));
+void css_clear_subchannel_slow_list(void);
+int css_slow_subchannels_exist(void);
+extern int need_rescan;
 #endif
--- diff/drivers/s390/cio/device.c	2004-02-09 10:36:11.000000000 +0000
+++ source/drivers/s390/cio/device.c	2004-02-23 13:56:45.000000000 +0000
@@ -1,7 +1,7 @@
 /*
  *  drivers/s390/cio/device.c
  *  bus driver for ccw devices
- *   $Revision: 1.85 $
+ *   $Revision: 1.103 $
  *
  *    Copyright (C) 2002 IBM Deutschland Entwicklung GmbH,
  *			 IBM Corporation
@@ -73,7 +73,7 @@ ccw_hotplug (struct device *dev, char **
 	/* what we want to pass to /sbin/hotplug */
 
 	envp[i++] = buffer;
-	length += snprintf(buffer, buffer_size - length, "CU_TYPE=%04X",
+	length += scnprintf(buffer, buffer_size - length, "CU_TYPE=%04X",
 			   cdev->id.cu_type);
 	if ((buffer_size - length <= 0) || (i >= num_envp))
 		return -ENOMEM;
@@ -81,7 +81,7 @@ ccw_hotplug (struct device *dev, char **
 	buffer += length;
 
 	envp[i++] = buffer;
-	length += snprintf(buffer, buffer_size - length, "CU_MODEL=%02X",
+	length += scnprintf(buffer, buffer_size - length, "CU_MODEL=%02X",
 			   cdev->id.cu_model);
 	if ((buffer_size - length <= 0) || (i >= num_envp))
 		return -ENOMEM;
@@ -90,7 +90,7 @@ ccw_hotplug (struct device *dev, char **
 
 	/* The next two can be zero, that's ok for us */
 	envp[i++] = buffer;
-	length += snprintf(buffer, buffer_size - length, "DEV_TYPE=%04X",
+	length += scnprintf(buffer, buffer_size - length, "DEV_TYPE=%04X",
 			   cdev->id.dev_type);
 	if ((buffer_size - length <= 0) || (i >= num_envp))
 		return -ENOMEM;
@@ -98,7 +98,7 @@ ccw_hotplug (struct device *dev, char **
 	buffer += length;
 
 	envp[i++] = buffer;
-	length += snprintf(buffer, buffer_size - length, "DEV_MODEL=%02X",
+	length += scnprintf(buffer, buffer_size - length, "DEV_MODEL=%02X",
 			   cdev->id.dev_model);
 	if ((buffer_size - length <= 0) || (i >= num_envp))
 		return -ENOMEM;
@@ -240,6 +240,22 @@ online_show (struct device *dev, char *b
 	return sprintf(buf, cdev->online ? "1\n" : "0\n");
 }
 
+static void
+ccw_device_remove_disconnected(struct ccw_device *cdev)
+{
+	struct subchannel *sch;
+	/*
+	 * Forced offline in disconnected state means
+	 * 'throw away device'.
+	 */
+	sch = to_subchannel(cdev->dev.parent);
+	device_unregister(&sch->dev);
+	/* Reset intparm to zeroes. */
+	sch->schib.pmcw.intparm = 0;
+	cio_modify(sch);
+	put_device(&sch->dev);
+}
+
 int
 ccw_device_set_offline(struct ccw_device *cdev)
 {
@@ -250,20 +266,6 @@ ccw_device_set_offline(struct ccw_device
 	if (!cdev->online || !cdev->drv)
 		return -EINVAL;
 
-	if (cdev->private->state == DEV_STATE_DISCONNECTED) {
-		struct subchannel *sch;
-		/* 
-		 * Forced offline in disconnected state means 
-		 * 'throw away device'.
-		 */
-		sch = to_subchannel(cdev->dev.parent);
-		device_unregister(&sch->dev);
-		/* Reset intparm to zeroes. */
-		sch->schib.pmcw.intparm = 0;
-		cio_modify(sch);
-		put_device(&sch->dev);
-		return 0;
-	}
 	if (cdev->drv->set_offline) {
 		ret = cdev->drv->set_offline(cdev);
 		if (ret != 0)
@@ -280,7 +282,7 @@ ccw_device_set_offline(struct ccw_device
 			 ret, cdev->dev.bus_id);
 		cdev->online = 1;
 	}
-	return ret;
+ 	return ret;
 }
 
 int
@@ -329,15 +331,19 @@ online_store (struct device *dev, const 
 
 	if (!cdev->drv)
 		return count;
+	if (atomic_compare_and_swap(0, 1, &cdev->private->onoff))
+		return -EAGAIN;
 
 	i = simple_strtoul(buf, &tmp, 16);
 	if (i == 1 && cdev->drv->set_online)
 		ccw_device_set_online(cdev);
-	else if (i == 0 && cdev->drv->set_offline)
-		ccw_device_set_offline(cdev);
-	else
-		return -EINVAL;
-
+	else if (i == 0 && cdev->drv->set_offline) {
+		if (cdev->private->state == DEV_STATE_DISCONNECTED)
+			ccw_device_remove_disconnected(cdev);
+		else
+			ccw_device_set_offline(cdev);
+	}
+	atomic_set(&cdev->private->onoff, 0);
 	return count;
 }
 
@@ -369,12 +375,37 @@ stlck_store(struct device *dev, const ch
 	return count;
 }
 
+static ssize_t
+available_show (struct device *dev, char *buf)
+{
+	struct ccw_device *cdev = to_ccwdev(dev);
+	struct subchannel *sch;
+
+	switch (cdev->private->state) {
+	case DEV_STATE_BOXED:
+		return sprintf(buf, "boxed\n");
+	case DEV_STATE_DISCONNECTED:
+	case DEV_STATE_DISCONNECTED_SENSE_ID:
+	case DEV_STATE_NOT_OPER:
+		sch = to_subchannel(dev->parent);
+		if (!sch->lpm)
+			return sprintf(buf, "no path\n");
+		else
+			return sprintf(buf, "no device\n");
+	default:
+		/* All other states considered fine. */
+		return sprintf(buf, "good\n");
+	}
+}
+
 static DEVICE_ATTR(chpids, 0444, chpids_show, NULL);
 static DEVICE_ATTR(pimpampom, 0444, pimpampom_show, NULL);
 static DEVICE_ATTR(devtype, 0444, devtype_show, NULL);
 static DEVICE_ATTR(cutype, 0444, cutype_show, NULL);
 static DEVICE_ATTR(online, 0644, online_show, online_store);
 static DEVICE_ATTR(steal_lock, 0200, NULL, stlck_store);
+extern struct device_attribute dev_attr_cmb_enable;
+static DEVICE_ATTR(availability, 0444, available_show, NULL);
 
 /* A device has been unboxed. Start device recognition. */
 static void
@@ -419,6 +450,8 @@ static struct attribute * ccwdev_attrs[]
 	&dev_attr_devtype.attr,
 	&dev_attr_cutype.attr,
 	&dev_attr_online.attr,
+	&dev_attr_cmb_enable.attr,
+	&dev_attr_availability.attr,
 	NULL,
 };
 
@@ -468,7 +501,7 @@ ccw_device_register(struct ccw_device *c
 		return ret;
 
 	if ((ret = device_add_files(dev)))
-		device_unregister(dev);
+		device_del(dev);
 
 	return ret;
 }
@@ -521,6 +554,7 @@ io_subchannel_register(void *data)
 	if (ret) {
 		printk (KERN_WARNING "%s: could not register %s\n",
 			__func__, cdev->dev.bus_id);
+		put_device(&cdev->dev);
 		sch->dev.driver_data = 0;
 		kfree (cdev->private);
 		kfree (cdev);
@@ -533,10 +567,25 @@ io_subchannel_register(void *data)
 		       __func__, sch->dev.bus_id);
 	if (cdev->private->state == DEV_STATE_BOXED)
 		device_create_file(&cdev->dev, &dev_attr_steal_lock);
+	put_device(&cdev->dev);
 out:
 	put_device(&sch->dev);
 }
 
+static void
+device_call_sch_unregister(void *data)
+{
+	struct ccw_device *cdev = data;
+	struct subchannel *sch;
+
+	sch = to_subchannel(cdev->dev.parent);
+	device_unregister(&sch->dev);
+	/* Reset intparm to zeroes. */
+	sch->schib.pmcw.intparm = 0;
+	cio_modify(sch);
+	put_device(&cdev->dev);
+}
+
 /*
  * subchannel recognition done. Called from the state machine.
  */
@@ -550,11 +599,12 @@ io_subchannel_recog_done(struct ccw_devi
 	switch (cdev->private->state) {
 	case DEV_STATE_NOT_OPER:
 		/* Remove device found not operational. */
+		if (!get_device(&cdev->dev))
+			break;
 		sch = to_subchannel(cdev->dev.parent);
-		sch->dev.driver_data = 0;
-		put_device(&sch->dev);
-		if (cdev->dev.release)
-			cdev->dev.release(&cdev->dev);
+		INIT_WORK(&cdev->private->kick_work,
+			  device_call_sch_unregister, (void *) cdev);
+		queue_work(ccw_device_work, &cdev->private->kick_work);
 		break;
 	case DEV_STATE_BOXED:
 		/* Device did not respond in time. */
@@ -563,6 +613,8 @@ io_subchannel_recog_done(struct ccw_devi
 		 * We can't register the device in interrupt context so
 		 * we schedule a work item.
 		 */
+		if (!get_device(&cdev->dev))
+			break;
 		INIT_WORK(&cdev->private->kick_work,
 			  io_subchannel_register, (void *) cdev);
 		queue_work(ccw_device_work, &cdev->private->kick_work);
@@ -584,6 +636,7 @@ io_subchannel_recog(struct ccw_device *c
 		.devno	= sch->schib.pmcw.dev,
 		.irq	= sch->irq,
 		.state	= DEV_STATE_NOT_OPER,
+		.cmb_list = LIST_HEAD_INIT(cdev->private->cmb_list),
 	};
 	init_waitqueue_head(&cdev->private->wait_q);
 	init_timer(&cdev->private->timer);
@@ -647,6 +700,7 @@ io_subchannel_probe (struct device *pdev
 		return -ENOMEM;
 	}
 	memset(cdev->private, 0, sizeof(struct ccw_device_private));
+	atomic_set(&cdev->private->onoff, 0);
 	cdev->dev = (struct device) {
 		.parent = pdev,
 		.release = ccw_device_release,
@@ -657,18 +711,17 @@ io_subchannel_probe (struct device *pdev
 	if (!get_device(&sch->dev)) {
 		if (cdev->dev.release)
 			cdev->dev.release(&cdev->dev);
-		return 0;
+		return -ENODEV;
 	}
 
 	rc = io_subchannel_recog(cdev, to_subchannel(pdev));
 	if (rc) {
 		sch->dev.driver_data = 0;
-		put_device(&sch->dev);
 		if (cdev->dev.release)
 			cdev->dev.release(&cdev->dev);
 	}
 
-	return 0;
+	return rc;
 }
 
 static int
@@ -680,8 +733,14 @@ io_subchannel_remove (struct device *dev
 		return 0;
 	cdev = dev->driver_data;
 	/* Set ccw device to not operational and drop reference. */
-	dev_fsm_event(cdev, DEV_EVENT_NOTOPER);
-	put_device(&cdev->dev);
+	cdev->private->state = DEV_STATE_NOT_OPER;
+	/*
+	 * Careful here. Our ccw device might be yet unregistered when
+	 * de-registering its subchannel (machine check during device
+	 * recognition). Better look if the subchannel has children.
+	 */
+	if (!list_empty(&dev->children))
+		device_unregister(&cdev->dev);
 	dev->driver_data = NULL;
 	return 0;
 }
@@ -860,10 +919,7 @@ ccw_device_remove (struct device *dev)
 	struct ccw_driver *cdrv = cdev->drv;
 	int ret;
 
-	pr_debug("removing device %s, sch %d, devno %x\n",
-		 cdev->dev.bus_id,
-		 cdev->private->irq,
-		 cdev->private->devno);
+	pr_debug("removing device %s\n", cdev->dev.bus_id);
 	if (cdrv->remove)
 		cdrv->remove(cdev);
 	if (cdev->online) {
@@ -879,6 +935,7 @@ ccw_device_remove (struct device *dev)
 			pr_debug("ccw_device_offline returned %d, device %s\n",
 				 ret, cdev->dev.bus_id);
 	}
+	cdev->drv = 0;
 	return 0;
 }
 
--- diff/drivers/s390/cio/device.h	2004-02-09 10:36:11.000000000 +0000
+++ source/drivers/s390/cio/device.h	2004-02-23 13:56:45.000000000 +0000
@@ -21,6 +21,7 @@ enum dev_state {
 	/* special states for devices gone not operational */
 	DEV_STATE_DISCONNECTED,
 	DEV_STATE_DISCONNECTED_SENSE_ID,
+	DEV_STATE_CMFCHANGE,
 	/* last element! */
 	NR_DEV_STATES
 };
@@ -106,4 +107,6 @@ int ccw_device_stlck(struct ccw_device *
 
 /* qdio needs this. */
 void ccw_device_set_timeout(struct ccw_device *, int);
+
+void retry_set_schib(struct ccw_device *cdev);
 #endif
--- diff/drivers/s390/cio/device_fsm.c	2004-02-09 10:36:11.000000000 +0000
+++ source/drivers/s390/cio/device_fsm.c	2004-02-23 13:56:45.000000000 +0000
@@ -19,6 +19,7 @@
 #include "cio_debug.h"
 #include "css.h"
 #include "device.h"
+#include "chsc.h"
 #include "ioasm.h"
 #include "qdio.h"
 
@@ -42,6 +43,7 @@ device_set_disconnected(struct subchanne
 	if (!sch->dev.driver_data)
 		return;
 	cdev = sch->dev.driver_data;
+	ccw_device_set_timeout(cdev, 0);
 	cdev->private->state = DEV_STATE_DISCONNECTED;
 }
 
@@ -78,8 +80,7 @@ void
 ccw_device_set_timeout(struct ccw_device *cdev, int expires)
 {
 	if (expires == 0) {
-		if (timer_pending(&cdev->private->timer))
-			del_timer(&cdev->private->timer);
+		del_timer(&cdev->private->timer);
 		return;
 	}
 	if (timer_pending(&cdev->private->timer)) {
@@ -167,18 +168,53 @@ ccw_device_handle_oper(struct ccw_device
 }
 
 /*
+ * The machine won't give us any notification by machine check if a chpid has
+ * been varied online on the SE so we have to find out by magic (i. e. driving
+ * the channel subsystem to device selection and updating our path masks).
+ */
+static inline void
+__recover_lost_chpids(struct subchannel *sch, int old_lpm)
+{
+	int mask, i;
+
+	for (i = 0; i<8; i++) {
+		mask = 0x80 >> i;
+		if (!(sch->lpm & mask))
+			continue;
+		if (old_lpm & mask)
+			continue;
+		chpid_is_actually_online(sch->schib.pmcw.chpid[i]);
+	}
+}
+
+/*
  * Stop device recognition.
  */
 static void
 ccw_device_recog_done(struct ccw_device *cdev, int state)
 {
 	struct subchannel *sch;
-	int notify;
+	int notify, old_lpm;
 
 	sch = to_subchannel(cdev->dev.parent);
 
 	ccw_device_set_timeout(cdev, 0);
 	cio_disable_subchannel(sch);
+	/*
+	 * Now that we tried recognition, we have performed device selection
+	 * through ssch() and the path information is up to date.
+	 */
+	old_lpm = sch->lpm;
+	stsch(sch->irq, &sch->schib);
+	sch->lpm = sch->schib.pmcw.pim &
+		sch->schib.pmcw.pam &
+		sch->schib.pmcw.pom &
+		sch->opm;
+	if (cdev->private->state == DEV_STATE_DISCONNECTED_SENSE_ID)
+		/* Force reprobe on all chpids. */
+		old_lpm = 0;
+	if (sch->lpm != old_lpm)
+		__recover_lost_chpids(sch, old_lpm);
 	if (cdev->private->state == DEV_STATE_DISCONNECTED_SENSE_ID) {
 		if (state == DEV_STATE_NOT_OPER) {
 			cdev->private->state = DEV_STATE_DISCONNECTED;
@@ -190,8 +226,8 @@ ccw_device_recog_done(struct ccw_device 
 	switch (state) {
 	case DEV_STATE_NOT_OPER:
 		CIO_DEBUG(KERN_WARNING, 2,
-			  "SenseID : unknown device %s on subchannel %s\n",
-			  cdev->dev.bus_id, sch->dev.bus_id);
+			  "SenseID : unknown device %04x on subchannel %04x\n",
+			  cdev->private->devno, sch->irq);
 		break;
 	case DEV_STATE_OFFLINE:
 		if (cdev->private->state == DEV_STATE_DISCONNECTED_SENSE_ID)
@@ -204,16 +240,16 @@ ccw_device_recog_done(struct ccw_device 
 				.dev_model = cdev->private->senseid.dev_model,
 			};
 		/* Issue device info message. */
-		CIO_DEBUG(KERN_INFO, 2, "SenseID : device %s reports: "
+		CIO_DEBUG(KERN_INFO, 2, "SenseID : device %04x reports: "
 			  "CU  Type/Mod = %04X/%02X, Dev Type/Mod = "
-			  "%04X/%02X\n", cdev->dev.bus_id,
+			  "%04X/%02X\n", cdev->private->devno,
 			  cdev->id.cu_type, cdev->id.cu_model,
 			  cdev->id.dev_type, cdev->id.dev_model);
 		break;
 	case DEV_STATE_BOXED:
 		CIO_DEBUG(KERN_WARNING, 2,
-			  "SenseID : boxed device %s on subchannel %s\n",
-			  cdev->dev.bus_id, sch->dev.bus_id);
+			  "SenseID : boxed device %04x on subchannel %04x\n",
+			  cdev->private->devno, sch->irq);
 		break;
 	}
 	cdev->private->state = state;
@@ -283,8 +319,8 @@ ccw_device_done(struct ccw_device *cdev,
 
 	if (state == DEV_STATE_BOXED) {
 		CIO_DEBUG(KERN_WARNING, 2,
-			  "Boxed device %s on subchannel %s\n",
-			  cdev->dev.bus_id, sch->dev.bus_id);
+			  "Boxed device %04x on subchannel %04x\n",
+			  cdev->private->devno, sch->irq);
 		INIT_WORK(&cdev->private->kick_work,
 			  ccw_device_add_stlck, (void *) cdev);
 		queue_work(ccw_device_work, &cdev->private->kick_work);
@@ -387,6 +423,46 @@ ccw_device_recog_timeout(struct ccw_devi
 }
 
 
+static void
+ccw_device_nopath_notify(void *data)
+{
+	struct ccw_device *cdev;
+	struct subchannel *sch;
+	int ret;
+
+	cdev = (struct ccw_device *)data;
+	sch = to_subchannel(cdev->dev.parent);
+	/* Extra sanity. */
+	if (sch->lpm)
+		return;
+	ret = (sch->driver && sch->driver->notify) ?
+		sch->driver->notify(&sch->dev, CIO_NO_PATH) : 0;
+	if (!ret) {
+		/* Driver doesn't want to keep device. */
+		device_unregister(&sch->dev);
+		sch->schib.pmcw.intparm = 0;
+		cio_modify(sch);
+	} else {
+		ccw_device_set_timeout(cdev, 0);
+		cdev->private->state = DEV_STATE_DISCONNECTED;
+		wake_up(&cdev->private->wait_q);
+	}
+}
+
+void
+device_call_nopath_notify(struct subchannel *sch)
+{
+	struct ccw_device *cdev;
+
+	if (!sch->dev.driver_data)
+		return;
+	cdev = sch->dev.driver_data;
+	PREPARE_WORK(&cdev->private->kick_work,
+		     ccw_device_nopath_notify, (void *)cdev);
+	queue_work(ccw_device_work, &cdev->private->kick_work);
+}
+
+
 void
 ccw_device_verify_done(struct ccw_device *cdev, int err)
 {
@@ -399,6 +475,9 @@ ccw_device_verify_done(struct ccw_device
 		ccw_device_done(cdev, DEV_STATE_BOXED);
 		break;
 	default:
+		PREPARE_WORK(&cdev->private->kick_work,
+			     ccw_device_nopath_notify, (void *)cdev);
+		queue_work(ccw_device_work, &cdev->private->kick_work);
 		ccw_device_done(cdev, DEV_STATE_NOT_OPER);
 		break;
 	}
@@ -508,10 +587,7 @@ ccw_device_onoff_timeout(struct ccw_devi
 static void
 ccw_device_recog_notoper(struct ccw_device *cdev, enum dev_event dev_event)
 {
-	if (cdev->private->state == DEV_STATE_DISCONNECTED_SENSE_ID)
-		cdev->private->state = DEV_STATE_DISCONNECTED;
-	else
-		ccw_device_recog_done(cdev, DEV_STATE_NOT_OPER);
+	ccw_device_recog_done(cdev, DEV_STATE_NOT_OPER);
 }
 
 /*
@@ -520,8 +596,13 @@ ccw_device_recog_notoper(struct ccw_devi
 static void
 ccw_device_offline_notoper(struct ccw_device *cdev, enum dev_event dev_event)
 {
+	struct subchannel *sch;
+
 	cdev->private->state = DEV_STATE_NOT_OPER;
-	device_unregister(&cdev->dev);
+	sch = to_subchannel(cdev->dev.parent);
+	device_unregister(&sch->dev);
+	sch->schib.pmcw.intparm = 0;
+	cio_modify(sch);
 	wake_up(&cdev->private->wait_q);
 }
 
@@ -540,7 +621,9 @@ ccw_device_online_notoper(struct ccw_dev
 		// FIXME: not-oper indication to device driver ?
 		ccw_device_call_handler(cdev);
 	}
-	device_unregister(&cdev->dev);
+	device_unregister(&sch->dev);
+	sch->schib.pmcw.intparm = 0;
+	cio_modify(sch);
 	wake_up(&cdev->private->wait_q);
 }
 
@@ -553,7 +636,9 @@ ccw_device_disconnected_notoper(struct c
 	sch = to_subchannel(cdev->dev.parent);
 	cdev->private->state = DEV_STATE_NOT_OPER;
 	cio_disable_subchannel(sch);
-	device_unregister(&cdev->dev);
+	device_unregister(&sch->dev);
+	sch->schib.pmcw.intparm = 0;
+	cio_modify(sch);
 	wake_up(&cdev->private->wait_q);
 }
 
@@ -692,11 +777,21 @@ ccw_device_clear_verify(struct ccw_devic
 static void
 ccw_device_killing_irq(struct ccw_device *cdev, enum dev_event dev_event)
 {
+	struct subchannel *sch;
+
+	sch = to_subchannel(cdev->dev.parent);
 	/* OK, i/o is dead now. Call interrupt handler. */
 	cdev->private->state = DEV_STATE_ONLINE;
 	if (cdev->handler)
 		cdev->handler(cdev, cdev->private->intparm,
 			      ERR_PTR(-ETIMEDOUT));
+	if (!sch->lpm) {
+		PREPARE_WORK(&cdev->private->kick_work,
+			     ccw_device_nopath_notify, (void *)cdev);
+		queue_work(ccw_device_work, &cdev->private->kick_work);
+	} else if (cdev->private->flags.doverify)
+		/* Start delayed path verification. */
+		ccw_device_online_verify(cdev, 0);
 }
 
 static void
@@ -710,6 +805,14 @@ ccw_device_killing_timeout(struct ccw_de
 		return;
 	}
 	if (ret == -ENODEV) {
+		struct subchannel *sch;
+
+		sch = to_subchannel(cdev->dev.parent);
+		if (!sch->lpm) {
+			PREPARE_WORK(&cdev->private->kick_work,
+				     ccw_device_nopath_notify, (void *)cdev);
+			queue_work(ccw_device_work, &cdev->private->kick_work);
+		}
 		dev_fsm_event(cdev, DEV_EVENT_NOTOPER);
 		return;
 	}
@@ -751,7 +854,12 @@ ccw_device_wait4io_irq(struct ccw_device
 		if (sch->schib.scsw.actl == 0)
 			ccw_device_set_timeout(cdev, 0);
 	/* Call the handler. */
-	if (ccw_device_call_handler(cdev) && cdev->private->flags.doverify)
+	ccw_device_call_handler(cdev);
+	if (!sch->lpm) {
+		PREPARE_WORK(&cdev->private->kick_work,
+			     ccw_device_nopath_notify, (void *)cdev);
+		queue_work(ccw_device_work, &cdev->private->kick_work);
+	} else if (cdev->private->flags.doverify)
 		ccw_device_online_verify(cdev, 0);
 }
 
@@ -759,6 +867,7 @@ static void
 ccw_device_wait4io_timeout(struct ccw_device *cdev, enum dev_event dev_event)
 {
 	int ret;
+	struct subchannel *sch;
 
 	ccw_device_set_timeout(cdev, 0);
 	ret = ccw_device_cancel_halt_clear(cdev);
@@ -767,11 +876,24 @@ ccw_device_wait4io_timeout(struct ccw_de
 		cdev->private->state = DEV_STATE_TIMEOUT_KILL;
 		return;
 	}
-	if (ret == -ENODEV)
+	if (ret == -ENODEV) {
+		PREPARE_WORK(&cdev->private->kick_work,
+			     ccw_device_nopath_notify, (void *)cdev);
+		queue_work(ccw_device_work, &cdev->private->kick_work);
 		dev_fsm_event(cdev, DEV_EVENT_NOTOPER);
-	else if (cdev->handler)
+		return;
+	}
+	if (cdev->handler)
 		cdev->handler(cdev, cdev->private->intparm,
 			      ERR_PTR(-ETIMEDOUT));
+	sch = to_subchannel(cdev->dev.parent);
+	if (!sch->lpm) {
+		PREPARE_WORK(&cdev->private->kick_work,
+			     ccw_device_nopath_notify, (void *)cdev);
+		queue_work(ccw_device_work, &cdev->private->kick_work);
+	} else if (cdev->private->flags.doverify)
+		/* Start delayed path verification. */
+		ccw_device_online_verify(cdev, 0);
 }
 
 static void
@@ -831,9 +953,24 @@ device_trigger_reprobe(struct subchannel
 	if (!sch->dev.driver_data)
 		return;
 	cdev = sch->dev.driver_data;
-	if (cdev->private->state != DEV_STATE_DISCONNECTED)
-		return;
 	spin_lock_irqsave(&sch->lock, flags);
+	if (cdev->private->state != DEV_STATE_DISCONNECTED) {
+		spin_unlock_irqrestore(&sch->lock, flags);
+		return;
+	}
+	/* Update some values. */
+	if (stsch(sch->irq, &sch->schib)) {
+		spin_unlock_irqrestore(&sch->lock, flags);
+		return;
+	}
+	/*
+	 * The pim, pam, pom values may not be accurate, but they are the best
+	 * we have before performing device selection :/
+	 */
+	sch->lpm = sch->schib.pmcw.pim &
+		sch->schib.pmcw.pam &
+		sch->schib.pmcw.pom &
+		sch->opm;
 	/* Re-set some bits in the pmcw that were lost. */
 	sch->schib.pmcw.isc = 3;
 	sch->schib.pmcw.csense = 1;
@@ -858,6 +995,15 @@ ccw_device_offline_irq(struct ccw_device
 	cio_disable_subchannel(sch);
 }
 
+static void
+ccw_device_change_cmfstate(struct ccw_device *cdev, enum dev_event dev_event)
+{
+	retry_set_schib(cdev);
+	cdev->private->state = DEV_STATE_ONLINE;
+	dev_fsm_event(cdev, dev_event);
+}
+
+
 /*
  * No operation action. This is used e.g. to ignore a timeout event in
  * state offline.
@@ -968,6 +1114,12 @@ fsm_func_t *dev_jumptable[NR_DEV_STATES]
 		[DEV_EVENT_TIMEOUT]	ccw_device_recog_timeout,
 		[DEV_EVENT_VERIFY]	ccw_device_nop,
 	},
+	[DEV_STATE_CMFCHANGE] {
+		[DEV_EVENT_NOTOPER]	ccw_device_change_cmfstate,
+		[DEV_EVENT_INTERRUPT]	ccw_device_change_cmfstate,
+		[DEV_EVENT_TIMEOUT]	ccw_device_change_cmfstate,
+		[DEV_EVENT_VERIFY]	ccw_device_change_cmfstate,
+	},
 };
 
 /*
--- diff/drivers/s390/cio/device_id.c	2004-02-09 10:36:11.000000000 +0000
+++ source/drivers/s390/cio/device_id.c	2004-02-23 13:56:45.000000000 +0000
@@ -195,7 +195,7 @@ __ccw_device_sense_id_start(struct ccw_d
 	/* Try on every path. */
 	ret = -ENODEV;
 	while (cdev->private->imask != 0) {
-		if ((sch->lpm & cdev->private->imask) != 0 &&
+		if ((sch->opm & cdev->private->imask) != 0 &&
 		    cdev->private->iretry > 0) {
 			cdev->private->iretry--;
 			ret = cio_start (sch, cdev->private->iccws,
@@ -246,22 +246,26 @@ ccw_device_check_sense_id(struct ccw_dev
 	/* Check the error cases. */
 	if (irb->scsw.fctl & (SCSW_FCTL_HALT_FUNC | SCSW_FCTL_CLEAR_FUNC))
 		return -ETIME;
-	if (irb->esw.esw0.erw.cons &&
-	    (irb->ecw[0] & (SNS0_CMD_REJECT | SNS0_INTERVENTION_REQ))) {
+	if (irb->esw.esw0.erw.cons && (irb->ecw[0] & SNS0_CMD_REJECT)) {
 		/*
 		 * if the device doesn't support the SenseID
 		 *  command further retries wouldn't help ...
+		 * NB: We don't check here for intervention required like we
+		 *     did before, because tape devices with no tape inserted
+		 *     may present this status *in conjunction with* the
+		 *     sense id information. So, for intervention required,
+		 *     we use the "whack it until it talks" strategy...
 		 */
-		CIO_MSG_EVENT(2, "SenseID : device %s on Subchannel %s "
-			      "reports cmd reject or intervention required\n",
-			      cdev->dev.bus_id, sch->dev.bus_id);
+		CIO_MSG_EVENT(2, "SenseID : device %04x on Subchannel %04x "
+			      "reports cmd reject\n",
+			      cdev->private->devno, sch->irq);
 		return -EOPNOTSUPP;
 	}
 	if (irb->esw.esw0.erw.cons) {
-		CIO_MSG_EVENT(2, "SenseID : UC on dev %s, "
+		CIO_MSG_EVENT(2, "SenseID : UC on dev %04x, "
 			      "lpum %02X, cnt %02d, sns :"
 			      " %02X%02X%02X%02X %02X%02X%02X%02X ...\n",
-			      cdev->dev.bus_id,
+			      cdev->private->devno,
 			      irb->esw.esw0.sublog.lpum,
 			      irb->esw.esw0.erw.scnt,
 			      irb->ecw[0], irb->ecw[1],
@@ -271,15 +275,18 @@ ccw_device_check_sense_id(struct ccw_dev
 		return -EAGAIN;
 	}
 	if (irb->scsw.cc == 3) {
-		CIO_MSG_EVENT(2, "SenseID : path %02X for device %s on "
-			      "subchannel %s is 'not operational'\n",
-			      sch->orb.lpm, cdev->dev.bus_id, sch->dev.bus_id);
+		if ((sch->orb.lpm &
+		     sch->schib.pmcw.pim & sch->schib.pmcw.pam) != 0)
+			CIO_MSG_EVENT(2, "SenseID : path %02X for device %04x on"
+				      " subchannel %04x is 'not operational'\n",
+				      sch->orb.lpm, cdev->private->devno,
+				      sch->irq);
 		return -EACCES;
 	}
 	/* Hmm, whatever happened, try again. */
-	CIO_MSG_EVENT(2, "SenseID : start_IO() for device %s on "
-		      "subchannel %s returns status %02X%02X\n",
-		      cdev->dev.bus_id, sch->dev.bus_id,
+	CIO_MSG_EVENT(2, "SenseID : start_IO() for device %04x on "
+		      "subchannel %04x returns status %02X%02X\n",
+		      cdev->private->devno, sch->irq,
 		      irb->scsw.dstat, irb->scsw.cstat);
 	return -EAGAIN;
 }
--- diff/drivers/s390/cio/device_ops.c	2004-02-09 10:36:11.000000000 +0000
+++ source/drivers/s390/cio/device_ops.c	2004-02-23 13:56:45.000000000 +0000
@@ -154,6 +154,7 @@ ccw_device_call_handler(struct ccw_devic
 {
 	struct subchannel *sch;
 	unsigned int stctl;
+	int ending_status;
 
 	sch = to_subchannel(cdev->dev.parent);
 
@@ -166,7 +167,10 @@ ccw_device_call_handler(struct ccw_devic
 	 *  - unsolicited interrupts
 	 */
 	stctl = cdev->private->irb.scsw.stctl;
-	if (sch->schib.scsw.actl != 0 &&
+	ending_status = (stctl & SCSW_STCTL_SEC_STATUS) ||
+		(stctl == (SCSW_STCTL_ALERT_STATUS | SCSW_STCTL_STATUS_PEND)) ||
+		(stctl == SCSW_STCTL_STATUS_PEND);
+	if (!ending_status &&
 	    !cdev->private->options.repall &&
 	    !(stctl & SCSW_STCTL_INTER_STATUS) &&
 	    !(cdev->private->options.fast &&
@@ -469,6 +473,7 @@ ccw_device_stlck(struct ccw_device *cdev
 		cio_disable_subchannel(sch); //FIXME: return code?
 		goto out_unlock;
 	}
+	cdev->private->irb.scsw.actl |= SCSW_ACTL_START_PEND;
 	spin_unlock_irqrestore(&sch->lock, flags);
 	wait_event(cdev->private->wait_q, cdev->private->irb.scsw.actl == 0);
 	spin_lock_irqsave(&sch->lock, flags);
--- diff/drivers/s390/cio/device_pgid.c	2004-02-09 10:36:11.000000000 +0000
+++ source/drivers/s390/cio/device_pgid.c	2004-02-23 13:56:45.000000000 +0000
@@ -55,10 +55,10 @@ __ccw_device_sense_pgid_start(struct ccw
 			/* ret is 0, -EBUSY, -EACCES or -ENODEV */
 			if (ret != -EACCES)
 				return ret;
-			CIO_MSG_EVENT(2, "SNID - Device %s on Subchannel "
-				      "%s, lpm %02X, became 'not "
+			CIO_MSG_EVENT(2, "SNID - Device %04x on Subchannel "
+				      "%04x, lpm %02X, became 'not "
 				      "operational'\n",
-				      cdev->dev.bus_id, sch->dev.bus_id,
+				      cdev->private->devno, sch->irq,
 				      cdev->private->imask);
 
 		}
@@ -105,10 +105,10 @@ __ccw_device_check_sense_pgid(struct ccw
 		return -EOPNOTSUPP;
 	}
 	if (irb->esw.esw0.erw.cons) {
-		CIO_MSG_EVENT(2, "SNID - device %s, unit check, "
+		CIO_MSG_EVENT(2, "SNID - device %04x, unit check, "
 			      "lpum %02X, cnt %02d, sns : "
 			      "%02X%02X%02X%02X %02X%02X%02X%02X ...\n",
-			      cdev->dev.bus_id,
+			      cdev->private->devno,
 			      irb->esw.esw0.sublog.lpum,
 			      irb->esw.esw0.erw.scnt,
 			      irb->ecw[0], irb->ecw[1],
@@ -118,15 +118,15 @@ __ccw_device_check_sense_pgid(struct ccw
 		return -EAGAIN;
 	}
 	if (irb->scsw.cc == 3) {
-		CIO_MSG_EVENT(2, "SNID - Device %s on Subchannel "
-			      "%s, lpm %02X, became 'not operational'\n",
-			      cdev->dev.bus_id, sch->dev.bus_id, sch->orb.lpm);
+		CIO_MSG_EVENT(2, "SNID - Device %04x on Subchannel "
+			      "%04x, lpm %02X, became 'not operational'\n",
+			      cdev->private->devno, sch->irq, sch->orb.lpm);
 		return -EACCES;
 	}
 	if (cdev->private->pgid.inf.ps.state2 == SNID_STATE2_RESVD_ELSE) {
-		CIO_MSG_EVENT(2, "SNID - Device %s on Subchannel %s "
+		CIO_MSG_EVENT(2, "SNID - Device %04x on Subchannel %04x "
 			      "is reserved by someone else\n",
-			      cdev->dev.bus_id, sch->dev.bus_id);
+			      cdev->private->devno, sch->irq);
 		return -EUSERS;
 	}
 	return 0;
@@ -233,9 +233,9 @@ __ccw_device_do_pgid(struct ccw_device *
 	/* PGID command failed on this path. Switch it off. */
 	sch->lpm &= ~cdev->private->imask;
 	sch->vpm &= ~cdev->private->imask;
-	CIO_MSG_EVENT(2, "SPID - Device %s on Subchannel "
-		      "%s, lpm %02X, became 'not operational'\n",
-		      cdev->dev.bus_id, sch->dev.bus_id, cdev->private->imask);
+	CIO_MSG_EVENT(2, "SPID - Device %04x on Subchannel "
+		      "%04x, lpm %02X, became 'not operational'\n",
+		      cdev->private->devno, sch->irq, cdev->private->imask);
 	return ret;
 }
 
@@ -257,9 +257,9 @@ __ccw_device_check_pgid(struct ccw_devic
 		if (irb->ecw[0] & SNS0_CMD_REJECT)
 			return -EOPNOTSUPP;
 		/* Hmm, whatever happened, try again. */
-		CIO_MSG_EVENT(2, "SPID - device %s, unit check, cnt %02d, "
+		CIO_MSG_EVENT(2, "SPID - device %04x, unit check, cnt %02d, "
 			      "sns : %02X%02X%02X%02X %02X%02X%02X%02X ...\n",
-			      cdev->dev.bus_id, irb->esw.esw0.erw.scnt,
+			      cdev->private->devno, irb->esw.esw0.erw.scnt,
 			      irb->ecw[0], irb->ecw[1],
 			      irb->ecw[2], irb->ecw[3],
 			      irb->ecw[4], irb->ecw[5],
@@ -267,9 +267,9 @@ __ccw_device_check_pgid(struct ccw_devic
 		return -EAGAIN;
 	}
 	if (irb->scsw.cc == 3) {
-		CIO_MSG_EVENT(2, "SPID - Device %s on Subchannel "
-			      "%s, lpm %02X, became 'not operational'\n",
-			      cdev->dev.bus_id, sch->dev.bus_id,
+		CIO_MSG_EVENT(2, "SPID - Device %04x on Subchannel "
+			      "%04x, lpm %02X, became 'not operational'\n",
+			      cdev->private->devno, sch->irq,
 			      cdev->private->imask);
 		return -EACCES;
 	}
--- diff/drivers/s390/cio/device_status.c	2004-02-09 10:36:11.000000000 +0000
+++ source/drivers/s390/cio/device_status.c	2004-02-23 13:56:45.000000000 +0000
@@ -62,8 +62,8 @@ ccw_device_path_notoper(struct ccw_devic
 	sch = to_subchannel(cdev->dev.parent);
 	stsch (sch->irq, &sch->schib);
 
-	CIO_MSG_EVENT(0, "%s(%s) - path(s) %02x are "
-		      "not operational \n", __FUNCTION__, sch->dev.bus_id,
+	CIO_MSG_EVENT(0, "%s(%04x) - path(s) %02x are "
+		      "not operational \n", __FUNCTION__, sch->irq,
 		      sch->schib.pmcw.pnom);
 
 	sch->lpm &= ~sch->schib.pmcw.pnom;
@@ -228,8 +228,8 @@ ccw_device_accumulate_irb(struct ccw_dev
 		cdev_irb->scsw.key = irb->scsw.key;
 		/* Copy suspend control bit. */
 		cdev_irb->scsw.sctl = irb->scsw.sctl;
-		/* Copy deferred condition code. */
-		cdev_irb->scsw.cc = irb->scsw.cc;
+		/* Accumulate deferred condition code. */
+		cdev_irb->scsw.cc |= irb->scsw.cc;
 		/* Copy ccw format bit. */
 		cdev_irb->scsw.fmt = irb->scsw.fmt;
 		/* Copy prefetch bit. */
--- diff/drivers/s390/cio/qdio.c	2004-02-09 10:36:11.000000000 +0000
+++ source/drivers/s390/cio/qdio.c	2004-02-23 13:56:45.000000000 +0000
@@ -6,8 +6,8 @@
  * version 2
  *
  * Copyright 2000,2002 IBM Corporation
- * Author(s): Utz Bacher <utz.bacher@de.ibm.com>
- *            Cornelia Huck <cohuck@de.ibm.com>
+ * Author(s):             Utz Bacher <utz.bacher@de.ibm.com>
+ * 2.6 cio integration by Cornelia Huck <cohuck@de.ibm.com>
  *
  * Restriction: only 63 iqdio subchannels would have its own indicator,
  * after that, subsequent subchannels share one indicator
@@ -56,7 +56,7 @@
 #include "ioasm.h"
 #include "chsc.h"
 
-#define VERSION_QDIO_C "$Revision: 1.67 $"
+#define VERSION_QDIO_C "$Revision: 1.74 $"
 
 /****************** MODULE PARAMETER VARIABLES ********************/
 MODULE_AUTHOR("Utz Bacher <utz.bacher@de.ibm.com>");
@@ -76,6 +76,7 @@ static struct qdio_perf_stats perf_stats
 #endif /* QDIO_PERFORMANCE_STATS */
 
 static int hydra_thinints;
+static int omit_svs;
 
 static int indicator_used[INDICATORS_PER_CACHELINE];
 static __u32 * volatile indicators;
@@ -114,7 +115,7 @@ qdio_min(int a,int b)
 static inline volatile __u64 
 qdio_get_micros(void)
 {
-        return (get_clock() >> 12); /* time>>12 is microseconds */
+        return (get_clock() >> 10); /* time>>12 is microseconds */
 }
 
 /* 
@@ -530,7 +531,6 @@ qdio_has_outbound_q_moved(struct qdio_q 
 	if ( (i!=GET_SAVED_FRONTIER(q)) ||
 	     (q->error_status_flags&QDIO_STATUS_LOOK_FOR_ERROR) ) {
 		SAVE_FRONTIER(q,i);
-		SAVE_TIMESTAMP(q);
 		QDIO_DBF_TEXT4(0,trace,"oqhasmvd");
 		QDIO_DBF_HEX4(0,trace,&q,sizeof(void*));
 		return 1;
@@ -596,8 +596,8 @@ qdio_kick_outbound_handler(struct qdio_q
 	q->error_status_flags=0;
 }
 
-static void
-qdio_outbound_processing(struct qdio_q *q)
+static inline void
+__qdio_outbound_processing(struct qdio_q *q)
 {
 	QDIO_DBF_TEXT4(0,trace,"qoutproc");
 	QDIO_DBF_HEX4(0,trace,&q,sizeof(void*));
@@ -639,6 +639,12 @@ qdio_outbound_processing(struct qdio_q *
 	qdio_release_q(q);
 }
 
+static void
+qdio_outbound_processing(struct qdio_q *q)
+{
+	__qdio_outbound_processing(q);
+}
+
 /************************* INBOUND ROUTINES *******************************/
 
 
@@ -997,7 +1003,7 @@ __tiqdio_inbound_processing(struct qdio_
 			perf_stats.tl_runs--;
 #endif /* QDIO_PERFORMANCE_STATS */
 			if (!qdio_is_outbound_q_done(oq))
-				qdio_outbound_processing(oq);
+				__qdio_outbound_processing(oq);
 		}
 	}
 
@@ -1024,8 +1030,8 @@ tiqdio_inbound_processing(struct qdio_q 
 	__tiqdio_inbound_processing(q, atomic_read(&spare_indicator_usecount));
 }
 
-static void
-qdio_inbound_processing(struct qdio_q *q)
+static inline void
+__qdio_inbound_processing(struct qdio_q *q)
 {
 	int q_laps=0;
 
@@ -1067,6 +1073,12 @@ again:
 	qdio_release_q(q);
 }
 
+static void
+qdio_inbound_processing(struct qdio_q *q)
+{
+	__qdio_inbound_processing(q);
+}
+
 /************************* MAIN ROUTINES *******************************/
 
 #ifdef QDIO_USE_PROCESSING_STATE
@@ -1211,8 +1223,7 @@ next:
 		kfree(irq_ptr->output_qs[i]);
 
 	}
-	if (irq_ptr->qdr)
-		kfree(irq_ptr->qdr);
+	kfree(irq_ptr->qdr);
 	kfree(irq_ptr);
 }
 
@@ -1493,8 +1504,11 @@ tiqdio_thinint_handler(void)
 	perf_stats.thinints++;
 	perf_stats.start_time_inbound=NOW;
 #endif /* QDIO_PERFORMANCE_STATS */
-	/* VM will do the SVS for us */
-	if (!MACHINE_IS_VM)
+
+	/* SVS only when needed:
+	 * issue SVS to benefit from iqdio interrupt avoidance
+	 * (SVS clears AISOI)*/
+	if (!omit_svs)
 		tiqdio_clear_global_summary();
 
 	tiqdio_inbound_checks();
@@ -1554,7 +1568,7 @@ qdio_handle_pci(struct qdio_irq *irq_ptr
 #ifdef QDIO_PERFORMANCE_STATS
 			perf_stats.tl_runs--;
 #endif /* QDIO_PERFORMANCE_STATS */
-			qdio_inbound_processing(q);
+			__qdio_inbound_processing(q);
 		}
 	}
 	if (!irq_ptr->hydra_gives_outbound_pcis)
@@ -1568,7 +1582,7 @@ qdio_handle_pci(struct qdio_irq *irq_ptr
 			continue;
 		if (!irq_ptr->sync_done_on_outb_pcis)
 			SYNC_MEMORY;
-		qdio_outbound_processing(q);
+		__qdio_outbound_processing(q);
 	}
 }
 
@@ -1700,7 +1714,6 @@ qdio_handler(struct ccw_device *cdev, un
 		case -EIO:
 			QDIO_PRINT_ERR("i/o error on device %s\n",
 				       cdev->dev.bus_id);
-			//FIXME: hm?
 			return;
 		case -ETIMEDOUT:
 			qdio_timeout_handler(cdev);
@@ -1817,12 +1830,13 @@ qdio_check_siga_needs(int sch)
 		u8  ocnt;
 	} *ssqd_area;
 
-	/* FIXME make this GFP_KERNEL */
-	ssqd_area = (void *)get_zeroed_page(GFP_ATOMIC | GFP_DMA);
+	ssqd_area = (void *)get_zeroed_page(GFP_KERNEL | GFP_DMA);
 	if (!ssqd_area) {
 	        QDIO_PRINT_WARN("Could not get memory for chsc. Using all " \
 				"SIGAs for sch x%x.\n", sch);
-		return -1; /* all flags set */
+		return CHSC_FLAG_SIGA_INPUT_NECESSARY ||
+			CHSC_FLAG_SIGA_OUTPUT_NECESSARY ||
+			CHSC_FLAG_SIGA_SYNC_NECESSARY; /* all flags set */
 	}
 	ssqd_area->request = (struct chsc_header) {
 		.length = 0x0010,
@@ -1838,7 +1852,9 @@ qdio_check_siga_needs(int sch)
 		QDIO_PRINT_WARN("CHSC returned cc %i. Using all " \
 				"SIGAs for sch x%x.\n",
 				result,sch);
-		qdioac = -1; /* all flags set */
+		qdioac = CHSC_FLAG_SIGA_INPUT_NECESSARY ||
+			CHSC_FLAG_SIGA_OUTPUT_NECESSARY ||
+			CHSC_FLAG_SIGA_SYNC_NECESSARY; /* all flags set */
 		goto out;
 	}
 
@@ -1846,7 +1862,9 @@ qdio_check_siga_needs(int sch)
 		QDIO_PRINT_WARN("response upon checking SIGA needs " \
 				"is 0x%x. Using all SIGAs for sch x%x.\n",
 				ssqd_area->response.code, sch);
-		qdioac = -1; /* all flags set */
+		qdioac = CHSC_FLAG_SIGA_INPUT_NECESSARY ||
+			CHSC_FLAG_SIGA_OUTPUT_NECESSARY ||
+			CHSC_FLAG_SIGA_SYNC_NECESSARY; /* all flags set */
 		goto out;
 	}
 	if (!(ssqd_area->flags & CHSC_FLAG_QDIO_CAPABILITY) ||
@@ -1930,6 +1948,13 @@ tiqdio_check_chsc_availability(void)
 		== 0x10000000);
 	sprintf(dbf_text,"hydrati%1x", hydra_thinints);
 	QDIO_DBF_TEXT0(0,setup,dbf_text);
+
+	/* Check for aif time delay disablement fac (bit 56). If installed,
+	 * omit svs even under lpar (good point by rick again) */
+	omit_svs = ((scsc_area->general_char[1] & 0x00000080)
+		== 0x00000080);
+	sprintf(dbf_text,"omitsvs%1x", omit_svs);
+	QDIO_DBF_TEXT0(0,setup,dbf_text);
 exit:
 	free_page ((unsigned long) scsc_area);
 	return result;
@@ -2122,7 +2147,7 @@ qdio_shutdown(struct ccw_device *cdev, i
 	int result = 0;
 	unsigned long flags;
 	int timeout;
-	char dbf_text[15]="12345678";
+	char dbf_text[15];
 
 	irq_ptr = cdev->private->qdio_data;
 	if (!irq_ptr)
@@ -2152,13 +2177,6 @@ qdio_shutdown(struct ccw_device *cdev, i
 							      use_count),
 						 QDIO_NO_USE_COUNT_TIMEOUT);
 		if (atomic_read(&irq_ptr->input_qs[i]->use_count))
-			/*
-			 * FIXME:
-			 * nobody cares about such retval,
-			 * does a timeout make sense at all?
-			 * can this case be eliminated?
-			 * mutex should be released anyway, shouldn't it?
-			 */ 
 			result=-EINPROGRESS;
 	}
 
@@ -2170,13 +2188,6 @@ qdio_shutdown(struct ccw_device *cdev, i
 							      use_count),
 						 QDIO_NO_USE_COUNT_TIMEOUT);
 		if (atomic_read(&irq_ptr->output_qs[i]->use_count))
-			/*
-			 * FIXME:
-			 * nobody cares about such retval,
-			 * does a timeout make sense at all?
-			 * can this case be eliminated?
-			 * mutex should be released anyway, shouldn't it?
-			 */ 
 			result=-EINPROGRESS;
 	}
 
@@ -2260,11 +2271,10 @@ qdio_free(struct ccw_device *cdev)
 static inline void
 qdio_allocate_do_dbf(struct qdio_initialize *init_data)
 {
-	char dbf_text[20]; /* if a printf would print out more than 8 chars */
+	char dbf_text[20]; /* if a printf printed out more than 8 chars */
 
 	sprintf(dbf_text,"qfmt:%x",init_data->q_format);
 	QDIO_DBF_TEXT0(0,setup,dbf_text);
-	QDIO_DBF_TEXT0(0,setup,init_data->adapter_name);
 	QDIO_DBF_HEX0(0,setup,init_data->adapter_name,8);
 	sprintf(dbf_text,"qpff%4x",init_data->qib_param_field_format);
 	QDIO_DBF_TEXT0(0,setup,dbf_text);
@@ -2510,7 +2520,6 @@ qdio_allocate(struct qdio_initialize *in
 
 	irq_ptr->qdr=kmalloc(sizeof(struct qdr), GFP_KERNEL | GFP_DMA);
   	if (!(irq_ptr->qdr)) {
-   		kfree(irq_ptr->qdr);
    		kfree(irq_ptr);
     		QDIO_PRINT_ERR("kmalloc of irq_ptr->qdr failed!\n");
 		return -ENOMEM;
@@ -2660,8 +2669,6 @@ int qdio_fill_irq(struct qdio_initialize
 	irq_ptr->original_int_handler = init_data->cdev->handler;
 	init_data->cdev->handler = qdio_handler;
 
-	up(&irq_ptr->setting_up_sema);
-
 	return 0;
 }
 
@@ -2692,7 +2699,7 @@ qdio_establish(struct qdio_initialize *i
 		result = tiqdio_set_subchannel_ind(irq_ptr,0);
 		if (result) {
 			up(&irq_ptr->setting_up_sema);
-			qdio_cleanup(cdev, QDIO_FLAG_CLEANUP_USING_CLEAR);
+			qdio_shutdown(cdev, QDIO_FLAG_CLEANUP_USING_CLEAR);
 			return result;
 		}
 		tiqdio_set_delay_target(irq_ptr,TIQDIO_DELAY_TARGET);
@@ -2740,23 +2747,23 @@ qdio_establish(struct qdio_initialize *i
 		return result;
 	}
 	
-	/* FIXME: don't wait forever if hardware is broken */
-	wait_event(cdev->private->wait_q,
-		   irq_ptr->state == QDIO_IRQ_STATE_ESTABLISHED ||
-		   irq_ptr->state == QDIO_IRQ_STATE_ERR);
+	wait_event_interruptible_timeout(cdev->private->wait_q,
+		 irq_ptr->state == QDIO_IRQ_STATE_ESTABLISHED ||
+		 irq_ptr->state == QDIO_IRQ_STATE_ERR,
+		 QDIO_ESTABLISH_TIMEOUT);
 
 	if (irq_ptr->state == QDIO_IRQ_STATE_ESTABLISHED)
 		result = 0;
 	else {
+		up(&irq_ptr->setting_up_sema);
 		qdio_shutdown(cdev, QDIO_FLAG_CLEANUP_USING_CLEAR);
-		result = -EIO;
+		return -EIO;
 	}
 
-	if (MACHINE_IS_VM)
-		irq_ptr->qdioac=qdio_check_siga_needs(irq_ptr->irq);
-	else
-                irq_ptr->qdioac=CHSC_FLAG_SIGA_INPUT_NECESSARY
-                        | CHSC_FLAG_SIGA_OUTPUT_NECESSARY;
+	irq_ptr->qdioac=qdio_check_siga_needs(irq_ptr->irq);
+	/* if this gets set once, we're running under VM and can omit SVSes */
+	if (irq_ptr->qdioac&CHSC_FLAG_SIGA_SYNC_NECESSARY)
+		omit_svs=1;
 
 	sprintf(dbf_text,"qdioac%2x",irq_ptr->qdioac);
 	QDIO_DBF_TEXT2(0,setup,dbf_text);
@@ -2864,7 +2871,9 @@ qdio_activate(struct ccw_device *cdev, i
 	switch (irq_ptr->state) {
 	case QDIO_IRQ_STATE_STOPPED:
 	case QDIO_IRQ_STATE_ERR:
+		up(&irq_ptr->setting_up_sema);
 		qdio_shutdown(cdev, QDIO_FLAG_CLEANUP_USING_CLEAR);
+		down(&irq_ptr->setting_up_sema);
 		result = -EIO;
 		break;
 	default:
@@ -2878,7 +2887,7 @@ qdio_activate(struct ccw_device *cdev, i
 }
 
 /* buffers filled forwards again to make Rick happy */
-static void
+static inline void
 qdio_do_qdio_fill_input(struct qdio_q *q, unsigned int qidx,
 			unsigned int count, struct qdio_buffer *buffers)
 {
@@ -2972,7 +2981,7 @@ do_qdio_handle_outbound(struct qdio_q *q
 		while (count--)
 			qdio_kick_outbound_q(q);
 			
-		qdio_outbound_processing(q);
+		__qdio_outbound_processing(q);
 	} else {
 		/* under VM, we do a SIGA sync unconditionally */
 		SYNC_MEMORY;
@@ -2998,7 +3007,7 @@ do_qdio_handle_outbound(struct qdio_q *q
 		 * the upper layer module could do a lot of
 		 * traffic in that time 
 		 */
-		qdio_outbound_processing(q);
+		__qdio_outbound_processing(q);
 	}
 
 #ifdef QDIO_PERFORMANCE_STATS
--- diff/drivers/s390/net/Kconfig	2003-09-30 15:46:16.000000000 +0100
+++ source/drivers/s390/net/Kconfig	2004-02-23 13:56:45.000000000 +0000
@@ -23,12 +23,32 @@ config CTC
 	  called ctc.ko.  If you do not know what it is, it's safe to say "Y".
 
 config IUCV
-	tristate "IUCV device support (VM only)"
-	depends on NETDEVICES
+	tristate "IUCV support (VM only)"
 	help
 	  Select this option if you want to use inter-user communication
-	  vehicle networking under VM or VIF.  This option is also available
-	  as a module which will be called iucv.ko. If unsure, say "Y".
+	  under VM or VIF. If unsure, say "Y" to enable a fast communication
+	  link between VM guests. At boot time the user ID of the guest needs
+	  to be passed to the kernel. Note that both kernels need to be
+	  compiled with this option and both need to be booted with the user ID
+	  of the other VM guest.
+
+config NETIUCV
+	tristate "IUCV network device support (VM only)"
+	depends on IUCV && NETDEVICES
+	help
+	  Select this option if you want to use inter-user communication
+	  vehicle networking under VM or VIF. It enables a fast communication
+	  link between VM guests. Using ifconfig a point-to-point connection
+	  can be established to the Linux for zSeries and S7390 system
+	  running on the other VM guest. This option is also available
+	  as a module which will be called netiucv.ko. If unsure, say "Y".
+
+config SMSGIUCV
+	tristate "IUCV special message support (VM only)"
+	depends on IUCV
+	help
+	  Select this option if you want to be able to receive SMSG messages
+	  from other VM guest systems.
 
 
 config QETH
--- diff/drivers/s390/net/Makefile	2003-07-08 09:55:18.000000000 +0100
+++ source/drivers/s390/net/Makefile	2004-02-23 13:56:45.000000000 +0000
@@ -4,9 +4,10 @@
 
 ctc-objs := ctcmain.o ctctty.o
 
-obj-$(CONFIG_IUCV) += iucv.o fsm.o
+obj-$(CONFIG_IUCV) += iucv.o
+obj-$(CONFIG_NETIUCV) += netiucv.o fsm.o
+obj-$(CONFIG_SMSGIUCV) += smsgiucv.o
 obj-$(CONFIG_CTC) += ctc.o fsm.o cu3088.o
-obj-$(CONFIG_IUCV) += netiucv.o
 obj-$(CONFIG_LCS) += lcs.o cu3088.o
 qeth_mod-objs := qeth.o qeth_mpc.o
 obj-$(CONFIG_QETH) += qeth_mod.o
--- diff/drivers/s390/net/ctcmain.c	2004-02-09 10:36:11.000000000 +0000
+++ source/drivers/s390/net/ctcmain.c	2004-02-23 13:56:45.000000000 +0000
@@ -1,5 +1,5 @@
 /*
- * $Id: ctcmain.c,v 1.50 2003/12/02 15:18:50 cohuck Exp $
+ * $Id: ctcmain.c,v 1.54 2004/02/18 12:35:59 ptiedem Exp $
  *
  * CTC / ESCON network driver
  *
@@ -36,7 +36,7 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
- * RELEASE-TAG: CTC/ESCON network driver $Revision: 1.50 $
+ * RELEASE-TAG: CTC/ESCON network driver $Revision: 1.54 $
  *
  */
 
@@ -204,15 +204,60 @@ struct channel {
 	struct ctc_profile prof;
 
 	unsigned char *trans_skb_data;
+
+	__u16 logflags;
 };
 
 #define CHANNEL_FLAGS_READ            0
 #define CHANNEL_FLAGS_WRITE           1
 #define CHANNEL_FLAGS_INUSE           2
 #define CHANNEL_FLAGS_BUFSIZE_CHANGED 4
+#define CHANNEL_FLAGS_FAILED          8
+#define CHANNEL_FLAGS_WAITIRQ        16
 #define CHANNEL_FLAGS_RWMASK 1
 #define CHANNEL_DIRECTION(f) (f & CHANNEL_FLAGS_RWMASK)
 
+#define LOG_FLAG_ILLEGALPKT  1
+#define LOG_FLAG_ILLEGALSIZE 2
+#define LOG_FLAG_OVERRUN     4
+#define LOG_FLAG_NOMEM       8
+
+#define CTC_LOGLEVEL_INFO     1
+#define CTC_LOGLEVEL_NOTICE   2
+#define CTC_LOGLEVEL_WARN     4
+#define CTC_LOGLEVEL_EMERG    8
+#define CTC_LOGLEVEL_ERR     16
+#define CTC_LOGLEVEL_DEBUG   32
+#define CTC_LOGLEVEL_CRIT    64
+
+#define CTC_LOGLEVEL_DEFAULT \
+(CTC_LOGLEVEL_INFO | CTC_LOGLEVEL_NOTICE | CTC_LOGLEVEL_WARN | CTC_LOGLEVEL_CRIT)
+
+#define CTC_LOGLEVEL_MAX     ((CTC_LOGLEVEL_CRIT<<1)-1)
+
+static int loglevel = CTC_LOGLEVEL_DEFAULT;
+
+#define ctc_pr_debug(fmt, arg...) \
+do { if (loglevel & CTC_LOGLEVEL_DEBUG) printk(KERN_DEBUG fmt,##arg); } while (0)
+
+#define ctc_pr_info(fmt, arg...) \
+do { if (loglevel & CTC_LOGLEVEL_INFO) printk(KERN_INFO fmt,##arg); } while (0)
+
+#define ctc_pr_notice(fmt, arg...) \
+do { if (loglevel & CTC_LOGLEVEL_NOTICE) printk(KERN_NOTICE fmt,##arg); } while (0)
+
+#define ctc_pr_warn(fmt, arg...) \
+do { if (loglevel & CTC_LOGLEVEL_WARN) printk(KERN_WARNING fmt,##arg); } while (0)
+
+#define ctc_pr_emerg(fmt, arg...) \
+do { if (loglevel & CTC_LOGLEVEL_EMERG) printk(KERN_EMERG fmt,##arg); } while (0)
+
+#define ctc_pr_err(fmt, arg...) \
+do { if (loglevel & CTC_LOGLEVEL_ERR) printk(KERN_ERR fmt,##arg); } while (0)
+
+#define ctc_pr_crit(fmt, arg...) \
+do { if (loglevel & CTC_LOGLEVEL_CRIT) printk(KERN_CRIT fmt,##arg); } while (0)
+
 /**
  * Linked list of all detected channels.
  */
@@ -255,13 +300,15 @@ static __inline__ void
 ctc_clear_busy(struct net_device * dev)
 {
 	clear_bit(0, &(((struct ctc_priv *) dev->priv)->tbusy));
-	netif_wake_queue(dev);
+	if (((struct ctc_priv *)dev->priv)->protocol != CTC_PROTO_LINUX_TTY)
+		netif_wake_queue(dev);
 }
 
 static __inline__ int
 ctc_test_and_set_busy(struct net_device * dev)
 {
-	netif_stop_queue(dev);
+	if (((struct ctc_priv *)dev->priv)->protocol != CTC_PROTO_LINUX_TTY)
+		netif_stop_queue(dev);
 	return test_and_set_bit(0, &((struct ctc_priv *) dev->priv)->tbusy);
 }
 
@@ -272,7 +319,7 @@ static void
 print_banner(void)
 {
 	static int printed = 0;
-	char vbuf[] = "$Revision: 1.50 $";
+	char vbuf[] = "$Revision: 1.54 $";
 	char *version = vbuf;
 
 	if (printed)
@@ -285,9 +332,9 @@ print_banner(void)
 		version = " ??? ";
 	printk(KERN_INFO "CTC driver Version%s"
 #ifdef DEBUG
-	       " (DEBUG-VERSION, " __DATE__ __TIME__ ")"
+		    " (DEBUG-VERSION, " __DATE__ __TIME__ ")"
 #endif
-	       " initialized\n", version);
+		    " initialized\n", version);
 	printed = 1;
 }
 
@@ -426,11 +473,11 @@ enum ch_events {
 };
 
 static const char *ch_event_names[] = {
-	"do_IO success",
-	"do_IO busy",
-	"do_IO enodev",
-	"do_IO ioerr",
-	"do_IO unknown",
+	"ccw_device success",
+	"ccw_device busy",
+	"ccw_device enodev",
+	"ccw_device ioerr",
+	"ccw_device unknown",
 
 	"Status ATTN & BUSY",
 	"Status ATTN",
@@ -528,6 +575,8 @@ ctc_dump_skb(struct sk_buff *skb, int of
 	struct ll_header *header;
 	int i;
 
+	if (!(loglevel & CTC_LOGLEVEL_DEBUG))
+		return;
 	p += offset;
 	bl = *((__u16 *) p);
 	p += 2;
@@ -580,53 +629,88 @@ ctc_unpack_skb(struct channel *ch, struc
 		skb_pull(pskb, LL_HEADER_LENGTH);
 		if ((ch->protocol == CTC_PROTO_S390) &&
 		    (header->type != ETH_P_IP)) {
-			/**
-			 * Check packet type only if we stick strictly
-			 * to S/390's protocol of OS390. This only
-			 * supports IP. Otherwise allow any packet
-			 * type.
-			 */
-			printk(KERN_WARNING
-			       "%s Illegal packet type 0x%04x "
-			       "received, dropping\n", dev->name, header->type);
+
+#ifndef DEBUG
+		        if (!(ch->logflags & LOG_FLAG_ILLEGALPKT)) {
+#endif
+				/**
+				 * Check packet type only if we stick strictly
+				 * to S/390's protocol of OS390. This only
+				 * supports IP. Otherwise allow any packet
+				 * type.
+				 */
+				ctc_pr_warn(
+					"%s Illegal packet type 0x%04x received, dropping\n",
+					dev->name, header->type);
+				ch->logflags |= LOG_FLAG_ILLEGALPKT;
+#ifndef DEBUG
+			}
+#endif
+#ifdef DEBUG
 			ctc_dump_skb(pskb, -6);
+#endif
 			privptr->stats.rx_dropped++;
 			privptr->stats.rx_frame_errors++;
 			return;
 		}
 		pskb->protocol = ntohs(header->type);
-		header->length -= LL_HEADER_LENGTH;
-		if ((header->length == 0) ||
-		    (header->length > skb_tailroom(pskb)) ||
-		    (header->length > len)) {
-			printk(KERN_WARNING
-			       "%s Illegal packet size %d "
-			       "received (MTU=%d blocklen=%d), "
-			       "dropping\n", dev->name, header->length,
-			       dev->mtu, len);
+		if (header->length <= LL_HEADER_LENGTH) {
+#ifndef DEBUG
+		        if (!(ch->logflags & LOG_FLAG_ILLEGALSIZE)) {
+#endif
+				ctc_pr_warn(
+				       "%s Illegal packet size %d "
+				       "received (MTU=%d blocklen=%d), "
+				       "dropping\n", dev->name, header->length,
+				       dev->mtu, len);
+				ch->logflags |= LOG_FLAG_ILLEGALSIZE;
+#ifndef DEBUG
+			}
+#endif
+#ifdef DEBUG
 			ctc_dump_skb(pskb, -6);
+#endif
 			privptr->stats.rx_dropped++;
 			privptr->stats.rx_length_errors++;
 			return;
 		}
-		if (header->length > skb_tailroom(pskb)) {
-			printk(KERN_WARNING
-			       "%s Illegal packet size %d "
-			       "(beyond the end of received data), "
-			       "dropping\n", dev->name, header->length);
+		header->length -= LL_HEADER_LENGTH;
+		len -= LL_HEADER_LENGTH;
+		if ((header->length > skb_tailroom(pskb)) ||
+		    (header->length > len)) {
+#ifndef DEBUG
+		        if (!(ch->logflags & LOG_FLAG_OVERRUN)) {
+#endif
+				ctc_pr_warn(
+					"%s Illegal packet size %d "
+					"(beyond the end of received data), "
+					"dropping\n", dev->name, header->length);
+				ch->logflags |= LOG_FLAG_OVERRUN;
+#ifndef DEBUG
+			}
+#endif
+#ifdef DEBUG
 			ctc_dump_skb(pskb, -6);
+#endif
 			privptr->stats.rx_dropped++;
 			privptr->stats.rx_length_errors++;
 			return;
 		}
 		skb_put(pskb, header->length);
 		pskb->mac.raw = pskb->data;
-		len -= (LL_HEADER_LENGTH + header->length);
+		len -= header->length;
 		skb = dev_alloc_skb(pskb->len);
 		if (!skb) {
-			printk(KERN_WARNING
-			       "%s Out of memory in ctc_unpack_skb\n",
-			       dev->name);
+#ifndef DEBUG
+		        if (!(ch->logflags & LOG_FLAG_NOMEM)) {
+#endif
+				ctc_pr_warn(
+					"%s Out of memory in ctc_unpack_skb\n",
+					dev->name);
+				ch->logflags |= LOG_FLAG_NOMEM;
+#ifndef DEBUG
+			}
+#endif
 			privptr->stats.rx_dropped++;
 			return;
 		}
@@ -639,47 +723,64 @@ ctc_unpack_skb(struct channel *ch, struc
 			ctc_tty_netif_rx(skb);
 		else
 			netif_rx(skb);
+		/**
+		 * Successful rx; reset logflags
+		 */
+		ch->logflags = 0;
 		dev->last_rx = jiffies;
 		privptr->stats.rx_packets++;
 		privptr->stats.rx_bytes += skb->len;
 		if (len > 0) {
 			skb_pull(pskb, header->length);
+			if (skb_tailroom(pskb) < LL_HEADER_LENGTH) {
+#ifndef DEBUG
+				if (!(ch->logflags & LOG_FLAG_OVERRUN)) {
+#endif
+					ctc_pr_warn(
+						"%s Overrun in ctc_unpack_skb\n",
+						dev->name);
+					ch->logflags |= LOG_FLAG_OVERRUN;
+#ifndef DEBUG
+				}
+#endif
+				return;
+			}
 			skb_put(pskb, LL_HEADER_LENGTH);
 		}
 	}
 }
 
 /**
- * Check return code of a preceeding do_IO, halt_IO etc...
+ * Check return code of a preceeding ccw_device call, halt_IO etc...
  *
  * @param ch          The channel, the error belongs to.
  * @param return_code The error code to inspect.
  */
 static void inline
-ccw_check_return_code(struct channel *ch, int return_code)
+ccw_check_return_code(struct channel *ch, int return_code, char *msg)
 {
 	switch (return_code) {
-	case 0:
-		fsm_event(ch->fsm, CH_EVENT_IO_SUCCESS, ch);
-		break;
-	case -EBUSY:
-		printk(KERN_INFO "%s: Busy !\n", ch->id);
-		fsm_event(ch->fsm, CH_EVENT_IO_EBUSY, ch);
-		break;
-	case -ENODEV:
-		printk(KERN_EMERG
-		       "%s: Invalid device called for IO\n", ch->id);
-		fsm_event(ch->fsm, CH_EVENT_IO_ENODEV, ch);
-		break;
-	case -EIO:
-		printk(KERN_EMERG "%s: Status pending... \n", ch->id);
-		fsm_event(ch->fsm, CH_EVENT_IO_EIO, ch);
-		break;
-	default:
-		printk(KERN_EMERG
-		       "%s: Unknown error in do_IO %04x\n",
-		       ch->id, return_code);
-		fsm_event(ch->fsm, CH_EVENT_IO_UNKNOWN, ch);
+		case 0:
+			fsm_event(ch->fsm, CH_EVENT_IO_SUCCESS, ch);
+			break;
+		case -EBUSY:
+			ctc_pr_warn("%s (%s): Busy !\n", ch->id, msg);
+			fsm_event(ch->fsm, CH_EVENT_IO_EBUSY, ch);
+			break;
+		case -ENODEV:
+			ctc_pr_emerg("%s (%s): Invalid device called for IO\n",
+				     ch->id, msg);
+			fsm_event(ch->fsm, CH_EVENT_IO_ENODEV, ch);
+			break;
+		case -EIO:
+			ctc_pr_emerg("%s (%s): Status pending... \n",
+				     ch->id, msg);
+			fsm_event(ch->fsm, CH_EVENT_IO_EIO, ch);
+			break;
+		default:
+			ctc_pr_emerg("%s (%s): Unknown error in do_IO %04x\n",
+				     ch->id, msg, return_code);
+			fsm_event(ch->fsm, CH_EVENT_IO_UNKNOWN, ch);
 	}
 }
 
@@ -695,47 +796,39 @@ ccw_unit_check(struct channel *ch, unsig
 	if (sense & SNS0_INTERVENTION_REQ) {
 		if (sense & 0x01) {
 			if (ch->protocol != CTC_PROTO_LINUX_TTY)
-				printk(KERN_DEBUG
-				       "%s: Interface disc. or Sel. reset "
-				       "(remote)\n", ch->id);
+				ctc_pr_debug("%s: Interface disc. or Sel. reset "
+					"(remote)\n", ch->id);
 			fsm_event(ch->fsm, CH_EVENT_UC_RCRESET, ch);
 		} else {
-			printk(KERN_DEBUG "%s: System reset (remote)\n",
-			       ch->id);
+			ctc_pr_debug("%s: System reset (remote)\n", ch->id);
 			fsm_event(ch->fsm, CH_EVENT_UC_RSRESET, ch);
 		}
 	} else if (sense & SNS0_EQUIPMENT_CHECK) {
 		if (sense & SNS0_BUS_OUT_CHECK) {
-			printk(KERN_WARNING
-			       "%s: Hardware malfunction (remote)\n",
-			       ch->id);
+			ctc_pr_warn("%s: Hardware malfunction (remote)\n",
+				    ch->id);
 			fsm_event(ch->fsm, CH_EVENT_UC_HWFAIL, ch);
 		} else {
-			printk(KERN_WARNING
-			       "%s: Read-data parity error (remote)\n",
-			       ch->id);
+			ctc_pr_warn("%s: Read-data parity error (remote)\n",
+				    ch->id);
 			fsm_event(ch->fsm, CH_EVENT_UC_RXPARITY, ch);
 		}
 	} else if (sense & SNS0_BUS_OUT_CHECK) {
 		if (sense & 0x04) {
-			printk(KERN_WARNING
-			       "%s: Data-streaming timeout)\n", ch->id);
+			ctc_pr_warn("%s: Data-streaming timeout)\n", ch->id);
 			fsm_event(ch->fsm, CH_EVENT_UC_TXTIMEOUT, ch);
 		} else {
-			printk(KERN_WARNING
-			       "%s: Data-transfer parity error\n",
-			       ch->id);
+			ctc_pr_warn("%s: Data-transfer parity error\n", ch->id);
 			fsm_event(ch->fsm, CH_EVENT_UC_TXPARITY, ch);
 		}
 	} else if (sense & SNS0_CMD_REJECT) {
-		printk(KERN_WARNING "%s: Command reject\n", ch->id);
+		ctc_pr_warn("%s: Command reject\n", ch->id);
 	} else if (sense == 0) {
-		printk(KERN_DEBUG "%s: Unit check ZERO\n", ch->id);
+		ctc_pr_debug("%s: Unit check ZERO\n", ch->id);
 		fsm_event(ch->fsm, CH_EVENT_UC_ZERO, ch);
 	} else {
-		printk(KERN_WARNING
-		       "%s: Unit Check with sense code: %02x\n",
-		       ch->id, sense);
+		ctc_pr_warn("%s: Unit Check with sense code: %02x\n",
+			    ch->id, sense);
 		fsm_event(ch->fsm, CH_EVENT_UC_UNKNOWN, ch);
 	}
 }
@@ -763,11 +856,11 @@ ctc_checkalloc_buffer(struct channel *ch
 						GFP_ATOMIC | GFP_DMA);
 		if (ch->trans_skb == NULL) {
 			if (warn)
-				printk(KERN_WARNING
-				       "%s: Couldn't alloc %s trans_skb\n",
-				       ch->id,
-				       (CHANNEL_DIRECTION(ch->flags) == READ) ?
-				       "RX" : "TX");
+				ctc_pr_warn(
+					"%s: Couldn't alloc %s trans_skb\n",
+					ch->id,
+					(CHANNEL_DIRECTION(ch->flags) == READ) ?
+					"RX" : "TX");
 			return -ENOMEM;
 		}
 		ch->ccw[1].count = ch->max_bufsize;
@@ -775,12 +868,12 @@ ctc_checkalloc_buffer(struct channel *ch
 			dev_kfree_skb(ch->trans_skb);
 			ch->trans_skb = NULL;
 			if (warn)
-				printk(KERN_WARNING
-				       "%s: set_normalized_cda for %s "
-				       "trans_skb failed, dropping packets\n",
-				       ch->id,
-				       (CHANNEL_DIRECTION(ch->flags) == READ) ?
-				       "RX" : "TX");
+				ctc_pr_warn(
+					"%s: set_normalized_cda for %s "
+					"trans_skb failed, dropping packets\n",
+					ch->id,
+					(CHANNEL_DIRECTION(ch->flags) == READ) ?
+					"RX" : "TX");
 			return -ENOMEM;
 		}
 		ch->ccw[1].count = 0;
@@ -829,9 +922,8 @@ ch_action_txdone(fsm_instance * fi, int 
 		ch->prof.tx_time = duration;
 
 	if (ch->irb->scsw.count != 0)
-		printk(KERN_DEBUG "%s: TX not complete, remaining %d bytes\n",
-		       dev->name, ch->irb->scsw.count);
-
+		ctc_pr_debug("%s: TX not complete, remaining %d bytes\n",
+			     dev->name, ch->irb->scsw.count);
 	fsm_deltimer(&ch->timer);
 	while ((skb = skb_dequeue(&ch->io_queue))) {
 		privptr->stats.tx_packets++;
@@ -881,7 +973,7 @@ ch_action_txdone(fsm_instance * fi, int 
 			privptr->stats.tx_dropped += i;
 			privptr->stats.tx_errors += i;
 			fsm_deltimer(&ch->timer);
-			ccw_check_return_code(ch, rc);
+			ccw_check_return_code(ch, rc, "chained TX");
 		}
 	} else {
 		spin_unlock(&ch->collect_lock);
@@ -932,15 +1024,15 @@ ch_action_rx(fsm_instance * fi, int even
 
 	fsm_deltimer(&ch->timer);
 	if (len < 8) {
-		printk(KERN_DEBUG "%s: got packet with length %d < 8\n",
-		       dev->name, len);
+		ctc_pr_debug("%s: got packet with length %d < 8\n",
+			     dev->name, len);
 		privptr->stats.rx_dropped++;
 		privptr->stats.rx_length_errors++;
 		goto again;
 	}
 	if (len > ch->max_bufsize) {
-		printk(KERN_DEBUG "%s: got packet with length %d > %d\n",
-		       dev->name, len, ch->max_bufsize);
+		ctc_pr_debug("%s: got packet with length %d > %d\n",
+			     dev->name, len, ch->max_bufsize);
 		privptr->stats.rx_dropped++;
 		privptr->stats.rx_length_errors++;
 		goto again;
@@ -950,18 +1042,20 @@ ch_action_rx(fsm_instance * fi, int even
 	 * VM TCP seems to have a bug sending 2 trailing bytes of garbage.
 	 */
 	switch (ch->protocol) {
-	case CTC_PROTO_S390:
-	case CTC_PROTO_OS390:
-		check_len = block_len + 2;
-		break;
-	default:
-		check_len = block_len;
-		break;
+		case CTC_PROTO_S390:
+		case CTC_PROTO_OS390:
+			check_len = block_len + 2;
+			break;
+		default:
+			check_len = block_len;
+			break;
 	}
 	if ((len < block_len) || (len > check_len)) {
-		printk(KERN_DEBUG "%s: got block length %d != rx length %d\n",
-		       dev->name, block_len, len);
+		ctc_pr_debug("%s: got block length %d != rx length %d\n",
+			     dev->name, block_len, len);
+#ifdef DEBUG
 		ctc_dump_skb(skb, 0);
+#endif
 		*((__u16 *) skb->data) = len;
 		privptr->stats.rx_dropped++;
 		privptr->stats.rx_length_errors++;
@@ -972,7 +1066,7 @@ ch_action_rx(fsm_instance * fi, int even
 		*((__u16 *) skb->data) = block_len;
 		ctc_unpack_skb(ch, skb);
 	}
-      again:
+ again:
 	skb->data = skb->tail = ch->trans_skb_data;
 	skb->len = 0;
 	if (ctc_checkalloc_buffer(ch, 1))
@@ -980,7 +1074,7 @@ ch_action_rx(fsm_instance * fi, int even
 	ch->ccw[1].count = ch->max_bufsize;
 	rc = ccw_device_start(ch->cdev, &ch->ccw[0], (unsigned long) ch, 0xff, 0);
 	if (rc != 0)
-		ccw_check_return_code(ch, rc);
+		ccw_check_return_code(ch, rc, "normal RX");
 }
 
 static void ch_action_rxidle(fsm_instance * fi, int event, void *arg);
@@ -999,8 +1093,7 @@ ch_action_firstio(fsm_instance * fi, int
 	int rc;
 
 	if (fsm_getstate(fi) == CH_STATE_TXIDLE)
-		printk(KERN_DEBUG "%s: remote side issued READ?, "
-		       "init ...\n", ch->id);
+		ctc_pr_debug("%s: remote side issued READ?, init ...\n", ch->id);
 	fsm_deltimer(&ch->timer);
 	if (ctc_checkalloc_buffer(ch, 1))
 		return;
@@ -1039,7 +1132,7 @@ ch_action_firstio(fsm_instance * fi, int
 	if (rc != 0) {
 		fsm_deltimer(&ch->timer);
 		fsm_newstate(fi, CH_STATE_SETUPWAIT);
-		ccw_check_return_code(ch, rc);
+		ccw_check_return_code(ch, rc, "init IO");
 	}
 	/**
 	 * If in compatibility mode since we don´t setup a timer, we
@@ -1075,7 +1168,9 @@ ch_action_rxidle(fsm_instance * fi, int 
 
 	fsm_deltimer(&ch->timer);
 	buflen = *((__u16 *) ch->trans_skb->data);
-	pr_debug("%s: Initial RX count %d\n", dev->name, buflen);
+#ifdef DEBUG
+	ctc_pr_debug("%s: Initial RX count %d\n", dev->name, buflen);
+#endif
 	if (buflen >= CTC_INITIAL_BLOCKLEN) {
 		if (ctc_checkalloc_buffer(ch, 1))
 			return;
@@ -1085,13 +1180,13 @@ ch_action_rxidle(fsm_instance * fi, int 
 				      (unsigned long) ch, 0xff, 0);
 		if (rc != 0) {
 			fsm_newstate(fi, CH_STATE_RXINIT);
-			ccw_check_return_code(ch, rc);
+			ccw_check_return_code(ch, rc, "initial RX");
 		} else
 			fsm_event(((struct ctc_priv *) dev->priv)->fsm,
 				  DEV_EVENT_RXUP, dev);
 	} else {
-		printk(KERN_DEBUG "%s: Initial RX count %d not %d\n",
-		       dev->name, buflen, CTC_INITIAL_BLOCKLEN);
+		ctc_pr_debug("%s: Initial RX count %d not %d\n",
+			     dev->name, buflen, CTC_INITIAL_BLOCKLEN);
 		ch_action_firstio(fi, event, arg);
 	}
 }
@@ -1121,7 +1216,7 @@ ch_action_setmode(fsm_instance * fi, int
 	if (rc != 0) {
 		fsm_deltimer(&ch->timer);
 		fsm_newstate(fi, CH_STATE_STARTWAIT);
-		ccw_check_return_code(ch, rc);
+		ccw_check_return_code(ch, rc, "set Mode");
 	} else
 		ch->retry = 0;
 }
@@ -1142,18 +1237,19 @@ ch_action_start(fsm_instance * fi, int e
 	struct net_device *dev;
 
 	if (ch == NULL) {
-		printk(KERN_WARNING "ch_action_start ch=NULL\n");
+		ctc_pr_warn("ch_action_start ch=NULL\n");
 		return;
 	}
 	if (ch->netdev == NULL) {
-		printk(KERN_WARNING "ch_action_start dev=NULL, id=%s\n",
-		       ch->id);
+		ctc_pr_warn("ch_action_start dev=NULL, id=%s\n", ch->id);
 		return;
 	}
 	dev = ch->netdev;
 
-	pr_debug("%s: %s channel start\n", dev->name,
-		 (CHANNEL_DIRECTION(ch->flags) == READ) ? "RX" : "TX");
+#ifdef DEBUG
+	ctc_pr_debug("%s: %s channel start\n", dev->name,
+		     (CHANNEL_DIRECTION(ch->flags) == READ) ? "RX" : "TX");
+#endif
 
 	if (ch->trans_skb != NULL) {
 		clear_normalized_cda(&ch->ccw[1]);
@@ -1169,12 +1265,13 @@ ch_action_start(fsm_instance * fi, int e
 		ch->ccw[1].flags = CCW_FLAG_SLI | CCW_FLAG_CC;
 		ch->ccw[1].count = 0;
 	}
-	if (ctc_checkalloc_buffer(ch, 0))
-		printk(KERN_NOTICE
-		       "%s: Could not allocate %s trans_skb, delaying "
-		       "allocation until first transfer\n",
-		       dev->name,
-		       (CHANNEL_DIRECTION(ch->flags) == READ) ? "RX" : "TX");
+	if (ctc_checkalloc_buffer(ch, 0)) {
+		ctc_pr_notice(
+			"%s: Could not allocate %s trans_skb, delaying "
+			"allocation until first transfer\n",
+			dev->name,
+			(CHANNEL_DIRECTION(ch->flags) == READ) ? "RX" : "TX");
+	}
 
 	ch->ccw[0].cmd_code = CCW_CMD_PREPARE;
 	ch->ccw[0].flags = CCW_FLAG_SLI | CCW_FLAG_CC;
@@ -1194,10 +1291,13 @@ ch_action_start(fsm_instance * fi, int e
 	rc = ccw_device_halt(ch->cdev, (unsigned long) ch);
 	spin_unlock_irqrestore(get_ccwdev_lock(ch->cdev), saveflags);
 	if (rc != 0) {
-		fsm_deltimer(&ch->timer);
-		ccw_check_return_code(ch, rc);
+		if (rc != -EBUSY)
+		    fsm_deltimer(&ch->timer);
+		ccw_check_return_code(ch, rc, "initial HaltIO");
 	}
-	pr_debug("ctc: %s(): leaving\n", __FUNCTION__);
+#ifdef DEBUG
+	ctc_pr_debug("ctc: %s(): leaving\n", __func__);
+#endif
 }
 
 /**
@@ -1225,9 +1325,11 @@ ch_action_haltio(fsm_instance * fi, int 
 	if (event == CH_EVENT_STOP)
 		spin_unlock_irqrestore(get_ccwdev_lock(ch->cdev), saveflags);
 	if (rc != 0) {
-		fsm_deltimer(&ch->timer);
-		fsm_newstate(fi, oldstate);
-		ccw_check_return_code(ch, rc);
+		if (rc != -EBUSY) {
+		    fsm_deltimer(&ch->timer);
+		    fsm_newstate(fi, oldstate);
+		}
+		ccw_check_return_code(ch, rc, "HaltIO in ch_action_haltio");
 	}
 }
 
@@ -1340,15 +1442,16 @@ ch_action_setuperr(fsm_instance * fi, in
 		if (CHANNEL_DIRECTION(ch->flags) == READ) {
 			int rc = ccw_device_halt(ch->cdev, (unsigned long) ch);
 			if (rc != 0)
-				ccw_check_return_code(ch, rc);
+				ccw_check_return_code(
+					ch, rc, "HaltIO in ch_action_setuperr");
 		}
 		return;
 	}
 
-	printk(KERN_DEBUG "%s: Error %s during %s channel setup state=%s\n",
-	       dev->name, ch_event_names[event],
-	       (CHANNEL_DIRECTION(ch->flags) == READ) ? "RX" : "TX",
-	       fsm_getstate_str(fi));
+	ctc_pr_debug("%s: Error %s during %s channel setup state=%s\n",
+		     dev->name, ch_event_names[event],
+		     (CHANNEL_DIRECTION(ch->flags) == READ) ? "RX" : "TX",
+		     fsm_getstate_str(fi));
 	if (CHANNEL_DIRECTION(ch->flags) == READ) {
 		fsm_newstate(fi, CH_STATE_RXERR);
 		fsm_event(((struct ctc_priv *) dev->priv)->fsm,
@@ -1378,8 +1481,8 @@ ch_action_restart(fsm_instance * fi, int
 	struct net_device *dev = ch->netdev;
 
 	fsm_deltimer(&ch->timer);
-	printk(KERN_DEBUG "%s: %s channel restart\n", dev->name,
-	       (CHANNEL_DIRECTION(ch->flags) == READ) ? "RX" : "TX");
+	ctc_pr_debug("%s: %s channel restart\n", dev->name,
+		     (CHANNEL_DIRECTION(ch->flags) == READ) ? "RX" : "TX");
 	fsm_addtimer(&ch->timer, CTC_TIMEOUT_5SEC, CH_EVENT_TIMER, ch);
 	oldstate = fsm_getstate(fi);
 	fsm_newstate(fi, CH_STATE_STARTWAIT);
@@ -1389,9 +1492,11 @@ ch_action_restart(fsm_instance * fi, int
 	if (event == CH_EVENT_TIMER)
 		spin_unlock_irqrestore(get_ccwdev_lock(ch->cdev), saveflags);
 	if (rc != 0) {
-		fsm_deltimer(&ch->timer);
-		fsm_newstate(fi, oldstate);
-		ccw_check_return_code(ch, rc);
+		if (rc != -EBUSY) {
+		    fsm_deltimer(&ch->timer);
+		    fsm_newstate(fi, oldstate);
+		}
+		ccw_check_return_code(ch, rc, "HaltIO in ch_action_restart");
 	}
 }
 
@@ -1411,8 +1516,7 @@ ch_action_rxiniterr(fsm_instance * fi, i
 
 	if (event == CH_EVENT_TIMER) {
 		fsm_deltimer(&ch->timer);
-		printk(KERN_DEBUG "%s: Timeout during RX init handshake\n",
-		       dev->name);
+		ctc_pr_debug("%s: Timeout during RX init handshake\n", dev->name);
 		if (ch->retry++ < 3)
 			ch_action_restart(fi, event, arg);
 		else {
@@ -1421,8 +1525,7 @@ ch_action_rxiniterr(fsm_instance * fi, i
 				  DEV_EVENT_RXDOWN, dev);
 		}
 	} else
-		printk(KERN_WARNING "%s: Error during RX init handshake\n",
-		       dev->name);
+		ctc_pr_warn("%s: Error during RX init handshake\n", dev->name);
 }
 
 /**
@@ -1440,8 +1543,8 @@ ch_action_rxinitfail(fsm_instance * fi, 
 	struct net_device *dev = ch->netdev;
 
 	fsm_newstate(fi, CH_STATE_RXERR);
-	printk(KERN_WARNING "%s: RX initialization failed\n", dev->name);
-	printk(KERN_WARNING "%s: RX <-> RX connection detected\n", dev->name);
+	ctc_pr_warn("%s: RX initialization failed\n", dev->name);
+	ctc_pr_warn("%s: RX <-> RX connection detected\n", dev->name);
 	fsm_event(((struct ctc_priv *) dev->priv)->fsm, DEV_EVENT_RXDOWN, dev);
 }
 
@@ -1460,8 +1563,8 @@ ch_action_rxdisc(fsm_instance * fi, int 
 	struct net_device *dev = ch->netdev;
 
 	fsm_deltimer(&ch->timer);
-	printk(KERN_DEBUG "%s: Got remote disconnect, re-initializing ...\n",
-	       dev->name);
+	ctc_pr_debug("%s: Got remote disconnect, re-initializing ...\n",
+		     dev->name);
 
 	/**
 	 * Notify device statemachine
@@ -1492,8 +1595,7 @@ ch_action_txiniterr(fsm_instance * fi, i
 
 	if (event == CH_EVENT_TIMER) {
 		fsm_deltimer(&ch->timer);
-		printk(KERN_DEBUG "%s: Timeout during TX init handshake\n",
-		       dev->name);
+		ctc_pr_debug("%s: Timeout during TX init handshake\n", dev->name);
 		if (ch->retry++ < 3)
 			ch_action_restart(fi, event, arg);
 		else {
@@ -1502,8 +1604,7 @@ ch_action_txiniterr(fsm_instance * fi, i
 				  DEV_EVENT_TXDOWN, dev);
 		}
 	} else
-		printk(KERN_WARNING "%s: Error during TX init handshake\n",
-		       dev->name);
+		ctc_pr_warn("%s: Error during TX init handshake\n", dev->name);
 }
 
 /**
@@ -1522,23 +1623,24 @@ ch_action_txretry(fsm_instance * fi, int
 
 	fsm_deltimer(&ch->timer);
 	if (ch->retry++ > 3) {
-		printk(KERN_DEBUG "%s: TX retry failed, restarting channel\n",
-		       dev->name);
+		ctc_pr_debug("%s: TX retry failed, restarting channel\n",
+			     dev->name);
 		fsm_event(((struct ctc_priv *) dev->priv)->fsm,
 			  DEV_EVENT_TXDOWN, dev);
 		ch_action_restart(fi, event, arg);
 	} else {
 		struct sk_buff *skb;
 
-		printk(KERN_DEBUG "%s: TX retry %d\n", dev->name, ch->retry);
+		ctc_pr_debug("%s: TX retry %d\n", dev->name, ch->retry);
 		if ((skb = skb_peek(&ch->io_queue))) {
 			int rc = 0;
 
 			clear_normalized_cda(&ch->ccw[4]);
 			ch->ccw[4].count = skb->len;
 			if (set_normalized_cda(&ch->ccw[4], skb->data)) {
-				printk(KERN_DEBUG "%s: IDAL alloc failed, "
-				       "restarting channel\n", dev->name);
+				ctc_pr_debug(
+					"%s: IDAL alloc failed, chan restart\n",
+					dev->name);
 				fsm_event(((struct ctc_priv *) dev->priv)->fsm,
 					  DEV_EVENT_TXDOWN, dev);
 				ch_action_restart(fi, event, arg);
@@ -1555,7 +1657,7 @@ ch_action_txretry(fsm_instance * fi, int
 						       saveflags);
 			if (rc != 0) {
 				fsm_deltimer(&ch->timer);
-				ccw_check_return_code(ch, rc);
+				ccw_check_return_code(ch, rc, "TX in ch_action_txretry");
 				ctc_purge_skb_queue(&ch->io_queue);
 			}
 		}
@@ -1578,12 +1680,12 @@ ch_action_iofatal(fsm_instance * fi, int
 
 	fsm_deltimer(&ch->timer);
 	if (CHANNEL_DIRECTION(ch->flags) == READ) {
-		printk(KERN_DEBUG "%s: RX I/O error\n", dev->name);
+		ctc_pr_debug("%s: RX I/O error\n", dev->name);
 		fsm_newstate(fi, CH_STATE_RXERR);
 		fsm_event(((struct ctc_priv *) dev->priv)->fsm,
 			  DEV_EVENT_RXDOWN, dev);
 	} else {
-		printk(KERN_DEBUG "%s: TX I/O error\n", dev->name);
+		ctc_pr_debug("%s: TX I/O error\n", dev->name);
 		fsm_newstate(fi, CH_STATE_TXERR);
 		fsm_event(((struct ctc_priv *) dev->priv)->fsm,
 			  DEV_EVENT_TXDOWN, dev);
@@ -1606,109 +1708,109 @@ ch_action_reinit(fsm_instance *fi, int e
  * The statemachine for a channel.
  */
 static const fsm_node ch_fsm[] = {
-	{CH_STATE_STOPPED, CH_EVENT_STOP, fsm_action_nop},
-	{CH_STATE_STOPPED, CH_EVENT_START, ch_action_start},
-	{CH_STATE_STOPPED, CH_EVENT_FINSTAT, fsm_action_nop},
-	{CH_STATE_STOPPED, CH_EVENT_MC_FAIL, fsm_action_nop},
-
-	{CH_STATE_NOTOP, CH_EVENT_STOP, ch_action_stop},
-	{CH_STATE_NOTOP, CH_EVENT_START, fsm_action_nop},
-	{CH_STATE_NOTOP, CH_EVENT_FINSTAT, fsm_action_nop},
-	{CH_STATE_NOTOP, CH_EVENT_MC_FAIL, fsm_action_nop},
-	{CH_STATE_NOTOP, CH_EVENT_MC_GOOD, ch_action_start},
-
-	{CH_STATE_STARTWAIT, CH_EVENT_STOP, ch_action_haltio},
-	{CH_STATE_STARTWAIT, CH_EVENT_START, fsm_action_nop},
-	{CH_STATE_STARTWAIT, CH_EVENT_FINSTAT, ch_action_setmode},
-	{CH_STATE_STARTWAIT, CH_EVENT_TIMER, ch_action_setuperr},
-	{CH_STATE_STARTWAIT, CH_EVENT_IO_ENODEV, ch_action_iofatal},
-	{CH_STATE_STARTWAIT, CH_EVENT_IO_EIO, ch_action_reinit},
-	{CH_STATE_STARTWAIT, CH_EVENT_MC_FAIL, ch_action_fail},
-
-	{CH_STATE_STARTRETRY, CH_EVENT_STOP, ch_action_haltio},
-	{CH_STATE_STARTRETRY, CH_EVENT_TIMER, ch_action_setmode},
-	{CH_STATE_STARTRETRY, CH_EVENT_FINSTAT, fsm_action_nop},
-	{CH_STATE_STARTRETRY, CH_EVENT_MC_FAIL, ch_action_fail},
-
-	{CH_STATE_SETUPWAIT, CH_EVENT_STOP, ch_action_haltio},
-	{CH_STATE_SETUPWAIT, CH_EVENT_START, fsm_action_nop},
-	{CH_STATE_SETUPWAIT, CH_EVENT_FINSTAT, ch_action_firstio},
-	{CH_STATE_SETUPWAIT, CH_EVENT_UC_RCRESET, ch_action_setuperr},
-	{CH_STATE_SETUPWAIT, CH_EVENT_UC_RSRESET, ch_action_setuperr},
-	{CH_STATE_SETUPWAIT, CH_EVENT_TIMER, ch_action_setmode},
-	{CH_STATE_SETUPWAIT, CH_EVENT_IO_ENODEV, ch_action_iofatal},
-	{CH_STATE_SETUPWAIT, CH_EVENT_IO_EIO, ch_action_reinit},
-	{CH_STATE_SETUPWAIT, CH_EVENT_MC_FAIL, ch_action_fail},
-
-	{CH_STATE_RXINIT, CH_EVENT_STOP, ch_action_haltio},
-	{CH_STATE_RXINIT, CH_EVENT_START, fsm_action_nop},
-	{CH_STATE_RXINIT, CH_EVENT_FINSTAT, ch_action_rxidle},
-	{CH_STATE_RXINIT, CH_EVENT_UC_RCRESET, ch_action_rxiniterr},
-	{CH_STATE_RXINIT, CH_EVENT_UC_RSRESET, ch_action_rxiniterr},
-	{CH_STATE_RXINIT, CH_EVENT_TIMER, ch_action_rxiniterr},
-	{CH_STATE_RXINIT, CH_EVENT_ATTNBUSY, ch_action_rxinitfail},
-	{CH_STATE_RXINIT, CH_EVENT_IO_ENODEV, ch_action_iofatal},
-	{CH_STATE_RXINIT, CH_EVENT_IO_EIO, ch_action_reinit},
-	{CH_STATE_RXINIT, CH_EVENT_UC_ZERO, ch_action_firstio},
-	{CH_STATE_RXINIT, CH_EVENT_MC_FAIL, ch_action_fail},
-
-	{CH_STATE_RXIDLE, CH_EVENT_STOP, ch_action_haltio},
-	{CH_STATE_RXIDLE, CH_EVENT_START, fsm_action_nop},
-	{CH_STATE_RXIDLE, CH_EVENT_FINSTAT, ch_action_rx},
-	{CH_STATE_RXIDLE, CH_EVENT_UC_RCRESET, ch_action_rxdisc},
-//      { CH_STATE_RXIDLE,     CH_EVENT_UC_RSRESET, ch_action_rxretry    },
-	{CH_STATE_RXIDLE, CH_EVENT_IO_ENODEV, ch_action_iofatal},
-	{CH_STATE_RXIDLE, CH_EVENT_IO_EIO, ch_action_reinit},
-	{CH_STATE_RXIDLE, CH_EVENT_MC_FAIL, ch_action_fail},
-	{CH_STATE_RXIDLE, CH_EVENT_UC_ZERO, ch_action_rx},
-
-	{CH_STATE_TXINIT, CH_EVENT_STOP, ch_action_haltio},
-	{CH_STATE_TXINIT, CH_EVENT_START, fsm_action_nop},
-	{CH_STATE_TXINIT, CH_EVENT_FINSTAT, ch_action_txidle},
-	{CH_STATE_TXINIT, CH_EVENT_UC_RCRESET, ch_action_txiniterr},
-	{CH_STATE_TXINIT, CH_EVENT_UC_RSRESET, ch_action_txiniterr},
-	{CH_STATE_TXINIT, CH_EVENT_TIMER, ch_action_txiniterr},
-	{CH_STATE_TXINIT, CH_EVENT_IO_ENODEV, ch_action_iofatal},
-	{CH_STATE_TXINIT, CH_EVENT_IO_EIO, ch_action_reinit},
-	{CH_STATE_TXINIT, CH_EVENT_MC_FAIL, ch_action_fail},
-
-	{CH_STATE_TXIDLE, CH_EVENT_STOP, ch_action_haltio},
-	{CH_STATE_TXIDLE, CH_EVENT_START, fsm_action_nop},
-	{CH_STATE_TXIDLE, CH_EVENT_FINSTAT, ch_action_firstio},
-	{CH_STATE_TXIDLE, CH_EVENT_UC_RCRESET, fsm_action_nop},
-	{CH_STATE_TXIDLE, CH_EVENT_UC_RSRESET, fsm_action_nop},
-	{CH_STATE_TXIDLE, CH_EVENT_IO_ENODEV, ch_action_iofatal},
-	{CH_STATE_TXIDLE, CH_EVENT_IO_EIO, ch_action_reinit},
-	{CH_STATE_TXIDLE, CH_EVENT_MC_FAIL, ch_action_fail},
-
-	{CH_STATE_TERM, CH_EVENT_STOP, fsm_action_nop},
-	{CH_STATE_TERM, CH_EVENT_START, ch_action_restart},
-	{CH_STATE_TERM, CH_EVENT_FINSTAT, ch_action_stopped},
-	{CH_STATE_TERM, CH_EVENT_UC_RCRESET, fsm_action_nop},
-	{CH_STATE_TERM, CH_EVENT_UC_RSRESET, fsm_action_nop},
-	{CH_STATE_TERM, CH_EVENT_MC_FAIL, ch_action_fail},
-
-	{CH_STATE_DTERM, CH_EVENT_STOP, ch_action_haltio},
-	{CH_STATE_DTERM, CH_EVENT_START, ch_action_restart},
-	{CH_STATE_DTERM, CH_EVENT_FINSTAT, ch_action_setmode},
-	{CH_STATE_DTERM, CH_EVENT_UC_RCRESET, fsm_action_nop},
-	{CH_STATE_DTERM, CH_EVENT_UC_RSRESET, fsm_action_nop},
-	{CH_STATE_DTERM, CH_EVENT_MC_FAIL, ch_action_fail},
-
-	{CH_STATE_TX, CH_EVENT_STOP, ch_action_haltio},
-	{CH_STATE_TX, CH_EVENT_START, fsm_action_nop},
-	{CH_STATE_TX, CH_EVENT_FINSTAT, ch_action_txdone},
-	{CH_STATE_TX, CH_EVENT_UC_RCRESET, ch_action_txretry},
-	{CH_STATE_TX, CH_EVENT_UC_RSRESET, ch_action_txretry},
-	{CH_STATE_TX, CH_EVENT_TIMER, ch_action_txretry},
-	{CH_STATE_TX, CH_EVENT_IO_ENODEV, ch_action_iofatal},
-	{CH_STATE_TX, CH_EVENT_IO_EIO, ch_action_reinit},
-	{CH_STATE_TX, CH_EVENT_MC_FAIL, ch_action_fail},
-
-	{CH_STATE_RXERR, CH_EVENT_STOP, ch_action_haltio},
-	{CH_STATE_TXERR, CH_EVENT_STOP, ch_action_haltio},
-	{CH_STATE_TXERR, CH_EVENT_MC_FAIL, ch_action_fail},
-	{CH_STATE_RXERR, CH_EVENT_MC_FAIL, ch_action_fail},
+	{CH_STATE_STOPPED,    CH_EVENT_STOP,       fsm_action_nop       },
+	{CH_STATE_STOPPED,    CH_EVENT_START,      ch_action_start      },
+	{CH_STATE_STOPPED,    CH_EVENT_FINSTAT,    fsm_action_nop       },
+	{CH_STATE_STOPPED,    CH_EVENT_MC_FAIL,    fsm_action_nop       },
+
+	{CH_STATE_NOTOP,      CH_EVENT_STOP,       ch_action_stop       },
+	{CH_STATE_NOTOP,      CH_EVENT_START,      fsm_action_nop       },
+	{CH_STATE_NOTOP,      CH_EVENT_FINSTAT,    fsm_action_nop       },
+	{CH_STATE_NOTOP,      CH_EVENT_MC_FAIL,    fsm_action_nop       },
+	{CH_STATE_NOTOP,      CH_EVENT_MC_GOOD,    ch_action_start      },
+
+	{CH_STATE_STARTWAIT,  CH_EVENT_STOP,       ch_action_haltio     },
+	{CH_STATE_STARTWAIT,  CH_EVENT_START,      fsm_action_nop       },
+	{CH_STATE_STARTWAIT,  CH_EVENT_FINSTAT,    ch_action_setmode    },
+	{CH_STATE_STARTWAIT,  CH_EVENT_TIMER,      ch_action_setuperr   },
+	{CH_STATE_STARTWAIT,  CH_EVENT_IO_ENODEV,  ch_action_iofatal    },
+	{CH_STATE_STARTWAIT,  CH_EVENT_IO_EIO,     ch_action_reinit     },
+	{CH_STATE_STARTWAIT,  CH_EVENT_MC_FAIL,    ch_action_fail       },
+
+	{CH_STATE_STARTRETRY, CH_EVENT_STOP,       ch_action_haltio     },
+	{CH_STATE_STARTRETRY, CH_EVENT_TIMER,      ch_action_setmode    },
+	{CH_STATE_STARTRETRY, CH_EVENT_FINSTAT,    fsm_action_nop       },
+	{CH_STATE_STARTRETRY, CH_EVENT_MC_FAIL,    ch_action_fail       },
+
+	{CH_STATE_SETUPWAIT,  CH_EVENT_STOP,       ch_action_haltio     },
+	{CH_STATE_SETUPWAIT,  CH_EVENT_START,      fsm_action_nop       },
+	{CH_STATE_SETUPWAIT,  CH_EVENT_FINSTAT,    ch_action_firstio    },
+	{CH_STATE_SETUPWAIT,  CH_EVENT_UC_RCRESET, ch_action_setuperr   },
+	{CH_STATE_SETUPWAIT,  CH_EVENT_UC_RSRESET, ch_action_setuperr   },
+	{CH_STATE_SETUPWAIT,  CH_EVENT_TIMER,      ch_action_setmode    },
+	{CH_STATE_SETUPWAIT,  CH_EVENT_IO_ENODEV,  ch_action_iofatal    },
+	{CH_STATE_SETUPWAIT,  CH_EVENT_IO_EIO,     ch_action_reinit     },
+	{CH_STATE_SETUPWAIT,  CH_EVENT_MC_FAIL,    ch_action_fail       },
+
+	{CH_STATE_RXINIT,     CH_EVENT_STOP,       ch_action_haltio     },
+	{CH_STATE_RXINIT,     CH_EVENT_START,      fsm_action_nop       },
+	{CH_STATE_RXINIT,     CH_EVENT_FINSTAT,    ch_action_rxidle     },
+	{CH_STATE_RXINIT,     CH_EVENT_UC_RCRESET, ch_action_rxiniterr  },
+	{CH_STATE_RXINIT,     CH_EVENT_UC_RSRESET, ch_action_rxiniterr  },
+	{CH_STATE_RXINIT,     CH_EVENT_TIMER,      ch_action_rxiniterr  },
+	{CH_STATE_RXINIT,     CH_EVENT_ATTNBUSY,   ch_action_rxinitfail },
+	{CH_STATE_RXINIT,     CH_EVENT_IO_ENODEV,  ch_action_iofatal    },
+	{CH_STATE_RXINIT,     CH_EVENT_IO_EIO,     ch_action_reinit     },
+	{CH_STATE_RXINIT,     CH_EVENT_UC_ZERO,    ch_action_firstio    },
+	{CH_STATE_RXINIT,     CH_EVENT_MC_FAIL,    ch_action_fail       },
+
+	{CH_STATE_RXIDLE,     CH_EVENT_STOP,       ch_action_haltio     },
+	{CH_STATE_RXIDLE,     CH_EVENT_START,      fsm_action_nop       },
+	{CH_STATE_RXIDLE,     CH_EVENT_FINSTAT,    ch_action_rx         },
+	{CH_STATE_RXIDLE,     CH_EVENT_UC_RCRESET, ch_action_rxdisc     },
+//      {CH_STATE_RXIDLE,     CH_EVENT_UC_RSRESET, ch_action_rxretry    },
+	{CH_STATE_RXIDLE,     CH_EVENT_IO_ENODEV,  ch_action_iofatal    },
+	{CH_STATE_RXIDLE,     CH_EVENT_IO_EIO,     ch_action_reinit     },
+	{CH_STATE_RXIDLE,     CH_EVENT_MC_FAIL,    ch_action_fail       },
+	{CH_STATE_RXIDLE,     CH_EVENT_UC_ZERO,    ch_action_rx         },
+
+	{CH_STATE_TXINIT,     CH_EVENT_STOP,       ch_action_haltio     },
+	{CH_STATE_TXINIT,     CH_EVENT_START,      fsm_action_nop       },
+	{CH_STATE_TXINIT,     CH_EVENT_FINSTAT,    ch_action_txidle     },
+	{CH_STATE_TXINIT,     CH_EVENT_UC_RCRESET, ch_action_txiniterr  },
+	{CH_STATE_TXINIT,     CH_EVENT_UC_RSRESET, ch_action_txiniterr  },
+	{CH_STATE_TXINIT,     CH_EVENT_TIMER,      ch_action_txiniterr  },
+	{CH_STATE_TXINIT,     CH_EVENT_IO_ENODEV,  ch_action_iofatal    },
+	{CH_STATE_TXINIT,     CH_EVENT_IO_EIO,     ch_action_reinit     },
+	{CH_STATE_TXINIT,     CH_EVENT_MC_FAIL,    ch_action_fail       },
+
+	{CH_STATE_TXIDLE,     CH_EVENT_STOP,       ch_action_haltio     },
+	{CH_STATE_TXIDLE,     CH_EVENT_START,      fsm_action_nop       },
+	{CH_STATE_TXIDLE,     CH_EVENT_FINSTAT,    ch_action_firstio    },
+	{CH_STATE_TXIDLE,     CH_EVENT_UC_RCRESET, fsm_action_nop       },
+	{CH_STATE_TXIDLE,     CH_EVENT_UC_RSRESET, fsm_action_nop       },
+	{CH_STATE_TXIDLE,     CH_EVENT_IO_ENODEV,  ch_action_iofatal    },
+	{CH_STATE_TXIDLE,     CH_EVENT_IO_EIO,     ch_action_reinit     },
+	{CH_STATE_TXIDLE,     CH_EVENT_MC_FAIL,    ch_action_fail       },
+
+	{CH_STATE_TERM,       CH_EVENT_STOP,       fsm_action_nop       },
+	{CH_STATE_TERM,       CH_EVENT_START,      ch_action_restart    },
+	{CH_STATE_TERM,       CH_EVENT_FINSTAT,    ch_action_stopped    },
+	{CH_STATE_TERM,       CH_EVENT_UC_RCRESET, fsm_action_nop       },
+	{CH_STATE_TERM,       CH_EVENT_UC_RSRESET, fsm_action_nop       },
+	{CH_STATE_TERM,       CH_EVENT_MC_FAIL,    ch_action_fail       },
+
+	{CH_STATE_DTERM,      CH_EVENT_STOP,       ch_action_haltio     },
+	{CH_STATE_DTERM,      CH_EVENT_START,      ch_action_restart    },
+	{CH_STATE_DTERM,      CH_EVENT_FINSTAT,    ch_action_setmode    },
+	{CH_STATE_DTERM,      CH_EVENT_UC_RCRESET, fsm_action_nop       },
+	{CH_STATE_DTERM,      CH_EVENT_UC_RSRESET, fsm_action_nop       },
+	{CH_STATE_DTERM,      CH_EVENT_MC_FAIL,    ch_action_fail       },
+
+	{CH_STATE_TX,         CH_EVENT_STOP,       ch_action_haltio     },
+	{CH_STATE_TX,         CH_EVENT_START,      fsm_action_nop       },
+	{CH_STATE_TX,         CH_EVENT_FINSTAT,    ch_action_txdone     },
+	{CH_STATE_TX,         CH_EVENT_UC_RCRESET, ch_action_txretry    },
+	{CH_STATE_TX,         CH_EVENT_UC_RSRESET, ch_action_txretry    },
+	{CH_STATE_TX,         CH_EVENT_TIMER,      ch_action_txretry    },
+	{CH_STATE_TX,         CH_EVENT_IO_ENODEV,  ch_action_iofatal    },
+	{CH_STATE_TX,         CH_EVENT_IO_EIO,     ch_action_reinit     },
+	{CH_STATE_TX,         CH_EVENT_MC_FAIL,    ch_action_fail       },
+
+	{CH_STATE_RXERR,      CH_EVENT_STOP,       ch_action_haltio     },
+	{CH_STATE_TXERR,      CH_EVENT_STOP,       ch_action_haltio     },
+	{CH_STATE_TXERR,      CH_EVENT_MC_FAIL,    ch_action_fail       },
+	{CH_STATE_RXERR,      CH_EVENT_MC_FAIL,    ch_action_fail       },
 };
 
 static const int CH_FSM_LEN = sizeof (ch_fsm) / sizeof (fsm_node);
@@ -1720,16 +1822,16 @@ static const int CH_FSM_LEN = sizeof (ch
 static inline int
 less_than(char *id1, char *id2)
 {
-	int dev1,dev2,i;
+	int dev1, dev2, i;
 
-	for (i=0;i<5;i++) {
+	for (i = 0; i < 5; i++) {
 		id1++;
 		id2++;
 	}
 	dev1 = simple_strtoul(id1, &id1, 16);
 	dev2 = simple_strtoul(id2, &id2, 16);
 	
-	return (dev1<dev2);
+	return (dev1 < dev2);
 }
 
 /**
@@ -1750,14 +1852,14 @@ add_channel(struct ccw_device *cdev, enu
 	if ((ch =
 	     (struct channel *) kmalloc(sizeof (struct channel),
 					GFP_KERNEL)) == NULL) {
-		printk(KERN_WARNING "ctc: Out of memory in add_channel\n");
+		ctc_pr_warn("ctc: Out of memory in add_channel\n");
 		return -1;
 	}
 	memset(ch, 0, sizeof (struct channel));
 	if ((ch->ccw = (struct ccw1 *) kmalloc(sizeof (struct ccw1) * 8,
 					       GFP_KERNEL | GFP_DMA)) == NULL) {
 		kfree(ch);
-		printk(KERN_WARNING "ctc: Out of memory in add_channel\n");
+		ctc_pr_warn("ctc: Out of memory in add_channel\n");
 		return -1;
 	}
 
@@ -1793,19 +1895,19 @@ add_channel(struct ccw_device *cdev, enu
 	ch->cdev = cdev;
 	snprintf(ch->id, CTC_ID_SIZE, "ch-%s", cdev->dev.bus_id);
 	ch->type = type;
+	loglevel = CTC_LOGLEVEL_DEFAULT;
 	ch->fsm = init_fsm(ch->id, ch_state_names,
 			   ch_event_names, NR_CH_STATES, NR_CH_EVENTS,
 			   ch_fsm, CH_FSM_LEN, GFP_KERNEL);
 	if (ch->fsm == NULL) {
-		printk(KERN_WARNING
-		       "ctc: Could not create FSM in add_channel\n");
+		ctc_pr_warn("ctc: Could not create FSM in add_channel\n");
 		kfree(ch);
 		return -1;
 	}
 	fsm_newstate(ch->fsm, CH_STATE_IDLE);
 	if ((ch->irb = (struct irb *) kmalloc(sizeof (struct irb),
 					      GFP_KERNEL)) == NULL) {
-		printk(KERN_WARNING "ctc: Out of memory in add_channel\n");
+		ctc_pr_warn("ctc: Out of memory in add_channel\n");
 		kfree_fsm(ch->fsm);
 		kfree(ch);
 		return -1;
@@ -1814,9 +1916,9 @@ add_channel(struct ccw_device *cdev, enu
 	while (*c && less_than((*c)->id, ch->id))
 		c = &(*c)->next;
 	if (!strncmp((*c)->id, ch->id, CTC_ID_SIZE)) {
-		printk(KERN_DEBUG
-		       "ctc: add_channel: device %s already in list, "
-		       "using old entry\n", (*c)->id);
+		ctc_pr_debug(
+			"ctc: add_channel: device %s already in list, "
+			"using old entry\n", (*c)->id);
 		kfree(ch->irb);
 		kfree_fsm(ch->fsm);
 		kfree(ch);
@@ -1888,20 +1990,26 @@ channel_get(enum channel_types type, cha
 {
 	struct channel *ch = channels;
 
-	pr_debug("ctc: %s(): searching for ch with id %d and type %d\n",
-		 __FUNCTION__, id, type);
+#ifdef DEBUG
+	ctc_pr_debug("ctc: %s(): searching for ch with id %s and type %d\n",
+		     __func__, id, type);
+#endif
 
 	while (ch && ((strncmp(ch->id, id, CTC_ID_SIZE)) || (ch->type != type))) {
-		pr_debug("ctc: %s(): ch=0x%p (id=%s, type=%d\n",
-			 __FUNCTION__, ch, ch->id, ch->type);
+#ifdef DEBUG
+		ctc_pr_debug("ctc: %s(): ch=0x%p (id=%s, type=%d\n",
+			     __func__, ch, ch->id, ch->type);
+#endif
 		ch = ch->next;
 	}
-	pr_debug("ctc: %s(): ch=0x%pq (id=%s, type=%d\n",
-		 __FUNCTION__, ch, ch->id, ch->type);
+#ifdef DEBUG
+	ctc_pr_debug("ctc: %s(): ch=0x%pq (id=%s, type=%d\n",
+		     __func__, ch, ch->id, ch->type);
+#endif
 	if (!ch) {
-		printk(KERN_WARNING "ctc: %s(): channel with id %s "
-		       "and type %d not found in channel list\n",
-		       __FUNCTION__, id, type);
+		ctc_pr_warn("ctc: %s(): channel with id %s "
+			    "and type %d not found in channel list\n",
+			    __func__, id, type);
 	} else {
 		if (ch->flags & CHANNEL_FLAGS_INUSE)
 			ch = NULL;
@@ -1953,10 +2061,9 @@ ctc_irq_handler(struct ccw_device *cdev,
 
 	/* Check for unsolicited interrupts. */
 	if (!cdev->dev.driver_data) {
-		printk(KERN_WARNING
-		       "ctc: Got unsolicited irq: %s c-%02x d-%02x\n",
-		       cdev->dev.bus_id, irb->scsw.cstat,
-		       irb->scsw.dstat);
+		ctc_pr_warn("ctc: Got unsolicited irq: %s c-%02x d-%02x\n",
+			    cdev->dev.bus_id, irb->scsw.cstat,
+			    irb->scsw.dstat);
 		return;
 	}
 	
@@ -1968,22 +2075,22 @@ ctc_irq_handler(struct ccw_device *cdev,
 	else if (priv->channel[WRITE]->cdev == cdev)
 		ch = priv->channel[WRITE];
 	else {
-		printk(KERN_ERR
-		       "ctc: Can't determine channel for interrupt, "
-		       "device %s\n", cdev->dev.bus_id);
+		ctc_pr_err("ctc: Can't determine channel for interrupt, "
+			   "device %s\n", cdev->dev.bus_id);
 		return;
 	}
 	
 	dev = (struct net_device *) (ch->netdev);
 	if (dev == NULL) {
-		printk(KERN_CRIT
-		       "ctc: ctc_irq_handler dev = NULL bus_id=%s, ch=0x%p\n",
-		       cdev->dev.bus_id, ch);
+		ctc_pr_crit("ctc: ctc_irq_handler dev=NULL bus_id=%s, ch=0x%p\n",
+			    cdev->dev.bus_id, ch);
 		return;
 	}
 
-	pr_debug("%s: interrupt for device: %s received c-%02x d-%02x\n"
-		 dev->name, ch->id, irb->scsw.cstat, irb->scsw.dstat);
+#ifdef DEBUG
+	ctc_pr_debug("%s: interrupt for device: %s received c-%02x d-%02x\n",
+		     dev->name, ch->id, irb->scsw.cstat, irb->scsw.dstat);
+#endif
 
 	/* Copy interruption response block. */
 	memcpy(ch->irb, irb, sizeof(struct irb));
@@ -1991,10 +2098,9 @@ ctc_irq_handler(struct ccw_device *cdev,
 	/* Check for good subchannel return code, otherwise error message */
 	if (ch->irb->scsw.cstat) {
 		fsm_event(ch->fsm, CH_EVENT_SC_UNKNOWN, ch);
-		printk(KERN_WARNING
-		       "%s: subchannel check for device: %s - %02x %02x\n",
-		       dev->name, ch->id, ch->irb->scsw.cstat,
-		       ch->irb->scsw.dstat);
+		ctc_pr_warn("%s: subchannel check for device: %s - %02x %02x\n",
+			    dev->name, ch->id, ch->irb->scsw.cstat,
+			    ch->irb->scsw.dstat);
 		return;
 	}
 
@@ -2076,7 +2182,7 @@ dev_action_restart(fsm_instance *fi, int
 	struct net_device *dev = (struct net_device *)arg;
 	struct ctc_priv *privptr = dev->priv;
 	
-	printk(KERN_DEBUG "%s: Restarting\n", dev->name);
+	ctc_pr_debug("%s: Restarting\n", dev->name);
 	dev_action_stop(fi, event, arg);
 	fsm_event(privptr->fsm, DEV_EVENT_STOP, dev);
 	fsm_addtimer(&privptr->restart_timer, CTC_TIMEOUT_5SEC,
@@ -2098,40 +2204,40 @@ dev_action_chup(fsm_instance * fi, int e
 	struct ctc_priv *privptr = dev->priv;
 
 	switch (fsm_getstate(fi)) {
-	case DEV_STATE_STARTWAIT_RXTX:
-		if (event == DEV_EVENT_RXUP)
-			fsm_newstate(fi, DEV_STATE_STARTWAIT_TX);
-		else
-			fsm_newstate(fi, DEV_STATE_STARTWAIT_RX);
-		break;
-	case DEV_STATE_STARTWAIT_RX:
-		if (event == DEV_EVENT_RXUP) {
-			fsm_newstate(fi, DEV_STATE_RUNNING);
-			printk(KERN_INFO
-			       "%s: connected with remote side\n", dev->name);
-			if (privptr->protocol == CTC_PROTO_LINUX_TTY)
-				ctc_tty_setcarrier(dev, 1);
-			ctc_clear_busy(dev);
-		}
-		break;
-	case DEV_STATE_STARTWAIT_TX:
-		if (event == DEV_EVENT_TXUP) {
-			fsm_newstate(fi, DEV_STATE_RUNNING);
-			printk(KERN_INFO
-			       "%s: connected with remote side\n", dev->name);
-			if (privptr->protocol == CTC_PROTO_LINUX_TTY)
-				ctc_tty_setcarrier(dev, 1);
-			ctc_clear_busy(dev);
-		}
-		break;
-	case DEV_STATE_STOPWAIT_TX:
-		if (event == DEV_EVENT_RXUP)
-			fsm_newstate(fi, DEV_STATE_STOPWAIT_RXTX);
-		break;
-	case DEV_STATE_STOPWAIT_RX:
-		if (event == DEV_EVENT_TXUP)
-			fsm_newstate(fi, DEV_STATE_STOPWAIT_RXTX);
-		break;
+		case DEV_STATE_STARTWAIT_RXTX:
+			if (event == DEV_EVENT_RXUP)
+				fsm_newstate(fi, DEV_STATE_STARTWAIT_TX);
+			else
+				fsm_newstate(fi, DEV_STATE_STARTWAIT_RX);
+			break;
+		case DEV_STATE_STARTWAIT_RX:
+			if (event == DEV_EVENT_RXUP) {
+				fsm_newstate(fi, DEV_STATE_RUNNING);
+				ctc_pr_info("%s: connected with remote side\n",
+					    dev->name);
+				if (privptr->protocol == CTC_PROTO_LINUX_TTY)
+					ctc_tty_setcarrier(dev, 1);
+				ctc_clear_busy(dev);
+			}
+			break;
+		case DEV_STATE_STARTWAIT_TX:
+			if (event == DEV_EVENT_TXUP) {
+				fsm_newstate(fi, DEV_STATE_RUNNING);
+				ctc_pr_info("%s: connected with remote side\n",
+					    dev->name);
+				if (privptr->protocol == CTC_PROTO_LINUX_TTY)
+					ctc_tty_setcarrier(dev, 1);
+				ctc_clear_busy(dev);
+			}
+			break;
+		case DEV_STATE_STOPWAIT_TX:
+			if (event == DEV_EVENT_RXUP)
+				fsm_newstate(fi, DEV_STATE_STOPWAIT_RXTX);
+			break;
+		case DEV_STATE_STOPWAIT_RX:
+			if (event == DEV_EVENT_TXUP)
+				fsm_newstate(fi, DEV_STATE_STOPWAIT_RXTX);
+			break;
 	}
 }
 
@@ -2150,84 +2256,84 @@ dev_action_chdown(fsm_instance * fi, int
 	struct ctc_priv *privptr = dev->priv;
 
 	switch (fsm_getstate(fi)) {
-	case DEV_STATE_RUNNING:
-		if (privptr->protocol == CTC_PROTO_LINUX_TTY)
-			ctc_tty_setcarrier(dev, 0);
-		if (event == DEV_EVENT_TXDOWN)
-			fsm_newstate(fi, DEV_STATE_STARTWAIT_TX);
-		else
-			fsm_newstate(fi, DEV_STATE_STARTWAIT_RX);
-		break;
-	case DEV_STATE_STARTWAIT_RX:
-		if (event == DEV_EVENT_TXDOWN)
-			fsm_newstate(fi, DEV_STATE_STARTWAIT_RXTX);
-		break;
-	case DEV_STATE_STARTWAIT_TX:
-		if (event == DEV_EVENT_RXDOWN)
-			fsm_newstate(fi, DEV_STATE_STARTWAIT_RXTX);
-		break;
-	case DEV_STATE_STOPWAIT_RXTX:
-		if (event == DEV_EVENT_TXDOWN)
-			fsm_newstate(fi, DEV_STATE_STOPWAIT_RX);
-		else
-			fsm_newstate(fi, DEV_STATE_STOPWAIT_TX);
-		break;
-	case DEV_STATE_STOPWAIT_RX:
-		if (event == DEV_EVENT_RXDOWN)
-			fsm_newstate(fi, DEV_STATE_STOPPED);
-		break;
-	case DEV_STATE_STOPWAIT_TX:
-		if (event == DEV_EVENT_TXDOWN)
-			fsm_newstate(fi, DEV_STATE_STOPPED);
-		break;
+		case DEV_STATE_RUNNING:
+			if (privptr->protocol == CTC_PROTO_LINUX_TTY)
+				ctc_tty_setcarrier(dev, 0);
+			if (event == DEV_EVENT_TXDOWN)
+				fsm_newstate(fi, DEV_STATE_STARTWAIT_TX);
+			else
+				fsm_newstate(fi, DEV_STATE_STARTWAIT_RX);
+			break;
+		case DEV_STATE_STARTWAIT_RX:
+			if (event == DEV_EVENT_TXDOWN)
+				fsm_newstate(fi, DEV_STATE_STARTWAIT_RXTX);
+			break;
+		case DEV_STATE_STARTWAIT_TX:
+			if (event == DEV_EVENT_RXDOWN)
+				fsm_newstate(fi, DEV_STATE_STARTWAIT_RXTX);
+			break;
+		case DEV_STATE_STOPWAIT_RXTX:
+			if (event == DEV_EVENT_TXDOWN)
+				fsm_newstate(fi, DEV_STATE_STOPWAIT_RX);
+			else
+				fsm_newstate(fi, DEV_STATE_STOPWAIT_TX);
+			break;
+		case DEV_STATE_STOPWAIT_RX:
+			if (event == DEV_EVENT_RXDOWN)
+				fsm_newstate(fi, DEV_STATE_STOPPED);
+			break;
+		case DEV_STATE_STOPWAIT_TX:
+			if (event == DEV_EVENT_TXDOWN)
+				fsm_newstate(fi, DEV_STATE_STOPPED);
+			break;
 	}
 }
 
 static const fsm_node dev_fsm[] = {
 	{DEV_STATE_STOPPED, DEV_EVENT_START, dev_action_start},
 
-	{DEV_STATE_STOPWAIT_RXTX, DEV_EVENT_START, dev_action_start},
-	{DEV_STATE_STOPWAIT_RXTX, DEV_EVENT_RXDOWN, dev_action_chdown},
-	{DEV_STATE_STOPWAIT_RXTX, DEV_EVENT_TXDOWN, dev_action_chdown},
- 	{DEV_STATE_STOPWAIT_RXTX, DEV_EVENT_RESTART, dev_action_restart },
-
-	{DEV_STATE_STOPWAIT_RX, DEV_EVENT_START, dev_action_start},
-	{DEV_STATE_STOPWAIT_RX, DEV_EVENT_RXUP, dev_action_chup},
-	{DEV_STATE_STOPWAIT_RX, DEV_EVENT_TXUP, dev_action_chup},
-	{DEV_STATE_STOPWAIT_RX, DEV_EVENT_RXDOWN, dev_action_chdown},
- 	{DEV_STATE_STOPWAIT_RX, DEV_EVENT_RESTART, dev_action_restart },
-
-	{DEV_STATE_STOPWAIT_TX, DEV_EVENT_START, dev_action_start},
-	{DEV_STATE_STOPWAIT_TX, DEV_EVENT_RXUP, dev_action_chup},
-	{DEV_STATE_STOPWAIT_TX, DEV_EVENT_TXUP, dev_action_chup},
-	{DEV_STATE_STOPWAIT_TX, DEV_EVENT_TXDOWN, dev_action_chdown},
- 	{DEV_STATE_STOPWAIT_TX, DEV_EVENT_RESTART, dev_action_restart },
-
-	{DEV_STATE_STARTWAIT_RXTX, DEV_EVENT_STOP, dev_action_stop},
-	{DEV_STATE_STARTWAIT_RXTX, DEV_EVENT_RXUP, dev_action_chup},
-	{DEV_STATE_STARTWAIT_RXTX, DEV_EVENT_TXUP, dev_action_chup},
-	{DEV_STATE_STARTWAIT_RXTX, DEV_EVENT_RXDOWN, dev_action_chdown},
-	{DEV_STATE_STARTWAIT_RXTX, DEV_EVENT_TXDOWN, dev_action_chdown},
+	{DEV_STATE_STOPWAIT_RXTX,  DEV_EVENT_START,   dev_action_start   },
+	{DEV_STATE_STOPWAIT_RXTX,  DEV_EVENT_RXDOWN,  dev_action_chdown  },
+	{DEV_STATE_STOPWAIT_RXTX,  DEV_EVENT_TXDOWN,  dev_action_chdown  },
+ 	{DEV_STATE_STOPWAIT_RXTX,  DEV_EVENT_RESTART, dev_action_restart },
+
+	{DEV_STATE_STOPWAIT_RX,    DEV_EVENT_START,   dev_action_start   },
+	{DEV_STATE_STOPWAIT_RX,    DEV_EVENT_RXUP,    dev_action_chup    },
+	{DEV_STATE_STOPWAIT_RX,    DEV_EVENT_TXUP,    dev_action_chup    },
+	{DEV_STATE_STOPWAIT_RX,    DEV_EVENT_RXDOWN,  dev_action_chdown  },
+ 	{DEV_STATE_STOPWAIT_RX,    DEV_EVENT_RESTART, dev_action_restart },
+
+	{DEV_STATE_STOPWAIT_TX,    DEV_EVENT_START,   dev_action_start   },
+	{DEV_STATE_STOPWAIT_TX,    DEV_EVENT_RXUP,    dev_action_chup    },
+	{DEV_STATE_STOPWAIT_TX,    DEV_EVENT_TXUP,    dev_action_chup    },
+	{DEV_STATE_STOPWAIT_TX,    DEV_EVENT_TXDOWN,  dev_action_chdown  },
+ 	{DEV_STATE_STOPWAIT_TX,    DEV_EVENT_RESTART, dev_action_restart },
+
+	{DEV_STATE_STARTWAIT_RXTX, DEV_EVENT_STOP,    dev_action_stop    },
+	{DEV_STATE_STARTWAIT_RXTX, DEV_EVENT_RXUP,    dev_action_chup    },
+	{DEV_STATE_STARTWAIT_RXTX, DEV_EVENT_TXUP,    dev_action_chup    },
+	{DEV_STATE_STARTWAIT_RXTX, DEV_EVENT_RXDOWN,  dev_action_chdown  },
+	{DEV_STATE_STARTWAIT_RXTX, DEV_EVENT_TXDOWN,  dev_action_chdown  },
  	{DEV_STATE_STARTWAIT_RXTX, DEV_EVENT_RESTART, dev_action_restart },
 
-	{DEV_STATE_STARTWAIT_TX, DEV_EVENT_STOP, dev_action_stop},
-	{DEV_STATE_STARTWAIT_TX, DEV_EVENT_RXUP, dev_action_chup},
-	{DEV_STATE_STARTWAIT_TX, DEV_EVENT_TXUP, dev_action_chup},
-	{DEV_STATE_STARTWAIT_TX, DEV_EVENT_RXDOWN, dev_action_chdown},
- 	{DEV_STATE_STARTWAIT_TX, DEV_EVENT_RESTART, dev_action_restart },
-
-	{DEV_STATE_STARTWAIT_RX, DEV_EVENT_STOP, dev_action_stop},
-	{DEV_STATE_STARTWAIT_RX, DEV_EVENT_RXUP, dev_action_chup},
-	{DEV_STATE_STARTWAIT_RX, DEV_EVENT_TXUP, dev_action_chup},
-	{DEV_STATE_STARTWAIT_RX, DEV_EVENT_TXDOWN, dev_action_chdown},
- 	{DEV_STATE_STARTWAIT_RX, DEV_EVENT_RESTART, dev_action_restart },
-
-	{DEV_STATE_RUNNING, DEV_EVENT_STOP, dev_action_stop},
-	{DEV_STATE_RUNNING, DEV_EVENT_RXDOWN, dev_action_chdown},
-	{DEV_STATE_RUNNING, DEV_EVENT_TXDOWN, dev_action_chdown},
-	{DEV_STATE_RUNNING, DEV_EVENT_TXUP, fsm_action_nop},
-	{DEV_STATE_RUNNING, DEV_EVENT_RXUP, fsm_action_nop},
- 	{DEV_STATE_RUNNING, DEV_EVENT_RESTART, dev_action_restart },
+	{DEV_STATE_STARTWAIT_TX,   DEV_EVENT_STOP,    dev_action_stop    },
+	{DEV_STATE_STARTWAIT_TX,   DEV_EVENT_RXUP,    dev_action_chup    },
+	{DEV_STATE_STARTWAIT_TX,   DEV_EVENT_TXUP,    dev_action_chup    },
+	{DEV_STATE_STARTWAIT_TX,   DEV_EVENT_RXDOWN,  dev_action_chdown  },
+ 	{DEV_STATE_STARTWAIT_TX,   DEV_EVENT_RESTART, dev_action_restart },
+
+	{DEV_STATE_STARTWAIT_RX,   DEV_EVENT_STOP,    dev_action_stop    },
+	{DEV_STATE_STARTWAIT_RX,   DEV_EVENT_RXUP,    dev_action_chup    },
+	{DEV_STATE_STARTWAIT_RX,   DEV_EVENT_TXUP,    dev_action_chup    },
+	{DEV_STATE_STARTWAIT_RX,   DEV_EVENT_TXDOWN,  dev_action_chdown  },
+ 	{DEV_STATE_STARTWAIT_RX,   DEV_EVENT_RESTART, dev_action_restart },
+
+	{DEV_STATE_RUNNING,        DEV_EVENT_STOP,    dev_action_stop    },
+	{DEV_STATE_RUNNING,        DEV_EVENT_RXDOWN,  dev_action_chdown  },
+	{DEV_STATE_RUNNING,        DEV_EVENT_TXDOWN,  dev_action_chdown  },
+	{DEV_STATE_RUNNING,        DEV_EVENT_TXUP,    fsm_action_nop     },
+	{DEV_STATE_RUNNING,        DEV_EVENT_RXUP,    fsm_action_nop     },
+ 	{DEV_STATE_RUNNING,        DEV_EVENT_RESTART, dev_action_restart },
 };
 
 static const int DEV_FSM_LEN = sizeof (dev_fsm) / sizeof (fsm_node);
@@ -2349,7 +2455,7 @@ transmit_skb(struct channel *ch, struct 
 			ch->prof.doios_single++;
 		if (rc != 0) {
 			fsm_deltimer(&ch->timer);
-			ccw_check_return_code(ch, rc);
+			ccw_check_return_code(ch, rc, "single skb TX");
 			if (ccw_idx == 3)
 				skb_dequeue_tail(&ch->io_queue);
 			/**
@@ -2426,14 +2532,13 @@ ctc_tx(struct sk_buff *skb, struct net_d
 	 * Some sanity checks ...
 	 */
 	if (skb == NULL) {
-		printk(KERN_WARNING "%s: NULL sk_buff passed\n", dev->name);
+		ctc_pr_warn("%s: NULL sk_buff passed\n", dev->name);
 		privptr->stats.tx_dropped++;
 		return 0;
 	}
 	if (skb_headroom(skb) < (LL_HEADER_LENGTH + 2)) {
-		printk(KERN_WARNING
-		       "%s: Got sk_buff with head room < %ld bytes\n",
-		       dev->name, LL_HEADER_LENGTH + 2);
+		ctc_pr_warn("%s: Got sk_buff with head room < %ld bytes\n",
+			    dev->name, LL_HEADER_LENGTH + 2);
 		dev_kfree_skb(skb);
 		privptr->stats.tx_dropped++;
 		return 0;
@@ -2505,8 +2610,6 @@ ctc_stats(struct net_device * dev)
 /*
  * sysfs attributes
  */
-#define CTRL_BUFSIZE 40
-
 static ssize_t
 buffer_show(struct device *dev, char *buf)
 {
@@ -2553,120 +2656,115 @@ buffer_write(struct device *dev, const c
 
 }
 
-static DEVICE_ATTR(buffer, 0644, buffer_show, buffer_write);
-
-static int
-ctc_add_attributes(struct device *dev)
+static ssize_t
+loglevel_show(struct device *dev, char *buf)
 {
-	return device_create_file(dev, &dev_attr_buffer);
+	struct ctc_priv *priv;
 
+	priv = dev->driver_data;
+	if (!priv)
+		return -ENODEV;
+	return sprintf(buf, "%d\n", loglevel);
 }
 
-static void
-ctc_remove_attributes(struct device *dev)
+static ssize_t
+loglevel_write(struct device *dev, const char *buf, size_t count)
 {
-	device_remove_file(dev, &dev_attr_buffer);
-
-}
+	struct ctc_priv *priv;
+	int ll1;
 
-#if 0
-/* FIXME: This has to be converted to another interface, as we can only have one
- *        value per file and can't have atomicity then */
-#define STATS_BUFSIZE 2048
+	priv = dev->driver_data;
+	if (!priv)
+		return -ENODEV;
+	sscanf(buf, "%i", &ll1);
 
-static int
-ctc_stat_open(struct inode *inode, struct file *file)
-{
-	file->private_data = kmalloc(STATS_BUFSIZE, GFP_KERNEL);
-	if (file->private_data == NULL)
-		return -ENOMEM;
-	return 0;
+	if ((ll1 > CTC_LOGLEVEL_MAX) || (ll1 < 0))
+		return -EINVAL;
+	loglevel = ll1;
+	return count;
 }
 
-static int
-ctc_stat_close(struct inode *inode, struct file *file)
+static void
+ctc_print_statistics(struct ctc_priv *priv)
 {
-	kfree(file->private_data);
-	return 0;
+	char *sbuf;
+	char *p;
+
+	if (!priv)
+		return;
+	sbuf = (char *)kmalloc(2048, GFP_KERNEL);
+	if (sbuf == NULL)
+		return;
+	p = sbuf;
+
+	p += sprintf(p, "  Device FSM state: %s\n",
+		     fsm_getstate_str(priv->fsm));
+	p += sprintf(p, "  RX channel FSM state: %s\n",
+		     fsm_getstate_str(priv->channel[READ]->fsm));
+	p += sprintf(p, "  TX channel FSM state: %s\n",
+		     fsm_getstate_str(priv->channel[WRITE]->fsm));
+	p += sprintf(p, "  Max. TX buffer used: %ld\n",
+		     priv->channel[WRITE]->prof.maxmulti);
+	p += sprintf(p, "  Max. chained SKBs: %ld\n",
+		     priv->channel[WRITE]->prof.maxcqueue);
+	p += sprintf(p, "  TX single write ops: %ld\n",
+		     priv->channel[WRITE]->prof.doios_single);
+	p += sprintf(p, "  TX multi write ops: %ld\n",
+		     priv->channel[WRITE]->prof.doios_multi);
+	p += sprintf(p, "  Netto bytes written: %ld\n",
+		     priv->channel[WRITE]->prof.txlen);
+	p += sprintf(p, "  Max. TX IO-time: %ld\n",
+		     priv->channel[WRITE]->prof.tx_time);
+
+	ctc_pr_debug("Statistics for %s:\n%s",
+		     priv->channel[WRITE]->netdev->name, sbuf);
+	kfree(sbuf);
+	return;
 }
 
 static ssize_t
-ctc_stat_write(struct file *file, const char *buf, size_t count, loff_t * off)
+stats_show(struct device *dev, char *buf)
 {
-	struct proc_dir_entry *pde = PDE(file->f_dentry->d_inode);
-	struct net_device *dev;
-	struct ctc_priv *privptr;
-
-	if (!(dev = find_netdev_by_ino(pde)))
+	struct ctc_priv *priv = dev->driver_data;
+	if (!priv)
 		return -ENODEV;
-	privptr = (struct ctc_priv *) dev->priv;
-	privptr->channel[WRITE]->prof.maxmulti = 0;
-	privptr->channel[WRITE]->prof.maxcqueue = 0;
-	privptr->channel[WRITE]->prof.doios_single = 0;
-	privptr->channel[WRITE]->prof.doios_multi = 0;
-	privptr->channel[WRITE]->prof.txlen = 0;
-	privptr->channel[WRITE]->prof.tx_time = 0;
-	return count;
+	ctc_print_statistics(priv);
+	return sprintf(buf, "0\n");
 }
 
 static ssize_t
-ctc_stat_read(struct file *file, char *buf, size_t count, loff_t * off)
+stats_write(struct device *dev, const char *buf, size_t count)
 {
-	struct proc_dir_entry *pde = PDE(file->f_dentry->d_inode);
-	char *sbuf = (char *) file->private_data;
-	struct net_device *dev;
-	struct ctc_priv *privptr;
-	ssize_t ret = 0;
-	char *p = sbuf;
-	int l;
-
-	if (!(dev = find_netdev_by_ino(pde)))
+	struct ctc_priv *priv = dev->driver_data;
+	if (!priv)
 		return -ENODEV;
-	if (off != &file->f_pos)
-		return -ESPIPE;
+	/* Reset statistics */
+	memset(&priv->channel[WRITE]->prof, 0,
+			sizeof(priv->channel[WRITE]->prof));
+	return count;
+}
 
-	privptr = (struct ctc_priv *) dev->priv;
+static DEVICE_ATTR(buffer, 0644, buffer_show, buffer_write);
+static DEVICE_ATTR(loglevel, 0644, loglevel_show, loglevel_write);
+static DEVICE_ATTR(stats, 0644, stats_show, stats_write);
 
-	if (file->f_pos == 0) {
-		p += sprintf(p, "Device FSM state: %s\n",
-			     fsm_getstate_str(privptr->fsm));
-		p += sprintf(p, "RX channel FSM state: %s\n",
-			     fsm_getstate_str(privptr->channel[READ]->fsm));
-		p += sprintf(p, "TX channel FSM state: %s\n",
-			     fsm_getstate_str(privptr->channel[WRITE]->fsm));
-		p += sprintf(p, "Max. TX buffer used: %ld\n",
-			     privptr->channel[WRITE]->prof.maxmulti);
-		p += sprintf(p, "Max. chained SKBs: %ld\n",
-			     privptr->channel[WRITE]->prof.maxcqueue);
-		p += sprintf(p, "TX single write ops: %ld\n",
-			     privptr->channel[WRITE]->prof.doios_single);
-		p += sprintf(p, "TX multi write ops: %ld\n",
-			     privptr->channel[WRITE]->prof.doios_multi);
-		p += sprintf(p, "Netto bytes written: %ld\n",
-			     privptr->channel[WRITE]->prof.txlen);
-		p += sprintf(p, "Max. TX IO-time: %ld\n",
-			     privptr->channel[WRITE]->prof.tx_time);
-	}
-	l = strlen(sbuf);
-	p = sbuf;
-	if (file->f_pos < l) {
-		p += file->f_pos;
-		l = strlen(p);
-		ret = (count > l) ? l : count;
-		if (copy_to_user(buf, p, ret))
-			return -EFAULT;
-	}
-	file->f_pos += ret;
-	return ret;
+static int
+ctc_add_attributes(struct device *dev)
+{
+	device_create_file(dev, &dev_attr_buffer);
+	device_create_file(dev, &dev_attr_loglevel);
+	device_create_file(dev, &dev_attr_stats);
+	return 0;
+}
+
+static void
+ctc_remove_attributes(struct device *dev)
+{
+	device_remove_file(dev, &dev_attr_stats);
+	device_remove_file(dev, &dev_attr_loglevel);
+	device_remove_file(dev, &dev_attr_buffer);
 }
 
-static struct file_operations ctc_stat_fops = {
-	.read    = ctc_stat_read,
-	.write   = ctc_stat_write,
-	.open    = ctc_stat_open,
-	.release = ctc_stat_close,
-};
-#endif
 
 static void
 ctc_netdev_unregister(struct net_device * dev)
@@ -2772,11 +2870,14 @@ ctc_proto_store(struct device *dev, cons
 	struct ctc_priv *priv;
 	int value;
 
+	pr_debug("%s() called\n", __FUNCTION__);
+
 	priv = dev->driver_data;
 	if (!priv)
 		return -ENODEV;
 	sscanf(buf, "%u", &value);
-	/* TODO: sanity checks */
+	if ((value < 0) || (value > CTC_PROTO_MAX))
+		return -EINVAL;
 	priv->protocol = value;
 
 	return count;
@@ -2811,12 +2912,16 @@ static struct attribute_group ctc_attr_g
 static int
 ctc_add_files(struct device *dev)
 {
+	pr_debug("%s() called\n", __FUNCTION__);
+
 	return sysfs_create_group(&dev->kobj, &ctc_attr_group);
 }
 
 static void
 ctc_remove_files(struct device *dev)
 {
+	pr_debug("%s() called\n", __FUNCTION__);
+
 	sysfs_remove_group(&dev->kobj, &ctc_attr_group);
 }
 
@@ -2835,12 +2940,14 @@ ctc_probe_device(struct ccwgroup_device 
 	struct ctc_priv *priv;
 	int rc;
 
+	pr_debug("%s() called\n", __FUNCTION__);
+
 	if (!get_device(&cgdev->dev))
 		return -ENODEV;
 
 	priv = kmalloc(sizeof (struct ctc_priv), GFP_KERNEL);
 	if (!priv) {
-		printk(KERN_ERR "%s: Out of memory\n", __func__);
+		ctc_pr_err("%s: Out of memory\n", __func__);
 		put_device(&cgdev->dev);
 		return -ENOMEM;
 	}
@@ -2879,6 +2986,9 @@ ctc_new_device(struct ccwgroup_device *c
 	enum channel_types type;
 	struct ctc_priv *privptr;
 	struct net_device *dev;
+	int ret;
+
+	pr_debug("%s() called\n", __FUNCTION__);
 
 	privptr = cgdev->dev.driver_data;
 	if (!privptr)
@@ -2894,13 +3004,22 @@ ctc_new_device(struct ccwgroup_device *c
 	if (add_channel(cgdev->cdev[1], type))
 		return -ENOMEM;
 
-	ccw_device_set_online(cgdev->cdev[0]);
-	ccw_device_set_online(cgdev->cdev[1]);	
+	ret = ccw_device_set_online(cgdev->cdev[0]);
+	if (ret != 0) {
+			printk(KERN_WARNING
+		 	"ccw_device_set_online (cdev[0]) failed with ret = %d\n", ret);
+	}
+
+	ret = ccw_device_set_online(cgdev->cdev[1]);
+	if (ret != 0) {
+			printk(KERN_WARNING
+		 	"ccw_device_set_online (cdev[1]) failed with ret = %d\n", ret);
+	}
 
 	dev = ctc_init_netdevice(NULL, 1, privptr);
 
 	if (!dev) {
-		printk(KERN_WARNING "ctc_init_netdevice failed\n");
+		ctc_pr_warn("ctc_init_netdevice failed\n");
 		goto out;
 	}
 
@@ -2928,6 +3047,22 @@ ctc_new_device(struct ccwgroup_device *c
 		ctc_free_netdevice(dev, 1);
 		goto out;
 	}
+	/* Create symlinks. */
+	if (sysfs_create_link(&cgdev->dev.kobj, &dev->class_dev.kobj,
+			      dev->name)) {
+		ctc_netdev_unregister(dev);
+		dev->priv = 0;
+		ctc_free_netdevice(dev, 1);
+		goto out;
+	}
+	if (sysfs_create_link(&dev->class_dev.kobj, &cgdev->dev.kobj,
+			      cgdev->dev.bus_id)) {
+		sysfs_remove_link(&cgdev->dev.kobj, dev->name);
+		ctc_netdev_unregister(dev);
+		dev->priv = 0;
+		ctc_free_netdevice(dev, 1);
+		goto out;
+	}
 
 	ctc_add_attributes(&cgdev->dev);
 
@@ -2935,10 +3070,9 @@ ctc_new_device(struct ccwgroup_device *c
 
 	print_banner();
 
-	printk(KERN_INFO
-	       "%s: read: %s, write: %s, proto: %d\n",
-	       dev->name, privptr->channel[READ]->id,
-	       privptr->channel[WRITE]->id, privptr->protocol);
+	ctc_pr_info("%s: read: %s, write: %s, proto: %d\n",
+		    dev->name, privptr->channel[READ]->id,
+		    privptr->channel[WRITE]->id, privptr->protocol);
 
 	return 0;
 out:
@@ -2962,32 +3096,48 @@ ctc_shutdown_device(struct ccwgroup_devi
 	struct net_device *ndev;
 		
 
+	pr_debug("%s() called\n", __FUNCTION__);
+
 	priv = cgdev->dev.driver_data;
+	ndev = NULL;
 	if (!priv)
 		return -ENODEV;
-	ndev = priv->channel[READ]->netdev;
 
-	/* Close the device */
-	ctc_close(ndev);
-	ndev->flags &=~IFF_RUNNING;
+	if (priv->channel[READ]) {
+		ndev = priv->channel[READ]->netdev;
 
-	ctc_remove_attributes(&cgdev->dev);
+		/* Close the device */
+		ctc_close(ndev);
+		ndev->flags &=~IFF_RUNNING;
 
-	channel_free(priv->channel[READ]);
-	channel_free(priv->channel[WRITE]);
+		ctc_remove_attributes(&cgdev->dev);
 
-	ctc_netdev_unregister(ndev);
-	ndev->priv = NULL;
-	ctc_free_netdevice(ndev, 1);
+		channel_free(priv->channel[READ]);
+	}
+	if (priv->channel[WRITE])
+		channel_free(priv->channel[WRITE]);
+
+	if (ndev) {
+		sysfs_remove_link(&ndev->class_dev.kobj, cgdev->dev.bus_id);
+		sysfs_remove_link(&cgdev->dev.kobj, ndev->name);
+		ctc_netdev_unregister(ndev);
+		ndev->priv = NULL;
+		ctc_free_netdevice(ndev, 1);
+	}
 
-	kfree_fsm(priv->fsm);
+	if (priv->fsm)
+		kfree_fsm(priv->fsm);
 
 	ccw_device_set_offline(cgdev->cdev[1]);
 	ccw_device_set_offline(cgdev->cdev[0]);
 
-	channel_remove(priv->channel[READ]);
-	channel_remove(priv->channel[WRITE]);
+	if (priv->channel[READ])
+		channel_remove(priv->channel[READ]);
+	if (priv->channel[WRITE])
+		channel_remove(priv->channel[WRITE]);
 	
+	priv->channel[READ] = priv->channel[WRITE] = NULL;
+
 	return 0;
 
 }
@@ -2997,6 +3147,8 @@ ctc_remove_device(struct ccwgroup_device
 {
 	struct ctc_priv *priv;
 
+	pr_debug("%s() called\n", __FUNCTION__);
+
 	priv = cgdev->dev.driver_data;
 	if (!priv)
 		return;
@@ -3033,7 +3185,7 @@ ctc_exit(void)
 {
 	unregister_cu3088_discipline(&ctc_group_driver);
 	ctc_tty_cleanup();
-	printk(KERN_INFO "CTC driver unloaded\n");
+	ctc_pr_info("CTC driver unloaded\n");
 }
 
 /**
--- diff/drivers/s390/net/ctctty.c	2004-02-09 10:36:11.000000000 +0000
+++ source/drivers/s390/net/ctctty.c	2004-02-23 13:56:45.000000000 +0000
@@ -1,5 +1,5 @@
 /*
- * $Id: ctctty.c,v 1.15 2004/01/26 10:21:01 mschwide Exp $
+ * $Id: ctctty.c,v 1.16 2004/02/05 12:39:55 felfert Exp $
  *
  * CTC / ESCON network driver, tty interface.
  *
@@ -655,14 +655,19 @@ ctc_tty_get_lsr_info(ctc_tty_info * info
 }
 
 
-static int
-ctc_tty_get_ctc_tty_info(ctc_tty_info * info, uint * value)
+static int ctc_tty_tiocmget(struct tty_struct *tty, struct file *file)
 {
+	ctc_tty_info *info = (ctc_tty_info *) tty->driver_data;
 	u_char control,
 	 status;
 	uint result;
 	ulong flags;
 
+	if (ctc_tty_paranoia_check(info, tty->name, "ctc_tty_ioctl"))
+		return -ENODEV;
+	if (tty->flags & (1 << TTY_IO_ERROR))
+		return -EIO;
+
 	control = info->mcr;
 	spin_lock_irqsave(&ctc_tty_lock, flags);
 	status = info->msr;
@@ -673,51 +678,31 @@ ctc_tty_get_ctc_tty_info(ctc_tty_info * 
 	    | ((status & UART_MSR_RI) ? TIOCM_RNG : 0)
 	    | ((status & UART_MSR_DSR) ? TIOCM_DSR : 0)
 	    | ((status & UART_MSR_CTS) ? TIOCM_CTS : 0);
-	put_user(result, (uint *) value);
-	return 0;
+	return result;
 }
 
 static int
-ctc_tty_set_ctc_tty_info(ctc_tty_info * info, uint cmd, uint * value)
+ctc_tty_tiocmset(struct tty_struct *tty, struct file *file,
+		 unsigned int set, unsigned int clear)
 {
-	uint arg;
-	int old_mcr = info->mcr & (UART_MCR_RTS | UART_MCR_DTR);
+	ctc_tty_info *info = (ctc_tty_info *) tty->driver_data;
 
-	get_user(arg, (uint *) value);
-	switch (cmd) {
-		case TIOCMBIS:
-#ifdef CTC_DEBUG_MODEM_IOCTL
-			printk(KERN_DEBUG "%s%d ioctl TIOCMBIS\n", CTC_TTY_NAME,
-			       info->line);
-#endif
-			if (arg & TIOCM_RTS)
-				info->mcr |= UART_MCR_RTS;
-			if (arg & TIOCM_DTR)
-				info->mcr |= UART_MCR_DTR;
-			break;
-		case TIOCMBIC:
-#ifdef CTC_DEBUG_MODEM_IOCTL
-			printk(KERN_DEBUG "%s%d ioctl TIOCMBIC\n", CTC_TTY_NAME,
-			       info->line);
-#endif
-			if (arg & TIOCM_RTS)
-				info->mcr &= ~UART_MCR_RTS;
-			if (arg & TIOCM_DTR)
-				info->mcr &= ~UART_MCR_DTR;
-			break;
-		case TIOCMSET:
-#ifdef CTC_DEBUG_MODEM_IOCTL
-			printk(KERN_DEBUG "%s%d ioctl TIOCMSET\n", CTC_TTY_NAME,
-			       info->line);
-#endif
-			info->mcr = ((info->mcr & ~(UART_MCR_RTS | UART_MCR_DTR))
-				 | ((arg & TIOCM_RTS) ? UART_MCR_RTS : 0)
-			       | ((arg & TIOCM_DTR) ? UART_MCR_DTR : 0));
-			break;
-		default:
-			return -EINVAL;
-	}
-	if ((info->mcr  & (UART_MCR_RTS | UART_MCR_DTR)) != old_mcr)
+	if (ctc_tty_paranoia_check(info, tty->name, "ctc_tty_ioctl"))
+		return -ENODEV;
+	if (tty->flags & (1 << TTY_IO_ERROR))
+		return -EIO;
+
+	if (set & TIOCM_RTS)
+		info->mcr |= UART_MCR_RTS;
+	if (set & TIOCM_DTR)
+		info->mcr |= UART_MCR_DTR;
+
+	if (clear & TIOCM_RTS)
+		info->mcr &= ~UART_MCR_RTS;
+	if (clear & TIOCM_DTR)
+		info->mcr &= ~UART_MCR_DTR;
+
+	if ((set | clear) & (TIOCM_RTS|TIOCM_DTR))
 		ctc_tty_transmit_status(info);
 	return 0;
 }
@@ -772,22 +757,6 @@ ctc_tty_ioctl(struct tty_struct *tty, st
 			    ((tty->termios->c_cflag & ~CLOCAL) |
 			     (arg ? CLOCAL : 0));
 			return 0;
-		case TIOCMGET:
-#ifdef CTC_DEBUG_MODEM_IOCTL
-			printk(KERN_DEBUG "%s%d ioctl TIOCMGET\n", CTC_TTY_NAME,
-			       info->line);
-#endif
-			error = verify_area(VERIFY_WRITE, (void *) arg, sizeof(uint));
-			if (error)
-				return error;
-			return ctc_tty_get_ctc_tty_info(info, (uint *) arg);
-		case TIOCMBIS:
-		case TIOCMBIC:
-		case TIOCMSET:
-			error = verify_area(VERIFY_READ, (void *) arg, sizeof(uint));
-			if (error)
-				return error;
-			return ctc_tty_set_ctc_tty_info(info, cmd, (uint *) arg);
 		case TIOCSERGETLSR:	/* Get line status register */
 #ifdef CTC_DEBUG_MODEM_IOCTL
 			printk(KERN_DEBUG "%s%d ioctl TIOCSERGETLSR\n", CTC_TTY_NAME,
@@ -1139,6 +1108,8 @@ static struct tty_operations ctc_ops = {
 	.unthrottle = ctc_tty_unthrottle,
 	.set_termios = ctc_tty_set_termios,
 	.hangup = ctc_tty_hangup,
+	.tiocmget = ctc_tty_tiocmget,
+	.tiocmset = ctc_tty_tiocmset,
 };
 
 int
@@ -1259,9 +1230,9 @@ ctc_tty_cleanup(void) {
 	
 	spin_lock_irqsave(&ctc_tty_lock, saveflags);
 	ctc_tty_shuttingdown = 1;
+	spin_unlock_irqrestore(&ctc_tty_lock, saveflags);
 	tty_unregister_driver(driver->ctc_tty_device);
 	kfree(driver);
 	put_tty_driver(driver->ctc_tty_device);
 	driver = NULL;
-	spin_unlock_irqrestore(&ctc_tty_lock, saveflags);
 }
--- diff/drivers/s390/net/iucv.c	2004-02-09 10:36:11.000000000 +0000
+++ source/drivers/s390/net/iucv.c	2004-02-23 13:56:45.000000000 +0000
@@ -1,5 +1,5 @@
 /* 
- * $Id: iucv.c,v 1.19 2003/12/18 15:28:49 braunu Exp $
+ * $Id: iucv.c,v 1.24 2004/02/05 14:16:01 braunu Exp $
  *
  * IUCV network driver
  *
@@ -29,10 +29,12 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
- * RELEASE-TAG: IUCV lowlevel driver $Revision: 1.19 $
+ * RELEASE-TAG: IUCV lowlevel driver $Revision: 1.24 $
  *
  */
 
+/* #define DEBUG */
+
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <linux/config.h>
@@ -53,8 +55,6 @@
 #include <asm/ebcdic.h>
 #include <asm/ccwdev.h> //for root device stuff
 
-#define DEBUG
-
 /* FLAGS:
  * All flags are defined in the field IPFLAGS1 of each function
  * and can be found in CP Programming Services.
@@ -104,6 +104,8 @@ static iucv_GeneralInterrupt *iucv_exter
 
 static spinlock_t iucv_lock = SPIN_LOCK_UNLOCKED;
 
+static int messagesDisabled = 0;
+
 /***************INTERRUPT HANDLING ***************/
 
 typedef struct {
@@ -349,7 +351,7 @@ do { \
 static void
 iucv_banner(void)
 {
-	char vbuf[] = "$Revision: 1.19 $";
+	char vbuf[] = "$Revision: 1.24 $";
 	char *version = vbuf;
 
 	if ((version = strchr(version, ':'))) {
@@ -433,10 +435,13 @@ iucv_init(void)
  *
  * Frees everything allocated from iucv_init.
  */
+static int iucv_retrieve_buffer (void);
+
 static void
 iucv_exit(void)
 {
-	if (iucv_external_int_buffer)
+	iucv_retrieve_buffer();
+      	if (iucv_external_int_buffer)
 		kfree(iucv_external_int_buffer);
 	if (iucv_param_pool)
 		kfree(iucv_param_pool);
@@ -716,7 +721,6 @@ iucv_remove_handler(handler *handler)
 	spin_lock_irqsave (&iucv_lock, flags);
 	list_del(&handler->list);
 	if (list_empty(&iucv_handler_table)) {
-		iucv_retrieve_buffer();
 		if (register_flag) {
 			unregister_external_interrupt(0x4000, iucv_irq_handler);
 			register_flag = 0;
@@ -1028,6 +1032,8 @@ iucv_accept(__u16 pathid, __u16 msglim_r
 	b2f0_result = b2f0(ACCEPT, parm);
 
 	if (b2f0_result == 0) {
+		if (msglim)
+			*msglim = parm->ipmsglim;
 		if (pgm_data)
 			h->pgm_data = pgm_data;
 		if (flags1_out)
@@ -1083,6 +1089,7 @@ iucv_connect (__u16 *pathid, __u16 msgli
 	      iucv_handle_t handle, void *pgm_data)
 {
 	iparml_control *parm;
+	iparml_control local_parm;
 	struct list_head *lh;
 	ulong b2f0_result = 0;
 	ulong flags;
@@ -1139,27 +1146,53 @@ iucv_connect (__u16 *pathid, __u16 msgli
 		EBC_TOUPPER(parm->iptarget, sizeof(parm->iptarget));
 	}
 
+	/* In order to establish an IUCV connection, the procedure is:
+         *
+         * b2f0(CONNECT)
+         * take the ippathid from the b2f0 call
+         * register the handler to the ippathid
+         *
+         * Unfortunately, the ConnectionEstablished message gets sent after the
+         * b2f0(CONNECT) call but before the register is handled.
+         *
+         * In order for this race condition to be eliminated, the IUCV Control
+         * Interrupts must be disabled for the above procedure.
+         *
+         * David Kennedy <dkennedy@linuxcare.com>
+         */
+
+	/* Enable everything but IUCV Control messages */
+	iucv_setmask(~(AllInterrupts));
+	messagesDisabled = 1;
+
 	spin_lock_irqsave (&iucv_lock, flags);
 	parm->ipflags1 = (__u8)flags1;
 	b2f0_result = b2f0(CONNECT, parm);
+	memcpy(&local_parm, parm, sizeof(local_parm));
+	release_param(parm);
+	parm = &local_parm;
 	if (b2f0_result == 0)
 		add_pathid_result = __iucv_add_pathid(parm->ippathid, h);
 	spin_unlock_irqrestore (&iucv_lock, flags);
 
 	if (b2f0_result) {
-		release_param(parm);
+		iucv_setmask(~0);
+		messagesDisabled = 0;
 		return b2f0_result;
 	}
 
 	*pathid = parm->ippathid;
 
+	/* Enable everything again */
+	iucv_setmask(IUCVControlInterruptsFlag);
+
 	if (msglim)
 		*msglim = parm->ipmsglim;
 	if (flags1_out)
 		*flags1_out = (parm->ipflags1 & IPPRTY) ? IPPRTY : 0;
 
 	if (add_pathid_result) {
-		iucv_sever(parm->ippathid, no_memory);
+		iucv_sever(*pathid, no_memory);
 		printk(KERN_WARNING "%s: add_pathid failed with rc ="
 			" %d\n", __FUNCTION__, add_pathid_result);
 		return(add_pathid_result);
@@ -2142,6 +2175,24 @@ iucv_send2way_prmmsg_array (__u16 pathid
 	return b2f0_result;
 }
 
+void
+iucv_setmask_cpu0 (void *result)
+{
+        iparml_set_mask *parm;
+
+        if (smp_processor_id() != 0)
+                return;
+
+        iucv_debug(1, "entering");
+        parm = (iparml_set_mask *)grab_param();
+        parm->ipmask = *((__u8*)result);
+        *((ulong *)result) = b2f0(SETMASK, parm);
+        release_param(parm);
+
+        iucv_debug(1, "b2f0_result = %ld", *((ulong *)result));
+        iucv_debug(1, "exiting");
+}
+
 /*
  * Name: iucv_setmask
  * Purpose: This function enables or disables the following IUCV
@@ -2152,28 +2203,25 @@ iucv_send2way_prmmsg_array (__u16 pathid
  *           0x40 - Priority_MessagePendingInterruptsFlag
  *           0x20 - Nonpriority_MessageCompletionInterruptsFlag
  *           0x10 - Priority_MessageCompletionInterruptsFlag
+ *           0x08 - IUCVControlInterruptsFlag
  * Output: NA
  * Return: b2f0_result - return code from CP
 */
 int
 iucv_setmask (int SetMaskFlag)
 {
-	iparml_set_mask *parm;
-	ulong b2f0_result = 0;
-
-	iucv_debug(1, "entering");
-
-	parm = (iparml_set_mask *)grab_param();
-
-	parm->ipmask = (__u8)SetMaskFlag;
-
-	b2f0_result = b2f0(SETMASK, parm);
-	release_param(parm);
+	union {
+		ulong result;
+		__u8  param;
+	} u;
 
-	iucv_debug(1, "b2f0_result = %ld", b2f0_result);
-	iucv_debug(1, "exiting");
+	u.param = SetMaskFlag;
+	if (smp_processor_id() == 0)
+		iucv_setmask_cpu0(&u);
+	else
+		smp_call_function(iucv_setmask_cpu0, &u, 0, 1);
 
-	return b2f0_result;
+	return u.result;
 }
 
 /**
@@ -2280,6 +2328,10 @@ iucv_do_int(iucv_GeneralInterrupt * int_
 	/* end of if statement */
 	switch (int_buf->iptype) {
 		case 0x01:		/* connection pending */
+			if (messagesDisabled) {
+			    iucv_setmask(~0);
+			    messagesDisabled = 0;
+			}
 			spin_lock_irqsave(&iucv_lock, flags);
 			list_for_each(lh, &iucv_handler_table) {
 				h = list_entry(lh, handler, list);
@@ -2328,11 +2380,17 @@ iucv_do_int(iucv_GeneralInterrupt * int_
 			break;
 			
 		case 0x02:		/*connection complete */
+			if (messagesDisabled) {
+			    iucv_setmask(~0);
+			    messagesDisabled = 0;
+			}
 			if (h) {
 				if (interrupt->ConnectionComplete)
+				{
 					interrupt->ConnectionComplete(
 						(iucv_ConnectionComplete *)int_buf,
 						h->pgm_data);
+				}
 				else
 					iucv_debug(1,
 						   "ConnectionComplete not called");
@@ -2341,6 +2399,10 @@ iucv_do_int(iucv_GeneralInterrupt * int_
 			break;
 			
 		case 0x03:		/* connection severed */
+			if (messagesDisabled) {
+			    iucv_setmask(~0);
+			    messagesDisabled = 0;
+			}
 			if (h) {
 				if (interrupt->ConnectionSevered)
 					interrupt->ConnectionSevered(
@@ -2354,6 +2416,10 @@ iucv_do_int(iucv_GeneralInterrupt * int_
 			break;
 			
 		case 0x04:		/* connection quiesced */
+			if (messagesDisabled) {
+			    iucv_setmask(~0);
+			    messagesDisabled = 0;
+			}
 			if (h) {
 				if (interrupt->ConnectionQuiesced)
 					interrupt->ConnectionQuiesced(
@@ -2366,6 +2432,10 @@ iucv_do_int(iucv_GeneralInterrupt * int_
 			break;
 			
 		case 0x05:		/* connection resumed */
+			if (messagesDisabled) {
+			    iucv_setmask(~0);
+			    messagesDisabled = 0;
+			}
 			if (h) {
 				if (interrupt->ConnectionResumed)
 					interrupt->ConnectionResumed(
@@ -2467,7 +2537,9 @@ EXPORT_SYMBOL (iucv_quiesce);
 EXPORT_SYMBOL (iucv_receive);
 #if 0
 EXPORT_SYMBOL (iucv_receive_array);
+#endif
 EXPORT_SYMBOL (iucv_reject);
+#if 0
 EXPORT_SYMBOL (iucv_reply);
 EXPORT_SYMBOL (iucv_reply_array);
 EXPORT_SYMBOL (iucv_reply_prmmsg);
--- diff/drivers/s390/net/iucv.h	2004-02-09 10:36:11.000000000 +0000
+++ source/drivers/s390/net/iucv.h	2004-02-23 13:56:45.000000000 +0000
@@ -62,6 +62,8 @@
 #define Priority_MessagePendingInterruptsFlag            0x40
 #define Nonpriority_MessageCompletionInterruptsFlag      0x20
 #define Priority_MessageCompletionInterruptsFlag         0x10
+#define IUCVControlInterruptsFlag                        0x08
+#define AllInterrupts                                    0xf8
 /*
  * Mapping of external interrupt buffers should be used with the corresponding
  * interrupt types.                  
@@ -738,6 +740,7 @@ int iucv_send2way_prmmsg_array (u16 path
  *           0x40 - Priority_MessagePendingInterruptsFlag            
  *           0x20 - Nonpriority_MessageCompletionInterruptsFlag      
  *           0x10 - Priority_MessageCompletionInterruptsFlag         
+ *           0x08 - IUCVControlInterruptsFlag
  * Output: NA                                                        
  * Return: Return code from CP IUCV call.                         
 */
--- diff/drivers/s390/net/lcs.c	2004-02-09 10:36:11.000000000 +0000
+++ source/drivers/s390/net/lcs.c	2004-02-23 13:56:45.000000000 +0000
@@ -11,7 +11,7 @@
  *			  Frank Pavlic (pavlic@de.ibm.com) and
  *		 	  Martin Schwidefsky <schwidefsky@de.ibm.com>
  *
- *    $Revision: 1.61 $	 $Date: 2003/12/02 15:18:50 $
+ *    $Revision: 1.66 $	 $Date: 2004/02/19 13:46:01 $
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -58,7 +58,7 @@
 /**
  * initialization string for output
  */
-#define VERSION_LCS_C  "$Revision: 1.61 $"
+#define VERSION_LCS_C  "$Revision: 1.66 $"
 
 static char version[] __initdata = "LCS driver ("VERSION_LCS_C "/" VERSION_LCS_H ")";
 
@@ -100,7 +100,7 @@ lcs_register_debug_facility(void)
 	debug_register_view(lcs_dbf_setup, &debug_hex_ascii_view);
 	debug_set_level(lcs_dbf_setup, 5);
 	debug_register_view(lcs_dbf_trace, &debug_hex_ascii_view);
-	debug_set_level(lcs_dbf_trace, 3);
+	debug_set_level(lcs_dbf_trace, 5);
 	return 0;
 }
 
@@ -141,8 +141,11 @@ lcs_free_channel(struct lcs_channel *cha
 	int cnt;
 
 	LCS_DBF_TEXT(3, setup, "ichfree");
-	for (cnt = 0; cnt < LCS_NUM_BUFFS; cnt++)
-		kfree(channel->iob[cnt].data);
+	for (cnt = 0; cnt < LCS_NUM_BUFFS; cnt++) {
+		if (channel->iob[cnt].data != NULL)
+			kfree(channel->iob[cnt].data);
+		channel->iob[cnt].data = NULL;
+	}
 }
 
 /**
@@ -360,7 +363,8 @@ lcs_cleanup_card(struct lcs_card *card)
 		kfree(ipm_list);
 	}
 #endif
-	kfree(card->dev);
+	if (card->dev != NULL)
+		free_netdev(card->dev);
 	/* Cleanup channels. */
 	lcs_cleanup_channel(&card->write);
 	lcs_cleanup_channel(&card->read);
@@ -672,6 +676,7 @@ lcs_send_lancmd(struct lcs_card *card, s
 	struct lcs_cmd *cmd;
 	struct timer_list timer;
 	int rc;
+	char buf[16];
 
 	cmd = (struct lcs_cmd *) buffer->data;
 	cmd->sequence_no = ++card->sequence_no;
@@ -695,6 +700,9 @@ lcs_send_lancmd(struct lcs_card *card, s
 	add_timer(&timer);
 	wait_event(reply.wait_q, reply.received);
 	del_timer(&timer);
+	LCS_DBF_TEXT(5, trace, "sendcmd");
+	sprintf(buf, "rc:%d", reply.rc);
+	LCS_DBF_TEXT(5, trace, buf);
 	return reply.rc ? -EIO : 0;
 }
 
@@ -794,7 +802,7 @@ lcs_send_startlan(struct lcs_card *card,
 	struct lcs_buffer *buffer;
 	struct lcs_cmd *cmd;
 
-	LCS_DBF_TEXT(2, trace, "cmdstpln");
+	LCS_DBF_TEXT(2, trace, "cmdstaln");
 	buffer = lcs_get_lancmd(card, LCS_STD_CMD_SIZE);
 	cmd = (struct lcs_cmd *) buffer->data;
 	cmd->cmd_code = LCS_CMD_STARTLAN;
@@ -1042,7 +1050,8 @@ lcs_irq(struct ccw_device *cdev, unsigne
 	LCS_DBF_TEXT(5, trace, dbf_text);
 
 	/* How far in the ccw chain have we processed? */
-	if (channel->state != CH_STATE_INIT) {
+	if ((channel->state != CH_STATE_INIT) &&
+	    (irb->scsw.fctl & SCSW_FCTL_START_FUNC)) {
 		index = (struct ccw1 *) __va((addr_t) irb->scsw.cpa) 
 			- channel->ccws;
 		if ((irb->scsw.actl & SCSW_ACTL_SUSPENDED) ||
@@ -1066,9 +1075,14 @@ lcs_irq(struct ccw_device *cdev, unsigne
 		/* CCW execution stopped on a suspend bit. */
 		channel->state = CH_STATE_SUSPENDED;
 
-	if (irb->scsw.fctl & SCSW_FCTL_HALT_FUNC)
+	if (irb->scsw.fctl & SCSW_FCTL_HALT_FUNC) {
+		if (irb->scsw.cc != 0) {
+			ccw_device_halt(channel->ccwdev, (addr_t) channel);
+			return;
+		}
 		/* The channel has been stopped by halt_IO. */
 		channel->state = CH_STATE_HALTED;
+	}
 
 	/* Do the rest in the tasklet. */
 	tasklet_schedule(&channel->irq_tasklet);
@@ -1267,7 +1281,7 @@ lcs_startlan(struct lcs_card *card)
 		else
 			rc = lcs_send_startlan(card, LCS_INITIATOR_TCPIP);
 	} else {
-                for (i = 0; i <= card->max_port_no; i++) {
+                for (i = 0; i <= 16; i++) {
                         card->portno = i;
                         if (card->lan_type != LCS_FRAME_TYPE_AUTO)
                                 rc = lcs_send_startlan(card,
@@ -1291,7 +1305,7 @@ lcs_startlan(struct lcs_card *card)
 static int
 lcs_detect(struct lcs_card *card)
 {
-	int rc;
+	int rc = 0;
 
 	LCS_DBF_TEXT(3, setup," lcsdetct");
 	/* start/reset card */
@@ -1790,7 +1804,6 @@ lcs_new_device(struct ccwgroup_device *c
 	if (rc) {
 		LCS_DBF_TEXT(3, setup, "errinit");
 		PRINT_ERR("LCS card Initialization failed\n");
-		lcs_free_card(card);
 		return rc;
 	}
 
@@ -1798,7 +1811,6 @@ lcs_new_device(struct ccwgroup_device *c
 	if (rc) {
 		lcs_stopcard(card);
 		lcs_cleanup_card(card);
-		lcs_free_card(card);
 		return -ENODEV;
 	}
 	switch (card->lan_type) {
@@ -1858,9 +1870,7 @@ lcs_new_device(struct ccwgroup_device *c
 	lcs_stopcard(card);
 	return 0;
 out:
-	lcs_cleanup_channel(&card->read);
-	lcs_cleanup_channel(&card->write);
-	lcs_free_card(card);
+	lcs_cleanup_card(card);
 	return -ENODEV;
 }
 
@@ -1933,9 +1943,9 @@ __init lcs_init_module(void)
 {
 	int rc;
 
-	LCS_DBF_TEXT(0, setup, "lcsinit");
 	PRINT_INFO("Loading %s\n",version);
 	rc = lcs_register_debug_facility();
+	LCS_DBF_TEXT(0, setup, "lcsinit");
 	if (rc) {
 		PRINT_ERR("Initialization failed\n");
 		return rc;
--- diff/drivers/s390/net/netiucv.c	2004-02-09 10:36:11.000000000 +0000
+++ source/drivers/s390/net/netiucv.c	2004-02-23 13:56:45.000000000 +0000
@@ -1,5 +1,5 @@
 /*
- * $Id: netiucv.c,v 1.30 2003/12/02 12:29:32 braunu Exp $
+ * $Id: netiucv.c,v 1.38 2004/02/19 13:12:57 mschwide Exp $
  *
  * IUCV network driver
  *
@@ -30,10 +30,12 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
- * RELEASE-TAG: IUCV network driver $Revision: 1.30 $
+ * RELEASE-TAG: IUCV network driver $Revision: 1.38 $
  *
  */
 
+#undef DEBUG
+
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
@@ -62,8 +64,6 @@
 #include "iucv.h"
 #include "fsm.h"
 
-#undef DEBUG
-
 MODULE_AUTHOR
     ("(C) 2001 IBM Corporation by Fritz Elfert (felfert@millenux.com)");
 MODULE_DESCRIPTION ("Linux for S/390 IUCV network driver");
@@ -80,6 +80,8 @@ struct connection_profile {
 	unsigned long txlen;
 	unsigned long tx_time;
 	struct timespec send_stamp;
+	unsigned long tx_pending;
+	unsigned long tx_max_pending;
 };
 
 /**
@@ -92,6 +94,7 @@ struct iucv_connection {
 	struct sk_buff            *rx_buff;
 	struct sk_buff            *tx_buff;
 	struct sk_buff_head       collect_queue;
+	struct sk_buff_head	  commit_queue;
 	spinlock_t                collect_lock;
 	int                       collect_len;
 	int                       max_buffsize;
@@ -131,7 +134,8 @@ struct netiucv_priv {
 	unsigned long           tbusy;
 	fsm_instance            *fsm;
         struct iucv_connection  *conn;
-	struct device           dev;
+	struct device           *dev;
+	fsm_timer               timer;
 };
 
 /**
@@ -213,6 +217,7 @@ enum dev_states {
 	DEV_STATE_STARTWAIT,
 	DEV_STATE_STOPWAIT,
 	DEV_STATE_RUNNING,
+	DEV_STATE_STARTRETRY,
 	/**
 	 * MUST be always the last element!!
 	 */
@@ -234,6 +239,7 @@ enum dev_events {
 	DEV_EVENT_STOP,
 	DEV_EVENT_CONUP,
 	DEV_EVENT_CONDOWN,
+	DEV_EVENT_TIMER,
 	/**
 	 * MUST be always the last element!!
 	 */
@@ -530,7 +536,11 @@ netiucv_unpack_skb(struct iucv_connectio
 		skb->dev = pskb->dev;
 		skb->protocol = pskb->protocol;
 		pskb->ip_summed = CHECKSUM_UNNECESSARY;
-		netif_rx(skb);
+		/*
+		 * Since receiving is always initiated from a tasklet (in iucv.c),
+		 * we must use netif_rx_ni() instead of netif_rx()
+		 */
+		netif_rx_ni(skb);
 		dev->last_rx = jiffies;
 		privptr->stats.rx_packets++;
 		privptr->stats.rx_bytes += skb->len;
@@ -582,10 +592,11 @@ conn_action_txdone(fsm_instance *fi, int
 	iucv_MessageComplete *eib = (iucv_MessageComplete *)ev->data;
 	struct netiucv_priv *privptr = NULL;
 			         /* Shut up, gcc! skb is always below 2G. */
-	struct sk_buff *skb = (struct sk_buff *)(unsigned long)eib->ipmsgtag;
+	__u32 single_flag = eib->ipmsgtag;
 	__u32 txbytes = 0;
 	__u32 txpackets = 0;
 	__u32 stat_maxcq = 0;
+	struct sk_buff *skb;
 	unsigned long saveflags;
 	ll_header header;
 
@@ -594,13 +605,17 @@ conn_action_txdone(fsm_instance *fi, int
 	fsm_deltimer(&conn->timer);
 	if (conn && conn->netdev && conn->netdev->priv)
 		privptr = (struct netiucv_priv *)conn->netdev->priv;
-	if (skb) {
+	conn->prof.tx_pending--;
+	if (single_flag) {
+		if ((skb = skb_dequeue(&conn->commit_queue))) {
+			atomic_dec(&skb->users);
+			dev_kfree_skb_any(skb);
+		}
 		if (privptr) {
 			privptr->stats.tx_packets++;
 			privptr->stats.tx_bytes +=
 				(skb->len - NETIUCV_HDRLEN - NETIUCV_HDRLEN);
 		}
-		dev_kfree_skb_any(skb);
 	}
 	conn->tx_buff->data = conn->tx_buff->tail = conn->tx_buff->head;
 	conn->tx_buff->len = 0;
@@ -634,11 +649,17 @@ conn_action_txdone(fsm_instance *fi, int
 			       conn->tx_buff->data, conn->tx_buff->len);
 		conn->prof.doios_multi++;
 		conn->prof.txlen += conn->tx_buff->len;
+		conn->prof.tx_pending++;
+		if (conn->prof.tx_pending > conn->prof.tx_max_pending)
+			conn->prof.tx_max_pending = conn->prof.tx_pending;
 		if (rc != 0) {
 			fsm_deltimer(&conn->timer);
+			conn->prof.tx_pending--;
 			fsm_newstate(fi, CONN_STATE_IDLE);
 			if (privptr)
 				privptr->stats.tx_errors += txpackets;
+			printk(KERN_DEBUG "iucv_send returned %08x\n",
+				rc);
 		} else {
 			if (privptr) {
 				privptr->stats.tx_packets += txpackets;
@@ -722,6 +743,12 @@ conn_action_connsever(fsm_instance *fi, 
 	pr_debug("%s() called\n", __FUNCTION__);
 
 	switch (state) {
+		case CONN_STATE_SETUPWAIT:
+			printk(KERN_INFO "%s: Remote dropped connection\n",
+			       netdev->name);
+			fsm_newstate(fi, CONN_STATE_STOPPED);
+			fsm_event(privptr->fsm, DEV_EVENT_CONDOWN, netdev);
+			break;
 		case CONN_STATE_IDLE:
 		case CONN_STATE_TX:
 			printk(KERN_INFO "%s: Remote dropped connection\n",
@@ -763,10 +790,14 @@ conn_action_start(fsm_instance *fi, int 
 	pr_debug("%s('%s'): connecting ...\n",
 		 conn->netdev->name, conn->userid);
 
+	/* We must set the state before calling iucv_connect because the callback
+	 * handler could be called at any point after the connection request is
+	 * sent */
+
+	fsm_newstate(fi, CONN_STATE_SETUPWAIT);
 	rc = iucv_connect(&(conn->pathid), NETIUCV_QUEUELEN_DEFAULT, iucvMagic,
 			  conn->userid, iucv_host, 0, NULL, NULL, conn->handle,
 			  conn);
-	fsm_newstate(fi, CONN_STATE_SETUPWAIT);
 	switch (rc) {
 		case 0:
 			return;
@@ -840,6 +871,7 @@ conn_action_stop(fsm_instance *fi, int e
 	if (conn->handle)
 		iucv_unregister_program(conn->handle);
 	conn->handle = 0;
+	netiucv_purge_skb_queue(&conn->commit_queue);
 	fsm_event(privptr->fsm, DEV_EVENT_CONDOWN, netdev);
 }
 
@@ -860,6 +892,7 @@ static const fsm_node conn_fsm[] = {
 	{ CONN_STATE_STOPPED,   CONN_EVENT_START,    conn_action_start      },
 	{ CONN_STATE_STARTWAIT, CONN_EVENT_START,    conn_action_start      },
 
+	{ CONN_STATE_STOPPED,   CONN_EVENT_STOP,     conn_action_stop       },
 	{ CONN_STATE_STARTWAIT, CONN_EVENT_STOP,     conn_action_stop       },
 	{ CONN_STATE_SETUPWAIT, CONN_EVENT_STOP,     conn_action_stop       },
 	{ CONN_STATE_IDLE,      CONN_EVENT_STOP,     conn_action_stop       },
@@ -883,6 +916,7 @@ static const fsm_node conn_fsm[] = {
 	{ CONN_STATE_TX,        CONN_EVENT_RX,       conn_action_rx         },
 
 	{ CONN_STATE_TX,        CONN_EVENT_TXDONE,   conn_action_txdone     },
+	{ CONN_STATE_IDLE,      CONN_EVENT_TXDONE,   conn_action_txdone     },
 };
 
 static const int CONN_FSM_LEN = sizeof(conn_fsm) / sizeof(fsm_node);
@@ -908,6 +942,7 @@ dev_action_start(fsm_instance *fi, int e
 
 	pr_debug("%s() called\n", __FUNCTION__);
 
+	fsm_deltimer(&privptr->timer);
 	ev.conn = privptr->conn;
 	fsm_newstate(fi, DEV_STATE_STARTWAIT);
 	fsm_event(privptr->conn->fsm, CONN_EVENT_START, &ev);
@@ -931,6 +966,7 @@ dev_action_stop(fsm_instance *fi, int ev
 
 	ev.conn = privptr->conn;
 
+	fsm_deltimer(&privptr->timer);
 	fsm_newstate(fi, DEV_STATE_STOPWAIT);
 	fsm_event(privptr->conn->fsm, CONN_EVENT_STOP, &ev);
 }
@@ -947,10 +983,13 @@ static void
 dev_action_connup(fsm_instance *fi, int event, void *arg)
 {
 	struct net_device   *dev = (struct net_device *)arg;
+	struct netiucv_priv *privptr = dev->priv;
 
 	pr_debug("%s() called\n", __FUNCTION__);
 
 	switch (fsm_getstate(fi)) {
+		case DEV_STATE_STARTRETRY:
+			fsm_deltimer(&privptr->timer);
 		case DEV_STATE_STARTWAIT:
 			fsm_newstate(fi, DEV_STATE_RUNNING);
 			printk(KERN_INFO
@@ -989,6 +1028,9 @@ dev_action_conndown(fsm_instance *fi, in
 			fsm_event(privptr->conn->fsm, CONN_EVENT_START, &ev);
 			break;
 		case DEV_STATE_STARTWAIT:
+			fsm_addtimer(&privptr->timer, NETIUCV_TIMEOUT_5SEC,
+				     DEV_EVENT_TIMER, dev);
+			fsm_newstate(fi, DEV_STATE_STARTRETRY);
 			break;
 		case DEV_STATE_STOPWAIT:
 			fsm_newstate(fi, DEV_STATE_STOPPED);
@@ -997,18 +1039,22 @@ dev_action_conndown(fsm_instance *fi, in
 }
 
 static const fsm_node dev_fsm[] = {
-	{ DEV_STATE_STOPPED,   DEV_EVENT_START,   dev_action_start    },
+	{ DEV_STATE_STOPPED,    DEV_EVENT_START,   dev_action_start    },
 
-	{ DEV_STATE_STOPWAIT,  DEV_EVENT_START,   dev_action_start    },
-	{ DEV_STATE_STOPWAIT,  DEV_EVENT_CONDOWN, dev_action_conndown },
+	{ DEV_STATE_STOPWAIT,   DEV_EVENT_START,   dev_action_start    },
+	{ DEV_STATE_STOPWAIT,   DEV_EVENT_CONDOWN, dev_action_conndown },
 
-	{ DEV_STATE_STARTWAIT, DEV_EVENT_STOP,    dev_action_stop     },
-	{ DEV_STATE_STARTWAIT, DEV_EVENT_CONUP,   dev_action_connup   },
-	{ DEV_STATE_STARTWAIT, DEV_EVENT_CONDOWN, dev_action_conndown },
-
-	{ DEV_STATE_RUNNING,   DEV_EVENT_STOP,    dev_action_stop     },
-	{ DEV_STATE_RUNNING,   DEV_EVENT_CONDOWN, dev_action_conndown },
-	{ DEV_STATE_RUNNING,   DEV_EVENT_CONUP,   fsm_action_nop      },
+	{ DEV_STATE_STARTWAIT,  DEV_EVENT_STOP,    dev_action_stop     },
+	{ DEV_STATE_STARTWAIT,  DEV_EVENT_CONUP,   dev_action_connup   },
+	{ DEV_STATE_STARTWAIT,  DEV_EVENT_CONDOWN, dev_action_conndown },
+
+	{ DEV_STATE_STARTRETRY, DEV_EVENT_TIMER,   dev_action_start    },
+	{ DEV_STATE_STARTRETRY, DEV_EVENT_CONUP,   dev_action_connup   },
+	{ DEV_STATE_STARTRETRY, DEV_EVENT_STOP,    dev_action_stop     },
+
+	{ DEV_STATE_RUNNING,    DEV_EVENT_STOP,    dev_action_stop     },
+	{ DEV_STATE_RUNNING,    DEV_EVENT_CONDOWN, dev_action_conndown },
+	{ DEV_STATE_RUNNING,    DEV_EVENT_CONUP,   fsm_action_nop      },
 };
 
 static const int DEV_FSM_LEN = sizeof(dev_fsm) / sizeof(fsm_node);
@@ -1081,14 +1127,22 @@ netiucv_transmit_skb(struct iucv_connect
 			     CONN_EVENT_TIMER, conn);
 		conn->prof.send_stamp = xtime;
 		
-		rc = iucv_send(conn->pathid, NULL, 0, 0,
+		rc = iucv_send(conn->pathid, NULL, 0, 0, 1 /* single_flag */,
+			0, nskb->data, nskb->len);
 			       /* Shut up, gcc! nskb is always below 2G. */
-			       (__u32)(((unsigned long)nskb)&0xffffffff), 0,
-			       nskb->data, nskb->len);
 		conn->prof.doios_single++;
 		conn->prof.txlen += skb->len;
+		conn->prof.tx_pending++;
+		if (conn->prof.tx_pending > conn->prof.tx_max_pending)
+			conn->prof.tx_max_pending = conn->prof.tx_pending;
 		if (rc != 0) {
+			struct netiucv_priv *privptr;
 			fsm_deltimer(&conn->timer);
+			fsm_newstate(conn->fsm, CONN_STATE_IDLE);
+			conn->prof.tx_pending--;
+			privptr = (struct netiucv_priv *)conn->netdev->priv;
+			if (privptr)
+				privptr->stats.tx_errors++;
 			if (copied)
 				dev_kfree_skb(nskb);
 			else {
@@ -1099,9 +1153,13 @@ netiucv_transmit_skb(struct iucv_connect
 				skb_pull(skb, NETIUCV_HDRLEN);
 				skb_trim(skb, skb->len - NETIUCV_HDRLEN);
 			}
+			printk(KERN_DEBUG "iucv_send returned %08x\n",
+				rc);
 		} else {
 			if (copied)
 				dev_kfree_skb(skb);
+			atomic_inc(&nskb->users);
+			skb_queue_tail(&conn->commit_queue, nskb);
 		}
 	}
 
@@ -1256,8 +1314,7 @@ static ssize_t
 buffer_write (struct device *dev, const char *buf, size_t count)
 {
 	struct netiucv_priv *priv = dev->driver_data;
-	struct net_device *ndev =
-		container_of((void *)priv, struct net_device, priv);
+	struct net_device *ndev = priv->conn->netdev;
 	char         *e;
 	int          bs1;
 	char         tmp[CTRL_BUFSIZE];
@@ -1266,7 +1323,7 @@ buffer_write (struct device *dev, const 
 		return -EINVAL;
 
 	if (copy_from_user(tmp, buf, count))
-		return -EFAULT;
+		 return -EFAULT;
 	tmp[count+1] = '\0';
 	bs1 = simple_strtoul(tmp, &e, 0);
 
@@ -1425,6 +1482,44 @@ txtime_write (struct device *dev, const 
 
 static DEVICE_ATTR(max_tx_io_time, 0644, txtime_show, txtime_write);
 
+static ssize_t
+txpend_show (struct device *dev, char *buf)
+{
+	struct netiucv_priv *priv = dev->driver_data;
+
+	return sprintf(buf, "%ld\n", priv->conn->prof.tx_pending);
+}
+
+static ssize_t
+txpend_write (struct device *dev, const char *buf, size_t count)
+{
+	struct netiucv_priv *priv = dev->driver_data;
+
+	priv->conn->prof.tx_pending = 0;
+	return count;
+}
+
+static DEVICE_ATTR(tx_pending, 0644, txpend_show, txpend_write);
+
+static ssize_t
+txmpnd_show (struct device *dev, char *buf)
+{
+	struct netiucv_priv *priv = dev->driver_data;
+
+	return sprintf(buf, "%ld\n", priv->conn->prof.tx_max_pending);
+}
+
+static ssize_t
+txmpnd_write (struct device *dev, const char *buf, size_t count)
+{
+	struct netiucv_priv *priv = dev->driver_data;
+
+	priv->conn->prof.tx_max_pending = 0;
+	return count;
+}
+
+static DEVICE_ATTR(tx_max_pending, 0644, txmpnd_show, txmpnd_write);
+
 static struct attribute *netiucv_attrs[] = {
 	&dev_attr_buffer.attr,
 	&dev_attr_user.attr,
@@ -1444,6 +1539,8 @@ static struct attribute *netiucv_stat_at
 	&dev_attr_tx_multi_write_ops.attr,
 	&dev_attr_netto_bytes.attr,
 	&dev_attr_max_tx_io_time.attr,
+	&dev_attr_tx_pending.attr,
+	&dev_attr_tx_max_pending.attr,
 	NULL,
 };
 
@@ -1457,6 +1554,8 @@ netiucv_add_files(struct device *dev)
 {
 	int ret;
 
+	pr_debug("%s() called\n", __FUNCTION__);
+
 	ret = sysfs_create_group(&dev->kobj, &netiucv_attr_group);
 	if (ret)
 		return ret;
@@ -1469,6 +1568,7 @@ netiucv_add_files(struct device *dev)
 static inline void
 netiucv_remove_files(struct device *dev)
 {
+	pr_debug("%s() called\n", __FUNCTION__);
 	sysfs_remove_group(&dev->kobj, &netiucv_stat_attr_group);
 	sysfs_remove_group(&dev->kobj, &netiucv_attr_group);
 }
@@ -1477,34 +1577,63 @@ static int
 netiucv_register_device(struct net_device *ndev, int ifno)
 {
 	struct netiucv_priv *priv = ndev->priv;
-	struct device *dev = &priv->dev;
+	struct device *dev = kmalloc(sizeof(struct device), GFP_KERNEL);
 	int ret;
-	char *str = "netiucv";
 
-	snprintf(dev->bus_id, BUS_ID_SIZE, "%s%x", str, ifno);
-	dev->bus = &iucv_bus;
-	dev->parent = iucv_root;
+
+	pr_debug("%s() called\n", __FUNCTION__);
+
+	if (dev) {
+		memset(dev, 0, sizeof(struct device));
+		snprintf(dev->bus_id, BUS_ID_SIZE, "netiucv%x", ifno);
+		dev->bus = &iucv_bus;
+		dev->parent = iucv_root;
+		/*
+		 * The release function could be called after the
+		 * module has been unloaded. It's _only_ task is to
+		 * free the struct. Therefore, we specify kfree()
+		 * directly here. (Probably a little bit obfuscating
+		 * but legitime ...).
+		 */
+		dev->release = (void (*)(struct device *))kfree;
+	} else
+		return -ENOMEM;
 
 	ret = device_register(dev);
 
 	if (ret)
 		return ret;
-
 	ret = netiucv_add_files(dev);
-
+	if (ret)
+		goto out_unreg;
+	ret = sysfs_create_link(&dev->kobj, &ndev->class_dev.kobj, ndev->name);
 	if (ret) 
-		device_unregister(dev);
-	else
-		dev->driver_data = priv;
+		goto out_rm_files;
+	ret = sysfs_create_link(&ndev->class_dev.kobj, &dev->kobj, dev->bus_id);
+	if (ret)
+		goto out_rm_link;
+	dev->driver_data = priv;
+	priv->dev = dev;
+	return 0;
+
+out_rm_link:
+	sysfs_remove_link(&dev->kobj, ndev->name);
+out_rm_files:
+	netiucv_remove_files(dev);
+out_unreg:
+	device_unregister(dev);
 	return ret;
 }
 
 static void
-netiucv_unregister_device(struct net_device *ndev)
+netiucv_unregister_device(struct device *dev)
 {
-	struct netiucv_priv *priv = (struct netiucv_priv*)ndev->priv;
-	struct device *dev = &priv->dev;
-	
+	struct netiucv_priv *priv = dev->driver_data;
+	struct net_device *ndev = priv->conn->netdev;
+
+	pr_debug("%s() called\n", __FUNCTION__);
+	sysfs_remove_link(&ndev->class_dev.kobj, dev->bus_id);
+	sysfs_remove_link(&dev->kobj, ndev->name);
 	netiucv_remove_files(dev);
 	device_unregister(dev);
 }
@@ -1524,6 +1653,7 @@ netiucv_new_connection(struct net_device
 	if (conn) {
 		memset(conn, 0, sizeof(struct iucv_connection));
 		skb_queue_head_init(&conn->collect_queue);
+		skb_queue_head_init(&conn->commit_queue);
 		conn->max_buffsize = NETIUCV_BUFSIZE_DEFAULT;
 		conn->netdev = dev;
 
@@ -1573,6 +1703,8 @@ netiucv_remove_connection(struct iucv_co
 {
 	struct iucv_connection **clist = &connections;
 
+	pr_debug("%s() called\n", __FUNCTION__);
+
 	if (conn == NULL)
 		return;
 	while (*clist) {
@@ -1593,80 +1725,88 @@ netiucv_remove_connection(struct iucv_co
 }
 
 /**
- * Allocate and initialize everything of a net device.
+ * Release everything of a net device.
  */
-static struct net_device *
-netiucv_init_netdevice(int ifno, char *username)
+static void
+netiucv_free_netdevice(struct net_device *dev)
 {
 	struct netiucv_priv *privptr;
-	int          priv_size;
 
-	struct net_device *dev = kmalloc(sizeof(struct net_device), GFP_KERNEL);
+	pr_debug("%s() called\n", __FUNCTION__);
+
 	if (!dev)
-		return NULL;
-	memset(dev, 0, sizeof(struct net_device));
-	sprintf(dev->name, "iucv%d", ifno);
+		return;
 
-	priv_size = sizeof(struct netiucv_priv);
-	dev->priv = kmalloc(priv_size, GFP_KERNEL);
-	if (dev->priv == NULL) {
-		kfree(dev);
-		return NULL;
-	}
-        memset(dev->priv, 0, priv_size);
-        privptr = (struct netiucv_priv *)dev->priv;
-	privptr->fsm = init_fsm("netiucvdev", dev_state_names,
-				dev_event_names, NR_DEV_STATES, NR_DEV_EVENTS,
-				dev_fsm, DEV_FSM_LEN, GFP_KERNEL);
-	if (privptr->fsm == NULL) {
-		kfree(privptr);
-		kfree(dev);
-		return NULL;
-	}
-	privptr->conn = netiucv_new_connection(dev, username);
-	if (!privptr->conn) {
-		kfree_fsm(privptr->fsm);
-		kfree(privptr);
-		kfree(dev);
-		return NULL;
+	privptr = (struct netiucv_priv *)dev->priv;
+	if (privptr) {
+		if (privptr->fsm)
+			fsm_deltimer(&privptr->timer);
+		if (privptr->conn)
+			netiucv_remove_connection(privptr->conn);
+		if (privptr->fsm)
+			kfree_fsm(privptr->fsm);
+		privptr->conn = 0; privptr->fsm = 0;
+		/* privptr gets freed by free_netdev() */
 	}
+	free_netdev(dev);
+}
+
+/**
+ * Initialize a net device. (Called from kernel in alloc_netdev())
+ */
+static void
+netiucv_setup_netdevice(struct net_device *dev)
+{
+        memset(dev->priv, 0, sizeof(struct netiucv_priv));
 
-	fsm_newstate(privptr->fsm, DEV_STATE_STOPPED);
 	dev->mtu	         = NETIUCV_MTU_DEFAULT;
 	dev->hard_start_xmit     = netiucv_tx;
 	dev->open	         = netiucv_open;
 	dev->stop	         = netiucv_close;
 	dev->get_stats	         = netiucv_stats;
 	dev->change_mtu          = netiucv_change_mtu;
+	dev->destructor          = netiucv_free_netdevice;
 	dev->hard_header_len     = NETIUCV_HDRLEN;
 	dev->addr_len            = 0;
 	dev->type                = ARPHRD_SLIP;
 	dev->tx_queue_len        = NETIUCV_QUEUELEN_DEFAULT;
 	dev->flags	         = IFF_POINTOPOINT | IFF_NOARP;
 	SET_MODULE_OWNER(dev);
-	return dev;
 }
 
 /**
  * Allocate and initialize everything of a net device.
  */
-static void
-netiucv_free_netdevice(struct net_device *dev)
+static struct net_device *
+netiucv_init_netdevice(int ifno, char *username)
 {
 	struct netiucv_priv *privptr;
+	struct net_device *dev;
 
+	dev = alloc_netdev(sizeof(struct netiucv_priv), "",
+			   netiucv_setup_netdevice);
 	if (!dev)
-		return;
+		return NULL;
+	sprintf(dev->name, "iucv%d", ifno);
 
-	privptr = (struct netiucv_priv *)dev->priv;
-	if (privptr) {
-		if (privptr->conn)
-			netiucv_remove_connection(privptr->conn);
-		if (privptr->fsm)
-			kfree_fsm(privptr->fsm);
-		kfree(privptr);
+        privptr = (struct netiucv_priv *)dev->priv;
+	privptr->fsm = init_fsm("netiucvdev", dev_state_names,
+				dev_event_names, NR_DEV_STATES, NR_DEV_EVENTS,
+				dev_fsm, DEV_FSM_LEN, GFP_KERNEL);
+	if (privptr->fsm == NULL) {
+		free_netdev(dev);
+		return NULL;
 	}
-	free_netdev(dev);
+	privptr->conn = netiucv_new_connection(dev, username);
+	if (!privptr->conn) {
+		kfree_fsm(privptr->fsm);
+		free_netdev(dev);
+		return NULL;
+	}
+	fsm_settimer(privptr->fsm, &privptr->timer);
+	fsm_newstate(privptr->fsm, DEV_STATE_STOPPED);
+
+	return dev;
 }
 
 static ssize_t
@@ -1684,7 +1824,7 @@ conn_write(struct device_driver *drv, co
 	}
 
 	for (i=0, p=(char *)buf; i<8 && *p; i++, p++) {
-		if (isalnum(*p))
+		if (isalnum(*p) || (*p == '$'))
 			username[i]= *p;
 		else if (*p == '\n') {
 			/* trailing lf, grr */
@@ -1729,7 +1869,7 @@ static struct device_driver netiucv_driv
 static void
 netiucv_banner(void)
 {
-	char vbuf[] = "$Revision: 1.30 $";
+	char vbuf[] = "$Revision: 1.38 $";
 	char *version = vbuf;
 
 	if ((version = strchr(version, ':'))) {
@@ -1745,10 +1885,12 @@ static void __exit
 netiucv_exit(void)
 {
 	while (connections) {
-		struct net_device *dev = connections->netdev;
-		unregister_netdev(dev);
+		struct net_device *ndev = connections->netdev;
+		struct netiucv_priv *priv = (struct netiucv_priv*)ndev->priv;
+		struct device *dev = priv->dev;
+
+		unregister_netdev(ndev);
 		netiucv_unregister_device(dev);
-		netiucv_free_netdevice(dev);
 	}
 
 	driver_remove_file(&netiucv_driver, &driver_attr_connection);
--- diff/drivers/s390/net/qeth.c	2004-02-18 08:54:10.000000000 +0000
+++ source/drivers/s390/net/qeth.c	2004-02-23 13:56:45.000000000 +0000
@@ -6707,15 +6707,6 @@ qeth_remove_card(struct qeth_card *card,
 }
 
 static void
-qeth_destructor(struct net_device *dev)
-{
-	struct qeth_card *card;
-
-	card = (struct qeth_card *) (dev->priv);
-	QETH_DBF_CARD2(0, trace, "dstr", card);
-}
-
-static void
 qeth_set_multicast_list(struct net_device *dev)
 {
 	struct qeth_card *card = dev->priv;
@@ -7655,28 +7646,11 @@ qeth_init_dev(struct net_device *dev)
 
 	QETH_DBF_CARD3(0, trace, "inid", card);
 
-	dev->tx_timeout = &qeth_tx_timeout;
-	dev->watchdog_timeo = QETH_TX_TIMEOUT;
-	dev->open = qeth_open;
-	dev->stop = qeth_stop;
-	dev->set_config = qeth_set_config;
-	dev->hard_start_xmit = qeth_hard_start_xmit;
-	dev->do_ioctl = qeth_do_ioctl;
-	dev->get_stats = qeth_get_stats;
-	dev->change_mtu = qeth_change_mtu;
-#ifdef QETH_VLAN
-	dev->vlan_rx_register = qeth_vlan_rx_register;
-	dev->vlan_rx_kill_vid = qeth_vlan_rx_kill_vid;
-#endif
 	dev->rebuild_header = __qeth_rebuild_header_func(card);
 	dev->hard_header = __qeth_hard_header_func(card);
 	dev->header_cache_update = __qeth_header_cache_update_func(card);
 	dev->hard_header_cache = __qeth_hard_header_cache_func(card);
 	dev->hard_header_parse = NULL;
-	dev->destructor = qeth_destructor;
-	dev->set_multicast_list = qeth_set_multicast_list;
-	dev->set_mac_address = qeth_set_mac_address;
-	dev->neigh_setup = qeth_neigh_setup;
 
 	dev->flags |= qeth_get_additional_dev_flags(card->type);
 
@@ -7694,8 +7668,6 @@ qeth_init_dev(struct net_device *dev)
 	dev->tx_queue_len = qeth_get_device_tx_q_len(card->type);
 	dev->hard_header_len =
 		qeth_get_hlen(card->link_type) + card->options.add_hhlen;
-	dev->addr_len = OSA_ADDR_LEN;	/* is ok for eth, tr, atm lane */
-	SET_MODULE_OWNER(dev);
 	netif_start_queue(dev);
 
 	dev->mtu = card->initial_mtu;
@@ -8358,6 +8330,28 @@ qeth_fill_qeth_card_options(struct qeth_
 	card->options.fake_ll = DONT_FAKE_LL;
 }
 
+static void qeth_setup(struct net_device *dev)
+{
+	dev->tx_timeout = &qeth_tx_timeout;
+	dev->watchdog_timeo = QETH_TX_TIMEOUT;
+	dev->open = qeth_open;
+	dev->stop = qeth_stop;
+	dev->set_config = qeth_set_config;
+	dev->hard_start_xmit = qeth_hard_start_xmit;
+	dev->do_ioctl = qeth_do_ioctl;
+	dev->get_stats = qeth_get_stats;
+	dev->change_mtu = qeth_change_mtu;
+#ifdef QETH_VLAN
+	dev->vlan_rx_register = qeth_vlan_rx_register;
+	dev->vlan_rx_kill_vid = qeth_vlan_rx_kill_vid;
+#endif
+	dev->set_multicast_list = qeth_set_multicast_list;
+	dev->set_mac_address = qeth_set_mac_address;
+	dev->neigh_setup = qeth_neigh_setup;
+	dev->addr_len = OSA_ADDR_LEN;	/* is ok for eth, tr, atm lane */
+	SET_MODULE_OWNER(dev);
+}
+
 static int
 qeth_alloc_card_stuff(struct qeth_card *card)
 {
@@ -8385,11 +8379,9 @@ qeth_alloc_card_stuff(struct qeth_card *
 		goto exit_dma2;
 	memset(card->dma_stuff->sendbuf, 0, QETH_BUFSIZE);
 
-	card->dev = (struct net_device *) kmalloc(sizeof (struct net_device),
-						  GFP_KERNEL);
+	card->dev = alloc_netdev(0, "", qeth_setup);
 	if (!card->dev)
 		goto exit_dev;
-	memset(card->dev, 0, sizeof (struct net_device));
 
 	card->stats =
 	    (struct net_device_stats *)
--- diff/drivers/s390/s390mach.c	2004-02-09 10:36:11.000000000 +0000
+++ source/drivers/s390/s390mach.c	2004-02-23 13:56:45.000000000 +0000
@@ -11,6 +11,7 @@
 #include <linux/config.h>
 #include <linux/init.h>
 #include <linux/sched.h>
+#include <linux/errno.h>
 
 #include <asm/lowcore.h>
 
@@ -19,12 +20,14 @@
 #define DBG printk
 // #define DBG(args,...) do {} while (0);
 
+static struct semaphore m_sem;
 static struct semaphore s_sem;
 
-extern void css_process_crw(int);
-extern void chsc_process_crw(void);
-extern void chp_process_crw(int, int);
+extern int css_process_crw(int);
+extern int chsc_process_crw(void);
+extern int chp_process_crw(int, int);
 extern void css_reiterate_subchannels(void);
+extern void css_trigger_slow_path(void);
 
 static void
 s390_handle_damage(char *msg)
@@ -36,6 +39,21 @@ s390_handle_damage(char *msg)
 	disabled_wait((unsigned long) __builtin_return_address(0));
 }
 
+static int
+s390_mchk_slow_path(void *param)
+{
+	struct semaphore *sem;
+
+	sem = (struct semaphore *)param;
+	/* Set a nice name. */
+	daemonize("kslowcrw");
+repeat:
+	down_interruptible(sem);
+	css_trigger_slow_path();
+	goto repeat;
+	return 0;
+}
+
 /*
  * Retrieve CRWs and call function to handle event.
  *
@@ -45,15 +63,15 @@ static int
 s390_collect_crw_info(void *param)
 {
 	struct crw crw;
-	int ccode;
+	int ccode, ret, slow;
 	struct semaphore *sem;
 
 	sem = (struct semaphore *)param;
 	/* Set a nice name. */
 	daemonize("kmcheck");
-
 repeat:
 	down_interruptible(sem);
+	slow = 0;
 	while (1) {
 		ccode = stcrw(&crw);
 		if (ccode != 0)
@@ -66,12 +84,15 @@ repeat:
 		if (crw.oflw) {
 			pr_debug("%s: crw overflow detected!\n", __FUNCTION__);
 			css_reiterate_subchannels();
+			slow = 1;
 			continue;
 		}
 		switch (crw.rsc) {
 		case CRW_RSC_SCH:
 			pr_debug("source is subchannel %04X\n", crw.rsid);
-			css_process_crw (crw.rsid);
+			ret = css_process_crw (crw.rsid);
+			if (ret == -EAGAIN)
+				slow = 1;
 			break;
 		case CRW_RSC_MONITOR:
 			pr_debug("source is monitoring facility\n");
@@ -80,28 +101,36 @@ repeat:
 			pr_debug("source is channel path %02X\n", crw.rsid);
 			switch (crw.erc) {
 			case CRW_ERC_IPARM: /* Path has come. */
-				chp_process_crw(crw.rsid, 1);
+				ret = chp_process_crw(crw.rsid, 1);
 				break;
 			case CRW_ERC_PERRI: /* Path has gone. */
-				chp_process_crw(crw.rsid, 0);
+			case CRW_ERC_PERRN:
+				ret = chp_process_crw(crw.rsid, 0);
 				break;
 			default:
 				pr_debug("Don't know how to handle erc=%x\n",
 					 crw.erc);
+				ret = 0;
 			}
+			if (ret == -EAGAIN)
+				slow = 1;
 			break;
 		case CRW_RSC_CONFIG:
 			pr_debug("source is configuration-alert facility\n");
 			break;
 		case CRW_RSC_CSS:
 			pr_debug("source is channel subsystem\n");
-			chsc_process_crw();
+			ret = chsc_process_crw();
+			if (ret == -EAGAIN)
+				slow = 1;
 			break;
 		default:
 			pr_debug("unknown source\n");
 			break;
 		}
 	}
+	if (slow)
+		up(&s_sem);
 	goto repeat;
 	return 0;
 }
@@ -140,7 +169,7 @@ s390_do_machine_check(void)
 				   "check\n");
 
 	if (mci->cp)		/* channel report word pending */
-		up(&s_sem);
+		up(&m_sem);
 
 #ifdef CONFIG_MACHCHK_WARNING
 /*
@@ -172,6 +201,7 @@ s390_do_machine_check(void)
 static int
 machine_check_init(void)
 {
+	init_MUTEX_LOCKED(&m_sem);
 	init_MUTEX_LOCKED( &s_sem );
 	ctl_clear_bit(14, 25);	/* disable damage MCH */
 	ctl_set_bit(14, 26);	/* enable degradation MCH */
@@ -195,7 +225,8 @@ arch_initcall(machine_check_init);
 static int __init
 machine_check_crw_init (void)
 {
-	kernel_thread(s390_collect_crw_info, &s_sem, CLONE_FS|CLONE_FILES);
+	kernel_thread(s390_collect_crw_info, &m_sem, CLONE_FS|CLONE_FILES);
+	kernel_thread(s390_mchk_slow_path, &s_sem, CLONE_FS|CLONE_FILES);
 	ctl_set_bit(14, 28);	/* enable channel report MCH */
 	return 0;
 }
--- diff/drivers/s390/scsi/zfcp_aux.c	2004-02-09 10:36:11.000000000 +0000
+++ source/drivers/s390/scsi/zfcp_aux.c	2004-02-23 13:56:45.000000000 +0000
@@ -4,11 +4,12 @@
  *
  * FCP adapter driver for IBM eServer zSeries
  *
- * Copyright 2002 IBM Corporation
+ * (C) Copyright IBM Corp. 2002, 2004
+ *
  * Author(s): Martin Peschke <mpeschke@de.ibm.com>
  *            Raimund Schroeder <raimund.schroeder@de.ibm.com>
- *            Aron Zeh <arzeh@de.ibm.com>
- *            Wolfgang Taphorn <taphorn@de.ibm.com>
+ *            Aron Zeh
+ *            Wolfgang Taphorn
  *            Stefan Bader <stefan.bader@de.ibm.com>
  *            Heiko Carstens <heiko.carstens@de.ibm.com>
  *
@@ -28,7 +29,7 @@
  */
 
 /* this drivers version (do not edit !!! generated and updated by cvs) */
-#define ZFCP_AUX_REVISION "$Revision: 1.79 $"
+#define ZFCP_AUX_REVISION "$Revision: 1.98 $"
 
 /********************** INCLUDES *********************************************/
 
@@ -61,6 +62,9 @@
 #include <asm/cpcmd.h>		/* Debugging only */
 #include <asm/processor.h>	/* Debugging only */
 
+#include <linux/miscdevice.h>
+#include <linux/major.h>
+
 /* accumulated log level (module parameter) */
 static u32 loglevel = ZFCP_LOG_LEVEL_DEFAULTS;
 static char *device;
@@ -73,7 +77,7 @@ static void __exit zfcp_module_exit(void
 int zfcp_reboot_handler(struct notifier_block *, unsigned long, void *);
 
 /* FCP related */
-static void zfcp_nameserver_request_handler(struct zfcp_fsf_req *);
+static void zfcp_ns_gid_pn_handler(unsigned long);
 
 /* miscellaneous */
 #ifdef ZFCP_STAT_REQSIZES
@@ -83,6 +87,34 @@ static int zfcp_statistics_clear(struct 
 static int zfcp_statistics_new(struct list_head *, u32);
 #endif
 
+static inline int zfcp_sg_list_alloc(struct zfcp_sg_list *, size_t);
+static inline int zfcp_sg_list_free(struct zfcp_sg_list *);
+static inline int zfcp_sg_list_copy_from_user(struct zfcp_sg_list *, void *,
+					      size_t);
+static inline int zfcp_sg_list_copy_to_user(void *, struct zfcp_sg_list *,
+					    size_t);
+
+static int zfcp_cfdc_dev_ioctl(struct inode *, struct file *,
+	unsigned int, unsigned long);
+
+#define ZFCP_CFDC_IOC_MAGIC                     0xDD
+#define ZFCP_CFDC_IOC \
+	_IOWR(ZFCP_CFDC_IOC_MAGIC, 0, struct zfcp_cfdc_sense_data)
+
+#ifdef CONFIG_S390_SUPPORT
+static struct ioctl_trans zfcp_ioctl_trans = {ZFCP_CFDC_IOC, (void*) sys_ioctl};
+#endif
+
+static struct file_operations zfcp_cfdc_fops = {
+	.ioctl = zfcp_cfdc_dev_ioctl
+};
+
+static struct miscdevice zfcp_cfdc_misc = {
+	.minor = ZFCP_CFDC_DEV_MINOR,
+	.name = ZFCP_CFDC_DEV_NAME,
+	.fops = &zfcp_cfdc_fops
+};
+
 /*********************** KERNEL/MODULE PARAMETERS  ***************************/
 
 /* declare driver module init/cleanup functions */
@@ -128,7 +160,7 @@ _zfcp_hex_dump(char *addr, int count)
 		if ((i % 32) == 31)
 			printk("\n");
 	}
-	if ((i % 32) != 31)
+	if (((i-1) % 32) != 31)
 		printk("\n");
 }
 
@@ -137,7 +169,6 @@ _zfcp_hex_dump(char *addr, int count)
 /****************************************************************/
 
 #define ZFCP_LOG_AREA			ZFCP_LOG_AREA_OTHER
-#define ZFCP_LOG_AREA_PREFIX		ZFCP_LOG_AREA_PREFIX_OTHER
 
 #ifdef ZFCP_STAT_REQSIZES
 
@@ -242,7 +273,7 @@ zfcp_cmd_dbf_event_fsf(const char *text,
 {
 #ifdef ZFCP_DEBUG_COMMANDS
 	struct zfcp_adapter *adapter = fsf_req->adapter;
-	Scsi_Cmnd *scsi_cmnd;
+	struct scsi_cmnd *scsi_cmnd;
 	int level = 3;
 	int i;
 	unsigned long flags;
@@ -258,6 +289,8 @@ zfcp_cmd_dbf_event_fsf(const char *text,
 			    sizeof (u32));
 		debug_event(adapter->cmd_dbf, level, &scsi_cmnd,
 			    sizeof (unsigned long));
+		debug_event(adapter->cmd_dbf, level, &scsi_cmnd->cmnd,
+			    min(ZFCP_CMD_DBF_LENGTH, (int)scsi_cmnd->cmd_len));
 		for (i = 0; i < add_length; i += ZFCP_CMD_DBF_LENGTH)
 			debug_event(adapter->cmd_dbf,
 				    level,
@@ -268,8 +301,10 @@ zfcp_cmd_dbf_event_fsf(const char *text,
 #endif
 }
 
+/* XXX additionally log unit if available */
+/* ---> introduce new parameter for unit, see 2.4 code */
 void
-zfcp_cmd_dbf_event_scsi(const char *text, Scsi_Cmnd * scsi_cmnd)
+zfcp_cmd_dbf_event_scsi(const char *text, struct scsi_cmnd *scsi_cmnd)
 {
 #ifdef ZFCP_DEBUG_COMMANDS
 	struct zfcp_adapter *adapter;
@@ -287,6 +322,8 @@ zfcp_cmd_dbf_event_scsi(const char *text
 	debug_event(adapter->cmd_dbf, level, &scsi_cmnd->result, sizeof (u32));
 	debug_event(adapter->cmd_dbf, level, &scsi_cmnd,
 		    sizeof (unsigned long));
+	debug_event(adapter->cmd_dbf, level, &scsi_cmnd->cmnd,
+		    min(ZFCP_CMD_DBF_LENGTH, (int)scsi_cmnd->cmd_len));
 	if (likely(fsf_req)) {
 		debug_event(adapter->cmd_dbf, level, &fsf_req,
 			    sizeof (unsigned long));
@@ -359,13 +396,12 @@ static void __init
 zfcp_init_device_configure(void)
 {
 	int found = 0;
-	unsigned long flags;
 	struct zfcp_adapter *adapter;
 	struct zfcp_port *port;
 	struct zfcp_unit *unit;
 
 	down(&zfcp_data.config_sema);
-	read_lock_irqsave(&zfcp_data.config_lock, flags);
+	read_lock_irq(&zfcp_data.config_lock);
 	list_for_each_entry(adapter, &zfcp_data.adapter_list_head, list)
 		if (strcmp(zfcp_data.init_busid,
 			   zfcp_get_busid_by_adapter(adapter)) == 0) {
@@ -373,7 +409,7 @@ zfcp_init_device_configure(void)
 			found = 1;
 			break;
 		}
-	read_unlock_irqrestore(&zfcp_data.config_lock, flags);
+	read_unlock_irq(&zfcp_data.config_lock);
 	if (!found)
 		goto out_adapter;
 	port = zfcp_port_enqueue(adapter, zfcp_data.init_wwpn, 0);
@@ -419,6 +455,28 @@ zfcp_module_init(void)
 	zfcp_statistics_init_all();
 #endif
 
+#ifdef CONFIG_S390_SUPPORT
+	retval = register_ioctl32_conversion(zfcp_ioctl_trans.cmd,
+					     zfcp_ioctl_trans.handler);
+	if (retval != 0) {
+		ZFCP_LOG_INFO("Cannot register a 32-bit support of "
+			      "the IOC handler\n");
+		goto out_ioctl32;
+	}
+#endif
+	retval = misc_register(&zfcp_cfdc_misc);
+	if (retval != 0) {
+		ZFCP_LOG_INFO(
+			"Device file for the control file data channel "
+			"cannot be registered\n");
+		goto out_misc_register;
+	} else {
+		ZFCP_LOG_INFO(
+			"Device file for the control file data channel "
+			"has become MAJOR/MINOR numbers %d/%d\n",
+			ZFCP_CFDC_DEV_MAJOR, zfcp_cfdc_misc.minor);
+	}
+
 	/* Initialise proc semaphores */
 	sema_init(&zfcp_data.config_sema, 1);
 
@@ -445,6 +503,12 @@ zfcp_module_init(void)
 
  out_ccw_register:
 	unregister_reboot_notifier(&zfcp_data.reboot_notifier);
+	misc_deregister(&zfcp_cfdc_misc);
+ out_misc_register:
+#ifdef CONFIG_S390_SUPPORT
+	unregister_ioctl32_conversion(zfcp_ioctl_trans.cmd);
+ out_ioctl32:
+#endif
 #ifdef ZFCP_STAT_REQSIZES
 	zfcp_statistics_clear_all();
 #endif
@@ -458,6 +522,10 @@ zfcp_module_exit(void)
 {
 	unregister_reboot_notifier(&zfcp_data.reboot_notifier);
 	zfcp_ccw_unregister();
+	misc_deregister(&zfcp_cfdc_misc);
+#ifdef CONFIG_S390_SUPPORT
+	unregister_ioctl32_conversion(zfcp_ioctl_trans.cmd);
+#endif
 #ifdef ZFCP_STAT_REQSIZES
 	zfcp_statistics_clear_all();
 #endif
@@ -480,15 +548,372 @@ zfcp_reboot_handler(struct notifier_bloc
 	return NOTIFY_DONE;
 }
 
+
+/*
+ * function:    zfcp_cfdc_dev_ioctl
+ *
+ * purpose:     Handle control file upload/download transaction via IOCTL
+ *		interface
+ *
+ * returns:     0           - Operation completed successfuly
+ *              -ENOTTY     - Unknown IOCTL command
+ *              -EINVAL     - Invalid sense data record
+ *              -ENXIO      - The FCP adapter is not available
+ *              -EOPNOTSUPP - The FCP adapter does not have CFDC support
+ *              -ENOMEM     - Insufficient memory
+ *              -EFAULT     - User space memory I/O operation fault
+ *              -EPERM      - Cannot create or queue FSF request or create SBALs
+ */
+static int
+zfcp_cfdc_dev_ioctl(struct inode *inode, struct file *file,
+                    unsigned int command, unsigned long buffer)
+{
+	struct zfcp_cfdc_sense_data sense_data, *sense_data_user;
+	struct zfcp_adapter *adapter = NULL;
+	struct zfcp_fsf_req *fsf_req = NULL;
+	struct zfcp_sg_list *sg_list = NULL;
+	u32 fsf_command, option;
+	char *bus_id = NULL;
+	int retval = 0;
+
+	ZFCP_LOG_NORMAL(
+		"Control file data channel transaction opened\n");
+
+	sg_list = kmalloc(sizeof(struct zfcp_sg_list), GFP_KERNEL);
+	if (sg_list == NULL) {
+		ZFCP_LOG_NORMAL(
+			"Not enough memory for the scatter-gather list\n");
+		retval = -ENOMEM;
+		goto out;
+	}
+	sg_list->count = 0;
+
+	if (command != ZFCP_CFDC_IOC) {
+		ZFCP_LOG_NORMAL(
+			"IOC request code 0x%x is not valid\n",
+			command);
+		retval = -ENOTTY;
+		goto out;
+	}
+
+	if ((sense_data_user = (struct zfcp_cfdc_sense_data*)buffer) == NULL) {
+		ZFCP_LOG_NORMAL(
+			"Sense data record is required\n");
+		retval = -EINVAL;
+		goto out;
+	}
+
+	retval = copy_from_user(&sense_data, sense_data_user,
+		sizeof(struct zfcp_cfdc_sense_data));
+	if (retval) {
+		ZFCP_LOG_NORMAL("Cannot copy sense data record from user space "
+				"memory\n");
+		retval = -EFAULT;
+		goto out;
+	}
+
+	if (sense_data.signature != ZFCP_CFDC_SIGNATURE) {
+		ZFCP_LOG_NORMAL(
+			"No valid sense data request signature 0x%08x found\n",
+			ZFCP_CFDC_SIGNATURE);
+		retval = -EINVAL;
+		goto out;
+	}
+
+	switch (sense_data.command) {
+
+	case ZFCP_CFDC_CMND_DOWNLOAD_NORMAL:
+		fsf_command = FSF_QTCB_DOWNLOAD_CONTROL_FILE;
+		option = FSF_CFDC_OPTION_NORMAL_MODE;
+		break;
+
+	case ZFCP_CFDC_CMND_DOWNLOAD_FORCE:
+		fsf_command = FSF_QTCB_DOWNLOAD_CONTROL_FILE;
+		option = FSF_CFDC_OPTION_FORCE;
+		break;
+
+	case ZFCP_CFDC_CMND_FULL_ACCESS:
+		fsf_command = FSF_QTCB_DOWNLOAD_CONTROL_FILE;
+		option = FSF_CFDC_OPTION_FULL_ACCESS;
+		break;
+
+	case ZFCP_CFDC_CMND_RESTRICTED_ACCESS:
+		fsf_command = FSF_QTCB_DOWNLOAD_CONTROL_FILE;
+		option = FSF_CFDC_OPTION_RESTRICTED_ACCESS;
+		break;
+
+	case ZFCP_CFDC_CMND_UPLOAD:
+		fsf_command = FSF_QTCB_UPLOAD_CONTROL_FILE;
+		option = 0;
+		break;
+
+	default:
+		ZFCP_LOG_NORMAL(
+			"Command code 0x%08x is not valid\n",
+			sense_data.command);
+		retval = -EINVAL;
+		goto out;
+	}
+
+	bus_id = kmalloc(BUS_ID_SIZE, GFP_KERNEL);
+	if (bus_id == NULL) {
+		ZFCP_LOG_NORMAL("Out of memory!\n");
+		retval = -ENOMEM;
+		goto out;
+	}
+	snprintf(bus_id, BUS_ID_SIZE, "%d.%d.%04x",
+		(sense_data.devno >> 24),
+		(sense_data.devno >> 16) & 0xFF,
+		(sense_data.devno & 0xFFFF));
+
+	retval = -ENXIO;
+	read_lock_irq(&zfcp_data.config_lock);
+	list_for_each_entry(adapter, &zfcp_data.adapter_list_head, list) {
+		if (strncmp(bus_id, zfcp_get_busid_by_adapter(adapter),
+		    BUS_ID_SIZE) == 0) {
+			zfcp_adapter_get(adapter);
+			retval = 0;
+			break;
+		}
+	}
+	read_unlock_irq(&zfcp_data.config_lock);
+
+	kfree(bus_id);
+
+	if (retval != 0) {
+		ZFCP_LOG_NORMAL("Specified adapter does not exist\n");
+		goto out;
+	}
+
+	if (sense_data.command & ZFCP_CFDC_WITH_CONTROL_FILE) {
+		retval = zfcp_sg_list_alloc(sg_list,
+					    ZFCP_CFDC_MAX_CONTROL_FILE_SIZE);
+		if (retval) {
+			ZFCP_LOG_NORMAL("Not enough memory for the "
+					"scatter-gather list\n");
+			retval = -ENOMEM;
+			goto out;
+		}
+	}
+
+	if ((sense_data.command & ZFCP_CFDC_DOWNLOAD) &&
+	    (sense_data.command & ZFCP_CFDC_WITH_CONTROL_FILE)) {
+		retval = zfcp_sg_list_copy_from_user(
+			sg_list, &sense_data_user->control_file,
+			ZFCP_CFDC_MAX_CONTROL_FILE_SIZE);
+		if (retval) {
+			ZFCP_LOG_NORMAL("Cannot copy control file from user "
+					"space memory\n");
+			retval = -EFAULT;
+			goto out;
+		}
+	}
+
+	retval = zfcp_fsf_control_file(
+		adapter, &fsf_req, fsf_command, option, sg_list);
+	if (retval == -EOPNOTSUPP) {
+		ZFCP_LOG_NORMAL(
+			"Specified adapter does not support control file\n");
+		goto out;
+	} else if (retval != 0) {
+		ZFCP_LOG_NORMAL(
+			"Cannot create or queue FSF request or create SBALs\n");
+		retval = -EPERM;
+		goto out;
+	}
+
+	wait_event(fsf_req->completion_wq,
+	           fsf_req->status & ZFCP_STATUS_FSFREQ_COMPLETED);
+
+	sense_data.fsf_status = fsf_req->qtcb->header.fsf_status;
+	memcpy(&sense_data.fsf_status_qual,
+	       &fsf_req->qtcb->header.fsf_status_qual,
+	       sizeof(union fsf_status_qual));
+	memcpy(&sense_data.payloads, &fsf_req->qtcb->bottom.support.els, 256);
+
+	retval = copy_to_user(sense_data_user, &sense_data,
+		sizeof(struct zfcp_cfdc_sense_data));
+	if (retval) {
+		ZFCP_LOG_NORMAL(
+			"Cannot copy sense data record to user space memory\n");
+		retval = -EFAULT;
+		goto out;
+	}
+
+	if (sense_data.command & ZFCP_CFDC_UPLOAD) {
+		retval = zfcp_sg_list_copy_to_user(
+			&sense_data_user->control_file, sg_list,
+			ZFCP_CFDC_MAX_CONTROL_FILE_SIZE);
+		if (retval) {
+			ZFCP_LOG_NORMAL("Cannot copy control file to user "
+					"space memory\n");
+			retval = -EFAULT;
+			goto out;
+		}
+	}
+
+ out:
+	if (fsf_req != NULL)
+		zfcp_fsf_req_cleanup(fsf_req);
+
+	if ((adapter != NULL) && (retval != -ENXIO))
+		zfcp_adapter_put(adapter);
+
+	if (sg_list != NULL) {
+		zfcp_sg_list_free(sg_list);
+		kfree(sg_list);
+	}
+
+	ZFCP_LOG_NORMAL(
+		"Control file data channel transaction closed\n");
+
+	return retval;
+}
+
+
+/*
+ * function:    zfcp_sg_list_alloc
+ *
+ * purpose:     Create a scatter-gather list of the specified size
+ *
+ * returns:     0       - Scatter gather list is created
+ *              -ENOMEM - Insufficient memory (*list_ptr is then set to NULL)
+ */
+static inline int
+zfcp_sg_list_alloc(struct zfcp_sg_list *sg_list, size_t size)
+{
+	struct scatterlist *sg;
+	int i;
+	int retval = 0;
+
+	sg_list->count = size >> PAGE_SHIFT;
+	if (size & ~PAGE_MASK)
+		sg_list->count++;
+	sg_list->sg = kmalloc(sg_list->count * sizeof(struct scatterlist),
+			      GFP_KERNEL);
+	if (sg_list->sg == NULL) {
+		retval = -ENOMEM;
+		goto out;
+	}
+
+	for (i = 0, sg = sg_list->sg; i < sg_list->count; i++, sg++) {
+		sg->length = min(size, PAGE_SIZE);
+		sg->offset = 0;
+		sg->page = alloc_pages(GFP_KERNEL, 0);
+		if (sg->page == NULL) {
+			sg_list->count = i;
+			zfcp_sg_list_free(sg_list);
+			retval = -ENOMEM;
+			goto out;
+		}
+		size -= sg->length;
+	}
+
+ out:
+	return retval;
+}
+
+
+/*
+ * function:    zfcp_sg_list_free
+ *
+ * purpose:     Destroy a scatter-gather list and release memory
+ *
+ * returns:     Always 0
+ */
+static inline int
+zfcp_sg_list_free(struct zfcp_sg_list *sg_list)
+{
+	struct scatterlist *sg;
+	int i;
+	int retval = 0;
+
+	BUG_ON((sg_list->sg == NULL) || (sg_list == NULL));
+
+	for (i = 0, sg = sg_list->sg; i < sg_list->count; i++, sg++)
+		__free_pages(sg->page, 0);
+
+	return retval;
+}
+
+
+/*
+ * function:    zfcp_sg_list_copy_from_user
+ *
+ * purpose:     Copy data from user space memory to the scatter-gather list
+ *
+ * returns:     0       - The data has been copied from user
+ *              -EFAULT - Memory I/O operation fault
+ */
+static inline int
+zfcp_sg_list_copy_from_user(struct zfcp_sg_list *sg_list, void *user_buffer,
+                            size_t size)
+{
+	struct scatterlist *sg;
+	unsigned int length;
+	void *zfcp_buffer;
+	int retval = 0;
+
+	for (sg = sg_list->sg; size > 0; sg++) {
+		length = min((unsigned int)size, sg->length);
+		zfcp_buffer = (void*)
+			((page_to_pfn(sg->page) << PAGE_SHIFT) + sg->offset);
+		if (copy_from_user(zfcp_buffer, user_buffer, length)) {
+			ZFCP_LOG_INFO("Memory error (copy_from_user)\n");
+			retval = -EFAULT;
+			goto out;
+		}
+		user_buffer += length;
+		size -= length;
+	}
+
+ out:
+	return retval;
+}
+
+
+/*
+ * function:    zfcp_sg_list_copy_to_user
+ *
+ * purpose:     Copy data from the scatter-gather list to user space memory
+ *
+ * returns:     0       - The data has been copied to user
+ *              -EFAULT - Memory I/O operation fault
+ */
+static inline int
+zfcp_sg_list_copy_to_user(void *user_buffer, struct zfcp_sg_list *sg_list,
+                          size_t size)
+{
+	struct scatterlist *sg;
+	unsigned int length;
+	void *zfcp_buffer;
+	int retval = 0;
+
+	for (sg = sg_list->sg; size > 0; sg++) {
+		length = min((unsigned int)size, sg->length);
+		zfcp_buffer = (void*)
+			((page_to_pfn(sg->page) << PAGE_SHIFT) + sg->offset);
+		if (copy_to_user(user_buffer, zfcp_buffer, length)) {
+			ZFCP_LOG_INFO("Memory error (copy_to_user)\n");
+			retval = -EFAULT;
+			goto out;
+		}
+		user_buffer += length;
+		size -= length;
+	}
+
+ out:
+	return retval;
+}
+
+
 #undef ZFCP_LOG_AREA
-#undef ZFCP_LOG_AREA_PREFIX
 
 /****************************************************************/
 /****** Functions for configuration/set-up of structures ********/
 /****************************************************************/
 
 #define ZFCP_LOG_AREA			ZFCP_LOG_AREA_CONFIG
-#define ZFCP_LOG_AREA_PREFIX		ZFCP_LOG_AREA_PREFIX_CONFIG
 
 /**
  * zfcp_get_unit_by_lun - find unit in unit list of port by fcp lun
@@ -684,83 +1109,92 @@ zfcp_mempool_free(void *element, void *s
 static int
 zfcp_allocate_low_mem_buffers(struct zfcp_adapter *adapter)
 {
-	adapter->pool.erp_fsf = mempool_create(
-		1,
-		zfcp_mempool_alloc,
-		zfcp_mempool_free,
-		(void *) ZFCP_QTCB_AND_REQ_SIZE);
-	if (!adapter->pool.erp_fsf) {
-		ZFCP_LOG_INFO
-		    ("error: FCP command buffer pool allocation failed\n");
+	adapter->pool.fsf_req_erp =
+		mempool_create(ZFCP_POOL_FSF_REQ_ERP_NR,
+			       zfcp_mempool_alloc, zfcp_mempool_free, (void *)
+			       sizeof(struct zfcp_fsf_req_pool_element));
+
+	if (NULL == adapter->pool.fsf_req_erp) {
+		ZFCP_LOG_INFO("error: pool allocation failed (fsf_req_erp)\n");
 		return -ENOMEM;
 	}
 
-	adapter->pool.nameserver = mempool_create(
-		1,
-		zfcp_mempool_alloc,
-		zfcp_mempool_free,
-		(void *) (2 *  sizeof (struct fc_ct_iu)));
-	if (!adapter->pool.nameserver) {
-		ZFCP_LOG_INFO
-		    ("error: Nameserver buffer pool allocation failed\n");
+	adapter->pool.fsf_req_scsi =
+		mempool_create(ZFCP_POOL_FSF_REQ_SCSI_NR,
+			       zfcp_mempool_alloc, zfcp_mempool_free, (void *)
+			       sizeof(struct zfcp_fsf_req_pool_element));
+
+	if (NULL == adapter->pool.fsf_req_scsi) {
+		ZFCP_LOG_INFO("error: pool allocation failed (fsf_req_scsi)\n");
 		return -ENOMEM;
 	}
 
-	adapter->pool.status_read_fsf = mempool_create(
-		ZFCP_STATUS_READS_RECOM,
-		zfcp_mempool_alloc,
-		zfcp_mempool_free,
-		(void *) sizeof (struct zfcp_fsf_req));
-	if (!adapter->pool.status_read_fsf) {
-		ZFCP_LOG_INFO
-		    ("error: Status read request pool allocation failed\n");
+	adapter->pool.fsf_req_abort =
+		mempool_create(ZFCP_POOL_FSF_REQ_ABORT_NR,
+			       zfcp_mempool_alloc, zfcp_mempool_free, (void *)
+			       sizeof(struct zfcp_fsf_req_pool_element));
+
+	if (NULL == adapter->pool.fsf_req_abort) {
+		ZFCP_LOG_INFO("error: pool allocation failed "
+			      "(fsf_req_abort)\n");
 		return -ENOMEM;
 	}
 
-	adapter->pool.status_read_buf = mempool_create(
-		ZFCP_STATUS_READS_RECOM,
-		zfcp_mempool_alloc,
-		zfcp_mempool_free,
-		(void *) sizeof (struct	fsf_status_read_buffer));
-	if (!adapter->pool.status_read_buf) {
-		ZFCP_LOG_INFO
-		    ("error: Status read buffer pool allocation failed\n");
+	adapter->pool.fsf_req_status_read =
+		mempool_create(ZFCP_POOL_STATUS_READ_NR,
+			       zfcp_mempool_alloc, zfcp_mempool_free,
+			       (void *) sizeof(struct zfcp_fsf_req));
+
+	if (NULL == adapter->pool.fsf_req_status_read) {
+		ZFCP_LOG_INFO("error: pool allocation failed "
+			      "(fsf_req_status_read\n");
 		return -ENOMEM;
 	}
 
-	adapter->pool.fcp_command_fsf = mempool_create(
-		1,
-		zfcp_mempool_alloc,
-		zfcp_mempool_free,
-		(void *)
-		ZFCP_QTCB_AND_REQ_SIZE);
-	if (!adapter->pool.fcp_command_fsf) {
-		ZFCP_LOG_INFO
-		    ("error: FCP command buffer pool allocation failed\n");
+	adapter->pool.data_status_read =
+		mempool_create(ZFCP_POOL_STATUS_READ_NR,
+			       zfcp_mempool_alloc, zfcp_mempool_free,
+			       (void *) sizeof(struct fsf_status_read_buffer));
+
+	if (NULL == adapter->pool.data_status_read) {
+		ZFCP_LOG_INFO("error: pool allocation failed "
+			      "(data_status_read)\n");
+		return -ENOMEM;
+	}
+
+	adapter->pool.data_gid_pn =
+		mempool_create(ZFCP_POOL_DATA_GID_PN_NR,
+			       zfcp_mempool_alloc, zfcp_mempool_free, (void *)
+			       sizeof(struct zfcp_gid_pn_data));
+
+	if (NULL == adapter->pool.data_gid_pn) {
+		ZFCP_LOG_INFO("error: pool allocation failed (data_gid_pn)\n");
 		return -ENOMEM;
 	}
-	init_timer(&adapter->pool.fcp_command_fsf_timer);
-	adapter->pool.fcp_command_fsf_timer.function =
-	    zfcp_erp_scsi_low_mem_buffer_timeout_handler;
-	adapter->pool.fcp_command_fsf_timer.data = (unsigned long) adapter;
 
 	return 0;
 }
 
-/* locks:       must only be called with zfcp_data.config_sema taken */
+/**
+ * zfcp_free_low_mem_buffers - free memory pools of an adapter
+ * @adapter: pointer to zfcp_adapter for which memory pools should be freed
+ * locking:  zfcp_data.config_sema must be held
+ */
 static void
 zfcp_free_low_mem_buffers(struct zfcp_adapter *adapter)
 {
-	if (adapter->pool.status_read_fsf)
-		mempool_destroy(adapter->pool.status_read_fsf);
-	if (adapter->pool.status_read_buf)
-		mempool_destroy(adapter->pool.status_read_buf);
-	if (adapter->pool.nameserver)
-		mempool_destroy(adapter->pool.nameserver);
-	if (adapter->pool.erp_fsf)
-		mempool_destroy(adapter->pool.erp_fsf);
-	if (adapter->pool.fcp_command_fsf)
-		mempool_destroy(adapter->pool.fcp_command_fsf);
+	if (adapter->pool.fsf_req_erp)
+		mempool_destroy(adapter->pool.fsf_req_erp);
+	if (adapter->pool.fsf_req_scsi)
+		mempool_destroy(adapter->pool.fsf_req_scsi);
+	if (adapter->pool.fsf_req_abort)
+		mempool_destroy(adapter->pool.fsf_req_abort);
+	if (adapter->pool.fsf_req_status_read)
+		mempool_destroy(adapter->pool.fsf_req_status_read);
+	if (adapter->pool.data_status_read)
+		mempool_destroy(adapter->pool.data_status_read);
+	if (adapter->pool.data_gid_pn)
+		mempool_destroy(adapter->pool.data_gid_pn);
 }
 
 /*
@@ -859,7 +1293,7 @@ zfcp_adapter_enqueue(struct ccw_device *
 
 #ifdef ZFCP_DEBUG_REQUESTS
 	/* debug feature area which records fsf request sequence numbers */
-	sprintf(dbf_name, ZFCP_REQ_DBF_NAME "0x%s",
+	sprintf(dbf_name, ZFCP_REQ_DBF_NAME "%s",
 		zfcp_get_busid_by_adapter(adapter));
 	adapter->req_dbf = debug_register(dbf_name,
 					  ZFCP_REQ_DBF_INDEX,
@@ -954,15 +1388,6 @@ zfcp_adapter_enqueue(struct ccw_device *
 	debug_register_view(adapter->erp_dbf, &debug_hex_ascii_view);
 	debug_set_level(adapter->erp_dbf, ZFCP_ERP_DBF_LEVEL);
 
-	retval = zfcp_erp_thread_setup(adapter);
-	if (retval) {
-		ZFCP_LOG_INFO("error: out of resources. "
-			      "error recovery thread for the adapter %s "
-			      "could not be started\n",
-			      zfcp_get_busid_by_adapter(adapter));
-		goto thread_failed;
-	}
-
 	/* put allocated adapter at list tail */
 	write_lock_irq(&zfcp_data.config_lock);
 	atomic_clear_mask(ZFCP_STATUS_COMMON_REMOVE, &adapter->status);
@@ -973,15 +1398,6 @@ zfcp_adapter_enqueue(struct ccw_device *
 
 	goto out;
 
- thread_failed:
-	if (qdio_free(adapter->ccw_device) != 0)
-		ZFCP_LOG_NORMAL
-		    ("bug: could not free memory used by data transfer "
-		     "mechanism for adapter %s\n",
-		     zfcp_get_busid_by_adapter(adapter));
-
-	debug_unregister(adapter->erp_dbf);
-
  failed_erp_dbf:
 #ifdef ZFCP_DEBUG_INCOMING_ELS
 	debug_unregister(adapter->in_els_dbf);
@@ -1007,7 +1423,11 @@ zfcp_adapter_enqueue(struct ccw_device *
 	dev_set_drvdata(&ccw_device->dev, NULL);
  failed_low_mem_buffers:
 	zfcp_free_low_mem_buffers(adapter);
-	qdio_free(ccw_device);
+	if (qdio_free(ccw_device) != 0)
+		ZFCP_LOG_NORMAL
+		    ("bug: could not free memory used by data transfer "
+		     "mechanism for adapter %s\n",
+		     zfcp_get_busid_by_adapter(adapter));
  qdio_allocate_failed:
 	zfcp_qdio_free_queues(adapter);
  queues_alloc_failed:
@@ -1060,9 +1480,7 @@ zfcp_adapter_dequeue(struct zfcp_adapter
 		       "%i adapters still in list\n",
 		       (unsigned long) adapter, zfcp_data.adapters);
 
-	retval = zfcp_erp_thread_kill(adapter);
-
-	retval |= qdio_free(adapter->ccw_device);
+	retval = qdio_free(adapter->ccw_device);
 	if (retval)
 		ZFCP_LOG_NORMAL
 		    ("bug: could not free memory used by data transfer "
@@ -1261,14 +1679,12 @@ zfcp_nameserver_enqueue(struct zfcp_adap
 }
 
 #undef ZFCP_LOG_AREA
-#undef ZFCP_LOG_AREA_PREFIX
 
 /****************************************************************/
 /******* Fibre Channel Standard related Functions  **************/
 /****************************************************************/
 
 #define ZFCP_LOG_AREA                   ZFCP_LOG_AREA_FC
-#define ZFCP_LOG_AREA_PREFIX            ZFCP_LOG_AREA_PREFIX_FC
 
 void
 zfcp_fsf_incoming_els_rscn(struct zfcp_adapter *adapter,
@@ -1361,7 +1777,7 @@ zfcp_fsf_incoming_els_rscn(struct zfcp_a
 				     "0x%Lx.\n", port->wwpn);
 				debug_text_event(adapter->erp_dbf, 1,
 						 "unsol_els_rscnk:");
-				zfcp_erp_port_reopen(port, 0);
+				zfcp_test_link(port);
 			}
 		}
 		read_unlock_irqrestore(&zfcp_data.config_lock, flags);
@@ -1462,222 +1878,180 @@ zfcp_fsf_incoming_els(struct zfcp_fsf_re
 		zfcp_fsf_incoming_els_rscn(adapter, status_buffer);
 	else
 		zfcp_fsf_incoming_els_unknown(adapter, status_buffer);
-}
-
-/*
- * function:	zfcp_release_nameserver_buffers
- *
- * purpose:	
- *
- * returns:
- */
-static void
-zfcp_release_nameserver_buffers(struct zfcp_fsf_req *fsf_req)
-{
-	struct zfcp_adapter *adapter = fsf_req->adapter;
-	void *buffer = fsf_req->data.send_generic.outbuf;
 
-	/* FIXME: not sure about appeal of this new flag (martin) */
-	if (fsf_req->status & ZFCP_STATUS_FSFREQ_POOLBUF)
-		mempool_free(buffer, adapter->pool.nameserver);
-	else
-		kfree(buffer);
 }
 
-/*
- * function:	zfcp_get_nameserver_buffers
- *
- * purpose:	
- *
- * returns:
- *
- * locks:       fsf_request_list_lock is held when doing buffer pool 
- *              operations
+
+/**
+ * zfcp_gid_pn_buffers_alloc - allocate buffers for GID_PN nameserver request
+ * @gid_pn: pointer to return pointer to struct zfcp_gid_pn_data
+ * @pool: pointer to mempool_t if non-null memory pool is used for allocation
  */
 static int
-zfcp_get_nameserver_buffers(struct zfcp_fsf_req *fsf_req)
+zfcp_gid_pn_buffers_alloc(struct zfcp_gid_pn_data **gid_pn, mempool_t *pool)
 {
-	struct zfcp_send_generic *data = &fsf_req->data.send_generic;
-	struct zfcp_adapter *adapter = fsf_req->adapter;
-	int retval = 0;
+	struct zfcp_gid_pn_data *data;
 
-	data->outbuf = kmalloc(2 * sizeof (struct fc_ct_iu), GFP_ATOMIC);
-	if (data->outbuf) {
-		memset(data->outbuf, 0, 2 * sizeof (struct fc_ct_iu));
+	if (pool != NULL) {
+		data = mempool_alloc(pool, GFP_ATOMIC);
+		if (likely(data != NULL)) {
+			data->ct.pool = pool;
+		}
 	} else {
-		ZFCP_LOG_DEBUG("Out of memory. Could not allocate at "
-			       "least one of the buffers "
-			       "required for a name-server request on the"
-			       "adapter %s directly.. trying emergency pool\n",
-			       zfcp_get_busid_by_adapter(adapter));
-		data->outbuf =
-		    mempool_alloc(adapter->pool.nameserver, GFP_ATOMIC);
-		if (!data->outbuf) {
-			ZFCP_LOG_DEBUG
-				("Out of memory. Could not get emergency "
-				 "buffer required for a name-server request "
-				 "on the adapter %s. All buffers are in "
-				 "use.\n",
-				 zfcp_get_busid_by_adapter(adapter));
-			retval = -ENOMEM;
-			goto out;
+		data = kmalloc(sizeof(struct zfcp_gid_pn_data), GFP_ATOMIC);
 		}
-		memset(data->outbuf, 0, 2 * sizeof (struct fc_ct_iu));
-		fsf_req->status |= ZFCP_STATUS_FSFREQ_POOLBUF;
+
+        if (NULL == data){
+		ZFCP_LOG_DEBUG("Out of memory.\n");
+                return -ENOMEM;
 	}
-	data->outbuf_length = sizeof (struct fc_ct_iu);
-	data->inbuf_length = sizeof (struct fc_ct_iu);
-	data->inbuf =
-	    (char *) ((unsigned long) data->outbuf + sizeof (struct fc_ct_iu));
- out:
-	return retval;
+
+	memset(data, 0, sizeof(*data));
+        data->ct.req = &data->req;
+        data->ct.resp = &data->resp;
+	data->ct.req_count = data->ct.resp_count = 1;
+	zfcp_address_to_sg(&data->ct_iu_req, &data->req);
+        zfcp_address_to_sg(&data->ct_iu_resp, &data->resp);
+        data->req.length = sizeof(struct ct_iu_gid_pn_req);
+        data->resp.length = sizeof(struct ct_iu_gid_pn_resp);
+
+	*gid_pn = data;
+	return 0;
 }
 
-/*
- * function:	zfcp_nameserver_request
- *
- * purpose:	
- *
- * returns:
+/**
+ * zfcp_gid_pn_buffers_free - free buffers for GID_PN nameserver request
+ * @gid_pn: pointer to struct zfcp_gid_pn_data which has to be freed
  */
-int
-zfcp_nameserver_request(struct zfcp_erp_action *erp_action)
+static void
+zfcp_gid_pn_buffers_free(struct zfcp_gid_pn_data *gid_pn)
 {
-	int retval = 0;
-	struct fc_ct_iu *fc_ct_iu;
-	unsigned long lock_flags;
-
-	/* setup new FSF request */
-	retval = zfcp_fsf_req_create(erp_action->adapter,
-				     FSF_QTCB_SEND_GENERIC,
-				     &lock_flags,
-				     ZFCP_WAIT_FOR_SBAL | ZFCP_REQ_AUTO_CLEANUP,
-				     &(erp_action->fsf_req));
-	if (retval < 0) {
-		ZFCP_LOG_INFO("error: Out of resources. Could not create a "
-			      "nameserver registration request for "
-			      "adapter %s.\n",
-			      zfcp_get_busid_by_adapter(erp_action->adapter));
-		goto failed_req;
-	}
-	retval = zfcp_get_nameserver_buffers(erp_action->fsf_req);
-	if (retval < 0) {
-		ZFCP_LOG_INFO("error: Out of memory. Could not allocate one of "
-			      "the buffers required for a nameserver request "
-			      "on adapter %s.\n",
-			      zfcp_get_busid_by_adapter(erp_action->adapter));
-		goto failed_buffers;
-	}
-
-	/* setup name-server request in first page */
-	fc_ct_iu =
-	    (struct fc_ct_iu *) erp_action->fsf_req->data.send_generic.outbuf;
-	fc_ct_iu->revision = ZFCP_CT_REVISION;
-	fc_ct_iu->gs_type = ZFCP_CT_DIRECTORY_SERVICE;
-	fc_ct_iu->gs_subtype = ZFCP_CT_NAME_SERVER;
-	fc_ct_iu->options = ZFCP_CT_SYNCHRONOUS;
-	fc_ct_iu->cmd_rsp_code = ZFCP_CT_GID_PN;
-	fc_ct_iu->max_res_size = ZFCP_CT_MAX_SIZE;
-	fc_ct_iu->data.wwpn = erp_action->port->wwpn;
-
-	erp_action->fsf_req->data.send_generic.handler =
-	    zfcp_nameserver_request_handler;
-	erp_action->fsf_req->data.send_generic.handler_data =
-	    (unsigned long) erp_action->port;
-	erp_action->fsf_req->data.send_generic.port =
-	    erp_action->adapter->nameserver_port;
-	erp_action->fsf_req->erp_action = erp_action;
-
-	/* send this one */
-	retval = zfcp_fsf_send_generic(erp_action->fsf_req,
-				       ZFCP_NAMESERVER_TIMEOUT,
-				       &lock_flags,
-				       &erp_action->timer);
-	if (retval) {
-		ZFCP_LOG_INFO("error: Could not send a"
-			      "nameserver request command to adapter %s\n",
-			      zfcp_get_busid_by_adapter(erp_action->adapter));
-		goto failed_send;
+        if ((gid_pn->ct.pool != 0)) {
+		mempool_free(gid_pn, gid_pn->ct.pool);
+        } else {
+                kfree(gid_pn);
 	}
 
+	return;
+}
+
+/**
+ * zfcp_ns_gid_pn_request - initiate GID_PN nameserver request
+ * @erp_action: pointer to zfcp_erp_action where GID_PN request is needed
+ */
+int
+zfcp_ns_gid_pn_request(struct zfcp_erp_action *erp_action)
+{
+	int ret;
+        struct ct_iu_gid_pn_req *ct_iu_req;
+        struct zfcp_gid_pn_data *gid_pn;
+        struct zfcp_adapter *adapter = erp_action->adapter;
+
+	ret = zfcp_gid_pn_buffers_alloc(&gid_pn, adapter->pool.data_gid_pn);
+	if (ret < 0) {
+		ZFCP_LOG_INFO("error: Out of memory. Could not allocate "
+                              "buffers for nameserver request GID_PN. "
+                              "(adapter: %s)\n",
+			      zfcp_get_busid_by_adapter(adapter));
 	goto out;
+	}
 
- failed_send:
-	zfcp_release_nameserver_buffers(erp_action->fsf_req);
+	/* setup nameserver request */
+        ct_iu_req = zfcp_sg_to_address(gid_pn->ct.req);
+        ct_iu_req->header.revision = ZFCP_CT_REVISION;
+        ct_iu_req->header.gs_type = ZFCP_CT_DIRECTORY_SERVICE;
+        ct_iu_req->header.gs_subtype = ZFCP_CT_NAME_SERVER;
+        ct_iu_req->header.options = ZFCP_CT_SYNCHRONOUS;
+        ct_iu_req->header.cmd_rsp_code = ZFCP_CT_GID_PN;
+        ct_iu_req->header.max_res_size = ZFCP_CT_MAX_SIZE;
+	ct_iu_req->wwpn = erp_action->port->wwpn;
+
+        /* setup parameters for send generic command */
+        gid_pn->ct.port = adapter->nameserver_port;
+	gid_pn->ct.handler = zfcp_ns_gid_pn_handler;
+	gid_pn->ct.handler_data = (unsigned long) gid_pn;
+        gid_pn->ct.timeout = ZFCP_NS_GID_PN_TIMEOUT;
+        gid_pn->ct.timer = &erp_action->timer;
+	gid_pn->port = erp_action->port;
+
+	ret = zfcp_fsf_send_ct(&gid_pn->ct, adapter->pool.fsf_req_erp,
+			       erp_action);
+	if (ret) {
+		ZFCP_LOG_INFO("error: Could not send nameserver request GID_PN."
+                              "(adapter %s)\n",
+			      zfcp_get_busid_by_adapter(adapter));
 
- failed_buffers:
-	zfcp_fsf_req_free(erp_action->fsf_req);
-	erp_action->fsf_req = NULL;
+                zfcp_gid_pn_buffers_free(gid_pn);
+	}
 
- failed_req:
  out:
-	write_unlock_irqrestore(&erp_action->adapter->request_queue.queue_lock,
-				lock_flags);
-	return retval;
+	return ret;
 }
 
-/*
- * function:	zfcp_nameserver_request_handler
- *
- * purpose:	
- *
- * returns:
+/**
+ * zfcp_ns_gid_pn_handler - handler for GID_PN nameserver request
+ * @data: unsigned long, contains pointer to struct zfcp_gid_pn_data
  */
-static void
-zfcp_nameserver_request_handler(struct zfcp_fsf_req *fsf_req)
+static void zfcp_ns_gid_pn_handler(unsigned long data)
 {
-	struct fc_ct_iu *fc_ct_iu_resp =
-	    (struct fc_ct_iu *) (fsf_req->data.send_generic.inbuf);
-	struct fc_ct_iu *fc_ct_iu_req =
-	    (struct fc_ct_iu *) (fsf_req->data.send_generic.outbuf);
-	struct zfcp_port *port =
-	    (struct zfcp_port *) fsf_req->data.send_generic.handler_data;
+	struct zfcp_port *port;
+        struct zfcp_send_ct *ct;
+	struct ct_iu_gid_pn_req *ct_iu_req;
+	struct ct_iu_gid_pn_resp *ct_iu_resp;
+        struct zfcp_gid_pn_data *gid_pn;
+
 
-	if (fc_ct_iu_resp->revision != ZFCP_CT_REVISION)
+	gid_pn = (struct zfcp_gid_pn_data *) data;
+	port = gid_pn->port;
+        ct = &gid_pn->ct;
+	ct_iu_req = zfcp_sg_to_address(ct->req);
+	ct_iu_resp = zfcp_sg_to_address(ct->resp);
+
+        if (ct_iu_resp->header.revision != ZFCP_CT_REVISION)
 		goto failed;
-	if (fc_ct_iu_resp->gs_type != ZFCP_CT_DIRECTORY_SERVICE)
+        if (ct_iu_resp->header.gs_type != ZFCP_CT_DIRECTORY_SERVICE)
 		goto failed;
-	if (fc_ct_iu_resp->gs_subtype != ZFCP_CT_NAME_SERVER)
+        if (ct_iu_resp->header.gs_subtype != ZFCP_CT_NAME_SERVER)
 		goto failed;
-	if (fc_ct_iu_resp->options != ZFCP_CT_SYNCHRONOUS)
+        if (ct_iu_resp->header.options != ZFCP_CT_SYNCHRONOUS)
 		goto failed;
-	if (fc_ct_iu_resp->cmd_rsp_code != ZFCP_CT_ACCEPT) {
+        if (ct_iu_resp->header.cmd_rsp_code != ZFCP_CT_ACCEPT) {
 		/* FIXME: do we need some specific erp entry points */
 		atomic_set_mask(ZFCP_STATUS_PORT_INVALID_WWPN, &port->status);
 		goto failed;
 	}
 	/* paranoia */
-	if (fc_ct_iu_req->data.wwpn != port->wwpn) {
-		ZFCP_LOG_NORMAL("bug: Port WWPN returned by nameserver lookup "
-				"does not correspond to "
-				"the expected value on the adapter %s. "
-				"(debug info 0x%Lx, 0x%Lx)\n",
-				zfcp_get_busid_by_port(port),
-				port->wwpn, fc_ct_iu_req->data.wwpn);
+	if (ct_iu_req->wwpn != port->wwpn) {
+		ZFCP_LOG_NORMAL(
+			"bug: Port WWPN returned by nameserver lookup "
+                        "does not correspond to the expected value "
+			"(adapter: %s, debug info: 0x%016Lx, 0x%016Lx)\n",
+			zfcp_get_busid_by_port(port), port->wwpn,
+                        ct_iu_req->wwpn);
 		goto failed;
 	}
 
 	/* looks like a valid d_id */
-	port->d_id = ZFCP_DID_MASK & fc_ct_iu_resp->data.d_id;
+        port->d_id = ct_iu_resp->d_id & ZFCP_DID_MASK;
 	atomic_set_mask(ZFCP_STATUS_PORT_DID_DID, &port->status);
 	ZFCP_LOG_DEBUG("busid %s:  WWPN=0x%Lx ---> D_ID=0x%6.6x\n",
 		       zfcp_get_busid_by_port(port),
 		       port->wwpn, (unsigned int) port->d_id);
 	goto out;
 
- failed:
+failed:
 	ZFCP_LOG_NORMAL("warning: WWPN 0x%Lx not found by nameserver lookup "
-			"using the adapter %s\n",
+			"(adapter: %s)\n",
 			port->wwpn, zfcp_get_busid_by_port(port));
 	ZFCP_LOG_DEBUG("CT IUs do not match:\n");
-	ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_DEBUG,
-		      (char *) fc_ct_iu_req, sizeof (struct fc_ct_iu));
-	ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_DEBUG,
-		      (char *) fc_ct_iu_resp, sizeof (struct fc_ct_iu));
+	ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_DEBUG, (char *) ct_iu_req,
+		      sizeof(struct ct_iu_gid_pn_req));
+	ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_DEBUG, (char *) ct_iu_resp,
+		      sizeof(struct ct_iu_gid_pn_resp));
 
  out:
-	zfcp_release_nameserver_buffers(fsf_req);
+        zfcp_gid_pn_buffers_free(gid_pn);
+	return;
 }
 
 #undef ZFCP_LOG_AREA
-#undef ZFCP_LOG_AREA_PREFIX
--- diff/drivers/s390/scsi/zfcp_ccw.c	2004-02-09 10:36:11.000000000 +0000
+++ source/drivers/s390/scsi/zfcp_ccw.c	2004-02-23 13:56:45.000000000 +0000
@@ -5,7 +5,8 @@
  *
  * CCW driver related routines
  *
- * Copyright (C) 2003 IBM Entwicklung GmbH, IBM Corporation
+ * (C) Copyright IBM Corp. 2003, 2004
+ *
  * Authors:
  *      Martin Peschke <mpeschke@de.ibm.com>
  *	Heiko Carstens <heiko.carstens@de.ibm.com>
@@ -25,7 +26,7 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
-#define ZFCP_CCW_C_REVISION "$Revision: 1.36 $"
+#define ZFCP_CCW_C_REVISION "$Revision: 1.48 $"
 
 #include <linux/init.h>
 #include <linux/module.h>
@@ -34,18 +35,22 @@
 #include "zfcp_def.h"
 
 #define ZFCP_LOG_AREA                   ZFCP_LOG_AREA_CONFIG
-#define ZFCP_LOG_AREA_PREFIX            ZFCP_LOG_AREA_PREFIX_CONFIG
 
 static int zfcp_ccw_probe(struct ccw_device *);
 static void zfcp_ccw_remove(struct ccw_device *);
 static int zfcp_ccw_set_online(struct ccw_device *);
 static int zfcp_ccw_set_offline(struct ccw_device *);
+static int zfcp_ccw_notify(struct ccw_device *, int);
 
 static struct ccw_device_id zfcp_ccw_device_id[] = {
 	{CCW_DEVICE_DEVTYPE(ZFCP_CONTROL_UNIT_TYPE,
 			    ZFCP_CONTROL_UNIT_MODEL,
 			    ZFCP_DEVICE_TYPE,
 			    ZFCP_DEVICE_MODEL)},
+	{CCW_DEVICE_DEVTYPE(ZFCP_CONTROL_UNIT_TYPE,
+			    ZFCP_CONTROL_UNIT_MODEL,
+			    ZFCP_DEVICE_TYPE,
+			    ZFCP_DEVICE_MODEL_PRIV)},
 	{},
 };
 
@@ -56,6 +61,7 @@ static struct ccw_driver zfcp_ccw_driver
 	.remove      = zfcp_ccw_remove,
 	.set_online  = zfcp_ccw_set_online,
 	.set_offline = zfcp_ccw_set_offline,
+	.notify      = zfcp_ccw_notify,
 };
 
 MODULE_DEVICE_TABLE(ccw, zfcp_ccw_device_id);
@@ -80,6 +86,9 @@ zfcp_ccw_probe(struct ccw_device *ccw_de
 	adapter = zfcp_adapter_enqueue(ccw_device);
 	if (!adapter)
 		retval = -EINVAL;
+	else
+		ZFCP_LOG_DEBUG("Probed adapter %s\n",
+			       zfcp_get_busid_by_adapter(adapter));
 	up(&zfcp_data.config_sema);
 	return retval;
 }
@@ -104,6 +113,8 @@ zfcp_ccw_remove(struct ccw_device *ccw_d
 	down(&zfcp_data.config_sema);
 	adapter = dev_get_drvdata(&ccw_device->dev);
 
+	ZFCP_LOG_DEBUG("Removing adapter %s\n",
+		       zfcp_get_busid_by_adapter(adapter));
 	write_lock_irq(&zfcp_data.config_lock);
 	list_for_each_entry_safe(port, p, &adapter->port_list_head, list) {
 		list_for_each_entry_safe(unit, u, &port->unit_list_head, list) {
@@ -152,13 +163,26 @@ zfcp_ccw_set_online(struct ccw_device *c
 	down(&zfcp_data.config_sema);
 	adapter = dev_get_drvdata(&ccw_device->dev);
 
+	retval = zfcp_erp_thread_setup(adapter);
+	if (retval) {
+		ZFCP_LOG_INFO("error: out of resources. "
+			      "error recovery thread for adapter %s "
+			      "could not be started\n",
+			      zfcp_get_busid_by_adapter(adapter));
+		goto out;
+	}
+
 	retval = zfcp_adapter_scsi_register(adapter);
 	if (retval)
-		goto out;
+		goto out_scsi_register;
 	zfcp_erp_modify_adapter_status(adapter, ZFCP_STATUS_COMMON_RUNNING,
 				       ZFCP_SET);
 	zfcp_erp_adapter_reopen(adapter, ZFCP_STATUS_COMMON_ERP_FAILED);
 	zfcp_erp_wait(adapter);
+	goto out;
+
+ out_scsi_register:
+	zfcp_erp_thread_kill(adapter);
  out:
 	up(&zfcp_data.config_sema);
 	return retval;
@@ -183,11 +207,50 @@ zfcp_ccw_set_offline(struct ccw_device *
 	zfcp_erp_adapter_shutdown(adapter, 0);
 	zfcp_erp_wait(adapter);
 	zfcp_adapter_scsi_unregister(adapter);
+	zfcp_erp_thread_kill(adapter);
 	up(&zfcp_data.config_sema);
 	return 0;
 }
 
 /**
+ * zfcp_ccw_notify
+ * @ccw_device: pointer to belonging ccw device
+ * @event: indicates if adapter was detached or attached
+ *
+ * This function gets called by the common i/o layer if an adapter has gone
+ * or reappeared.
+ */
+static int
+zfcp_ccw_notify(struct ccw_device *ccw_device, int event)
+{
+	struct zfcp_adapter *adapter;
+
+	down(&zfcp_data.config_sema);
+	adapter = dev_get_drvdata(&ccw_device->dev);
+	switch (event) {
+	case CIO_GONE:
+		ZFCP_LOG_NORMAL("Adapter %s: device gone.\n",
+				zfcp_get_busid_by_adapter(adapter));
+		break;
+	case CIO_NO_PATH:
+		ZFCP_LOG_NORMAL("Adapter %s: no path.\n",
+				zfcp_get_busid_by_adapter(adapter));
+		break;
+	case CIO_OPER:
+		ZFCP_LOG_NORMAL("Adapter %s: operational again.\n",
+				zfcp_get_busid_by_adapter(adapter));
+		zfcp_erp_modify_adapter_status(adapter,
+					       ZFCP_STATUS_COMMON_RUNNING,
+					       ZFCP_SET);
+		zfcp_erp_adapter_reopen(adapter,
+					ZFCP_STATUS_COMMON_ERP_FAILED);
+		break;
+	}
+	up(&zfcp_data.config_sema);
+	return 1;
+}
+
+/**
  * zfcp_ccw_register - ccw register function
  *
  * Registers the driver at the common i/o layer. This function will be called
@@ -222,4 +285,3 @@ zfcp_ccw_unregister(void)
 }
 
 #undef ZFCP_LOG_AREA
-#undef ZFCP_LOG_AREA_PREFIX
--- diff/drivers/s390/scsi/zfcp_def.h	2004-02-09 10:36:11.000000000 +0000
+++ source/drivers/s390/scsi/zfcp_def.h	2004-02-23 13:56:45.000000000 +0000
@@ -4,11 +4,12 @@
  * 
  * FCP adapter driver for IBM eServer zSeries 
  * 
- * Copyright 2002 IBM Corporation 
+ * (C) Copyright IBM Corp. 2002, 2004
+ *
  * Author(s): Martin Peschke <mpeschke@de.ibm.com> 
  *            Raimund Schroeder <raimund.schroeder@de.ibm.com> 
- *            Aron Zeh <arzeh@de.ibm.com> 
- *            Wolfgang Taphorn <taphorn@de.ibm.com> 
+ *            Aron Zeh
+ *            Wolfgang Taphorn
  *            Stefan Bader <stefan.bader@de.ibm.com> 
  *            Heiko Carstens <heiko.carstens@de.ibm.com> 
  * 
@@ -32,19 +33,29 @@
 #define ZFCP_DEF_H
 
 /* this drivers version (do not edit !!! generated and updated by cvs) */
-#define ZFCP_DEF_REVISION "$Revision: 1.48 $"
+#define ZFCP_DEF_REVISION "$Revision: 1.62 $"
 
 /*************************** INCLUDES *****************************************/
 
 #include <linux/blkdev.h>
+#include <scsi/scsi.h>
+#include <scsi/scsi_tcq.h>
+#include <scsi/scsi_cmnd.h>
+#include <scsi/scsi_device.h>
+#include <scsi/scsi_host.h>
 #include "../../scsi/scsi.h"
-#include "../../scsi/hosts.h"
 #include "../../fc4/fc.h"
 #include "zfcp_fsf.h"			/* FSF SW Interface */
 #include <asm/ccwdev.h>
 #include <asm/qdio.h>
 #include <asm/debug.h>
+#include <asm/ebcdic.h>
 #include <linux/reboot.h>
+#include <linux/mempool.h>
+#include <linux/ioctl.h>
+#ifdef CONFIG_S390_SUPPORT
+#include <linux/ioctl32.h>
+#endif
 
 /************************ DEBUG FLAGS *****************************************/
 
@@ -56,6 +67,24 @@
 #define	ZFCP_STAT_REQSIZES
 #define	ZFCP_STAT_QUEUES
 
+/********************* GENERAL DEFINES *********************************/
+
+/* zfcp version number, it consists of major, minor, and patch-level number */
+#define ZFCP_VERSION		"4.0.0"
+
+static inline void *
+zfcp_sg_to_address(struct scatterlist *list)
+{
+	return (void *) (page_address(list->page) + list->offset);
+}
+
+static inline void
+zfcp_address_to_sg(void *address, struct scatterlist *list)
+{
+	list->page = virt_to_page(address);
+	list->offset = ((unsigned long) address) & (PAGE_SIZE - 1);
+}
+
 /********************* SCSI SPECIFIC DEFINES *********************************/
 
 /* 32 bit for SCSI ID and LUN as long as the SCSI stack uses this type */
@@ -64,7 +93,6 @@ typedef u32 scsi_lun_t;
 
 #define ZFCP_ERP_SCSI_LOW_MEM_TIMEOUT           (100*HZ)
 #define ZFCP_SCSI_ER_TIMEOUT                    (100*HZ)
-#define ZFCP_SCSI_HOST_FLUSH_TIMEOUT            (1*HZ)
 
 /********************* CIO/QDIO SPECIFIC DEFINES *****************************/
 
@@ -73,9 +101,12 @@ typedef u32 scsi_lun_t;
 #define ZFCP_CONTROL_UNIT_MODEL 0x03
 #define ZFCP_DEVICE_TYPE        0x1732
 #define ZFCP_DEVICE_MODEL       0x03
+#define ZFCP_DEVICE_MODEL_PRIV	0x04
  
 /* allow as many chained SBALs as are supported by hardware */
 #define ZFCP_MAX_SBALS_PER_REQ		FSF_MAX_SBALS_PER_REQ
+#define ZFCP_MAX_SBALS_PER_CT_REQ	FSF_MAX_SBALS_PER_REQ
+#define ZFCP_MAX_SBALS_PER_ELS_REQ	FSF_MAX_SBALS_PER_ELS_REQ
 
 /* DMQ bug workaround: don't use last SBALE */
 #define ZFCP_MAX_SBALES_PER_SBAL	(QDIO_MAX_ELEMENTS_PER_BUFFER - 1)
@@ -115,9 +146,6 @@ typedef u32 scsi_lun_t;
 #define ZFCP_EXCHANGE_CONFIG_DATA_RETRIES	6
 #define ZFCP_EXCHANGE_CONFIG_DATA_SLEEP		50
 
-#define ZFCP_QTCB_SIZE		(sizeof(struct fsf_qtcb) + FSF_QTCB_LOG_SIZE)
-#define ZFCP_QTCB_AND_REQ_SIZE	(sizeof(struct zfcp_fsf_req) + ZFCP_QTCB_SIZE)
-
 /*************** FIBRE CHANNEL PROTOCOL SPECIFIC DEFINES ********************/
 
 typedef unsigned long long wwn_t;
@@ -129,7 +157,8 @@ typedef unsigned int       fcp_dl_t;
 #define ZFCP_FC_SERVICE_CLASS_DEFAULT	FSF_CLASS_3
 
 /* timeout for name-server lookup (in seconds) */
-#define ZFCP_NAMESERVER_TIMEOUT		10
+#define ZFCP_NS_GID_PN_TIMEOUT		10
+#define ZFCP_NS_GA_NXT_TIMEOUT		120
 
 /* largest SCSI command we can process */
 /* FCP-2 (FCP_CMND IU) allows up to (255-3+16) */
@@ -241,33 +270,177 @@ struct fcp_logo {
         wwn_t nport_wwpn;
 } __attribute__((packed));
 
-struct fc_ct_iu {
-	u8	revision;	/* 0x01 */
-	u8	in_id[3];	/* 0x00 */
-	u8	gs_type;	/* 0xFC	Directory Service */
-	u8	gs_subtype;	/* 0x02	Name Server */
-	u8	options;	/* 0x10 synchronous/single exchange */
-	u8	reserved0;
-	u16	cmd_rsp_code;	/* 0x0121 GID_PN */
-	u16	max_res_size;	/* <= (4096 - 16) / 4 */
-	u8	reserved1;
+/*
+ * FC-FS stuff
+ */
+#define R_A_TOV				10 /* seconds */
+#define ZFCP_ELS_TIMEOUT		(2 * R_A_TOV)
+
+#define ZFCP_LS_RJT			0x01
+#define ZFCP_LS_ACC			0x02
+#define ZFCP_LS_RTV			0x0E
+#define ZFCP_LS_RLS			0x0F
+#define ZFCP_LS_PDISC			0x50
+#define ZFCP_LS_ADISC			0x52
+#define ZFCP_LS_RSCN			0x61
+#define ZFCP_LS_RNID			0x78
+#define ZFCP_LS_RLIR			0x7A
+#define ZFCP_LS_RTV_E_D_TOV_FLAG	0x04000000
+
+/* LS_ACC Reason Codes */
+#define ZFCP_LS_RJT_INVALID_COMMAND_CODE	0x01
+#define ZFCP_LS_RJT_LOGICAL_ERROR		0x03
+#define ZFCP_LS_RJT_LOGICAL_BUSY		0x05
+#define ZFCP_LS_RJT_PROTOCOL_ERROR		0x07
+#define ZFCP_LS_RJT_UNABLE_TO_PERFORM		0x09
+#define ZFCP_LS_RJT_COMMAND_NOT_SUPPORTED	0x0B
+#define ZFCP_LS_RJT_VENDOR_UNIQUE_ERROR		0xFF
+
+struct zfcp_ls_rjt {
+	u8		code;
+	u8		field[3];
+	u8		reserved;
 	u8	reason_code;
-	u8	reason_code_expl;
+	u8		reason_expl;
 	u8	vendor_unique;
-	union {
+} __attribute__ ((packed));
+
+struct zfcp_ls_rtv {
+	u8		code;
+	u8		field[3];
+} __attribute__ ((packed));
+
+struct zfcp_ls_rtv_acc {
+	u8		code;
+	u8		field[3];
+	u32		r_a_tov;
+	u32		e_d_tov;
+	u32		qualifier;
+} __attribute__ ((packed));
+
+struct zfcp_ls_rls {
+	u8		code;
+	u8		field[3];
+	fc_id_t		port_id;
+} __attribute__ ((packed));
+
+struct zfcp_ls_rls_acc {
+	u8		code;
+	u8		field[3];
+	u32		link_failure_count;
+	u32		loss_of_sync_count;
+	u32		loss_of_signal_count;
+	u32		prim_seq_prot_error;
+	u32		invalid_transmition_word;
+	u32		invalid_crc_count;
+} __attribute__ ((packed));
+
+struct zfcp_ls_pdisc {
+	u8		code;
+	u8		field[3];
+	u8		common_svc_parm[16];
 		wwn_t	wwpn;
-		fc_id_t	d_id;
-	} data;
+	wwn_t		wwnn;
+	struct {
+		u8	class1[16];
+		u8	class2[16];
+		u8	class3[16];
+	} svc_parm;
+	u8		reserved[16];
+	u8		vendor_version[16];
 } __attribute__ ((packed));
 
+struct zfcp_ls_pdisc_acc {
+	u8		code;
+	u8		field[3];
+	u8		common_svc_parm[16];
+	wwn_t		wwpn;
+	wwn_t		wwnn;
+	struct {
+		u8	class1[16];
+		u8	class2[16];
+		u8	class3[16];
+	} svc_parm;
+	u8		reserved[16];
+	u8		vendor_version[16];
+} __attribute__ ((packed));
+
+struct zfcp_ls_adisc {
+	u8		code;
+	u8		field[3];
+	fc_id_t		hard_nport_id;
+	wwn_t		wwpn;
+	wwn_t		wwnn;
+	fc_id_t		nport_id;
+} __attribute__ ((packed));
+
+struct zfcp_ls_adisc_acc {
+	u8		code;
+	u8		field[3];
+	fc_id_t		hard_nport_id;
+	wwn_t		wwpn;
+	wwn_t		wwnn;
+	fc_id_t		nport_id;
+} __attribute__ ((packed));
+
+struct zfcp_ls_rnid {
+	u8		code;
+	u8		field[3];
+	u8		node_id_format;
+	u8		reserved[3];
+} __attribute__((packed));
+
+/* common identification data */
+struct zfcp_ls_rnid_common_id {
+	u64		n_port_name;
+	u64		node_name;
+} __attribute__((packed));
+
+/* general topology specific identification data */
+struct zfcp_ls_rnid_general_topology_id {
+	u8		vendor_unique[16];
+	u32		associated_type;
+	u32		physical_port_number;
+	u32		nr_attached_nodes;
+	u8		node_management;
+	u8		ip_version;
+	u16		port_number;
+	u8		ip_address[16];
+	u8		reserved[2];
+	u16		vendor_specific;
+} __attribute__((packed));
+
+struct zfcp_ls_rnid_acc {
+	u8		code;
+	u8		field[3];
+	u8		node_id_format;
+	u8		common_id_length;
+	u8		reserved;
+	u8		specific_id_length;
+	struct zfcp_ls_rnid_common_id
+			common_id;
+	struct zfcp_ls_rnid_general_topology_id
+			specific_id;
+} __attribute__((packed));
+
+/*
+ * FC-GS-2 stuff
+ */
 #define ZFCP_CT_REVISION		0x01
 #define ZFCP_CT_DIRECTORY_SERVICE	0xFC
 #define ZFCP_CT_NAME_SERVER		0x02
 #define ZFCP_CT_SYNCHRONOUS		0x00
 #define ZFCP_CT_GID_PN			0x0121
+#define ZFCP_CT_GA_NXT			0x0100
 #define ZFCP_CT_MAX_SIZE		0x1020
 #define ZFCP_CT_ACCEPT			0x8002
 
+/*
+ * FC-GS-4 stuff
+ */
+#define ZFCP_CT_TIMEOUT			(3 * R_A_TOV)
+
+
 /***************** S390 DEBUG FEATURE SPECIFIC DEFINES ***********************/
 
 /* debug feature entries per adapter */
@@ -333,16 +506,6 @@ struct fc_ct_iu {
 #define ZFCP_LOG_LEVEL_DEBUG	2
 #define ZFCP_LOG_LEVEL_TRACE	3
 
-/* default log levels for different log areas */
-#define ZFCP_LOG_LEVEL_DEFAULT_OTHER	ZFCP_LOG_LEVEL_INFO
-#define ZFCP_LOG_LEVEL_DEFAULT_SCSI	ZFCP_LOG_LEVEL_INFO
-#define ZFCP_LOG_LEVEL_DEFAULT_FSF	ZFCP_LOG_LEVEL_INFO
-#define ZFCP_LOG_LEVEL_DEFAULT_CONFIG	ZFCP_LOG_LEVEL_INFO
-#define ZFCP_LOG_LEVEL_DEFAULT_CIO	ZFCP_LOG_LEVEL_INFO
-#define ZFCP_LOG_LEVEL_DEFAULT_QDIO	ZFCP_LOG_LEVEL_INFO
-#define ZFCP_LOG_LEVEL_DEFAULT_ERP	ZFCP_LOG_LEVEL_INFO
-#define ZFCP_LOG_LEVEL_DEFAULT_FC	ZFCP_LOG_LEVEL_INFO
-
 /*
  * this allows removal of logging code by the preprocessor
  * (the most detailed log level still to be compiled in is specified, 
@@ -350,93 +513,75 @@ struct fc_ct_iu {
  */
 #define ZFCP_LOG_LEVEL_LIMIT	ZFCP_LOG_LEVEL_TRACE
 
-/* positional "loglevel" nibble assignment */
-#define ZFCP_LOG_VALUE(zfcp_lognibble) \
+/* get "loglevel" nibble assignment */
+#define ZFCP_GET_LOG_VALUE(zfcp_lognibble) \
 	       ((atomic_read(&zfcp_data.loglevel) >> (zfcp_lognibble<<2)) & 0xF)
 
-#define ZFCP_LOG_VALUE_OTHER	ZFCP_LOG_VALUE(ZFCP_LOG_AREA_OTHER)
-#define ZFCP_LOG_VALUE_SCSI	ZFCP_LOG_VALUE(ZFCP_LOG_AREA_SCSI)
-#define ZFCP_LOG_VALUE_FSF	ZFCP_LOG_VALUE(ZFCP_LOG_AREA_FSF)
-#define ZFCP_LOG_VALUE_CONFIG	ZFCP_LOG_VALUE(ZFCP_LOG_AREA_CONFIG)
-#define ZFCP_LOG_VALUE_CIO	ZFCP_LOG_VALUE(ZFCP_LOG_AREA_CIO)
-#define ZFCP_LOG_VALUE_QDIO	ZFCP_LOG_VALUE(ZFCP_LOG_AREA_QDIO)
-#define ZFCP_LOG_VALUE_ERP	ZFCP_LOG_VALUE(ZFCP_LOG_AREA_ERP)
-#define ZFCP_LOG_VALUE_FC	ZFCP_LOG_VALUE(ZFCP_LOG_AREA_FC)
+/* set "loglevel" nibble */
+#define ZFCP_SET_LOG_NIBBLE(value, zfcp_lognibble) \
+	       (value << (zfcp_lognibble << 2))
 
 /* all log-level defaults are combined to generate initial log-level */
 #define ZFCP_LOG_LEVEL_DEFAULTS \
-	((ZFCP_LOG_LEVEL_DEFAULT_OTHER	<< (ZFCP_LOG_AREA_OTHER<<2))	| \
-	 (ZFCP_LOG_LEVEL_DEFAULT_SCSI	<< (ZFCP_LOG_AREA_SCSI<<2))	| \
-	 (ZFCP_LOG_LEVEL_DEFAULT_FSF	<< (ZFCP_LOG_AREA_FSF<<2))	| \
-	 (ZFCP_LOG_LEVEL_DEFAULT_CONFIG	<< (ZFCP_LOG_AREA_CONFIG<<2))	| \
-	 (ZFCP_LOG_LEVEL_DEFAULT_CIO	<< (ZFCP_LOG_AREA_CIO<<2))	| \
-	 (ZFCP_LOG_LEVEL_DEFAULT_QDIO	<< (ZFCP_LOG_AREA_QDIO<<2))	| \
-	 (ZFCP_LOG_LEVEL_DEFAULT_ERP	<< (ZFCP_LOG_AREA_ERP<<2))      | \
-	 (ZFCP_LOG_LEVEL_DEFAULT_FC	<< (ZFCP_LOG_AREA_FC<<2)))
-
-/* the prefix placed at the beginning of each driver message */
-#define ZFCP_LOG_PREFIX ZFCP_NAME": "
-
-/* log area specific prefixes */
-#define ZFCP_LOG_AREA_PREFIX_OTHER	""
-#define ZFCP_LOG_AREA_PREFIX_SCSI	"SCSI: "
-#define ZFCP_LOG_AREA_PREFIX_FSF	"FSF: "
-#define ZFCP_LOG_AREA_PREFIX_CONFIG	"config: "
-#define ZFCP_LOG_AREA_PREFIX_CIO	"common I/O: "
-#define ZFCP_LOG_AREA_PREFIX_QDIO	"QDIO: "
-#define ZFCP_LOG_AREA_PREFIX_ERP	"ERP: "
-#define ZFCP_LOG_AREA_PREFIX_FC 	"FC: "
+	(ZFCP_SET_LOG_NIBBLE(ZFCP_LOG_LEVEL_INFO, ZFCP_LOG_AREA_OTHER) | \
+	 ZFCP_SET_LOG_NIBBLE(ZFCP_LOG_LEVEL_INFO, ZFCP_LOG_AREA_SCSI) | \
+	 ZFCP_SET_LOG_NIBBLE(ZFCP_LOG_LEVEL_INFO, ZFCP_LOG_AREA_FSF) | \
+	 ZFCP_SET_LOG_NIBBLE(ZFCP_LOG_LEVEL_INFO, ZFCP_LOG_AREA_CONFIG) | \
+	 ZFCP_SET_LOG_NIBBLE(ZFCP_LOG_LEVEL_INFO, ZFCP_LOG_AREA_CIO) | \
+	 ZFCP_SET_LOG_NIBBLE(ZFCP_LOG_LEVEL_INFO, ZFCP_LOG_AREA_QDIO) | \
+	 ZFCP_SET_LOG_NIBBLE(ZFCP_LOG_LEVEL_INFO, ZFCP_LOG_AREA_ERP) | \
+	 ZFCP_SET_LOG_NIBBLE(ZFCP_LOG_LEVEL_INFO, ZFCP_LOG_AREA_FC))
 
 /* check whether we have the right level for logging */
-#define ZFCP_LOG_CHECK(ll)	(ZFCP_LOG_VALUE(ZFCP_LOG_AREA)) >= ll
-
-/* As we have two printks it is possible for them to be seperated by another
- * message. This holds true even for printks from within this module.
- * In any case there should only be a small readability hit, however.
- */
-#define _ZFCP_LOG(m...) \
-		{ \
-			printk( "%s%s: ", \
-				ZFCP_LOG_PREFIX ZFCP_LOG_AREA_PREFIX, \
-				__FUNCTION__); \
-			printk(m); \
-		}
+#define ZFCP_LOG_CHECK(level) \
+	((ZFCP_GET_LOG_VALUE(ZFCP_LOG_AREA)) >= level)
 
-#define ZFCP_LOG(ll, m...) \
-		if (ZFCP_LOG_CHECK(ll)) \
-			_ZFCP_LOG(m)
+/* logging routine for zfcp */
+#define _ZFCP_LOG(fmt, args...) \
+	printk(KERN_ERR ZFCP_NAME": %s(%d): " fmt, __FUNCTION__, \
+	       __LINE__ , ##args);
+
+#define ZFCP_LOG(level, fmt, args...) \
+	if (ZFCP_LOG_CHECK(level)) \
+		_ZFCP_LOG(fmt , ##args)
 	
 #if ZFCP_LOG_LEVEL_LIMIT < ZFCP_LOG_LEVEL_NORMAL
-#define ZFCP_LOG_NORMAL(m...)
-#else	/* ZFCP_LOG_LEVEL_LIMIT >= ZFCP_LOG_LEVEL_NORMAL */
-#define ZFCP_LOG_NORMAL(m...)		ZFCP_LOG(ZFCP_LOG_LEVEL_NORMAL, m)
+# define ZFCP_LOG_NORMAL(fmt, args...)
+#else
+# define ZFCP_LOG_NORMAL(fmt, args...) \
+	if (ZFCP_LOG_CHECK(ZFCP_LOG_LEVEL_NORMAL)) \
+		printk(KERN_ERR ZFCP_NAME": " fmt , ##args);
 #endif
 
 #if ZFCP_LOG_LEVEL_LIMIT < ZFCP_LOG_LEVEL_INFO
-#define ZFCP_LOG_INFO(m...)
-#else	/* ZFCP_LOG_LEVEL_LIMIT >= ZFCP_LOG_LEVEL_INFO */
-#define ZFCP_LOG_INFO(m...)		ZFCP_LOG(ZFCP_LOG_LEVEL_INFO, m)
+# define ZFCP_LOG_INFO(fmt, args...)
+#else
+# define ZFCP_LOG_INFO(fmt, args...) \
+	if (ZFCP_LOG_CHECK(ZFCP_LOG_LEVEL_INFO)) \
+		printk(KERN_ERR ZFCP_NAME": " fmt , ##args);
 #endif
 
 #if ZFCP_LOG_LEVEL_LIMIT < ZFCP_LOG_LEVEL_DEBUG
-#define ZFCP_LOG_DEBUG(m...)
-#else	/* ZFCP_LOG_LEVEL_LIMIT >= ZFCP_LOG_LEVEL_DEBUG */
-#define ZFCP_LOG_DEBUG(m...)		ZFCP_LOG(ZFCP_LOG_LEVEL_DEBUG, m)
+# define ZFCP_LOG_DEBUG(fmt, args...)
+#else
+# define ZFCP_LOG_DEBUG(fmt, args...) \
+	ZFCP_LOG(ZFCP_LOG_LEVEL_DEBUG, fmt , ##args)
 #endif
 
 #if ZFCP_LOG_LEVEL_LIMIT < ZFCP_LOG_LEVEL_TRACE
-#define ZFCP_LOG_TRACE(m...)
-#else	/* ZFCP_LOG_LEVEL_LIMIT >= ZFCP_LOG_LEVEL_TRACE */
-#define ZFCP_LOG_TRACE(m...)		ZFCP_LOG(ZFCP_LOG_LEVEL_TRACE, m)
+# define ZFCP_LOG_TRACE(fmt, args...)
+#else
+# define ZFCP_LOG_TRACE(fmt, args...) \
+	ZFCP_LOG(ZFCP_LOG_LEVEL_TRACE, fmt , ##args)
 #endif
 
-#ifdef ZFCP_PRINT_FLAGS
-extern u32 flags_dump;
-#define ZFCP_LOG_FLAGS(ll, m...) \
-		if (ll<=flags_dump) \
-			_ZFCP_LOG(m)
+#ifndef ZFCP_PRINT_FLAGS
+# define ZFCP_LOG_FLAGS(level, fmt, args...)
 #else
-#define ZFCP_LOG_FLAGS(ll, m...)
+extern u32 flags_dump;
+# define ZFCP_LOG_FLAGS(level, fmt, args...) \
+	if (level <= flags_dump) \
+		_ZFCP_LOG(fmt , ##args)
 #endif
 
 /*************** ADAPTER/PORT/UNIT AND FSF_REQ STATUS FLAGS ******************/
@@ -506,19 +651,19 @@ extern u32 flags_dump;
 #define ZFCP_STATUS_FSFREQ_TMFUNCNOTSUPP        0x00000400
 #define ZFCP_STATUS_FSFREQ_RETRY                0x00000800
 #define ZFCP_STATUS_FSFREQ_DISMISSED            0x00001000
-#define ZFCP_STATUS_FSFREQ_POOLBUF              0x00002000
 
 /*********************** ERROR RECOVERY PROCEDURE DEFINES ********************/
 
 #define ZFCP_MAX_ERPS                   3
 
-#define ZFCP_ERP_FSFREQ_TIMEOUT		(100 * HZ)
+#define ZFCP_ERP_FSFREQ_TIMEOUT		(30 * HZ)
 #define ZFCP_ERP_MEMWAIT_TIMEOUT	HZ
 
 #define ZFCP_STATUS_ERP_TIMEDOUT	0x10000000
 #define ZFCP_STATUS_ERP_CLOSE_ONLY	0x01000000
 #define ZFCP_STATUS_ERP_DISMISSING	0x00100000
 #define ZFCP_STATUS_ERP_DISMISSED	0x00200000
+#define ZFCP_STATUS_ERP_LOWMEM		0x00400000
 
 #define ZFCP_ERP_STEP_UNINITIALIZED	0x00000000
 #define ZFCP_ERP_STEP_FSF_XCONFIG	0x00000001
@@ -546,19 +691,55 @@ extern u32 flags_dump;
 #define ZFCP_ERP_DISMISSED	0x4
 #define ZFCP_ERP_NOMEM		0x5
 
-/************************* STRUCTURE DEFINITIONS *****************************/
+
+/******************** CFDC SPECIFIC STUFF *****************************/
+
+/* Firewall data channel sense data record */
+struct zfcp_cfdc_sense_data {
+	u32 signature;           /* Request signature */
+	u32 devno;               /* FCP adapter device number */
+	u32 command;             /* Command code */
+	u32 fsf_status;          /* FSF request status and status qualifier */
+	u8  fsf_status_qual[FSF_STATUS_QUALIFIER_SIZE];
+	u8  payloads[256];       /* Access conflicts list */
+	u8  control_file[0];     /* Access control table */
+};
+
+#define ZFCP_CFDC_SIGNATURE			0xCFDCACDF
+
+#define ZFCP_CFDC_CMND_DOWNLOAD_NORMAL		0x00010001
+#define ZFCP_CFDC_CMND_DOWNLOAD_FORCE		0x00010101
+#define ZFCP_CFDC_CMND_FULL_ACCESS		0x00000201
+#define ZFCP_CFDC_CMND_RESTRICTED_ACCESS	0x00000401
+#define ZFCP_CFDC_CMND_UPLOAD			0x00010002
+
+#define ZFCP_CFDC_DOWNLOAD			0x00000001
+#define ZFCP_CFDC_UPLOAD			0x00000002
+#define ZFCP_CFDC_WITH_CONTROL_FILE		0x00010000
+
+#define ZFCP_CFDC_DEV_NAME			"zfcp_cfdc"
+#define ZFCP_CFDC_DEV_MAJOR			MISC_MAJOR
+#define ZFCP_CFDC_DEV_MINOR			MISC_DYNAMIC_MINOR
+
+#define ZFCP_CFDC_MAX_CONTROL_FILE_SIZE		127 * 1024
+
+static const char zfcp_act_subtable_type[5][8] = {
+	{"unknown"}, {"OS"}, {"WWPN"}, {"DID"}, {"LUN"}
+};
 
 
+/************************* STRUCTURE DEFINITIONS *****************************/
+
 struct zfcp_fsf_req;
-typedef void zfcp_send_generic_handler_t(struct zfcp_fsf_req*);
 
+/* holds various memory pools of an adapter */
 struct zfcp_adapter_mempool {
-        mempool_t *status_read_fsf;
-	mempool_t *status_read_buf;
-        mempool_t *nameserver;
-        mempool_t *erp_fsf;
-        mempool_t *fcp_command_fsf;
-        struct timer_list fcp_command_fsf_timer;
+	mempool_t *fsf_req_erp;
+	mempool_t *fsf_req_scsi;
+	mempool_t *fsf_req_abort;
+	mempool_t *fsf_req_status_read;
+	mempool_t *data_status_read;
+	mempool_t *data_gid_pn;
 };
 
 struct  zfcp_exchange_config_data{
@@ -587,7 +768,7 @@ struct zfcp_close_physical_port {
 struct zfcp_send_fcp_command_task {
 	struct zfcp_fsf_req *fsf_req;
 	struct zfcp_unit *unit;
- 	Scsi_Cmnd *scsi_cmnd;
+ 	struct scsi_cmnd *scsi_cmnd;
 	unsigned long start_jiffies;
 };
 
@@ -600,20 +781,119 @@ struct zfcp_abort_fcp_command {
 	struct zfcp_unit *unit;
 };
 
-struct zfcp_send_generic {
+/*
+ * header for CT_IU
+ */
+struct ct_hdr {
+	u8 revision;		// 0x01
+	u8 in_id[3];		// 0x00
+	u8 gs_type;		// 0xFC	Directory Service
+	u8 gs_subtype;		// 0x02	Name Server
+	u8 options;		// 0x00 single bidirectional exchange
+	u8 reserved0;
+	u16 cmd_rsp_code;	// 0x0121 GID_PN, or 0x0100 GA_NXT
+	u16 max_res_size;	// <= (4096 - 16) / 4
+	u8 reserved1;
+	u8 reason_code;
+	u8 reason_code_expl;
+	u8 vendor_unique;
+} __attribute__ ((packed));
+
+/* nameserver request CT_IU -- for requests where
+ * a port name is required */
+struct ct_iu_gid_pn_req {
+	struct ct_hdr header;
+	wwn_t wwpn;
+} __attribute__ ((packed));
+
+/* nameserver request CT_IU -- for requests where
+ * a port identifier is required */
+struct ct_iu_ga_nxt_req {
+	struct ct_hdr header;
+	fc_id_t d_id;
+} __attribute__ ((packed));
+
+/* FS_ACC IU and data unit for GID_PN nameserver request */
+struct ct_iu_gid_pn_resp {
+	struct ct_hdr header;
+	fc_id_t d_id;
+} __attribute__ ((packed));
+
+/* FS_ACC IU and data unit for GA_NXT nameserver request */
+struct ct_iu_ga_nxt_resp {
+	struct ct_hdr header;
+        u8 port_type;
+        u8 port_id[3];
+        u64 port_wwn;
+        u8 port_symbolic_name_length;
+        u8 port_symbolic_name[255];
+        u64 node_wwn;
+        u8 node_symbolic_name_length;
+        u8 node_symbolic_name[255];
+        u64 initial_process_associator;
+        u8 node_ip[16];
+        u32 cos;
+        u8 fc4_types[32];
+        u8 port_ip[16];
+        u64 fabric_wwn;
+        u8 reserved;
+        u8 hard_address[3];
+} __attribute__ ((packed));
+
+typedef void (*zfcp_send_ct_handler_t)(unsigned long);
+
+/* used to pass parameters to zfcp_send_ct() */
+struct zfcp_send_ct {
+	struct zfcp_port *port;
+	struct scatterlist *req;
+	struct scatterlist *resp;
+	unsigned int req_count;
+	unsigned int resp_count;
+	zfcp_send_ct_handler_t handler;
+	unsigned long handler_data;
+	mempool_t *pool;		/* mempool for ct not for fsf_req */
+	int timeout;
+	struct timer_list *timer;
+	struct completion *completion;
+	int status;
+};
+
+/* used for name server requests in error recovery */
+struct zfcp_gid_pn_data {
+	struct zfcp_send_ct ct;
+	struct scatterlist req;
+	struct scatterlist resp;
+	struct ct_iu_gid_pn_req ct_iu_req;
+	struct ct_iu_gid_pn_resp ct_iu_resp;
         struct zfcp_port *port;
-	char *outbuf;
-	char *inbuf;
-	int outbuf_length;
-	int inbuf_length;
-	zfcp_send_generic_handler_t *handler;
+};
+
+typedef int (*zfcp_send_els_handler_t)(unsigned long);
+
+/* used to pass parameters to zfcp_send_els() */
+/* ToDo merge send_ct() and send_els() and corresponding structs */
+struct zfcp_send_els {
+	struct zfcp_port *port;
+	struct scatterlist *req;
+	struct scatterlist *resp;
+	unsigned int req_count;
+	unsigned int resp_count;
+	zfcp_send_els_handler_t handler;
 	unsigned long handler_data;
+	struct completion *completion;
+	int ls_code;
+	int status;
 };
 
 struct zfcp_status_read {
 	struct fsf_status_read_buffer *buffer;
 };
 
+struct zfcp_fsf_done {
+	struct completion *complete;
+	int status;
+};
+
 /* request specific data */
 union zfcp_req_data {
 	struct zfcp_exchange_config_data exchange_config_data;
@@ -626,7 +906,8 @@ union zfcp_req_data {
         struct zfcp_send_fcp_command_task_management
 					  send_fcp_command_task_management;
 	struct zfcp_abort_fcp_command	  abort_fcp_command;
-	struct zfcp_send_generic	  send_generic;
+	struct zfcp_send_ct *send_ct;
+	struct zfcp_send_els *send_els;
 	struct zfcp_status_read 	  status_read;
 };
 
@@ -671,6 +952,9 @@ struct zfcp_adapter {
 	u32			fc_link_speed;	   /* FC interface speed */
 	u32			hydra_version;	   /* Hydra version */
 	u32			fsf_lic_version;
+        u32			supported_features;/* of FCP channel */
+        u32			hardware_version;  /* of FCP channel */
+        u8			serial_number[32]; /* of hardware */
 	struct Scsi_Host	*scsi_host;	   /* Pointer to mid-layer */
 
 	unsigned char		name[9];
@@ -704,6 +988,10 @@ struct zfcp_adapter {
 	wait_queue_head_t	erp_done_wqh;
 	struct zfcp_erp_action	erp_action;	   /* pending error recovery */
         atomic_t                erp_counter;
+	u32			erp_total_count;   /* total nr of enqueued erp
+						      actions */
+	u32			erp_low_mem_count; /* nr of erp actions waiting
+						      for memory */
 	struct zfcp_port	*nameserver_port;  /* adapter's nameserver */
         debug_info_t            *erp_dbf;          /* S/390 debug features */
 	debug_info_t            *abort_dbf;
@@ -751,7 +1039,7 @@ struct zfcp_unit {
 	scsi_lun_t	       scsi_lun;       /* own SCSI LUN */
 	fcp_lun_t	       fcp_lun;	       /* own FCP_LUN */
 	u32		       handle;	       /* handle assigned by FSF */
-        Scsi_Device            *device;        /* scsi device struct pointer */
+        struct scsi_device     *device;        /* scsi device struct pointer */
 	struct zfcp_erp_action erp_action;     /* pending error recovery */
         atomic_t               erp_counter;
 	struct device          sysfs_device;   /* sysfs device */
@@ -765,8 +1053,14 @@ struct zfcp_fsf_req {
 	u32		       specific_magic; /* structure specific magic */
 	struct list_head       list;	       /* list of FSF requests */
 	struct zfcp_adapter    *adapter;       /* adapter request belongs to */
-	u8		       sbal_count;     /* # of SBALs in FSF request */
-	u8		       sbal_index;     /* position of 1st SBAL */
+	u8		       sbal_number;    /* nr of SBALs free for use */
+	u8		       sbal_first;     /* first SBAL for this request */
+	u8		       sbal_last;      /* last possible SBAL for
+						  this reuest */
+	u8		       sbal_curr;      /* current SBAL during creation
+						  of request */
+	u8		       sbale_curr;     /* current SBALE during creation
+						  of request */
 	wait_queue_head_t      completion_wq;  /* can be used by a routine
 						  to wait for completion */
 	volatile u32	       status;	       /* status of this request */
@@ -776,13 +1070,15 @@ struct zfcp_fsf_req {
         union zfcp_req_data    data;           /* Info fields of request */ 
 	struct zfcp_erp_action *erp_action;    /* used if this request is
 						  issued on behalf of erp */
+	mempool_t	       *pool;	       /* used if request was alloacted
+						  from emergency pool */
 };
 
 typedef void zfcp_fsf_req_handler_t(struct zfcp_fsf_req*);
 
 /* driver data */
 struct zfcp_data {
-	Scsi_Host_Template	scsi_host_template;
+	struct scsi_host_template scsi_host_template;
         atomic_t                status;             /* Module status flags */
 	struct list_head	adapter_list_head;  /* head of adapter list */
 	struct list_head	adapter_remove_lh;  /* head of adapters to be
@@ -792,7 +1088,7 @@ struct zfcp_data {
         struct list_head        status_read_send_head;
         struct semaphore        status_read_sema;
 	wait_queue_head_t	status_read_thread_wqh;
-	u16			adapters;	    /* # of adapters in list */
+	u32			adapters;	    /* # of adapters in list */
 	rwlock_t                config_lock;        /* serialises changes
 						       to adapter/port/unit
 						       lists */
@@ -829,6 +1125,24 @@ struct zfcp_statistics {
 };
 #endif
 
+struct zfcp_sg_list {
+	struct scatterlist *sg;
+	unsigned int count;
+};
+
+/* number of elements for various memory pools */
+#define ZFCP_POOL_FSF_REQ_ERP_NR	1
+#define ZFCP_POOL_FSF_REQ_SCSI_NR	1
+#define ZFCP_POOL_FSF_REQ_ABORT_NR	1
+#define ZFCP_POOL_STATUS_READ_NR	ZFCP_STATUS_READS_RECOM
+#define ZFCP_POOL_DATA_GID_PN_NR	1
+
+/* struct used by memory pools for fsf_requests */
+struct zfcp_fsf_req_pool_element {
+	struct zfcp_fsf_req fsf_req;
+	struct fsf_qtcb qtcb;
+};
+
 /********************** ZFCP SPECIFIC DEFINES ********************************/
 
 #define ZFCP_FSFREQ_CLEANUP_TIMEOUT	HZ/10
@@ -836,6 +1150,7 @@ struct zfcp_statistics {
 #define ZFCP_KNOWN              0x00000001
 #define ZFCP_REQ_AUTO_CLEANUP	0x00000002
 #define ZFCP_WAIT_FOR_SBAL	0x00000004
+#define ZFCP_REQ_NO_QTCB	0x00000008
 
 #define ZFCP_SET                0x00000100
 #define ZFCP_CLEAR              0x00000200
--- diff/drivers/s390/scsi/zfcp_erp.c	2004-02-09 10:36:11.000000000 +0000
+++ source/drivers/s390/scsi/zfcp_erp.c	2004-02-23 13:56:45.000000000 +0000
@@ -4,11 +4,12 @@
  * 
  * FCP adapter driver for IBM eServer zSeries 
  * 
- * Copyright 2002 IBM Corporation 
+ * (C) Copyright IBM Corp. 2002, 2004
+ *
  * Author(s): Martin Peschke <mpeschke@de.ibm.com> 
  *            Raimund Schroeder <raimund.schroeder@de.ibm.com> 
- *            Aron Zeh <arzeh@de.ibm.com> 
- *            Wolfgang Taphorn <taphorn@de.ibm.com> 
+ *            Aron Zeh
+ *            Wolfgang Taphorn
  *            Stefan Bader <stefan.bader@de.ibm.com> 
  *            Heiko Carstens <heiko.carstens@de.ibm.com> 
  * 
@@ -28,12 +29,15 @@
  */
 
 #define ZFCP_LOG_AREA			ZFCP_LOG_AREA_ERP
-#define ZFCP_LOG_AREA_PREFIX		ZFCP_LOG_AREA_PREFIX_ERP
+
 /* this drivers version (do not edit !!! generated and updated by cvs) */
-#define ZFCP_ERP_REVISION "$Revision: 1.39 $"
+#define ZFCP_ERP_REVISION "$Revision: 1.44 $"
 
 #include "zfcp_ext.h"
 
+static int zfcp_els(struct zfcp_port *, u8);
+static int zfcp_els_handler(unsigned long);
+
 static int zfcp_erp_adapter_reopen_internal(struct zfcp_adapter *, int);
 static int zfcp_erp_port_forced_reopen_internal(struct zfcp_port *, int);
 static int zfcp_erp_port_reopen_internal(struct zfcp_port *, int);
@@ -326,6 +330,375 @@ zfcp_erp_unit_shutdown(struct zfcp_unit 
 	return retval;
 }
 
+
+/*
+ * function:    zfcp_els
+ *
+ * purpose:     Originator of the ELS commands
+ *
+ * returns:     0       - Operation completed successfuly
+ *              -EINVAL - Unknown IOCTL command or invalid sense data record
+ *              -ENOMEM - Insufficient memory
+ *              -EPERM  - Cannot create or queue FSF request
+ */
+int
+zfcp_els(struct zfcp_port *port, u8 ls_code)
+{
+	struct zfcp_send_els *send_els;
+	struct zfcp_ls_rls *rls;
+	struct zfcp_ls_pdisc *pdisc;
+	struct zfcp_ls_adisc *adisc;
+	struct page *page = NULL;
+	void *req;
+	int retval = 0;
+
+	send_els = kmalloc(sizeof(struct zfcp_send_els), GFP_ATOMIC);
+	if (send_els == NULL)
+		goto nomem;
+
+	send_els->req = kmalloc(sizeof(struct scatterlist), GFP_ATOMIC);
+	if (send_els->req == NULL)
+		goto nomem;
+	send_els->req_count = 1;
+
+	send_els->resp = kmalloc(sizeof(struct scatterlist), GFP_ATOMIC);
+	if (send_els->resp == NULL)
+		goto nomem;
+	send_els->resp_count = 1;
+
+	page = alloc_pages(GFP_ATOMIC, 0);
+	if (page == NULL)
+		goto nomem;
+	send_els->req->page = page;
+	send_els->resp->page = page;
+	send_els->req->offset = 0;
+	send_els->resp->offset = PAGE_SIZE >> 1;
+
+	send_els->port = port;
+	send_els->ls_code = ls_code;
+	send_els->handler = zfcp_els_handler;
+	send_els->handler_data = (unsigned long)send_els;
+	send_els->completion = NULL;
+
+	req = zfcp_sg_to_address(send_els->req);
+
+	*(u32*)req = 0;
+	*(u8*)req = ls_code;
+
+	switch (ls_code) {
+
+	case ZFCP_LS_RTV:
+		send_els->req->length = sizeof(struct zfcp_ls_rtv);
+		send_els->resp->length = sizeof(struct zfcp_ls_rtv_acc);
+		ZFCP_LOG_NORMAL(
+			"RTV request from sid 0x%06x to did 0x%06x\n",
+			port->adapter->s_id, port->d_id);
+		break;
+
+	case ZFCP_LS_RLS:
+		send_els->req->length = sizeof(struct zfcp_ls_rls);
+		send_els->resp->length = sizeof(struct zfcp_ls_rls_acc);
+		rls = (struct zfcp_ls_rls*)req;
+		rls->port_id = port->adapter->s_id;
+		ZFCP_LOG_NORMAL(
+			"RLS request from sid 0x%06x to did 0x%06x "
+			"with payload(port_id=0x%06x)\n",
+			port->adapter->s_id, port->d_id, rls->port_id);
+		break;
+
+	case ZFCP_LS_PDISC:
+		send_els->req->length = sizeof(struct zfcp_ls_pdisc);
+		send_els->resp->length = sizeof(struct zfcp_ls_pdisc_acc);
+		pdisc = (struct zfcp_ls_pdisc*)req;
+		pdisc->wwpn = port->adapter->wwpn;
+		pdisc->wwnn = port->adapter->wwnn;
+		ZFCP_LOG_NORMAL(
+			"PDISC request from sid 0x%06x to did 0x%06x "
+			"with payload(wwpn=0x%016Lx wwnn=0x%016Lx)\n",
+			port->adapter->s_id, port->d_id,
+			pdisc->wwpn, pdisc->wwnn);
+		break;
+
+	case ZFCP_LS_ADISC:
+		send_els->req->length = sizeof(struct zfcp_ls_adisc);
+		send_els->resp->length = sizeof(struct zfcp_ls_adisc_acc);
+		adisc = (struct zfcp_ls_adisc*)req;
+		adisc->hard_nport_id = port->adapter->s_id;
+		adisc->wwpn = port->adapter->wwpn;
+		adisc->wwnn = port->adapter->wwnn;
+		adisc->nport_id = port->adapter->s_id;
+		ZFCP_LOG_NORMAL(
+			"ADISC request from sid 0x%06x to did 0x%06x "
+			"with payload(wwpn=0x%016Lx wwnn=0x%016Lx "
+			"hard_nport_id=0x%06x nport_id=0x%06x)\n",
+			port->adapter->s_id, port->d_id,
+			adisc->wwpn, adisc->wwnn,
+			adisc->hard_nport_id, adisc->nport_id);
+		break;
+
+	default:
+		ZFCP_LOG_NORMAL(
+			"ELS command code 0x%02x is not supported\n", ls_code);
+		retval = -EINVAL;
+		goto invalid_ls_code;
+	}
+
+	retval = zfcp_fsf_send_els(send_els);
+	if (retval != 0) {
+		ZFCP_LOG_NORMAL(
+			"ELS request could not be processed "
+			"(sid=0x%06x did=0x%06x)\n",
+			port->adapter->s_id, port->d_id);
+		retval = -EPERM;
+	}
+
+	goto out;
+
+nomem:
+	ZFCP_LOG_INFO("Out of memory!\n");
+	retval = -ENOMEM;
+
+invalid_ls_code:
+	if (page != NULL)
+		__free_pages(page, 0);
+	if (send_els != NULL) {
+		if (send_els->req != NULL)
+			kfree(send_els->req);
+		if (send_els->resp != NULL)
+			kfree(send_els->resp);
+		kfree(send_els);
+	}
+
+out:
+	return retval;
+}
+
+
+/*
+ * function:    zfcp_els_handler
+ *
+ * purpose:     Handler for all kind of ELSs
+ *
+ * returns:     0       - Operation completed successfuly
+ *              -ENXIO  - ELS has been rejected
+ *              -EPERM  - Port forced reopen failed
+ */
+int
+zfcp_els_handler(unsigned long data)
+{
+	struct zfcp_send_els *send_els = (struct zfcp_send_els*)data;
+	struct zfcp_port *port = send_els->port;
+	struct zfcp_ls_rjt *rjt;
+	struct zfcp_ls_rtv_acc *rtv;
+	struct zfcp_ls_rls_acc *rls;
+	struct zfcp_ls_pdisc_acc *pdisc;
+	struct zfcp_ls_adisc_acc *adisc;
+	void *req, *resp;
+	u8 req_code, resp_code;
+	int retval = 0;
+
+	if (send_els->status != 0)
+		goto skip_fsfstatus;
+
+	req = (void*)((page_to_pfn(send_els->req->page) << PAGE_SHIFT) + send_els->req->offset);
+	resp = (void*)((page_to_pfn(send_els->resp->page) << PAGE_SHIFT) + send_els->resp->offset);
+	req_code = *(u8*)req;
+	resp_code = *(u8*)resp;
+
+	switch (resp_code) {
+
+	case ZFCP_LS_RJT:
+		rjt = (struct zfcp_ls_rjt*)resp;
+
+		switch (rjt->reason_code) {
+
+		case ZFCP_LS_RJT_INVALID_COMMAND_CODE:
+			ZFCP_LOG_NORMAL(
+				"Invalid command code "
+				"(wwpn=0x%016Lx command=0x%02x)\n",
+				(unsigned long long)port->wwpn,
+				req_code);
+			break;
+
+		case ZFCP_LS_RJT_LOGICAL_ERROR:
+			ZFCP_LOG_NORMAL(
+				"Logical error "
+				"(wwpn=0x%016Lx reason_explanation=0x%02x)\n",
+				(unsigned long long)port->wwpn,
+				rjt->reason_expl);
+			break;
+
+		case ZFCP_LS_RJT_LOGICAL_BUSY:
+			ZFCP_LOG_NORMAL(
+				"Logical busy "
+				"(wwpn=0x%016Lx reason_explanation=0x%02x)\n",
+				(unsigned long long)port->wwpn,
+				rjt->reason_expl);
+			break;
+
+		case ZFCP_LS_RJT_PROTOCOL_ERROR:
+			ZFCP_LOG_NORMAL(
+				"Protocol error "
+				"(wwpn=0x%016Lx reason_explanation=0x%02x)\n",
+				(unsigned long long)port->wwpn,
+				rjt->reason_expl);
+			break;
+
+		case ZFCP_LS_RJT_UNABLE_TO_PERFORM:
+			ZFCP_LOG_NORMAL(
+				"Unable to perform command requested "
+				"(wwpn=0x%016Lx reason_explanation=0x%02x)\n",
+				(unsigned long long)port->wwpn,
+				rjt->reason_expl);
+			break;
+
+		case ZFCP_LS_RJT_COMMAND_NOT_SUPPORTED:
+			ZFCP_LOG_NORMAL(
+				"Command not supported "
+				"(wwpn=0x%016Lx command=0x%02x)\n",
+				(unsigned long long)port->wwpn,
+				req_code);
+			break;
+
+		case ZFCP_LS_RJT_VENDOR_UNIQUE_ERROR:
+			ZFCP_LOG_NORMAL(
+				"Vendor unique error "
+				"(wwpn=0x%016Lx vendor_unique=0x%02x)\n",
+				(unsigned long long)port->wwpn,
+				rjt->vendor_unique);
+			break;
+
+		default:
+			ZFCP_LOG_NORMAL(
+				"ELS has been rejected by remote port "
+				"with WWPN 0x%Lx on the adapter %s "
+				"with the reason code 0x%02x\n",
+				port->wwpn, zfcp_get_busid_by_port(port),
+				rjt->reason_code);
+		}
+		retval = -ENXIO;
+		break;
+
+	case ZFCP_LS_ACC:
+		switch (req_code) {
+
+		case ZFCP_LS_RTV:
+			rtv = (struct zfcp_ls_rtv_acc*)resp;
+			ZFCP_LOG_NORMAL(
+				"RTV response from did 0x%06x to sid 0x%06x "
+				"with payload(R_A_TOV=%ds E_D_TOV=%d%cs)\n",
+				port->d_id, port->adapter->s_id,
+				rtv->r_a_tov, rtv->e_d_tov,
+				rtv->qualifier & ZFCP_LS_RTV_E_D_TOV_FLAG ?
+					'n' : 'm');
+			break;
+
+		case ZFCP_LS_RLS:
+			rls = (struct zfcp_ls_rls_acc*)resp;
+			ZFCP_LOG_NORMAL(
+				"RLS response from did 0x%06x to sid 0x%06x "
+				"with payload(link_failure_count=%u "
+				"loss_of_sync_count=%u "
+				"loss_of_signal_count=%u "
+				"primitive_sequence_protocol_error=%u "
+				"invalid_transmition_word=%u "
+				"invalid_crc_count=%u)\n",
+				port->d_id, port->adapter->s_id,
+				rls->link_failure_count,
+				rls->loss_of_sync_count,
+				rls->loss_of_signal_count,
+				rls->prim_seq_prot_error,
+				rls->invalid_transmition_word,
+				rls->invalid_crc_count);
+			break;
+
+		case ZFCP_LS_PDISC:
+			pdisc = (struct zfcp_ls_pdisc_acc*)resp;
+			ZFCP_LOG_NORMAL(
+				"PDISC response from did 0x%06x to sid 0x%06x "
+				"with payload(wwpn=0x%016Lx wwnn=0x%016Lx "
+				"vendor='%-16s')\n",
+				port->d_id, port->adapter->s_id,
+				(unsigned long long)pdisc->wwpn,
+				(unsigned long long)pdisc->wwnn,
+				pdisc->vendor_version);
+			break;
+
+		case ZFCP_LS_ADISC:
+			adisc = (struct zfcp_ls_adisc_acc*)resp;
+			ZFCP_LOG_NORMAL(
+				"ADISC response from did 0x%06x to sid 0x%06x "
+				"with payload(wwpn=0x%016Lx wwnn=0x%016Lx "
+				"hard_nport_id=0x%06x nport_id=0x%06x)\n",
+				port->d_id, port->adapter->s_id,
+				(unsigned long long)adisc->wwpn,
+				(unsigned long long)adisc->wwnn,
+				adisc->hard_nport_id, adisc->nport_id);
+			/* FIXME: missing wwnn value in port struct */
+			if (port->wwnn == 0)
+				port->wwnn = adisc->wwnn;
+			break;
+		}
+		break;
+
+	default:
+		ZFCP_LOG_NORMAL(
+			"Unknown payload code 0x%02x received on a request "
+			"0x%02x from sid 0x%06x to did 0x%06x, "
+			"port needs to be reopened\n",
+			req_code, resp_code, port->adapter->s_id, port->d_id);
+		retval = zfcp_erp_port_forced_reopen(port, 0);
+		if (retval != 0) {
+			ZFCP_LOG_NORMAL(
+				"Cannot reopen a remote port "
+				"with WWPN 0x%Lx on the adapter %s\n",
+				port->wwpn, zfcp_get_busid_by_port(port));
+			retval = -EPERM;
+		}
+	}
+
+skip_fsfstatus:
+	__free_pages(send_els->req->page, 0);
+	kfree(send_els->req);
+	kfree(send_els->resp);
+
+	return retval;
+}
+
+
+/*
+ * function:    zfcp_test_link
+ *
+ * purpose:     Test a status of a link to a remote port using the ELS command ADISC
+ *
+ * returns:     0       - Link is OK
+ *              -EPERM  - Port forced reopen failed
+ */
+int
+zfcp_test_link(struct zfcp_port *port)
+{
+	int retval;
+
+	retval = zfcp_els(port, ZFCP_LS_ADISC);
+	if (retval != 0) {
+		ZFCP_LOG_NORMAL(
+			"Port with WWPN 0x%Lx on the adapter %s "
+			"needs to be reopened\n",
+			port->wwpn, zfcp_get_busid_by_port(port));
+		retval = zfcp_erp_port_forced_reopen(port, 0);
+		if (retval != 0) {
+			ZFCP_LOG_NORMAL(
+				"Cannot reopen a remote port "
+				"with WWPN 0x%Lx on the adapter %s\n",
+				port->wwpn, zfcp_get_busid_by_port(port));
+			retval = -EPERM;
+		}
+	}
+
+	return retval;
+}
+
+
 /*
  * function:	
  *
@@ -741,37 +1114,27 @@ zfcp_erp_strategy_check_fsfreq(struct zf
 						 "a_ca_disreq");
 				fsf_req->status |= ZFCP_STATUS_FSFREQ_DISMISSED;
 			}
+			if (erp_action->status & ZFCP_STATUS_ERP_TIMEDOUT) {
+				ZFCP_LOG_NORMAL
+					("error: Error Recovery Procedure "
+					 "step timed out. The action flag "
+					 "is 0x%x. The FSF request "
+					 "is at 0x%lx\n",
+					 erp_action->action,
+					 (unsigned long)
+					 erp_action->fsf_req);
+			}
 			/*
 			 * If fsf_req is neither dismissed nor completed
-			 * then keep it running asynchronously and don't mess with
-			 * the association of erp_action and fsf_req.
+			 * then keep it running asynchronously and don't mess
+			 * with the association of erp_action and fsf_req.
 			 */
 			if (fsf_req->status & (ZFCP_STATUS_FSFREQ_COMPLETED |
 					       ZFCP_STATUS_FSFREQ_DISMISSED)) {
-				/* forget about association between fsf_req and erp_action */
+				/* forget about association between fsf_req
+				   and erp_action */
 				fsf_req->erp_action = NULL;
 				erp_action->fsf_req = NULL;
-				/* some special things for time out conditions */
-				if (erp_action-> status & ZFCP_STATUS_ERP_TIMEDOUT) {
-					ZFCP_LOG_NORMAL
-					    ("error: Error Recovery Procedure step timed out. "
-					     "The action flag is 0x%x. The FSF request "
-					     "is at 0x%lx\n", erp_action->action,
-					     (unsigned long) erp_action->fsf_req);
-					/* fight for low memory buffer, if required */
-					if (fsf_req->
-					    status & ZFCP_STATUS_FSFREQ_POOL) {
-						debug_text_event(adapter->erp_dbf, 3,
-								 "a_ca_lowmem");
-						ZFCP_LOG_NORMAL
-						    ("error: The error recovery action using the "
-						     "low memory pool timed out. Restarting IO on "
-						     "the adapter %s to free it.\n",
-						     zfcp_get_busid_by_adapter
-						     (adapter));
-						zfcp_erp_adapter_reopen_internal(adapter, 0);
-					}
-				}
 			}
 		} else {
 			debug_text_event(adapter->erp_dbf, 3, "a_ca_gonereq");
@@ -1122,12 +1485,36 @@ zfcp_erp_strategy(struct zfcp_erp_action
 		goto unlock;
 	case ZFCP_ERP_NOMEM:
 		/* no memory to continue immediately, let it sleep */
+		if (!(erp_action->status & ZFCP_STATUS_ERP_LOWMEM)) {
+			++adapter->erp_low_mem_count;
+			erp_action->status |= ZFCP_STATUS_ERP_LOWMEM;
+		}
+		/* This condition is true if there is no memory available
+		   for any erp_action on this adapter. This implies that there
+		   are no elements in the memory pool(s) left for erp_actions.
+		   This might happen if an erp_action that used a memory pool
+		   element was timed out.
+		 */
+		if (adapter->erp_total_count == adapter->erp_low_mem_count) {
+			debug_text_event(adapter->erp_dbf, 3, "a_st_lowmem");
+			ZFCP_LOG_NORMAL
+				("error: Out of memory. No mempool elements "
+				 "available. Restarting IO on the adapter %s "
+				 "to free mempool.\n",
+				 zfcp_get_busid_by_adapter(adapter));
+			zfcp_erp_adapter_reopen_internal(adapter, 0);
+		} else {
 		debug_text_event(adapter->erp_dbf, 2, "a_st_memw");
 		retval = zfcp_erp_strategy_memwait(erp_action);
-		/* fall through, waiting for memory means action continues */
+		}
+		goto unlock;
 	case ZFCP_ERP_CONTINUES:
 		/* leave since this action runs asynchronously */
 		debug_text_event(adapter->erp_dbf, 6, "a_st_cont");
+		if (erp_action->status & ZFCP_STATUS_ERP_LOWMEM) {
+			--adapter->erp_low_mem_count;
+			erp_action->status &= ~ZFCP_STATUS_ERP_LOWMEM;
+		}
 		goto unlock;
 	}
 	/* ok, finished action (whatever its result is) */
@@ -1531,16 +1918,24 @@ zfcp_erp_strategy_check_unit(struct zfcp
 	debug_event(unit->port->adapter->erp_dbf, 5, &unit->fcp_lun,
 		    sizeof (fcp_lun_t));
 
-	if (result == ZFCP_ERP_SUCCEEDED) {
+	switch (result) {
+	case ZFCP_ERP_SUCCEEDED :
 		atomic_set(&unit->erp_counter, 0);
 		zfcp_erp_unit_unblock(unit);
-	} else {
-		/* ZFCP_ERP_FAILED or ZFCP_ERP_EXIT */
+		break;
+	case ZFCP_ERP_FAILED :
 		atomic_inc(&unit->erp_counter);
-		if (atomic_read(&unit->erp_counter) > ZFCP_MAX_ERPS) {
+		if (atomic_read(&unit->erp_counter) > ZFCP_MAX_ERPS)
 			zfcp_erp_unit_failed(unit);
-			result = ZFCP_ERP_EXIT;
-		}
+		break;
+	case ZFCP_ERP_EXIT :
+		/* nothing */
+		break;
+	}
+
+	if (atomic_test_mask(ZFCP_STATUS_COMMON_ERP_FAILED, &unit->status)) {
+		zfcp_erp_unit_block(unit, 0); /* for ZFCP_ERP_SUCCEEDED */
+		result = ZFCP_ERP_EXIT;
 	}
 
 	return result;
@@ -1559,16 +1954,24 @@ zfcp_erp_strategy_check_port(struct zfcp
 	debug_text_event(port->adapter->erp_dbf, 5, "p_stct");
 	debug_event(port->adapter->erp_dbf, 5, &port->wwpn, sizeof (wwn_t));
 
-	if (result == ZFCP_ERP_SUCCEEDED) {
+	switch (result) {
+	case ZFCP_ERP_SUCCEEDED :
 		atomic_set(&port->erp_counter, 0);
 		zfcp_erp_port_unblock(port);
-	} else {
-		/* ZFCP_ERP_FAILED or ZFCP_ERP_EXIT */
+		break;
+	case ZFCP_ERP_FAILED :
 		atomic_inc(&port->erp_counter);
-		if (atomic_read(&port->erp_counter) > ZFCP_MAX_ERPS) {
+		if (atomic_read(&port->erp_counter) > ZFCP_MAX_ERPS)
+		break;
+	case ZFCP_ERP_EXIT :
+		/* nothing */
+		break;
+	}
+
+	if (atomic_test_mask(ZFCP_STATUS_COMMON_ERP_FAILED, &port->status)) {
+		zfcp_erp_port_block(port, 0); /* for ZFCP_ERP_SUCCEEDED */
+		result = ZFCP_ERP_EXIT;
 			zfcp_erp_port_failed(port);
-			result = ZFCP_ERP_EXIT;
-		}
 	}
 
 	return result;
@@ -1586,16 +1989,24 @@ zfcp_erp_strategy_check_adapter(struct z
 {
 	debug_text_event(adapter->erp_dbf, 5, "a_stct");
 
-	if (result == ZFCP_ERP_SUCCEEDED) {
+	switch (result) {
+	case ZFCP_ERP_SUCCEEDED :
 		atomic_set(&adapter->erp_counter, 0);
 		zfcp_erp_adapter_unblock(adapter);
-	} else {
-		/* ZFCP_ERP_FAILED or ZFCP_ERP_EXIT */
+		break;
+	case ZFCP_ERP_FAILED :
 		atomic_inc(&adapter->erp_counter);
-		if (atomic_read(&adapter->erp_counter) > ZFCP_MAX_ERPS) {
+		if (atomic_read(&adapter->erp_counter) > ZFCP_MAX_ERPS)
 			zfcp_erp_adapter_failed(adapter);
-			result = ZFCP_ERP_EXIT;
-		}
+		break;
+	case ZFCP_ERP_EXIT :
+		/* nothing */
+		break;
+	}
+
+	if (atomic_test_mask(ZFCP_STATUS_COMMON_ERP_FAILED, &adapter->status)) {
+		zfcp_erp_adapter_block(adapter, 0); /* for ZFCP_ERP_SUCCEEDED */
+		result = ZFCP_ERP_EXIT;
 	}
 
 	return result;
@@ -1999,10 +2410,10 @@ zfcp_erp_adapter_strategy_generic(struct
 int
 zfcp_erp_adapter_strategy_open_qdio(struct zfcp_erp_action *erp_action)
 {
-	int retval = 0;
-	struct zfcp_adapter *adapter = erp_action->adapter;
+	int retval;
 	int i;
-	volatile struct qdio_buffer_element *buffere;
+	volatile struct qdio_buffer_element *sbale;
+	struct zfcp_adapter *adapter = erp_action->adapter;
 	int retval_cleanup = 0;
 
 	if (atomic_test_mask(ZFCP_STATUS_ADAPTER_QDIOUP, &adapter->status)) {
@@ -2034,10 +2445,10 @@ zfcp_erp_adapter_strategy_open_qdio(stru
 	 * put buffers into response queue,
 	 */
 	for (i = 0; i < QDIO_MAX_BUFFERS_PER_Q; i++) {
-		buffere = &(adapter->response_queue.buffer[i]->element[0]);
-		buffere->length = 0;
-		buffere->flags = SBAL_FLAGS_LAST_ENTRY;
-		buffere->addr = 0;
+		sbale = &(adapter->response_queue.buffer[i]->element[0]);
+		sbale->length = 0;
+		sbale->flags = SBAL_FLAGS_LAST_ENTRY;
+		sbale->addr = 0;
 	}
 
 	ZFCP_LOG_TRACE("Calling do QDIO busid=%s, flags=0x%x, queue_no=%i, "
@@ -2591,7 +3002,7 @@ zfcp_erp_port_strategy_open_common(struc
 		if (atomic_test_mask((ZFCP_STATUS_COMMON_OPEN |
 				      ZFCP_STATUS_PORT_DID_DID),
 				     &port->status)) {
-			ZFCP_LOG_DEBUG("port wwpn=0x%Lx is open ", port->wwpn);
+			ZFCP_LOG_DEBUG("port wwpn=0x%Lx is open\n", port->wwpn);
 			retval = ZFCP_ERP_SUCCEEDED;
 		} else {
 			ZFCP_LOG_DEBUG("failed to open port wwpn=0x%Lx\n",
@@ -2845,7 +3256,7 @@ zfcp_erp_port_strategy_open_common_looku
 	struct zfcp_port *port = erp_action->port;
 
 	zfcp_erp_timeout_init(erp_action);
-	retval = zfcp_nameserver_request(erp_action);
+	retval = zfcp_ns_gid_pn_request(erp_action);
 	if (retval == -ENOMEM) {
 		debug_text_event(adapter->erp_dbf, 5, "p_pstn_nomem");
 		debug_event(adapter->erp_dbf, 5, &port->wwpn, sizeof (wwn_t));
@@ -3087,6 +3498,10 @@ zfcp_erp_action_enqueue(int action,
 	 * efficient.
 	 */
 
+	if (!atomic_test_mask(ZFCP_STATUS_ADAPTER_ERP_THREAD_UP,
+			      &adapter->status))
+		goto out;
+
 	debug_event(adapter->erp_dbf, 4, &action, sizeof (int));
 	/* check whether we really need this */
 	switch (action) {
@@ -3222,6 +3637,8 @@ zfcp_erp_action_enqueue(int action,
 	erp_action->action = action;
 	erp_action->status = status;
 
+	++adapter->erp_total_count;
+
 	/* finally put it into 'ready' queue and kick erp thread */
 	list_add(&erp_action->list, &adapter->erp_ready_head);
 	up(&adapter->erp_ready_sem);
@@ -3243,6 +3660,12 @@ zfcp_erp_action_dequeue(struct zfcp_erp_
 	int retval = 0;
 	struct zfcp_adapter *adapter = erp_action->adapter;
 
+	--adapter->erp_total_count;
+	if (erp_action->status & ZFCP_STATUS_ERP_LOWMEM) {
+		--adapter->erp_low_mem_count;
+		erp_action->status &= ~ZFCP_STATUS_ERP_LOWMEM;
+	}
+
 	debug_text_event(adapter->erp_dbf, 4, "a_actdeq");
 	debug_event(adapter->erp_dbf, 4, &erp_action->action, sizeof (int));
 	list_del(&erp_action->list);
@@ -3404,4 +3827,3 @@ zfcp_erp_action_to_ready(struct zfcp_erp
 }
 
 #undef ZFCP_LOG_AREA
-#undef ZFCP_LOG_AREA_PREFIX
--- diff/drivers/s390/scsi/zfcp_ext.h	2004-02-09 10:36:11.000000000 +0000
+++ source/drivers/s390/scsi/zfcp_ext.h	2004-02-23 13:56:45.000000000 +0000
@@ -4,11 +4,12 @@
  * 
  * FCP adapter driver for IBM eServer zSeries 
  * 
- * Copyright 2002 IBM Corporation 
+ * (C) Copyright IBM Corp. 2002, 2004
+ *
  * Author(s): Martin Peschke <mpeschke@de.ibm.com> 
  *            Raimund Schroeder <raimund.schroeder@de.ibm.com> 
- *            Aron Zeh <arzeh@de.ibm.com> 
- *            Wolfgang Taphorn <taphorn@de.ibm.com> 
+ *            Aron Zeh
+ *            Wolfgang Taphorn
  *            Stefan Bader <stefan.bader@de.ibm.com> 
  *            Heiko Carstens <heiko.carstens@de.ibm.com> 
  * 
@@ -30,7 +31,7 @@
 #ifndef ZFCP_EXT_H
 #define ZFCP_EXT_H
 /* this drivers version (do not edit !!! generated and updated by cvs) */
-#define ZFCP_EXT_REVISION "$Revision: 1.38 $"
+#define ZFCP_EXT_REVISION "$Revision: 1.45 $"
 
 #include "zfcp_def.h"
 
@@ -46,7 +47,6 @@ extern void zfcp_sysfs_port_remove_files
 extern int  zfcp_sysfs_unit_create_files(struct device *);
 extern void zfcp_sysfs_unit_remove_files(struct device *);
 extern void zfcp_sysfs_port_release(struct device *);
-extern int  zfcp_sysfs_port_shutdown(struct zfcp_port *);
 extern void zfcp_sysfs_unit_release(struct device *);
 
 /**************************** CONFIGURATION  *********************************/
@@ -65,7 +65,6 @@ extern void   zfcp_unit_dequeue(struct z
 extern int  zfcp_ccw_register(void);
 extern void zfcp_ccw_unregister(void);
 
-extern int  zfcp_initialize_with_0copy(struct zfcp_adapter *);
 extern void zfcp_qdio_zero_sbals(struct qdio_buffer **, int, int);
 extern int  zfcp_qdio_allocate(struct zfcp_adapter *);
 extern int  zfcp_qdio_allocate_queues(struct zfcp_adapter *);
@@ -74,6 +73,16 @@ extern int  zfcp_qdio_determine_pci(stru
 				    struct zfcp_fsf_req *);
 extern int  zfcp_qdio_reqid_check(struct zfcp_adapter *, void *);
 
+extern volatile struct qdio_buffer_element *zfcp_qdio_sbale_req
+	(struct zfcp_fsf_req *, int, int);
+extern volatile struct qdio_buffer_element *zfcp_qdio_sbale_curr
+	(struct zfcp_fsf_req *);
+extern int zfcp_qdio_sbals_from_sg
+	(struct zfcp_fsf_req *, unsigned long, struct scatterlist *, int, int);
+extern int zfcp_qdio_sbals_from_scsicmnd
+	(struct zfcp_fsf_req *, unsigned long, struct scsi_cmnd *);
+
+
 /******************************** FSF ****************************************/
 extern int  zfcp_fsf_open_port(struct zfcp_erp_action *);
 extern int  zfcp_fsf_close_port(struct zfcp_erp_action *);
@@ -83,17 +92,20 @@ extern int  zfcp_fsf_open_unit(struct zf
 extern int  zfcp_fsf_close_unit(struct zfcp_erp_action *);
 
 extern int  zfcp_fsf_exchange_config_data(struct zfcp_erp_action *);
+extern int  zfcp_fsf_control_file(struct zfcp_adapter *, struct zfcp_fsf_req **,
+				  u32, u32, struct zfcp_sg_list *);
 extern void zfcp_fsf_scsi_er_timeout_handler(unsigned long);
 extern int  zfcp_fsf_req_dismiss_all(struct zfcp_adapter *);
 extern int  zfcp_fsf_status_read(struct zfcp_adapter *, int);
-extern int  zfcp_fsf_req_create(struct zfcp_adapter *,u32, unsigned long *,
-				int, struct zfcp_fsf_req **);
-extern void zfcp_fsf_req_free(struct zfcp_fsf_req *);
-extern int  zfcp_fsf_send_generic(struct zfcp_fsf_req *, unsigned char,
-				  unsigned long *, struct timer_list *);
+extern int zfcp_fsf_req_create(struct zfcp_adapter *, u32, int, mempool_t *,
+			       unsigned long *, struct zfcp_fsf_req **);
+extern int zfcp_fsf_send_ct(struct zfcp_send_ct *, mempool_t *,
+			    struct zfcp_erp_action *);
+extern int zfcp_fsf_send_els(struct zfcp_send_els *);
 extern int  zfcp_fsf_req_wait_and_cleanup(struct zfcp_fsf_req *, int, u32 *);
 extern int  zfcp_fsf_send_fcp_command_task(struct zfcp_adapter *,
-					   struct zfcp_unit *, Scsi_Cmnd *,
+					   struct zfcp_unit *,
+					   struct scsi_cmnd *,
 					   int);
 extern int  zfcp_fsf_req_complete(struct zfcp_fsf_req *);
 extern void zfcp_fsf_incoming_els(struct zfcp_fsf_req *);
@@ -105,15 +117,11 @@ extern struct zfcp_fsf_req *zfcp_fsf_abo
 
 /******************************** FCP ****************************************/
 extern int  zfcp_nameserver_enqueue(struct zfcp_adapter *);
-extern int  zfcp_nameserver_request(struct zfcp_erp_action *);
-extern void zfcp_fsf_els_processing(struct zfcp_fsf_req *);
+extern int  zfcp_ns_gid_pn_request(struct zfcp_erp_action *);
 
 /******************************* SCSI ****************************************/
 extern int  zfcp_adapter_scsi_register(struct zfcp_adapter *);
 extern void zfcp_adapter_scsi_unregister(struct zfcp_adapter *);
-extern void zfcp_scsi_block_requests(struct Scsi_Host *);
-extern int  zfcp_create_sbals_from_sg(struct zfcp_fsf_req *,
-				     Scsi_Cmnd *, char, int, int);
 extern void zfcp_set_fcp_dl(struct fcp_cmnd_iu *, fcp_dl_t);
 extern char *zfcp_get_fcp_rsp_info_ptr(struct fcp_rsp_iu *);
 extern void set_host_byte(u32 *, char);
@@ -122,6 +130,11 @@ extern char *zfcp_get_fcp_sns_info_ptr(s
 extern void zfcp_fsf_start_scsi_er_timer(struct zfcp_adapter *);
 extern fcp_dl_t zfcp_get_fcp_dl(struct fcp_cmnd_iu *);
 
+extern int zfcp_scsi_command_async(struct zfcp_adapter *,struct zfcp_unit *unit,
+				   struct scsi_cmnd *scsi_cmnd);
+extern int zfcp_scsi_command_sync(struct zfcp_unit *unit,
+				  struct scsi_cmnd *scsi_cmnd);
+
 /******************************** ERP ****************************************/
 extern void zfcp_erp_modify_adapter_status(struct zfcp_adapter *, u32, int);
 extern int  zfcp_erp_adapter_reopen(struct zfcp_adapter *, int);
@@ -147,10 +160,12 @@ extern int  zfcp_erp_thread_kill(struct 
 extern int  zfcp_erp_wait(struct zfcp_adapter *);
 extern void zfcp_erp_fsf_req_handler(struct zfcp_fsf_req *);
 
+extern int  zfcp_test_link(struct zfcp_port *);
+
 /******************************** AUX ****************************************/
 extern void zfcp_cmd_dbf_event_fsf(const char *, struct zfcp_fsf_req *,
 				   void *, int);
-extern void zfcp_cmd_dbf_event_scsi(const char *, Scsi_Cmnd *);
+extern void zfcp_cmd_dbf_event_scsi(const char *, struct scsi_cmnd *);
 extern void zfcp_in_els_dbf_event(struct zfcp_adapter *, const char *,
 				  struct fsf_status_read_buffer *, int);
 #ifdef ZFCP_STAT_REQSIZES
--- diff/drivers/s390/scsi/zfcp_fsf.c	2004-02-09 10:36:11.000000000 +0000
+++ source/drivers/s390/scsi/zfcp_fsf.c	2004-02-23 13:56:45.000000000 +0000
@@ -4,11 +4,12 @@
  *
  * FCP adapter driver for IBM eServer zSeries
  *
- * Copyright 2002 IBM Corporation
+ * (C) Copyright IBM Corp. 2002, 2004
+ *
  * Author(s): Martin Peschke <mpeschke@de.ibm.com>
  *            Raimund Schroeder <raimund.schroeder@de.ibm.com>
- *            Aron Zeh <arzeh@de.ibm.com>
- *            Wolfgang Taphorn <taphorn@de.ibm.com>
+ *            Aron Zeh
+ *            Wolfgang Taphorn
  *            Stefan Bader <stefan.bader@de.ibm.com>
  *            Heiko Carstens <heiko.carstens@de.ibm.com>
  *
@@ -28,7 +29,7 @@
  */
 
 /* this drivers version (do not edit !!! generated and updated by cvs) */
-#define ZFCP_FSF_C_REVISION "$Revision: 1.16 $"
+#define ZFCP_FSF_C_REVISION "$Revision: 1.29 $"
 
 #include "zfcp_ext.h"
 
@@ -43,18 +44,22 @@ static int zfcp_fsf_send_fcp_command_tas
 static int zfcp_fsf_send_fcp_command_task_management_handler(
 	struct zfcp_fsf_req *);
 static int zfcp_fsf_abort_fcp_command_handler(struct zfcp_fsf_req *);
-static int zfcp_fsf_send_generic_handler(struct zfcp_fsf_req *);
 static int zfcp_fsf_status_read_handler(struct zfcp_fsf_req *);
+static int zfcp_fsf_send_ct_handler(struct zfcp_fsf_req *);
+static int zfcp_fsf_send_els_handler(struct zfcp_fsf_req *);
+static int zfcp_fsf_control_file_handler(struct zfcp_fsf_req *);
 static inline int zfcp_fsf_req_create_sbal_check(
 	unsigned long *, struct zfcp_qdio_queue *, int);
-static struct zfcp_fsf_req *zfcp_fsf_req_get(int, mempool_t *);
-static struct zfcp_fsf_req *zfcp_fsf_req_alloc(struct zfcp_adapter *, u32, int);
+static inline int zfcp_use_one_sbal(
+	struct scatterlist *, int, struct scatterlist *, int);
+static struct zfcp_fsf_req *zfcp_fsf_req_alloc(mempool_t *, int);
 static int zfcp_fsf_req_send(struct zfcp_fsf_req *, struct timer_list *);
 static int zfcp_fsf_protstatus_eval(struct zfcp_fsf_req *);
 static int zfcp_fsf_fsfstatus_eval(struct zfcp_fsf_req *);
 static int zfcp_fsf_fsfstatus_qual_eval(struct zfcp_fsf_req *);
 static int zfcp_fsf_req_dispatch(struct zfcp_fsf_req *);
 static void zfcp_fsf_req_dismiss(struct zfcp_fsf_req *);
+static void zfcp_fsf_req_free(struct zfcp_fsf_req *);
 
 /* association between FSF command and FSF QTCB type */
 static u32 fsf_qtcb_type[] = {
@@ -67,7 +72,10 @@ static u32 fsf_qtcb_type[] = {
 	[FSF_QTCB_CLOSE_PHYSICAL_PORT] =  FSF_SUPPORT_COMMAND,
 	[FSF_QTCB_SEND_ELS] =             FSF_SUPPORT_COMMAND,
 	[FSF_QTCB_SEND_GENERIC] =         FSF_SUPPORT_COMMAND,
-	[FSF_QTCB_EXCHANGE_CONFIG_DATA] = FSF_CONFIG_COMMAND
+	[FSF_QTCB_EXCHANGE_CONFIG_DATA] = FSF_CONFIG_COMMAND,
+	[FSF_QTCB_EXCHANGE_PORT_DATA] =   FSF_PORT_COMMAND,
+	[FSF_QTCB_DOWNLOAD_CONTROL_FILE] = FSF_SUPPORT_COMMAND,
+	[FSF_QTCB_UPLOAD_CONTROL_FILE] =  FSF_SUPPORT_COMMAND
 };
 
 /****************************************************************/
@@ -75,7 +83,6 @@ static u32 fsf_qtcb_type[] = {
 /****************************************************************/
 
 #define ZFCP_LOG_AREA			ZFCP_LOG_AREA_FSF
-#define ZFCP_LOG_AREA_PREFIX		ZFCP_LOG_AREA_PREFIX_FSF
 
 /*
  * function:	zfcp_fsf_req_alloc
@@ -91,93 +98,38 @@ static u32 fsf_qtcb_type[] = {
  *
  */
 static struct zfcp_fsf_req *
-zfcp_fsf_req_alloc(struct zfcp_adapter *adapter, u32 fsf_cmd, int kmalloc_flags)
+zfcp_fsf_req_alloc(mempool_t *pool, int req_flags)
 {
+	size_t size;
+	void *ptr;
 	struct zfcp_fsf_req *fsf_req = NULL;
 
-	switch (fsf_cmd) {
+	if (req_flags & ZFCP_REQ_NO_QTCB)
+		size = sizeof(struct zfcp_fsf_req);
+	else
+		size = sizeof(struct zfcp_fsf_req_pool_element);
 
-	case FSF_QTCB_FCP_CMND:
-	case FSF_QTCB_ABORT_FCP_CMND:
-		fsf_req = zfcp_fsf_req_get(kmalloc_flags,
-					   adapter->pool.fcp_command_fsf);
-		if (unlikely(fsf_req &&
-		             (fsf_req->status & ZFCP_STATUS_FSFREQ_POOL))) {
-			/*
-			 * watch low mem buffer
-			 * Note: If the command is reset or aborted, two
-			 * timeouts (this and the SCSI ER one) will be started
-			 * for the command. There is no problem however as
-			 * the first expired timer will call adapter_reopen
-			 * which will delete the other 
-			 */
-			adapter->pool.fcp_command_fsf_timer.expires =
-			    jiffies + ZFCP_ERP_SCSI_LOW_MEM_TIMEOUT;
-			add_timer(&adapter->pool.fcp_command_fsf_timer);
-		}
-#ifdef ZFCP_DEBUG_REQUESTS
-		debug_text_event(adapter->req_dbf, 5, "fsfa_fcp");
-		if (unlikely(fsf_req &&
-		             (fsf_req->status & ZFCP_STATUS_FSFREQ_POOL)))
-			debug_text_event(adapter->req_dbf, 5, "fsfa_pl");
-#endif /* ZFCP_DEBUG_REQUESTS */
-		break;
+	if (likely(pool != NULL))
+		ptr = mempool_alloc(pool, GFP_ATOMIC);
+	else
+		ptr = kmalloc(size, GFP_ATOMIC);
 
-	case FSF_QTCB_OPEN_PORT_WITH_DID:
-	case FSF_QTCB_OPEN_LUN:
-	case FSF_QTCB_CLOSE_LUN:
-	case FSF_QTCB_CLOSE_PORT:
-	case FSF_QTCB_CLOSE_PHYSICAL_PORT:
-	case FSF_QTCB_SEND_ELS:
-	case FSF_QTCB_EXCHANGE_CONFIG_DATA:
-	case FSF_QTCB_SEND_GENERIC:
-		fsf_req =
-		    zfcp_fsf_req_get(kmalloc_flags, adapter->pool.erp_fsf);
-#ifdef ZFCP_DEBUG_REQUESTS
-		debug_text_event(adapter->req_dbf, 5, "fsfa_erp");
-		if (fsf_req && (fsf_req->status & ZFCP_STATUS_FSFREQ_POOL))
-			debug_text_event(adapter->req_dbf, 5, "fsfa_pl");
-#endif				/* ZFCP_DEBUG_REQUESTS */
-		break;
+	if (unlikely(NULL == ptr))
+		goto out;
 
-	case FSF_QTCB_UNSOLICITED_STATUS:
-		fsf_req =
-		    mempool_alloc(adapter->pool.status_read_fsf, GFP_ATOMIC);
-		if (fsf_req) {
-			memset(fsf_req, 0, sizeof (struct zfcp_fsf_req));
-			fsf_req->status |= ZFCP_STATUS_FSFREQ_POOL;
-		} else
-			ZFCP_LOG_NORMAL("bug: could not find free fsf_req\n");
-#ifdef ZFCP_DEBUG_REQUESTS
-		debug_text_event(adapter->req_dbf, 5, "fsfa_sr");
-		debug_text_event(adapter->req_dbf, 5, "fsfa_pl");
-#endif				/* ZFCP_DEBUG_REQUESTS */
-		break;
+	memset(ptr, 0, size);
 
-	default:
-		ZFCP_LOG_NORMAL("bug: An attempt to send an unsupported "
-				"command has been detected. "
-				"(debug info 0x%x)\n", fsf_cmd);
-	}			//switch(fsf_cmd)
-
-	if (unlikely(!fsf_req)) {
-		ZFCP_LOG_DEBUG("error: Out of memory. Allocation of FSF "
-			       "request structure failed\n");
+	if (req_flags & ZFCP_REQ_NO_QTCB) {
+		fsf_req = (struct zfcp_fsf_req *) ptr;
 	} else {
-		ZFCP_LOG_TRACE("FSF request allocated at 0x%lx, "
-			       "adapter 0x%lx (%s)\n",
-			       (unsigned long) fsf_req,
-			       (unsigned long) adapter,
-			       zfcp_get_busid_by_adapter(adapter));
+		fsf_req = &((struct zfcp_fsf_req_pool_element *) ptr)->fsf_req;
+		fsf_req->qtcb =
+			&((struct zfcp_fsf_req_pool_element *) ptr)->qtcb;
 	}
 
-#ifdef ZFCP_DEBUG_REQUESTS
-	debug_event(adapter->req_dbf, 5, &fsf_req, sizeof (unsigned long));
-	if (likely(fsf_req->qtcb))
-		debug_event(adapter->req_dbf, 5, &fsf_req->qtcb,
-			    sizeof (unsigned long));
-#endif				/* ZFCP_DEBUG_REQUESTS */
+	fsf_req->pool = pool;
 
+ out:
 	return fsf_req;
 }
 
@@ -191,40 +143,13 @@ zfcp_fsf_req_alloc(struct zfcp_adapter *
  *
  * locks:       none
  */
-void
+static void
 zfcp_fsf_req_free(struct zfcp_fsf_req *fsf_req)
 {
-	struct zfcp_adapter *adapter = fsf_req->adapter;
-
-	switch (fsf_req->fsf_command) {
-
-	case FSF_QTCB_FCP_CMND:
-	case FSF_QTCB_ABORT_FCP_CMND:
-		if (unlikely(fsf_req->status & ZFCP_STATUS_FSFREQ_POOL)) {
-			del_timer(&adapter->pool.fcp_command_fsf_timer);
-			mempool_free(fsf_req, adapter->pool.fcp_command_fsf);
-		} else
-			kfree(fsf_req);
-		break;
-
-	case FSF_QTCB_OPEN_PORT_WITH_DID:
-	case FSF_QTCB_OPEN_LUN:
-	case FSF_QTCB_CLOSE_LUN:
-	case FSF_QTCB_CLOSE_PORT:
-	case FSF_QTCB_CLOSE_PHYSICAL_PORT:
-	case FSF_QTCB_SEND_ELS:
-	case FSF_QTCB_EXCHANGE_CONFIG_DATA:
-	case FSF_QTCB_SEND_GENERIC:
-		if (fsf_req->status & ZFCP_STATUS_FSFREQ_POOL)
-			mempool_free(fsf_req, adapter->pool.erp_fsf);
+	if (likely(fsf_req->pool != NULL))
+		mempool_free(fsf_req, fsf_req->pool);
 		else
 			kfree(fsf_req);
-		break;
-
-	case FSF_QTCB_UNSOLICITED_STATUS:
-		mempool_free(fsf_req, adapter->pool.status_read_fsf);
-		break;
-	}
 }
 
 /*
@@ -386,23 +311,24 @@ zfcp_fsf_protstatus_eval(struct zfcp_fsf
 	/* log additional information provided by FSF (if any) */
 	if (unlikely(fsf_req->qtcb->header.log_length)) {
 		/* do not trust them ;-) */
-		if (fsf_req->qtcb->header.log_start > ZFCP_QTCB_SIZE) {
+		if (fsf_req->qtcb->header.log_start > sizeof(struct fsf_qtcb)) {
 			ZFCP_LOG_NORMAL
 			    ("bug: ULP (FSF logging) log data starts "
 			     "beyond end of packet header. Ignored. "
 			     "(start=%i, size=%li)\n",
-			     fsf_req->qtcb->header.log_start, ZFCP_QTCB_SIZE);
+			     fsf_req->qtcb->header.log_start,
+			     sizeof(struct fsf_qtcb));
 			goto forget_log;
 		}
 		if ((fsf_req->qtcb->header.log_start +
 		     fsf_req->qtcb->header.log_length)
-		    > ZFCP_QTCB_SIZE) {
+		    > sizeof(struct fsf_qtcb)) {
 			ZFCP_LOG_NORMAL("bug: ULP (FSF logging) log data ends "
 					"beyond end of packet header. Ignored. "
 					"(start=%i, length=%i, size=%li)\n",
 					fsf_req->qtcb->header.log_start,
 					fsf_req->qtcb->header.log_length,
-					ZFCP_QTCB_SIZE);
+					sizeof(struct fsf_qtcb));
 			goto forget_log;
 		}
 		ZFCP_LOG_TRACE("ULP log data: \n");
@@ -667,7 +593,7 @@ zfcp_fsf_protstatus_eval(struct zfcp_fsf
 			      (char *) (((unsigned long) fsf_req) & 0xFFFFFF00),
 			      sizeof (struct zfcp_fsf_req));
 		ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_NORMAL, (char *) fsf_req->qtcb,
-			      ZFCP_QTCB_SIZE);
+			      sizeof(struct fsf_qtcb));
 		debug_text_event(adapter->erp_dbf, 0, "prot_inval:");
 		debug_exception(adapter->erp_dbf, 0,
 				&fsf_req->qtcb->prefix.prot_status,
@@ -852,7 +778,7 @@ zfcp_fsf_req_dispatch(struct zfcp_fsf_re
 			       (unsigned long) fsf_req,
 			       (unsigned long) (fsf_req->qtcb));
 		ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_TRACE,
-			      (char *) fsf_req->qtcb, ZFCP_QTCB_SIZE);
+			      (char *) fsf_req->qtcb, sizeof(struct fsf_qtcb));
 	}
 
 	switch (fsf_req->fsf_command) {
@@ -869,44 +795,52 @@ zfcp_fsf_req_dispatch(struct zfcp_fsf_re
 
 	case FSF_QTCB_SEND_GENERIC:
 		ZFCP_LOG_FLAGS(2, "FSF_QTCB_SEND_GENERIC\n");
-		zfcp_fsf_send_generic_handler(fsf_req);
-		zfcp_erp_fsf_req_handler(fsf_req);
+		zfcp_fsf_send_ct_handler(fsf_req);
 		break;
 
 	case FSF_QTCB_OPEN_PORT_WITH_DID:
 		ZFCP_LOG_FLAGS(2, "FSF_QTCB_OPEN_PORT_WITH_DID\n");
 		zfcp_fsf_open_port_handler(fsf_req);
-		zfcp_erp_fsf_req_handler(fsf_req);
 		break;
 
 	case FSF_QTCB_OPEN_LUN:
 		ZFCP_LOG_FLAGS(2, "FSF_QTCB_OPEN_LUN\n");
 		zfcp_fsf_open_unit_handler(fsf_req);
-		zfcp_erp_fsf_req_handler(fsf_req);
 		break;
 
 	case FSF_QTCB_CLOSE_LUN:
 		ZFCP_LOG_FLAGS(2, "FSF_QTCB_CLOSE_LUN\n");
 		zfcp_fsf_close_unit_handler(fsf_req);
-		zfcp_erp_fsf_req_handler(fsf_req);
 		break;
 
 	case FSF_QTCB_CLOSE_PORT:
 		ZFCP_LOG_FLAGS(2, "FSF_QTCB_CLOSE_PORT\n");
 		zfcp_fsf_close_port_handler(fsf_req);
-		zfcp_erp_fsf_req_handler(fsf_req);
 		break;
 
 	case FSF_QTCB_CLOSE_PHYSICAL_PORT:
 		ZFCP_LOG_FLAGS(2, "FSF_QTCB_CLOSE_PHYSICAL_PORT\n");
 		zfcp_fsf_close_physical_port_handler(fsf_req);
-		zfcp_erp_fsf_req_handler(fsf_req);
 		break;
 
 	case FSF_QTCB_EXCHANGE_CONFIG_DATA:
 		ZFCP_LOG_FLAGS(2, "FSF_QTCB_EXCHANGE_CONFIG_DATA\n");
 		zfcp_fsf_exchange_config_data_handler(fsf_req);
-		zfcp_erp_fsf_req_handler(fsf_req);
+		break;
+
+	case FSF_QTCB_SEND_ELS :
+		ZFCP_LOG_FLAGS(2, "FSF_QTCB_SEND_ELS\n");
+		zfcp_fsf_send_els_handler(fsf_req);
+		break;
+
+	case FSF_QTCB_DOWNLOAD_CONTROL_FILE:
+		ZFCP_LOG_FLAGS(2, "FSF_QTCB_DOWNLOAD_CONTROL_FILE\n");
+		zfcp_fsf_control_file_handler(fsf_req);
+		break;
+
+	case FSF_QTCB_UPLOAD_CONTROL_FILE:
+		ZFCP_LOG_FLAGS(2, "FSF_QTCB_UPLOAD_CONTROL_FILE\n");
+		zfcp_fsf_control_file_handler(fsf_req);
 		break;
 
 	default:
@@ -927,6 +861,7 @@ zfcp_fsf_req_dispatch(struct zfcp_fsf_re
 			     fsf_req->qtcb->header.fsf_command);
 	}
 
+        zfcp_erp_fsf_req_handler(fsf_req);
 	return retval;
 }
 
@@ -943,14 +878,14 @@ zfcp_fsf_status_read(struct zfcp_adapter
 	struct zfcp_fsf_req *fsf_req;
 	struct fsf_status_read_buffer *status_buffer;
 	unsigned long lock_flags;
-	volatile struct qdio_buffer_element *buffere;
-	struct zfcp_qdio_queue *req_queue = &adapter->request_queue;
+	volatile struct qdio_buffer_element *sbale;
 	int retval = 0;
 
 	/* setup new FSF request */
-	retval = zfcp_fsf_req_create(adapter,
-				     FSF_QTCB_UNSOLICITED_STATUS,
-				     &lock_flags, req_flags, &fsf_req);
+	retval = zfcp_fsf_req_create(adapter, FSF_QTCB_UNSOLICITED_STATUS,
+				     req_flags | ZFCP_REQ_NO_QTCB,
+				     adapter->pool.fsf_req_status_read,
+				     &lock_flags, &fsf_req);
 	if (retval < 0) {
 		ZFCP_LOG_INFO("error: Out of resources. Could not create an "
 			      "unsolicited status buffer for "
@@ -959,8 +894,13 @@ zfcp_fsf_status_read(struct zfcp_adapter
 		goto failed_req_create;
 	}
 
+	sbale = zfcp_qdio_sbale_req(fsf_req, fsf_req->sbal_curr, 0);
+        sbale[0].flags |= SBAL_FLAGS0_TYPE_STATUS;
+        sbale[2].flags |= SBAL_FLAGS_LAST_ENTRY;
+        fsf_req->sbale_curr = 2;
+
 	status_buffer =
-	    mempool_alloc(adapter->pool.status_read_buf, GFP_ATOMIC);
+		mempool_alloc(adapter->pool.data_status_read, GFP_ATOMIC);
 	if (!status_buffer) {
 		ZFCP_LOG_NORMAL("bug: could not get some buffer\n");
 		goto failed_buf;
@@ -969,9 +909,9 @@ zfcp_fsf_status_read(struct zfcp_adapter
 	fsf_req->data.status_read.buffer = status_buffer;
 
 	/* insert pointer to respective buffer */
-	buffere = req_queue->buffer[fsf_req->sbal_index]->element;
-	buffere[2].addr = (void *) status_buffer;
-	buffere[2].length = sizeof (struct fsf_status_read_buffer);
+	sbale = zfcp_qdio_sbale_curr(fsf_req);
+	sbale->addr = (void *) status_buffer;
+	sbale->length = sizeof(struct fsf_status_read_buffer);
 
 	/* start QDIO request for this FSF request */
 	retval = zfcp_fsf_req_send(fsf_req, NULL);
@@ -990,7 +930,7 @@ zfcp_fsf_status_read(struct zfcp_adapter
 	goto out;
 
  failed_req_send:
-	mempool_free(status_buffer, adapter->pool.status_read_buf);
+	mempool_free(status_buffer, adapter->pool.data_status_read);
 
  failed_buf:
 	zfcp_fsf_req_free(fsf_req);
@@ -1072,7 +1012,7 @@ zfcp_fsf_status_read_handler(struct zfcp
 	    fsf_req->data.status_read.buffer;
 
 	if (fsf_req->status & ZFCP_STATUS_FSFREQ_DISMISSED) {
-		mempool_free(status_buffer, adapter->pool.status_read_buf);
+		mempool_free(status_buffer, adapter->pool.data_status_read);
 		zfcp_fsf_req_cleanup(fsf_req);
 		goto out;
 	}
@@ -1104,6 +1044,7 @@ zfcp_fsf_status_read_handler(struct zfcp
 
 	case FSF_STATUS_READ_LINK_DOWN:
 		ZFCP_LOG_FLAGS(1, "FSF_STATUS_READ_LINK_DOWN\n");
+
 		/* Unneccessary, ignoring.... */
 		break;
 
@@ -1121,6 +1062,59 @@ zfcp_fsf_status_read_handler(struct zfcp
 		zfcp_erp_adapter_reopen(adapter,
 					ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED
 					| ZFCP_STATUS_COMMON_ERP_FAILED);
+
+		break;
+
+	case FSF_STATUS_READ_NOTIFICATION_LOST:
+		ZFCP_LOG_FLAGS(1, "FSF_STATUS_READ_NOTIFICATION_LOST\n");
+		debug_text_event(adapter->erp_dbf, 2, "unsol_not_lost:");
+		switch (status_buffer->status_subtype) {
+		case FSF_STATUS_READ_SUB_LOST_CFDC_UPDATED:
+			ZFCP_LOG_NORMAL(
+				"The unsolicited status information about "
+				"CFDC update on the adapter %s is lost "
+				"due to the lack of internal resources\n",
+				zfcp_get_busid_by_adapter(adapter));
+			break;
+		case FSF_STATUS_READ_SUB_LOST_CFDC_HARDENED:
+			ZFCP_LOG_NORMAL(
+				"The unsolicited status information about "
+				"CFDC harden on the adapter %s is lost "
+				"due to the lack of internal resources\n",
+				zfcp_get_busid_by_adapter(adapter));
+			break;
+		}
+		break;
+
+	case FSF_STATUS_READ_CFDC_UPDATED:
+		ZFCP_LOG_FLAGS(1, "FSF_STATUS_READ_CFDC_UPDATED\n");
+		debug_text_event(adapter->erp_dbf, 2, "unsol_cfdc_update:");
+		ZFCP_LOG_NORMAL(
+			"CFDC has been updated on the adapter %s\n",
+			zfcp_get_busid_by_adapter(adapter));
+		break;
+
+	case FSF_STATUS_READ_CFDC_HARDENED:
+		ZFCP_LOG_FLAGS(1, "FSF_STATUS_READ_CFDC_HARDENED\n");
+		debug_text_event(adapter->erp_dbf, 2, "unsol_cfdc_harden:");
+		switch (status_buffer->status_subtype) {
+		case FSF_STATUS_READ_SUB_CFDC_HARDENED_ON_SE:
+			ZFCP_LOG_NORMAL(
+				"CFDC of the adapter %s "
+				"has been saved on the SE\n",
+				zfcp_get_busid_by_adapter(adapter));
+			break;
+		case FSF_STATUS_READ_SUB_CFDC_HARDENED_ON_SE2:
+			ZFCP_LOG_NORMAL(
+				"CFDC of the adapter %s "
+				"has been copied to the secondary SE\n",
+				zfcp_get_busid_by_adapter(adapter));
+			break;
+		default:
+			ZFCP_LOG_NORMAL(
+				"CFDC of the adapter %s has been hardened\n",
+				zfcp_get_busid_by_adapter(adapter));
+		}
 		break;
 
 	default:
@@ -1138,7 +1132,7 @@ zfcp_fsf_status_read_handler(struct zfcp
 			      sizeof (struct fsf_status_read_buffer));
 		break;
 	}
-	mempool_free(status_buffer, adapter->pool.status_read_buf);
+	mempool_free(status_buffer, adapter->pool.data_status_read);
 	zfcp_fsf_req_cleanup(fsf_req);
 	/*
 	 * recycle buffer and start new request repeat until outbound
@@ -1192,13 +1186,15 @@ zfcp_fsf_abort_fcp_command(unsigned long
 			   struct zfcp_adapter *adapter,
 			   struct zfcp_unit *unit, int req_flags)
 {
-	struct zfcp_fsf_req *new_fsf_req = NULL;
-	int retval = 0;
+	volatile struct qdio_buffer_element *sbale;
 	unsigned long lock_flags;
+	struct zfcp_fsf_req *fsf_req = NULL;
+	int retval = 0;
 
 	/* setup new FSF request */
 	retval = zfcp_fsf_req_create(adapter, FSF_QTCB_ABORT_FCP_CMND,
-				     &lock_flags, req_flags, &new_fsf_req);
+				     req_flags, adapter->pool.fsf_req_abort,
+				     &lock_flags, &fsf_req);
 	if (retval < 0) {
 		ZFCP_LOG_INFO("error: Out of resources. Could not create an "
 			      "abort command request on the device with "
@@ -1211,19 +1207,23 @@ zfcp_fsf_abort_fcp_command(unsigned long
 		goto out;
 	}
 
-	new_fsf_req->data.abort_fcp_command.unit = unit;
+	sbale = zfcp_qdio_sbale_req(fsf_req, fsf_req->sbal_curr, 0);
+        sbale[0].flags |= SBAL_FLAGS0_TYPE_READ;
+        sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY;
+
+	fsf_req->data.abort_fcp_command.unit = unit;
 
 	/* set handles of unit and its parent port in QTCB */
-	new_fsf_req->qtcb->header.lun_handle = unit->handle;
-	new_fsf_req->qtcb->header.port_handle = unit->port->handle;
+	fsf_req->qtcb->header.lun_handle = unit->handle;
+	fsf_req->qtcb->header.port_handle = unit->port->handle;
 
 	/* set handle of request which should be aborted */
-	new_fsf_req->qtcb->bottom.support.req_handle = (u64) old_req_id;
+	fsf_req->qtcb->bottom.support.req_handle = (u64) old_req_id;
 
 	/* start QDIO request for this FSF request */
 
 	zfcp_fsf_start_scsi_er_timer(adapter);
-	retval = zfcp_fsf_req_send(new_fsf_req, NULL);
+	retval = zfcp_fsf_req_send(fsf_req, NULL);
 	if (retval) {
 		del_timer(&adapter->scsi_er_timer);
 		ZFCP_LOG_INFO("error: Could not send an abort command request "
@@ -1231,8 +1231,8 @@ zfcp_fsf_abort_fcp_command(unsigned long
 			      "port WWPN 0x%Lx and unit LUN 0x%Lx\n",
 			      zfcp_get_busid_by_adapter(adapter),
 			      unit->port->wwpn, unit->fcp_lun);
-		zfcp_fsf_req_free(new_fsf_req);
-		new_fsf_req = NULL;
+		zfcp_fsf_req_free(fsf_req);
+		fsf_req = NULL;
 		goto out;
 	}
 
@@ -1244,7 +1244,7 @@ zfcp_fsf_abort_fcp_command(unsigned long
 		       unit->fcp_lun, old_req_id);
  out:
 	write_unlock_irqrestore(&adapter->request_queue.queue_lock, lock_flags);
-	return new_fsf_req;
+	return fsf_req;
 }
 
 /*
@@ -1429,73 +1429,183 @@ zfcp_fsf_abort_fcp_command_handler(struc
 	return retval;
 }
 
-/*
- * function:    zfcp_fsf_send_generic
- *
- * purpose:	sends a FC request according to FC-GS-3
- *
- * returns:	address of initiated FSF request
- *		NULL - request could not be initiated 
+/**
+ * zfcp_use_one_sbal - checks whether req buffer and resp bother each fit into
+ *	one SBALE
+ * Two scatter-gather lists are passed, one for the reqeust and one for the
+ * response.
+ */
+static inline int
+zfcp_use_one_sbal(struct scatterlist *req, int req_count,
+                  struct scatterlist *resp, int resp_count)
+{
+        return ((req_count == 1) &&
+		(resp_count == 1) &&
+                (((unsigned long) zfcp_sg_to_address(&req[0]) &
+		  PAGE_MASK) ==
+		 ((unsigned long) (zfcp_sg_to_address(&req[0]) +
+				   req[0].length - 1) & PAGE_MASK)) &&
+                (((unsigned long) zfcp_sg_to_address(&resp[0]) &
+		  PAGE_MASK) ==
+                 ((unsigned long) (zfcp_sg_to_address(&resp[0]) +
+				   resp[0].length - 1) & PAGE_MASK)));
+}
+
+/**
+ * zfcp_fsf_send_ct - initiate a Generic Service request (FC-GS)
+ * @ct: pointer to struct zfcp_send_ct which conatins all needed data for
+ *	the request
+ * @pool: pointer to memory pool, if non-null this pool is used to allocate
+ *	a struct zfcp_fsf_req
+ * @erp_action: pointer to erp_action, if non-null the Generic Service request
+ *	is sent within error recovery
  */
 int
-zfcp_fsf_send_generic(struct zfcp_fsf_req *fsf_req, unsigned char timeout,
-		      unsigned long *lock_flags, struct timer_list *timer)
+zfcp_fsf_send_ct(struct zfcp_send_ct *ct, mempool_t *pool,
+		 struct zfcp_erp_action *erp_action)
 {
-	int retval = 0;
-	struct qdio_buffer *buffer;
-	volatile struct qdio_buffer_element *buffer_element = NULL;
-	struct zfcp_port *port = fsf_req->data.send_generic.port;
-	struct zfcp_adapter *adapter = port->adapter;
-
-	/* put buffers to the 2 SBALEs after the QTCB */
-	buffer = (adapter->request_queue.buffer[fsf_req->sbal_index]);
-	buffer_element = &(buffer->element[2]);
-	buffer_element->addr = fsf_req->data.send_generic.outbuf;
-	buffer_element->length = fsf_req->data.send_generic.outbuf_length;
-	buffer_element++;
-	buffer_element->addr = fsf_req->data.send_generic.inbuf;
-	buffer_element->length = fsf_req->data.send_generic.inbuf_length;
-	buffer_element->flags |= SBAL_FLAGS_LAST_ENTRY;
+	volatile struct qdio_buffer_element *sbale;
+	struct zfcp_port *port;
+	struct zfcp_adapter *adapter;
+        struct zfcp_fsf_req *fsf_req;
+        unsigned long lock_flags;
+        int bytes;
+	int ret = 0;
+
+	port = ct->port;
+	adapter = port->adapter;
+
+	ret = zfcp_fsf_req_create(adapter, FSF_QTCB_SEND_GENERIC,
+				  ZFCP_WAIT_FOR_SBAL | ZFCP_REQ_AUTO_CLEANUP,
+				  pool, &lock_flags, &fsf_req);
+	if (ret < 0) {
+                ZFCP_LOG_INFO("error: out of memory. Could not create CT "
+			      "request (FC-GS). (adapter: %s)\n",
+			      zfcp_get_busid_by_adapter(adapter));
+		goto failed_req;
+	}
+
+        if (erp_action != NULL) {
+                erp_action->fsf_req = fsf_req;
+                fsf_req->erp_action = erp_action;
+        }
+
+	sbale = zfcp_qdio_sbale_req(fsf_req, fsf_req->sbal_curr, 0);
+        if (zfcp_use_one_sbal(ct->req, ct->req_count,
+                              ct->resp, ct->resp_count)){
+                /* both request buffer and response buffer
+                   fit into one sbale each */
+                sbale[0].flags |= SBAL_FLAGS0_TYPE_WRITE_READ;
+                sbale[2].addr = zfcp_sg_to_address(&ct->req[0]);
+                sbale[2].length = ct->req[0].length;
+                sbale[3].addr = zfcp_sg_to_address(&ct->resp[0]);
+                sbale[3].length = ct->resp[0].length;
+                sbale[3].flags |= SBAL_FLAGS_LAST_ENTRY;
+        } else if (adapter->supported_features &
+                   FSF_FEATURE_ELS_CT_CHAINED_SBALS) {
+                /* try to use chained SBALs */
+                bytes = zfcp_qdio_sbals_from_sg(fsf_req,
+                                                SBAL_FLAGS0_TYPE_WRITE_READ,
+                                                ct->req, ct->req_count,
+                                                ZFCP_MAX_SBALS_PER_CT_REQ);
+                if (bytes <= 0) {
+                        ZFCP_LOG_INFO("error: out of resources (outbuf). "
+                                      "Could not create CT request (FC-GS). "
+				      "(adapter: %s)\n",
+				      zfcp_get_busid_by_adapter(adapter));
+                        if (bytes == 0)
+                                ret = -ENOMEM;
+                        else
+                                ret = bytes;
+
+                        goto failed_send;
+                }
+                fsf_req->qtcb->bottom.support.req_buf_length = bytes;
+                fsf_req->sbale_curr = ZFCP_LAST_SBALE_PER_SBAL;
+                bytes = zfcp_qdio_sbals_from_sg(fsf_req,
+                                                SBAL_FLAGS0_TYPE_WRITE_READ,
+                                                ct->resp, ct->resp_count,
+                                                ZFCP_MAX_SBALS_PER_CT_REQ);
+                if (bytes <= 0) {
+                        ZFCP_LOG_INFO("error: out of resources (inbuf). "
+                                      "Could not create a CT request (FC-GS). "
+				      "(adapter: %s)\n",
+				      zfcp_get_busid_by_adapter(adapter));
+                        if (bytes == 0)
+                                ret = -ENOMEM;
+                        else
+                                ret = bytes;
+
+                        goto failed_send;
+                }
+                fsf_req->qtcb->bottom.support.resp_buf_length = bytes;
+        } else {
+                /* reject send generic request */
+		ZFCP_LOG_INFO(
+			"error: microcode does not support chained SBALs."
+                        "CT request (FC-GS) too big. (adapter: %s)\n",
+			zfcp_get_busid_by_adapter(adapter));
+                ret = -EOPNOTSUPP;
+                goto failed_send;
+        }
 
 	/* settings in QTCB */
 	fsf_req->qtcb->header.port_handle = port->handle;
 	fsf_req->qtcb->bottom.support.service_class = adapter->fc_service_class;
-	fsf_req->qtcb->bottom.support.timeout = timeout;
+	fsf_req->qtcb->bottom.support.timeout = ct->timeout;
+        fsf_req->data.send_ct = ct;
 
 	/* start QDIO request for this FSF request */
-	retval = zfcp_fsf_req_send(fsf_req, timer);
-	if (retval) {
-		ZFCP_LOG_DEBUG("error: Out of resources. could not send a "
-			       "generic services "
-			       "command via the adapter %s, port "
-			       "WWPN 0x%Lx\n",
+	ret = zfcp_fsf_req_send(fsf_req, ct->timer);
+	if (ret) {
+		ZFCP_LOG_DEBUG("error: out of resources. Could not send CT "
+			       "request (FC-GS). (adapter: %s, "
+			       "port WWPN 0x%Lx)\n",
 			       zfcp_get_busid_by_adapter(adapter), port->wwpn);
-		/*
-		 * fsf_req structure will be cleaned up by higher layer handler
-		 */
-		goto out;
+		goto failed_send;
 	}
 
-	ZFCP_LOG_DEBUG("Send Generic request initiated "
-		       "(adapter busido=%s, port d_id=0x%x)\n",
-		       zfcp_get_busid_by_adapter(adapter),
-		       (unsigned int) port->d_id);
+	ZFCP_LOG_DEBUG("CT request initiated. (adapter: %s, port WWPN 0x%Lx)\n",
+		       zfcp_get_busid_by_adapter(adapter), port->wwpn);
+	goto out;
+
+ failed_send:
+	zfcp_fsf_req_free(fsf_req);
+        if (erp_action != NULL) {
+                erp_action->fsf_req = NULL;
+        }
+ failed_req:
  out:
-	return retval;
+        write_unlock_irqrestore(&adapter->request_queue.queue_lock,
+				lock_flags);
+	return ret;
 }
 
-/*
- * function:    zfcp_fsf_send_generic_handler
- *
- * purpose:	is called for finished Send Generic request
- *
- * returns:	
+/**
+ * zfcp_fsf_send_ct_handler - handler for Generic Service requests
+ * @fsf_req: pointer to struct zfcp_fsf_req
+ *
+ * Data specific for the Generic Service request is passed by
+ * fsf_req->data.send_ct
+ * Usually a specific handler for the request is called via
+ * fsf_req->data.send_ct->handler at end of this function.
  */
 static int
-zfcp_fsf_send_generic_handler(struct zfcp_fsf_req *fsf_req)
+zfcp_fsf_send_ct_handler(struct zfcp_fsf_req *fsf_req)
 {
+	struct zfcp_port *port;
+	struct zfcp_adapter *adapter;
+	struct zfcp_send_ct *send_ct;
+	struct fsf_qtcb_header *header;
+	struct fsf_qtcb_bottom_support *bottom;
 	int retval = -EINVAL;
-	struct zfcp_port *port = fsf_req->data.send_generic.port;
+	u16 subtable, rule, counter;
+
+	adapter = fsf_req->adapter;
+	send_ct = fsf_req->data.send_ct;
+	port = send_ct->port;
+	header = &fsf_req->qtcb->header;
+	bottom = &fsf_req->qtcb->bottom.support;
 
 	if (fsf_req->status & ZFCP_STATUS_FSFREQ_ERROR) {
 		/* do not set ZFCP_STATUS_FSFREQ_ABORTSUCCEEDED */
@@ -1503,180 +1613,514 @@ zfcp_fsf_send_generic_handler(struct zfc
 	}
 
 	/* evaluate FSF status in QTCB */
-	switch (fsf_req->qtcb->header.fsf_status) {
+	switch (header->fsf_status) {
 
-	case FSF_PORT_HANDLE_NOT_VALID:
-		ZFCP_LOG_FLAGS(1, "FSF_PORT_HANDLE_NOT_VALID\n");
-		ZFCP_LOG_DEBUG("Temporary port identifier (handle) 0x%x "
-			       "for the port with WWPN 0x%Lx connected to "
-			       "the adapter %s is "
-			       "not valid. This may happen occasionally.\n",
-			       port->handle,
-			       port->wwpn, zfcp_get_busid_by_port(port));
-		ZFCP_LOG_INFO("status qualifier:\n");
-		ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_INFO,
-			      (char *) &fsf_req->qtcb->header.fsf_status_qual,
-			      sizeof (union fsf_status_qual));
-		debug_text_event(fsf_req->adapter->erp_dbf, 1,
-				 "fsf_s_phandle_nv");
-		zfcp_erp_adapter_reopen(port->adapter, 0);
-		fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
+        case FSF_GOOD :
+                ZFCP_LOG_FLAGS(2,"FSF_GOOD\n");
+                retval = 0;
 		break;
 
-	case FSF_SERVICE_CLASS_NOT_SUPPORTED:
-		ZFCP_LOG_FLAGS(0, "FSF_SERVICE_CLASS_NOT_SUPPORTED\n");
-		if (fsf_req->adapter->fc_service_class <= 3) {
-			ZFCP_LOG_NORMAL("error: The adapter %s does "
+        case FSF_SERVICE_CLASS_NOT_SUPPORTED :
+		ZFCP_LOG_FLAGS(2, "FSF_SERVICE_CLASS_NOT_SUPPORTED\n");
+		if (adapter->fc_service_class <= 3) {
+			ZFCP_LOG_INFO("error: The adapter %s does "
 					"not support fibre-channel class %d.\n",
 					zfcp_get_busid_by_port(port),
-					fsf_req->adapter->fc_service_class);
+				      adapter->fc_service_class);
 		} else {
-			ZFCP_LOG_NORMAL
-			    ("bug: The fibre channel class at the adapter "
-			     "%s is invalid. " "(debug info %d)\n",
+			ZFCP_LOG_INFO("bug: The fibre channel class at the "
+				      "adapter %s is invalid. "
+				      "(debug info %d)\n",
 			     zfcp_get_busid_by_port(port),
-			     fsf_req->adapter->fc_service_class);
+				      adapter->fc_service_class);
 		}
 		/* stop operation for this adapter */
-		debug_text_exception(fsf_req->adapter->erp_dbf, 0,
-				     "fsf_s_class_nsup");
+		debug_text_exception(adapter->erp_dbf, 0, "fsf_s_class_nsup");
 		zfcp_erp_adapter_shutdown(port->adapter, 0);
 		fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
 		break;
 
-	case FSF_GENERIC_COMMAND_REJECTED:
-		ZFCP_LOG_FLAGS(1, "FSF_GENERIC_COMMAND_REJECTED\n");
+        case FSF_ADAPTER_STATUS_AVAILABLE :
+                ZFCP_LOG_FLAGS(2, "FSF_ADAPTER_STATUS_AVAILABLE\n");
+                switch (header->fsf_status_qual.word[0]){
+                case FSF_SQ_INVOKE_LINK_TEST_PROCEDURE :
+			ZFCP_LOG_FLAGS(2,"FSF_SQ_INVOKE_LINK_TEST_PROCEDURE\n");
+			/* reopening link to port */
+			debug_text_event(adapter->erp_dbf, 1, "fsf_sq_ltest");
+			zfcp_test_link(port);
+			fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
+			break;
+                case FSF_SQ_ULP_DEPENDENT_ERP_REQUIRED :
+			ZFCP_LOG_FLAGS(2,"FSF_SQ_ULP_DEPENDENT_ERP_REQUIRED\n");
+			/* ERP strategy will escalate */
+			debug_text_event(adapter->erp_dbf, 1, "fsf_sq_ulp");
+			fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
+			break;
+                default:
+			ZFCP_LOG_INFO("bug: Wrong status qualifier 0x%x "
+				      "arrived.\n",
+				      header->fsf_status_qual.word[0]);
+			break;
+                }
+                break;
+
+	case FSF_ACCESS_DENIED:
+		ZFCP_LOG_FLAGS(2, "FSF_ACCESS_DENIED\n");
+		ZFCP_LOG_NORMAL("Access denied, cannot send generic command "
+				"to a port with WWPN 0x%Lx connected "
+				"to the adapter %s\n", port->wwpn,
+				zfcp_get_busid_by_port(port));
+		counter = 0;
+		do {
+			subtable = header->fsf_status_qual.halfword[counter++];
+			rule = header->fsf_status_qual.halfword[counter++];
+			switch (subtable) {
+			case FSF_SQ_CFDC_SUBTABLE_OS:
+			case FSF_SQ_CFDC_SUBTABLE_PORT_WWPN:
+			case FSF_SQ_CFDC_SUBTABLE_PORT_DID:
+			case FSF_SQ_CFDC_SUBTABLE_LUN:
+       				ZFCP_LOG_NORMAL("Access denied (%s rule %d)\n",
+					zfcp_act_subtable_type[subtable], rule);
+				break;
+			}
+		} while (counter < 4);
+		debug_text_event(fsf_req->adapter->erp_dbf, 1, "fsf_s_access");
+		fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
+		break;
+
+        case FSF_GENERIC_COMMAND_REJECTED :
+		ZFCP_LOG_FLAGS(2, "FSF_GENERIC_COMMAND_REJECTED\n");
 		ZFCP_LOG_INFO("warning: The port with WWPN 0x%Lx connected to "
-			      "the adapter %s is"
+			      "the adapter %s has "
 			      "rejected a generic services command.\n",
 			      port->wwpn, zfcp_get_busid_by_port(port));
 		ZFCP_LOG_INFO("status qualifier:\n");
 		ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_INFO,
-			      (char *) &fsf_req->qtcb->header.fsf_status_qual,
+			      (char *) &header->fsf_status_qual,
 			      sizeof (union fsf_status_qual));
-		debug_text_event(fsf_req->adapter->erp_dbf, 1,
-				 "fsf_s_gcom_rej");
+		debug_text_event(adapter->erp_dbf, 1, "fsf_s_gcom_rej");
+		fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
+		break;
+
+        case FSF_PORT_HANDLE_NOT_VALID :
+		ZFCP_LOG_FLAGS(2, "FSF_PORT_HANDLE_NOT_VALID\n");
+		ZFCP_LOG_DEBUG("Temporary port identifier (handle) 0x%x "
+			       "for the port with WWPN 0x%Lx connected to "
+			       "the adapter %s is "
+			       "not valid. This may happen occasionally.\n",
+			       port->handle,
+			       port->wwpn, zfcp_get_busid_by_port(port));
+		ZFCP_LOG_INFO("status qualifier:\n");
+		ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_INFO,
+			      (char *) &header->fsf_status_qual,
+			      sizeof (union fsf_status_qual));
+		debug_text_event(adapter->erp_dbf, 1, "fsf_s_phandle_nv");
+		zfcp_erp_adapter_reopen(port->adapter, 0);
 		fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
 		break;
 
-	case FSF_REQUEST_BUF_NOT_VALID:
-		ZFCP_LOG_FLAGS(1, "FSF_REQUEST_BUF_NOT_VALID\n");
+	case FSF_REQUEST_BUF_NOT_VALID :
+		ZFCP_LOG_FLAGS(2, "FSF_REQUEST_BUF_NOT_VALID\n");
 		ZFCP_LOG_NORMAL("error: The port with WWPN 0x%Lx connected to "
-				"the adapter %s is"
+				"the adapter %s has "
 				"rejected a generic services command "
 				"due to invalid request buffer.\n",
 				port->wwpn, zfcp_get_busid_by_port(port));
-		debug_text_event(fsf_req->adapter->erp_dbf, 1, "fsf_s_reqiv");
+		debug_text_event(adapter->erp_dbf, 1, "fsf_s_reqiv");
 		fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
 		break;
 
-	case FSF_RESPONSE_BUF_NOT_VALID:
-		ZFCP_LOG_FLAGS(1, "FSF_RESPONSE_BUF_NOT_VALID\n");
+	case FSF_RESPONSE_BUF_NOT_VALID :
+		ZFCP_LOG_FLAGS(2, "FSF_RESPONSE_BUF_NOT_VALID\n");
 		ZFCP_LOG_NORMAL("error: The port with WWPN 0x%Lx connected to "
-				"the adapter %s is"
+				"the adapter %s has "
 				"rejected a generic services command "
 				"due to invalid response buffer.\n",
 				port->wwpn, zfcp_get_busid_by_port(port));
-		debug_text_event(fsf_req->adapter->erp_dbf, 1, "fsf_s_resiv");
+		debug_text_event(adapter->erp_dbf, 1, "fsf_s_resiv");
 		fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
 		break;
 
-	case FSF_PORT_BOXED:
+        case FSF_PORT_BOXED :
 		ZFCP_LOG_FLAGS(2, "FSF_PORT_BOXED\n");
 		ZFCP_LOG_DEBUG("The remote port "
 			       "with WWPN 0x%Lx on the adapter %s "
 			       "needs to be reopened\n",
 			       port->wwpn, zfcp_get_busid_by_port(port));
-		debug_text_event(fsf_req->adapter->erp_dbf, 2, "fsf_s_pboxed");
+		debug_text_event(adapter->erp_dbf, 2, "fsf_s_pboxed");
 		zfcp_erp_port_reopen(port, 0);
 		fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR
 		    | ZFCP_STATUS_FSFREQ_RETRY;
 		break;
 
-	case FSF_ADAPTER_STATUS_AVAILABLE:
-		ZFCP_LOG_FLAGS(2, "FSF_ADAPTER_STATUS_AVAILABLE\n");
-		switch (fsf_req->qtcb->header.fsf_status_qual.word[0]) {
-		case FSF_SQ_INVOKE_LINK_TEST_PROCEDURE:
-			ZFCP_LOG_FLAGS(2,
-				       "FSF_SQ_INVOKE_LINK_TEST_PROCEDURE\n");
-			/* reopening link to port */
-			debug_text_event(fsf_req->adapter->erp_dbf, 1,
-					 "fsf_sq_ltest");
-			zfcp_erp_port_forced_reopen(port, 0);
-			fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
-			break;
-		case FSF_SQ_ULP_DEPENDENT_ERP_REQUIRED:
-			/* ERP strategy will escalate */
-			debug_text_event(fsf_req->adapter->erp_dbf, 1,
-					 "fsf_sq_ulp");
-			fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
-			break;
-
-		default:
-			ZFCP_LOG_NORMAL
-			    ("bug: Wrong status qualifier 0x%x arrived.\n",
-			     fsf_req->qtcb->header.fsf_status_qual.word[0]);
-			break;
-		}
-		break;
-
-	case FSF_GOOD:
-		ZFCP_LOG_FLAGS(2, "FSF_GOOD\n");
-		retval = 0;
-		break;
-
-	default:
+       default :
 		ZFCP_LOG_NORMAL("bug: An unknown FSF Status was presented "
-				"(debug info 0x%x)\n",
-				fsf_req->qtcb->header.fsf_status);
-		debug_text_event(fsf_req->adapter->erp_dbf, 0, "fsf_sq_inval:");
-		debug_exception(fsf_req->adapter->erp_dbf, 0,
-				&fsf_req->qtcb->header.fsf_status_qual.word[0],
-				sizeof (u32));
+				"(debug info 0x%x)\n", header->fsf_status);
+		debug_text_event(adapter->erp_dbf, 0, "fsf_sq_inval:");
+		debug_exception(adapter->erp_dbf, 0,
+				&header->fsf_status_qual.word[0], sizeof (u32));
 		break;
 	}
- skip_fsfstatus:
-	/* callback */
-	(fsf_req->data.send_generic.handler)(fsf_req);
+
+skip_fsfstatus:
+	if (send_ct->handler != NULL) {
+		send_ct->handler(send_ct->handler_data);
+        }
+
 	return retval;
 }
 
-/*
- * function:
- *
- * purpose:
- *
- * returns:	address of initiated FSF request
- *		NULL - request could not be initiated
+/**
+ * zfcp_fsf_send_els - initiate an ELS command (FC-FS)
+ * @els: pointer to struct zfcp_send_els which contains all needed data for
+ *	the command.
  */
 int
-zfcp_fsf_exchange_config_data(struct zfcp_erp_action *erp_action)
+zfcp_fsf_send_els(struct zfcp_send_els *els)
 {
-	int retval = 0;
+	volatile struct qdio_buffer_element *sbale;
+	struct zfcp_fsf_req *fsf_req;
+	struct zfcp_port *port;
+	struct zfcp_adapter *adapter;
 	unsigned long lock_flags;
+        int bytes;
+	int ret = 0;
 
-	/* setup new FSF request */
-	retval = zfcp_fsf_req_create(erp_action->adapter,
-				     FSF_QTCB_EXCHANGE_CONFIG_DATA,
-				     &lock_flags,
-				     ZFCP_REQ_AUTO_CLEANUP,
-				     &(erp_action->fsf_req));
-	if (retval < 0) {
-		ZFCP_LOG_INFO("error: Out of resources. Could not create an "
-			      "exchange configuration data request for"
-			      "the adapter %s.\n",
-			      zfcp_get_busid_by_adapter(erp_action->adapter));
-		goto out;
-	}
+	port = els->port;
+	adapter = port->adapter;
 
-	erp_action->fsf_req->erp_action = erp_action;
-	/* no information from us to adapter, set nothing */
+        ret = zfcp_fsf_req_create(adapter, FSF_QTCB_SEND_ELS,
+				  ZFCP_WAIT_FOR_SBAL|ZFCP_REQ_AUTO_CLEANUP,
+				  NULL, &lock_flags, &fsf_req);
+	if (ret < 0) {
+                ZFCP_LOG_INFO("error: out of memory. Could not create ELS "
+			      "request. (adapter: %s, port did: 0x%06x)\n",
+                              zfcp_get_busid_by_adapter(adapter), port->d_id);
+                goto failed_req;
+	}
+
+	sbale = zfcp_qdio_sbale_req(fsf_req, fsf_req->sbal_curr, 0);
+        if (zfcp_use_one_sbal(els->req, els->req_count,
+                              els->resp, els->resp_count)){
+                /* both request buffer and response buffer
+                   fit into one sbale each */
+                sbale[0].flags |= SBAL_FLAGS0_TYPE_WRITE_READ;
+                sbale[2].addr = zfcp_sg_to_address(&els->req[0]);
+                sbale[2].length = els->req[0].length;
+                sbale[3].addr = zfcp_sg_to_address(&els->resp[0]);
+                sbale[3].length = els->resp[0].length;
+                sbale[3].flags |= SBAL_FLAGS_LAST_ENTRY;
+        } else if (adapter->supported_features &
+                   FSF_FEATURE_ELS_CT_CHAINED_SBALS) {
+                /* try to use chained SBALs */
+                bytes = zfcp_qdio_sbals_from_sg(fsf_req,
+                                                SBAL_FLAGS0_TYPE_WRITE_READ,
+                                                els->req, els->req_count,
+                                                ZFCP_MAX_SBALS_PER_ELS_REQ);
+                if (bytes <= 0) {
+                        ZFCP_LOG_INFO("error: out of resources (outbuf). "
+                                      "Could not create ELS request. "
+				      "(adapter: %s, port did: 0x%06x)\n",
+				      zfcp_get_busid_by_adapter(adapter),
+				      port->d_id);
+                        if (bytes == 0) {
+                                ret = -ENOMEM;
+                        } else {
+                                ret = bytes;
+                        }
+                        goto failed_send;
+                }
+                fsf_req->qtcb->bottom.support.req_buf_length = bytes;
+                fsf_req->sbale_curr = ZFCP_LAST_SBALE_PER_SBAL;
+                bytes = zfcp_qdio_sbals_from_sg(fsf_req,
+                                                SBAL_FLAGS0_TYPE_WRITE_READ,
+                                                els->resp, els->resp_count,
+                                                ZFCP_MAX_SBALS_PER_ELS_REQ);
+                if (bytes <= 0) {
+                        ZFCP_LOG_INFO("error: out of resources (inbuf). "
+                                      "Could not create ELS request. "
+				      "(adapter: %s, port did: 0x%06x)\n",
+				      zfcp_get_busid_by_adapter(adapter),
+				      port->d_id);
+                        if (bytes == 0) {
+                                ret = -ENOMEM;
+                        } else {
+                                ret = bytes;
+                        }
+                        goto failed_send;
+                }
+                fsf_req->qtcb->bottom.support.resp_buf_length = bytes;
+        } else {
+                /* reject request */
+		ZFCP_LOG_INFO("error: microcode does not support chained SBALs."
+                              "ELS request too big. "
+			      "(adapter: %s, port did: 0x%06x)\n",
+			      zfcp_get_busid_by_adapter(adapter), port->d_id);
+                ret = -EOPNOTSUPP;
+                goto failed_send;
+        }
+
+	/* settings in QTCB */
+	fsf_req->qtcb->bottom.support.d_id = port->d_id;
+	fsf_req->qtcb->bottom.support.service_class = adapter->fc_service_class;
+	fsf_req->qtcb->bottom.support.timeout = ZFCP_ELS_TIMEOUT;
+	fsf_req->data.send_els = els;
+
+	sbale = zfcp_qdio_sbale_req(fsf_req, fsf_req->sbal_curr, 0);
 
 	/* start QDIO request for this FSF request */
-	retval = zfcp_fsf_req_send(erp_action->fsf_req, &erp_action->timer);
-	if (retval) {
-		ZFCP_LOG_INFO
-		    ("error: Could not send an exchange configuration data "
+	ret = zfcp_fsf_req_send(fsf_req, NULL);
+	if (ret) {
+		ZFCP_LOG_DEBUG("error: out of resources. Could not send ELS "
+                               "request. (adapter: %s, port WWPN 0x%Lx)\n",
+			       zfcp_get_busid_by_adapter(adapter), port->wwpn);
+		goto failed_send;
+	}
+
+	ZFCP_LOG_DEBUG("ELS request initiated (adapter: %s, port WWPN 0x%Lx)\n",
+		       zfcp_get_busid_by_adapter(adapter), port->wwpn);
+	goto out;
+
+ failed_send:
+	zfcp_fsf_req_free(fsf_req);
+
+ failed_req:
+ out:
+	write_unlock_irqrestore(&adapter->request_queue.queue_lock,
+				lock_flags);
+
+        return ret;
+}
+
+/**
+ * zfcp_fsf_send_els_handler - handler for ELS commands
+ * @fsf_req: pointer to struct zfcp_fsf_req
+ *
+ * Data specific for the ELS command is passed by
+ * fsf_req->data.send_els
+ * Usually a specific handler for the command is called via
+ * fsf_req->data.send_els->handler at end of this function.
+ */
+static int zfcp_fsf_send_els_handler(struct zfcp_fsf_req *fsf_req)
+{
+	struct zfcp_adapter *adapter;
+	struct zfcp_port *port;
+	struct fsf_qtcb_header *header;
+	struct fsf_qtcb_bottom_support *bottom;
+	struct zfcp_send_els *send_els;
+	int retval = -EINVAL;
+	u16 subtable, rule, counter;
+
+	adapter = fsf_req->adapter;
+	send_els = fsf_req->data.send_els;
+	port = send_els->port;
+	header = &fsf_req->qtcb->header;
+	bottom = &fsf_req->qtcb->bottom.support;
+
+	if (fsf_req->status & ZFCP_STATUS_FSFREQ_ERROR)
+		goto skip_fsfstatus;
+
+	switch (header->fsf_status) {
+
+	case FSF_GOOD:
+		ZFCP_LOG_FLAGS(2, "FSF_GOOD\n");
+		retval = 0;
+		break;
+
+	case FSF_SERVICE_CLASS_NOT_SUPPORTED:
+		ZFCP_LOG_FLAGS(2, "FSF_SERVICE_CLASS_NOT_SUPPORTED\n");
+		if (adapter->fc_service_class <= 3) {
+			ZFCP_LOG_INFO("error: The adapter %s does "
+				      "not support fibre-channel class %d.\n",
+				      zfcp_get_busid_by_port(port),
+				      adapter->fc_service_class);
+		} else {
+			ZFCP_LOG_INFO("bug: The fibre channel class at the "
+				      "adapter %s is invalid. "
+				      "(debug info %d)\n",
+				      zfcp_get_busid_by_port(port),
+				      adapter->fc_service_class);
+		}
+		/* stop operation for this adapter */
+		debug_text_exception(adapter->erp_dbf, 0, "fsf_s_class_nsup");
+		zfcp_erp_adapter_shutdown(port->adapter, 0);
+		fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
+		break;
+
+	case FSF_ADAPTER_STATUS_AVAILABLE:
+		ZFCP_LOG_FLAGS(2, "FSF_ADAPTER_STATUS_AVAILABLE\n");
+		switch (header->fsf_status_qual.word[0]){
+		case FSF_SQ_INVOKE_LINK_TEST_PROCEDURE: {
+			ZFCP_LOG_FLAGS(2,"FSF_SQ_INVOKE_LINK_TEST_PROCEDURE\n");
+			debug_text_event(adapter->erp_dbf, 1, "fsf_sq_ltest");
+			if (send_els->ls_code != ZFCP_LS_ADISC)
+				zfcp_test_link(port);
+			fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
+			break;
+		}
+		case FSF_SQ_ULP_DEPENDENT_ERP_REQUIRED:
+			ZFCP_LOG_FLAGS(2,"FSF_SQ_ULP_DEPENDENT_ERP_REQUIRED\n");
+			/* ERP strategy will escalate */
+			debug_text_event(adapter->erp_dbf, 1, "fsf_sq_ulp");
+			fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
+			break;
+		case FSF_SQ_RETRY_IF_POSSIBLE:
+			ZFCP_LOG_FLAGS(2, "FSF_SQ_RETRY_IF_POSSIBLE\n");
+			debug_text_event(adapter->erp_dbf, 1, "fsf_sq_retry");
+			fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
+			break;
+		default:
+			ZFCP_LOG_INFO("bug: Wrong status qualifier 0x%x\n",
+				      header->fsf_status_qual.word[0]);
+			ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_INFO,
+				(char*)header->fsf_status_qual.word, 16);
+		}
+		break;
+
+	case FSF_ELS_COMMAND_REJECTED:
+		ZFCP_LOG_FLAGS(2, "FSF_ELS_COMMAND_REJECTED\n");
+		ZFCP_LOG_INFO("The ELS command has been rejected because "
+			      "a command filter in the FCP channel prohibited "
+			      "sending of the ELS to the SAN "
+			      "(adapter: %s, wwpn=0x%016Lx)\n",
+			      zfcp_get_busid_by_port(port), port->wwpn);
+
+		break;
+
+	case FSF_PAYLOAD_SIZE_MISMATCH:
+		ZFCP_LOG_FLAGS(2, "FSF_PAYLOAD_SIZE_MISMATCH\n");
+		ZFCP_LOG_INFO(
+			"ELS request size and ELS response size must be either "
+			"both 0, or both greater than 0 "
+			"(adapter: %s, req_buf_length=%d resp_buf_length=%d)\n",
+			zfcp_get_busid_by_port(port),
+			bottom->req_buf_length,
+			bottom->resp_buf_length);
+		break;
+
+	case FSF_REQUEST_SIZE_TOO_LARGE:
+		ZFCP_LOG_FLAGS(2, "FSF_REQUEST_SIZE_TOO_LARGE\n");
+		ZFCP_LOG_INFO(
+			"Length of the ELS request buffer, "
+			"specified in QTCB bottom, "
+			"exceeds the size of the buffers "
+			"that have been allocated for ELS request data "
+			"(adapter: %s, req_buf_length=%d)\n",
+			zfcp_get_busid_by_port(port),
+			bottom->req_buf_length);
+		break;
+
+	case FSF_RESPONSE_SIZE_TOO_LARGE:
+		ZFCP_LOG_FLAGS(2, "FSF_RESPONSE_SIZE_TOO_LARGE\n");
+		ZFCP_LOG_INFO(
+			"Length of the ELS response buffer, "
+			"specified in QTCB bottom, "
+			"exceeds the size of the buffers "
+			"that have been allocated for ELS response data "
+			"(adapter: %s, resp_buf_length=%d)\n",
+			zfcp_get_busid_by_port(port),
+			bottom->resp_buf_length);
+		break;
+
+	case FSF_UNKNOWN_COMMAND:
+		ZFCP_LOG_FLAGS(2, "FSF_UNKNOWN_COMMAND\n");
+		ZFCP_LOG_INFO(
+			"FSF command 0x%x is not supported by FCP adapter "
+			"(adapter: %s)\n", fsf_req->fsf_command,
+			zfcp_get_busid_by_port(port));
+		fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
+		break;
+
+	case FSF_ACCESS_DENIED:
+		ZFCP_LOG_FLAGS(2, "FSF_ACCESS_DENIED\n");
+		ZFCP_LOG_NORMAL("Access denied, cannot send ELS "
+				"(adapter: %s, wwpn=0x%016Lx)\n",
+				zfcp_get_busid_by_port(port), port->wwpn);
+		counter = 0;
+		do {
+			subtable = header->fsf_status_qual.halfword[counter++];
+			rule = header->fsf_status_qual.halfword[counter++];
+			switch (subtable) {
+			case FSF_SQ_CFDC_SUBTABLE_OS:
+			case FSF_SQ_CFDC_SUBTABLE_PORT_WWPN:
+			case FSF_SQ_CFDC_SUBTABLE_PORT_DID:
+			case FSF_SQ_CFDC_SUBTABLE_LUN:
+				ZFCP_LOG_NORMAL("Access denied (%s rule %d)\n",
+					zfcp_act_subtable_type[subtable], rule);
+				break;
+			}
+		} while (counter < 4);
+		debug_text_event(adapter->erp_dbf, 1, "fsf_s_access");
+		fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
+		break;
+
+	default:
+		ZFCP_LOG_NORMAL(
+			"bug: An unknown FSF Status was presented "
+			"(adapter: %s, fsf_status=0x%08x)\n",
+			zfcp_get_busid_by_port(port),
+			header->fsf_status);
+		debug_text_event(adapter->erp_dbf, 0, "fsf_sq_inval");
+		debug_exception(adapter->erp_dbf, 0,
+			&header->fsf_status_qual.word[0], sizeof(u32));
+		fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
+		break;
+	}
+
+skip_fsfstatus:
+	send_els->status = retval;
+
+	if (send_els->handler != 0)
+		send_els->handler(send_els->handler_data);
+
+	kfree(send_els);
+
+	return retval;
+}
+
+/*
+ * function:
+ *
+ * purpose:
+ *
+ * returns:	address of initiated FSF request
+ *		NULL - request could not be initiated
+ */
+int
+zfcp_fsf_exchange_config_data(struct zfcp_erp_action *erp_action)
+{
+	volatile struct qdio_buffer_element *sbale;
+	unsigned long lock_flags;
+	int retval = 0;
+
+	/* setup new FSF request */
+	retval = zfcp_fsf_req_create(erp_action->adapter,
+				     FSF_QTCB_EXCHANGE_CONFIG_DATA,
+				     ZFCP_REQ_AUTO_CLEANUP,
+				     erp_action->adapter->pool.fsf_req_erp,
+				     &lock_flags, &(erp_action->fsf_req));
+	if (retval < 0) {
+		ZFCP_LOG_INFO("error: Out of resources. Could not create an "
+			      "exchange configuration data request for"
+			      "the adapter %s.\n",
+			      zfcp_get_busid_by_adapter(erp_action->adapter));
+		goto out;
+	}
+
+	sbale = zfcp_qdio_sbale_req(erp_action->fsf_req,
+                                    erp_action->fsf_req->sbal_curr, 0);
+        sbale[0].flags |= SBAL_FLAGS0_TYPE_READ;
+        sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY;
+
+	erp_action->fsf_req->erp_action = erp_action;
+	erp_action->fsf_req->qtcb->bottom.config.feature_selection =
+		FSF_FEATURE_CFDC;
+
+	/* start QDIO request for this FSF request */
+	retval = zfcp_fsf_req_send(erp_action->fsf_req, &erp_action->timer);
+	if (retval) {
+		ZFCP_LOG_INFO
+		    ("error: Could not send an exchange configuration data "
 		     "command on the adapter %s\n",
 		     zfcp_get_busid_by_adapter(erp_action->adapter));
 		zfcp_fsf_req_free(erp_action->fsf_req);
@@ -1702,7 +2146,8 @@ zfcp_fsf_exchange_config_data(struct zfc
  * returns:
  */
 static int
-zfcp_fsf_exchange_config_data_handler(struct zfcp_fsf_req *fsf_req) {
+zfcp_fsf_exchange_config_data_handler(struct zfcp_fsf_req *fsf_req)
+{
 	int retval = -EIO;
 	struct fsf_qtcb_bottom_config *bottom;
 	struct zfcp_adapter *adapter = fsf_req->adapter;
@@ -1730,6 +2175,17 @@ zfcp_fsf_exchange_config_data_handler(st
 		adapter->fsf_lic_version = bottom->lic_version;
 		adapter->fc_topology = bottom->fc_topology;
 		adapter->fc_link_speed = bottom->fc_link_speed;
+                adapter->supported_features = bottom->supported_features;
+
+		if(adapter->supported_features & FSF_FEATURE_HBAAPI_MANAGEMENT){
+			adapter->hardware_version = bottom->hardware_version;
+                        /* copy just first 17 bytes */
+                        memcpy(adapter->serial_number,
+                               bottom->serial_number, 17);
+                        EBCASC(adapter->serial_number,
+                               sizeof(adapter->serial_number));
+		}
+
 		ZFCP_LOG_INFO("The adapter %s reported "
 			      "the following characteristics:\n"
 			      "WWNN 0x%16.16Lx, "
@@ -1810,14 +2266,14 @@ zfcp_fsf_exchange_config_data_handler(st
 			zfcp_erp_adapter_shutdown(adapter, 0);
 			goto skip_fsfstatus;
 		}
-		if (bottom->max_qtcb_size < ZFCP_QTCB_SIZE) {
+		if (bottom->max_qtcb_size < sizeof(struct fsf_qtcb)) {
 			ZFCP_LOG_NORMAL("bug: Maximum QTCB size (%d bytes) "
 					"allowed by the adapter %s "
 					"is lower than the minimum "
 					"required by the driver (%ld bytes).\n",
 					bottom->max_qtcb_size,
 					zfcp_get_busid_by_adapter(adapter),
-					ZFCP_QTCB_SIZE);
+					sizeof(struct fsf_qtcb));
 			debug_text_event(fsf_req->adapter->erp_dbf, 0,
 					 "qtcb-size");
 			debug_event(fsf_req->adapter->erp_dbf, 0,
@@ -1828,13 +2284,14 @@ zfcp_fsf_exchange_config_data_handler(st
 		atomic_set_mask(ZFCP_STATUS_ADAPTER_XCONFIG_OK,
 				&adapter->status);
 		retval = 0;
+
 		break;
+
 	default:
 		/* retval is -EIO by default */
 		debug_text_event(fsf_req->adapter->erp_dbf, 0, "fsf-stat-ng");
 		debug_event(fsf_req->adapter->erp_dbf, 0,
 			    &fsf_req->qtcb->header.fsf_status, sizeof (u32));
-		zfcp_erp_adapter_shutdown(adapter, 0);
 	}
  skip_fsfstatus:
 	return retval;
@@ -1851,15 +2308,16 @@ zfcp_fsf_exchange_config_data_handler(st
 int
 zfcp_fsf_open_port(struct zfcp_erp_action *erp_action)
 {
-	int retval = 0;
+	volatile struct qdio_buffer_element *sbale;
 	unsigned long lock_flags;
+	int retval = 0;
 
 	/* setup new FSF request */
 	retval = zfcp_fsf_req_create(erp_action->adapter,
 				     FSF_QTCB_OPEN_PORT_WITH_DID,
-				     &lock_flags,
 				     ZFCP_WAIT_FOR_SBAL | ZFCP_REQ_AUTO_CLEANUP,
-				     &(erp_action->fsf_req));
+				     erp_action->adapter->pool.fsf_req_erp,
+				     &lock_flags, &(erp_action->fsf_req));
 	if (retval < 0) {
 		ZFCP_LOG_INFO("error: Out of resources. Could not create an "
 			      "open port request for "
@@ -1870,6 +2328,11 @@ zfcp_fsf_open_port(struct zfcp_erp_actio
 		goto out;
 	}
 
+	sbale = zfcp_qdio_sbale_req(erp_action->fsf_req,
+                                    erp_action->fsf_req->sbal_curr, 0);
+        sbale[0].flags |= SBAL_FLAGS0_TYPE_READ;
+        sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY;
+
 	erp_action->fsf_req->qtcb->bottom.support.d_id = erp_action->port->d_id;
 	atomic_set_mask(ZFCP_STATUS_COMMON_OPENING, &erp_action->port->status);
 	erp_action->fsf_req->data.open_port.port = erp_action->port;
@@ -1912,8 +2375,11 @@ zfcp_fsf_open_port_handler(struct zfcp_f
 	int retval = -EINVAL;
 	struct zfcp_port *port;
 	struct fsf_plogi *plogi;
+	struct fsf_qtcb_header *header;
+	u16 subtable, rule, counter;
 
 	port = fsf_req->data.open_port.port;
+	header = &fsf_req->qtcb->header;
 
 	if (fsf_req->status & ZFCP_STATUS_FSFREQ_ERROR) {
 		/* don't change port status in our bookkeeping */
@@ -1921,7 +2387,7 @@ zfcp_fsf_open_port_handler(struct zfcp_f
 	}
 
 	/* evaluate FSF status in QTCB */
-	switch (fsf_req->qtcb->header.fsf_status) {
+	switch (header->fsf_status) {
 
 	case FSF_PORT_ALREADY_OPEN:
 		ZFCP_LOG_FLAGS(0, "FSF_PORT_ALREADY_OPEN\n");
@@ -1937,6 +2403,30 @@ zfcp_fsf_open_port_handler(struct zfcp_f
 		 */
 		break;
 
+	case FSF_ACCESS_DENIED:
+		ZFCP_LOG_FLAGS(2, "FSF_ACCESS_DENIED\n");
+		ZFCP_LOG_NORMAL("Access denied, cannot open port "
+			"with WWPN 0x%Lx connected to the adapter %s\n",
+			port->wwpn, zfcp_get_busid_by_port(port));
+		counter = 0;
+		do {
+			subtable = header->fsf_status_qual.halfword[counter++];
+			rule = header->fsf_status_qual.halfword[counter++];
+			switch (subtable) {
+			case FSF_SQ_CFDC_SUBTABLE_OS:
+			case FSF_SQ_CFDC_SUBTABLE_PORT_WWPN:
+			case FSF_SQ_CFDC_SUBTABLE_PORT_DID:
+			case FSF_SQ_CFDC_SUBTABLE_LUN:
+				ZFCP_LOG_NORMAL("Access denied (%s rule %d)\n",
+					zfcp_act_subtable_type[subtable], rule);
+				break;
+			}
+		} while (counter < 4);
+		debug_text_event(fsf_req->adapter->erp_dbf, 1, "fsf_s_access");
+		zfcp_erp_port_failed(port);
+		fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
+		break;
+
 	case FSF_MAXIMUM_NUMBER_OF_PORTS_EXCEEDED:
 		ZFCP_LOG_FLAGS(1, "FSF_MAXIMUM_NUMBER_OF_PORTS_EXCEEDED\n");
 		ZFCP_LOG_INFO("error: The FSF adapter is out of resources. "
@@ -1952,7 +2442,7 @@ zfcp_fsf_open_port_handler(struct zfcp_f
 
 	case FSF_ADAPTER_STATUS_AVAILABLE:
 		ZFCP_LOG_FLAGS(2, "FSF_ADAPTER_STATUS_AVAILABLE\n");
-		switch (fsf_req->qtcb->header.fsf_status_qual.word[0]) {
+		switch (header->fsf_status_qual.word[0]) {
 		case FSF_SQ_INVOKE_LINK_TEST_PROCEDURE:
 			ZFCP_LOG_FLAGS(2,
 				       "FSF_SQ_INVOKE_LINK_TEST_PROCEDURE\n");
@@ -1982,12 +2472,12 @@ zfcp_fsf_open_port_handler(struct zfcp_f
 		default:
 			ZFCP_LOG_NORMAL
 			    ("bug: Wrong status qualifier 0x%x arrived.\n",
-			     fsf_req->qtcb->header.fsf_status_qual.word[0]);
+			     header->fsf_status_qual.word[0]);
 			debug_text_event(fsf_req->adapter->erp_dbf, 0,
 					 "fsf_sq_inval:");
 			debug_exception(
 				fsf_req->adapter->erp_dbf, 0,
-				&fsf_req->qtcb->header.fsf_status_qual.word[0],
+				&header->fsf_status_qual.word[0],
 				sizeof (u32));
 			break;
 		}
@@ -1996,7 +2486,7 @@ zfcp_fsf_open_port_handler(struct zfcp_f
 	case FSF_GOOD:
 		ZFCP_LOG_FLAGS(3, "FSF_GOOD\n");
 		/* save port handle assigned by FSF */
-		port->handle = fsf_req->qtcb->header.port_handle;
+		port->handle = header->port_handle;
 		ZFCP_LOG_INFO("The remote port (WWPN=0x%Lx) via adapter "
 			      "(busid=%s) was opened, it's "
 			      "port handle is 0x%x\n",
@@ -2055,11 +2545,10 @@ zfcp_fsf_open_port_handler(struct zfcp_f
 	default:
 		ZFCP_LOG_NORMAL("bug: An unknown FSF Status was presented "
 				"(debug info 0x%x)\n",
-				fsf_req->qtcb->header.fsf_status);
+				header->fsf_status);
 		debug_text_event(fsf_req->adapter->erp_dbf, 0, "fsf_s_inval:");
 		debug_exception(fsf_req->adapter->erp_dbf, 0,
-				&fsf_req->qtcb->header.fsf_status,
-				sizeof (u32));
+				&header->fsf_status, sizeof (u32));
 		break;
 	}
 
@@ -2079,15 +2568,16 @@ zfcp_fsf_open_port_handler(struct zfcp_f
 int
 zfcp_fsf_close_port(struct zfcp_erp_action *erp_action)
 {
-	int retval = 0;
+	volatile struct qdio_buffer_element *sbale;
 	unsigned long lock_flags;
+	int retval = 0;
 
 	/* setup new FSF request */
 	retval = zfcp_fsf_req_create(erp_action->adapter,
 				     FSF_QTCB_CLOSE_PORT,
-				     &lock_flags,
 				     ZFCP_WAIT_FOR_SBAL | ZFCP_REQ_AUTO_CLEANUP,
-				     &(erp_action->fsf_req));
+				     erp_action->adapter->pool.fsf_req_erp,
+				     &lock_flags, &(erp_action->fsf_req));
 	if (retval < 0) {
 		ZFCP_LOG_INFO("error: Out of resources. Could not create a "
 			      "close port request for WWPN 0x%Lx connected to "
@@ -2097,6 +2587,11 @@ zfcp_fsf_close_port(struct zfcp_erp_acti
 		goto out;
 	}
 
+	sbale = zfcp_qdio_sbale_req(erp_action->fsf_req,
+                                    erp_action->fsf_req->sbal_curr, 0);
+        sbale[0].flags |= SBAL_FLAGS0_TYPE_READ;
+        sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY;
+
 	atomic_set_mask(ZFCP_STATUS_COMMON_CLOSING, &erp_action->port->status);
 	erp_action->fsf_req->data.close_port.port = erp_action->port;
 	erp_action->fsf_req->erp_action = erp_action;
@@ -2153,7 +2648,7 @@ zfcp_fsf_close_port_handler(struct zfcp_
 		ZFCP_LOG_FLAGS(1, "FSF_PORT_HANDLE_NOT_VALID\n");
 		ZFCP_LOG_INFO("Temporary port identifier (handle) 0x%x "
 			      "for the port with WWPN 0x%Lx connected to "
-			      "the adapter %s is"
+			      "the adapter %s is "
 			      "not valid. This may happen occasionally.\n",
 			      port->handle,
 			      port->wwpn, zfcp_get_busid_by_port(port));
@@ -2221,9 +2716,9 @@ zfcp_fsf_close_physical_port(struct zfcp
 	/* setup new FSF request */
 	retval = zfcp_fsf_req_create(erp_action->adapter,
 				     FSF_QTCB_CLOSE_PHYSICAL_PORT,
-				     &lock_flags,
 				     ZFCP_WAIT_FOR_SBAL | ZFCP_REQ_AUTO_CLEANUP,
-				     &erp_action->fsf_req);
+				     erp_action->adapter->pool.fsf_req_erp,
+				     &lock_flags, &erp_action->fsf_req);
 	if (retval < 0) {
 		ZFCP_LOG_INFO("error: Out of resources. Could not create a "
 			      "close physical port request for "
@@ -2280,8 +2775,11 @@ zfcp_fsf_close_physical_port_handler(str
 	int retval = -EINVAL;
 	struct zfcp_port *port;
 	struct zfcp_unit *unit;
+	struct fsf_qtcb_header *header;
+	u16 subtable, rule, counter;
 
 	port = fsf_req->data.close_physical_port.port;
+	header = &fsf_req->qtcb->header;
 
 	if (fsf_req->status & ZFCP_STATUS_FSFREQ_ERROR) {
 		/* don't change port status in our bookkeeping */
@@ -2289,7 +2787,7 @@ zfcp_fsf_close_physical_port_handler(str
 	}
 
 	/* evaluate FSF status in QTCB */
-	switch (fsf_req->qtcb->header.fsf_status) {
+	switch (header->fsf_status) {
 
 	case FSF_PORT_HANDLE_NOT_VALID:
 		ZFCP_LOG_FLAGS(1, "FSF_PORT_HANDLE_NOT_VALID\n");
@@ -2302,7 +2800,7 @@ zfcp_fsf_close_physical_port_handler(str
 			      zfcp_get_busid_by_port(port));
 		ZFCP_LOG_DEBUG("status qualifier:\n");
 		ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_DEBUG,
-			      (char *) &fsf_req->qtcb->header.fsf_status_qual,
+			      (char *) &header->fsf_status_qual,
 			      sizeof (union fsf_status_qual));
 		debug_text_event(fsf_req->adapter->erp_dbf, 1,
 				 "fsf_s_phand_nv");
@@ -2310,6 +2808,30 @@ zfcp_fsf_close_physical_port_handler(str
 		fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
 		break;
 
+	case FSF_ACCESS_DENIED:
+		ZFCP_LOG_FLAGS(2, "FSF_ACCESS_DENIED\n");
+		ZFCP_LOG_NORMAL("Access denied, cannot close "
+				"physical port with WWPN 0x%Lx connected to "
+				"the adapter %s\n", port->wwpn,
+				zfcp_get_busid_by_port(port));
+		counter = 0;
+		do {
+			subtable = header->fsf_status_qual.halfword[counter++];
+			rule = header->fsf_status_qual.halfword[counter++];
+			switch (subtable) {
+			case FSF_SQ_CFDC_SUBTABLE_OS:
+			case FSF_SQ_CFDC_SUBTABLE_PORT_WWPN:
+			case FSF_SQ_CFDC_SUBTABLE_PORT_DID:
+			case FSF_SQ_CFDC_SUBTABLE_LUN:
+	       			ZFCP_LOG_NORMAL("Access denied (%s rule %d)\n",
+					zfcp_act_subtable_type[subtable], rule);
+				break;
+			}
+		} while (counter < 4);
+		debug_text_event(fsf_req->adapter->erp_dbf, 1, "fsf_s_access");
+		fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
+		break;
+
 	case FSF_PORT_BOXED:
 		ZFCP_LOG_FLAGS(2, "FSF_PORT_BOXED\n");
 		ZFCP_LOG_DEBUG("The remote port with WWPN 0x%Lx on the adapter "
@@ -2325,7 +2847,7 @@ zfcp_fsf_close_physical_port_handler(str
 
 	case FSF_ADAPTER_STATUS_AVAILABLE:
 		ZFCP_LOG_FLAGS(2, "FSF_ADAPTER_STATUS_AVAILABLE\n");
-		switch (fsf_req->qtcb->header.fsf_status_qual.word[0]) {
+		switch (header->fsf_status_qual.word[0]) {
 		case FSF_SQ_INVOKE_LINK_TEST_PROCEDURE:
 			ZFCP_LOG_FLAGS(2,
 				       "FSF_SQ_INVOKE_LINK_TEST_PROCEDURE\n");
@@ -2345,13 +2867,12 @@ zfcp_fsf_close_physical_port_handler(str
 		default:
 			ZFCP_LOG_NORMAL
 			    ("bug: Wrong status qualifier 0x%x arrived.\n",
-			     fsf_req->qtcb->header.fsf_status_qual.word[0]);
+			     header->fsf_status_qual.word[0]);
 			debug_text_event(fsf_req->adapter->erp_dbf, 0,
 					 "fsf_sq_inval:");
 			debug_exception(
 				fsf_req->adapter->erp_dbf, 0,
-				&fsf_req->qtcb->header.fsf_status_qual.word[0],
-				sizeof (u32));
+				&header->fsf_status_qual.word[0], sizeof (u32));
 			break;
 		}
 		break;
@@ -2375,11 +2896,10 @@ zfcp_fsf_close_physical_port_handler(str
 	default:
 		ZFCP_LOG_NORMAL("bug: An unknown FSF Status was presented "
 				"(debug info 0x%x)\n",
-				fsf_req->qtcb->header.fsf_status);
+				header->fsf_status);
 		debug_text_event(fsf_req->adapter->erp_dbf, 0, "fsf_s_inval:");
 		debug_exception(fsf_req->adapter->erp_dbf, 0,
-				&fsf_req->qtcb->header.fsf_status,
-				sizeof (u32));
+				&header->fsf_status, sizeof (u32));
 		break;
 	}
 
@@ -2403,15 +2923,16 @@ zfcp_fsf_close_physical_port_handler(str
 int
 zfcp_fsf_open_unit(struct zfcp_erp_action *erp_action)
 {
-	int retval = 0;
+	volatile struct qdio_buffer_element *sbale;
 	unsigned long lock_flags;
+	int retval = 0;
 
 	/* setup new FSF request */
 	retval = zfcp_fsf_req_create(erp_action->adapter,
 				     FSF_QTCB_OPEN_LUN,
-				     &lock_flags,
 				     ZFCP_WAIT_FOR_SBAL | ZFCP_REQ_AUTO_CLEANUP,
-				     &(erp_action->fsf_req));
+				     erp_action->adapter->pool.fsf_req_erp,
+				     &lock_flags, &(erp_action->fsf_req));
 	if (retval < 0) {
 		ZFCP_LOG_INFO("error: Out of resources. Could not create an "
 			      "open unit request for FCP-LUN 0x%Lx connected "
@@ -2423,6 +2944,11 @@ zfcp_fsf_open_unit(struct zfcp_erp_actio
 		goto out;
 	}
 
+	sbale = zfcp_qdio_sbale_req(erp_action->fsf_req,
+                                    erp_action->fsf_req->sbal_curr, 0);
+        sbale[0].flags |= SBAL_FLAGS0_TYPE_READ;
+        sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY;
+
 	erp_action->fsf_req->qtcb->header.port_handle =
 		erp_action->port->handle;
 	erp_action->fsf_req->qtcb->bottom.support.fcp_lun =
@@ -2430,6 +2956,8 @@ zfcp_fsf_open_unit(struct zfcp_erp_actio
 	atomic_set_mask(ZFCP_STATUS_COMMON_OPENING, &erp_action->unit->status);
 	erp_action->fsf_req->data.open_unit.unit = erp_action->unit;
 	erp_action->fsf_req->erp_action = erp_action;
+	erp_action->fsf_req->qtcb->bottom.support.option =
+		FSF_OPEN_LUN_SUPPRESS_BOXING;
 
 	/* start QDIO request for this FSF request */
 	retval = zfcp_fsf_req_send(erp_action->fsf_req, &erp_action->timer);
@@ -2467,8 +2995,11 @@ zfcp_fsf_open_unit_handler(struct zfcp_f
 {
 	int retval = -EINVAL;
 	struct zfcp_unit *unit;
+	struct fsf_qtcb_header *header;
+	u16 subtable, rule, counter;
 
 	unit = fsf_req->data.open_unit.unit;
+	header = &fsf_req->qtcb->header;
 
 	if (fsf_req->status & ZFCP_STATUS_FSFREQ_ERROR) {
 		/* don't change unit status in our bookkeeping */
@@ -2476,19 +3007,19 @@ zfcp_fsf_open_unit_handler(struct zfcp_f
 	}
 
 	/* evaluate FSF status in QTCB */
-	switch (fsf_req->qtcb->header.fsf_status) {
+	switch (header->fsf_status) {
 
 	case FSF_PORT_HANDLE_NOT_VALID:
 		ZFCP_LOG_FLAGS(1, "FSF_PORT_HANDLE_NOT_VALID\n");
 		ZFCP_LOG_INFO("Temporary port identifier (handle) 0x%x "
 			      "for the port with WWPN 0x%Lx connected to "
-			      "the adapter %s is"
+			      "the adapter %s is "
 			      "not valid. This may happen occasionally.\n",
 			      unit->port->handle,
 			      unit->port->wwpn, zfcp_get_busid_by_unit(unit));
 		ZFCP_LOG_DEBUG("status qualifier:\n");
 		ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_DEBUG,
-			      (char *) &fsf_req->qtcb->header.fsf_status_qual,
+			      (char *) &header->fsf_status_qual,
 			      sizeof (union fsf_status_qual));
 		debug_text_event(fsf_req->adapter->erp_dbf, 1, "fsf_s_ph_nv");
 		zfcp_erp_adapter_reopen(unit->port->adapter, 0);
@@ -2508,6 +3039,32 @@ zfcp_fsf_open_unit_handler(struct zfcp_f
 		fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
 		break;
 
+	case FSF_ACCESS_DENIED:
+		ZFCP_LOG_FLAGS(2, "FSF_ACCESS_DENIED\n");
+		ZFCP_LOG_NORMAL("Access denied, cannot open unit "
+				"with FCP-LUN 0x%Lx at the remote port with "
+				"WWPN 0x%Lx connected to the adapter %s\n",
+			unit->fcp_lun, unit->port->wwpn,
+			zfcp_get_busid_by_unit(unit));
+		counter = 0;
+		do {
+			subtable = header->fsf_status_qual.halfword[counter++];
+			rule = header->fsf_status_qual.halfword[counter++];
+			switch (subtable) {
+			case FSF_SQ_CFDC_SUBTABLE_OS:
+			case FSF_SQ_CFDC_SUBTABLE_PORT_WWPN:
+			case FSF_SQ_CFDC_SUBTABLE_PORT_DID:
+			case FSF_SQ_CFDC_SUBTABLE_LUN:
+				ZFCP_LOG_NORMAL("Access denied (%s rule %d)\n",
+					zfcp_act_subtable_type[subtable], rule);
+				break;
+			}
+		} while (counter < 4);
+		debug_text_event(fsf_req->adapter->erp_dbf, 1, "fsf_s_access");
+		zfcp_erp_unit_failed(unit);
+		fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
+		break;
+
 	case FSF_PORT_BOXED:
 		ZFCP_LOG_FLAGS(2, "FSF_PORT_BOXED\n");
 		ZFCP_LOG_DEBUG("The remote port "
@@ -2520,8 +3077,8 @@ zfcp_fsf_open_unit_handler(struct zfcp_f
 			ZFCP_STATUS_FSFREQ_RETRY;
 		break;
 
-	case FSF_LUN_IN_USE:
-		ZFCP_LOG_FLAGS(0, "FSF_LUN_IN_USE\n");
+	case FSF_LUN_SHARING_VIOLATION :
+		ZFCP_LOG_FLAGS(2, "FSF_LUN_SHARING_VIOLATION\n");
 		ZFCP_LOG_NORMAL("error: FCP-LUN 0x%Lx at "
 				"the remote port with WWPN 0x%Lx connected "
 				"to the adapter %s "
@@ -2530,12 +3087,23 @@ zfcp_fsf_open_unit_handler(struct zfcp_f
 				unit->fcp_lun,
 				unit->port->wwpn,
 				zfcp_get_busid_by_unit(unit));
+		subtable = header->fsf_status_qual.halfword[4];
+		rule = header->fsf_status_qual.halfword[5];
+		switch (subtable) {
+		case FSF_SQ_CFDC_SUBTABLE_OS:
+		case FSF_SQ_CFDC_SUBTABLE_PORT_WWPN:
+		case FSF_SQ_CFDC_SUBTABLE_PORT_DID:
+		case FSF_SQ_CFDC_SUBTABLE_LUN:
+			ZFCP_LOG_NORMAL("Access denied (%s rule %d)\n",
+				zfcp_act_subtable_type[subtable], rule);
+			break;
+		}
 		ZFCP_LOG_NORMAL("Additional sense data is presented:\n");
 		ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_NORMAL,
-			      (char *) &fsf_req->qtcb->header.fsf_status_qual,
+			      (char *) &header->fsf_status_qual,
 			      sizeof (union fsf_status_qual));
 		debug_text_event(fsf_req->adapter->erp_dbf, 2,
-				 "fsf_s_l_in_use");
+				 "fsf_s_l_sh_vio");
 		zfcp_erp_unit_failed(unit);
 		fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
 		break;
@@ -2558,7 +3126,7 @@ zfcp_fsf_open_unit_handler(struct zfcp_f
 
 	case FSF_ADAPTER_STATUS_AVAILABLE:
 		ZFCP_LOG_FLAGS(2, "FSF_ADAPTER_STATUS_AVAILABLE\n");
-		switch (fsf_req->qtcb->header.fsf_status_qual.word[0]) {
+		switch (header->fsf_status_qual.word[0]) {
 		case FSF_SQ_INVOKE_LINK_TEST_PROCEDURE:
 			ZFCP_LOG_FLAGS(2,
 				       "FSF_SQ_INVOKE_LINK_TEST_PROCEDURE\n");
@@ -2579,12 +3147,11 @@ zfcp_fsf_open_unit_handler(struct zfcp_f
 		default:
 			ZFCP_LOG_NORMAL
 			    ("bug: Wrong status qualifier 0x%x arrived.\n",
-			     fsf_req->qtcb->header.fsf_status_qual.word[0]);
+			     header->fsf_status_qual.word[0]);
 			debug_text_event(fsf_req->adapter->erp_dbf, 0,
 					 "fsf_sq_inval:");
-			debug_exception(
-				fsf_req->adapter->erp_dbf, 0,
-				&fsf_req->qtcb->header.fsf_status_qual.word[0],
+			debug_exception(fsf_req->adapter->erp_dbf, 0,
+					&header->fsf_status_qual.word[0],
 				sizeof (u32));
 		}
 		break;
@@ -2592,7 +3159,7 @@ zfcp_fsf_open_unit_handler(struct zfcp_f
 	case FSF_GOOD:
 		ZFCP_LOG_FLAGS(3, "FSF_GOOD\n");
 		/* save LUN handle assigned by FSF */
-		unit->handle = fsf_req->qtcb->header.lun_handle;
+		unit->handle = header->lun_handle;
 		ZFCP_LOG_TRACE("unit (FCP_LUN=0x%Lx) of remote port "
 			       "(WWPN=0x%Lx) via adapter (busid=%s) opened, "
 			       "port handle 0x%x \n",
@@ -2608,11 +3175,10 @@ zfcp_fsf_open_unit_handler(struct zfcp_f
 	default:
 		ZFCP_LOG_NORMAL("bug: An unknown FSF Status was presented "
 				"(debug info 0x%x)\n",
-				fsf_req->qtcb->header.fsf_status);
+				header->fsf_status);
 		debug_text_event(fsf_req->adapter->erp_dbf, 0, "fsf_s_inval:");
 		debug_exception(fsf_req->adapter->erp_dbf, 0,
-				&fsf_req->qtcb->header.fsf_status,
-				sizeof (u32));
+				&header->fsf_status, sizeof (u32));
 		break;
 	}
 
@@ -2637,15 +3203,16 @@ zfcp_fsf_open_unit_handler(struct zfcp_f
 int
 zfcp_fsf_close_unit(struct zfcp_erp_action *erp_action)
 {
-	int retval = 0;
+	volatile struct qdio_buffer_element *sbale;
 	unsigned long lock_flags;
+	int retval = 0;
 
 	/* setup new FSF request */
 	retval = zfcp_fsf_req_create(erp_action->adapter,
 				     FSF_QTCB_CLOSE_LUN,
-				     &lock_flags,
 				     ZFCP_WAIT_FOR_SBAL | ZFCP_REQ_AUTO_CLEANUP,
-				     &(erp_action->fsf_req));
+				     erp_action->adapter->pool.fsf_req_erp,
+				     &lock_flags, &(erp_action->fsf_req));
 	if (retval < 0) {
 		ZFCP_LOG_INFO("error: Out of resources. Could not create a "
 			      "close unit request for FCP-LUN 0x%Lx "
@@ -2657,6 +3224,11 @@ zfcp_fsf_close_unit(struct zfcp_erp_acti
 		goto out;
 	}
 
+	sbale = zfcp_qdio_sbale_req(erp_action->fsf_req,
+                                    erp_action->fsf_req->sbal_curr, 0);
+        sbale[0].flags |= SBAL_FLAGS0_TYPE_READ;
+        sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY;
+
 	erp_action->fsf_req->qtcb->header.port_handle =
 	    erp_action->port->handle;
 	erp_action->fsf_req->qtcb->header.lun_handle = erp_action->unit->handle;
@@ -2846,21 +3418,19 @@ zfcp_fsf_close_unit_handler(struct zfcp_
 int
 zfcp_fsf_send_fcp_command_task(struct zfcp_adapter *adapter,
 			       struct zfcp_unit *unit,
-			       Scsi_Cmnd * scsi_cmnd, int req_flags)
+			       struct scsi_cmnd * scsi_cmnd, int req_flags)
 {
 	struct zfcp_fsf_req *fsf_req = NULL;
 	struct fcp_cmnd_iu *fcp_cmnd_iu;
-	volatile struct qdio_buffer_element *buffere;
 	unsigned int sbtype;
 	unsigned long lock_flags;
 	int real_bytes = 0;
 	int retval = 0;
 
 	/* setup new FSF request */
-
-	retval = zfcp_fsf_req_create(adapter,
-				     FSF_QTCB_FCP_CMND,
-				     &lock_flags, req_flags, &(fsf_req));
+	retval = zfcp_fsf_req_create(adapter, FSF_QTCB_FCP_CMND, req_flags,
+				     adapter->pool.fsf_req_scsi,
+				     &lock_flags, &fsf_req);
 	if (unlikely(retval < 0)) {
 		ZFCP_LOG_DEBUG("error: Out of resources. Could not create an "
 			       "FCP command request for FCP-LUN 0x%Lx "
@@ -2912,8 +3482,8 @@ zfcp_fsf_send_fcp_command_task(struct zf
 	 *      data direction bits in FCP_CMND IU
 	 */
 	switch (scsi_cmnd->sc_data_direction) {
-	case SCSI_DATA_NONE:
-		ZFCP_LOG_FLAGS(3, "SCSI_DATA_NONE\n");
+	case DMA_NONE:
+		ZFCP_LOG_FLAGS(3, "DMA_NONE\n");
 		fsf_req->qtcb->bottom.io.data_direction = FSF_DATADIR_CMND;
 		/*
 		 * FIXME(qdio):
@@ -2922,20 +3492,20 @@ zfcp_fsf_send_fcp_command_task(struct zf
 		 */
 		sbtype = SBAL_FLAGS0_TYPE_READ;
 		break;
-	case SCSI_DATA_READ:
-		ZFCP_LOG_FLAGS(3, "SCSI_DATA_READ\n");
+	case DMA_FROM_DEVICE:
+		ZFCP_LOG_FLAGS(3, "DMA_FROM_DEVICE\n");
 		fsf_req->qtcb->bottom.io.data_direction = FSF_DATADIR_READ;
 		sbtype = SBAL_FLAGS0_TYPE_READ;
 		fcp_cmnd_iu->rddata = 1;
 		break;
-	case SCSI_DATA_WRITE:
-		ZFCP_LOG_FLAGS(3, "SCSI_DATA_WRITE\n");
+	case DMA_TO_DEVICE:
+		ZFCP_LOG_FLAGS(3, "DMA_TO_DEVICE\n");
 		fsf_req->qtcb->bottom.io.data_direction = FSF_DATADIR_WRITE;
 		sbtype = SBAL_FLAGS0_TYPE_WRITE;
 		fcp_cmnd_iu->wddata = 1;
 		break;
-	case SCSI_DATA_UNKNOWN:
-		ZFCP_LOG_FLAGS(0, "SCSI_DATA_UNKNOWN not supported\n");
+	case DMA_BIDIRECTIONAL:
+		ZFCP_LOG_FLAGS(0, "DMA_BIDIRECTIONAL not supported\n");
 	default:
 		/*
 		 * dummy, catch this condition earlier
@@ -2943,9 +3513,6 @@ zfcp_fsf_send_fcp_command_task(struct zf
 		 */
 		goto failed_scsi_cmnd;
 	}
-	buffere =
-	    &(adapter->request_queue.buffer[fsf_req->sbal_index]->element[0]);
-	buffere->flags |= sbtype;
 
 	/* set FC service class in QTCB (3 per default) */
 	fsf_req->qtcb->bottom.io.service_class = adapter->fc_service_class;
@@ -2984,29 +3551,24 @@ zfcp_fsf_send_fcp_command_task(struct zf
 		fcp_cmnd_iu->add_fcp_cdb_length + sizeof (fcp_dl_t);
 
 	/* generate SBALEs from data buffer */
-	real_bytes = zfcp_create_sbals_from_sg(fsf_req,
-					       scsi_cmnd,
-					       sbtype,
-					       0, ZFCP_MAX_SBALS_PER_REQ);
-	/* Note: >= and not = because the combined scatter-gather entries
-	 * may be larger than request_bufflen according to the mailing list
-	 */
-	if (likely(real_bytes >= scsi_cmnd->request_bufflen)) {
-		ZFCP_LOG_TRACE("Data fits\n");
-	} else if (likely(real_bytes == 0)) {
-		ZFCP_LOG_DEBUG("Data did not fit into available buffer(s), "
+	real_bytes = zfcp_qdio_sbals_from_scsicmnd(fsf_req, sbtype, scsi_cmnd);
+	if (unlikely(real_bytes < 0)) {
+		if (fsf_req->sbal_number < ZFCP_MAX_SBALS_PER_REQ) {
+			ZFCP_LOG_DEBUG(
+				"Data did not fit into available buffer(s), "
 			       "waiting for more...\n");
 		retval = -EIO;
-		goto no_fit;
 	} else {
 		ZFCP_LOG_NORMAL("error: No truncation implemented but "
-				"required. Shutting down unit (busid=%s, "
-				"WWPN=0x%16.16Lx, FCP_LUN=0x%16.16Lx)\n",
+					"required. Shutting down unit "
+					"(busid=%s, WWPN=0x%16.16Lx, "
+					"FCP_LUN=0x%16.16Lx)\n",
 				zfcp_get_busid_by_unit(unit),
 				unit->port->wwpn,
 				unit->fcp_lun);
 		zfcp_erp_unit_shutdown(unit, 0);
 		retval = -EINVAL;
+		}
 		goto no_fit;
 	}
 
@@ -3077,11 +3639,12 @@ zfcp_fsf_send_fcp_command_task_managemen
 	int retval = 0;
 	struct fcp_cmnd_iu *fcp_cmnd_iu;
 	unsigned long lock_flags;
-	volatile struct qdio_buffer_element *buffere;
+	volatile struct qdio_buffer_element *sbale;
 
 	/* setup new FSF request */
-	retval = zfcp_fsf_req_create(adapter, FSF_QTCB_FCP_CMND,
-				     &lock_flags, req_flags, &(fsf_req));
+	retval = zfcp_fsf_req_create(adapter, FSF_QTCB_FCP_CMND, req_flags,
+				     adapter->pool.fsf_req_scsi,
+				     &lock_flags, &fsf_req);
 	if (retval < 0) {
 		ZFCP_LOG_INFO("error: Out of resources. Could not create an "
 			      "FCP command (task management) request for "
@@ -3113,10 +3676,9 @@ zfcp_fsf_send_fcp_command_task_managemen
 	fsf_req->qtcb->bottom.io.fcp_cmnd_length =
 		sizeof (struct fcp_cmnd_iu) + sizeof (fcp_dl_t);
 
-	buffere =
-	    &(adapter->request_queue.buffer[fsf_req->sbal_index]->element[0]);
-	buffere[0].flags |= SBAL_FLAGS0_TYPE_WRITE;
-	buffere[1].flags |= SBAL_FLAGS_LAST_ENTRY;
+	sbale = zfcp_qdio_sbale_req(fsf_req, fsf_req->sbal_curr, 0);
+	sbale[0].flags |= SBAL_FLAGS0_TYPE_WRITE;
+	sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY;
 
 	/* set FCP related fields in FCP_CMND IU in QTCB */
 	fcp_cmnd_iu = (struct fcp_cmnd_iu *)
@@ -3164,6 +3726,10 @@ zfcp_fsf_send_fcp_command_handler(struct
 {
 	int retval = -EINVAL;
 	struct zfcp_unit *unit;
+	struct fsf_qtcb_header *header;
+	u16 subtable, rule, counter;
+
+	header = &fsf_req->qtcb->header;
 
 	if (unlikely(fsf_req->status & ZFCP_STATUS_FSFREQ_TASK_MANAGEMENT))
 		unit = fsf_req->data.send_fcp_command_task_management.unit;
@@ -3176,7 +3742,7 @@ zfcp_fsf_send_fcp_command_handler(struct
 	}
 
 	/* evaluate FSF status in QTCB */
-	switch (fsf_req->qtcb->header.fsf_status) {
+	switch (header->fsf_status) {
 
 	case FSF_PORT_HANDLE_NOT_VALID:
 		ZFCP_LOG_FLAGS(1, "FSF_PORT_HANDLE_NOT_VALID\n");
@@ -3186,7 +3752,7 @@ zfcp_fsf_send_fcp_command_handler(struct
 			      unit->port->handle,
 			      unit->port->wwpn, zfcp_get_busid_by_unit(unit));
 		ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_DEBUG,
-			      (char *) &fsf_req->qtcb->header.fsf_status_qual,
+			      (char *) &header->fsf_status_qual,
 			      sizeof (union fsf_status_qual));
 		debug_text_event(fsf_req->adapter->erp_dbf, 1,
 				 "fsf_s_phand_nv");
@@ -3207,7 +3773,7 @@ zfcp_fsf_send_fcp_command_handler(struct
 			      zfcp_get_busid_by_unit(unit));
 		ZFCP_LOG_NORMAL("Status qualifier data:\n");
 		ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_NORMAL,
-			      (char *) &fsf_req->qtcb->header.fsf_status_qual,
+			      (char *) &header->fsf_status_qual,
 			      sizeof (union fsf_status_qual));
 		debug_text_event(fsf_req->adapter->erp_dbf, 1,
 				 "fsf_s_uhand_nv");
@@ -3229,14 +3795,14 @@ zfcp_fsf_send_fcp_command_handler(struct
 				zfcp_get_busid_by_unit(unit));
 		ZFCP_LOG_NORMAL("status qualifier:\n");
 		ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_NORMAL,
-			      (char *) &fsf_req->qtcb->header.fsf_status_qual,
+			      (char *) &header->fsf_status_qual,
 			      sizeof (union fsf_status_qual));
 		debug_text_event(fsf_req->adapter->erp_dbf, 1,
 				 "fsf_s_hand_mis");
 		zfcp_erp_adapter_reopen(unit->port->adapter, 0);
 		zfcp_cmd_dbf_event_fsf("handmism",
 				       fsf_req,
-				       &fsf_req->qtcb->header.fsf_status_qual,
+				       &header->fsf_status_qual,
 				       sizeof (union fsf_status_qual));
 		fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
 		break;
@@ -3261,7 +3827,7 @@ zfcp_fsf_send_fcp_command_handler(struct
 		zfcp_erp_adapter_shutdown(unit->port->adapter, 0);
 		zfcp_cmd_dbf_event_fsf("unsclass",
 				       fsf_req,
-				       &fsf_req->qtcb->header.fsf_status_qual,
+				       &header->fsf_status_qual,
 				       sizeof (union fsf_status_qual));
 		fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
 		break;
@@ -3278,18 +3844,43 @@ zfcp_fsf_send_fcp_command_handler(struct
 				unit->handle);
 		ZFCP_LOG_DEBUG("status qualifier:\n");
 		ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_DEBUG,
-			      (char *) &fsf_req->qtcb->header.fsf_status_qual,
+			      (char *) &header->fsf_status_qual,
 			      sizeof (union fsf_status_qual));
 		debug_text_event(fsf_req->adapter->erp_dbf, 1,
 				 "fsf_s_fcp_lun_nv");
 		zfcp_erp_port_reopen(unit->port, 0);
 		zfcp_cmd_dbf_event_fsf("fluninv",
 				       fsf_req,
-				       &fsf_req->qtcb->header.fsf_status_qual,
+				       &header->fsf_status_qual,
 				       sizeof (union fsf_status_qual));
 		fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
 		break;
 
+	case FSF_ACCESS_DENIED:
+		ZFCP_LOG_FLAGS(2, "FSF_ACCESS_DENIED\n");
+		ZFCP_LOG_NORMAL("Access denied, cannot send FCP "
+				"command to the unit with FCP-LUN 0x%Lx at the "
+				"remote port with WWPN 0x%Lx connected to the "
+				"adapter %s\n",	unit->fcp_lun, unit->port->wwpn,
+			zfcp_get_busid_by_unit(unit));
+		counter = 0;
+		do {
+			subtable = header->fsf_status_qual.halfword[counter++];
+			rule = header->fsf_status_qual.halfword[counter++];
+			switch (subtable) {
+			case FSF_SQ_CFDC_SUBTABLE_OS:
+			case FSF_SQ_CFDC_SUBTABLE_PORT_WWPN:
+			case FSF_SQ_CFDC_SUBTABLE_PORT_DID:
+			case FSF_SQ_CFDC_SUBTABLE_LUN:
+				ZFCP_LOG_NORMAL("Access denied (%s rule %d)\n",
+					zfcp_act_subtable_type[subtable], rule);
+				break;
+			}
+		} while (counter < 4);
+		debug_text_event(fsf_req->adapter->erp_dbf, 1, "fsf_s_access");
+		fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
+		break;
+
 	case FSF_DIRECTION_INDICATOR_NOT_VALID:
 		ZFCP_LOG_FLAGS(0, "FSF_DIRECTION_INDICATOR_NOT_VALID\n");
 		ZFCP_LOG_INFO("bug: Invalid data direction given for the unit "
@@ -3306,7 +3897,7 @@ zfcp_fsf_send_fcp_command_handler(struct
 		zfcp_erp_adapter_shutdown(unit->port->adapter, 0);
 		zfcp_cmd_dbf_event_fsf("dirinv",
 				       fsf_req,
-				       &fsf_req->qtcb->header.fsf_status_qual,
+				       &header->fsf_status_qual,
 				       sizeof (union fsf_status_qual));
 		fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
 		break;
@@ -3326,7 +3917,7 @@ zfcp_fsf_send_fcp_command_handler(struct
 		zfcp_erp_adapter_shutdown(unit->port->adapter, 0);
 		zfcp_cmd_dbf_event_fsf("idleninv",
 				       fsf_req,
-				       &fsf_req->qtcb->header.fsf_status_qual,
+				       &header->fsf_status_qual,
 				       sizeof (union fsf_status_qual));
 		fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
 		break;
@@ -3346,7 +3937,7 @@ zfcp_fsf_send_fcp_command_handler(struct
 				 "fsf_s_out_dl_nv");
 		zfcp_erp_adapter_shutdown(unit->port->adapter, 0);
 		zfcp_cmd_dbf_event_fsf("odleninv", fsf_req,
-				       &fsf_req->qtcb->header.fsf_status_qual,
+				       &header->fsf_status_qual,
 				       sizeof (union fsf_status_qual));
 		fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
 		break;
@@ -3367,7 +3958,7 @@ zfcp_fsf_send_fcp_command_handler(struct
 		zfcp_erp_adapter_shutdown(unit->port->adapter, 0);
 		zfcp_cmd_dbf_event_fsf("cleninv",
 				       fsf_req,
-				       &fsf_req->qtcb->header.fsf_status_qual,
+				       &header->fsf_status_qual,
 				       sizeof (union fsf_status_qual));
 		fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
 		break;
@@ -3381,15 +3972,32 @@ zfcp_fsf_send_fcp_command_handler(struct
 		debug_text_event(fsf_req->adapter->erp_dbf, 2, "fsf_s_pboxed");
 		zfcp_erp_port_reopen(unit->port, 0);
 		zfcp_cmd_dbf_event_fsf("portbox", fsf_req,
-				       &fsf_req->qtcb->header.fsf_status_qual,
+				       &header->fsf_status_qual,
 				       sizeof (union fsf_status_qual));
 		fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR |
 			ZFCP_STATUS_FSFREQ_RETRY;
 		break;
 
+	case FSF_LUN_BOXED:
+		ZFCP_LOG_FLAGS(0, "FSF_LUN_BOXED\n");
+		ZFCP_LOG_NORMAL(
+			"The remote unit with FCP-LUN 0x%Lx "
+			"at the remote port with WWPN 0x%Lx "
+			"connected to the adapter %s needs to be reopened\n",
+			unit->fcp_lun, unit->port->wwpn,
+			zfcp_get_busid_by_unit(unit));
+		debug_text_event(fsf_req->adapter->erp_dbf, 1, "fsf_s_lboxed");
+		zfcp_erp_unit_reopen(unit, 0);
+		zfcp_cmd_dbf_event_fsf("unitbox", fsf_req,
+			&header->fsf_status_qual,
+			sizeof(union fsf_status_qual));
+		fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR
+			| ZFCP_STATUS_FSFREQ_RETRY;
+		break;
+
 	case FSF_ADAPTER_STATUS_AVAILABLE:
 		ZFCP_LOG_FLAGS(2, "FSF_ADAPTER_STATUS_AVAILABLE\n");
-		switch (fsf_req->qtcb->header.fsf_status_qual.word[0]) {
+		switch (header->fsf_status_qual.word[0]) {
 		case FSF_SQ_INVOKE_LINK_TEST_PROCEDURE:
 			ZFCP_LOG_FLAGS(2,
 				       "FSF_SQ_INVOKE_LINK_TEST_PROCEDURE\n");
@@ -3400,7 +4008,7 @@ zfcp_fsf_send_fcp_command_handler(struct
 			zfcp_cmd_dbf_event_fsf(
 				"sqltest",
 				fsf_req,
-				&fsf_req->qtcb->header.fsf_status_qual,
+				&header->fsf_status_qual,
 				sizeof (union fsf_status_qual));
 			fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
 			break;
@@ -3414,7 +4022,7 @@ zfcp_fsf_send_fcp_command_handler(struct
 			zfcp_cmd_dbf_event_fsf(
 				"sqdeperp",
 				fsf_req,
-				&fsf_req->qtcb->header.fsf_status_qual,
+				&header->fsf_status_qual,
 				sizeof (union fsf_status_qual));
 			fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
 			break;
@@ -3422,14 +4030,12 @@ zfcp_fsf_send_fcp_command_handler(struct
 			/* FIXME: shall we consider this a successful transfer? */
 			ZFCP_LOG_NORMAL
 			    ("bug: Wrong status qualifier 0x%x arrived.\n",
-			     fsf_req->qtcb->header.fsf_status_qual.word[0]);
+			     header->fsf_status_qual.word[0]);
 			debug_text_event(fsf_req->adapter->erp_dbf, 0,
 					 "fsf_sq_inval:");
-			debug_exception(
-				fsf_req->adapter->erp_dbf,
-				0,
-				&fsf_req->qtcb->header.fsf_status_qual.word[0],
-				sizeof (u32));
+			debug_exception(fsf_req->adapter->erp_dbf, 0,
+					&header->fsf_status_qual.word[0],
+					sizeof(u32));
 			break;
 		}
 		break;
@@ -3445,8 +4051,7 @@ zfcp_fsf_send_fcp_command_handler(struct
 	default:
 		debug_text_event(fsf_req->adapter->erp_dbf, 0, "fsf_s_inval:");
 		debug_exception(fsf_req->adapter->erp_dbf, 0,
-				&fsf_req->qtcb->header.fsf_status,
-				sizeof (u32));
+				&header->fsf_status, sizeof(u32));
 		break;
 	}
 
@@ -3471,8 +4076,7 @@ static int
 zfcp_fsf_send_fcp_command_task_handler(struct zfcp_fsf_req *fsf_req)
 {
 	int retval = 0;
-
-	Scsi_Cmnd *scpnt;
+	struct scsi_cmnd *scpnt;
 	struct fcp_rsp_iu *fcp_rsp_iu = (struct fcp_rsp_iu *)
 	    &(fsf_req->qtcb->bottom.io.fcp_rsp);
 	struct fcp_cmnd_iu *fcp_cmnd_iu = (struct fcp_cmnd_iu *)
@@ -3874,6 +4478,310 @@ zfcp_fsf_send_fcp_command_task_managemen
 	return retval;
 }
 
+
+/*
+ * function:    zfcp_fsf_control_file
+ *
+ * purpose:     Initiator of the control file upload/download FSF requests
+ *
+ * returns:     0           - FSF request is successfuly created and queued
+ *              -EOPNOTSUPP - The FCP adapter does not have Control File support
+ *              -EINVAL     - Invalid direction specified
+ *              -ENOMEM     - Insufficient memory
+ *              -EPERM      - Cannot create FSF request or or place it in QDIO queue
+ */
+int
+zfcp_fsf_control_file(struct zfcp_adapter *adapter,
+                      struct zfcp_fsf_req **fsf_req_ptr,
+                      u32 fsf_command,
+                      u32 option,
+                      struct zfcp_sg_list *sg_list)
+{
+	struct zfcp_fsf_req *fsf_req;
+	struct fsf_qtcb_bottom_support *bottom;
+	volatile struct qdio_buffer_element *sbale;
+	unsigned long lock_flags;
+	int req_flags = 0;
+	int direction;
+	int retval = 0;
+
+#if 0
+	if (!(adapter->features & FSF_FEATURE_CFDC)) {
+		ZFCP_LOG_INFO(
+			"Adapter %s does not support control file\n",
+			zfcp_get_busid_by_adapter(adapter));
+		retval = -EOPNOTSUPP;
+		goto no_act_support;
+	}
+#endif
+
+	switch (fsf_command) {
+
+	case FSF_QTCB_DOWNLOAD_CONTROL_FILE:
+		direction = SBAL_FLAGS0_TYPE_WRITE;
+		if ((option != FSF_CFDC_OPTION_FULL_ACCESS) &&
+		    (option != FSF_CFDC_OPTION_RESTRICTED_ACCESS))
+			req_flags = ZFCP_WAIT_FOR_SBAL;
+		break;
+
+	case FSF_QTCB_UPLOAD_CONTROL_FILE:
+		direction = SBAL_FLAGS0_TYPE_READ;
+		break;
+
+	default:
+		ZFCP_LOG_INFO("Invalid FSF command code 0x%08x\n", fsf_command);
+		goto invalid_command;
+	}
+
+	retval = zfcp_fsf_req_create(adapter, fsf_command, req_flags,
+				     NULL, &lock_flags, &fsf_req);
+	if (retval < 0) {
+		ZFCP_LOG_INFO("error: Could not create FSF request for the "
+			      "adapter %s\n",
+			zfcp_get_busid_by_adapter(adapter));
+		retval = -EPERM;
+		goto out;
+	}
+
+	sbale = zfcp_qdio_sbale_req(fsf_req, fsf_req->sbal_curr, 0);
+	sbale[0].flags |= direction;
+
+	bottom = &fsf_req->qtcb->bottom.support;
+	bottom->operation_subtype = FSF_CFDC_OPERATION_SUBTYPE;
+	bottom->option = option;
+
+	if (sg_list->count > 0) {
+		int bytes;
+
+		bytes = zfcp_qdio_sbals_from_sg(fsf_req, direction,
+						sg_list->sg, sg_list->count,
+						ZFCP_MAX_SBALS_PER_REQ);
+                if (bytes != ZFCP_CFDC_MAX_CONTROL_FILE_SIZE) {
+			ZFCP_LOG_INFO(
+				"error: Could not create sufficient number of "
+				"SBALS for an FSF request to the adapter %s\n",
+				zfcp_get_busid_by_adapter(adapter));
+			retval = -ENOMEM;
+			goto sbals_failed;
+		}
+	} else {
+		sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY;
+	}
+
+	retval = zfcp_fsf_req_send(fsf_req, NULL);
+	if (retval < 0) {
+		ZFCP_LOG_INFO(
+			"error: Could not send FSF request to the adapter %s\n",
+			zfcp_get_busid_by_adapter(adapter));
+		retval = -EPERM;
+		goto queue_failed;
+	}
+
+	ZFCP_LOG_NORMAL(
+		"Control file %s FSF request has been sent to the adapter %s\n",
+		fsf_command == FSF_QTCB_DOWNLOAD_CONTROL_FILE ?
+			"download" : "upload",
+		zfcp_get_busid_by_adapter(adapter));
+
+	*fsf_req_ptr = fsf_req;
+
+	goto out;
+
+sbals_failed:
+queue_failed:
+	zfcp_fsf_req_free(fsf_req);
+
+out:
+	write_unlock_irqrestore(&adapter->request_queue.queue_lock, lock_flags);
+
+invalid_command:
+	return retval;
+}
+
+
+/*
+ * function:    zfcp_fsf_control_file_handler
+ *
+ * purpose:     Handler of the control file upload/download FSF requests
+ *
+ * returns:     0       - FSF request successfuly processed
+ *              -EAGAIN - Operation has to be repeated because of a temporary problem
+ *              -EACCES - There is no permission to execute an operation
+ *              -EPERM  - The control file is not in a right format
+ *              -EIO    - There is a problem with the FCP adapter
+ *              -EINVAL - Invalid operation
+ *              -EFAULT - User space memory I/O operation fault
+ */
+static int
+zfcp_fsf_control_file_handler(struct zfcp_fsf_req *fsf_req)
+{
+	struct zfcp_adapter *adapter = fsf_req->adapter;
+	struct fsf_qtcb_header *header = &fsf_req->qtcb->header;
+	struct fsf_qtcb_bottom_support *bottom = &fsf_req->qtcb->bottom.support;
+	int retval = 0;
+
+	if (fsf_req->status & ZFCP_STATUS_FSFREQ_ERROR) {
+		retval = -EINVAL;
+		goto skip_fsfstatus;
+	}
+
+	switch (header->fsf_status) {
+
+	case FSF_GOOD:
+		ZFCP_LOG_FLAGS(2, "FSF_GOOD\n");
+		ZFCP_LOG_NORMAL(
+			"The FSF request has been successfully completed "
+			"on the adapter %s\n",
+			zfcp_get_busid_by_adapter(adapter));
+		break;
+
+	case FSF_OPERATION_PARTIALLY_SUCCESSFUL:
+		ZFCP_LOG_FLAGS(2, "FSF_OPERATION_PARTIALLY_SUCCESSFUL\n");
+		if (bottom->operation_subtype == FSF_CFDC_OPERATION_SUBTYPE) {
+			switch (header->fsf_status_qual.word[0]) {
+
+			case FSF_SQ_CFDC_COULD_NOT_HARDEN_ON_SE:
+				ZFCP_LOG_NORMAL(
+					"CFDC of the adapter %s could not "
+					"be saved on the SE\n",
+					zfcp_get_busid_by_adapter(adapter));
+				break;
+
+			case FSF_SQ_CFDC_COULD_NOT_HARDEN_ON_SE2:
+				ZFCP_LOG_NORMAL(
+					"CFDC of the adapter %s could not "
+					"be copied to the secondary SE\n",
+					zfcp_get_busid_by_adapter(adapter));
+				break;
+
+			default:
+				ZFCP_LOG_NORMAL(
+					"CFDC could not be hardened "
+					"on the adapter %s\n",
+					zfcp_get_busid_by_adapter(adapter));
+			}
+		}
+		fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
+		retval = -EAGAIN;
+		break;
+
+	case FSF_AUTHORIZATION_FAILURE:
+		ZFCP_LOG_FLAGS(2, "FSF_AUTHORIZATION_FAILURE\n");
+		ZFCP_LOG_NORMAL(
+			"Adapter %s does not accept privileged commands\n",
+			zfcp_get_busid_by_adapter(adapter));
+		fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
+		retval = -EACCES;
+		break;
+
+	case FSF_CFDC_ERROR_DETECTED:
+		ZFCP_LOG_FLAGS(2, "FSF_CFDC_ERROR_DETECTED\n");
+		ZFCP_LOG_NORMAL(
+			"Error at position %d in the CFDC, "
+			"CFDC is discarded by the adapter %s\n",
+			header->fsf_status_qual.word[0],
+			zfcp_get_busid_by_adapter(adapter));
+		fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
+		retval = -EPERM;
+		break;
+
+	case FSF_CONTROL_FILE_UPDATE_ERROR:
+		ZFCP_LOG_FLAGS(2, "FSF_CONTROL_FILE_UPDATE_ERROR\n");
+		ZFCP_LOG_NORMAL(
+			"Adapter %s cannot harden the control file, "
+			"file is discarded\n",
+			zfcp_get_busid_by_adapter(adapter));
+		fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
+		retval = -EIO;
+		break;
+
+	case FSF_CONTROL_FILE_TOO_LARGE:
+		ZFCP_LOG_FLAGS(2, "FSF_CONTROL_FILE_TOO_LARGE\n");
+		ZFCP_LOG_NORMAL(
+			"Control file is too large, file is discarded "
+			"by the adapter %s\n",
+			zfcp_get_busid_by_adapter(adapter));
+		fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
+		retval = -EIO;
+		break;
+
+	case FSF_ACCESS_CONFLICT_DETECTED:
+		ZFCP_LOG_FLAGS(2, "FSF_ACCESS_CONFLICT_DETECTED\n");
+		if (bottom->operation_subtype == FSF_CFDC_OPERATION_SUBTYPE)
+			ZFCP_LOG_NORMAL(
+				"CFDC has been discarded by the adapter %s, "
+				"because activation would impact "
+				"%d active connection(s)\n",
+				zfcp_get_busid_by_adapter(adapter),
+				header->fsf_status_qual.word[0]);
+		fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
+		retval = -EIO;
+		break;
+
+	case FSF_CONFLICTS_OVERRULED:
+		ZFCP_LOG_FLAGS(2, "FSF_CONFLICTS_OVERRULED\n");
+		if (bottom->operation_subtype == FSF_CFDC_OPERATION_SUBTYPE)
+			ZFCP_LOG_NORMAL(
+				"CFDC has been activated on the adapter %s, "
+				"but activation has impacted "
+				"%d active connection(s)\n",
+				zfcp_get_busid_by_adapter(adapter),
+				header->fsf_status_qual.word[0]);
+		fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
+		retval = -EIO;
+		break;
+
+	case FSF_UNKNOWN_COMMAND:
+		ZFCP_LOG_FLAGS(2, "FSF_UNKNOWN_COMMAND\n");
+		ZFCP_LOG_NORMAL(
+			"FSF command 0x%x is not supported by the adapter %s\n",
+			fsf_req->fsf_command,
+			zfcp_get_busid_by_adapter(adapter));
+		fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
+		retval = -EINVAL;
+		break;
+
+	case FSF_UNKNOWN_OP_SUBTYPE:
+		ZFCP_LOG_FLAGS(2, "FSF_UNKNOWN_OP_SUBTYPE\n");
+		ZFCP_LOG_NORMAL(
+			"Invalid operation subtype 0x%x has been specified "
+			"in QTCB bottom sent to the adapter %s\n",
+			bottom->operation_subtype,
+			zfcp_get_busid_by_adapter(adapter));
+		fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
+		retval = -EINVAL;
+		break;
+
+	case FSF_INVALID_COMMAND_OPTION:
+		ZFCP_LOG_FLAGS(2, "FSF_INVALID_COMMAND_OPTION\n");
+		ZFCP_LOG_NORMAL(
+			"Invalid option 0x%x has been specified "
+			"in QTCB bottom sent to the adapter %s\n",
+			bottom->option,
+			zfcp_get_busid_by_adapter(adapter));
+		fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
+		retval = -EINVAL;
+		break;
+
+	default:
+		ZFCP_LOG_NORMAL(
+			"bug: An unknown/unexpected FSF status 0x%08x "
+			"was presented on the adapter %s\n",
+			header->fsf_status,
+			zfcp_get_busid_by_adapter(adapter));
+		debug_text_event(fsf_req->adapter->erp_dbf, 0, "fsf_sq_inval");
+		debug_exception(fsf_req->adapter->erp_dbf, 0,
+			&header->fsf_status_qual.word[0], sizeof(u32));
+		fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
+		retval = -EINVAL;
+		break;
+	}
+
+skip_fsfstatus:
+	return retval;
+}
+
+
 /*
  * function:    zfcp_fsf_req_wait_and_cleanup
  *
@@ -3931,6 +4839,54 @@ zfcp_fsf_req_create_sbal_check(unsigned 
 }
 
 /*
+ * set qtcb pointer in fsf_req and initialize QTCB
+ */
+static inline void
+zfcp_fsf_req_qtcb_init(struct zfcp_fsf_req *fsf_req, u32 fsf_cmd)
+{
+	if (likely(fsf_req->qtcb != NULL)) {
+		fsf_req->qtcb->prefix.req_id = (unsigned long)fsf_req;
+		fsf_req->qtcb->prefix.ulp_info = ZFCP_ULP_INFO_VERSION;
+		fsf_req->qtcb->prefix.qtcb_type = fsf_qtcb_type[fsf_cmd];
+		fsf_req->qtcb->prefix.qtcb_version = ZFCP_QTCB_VERSION;
+		fsf_req->qtcb->header.req_handle = (unsigned long)fsf_req;
+		fsf_req->qtcb->header.fsf_command = fsf_cmd;
+	}
+}
+
+/**
+ * zfcp_fsf_req_sbal_get - try to get one SBAL in the request queue
+ * @adapter: adapter for which request queue is examined
+ * @req_flags: flags indicating whether to wait for needed SBAL or not
+ * @lock_flags: lock_flags is queue_lock is taken
+ *
+ * locking: on success the queue_lock for the request queue of the adapter
+ *	is held
+ */
+static int
+zfcp_fsf_req_sbal_get(struct zfcp_adapter *adapter, int req_flags,
+		      unsigned long *lock_flags)
+{
+        int condition;
+        unsigned long timeout = ZFCP_SBAL_TIMEOUT;
+        struct zfcp_qdio_queue *req_queue = &adapter->request_queue;
+
+        if (unlikely(req_flags & ZFCP_WAIT_FOR_SBAL)) {
+                ZFCP_WAIT_EVENT_TIMEOUT(adapter->request_wq, timeout,
+                                        (condition =
+                                         (zfcp_fsf_req_create_sbal_check)
+                                         (lock_flags, req_queue, 1)));
+                if (!condition) {
+                        return -EIO;
+		}
+        } else if (!zfcp_fsf_req_create_sbal_check(lock_flags, req_queue, 1)) {
+                return -EIO;
+	}
+
+        return 0;
+}
+
+/*
  * function:    zfcp_fsf_req_create
  *
  * purpose:	create an FSF request at the specified adapter and
@@ -3947,149 +4903,65 @@ zfcp_fsf_req_create_sbal_check(unsigned 
  *		but is held on completion (write, irqsave)
  */
 int
-zfcp_fsf_req_create(struct zfcp_adapter *adapter,
-		    u32 fsf_cmd,
-		    unsigned long *lock_flags,
-		    int req_flags,
+zfcp_fsf_req_create(struct zfcp_adapter *adapter, u32 fsf_cmd, int req_flags,
+		    mempool_t *pool, unsigned long *lock_flags,
 		    struct zfcp_fsf_req **fsf_req_p)
 {
+	volatile struct qdio_buffer_element *sbale;
 	struct zfcp_fsf_req *fsf_req = NULL;
-	int retval = 0;
+	int ret = 0;
 	struct zfcp_qdio_queue *req_queue = &adapter->request_queue;
-	volatile struct qdio_buffer_element *buffere;
-	unsigned long timeout;
-	int condition;
 
 	/* allocate new FSF request */
-	fsf_req = zfcp_fsf_req_alloc(adapter, fsf_cmd, GFP_ATOMIC);
-	if (unlikely(!fsf_req)) {
+	fsf_req = zfcp_fsf_req_alloc(pool, req_flags);
+	if (unlikely(NULL == fsf_req)) {
 		ZFCP_LOG_DEBUG("error: Could not put an FSF request into"
 			       "the outbound (send) queue.\n");
-		retval = -ENOMEM;
+		ret = -ENOMEM;
 		goto failed_fsf_req;
 	}
-	/* save pointer to "parent" adapter */
-	fsf_req->adapter = adapter;
+
+        zfcp_fsf_req_qtcb_init(fsf_req, fsf_cmd);
 
 	/* initialize waitqueue which may be used to wait on 
 	   this request completion */
 	init_waitqueue_head(&fsf_req->completion_wq);
 
+        ret = zfcp_fsf_req_sbal_get(adapter, req_flags, lock_flags);
+        if(ret < 0) {
+                goto failed_sbals;
+	}
+
+
 	/* set magics */
 	fsf_req->common_magic = ZFCP_MAGIC;
 	fsf_req->specific_magic = ZFCP_MAGIC_FSFREQ;
 
+	fsf_req->adapter = adapter;	/* pointer to "parent" adapter */
 	fsf_req->fsf_command = fsf_cmd;
-	if (likely(req_flags & ZFCP_REQ_AUTO_CLEANUP))
-		fsf_req->status |= ZFCP_STATUS_FSFREQ_CLEANUP;
+	fsf_req->sbal_number = 1;
+	fsf_req->sbal_first = req_queue->free_index;
+	fsf_req->sbal_curr = req_queue->free_index;
+        fsf_req->sbale_curr = 1;
 
-	/* initialize QTCB */
-	if (likely(fsf_cmd != FSF_QTCB_UNSOLICITED_STATUS)) {
-		ZFCP_LOG_TRACE("fsf_req->qtcb=0x%lx\n",
-			       (unsigned long) fsf_req->qtcb);
-		fsf_req->qtcb->prefix.req_id = (unsigned long) fsf_req;
-		fsf_req->qtcb->prefix.ulp_info = ZFCP_ULP_INFO_VERSION;
-		fsf_req->qtcb->prefix.qtcb_type = fsf_qtcb_type[fsf_cmd];
-		fsf_req->qtcb->prefix.qtcb_version = ZFCP_QTCB_VERSION;
-		fsf_req->qtcb->header.req_handle = (unsigned long) fsf_req;
-		fsf_req->qtcb->header.fsf_command = fsf_cmd;
-		/*
-		 * Request Sequence Number is set later when the request is
-		 * actually sent.
-		 */
+	if (likely(req_flags & ZFCP_REQ_AUTO_CLEANUP)) {
+		fsf_req->status |= ZFCP_STATUS_FSFREQ_CLEANUP;
 	}
 
-	/*
-	 * try to get needed SBALs in request queue (get queue lock on success)
-	 */
-	ZFCP_LOG_TRACE("try to get free BUFFER in request queue\n");
-	if (unlikely(req_flags & ZFCP_WAIT_FOR_SBAL)) {
-		timeout = ZFCP_SBAL_TIMEOUT;
-		ZFCP_WAIT_EVENT_TIMEOUT(adapter->request_wq,
-					timeout,
-					(condition =
-					 (zfcp_fsf_req_create_sbal_check)
-					 (lock_flags, req_queue, 1)));
-		if (!condition) {
-			retval = -EIO;
-			goto failed_sbals;
-		}
-	} else {
-		if (!zfcp_fsf_req_create_sbal_check(lock_flags, req_queue, 1)) {
-			retval = -EIO;
-			goto failed_sbals;
-		}
-	}
-	fsf_req->sbal_count = 1;
-	fsf_req->sbal_index = req_queue->free_index;
+	sbale = zfcp_qdio_sbale_req(fsf_req, fsf_req->sbal_curr, 0);
 
-	ZFCP_LOG_TRACE("got %i free BUFFERs starting at index %i\n",
-		       fsf_req->sbal_count, fsf_req->sbal_index);
-	buffere = req_queue->buffer[fsf_req->sbal_index]->element;
 	/* setup common SBALE fields */
-	buffere[0].addr = fsf_req;
-	buffere[0].flags |= SBAL_FLAGS0_COMMAND;
-	if (likely(fsf_cmd != FSF_QTCB_UNSOLICITED_STATUS)) {
-		buffere[1].addr = (void *) fsf_req->qtcb;
-		buffere[1].length = ZFCP_QTCB_SIZE;
+	sbale[0].addr = fsf_req;
+	sbale[0].flags |= SBAL_FLAGS0_COMMAND;
+	if (likely(fsf_req->qtcb != NULL)) {
+		sbale[1].addr = (void *) fsf_req->qtcb;
+		sbale[1].length = sizeof(struct fsf_qtcb);
 	}
 
-	/* set specific common SBALE and QTCB fields */
-	switch (fsf_cmd) {
-	case FSF_QTCB_FCP_CMND:
-		ZFCP_LOG_FLAGS(3, "FSF_QTCB_FCP_CMND\n");
-		/*
-		 * storage-block type depends on actual
-		 * SCSI command and is set by calling
-		 * routine according to transfer direction
-		 * of data buffers associated with SCSI
-		 * command
-		 */
-		break;
-	case FSF_QTCB_ABORT_FCP_CMND:
-	case FSF_QTCB_OPEN_PORT_WITH_DID:
-	case FSF_QTCB_OPEN_LUN:
-	case FSF_QTCB_CLOSE_LUN:
-	case FSF_QTCB_CLOSE_PORT:
-	case FSF_QTCB_CLOSE_PHYSICAL_PORT:
-	case FSF_QTCB_SEND_ELS:	/* FIXME: ELS needs separate case */
-		ZFCP_LOG_FLAGS(3, "FSF_QTCB_*\n");
-		/*
-		 * FIXME(qdio):
-		 * what is the correct type for commands
-		 * without 'real' data buffers?
-		 */
-		buffere[0].flags |= SBAL_FLAGS0_TYPE_READ;
-		buffere[1].flags |= SBAL_FLAGS_LAST_ENTRY;
-		break;
-	case FSF_QTCB_EXCHANGE_CONFIG_DATA:
-		ZFCP_LOG_FLAGS(3, "FSF_QTCB_EXCHANGE_CONFIG_DATA\n");
-		buffere[0].flags |= SBAL_FLAGS0_TYPE_READ;
-		buffere[1].flags |= SBAL_FLAGS_LAST_ENTRY;
-		break;
-
-	case FSF_QTCB_SEND_GENERIC:
-		ZFCP_LOG_FLAGS(3, "FSF_QTCB_SEND_GENERIC\n");
-		buffere[0].flags |= SBAL_FLAGS0_TYPE_WRITE_READ;
-		break;
-
-	case FSF_QTCB_UNSOLICITED_STATUS:
-		ZFCP_LOG_FLAGS(3, "FSF_QTCB_UNSOLICITED_STATUS\n");
-		buffere[0].flags |= SBAL_FLAGS0_TYPE_STATUS;
-		buffere[2].flags |= SBAL_FLAGS_LAST_ENTRY;
-		break;
-
-	default:
-		ZFCP_LOG_NORMAL("bug: An attempt to send an unsupported "
-				"command has been detected. "
-				"(debug info 0x%x)\n", fsf_cmd);
-		goto unsupported_fsf_cmd;
-	}
-
-	/* yes, we did it - skip all cleanups for different failures */
-	goto out;
+	ZFCP_LOG_TRACE("got %i free BUFFERs starting at index %i\n",
+                       fsf_req->sbal_number, fsf_req->sbal_first);
 
- unsupported_fsf_cmd:
+	goto success;
 
  failed_sbals:
 #ifdef ZFCP_STAT_QUEUES
@@ -4101,9 +4973,9 @@ zfcp_fsf_req_create(struct zfcp_adapter 
 
  failed_fsf_req:
 	write_lock_irqsave(&req_queue->queue_lock, *lock_flags);
- out:
+ success:
 	*fsf_req_p = fsf_req;
-	return retval;
+	return ret;
 }
 
 /*
@@ -4117,23 +4989,24 @@ zfcp_fsf_req_create(struct zfcp_adapter 
 static int
 zfcp_fsf_req_send(struct zfcp_fsf_req *fsf_req, struct timer_list *timer)
 {
-	int retval = 0;
-	struct zfcp_adapter *adapter = fsf_req->adapter;
-	struct zfcp_qdio_queue *req_queue = &adapter->request_queue;
-	volatile struct qdio_buffer_element *buffere;
-	int inc_seq_no = 1;
+	struct zfcp_adapter *adapter;
+	struct zfcp_qdio_queue *req_queue;
+	volatile struct qdio_buffer_element *sbale;
 	int new_distance_from_int;
 	unsigned long flags;
+	int inc_seq_no = 1;
+	int retval = 0;
+
+	adapter = fsf_req->adapter;
+	req_queue = &adapter->request_queue,
 
-	u8 sbal_index = fsf_req->sbal_index;
 
 	/* FIXME(debug): remove it later */
-	buffere = &(req_queue->buffer[sbal_index]->element[0]);
-	ZFCP_LOG_DEBUG("zeroeth BUFFERE flags=0x%x \n ", buffere->flags);
-	buffere = &(req_queue->buffer[sbal_index]->element[1]);
-	ZFCP_LOG_TRACE("HEX DUMP OF 0eth BUFFERE PAYLOAD:\n");
-	ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_TRACE, (char *) buffere->addr,
-		      buffere->length);
+	sbale = zfcp_qdio_sbale_req(fsf_req, fsf_req->sbal_first, 0);
+	ZFCP_LOG_DEBUG("SBALE0 flags=0x%x\n", sbale[0].flags);
+	ZFCP_LOG_TRACE("HEX DUMP OF SBALE1 PAYLOAD:\n");
+	ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_TRACE, (char *) sbale[1].addr,
+		      sbale[1].length);
 
 	/* set sequence counter in QTCB */
 	if (likely(fsf_req->qtcb)) {
@@ -4168,24 +5041,22 @@ zfcp_fsf_req_send(struct zfcp_fsf_req *f
 		       "index_in_queue=%i, count=%i, buffers=0x%lx\n",
 		       zfcp_get_busid_by_adapter(adapter),
 		       QDIO_FLAG_SYNC_OUTPUT,
-		       0,
-		       sbal_index,
-		       fsf_req->sbal_count,
-		       (unsigned long) &req_queue->buffer[sbal_index]);
+		       0, fsf_req->sbal_first, fsf_req->sbal_number,
+		       (unsigned long) &req_queue->buffer[fsf_req->sbal_first]);
 
 	/*
 	 * adjust the number of free SBALs in request queue as well as
 	 * position of first one
 	 */
-	atomic_sub(fsf_req->sbal_count, &req_queue->free_count);
+	atomic_sub(fsf_req->sbal_number, &req_queue->free_count);
 	ZFCP_LOG_TRACE("free_count=%d\n", atomic_read(&req_queue->free_count));
-	req_queue->free_index += fsf_req->sbal_count;	  /* increase */
+	req_queue->free_index += fsf_req->sbal_number;	  /* increase */
 	req_queue->free_index %= QDIO_MAX_BUFFERS_PER_Q;  /* wrap if needed */
 	new_distance_from_int = zfcp_qdio_determine_pci(req_queue, fsf_req);
 
 	retval = do_QDIO(adapter->ccw_device,
 			 QDIO_FLAG_SYNC_OUTPUT,
-			 0, fsf_req->sbal_index, fsf_req->sbal_count, NULL);
+			 0, fsf_req->sbal_first, fsf_req->sbal_number, NULL);
 
 	if (unlikely(retval)) {
 		/* Queues are down..... */
@@ -4204,9 +5075,9 @@ zfcp_fsf_req_send(struct zfcp_fsf_req *f
 		 * position of first one
 		 */
 		zfcp_qdio_zero_sbals(req_queue->buffer,
-				     fsf_req->sbal_index, fsf_req->sbal_count);
-		atomic_add(fsf_req->sbal_count, &req_queue->free_count);
-		req_queue->free_index -= fsf_req->sbal_count;	 /* increase */
+				     fsf_req->sbal_first, fsf_req->sbal_number);
+		atomic_add(fsf_req->sbal_number, &req_queue->free_count);
+		req_queue->free_index -= fsf_req->sbal_number;	 /* increase */
 		req_queue->free_index += QDIO_MAX_BUFFERS_PER_Q;
 		req_queue->free_index %= QDIO_MAX_BUFFERS_PER_Q; /* wrap */
 		ZFCP_LOG_DEBUG
@@ -4270,35 +5141,4 @@ zfcp_fsf_req_cleanup(struct zfcp_fsf_req
 	zfcp_fsf_req_free(fsf_req);
 }
 
-/*
- * try to allocate fsf_req with QTCB,
- * alternately try to get hold of fsf_req+QTCB provided by the specified memory
- * pool element, this routine is called for all kinds of fsf requests other than
- * status read since status read does neither require kmalloc involvement
- * nor a QTCB
- */
-static struct zfcp_fsf_req *
-zfcp_fsf_req_get(int kmalloc_flags, mempool_t * pool)
-{
-	struct zfcp_fsf_req *fsf_req;
-
-	fsf_req = kmalloc(ZFCP_QTCB_AND_REQ_SIZE, kmalloc_flags);
-	if (likely(fsf_req)) {
-		memset(fsf_req, 0, ZFCP_QTCB_AND_REQ_SIZE);
-	} else {
-		fsf_req = mempool_alloc(pool, kmalloc_flags);
-		if (likely(fsf_req)) {
-			memset(fsf_req, 0, ZFCP_QTCB_AND_REQ_SIZE);
-			fsf_req->status |= ZFCP_STATUS_FSFREQ_POOL;
-		}
-	}
-	if (likely(fsf_req))
-		fsf_req->qtcb =
-		    (struct fsf_qtcb *) ((unsigned long) fsf_req +
-					 sizeof (struct zfcp_fsf_req));
-
-	return fsf_req;
-}
-
 #undef ZFCP_LOG_AREA
-#undef ZFCP_LOG_AREA_PREFIX
--- diff/drivers/s390/scsi/zfcp_fsf.h	2004-02-09 10:36:11.000000000 +0000
+++ source/drivers/s390/scsi/zfcp_fsf.h	2004-02-23 13:56:45.000000000 +0000
@@ -4,11 +4,12 @@
  * 
  * FCP adapter driver for IBM eServer zSeries 
  * 
- * Copyright 2002 IBM Corporation 
+ * (C) Copyright IBM Corp. 2002, 2004
+ *
  * Author(s): Martin Peschke <mpeschke@de.ibm.com> 
  *            Raimund Schroeder <raimund.schroeder@de.ibm.com> 
- *            Aron Zeh <arzeh@de.ibm.com> 
- *            Wolfgang Taphorn <taphorn@de.ibm.com> 
+ *            Aron Zeh
+ *            Wolfgang Taphorn
  *            Stefan Bader <stefan.bader@de.ibm.com> 
  *            Heiko Carstens <heiko.carstens@de.ibm.com> 
  * 
@@ -44,11 +45,22 @@
 #define	FSF_QTCB_SEND_ELS			0x0000000B
 #define	FSF_QTCB_SEND_GENERIC			0x0000000C
 #define	FSF_QTCB_EXCHANGE_CONFIG_DATA		0x0000000D
+#define	FSF_QTCB_EXCHANGE_PORT_DATA		0x0000000E
+#define FSF_QTCB_DOWNLOAD_CONTROL_FILE		0x00000012
+#define FSF_QTCB_UPLOAD_CONTROL_FILE		0x00000013
 
 /* FSF QTCB types */
 #define FSF_IO_COMMAND				0x00000001
 #define FSF_SUPPORT_COMMAND			0x00000002
 #define FSF_CONFIG_COMMAND			0x00000003
+#define FSF_PORT_COMMAND			0x00000004
+
+/* FSF control file upload/download operations' subtype and options */
+#define FSF_CFDC_OPERATION_SUBTYPE		0x00020001
+#define FSF_CFDC_OPTION_NORMAL_MODE		0x00000000
+#define FSF_CFDC_OPTION_FORCE			0x00000001
+#define FSF_CFDC_OPTION_FULL_ACCESS		0x00000002
+#define FSF_CFDC_OPTION_RESTRICTED_ACCESS	0x00000004
 
 /* FSF protocol stati */
 #define FSF_PROT_GOOD				0x00000001
@@ -71,9 +83,9 @@
 #define FSF_HANDLE_MISMATCH			0x00000005
 #define FSF_SERVICE_CLASS_NOT_SUPPORTED		0x00000006
 #define FSF_FCPLUN_NOT_VALID			0x00000009
-//#define FSF_ACCESS_DENIED                     0x00000010
+#define FSF_ACCESS_DENIED			0x00000010
 #define FSF_ACCESS_TYPE_NOT_VALID		0x00000011
-#define FSF_LUN_IN_USE				0x00000012
+#define FSF_LUN_SHARING_VIOLATION               0x00000012
 #define FSF_COMMAND_ABORTED_ULP			0x00000020
 #define FSF_COMMAND_ABORTED_ADAPTER		0x00000021
 #define FSF_FCP_COMMAND_DOES_NOT_EXIST		0x00000022
@@ -87,13 +99,24 @@
 #define FSF_RESPONSE_BUF_NOT_VALID		0x00000043
 #define FSF_ELS_COMMAND_REJECTED		0x00000050
 #define FSF_GENERIC_COMMAND_REJECTED		0x00000051
-//#define FSF_AUTHORIZATION_FAILURE             0x00000053
+#define FSF_OPERATION_PARTIALLY_SUCCESSFUL	0x00000052
+#define FSF_AUTHORIZATION_FAILURE		0x00000053
+#define FSF_CFDC_ERROR_DETECTED			0x00000054
+#define FSF_CONTROL_FILE_UPDATE_ERROR		0x00000055
+#define FSF_CONTROL_FILE_TOO_LARGE		0x00000056
+#define FSF_ACCESS_CONFLICT_DETECTED		0x00000057
+#define FSF_CONFLICTS_OVERRULED			0x00000058
 #define FSF_PORT_BOXED				0x00000059
-//#define FSF_LUN_BOXED                         0x0000005A
+#define FSF_LUN_BOXED				0x0000005A
+#define FSF_PAYLOAD_SIZE_MISMATCH		0x00000060
+#define FSF_REQUEST_SIZE_TOO_LARGE		0x00000061
+#define FSF_RESPONSE_SIZE_TOO_LARGE		0x00000062
 #define FSF_ADAPTER_STATUS_AVAILABLE		0x000000AD
 #define FSF_FCP_RSP_AVAILABLE			0x000000AF
 #define FSF_UNKNOWN_COMMAND			0x000000E2
-//#define FSF_ERROR                             0x000000FF 
+#define FSF_UNKNOWN_OP_SUBTYPE                  0x000000E3
+#define FSF_INVALID_COMMAND_OPTION              0x000000E5
+/* #define FSF_ERROR                             0x000000FF  */
 
 #define FSF_STATUS_QUALIFIER_SIZE		16
 
@@ -107,6 +130,15 @@
 #define FSF_SQ_COMMAND_ABORTED			0x06
 #define FSF_SQ_NO_RETRY_POSSIBLE		0x07
 
+/* FSF status qualifier for CFDC commands */
+#define FSF_SQ_CFDC_COULD_NOT_HARDEN_ON_SE	0x00000001
+#define FSF_SQ_CFDC_COULD_NOT_HARDEN_ON_SE2	0x00000002
+/* CFDC subtable codes */
+#define FSF_SQ_CFDC_SUBTABLE_OS			0x0001
+#define FSF_SQ_CFDC_SUBTABLE_PORT_WWPN		0x0002
+#define FSF_SQ_CFDC_SUBTABLE_PORT_DID		0x0003
+#define FSF_SQ_CFDC_SUBTABLE_LUN		0x0004
+
 /* FSF status qualifier (most significant 4 bytes), local link down */
 #define FSF_PSQ_LINK_NOLIGHT			0x00000004
 #define FSF_PSQ_LINK_WRAPPLUG			0x00000008
@@ -124,11 +156,20 @@
 #define FSF_STATUS_READ_BIT_ERROR_THRESHOLD	0x00000004
 #define FSF_STATUS_READ_LINK_DOWN		0x00000005 /* FIXME: really? */
 #define FSF_STATUS_READ_LINK_UP          	0x00000006
+#define FSF_STATUS_READ_NOTIFICATION_LOST	0x00000009
+#define FSF_STATUS_READ_CFDC_UPDATED		0x0000000A
+#define FSF_STATUS_READ_CFDC_HARDENED		0x0000000B
 
 /* status subtypes in status read buffer */
 #define FSF_STATUS_READ_SUB_CLOSE_PHYS_PORT	0x00000001
 #define FSF_STATUS_READ_SUB_ERROR_PORT		0x00000002
 
+/* status subtypes for CFDC */
+#define FSF_STATUS_READ_SUB_LOST_CFDC_UPDATED	0x00000020
+#define FSF_STATUS_READ_SUB_LOST_CFDC_HARDENED	0x00000040
+#define FSF_STATUS_READ_SUB_CFDC_HARDENED_ON_SE	0x00000002
+#define FSF_STATUS_READ_SUB_CFDC_HARDENED_ON_SE2 0x0000000F
+
 /* topologie that is detected by the adapter */
 #define FSF_TOPO_ERROR				0x00000000
 #define FSF_TOPO_P2P				0x00000001
@@ -149,10 +190,48 @@
 
 /* SBAL chaining */
 #define FSF_MAX_SBALS_PER_REQ			36
+#define FSF_MAX_SBALS_PER_ELS_REQ		2
 
 /* logging space behind QTCB */
 #define FSF_QTCB_LOG_SIZE			1024
 
+/* channel features */
+#define FSF_FEATURE_QTCB_SUPPRESSION            0x00000001
+#define FSF_FEATURE_CFDC			0x00000002
+#define FSF_FEATURE_SENSEDATA_REPLICATION       0x00000004
+#define FSF_FEATURE_LOST_SAN_NOTIFICATION       0x00000008
+#define FSF_FEATURE_HBAAPI_MANAGEMENT           0x00000010
+#define FSF_FEATURE_ELS_CT_CHAINED_SBALS        0x00000020
+
+/* option */
+#define FSF_OPEN_LUN_SUPPRESS_BOXING		0x00000001
+
+/* adapter types */
+#define FSF_ADAPTER_TYPE_FICON                  0x00000001
+#define FSF_ADAPTER_TYPE_FICON_EXPRESS          0x00000002
+
+/* port types */
+#define FSF_HBA_PORTTYPE_UNKNOWN		0x00000001
+#define FSF_HBA_PORTTYPE_NOTPRESENT		0x00000003
+#define FSF_HBA_PORTTYPE_NPORT			0x00000005
+#define FSF_HBA_PORTTYPE_PTP			0x00000021
+/* following are not defined and used by FSF Spec
+   but are additionally defined by FC-HBA */
+#define FSF_HBA_PORTTYPE_OTHER			0x00000002
+#define FSF_HBA_PORTTYPE_NOTPRESENT		0x00000003
+#define FSF_HBA_PORTTYPE_NLPORT			0x00000006
+#define FSF_HBA_PORTTYPE_FLPORT			0x00000007
+#define FSF_HBA_PORTTYPE_FPORT			0x00000008
+#define FSF_HBA_PORTTYPE_LPORT			0x00000020
+
+/* port states */
+#define FSF_HBA_PORTSTATE_UNKNOWN		0x00000001
+#define FSF_HBA_PORTSTATE_ONLINE		0x00000002
+#define FSF_HBA_PORTSTATE_OFFLINE		0x00000003
+#define FSF_HBA_PORTSTATE_LINKDOWN		0x00000006
+#define FSF_HBA_PORTSTATE_ERROR			0x00000007
+
+
 struct fsf_queue_designator;
 struct fsf_status_read_buffer;
 struct fsf_port_closed_payload;
@@ -307,49 +386,92 @@ struct fsf_qtcb_bottom_io {
 } __attribute__ ((packed));
 
 struct fsf_qtcb_bottom_support {
-	u8  res1[16];
+	u32 operation_subtype;
+	u8  res1[12];
 	u32 d_id;
-	u32 res2;
+	u32 option;
 	u64 fcp_lun;
-	u64 res3;
+	u64 res2;
 	u64 req_handle;
 	u32 service_class;
-	u8  res4[3];
+	u8 res3[3];
 	u8  timeout;
-	u8  res5[184];
+	u8 res4[184];
 	u32 els1_length;
 	u32 els2_length;
-	u64 res6;
+	u32 req_buf_length;
+	u32 resp_buf_length;
 	u8  els[256];
 } __attribute__ ((packed));
 
 struct fsf_qtcb_bottom_config {
 	u32 lic_version;
-	u32 res1;
+	u32 feature_selection;
 	u32 high_qtcb_version;
 	u32 low_qtcb_version;
 	u32 max_qtcb_size;
-	u8  res2[12];
+	u32 max_data_transfer_size;
+	u32 supported_features;
+	u8  res1[4];
 	u32 fc_topology;
 	u32 fc_link_speed;
 	u32 adapter_type;
 	u32 peer_d_id;
-	u8  res3[12];
+	u8 res2[12];
 	u32 s_id;
 	struct fsf_nport_serv_param nport_serv_param;
-	u8  res4[320];
+	u8 res3[8];
+	u32 adapter_ports;
+	u32 hardware_version;
+	u8 serial_number[32];
+	u8 res4[272];
+} __attribute__ ((packed));
+
+struct fsf_qtcb_bottom_port {
+	u8 res1[8];
+	u32 fc_port_id;
+	u32 port_type;
+	u32 port_state;
+	u32 class_of_service;	/* should be 0x00000006 for class 2 and 3 */
+	u8 supported_fc4_types[32]; /* should be 0x00000100 for scsi fcp */
+	u8 active_fc4_types[32];
+	u32 supported_speed;	/* 0x0001 for 1 GBit/s or 0x0002 for 2 GBit/s */
+	u32 maximum_frame_size;	/* fixed value of 2112 */
+	u64 seconds_since_last_reset;
+	u64 tx_frames;
+	u64 tx_words;
+	u64 rx_frames;
+	u64 rx_words;
+	u64 lip;		/* 0 */
+	u64 nos;		/* currently 0 */
+	u64 error_frames;	/* currently 0 */
+	u64 dumped_frames;	/* currently 0 */
+	u64 link_failure;
+	u64 loss_of_sync;
+	u64 loss_of_signal;
+	u64 psp_error_counts;
+	u64 invalid_tx_words;
+	u64 invalid_crcs;
+	u64 input_requests;
+	u64 output_requests;
+	u64 control_requests;
+	u64 input_mb;		/* where 1 MByte == 1.000.000 Bytes */
+	u64 output_mb;		/* where 1 MByte == 1.000.000 Bytes */
+	u8 res2[256];
 } __attribute__ ((packed));
 
 union fsf_qtcb_bottom {
 	struct fsf_qtcb_bottom_io      io;
 	struct fsf_qtcb_bottom_support support;
 	struct fsf_qtcb_bottom_config  config;
+	struct fsf_qtcb_bottom_port port;
 };
 
 struct fsf_qtcb {
 	struct fsf_qtcb_prefix prefix;
 	struct fsf_qtcb_header header;
 	union  fsf_qtcb_bottom bottom;
+	u8 log[FSF_QTCB_LOG_SIZE];
 } __attribute__ ((packed));
 
 #endif				/* FSF_H */
--- diff/drivers/s390/scsi/zfcp_qdio.c	2004-02-09 10:36:11.000000000 +0000
+++ source/drivers/s390/scsi/zfcp_qdio.c	2004-02-23 13:56:45.000000000 +0000
@@ -5,11 +5,12 @@
  *
  * QDIO related routines
  *
- * Copyright (C) 2003 IBM Entwicklung GmbH, IBM Corporation
+ * (C) Copyright IBM Corp. 2002, 2004
+ *
  * Authors:
  *      Martin Peschke <mpeschke@de.ibm.com>
  *      Raimund Schroeder <raimund.schroeder@de.ibm.com>
- *      Wolfgang Taphorn <taphorn@de.ibm.com>
+ *      Wolfgang Taphorn
  *      Heiko Carstens <heiko.carstens@de.ibm.com>
  *
  * This program is free software; you can redistribute it and/or modify
@@ -27,10 +28,28 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
-#define ZFCP_QDIO_C_REVISION "$Revision: 1.10 $"
+#define ZFCP_QDIO_C_REVISION "$Revision: 1.13 $"
 
 #include "zfcp_ext.h"
 
+static inline void zfcp_qdio_sbal_limit(struct zfcp_fsf_req *, int);
+static inline volatile struct qdio_buffer_element *zfcp_qdio_sbale_get
+	(struct zfcp_qdio_queue *, int, int);
+static inline volatile struct qdio_buffer_element *zfcp_qdio_sbale_resp
+	(struct zfcp_fsf_req *, int, int);
+static inline volatile struct qdio_buffer_element *zfcp_qdio_sbal_chain
+	(struct zfcp_fsf_req *, unsigned long);
+static inline volatile struct qdio_buffer_element *zfcp_qdio_sbale_next
+	(struct zfcp_fsf_req *, unsigned long);
+static inline int zfcp_qdio_sbals_zero(struct zfcp_qdio_queue *, int, int);
+static inline int zfcp_qdio_sbals_wipe(struct zfcp_fsf_req *);
+static inline void zfcp_qdio_sbale_fill
+	(struct zfcp_fsf_req *, unsigned long, void *, int);
+static inline int zfcp_qdio_sbals_from_segment
+	(struct zfcp_fsf_req *, unsigned long, void *, unsigned long);
+static inline int zfcp_qdio_sbals_from_buffer
+	(struct zfcp_fsf_req *, unsigned long, void *, unsigned long, int);
+
 static qdio_handler_t zfcp_qdio_request_handler;
 static qdio_handler_t zfcp_qdio_response_handler;
 static int zfcp_qdio_handler_error_check(struct zfcp_adapter *,
@@ -38,7 +57,6 @@ static int zfcp_qdio_handler_error_check
 					 unsigned int, unsigned int);
 
 #define ZFCP_LOG_AREA                   ZFCP_LOG_AREA_QDIO
-#define ZFCP_LOG_AREA_PREFIX            ZFCP_LOG_AREA_PREFIX_QDIO
 
 /*
  * Allocates BUFFER memory to each of the pointers of the qdio_buffer_t 
@@ -318,7 +336,7 @@ zfcp_qdio_request_handler(struct ccw_dev
 	atomic_add(elements_processed, &queue->free_count);
 	ZFCP_LOG_DEBUG("free_count=%d\n", atomic_read(&queue->free_count));
 	wake_up(&adapter->request_wq);
-	ZFCP_LOG_DEBUG("Elements_processed = %d, free count=%d \n",
+	ZFCP_LOG_DEBUG("Elements_processed = %d, free count=%d\n",
 		       elements_processed, atomic_read(&queue->free_count));
  out:
 	return;
@@ -365,7 +383,7 @@ zfcp_qdio_response_handler(struct ccw_de
 	 */
 
 	buffere = &(queue->buffer[first_element]->element[0]);
-	ZFCP_LOG_DEBUG("first BUFFERE flags=0x%x \n ", buffere->flags);
+	ZFCP_LOG_DEBUG("first BUFFERE flags=0x%x \n", buffere->flags);
 	/*
 	 * go through all SBALs from input queue currently
 	 * returned by QDIO layer
@@ -516,8 +534,8 @@ zfcp_qdio_reqid_check(struct zfcp_adapte
 		       (unsigned long) fsf_req, (unsigned long) fsf_req->qtcb);
 	if (likely(fsf_req->qtcb)) {
 		ZFCP_LOG_TRACE("HEX DUMP OF 1ST BUFFERE PAYLOAD (QTCB):\n");
-		ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_TRACE,
-			      (char *) fsf_req->qtcb, ZFCP_QTCB_SIZE);
+		ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_TRACE, (char *) fsf_req->qtcb,
+			      sizeof(struct fsf_qtcb));
 	}
 
 	/* finish the FSF request */
@@ -526,24 +544,346 @@ zfcp_qdio_reqid_check(struct zfcp_adapte
 	return retval;
 }
 
+/**
+ * zfcp_qdio_sbale_get - return pointer to SBALE of qdio_queue
+ * @queue: queue from which SBALE should be returned
+ * @sbal: specifies number of SBAL in queue
+ * @sbale: specifes number of SBALE in SBAL
+ */
+static inline volatile struct qdio_buffer_element *
+zfcp_qdio_sbale_get(struct zfcp_qdio_queue *queue, int sbal, int sbale)
+{
+	return &queue->buffer[sbal]->element[sbale];
+}
+
+/**
+ * zfcp_qdio_sbale_req - return pointer to SBALE of request_queue for
+ *	a struct zfcp_fsf_req
+ */
+inline volatile struct qdio_buffer_element *
+zfcp_qdio_sbale_req(struct zfcp_fsf_req *fsf_req, int sbal, int sbale)
+{
+	return zfcp_qdio_sbale_get(&fsf_req->adapter->request_queue,
+				   sbal, sbale);
+}
+
+/**
+ * zfcp_qdio_sbale_resp - return pointer to SBALE of response_queue for
+ *	a struct zfcp_fsf_req
+ */
+static inline volatile struct qdio_buffer_element *
+zfcp_qdio_sbale_resp(struct zfcp_fsf_req *fsf_req, int sbal, int sbale)
+{
+	return zfcp_qdio_sbale_get(&fsf_req->adapter->response_queue,
+				   sbal, sbale);
+}
+
+/**
+ * zfcp_qdio_sbale_curr - return current SBALE on request_queue for
+ *	a struct zfcp_fsf_req
+ */
+inline volatile struct qdio_buffer_element *
+zfcp_qdio_sbale_curr(struct zfcp_fsf_req *fsf_req)
+{
+	return zfcp_qdio_sbale_req(fsf_req, fsf_req->sbal_curr,
+				   fsf_req->sbale_curr);
+}
+
+/**
+ * zfcp_qdio_sbal_limit - determine maximum number of SBALs that can be used
+ *	on the request_queue for a struct zfcp_fsf_req
+ * @fsf_req: the number of the last SBAL that can be used is stored herein
+ * @max_sbals: used to pass an upper limit for the number of SBALs
+ *
+ * Note: We can assume at least one free SBAL in the request_queue when called.
+ */
+static inline void
+zfcp_qdio_sbal_limit(struct zfcp_fsf_req *fsf_req, int max_sbals)
+{
+	int count = atomic_read(&fsf_req->adapter->request_queue.free_count);
+	count = min(count, max_sbals);
+	fsf_req->sbal_last  = fsf_req->sbal_first;
+	fsf_req->sbal_last += (count - 1);
+	fsf_req->sbal_last %= QDIO_MAX_BUFFERS_PER_Q;
+}
+
+/**
+ * zfcp_qdio_sbal_chain - chain SBALs if more than one SBAL is needed for a
+ *	request
+ * @fsf_req: zfcp_fsf_req to be processed
+ * @sbtype: SBAL flags which have to be set in first SBALE of new SBAL
+ *
+ * This function changes sbal_curr, sbale_curr, sbal_number of fsf_req.
+ */
+static inline volatile struct qdio_buffer_element *
+zfcp_qdio_sbal_chain(struct zfcp_fsf_req *fsf_req, unsigned long sbtype)
+{
+	volatile struct qdio_buffer_element *sbale;
+
+	/* set last entry flag in current SBALE of current SBAL */
+	sbale = zfcp_qdio_sbale_curr(fsf_req);
+	sbale->flags |= SBAL_FLAGS_LAST_ENTRY;
+
+	/* don't exceed last allowed SBAL */
+	if (fsf_req->sbal_curr == fsf_req->sbal_last)
+		return NULL;
+
+	/* set chaining flag in first SBALE of current SBAL */
+	sbale = zfcp_qdio_sbale_req(fsf_req, fsf_req->sbal_curr, 0);
+	sbale->flags |= SBAL_FLAGS0_MORE_SBALS;
+
+	/* calculate index of next SBAL */
+	fsf_req->sbal_curr++;
+	fsf_req->sbal_curr %= QDIO_MAX_BUFFERS_PER_Q;
+
+	/* keep this requests number of SBALs up-to-date */
+	fsf_req->sbal_number++;
+
+	/* start at first SBALE of new SBAL */
+	fsf_req->sbale_curr = 0;
+
+	/* set storage-block type for new SBAL */
+	sbale = zfcp_qdio_sbale_curr(fsf_req);
+	sbale->flags |= sbtype;
+
+	return sbale;
+}
+
+/**
+ * zfcp_qdio_sbale_next - switch to next SBALE, chain SBALs if needed
+ */
+static inline volatile struct qdio_buffer_element *
+zfcp_qdio_sbale_next(struct zfcp_fsf_req *fsf_req, unsigned long sbtype)
+{
+	if (fsf_req->sbale_curr == ZFCP_LAST_SBALE_PER_SBAL)
+		return zfcp_qdio_sbal_chain(fsf_req, sbtype);
+
+	fsf_req->sbale_curr++;
+
+	return zfcp_qdio_sbale_curr(fsf_req);
+}
+
+/**
+ * zfcp_qdio_sbals_zero - initialize SBALs between first and last in queue
+ *	with zero from
+ */
+static inline int
+zfcp_qdio_sbals_zero(struct zfcp_qdio_queue *queue, int first, int last)
+{
+	struct qdio_buffer **buf = queue->buffer;
+	int curr = first;
+	int count = 0;
+
+	for(;;) {
+		curr %= QDIO_MAX_BUFFERS_PER_Q;
+		count++;
+		memset(buf[curr], 0, sizeof(struct qdio_buffer));
+		if (curr == last)
+			break;
+		curr++;
+	}
+	return count;
+}
+
+
+/**
+ * zfcp_qdio_sbals_wipe - reset all changes in SBALs for an fsf_req
+ */
+static inline int
+zfcp_qdio_sbals_wipe(struct zfcp_fsf_req *fsf_req)
+{
+	return zfcp_qdio_sbals_zero(&fsf_req->adapter->request_queue,
+				    fsf_req->sbal_first, fsf_req->sbal_curr);
+}
+
+
+/**
+ * zfcp_qdio_sbale_fill - set address and lenght in current SBALE
+ *	on request_queue
+ */
+static inline void
+zfcp_qdio_sbale_fill(struct zfcp_fsf_req *fsf_req, unsigned long sbtype,
+		     void *addr, int length)
+{
+	volatile struct qdio_buffer_element *sbale;
+
+	sbale = zfcp_qdio_sbale_curr(fsf_req);
+	sbale->addr = addr;
+	sbale->length = length;
+
+#ifdef ZFCP_STAT_REQSIZES
+        if (sbtype == SBAL_FLAGS0_TYPE_READ)
+                zfcp_statistics_inc(&zfcp_data.read_sg_head, length);
+        else    zfcp_statistics_inc(&zfcp_data.write_sg_head, length);
+#endif
+}
+
+/**
+ * zfcp_qdio_sbals_from_segment - map memory segment to SBALE(s)
+ * @fsf_req: request to be processed
+ * @sbtype: SBALE flags
+ * @start_addr: address of memory segment
+ * @total_length: length of memory segment
+ *
+ * Alignment and length of the segment determine how many SBALEs are needed
+ * for the memory segment.
+ */
+static inline int
+zfcp_qdio_sbals_from_segment(struct zfcp_fsf_req *fsf_req, unsigned long sbtype,
+			     void *start_addr, unsigned long total_length)
+{
+	unsigned long remaining, length;
+	void *addr;
+
+	/* split segment up heeding page boundaries */
+	for (addr = start_addr, remaining = total_length; remaining > 0;
+	     addr += length, remaining -= length) {
+		/* get next free SBALE for new piece */
+		if (NULL == zfcp_qdio_sbale_next(fsf_req, sbtype)) {
+			/* no SBALE left, clean up and leave */
+			zfcp_qdio_sbals_wipe(fsf_req);
+			return -EINVAL;
+		}
+		/* calculate length of new piece */
+		length = min(remaining,
+			     (PAGE_SIZE - ((unsigned long) addr &
+					   (PAGE_SIZE - 1))));
+		/* fill current SBALE with calculated piece */
+		zfcp_qdio_sbale_fill(fsf_req, sbtype, addr, length);
+	}
+	return total_length;
+}
+
+
+/**
+ * zfcp_qdio_sbals_from_sg - fill SBALs from scatter-gather list
+ * @fsf_req: request to be processed
+ * @sbtype: SBALE flags
+ * @sg: scatter-gather list
+ * @sg_count: number of elements in scatter-gather list
+ * @max_sbals: upper bound for number of SBALs to be used
+ */
+inline int
+zfcp_qdio_sbals_from_sg(struct zfcp_fsf_req *fsf_req, unsigned long sbtype,
+                        struct scatterlist *sg,	int sg_count, int max_sbals)
+{
+	int sg_index;
+	struct scatterlist *sg_segment;
+	int retval;
+	volatile struct qdio_buffer_element *sbale;
+	int bytes = 0;
+
+	/* figure out last allowed SBAL */
+	zfcp_qdio_sbal_limit(fsf_req, max_sbals);
+
+	/* set storage-block type for current SBAL */
+	sbale = zfcp_qdio_sbale_req(fsf_req, fsf_req->sbal_curr, 0);
+	sbale->flags |= sbtype;
+
+	/* process all segements of scatter-gather list */
+	for (sg_index = 0, sg_segment = sg, bytes = 0;
+	     sg_index < sg_count;
+	     sg_index++, sg_segment++) {
+		retval = zfcp_qdio_sbals_from_segment(
+				fsf_req,
+				sbtype,
+				zfcp_sg_to_address(sg_segment),
+				sg_segment->length);
+		if (retval < 0) {
+			bytes = retval;
+			goto out;
+		} else
+                        bytes += retval;
+	}
+	/* assume that no other SBALEs are to follow in the same SBAL */
+	sbale = zfcp_qdio_sbale_curr(fsf_req);
+	sbale->flags |= SBAL_FLAGS_LAST_ENTRY;
+
+out:
+#ifdef ZFCP_STAT_REQSIZES
+	if (sbtype == SBAL_FLAGS0_TYPE_READ) {
+		zfcp_statistics_inc(&zfcp_data.read_sguse_head, sg_count);
+		zfcp_statistics_inc(&zfcp_data.read_req_head, bytes);
+	} else	{
+		zfcp_statistics_inc(&zfcp_data.write_sguse_head, sg_count);
+        	zfcp_statistics_inc(&zfcp_data.write_req_head, bytes);
+	}
+#endif
+
+	return bytes;
+}
+
+
+/**
+ * zfcp_qdio_sbals_from_buffer - fill SBALs from buffer
+ * @fsf_req: request to be processed
+ * @sbtype: SBALE flags
+ * @buffer: data buffer
+ * @length: length of buffer
+ * @max_sbals: upper bound for number of SBALs to be used
+ */
+static inline int
+zfcp_qdio_sbals_from_buffer(struct zfcp_fsf_req *fsf_req, unsigned long sbtype,
+			    void *buffer, unsigned long length, int max_sbals)
+{
+	struct scatterlist sg_segment;
+
+	zfcp_address_to_sg(buffer, &sg_segment);
+	sg_segment.length = length;
+
+	return zfcp_qdio_sbals_from_sg(fsf_req, sbtype, &sg_segment, 1,
+                                       max_sbals);
+}
+
+
+/**
+ * zfcp_qdio_sbals_from_scsicmnd - fill SBALs from scsi command
+ * @fsf_req: request to be processed
+ * @sbtype: SBALE flags
+ * @scsi_cmnd: either scatter-gather list or buffer contained herein is used
+ *	to fill SBALs
+ */
+inline int
+zfcp_qdio_sbals_from_scsicmnd(struct zfcp_fsf_req *fsf_req,
+			      unsigned long sbtype, struct scsi_cmnd *scsi_cmnd)
+{
+	if (scsi_cmnd->use_sg) {
+		return zfcp_qdio_sbals_from_sg(fsf_req,	sbtype,
+                                               (struct scatterlist *)
+                                               scsi_cmnd->request_buffer,
+                                               scsi_cmnd->use_sg,
+                                               ZFCP_MAX_SBALS_PER_REQ);
+	} else {
+                return zfcp_qdio_sbals_from_buffer(fsf_req, sbtype,
+                                                   scsi_cmnd->request_buffer,
+                                                   scsi_cmnd->request_bufflen,
+                                                   ZFCP_MAX_SBALS_PER_REQ);
+	}
+}
+
+/**
+ * zfcp_qdio_determine_pci - set PCI flag in first SBALE on qdio queue if needed
+ */
 int
 zfcp_qdio_determine_pci(struct zfcp_qdio_queue *req_queue,
 			struct zfcp_fsf_req *fsf_req)
 {
 	int new_distance_from_int;
 	int pci_pos;
+	volatile struct qdio_buffer_element *sbale;
 
 	new_distance_from_int = req_queue->distance_from_int +
-				fsf_req->sbal_count;
+                fsf_req->sbal_number;
+
 	if (unlikely(new_distance_from_int >= ZFCP_QDIO_PCI_INTERVAL)) {
 		new_distance_from_int %= ZFCP_QDIO_PCI_INTERVAL;
-		pci_pos = fsf_req->sbal_index;
-		pci_pos += fsf_req->sbal_count;
+                pci_pos  = fsf_req->sbal_first;
+		pci_pos += fsf_req->sbal_number;
 		pci_pos -= new_distance_from_int;
 		pci_pos -= 1;
 		pci_pos %= QDIO_MAX_BUFFERS_PER_Q;
-		req_queue->buffer[pci_pos]->element[0].flags |= SBAL_FLAGS0_PCI;
-		ZFCP_LOG_TRACE("Setting PCI flag at pos %d\n", pci_pos);
+		sbale = zfcp_qdio_sbale_req(fsf_req, pci_pos, 0);
+		sbale->flags |= SBAL_FLAGS0_PCI;
 	}
 	return new_distance_from_int;
 }
@@ -570,4 +910,3 @@ zfcp_qdio_zero_sbals(struct qdio_buffer 
 }
 
 #undef ZFCP_LOG_AREA
-#undef ZFCP_LOG_AREA_PREFIX
--- diff/drivers/s390/scsi/zfcp_scsi.c	2004-02-09 10:36:11.000000000 +0000
+++ source/drivers/s390/scsi/zfcp_scsi.c	2004-02-23 13:56:45.000000000 +0000
@@ -4,11 +4,12 @@
  * 
  * FCP adapter driver for IBM eServer zSeries 
  * 
- * Copyright 2002 IBM Corporation 
+ * (C) Copyright IBM Corp. 2002, 2004
+ *
  * Author(s): Martin Peschke <mpeschke@de.ibm.com> 
  *            Raimund Schroeder <raimund.schroeder@de.ibm.com> 
- *            Aron Zeh <arzeh@de.ibm.com> 
- *            Wolfgang Taphorn <taphorn@de.ibm.com> 
+ *            Aron Zeh
+ *            Wolfgang Taphorn
  *            Stefan Bader <stefan.bader@de.ibm.com> 
  *            Heiko Carstens <heiko.carstens@de.ibm.com> 
  * 
@@ -28,9 +29,9 @@
  */
 
 #define ZFCP_LOG_AREA			ZFCP_LOG_AREA_SCSI
-#define ZFCP_LOG_AREA_PREFIX		ZFCP_LOG_AREA_PREFIX_SCSI
+
 /* this drivers version (do not edit !!! generated and updated by cvs) */
-#define ZFCP_SCSI_REVISION "$Revision: 1.42 $"
+#define ZFCP_SCSI_REVISION "$Revision: 1.52 $"
 
 #include <linux/blkdev.h>
 
@@ -39,24 +40,14 @@
 static void zfcp_scsi_slave_destroy(struct scsi_device *sdp);
 static int zfcp_scsi_slave_alloc(struct scsi_device *sdp);
 static int zfcp_scsi_slave_configure(struct scsi_device *sdp);
-static int zfcp_scsi_queuecommand(Scsi_Cmnd *, void (*done) (Scsi_Cmnd *));
-static int zfcp_scsi_eh_abort_handler(Scsi_Cmnd *);
-static int zfcp_scsi_eh_device_reset_handler(Scsi_Cmnd *);
-static int zfcp_scsi_eh_bus_reset_handler(Scsi_Cmnd *);
-static int zfcp_scsi_eh_host_reset_handler(Scsi_Cmnd *);
+static int zfcp_scsi_queuecommand(struct scsi_cmnd *,
+				  void (*done) (struct scsi_cmnd *));
+static int zfcp_scsi_eh_abort_handler(struct scsi_cmnd *);
+static int zfcp_scsi_eh_device_reset_handler(struct scsi_cmnd *);
+static int zfcp_scsi_eh_bus_reset_handler(struct scsi_cmnd *);
+static int zfcp_scsi_eh_host_reset_handler(struct scsi_cmnd *);
 static int zfcp_task_management_function(struct zfcp_unit *, u8);
 
-static int zfcp_create_sbales_from_segment(unsigned long, int, int *,
-					   int, int, int *, int *, int,
-					   int, struct qdio_buffer **,
-					   char);
-
-static int zfcp_create_sbale(unsigned long, int, int *, int, int, int *,
-			     int, int, int *, struct qdio_buffer **,
-			     char);
-
-static struct zfcp_unit *zfcp_scsi_determine_unit(struct zfcp_adapter *,
-						  Scsi_Cmnd *);
 static struct zfcp_unit *zfcp_unit_lookup(struct zfcp_adapter *, int, int, int);
 
 static struct device_attribute *zfcp_sysfs_sdev_attrs[];
@@ -225,59 +216,7 @@ zfcp_scsi_slave_destroy(struct scsi_devi
 	}
 }
 
-void
-zfcp_scsi_block_requests(struct Scsi_Host *shpnt)
-{
-	scsi_block_requests(shpnt);
-	/* This is still somewhat racy but the best I could imagine */
-	do {
-		set_current_state(TASK_UNINTERRUPTIBLE);
-		schedule_timeout(ZFCP_SCSI_HOST_FLUSH_TIMEOUT);
-
-	} while (shpnt->host_busy || shpnt->eh_active);
-}
-
 /* 
- * Tries to associate a zfcp unit with the scsi device.
- *
- * returns:       unit pointer   if unit is found
- *                NULL           otherwise
- */
-struct zfcp_unit *
-zfcp_scsi_determine_unit(struct zfcp_adapter *adapter, Scsi_Cmnd * scpnt)
-{
-	struct zfcp_unit *unit;
-
-	/*
-	 * figure out target device
-	 * (stored there by zfcp_scsi_slave_alloc)
-	 * ATTENTION: assumes hostdata initialized to NULL by
-	 * mid layer (see scsi_scan.c)
-	 */
-	unit = (struct zfcp_unit *) scpnt->device->hostdata;
-	if (!unit) {
-		ZFCP_LOG_DEBUG("logical unit (%i %i %i %i) not configured\n",
-			       scpnt->device->host->host_no,
-			       scpnt->device->channel,
-			       scpnt->device->id, scpnt->device->lun);
-		/*
-		 * must fake SCSI command execution and scsi_done
-		 * callback for non-configured logical unit
-		 */
-		/* return this as long as we are unable to process requests */
-		set_host_byte(&scpnt->result, DID_NO_CONNECT);
-		zfcp_cmd_dbf_event_scsi("notconf", scpnt);
-		scpnt->scsi_done(scpnt);
-#ifdef ZFCP_DEBUG_REQUESTS
-		debug_text_event(adapter->req_dbf, 2, "nc_done:");
-		debug_event(adapter->req_dbf, 2, &scpnt,
-			    sizeof (unsigned long));
-#endif				/* ZFCP_DEBUG_REQUESTS */
-	}
-	return unit;
-}
-
-/*
  * called from scsi midlayer to allow finetuning of a device.
  */
 static int
@@ -290,124 +229,143 @@ zfcp_scsi_slave_configure(struct scsi_de
 	return 0;
 }
 
-/* Complete a command immediately handing back DID_ERROR */
+/**
+ * zfcp_scsi_command_fail - set result in scsi_cmnd and call scsi_done function
+ * @scpnt: pointer to struct scsi_cmnd where result is set
+ * @result: result to be set in scpnt (e.g. DID_ERROR)
+ */
 static void
-zfcp_scsi_queuecommand_stop(Scsi_Cmnd * scpnt,
-			    struct zfcp_adapter *adapter,
-			    struct zfcp_unit *unit)
-{
-	/* Always pass through to upper layer */
-	scpnt->retries = scpnt->allowed - 1;
-	set_host_byte(&scpnt->result, DID_ERROR);
-	zfcp_cmd_dbf_event_scsi("stopping", scpnt);
+zfcp_scsi_command_fail(struct scsi_cmnd *scpnt, int result)
+{
+	set_host_byte(&scpnt->result, result);
+	zfcp_cmd_dbf_event_scsi("failing", scpnt);
 	/* return directly */
 	scpnt->scsi_done(scpnt);
-	if (adapter && unit) {
-		ZFCP_LOG_INFO("Stopping SCSI IO on the unit with FCP LUN 0x%Lx "
-			      "connected to the port with WWPN 0x%Lx at the "
-			      "adapter %s.\n",
-			      unit->fcp_lun,
-			      unit->port->wwpn,
-			      zfcp_get_busid_by_adapter(adapter));
-#ifdef ZFCP_DEBUG_REQUESTS
-		debug_text_event(adapter->req_dbf, 2, "de_done:");
-		debug_event(adapter->req_dbf, 2, &scpnt,
-			    sizeof (unsigned long));
-#endif				/* ZFCP_DEBUG_REQUESTS */
-	} else {
-		ZFCP_LOG_INFO("There is no adapter registered in the zfcp "
-			      "module for the SCSI host with hostnumber %d. "
-			      "Stopping IO.\n", scpnt->device->host->host_no);
-	}
 }
 
-/*
- * function:	zfcp_scsi_queuecommand
- *
- * purpose:	enqueues a SCSI command to the specified target device
- *
- * note:        The scsi_done midlayer function may be called directly from
- *              within queuecommand provided queuecommand returns with
- *              success (0).
- *              If it fails, it is expected that the command could not be sent
- *              and is still available for processing.
- *              As we ensure that queuecommand never fails, we have the choice 
- *              to call done directly wherever we please.
- *              Thus, any kind of send errors other than those indicating
- *              'infinite' retries will be reported directly.
- *              Retry requests are put into a list to be processed under timer 
- *              control once in a while to allow for other operations to
- *              complete in the meantime.
+/**
+ * zfcp_scsi_command_async - worker for zfcp_scsi_queuecommand and
+ *	zfcp_scsi_command_sync
+ * @adapter: adapter for where scsi command is issued
+ * @unit: unit to which scsi command is sent
+ * @scpnt: scsi command to be sent
  *
- * returns:	0 - success, SCSI command enqueued
- *		!0 - failure, note that we never allow this to happen as the 
- *              SCSI stack would block indefinitely should a non-zero return
- *              value be reported if there are no outstanding commands
- *              (as in when the queues are down)
+ * Note: In scsi_done function must be set in scpnt.
  */
 int
-zfcp_scsi_queuecommand(Scsi_Cmnd * scpnt, void (*done) (Scsi_Cmnd *))
+zfcp_scsi_command_async(struct zfcp_adapter *adapter, struct zfcp_unit *unit,
+			struct scsi_cmnd *scpnt)
 {
+	int tmp;
 	int retval;
-	int temp_ret;
-	struct zfcp_unit *unit;
-	struct zfcp_adapter *adapter;
 
 	retval = 0;
-	/* reset the status for this request */
-	scpnt->result = 0;
-	/* save address of mid layer call back function */
-	scpnt->scsi_done = done;
-	/*
-	 * figure out adapter
-	 * (previously stored there by the driver when
-	 * the adapter was registered)
-	 */
-	adapter = (struct zfcp_adapter *) scpnt->device->host->hostdata[0];
-	/* NULL when the adapter was removed from the zfcp list */
-	if (unlikely(adapter == NULL)) {
-		zfcp_scsi_queuecommand_stop(scpnt, NULL, NULL);
-		goto out;
-	}
 
-	unit = zfcp_scsi_determine_unit(adapter, scpnt);
-	if (unlikely(unit == NULL))
+	BUG_ON((adapter == NULL) || (adapter != unit->port->adapter));
+	BUG_ON(scpnt->scsi_done == NULL);
+
+	if (unlikely(NULL == unit)) {
+		zfcp_scsi_command_fail(scpnt, DID_NO_CONNECT);
 		goto out;
+	}
 
 	if (unlikely(
 	      atomic_test_mask(ZFCP_STATUS_COMMON_ERP_FAILED, &unit->status) ||
 	     !atomic_test_mask(ZFCP_STATUS_COMMON_RUNNING, &unit->status))) {
-		zfcp_scsi_queuecommand_stop(scpnt, adapter, unit);
+		ZFCP_LOG_DEBUG("Stopping SCSI IO on the unit with "
+			       "FCP LUN 0x%Lx connected to the port "
+			       "with WWPN 0x%Lx at the adapter %s.\n",
+			       unit->fcp_lun,
+			       unit->port->wwpn,
+			       zfcp_get_busid_by_adapter(adapter));
+		zfcp_scsi_command_fail(scpnt, DID_ERROR);
 		goto out;
 	}
+
 	if (unlikely(
 	     !atomic_test_mask(ZFCP_STATUS_COMMON_UNBLOCKED, &unit->status))) {
 		ZFCP_LOG_DEBUG("adapter %s not ready or unit with LUN 0x%Lx "
 			       "on the port with WWPN 0x%Lx in recovery.\n",
-			       zfcp_get_busid_by_adapter(adapter),
+			       zfcp_get_busid_by_unit(unit),
 			       unit->fcp_lun, unit->port->wwpn);
 		retval = SCSI_MLQUEUE_DEVICE_BUSY;
 		goto out;
 	}
 
-	temp_ret = zfcp_fsf_send_fcp_command_task(adapter,
-						  unit,
-						  scpnt, ZFCP_REQ_AUTO_CLEANUP);
+	tmp = zfcp_fsf_send_fcp_command_task(adapter, unit, scpnt,
+					     ZFCP_REQ_AUTO_CLEANUP);
 
-	if (unlikely(temp_ret < 0)) {
+	if (unlikely(tmp < 0)) {
 		ZFCP_LOG_DEBUG("error: Could not send a Send FCP Command\n");
 		retval = SCSI_MLQUEUE_HOST_BUSY;
 	} else {
+
 #ifdef ZFCP_DEBUG_REQUESTS
 		debug_text_event(adapter->req_dbf, 3, "q_scpnt");
 		debug_event(adapter->req_dbf, 3, &scpnt,
 			    sizeof (unsigned long));
 #endif				/* ZFCP_DEBUG_REQUESTS */
 	}
- out:
+
+out:
 	return retval;
 }
 
+void
+zfcp_scsi_command_sync_handler(struct scsi_cmnd *scpnt)
+{
+	struct completion *wait = (struct completion *) scpnt->SCp.ptr;
+	complete(wait);
+}
+
+
+/**
+ * zfcp_scsi_command_sync - send a SCSI command and wait for completion
+ * returns 0, errors are indicated by scsi_cmnd->result
+ */
+int
+zfcp_scsi_command_sync(struct zfcp_unit *unit, struct scsi_cmnd *scpnt)
+{
+	DECLARE_COMPLETION(wait);
+
+	scpnt->SCp.ptr = (void *) &wait;  /* silent re-use */
+	scpnt->done = zfcp_scsi_command_sync_handler;
+        zfcp_scsi_command_async(unit->port->adapter, unit, scpnt);
+	wait_for_completion(&wait);
+
+	return 0;
+}
+
+/*
+ * function:	zfcp_scsi_queuecommand
+ *
+ * purpose:	enqueues a SCSI command to the specified target device
+ *
+ * returns:	0 - success, SCSI command enqueued
+ *		!0 - failure
+ */
+int
+zfcp_scsi_queuecommand(struct scsi_cmnd *scpnt,
+		       void (*done) (struct scsi_cmnd *))
+{
+	struct zfcp_unit *unit;
+	struct zfcp_adapter *adapter;
+
+	/* reset the status for this request */
+	scpnt->result = 0;
+	/* save address of mid layer call back function */
+	scpnt->scsi_done = done;
+
+	/*
+	 * figure out adapter and target device
+	 * (stored there by zfcp_scsi_slave_alloc)
+	 */
+	adapter = (struct zfcp_adapter *) scpnt->device->host->hostdata[0];
+	unit = (struct zfcp_unit *) scpnt->device->hostdata;
+
+	return zfcp_scsi_command_async(adapter, unit, scpnt);
+}
+
 /*
  * function:    zfcp_unit_lookup
  *
@@ -456,22 +414,18 @@ zfcp_unit_lookup(struct zfcp_adapter *ad
  *		FAILED	- otherwise
  */
 int
-zfcp_scsi_eh_abort_handler(Scsi_Cmnd * scpnt)
+zfcp_scsi_eh_abort_handler(struct scsi_cmnd *scpnt)
 {
 	int retval = SUCCESS;
 	struct zfcp_fsf_req *new_fsf_req, *old_fsf_req;
-	struct zfcp_adapter *adapter;
-	struct zfcp_unit *unit;
-	struct zfcp_port *port;
-	struct Scsi_Host *scsi_host;
+	struct zfcp_adapter *adapter = (struct zfcp_adapter *) scpnt->device->host->hostdata[0];
+	struct zfcp_unit *unit = (struct zfcp_unit *) scpnt->device->hostdata;
+	struct zfcp_port *port = unit->port;
+	struct Scsi_Host *scsi_host = scpnt->device->host;
 	union zfcp_req_data *req_data = NULL;
 	unsigned long flags;
 	u32 status = 0;
 
-	adapter = (struct zfcp_adapter *) scpnt->device->host->hostdata[0];
-	scsi_host = scpnt->device->host;
-	unit = (struct zfcp_unit *) scpnt->device->hostdata;
-	port = unit->port;
 
 #ifdef ZFCP_DEBUG_ABORTS
 	/* the components of a abort_dbf record (fixed size record) */
@@ -657,7 +611,7 @@ zfcp_scsi_eh_abort_handler(Scsi_Cmnd * s
  * returns:
  */
 int
-zfcp_scsi_eh_device_reset_handler(Scsi_Cmnd * scpnt)
+zfcp_scsi_eh_device_reset_handler(struct scsi_cmnd *scpnt)
 {
 	int retval;
 	struct zfcp_unit *unit = (struct zfcp_unit *) scpnt->device->hostdata;
@@ -764,7 +718,7 @@ zfcp_task_management_function(struct zfc
  * returns:
  */
 int
-zfcp_scsi_eh_bus_reset_handler(Scsi_Cmnd * scpnt)
+zfcp_scsi_eh_bus_reset_handler(struct scsi_cmnd *scpnt)
 {
 	int retval = 0;
 	struct zfcp_unit *unit;
@@ -793,7 +747,7 @@ zfcp_scsi_eh_bus_reset_handler(Scsi_Cmnd
  * returns:
  */
 int
-zfcp_scsi_eh_host_reset_handler(Scsi_Cmnd * scpnt)
+zfcp_scsi_eh_host_reset_handler(struct scsi_cmnd *scpnt)
 {
 	int retval = 0;
 	struct zfcp_unit *unit;
@@ -887,332 +841,6 @@ zfcp_adapter_scsi_unregister(struct zfcp
 }
 
 
-/**
- * zfcp_create_sbales_from_segment - creates SBALEs
- * @addr:          begin of this buffer segment
- * @length_seg:	   length of this buffer segment
- * @length_total:  total length of buffer
- * @length_min:    roll back if generated buffer smaller than this
- * @length_max:	   sum of all SBALEs (count) not larger than this
- * @buffer_index:  position of current BUFFER
- * @buffere_index: position of current BUFFERE
- * @buffer_first:  first BUFFER used for this buffer
- * @buffer_last:   last BUFFER in request queue allowed
- * @buffer:        begin of SBAL array of request queue
- * @sbtype:        storage-block type
- */
-static int
-zfcp_create_sbales_from_segment(unsigned long addr, int length_seg,
-				int *length_total, int length_min,
-				int length_max, int *buffer_index,
-				int *buffere_index, int buffer_first,
-				int buffer_last, struct qdio_buffer *buffer[],
-				char sbtype)
-{
-	int retval = 0;
-	int length = 0;
-
-	ZFCP_LOG_TRACE
-	    ("SCSI data buffer segment with %i bytes from 0x%lx to 0x%lx\n",
-	     length_seg, addr, (addr + length_seg) - 1);
-
-	if (!length_seg)
-		goto out;
-
-	if (addr & (PAGE_SIZE - 1)) {
-		length =
-		    min((int) (PAGE_SIZE - (addr & (PAGE_SIZE - 1))),
-			length_seg);
-		ZFCP_LOG_TRACE
-		    ("address 0x%lx not on page boundary, length=0x%x\n",
-		     (unsigned long) addr, length);
-		retval =
-		    zfcp_create_sbale(addr, length, length_total, length_min,
-				      length_max, buffer_index, buffer_first,
-				      buffer_last, buffere_index, buffer,
-				      sbtype);
-		if (retval) {
-			/* no resources */
-			goto out;
-		}
-		addr += length;
-		length = length_seg - length;
-	} else
-		length = length_seg;
-
-	while (length > 0) {
-		retval = zfcp_create_sbale(addr, min((int) PAGE_SIZE, length),
-					   length_total, length_min, length_max,
-					   buffer_index, buffer_first,
-					   buffer_last, buffere_index, buffer,
-					   sbtype);
-		if (*buffere_index > ZFCP_LAST_SBALE_PER_SBAL)
-			ZFCP_LOG_NORMAL("bug: Filling output buffers with SCSI "
-					"data failed. Index ran out of bounds. "
-					"(debug info %d)\n", *buffere_index);
-		if (retval) {
-			/* no resources */
-			goto out;
-		}
-		length -= PAGE_SIZE;
-		addr += PAGE_SIZE;
-	}
- out:
-	return retval;
-}
-
-/**
- * zfcp_create_sbale - creates a single SBALE
- * @addr:          begin of this buffer segment
- * @length:        length of this buffer segment
- * @length_total:  total length of buffer
- * @length_min:    roll back if generated buffer smaller than this
- * @length_max:    sum of all SBALEs (count) not larger than this
- * @buffer_index:  position of current BUFFER
- * @buffer_first:  first BUFFER used for this buffer
- * @buffer_last:   last BUFFER allowed for this buffer
- * @buffere_index: position of current BUFFERE of current BUFFER
- * @buffer:        begin of SBAL array of request queue
- * @sbtype:        storage-block type
- */
-static int
-zfcp_create_sbale(unsigned long addr, int length, int *length_total,
-		  int length_min, int length_max, int *buffer_index,
-		  int buffer_first, int buffer_last, int *buffere_index,
-		  struct qdio_buffer *buffer[], char sbtype)
-{
-	int retval = 0;
-	int length_real, residual;
-	int buffers_used;
-
-	volatile struct qdio_buffer_element *buffere =
-	    &(buffer[*buffer_index]->element[*buffere_index]);
-
-	/* check whether we hit the limit */
-	residual = length_max - *length_total;
-	if (residual == 0) {
-		ZFCP_LOG_TRACE("skip remaining %i bytes since length_max hit\n",
-			       length);
-		goto out;
-	}
-	length_real = min(length, residual);
-
-	/*
-	 * figure out next BUFFERE
-	 * (first BUFFERE of first BUFFER is skipped - 
-	 * this is ok since it is reserved for the QTCB)
-	 */
-	if (*buffere_index == ZFCP_LAST_SBALE_PER_SBAL) {
-		/* last BUFFERE in this BUFFER */
-		buffere->flags |= SBAL_FLAGS_LAST_ENTRY;
-		/* need further BUFFER */
-		if (*buffer_index == buffer_last) {
-			/* queue full or last allowed BUFFER */
-			buffers_used = (buffer_last - buffer_first) + 1;
-			/* avoid modulo operation on negative value */
-			buffers_used += QDIO_MAX_BUFFERS_PER_Q;
-			buffers_used %= QDIO_MAX_BUFFERS_PER_Q;
-			ZFCP_LOG_DEBUG("reached limit of number of BUFFERs "
-				       "allowed for this request\n");
-			/* FIXME (design) - This check is wrong and enforces the
-			 * use of one SBALE less than possible 
-			 */
-			if ((*length_total < length_min)
-			    || (buffers_used < ZFCP_MAX_SBALS_PER_REQ)) {
-				ZFCP_LOG_DEBUG("Rolling back SCSI command as "
-					       "there are insufficient buffers "
-					       "to cover the minimum required "
-					       "amount of data\n");
-				/*
-				 * roll back complete list of BUFFERs generated
-				 * from the scatter-gather list associated
-				 * with this SCSI command
-				 */
-				zfcp_qdio_zero_sbals(buffer,
-						     buffer_first,
-						     buffers_used);
-				*length_total = 0;
-			} else {
-				/* DEBUG */
-				ZFCP_LOG_NORMAL("Not enough buffers available. "
-						"Can only transfer %i bytes of "
-						"data\n",
-						*length_total);
-			}
-			retval = -ENOMEM;
-			goto out;
-		} else {	/* *buffer_index != buffer_last */
-			/* chain BUFFERs */
-			*buffere_index = 0;
-			buffere =
-			    &(buffer[*buffer_index]->element[*buffere_index]);
-			buffere->flags |= SBAL_FLAGS0_MORE_SBALS;
-			(*buffer_index)++;
-			*buffer_index %= QDIO_MAX_BUFFERS_PER_Q;
-			buffere =
-			    &(buffer[*buffer_index]->element[*buffere_index]);
-			buffere->flags |= sbtype;
-			ZFCP_LOG_DEBUG
-			    ("Chaining previous BUFFER %i to BUFFER %i\n",
-			     ((*buffer_index !=
-			       0) ? *buffer_index - 1 : QDIO_MAX_BUFFERS_PER_Q -
-			      1), *buffer_index);
-		}
-	} else { /* *buffere_index != (QDIO_MAX_ELEMENTS_PER_BUFFER - 1) */
-		(*buffere_index)++;
-		buffere = &(buffer[*buffer_index]->element[*buffere_index]);
-	}
-
-	/* ok, found a place for this piece, put it there */
-	buffere->addr = (void *) addr;
-	buffere->length = length_real;
-
-#ifdef ZFCP_STAT_REQSIZES
-	if (sbtype == SBAL_FLAGS0_TYPE_READ)
-		zfcp_statistics_inc(&zfcp_data.read_sg_head, length_real);
-	else
-		zfcp_statistics_inc(&zfcp_data.write_sg_head, length_real);
-#endif
-
-	ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_TRACE, (char *) addr, length_real);
-	ZFCP_LOG_TRACE("BUFFER no %i (0x%lx) BUFFERE no %i (0x%lx): BUFFERE "
-		       "data addr 0x%lx, BUFFERE length %i, BUFFER type %i\n",
-		       *buffer_index,
-		       (unsigned long) &buffer[*buffer_index], *buffere_index,
-		       (unsigned long) buffere, addr, length_real, sbtype);
-	*length_total += length_real;
- out:
-	return retval;
-}
-
-/*
- * function:    zfcp_create_sbals_from_sg
- *
- * purpose:	walks through scatter-gather list of specified SCSI command
- *		and creates a corresponding list of SBALs
- *
- * returns:	size of generated buffer in bytes 
- *
- * context:	
- */
-int
-zfcp_create_sbals_from_sg(struct zfcp_fsf_req *fsf_req, Scsi_Cmnd * scpnt,
-			  char sbtype,	/* storage-block type */
-			  int length_min, /* roll back if generated buffer */
-			  int buffer_max) /* max numbers of BUFFERs */
-{
-	int length_total = 0;
-	int buffer_index = 0;
-	int buffer_last = 0;
-	int buffere_index = 1;	/* elements 0 and 1 are req-id and qtcb */
-	volatile struct qdio_buffer_element *buffere = NULL;
-	struct zfcp_qdio_queue *req_q = NULL;
-	int length_max = scpnt->request_bufflen;
-
-	req_q = &fsf_req->adapter->request_queue;
-
-	buffer_index = req_q->free_index;
-	buffer_last = req_q->free_index +
-	    min(buffer_max, atomic_read(&req_q->free_count)) - 1;
-	buffer_last %= QDIO_MAX_BUFFERS_PER_Q;
-
-	ZFCP_LOG_TRACE
-	    ("total SCSI data buffer size is (scpnt->request_bufflen) %i\n",
-	     scpnt->request_bufflen);
-	ZFCP_LOG_TRACE
-	    ("BUFFERs from (buffer_index)%i to (buffer_last)%i available\n",
-	     buffer_index, buffer_last);
-	ZFCP_LOG_TRACE("buffer_max=%d, req_q->free_count=%d\n", buffer_max,
-		       atomic_read(&req_q->free_count));
-
-	if (scpnt->use_sg) {
-		int sg_index;
-		struct scatterlist *list
-		    = (struct scatterlist *) scpnt->request_buffer;
-
-		ZFCP_LOG_DEBUG("%i (scpnt->use_sg) scatter-gather segments\n",
-			       scpnt->use_sg);
-
-		//                length_max+=0x2100;
-
-#ifdef ZFCP_STAT_REQSIZES
-		if (sbtype == SBAL_FLAGS0_TYPE_READ)
-			zfcp_statistics_inc(&zfcp_data.read_sguse_head,
-					    scpnt->use_sg);
-		else
-			zfcp_statistics_inc(&zfcp_data.write_sguse_head,
-					    scpnt->use_sg);
-#endif
-
-		for (sg_index = 0; sg_index < scpnt->use_sg; sg_index++, list++)
-		{
-			if (zfcp_create_sbales_from_segment(
-				    (page_to_pfn (list->page) << PAGE_SHIFT) +
-				    list->offset,
-				    list->length,
-				    &length_total,
-				    length_min,
-				    length_max,
-				    &buffer_index,
-				    &buffere_index,
-				    req_q->free_index,
-				    buffer_last,
-				    req_q->buffer,
-				    sbtype))
-				break;
-		}
-	} else {
-		ZFCP_LOG_DEBUG("no scatter-gather list\n");
-#ifdef ZFCP_STAT_REQSIZES
-		if (sbtype == SBAL_FLAGS0_TYPE_READ)
-			zfcp_statistics_inc(&zfcp_data.read_sguse_head, 1);
-		else
-			zfcp_statistics_inc(&zfcp_data.write_sguse_head, 1);
-#endif
-		zfcp_create_sbales_from_segment(
-			(unsigned long) scpnt->request_buffer,
-			scpnt->request_bufflen,
-			&length_total,
-			length_min,
-			length_max,
-			&buffer_index,
-			&buffere_index,
-			req_q->free_index,
-			buffer_last,
-			req_q->buffer,
-			sbtype);
-	}
-
-	fsf_req->sbal_index = req_q->free_index;
-
-	if (buffer_index >= fsf_req->sbal_index) {
-		fsf_req->sbal_count = (buffer_index - fsf_req->sbal_index) + 1;
-	} else {
-		fsf_req->sbal_count =
-		    (QDIO_MAX_BUFFERS_PER_Q - fsf_req->sbal_index) +
-		    buffer_index + 1;
-	}
-	/* HACK */
-	if ((scpnt->request_bufflen != 0) && (length_total == 0))
-		goto out;
-
-#ifdef ZFCP_STAT_REQSIZES
-	if (sbtype == SBAL_FLAGS0_TYPE_READ)
-		zfcp_statistics_inc(&zfcp_data.read_req_head, length_total);
-	else
-		zfcp_statistics_inc(&zfcp_data.write_req_head, length_total);
-#endif
-
-	buffere = &(req_q->buffer[buffer_index]->element[buffere_index]);
-	buffere->flags |= SBAL_FLAGS_LAST_ENTRY;
- out:
-	ZFCP_LOG_DEBUG("%i BUFFER(s) from %i to %i needed\n",
-		       fsf_req->sbal_count, fsf_req->sbal_index, buffer_index);
-	ZFCP_LOG_TRACE("total QDIO data buffer size is %i\n", length_total);
-
-	return length_total;
-}
-
 void
 zfcp_fsf_start_scsi_er_timer(struct zfcp_adapter *adapter)
 {
@@ -1293,4 +921,3 @@ static struct device_attribute *zfcp_sys
 };
 
 #undef ZFCP_LOG_AREA
-#undef ZFCP_LOG_AREA_PREFIX
--- diff/drivers/s390/scsi/zfcp_sysfs_adapter.c	2004-02-09 10:36:11.000000000 +0000
+++ source/drivers/s390/scsi/zfcp_sysfs_adapter.c	2004-02-23 13:56:45.000000000 +0000
@@ -5,7 +5,8 @@
  *
  * sysfs adapter related routines
  *
- * Copyright (C) 2003 IBM Entwicklung GmbH, IBM Corporation
+ * (C) Copyright IBM Corp. 2003, 2004
+ *
  * Authors:
  *      Martin Peschke <mpeschke@de.ibm.com>
  *	Heiko Carstens <heiko.carstens@de.ibm.com>
@@ -25,14 +26,13 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
-#define ZFCP_SYSFS_ADAPTER_C_REVISION "$Revision: 1.26 $"
+#define ZFCP_SYSFS_ADAPTER_C_REVISION "$Revision: 1.30 $"
 
 #include <asm/ccwdev.h>
 #include "zfcp_ext.h"
 #include "zfcp_def.h"
 
 #define ZFCP_LOG_AREA                   ZFCP_LOG_AREA_CONFIG
-#define ZFCP_LOG_AREA_PREFIX            ZFCP_LOG_AREA_PREFIX_CONFIG
 
 static const char fc_topologies[5][25] = {
 	{"<error>"},
@@ -66,12 +66,15 @@ ZFCP_DEFINE_ADAPTER_ATTR(status, "0x%08x
 ZFCP_DEFINE_ADAPTER_ATTR(wwnn, "0x%016llx\n", adapter->wwnn);
 ZFCP_DEFINE_ADAPTER_ATTR(wwpn, "0x%016llx\n", adapter->wwpn);
 ZFCP_DEFINE_ADAPTER_ATTR(s_id, "0x%06x\n", adapter->s_id);
-ZFCP_DEFINE_ADAPTER_ATTR(hw_version, "0x%04x\n", adapter->hydra_version);
+ZFCP_DEFINE_ADAPTER_ATTR(card_version, "0x%04x\n", adapter->hydra_version);
 ZFCP_DEFINE_ADAPTER_ATTR(lic_version, "0x%08x\n", adapter->fsf_lic_version);
 ZFCP_DEFINE_ADAPTER_ATTR(fc_link_speed, "%d Gb/s\n", adapter->fc_link_speed);
 ZFCP_DEFINE_ADAPTER_ATTR(fc_service_class, "%d\n", adapter->fc_service_class);
 ZFCP_DEFINE_ADAPTER_ATTR(fc_topology, "%s\n",
 			 fc_topologies[adapter->fc_topology]);
+ZFCP_DEFINE_ADAPTER_ATTR(hardware_version, "0x%08x\n",
+			 adapter->hardware_version);
+ZFCP_DEFINE_ADAPTER_ATTR(serial_number, "%17s\n", adapter->serial_number);
 
 /**
  * zfcp_sysfs_adapter_in_recovery_show - recovery state of adapter
@@ -259,11 +262,6 @@ zfcp_sysfs_adapter_failed_store(struct d
 		goto out;
 	}
 
-	/* restart error recovery only if adapter is online */
-	if (adapter->ccw_device->online != 1) {
-		retval = -ENXIO;
-		goto out;
-	}
 	zfcp_erp_modify_adapter_status(adapter, ZFCP_STATUS_COMMON_RUNNING,
 				       ZFCP_SET);
 	zfcp_erp_adapter_reopen(adapter, ZFCP_STATUS_COMMON_ERP_FAILED);
@@ -304,13 +302,15 @@ static struct attribute *zfcp_adapter_at
 	&dev_attr_wwnn.attr,
 	&dev_attr_wwpn.attr,
 	&dev_attr_s_id.attr,
-	&dev_attr_hw_version.attr,
+	&dev_attr_card_version.attr,
 	&dev_attr_lic_version.attr,
 	&dev_attr_fc_link_speed.attr,
 	&dev_attr_fc_service_class.attr,
 	&dev_attr_fc_topology.attr,
 	&dev_attr_scsi_host_no.attr,
 	&dev_attr_status.attr,
+	&dev_attr_hardware_version.attr,
+	&dev_attr_serial_number.attr,
 	NULL
 };
 
@@ -343,4 +343,3 @@ zfcp_sysfs_adapter_remove_files(struct d
 }
 
 #undef ZFCP_LOG_AREA
-#undef ZFCP_LOG_AREA_PREFIX
--- diff/drivers/s390/scsi/zfcp_sysfs_driver.c	2003-10-09 09:47:34.000000000 +0100
+++ source/drivers/s390/scsi/zfcp_sysfs_driver.c	2004-02-23 13:56:45.000000000 +0000
@@ -5,7 +5,8 @@
  *
  * sysfs driver related routines
  *
- * Copyright (C) 2003 IBM Entwicklung GmbH, IBM Corporation
+ * (C) Copyright IBM Corp. 2003, 2004
+ *
  * Authors:
  *      Martin Peschke <mpeschke@de.ibm.com>
  *	Heiko Carstens <heiko.carstens@de.ibm.com>
@@ -25,14 +26,13 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
-#define ZFCP_SYSFS_DRIVER_C_REVISION "$Revision: 1.8 $"
+#define ZFCP_SYSFS_DRIVER_C_REVISION "$Revision: 1.12 $"
 
 #include <asm/ccwdev.h>
 #include "zfcp_ext.h"
 #include "zfcp_def.h"
 
 #define ZFCP_LOG_AREA                   ZFCP_LOG_AREA_CONFIG
-#define ZFCP_LOG_AREA_PREFIX            ZFCP_LOG_AREA_PREFIX_CONFIG
 
 /**
  * ZFCP_DEFINE_DRIVER_ATTR - define for all loglevels sysfs attributes
@@ -67,7 +67,8 @@ static ssize_t zfcp_sysfs_loglevel_##_na
 static ssize_t zfcp_sysfs_loglevel_##_name##_show(struct device_driver *dev,  \
 						  char *buf)                  \
 {                                                                             \
-	return sprintf(buf,"%d\n", ZFCP_LOG_VALUE(ZFCP_LOG_AREA_##_define));  \
+	return sprintf(buf,"%d\n",				              \
+		       ZFCP_GET_LOG_VALUE(ZFCP_LOG_AREA_##_define));          \
 }                                                                             \
                                                                               \
 static DRIVER_ATTR(loglevel_##_name, S_IWUSR | S_IRUGO,                       \
@@ -83,6 +84,14 @@ ZFCP_DEFINE_DRIVER_ATTR(qdio, QDIO);
 ZFCP_DEFINE_DRIVER_ATTR(erp, ERP);
 ZFCP_DEFINE_DRIVER_ATTR(fc, FC);
 
+static ssize_t zfcp_sysfs_version_show(struct device_driver *dev,
+					      char *buf)
+{
+	return sprintf(buf, "%s\n", ZFCP_VERSION);
+}
+
+static DRIVER_ATTR(version, S_IRUGO, zfcp_sysfs_version_show, NULL);
+
 static struct attribute *zfcp_driver_attrs[] = {
 	&driver_attr_loglevel_other.attr,
 	&driver_attr_loglevel_scsi.attr,
@@ -92,6 +101,7 @@ static struct attribute *zfcp_driver_att
 	&driver_attr_loglevel_qdio.attr,
 	&driver_attr_loglevel_erp.attr,
 	&driver_attr_loglevel_fc.attr,
+	&driver_attr_version.attr,
 	NULL
 };
 
@@ -124,4 +134,3 @@ zfcp_sysfs_driver_remove_files(struct de
 }
 
 #undef ZFCP_LOG_AREA
-#undef ZFCP_LOG_AREA_PREFIX
--- diff/drivers/s390/scsi/zfcp_sysfs_port.c	2004-02-09 10:36:11.000000000 +0000
+++ source/drivers/s390/scsi/zfcp_sysfs_port.c	2004-02-23 13:56:45.000000000 +0000
@@ -5,7 +5,8 @@
  *
  * sysfs port related routines
  *
- * Copyright (C) 2003 IBM Entwicklung GmbH, IBM Corporation
+ * (C) Copyright IBM Corp. 2003, 2004
+ *
  * Authors:
  *      Martin Peschke <mpeschke@de.ibm.com>
  *	Heiko Carstens <heiko.carstens@de.ibm.com>
@@ -25,7 +26,7 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
-#define ZFCP_SYSFS_PORT_C_REVISION "$Revision: 1.32 $"
+#define ZFCP_SYSFS_PORT_C_REVISION "$Revision: 1.37 $"
 
 #include <linux/init.h>
 #include <linux/module.h>
@@ -34,7 +35,6 @@
 #include "zfcp_def.h"
 
 #define ZFCP_LOG_AREA                   ZFCP_LOG_AREA_CONFIG
-#define ZFCP_LOG_AREA_PREFIX            ZFCP_LOG_AREA_PREFIX_CONFIG
 
 /**
  * zfcp_sysfs_port_release - gets called when a struct device port is released
@@ -209,11 +209,6 @@ zfcp_sysfs_port_failed_store(struct devi
 		goto out;
 	}
 
-	/* restart error recovery only if adapter is online */
-	if (port->adapter->ccw_device->online != 1) {
-		retval = -ENXIO;
-		goto out;
-	}
 	zfcp_erp_modify_port_status(port, ZFCP_STATUS_COMMON_RUNNING, ZFCP_SET);
 	zfcp_erp_port_reopen(port, ZFCP_STATUS_COMMON_ERP_FAILED);
 	zfcp_erp_wait(port->adapter);
@@ -268,6 +263,10 @@ zfcp_sysfs_port_in_recovery_show(struct 
 static DEVICE_ATTR(in_recovery, S_IRUGO, zfcp_sysfs_port_in_recovery_show,
 		   NULL);
 
+/**
+ * zfcp_port_common_attrs
+ * sysfs attributes that are common for all kind of fc ports.
+ */
 static struct attribute *zfcp_port_common_attrs[] = {
 	&dev_attr_failed.attr,
 	&dev_attr_in_recovery.attr,
@@ -281,6 +280,10 @@ static struct attribute_group zfcp_port_
 	.attrs = zfcp_port_common_attrs,
 };
 
+/**
+ * zfcp_port_no_ns_attrs
+ * sysfs attributes not to be used for nameserver ports.
+ */
 static struct attribute *zfcp_port_no_ns_attrs[] = {
 	&dev_attr_unit_add.attr,
 	&dev_attr_unit_remove.attr,
@@ -330,4 +333,3 @@ zfcp_sysfs_port_remove_files(struct devi
 }
 
 #undef ZFCP_LOG_AREA
-#undef ZFCP_LOG_AREA_PREFIX
--- diff/drivers/s390/scsi/zfcp_sysfs_unit.c	2004-02-09 10:36:11.000000000 +0000
+++ source/drivers/s390/scsi/zfcp_sysfs_unit.c	2004-02-23 13:56:45.000000000 +0000
@@ -5,7 +5,8 @@
  *
  * sysfs unit related routines
  *
- * Copyright (C) 2003 IBM Entwicklung GmbH, IBM Corporation
+ * (C) Copyright IBM Corp. 2003, 2004
+ *
  * Authors:
  *      Martin Peschke <mpeschke@de.ibm.com>
  *	Heiko Carstens <heiko.carstens@de.ibm.com>
@@ -25,7 +26,7 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
-#define ZFCP_SYSFS_UNIT_C_REVISION "$Revision: 1.19 $"
+#define ZFCP_SYSFS_UNIT_C_REVISION "$Revision: 1.23 $"
 
 #include <linux/init.h>
 #include <linux/module.h>
@@ -34,7 +35,6 @@
 #include "zfcp_def.h"
 
 #define ZFCP_LOG_AREA                   ZFCP_LOG_AREA_CONFIG
-#define ZFCP_LOG_AREA_PREFIX            ZFCP_LOG_AREA_PREFIX_CONFIG
 
 /**
  * zfcp_sysfs_unit_release - gets called when a struct device unit is released
@@ -104,13 +104,9 @@ zfcp_sysfs_unit_failed_store(struct devi
 		goto out;
 	}
 
-	/* restart error recovery only if adapter is online */
-	if (unit->port->adapter->ccw_device->online != 1) {
-		retval = -ENXIO;
-		goto out;
-	}
 	zfcp_erp_modify_unit_status(unit, ZFCP_STATUS_COMMON_RUNNING, ZFCP_SET);
 	zfcp_erp_unit_reopen(unit, ZFCP_STATUS_COMMON_ERP_FAILED);
+	zfcp_erp_wait(unit->port->adapter);
  out:
 	up(&zfcp_data.config_sema);
 	return retval ? retval : count;
@@ -199,4 +195,3 @@ zfcp_sysfs_unit_remove_files(struct devi
 }
 
 #undef ZFCP_LOG_AREA
-#undef ZFCP_LOG_AREA_PREFIX
--- diff/drivers/sbus/char/aurora.c	2003-06-30 10:07:22.000000000 +0100
+++ source/drivers/sbus/char/aurora.c	2004-02-23 13:56:45.000000000 +0000
@@ -1752,8 +1752,9 @@ static void aurora_flush_buffer(struct t
 #endif
 }
 
-static int aurora_get_modem_info(struct Aurora_port * port, unsigned int *value)
+static int aurora_tiocmget(struct tty_struct *tty, struct file *file)
 {
+	struct Aurora_port *port = (struct Aurora_port *) tty->driver_data;
 	struct Aurora_board * bp;
 	unsigned char status,chip;
 	unsigned int result;
@@ -1762,6 +1763,9 @@ static int aurora_get_modem_info(struct 
 #ifdef AURORA_DEBUG
 	printk("aurora_get_modem_info: start\n");
 #endif
+	if ((aurora_paranoia_check(port, tty->name, __FUNCTION__))
+		return -ENODEV;
+
 	chip = AURORA_CD180(port_No(port));
 
 	bp = port_Board(port);
@@ -1782,16 +1786,16 @@ static int aurora_get_modem_info(struct 
 		| ((status & MSVR_DSR) ? TIOCM_DSR : 0)
 		| ((status & MSVR_CTS) ? TIOCM_CTS : 0);
 
-	put_user(result,(unsigned long *) value);
 #ifdef AURORA_DEBUG
 	printk("aurora_get_modem_info: end\n");
 #endif
-	return 0;
+	return result;
 }
 
-static int aurora_set_modem_info(struct Aurora_port * port, unsigned int cmd,
-				 unsigned int *value)
+static int aurora_tiocmset(struct tty_struct *tty, struct file *file,
+			   unsigned int set, unsigned int clear)
 {
+	struct Aurora_port *port = (struct Aurora_port *) tty->driver_data;
 	unsigned int arg;
 	unsigned long flags;
 	struct Aurora_board *bp = port_Board(port);
@@ -1800,33 +1804,20 @@ static int aurora_set_modem_info(struct 
 #ifdef AURORA_DEBUG
 	printk("aurora_set_modem_info: start\n");
 #endif
-	if (get_user(arg, value))
-		return -EFAULT;
+	if ((aurora_paranoia_check(port, tty->name, __FUNCTION__))
+		return -ENODEV;
+
 	chip = AURORA_CD180(port_No(port));
-	switch (cmd) {
-	 case TIOCMBIS: 
-		if (arg & TIOCM_RTS) 
-			port->MSVR |= bp->RTS;
-		if (arg & TIOCM_DTR)
-			port->MSVR |= bp->DTR;
-		break;
-	case TIOCMBIC:
-		if (arg & TIOCM_RTS)
-			port->MSVR &= ~bp->RTS;
-		if (arg & TIOCM_DTR)
-			port->MSVR &= ~bp->DTR;
-		break;
-	case TIOCMSET:
-		port->MSVR = (arg & TIOCM_RTS) ? (port->MSVR | bp->RTS) : 
-					         (port->MSVR & ~bp->RTS);
-		port->MSVR = (arg & TIOCM_DTR) ? (port->MSVR | bp->RTS) :
-						 (port->MSVR & ~bp->RTS);
-		break;
-	 default:
-		return -EINVAL;
-	};
 
 	save_flags(flags); cli();
+	if (set & TIOCM_RTS)
+		port->MSVR |= bp->RTS;
+	if (set & TIOCM_DTR)
+		port->MSVR |= bp->DTR;
+	if (clear & TIOCM_RTS)
+		port->MSVR &= ~bp->RTS;
+	if (clear & TIOCM_DTR)
+		port->MSVR &= ~bp->DTR;
 
 	sbus_writeb(port_No(port) & 7, &bp->r[chip]->r[CD180_CAR]);
 	udelay(1);
@@ -1993,16 +1984,6 @@ static int aurora_ioctl(struct tty_struc
 			((tty->termios->c_cflag & ~CLOCAL) |
 			 (arg ? CLOCAL : 0));
 		return 0;
-	case TIOCMGET:
-		retval = verify_area(VERIFY_WRITE, (void *) arg,
-				    sizeof(unsigned int));
-		if (retval)
-			return retval;
-		return aurora_get_modem_info(port, (unsigned int *) arg);
-	case TIOCMBIS:
-	case TIOCMBIC:
-	case TIOCMSET:
-		return aurora_set_modem_info(port, cmd, (unsigned int *) arg);
 	case TIOCGSERIAL:	
 		return aurora_get_serial_info(port, (struct serial_struct *) arg);
 	case TIOCSSERIAL:	
@@ -2268,6 +2249,8 @@ static struct tty_operations aurora_ops 
 	.stop = aurora_stop,
 	.start = aurora_start,
 	.hangup = aurora_hangup,
+	.tiocmget = aurora_tiocmget,
+	.tiocmset = aurora_tiocmset,
 };
 
 static int aurora_init_drivers(void)
--- diff/drivers/scsi/53c700.h	2004-02-18 08:54:11.000000000 +0000
+++ source/drivers/scsi/53c700.h	2004-02-23 13:56:45.000000000 +0000
@@ -37,7 +37,7 @@
 #define NCR_700_LUN_MASK		(NCR_700_MAX_LUNS - 1)
 /* Alter this with care: too many tags won't give the elevator a chance to
  * work; too few will cause the device to operate less efficiently */
-#define NCR_700_MAX_TAGS		16
+#define NCR_700_MAX_TAGS		4
 /* This is the default number of commands per LUN in the untagged case.
  * two is a good value because it means we can have one command active and
  * one command fully prepared and waiting
--- diff/drivers/scsi/Kconfig	2004-02-18 08:54:11.000000000 +0000
+++ source/drivers/scsi/Kconfig	2004-02-23 13:56:45.000000000 +0000
@@ -23,7 +23,7 @@ config SCSI
 
 config SCSI_PROC_FS
 	bool "legacy /proc/scsi/ support"
-	depends on SCSI
+	depends on SCSI && PROC_FS
 	default y
 	---help---
 	  This option enables support for the various files in
@@ -55,6 +55,14 @@ config BLK_DEV_SD
 	  In this case, do not compile the driver for your SCSI host adapter
 	  (below) as a module either.
 
+config MAX_SD_DISKS
+	int "Maximum number of SCSI disks to support (256-8192)"
+	depends on BLK_DEV_SD
+	default "256"
+	help
+	The maximum number SCSI disks to support. Default is 256.
+	Change this value if you want kernel to support lots of SCSI devices.
+
 config CHR_DEV_ST
 	tristate "SCSI tape support"
 	depends on SCSI
@@ -1267,29 +1275,10 @@ config SCSI_DC390T
 
 	  Note that this driver does NOT support Tekram DC390W/U/F, which are
 	  based on NCR/Symbios chips. Use "NCR53C8XX SCSI support" for those.
-	  Also note that there is another generic Am53C974 driver,
-	  "AM53/79C974 PCI SCSI support" below.  You can pick either one.
 
 	  To compile this driver as a module, choose M here: the
 	  module will be called tmscsim.
 
-config SCSI_DC390T_NOGENSUPP
-	bool "_omit_ support for non-DC390 adapters"
-	depends on SCSI_DC390T
-	---help---
-	  If you say N here, the DC390(T) SCSI driver relies on the DC390
-	  EEPROM to get initial values for its settings, such as speed,
-	  termination, etc.  If it can't find this EEPROM, it will use
-	  defaults or the user supplied boot/module parameters.  For details
-	  on driver configuration see <file:Documentation/scsi/tmscsim.txt>.
-
-	  If you say Y here and if no EEPROM is found, the driver gives up and
-	  thus only supports Tekram DC390(T) adapters.  This can be useful if
-	  you have a DC390(T) and another Am53C974 based adapter, which, for
-	  some reason, you want to drive with the other AM53C974 driver.
-
-	  If unsure, say N.
-
 config SCSI_T128
 	tristate "Trantor T128/T128F/T228 SCSI support"
 	depends on ISA && SCSI
--- diff/drivers/scsi/NCR5380.c	2003-09-30 15:46:17.000000000 +0100
+++ source/drivers/scsi/NCR5380.c	2004-02-23 13:56:45.000000000 +0000
@@ -1326,81 +1326,71 @@ static void NCR5380_main(void *p)
 static irqreturn_t NCR5380_intr(int irq, void *dev_id, struct pt_regs *regs) 
 {
 	NCR5380_local_declare();
-	struct Scsi_Host *instance;
+	struct Scsi_Host *instance = (struct Scsi_Host *)dev_id;
+	struct NCR5380_hostdata *hostdata = (struct NCR5380_hostdata *) instance->hostdata;
 	int done;
 	unsigned char basr;
-	struct NCR5380_hostdata *hostdata;
-	int handled = 0;
 
 	dprintk(NDEBUG_INTR, ("scsi : NCR5380 irq %d triggered\n", irq));
 
 	do {
 		done = 1;
-		/* The instance list is constant while the driver is
-		   loaded */
-		for (hostdata = first_host; hostdata != NULL; hostdata = hostdata->next)
-		{
-			instance = hostdata->host;
-			if (instance->irq == irq) {
-				handled = 1;
-				spin_lock_irq(instance->host_lock);
-				/* Look for pending interrupts */
-				NCR5380_setup(instance);
-				basr = NCR5380_read(BUS_AND_STATUS_REG);
-				/* XXX dispatch to appropriate routine if found and done=0 */
-				if (basr & BASR_IRQ) {
-					NCR5380_dprint(NDEBUG_INTR, instance);
-					if ((NCR5380_read(STATUS_REG) & (SR_SEL | SR_IO)) == (SR_SEL | SR_IO)) {
-						done = 0;
-						dprintk(NDEBUG_INTR, ("scsi%d : SEL interrupt\n", instance->host_no));
-						NCR5380_reselect(instance);
-						(void) NCR5380_read(RESET_PARITY_INTERRUPT_REG);
-					} else if (basr & BASR_PARITY_ERROR) {
-						dprintk(NDEBUG_INTR, ("scsi%d : PARITY interrupt\n", instance->host_no));
-						(void) NCR5380_read(RESET_PARITY_INTERRUPT_REG);
-					} else if ((NCR5380_read(STATUS_REG) & SR_RST) == SR_RST) {
-						dprintk(NDEBUG_INTR, ("scsi%d : RESET interrupt\n", instance->host_no));
-						(void) NCR5380_read(RESET_PARITY_INTERRUPT_REG);
-					} else {
+		spin_lock_irq(instance->host_lock);
+		/* Look for pending interrupts */
+		NCR5380_setup(instance);
+		basr = NCR5380_read(BUS_AND_STATUS_REG);
+		/* XXX dispatch to appropriate routine if found and done=0 */
+		if (basr & BASR_IRQ) {
+			NCR5380_dprint(NDEBUG_INTR, instance);
+			if ((NCR5380_read(STATUS_REG) & (SR_SEL | SR_IO)) == (SR_SEL | SR_IO)) {
+				done = 0;
+				dprintk(NDEBUG_INTR, ("scsi%d : SEL interrupt\n", instance->host_no));
+				NCR5380_reselect(instance);
+				(void) NCR5380_read(RESET_PARITY_INTERRUPT_REG);
+			} else if (basr & BASR_PARITY_ERROR) {
+				dprintk(NDEBUG_INTR, ("scsi%d : PARITY interrupt\n", instance->host_no));
+				(void) NCR5380_read(RESET_PARITY_INTERRUPT_REG);
+			} else if ((NCR5380_read(STATUS_REG) & SR_RST) == SR_RST) {
+				dprintk(NDEBUG_INTR, ("scsi%d : RESET interrupt\n", instance->host_no));
+				(void) NCR5380_read(RESET_PARITY_INTERRUPT_REG);
+			} else {
 #if defined(REAL_DMA)
-						/*
-						 * We should only get PHASE MISMATCH and EOP interrupts
-						 * if we have DMA enabled, so do a sanity check based on
-						 * the current setting of the MODE register.
-						 */
+				/*
+				 * We should only get PHASE MISMATCH and EOP interrupts
+				 * if we have DMA enabled, so do a sanity check based on
+				 * the current setting of the MODE register.
+				 */
 
-						if ((NCR5380_read(MODE_REG) & MR_DMA) && ((basr & BASR_END_DMA_TRANSFER) || !(basr & BASR_PHASE_MATCH))) {
-							int transfered;
+				if ((NCR5380_read(MODE_REG) & MR_DMA) && ((basr & BASR_END_DMA_TRANSFER) || !(basr & BASR_PHASE_MATCH))) {
+					int transfered;
 
-							if (!hostdata->connected)
-								panic("scsi%d : received end of DMA interrupt with no connected cmd\n", instance->hostno);
+					if (!hostdata->connected)
+						panic("scsi%d : received end of DMA interrupt with no connected cmd\n", instance->hostno);
 
-							transfered = (hostdata->dmalen - NCR5380_dma_residual(instance));
-							hostdata->connected->SCp.this_residual -= transferred;
-							hostdata->connected->SCp.ptr += transferred;
-							hostdata->dmalen = 0;
+					transfered = (hostdata->dmalen - NCR5380_dma_residual(instance));
+					hostdata->connected->SCp.this_residual -= transferred;
+					hostdata->connected->SCp.ptr += transferred;
+					hostdata->dmalen = 0;
 
-							(void) NCR5380_read(RESET_PARITY_INTERRUPT_REG);
+					(void) NCR5380_read(RESET_PARITY_INTERRUPT_REG);
 							
-							/* FIXME: we need to poll briefly then defer a workqueue task ! */
-							NCR5380_poll_politely(hostdata, BUS_AND_STATUS_REG, BASR_ACK, 0, 2*HZ);
+					/* FIXME: we need to poll briefly then defer a workqueue task ! */
+					NCR5380_poll_politely(hostdata, BUS_AND_STATUS_REG, BASR_ACK, 0, 2*HZ);
 
-							NCR5380_write(MODE_REG, MR_BASE);
-							NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
-						}
+					NCR5380_write(MODE_REG, MR_BASE);
+					NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
+				}
 #else
-						dprintk(NDEBUG_INTR, ("scsi : unknown interrupt, BASR 0x%X, MR 0x%X, SR 0x%x\n", basr, NCR5380_read(MODE_REG), NCR5380_read(STATUS_REG)));
-						(void) NCR5380_read(RESET_PARITY_INTERRUPT_REG);
+				dprintk(NDEBUG_INTR, ("scsi : unknown interrupt, BASR 0x%X, MR 0x%X, SR 0x%x\n", basr, NCR5380_read(MODE_REG), NCR5380_read(STATUS_REG)));
+				(void) NCR5380_read(RESET_PARITY_INTERRUPT_REG);
 #endif
-					}
-				}	/* if BASR_IRQ */
-				spin_unlock_irq(instance->host_lock);
-				if(!done)
-					schedule_work(&hostdata->coroutine);
-			}	/* if (instance->irq == irq) */
-		}
+			}
+		}	/* if BASR_IRQ */
+		spin_unlock_irq(instance->host_lock);
+		if(!done)
+			schedule_work(&hostdata->coroutine);
 	} while (!done);
-	return IRQ_RETVAL(handled);
+	return IRQ_HANDLED;
 }
 
 #endif 
--- diff/drivers/scsi/NCR53C9x.c	2003-11-25 15:24:58.000000000 +0000
+++ source/drivers/scsi/NCR53C9x.c	2004-02-23 13:56:45.000000000 +0000
@@ -3615,6 +3615,27 @@ out:
 }
 #endif
 
+int esp_slave_alloc(Scsi_Device *SDptr)
+{
+	struct esp_device *esp_dev =
+		kmalloc(sizeof(struct esp_device), GFP_ATOMIC);
+
+	if (!esp_dev)
+		return -ENOMEM;
+	memset(esp_dev, 0, sizeof(struct esp_device));
+	SDptr->hostdata = esp_dev;
+	return 0;
+}
+
+void esp_slave_destroy(Scsi_Device *SDptr)
+{
+	struct NCR_ESP *esp = (struct NCR_ESP *) SDptr->host->hostdata;
+
+	esp->targets_present &= ~(1 << SDptr->id);
+	kfree(SDptr->hostdata);
+	SDptr->hostdata = NULL;
+}
+
 #ifdef MODULE
 int init_module(void) { return 0; }
 void cleanup_module(void) {}
--- diff/drivers/scsi/NCR53C9x.h	2004-02-09 10:36:11.000000000 +0000
+++ source/drivers/scsi/NCR53C9x.h	2004-02-23 13:56:45.000000000 +0000
@@ -665,4 +665,6 @@ extern int esp_abort(Scsi_Cmnd *);
 extern int esp_reset(Scsi_Cmnd *);
 extern int esp_proc_info(struct Scsi_Host *shost, char *buffer, char **start, off_t offset, int length,
 			 int inout);
+extern int esp_slave_alloc(Scsi_Device *);
+extern void esp_slave_destroy(Scsi_Device *);
 #endif /* !(NCR53C9X_H) */
--- diff/drivers/scsi/aacraid/Makefile	2002-12-16 09:26:06.000000000 +0000
+++ source/drivers/scsi/aacraid/Makefile	2004-02-23 13:56:45.000000000 +0000
@@ -3,6 +3,6 @@
 obj-$(CONFIG_SCSI_AACRAID) := aacraid.o
 
 aacraid-objs	:= linit.o aachba.o commctrl.o comminit.o commsup.o \
-		   dpcsup.o rx.o sa.o
+		   dpcsup.o rx.o sa.o rkt.o
 
 EXTRA_CFLAGS	:= -Idrivers/scsi
--- diff/drivers/scsi/aacraid/aacraid.h	2004-02-09 10:36:11.000000000 +0000
+++ source/drivers/scsi/aacraid/aacraid.h	2004-02-23 13:56:45.000000000 +0000
@@ -512,6 +512,7 @@ struct adapter_ops
 	void (*adapter_enable_int)(struct aac_dev *dev, u32 event);
 	void (*adapter_disable_int)(struct aac_dev *dev, u32 event);
 	int  (*adapter_sync_cmd)(struct aac_dev *dev, u32 command, u32 p1, u32 *status);
+	int  (*adapter_check_health)(struct aac_dev *dev);
 };
 
 /*
@@ -713,6 +714,24 @@ struct rx_registers {
 #define rx_writeb(AEP, CSR, value)	writeb(value, &((AEP)->regs.rx->CSR))
 #define rx_writel(AEP, CSR, value)	writel(value, &((AEP)->regs.rx->CSR))
 
+/*
+ *	Rkt Message Unit Registers (same as Rx, except a larger reserve region)
+ */
+
+#define rkt_mu_registers rx_mu_registers
+#define rkt_inbound rx_inbound
+
+struct rkt_registers {
+	struct rkt_mu_registers		MUnit;		 /* 1300h - 1334h */
+	u32				reserved1[1010]; /* 1338h - 22fch */
+	struct rkt_inbound		IndexRegs;	 /* 2300h - */
+};
+
+#define rkt_readb(AEP, CSR)		readb(&((AEP)->regs.rkt->CSR))
+#define rkt_readl(AEP, CSR)		readl(&((AEP)->regs.rkt->CSR))
+#define rkt_writeb(AEP, CSR, value)	writeb(value, &((AEP)->regs.rkt->CSR))
+#define rkt_writel(AEP, CSR, value)	writel(value, &((AEP)->regs.rkt->CSR))
+
 struct fib;
 
 typedef void (*fib_callback)(void *ctxt, struct fib *fibctx);
@@ -889,7 +908,9 @@ struct aac_dev
 	{
 		struct sa_registers *sa;
 		struct rx_registers *rx;
+		struct rkt_registers *rkt;
 	} regs;
+	u32			OIMR; /* Mask Register Cache */
 	/*
 	 *	The following is the number of the individual adapter
 	 */
@@ -922,6 +943,8 @@ struct aac_dev
 #define aac_adapter_disable_int(dev, event) \
 	dev->a_ops.adapter_disable_int(dev, event)
 
+#define aac_adapter_check_health(dev) \
+	(dev)->a_ops.adapter_check_health(dev)
 
 
 #define FIB_CONTEXT_FLAG_TIMED_OUT		(0x00000001)
@@ -1492,6 +1515,7 @@ int aac_scsi_cmd(struct scsi_cmnd *cmd);
 int aac_dev_ioctl(struct aac_dev *dev, int cmd, void *arg);
 int aac_do_ioctl(struct aac_dev * dev, int cmd, void *arg);
 int aac_rx_init(struct aac_dev *dev, unsigned long devNumber);
+int aac_rkt_init(struct aac_dev *dev, unsigned long devNumber);
 int aac_sa_init(struct aac_dev *dev, unsigned long devNumber);
 unsigned int aac_response_normal(struct aac_queue * q);
 unsigned int aac_command_normal(struct aac_queue * q);
--- diff/drivers/scsi/aacraid/linit.c	2004-02-09 10:36:11.000000000 +0000
+++ source/drivers/scsi/aacraid/linit.c	2004-02-23 13:56:45.000000000 +0000
@@ -49,6 +49,7 @@
 #include <scsi/scsi_host.h>
 #include <scsi/scsi_tcq.h>
 #include <scsi/scsicam.h>
+#include <scsi/scsi_eh.h>
 
 #include "aacraid.h"
 
@@ -101,14 +102,20 @@ static struct pci_device_id aac_pci_tbl[
 	{ 0x9005, 0x0285, 0x9005, 0x028a, 0, 0, 18 }, /* ASR-2020S PCI-X ZCR (Skyhawk)*/
 	{ 0x9005, 0x0285, 0x9005, 0x028b, 0, 0, 19 }, /* ASR-2020S SO-DIMM PCI-X ZCR(Terminator)*/
 	{ 0x9005, 0x0285, 0x9005, 0x0290, 0, 0, 20 }, /* AAR-2410SA PCI SATA 4ch (Jaguar II)*/
-	{ 0x9005, 0x0250, 0x1014, 0x0279, 0, 0, 21 }, /* (Marco)*/
-	{ 0x9005, 0x0250, 0x1014, 0x028c, 0, 0, 22 }, /* (Sebring)*/
 
-	{ 0x9005, 0x0285, 0x1028, 0x0287, 0, 0, 23 }, /* Perc 320/DC*/
-	{ 0x1011, 0x0046, 0x9005, 0x0365, 0, 0, 24 }, /* Adaptec 5400S (Mustang)*/
-	{ 0x1011, 0x0046, 0x9005, 0x0364, 0, 0, 25 }, /* Adaptec 5400S (Mustang)*/
-	{ 0x1011, 0x0046, 0x9005, 0x1364, 0, 0, 26 }, /* Dell PERC2 "Quad Channel" */
-	{ 0x1011, 0x0046, 0x103c, 0x10c2, 0, 0, 27 }, /* HP NetRAID-4M */
+	{ 0x9005, 0x0285, 0x1028, 0x0287, 0, 0, 21 }, /* Perc 320/DC*/
+	{ 0x1011, 0x0046, 0x9005, 0x0365, 0, 0, 22 }, /* Adaptec 5400S (Mustang)*/
+	{ 0x1011, 0x0046, 0x9005, 0x0364, 0, 0, 23 }, /* Adaptec 5400S (Mustang)*/
+	{ 0x1011, 0x0046, 0x9005, 0x1364, 0, 0, 24 }, /* Dell PERC2 "Quad Channel" */
+	{ 0x1011, 0x0046, 0x103c, 0x10c2, 0, 0, 25 }, /* HP NetRAID-4M */
+
+	{ 0x9005, 0x0285, 0x1028, 0x0291, 0, 0, 26 }, /* CERC SATA RAID 2 PCI SATA 6ch (DellCorsair) */
+	{ 0x9005, 0x0285, 0x9005, 0x0292, 0, 0, 27 }, /* AAR-2810SA PCI SATA 8ch (Corsair-8) */
+	{ 0x9005, 0x0285, 0x9005, 0x0293, 0, 0, 28 }, /* AAR-21610SA PCI SATA 16ch (Corsair-16) */
+	{ 0x9005, 0x0285, 0x9005, 0x0294, 0, 0, 29 }, /* ESD SO-DIMM PCI-X SATA ZCR (Prowler) */
+	{ 0x9005, 0x0285, 0x0E11, 0x0295, 0, 0, 30 }, /* SATA 6Ch (Bearcat) */
+
+	{ 0x9005, 0x0286, 0x9005, 0x028c, 0, 0, 31 }, /* ASR-2230S + ASR-2230SLP PCI-X (Lancer) */
 	{ 0,}
 };
 MODULE_DEVICE_TABLE(pci, aac_pci_tbl);
@@ -141,14 +148,20 @@ static struct aac_driver_ident aac_drive
 	{ aac_rx_init, "aacraid",  "ADAPTEC ", "ASR-2020S PCI-X ", 2 }, /* ASR-2020S PCI-X ZCR (Skyhawk)*/
 	{ aac_rx_init, "aacraid",  "ADAPTEC ", "ASR-2020S PCI-X ", 2 }, /* ASR-2020S SO-DIMM PCI-X ZCR(Terminator)*/
 	{ aac_rx_init, "aacraid",  "ADAPTEC ", "AAR-2410SA SATA ", 2 }, /* AAR-2410SA PCI SATA 4ch (Jaguar II)*/
-	{ aac_rx_init, "aacraid",  "ADAPTEC ", "Adaptec         ", 2 }, /* (Marco)*/
-	{ aac_rx_init, "aacraid",  "ADAPTEC ", "Adaptec         ", 2 }, /* (Sebring)*/
 
 	{ aac_rx_init, "percraid", "DELL    ", "PERC 320/DC     ", 2, AAC_QUIRK_31BIT }, /* Perc 320/DC*/
 	{ aac_sa_init, "aacraid",  "ADAPTEC ", "Adaptec 5400S   ", 4 }, /* Adaptec 5400S (Mustang)*/
 	{ aac_sa_init, "aacraid",  "ADAPTEC ", "AAC-364         ", 4 }, /* Adaptec 5400S (Mustang)*/
 	{ aac_sa_init, "percraid", "DELL    ", "PERCRAID        ", 4, AAC_QUIRK_31BIT }, /* Dell PERC2 "Quad Channel" */
-	{ aac_sa_init, "hpnraid",  "HP      ", "NetRAID         ", 4 }  /* HP NetRAID-4M */
+	{ aac_sa_init, "hpnraid",  "HP      ", "NetRAID         ", 4 },  /* HP NetRAID-4M */
+
+	{ aac_rx_init, "aacraid",  "DELL    ", "CERC SR2        ", 1 }, /* CERC SATA RAID 2 PCI SATA 6ch (DellCorsair) */
+	{ aac_rx_init, "aacraid",  "ADAPTEC ", "AAR-2810SA SATA ", 1 }, /* AAR-2810SA PCI SATA 8ch (Corsair-8) */
+	{ aac_rx_init, "aacraid",  "ADAPTEC ", "AAR-21610SA SATA", 1 }, /* AAR-21610SA PCI SATA 16ch (Corsair-16) */
+	{ aac_rx_init, "aacraid",  "ADAPTEC ", "SO-DIMM SATA ZCR", 1 }, /* ESD SO-DIMM PCI-X SATA ZCR (Prowler) */
+	{ aac_rx_init, "aacraid",  "ADAPTEC ", "SATA 6Channel   ", 1 }, /* SATA 6Ch (Bearcat) */
+
+	{ aac_rkt_init,"aacraid",  "ADAPTEC ", "ASR-2230S PCI-X ", 2 }, /* ASR-2230S + ASR-2230SLP PCI-X (Lancer) */
 };
 
 /**
@@ -327,6 +340,51 @@ static int aac_eh_abort(struct scsi_cmnd
 	return FAILED;
 }
 
+/*
+ *	aac_eh_reset	- Reset command handling
+ *	@scsi_cmd:	SCSI command block causing the reset
+ *
+ */
+static int aac_eh_reset(struct scsi_cmnd* cmd)
+{
+	struct scsi_device * dev = cmd->device;
+	struct Scsi_Host * host = dev->host;
+	struct scsi_cmnd * command;
+	int count;
+	unsigned long flags;
+
+	printk(KERN_ERR "%s: Host adapter reset request. SCSI hang ?\n", 
+					AAC_DRIVERNAME);
+
+
+	if (aac_adapter_check_health((struct aac_dev *)host->hostdata)) {
+		printk(KERN_ERR "%s: Host adapter appears dead\n", 
+				AAC_DRIVERNAME);
+		return -ENODEV;
+	}
+	/*
+	 * Wait for all commands to complete to this specific
+	 * target (block maximum 60 seconds).
+	 */
+	for (count = 60; count; --count) {
+		__shost_for_each_device(dev, host) {
+			spin_lock_irqsave(&dev->list_lock, flags);
+			list_for_each_entry(command, &dev->cmd_list, list) {
+				if (command->serial_number) {
+					spin_unlock_irqrestore(&dev->list_lock, flags);
+					return SUCCESS;
+				}
+			}
+			spin_unlock_irqrestore(&dev->list_lock, flags);
+		}
+		spin_unlock_irq(host->host_lock);
+		scsi_sleep(HZ);
+		spin_lock_irq(host->host_lock);
+	}
+	printk(KERN_ERR "%s: SCSI bus appears hung\n", AAC_DRIVERNAME);
+	return -ETIMEDOUT;
+}
+
 /**
  *	aac_cfg_open		-	open a configuration file
  *	@inode: inode being opened
@@ -385,6 +443,7 @@ static struct scsi_host_template aac_dri
 	.bios_param     		= aac_biosparm,	
 	.slave_configure		= aac_slave_configure,
 	.eh_abort_handler		= aac_eh_abort,
+	.eh_host_reset_handler		= aac_eh_reset,
 	.can_queue      		= AAC_NUM_IO_FIB,	
 	.this_id        		= 16,
 	.sg_tablesize   		= 16,
--- diff/drivers/scsi/aacraid/rx.c	2004-01-19 10:22:58.000000000 +0000
+++ source/drivers/scsi/aacraid/rx.c	2004-02-23 13:56:45.000000000 +0000
@@ -56,7 +56,7 @@ static irqreturn_t aac_rx_intr(int irq, 
 	 *	This allows us to only service interrupts that have 
 	 *	been enabled.
 	 */
-	mask = ~(rx_readb(dev, MUnit.OIMR));
+	mask = ~(dev->OIMR);
 	/* Check to see if this is our interrupt.  If it isn't just return */
 	if (intstat & mask) 
 	{
@@ -179,7 +179,7 @@ static int rx_sync_cmd(struct aac_dev *d
 	/*
 	 *	Disable doorbell interrupts
 	 */
-	rx_writeb(dev, MUnit.OIMR, rx_readb(dev, MUnit.OIMR) | 0x04);
+	rx_writeb(dev, MUnit.OIMR, dev->OIMR |= 0x04);
 	/*
 	 *	Force the completion of the mask register write before issuing
 	 *	the interrupt.
@@ -220,7 +220,7 @@ static int rx_sync_cmd(struct aac_dev *d
 		/*
 		 *	Restore interrupt mask even though we timed out
 		 */
-		rx_writeb(dev, MUnit.OIMR, rx_readl(dev, MUnit.OIMR) & 0xfb);
+		rx_writeb(dev, MUnit.OIMR, dev->OIMR &= 0xfb);
 		return -ETIMEDOUT;
 	}
 	/*
@@ -234,7 +234,7 @@ static int rx_sync_cmd(struct aac_dev *d
 	/*
 	 *	Restore interrupt mask
 	 */
-	rx_writeb(dev, MUnit.OIMR, rx_readl(dev, MUnit.OIMR) & 0xfb);
+	rx_writeb(dev, MUnit.OIMR, dev->OIMR &= 0xfb);
 	return 0;
 
 }
@@ -318,13 +318,45 @@ static void aac_rx_start_adapter(struct 
 	rx_writeb(dev, MUnit.OIMR, 0xff);
 	rx_writel(dev, MUnit.ODR, 0xffffffff);
 //	rx_writeb(dev, MUnit.OIMR, ~(u8)OUTBOUND_DOORBELL_INTERRUPT_MASK);
-	rx_writeb(dev, MUnit.OIMR, 0xfb);
+	rx_writeb(dev, MUnit.OIMR, dev->OIMR = 0xfb);
 
 	// We can only use a 32 bit address here
 	rx_sync_cmd(dev, INIT_STRUCT_BASE_ADDRESS, (u32)(ulong)dev->init_pa, &status);
 }
 
 /**
+ *	aac_rx_check_health
+ *	@dev: device to check if healthy
+ *
+ *	Will attempt to determine if the specified adapter is alive and
+ *	capable of handling requests, returning 0 if alive.
+ */
+static int aac_rx_check_health(struct aac_dev *dev)
+{
+	long status = rx_readl(dev, IndexRegs.Mailbox[7]);
+
+	/*
+	 *	Check to see if the board failed any self tests.
+	 */
+	if (status & SELF_TEST_FAILED)
+		return -1;
+	/*
+	 *	Check to see if the board panic'd while booting.
+	 */
+	if (status & KERNEL_PANIC)
+		return -2;
+	/*
+	 *	Wait for the adapter to be up and running. Wait up to 3 minutes
+	 */
+	if (!(status & KERNEL_UP_AND_RUNNING))
+		return -3;
+	/*
+	 *	Everything is OK
+	 */
+	return 0;
+} /* aac_rx_check_health */
+
+/**
  *	aac_rx_init	-	initialize an i960 based AAC card
  *	@dev: device to configure
  *	@devnum: adapter number
--- diff/drivers/scsi/aacraid/sa.c	2004-01-19 10:22:58.000000000 +0000
+++ source/drivers/scsi/aacraid/sa.c	2004-02-23 13:56:45.000000000 +0000
@@ -300,6 +300,38 @@ static void aac_sa_start_adapter(struct 
 }
 
 /**
+ *	aac_sa_check_health
+ *	@dev: device to check if healthy
+ *
+ *	Will attempt to determine if the specified adapter is alive and
+ *	capable of handling requests, returning 0 if alive.
+ */
+static int aac_sa_check_health(struct aac_dev *dev)
+{
+	long status = sa_readl(dev, Mailbox7);
+
+	/*
+	 *	Check to see if the board failed any self tests.
+	 */
+	if (status & SELF_TEST_FAILED)
+		return -1;
+	/*
+	 *	Check to see if the board panic'd while booting.
+	 */
+	if (status & KERNEL_PANIC)
+		return -2;
+	/*
+	 *	Wait for the adapter to be up and running. Wait up to 3 minutes
+	 */
+	if (!(status & KERNEL_UP_AND_RUNNING))
+		return -3;
+	/*
+	 *	Everything is OK
+	 */
+	return 0;
+} /* aac_sa_check_health */
+
+/**
  *	aac_sa_init	-	initialize an ARM based AAC card
  *	@dev: device to configure
  *	@devnum: adapter number
--- diff/drivers/scsi/aic7xxx/aic79xx_osm.c	2004-02-09 10:36:11.000000000 +0000
+++ source/drivers/scsi/aic7xxx/aic79xx_osm.c	2004-02-23 13:56:45.000000000 +0000
@@ -452,14 +452,14 @@ MODULE_PARM_DESC(aic79xx,
 "	seltime:<int>		Selection Timeout:\n"
 "				(0/256ms,1/128ms,2/64ms,3/32ms)\n"
 "\n"
-"	Sample /etc/modules.conf line:\n"
+"	Sample /etc/modprobe.conf line:\n"
 "		Enable verbose logging\n"
 "		Set tag depth on Controller 2/Target 2 to 10 tags\n"
 "		Shorten the selection timeout to 128ms\n"
 "\n"
 "	options aic79xx 'aic79xx=verbose.tag_info:{{}.{}.{..10}}.seltime:1'\n"
 "\n"
-"	Sample /etc/modules.conf line:\n"
+"	Sample /etc/modprobe.conf line:\n"
 "		Change Read Streaming for Controller's 2 and 3\n"
 "\n"
 "	options aic79xx 'aic79xx=rd_strm:{..0xFFF0.0xC0F0}'");
--- diff/drivers/scsi/aic7xxx/aic7xxx_osm.c	2004-02-09 10:36:11.000000000 +0000
+++ source/drivers/scsi/aic7xxx/aic7xxx_osm.c	2004-02-23 13:56:45.000000000 +0000
@@ -472,7 +472,7 @@ MODULE_PARM_DESC(aic7xxx,
 "	seltime:<int>		Selection Timeout\n"
 "				(0/256ms,1/128ms,2/64ms,3/32ms)\n"
 "\n"
-"	Sample /etc/modules.conf line:\n"
+"	Sample /etc/modprobe.conf line:\n"
 "		Toggle EISA/VLB probing\n"
 "		Set tag depth on Controller 1/Target 1 to 10 tags\n"
 "		Shorten the selection timeout to 128ms\n"
@@ -3969,11 +3969,10 @@ ahc_linux_alloc_device(struct ahc_softc 
 }
 
 static void
-ahc_linux_free_device(struct ahc_softc *ahc, struct ahc_linux_device *dev)
+__ahc_linux_free_device(struct ahc_softc *ahc, struct ahc_linux_device *dev)
 {
 	struct ahc_linux_target *targ;
 
-	del_timer_sync(&dev->timer);
 	targ = dev->target;
 	targ->devices[dev->lun] = NULL;
 	free(dev, M_DEVBUF);
@@ -3983,6 +3982,13 @@ ahc_linux_free_device(struct ahc_softc *
 		ahc_linux_free_target(ahc, targ);
 }
 
+static void
+ahc_linux_free_device(struct ahc_softc *ahc, struct ahc_linux_device *dev)
+{
+	del_timer_sync(&dev->timer);
+	__ahc_linux_free_device(ahc, dev);
+}
+
 void
 ahc_send_async(struct ahc_softc *ahc, char channel,
 	       u_int target, u_int lun, ac_code code, void *arg)
@@ -4693,7 +4699,7 @@ ahc_linux_dev_timed_unfreeze(u_long arg)
 		ahc_linux_run_device_queue(ahc, dev);
 	if (TAILQ_EMPTY(&dev->busyq)
 	 && dev->active == 0)
-		ahc_linux_free_device(ahc, dev);
+		__ahc_linux_free_device(ahc, dev);
 	ahc_unlock(ahc, &s);
 }
 
--- diff/drivers/scsi/blz1230.c	2003-08-20 14:16:12.000000000 +0100
+++ source/drivers/scsi/blz1230.c	2004-02-23 13:56:45.000000000 +0000
@@ -333,6 +333,8 @@ static Scsi_Host_Template driver_templat
 	.proc_info		= esp_proc_info,
 	.name			= "Blizzard1230 SCSI IV",
 	.detect			= blz1230_esp_detect,
+	.slave_alloc		= esp_slave_alloc,
+	.slave_destroy		= esp_slave_destroy,
 	.release		= blz1230_esp_release,
 	.queuecommand		= esp_queue,
 	.eh_abort_handler	= esp_abort,
--- diff/drivers/scsi/blz2060.c	2003-08-20 14:16:12.000000000 +0100
+++ source/drivers/scsi/blz2060.c	2004-02-23 13:56:45.000000000 +0000
@@ -287,6 +287,8 @@ static Scsi_Host_Template driver_templat
 	.proc_info		= esp_proc_info,
 	.name			= "Blizzard2060 SCSI",
 	.detect			= blz2060_esp_detect,
+	.slave_alloc		= esp_slave_alloc,
+	.slave_destroy		= esp_slave_destroy,
 	.release		= blz2060_esp_release,
 	.queuecommand		= esp_queue,
 	.eh_abort_handler	= esp_abort,
--- diff/drivers/scsi/cyberstorm.c	2003-08-20 14:16:12.000000000 +0100
+++ source/drivers/scsi/cyberstorm.c	2004-02-23 13:56:45.000000000 +0000
@@ -358,6 +358,8 @@ static Scsi_Host_Template driver_templat
 	.proc_info		= esp_proc_info,
 	.name			= "CyberStorm SCSI",
 	.detect			= cyber_esp_detect,
+	.slave_alloc		= esp_slave_alloc,
+	.slave_destroy		= esp_slave_destroy,
 	.release		= cyber_esp_release,
 	.queuecommand		= esp_queue,
 	.eh_abort_handler	= esp_abort,
--- diff/drivers/scsi/cyberstormII.c	2003-08-20 14:16:12.000000000 +0100
+++ source/drivers/scsi/cyberstormII.c	2004-02-23 13:56:45.000000000 +0000
@@ -295,6 +295,8 @@ static Scsi_Host_Template driver_templat
 	.proc_info		= esp_proc_info,
 	.name			= "CyberStorm Mk II SCSI",
 	.detect			= cyberII_esp_detect,
+	.slave_alloc		= esp_slave_alloc,
+	.slave_destroy		= esp_slave_destroy,
 	.release		= cyberII_esp_release,
 	.queuecommand		= esp_queue,
 	.eh_abort_handler	= esp_abort,
--- diff/drivers/scsi/dec_esp.c	2003-08-20 14:16:12.000000000 +0100
+++ source/drivers/scsi/dec_esp.c	2004-02-23 13:56:45.000000000 +0000
@@ -124,6 +124,8 @@ static Scsi_Host_Template driver_templat
 	.proc_info		= &esp_proc_info,
 	.name			= "NCR53C94",
 	.detect			= dec_esp_detect,
+	.slave_alloc		= esp_slave_alloc,
+	.slave_destroy		= esp_slave_destroy,
 	.release		= dec_esp_release,
 	.info			= esp_info,
 	.queuecommand		= esp_queue,
--- diff/drivers/scsi/fastlane.c	2003-08-20 14:16:12.000000000 +0100
+++ source/drivers/scsi/fastlane.c	2004-02-23 13:56:45.000000000 +0000
@@ -404,6 +404,8 @@ static Scsi_Host_Template driver_templat
 	.proc_info		= esp_proc_info,
 	.name			= "Fastlane SCSI",
 	.detect			= fastlane_esp_detect,
+	.slave_alloc		= esp_slave_alloc,
+	.slave_destroy		= esp_slave_destroy,
 	.release		= fastlane_esp_release,
 	.queuecommand		= esp_queue,
 	.eh_abort_handler	= esp_abort,
--- diff/drivers/scsi/g_NCR5380.c	2004-02-09 10:36:11.000000000 +0000
+++ source/drivers/scsi/g_NCR5380.c	2004-02-23 13:56:45.000000000 +0000
@@ -450,7 +450,7 @@ int __init generic_NCR5380_detect(Scsi_H
 			instance->irq = NCR5380_probe_irq(instance, 0xffff);
 
 		if (instance->irq != SCSI_IRQ_NONE)
-			if (request_irq(instance->irq, generic_NCR5380_intr, SA_INTERRUPT, "NCR5380", NULL)) {
+			if (request_irq(instance->irq, generic_NCR5380_intr, SA_INTERRUPT, "NCR5380", instance)) {
 				printk(KERN_WARNING "scsi%d : IRQ%d not free, interrupts disabled\n", instance->host_no, instance->irq);
 				instance->irq = SCSI_IRQ_NONE;
 			}
--- diff/drivers/scsi/ide-scsi.c	2004-02-09 10:36:11.000000000 +0000
+++ source/drivers/scsi/ide-scsi.c	2004-02-23 13:56:45.000000000 +0000
@@ -78,6 +78,7 @@ typedef struct idescsi_pc_s {
 #define PC_DMA_IN_PROGRESS		0	/* 1 while DMA in progress */
 #define PC_WRITING			1	/* Data direction */
 #define PC_TRANSFORM			2	/* transform SCSI commands */
+#define PC_TIMEDOUT			3	/* command timed out */
 #define PC_DMA_OK			4	/* Use DMA */
 
 /*
@@ -307,6 +308,89 @@ static int idescsi_check_condition(ide_d
 	return ide_do_drive_cmd(drive, rq, ide_preempt);
 }
 
+/* Code derived from ide_cdrom_error()/abort() -- see ide-cd.c */
+
+/*
+ * Error reporting, in human readable form (luxurious, but a memory hog).
+ */
+byte idescsi_dump_status (ide_drive_t *drive, const char *msg, byte stat)
+{
+	unsigned long flags;
+
+	atapi_status_t status;
+	atapi_error_t error;
+
+	status.all = stat;
+	local_irq_set(flags);
+	printk(KERN_WARNING "ide-scsi: %s: %s: status=0x%02x", drive->name, msg, stat);
+#if IDESCSI_DEBUG_LOG
+	printk(" { ");
+	if (status.b.bsy)
+	       printk("Busy ");
+	else {
+	       if (status.b.drdy)      printk("DriveReady ");
+	       if (status.b.df)        printk("DeviceFault ");
+	       if (status.b.dsc)       printk("SeekComplete ");
+	       if (status.b.drq)       printk("DataRequest ");
+	       if (status.b.corr)      printk("CorrectedError ");
+	       if (status.b.idx)       printk("Index ");
+	       if (status.b.check)     printk("Error ");
+	}
+	printk("}");
+#endif  /* IDESCSI_DEBUG_LOG */
+	printk("\n");
+	if ((status.all & (status.b.bsy|status.b.check)) == status.b.check) {
+	       error.all = HWIF(drive)->INB(IDE_ERROR_REG);
+	       printk(KERN_WARNING "ide-scsi: %s: %s: error=0x%02x", drive->name, msg, error.all);
+#if IDESCSI_DEBUG_LOG
+	       if (error.b.ili)        printk("IllegalLengthIndication ");
+	       if (error.b.eom)        printk("EndOfMedia ");
+	       if (error.b.abrt)       printk("Aborted Command ");
+	       if (error.b.mcr)        printk("MediaChangeRequested ");
+	       if (error.b.sense_key)  printk("LastFailedSense 0x%02x ",
+					   error.b.sense_key);
+#endif  /* IDESCSI_DEBUG_LOG */
+	       printk("\n");
+	}
+	local_irq_restore(flags);
+	return error.all;
+}
+
+ide_startstop_t idescsi_atapi_error (ide_drive_t *drive, const char *msg, byte stat)
+{
+	struct request *rq;
+	byte err;
+
+	err = idescsi_dump_status(drive, msg, stat);
+
+	if (drive == NULL || (rq = HWGROUP(drive)->rq) == NULL)
+		return ide_stopped;
+
+	if (HWIF(drive)->INB(IDE_STATUS_REG) & (BUSY_STAT|DRQ_STAT))
+		/* force an abort */
+		HWIF(drive)->OUTB(WIN_IDLEIMMEDIATE,IDE_COMMAND_REG);
+
+	rq->errors++;
+	DRIVER(drive)->end_request(drive, 0, 0);
+	return ide_stopped;
+}
+
+ide_startstop_t idescsi_atapi_abort (ide_drive_t *drive, const char *msg)
+{
+	struct request *rq;
+
+	if (drive == NULL || (rq = HWGROUP(drive)->rq) == NULL)
+	       return ide_stopped;
+
+#if IDESCSI_DEBUG_LOG
+	printk(KERN_WARNING "idescsi_atapi_abort called for %lu\n",
+			((idescsi_pc_t *) rq->special)->scsi_cmd->serial_number);
+#endif
+	rq->errors |= ERROR_MAX;
+	DRIVER(drive)->end_request(drive, 0, 0);
+	return ide_stopped;
+}
+
 static int idescsi_end_request (ide_drive_t *drive, int uptodate, int nrsecs)
 {
 	idescsi_scsi_t *scsi = drive_to_idescsi(drive);
@@ -334,7 +418,13 @@ static int idescsi_end_request (ide_driv
 		kfree(rq);
 		pc = opc;
 		rq = pc->rq;
-		pc->scsi_cmd->result = (CHECK_CONDITION << 1) | (DID_OK << 16);
+		pc->scsi_cmd->result = (CHECK_CONDITION << 1) |
+					((test_bit(PC_TIMEDOUT, &pc->flags)?DID_TIME_OUT:DID_OK) << 16);
+	} else if (test_bit(PC_TIMEDOUT, &pc->flags)) {
+		if (log)
+			printk (KERN_WARNING "ide-scsi: %s: timed out for %lu\n",
+					drive->name, pc->scsi_cmd->serial_number);
+		pc->scsi_cmd->result = DID_TIME_OUT << 16;
 	} else if (rq->errors >= ERROR_MAX) {
 		pc->scsi_cmd->result = DID_ERROR << 16;
 		if (log)
@@ -374,6 +464,19 @@ static inline unsigned long get_timeout(
 	return IDE_MAX(WAIT_CMD, pc->timeout - jiffies);
 }
 
+static int idescsi_expiry(ide_drive_t *drive)
+{
+	idescsi_scsi_t *scsi = drive->driver_data;
+	idescsi_pc_t   *pc   = scsi->pc;
+
+#if IDESCSI_DEBUG_LOG
+	printk(KERN_WARNING "idescsi_expiry called for %lu at %lu\n", pc->scsi_cmd->serial_number, jiffies);
+#endif
+	set_bit(PC_TIMEDOUT, &pc->flags);
+
+	return 0;					/* we do not want the ide subsystem to retry */
+}
+
 /*
  *	Our interrupt handler.
  */
@@ -393,6 +496,15 @@ static ide_startstop_t idescsi_pc_intr (
 	printk (KERN_INFO "ide-scsi: Reached idescsi_pc_intr interrupt handler\n");
 #endif /* IDESCSI_DEBUG_LOG */
 
+	if (test_bit(PC_TIMEDOUT, &pc->flags)){
+#if IDESCSI_DEBUG_LOG
+		printk(KERN_WARNING "idescsi_pc_intr: got timed out packet  %lu at %lu\n",
+				pc->scsi_cmd->serial_number, jiffies);
+#endif
+		/* end this request now - scsi should retry it*/
+		idescsi_end_request (drive, 1, 0);
+		return ide_stopped;
+	}
 	if (test_and_clear_bit (PC_DMA_IN_PROGRESS, &pc->flags)) {
 #if IDESCSI_DEBUG_LOG
 		printk ("ide-scsi: %s: DMA complete\n", drive->name);
@@ -442,7 +554,7 @@ static ide_startstop_t idescsi_pc_intr (
 				pc->actually_transferred += temp;
 				pc->current_position += temp;
 				idescsi_discard_data(drive, bcount.all - temp);
-				ide_set_handler(drive, &idescsi_pc_intr, get_timeout(pc), NULL);
+				ide_set_handler(drive, &idescsi_pc_intr, get_timeout(pc), idescsi_expiry);
 				return ide_started;
 			}
 #if IDESCSI_DEBUG_LOG
@@ -467,7 +579,8 @@ static ide_startstop_t idescsi_pc_intr (
 	pc->actually_transferred += bcount.all;
 	pc->current_position += bcount.all;
 
-	ide_set_handler(drive, &idescsi_pc_intr, get_timeout(pc), NULL);	/* And set the interrupt handler again */
+	/* And set the interrupt handler again */
+	ide_set_handler(drive, &idescsi_pc_intr, get_timeout(pc), idescsi_expiry);
 	return ide_started;
 }
 
@@ -492,7 +605,7 @@ static ide_startstop_t idescsi_transfer_
 	if (HWGROUP(drive)->handler != NULL)
 		BUG();
 	/* Set the interrupt routine */
-	ide_set_handler(drive, &idescsi_pc_intr, get_timeout(pc), NULL);
+	ide_set_handler(drive, &idescsi_pc_intr, get_timeout(pc), idescsi_expiry);
 	/* Send the actual packet */
 	atapi_output_bytes(drive, scsi->pc->c, 12);
 	if (test_bit (PC_DMA_OK, &pc->flags)) {
@@ -540,7 +653,7 @@ static ide_startstop_t idescsi_issue_pc 
 		if (HWGROUP(drive)->handler != NULL)
 			BUG();
 		ide_set_handler(drive, &idescsi_transfer_pc,
-				get_timeout(pc), NULL);
+				get_timeout(pc), idescsi_expiry);
 		/* Issue the packet command */
 		HWIF(drive)->OUTB(WIN_PACKETCMD, IDE_COMMAND_REG);
 		return ide_started;
@@ -633,6 +746,8 @@ static ide_driver_t idescsi_driver = {
 	.cleanup		= idescsi_cleanup,
 	.do_request		= idescsi_do_request,
 	.end_request		= idescsi_end_request,
+	.error                  = idescsi_atapi_error,
+	.abort                  = idescsi_atapi_abort,
 	.drives			= LIST_HEAD_INIT(idescsi_driver.drives),
 };
 
@@ -852,66 +967,132 @@ abort:
 	return 1;
 }
 
-static int idescsi_abort (Scsi_Cmnd *cmd)
+static int idescsi_eh_abort (Scsi_Cmnd *cmd)
 {
-	int countdown = 8;
-	unsigned long flags;
-	idescsi_scsi_t *scsi = scsihost_to_idescsi(cmd->device->host);
-	ide_drive_t *drive = scsi->drive;
+	idescsi_scsi_t *scsi  = scsihost_to_idescsi(cmd->device->host);
+	ide_drive_t    *drive = scsi->drive;
+	int		busy;
+	int             ret   = FAILED;
 
-	printk (KERN_ERR "ide-scsi: abort called for %lu\n", cmd->serial_number);
-	while (countdown--) {
-		/* is cmd active?
-		 *  need to lock so this stuff doesn't change under us */
-		spin_lock_irqsave(&ide_lock, flags);
-		if (scsi->pc && scsi->pc->scsi_cmd && 
-				scsi->pc->scsi_cmd->serial_number == cmd->serial_number) {
-			/* yep - let's give it some more time - 
-			 * we can do that, we're in _our_ error kernel thread */
-			spin_unlock_irqrestore(&ide_lock, flags);
-			scsi_sleep(HZ);
-			continue;
-		}
-		/* no, but is it queued in the ide subsystem? */
-		if (elv_queue_empty(drive->queue)) {
-			spin_unlock_irqrestore(&ide_lock, flags);
-			return SUCCESS;
-		}
-		spin_unlock_irqrestore(&ide_lock, flags);
-		schedule_timeout(HZ/10);
+	/* In idescsi_eh_abort we try to gently pry our command from the ide subsystem */
+
+	if (test_bit(IDESCSI_LOG_CMD, &scsi->log))
+		printk (KERN_WARNING "ide-scsi: abort called for %lu\n", cmd->serial_number);
+
+	if (!drive) {
+		BUG();
+		goto no_drive;
+	}
+
+	/* First give it some more time, how much is "right" is hard to say :-( */
+
+	busy = ide_wait_not_busy(HWIF(drive), 100);	/* FIXME - uses mdelay which causes latency? */
+	if (test_bit(IDESCSI_LOG_CMD, &scsi->log))
+		printk (KERN_WARNING "ide-scsi: drive did%s become ready\n", busy?" not":"");
+
+	spin_lock_irq(&ide_lock);
+
+	/* If there is no pc running we're done (our interrupt took care of it) */
+	if (!scsi->pc) {
+		ret = SUCCESS;
+		goto ide_unlock;
 	}
-	return FAILED;
+
+	/* It's somewhere in flight. Does ide subsystem agree? */
+	if (scsi->pc->scsi_cmd->serial_number == cmd->serial_number && !busy &&
+	    elv_queue_empty(drive->queue) && HWGROUP(drive)->rq != scsi->pc->rq) {
+		/*
+		 * FIXME - not sure this condition can ever occur
+		 */
+		printk (KERN_ERR "ide-scsi: cmd aborted!\n");
+
+		idescsi_free_bio(scsi->pc->rq->bio);
+		if (scsi->pc->rq->flags & REQ_SENSE)
+			kfree(scsi->pc->buffer);
+		kfree(scsi->pc->rq);
+		kfree(scsi->pc);
+		scsi->pc = NULL;
+
+		ret = SUCCESS;
+	}
+
+ide_unlock:
+	spin_unlock_irq(&ide_lock);
+no_drive:
+	if (test_bit(IDESCSI_LOG_CMD, &scsi->log))
+		printk (KERN_WARNING "ide-scsi: abort returns %s\n", ret == SUCCESS?"success":"failed");
+
+	return ret;
 }
 
-static int idescsi_reset (Scsi_Cmnd *cmd)
+static int idescsi_eh_reset (Scsi_Cmnd *cmd)
 {
-	unsigned long flags;
 	struct request *req;
-	idescsi_scsi_t *idescsi = scsihost_to_idescsi(cmd->device->host);
-	ide_drive_t *drive = idescsi->drive;
+	idescsi_scsi_t *scsi  = scsihost_to_idescsi(cmd->device->host);
+	ide_drive_t    *drive = scsi->drive;
+	int             ready = 0;
+	int             ret   = SUCCESS;
+
+	/* In idescsi_eh_reset we forcefully remove the command from the ide subsystem and reset the device. */
+
+	if (test_bit(IDESCSI_LOG_CMD, &scsi->log))
+		printk (KERN_WARNING "ide-scsi: reset called for %lu\n", cmd->serial_number);
 
-	printk (KERN_ERR "ide-scsi: reset called for %lu\n", cmd->serial_number);
-	/* first null the handler for the drive and let any process
-	 * doing IO (on another CPU) run to (partial) completion
-	 * the lock prevents processing new requests */
-	spin_lock_irqsave(&ide_lock, flags);
-	while (HWGROUP(drive)->handler) {
-		HWGROUP(drive)->handler = NULL;
-		schedule_timeout(1);
+	if (!drive) {
+		BUG();
+		return FAILED;
 	}
+
+	spin_lock_irq(&ide_lock);
+
+	if (!scsi->pc || (req = scsi->pc->rq) != HWGROUP(drive)->rq || !HWGROUP(drive)->handler) {
+		BUG();
+		spin_unlock(&ide_lock);
+		return FAILED;
+	}
+
+	/* kill current request */
+	blkdev_dequeue_request(req);
+	end_that_request_last(req);
+	idescsi_free_bio(req->bio);
+	if (req->flags & REQ_SENSE)
+		kfree(scsi->pc->buffer);
+	kfree(scsi->pc);
+	scsi->pc = NULL;
+	kfree(req);
+
 	/* now nuke the drive queue */
 	while ((req = elv_next_request(drive->queue))) {
 		blkdev_dequeue_request(req);
 		end_that_request_last(req);
 	}
-	/* FIXME - this will probably leak memory */
+
 	HWGROUP(drive)->rq = NULL;
-	if (drive_to_idescsi(drive))
-		drive_to_idescsi(drive)->pc = NULL;
-	spin_unlock_irqrestore(&ide_lock, flags);
-	/* finally, reset the drive (and its partner on the bus...) */
-	ide_do_reset (drive);	
-	return SUCCESS;
+	HWGROUP(drive)->handler = NULL;
+	HWGROUP(drive)->busy = 1;		/* will set this to zero when ide reset finished */
+	spin_unlock_irq(&ide_lock);
+
+	ide_do_reset(drive);
+
+	spin_unlock_irq(cmd->device->host->host_lock);
+
+	/* ide_do_reset starts a polling handler which restarts itself every 50ms until the reset finishes */
+
+	do
+		/* There should be no locks taken at this point */
+		schedule_timeout(HZ/20);
+	while ( HWGROUP(drive)->handler );
+
+	ready = drive_is_ready(drive);
+	HWGROUP(drive)->busy--;
+	if (!ready) {
+		printk (KERN_ERR "ide-scsi: reset failed!\n");
+		ret = FAILED;
+	}
+
+	spin_lock_irq(cmd->device->host->host_lock);
+
+	return ret;
 }
 
 static int idescsi_bios(struct scsi_device *sdev, struct block_device *bdev,
@@ -935,8 +1116,8 @@ static Scsi_Host_Template idescsi_templa
 	.slave_configure        = idescsi_slave_configure,
 	.ioctl			= idescsi_ioctl,
 	.queuecommand		= idescsi_queue,
-	.eh_abort_handler	= idescsi_abort,
-	.eh_device_reset_handler = idescsi_reset,
+	.eh_abort_handler	= idescsi_eh_abort,
+	.eh_host_reset_handler  = idescsi_eh_reset,
 	.bios_param		= idescsi_bios,
 	.can_queue		= 40,
 	.this_id		= -1,
@@ -971,8 +1152,7 @@ static int idescsi_attach(ide_drive_t *d
 	drive->driver_data = host;
 	idescsi = scsihost_to_idescsi(host);
 	idescsi->drive = drive;
-	err = ide_register_subdriver (drive, &idescsi_driver,
-				      IDE_SUBDRIVER_VERSION);
+	err = ide_register_subdriver(drive, &idescsi_driver);
 	if (!err) {
 		idescsi_setup (drive, idescsi);
 		drive->disk->fops = &idescsi_ops;
--- diff/drivers/scsi/ini9100u.c	2004-02-09 10:36:11.000000000 +0000
+++ source/drivers/scsi/ini9100u.c	2004-02-23 13:56:45.000000000 +0000
@@ -272,6 +272,17 @@ static Scsi_Cmnd *i91uPopSRBFromQueue(HC
 	return (pSRB);
 }
 
+static irqreturn_t i91u_intr(int irqno, void *dev_id, struct pt_regs *regs)
+{
+	struct Scsi_Host *dev = dev_id;
+	unsigned long flags;
+	
+	spin_lock_irqsave(dev->host_lock, flags);
+	tul_isr((HCS *)hreg->base);
+	spin_unlock_irqrestore(dev->host_lock, flags);
+	return IRQ_HANDLED;
+}
+
 /* called from init/main.c */
 
 void i91u_setup(char *str, int *ints)
@@ -396,8 +407,7 @@ int i91u_detect(Scsi_Host_Template * tpn
 
 		pHCB->HCS_Index = i;	/* 7/29/98 */
 		hreg = scsi_register(tpnt, sizeof(HCS));
-		if(hreg == NULL)
-		{
+		if(hreg == NULL) {
 			release_region(pHCB->HCS_Base, 256);
 			return 0;
 		}
@@ -413,48 +423,10 @@ int i91u_detect(Scsi_Host_Template * tpn
 		hreg->sg_tablesize = TOTAL_SG_ENTRY;	/* Maximun support is 32 */
 
 		/* Initial tulip chip           */
-		switch (i) {
-		case 0:
-			ok = request_irq(pHCB->HCS_Intr, i91u_intr0, SA_INTERRUPT | SA_SHIRQ, "i91u", hreg);
-			break;
-		case 1:
-			ok = request_irq(pHCB->HCS_Intr, i91u_intr1, SA_INTERRUPT | SA_SHIRQ, "i91u", hreg);
-			break;
-		case 2:
-			ok = request_irq(pHCB->HCS_Intr, i91u_intr2, SA_INTERRUPT | SA_SHIRQ, "i91u", hreg);
-			break;
-		case 3:
-			ok = request_irq(pHCB->HCS_Intr, i91u_intr3, SA_INTERRUPT | SA_SHIRQ, "i91u", hreg);
-			break;
-		case 4:
-			ok = request_irq(pHCB->HCS_Intr, i91u_intr4, SA_INTERRUPT | SA_SHIRQ, "i91u", hreg);
-			break;
-		case 5:
-			ok = request_irq(pHCB->HCS_Intr, i91u_intr5, SA_INTERRUPT | SA_SHIRQ, "i91u", hreg);
-			break;
-		case 6:
-			ok = request_irq(pHCB->HCS_Intr, i91u_intr6, SA_INTERRUPT | SA_SHIRQ, "i91u", hreg);
-			break;
-		case 7:
-			ok = request_irq(pHCB->HCS_Intr, i91u_intr7, SA_INTERRUPT | SA_SHIRQ, "i91u", hreg);
-			break;
-		default:
-			i91u_panic("i91u: Too many host adapters\n");
-			break;
-		}
+		ok = request_irq(pHCB->HCS_Intr, i91u_intr, SA_INTERRUPT | SA_SHIRQ, "i91u", hreg);
 		if (ok < 0) {
-			if (ok == -EINVAL) {
-				printk("i91u: bad IRQ %d.\n", pHCB->HCS_Intr);
-				printk("         Contact author.\n");
-			} else if (ok == -EBUSY)
-				printk("i91u: IRQ %d already in use. Configure another.\n",
-				       pHCB->HCS_Intr);
-			else {
-				printk("\ni91u: Unexpected error code on requesting IRQ %d.\n",
-				       pHCB->HCS_Intr);
-				printk("         Contact author.\n");
-			}
-			i91u_panic("i91u: driver needs an IRQ.\n");
+			printk(KERN_WARNING "i91u: unable to request IRQ %d\n\n", pHCB->HCS_Intr);
+			return 0;
 		}
 	}
 
@@ -731,137 +703,6 @@ static void i91uSCBPost(BYTE * pHcb, BYT
 	return;
 }
 
-/*
- * Interrupts handler (main routine of the driver)
- */
-static irqreturn_t i91u_intr0(int irqno, void *dev_id, struct pt_regs *regs)
-{
-	unsigned long flags;
-	struct Scsi_Host *dev = dev_id;
-	
-	if (tul_hcs[0].HCS_Intr != irqno)
-		return IRQ_NONE;
-
-	spin_lock_irqsave(dev->host_lock, flags);
-
-	tul_isr(&tul_hcs[0]);
-
-	spin_unlock_irqrestore(dev->host_lock, flags);
-	return IRQ_HANDLED;
-}
-
-static irqreturn_t i91u_intr1(int irqno, void *dev_id, struct pt_regs *regs)
-{
-	unsigned long flags;
-	struct Scsi_Host *dev = dev_id;
-	
-	if (tul_hcs[1].HCS_Intr != irqno)
-		return IRQ_NONE;
-
-	spin_lock_irqsave(dev->host_lock, flags);
-
-	tul_isr(&tul_hcs[1]);
-
-	spin_unlock_irqrestore(dev->host_lock, flags);
-	return IRQ_HANDLED;
-}
-
-static irqreturn_t i91u_intr2(int irqno, void *dev_id, struct pt_regs *regs)
-{
-	unsigned long flags;
-	struct Scsi_Host *dev = dev_id;
-	
-	if (tul_hcs[2].HCS_Intr != irqno)
-		return IRQ_NONE;
-
-	spin_lock_irqsave(dev->host_lock, flags);
-
-	tul_isr(&tul_hcs[2]);
-
-	spin_unlock_irqrestore(dev->host_lock, flags);
-	return IRQ_HANDLED;
-}
-
-static irqreturn_t i91u_intr3(int irqno, void *dev_id, struct pt_regs *regs)
-{
-	unsigned long flags;
-	struct Scsi_Host *dev = dev_id;
-	
-	if (tul_hcs[3].HCS_Intr != irqno)
-		return IRQ_NONE;
-
-	spin_lock_irqsave(dev->host_lock, flags);
-
-	tul_isr(&tul_hcs[3]);
-
-	spin_unlock_irqrestore(dev->host_lock, flags);
-	return IRQ_HANDLED;
-}
-
-static irqreturn_t i91u_intr4(int irqno, void *dev_id, struct pt_regs *regs)
-{
-	unsigned long flags;
-	struct Scsi_Host *dev = dev_id;
-	
-	if (tul_hcs[4].HCS_Intr != irqno)
-		return IRQ_NONE;
-
-	spin_lock_irqsave(dev->host_lock, flags);
-
-	tul_isr(&tul_hcs[4]);
-
-	spin_unlock_irqrestore(dev->host_lock, flags);
-	return IRQ_HANDLED;
-}
-
-static irqreturn_t i91u_intr5(int irqno, void *dev_id, struct pt_regs *regs)
-{
-	unsigned long flags;
-	struct Scsi_Host *dev = dev_id;
-	
-	if (tul_hcs[5].HCS_Intr != irqno)
-		return IRQ_NONE;
-
-	spin_lock_irqsave(dev->host_lock, flags);
-
-	tul_isr(&tul_hcs[5]);
-
-	spin_unlock_irqrestore(dev->host_lock, flags);
-	return IRQ_HANDLED;
-}
-	
-static irqreturn_t i91u_intr6(int irqno, void *dev_id, struct pt_regs *regs)
-{
-	unsigned long flags;
-	struct Scsi_Host *dev = dev_id;
-	
-	if (tul_hcs[6].HCS_Intr != irqno)
-		return IRQ_NONE;
-
-	spin_lock_irqsave(dev->host_lock, flags);
-
-	tul_isr(&tul_hcs[6]);
-
-	spin_unlock_irqrestore(dev->host_lock, flags);
-	return IRQ_HANDLED;
-}
-
-static irqreturn_t i91u_intr7(int irqno, void *dev_id, struct pt_regs *regs)
-{
-	unsigned long flags;
-	struct Scsi_Host *dev = dev_id;
-	
-	if (tul_hcs[7].HCS_Intr != irqno)
-		return IRQ_NONE;
-
-	spin_lock_irqsave(dev->host_lock, flags);
-
-	tul_isr(&tul_hcs[7]);
-
-	spin_unlock_irqrestore(dev->host_lock, flags);
-	return IRQ_HANDLED;
-}
-
 /* 
  * Dump the current driver status and panic...
  */
--- diff/drivers/scsi/jazz_esp.c	2003-08-20 14:16:12.000000000 +0100
+++ source/drivers/scsi/jazz_esp.c	2004-02-23 13:56:45.000000000 +0000
@@ -290,6 +290,8 @@ static Scsi_Host_Template driver_templat
 	.proc_info		= &esp_proc_info,
 	.name			= "ESP 100/100a/200",
 	.detect			= jazz_esp_detect,
+	.slave_alloc		= esp_slave_alloc,
+	.slave_destroy		= esp_slave_destroy,
 	.release		= jazz_esp_release,
 	.info			= esp_info,
 	.queuecommand		= esp_queue,
--- diff/drivers/scsi/mac_esp.c	2004-02-09 10:36:11.000000000 +0000
+++ source/drivers/scsi/mac_esp.c	2004-02-23 13:56:45.000000000 +0000
@@ -734,6 +734,8 @@ static Scsi_Host_Template driver_templat
 	.proc_name		= "esp",
 	.name			= "Mac 53C9x SCSI",
 	.detect			= mac_esp_detect,
+	.slave_alloc		= esp_slave_alloc,
+	.slave_destroy		= esp_slave_destroy,
 	.release		= mac_esp_release,
 	.info			= esp_info,
 	.queuecommand		= esp_queue,
--- diff/drivers/scsi/mca_53c9x.c	2003-08-20 14:16:12.000000000 +0100
+++ source/drivers/scsi/mca_53c9x.c	2004-02-23 13:56:45.000000000 +0000
@@ -448,6 +448,8 @@ static Scsi_Host_Template driver_templat
 	.proc_name		= "esp",
 	.name			= "NCR 53c9x SCSI",
 	.detect			= mca_esp_detect,
+	.slave_alloc		= esp_slave_alloc,
+	.slave_destroy		= esp_slave_destroy,
 	.release		= mca_esp_release,
 	.queuecommand		= esp_queue,
 	.eh_abort_handler	= esp_abort,
--- diff/drivers/scsi/oktagon_esp.c	2003-08-20 14:16:13.000000000 +0100
+++ source/drivers/scsi/oktagon_esp.c	2004-02-23 13:56:45.000000000 +0000
@@ -595,6 +595,8 @@ static Scsi_Host_Template driver_templat
 	.proc_info		= &esp_proc_info,
 	.name			= "BSC Oktagon SCSI",
 	.detect			= oktagon_esp_detect,
+	.slave_alloc		= esp_slave_alloc,
+	.slave_destroy		= esp_slave_destroy,
 	.release		= oktagon_esp_release,
 	.queuecommand		= esp_queue,
 	.eh_abort_handler	= esp_abort,
--- diff/drivers/scsi/qla1280.c	2004-02-09 10:36:11.000000000 +0000
+++ source/drivers/scsi/qla1280.c	2004-02-23 13:56:45.000000000 +0000
@@ -348,7 +348,6 @@
 #include <asm/system.h>
 
 #if LINUX_VERSION_CODE >= 0x020545
-#include <asm/cacheflush.h>	/* for flush_cache_all() */
 #include <scsi/scsi.h>
 #include <scsi/scsi_cmnd.h>
 #include <scsi/scsi_device.h>
@@ -2123,8 +2122,6 @@ qla1280_setup_chip(struct scsi_qla_host 
 			((uint16_t *)ha->request_ring)[i] =
 				cpu_to_le16(risc_code_address[i]);
 
-		flush_cache_all();
-
 		mb[0] = MBC_LOAD_RAM;
 		mb[1] = risc_address;
 		mb[4] = cnt;
--- diff/drivers/scsi/qla2xxx/qla_init.c	2004-02-18 08:54:11.000000000 +0000
+++ source/drivers/scsi/qla2xxx/qla_init.c	2004-02-23 13:56:45.000000000 +0000
@@ -690,12 +690,6 @@ qla2x00_setup_chip(scsi_qla_host_t *ha)
 			for (i = 0; i < cnt; i++)
 				req_ring[i] = cpu_to_le16(risc_code[i]);
 
-			/*
-			 * Flush written firmware to the ha->request_ring buffer
-			 * before DMA.
-			 */
-			flush_cache_all();
-
 			if (fw_iter->addressing == FW_INFO_ADDR_NORMAL) {
 				rval = qla2x00_load_ram(ha,
 				    ha->request_dma, risc_address, cnt);
--- diff/drivers/scsi/qla2xxx/qla_isr.c	2004-02-18 08:54:11.000000000 +0000
+++ source/drivers/scsi/qla2xxx/qla_isr.c	2004-02-23 13:56:45.000000000 +0000
@@ -828,6 +828,7 @@ qla2x00_status_entry(scsi_qla_host_t *ha
 	uint8_t		lscsi_status;
 	uint32_t	resid;
 	uint8_t		sense_sz = 0;
+	uint16_t	rsp_info_len;
 
 	/* Fast path completion. */
 	if (le16_to_cpu(pkt->comp_status) == CS_COMPLETE &&
@@ -919,6 +920,24 @@ qla2x00_status_entry(scsi_qla_host_t *ha
 		}
 	}
 
+	/* Check for any FCP transport errors. */
+	if (scsi_status & SS_RESPONSE_INFO_LEN_VALID) {
+		rsp_info_len = le16_to_cpu(pkt->rsp_info_len);
+		if (rsp_info_len > 3 && pkt->rsp_info[3]) {
+			DEBUG2(printk("scsi(%ld:%d:%d:%d) FCP I/O protocol "
+			    "failure (%x/%02x%02x%02x%02x%02x%02x%02x%02x)..."
+			    "retrying command\n", ha->host_no, b, t, l,
+			    rsp_info_len, pkt->rsp_info[0], pkt->rsp_info[1],
+			    pkt->rsp_info[2], pkt->rsp_info[3],
+			    pkt->rsp_info[4], pkt->rsp_info[5],
+			    pkt->rsp_info[6], pkt->rsp_info[7]));
+
+			cp->result = DID_BUS_BUSY << 16;
+			add_to_done_queue(ha, sp);
+			return;
+		}
+	}
+
 	/*
 	 * Based on Host and scsi status generate status code for Linux
 	 */
--- diff/drivers/scsi/qla2xxx/qla_mbx.c	2004-02-18 08:54:11.000000000 +0000
+++ source/drivers/scsi/qla2xxx/qla_mbx.c	2004-02-23 13:56:45.000000000 +0000
@@ -1421,7 +1421,7 @@ qla2x00_get_port_database(scsi_qla_host_
 	mcp->in_mb = MBX_0;
 	mcp->buf_size = PORT_DATABASE_SIZE;
 	mcp->flags = MBX_DMA_IN;
-	mcp->tov =  ha->login_timeout * 2;
+	mcp->tov = (ha->login_timeout * 2) + (ha->login_timeout / 2);
 	rval = qla2x00_mailbox_command(ha, mcp);
 
 	if (rval == QLA_SUCCESS) {
@@ -1774,8 +1774,7 @@ qla2x00_send_sns(scsi_qla_host_t *ha, dm
 	mcp->in_mb = MBX_0|MBX_1;
 	mcp->buf_size = buf_size;
 	mcp->flags = MBX_DMA_OUT|MBX_DMA_IN;
-	/*mcp->tov = ha->retry_count * ha->login_timeout * 2;*/
-	mcp->tov =  ha->login_timeout * 2;
+	mcp->tov = (ha->login_timeout * 2) + (ha->login_timeout / 2);
 	rval = qla2x00_mailbox_command(ha, mcp);
 
 	if (rval != QLA_SUCCESS) {
@@ -1836,8 +1835,7 @@ qla2x00_login_fabric(scsi_qla_host_t *ha
 	mcp->mb[3] = area << 8 | al_pa;
 
 	mcp->in_mb = MBX_7|MBX_6|MBX_2|MBX_1|MBX_0;
-	/*mcp->tov = ha->retry_count * ha->login_timeout * 2;*/
-	mcp->tov = ha->login_timeout * 2;
+	mcp->tov = (ha->login_timeout * 2) + (ha->login_timeout / 2);
 	mcp->flags = 0;
 	rval = qla2x00_mailbox_command(ha, mcp);
 
@@ -1909,7 +1907,7 @@ qla2x00_login_local_device(scsi_qla_host
 	mcp->mb[2] = opt;
 	mcp->out_mb = MBX_2|MBX_1|MBX_0;
  	mcp->in_mb = MBX_7|MBX_6|MBX_1|MBX_0;
-	mcp->tov =  ha->login_timeout * 2;
+	mcp->tov = (ha->login_timeout * 2) + (ha->login_timeout / 2);
 	mcp->flags = 0;
 	rval = qla2x00_mailbox_command(ha, mcp);
 
@@ -2412,7 +2410,7 @@ qla2x00_get_fcal_position_map(scsi_qla_h
 	mcp->in_mb = MBX_1|MBX_0;
 	mcp->buf_size = FCAL_MAP_SIZE;
 	mcp->flags = MBX_DMA_IN;
-	mcp->tov =  ha->login_timeout * 2;
+	mcp->tov = (ha->login_timeout * 2) + (ha->login_timeout / 2);
 	rval = qla2x00_mailbox_command(ha, mcp);
 
 	if (rval == QLA_SUCCESS) {
--- diff/drivers/scsi/qla2xxx/qla_os.c	2004-02-18 08:54:11.000000000 +0000
+++ source/drivers/scsi/qla2xxx/qla_os.c	2004-02-23 13:56:45.000000000 +0000
@@ -70,7 +70,7 @@ MODULE_PARM_DESC(ql2xretrycount,
 int displayConfig;
 module_param(displayConfig, int, 0);
 MODULE_PARM_DESC(displayConfig,
-		"If 1 then display the configuration used in /etc/modules.conf.");
+		"If 1 then display the configuration used in /etc/modprobe.conf.");
 
 int ql2xplogiabsentdevice;
 module_param(ql2xplogiabsentdevice, int, 0);
--- diff/drivers/scsi/scsi.c	2004-02-09 10:36:11.000000000 +0000
+++ source/drivers/scsi/scsi.c	2004-02-23 13:56:45.000000000 +0000
@@ -22,7 +22,7 @@
  *  support added by Michael Neuffer <mike@i-connect.net>
  *
  *  Added request_module("scsi_hostadapter") for kerneld:
- *  (Put an "alias scsi_hostadapter your_hostadapter" in /etc/modules.conf)
+ *  (Put an "alias scsi_hostadapter your_hostadapter" in /etc/modprobe.conf)
  *  Bjorn Ekwall  <bj0rn@blox.se>
  *  (changed to kmod)
  *
@@ -53,6 +53,8 @@
 #include <linux/spinlock.h>
 #include <linux/kmod.h>
 #include <linux/interrupt.h>
+#include <linux/notifier.h>
+#include <linux/cpu.h>
 
 #include <scsi/scsi_host.h>
 #include "scsi.h"
@@ -784,7 +786,7 @@ int scsi_retry_command(struct scsi_cmnd 
          */
 	memset(cmd->sense_buffer, 0, sizeof(cmd->sense_buffer));
 
-	return scsi_dispatch_cmd(cmd);
+	return scsi_queue_insert(cmd, SCSI_MLQUEUE_EH_RETRY);
 }
 
 /*
@@ -1129,6 +1131,38 @@ int scsi_device_cancel(struct scsi_devic
 	return 0;
 }
 
+#ifdef CONFIG_HOTPLUG_CPU
+static int scsi_cpu_notify(struct notifier_block *self,
+			   unsigned long action, void *hcpu)
+{
+	int cpu = (unsigned long)hcpu;
+
+	switch(action) {
+	case CPU_DEAD:
+		/* Drain scsi_done_q. */
+		local_irq_disable();
+		list_splice_init(&per_cpu(scsi_done_q, cpu),
+				 &__get_cpu_var(scsi_done_q));
+		raise_softirq_irqoff(SCSI_SOFTIRQ);
+		local_irq_enable();
+		break;
+	default:
+		break;
+	}
+	return NOTIFY_OK;
+}
+
+static struct notifier_block __devinitdata scsi_cpu_nb = {
+	.notifier_call	= scsi_cpu_notify,
+};
+
+#define register_scsi_cpu() register_cpu_notifier(&scsi_cpu_nb)
+#define unregister_scsi_cpu() unregister_cpu_notifier(&scsi_cpu_nb)
+#else
+#define register_scsi_cpu()
+#define unregister_scsi_cpu()
+#endif /* CONFIG_HOTPLUG_CPU */
+
 MODULE_DESCRIPTION("SCSI core");
 MODULE_LICENSE("GPL");
 
@@ -1163,6 +1197,7 @@ static int __init init_scsi(void)
 
 	devfs_mk_dir("scsi");
 	open_softirq(SCSI_SOFTIRQ, scsi_softirq, NULL);
+	register_scsi_cpu();
 	printk(KERN_NOTICE "SCSI subsystem initialized\n");
 	return 0;
 
@@ -1190,6 +1225,7 @@ static void __exit exit_scsi(void)
 	devfs_remove("scsi");
 	scsi_exit_procfs();
 	scsi_exit_queue();
+	unregister_scsi_cpu();
 }
 
 subsys_initcall(init_scsi);
--- diff/drivers/scsi/scsi.h	2003-09-30 15:46:17.000000000 +0100
+++ source/drivers/scsi/scsi.h	2004-02-23 13:56:45.000000000 +0000
@@ -34,52 +34,12 @@
 #define FALSE 0
 #endif
 
-#define MAX_SCSI_DEVICE_CODE 14
-extern const char *const scsi_device_types[MAX_SCSI_DEVICE_CODE];
-
 #ifdef DEBUG
 #define SCSI_TIMEOUT (5*HZ)
 #else
 #define SCSI_TIMEOUT (2*HZ)
 #endif
 
-/*
- *  Use these to separate status msg and our bytes
- *
- *  These are set by:
- *
- *      status byte = set from target device
- *      msg_byte    = return status from host adapter itself.
- *      host_byte   = set by low-level driver to indicate status.
- *      driver_byte = set by mid-level.
- */
-#define status_byte(result) (((result) >> 1) & 0x1f)
-#define msg_byte(result)    (((result) >> 8) & 0xff)
-#define host_byte(result)   (((result) >> 16) & 0xff)
-#define driver_byte(result) (((result) >> 24) & 0xff)
-#define suggestion(result)  (driver_byte(result) & SUGGEST_MASK)
-
-#define sense_class(sense)  (((sense) >> 4) & 0x7)
-#define sense_error(sense)  ((sense) & 0xf)
-#define sense_valid(sense)  ((sense) & 0x80);
-
-
-#define IDENTIFY_BASE       0x80
-#define IDENTIFY(can_disconnect, lun)   (IDENTIFY_BASE |\
-		     ((can_disconnect) ?  0x40 : 0) |\
-		     ((lun) & 0x07))
-
-/*
- *  SCSI command sets
- */
-
-#define SCSI_UNKNOWN    0
-#define SCSI_1          1
-#define SCSI_1_CCS      2
-#define SCSI_2          3
-#define SCSI_3          4
-
-
 struct Scsi_Host;
 struct scsi_cmnd;
 struct scsi_device;
--- diff/drivers/scsi/scsi_debug.c	2004-01-19 10:22:58.000000000 +0000
+++ source/drivers/scsi/scsi_debug.c	2004-02-23 13:56:45.000000000 +0000
@@ -557,8 +557,7 @@ static int resp_inquiry(unsigned char * 
 		
 		dev_id_num = ((devip->sdbg_host->shost->host_no + 1) * 2000) +
 			     (devip->target * 1000) + devip->lun;
-		len = snprintf(dev_id_str, 6, "%d", dev_id_num);
-		len = (len > 6) ? 6 : len;
+		len = scnprintf(dev_id_str, 6, "%d", dev_id_num);
 		if (0 == cmd[2]) { /* supported vital product data pages */
 			arr[3] = 3;
 			arr[4] = 0x0; /* this page */
@@ -1309,7 +1308,7 @@ static int scsi_debug_proc_info(struct S
 
 static ssize_t sdebug_delay_show(struct device_driver * ddp, char * buf) 
 {
-        return snprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_delay);
+        return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_delay);
 }
 
 static ssize_t sdebug_delay_store(struct device_driver * ddp, 
@@ -1331,7 +1330,7 @@ DRIVER_ATTR(delay, S_IRUGO | S_IWUSR, sd
 
 static ssize_t sdebug_opts_show(struct device_driver * ddp, char * buf) 
 {
-        return snprintf(buf, PAGE_SIZE, "0x%x\n", scsi_debug_opts);
+        return scnprintf(buf, PAGE_SIZE, "0x%x\n", scsi_debug_opts);
 }
 
 static ssize_t sdebug_opts_store(struct device_driver * ddp, 
@@ -1360,7 +1359,7 @@ DRIVER_ATTR(opts, S_IRUGO | S_IWUSR, sde
 
 static ssize_t sdebug_num_tgts_show(struct device_driver * ddp, char * buf) 
 {
-        return snprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_num_tgts);
+        return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_num_tgts);
 }
 static ssize_t sdebug_num_tgts_store(struct device_driver * ddp, 
 				     const char * buf, size_t count)
@@ -1378,13 +1377,13 @@ DRIVER_ATTR(num_tgts, S_IRUGO | S_IWUSR,
 
 static ssize_t sdebug_dev_size_mb_show(struct device_driver * ddp, char * buf) 
 {
-        return snprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_dev_size_mb);
+        return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_dev_size_mb);
 }
 DRIVER_ATTR(dev_size_mb, S_IRUGO, sdebug_dev_size_mb_show, NULL) 
 
 static ssize_t sdebug_every_nth_show(struct device_driver * ddp, char * buf) 
 {
-        return snprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_every_nth);
+        return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_every_nth);
 }
 static ssize_t sdebug_every_nth_store(struct device_driver * ddp, 
 				      const char * buf, size_t count)
@@ -1403,7 +1402,7 @@ DRIVER_ATTR(every_nth, S_IRUGO | S_IWUSR
 
 static ssize_t sdebug_max_luns_show(struct device_driver * ddp, char * buf) 
 {
-        return snprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_max_luns);
+        return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_max_luns);
 }
 static ssize_t sdebug_max_luns_store(struct device_driver * ddp, 
 				     const char * buf, size_t count)
@@ -1421,13 +1420,13 @@ DRIVER_ATTR(max_luns, S_IRUGO | S_IWUSR,
 
 static ssize_t sdebug_scsi_level_show(struct device_driver * ddp, char * buf) 
 {
-        return snprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_scsi_level);
+        return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_scsi_level);
 }
 DRIVER_ATTR(scsi_level, S_IRUGO, sdebug_scsi_level_show, NULL) 
 
 static ssize_t sdebug_add_host_show(struct device_driver * ddp, char * buf) 
 {
-        return snprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_add_host);
+        return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_add_host);
 }
 
 static ssize_t sdebug_add_host_store(struct device_driver * ddp, 
--- diff/drivers/scsi/scsi_devinfo.c	2003-10-27 09:20:43.000000000 +0000
+++ source/drivers/scsi/scsi_devinfo.c	2004-02-23 13:56:45.000000000 +0000
@@ -151,6 +151,7 @@ static struct {
 	{"EMC", "SYMMETRIX", NULL, BLIST_SPARSELUN | BLIST_LARGELUN | BLIST_FORCELUN},
 	{"HP", "A6189A", NULL, BLIST_SPARSELUN | BLIST_LARGELUN},	/* HP VA7400 */
 	{"HP", "OPEN-", "*", BLIST_SPARSELUN | BLIST_LARGELUN}, /* HP XP Arrays */
+	{"HITACHI", "DISK-SUBSYSTEM", "*", BLIST_SPARSELUN | BLIST_LARGELUN},  /* HITACHI 9960 */
 	{"CMD", "CRA-7280", NULL, BLIST_SPARSELUN},	/* CMD RAID Controller */
 	{"CNSI", "G7324", NULL, BLIST_SPARSELUN},	/* Chaparral G7324 RAID */
 	{"CNSi", "G8324", NULL, BLIST_SPARSELUN},	/* Chaparral G8324 RAID */
--- diff/drivers/scsi/sd.c	2004-02-18 08:54:11.000000000 +0000
+++ source/drivers/scsi/sd.c	2004-02-23 13:56:45.000000000 +0000
@@ -62,6 +62,7 @@
  */
 #define SD_MAJORS	16
 #define SD_DISKS	(SD_MAJORS << 4)
+#define TOTAL_SD_DISKS	CONFIG_MAX_SD_DISKS
 
 /*
  * Time out in seconds for disks and Magneto-opticals (which are slower).
@@ -95,7 +96,7 @@ struct scsi_disk {
 };
 
 
-static unsigned long sd_index_bits[SD_DISKS / BITS_PER_LONG];
+static unsigned long sd_index_bits[TOTAL_SD_DISKS / BITS_PER_LONG];
 static spinlock_t sd_index_lock = SPIN_LOCK_UNLOCKED;
 
 static int sd_revalidate_disk(struct gendisk *disk);
@@ -130,6 +131,9 @@ static int sd_major(int major_idx)
 		return SCSI_DISK1_MAJOR + major_idx - 1;
 	case 8 ... 15:
 		return SCSI_DISK8_MAJOR + major_idx - 8;
+#define MAX_IDX        (TOTAL_SD_DISKS >> 4)
+	case 16 ... MAX_IDX:
+		return SCSI_DISK15_MAJOR;
 	default:
 		BUG();
 		return 0;	/* shut up gcc */
@@ -1322,8 +1326,8 @@ static int sd_probe(struct device *dev)
 		goto out_free;
 
 	spin_lock(&sd_index_lock);
-	index = find_first_zero_bit(sd_index_bits, SD_DISKS);
-	if (index == SD_DISKS) {
+	index = find_first_zero_bit(sd_index_bits, TOTAL_SD_DISKS);
+	if (index == TOTAL_SD_DISKS) {
 		spin_unlock(&sd_index_lock);
 		error = -EBUSY;
 		goto out_put;
@@ -1338,15 +1342,24 @@ static int sd_probe(struct device *dev)
 	sdkp->openers = 0;
 
 	gd->major = sd_major(index >> 4);
-	gd->first_minor = (index & 15) << 4;
+	if (index > SD_DISKS)
+		gd->first_minor = ((index - SD_DISKS) & 15) << 4;
+	else
+		gd->first_minor = (index & 15) << 4;
 	gd->minors = 16;
 	gd->fops = &sd_fops;
 
-	if (index >= 26) {
+	if (index < 26) {
+		sprintf(gd->disk_name, "sd%c", 'a' + index % 26);
+	} else if (index < (26*27)) {
 		sprintf(gd->disk_name, "sd%c%c",
 			'a' + index/26-1,'a' + index % 26);
 	} else {
-		sprintf(gd->disk_name, "sd%c", 'a' + index % 26);
+		const unsigned int m1 = (index/ 26 - 1) / 26 - 1;
+		const unsigned int m2 = (index / 26 - 1) % 26;
+		const unsigned int m3 = index % 26;
+		sprintf(gd->disk_name, "sd%c%c%c",
+			'a' + m1, 'a' + m2, 'a' + m3);
 	}
 
 	strcpy(gd->devfs_name, sdp->devfs_name);
--- diff/drivers/scsi/st.c	2004-02-18 08:54:11.000000000 +0000
+++ source/drivers/scsi/st.c	2004-02-23 13:56:45.000000000 +0000
@@ -17,7 +17,7 @@
    Last modified: 18-JAN-1998 Richard Gooch <rgooch@atnf.csiro.au> Devfs support
  */
 
-static char *verstr = "20040122";
+static char *verstr = "20040213";
 
 #include <linux/module.h>
 
@@ -77,6 +77,8 @@ static int try_wdio = TRUE;
 static int st_dev_max;
 static int st_nr_dev;
 
+static struct class_simple *st_sysfs_class;
+
 MODULE_AUTHOR("Kai Makisara");
 MODULE_DESCRIPTION("SCSI Tape Driver");
 MODULE_LICENSE("GPL");
@@ -183,7 +185,7 @@ static int st_init_command(struct scsi_c
 
 static void do_create_driverfs_files(void);
 static void do_remove_driverfs_files(void);
-
+static void do_create_class_files(Scsi_Tape *, int, int);
 
 static struct scsi_driver st_template = {
 	.owner			= THIS_MODULE,
@@ -3902,20 +3904,8 @@ static int st_probe(struct device *dev)
 			}
 			STm->cdevs[j] = cdev;
 
-			error = sysfs_create_link(&STm->cdevs[j]->kobj, &SDp->sdev_gendev.kobj,
-						  "device");
-			if (error) {
-				printk(KERN_ERR
-				       "st%d: Can't create sysfs link from SCSI device.\n",
-				       dev_num);
-			}
 		}
-	}
-	error = sysfs_create_link(&SDp->sdev_gendev.kobj, &tpnt->modes[0].cdevs[0]->kobj,
-				  "tape");
-	if (error) {
-		printk(KERN_ERR "st%d: Can't create sysfs link from SCSI device.\n",
-		       dev_num);
+		do_create_class_files(tpnt, dev_num, mode);
 	}
 
 	for (mode = 0; mode < ST_NBR_MODES; ++mode) {
@@ -3941,11 +3931,14 @@ static int st_probe(struct device *dev)
 out_free_tape:
 	for (mode=0; mode < ST_NBR_MODES; mode++) {
 		STm = &(tpnt->modes[mode]);
+		sysfs_remove_link(&tpnt->device->sdev_gendev.kobj,
+				  "tape");
 		for (j=0; j < 2; j++) {
 			if (STm->cdevs[j]) {
 				if (cdev == STm->cdevs[j])
 					cdev = NULL;
-				sysfs_remove_link(&STm->cdevs[j]->kobj, "device");
+				class_simple_device_remove(MKDEV(SCSI_TAPE_MAJOR,
+								 TAPE_MINOR(i, mode, j)));
 				cdev_del(STm->cdevs[j]);
 			}
 		}
@@ -3981,13 +3974,14 @@ static int st_remove(struct device *dev)
 			st_nr_dev--;
 			write_unlock(&st_dev_arr_lock);
 			devfs_unregister_tape(tpnt->disk->number);
-			sysfs_remove_link(&SDp->sdev_gendev.kobj, "tape");
+			sysfs_remove_link(&tpnt->device->sdev_gendev.kobj,
+					  "tape");
 			for (mode = 0; mode < ST_NBR_MODES; ++mode) {
 				devfs_remove("%s/mt%s", SDp->devfs_name, st_formats[mode]);
 				devfs_remove("%s/mt%sn", SDp->devfs_name, st_formats[mode]);
 				for (j=0; j < 2; j++) {
-					sysfs_remove_link(&tpnt->modes[mode].cdevs[j]->kobj,
-							  "device");
+					class_simple_device_remove(MKDEV(SCSI_TAPE_MAJOR,
+									 TAPE_MINOR(i, mode, j)));
 					cdev_del(tpnt->modes[mode].cdevs[j]);
 					tpnt->modes[mode].cdevs[j] = NULL;
 				}
@@ -4052,13 +4046,23 @@ static int __init init_st(void)
 		"st: Version %s, fixed bufsize %d, s/g segs %d\n",
 		verstr, st_fixed_buffer_size, st_max_sg_segs);
 
+	st_sysfs_class = class_simple_create(THIS_MODULE, "scsi_tape");
+	if (IS_ERR(st_sysfs_class)) {
+		st_sysfs_class = NULL;
+		printk(KERN_ERR "Unable create sysfs class for SCSI tapes\n");
+		return 1;
+	}
+
 	if (!register_chrdev_region(MKDEV(SCSI_TAPE_MAJOR, 0),
 				    ST_MAX_TAPE_ENTRIES, "st")) {
 		if (scsi_register_driver(&st_template.gendrv) == 0) {
 			do_create_driverfs_files();
 			return 0;
 		}
+		if (st_sysfs_class)
+			class_simple_destroy(st_sysfs_class);		
 		unregister_chrdev_region(MKDEV(SCSI_TAPE_MAJOR, 0),
+
 					 ST_MAX_TAPE_ENTRIES);
 	}
 
@@ -4068,6 +4072,9 @@ static int __init init_st(void)
 
 static void __exit exit_st(void)
 {
+	if (st_sysfs_class)
+		class_simple_destroy(st_sysfs_class);
+	st_sysfs_class = NULL;
 	do_remove_driverfs_files();
 	scsi_unregister_driver(&st_template.gendrv);
 	unregister_chrdev_region(MKDEV(SCSI_TAPE_MAJOR, 0),
@@ -4080,7 +4087,7 @@ module_init(init_st);
 module_exit(exit_st);
 
 
-/* The sysfs interface. Read-only at the moment */
+/* The sysfs driver interface. Read-only at the moment */
 static ssize_t st_try_direct_io_show(struct device_driver *ddp, char *buf)
 {
 	return snprintf(buf, PAGE_SIZE, "%d\n", try_direct_io);
@@ -4126,6 +4133,99 @@ static void do_remove_driverfs_files(voi
 }
 
 
+/* The sysfs simple class interface */
+static ssize_t st_defined_show(struct class_device *class_dev, char *buf)
+{
+	ST_mode *STm = (ST_mode *)class_get_devdata(class_dev);
+	ssize_t l = 0;
+
+	l = snprintf(buf, PAGE_SIZE, "%d\n", STm->defined);
+	return l;
+}
+
+CLASS_DEVICE_ATTR(defined, S_IRUGO, st_defined_show, NULL);
+
+static ssize_t st_defblk_show(struct class_device *class_dev, char *buf)
+{
+	ST_mode *STm = (ST_mode *)class_get_devdata(class_dev);
+	ssize_t l = 0;
+
+	l = snprintf(buf, PAGE_SIZE, "%d\n", STm->default_blksize);
+	return l;
+}
+
+CLASS_DEVICE_ATTR(default_blksize, S_IRUGO, st_defblk_show, NULL);
+
+static ssize_t st_defdensity_show(struct class_device *class_dev, char *buf)
+{
+	ST_mode *STm = (ST_mode *)class_get_devdata(class_dev);
+	ssize_t l = 0;
+	char *fmt;
+
+	fmt = STm->default_density >= 0 ? "0x%02x\n" : "%d\n";
+	l = snprintf(buf, PAGE_SIZE, fmt, STm->default_density);
+	return l;
+}
+
+CLASS_DEVICE_ATTR(default_density, S_IRUGO, st_defdensity_show, NULL);
+
+static ssize_t st_defcompression_show(struct class_device *class_dev, char *buf)
+{
+	ST_mode *STm = (ST_mode *)class_get_devdata(class_dev);
+	ssize_t l = 0;
+
+	l = snprintf(buf, PAGE_SIZE, "%d\n", STm->default_compression - 1);
+	return l;
+}
+
+CLASS_DEVICE_ATTR(default_compression, S_IRUGO, st_defcompression_show, NULL);
+
+static void do_create_class_files(Scsi_Tape *STp, int dev_num, int mode)
+{
+	int rew, error;
+	struct class_device *st_class_member;
+
+	if (!st_sysfs_class)
+		return;
+
+	for (rew=0; rew < 2; rew++) {
+		st_class_member =
+			class_simple_device_add(st_sysfs_class,
+						MKDEV(SCSI_TAPE_MAJOR,
+						      TAPE_MINOR(dev_num, mode, rew)),
+						&STp->device->sdev_gendev, "%s",
+						STp->modes[mode].cdevs[rew]->kobj.name);
+		if (!st_class_member) {
+			printk(KERN_WARNING "st%d: class_simple_device_add failed\n",
+			       dev_num);
+			goto out;
+		}
+		class_set_devdata(st_class_member, &STp->modes[mode]);
+
+		class_device_create_file(st_class_member,
+					 &class_device_attr_defined);
+		class_device_create_file(st_class_member,
+					 &class_device_attr_default_blksize);
+		class_device_create_file(st_class_member,
+					 &class_device_attr_default_density);
+		class_device_create_file(st_class_member,
+					 &class_device_attr_default_compression);
+		if (mode == 0 && rew == 0) {
+			error = sysfs_create_link(&STp->device->sdev_gendev.kobj,
+						  &st_class_member->kobj,
+						  "tape");
+			if (error) {
+				printk(KERN_ERR
+				       "st%d: Can't create sysfs link from SCSI device.\n",
+				       dev_num);
+			}
+		}
+	}
+ out:
+	return;
+}
+
+
 /* Pin down user pages and put them into a scatter gather list. Returns <= 0 if
    - mapping of all pages not successful
    - any page is above max_pfn
--- diff/drivers/scsi/sun3x_esp.c	2003-08-20 14:16:13.000000000 +0100
+++ source/drivers/scsi/sun3x_esp.c	2004-02-23 13:56:45.000000000 +0000
@@ -46,12 +46,6 @@ static void dma_mmu_release_scsi_one (st
 static void dma_mmu_release_scsi_sgl (struct NCR_ESP *esp, Scsi_Cmnd *sp);
 static void dma_advance_sg (Scsi_Cmnd *sp);
 
-static volatile unsigned char cmd_buffer[16];
-                                /* This is where all commands are put
-                                 * before they are trasfered to the ESP chip
-                                 * via PIO.
-                                 */
-
 /* Detecting ESP chips on the machine.  This is the simple and easy
  * version.
  */
@@ -101,14 +95,8 @@ int sun3x_esp_detect(Scsi_Host_Template 
 	esp->eregs = (struct ESP_regs *)(SUN3X_ESP_BASE);
 	esp->dregs = (void *)SUN3X_ESP_DMA;
 
-#if 0
-  	esp->esp_command = (volatile unsigned char *)cmd_buffer;
- 	esp->esp_command_dvma = dvma_map((unsigned long)cmd_buffer,
- 					 sizeof (cmd_buffer));
-#else
 	esp->esp_command = (volatile unsigned char *)dvma_malloc(DVMA_PAGE_SIZE);
 	esp->esp_command_dvma = dvma_vtob((unsigned long)esp->esp_command);
-#endif
 
 	esp->irq = 2;
 	if (request_irq(esp->irq, esp_intr, SA_INTERRUPT, 
@@ -374,29 +362,6 @@ static void dma_advance_sg (Scsi_Cmnd *s
     sp->SCp.ptr = (char *)((unsigned long)sp->SCp.buffer->dvma_address);
 }
 
-
-static int esp_slave_alloc(Scsi_Device *SDptr)
-{
-	struct esp_device *esp_dev =
-		kmalloc(sizeof(struct esp_device), GFP_ATOMIC);
-
-	if (!esp_dev)
-		return -ENOMEM;
-	memset(esp_dev, 0, sizeof(struct esp_device));
-	SDptr->hostdata = esp_dev;
-	return 0;
-}
-
-static void esp_slave_destroy(Scsi_Device *SDptr)
-{
-	struct NCR_ESP *esp = (struct NCR_ESP *) SDptr->host->hostdata;
-
-	esp->targets_present &= ~(1 << SDptr->id);
-	kfree(SDptr->hostdata);
-	SDptr->hostdata = NULL;
-}
-
-
 static int sun3x_esp_release(struct Scsi_Host *instance)
 {
 	/* this code does not support being compiled as a module */	 
--- diff/drivers/scsi/tmscsim.c	2004-01-19 10:22:58.000000000 +0000
+++ source/drivers/scsi/tmscsim.c	2004-02-23 13:56:45.000000000 +0000
@@ -518,7 +518,6 @@ static void __init dc390_check_for_safe_
 }
 
 
-#ifndef CONFIG_SCSI_DC390T_NOGENSUPP
 int __initdata tmscsim_def[] = {7, 0 /* 10MHz */,
 		PARITY_CHK_ | SEND_START_ | EN_DISCONNECT_
 		| SYNC_NEGO_ | TAG_QUEUEING_,
@@ -546,7 +545,6 @@ static void __init dc390_fill_with_defau
 	if (tmscsim[4] >   5) tmscsim[4] =   4;
 	if (tmscsim[5] > 180) tmscsim[5] = 180;
 }
-#endif
 
 /* Override defaults on cmdline:
  * tmscsim: AdaptID, MaxSpeed (Index), DevMode (Bitmapped), AdaptMode (Bitmapped)
@@ -2105,10 +2103,6 @@ static int __init DC390_init (PSHT psht,
     
     if (dc390_CheckEEpromCheckSum (PDEV, index))
     {
-#ifdef CONFIG_SCSI_DC390T_NOGENSUPP
-	printk (KERN_ERR "DC390_init: No EEPROM found!\n");
-	return( -1 );
-#else
 	int speed;
 	dc390_adapname = "AM53C974";
 	printk (KERN_INFO "DC390_init: No EEPROM found! Trying default settings ...\n");
@@ -2120,7 +2114,6 @@ static int __init DC390_init (PSHT psht,
 		" DevMode=0x%02x, AdaptMode=0x%02x, TaggedCmnds=%i (%i), DelayReset=%is\n", 
 		tmscsim[0], tmscsim[1], speed/10, speed%10,
 		(UCHAR)tmscsim[2], (UCHAR)tmscsim[3], tmscsim[4], 2 << (tmscsim[4]), tmscsim[5]);
-#endif
     }
     else
     {
--- diff/drivers/serial/68360serial.c	2003-06-30 10:07:23.000000000 +0100
+++ source/drivers/serial/68360serial.c	2004-02-23 13:56:45.000000000 +0000
@@ -1282,12 +1282,19 @@ static int get_lsr_info(struct async_str
 }
 #endif
 
-static int get_modem_info(ser_info_t *info, unsigned int *value)
+static int rs_360_tiocmget(struct tty_struct *tty, struct file *file)
 {
+	ser_info_t *info = (ser_info_t *)tty->driver_data;
 	unsigned int result = 0;
 #ifdef modem_control
 	unsigned char control, status;
 
+	if (serial_paranoia_check(info, tty->name, __FUNCTION__))
+		return -ENODEV;
+
+	if (tty->flags & (1 << TTY_IO_ERROR))
+		return -EIO;
+
 	control = info->MCR;
 	local_irq_disable();
 	status = serial_in(info, UART_MSR);
@@ -1303,63 +1310,42 @@ static int get_modem_info(ser_info_t *in
 		| ((status  & UART_MSR_DSR) ? TIOCM_DSR : 0)
 		| ((status  & UART_MSR_CTS) ? TIOCM_CTS : 0);
 #endif
-	/* return put_user(result,value); */
-	put_user(result,value);
-	return (0);
+	return result;
 }
 
-static int set_modem_info(ser_info_t *info, unsigned int cmd,
-			  unsigned int *value)
+static int rs_360_tiocmset(struct tty_struct *tty, struct file *file,
+			   unsigned int set, unsigned int clear)
 {
-	int error;
- 	unsigned int arg; 
-
-	error = get_user(arg,value);
-	if (error)
-		return error;
 #ifdef modem_control
-	switch (cmd) {
-	case TIOCMBIS: 
-		if (arg & TIOCM_RTS)
-			info->MCR |= UART_MCR_RTS;
-		if (arg & TIOCM_DTR)
-			info->MCR |= UART_MCR_DTR;
-#ifdef TIOCM_OUT1
-		if (arg & TIOCM_OUT1)
-			info->MCR |= UART_MCR_OUT1;
-		if (arg & TIOCM_OUT2)
-			info->MCR |= UART_MCR_OUT2;
-#endif
-		break;
-	case TIOCMBIC:
-		if (arg & TIOCM_RTS)
-			info->MCR &= ~UART_MCR_RTS;
-		if (arg & TIOCM_DTR)
-			info->MCR &= ~UART_MCR_DTR;
-#ifdef TIOCM_OUT1
-		if (arg & TIOCM_OUT1)
-			info->MCR &= ~UART_MCR_OUT1;
-		if (arg & TIOCM_OUT2)
-			info->MCR &= ~UART_MCR_OUT2;
-#endif
-		break;
-	case TIOCMSET:
-		info->MCR = ((info->MCR & ~(UART_MCR_RTS |
-#ifdef TIOCM_OUT1
-					    UART_MCR_OUT1 |
-					    UART_MCR_OUT2 |
-#endif
-					    UART_MCR_DTR))
-			     | ((arg & TIOCM_RTS) ? UART_MCR_RTS : 0)
+	ser_info_t *info = (ser_info_t *)tty->driver_data;
+ 	unsigned int arg;
+
+	if (serial_paranoia_check(info, tty->name, __FUNCTION__))
+		return -ENODEV;
+
+	if (tty->flags & (1 << TTY_IO_ERROR))
+		return -EIO;
+
+ 	if (set & TIOCM_RTS)
+ 		info->mcr |= UART_MCR_RTS;
+ 	if (set & TIOCM_DTR)
+ 		info->mcr |= UART_MCR_DTR;
+	if (clear & TIOCM_RTS)
+		info->MCR &= ~UART_MCR_RTS;
+	if (clear & TIOCM_DTR)
+		info->MCR &= ~UART_MCR_DTR;
+
 #ifdef TIOCM_OUT1
-			     | ((arg & TIOCM_OUT1) ? UART_MCR_OUT1 : 0)
-			     | ((arg & TIOCM_OUT2) ? UART_MCR_OUT2 : 0)
+	if (set & TIOCM_OUT1)
+		info->MCR |= UART_MCR_OUT1;
+	if (set & TIOCM_OUT2)
+		info->MCR |= UART_MCR_OUT2;
+	if (clear & TIOCM_OUT1)
+		info->MCR &= ~UART_MCR_OUT1;
+	if (clear & TIOCM_OUT2)
+		info->MCR &= ~UART_MCR_OUT2;
 #endif
-			     | ((arg & TIOCM_DTR) ? UART_MCR_DTR : 0));
-		break;
-	default:
-		return -EINVAL;
-	}
+
 	local_irq_disable();
 	serial_out(info, UART_MCR, info->MCR);
 	local_irq_enable();
@@ -1506,12 +1492,6 @@ static int rs_360_ioctl(struct tty_struc
 				((tty->termios->c_cflag & ~CLOCAL) |
 				 (arg ? CLOCAL : 0));
 			return 0;
-		case TIOCMGET:
-			return get_modem_info(info, (unsigned int *) arg);
-		case TIOCMBIS:
-		case TIOCMBIC:
-		case TIOCMSET:
-			return set_modem_info(info, cmd, (unsigned int *) arg);
 #ifdef maybe
 		case TIOCSERGETLSR: /* Get line status register */
 			return get_lsr_info(info, (unsigned int *) arg);
@@ -2513,6 +2493,8 @@ static struct tty_operations rs_360_ops 
 	.hangup = rs_360_hangup,
 	/* .wait_until_sent = rs_360_wait_until_sent, */
 	/* .read_proc = rs_360_read_proc, */
+	.tiocmget = rs_360_tiocmget,
+	.tiocmset = rs_360_tiocmset,
 };
 
 /* int __init rs_360_init(void) */
--- diff/drivers/serial/8250.c	2004-01-19 10:22:58.000000000 +0000
+++ source/drivers/serial/8250.c	2004-02-23 13:56:45.000000000 +0000
@@ -837,7 +837,7 @@ receive_chars(struct uart_8250_port *up,
 		if (unlikely(tty->flip.count >= TTY_FLIPBUF_SIZE)) {
 			tty->flip.work.func((void *)tty);
 			if (tty->flip.count >= TTY_FLIPBUF_SIZE)
-				return; // if TTY_DONT_FLIP is set
+				return;	/* if TTY_DONT_FLIP is set */
 		}
 		ch = serial_inp(up, UART_RX);
 		*tty->flip.char_buf_ptr = ch;
@@ -1198,12 +1198,21 @@ static void serial8250_break_ctl(struct 
 	spin_unlock_irqrestore(&up->port.lock, flags);
 }
 
+#ifdef CONFIG_KGDB
+static int kgdb_irq = -1;
+#endif
+
 static int serial8250_startup(struct uart_port *port)
 {
 	struct uart_8250_port *up = (struct uart_8250_port *)port;
 	unsigned long flags;
 	int retval;
 
+#ifdef CONFIG_KGDB
+	if (up->port.irq == kgdb_irq)
+		return -EBUSY;
+#endif
+
 	up->capabilities = uart_config[up->port.type].flags;
 
 	if (up->port.type == PORT_16C950) {
@@ -1869,6 +1878,10 @@ static void __init serial8250_register_p
 	for (i = 0; i < UART_NR; i++) {
 		struct uart_8250_port *up = &serial8250_ports[i];
 
+#ifdef CONFIG_KGDB
+		if (up->port.irq == kgdb_irq)
+			up->port.kgdb = 1;
+#endif
 		up->port.line = i;
 		up->port.ops = &serial8250_pops;
 		init_timer(&up->timer);
@@ -2138,6 +2151,31 @@ void serial8250_resume_port(int line)
 	uart_resume_port(&serial8250_reg, &serial8250_ports[line].port);
 }
 
+#ifdef CONFIG_KGDB
+/*
+ * Find all the ports using the given irq and shut them down.
+ * Result should be that the irq will be released.
+ */
+void shutdown_for_kgdb(struct async_struct * info)
+{
+        int irq = info->state->irq;
+        struct uart_8250_port *up;
+	int ttyS;
+
+	kgdb_irq = irq;			/* save for later init */
+	for (ttyS = 0; ttyS < UART_NR; ttyS++){
+		up =  &serial8250_ports[ttyS];
+		if (up->port.irq == irq && (irq_lists + irq)->head) {
+#ifdef CONFIG_DEBUG_SPINLOCK   /* ugly business... */
+			if(up->port.lock.magic != SPINLOCK_MAGIC)
+				spin_lock_init(&up->port.lock);
+#endif
+			serial8250_shutdown(&up->port);
+		}
+        }
+}
+#endif	/* CONFIG_KGDB */
+
 static int __init serial8250_init(void)
 {
 	int ret, i;
--- diff/drivers/serial/8250_pnp.c	2004-02-18 08:54:11.000000000 +0000
+++ source/drivers/serial/8250_pnp.c	2004-02-23 13:56:45.000000000 +0000
@@ -21,8 +21,10 @@
 #include <linux/pnp.h>
 #include <linux/string.h>
 #include <linux/kernel.h>
+#include <linux/tty.h>
 #include <linux/serial.h>
 #include <linux/serialP.h>
+#include <linux/serial_core.h>
 
 #include <asm/bitops.h>
 #include <asm/byteorder.h>
@@ -408,7 +410,7 @@ serial_pnp_probe(struct pnp_dev * dev, c
 	       serial_req.port, serial_req.irq, serial_req.io_type);
 #endif
 
-	serial_req.flags = ASYNC_SKIP_TEST | ASYNC_AUTOPROBE;
+	serial_req.flags = UPF_SKIP_TEST | UPF_AUTOPROBE  | UPF_RESOURCES;
 	serial_req.baud_base = 115200;
 	line = register_serial(&serial_req);
 
--- diff/drivers/serial/Kconfig	2004-02-09 10:36:11.000000000 +0000
+++ source/drivers/serial/Kconfig	2004-02-23 13:56:45.000000000 +0000
@@ -256,6 +256,27 @@ config SERIAL_CLPS711X_OLD_NAME
 	help
 	  ::: To be written :::
 
+config SERIAL_DZ
+	bool "DECstation DZ serial driver"
+	depends on DECSTATION
+	select SERIAL_CORE
+	help
+	  DZ11-family serial controllers for VAXstations, including the
+	  DC7085, M7814, and M7819.
+
+config SERIAL_DZ_CONSOLE
+	bool "Support console on DECstation DZ serial driver"
+	depends on SERIAL_DZ=y
+	select SERIAL_CORE_CONSOLE
+	help
+	  If you say Y here, it will be possible to use a serial port as the
+	  system console (the system console is the device which receives all
+	  kernel messages and warnings and which allows logins in single user
+	  mode).  Note that the firmware uses ttyS0 as the serial console on
+	  the Maxine and ttyS2 on the others.
+
+	  If unsure, say Y.
+
 config SERIAL_21285
 	tristate "DC21285 serial port support"
 	depends on ARM && FOOTBRIDGE
@@ -303,6 +324,29 @@ config SERIAL_UART00_CONSOLE
 	  your boot loader (lilo or loadlin) about how to pass options to the
 	  kernel at boot time.)
 
+config SERIAL_PXA
+	bool "PXA serial port support"
+	depends on ARM && ARCH_PXA
+	select SERIAL_CORE
+	help
+	  If you have a machine based on an Intel XScale PXA2xx CPU you
+	  can enable its onboard serial ports by enabling this option.
+
+config SERIAL_PXA_CONSOLE
+	bool "Console on PXA serial port"
+	depends on SERIAL_PXA
+	select SERIAL_CORE_CONSOLE
+	help
+	  If you have enabled the serial port on the Intel XScale PXA
+	  CPU you can make it the console by answering Y to this option.
+
+	  Even if you say Y here, the currently visible virtual console
+	  (/dev/tty0) will still be used as the system console by default, but
+	  you can alter that using a kernel command line option such as
+	  "console=ttySA0". (Try "man bootparam" or see the documentation of
+	  your boot loader (lilo or loadlin) about how to pass options to the
+	  kernel at boot time.)
+
 config SERIAL_SA1100
 	bool "SA1100 serial port support"
 	depends on ARM && ARCH_SA1100
@@ -422,6 +466,20 @@ config SERIAL_SUNSAB_CONSOLE
 	  on your Sparc system as the console, you can do so by answering
 	  Y to this option.
 
+config SERIAL_IP22_ZILOG
+	tristate "IP22 Zilog8530 serial support"
+	depends on SGI_IP22
+	select SERIAL_CORE
+	help
+	  This driver supports the Zilog8530 serial ports found on SGI IP22
+	  systems.  Say Y or M if you want to be able to these serial ports.
+
+config SERIAL_IP22_ZILOG_CONSOLE
+	bool "Console on IP22 Zilog8530 serial port"
+	depends on SERIAL_IP22_ZILOG=y
+	select SERIAL_CORE_CONSOLE
+	help
+
 config V850E_UART
 	bool "NEC V850E on-chip UART support"
 	depends on V850E_MA1 || V850E_ME2 || V850E_TEG || V850E2_ANNA || V850E_AS85EP1
@@ -451,6 +509,22 @@ config SERIAL98_CONSOLE
         depends on SERIAL98=y
 	select SERIAL_CORE_CONSOLE
 
+config SERIAL_AU1X00
+	bool "Enable Au1x00 UART Support"
+	depends on MIPS && SOC_AU1X00
+	select SERIAL_CORE
+	help
+	  If you have an Alchemy AU1X00 processor (MIPS based) and you want
+	  to use serial ports, say Y.  Otherwise, say N.
+
+config SERIAL_AU1X00_CONSOLE
+	bool "Enable Au1x00 serial console"
+	depends on SERIAL_AU1X00
+	select SERIAL_CORE_CONSOLE
+	help
+	  If you have an Alchemy AU1X00 processor (MIPS based) and you want
+	  to use a console on a serial port, say Y.  Otherwise, say N.
+
 config SERIAL_CORE
 	tristate
 
--- diff/drivers/serial/Makefile	2003-09-30 15:46:17.000000000 +0100
+++ source/drivers/serial/Makefile	2004-02-23 13:56:45.000000000 +0000
@@ -5,11 +5,11 @@
 #
 
 serial-8250-y :=
+serial-8250-$(CONFIG_SERIAL_8250_ACPI) += 8250_acpi.o
 serial-8250-$(CONFIG_GSC) += 8250_gsc.o
 serial-8250-$(CONFIG_PCI) += 8250_pci.o
 serial-8250-$(CONFIG_PNP) += 8250_pnp.o
 serial-8250-$(CONFIG_SERIAL_8250_HCDP) += 8250_hcdp.o
-serial-8250-$(CONFIG_SERIAL_8250_ACPI) += 8250_acpi.o
 
 obj-$(CONFIG_SERIAL_CORE) += serial_core.o
 obj-$(CONFIG_SERIAL_21285) += 21285.o
@@ -19,10 +19,12 @@ obj-$(CONFIG_SERIAL_8250_ACORN) += 8250_
 obj-$(CONFIG_SERIAL_ANAKIN) += anakin.o
 obj-$(CONFIG_SERIAL_AMBA) += amba.o
 obj-$(CONFIG_SERIAL_CLPS711X) += clps711x.o
+obj-$(CONFIG_SERIAL_PXA) += pxa.o
 obj-$(CONFIG_SERIAL_SA1100) += sa1100.o
 obj-$(CONFIG_SERIAL_UART00) += uart00.o
 obj-$(CONFIG_SERIAL_SUNCORE) += suncore.o
 obj-$(CONFIG_SERIAL_SUNZILOG) += sunzilog.o
+obj-$(CONFIG_SERIAL_IP22_ZILOG) += ip22zilog.o
 obj-$(CONFIG_SERIAL_SUNSU) += sunsu.o
 obj-$(CONFIG_SERIAL_SUNSAB) += sunsab.o
 obj-$(CONFIG_SERIAL_MUX) += mux.o
@@ -32,3 +34,5 @@ obj-$(CONFIG_SERIAL_COLDFIRE) += mcfseri
 obj-$(CONFIG_V850E_UART) += v850e_uart.o
 obj-$(CONFIG_SERIAL98) += serial98.o
 obj-$(CONFIG_SERIAL_PMACZILOG) += pmac_zilog.o
+obj-$(CONFIG_SERIAL_AU1X00) += au1x00_uart.o
+obj-$(CONFIG_SERIAL_DZ) += dz.o
--- diff/drivers/serial/mcfserial.c	2003-07-11 09:39:50.000000000 +0100
+++ source/drivers/serial/mcfserial.c	2004-02-23 13:56:45.000000000 +0000
@@ -985,13 +985,51 @@ static void send_break(	struct mcf_seria
 	local_irq_restore(flags);
 }
 
+static int mcfrs_tiocmget(struct tty_struct *tty, struct file *file)
+{
+	struct mcf_serial * info = (struct mcf_serial *)tty->driver_data;
+
+	if (serial_paranoia_check(info, tty->name, "mcfrs_ioctl"))
+		return -ENODEV;
+	if (tty->flags & (1 << TTY_IO_ERROR))
+		return -EIO;
+
+	return mcfrs_getsignals(info);
+}
+
+static int mcfrs_tiocmset(struct tty_struct *tty, struct file *file,
+			  unsigned int set, unsigned int clear)
+{
+	struct mcf_serial * info = (struct mcf_serial *)tty->driver_data;
+	int rts = -1, dtr = -1;
+
+	if (serial_paranoia_check(info, tty->name, "mcfrs_ioctl"))
+		return -ENODEV;
+	if (tty->flags & (1 << TTY_IO_ERROR))
+		return -EIO;
+
+	if (set & TIOCM_RTS)
+		rts = 1;
+	if (set & TIOCM_DTR)
+		dtr = 1;
+	if (clear & TIOCM_RTS)
+		rts = 0;
+	if (clear & TIOCM_DTR)
+		dtr = 0;
+
+	mcfrs_setsignals(info, dtr, rts);
+
+	return 0;
+}
+
 static int mcfrs_ioctl(struct tty_struct *tty, struct file * file,
 		    unsigned int cmd, unsigned long arg)
 {
 	struct mcf_serial * info = (struct mcf_serial *)tty->driver_data;
+#ifdef TIOCSET422
 	unsigned int val;
+#endif
 	int retval, error;
-	int dtr, rts;
 
 	if (serial_paranoia_check(info, tty->name, "mcfrs_ioctl"))
 		return -ENODEV;
@@ -1059,45 +1097,6 @@ static int mcfrs_ioctl(struct tty_struct
 				    info, sizeof(struct mcf_serial));
 			return 0;
 			
-		case TIOCMGET:
-			if ((error = verify_area(VERIFY_WRITE, (void *) arg,
-                            sizeof(unsigned int))))
-                                return(error);
-			val = mcfrs_getsignals(info);
-			put_user(val, (unsigned int *) arg);
-			break;
-
-                case TIOCMBIS:
-			if ((error = verify_area(VERIFY_WRITE, (void *) arg,
-                            sizeof(unsigned int))))
-				return(error);
-
-			get_user(val, (unsigned int *) arg);
-			rts = (val & TIOCM_RTS) ? 1 : -1;
-			dtr = (val & TIOCM_DTR) ? 1 : -1;
-			mcfrs_setsignals(info, dtr, rts);
-			break;
-
-                case TIOCMBIC:
-			if ((error = verify_area(VERIFY_WRITE, (void *) arg,
-                            sizeof(unsigned int))))
-				return(error);
-			get_user(val, (unsigned int *) arg);
-			rts = (val & TIOCM_RTS) ? 0 : -1;
-			dtr = (val & TIOCM_DTR) ? 0 : -1;
-			mcfrs_setsignals(info, dtr, rts);
-			break;
-
-                case TIOCMSET:
-			if ((error = verify_area(VERIFY_WRITE, (void *) arg,
-                            sizeof(unsigned int))))
-				return(error);
-			get_user(val, (unsigned int *) arg);
-			rts = (val & TIOCM_RTS) ? 1 : 0;
-			dtr = (val & TIOCM_DTR) ? 1 : 0;
-			mcfrs_setsignals(info, dtr, rts);
-			break;
-
 #ifdef TIOCSET422
 		case TIOCSET422:
 			get_user(val, (unsigned int *) arg);
@@ -1563,6 +1562,8 @@ static struct tty_operations mcfrs_ops =
 	.start = mcfrs_start,
 	.hangup = mcfrs_hangup,
 	.read_proc = mcfrs_readproc,
+	.tiocmget = mcfrs_tiocmget,
+	.tiocmset = mcfrs_tiocmset,
 };
 
 /* mcfrs_init inits the driver */
--- diff/drivers/serial/serial_core.c	2004-02-09 10:36:11.000000000 +0000
+++ source/drivers/serial/serial_core.c	2004-02-23 13:56:45.000000000 +0000
@@ -1666,9 +1666,12 @@ static int uart_line_info(char *buf, str
 	if (!port)
 		return 0;
 
-	ret = sprintf(buf, "%d: uart:%s port:%08X irq:%d",
+	ret = sprintf(buf, "%d: uart:%s %s%08lX irq:%d",
 			port->line, uart_type(port),
-			port->iobase, port->irq);
+			port->iotype == UPIO_MEM ? "mmio:0x" : "port:",
+			port->iotype == UPIO_MEM ? port->mapbase :
+						(unsigned long) port->iobase,
+			port->irq);
 
 	if (port->type == PORT_UNKNOWN) {
 		strcat(buf, "\n");
@@ -1987,6 +1990,11 @@ uart_configure_port(struct uart_driver *
 {
 	unsigned int flags;
 
+#ifdef CONFIG_KGDB
+	if (port->kgdb)
+		return;
+#endif
+
 	/*
 	 * If there isn't a port here, don't do anything further.
 	 */
--- diff/drivers/tc/zs.c	2003-09-30 15:46:17.000000000 +0100
+++ source/drivers/tc/zs.c	2004-02-23 13:56:45.000000000 +0000
@@ -1176,11 +1176,21 @@ static int get_lsr_info(struct dec_seria
 	return 0;
 }
 
-static int get_modem_info(struct dec_serial *info, unsigned int *value)
+static int rs_tiocmget(struct tty_struct *tty, struct file *file)
 {
+	struct dec_serial * info = (struct dec_serial *)tty->driver_data;
 	unsigned char control, status_a, status_b;
 	unsigned int result;
 
+	if (info->hook)
+		return -ENODEV;
+
+	if (serial_paranoia_check(info, tty->name, __FUNCTION__))
+		return -ENODEV;
+
+	if (tty->flags & (1 << TTY_IO_ERROR))
+		return -EIO;
+
 	if (info->zs_channel == info->zs_chan_a)
 		result = 0;
 	else {
@@ -1196,41 +1206,37 @@ static int get_modem_info(struct dec_ser
 			| ((status_a & SYNC_HUNT) ? TIOCM_DSR: 0)
 			| ((status_b & CTS) ? TIOCM_CTS: 0);
 	}
-	put_user(result, value);
-	return 0;
+	return result;
 }
 
-static int set_modem_info(struct dec_serial *info, unsigned int cmd,
-			  unsigned int *value)
+static int rs_tiocmset(struct tty_struct *tty, struct file *file,
+		       unsigned int set, unsigned int clear)
 {
+	struct dec_serial * info = (struct dec_serial *)tty->driver_data;
 	int error;
 	unsigned int arg, bits;
 
-	error = verify_area(VERIFY_READ, value, sizeof(int));
-	if (error)
-		return error;
+	if (info->hook)
+		return -ENODEV;
+
+	if (serial_paranoia_check(info, tty->name, __FUNCTION__))
+		return -ENODEV;
+
+	if (tty->flags & (1 << TTY_IO_ERROR))
+		return -EIO;
 
 	if (info->zs_channel == info->zs_chan_a)
 		return 0;
 
-	get_user(arg, value);
-	bits = (arg & TIOCM_RTS? RTS: 0) + (arg & TIOCM_DTR? DTR: 0);
 	cli();
-	switch (cmd) {
-	case TIOCMBIS:
-		info->zs_chan_a->curregs[5] |= bits;
-		break;
-	case TIOCMBIC:
-		info->zs_chan_a->curregs[5] &= ~bits;
-		break;
-	case TIOCMSET:
-		info->zs_chan_a->curregs[5] = 
-			(info->zs_chan_a->curregs[5] & ~(DTR | RTS)) | bits;
-		break;
-	default:
-		sti();
-		return -EINVAL;
-	}
+	if (set & TIOCM_RTS)
+		info->zs_chan_a->curregs[5] |= RTS;
+	if (set & TIOCM_DTR)
+		info->zs_chan_a->curregs[5] |= DTR;
+	if (clear & TIOCM_RTS)
+		info->zs_chan_a->curregs[5] &= ~RTS;
+	if (clear & TIOCM_DTR)
+		info->zs_chan_a->curregs[5] &= ~DTR;
 	write_zsreg(info->zs_chan_a, 5, info->zs_chan_a->curregs[5]);
 	sti();
 	return 0;
@@ -1278,16 +1284,6 @@ static int rs_ioctl(struct tty_struct *t
 	}
 	
 	switch (cmd) {
-		case TIOCMGET:
-			error = verify_area(VERIFY_WRITE, (void *) arg,
-				sizeof(unsigned int));
-			if (error)
-				return error;
-			return get_modem_info(info, (unsigned int *) arg);
-		case TIOCMBIS:
-		case TIOCMBIC:
-		case TIOCMSET:
-			return set_modem_info(info, cmd, (unsigned int *) arg);
 		case TIOCGSERIAL:
 			error = verify_area(VERIFY_WRITE, (void *) arg,
 						sizeof(struct serial_struct));
@@ -1816,6 +1812,8 @@ static struct tty_operations serial_ops 
 	.hangup = rs_hangup,
 	.break_ctl = rs_break,
 	.wait_until_sent = rs_wait_until_sent,
+	.tiocmget = rs_tiocmget,
+	.tiocmset = rs_tiocmset,
 };
 
 /* zs_init inits the driver */
--- diff/drivers/telephony/ixj.h	2003-10-09 09:47:34.000000000 +0100
+++ source/drivers/telephony/ixj.h	2004-02-23 13:56:46.000000000 +0000
@@ -60,13 +60,6 @@ typedef __u8 BOOL;
 #define TRUE 1
 #define FALSE 0
 
-#ifndef min
-#define min(a,b) (((a)<(b))?(a):(b))
-#endif
-#ifndef max
-#define max(a,b) (((a)>(b))?(a):(b))
-#endif
-
 /******************************************************************************
 *
 *  This structure when unioned with the structures below makes simple byte
--- diff/drivers/usb/class/usblp.c	2004-01-19 10:22:58.000000000 +0000
+++ source/drivers/usb/class/usblp.c	2004-02-23 13:56:46.000000000 +0000
@@ -603,7 +603,7 @@ static ssize_t usblp_write(struct file *
 {
 	DECLARE_WAITQUEUE(wait, current);
 	struct usblp *usblp = file->private_data;
-	int timeout, err = 0;
+	int timeout, err = 0, transfer_length;
 	size_t writecount = 0;
 
 	while (writecount < count) {
@@ -654,19 +654,13 @@ static ssize_t usblp_write(struct file *
 			continue;
 		}
 
-		writecount += usblp->writeurb->transfer_buffer_length;
-		usblp->writeurb->transfer_buffer_length = 0;
+		transfer_length=(count - writecount);
+		if (transfer_length > USBLP_BUF_SIZE)
+			transfer_length = USBLP_BUF_SIZE;
 
-		if (writecount == count) {
-			up (&usblp->sem);
-			break;
-		}
+		usblp->writeurb->transfer_buffer_length = transfer_length;
 
-		usblp->writeurb->transfer_buffer_length = (count - writecount) < USBLP_BUF_SIZE ?
-							  (count - writecount) : USBLP_BUF_SIZE;
-
-		if (copy_from_user(usblp->writeurb->transfer_buffer, buffer + writecount,
-				usblp->writeurb->transfer_buffer_length)) {
+		if (copy_from_user(usblp->writeurb->transfer_buffer, buffer + writecount, transfer_length)) {
 			up(&usblp->sem);
 			return writecount ? writecount : -EFAULT;
 		}
@@ -683,6 +677,8 @@ static ssize_t usblp_write(struct file *
 			break;
 		}
 		up (&usblp->sem);
+
+		writecount += transfer_length;
 	}
 
 	return count;
--- diff/drivers/usb/core/buffer.c	2004-02-09 10:36:11.000000000 +0000
+++ source/drivers/usb/core/buffer.c	2004-02-23 13:56:46.000000000 +0000
@@ -2,14 +2,19 @@
  * DMA memory management for framework level HCD code (hc_driver)
  *
  * This implementation plugs in through generic "usb_bus" level methods,
- * and works with real PCI, or when "pci device == null" makes sense.
+ * and should work with all USB controllers, regardles of bus type.
  */
 
 #include <linux/config.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/slab.h>
-#include <linux/pci.h>
+#include <linux/device.h>
+#include <linux/mm.h>
+#include <asm/io.h>
+#include <asm/scatterlist.h>
+#include <linux/dma-mapping.h>
+#include <linux/dmapool.h>
 
 
 #ifdef CONFIG_USB_DEBUG
@@ -62,7 +67,7 @@ int hcd_buffer_create (struct usb_hcd *h
 		if (!(size = pool_max [i]))
 			continue;
 		snprintf (name, sizeof name, "buffer-%d", size);
-		hcd->pool [i] = pci_pool_create (name, hcd->pdev,
+		hcd->pool [i] = dma_pool_create (name, hcd->self.controller,
 				size, size, 0);
 		if (!hcd->pool [i]) {
 			hcd_buffer_destroy (hcd);
@@ -86,9 +91,9 @@ void hcd_buffer_destroy (struct usb_hcd 
 	int		i;
 
 	for (i = 0; i < HCD_BUFFER_POOLS; i++) { 
-		struct pci_pool		*pool = hcd->pool [i];
+		struct dma_pool		*pool = hcd->pool [i];
 		if (pool) {
-			pci_pool_destroy (pool);
+			dma_pool_destroy (pool);
 			hcd->pool [i] = 0;
 		}
 	}
@@ -112,9 +117,9 @@ void *hcd_buffer_alloc (
 
 	for (i = 0; i < HCD_BUFFER_POOLS; i++) {
 		if (size <= pool_max [i])
-			return pci_pool_alloc (hcd->pool [i], mem_flags, dma);
+			return dma_pool_alloc (hcd->pool [i], mem_flags, dma);
 	}
-	return pci_alloc_consistent (hcd->pdev, size, dma);
+	return dma_alloc_coherent (hcd->self.controller, size, dma, 0);
 }
 
 void hcd_buffer_free (
@@ -131,9 +136,9 @@ void hcd_buffer_free (
 		return;
 	for (i = 0; i < HCD_BUFFER_POOLS; i++) {
 		if (size <= pool_max [i]) {
-			pci_pool_free (hcd->pool [i], addr, dma);
+			dma_pool_free (hcd->pool [i], addr, dma);
 			return;
 		}
 	}
-	pci_free_consistent (hcd->pdev, size, addr, dma);
+	dma_free_coherent (hcd->self.controller, size, addr, dma);
 }
--- diff/drivers/usb/core/hcd-pci.c	2003-10-27 09:20:38.000000000 +0000
+++ source/drivers/usb/core/hcd-pci.c	2004-02-23 13:56:46.000000000 +0000
@@ -146,12 +146,10 @@ clean_2:
 	pci_set_drvdata (dev, hcd);
 	hcd->driver = driver;
 	hcd->description = driver->description;
-	hcd->pdev = dev;
 	hcd->self.bus_name = pci_name(dev);
 	if (hcd->product_desc == NULL)
 		hcd->product_desc = "USB Host Controller";
 	hcd->self.controller = &dev->dev;
-	hcd->controller = hcd->self.controller;
 
 	if ((retval = hcd_buffer_create (hcd)) != 0) {
 clean_3:
@@ -159,11 +157,11 @@ clean_3:
 		goto clean_2;
 	}
 
-	dev_info (hcd->controller, "%s\n", hcd->product_desc);
+	dev_info (hcd->self.controller, "%s\n", hcd->product_desc);
 
 	/* till now HC has been in an indeterminate state ... */
 	if (driver->reset && (retval = driver->reset (hcd)) < 0) {
-		dev_err (hcd->controller, "can't reset\n");
+		dev_err (hcd->self.controller, "can't reset\n");
 		goto clean_3;
 	}
 	hcd->state = USB_STATE_HALT;
@@ -177,13 +175,13 @@ clean_3:
 	retval = request_irq (dev->irq, usb_hcd_irq, SA_SHIRQ,
 				hcd->description, hcd);
 	if (retval != 0) {
-		dev_err (hcd->controller,
+		dev_err (hcd->self.controller,
 				"request interrupt %s failed\n", bufp);
 		goto clean_3;
 	}
 	hcd->irq = dev->irq;
 
-	dev_info (hcd->controller, "irq %s, %s %p\n", bufp,
+	dev_info (hcd->self.controller, "irq %s, %s %p\n", bufp,
 		(driver->flags & HCD_MEMORY) ? "pci mem" : "io base",
 		base);
 
@@ -226,7 +224,7 @@ void usb_hcd_pci_remove (struct pci_dev 
 	hcd = pci_get_drvdata(dev);
 	if (!hcd)
 		return;
-	dev_info (hcd->controller, "remove, state %x\n", hcd->state);
+	dev_info (hcd->self.controller, "remove, state %x\n", hcd->state);
 
 	if (in_interrupt ())
 		BUG ();
@@ -235,7 +233,7 @@ void usb_hcd_pci_remove (struct pci_dev 
 	if (HCD_IS_RUNNING (hcd->state))
 		hcd->state = USB_STATE_QUIESCING;
 
-	dev_dbg (hcd->controller, "roothub graceful disconnect\n");
+	dev_dbg (hcd->self.controller, "roothub graceful disconnect\n");
 	usb_disconnect (&hub);
 
 	hcd->driver->stop (hcd);
@@ -273,15 +271,15 @@ int usb_hcd_pci_suspend (struct pci_dev 
 	int			retval = 0;
 
 	hcd = pci_get_drvdata(dev);
-	dev_dbg (hcd->controller, "suspend D%d --> D%d\n",
+	dev_dbg (hcd->self.controller, "suspend D%d --> D%d\n",
 			dev->current_state, state);
 
 	switch (hcd->state) {
 	case USB_STATE_HALT:
-		dev_dbg (hcd->controller, "halted; hcd not suspended\n");
+		dev_dbg (hcd->self.controller, "halted; hcd not suspended\n");
 		break;
 	case USB_STATE_SUSPENDED:
-		dev_dbg (hcd->controller, "hcd already suspended\n");
+		dev_dbg (hcd->self.controller, "hcd already suspended\n");
 		break;
 	default:
 		/* remote wakeup needs hub->suspend() cooperation */
@@ -293,7 +291,8 @@ int usb_hcd_pci_suspend (struct pci_dev 
 		hcd->state = USB_STATE_QUIESCING;
 		retval = hcd->driver->suspend (hcd, state);
 		if (retval)
-			dev_dbg (hcd->controller, "suspend fail, retval %d\n",
+			dev_dbg (hcd->self.controller, 
+					"suspend fail, retval %d\n",
 					retval);
 		else
 			hcd->state = USB_STATE_SUSPENDED;
@@ -316,11 +315,12 @@ int usb_hcd_pci_resume (struct pci_dev *
 	int			retval;
 
 	hcd = pci_get_drvdata(dev);
-	dev_dbg (hcd->controller, "resume from state D%d\n",
+	dev_dbg (hcd->self.controller, "resume from state D%d\n",
 			dev->current_state);
 
 	if (hcd->state != USB_STATE_SUSPENDED) {
-		dev_dbg (hcd->controller, "can't resume, not suspended!\n");
+		dev_dbg (hcd->self.controller, 
+				"can't resume, not suspended!\n");
 		return -EL3HLT;
 	}
 	hcd->state = USB_STATE_RESUMING;
@@ -333,7 +333,8 @@ int usb_hcd_pci_resume (struct pci_dev *
 
 	retval = hcd->driver->resume (hcd);
 	if (!HCD_IS_RUNNING (hcd->state)) {
-		dev_dbg (hcd->controller, "resume fail, retval %d\n", retval);
+		dev_dbg (hcd->self.controller, 
+				"resume fail, retval %d\n", retval);
 		usb_hc_died (hcd);
 	}
 
--- diff/drivers/usb/core/hcd.c	2004-02-18 08:54:11.000000000 +0000
+++ source/drivers/usb/core/hcd.c	2004-02-23 13:56:46.000000000 +0000
@@ -351,7 +351,7 @@ static int rh_call_control (struct usb_h
 			/* FALLTHROUGH */
 	case DeviceOutRequest | USB_REQ_CLEAR_FEATURE:
 	case DeviceOutRequest | USB_REQ_SET_FEATURE:
-		dev_dbg (hcd->controller, "no device features yet yet\n");
+		dev_dbg (hcd->self.controller, "no device features yet yet\n");
 		break;
 	case DeviceRequest | USB_REQ_GET_CONFIGURATION:
 		ubuf [0] = 1;
@@ -394,7 +394,7 @@ static int rh_call_control (struct usb_h
 		break;
 	case DeviceOutRequest | USB_REQ_SET_ADDRESS:
 		// wValue == urb->dev->devaddr
-		dev_dbg (hcd->controller, "root hub device address %d\n",
+		dev_dbg (hcd->self.controller, "root hub device address %d\n",
 			wValue);
 		break;
 
@@ -409,7 +409,7 @@ static int rh_call_control (struct usb_h
 			/* FALLTHROUGH */
 	case EndpointOutRequest | USB_REQ_CLEAR_FEATURE:
 	case EndpointOutRequest | USB_REQ_SET_FEATURE:
-		dev_dbg (hcd->controller, "no endpoint features yet\n");
+		dev_dbg (hcd->self.controller, "no endpoint features yet\n");
 		break;
 
 	/* CLASS REQUESTS (and errors) */
@@ -423,12 +423,12 @@ static int rh_call_control (struct usb_h
 error:
 		/* "protocol stall" on error */
 		urb->status = -EPIPE;
-		dev_dbg (hcd->controller, "unsupported hub control message (maxchild %d)\n",
+		dev_dbg (hcd->self.controller, "unsupported hub control message (maxchild %d)\n",
 				urb->dev->maxchild);
 	}
 	if (urb->status) {
 		urb->actual_length = 0;
-		dev_dbg (hcd->controller, "CTRL: TypeReq=0x%x val=0x%x idx=0x%x len=%d ==> %d\n",
+		dev_dbg (hcd->self.controller, "CTRL: TypeReq=0x%x val=0x%x idx=0x%x len=%d ==> %d\n",
 			typeReq, wValue, wIndex, wLength, urb->status);
 	}
 	if (bufp) {
@@ -464,7 +464,7 @@ static int rh_status_urb (struct usb_hcd
 			|| urb->status != -EINPROGRESS
 			|| urb->transfer_buffer_length < len
 			|| !HCD_IS_RUNNING (hcd->state)) {
-		dev_dbg (hcd->controller,
+		dev_dbg (hcd->self.controller,
 				"not queuing rh status urb, stat %d\n",
 				urb->status);
 		return -EINVAL;
@@ -1068,18 +1068,18 @@ static int hcd_submit_urb (struct urb *u
 	/* lower level hcd code should use *_dma exclusively,
 	 * unless it uses pio or talks to another transport.
 	 */
-	if (hcd->controller->dma_mask) {
+	if (hcd->self.controller->dma_mask) {
 		if (usb_pipecontrol (urb->pipe)
 			&& !(urb->transfer_flags & URB_NO_SETUP_DMA_MAP))
 			urb->setup_dma = dma_map_single (
-					hcd->controller,
+					hcd->self.controller,
 					urb->setup_packet,
 					sizeof (struct usb_ctrlrequest),
 					DMA_TO_DEVICE);
 		if (urb->transfer_buffer_length != 0
 			&& !(urb->transfer_flags & URB_NO_TRANSFER_DMA_MAP))
 			urb->transfer_dma = dma_map_single (
-					hcd->controller,
+					hcd->self.controller,
 					urb->transfer_buffer,
 					urb->transfer_buffer_length,
 					usb_pipein (urb->pipe)
@@ -1125,7 +1125,7 @@ unlink1 (struct usb_hcd *hcd, struct urb
 		/* failures "should" be harmless */
 		value = hcd->driver->urb_dequeue (hcd, urb);
 		if (value != 0)
-			dev_dbg (hcd->controller,
+			dev_dbg (hcd->self.controller,
 				"dequeue %p --> %d\n",
 				urb, value);
 	}
@@ -1232,7 +1232,7 @@ static int hcd_unlink_urb (struct urb *u
 	 * finish unlinking the initial failed usb_set_address().
 	 */
 	if (!hcd->saw_irq) {
-		dev_warn (hcd->controller, "Unlink after no-IRQ?  "
+		dev_warn (hcd->self.controller, "Unlink after no-IRQ?  "
 			"Different ACPI or APIC settings may help."
 			"\n");
 		hcd->saw_irq = 1;
@@ -1244,7 +1244,8 @@ static int hcd_unlink_urb (struct urb *u
 	 */
 	if (!(urb->transfer_flags & URB_ASYNC_UNLINK)) {
 		if (in_interrupt ()) {
-			dev_dbg (hcd->controller, "non-async unlink in_interrupt");
+			dev_dbg (hcd->self.controller, 
+				"non-async unlink in_interrupt");
 			retval = -EWOULDBLOCK;
 			goto done;
 		}
@@ -1363,7 +1364,7 @@ rescan:
 		if (tmp == -EINPROGRESS) {
 			tmp = urb->pipe;
 			unlink1 (hcd, urb);
-			dev_dbg (hcd->controller,
+			dev_dbg (hcd->self.controller,
 				"shutdown urb %p pipe %08x ep%d%s%s\n",
 				urb, tmp, usb_pipeendpoint (tmp),
 				(tmp & USB_DIR_IN) ? "in" : "out",
@@ -1417,7 +1418,7 @@ static int hcd_free_dev (struct usb_devi
 
 	/* device driver problem with refcounts? */
 	if (!list_empty (&dev->urb_list)) {
-		dev_dbg (hcd->controller, "free busy dev, %s devnum %d (bug!)\n",
+		dev_dbg (hcd->self.controller, "free busy dev, %s devnum %d (bug!)\n",
 			hcd->self.bus_name, udev->devnum);
 		return -EINVAL;
 	}
@@ -1474,15 +1475,16 @@ void usb_hcd_giveback_urb (struct usb_hc
 	// It would catch exit/unlink paths for all urbs.
 
 	/* lower level hcd code should use *_dma exclusively */
-	if (hcd->controller->dma_mask) {
+	if (hcd->self.controller->dma_mask) {
 		if (usb_pipecontrol (urb->pipe)
 			&& !(urb->transfer_flags & URB_NO_SETUP_DMA_MAP))
-			dma_unmap_single (hcd->controller, urb->setup_dma,
+			dma_unmap_single (hcd->self.controller, urb->setup_dma,
 					sizeof (struct usb_ctrlrequest),
 					DMA_TO_DEVICE);
 		if (urb->transfer_buffer_length != 0
 			&& !(urb->transfer_flags & URB_NO_TRANSFER_DMA_MAP))
-			dma_unmap_single (hcd->controller, urb->transfer_dma,
+			dma_unmap_single (hcd->self.controller, 
+					urb->transfer_dma,
 					urb->transfer_buffer_length,
 					usb_pipein (urb->pipe)
 					    ? DMA_FROM_DEVICE
@@ -1551,7 +1553,7 @@ static void hcd_panic (void *_hcd)
  */
 void usb_hc_died (struct usb_hcd *hcd)
 {
-	dev_err (hcd->controller, "HC died; cleaning up\n");
+	dev_err (hcd->self.controller, "HC died; cleaning up\n");
 
 	/* clean up old urbs and devices; needs a task context */
 	INIT_WORK (&hcd->work, hcd_panic, hcd);
--- diff/drivers/usb/core/hcd.h	2004-02-18 08:54:11.000000000 +0000
+++ source/drivers/usb/core/hcd.h	2004-02-23 13:56:46.000000000 +0000
@@ -76,17 +76,14 @@ struct usb_hcd {	/* usb_bus.hcpriv point
 	unsigned		saw_irq : 1;
 	int			irq;		/* irq allocated */
 	void			*regs;		/* device memory/io */
-	struct device		*controller;	/* handle to hardware */
 
-	/* a few non-PCI controllers exist, mostly for OHCI */
-	struct pci_dev		*pdev;		/* pci is typical */
 #ifdef	CONFIG_PCI
 	int			region;		/* pci region for regs */
 	u32			pci_state [16];	/* for PM state save */
 #endif
 
 #define HCD_BUFFER_POOLS	4
-	struct pci_pool		*pool [HCD_BUFFER_POOLS];
+	struct dma_pool		*pool [HCD_BUFFER_POOLS];
 
 	int			state;
 #	define	__ACTIVE		0x01
@@ -355,7 +352,7 @@ extern int usb_register_root_hub (struct
 static inline int hcd_register_root (struct usb_hcd *hcd)
 {
 	return usb_register_root_hub (
-		hcd_to_bus (hcd)->root_hub, hcd->controller);
+		hcd_to_bus (hcd)->root_hub, hcd->self.controller);
 }
 
 /*-------------------------------------------------------------------------*/
--- diff/drivers/usb/core/hub.c	2004-02-18 08:54:11.000000000 +0000
+++ source/drivers/usb/core/hub.c	2004-02-23 13:56:46.000000000 +0000
@@ -405,9 +405,14 @@ static int hub_configure(struct usb_hub 
 			hub->tt.hub = dev;
 			break;
 		case 2:
-			dev_dbg(hub_dev, "TT per port\n");
+			ret = usb_set_interface(dev, 0, 1);
+			if (ret == 0) {
+				dev_dbg(hub_dev, "TT per port\n");
+				hub->tt.multi = 1;
+			} else
+				dev_err(hub_dev, "Using single TT (err %d)\n",
+					ret);
 			hub->tt.hub = dev;
-			hub->tt.multi = 1;
 			break;
 		default:
 			dev_dbg(hub_dev, "Unrecognized hub protocol %d\n",
--- diff/drivers/usb/core/message.c	2004-02-09 10:36:11.000000000 +0000
+++ source/drivers/usb/core/message.c	2004-02-23 13:56:46.000000000 +0000
@@ -213,9 +213,8 @@ static void sg_clean (struct usb_sg_requ
 static void sg_complete (struct urb *urb, struct pt_regs *regs)
 {
 	struct usb_sg_request	*io = (struct usb_sg_request *) urb->context;
-	unsigned long		flags;
 
-	spin_lock_irqsave (&io->lock, flags);
+	spin_lock (&io->lock);
 
 	/* In 2.5 we require hcds' endpoint queues not to progress after fault
 	 * reports, until the completion callback (this!) returns.  That lets
@@ -269,7 +268,7 @@ static void sg_complete (struct urb *urb
 	if (!io->count)
 		complete (&io->complete);
 
-	spin_unlock_irqrestore (&io->lock, flags);
+	spin_unlock (&io->lock);
 }
 
 
@@ -441,12 +440,11 @@ nomem:
  */
 void usb_sg_wait (struct usb_sg_request *io)
 {
-	int		i;
-	unsigned long	flags;
+	int		i, entries = io->entries;
 
 	/* queue the urbs.  */
-	spin_lock_irqsave (&io->lock, flags);
-	for (i = 0; i < io->entries && !io->status; i++) {
+	spin_lock_irq (&io->lock);
+	for (i = 0; i < entries && !io->status; i++) {
 		int	retval;
 
 		io->urbs [i]->dev = io->dev;
@@ -455,7 +453,7 @@ void usb_sg_wait (struct usb_sg_request 
 		/* after we submit, let completions or cancelations fire;
 		 * we handshake using io->status.
 		 */
-		spin_unlock_irqrestore (&io->lock, flags);
+		spin_unlock_irq (&io->lock);
 		switch (retval) {
 			/* maybe we retrying will recover */
 		case -ENXIO:	// hc didn't queue this one
@@ -479,17 +477,25 @@ void usb_sg_wait (struct usb_sg_request 
 
 			/* fail any uncompleted urbs */
 		default:
+			spin_lock_irq (&io->lock);
+			io->count -= entries - i;
+			if (io->status == -EINPROGRESS)
+				io->status = retval;
+			if (io->count == 0)
+				complete (&io->complete);
+			spin_unlock_irq (&io->lock);
+
 			io->urbs [i]->dev = 0;
 			io->urbs [i]->status = retval;
 			dev_dbg (&io->dev->dev, "%s, submit --> %d\n",
 				__FUNCTION__, retval);
 			usb_sg_cancel (io);
 		}
-		spin_lock_irqsave (&io->lock, flags);
+		spin_lock_irq (&io->lock);
 		if (retval && io->status == -ECONNRESET)
 			io->status = retval;
 	}
-	spin_unlock_irqrestore (&io->lock, flags);
+	spin_unlock_irq (&io->lock);
 
 	/* OK, yes, this could be packaged as non-blocking.
 	 * So could the submit loop above ... but it's easier to
--- diff/drivers/usb/core/usb.c	2004-02-18 08:54:11.000000000 +0000
+++ source/drivers/usb/core/usb.c	2004-02-23 13:56:46.000000000 +0000
@@ -1152,12 +1152,19 @@ int usb_new_device(struct usb_device *de
 	config = dev->config[0].desc.bConfigurationValue;
 	if (dev->descriptor.bNumConfigurations != 1) {
 		for (i = 0; i < dev->descriptor.bNumConfigurations; i++) {
+			struct usb_interface_descriptor	*desc;
+
 			/* heuristic:  Linux is more likely to have class
 			 * drivers, so avoid vendor-specific interfaces.
 			 */
-			if (dev->config[i].interface[0]->altsetting
-						->desc.bInterfaceClass
-					== USB_CLASS_VENDOR_SPEC)
+			desc = &dev->config[i].interface[0]
+					->altsetting->desc;
+			if (desc->bInterfaceClass == USB_CLASS_VENDOR_SPEC)
+				continue;
+			/* COMM/2/all is CDC ACM, except 0xff is MSFT RNDIS */
+			if (desc->bInterfaceClass == USB_CLASS_COMM
+					&& desc->bInterfaceSubClass == 2
+					&& desc->bInterfaceProtocol == 0xff)
 				continue;
 			config = dev->config[i].desc.bConfigurationValue;
 			break;
--- diff/drivers/usb/gadget/goku_udc.c	2004-02-09 10:36:11.000000000 +0000
+++ source/drivers/usb/gadget/goku_udc.c	2004-02-23 13:56:46.000000000 +0000
@@ -1111,7 +1111,7 @@ dump_intmask(const char *label, u32 mask
 	int t;
 
 	/* int_status is the same format ... */
-	t = snprintf(*next, *size,
+	t = scnprintf(*next, *size,
 		"%s %05X =" FOURBITS EIGHTBITS EIGHTBITS "\n",
 		label, mask,
 		(mask & INT_PWRDETECT) ? " power" : "",
@@ -1164,7 +1164,7 @@ udc_proc_read(char *buffer, char **start
 	/* basic device status */
 	tmp = readl(&regs->power_detect);
 	is_usb_connected = tmp & PW_DETECT;
-	t = snprintf(next, size,
+	t = scnprintf(next, size,
 		"%s - %s\n"
 		"%s version: %s %s\n"
 		"Gadget driver: %s\n"
@@ -1198,7 +1198,7 @@ udc_proc_read(char *buffer, char **start
 		goto done;
 
 	/* registers for (active) device and ep0 */
-	t = snprintf(next, size, "\nirqs %lu\ndataset %02x "
+	t = scnprintf(next, size, "\nirqs %lu\ndataset %02x "
 			"single.bcs %02x.%02x state %x addr %u\n",
 			dev->irqs, readl(&regs->DataSet),
 			readl(&regs->EPxSingle), readl(&regs->EPxBCS),
@@ -1208,7 +1208,7 @@ udc_proc_read(char *buffer, char **start
 	next += t;
 
 	tmp = readl(&regs->dma_master);
-	t = snprintf(next, size,
+	t = scnprintf(next, size,
 		"dma %03X =" EIGHTBITS "%s %s\n", tmp,
 		(tmp & MST_EOPB_DIS) ? " eopb-" : "",
 		(tmp & MST_EOPB_ENA) ? " eopb+" : "",
@@ -1237,7 +1237,7 @@ udc_proc_read(char *buffer, char **start
 			continue;
 
 		tmp = readl(ep->reg_status);
-		t = snprintf(next, size,
+		t = scnprintf(next, size,
 			"%s %s max %u %s, irqs %lu, "
 			"status %02x (%s) " FOURBITS "\n",
 			ep->ep.name,
@@ -1277,7 +1277,7 @@ udc_proc_read(char *buffer, char **start
 		next += t;
 
 		if (list_empty(&ep->queue)) {
-			t = snprintf(next, size, "\t(nothing queued)\n");
+			t = scnprintf(next, size, "\t(nothing queued)\n");
 			if (t <= 0 || t > size)
 				goto done;
 			size -= t;
@@ -1295,7 +1295,7 @@ udc_proc_read(char *buffer, char **start
 			} else
 				tmp = req->req.actual;
 
-			t = snprintf(next, size,
+			t = scnprintf(next, size,
 				"\treq %p len %u/%u buf %p\n",
 				&req->req, tmp, req->req.length,
 				req->req.buf);
@@ -1913,7 +1913,7 @@ static int goku_probe(struct pci_dev *pd
 	INFO(dev, "%s\n", driver_desc);
 	INFO(dev, "version: " DRIVER_VERSION " %s\n", dmastr());
 #ifndef __sparc__
-	snprintf(buf, sizeof buf, "%d", pdev->irq);
+	scnprintf(buf, sizeof buf, "%d", pdev->irq);
 	bufp = buf;
 #else
 	bufp = __irq_itoa(pdev->irq);
--- diff/drivers/usb/gadget/net2280.c	2004-02-18 08:54:11.000000000 +0000
+++ source/drivers/usb/gadget/net2280.c	2004-02-23 13:56:46.000000000 +0000
@@ -1439,7 +1439,7 @@ show_function (struct device *_dev, char
 			|| !dev->driver->function
 			|| strlen (dev->driver->function) > PAGE_SIZE)
 		return 0;
-	return snprintf (buf, PAGE_SIZE, "%s\n", dev->driver->function);
+	return scnprintf (buf, PAGE_SIZE, "%s\n", dev->driver->function);
 }
 static DEVICE_ATTR (function, S_IRUGO, show_function, NULL);
 
@@ -1465,7 +1465,7 @@ show_registers (struct device *_dev, cha
 		s = "(none)";
 
 	/* Main Control Registers */
-	t = snprintf (next, size, "%s version " DRIVER_VERSION
+	t = scnprintf (next, size, "%s version " DRIVER_VERSION
 			", chiprev %04x, dma %s\n\n"
 			"devinit %03x fifoctl %08x gadget '%s'\n"
 			"pci irqenb0 %02x irqenb1 %08x "
@@ -1497,7 +1497,7 @@ show_registers (struct device *_dev, cha
 		/* full speed bit (6) not working?? */
 	} else
 			s = "not attached";
-	t = snprintf (next, size,
+	t = scnprintf (next, size,
 			"stdrsp %08x usbctl %08x usbstat %08x "
 				"addr 0x%02x (%s)\n",
 			readl (&dev->usb->stdrsp), t1, t2,
@@ -1519,7 +1519,7 @@ show_registers (struct device *_dev, cha
 
 		t1 = readl (&ep->regs->ep_cfg);
 		t2 = readl (&ep->regs->ep_rsp) & 0xff;
-		t = snprintf (next, size,
+		t = scnprintf (next, size,
 				"\n%s\tcfg %05x rsp (%02x) %s%s%s%s%s%s%s%s"
 					"irqenb %02x\n",
 				ep->ep.name, t1, t2,
@@ -1543,7 +1543,7 @@ show_registers (struct device *_dev, cha
 		size -= t;
 		next += t;
 
-		t = snprintf (next, size,
+		t = scnprintf (next, size,
 				"\tstat %08x avail %04x "
 				"(ep%d%s-%s)%s\n",
 				readl (&ep->regs->ep_stat),
@@ -1557,7 +1557,7 @@ show_registers (struct device *_dev, cha
 		if (!ep->dma)
 			continue;
 
-		t = snprintf (next, size,
+		t = scnprintf (next, size,
 				"  dma\tctl %08x stat %08x count %08x\n"
 				"\taddr %08x desc %08x\n",
 				readl (&ep->dma->dmactl),
@@ -1574,7 +1574,7 @@ show_registers (struct device *_dev, cha
 		// none yet 
 
 	/* Statistics */
-	t = snprintf (next, size, "\nirqs:  ");
+	t = scnprintf (next, size, "\nirqs:  ");
 	size -= t;
 	next += t;
 	for (i = 0; i < 7; i++) {
@@ -1583,12 +1583,12 @@ show_registers (struct device *_dev, cha
 		ep = &dev->ep [i];
 		if (i && !ep->irqs)
 			continue;
-		t = snprintf (next, size, " %s/%lu", ep->ep.name, ep->irqs);
+		t = scnprintf (next, size, " %s/%lu", ep->ep.name, ep->irqs);
 		size -= t;
 		next += t;
 
 	}
-	t = snprintf (next, size, "\n");
+	t = scnprintf (next, size, "\n");
 	size -= t;
 	next += t;
 
@@ -1624,7 +1624,7 @@ show_queues (struct device *_dev, char *
 			if (!d)
 				continue;
 			t = d->bEndpointAddress;
-			t = snprintf (next, size,
+			t = scnprintf (next, size,
 				"\n%s (ep%d%s-%s) max %04x %s fifo %d\n",
 				ep->ep.name, t & USB_ENDPOINT_NUMBER_MASK,
 				(t & USB_DIR_IN) ? "in" : "out",
@@ -1641,7 +1641,7 @@ show_queues (struct device *_dev, char *
 				ep->dma ? "dma" : "pio", ep->fifo_size
 				);
 		} else /* ep0 should only have one transfer queued */
-			t = snprintf (next, size, "ep0 max 64 pio %s\n",
+			t = scnprintf (next, size, "ep0 max 64 pio %s\n",
 					ep->is_in ? "in" : "out");
 		if (t <= 0 || t > size)
 			goto done;
@@ -1649,7 +1649,7 @@ show_queues (struct device *_dev, char *
 		next += t;
 
 		if (list_empty (&ep->queue)) {
-			t = snprintf (next, size, "\t(nothing queued)\n");
+			t = scnprintf (next, size, "\t(nothing queued)\n");
 			if (t <= 0 || t > size)
 				goto done;
 			size -= t;
@@ -1658,14 +1658,14 @@ show_queues (struct device *_dev, char *
 		}
 		list_for_each_entry (req, &ep->queue, queue) {
 			if (ep->dma && req->td_dma == readl (&ep->dma->dmadesc))
-				t = snprintf (next, size,
+				t = scnprintf (next, size,
 					"\treq %p len %d/%d "
 					"buf %p (dmacount %08x)\n",
 					&req->req, req->req.actual,
 					req->req.length, req->req.buf,
 					readl (&ep->dma->dmacount));
 			else
-				t = snprintf (next, size,
+				t = scnprintf (next, size,
 					"\treq %p len %d/%d buf %p\n",
 					&req->req, req->req.actual,
 					req->req.length, req->req.buf);
@@ -1678,7 +1678,7 @@ show_queues (struct device *_dev, char *
 				struct net2280_dma	*td;
 
 				td = req->td;
-				t = snprintf (next, size, "\t    td %08x "
+				t = scnprintf (next, size, "\t    td %08x "
 					" count %08x buf %08x desc %08x\n",
 					req->td_dma, td->dmacount,
 					td->dmaaddr, td->dmadesc);
@@ -2788,7 +2788,7 @@ static int net2280_probe (struct pci_dev
 		goto done;
 	}
 #ifndef __sparc__
-	snprintf (buf, sizeof buf, "%d", pdev->irq);
+	scnprintf (buf, sizeof buf, "%d", pdev->irq);
 	bufp = buf;
 #else
 	bufp = __irq_itoa(pdev->irq);
--- diff/drivers/usb/gadget/pxa2xx_udc.c	2004-02-18 08:54:12.000000000 +0000
+++ source/drivers/usb/gadget/pxa2xx_udc.c	2004-02-23 13:56:46.000000000 +0000
@@ -1232,7 +1232,7 @@ udc_proc_read(char *page, char **start, 
 	local_irq_save(flags);
 
 	/* basic device status */
-	t = snprintf(next, size, DRIVER_DESC "\n"
+	t = scnprintf(next, size, DRIVER_DESC "\n"
 		"%s version: %s\nGadget driver: %s\nHost %s\n\n",
 		driver_name, DRIVER_VERSION SIZE_STR DMASTR,
 		dev->driver ? dev->driver->driver.name : "(none)",
@@ -1241,14 +1241,14 @@ udc_proc_read(char *page, char **start, 
 	next += t;
 
 	/* registers for device and ep0 */
-	t = snprintf(next, size,
+	t = scnprintf(next, size,
 		"uicr %02X.%02X, usir %02X.%02x, ufnr %02X.%02X\n",
 		UICR1, UICR0, USIR1, USIR0, UFNRH, UFNRL);
 	size -= t;
 	next += t;
 
 	tmp = UDCCR;
-	t = snprintf(next, size,
+	t = scnprintf(next, size,
 		"udccr %02X =%s%s%s%s%s%s%s%s\n", tmp,
 		(tmp & UDCCR_REM) ? " rem" : "",
 		(tmp & UDCCR_RSTIR) ? " rstir" : "",
@@ -1262,7 +1262,7 @@ udc_proc_read(char *page, char **start, 
 	next += t;
 
 	tmp = UDCCS0;
-	t = snprintf(next, size,
+	t = scnprintf(next, size,
 		"udccs0 %02X =%s%s%s%s%s%s%s%s\n", tmp,
 		(tmp & UDCCS0_SA) ? " sa" : "",
 		(tmp & UDCCS0_RNE) ? " rne" : "",
@@ -1277,7 +1277,7 @@ udc_proc_read(char *page, char **start, 
 
 	if (dev->has_cfr) {
 		tmp = UDCCFR;
-		t = snprintf(next, size,
+		t = scnprintf(next, size,
 			"udccfr %02X =%s%s\n", tmp,
 			(tmp & UDCCFR_AREN) ? " aren" : "",
 			(tmp & UDCCFR_ACM) ? " acm" : "");
@@ -1288,7 +1288,7 @@ udc_proc_read(char *page, char **start, 
 	if (!is_usb_connected() || !dev->driver)
 		goto done;
 
-	t = snprintf(next, size, "ep0 IN %lu/%lu, OUT %lu/%lu\nirqs %lu\n\n",
+	t = scnprintf(next, size, "ep0 IN %lu/%lu, OUT %lu/%lu\nirqs %lu\n\n",
 		dev->stats.write.bytes, dev->stats.write.ops,
 		dev->stats.read.bytes, dev->stats.read.ops,
 		dev->stats.irqs);
@@ -1308,7 +1308,7 @@ udc_proc_read(char *page, char **start, 
 			if (!d)
 				continue;
 			tmp = *dev->ep [i].reg_udccs;
-			t = snprintf(next, size,
+			t = scnprintf(next, size,
 				"%s max %d %s udccs %02x irqs %lu/%lu\n",
 				ep->ep.name, le16_to_cpu (d->wMaxPacketSize),
 				(ep->dma >= 0) ? "dma" : "pio", tmp,
@@ -1316,7 +1316,7 @@ udc_proc_read(char *page, char **start, 
 			/* TODO translate all five groups of udccs bits! */
 
 		} else /* ep0 should only have one transfer queued */
-			t = snprintf(next, size, "ep0 max 16 pio irqs %lu\n",
+			t = scnprintf(next, size, "ep0 max 16 pio irqs %lu\n",
 				ep->pio_irqs);
 		if (t <= 0 || t > size)
 			goto done;
@@ -1324,7 +1324,7 @@ udc_proc_read(char *page, char **start, 
 		next += t;
 
 		if (list_empty(&ep->queue)) {
-			t = snprintf(next, size, "\t(nothing queued)\n");
+			t = scnprintf(next, size, "\t(nothing queued)\n");
 			if (t <= 0 || t > size)
 				goto done;
 			size -= t;
@@ -1334,7 +1334,7 @@ udc_proc_read(char *page, char **start, 
 		list_for_each_entry(req, &ep->queue, queue) {
 #ifdef	USE_DMA
 			if (ep->dma >= 0 && req->queue.prev == &ep->queue)
-				t = snprintf(next, size,
+				t = scnprintf(next, size,
 					"\treq %p len %d/%d "
 					"buf %p (dma%d dcmd %08x)\n",
 					&req->req, req->req.actual,
@@ -1344,7 +1344,7 @@ udc_proc_read(char *page, char **start, 
 					);
 			else
 #endif
-				t = snprintf(next, size,
+				t = scnprintf(next, size,
 					"\treq %p len %d/%d buf %p\n",
 					&req->req, req->req.actual,
 					req->req.length, req->req.buf);
@@ -1382,7 +1382,7 @@ show_function (struct device *_dev, char
 			|| !dev->driver->function
 			|| strlen (dev->driver->function) > PAGE_SIZE)
 		return 0;
-	return snprintf (buf, PAGE_SIZE, "%s\n", dev->driver->function);
+	return scnprintf (buf, PAGE_SIZE, "%s\n", dev->driver->function);
 }
 static DEVICE_ATTR (function, S_IRUGO, show_function, NULL);
 
--- diff/drivers/usb/host/ehci-dbg.c	2004-02-09 10:36:11.000000000 +0000
+++ source/drivers/usb/host/ehci-dbg.c	2004-02-23 13:56:46.000000000 +0000
@@ -19,13 +19,13 @@
 /* this file is part of ehci-hcd.c */
 
 #define ehci_dbg(ehci, fmt, args...) \
-	dev_dbg ((ehci)->hcd.controller , fmt , ## args )
+	dev_dbg ((ehci)->hcd.self.controller , fmt , ## args )
 #define ehci_err(ehci, fmt, args...) \
-	dev_err ((ehci)->hcd.controller , fmt , ## args )
+	dev_err ((ehci)->hcd.self.controller , fmt , ## args )
 #define ehci_info(ehci, fmt, args...) \
-	dev_info ((ehci)->hcd.controller , fmt , ## args )
+	dev_info ((ehci)->hcd.self.controller , fmt , ## args )
 #define ehci_warn(ehci, fmt, args...) \
-	dev_warn ((ehci)->hcd.controller , fmt , ## args )
+	dev_warn ((ehci)->hcd.self.controller , fmt , ## args )
 
 #ifdef EHCI_VERBOSE_DEBUG
 #	define vdbg dbg
@@ -173,7 +173,7 @@ dbg_itd (const char *label, struct ehci_
 static int __attribute__((__unused__))
 dbg_status_buf (char *buf, unsigned len, char *label, u32 status)
 {
-	return snprintf (buf, len,
+	return scnprintf (buf, len,
 		"%s%sstatus %04x%s%s%s%s%s%s%s%s%s%s",
 		label, label [0] ? " " : "", status,
 		(status & STS_ASS) ? " Async" : "",
@@ -192,7 +192,7 @@ dbg_status_buf (char *buf, unsigned len,
 static int __attribute__((__unused__))
 dbg_intr_buf (char *buf, unsigned len, char *label, u32 enable)
 {
-	return snprintf (buf, len,
+	return scnprintf (buf, len,
 		"%s%sintrenable %02x%s%s%s%s%s%s",
 		label, label [0] ? " " : "", enable,
 		(enable & STS_IAA) ? " IAA" : "",
@@ -209,7 +209,7 @@ static const char *const fls_strings [] 
 
 static int dbg_command_buf (char *buf, unsigned len, char *label, u32 command)
 {
-	return snprintf (buf, len,
+	return scnprintf (buf, len,
 		"%s%scommand %06x %s=%d ithresh=%d%s%s%s%s period=%s%s %s",
 		label, label [0] ? " " : "", command,
 		(command & CMD_PARK) ? "park" : "(park)",
@@ -238,7 +238,7 @@ dbg_port_buf (char *buf, unsigned len, c
 	default: sig = "?"; break;
 	}
 
-	return snprintf (buf, len,
+	return scnprintf (buf, len,
 		"%s%sport %d status %06x%s%s sig=%s %s%s%s%s%s%s%s%s%s",
 		label, label [0] ? " " : "", port, status,
 		(status & PORT_POWER) ? " POWER" : "",
@@ -359,7 +359,7 @@ static void qh_lines (
 	}
 	scratch = cpu_to_le32p (&qh->hw_info1);
 	hw_curr = (mark == '*') ? cpu_to_le32p (&qh->hw_current) : 0;
-	temp = snprintf (next, size,
+	temp = scnprintf (next, size,
 			"qh/%p dev%d %cs ep%d %08x %08x (%08x%c %s nak%d)",
 			qh, scratch & 0x007f,
 			speed_char (scratch),
@@ -367,7 +367,7 @@ static void qh_lines (
 			scratch, cpu_to_le32p (&qh->hw_info2),
 			cpu_to_le32p (&qh->hw_token), mark,
 			(__constant_cpu_to_le32 (QTD_TOGGLE) & qh->hw_token)
-				? "data0" : "data1",
+				? "data1" : "data0",
 			(cpu_to_le32p (&qh->hw_alt_next) >> 1) & 0x0f);
 	size -= temp;
 	next += temp;
@@ -449,7 +449,7 @@ show_async (struct class_device *class_d
 	for (qh = ehci->async->qh_next.qh; size > 0 && qh; qh = qh->qh_next.qh)
 		qh_lines (ehci, qh, &next, &size);
 	if (ehci->reclaim && size > 0) {
-		temp = snprintf (next, size, "\nreclaim =\n");
+		temp = scnprintf (next, size, "\nreclaim =\n");
 		size -= temp;
 		next += temp;
 
@@ -486,7 +486,7 @@ show_periodic (struct class_device *clas
 	next = buf;
 	size = PAGE_SIZE;
 
-	temp = snprintf (next, size, "size = %d\n", ehci->periodic_size);
+	temp = scnprintf (next, size, "size = %d\n", ehci->periodic_size);
 	size -= temp;
 	next += temp;
 
@@ -500,14 +500,14 @@ show_periodic (struct class_device *clas
 			continue;
 		tag = Q_NEXT_TYPE (ehci->periodic [i]);
 
-		temp = snprintf (next, size, "%4d: ", i);
+		temp = scnprintf (next, size, "%4d: ", i);
 		size -= temp;
 		next += temp;
 
 		do {
 			switch (tag) {
 			case Q_TYPE_QH:
-				temp = snprintf (next, size, " qh%d-%04x/%p",
+				temp = scnprintf (next, size, " qh%d-%04x/%p",
 						p.qh->period,
 						le32_to_cpup (&p.qh->hw_info2)
 							/* uframe masks */
@@ -520,7 +520,7 @@ show_periodic (struct class_device *clas
 					if (seen [temp].ptr != p.ptr)
 						continue;
 					if (p.qh->qh_next.ptr)
-						temp = snprintf (next, size,
+						temp = scnprintf (next, size,
 							" ...");
 					p.ptr = 0;
 					break;
@@ -545,7 +545,7 @@ show_periodic (struct class_device *clas
 						}
 					}
 
-					temp = snprintf (next, size,
+					temp = scnprintf (next, size,
 						" (%c%d ep%d%s "
 						"[%d/%d] q%d p%d)",
 						speed_char (scratch),
@@ -565,20 +565,20 @@ show_periodic (struct class_device *clas
 				}
 				break;
 			case Q_TYPE_FSTN:
-				temp = snprintf (next, size,
+				temp = scnprintf (next, size,
 					" fstn-%8x/%p", p.fstn->hw_prev,
 					p.fstn);
 				tag = Q_NEXT_TYPE (p.fstn->hw_next);
 				p = p.fstn->fstn_next;
 				break;
 			case Q_TYPE_ITD:
-				temp = snprintf (next, size,
+				temp = scnprintf (next, size,
 					" itd/%p", p.itd);
 				tag = Q_NEXT_TYPE (p.itd->hw_next);
 				p = p.itd->itd_next;
 				break;
 			case Q_TYPE_SITD:
-				temp = snprintf (next, size,
+				temp = scnprintf (next, size,
 					" sitd/%p", p.sitd);
 				tag = Q_NEXT_TYPE (p.sitd->hw_next);
 				p = p.sitd->sitd_next;
@@ -588,7 +588,7 @@ show_periodic (struct class_device *clas
 			next += temp;
 		} while (p.ptr);
 
-		temp = snprintf (next, size, "\n");
+		temp = scnprintf (next, size, "\n");
 		size -= temp;
 		next += temp;
 	}
@@ -623,44 +623,44 @@ show_registers (struct class_device *cla
 
 	/* Capability Registers */
 	i = HC_VERSION(readl (&ehci->caps->hc_capbase));
-	temp = snprintf (next, size,
+	temp = scnprintf (next, size,
 		"PCI device %s\nEHCI %x.%02x, hcd state %d (driver " DRIVER_VERSION ")\n",
-		pci_name(hcd->pdev),
+		pci_name(to_pci_dev(hcd->self.controller)),
 		i >> 8, i & 0x0ff, ehci->hcd.state);
 	size -= temp;
 	next += temp;
 
 	// FIXME interpret both types of params
 	i = readl (&ehci->caps->hcs_params);
-	temp = snprintf (next, size, "structural params 0x%08x\n", i);
+	temp = scnprintf (next, size, "structural params 0x%08x\n", i);
 	size -= temp;
 	next += temp;
 
 	i = readl (&ehci->caps->hcc_params);
-	temp = snprintf (next, size, "capability params 0x%08x\n", i);
+	temp = scnprintf (next, size, "capability params 0x%08x\n", i);
 	size -= temp;
 	next += temp;
 
 	/* Operational Registers */
 	temp = dbg_status_buf (scratch, sizeof scratch, label,
 			readl (&ehci->regs->status));
-	temp = snprintf (next, size, fmt, temp, scratch);
+	temp = scnprintf (next, size, fmt, temp, scratch);
 	size -= temp;
 	next += temp;
 
 	temp = dbg_command_buf (scratch, sizeof scratch, label,
 			readl (&ehci->regs->command));
-	temp = snprintf (next, size, fmt, temp, scratch);
+	temp = scnprintf (next, size, fmt, temp, scratch);
 	size -= temp;
 	next += temp;
 
 	temp = dbg_intr_buf (scratch, sizeof scratch, label,
 			readl (&ehci->regs->intr_enable));
-	temp = snprintf (next, size, fmt, temp, scratch);
+	temp = scnprintf (next, size, fmt, temp, scratch);
 	size -= temp;
 	next += temp;
 
-	temp = snprintf (next, size, "uframe %04x\n",
+	temp = scnprintf (next, size, "uframe %04x\n",
 			readl (&ehci->regs->frame_index));
 	size -= temp;
 	next += temp;
@@ -668,13 +668,13 @@ show_registers (struct class_device *cla
 	for (i = 0; i < HCS_N_PORTS (ehci->hcs_params); i++) {
 		temp = dbg_port_buf (scratch, sizeof scratch, label, i,
 				readl (&ehci->regs->port_status [i]));
-		temp = snprintf (next, size, fmt, temp, scratch);
+		temp = scnprintf (next, size, fmt, temp, scratch);
 		size -= temp;
 		next += temp;
 	}
 
 	if (ehci->reclaim) {
-		temp = snprintf (next, size, "reclaim qh %p%s\n",
+		temp = scnprintf (next, size, "reclaim qh %p%s\n",
 				ehci->reclaim,
 				ehci->reclaim_ready ? " ready" : "");
 		size -= temp;
@@ -682,14 +682,14 @@ show_registers (struct class_device *cla
 	}
 
 #ifdef EHCI_STATS
-	temp = snprintf (next, size,
+	temp = scnprintf (next, size,
 		"irq normal %ld err %ld reclaim %ld (lost %ld)\n",
 		ehci->stats.normal, ehci->stats.error, ehci->stats.reclaim,
 		ehci->stats.lost_iaa);
 	size -= temp;
 	next += temp;
 
-	temp = snprintf (next, size, "complete %ld unlink %ld\n",
+	temp = scnprintf (next, size, "complete %ld unlink %ld\n",
 		ehci->stats.complete, ehci->stats.unlink);
 	size -= temp;
 	next += temp;
--- diff/drivers/usb/host/ehci-hcd.c	2004-02-18 08:54:12.000000000 +0000
+++ source/drivers/usb/host/ehci-hcd.c	2004-02-23 13:56:46.000000000 +0000
@@ -26,6 +26,7 @@
 
 #include <linux/module.h>
 #include <linux/pci.h>
+#include <linux/dmapool.h>
 #include <linux/kernel.h>
 #include <linux/delay.h>
 #include <linux/ioport.h>
@@ -40,6 +41,7 @@
 #include <linux/reboot.h>
 #include <linux/usb.h>
 #include <linux/moduleparam.h>
+#include <linux/dma-mapping.h>
 
 #include "../core/hcd.h"
 
@@ -67,6 +69,7 @@
  *
  * HISTORY:
  *
+ * 2004-02-24 Replace pci_* with generic dma_* API calls (dsaxena@plexity.net)
  * 2003-12-29 Rewritten high speed iso transfer support (by Michal Sojka,
  *	<sojkam@centrum.cz>, updates by DB).
  *
@@ -288,13 +291,13 @@ static int bios_handoff (struct ehci_hcd
 
 		/* request handoff to OS */
 		cap &= 1 << 24;
-		pci_write_config_dword (ehci->hcd.pdev, where, cap);
+		pci_write_config_dword (to_pci_dev(ehci->hcd.self.controller), where, cap);
 
 		/* and wait a while for it to happen */
 		do {
 			wait_ms (10);
 			msec -= 10;
-			pci_read_config_dword (ehci->hcd.pdev, where, &cap);
+			pci_read_config_dword (to_pci_dev(ehci->hcd.self.controller), where, &cap);
 		} while ((cap & (1 << 16)) && msec);
 		if (cap & (1 << 16)) {
 			ehci_err (ehci, "BIOS handoff failed (%d, %04x)\n",
@@ -339,7 +342,7 @@ static int ehci_hc_reset (struct usb_hcd
 	while (temp) {
 		u32		cap;
 
-		pci_read_config_dword (ehci->hcd.pdev, temp, &cap);
+		pci_read_config_dword (to_pci_dev(ehci->hcd.self.controller), temp, &cap);
 		ehci_dbg (ehci, "capability %04x at %02x\n", cap, temp);
 		switch (cap & 0xff) {
 		case 1:			/* BIOS/SMM/... handoff */
@@ -378,7 +381,7 @@ static int ehci_start (struct usb_hcd *h
 	 * periodic_size can shrink by USBCMD update if hcc_params allows.
 	 */
 	ehci->periodic_size = DEFAULT_I_TDPS;
-	if ((retval = ehci_mem_init (ehci, SLAB_KERNEL)) < 0)
+	if ((retval = ehci_mem_init (ehci, GFP_KERNEL)) < 0)
 		return retval;
 
 	/* controllers may cache some of the periodic schedule ... */
@@ -433,13 +436,13 @@ static int ehci_start (struct usb_hcd *h
 		writel (0, &ehci->regs->segment);
 #if 0
 // this is deeply broken on almost all architectures
-		if (!pci_set_dma_mask (ehci->hcd.pdev, 0xffffffffffffffffULL))
+		if (!pci_set_dma_mask (to_pci_dev(ehci->hcd.self.controller), 0xffffffffffffffffULL))
 			ehci_info (ehci, "enabled 64bit PCI DMA\n");
 #endif
 	}
 
 	/* help hc dma work well with cachelines */
-	pci_set_mwi (ehci->hcd.pdev);
+	pci_set_mwi (to_pci_dev(ehci->hcd.self.controller));
 
 	/* clear interrupt enables, set irq latency */
 	temp = readl (&ehci->regs->command) & 0x0fff;
@@ -493,7 +496,7 @@ done2:
 	readl (&ehci->regs->command);	/* unblock posted write */
 
         /* PCI Serial Bus Release Number is at 0x60 offset */
-	pci_read_config_byte (hcd->pdev, 0x60, &tempbyte);
+	pci_read_config_byte(to_pci_dev(hcd->self.controller), 0x60, &tempbyte);
 	temp = HC_VERSION(readl (&ehci->caps->hc_capbase));
 	ehci_info (ehci,
 		"USB %x.%x enabled, EHCI %x.%02x, driver %s\n",
@@ -758,7 +761,7 @@ done:
  * non-error returns are a promise to giveback() the urb later
  * we drop ownership so next owner (or urb unlink) can get it
  *
- * urb + dev is in hcd_dev.urb_list
+ * urb + dev is in hcd.self.controller.urb_list
  * we're queueing TDs onto software and hardware lists
  *
  * hcd-specific init for hcpriv hasn't been done yet
--- diff/drivers/usb/host/ehci-hub.c	2004-02-09 10:36:11.000000000 +0000
+++ source/drivers/usb/host/ehci-hub.c	2004-02-23 13:56:46.000000000 +0000
@@ -113,7 +113,7 @@ ehci_hub_descriptor (
 	u16		temp;
 
 	desc->bDescriptorType = 0x29;
-	desc->bPwrOn2PwrGood = 10;	/* FIXME: f(system power) */
+	desc->bPwrOn2PwrGood = 10;	/* ehci 1.0, 2.3.9 says 20ms max */
 	desc->bHubContrCurrent = 0;
 
 	desc->bNbrPorts = ports;
--- diff/drivers/usb/host/ehci-mem.c	2004-02-09 10:36:11.000000000 +0000
+++ source/drivers/usb/host/ehci-mem.c	2004-02-23 13:56:46.000000000 +0000
@@ -24,7 +24,7 @@
  * There's basically three types of memory:
  *	- data used only by the HCD ... kmalloc is fine
  *	- async and periodic schedules, shared by HC and HCD ... these
- *	  need to use pci_pool or pci_alloc_consistent
+ *	  need to use dma_pool or dma_alloc_coherent
  *	- driver buffers, read/written by HC ... single shot DMA mapped 
  *
  * There's also PCI "register" data, which is memory mapped.
@@ -74,7 +74,7 @@ static struct ehci_qtd *ehci_qtd_alloc (
 	struct ehci_qtd		*qtd;
 	dma_addr_t		dma;
 
-	qtd = pci_pool_alloc (ehci->qtd_pool, flags, &dma);
+	qtd = dma_pool_alloc (ehci->qtd_pool, flags, &dma);
 	if (qtd != 0) {
 		ehci_qtd_init (qtd, dma);
 	}
@@ -83,7 +83,7 @@ static struct ehci_qtd *ehci_qtd_alloc (
 
 static inline void ehci_qtd_free (struct ehci_hcd *ehci, struct ehci_qtd *qtd)
 {
-	pci_pool_free (ehci->qtd_pool, qtd, qtd->qtd_dma);
+	dma_pool_free (ehci->qtd_pool, qtd, qtd->qtd_dma);
 }
 
 
@@ -93,7 +93,7 @@ static struct ehci_qh *ehci_qh_alloc (st
 	dma_addr_t		dma;
 
 	qh = (struct ehci_qh *)
-		pci_pool_alloc (ehci->qh_pool, flags, &dma);
+		dma_pool_alloc (ehci->qh_pool, flags, &dma);
 	if (!qh)
 		return qh;
 
@@ -107,7 +107,7 @@ static struct ehci_qh *ehci_qh_alloc (st
 	qh->dummy = ehci_qtd_alloc (ehci, flags);
 	if (qh->dummy == 0) {
 		ehci_dbg (ehci, "no dummy td\n");
-		pci_pool_free (ehci->qh_pool, qh, qh->qh_dma);
+		dma_pool_free (ehci->qh_pool, qh, qh->qh_dma);
 		qh = 0;
 	}
 	return qh;
@@ -132,7 +132,7 @@ static void qh_put (struct ehci_hcd *ehc
 	if (qh->dummy)
 		ehci_qtd_free (ehci, qh->dummy);
 	usb_put_dev (qh->dev);
-	pci_pool_free (ehci->qh_pool, qh, qh->qh_dma);
+	dma_pool_free (ehci->qh_pool, qh, qh->qh_dma);
 }
 
 /*-------------------------------------------------------------------------*/
@@ -148,26 +148,26 @@ static void ehci_mem_cleanup (struct ehc
 		qh_put (ehci, ehci->async);
 	ehci->async = 0;
 
-	/* PCI consistent memory and pools */
+	/* DMA consistent memory and pools */
 	if (ehci->qtd_pool)
-		pci_pool_destroy (ehci->qtd_pool);
+		dma_pool_destroy (ehci->qtd_pool);
 	ehci->qtd_pool = 0;
 
 	if (ehci->qh_pool) {
-		pci_pool_destroy (ehci->qh_pool);
+		dma_pool_destroy (ehci->qh_pool);
 		ehci->qh_pool = 0;
 	}
 
 	if (ehci->itd_pool)
-		pci_pool_destroy (ehci->itd_pool);
+		dma_pool_destroy (ehci->itd_pool);
 	ehci->itd_pool = 0;
 
 	if (ehci->sitd_pool)
-		pci_pool_destroy (ehci->sitd_pool);
+		dma_pool_destroy (ehci->sitd_pool);
 	ehci->sitd_pool = 0;
 
 	if (ehci->periodic)
-		pci_free_consistent (ehci->hcd.pdev,
+		dma_free_coherent (ehci->hcd.self.controller,
 			ehci->periodic_size * sizeof (u32),
 			ehci->periodic, ehci->periodic_dma);
 	ehci->periodic = 0;
@@ -184,7 +184,8 @@ static int ehci_mem_init (struct ehci_hc
 	int i;
 
 	/* QTDs for control/bulk/intr transfers */
-	ehci->qtd_pool = pci_pool_create ("ehci_qtd", ehci->hcd.pdev,
+	ehci->qtd_pool = dma_pool_create ("ehci_qtd", 
+			ehci->hcd.self.controller,
 			sizeof (struct ehci_qtd),
 			32 /* byte alignment (for hw parts) */,
 			4096 /* can't cross 4K */);
@@ -193,7 +194,8 @@ static int ehci_mem_init (struct ehci_hc
 	}
 
 	/* QHs for control/bulk/intr transfers */
-	ehci->qh_pool = pci_pool_create ("ehci_qh", ehci->hcd.pdev,
+	ehci->qh_pool = dma_pool_create ("ehci_qh", 
+			ehci->hcd.self.controller,
 			sizeof (struct ehci_qh),
 			32 /* byte alignment (for hw parts) */,
 			4096 /* can't cross 4K */);
@@ -206,7 +208,8 @@ static int ehci_mem_init (struct ehci_hc
 	}
 
 	/* ITD for high speed ISO transfers */
-	ehci->itd_pool = pci_pool_create ("ehci_itd", ehci->hcd.pdev,
+	ehci->itd_pool = dma_pool_create ("ehci_itd", 
+			ehci->hcd.self.controller,
 			sizeof (struct ehci_itd),
 			32 /* byte alignment (for hw parts) */,
 			4096 /* can't cross 4K */);
@@ -215,7 +218,8 @@ static int ehci_mem_init (struct ehci_hc
 	}
 
 	/* SITD for full/low speed split ISO transfers */
-	ehci->sitd_pool = pci_pool_create ("ehci_sitd", ehci->hcd.pdev,
+	ehci->sitd_pool = dma_pool_create ("ehci_sitd", 
+			ehci->hcd.self.controller,
 			sizeof (struct ehci_sitd),
 			32 /* byte alignment (for hw parts) */,
 			4096 /* can't cross 4K */);
@@ -225,9 +229,9 @@ static int ehci_mem_init (struct ehci_hc
 
 	/* Hardware periodic table */
 	ehci->periodic = (u32 *)
-		pci_alloc_consistent (ehci->hcd.pdev,
+		dma_alloc_coherent (ehci->hcd.self.controller,
 			ehci->periodic_size * sizeof (u32),
-			&ehci->periodic_dma);
+			&ehci->periodic_dma, 0);
 	if (ehci->periodic == 0) {
 		goto fail;
 	}
--- diff/drivers/usb/host/ehci-q.c	2004-02-09 10:36:11.000000000 +0000
+++ source/drivers/usb/host/ehci-q.c	2004-02-23 13:56:46.000000000 +0000
@@ -776,7 +776,7 @@ static struct ehci_qh *qh_append_tds (
 	qh = (struct ehci_qh *) *ptr;
 	if (unlikely (qh == 0)) {
 		/* can't sleep here, we have ehci->lock... */
-		qh = qh_make (ehci, urb, SLAB_ATOMIC);
+		qh = qh_make (ehci, urb, GFP_ATOMIC);
 		*ptr = qh;
 	}
 	if (likely (qh != 0)) {
--- diff/drivers/usb/host/ehci-sched.c	2004-02-09 10:36:11.000000000 +0000
+++ source/drivers/usb/host/ehci-sched.c	2004-02-23 13:56:46.000000000 +0000
@@ -115,6 +115,7 @@ periodic_usecs (struct ehci_hcd *ehci, u
 			/* ... or C-mask? */
 			if (q->qh->hw_info2 & cpu_to_le32 (1 << (8 + uframe)))
 				usecs += q->qh->c_usecs;
+			hw_p = &q->qh->hw_next;
 			q = &q->qh->qh_next;
 			break;
 		case Q_TYPE_FSTN:
@@ -122,37 +123,35 @@ periodic_usecs (struct ehci_hcd *ehci, u
 			 * bandwidth from the previous frame
 			 */
 			if (q->fstn->hw_prev != EHCI_LIST_END) {
-				dbg ("not counting FSTN bandwidth yet ...");
+				ehci_dbg (ehci, "ignoring FSTN cost ...\n");
 			}
+			hw_p = &q->fstn->hw_next;
 			q = &q->fstn->fstn_next;
 			break;
 		case Q_TYPE_ITD:
 			usecs += q->itd->usecs [uframe];
+			hw_p = &q->itd->hw_next;
 			q = &q->itd->itd_next;
 			break;
 #ifdef have_split_iso
 		case Q_TYPE_SITD:
-			temp = q->sitd->hw_fullspeed_ep &
-				__constant_cpu_to_le32 (1 << 31);
-
-			// FIXME:  this doesn't count data bytes right...
-
 			/* is it in the S-mask?  (count SPLIT, DATA) */
 			if (q->sitd->hw_uframe & cpu_to_le32 (1 << uframe)) {
-				if (temp)
-					usecs += HS_USECS (188);
-				else
-					usecs += HS_USECS (1);
+				if (q->sitd->hw_fullspeed_ep &
+						__constant_cpu_to_le32 (1<<31))
+					usecs += q->sitd->stream->usecs;
+				else	/* worst case for OUT start-split */
+					usecs += HS_USECS_ISO (188);
 			}
 
 			/* ... C-mask?  (count CSPLIT, DATA) */
 			if (q->sitd->hw_uframe &
 					cpu_to_le32 (1 << (8 + uframe))) {
-				if (temp)
-					usecs += HS_USECS (0);
-				else
-					usecs += HS_USECS (188);
+				/* worst case for IN complete-split */
+				usecs += q->sitd->stream->c_usecs;
 			}
+
+			hw_p = &q->sitd->hw_next;
 			q = &q->sitd->sitd_next;
 			break;
 #endif /* have_split_iso */
@@ -170,6 +169,93 @@ periodic_usecs (struct ehci_hcd *ehci, u
 
 /*-------------------------------------------------------------------------*/
 
+static int same_tt (struct usb_device *dev1, struct usb_device *dev2)
+{
+	if (!dev1->tt || !dev2->tt)
+		return 0;
+	if (dev1->tt != dev2->tt)
+		return 0;
+	if (dev1->tt->multi)
+		return dev1->ttport == dev2->ttport;
+	else
+		return 1;
+}
+
+/* return true iff the device's transaction translator is available
+ * for a periodic transfer starting at the specified frame, using
+ * all the uframes in the mask.
+ */
+static int tt_no_collision (
+	struct ehci_hcd		*ehci,
+	unsigned		period,
+	struct usb_device	*dev,
+	unsigned		frame,
+	u32			uf_mask
+)
+{
+	if (period == 0)	/* error */
+		return 0;
+
+	/* note bandwidth wastage:  split never follows csplit
+	 * (different dev or endpoint) until the next uframe.
+	 * calling convention doesn't make that distinction.
+	 */
+	for (; frame < ehci->periodic_size; frame += period) {
+		union ehci_shadow	here;
+		u32			type;
+
+		here = ehci->pshadow [frame];
+		type = Q_NEXT_TYPE (ehci->periodic [frame]);
+		while (here.ptr) {
+			switch (type) {
+			case Q_TYPE_ITD:
+				type = Q_NEXT_TYPE (here.itd->hw_next);
+				here = here.itd->itd_next;
+				continue;
+			case Q_TYPE_QH:
+				if (same_tt (dev, here.qh->dev)) {
+					u32		mask;
+
+					mask = le32_to_cpu (here.qh->hw_info2);
+					/* "knows" no gap is needed */
+					mask |= mask >> 8;
+					if (mask & uf_mask)
+						break;
+				}
+				type = Q_NEXT_TYPE (here.qh->hw_next);
+				here = here.qh->qh_next;
+				continue;
+			case Q_TYPE_SITD:
+				if (same_tt (dev, here.itd->urb->dev)) {
+					u16		mask;
+
+					mask = le32_to_cpu (here.sitd->hw_uframe);
+					/* FIXME assumes no gap for IN! */
+					mask |= mask >> 8;
+					if (mask & uf_mask)
+						break;
+				}
+				type = Q_NEXT_TYPE (here.qh->hw_next);
+				here = here.sitd->sitd_next;
+				break;
+			// case Q_TYPE_FSTN:
+			default:
+				ehci_dbg (ehci,
+					"periodic frame %d bogus type %d\n",
+					frame, type);
+			}
+
+			/* collision or error */
+			return 0;
+		}
+	}
+
+	/* no collision */
+	return 1;
+}
+
+/*-------------------------------------------------------------------------*/
+
 static int enable_periodic (struct ehci_hcd *ehci)
 {
 	u32	cmd;
@@ -490,36 +576,11 @@ done:
 	return status;
 }
 
-static unsigned
-intr_complete (
-	struct ehci_hcd	*ehci,
-	unsigned	frame,
-	struct ehci_qh	*qh,
-	struct pt_regs	*regs
-) {
-	unsigned	count;
-
-	/* nothing to report? */
-	if (likely ((qh->hw_token & __constant_cpu_to_le32 (QTD_STS_ACTIVE))
-			!= 0))
-		return 0;
-	if (unlikely (list_empty (&qh->qtd_list))) {
-		dbg ("intr qh %p no TDs?", qh);
-		return 0;
-	}
-	
-	/* handle any completions */
-	count = qh_completions (ehci, qh, regs);
-
-	if (unlikely (list_empty (&qh->qtd_list)))
-		intr_deschedule (ehci, qh, 0);
-
-	return count;
-}
-
 /*-------------------------------------------------------------------------*/
 
-static inline struct ehci_iso_stream *
+/* ehci_iso_stream ops work with both ITD and SITD */
+
+static struct ehci_iso_stream *
 iso_stream_alloc (int mem_flags)
 {
 	struct ehci_iso_stream *stream;
@@ -527,15 +588,15 @@ iso_stream_alloc (int mem_flags)
 	stream = kmalloc(sizeof *stream, mem_flags);
 	if (likely (stream != 0)) {
 		memset (stream, 0, sizeof(*stream));
-		INIT_LIST_HEAD(&stream->itd_list);
-		INIT_LIST_HEAD(&stream->free_itd_list);
+		INIT_LIST_HEAD(&stream->td_list);
+		INIT_LIST_HEAD(&stream->free_list);
 		stream->next_uframe = -1;
 		stream->refcount = 1;
 	}
 	return stream;
 }
 
-static inline void
+static void
 iso_stream_init (
 	struct ehci_iso_stream	*stream,
 	struct usb_device	*dev,
@@ -543,8 +604,10 @@ iso_stream_init (
 	unsigned		interval
 )
 {
+	static const u8 smask_out [] = { 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f };
+
 	u32			buf1;
-	unsigned		epnum, maxp, multi;
+	unsigned		epnum, maxp;
 	int			is_input;
 	long			bandwidth;
 
@@ -562,28 +625,62 @@ iso_stream_init (
 		buf1 = 0;
 	}
 
-	multi = hb_mult(maxp);
-	maxp = max_packet(maxp);
-	buf1 |= maxp;
-	maxp *= multi;
+	/* knows about ITD vs SITD */
+	if (dev->speed == USB_SPEED_HIGH) {
+		unsigned multi = hb_mult(maxp);
+
+		stream->highspeed = 1;
+
+		maxp = max_packet(maxp);
+		buf1 |= maxp;
+		maxp *= multi;
+
+		stream->buf0 = cpu_to_le32 ((epnum << 8) | dev->devnum);
+		stream->buf1 = cpu_to_le32 (buf1);
+		stream->buf2 = cpu_to_le32 (multi);
 
-	stream->dev = (struct hcd_dev *)dev->hcpriv;
+		/* usbfs wants to report the average usecs per frame tied up
+		 * when transfers on this endpoint are scheduled ...
+		 */
+		stream->usecs = HS_USECS_ISO (maxp);
+		bandwidth = stream->usecs * 8;
+		bandwidth /= 1 << (interval - 1);
 
-	stream->bEndpointAddress = is_input | epnum;
-	stream->interval = interval;
-	stream->maxp = maxp;
+	} else {
+		u32		addr;
 
-	stream->buf0 = cpu_to_le32 ((epnum << 8) | dev->devnum);
-	stream->buf1 = cpu_to_le32 (buf1);
-	stream->buf2 = cpu_to_le32 (multi);
+		addr = dev->ttport << 24;
+		addr |= dev->tt->hub->devnum << 16;
+		addr |= epnum << 8;
+		addr |= dev->devnum;
+		stream->usecs = HS_USECS_ISO (maxp);
+		if (is_input) {
+			u32	tmp;
+
+			addr |= 1 << 31;
+			stream->c_usecs = stream->usecs;
+			stream->usecs = HS_USECS_ISO (1);
+			stream->raw_mask = 1;
+
+			/* pessimistic c-mask */
+			tmp = usb_calc_bus_time (USB_SPEED_FULL, 1, 0, maxp)
+					/ (125 * 1000);
+			stream->raw_mask |= 3 << (tmp + 9);
+		} else
+			stream->raw_mask = smask_out [maxp / 188];
+		bandwidth = stream->usecs + stream->c_usecs;
+		bandwidth /= 1 << (interval + 2);
 
-	/* usbfs wants to report the average usecs per frame tied up
-	 * when transfers on this endpoint are scheduled ...
-	 */
-	stream->usecs = HS_USECS_ISO (maxp);
-	bandwidth = stream->usecs * 8;
-	bandwidth /= 1 << (interval - 1);
+		/* stream->splits gets created from raw_mask later */
+		stream->address = cpu_to_le32 (addr);
+	}
 	stream->bandwidth = bandwidth;
+
+	stream->udev = dev;
+
+	stream->bEndpointAddress = is_input | epnum;
+	stream->interval = interval;
+	stream->maxp = maxp;
 }
 
 static void
@@ -595,22 +692,23 @@ iso_stream_put(struct ehci_hcd *ehci, st
 	 * not like a QH -- no persistent state (toggle, halt)
 	 */
 	if (stream->refcount == 1) {
-		int is_in;
+		int		is_in;
+		struct hcd_dev	*dev = stream->udev->hcpriv;
 
-		// BUG_ON (!list_empty(&stream->itd_list));
+		// BUG_ON (!list_empty(&stream->td_list));
 
-		while (!list_empty (&stream->free_itd_list)) {
+		while (!list_empty (&stream->free_list)) {
 			struct ehci_itd	*itd;
 
-			itd = list_entry (stream->free_itd_list.next,
+			itd = list_entry (stream->free_list.next,
 				struct ehci_itd, itd_list);
 			list_del (&itd->itd_list);
-			pci_pool_free (ehci->itd_pool, itd, itd->itd_dma);
+			dma_pool_free (ehci->itd_pool, itd, itd->itd_dma);
 		}
 
 		is_in = (stream->bEndpointAddress & USB_DIR_IN) ? 0x10 : 0;
 		stream->bEndpointAddress &= 0x0f;
-		stream->dev->ep [is_in + stream->bEndpointAddress] = 0;
+		dev->ep [is_in + stream->bEndpointAddress] = 0;
 
 		if (stream->rescheduled) {
 			ehci_info (ehci, "ep%d%s-iso rescheduled "
@@ -676,24 +774,26 @@ iso_stream_find (struct ehci_hcd *ehci, 
 
 /*-------------------------------------------------------------------------*/
 
-static inline struct ehci_itd_sched *
-itd_sched_alloc (unsigned packets, int mem_flags)
+/* ehci_iso_sched ops can be shared, ITD-only, or SITD-only */
+
+static struct ehci_iso_sched *
+iso_sched_alloc (unsigned packets, int mem_flags)
 {
-	struct ehci_itd_sched	*itd_sched;
-	int			size = sizeof *itd_sched;
+	struct ehci_iso_sched	*iso_sched;
+	int			size = sizeof *iso_sched;
 
-	size += packets * sizeof (struct ehci_iso_uframe);
-	itd_sched = kmalloc (size, mem_flags);
-	if (likely (itd_sched != 0)) {
-		memset(itd_sched, 0, size);
-		INIT_LIST_HEAD (&itd_sched->itd_list);
+	size += packets * sizeof (struct ehci_iso_packet);
+	iso_sched = kmalloc (size, mem_flags);
+	if (likely (iso_sched != 0)) {
+		memset(iso_sched, 0, size);
+		INIT_LIST_HEAD (&iso_sched->td_list);
 	}
-	return itd_sched;
+	return iso_sched;
 }
 
-static int
+static inline void
 itd_sched_init (
-	struct ehci_itd_sched	*itd_sched,
+	struct ehci_iso_sched	*iso_sched,
 	struct ehci_iso_stream	*stream,
 	struct urb		*urb
 )
@@ -702,13 +802,13 @@ itd_sched_init (
 	dma_addr_t	dma = urb->transfer_dma;
 
 	/* how many uframes are needed for these transfers */
-	itd_sched->span = urb->number_of_packets * stream->interval;
+	iso_sched->span = urb->number_of_packets * stream->interval;
 
 	/* figure out per-uframe itd fields that we'll need later
 	 * when we fit new itds into the schedule.
 	 */
 	for (i = 0; i < urb->number_of_packets; i++) {
-		struct ehci_iso_uframe	*uframe = &itd_sched->packet [i];
+		struct ehci_iso_packet	*uframe = &iso_sched->packet [i];
 		unsigned		length;
 		dma_addr_t		buf;
 		u32			trans;
@@ -718,7 +818,8 @@ itd_sched_init (
 
 		trans = EHCI_ISOC_ACTIVE;
 		trans |= buf & 0x0fff;
-		if (unlikely ((i + 1) == urb->number_of_packets))
+		if (unlikely (((i + 1) == urb->number_of_packets))
+				&& !(urb->transfer_flags & URB_NO_INTERRUPT))
 			trans |= EHCI_ITD_IOC;
 		trans |= length << 16;
 		uframe->transaction = cpu_to_le32 (trans);
@@ -729,17 +830,19 @@ itd_sched_init (
 		if (unlikely ((uframe->bufp != (buf & ~(u64)0x0fff))))
 			uframe->cross = 1;
 	}
-	return 0;
 }
 
 static void
-itd_sched_free (
+iso_sched_free (
 	struct ehci_iso_stream	*stream,
-	struct ehci_itd_sched	*itd_sched
+	struct ehci_iso_sched	*iso_sched
 )
 {
-	list_splice (&itd_sched->itd_list, &stream->free_itd_list);
-	kfree (itd_sched);
+	if (!iso_sched)
+		return;
+	// caller must hold ehci->lock!
+	list_splice (&iso_sched->td_list, &stream->free_list);
+	kfree (iso_sched);
 }
 
 static int
@@ -751,110 +854,201 @@ itd_urb_transaction (
 )
 {
 	struct ehci_itd		*itd;
-	int			status;
 	dma_addr_t		itd_dma;
 	int			i;
 	unsigned		num_itds;
-	struct ehci_itd_sched	*itd_sched;
+	struct ehci_iso_sched	*sched;
 
-	itd_sched = itd_sched_alloc (urb->number_of_packets, mem_flags);
-	if (unlikely (itd_sched == 0))
+	sched = iso_sched_alloc (urb->number_of_packets, mem_flags);
+	if (unlikely (sched == 0))
 		return -ENOMEM;
 
-	status = itd_sched_init (itd_sched, stream, urb);
-	if (unlikely (status != 0))  {
-		itd_sched_free (stream, itd_sched);
-		return status;
-	}
+	itd_sched_init (sched, stream, urb);
 
 	if (urb->interval < 8)
-		num_itds = 1 + (itd_sched->span + 7) / 8;
+		num_itds = 1 + (sched->span + 7) / 8;
 	else
 		num_itds = urb->number_of_packets;
 
 	/* allocate/init ITDs */
 	for (i = 0; i < num_itds; i++) {
 
-		/* free_itd_list.next might be cache-hot ... but maybe
+		/* free_list.next might be cache-hot ... but maybe
 		 * the HC caches it too. avoid that issue for now.
 		 */
 
 		/* prefer previously-allocated itds */
-		if (likely (!list_empty(&stream->free_itd_list))) {
-			itd = list_entry (stream->free_itd_list.prev,
+		if (likely (!list_empty(&stream->free_list))) {
+			itd = list_entry (stream->free_list.prev,
 					 struct ehci_itd, itd_list);
 			list_del (&itd->itd_list);
 			itd_dma = itd->itd_dma;
 		} else
-			itd = pci_pool_alloc (ehci->itd_pool, mem_flags,
+			itd = dma_pool_alloc (ehci->itd_pool, mem_flags,
 					&itd_dma);
 
 		if (unlikely (0 == itd)) {
-			itd_sched_free (stream, itd_sched);
+			iso_sched_free (stream, sched);
 			return -ENOMEM;
 		}
 		memset (itd, 0, sizeof *itd);
 		itd->itd_dma = itd_dma;
-		list_add (&itd->itd_list, &itd_sched->itd_list);
+		list_add (&itd->itd_list, &sched->td_list);
 	}
 
 	/* temporarily store schedule info in hcpriv */
-	urb->hcpriv = itd_sched;
+	urb->hcpriv = sched;
 	urb->error_count = 0;
 	return 0;
 }
 
+/*-------------------------------------------------------------------------*/
+
+static inline int
+itd_slot_ok (
+	struct ehci_hcd		*ehci,
+	u32			mod,
+	u32			uframe,
+	u32			end,
+	u8			usecs,
+	u32			period
+)
+{
+	do {
+		/* can't commit more than 80% periodic == 100 usec */
+		if (periodic_usecs (ehci, uframe >> 3, uframe & 0x7)
+				> (100 - usecs))
+			return 0;
+
+		/* we know urb->interval is 2^N uframes */
+		uframe += period;
+		uframe %= mod;
+	} while (uframe != end);
+	return 1;
+}
+
+static inline int
+sitd_slot_ok (
+	struct ehci_hcd		*ehci,
+	u32			mod,
+	struct ehci_iso_stream	*stream,
+	u32			uframe,
+	u32			end,
+	struct ehci_iso_sched	*sched,
+	u32			period_uframes
+)
+{
+	u32			mask, tmp;
+	u32			frame, uf;
+
+	mask = stream->raw_mask << (uframe & 7);
+
+	/* for IN, don't wrap CSPLIT into the next frame */
+	if (mask & ~0xffff)
+		return 0;
+
+	/* this multi-pass logic is simple, but performance may
+	 * suffer when the schedule data isn't cached.
+	 */
+
+	/* check bandwidth */
+	do {
+		u32		max_used;
+
+		frame = uframe >> 3;
+		uf = uframe & 7;
+
+		/* check starts (OUT uses more than one) */
+		max_used = 100 - stream->usecs;
+		for (tmp = stream->raw_mask & 0xff; tmp; tmp >>= 1, uf++) {
+			if (periodic_usecs (ehci, frame, uf) > max_used)
+				return 0;
+		}
+
+		/* for IN, check CSPLIT */
+		if (stream->c_usecs) {
+			max_used = 100 - stream->c_usecs;
+			do {
+				/* tt is busy in the gap before CSPLIT */
+				tmp = 1 << uf;
+				mask |= tmp;
+				tmp <<= 8;
+				if (stream->raw_mask & tmp)
+					break;
+			} while (++uf < 8);
+			if (periodic_usecs (ehci, frame, uf) > max_used)
+				return 0;
+		}
+
+		/* we know urb->interval is 2^N uframes */
+		uframe += period_uframes;
+		uframe %= mod;
+	} while (uframe != end);
+
+	/* tt must be idle for start(s), any gap, and csplit */
+	if (!tt_no_collision (ehci, period_uframes, stream->udev, frame, mask))
+		return 0;
+
+	stream->splits = stream->raw_mask << (uframe & 7);
+	cpu_to_le32s (&stream->splits);
+	return 1;
+}
+
 /*
  * This scheduler plans almost as far into the future as it has actual
  * periodic schedule slots.  (Affected by TUNE_FLS, which defaults to
  * "as small as possible" to be cache-friendlier.)  That limits the size
  * transfers you can stream reliably; avoid more than 64 msec per urb.
- * Also avoid queue depths of less than the system's worst irq latency.
+ * Also avoid queue depths of less than ehci's worst irq latency (affected
+ * by the per-urb URB_NO_INTERRUPT hint, the log2_irq_thresh module parameter,
+ * and other factors); or more than about 230 msec total (for portability,
+ * given EHCI_TUNE_FLS and the slop).  Or, write a smarter scheduler!
  */
 
 #define SCHEDULE_SLOP	10	/* frames */
 
 static int
-itd_stream_schedule (
+iso_stream_schedule (
 	struct ehci_hcd		*ehci,
 	struct urb		*urb,
 	struct ehci_iso_stream	*stream
 )
 {
-	u32			now, start, end, max;
+	u32			now, start, end, max, period;
 	int			status;
 	unsigned		mod = ehci->periodic_size << 3;
-	struct ehci_itd_sched	*itd_sched = urb->hcpriv;
+	struct ehci_iso_sched	*sched = urb->hcpriv;
 
-	if (unlikely (itd_sched->span > (mod - 8 * SCHEDULE_SLOP))) {
+	if (sched->span > (mod - 8 * SCHEDULE_SLOP)) {
 		ehci_dbg (ehci, "iso request %p too long\n", urb);
 		status = -EFBIG;
 		goto fail;
 	}
 
+	if ((stream->depth + sched->span) > mod) {
+		ehci_dbg (ehci, "request %p would overflow (%d+%d>%d)\n",
+			urb, stream->depth, sched->span, mod);
+		status = -EFBIG;
+		goto fail;
+	}
+
 	now = readl (&ehci->regs->frame_index) % mod;
 
 	/* when's the last uframe this urb could start? */
 	max = now + mod;
-	max -= itd_sched->span;
+	max -= sched->span;
 	max -= 8 * SCHEDULE_SLOP;
 
 	/* typical case: reuse current schedule. stream is still active,
 	 * and no gaps from host falling behind (irq delays etc)
 	 */
-	if (likely (!list_empty (&stream->itd_list))) {
-
+	if (likely (!list_empty (&stream->td_list))) {
 		start = stream->next_uframe;
 		if (start < now)
 			start += mod;
 		if (likely (start < max))
 			goto ready;
-
-		/* two cases:
-		 * (a) we missed some uframes ... can reschedule
-		 * (b) trying to overcommit the schedule
-		 * FIXME (b) should be a hard failure
-		 */
+		/* else fell behind; try to reschedule */
 	}
 
 	/* need to schedule; when's the next (u)frame we could start?
@@ -864,47 +1058,41 @@ itd_stream_schedule (
 	 * jump until after the queue is primed.
 	 */
 	start = SCHEDULE_SLOP * 8 + (now & ~0x07);
+	start %= mod;
 	end = start;
 
-	ehci_vdbg (ehci, "%s schedule from %d (%d..%d), was %d\n",
-			__FUNCTION__, now, start, max,
-			stream->next_uframe);
-
 	/* NOTE:  assumes URB_ISO_ASAP, to limit complexity/bugs */
 
-	if (likely (max > (start + urb->interval)))
-		max = start + urb->interval;
+	period = urb->interval;
+	if (!stream->highspeed)
+		period <<= 3;
+	if (max > (start + period))
+		max = start + period;
 
 	/* hack:  account for itds already scheduled to this endpoint */
-	if (unlikely (list_empty (&stream->itd_list)))
+	if (list_empty (&stream->td_list))
 		end = max;
 
 	/* within [start..max] find a uframe slot with enough bandwidth */
 	end %= mod;
 	do {
-		unsigned	uframe;
-		int		enough_space = 1;
+		int		enough_space;
 
 		/* check schedule: enough space? */
-		uframe = start;
-		do {
-			uframe %= mod;
-
-			/* can't commit more than 80% periodic == 100 usec */
-			if (periodic_usecs (ehci, uframe >> 3, uframe & 0x7)
-					> (100 - stream->usecs)) {
-				enough_space = 0;
-				break;
-			}
-
-			/* we know urb->interval is 2^N uframes */
-			uframe += urb->interval;
-		} while (uframe != end);
+		if (stream->highspeed)
+			enough_space = itd_slot_ok (ehci, mod, start, end,
+					stream->usecs, period);
+		else {
+			if ((start % 8) >= 6)
+				continue;
+			enough_space = sitd_slot_ok (ehci, mod, stream,
+					start, end, sched, period);
+		}
 
 		/* (re)schedule it here if there's enough bandwidth */
 		if (enough_space) {
 			start %= mod;
-			if (unlikely (!list_empty (&stream->itd_list))) {
+			if (unlikely (!list_empty (&stream->td_list))) {
 				/* host fell behind ... maybe irq latencies
 				 * delayed this request queue for too long.
 				 */
@@ -926,12 +1114,12 @@ itd_stream_schedule (
 
 	/* no room in the schedule */
 	ehci_dbg (ehci, "iso %ssched full %p (now %d end %d max %d)\n",
-		list_empty (&stream->itd_list) ? "" : "re",
+		list_empty (&stream->td_list) ? "" : "re",
 		urb, now, end, max);
 	status = -ENOSPC;
 
 fail:
-	itd_sched_free (stream, itd_sched);
+	iso_sched_free (stream, sched);
 	urb->hcpriv = 0;
 	return status;
 
@@ -961,13 +1149,13 @@ itd_init (struct ehci_iso_stream *stream
 static inline void
 itd_patch (
 	struct ehci_itd		*itd,
-	struct ehci_itd_sched	*itd_sched,
+	struct ehci_iso_sched	*iso_sched,
 	unsigned		index,
 	u16			uframe,
 	int			first
 )
 {
-	struct ehci_iso_uframe	*uf = &itd_sched->packet [index];
+	struct ehci_iso_packet	*uf = &iso_sched->packet [index];
 	unsigned		pg = itd->pg;
 
 	// BUG_ON (pg == 6 && uf->cross);
@@ -1012,12 +1200,12 @@ itd_link_urb (
 {
 	int			packet, first = 1;
 	unsigned		next_uframe, uframe, frame;
-	struct ehci_itd_sched	*itd_sched = urb->hcpriv;
+	struct ehci_iso_sched	*iso_sched = urb->hcpriv;
 	struct ehci_itd		*itd;
 
 	next_uframe = stream->next_uframe % mod;
 
-	if (unlikely (list_empty(&stream->itd_list))) {
+	if (unlikely (list_empty(&stream->td_list))) {
 		hcd_to_bus (&ehci->hcd)->bandwidth_allocated
 				+= stream->bandwidth;
 		ehci_vdbg (ehci,
@@ -1034,13 +1222,13 @@ itd_link_urb (
 	for (packet = 0, itd = 0; packet < urb->number_of_packets; ) {
 		if (itd == 0) {
 			/* ASSERT:  we have all necessary itds */
-			// BUG_ON (list_empty (&itd_sched->itd_list));
+			// BUG_ON (list_empty (&iso_sched->td_list));
 
 			/* ASSERT:  no itds for this endpoint in this uframe */
 
-			itd = list_entry (itd_sched->itd_list.next,
+			itd = list_entry (iso_sched->td_list.next,
 					struct ehci_itd, itd_list);
-			list_move_tail (&itd->itd_list, &stream->itd_list);
+			list_move_tail (&itd->itd_list, &stream->td_list);
 			itd->stream = iso_stream_get (stream);
 			itd->urb = usb_get_urb (urb);
 			first = 1;
@@ -1051,10 +1239,11 @@ itd_link_urb (
 		frame = next_uframe >> 3;
 
 		itd->usecs [uframe] = stream->usecs;
-		itd_patch (itd, itd_sched, packet, uframe, first);
+		itd_patch (itd, iso_sched, packet, uframe, first);
 		first = 0;
 
 		next_uframe += stream->interval;
+		stream->depth += stream->interval;
 		next_uframe %= mod;
 		packet++;
 
@@ -1068,7 +1257,7 @@ itd_link_urb (
 	stream->next_uframe = next_uframe;
 
 	/* don't need that schedule data any more */
-	itd_sched_free (stream, itd_sched);
+	iso_sched_free (stream, iso_sched);
 	urb->hcpriv = 0;
 
 	if (unlikely (!ehci->periodic_sched++))
@@ -1101,6 +1290,7 @@ itd_complete (
 
 		t = le32_to_cpup (&itd->hw_transaction [uframe]);
 		itd->hw_transaction [uframe] = 0;
+		stream->depth -= stream->interval;
 
 		/* report transfer status */
 		if (unlikely (t & ISO_ERRS)) {
@@ -1126,7 +1316,7 @@ itd_complete (
 	usb_put_urb (urb);
 	itd->urb = 0;
 	itd->stream = 0;
-	list_move (&itd->itd_list, &stream->free_itd_list);
+	list_move (&itd->itd_list, &stream->free_list);
 	iso_stream_put (ehci, stream);
 
 	/* handle completion now? */
@@ -1134,7 +1324,7 @@ itd_complete (
 		return 0;
 
 	/* ASSERT: it's really the last itd for this urb
-	list_for_each_entry (itd, &stream->itd_list, itd_list)
+	list_for_each_entry (itd, &stream->td_list, itd_list)
 		BUG_ON (itd->urb == urb);
 	 */
 
@@ -1149,7 +1339,7 @@ itd_complete (
 		(void) disable_periodic (ehci);
 	hcd_to_bus (&ehci->hcd)->bandwidth_isoc_reqs--;
 
-	if (unlikely (list_empty (&stream->itd_list))) {
+	if (unlikely (list_empty (&stream->td_list))) {
 		hcd_to_bus (&ehci->hcd)->bandwidth_allocated
 				-= stream->bandwidth;
 		ehci_vdbg (ehci,
@@ -1203,7 +1393,7 @@ static int itd_submit (struct ehci_hcd *
 
 	/* schedule ... need to lock */
 	spin_lock_irqsave (&ehci->lock, flags);
-	status = itd_stream_schedule (ehci, urb, stream);
+	status = iso_stream_schedule (ehci, urb, stream);
  	if (likely (status == 0))
 		itd_link_urb (ehci, urb, ehci->periodic_size << 3, stream);
 	spin_unlock_irqrestore (&ehci->lock, flags);
@@ -1233,7 +1423,7 @@ static void
 scan_periodic (struct ehci_hcd *ehci, struct pt_regs *regs)
 {
 	unsigned	frame, clock, now_uframe, mod;
-	unsigned	count = 0;
+	unsigned	modified;
 
 	mod = ehci->periodic_size << 3;
 
@@ -1244,47 +1434,50 @@ scan_periodic (struct ehci_hcd *ehci, st
 	 */
 	now_uframe = ehci->next_uframe;
 	if (HCD_IS_RUNNING (ehci->hcd.state))
-		clock = readl (&ehci->regs->frame_index) % mod;
+		clock = readl (&ehci->regs->frame_index);
 	else
 		clock = now_uframe + mod - 1;
+	clock %= mod;
 
 	for (;;) {
 		union ehci_shadow	q, *q_p;
 		u32			type, *hw_p;
 		unsigned		uframes;
 
+		/* don't scan past the live uframe */
 		frame = now_uframe >> 3;
-restart:
-		/* scan schedule to _before_ current frame index */
-		if ((frame == (clock >> 3))
-				&& HCD_IS_RUNNING (ehci->hcd.state))
+		if (frame == (clock >> 3))
 			uframes = now_uframe & 0x07;
-		else
+		else {
+			/* safe to scan the whole frame at once */
+			now_uframe |= 0x07;
 			uframes = 8;
+		}
 
+restart:
+		/* scan each element in frame's queue for completions */
 		q_p = &ehci->pshadow [frame];
 		hw_p = &ehci->periodic [frame];
 		q.ptr = q_p->ptr;
 		type = Q_NEXT_TYPE (*hw_p);
+		modified = 0;
 
-		/* scan each element in frame's queue for completions */
 		while (q.ptr != 0) {
-			int			last;
 			unsigned		uf;
 			union ehci_shadow	temp;
 
 			switch (type) {
 			case Q_TYPE_QH:
-				last = (q.qh->hw_next == EHCI_LIST_END);
-				temp = q.qh->qh_next;
+				/* handle any completions */
+				temp.qh = qh_get (q.qh);
 				type = Q_NEXT_TYPE (q.qh->hw_next);
-				count += intr_complete (ehci, frame,
-						qh_get (q.qh), regs);
-				qh_put (ehci, q.qh);
-				q = temp;
+				q = q.qh->qh_next;
+				modified = qh_completions (ehci, temp.qh, regs);
+				if (unlikely (list_empty (&temp.qh->qtd_list)))
+					intr_deschedule (ehci, temp.qh, 0);
+				qh_put (ehci, temp.qh);
 				break;
 			case Q_TYPE_FSTN:
-				last = (q.fstn->hw_next == EHCI_LIST_END);
 				/* for "save place" FSTNs, look at QH entries
 				 * in the previous frame for completions.
 				 */
@@ -1295,13 +1488,11 @@ restart:
 				q = q.fstn->fstn_next;
 				break;
 			case Q_TYPE_ITD:
-				last = (q.itd->hw_next == EHCI_LIST_END);
-
 				/* skip itds for later in the frame */
 				rmb ();
 				for (uf = uframes; uf < 8; uf++) {
 					if (0 == (q.itd->hw_transaction [uf]
-							& ISO_ACTIVE))
+							& ITD_ACTIVE))
 						continue;
 					q_p = &q.itd->itd_next;
 					hw_p = &q.itd->hw_next;
@@ -1317,31 +1508,37 @@ restart:
 				 */
 				*q_p = q.itd->itd_next;
 				*hw_p = q.itd->hw_next;
+				type = Q_NEXT_TYPE (q.itd->hw_next);
 				wmb();
-
-				/* always rescan here; simpler */
-				count += itd_complete (ehci, q.itd, regs);
-				goto restart;
+				modified = itd_complete (ehci, q.itd, regs);
+				q = *q_p;
+				break;
 #ifdef have_split_iso
 			case Q_TYPE_SITD:
-				last = (q.sitd->hw_next == EHCI_LIST_END);
-				sitd_complete (ehci, q.sitd);
+				if (q.sitd->hw_results & SITD_ACTIVE) {
+					q_p = &q.sitd->sitd_next;
+					hw_p = &q.sitd->hw_next;
+					type = Q_NEXT_TYPE (q.sitd->hw_next);
+					q = *q_p;
+					break;
+				}
+				*q_p = q.sitd->sitd_next;
+				*hw_p = q.sitd->hw_next;
 				type = Q_NEXT_TYPE (q.sitd->hw_next);
-
-				// FIXME unlink SITD after split completes
-				q = q.sitd->sitd_next;
+				wmb();
+				modified = sitd_complete (ehci, q.sitd, regs);
+				q = *q_p;
 				break;
 #endif /* have_split_iso */
 			default:
 				dbg ("corrupt type %d frame %d shadow %p",
 					type, frame, q.ptr);
 				// BUG ();
-				last = 1;
 				q.ptr = 0;
 			}
 
-			/* did completion remove an interior q entry? */
-			if (unlikely (q.ptr == 0 && !last))
+			/* assume completion callbacks modify the queue */
+			if (unlikely (modified))
 				goto restart;
 		}
 
@@ -1368,9 +1565,6 @@ restart:
 			/* rescan the rest of this frame, then ... */
 			clock = now;
 		} else {
-			/* FIXME sometimes we can scan the next frame
-			 * right away, not always inching up on it ...
-			 */
 			now_uframe++;
 			now_uframe %= mod;
 		}
--- diff/drivers/usb/host/ehci.h	2004-02-09 10:36:11.000000000 +0000
+++ source/drivers/usb/host/ehci.h	2004-02-23 13:56:46.000000000 +0000
@@ -74,11 +74,11 @@ struct ehci_hcd {			/* one per controlle
 	struct ehci_regs	*regs;
 	u32			hcs_params;	/* cached register copy */
 
-	/* per-HC memory pools (could be per-PCI-bus, but ...) */
-	struct pci_pool		*qh_pool;	/* qh per active urb */
-	struct pci_pool		*qtd_pool;	/* one or more per qh */
-	struct pci_pool		*itd_pool;	/* itd per iso urb */
-	struct pci_pool		*sitd_pool;	/* sitd per split iso urb */
+	/* per-HC memory pools (could be per-bus, but ...) */
+	struct dma_pool		*qh_pool;	/* qh per active urb */
+	struct dma_pool		*qtd_pool;	/* one or more per qh */
+	struct dma_pool		*itd_pool;	/* itd per iso urb */
+	struct dma_pool		*sitd_pool;	/* sitd per split iso urb */
 
 	struct timer_list	watchdog;
 	struct notifier_block	reboot_notifier;
@@ -386,22 +386,24 @@ struct ehci_qh {
 
 /*-------------------------------------------------------------------------*/
 
-/* description of one iso highspeed transaction (up to 3 KB data) */
-struct ehci_iso_uframe {
+/* description of one iso transaction (up to 3 KB data if highspeed) */
+struct ehci_iso_packet {
 	/* These will be copied to iTD when scheduling */
 	u64			bufp;		/* itd->hw_bufp{,_hi}[pg] |= */
 	u32			transaction;	/* itd->hw_transaction[i] |= */
 	u8			cross;		/* buf crosses pages */
+	/* for full speed OUT splits */
+	u16			buf1;
 };
 
-/* temporary schedule data for highspeed packets from iso urbs
- * each packet is one uframe's usb transactions, in some itd,
+/* temporary schedule data for packets from iso urbs (both speeds)
+ * each packet is one logical usb transaction to the device (not TT),
  * beginning at stream->next_uframe
  */
-struct ehci_itd_sched {
-	struct list_head	itd_list;
+struct ehci_iso_sched {
+	struct list_head	td_list;
 	unsigned		span;
-	struct ehci_iso_uframe	packet [0];
+	struct ehci_iso_packet	packet [0];
 };
 
 /*
@@ -415,22 +417,26 @@ struct ehci_iso_stream {
 
 	u32			refcount;
 	u8			bEndpointAddress;
-	struct list_head	itd_list;	/* queued itds */
-	struct list_head	free_itd_list;	/* list of unused itds */
-	struct hcd_dev		*dev;
+	u8			highspeed;
+	u16			depth;		/* depth in uframes */
+	struct list_head	td_list;	/* queued itds/sitds */
+	struct list_head	free_list;	/* list of unused itds/sitds */
+	struct usb_device	*udev;
 
 	/* output of (re)scheduling */
 	unsigned long		start;		/* jiffies */
 	unsigned long		rescheduled;
 	int			next_uframe;
+	u32			splits;
 
 	/* the rest is derived from the endpoint descriptor,
-	 * trusting urb->interval == (1 << (epdesc->bInterval - 1)),
+	 * trusting urb->interval == f(epdesc->bInterval) and
 	 * including the extra info for hw_bufp[0..2]
 	 */
 	u8			interval;
-	u8			usecs;		
+	u8			usecs, c_usecs;
 	u16			maxp;
+	u16			raw_mask;
 	unsigned		bandwidth;
 
 	/* This is used to initialize iTD's hw_bufp fields */
@@ -438,7 +444,8 @@ struct ehci_iso_stream {
 	u32			buf1;		
 	u32			buf2;
 
-	/* ... sITD won't use buf[012], and needs TT access ... */
+	/* this is used to initialize sITD's tt info */
+	u32			address;
 };
 
 /*-------------------------------------------------------------------------*/
@@ -460,7 +467,7 @@ struct ehci_itd {
 #define	EHCI_ITD_LENGTH(tok)	(((tok)>>16) & 0x0fff)
 #define	EHCI_ITD_IOC		(1 << 15)	/* interrupt on complete */
 
-#define ISO_ACTIVE	__constant_cpu_to_le32(EHCI_ISOC_ACTIVE)
+#define ITD_ACTIVE	__constant_cpu_to_le32(EHCI_ISOC_ACTIVE)
 
 	u32			hw_bufp [7];	/* see EHCI 3.3.3 */ 
 	u32			hw_bufp_hi [7];	/* Appendix B */
@@ -492,22 +499,35 @@ struct ehci_sitd {
 	/* first part defined by EHCI spec */
 	u32			hw_next;
 /* uses bit field macros above - see EHCI 0.95 Table 3-8 */
-	u32			hw_fullspeed_ep;  /* see EHCI table 3-9 */
-	u32                     hw_uframe;        /* see EHCI table 3-10 */
-        u32                     hw_tx_results1;   /* see EHCI table 3-11 */
-	u32                     hw_tx_results2;   /* see EHCI table 3-12 */
-	u32                     hw_tx_results3;   /* see EHCI table 3-12 */
-        u32                     hw_backpointer;   /* see EHCI table 3-13 */
-	u32			hw_buf_hi [2];	  /* Appendix B */
+	u32			hw_fullspeed_ep;	/* see EHCI table 3-9 */
+	u32			hw_uframe;		/* see EHCI table 3-10 */
+	u32			hw_results;		/* see EHCI table 3-11 */
+#define	SITD_IOC	(1 << 31)	/* interrupt on completion */
+#define	SITD_PAGE	(1 << 30)	/* buffer 0/1 */
+#define	SITD_LENGTH(x)	(0x3ff & ((x)>>16))
+#define	SITD_STS_ACTIVE	(1 << 7)	/* HC may execute this */
+#define	SITD_STS_ERR	(1 << 6)	/* error from TT */
+#define	SITD_STS_DBE	(1 << 5)	/* data buffer error (in HC) */
+#define	SITD_STS_BABBLE	(1 << 4)	/* device was babbling */
+#define	SITD_STS_XACT	(1 << 3)	/* illegal IN response */
+#define	SITD_STS_MMF	(1 << 2)	/* incomplete split transaction */
+#define	SITD_STS_STS	(1 << 1)	/* split transaction state */
+
+#define SITD_ACTIVE	__constant_cpu_to_le32(SITD_STS_ACTIVE)
+
+	u32			hw_buf [2];		/* see EHCI table 3-12 */
+	u32			hw_backpointer;		/* see EHCI table 3-13 */
+	u32			hw_buf_hi [2];		/* Appendix B */
 
 	/* the rest is HCD-private */
 	dma_addr_t		sitd_dma;
 	union ehci_shadow	sitd_next;	/* ptr to periodic q entry */
-	struct urb		*urb;
-	dma_addr_t		buf_dma;	/* buffer address */
 
-	unsigned short		usecs;		/* start bandwidth */
-	unsigned short		c_usecs;	/* completion bandwidth */
+	struct urb		*urb;
+	struct ehci_iso_stream	*stream;	/* endpoint's queue */
+	struct list_head	sitd_list;	/* list of stream's sitds */
+	unsigned		frame;
+	unsigned		index;
 } __attribute__ ((aligned (32)));
 
 /*-------------------------------------------------------------------------*/
--- diff/drivers/usb/host/ohci-dbg.c	2004-01-19 10:22:58.000000000 +0000
+++ source/drivers/usb/host/ohci-dbg.c	2004-02-23 13:56:46.000000000 +0000
@@ -76,7 +76,7 @@ urb_print (struct urb * urb, char * str,
 	do { \
 	if (next) { \
 		unsigned s_len; \
-		s_len = snprintf (*next, *size, format, ## arg ); \
+		s_len = scnprintf (*next, *size, format, ## arg ); \
 		*size -= s_len; *next += s_len; \
 	} else \
 		ohci_dbg(ohci,format, ## arg ); \
@@ -420,7 +420,7 @@ show_list (struct ohci_hcd *ohci, char *
 		struct list_head	*entry;
 		struct td		*td;
 
-		temp = snprintf (buf, size,
+		temp = scnprintf (buf, size,
 			"ed/%p %cs dev%d ep%d%s max %d %08x%s%s %s",
 			ed,
 			(info & ED_LOWSPEED) ? 'l' : 'f',
@@ -442,7 +442,7 @@ show_list (struct ohci_hcd *ohci, char *
 			scratch = cpu_to_le32p (&td->hwINFO);
 			cbp = le32_to_cpup (&td->hwCBP);
 			be = le32_to_cpup (&td->hwBE);
-			temp = snprintf (buf, size,
+			temp = scnprintf (buf, size,
 					"\n\ttd %p %s %d cc=%x urb %p (%08x)",
 					td,
 					({ char *pid;
@@ -458,7 +458,7 @@ show_list (struct ohci_hcd *ohci, char *
 			buf += temp;
 		}
 
-		temp = snprintf (buf, size, "\n");
+		temp = scnprintf (buf, size, "\n");
 		size -= temp;
 		buf += temp;
 
@@ -515,7 +515,7 @@ show_periodic (struct class_device *clas
 	next = buf;
 	size = PAGE_SIZE;
 
-	temp = snprintf (next, size, "size = %d\n", NUM_INTS);
+	temp = scnprintf (next, size, "size = %d\n", NUM_INTS);
 	size -= temp;
 	next += temp;
 
@@ -525,12 +525,12 @@ show_periodic (struct class_device *clas
 		if (!(ed = ohci->periodic [i]))
 			continue;
 
-		temp = snprintf (next, size, "%2d [%3d]:", i, ohci->load [i]);
+		temp = scnprintf (next, size, "%2d [%3d]:", i, ohci->load [i]);
 		size -= temp;
 		next += temp;
 
 		do {
-			temp = snprintf (next, size, " ed%d/%p",
+			temp = scnprintf (next, size, " ed%d/%p",
 				ed->interval, ed);
 			size -= temp;
 			next += temp;
@@ -550,7 +550,7 @@ show_periodic (struct class_device *clas
 				list_for_each (entry, &ed->td_list)
 					qlen++;
 
-				temp = snprintf (next, size,
+				temp = scnprintf (next, size,
 					" (%cs dev%d ep%d%s-%s qlen %u"
 					" max %d %08x%s%s)",
 					(info & ED_LOWSPEED) ? 'l' : 'f',
@@ -579,7 +579,7 @@ show_periodic (struct class_device *clas
 
 		} while (ed);
 
-		temp = snprintf (next, size, "\n");
+		temp = scnprintf (next, size, "\n");
 		size -= temp;
 		next += temp;
 	}
@@ -628,7 +628,7 @@ show_registers (struct class_device *cla
 
 	/* other registers mostly affect frame timings */
 	rdata = readl (&regs->fminterval);
-	temp = snprintf (next, size,
+	temp = scnprintf (next, size,
 			"fmintvl 0x%08x %sFSMPS=0x%04x FI=0x%04x\n",
 			rdata, (rdata >> 31) ? " FIT" : "",
 			(rdata >> 16) & 0xefff, rdata & 0xffff);
@@ -636,20 +636,20 @@ show_registers (struct class_device *cla
 	next += temp;
 
 	rdata = readl (&regs->fmremaining);
-	temp = snprintf (next, size, "fmremaining 0x%08x %sFR=0x%04x\n",
+	temp = scnprintf (next, size, "fmremaining 0x%08x %sFR=0x%04x\n",
 			rdata, (rdata >> 31) ? " FRT" : "",
 			rdata & 0x3fff);
 	size -= temp;
 	next += temp;
 
 	rdata = readl (&regs->periodicstart);
-	temp = snprintf (next, size, "periodicstart 0x%04x\n",
+	temp = scnprintf (next, size, "periodicstart 0x%04x\n",
 			rdata & 0x3fff);
 	size -= temp;
 	next += temp;
 
 	rdata = readl (&regs->lsthresh);
-	temp = snprintf (next, size, "lsthresh 0x%04x\n",
+	temp = scnprintf (next, size, "lsthresh 0x%04x\n",
 			rdata & 0x3fff);
 	size -= temp;
 	next += temp;
--- diff/drivers/usb/host/ohci-hcd.c	2004-02-18 08:54:12.000000000 +0000
+++ source/drivers/usb/host/ohci-hcd.c	2004-02-23 13:56:46.000000000 +0000
@@ -17,6 +17,7 @@
  *
  * History:
  * 
+ * 2004/02/04 use generic dma_* functions instead of pci_* (dsaxena@plexity.net)
  * 2003/02/24 show registers in sysfs (Kevin Brosius)
  *
  * 2002/09/03 get rid of ed hashtables, rework periodic scheduling and
@@ -96,6 +97,8 @@
 #include <linux/interrupt.h>  /* for in_interrupt () */
 #include <linux/usb.h>
 #include "../core/hcd.h"
+#include <linux/dma-mapping.h> 
+#include <linux/dmapool.h>    /* needed by ohci-mem.c when no PCI */
 
 #include <asm/io.h>
 #include <asm/irq.h>
@@ -642,8 +645,9 @@ static void ohci_stop (struct usb_hcd *h
 	remove_debug_files (ohci);
 	ohci_mem_cleanup (ohci);
 	if (ohci->hcca) {
-		pci_free_consistent (ohci->hcd.pdev, sizeof *ohci->hcca,
-					ohci->hcca, ohci->hcca_dma);
+		dma_free_coherent (ohci->hcd.self.controller, 
+				sizeof *ohci->hcca, 
+				ohci->hcca, ohci->hcca_dma);
 		ohci->hcca = NULL;
 		ohci->hcca_dma = 0;
 	}
--- diff/drivers/usb/host/ohci-mem.c	2003-08-20 14:16:31.000000000 +0100
+++ source/drivers/usb/host/ohci-mem.c	2004-02-23 13:56:46.000000000 +0000
@@ -13,7 +13,7 @@
  * There's basically three types of memory:
  *	- data used only by the HCD ... kmalloc is fine
  *	- async and periodic schedules, shared by HC and HCD ... these
- *	  need to use pci_pool or pci_alloc_consistent
+ *	  need to use dma_pool or dma_alloc_coherent
  *	- driver buffers, read/written by HC ... the hcd glue or the
  *	  device driver provides us with dma addresses
  *
@@ -45,18 +45,18 @@ static void ohci_hcd_free (struct usb_hc
 
 static int ohci_mem_init (struct ohci_hcd *ohci)
 {
-	ohci->td_cache = pci_pool_create ("ohci_td", ohci->hcd.pdev,
+	ohci->td_cache = dma_pool_create ("ohci_td", ohci->hcd.self.controller,
 		sizeof (struct td),
 		32 /* byte alignment */,
 		0 /* no page-crossing issues */);
 	if (!ohci->td_cache)
 		return -ENOMEM;
-	ohci->ed_cache = pci_pool_create ("ohci_ed", ohci->hcd.pdev,
+	ohci->ed_cache = dma_pool_create ("ohci_ed", ohci->hcd.self.controller,
 		sizeof (struct ed),
 		16 /* byte alignment */,
 		0 /* no page-crossing issues */);
 	if (!ohci->ed_cache) {
-		pci_pool_destroy (ohci->td_cache);
+		dma_pool_destroy (ohci->td_cache);
 		return -ENOMEM;
 	}
 	return 0;
@@ -65,11 +65,11 @@ static int ohci_mem_init (struct ohci_hc
 static void ohci_mem_cleanup (struct ohci_hcd *ohci)
 {
 	if (ohci->td_cache) {
-		pci_pool_destroy (ohci->td_cache);
+		dma_pool_destroy (ohci->td_cache);
 		ohci->td_cache = 0;
 	}
 	if (ohci->ed_cache) {
-		pci_pool_destroy (ohci->ed_cache);
+		dma_pool_destroy (ohci->ed_cache);
 		ohci->ed_cache = 0;
 	}
 }
@@ -96,7 +96,7 @@ td_alloc (struct ohci_hcd *hc, int mem_f
 	dma_addr_t	dma;
 	struct td	*td;
 
-	td = pci_pool_alloc (hc->td_cache, mem_flags, &dma);
+	td = dma_pool_alloc (hc->td_cache, mem_flags, &dma);
 	if (td) {
 		/* in case hc fetches it, make it look dead */
 		memset (td, 0, sizeof *td);
@@ -118,7 +118,7 @@ td_free (struct ohci_hcd *hc, struct td 
 		*prev = td->td_hash;
 	else if ((td->hwINFO & TD_DONE) != 0)
 		ohci_dbg (hc, "no hash for td %p\n", td);
-	pci_pool_free (hc->td_cache, td, td->td_dma);
+	dma_pool_free (hc->td_cache, td, td->td_dma);
 }
 
 /*-------------------------------------------------------------------------*/
@@ -130,7 +130,7 @@ ed_alloc (struct ohci_hcd *hc, int mem_f
 	dma_addr_t	dma;
 	struct ed	*ed;
 
-	ed = pci_pool_alloc (hc->ed_cache, mem_flags, &dma);
+	ed = dma_pool_alloc (hc->ed_cache, mem_flags, &dma);
 	if (ed) {
 		memset (ed, 0, sizeof (*ed));
 		INIT_LIST_HEAD (&ed->td_list);
@@ -142,6 +142,6 @@ ed_alloc (struct ohci_hcd *hc, int mem_f
 static void
 ed_free (struct ohci_hcd *hc, struct ed *ed)
 {
-	pci_pool_free (hc->ed_cache, ed, ed->dma);
+	dma_pool_free (hc->ed_cache, ed, ed->dma);
 }
 
--- diff/drivers/usb/host/ohci-omap.c	2004-02-18 08:54:12.000000000 +0000
+++ source/drivers/usb/host/ohci-omap.c	2004-02-23 13:56:46.000000000 +0000
@@ -388,9 +388,7 @@ int usb_hcd_omap_probe (const struct hc_
 	hcd->description = driver->description;
 	hcd->irq = dev->irq[0];
 	hcd->regs = dev->mapbase;
-	hcd->pdev = OMAP_FAKE_PCIDEV;
 	hcd->self.controller = &dev->dev;
-	hcd->controller = hcd->self.controller;
 
 	retval = hcd_buffer_create (hcd);
 	if (retval != 0) {
@@ -494,12 +492,10 @@ ohci_omap_start (struct usb_hcd *hcd)
 	struct ohci_hcd	*ohci = hcd_to_ohci (hcd);
 	int		ret;
 
-	if (hcd->pdev) {
-		ohci->hcca = pci_alloc_consistent (hcd->pdev,
-				sizeof *ohci->hcca, &ohci->hcca_dma);
-		if (!ohci->hcca)
-			return -ENOMEM;
-	}
+	ohci->hcca = dma_alloc_consistent (hcd->self.controller,
+			sizeof *ohci->hcca, &ohci->hcca_dma);
+	if (!ohci->hcca)
+		return -ENOMEM;
 
         memset (ohci->hcca, 0, sizeof (struct ohci_hcca));
 	if ((ret = ohci_mem_init (ohci)) < 0) {
--- diff/drivers/usb/host/ohci-pci.c	2004-02-18 08:54:12.000000000 +0000
+++ source/drivers/usb/host/ohci-pci.c	2004-02-23 13:56:46.000000000 +0000
@@ -45,17 +45,19 @@ ohci_pci_start (struct usb_hcd *hcd)
 	struct ohci_hcd	*ohci = hcd_to_ohci (hcd);
 	int		ret;
 
-	if (hcd->pdev) {
-		ohci->hcca = pci_alloc_consistent (hcd->pdev,
-				sizeof *ohci->hcca, &ohci->hcca_dma);
-		if (!ohci->hcca)
-			return -ENOMEM;
+	ohci->hcca = dma_alloc_coherent (hcd->self.controller,
+			sizeof *ohci->hcca, &ohci->hcca_dma, 0);
+	if (!ohci->hcca)
+		return -ENOMEM;
+
+	if(hcd->self.controller && hcd->self.controller->bus == &pci_bus_type) {
+		struct pci_dev *pdev = to_pci_dev(hcd->self.controller);
 
 		/* AMD 756, for most chips (early revs), corrupts register
 		 * values on read ... so enable the vendor workaround.
 		 */
-		if (hcd->pdev->vendor == PCI_VENDOR_ID_AMD
-				&& hcd->pdev->device == 0x740c) {
+		if (pdev->vendor == PCI_VENDOR_ID_AMD
+				&& pdev->device == 0x740c) {
 			ohci->flags = OHCI_QUIRK_AMD756;
 			ohci_info (ohci, "AMD756 erratum 4 workaround\n");
 		}
@@ -68,8 +70,8 @@ ohci_pci_start (struct usb_hcd *hcd)
 		 * for this chip.  Evidently control and bulk lists
 		 * can get confused.  (B&W G3 models, and ...)
 		 */
-		else if (hcd->pdev->vendor == PCI_VENDOR_ID_OPTI
-				&& hcd->pdev->device == 0xc861) {
+		else if (pdev->vendor == PCI_VENDOR_ID_OPTI
+				&& pdev->device == 0xc861) {
 			ohci_info (ohci,
 				"WARNING: OPTi workarounds unavailable\n");
 		}
@@ -78,12 +80,11 @@ ohci_pci_start (struct usb_hcd *hcd)
 		 * identify the USB (fn2). This quirk might apply to more or
 		 * even all NSC stuff.
 		 */
-		else if (hcd->pdev->vendor == PCI_VENDOR_ID_NS) {
-			struct pci_dev	*b, *hc;
+		else if (pdev->vendor == PCI_VENDOR_ID_NS) {
+			struct pci_dev	*b;
 
-			hc = hcd->pdev;
-			b  = pci_find_slot (hc->bus->number,
-					PCI_DEVFN (PCI_SLOT (hc->devfn), 1));
+			b  = pci_find_slot (pdev->bus->number,
+					PCI_DEVFN (PCI_SLOT (pdev->devfn), 1));
 			if (b && b->device == PCI_DEVICE_ID_NS_87560_LIO
 					&& b->vendor == PCI_VENDOR_ID_NS) {
 				ohci->flags |= OHCI_QUIRK_SUPERIO;
@@ -145,7 +146,7 @@ static int ohci_pci_suspend (struct usb_
 		
 #ifdef CONFIG_PMAC_PBOOK
 	if (_machine == _MACH_Pmac)
-		disable_irq (hcd->pdev->irq);
+		disable_irq ((to_pci_dev(hcd->self.controller))->irq);
  	/* else, 2.4 assumes shared irqs -- don't disable */
 #endif
 
@@ -179,15 +180,17 @@ static int ohci_pci_suspend (struct usb_
 	 * memory during sleep. We disable its bus master bit during
 	 * suspend
 	 */
-	pci_read_config_word (hcd->pdev, PCI_COMMAND, &cmd);
+	pci_read_config_word (to_pci_dev(hcd->self.controller), PCI_COMMAND, 
+				&cmd);
 	cmd &= ~PCI_COMMAND_MASTER;
-	pci_write_config_word (hcd->pdev, PCI_COMMAND, cmd);
+	pci_write_config_word (to_pci_dev(hcd->self.controller), PCI_COMMAND, 
+				cmd);
 #ifdef CONFIG_PMAC_PBOOK
 	{
 	   	struct device_node	*of_node;
  
 		/* Disable USB PAD & cell clock */
-		of_node = pci_device_to_OF_node (hcd->pdev);
+		of_node = pci_device_to_OF_node (to_pci_dev(hcd->self.controller));
 		if (of_node)
 			pmac_call_feature(PMAC_FTR_USB_ENABLE, of_node, 0, 0);
 	}
@@ -207,7 +210,7 @@ static int ohci_pci_resume (struct usb_h
 		struct device_node *of_node;
 
 		/* Re-enable USB PAD & cell clock */
-		of_node = pci_device_to_OF_node (hcd->pdev);
+		of_node = pci_device_to_OF_node (to_pci_dev(hcd->self.controller));
 		if (of_node)
 			pmac_call_feature (PMAC_FTR_USB_ENABLE, of_node, 0, 1);
 	}
@@ -222,7 +225,7 @@ static int ohci_pci_resume (struct usb_h
 #endif
 
 	/* Re-enable bus mastering */
-	pci_set_master (ohci->hcd.pdev);
+	pci_set_master (to_pci_dev(ohci->hcd.self.controller));
 	
 	switch (temp) {
 
@@ -282,7 +285,7 @@ restart:
 
 #ifdef CONFIG_PMAC_PBOOK
 		if (_machine == _MACH_Pmac)
-			enable_irq (hcd->pdev->irq);
+			enable_irq (to_pci_dev(hcd->self.controller)->irq);
 #endif
 
 		/* Check for a pending done list */
--- diff/drivers/usb/host/ohci-q.c	2004-02-18 08:54:12.000000000 +0000
+++ source/drivers/usb/host/ohci-q.c	2004-02-23 13:56:46.000000000 +0000
@@ -375,7 +375,7 @@ static struct ed *ed_get (
 	if (!(ed = dev->ep [ep])) {
 		struct td	*td;
 
-		ed = ed_alloc (ohci, SLAB_ATOMIC);
+		ed = ed_alloc (ohci, GFP_ATOMIC);
 		if (!ed) {
 			/* out of memory */
 			goto done;
@@ -383,7 +383,7 @@ static struct ed *ed_get (
 		dev->ep [ep] = ed;
 
   		/* dummy td; end of td list for ed */
-		td = td_alloc (ohci, SLAB_ATOMIC);
+		td = td_alloc (ohci, GFP_ATOMIC);
  		if (!td) {
 			/* out of memory */
 			ed_free (ohci, ed);
--- diff/drivers/usb/host/ohci-sa1111.c	2004-02-18 08:54:12.000000000 +0000
+++ source/drivers/usb/host/ohci-sa1111.c	2004-02-23 13:56:46.000000000 +0000
@@ -167,9 +167,7 @@ int usb_hcd_sa1111_probe (const struct h
 	hcd->description = driver->description;
 	hcd->irq = dev->irq[1];
 	hcd->regs = dev->mapbase;
-	hcd->pdev = SA1111_FAKE_PCIDEV;
 	hcd->self.controller = &dev->dev;
-	hcd->controller = hcd->self.controller;
 
 	retval = hcd_buffer_create (hcd);
 	if (retval != 0) {
@@ -270,14 +268,12 @@ ohci_sa1111_start (struct usb_hcd *hcd)
 	struct ohci_hcd	*ohci = hcd_to_ohci (hcd);
 	int		ret;
 
-	if (hcd->pdev) {
-		ohci->hcca = pci_alloc_consistent (hcd->pdev,
-				sizeof *ohci->hcca, &ohci->hcca_dma);
-		if (!ohci->hcca)
-			return -ENOMEM;
-	}
-
-        memset (ohci->hcca, 0, sizeof (struct ohci_hcca));
+	ohci->hcca = dma_alloc_coherent (hcd->self.controller,
+			sizeof *ohci->hcca, &ohci->hcca_dma, 0);
+	if (!ohci->hcca)
+		return -ENOMEM;
+        
+	memset (ohci->hcca, 0, sizeof (struct ohci_hcca));
 	if ((ret = ohci_mem_init (ohci)) < 0) {
 		ohci_stop (hcd);
 		return ret;
--- diff/drivers/usb/host/ohci.h	2004-01-19 10:22:58.000000000 +0000
+++ source/drivers/usb/host/ohci.h	2004-02-23 13:56:46.000000000 +0000
@@ -361,8 +361,8 @@ struct ohci_hcd {
 	/*
 	 * memory management for queue data structures
 	 */
-	struct pci_pool		*td_cache;
-	struct pci_pool		*ed_cache;
+	struct dma_pool		*td_cache;
+	struct dma_pool		*ed_cache;
 	struct td		*td_hash [TD_HASH_SIZE];
 
 	/*
@@ -391,13 +391,13 @@ struct ohci_hcd {
 #endif	/* DEBUG */
 
 #define ohci_dbg(ohci, fmt, args...) \
-	dev_dbg ((ohci)->hcd.controller , fmt , ## args )
+	dev_dbg ((ohci)->hcd.self.controller , fmt , ## args )
 #define ohci_err(ohci, fmt, args...) \
-	dev_err ((ohci)->hcd.controller , fmt , ## args )
+	dev_err ((ohci)->hcd.self.controller , fmt , ## args )
 #define ohci_info(ohci, fmt, args...) \
-	dev_info ((ohci)->hcd.controller , fmt , ## args )
+	dev_info ((ohci)->hcd.self.controller , fmt , ## args )
 #define ohci_warn(ohci, fmt, args...) \
-	dev_warn ((ohci)->hcd.controller , fmt , ## args )
+	dev_warn ((ohci)->hcd.self.controller , fmt , ## args )
 
 #ifdef OHCI_VERBOSE_DEBUG
 #	define ohci_vdbg ohci_dbg
--- diff/drivers/usb/host/uhci-debug.c	2003-10-09 09:47:34.000000000 +0100
+++ source/drivers/usb/host/uhci-debug.c	2004-02-23 13:56:46.000000000 +0000
@@ -225,20 +225,22 @@ static int uhci_show_sc(int port, unsign
 	char *out = buf;
 
 	/* Try to make sure there's enough memory */
-	if (len < 80)
+	if (len < 160)
 		return 0;
 
-	out += sprintf(out, "  stat%d     =     %04x   %s%s%s%s%s%s%s%s\n",
+	out += sprintf(out, "  stat%d     =     %04x  %s%s%s%s%s%s%s%s%s%s\n",
 		port,
 		status,
-		(status & USBPORTSC_SUSP) ? "PortSuspend " : "",
-		(status & USBPORTSC_PR) ?   "PortReset " : "",
-		(status & USBPORTSC_LSDA) ? "LowSpeed " : "",
-		(status & USBPORTSC_RD) ?   "ResumeDetect " : "",
-		(status & USBPORTSC_PEC) ?  "EnableChange " : "",
-		(status & USBPORTSC_PE) ?   "PortEnabled " : "",
-		(status & USBPORTSC_CSC) ?  "ConnectChange " : "",
-		(status & USBPORTSC_CCS) ?  "PortConnected " : "");
+		(status & USBPORTSC_SUSP) ?	" Suspend" : "",
+		(status & USBPORTSC_OCC) ?	" OverCurrentChange" : "",
+		(status & USBPORTSC_OC) ?	" OverCurrent" : "",
+		(status & USBPORTSC_PR) ?	" Reset" : "",
+		(status & USBPORTSC_LSDA) ?	" LowSpeed" : "",
+		(status & USBPORTSC_RD) ?	" ResumeDetect" : "",
+		(status & USBPORTSC_PEC) ?	" EnableChange" : "",
+		(status & USBPORTSC_PE) ?	" Enabled" : "",
+		(status & USBPORTSC_CSC) ?	" ConnectChange" : "",
+		(status & USBPORTSC_CCS) ?	" Connected" : "");
 
 	return out - buf;
 }
@@ -321,8 +323,8 @@ static int uhci_show_urbp(struct uhci_hc
 	out += sprintf(out, "%s", (urbp->fsbr ? "FSBR " : ""));
 	out += sprintf(out, "%s", (urbp->fsbr_timeout ? "FSBR_TO " : ""));
 
-	if (urbp->status != -EINPROGRESS)
-		out += sprintf(out, "Status=%d ", urbp->status);
+	if (urbp->urb->status != -EINPROGRESS)
+		out += sprintf(out, "Status=%d ", urbp->urb->status);
 	//out += sprintf(out, "Inserttime=%lx ",urbp->inserttime);
 	//out += sprintf(out, "FSBRtime=%lx ",urbp->fsbrtime);
 
@@ -402,7 +404,7 @@ static int uhci_show_lists(struct uhci_h
 		head = &uhci->complete_list;
 		tmp = head->next;
 		while (tmp != head) {
-			struct urb_priv *urbp = list_entry(tmp, struct urb_priv, complete_list);
+			struct urb_priv *urbp = list_entry(tmp, struct urb_priv, urb_list);
 
 			out += sprintf(out, "  %d: ", ++count);
 			out += uhci_show_urbp(uhci, urbp, out, len - (out - buf));
@@ -418,7 +420,7 @@ static int uhci_sprint_schedule(struct u
 {
 	unsigned long flags;
 	char *out = buf;
-	int i;
+	int i, j;
 	struct uhci_qh *qh;
 	struct uhci_td *td;
 	struct list_head *tmp, *head;
@@ -473,10 +475,11 @@ static int uhci_sprint_schedule(struct u
 			continue;
 		}
 
+		j = (i < 7) ? 7 : i+1;		/* Next skeleton */
 		if (list_empty(&qh->list)) {
 			if (i < UHCI_NUM_SKELQH - 1) {
 				if (qh->link !=
-				    (cpu_to_le32(uhci->skelqh[i + 1]->dma_handle) | UHCI_PTR_QH)) {
+				    (cpu_to_le32(uhci->skelqh[j]->dma_handle) | UHCI_PTR_QH)) {
 					show_qh_name();
 					out += sprintf(out, "    skeleton QH not linked to next skeleton QH!\n");
 				}
@@ -500,7 +503,7 @@ static int uhci_sprint_schedule(struct u
 
 		if (i < UHCI_NUM_SKELQH - 1) {
 			if (qh->link !=
-			    (cpu_to_le32(uhci->skelqh[i + 1]->dma_handle) | UHCI_PTR_QH))
+			    (cpu_to_le32(uhci->skelqh[j]->dma_handle) | UHCI_PTR_QH))
 				out += sprintf(out, "    last QH not linked to next skeleton!\n");
 		}
 	}
--- diff/drivers/usb/host/uhci-hcd.c	2004-02-18 08:54:12.000000000 +0000
+++ source/drivers/usb/host/uhci-hcd.c	2004-02-23 13:56:46.000000000 +0000
@@ -13,6 +13,7 @@
  * (C) Copyright 2000 Yggdrasil Computing, Inc. (port of new PCI interface
  *               support from usb-ohci.c by Adam Richter, adam@yggdrasil.com).
  * (C) Copyright 1999 Gregory P. Smith (from usb-ohci.c)
+ * (C) Copyright 2004 Alan Stern, stern@rowland.harvard.edu
  *
  * Intel documents this fairly well, and as far as I know there
  * are no royalties or anything like that, but even so there are
@@ -27,6 +28,11 @@
  */
 
 #include <linux/config.h>
+#ifdef CONFIG_USB_DEBUG
+#define DEBUG
+#else
+#undef DEBUG
+#endif
 #include <linux/module.h>
 #include <linux/pci.h>
 #include <linux/kernel.h>
@@ -41,13 +47,12 @@
 #include <linux/interrupt.h>
 #include <linux/spinlock.h>
 #include <linux/proc_fs.h>
-#ifdef CONFIG_USB_DEBUG
-#define DEBUG
-#else
-#undef DEBUG
-#endif
+#include <linux/pm.h>
+#include <linux/dmapool.h>
+#include <linux/dma-mapping.h>
 #include <linux/usb.h>
 
+#include <asm/bitops.h>
 #include <asm/uaccess.h>
 #include <asm/io.h>
 #include <asm/irq.h>
@@ -56,13 +61,13 @@
 #include "../core/hcd.h"
 #include "uhci-hcd.h"
 
-#include <linux/pm.h>
-
 /*
  * Version Information
  */
-#define DRIVER_VERSION "v2.1"
-#define DRIVER_AUTHOR "Linus 'Frodo Rabbit' Torvalds, Johannes Erdfelt, Randy Dunlap, Georg Acher, Deti Fliegl, Thomas Sailer, Roman Weissgaerber"
+#define DRIVER_VERSION "v2.2"
+#define DRIVER_AUTHOR "Linus 'Frodo Rabbit' Torvalds, Johannes Erdfelt, \
+Randy Dunlap, Georg Acher, Deti Fliegl, Thomas Sailer, Roman Weissgaerber, \
+Alan Stern"
 #define DRIVER_DESC "USB Universal Host Controller Interface driver"
 
 /*
@@ -80,7 +85,7 @@ static int debug = 0;
 MODULE_PARM(debug, "i");
 MODULE_PARM_DESC(debug, "Debug level");
 static char *errbuf;
-#define ERRBUF_LEN    (PAGE_SIZE * 8)
+#define ERRBUF_LEN    (32 * 1024)
 
 #include "uhci-hub.c"
 #include "uhci-debug.c"
@@ -121,21 +126,17 @@ static inline void uhci_set_next_interru
 
 static inline void uhci_clear_next_interrupt(struct uhci_hcd *uhci)
 {
-	unsigned long flags;
-
-	spin_lock_irqsave(&uhci->frame_list_lock, flags);
+	spin_lock(&uhci->frame_list_lock);
 	uhci->term_td->status &= ~cpu_to_le32(TD_CTRL_IOC);
-	spin_unlock_irqrestore(&uhci->frame_list_lock, flags);
+	spin_unlock(&uhci->frame_list_lock);
 }
 
-static inline void uhci_add_complete(struct uhci_hcd *uhci, struct urb *urb)
+static inline void uhci_moveto_complete(struct uhci_hcd *uhci, 
+					struct urb_priv *urbp)
 {
-	struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv;
-	unsigned long flags;
-
-	spin_lock_irqsave(&uhci->complete_list_lock, flags);
-	list_add_tail(&urbp->complete_list, &uhci->complete_list);
-	spin_unlock_irqrestore(&uhci->complete_list_lock, flags);
+	spin_lock(&uhci->complete_list_lock);
+	list_move_tail(&urbp->urb_list, &uhci->complete_list);
+	spin_unlock(&uhci->complete_list_lock);
 }
 
 static struct uhci_td *uhci_alloc_td(struct uhci_hcd *uhci, struct usb_device *dev)
@@ -143,7 +144,7 @@ static struct uhci_td *uhci_alloc_td(str
 	dma_addr_t dma_handle;
 	struct uhci_td *td;
 
-	td = pci_pool_alloc(uhci->td_pool, GFP_ATOMIC, &dma_handle);
+	td = dma_pool_alloc(uhci->td_pool, GFP_ATOMIC, &dma_handle);
 	if (!td)
 		return NULL;
 
@@ -286,16 +287,16 @@ static void uhci_insert_tds_in_qh(struct
 static void uhci_free_td(struct uhci_hcd *uhci, struct uhci_td *td)
 {
 	if (!list_empty(&td->list))
-		dbg("td %p is still in list!", td);
+		dev_warn(uhci_dev(uhci), "td %p still in list!\n", td);
 	if (!list_empty(&td->remove_list))
-		dbg("td %p still in remove_list!", td);
+		dev_warn(uhci_dev(uhci), "td %p still in remove_list!\n", td);
 	if (!list_empty(&td->fl_list))
-		dbg("td %p is still in fl_list!", td);
+		dev_warn(uhci_dev(uhci), "td %p still in fl_list!\n", td);
 
 	if (td->dev)
 		usb_put_dev(td->dev);
 
-	pci_pool_free(uhci->td_pool, td, td->dma_handle);
+	dma_pool_free(uhci->td_pool, td, td->dma_handle);
 }
 
 static struct uhci_qh *uhci_alloc_qh(struct uhci_hcd *uhci, struct usb_device *dev)
@@ -303,7 +304,7 @@ static struct uhci_qh *uhci_alloc_qh(str
 	dma_addr_t dma_handle;
 	struct uhci_qh *qh;
 
-	qh = pci_pool_alloc(uhci->qh_pool, GFP_ATOMIC, &dma_handle);
+	qh = dma_pool_alloc(uhci->qh_pool, GFP_ATOMIC, &dma_handle);
 	if (!qh)
 		return NULL;
 
@@ -326,14 +327,14 @@ static struct uhci_qh *uhci_alloc_qh(str
 static void uhci_free_qh(struct uhci_hcd *uhci, struct uhci_qh *qh)
 {
 	if (!list_empty(&qh->list))
-		dbg("qh %p list not empty!", qh);
+		dev_warn(uhci_dev(uhci), "qh %p list not empty!\n", qh);
 	if (!list_empty(&qh->remove_list))
-		dbg("qh %p still in remove_list!", qh);
+		dev_warn(uhci_dev(uhci), "qh %p still in remove_list!\n", qh);
 
 	if (qh->dev)
 		usb_put_dev(qh->dev);
 
-	pci_pool_free(uhci->qh_pool, qh, qh->dma_handle);
+	dma_pool_free(uhci->qh_pool, qh, qh->dma_handle);
 }
 
 /*
@@ -658,10 +659,8 @@ static struct urb_priv *uhci_alloc_urb_p
 	struct urb_priv *urbp;
 
 	urbp = kmem_cache_alloc(uhci_up_cachep, SLAB_ATOMIC);
-	if (!urbp) {
-		err("uhci_alloc_urb_priv: couldn't allocate memory for urb_priv\n");
+	if (!urbp)
 		return NULL;
-	}
 
 	memset((void *)urbp, 0, sizeof(*urbp));
 
@@ -671,7 +670,6 @@ static struct urb_priv *uhci_alloc_urb_p
 	
 	INIT_LIST_HEAD(&urbp->td_list);
 	INIT_LIST_HEAD(&urbp->queue_list);
-	INIT_LIST_HEAD(&urbp->complete_list);
 	INIT_LIST_HEAD(&urbp->urb_list);
 
 	list_add_tail(&urbp->urb_list, &uhci->urb_list);
@@ -720,10 +718,8 @@ static void uhci_destroy_urb_priv(struct
 		return;
 
 	if (!list_empty(&urbp->urb_list))
-		warn("uhci_destroy_urb_priv: urb %p still on uhci->urb_list or uhci->remove_list", urb);
-
-	if (!list_empty(&urbp->complete_list))
-		warn("uhci_destroy_urb_priv: urb %p still on uhci->complete_list", urb);
+		dev_warn(uhci_dev(uhci), "urb %p still on uhci->urb_list "
+				"or uhci->remove_list!\n", urb);
 
 	spin_lock_irqsave(&uhci->td_remove_list_lock, flags);
 
@@ -913,7 +909,7 @@ static int uhci_submit_control(struct uh
 
 	uhci_insert_tds_in_qh(qh, urb, UHCI_PTR_BREADTH);
 
-	/* Low speed transfers get a different queue, and won't hog the bus */
+	/* Low-speed transfers get a different queue, and won't hog the bus */
 	if (urb->dev->speed == USB_SPEED_LOW)
 		skelqh = uhci->skel_ls_control_qh;
 	else {
@@ -961,17 +957,15 @@ static int usb_control_retrigger_status(
 	}
 
 	urbp->qh = uhci_alloc_qh(uhci, urb->dev);
-	if (!urbp->qh) {
-		err("unable to allocate new QH for control retrigger");
+	if (!urbp->qh)
 		return -ENOMEM;
-	}
 
 	urbp->qh->urbp = urbp;
 
 	/* One TD, who cares about Breadth first? */
 	uhci_insert_tds_in_qh(urbp->qh, urb, UHCI_PTR_DEPTH);
 
-	/* Low speed transfers get a different queue */
+	/* Low-speed transfers get a different queue */
 	if (urb->dev->speed == USB_SPEED_LOW)
 		uhci_insert_qh(uhci, uhci->skel_ls_control_qh, urb);
 	else
@@ -1073,7 +1067,8 @@ td_error:
 err:
 	if ((debug == 1 && ret != -EPIPE) || debug > 1) {
 		/* Some debugging code */
-		dbg("uhci_result_control() failed with status %x", status);
+		dev_dbg(uhci_dev(uhci), "%s: failed with status %x\n",
+				__FUNCTION__, status);
 
 		if (errbuf) {
 			/* Print the chain for debugging purposes */
@@ -1238,7 +1233,8 @@ err:
 #if 0
 	if ((debug == 1 && ret != -EPIPE) || debug > 1) {
 		/* Some debugging code */
-		dbg("uhci_result_common() failed with status %x", status);
+		dev_dbg(uhci_dev(uhci), "%s: failed with status %x\n",
+				__FUNCTION__, status);
 
 		if (errbuf) {
 			/* Print the chain for debugging purposes */
@@ -1255,7 +1251,7 @@ static inline int uhci_submit_bulk(struc
 {
 	int ret;
 
-	/* Can't have low speed bulk transfers */
+	/* Can't have low-speed bulk transfers */
 	if (urb->dev->speed == USB_SPEED_LOW)
 		return -EINVAL;
 
@@ -1462,11 +1458,14 @@ static int uhci_urb_enqueue(struct usb_h
 
 	spin_lock_irqsave(&uhci->urb_list_lock, flags);
 
+	if (urb->status != -EINPROGRESS)	/* URB already unlinked! */
+		goto out;
+
 	eurb = uhci_find_urb_ep(uhci, urb);
 
 	if (!uhci_alloc_urb_priv(uhci, urb)) {
-		spin_unlock_irqrestore(&uhci->urb_list_lock, flags);
-		return -ENOMEM;
+		ret = -ENOMEM;
+		goto out;
 	}
 
 	switch (usb_pipetype(urb->pipe)) {
@@ -1514,10 +1513,11 @@ static int uhci_urb_enqueue(struct usb_h
 
 		return ret;
 	}
+	ret = 0;
 
+out:
 	spin_unlock_irqrestore(&uhci->urb_list_lock, flags);
-
-	return 0;
+	return ret;
 }
 
 /*
@@ -1527,18 +1527,15 @@ static int uhci_urb_enqueue(struct usb_h
  */
 static void uhci_transfer_result(struct uhci_hcd *uhci, struct urb *urb)
 {
-	int ret = -EINVAL;
-	unsigned long flags;
+	int ret = -EINPROGRESS;
 	struct urb_priv *urbp;
 
-	spin_lock_irqsave(&urb->lock, flags);
+	spin_lock(&urb->lock);
 
 	urbp = (struct urb_priv *)urb->hcpriv;
 
-	if (urb->status != -EINPROGRESS) {
-		info("uhci_transfer_result: called for URB %p not in flight?", urb);
+	if (urb->status != -EINPROGRESS)	/* URB already dequeued */
 		goto out;
-	}
 
 	switch (usb_pipetype(urb->pipe)) {
 	case PIPE_CONTROL:
@@ -1555,10 +1552,9 @@ static void uhci_transfer_result(struct 
 		break;
 	}
 
-	urbp->status = ret;
-
 	if (ret == -EINPROGRESS)
 		goto out;
+	urb->status = ret;
 
 	switch (usb_pipetype(urb->pipe)) {
 	case PIPE_CONTROL:
@@ -1585,17 +1581,16 @@ static void uhci_transfer_result(struct 
 		uhci_unlink_generic(uhci, urb);
 		break;
 	default:
-		info("uhci_transfer_result: unknown pipe type %d for urb %p\n",
-			usb_pipetype(urb->pipe), urb);
+		dev_info(uhci_dev(uhci), "%s: unknown pipe type %d "
+				"for urb %p\n",
+				__FUNCTION__, usb_pipetype(urb->pipe), urb);
 	}
 
-	/* Remove it from uhci->urb_list */
-	list_del_init(&urbp->urb_list);
-
-	uhci_add_complete(uhci, urb);
+	/* Move it from uhci->urb_list to uhci->complete_list */
+	uhci_moveto_complete(uhci, urbp);
 
 out:
-	spin_unlock_irqrestore(&urb->lock, flags);
+	spin_unlock(&urb->lock);
 }
 
 /*
@@ -1607,10 +1602,6 @@ static void uhci_unlink_generic(struct u
 	struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv;
 	int prevactive = 1;
 
-	/* We can get called when urbp allocation fails, so check */
-	if (!urbp)
-		return;
-
 	uhci_dec_fsbr(uhci, urb);	/* Safe since it checks */
 
 	/*
@@ -1660,13 +1651,6 @@ static int uhci_urb_dequeue(struct usb_h
 	unsigned long flags;
 	struct urb_priv *urbp = urb->hcpriv;
 
-	/* If this is an interrupt URB that is being killed in urb->complete, */
-	/* then just set its status and return */
-	if (!urbp) {
-	  urb->status = -ECONNRESET;
-	  return 0;
-	}
-
 	spin_lock_irqsave(&uhci->urb_list_lock, flags);
 
 	list_del_init(&urbp->urb_list);
@@ -1678,7 +1662,7 @@ static int uhci_urb_dequeue(struct usb_h
 	/* If we're the first, set the next interrupt bit */
 	if (list_empty(&uhci->urb_remove_list))
 		uhci_set_next_interrupt(uhci);
-	list_add(&urbp->urb_list, &uhci->urb_remove_list);
+	list_add_tail(&urbp->urb_list, &uhci->urb_remove_list);
 
 	spin_unlock(&uhci->urb_remove_list_lock);
 	spin_unlock_irqrestore(&uhci->urb_list_lock, flags);
@@ -1805,9 +1789,8 @@ static int init_stall_timer(struct usb_h
 static void uhci_free_pending_qhs(struct uhci_hcd *uhci)
 {
 	struct list_head *tmp, *head;
-	unsigned long flags;
 
-	spin_lock_irqsave(&uhci->qh_remove_list_lock, flags);
+	spin_lock(&uhci->qh_remove_list_lock);
 	head = &uhci->qh_remove_list;
 	tmp = head->next;
 	while (tmp != head) {
@@ -1819,15 +1802,14 @@ static void uhci_free_pending_qhs(struct
 
 		uhci_free_qh(uhci, qh);
 	}
-	spin_unlock_irqrestore(&uhci->qh_remove_list_lock, flags);
+	spin_unlock(&uhci->qh_remove_list_lock);
 }
 
 static void uhci_free_pending_tds(struct uhci_hcd *uhci)
 {
 	struct list_head *tmp, *head;
-	unsigned long flags;
 
-	spin_lock_irqsave(&uhci->td_remove_list_lock, flags);
+	spin_lock(&uhci->td_remove_list_lock);
 	head = &uhci->td_remove_list;
 	tmp = head->next;
 	while (tmp != head) {
@@ -1839,23 +1821,16 @@ static void uhci_free_pending_tds(struct
 
 		uhci_free_td(uhci, td);
 	}
-	spin_unlock_irqrestore(&uhci->td_remove_list_lock, flags);
+	spin_unlock(&uhci->td_remove_list_lock);
 }
 
 static void uhci_finish_urb(struct usb_hcd *hcd, struct urb *urb, struct pt_regs *regs)
 {
-	struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv;
 	struct uhci_hcd *uhci = hcd_to_uhci(hcd);
-	int status;
-	unsigned long flags;
 
-	spin_lock_irqsave(&urb->lock, flags);
-	status = urbp->status;
+	spin_lock(&urb->lock);
 	uhci_destroy_urb_priv(uhci, urb);
-
- 	if (urb->status != -ENOENT && urb->status != -ECONNRESET)
-		urb->status = status;
-	spin_unlock_irqrestore(&urb->lock, flags);
+	spin_unlock(&urb->lock);
 
 	usb_hcd_giveback_urb(hcd, urb, regs);
 }
@@ -1864,48 +1839,40 @@ static void uhci_finish_completion(struc
 {
 	struct uhci_hcd *uhci = hcd_to_uhci(hcd);
 	struct list_head *tmp, *head;
-	unsigned long flags;
 
-	spin_lock_irqsave(&uhci->complete_list_lock, flags);
+	spin_lock(&uhci->complete_list_lock);
 	head = &uhci->complete_list;
 	tmp = head->next;
 	while (tmp != head) {
-		struct urb_priv *urbp = list_entry(tmp, struct urb_priv, complete_list);
+		struct urb_priv *urbp = list_entry(tmp, struct urb_priv, urb_list);
 		struct urb *urb = urbp->urb;
 
-		list_del_init(&urbp->complete_list);
-		spin_unlock_irqrestore(&uhci->complete_list_lock, flags);
+		list_del_init(&urbp->urb_list);
+		spin_unlock(&uhci->complete_list_lock);
 
 		uhci_finish_urb(hcd, urb, regs);
 
-		spin_lock_irqsave(&uhci->complete_list_lock, flags);
+		spin_lock(&uhci->complete_list_lock);
 		head = &uhci->complete_list;
 		tmp = head->next;
 	}
-	spin_unlock_irqrestore(&uhci->complete_list_lock, flags);
+	spin_unlock(&uhci->complete_list_lock);
 }
 
-static void uhci_remove_pending_qhs(struct uhci_hcd *uhci)
+static void uhci_remove_pending_urbps(struct uhci_hcd *uhci)
 {
 	struct list_head *tmp, *head;
-	unsigned long flags;
 
-	spin_lock_irqsave(&uhci->urb_remove_list_lock, flags);
+	spin_lock(&uhci->urb_remove_list_lock);
 	head = &uhci->urb_remove_list;
 	tmp = head->next;
 	while (tmp != head) {
 		struct urb_priv *urbp = list_entry(tmp, struct urb_priv, urb_list);
-		struct urb *urb = urbp->urb;
 
 		tmp = tmp->next;
-
-		list_del_init(&urbp->urb_list);
-
-		urbp->status = urb->status = -ECONNRESET;
-
-		uhci_add_complete(uhci, urb);
+		uhci_moveto_complete(uhci, urbp);
 	}
-	spin_unlock_irqrestore(&uhci->urb_remove_list_lock, flags);
+	spin_unlock(&uhci->urb_remove_list_lock);
 }
 
 static irqreturn_t uhci_irq(struct usb_hcd *hcd, struct pt_regs *regs)
@@ -1917,20 +1884,24 @@ static irqreturn_t uhci_irq(struct usb_h
 
 	/*
 	 * Read the interrupt status, and write it back to clear the
-	 * interrupt cause
+	 * interrupt cause.  Contrary to the UHCI specification, the
+	 * "HC Halted" status bit is persistent: it is RO, not R/WC.
 	 */
 	status = inw(io_addr + USBSTS);
-	if (!status)	/* shared interrupt, not mine */
+	if (!(status & ~USBSTS_HCH))	/* shared interrupt, not mine */
 		return IRQ_NONE;
 	outw(status, io_addr + USBSTS);		/* Clear it */
 
 	if (status & ~(USBSTS_USBINT | USBSTS_ERROR | USBSTS_RD)) {
 		if (status & USBSTS_HSE)
-			err("%x: host system error, PCI problems?", io_addr);
+			dev_err(uhci_dev(uhci), "host system error, "
+					"PCI problems?\n");
 		if (status & USBSTS_HCPE)
-			err("%x: host controller process error. something bad happened", io_addr);
+			dev_err(uhci_dev(uhci), "host controller process "
+					"error, something bad happened!\n");
 		if ((status & USBSTS_HCH) && uhci->state > 0) {
-			err("%x: host controller halted. very bad", io_addr);
+			dev_err(uhci_dev(uhci), "host controller halted, "
+					"very bad!\n");
 			/* FIXME: Reset the controller, fix the offending TD */
 		}
 	}
@@ -1942,7 +1913,7 @@ static irqreturn_t uhci_irq(struct usb_h
 
 	uhci_free_pending_tds(uhci);
 
-	uhci_remove_pending_qhs(uhci);
+	uhci_remove_pending_urbps(uhci);
 
 	uhci_clear_next_interrupt(uhci);
 
@@ -1986,7 +1957,7 @@ static void suspend_hc(struct uhci_hcd *
 {
 	unsigned int io_addr = uhci->io_addr;
 
-	dbg("%x: suspend_hc", io_addr);
+	dev_dbg(uhci_dev(uhci), "%s\n", __FUNCTION__);
 	uhci->state = UHCI_SUSPENDED;
 	uhci->resume_detect = 0;
 	outw(USBCMD_EGSM, io_addr + USBCMD);
@@ -1998,7 +1969,7 @@ static void wakeup_hc(struct uhci_hcd *u
 
 	switch (uhci->state) {
 		case UHCI_SUSPENDED:		/* Start the resume */
-			dbg("%x: wakeup_hc", io_addr);
+			dev_dbg(uhci_dev(uhci), "%s\n", __FUNCTION__);
 
 			/* Global resume for >= 20ms */
 			outw(USBCMD_FGR | USBCMD_EGSM, io_addr + USBCMD);
@@ -2049,7 +2020,7 @@ static int suspend_allowed(struct uhci_h
 	unsigned int io_addr = uhci->io_addr;
 	int i;
 
-	if (!uhci->hcd.pdev || uhci->hcd.pdev->vendor != PCI_VENDOR_ID_INTEL)
+	if (to_pci_dev(uhci_dev(uhci))->vendor != PCI_VENDOR_ID_INTEL)
 		return 1;
 
 	/* Some of Intel's USB controllers have a bug that causes false
@@ -2123,7 +2094,7 @@ static void start_hc(struct uhci_hcd *uh
 	outw(USBCMD_HCRESET, io_addr + USBCMD);
 	while (inw(io_addr + USBCMD) & USBCMD_HCRESET) {
 		if (!--timeout) {
-			printk(KERN_ERR "uhci: USBCMD_HCRESET timed out!\n");
+			dev_err(uhci_dev(uhci), "USBCMD_HCRESET timed out!\n");
 			break;
 		}
 	}
@@ -2163,17 +2134,18 @@ static void release_uhci(struct uhci_hcd
 	}
 
 	if (uhci->qh_pool) {
-		pci_pool_destroy(uhci->qh_pool);
+		dma_pool_destroy(uhci->qh_pool);
 		uhci->qh_pool = NULL;
 	}
 
 	if (uhci->td_pool) {
-		pci_pool_destroy(uhci->td_pool);
+		dma_pool_destroy(uhci->td_pool);
 		uhci->td_pool = NULL;
 	}
 
 	if (uhci->fl) {
-		pci_free_consistent(uhci->hcd.pdev, sizeof(*uhci->fl), uhci->fl, uhci->fl->dma_handle);
+		dma_free_coherent(uhci_dev(uhci), sizeof(*uhci->fl),
+				uhci->fl, uhci->fl->dma_handle);
 		uhci->fl = NULL;
 	}
 
@@ -2198,7 +2170,8 @@ static int uhci_reset(struct usb_hcd *hc
 	 * interrupts from any previous setup.
 	 */
 	reset_hc(uhci);
-	pci_write_config_word(hcd->pdev, USBLEGSUP, USBLEGSUP_DEFAULT);
+	pci_write_config_word(to_pci_dev(uhci_dev(uhci)), USBLEGSUP,
+			USBLEGSUP_DEFAULT);
 	return 0;
 }
 
@@ -2213,10 +2186,10 @@ static int uhci_reset(struct usb_hcd *hc
  *    of the queues. We don't do that here, because
  *    we'll create the actual TD entries on demand.
  *  - The first queue is the interrupt queue.
- *  - The second queue is the control queue, split into low and high speed
+ *  - The second queue is the control queue, split into low- and full-speed
  *  - The third queue is bulk queue.
  *  - The fourth queue is the bandwidth reclamation queue, which loops back
- *    to the high speed control queue.
+ *    to the full-speed control queue.
  */
 static int uhci_start(struct usb_hcd *hcd)
 {
@@ -2230,12 +2203,12 @@ static int uhci_start(struct usb_hcd *hc
 	struct proc_dir_entry *ent;
 #endif
 
-	io_size = pci_resource_len(hcd->pdev, hcd->region);
+	io_size = pci_resource_len(to_pci_dev(uhci_dev(uhci)), hcd->region);
 
 #ifdef CONFIG_PROC_FS
 	ent = create_proc_entry(hcd->self.bus_name, S_IFREG|S_IRUGO|S_IWUSR, uhci_proc_root);
 	if (!ent) {
-		err("couldn't create uhci proc entry");
+		dev_err(uhci_dev(uhci), "couldn't create uhci proc entry\n");
 		retval = -ENOMEM;
 		goto err_create_proc_entry;
 	}
@@ -2266,9 +2239,11 @@ static int uhci_start(struct usb_hcd *hc
 
 	spin_lock_init(&uhci->frame_list_lock);
 
-	uhci->fl = pci_alloc_consistent(hcd->pdev, sizeof(*uhci->fl), &dma_handle);
+	uhci->fl = dma_alloc_coherent(uhci_dev(uhci), sizeof(*uhci->fl),
+			&dma_handle, 0);
 	if (!uhci->fl) {
-		err("unable to allocate consistent memory for frame list");
+		dev_err(uhci_dev(uhci), "unable to allocate "
+				"consistent memory for frame list\n");
 		goto err_alloc_fl;
 	}
 
@@ -2276,17 +2251,17 @@ static int uhci_start(struct usb_hcd *hc
 
 	uhci->fl->dma_handle = dma_handle;
 
-	uhci->td_pool = pci_pool_create("uhci_td", hcd->pdev,
-		sizeof(struct uhci_td), 16, 0);
+	uhci->td_pool = dma_pool_create("uhci_td", uhci_dev(uhci),
+			sizeof(struct uhci_td), 16, 0);
 	if (!uhci->td_pool) {
-		err("unable to create td pci_pool");
+		dev_err(uhci_dev(uhci), "unable to create td dma_pool\n");
 		goto err_create_td_pool;
 	}
 
-	uhci->qh_pool = pci_pool_create("uhci_qh", hcd->pdev,
-		sizeof(struct uhci_qh), 16, 0);
+	uhci->qh_pool = dma_pool_create("uhci_qh", uhci_dev(uhci),
+			sizeof(struct uhci_qh), 16, 0);
 	if (!uhci->qh_pool) {
-		err("unable to create qh pci_pool");
+		dev_err(uhci_dev(uhci), "unable to create qh dma_pool\n");
 		goto err_create_qh_pool;
 	}
 
@@ -2304,12 +2279,13 @@ static int uhci_start(struct usb_hcd *hc
 			break;
 	}
 	if (debug)
-		info("detected %d ports", port);
+		dev_info(uhci_dev(uhci), "detected %d ports\n", port);
 
 	/* This is experimental so anything less than 2 or greater than 8 is */
 	/*  something weird and we'll ignore it */
-	if (port < 2 || port > 8) {
-		info("port count misdetected? forcing to 2 ports");
+	if (port < 2 || port > UHCI_RH_MAXCHILD) {
+		dev_info(uhci_dev(uhci), "port count misdetected? "
+				"forcing to 2 ports\n");
 		port = 2;
 	}
 
@@ -2317,35 +2293,36 @@ static int uhci_start(struct usb_hcd *hc
 
 	hcd->self.root_hub = udev = usb_alloc_dev(NULL, &hcd->self, 0);
 	if (!udev) {
-		err("unable to allocate root hub");
+		dev_err(uhci_dev(uhci), "unable to allocate root hub\n");
 		goto err_alloc_root_hub;
 	}
 
 	uhci->term_td = uhci_alloc_td(uhci, udev);
 	if (!uhci->term_td) {
-		err("unable to allocate terminating TD");
+		dev_err(uhci_dev(uhci), "unable to allocate terminating TD\n");
 		goto err_alloc_term_td;
 	}
 
 	for (i = 0; i < UHCI_NUM_SKELQH; i++) {
 		uhci->skelqh[i] = uhci_alloc_qh(uhci, udev);
 		if (!uhci->skelqh[i]) {
-			err("unable to allocate QH %d", i);
+			dev_err(uhci_dev(uhci), "unable to allocate QH\n");
 			goto err_alloc_skelqh;
 		}
 	}
 
 	/*
-	 * 8 Interrupt queues; link int2 to int1, int4 to int2, etc
+	 * 8 Interrupt queues; link all higher int queues to int1,
 	 * then link int1 to control and control to bulk
 	 */
-	uhci->skel_int128_qh->link = cpu_to_le32(uhci->skel_int64_qh->dma_handle) | UHCI_PTR_QH;
-	uhci->skel_int64_qh->link = cpu_to_le32(uhci->skel_int32_qh->dma_handle) | UHCI_PTR_QH;
-	uhci->skel_int32_qh->link = cpu_to_le32(uhci->skel_int16_qh->dma_handle) | UHCI_PTR_QH;
-	uhci->skel_int16_qh->link = cpu_to_le32(uhci->skel_int8_qh->dma_handle) | UHCI_PTR_QH;
-	uhci->skel_int8_qh->link = cpu_to_le32(uhci->skel_int4_qh->dma_handle) | UHCI_PTR_QH;
-	uhci->skel_int4_qh->link = cpu_to_le32(uhci->skel_int2_qh->dma_handle) | UHCI_PTR_QH;
-	uhci->skel_int2_qh->link = cpu_to_le32(uhci->skel_int1_qh->dma_handle) | UHCI_PTR_QH;
+	uhci->skel_int128_qh->link =
+			uhci->skel_int64_qh->link =
+			uhci->skel_int32_qh->link =
+			uhci->skel_int16_qh->link =
+			uhci->skel_int8_qh->link =
+			uhci->skel_int4_qh->link =
+			uhci->skel_int2_qh->link =
+			cpu_to_le32(uhci->skel_int1_qh->dma_handle) | UHCI_PTR_QH;
 	uhci->skel_int1_qh->link = cpu_to_le32(uhci->skel_ls_control_qh->dma_handle) | UHCI_PTR_QH;
 
 	uhci->skel_ls_control_qh->link = cpu_to_le32(uhci->skel_hs_control_qh->dma_handle) | UHCI_PTR_QH;
@@ -2361,39 +2338,33 @@ static int uhci_start(struct usb_hcd *hc
 	uhci->skel_term_qh->element = cpu_to_le32(uhci->term_td->dma_handle);
 
 	/*
-	 * Fill the frame list: make all entries point to
-	 * the proper interrupt queue.
+	 * Fill the frame list: make all entries point to the proper
+	 * interrupt queue.
 	 *
-	 * This is probably silly, but it's a simple way to
-	 * scatter the interrupt queues in a way that gives
-	 * us a reasonable dynamic range for irq latencies.
+	 * The interrupt queues will be interleaved as evenly as possible.
+	 * There's not much to be done about period-1 interrupts; they have
+	 * to occur in every frame.  But we can schedule period-2 interrupts
+	 * in odd-numbered frames, period-4 interrupts in frames congruent
+	 * to 2 (mod 4), and so on.  This way each frame only has two
+	 * interrupt QHs, which will help spread out bandwidth utilization.
 	 */
 	for (i = 0; i < UHCI_NUMFRAMES; i++) {
-		int irq = 0;
+		int irq;
 
-		if (i & 1) {
-			irq++;
-			if (i & 2) {
-				irq++;
-				if (i & 4) { 
-					irq++;
-					if (i & 8) { 
-						irq++;
-						if (i & 16) {
-							irq++;
-							if (i & 32) {
-								irq++;
-								if (i & 64)
-									irq++;
-							}
-						}
-					}
-				}
-			}
-		}
+		/*
+		 * ffs (Find First bit Set) does exactly what we need:
+		 * 1,3,5,...  => ffs = 0 => use skel_int2_qh = skelqh[6],
+		 * 2,6,10,... => ffs = 1 => use skel_int4_qh = skelqh[5], etc.
+		 * ffs > 6 => not on any high-period queue, so use
+		 *	skel_int1_qh = skelqh[7].
+		 * Add UHCI_NUMFRAMES to insure at least one bit is set.
+		 */
+		irq = 6 - (int) __ffs(i + UHCI_NUMFRAMES);
+		if (irq < 0)
+			irq = 7;
 
 		/* Only place we don't use the frame list routines */
-		uhci->fl->frame[i] = cpu_to_le32(uhci->skelqh[7 - irq]->dma_handle);
+		uhci->fl->frame[i] = cpu_to_le32(uhci->skelqh[irq]->dma_handle);
 	}
 
 	start_hc(uhci);
@@ -2402,8 +2373,8 @@ static int uhci_start(struct usb_hcd *hc
 
 	udev->speed = USB_SPEED_FULL;
 
-	if (usb_register_root_hub(udev, &hcd->pdev->dev) != 0) {
-		err("unable to start root hub");
+	if (usb_register_root_hub(udev, uhci_dev(uhci)) != 0) {
+		dev_err(uhci_dev(uhci), "unable to start root hub\n");
 		retval = -ENOMEM;
 		goto err_start_root_hub;
 	}
@@ -2433,15 +2404,16 @@ err_alloc_term_td:
 	hcd->self.root_hub = NULL;
 
 err_alloc_root_hub:
-	pci_pool_destroy(uhci->qh_pool);
+	dma_pool_destroy(uhci->qh_pool);
 	uhci->qh_pool = NULL;
 
 err_create_qh_pool:
-	pci_pool_destroy(uhci->td_pool);
+	dma_pool_destroy(uhci->td_pool);
 	uhci->td_pool = NULL;
 
 err_create_td_pool:
-	pci_free_consistent(hcd->pdev, sizeof(*uhci->fl), uhci->fl, uhci->fl->dma_handle);
+	dma_free_coherent(uhci_dev(uhci), sizeof(*uhci->fl),
+			uhci->fl, uhci->fl->dma_handle);
 	uhci->fl = NULL;
 
 err_alloc_fl:
@@ -2458,6 +2430,7 @@ err_create_proc_entry:
 static void uhci_stop(struct usb_hcd *hcd)
 {
 	struct uhci_hcd *uhci = hcd_to_uhci(hcd);
+	unsigned long flags;
 
 	del_timer_sync(&uhci->stall_timer);
 
@@ -2465,15 +2438,17 @@ static void uhci_stop(struct usb_hcd *hc
 	 * At this point, we're guaranteed that no new connects can be made
 	 * to this bus since there are no more parents
 	 */
+	local_irq_save(flags);
 	uhci_free_pending_qhs(uhci);
 	uhci_free_pending_tds(uhci);
-	uhci_remove_pending_qhs(uhci);
+	uhci_remove_pending_urbps(uhci);
 
 	reset_hc(uhci);
 
 	uhci_free_pending_qhs(uhci);
 	uhci_free_pending_tds(uhci);
-
+	local_irq_restore(flags);
+	
 	release_uhci(uhci);
 }
 
@@ -2494,7 +2469,7 @@ static int uhci_resume(struct usb_hcd *h
 {
 	struct uhci_hcd *uhci = hcd_to_uhci(hcd);
 
-	pci_set_master(uhci->hcd.pdev);
+	pci_set_master(to_pci_dev(uhci_dev(uhci)));
 
 	if (uhci->state == UHCI_SUSPENDED)
 		uhci->resume_detect = 1;
@@ -2586,7 +2561,7 @@ static int __init uhci_hcd_init(void)
 {
 	int retval = -ENOMEM;
 
-	info(DRIVER_DESC " " DRIVER_VERSION);
+	printk(KERN_INFO DRIVER_DESC " " DRIVER_VERSION "\n");
 
 	if (usb_disabled())
 		return -ENODEV;
@@ -2616,7 +2591,7 @@ static int __init uhci_hcd_init(void)
 
 init_failed:
 	if (kmem_cache_destroy(uhci_up_cachep))
-		printk(KERN_INFO "uhci: not all urb_priv's were freed\n");
+		warn("not all urb_priv's were freed!");
 
 up_failed:
 
@@ -2638,7 +2613,7 @@ static void __exit uhci_hcd_cleanup(void
 	pci_unregister_driver(&uhci_pci_driver);
 	
 	if (kmem_cache_destroy(uhci_up_cachep))
-		printk(KERN_INFO "uhci: not all urb_priv's were freed\n");
+		warn("not all urb_priv's were freed!");
 
 #ifdef CONFIG_PROC_FS
 	remove_proc_entry("driver/uhci", 0);
@@ -2654,4 +2629,3 @@ module_exit(uhci_hcd_cleanup);
 MODULE_AUTHOR(DRIVER_AUTHOR);
 MODULE_DESCRIPTION(DRIVER_DESC);
 MODULE_LICENSE("GPL");
-
--- diff/drivers/usb/host/uhci-hcd.h	2004-02-18 08:54:12.000000000 +0000
+++ source/drivers/usb/host/uhci-hcd.h	2004-02-23 13:56:46.000000000 +0000
@@ -49,12 +49,19 @@
 #define   USBPORTSC_CSC		0x0002	/* Connect Status Change */
 #define   USBPORTSC_PE		0x0004	/* Port Enable */
 #define   USBPORTSC_PEC		0x0008	/* Port Enable Change */
-#define   USBPORTSC_LS		0x0030	/* Line Status */
+#define   USBPORTSC_DPLUS	0x0010	/* D+ high (line status) */
+#define   USBPORTSC_DMINUS	0x0020	/* D- high (line status) */
 #define   USBPORTSC_RD		0x0040	/* Resume Detect */
+#define   USBPORTSC_RES1	0x0080	/* reserved, always 1 */
 #define   USBPORTSC_LSDA	0x0100	/* Low Speed Device Attached */
 #define   USBPORTSC_PR		0x0200	/* Port Reset */
+/* OC and OCC from Intel 430TX and later (not UHCI 1.1d spec) */
 #define   USBPORTSC_OC		0x0400	/* Over Current condition */
+#define   USBPORTSC_OCC		0x0800	/* Over Current Change R/WC */
 #define   USBPORTSC_SUSP	0x1000	/* Suspend */
+#define   USBPORTSC_RES2	0x2000	/* reserved, write zeroes */
+#define   USBPORTSC_RES3	0x4000	/* reserved, write zeroes */
+#define   USBPORTSC_RES4	0x8000	/* reserved, write zeroes */
 
 /* Legacy support register */
 #define USBLEGSUP		0xc0
@@ -200,8 +207,8 @@ struct uhci_td {
  * The UHCI driver places Interrupt, Control and Bulk into QH's both
  * to group together TD's for one transfer, and also to faciliate queuing
  * of URB's. To make it easy to insert entries into the schedule, we have
- * a skeleton of QH's for each predefined Interrupt latency, low speed
- * control, high speed control and terminating QH (see explanation for
+ * a skeleton of QH's for each predefined Interrupt latency, low-speed
+ * control, full-speed control and terminating QH (see explanation for
  * the terminating QH below).
  *
  * When we want to add a new QH, we add it to the end of the list for the
@@ -216,9 +223,9 @@ struct uhci_td {
  * skel int32 QH
  * ...
  * skel int1 QH
- * skel low speed control QH
+ * skel low-speed control QH
  * dev 5 control QH
- * skel high speed control QH
+ * skel full-speed control QH
  * skel bulk QH
  * dev 1 bulk QH
  * dev 2 bulk QH
@@ -227,7 +234,7 @@ struct uhci_td {
  * The terminating QH is used for 2 reasons:
  * - To place a terminating TD which is used to workaround a PIIX bug
  *   (see Intel errata for explanation)
- * - To loop back to the high speed control queue for full speed bandwidth
+ * - To loop back to the full-speed control queue for full-speed bandwidth
  *   reclamation
  *
  * Isochronous transfers are stored before the start of the skeleton
@@ -308,6 +315,7 @@ enum uhci_state {
 };
 
 #define hcd_to_uhci(hcd_ptr) container_of(hcd_ptr, struct uhci_hcd, hcd)
+#define uhci_dev(u)	((u)->hcd.self.controller)
 
 /*
  * This describes the full uhci information.
@@ -326,8 +334,8 @@ struct uhci_hcd {
 	/* Grabbed from PCI */
 	unsigned long io_addr;
 
-	struct pci_pool *qh_pool;
-	struct pci_pool *td_pool;
+	struct dma_pool *qh_pool;
+	struct dma_pool *td_pool;
 
 	struct usb_bus *bus;
 
@@ -336,7 +344,7 @@ struct uhci_hcd {
 
 	spinlock_t frame_list_lock;
 	struct uhci_frame_list *fl;		/* P: uhci->frame_list_lock */
-	int fsbr;				/* Full speed bandwidth reclamation */
+	int fsbr;				/* Full-speed bandwidth reclamation */
 	unsigned long fsbrtimeout;		/* FSBR delay */
 
 	enum uhci_state state;			/* FIXME: needs a spinlock */
@@ -383,13 +391,10 @@ struct urb_priv {
 					/*  a control transfer, retrigger */
 					/*  the status phase */
 
-	int status;			/* Final status */
-
 	unsigned long inserttime;	/* In jiffies */
 	unsigned long fsbrtime;		/* In jiffies */
 
 	struct list_head queue_list;	/* P: uhci->frame_list_lock */
-	struct list_head complete_list;	/* P: uhci->complete_list_lock */
 };
 
 /*
@@ -418,4 +423,3 @@ struct urb_priv {
  */
 
 #endif
-
--- diff/drivers/usb/host/uhci-hub.c	2002-10-16 04:27:14.000000000 +0100
+++ source/drivers/usb/host/uhci-hub.c	2004-02-23 13:56:46.000000000 +0000
@@ -1,7 +1,7 @@
 /*
  * Universal Host Controller Interface driver for USB.
  *
- * Maintainer: Johannes Erdfelt <johannes@erdfelt.com>
+ * Maintainer: Alan Stern <stern@rowland.harvard.edu>
  *
  * (C) Copyright 1999 Linus Torvalds
  * (C) Copyright 1999-2002 Johannes Erdfelt, johannes@erdfelt.com
@@ -9,6 +9,7 @@
  * (C) Copyright 1999 Georg Acher, acher@in.tum.de
  * (C) Copyright 1999 Deti Fliegl, deti@fliegl.de
  * (C) Copyright 1999 Thomas Sailer, sailer@ife.ee.ethz.ch
+ * (C) Copyright 2004 Alan Stern, stern@rowland.harvard.edu
  */
 
 static __u8 root_hub_hub_des[] =
@@ -16,40 +17,50 @@ static __u8 root_hub_hub_des[] =
 	0x09,			/*  __u8  bLength; */
 	0x29,			/*  __u8  bDescriptorType; Hub-descriptor */
 	0x02,			/*  __u8  bNbrPorts; */
-	0x00,			/* __u16  wHubCharacteristics; */
-	0x00,
+	0x0a,			/* __u16  wHubCharacteristics; */
+	0x00,			/*   (per-port OC, no power switching) */
 	0x01,			/*  __u8  bPwrOn2pwrGood; 2ms */
 	0x00,			/*  __u8  bHubContrCurrent; 0 mA */
 	0x00,			/*  __u8  DeviceRemovable; *** 7 Ports max *** */
 	0xff			/*  __u8  PortPwrCtrlMask; *** 7 ports max *** */
 };
 
+#define	UHCI_RH_MAXCHILD	7
+
+/* must write as zeroes */
+#define WZ_BITS		(USBPORTSC_RES2 | USBPORTSC_RES3 | USBPORTSC_RES4)
+
+/* status change bits:  nonzero writes will clear */
+#define RWC_BITS	(USBPORTSC_OCC | USBPORTSC_PEC | USBPORTSC_CSC)
+
 static int uhci_hub_status_data(struct usb_hcd *hcd, char *buf)
 {
 	struct uhci_hcd *uhci = hcd_to_uhci(hcd);
 	unsigned int io_addr = uhci->io_addr;
-	int i, len = 1;
+	int i;
 
 	*buf = 0;
 	for (i = 0; i < uhci->rh_numports; i++) {
-		*buf |= ((inw(io_addr + USBPORTSC1 + i * 2) & 0xa) > 0 ? (1 << (i + 1)) : 0);
-		len = (i + 1) / 8 + 1;
+		if (inw(io_addr + USBPORTSC1 + i * 2) & RWC_BITS)
+			*buf |= (1 << (i + 1));
 	}
-
 	return !!*buf;
 }
 
 #define OK(x)			len = (x); break
 
 #define CLR_RH_PORTSTAT(x) \
-	status = inw(io_addr + USBPORTSC1 + 2 * (wIndex-1)); \
-	status = (status & 0xfff5) & ~(x); \
-	outw(status, io_addr + USBPORTSC1 + 2 * (wIndex-1))
+	status = inw(port_addr); \
+	status &= ~(RWC_BITS|WZ_BITS); \
+	status &= ~(x); \
+	status |= RWC_BITS & (x); \
+	outw(status, port_addr)
 
 #define SET_RH_PORTSTAT(x) \
-	status = inw(io_addr + USBPORTSC1 + 2 * (wIndex-1)); \
-	status = (status & 0xfff5) | (x); \
-	outw(status, io_addr + USBPORTSC1 + 2 * (wIndex-1))
+	status = inw(port_addr); \
+	status |= (x); \
+	status &= ~(RWC_BITS|WZ_BITS); \
+	outw(status, port_addr)
 
 
 /* size of returned buffer is part of USB spec */
@@ -57,13 +68,9 @@ static int uhci_hub_control(struct usb_h
 			u16 wIndex, char *buf, u16 wLength)
 {
 	struct uhci_hcd *uhci = hcd_to_uhci(hcd);
-	int i, status, retval = 0, len = 0;
-	unsigned int io_addr = uhci->io_addr;
-	__u16 cstatus;
-	char c_p_r[8];
-
-	for (i = 0; i < 8; i++)
-		c_p_r[i] = 0;
+	int status, retval = 0, len = 0;
+	unsigned int port_addr = uhci->io_addr + USBPORTSC1 + 2 * (wIndex-1);
+	__u16 wPortChange, wPortStatus;
 
 	switch (typeReq) {
 		/* Request Destination:
@@ -78,33 +85,56 @@ static int uhci_hub_control(struct usb_h
 		*(__u32 *)buf = cpu_to_le32(0);
 		OK(4);		/* hub power */
 	case GetPortStatus:
-		status = inw(io_addr + USBPORTSC1 + 2 * (wIndex - 1));
-		cstatus = ((status & USBPORTSC_CSC) >> (1 - 0)) |
-			((status & USBPORTSC_PEC) >> (3 - 1)) |
-			(c_p_r[wIndex - 1] << (0 + 4));
-			status = (status & USBPORTSC_CCS) |
-			((status & USBPORTSC_PE) >> (2 - 1)) |
-			((status & USBPORTSC_SUSP) >> (12 - 2)) |
-			((status & USBPORTSC_PR) >> (9 - 4)) |
-			(1 << 8) |      /* power on */
-			((status & USBPORTSC_LSDA) << (-8 + 9));
-
-		*(__u16 *)buf = cpu_to_le16(status);
-		*(__u16 *)(buf + 2) = cpu_to_le16(cstatus);
-		OK(4);
-	case SetHubFeature:
-		switch (wValue) {
-		case C_HUB_OVER_CURRENT:
-		case C_HUB_LOCAL_POWER:
-			break;
-		default:
+		if (!wIndex || wIndex > uhci->rh_numports)
 			goto err;
+		status = inw(port_addr);
+
+		/* Intel controllers report the OverCurrent bit active on.
+		 * VIA controllers report it active off, so we'll adjust the
+		 * bit value.  (It's not standardized in the UHCI spec.)
+		 */
+		if (to_pci_dev(hcd->self.controller)->vendor ==
+				PCI_VENDOR_ID_VIA)
+			status ^= USBPORTSC_OC;
+
+		/* UHCI doesn't support C_SUSPEND and C_RESET (always false) */
+		wPortChange = 0;
+		if (status & USBPORTSC_CSC)
+			wPortChange |= 1 << (USB_PORT_FEAT_C_CONNECTION - 16);
+		if (status & USBPORTSC_PEC)
+			wPortChange |= 1 << (USB_PORT_FEAT_C_ENABLE - 16);
+		if (status & USBPORTSC_OCC)
+			wPortChange |= 1 << (USB_PORT_FEAT_C_OVER_CURRENT - 16);
+
+		/* UHCI has no power switching (always on) */
+		wPortStatus = 1 << USB_PORT_FEAT_POWER;
+		if (status & USBPORTSC_CCS)
+			wPortStatus |= 1 << USB_PORT_FEAT_CONNECTION;
+		if (status & USBPORTSC_PE) {
+			wPortStatus |= 1 << USB_PORT_FEAT_ENABLE;
+			if (status & (USBPORTSC_SUSP | USBPORTSC_RD))
+				wPortStatus |= 1 << USB_PORT_FEAT_SUSPEND;
 		}
-		break;
+		if (status & USBPORTSC_OC)
+			wPortStatus |= 1 << USB_PORT_FEAT_OVER_CURRENT;
+		if (status & USBPORTSC_PR)
+			wPortStatus |= 1 << USB_PORT_FEAT_RESET;
+		if (status & USBPORTSC_LSDA)
+			wPortStatus |= 1 << USB_PORT_FEAT_LOWSPEED;
+
+		if (wPortChange)
+			dev_dbg(uhci_dev(uhci), "port %d portsc %04x\n",
+					wIndex, status);
+
+		*(__u16 *)buf = cpu_to_le16(wPortStatus);
+		*(__u16 *)(buf + 2) = cpu_to_le16(wPortChange);
+		OK(4);
+	case SetHubFeature:		/* We don't implement these */
 	case ClearHubFeature:
 		switch (wValue) {
 		case C_HUB_OVER_CURRENT:
-			OK(0);	/* hub power over current */
+		case C_HUB_LOCAL_POWER:
+			OK(0);
 		default:
 			goto err;
 		}
@@ -120,17 +150,14 @@ static int uhci_hub_control(struct usb_h
 		case USB_PORT_FEAT_RESET:
 			SET_RH_PORTSTAT(USBPORTSC_PR);
 			mdelay(50);	/* USB v1.1 7.1.7.3 */
-			c_p_r[wIndex - 1] = 1;
 			CLR_RH_PORTSTAT(USBPORTSC_PR);
 			udelay(10);
 			SET_RH_PORTSTAT(USBPORTSC_PE);
 			mdelay(10);
-			SET_RH_PORTSTAT(0xa);
+			CLR_RH_PORTSTAT(USBPORTSC_PEC|USBPORTSC_CSC);
 			OK(0);
 		case USB_PORT_FEAT_POWER:
-			OK(0); /* port power ** */
-		case USB_PORT_FEAT_ENABLE:
-			SET_RH_PORTSTAT(USBPORTSC_PE);
+			/* UHCI has no power switching */
 			OK(0);
 		default:
 			goto err;
@@ -145,31 +172,32 @@ static int uhci_hub_control(struct usb_h
 			CLR_RH_PORTSTAT(USBPORTSC_PE);
 			OK(0);
 		case USB_PORT_FEAT_C_ENABLE:
-			SET_RH_PORTSTAT(USBPORTSC_PEC);
+			CLR_RH_PORTSTAT(USBPORTSC_PEC);
 			OK(0);
 		case USB_PORT_FEAT_SUSPEND:
 			CLR_RH_PORTSTAT(USBPORTSC_SUSP);
 			OK(0);
 		case USB_PORT_FEAT_C_SUSPEND:
-			/*** WR_RH_PORTSTAT(RH_PS_PSSC); */
+			/* this driver won't report these */
 			OK(0);
 		case USB_PORT_FEAT_POWER:
-			OK(0);	/* port power */
+			/* UHCI has no power switching */
+			goto err;
 		case USB_PORT_FEAT_C_CONNECTION:
-			SET_RH_PORTSTAT(USBPORTSC_CSC);
+			CLR_RH_PORTSTAT(USBPORTSC_CSC);
 			OK(0);
 		case USB_PORT_FEAT_C_OVER_CURRENT:
-			OK(0);	/* port power over current */
+			CLR_RH_PORTSTAT(USBPORTSC_OCC);
+			OK(0);
 		case USB_PORT_FEAT_C_RESET:
-			c_p_r[wIndex - 1] = 0;
+			/* this driver won't report these */
 			OK(0);
 		default:
 			goto err;
 		}
 		break;
 	case GetHubDescriptor:
-		len = min_t(unsigned int, wLength,
-			  min_t(unsigned int, sizeof(root_hub_hub_des), wLength));
+		len = min_t(unsigned int, sizeof(root_hub_hub_des), wLength);
 		memcpy(buf, root_hub_hub_des, len);
 		if (len > 2)
 			buf[2] = uhci->rh_numports;
@@ -181,4 +209,3 @@ err:
 
 	return retval;
 }
-
--- diff/drivers/usb/input/hid-core.c	2004-02-18 08:54:12.000000000 +0000
+++ source/drivers/usb/input/hid-core.c	2004-02-23 13:56:46.000000000 +0000
@@ -224,6 +224,9 @@ static int hid_add_field(struct hid_pars
 	offset = report->size;
 	report->size += parser->global.report_size * parser->global.report_count;
 
+	if (usages < parser->global.report_count)
+		usages = parser->global.report_count;
+
 	if (usages == 0)
 		return 0; /* ignore padding fields */
 
@@ -235,9 +238,13 @@ static int hid_add_field(struct hid_pars
 	field->application = hid_lookup_collection(parser, HID_COLLECTION_APPLICATION);
 
 	for (i = 0; i < usages; i++) {
-		field->usage[i].hid = parser->local.usage[i];
+		int j = i;
+		/* Duplicate the last usage we parsed if we have excess values */
+		if (i >= parser->local.usage_index)
+			j = parser->local.usage_index - 1;
+		field->usage[i].hid = parser->local.usage[j];
 		field->usage[i].collection_index =
-			parser->local.collection_index[i];
+			parser->local.collection_index[j];
 	}
 
 	field->maxusage = usages;
@@ -1317,7 +1324,6 @@ void hid_init_reports(struct hid_device 
 #define USB_VENDOR_ID_KBGEAR            0x084e
 #define USB_DEVICE_ID_KBGEAR_JAMSTUDIO  0x1001
 
-
 #define USB_VENDOR_ID_AIPTEK		0x08ca
 #define USB_DEVICE_ID_AIPTEK_6000	0x0020
 
@@ -1356,17 +1362,40 @@ void hid_init_reports(struct hid_device 
 #define USB_VENDOR_ID_A4TECH		0x09DA
 #define USB_DEVICE_ID_A4TECH_WCP32PU	0x0006
 
+#define USB_VENDOR_ID_CYPRESS		0x04b4
+#define USB_DEVICE_ID_CYPRESS_MOUSE	0x0001
+
 #define USB_VENDOR_ID_BERKSHIRE		0x0c98
 #define USB_DEVICE_ID_BERKSHIRE_PCWD	0x1140
 
 #define USB_VENDOR_ID_ALPS		0x0433
 #define USB_DEVICE_ID_IBM_GAMEPAD	0x1101
 
+#define USB_VENDOR_ID_SAITEK		0x06a3
+#define USB_DEVICE_ID_SAITEK_RUMBLEPAD	0xff17
+
 struct hid_blacklist {
 	__u16 idVendor;
 	__u16 idProduct;
 	unsigned quirks;
 } hid_blacklist[] = {
+
+	{ USB_VENDOR_ID_AIPTEK, USB_DEVICE_ID_AIPTEK_6000, HID_QUIRK_IGNORE },
+	{ USB_VENDOR_ID_BERKSHIRE, USB_DEVICE_ID_BERKSHIRE_PCWD, HID_QUIRK_IGNORE },
+	{ USB_VENDOR_ID_ESSENTIAL_REALITY, USB_DEVICE_ID_ESSENTIAL_REALITY_P5, HID_QUIRK_IGNORE },
+	{ USB_VENDOR_ID_KBGEAR, USB_DEVICE_ID_KBGEAR_JAMSTUDIO, HID_QUIRK_IGNORE },
+	{ USB_VENDOR_ID_GRIFFIN, USB_DEVICE_ID_POWERMATE, HID_QUIRK_IGNORE },
+	{ USB_VENDOR_ID_GRIFFIN, USB_DEVICE_ID_SOUNDKNOB, HID_QUIRK_IGNORE },
+	{ USB_VENDOR_ID_MGE, USB_DEVICE_ID_MGE_UPS, HID_QUIRK_IGNORE },
+	{ USB_VENDOR_ID_MGE, USB_DEVICE_ID_MGE_UPS1, HID_QUIRK_IGNORE },
+
+	{ USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100, HID_QUIRK_IGNORE },
+	{ USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100 + 100, HID_QUIRK_IGNORE },
+	{ USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100 + 200, HID_QUIRK_IGNORE },
+	{ USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100 + 300, HID_QUIRK_IGNORE },
+	{ USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100 + 400, HID_QUIRK_IGNORE },
+	{ USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100 + 500, HID_QUIRK_IGNORE },
+
 	{ USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_PENPARTNER, HID_QUIRK_IGNORE },
 	{ USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_GRAPHIRE, HID_QUIRK_IGNORE },
 	{ USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_GRAPHIRE + 1, HID_QUIRK_IGNORE },
@@ -1388,32 +1417,24 @@ struct hid_blacklist {
 	{ USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS2 + 2, HID_QUIRK_IGNORE },
 	{ USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS2 + 3, HID_QUIRK_IGNORE },
 	{ USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS2 + 4, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_KBGEAR, USB_DEVICE_ID_KBGEAR_JAMSTUDIO, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_AIPTEK, USB_DEVICE_ID_AIPTEK_6000, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_GRIFFIN, USB_DEVICE_ID_POWERMATE, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_GRIFFIN, USB_DEVICE_ID_SOUNDKNOB, HID_QUIRK_IGNORE },
+
 	{ USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_UC100KM, HID_QUIRK_NOGET },
 	{ USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_CS124U, HID_QUIRK_NOGET },
 	{ USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_2PORTKVM, HID_QUIRK_NOGET },
 	{ USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_4PORTKVM, HID_QUIRK_NOGET },
 	{ USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_4PORTKVMC, HID_QUIRK_NOGET },
-	{ USB_VENDOR_ID_MGE, USB_DEVICE_ID_MGE_UPS, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_MGE, USB_DEVICE_ID_MGE_UPS1, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_TOPMAX, USB_DEVICE_ID_TOPMAX_COBRAPAD, HID_QUIRK_BADPAD },
-	{ USB_VENDOR_ID_HAPP, USB_DEVICE_ID_UGCI_DRIVING, HID_QUIRK_BADPAD|HID_QUIRK_MULTI_INPUT },
-	{ USB_VENDOR_ID_HAPP, USB_DEVICE_ID_UGCI_FLYING, HID_QUIRK_BADPAD|HID_QUIRK_MULTI_INPUT },
-	{ USB_VENDOR_ID_HAPP, USB_DEVICE_ID_UGCI_FIGHTING, HID_QUIRK_BADPAD|HID_QUIRK_MULTI_INPUT },
-	{ USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100 + 100, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100 + 200, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100 + 300, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100 + 400, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100 + 500, HID_QUIRK_IGNORE },
 	{ USB_VENDOR_ID_TANGTOP, USB_DEVICE_ID_TANGTOP_USBPS2, HID_QUIRK_NOGET },
-	{ USB_VENDOR_ID_ESSENTIAL_REALITY, USB_DEVICE_ID_ESSENTIAL_REALITY_P5, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_A4TECH, USB_DEVICE_ID_A4TECH_WCP32PU, HID_QUIRK_2WHEEL_MOUSE_HACK },
-	{ USB_VENDOR_ID_BERKSHIRE, USB_DEVICE_ID_BERKSHIRE_PCWD, HID_QUIRK_IGNORE },
+
+	{ USB_VENDOR_ID_A4TECH, USB_DEVICE_ID_A4TECH_WCP32PU, HID_QUIRK_2WHEEL_MOUSE_HACK_BACK },
+	{ USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_MOUSE, HID_QUIRK_2WHEEL_MOUSE_HACK_EXTRA },
+
 	{ USB_VENDOR_ID_ALPS, USB_DEVICE_ID_IBM_GAMEPAD, HID_QUIRK_BADPAD },
+	{ USB_VENDOR_ID_HAPP, USB_DEVICE_ID_UGCI_DRIVING, HID_QUIRK_BADPAD | HID_QUIRK_MULTI_INPUT },
+	{ USB_VENDOR_ID_HAPP, USB_DEVICE_ID_UGCI_FLYING, HID_QUIRK_BADPAD | HID_QUIRK_MULTI_INPUT },
+	{ USB_VENDOR_ID_HAPP, USB_DEVICE_ID_UGCI_FIGHTING, HID_QUIRK_BADPAD | HID_QUIRK_MULTI_INPUT },
+	{ USB_VENDOR_ID_SAITEK, USB_DEVICE_ID_SAITEK_RUMBLEPAD, HID_QUIRK_BADPAD },
+	{ USB_VENDOR_ID_TOPMAX, USB_DEVICE_ID_TOPMAX_COBRAPAD, HID_QUIRK_BADPAD },
+
 	{ 0, 0 }
 };
 
--- diff/drivers/usb/input/hid-input.c	2004-02-09 10:36:11.000000000 +0000
+++ source/drivers/usb/input/hid-input.c	2004-02-23 13:56:46.000000000 +0000
@@ -377,7 +377,8 @@ static void hidinput_configure_usage(str
 
 	set_bit(usage->type, input->evbit);
 	if ((usage->type == EV_REL)
-			&& (device->quirks & HID_QUIRK_2WHEEL_MOUSE_HACK)
+			&& (device->quirks & (HID_QUIRK_2WHEEL_MOUSE_HACK_BACK
+				| HID_QUIRK_2WHEEL_MOUSE_HACK_EXTRA))
 			&& (usage->code == REL_WHEEL)) {
 		set_bit(REL_HWHEEL, bit);
 	}
@@ -431,21 +432,22 @@ void hidinput_hid_event(struct hid_devic
 
 	input_regs(input, regs);
 
-	if ((hid->quirks & HID_QUIRK_2WHEEL_MOUSE_HACK)
-			&& (usage->code == BTN_BACK)) {
+	if (((hid->quirks & HID_QUIRK_2WHEEL_MOUSE_HACK_EXTRA) && (usage->code == BTN_EXTRA))
+		|| ((hid->quirks & HID_QUIRK_2WHEEL_MOUSE_HACK_BACK) && (usage->code == BTN_BACK))) {
 		if (value)
 			hid->quirks |= HID_QUIRK_2WHEEL_MOUSE_HACK_ON;
 		else
 			hid->quirks &= ~HID_QUIRK_2WHEEL_MOUSE_HACK_ON;
 		return;
 	}
+
 	if ((hid->quirks & HID_QUIRK_2WHEEL_MOUSE_HACK_ON)
 			&& (usage->code == REL_WHEEL)) {
 		input_event(input, usage->type, REL_HWHEEL, value);
 		return;
 	}
 
-	if (usage->hat_min != usage->hat_max) {
+	if (usage->hat_min != usage->hat_max ) { /* FIXME: hat_max can be 0 and hat_min 1 */
 		value = (value - usage->hat_min) * 8 / (usage->hat_max - usage->hat_min + 1) + 1;
 		if (value < 0 || value > 8) value = 0;
 		input_event(input, usage->type, usage->code    , hid_hat_to_axis[value].x);
@@ -484,7 +486,7 @@ void hidinput_hid_event(struct hid_devic
 		return;
 	}
 
-	if((usage->type == EV_KEY) && (usage->code == 0)) /* Key 0 is "unassigned", not KEY_UKNOWN */
+	if((usage->type == EV_KEY) && (usage->code == 0)) /* Key 0 is "unassigned", not KEY_UNKNOWN */
 		return;
 
 	input_event(input, usage->type, usage->code, value);
--- diff/drivers/usb/input/hid.h	2004-02-09 10:36:11.000000000 +0000
+++ source/drivers/usb/input/hid.h	2004-02-23 13:56:46.000000000 +0000
@@ -201,15 +201,16 @@ struct hid_item {
  * HID device quirks.
  */
 
-#define HID_QUIRK_INVERT		0x001
-#define HID_QUIRK_NOTOUCH		0x002
-#define HID_QUIRK_IGNORE		0x004
-#define HID_QUIRK_NOGET			0x008
-#define HID_QUIRK_HIDDEV		0x010
-#define HID_QUIRK_BADPAD		0x020
-#define HID_QUIRK_MULTI_INPUT		0x040
-#define HID_QUIRK_2WHEEL_MOUSE_HACK	0x080
-#define HID_QUIRK_2WHEEL_MOUSE_HACK_ON	0x100
+#define HID_QUIRK_INVERT			0x001
+#define HID_QUIRK_NOTOUCH			0x002
+#define HID_QUIRK_IGNORE			0x004
+#define HID_QUIRK_NOGET				0x008
+#define HID_QUIRK_HIDDEV			0x010
+#define HID_QUIRK_BADPAD			0x020
+#define HID_QUIRK_MULTI_INPUT			0x040
+#define HID_QUIRK_2WHEEL_MOUSE_HACK_BACK	0x080
+#define HID_QUIRK_2WHEEL_MOUSE_HACK_EXTRA	0x100
+#define HID_QUIRK_2WHEEL_MOUSE_HACK_ON		0x200
 
 /*
  * This is the global environment of the parser. This information is
--- diff/drivers/usb/input/hiddev.c	2004-02-09 10:36:11.000000000 +0000
+++ source/drivers/usb/input/hiddev.c	2004-02-23 13:56:46.000000000 +0000
@@ -403,7 +403,8 @@ static int hiddev_ioctl(struct inode *in
 	struct hiddev_collection_info cinfo;
 	struct hiddev_report_info rinfo;
 	struct hiddev_field_info finfo;
-	struct hiddev_usage_ref uref;
+	struct hiddev_usage_ref_multi uref_multi;
+	struct hiddev_usage_ref *uref = &uref_multi.uref;
 	struct hiddev_devinfo dinfo;
 	struct hid_report *report;
 	struct hid_field *field;
@@ -575,68 +576,98 @@ static int hiddev_ioctl(struct inode *in
 		return 0;
 
 	case HIDIOCGUCODE:
-		if (copy_from_user(&uref, (void *) arg, sizeof(uref)))
+		if (copy_from_user(uref, (void *) arg, sizeof(*uref)))
 			return -EFAULT;
 
-		rinfo.report_type = uref.report_type;
-		rinfo.report_id = uref.report_id;
+		rinfo.report_type = uref->report_type;
+		rinfo.report_id = uref->report_id;
 		if ((report = hiddev_lookup_report(hid, &rinfo)) == NULL)
 			return -EINVAL;
 
-		if (uref.field_index >= report->maxfield)
+		if (uref->field_index >= report->maxfield)
 			return -EINVAL;
 
-		field = report->field[uref.field_index];
-		if (uref.usage_index >= field->maxusage)
+		field = report->field[uref->field_index];
+		if (uref->usage_index >= field->maxusage)
 			return -EINVAL;
 
-		uref.usage_code = field->usage[uref.usage_index].hid;
+		uref->usage_code = field->usage[uref->usage_index].hid;
 
-		if (copy_to_user((void *) arg, &uref, sizeof(uref)))
+		if (copy_to_user((void *) arg, uref, sizeof(*uref)))
 			return -EFAULT;
 
 		return 0;
 
 	case HIDIOCGUSAGE:
 	case HIDIOCSUSAGE:
+	case HIDIOCGUSAGES:
+	case HIDIOCSUSAGES:
 	case HIDIOCGCOLLECTIONINDEX:
-		if (copy_from_user(&uref, (void *) arg, sizeof(uref)))
-			return -EFAULT;
+		if (cmd == HIDIOCGUSAGES || cmd == HIDIOCSUSAGES) {
+			if (copy_from_user(&uref_multi, (void *) arg, 
+					   sizeof(uref_multi)))
+				return -EFAULT;
+		} else {
+			if (copy_from_user(uref, (void *) arg, sizeof(*uref)))
+				return -EFAULT;
+		}
 
-		if (cmd != HIDIOCGUSAGE && uref.report_type == HID_REPORT_TYPE_INPUT)
-				return -EINVAL;
+		if (cmd != HIDIOCGUSAGE && 
+		    cmd != HIDIOCGUSAGES &&
+		    uref->report_type == HID_REPORT_TYPE_INPUT)
+			return -EINVAL;
 
-		if (uref.report_id == HID_REPORT_ID_UNKNOWN) {
-			field = hiddev_lookup_usage(hid, &uref);
+		if (uref->report_id == HID_REPORT_ID_UNKNOWN) {
+			field = hiddev_lookup_usage(hid, uref);
 			if (field == NULL)
 				return -EINVAL;
 		} else {
-			rinfo.report_type = uref.report_type;
-			rinfo.report_id = uref.report_id;
+			rinfo.report_type = uref->report_type;
+			rinfo.report_id = uref->report_id;
 			if ((report = hiddev_lookup_report(hid, &rinfo)) == NULL)
 				return -EINVAL;
 
-			if (uref.field_index >= report->maxfield)
+			if (uref->field_index >= report->maxfield)
 				return -EINVAL;
 
-			field = report->field[uref.field_index];
-			if (uref.usage_index >= field->maxusage)
+			field = report->field[uref->field_index];
+			if (uref->usage_index >= field->maxusage)
 				return -EINVAL;
+
+			if (cmd == HIDIOCGUSAGES || cmd == HIDIOCSUSAGES) {
+				if (uref_multi.num_values >= HID_MAX_USAGES || 
+				    uref->usage_index >= field->maxusage || 
+				   (uref->usage_index + uref_multi.num_values) >= field->maxusage)
+					return -EINVAL;
+			}
 		}
 
 		switch (cmd) {
 			case HIDIOCGUSAGE:
-				uref.value = field->value[uref.usage_index];
-				if (copy_to_user((void *) arg, &uref, sizeof(uref)))
+				uref->value = field->value[uref->usage_index];
+				if (copy_to_user((void *) arg, uref, sizeof(*uref)))
 					return -EFAULT;
 				return 0;
 
 			case HIDIOCSUSAGE:
-				field->value[uref.usage_index] = uref.value;
+				field->value[uref->usage_index] = uref->value;
 				return 0;
 
 			case HIDIOCGCOLLECTIONINDEX:
-				return field->usage[uref.usage_index].collection_index;
+				return field->usage[uref->usage_index].collection_index;
+			case HIDIOCGUSAGES:
+				for (i = 0; i < uref_multi.num_values; i++)
+					uref_multi.values[i] = 
+					    field->value[uref->usage_index + i];
+				if (copy_to_user((void *) arg, &uref_multi, 
+						 sizeof(uref_multi)))
+					return -EFAULT;
+				return 0;
+			case HIDIOCSUSAGES:
+				for (i = 0; i < uref_multi.num_values; i++)
+					field->value[uref->usage_index + i] = 
+				  	    uref_multi.values[i];
+				return 0;
 		}
 
 		return 0;
--- diff/drivers/usb/input/wacom.c	2004-02-09 10:36:11.000000000 +0000
+++ source/drivers/usb/input/wacom.c	2004-02-23 13:56:46.000000000 +0000
@@ -1,7 +1,7 @@
 /*
  *  USB Wacom Graphire and Wacom Intuos tablet support
  *
- *  Copyright (c) 2000-2002 Vojtech Pavlik	<vojtech@ucw.cz>
+ *  Copyright (c) 2000-2004 Vojtech Pavlik	<vojtech@ucw.cz>
  *  Copyright (c) 2000 Andreas Bach Aaen	<abach@stofanet.dk>
  *  Copyright (c) 2000 Clifford Wolf		<clifford@clifford.at>
  *  Copyright (c) 2000 Sam Mosel		<sam.mosel@computer.org>
@@ -9,6 +9,7 @@
  *  Copyright (c) 2000 Daniel Egger		<egger@suse.de>
  *  Copyright (c) 2001 Frederic Lepied		<flepied@mandrakesoft.com>
  *  Copyright (c) 2002 Ping Cheng		<pingc@wacom.com>
+ *  Copyright (c) 2004 Panagiotis Issaris	<panagiotis.issaris@mech.kuleuven.ac.be>
  *
  *  ChangeLog:
  *      v0.1 (vp)  - Initial release
@@ -48,6 +49,7 @@
  *	v1.30 (vp) - Merge 2.4 and 2.5 drivers
  *		   - Since 2.5 now has input_sync(), remove MSC_SERIAL abuse
  *		   - Cleanups here and there
+ *    v1.30.1 (pi) - Added Graphire3 support
  */
 
 /*
--- diff/drivers/usb/media/stv680.c	2003-09-17 12:28:10.000000000 +0100
+++ source/drivers/usb/media/stv680.c	2004-02-23 13:56:46.000000000 +0000
@@ -490,10 +490,9 @@ exit:
 	stv680->hue = 32767;
 	stv680->palette = STV_VIDEO_PALETTE;
 	stv680->depth = 24;	/* rgb24 bits */
-	swapRGB = 0;
 	if ((swapRGB_on == 0) && (swapRGB == 0))
 		PDEBUG (1, "STV(i): swapRGB is (auto) OFF");
-	else if ((swapRGB_on == 1) && (swapRGB == 1))
+	else if ((swapRGB_on == 0) && (swapRGB == 1))
 		PDEBUG (1, "STV(i): swapRGB is (auto) ON");
 	else if (swapRGB_on == 1)
 		PDEBUG (1, "STV(i): swapRGB is (forced) ON");
@@ -657,7 +656,7 @@ static void stv680_video_irq (struct urb
 	/* Resubmit urb for new data */
 	urb->status = 0;
 	urb->dev = stv680->udev;
-	if (usb_submit_urb (urb, GFP_KERNEL))
+	if (usb_submit_urb (urb, GFP_ATOMIC))
 		PDEBUG (0, "STV(e): urb burned down in video irq");
 	return;
 }				/*  _video_irq  */
@@ -1252,13 +1251,10 @@ static int stv680_do_ioctl (struct inode
 			return -EINVAL;
 		}
 	case VIDIOCSFBUF:
-		return -EINVAL;
 	case VIDIOCGTUNER:
 	case VIDIOCSTUNER:
-		return -EINVAL;
 	case VIDIOCGFREQ:
 	case VIDIOCSFREQ:
-		return -EINVAL;
 	case VIDIOCGAUDIO:
 	case VIDIOCSAUDIO:
 		return -EINVAL;
@@ -1434,7 +1430,7 @@ static int stv680_probe (struct usb_inte
 	if (video_register_device (stv680->vdev, VFL_TYPE_GRABBER, video_nr) == -1) {
 		PDEBUG (0, "STV(e): video_register_device failed");
 		retval = -EIO;
-		goto error;
+		goto error_vdev;
 	}
 	PDEBUG (0, "STV(i): registered new video device: video%d", stv680->vdev->minor);
 
@@ -1442,6 +1438,8 @@ static int stv680_probe (struct usb_inte
 	stv680_create_sysfs_files(stv680->vdev);
 	return 0;
 
+error_vdev:
+	video_device_release(stv680->vdev);
 error:
 	kfree(stv680);
 	return retval;
@@ -1466,9 +1464,7 @@ static inline void usb_stv680_remove_dis
 			kfree (stv680->sbuf[i].data);
 		}
 	for (i = 0; i < STV680_NUMSCRATCH; i++)
-		if (stv680->scratch[i].data) {
-			kfree (stv680->scratch[i].data);
-		}
+		kfree (stv680->scratch[i].data);
 	PDEBUG (0, "STV(i): %s disconnected", stv680->camera_name);
 
 	/* Free the memory */
--- diff/drivers/usb/media/w9968cf.c	2004-02-09 10:36:11.000000000 +0000
+++ source/drivers/usb/media/w9968cf.c	2004-02-23 13:56:46.000000000 +0000
@@ -820,7 +820,7 @@ static void w9968cf_urb_complete(struct 
 			(*f)->length = cam->frame_tmp.length;
 			memcpy((*f)->buffer, cam->frame_tmp.buffer,
 			       (*f)->length);
-			DBG(6, "Switched from temp. frame to frame #%d", 
+			DBG(6, "Switched from temp. frame to frame #%zd", 
 			    (*f) - &cam->frame[0])
 		}
 	}
@@ -858,7 +858,7 @@ static void w9968cf_urb_complete(struct 
 
 		} else if ((*f)->status == F_GRABBING) { /* end of frame */
 
-			DBG(6, "Frame #%d successfully grabbed.",
+			DBG(6, "Frame #%zd successfully grabbed.",
 			    ((*f)==&cam->frame_tmp ? -1 : (*f)-&cam->frame[0]))
 
 			if (cam->vpp_flag & VPP_DECOMPRESSION) {
@@ -2075,7 +2075,7 @@ w9968cf_pop_frame(struct w9968cf_device*
 
 	spin_unlock(&cam->flist_lock);
 
-	DBG(6,"Popped frame #%d from the list.",*framep-&cam->frame[0])
+	DBG(6,"Popped frame #%zd from the list.",*framep-&cam->frame[0])
 }
 
 
@@ -2830,7 +2830,7 @@ w9968cf_read(struct file* filp, char* bu
 
 	fr->status = F_UNUSED;
 
-	DBG(5, "%d bytes read.", count)
+	DBG(5, "%zd bytes read.", count)
 
 	up(&cam->fileop_sem);
 	return count;
@@ -3506,7 +3506,7 @@ w9968cf_usb_probe(struct usb_interface* 
 	          kmalloc(sizeof(struct w9968cf_device), GFP_KERNEL);
 
 	if (!cam) {
-		DBG(1, "Couldn't allocate %d bytes of kernel memory.",
+		DBG(1, "Couldn't allocate %zd bytes of kernel memory.",
 		    sizeof(struct w9968cf_device))
 		err = -ENOMEM;
 		goto fail;
--- diff/drivers/usb/misc/speedtch.c	2003-10-09 09:47:34.000000000 +0100
+++ source/drivers/usb/misc/speedtch.c	2004-02-23 13:56:46.000000000 +0000
@@ -1161,7 +1161,7 @@ static int udsl_usb_probe (struct usb_in
 	buf += i;
 	length -= i;
 
-	i = snprintf (buf, length, " (");
+	i = scnprintf (buf, length, " (");
 	buf += i;
 	length -= i;
 
--- diff/drivers/usb/misc/usbtest.c	2004-02-18 08:54:12.000000000 +0000
+++ source/drivers/usb/misc/usbtest.c	2004-02-23 13:56:46.000000000 +0000
@@ -724,7 +724,7 @@ struct ctrl_ctx {
 	int			last;
 };
 
-#define NUM_SUBCASES	13		/* how many test subcases here? */
+#define NUM_SUBCASES	15		/* how many test subcases here? */
 
 struct subcase {
 	struct usb_ctrlrequest	setup;
@@ -952,8 +952,25 @@ test_ctrl_queue (struct usbtest_dev *dev
 			req.wValue = cpu_to_le16 (USB_DT_STRING << 8);
 			// string == 0, for language IDs
 			len = sizeof (struct usb_interface_descriptor);
+			// may succeed when > 4 languages
 			expected = EREMOTEIO;	// or EPIPE, if no strings
 			break;
+		case 13:	// short read, resembling case 10
+			req.wValue = cpu_to_le16 ((USB_DT_CONFIG << 8) | 0);
+			// last data packet "should" be DATA1, not DATA0
+			len = 1024 - udev->epmaxpacketin [0];
+			expected = -EREMOTEIO;
+			break;
+		case 14:	// short read; try to fill the last packet
+			req.wValue = cpu_to_le16 ((USB_DT_DEVICE << 8) | 0);
+			// device descriptor size == 18 bytes 
+			len = udev->epmaxpacketin [0];
+			switch (len) {
+			case 8:		len = 24; break;
+			case 16:	len = 32; break;
+			}
+			expected = -EREMOTEIO;
+			break;
 		default:
 			err ("bogus number of ctrl queue testcases!");
 			context.status = -EINVAL;
--- diff/drivers/usb/misc/uss720.c	2004-02-18 08:54:12.000000000 +0000
+++ source/drivers/usb/misc/uss720.c	2004-02-23 13:56:46.000000000 +0000
@@ -592,7 +592,6 @@ static int uss720_probe(struct usb_inter
 		goto probe_abort_port;
 	}
 #endif
-	parport_proc_register(pp);
 	parport_announce_port(pp);
 
 	usb_set_intfdata (intf, pp);
@@ -600,7 +599,7 @@ static int uss720_probe(struct usb_inter
 
 #if 0
 probe_abort_port:
-	parport_unregister_port(pp);
+	parport_put_port(pp);
 #endif
 probe_abort:
 	kfree(priv);
@@ -615,12 +614,12 @@ static void uss720_disconnect(struct usb
 	usb_set_intfdata (intf, NULL);
 	if (pp) {
 		priv = pp->private_data;
+		parport_remove_port(pp);
 #if 0
 		usb_release_irq(usbdev, priv->irqhandle, priv->irqpipe);
 #endif
 		priv->usbdev = NULL;
-		parport_proc_unregister(pp);
-		parport_unregister_port(pp);
+		parport_put_port(pp);
 		kfree(priv);
 	}
 }
--- diff/drivers/usb/net/catc.c	2003-08-26 10:00:54.000000000 +0100
+++ source/drivers/usb/net/catc.c	2004-02-23 13:56:46.000000000 +0000
@@ -838,7 +838,7 @@ static int catc_probe(struct usb_interfa
 			usb_free_urb(catc->rx_urb);
 		if (catc->irq_urb)
 			usb_free_urb(catc->irq_urb);
-		kfree(netdev);
+		free_netdev(netdev);
 		kfree(catc);
 		return -ENOMEM;
 	}
@@ -943,7 +943,7 @@ static int catc_probe(struct usb_interfa
 		usb_free_urb(catc->tx_urb);
 		usb_free_urb(catc->rx_urb);
 		usb_free_urb(catc->irq_urb);
-		kfree(netdev);
+		free_netdev(netdev);
 		kfree(catc);
 		return -EIO;
 	}
--- diff/drivers/usb/net/kaweth.c	2003-11-25 15:24:58.000000000 +0000
+++ source/drivers/usb/net/kaweth.c	2004-02-23 13:56:46.000000000 +0000
@@ -1150,7 +1150,7 @@ err_tx_and_rx:
 err_only_tx:
 	usb_free_urb(kaweth->tx_urb);
 err_no_urb:
-	kfree(netdev);
+	free_netdev(netdev);
 err_no_netdev:
 	kfree(kaweth);
 	return -EIO;
--- diff/drivers/usb/net/pegasus.c	2003-08-26 10:00:54.000000000 +0100
+++ source/drivers/usb/net/pegasus.c	2004-02-23 13:56:46.000000000 +0000
@@ -1283,7 +1283,7 @@ out4:
 	usb_set_intfdata(intf, NULL);
 	free_skb_pool(pegasus);
 out3:
-	kfree(net);
+	free_netdev(net);
 out2:
 	free_all_urbs(pegasus);
 out1:
--- diff/drivers/usb/net/rtl8150.c	2003-08-26 10:00:54.000000000 +0100
+++ source/drivers/usb/net/rtl8150.c	2004-02-23 13:56:46.000000000 +0000
@@ -852,7 +852,7 @@ out1:
 	free_all_urbs(dev);
 out:
 	kfree(dev->intr_buff);
-	kfree(netdev);
+	free_netdev(netdev);
 	kfree(dev);
 	return -EIO;
 }
--- diff/drivers/usb/net/usbnet.c	2004-02-18 08:54:12.000000000 +0000
+++ source/drivers/usb/net/usbnet.c	2004-02-23 13:56:46.000000000 +0000
@@ -2981,7 +2981,7 @@ static void usbnet_disconnect (struct us
 	if (dev->driver_info->unbind)
 		dev->driver_info->unbind (dev, intf);
 
-	kfree(dev->net);
+	free_netdev(dev->net);
 	kfree (dev);
 	usb_put_dev (xdev);
 }
@@ -3111,7 +3111,7 @@ out3:
 	if (info->unbind)
 		info->unbind (dev, udev);
 out2:
-	kfree(net);
+	free_netdev(net);
 out1:
 	kfree(dev);
 out:
--- diff/drivers/usb/serial/ftdi_sio.c	2004-02-09 10:36:11.000000000 +0000
+++ source/drivers/usb/serial/ftdi_sio.c	2004-02-23 13:56:46.000000000 +0000
@@ -17,6 +17,11 @@
  * See http://ftdi-usb-sio.sourceforge.net for upto date testing info
  *	and extra documentation
  *
+ * (09/Feb/2004) Ian Abbott
+ *      Changed full name of USB-UIRT device to avoid "/" character.
+ *      Added FTDI's alternate PID (0x6006) for FT232/245 devices.
+ *      Added PID for "ELV USB Module UO100" from Stefan Frings.
+ * 
  * (21/Oct/2003) Ian Abbott
  *      Renamed some VID/PID macros for Matrix Orbital and Perle Systems
  *      devices.  Removed Matrix Orbital and Perle Systems devices from the
@@ -282,6 +287,7 @@ static struct usb_device_id id_table_sio
 
 static struct usb_device_id id_table_8U232AM [] = {
 	{ USB_DEVICE_VER(FTDI_VID, FTDI_8U232AM_PID, 0, 0x3ff) },
+	{ USB_DEVICE_VER(FTDI_VID, FTDI_8U232AM_ALT_PID, 0, 0x3ff) },
 	{ USB_DEVICE_VER(FTDI_VID, FTDI_RELAIS_PID, 0, 0x3ff) },
 	{ USB_DEVICE_VER(FTDI_NF_RIC_VID, FTDI_NF_RIC_PID, 0, 0x3ff) },
 	{ USB_DEVICE_VER(FTDI_VID, FTDI_XF_632_PID, 0, 0x3ff) },
@@ -346,12 +352,14 @@ static struct usb_device_id id_table_8U2
 	{ USB_DEVICE_VER(FTDI_VID, PROTEGO_R2X0, 0, 0x3ff) },
 	{ USB_DEVICE_VER(FTDI_VID, PROTEGO_SPECIAL_3, 0, 0x3ff) },
 	{ USB_DEVICE_VER(FTDI_VID, PROTEGO_SPECIAL_4, 0, 0x3ff) },
+	{ USB_DEVICE_VER(FTDI_VID, FTDI_ELV_UO100_PID, 0, 0x3ff) },
 	{ }						/* Terminating entry */
 };
 
 
 static struct usb_device_id id_table_FT232BM [] = {
 	{ USB_DEVICE_VER(FTDI_VID, FTDI_8U232AM_PID, 0x400, 0xffff) },
+	{ USB_DEVICE_VER(FTDI_VID, FTDI_8U232AM_ALT_PID, 0x400, 0xffff) },
 	{ USB_DEVICE_VER(FTDI_VID, FTDI_RELAIS_PID, 0x400, 0xffff) },
 	{ USB_DEVICE_VER(FTDI_NF_RIC_VID, FTDI_NF_RIC_PID, 0x400, 0xffff) },
 	{ USB_DEVICE_VER(FTDI_VID, FTDI_XF_632_PID, 0x400, 0xffff) },
@@ -425,6 +433,7 @@ static struct usb_device_id id_table_FT2
 	{ USB_DEVICE_VER(FTDI_VID, PROTEGO_R2X0, 0x400, 0xffff) },
 	{ USB_DEVICE_VER(FTDI_VID, PROTEGO_SPECIAL_3, 0x400, 0xffff) },
 	{ USB_DEVICE_VER(FTDI_VID, PROTEGO_SPECIAL_4, 0x400, 0xffff) },
+	{ USB_DEVICE_VER(FTDI_VID, FTDI_ELV_UO100_PID, 0x400, 0xffff) },
 	{ }						/* Terminating entry */
 };
 
@@ -444,6 +453,7 @@ static struct usb_device_id id_table_HE_
 static struct usb_device_id id_table_combined [] = {
 	{ USB_DEVICE(FTDI_VID, FTDI_SIO_PID) },
 	{ USB_DEVICE(FTDI_VID, FTDI_8U232AM_PID) },
+	{ USB_DEVICE(FTDI_VID, FTDI_8U232AM_ALT_PID) },
 	{ USB_DEVICE(FTDI_VID, FTDI_RELAIS_PID) },
 	{ USB_DEVICE(FTDI_VID, FTDI_XF_632_PID) },
 	{ USB_DEVICE(FTDI_VID, FTDI_XF_634_PID) },
@@ -518,6 +528,7 @@ static struct usb_device_id id_table_com
 	{ USB_DEVICE(FTDI_VID, PROTEGO_R2X0) },
 	{ USB_DEVICE(FTDI_VID, PROTEGO_SPECIAL_3) },
 	{ USB_DEVICE(FTDI_VID, PROTEGO_SPECIAL_4) },
+	{ USB_DEVICE(FTDI_VID, FTDI_ELV_UO100_PID) },
 	{ }						/* Terminating entry */
 };
 
@@ -669,7 +680,7 @@ static struct usb_serial_device_type ftd
 
 static struct usb_serial_device_type ftdi_USB_UIRT_device = {
 	.owner =		THIS_MODULE,
-	.name =			"USB-UIRT Infrared Receiver/Transmitter",
+	.name =			"USB-UIRT Infrared Tranceiver",
 	.id_table =		id_table_USB_UIRT,
 	.num_interrupt_in =	0,
 	.num_bulk_in =		1,
--- diff/drivers/usb/serial/ftdi_sio.h	2004-02-09 10:36:11.000000000 +0000
+++ source/drivers/usb/serial/ftdi_sio.h	2004-02-23 13:56:46.000000000 +0000
@@ -25,6 +25,7 @@
 #define FTDI_VID	0x0403	/* Vendor Id */
 #define FTDI_SIO_PID	0x8372	/* Product Id SIO application of 8U100AX  */
 #define FTDI_8U232AM_PID 0x6001 /* Similar device to SIO above */
+#define FTDI_8U232AM_ALT_PID 0x6006 /* FTDI's alternate PID for above */
 #define FTDI_RELAIS_PID	0xFA10  /* Relais device from Rudolf Gugler */
 #define FTDI_NF_RIC_VID	0x0DCD	/* Vendor Id */
 #define FTDI_NF_RIC_PID	0x0001	/* Product Id */
@@ -132,6 +133,9 @@
 /* http://home.earthlink.net/~jrhees/USBUIRT/index.htm */
 #define FTDI_USB_UIRT_PID	0xF850	/* Product Id */
 
+/* ELV USB Module UO100 (PID sent by Stefan Frings) */
+#define FTDI_ELV_UO100_PID	0xFB58	/* Product Id */
+
 /*
  * Definitions for ID TECH (www.idt-net.com) devices
  */
--- diff/drivers/usb/storage/sddr09.c	2004-02-09 10:36:11.000000000 +0000
+++ source/drivers/usb/storage/sddr09.c	2004-02-23 13:56:46.000000000 +0000
@@ -27,6 +27,20 @@
  * 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
+/*
+ * Known vendor commands: 12 bytes, first byte is opcode
+ *
+ * E7: read scatter gather
+ * E8: read
+ * E9: write
+ * EA: erase
+ * EB: reset
+ * EC: read status
+ * ED: read ID
+ * EE: write CIS (?)
+ * EF: compute checksum (?)
+ */
+
 #include "transport.h"
 #include "protocol.h"
 #include "usb.h"
@@ -461,6 +475,7 @@ sddr09_read23(struct us_data *us, unsign
  * 
  * Always precisely one block is erased; bytes 2-5 and 10-11 are ignored.
  * The byte address being erased is 2*Eaddress.
+ * The CIS cannot be erased.
  */
 static int
 sddr09_erase(struct us_data *us, unsigned long Eaddress) {
@@ -487,6 +502,20 @@ sddr09_erase(struct us_data *us, unsigne
 }
 
 /*
+ * Write CIS Command: 12 bytes.
+ * byte 0: opcode: EE
+ * bytes 2-5: write address in shorts
+ * bytes 10-11: sector count
+ *
+ * This writes at the indicated address. Don't know how it differs
+ * from E9. Maybe it does not erase? However, it will also write to
+ * the CIS.
+ *
+ * When two such commands on the same page follow each other directly,
+ * the second one is not done.
+ */
+
+/*
  * Write Command: 12 bytes.
  * byte 0: opcode: E9
  * bytes 2-5: write address (big-endian, counting shorts, sector aligned).
@@ -1478,7 +1507,7 @@ int sddr09_transport(Scsi_Cmnd *srb, str
 				  "mode page 0x%x\n", modepage);
 
 			memcpy(ptr, mode_page_01, sizeof(mode_page_01));
-			((u16*)ptr)[0] = sizeof(mode_page_01) - 2;
+			((u16*)ptr)[0] = cpu_to_be16(sizeof(mode_page_01) - 2);
 			ptr[3] = (info->flags & SDDR09_WP) ? 0x80 : 0;
 			usb_stor_set_xfer_buf(ptr, sizeof(mode_page_01), srb);
 			return USB_STOR_TRANSPORT_GOOD;
--- diff/drivers/usb/storage/transport.c	2004-02-09 10:36:11.000000000 +0000
+++ source/drivers/usb/storage/transport.c	2004-02-23 13:56:46.000000000 +0000
@@ -552,6 +552,8 @@ void usb_stor_invoke_transport(Scsi_Cmnd
 		return;
 	}
 
+	srb->result = SAM_STAT_GOOD;
+
 	/* Determine if we need to auto-sense
 	 *
 	 * I normally don't use a flag like this, but it's almost impossible
@@ -561,23 +563,14 @@ void usb_stor_invoke_transport(Scsi_Cmnd
 
 	/*
 	 * If we're running the CB transport, which is incapable
-	 * of determining status on it's own, we need to auto-sense almost
-	 * every time.
+	 * of determining status on its own, we need to auto-sense
+	 * unless the operation involved a data-in transfer.  Devices
+	 * can signal data-in errors by stalling the bulk-in pipe.
 	 */
-	if (us->protocol == US_PR_CB || us->protocol == US_PR_DPCM_USB) {
+	if ((us->protocol == US_PR_CB || us->protocol == US_PR_DPCM_USB) &&
+			srb->sc_data_direction != SCSI_DATA_READ) {
 		US_DEBUGP("-- CB transport device requiring auto-sense\n");
 		need_auto_sense = 1;
-
-		/* There are some exceptions to this.  Notably, if this is
-		 * a UFI device and the command is REQUEST_SENSE or INQUIRY,
-		 * then it is impossible to truly determine status.
-		 */
-		if (us->subclass == US_SC_UFI &&
-		    ((srb->cmnd[0] == REQUEST_SENSE) ||
-		     (srb->cmnd[0] == INQUIRY))) {
-			US_DEBUGP("** no auto-sense for a special command\n");
-			need_auto_sense = 0;
-		}
 	}
 
 	/*
@@ -591,8 +584,8 @@ void usb_stor_invoke_transport(Scsi_Cmnd
 	}
 
 	/*
-	 * Also, if we have a short transfer on a command that can't have
-	 * a short transfer, we're going to do this.
+	 * A short transfer on a command where we don't expect it
+	 * is unusual, but it doesn't mean we need to auto-sense.
 	 */
 	if ((srb->resid > 0) &&
 	    !((srb->cmnd[0] == REQUEST_SENSE) ||
@@ -601,7 +594,6 @@ void usb_stor_invoke_transport(Scsi_Cmnd
 	      (srb->cmnd[0] == LOG_SENSE) ||
 	      (srb->cmnd[0] == MODE_SENSE_10))) {
 		US_DEBUGP("-- unexpectedly short transfer\n");
-		need_auto_sense = 1;
 	}
 
 	/* Now, if we need to do the auto-sense, let's do it */
@@ -614,6 +606,7 @@ void usb_stor_invoke_transport(Scsi_Cmnd
 		unsigned char old_cmd_len;
 		unsigned char old_cmnd[MAX_COMMAND_SIZE];
 		unsigned long old_serial_number;
+		int old_resid;
 
 		US_DEBUGP("Issuing auto-REQUEST_SENSE\n");
 
@@ -654,9 +647,12 @@ void usb_stor_invoke_transport(Scsi_Cmnd
 		srb->serial_number ^= 0x80000000;
 
 		/* issue the auto-sense command */
+		old_resid = srb->resid;
+		srb->resid = 0;
 		temp_result = us->transport(us->srb, us);
 
 		/* let's clean up right away */
+		srb->resid = old_resid;
 		srb->request_buffer = old_request_buffer;
 		srb->request_bufflen = old_request_bufflen;
 		srb->use_sg = old_sg;
@@ -698,26 +694,15 @@ void usb_stor_invoke_transport(Scsi_Cmnd
 		/* set the result so the higher layers expect this data */
 		srb->result = SAM_STAT_CHECK_CONDITION;
 
-		/* If things are really okay, then let's show that */
-		if ((srb->sense_buffer[2] & 0xf) == 0x0)
+		/* If things are really okay, then let's show that.  Zero
+		 * out the sense buffer so the higher layers won't realize
+		 * we did an unsolicited auto-sense. */
+		if (result == USB_STOR_TRANSPORT_GOOD &&
+				(srb->sense_buffer[2] & 0xf) == 0x0) {
 			srb->result = SAM_STAT_GOOD;
-	} else /* if (need_auto_sense) */
-		srb->result = SAM_STAT_GOOD;
-
-	/* Regardless of auto-sense, if we _know_ we have an error
-	 * condition, show that in the result code
-	 */
-	if (result == USB_STOR_TRANSPORT_FAILED)
-		srb->result = SAM_STAT_CHECK_CONDITION;
-
-	/* If we think we're good, then make sure the sense data shows it.
-	 * This is necessary because the auto-sense for some devices always
-	 * sets byte 0 == 0x70, even if there is no error
-	 */
-	if ((us->protocol == US_PR_CB || us->protocol == US_PR_DPCM_USB) && 
-	    (result == USB_STOR_TRANSPORT_GOOD) &&
-	    ((srb->sense_buffer[2] & 0xf) == 0x0))
-		srb->sense_buffer[0] = 0x0;
+			srb->sense_buffer[0] = 0x0;
+		}
+	}
 	return;
 
 	/* abort processing: the bulk-only transport requires a reset
@@ -792,6 +777,10 @@ int usb_stor_CBI_transport(Scsi_Cmnd *sr
 					srb->request_buffer, transfer_length,
 					srb->use_sg, &srb->resid);
 		US_DEBUGP("CBI data stage result is 0x%x\n", result);
+
+		/* if we stalled the data transfer it means command failed */
+		if (result == USB_STOR_XFER_STALLED)
+			return USB_STOR_TRANSPORT_FAILED;
 		if (result > USB_STOR_XFER_STALLED)
 			return USB_STOR_TRANSPORT_ERROR;
 	}
@@ -883,6 +872,10 @@ int usb_stor_CB_transport(Scsi_Cmnd *srb
 					srb->request_buffer, transfer_length,
 					srb->use_sg, &srb->resid);
 		US_DEBUGP("CB data stage result is 0x%x\n", result);
+
+		/* if we stalled the data transfer it means command failed */
+		if (result == USB_STOR_XFER_STALLED)
+			return USB_STOR_TRANSPORT_FAILED;
 		if (result > USB_STOR_XFER_STALLED)
 			return USB_STOR_TRANSPORT_ERROR;
 	}
@@ -929,6 +922,7 @@ int usb_stor_Bulk_transport(Scsi_Cmnd *s
 	unsigned int residue;
 	int result;
 	int fake_sense = 0;
+	unsigned int cswlen;
 
 	/* set up the command wrapper */
 	bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN);
@@ -985,7 +979,17 @@ int usb_stor_Bulk_transport(Scsi_Cmnd *s
 	/* get CSW for device status */
 	US_DEBUGP("Attempting to get CSW...\n");
 	result = usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe,
-				bcs, US_BULK_CS_WRAP_LEN, NULL);
+				bcs, US_BULK_CS_WRAP_LEN, &cswlen);
+
+	/* Some broken devices add unnecessary zero-length packets to the
+	 * end of their data transfers.  Such packets show up as 0-length
+	 * CSWs.  If we encounter such a thing, try to read the CSW again.
+	 */
+	if (result == USB_STOR_XFER_SHORT && cswlen == 0) {
+		US_DEBUGP("Received 0-length CSW; retrying...\n");
+		result = usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe,
+				bcs, US_BULK_CS_WRAP_LEN, &cswlen);
+	}
 
 	/* did the attempt to read the CSW fail? */
 	if (result == USB_STOR_XFER_STALLED) {
--- diff/drivers/usb/storage/unusual_devs.h	2004-02-18 08:54:12.000000000 +0000
+++ source/drivers/usb/storage/unusual_devs.h	2004-02-23 13:56:46.000000000 +0000
@@ -108,6 +108,15 @@ UNUSUAL_DEV(  0x0482, 0x0103, 0x0100, 0x
 		"Finecam S5",
 		US_SC_DEVICE, US_PR_DEVICE, NULL, US_FL_FIX_INQUIRY),
 
+/* Patch for Kyocera Finecam L3
+ * Submitted by Michael Krauth <michael.krauth@web.de>
+ */
+UNUSUAL_DEV(  0x0482, 0x0105, 0x0100, 0x0100,
+		"Kyocera",
+		"Finecam L3",
+		US_SC_SCSI, US_PR_BULK, NULL,
+		US_FL_FIX_INQUIRY),
+
 /* Reported by Paul Stewart <stewart@wetlogic.net>
  * This entry is needed because the device reports Sub=ff */
 UNUSUAL_DEV(  0x04a4, 0x0004, 0x0001, 0x0001,
@@ -132,7 +141,7 @@ UNUSUAL_DEV(  0x04b8, 0x0602, 0x0110, 0x
 UNUSUAL_DEV(  0x04cb, 0x0100, 0x0000, 0x2210,
 		"Fujifilm",
 		"FinePix 1400Zoom",
-		US_SC_DEVICE, US_PR_DEVICE, NULL, US_FL_FIX_INQUIRY),
+		US_SC_UFI, US_PR_DEVICE, NULL, US_FL_FIX_INQUIRY),
 
 /* Reported by Peter Wächtler <pwaechtler@loewe-komp.de>
  * The device needs the flags only.
@@ -171,7 +180,7 @@ UNUSUAL_DEV(  0x04e6, 0x0001, 0x0200, 0x
 UNUSUAL_DEV(  0x04e6, 0x0002, 0x0100, 0x0100, 
 		"Shuttle",
 		"eUSCSI Bridge",
-		US_SC_SCSI, US_PR_BULK, usb_stor_euscsi_init, 
+		US_SC_DEVICE, US_PR_DEVICE, usb_stor_euscsi_init, 
 		US_FL_SCM_MULT_TARG ), 
 
 #ifdef CONFIG_USB_STORAGE_SDDR09
@@ -285,6 +294,13 @@ UNUSUAL_DEV(  0x054c, 0x0032, 0x0000, 0x
 		"Memorystick MSC-U01N",
 		US_SC_DEVICE, US_PR_DEVICE, NULL,
 		US_FL_SINGLE_LUN ),
+
+/* Submitted by Michal Mlotek <mlotek@foobar.pl> */
+UNUSUAL_DEV(  0x054c, 0x0058, 0x0000, 0x9999,
+		"Sony",
+		"PEG N760c Memorystick",
+		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		US_FL_FIX_INQUIRY ),
 		
 UNUSUAL_DEV(  0x054c, 0x0069, 0x0000, 0x9999,
 		"Sony",
@@ -414,6 +430,28 @@ UNUSUAL_DEV(  0x066b, 0x0105, 0x0100, 0x
 		US_FL_SINGLE_LUN ),
 #endif
 
+/* Following three Minolta cameras reported by Martin Pool
+ * <mbp@sourcefrog.net>.  Originally discovered by Kedar Petankar,
+ * Matthew Geier, Mikael Lofj"ard, Marcel de Boer.
+ */
+UNUSUAL_DEV( 0x0686, 0x4006, 0x0001, 0x0001,
+		"Minolta",
+		"DiMAGE 7",
+		US_SC_SCSI, US_PR_DEVICE, NULL,
+		0 ),
+
+UNUSUAL_DEV( 0x0686, 0x400b, 0x0001, 0x0001,
+		"Minolta",
+		"DiMAGE 7i",
+		US_SC_SCSI, US_PR_DEVICE, NULL,
+		0 ),
+
+UNUSUAL_DEV( 0x0686, 0x400f, 0x0001, 0x0001,
+		"Minolta",
+		"DiMAGE 7Hi",
+		US_SC_SCSI, US_PR_DEVICE, NULL,
+		0 ),
+
 /* Submitted by Benny Sjostrand <benny@hostmobility.com> */
 UNUSUAL_DEV( 0x0686, 0x4011, 0x0001, 0x0001,
 		"Minolta",
@@ -426,28 +464,6 @@ UNUSUAL_DEV(  0x0686, 0x4017, 0x0001, 0x
                 "DIMAGE E223",
                 US_SC_SCSI, US_PR_DEVICE, NULL, 0 ),
 
-/* Following three Minolta cameras reported by Martin Pool
- * <mbp@sourcefrog.net>.  Originally discovered by Kedar Petankar,
- * Matthew Geier, Mikael Lofj"ard, Marcel de Boer.
- */
-UNUSUAL_DEV( 0x0686, 0x4006, 0x0001, 0x0001,
-             "Minolta",
-             "DiMAGE 7",
-             US_SC_SCSI, US_PR_DEVICE, NULL,
-             0 ),
-
-UNUSUAL_DEV( 0x0686, 0x400b, 0x0001, 0x0001,
-             "Minolta",
-             "DiMAGE 7i",
-             US_SC_SCSI, US_PR_DEVICE, NULL,
-             0 ),
-
-UNUSUAL_DEV( 0x0686, 0x400f, 0x0001, 0x0001,
-             "Minolta",
-             "DiMAGE 7Hi",
-             US_SC_SCSI, US_PR_DEVICE, NULL,
-             0 ),
-
 UNUSUAL_DEV(  0x0693, 0x0002, 0x0100, 0x0100, 
 		"Hagiwara",
 		"FlashGate SmartMedia",
@@ -607,7 +623,7 @@ UNUSUAL_DEV(  0x07c4, 0xa400, 0x0000, 0x
 UNUSUAL_DEV( 0x07cf, 0x1001, 0x1000, 0x9009,
 		"Casio",
 		"QV DigitalCamera",
-		US_SC_8070, US_PR_CB, NULL,
+		US_SC_DEVICE, US_PR_CB, NULL,
 		US_FL_FIX_INQUIRY ),
 
 /* Later Casio cameras apparently tell the truth */
@@ -633,15 +649,6 @@ UNUSUAL_DEV(  0x08ca, 0x2011, 0x0000, 0x
 		US_SC_DEVICE, US_PR_DEVICE, NULL,
 		US_FL_MODE_XLATE ),
 
-/*Medion 6047 Digital Camera
-Davide Andrian <_nessuno_@katamail.com>
-*/
-UNUSUAL_DEV( 0x08ca, 0x2011, 0x0001, 0x0001,
-		"3MegaCam",
-		"3MegaCam",
-		US_SC_DEVICE, US_PR_BULK, NULL,
-		US_FL_MODE_XLATE ),
-
 /* Trumpion Microelectronics MP3 player (felipe_alfaro@linuxmail.org) */
 UNUSUAL_DEV( 0x090a, 0x1200, 0x0000, 0x9999,
 		"Trumpion",
@@ -720,6 +727,17 @@ UNUSUAL_DEV(  0x0d96, 0x5200, 0x0001, 0x
 		"JD 5200 z3",
 		US_SC_DEVICE, US_PR_DEVICE, NULL, US_FL_FIX_INQUIRY),
 
+/* Reported by Lubomir Blaha <tritol@trilogic.cz>
+ * I _REALLY_ don't know what 3rd, 4th number and all defines mean, but this
+ * works for me. Can anybody correct these values? (I able to test corrected
+ * version.)
+ */
+UNUSUAL_DEV( 0x0dd8, 0x1060, 0x0000, 0xffff,
+		"Netac",
+		"USB-CF-Card",
+		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		US_FL_FIX_INQUIRY ),
+
 /* Submitted by Antoine Mairesse <antoine.mairesse@free.fr> */
 UNUSUAL_DEV( 0x0ed1, 0x6660, 0x0100, 0x0300,
 		"USB",
--- diff/drivers/video/amifb.c	2003-06-09 14:18:19.000000000 +0100
+++ source/drivers/video/amifb.c	2004-02-23 13:56:46.000000000 +0000
@@ -832,7 +832,7 @@ static struct fb_videomode ami_modedb[] 
 	FB_SYNC_BROADCAST, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
     }, {
 	/* 640x400, 15 kHz, 60 Hz interlaced (NTSC) */
-	"ntsc-lace", 60, 640, TAG_HIRES, 106, 86, 88, 33, 76, 4,
+	"ntsc-lace", 60, 640, 400, TAG_HIRES, 106, 86, 88, 33, 76, 4,
 	FB_SYNC_BROADCAST, FB_VMODE_INTERLACED | FB_VMODE_YWRAP
     }, {
 	/* 640x256, 15 kHz, 50 Hz (PAL) */
@@ -927,7 +927,7 @@ static struct fb_videomode ami_modedb[] 
 	0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
     }, {
 	/* 1024x800, 15 Hz */
-	"a2024-15", 10, 1024, 800, TAG_HIRES, 0, 0, 0, 0, 0, 0,
+	"a2024-15", 15, 1024, 800, TAG_HIRES, 0, 0, 0, 0, 0, 0,
 	0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
     }
 #endif
--- diff/drivers/video/console/fbcon.c	2004-02-18 08:54:12.000000000 +0000
+++ source/drivers/video/console/fbcon.c	2004-02-23 13:56:46.000000000 +0000
@@ -324,7 +324,7 @@ static void putcs_unaligned(struct vc_da
 	unsigned int buf_align = info->pixmap.buf_align - 1;
 	unsigned int scan_align = info->pixmap.scan_align - 1;
 	unsigned int idx = vc->vc_font.width >> 3;
-	u8 mask, *src, *dst, *dst0;
+	u8 *src, *dst, *dst0;
 
 	while (count) {
 		if (count > maxcnt)
@@ -337,15 +337,15 @@ static void putcs_unaligned(struct vc_da
 		pitch &= ~scan_align;
 		size = pitch * vc->vc_font.height + buf_align;
 		size &= ~buf_align;
-		dst0 = info->pixmap.addr + fb_get_buffer_offset(info, size);
+		dst0 = fb_get_buffer_offset(info, &info->pixmap, size);
 		image->data = dst0;
 		while (k--) {
 			src = vc->vc_font.data + (scr_readw(s++) & charmask)*
 			cellsize;
 			dst = dst0;
-			mask = (u8) (0xfff << shift_high);
-			move_buf_unaligned(info, dst, src, pitch, image->height,
-					mask, shift_high, shift_low, mod, idx);
+			fb_move_buf_unaligned(info, &info->pixmap, dst, pitch, src,
+						idx, image->height, shift_high,
+						shift_low, mod);
 			shift_low += mod;
 			dst0 += (shift_low >= 8) ? width : width - 1;
 			shift_low &= 7;
@@ -381,12 +381,13 @@ static void putcs_aligned(struct vc_data
 		size = pitch * vc->vc_font.height + buf_align;
 		size &= ~buf_align;
 		image->width = vc->vc_font.width * cnt;
-		dst0 = info->pixmap.addr + fb_get_buffer_offset(info, size);
+		dst0 = fb_get_buffer_offset(info, &info->pixmap, size);
 		image->data = dst0;
 		while (k--) {
 			src = vc->vc_font.data + (scr_readw(s++)&charmask)*cellsize;
 			dst = dst0;
-			move_buf_aligned(info, dst, src, pitch, width, image->height);
+			fb_move_buf_aligned(info, &info->pixmap, dst, pitch, src,
+						width, image->height);
 			dst0 += width;
 		}
 		info->fbops->fb_imageblit(info, image);
@@ -455,11 +456,11 @@ static void accel_putc(struct vc_data *v
 	size = pitch * vc->vc_font.height;
 	size += buf_align;
 	size &= ~buf_align;
-	dst = info->pixmap.addr + fb_get_buffer_offset(info, size);
+	dst = fb_get_buffer_offset(info, &info->pixmap, size);
 	image.data = dst;
 	src = vc->vc_font.data + (c & charmask) * vc->vc_font.height * width;
 
-	move_buf_aligned(info, dst, src, pitch, width, image.height);
+	fb_move_buf_aligned(info, &info->pixmap, dst, pitch, src, width, image.height);
 
 	info->fbops->fb_imageblit(info, &image);
 }
@@ -2335,6 +2336,7 @@ int __init fb_console_init(void)
 {
 	if (!num_registered_fb)
 		return -ENODEV;
+
 	take_over_console(&fb_con, first_fb_vc, last_fb_vc, fbcon_is_default);
 	acquire_console_sem();
 	if (!fbcon_event_notifier_registered) {
@@ -2342,10 +2344,11 @@ int __init fb_console_init(void)
 		fbcon_event_notifier_registered = 1;
 	} 
 	release_console_sem();
-
 	return 0;
 }
 
+#ifdef MODULE
+
 void __exit fb_console_exit(void)
 {
 	acquire_console_sem();
@@ -2360,6 +2363,8 @@ void __exit fb_console_exit(void)
 module_init(fb_console_init);
 module_exit(fb_console_exit);
 
+#endif
+
 /*
  *  Visible symbols for modules
  */
--- diff/drivers/video/fbmem.c	2004-02-18 08:54:12.000000000 +0000
+++ source/drivers/video/fbmem.c	2004-02-23 13:56:46.000000000 +0000
@@ -395,7 +395,7 @@ static struct {
 };
 
 #define NUM_FB_DRIVERS	(sizeof(fb_drivers)/sizeof(*fb_drivers))
-#define FBPIXMAPSIZE	8192
+#define FBPIXMAPSIZE	16384
 
 extern const char *global_mode_option;
 
@@ -412,52 +412,54 @@ static int ofonly __initdata = 0;
 /*
  * Drawing helpers.
  */
-u8 sys_inbuf(u8 *src)
+u8 sys_inbuf(struct fb_info *info, u8 *src)
 {	
 	return *src;
 }
 
-void sys_outbuf(u8 *src, u8 *dst, unsigned int size)
+void sys_outbuf(struct fb_info *info, u8 *dst, u8 *src, unsigned int size)
 {
 	memcpy(dst, src, size);
 }	
 
-void move_buf_aligned(struct fb_info *info, u8 *dst, u8 *src, u32 d_pitch, 
-			u32 s_pitch, u32 height)
+void fb_move_buf_aligned(struct fb_info *info, struct fb_pixmap *buf,
+			u8 *dst, u32 d_pitch, u8 *src, u32 s_pitch,
+			u32 height)
 {
 	int i;
 
 	for (i = height; i--; ) {
-		info->pixmap.outbuf(src, dst, s_pitch);
+		buf->outbuf(info, dst, src, s_pitch);
 		src += s_pitch;
 		dst += d_pitch;
 	}
 }
 
-void move_buf_unaligned(struct fb_info *info, u8 *dst, u8 *src, u32 d_pitch, 
-			u32 height, u32 mask, u32 shift_high, u32 shift_low,
-			u32 mod, u32 idx)
+void fb_move_buf_unaligned(struct fb_info *info, struct fb_pixmap *buf,
+			u8 *dst, u32 d_pitch, u8 *src, u32 idx,
+			u32 height, u32 shift_high, u32 shift_low,
+			u32 mod)
 {
+	u8 mask = (u8) (0xfff << shift_high), tmp;
 	int i, j;
-	u8 tmp;
 
 	for (i = height; i--; ) {
 		for (j = 0; j < idx; j++) {
-			tmp = info->pixmap.inbuf(dst+j);
+			tmp = buf->inbuf(info, dst+j);
 			tmp &= mask;
 			tmp |= *src >> shift_low;
-			info->pixmap.outbuf(&tmp, dst+j, 1);
+			buf->outbuf(info, dst+j, &tmp, 1);
 			tmp = *src << shift_high;
-			info->pixmap.outbuf(&tmp, dst+j+1, 1);
+			buf->outbuf(info, dst+j+1, &tmp, 1);
 			src++;
 		}
-		tmp = info->pixmap.inbuf(dst+idx);
+		tmp = buf->inbuf(info, dst+idx);
 		tmp &= mask;
 		tmp |= *src >> shift_low;
-		info->pixmap.outbuf(&tmp, dst+idx, 1);
+		buf->outbuf(info, dst+idx, &tmp, 1);
 		if (shift_high < mod) {
 			tmp = *src << shift_high;
-			info->pixmap.outbuf(&tmp, dst+idx+1, 1);
+			buf->outbuf(info, dst+idx+1, &tmp, 1);
 		}	
 		src++;
 		dst += d_pitch;
@@ -468,10 +470,10 @@ void move_buf_unaligned(struct fb_info *
  * we need to lock this section since fb_cursor
  * may use fb_imageblit()
  */
-u32 fb_get_buffer_offset(struct fb_info *info, u32 size)
+char* fb_get_buffer_offset(struct fb_info *info, struct fb_pixmap *buf, u32 size)
 {
-	struct fb_pixmap *buf = &info->pixmap;
 	u32 align = buf->buf_align - 1, offset;
+	char *addr = buf->addr;
 
 	/* If IO mapped, we need to sync before access, no sharing of
 	 * the pixmap is done
@@ -479,7 +481,7 @@ u32 fb_get_buffer_offset(struct fb_info 
 	if (buf->flags & FB_PIXMAP_IO) {
 		if (info->fbops->fb_sync && (buf->flags & FB_PIXMAP_SYNC))
 			info->fbops->fb_sync(info);
-		return 0;
+		return addr;
 	}
 
 	/* See if we fit in the remaining pixmap space */
@@ -495,8 +497,9 @@ u32 fb_get_buffer_offset(struct fb_info 
 		offset = 0;
 	}
 	buf->offset = offset + size;
+	addr += offset;
 
-	return offset;
+	return addr;
 }
 
 #ifdef CONFIG_LOGO
@@ -869,6 +872,15 @@ static void try_to_load(int fb)
 }
 #endif /* CONFIG_KMOD */
 
+void
+fb_load_cursor_image(struct fb_info *info)
+{
+	unsigned int width = (info->cursor.image.width + 7) >> 3;
+	u8 *data = (u8 *) info->cursor.image.data;
+
+	info->sprite.outbuf(info, info->sprite.addr, data, width);
+}
+
 int
 fb_cursor(struct fb_info *info, struct fb_cursor *sprite)
 {
@@ -1276,6 +1288,21 @@ register_framebuffer(struct fb_info *fb_
 	if (fb_info->pixmap.inbuf == NULL)
 		fb_info->pixmap.inbuf = sys_inbuf;
 
+	if (fb_info->sprite.addr == NULL) {
+		fb_info->sprite.addr = kmalloc(FBPIXMAPSIZE, GFP_KERNEL);
+		if (fb_info->sprite.addr) {
+			fb_info->sprite.size = FBPIXMAPSIZE;
+			fb_info->sprite.buf_align = 1;
+			fb_info->sprite.scan_align = 1;
+			fb_info->sprite.flags = FB_PIXMAP_DEFAULT;
+		}
+	}
+	fb_info->sprite.offset = 0;
+	if (fb_info->sprite.outbuf == NULL)
+		fb_info->sprite.outbuf = sys_outbuf;
+	if (fb_info->sprite.inbuf == NULL)
+		fb_info->sprite.inbuf = sys_inbuf;
+
 	registered_fb[i] = fb_info;
 
 	devfs_mk_cdev(MKDEV(FB_MAJOR, i),
@@ -1304,8 +1331,10 @@ unregister_framebuffer(struct fb_info *f
 		return -EINVAL;
 	devfs_remove("fb/%d", i);
 
-	if (fb_info->pixmap.addr)
+	if (fb_info->pixmap.addr && (fb_info->pixmap.flags & FB_PIXMAP_DEFAULT))
 		kfree(fb_info->pixmap.addr);
+	if (fb_info->sprite.addr && (fb_info->sprite.flags & FB_PIXMAP_DEFAULT))
+		kfree(fb_info->sprite.addr);
 	registered_fb[i]=NULL;
 	num_registered_fb--;
 	return 0;
@@ -1460,8 +1489,9 @@ EXPORT_SYMBOL(fb_set_var);
 EXPORT_SYMBOL(fb_blank);
 EXPORT_SYMBOL(fb_pan_display);
 EXPORT_SYMBOL(fb_get_buffer_offset);
-EXPORT_SYMBOL(move_buf_unaligned);
-EXPORT_SYMBOL(move_buf_aligned);
+EXPORT_SYMBOL(fb_move_buf_unaligned);
+EXPORT_SYMBOL(fb_move_buf_aligned);
+EXPORT_SYMBOL(fb_load_cursor_image);
 EXPORT_SYMBOL(fb_set_suspend);
 EXPORT_SYMBOL(fb_register_client);
 EXPORT_SYMBOL(fb_unregister_client);
--- diff/drivers/video/riva/fbdev.c	2004-02-18 08:54:12.000000000 +0000
+++ source/drivers/video/riva/fbdev.c	2004-02-23 13:56:46.000000000 +0000
@@ -1530,9 +1530,9 @@ static int rivafb_cursor(struct fb_info 
 			break;
 		}
 		
-		move_buf_aligned(info, data, src, d_pitch, s_pitch, info->cursor.image.height);
+		fb_move_buf_aligned(info, &info->sprite, data, d_pitch, src, s_pitch, info->cursor.image.height);
 
-		move_buf_aligned(info, mask, msk, d_pitch, s_pitch, info->cursor.image.height);
+		fb_move_buf_aligned(info, &info->sprite, mask, d_pitch, msk, s_pitch, info->cursor.image.height);
 
 		bg = ((info->cmap.red[bg_idx] & 0xf8) << 7) |
 		     ((info->cmap.green[bg_idx] & 0xf8) << 2) |
--- diff/drivers/video/softcursor.c	2004-02-18 08:54:12.000000000 +0000
+++ source/drivers/video/softcursor.c	2004-02-23 13:56:46.000000000 +0000
@@ -19,8 +19,8 @@
 
 int soft_cursor(struct fb_info *info, struct fb_cursor *cursor)
 {
-	unsigned int scan_align = info->pixmap.scan_align - 1;
-	unsigned int buf_align = info->pixmap.buf_align - 1;
+	unsigned int scan_align = info->sprite.scan_align - 1;
+	unsigned int buf_align = info->sprite.buf_align - 1;
 	unsigned int i, size, dsize, s_pitch, d_pitch;
 	u8 *dst, src[64];
 
@@ -56,7 +56,7 @@ int soft_cursor(struct fb_info *info, st
 	d_pitch = (s_pitch + scan_align) & ~scan_align;
 	size = d_pitch * info->cursor.image.height + buf_align;
 	size &= ~buf_align;
-	dst = info->pixmap.addr + fb_get_buffer_offset(info, size);
+	dst = fb_get_buffer_offset(info, &info->sprite, size);
 
 	if (info->cursor.enable) {
 		switch (info->cursor.rop) {
@@ -73,7 +73,7 @@ int soft_cursor(struct fb_info *info, st
 	} else 
 		memcpy(src, cursor->image.data, dsize);
 	
-	move_buf_aligned(info, dst, src, d_pitch, s_pitch, info->cursor.image.height);
+	fb_move_buf_aligned(info, &info->sprite, dst, d_pitch, src, s_pitch, info->cursor.image.height);
 	info->cursor.image.data = dst;
 	
 	info->fbops->fb_imageblit(info, &info->cursor.image);
--- diff/fs/Kconfig	2004-02-18 08:54:12.000000000 +0000
+++ source/fs/Kconfig	2004-02-23 13:56:46.000000000 +0000
@@ -780,6 +780,30 @@ config PROC_KCORE
 	bool
 	default y if !ARM
 
+config SYSFS
+	bool "sysfs file system support" if EMBEDDED
+	default y
+	help
+	The sysfs filesystem is a virtual filesystem that the kernel uses to export
+	internal kernel objects, their attributes, and their relationships to one
+	another.
+
+	Users can use sysfs to ascertain useful information about the running kernel,
+	such as the devices the kernel has discovered on each bus and which driver
+	each is bound to. sysfs can also be used to tune devices and other kernel
+	subsystems.
+
+	Some system agents rely on the information in sysfs to operate. /sbin/hotplug
+	uses device and object attributes in sysfs to assist in delegating policy
+	decisions, like persistantly naming devices.
+
+	sysfs is currently needed by the block subsystem to mount the root partition.
+	Therefore, you MUST say Y if you're booting from a hard drive. If you use any
+	type of hotpluggable device, you'll also need sysfs for /sbin/hotplug support.
+
+	However, designers of embedded systems may want to say N here to conserve
+	space.
+
 config DEVFS_FS
 	bool "/dev file system support (OBSOLETE)"
 	depends on EXPERIMENTAL
@@ -797,8 +821,7 @@ config DEVFS_FS
 	  the file README there.
 
 	  Note that devfs no longer manages /dev/pts!  If you are using UNIX98
-	  ptys, you will also need to enable (and mount) the /dev/pts
-	  filesystem (CONFIG_DEVPTS_FS).
+	  ptys, you will also need to mount the /dev/pts filesystem (devpts).
 
 	  Note that devfs has been obsoleted by udev,
 	  <http://www.kernel.org/pub/linux/utils/kernel/hotplug/>.
@@ -831,32 +854,9 @@ config DEVFS_DEBUG
 
 	  If unsure, say N.
 
-config DEVPTS_FS
-# It compiles as a module for testing only.  It should not be used
-# as a module in general.  If we make this "tristate", a bunch of people
-# who don't know what they are doing turn it on and complain when it
-# breaks.
-	bool "/dev/pts file system for Unix98 PTYs"
-	depends on UNIX98_PTYS
-	---help---
-	  You should say Y here if you said Y to "Unix98 PTY support" above.
-	  You'll then get a virtual file system which can be mounted on
-	  /dev/pts with "mount -t devpts". This, together with the pseudo
-	  terminal master multiplexer /dev/ptmx, is used for pseudo terminal
-	  support as described in The Open Group's Unix98 standard: in order
-	  to acquire a pseudo terminal, a process opens /dev/ptmx; the number
-	  of the pseudo terminal is then made available to the process and the
-	  pseudo terminal slave can be accessed as /dev/pts/<number>. What was
-	  traditionally /dev/ttyp2 will then be /dev/pts/2, for example.
-
-	  The GNU C library glibc 2.1 contains the requisite support for this
-	  mode of operation; you also need client programs that use the Unix98
-	  API. Please read <file:Documentation/Changes> for more information
-	  about the Unix98 pty devices.
-
 config DEVPTS_FS_XATTR
 	bool "/dev/pts Extended Attributes"
-	depends on DEVPTS_FS
+	depends on UNIX98_PTYS
 	help
 	  Extended attributes are name:value pairs associated with inodes by
 	  the kernel or by users (see the attr(5) manual page, or visit
@@ -975,6 +975,18 @@ config HFS_FS
 	  To compile this file system support as a module, choose M here: the
 	  module will be called hfs.
 
+config HFSPLUS_FS
+	tristate "Apple Extended HFS file system support"
+	select NLS
+	help
+	  If you say Y here, you will be able to mount extended format
+	  Macintosh-formatted hard drive partitions with full read-write access.
+
+	  This file system is often called HFS+ and was introduced with
+	  MacOS 8. It includes all Mac specific filesystem data such as
+	  data forks and creator codes, but it also has several UNIX
+	  style features such as file ownership and permissions.
+
 config BEFS_FS
 	tristate "BeOS file systemv(BeFS) support (read only) (EXPERIMENTAL)"
 	depends on EXPERIMENTAL
@@ -1239,6 +1251,9 @@ config UFS_FS
 	  experimental "UFS file system write support", below. Please read the
 	  file <file:Documentation/filesystems/ufs.txt> for more information.
 
+          The recently released UFS2 variant (used in FreeBSD 5.x) is
+          READ-ONLY supported.
+
 	  If you only intend to mount files from some other Unix over the
 	  network using NFS, you don't need the UFS file system support (but
 	  you need NFS file system support obviously).
@@ -1592,9 +1607,12 @@ config CODA_FS_OLD_API
 	  
 	  For most cases you probably want to say N.
 
+#
+# Intermezzo broke when we added the expanded NGROUPS patches
+#
 config INTERMEZZO_FS
 	tristate "InterMezzo file system support (replicating fs) (EXPERIMENTAL)"
-	depends on INET && EXPERIMENTAL
+	depends on INET && EXPERIMENTAL && BROKEN
 	help
 	  InterMezzo is a networked file system with disconnected operation
 	  and kernel level write back caching.  It is most often used for
--- diff/fs/Kconfig.binfmt	2004-01-19 10:22:59.000000000 +0000
+++ source/fs/Kconfig.binfmt	2004-02-23 13:56:46.000000000 +0000
@@ -36,6 +36,12 @@ config BINFMT_ZFLAT
 	help
 	  Support FLAT format compressed binaries
 
+config BINFMT_SHARED_FLAT
+	bool "Enable shared FLAT support"
+	depends on BINFMT_FLAT
+	help
+	  Support FLAT shared libraries
+
 config BINFMT_AOUT
 	tristate "Kernel support for a.out and ECOFF binaries"
 	depends on (X86 && !X86_64) || ALPHA || ARM || M68K || MIPS || SPARC
--- diff/fs/Makefile	2004-02-18 08:54:12.000000000 +0000
+++ source/fs/Makefile	2004-02-23 13:56:46.000000000 +0000
@@ -39,7 +39,7 @@ obj-$(CONFIG_QUOTACTL)		+= quota.o
 
 obj-$(CONFIG_PROC_FS)		+= proc/
 obj-y				+= partitions/
-obj-y				+= sysfs/
+obj-$(CONFIG_SYSFS)		+= sysfs/
 obj-y				+= devpts/
 
 obj-$(CONFIG_PROFILING)		+= dcookies.o
@@ -62,6 +62,7 @@ obj-$(CONFIG_VFAT_FS)		+= vfat/
 obj-$(CONFIG_BFS_FS)		+= bfs/
 obj-$(CONFIG_ISO9660_FS)	+= isofs/
 obj-$(CONFIG_DEVFS_FS)		+= devfs/
+obj-$(CONFIG_HFSPLUS_FS)	+= hfsplus/ # Before hfs to find wrapped HFS+
 obj-$(CONFIG_HFS_FS)		+= hfs/
 obj-$(CONFIG_VXFS_FS)		+= freevxfs/
 obj-$(CONFIG_NFS_FS)		+= nfs/
--- diff/fs/adfs/adfs.h	2003-09-17 12:28:11.000000000 +0100
+++ source/fs/adfs/adfs.h	2004-02-23 13:56:46.000000000 +0000
@@ -68,12 +68,8 @@ struct adfs_discmap {
 
 
 /* Inode stuff */
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0)
 int adfs_get_block(struct inode *inode, sector_t block,
 		   struct buffer_head *bh, int create);
-#else
-int adfs_bmap(struct inode *inode, int block);
-#endif
 struct inode *adfs_iget(struct super_block *sb, struct object_info *obj);
 void adfs_read_inode(struct inode *inode);
 void adfs_write_inode(struct inode *inode,int unused);
--- diff/fs/binfmt_aout.c	2003-09-30 15:46:18.000000000 +0100
+++ source/fs/binfmt_aout.c	2004-02-23 13:56:46.000000000 +0000
@@ -309,7 +309,7 @@ static int load_aout_binary(struct linux
 		(current->mm->start_brk = N_BSSADDR(ex));
 	current->mm->free_area_cache = TASK_UNMAPPED_BASE;
 
-	current->mm->rss = 0;
+	zero_rss(current->mm);
 	current->mm->mmap = NULL;
 	compute_creds(bprm);
  	current->flags &= ~PF_FORKNOEXEC;
--- diff/fs/binfmt_elf.c	2004-02-18 08:54:12.000000000 +0000
+++ source/fs/binfmt_elf.c	2004-02-23 13:56:46.000000000 +0000
@@ -36,6 +36,7 @@
 #include <linux/highmem.h>
 #include <linux/pagemap.h>
 #include <linux/security.h>
+#include <linux/syscalls.h>
 
 #include <asm/uaccess.h>
 #include <asm/param.h>
@@ -671,7 +672,7 @@ static int load_elf_binary(struct linux_
 
 	/* Do this so that we can load the interpreter, if need be.  We will
 	   change some of these later */
-	current->mm->rss = 0;
+	zero_rss(current->mm);
 	current->mm->free_area_cache = TASK_UNMAPPED_BASE;
 	retval = setup_arg_pages(bprm);
 	if (retval < 0) {
--- diff/fs/binfmt_flat.c	2003-08-20 14:16:32.000000000 +0100
+++ source/fs/binfmt_flat.c	2004-02-23 13:56:46.000000000 +0000
@@ -179,7 +179,7 @@ static int decompress_exec(
 	unsigned char *buf;
 	z_stream strm;
 	loff_t fpos;
-	int ret;
+	int ret, retval;
 
 	DBG_FLT("decompress_exec(offset=%x,buf=%x,len=%x)\n",(int)offset, (int)dst, (int)len);
 
@@ -192,7 +192,8 @@ static int decompress_exec(
 	buf = kmalloc(LBUFSIZE, GFP_KERNEL);
 	if (buf == NULL) {
 		DBG_FLT("binfmt_flat: no memory for read buffer\n");
-		return -ENOMEM;
+		retval = -ENOMEM;
+		goto out_free;
 	}
 
 	/* Read in first chunk of data and parse gzip header. */
@@ -203,28 +204,30 @@ static int decompress_exec(
 	strm.avail_in = ret;
 	strm.total_in = 0;
 
+	retval = -ENOEXEC;
+
 	/* Check minimum size -- gzip header */
 	if (ret < 10) {
 		DBG_FLT("binfmt_flat: file too small?\n");
-		return -ENOEXEC;
+		goto out_free_buf;
 	}
 
 	/* Check gzip magic number */
 	if ((buf[0] != 037) || ((buf[1] != 0213) && (buf[1] != 0236))) {
 		DBG_FLT("binfmt_flat: unknown compression magic?\n");
-		return -ENOEXEC;
+		goto out_free_buf;
 	}
 
 	/* Check gzip method */
 	if (buf[2] != 8) {
 		DBG_FLT("binfmt_flat: unknown compression method?\n");
-		return -ENOEXEC;
+		goto out_free_buf;
 	}
 	/* Check gzip flags */
 	if ((buf[3] & ENCRYPTED) || (buf[3] & CONTINUATION) ||
 	    (buf[3] & RESERVED)) {
 		DBG_FLT("binfmt_flat: unknown flags?\n");
-		return -ENOEXEC;
+		goto out_free_buf;
 	}
 
 	ret = 10;
@@ -232,7 +235,7 @@ static int decompress_exec(
 		ret += 2 + buf[10] + (buf[11] << 8);
 		if (unlikely(LBUFSIZE == ret)) {
 			DBG_FLT("binfmt_flat: buffer overflow (EXTRA)?\n");
-			return -ENOEXEC;
+			goto out_free_buf;
 		}
 	}
 	if (buf[3] & ORIG_NAME) {
@@ -240,7 +243,7 @@ static int decompress_exec(
 			;
 		if (unlikely(LBUFSIZE == ret)) {
 			DBG_FLT("binfmt_flat: buffer overflow (ORIG_NAME)?\n");
-			return -ENOEXEC;
+			goto out_free_buf;
 		}
 	}
 	if (buf[3] & COMMENT) {
@@ -248,7 +251,7 @@ static int decompress_exec(
 			;
 		if (unlikely(LBUFSIZE == ret)) {
 			DBG_FLT("binfmt_flat: buffer overflow (COMMENT)?\n");
-			return -ENOEXEC;
+			goto out_free_buf;
 		}
 	}
 
@@ -261,7 +264,7 @@ static int decompress_exec(
 
 	if (zlib_inflateInit2(&strm, -MAX_WBITS) != Z_OK) {
 		DBG_FLT("binfmt_flat: zlib init failed?\n");
-		return -ENOEXEC;
+		goto out_free_buf;
 	}
 
 	while ((ret = zlib_inflate(&strm, Z_NO_FLUSH)) == Z_OK) {
@@ -280,13 +283,18 @@ static int decompress_exec(
 	if (ret < 0) {
 		DBG_FLT("binfmt_flat: decompression failed (%d), %s\n",
 			ret, strm.msg);
-		return -ENOEXEC;
+		goto out_zlib;
 	}
 
+	retval = 0;
+out_zlib:
 	zlib_inflateEnd(&strm);
+out_free_buf:
 	kfree(buf);
+out_free:
 	kfree(strm.workspace);
-	return 0;
+out:
+	return retval;
 }
 
 #endif /* CONFIG_BINFMT_ZFLAT */
@@ -643,7 +651,7 @@ static int load_flat_file(struct linux_b
 		current->mm->start_brk = datapos + data_len + bss_len;
 		current->mm->brk = (current->mm->start_brk + 3) & ~3;
 		current->mm->context.end_brk = memp + ksize((void *) memp) - stack_len;
-		current->mm->rss = 0;
+		zero_rss(current->mm);
 	}
 
 	if (flags & FLAT_FLAG_KTRACE)
--- diff/fs/binfmt_misc.c	2003-11-25 15:24:58.000000000 +0000
+++ source/fs/binfmt_misc.c	2004-02-23 13:56:46.000000000 +0000
@@ -26,6 +26,7 @@
 #include <linux/pagemap.h>
 #include <linux/namei.h>
 #include <linux/mount.h>
+#include <linux/syscalls.h>
 
 #include <asm/uaccess.h>
 
@@ -38,6 +39,8 @@ static int enabled = 1;
 
 enum {Enabled, Magic};
 #define MISC_FMT_PRESERVE_ARGV0 (1<<31)
+#define MISC_FMT_OPEN_BINARY (1<<30)
+#define MISC_FMT_CREDENTIALS (1<<29)
 
 typedef struct {
 	struct list_head list;
@@ -101,10 +104,15 @@ static Node *check_file(struct linux_bin
 static int load_misc_binary(struct linux_binprm *bprm, struct pt_regs *regs)
 {
 	Node *fmt;
-	struct file * file;
+	struct file * interp_file = NULL;
+	struct file * binary_file = NULL;
 	char iname[BINPRM_BUF_SIZE];
 	char *iname_addr = iname;
 	int retval;
+	int fd_binary = -1;
+	char fd_str[32];
+	char * fdsp = fd_str;
+	int is_open_bin;
 
 	retval = -ENOEXEC;
 	if (!enabled)
@@ -119,33 +127,105 @@ static int load_misc_binary(struct linux
 	if (!fmt)
 		goto _ret;
 
-	allow_write_access(bprm->file);
-	fput(bprm->file);
-	bprm->file = NULL;
+	is_open_bin = (fmt->flags & MISC_FMT_OPEN_BINARY) ? 1 : 0;
+
+ 	if (is_open_bin) {
+		/* if the binary should be opened on behalf of the
+		 * interpreter than keep it open and assign descriptor
+		 * to it */
+ 		fd_binary = get_unused_fd ();
+ 		if (fd_binary < 0) {
+ 			retval = fd_binary;
+ 			goto _ret;
+ 		}
+ 		snprintf (fd_str, sizeof(fd_str) - 1, "%d", fd_binary);
+ 	} else {
+ 		allow_write_access (bprm->file);
+ 		fput (bprm->file);
+ 		bprm->file = NULL;
+ 	}
 
 	/* Build args for interpreter */
 	if (!(fmt->flags & MISC_FMT_PRESERVE_ARGV0)) {
 		remove_arg_zero(bprm);
 	}
-	retval = copy_strings_kernel(1, &bprm->interp, bprm);
-	if (retval < 0) goto _ret; 
-	bprm->argc++;
-	retval = copy_strings_kernel(1, &iname_addr, bprm);
-	if (retval < 0) goto _ret; 
-	bprm->argc++;
+
+ 	if (is_open_bin) {
+		/* make argv[1] be the file descriptor of the binary */
+ 		retval = copy_strings_kernel (1, &fdsp, bprm);
+ 	} else {
+		/* make argv[1] be the path to the binary */
+ 		retval = copy_strings_kernel (1, &bprm->interp, bprm);
+ 	}
+	if (retval < 0)
+		goto _error;
+	bprm->argc ++;
+	retval = copy_strings_kernel (1, &iname_addr, bprm);
+	if (retval < 0)
+		goto _error;
+	bprm->argc ++;
 	bprm->interp = iname;	/* for binfmt_script */
 
-	file = open_exec(iname);
-	retval = PTR_ERR(file);
-	if (IS_ERR(file))
-		goto _ret;
-	bprm->file = file;
+	interp_file = open_exec (iname);
+	retval = PTR_ERR (interp_file);
+	if (IS_ERR (interp_file))
+		goto _error;
+
+
+	binary_file = bprm->file;
+	if (fmt->flags & MISC_FMT_CREDENTIALS) {
+		/*
+		 * Call prepare_binprm before switching to interpreter's file
+		 * so that all security calculation will be done according to
+		 * binary and not interpreter
+		 */
+		retval = prepare_binprm(bprm);
+		if (retval < 0)
+			goto _error;
+		bprm->file = interp_file;
+		memset(bprm->buf, 0, BINPRM_BUF_SIZE);
+		retval = kernel_read(bprm->file, 0, bprm->buf, BINPRM_BUF_SIZE);
+	} else {
+		bprm->file = interp_file;
+		retval = prepare_binprm (bprm);
+	}
+
+	if (retval < 0)
+		goto _error;
+
+	if (is_open_bin) {
+		/* if the binary is not readable than enforce mm->dumpable=0
+		   regardless of the interpreter's permissions */
+		if (permission (binary_file->f_dentry->d_inode, MAY_READ, NULL)) {
+			bprm->interp_flags |= BINPRM_FLAGS_ENFORCE_NONDUMP;
+		}
+		/* install the binary's fd. it is done at the latest possible point
+	 	 * because once it is installed it will need to be sys_close()ed
+	 	 * in case of error.
+	 	 */
+ 		fd_install (fd_binary, binary_file);
+	}
+
+	retval = search_binary_handler (bprm, regs);
+
+	if (retval < 0)
+		goto _error_close_file;
 
-	retval = prepare_binprm(bprm);
-	if (retval >= 0)
-		retval = search_binary_handler(bprm, regs);
 _ret:
 	return retval;
+
+_error_close_file:
+	if (fd_binary > 0) {
+		sys_close (fd_binary);
+		fd_binary = -1;
+		bprm->file = NULL;
+	}
+_error:
+	if (fd_binary > 0)
+		put_unused_fd (fd_binary);
+	bprm->interp_flags = 0;
+	goto _ret;
+
 }
 
 /* Command parsers */
@@ -190,6 +270,36 @@ static int unquote(char *from)
 	return p - from;
 }
 
+static inline char * check_special_flags (char * sfs, Node * e)
+{
+	char * p = sfs;
+	int cont = 1;
+
+	/* special flags */
+	while (cont) {
+		switch (*p) {
+			case 'P':
+				p++;
+				e->flags |= MISC_FMT_PRESERVE_ARGV0;
+				break;
+			case 'O':
+				p++;
+				e->flags |= MISC_FMT_OPEN_BINARY;
+				break;
+			case 'C':
+				p++;
+				/* this flags also implies the
+				   open-binary flag */
+				e->flags |= (MISC_FMT_CREDENTIALS |
+						MISC_FMT_OPEN_BINARY);
+				break;
+			default:
+				cont = 0;
+		}
+	}
+
+	return p;
+}
 /*
  * This registers a new binary format, it recognises the syntax
  * ':name:type:offset:magic:mask:interpreter:'
@@ -292,10 +402,8 @@ static Node *create_entry(const char *bu
 	if (!e->interpreter[0])
 		goto Einval;
 
-	if (*p == 'P') {
-		p++;
-		e->flags |= MISC_FMT_PRESERVE_ARGV0;
-	}
+
+	p = check_special_flags (p, e);
 
 	if (*p == '\n')
 		p++;
@@ -345,6 +453,7 @@ static void entry_status(Node *e, char *
 {
 	char *dp;
 	char *status = "disabled";
+	const char * flags = "flags: ";
 
 	if (test_bit(Enabled, &e->flags))
 		status = "enabled";
@@ -356,6 +465,22 @@ static void entry_status(Node *e, char *
 
 	sprintf(page, "%s\ninterpreter %s\n", status, e->interpreter);
 	dp = page + strlen(page);
+
+	/* print the special flags */
+	sprintf (dp, "%s", flags);
+	dp += strlen (flags);
+	if (e->flags & MISC_FMT_PRESERVE_ARGV0) {
+		*dp ++ = 'P';
+	}
+	if (e->flags & MISC_FMT_OPEN_BINARY) {
+		*dp ++ = 'O';
+	}
+	if (e->flags & MISC_FMT_CREDENTIALS) {
+		*dp ++ = 'C';
+	}
+	*dp ++ = '\n';
+
+
 	if (!test_bit(Magic, &e->flags)) {
 		sprintf(dp, "extension .%s\n", e->magic);
 	} else {
--- diff/fs/binfmt_som.c	2004-01-19 10:22:59.000000000 +0000
+++ source/fs/binfmt_som.c	2004-02-23 13:56:46.000000000 +0000
@@ -259,7 +259,7 @@ load_som_binary(struct linux_binprm * bp
 	create_som_tables(bprm);
 
 	current->mm->start_stack = bprm->p;
-	current->mm->rss = 0;
+	zero_rss(current->mm);
 
 #if 0
 	printk("(start_brk) %08lx\n" , (unsigned long) current->mm->start_brk);
--- diff/fs/block_dev.c	2004-02-18 08:54:12.000000000 +0000
+++ source/fs/block_dev.c	2004-02-23 13:56:46.000000000 +0000
@@ -146,8 +146,8 @@ blkdev_direct_IO(int rw, struct kiocb *i
 	struct file *file = iocb->ki_filp;
 	struct inode *inode = file->f_mapping->host;
 
-	return blockdev_direct_IO(rw, iocb, inode, I_BDEV(inode), iov, offset,
-				nr_segs, blkdev_get_blocks, NULL);
+	return blockdev_direct_IO_no_locking(rw, iocb, inode, I_BDEV(inode),
+				iov, offset, nr_segs, blkdev_get_blocks, NULL);
 }
 
 static int blkdev_writepage(struct page *page, struct writeback_control *wbc)
@@ -479,13 +479,13 @@ EXPORT_SYMBOL(bd_release);
  * to be used for internal purposes.  If you ever need it - reconsider
  * your API.
  */
-struct block_device *open_by_devnum(dev_t dev, unsigned mode, int kind)
+struct block_device *open_by_devnum(dev_t dev, unsigned mode)
 {
 	struct block_device *bdev = bdget(dev);
 	int err = -ENOMEM;
 	int flags = mode & FMODE_WRITE ? O_RDWR : O_RDONLY;
 	if (bdev)
-		err = blkdev_get(bdev, mode, flags, kind);
+		err = blkdev_get(bdev, mode, flags);
 	return err ? ERR_PTR(err) : bdev;
 }
 
@@ -525,7 +525,8 @@ EXPORT_SYMBOL(check_disk_change);
 static void bd_set_size(struct block_device *bdev, loff_t size)
 {
 	unsigned bsize = bdev_hardsect_size(bdev);
-	i_size_write(bdev->bd_inode, size);
+
+	bdev->bd_inode->i_size = size;
 	while (bsize < PAGE_CACHE_SIZE) {
 		if (size & bsize)
 			break;
@@ -579,7 +580,7 @@ static int do_open(struct block_device *
 			ret = -ENOMEM;
 			if (!whole)
 				goto out_first;
-			ret = blkdev_get(whole, file->f_mode, file->f_flags, BDEV_RAW);
+			ret = blkdev_get(whole, file->f_mode, file->f_flags);
 			if (ret)
 				goto out_first;
 			bdev->bd_contains = whole;
@@ -625,7 +626,7 @@ out_first:
 	bdev->bd_disk = NULL;
 	bdev->bd_inode->i_data.backing_dev_info = &default_backing_dev_info;
 	if (bdev != bdev->bd_contains)
-		blkdev_put(bdev->bd_contains, BDEV_RAW);
+		blkdev_put(bdev->bd_contains);
 	bdev->bd_contains = NULL;
 	put_disk(disk);
 	module_put(owner);
@@ -637,7 +638,7 @@ out:
 	return ret;
 }
 
-int blkdev_get(struct block_device *bdev, mode_t mode, unsigned flags, int kind)
+int blkdev_get(struct block_device *bdev, mode_t mode, unsigned flags)
 {
 	/*
 	 * This crockload is due to bad choice of ->open() type.
@@ -682,13 +683,13 @@ int blkdev_open(struct inode * inode, st
 	if (!(res = bd_claim(bdev, filp)))
 		return 0;
 
-	blkdev_put(bdev, BDEV_FILE);
+	blkdev_put(bdev);
 	return res;
 }
 
 EXPORT_SYMBOL(blkdev_open);
 
-int blkdev_put(struct block_device *bdev, int kind)
+int blkdev_put(struct block_device *bdev)
 {
 	int ret = 0;
 	struct inode *bd_inode = bdev->bd_inode;
@@ -721,7 +722,7 @@ int blkdev_put(struct block_device *bdev
 		bdev->bd_disk = NULL;
 		bdev->bd_inode->i_data.backing_dev_info = &default_backing_dev_info;
 		if (bdev != bdev->bd_contains) {
-			blkdev_put(bdev->bd_contains, BDEV_RAW);
+			blkdev_put(bdev->bd_contains);
 		}
 		bdev->bd_contains = NULL;
 	}
@@ -738,7 +739,7 @@ static int blkdev_close(struct inode * i
 	struct block_device *bdev = I_BDEV(filp->f_mapping->host);
 	if (bdev->bd_holder == filp)
 		bd_release(bdev);
-	return blkdev_put(bdev, BDEV_FILE);
+	return blkdev_put(bdev);
 }
 
 static ssize_t blkdev_file_write(struct file *file, const char __user *buf,
@@ -785,7 +786,7 @@ struct file_operations def_blk_fops = {
 	.fsync		= block_fsync,
 	.ioctl		= block_ioctl,
 	.readv		= generic_file_readv,
-	.writev		= generic_file_writev,
+	.writev		= generic_file_write_nolock,
 	.sendfile	= generic_file_sendfile,
 };
 
@@ -850,14 +851,12 @@ fail:
  *
  * @path:	special file representing the block device
  * @flags:	%MS_RDONLY for opening read-only
- * @kind:	usage (same as the 4th paramter to blkdev_get)
  * @holder:	owner for exclusion
  *
  * Open the blockdevice described by the special file at @path, claim it
- * for the @holder and properly set it up for @kind usage.
+ * for the @holder.
  */
-struct block_device *open_bdev_excl(const char *path, int flags,
-				    int kind, void *holder)
+struct block_device *open_bdev_excl(const char *path, int flags, void *holder)
 {
 	struct block_device *bdev;
 	mode_t mode = FMODE_READ;
@@ -869,7 +868,7 @@ struct block_device *open_bdev_excl(cons
 
 	if (!(flags & MS_RDONLY))
 		mode |= FMODE_WRITE;
-	error = blkdev_get(bdev, mode, 0, kind);
+	error = blkdev_get(bdev, mode, 0);
 	if (error)
 		return ERR_PTR(error);
 	error = -EACCES;
@@ -882,7 +881,7 @@ struct block_device *open_bdev_excl(cons
 	return bdev;
 	
 blkdev_put:
-	blkdev_put(bdev, BDEV_FS);
+	blkdev_put(bdev);
 	return ERR_PTR(error);
 }
 
@@ -892,14 +891,13 @@ EXPORT_SYMBOL(open_bdev_excl);
  * close_bdev_excl  -  release a blockdevice openen by open_bdev_excl()
  *
  * @bdev:	blockdevice to close
- * @kind:	usage (same as the 4th paramter to blkdev_get)
  *
  * This is the counterpart to open_bdev_excl().
  */
-void close_bdev_excl(struct block_device *bdev, int kind)
+void close_bdev_excl(struct block_device *bdev)
 {
 	bd_release(bdev);
-	blkdev_put(bdev, kind);
+	blkdev_put(bdev);
 }
 
 EXPORT_SYMBOL(close_bdev_excl);
--- diff/fs/buffer.c	2004-02-09 10:36:12.000000000 +0000
+++ source/fs/buffer.c	2004-02-23 13:56:46.000000000 +0000
@@ -431,6 +431,7 @@ __find_get_block_slow(struct block_devic
 	printk("block=%llu, b_blocknr=%llu\n",
 		(unsigned long long)block, (unsigned long long)bh->b_blocknr);
 	printk("b_state=0x%08lx, b_size=%u\n", bh->b_state, bh->b_size);
+	printk("device blocksize: %d\n", 1 << bd_inode->i_blkbits);
 out_unlock:
 	spin_unlock(&bd_mapping->private_lock);
 	page_cache_release(page);
@@ -857,10 +858,13 @@ int __set_page_dirty_buffers(struct page
 		struct buffer_head *bh = head;
 
 		do {
-			if (buffer_uptodate(bh))
+			if (buffer_uptodate(bh)) {
 				set_buffer_dirty(bh);
-			else
+				if (unlikely(block_dump))
+					printk("%s(%d): dirtied buffer\n", current->comm, current->pid);
+			} else {
 				buffer_error();
+			}
 			bh = bh->b_this_page;
 		} while (bh != head);
 	}
@@ -1806,23 +1810,23 @@ static int __block_write_full_page(struc
 
 	do {
 		get_bh(bh);
-		if (buffer_mapped(bh) && buffer_dirty(bh)) {
-			if (wbc->sync_mode != WB_SYNC_NONE) {
-				lock_buffer(bh);
-			} else {
-				if (test_set_buffer_locked(bh)) {
-					__set_page_dirty_nobuffers(page);
-					continue;
-				}
-			}
-			if (test_clear_buffer_dirty(bh)) {
-				if (!buffer_uptodate(bh))
-					buffer_error();
-				mark_buffer_async_write(bh);
-			} else {
-				unlock_buffer(bh);
+		if (!buffer_mapped(bh))
+			continue;
+		if (wbc->sync_mode != WB_SYNC_NONE) {
+			lock_buffer(bh);
+		} else {
+			if (test_set_buffer_locked(bh)) {
+				__set_page_dirty_nobuffers(page);
+				continue;
 			}
 		}
+		if (test_clear_buffer_dirty(bh)) {
+			if (!buffer_uptodate(bh))
+				buffer_error();
+			mark_buffer_async_write(bh);
+		} else {
+			unlock_buffer(bh);
+		}
 	} while ((bh = bh->b_this_page) != head);
 
 	BUG_ON(PageWriteback(page));
@@ -2987,33 +2991,26 @@ init_buffer_head(void *data, kmem_cache_
 	}
 }
 
-static void buffer_init_cpu(int cpu)
+#ifdef CONFIG_HOTPLUG_CPU
+static void buffer_exit_cpu(int cpu)
 {
-	struct bh_accounting *bha = &per_cpu(bh_accounting, cpu);
-	struct bh_lru *bhl = &per_cpu(bh_lrus, cpu);
+	int i;
+	struct bh_lru *b = &per_cpu(bh_lrus, cpu);
 
-	bha->nr = 0;
-	bha->ratelimit = 0;
-	memset(bhl, 0, sizeof(*bhl));
+	for (i = 0; i < BH_LRU_SIZE; i++) {
+		brelse(b->bhs[i]);
+		b->bhs[i] = NULL;
+	}
 }
-	
-static int __devinit buffer_cpu_notify(struct notifier_block *self, 
-				unsigned long action, void *hcpu)
+
+static int buffer_cpu_notify(struct notifier_block *self,
+			      unsigned long action, void *hcpu)
 {
-	long cpu = (long)hcpu;
-	switch(action) {
-	case CPU_UP_PREPARE:
-		buffer_init_cpu(cpu);
-		break;
-	default:
-		break;
-	}
+	if (action == CPU_DEAD)
+		buffer_exit_cpu((unsigned long)hcpu);
 	return NOTIFY_OK;
 }
-
-static struct notifier_block __devinitdata buffer_nb = {
-	.notifier_call	= buffer_cpu_notify,
-};
+#endif /* CONFIG_HOTPLUG_CPU */
 
 void __init buffer_init(void)
 {
@@ -3031,9 +3028,7 @@ void __init buffer_init(void)
 	 */
 	nrpages = (nr_free_buffer_pages() * 10) / 100;
 	max_buffer_heads = nrpages * (PAGE_SIZE / sizeof(struct buffer_head));
-	buffer_cpu_notify(&buffer_nb, (unsigned long)CPU_UP_PREPARE,
-				(void *)(long)smp_processor_id());
-	register_cpu_notifier(&buffer_nb);
+	hotcpu_notifier(buffer_cpu_notify, 0);
 }
 
 EXPORT_SYMBOL(__bforget);
--- diff/fs/compat.c	2004-01-19 10:22:59.000000000 +0000
+++ source/fs/compat.c	2004-02-23 13:56:46.000000000 +0000
@@ -28,6 +28,7 @@
 #include <linux/init.h>
 #include <linux/sockios.h>	/* for SIOCDEVPRIVATE */
 #include <linux/smp_lock.h>
+#include <linux/syscalls.h>
 #include <linux/ctype.h>
 #include <linux/module.h>
 #include <net/sock.h>		/* siocdevprivate_ioctl */
@@ -494,8 +495,6 @@ static int put_compat_flock64(struct flo
 }
 #endif
 
-extern asmlinkage long sys_fcntl(unsigned int, unsigned int, unsigned long);
-
 asmlinkage long compat_sys_fcntl64(unsigned int fd, unsigned int cmd,
 		unsigned long arg)
 {
@@ -559,8 +558,6 @@ asmlinkage long compat_sys_fcntl(unsigne
 	return compat_sys_fcntl64(fd, cmd, arg);
 }
 
-extern asmlinkage long sys_io_setup(unsigned nr_reqs, aio_context_t *ctx);
-
 asmlinkage long
 compat_sys_io_setup(unsigned nr_reqs, u32 *ctx32p)
 {
@@ -580,12 +577,6 @@ compat_sys_io_setup(unsigned nr_reqs, u3
 	return ret;
 }
 
-extern asmlinkage long sys_io_getevents(aio_context_t ctx_id,
-					  long min_nr,
-					  long nr,
-					  struct io_event *events,
-					  struct timespec *timeout);
-
 asmlinkage long
 compat_sys_io_getevents(aio_context_t ctx_id,
 				 unsigned long min_nr,
@@ -614,9 +605,6 @@ out:
 	return ret;
 }
 
-extern asmlinkage long sys_io_submit(aio_context_t, long, 
-				struct iocb __user **);
-
 static inline long
 copy_iocb(long nr, u32 *ptr32, u64 *ptr64)
 {
--- diff/fs/compat_ioctl.c	2004-02-18 08:54:12.000000000 +0000
+++ source/fs/compat_ioctl.c	2004-02-23 13:56:46.000000000 +0000
@@ -62,6 +62,7 @@
 #include <linux/if_tun.h>
 #include <linux/ctype.h>
 #include <linux/ioctl32.h>
+#include <linux/syscalls.h>
 #include <linux/ncp_fs.h>
 #include <linux/i2c.h>
 #include <linux/i2c-dev.h>
--- diff/fs/dcache.c	2004-02-18 08:54:12.000000000 +0000
+++ source/fs/dcache.c	2004-02-23 13:56:46.000000000 +0000
@@ -895,7 +895,7 @@ struct dentry *d_splice_alias(struct ino
 			new = list_entry(inode->i_dentry.next, struct dentry, d_alias);
 			__dget_locked(new);
 			spin_unlock(&dcache_lock);
-			security_d_instantiate(dentry, inode);
+			security_d_instantiate(new, inode);
 			d_rehash(dentry);
 			d_move(new, dentry);
 			iput(inode);
@@ -1531,6 +1531,16 @@ out:
 	return ino;
 }
 
+static __initdata unsigned long dhash_entries;
+static int __init set_dhash_entries(char *str)
+{
+	if (!str)
+		return 0;
+	dhash_entries = simple_strtoul(str, &str, 0);
+	return 1;
+}
+__setup("dhash_entries=", set_dhash_entries);
+
 static void __init dcache_init(unsigned long mempages)
 {
 	struct hlist_head *d;
@@ -1556,11 +1566,13 @@ static void __init dcache_init(unsigned 
 	
 	set_shrinker(DEFAULT_SEEKS, shrink_dcache_memory);
 
-#if PAGE_SHIFT < 13
-	mempages >>= (13 - PAGE_SHIFT);
-#endif
-	mempages *= sizeof(struct hlist_head);
-	for (order = 0; ((1UL << order) << PAGE_SHIFT) < mempages; order++)
+	if (!dhash_entries)
+		dhash_entries = PAGE_SHIFT < 13 ?
+				mempages >> (13 - PAGE_SHIFT) :
+				mempages << (PAGE_SHIFT - 13);
+
+	dhash_entries *= sizeof(struct hlist_head);
+	for (order = 0; ((1UL << order) << PAGE_SHIFT) < dhash_entries; order++)
 		;
 
 	do {
--- diff/fs/devfs/base.c	2004-02-18 08:54:12.000000000 +0000
+++ source/fs/devfs/base.c	2004-02-23 13:56:46.000000000 +0000
@@ -676,6 +676,7 @@
 #include <linux/smp.h>
 #include <linux/rwsem.h>
 #include <linux/sched.h>
+#include <linux/namei.h>
 
 #include <asm/uaccess.h>
 #include <asm/io.h>
@@ -685,9 +686,7 @@
 #include <asm/bitops.h>
 #include <asm/atomic.h>
 
-#include "internal.h"
-
-#define DEVFS_VERSION            "1.22 (20021013)"
+#define DEVFS_VERSION            "2004-01-31"
 
 #define DEVFS_NAME "devfs"
 
@@ -762,18 +761,6 @@ struct directory_type
     unsigned char no_more_additions:1;
 };
 
-struct bdev_type
-{
-    dev_t dev;
-};
-
-struct cdev_type
-{
-    struct file_operations *ops;
-    dev_t dev;
-    unsigned char autogen:1;
-};
-
 struct symlink_type
 {
     unsigned int length;         /*  Not including the NULL-termimator       */
@@ -801,8 +788,7 @@ struct devfs_entry
     union 
     {
 	struct directory_type dir;
-	struct bdev_type bdev;
-	struct cdev_type cdev;
+	dev_t dev;
 	struct symlink_type symlink;
 	const char *name;        /*  Only used for (mode == 0)               */
     }
@@ -813,7 +799,7 @@ struct devfs_entry
     struct devfs_inode inode;
     umode_t mode;
     unsigned short namelen;      /*  I think 64k+ filenames are a way off... */
-    unsigned char vfs_deletable:1;/*  Whether the VFS may delete the entry   */
+    unsigned char vfs:1;/*  Whether the VFS may delete the entry   */
     char name[1];                /*  This is just a dummy: the allocated array
 				     is bigger. This is NULL-terminated      */
 };
@@ -925,8 +911,6 @@ static void devfs_put (devfs_handle_t de
 	     de->name, de, de->parent,
 	     de->parent ? de->parent->name : "no parent");
     if ( S_ISLNK (de->mode) ) kfree (de->u.symlink.linkname);
-    if ( S_ISCHR (de->mode) && de->u.cdev.autogen )
-	devfs_dealloc_devnum (de->mode, de->u.cdev.dev);
     WRITE_ENTRY_MAGIC (de, 0);
 #ifdef CONFIG_DEVFS_DEBUG
     spin_lock (&stat_lock);
@@ -1063,46 +1047,40 @@ static int _devfs_append_entry (devfs_ha
     return retval;
 }   /*  End Function _devfs_append_entry  */
 
-
 /**
  *	_devfs_get_root_entry - Get the root devfs entry.
  *
  *	Returns the root devfs entry on success, else %NULL.
+ *
+ *	TODO it must be called asynchronously due to the fact
+ *	that devfs is initialized relatively late. Proper way
+ *	is to remove module_init from init_devfs_fs and manually
+ *	call it early enough during system init
  */
 
-static struct devfs_entry *_devfs_get_root_entry (void)
+static struct devfs_entry *_devfs_get_root_entry(void)
 {
-    struct devfs_entry *new;
-    static spinlock_t root_lock = SPIN_LOCK_UNLOCKED;
+	struct devfs_entry *new;
+	static spinlock_t root_lock = SPIN_LOCK_UNLOCKED;
 
-    /*  Always ensure the root is created  */
-    if (root_entry) return root_entry;
-    if ( ( new = _devfs_alloc_entry (NULL, 0,MODE_DIR) ) == NULL ) return NULL;
-    spin_lock (&root_lock);
-    if (root_entry)
-    {
-	spin_unlock (&root_lock);
-	devfs_put (new);
-	return (root_entry);
-    }
-    root_entry = new;
-    spin_unlock (&root_lock);
-    /*  And create the entry for ".devfsd"  */
-    if ( ( new = _devfs_alloc_entry (".devfsd", 0, S_IFCHR |S_IRUSR |S_IWUSR) )
-	 == NULL ) return NULL;
-    new->u.cdev.dev = devfs_alloc_devnum (S_IFCHR |S_IRUSR |S_IWUSR);
-    new->u.cdev.ops = &devfsd_fops;
-    _devfs_append_entry (root_entry, new, NULL);
-#ifdef CONFIG_DEVFS_DEBUG
-    if ( ( new = _devfs_alloc_entry (".stat", 0, S_IFCHR | S_IRUGO | S_IWUGO) )
-	 == NULL ) return NULL;
-    new->u.cdev.dev = devfs_alloc_devnum (S_IFCHR | S_IRUGO | S_IWUGO);
-    new->u.cdev.ops = &stat_fops;
-    _devfs_append_entry (root_entry, new, NULL);
-#endif
-    return root_entry;
-}   /*  End Function _devfs_get_root_entry  */
+	if (root_entry)
+		return root_entry;
 
+	new = _devfs_alloc_entry(NULL, 0, MODE_DIR);
+	if (new == NULL )
+		return NULL;
+
+	spin_lock(&root_lock);
+	if (root_entry) {
+		spin_unlock(&root_lock);
+		devfs_put(new);
+		return root_entry;
+	}
+	root_entry = new;
+	spin_unlock(&root_lock);
+
+	return root_entry;
+}   /*  End Function _devfs_get_root_entry  */
 
 /**
  *	_devfs_descend - Descend down a tree using the next component name.
@@ -1237,6 +1215,7 @@ static devfs_handle_t _devfs_walk_path (
 	}
 	if (S_ISLNK (de->mode) && traverse_symlink)
 	{   /*  Need to follow the link: this is a stack chomper  */
+		/* FIXME what if it puts outside of mounted tree? */
 	    link = _devfs_walk_path (dir, de->u.symlink.linkname,
 				     de->u.symlink.length, TRUE);
 	    devfs_put (de);
@@ -1444,27 +1423,19 @@ static void devfsd_notify (struct devfs_
 			 current->egid, &fs_info);
 } 
 
-int devfs_mk_bdev(dev_t dev, umode_t mode, const char *fmt, ...)
+static int devfs_mk_dev(dev_t dev, umode_t mode, const char *fmt, va_list args)
 {
 	struct devfs_entry *dir = NULL, *de;
 	char buf[64];
-	va_list args;
 	int error, n;
 
-	va_start(args, fmt);
-	n = vsnprintf(buf, 64, fmt, args);
-	if (n >= 64 || !buf[0]) {
-		printk(KERN_WARNING "%s: invalid format string\n",
-				__FUNCTION__);
+	n = vsnprintf(buf, sizeof(buf), fmt, args);
+	if (n >= sizeof(buf) || !buf[0]) {
+		printk(KERN_WARNING "%s: invalid format string %s\n",
+				__FUNCTION__, fmt);
 		return -EINVAL;
 	}
 	
-	if (!S_ISBLK(mode)) {
-		printk(KERN_WARNING "%s: invalide mode (%u) for %s\n",
-				__FUNCTION__, mode, buf);
-		return -EINVAL;
-	}
-
 	de = _devfs_prepare_leaf(&dir, buf, mode);
 	if (!de) {
 		printk(KERN_WARNING "%s: could not prepare leaf for %s\n",
@@ -1472,7 +1443,7 @@ int devfs_mk_bdev(dev_t dev, umode_t mod
 		return -ENOMEM;		/* could be more accurate... */
 	}
 
-	de->u.bdev.dev = dev;
+	de->u.dev = dev;
 
 	error = _devfs_append_entry(dir, de, NULL);
 	if (error) {
@@ -1487,50 +1458,35 @@ int devfs_mk_bdev(dev_t dev, umode_t mod
 	return error;
 }
 
+int devfs_mk_bdev(dev_t dev, umode_t mode, const char *fmt, ...)
+{
+	va_list args;
+
+	if (!S_ISBLK(mode)) {
+		printk(KERN_WARNING "%s: invalide mode (%u) for %s\n",
+				__FUNCTION__, mode, fmt);
+		return -EINVAL;
+	}
+
+	va_start(args, fmt);
+	return devfs_mk_dev(dev, mode, fmt, args);
+}
+
 EXPORT_SYMBOL(devfs_mk_bdev);
 
 
 int devfs_mk_cdev(dev_t dev, umode_t mode, const char *fmt, ...)
 {
-	struct devfs_entry *dir = NULL, *de;
-	char buf[64];
 	va_list args;
-	int error, n;
-
-	va_start(args, fmt);
-	n = vsnprintf(buf, 64, fmt, args);
-	if (n >= 64 || !buf[0]) {
-		printk(KERN_WARNING "%s: invalid format string\n",
-				__FUNCTION__);
-		return -EINVAL;
-	}
 
 	if (!S_ISCHR(mode)) {
 		printk(KERN_WARNING "%s: invalide mode (%u) for %s\n",
-				__FUNCTION__, mode, buf);
+				__FUNCTION__, mode, fmt);
 		return -EINVAL;
 	}
 
-	de = _devfs_prepare_leaf(&dir, buf, mode);
-	if (!de) {
-		printk(KERN_WARNING "%s: could not prepare leaf for %s\n",
-				__FUNCTION__, buf);
-		return -ENOMEM;		/* could be more accurate... */
-	}
-
-	de->u.cdev.dev = dev;
-
-	error = _devfs_append_entry(dir, de, NULL);
-	if (error) {
-		printk(KERN_WARNING "%s: could not append to parent for %s\n",
-				__FUNCTION__, buf);
-		goto out;
-	}
-
-	devfsd_notify(de, DEVFSD_NOTIFY_REGISTERED);
- out:
-	devfs_put(dir);
-	return error;
+	va_start(args, fmt);
+	return devfs_mk_dev(dev, mode, fmt, args);
 }
 
 EXPORT_SYMBOL(devfs_mk_cdev);
@@ -1663,7 +1619,7 @@ int devfs_mk_symlink(const char *from, c
 
 	err = devfs_do_symlink(NULL, from, to, &de);
 	if (!err) {
-		de->vfs_deletable = TRUE;
+		de->vfs = TRUE;
 		devfsd_notify(de, DEVFSD_NOTIFY_REGISTERED);
 	}
 
@@ -1732,8 +1688,8 @@ void devfs_remove(const char *fmt, ...)
 	int n;
 
 	va_start(args, fmt);
-	n = vsnprintf(buf, 64, fmt, args);
-	if (n < 64 && buf[0]) {
+	n = vsnprintf(buf, sizeof(buf), fmt, args);
+	if (n < sizeof(buf) && buf[0]) {
 		devfs_handle_t de = _devfs_find_entry(NULL, buf, 0);
 
 		if (!de) {
@@ -1784,33 +1740,6 @@ static int devfs_generate_path (devfs_ha
     return pos;
 }   /*  End Function devfs_generate_path  */
 
-
-/**
- *	devfs_get_ops - Get the device operations for a devfs entry.
- *	@de: The handle to the device entry.
- *
- *	Returns a pointer to the device operations on success, else NULL.
- *	The use count for the module owning the operations will be incremented.
- */
-
-static struct file_operations *devfs_get_ops (devfs_handle_t de)
-{
-    struct file_operations *ops = de->u.cdev.ops;
-    struct module *owner;
-
-    if (!ops)
-	return NULL;
-    owner = ops->owner;
-    read_lock (&de->parent->u.dir.lock);  /*  Prevent module from unloading  */
-    if ( (de->next == de) || !try_module_get (owner) )
-    {   /*  Entry is already unhooked or module is unloading  */
-	read_unlock (&de->parent->u.dir.lock);
-	return NULL;
-    }
-    read_unlock (&de->parent->u.dir.lock);  /*  Module can continue unloading*/
-    return ops;
-}   /*  End Function devfs_get_ops  */
-
 /**
  *	devfs_setup - Process kernel boot options.
  *	@str: The boot options after the "devfs=".
@@ -1876,7 +1805,6 @@ static int __init devfs_setup (char *str
 
 __setup("devfs=", devfs_setup);
 
-EXPORT_SYMBOL(devfs_put);
 EXPORT_SYMBOL(devfs_mk_symlink);
 EXPORT_SYMBOL(devfs_mk_dir);
 EXPORT_SYMBOL(devfs_remove);
@@ -1996,6 +1924,7 @@ static struct inode *_devfs_get_vfs_inod
 	iput (inode);
 	return NULL;
     }
+    /* FIXME where is devfs_put? */
     inode->u.generic_ip = devfs_get (de);
     inode->i_ino = de->inode.ino;
     DPRINTK (DEBUG_I_GET, "(%d): VFS inode: %p  devfs_entry: %p\n",
@@ -2003,26 +1932,25 @@ static struct inode *_devfs_get_vfs_inod
     inode->i_blocks = 0;
     inode->i_blksize = FAKE_BLOCK_SIZE;
     inode->i_op = &devfs_iops;
-    inode->i_fop = &devfs_fops;
-    if ( S_ISCHR (de->mode) )
-    {
-	inode->i_rdev = de->u.cdev.dev;
-    }
-    else if ( S_ISBLK (de->mode) )
-	init_special_inode(inode, de->mode, de->u.bdev.dev);
-    else if ( S_ISFIFO (de->mode) )
-    	inode->i_fop = &def_fifo_fops;
-    else if ( S_ISDIR (de->mode) )
-    {
-	inode->i_op = &devfs_dir_iops;
-    	inode->i_fop = &devfs_dir_fops;
-    }
-    else if ( S_ISLNK (de->mode) )
-    {
-	inode->i_op = &devfs_symlink_iops;
-	inode->i_size = de->u.symlink.length;
-    }
     inode->i_mode = de->mode;
+	if (S_ISDIR(de->mode)) {
+		inode->i_op = &devfs_dir_iops;
+		inode->i_fop = &devfs_dir_fops;
+	} else if (S_ISLNK(de->mode)) {
+		inode->i_op = &devfs_symlink_iops;
+		inode->i_size = de->u.symlink.length;
+	} else if (S_ISCHR(de->mode) || S_ISBLK(de->mode)) {
+		init_special_inode(inode, de->mode, de->u.dev);
+	} else if (S_ISFIFO(de->mode) || S_ISSOCK(de->mode)) {
+		init_special_inode(inode, de->mode, 0);
+	} else {
+		PRINTK("(%s): unknown mode %o de: %p\n",
+			de->name, de->mode, de);
+		iput(inode);
+		devfs_put(de);
+		return NULL;
+	}
+
     inode->i_uid = de->inode.uid;
     inode->i_gid = de->inode.gid;
     inode->i_atime = de->inode.atime;
@@ -2098,29 +2026,37 @@ static int devfs_readdir (struct file *f
     return stored;
 }   /*  End Function devfs_readdir  */
 
+/* Open devfs specific special files */
 static int devfs_open (struct inode *inode, struct file *file)
 {
-    int err = -ENODEV;
-    struct devfs_entry *de;
-    struct file_operations *ops;
+	int err;
+	int minor = MINOR(inode->i_rdev);
+	struct file_operations *old_fops, *new_fops;
 
-    de = get_devfs_entry_from_vfs_inode (inode);
-    if (de == NULL) return -ENODEV;
-    if ( S_ISDIR (de->mode) ) return 0;
-    file->private_data = de->info;
-    if (S_ISCHR(inode->i_mode)) {
-	ops = devfs_get_ops (de);  /*  Now have module refcount  */
-	file->f_op = ops;
-	if (file->f_op)
-	{
-	    lock_kernel ();
-	    err = file->f_op->open ? (*file->f_op->open) (inode, file) : 0;
-	    unlock_kernel ();
+	switch (minor) {
+	case 0: /* /dev/.devfsd */
+		new_fops = fops_get(&devfsd_fops);
+		break;
+#ifdef CONFIG_DEVFS_DEBUG
+	case 1: /* /dev/.stat */
+		new_fops = fops_get(&stat_fops);
+		break;
+#endif
+	default:
+		return -ENODEV;
 	}
-	else
-	    err = chrdev_open (inode, file);
-    }
-    return err;
+
+	if (new_fops == NULL)
+		return -ENODEV;
+	old_fops = file->f_op;
+	file->f_op = new_fops;
+	err = new_fops->open ? new_fops->open(inode, file) : 0;
+	if (err) {
+		file->f_op = old_fops;
+		fops_put(new_fops);
+	} else
+		fops_put(old_fops);
+	return err;
 }   /*  End Function devfs_open  */
 
 static struct file_operations devfs_fops =
@@ -2132,7 +2068,6 @@ static struct file_operations devfs_dir_
 {
     .read    = generic_read_dir,
     .readdir = devfs_readdir,
-    .open    = devfs_open,
 };
 
 
@@ -2223,6 +2158,34 @@ static int devfs_d_revalidate_wait (stru
     devfs_handle_t parent = get_devfs_entry_from_vfs_inode (dir);
     struct devfs_lookup_struct *lookup_info = dentry->d_fsdata;
     DECLARE_WAITQUEUE (wait, current);
+    int need_lock;
+
+    /*
+     * FIXME HACK
+     *
+     * make sure that
+     *   d_instantiate always runs under lock
+     *   we release i_sem lock before going to sleep
+     *
+     * unfortunately sometimes d_revalidate is called with
+     * and sometimes without i_sem lock held. The following checks
+     * attempt to deduce when we need to add (and drop resp.) lock
+     * here. This relies on current (2.6.2) calling coventions:
+     *
+     *   lookup_hash is always run under i_sem and is passing NULL
+     *   as nd
+     *
+     *   open(...,O_CREATE,...) calls _lookup_hash under i_sem
+     *   and sets flags to LOOKUP_OPEN|LOOKUP_CREATE
+     *
+     *   all other invocations of ->d_revalidate seem to happen
+     *   outside of i_sem
+     */
+    need_lock = nd &&
+		(!(nd->flags & LOOKUP_CREATE) || (nd->flags & LOOKUP_PARENT));
+
+    if (need_lock)
+	down(&dir->i_sem);
 
     if ( is_devfsd_or_child (fs_info) )
     {
@@ -2233,33 +2196,40 @@ static int devfs_d_revalidate_wait (stru
 		 "(%s): dentry: %p inode: %p de: %p by: \"%s\"\n",
 		 dentry->d_name.name, dentry, dentry->d_inode, de,
 		 current->comm);
-	if (dentry->d_inode) return 1;
+	if (dentry->d_inode)
+	    goto out;
 	if (de == NULL)
 	{
 	    read_lock (&parent->u.dir.lock);
 	    de = _devfs_search_dir (parent, dentry->d_name.name,
 				    dentry->d_name.len);
 	    read_unlock (&parent->u.dir.lock);
-	    if (de == NULL) return 1;
+	    if (de == NULL)
+		goto out;
 	    lookup_info->de = de;
 	}
 	/*  Create an inode, now that the driver information is available  */
 	inode = _devfs_get_vfs_inode (dir->i_sb, de, dentry);
-	if (!inode) return 1;
+	if (!inode)
+	    goto out;
 	DPRINTK (DEBUG_I_LOOKUP,
 		 "(%s): new VFS inode(%u): %p de: %p by: \"%s\"\n",
 		 de->name, de->inode.ino, inode, de, current->comm);
 	d_instantiate (dentry, inode);
-	return 1;
+	goto out;
     }
-    if (lookup_info == NULL) return 1;  /*  Early termination  */
+    if (lookup_info == NULL)
+	goto out;  /*  Early termination  */
     read_lock (&parent->u.dir.lock);
     if (dentry->d_fsdata)
     {
 	set_current_state (TASK_UNINTERRUPTIBLE);
 	add_wait_queue (&lookup_info->wait_queue, &wait);
 	read_unlock (&parent->u.dir.lock);
+	/* at this point it is always (hopefully) locked */
+	up(&dir->i_sem);
 	schedule ();
+	down(&dir->i_sem);
 	/*
 	 * This does not need nor should remove wait from wait_queue.
 	 * Wait queue head is never reused - nothing is ever added to it
@@ -2271,6 +2241,10 @@ static int devfs_d_revalidate_wait (stru
 
     }
     else read_unlock (&parent->u.dir.lock);
+
+out:
+    if (need_lock)
+	up(&dir->i_sem);
     return 1;
 }   /*  End Function devfs_d_revalidate_wait  */
 
@@ -2320,6 +2294,7 @@ static struct dentry *devfs_lookup (stru
 	revalidation  */
     up (&dir->i_sem);
     wait_for_devfsd_finished (fs_info);  /*  If I'm not devfsd, must wait  */
+    down (&dir->i_sem);      /*  Grab it again because them's the rules  */
     de = lookup_info.de;
     /*  If someone else has been so kind as to make the inode, we go home
 	early  */
@@ -2349,7 +2324,6 @@ out:
     dentry->d_fsdata = NULL;
     wake_up (&lookup_info.wait_queue);
     write_unlock (&parent->u.dir.lock);
-    down (&dir->i_sem);      /*  Grab it again because them's the rules  */
     devfs_put (de);
     return retval;
 }   /*  End Function devfs_lookup  */
@@ -2364,7 +2338,7 @@ static int devfs_unlink (struct inode *d
     de = get_devfs_entry_from_vfs_inode (inode);
     DPRINTK (DEBUG_I_UNLINK, "(%s): de: %p\n", dentry->d_name.name, de);
     if (de == NULL) return -ENOENT;
-    if (!de->vfs_deletable) return -EPERM;
+    if (!de->vfs) return -EPERM;
     write_lock (&de->parent->u.dir.lock);
     unhooked = _devfs_unhook (de);
     write_unlock (&de->parent->u.dir.lock);
@@ -2392,7 +2366,7 @@ static int devfs_symlink (struct inode *
     DPRINTK (DEBUG_DISABLED, "(%s): errcode from <devfs_do_symlink>: %d\n",
 	     dentry->d_name.name, err);
     if (err < 0) return err;
-    de->vfs_deletable = TRUE;
+    de->vfs = TRUE;
     de->inode.uid = current->euid;
     de->inode.gid = current->egid;
     de->inode.atime = CURRENT_TIME;
@@ -2421,7 +2395,7 @@ static int devfs_mkdir (struct inode *di
     if (parent == NULL) return -ENOENT;
     de = _devfs_alloc_entry (dentry->d_name.name, dentry->d_name.len, mode);
     if (!de) return -ENOMEM;
-    de->vfs_deletable = TRUE;
+    de->vfs = TRUE;
     if ( ( err = _devfs_append_entry (parent, de, NULL) ) != 0 )
 	return err;
     de->inode.uid = current->euid;
@@ -2451,7 +2425,7 @@ static int devfs_rmdir (struct inode *di
     de = get_devfs_entry_from_vfs_inode (inode);
     if (de == NULL) return -ENOENT;
     if ( !S_ISDIR (de->mode) ) return -ENOTDIR;
-    if (!de->vfs_deletable) return -EPERM;
+    if (!de->vfs) return -EPERM;
     /*  First ensure the directory is empty and will stay that way  */
     write_lock (&de->u.dir.lock);
     if (de->u.dir.first) err = -ENOTEMPTY;
@@ -2485,11 +2459,9 @@ static int devfs_mknod (struct inode *di
     if (parent == NULL) return -ENOENT;
     de = _devfs_alloc_entry (dentry->d_name.name, dentry->d_name.len, mode);
     if (!de) return -ENOMEM;
-    de->vfs_deletable = TRUE;
-    if (S_ISCHR (mode))
-	de->u.cdev.dev = rdev;
-    else if (S_ISBLK (mode))
-	de->u.bdev.dev = rdev;
+    de->vfs = TRUE;
+    if (S_ISCHR(mode) || S_ISBLK(mode))
+	de->u.dev = rdev;
     if ( ( err = _devfs_append_entry (parent, de, NULL) ) != 0 )
 	return err;
     de->inode.uid = current->euid;
@@ -2642,12 +2614,9 @@ static ssize_t devfsd_read (struct file 
     info->uid = entry->uid;
     info->gid = entry->gid;
     de = entry->de;
-    if (S_ISCHR(de->mode)) {
-	info->major = MAJOR(de->u.cdev.dev);
-	info->minor = MINOR(de->u.cdev.dev);
-    } else if (S_ISBLK (de->mode)) {
-	info->major = MAJOR(de->u.bdev.dev);
-	info->minor = MINOR(de->u.bdev.dev);
+    if (S_ISCHR(de->mode) || S_ISBLK(de->mode)) {
+	info->major = MAJOR(de->u.dev);
+	info->minor = MINOR(de->u.dev);
     }
     pos = devfs_generate_path (de, info->devname, DEVFS_PATHLEN);
     if (pos < 0) return pos;
@@ -2809,30 +2778,53 @@ static ssize_t stat_read (struct file *f
 }   /*  End Function stat_read  */
 #endif
 
-
-static int __init init_devfs_fs (void)
+static int __init init_devfs_fs(void)
 {
-    int err;
+	int err;
+	int major;
+	struct devfs_entry *devfsd;
+#ifdef CONFIG_DEVFS_DEBUG
+	struct devfs_entry *stat;
+#endif
 
-    printk (KERN_INFO "%s: v%s Richard Gooch (rgooch@atnf.csiro.au)\n",
-	    DEVFS_NAME, DEVFS_VERSION);
-    devfsd_buf_cache = kmem_cache_create ("devfsd_event",
+	if (_devfs_get_root_entry() == NULL)
+		return -ENOMEM;
+
+	printk(KERN_INFO "%s: %s Richard Gooch (rgooch@atnf.csiro.au)\n",
+	       DEVFS_NAME, DEVFS_VERSION);
+	devfsd_buf_cache = kmem_cache_create("devfsd_event",
 					  sizeof (struct devfsd_buf_entry),
 					  0, 0, NULL, NULL);
-    if (!devfsd_buf_cache) OOPS ("(): unable to allocate event slab\n");
+	if (!devfsd_buf_cache)
+		OOPS("(): unable to allocate event slab\n");
 #ifdef CONFIG_DEVFS_DEBUG
-    devfs_debug = devfs_debug_init;
-    printk (KERN_INFO "%s: devfs_debug: 0x%0x\n", DEVFS_NAME, devfs_debug);
+	devfs_debug = devfs_debug_init;
+	printk(KERN_INFO "%s: devfs_debug: 0x%0x\n", DEVFS_NAME, devfs_debug);
 #endif
-    printk (KERN_INFO "%s: boot_options: 0x%0x\n", DEVFS_NAME, boot_options);
-    err = register_filesystem (&devfs_fs_type);
-    if (!err)
-    {
-	struct vfsmount *devfs_mnt = kern_mount (&devfs_fs_type);
-	err = PTR_ERR (devfs_mnt);
-	if ( !IS_ERR (devfs_mnt) ) err = 0;
-    }
-    return err;
+	printk(KERN_INFO "%s: boot_options: 0x%0x\n", DEVFS_NAME, boot_options);
+
+	/* register special device for devfsd communication */
+	major = register_chrdev(0, "devfs", &devfs_fops);
+	if (major < 0)
+		return major;
+
+	/*  And create the entry for ".devfsd"  */
+	devfsd = _devfs_alloc_entry(".devfsd", 0, S_IFCHR|S_IRUSR|S_IWUSR);
+	if (devfsd == NULL )
+		return -ENOMEM;
+	devfsd->u.dev = MKDEV(major, 0);
+	_devfs_append_entry(root_entry, devfsd, NULL);
+
+#ifdef CONFIG_DEVFS_DEBUG
+	stat = _devfs_alloc_entry(".stat", 0, S_IFCHR|S_IRUGO);
+	if (stat == NULL )
+		return -ENOMEM;
+	stat->u.dev = MKDEV(major, 1);
+	_devfs_append_entry (root_entry, stat, NULL);
+#endif
+
+	err = register_filesystem(&devfs_fs_type);
+	return err;
 }   /*  End Function init_devfs_fs  */
 
 void __init mount_devfs_fs (void)
--- diff/fs/devfs/util.c	2003-05-21 11:50:16.000000000 +0100
+++ source/fs/devfs/util.c	2004-02-23 13:56:46.000000000 +0000
@@ -72,7 +72,6 @@
 #include <linux/vmalloc.h>
 #include <linux/genhd.h>
 #include <asm/bitops.h>
-#include "internal.h"
 
 
 int devfs_register_tape(const char *name)
@@ -96,161 +95,3 @@ void devfs_unregister_tape(int num)
 }
 
 EXPORT_SYMBOL(devfs_unregister_tape);
-
-struct major_list
-{
-    spinlock_t lock;
-    unsigned long bits[256 / BITS_PER_LONG];
-};
-#if BITS_PER_LONG == 32
-#  define INITIALISER64(low,high) (low), (high)
-#else
-#  define INITIALISER64(low,high) ( (unsigned long) (high) << 32 | (low) )
-#endif
-
-/*  Block majors already assigned:
-    0-3, 7-9, 11-63, 65-99, 101-113, 120-127, 199, 201, 240-255
-    Total free: 122
-*/
-static struct major_list block_major_list =
-{SPIN_LOCK_UNLOCKED,
-    {INITIALISER64 (0xfffffb8f, 0xffffffff),  /*  Majors 0-31,    32-63    */
-     INITIALISER64 (0xfffffffe, 0xff03ffef),  /*  Majors 64-95,   96-127   */
-     INITIALISER64 (0x00000000, 0x00000000),  /*  Majors 128-159, 160-191  */
-     INITIALISER64 (0x00000280, 0xffff0000),  /*  Majors 192-223, 224-255  */
-    }
-};
-
-/*  Char majors already assigned:
-    0-7, 9-151, 154-158, 160-211, 216-221, 224-230, 240-255
-    Total free: 19
-*/
-static struct major_list char_major_list =
-{SPIN_LOCK_UNLOCKED,
-    {INITIALISER64 (0xfffffeff, 0xffffffff),  /*  Majors 0-31,    32-63    */
-     INITIALISER64 (0xffffffff, 0xffffffff),  /*  Majors 64-95,   96-127   */
-     INITIALISER64 (0x7cffffff, 0xffffffff),  /*  Majors 128-159, 160-191  */
-     INITIALISER64 (0x3f0fffff, 0xffff007f),  /*  Majors 192-223, 224-255  */
-    }
-};
-
-
-/**
- *	devfs_alloc_major - Allocate a major number.
- *	@mode: The file mode (must be block device or character device).
- *	Returns the allocated major, else -1 if none are available.
- *	This routine is thread safe and does not block.
- */
-
-
-struct minor_list
-{
-    int major;
-    unsigned long bits[256 / BITS_PER_LONG];
-    struct minor_list *next;
-};
-
-static struct device_list {
-	struct minor_list	*first;
-	struct minor_list	*last;
-	int			none_free;
-} block_list, char_list;
-
-static DECLARE_MUTEX(device_list_mutex);
-
-
-/**
- *	devfs_alloc_devnum - Allocate a device number.
- *	@mode: The file mode (must be block device or character device).
- *
- *	Returns the allocated device number, else NODEV if none are available.
- *	This routine is thread safe and may block.
- */
-
-dev_t devfs_alloc_devnum(umode_t mode)
-{
-	struct device_list *list;
-	struct major_list *major_list;
-	struct minor_list *entry;
-	int minor;
-
-	if (S_ISCHR(mode)) {
-		major_list = &char_major_list;
-		list = &char_list;
-	} else {
-		major_list = &block_major_list;
-		list = &block_list;
-	}
-
-	down(&device_list_mutex);
-	if (list->none_free)
-		goto out_unlock;
-
-	for (entry = list->first; entry; entry = entry->next) {
-		minor = find_first_zero_bit (entry->bits, 256);
-		if (minor >= 256)
-			continue;
-		goto out_done;
-	}
-	
-	/*  Need to allocate a new major  */
-	entry = kmalloc (sizeof *entry, GFP_KERNEL);
-	if (!entry)
-		goto out_full;
-	memset(entry, 0, sizeof *entry);
-
-	spin_lock(&major_list->lock);
-	entry->major = find_first_zero_bit(major_list->bits, 256);
-	if (entry->major >= 256) {
-		spin_unlock(&major_list->lock);
-		kfree(entry);
-		goto out_full;
-	}
-	__set_bit(entry->major, major_list->bits);
-	spin_unlock(&major_list->lock);
-
-	if (!list->first)
-		list->first = entry;
-	else
-		list->last->next = entry;
-	list->last = entry;
-
-	minor = 0;
- out_done:
-	__set_bit(minor, entry->bits);
-	up(&device_list_mutex);
-	return MKDEV(entry->major, minor);
- out_full:
-	list->none_free = 1;
- out_unlock:
-	up(&device_list_mutex);
-	return 0;
-}
-
-
-/**
- *	devfs_dealloc_devnum - Dellocate a device number.
- *	@mode: The file mode (must be block device or character device).
- *	@devnum: The device number.
- *
- *	This routine is thread safe and may block.
- */
-
-void devfs_dealloc_devnum(umode_t mode, dev_t devnum)
-{
-	struct device_list *list = S_ISCHR(mode) ? &char_list : &block_list;
-	struct minor_list *entry;
-
-	if (!devnum)
-		return;
-
-	down(&device_list_mutex);
-	for (entry = list->first; entry; entry = entry->next) {
-		if (entry->major == MAJOR(devnum)) {
-			if (__test_and_clear_bit(MINOR(devnum), entry->bits))
-				list->none_free = 0;
-			break;
-		}
-	}
-	up(&device_list_mutex);
-}
--- diff/fs/devpts/Makefile	2003-08-20 14:16:13.000000000 +0100
+++ source/fs/devpts/Makefile	2004-02-23 13:56:46.000000000 +0000
@@ -2,8 +2,8 @@
 # Makefile for the Linux /dev/pts virtual filesystem.
 #
 
-obj-$(CONFIG_DEVPTS_FS) += devpts.o
+obj-$(CONFIG_UNIX98_PTYS)		+= devpts.o
 
-devpts-y := inode.o
+devpts-$(CONFIG_UNIX98_PTYS)		:= inode.o
 devpts-$(CONFIG_DEVPTS_FS_XATTR)	+= xattr.o 
 devpts-$(CONFIG_DEVPTS_FS_SECURITY)	+= xattr_security.o
--- diff/fs/devpts/inode.c	2003-10-09 09:47:17.000000000 +0100
+++ source/fs/devpts/inode.c	2004-02-23 13:56:46.000000000 +0000
@@ -2,7 +2,7 @@
  *
  * linux/fs/devpts/inode.c
  *
- *  Copyright 1998 H. Peter Anvin -- All Rights Reserved
+ *  Copyright 1998-2004 H. Peter Anvin -- All Rights Reserved
  *
  * This file is part of the Linux kernel and is made available under
  * the terms of the GNU General Public License, version 2, or at your
@@ -16,6 +16,8 @@
 #include <linux/sched.h>
 #include <linux/namei.h>
 #include <linux/mount.h>
+#include <linux/tty.h>
+#include <linux/devpts_fs.h>
 #include "xattr.h"
 
 #define DEVPTS_SUPER_MAGIC 0x1cd1
@@ -126,7 +128,7 @@ static struct file_system_type devpts_fs
 
 static struct dentry *get_node(int num)
 {
-	char s[10];
+	char s[12];
 	struct dentry *root = devpts_root;
 	down(&root->d_inode->i_sem);
 	return lookup_one_len(s, root, sprintf(s, "%d", num));
@@ -139,12 +141,21 @@ static struct inode_operations devpts_fi
 	.removexattr	= devpts_removexattr,
 };
 
-void devpts_pty_new(int number, dev_t device)
+int devpts_pty_new(struct tty_struct *tty)
 {
+	int number = tty->index;
+	struct tty_driver *driver = tty->driver;
+	dev_t device = MKDEV(driver->major, driver->minor_start+number);
 	struct dentry *dentry;
 	struct inode *inode = new_inode(devpts_mnt->mnt_sb);
+
+	/* We're supposed to be given the slave end of a pty */
+	BUG_ON(driver->type != TTY_DRIVER_TYPE_PTY);
+	BUG_ON(driver->subtype != PTY_TYPE_SLAVE);
+
 	if (!inode)
-		return;
+		return -ENOMEM;
+
 	inode->i_ino = number+2;
 	inode->i_blksize = 1024;
 	inode->i_uid = config.setuid ? config.uid : current->fsuid;
@@ -152,11 +163,28 @@ void devpts_pty_new(int number, dev_t de
 	inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
 	init_special_inode(inode, S_IFCHR|config.mode, device);
 	inode->i_op = &devpts_file_inode_operations;
+	inode->u.generic_ip = tty;
 
 	dentry = get_node(number);
 	if (!IS_ERR(dentry) && !dentry->d_inode)
 		d_instantiate(dentry, inode);
+
+	up(&devpts_root->d_inode->i_sem);
+
+	return 0;
+}
+
+struct tty_struct *devpts_get_tty(int number)
+{
+	struct dentry *dentry = get_node(number);
+	struct tty_struct *tty;
+
+	tty = (IS_ERR(dentry) || !dentry->d_inode) ? NULL :
+			dentry->d_inode->u.generic_ip;
+
 	up(&devpts_root->d_inode->i_sem);
+
+	return tty;
 }
 
 void devpts_pty_kill(int number)
--- diff/fs/direct-io.c	2004-01-19 10:22:59.000000000 +0000
+++ source/fs/direct-io.c	2004-02-23 13:56:46.000000000 +0000
@@ -52,6 +52,10 @@
  *
  * If blkfactor is zero then the user's request was aligned to the filesystem's
  * blocksize.
+ *
+ * needs_locking is set for regular files on direct-IO-naive filesystems.  It
+ * determines whether we need to do the fancy locking which prevents direct-IO
+ * from being able to read uninitialised disk blocks.
  */
 
 struct dio {
@@ -59,6 +63,7 @@ struct dio {
 	struct bio *bio;		/* bio under assembly */
 	struct inode *inode;
 	int rw;
+	int needs_locking;		/* doesn't change */
 	unsigned blkbits;		/* doesn't change */
 	unsigned blkfactor;		/* When we're using an alignment which
 					   is finer than the filesystem's soft
@@ -69,6 +74,7 @@ struct dio {
 					   been performed at the start of a
 					   write */
 	int pages_in_io;		/* approximate total IO pages */
+	size_t	size;			/* total request size (doesn't change)*/
 	sector_t block_in_file;		/* Current offset into the underlying
 					   file in dio_block units. */
 	unsigned blocks_available;	/* At block_in_file.  changes */
@@ -110,9 +116,9 @@ struct dio {
 	int page_errors;		/* errno from get_user_pages() */
 
 	/* BIO completion state */
-	atomic_t bio_count;		/* nr bios to be completed */
-	atomic_t bios_in_flight;	/* nr bios in flight */
-	spinlock_t bio_list_lock;	/* protects bio_list */
+	spinlock_t bio_lock;		/* protects BIO fields below */
+	int bio_count;			/* nr bios to be completed */
+	int bios_in_flight;		/* nr bios in flight */
 	struct bio *bio_list;		/* singly linked via bi_private */
 	struct task_struct *waiter;	/* waiting task (NULL if none) */
 
@@ -204,8 +210,10 @@ static struct page *dio_get_page(struct 
  */
 static void dio_complete(struct dio *dio, loff_t offset, ssize_t bytes)
 {
-	if (dio->end_io)
+	if (dio->end_io && dio->result)
 		dio->end_io(dio->inode, offset, bytes, dio->map_bh.b_private);
+	if (dio->needs_locking)
+		up_read(&dio->inode->i_alloc_sem);
 }
 
 /*
@@ -214,14 +222,38 @@ static void dio_complete(struct dio *dio
  */
 static void finished_one_bio(struct dio *dio)
 {
-	if (atomic_dec_and_test(&dio->bio_count)) {
+	unsigned long flags;
+
+	spin_lock_irqsave(&dio->bio_lock, flags);
+	if (dio->bio_count == 1) {
 		if (dio->is_async) {
+			/*
+			 * Last reference to the dio is going away.
+			 * Drop spinlock and complete the DIO.
+			 */
+			spin_unlock_irqrestore(&dio->bio_lock, flags);
 			dio_complete(dio, dio->block_in_file << dio->blkbits,
 					dio->result);
-			aio_complete(dio->iocb, dio->result, 0);
-			kfree(dio);
+			/* Complete AIO later if falling back to buffered i/o */
+			if (dio->result == dio->size || dio->rw == READ) {
+				aio_complete(dio->iocb, dio->result, 0);
+				kfree(dio);
+				return;
+			} else {
+				/*
+				 * Falling back to buffered
+				 */
+				spin_lock_irqsave(&dio->bio_lock, flags);
+				dio->bio_count--;
+				if (dio->waiter)
+					wake_up_process(dio->waiter);
+				spin_unlock_irqrestore(&dio->bio_lock, flags);
+				return;
+			}
 		}
 	}
+	dio->bio_count--;
+	spin_unlock_irqrestore(&dio->bio_lock, flags);
 }
 
 static int dio_bio_complete(struct dio *dio, struct bio *bio);
@@ -255,13 +287,13 @@ static int dio_bio_end_io(struct bio *bi
 	if (bio->bi_size)
 		return 1;
 
-	spin_lock_irqsave(&dio->bio_list_lock, flags);
+	spin_lock_irqsave(&dio->bio_lock, flags);
 	bio->bi_private = dio->bio_list;
 	dio->bio_list = bio;
-	atomic_dec(&dio->bios_in_flight);
-	if (dio->waiter && atomic_read(&dio->bios_in_flight) == 0)
+	dio->bios_in_flight--;
+	if (dio->waiter && dio->bios_in_flight == 0)
 		wake_up_process(dio->waiter);
-	spin_unlock_irqrestore(&dio->bio_list_lock, flags);
+	spin_unlock_irqrestore(&dio->bio_lock, flags);
 	return 0;
 }
 
@@ -294,10 +326,13 @@ dio_bio_alloc(struct dio *dio, struct bl
 static void dio_bio_submit(struct dio *dio)
 {
 	struct bio *bio = dio->bio;
+	unsigned long flags;
 
 	bio->bi_private = dio;
-	atomic_inc(&dio->bio_count);
-	atomic_inc(&dio->bios_in_flight);
+	spin_lock_irqsave(&dio->bio_lock, flags);
+	dio->bio_count++;
+	dio->bios_in_flight++;
+	spin_unlock_irqrestore(&dio->bio_lock, flags);
 	if (dio->is_async && dio->rw == READ)
 		bio_set_pages_dirty(bio);
 	submit_bio(dio->rw, bio);
@@ -323,22 +358,22 @@ static struct bio *dio_await_one(struct 
 	unsigned long flags;
 	struct bio *bio;
 
-	spin_lock_irqsave(&dio->bio_list_lock, flags);
+	spin_lock_irqsave(&dio->bio_lock, flags);
 	while (dio->bio_list == NULL) {
 		set_current_state(TASK_UNINTERRUPTIBLE);
 		if (dio->bio_list == NULL) {
 			dio->waiter = current;
-			spin_unlock_irqrestore(&dio->bio_list_lock, flags);
+			spin_unlock_irqrestore(&dio->bio_lock, flags);
 			blk_run_queues();
 			io_schedule();
-			spin_lock_irqsave(&dio->bio_list_lock, flags);
+			spin_lock_irqsave(&dio->bio_lock, flags);
 			dio->waiter = NULL;
 		}
 		set_current_state(TASK_RUNNING);
 	}
 	bio = dio->bio_list;
 	dio->bio_list = bio->bi_private;
-	spin_unlock_irqrestore(&dio->bio_list_lock, flags);
+	spin_unlock_irqrestore(&dio->bio_lock, flags);
 	return bio;
 }
 
@@ -380,7 +415,12 @@ static int dio_await_completion(struct d
 	if (dio->bio)
 		dio_bio_submit(dio);
 
-	while (atomic_read(&dio->bio_count)) {
+	/*
+	 * The bio_lock is not held for the read of bio_count.
+	 * This is ok since it is the dio_bio_complete() that changes
+	 * bio_count.
+	 */
+	while (dio->bio_count) {
 		struct bio *bio = dio_await_one(dio);
 		int ret2;
 
@@ -407,10 +447,10 @@ static int dio_bio_reap(struct dio *dio)
 			unsigned long flags;
 			struct bio *bio;
 
-			spin_lock_irqsave(&dio->bio_list_lock, flags);
+			spin_lock_irqsave(&dio->bio_lock, flags);
 			bio = dio->bio_list;
 			dio->bio_list = bio->bi_private;
-			spin_unlock_irqrestore(&dio->bio_list_lock, flags);
+			spin_unlock_irqrestore(&dio->bio_lock, flags);
 			ret = dio_bio_complete(dio, bio);
 		}
 		dio->reap_counter = 0;
@@ -449,6 +489,7 @@ static int get_more_blocks(struct dio *d
 	unsigned long fs_count;	/* Number of filesystem-sized blocks */
 	unsigned long dio_count;/* Number of dio_block-sized blocks */
 	unsigned long blkmask;
+	int beyond_eof = 0;
 
 	/*
 	 * If there was a memory error and we've overwritten all the
@@ -466,8 +507,19 @@ static int get_more_blocks(struct dio *d
 		if (dio_count & blkmask)	
 			fs_count++;
 
+		if (dio->needs_locking) {
+			if (dio->block_in_file >= (i_size_read(dio->inode) >>
+							dio->blkbits))
+				beyond_eof = 1;
+		}
+		/*
+		 * For writes inside i_size we forbid block creations: only
+		 * overwrites are permitted.  We fall back to buffered writes
+		 * at a higher level for inside-i_size block-instantiating
+		 * writes.
+		 */
 		ret = (*dio->get_blocks)(dio->inode, fs_startblk, fs_count,
-				map_bh, dio->rw == WRITE);
+				map_bh, (dio->rw == WRITE) && beyond_eof);
 	}
 	return ret;
 }
@@ -774,6 +826,10 @@ do_holes:
 			if (!buffer_mapped(map_bh)) {
 				char *kaddr;
 
+				/* AKPM: eargh, -ENOTBLK is a hack */
+				if (dio->rw == WRITE)
+					return -ENOTBLK;
+
 				if (dio->block_in_file >=
 					i_size_read(dio->inode)>>blkbits) {
 					/* We hit eof */
@@ -839,32 +895,30 @@ out:
 	return ret;
 }
 
+/*
+ * Releases both i_sem and i_alloc_sem
+ */
 static int
 direct_io_worker(int rw, struct kiocb *iocb, struct inode *inode, 
 	const struct iovec *iov, loff_t offset, unsigned long nr_segs, 
-	unsigned blkbits, get_blocks_t get_blocks, dio_iodone_t end_io)
+	unsigned blkbits, get_blocks_t get_blocks, dio_iodone_t end_io,
+	struct dio *dio)
 {
 	unsigned long user_addr; 
 	int seg;
 	int ret = 0;
 	int ret2;
-	struct dio *dio;
 	size_t bytes;
 
-	dio = kmalloc(sizeof(*dio), GFP_KERNEL);
-	if (!dio)
-		return -ENOMEM;
-	dio->is_async = !is_sync_kiocb(iocb);
-
 	dio->bio = NULL;
 	dio->inode = inode;
 	dio->rw = rw;
 	dio->blkbits = blkbits;
 	dio->blkfactor = inode->i_blkbits - blkbits;
 	dio->start_zero_done = 0;
+	dio->size = 0;
 	dio->block_in_file = offset >> blkbits;
 	dio->blocks_available = 0;
-
 	dio->cur_page = NULL;
 
 	dio->boundary = 0;
@@ -887,9 +941,9 @@ direct_io_worker(int rw, struct kiocb *i
 	 * (or synchronous) device could take the count to zero while we're
 	 * still submitting BIOs.
 	 */
-	atomic_set(&dio->bio_count, 1);
-	atomic_set(&dio->bios_in_flight, 0);
-	spin_lock_init(&dio->bio_list_lock);
+	dio->bio_count = 1;
+	dio->bios_in_flight = 0;
+	spin_lock_init(&dio->bio_lock);
 	dio->bio_list = NULL;
 	dio->waiter = NULL;
 
@@ -899,7 +953,7 @@ direct_io_worker(int rw, struct kiocb *i
 
 	for (seg = 0; seg < nr_segs; seg++) {
 		user_addr = (unsigned long)iov[seg].iov_base;
-		bytes = iov[seg].iov_len;
+		dio->size += bytes = iov[seg].iov_len;
 
 		/* Index into the first page of the first block */
 		dio->first_block_in_page = (user_addr & ~PAGE_MASK) >> blkbits;
@@ -930,6 +984,13 @@ direct_io_worker(int rw, struct kiocb *i
 		}
 	} /* end iovec loop */
 
+	if (ret == -ENOTBLK && rw == WRITE) {
+		/*
+		 * The remaining part of the request will be
+		 * be handled by buffered I/O when we return
+		 */
+		ret = 0;
+	}
 	/*
 	 * There may be some unwritten disk at the end of a part-written
 	 * fs-block-sized block.  Go zero that now.
@@ -953,14 +1014,48 @@ direct_io_worker(int rw, struct kiocb *i
 	dio_cleanup(dio);
 
 	/*
+	 * All block lookups have been performed. For READ requests
+	 * we can let i_sem go now that its achieved its purpose
+	 * of protecting us from looking up uninitialized blocks.
+	 */
+	if ((rw == READ) && dio->needs_locking)
+		up(&dio->inode->i_sem);
+
+	/*
 	 * OK, all BIOs are submitted, so we can decrement bio_count to truly
 	 * reflect the number of to-be-processed BIOs.
 	 */
 	if (dio->is_async) {
+		int should_wait = 0;
+
+		if (dio->result < dio->size && rw == WRITE) {
+			dio->waiter = current;
+			should_wait = 1;
+		}
 		if (ret == 0)
-			ret = dio->result;	/* Bytes written */
+			ret = dio->result;
 		finished_one_bio(dio);		/* This can free the dio */
 		blk_run_queues();
+		if (should_wait) {
+			unsigned long flags;
+			/*
+			 * Wait for already issued I/O to drain out and
+			 * release its references to user-space pages
+			 * before returning to fallback on buffered I/O
+			 */
+
+			spin_lock_irqsave(&dio->bio_lock, flags);
+			set_current_state(TASK_UNINTERRUPTIBLE);
+			while (dio->bio_count) {
+				spin_unlock_irqrestore(&dio->bio_lock, flags);
+				io_schedule();
+				spin_lock_irqsave(&dio->bio_lock, flags);
+				set_current_state(TASK_UNINTERRUPTIBLE);
+			}
+			spin_unlock_irqrestore(&dio->bio_lock, flags);
+			set_current_state(TASK_RUNNING);
+			kfree(dio);
+		}
 	} else {
 		finished_one_bio(dio);
 		ret2 = dio_await_completion(dio);
@@ -980,6 +1075,10 @@ direct_io_worker(int rw, struct kiocb *i
 				ret = i_size - offset;
 		}
 		dio_complete(dio, offset, ret);
+		/* We could have also come here on an AIO file extend */
+		if (!is_sync_kiocb(iocb) && !(rw == WRITE && ret >= 0 &&
+			dio->result < dio->size))
+			aio_complete(iocb, ret, 0);
 		kfree(dio);
 	}
 	return ret;
@@ -987,11 +1086,17 @@ direct_io_worker(int rw, struct kiocb *i
 
 /*
  * This is a library function for use by filesystem drivers.
+ *
+ * For writes to S_ISREG files, we are called under i_sem and return with i_sem
+ * held, even though it is internally dropped.
+ *
+ * For writes to S_ISBLK files, i_sem is not held on entry; it is never taken.
  */
 int
-blockdev_direct_IO(int rw, struct kiocb *iocb, struct inode *inode, 
+__blockdev_direct_IO(int rw, struct kiocb *iocb, struct inode *inode,
 	struct block_device *bdev, const struct iovec *iov, loff_t offset, 
-	unsigned long nr_segs, get_blocks_t get_blocks, dio_iodone_t end_io)
+	unsigned long nr_segs, get_blocks_t get_blocks, dio_iodone_t end_io,
+	int needs_special_locking)
 {
 	int seg;
 	size_t size;
@@ -1000,6 +1105,9 @@ blockdev_direct_IO(int rw, struct kiocb 
 	unsigned bdev_blkbits = 0;
 	unsigned blocksize_mask = (1 << blkbits) - 1;
 	ssize_t retval = -EINVAL;
+	loff_t end = offset;
+	struct dio *dio;
+	int needs_locking;
 
 	if (bdev)
 		bdev_blkbits = blksize_bits(bdev_hardsect_size(bdev));
@@ -1016,6 +1124,7 @@ blockdev_direct_IO(int rw, struct kiocb 
 	for (seg = 0; seg < nr_segs; seg++) {
 		addr = (unsigned long)iov[seg].iov_base;
 		size = iov[seg].iov_len;
+		end += size;
 		if ((addr & blocksize_mask) || (size & blocksize_mask))  {
 			if (bdev)
 				 blkbits = bdev_blkbits;
@@ -1025,10 +1134,46 @@ blockdev_direct_IO(int rw, struct kiocb 
 		}
 	}
 
-	retval = direct_io_worker(rw, iocb, inode, iov, offset, 
-				nr_segs, blkbits, get_blocks, end_io);
+	dio = kmalloc(sizeof(*dio), GFP_KERNEL);
+	retval = -ENOMEM;
+	if (!dio)
+		goto out;
+
+	/*
+	 * For regular files,
+	 *	readers need to grab i_sem and i_alloc_sem
+	 *	writers need to grab i_alloc_sem only (i_sem is already held)
+	 */
+	needs_locking = 0;
+	if (S_ISREG(inode->i_mode) && needs_special_locking) {
+		needs_locking = 1;
+		if (rw == READ) {
+			struct address_space *mapping;
+
+			mapping = iocb->ki_filp->f_mapping;
+			down(&inode->i_sem);
+			retval = filemap_write_and_wait(mapping);
+			if (retval) {
+				up(&inode->i_sem);
+				kfree(dio);
+				goto out;
+			}
+		}
+		down_read(&inode->i_alloc_sem);
+	}
+	dio->needs_locking = needs_locking;
+	/*
+	 * For file extending writes updating i_size before data
+	 * writeouts complete can expose uninitialized blocks. So
+	 * even for AIO, we need to wait for i/o to complete before
+	 * returning in this case.
+	 */
+	dio->is_async = !is_sync_kiocb(iocb) && !((rw == WRITE) &&
+		(end > i_size_read(inode)));
+
+	retval = direct_io_worker(rw, iocb, inode, iov, offset,
+				nr_segs, blkbits, get_blocks, end_io, dio);
 out:
 	return retval;
 }
-
-EXPORT_SYMBOL(blockdev_direct_IO);
+EXPORT_SYMBOL(__blockdev_direct_IO);
--- diff/fs/dquot.c	2004-02-09 10:36:12.000000000 +0000
+++ source/fs/dquot.c	2004-02-23 13:56:46.000000000 +0000
@@ -261,6 +261,25 @@ static void wait_on_dquot(struct dquot *
 	up(&dquot->dq_lock);
 }
 
+#define mark_dquot_dirty(dquot) ((dquot)->dq_sb->dq_op->mark_dirty(dquot))
+
+int dquot_mark_dquot_dirty(struct dquot *dquot)
+{
+	spin_lock(&dq_data_lock);
+	set_bit(DQF_ANY_DQUOT_DIRTY_B, &(sb_dqopt((dquot)->dq_sb)->info[(dquot)->dq_type].dqi_flags));
+	set_bit(DQ_MOD_B, &(dquot)->dq_flags);
+	spin_unlock(&dq_data_lock);
+	return 0;
+}
+
+void mark_info_dirty(struct super_block *sb, int type)
+{
+	spin_lock(&dq_data_lock);
+	set_bit(DQF_INFO_DIRTY_B, &sb_dqopt(sb)->info[type].dqi_flags);
+	spin_unlock(&dq_data_lock);
+}
+
+
 static int read_dqblk(struct dquot *dquot)
 {
 	int ret;
@@ -274,14 +293,21 @@ static int read_dqblk(struct dquot *dquo
 	return ret;
 }
 
-static int commit_dqblk(struct dquot *dquot)
+/*
+ *	Write dquot to disk
+ */
+int dquot_commit(struct dquot *dquot, int init)
 {
-	int ret;
+	int ret = 0;
 	struct quota_info *dqopt = sb_dqopt(dquot->dq_sb);
 
 	down(&dqopt->dqio_sem);
-	ret = dqopt->ops[dquot->dq_type]->commit_dqblk(dquot);
+	clear_bit(DQ_MOD_B, &dquot->dq_flags);
+	if (!init || !dquot->dq_off)	/* Isn't dquot already allocated? */
+		ret = dqopt->ops[dquot->dq_type]->commit_dqblk(dquot, init);
 	up(&dqopt->dqio_sem);
+	if (info_dirty(&dqopt->info[dquot->dq_type]))
+		dquot->dq_sb->dq_op->write_info(dquot->dq_sb, dquot->dq_type);
 	return ret;
 }
 
@@ -316,7 +342,7 @@ static void invalidate_dquots(struct sup
 	spin_unlock(&dq_list_lock);
 }
 
-static int vfs_quota_sync(struct super_block *sb, int type)
+int vfs_quota_sync(struct super_block *sb, int type)
 {
 	struct list_head *head;
 	struct dquot *dquot;
@@ -327,9 +353,11 @@ static int vfs_quota_sync(struct super_b
 restart:
 	/* At this point any dirty dquot will definitely be written so we can clear
 	   dirty flag from info */
+	spin_lock(&dq_data_lock);
 	for (cnt = 0; cnt < MAXQUOTAS; cnt++)
 		if ((cnt == type || type == -1) && sb_has_quota_enabled(sb, cnt))
 			clear_bit(DQF_ANY_DQUOT_DIRTY_B, &dqopt->info[cnt].dqi_flags);
+	spin_unlock(&dq_data_lock);
 	spin_lock(&dq_list_lock);
 	list_for_each(head, &inuse_list) {
 		dquot = list_entry(head, struct dquot, dq_inuse);
@@ -344,18 +372,15 @@ restart:
 		atomic_inc(&dquot->dq_count);
 		dqstats.lookups++;
 		spin_unlock(&dq_list_lock);
-		sb->dq_op->write_dquot(dquot);
+		sb->dq_op->write_dquot(dquot, 0);
 		dqput(dquot);
 		goto restart;
 	}
 	spin_unlock(&dq_list_lock);
 
 	for (cnt = 0; cnt < MAXQUOTAS; cnt++)
-		if ((cnt == type || type == -1) && sb_has_quota_enabled(sb, cnt) && info_dirty(&dqopt->info[cnt])) {
-			down(&dqopt->dqio_sem);
-			dqopt->ops[cnt]->write_file_info(sb, cnt);
-			up(&dqopt->dqio_sem);
-		}
+		if ((cnt == type || type == -1) && sb_has_quota_enabled(sb, cnt) && info_dirty(&dqopt->info[cnt]))
+			sb->dq_op->write_info(sb, cnt);
 	spin_lock(&dq_list_lock);
 	dqstats.syncs++;
 	spin_unlock(&dq_list_lock);
@@ -430,9 +455,10 @@ we_slept:
 		spin_unlock(&dq_list_lock);
 		return;
 	}
+	/* This should never happen when we are journalling quota */
 	if (dquot_dirty(dquot)) {
 		spin_unlock(&dq_list_lock);
-		dquot->dq_sb->dq_op->write_dquot(dquot);
+		dquot->dq_sb->dq_op->write_dquot(dquot, 0);
 		goto we_slept;
 	}
 	atomic_dec(&dquot->dq_count);
@@ -539,12 +565,10 @@ restart:
 		struct file *filp = list_entry(p, struct file, f_list);
 		struct inode *inode = filp->f_dentry->d_inode;
 		if (filp->f_mode & FMODE_WRITE && dqinit_needed(inode, type)) {
-			struct vfsmount *mnt = mntget(filp->f_vfsmnt);
 			struct dentry *dentry = dget(filp->f_dentry);
 			file_list_unlock();
 			sb->dq_op->initialize(inode, type);
 			dput(dentry);
-			mntput(mnt);
 			/* As we may have blocked we had better restart... */
 			goto restart;
 		}
@@ -612,13 +636,11 @@ void put_dquot_list(struct list_head *to
 static inline void dquot_incr_inodes(struct dquot *dquot, unsigned long number)
 {
 	dquot->dq_dqb.dqb_curinodes += number;
-	mark_dquot_dirty(dquot);
 }
 
 static inline void dquot_incr_space(struct dquot *dquot, qsize_t number)
 {
 	dquot->dq_dqb.dqb_curspace += number;
-	mark_dquot_dirty(dquot);
 }
 
 static inline void dquot_decr_inodes(struct dquot *dquot, unsigned long number)
@@ -630,7 +652,6 @@ static inline void dquot_decr_inodes(str
 	if (dquot->dq_dqb.dqb_curinodes < dquot->dq_dqb.dqb_isoftlimit)
 		dquot->dq_dqb.dqb_itime = (time_t) 0;
 	clear_bit(DQ_INODES_B, &dquot->dq_flags);
-	mark_dquot_dirty(dquot);
 }
 
 static inline void dquot_decr_space(struct dquot *dquot, qsize_t number)
@@ -642,7 +663,6 @@ static inline void dquot_decr_space(stru
 	if (toqb(dquot->dq_dqb.dqb_curspace) < dquot->dq_dqb.dqb_bsoftlimit)
 		dquot->dq_dqb.dqb_btime = (time_t) 0;
 	clear_bit(DQ_BLKS_B, &dquot->dq_flags);
-	mark_dquot_dirty(dquot);
 }
 
 static inline int need_print_warning(struct dquot *dquot)
@@ -799,17 +819,19 @@ static int check_bdq(struct dquot *dquot
  *
  * Note: this is a blocking operation.
  */
-void dquot_initialize(struct inode *inode, int type)
+int dquot_initialize(struct inode *inode, int type)
 {
 	unsigned int id = 0;
-	int cnt;
+	int cnt, ret = 0;
 
+	/* First test before acquiring semaphore - solves deadlocks when we
+         * re-enter the quota code and are already holding the semaphore */
+	if (IS_NOQUOTA(inode))
+		return 0;
 	down_write(&sb_dqopt(inode->i_sb)->dqptr_sem);
 	/* Having dqptr_sem we know NOQUOTA flags can't be altered... */
-	if (IS_NOQUOTA(inode)) {
-		up_write(&sb_dqopt(inode->i_sb)->dqptr_sem);
-		return;
-	}
+	if (IS_NOQUOTA(inode))
+		goto out_err;
 	/* Build list of quotas to initialize... */
 	for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
 		if (type != -1 && cnt != type)
@@ -824,18 +846,23 @@ void dquot_initialize(struct inode *inod
 					break;
 			}
 			inode->i_dquot[cnt] = dqget(inode->i_sb, id, cnt);
-			if (inode->i_dquot[cnt])
+			if (inode->i_dquot[cnt]) {
 				inode->i_flags |= S_QUOTA;
+				/* Write dquot to allocate space in file if it's not allocated yet */
+				inode->i_sb->dq_op->write_dquot(inode->i_dquot[cnt], 1);
+			}
 		}
 	}
+out_err:
 	up_write(&sb_dqopt(inode->i_sb)->dqptr_sem);
+	return ret;
 }
 
 /*
  *	Remove references to quota from inode
  *	This function needs dqptr_sem for writing
  */
-static void dquot_drop_iupdate(struct inode *inode, struct dquot **to_drop)
+static int dquot_drop_iupdate(struct inode *inode, struct dquot **to_drop)
 {
 	int cnt;
 
@@ -844,22 +871,24 @@ static void dquot_drop_iupdate(struct in
 		to_drop[cnt] = inode->i_dquot[cnt];
 		inode->i_dquot[cnt] = NODQUOT;
 	}
+	return 0;
 }
 
 /*
  * 	Release all quotas referenced by inode
  */
-void dquot_drop(struct inode *inode)
+int dquot_drop(struct inode *inode)
 {
 	struct dquot *to_drop[MAXQUOTAS];
-	int cnt;
+	int cnt, ret;
 
 	down_write(&sb_dqopt(inode->i_sb)->dqptr_sem);
-	dquot_drop_iupdate(inode, to_drop);
+	ret = dquot_drop_iupdate(inode, to_drop);
 	up_write(&sb_dqopt(inode->i_sb)->dqptr_sem);
 	for (cnt = 0; cnt < MAXQUOTAS; cnt++)
 		if (to_drop[cnt] != NODQUOT)
 			dqput(to_drop[cnt]);
+	return ret;
 }
 
 /*
@@ -878,6 +907,15 @@ void dquot_drop_nolock(struct inode *ino
 }
 
 /*
+ * Following four functions update i_blocks+i_bytes fields and
+ * quota information (togethter with appropriate checks)
+ * NOTE: We absolutely rely on the fact that caller dirtifies
+ * the inode (usually macros in quotaops.h care about this) and
+ * holds a handle for the current transaction so that dquot write and
+ * inode write go into the same transaction.
+ */
+
+/*
  * This operation can block, but only after everything is updated
  */
 int dquot_alloc_space(struct inode *inode, qsize_t number, int warn)
@@ -885,13 +923,22 @@ int dquot_alloc_space(struct inode *inod
 	int cnt, ret = NO_QUOTA;
 	char warntype[MAXQUOTAS];
 
+	/* First test before acquiring semaphore - solves deadlocks when we
+         * re-enter the quota code and are already holding the semaphore */
+	if (IS_NOQUOTA(inode)) {
+out_add:
+		inode_add_bytes(inode, number);
+		return QUOTA_OK;
+	}
 	for (cnt = 0; cnt < MAXQUOTAS; cnt++)
 		warntype[cnt] = NOWARN;
 
 	down_read(&sb_dqopt(inode->i_sb)->dqptr_sem);
+	if (IS_NOQUOTA(inode)) {	/* Now we can do reliable test... */
+		up_read(&sb_dqopt(inode->i_sb)->dqptr_sem);
+		goto out_add;
+	}
 	spin_lock(&dq_data_lock);
-	if (IS_NOQUOTA(inode))
-		goto add_bytes;
 	for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
 		if (inode->i_dquot[cnt] == NODQUOT)
 			continue;
@@ -903,11 +950,15 @@ int dquot_alloc_space(struct inode *inod
 			continue;
 		dquot_incr_space(inode->i_dquot[cnt], number);
 	}
-add_bytes:
 	inode_add_bytes(inode, number);
 	ret = QUOTA_OK;
 warn_put_all:
 	spin_unlock(&dq_data_lock);
+	if (ret == QUOTA_OK)
+		/* Dirtify all the dquots - this can block when journalling */
+		for (cnt = 0; cnt < MAXQUOTAS; cnt++)
+			if (inode->i_dquot[cnt])
+				mark_dquot_dirty(inode->i_dquot[cnt]);
 	flush_warnings(inode->i_dquot, warntype);
 	up_read(&sb_dqopt(inode->i_sb)->dqptr_sem);
 	return ret;
@@ -921,6 +972,10 @@ int dquot_alloc_inode(const struct inode
 	int cnt, ret = NO_QUOTA;
 	char warntype[MAXQUOTAS];
 
+	/* First test before acquiring semaphore - solves deadlocks when we
+         * re-enter the quota code and are already holding the semaphore */
+	if (IS_NOQUOTA(inode))
+		return QUOTA_OK;
 	for (cnt = 0; cnt < MAXQUOTAS; cnt++)
 		warntype[cnt] = NOWARN;
 	down_read(&sb_dqopt(inode->i_sb)->dqptr_sem);
@@ -944,6 +999,11 @@ int dquot_alloc_inode(const struct inode
 	ret = QUOTA_OK;
 warn_put_all:
 	spin_unlock(&dq_data_lock);
+	if (ret == QUOTA_OK)
+		/* Dirtify all the dquots - this can block when journalling */
+		for (cnt = 0; cnt < MAXQUOTAS; cnt++)
+			if (inode->i_dquot[cnt])
+				mark_dquot_dirty(inode->i_dquot[cnt]);
 	flush_warnings((struct dquot **)inode->i_dquot, warntype);
 	up_read(&sb_dqopt(inode->i_sb)->dqptr_sem);
 	return ret;
@@ -952,36 +1012,53 @@ warn_put_all:
 /*
  * This is a non-blocking operation.
  */
-void dquot_free_space(struct inode *inode, qsize_t number)
+int dquot_free_space(struct inode *inode, qsize_t number)
 {
 	unsigned int cnt;
 
+	/* First test before acquiring semaphore - solves deadlocks when we
+         * re-enter the quota code and are already holding the semaphore */
+	if (IS_NOQUOTA(inode)) {
+out_sub:
+		inode_sub_bytes(inode, number);
+		return QUOTA_OK;
+	}
 	down_read(&sb_dqopt(inode->i_sb)->dqptr_sem);
+	if (IS_NOQUOTA(inode)) {
+		up_read(&sb_dqopt(inode->i_sb)->dqptr_sem);
+		goto out_sub;
+	}
 	spin_lock(&dq_data_lock);
-	if (IS_NOQUOTA(inode))
-		goto sub_bytes;
 	for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
 		if (inode->i_dquot[cnt] == NODQUOT)
 			continue;
 		dquot_decr_space(inode->i_dquot[cnt], number);
 	}
-sub_bytes:
 	inode_sub_bytes(inode, number);
 	spin_unlock(&dq_data_lock);
+	/* Dirtify all the dquots - this can block when journalling */
+	for (cnt = 0; cnt < MAXQUOTAS; cnt++)
+		if (inode->i_dquot[cnt])
+			mark_dquot_dirty(inode->i_dquot[cnt]);
 	up_read(&sb_dqopt(inode->i_sb)->dqptr_sem);
+	return QUOTA_OK;
 }
 
 /*
  * This is a non-blocking operation.
  */
-void dquot_free_inode(const struct inode *inode, unsigned long number)
+int dquot_free_inode(const struct inode *inode, unsigned long number)
 {
 	unsigned int cnt;
 
+	/* First test before acquiring semaphore - solves deadlocks when we
+         * re-enter the quota code and are already holding the semaphore */
+	if (IS_NOQUOTA(inode))
+		return QUOTA_OK;
 	down_read(&sb_dqopt(inode->i_sb)->dqptr_sem);
 	if (IS_NOQUOTA(inode)) {
 		up_read(&sb_dqopt(inode->i_sb)->dqptr_sem);
-		return;
+		return QUOTA_OK;
 	}
 	spin_lock(&dq_data_lock);
 	for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
@@ -990,7 +1067,12 @@ void dquot_free_inode(const struct inode
 		dquot_decr_inodes(inode->i_dquot[cnt], number);
 	}
 	spin_unlock(&dq_data_lock);
+	/* Dirtify all the dquots - this can block when journalling */
+	for (cnt = 0; cnt < MAXQUOTAS; cnt++)
+		if (inode->i_dquot[cnt])
+			mark_dquot_dirty(inode->i_dquot[cnt]);
 	up_read(&sb_dqopt(inode->i_sb)->dqptr_sem);
+	return QUOTA_OK;
 }
 
 /*
@@ -1007,6 +1089,10 @@ int dquot_transfer(struct inode *inode, 
 	    chgid = (iattr->ia_valid & ATTR_GID) && inode->i_gid != iattr->ia_gid;
 	char warntype[MAXQUOTAS];
 
+	/* First test before acquiring semaphore - solves deadlocks when we
+         * re-enter the quota code and are already holding the semaphore */
+	if (IS_NOQUOTA(inode))
+		return QUOTA_OK;
 	/* Clear the arrays */
 	for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
 		transfer_to[cnt] = transfer_from[cnt] = NODQUOT;
@@ -1065,6 +1151,13 @@ int dquot_transfer(struct inode *inode, 
 	ret = QUOTA_OK;
 warn_put_all:
 	spin_unlock(&dq_data_lock);
+	/* Dirtify all the dquots - this can block when journalling */
+	for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
+		if (transfer_from[cnt])
+			mark_dquot_dirty(transfer_from[cnt]);
+		if (transfer_to[cnt])
+			mark_dquot_dirty(transfer_to[cnt]);
+	}
 	flush_warnings(transfer_to, warntype);
 	
 	for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
@@ -1078,25 +1171,35 @@ warn_put_all:
 }
 
 /*
+ * Write info of quota file to disk
+ */
+int dquot_commit_info(struct super_block *sb, int type)
+{
+	int ret;
+	struct quota_info *dqopt = sb_dqopt(sb);
+
+	down(&dqopt->dqio_sem);
+	ret = dqopt->ops[type]->write_file_info(sb, type);
+	up(&dqopt->dqio_sem);
+	return ret;
+}
+
+/*
  * Definitions of diskquota operations.
  */
 struct dquot_operations dquot_operations = {
-	.initialize	= dquot_initialize,		/* mandatory */
-	.drop		= dquot_drop,			/* mandatory */
+	.initialize	= dquot_initialize,
+	.drop		= dquot_drop,
 	.alloc_space	= dquot_alloc_space,
 	.alloc_inode	= dquot_alloc_inode,
 	.free_space	= dquot_free_space,
 	.free_inode	= dquot_free_inode,
 	.transfer	= dquot_transfer,
-	.write_dquot	= commit_dqblk
+	.write_dquot	= dquot_commit,
+	.mark_dirty	= dquot_mark_dquot_dirty,
+	.write_info	= dquot_commit_info
 };
 
-/* Function used by filesystems for initializing the dquot_operations structure */
-void init_dquot_operations(struct dquot_operations *fsdqops)
-{
-	memcpy(fsdqops, &dquot_operations, sizeof(dquot_operations));
-}
-
 static inline void set_enable_flags(struct quota_info *dqopt, int type)
 {
 	switch (type) {
@@ -1127,7 +1230,7 @@ extern void remove_dquot_ref(struct supe
 /*
  * Turn quota off on a device. type == -1 ==> quotaoff for all types (umount)
  */
-int vfs_quota_off(struct super_block *sb, int type)
+static int __vfs_quota_off(struct super_block *sb, int type, int onmount)
 {
 	int cnt;
 	struct quota_info *dqopt = sb_dqopt(sb);
@@ -1152,17 +1255,14 @@ int vfs_quota_off(struct super_block *sb
 		 * Now all dquots should be invalidated, all writes done so we should be only
 		 * users of the info. No locks needed.
 		 */
-		if (info_dirty(&dqopt->info[cnt])) {
-			down(&dqopt->dqio_sem);
-			dqopt->ops[cnt]->write_file_info(sb, cnt);
-			up(&dqopt->dqio_sem);
-		}
+		if (info_dirty(&dqopt->info[cnt]))
+			sb->dq_op->write_info(sb, cnt);
 		if (dqopt->ops[cnt]->free_file_info)
 			dqopt->ops[cnt]->free_file_info(sb, cnt);
 		put_quota_format(dqopt->info[cnt].dqi_format);
 
 		fput(dqopt->files[cnt]);
-		dqopt->files[cnt] = (struct file *)NULL;
+		dqopt->files[cnt] = NULL;
 		dqopt->info[cnt].dqi_flags = 0;
 		dqopt->info[cnt].dqi_igrace = 0;
 		dqopt->info[cnt].dqi_bgrace = 0;
@@ -1174,32 +1274,39 @@ out:
 	return 0;
 }
 
-int vfs_quota_on(struct super_block *sb, int type, int format_id, char *path)
+int vfs_quota_off(struct super_block *sb, int type)
 {
-	struct file *f;
+	return __vfs_quota_off(sb, type, 0);
+}
+
+int vfs_quota_off_mount(struct super_block *sb, int type)
+{
+	return __vfs_quota_off(sb, type, 1);
+}
+
+/*
+ *	Turn quotas on on a device
+ */
+
+/* Helper function when we already have file open */
+static int vfs_quota_on_file(struct file *f, int type, int format_id)
+{
+	struct quota_format_type *fmt = find_quota_format(format_id);
 	struct inode *inode;
+	struct super_block *sb = f->f_dentry->d_sb;
 	struct quota_info *dqopt = sb_dqopt(sb);
-	struct quota_format_type *fmt = find_quota_format(format_id);
 	int error;
 	unsigned int oldflags;
 
 	if (!fmt)
 		return -ESRCH;
-	f = filp_open(path, O_RDWR, 0600);
-	if (IS_ERR(f)) {
-		error = PTR_ERR(f);
-		goto out_fmt;
-	}
 	error = -EIO;
 	if (!f->f_op || !f->f_op->read || !f->f_op->write)
-		goto out_f;
-	error = security_quota_on(f);
-	if (error)
-		goto out_f;
+		goto out_fmt;
 	inode = f->f_dentry->d_inode;
 	error = -EACCES;
 	if (!S_ISREG(inode->i_mode))
-		goto out_f;
+		goto out_fmt;
 
 	down(&dqopt->dqonoff_sem);
 	down_write(&dqopt->dqptr_sem);
@@ -1238,14 +1345,57 @@ out_file_init:
 out_lock:
 	up_write(&dqopt->dqptr_sem);
 	up(&dqopt->dqonoff_sem);
-out_f:
-	filp_close(f, NULL);
 out_fmt:
 	put_quota_format(fmt);
 
 	return error; 
 }
 
+/* Actual function called from quotactl() */
+int vfs_quota_on(struct super_block *sb, int type, int format_id, char *path)
+{
+	struct file *f;
+	int error;
+
+	f = filp_open(path, O_RDWR, 0600);
+	if (IS_ERR(f))
+		return PTR_ERR(f);
+	error = security_quota_on(f);
+	if (error)
+		goto out_f;
+	error = vfs_quota_on_file(f, type, format_id);
+	if (!error)
+		return 0;
+out_f:
+	filp_close(f, NULL);
+	return error;
+}
+
+/*
+ * Function used by filesystems when filp_open() would fail (filesystem is being mounted now)
+ * We will use a private file structure. Caller is responsible that it's IO functions won't
+ * need vfsmnt structure or some dentry tricks...
+ */
+int vfs_quota_on_mount(int type, int format_id, struct dentry *dentry)
+{
+	struct file *f;
+	int error;
+
+	dget(dentry);	/* Get a reference for struct file */
+	f = dentry_open(dentry, NULL, O_RDWR);
+	if (IS_ERR(f)) {
+		error = PTR_ERR(f);
+		goto out_dentry;
+	}
+	error = vfs_quota_on_file(f, type, format_id);
+	if (!error)
+		return 0;
+	fput(f);
+out_dentry:
+	dput(dentry);
+	return error;
+}
+
 /* Generic routine for getting common part of quota structure */
 static void do_get_dqblk(struct dquot *dquot, struct if_dqblk *di)
 {
@@ -1329,8 +1479,8 @@ static void do_set_dqblk(struct dquot *d
 		clear_bit(DQ_FAKE_B, &dquot->dq_flags);
 	else
 		set_bit(DQ_FAKE_B, &dquot->dq_flags);
-	mark_dquot_dirty(dquot);
 	spin_unlock(&dq_data_lock);
+	mark_dquot_dirty(dquot);
 }
 
 int vfs_set_dqblk(struct super_block *sb, int type, qid_t id, struct if_dqblk *di)
@@ -1387,9 +1537,11 @@ int vfs_set_dqinfo(struct super_block *s
 		mi->dqi_igrace = ii->dqi_igrace;
 	if (ii->dqi_valid & IIF_FLAGS)
 		mi->dqi_flags = (mi->dqi_flags & ~DQF_MASK) | (ii->dqi_flags & DQF_MASK);
-	mark_info_dirty(mi);
 	spin_unlock(&dq_data_lock);
 	up_read(&sb_dqopt(sb)->dqptr_sem);
+	mark_info_dirty(sb, type);
+	/* Force write to disk */
+	sb->dq_op->write_info(sb, type);
 	return 0;
 }
 
@@ -1520,4 +1672,3 @@ EXPORT_SYMBOL(unregister_quota_format);
 EXPORT_SYMBOL(dqstats);
 EXPORT_SYMBOL(dq_list_lock);
 EXPORT_SYMBOL(dq_data_lock);
-EXPORT_SYMBOL(init_dquot_operations);
--- diff/fs/eventpoll.c	2004-02-18 08:54:12.000000000 +0000
+++ source/fs/eventpoll.c	2004-02-23 13:56:46.000000000 +0000
@@ -27,6 +27,7 @@
 #include <linux/list.h>
 #include <linux/hash.h>
 #include <linux/spinlock.h>
+#include <linux/syscalls.h>
 #include <linux/rwsem.h>
 #include <linux/wait.h>
 #include <linux/eventpoll.h>
@@ -1155,8 +1156,7 @@ static int ep_modify(struct eventpoll *e
 				if (waitqueue_active(&ep->poll_wait))
 					pwake++;
 			}
-		} else if (EP_IS_LINKED(&epi->rdllink))
-			EP_LIST_DEL(&epi->rdllink);
+		}
 	}
 
 	write_unlock_irqrestore(&ep->lock, flags);
--- diff/fs/exec.c	2004-02-09 10:36:12.000000000 +0000
+++ source/fs/exec.c	2004-02-23 13:56:46.000000000 +0000
@@ -44,6 +44,7 @@
 #include <linux/ptrace.h>
 #include <linux/mount.h>
 #include <linux/security.h>
+#include <linux/syscalls.h>
 #include <linux/rmap-locking.h>
 
 #include <asm/uaccess.h>
@@ -326,7 +327,7 @@ void put_dirty_page(struct task_struct *
 	set_pte(pte, pte_mkdirty(pte_mkwrite(mk_pte(page, prot))));
 	pte_chain = page_add_rmap(page, pte, pte_chain);
 	pte_unmap(pte);
-	tsk->mm->rss++;
+	inc_rss(tsk->mm, page);
 	spin_unlock(&tsk->mm->page_table_lock);
 
 	/* no need for flush_tlb */
@@ -832,7 +833,8 @@ int flush_old_exec(struct linux_binprm *
 	flush_thread();
 
 	if (bprm->e_uid != current->euid || bprm->e_gid != current->egid || 
-	    permission(bprm->file->f_dentry->d_inode,MAY_READ, NULL))
+	    permission(bprm->file->f_dentry->d_inode,MAY_READ, NULL) ||
+	    (bprm->interp_flags & BINPRM_FLAGS_ENFORCE_NONDUMP))
 		current->mm->dumpable = 0;
 
 	/* An exec changes our domain. We are no longer part of the thread
@@ -1105,6 +1107,7 @@ int do_execve(char * filename,
 	bprm.file = file;
 	bprm.filename = filename;
 	bprm.interp = filename;
+	bprm.interp_flags = 0;
 	bprm.sh_bang = 0;
 	bprm.loader = 0;
 	bprm.exec = 0;
@@ -1386,7 +1389,7 @@ int do_coredump(long signr, int exit_cod
 		goto fail_unlock;
 
  	format_corename(corename, core_pattern, signr);
-	file = filp_open(corename, O_CREAT | 2 | O_NOFOLLOW, 0600);
+	file = filp_open(corename, O_CREAT | 2 | O_NOFOLLOW | O_LARGEFILE, 0600);
 	if (IS_ERR(file))
 		goto fail_unlock;
 	inode = file->f_dentry->d_inode;
--- diff/fs/ext2/acl.c	2003-10-27 09:20:38.000000000 +0000
+++ source/fs/ext2/acl.c	2004-02-23 13:56:46.000000000 +0000
@@ -322,7 +322,8 @@ check_groups:
 
 check_capabilities:
 	/* Allowed to override Discretionary Access Control? */
-	if ((mask & (MAY_READ|MAY_WRITE)) || (inode->i_mode & S_IXUGO))
+	if (!(mask & MAY_EXEC) ||
+	    (inode->i_mode & S_IXUGO) || S_ISDIR(inode->i_mode))
 		if (capable(CAP_DAC_OVERRIDE))
 			return 0;
 	/* Read and search granted if capable(CAP_DAC_READ_SEARCH) */
--- diff/fs/ext3/acl.c	2003-10-27 09:20:38.000000000 +0000
+++ source/fs/ext3/acl.c	2004-02-23 13:56:46.000000000 +0000
@@ -327,7 +327,8 @@ check_groups:
 
 check_capabilities:
 	/* Allowed to override Discretionary Access Control? */
-	if ((mask & (MAY_READ|MAY_WRITE)) || (inode->i_mode & S_IXUGO))
+	if (!(mask & MAY_EXEC) ||
+	    (inode->i_mode & S_IXUGO) || S_ISDIR(inode->i_mode))
 		if (capable(CAP_DAC_OVERRIDE))
 			return 0;
 	/* Read and search granted if capable(CAP_DAC_READ_SEARCH) */
--- diff/fs/ext3/balloc.c	2004-01-19 10:22:59.000000000 +0000
+++ source/fs/ext3/balloc.c	2004-02-23 13:56:46.000000000 +0000
@@ -239,9 +239,10 @@ do_more:
 		BUFFER_TRACE(bitmap_bh, "clear bit");
 		if (!ext3_clear_bit_atomic(sb_bgl_lock(sbi, block_group),
 						bit + i, bitmap_bh->b_data)) {
-			ext3_error (sb, __FUNCTION__,
-				      "bit already cleared for block %lu", 
-				      block + i);
+			jbd_unlock_bh_state(bitmap_bh);
+			ext3_error(sb, __FUNCTION__,
+				"bit already cleared for block %lu", block + i);
+			jbd_lock_bh_state(bitmap_bh);
 			BUFFER_TRACE(bitmap_bh, "bit already cleared");
 		} else {
 			dquot_freed_blocks++;
--- diff/fs/ext3/inode.c	2004-02-09 10:36:12.000000000 +0000
+++ source/fs/ext3/inode.c	2004-02-23 13:56:46.000000000 +0000
@@ -2772,9 +2772,25 @@ int ext3_setattr(struct dentry *dentry, 
 
 	if ((ia_valid & ATTR_UID && attr->ia_uid != inode->i_uid) ||
 		(ia_valid & ATTR_GID && attr->ia_gid != inode->i_gid)) {
+		handle_t *handle;
+
+		handle = ext3_journal_start(inode, 2*EXT3_QUOTA_TRANS_BLOCKS+3);
+		if (IS_ERR(handle)) {
+			error = PTR_ERR(handle);
+			goto err_out;
+		}
 		error = DQUOT_TRANSFER(inode, attr) ? -EDQUOT : 0;
-		if (error)
+		if (error) {
+			ext3_journal_stop(handle);
 			return error;
+		}
+		/* Update corresponding info in inode so that everything is in one transaction */
+		if (attr->ia_valid & ATTR_UID)
+			inode->i_uid = attr->ia_uid;
+		if (attr->ia_valid & ATTR_GID)
+			inode->i_gid = attr->ia_gid;
+		error = ext3_mark_inode_dirty(handle, inode);
+		ext3_journal_stop(handle);
 	}
 
 	if (S_ISREG(inode->i_mode) &&
@@ -2853,7 +2869,9 @@ int ext3_writepage_trans_blocks(struct i
 		ret = 2 * (bpp + indirects) + 2;
 
 #ifdef CONFIG_QUOTA
-	ret += 2 * EXT3_SINGLEDATA_TRANS_BLOCKS;
+	/* We know that structure was already allocated during DQUOT_INIT so
+	 * we will be updating only the data blocks + inodes */
+	ret += 2*EXT3_QUOTA_TRANS_BLOCKS;
 #endif
 
 	return ret;
--- diff/fs/ext3/namei.c	2004-02-18 08:54:12.000000000 +0000
+++ source/fs/ext3/namei.c	2004-02-23 13:56:46.000000000 +0000
@@ -1974,6 +1974,8 @@ static int ext3_rmdir (struct inode * di
 	struct ext3_dir_entry_2 * de;
 	handle_t *handle;
 
+	/* Initialize quotas before so that eventual writes goes in separate transaction */
+	DQUOT_INIT(dentry->d_inode);
 	handle = ext3_journal_start(dir, EXT3_DELETE_TRANS_BLOCKS);
 	if (IS_ERR(handle))
 		return PTR_ERR(handle);
@@ -1987,7 +1989,6 @@ static int ext3_rmdir (struct inode * di
 		handle->h_sync = 1;
 
 	inode = dentry->d_inode;
-	DQUOT_INIT(inode);
 
 	retval = -EIO;
 	if (le32_to_cpu(de->inode) != inode->i_ino)
@@ -2031,6 +2032,8 @@ static int ext3_unlink(struct inode * di
 	struct ext3_dir_entry_2 * de;
 	handle_t *handle;
 
+	/* Initialize quotas before so that eventual writes goes in separate transaction */
+	DQUOT_INIT(dentry->d_inode);
 	handle = ext3_journal_start(dir, EXT3_DELETE_TRANS_BLOCKS);
 	if (IS_ERR(handle))
 		return PTR_ERR(handle);
@@ -2044,7 +2047,6 @@ static int ext3_unlink(struct inode * di
 		goto end_unlink;
 
 	inode = dentry->d_inode;
-	DQUOT_INIT(inode);
 
 	retval = -EIO;
 	if (le32_to_cpu(de->inode) != inode->i_ino)
@@ -2172,6 +2174,9 @@ static int ext3_rename (struct inode * o
 
 	old_bh = new_bh = dir_bh = NULL;
 
+	/* Initialize quotas before so that eventual writes goes in separate transaction */
+	if (new_dentry->d_inode)
+		DQUOT_INIT(new_dentry->d_inode);
 	handle = ext3_journal_start(old_dir, 2 * EXT3_DATA_TRANS_BLOCKS +
 			 		EXT3_INDEX_EXTRA_TRANS_BLOCKS + 2);
 	if (IS_ERR(handle))
@@ -2198,8 +2203,6 @@ static int ext3_rename (struct inode * o
 		if (!new_inode) {
 			brelse (new_bh);
 			new_bh = NULL;
-		} else {
-			DQUOT_INIT(new_inode);
 		}
 	}
 	if (S_ISDIR(old_inode->i_mode)) {
--- diff/fs/ext3/super.c	2004-02-09 10:36:12.000000000 +0000
+++ source/fs/ext3/super.c	2004-02-23 13:56:46.000000000 +0000
@@ -32,6 +32,9 @@
 #include <linux/buffer_head.h>
 #include <linux/vfs.h>
 #include <linux/random.h>
+#include <linux/mount.h>
+#include <linux/namei.h>
+#include <linux/quotaops.h>
 #include <asm/uaccess.h>
 #include "xattr.h"
 #include "acl.h"
@@ -325,7 +328,7 @@ static struct block_device *ext3_blkdev_
 	struct block_device *bdev;
 	char b[BDEVNAME_SIZE];
 
-	bdev = open_by_devnum(dev, FMODE_READ|FMODE_WRITE, BDEV_FS);
+	bdev = open_by_devnum(dev, FMODE_READ|FMODE_WRITE);
 	if (IS_ERR(bdev))
 		goto fail;
 	return bdev;
@@ -342,7 +345,7 @@ fail:
 static int ext3_blkdev_put(struct block_device *bdev)
 {
 	bd_release(bdev);
-	return blkdev_put(bdev, BDEV_FS);
+	return blkdev_put(bdev);
 }
 
 static int ext3_blkdev_remove(struct ext3_sb_info *sbi)
@@ -504,7 +507,41 @@ static void ext3_clear_inode(struct inod
 # define ext3_clear_inode NULL
 #endif
 
-static struct dquot_operations ext3_qops;
+#ifdef CONFIG_QUOTA
+
+#define QTYPE2NAME(t) ((t)==USRQUOTA?"user":"group")
+#define QTYPE2MOPT(on, t) ((t)==USRQUOTA?((on)##USRJQUOTA):((on)##GRPJQUOTA))
+
+static int ext3_write_dquot(struct dquot *dquot, int init);
+static int ext3_mark_dquot_dirty(struct dquot *dquot);
+static int ext3_write_info(struct super_block *sb, int type);
+static int ext3_quota_on(struct super_block *sb, int type, int format_id, char *path);
+static int ext3_quota_on_mount(struct super_block *sb, int type);
+static int ext3_quota_off_mount(struct super_block *sb, int type);
+
+static struct dquot_operations ext3_quota_operations = {
+	.initialize	= dquot_initialize,
+	.drop		= dquot_drop,
+	.alloc_space	= dquot_alloc_space,
+	.alloc_inode	= dquot_alloc_inode,
+	.free_space	= dquot_free_space,
+	.free_inode	= dquot_free_inode,
+	.transfer	= dquot_transfer,
+	.write_dquot	= ext3_write_dquot,
+	.mark_dirty	= ext3_mark_dquot_dirty,
+	.write_info	= ext3_write_info
+};
+
+static struct quotactl_ops ext3_qctl_operations = {
+	.quota_on	= ext3_quota_on,
+	.quota_off	= vfs_quota_off,
+	.quota_sync	= vfs_quota_sync,
+	.get_info	= vfs_get_dqinfo,
+	.set_info	= vfs_set_dqinfo,
+	.get_dqblk	= vfs_get_dqblk,
+	.set_dqblk	= vfs_set_dqblk
+};
+#endif
 
 static struct super_operations ext3_sops = {
 	.alloc_inode	= ext3_alloc_inode,
@@ -536,6 +573,8 @@ enum {
 	Opt_user_xattr, Opt_nouser_xattr, Opt_acl, Opt_noacl, Opt_noload,
 	Opt_commit, Opt_journal_update, Opt_journal_inum,
 	Opt_abort, Opt_data_journal, Opt_data_ordered, Opt_data_writeback,
+	Opt_usrjquota, Opt_grpjquota, Opt_offusrjquota, Opt_offgrpjquota,
+	Opt_jqfmt_vfsold, Opt_jqfmt_vfsv0,
 	Opt_ignore, Opt_err,
 };
 
@@ -571,6 +610,12 @@ static match_table_t tokens = {
 	{Opt_data_journal, "data=journal"},
 	{Opt_data_ordered, "data=ordered"},
 	{Opt_data_writeback, "data=writeback"},
+	{Opt_offusrjquota, "usrjquota="},
+	{Opt_usrjquota, "usrjquota=%s"},
+	{Opt_offgrpjquota, "grpjquota="},
+	{Opt_grpjquota, "grpjquota=%s"},
+	{Opt_jqfmt_vfsold, "jqfmt=vfsold"},
+	{Opt_jqfmt_vfsv0, "jqfmt=vfsv0"},
 	{Opt_ignore, "grpquota"},
 	{Opt_ignore, "noquota"},
 	{Opt_ignore, "quota"},
@@ -598,13 +643,17 @@ static unsigned long get_sb_block(void *
 	return sb_block;
 }
 
-static int parse_options (char * options, struct ext3_sb_info *sbi,
+static int parse_options (char * options, struct super_block *sb,
 			  unsigned long * inum, int is_remount)
 {
+	struct ext3_sb_info *sbi = EXT3_SB(sb);
 	char * p;
 	substring_t args[MAX_OPT_ARGS];
 	int data_opt = 0;
 	int option;
+#ifdef CONFIG_QUOTA
+	int qtype;
+#endif
 
 	if (!options)
 		return 1;
@@ -759,6 +808,64 @@ static int parse_options (char * options
 				sbi->s_mount_opt |= data_opt;
 			}
 			break;
+#ifdef CONFIG_QUOTA
+		case Opt_usrjquota:
+			qtype = USRQUOTA;
+			goto set_qf_name;
+		case Opt_grpjquota:
+			qtype = GRPQUOTA;
+set_qf_name:
+			if (sb_any_quota_enabled(sb)) {
+				printk(KERN_ERR "EXT3-fs: Cannot change journalled quota options when quota turned on.\n");
+				return 0;
+			}
+			if (sbi->s_qf_names[qtype]) {
+				printk(KERN_ERR "EXT3-fs: %s quota file already specified.\n", QTYPE2NAME(qtype));
+				return 0;
+			}
+			sbi->s_qf_names[qtype] = match_strdup(&args[0]);
+			if (!sbi->s_qf_names[qtype]) {
+				printk(KERN_ERR "EXT3-fs: not enough memory for storing quotafile name.\n");
+				return 0;
+			}
+			if (strchr(sbi->s_qf_names[qtype], '/')) {
+				printk(KERN_ERR "EXT3-fs: quotafile must be on filesystem root.\n");
+				kfree(sbi->s_qf_names[qtype]);
+				sbi->s_qf_names[qtype] = NULL;
+				return 0;
+			}
+			break;
+		case Opt_offusrjquota:
+			qtype = USRQUOTA;
+			goto clear_qf_name;
+		case Opt_offgrpjquota:
+			qtype = GRPQUOTA;
+clear_qf_name:
+			if (sb_any_quota_enabled(sb)) {
+				printk(KERN_ERR "EXT3-fs: Cannot change journalled quota options when quota turned on.\n");
+				return 0;
+			}
+			if (sbi->s_qf_names[qtype]) {
+				kfree(sbi->s_qf_names[qtype]);
+				sbi->s_qf_names[qtype] = NULL;
+			}
+			break;
+		case Opt_jqfmt_vfsold:
+			sbi->s_jquota_fmt = QFMT_VFS_OLD;
+			break;
+		case Opt_jqfmt_vfsv0:
+			sbi->s_jquota_fmt = QFMT_VFS_V0;
+			break;
+#else
+		case Opt_usrjquota:
+		case Opt_grpjquota:
+		case Opt_offusrjquota:
+		case Opt_offgrpjquota:
+		case Opt_jqfmt_vfsold:
+		case Opt_jqfmt_vfsv0:
+			printk (KERN_ERR "EXT3-fs: journalled quota options not supported.\n");
+			break;
+#endif
 		case Opt_abort:
 			set_opt(sbi->s_mount_opt, ABORT);
 			break;
@@ -771,6 +878,12 @@ static int parse_options (char * options
 			return 0;
 		}
 	}
+#ifdef CONFIG_QUOTA
+	if (!sbi->s_jquota_fmt && (sbi->s_qf_names[0] || sbi->s_qf_names[1])) {
+		printk(KERN_ERR "EXT3-fs: journalled quota format not specified.\n");
+		return 0;
+	}
+#endif
 
 	return 1;
 }
@@ -929,7 +1042,12 @@ static void ext3_orphan_cleanup (struct 
 				 struct ext3_super_block * es)
 {
 	unsigned int s_flags = sb->s_flags;
-	int nr_orphans = 0, nr_truncates = 0;
+	int nr_orphans = 0;
+	int nr_truncates = 0;
+#ifdef CONFIG_QUOTA
+	int i;
+#endif
+
 	if (!es->s_last_orphan) {
 		jbd_debug(4, "no orphan inodes to clean up\n");
 		return;
@@ -949,6 +1067,19 @@ static void ext3_orphan_cleanup (struct 
 		       sb->s_id);
 		sb->s_flags &= ~MS_RDONLY;
 	}
+#ifdef CONFIG_QUOTA
+	sb->s_flags |= MS_ACTIVE;	/* Needed for iput() to work correctly
+					   and not trash data */
+	/* Turn on quotas so that they are updated correctly */
+	for (i = 0; i < MAXQUOTAS; i++) {
+		if (EXT3_SB(sb)->s_qf_names[i]) {
+			int ret = ext3_quota_on_mount(sb, i);
+			if (ret < 0)
+				printk(KERN_ERR "EXT3-fs: Cannot turn on "
+					"journalled quota: error %d\n", ret);
+		}
+	}
+#endif
 
 	while (es->s_last_orphan) {
 		struct inode *inode;
@@ -960,6 +1091,7 @@ static void ext3_orphan_cleanup (struct 
 		}
 
 		list_add(&EXT3_I(inode)->i_orphan, &EXT3_SB(sb)->s_orphan);
+		DQUOT_INIT(inode);
 		if (inode->i_nlink) {
 			printk(KERN_DEBUG
 				"%s: truncating inode %ld to %Ld bytes\n",
@@ -987,6 +1119,13 @@ static void ext3_orphan_cleanup (struct 
 	if (nr_truncates)
 		printk(KERN_INFO "EXT3-fs: %s: %d truncate%s cleaned up\n",
 		       sb->s_id, PLURAL(nr_truncates));
+#ifdef CONFIG_QUOTA
+	/* Turn quotas off */
+	for (i = 0; i < MAXQUOTAS; i++) {
+		if (sb_dqopt(sb)->files[i])
+			ext3_quota_off_mount(sb, i);
+	}
+#endif
 	sb->s_flags = s_flags; /* Restore MS_RDONLY status */
 }
 
@@ -1116,7 +1255,7 @@ static int ext3_fill_super (struct super
 	sbi->s_resuid = le16_to_cpu(es->s_def_resuid);
 	sbi->s_resgid = le16_to_cpu(es->s_def_resgid);
 
-	if (!parse_options ((char *) data, sbi, &journal_inum, 0))
+	if (!parse_options ((char *) data, sb, &journal_inum, 0))
 		goto failed_mount;
 
 	sb->s_flags |= MS_ONE_SECOND;
@@ -1295,7 +1434,10 @@ static int ext3_fill_super (struct super
 	 */
 	sb->s_op = &ext3_sops;
 	sb->s_export_op = &ext3_export_ops;
-	sb->dq_op = &ext3_qops;
+#ifdef CONFIG_QUOTA
+	sb->s_qcop = &ext3_qctl_operations;
+	sb->dq_op = &ext3_quota_operations;
+#endif
 	INIT_LIST_HEAD(&sbi->s_orphan); /* unlinked but open files */
 
 	sb->s_root = 0;
@@ -1404,6 +1546,11 @@ failed_mount2:
 		brelse(sbi->s_group_desc[i]);
 	kfree(sbi->s_group_desc);
 failed_mount:
+#ifdef CONFIG_QUOTA
+	for (i = 0; i < MAXQUOTAS; i++)
+		if (sbi->s_qf_names[i])
+			kfree(sbi->s_qf_names[i]);
+#endif
 	ext3_blkdev_remove(sbi);
 	brelse(bh);
 out_fail:
@@ -1487,7 +1634,7 @@ static journal_t *ext3_get_dev_journal(s
 	if (bd_claim(bdev, sb)) {
 		printk(KERN_ERR
 		        "EXT3: failed to claim external journal device.\n");
-		blkdev_put(bdev, BDEV_FS);
+		blkdev_put(bdev);
 		return NULL;
 	}
 
@@ -1830,7 +1977,7 @@ int ext3_remount (struct super_block * s
 	/*
 	 * Allow the "check" option to be passed as a remount option.
 	 */
-	if (!parse_options(data, sbi, &tmp, 1))
+	if (!parse_options(data, sb, &tmp, 1))
 		return -EINVAL;
 
 	if (sbi->s_mount_opt & EXT3_MOUNT_ABORT)
@@ -1938,8 +2085,9 @@ int ext3_statfs (struct super_block * sb
 	return 0;
 }
 
-/* Helper function for writing quotas on sync - we need to start transaction before quota file
- * is locked for write. Otherwise the are possible deadlocks:
+/*
+ * Helper function for writing quotas on sync - we need to start transaction
+ * before quota file is locked for write. Otherwise the are possible deadlocks:
  * Process 1                         Process 2
  * ext3_create()                     quota_sync()
  *   journal_start()                   write_dquot()
@@ -1950,45 +2098,128 @@ int ext3_statfs (struct super_block * sb
 
 #ifdef CONFIG_QUOTA
 
-/* Blocks: (2 data blocks) * (3 indirect + 1 descriptor + 1 bitmap) + superblock */
-#define EXT3_OLD_QFMT_BLOCKS 11
-/* Blocks: quota info + (4 pointer blocks + 1 entry block) * (3 indirect + 1 descriptor + 1 bitmap) + superblock */
-#define EXT3_V0_QFMT_BLOCKS 27
+static inline int writes_to_blocks(int writes)
+{
+	return writes*5+2;
+}
 
-static int (*old_write_dquot)(struct dquot *dquot);
+static inline struct inode *dquot_to_inode(struct dquot *dquot)
+{
+	return sb_dqopt(dquot->dq_sb)->files[dquot->dq_type]->f_dentry->d_inode;
+}
 
-static int ext3_write_dquot(struct dquot *dquot)
+static int ext3_write_dquot(struct dquot *dquot, int init)
 {
-	int nblocks;
-	int ret;
-	int err;
+	int ret, err;
 	handle_t *handle;
-	struct quota_info *dqops = sb_dqopt(dquot->dq_sb);
-	struct inode *qinode;
 
-	switch (dqops->info[dquot->dq_type].dqi_format->qf_fmt_id) {
-		case QFMT_VFS_OLD:
-			nblocks = EXT3_OLD_QFMT_BLOCKS;
-			break;
-		case QFMT_VFS_V0:
-			nblocks = EXT3_V0_QFMT_BLOCKS;
-			break;
-		default:
-			nblocks = EXT3_MAX_TRANS_DATA;
+	handle = ext3_journal_start(dquot_to_inode(dquot),
+		init ? EXT3_QUOTA_INIT_BLOCKS : EXT3_QUOTA_TRANS_BLOCKS);
+	if (IS_ERR(handle)) {
+		ret = PTR_ERR(handle);
+		goto out;
 	}
-	qinode = dqops->files[dquot->dq_type]->f_dentry->d_inode;
-	handle = ext3_journal_start(qinode, nblocks);
+	ret = dquot_commit(dquot, init);
+	err = ext3_journal_stop(handle);
+	if (!ret)
+		ret = err;
+out:
+	return ret;
+}
+
+static int ext3_mark_dquot_dirty(struct dquot * dquot)
+{
+	/* Are we journalling quotas? */
+	if (EXT3_SB(dquot->dq_sb)->s_qf_names[0] ||
+			EXT3_SB(dquot->dq_sb)->s_qf_names[1])
+		return ext3_write_dquot(dquot, 0);
+	else
+		return dquot_mark_dquot_dirty(dquot);
+}
+
+static int ext3_write_info(struct super_block *sb, int type)
+{
+	int ret, err;
+	handle_t *handle;
+
+	handle = ext3_journal_start(sb->s_root->d_inode, writes_to_blocks(1));
 	if (IS_ERR(handle)) {
 		ret = PTR_ERR(handle);
 		goto out;
 	}
-	ret = old_write_dquot(dquot);
+	ret = dquot_commit_info(sb, type);
 	err = ext3_journal_stop(handle);
-	if (ret == 0)
+	if (!ret)
 		ret = err;
 out:
 	return ret;
 }
+
+/*
+ * Turn on quotas during mount time - we need to find the quota file and such.
+ */
+static int ext3_quota_on_mount(struct super_block *sb, int type)
+{
+	int err;
+	struct dentry *dentry;
+	struct qstr name = { .name = EXT3_SB(sb)->s_qf_names[type],
+			     .hash = 0,
+			     .len = strlen(EXT3_SB(sb)->s_qf_names[type])};
+
+	dentry = lookup_hash(&name, sb->s_root);
+	if (IS_ERR(dentry))
+		return PTR_ERR(dentry);
+	err = vfs_quota_on_mount(type, EXT3_SB(sb)->s_jquota_fmt, dentry);
+	if (err)
+		dput(dentry);
+	/*
+	 * We keep the dentry reference if everything went ok - we drop it on
+	 * quota_off time
+	 */
+	return err;
+}
+
+/* Turn quotas off during mount time */
+static int ext3_quota_off_mount(struct super_block *sb, int type)
+{
+	int err;
+	struct dentry *dentry;
+
+	dentry = sb_dqopt(sb)->files[type]->f_dentry;
+	err = vfs_quota_off_mount(sb, type);
+
+	/* We invalidate dentry - it has at least wrong hash... */
+	d_invalidate(dentry);
+	dput(dentry);
+	return err;
+}
+
+static int
+ext3_quota_on(struct super_block *sb, int type, int format_id, char *path)
+{
+	int err;
+	struct nameidata nd;
+
+	if (!EXT3_SB(sb)->s_qf_names[0] && !EXT3_SB(sb)->s_qf_names[1]) {
+		/* Not journalling quota? */
+		return vfs_quota_on(sb, type, format_id, path);
+	}
+	err = path_lookup(path, LOOKUP_FOLLOW, &nd);
+	if (err)
+		return err;
+	if (nd.mnt->mnt_sb != sb)	/* Quotafile not on the same fs? */
+		return -EXDEV;
+	if (nd.dentry->d_parent->d_inode != sb->s_root->d_inode)
+		/* Quotafile not of fs root? */
+		printk(KERN_WARNING "EXT3-fs: Quota file not on filesystem "
+				"root. Journalled quota will not work\n");
+	if (!ext3_should_journal_data(nd.dentry->d_inode))
+		printk(KERN_WARNING "EXT3-fs: Quota file does not have "
+			"data-journalling. Journalled quota will not work\n");
+	path_release(&nd);
+	return vfs_quota_on(sb, type, format_id, path);
+}
+
 #endif
 
 static struct super_block *ext3_get_sb(struct file_system_type *fs_type,
@@ -2013,11 +2244,6 @@ static int __init init_ext3_fs(void)
 	err = init_inodecache();
 	if (err)
 		goto out1;
-#ifdef CONFIG_QUOTA
-	init_dquot_operations(&ext3_qops);
-	old_write_dquot = ext3_qops.write_dquot;
-	ext3_qops.write_dquot = ext3_write_dquot;
-#endif
         err = register_filesystem(&ext3_fs_type);
 	if (err)
 		goto out;
--- diff/fs/freevxfs/vxfs_bmap.c	2004-02-18 08:54:12.000000000 +0000
+++ source/fs/freevxfs/vxfs_bmap.c	2004-02-23 13:56:46.000000000 +0000
@@ -167,7 +167,9 @@ vxfs_bmap_indir(struct inode *ip, long i
 
 			printk(KERN_INFO "\n\nTYPED_DEV4 detected!\n");
 			printk(KERN_INFO "block: %Lu\tsize: %Ld\tdev: %d\n",
-				typ4->vd4_block, typ4->vd4_size, typ4->vd4_dev);
+			       (unsigned long long) typ4->vd4_block,
+			       (unsigned long long) typ4->vd4_size,
+			       typ4->vd4_dev);
 			goto fail;
 		}
 		default:
@@ -228,7 +230,9 @@ vxfs_bmap_typed(struct inode *ip, long i
 
 			printk(KERN_INFO "\n\nTYPED_DEV4 detected!\n");
 			printk(KERN_INFO "block: %Lu\tsize: %Ld\tdev: %d\n",
-				typ4->vd4_block, typ4->vd4_size, typ4->vd4_dev);
+			       (unsigned long long) typ4->vd4_block,
+			       (unsigned long long) typ4->vd4_size,
+			       typ4->vd4_dev);
 			return 0;
 		}
 		default:
--- diff/fs/fs-writeback.c	2004-02-18 08:54:12.000000000 +0000
+++ source/fs/fs-writeback.c	2004-02-23 13:56:46.000000000 +0000
@@ -22,6 +22,7 @@
 #include <linux/blkdev.h>
 #include <linux/backing-dev.h>
 #include <linux/buffer_head.h>
+#include <linux/ext3_fs_i.h>
 
 extern struct super_block *blockdev_superblock;
 
@@ -187,6 +188,14 @@ __sync_single_inode(struct inode *inode,
 			list_move(&inode->i_list, &inode_in_use);
 		} else {
 			mapping->dirtied_when = 0;
+			if (!strcmp(inode->i_sb->s_type->name, "ext3")) {
+				struct ext3_inode_info *ext3_i;
+				ext3_i = container_of(inode,
+						struct ext3_inode_info,
+						vfs_inode);
+				if (!list_empty(&ext3_i->i_orphan))
+					WARN_ON(1);
+			}
 			list_move(&inode->i_list, &inode_unused);
 		}
 	}
--- diff/fs/hfs/Makefile	2002-12-16 09:26:07.000000000 +0000
+++ source/fs/hfs/Makefile	2004-02-23 13:56:46.000000000 +0000
@@ -4,7 +4,7 @@
 
 obj-$(CONFIG_HFS_FS) += hfs.o
 
-hfs-objs := balloc.o bdelete.o bfind.o bins_del.o binsert.o bitmap.o bitops.o \
-	    bnode.o brec.o btree.o catalog.o dir.o dir_cap.o dir_dbl.o \
-	    dir_nat.o extent.o file.o file_cap.o file_hdr.o inode.o mdb.o \
-            part_tbl.o string.o super.o sysdep.o trans.o version.o
+hfs-objs := bitmap.o bfind.o bnode.o brec.o btree.o \
+	    catalog.o dir.o extent.o inode.o mdb.o \
+            part_tbl.o string.o super.o sysdep.o trans.o
+
--- diff/fs/hfs/bfind.c	2002-10-16 04:27:19.000000000 +0100
+++ source/fs/hfs/bfind.c	2004-02-23 13:56:46.000000000 +0000
@@ -1,322 +1,209 @@
 /*
- * linux/fs/hfs/bfind.c
+ *  linux/fs/hfs/bfind.c
  *
- * Copyright (C) 1995, 1996  Paul H. Hargrove
- * This file may be distributed under the terms of the GNU General Public License.
+ * Copyright (C) 2001
+ * Brad Boyer (flar@allandria.com)
+ * (C) 2003 Ardis Technologies <roman@ardistech.com>
  *
- * This file contains the code to access records in a btree.
- *
- * "XXX" in a comment is a note to myself to consider changing something.
- *
- * In function preconditions the term "valid" applied to a pointer to
- * a structure means that the pointer is non-NULL and the structure it
- * points to has all fields initialized to consistent values.
+ * Search routines for btrees
  */
 
-#include "hfs_btree.h"
+#include <linux/slab.h>
+#include "btree.h"
 
-/*================ Global functions ================*/
-
-/*
- * hfs_brec_relse()
- *
- * Description:
- *   This function releases some of the nodes associated with a brec.
- * Input Variable(s):
- *   struct hfs_brec *brec: pointer to the brec to release some nodes from.
- *   struct hfs_belem *elem: the last node to release or NULL for all
- * Output Variable(s):
- *   NONE
- * Returns:
- *   void
- * Preconditions:
- *   'brec' points to a "valid" (struct hfs_brec)
- * Postconditions: 
- *   All nodes between the indicated node and the beginning of the path
- *    are released.
- */
-void hfs_brec_relse(struct hfs_brec *brec, struct hfs_belem *elem)
+int hfs_find_init(struct hfs_btree *tree, struct hfs_find_data *fd)
 {
-	if (!elem) {
-		elem = brec->bottom;
-	}
+	void *ptr;
 
-	while (brec->top <= elem) {
-		hfs_bnode_relse(&brec->top->bnr);
-		++brec->top;
-	}
+	fd->tree = tree;
+	fd->bnode = NULL;
+	ptr = kmalloc(tree->max_key_len * 2 + 4, GFP_KERNEL);
+	if (!ptr)
+		return -ENOMEM;
+	fd->search_key = ptr;
+	fd->key = ptr + tree->max_key_len + 2;
+	dprint(DBG_BNODE_REFS, "find_init: %d (%p)\n", tree->cnid, __builtin_return_address(0));
+	down(&tree->tree_lock);
+	return 0;
 }
 
-/*
- * hfs_bfind()
- *
- * Description:
- *   This function has sole responsibility for locating existing
- *   records in a B-tree.  Given a B-tree and a key it locates the
- *   "greatest" record "less than or equal to" the given key.  The
- *   exact behavior is determined by the bits of the flags variable as
- *   follows:
- *     ('flags' & HFS_LOCK_MASK):
- *      The lock_type argument to be used when calling hfs_bnode_find().
- *     HFS_BFIND_EXACT: only accept an exact match, otherwise take the
- *	"largest" record less than 'target' as a "match"
- *     HFS_BFIND_LOCK: request HFS_LOCK_WRITE access to the node containing
- *	the "matching" record when it is located
- *     HFS_BPATH_FIRST: keep access to internal nodes when accessing their
- *      first child.
- *     HFS_BPATH_OVERFLOW: keep access to internal nodes when the accessed
- *      child is too full to insert another pointer record.
- *     HFS_BPATH_UNDERFLOW: keep access to internal nodes when the accessed
- *      child is would be less than half full upon removing a pointer record.
- * Input Variable(s):
- *   struct hfs_brec *brec: pointer to the (struct hfs_brec) to hold
- *    the search results.
- *   struct hfs_bkey *target: pointer to the (struct hfs_bkey)
- *    to search for
- *   int flags: bitwise OR of flags which determine the function's behavior
- * Output Variable(s):
- *   'brec' contains the results of the search on success or is invalid
- *    on failure.
- * Returns:
- *   int: 0 or 1 on success or an error code on failure:
- *     -EINVAL: one of the input variables was NULL.
- *     -ENOENT: tree is valid but empty or no "matching" record was located.
- *	 If the HFS_BFIND_EXACT bit of 'flags' is not set then the case of no
- *	 matching record will give a 'brec' with a 'record' field of zero
- *	 rather than returning this error.
- *     -EIO: an I/O operation or an assertion about the structure of a
- *       valid B-tree failed indicating corruption of either the B-tree
- *       structure on the disk or one of the in-core structures representing
- *       the B-tree.
- *	 (This could also be returned if a kmalloc() call failed in a
- *	 subordinate routine that is intended to get the data from the
- *	 disk or the buffer cache.)
- * Preconditions:
- *   'brec' is NULL or points to a (struct hfs_brec) with a 'tree' field
- *    which points to a valid (struct hfs_btree).
- *   'target' is NULL or points to a "valid" (struct hfs_bkey)
- * Postconditions:
- *   If 'brec', 'brec->tree' or 'target' is NULL then -EINVAL is returned.
- *   If 'brec', 'brec->tree' and 'target' are non-NULL but the tree
- *   is empty then -ENOENT is returned.
- *   If 'brec', 'brec->tree' and 'target' are non-NULL but the call to
- *   hfs_brec_init() fails then '*brec' is NULL and -EIO is returned.
- *   If 'brec', 'brec->tree' and 'target' are non-NULL and the tree is
- *   non-empty then the tree is searched as follows:
- *    If any call to hfs_brec_next() fails or returns a node that is
- *     neither an index node nor a leaf node then -EIO is returned to
- *     indicate that the B-tree or buffer-cache are corrupted.
- *    If every record in the tree is "greater than" the given key
- *     and the HFS_BFIND_EXACT bit of 'flags' is set then -ENOENT is returned.
- *    If every record in the tree is "greater than" the given key
- *     and the HFS_BFIND_EXACT bit of 'flags' is clear then 'brec' refers
- *     to the first leaf node in the tree and has a 'record' field of
- *     zero, and 1 is returned.
- *    If a "matching" record is located with key "equal to" 'target'
- *     then the return value is 0 and 'brec' indicates the record.
- *    If a "matching" record is located with key "greater than" 'target'
- *     then the behavior is determined as follows:
- *	If the HFS_BFIND_EXACT bit of 'flags' is not set then 1 is returned
- *       and 'brec' refers to the "matching" record.
- *	If the HFS_BFIND_EXACT bit of 'flags' is set then -ENOENT is returned.
- *    If the return value is non-negative and the HFS_BFIND_LOCK bit of
- *     'flags' is set then hfs_brec_lock() is called on the bottom element
- *     of 'brec' before returning.
- */
-int hfs_bfind(struct hfs_brec *brec, struct hfs_btree *tree,
-	      const struct hfs_bkey *target, int flags)
+void hfs_find_exit(struct hfs_find_data *fd)
 {
-	struct hfs_belem *curr;
-	struct hfs_bkey *key;
-	struct hfs_bnode *bn;
-	int result, ntype;
-
-	/* check for invalid arguments */
-	if (!brec || (tree->magic != HFS_BTREE_MAGIC) || !target) {
-		return -EINVAL;
-	}
-
-	/* check for empty tree */
-	if (!tree->root || !tree->bthNRecs) {
-		return -ENOENT;
-	}
-
-	/* start search at root of tree */
-	if (!(curr = hfs_brec_init(brec, tree, flags))) {
-		return -EIO;
-	}
+	hfs_bnode_put(fd->bnode);
+	kfree(fd->search_key);
+	dprint(DBG_BNODE_REFS, "find_exit: %d (%p)\n", fd->tree->cnid, __builtin_return_address(0));
+	up(&fd->tree->tree_lock);
+	fd->tree = NULL;
+}
 
-	/* traverse the tree */
+/* Find the record in bnode that best matches key (not greater than...)*/
+int __hfs_brec_find(struct hfs_bnode *bnode, struct hfs_find_data *fd)
+{
+	int cmpval;
+	u16 off, len, keylen;
+	int rec;
+	int b, e;
+	int res;
+
+	b = 0;
+	e = bnode->num_recs - 1;
+	res = -ENOENT;
 	do {
-		bn = curr->bnr.bn;
-
-		if (!curr->record) {
-			hfs_warn("hfs_bfind: empty bnode\n");
-			hfs_brec_relse(brec, NULL);
-			return -EIO;
-		}
-
-		/* reverse linear search yielding largest key "less
-		   than or equal to" 'target'.
-		   It is questionable whether a binary search would be
-		   significantly faster */
-		do {
-			key = belem_key(curr);
-			if (!key->KeyLen) {
-				hfs_warn("hfs_bfind: empty key\n");
-				hfs_brec_relse(brec, NULL);
-				return -EIO;
-			}
-			result = (tree->compare)(target, key);
-		} while ((result<0) && (--curr->record));
-
-		ntype = bn->ndType;
-
-		/* see if all keys > target */
-		if (!curr->record) {
-			if (bn->ndBLink) {
-				/* at a node other than the left-most at a
-				   given level it means the parent had an
-				   incorrect key for this child */
-				hfs_brec_relse(brec, NULL);
-				hfs_warn("hfs_bfind: corrupted b-tree %d.\n",
-					 (int)ntohl(tree->entry.cnid));
-				return -EIO;
-			}
-			if (flags & HFS_BFIND_EXACT) {
-				/* we're not going to find it */
-				hfs_brec_relse(brec, NULL);
-				return -ENOENT;
-			}
-			if (ntype == ndIndxNode) {
-				/* since we are at the left-most node at
-				   the current level and looking for the
-				   predecessor of 'target' keep going down */
-				curr->record = 1;
-			} else {
-				/* we're at first leaf so fall through */
-			}
+		rec = (e + b) / 2;
+		len = hfs_brec_lenoff(bnode, rec, &off);
+		keylen = hfs_brec_keylen(bnode, rec);
+		hfs_bnode_read(bnode, fd->key, off, keylen);
+		cmpval = bnode->tree->keycmp(fd->key, fd->search_key);
+		if (!cmpval) {
+			e = rec;
+			res = 0;
+			goto done;
 		}
+		if (cmpval < 0)
+			b = rec + 1;
+		else
+			e = rec - 1;
+	} while (b <= e);
+	//printk("%d: %d,%d,%d\n", bnode->this, b, e, rec);
+	if (rec != e && e >= 0) {
+		len = hfs_brec_lenoff(bnode, e, &off);
+		keylen = hfs_brec_keylen(bnode, e);
+		hfs_bnode_read(bnode, fd->key, off, keylen);
+	}
+done:
+	fd->record = e;
+	fd->keyoffset = off;
+	fd->keylength = keylen;
+	fd->entryoffset = off + keylen;
+	fd->entrylength = len - keylen;
+	return res;
+}
 
-		/* get next node if necessary */
-		if ((ntype == ndIndxNode) && !(curr = hfs_brec_next(brec))) {
-			return -EIO;
-		}
-	} while (ntype == ndIndxNode);
-
-	if (key->KeyLen > tree->bthKeyLen) {
-		hfs_warn("hfs_bfind: oversized key\n");
-		hfs_brec_relse(brec, NULL);
-		return -EIO;
-	}
-
-	if (ntype != ndLeafNode) {
-		hfs_warn("hfs_bfind: invalid node type %02x in node %d of "
-		         "btree %d\n", bn->ndType, bn->node,
-		         (int)ntohl(tree->entry.cnid));
-		hfs_brec_relse(brec, NULL);
-		return -EIO;
-	}
-
-	if ((flags & HFS_BFIND_EXACT) && result) {
-		hfs_brec_relse(brec, NULL);
+/* Traverse a B*Tree from the root to a leaf finding best fit to key */
+/* Return allocated copy of node found, set recnum to best record */
+int hfs_brec_find(struct hfs_find_data *fd)
+{
+	struct hfs_btree *tree;
+	struct hfs_bnode *bnode;
+	u32 data, nidx, parent;
+	int height, res;
+
+	tree = fd->tree;
+	if (fd->bnode)
+		hfs_bnode_put(fd->bnode);
+	fd->bnode = NULL;
+	nidx = tree->root;
+	if (!nidx)
 		return -ENOENT;
-	}
-
-	if (!(flags & HFS_BPATH_MASK)) {
-		hfs_brec_relse(brec, brec->bottom-1);
-	}
-
-	if (flags & HFS_BFIND_LOCK) {
-		hfs_brec_lock(brec, brec->bottom);
-	}
+	height = tree->depth;
+	res = 0;
+	parent = 0;
+	for (;;) {
+		bnode = hfs_bnode_find(tree, nidx);
+		if (IS_ERR(bnode)) {
+			res = PTR_ERR(bnode);
+			bnode = NULL;
+			break;
+		}
+		if (bnode->height != height)
+			goto invalid;
+		if (bnode->type != (--height ? HFS_NODE_INDEX : HFS_NODE_LEAF))
+			goto invalid;
+		bnode->parent = parent;
 
-	brec->key  = brec_key(brec);
-	brec->data = bkey_record(brec->key);
+		res = __hfs_brec_find(bnode, fd);
+		if (!height)
+			break;
+		if (fd->record < 0)
+			goto release;
 
-	return result ? 1 : 0;
+		parent = nidx;
+		hfs_bnode_read(bnode, &data, fd->entryoffset, 4);
+		nidx = be32_to_cpu(data);
+		hfs_bnode_put(bnode);
+	}
+	fd->bnode = bnode;
+	return res;
+
+invalid:
+	printk("HFS: inconsistency in B*Tree (%d,%d,%d,%u,%u)\n",
+		height, bnode->height, bnode->type, nidx, parent);
+	res = -EIO;
+release:
+	hfs_bnode_put(bnode);
+	return res;
 }
 
-/*
- * hfs_bsucc()
- *
- * Description:
- *   This function overwrites '*brec' with its successor in the B-tree,
- *   obtaining the same type of access.
- * Input Variable(s):
- *   struct hfs_brec *brec: address of the (struct hfs_brec) to overwrite
- *    with its successor
- * Output Variable(s):
- *   struct hfs_brec *brec: address of the successor of the original
- *    '*brec' or to invalid data
- * Returns:
- *   int: 0 on success, or one of -EINVAL, -EIO, or -EINVAL on failure
- * Preconditions:
- *   'brec' pointers to a "valid" (struct hfs_brec)
- * Postconditions:
- *   If the given '*brec' is not "valid" -EINVAL is returned and
- *    '*brec' is unchanged.
- *   If the given 'brec' is "valid" but has no successor then -ENOENT
- *    is returned and '*brec' is invalid.
- *   If a call to hfs_bnode_find() is necessary to find the successor,
- *    but fails then -EIO is returned and '*brec' is invalid.
- *   If none of the three previous conditions prevents finding the
- *    successor of '*brec', then 0 is returned, and '*brec' is overwritten
- *    with the (struct hfs_brec) for its successor.
- *   In the cases when '*brec' is invalid, the old records is freed.
- */
-int hfs_bsucc(struct hfs_brec *brec, int count)
+int hfs_brec_read(struct hfs_find_data *fd, void *rec, int rec_len)
 {
-	struct hfs_belem *belem;
-	struct hfs_bnode *bn;
+	int res;
 
-	if (!brec || !(belem = brec->bottom) || (belem != brec->top) ||
-	    !(bn = belem->bnr.bn) || (bn->magic != HFS_BNODE_MAGIC) ||
-	    !bn->tree || (bn->tree->magic != HFS_BTREE_MAGIC) ||
-	    !hfs_buffer_ok(bn->buf)) {
-		hfs_warn("hfs_bsucc: invalid/corrupt arguments.\n");
+	res = hfs_brec_find(fd);
+	if (res)
+		return res;
+	if (fd->entrylength > rec_len)
 		return -EINVAL;
-	}
-
-	while (count) {
-		int left = bn->ndNRecs - belem->record;
+	hfs_bnode_read(fd->bnode, rec, fd->entryoffset, fd->entrylength);
+	return 0;
+}
 
-		if (left < count) {
-			struct hfs_bnode_ref old;
-			hfs_u32 node;
-
-			/* Advance to next node */
-			if (!(node = bn->ndFLink)) {
-				hfs_brec_relse(brec, belem);
-				return -ENOENT;
-			}
-			if (node == bn->node) {
-				hfs_warn("hfs_bsucc: corrupt btree\n");
-				hfs_brec_relse(brec, belem);
-				return -EIO;
+int hfs_brec_goto(struct hfs_find_data *fd, int cnt)
+{
+	struct hfs_btree *tree;
+	struct hfs_bnode *bnode;
+	int idx, res = 0;
+	u16 off, len, keylen;
+
+	bnode = fd->bnode;
+	tree = bnode->tree;
+
+	if (cnt < 0) {
+		cnt = -cnt;
+		while (cnt > fd->record) {
+			cnt -= fd->record + 1;
+			fd->record = bnode->num_recs - 1;
+			idx = bnode->prev;
+			if (!idx) {
+				res = -ENOENT;
+				goto out;
+			}
+			hfs_bnode_put(bnode);
+			bnode = hfs_bnode_find(tree, idx);
+			if (IS_ERR(bnode)) {
+				res = PTR_ERR(bnode);
+				bnode = NULL;
+				goto out;
 			}
-			old = belem->bnr;
-			belem->bnr = hfs_bnode_find(brec->tree, node,
-						    belem->bnr.lock_type);
-			hfs_bnode_relse(&old);
-			if (!(bn = belem->bnr.bn)) {
-				return -EIO;
+		}
+		fd->record -= cnt;
+	} else {
+		while (cnt >= bnode->num_recs - fd->record) {
+			cnt -= bnode->num_recs - fd->record;
+			fd->record = 0;
+			idx = bnode->next;
+			if (!idx) {
+				res = -ENOENT;
+				goto out;
+			}
+			hfs_bnode_put(bnode);
+			bnode = hfs_bnode_find(tree, idx);
+			if (IS_ERR(bnode)) {
+				res = PTR_ERR(bnode);
+				bnode = NULL;
+				goto out;
 			}
-			belem->record = 1;
-			count -= (left + 1);
-		} else {
-			belem->record += count;
-			break;
 		}
+		fd->record += cnt;
 	}
-	brec->key  = belem_key(belem);
-	brec->data = bkey_record(brec->key);
 
-	if (brec->key->KeyLen > brec->tree->bthKeyLen) {
-		hfs_warn("hfs_bsucc: oversized key\n");
-		hfs_brec_relse(brec, NULL);
-		return -EIO;
-	}
-
-	return 0;
+	len = hfs_brec_lenoff(bnode, fd->record, &off);
+	keylen = hfs_brec_keylen(bnode, fd->record);
+	fd->keyoffset = off;
+	fd->keylength = keylen;
+	fd->entryoffset = off + keylen;
+	fd->entrylength = len - keylen;
+	hfs_bnode_read(bnode, fd->key, off, keylen);
+out:
+	fd->bnode = bnode;
+	return res;
 }
--- diff/fs/hfs/bitmap.c	2002-10-16 04:29:05.000000000 +0100
+++ source/fs/hfs/bitmap.c	2004-02-23 13:56:46.000000000 +0000
@@ -1,84 +1,111 @@
 /*
- * linux/fs/hfs/bitmap.c
+ *  linux/fs/hfs/bitmap.c
  *
  * Copyright (C) 1996-1997  Paul H. Hargrove
+ * (C) 2003 Ardis Technologies <roman@ardistech.com>
  * This file may be distributed under the terms of the GNU General Public License.
  *
  * Based on GPLed code Copyright (C) 1995  Michael Dreher
  *
  * This file contains the code to modify the volume bitmap:
  * search/set/clear bits.
- *
- * "XXX" in a comment is a note to myself to consider changing something.
- *
- * In function preconditions the term "valid" applied to a pointer to
- * a structure means that the pointer is non-NULL and the structure it
- * points to has all fields initialized to consistent values.
  */
 
-#include "hfs.h"
-
-/*================ Global functions ================*/
+#include "hfs_fs.h"
 
 /*
- * hfs_vbm_count_free()
+ * hfs_find_zero_bit()
  *
  * Description:
- *   Count the number of consecutive cleared bits in the bitmap blocks of
- *   the hfs MDB starting at bit number 'start'.  'mdb' had better
- *   be locked or the indicated number of blocks may be no longer free,
- *   when this functions returns!
- * Input Variable(s):
- *   struct hfs_mdb *mdb: Pointer to the hfs MDB
- *   hfs_u16 start: bit number to start at
- * Output Variable(s):
- *   NONE
- * Returns:
- *   The number of consecutive cleared bits starting at bit 'start'
- * Preconditions:
- *   'mdb' points to a "valid" (struct hfs_mdb).
- * Postconditions:
- *   NONE
+ *  Given a block of memory, its length in bits, and a starting bit number,
+ *  determine the number of the first zero bits (in left-to-right ordering)
+ *  in that range.
+ *
+ *  Returns >= 'size' if no zero bits are found in the range.
+ *
+ *  Accesses memory in 32-bit aligned chunks of 32-bits and thus
+ *  may read beyond the 'size'th bit.
  */
-hfs_u16 hfs_vbm_count_free(const struct hfs_mdb *mdb, hfs_u16 start)
+static u32 hfs_find_set_zero_bits(u32 *bitmap, u32 size, u32 offset, u32 *max)
 {
-	hfs_u16 block_nr;	/* index of the current bitmap block */
-	hfs_u16 bit_nr;		/* index of the current bit in block */
-	hfs_u16 count;		/* number of bits found so far */
-	hfs_u16 len;		/* number of bits found in this block */
-	hfs_u16 max_block;	/* index of last bitmap block */
-	hfs_u16 max_bits;	/* index of last bit in block */
-
-	/* is this a valid HFS MDB? */
-	if (!mdb) {
-		return 0;
+	u32 *curr, *end;
+	u32 val, mask, start, len;
+	int i;
+
+	len = *max;
+	if (!len)
+		return size;
+
+	curr = bitmap + (offset / 32);
+	end = bitmap + ((size + 31) / 32);
+
+	/* scan the first partial u32 for zero bits */
+	val = *curr;
+	if (~val) {
+		val = be32_to_cpu(val);
+		i = offset % 32;
+		mask = (1U << 31) >> i;
+		for (; i < 32; mask >>= 1, i++) {
+			if (!(val & mask))
+				goto found;
+		}
 	}
 
-	block_nr = start / HFS_BM_BPB;
-	bit_nr	 = start % HFS_BM_BPB;
-	max_block = (mdb->fs_ablocks + HFS_BM_BPB - 1) / HFS_BM_BPB - 1;
-
-	count = 0;
-	while (block_nr <= max_block) {
-		if (block_nr != max_block) {
-			max_bits = HFS_BM_BPB;
-		} else {
-			max_bits = mdb->fs_ablocks % HFS_BM_BPB;
+	/* scan complete u32s for the first zero bit */
+	while (++curr < end) {
+		val = *curr;
+		if (~val) {
+			val = be32_to_cpu(val);
+			mask = 1 << 31;
+			for (i = 0; i < 32; mask >>= 1, i++) {
+				if (!(val & mask))
+					goto found;
+			}
 		}
+	}
+	return size;
 
-		len=hfs_count_zero_bits(hfs_buffer_data(mdb->bitmap[block_nr]),
-					max_bits, bit_nr);
-		count += len;
-
-		/* see if we fell short of the end of this block */
-		if ((len + bit_nr) < max_bits) {
+found:
+	start = (curr - bitmap) * 32 + i;
+	if (start >= size)
+		return start;
+	/* do any partial u32 at the start */
+	len = min(size - start, len);
+	while (1) {
+		val |= mask;
+		if (++i >= 32)
+			break;
+		mask >>= 1;
+		if (!--len || val & mask)
+			goto done;
+	}
+	if (!--len)
+		goto done;
+	*curr++ = cpu_to_be32(val);
+	/* do full u32s */
+	while (1) {
+		val = be32_to_cpu(*curr);
+		if (len < 32)
+			break;
+		if (val) {
+			len = 32;
 			break;
 		}
-
-		++block_nr;
-		bit_nr = 0;
+		*curr++ = 0xffffffffU;
+		len -= 32;
+	}
+	/* do any partial u32 at end */
+	mask = 1U << 31;
+	for (i = 0; i < len; i++) {
+		if (val & mask)
+			break;
+		val |= mask;
+		mask >>= 1;
 	}
-	return count;
+done:
+	*curr = cpu_to_be32(val);
+	*max = (curr - bitmap) * 32 + i - start;
+	return start;
 }
 
 /*
@@ -92,10 +119,10 @@ hfs_u16 hfs_vbm_count_free(const struct 
  *   the bit number stored in 's_alloc_ptr' of the MDB.
  * Input Variable(s):
  *   struct hfs_mdb *mdb: Pointer to the hfs MDB
- *   hfs_u16 *num_bits: Pointer to the number of cleared bits
+ *   u16 *num_bits: Pointer to the number of cleared bits
  *     to search for
  * Output Variable(s):
- *   hfs_u16 *num_bits: The number of consecutive clear bits of the
+ *   u16 *num_bits: The number of consecutive clear bits of the
  *     returned range. If the bitmap is fragmented, this will be less than
  *     requested and it will be zero, when the disk is full.
  * Returns:
@@ -103,198 +130,42 @@ hfs_u16 hfs_vbm_count_free(const struct 
  *   found. When 'num_bits' is zero, this is invalid!
  * Preconditions:
  *   'mdb' points to a "valid" (struct hfs_mdb).
- *   'num_bits' points to a variable of type (hfs_u16), which contains
+ *   'num_bits' points to a variable of type (u16), which contains
  *	the number of cleared bits to find.
  * Postconditions:
  *   'num_bits' is set to the length of the found sequence.
  */
-hfs_u16 hfs_vbm_search_free(const struct hfs_mdb *mdb, hfs_u16 *num_bits)
+u32 hfs_vbm_search_free(struct super_block *sb, u32 goal, u32 *num_bits)
 {
-	hfs_u16 block_nr; /* index of the current bitmap block */
-
-	/* position and length of current portion of a run */
-	hfs_u16 cur_pos, cur_len;
+	void *bitmap;
+	u32 pos;
 
-	/* position and length of current complete run */
-	hfs_u16 pos=0, len=0;
-	
-	/* position and length of longest complete run */
-	hfs_u16 longest_pos=0, longest_len=0;
-
-	void *bitmap; /* contents of the current bitmap block */
-	hfs_u16 max_block; /* upper limit of outer loop */
-	hfs_u16 max_bits; /* upper limit of inner loop */
-
-	/* is this a valid HFS MDB? */
-	if (!mdb) {
-		*num_bits = 0;
-		hfs_warn("hfs_vbm_search_free: not a valid MDB\n");
-		return 0;
-	}
-	
 	/* make sure we have actual work to perform */
-	if (!(*num_bits)) {
+	if (!*num_bits)
 		return 0;
-	}
 
-	max_block = (mdb->fs_ablocks+HFS_BM_BPB-1) / HFS_BM_BPB - 1;
-	
-	/* search all bitmap blocks */
-	for (block_nr = 0; block_nr <= max_block; block_nr++) {
-		bitmap = hfs_buffer_data(mdb->bitmap[block_nr]);
-
-		if (block_nr != max_block) {
-			max_bits = HFS_BM_BPB;
-		} else {
-			max_bits = mdb->fs_ablocks % HFS_BM_BPB;
-		}
+	down(&HFS_SB(sb)->bitmap_lock);
+	bitmap = HFS_SB(sb)->bitmap;
 
-		cur_pos = 0;
-		do {
-			cur_len = hfs_count_zero_bits(bitmap, max_bits,
-						      cur_pos);
-			len += cur_len;
-			if (len > longest_len) {
-				longest_pos = pos;
-				longest_len = len;
-				if (len >= *num_bits) {
-					goto search_end;
-				}
-			}
-			if ((cur_pos + cur_len) == max_bits) {
-				break; /* zeros may continue into next block */
-			}
-
-			/* find start of next run of zeros */
-			cur_pos = hfs_find_zero_bit(bitmap, max_bits,
-						    cur_pos + cur_len);
-			pos = cur_pos + HFS_BM_BPB*block_nr;
-			len = 0;
-		} while (cur_pos < max_bits);
-	}
-
-search_end:
-	*num_bits = longest_len;
-	return longest_pos;
-}
-
-
-/*
- * hfs_set_vbm_bits()
- *
- * Description:
- *   Set the requested bits in the volume bitmap of the hfs filesystem
- * Input Variable(s):
- *   struct hfs_mdb *mdb: Pointer to the hfs MDB
- *   hfs_u16 start: The offset of the first bit
- *   hfs_u16 count: The number of bits
- * Output Variable(s):
- *   None
- * Returns:
- *    0: no error
- *   -1: One of the bits was already set.  This is a strange
- *	 error and when it happens, the filesystem must be repaired!
- *   -2: One or more of the bits are out of range of the bitmap.
- *   -3: The 's_magic' field of the MDB does not match
- * Preconditions:
- *   'mdb' points to a "valid" (struct hfs_mdb).
- * Postconditions:
- *   Starting with bit number 'start', 'count' bits in the volume bitmap
- *   are set. The affected bitmap blocks are marked "dirty", the free
- *   block count of the MDB is updated and the MDB is marked dirty.
- */
-int hfs_set_vbm_bits(struct hfs_mdb *mdb, hfs_u16 start, hfs_u16 count)
-{
-	hfs_u16 block_nr;	/* index of the current bitmap block */
-	hfs_u16 u32_nr;		/* index of the current hfs_u32 in block */
-	hfs_u16 bit_nr;		/* index of the current bit in hfs_u32 */
-	hfs_u16 left = count;	/* number of bits left to be set */
-	hfs_u32 *bitmap;	/* the current bitmap block's contents */
-
-	/* is this a valid HFS MDB? */
-	if (!mdb) {
-		return -3;
-	}
-
-	/* is there any actual work to be done? */
-	if (!count) {
-		return 0;
-	}
-
-	/* are all of the bits in range? */
-	if ((start + count) > mdb->fs_ablocks) {
-		return -2;
-	}
-
-	block_nr = start / HFS_BM_BPB;
-	u32_nr = (start % HFS_BM_BPB) / 32;
-	bit_nr = start % 32;
-
-	/* bitmap is always on a 32-bit boundary */
-	bitmap = (hfs_u32 *)hfs_buffer_data(mdb->bitmap[block_nr]);
-
-	/* do any partial hfs_u32 at the start */
-	if (bit_nr != 0) {
-		while ((bit_nr < 32) && left) {
-			if (hfs_set_bit(bit_nr, bitmap + u32_nr)) {
-				hfs_buffer_dirty(mdb->bitmap[block_nr]);
-				return -1;
-			}
-			++bit_nr;
-			--left;
-		}
-		bit_nr=0;
-
-		/* advance u32_nr and check for end of this block */
-		if (++u32_nr > 127) {
-			u32_nr = 0;
-			hfs_buffer_dirty(mdb->bitmap[block_nr]);
-			++block_nr;
-			/* bitmap is always on a 32-bit boundary */
-			bitmap = (hfs_u32 *)
-					hfs_buffer_data(mdb->bitmap[block_nr]);
-		}
-	}
-
-	/* do full hfs_u32s */
-	while (left > 31) {
-		if (bitmap[u32_nr] != ((hfs_u32)0)) {
-			hfs_buffer_dirty(mdb->bitmap[block_nr]);
-			return -1;
-		}
-		bitmap[u32_nr] = ~((hfs_u32)0);
-		left -= 32;
-
-		/* advance u32_nr and check for end of this block */
-		if (++u32_nr > 127) {
-			u32_nr = 0;
-			hfs_buffer_dirty(mdb->bitmap[block_nr]);
-			++block_nr;
-			/* bitmap is always on a 32-bit boundary */
-			bitmap = (hfs_u32 *)
-					hfs_buffer_data(mdb->bitmap[block_nr]);
+	pos = hfs_find_set_zero_bits(bitmap, HFS_SB(sb)->fs_ablocks, goal, num_bits);
+	if (pos >= HFS_SB(sb)->fs_ablocks) {
+		if (goal)
+			pos = hfs_find_set_zero_bits(bitmap, goal, 0, num_bits);
+		if (pos >= HFS_SB(sb)->fs_ablocks) {
+			*num_bits = pos = 0;
+			goto out;
 		}
 	}
 
-			
-	/* do any partial hfs_u32 at end */
-	while (left) {
-		if (hfs_set_bit(bit_nr, bitmap + u32_nr)) {
-			hfs_buffer_dirty(mdb->bitmap[block_nr]);
-			return -1;
-		}
-		++bit_nr;
-		--left;
-	}
-
-	hfs_buffer_dirty(mdb->bitmap[block_nr]);
-	mdb->free_ablocks -= count;
-
-	/* successful completion */
-	hfs_mdb_dirty(mdb->sys_mdb);
-	return 0;
+	dprint(DBG_BITMAP, "alloc_bits: %u,%u\n", pos, *num_bits);
+	HFS_SB(sb)->free_ablocks -= *num_bits;
+	hfs_bitmap_dirty(sb);
+out:
+	up(&HFS_SB(sb)->bitmap_lock);
+	return pos;
 }
 
+
 /*
  * hfs_clear_vbm_bits()
  *
@@ -302,8 +173,8 @@ int hfs_set_vbm_bits(struct hfs_mdb *mdb
  *   Clear the requested bits in the volume bitmap of the hfs filesystem
  * Input Variable(s):
  *   struct hfs_mdb *mdb: Pointer to the hfs MDB
- *   hfs_u16 start: The offset of the first bit
- *   hfs_u16 count: The number of bits
+ *   u16 start: The offset of the first bit
+ *   u16 count: The number of bits
  * Output Variable(s):
  *   None
  * Returns:
@@ -311,7 +182,6 @@ int hfs_set_vbm_bits(struct hfs_mdb *mdb
  *   -1: One of the bits was already clear.  This is a strange
  *	 error and when it happens, the filesystem must be repaired!
  *   -2: One or more of the bits are out of range of the bitmap.
- *   -3: The 's_magic' field of the MDB does not match
  * Preconditions:
  *   'mdb' points to a "valid" (struct hfs_mdb).
  * Postconditions:
@@ -319,94 +189,54 @@ int hfs_set_vbm_bits(struct hfs_mdb *mdb
  *   are cleared. The affected bitmap blocks are marked "dirty", the free
  *   block count of the MDB is updated and the MDB is marked dirty.
  */
-int hfs_clear_vbm_bits(struct hfs_mdb *mdb, hfs_u16 start, hfs_u16 count)
+int hfs_clear_vbm_bits(struct super_block *sb, u16 start, u16 count)
 {
-	hfs_u16 block_nr;	/* index of the current bitmap block */
-	hfs_u16 u32_nr;		/* index of the current hfs_u32 in block */
-	hfs_u16 bit_nr;		/* index of the current bit in hfs_u32 */
-	hfs_u16 left = count;	/* number of bits left to be set */
-	hfs_u32 *bitmap;	/* the current bitmap block's contents */
-
-	/* is this a valid HFS MDB? */
-	if (!mdb) {
-		return -3;
-	}
+	u32 *curr;
+	u32 mask;
+	int i, len;
 
 	/* is there any actual work to be done? */
-	if (!count) {
+	if (!count)
 		return 0;
-	}
 
+	dprint(DBG_BITMAP, "clear_bits: %u,%u\n", start, count);
 	/* are all of the bits in range? */
-	if ((start + count) > mdb->fs_ablocks) {
+	if ((start + count) > HFS_SB(sb)->fs_ablocks)
 		return -2;
-	}
-
-	block_nr = start / HFS_BM_BPB;
-	u32_nr = (start % HFS_BM_BPB) / 32;
-	bit_nr = start % 32;
 
+	down(&HFS_SB(sb)->bitmap_lock);
 	/* bitmap is always on a 32-bit boundary */
-	bitmap = (hfs_u32 *)hfs_buffer_data(mdb->bitmap[block_nr]);
-
-	/* do any partial hfs_u32 at the start */
-	if (bit_nr != 0) {
-		while ((bit_nr < 32) && left) {
-			if (!hfs_clear_bit(bit_nr, bitmap + u32_nr)) {
-				hfs_buffer_dirty(mdb->bitmap[block_nr]);
-				return -1;
-			}
-			++bit_nr;
-			--left;
-		}
-		bit_nr=0;
-
-		/* advance u32_nr and check for end of this block */
-		if (++u32_nr > 127) {
-			u32_nr = 0;
-			hfs_buffer_dirty(mdb->bitmap[block_nr]);
-			++block_nr;
-			/* bitmap is always on a 32-bit boundary */
-			bitmap = (hfs_u32 *)
-					hfs_buffer_data(mdb->bitmap[block_nr]);
-		}
-	}
-
-	/* do full hfs_u32s */
-	while (left > 31) {
-		if (bitmap[u32_nr] != ~((hfs_u32)0)) {
-			hfs_buffer_dirty(mdb->bitmap[block_nr]);
-			return -1;
-		}
-		bitmap[u32_nr] = ((hfs_u32)0);
-		left -= 32;
-
-		/* advance u32_nr and check for end of this block */
-		if (++u32_nr > 127) {
-			u32_nr = 0;
-			hfs_buffer_dirty(mdb->bitmap[block_nr]);
-			++block_nr;
-			/* bitmap is always on a 32-bit boundary */
-			bitmap = (hfs_u32 *)
-					hfs_buffer_data(mdb->bitmap[block_nr]);
-		}
-	}
-
-			
-	/* do any partial hfs_u32 at end */
-	while (left) {
-		if (!hfs_clear_bit(bit_nr, bitmap + u32_nr)) {
-			hfs_buffer_dirty(mdb->bitmap[block_nr]);
-			return -1;
-		}
-		++bit_nr;
-		--left;
-	}
+	curr = HFS_SB(sb)->bitmap + (start / 32);
+	len = count;
 
-	hfs_buffer_dirty(mdb->bitmap[block_nr]);
-	mdb->free_ablocks += count;
+	/* do any partial u32 at the start */
+	i = start % 32;
+	if (i) {
+		int j = 32 - i;
+		mask = 0xffffffffU << j;
+		if (j > count) {
+			mask |= 0xffffffffU >> (i + count);
+			*curr &= cpu_to_be32(mask);
+			goto out;
+		}
+		*curr++ &= cpu_to_be32(mask);
+		count -= j;
+	}
+
+	/* do full u32s */
+	while (count >= 32) {
+		*curr++ = 0;
+		count -= 32;
+	}
+	/* do any partial u32 at end */
+	if (count) {
+		mask = 0xffffffffU >> count;
+		*curr &= cpu_to_be32(mask);
+	}
+out:
+	HFS_SB(sb)->free_ablocks += len;
+	up(&HFS_SB(sb)->bitmap_lock);
+	hfs_bitmap_dirty(sb);
 
-	/* successful completion */
-	hfs_mdb_dirty(mdb->sys_mdb);
 	return 0;
 }
--- diff/fs/hfs/bnode.c	2002-10-16 04:27:53.000000000 +0100
+++ source/fs/hfs/bnode.c	2004-02-23 13:56:46.000000000 +0000
@@ -1,544 +1,486 @@
 /*
- * linux/fs/hfs/bnode.c
+ *  linux/fs/hfs/bnode.c
  *
- * Copyright (C) 1995-1997  Paul H. Hargrove
- * This file may be distributed under the terms of the GNU General Public License.
+ * Copyright (C) 2001
+ * Brad Boyer (flar@allandria.com)
+ * (C) 2003 Ardis Technologies <roman@ardistech.com>
  *
- * This file contains the code to access nodes in the B-tree structure.
- *
- * "XXX" in a comment is a note to myself to consider changing something.
- *
- * In function preconditions the term "valid" applied to a pointer to
- * a structure means that the pointer is non-NULL and the structure it
- * points to has all fields initialized to consistent values.
- *
- * The code in this file initializes some structures which contain
- * pointers by calling memset(&foo, 0, sizeof(foo)).
- * This produces the desired behavior only due to the non-ANSI
- * assumption that the machine representation of NULL is all zeros.
+ * Handle basic btree node operations
  */
 
-#include "hfs_btree.h"
+#include <linux/pagemap.h>
+#include <linux/swap.h>
 
-/*================ File-local variables ================*/
- 
-/* debugging statistics */
-#if defined(DEBUG_BNODES) || defined(DEBUG_ALL)
-int bnode_count = 0;
-#endif
+#include "btree.h"
 
-/*================ Global functions ================*/
+#define REF_PAGES	0
 
-/*
- * hfs_bnode_delete()
- *
- * Description:
- *   This function is called to remove a bnode from the cache and
- *   release its resources.
- * Input Variable(s):
- *   struct hfs_bnode *bn: Pointer to the (struct hfs_bnode) to be
- *   removed from the cache.
- * Output Variable(s):
- *   NONE
- * Returns:
- *   void
- * Preconditions:
- *   'bn' points to a "valid" (struct hfs_bnode).
- * Postconditions:
- *   The node 'bn' is removed from the cache, its memory freed and its
- *   buffer (if any) released.
- */
-void hfs_bnode_delete(struct hfs_bnode *bn)
+void hfs_bnode_read(struct hfs_bnode *node, void *buf,
+		int off, int len)
 {
-#if defined(DEBUG_BNODES) || defined(DEBUG_ALL)
-	--bnode_count;
-#endif
-	/* join neighbors */
-	if (bn->next) {
-		bn->next->prev = bn->prev;
-	}
-	if (bn->prev) {
-		bn->prev->next = bn->next;
-	}
-	/* fix cache slot if necessary */
-	if (bhash(bn->tree, bn->node) == bn) {
-		bhash(bn->tree, bn->node) = bn->next;
-	}
-	/* release resources */
-	hfs_buffer_put(bn->buf); /* safe: checks for NULL argument */
-	HFS_DELETE(bn);
+	struct page *page;
+
+	off += node->page_offset;
+	page = node->page[0];
+
+	memcpy(buf, kmap(page) + off, len);
+	kunmap(page);
 }
 
+u16 hfs_bnode_read_u16(struct hfs_bnode *node, int off)
+{
+	u16 data;
+	// optimize later...
+	hfs_bnode_read(node, &data, off, 2);
+	return be16_to_cpu(data);
+}
 
-/*
- * hfs_bnode_read()
- *
- * Description: 
- *   This function creates a (struct hfs_bnode) and, if appropriate,
- *   inserts it in the cache.
- * Input Variable(s):
- *   struct hfs_bnode *bnode: pointer to the new bnode.
- *   struct hfs_btree *tree: pointer to the (struct hfs_btree)
- *    containing the desired node
- *   hfs_u32 node: the number of the desired node.
- *   int sticky: the value to assign to the 'sticky' field.
- * Output Variable(s):
- *   NONE
- * Returns:
- *   (struct hfs_bnode *) pointing to the newly created bnode or NULL.
- * Preconditions:
- *   'bnode' points to a "valid" (struct hfs_bnode).
- *   'tree' points to a "valid" (struct hfs_btree).
- *   'node' is an existing node number in the B-tree.
- * Postconditions:
- *   The following are true of 'bnode' upon return:
- *    The 'magic' field is set to indicate a valid (struct hfs_bnode). 
- *    The 'sticky', 'tree' and 'node' fields are initialized to the
- *    values of the of the corresponding arguments.
- *    If the 'sticky' argument is zero then the fields 'prev' and
- *    'next' are initialized by inserting the (struct hfs_bnode) in the
- *    linked list of the appropriate cache slot; otherwise they are
- *    initialized to NULL.
- *    The data is read from disk (or buffer cache) and the 'buf' field
- *    points to the buffer for that data.
- *    If no other processes tried to access this node while this
- *    process was waiting on disk I/O (if necessary) then the
- *    remaining fields are zero ('count', 'resrv', 'lock') or NULL
- *    ('wqueue', 'rqueue') corresponding to no accesses.
- *    If there were access attempts during I/O then they were blocked
- *    until the I/O was complete, and the fields 'count', 'resrv',
- *    'lock', 'wqueue' and 'rqueue' reflect the results of unblocking
- *    those processes when the I/O was completed.
- */
-void hfs_bnode_read(struct hfs_bnode *bnode, struct hfs_btree *tree,
-		    hfs_u32 node, int sticky)
+u8 hfs_bnode_read_u8(struct hfs_bnode *node, int off)
 {
-	struct NodeDescriptor *nd;
-	int block, lcv;
-	hfs_u16 curr, prev, limit;
-
-	/* Initialize the structure */
-	memset(bnode, 0, sizeof(*bnode));
-	bnode->magic = HFS_BNODE_MAGIC;
-	bnode->tree = tree;
-	bnode->node = node;
-	bnode->sticky = sticky;
-	hfs_init_waitqueue(&bnode->rqueue);
-	hfs_init_waitqueue(&bnode->wqueue);
-
-	if (sticky == HFS_NOT_STICKY) {
-		/* Insert it in the cache if appropriate */
-		if ((bnode->next = bhash(tree, node))) {
-			bnode->next->prev = bnode;
-		}
-		bhash(tree, node) = bnode;
-	}
+	u8 data;
+	// optimize later...
+	hfs_bnode_read(node, &data, off, 1);
+	return data;
+}
 
-	/* Make the bnode look like it is being
-	   modified so other processes will wait for
-	   the I/O to complete */
-	bnode->count = bnode->resrv = bnode->lock = 1;
-
-	/* Read in the node, possibly causing a schedule()
-	   call.  If the I/O fails then emit a warning.	 Each
-	   process that was waiting on the bnode (including
-	   the current one) will notice the failure and
-	   hfs_bnode_relse() the node.	The last hfs_bnode_relse()
-	   will call hfs_bnode_delete() and discard the bnode.	*/
-
-	block = hfs_extent_map(&tree->entry.u.file.data_fork, node, 0);
-	if (!block) {
-		hfs_warn("hfs_bnode_read: bad node number 0x%08x\n", node);
-	} else if (hfs_buffer_ok(bnode->buf =
-				 hfs_buffer_get(tree->sys_mdb, block, 1))) {
-		/* read in the NodeDescriptor */
-		nd = (struct NodeDescriptor *)hfs_buffer_data(bnode->buf);
-		bnode->ndFLink    = hfs_get_hl(nd->ndFLink);
-		bnode->ndBLink    = hfs_get_hl(nd->ndBLink);
-		bnode->ndType     = nd->ndType;
-		bnode->ndNHeight  = nd->ndNHeight;
-		bnode->ndNRecs    = hfs_get_hs(nd->ndNRecs);
-
-		/* verify the integrity of the node */
-		prev = sizeof(struct NodeDescriptor);
-		limit = HFS_SECTOR_SIZE - sizeof(hfs_u16)*(bnode->ndNRecs + 1);
-		for (lcv=1; lcv <= (bnode->ndNRecs + 1); ++lcv) {
-			curr = hfs_get_hs(RECTBL(bnode, lcv));
-			if ((curr < prev) || (curr > limit)) {
-				hfs_warn("hfs_bnode_read: corrupt node "
-					 "number 0x%08x\n", node);
-				hfs_buffer_put(bnode->buf);
-				bnode->buf = NULL;
-				break;
-			}
-			prev = curr;
-		}
-	}
+void hfs_bnode_read_key(struct hfs_bnode *node, void *key, int off)
+{
+	struct hfs_btree *tree;
+	int key_len;
 
-	/* Undo our fakery with the lock state and
-	   hfs_wake_up() anyone who we managed to trick */
-	--bnode->count;
-	bnode->resrv = bnode->lock = 0;
-	hfs_wake_up(&bnode->rqueue);
+	tree = node->tree;
+	if (node->type == HFS_NODE_LEAF ||
+	    tree->attributes & HFS_TREE_VARIDXKEYS)
+		key_len = hfs_bnode_read_u8(node, off) + 1;
+	else
+		key_len = tree->max_key_len + 1;
+
+	hfs_bnode_read(node, key, off, key_len);
 }
 
-/*
- * hfs_bnode_lock()
- *
- * Description:
- *   This function does the locking of a bnode.
- * Input Variable(s):
- *   struct hfs_bnode *bn: pointer to the (struct hfs_bnode) to lock
- *   int lock_type: the type of lock desired
- * Output Variable(s):
- *   NONE
- * Returns:
- *   void
- * Preconditions:
- *   'bn' points to a "valid" (struct hfs_bnode).
- *   'lock_type' is a valid hfs_lock_t
- * Postconditions:
- *   The 'count' field of 'bn' is incremented by one.  If 'lock_type'
- *   is HFS_LOCK_RESRV the 'resrv' field is also incremented.
- */
-void hfs_bnode_lock(struct hfs_bnode_ref *bnr, int lock_type)
+void hfs_bnode_write(struct hfs_bnode *node, void *buf, int off, int len)
+{
+	struct page *page;
+
+	off += node->page_offset;
+	page = node->page[0];
+
+	memcpy(kmap(page) + off, buf, len);
+	kunmap(page);
+	set_page_dirty(page);
+}
+
+void hfs_bnode_write_u16(struct hfs_bnode *node, int off, u16 data)
+{
+	data = cpu_to_be16(data);
+	// optimize later...
+	hfs_bnode_write(node, &data, off, 2);
+}
+
+void hfs_bnode_write_u8(struct hfs_bnode *node, int off, u8 data)
+{
+	// optimize later...
+	hfs_bnode_write(node, &data, off, 1);
+}
+
+void hfs_bnode_clear(struct hfs_bnode *node, int off, int len)
 {
-	struct hfs_bnode *bn = bnr->bn;
+	struct page *page;
+
+	off += node->page_offset;
+	page = node->page[0];
+
+	memset(kmap(page) + off, 0, len);
+	kunmap(page);
+	set_page_dirty(page);
+}
 
-	if ((lock_type == bnr->lock_type) || !bn) {
+void hfs_bnode_copy(struct hfs_bnode *dst_node, int dst,
+		struct hfs_bnode *src_node, int src, int len)
+{
+	struct hfs_btree *tree;
+	struct page *src_page, *dst_page;
+
+	dprint(DBG_BNODE_MOD, "copybytes: %u,%u,%u\n", dst, src, len);
+	if (!len)
 		return;
-	}
+	tree = src_node->tree;
+	src += src_node->page_offset;
+	dst += dst_node->page_offset;
+	src_page = src_node->page[0];
+	dst_page = dst_node->page[0];
+
+	memcpy(kmap(dst_page) + dst, kmap(src_page) + src, len);
+	kunmap(src_page);
+	kunmap(dst_page);
+	set_page_dirty(dst_page);
+}
 
-	if (bnr->lock_type == HFS_LOCK_WRITE) {
-		hfs_bnode_commit(bnr->bn);
-	}
+void hfs_bnode_move(struct hfs_bnode *node, int dst, int src, int len)
+{
+	struct page *page;
+	void *ptr;
 
-	switch (lock_type) {
-	default:
-		goto bail;
-		break;
+	dprint(DBG_BNODE_MOD, "movebytes: %u,%u,%u\n", dst, src, len);
+	if (!len)
+		return;
+	src += node->page_offset;
+	dst += node->page_offset;
+	page = node->page[0];
+	ptr = kmap(page);
+	memmove(ptr + dst, ptr + src, len);
+	kunmap(page);
+	set_page_dirty(page);
+}
 
-	case HFS_LOCK_READ:
-		/* We may not obtain read access if any process is
-		   currently modifying or waiting to modify this node.
-		   If we can't obtain access we wait on the rqueue
-		   wait queue to be woken up by the modifying process
-		   when it relinquishes its lock. */
-		switch (bnr->lock_type) {
-		default:
-			goto bail;
-			break;
-
-		case HFS_LOCK_NONE:
-			while (bn->lock || waitqueue_active(&bn->wqueue)) {
-				hfs_sleep_on(&bn->rqueue);
-			}
-			++bn->count;
-			break;
-		}
-		break;
-			
-	case HFS_LOCK_RESRV:
-		/* We may not obtain a reservation (read access with
-		   an option to write later), if any process currently
-		   holds a reservation on this node.  That includes
-		   any process which is currently modifying this node.
-		   If we can't obtain access, then we wait on the
-		   rqueue wait queue to e woken up by the
-		   reservation-holder when it calls hfs_bnode_relse. */
-		switch (bnr->lock_type) {
-		default:
-			goto bail;
-			break;
-
-		case HFS_LOCK_NONE:
-			while (bn->resrv) {
-				hfs_sleep_on(&bn->rqueue);
-			}
-			bn->resrv = 1;
-			++bn->count;
-			break;
-
-		case HFS_LOCK_WRITE:
-			bn->lock = 0;
-			hfs_wake_up(&bn->rqueue);
-			break;
-		}
-		break;
-		
-	case HFS_LOCK_WRITE:
-		switch (bnr->lock_type) {
-		default:
-			goto bail;
-			break;
-
-		case HFS_LOCK_NONE:
-			while (bn->resrv) {
-				hfs_sleep_on(&bn->rqueue);
-			}
-			bn->resrv = 1;
-			++bn->count;
-		case HFS_LOCK_RESRV:
-			while (bn->count > 1) {
-				hfs_sleep_on(&bn->wqueue);
-			}
-			bn->lock = 1;
-			break;
-		}
-		break;
+void hfs_bnode_dump(struct hfs_bnode *node)
+{
+	struct hfs_bnode_desc desc;
+	u32 cnid;
+	int i, off, key_off;
+
+	dprint(DBG_BNODE_MOD, "bnode: %d\n", node->this);
+	hfs_bnode_read(node, &desc, 0, sizeof(desc));
+	dprint(DBG_BNODE_MOD, "%d, %d, %d, %d, %d\n",
+		be32_to_cpu(desc.next), be32_to_cpu(desc.prev),
+		desc.type, desc.height, be16_to_cpu(desc.num_recs));
+
+	off = node->tree->node_size - 2;
+	for (i = be16_to_cpu(desc.num_recs); i >= 0; off -= 2, i--) {
+		key_off = hfs_bnode_read_u16(node, off);
+		dprint(DBG_BNODE_MOD, " %d", key_off);
+		if (i && node->type == HFS_NODE_INDEX) {
+			int tmp;
+
+			if (node->tree->attributes & HFS_TREE_VARIDXKEYS)
+				tmp = (hfs_bnode_read_u8(node, key_off) | 1) + 1;
+			else
+				tmp = node->tree->max_key_len + 1;
+			dprint(DBG_BNODE_MOD, " (%d,%d", tmp, hfs_bnode_read_u8(node, key_off));
+			hfs_bnode_read(node, &cnid, key_off + tmp, 4);
+			dprint(DBG_BNODE_MOD, ",%d)", be32_to_cpu(cnid));
+		} else if (i && node->type == HFS_NODE_LEAF) {
+			int tmp;
 
-	case HFS_LOCK_NONE:
-		switch (bnr->lock_type) {
-		default:
-			goto bail;
-			break;
-
-		case HFS_LOCK_READ:
-			/* This process was reading this node.	If
-			   there is now exactly one other process using
-			   the node then hfs_wake_up() a (potentially
-			   nonexistent) waiting process.  Note that I
-			   refer to "a" process since the reservation
-			   system ensures that only one process can
-			   get itself on the wait queue.  */
-			if (bn->count == 2) {
-				hfs_wake_up(&bn->wqueue);
-			}
-			break;
-
-		case HFS_LOCK_WRITE:
-			/* This process was modifying this node.
-			   Unlock the node and fall-through to the
-			   HFS_LOCK_RESRV case, since a 'reservation'
-			   is a prerequisite for HFS_LOCK_WRITE.  */
-			bn->lock = 0;
-		case HFS_LOCK_RESRV:
-			/* This process had placed a 'reservation' on
-			   this node, indicating an intention to
-			   possibly modify the node.  We can get to
-			   this spot directly (if the 'reservation'
-			   not converted to a HFS_LOCK_WRITE), or by
-			   falling through from the above case if the
-			   reservation was converted.
-			   Since HFS_LOCK_RESRV and HFS_LOCK_WRITE
-			   both block processes that want access
-			   (HFS_LOCK_RESRV blocks other processes that
-			   want reservations but allow HFS_LOCK_READ
-			   accesses, while HFS_LOCK_WRITE must have
-			   exclusive access and thus blocks both
-			   types) we hfs_wake_up() any processes that
-			   might be waiting for access.	 If multiple
-			   processes are waiting for a reservation
-			   then the magic of process scheduling will
-			   settle the dispute. */
-			bn->resrv = 0;
-			hfs_wake_up(&bn->rqueue);
-			break;
+			tmp = hfs_bnode_read_u8(node, key_off);
+			dprint(DBG_BNODE_MOD, " (%d)", tmp);
 		}
-		--bn->count;
-		break;
 	}
-	bnr->lock_type = lock_type;
-	return;
+	dprint(DBG_BNODE_MOD, "\n");
+}
 
-bail:
-	hfs_warn("hfs_bnode_lock: invalid lock change: %d->%d.\n",
-		bnr->lock_type, lock_type);
-	return;
+void hfs_bnode_unlink(struct hfs_bnode *node)
+{
+	struct hfs_btree *tree;
+	struct hfs_bnode *tmp;
+	u32 cnid;
+
+	tree = node->tree;
+	if (node->prev) {
+		tmp = hfs_bnode_find(tree, node->prev);
+		if (IS_ERR(tmp))
+			return;
+		tmp->next = node->next;
+		cnid = cpu_to_be32(tmp->next);
+		hfs_bnode_write(tmp, &cnid, offsetof(struct hfs_bnode_desc, next), 4);
+		hfs_bnode_put(tmp);
+	} else if (node->type == HFS_NODE_LEAF)
+		tree->leaf_head = node->next;
+
+	if (node->next) {
+		tmp = hfs_bnode_find(tree, node->next);
+		if (IS_ERR(tmp))
+			return;
+		tmp->prev = node->prev;
+		cnid = cpu_to_be32(tmp->prev);
+		hfs_bnode_write(tmp, &cnid, offsetof(struct hfs_bnode_desc, prev), 4);
+		hfs_bnode_put(tmp);
+	} else if (node->type == HFS_NODE_LEAF)
+		tree->leaf_tail = node->prev;
+
+	// move down?
+	if (!node->prev && !node->next) {
+		printk("hfs_btree_del_level\n");
+	}
+	if (!node->parent) {
+		tree->root = 0;
+		tree->depth = 0;
+	}
+	set_bit(HFS_BNODE_DELETED, &node->flags);
 }
 
-/*
- * hfs_bnode_relse()
- *
- * Description:
- *   This function is called when a process is done using a bnode.  If
- *   the proper conditions are met then we call hfs_bnode_delete() to remove
- *   it from the cache.	 If it is not deleted then we update its state
- *   to reflect one less process using it.
- * Input Variable(s):
- *   struct hfs_bnode *bn: pointer to the (struct hfs_bnode) to release.
- *   int lock_type: The type of lock held by the process releasing this node.
- * Output Variable(s):
- *   NONE
- * Returns:
- *   void
- * Preconditions:
- *   'bn' is NULL or points to a "valid" (struct hfs_bnode).
- * Postconditions:
- *   If 'bn' meets the appropriate conditions (see below) then it is
- *   kept in the cache and all fields are set to consistent values
- *   which reflect one less process using the node than upon entry.
- *   If 'bn' does not meet the conditions then it is deleted (see
- *   hfs_bnode_delete() for postconditions).
- *   In either case, if 'lock_type' is HFS_LOCK_WRITE
- *   then the corresponding buffer is dirtied.
- */
-void hfs_bnode_relse(struct hfs_bnode_ref *bnr)
+static inline int hfs_bnode_hash(u32 num)
 {
-	struct hfs_bnode *bn;
+	num = (num >> 16) + num;
+	num += num >> 8;
+	return num & (NODE_HASH_SIZE - 1);
+}
 
-	if (!bnr || !(bn = bnr->bn)) {
-		return;
+struct hfs_bnode *hfs_bnode_findhash(struct hfs_btree *tree, u32 cnid)
+{
+	struct hfs_bnode *node;
+
+	if (cnid >= tree->node_count) {
+		printk("HFS: request for non-existent node %d in B*Tree\n", cnid);
+		return NULL;
 	}
 
-	/* We update the lock state of the node if it is still in use
-	   or if it is "sticky" (such as the B-tree head and root).
-	   Otherwise we just delete it.	 */
-	if ((bn->count > 1) || (waitqueue_active(&bn->rqueue)) || (bn->sticky != HFS_NOT_STICKY)) {
-		hfs_bnode_lock(bnr, HFS_LOCK_NONE);
-	} else {
-		/* dirty buffer if we (might) have modified it */
-		if (bnr->lock_type == HFS_LOCK_WRITE) {
-			hfs_bnode_commit(bn);
+	for (node = tree->node_hash[hfs_bnode_hash(cnid)];
+	     node; node = node->next_hash) {
+		if (node->this == cnid) {
+			return node;
 		}
-		hfs_bnode_delete(bn);
-		bnr->lock_type = HFS_LOCK_NONE;
 	}
-	bnr->bn = NULL;
+	return NULL;
 }
 
-/*
- * hfs_bnode_find()
- *
- * Description:
- *   This function is called to obtain a bnode.  The cache is
- *   searched for the node.  If it not found there it is added to
- *   the cache by hfs_bnode_read().  There are two special cases node=0
- *   (the header node) and node='tree'->bthRoot (the root node), in
- *   which the nodes are obtained from fields of 'tree' without
- *   consulting or modifying the cache.
- * Input Variable(s):
- *   struct hfs_tree *tree: pointer to the (struct hfs_btree) from
- *    which to get a node.
- *   int node: the node number to get from 'tree'.
- *   int lock_type: The kind of access (HFS_LOCK_READ, or
- *    HFS_LOCK_RESRV) to obtain to the node
- * Output Variable(s):
- *   NONE
- * Returns:
- *   (struct hfs_bnode_ref) Reference to the requested node.
- * Preconditions:
- *   'tree' points to a "valid" (struct hfs_btree).
- * Postconditions:
- *   If 'node' refers to a valid node in 'tree' and 'lock_type' has
- *   one of the values listed above and no I/O errors occur then the
- *   value returned refers to a valid (struct hfs_bnode) corresponding
- *   to the requested node with the requested access type.  The node
- *   is also added to the cache if not previously present and not the
- *   root or header.
- *   If the conditions given above are not met, the bnode in the
- *   returned reference is NULL.
- */
-struct hfs_bnode_ref hfs_bnode_find(struct hfs_btree *tree,
-				    hfs_u32 node, int lock_type)
+static struct hfs_bnode *__hfs_bnode_create(struct hfs_btree *tree, u32 cnid)
 {
-	struct hfs_bnode *bn;
-	struct hfs_bnode *empty = NULL;
-	struct hfs_bnode_ref bnr;
-
-	bnr.lock_type = HFS_LOCK_NONE;
-	bnr.bn = NULL;
-
-#if defined(DEBUG_BNODES) || defined(DEBUG_ALL)
-	hfs_warn("hfs_bnode_find: %c %d:%d\n",
-		 lock_type==HFS_LOCK_READ?'R':
-			(lock_type==HFS_LOCK_RESRV?'V':'W'),
-		 (int)ntohl(tree->entry.cnid), node);
+	struct super_block *sb;
+	struct hfs_bnode *node, *node2;
+	struct address_space *mapping;
+	struct page *page;
+	int size, block, i, hash;
+	loff_t off;
+
+	if (cnid >= tree->node_count) {
+		printk("HFS: request for non-existent node %d in B*Tree\n", cnid);
+		return NULL;
+	}
+
+	sb = tree->inode->i_sb;
+	size = sizeof(struct hfs_bnode) + tree->pages_per_bnode *
+		sizeof(struct page *);
+	node = kmalloc(size, GFP_KERNEL);
+	if (!node)
+		return NULL;
+	memset(node, 0, size);
+	node->tree = tree;
+	node->this = cnid;
+	set_bit(HFS_BNODE_NEW, &node->flags);
+	atomic_set(&node->refcnt, 1);
+	dprint(DBG_BNODE_REFS, "new_node(%d:%d): 1\n",
+	       node->tree->cnid, node->this);
+	init_waitqueue_head(&node->lock_wq);
+	spin_lock(&tree->hash_lock);
+	node2 = hfs_bnode_findhash(tree, cnid);
+	if (!node2) {
+		hash = hfs_bnode_hash(cnid);
+		node->next_hash = tree->node_hash[hash];
+		tree->node_hash[hash] = node;
+		tree->node_hash_cnt++;
+	} else {
+		spin_unlock(&tree->hash_lock);
+		kfree(node);
+		wait_event(node2->lock_wq, !test_bit(HFS_BNODE_NEW, &node2->flags));
+		return node2;
+	}
+	spin_unlock(&tree->hash_lock);
+
+	mapping = tree->inode->i_mapping;
+	off = (loff_t)cnid * tree->node_size;
+	block = off >> PAGE_CACHE_SHIFT;
+	node->page_offset = off & ~PAGE_CACHE_MASK;
+	for (i = 0; i < tree->pages_per_bnode; i++) {
+		page = read_cache_page(mapping, block++, (filler_t *)mapping->a_ops->readpage, NULL);
+		if (IS_ERR(page))
+			goto fail;
+#if !REF_PAGES
+		page_cache_release(page);
 #endif
+		node->page[i] = page;
+	}
 
-	/* check special cases */
-	if (!node) {
-		bn = &tree->head;
-		goto return_it;
-	} else if (node == tree->bthRoot) {
-		bn = tree->root;
-		goto return_it;
-	} 
-
-restart:
-	/* look for the node in the cache. */
-	bn = bhash(tree, node);
-	while (bn && (bn->magic == HFS_BNODE_MAGIC)) {
-		if (bn->node == node) {
-			goto found_it;
-		}
-		bn = bn->next;
+	return node;
+fail:
+	set_bit(HFS_BNODE_ERROR, &node->flags);
+	return node;
+}
+
+void hfs_bnode_unhash(struct hfs_bnode *node)
+{
+	struct hfs_bnode **p;
+
+	dprint(DBG_BNODE_REFS, "remove_node(%d:%d): %d\n",
+		node->tree->cnid, node->this, atomic_read(&node->refcnt));
+	for (p = &node->tree->node_hash[hfs_bnode_hash(node->this)];
+	     *p && *p != node; p = &(*p)->next_hash)
+		;
+	if (!*p)
+		BUG();
+	*p = node->next_hash;
+	node->tree->node_hash_cnt--;
+}
+
+/* Load a particular node out of a tree */
+struct hfs_bnode *hfs_bnode_find(struct hfs_btree *tree, u32 num)
+{
+	struct hfs_bnode *node;
+	struct hfs_bnode_desc *desc;
+	int i, rec_off, off, next_off;
+	int entry_size, key_size;
+
+	spin_lock(&tree->hash_lock);
+	node = hfs_bnode_findhash(tree, num);
+	if (node) {
+		hfs_bnode_get(node);
+		spin_unlock(&tree->hash_lock);
+		wait_event(node->lock_wq, !test_bit(HFS_BNODE_NEW, &node->flags));
+		return node;
+	}
+	spin_unlock(&tree->hash_lock);
+	node = __hfs_bnode_create(tree, num);
+	if (!node)
+		return ERR_PTR(-ENOMEM);
+	if (!test_bit(HFS_BNODE_NEW, &node->flags))
+		return node;
+
+	desc = (struct hfs_bnode_desc *)(kmap(node->page[0]) + node->page_offset);
+	node->prev = be32_to_cpu(desc->prev);
+	node->next = be32_to_cpu(desc->next);
+	node->num_recs = be16_to_cpu(desc->num_recs);
+	node->type = desc->type;
+	node->height = desc->height;
+	kunmap(node->page[0]);
+
+	switch (node->type) {
+	case HFS_NODE_HEADER:
+	case HFS_NODE_MAP:
+		if (node->height != 0)
+			goto node_error;
+		break;
+	case HFS_NODE_LEAF:
+		if (node->height != 1)
+			goto node_error;
+		break;
+	case HFS_NODE_INDEX:
+		if (node->height <= 1 || node->height > tree->depth)
+			goto node_error;
+		break;
+	default:
+		goto node_error;
 	}
 
-	if (!empty) {
-#if defined(DEBUG_BNODES) || defined(DEBUG_ALL)
-		++bnode_count;
-#endif
-		if (HFS_NEW(empty)) {
-			goto restart;
-		}
-		return bnr;
+	rec_off = tree->node_size - 2;
+	off = hfs_bnode_read_u16(node, rec_off);
+	if (off != sizeof(struct hfs_bnode_desc))
+		goto node_error;
+	for (i = 1; i <= node->num_recs; off = next_off, i++) {
+		rec_off -= 2;
+		next_off = hfs_bnode_read_u16(node, rec_off);
+		if (next_off <= off ||
+		    next_off > tree->node_size ||
+		    next_off & 1)
+			goto node_error;
+		entry_size = next_off - off;
+		if (node->type != HFS_NODE_INDEX &&
+		    node->type != HFS_NODE_LEAF)
+			continue;
+		key_size = hfs_bnode_read_u8(node, off) + 1;
+		if (key_size >= entry_size /*|| key_size & 1*/)
+			goto node_error;
+	}
+	clear_bit(HFS_BNODE_NEW, &node->flags);
+	wake_up(&node->lock_wq);
+	return node;
+
+node_error:
+	set_bit(HFS_BNODE_ERROR, &node->flags);
+	clear_bit(HFS_BNODE_NEW, &node->flags);
+	wake_up(&node->lock_wq);
+	hfs_bnode_put(node);
+	return ERR_PTR(-EIO);
+}
+
+void hfs_bnode_free(struct hfs_bnode *node)
+{
+	//int i;
+
+	//for (i = 0; i < node->tree->pages_per_bnode; i++)
+	//	if (node->page[i])
+	//		page_cache_release(node->page[i]);
+	kfree(node);
+}
+
+struct hfs_bnode *hfs_bnode_create(struct hfs_btree *tree, u32 num)
+{
+	struct hfs_bnode *node;
+	struct page **pagep;
+	int i;
+
+	spin_lock(&tree->hash_lock);
+	node = hfs_bnode_findhash(tree, num);
+	spin_unlock(&tree->hash_lock);
+	if (node)
+		BUG();
+	node = __hfs_bnode_create(tree, num);
+	if (!node)
+		return ERR_PTR(-ENOMEM);
+
+	pagep = node->page;
+	memset(kmap(*pagep) + node->page_offset, 0,
+	       min((int)PAGE_CACHE_SIZE, (int)tree->node_size));
+	set_page_dirty(*pagep);
+	kunmap(*pagep);
+	for (i = 1; i < tree->pages_per_bnode; i++) {
+		memset(kmap(*++pagep), 0, PAGE_CACHE_SIZE);
+		set_page_dirty(*pagep);
+		kunmap(*pagep);
 	}
-	bn = empty;
-	hfs_bnode_read(bn, tree, node, HFS_NOT_STICKY);
-	goto return_it;
-
-found_it:
-	/* check validity */
-	if (bn->magic != HFS_BNODE_MAGIC) {
-		/* If we find a corrupt bnode then we return
-		   NULL.  However, we don't try to remove it
-		   from the cache or release its resources
-		   since we have no idea what kind of trouble
-		   we could get into that way. */
-		hfs_warn("hfs_bnode_find: bnode cache is corrupt.\n");
-		return bnr;
-	} 
-	if (empty) {
-#if defined(DEBUG_BNODES) || defined(DEBUG_ALL)
-		--bnode_count;
+	clear_bit(HFS_BNODE_NEW, &node->flags);
+	wake_up(&node->lock_wq);
+
+	return node;
+}
+
+void hfs_bnode_get(struct hfs_bnode *node)
+{
+	if (node) {
+		atomic_inc(&node->refcnt);
+#if REF_PAGES
+		{
+		int i;
+		for (i = 0; i < node->tree->pages_per_bnode; i++)
+			get_page(node->page[i]);
+		}
 #endif
-		HFS_DELETE(empty);
-	}
-	
-return_it:
-	/* Wait our turn */
-	bnr.bn = bn;
-	hfs_bnode_lock(&bnr, lock_type);
-
-	/* Check for failure to read the node from disk */
-	if (!hfs_buffer_ok(bn->buf)) {
-		hfs_bnode_relse(&bnr);
-	}
-
-#if defined(DEBUG_BNODES) || defined(DEBUG_ALL)
-	if (!bnr.bn) {
-		hfs_warn("hfs_bnode_find: failed\n");
-	} else {
-		hfs_warn("hfs_bnode_find: use %d(%d) lvl %d [%d]\n", bn->count,
-			 bn->buf->b_count, bn->ndNHeight, bnode_count);
-		hfs_warn("hfs_bnode_find: blnk %u flnk %u recs %u\n", 
-			 bn->ndBLink, bn->ndFLink, bn->ndNRecs);
+		dprint(DBG_BNODE_REFS, "get_node(%d:%d): %d\n",
+		       node->tree->cnid, node->this, atomic_read(&node->refcnt));
 	}
-#endif
-
-	return bnr;
 }
 
-/*
- * hfs_bnode_commit()
- *
- * Called to write a possibly dirty bnode back to disk.
- */
-void hfs_bnode_commit(struct hfs_bnode *bn)
+/* Dispose of resources used by a node */
+void hfs_bnode_put(struct hfs_bnode *node)
 {
-	if (hfs_buffer_ok(bn->buf)) {
-		struct NodeDescriptor *nd;
-		nd = (struct NodeDescriptor *)hfs_buffer_data(bn->buf);
-
-		hfs_put_hl(bn->ndFLink, nd->ndFLink);
-		hfs_put_hl(bn->ndBLink, nd->ndBLink);
-		nd->ndType    = bn->ndType;
-		nd->ndNHeight = bn->ndNHeight;
-		hfs_put_hs(bn->ndNRecs, nd->ndNRecs);
-		hfs_buffer_dirty(bn->buf);
+	if (node) {
+		struct hfs_btree *tree = node->tree;
+		int i;
+
+		dprint(DBG_BNODE_REFS, "put_node(%d:%d): %d\n",
+		       node->tree->cnid, node->this, atomic_read(&node->refcnt));
+		if (!atomic_read(&node->refcnt))
+			BUG();
+		if (!atomic_dec_and_lock(&node->refcnt, &tree->hash_lock)) {
+#if REF_PAGES
+			for (i = 0; i < tree->pages_per_bnode; i++)
+				put_page(node->page[i]);
+#endif
+			return;
+		}
+		for (i = 0; i < tree->pages_per_bnode; i++) {
+			mark_page_accessed(node->page[i]);
+#if REF_PAGES
+			put_page(node->page[i]);
+#endif
+		}
 
-		/* increment write count */
-		hfs_mdb_dirty(bn->tree->sys_mdb);
+		if (test_bit(HFS_BNODE_DELETED, &node->flags)) {
+			hfs_bnode_unhash(node);
+			spin_unlock(&tree->hash_lock);
+			hfs_bmap_free(node);
+			hfs_bnode_free(node);
+			return;
+		}
+		spin_unlock(&tree->hash_lock);
 	}
 }
--- diff/fs/hfs/brec.c	2002-10-16 04:28:23.000000000 +0100
+++ source/fs/hfs/brec.c	2004-02-23 13:56:46.000000000 +0000
@@ -1,239 +1,492 @@
 /*
- * linux/fs/hfs/brec.c
+ *  linux/fs/hfs/brec.c
  *
- * Copyright (C) 1995-1997  Paul H. Hargrove
- * This file may be distributed under the terms of the GNU General Public License.
+ * Copyright (C) 2001
+ * Brad Boyer (flar@allandria.com)
+ * (C) 2003 Ardis Technologies <roman@ardistech.com>
  *
- * This file contains the code to access records in a btree.
- *
- * "XXX" in a comment is a note to myself to consider changing something.
- *
- * In function preconditions the term "valid" applied to a pointer to
- * a structure means that the pointer is non-NULL and the structure it
- * points to has all fields initialized to consistent values.
+ * Handle individual btree records
  */
 
-#include "hfs_btree.h"
-
-/*================ File-local functions ================*/
+#include "btree.h"
 
-/*
- * first()
- *
- * returns HFS_BPATH_FIRST if elem->record == 1, 0 otherwise
- */
-static inline int first(const struct hfs_belem *elem)
+/* Get the length and offset of the given record in the given node */
+u16 hfs_brec_lenoff(struct hfs_bnode *node, u16 rec, u16 *off)
 {
-	return (elem->record == 1) ? HFS_BPATH_FIRST : 0;
+	u16 retval[2];
+	u16 dataoff;
+
+	dataoff = node->tree->node_size - (rec + 2) * 2;
+	hfs_bnode_read(node, retval, dataoff, 4);
+	*off = be16_to_cpu(retval[1]);
+	return be16_to_cpu(retval[0]) - *off;
 }
 
-/*
- * overflow()
- *
- * return HFS_BPATH_OVERFLOW if the node has no room for an 
- * additional pointer record, 0 otherwise.
- */
-static inline int overflow(const struct hfs_btree *tree,
-			   const struct hfs_bnode *bnode)
+/* Get the length of the key from a keyed record */
+u16 hfs_brec_keylen(struct hfs_bnode *node, u16 rec)
 {
-	/* there is some algebra involved in getting this form */
-	return ((HFS_SECTOR_SIZE - sizeof(hfs_u32)) <
-		 (bnode_end(bnode) + (2+bnode->ndNRecs)*sizeof(hfs_u16) +
-		  ROUND(tree->bthKeyLen+1))) ?  HFS_BPATH_OVERFLOW : 0;
+	u16 retval, recoff;
+
+	if (node->type != HFS_NODE_INDEX && node->type != HFS_NODE_LEAF)
+		return 0;
+
+	if ((node->type == HFS_NODE_INDEX) &&
+	   !(node->tree->attributes & HFS_TREE_VARIDXKEYS)) {
+		if (node->tree->attributes & HFS_TREE_BIGKEYS)
+			retval = node->tree->max_key_len + 2;
+		else
+			retval = node->tree->max_key_len + 1;
+	} else {
+		recoff = hfs_bnode_read_u16(node, node->tree->node_size - (rec + 1) * 2);
+		if (!recoff)
+			return 0;
+		if (node->tree->attributes & HFS_TREE_BIGKEYS)
+			retval = hfs_bnode_read_u16(node, recoff) + 2;
+		else
+			retval = (hfs_bnode_read_u8(node, recoff) | 1) + 1;
+	}
+	return retval;
 }
 
-/*
- * underflow()
- *
- * return HFS_BPATH_UNDERFLOW if the node will be less that 1/2 full
- * upon removal of a pointer record, 0 otherwise.
- */
-static inline int underflow(const struct hfs_btree *tree,
-			    const struct hfs_bnode *bnode)
+int hfs_brec_insert(struct hfs_find_data *fd, void *entry, int entry_len)
 {
-	return ((bnode->ndNRecs * sizeof(hfs_u16) +
-		 bnode_offset(bnode, bnode->ndNRecs)) <
-		(HFS_SECTOR_SIZE - sizeof(struct NodeDescriptor))/2) ?
-		HFS_BPATH_UNDERFLOW : 0;
-}
+	struct hfs_btree *tree;
+	struct hfs_bnode *node, *new_node;
+	int size, key_len, rec;
+	int data_off, end_off;
+	int idx_rec_off, data_rec_off, end_rec_off;
+	u32 cnid;
+
+	tree = fd->tree;
+	if (!fd->bnode) {
+		if (!tree->root)
+			hfs_btree_inc_height(tree);
+		fd->bnode = hfs_bnode_find(tree, tree->leaf_head);
+		if (IS_ERR(fd->bnode))
+			return PTR_ERR(fd->bnode);
+		fd->record = -1;
+	}
+	new_node = NULL;
+	key_len = (fd->search_key->key_len | 1) + 1;
+again:
+	/* new record idx and complete record size */
+	rec = fd->record + 1;
+	size = key_len + entry_len;
+
+	node = fd->bnode;
+	hfs_bnode_dump(node);
+	/* get last offset */
+	end_rec_off = tree->node_size - (node->num_recs + 1) * 2;
+	end_off = hfs_bnode_read_u16(node, end_rec_off);
+	end_rec_off -= 2;
+	dprint(DBG_BNODE_MOD, "insert_rec: %d, %d, %d, %d\n", rec, size, end_off, end_rec_off);
+	if (size > end_rec_off - end_off) {
+		if (new_node)
+			panic("not enough room!\n");
+		new_node = hfs_bnode_split(fd);
+		if (IS_ERR(new_node))
+			return PTR_ERR(new_node);
+		goto again;
+	}
+	if (node->type == HFS_NODE_LEAF) {
+		tree->leaf_count++;
+		mark_inode_dirty(tree->inode);
+	}
+	node->num_recs++;
+	/* write new last offset */
+	hfs_bnode_write_u16(node, offsetof(struct hfs_bnode_desc, num_recs), node->num_recs);
+	hfs_bnode_write_u16(node, end_rec_off, end_off + size);
+	data_off = end_off;
+	data_rec_off = end_rec_off + 2;
+	idx_rec_off = tree->node_size - (rec + 1) * 2;
+	if (idx_rec_off == data_rec_off)
+		goto skip;
+	/* move all following entries */
+	do {
+		data_off = hfs_bnode_read_u16(node, data_rec_off + 2);
+		hfs_bnode_write_u16(node, data_rec_off, data_off + size);
+		data_rec_off += 2;
+	} while (data_rec_off < idx_rec_off);
+
+	/* move data away */
+	hfs_bnode_move(node, data_off + size, data_off,
+		       end_off - data_off);
+
+skip:
+	hfs_bnode_write(node, fd->search_key, data_off, key_len);
+	hfs_bnode_write(node, entry, data_off + key_len, entry_len);
+	hfs_bnode_dump(node);
+
+	if (new_node) {
+		/* update parent key if we inserted a key
+		 * at the start of the first node
+		 */
+		if (!rec && new_node != node)
+			hfs_brec_update_parent(fd);
+
+		hfs_bnode_put(fd->bnode);
+		if (!new_node->parent) {
+			hfs_btree_inc_height(tree);
+			new_node->parent = tree->root;
+		}
+		fd->bnode = hfs_bnode_find(tree, new_node->parent);
+
+		/* create index data entry */
+		cnid = cpu_to_be32(new_node->this);
+		entry = &cnid;
+		entry_len = sizeof(cnid);
+
+		/* get index key */
+		hfs_bnode_read_key(new_node, fd->search_key, 14);
+		__hfs_brec_find(fd->bnode, fd);
+
+		hfs_bnode_put(new_node);
+		new_node = NULL;
+
+		if (tree->attributes & HFS_TREE_VARIDXKEYS)
+			key_len = fd->search_key->key_len + 1;
+		else {
+			fd->search_key->key_len = tree->max_key_len;
+			key_len = tree->max_key_len + 1;
+		}
+		goto again;
+	}
 
-/*================ Global functions ================*/
+	if (!rec)
+		hfs_brec_update_parent(fd);
 
-/*
- * hfs_brec_next()
- *
- * Description:
- *   Obtain access to a child of an internal node in a B-tree.
- * Input Variable(s):
- *   struct hfs_brec *brec: pointer to the (struct hfs_brec) to
- *    add an element to.
- * Output Variable(s):
- *   NONE
- * Returns:
- *   struct hfs_belem *: pointer to the new path element or NULL
- * Preconditions:
- *   'brec' points to a "valid" (struct hfs_brec), the last element of
- *   which corresponds to a record in a bnode of type ndIndxNode and the
- *   'record' field indicates the index record for the desired child.
- * Postconditions:
- *   If the call to hfs_bnode_find() fails then 'brec' is released
- *   and a NULL is returned.
- *   Otherwise:
- *    Any ancestors in 'brec' that are not needed (as determined by the
- *     'keep_flags' field of 'brec) are released from 'brec'.
- *    A new element is added to 'brec' corresponding to the desired
- *     child.
- *    The child is obtained with the same 'lock_type' field as its
- *     parent.
- *    The 'record' field is initialized to the last record.
- *    A pointer to the new path element is returned.
- */
-struct hfs_belem *hfs_brec_next(struct hfs_brec *brec)
+	return 0;
+}
+
+int hfs_brec_remove(struct hfs_find_data *fd)
 {
-	struct hfs_belem *elem = brec->bottom;
-	hfs_u32 node;
-	int lock_type;
+	struct hfs_btree *tree;
+	struct hfs_bnode *node, *parent;
+	int end_off, rec_off, data_off, size;
+
+	tree = fd->tree;
+	node = fd->bnode;
+again:
+	rec_off = tree->node_size - (fd->record + 2) * 2;
+	end_off = tree->node_size - (node->num_recs + 1) * 2;
+
+	if (node->type == HFS_NODE_LEAF) {
+		tree->leaf_count--;
+		mark_inode_dirty(tree->inode);
+	}
+	hfs_bnode_dump(node);
+	dprint(DBG_BNODE_MOD, "remove_rec: %d, %d\n", fd->record, fd->keylength + fd->entrylength);
+	if (!--node->num_recs) {
+		hfs_bnode_unlink(node);
+		if (!node->parent)
+			return 0;
+		parent = hfs_bnode_find(tree, node->parent);
+		if (IS_ERR(parent))
+			return PTR_ERR(parent);
+		hfs_bnode_put(node);
+		node = fd->bnode = parent;
 
-	/* release unneeded ancestors */
-	elem->flags = first(elem) |
-		      overflow(brec->tree, elem->bnr.bn) |
-		      underflow(brec->tree, elem->bnr.bn);
-	if (!(brec->keep_flags & elem->flags)) {
-		hfs_brec_relse(brec, brec->bottom-1);
-	} else if ((brec->bottom-2 >= brec->top) &&
-		   !(elem->flags & (elem-1)->flags)) {
-		hfs_brec_relse(brec, brec->bottom-2);
+		__hfs_brec_find(node, fd);
+		goto again;
 	}
+	hfs_bnode_write_u16(node, offsetof(struct hfs_bnode_desc, num_recs), node->num_recs);
+
+	if (rec_off == end_off)
+		goto skip;
+	size = fd->keylength + fd->entrylength;
+
+	do {
+		data_off = hfs_bnode_read_u16(node, rec_off);
+		hfs_bnode_write_u16(node, rec_off + 2, data_off - size);
+		rec_off -= 2;
+	} while (rec_off >= end_off);
+
+	/* fill hole */
+	hfs_bnode_move(node, fd->keyoffset, fd->keyoffset + size,
+		       data_off - fd->keyoffset - size);
+skip:
+	hfs_bnode_dump(node);
+	if (!fd->record)
+		hfs_brec_update_parent(fd);
+	return 0;
+}
 
-	node = hfs_get_hl(belem_record(elem));
-	lock_type = elem->bnr.lock_type;
+struct hfs_bnode *hfs_bnode_split(struct hfs_find_data *fd)
+{
+	struct hfs_btree *tree;
+	struct hfs_bnode *node, *new_node;
+	struct hfs_bnode_desc node_desc;
+	int num_recs, new_rec_off, new_off, old_rec_off;
+	int data_start, data_end, size;
+
+	tree = fd->tree;
+	node = fd->bnode;
+	new_node = hfs_bmap_alloc(tree);
+	if (IS_ERR(new_node))
+		return new_node;
+	hfs_bnode_get(node);
+	dprint(DBG_BNODE_MOD, "split_nodes: %d - %d - %d\n",
+		node->this, new_node->this, node->next);
+	new_node->next = node->next;
+	new_node->prev = node->this;
+	new_node->parent = node->parent;
+	new_node->type = node->type;
+	new_node->height = node->height;
+
+	size = tree->node_size / 2 - node->num_recs * 2 - 14;
+	old_rec_off = tree->node_size - 4;
+	num_recs = 1;
+	for (;;) {
+		data_start = hfs_bnode_read_u16(node, old_rec_off);
+		if (data_start > size)
+			break;
+		old_rec_off -= 2;
+		if (++num_recs < node->num_recs)
+			continue;
+		/* panic? */
+		hfs_bnode_put(node);
+		hfs_bnode_put(new_node);
+		return ERR_PTR(-ENOSPC);
+	}
 
-	if (!node || hfs_bnode_in_brec(node, brec)) {
-		hfs_warn("hfs_bfind: corrupt btree\n");
-		hfs_brec_relse(brec, NULL);
-		return NULL;
+	if (fd->record + 1 < num_recs) {
+		/* new record is in the lower half,
+		 * so leave some more space there
+		 */
+		old_rec_off += 2;
+		num_recs--;
+		data_start = hfs_bnode_read_u16(node, old_rec_off);
+	} else {
+		hfs_bnode_put(node);
+		hfs_bnode_get(new_node);
+		fd->bnode = new_node;
+		fd->record -= num_recs;
+		fd->keyoffset -= data_start - 14;
+		fd->entryoffset -= data_start - 14;
 	}
+	new_node->num_recs = node->num_recs - num_recs;
+	node->num_recs = num_recs;
 
-	++elem;
-	++brec->bottom;
+	new_rec_off = tree->node_size - 2;
+	new_off = 14;
+	size = data_start - new_off;
+	num_recs = new_node->num_recs;
+	data_end = data_start;
+	while (num_recs) {
+		hfs_bnode_write_u16(new_node, new_rec_off, new_off);
+		old_rec_off -= 2;
+		new_rec_off -= 2;
+		data_end = hfs_bnode_read_u16(node, old_rec_off);
+		new_off = data_end - size;
+		num_recs--;
+	}
+	hfs_bnode_write_u16(new_node, new_rec_off, new_off);
+	hfs_bnode_copy(new_node, 14, node, data_start, data_end - data_start);
 
-	elem->bnr = hfs_bnode_find(brec->tree, node, lock_type);
-	if (!elem->bnr.bn) {
-		hfs_brec_relse(brec, NULL);
-		return NULL;
+	/* update new bnode header */
+	node_desc.next = cpu_to_be32(new_node->next);
+	node_desc.prev = cpu_to_be32(new_node->prev);
+	node_desc.type = new_node->type;
+	node_desc.height = new_node->height;
+	node_desc.num_recs = cpu_to_be16(new_node->num_recs);
+	node_desc.reserved = 0;
+	hfs_bnode_write(new_node, &node_desc, 0, sizeof(node_desc));
+
+	/* update previous bnode header */
+	node->next = new_node->this;
+	hfs_bnode_read(node, &node_desc, 0, sizeof(node_desc));
+	node_desc.next = cpu_to_be32(node->next);
+	node_desc.num_recs = cpu_to_be16(node->num_recs);
+	hfs_bnode_write(node, &node_desc, 0, sizeof(node_desc));
+
+	/* update next bnode header */
+	if (new_node->next) {
+		struct hfs_bnode *next_node = hfs_bnode_find(tree, new_node->next);
+		next_node->prev = new_node->this;
+		hfs_bnode_read(next_node, &node_desc, 0, sizeof(node_desc));
+		node_desc.prev = cpu_to_be32(next_node->prev);
+		hfs_bnode_write(next_node, &node_desc, 0, sizeof(node_desc));
+		hfs_bnode_put(next_node);
+	} else if (node->this == tree->leaf_tail) {
+		/* if there is no next node, this might be the new tail */
+		tree->leaf_tail = new_node->this;
+		mark_inode_dirty(tree->inode);
 	}
-	elem->record = elem->bnr.bn->ndNRecs;
 
-	return elem;
+	hfs_bnode_dump(node);
+	hfs_bnode_dump(new_node);
+	hfs_bnode_put(node);
+
+	return new_node;
 }
 
-/*
- * hfs_brec_lock()
- *
- * Description:
- *   This function obtains HFS_LOCK_WRITE access to the bnode
- *   containing this hfs_brec.	All descendents in the path from this
- *   record to the leaf are given HFS_LOCK_WRITE access and all
- *   ancestors in the path from the root to here are released.
- * Input Variable(s):
- *   struct hfs_brec *brec: pointer to the brec to obtain
- *    HFS_LOCK_WRITE access to some of the nodes of.
- *   struct hfs_belem *elem: the first node to lock or NULL for all
- * Output Variable(s):
- *   NONE
- * Returns:
- *   void
- * Preconditions:
- *   'brec' points to a "valid" (struct hfs_brec)
- * Postconditions: 
- *   All nodes between the indicated node and the beginning of the path
- *    are released.  hfs_bnode_lock() is called in turn on each node
- *    from the indicated node to the leaf node of the path, with a
- *    lock_type argument of HFS_LOCK_WRITE.  If one of those calls
- *    results in deadlock, then this function will never return.
- */
-void hfs_brec_lock(struct hfs_brec *brec, struct hfs_belem *elem) 
+int hfs_brec_update_parent(struct hfs_find_data *fd)
 {
-	if (!elem) {
-		elem = brec->top;
-	} else if (elem > brec->top) {
-		hfs_brec_relse(brec, elem-1);
+	struct hfs_btree *tree;
+	struct hfs_bnode *node, *new_node, *parent;
+	int newkeylen, diff;
+	int rec, rec_off, end_rec_off;
+	int start_off, end_off;
+
+	tree = fd->tree;
+	node = fd->bnode;
+	new_node = NULL;
+	if (!node->parent)
+		return 0;
+
+again:
+	parent = hfs_bnode_find(tree, node->parent);
+	if (IS_ERR(parent))
+		return PTR_ERR(parent);
+	__hfs_brec_find(parent, fd);
+	hfs_bnode_dump(parent);
+	rec = fd->record;
+
+	/* size difference between old and new key */
+	if (tree->attributes & HFS_TREE_VARIDXKEYS)
+		newkeylen = (hfs_bnode_read_u8(node, 14) | 1) + 1;
+	else
+		fd->keylength = newkeylen = tree->max_key_len + 1;
+	dprint(DBG_BNODE_MOD, "update_rec: %d, %d, %d\n", rec, fd->keylength, newkeylen);
+
+	rec_off = tree->node_size - (rec + 2) * 2;
+	end_rec_off = tree->node_size - (parent->num_recs + 1) * 2;
+	diff = newkeylen - fd->keylength;
+	if (!diff)
+		goto skip;
+	if (diff > 0) {
+		end_off = hfs_bnode_read_u16(parent, end_rec_off);
+		if (end_rec_off - end_off < diff) {
+
+			printk("splitting index node...\n");
+			fd->bnode = parent;
+			new_node = hfs_bnode_split(fd);
+			if (IS_ERR(new_node))
+				return PTR_ERR(new_node);
+			parent = fd->bnode;
+			rec = fd->record;
+			rec_off = tree->node_size - (rec + 2) * 2;
+			end_rec_off = tree->node_size - (parent->num_recs + 1) * 2;
+		}
 	}
 
-	while (elem <= brec->bottom) {
-		hfs_bnode_lock(&elem->bnr, HFS_LOCK_WRITE);
-		++elem;
+	end_off = start_off = hfs_bnode_read_u16(parent, rec_off);
+	hfs_bnode_write_u16(parent, rec_off, start_off + diff);
+	start_off -= 4;	/* move previous cnid too */
+
+	while (rec_off > end_rec_off) {
+		rec_off -= 2;
+		end_off = hfs_bnode_read_u16(parent, rec_off);
+		hfs_bnode_write_u16(parent, rec_off, end_off + diff);
+	}
+	hfs_bnode_move(parent, start_off + diff, start_off,
+		       end_off - start_off);
+skip:
+	hfs_bnode_copy(parent, fd->keyoffset, node, 14, newkeylen);
+	if (!(tree->attributes & HFS_TREE_VARIDXKEYS))
+		hfs_bnode_write_u8(parent, fd->keyoffset, newkeylen - 1);
+	hfs_bnode_dump(parent);
+
+	hfs_bnode_put(node);
+	node = parent;
+
+	if (new_node) {
+		u32 cnid;
+
+		fd->bnode = hfs_bnode_find(tree, new_node->parent);
+		/* create index key and entry */
+		hfs_bnode_read_key(new_node, fd->search_key, 14);
+		cnid = cpu_to_be32(new_node->this);
+
+		__hfs_brec_find(fd->bnode, fd);
+		hfs_brec_insert(fd, &cnid, sizeof(cnid));
+		hfs_bnode_put(fd->bnode);
+		hfs_bnode_put(new_node);
+
+		if (!rec) {
+			if (new_node == node)
+				goto out;
+			/* restore search_key */
+			hfs_bnode_read_key(node, fd->search_key, 14);
+		}
 	}
+
+	if (!rec && node->parent)
+		goto again;
+out:
+	fd->bnode = node;
+	return 0;
 }
 
-/*
- * hfs_brec_init()
- *
- * Description:
- *   Obtain access to the root node of a B-tree.
- *   Note that this first must obtain access to the header node.
- * Input Variable(s):
- *   struct hfs_brec *brec: pointer to the (struct hfs_brec) to
- *    initialize
- *   struct hfs_btree *btree: pointer to the (struct hfs_btree)
- *   int lock_type: the type of access to get to the nodes.
- * Output Variable(s):
- *   NONE
- * Returns:
- *   struct hfs_belem *: pointer to the root path element or NULL
- * Preconditions:
- *   'brec' points to a (struct hfs_brec).
- *   'tree' points to a valid (struct hfs_btree).
- * Postconditions:
- *   If the two calls to brec_bnode_find() succeed then the return value
- *   points to a (struct hfs_belem) which corresponds to the root node
- *   of 'brec->tree'.
- *   Both the root and header nodes are obtained with the type of lock
- *   given by (flags & HFS_LOCK_MASK).
- *   The fields 'record' field of the root is set to its last record.
- *   If the header node is not needed to complete the appropriate
- *   operation (as determined by the 'keep_flags' field of 'brec') then
- *   it is released before this function returns.
- *   If either call to brec_bnode_find() fails, NULL is returned and the
- *   (struct hfs_brec) pointed to by 'brec' is invalid.
- */
-struct hfs_belem *hfs_brec_init(struct hfs_brec *brec, struct hfs_btree *tree,
-				int flags)
+int hfs_btree_inc_height(struct hfs_btree *tree)
 {
-	struct hfs_belem *head = &brec->elem[0];
-	struct hfs_belem *root = &brec->elem[1];
-	int lock_type = flags & HFS_LOCK_MASK;
-
-	brec->tree = tree;
-
-	head->bnr = hfs_bnode_find(tree, 0, lock_type);
-	if (!head->bnr.bn) {
-		return NULL;
+	struct hfs_bnode *node, *new_node;
+	struct hfs_bnode_desc node_desc;
+	int key_size, rec;
+	u32 cnid;
+
+	node = NULL;
+	if (tree->root) {
+		node = hfs_bnode_find(tree, tree->root);
+		if (IS_ERR(node))
+			return PTR_ERR(node);
 	}
-
-	root->bnr = hfs_bnode_find(tree, tree->bthRoot, lock_type);
-	if (!root->bnr.bn) {
-		hfs_bnode_relse(&head->bnr);
-		return NULL;
+	new_node = hfs_bmap_alloc(tree);
+	if (IS_ERR(new_node)) {
+		hfs_bnode_put(node);
+		return PTR_ERR(new_node);
 	}
 
-	root->record = root->bnr.bn->ndNRecs;
-	
-	brec->top = head;
-	brec->bottom = root;
-	
-	brec->keep_flags = flags & HFS_BPATH_MASK;
-
-	/* HFS_BPATH_FIRST not applicable for root */
-	/* and HFS_BPATH_UNDERFLOW is different */
-	root->flags = overflow(tree, root->bnr.bn);
-	if (root->record < 3) {
-		root->flags |= HFS_BPATH_UNDERFLOW;
+	tree->root = new_node->this;
+	if (!tree->depth) {
+		tree->leaf_head = tree->leaf_tail = new_node->this;
+		new_node->type = HFS_NODE_LEAF;
+		new_node->num_recs = 0;
+	} else {
+		new_node->type = HFS_NODE_INDEX;
+		new_node->num_recs = 1;
 	}
+	new_node->parent = 0;
+	new_node->next = 0;
+	new_node->prev = 0;
+	new_node->height = ++tree->depth;
+
+	node_desc.next = cpu_to_be32(new_node->next);
+	node_desc.prev = cpu_to_be32(new_node->prev);
+	node_desc.type = new_node->type;
+	node_desc.height = new_node->height;
+	node_desc.num_recs = cpu_to_be16(new_node->num_recs);
+	node_desc.reserved = 0;
+	hfs_bnode_write(new_node, &node_desc, 0, sizeof(node_desc));
+
+	rec = tree->node_size - 2;
+	hfs_bnode_write_u16(new_node, rec, 14);
+
+	if (node) {
+		/* insert old root idx into new root */
+		node->parent = tree->root;
+		if (node->type == HFS_NODE_LEAF ||
+		    tree->attributes & HFS_TREE_VARIDXKEYS)
+			key_size = hfs_bnode_read_u8(node, 14) + 1;
+		else
+			key_size = tree->max_key_len + 1;
+		hfs_bnode_copy(new_node, 14, node, 14, key_size);
+
+		if (!(tree->attributes & HFS_TREE_VARIDXKEYS)) {
+			key_size = tree->max_key_len + 1;
+			hfs_bnode_write_u8(new_node, 14, tree->max_key_len);
+		}
+		key_size = (key_size + 1) & -2;
+		cnid = cpu_to_be32(node->this);
+		hfs_bnode_write(new_node, &cnid, 14 + key_size, 4);
+
+		rec -= 2;
+		hfs_bnode_write_u16(new_node, rec, 14 + key_size + 4);
 
-	if (!(root->flags & brec->keep_flags)) {
-		hfs_brec_relse(brec, head);
+		hfs_bnode_put(node);
 	}
+	hfs_bnode_put(new_node);
+	mark_inode_dirty(tree->inode);
 
-	return root;
+	return 0;
 }
--- diff/fs/hfs/btree.c	2002-10-16 04:27:53.000000000 +0100
+++ source/fs/hfs/btree.c	2004-02-23 13:56:46.000000000 +0000
@@ -1,323 +1,328 @@
 /*
- * linux/fs/hfs/btree.c
+ *  linux/fs/hfs/btree.c
  *
- * Copyright (C) 1995-1997  Paul H. Hargrove
- * This file may be distributed under the terms of the GNU General Public License.
+ * Copyright (C) 2001
+ * Brad Boyer (flar@allandria.com)
+ * (C) 2003 Ardis Technologies <roman@ardistech.com>
  *
- * This file contains the code to manipulate the B-tree structure.
- * The catalog and extents files are both B-trees.
- *
- * "XXX" in a comment is a note to myself to consider changing something.
- *
- * In function preconditions the term "valid" applied to a pointer to
- * a structure means that the pointer is non-NULL and the structure it
- * points to has all fields initialized to consistent values.
- *
- * The code in this file initializes some structures which contain
- * pointers by calling memset(&foo, 0, sizeof(foo)).
- * This produces the desired behavior only due to the non-ANSI
- * assumption that the machine representation of NULL is all zeros.
+ * Handle opening/closing btree
  */
 
-#include "hfs_btree.h"
+#include <linux/pagemap.h>
 
-/*================ File-local functions ================*/
+#include "btree.h"
 
-/*
- * hfs_bnode_ditch() 
- *
- * Description:
- *   This function deletes an entire linked list of bnodes, so it
- *   does not need to keep the linked list consistent as
- *   hfs_bnode_delete() does.
- *   Called by hfs_btree_init() for error cleanup and by hfs_btree_free().
- * Input Variable(s):
- *   struct hfs_bnode *bn: pointer to the first (struct hfs_bnode) in
- *    the linked list to be deleted.
- * Output Variable(s):
- *   NONE
- * Returns:
- *   void
- * Preconditions:
- *   'bn' is NULL or points to a "valid" (struct hfs_bnode) with a 'prev'
- *    field of NULL.
- * Postconditions:
- *   'bn' and all (struct hfs_bnode)s in the chain of 'next' pointers
- *   are deleted, freeing the associated memory and hfs_buffer_put()ing
- *   the associated buffer.
- */
-static void hfs_bnode_ditch(struct hfs_bnode *bn) {
-	struct hfs_bnode *tmp;
-#if defined(DEBUG_BNODES) || defined(DEBUG_ALL)
-	extern int bnode_count;
-#endif
-
-	while (bn != NULL) {
-		tmp = bn->next;
-#if defined(DEBUG_BNODES) || defined(DEBUG_ALL)
-		hfs_warn("deleting node %d from tree %d with count %d\n",
-		         bn->node, (int)ntohl(bn->tree->entry.cnid), bn->count);
-		--bnode_count;
-#endif
-		hfs_buffer_put(bn->buf); /* safe: checks for NULL argument */
-
-		/* free all but the header */
-		if (bn->node) {
-			HFS_DELETE(bn);
-		}
-		bn = tmp;
+/* Get a reference to a B*Tree and do some initial checks */
+struct hfs_btree *hfs_btree_open(struct super_block *sb, u32 id, btree_keycmp keycmp)
+{
+	struct hfs_btree *tree;
+	struct hfs_btree_header_rec *head;
+	struct address_space *mapping;
+	struct page *page;
+	unsigned int shift, size;
+
+	tree = kmalloc(sizeof(*tree), GFP_KERNEL);
+	if (!tree)
+		return NULL;
+	memset(tree, 0, sizeof(*tree));
+
+	init_MUTEX(&tree->tree_lock);
+	spin_lock_init(&tree->hash_lock);
+	/* Set the correct compare function */
+	tree->sb = sb;
+	tree->cnid = id;
+	tree->keycmp = keycmp;
+
+	tree->inode = iget_locked(sb, id);
+	if (!tree->inode)
+		goto free_tree;
+	if (!(tree->inode->i_state & I_NEW))
+		BUG();
+	{
+	struct hfs_mdb *mdb = HFS_SB(sb)->mdb;
+	HFS_I(tree->inode)->flags = 0;
+	init_MUTEX(&HFS_I(tree->inode)->extents_lock);
+	switch (id) {
+	case HFS_EXT_CNID:
+		hfs_inode_read_fork(tree->inode, mdb->drXTExtRec, mdb->drXTFlSize,
+				    mdb->drXTFlSize, be32_to_cpu(mdb->drXTClpSiz));
+		tree->inode->i_mapping->a_ops = &hfs_btree_aops;
+		break;
+	case HFS_CAT_CNID:
+		hfs_inode_read_fork(tree->inode, mdb->drCTExtRec, mdb->drCTFlSize,
+				    mdb->drCTFlSize, be32_to_cpu(mdb->drCTClpSiz));
+		tree->inode->i_mapping->a_ops = &hfs_btree_aops;
+		break;
+	default:
+		BUG();
 	}
-}
+	}
+	unlock_new_inode(tree->inode);
 
-/*================ Global functions ================*/
+	mapping = tree->inode->i_mapping;
+	page = read_cache_page(mapping, 0, (filler_t *)mapping->a_ops->readpage, NULL);
+	if (IS_ERR(page))
+		goto free_tree;
+
+	/* Load the header */
+	head = (struct hfs_btree_header_rec *)(kmap(page) + sizeof(struct hfs_bnode_desc));
+	tree->root = be32_to_cpu(head->root);
+	tree->leaf_count = be32_to_cpu(head->leaf_count);
+	tree->leaf_head = be32_to_cpu(head->leaf_head);
+	tree->leaf_tail = be32_to_cpu(head->leaf_tail);
+	tree->node_count = be32_to_cpu(head->node_count);
+	tree->free_nodes = be32_to_cpu(head->free_nodes);
+	tree->attributes = be32_to_cpu(head->attributes);
+	tree->node_size = be16_to_cpu(head->node_size);
+	tree->max_key_len = be16_to_cpu(head->max_key_len);
+	tree->depth = be16_to_cpu(head->depth);
+
+	size = tree->node_size;
+	if (!size || size & (size - 1))
+		goto fail_page;
+	if (!tree->node_count)
+		goto fail_page;
+	for (shift = 0; size >>= 1; shift += 1)
+		;
+	tree->node_size_shift = shift;
+
+	tree->pages_per_bnode = (tree->node_size + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
+
+	kunmap(page);
+	page_cache_release(page);
+	return tree;
+
+ fail_page:
+	tree->inode->i_mapping->a_ops = &hfs_aops;
+	page_cache_release(page);
+ free_tree:
+	iput(tree->inode);
+	kfree(tree);
+	return NULL;
+}
 
-/*
- * hfs_btree_free()
- *
- * Description:
- *   This function frees a (struct hfs_btree) obtained from hfs_btree_init().
- *   Called by hfs_put_super().
- * Input Variable(s):
- *   struct hfs_btree *bt: pointer to the (struct hfs_btree) to free
- * Output Variable(s):
- *   NONE
- * Returns:
- *   void
- * Preconditions:
- *   'bt' is NULL or points to a "valid" (struct hfs_btree)
- * Postconditions:
- *   If 'bt' points to a "valid" (struct hfs_btree) then all (struct
- *    hfs_bnode)s associated with 'bt' are freed by calling
- *    hfs_bnode_ditch() and the memory associated with the (struct
- *    hfs_btree) is freed.
- *   If 'bt' is NULL or not "valid" an error is printed and nothing
- *    is changed.
- */
-void hfs_btree_free(struct hfs_btree *bt)
+/* Release resources used by a btree */
+void hfs_btree_close(struct hfs_btree *tree)
 {
-	int lcv;
+	struct hfs_bnode *node;
+	int i;
 
-	if (bt && (bt->magic == HFS_BTREE_MAGIC)) {
-		hfs_extent_free(&bt->entry.u.file.data_fork);
+	if (!tree)
+		return;
 
-		for (lcv=0; lcv<HFS_CACHELEN; ++lcv) {
-#if defined(DEBUG_BNODES) || defined(DEBUG_ALL)
-			hfs_warn("deleting nodes from bucket %d:\n", lcv);
-#endif
-			hfs_bnode_ditch(bt->cache[lcv]);
+	for (i = 0; i < NODE_HASH_SIZE; i++) {
+		while ((node = tree->node_hash[i])) {
+			tree->node_hash[i] = node->next_hash;
+			if (atomic_read(&node->refcnt))
+				printk("HFS: node %d:%d still has %d user(s)!\n",
+					node->tree->cnid, node->this, atomic_read(&node->refcnt));
+			hfs_bnode_free(node);
+			tree->node_hash_cnt--;
 		}
-
-#if defined(DEBUG_BNODES) || defined(DEBUG_ALL)
-		hfs_warn("deleting header and bitmap nodes\n");
-#endif
-		hfs_bnode_ditch(&bt->head);
-
-#if defined(DEBUG_BNODES) || defined(DEBUG_ALL)
-		hfs_warn("deleting root node\n");
-#endif
-		hfs_bnode_ditch(bt->root);
-
-		HFS_DELETE(bt);
-	} else if (bt) {
-		hfs_warn("hfs_btree_free: corrupted hfs_btree.\n");
 	}
+	iput(tree->inode);
+	kfree(tree);
 }
 
-/*
- * hfs_btree_init()
- *
- * Description:
- *   Given some vital information from the MDB (HFS superblock),
- *   initializes the fields of a (struct hfs_btree).
- * Input Variable(s):
- *   struct hfs_mdb *mdb: pointer to the MDB
- *   ino_t cnid: the CNID (HFS_CAT_CNID or HFS_EXT_CNID) of the B-tree
- *   hfs_u32 tsize: the size, in bytes, of the B-tree
- *   hfs_u32 csize: the size, in bytes, of the clump size for the B-tree
- * Output Variable(s):
- *   NONE
- * Returns:
- *   (struct hfs_btree *): pointer to the initialized hfs_btree on success,
- *    or NULL on failure
- * Preconditions:
- *   'mdb' points to a "valid" (struct hfs_mdb)
- * Postconditions:
- *   Assuming the inputs are what they claim to be, no errors occur
- *   reading from disk, and no inconsistencies are noticed in the data
- *   read from disk, the return value is a pointer to a "valid"
- *   (struct hfs_btree).  If there are errors reading from disk or
- *   inconsistencies are noticed in the data read from disk, then and
- *   all resources that were allocated are released and NULL is
- *   returned.	If the inputs are not what they claim to be or if they
- *   are unnoticed inconsistencies in the data read from disk then the
- *   returned hfs_btree is probably going to lead to errors when it is
- *   used in a non-trivial way.
- */
-struct hfs_btree * hfs_btree_init(struct hfs_mdb *mdb, ino_t cnid,
-				  hfs_byte_t ext[12],
-				  hfs_u32 tsize, hfs_u32 csize)
+void hfs_btree_write(struct hfs_btree *tree)
 {
-	struct hfs_btree * bt;
-	struct BTHdrRec * th;
-	struct hfs_bnode * tmp;
-	unsigned int next;
-#if defined(DEBUG_HEADER) || defined(DEBUG_ALL)
-	unsigned char *p, *q;
-#endif
-
-	if (!mdb || !ext || !HFS_NEW(bt)) {
-		goto bail3;
-	}
-
-	bt->magic = HFS_BTREE_MAGIC;
-	bt->sys_mdb = mdb->sys_mdb;
-	bt->reserved = 0;
-	sema_init(&bt->sem, 1);
-	bt->dirt = 0;
-	memset(bt->cache, 0, sizeof(bt->cache));
-
-#if 0   /* this is a fake entry. so we don't need to initialize it. */
-	memset(&bt->entry, 0, sizeof(bt->entry));
-	hfs_init_waitqueue(&bt->entry.wait);
-	INIT_LIST_HEAD(&bt->entry.hash);
-	INIT_LIST_HEAD(&bt->entry.list);
-#endif
-
-	bt->entry.mdb = mdb;
-	bt->entry.cnid = cnid;
-	bt->entry.type = HFS_CDR_FIL;
-	bt->entry.u.file.magic = HFS_FILE_MAGIC;
-	bt->entry.u.file.clumpablks = (csize / mdb->alloc_blksz)
-						>> HFS_SECTOR_SIZE_BITS;
-	bt->entry.u.file.data_fork.entry = &bt->entry;
-	bt->entry.u.file.data_fork.lsize = tsize;
-	bt->entry.u.file.data_fork.psize = tsize >> HFS_SECTOR_SIZE_BITS;
-	bt->entry.u.file.data_fork.fork = HFS_FK_DATA;
-	hfs_extent_in(&bt->entry.u.file.data_fork, ext);
-
-	hfs_bnode_read(&bt->head, bt, 0, HFS_STICKY);
-	if (!hfs_buffer_ok(bt->head.buf)) {
-		goto bail2;
-	}
-	th = (struct BTHdrRec *)((char *)hfs_buffer_data(bt->head.buf) +
-						sizeof(struct NodeDescriptor));
+	struct hfs_btree_header_rec *head;
+	struct hfs_bnode *node;
+	struct page *page;
+
+	node = hfs_bnode_find(tree, 0);
+	if (IS_ERR(node))
+		/* panic? */
+		return;
+	/* Load the header */
+	page = node->page[0];
+	head = (struct hfs_btree_header_rec *)(kmap(page) + sizeof(struct hfs_bnode_desc));
+
+	head->root = cpu_to_be32(tree->root);
+	head->leaf_count = cpu_to_be32(tree->leaf_count);
+	head->leaf_head = cpu_to_be32(tree->leaf_head);
+	head->leaf_tail = cpu_to_be32(tree->leaf_tail);
+	head->node_count = cpu_to_be32(tree->node_count);
+	head->free_nodes = cpu_to_be32(tree->free_nodes);
+	head->attributes = cpu_to_be32(tree->attributes);
+	head->depth = cpu_to_be16(tree->depth);
+
+	kunmap(page);
+	set_page_dirty(page);
+	hfs_bnode_put(node);
+}
 
-	/* read in the bitmap nodes (if any) */
-	tmp = &bt->head;
-	while ((next = tmp->ndFLink)) {
-		if (!HFS_NEW(tmp->next)) {
-			goto bail2;
-		}
-		hfs_bnode_read(tmp->next, bt, next, HFS_STICKY);
-		if (!hfs_buffer_ok(tmp->next->buf)) {
-			goto bail2;
-		}
-		tmp->next->prev = tmp;
-		tmp = tmp->next;
-	}
+static struct hfs_bnode *hfs_bmap_new_bmap(struct hfs_bnode *prev, u32 idx)
+{
+	struct hfs_btree *tree = prev->tree;
+	struct hfs_bnode *node;
+	struct hfs_bnode_desc desc;
+	u32 cnid;
+
+	node = hfs_bnode_create(tree, idx);
+	if (IS_ERR(node))
+		return node;
+
+	if (!tree->free_nodes)
+		panic("FIXME!!!");
+	tree->free_nodes--;
+	prev->next = idx;
+	cnid = cpu_to_be32(idx);
+	hfs_bnode_write(prev, &cnid, offsetof(struct hfs_bnode_desc, next), 4);
+
+	node->type = HFS_NODE_MAP;
+	node->num_recs = 1;
+	hfs_bnode_clear(node, 0, tree->node_size);
+	desc.next = 0;
+	desc.prev = 0;
+	desc.type = HFS_NODE_MAP;
+	desc.height = 0;
+	desc.num_recs = cpu_to_be16(1);
+	desc.reserved = 0;
+	hfs_bnode_write(node, &desc, 0, sizeof(desc));
+	hfs_bnode_write_u16(node, 14, 0x8000);
+	hfs_bnode_write_u16(node, tree->node_size - 2, 14);
+	hfs_bnode_write_u16(node, tree->node_size - 4, tree->node_size - 6);
 
-	if (hfs_get_ns(th->bthNodeSize) != htons(HFS_SECTOR_SIZE)) {
-		hfs_warn("hfs_btree_init: bthNodeSize!=512 not supported\n");
-		goto bail2;
-	}
+	return node;
+}
 
-	if (cnid == htonl(HFS_CAT_CNID)) {
-		bt->compare = (hfs_cmpfn)hfs_cat_compare;
-	} else if (cnid == htonl(HFS_EXT_CNID)) {
-		bt->compare = (hfs_cmpfn)hfs_ext_compare;
-	} else {
-		goto bail2;
-	}
-	bt->bthDepth  = hfs_get_hs(th->bthDepth);
-	bt->bthRoot   = hfs_get_hl(th->bthRoot);
-	bt->bthNRecs  = hfs_get_hl(th->bthNRecs);
-	bt->bthFNode  = hfs_get_hl(th->bthFNode);
-	bt->bthLNode  = hfs_get_hl(th->bthLNode);
-	bt->bthNNodes = hfs_get_hl(th->bthNNodes);
-	bt->bthFree   = hfs_get_hl(th->bthFree);
-	bt->bthKeyLen = hfs_get_hs(th->bthKeyLen);
-
-#if defined(DEBUG_HEADER) || defined(DEBUG_ALL)
-	hfs_warn("bthDepth %d\n", bt->bthDepth);
-	hfs_warn("bthRoot %d\n", bt->bthRoot);
-	hfs_warn("bthNRecs %d\n", bt->bthNRecs);
-	hfs_warn("bthFNode %d\n", bt->bthFNode);
-	hfs_warn("bthLNode %d\n", bt->bthLNode);
-	hfs_warn("bthKeyLen %d\n", bt->bthKeyLen);
-	hfs_warn("bthNNodes %d\n", bt->bthNNodes);
-	hfs_warn("bthFree %d\n", bt->bthFree);
-	p = (unsigned char *)hfs_buffer_data(bt->head.buf);
-	q = p + HFS_SECTOR_SIZE;
-	while (p < q) {
-		hfs_warn("%02x %02x %02x %02x %02x %02x %02x %02x "
-		         "%02x %02x %02x %02x %02x %02x %02x %02x\n",
-			 *p++, *p++, *p++, *p++, *p++, *p++, *p++, *p++,
-			 *p++, *p++, *p++, *p++, *p++, *p++, *p++, *p++);
+struct hfs_bnode *hfs_bmap_alloc(struct hfs_btree *tree)
+{
+	struct hfs_bnode *node, *next_node;
+	struct page **pagep;
+	u32 nidx, idx;
+	u16 off, len;
+	u8 *data, byte, m;
+	int i;
+
+	while (!tree->free_nodes) {
+		struct inode *inode = tree->inode;
+		u32 count;
+		int res;
+
+		res = hfs_extend_file(inode);
+		if (res)
+			return ERR_PTR(res);
+		inode->i_blocks = HFS_I(inode)->alloc_blocks *
+				  HFS_SB(tree->sb)->fs_div;
+		HFS_I(inode)->phys_size = inode->i_size =
+			(loff_t)inode->i_blocks << tree->sb->s_blocksize_bits;
+		count = inode->i_size >> tree->node_size_shift;
+		tree->free_nodes = count - tree->node_count;
+		tree->node_count = count;
 	}
-#endif
 
-	/* Read in the root if it exists.
-	   The header always exists, but the root exists only if the
-	   tree is non-empty */
-	if (bt->bthDepth && bt->bthRoot) {
-		if (!HFS_NEW(bt->root)) {
-			goto bail2;
-		}
-		hfs_bnode_read(bt->root, bt, bt->bthRoot, HFS_STICKY);
-		if (!hfs_buffer_ok(bt->root->buf)) {
-			goto bail1;
+	nidx = 0;
+	node = hfs_bnode_find(tree, nidx);
+	if (IS_ERR(node))
+		return node;
+	len = hfs_brec_lenoff(node, 2, &off);
+
+	off += node->page_offset;
+	pagep = node->page + (off >> PAGE_CACHE_SHIFT);
+	data = kmap(*pagep);
+	off &= ~PAGE_CACHE_MASK;
+	idx = 0;
+
+	for (;;) {
+		while (len) {
+			byte = data[off];
+			if (byte != 0xff) {
+				for (m = 0x80, i = 0; i < 8; m >>= 1, i++) {
+					if (!(byte & m)) {
+						idx += i;
+						data[off] |= m;
+						set_page_dirty(*pagep);
+						kunmap(*pagep);
+						tree->free_nodes--;
+						mark_inode_dirty(tree->inode);
+						hfs_bnode_put(node);
+						return hfs_bnode_create(tree, idx);
+					}
+				}
+			}
+			if (++off >= PAGE_CACHE_SIZE) {
+				kunmap(*pagep);
+				data = kmap(*++pagep);
+				off = 0;
+			}
+			idx += 8;
+			len--;
 		}
-	} else {
-		bt->root = NULL;
+		kunmap(*pagep);
+		nidx = node->next;
+		if (!nidx) {
+			printk("create new bmap node...\n");
+			next_node = hfs_bmap_new_bmap(node, idx);
+		} else
+			next_node = hfs_bnode_find(tree, nidx);
+		hfs_bnode_put(node);
+		if (IS_ERR(next_node))
+			return next_node;
+		node = next_node;
+
+		len = hfs_brec_lenoff(node, 0, &off);
+		off += node->page_offset;
+		pagep = node->page + (off >> PAGE_CACHE_SHIFT);
+		data = kmap(*pagep);
+		off &= ~PAGE_CACHE_MASK;
 	}
-
-	return bt;
-
- bail1:
-	hfs_bnode_ditch(bt->root);
- bail2:
-	hfs_bnode_ditch(&bt->head);
-	HFS_DELETE(bt);
- bail3:
-	return NULL;
 }
 
-/*
- * hfs_btree_commit()
- *
- * Called to write a possibly dirty btree back to disk.
- */
-void hfs_btree_commit(struct hfs_btree *bt, hfs_byte_t ext[12], hfs_lword_t size)
+void hfs_bmap_free(struct hfs_bnode *node)
 {
-	if (bt->dirt) {
-		struct BTHdrRec *th;
-		th = (struct BTHdrRec *)((char *)hfs_buffer_data(bt->head.buf) +
-						 sizeof(struct NodeDescriptor));
-
-		hfs_put_hs(bt->bthDepth,  th->bthDepth);
-		hfs_put_hl(bt->bthRoot,   th->bthRoot);
-		hfs_put_hl(bt->bthNRecs,  th->bthNRecs);
-		hfs_put_hl(bt->bthFNode,  th->bthFNode);
-		hfs_put_hl(bt->bthLNode,  th->bthLNode);
-		hfs_put_hl(bt->bthNNodes, th->bthNNodes);
-		hfs_put_hl(bt->bthFree,   th->bthFree);
-		hfs_buffer_dirty(bt->head.buf);
-
-		/*
-		 * Commit the bnodes which are not cached.
-		 * The map nodes don't need to be committed here because
-		 * they are committed every time they are changed.
-		 */
-		hfs_bnode_commit(&bt->head);
-		if (bt->root) {
-			hfs_bnode_commit(bt->root);
+	struct hfs_btree *tree;
+	struct page *page;
+	u16 off, len;
+	u32 nidx;
+	u8 *data, byte, m;
+
+	dprint(DBG_BNODE_MOD, "btree_free_node: %u\n", node->this);
+	tree = node->tree;
+	nidx = node->this;
+	node = hfs_bnode_find(tree, 0);
+	if (IS_ERR(node))
+		return;
+	len = hfs_brec_lenoff(node, 2, &off);
+	while (nidx >= len * 8) {
+		u32 i;
+
+		nidx -= len * 8;
+		i = node->next;
+		hfs_bnode_put(node);
+		if (!i) {
+			/* panic */;
+			printk("HFS: unable to free bnode %u. bmap not found!\n", node->this);
+			return;
 		}
-
-	
-		hfs_put_hl(bt->bthNNodes << HFS_SECTOR_SIZE_BITS, size);
-		hfs_extent_out(&bt->entry.u.file.data_fork, ext);
-		/* hfs_buffer_dirty(mdb->buf); (Done by caller) */
-
-		bt->dirt = 0;
+		node = hfs_bnode_find(tree, i);
+		if (IS_ERR(node))
+			return;
+		if (node->type != HFS_NODE_MAP) {
+			/* panic */;
+			printk("HFS: invalid bmap found! (%u,%d)\n", node->this, node->type);
+			hfs_bnode_put(node);
+			return;
+		}
+		len = hfs_brec_lenoff(node, 0, &off);
+	}
+	off += node->page_offset + nidx / 8;
+	page = node->page[off >> PAGE_CACHE_SHIFT];
+	data = kmap(page);
+	off &= ~PAGE_CACHE_MASK;
+	m = 1 << (~nidx & 7);
+	byte = data[off];
+	if (!(byte & m)) {
+		printk("HFS: trying to free free bnode %u(%d)\n", node->this, node->type);
+		kunmap(page);
+		hfs_bnode_put(node);
+		return;
 	}
+	data[off] = byte & ~m;
+	set_page_dirty(page);
+	kunmap(page);
+	hfs_bnode_put(node);
+	tree->free_nodes++;
+	mark_inode_dirty(tree->inode);
 }
--- diff/fs/hfs/catalog.c	2002-10-16 04:28:32.000000000 +0100
+++ source/fs/hfs/catalog.c	2004-02-23 13:56:46.000000000 +0000
@@ -1,641 +1,75 @@
 /*
- * linux/fs/hfs/catalog.c
+ *  linux/fs/hfs/catalog.c
  *
  * Copyright (C) 1995-1997  Paul H. Hargrove
+ * (C) 2003 Ardis Technologies <roman@ardistech.com>
  * This file may be distributed under the terms of the GNU General Public License.
  *
  * This file contains the functions related to the catalog B-tree.
  *
- * "XXX" in a comment is a note to myself to consider changing something.
- *
- * Cache code shamelessly stolen from 
+ * Cache code shamelessly stolen from
  *     linux/fs/inode.c Copyright (C) 1991, 1992  Linus Torvalds
  *     re-shamelessly stolen Copyright (C) 1997 Linus Torvalds
- *
- * In function preconditions the term "valid" applied to a pointer to
- * a structure means that the pointer is non-NULL and the structure it
- * points to has all fields initialized to consistent values.
- *
- * The code in this file initializes some structures by calling
- * memset(&foo, 0, sizeof(foo)).  This produces the desired behavior
- * only due to the non-ANSI assumption that the machine representation
- */
-
-#include "hfs.h"
-
-/*================ Variable-like macros ================*/
-
-/* Number of hash table slots */
-#define C_HASHBITS  10
-#define C_HASHSIZE  (1UL << C_HASHBITS)
-#define C_HASHMASK  (C_HASHSIZE - 1)
-
-/* Number of entries to fit in a single page on an i386.
- * Actually, now it's used to increment the free entry pool. */
-#define CCACHE_INC (PAGE_SIZE/sizeof(struct hfs_cat_entry))
-#define CCACHE_MAX (CCACHE_INC * 8)
-
-/*================ File-local data types ================*/
-
-/* The catalog record for a file */
-typedef struct {
-	hfs_byte_t	Flags;		/* Flags such as read-only */
-	hfs_byte_t	Typ;		/* file version number = 0 */
-	hfs_finfo_t	UsrWds;		/* data used by the Finder */
-	hfs_lword_t	FlNum;		/* The CNID */
-	hfs_word_t	StBlk;		/* obsolete */
-	hfs_lword_t	LgLen;		/* The logical EOF of the data fork*/
-	hfs_lword_t	PyLen;		/* The physical EOF of the data fork */
-	hfs_word_t	RStBlk;		/* obsolete */
-	hfs_lword_t	RLgLen;		/* The logical EOF of the rsrc fork */
-	hfs_lword_t	RPyLen;		/* The physical EOF of the rsrc fork */
-	hfs_lword_t	CrDat;		/* The creation date */
-	hfs_lword_t	MdDat;		/* The modified date */
-	hfs_lword_t	BkDat;		/* The last backup date */
-	hfs_fxinfo_t	FndrInfo;	/* more data for the Finder */
-	hfs_word_t	ClpSize;	/* number of bytes to allocate
-					   when extending files */
-	hfs_byte_t	ExtRec[12];	/* first extent record
-					   for the data fork */
-	hfs_byte_t	RExtRec[12];	/* first extent record
-					   for the resource fork */
-	hfs_lword_t	Resrv;		/* reserved by Apple */
-} __attribute__((packed)) FIL_REC;
-
-/* the catalog record for a directory */
-typedef struct {
-	hfs_word_t	Flags;		/* flags */
-	hfs_word_t	Val;		/* Valence: number of files and
-					   dirs in the directory */
-	hfs_lword_t	DirID;		/* The CNID */
-	hfs_lword_t	CrDat;		/* The creation date */
-	hfs_lword_t	MdDat;		/* The modification date */
-	hfs_lword_t	BkDat;		/* The last backup date */
-	hfs_dinfo_t	UsrInfo;	/* data used by the Finder */
-	hfs_dxinfo_t	FndrInfo;	/* more data used by Finder */
-	hfs_byte_t	Resrv[16];	/* reserved by Apple */
-} __attribute__((packed)) DIR_REC;
-
-/* the catalog record for a thread */
-typedef struct {
-	hfs_byte_t		Reserv[8];	/* reserved by Apple */
-	hfs_lword_t		ParID;		/* CNID of parent directory */
-	struct hfs_name		CName;		/* The name of this entry */
-}  __attribute__((packed)) THD_REC;
-
-/* A catalog tree record */
-struct hfs_cat_rec {
-	hfs_byte_t		cdrType;	/* The type of entry */
-	hfs_byte_t		cdrResrv2;	/* padding */
-	union {
-		FIL_REC fil;
-		DIR_REC dir;
-		THD_REC thd;
-	} u;
-} __attribute__((packed));
-
-/*================ File-local variables ================*/
- 
-static LIST_HEAD(entry_in_use);
-static LIST_HEAD(entry_unused);
-static struct list_head hash_table[C_HASHSIZE];
-
-static spinlock_t entry_lock = SPIN_LOCK_UNLOCKED;
-
-static struct {
-        int nr_entries;
-        int nr_free_entries;
-} entries_stat;
-
-/*================ File-local functions ================*/
-
-/*
- * brec_to_id
- *
- * Get the CNID from a brec
- */
-static inline hfs_u32 brec_to_id(struct hfs_brec *brec)
-{
-	struct hfs_cat_rec *rec = brec->data;
-
-	return hfs_get_nl((rec->cdrType==HFS_CDR_FIL) ?
-				rec->u.fil.FlNum : rec->u.dir.DirID);
-}
-
-/*
- * hashfn()
- *
- * hash an (struct mdb *) and a (struct hfs_cat_key *) to an integer.
- */
-static inline unsigned int hashfn(const struct hfs_mdb *mdb,
-				  const struct hfs_cat_key *key)
-{
-	unsigned int hash;
-	
-	hash = (unsigned long) mdb | (unsigned long) key->ParID[3] | 
-		hfs_strhash(key->CName.Name, key->CName.Len);
-	hash = hash ^ (hash >> C_HASHBITS) ^ (hash >> C_HASHBITS*2);
-	return hash & C_HASHMASK;
-}
-
-/*
- * hash()
- *
- * hash an (struct mdb *) and a (struct hfs_cat_key *)
- * to a pointer to a slot in the hash table.
- */
-static inline struct list_head *hash(struct hfs_mdb *mdb,
-				     const struct hfs_cat_key *key)
-{
-	return hash_table + hashfn(mdb, key);
-}
-
-static inline void insert_hash(struct hfs_cat_entry *entry)
-{
-	struct list_head *head = hash(entry->mdb, &entry->key);
-	list_add(&entry->hash, head);
-}
-
-static inline void remove_hash(struct hfs_cat_entry *entry)
-{
-	list_del_init(&entry->hash);
-}
-
-/*
- * wait_on_entry()
- *
- * Sleep until a locked entry is unlocked.
- */
-static inline void wait_on_entry(struct hfs_cat_entry * entry)
-{
-	while ((entry->state & HFS_LOCK)) {
-		hfs_sleep_on(&entry->wait);
-	}
-}
-
-/*
- * lock_entry()
- *
- * Obtain an exclusive lock on an entry.
- */
-static void lock_entry(struct hfs_cat_entry * entry)
-{
-	wait_on_entry(entry);
-	spin_lock(&entry_lock);
-	entry->state |= HFS_LOCK;
-	spin_unlock(&entry_lock);
-}
-
-/*
- * lock_entry()
- *
- * Relinquish an exclusive lock on an entry.
- */
-static void unlock_entry(struct hfs_cat_entry * entry)
-{
-	spin_lock(&entry_lock);
-	entry->state &= ~HFS_LOCK;
-	spin_unlock(&entry_lock);
-	hfs_wake_up(&entry->wait);
-}
-
-/* put entry on mdb dirty list. */
-void hfs_cat_mark_dirty(struct hfs_cat_entry *entry)
-{
-        struct hfs_mdb *mdb = entry->mdb;
-
-	spin_lock(&entry_lock);
-	if (!(entry->state & HFS_DIRTY)) {
-	        entry->state |= HFS_DIRTY;
-
-		/* Only add valid (ie hashed) entries to the dirty list. */
-		if (!list_empty(&entry->hash)) {
-		        list_del(&entry->list);
-			list_add(&entry->list, &mdb->entry_dirty);
-		}
-	}
-	spin_unlock(&entry_lock);
-}
-
-/* delete an entry and remove it from the hash table. */
-static void delete_entry(struct hfs_cat_entry *entry)
-{
-        if (!(entry->state & HFS_DELETED)) {
-	        entry->state |= HFS_DELETED;
-		list_del_init(&entry->hash);
-
-	        if (entry->type == HFS_CDR_FIL) {
-		  /* free all extents */
-		  entry->u.file.data_fork.lsize = 0;
-		  hfs_extent_adj(&entry->u.file.data_fork);
-		  entry->u.file.rsrc_fork.lsize = 0;
-		  hfs_extent_adj(&entry->u.file.rsrc_fork);
-		}
-	}
-}
-
-
-static inline void init_entry(struct hfs_cat_entry *entry)
-{
-	memset(entry, 0, sizeof(*entry));
-	hfs_init_waitqueue(&entry->wait);
-	INIT_LIST_HEAD(&entry->hash);
-	INIT_LIST_HEAD(&entry->list);
-}
-
-/*
- * hfs_cat_alloc()
- *
- * Try to allocate another entry. 
  */
-static inline struct hfs_cat_entry *hfs_cat_alloc(void)
-{
-        struct hfs_cat_entry *entry;
-
-	if (!HFS_NEW(entry))
-	        return NULL;
-
-	init_entry(entry);
-	return entry;
-}
-
-/* this gets called with the spinlock held. */
-static int grow_entries(void)
-{
-        struct hfs_cat_entry *entry;
-	int i;
-	
-	for (i = 0; i < CCACHE_INC; i++) {
-	        if (!(entry = hfs_cat_alloc()))
-		        break;
-		list_add(&entry->list, &entry_unused);
-	}
 
-	entries_stat.nr_entries += i;
-	entries_stat.nr_free_entries += i;
-	        
-	return i;
-}
+#include "hfs_fs.h"
+#include "btree.h"
 
 /*
- * __read_entry()
+ * hfs_cat_build_key()
  *
- * Convert a (struct hfs_cat_rec) to a (struct hfs_cat_entry).
+ * Given the ID of the parent and the name build a search key.
  */
-static void __read_entry(struct hfs_cat_entry *entry,
-			 const struct hfs_cat_rec *cat)
+void hfs_cat_build_key(btree_key *key, u32 parent, struct qstr *name)
 {
-	entry->type = cat->cdrType;
-
-	if (cat->cdrType == HFS_CDR_DIR) {
-		struct hfs_dir *dir = &entry->u.dir;
-
-		entry->cnid = hfs_get_nl(cat->u.dir.DirID);
-
-		dir->magic = HFS_DIR_MAGIC;
-		dir->flags = hfs_get_ns(cat->u.dir.Flags);
-		memcpy(&entry->info.dir.dinfo, &cat->u.dir.UsrInfo, 16);
-		memcpy(&entry->info.dir.dxinfo, &cat->u.dir.FndrInfo, 16);
-		entry->create_date = hfs_get_nl(cat->u.dir.CrDat);
-		entry->modify_date = hfs_get_nl(cat->u.dir.MdDat);
-		entry->backup_date = hfs_get_nl(cat->u.dir.BkDat);
-		dir->dirs = dir->files = 0;
-		init_rwsem(&dir->sem);
-	} else if (cat->cdrType == HFS_CDR_FIL) {
-		struct hfs_file *fil = &entry->u.file;
-
-		entry->cnid = hfs_get_nl(cat->u.fil.FlNum);
-
-		fil->magic = HFS_FILE_MAGIC;
-
-		fil->data_fork.fork = HFS_FK_DATA;
-		fil->data_fork.entry = entry;
-		fil->data_fork.lsize = hfs_get_hl(cat->u.fil.LgLen);
-		fil->data_fork.psize = hfs_get_hl(cat->u.fil.PyLen) >>
-						     HFS_SECTOR_SIZE_BITS;
-		hfs_extent_in(&fil->data_fork, cat->u.fil.ExtRec);
-
-		fil->rsrc_fork.fork = HFS_FK_RSRC;
-		fil->rsrc_fork.entry = entry;
-		fil->rsrc_fork.lsize = hfs_get_hl(cat->u.fil.RLgLen);
-		fil->rsrc_fork.psize = hfs_get_hl(cat->u.fil.RPyLen) >>
-						     HFS_SECTOR_SIZE_BITS;
-		hfs_extent_in(&fil->rsrc_fork, cat->u.fil.RExtRec);
-
-		memcpy(&entry->info.file.finfo, &cat->u.fil.UsrWds, 16);
-		memcpy(&entry->info.file.fxinfo, &cat->u.fil.FndrInfo, 16);
-
-		entry->create_date = hfs_get_nl(cat->u.fil.CrDat);
-		entry->modify_date = hfs_get_nl(cat->u.fil.MdDat);
-		entry->backup_date = hfs_get_nl(cat->u.fil.BkDat);
-		fil->clumpablks = (hfs_get_hs(cat->u.fil.ClpSize)
-					/ entry->mdb->alloc_blksz)
-						>> HFS_SECTOR_SIZE_BITS;
-		fil->flags = cat->u.fil.Flags;
+	key->cat.reserved = 0;
+	key->cat.ParID = cpu_to_be32(parent);
+	if (name) {
+		hfs_triv2mac(&key->cat.CName, name);
+		key->key_len = 6 + key->cat.CName.len;
 	} else {
-		hfs_warn("hfs_fs: entry is neither file nor directory!\n");
+		memset(&key->cat.CName, 0, sizeof(struct hfs_name));
+		key->key_len = 6;
 	}
 }
 
-/*
- * count_dir_entries()
- *
- * Count the number of files and directories in a given directory.
- */
-static inline void count_dir_entries(struct hfs_cat_entry *entry,
-				     struct hfs_brec *brec)
+int hfs_cat_build_record(hfs_cat_rec *rec, u32 cnid, struct inode *inode)
 {
-	int error = 0;
-	hfs_u32 cnid;
-	hfs_u8 type;
-
-	if (!hfs_cat_open(entry, brec)) {
-		while (!(error = hfs_cat_next(entry, brec, 1, &cnid, &type))) {
-			if (type == HFS_CDR_FIL) {
-				++entry->u.dir.files;
-			} else if (type == HFS_CDR_DIR) {
-				++entry->u.dir.dirs;
-			}
-		} /* -ENOENT is normal termination */
-	}
-	if (error != -ENOENT) {
-		entry->cnid = 0;
-	}
-}
-
-/*
- * read_entry()
- *
- * Convert a (struct hfs_brec) to a (struct hfs_cat_entry).
- */
-static inline void read_entry(struct hfs_cat_entry *entry,
-			      struct hfs_brec *brec)
-{
-	int need_count;
-	struct hfs_cat_rec *rec = brec->data;
-
-	__read_entry(entry, rec);
-
-	need_count = (rec->cdrType == HFS_CDR_DIR) && rec->u.dir.Val;
-
-	hfs_brec_relse(brec, NULL);
-
-	if (need_count) {
-		count_dir_entries(entry, brec);
-	}
-}
-
-/*
- * __write_entry()
- *
- * Convert a (struct hfs_cat_entry) to a (struct hfs_cat_rec).
- */
-static void __write_entry(const struct hfs_cat_entry *entry,
-			  struct hfs_cat_rec *cat)
-{
-	if (entry->type == HFS_CDR_DIR) {
-		const struct hfs_dir *dir = &entry->u.dir;
+	u32 mtime = hfs_mtime();
 
-		hfs_put_ns(dir->flags,             cat->u.dir.Flags);
-		hfs_put_hs(dir->dirs + dir->files, cat->u.dir.Val);
-		hfs_put_nl(entry->cnid,            cat->u.dir.DirID);
-		hfs_put_nl(entry->create_date,     cat->u.dir.CrDat);
-		hfs_put_nl(entry->modify_date,     cat->u.dir.MdDat);
-		hfs_put_nl(entry->backup_date,     cat->u.dir.BkDat);
-		memcpy(&cat->u.dir.UsrInfo, &entry->info.dir.dinfo, 16);
-		memcpy(&cat->u.dir.FndrInfo, &entry->info.dir.dxinfo, 16);
-	} else if (entry->type == HFS_CDR_FIL) {
-		const struct hfs_file *fil = &entry->u.file;
-
-		cat->u.fil.Flags = fil->flags;
-		hfs_put_nl(entry->cnid,            cat->u.fil.FlNum);
-		memcpy(&cat->u.fil.UsrWds, &entry->info.file.finfo, 16);
-		hfs_put_hl(fil->data_fork.lsize, cat->u.fil.LgLen);
-		hfs_put_hl(fil->data_fork.psize << HFS_SECTOR_SIZE_BITS,
- 							cat->u.fil.PyLen);
-		hfs_put_hl(fil->rsrc_fork.lsize, cat->u.fil.RLgLen);
-		hfs_put_hl(fil->rsrc_fork.psize << HFS_SECTOR_SIZE_BITS,
- 							cat->u.fil.RPyLen);
-		hfs_put_nl(entry->create_date,     cat->u.fil.CrDat);
-		hfs_put_nl(entry->modify_date,     cat->u.fil.MdDat);
-		hfs_put_nl(entry->backup_date,     cat->u.fil.BkDat);
-		memcpy(&cat->u.fil.FndrInfo, &entry->info.file.fxinfo, 16);
-		hfs_put_hs((fil->clumpablks * entry->mdb->alloc_blksz)
-				<< HFS_SECTOR_SIZE_BITS, cat->u.fil.ClpSize);
-		hfs_extent_out(&fil->data_fork, cat->u.fil.ExtRec);
-		hfs_extent_out(&fil->rsrc_fork, cat->u.fil.RExtRec);
+	memset(rec, 0, sizeof(*rec));
+	if (S_ISDIR(inode->i_mode)) {
+		rec->type = HFS_CDR_DIR;
+		rec->dir.DirID = cpu_to_be32(cnid);
+		rec->dir.CrDat = mtime;
+		rec->dir.MdDat = mtime;
+		rec->dir.BkDat = 0;
+		rec->dir.UsrInfo.frView = cpu_to_be16(0xff);
+		return sizeof(struct hfs_cat_dir);
 	} else {
-		hfs_warn("__write_entry: invalid entry\n");
-	}
-}
-
-/*
- * write_entry()
- *
- * Write a modified entry back to the catalog B-tree. this gets called
- * with the entry locked.
- */
-static void write_entry(struct hfs_cat_entry * entry)
-{
-	struct hfs_brec brec;
-	int error;
-
-	if (!(entry->state & HFS_DELETED)) {
-		error = hfs_bfind(&brec, entry->mdb->cat_tree,
-				  HFS_BKEY(&entry->key), HFS_BFIND_WRITE);
-		if (!error) {
-			if ((entry->state & HFS_KEYDIRTY)) {
-				/* key may have changed case due to a rename */
-				entry->state &= ~HFS_KEYDIRTY;
-				if (brec.key->KeyLen != entry->key.KeyLen) {
-					hfs_warn("hfs_write_entry: key length "
-						 "changed!\n");
-					error = 1;
-				} else {
-					memcpy(brec.key, &entry->key,
-					       entry->key.KeyLen);
-				}
-			} else if (entry->cnid != brec_to_id(&brec)) {
-				hfs_warn("hfs_write_entry: CNID "
-					 "changed unexpectedly!\n");
-				error = 1;
-			}
-			if (!error) {
-				__write_entry(entry, brec.data);
-			}
-			hfs_brec_relse(&brec, NULL);
-		}
-		if (error) {
-			hfs_warn("hfs_write_entry: unable to write "
-				 "entry %08x\n", entry->cnid);
-		}
-	}
-}
-
-
-/* this gets called with the spinlock held. */
-static struct hfs_cat_entry *find_entry(struct hfs_mdb *mdb,
-					const struct hfs_cat_key *key)
-{
-	struct list_head *tmp, *head = hash(mdb, key);
-	struct hfs_cat_entry * entry;
-
-	tmp = head;
-	for (;;) {
-		tmp = tmp->next;
-		entry = NULL;
-		if (tmp == head)
-			break;
-		entry = list_entry(tmp, struct hfs_cat_entry, hash);
-		if (entry->mdb != mdb)
-			continue;
-		if (hfs_cat_compare(&entry->key, key)) {
-			continue;
-		}
-		entry->count++;
-		break;
+		/* init some fields for the file record */
+		rec->type = HFS_CDR_FIL;
+		rec->file.Flags = HFS_FIL_USED | HFS_FIL_THD;
+		if (!(inode->i_mode & S_IWUSR))
+			rec->file.Flags |= HFS_FIL_LOCK;
+		rec->file.FlNum = cpu_to_be32(cnid);
+		rec->file.CrDat = mtime;
+		rec->file.MdDat = mtime;
+		rec->file.BkDat = 0;
+		rec->file.UsrWds.fdType = HFS_SB(inode->i_sb)->s_type;
+		rec->file.UsrWds.fdCreator = HFS_SB(inode->i_sb)->s_creator;
+		return sizeof(struct hfs_cat_file);
 	}
-
-	return entry;
 }
 
-
-/* be careful. this gets called with the spinlock held. */
-static struct hfs_cat_entry *get_new_entry(struct hfs_mdb *mdb,
-					   const struct hfs_cat_key *key,
-					   const int read)
-{
-	struct hfs_cat_entry *entry;
-	struct list_head *head = hash(mdb, key);
-	struct list_head *tmp;
-
-add_new_entry:
-	tmp = entry_unused.next;
-	if ((tmp != &entry_unused) ) {
-		list_del(tmp);
-		entries_stat.nr_free_entries--;
-		entry = list_entry(tmp, struct hfs_cat_entry, list);
-		list_add(&entry->list, &entry_in_use);
-		list_add(&entry->hash, head);
-		entry->mdb = mdb;
-		entry->count = 1;
-		memcpy(&entry->key, key, sizeof(*key));
-		entry->state = HFS_LOCK;
-		spin_unlock(&entry_lock);
-
-		if (read) {
-		   struct hfs_brec brec;
-
-		   if (hfs_bfind(&brec, mdb->cat_tree,
-				 HFS_BKEY(key), HFS_BFIND_READ_EQ)) {
-		        /* uh oh. we failed to read the record.
-			 * the entry doesn't actually exist. */
-		        goto read_fail;
-		   }
-
-		   read_entry(entry, &brec);
-		   
-		   /* error */
-		   if (!entry->cnid) {
-		        goto read_fail;
-		   }
-
-		   /* we don't have to acquire a spinlock here or
-		    * below for the unlocking bits as we're the first
-		    * user of this entry. */
-		   entry->state &= ~HFS_LOCK;
-		   hfs_wake_up(&entry->wait);
-		}
-
-		return entry;
-	}
-
-
-	/* try to allocate more entries. grow_entries() doesn't release
-	 * the spinlock. */
-	if (grow_entries())
-	        goto add_new_entry;
-
-	spin_unlock(&entry_lock);
-	return NULL;
-
-read_fail: 
-	/* short-cut hfs_cat_put by doing everything here. */
-	spin_lock(&entry_lock);
-	list_del(&entry->hash);
-	list_del(&entry->list);
-	init_entry(entry);
-	list_add(&entry->list, &entry_unused);
-	entries_stat.nr_free_entries++;
-	spin_unlock(&entry_lock);
-	return NULL;
-}
-
-/*
- * get_entry()
- *
- * Try to return an entry for the indicated file or directory.
- * If ('read' == 0) then no attempt will be made to read it from disk
- * and a locked, but uninitialized, entry is returned.
- */
-static struct hfs_cat_entry *get_entry(struct hfs_mdb *mdb,
-				       const struct hfs_cat_key *key,
-				       const int read)
-{
-	struct hfs_cat_entry * entry;
-
-#if defined(DEBUG_CATALOG) || defined(DEBUG_ALL)
-	hfs_warn("hfs_get_entry: mdb=%p key=%s read=%d\n",
-		 mdb, key->CName.Name, read);
-#endif
-
-	spin_lock(&entry_lock);
-	entry = find_entry(mdb, key);
-	if (!entry) {
-	        return get_new_entry(mdb, key, read);
-	}
-	spin_unlock(&entry_lock);
-	wait_on_entry(entry);
-	return entry;
-}
-
-/* 
- * new_cnid()
- *
- * Allocate a CNID to use for a new file or directory.
- */
-static inline hfs_u32 new_cnid(struct hfs_mdb *mdb)
-{
-	/* If the create succeeds then the mdb will get dirtied */
-	return htonl(mdb->next_id++);
-}
-
-/*
- * update_dir()
- *
- * Update counts, times and dirt on a changed directory
- */
-static void update_dir(struct hfs_mdb *mdb, struct hfs_cat_entry *dir,
-		       int is_dir, int count)
-{
-	/* update counts */
-	if (is_dir) {
-		mdb->dir_count += count;
-		dir->u.dir.dirs += count;
-		if (dir->cnid == htonl(HFS_ROOT_CNID)) {
-			mdb->root_dirs += count;
-		}
-	} else {
-		mdb->file_count += count;
-		dir->u.dir.files += count;
-		if (dir->cnid == htonl(HFS_ROOT_CNID)) {
-			mdb->root_files += count;
-		}
-	}
-	
-	/* update times and dirt */
-	dir->modify_date = hfs_time();
-	hfs_cat_mark_dirty(dir);
+static int hfs_cat_build_thread(hfs_cat_rec *rec, int type,
+				u32 parentid, struct qstr *name)
+{
+	rec->type = type;
+	memset(rec->thread.reserved, 0, sizeof(rec->thread.reserved));
+	rec->thread.ParID = cpu_to_be32(parentid);
+	hfs_triv2mac(&rec->thread.CName, name);
+	return sizeof(struct hfs_cat_thread);
 }
 
 /*
@@ -644,301 +78,53 @@ static void update_dir(struct hfs_mdb *m
  * Add a new file or directory to the catalog B-tree and
  * return a (struct hfs_cat_entry) for it in '*result'.
  */
-static int create_entry(struct hfs_cat_entry *parent, struct hfs_cat_key *key,
-			const struct hfs_cat_rec *record, int is_dir,
-			hfs_u32 cnid, struct hfs_cat_entry **result)
-{
-	struct hfs_mdb *mdb = parent->mdb;
-	struct hfs_cat_entry *entry;
-	struct hfs_cat_key thd_key;
-	struct hfs_cat_rec thd_rec;
-	int error, has_thread;
-
-	if (result) {
-		*result = NULL;
-	}
-
-	/* keep readers from getting confused by changing dir size */
-	down_write(&parent->u.dir.sem);
-
-	/* create a locked entry in the cache */
-	entry = get_entry(mdb, key, 0);
-	if (!entry) {
-		/* The entry exists but can't be read */
-		error = -EIO;
-		goto done;
-	}
-
-	if (entry->cnid) {
-		/* The (unlocked) entry exists in the cache */
-		error = -EEXIST;
-		goto bail2;
-	}
-
-	/* limit directory valence to signed 16-bit integer */
-        if ((parent->u.dir.dirs + parent->u.dir.files) >= HFS_MAX_VALENCE) {
-		error = -ENOSPC;
-		goto bail1;
-	}
-
-	has_thread = is_dir || (record->u.fil.Flags & HFS_FIL_THD);
-
-	if (has_thread) {
-		/* init some fields for the thread record */
-		memset(&thd_rec, 0, sizeof(thd_rec));
-		thd_rec.cdrType = is_dir ? HFS_CDR_THD : HFS_CDR_FTH;
-		memcpy(&thd_rec.u.thd.ParID, &key->ParID,
-		       sizeof(hfs_u32) + sizeof(struct hfs_name));
-
-		/* insert the thread record */
-		hfs_cat_build_key(cnid, NULL, &thd_key);
-		error = hfs_binsert(mdb->cat_tree, HFS_BKEY(&thd_key),
-				    &thd_rec, 2 + sizeof(THD_REC));
-		if (error) {
-			goto bail1;
-		}
-	}
-
-	/* insert the record */
-	error = hfs_binsert(mdb->cat_tree, HFS_BKEY(key), record,
-				is_dir ?  2 + sizeof(DIR_REC) :
-					  2 + sizeof(FIL_REC));
-	if (error) {
-		if (has_thread && (error != -EIO)) {
-			/* at least TRY to remove the thread record */
-			(void)hfs_bdelete(mdb->cat_tree, HFS_BKEY(&thd_key));
-		}
-		goto bail1;
-	}
-
-	/* update the parent directory */
-	update_dir(mdb, parent, is_dir, 1);
-
-	/* complete the cache entry and return success */
-	__read_entry(entry, record);
-	unlock_entry(entry);
-
-	if (result) {
-		*result = entry;
-	} else {
-		hfs_cat_put(entry);
-	}
-	goto done;
-
-bail1:
-	/* entry really didn't exist, so we don't need to really delete it.
-	 * we do need to remove it from the hash, though. */
-	entry->state |= HFS_DELETED;
-	remove_hash(entry);
-	unlock_entry(entry);
-bail2:
-	hfs_cat_put(entry);
-done:
-	up_write(&parent->u.dir.sem);
-	return error;
-}
-
-/*================ Global functions ================*/
-
-/* 
- * hfs_cat_put()
- *
- * Release an entry we aren't using anymore.
- *
- * nothing in hfs_cat_put goes to sleep now except on the initial entry.  
- */
-void hfs_cat_put(struct hfs_cat_entry * entry)
-{
-	if (entry) {
-	        wait_on_entry(entry);
-
-		/* just in case. this should never happen. */
-		if (!entry->count) { 
-		  hfs_warn("hfs_cat_put: trying to free free entry: %p\n",
-			   entry);
-		  return;
-		}
-
-#if defined(DEBUG_CATALOG) || defined(DEBUG_ALL)
-		hfs_warn("hfs_cat_put: %p(%u) type=%d state=%lu\n", 
-			 entry, entry->count, entry->type, entry->state);
-#endif
-		spin_lock(&entry_lock);
-		if (!--entry->count) {
-			if ((entry->state & HFS_DELETED))
-			        goto entry_deleted;
-
-			if ((entry->type == HFS_CDR_FIL)) {
-		                /* clear out any cached extents */
-			        if (entry->u.file.data_fork.first.next) {
-				  hfs_extent_free(&entry->u.file.data_fork);
-				}
-				if (entry->u.file.rsrc_fork.first.next) {
-				  hfs_extent_free(&entry->u.file.rsrc_fork);
-				}
-			}
-
-			/* if we put a dirty entry, write it out. */
-			if ((entry->state & HFS_DIRTY)) {
-			        entry->state ^= HFS_DIRTY | HFS_LOCK;
-				write_entry(entry);
-				entry->state &= ~HFS_LOCK;
-			}
-
-			list_del(&entry->hash);
-entry_deleted: 		/* deleted entries have already been removed
-			 * from the hash list. */
-			list_del(&entry->list);
-			if (entries_stat.nr_free_entries > CCACHE_MAX) {
-			        HFS_DELETE(entry);
-				entries_stat.nr_entries--;
-			} else {
-				init_entry(entry);
-				list_add(&entry->list, &entry_unused);
-				entries_stat.nr_free_entries++;
-			}
-		}
-		spin_unlock(&entry_lock);
-	}
-}
-
-/* 
- * hfs_cat_get()
- *
- * Wrapper for get_entry() which always calls with ('read'==1).
- * Used for access to get_entry() from outside this file.
- */
-struct hfs_cat_entry *hfs_cat_get(struct hfs_mdb *mdb,
-				  const struct hfs_cat_key *key)
-{
-	return get_entry(mdb, key, 1);
-}
-
-/* invalidate all entries for a device */
-static void invalidate_list(struct list_head *head, struct hfs_mdb *mdb,
-			    struct list_head *dispose)
-{
-        struct list_head *next;
-
-	next = head->next;
-	for (;;) {
-	        struct list_head *tmp = next;
-		struct hfs_cat_entry * entry;
-		
-		next = next->next;
-		if (tmp == head)
-		        break;
-		entry = list_entry(tmp, struct hfs_cat_entry, list);
-		if (entry->mdb != mdb) {
-			continue;
-		}
-
-		if (!entry->count) {
-		        list_del_init(&entry->hash);
-			list_del(&entry->list);
-			list_add(&entry->list, dispose);
-			continue;
-		}
-		
-		hfs_warn("hfs_fs: entry %p(%u) busy on removed device %s.\n",
-			 entry, entry->count, 
-			 hfs_mdb_name(entry->mdb->sys_mdb));
-	}
-}
-
-/* delete entries from a list */
-static void delete_list(struct list_head *head) 
-{
-	struct list_head *next = head->next;
-	struct hfs_cat_entry *entry;
-	
-	for (;;) {
-		struct list_head * tmp = next;
-
-		next = next->next;
-		if (tmp == head) {
-			break;
-		}
-		entry = list_entry(tmp, struct hfs_cat_entry, list);
-		HFS_DELETE(entry);
-	}
-}
-
-/* 
- * hfs_cat_invalidate()
- *
- * Called by hfs_mdb_put() to remove all the entries
- * in the cache that are associated with a given MDB.
- */
-void hfs_cat_invalidate(struct hfs_mdb *mdb)
-{
-	LIST_HEAD(throw_away);
-
-	spin_lock(&entry_lock);
-	invalidate_list(&entry_in_use, mdb, &throw_away);
-	invalidate_list(&mdb->entry_dirty, mdb, &throw_away);
-	spin_unlock(&entry_lock);
-
-	delete_list(&throw_away);
-#if defined(DEBUG_CATALOG) || defined(DEBUG_ALL)
-	hfs_warn("hfs_cat_invalidate: free=%d total=%d\n",
-		 entries_stat.nr_free_entries,
-		 entries_stat.nr_entries);
-#endif
-}
-
-/*
- * hfs_cat_commit()
- *
- * Called by hfs_mdb_commit() to write dirty entries to the disk buffers.
- */
-void hfs_cat_commit(struct hfs_mdb *mdb)
+int hfs_cat_create(u32 cnid, struct inode *dir, struct qstr *str, struct inode *inode)
 {
-        struct list_head *tmp, *head = &mdb->entry_dirty;
-	struct hfs_cat_entry *entry;
-
-	spin_lock(&entry_lock);
-	while ((tmp = head->prev) != head) {
-	        entry = list_entry(tmp, struct hfs_cat_entry, list);
-		  
-		if ((entry->state & HFS_LOCK)) {
-		        spin_unlock(&entry_lock);
-			wait_on_entry(entry);
-			spin_lock(&entry_lock);
-		} else {
-		       struct list_head *insert = &entry_in_use;
-
-		       if (!entry->count)
-			        insert = entry_in_use.prev;
-
-		       /* add to in_use list */
-		       list_del(&entry->list);
-		       list_add(&entry->list, insert);
-
-		       /* reset DIRTY, set LOCK */
-		       entry->state ^= HFS_DIRTY | HFS_LOCK;
-		       spin_unlock(&entry_lock);
-		       write_entry(entry);
-		       spin_lock(&entry_lock);
-		       entry->state &= ~HFS_LOCK;
-		       hfs_wake_up(&entry->wait);
-		}
+	struct hfs_find_data fd;
+	struct super_block *sb;
+	union hfs_cat_rec entry;
+	int entry_size;
+	int err;
+
+	dprint(DBG_CAT_MOD, "create_cat: %s,%u(%d)\n", str->name, cnid, inode->i_nlink);
+	if (dir->i_size >= HFS_MAX_VALENCE)
+		return -ENOSPC;
+
+	sb = dir->i_sb;
+	hfs_find_init(HFS_SB(sb)->cat_tree, &fd);
+
+	hfs_cat_build_key(fd.search_key, cnid, NULL);
+	entry_size = hfs_cat_build_thread(&entry, S_ISDIR(inode->i_mode) ?
+			HFS_CDR_THD : HFS_CDR_FTH,
+			dir->i_ino, str);
+	err = hfs_brec_find(&fd);
+	if (err != -ENOENT) {
+		if (!err)
+			err = -EEXIST;
+		goto out;
+	}
+	err = hfs_brec_insert(&fd, &entry, entry_size);
+	if (err)
+		goto out;
+
+	hfs_cat_build_key(fd.search_key, dir->i_ino, str);
+	entry_size = hfs_cat_build_record(&entry, cnid, inode);
+	err = hfs_brec_find(&fd);
+	if (err != -ENOENT) {
+		/* panic? */
+		if (!err)
+			err = -EEXIST;
+		goto out;
+	}
+	err = hfs_brec_insert(&fd, &entry, entry_size);
+	if (!err) {
+		dir->i_size++;
+		mark_inode_dirty(dir);
 	}
-	spin_unlock(&entry_lock);
-}
+out:
+	hfs_find_exit(&fd);
 
-/*
- * hfs_cat_free()
- *
- * Releases all the memory allocated in grow_entries().
- * Must call hfs_cat_invalidate() on all MDBs before calling this.
- * This only gets rid of the unused pool of entries. all the other
- * entry references should have either been freed by cat_invalidate
- * or moved onto the unused list.
- */
-void hfs_cat_free(void)
-{
-	delete_list(&entry_unused);
+	return err;
 }
 
 /*
@@ -962,223 +148,43 @@ void hfs_cat_free(void)
  * Postconditions:
  *   This function has no side-effects
  */
-int hfs_cat_compare(const struct hfs_cat_key *key1,
-		    const struct hfs_cat_key *key2)
+int hfs_cat_keycmp(const btree_key *key1, const btree_key *key2)
 {
-	unsigned int parents;
 	int retval;
 
-	parents = hfs_get_hl(key1->ParID) - hfs_get_hl(key2->ParID);
-	if (parents != 0) {
-		retval = (int)parents;
-	} else {
-		retval = hfs_strcmp(key1->CName.Name, key1->CName.Len,
-				    key2->CName.Name, key2->CName.Len);
-	}
-	return retval;
-}
-
-/*
- * hfs_cat_build_key()
- *
- * Given the ID of the parent and the name build a search key.
- */
-void hfs_cat_build_key(hfs_u32 parent, const struct hfs_name *cname,
-		       struct hfs_cat_key *key)
-{
-	hfs_put_nl(parent, key->ParID);
-
-	if (cname) {
-		key->KeyLen = 6 + cname->Len;
-		memcpy(&key->CName, cname, sizeof(*cname));
-	} else {
-		key->KeyLen = 6;
-		memset(&key->CName, 0, sizeof(*cname));
-	}
-}
-
-/*
- * hfs_cat_open()
- *
- * Given a directory on an HFS filesystem get its thread and
- * lock the directory against insertions and deletions.
- * Return 0 on success or an error code on failure.
- */
-int hfs_cat_open(struct hfs_cat_entry *dir, struct hfs_brec *brec)
-{
-	struct hfs_cat_key key;
-	int error;
-
-	if (dir->type != HFS_CDR_DIR)
-		return -EINVAL;
-	
-	/* Block writers */
-	down_read(&dir->u.dir.sem);
-
-	/* Find the directory */
-	hfs_cat_build_key(dir->cnid, NULL, &key);
-	error = hfs_bfind(brec, dir->mdb->cat_tree,
-			  HFS_BKEY(&key), HFS_BFIND_READ_EQ);
-
-	if (error)
-		up_read(&dir->u.dir.sem);
-
-	return error;
-}
-
-/*
- * hfs_cat_next()
- *
- * Given a catalog brec structure, replace it with the count'th next brec
- * in the same directory.
- * Return an error code if there is a problem, 0 if OK.
- * Note that an error code of -ENOENT means there are no more entries
- * in this directory.
- * The directory is "closed" on an error.
- */
-int hfs_cat_next(struct hfs_cat_entry *dir, struct hfs_brec *brec,
-		 hfs_u16 count, hfs_u32 *cnid, hfs_u8 *type)
-{
-	int error;
+	retval = be32_to_cpu(key1->cat.ParID) - be32_to_cpu(key2->cat.ParID);
+	if (!retval)
+		retval = hfs_strcmp(key1->cat.CName.name, key1->cat.CName.len,
+				    key2->cat.CName.name, key2->cat.CName.len);
 
-	if (!dir || !brec) {
-		return -EINVAL;
-	}
-
-	/* Get the count'th next catalog tree entry */
-	error = hfs_bsucc(brec, count);
-	if (!error) {
-		struct hfs_cat_key *key = (struct hfs_cat_key *)brec->key;
-		if (hfs_get_nl(key->ParID) != dir->cnid) {
-			hfs_brec_relse(brec, NULL);
-			error = -ENOENT;
-		}
-	}
-	if (!error) {
-		*type = ((struct hfs_cat_rec *)brec->data)->cdrType;
-		*cnid = brec_to_id(brec);
-	} else {
-		up_read(&dir->u.dir.sem);
-	}
-	return error;
-}
-
-/*
- * hfs_cat_close()
- *
- * Given a catalog brec structure, replace it with the count'th next brec
- * in the same directory.
- * Return an error code if there is a problem, 0 if OK.
- * Note that an error code of -ENOENT means there are no more entries
- * in this directory.
- */
-void hfs_cat_close(struct hfs_cat_entry *dir, struct hfs_brec *brec)
-{
-	if (dir && brec) {
-		hfs_brec_relse(brec, NULL);
-		up_read(&dir->u.dir.sem);
-	}
-}
-
-/*
- * hfs_cat_parent()
- *
- * Given a catalog entry, return the entry for its parent.
- * Uses catalog key for the entry to get its parent's ID
- * and then uses the parent's thread record to locate the
- * parent's actual catalog entry.
- */
-struct hfs_cat_entry *hfs_cat_parent(struct hfs_cat_entry *entry)
-{
-	struct hfs_cat_entry *retval = NULL;
-	struct hfs_mdb *mdb = entry->mdb;
-	struct hfs_brec brec;
-	struct hfs_cat_key key;
-	int error;
-
-	lock_entry(entry);
-	if (!(entry->state & HFS_DELETED)) {
-		hfs_cat_build_key(hfs_get_nl(entry->key.ParID), NULL, &key);
-		error = hfs_bfind(&brec, mdb->cat_tree,
-				  HFS_BKEY(&key), HFS_BFIND_READ_EQ);
-		if (!error) {
-			/* convert thread record to key */
-			struct hfs_cat_rec *rec = brec.data;
-			key.KeyLen = 6 + rec->u.thd.CName.Len;
-			memcpy(&key.ParID, &rec->u.thd.ParID,
-                       	       sizeof(hfs_u32) + sizeof(struct hfs_name));
-
-                	hfs_brec_relse(&brec, NULL);
-
-			retval = hfs_cat_get(mdb, &key);
-		}
-	}
-	unlock_entry(entry);
 	return retval;
 }
-	
-/*
- * hfs_cat_create()
- *
- * Create a new file with the indicated name in the indicated directory.
- * The file will have the indicated flags, type and creator.
- * If successful an (struct hfs_cat_entry) is returned in '*result'.
- */
-int hfs_cat_create(struct hfs_cat_entry *parent, struct hfs_cat_key *key,
-		   hfs_u8 flags, hfs_u32 type, hfs_u32 creator,
-		   struct hfs_cat_entry **result)
-{
-	struct hfs_cat_rec record;
-	hfs_u32 id = new_cnid(parent->mdb);
-	hfs_u32 mtime = hfs_time();
-
-#if defined(DEBUG_CATALOG) || defined(DEBUG_ALL)
-	hfs_warn("hfs_cat_create: %p/%s flags=%d res=%p\n",
-		 parent, key->CName.Name, flags, result);
-#endif
-	/* init some fields for the file record */
-	memset(&record, 0, sizeof(record));
-	record.cdrType = HFS_CDR_FIL;
-	record.u.fil.Flags = flags | HFS_FIL_USED;
-	hfs_put_nl(id,      record.u.fil.FlNum);
-	hfs_put_nl(mtime,   record.u.fil.CrDat);
-	hfs_put_nl(mtime,   record.u.fil.MdDat);
-	hfs_put_nl(0,       record.u.fil.BkDat);
-	hfs_put_nl(type,    record.u.fil.UsrWds.fdType);
-	hfs_put_nl(creator, record.u.fil.UsrWds.fdCreator);
 
-	return create_entry(parent, key, &record, 0, id, result);
+/* Try to get a catalog entry for given catalog id */
+// move to read_super???
+int hfs_cat_find_brec(struct super_block *sb, u32 cnid,
+		      struct hfs_find_data *fd)
+{
+	hfs_cat_rec rec;
+	int res, len, type;
+
+	hfs_cat_build_key(fd->search_key, cnid, NULL);
+	res = hfs_brec_read(fd, &rec, sizeof(rec));
+	if (res)
+		return res;
+
+	type = rec.type;
+	if (type != HFS_CDR_THD && type != HFS_CDR_FTH) {
+		printk("HFS-fs: Found bad thread record in catalog\n");
+		return -EIO;
+	}
+
+	fd->search_key->cat.ParID = rec.thread.ParID;
+	len = fd->search_key->cat.CName.len = rec.thread.CName.len;
+	memcpy(fd->search_key->cat.CName.name, rec.thread.CName.name, len);
+	return hfs_brec_find(fd);
 }
 
-/*
- * hfs_cat_mkdir()
- *
- * Create a new directory with the indicated name in the indicated directory.
- * If successful an (struct hfs_cat_entry) is returned in '*result'.
- */
-int hfs_cat_mkdir(struct hfs_cat_entry *parent, struct hfs_cat_key *key,
-		  struct hfs_cat_entry **result)
-{
-	struct hfs_cat_rec record;
-	hfs_u32 id = new_cnid(parent->mdb);
-	hfs_u32 mtime = hfs_time();
-
-#if defined(DEBUG_CATALOG) || defined(DEBUG_ALL)
-	hfs_warn("hfs_cat_mkdir: %p/%s res=%p\n", parent, key->CName.Name,
-		 result);
-#endif
-
-	/* init some fields for the directory record */
-	memset(&record, 0, sizeof(record));
-	record.cdrType = HFS_CDR_DIR;
-	hfs_put_nl(id,     record.u.dir.DirID);
-	hfs_put_nl(mtime, record.u.dir.CrDat);
-	hfs_put_nl(mtime, record.u.dir.MdDat);
-	hfs_put_nl(0,     record.u.dir.BkDat);
-	hfs_put_hs(0xff,  record.u.dir.UsrInfo.frView);
-
-	return create_entry(parent, key, &record, 1, id, result);
-}
 
 /*
  * hfs_cat_delete()
@@ -1186,72 +192,60 @@ int hfs_cat_mkdir(struct hfs_cat_entry *
  * Delete the indicated file or directory.
  * The associated thread is also removed unless ('with_thread'==0).
  */
-int hfs_cat_delete(struct hfs_cat_entry *parent, struct hfs_cat_entry *entry,
-		   int with_thread)
+int hfs_cat_delete(u32 cnid, struct inode *dir, struct qstr *str)
 {
-	struct hfs_cat_key key;
-	struct hfs_mdb *mdb = parent->mdb;
-	int is_dir, error = 0;
-
-#if defined(DEBUG_CATALOG) || defined(DEBUG_ALL)
-	hfs_warn("hfs_cat_delete: %p/%p type=%d state=%lu, thread=%d\n",
-		 parent, entry, entry->type, entry->state, with_thread);
+	struct super_block *sb;
+	struct hfs_find_data fd;
+	struct list_head *pos;
+	int res, type;
+
+	dprint(DBG_CAT_MOD, "delete_cat: %s,%u\n", str ? str->name : NULL, cnid);
+	sb = dir->i_sb;
+	hfs_find_init(HFS_SB(sb)->cat_tree, &fd);
+
+	hfs_cat_build_key(fd.search_key, dir->i_ino, str);
+	res = hfs_brec_find(&fd);
+	if (res)
+		goto out;
+
+	type = hfs_bnode_read_u8(fd.bnode, fd.entryoffset);
+	if (type == HFS_CDR_FIL) {
+		struct hfs_cat_file file;
+		hfs_bnode_read(fd.bnode, &file, fd.entryoffset, sizeof(file));
+		if (be32_to_cpu(file.FlNum) == cnid) {
+#if 0
+			hfs_free_fork(sb, &file, HFS_FK_DATA);
 #endif
-	if (parent->mdb != entry->mdb) {
-		return -EINVAL;
-	}
-
-	if (entry->type == HFS_CDR_FIL) {
-		with_thread = (entry->u.file.flags&HFS_FIL_THD) && with_thread;
-		is_dir = 0;
-	} else {
-		is_dir = 1;
-	}
-
-	/* keep readers from getting confused by changing dir size */
-	down_write(&parent->u.dir.sem);
-
-	/* don't delete a busy directory */
-	if (entry->type == HFS_CDR_DIR) {
-		down_read(&entry->u.dir.sem);
-
-		error = -ENOTEMPTY;
-		if (entry->u.dir.files || entry->u.dir.dirs) 
-			goto hfs_delete_end;
+			hfs_free_fork(sb, &file, HFS_FK_RSRC);
+		}
 	}
 
-	/* try to delete the file or directory */
-	lock_entry(entry);
-	error = -ENOENT;
-	if ((entry->state & HFS_DELETED)) {
-		/* somebody beat us to it. */
-		goto hfs_delete_unlock;
-	}
-		
-	/* delete the catalog record */
-	if ((error = hfs_bdelete(mdb->cat_tree, HFS_BKEY(&entry->key)))) {
-		goto hfs_delete_unlock;
+	list_for_each(pos, &HFS_I(dir)->open_dir_list) {
+		struct hfs_readdir_data *rd =
+			list_entry(pos, struct hfs_readdir_data, list);
+		if (fd.tree->keycmp(fd.search_key, (void *)&rd->key) < 0)
+			rd->file->f_pos--;
 	}
 
-	/* Mark the entry deleted and remove it from the cache */
-	delete_entry(entry);
+	res = hfs_brec_remove(&fd);
+	if (res)
+		goto out;
 
-	/* try to delete the thread entry if it exists */
-	if (with_thread) {
-		hfs_cat_build_key(entry->cnid, NULL, &key);
-		(void)hfs_bdelete(mdb->cat_tree, HFS_BKEY(&key));
+	hfs_cat_build_key(fd.search_key, cnid, NULL);
+	res = hfs_brec_find(&fd);
+	if (!res) {
+		res = hfs_brec_remove(&fd);
+		if (res)
+			goto out;
 	}
-	
-	update_dir(mdb, parent, is_dir, -1);
 
-hfs_delete_unlock:
-	unlock_entry(entry);
+	dir->i_size--;
+	mark_inode_dirty(dir);
+	res = 0;
+out:
+	hfs_find_exit(&fd);
 
-hfs_delete_end:
-	if (entry->type == HFS_CDR_DIR)
-		up_read(&entry->u.dir.sem);
-	up_write(&parent->u.dir.sem);
-	return error;
+	return res;
 }
 
 /*
@@ -1261,267 +255,82 @@ hfs_delete_end:
  * If the destination exists it is removed and a
  * (struct hfs_cat_entry) for it is returned in '*result'.
  */
-int hfs_cat_move(struct hfs_cat_entry *old_dir, struct hfs_cat_entry *new_dir,
-		 struct hfs_cat_entry *entry, struct hfs_cat_key *new_key,
-		 struct hfs_cat_entry **removed)
+int hfs_cat_move(u32 cnid, struct inode *src_dir, struct qstr *src_name,
+		 struct inode *dst_dir, struct qstr *dst_name)
 {
-	struct hfs_cat_entry *dest;
-	struct hfs_mdb *mdb;
-	int error = 0;
-	int is_dir, has_thread;
-
-	if (removed) {
-		*removed = NULL;
-	}
-
-	/* sanity checks */
-	if (!old_dir || !new_dir) {
-		return -EINVAL;
-	}
-	mdb = old_dir->mdb;
-	if (mdb != new_dir->mdb) {
-		return -EXDEV;
-	}
-
-	/* precompute a few things */
-	if (entry->type == HFS_CDR_DIR) {
-		is_dir = 1;
-		has_thread = 1;
-	} else if (entry->type == HFS_CDR_FIL) {
-		is_dir = 0;
-		has_thread = entry->u.file.flags & HFS_FIL_THD;
-	} else {
-		return -EINVAL;
-	}
-
-	/* keep readers from getting confused by changing dir size */
-	down_write(&new_dir->u.dir.sem);
-	/* AV: smells like a deadlock */
-	if (old_dir != new_dir)
-		down_write(&old_dir->u.dir.sem);
-
-	/* Don't move a directory inside itself */
-	if (is_dir) {
-		struct hfs_cat_key thd_key;
-		struct hfs_brec brec;
-
-		hfs_u32 id = new_dir->cnid;
-		while (id != htonl(HFS_ROOT_CNID)) {
-			if (id == entry->cnid) {
-				error = -EINVAL;
-			} else {
-				hfs_cat_build_key(id, NULL, &thd_key);
-				error = hfs_bfind(&brec, mdb->cat_tree,
-						  HFS_BKEY(&thd_key),
-						  HFS_BFIND_READ_EQ);
-			}
-			if (error) {
-				goto done;
-			} else {
-				struct hfs_cat_rec *rec = brec.data;
-				id = hfs_get_nl(rec->u.thd.ParID);
-				hfs_brec_relse(&brec, NULL);
-			}
-		}
-	}
-
-restart:
-	/* see if the destination exists, getting it if it does */
-	dest = hfs_cat_get(mdb, new_key);
-	if (!dest) {
-		/* destination doesn't exist, so create it */
-		struct hfs_cat_rec new_record;
-
-		/* create a locked entry in the cache */
-		dest = get_entry(mdb, new_key, 0);
-		if (!dest) {
-			error = -EIO;
-			goto done;
-		}
-		if (dest->cnid) {
-			/* The (unlocked) entry exists in the cache */
-			goto have_distinct;
-		}
-
-		/* limit directory valence to signed 16-bit integer */
-        	if ((new_dir->u.dir.dirs + new_dir->u.dir.files) >=
-							HFS_MAX_VALENCE) {
-			error = -ENOSPC;
-			goto bail3;
-		}
-
-		/* build the new record. make sure to zero out the
-                   record. */
-		memset(&new_record, 0, sizeof(new_record));
-		new_record.cdrType = entry->type;
-		__write_entry(entry, &new_record);
-
-		/* insert the new record */
-		error = hfs_binsert(mdb->cat_tree, HFS_BKEY(new_key),
-				    &new_record, is_dir ? 2 + sizeof(DIR_REC) :
-				    2 + sizeof(FIL_REC));
-		if (error == -EEXIST) {
-			delete_entry(dest);
-			unlock_entry(dest);
-			hfs_cat_put(dest);
-			goto restart;
-		} else if (error) {
-			goto bail3;
-		}
-
-		/* update the destination directory */
-		update_dir(mdb, new_dir, is_dir, 1);
-	} else if (entry != dest) {
-have_distinct:
-		/* The destination exists and is not same as source */
-		lock_entry(dest);
-		if ((dest->state & HFS_DELETED)) {
-		        unlock_entry(dest);
-			hfs_cat_put(dest);
-			goto restart;
-		}
-		if (dest->type != entry->type) {
-			/* can't move a file on top
-			   of a dir nor vice versa. */
-			error = is_dir ? -ENOTDIR : -EISDIR;
-		} else if (is_dir && (dest->u.dir.dirs || dest->u.dir.files)) {
-			/* directory to replace is not empty */
-			error = -ENOTEMPTY;
-		}
-
-		if (error) {
-			goto bail2;
-		}
-	} else {
-		/* The destination exists but is same as source */
-	        --entry->count;
-		dest = NULL;
-	}
-
-	/* lock the entry */
-	lock_entry(entry);
-	if ((entry->state & HFS_DELETED)) {
-		error = -ENOENT;
-		goto bail1;
-	}
-
-	if (dest) {
-		/* remove the old entry */
-		error = hfs_bdelete(mdb->cat_tree, HFS_BKEY(&entry->key));
-
-		if (error) {
-			/* We couldn't remove the entry for the
-			   original file, so nothing has changed. */
-			goto bail1;
-		}
-		update_dir(mdb, old_dir, is_dir, -1);
-	}
-
-	/* update the thread of the dir/file we're moving */
-	if (has_thread) {
-		struct hfs_cat_key thd_key;
-		struct hfs_brec brec;
-
-		hfs_cat_build_key(entry->cnid, NULL, &thd_key);
-		error = hfs_bfind(&brec, mdb->cat_tree,
-				  HFS_BKEY(&thd_key), HFS_BFIND_WRITE);
-		if (error == -ENOENT) {
-			if (is_dir) {
-				/* directory w/o a thread! */
-				error = -EIO;
-			} else {
-				/* We were lied to! */
-				entry->u.file.flags &= ~HFS_FIL_THD;
-				hfs_cat_mark_dirty(entry);
-			}
-		}
-		if (!error) {
-			struct hfs_cat_rec *rec = brec.data;
-			memcpy(&rec->u.thd.ParID, &new_key->ParID,
-			       sizeof(hfs_u32) + sizeof(struct hfs_name));
-			hfs_brec_relse(&brec, NULL);
-		} else if (error == -ENOENT) {
-			error = 0;
-		} else if (!dest) {
-			/* Nothing was changed */
-			unlock_entry(entry);
-			goto done;
-		} else {
-			/* Something went seriously wrong.
-			   The dir/file has been deleted. */
-			/* XXX try some recovery? */
-			delete_entry(entry);
-			goto bail1;
-		}
-	}
-
-	/* TRY to remove the thread for the pre-existing entry */
-	if (dest && dest->cnid &&
-	    (is_dir || (dest->u.file.flags & HFS_FIL_THD))) {
-		struct hfs_cat_key thd_key;
-
-		hfs_cat_build_key(dest->cnid, NULL, &thd_key);
-		(void)hfs_bdelete(mdb->cat_tree, HFS_BKEY(&thd_key));
-	}
-
-	/* update directories */
-	new_dir->modify_date = hfs_time();
-	hfs_cat_mark_dirty(new_dir);
-
-	/* update key */
-	remove_hash(entry);
-	memcpy(&entry->key, new_key, sizeof(*new_key));
-	/* KEYDIRTY as case might differ */
-	entry->state |= HFS_KEYDIRTY;
-	insert_hash(entry);
-	hfs_cat_mark_dirty(entry);
-	unlock_entry(entry);
-
-	/* delete any pre-existing or place-holder entry */
-	if (dest) {
-		delete_entry(dest);
-		unlock_entry(dest);
-		if (removed && dest->cnid) {
-			*removed = dest;
-		} else {
-			hfs_cat_put(dest);
-		}
-	}
-	goto done;
-
-bail1:
-	unlock_entry(entry);
-bail2:
-	if (dest) {
-		if (!dest->cnid) {
-			/* TRY to remove the new entry */
-			(void)hfs_bdelete(mdb->cat_tree, HFS_BKEY(new_key));
-			update_dir(mdb, new_dir, is_dir, -1);
-bail3:
-			delete_entry(dest);
-		}
-		unlock_entry(dest);
-		hfs_cat_put(dest);
-	}
-done:
-	if (new_dir != old_dir)
-		up_write(&old_dir->u.dir.sem);
-	up_write(&new_dir->u.dir.sem);
-	return error;
-}
-
-/*
- * Initialize the hash tables
- */
-void hfs_cat_init(void)
-{
-	int i;
-	struct list_head *head = hash_table;
-
-        i = C_HASHSIZE;
-        do {
-                INIT_LIST_HEAD(head);
-                head++;
-                i--;
-        } while (i);
+	struct super_block *sb;
+	struct hfs_find_data src_fd, dst_fd;
+	union hfs_cat_rec entry;
+	int entry_size, type;
+	int err;
+
+	dprint(DBG_CAT_MOD, "rename_cat: %u - %lu,%s - %lu,%s\n", cnid, src_dir->i_ino, src_name->name,
+		dst_dir->i_ino, dst_name->name);
+	sb = src_dir->i_sb;
+	hfs_find_init(HFS_SB(sb)->cat_tree, &src_fd);
+	dst_fd = src_fd;
+
+	/* find the old dir entry and read the data */
+	hfs_cat_build_key(src_fd.search_key, src_dir->i_ino, src_name);
+	err = hfs_brec_find(&src_fd);
+	if (err)
+		goto out;
+
+	hfs_bnode_read(src_fd.bnode, &entry, src_fd.entryoffset,
+			    src_fd.entrylength);
+
+	/* create new dir entry with the data from the old entry */
+	hfs_cat_build_key(dst_fd.search_key, dst_dir->i_ino, dst_name);
+	err = hfs_brec_find(&dst_fd);
+	if (err != -ENOENT) {
+		if (!err)
+			err = -EEXIST;
+		goto out;
+	}
+
+	err = hfs_brec_insert(&dst_fd, &entry, src_fd.entrylength);
+	if (err)
+		goto out;
+	dst_dir->i_size++;
+	mark_inode_dirty(dst_dir);
+
+	/* finally remove the old entry */
+	hfs_cat_build_key(src_fd.search_key, src_dir->i_ino, src_name);
+	err = hfs_brec_find(&src_fd);
+	if (err)
+		goto out;
+	err = hfs_brec_remove(&src_fd);
+	if (err)
+		goto out;
+	src_dir->i_size--;
+	mark_inode_dirty(src_dir);
+
+	type = entry.type;
+	if (type == HFS_CDR_FIL && !(entry.file.Flags & HFS_FIL_THD))
+		goto out;
+
+	/* remove old thread entry */
+	hfs_cat_build_key(src_fd.search_key, cnid, NULL);
+	err = hfs_brec_find(&src_fd);
+	if (err)
+		goto out;
+	err = hfs_brec_remove(&src_fd);
+	if (err)
+		goto out;
+
+	/* create new thread entry */
+	hfs_cat_build_key(dst_fd.search_key, cnid, NULL);
+	entry_size = hfs_cat_build_thread(&entry, type == HFS_CDR_FIL ? HFS_CDR_FTH : HFS_CDR_THD,
+					dst_dir->i_ino, dst_name);
+	err = hfs_brec_find(&dst_fd);
+	if (err != -ENOENT) {
+		if (!err)
+			err = -EEXIST;
+		goto out;
+	}
+	err = hfs_brec_insert(&dst_fd, &entry, entry_size);
+out:
+	hfs_bnode_put(dst_fd.bnode);
+	hfs_find_exit(&src_fd);
+	return err;
 }
--- diff/fs/hfs/dir.c	2003-07-11 09:39:50.000000000 +0100
+++ source/fs/hfs/dir.c	2004-02-23 13:56:46.000000000 +0000
@@ -1,160 +1,174 @@
 /*
- * linux/fs/hfs/dir.c
+ *  linux/fs/hfs/dir.c
  *
  * Copyright (C) 1995-1997  Paul H. Hargrove
+ * (C) 2003 Ardis Technologies <roman@ardistech.com>
  * This file may be distributed under the terms of the GNU General Public License.
  *
  * This file contains directory-related functions independent of which
  * scheme is being used to represent forks.
  *
  * Based on the minix file system code, (C) 1991, 1992 by Linus Torvalds
- *
- * "XXX" in a comment is a note to myself to consider changing something.
- *
- * In function preconditions the term "valid" applied to a pointer to
- * a structure means that the pointer is non-NULL and the structure it
- * points to has all fields initialized to consistent values.
  */
 
-#include "hfs.h"
-#include <linux/hfs_fs_sb.h>
-#include <linux/hfs_fs_i.h>
-#include <linux/hfs_fs.h>
-#include <linux/smp_lock.h>
-
-/*================ File-local functions ================*/
+#include "hfs_fs.h"
+#include "btree.h"
 
 /*
- * build_key()
- *
- * Build a key for a file by the given name in the given directory.
- * If the name matches one of the reserved names returns 1 otherwise 0.
+ * hfs_lookup()
  */
-static int build_key(struct hfs_cat_key *key, struct inode *dir,
-		     const char *name, int len)
+struct dentry *hfs_lookup(struct inode *dir, struct dentry *dentry,
+			  struct nameidata *nd)
 {
-	struct hfs_name cname;
-	const struct hfs_name *reserved;
-
-	/* mangle the name */
-	hfs_nameout(dir, &cname, name, len);
-
-	/* check against reserved names */
-	reserved = HFS_SB(dir->i_sb)->s_reserved1;
-	while (reserved->Len) {
-		if (hfs_streq(reserved->Name, reserved->Len, 
-			      cname.Name, cname.Len)) {
-			return 1;
+	hfs_cat_rec rec;
+	struct hfs_find_data fd;
+	struct inode *inode = NULL;
+	int res;
+
+	dentry->d_op = &hfs_dentry_operations;
+
+	hfs_find_init(HFS_SB(dir->i_sb)->cat_tree, &fd);
+	hfs_cat_build_key(fd.search_key, dir->i_ino, &dentry->d_name);
+	res = hfs_brec_read(&fd, &rec, sizeof(rec));
+	if (res) {
+		hfs_find_exit(&fd);
+		if (res == -ENOENT) {
+			/* No such entry */
+			inode = NULL;
+			goto done;
 		}
-		++reserved;
+		return ERR_PTR(res);
 	}
-
-	/* check against the names reserved only in the root directory */
-	if (HFS_I(dir)->entry->cnid == htonl(HFS_ROOT_CNID)) {
-		reserved = HFS_SB(dir->i_sb)->s_reserved2;
-		while (reserved->Len) {
-			if (hfs_streq(reserved->Name, reserved->Len,
-				      cname.Name, cname.Len)) {
-				return 1;
-			}
-			++reserved;
-		}
-	}
-
-	/* build the key */
-	hfs_cat_build_key(HFS_I(dir)->entry->cnid, &cname, key);
-
-	return 0;
+	inode = hfs_iget(dir->i_sb, &fd.search_key->cat, &rec);
+	hfs_find_exit(&fd);
+	if (!inode)
+		return ERR_PTR(-EACCES);
+done:
+	d_add(dentry, inode);
+	return NULL;
 }
 
 /*
- * update_dirs_plus()
- *
- * Update the fields 'i_size', 'i_nlink', 'i_ctime' and 'i_mtime'
- * of the inodes associated with a directory that has
- * had a file ('is_dir'==0) or directory ('is_dir'!=0) added to it.
+ * hfs_readdir
  */
-static inline void update_dirs_plus(struct hfs_cat_entry *dir, int is_dir)
+int hfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
 {
-	int i;
-
-	for (i = 0; i < 4; ++i) {
-		struct dentry *de = dir->sys_entry[i];
-		if (de) {
-		        struct inode *tmp = de->d_inode;
-			if (S_ISDIR(tmp->i_mode)) {
-				if (is_dir &&
-				    (i == HFS_ITYPE_TO_INT(HFS_ITYPE_NORM))) {
-					/* In "normal" directory only */
-					++(tmp->i_nlink);
-				}
-				tmp->i_size += HFS_I(tmp)->dir_size;
-			}
-			tmp->i_ctime = tmp->i_mtime = CURRENT_TIME;
-			mark_inode_dirty(tmp);
+	struct inode *inode = filp->f_dentry->d_inode;
+	struct super_block *sb = inode->i_sb;
+	int len, err;
+	char strbuf[HFS_NAMELEN + 1];
+	union hfs_cat_rec entry;
+	struct hfs_find_data fd;
+	struct hfs_readdir_data *rd;
+	u16 type;
+
+	if (filp->f_pos >= inode->i_size)
+		return 0;
+
+	hfs_find_init(HFS_SB(sb)->cat_tree, &fd);
+	hfs_cat_build_key(fd.search_key, inode->i_ino, NULL);
+	err = hfs_brec_find(&fd);
+	if (err)
+		goto out;
+
+	switch ((u32)filp->f_pos) {
+	case 0:
+		/* This is completely artificial... */
+		if (filldir(dirent, ".", 1, 0, inode->i_ino, DT_DIR))
+			goto out;
+		filp->f_pos++;
+		/* fall through */
+	case 1:
+		hfs_bnode_read(fd.bnode, &entry, fd.entryoffset, fd.entrylength);
+		if (entry.type != HFS_CDR_THD) {
+			printk("HFS: bad catalog folder thread\n");
+			err = -EIO;
+			goto out;
 		}
-	}
-}
-
-/*
- * update_dirs_minus()
- *
- * Update the fields 'i_size', 'i_nlink', 'i_ctime', 'i_mtime' and
- * of the inodes associated with a directory that has
- * had a file ('is_dir'==0) or directory ('is_dir'!=0) removed.
- */
-static inline void update_dirs_minus(struct hfs_cat_entry *dir, int is_dir)
-{
-	int i;
-
-	for (i = 0; i < 4; ++i) {
-		struct dentry *de = dir->sys_entry[i];
-		if (de) {
-		        struct inode *tmp = de->d_inode;
-			if (S_ISDIR(tmp->i_mode)) {
-				if (is_dir &&
-				    (i == HFS_ITYPE_TO_INT(HFS_ITYPE_NORM))) {
-					/* In "normal" directory only */
-					--(tmp->i_nlink);
-				}
-				tmp->i_size -= HFS_I(tmp)->dir_size;
+		//if (fd.entrylength < HFS_MIN_THREAD_SZ) {
+		//	printk("HFS: truncated catalog thread\n");
+		//	err = -EIO;
+		//	goto out;
+		//}
+		if (filldir(dirent, "..", 2, 1,
+			    be32_to_cpu(entry.thread.ParID), DT_DIR))
+			goto out;
+		filp->f_pos++;
+		/* fall through */
+	default:
+		if (filp->f_pos >= inode->i_size)
+			goto out;
+		err = hfs_brec_goto(&fd, filp->f_pos - 1);
+		if (err)
+			goto out;
+	}
+
+	for (;;) {
+		if (be32_to_cpu(fd.key->cat.ParID) != inode->i_ino) {
+			printk("HFS: walked past end of dir\n");
+			err = -EIO;
+			goto out;
+		}
+		hfs_bnode_read(fd.bnode, &entry, fd.entryoffset, fd.entrylength);
+		type = entry.type;
+		len = hfs_mac2triv(strbuf, &fd.key->cat.CName);
+		if (type == HFS_CDR_DIR) {
+			if (fd.entrylength < sizeof(struct hfs_cat_dir)) {
+				printk("HFS: small dir entry\n");
+				err = -EIO;
+				goto out;
+			}
+			if (filldir(dirent, strbuf, len, filp->f_pos,
+				    be32_to_cpu(entry.dir.DirID), DT_DIR))
+				break;
+		} else if (type == HFS_CDR_FIL) {
+			if (fd.entrylength < sizeof(struct hfs_cat_file)) {
+				printk("HFS: small file entry\n");
+				err = -EIO;
+				goto out;
 			}
-			tmp->i_ctime = tmp->i_mtime = CURRENT_TIME;
-			mark_inode_dirty(tmp);
+			if (filldir(dirent, strbuf, len, filp->f_pos,
+				    be32_to_cpu(entry.file.FlNum), DT_REG))
+				break;
+		} else {
+			printk("HFS: bad catalog entry type %d\n", type);
+			err = -EIO;
+			goto out;
 		}
-	}
+		filp->f_pos++;
+		if (filp->f_pos >= inode->i_size)
+			goto out;
+		err = hfs_brec_goto(&fd, 1);
+		if (err)
+			goto out;
+	}
+	rd = filp->private_data;
+	if (!rd) {
+		rd = kmalloc(sizeof(struct hfs_readdir_data), GFP_KERNEL);
+		if (!rd) {
+			err = -ENOMEM;
+			goto out;
+		}
+		filp->private_data = rd;
+		rd->file = filp;
+		list_add(&rd->list, &HFS_I(inode)->open_dir_list);
+	}
+	memcpy(&rd->key, &fd.key, sizeof(struct hfs_cat_key));
+out:
+	hfs_find_exit(&fd);
+	return err;
 }
 
-/*
- * mark_inodes_deleted()
- *
- * Update inodes associated with a deleted entry to reflect its deletion.
- * Well, we really just drop the dentry.
- *
- * XXX: we should be using delete_inode for some of this stuff.
- */
-static inline void mark_inodes_deleted(struct hfs_cat_entry *entry, 
-				       struct dentry *dentry)
+static int hfs_dir_release(struct inode *inode, struct file *file)
 {
-	struct dentry *de;
-	struct inode *tmp;
-	int i;
-
-	for (i = 0; i < 4; ++i) {
-		if ((de = entry->sys_entry[i]) && (dentry != de)) {
-		      dget(de);
-		      tmp = de->d_inode;
-		      tmp->i_nlink = 0;
-		      tmp->i_ctime = CURRENT_TIME;
-		      mark_inode_dirty(tmp);
-		      d_delete(de);
-		      dput(de);
-		}
+	struct hfs_readdir_data *rd = file->private_data;
+	if (rd) {
+		list_del(&rd->list);
+		kfree(rd);
 	}
+	return 0;
 }
 
-/*================ Global functions ================*/
-
 /*
  * hfs_create()
  *
@@ -163,47 +177,25 @@ static inline void mark_inodes_deleted(s
  * a directory and return a corresponding inode, given the inode for
  * the directory and the name (and its length) of the new file.
  */
-int hfs_create(struct inode * dir, struct dentry *dentry, int mode, struct nameidata *nd)
+int hfs_create(struct inode *dir, struct dentry *dentry, int mode,
+	       struct nameidata *nd)
 {
-	struct hfs_cat_entry *entry = HFS_I(dir)->entry;
-	struct hfs_cat_entry *new;
-	struct hfs_cat_key key;
 	struct inode *inode;
-	int error;
+	int res;
 
-	lock_kernel();
-	/* build the key, checking against reserved names */
-	if (build_key(&key, dir, dentry->d_name.name, dentry->d_name.len)) {
-		unlock_kernel();
-		return -EEXIST;
+	inode = hfs_new_inode(dir, &dentry->d_name, mode);
+	if (!inode)
+		return -ENOSPC;
+
+	res = hfs_cat_create(inode->i_ino, dir, &dentry->d_name, inode);
+	if (res) {
+		inode->i_nlink = 0;
+		hfs_delete_inode(inode);
+		iput(inode);
+		return res;
 	}
-
-	if ((error = hfs_cat_create(entry, &key, 
-			       (mode & S_IWUSR) ? 0 : HFS_FIL_LOCK,
-			       HFS_SB(dir->i_sb)->s_type,
-			       HFS_SB(dir->i_sb)->s_creator, &new))) {
-		unlock_kernel();
-		return error;
-	}
-
-	/* create an inode for the new file. back out if we run
-	 * into trouble. */
-	new->count++; /* hfs_iget() eats one */
-	if (!(inode = hfs_iget(new, HFS_I(dir)->file_type, dentry))) {
-		hfs_cat_delete(entry, new, 1);
-		hfs_cat_put(new);
-		unlock_kernel();
-		return -EIO;
-	}
-
-	hfs_cat_put(new);
-	update_dirs_plus(entry, 0);
-	/* toss any relevant negative dentries */
-	if (HFS_I(dir)->d_drop_op)
-		HFS_I(dir)->d_drop_op(dentry, HFS_I(dir)->file_type);
-	mark_inode_dirty(inode);
-	unlock_kernel();
 	d_instantiate(dentry, inode);
+	mark_inode_dirty(inode);
 	return 0;
 }
 
@@ -215,43 +207,24 @@ int hfs_create(struct inode * dir, struc
  * in a directory, given the inode for the parent directory and the
  * name (and its length) of the new directory.
  */
-int hfs_mkdir(struct inode * parent, struct dentry *dentry, int mode)
+int hfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
 {
-	struct hfs_cat_entry *entry;
-	struct hfs_cat_entry *new;
-	struct hfs_cat_key key;
 	struct inode *inode;
-	int error;
+	int res;
 
-	lock_kernel();
-	entry = HFS_I(parent)->entry;
-	/* build the key, checking against reserved names */
-	if (build_key(&key, parent, dentry->d_name.name, 
-		      dentry->d_name.len)) {
-		unlock_kernel();
-		return -EEXIST;
+	inode = hfs_new_inode(dir, &dentry->d_name, S_IFDIR | mode);
+	if (!inode)
+		return -ENOSPC;
+
+	res = hfs_cat_create(inode->i_ino, dir, &dentry->d_name, inode);
+	if (res) {
+		inode->i_nlink = 0;
+		hfs_delete_inode(inode);
+		iput(inode);
+		return res;
 	}
-
-	/* try to create the directory */
-	if ((error = hfs_cat_mkdir(entry, &key, &new))) {
-		unlock_kernel();
-		return error;
-	}
-
-	/* back out if we run into trouble */
-	new->count++; /* hfs_iget eats one */
-	if (!(inode = hfs_iget(new, HFS_I(parent)->file_type, dentry))) {
-		hfs_cat_delete(entry, new, 1);
-		hfs_cat_put(new);
-		unlock_kernel();
-		return -EIO;
-	}
-
-	hfs_cat_put(new);
-	update_dirs_plus(entry, 1);
-	mark_inode_dirty(inode);
 	d_instantiate(dentry, inode);
-	unlock_kernel();
+	mark_inode_dirty(inode);
 	return 0;
 }
 
@@ -263,44 +236,22 @@ int hfs_mkdir(struct inode * parent, str
  * file, given the inode for the parent directory and the name
  * (and its length) of the existing file.
  */
-int hfs_unlink(struct inode * dir, struct dentry *dentry)
+int hfs_unlink(struct inode *dir, struct dentry *dentry)
 {
-	struct hfs_cat_entry *entry = HFS_I(dir)->entry;
-	struct hfs_cat_entry *victim = NULL;
-	struct hfs_cat_key key;
-	int error;
-
-	lock_kernel();
-	entry = HFS_I(dir)->entry;
-	if (build_key(&key, dir, dentry->d_name.name,
-		      dentry->d_name.len)) {
-		unlock_kernel();
-		return -EPERM;
-	}
+	struct inode *inode;
+	int res;
 
-	if (!(victim = hfs_cat_get(entry->mdb, &key))) {
-		unlock_kernel();
-		return -ENOENT;
-	}
+	inode = dentry->d_inode;
+	res = hfs_cat_delete(inode->i_ino, dir, &dentry->d_name);
+	if (res)
+		return res;
 
-	error = -EPERM;
-	if (victim->type != HFS_CDR_FIL)
-		goto hfs_unlink_put;
-
-	if (!(error = hfs_cat_delete(entry, victim, 1))) {
-		struct inode *inode = dentry->d_inode;
-
-		mark_inodes_deleted(victim, dentry);
-		inode->i_nlink--; 
-		inode->i_ctime = CURRENT_TIME;
-		mark_inode_dirty(inode);
-		update_dirs_minus(entry, 0);
-	}
+	inode->i_nlink--;
+	hfs_delete_inode(inode);
+	inode->i_ctime = CURRENT_TIME;
+	mark_inode_dirty(inode);
 
-hfs_unlink_put:
-	hfs_cat_put(victim);	/* Note that hfs_cat_put(NULL) is safe. */
-	unlock_kernel();
-	return error;
+	return res;
 }
 
 /*
@@ -311,55 +262,22 @@ hfs_unlink_put:
  * directory, given the inode for the parent directory and the name
  * (and its length) of the existing directory.
  */
-int hfs_rmdir(struct inode * parent, struct dentry *dentry)
+int hfs_rmdir(struct inode *dir, struct dentry *dentry)
 {
-	struct hfs_cat_entry *entry;
-	struct hfs_cat_entry *victim = NULL;
-	struct inode *inode = dentry->d_inode;
-	struct hfs_cat_key key;
-	int error;
-
-	lock_kernel();
-	entry = HFS_I(parent)->entry;
-	if (build_key(&key, parent, dentry->d_name.name,
-		      dentry->d_name.len)) {
-		unlock_kernel();
-		return -EPERM;
-	}
-
-	if (!(victim = hfs_cat_get(entry->mdb, &key))) {
-		unlock_kernel();
-		return -ENOENT;
-	}
-
-	error = -ENOTDIR;
-	if (victim->type != HFS_CDR_DIR) 
-		goto hfs_rmdir_put;
-
-	error = -EBUSY;
-	if (!d_unhashed(dentry))
-		goto hfs_rmdir_put;
-
-	/* we only have to worry about 2 and 3 for mount points */
-	if (victim->sys_entry[2] && d_mountpoint(victim->sys_entry[2]))
-		goto hfs_rmdir_put;
-	if (victim->sys_entry[3] && d_mountpoint(victim->sys_entry[3])) 
-		goto hfs_rmdir_put;
-
-	
-	if ((error = hfs_cat_delete(entry, victim, 1)))
-		goto hfs_rmdir_put;
+	struct inode *inode;
+	int res;
 
-	mark_inodes_deleted(victim, dentry);
+	inode = dentry->d_inode;
+	if (inode->i_size != 2)
+		return -ENOTEMPTY;
+	res = hfs_cat_delete(inode->i_ino, dir, &dentry->d_name);
+	if (res)
+		return res;
 	inode->i_nlink = 0;
 	inode->i_ctime = CURRENT_TIME;
+	hfs_delete_inode(inode);
 	mark_inode_dirty(inode);
-	update_dirs_minus(entry, 1);
-	 
-hfs_rmdir_put:
-	hfs_cat_put(victim);	/* Note that hfs_cat_put(NULL) is safe. */
-	unlock_kernel();
-	return error;
+	return 0;
 }
 
 /*
@@ -376,55 +294,34 @@ hfs_rmdir_put:
 int hfs_rename(struct inode *old_dir, struct dentry *old_dentry,
 	       struct inode *new_dir, struct dentry *new_dentry)
 {
-	struct hfs_cat_entry *old_parent;
-	struct hfs_cat_entry *new_parent;
-	struct hfs_cat_entry *victim = NULL;
-	struct hfs_cat_entry *deleted;
-	struct hfs_cat_key key;
-	int error;
-
-	lock_kernel();
-	old_parent = HFS_I(old_dir)->entry;
-	new_parent = HFS_I(new_dir)->entry;
-	if (build_key(&key, old_dir, old_dentry->d_name.name,
-		      old_dentry->d_name.len) ||
-	    (HFS_ITYPE(old_dir->i_ino) != HFS_ITYPE(new_dir->i_ino))) {
-		unlock_kernel();
-		return -EPERM;
-	}
-
-	if (!(victim = hfs_cat_get(old_parent->mdb, &key))) {
-		unlock_kernel();
-		return -ENOENT;
-	}
+	int res;
 
-	error = -EPERM;
-	if (build_key(&key, new_dir, new_dentry->d_name.name,
-			     new_dentry->d_name.len)) 
-		goto hfs_rename_put;
-
-	if (!(error = hfs_cat_move(old_parent, new_parent,
-				   victim, &key, &deleted))) {
-		int is_dir = (victim->type == HFS_CDR_DIR);
-		
-		/* drop the old dentries */
-		mark_inodes_deleted(victim, old_dentry);
-		update_dirs_minus(old_parent, is_dir);
-		if (deleted) {
-			mark_inodes_deleted(deleted, new_dentry);
-			hfs_cat_put(deleted);
-		} else {
-			/* no existing inodes. just drop negative dentries */
-			if (HFS_I(new_dir)->d_drop_op) 
-				HFS_I(new_dir)->d_drop_op(new_dentry, 
-					  HFS_I(new_dir)->file_type);
-			update_dirs_plus(new_parent, is_dir);
-		}
-	
+	/* Unlink destination if it already exists */
+	if (new_dentry->d_inode) {
+		res = hfs_unlink(new_dir, new_dentry);
+		if (res)
+			return res;
 	}
 
-hfs_rename_put:
-	hfs_cat_put(victim);	/* Note that hfs_cat_put(NULL) is safe. */
-	unlock_kernel();
-	return error;
+	res = hfs_cat_move(old_dentry->d_inode->i_ino,
+			   old_dir, &old_dentry->d_name,
+			   new_dir, &new_dentry->d_name);
+	return res;
 }
+
+struct file_operations hfs_dir_operations = {
+	.read		= generic_read_dir,
+	.readdir	= hfs_readdir,
+	.llseek		= generic_file_llseek,
+	.release	= hfs_dir_release,
+};
+
+struct inode_operations hfs_dir_inode_operations = {
+	.create		= hfs_create,
+	.lookup		= hfs_lookup,
+	.unlink		= hfs_unlink,
+	.mkdir		= hfs_mkdir,
+	.rmdir		= hfs_rmdir,
+	.rename		= hfs_rename,
+	.setattr	= hfs_inode_setattr,
+};
--- diff/fs/hfs/extent.c	2002-10-16 04:28:22.000000000 +0100
+++ source/fs/hfs/extent.c	2004-02-23 13:56:46.000000000 +0000
@@ -1,632 +1,32 @@
 /*
- * linux/fs/hfs/extent.c
+ *  linux/fs/hfs/extent.c
  *
  * Copyright (C) 1995-1997  Paul H. Hargrove
+ * (C) 2003 Ardis Technologies <roman@ardistech.com>
  * This file may be distributed under the terms of the GNU General Public License.
  *
  * This file contains the functions related to the extents B-tree.
- *
- * "XXX" in a comment is a note to myself to consider changing something.
- *
- * In function preconditions the term "valid" applied to a pointer to
- * a structure means that the pointer is non-NULL and the structure it
- * points to has all fields initialized to consistent values.
  */
 
-#include "hfs.h"
+#include <linux/pagemap.h>
 
-/*================ File-local data type ================*/
-
-/* An extent record on disk*/
-struct hfs_raw_extent {
-	hfs_word_t	block1;
-	hfs_word_t	length1;
-	hfs_word_t	block2;
-	hfs_word_t	length2;
-	hfs_word_t	block3;
-	hfs_word_t	length3;
-};
+#include "hfs_fs.h"
+#include "btree.h"
 
 /*================ File-local functions ================*/
 
 /*
  * build_key
  */
-static inline void build_key(struct hfs_ext_key *key,
-			     const struct hfs_fork *fork, hfs_u16 block)
-{
-	key->KeyLen = 7;
-	key->FkType = fork->fork;
-	hfs_put_nl(fork->entry->cnid, key->FNum);
-	hfs_put_hs(block,             key->FABN);
-}
-
-
-/*
- * lock_bitmap()
- *
- * Get an exclusive lock on the B-tree bitmap.
- */
-static inline void lock_bitmap(struct hfs_mdb *mdb) {
-	down(&mdb->bitmap_sem);
-}
-
-/*
- * unlock_bitmap()
- *
- * Relinquish an exclusive lock on the B-tree bitmap.
- */
-static inline void unlock_bitmap(struct hfs_mdb *mdb) {
-	up(&mdb->bitmap_sem);
-}
-
-/*
- * dump_ext()
- *
- * prints the content of a extent for debugging purposes.
- */
-#if defined(DEBUG_EXTENTS) || defined(DEBUG_ALL)
-static void dump_ext(const char *msg, const struct hfs_extent *e) {
-	if (e) {
-		hfs_warn("%s (%d-%d) (%d-%d) (%d-%d)\n", msg,
-			 e->start,
-			 e->start + e->length[0] - 1,
-			 e->start + e->length[0],
-			 e->start + e->length[0] + e->length[1] - 1,
-			 e->start + e->length[0] + e->length[1],
-			 e->end);
-	} else {
-		hfs_warn("%s NULL\n", msg);
-	}
-}
-#else
-#define dump_ext(A,B) {}
-#endif
-
-/*
- * read_extent()
- * 
- * Initializes a (struct hfs_extent) from a (struct hfs_raw_extent) and
- * the number of the starting block for the extent.
- *
- * Note that the callers must check that to,from != NULL
- */
-static void read_extent(struct hfs_extent *to,
-			const struct hfs_raw_extent *from,
-			hfs_u16 start)
-{
-	to->start = start;
-	to->block[0]  = hfs_get_hs(from->block1);
-	to->length[0] = hfs_get_hs(from->length1);
-	to->block[1]  = hfs_get_hs(from->block2);
-	to->length[1] = hfs_get_hs(from->length2);
-	to->block[2]  = hfs_get_hs(from->block3);
-	to->length[2] = hfs_get_hs(from->length3);
-	to->end = start + to->length[0] + to->length[1] + to->length[2] - 1;
-	to->next = to->prev = NULL;
-	to->count = 0;
-}
-
-/*
- * write_extent()
- * 
- * Initializes a (struct hfs_raw_extent) from a (struct hfs_extent).
- *
- * Note that the callers must check that to,from != NULL
- */
-static void write_extent(struct hfs_raw_extent *to,
-			 const struct hfs_extent *from)
-{
-	hfs_put_hs(from->block[0], to->block1);
-	hfs_put_hs(from->length[0], to->length1);
-	hfs_put_hs(from->block[1], to->block2);
-	hfs_put_hs(from->length[1], to->length2);
-	hfs_put_hs(from->block[2], to->block3);
-	hfs_put_hs(from->length[2], to->length3);
-}
-
-/*
- * decode_extent()
- *
- * Given an extent record and allocation block offset into the file,
- * return the number of the corresponding allocation block on disk,
- * or -1 if the desired block is not mapped by the given extent.
- *
- * Note that callers must check that extent != NULL
- */
-static int decode_extent(const struct hfs_extent * extent, int block)
-{
-	if (!extent || (block < extent->start) || (block > extent->end) ||
-	    (extent->end == (hfs_u16)(extent->start - 1))) {
-		return -1;
-	}
-	block -= extent->start;
-	if (block < extent->length[0]) {
-		return block + extent->block[0];
-	}
-	block -= extent->length[0];
-	if (block < extent->length[1]) {
-		return block + extent->block[1];
-	}
-	return block + extent->block[2] - extent->length[1];
-}
-
-/*
- * relse_ext()
- *
- * Reduce the reference count of an in-core extent record by one,
- * removing it from memory if the count falls to zero.
- */
-static void relse_ext(struct hfs_extent *ext)
-{
-	if (--ext->count || !ext->start) {
-		return;
-	}
-	ext->prev->next = ext->next;
-	if (ext->next) {
-		ext->next->prev = ext->prev;
-	}
-	HFS_DELETE(ext);
-}
-
-/*
- * set_cache()
- * 
- * Changes the 'cache' field of the fork.
- */
-static inline void set_cache(struct hfs_fork *fork, struct hfs_extent *ext)
-{
-	struct hfs_extent *tmp = fork->cache;
-
-	++ext->count;
-	fork->cache = ext;
-	relse_ext(tmp);
-}
-
-/*
- * find_ext()
- *
- * Given a pointer to a (struct hfs_file) and an allocation block
- * number in the file, find the extent record containing that block.
- * Returns a pointer to the extent record on success or NULL on failure.
- * The 'cache' field of 'fil' also points to the extent so it has a
- * reference count of at least 2.
- *
- * Callers must check that fil != NULL
- */
-static struct hfs_extent * find_ext(struct hfs_fork *fork, int alloc_block)
-{
-        struct hfs_cat_entry *entry = fork->entry;
-	struct hfs_btree *tr= entry->mdb->ext_tree;
-	struct hfs_ext_key target, *key;
-	struct hfs_brec brec;
-	struct hfs_extent *ext, *ptr;
-	int tmp;
-
-	if (alloc_block < 0) {
-		ext = &fork->first;
-		goto found;
-	}
-
-	ext = fork->cache;
-	if (!ext || (alloc_block < ext->start)) {
-		ext = &fork->first;
-	}
-	while (ext->next && (alloc_block > ext->end)) {
-		ext = ext->next;
-	}
-	if ((alloc_block <= ext->end) && (alloc_block >= ext->start)) {
-		goto found;
-	}
-
-	/* time to read more extents */
-	if (!HFS_NEW(ext)) {
-		goto bail3;
-	}
-
-	build_key(&target, fork, alloc_block);
-
-	tmp = hfs_bfind(&brec, tr, HFS_BKEY(&target), HFS_BFIND_READ_LE);
-	if (tmp < 0) {
-		goto bail2;
-	}
-
-	key = (struct hfs_ext_key *)brec.key;
-	if ((hfs_get_nl(key->FNum) != hfs_get_nl(target.FNum)) ||
-	    (key->FkType != fork->fork)) {
-		goto bail1;
-	}
-		
-	read_extent(ext, brec.data, hfs_get_hs(key->FABN));
-	hfs_brec_relse(&brec, NULL);
-
-	if ((alloc_block > ext->end) && (alloc_block < ext->start)) {
-		/* something strange happened */
-		goto bail2;
-	}
-
-	ptr = fork->cache;
-	if (!ptr || (alloc_block < ptr->start)) {
-		ptr = &fork->first;
-	}
-	while (ptr->next && (alloc_block > ptr->end)) {
-		ptr = ptr->next;
-	}
-	if (ext->start == ptr->start) {
-		/* somebody beat us to it. */
-		HFS_DELETE(ext);
-		ext = ptr;
-	} else if (ext->start < ptr->start) {
-		/* insert just before ptr */
-		ptr->prev->next = ext;
-		ext->prev = ptr->prev;
-		ext->next = ptr;
-		ptr->prev = ext;
-	} else {
-		/* insert at end */
-		ptr->next = ext;
-		ext->prev = ptr;
-	}
- found:
-	++ext->count; /* for return value */
-	set_cache(fork, ext);
-	return ext;
-
- bail1:
-	hfs_brec_relse(&brec, NULL);
- bail2:
-	HFS_DELETE(ext);
- bail3:
-	return NULL;
-}
-
-/*
- * delete_extent()
- *
- * Description:
- *   Deletes an extent record from a fork, reducing its physical length.
- * Input Variable(s):
- *   struct hfs_fork *fork: the fork
- *   struct hfs_extent *ext: the current last extent for 'fork'
- * Output Variable(s):
- *   NONE
- * Returns:
- *   void
- * Preconditions:
- *   'fork' points to a valid (struct hfs_fork)
- *   'ext' point to a valid (struct hfs_extent) which is the last in 'fork'
- *    and which is not also the first extent in 'fork'.
- * Postconditions:
- *   The extent record has been removed if possible, and a warning has been
- *   printed otherwise.
- */
-static void delete_extent(struct hfs_fork *fork, struct hfs_extent *ext)
+static void hfs_ext_build_key(hfs_btree_key *key, u32 cnid, u16 block, u8 type)
 {
-	struct hfs_mdb *mdb = fork->entry->mdb;
-	struct hfs_ext_key key;
-	int error;
-
-	if (fork->cache == ext) {
-		set_cache(fork, ext->prev);
-	}
-	ext->prev->next = NULL;
-	if (ext->count != 1) {
-		hfs_warn("hfs_truncate: extent has count %d.\n", ext->count);
-	}
-
-	lock_bitmap(mdb);
-	error = hfs_clear_vbm_bits(mdb, ext->block[2], ext->length[2]);
-	if (error) {
-		hfs_warn("hfs_truncate: error %d freeing blocks.\n", error);
-	}
-	error = hfs_clear_vbm_bits(mdb, ext->block[1], ext->length[1]);
-	if (error) {
-		hfs_warn("hfs_truncate: error %d freeing blocks.\n", error);
-	}
-	error = hfs_clear_vbm_bits(mdb, ext->block[0], ext->length[0]);
-	if (error) {
-		hfs_warn("hfs_truncate: error %d freeing blocks.\n", error);
-	}
-	unlock_bitmap(mdb);
-
-	build_key(&key, fork, ext->start);
-
-	error = hfs_bdelete(mdb->ext_tree, HFS_BKEY(&key));
-	if (error) {
-		hfs_warn("hfs_truncate: error %d deleting an extent.\n", error);
-	}
-
-	HFS_DELETE(ext);
+	key->key_len = 7;
+	key->ext.FkType = type;
+	key->ext.FNum = cpu_to_be32(cnid);
+	key->ext.FABN = cpu_to_be16(block);
 }
 
 /*
- * new_extent()
- *
- * Description:
- *   Adds a new extent record to a fork, extending its physical length.
- * Input Variable(s):
- *   struct hfs_fork *fork: the fork to extend
- *   struct hfs_extent *ext: the current last extent for 'fork'
- *   hfs_u16 ablock: the number of allocation blocks in 'fork'.
- *   hfs_u16 start: first allocation block to add to 'fork'.
- *   hfs_u16 len: the number of allocation blocks to add to 'fork'.
- *   hfs_u32 ablksz: number of sectors in an allocation block.
- * Output Variable(s):
- *   NONE
- * Returns:
- *   (struct hfs_extent *) the new extent or NULL
- * Preconditions:
- *   'fork' points to a valid (struct hfs_fork)
- *   'ext' point to a valid (struct hfs_extent) which is the last in 'fork'
- *   'ablock', 'start', 'len' and 'ablksz' are what they claim to be.
- * Postconditions:
- *   If NULL is returned then no changes have been made to 'fork'.
- *   If the return value is non-NULL that it is the extent that has been
- *   added to 'fork' both in memory and on disk.  The 'psize' field of
- *   'fork' has been updated to reflect the new physical size.
- */
-static struct hfs_extent *new_extent(struct hfs_fork *fork,
-				     struct hfs_extent *ext,
-				     hfs_u16 ablock, hfs_u16 start,
-				     hfs_u16 len, hfs_u16 ablksz)
-{
-	struct hfs_raw_extent raw;
-	struct hfs_ext_key key;
-	int error;
-
-	if (fork->entry->cnid == htonl(HFS_EXT_CNID)) {
-		/* Limit extents tree to the record in the MDB */
-		return NULL;
-	}
-
-	if (!HFS_NEW(ext->next)) {
-		return NULL;
-	}
-	ext->next->prev = ext;
-	ext->next->next = NULL;
-	ext = ext->next;
-	relse_ext(ext->prev);
-
-	ext->start = ablock;
-	ext->block[0] = start;
-	ext->length[0] = len;
-	ext->block[1] = 0;
-	ext->length[1] = 0;
-	ext->block[2] = 0;
-	ext->length[2] = 0;
-	ext->end = ablock + len - 1;
-	ext->count = 1;
-
-	write_extent(&raw, ext);
-	
-	build_key(&key, fork, ablock);
-
-	error = hfs_binsert(fork->entry->mdb->ext_tree, 
-			    HFS_BKEY(&key), &raw, sizeof(raw));
-	if (error) {
-		ext->prev->next = NULL;
-		HFS_DELETE(ext);
-		return NULL;
-	}
-	set_cache(fork, ext);
-	return ext;
-}
-
-/*
- * update_ext()
- *
- * Given a (struct hfs_fork) write an extent record back to disk.
- */
-static void update_ext(struct hfs_fork *fork, struct hfs_extent *ext)
-{
-	struct hfs_ext_key target;
-	struct hfs_brec brec;
-
-	if (ext->start) {
-		build_key(&target, fork, ext->start);
-
-		if (!hfs_bfind(&brec, fork->entry->mdb->ext_tree,
-			       HFS_BKEY(&target), HFS_BFIND_WRITE)) {
-			write_extent(brec.data, ext);
-			hfs_brec_relse(&brec, NULL);
-		}
-	}
-}
-
-/*
- * zero_blocks()
- * 
- * Zeros-out 'num' allocation blocks beginning with 'start'.
- */
-static int zero_blocks(struct hfs_mdb *mdb, int start, int num) {
-	hfs_buffer buf;
-	int end;
-	int j;
-
-	start = mdb->fs_start + start * mdb->alloc_blksz;
-	end = start + num * mdb->alloc_blksz;
-
-	for (j=start; j<end; ++j) {
-		if (hfs_buffer_ok(buf = hfs_buffer_get(mdb->sys_mdb, j, 0))) {
-			memset(hfs_buffer_data(buf), 0, HFS_SECTOR_SIZE);
-			hfs_buffer_dirty(buf);
-			hfs_buffer_put(buf);
-		}
-	}
-	return 0;
-}
-
-/*
- * shrink_fork()
- *
- * Try to remove enough allocation blocks from 'fork'
- * so that it is 'ablocks' allocation blocks long. 
- */
-static void shrink_fork(struct hfs_fork *fork, int ablocks)
-{
-	struct hfs_mdb *mdb = fork->entry->mdb;
-	struct hfs_extent *ext;
-	int i, error, next, count;
-	hfs_u32 ablksz = mdb->alloc_blksz;
-
-	next =  (fork->psize / ablksz) - 1;
-	ext = find_ext(fork, next);
-	while (ext && ext->start && (ext->start >= ablocks)) {
-		next = ext->start - 1;
-		delete_extent(fork, ext);
-		ext = find_ext(fork, next);
-	}
-	if (!ext) {
-		fork->psize = (next + 1) * ablksz;
-		return;
-	}
-
-	if ((count = next + 1 - ablocks) > 0) {
-		for (i=2; (i>=0) && !ext->length[i]; --i) {};
-		lock_bitmap(mdb);
-		while (count && (ext->length[i] <= count)) {
-			ext->end -= ext->length[i];
-			count -= ext->length[i];
-			error = hfs_clear_vbm_bits(mdb, ext->block[i],
-						   ext->length[i]);
-			if (error) {
-				hfs_warn("hfs_truncate: error %d freeing "
-				       "blocks.\n", error);
-			}
-			ext->block[i] = ext->length[i] = 0;
-			--i;
-		}
-		if (count) {
-			ext->end -= count;
-			ext->length[i] -= count;
-			error = hfs_clear_vbm_bits(mdb, ext->block[i] +
-						       ext->length[i], count);
-			if (error) {
-				hfs_warn("hfs_truncate: error %d freeing "
-				       "blocks.\n", error);
-			}
-		}
-		unlock_bitmap(mdb);
-		update_ext(fork, ext);
-	}
-
-	fork->psize = ablocks * ablksz;
-}
-
-/*
- * grow_fork()
- *
- * Try to add enough allocation blocks to 'fork'
- * so that it is 'ablock' allocation blocks long. 
- */
-static int grow_fork(struct hfs_fork *fork, int ablocks)
-{
-	struct hfs_cat_entry *entry = fork->entry;
-	struct hfs_mdb *mdb = entry->mdb;
-	struct hfs_extent *ext;
-	int i, start, err;
-	hfs_u16 need, len=0;
-	hfs_u32 ablksz = mdb->alloc_blksz;
-	hfs_u32 blocks, clumpablks;
-
-	blocks = fork->psize;
-	need = ablocks - blocks/ablksz;
-	if (need < 1) { /* no need to grow the fork */
-		return 0;
-	}
-
-	/* round up to clumpsize */
-	if (entry->u.file.clumpablks) {
-		clumpablks = entry->u.file.clumpablks;
-	} else {
-		clumpablks = mdb->clumpablks;
-	}
-	need = ((need + clumpablks - 1) / clumpablks) * clumpablks;
-
-	/* find last extent record and try to extend it */
-	if (!(ext = find_ext(fork, blocks/ablksz - 1))) {
-		/* somehow we couldn't find the end of the file! */
-		return -1;
-	}
-
-	/* determine which is the last used extent in the record */
-	/* then try to allocate the blocks immediately following it */
-	for (i=2; (i>=0) && !ext->length[i]; --i) {};
-	if (i>=0) {
-		/* try to extend the last extent */
-		start = ext->block[i] + ext->length[i];
-
-		err = 0;
-		lock_bitmap(mdb);
-		len = hfs_vbm_count_free(mdb, start);
-		if (!len) {
-			unlock_bitmap(mdb);
-			goto more_extents;
-		}
-		if (need < len) {
-			len = need;
-		}
-		err = hfs_set_vbm_bits(mdb, start, len);
-		unlock_bitmap(mdb);
-		if (err) {
-			relse_ext(ext);
-			return -1;
-		}
-	
-		zero_blocks(mdb, start, len);
-	
-		ext->length[i] += len;
-		ext->end += len;
-		blocks = (fork->psize += len * ablksz);
-		need -= len;
-		update_ext(fork, ext);
-	}
-
-more_extents:
-	/* add some more extents */
-	while (need) {
-		len = need;
-		err = 0;
-		lock_bitmap(mdb);
-		start = hfs_vbm_search_free(mdb, &len);
-		if (need < len) {
-			len = need;
-		}
-		err = hfs_set_vbm_bits(mdb, start, len);
-		unlock_bitmap(mdb);
-		if (!len || err) {
-			relse_ext(ext);
-			return -1;
-		}
-		zero_blocks(mdb, start, len);
-
-		/* determine which is the first free extent in the record */
-		for (i=0; (i<3) && ext->length[i]; ++i) {};
-		if (i < 3) {
-			ext->block[i] = start;
-			ext->length[i] = len;
-			ext->end += len;
-			update_ext(fork, ext);
-		} else {
-			if (!(ext = new_extent(fork, ext, blocks/ablksz,
-					       start, len, ablksz))) {
-				lock_bitmap(mdb);
-				hfs_clear_vbm_bits(mdb, start, len);
-				unlock_bitmap(mdb);
-				return -1;
-			}
-		}
-		blocks = (fork->psize += len * ablksz);
-		need -= len;
-	}
-	set_cache(fork, ext);
-	relse_ext(ext);
-	return 0;
-}
-
-/*================ Global functions ================*/
-
-/*
  * hfs_ext_compare()
  *
  * Description:
@@ -647,159 +47,480 @@ more_extents:
  *   key1 and key2 point to "valid" (struct hfs_ext_key)s.
  * Postconditions:
  *   This function has no side-effects */
-int hfs_ext_compare(const struct hfs_ext_key *key1,
-		    const struct hfs_ext_key *key2)
+int hfs_ext_keycmp(const btree_key *key1, const btree_key *key2)
 {
 	unsigned int tmp;
 	int retval;
 
-	tmp = hfs_get_hl(key1->FNum) - hfs_get_hl(key2->FNum);
+	tmp = be32_to_cpu(key1->ext.FNum) - be32_to_cpu(key2->ext.FNum);
 	if (tmp != 0) {
 		retval = (int)tmp;
 	} else {
-		tmp = (unsigned char)key1->FkType - (unsigned char)key2->FkType;
+		tmp = (unsigned char)key1->ext.FkType - (unsigned char)key2->ext.FkType;
 		if (tmp != 0) {
 			retval = (int)tmp;
 		} else {
-			retval = (int)(hfs_get_hs(key1->FABN)
-				       - hfs_get_hs(key2->FABN));
+			retval = (int)(be16_to_cpu(key1->ext.FABN)
+				       - be16_to_cpu(key2->ext.FABN));
 		}
 	}
 	return retval;
 }
 
 /*
- * hfs_extent_adj()
+ * hfs_ext_find_block
  *
- * Given an hfs_fork shrink or grow the fork to hold the
- * forks logical size.
+ * Find a block within an extent record
  */
-void hfs_extent_adj(struct hfs_fork *fork)
+static u16 hfs_ext_find_block(struct hfs_extent *ext, u16 off)
 {
-	if (fork) {
-		hfs_u32 blks, ablocks, ablksz;
+	int i;
+	u16 count;
 
-		if (fork->lsize > HFS_FORK_MAX) {
-			fork->lsize = HFS_FORK_MAX;
-		}
-
-		blks = (fork->lsize+HFS_SECTOR_SIZE-1) >> HFS_SECTOR_SIZE_BITS;
-		ablksz = fork->entry->mdb->alloc_blksz;
-		ablocks = (blks + ablksz - 1) / ablksz;
-
-		if (blks > fork->psize) {
-			grow_fork(fork, ablocks);
-			if (blks > fork->psize) {
-				fork->lsize =
-					fork->psize >> HFS_SECTOR_SIZE_BITS;
-			}
-		} else if (blks < fork->psize) {
-			shrink_fork(fork, ablocks);
-		}
+	for (i = 0; i < 3; ext++, i++) {
+		count = be16_to_cpu(ext->count);
+		if (off < count)
+			return be16_to_cpu(ext->block) + off;
+		off -= count;
 	}
+	/* panic? */
+	return 0;
 }
 
-/*
- * hfs_extent_map()
- *
- * Given an hfs_fork and a block number within the fork, return the
- * number of the corresponding physical block on disk, or zero on
- * error.
- */
-int hfs_extent_map(struct hfs_fork *fork, int block, int create) 
+static int hfs_ext_block_count(struct hfs_extent *ext)
 {
-	int ablksz, ablock, offset, tmp;
-	struct hfs_extent *ext;
+	int i;
+	u16 count = 0;
 
-	if (!fork || !fork->entry || !fork->entry->mdb) {
-		return 0;
-	}
+	for (i = 0; i < 3; ext++, i++)
+		count += be16_to_cpu(ext->count);
+	return count;
+}
 
-#if defined(DEBUG_EXTENTS) || defined(DEBUG_ALL)
-	hfs_warn("hfs_extent_map: ablock %d of file %d, fork %d\n",
-		 block, fork->entry->cnid, fork->fork);
-#endif
+static u16 hfs_ext_lastblock(struct hfs_extent *ext)
+{
+	int i;
 
-	if (block < 0) {
-		hfs_warn("hfs_extent_map: block < 0\n");
-		return 0;
-	}
-	if (block > (HFS_FORK_MAX >> HFS_SECTOR_SIZE_BITS)) {
-		hfs_warn("hfs_extent_map: block(0x%08x) > big; cnid=%d "
-			 "fork=%d\n", block, fork->entry->cnid, fork->fork);
-		return 0;
+	ext += 2;
+	for (i = 0; i < 2; ext--, i++)
+		if (ext->count)
+			break;
+	return be16_to_cpu(ext->block) + be16_to_cpu(ext->count);
+}
+
+static void __hfs_ext_write_extent(struct inode *inode, struct hfs_find_data *fd)
+{
+	int res;
+
+	hfs_ext_build_key(fd->search_key, inode->i_ino, HFS_I(inode)->cached_start,
+			  HFS_IS_RSRC(inode) ?  HFS_FK_RSRC : HFS_FK_DATA);
+	res = hfs_brec_find(fd);
+	if (HFS_I(inode)->flags & HFS_FLG_EXT_NEW) {
+		if (res != -ENOENT)
+			return;
+		hfs_brec_insert(fd, HFS_I(inode)->cached_extents, sizeof(hfs_extent_rec));
+		HFS_I(inode)->flags &= ~(HFS_FLG_EXT_DIRTY|HFS_FLG_EXT_NEW);
+	} else {
+		if (res)
+			return;
+		hfs_bnode_write(fd->bnode, HFS_I(inode)->cached_extents, fd->entryoffset, fd->entrylength);
+		HFS_I(inode)->flags &= ~HFS_FLG_EXT_DIRTY;
 	}
-	ablksz = fork->entry->mdb->alloc_blksz;
-	offset = fork->entry->mdb->fs_start + (block % ablksz);
-	ablock = block / ablksz;
-	
-	if (block >= fork->psize) {
-		if (!create || (grow_fork(fork, ablock + 1) < 0))
-			return 0;
+}
+
+void hfs_ext_write_extent(struct inode *inode)
+{
+	struct hfs_find_data fd;
+
+	if (HFS_I(inode)->flags & HFS_FLG_EXT_DIRTY) {
+		hfs_find_init(HFS_SB(inode->i_sb)->ext_tree, &fd);
+		__hfs_ext_write_extent(inode, &fd);
+		hfs_find_exit(&fd);
 	}
+}
 
-#if defined(DEBUG_EXTENTS) || defined(DEBUG_ALL)
-	hfs_warn("(lblock %d offset %d)\n", ablock, offset);
-#endif
-
-	if ((ext = find_ext(fork, ablock))) {
-		dump_ext("trying new: ", ext);
-		tmp = decode_extent(ext, ablock);
-		relse_ext(ext);
-		if (tmp >= 0) {
-			return tmp*ablksz + offset;
-		}
-	} 
+static inline int __hfs_ext_read_extent(struct hfs_find_data *fd, struct hfs_extent *extent,
+					u32 cnid, u32 block, u8 type)
+{
+	int res;
 
+	hfs_ext_build_key(fd->search_key, cnid, block, type);
+	fd->key->ext.FNum = 0;
+	res = hfs_brec_find(fd);
+	if (res && res != -ENOENT)
+		return res;
+	if (fd->key->ext.FNum != fd->search_key->ext.FNum ||
+	    fd->key->ext.FkType != fd->search_key->ext.FkType)
+		return -ENOENT;
+	if (fd->entrylength != sizeof(hfs_extent_rec))
+		return -EIO;
+	hfs_bnode_read(fd->bnode, extent, fd->entryoffset, sizeof(hfs_extent_rec));
 	return 0;
 }
 
-/*
- * hfs_extent_out()
- *
- * Copy the first extent record from a (struct hfs_fork) to a (struct
- * raw_extent), record (normally the one in the catalog entry).
- */
-void hfs_extent_out(const struct hfs_fork *fork, hfs_byte_t dummy[12])
+static inline int __hfs_ext_cache_extent(struct hfs_find_data *fd, struct inode *inode, u32 block)
 {
-	struct hfs_raw_extent *ext = (struct hfs_raw_extent *)dummy;
+	int res;
+
+	if (HFS_I(inode)->flags & HFS_FLG_EXT_DIRTY)
+		__hfs_ext_write_extent(inode, fd);
 
-	if (fork && ext) {
-		write_extent(ext, &fork->first);
-		dump_ext("extent out: ", &fork->first);
+	res = __hfs_ext_read_extent(fd, HFS_I(inode)->cached_extents, inode->i_ino,
+				    block, HFS_IS_RSRC(inode) ? HFS_FK_RSRC : HFS_FK_DATA);
+	if (!res) {
+		HFS_I(inode)->cached_start = be16_to_cpu(fd->key->ext.FABN);
+		HFS_I(inode)->cached_blocks = hfs_ext_block_count(HFS_I(inode)->cached_extents);
+	} else {
+		HFS_I(inode)->cached_start = HFS_I(inode)->cached_blocks = 0;
+		HFS_I(inode)->flags &= ~(HFS_FLG_EXT_DIRTY|HFS_FLG_EXT_NEW);
 	}
+	return res;
 }
 
-/*
- * hfs_extent_in()
- *
- * Copy an raw_extent to the 'first' and 'cache' fields of an hfs_fork.
- */
-void hfs_extent_in(struct hfs_fork *fork, const hfs_byte_t dummy[12])
+static int hfs_ext_read_extent(struct inode *inode, u16 block)
 {
-	const struct hfs_raw_extent *ext =
-		(const struct hfs_raw_extent *)dummy;
+	struct hfs_find_data fd;
+	int res;
+
+	if (block >= HFS_I(inode)->cached_start &&
+	    block < HFS_I(inode)->cached_start + HFS_I(inode)->cached_blocks)
+		return 0;
 
-	if (fork && ext) {
-		read_extent(&fork->first, ext, 0);
-		fork->cache = &fork->first;
-		fork->first.count = 2;
-		dump_ext("extent in: ", &fork->first);
+	hfs_find_init(HFS_SB(inode->i_sb)->ext_tree, &fd);
+	res = __hfs_ext_cache_extent(&fd, inode, block);
+	hfs_find_exit(&fd);
+	return res;
+}
+
+static void hfs_dump_extent(struct hfs_extent *extent)
+{
+	int i;
+
+	dprint(DBG_EXTENT, "   ");
+	for (i = 0; i < 3; i++)
+		dprint(DBG_EXTENT, " %u:%u", be16_to_cpu(extent[i].block),
+				 be16_to_cpu(extent[i].count));
+	dprint(DBG_EXTENT, "\n");
+}
+
+static int hfs_add_extent(struct hfs_extent *extent, u16 offset,
+			  u16 alloc_block, u16 block_count)
+{
+	u16 count, start;
+	int i;
+
+	hfs_dump_extent(extent);
+	for (i = 0; i < 3; extent++, i++) {
+		count = be16_to_cpu(extent->count);
+		if (offset == count) {
+			start = be16_to_cpu(extent->block);
+			if (alloc_block != start + count) {
+				if (++i >= 3)
+					return -ENOSPC;
+				extent++;
+				extent->block = cpu_to_be16(alloc_block);
+			} else
+				block_count += count;
+			extent->count = cpu_to_be16(block_count);
+			return 0;
+		} else if (offset < count)
+			break;
+		offset -= count;
+	}
+	/* panic? */
+	return -EIO;
+}
+
+int hfs_free_extents(struct super_block *sb, struct hfs_extent *extent,
+		     u16 offset, u16 block_nr)
+{
+	u16 count, start;
+	int i;
+
+	hfs_dump_extent(extent);
+	for (i = 0; i < 3; extent++, i++) {
+		count = be16_to_cpu(extent->count);
+		if (offset == count)
+			goto found;
+		else if (offset < count)
+			break;
+		offset -= count;
+	}
+	/* panic? */
+	return -EIO;
+found:
+	for (;;) {
+		start = be16_to_cpu(extent->block);
+		if (count <= block_nr) {
+			hfs_clear_vbm_bits(sb, start, count);
+			extent->block = 0;
+			extent->count = 0;
+			block_nr -= count;
+		} else {
+			count -= block_nr;
+			hfs_clear_vbm_bits(sb, start + count, block_nr);
+			extent->count = cpu_to_be16(count);
+			block_nr = 0;
+		}
+		if (!block_nr || !i)
+			return 0;
+		i--;
+		extent--;
+		count = be16_to_cpu(extent->count);
 	}
 }
 
-/* 
- * hfs_extent_free()
- *
- * Removes from memory all extents associated with 'fil'.
- */
-void hfs_extent_free(struct hfs_fork *fork)
+int hfs_free_fork(struct super_block *sb, struct hfs_cat_file *file, int type)
 {
-	if (fork) {
-		set_cache(fork, &fork->first);
+	struct hfs_find_data fd;
+	u32 total_blocks, blocks, start;
+	u32 cnid = be32_to_cpu(file->FlNum);
+	struct hfs_extent *extent;
+	int res, i;
 
-	        if (fork->first.next) {
-		        hfs_warn("hfs_extent_free: extents in use!\n");
+	if (type == HFS_FK_DATA) {
+		total_blocks = file->PyLen;
+		extent = file->ExtRec;
+	} else {
+		total_blocks = file->RPyLen;
+		extent = file->RExtRec;
+	}
+	total_blocks = be32_to_cpu(total_blocks) / HFS_SB(sb)->alloc_blksz;
+	if (!total_blocks)
+		return 0;
+
+	blocks = 0;
+	for (i = 0; i < 3; extent++, i++)
+		blocks += be16_to_cpu(extent[i].count);
+
+	res = hfs_free_extents(sb, extent, blocks, blocks);
+	if (res)
+		return res;
+	if (total_blocks == blocks)
+		return 0;
+
+	hfs_find_init(HFS_SB(sb)->ext_tree, &fd);
+	do {
+		res = __hfs_ext_read_extent(&fd, extent, cnid, total_blocks, type);
+		if (res)
+			break;
+		start = be16_to_cpu(fd.key->ext.FABN);
+		hfs_free_extents(sb, extent, total_blocks - start, total_blocks);
+		hfs_brec_remove(&fd);
+		total_blocks = start;
+	} while (total_blocks > blocks);
+	hfs_find_exit(&fd);
+
+	return res;
+}
+
+/*
+ * hfs_get_block
+ */
+int hfs_get_block(struct inode *inode, sector_t block,
+		  struct buffer_head *bh_result, int create)
+{
+	struct super_block *sb;
+	u16 dblock, ablock;
+	int res;
+
+	sb = inode->i_sb;
+	/* Convert inode block to disk allocation block */
+	ablock = (u32)block / HFS_SB(sb)->fs_div;
+
+	if (block >= inode->i_blocks) {
+		if (block > inode->i_blocks || !create)
+			return -EIO;
+		if (ablock >= HFS_I(inode)->alloc_blocks) {
+			res = hfs_extend_file(inode);
+			if (res)
+				return res;
+		}
+	} else
+		create = 0;
+
+	if (ablock < HFS_I(inode)->first_blocks) {
+		dblock = hfs_ext_find_block(HFS_I(inode)->first_extents, ablock);
+		goto done;
+	}
+
+	down(&HFS_I(inode)->extents_lock);
+	res = hfs_ext_read_extent(inode, ablock);
+	if (!res)
+		dblock = hfs_ext_find_block(HFS_I(inode)->cached_extents,
+					    ablock - HFS_I(inode)->cached_start);
+	else {
+		up(&HFS_I(inode)->extents_lock);
+		return -EIO;
+	}
+	up(&HFS_I(inode)->extents_lock);
+
+done:
+	map_bh(bh_result, sb, HFS_SB(sb)->fs_start +
+	       dblock * HFS_SB(sb)->fs_div +
+	       (u32)block % HFS_SB(sb)->fs_div);
+
+	if (create) {
+		set_buffer_new(bh_result);
+		HFS_I(inode)->phys_size += sb->s_blocksize;
+		inode->i_blocks++;
+		mark_inode_dirty(inode);
+	}
+	return 0;
+}
+
+int hfs_extend_file(struct inode *inode)
+{
+	struct super_block *sb = inode->i_sb;
+	u32 start, len, goal;
+	int res;
+
+	down(&HFS_I(inode)->extents_lock);
+	if (HFS_I(inode)->alloc_blocks == HFS_I(inode)->first_blocks)
+		goal = hfs_ext_lastblock(HFS_I(inode)->first_extents);
+	else {
+		res = hfs_ext_read_extent(inode, HFS_I(inode)->alloc_blocks);
+		if (res)
+			goto out;
+		goal = hfs_ext_lastblock(HFS_I(inode)->cached_extents);
+	}
+
+	len = HFS_I(inode)->clump_blocks;
+	start = hfs_vbm_search_free(sb, goal, &len);
+	if (!len) {
+		res = -ENOSPC;
+		goto out;
+	}
+
+	dprint(DBG_EXTENT, "extend %lu: %u,%u\n", inode->i_ino, start, len);
+	if (HFS_I(inode)->alloc_blocks == HFS_I(inode)->first_blocks) {
+		if (!HFS_I(inode)->first_blocks) {
+			dprint(DBG_EXTENT, "first extents\n");
+			/* no extents yet */
+			HFS_I(inode)->first_extents[0].block = cpu_to_be16(start);
+			HFS_I(inode)->first_extents[0].count = cpu_to_be16(len);
+			res = 0;
+		} else {
+			/* try to append to extents in inode */
+			res = hfs_add_extent(HFS_I(inode)->first_extents,
+					     HFS_I(inode)->alloc_blocks,
+					     start, len);
+			if (res == -ENOSPC)
+				goto insert_extent;
+		}
+		if (!res) {
+			hfs_dump_extent(HFS_I(inode)->first_extents);
+			HFS_I(inode)->first_blocks += len;
 		}
+	} else {
+		res = hfs_add_extent(HFS_I(inode)->cached_extents,
+				     HFS_I(inode)->alloc_blocks -
+				     HFS_I(inode)->cached_start,
+				     start, len);
+		if (!res) {
+			hfs_dump_extent(HFS_I(inode)->cached_extents);
+			HFS_I(inode)->flags |= HFS_FLG_EXT_DIRTY;
+			HFS_I(inode)->cached_blocks += len;
+		} else if (res == -ENOSPC)
+			goto insert_extent;
+	}
+out:
+	up(&HFS_I(inode)->extents_lock);
+	if (!res) {
+		HFS_I(inode)->alloc_blocks += len;
+		mark_inode_dirty(inode);
+		if (inode->i_ino < HFS_FIRSTUSER_CNID)
+			set_bit(HFS_FLG_ALT_MDB_DIRTY, &HFS_SB(sb)->flags);
+		set_bit(HFS_FLG_MDB_DIRTY, &HFS_SB(sb)->flags);
+		sb->s_dirt = 1;
+	}
+	return res;
+
+insert_extent:
+	dprint(DBG_EXTENT, "insert new extent\n");
+	hfs_ext_write_extent(inode);
+
+	memset(HFS_I(inode)->cached_extents, 0, sizeof(hfs_extent_rec));
+	HFS_I(inode)->cached_extents[0].block = cpu_to_be16(start);
+	HFS_I(inode)->cached_extents[0].count = cpu_to_be16(len);
+	hfs_dump_extent(HFS_I(inode)->cached_extents);
+	HFS_I(inode)->flags |= HFS_FLG_EXT_DIRTY|HFS_FLG_EXT_NEW;
+	HFS_I(inode)->cached_start = HFS_I(inode)->alloc_blocks;
+	HFS_I(inode)->cached_blocks = len;
+
+	res = 0;
+	goto out;
+}
+
+void hfs_file_truncate(struct inode *inode)
+{
+	struct super_block *sb = inode->i_sb;
+	struct hfs_find_data fd;
+	u16 blk_cnt, alloc_cnt, start;
+	u32 size;
+	int res;
+
+	dprint(DBG_INODE, "truncate: %lu, %Lu -> %Lu\n", inode->i_ino,
+	       (long long)HFS_I(inode)->phys_size, inode->i_size);
+	if (inode->i_size > HFS_I(inode)->phys_size) {
+		struct address_space *mapping = inode->i_mapping;
+		struct page *page;
+		int res;
+
+		size = inode->i_size - 1;
+		page = grab_cache_page(mapping, size >> PAGE_CACHE_SHIFT);
+		if (!page)
+			return;
+		size &= PAGE_CACHE_SIZE - 1;
+		size++;
+		res = mapping->a_ops->prepare_write(NULL, page, size, size);
+		if (!res)
+			res = mapping->a_ops->commit_write(NULL, page, size, size);
+		if (res)
+			inode->i_size = HFS_I(inode)->phys_size;
+		unlock_page(page);
+		page_cache_release(page);
+		mark_inode_dirty(inode);
+		return;
 	}
+	size = inode->i_size + HFS_SB(sb)->alloc_blksz - 1;
+	blk_cnt = size / HFS_SB(sb)->alloc_blksz;
+	alloc_cnt = HFS_I(inode)->alloc_blocks;
+	if (blk_cnt == alloc_cnt)
+		goto out;
+
+	down(&HFS_I(inode)->extents_lock);
+	hfs_find_init(HFS_SB(sb)->ext_tree, &fd);
+	while (1) {
+		if (alloc_cnt == HFS_I(inode)->first_blocks) {
+			hfs_free_extents(sb, HFS_I(inode)->first_extents,
+					 alloc_cnt, alloc_cnt - blk_cnt);
+			hfs_dump_extent(HFS_I(inode)->first_extents);
+			HFS_I(inode)->first_blocks = blk_cnt;
+			break;
+		}
+		res = __hfs_ext_cache_extent(&fd, inode, alloc_cnt);
+		if (res)
+			break;
+		start = HFS_I(inode)->cached_start;
+		hfs_free_extents(sb, HFS_I(inode)->cached_extents,
+				 alloc_cnt - start, alloc_cnt - blk_cnt);
+		hfs_dump_extent(HFS_I(inode)->cached_extents);
+		if (blk_cnt > start) {
+			HFS_I(inode)->flags |= HFS_FLG_EXT_DIRTY;
+			break;
+		}
+		alloc_cnt = start;
+		HFS_I(inode)->cached_start = HFS_I(inode)->cached_blocks = 0;
+		HFS_I(inode)->flags &= ~(HFS_FLG_EXT_DIRTY|HFS_FLG_EXT_NEW);
+		hfs_brec_remove(&fd);
+	}
+	hfs_find_exit(&fd);
+	up(&HFS_I(inode)->extents_lock);
+
+	HFS_I(inode)->alloc_blocks = blk_cnt;
+out:
+	HFS_I(inode)->phys_size = inode->i_size;
+	mark_inode_dirty(inode);
+	inode->i_blocks = (inode->i_size + sb->s_blocksize - 1) >> sb->s_blocksize_bits;
 }
--- diff/fs/hfs/hfs.h	2002-10-16 04:27:55.000000000 +0100
+++ source/fs/hfs/hfs.h	2004-02-23 13:56:46.000000000 +0000
@@ -1,21 +1,14 @@
-/* 
- * linux/fs/hfs/hfs.h
+/*
+ *  linux/fs/hfs/hfs.h
  *
  * Copyright (C) 1995-1997  Paul H. Hargrove
+ * (C) 2003 Ardis Technologies <roman@ardistech.com>
  * This file may be distributed under the terms of the GNU General Public License.
- *
- * "XXX" in a comment is a note to myself to consider changing something.
  */
 
 #ifndef _HFS_H
 #define _HFS_H
 
-#include <linux/hfs_sysdep.h>
-
-#define HFS_NEW(X)	((X) = hfs_malloc(sizeof(*(X))))
-#define HFS_DELETE(X)	do { hfs_free((X), sizeof(*(X))); (X) = NULL; } \
-                        while (0)
- 
 /* offsets to various blocks */
 #define HFS_DD_BLK		0 /* Driver Descriptor block */
 #define HFS_PMAP_BLK		1 /* First block of partition map */
@@ -28,46 +21,32 @@
 #define HFS_SUPER_MAGIC		0x4244 /* "BD": HFS MDB (super block) */
 #define HFS_MFS_SUPER_MAGIC	0xD2D7 /* MFS MDB (super block) */
 
-/* magic numbers for various internal structures */
-#define HFS_FILE_MAGIC		0x4801
-#define HFS_DIR_MAGIC		0x4802
-#define HFS_MDB_MAGIC		0x4803
-#define HFS_EXT_MAGIC		0x4804 /* XXX currently unused */
-#define HFS_BREC_MAGIC		0x4811 /* XXX currently unused */
-#define HFS_BTREE_MAGIC		0x4812
-#define HFS_BNODE_MAGIC		0x4813
-
 /* various FIXED size parameters */
 #define HFS_SECTOR_SIZE		512    /* size of an HFS sector */
 #define HFS_SECTOR_SIZE_BITS	9      /* log_2(HFS_SECTOR_SIZE) */
 #define HFS_NAMELEN		31     /* maximum length of an HFS filename */
-#define HFS_NAMEMAX		(3*31) /* max size of ENCODED filename */
-#define HFS_BM_MAXBLOCKS	(16)   /* max number of bitmap blocks */
-#define HFS_BM_BPB (8*HFS_SECTOR_SIZE) /* number of bits per bitmap block */
 #define HFS_MAX_VALENCE		32767U
-#define HFS_FORK_MAX		(0x7FFFFFFF)
 
 /* Meanings of the drAtrb field of the MDB,
  * Reference: _Inside Macintosh: Files_ p. 2-61
  */
-#define HFS_SB_ATTRIB_HLOCK 0x0080
-#define HFS_SB_ATTRIB_CLEAN 0x0100
-#define HFS_SB_ATTRIB_SPARED 0x0200
-#define HFS_SB_ATTRIB_SLOCK 0x8000
-
-/* 2**16 - 1 */
-#define HFS_USHRT_MAX	65535
+#define HFS_SB_ATTRIB_HLOCK	(1 << 7)
+#define HFS_SB_ATTRIB_UNMNT	(1 << 8)
+#define HFS_SB_ATTRIB_SPARED	(1 << 9)
+#define HFS_SB_ATTRIB_INCNSTNT	(1 << 11)
+#define HFS_SB_ATTRIB_SLOCK	(1 << 15)
 
 /* Some special File ID numbers */
-#define HFS_POR_CNID	1	/* Parent Of the Root */
-#define HFS_ROOT_CNID	2	/* ROOT directory */
-#define HFS_EXT_CNID	3	/* EXTents B-tree */
-#define HFS_CAT_CNID	4	/* CATalog B-tree */
-#define HFS_BAD_CNID	5	/* BAD blocks file */
-#define HFS_ALLOC_CNID  6       /* ALLOCation file (HFS+) */
-#define HFS_START_CNID  7       /* STARTup file (HFS+) */
-#define HFS_ATTR_CNID   8       /* ATTRibutes file (HFS+) */
-#define HFS_EXCH_CNID  15       /* ExchangeFiles temp id */
+#define HFS_POR_CNID		1	/* Parent Of the Root */
+#define HFS_ROOT_CNID		2	/* ROOT directory */
+#define HFS_EXT_CNID		3	/* EXTents B-tree */
+#define HFS_CAT_CNID		4	/* CATalog B-tree */
+#define HFS_BAD_CNID		5	/* BAD blocks file */
+#define HFS_ALLOC_CNID		6	/* ALLOCation file (HFS+) */
+#define HFS_START_CNID		7	/* STARTup file (HFS+) */
+#define HFS_ATTR_CNID		8	/* ATTRibutes file (HFS+) */
+#define HFS_EXCH_CNID		15	/* ExchangeFiles temp id */
+#define HFS_FIRSTUSER_CNID	16
 
 /* values for hfs_cat_rec.cdrType */
 #define HFS_CDR_DIR    0x01    /* folder (directory) */
@@ -85,7 +64,6 @@
 #define HFS_FIL_DOPEN   0x04  /* data fork open */
 #define HFS_FIL_ROPEN   0x08  /* resource fork open */
 #define HFS_FIL_DIR     0x10  /* directory (always clear) */
-#define HFS_FIL_RSRV1   0x20  /* reserved */
 #define HFS_FIL_NOCOPY  0x40  /* copy-protected file */
 #define HFS_FIL_USED	0x80  /* open */
 
@@ -96,449 +74,214 @@
 #define HFS_DIR_MOUNTED     0x08  /* mounted */
 #define HFS_DIR_DIR         0x10  /* directory (always set) */
 #define HFS_DIR_EXPFOLDER   0x20  /* share point */
-#define HFS_DIR_RSRV1       0x40  /* reserved */
-#define HFS_DIR_RSRV2       0x80  /* reserved */
 
-/* Access types used when requesting access to a B-node */
-#define HFS_LOCK_NONE	0x0000	/* Illegal */
-#define HFS_LOCK_READ	0x0001	/* read-only access */
-#define HFS_LOCK_RESRV	0x0002	/* might potentially modify */
-#define HFS_LOCK_WRITE	0x0003	/* will modify now (exclusive access) */
-#define HFS_LOCK_MASK	0x000f
-
-/* Flags field of the hfs_path_elem */
-#define HFS_BPATH_FIRST		0x0100
-#define HFS_BPATH_OVERFLOW	0x0200
-#define HFS_BPATH_UNDERFLOW	0x0400
-#define HFS_BPATH_MASK		0x0f00
-
-/* Flags for hfs_bfind() */
-#define HFS_BFIND_EXACT		0x0010
-#define HFS_BFIND_LOCK		0x0020
-
-/* Modes for hfs_bfind() */
-#define HFS_BFIND_WRITE   (HFS_LOCK_RESRV|HFS_BFIND_EXACT|HFS_BFIND_LOCK)
-#define HFS_BFIND_READ_EQ (HFS_LOCK_READ|HFS_BFIND_EXACT)
-#define HFS_BFIND_READ_LE (HFS_LOCK_READ)
-#define HFS_BFIND_INSERT  (HFS_LOCK_RESRV|HFS_BPATH_FIRST|HFS_BPATH_OVERFLOW)
-#define HFS_BFIND_DELETE \
-	 (HFS_LOCK_RESRV|HFS_BFIND_EXACT|HFS_BPATH_FIRST|HFS_BPATH_UNDERFLOW)
+/* bits hfs_finfo.fdFlags */
+#define HFS_FLG_INITED		0x0100
+#define HFS_FLG_LOCKED		0x1000
+#define HFS_FLG_INVISIBLE	0x4000
 
 /*======== HFS structures as they appear on the disk ========*/
 
+#define __packed __attribute__ ((packed))
+
 /* Pascal-style string of up to 31 characters */
 struct hfs_name {
-	hfs_byte_t	Len;
-	hfs_byte_t	Name[31];
-} __attribute__((packed));
-
-typedef struct {
-	hfs_word_t	v;
-	hfs_word_t	h;
-} hfs_point_t;
-
-typedef struct {
-	hfs_word_t	top;
-	hfs_word_t	left;
-	hfs_word_t	bottom;
-	hfs_word_t	right;
-} hfs_rect_t;
-
-typedef struct {
-	hfs_lword_t	 fdType;
-	hfs_lword_t	 fdCreator;
-	hfs_word_t	 fdFlags;
-	hfs_point_t	 fdLocation;
-	hfs_word_t	 fdFldr;
-} __attribute__((packed)) hfs_finfo_t;
-
-typedef struct {
-	hfs_word_t	fdIconID;
-	hfs_byte_t	fdUnused[8];
-	hfs_word_t	fdComment;
-	hfs_lword_t	fdPutAway;
-} __attribute__((packed)) hfs_fxinfo_t;
-
-typedef struct {
-	hfs_rect_t	frRect;
-	hfs_word_t	frFlags;
-	hfs_point_t	frLocation;
-	hfs_word_t	frView;
-} __attribute__((packed)) hfs_dinfo_t;
-
-typedef struct {
-	hfs_point_t	frScroll;
-	hfs_lword_t	frOpenChain;
-	hfs_word_t	frUnused;
-	hfs_word_t	frComment;
-	hfs_lword_t	frPutAway;
-} __attribute__((packed)) hfs_dxinfo_t;
+	u8 len;
+	u8 name[HFS_NAMELEN];
+} __packed;
+
+struct hfs_point {
+	u16 v;
+	u16 h;
+} __packed;
+
+struct hfs_rect {
+	u16 top;
+	u16 left;
+	u16 bottom;
+	u16 right;
+} __packed;
+
+struct hfs_finfo {
+	u32 fdType;
+	u32 fdCreator;
+	u16 fdFlags;
+	struct hfs_point fdLocation;
+	u16 fdFldr;
+} __packed;
+
+struct hfs_fxinfo {
+	u16 fdIconID;
+	u8 fdUnused[8];
+	u16 fdComment;
+	u32 fdPutAway;
+} __packed;
+
+struct hfs_dinfo {
+	struct hfs_rect frRect;
+	u16 frFlags;
+	struct hfs_point frLocation;
+	u16 frView;
+} __packed;
+
+struct hfs_dxinfo {
+	struct hfs_point frScroll;
+	u32 frOpenChain;
+	u16 frUnused;
+	u16 frComment;
+	u32 frPutAway;
+} __packed;
 
 union hfs_finder_info {
 	struct {
-		hfs_finfo_t	finfo;
-		hfs_fxinfo_t	fxinfo;
+		struct hfs_finfo finfo;
+		struct hfs_fxinfo fxinfo;
 	} file;
 	struct {
-		hfs_dinfo_t	dinfo;
-		hfs_dxinfo_t	dxinfo;
+		struct hfs_dinfo dinfo;
+		struct hfs_dxinfo dxinfo;
 	} dir;
-};
-
-/* A btree record key on disk */
-struct hfs_bkey {
-	hfs_byte_t	KeyLen;		/* number of bytes in the key */
-	hfs_byte_t	value[1];	/* (KeyLen) bytes of key */
-} __attribute__((packed));
+} __packed;
 
 /* Cast to a pointer to a generic bkey */
 #define	HFS_BKEY(X)	(((void)((X)->KeyLen)), ((struct hfs_bkey *)(X)))
 
 /* The key used in the catalog b-tree: */
 struct hfs_cat_key {
-	hfs_byte_t	KeyLen;	/* number of bytes in the key */
-	hfs_byte_t	Resrv1;	/* padding */
-	hfs_lword_t	ParID;	/* CNID of the parent dir */
+	u8 key_len;		/* number of bytes in the key */
+	u8 reserved;		/* padding */
+	u32 ParID;		/* CNID of the parent dir */
 	struct hfs_name	CName;	/* The filename of the entry */
-} __attribute__((packed));
+} __packed;
 
 /* The key used in the extents b-tree: */
 struct hfs_ext_key {
-	hfs_byte_t	KeyLen;	/* number of bytes in the key */
-	hfs_byte_t	FkType;	/* HFS_FK_{DATA,RSRC} */
-	hfs_lword_t	FNum;	/* The File ID of the file */
-	hfs_word_t	FABN;	/* allocation blocks number*/
-} __attribute__((packed));
+	u8 key_len;		/* number of bytes in the key */
+	u8 FkType;		/* HFS_FK_{DATA,RSRC} */
+	u32 FNum;		/* The File ID of the file */
+	u16 FABN;		/* allocation blocks number*/
+} __packed;
+
+typedef union hfs_btree_key {
+	u8 key_len;			/* number of bytes in the key */
+	struct hfs_cat_key cat;
+	struct hfs_ext_key ext;
+} hfs_btree_key;
 
-/*======== Data structures kept in memory ========*/
+typedef union hfs_btree_key btree_key;
 
-/*
- * struct hfs_mdb
- *
- * The fields from the MDB of an HFS filesystem
- */
-struct hfs_mdb {
-	int			magic;		/* A magic number */
-	unsigned char		vname[28];	/* The volume name */
-	hfs_sysmdb		sys_mdb;	/* superblock */
-	hfs_buffer		buf;		/* The hfs_buffer
-						   holding the real
-						   superblock (aka VIB
-						   or MDB) */
-	hfs_buffer		alt_buf;	/* The hfs_buffer holding
-						   the alternate superblock */
-	hfs_buffer		bitmap[16];	/* The hfs_buffer holding the
-						   allocation bitmap */
-	struct hfs_btree *	ext_tree;	/* Information about
-						   the extents b-tree */
-	struct hfs_btree *	cat_tree;	/* Information about
-						   the catalog b-tree */
-	hfs_u32			file_count;	/* The number of
-						   regular files in
-						   the filesystem */
-	hfs_u32			dir_count;	/* The number of
-						   directories in the
-						   filesystem */
-	hfs_u32			next_id;	/* The next available
-						   file id number */
-	hfs_u32			clumpablks;	/* The number of allocation
-						   blocks to try to add when
-						   extending a file */
-	hfs_u32			write_count;	/* The number of MDB
-						   writes (a sort of
-						   version number) */
-	hfs_u32			fs_start;	/* The first 512-byte
-						   block represented
-						   in the bitmap */
-	hfs_u32			create_date;	/* In network byte-order */
-	hfs_u32			modify_date;	/* In network byte-order */
-	hfs_u32			backup_date;	/* In network byte-order */
-	hfs_u16			root_files;	/* The number of
-						   regular
-						   (non-directory)
-						   files in the root
-						   directory */
-	hfs_u16			root_dirs;	/* The number of
-						   directories in the
-						   root directory */
-	hfs_u16			fs_ablocks;	/* The number of
-						   allocation blocks
-						   in the filesystem */
-	hfs_u16			free_ablocks;	/* The number of unused
-						   allocation blocks
-						   in the filesystem */
-	hfs_u32			alloc_blksz;	/* The number of
-						   512-byte blocks per
-						   "allocation block" */
-	hfs_u16			attrib;		/* Attribute word */
-	struct semaphore	bitmap_sem;
-        struct list_head        entry_dirty;
-};
-
-/*
- * struct hfs_extent
- *
- * The offset to allocation block mapping for a given file is
- * contained in a series of these structures.  Each (struct
- * hfs_extent) records up to three runs of contiguous allocation
- * blocks.  An allocation block is a contiguous group of physical
- * blocks.
- */
 struct hfs_extent {
-	int		   magic;     /* A magic number */
-	unsigned short	   start;     /* Where in the file this record
-					 begins (in allocation blocks) */
-	unsigned short	   end;	      /* Where in the file this record
-					 ends (in allocation blocks) */
-	unsigned short	   block[3];  /* The allocation block on disk which
-					 begins this extent */
-	unsigned short	   length[3]; /* The number of allocation blocks
-					 in this extent */
-	struct hfs_extent  *next;     /* Next extent record for this file */
-	struct hfs_extent  *prev;     /* Previous extent record for this file */
-	int		   count;     /* Number of times it is used */
-};
-
-/*
- * struct hfs_dir 
- *
- * This structure holds information specific
- * to a directory in an HFS filesystem.
- */
-struct hfs_dir {		
-	int		magic;		/* A magic number */
-	hfs_u16		flags;
-	hfs_u16		dirs;		/* Number of directories in this one */
-	hfs_u16		files;		/* Number of files in this directory */
-	struct rw_semaphore	sem;
-};
-
-/*
- * struct hfs_fork
- *
- * This structure holds the information
- * specific to a single fork of a file.
- */
-struct hfs_fork {
-	struct hfs_cat_entry	*entry;    /* The file this fork is part of */
-	struct hfs_extent	first;     /* The first extent record for
-						 this fork */
-	struct hfs_extent	*cache;    /* The most-recently accessed
-						 extent record for this fork */
-	hfs_u32			lsize;     /* The logical size in bytes */
-	hfs_u32			psize;     /* The phys size (512-byte blocks) */
-        hfs_u8			fork;      /* Which fork is this? */
-};
-
-/*
- * struct hfs_file 
- *
- * This structure holds information specific
- * to a file in an HFS filesystem.
- */
-struct hfs_file {
-	int		   magic;
-	struct hfs_fork    data_fork;
-	struct hfs_fork    rsrc_fork;
-	hfs_u16		   clumpablks;
-	hfs_u8		   flags;
-};
-
-/*
- * struct hfs_file 
- *
- * This structure holds information about a
- * file or directory in an HFS filesystem.
- *
- * 'wait' must remain 1st and 'hash' 2nd since we do some pointer arithmetic.
- */
-struct hfs_cat_entry {
-	hfs_wait_queue		wait;
-        struct list_head        hash;
-        struct list_head        list;
-	struct hfs_mdb		*mdb;
-	hfs_sysentry		sys_entry;
-	struct hfs_cat_key	key;
-	union hfs_finder_info	info;
-	hfs_u32			cnid;		/* In network byte-order */
-	hfs_u32			create_date;	/* In network byte-order */
-	hfs_u32			modify_date;	/* In network byte-order */
-	hfs_u32			backup_date;	/* In network byte-order */
-	unsigned short		count;
-        unsigned long           state;
-	hfs_u8			type;
-	union {
-		struct hfs_dir	dir;
-		struct hfs_file file;
-	} u;
+	u16 block;
+	u16 count;
 };
+typedef struct hfs_extent hfs_extent_rec[3];
 
-/* hfs entry state bits */
-#define HFS_DIRTY        1
-#define HFS_KEYDIRTY     2
-#define HFS_LOCK         4
-#define HFS_DELETED      8
+/* The catalog record for a file */
+struct hfs_cat_file {
+	s8 type;			/* The type of entry */
+	u8 reserved;
+	u8 Flags;			/* Flags such as read-only */
+	s8 Typ;				/* file version number = 0 */
+	struct hfs_finfo UsrWds;	/* data used by the Finder */
+	u32 FlNum;			/* The CNID */
+	u16 StBlk;			/* obsolete */
+	u32 LgLen;			/* The logical EOF of the data fork*/
+	u32 PyLen;			/* The physical EOF of the data fork */
+	u16 RStBlk;			/* obsolete */
+	u32 RLgLen;			/* The logical EOF of the rsrc fork */
+	u32 RPyLen;			/* The physical EOF of the rsrc fork */
+	u32 CrDat;			/* The creation date */
+	u32 MdDat;			/* The modified date */
+	u32 BkDat;			/* The last backup date */
+	struct hfs_fxinfo FndrInfo;	/* more data for the Finder */
+	u16 ClpSize;			/* number of bytes to allocate
+					   when extending files */
+	hfs_extent_rec ExtRec;		/* first extent record
+					   for the data fork */
+	hfs_extent_rec RExtRec;		/* first extent record
+					   for the resource fork */
+	u32 Resrv;			/* reserved by Apple */
+} __packed;
+
+/* the catalog record for a directory */
+struct hfs_cat_dir {
+	s8 type;			/* The type of entry */
+	u8 reserved;
+	u16 Flags;			/* flags */
+	u16 Val;			/* Valence: number of files and
+					   dirs in the directory */
+	u32 DirID;			/* The CNID */
+	u32 CrDat;			/* The creation date */
+	u32 MdDat;			/* The modification date */
+	u32 BkDat;			/* The last backup date */
+	struct hfs_dinfo UsrInfo;	/* data used by the Finder */
+	struct hfs_dxinfo FndrInfo;	/* more data used by Finder */
+	u8 Resrv[16];			/* reserved by Apple */
+} __packed;
+
+/* the catalog record for a thread */
+struct hfs_cat_thread {
+	s8 type;			/* The type of entry */
+	u8 reserved[9];			/* reserved by Apple */
+	u32 ParID;			/* CNID of parent directory */
+	struct hfs_name CName;		/* The name of this entry */
+}  __packed;
+
+/* A catalog tree record */
+typedef union hfs_cat_rec {
+	s8 type;			/* The type of entry */
+	struct hfs_cat_file file;
+	struct hfs_cat_dir dir;
+	struct hfs_cat_thread thread;
+} hfs_cat_rec;
 
-/* 
- * struct hfs_bnode_ref
- *
- * A pointer to a (struct hfs_bnode) and the type of lock held on it.
- */
-struct hfs_bnode_ref {
-        struct hfs_bnode *bn;
-        int lock_type;
-};
+struct hfs_mdb {
+	u16 drSigWord;			/* Signature word indicating fs type */
+	u32 drCrDate;			/* fs creation date/time */
+	u32 drLsMod;			/* fs modification date/time */
+	u16 drAtrb;			/* fs attributes */
+	u16 drNmFls;			/* number of files in root directory */
+	u16 drVBMSt;			/* location (in 512-byte blocks)
+					   of the volume bitmap */
+	u16 drAllocPtr;			/* location (in allocation blocks)
+					   to begin next allocation search */
+	u16 drNmAlBlks;			/* number of allocation blocks */
+	u32 drAlBlkSiz;			/* bytes in an allocation block */
+	u32 drClpSiz;			/* clumpsize, the number of bytes to
+					   allocate when extending a file */
+	u16 drAlBlSt;			/* location (in 512-byte blocks)
+					   of the first allocation block */
+	u32 drNxtCNID;			/* CNID to assign to the next
+					   file or directory created */
+	u16 drFreeBks;			/* number of free allocation blocks */
+	u8 drVN[28];			/* the volume label */
+	u32 drVolBkUp;			/* fs backup date/time */
+	u16 drVSeqNum;			/* backup sequence number */
+	u32 drWrCnt;			/* fs write count */
+	u32 drXTClpSiz;			/* clumpsize for the extents B-tree */
+	u32 drCTClpSiz;			/* clumpsize for the catalog B-tree */
+	u16 drNmRtDirs;			/* number of directories in
+					   the root directory */
+	u32 drFilCnt;			/* number of files in the fs */
+	u32 drDirCnt;			/* number of directories in the fs */
+	u8 drFndrInfo[32];		/* data used by the Finder */
+	u16 drEmbedSigWord;		/* embedded volume signature */
+	u32 drEmbedExtent;		/* starting block number (xdrStABN)
+					   and number of allocation blocks
+					   (xdrNumABlks) occupied by embedded
+					   volume */
+	u32 drXTFlSize;			/* bytes in the extents B-tree */
+	hfs_extent_rec drXTExtRec;	/* extents B-tree's first 3 extents */
+	u32 drCTFlSize;			/* bytes in the catalog B-tree */
+	hfs_extent_rec drCTExtRec;	/* catalog B-tree's first 3 extents */
+} __packed;
 
-/*
- * struct hfs_belem
- *
- * An element of the path from the root of a B-tree to a leaf.
- * Includes the reference to a (struct hfs_bnode), the index of
- * the appropriate record in that node, and some flags.
- */
-struct hfs_belem {
-	struct hfs_bnode_ref	bnr;
-	int			record;
-	int			flags;
-};
+/*======== Data structures kept in memory ========*/
 
-/*
- * struct hfs_brec
- *
- * The structure returned by hfs_bfind() to describe the requested record.
- */
-struct hfs_brec {
-	int			keep_flags;
-	struct hfs_btree	*tree;
-	struct hfs_belem	*top;
-	struct hfs_belem	*bottom;
-	struct hfs_belem	elem[9];
-	struct hfs_bkey		*key;
-	void			*data;	/* The actual data */
+struct hfs_readdir_data {
+	struct list_head list;
+	struct file *file;
+	struct hfs_cat_key key;
 };
 
-/*================ Function prototypes ================*/
-
-/* bdelete.c */
-extern int hfs_bdelete(struct hfs_btree *, const struct hfs_bkey *);
-
-/* bfind.c */
-extern void hfs_brec_relse(struct hfs_brec *, struct hfs_belem *);
-extern int hfs_bsucc(struct hfs_brec *, int);
-extern int hfs_bfind(struct hfs_brec *, struct hfs_btree *,
-		     const struct hfs_bkey *, int);
- 
-/* binsert.c */
-extern int hfs_binsert(struct hfs_btree *, const struct hfs_bkey *,
-		       const void *, hfs_u16);
-
-/* bitmap.c */
-extern hfs_u16 hfs_vbm_count_free(const struct hfs_mdb *, hfs_u16);
-extern hfs_u16 hfs_vbm_search_free(const struct hfs_mdb *, hfs_u16 *);
-extern int hfs_set_vbm_bits(struct hfs_mdb *, hfs_u16, hfs_u16);
-extern int hfs_clear_vbm_bits(struct hfs_mdb *, hfs_u16, hfs_u16);
-
-/* bitops.c */
-extern hfs_u32 hfs_find_zero_bit(const hfs_u32 *, hfs_u32, hfs_u32);
-extern hfs_u32 hfs_count_zero_bits(const hfs_u32 *, hfs_u32, hfs_u32);
-
-/* btree.c */
-extern struct hfs_btree *hfs_btree_init(struct hfs_mdb *, ino_t,
-				        hfs_byte_t *, hfs_u32, hfs_u32);
-extern void hfs_btree_free(struct hfs_btree *);
-extern void hfs_btree_commit(struct hfs_btree *, hfs_byte_t *, hfs_lword_t);
-
-/* catalog.c */
-extern void hfs_cat_init(void);
-extern void hfs_cat_put(struct hfs_cat_entry *);
-extern void hfs_cat_mark_dirty(struct hfs_cat_entry *);
-extern struct hfs_cat_entry *hfs_cat_get(struct hfs_mdb *,
-					 const struct hfs_cat_key *);
-
-extern void hfs_cat_invalidate(struct hfs_mdb *);
-extern void hfs_cat_commit(struct hfs_mdb *);
-extern void hfs_cat_free(void);
-
-extern int hfs_cat_compare(const struct hfs_cat_key *,
-			   const struct hfs_cat_key *);
-extern void hfs_cat_build_key(hfs_u32, const struct hfs_name *,
-			      struct hfs_cat_key *);
-extern struct hfs_cat_entry *hfs_cat_parent(struct hfs_cat_entry *);
-
-extern int hfs_cat_open(struct hfs_cat_entry *, struct hfs_brec *);
-extern int hfs_cat_next(struct hfs_cat_entry *, struct hfs_brec *,
-			hfs_u16, hfs_u32 *, hfs_u8 *);
-extern void hfs_cat_close(struct hfs_cat_entry *, struct hfs_brec *);
-
-extern int hfs_cat_create(struct hfs_cat_entry *, struct hfs_cat_key *,
-			  hfs_u8, hfs_u32, hfs_u32, struct hfs_cat_entry **);
-extern int hfs_cat_mkdir(struct hfs_cat_entry *, struct hfs_cat_key *,
-			 struct hfs_cat_entry **);
-extern int hfs_cat_delete(struct hfs_cat_entry *, struct hfs_cat_entry *, int);
-extern int hfs_cat_move(struct hfs_cat_entry *, struct hfs_cat_entry *,
-			struct hfs_cat_entry *, struct hfs_cat_key *,
-			struct hfs_cat_entry **);
-
-/* extent.c */
-extern int hfs_ext_compare(const struct hfs_ext_key *,
-			   const struct hfs_ext_key *);
-extern void hfs_extent_in(struct hfs_fork *, const hfs_byte_t *);
-extern void hfs_extent_out(const struct hfs_fork *, hfs_byte_t *);
-extern int hfs_extent_map(struct hfs_fork *, int, int);
-extern void hfs_extent_adj(struct hfs_fork *);
-extern void hfs_extent_free(struct hfs_fork *);
-
-/* file.c */
-extern int hfs_get_block(struct inode *, sector_t, struct buffer_head *, int);
-
-/* mdb.c */
-extern struct hfs_mdb *hfs_mdb_get(hfs_sysmdb, int, hfs_s32);
-extern void hfs_mdb_commit(struct hfs_mdb *, int);
-extern void hfs_mdb_put(struct hfs_mdb *, int);
-
-/* part_tbl.c */
-extern int hfs_part_find(hfs_sysmdb, int, int, hfs_s32 *, hfs_s32 *);
-
-/* string.c */
-extern unsigned int hfs_strhash(const unsigned char *, unsigned int);
-extern int hfs_strcmp(const unsigned char *, unsigned int, 
-		      const unsigned char *, unsigned int);
-extern int hfs_streq(const unsigned char *, unsigned int, 
-		     const unsigned char *, unsigned int);
-extern void hfs_tolower(unsigned char *, int);
-
-static __inline__ struct dentry 
-*hfs_lookup_dentry(struct dentry *base, const char *name, const int len)
-{
-  struct qstr this;
-
-  this.name = name;
-  this.len = len;
-  this.hash = hfs_strhash(name, len);
-
-  return d_lookup(base, &this);
-}
-
-/* drop a dentry for one of the special directories.
- * it's in the form of base/name/dentry. */
-static __inline__ void hfs_drop_special(struct dentry *base,
-					const struct hfs_name *name,
-					struct dentry *dentry)
-{
-  struct dentry *dparent, *de;
-  
-  dparent = hfs_lookup_dentry(base, name->Name, name->Len);
-  if (dparent) {
-	  de = hfs_lookup_dentry(dparent, dentry->d_name.name, 
-				 dentry->d_name.len);
-	  if (de) {
-		  if (!de->d_inode)
-			  d_drop(de);
-		  dput(de);
-	  }
-	  dput(dparent);
-  }
-}
-
-extern struct dentry_operations hfs_dentry_operations;
 #endif
--- diff/fs/hfs/inode.c	2003-09-17 12:28:11.000000000 +0100
+++ source/fs/hfs/inode.c	2004-02-23 13:56:46.000000000 +0000
@@ -1,259 +1,342 @@
 /*
- * linux/fs/hfs/inode.c
+ *  linux/fs/hfs/inode.c
  *
  * Copyright (C) 1995-1997  Paul H. Hargrove
+ * (C) 2003 Ardis Technologies <roman@ardistech.com>
  * This file may be distributed under the terms of the GNU General Public License.
  *
  * This file contains inode-related functions which do not depend on
  * which scheme is being used to represent forks.
  *
  * Based on the minix file system code, (C) 1991, 1992 by Linus Torvalds
- *
- * "XXX" in a comment is a note to myself to consider changing something.
- *
- * In function preconditions the term "valid" applied to a pointer to
- * a structure means that the pointer is non-NULL and the structure it
- * points to has all fields initialized to consistent values.
  */
 
-#include "hfs.h"
-#include <linux/hfs_fs_sb.h>
-#include <linux/hfs_fs_i.h>
-#include <linux/hfs_fs.h>
 #include <linux/pagemap.h>
-#include <linux/smp_lock.h>
+#include <linux/version.h>
+#include <linux/mpage.h>
+
+#include "hfs_fs.h"
+#include "btree.h"
 
 /*================ Variable-like macros ================*/
 
 #define HFS_VALID_MODE_BITS  (S_IFREG | S_IFDIR | S_IRWXUGO)
 
-/*================ File-local functions ================*/
+static int hfs_writepage(struct page *page, struct writeback_control *wbc)
+{
+	return block_write_full_page(page, hfs_get_block, wbc);
+}
 
-/*
- * init_file_inode()
- *
- * Given an HFS catalog entry initialize an inode for a file.
- */
-static void init_file_inode(struct inode *inode, hfs_u8 fork)
+static int hfs_readpage(struct file *file, struct page *page)
 {
-	struct hfs_fork *fk;
-	struct hfs_cat_entry *entry = HFS_I(inode)->entry;
+	return block_read_full_page(page, hfs_get_block);
+}
 
-	if (fork == HFS_FK_DATA) {
-		inode->i_mode = S_IRWXUGO | S_IFREG;
-	} else {
-		inode->i_mode = S_IRUGO | S_IWUGO | S_IFREG;
-	}
+static int hfs_prepare_write(struct file *file, struct page *page, unsigned from, unsigned to)
+{
+	return cont_prepare_write(page, from, to, hfs_get_block,
+				  &HFS_I(page->mapping->host)->phys_size);
+}
 
-	if (fork == HFS_FK_DATA) {
-#if 0 /* XXX: disable crlf translations for now */
-		hfs_u32 type = hfs_get_nl(entry->info.file.finfo.fdType);
-
-		HFS_I(inode)->convert =
-			((HFS_SB(inode->i_sb)->s_conv == 't') ||
-			 ((HFS_SB(inode->i_sb)->s_conv == 'a') &&
-			  ((type == htonl(0x54455854)) ||   /* "TEXT" */
-			   (type == htonl(0x7474726f)))));  /* "ttro" */
-#else
-		HFS_I(inode)->convert = 0;
-#endif
-		fk = &entry->u.file.data_fork;
+static sector_t hfs_bmap(struct address_space *mapping, sector_t block)
+{
+	return generic_block_bmap(mapping, block, hfs_get_block);
+}
+
+int hfs_releasepage(struct page *page, int mask)
+{
+	struct inode *inode = page->mapping->host;
+	struct super_block *sb = inode->i_sb;
+	struct hfs_btree *tree;
+	struct hfs_bnode *node;
+	u32 nidx;
+	int i, res = 1;
+
+	switch (inode->i_ino) {
+	case HFS_EXT_CNID:
+		tree = HFS_SB(sb)->ext_tree;
+		break;
+	case HFS_CAT_CNID:
+		tree = HFS_SB(sb)->cat_tree;
+		break;
+	default:
+		BUG();
+		return 0;
+	}
+	if (tree->node_size >= PAGE_CACHE_SIZE) {
+		nidx = page->index >> (tree->node_size_shift - PAGE_CACHE_SHIFT);
+		spin_lock(&tree->hash_lock);
+		node = hfs_bnode_findhash(tree, nidx);
+		if (!node)
+			;
+		else if (atomic_read(&node->refcnt))
+			res = 0;
+		else for (i = 0; i < tree->pages_per_bnode; i++) {
+			if (PageActive(node->page[i])) {
+				res = 0;
+				break;
+			}
+		}
+		if (res && node) {
+			hfs_bnode_unhash(node);
+			hfs_bnode_free(node);
+		}
+		spin_unlock(&tree->hash_lock);
 	} else {
-		fk = &entry->u.file.rsrc_fork;
-		HFS_I(inode)->convert = 0;
+		nidx = page->index << (PAGE_CACHE_SHIFT - tree->node_size_shift);
+		i = 1 << (PAGE_CACHE_SHIFT - tree->node_size_shift);
+		spin_lock(&tree->hash_lock);
+		do {
+			node = hfs_bnode_findhash(tree, nidx++);
+			if (!node)
+				continue;
+			if (atomic_read(&node->refcnt)) {
+				res = 0;
+				break;
+			}
+			hfs_bnode_unhash(node);
+			hfs_bnode_free(node);
+		} while (--i);
+		spin_unlock(&tree->hash_lock);
 	}
-	HFS_I(inode)->fork = fk;
-	inode->i_size = fk->lsize;
-	inode->i_blocks = fk->psize;
-	inode->i_nlink = 1;
+	//printk("releasepage: %lu,%x = %d\n", page->index, mask, res);
+	return res;
 }
 
-/*================ Global functions ================*/
+static int hfs_get_blocks(struct inode *inode, sector_t iblock, unsigned long max_blocks,
+			  struct buffer_head *bh_result, int create)
+{
+	int ret;
 
-/*
- * hfs_put_inode()
- *
- * This is the put_inode() entry in the super_operations for HFS
- * filesystems.  The purpose is to perform any filesystem-dependent 
- * cleanup necessary when the use-count of an inode falls to zero.
- */
-void hfs_put_inode(struct inode * inode)
+	ret = hfs_get_block(inode, iblock, bh_result, create);
+	if (!ret)
+		bh_result->b_size = (1 << inode->i_blkbits);
+	return ret;
+}
+
+static int hfs_direct_IO(int rw, struct kiocb *iocb, const struct iovec *iov,
+			 loff_t offset, unsigned long nr_segs)
 {
-	struct hfs_cat_entry *entry = HFS_I(inode)->entry;
+	struct file *file = iocb->ki_filp;
+	struct inode *inode = file->f_dentry->d_inode->i_mapping->host;
 
-	lock_kernel();
-	hfs_cat_put(entry);
-	if (atomic_read(&inode->i_count) == 1) {
-	  struct hfs_hdr_layout *tmp = HFS_I(inode)->layout;
+	return blockdev_direct_IO(rw, iocb, inode, inode->i_sb->s_bdev, iov,
+				  offset, nr_segs, hfs_get_blocks, NULL);
+}
 
-	  if (tmp) {
-		HFS_I(inode)->layout = NULL;
-		HFS_DELETE(tmp);
-	  }
-	}
-	unlock_kernel();
+static int hfs_writepages(struct address_space *mapping,
+			  struct writeback_control *wbc)
+{
+	return mpage_writepages(mapping, wbc, hfs_get_block);
 }
 
+struct address_space_operations hfs_btree_aops = {
+	.readpage	= hfs_readpage,
+	.writepage	= hfs_writepage,
+	.sync_page	= block_sync_page,
+	.prepare_write	= hfs_prepare_write,
+	.commit_write	= generic_commit_write,
+	.bmap		= hfs_bmap,
+	.releasepage	= hfs_releasepage,
+};
+
+struct address_space_operations hfs_aops = {
+	.readpage	= hfs_readpage,
+	.writepage	= hfs_writepage,
+	.sync_page	= block_sync_page,
+	.prepare_write	= hfs_prepare_write,
+	.commit_write	= generic_commit_write,
+	.bmap		= hfs_bmap,
+	.direct_IO	= hfs_direct_IO,
+	.writepages	= hfs_writepages,
+};
+
 /*
- * hfs_notify_change()
- *
- * Based very closely on fs/msdos/inode.c by Werner Almesberger
- *
- * This is the notify_change() field in the super_operations structure
- * for HFS file systems.  The purpose is to take that changes made to
- * an inode and apply then in a filesystem-dependent manner.  In this
- * case the process has a few of tasks to do:
- *  1) prevent changes to the i_uid and i_gid fields.
- *  2) map file permissions to the closest allowable permissions
- *  3) Since multiple Linux files can share the same on-disk inode under
- *     HFS (for instance the data and resource forks of a file) a change
- *     to permissions must be applied to all other in-core inodes which 
- *     correspond to the same HFS file.
+ * hfs_new_inode
  */
-enum {HFS_NORM, HFS_HDR, HFS_CAP};
-
-static int __hfs_notify_change(struct dentry *dentry, struct iattr * attr, int kind)
+struct inode *hfs_new_inode(struct inode *dir, struct qstr *name, int mode)
 {
-	struct inode *inode = dentry->d_inode;
-	struct hfs_cat_entry *entry = HFS_I(inode)->entry;
-	struct dentry **de = entry->sys_entry;
-	struct hfs_sb_info *hsb = HFS_SB(inode->i_sb);
-	int error=0, i;
+	struct super_block *sb = dir->i_sb;
+	struct inode *inode = new_inode(sb);
+	if (!inode)
+		return NULL;
 
-	lock_kernel();
+	init_MUTEX(&HFS_I(inode)->extents_lock);
+	INIT_LIST_HEAD(&HFS_I(inode)->open_dir_list);
+	hfs_cat_build_key((btree_key *)&HFS_I(inode)->cat_key, dir->i_ino, name);
+	inode->i_ino = HFS_SB(sb)->next_id++;
+	inode->i_mode = mode;
+	inode->i_uid = current->fsuid;
+	inode->i_gid = current->fsgid;
+	inode->i_nlink = 1;
+	inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
+	HFS_I(inode)->flags = 0;
+	HFS_I(inode)->rsrc_inode = NULL;
+	if (S_ISDIR(inode->i_mode)) {
+		inode->i_size = 2;
+		HFS_SB(sb)->folder_count++;
+		if (dir->i_ino == HFS_ROOT_CNID)
+			HFS_SB(sb)->root_dirs++;
+		inode->i_op = &hfs_dir_inode_operations;
+		inode->i_fop = &hfs_dir_operations;
+	} else if (S_ISREG(inode->i_mode)) {
+		HFS_I(inode)->clump_blocks = HFS_SB(sb)->clumpablks;
+		HFS_SB(sb)->file_count++;
+		if (dir->i_ino == HFS_ROOT_CNID)
+			HFS_SB(sb)->root_files++;
+		inode->i_op = &hfs_file_inode_operations;
+		inode->i_fop = &hfs_file_operations;
+		inode->i_mapping->a_ops = &hfs_aops;
+		HFS_I(inode)->phys_size = 0;
+		HFS_I(inode)->alloc_blocks = 0;
+		HFS_I(inode)->first_blocks = 0;
+		HFS_I(inode)->cached_start = 0;
+		HFS_I(inode)->cached_blocks = 0;
+		memset(HFS_I(inode)->first_extents, 0, sizeof(hfs_extent_rec));
+		memset(HFS_I(inode)->cached_extents, 0, sizeof(hfs_extent_rec));
+	}
+	insert_inode_hash(inode);
+	mark_inode_dirty(inode);
+	set_bit(HFS_FLG_MDB_DIRTY, &HFS_SB(sb)->flags);
+	sb->s_dirt = 1;
 
-	error = inode_change_ok(inode, attr); /* basic permission checks */
-	if (error) {
-		/* Let netatalk's afpd think chmod() always succeeds */
-		if (hsb->s_afpd &&
-		    (attr->ia_valid == (ATTR_MODE | ATTR_CTIME))) {
-			error = 0;
-		}
-		goto out; 
-	}
+	return inode;
+}
 
-	/* no uig/gid changes and limit which mode bits can be set */
-	if (((attr->ia_valid & ATTR_UID) && 
-	     (attr->ia_uid != hsb->s_uid)) ||
-	    ((attr->ia_valid & ATTR_GID) && 
-	     (attr->ia_gid != hsb->s_gid)) ||
-	    ((attr->ia_valid & ATTR_MODE) &&
-	     (((entry->type == HFS_CDR_DIR) &&
-	       (attr->ia_mode != inode->i_mode))||
-	      (attr->ia_mode & ~HFS_VALID_MODE_BITS)))) {
-		if( hsb->s_quiet ) { 
-			error = 0;
-			goto out;
-		}
-	}
-	
-	if (entry->type == HFS_CDR_DIR) {
-		attr->ia_valid &= ~ATTR_MODE;
-	} else if (attr->ia_valid & ATTR_MODE) {
-		/* Only the 'w' bits can ever change and only all together. */
-		if (attr->ia_mode & S_IWUSR) {
-			attr->ia_mode = inode->i_mode | S_IWUGO;
-		} else {
-			attr->ia_mode = inode->i_mode & ~S_IWUGO;
-		}
-		attr->ia_mode &= ~hsb->s_umask;
-	}
-	/*
-	 * Normal files handle size change in normal way.
-	 * Oddballs are served here.
-	 */
-	if (attr->ia_valid & ATTR_SIZE) {
-		if (kind == HFS_CAP) {
-			inode->i_size = attr->ia_size;
-			if (inode->i_size > HFS_FORK_MAX)
-				inode->i_size = HFS_FORK_MAX;
-			mark_inode_dirty(inode);
-			attr->ia_valid &= ~ATTR_SIZE;
-		} else if (kind == HFS_HDR) {
-			hdr_truncate(inode, attr->ia_size);
-			attr->ia_valid &= ~ATTR_SIZE;
-		}
-	}
-	error = inode_setattr(inode, attr);
-	if (error) 
-		goto out;
-	
-	/* We wouldn't want to mess with the sizes of the other fork */
-	attr->ia_valid &= ~ATTR_SIZE;
-
-	/* We must change all in-core inodes corresponding to this file. */
-	for (i = 0; i < 4; ++i) {
-	  if (de[i] && (de[i] != dentry)) {
-		inode_setattr(de[i]->d_inode, attr);
-	  }
-	}
+void hfs_delete_inode(struct inode *inode)
+{
+	struct super_block *sb = inode->i_sb;
 
-	/* Change the catalog entry if needed */
-	if (attr->ia_valid & ATTR_MTIME) {
-		entry->modify_date = hfs_u_to_mtime(inode->i_mtime.tv_sec);
-		hfs_cat_mark_dirty(entry);
-	}
-	if (attr->ia_valid & ATTR_MODE) {
-		hfs_u8 new_flags;
+	dprint(DBG_INODE, "delete_inode: %lu\n", inode->i_ino);
+	if (S_ISDIR(inode->i_mode)) {
+		HFS_SB(sb)->folder_count--;
+		if (HFS_I(inode)->cat_key.ParID == be32_to_cpu(HFS_ROOT_CNID))
+			HFS_SB(sb)->root_dirs--;
+		set_bit(HFS_FLG_MDB_DIRTY, &HFS_SB(sb)->flags);
+		sb->s_dirt = 1;
+		return;
+	}
+	HFS_SB(sb)->file_count--;
+	if (HFS_I(inode)->cat_key.ParID == be32_to_cpu(HFS_ROOT_CNID))
+		HFS_SB(sb)->root_files--;
+	if (S_ISREG(inode->i_mode)) {
+		if (!inode->i_nlink) {
+			inode->i_size = 0;
+			hfs_file_truncate(inode);
+		}
+	}
+	set_bit(HFS_FLG_MDB_DIRTY, &HFS_SB(sb)->flags);
+	sb->s_dirt = 1;
+}
+
+void hfs_inode_read_fork(struct inode *inode, struct hfs_extent *ext,
+			 u32 log_size, u32 phys_size, u32 clump_size)
+{
+	struct super_block *sb = inode->i_sb;
+	u16 count;
+	int i;
+
+	memcpy(HFS_I(inode)->first_extents, ext, sizeof(hfs_extent_rec));
+	for (count = 0, i = 0; i < 3; i++)
+		count += be16_to_cpu(ext[i].count);
+	HFS_I(inode)->first_blocks = count;
+
+	log_size = be32_to_cpu(log_size);
+	inode->i_size = HFS_I(inode)->phys_size = log_size;
+	inode->i_blocks = (log_size + sb->s_blocksize - 1) >> sb->s_blocksize_bits;
+	HFS_I(inode)->alloc_blocks = be32_to_cpu(phys_size) /
+				     HFS_SB(sb)->alloc_blksz;
+	HFS_I(inode)->clump_blocks = clump_size / HFS_SB(sb)->alloc_blksz;
+	if (!HFS_I(inode)->clump_blocks)
+		HFS_I(inode)->clump_blocks = HFS_SB(sb)->clumpablks;
+}
+
+struct hfs_iget_data {
+	struct hfs_cat_key *key;
+	hfs_cat_rec *rec;
+};
 
-		if (inode->i_mode & S_IWUSR) {
-			new_flags = entry->u.file.flags & ~HFS_FIL_LOCK;
-		} else {
-			new_flags = entry->u.file.flags | HFS_FIL_LOCK;
-		}
+int hfs_test_inode(struct inode *inode, void *data)
+{
+	struct hfs_iget_data *idata = data;
+	hfs_cat_rec *rec;
 
-		if (new_flags != entry->u.file.flags) {
-			entry->u.file.flags = new_flags;
-			hfs_cat_mark_dirty(entry);
-		}
+	rec = idata->rec;
+	switch (rec->type) {
+	case HFS_CDR_DIR:
+		return inode->i_ino == be32_to_cpu(rec->dir.DirID);
+	case HFS_CDR_FIL:
+		return inode->i_ino == be32_to_cpu(rec->file.FlNum);
+	default:
+		BUG();
+		return 1;
 	}
-	/* size changes handled in hfs_extent_adj() */
-
-out:
-	unlock_kernel();
-	return error;
 }
 
-int hfs_notify_change(struct dentry *dentry, struct iattr * attr)
+/*
+ * hfs_read_inode
+ */
+int hfs_read_inode(struct inode *inode, void *data)
 {
-	return __hfs_notify_change(dentry, attr, HFS_NORM);
-}
+	struct hfs_iget_data *idata = data;
+	struct hfs_sb_info *hsb = HFS_SB(inode->i_sb);
+	hfs_cat_rec *rec;
 
-int hfs_notify_change_cap(struct dentry *dentry, struct iattr * attr)
-{
-	return __hfs_notify_change(dentry, attr, HFS_CAP);
-}
+	HFS_I(inode)->flags = 0;
+	HFS_I(inode)->rsrc_inode = NULL;
+	init_MUTEX(&HFS_I(inode)->extents_lock);
+	INIT_LIST_HEAD(&HFS_I(inode)->open_dir_list);
+
+	/* Initialize the inode */
+	inode->i_uid = hsb->s_uid;
+	inode->i_gid = hsb->s_gid;
+	inode->i_nlink = 1;
 
-int hfs_notify_change_hdr(struct dentry *dentry, struct iattr * attr)
-{
-	return __hfs_notify_change(dentry, attr, HFS_HDR);
-}
+	if (idata->key)
+		HFS_I(inode)->cat_key = *idata->key;
+	else
+		HFS_I(inode)->flags |= HFS_FLG_RSRC;
+	HFS_I(inode)->tz_secondswest = sys_tz.tz_minuteswest * 60;
+
+	rec = idata->rec;
+	switch (rec->type) {
+	case HFS_CDR_FIL:
+		if (!HFS_IS_RSRC(inode)) {
+			hfs_inode_read_fork(inode, rec->file.ExtRec, rec->file.LgLen,
+					    rec->file.PyLen, be16_to_cpu(rec->file.ClpSize));
+		} else {
+			hfs_inode_read_fork(inode, rec->file.RExtRec, rec->file.RLgLen,
+					    rec->file.RPyLen, be16_to_cpu(rec->file.ClpSize));
+		}
 
-static int hfs_writepage(struct page *page, struct writeback_control *wbc)
-{
-	return block_write_full_page(page,hfs_get_block, wbc);
-}
-static int hfs_readpage(struct file *file, struct page *page)
-{
-	return block_read_full_page(page,hfs_get_block);
-}
-static int hfs_prepare_write(struct file *file, struct page *page, unsigned from, unsigned to)
-{
-	return cont_prepare_write(page,from,to,hfs_get_block,
-		&HFS_I(page->mapping->host)->mmu_private);
-}
-static sector_t hfs_bmap(struct address_space *mapping, sector_t block)
-{
-	return generic_block_bmap(mapping,block,hfs_get_block);
+		inode->i_ino = be32_to_cpu(rec->file.FlNum);
+		inode->i_mode = S_IRUGO | S_IXUGO;
+		if (!(rec->file.Flags & HFS_FIL_LOCK))
+			inode->i_mode |= S_IWUGO;
+		inode->i_mode &= hsb->s_file_umask;
+		inode->i_mode |= S_IFREG;
+		inode->i_ctime = inode->i_atime = inode->i_mtime =
+				hfs_m_to_utime(rec->file.MdDat);
+		inode->i_op = &hfs_file_inode_operations;
+		inode->i_fop = &hfs_file_operations;
+		inode->i_mapping->a_ops = &hfs_aops;
+		HFS_I(inode)->phys_size = inode->i_size;
+		break;
+	case HFS_CDR_DIR:
+		inode->i_ino = be32_to_cpu(rec->dir.DirID);
+		inode->i_blocks = 0;
+		inode->i_size = be16_to_cpu(rec->dir.Val) + 2;
+		inode->i_mode = S_IFDIR | (S_IRWXUGO & hsb->s_dir_umask);
+		inode->i_ctime = inode->i_atime = inode->i_mtime =
+				hfs_m_to_utime(rec->file.MdDat);
+		inode->i_op = &hfs_dir_inode_operations;
+		inode->i_fop = &hfs_dir_operations;
+		break;
+	default:
+		make_bad_inode(inode);
+	}
+	return 0;
 }
-struct address_space_operations hfs_aops = {
-	.readpage = hfs_readpage,
-	.writepage = hfs_writepage,
-	.sync_page = block_sync_page,
-	.prepare_write = hfs_prepare_write,
-	.commit_write = generic_commit_write,
-	.bmap = hfs_bmap
-};
 
 /*
  * __hfs_iget()
@@ -263,253 +346,277 @@ struct address_space_operations hfs_aops
  * inode for that file/directory or NULL.  Note that 'type' indicates
  * whether we want the actual file or directory, or the corresponding
  * metadata (AppleDouble header file or CAP metadata file).
- *
- * In an ideal world we could call iget() and would not need this
- * function.  However, since there is no way to even know the inode
- * number until we've found the file/directory in the catalog B-tree
- * that simply won't happen.
- *
- * The main idea here is to look in the catalog B-tree to get the
- * vital info about the file or directory (including the file id which
- * becomes the inode number) and then to call iget() and return the
- * inode if it is complete.  If it is not then we use the catalog
- * entry to fill in the missing info, by calling the appropriate
- * 'fillin' function.  Note that these fillin functions are
- * essentially hfs_*_read_inode() functions, but since there is no way
- * to pass the catalog entry through iget() to such a read_inode()
- * function, we have to call them after iget() returns an incomplete
- * inode to us.	 This is pretty much the same problem faced in the NFS
- * code, and pretty much the same solution. The SMB filesystem deals
- * with this in a different way: by using the address of the
- * kmalloc()'d space which holds the data as the inode number.
- *
- * XXX: Both this function and NFS's corresponding nfs_fhget() would
- * benefit from a way to pass an additional (void *) through iget() to
- * the VFS read_inode() function.
- *
- * this will hfs_cat_put() the entry if it fails.
  */
-struct inode *hfs_iget(struct hfs_cat_entry *entry, ino_t type,
-		       struct dentry *dentry)
+struct inode *hfs_iget(struct super_block *sb, struct hfs_cat_key *key, hfs_cat_rec *rec)
 {
-	struct dentry **sys_entry;
-	struct super_block *sb;
+	struct hfs_iget_data data = { key, rec };
 	struct inode *inode;
+	u32 cnid;
 
-	if (!entry) {
+	switch (rec->type) {
+	case HFS_CDR_DIR:
+		cnid = be32_to_cpu(rec->dir.DirID);
+		break;
+	case HFS_CDR_FIL:
+		cnid = be32_to_cpu(rec->file.FlNum);
+		break;
+	default:
 		return NULL;
 	}
+	inode = iget5_locked(sb, cnid, hfs_test_inode, hfs_read_inode, &data);
+	if (inode && (inode->i_state & I_NEW))
+		unlock_new_inode(inode);
+	return inode;
+}
 
-	/* If there are several processes all calling __iget() for
-	   the same inode then they will all get the same one back.
-	   The first one to return from __iget() will notice that the
-	   i_mode field of the inode is blank and KNOW that it is
-	   the first to return.  Therefore, it will set the appropriate
-	   'sys_entry' field in the entry and initialize the inode.
-	   All the initialization must be done without sleeping,
-	   or else other processes could end up using a partially
-	   initialized inode.				*/
-
-	sb = entry->mdb->sys_mdb;
-	sys_entry = &entry->sys_entry[HFS_ITYPE_TO_INT(type)];
-
-	if (!(inode = iget(sb, ntohl(entry->cnid) | type))) {
-	        hfs_cat_put(entry);
-	        return NULL;
-	}
-
-	if (!inode->i_mode || (*sys_entry == NULL)) {
-		/* Initialize the inode */
-		struct hfs_sb_info *hsb = HFS_SB(sb);
-
-		inode->i_ctime.tv_sec = inode->i_atime.tv_sec = inode->i_mtime.tv_sec =
-					hfs_m_to_utime(entry->modify_date);
-		inode->i_ctime.tv_nsec = 0;
-		inode->i_mtime.tv_nsec = 0;
-		inode->i_atime.tv_nsec = 0;
-		inode->i_blksize = HFS_SECTOR_SIZE;
-		inode->i_uid = hsb->s_uid;
-		inode->i_gid = hsb->s_gid;
-
-		HFS_I(inode)->mmu_private = 0;
-		HFS_I(inode)->fork = NULL;
-		HFS_I(inode)->convert = 0;
-		HFS_I(inode)->file_type = 0;
-		HFS_I(inode)->dir_size = 0;
-		HFS_I(inode)->default_layout = NULL;
-		HFS_I(inode)->layout = NULL;
-		HFS_I(inode)->magic = HFS_INO_MAGIC;
-		HFS_I(inode)->entry = entry;
-		HFS_I(inode)->tz_secondswest = hfs_to_utc(0);
-
-		hsb->s_ifill(inode, type, hsb->s_version);
-		if (!hsb->s_afpd && (entry->type == HFS_CDR_FIL) &&
-		    (entry->u.file.flags & HFS_FIL_LOCK)) {
-			inode->i_mode &= ~S_IWUGO;
-		}
-		inode->i_mode &= ~hsb->s_umask;
+void hfs_inode_write_fork(struct inode *inode, struct hfs_extent *ext,
+			  u32 *log_size, u32 *phys_size)
+{
+	memcpy(ext, HFS_I(inode)->first_extents, sizeof(hfs_extent_rec));
+
+	if (log_size)
+		*log_size = cpu_to_be32(inode->i_size);
+	if (phys_size)
+		*phys_size = cpu_to_be32(HFS_I(inode)->alloc_blocks *
+					 HFS_SB(inode->i_sb)->alloc_blksz);
+}
 
-		if (!inode->i_mode) {
-			iput(inode); /* does an hfs_cat_put */
-			inode = NULL;
-		} else
-			*sys_entry = dentry; /* cache dentry */
+void hfs_write_inode(struct inode *inode, int unused)
+{
+	struct hfs_find_data fd;
+	hfs_cat_rec rec;
+
+	dprint(DBG_INODE, "hfs_write_inode: %lu\n", inode->i_ino);
+	hfs_ext_write_extent(inode);
 
+	if (inode->i_ino < HFS_FIRSTUSER_CNID) {
+		switch (inode->i_ino) {
+		case HFS_ROOT_CNID:
+			break;
+		case HFS_EXT_CNID:
+			hfs_btree_write(HFS_SB(inode->i_sb)->ext_tree);
+			return;
+		case HFS_CAT_CNID:
+			hfs_btree_write(HFS_SB(inode->i_sb)->cat_tree);
+			return;
+		default:
+			BUG();
+			return;
+		}
 	}
 
-	return inode;
-}
+	if (HFS_IS_RSRC(inode)) {
+		mark_inode_dirty(HFS_I(inode)->rsrc_inode);
+		return;
+	}
 
-/*================ Scheme-specific functions ================*/
+	if (!inode->i_nlink)
+		return;
 
-/* 
- * hfs_cap_ifill()
- *
- * This function serves the same purpose as a read_inode() function does
- * in other filesystems.  It is called by __hfs_iget() to fill in
- * the missing fields of an uninitialized inode under the CAP scheme.
- */
-void hfs_cap_ifill(struct inode * inode, ino_t type, const int version)
-{
-	struct hfs_cat_entry *entry = HFS_I(inode)->entry;
+	if (hfs_find_init(HFS_SB(inode->i_sb)->cat_tree, &fd))
+		/* panic? */
+		return;
 
-	HFS_I(inode)->d_drop_op = hfs_cap_drop_dentry;
-	if (type == HFS_CAP_FNDR) {
-		inode->i_size = sizeof(struct hfs_cap_info);
-		inode->i_blocks = 0;
-		inode->i_nlink = 1;
-		inode->i_mode = S_IRUGO | S_IWUGO | S_IFREG;
-		inode->i_op = &hfs_cap_info_inode_operations;
-		inode->i_fop = &hfs_cap_info_operations;
-	} else if (entry->type == HFS_CDR_FIL) {
-		init_file_inode(inode, (type == HFS_CAP_DATA) ?
-						HFS_FK_DATA : HFS_FK_RSRC);
-		inode->i_op = &hfs_file_inode_operations;
-		inode->i_fop = &hfs_file_operations;
-		inode->i_mapping->a_ops = &hfs_aops;
-		HFS_I(inode)->mmu_private = inode->i_size;
-	} else { /* Directory */
-		struct hfs_dir *hdir = &entry->u.dir;
+	fd.search_key->cat = HFS_I(inode)->cat_key;
+	if (hfs_brec_find(&fd))
+		/* panic? */
+		goto out;
 
-		inode->i_blocks = 0;
-		inode->i_size = hdir->files + hdir->dirs + 5;
-		HFS_I(inode)->dir_size = 1;
-		if (type == HFS_CAP_NDIR) {
-			inode->i_mode = S_IRWXUGO | S_IFDIR;
-			inode->i_nlink = hdir->dirs + 4;
-			inode->i_op = &hfs_cap_ndir_inode_operations;
-			inode->i_fop = &hfs_cap_dir_operations;
-			HFS_I(inode)->file_type = HFS_CAP_NORM;
-		} else if (type == HFS_CAP_FDIR) {
-			inode->i_mode = S_IRUGO | S_IXUGO | S_IFDIR;
-			inode->i_nlink = 2;
-			inode->i_op = &hfs_cap_fdir_inode_operations;
-			inode->i_fop = &hfs_cap_dir_operations;
-			HFS_I(inode)->file_type = HFS_CAP_FNDR;
-		} else if (type == HFS_CAP_RDIR) {
-			inode->i_mode = S_IRUGO | S_IXUGO | S_IFDIR;
-			inode->i_nlink = 2;
-			inode->i_op = &hfs_cap_rdir_inode_operations;
-			inode->i_fop = &hfs_cap_dir_operations;
-			HFS_I(inode)->file_type = HFS_CAP_RSRC;
+	if (S_ISDIR(inode->i_mode)) {
+		if (fd.entrylength < sizeof(struct hfs_cat_dir))
+			/* panic? */;
+		hfs_bnode_read(fd.bnode, &rec, fd.entryoffset,
+			   sizeof(struct hfs_cat_dir));
+		if (rec.type != HFS_CDR_DIR ||
+		    be32_to_cpu(rec.dir.DirID) != inode->i_ino) {
 		}
+
+		rec.dir.MdDat = hfs_u_to_mtime(inode->i_mtime);
+		rec.dir.Val = cpu_to_be16(inode->i_size - 2);
+
+		hfs_bnode_write(fd.bnode, &rec, fd.entryoffset,
+			    sizeof(struct hfs_cat_dir));
+	} else {
+		if (fd.entrylength < sizeof(struct hfs_cat_file))
+			/* panic? */;
+		hfs_bnode_read(fd.bnode, &rec, fd.entryoffset,
+			   sizeof(struct hfs_cat_file));
+		if (rec.type != HFS_CDR_FIL ||
+		    be32_to_cpu(rec.file.FlNum) != inode->i_ino) {
+		}
+
+		if (inode->i_mode & S_IWUSR)
+			rec.file.Flags &= ~HFS_FIL_LOCK;
+		else
+			rec.file.Flags |= HFS_FIL_LOCK;
+		hfs_inode_write_fork(inode, rec.file.ExtRec, &rec.file.LgLen, &rec.file.PyLen);
+		if (HFS_I(inode)->rsrc_inode)
+			hfs_inode_write_fork(HFS_I(inode)->rsrc_inode, rec.file.RExtRec,
+					     &rec.file.RLgLen, &rec.file.RPyLen);
+		rec.file.MdDat = hfs_u_to_mtime(inode->i_mtime);
+
+		hfs_bnode_write(fd.bnode, &rec, fd.entryoffset,
+			    sizeof(struct hfs_cat_file));
 	}
+out:
+	hfs_find_exit(&fd);
 }
 
-/* 
- * hfs_dbl_ifill()
- *
- * This function serves the same purpose as a read_inode() function does
- * in other filesystems.  It is called by __hfs_iget() to fill in
- * the missing fields of an uninitialized inode under the AppleDouble
- * scheme.
- */
-void hfs_dbl_ifill(struct inode * inode, ino_t type, const int version)
+static struct dentry *hfs_file_lookup(struct inode *dir, struct dentry *dentry,
+				      struct nameidata *nd)
 {
-	struct hfs_cat_entry *entry = HFS_I(inode)->entry;
+	struct inode *inode = NULL;
+	hfs_cat_rec rec;
+	struct hfs_find_data fd;
+	int res;
 
-	HFS_I(inode)->d_drop_op = hfs_dbl_drop_dentry;
-	if (type == HFS_DBL_HDR) {
-		if (entry->type == HFS_CDR_FIL) {
-			init_file_inode(inode, HFS_FK_RSRC);
-			inode->i_size += HFS_DBL_HDR_LEN;
-			HFS_I(inode)->default_layout = &hfs_dbl_fil_hdr_layout;
-		} else {
-			inode->i_size = HFS_DBL_HDR_LEN;
-			inode->i_mode = S_IRUGO | S_IWUGO | S_IFREG;
-			inode->i_nlink = 1;
-			HFS_I(inode)->default_layout = &hfs_dbl_dir_hdr_layout;
-		}
-		inode->i_op = &hfs_hdr_inode_operations;
-		inode->i_fop = &hfs_hdr_operations;
-	} else if (entry->type == HFS_CDR_FIL) {
-		init_file_inode(inode, HFS_FK_DATA);
-		inode->i_op = &hfs_file_inode_operations;
-		inode->i_fop = &hfs_file_operations;
-		inode->i_mapping->a_ops = &hfs_aops;
-		HFS_I(inode)->mmu_private = inode->i_size;
-	} else { /* Directory */
-		struct hfs_dir *hdir = &entry->u.dir;
+	if (HFS_IS_RSRC(dir) || strcmp(dentry->d_name.name, "rsrc"))
+		goto out;
 
-		inode->i_blocks = 0;
-		inode->i_nlink = hdir->dirs + 2;
-		inode->i_size = 3 + 2 * (hdir->dirs + hdir->files);
-		inode->i_mode = S_IRWXUGO | S_IFDIR;
-		inode->i_op = &hfs_dbl_dir_inode_operations;
-		inode->i_fop = &hfs_dbl_dir_operations;
-		HFS_I(inode)->file_type = HFS_DBL_NORM;
-		HFS_I(inode)->dir_size = 2;
+	inode = HFS_I(dir)->rsrc_inode;
+	if (inode)
+		goto out;
+
+	inode = new_inode(dir->i_sb);
+	if (!inode)
+		return ERR_PTR(-ENOMEM);
+
+	hfs_find_init(HFS_SB(dir->i_sb)->cat_tree, &fd);
+	fd.search_key->cat = HFS_I(dir)->cat_key;
+	res = hfs_brec_read(&fd, &rec, sizeof(rec));
+	if (!res) {
+		struct hfs_iget_data idata = { NULL, &rec };
+		hfs_read_inode(inode, &idata);
+	}
+	hfs_find_exit(&fd);
+	if (res) {
+		iput(inode);
+		return ERR_PTR(res);
+	}
+	HFS_I(inode)->rsrc_inode = dir;
+	HFS_I(dir)->rsrc_inode = inode;
+	igrab(dir);
+	hlist_add_head(&inode->i_hash, &HFS_SB(dir->i_sb)->rsrc_inodes);
+	mark_inode_dirty(inode);
+out:
+	d_add(dentry, inode);
+	return NULL;
+}
+
+void hfs_clear_inode(struct inode *inode)
+{
+	if (HFS_IS_RSRC(inode) && HFS_I(inode)->rsrc_inode) {
+		HFS_I(HFS_I(inode)->rsrc_inode)->rsrc_inode = NULL;
+		iput(HFS_I(inode)->rsrc_inode);
+	}
+}
+
+static int hfs_permission(struct inode *inode, int mask,
+			  struct nameidata *nd)
+{
+	if (S_ISREG(inode->i_mode) && mask & MAY_EXEC)
+		return 0;
+	return vfs_permission(inode, mask);
+}
+
+static int hfs_file_open(struct inode *inode, struct file *file)
+{
+	if (HFS_IS_RSRC(inode))
+		inode = HFS_I(inode)->rsrc_inode;
+	if (atomic_read(&file->f_count) != 1)
+		return 0;
+	atomic_inc(&HFS_I(inode)->opencnt);
+	return 0;
+}
+
+static int hfs_file_release(struct inode *inode, struct file *file)
+{
+	//struct super_block *sb = inode->i_sb;
+
+	if (HFS_IS_RSRC(inode))
+		inode = HFS_I(inode)->rsrc_inode;
+	if (atomic_read(&file->f_count) != 0)
+		return 0;
+	if (atomic_dec_and_test(&HFS_I(inode)->opencnt)) {
+		down(&inode->i_sem);
+		hfs_file_truncate(inode);
+		//if (inode->i_flags & S_DEAD) {
+		//	hfs_delete_cat(inode->i_ino, HFSPLUS_SB(sb).hidden_dir, NULL);
+		//	hfs_delete_inode(inode);
+		//}
+		up(&inode->i_sem);
 	}
+	return 0;
 }
 
-/* 
- * hfs_nat_ifill()
+/*
+ * hfs_notify_change()
  *
- * This function serves the same purpose as a read_inode() function does
- * in other filesystems.  It is called by __hfs_iget() to fill in
- * the missing fields of an uninitialized inode under the Netatalk
- * scheme.
+ * Based very closely on fs/msdos/inode.c by Werner Almesberger
+ *
+ * This is the notify_change() field in the super_operations structure
+ * for HFS file systems.  The purpose is to take that changes made to
+ * an inode and apply then in a filesystem-dependent manner.  In this
+ * case the process has a few of tasks to do:
+ *  1) prevent changes to the i_uid and i_gid fields.
+ *  2) map file permissions to the closest allowable permissions
+ *  3) Since multiple Linux files can share the same on-disk inode under
+ *     HFS (for instance the data and resource forks of a file) a change
+ *     to permissions must be applied to all other in-core inodes which
+ *     correspond to the same HFS file.
  */
-void hfs_nat_ifill(struct inode * inode, ino_t type, const int version)
+
+int hfs_inode_setattr(struct dentry *dentry, struct iattr * attr)
 {
-	struct hfs_cat_entry *entry = HFS_I(inode)->entry;
+	struct inode *inode = dentry->d_inode;
+	struct hfs_sb_info *hsb = HFS_SB(inode->i_sb);
+	int error;
 
-	HFS_I(inode)->d_drop_op = hfs_nat_drop_dentry;
-	if (type == HFS_NAT_HDR) {
-		if (entry->type == HFS_CDR_FIL) {
-			init_file_inode(inode, HFS_FK_RSRC);
-			inode->i_size += HFS_NAT_HDR_LEN;
-		} else {
-			inode->i_size = HFS_NAT_HDR_LEN;
-			inode->i_mode = S_IRUGO | S_IWUGO | S_IFREG;
-			inode->i_nlink = 1;
-		}
-		inode->i_op = &hfs_hdr_inode_operations;
-		inode->i_fop = &hfs_hdr_operations;
-		HFS_I(inode)->default_layout = (version == 2) ?
-			&hfs_nat2_hdr_layout : &hfs_nat_hdr_layout;
-	} else if (entry->type == HFS_CDR_FIL) {
-		init_file_inode(inode, HFS_FK_DATA);
-		inode->i_op = &hfs_file_inode_operations;
-		inode->i_fop = &hfs_file_operations;
-		inode->i_mapping->a_ops = &hfs_aops;
-		HFS_I(inode)->mmu_private = inode->i_size;
-	} else { /* Directory */
-		struct hfs_dir *hdir = &entry->u.dir;
+	error = inode_change_ok(inode, attr); /* basic permission checks */
+	if (error)
+		return error;
 
-		inode->i_blocks = 0;
-		inode->i_size = hdir->files + hdir->dirs + 4;
-		inode->i_mode = S_IRWXUGO | S_IFDIR;
-		HFS_I(inode)->dir_size = 1;
-		if (type == HFS_NAT_NDIR) {
-			inode->i_nlink = hdir->dirs + 3;
-			inode->i_op = &hfs_nat_ndir_inode_operations;
-			HFS_I(inode)->file_type = HFS_NAT_NORM;
-		} else if (type == HFS_NAT_HDIR) {
-			inode->i_nlink = 2;
-			inode->i_op = &hfs_nat_hdir_inode_operations;
-			HFS_I(inode)->file_type = HFS_NAT_HDR;
-		}
-		inode->i_fop = &hfs_nat_dir_operations;
+	/* no uig/gid changes and limit which mode bits can be set */
+	if (((attr->ia_valid & ATTR_UID) &&
+	     (attr->ia_uid != hsb->s_uid)) ||
+	    ((attr->ia_valid & ATTR_GID) &&
+	     (attr->ia_gid != hsb->s_gid)) ||
+	    ((attr->ia_valid & ATTR_MODE) &&
+	     ((S_ISDIR(inode->i_mode) &&
+	       (attr->ia_mode != inode->i_mode)) ||
+	      (attr->ia_mode & ~HFS_VALID_MODE_BITS)))) {
+		return hsb->s_quiet ? 0 : error;
 	}
+
+	if (attr->ia_valid & ATTR_MODE) {
+		/* Only the 'w' bits can ever change and only all together. */
+		if (attr->ia_mode & S_IWUSR)
+			attr->ia_mode = inode->i_mode | S_IWUGO;
+		else
+			attr->ia_mode = inode->i_mode & ~S_IWUGO;
+		attr->ia_mode &= S_ISDIR(inode->i_mode) ? ~hsb->s_dir_umask: ~hsb->s_file_umask;
+	}
+	error = inode_setattr(inode, attr);
+	if (error)
+		return error;
+
+	return 0;
 }
+
+
+struct file_operations hfs_file_operations = {
+	.llseek		= generic_file_llseek,
+	.read		= generic_file_read,
+	.write		= generic_file_write,
+	.mmap		= generic_file_mmap,
+	.fsync		= file_fsync,
+	.open		= hfs_file_open,
+	.release	= hfs_file_release,
+};
+
+struct inode_operations hfs_file_inode_operations = {
+	.lookup		= hfs_file_lookup,
+	.truncate	= hfs_file_truncate,
+	.setattr	= hfs_inode_setattr,
+	.permission	= hfs_permission,
+};
--- diff/fs/hfs/mdb.c	2002-10-16 04:27:54.000000000 +0100
+++ source/fs/hfs/mdb.c	2004-02-23 13:56:46.000000000 +0000
@@ -1,28 +1,22 @@
 /*
- * linux/fs/hfs/mdb.c
+ *  linux/fs/hfs/mdb.c
  *
  * Copyright (C) 1995-1997  Paul H. Hargrove
+ * (C) 2003 Ardis Technologies <roman@ardistech.com>
  * This file may be distributed under the terms of the GNU General Public License.
  *
  * This file contains functions for reading/writing the MDB.
- *
- * "XXX" in a comment is a note to myself to consider changing something.
- *
- * In function preconditions the term "valid" applied to a pointer to
- * a structure means that the pointer is non-NULL and the structure it
- * points to has all fields initialized to consistent values.
- *
- * The code in this file initializes some structures which contain
- * pointers by calling memset(&foo, 0, sizeof(foo)).
- * This produces the desired behavior only due to the non-ANSI
- * assumption that the machine representation of NULL is all zeros.
  */
 
-#include "hfs.h"
+#include <linux/cdrom.h>
+#include <linux/genhd.h>
+
+#include "hfs_fs.h"
+#include "btree.h"
 
 /*================ File-local data types ================*/
 
-/* 
+/*
  * The HFS Master Directory Block (MDB).
  *
  * Also known as the Volume Information Block (VIB), this structure is
@@ -32,48 +26,35 @@
  *
  * modified for HFS Extended
  */
-struct raw_mdb {
-	hfs_word_t	drSigWord;	/* Signature word indicating fs type */
-	hfs_lword_t	drCrDate;	/* fs creation date/time */
-	hfs_lword_t	drLsMod;	/* fs modification date/time */
-	hfs_word_t	drAtrb;		/* fs attributes */
-	hfs_word_t	drNmFls;	/* number of files in root directory */
-	hfs_word_t	drVBMSt;	/* location (in 512-byte blocks)
-					   of the volume bitmap */
-	hfs_word_t	drAllocPtr;	/* location (in allocation blocks)
-					   to begin next allocation search */
-	hfs_word_t	drNmAlBlks;	/* number of allocation blocks */
-	hfs_lword_t	drAlBlkSiz;	/* bytes in an allocation block */
-	hfs_lword_t	drClpSiz;	/* clumpsize, the number of bytes to
-					   allocate when extending a file */
-	hfs_word_t	drAlBlSt;	/* location (in 512-byte blocks)
-					   of the first allocation block */
-	hfs_lword_t	drNxtCNID;	/* CNID to assign to the next
-					   file or directory created */
-	hfs_word_t	drFreeBks;	/* number of free allocation blocks */
-	hfs_byte_t	drVN[28];	/* the volume label */
-	hfs_lword_t	drVolBkUp;	/* fs backup date/time */
-	hfs_word_t	drVSeqNum;	/* backup sequence number */
-	hfs_lword_t	drWrCnt;	/* fs write count */
-	hfs_lword_t	drXTClpSiz;	/* clumpsize for the extents B-tree */
-	hfs_lword_t	drCTClpSiz;	/* clumpsize for the catalog B-tree */
-	hfs_word_t	drNmRtDirs;	/* number of directories in
-					   the root directory */
-	hfs_lword_t	drFilCnt;	/* number of files in the fs */
-	hfs_lword_t	drDirCnt;	/* number of directories in the fs */
-	hfs_byte_t	drFndrInfo[32];	/* data used by the Finder */
-	hfs_word_t	drEmbedSigWord;	/* embedded volume signature */
-	hfs_lword_t     drEmbedExtent;  /* starting block number (xdrStABN) 
-					   and number of allocation blocks 
-					   (xdrNumABlks) occupied by embedded
-					   volume */
-	hfs_lword_t	drXTFlSize;	/* bytes in the extents B-tree */
-	hfs_byte_t	drXTExtRec[12];	/* extents B-tree's first 3 extents */
-	hfs_lword_t	drCTFlSize;	/* bytes in the catalog B-tree */
-	hfs_byte_t	drCTExtRec[12];	/* catalog B-tree's first 3 extents */
-} __attribute__((packed));
 
-/*================ Global functions ================*/
+static int hfs_get_last_session(struct super_block *sb,
+				sector_t *start, sector_t *size)
+{
+	struct cdrom_multisession ms_info;
+	struct cdrom_tocentry te;
+	int res;
+
+	/* default values */
+	*start = 0;
+	*size = sb->s_bdev->bd_inode->i_size >> 9;
+
+	if (HFS_SB(sb)->session >= 0) {
+		te.cdte_track = HFS_SB(sb)->session;
+		te.cdte_format = CDROM_LBA;
+		res = ioctl_by_bdev(sb->s_bdev, CDROMREADTOCENTRY, (unsigned long)&te);
+		if (!res && (te.cdte_ctrl & CDROM_DATA_TRACK) == 4) {
+			*start = (sector_t)te.cdte_addr.lba << 2;
+			return 0;
+		}
+		printk(KERN_ERR "HFS: Invalid session number or type of track\n");
+		return -EINVAL;
+	}
+	ms_info.addr_format = CDROM_LBA;
+	res = ioctl_by_bdev(sb->s_bdev, CDROMMULTISESSION, (unsigned long)&ms_info);
+	if (!res && ms_info.xa_flag)
+		*start = (sector_t)ms_info.addr.lba << 2;
+	return 0;
+}
 
 /*
  * hfs_mdb_get()
@@ -81,135 +62,172 @@ struct raw_mdb {
  * Build the in-core MDB for a filesystem, including
  * the B-trees and the volume bitmap.
  */
-struct hfs_mdb *hfs_mdb_get(hfs_sysmdb sys_mdb, int readonly,
-			    hfs_s32 part_start)
+int hfs_mdb_get(struct super_block *sb)
 {
-	struct hfs_mdb *mdb;
-	hfs_buffer buf;
-	struct raw_mdb *raw;
-	unsigned int bs, block;
-	int lcv, limit;
-	hfs_buffer *bmbuf;
-
-	if (!HFS_NEW(mdb)) {
-		hfs_warn("hfs_fs: out of memory\n");
-		return NULL;
-	}
-
-	memset(mdb, 0, sizeof(*mdb));
-	mdb->magic = HFS_MDB_MAGIC;
-	mdb->sys_mdb = sys_mdb;
-	INIT_LIST_HEAD(&mdb->entry_dirty);
-	init_MUTEX(&mdb->bitmap_sem);
-
-	/* See if this is an HFS filesystem */
-	buf = hfs_buffer_get(sys_mdb, part_start + HFS_MDB_BLK, 1);
-	if (!hfs_buffer_ok(buf)) {
-		hfs_warn("hfs_fs: Unable to read superblock\n");
-		HFS_DELETE(mdb);
-		goto bail2;
-	}
-
-	raw = (struct raw_mdb *)hfs_buffer_data(buf);
-	if (hfs_get_ns(raw->drSigWord) != htons(HFS_SUPER_MAGIC)) {
-		hfs_buffer_put(buf);
-		HFS_DELETE(mdb);
-		goto bail2;
-	}
-	mdb->buf = buf;
-	
-	bs = hfs_get_hl(raw->drAlBlkSiz);
-	if (!bs || (bs & (HFS_SECTOR_SIZE-1))) {
-		hfs_warn("hfs_fs: bad allocation block size %d != 512\n", bs);
-		hfs_buffer_put(buf);
-		HFS_DELETE(mdb);
-		goto bail2;
-	}
-	mdb->alloc_blksz = bs >> HFS_SECTOR_SIZE_BITS;
+	struct buffer_head *bh;
+	struct hfs_mdb *mdb, *mdb2;
+	unsigned int block;
+	char *ptr;
+	int off2, len, size, sect;
+	sector_t part_start, part_size;
+	loff_t off;
+	u16 attrib;
+
+	/* set the device driver to 512-byte blocks */
+	size = sb_min_blocksize(sb, HFS_SECTOR_SIZE);
+	if (!size)
+		return -EINVAL;
+
+	if (hfs_get_last_session(sb, &part_start, &part_size))
+		return -EINVAL;
+	while (1) {
+		/* See if this is an HFS filesystem */
+		bh = sb_bread512(sb, part_start + HFS_MDB_BLK, mdb);
+		if (!bh)
+			goto out;
+
+		if (mdb->drSigWord == cpu_to_be16(HFS_SUPER_MAGIC))
+			break;
+		brelse(bh);
+
+		/* check for a partition block
+		 * (should do this only for cdrom/loop though)
+		 */
+		if (hfs_part_find(sb, &part_start, &part_size))
+			goto out;
+	}
+
+	HFS_SB(sb)->alloc_blksz = size = be32_to_cpu(mdb->drAlBlkSiz);
+	if (!size || (size & (HFS_SECTOR_SIZE - 1))) {
+		hfs_warn("hfs_fs: bad allocation block size %d\n", size);
+		goto out_bh;
+	}
+
+	size = min(HFS_SB(sb)->alloc_blksz, (u32)PAGE_SIZE);
+	/* size must be a multiple of 512 */
+	while (size & (size - 1))
+		size -= HFS_SECTOR_SIZE;
+	sect = be16_to_cpu(mdb->drAlBlSt) + part_start;
+	/* align block size to first sector */
+	while (sect & ((size - 1) >> HFS_SECTOR_SIZE_BITS))
+		size >>= 1;
+	/* align block size to weird alloc size */
+	while (HFS_SB(sb)->alloc_blksz & (size - 1))
+		size >>= 1;
+	brelse(bh);
+	if (!sb_set_blocksize(sb, size)) {
+		printk("hfs_fs: unable to set blocksize to %u\n", size);
+		goto out;
+	}
+
+	bh = sb_bread512(sb, part_start + HFS_MDB_BLK, mdb);
+	if (!bh)
+		goto out;
+	if (mdb->drSigWord != cpu_to_be16(HFS_SUPER_MAGIC))
+		goto out_bh;
+
+	HFS_SB(sb)->mdb_bh = bh;
+	HFS_SB(sb)->mdb = mdb;
 
 	/* These parameters are read from the MDB, and never written */
-	mdb->create_date = hfs_get_hl(raw->drCrDate);
-	mdb->fs_ablocks  = hfs_get_hs(raw->drNmAlBlks);
-	mdb->fs_start    = hfs_get_hs(raw->drAlBlSt) + part_start;
-	mdb->backup_date = hfs_get_hl(raw->drVolBkUp);
-	mdb->clumpablks  = (hfs_get_hl(raw->drClpSiz) / mdb->alloc_blksz)
-						 >> HFS_SECTOR_SIZE_BITS;
-	memcpy(mdb->vname, raw->drVN, sizeof(raw->drVN));
+	HFS_SB(sb)->part_start = part_start;
+	HFS_SB(sb)->fs_ablocks = be16_to_cpu(mdb->drNmAlBlks);
+	HFS_SB(sb)->fs_div = HFS_SB(sb)->alloc_blksz >> sb->s_blocksize_bits;
+	HFS_SB(sb)->clumpablks = be32_to_cpu(mdb->drClpSiz) /
+				 HFS_SB(sb)->alloc_blksz;
+	if (!HFS_SB(sb)->clumpablks)
+		HFS_SB(sb)->clumpablks = 1;
+	HFS_SB(sb)->fs_start = (be16_to_cpu(mdb->drAlBlSt) + part_start) >>
+			       (sb->s_blocksize_bits - HFS_SECTOR_SIZE_BITS);
 
 	/* These parameters are read from and written to the MDB */
-	mdb->modify_date  = hfs_get_nl(raw->drLsMod);
-	mdb->attrib       = hfs_get_ns(raw->drAtrb);
-	mdb->free_ablocks = hfs_get_hs(raw->drFreeBks);
-	mdb->next_id      = hfs_get_hl(raw->drNxtCNID);
-	mdb->write_count  = hfs_get_hl(raw->drWrCnt);
-	mdb->root_files   = hfs_get_hs(raw->drNmFls);
-	mdb->root_dirs    = hfs_get_hs(raw->drNmRtDirs);
-	mdb->file_count   = hfs_get_hl(raw->drFilCnt);
-	mdb->dir_count    = hfs_get_hl(raw->drDirCnt);
+	HFS_SB(sb)->free_ablocks = be16_to_cpu(mdb->drFreeBks);
+	HFS_SB(sb)->next_id = be32_to_cpu(mdb->drNxtCNID);
+	HFS_SB(sb)->root_files = be16_to_cpu(mdb->drNmFls);
+	HFS_SB(sb)->root_dirs = be16_to_cpu(mdb->drNmRtDirs);
+	HFS_SB(sb)->file_count = be32_to_cpu(mdb->drFilCnt);
+	HFS_SB(sb)->folder_count = be32_to_cpu(mdb->drDirCnt);
 
 	/* TRY to get the alternate (backup) MDB. */
-	lcv = mdb->fs_start + mdb->fs_ablocks * mdb->alloc_blksz;
-	limit = lcv + mdb->alloc_blksz;
-	for (; lcv < limit; ++lcv) {
-		buf = hfs_buffer_get(sys_mdb, lcv, 1);
-		if (hfs_buffer_ok(buf)) {
-			struct raw_mdb *tmp =
-				(struct raw_mdb *)hfs_buffer_data(buf);
-			
-			if (hfs_get_ns(tmp->drSigWord) ==
-			    htons(HFS_SUPER_MAGIC)) {
-				mdb->alt_buf = buf;
-				break;
-			}
-		}
-		hfs_buffer_put(buf);
+	sect = part_start + part_size - 2;
+	bh = sb_bread512(sb, sect, mdb2);
+	if (bh) {
+		if (mdb2->drSigWord == cpu_to_be16(HFS_SUPER_MAGIC)) {
+			HFS_SB(sb)->alt_mdb_bh = bh;
+			HFS_SB(sb)->alt_mdb = mdb2;
+		} else
+			brelse(bh);
 	}
-	
-	if (mdb->alt_buf == NULL) {
+
+	if (!HFS_SB(sb)->alt_mdb) {
 		hfs_warn("hfs_fs: unable to locate alternate MDB\n");
 		hfs_warn("hfs_fs: continuing without an alternate MDB\n");
 	}
-	
+
+	HFS_SB(sb)->bitmap = (u32 *)__get_free_pages(GFP_KERNEL, PAGE_SIZE < 8192 ? 1 : 0);
+	if (!HFS_SB(sb)->bitmap)
+		goto out;
+
 	/* read in the bitmap */
-	block = hfs_get_hs(raw->drVBMSt) + part_start;
-	bmbuf = mdb->bitmap;
-	lcv = (mdb->fs_ablocks + 4095) / 4096;
-	for ( ; lcv; --lcv, ++bmbuf, ++block) {
-		if (!hfs_buffer_ok(*bmbuf =
-				   hfs_buffer_get(sys_mdb, block, 1))) {
+	block = be16_to_cpu(mdb->drVBMSt) + part_start;
+	off = (loff_t)block << HFS_SECTOR_SIZE_BITS;
+	size = (HFS_SB(sb)->fs_ablocks + 8) / 8;
+	ptr = (u8 *)HFS_SB(sb)->bitmap;
+	while (size) {
+		bh = sb_bread(sb, off >> sb->s_blocksize_bits);
+		if (!bh) {
 			hfs_warn("hfs_fs: unable to read volume bitmap\n");
-			goto bail1;
+			goto out;
 		}
+		off2 = off & (sb->s_blocksize - 1);
+		len = min((int)sb->s_blocksize - off2, size);
+		memcpy(ptr, bh->b_data + off2, len);
+		brelse(bh);
+		ptr += len;
+		off += len;
+		size -= len;
+	}
+
+	HFS_SB(sb)->ext_tree = hfs_btree_open(sb, HFS_EXT_CNID, hfs_ext_keycmp);
+	if (!HFS_SB(sb)->ext_tree) {
+		hfs_warn("hfs_fs: unable to open extent tree\n");
+		goto out;
+	}
+	HFS_SB(sb)->cat_tree = hfs_btree_open(sb, HFS_CAT_CNID, hfs_cat_keycmp);
+	if (!HFS_SB(sb)->cat_tree) {
+		hfs_warn("hfs_fs: unable to open catalog tree\n");
+		goto out;
+	}
+
+	attrib = mdb->drAtrb;
+	if (!(attrib & cpu_to_be16(HFS_SB_ATTRIB_UNMNT))
+	    || (attrib & cpu_to_be16(HFS_SB_ATTRIB_INCNSTNT))) {
+		hfs_warn("HFS-fs warning: Filesystem was not cleanly unmounted, "
+			 "running fsck.hfs is recommended.  mounting read-only.\n");
+		sb->s_flags |= MS_RDONLY;
+	}
+	if ((attrib & cpu_to_be16(HFS_SB_ATTRIB_SLOCK))) {
+		hfs_warn("HFS-fs: Filesystem is marked locked, mounting read-only.\n");
+		sb->s_flags |= MS_RDONLY;
 	}
-
-	if (!(mdb->ext_tree = hfs_btree_init(mdb, htonl(HFS_EXT_CNID),
-					     raw->drXTExtRec,
-					     hfs_get_hl(raw->drXTFlSize),
-					     hfs_get_hl(raw->drXTClpSiz))) ||
-	    !(mdb->cat_tree = hfs_btree_init(mdb, htonl(HFS_CAT_CNID),
-					     raw->drCTExtRec,
-					     hfs_get_hl(raw->drCTFlSize),
-					     hfs_get_hl(raw->drCTClpSiz)))) {
-		hfs_warn("hfs_fs: unable to initialize data structures\n");
-		goto bail1;
-	}
-
-	if (!(mdb->attrib & htons(HFS_SB_ATTRIB_CLEAN))) {
-		hfs_warn("hfs_fs: WARNING: mounting unclean filesystem.\n");
-	} else if (!readonly) {
+	if (!(sb->s_flags & MS_RDONLY)) {
 		/* Mark the volume uncleanly unmounted in case we crash */
-		hfs_put_ns(mdb->attrib & htons(~HFS_SB_ATTRIB_CLEAN),
-			   raw->drAtrb);
-		hfs_buffer_dirty(mdb->buf);
-		hfs_buffer_sync(mdb->buf);
-	}
-
-	return mdb;
-
-bail1:
-	hfs_mdb_put(mdb, readonly);
-bail2:
-	return NULL;
+		mdb->drAtrb = attrib & cpu_to_be16(~HFS_SB_ATTRIB_UNMNT);
+		mdb->drAtrb = attrib | cpu_to_be16(HFS_SB_ATTRIB_INCNSTNT);
+		mdb->drWrCnt = cpu_to_be32(be32_to_cpu(mdb->drWrCnt) + 1);
+		mdb->drLsMod = hfs_mtime();
+
+		mark_buffer_dirty(HFS_SB(sb)->mdb_bh);
+		hfs_buffer_sync(HFS_SB(sb)->mdb_bh);
+	}
+
+	return 0;
+
+out_bh:
+	brelse(bh);
+out:
+	hfs_mdb_put(sb);
+	return -EIO;
 }
 
 /*
@@ -236,84 +254,90 @@ bail2:
  *   If 'backup' is non-zero then the alternate MDB is also written
  *   and the function doesn't return until it is actually on disk.
  */
-void hfs_mdb_commit(struct hfs_mdb *mdb, int backup)
+void hfs_mdb_commit(struct super_block *sb)
 {
-	struct raw_mdb *raw = (struct raw_mdb *)hfs_buffer_data(mdb->buf);
-
-	/* Commit catalog entries to buffers */
-	hfs_cat_commit(mdb);
+	struct hfs_mdb *mdb = HFS_SB(sb)->mdb;
 
-	/* Commit B-tree data to buffers */
-	hfs_btree_commit(mdb->cat_tree, raw->drCTExtRec, raw->drCTFlSize);
-	hfs_btree_commit(mdb->ext_tree, raw->drXTExtRec, raw->drXTFlSize);
-
-	/* Update write_count and modify_date */
-	++mdb->write_count;
-	mdb->modify_date = hfs_time();
-
-	/* These parameters may have been modified, so write them back */
-	hfs_put_nl(mdb->modify_date,   raw->drLsMod);
-	hfs_put_hs(mdb->free_ablocks,  raw->drFreeBks);
-	hfs_put_hl(mdb->next_id,       raw->drNxtCNID);
-	hfs_put_hl(mdb->write_count,   raw->drWrCnt);
-	hfs_put_hs(mdb->root_files,    raw->drNmFls);
-	hfs_put_hs(mdb->root_dirs,     raw->drNmRtDirs);
-	hfs_put_hl(mdb->file_count,    raw->drFilCnt);
-	hfs_put_hl(mdb->dir_count,     raw->drDirCnt);
-
-	/* write MDB to disk */
-	hfs_buffer_dirty(mdb->buf);
-
-       	/* write the backup MDB, not returning until it is written. 
-         * we only do this when either the catalog or extents overflow
-         * files grow. */
-        if (backup && hfs_buffer_ok(mdb->alt_buf)) {
-		struct raw_mdb *tmp = (struct raw_mdb *)
-			hfs_buffer_data(mdb->alt_buf);
-		
-		if ((hfs_get_hl(tmp->drCTFlSize) < 
-		     hfs_get_hl(raw->drCTFlSize)) ||
-		    (hfs_get_hl(tmp->drXTFlSize) <
-		     hfs_get_hl(raw->drXTFlSize))) {
-			memcpy(hfs_buffer_data(mdb->alt_buf), 
-			       hfs_buffer_data(mdb->buf), HFS_SECTOR_SIZE); 
-			hfs_buffer_dirty(mdb->alt_buf);
-			hfs_buffer_sync(mdb->alt_buf);
+	if (test_and_clear_bit(HFS_FLG_MDB_DIRTY, &HFS_SB(sb)->flags)) {
+		/* These parameters may have been modified, so write them back */
+		mdb->drLsMod = hfs_mtime();
+		mdb->drFreeBks = cpu_to_be16(HFS_SB(sb)->free_ablocks);
+		mdb->drNxtCNID = cpu_to_be32(HFS_SB(sb)->next_id);
+		mdb->drNmFls = cpu_to_be16(HFS_SB(sb)->root_files);
+		mdb->drNmRtDirs = cpu_to_be16(HFS_SB(sb)->root_dirs);
+		mdb->drFilCnt = cpu_to_be32(HFS_SB(sb)->file_count);
+		mdb->drDirCnt = cpu_to_be32(HFS_SB(sb)->folder_count);
+
+		/* write MDB to disk */
+		mark_buffer_dirty(HFS_SB(sb)->mdb_bh);
+	}
+
+	/* write the backup MDB, not returning until it is written.
+	 * we only do this when either the catalog or extents overflow
+	 * files grow. */
+	if (test_and_clear_bit(HFS_FLG_ALT_MDB_DIRTY, &HFS_SB(sb)->flags) &&
+	    HFS_SB(sb)->alt_mdb) {
+		hfs_inode_write_fork(HFS_SB(sb)->ext_tree->inode, mdb->drXTExtRec,
+				     &mdb->drXTFlSize, NULL);
+		hfs_inode_write_fork(HFS_SB(sb)->cat_tree->inode, mdb->drCTExtRec,
+				     &mdb->drCTFlSize, NULL);
+		memcpy(HFS_SB(sb)->alt_mdb, HFS_SB(sb)->mdb, HFS_SECTOR_SIZE);
+		HFS_SB(sb)->alt_mdb->drAtrb |= cpu_to_be16(HFS_SB_ATTRIB_UNMNT);
+		HFS_SB(sb)->alt_mdb->drAtrb &= cpu_to_be16(~HFS_SB_ATTRIB_INCNSTNT);
+		mark_buffer_dirty(HFS_SB(sb)->alt_mdb_bh);
+		hfs_buffer_sync(HFS_SB(sb)->alt_mdb_bh);
+	}
+
+	if (test_and_clear_bit(HFS_FLG_BITMAP_DIRTY, &HFS_SB(sb)->flags)) {
+		struct buffer_head *bh;
+		sector_t block;
+		char *ptr;
+		int off, size, len;
+
+		block = be16_to_cpu(HFS_SB(sb)->mdb->drVBMSt) + HFS_SB(sb)->part_start;
+		off = (block << HFS_SECTOR_SIZE_BITS) & (sb->s_blocksize - 1);
+		block >>= sb->s_blocksize_bits - HFS_SECTOR_SIZE_BITS;
+		size = (HFS_SB(sb)->fs_ablocks + 7) / 8;
+		ptr = (u8 *)HFS_SB(sb)->bitmap;
+		while (size) {
+			bh = sb_bread(sb, block);
+			if (!bh) {
+				hfs_warn("hfs_fs: unable to read volume bitmap\n");
+				break;
+			}
+			len = min((int)sb->s_blocksize - off, size);
+			memcpy(bh->b_data + off, ptr, len);
+			mark_buffer_dirty(bh);
+			brelse(bh);
+			block++;
+			off = 0;
+			ptr += len;
+			size -= len;
 		}
-        }
+	}
+}
+
+void hfs_mdb_close(struct super_block *sb)
+{
+	/* update volume attributes */
+	if (sb->s_flags & MS_RDONLY)
+		return;
+	HFS_SB(sb)->mdb->drAtrb |= cpu_to_be16(HFS_SB_ATTRIB_UNMNT);
+	HFS_SB(sb)->mdb->drAtrb &= cpu_to_be16(~HFS_SB_ATTRIB_INCNSTNT);
+	mark_buffer_dirty(HFS_SB(sb)->mdb_bh);
 }
 
 /*
  * hfs_mdb_put()
  *
  * Release the resources associated with the in-core MDB.  */
-void hfs_mdb_put(struct hfs_mdb *mdb, int readonly) {
-	int lcv;
-
-	/* invalidate cached catalog entries */
-	hfs_cat_invalidate(mdb);
-
+void hfs_mdb_put(struct super_block *sb)
+{
 	/* free the B-trees */
-	hfs_btree_free(mdb->ext_tree);
-	hfs_btree_free(mdb->cat_tree);
-
-	/* free the volume bitmap */
-	for (lcv = 0; lcv < HFS_BM_MAXBLOCKS; ++lcv) {
-		hfs_buffer_put(mdb->bitmap[lcv]);
-	}
-
-	/* update volume attributes */
-	if (!readonly) {
-		struct raw_mdb *raw = 
-				(struct raw_mdb *)hfs_buffer_data(mdb->buf);
-		hfs_put_ns(mdb->attrib, raw->drAtrb);
-		hfs_buffer_dirty(mdb->buf);
-	}
+	hfs_btree_close(HFS_SB(sb)->ext_tree);
+	hfs_btree_close(HFS_SB(sb)->cat_tree);
 
 	/* free the buffers holding the primary and alternate MDBs */
-	hfs_buffer_put(mdb->buf);
-	hfs_buffer_put(mdb->alt_buf);
-
-	/* free the MDB */
-	HFS_DELETE(mdb);
+	brelse(HFS_SB(sb)->mdb_bh);
+	brelse(HFS_SB(sb)->alt_mdb_bh);
 }
--- diff/fs/hfs/part_tbl.c	2002-10-16 04:28:24.000000000 +0100
+++ source/fs/hfs/part_tbl.c	2004-02-23 13:56:46.000000000 +0000
@@ -1,40 +1,17 @@
 /*
- * linux/fs/hfs/part_tbl.c
+ *  linux/fs/hfs/part_tbl.c
  *
  * Copyright (C) 1996-1997  Paul H. Hargrove
+ * (C) 2003 Ardis Technologies <roman@ardistech.com>
  * This file may be distributed under the terms of the GNU General Public License.
  *
  * Original code to handle the new style Mac partition table based on
  * a patch contributed by Holger Schemel (aeglos@valinor.owl.de).
- *
- * "XXX" in a comment is a note to myself to consider changing something.
- *
- * In function preconditions the term "valid" applied to a pointer to
- * a structure means that the pointer is non-NULL and the structure it
- * points to has all fields initialized to consistent values.
- *
- * The code in this file initializes some structures which contain
- * pointers by calling memset(&foo, 0, sizeof(foo)).
- * This produces the desired behavior only due to the non-ANSI
- * assumption that the machine representation of NULL is all zeros.
  */
 
-#include "hfs.h"
-
-/*================ File-local data types ================*/
+#include "hfs_fs.h"
 
 /*
- * The Macintosh Driver Descriptor Block
- *
- * On partitioned Macintosh media this is block 0.
- * We really only need the "magic number" to check for partitioned media.
- */
-struct hfs_drvr_desc {
-	hfs_word_t	ddSig;		/* The signature word */
-	/* a bunch more stuff we don't need */
-};
-
-/* 
  * The new style Mac partition map
  *
  * For each partition on the media there is a physical block (512-byte
@@ -42,28 +19,21 @@ struct hfs_drvr_desc {
  * contiguous starting at block 1.
  */
 struct new_pmap {
-	hfs_word_t	pmSig;		/* Signature bytes to verify
-					   that this is a partition
-					   map block */
-	hfs_word_t	reSigPad;	/* padding */
-	hfs_lword_t	pmMapBlkCnt;	/* (At least in block 1) this
-					   is the number of partition
-					   map blocks */
-	hfs_lword_t	pmPyPartStart;	/* The physical block number
-					   of the first block in this
-					   partition */
-	hfs_lword_t	pmPartBlkCnt;	/* The number of physical
-					   blocks in this partition */
-	hfs_byte_t	pmPartName[32];	/* (null terminated?) string
-					   giving the name of this
-					   partition */
-	hfs_byte_t	pmPartType[32];	/* (null terminated?) string
-					   giving the type of this
-					   partition */
+	u16	pmSig;		/* signature */
+	u16	reSigPad;	/* padding */
+	u32	pmMapBlkCnt;	/* partition blocks count */
+	u32	pmPyPartStart;	/* physical block start of partition */
+	u32	pmPartBlkCnt;	/* physical block count of partition */
+	u8	pmPartName[32];	/* (null terminated?) string
+				   giving the name of this
+				   partition */
+	u8	pmPartType[32];	/* (null terminated?) string
+				   giving the type of this
+				   partition */
 	/* a bunch more stuff we don't need */
-};
+} __packed;
 
-/* 
+/*
  * The old style Mac partition map
  *
  * The partition map consists for a 2-byte signature followed by an
@@ -71,95 +41,13 @@ struct new_pmap {
  * one of these.
  */
 struct old_pmap {
-	hfs_word_t		pdSig;	/* Signature bytes */
+	u16		pdSig;	/* Signature bytes */
 	struct 	old_pmap_entry {
-		hfs_lword_t	pdStart;
-		hfs_lword_t	pdSize;
-		hfs_lword_t	pdFSID;
+		u32	pdStart;
+		u32	pdSize;
+		u32	pdFSID;
 	}	pdEntry[42];
-} __attribute__((packed));
-
-/*================ File-local functions ================*/
-
-/*
- * parse_new_part_table()
- *
- * Parse a new style partition map looking for the
- * start and length of the 'part'th HFS partition.
- */
-static int parse_new_part_table(hfs_sysmdb sys_mdb, hfs_buffer buf,
-				int part, hfs_s32 *size, hfs_s32 *start)
-{
-	struct new_pmap *pm = (struct new_pmap *)hfs_buffer_data(buf);
-	hfs_u32 pmap_entries = hfs_get_hl(pm->pmMapBlkCnt);
-	int hfs_part = 0;
-	int entry;
-
-	for (entry = 0; (entry < pmap_entries) && !(*start); ++entry) {
-		if (entry) {
-			/* read the next partition map entry */
-			buf = hfs_buffer_get(sys_mdb, HFS_PMAP_BLK + entry, 1);
-			if (!hfs_buffer_ok(buf)) {
-				hfs_warn("hfs_fs: unable to "
-				         "read partition map.\n");
-				goto bail;
-			}
-			pm = (struct new_pmap *)hfs_buffer_data(buf);
-			if (hfs_get_ns(pm->pmSig) !=
-						htons(HFS_NEW_PMAP_MAGIC)) {
-				hfs_warn("hfs_fs: invalid "
-				         "entry in partition map\n");
-				hfs_buffer_put(buf);
-				goto bail;
-			}
-		}
-
-		/* look for an HFS partition */
-		if (!memcmp(pm->pmPartType,"Apple_HFS",9) && 
-		    ((hfs_part++) == part)) {
-			/* Found it! */
-			*start = hfs_get_hl(pm->pmPyPartStart);
-			*size = hfs_get_hl(pm->pmPartBlkCnt);
-		}
-
-		hfs_buffer_put(buf);
-	}
-
-	return 0;
-
-bail:
-	return 1;
-}
-
-/*
- * parse_old_part_table()
- *
- * Parse a old style partition map looking for the
- * start and length of the 'part'th HFS partition.
- */
-static int parse_old_part_table(hfs_sysmdb sys_mdb, hfs_buffer buf,
-				int part, hfs_s32 *size, hfs_s32 *start)
-{
-	struct old_pmap *pm = (struct old_pmap *)hfs_buffer_data(buf);
-	struct old_pmap_entry *p = &pm->pdEntry[0];
-	int hfs_part = 0;
-
-	while ((p->pdStart || p->pdSize || p->pdFSID) && !(*start)) {
-		/* look for an HFS partition */
-		if ((hfs_get_nl(p->pdFSID) == htonl(0x54465331)/*"TFS1"*/) &&
-		    ((hfs_part++) == part)) {
-			/* Found it! */
-			*start = hfs_get_hl(p->pdStart);
-			*size = hfs_get_hl(p->pdSize);
-		}
-		++p;
-	}
-	hfs_buffer_put(buf);
-
-	return 0;
-}
-
-/*================ Global functions ================*/
+} __packed;
 
 /*
  * hfs_part_find()
@@ -167,78 +55,63 @@ static int parse_old_part_table(hfs_sysm
  * Parse the partition map looking for the
  * start and length of the 'part'th HFS partition.
  */
-int hfs_part_find(hfs_sysmdb sys_mdb, int part, int silent,
-		  hfs_s32 *size, hfs_s32 *start)
+int hfs_part_find(struct super_block *sb,
+		  sector_t *part_start, sector_t *part_size)
 {
-	hfs_buffer buf;
-	hfs_u16 sig;
-	int dd_found = 0;
-	int retval = 1;
-
-	/* Read block 0 to see if this media is partitioned */
-	buf = hfs_buffer_get(sys_mdb, HFS_DD_BLK, 1);
-	if (!hfs_buffer_ok(buf)) {
-		hfs_warn("hfs_fs: Unable to read block 0.\n");
-		goto done;
-	}
-	sig = hfs_get_ns(((struct hfs_drvr_desc *)hfs_buffer_data(buf))->ddSig);
-	hfs_buffer_put(buf);
-
-        if (sig == htons(HFS_DRVR_DESC_MAGIC)) {
-		/* We are definitely on partitioned media. */
-		dd_found = 1;
-	}
-
-	buf = hfs_buffer_get(sys_mdb, HFS_PMAP_BLK, 1);
-	if (!hfs_buffer_ok(buf)) {
-		hfs_warn("hfs_fs: Unable to read block 1.\n");
-		goto done;
-	}
-
-	*size = *start = 0;
-
-	switch (hfs_get_ns(hfs_buffer_data(buf))) {
-	case __constant_htons(HFS_OLD_PMAP_MAGIC):
-		retval = parse_old_part_table(sys_mdb, buf, part, size, start);
-		break;
-
-	case __constant_htons(HFS_NEW_PMAP_MAGIC):
-		retval = parse_new_part_table(sys_mdb, buf, part, size, start);
-		break;
-
-	default:
-		if (dd_found) {
-			/* The media claimed to have a partition map */
-			if (!silent) {
-				hfs_warn("hfs_fs: This disk has an "
-					 "unrecognized partition map type.\n");
+	struct buffer_head *bh;
+	u16 *data;
+	int i, size, res;
+
+	res = -ENOENT;
+	bh = sb_bread512(sb, *part_start + HFS_PMAP_BLK, data);
+	if (!bh)
+		return -EIO;
+
+	switch (be16_to_cpu(*data)) {
+	case HFS_OLD_PMAP_MAGIC:
+	  {
+		struct old_pmap *pm;
+		struct old_pmap_entry *p;
+
+		pm = (struct old_pmap *)bh->b_data;
+		p = pm->pdEntry;
+		size = 42;
+		for (i = 0; i < size; p++, i++) {
+			if (p->pdStart && p->pdSize &&
+			    p->pdFSID == cpu_to_be32(0x54465331)/*"TFS1"*/ &&
+			    (HFS_SB(sb)->part < 0 || HFS_SB(sb)->part == i)) {
+				*part_start += be32_to_cpu(p->pdStart);
+				*part_size = be32_to_cpu(p->pdSize);
+				res = 0;
 			}
-		} else {
-			/* Conclude that the media is not partitioned */
-			retval = 0;
 		}
-		goto done;
-	}
-
-	if (!retval) {
-		if (*start == 0) {
-			if (part) {
-				hfs_warn("hfs_fs: unable to locate "
-				         "HFS partition number %d.\n", part);
-			} else {
-				hfs_warn("hfs_fs: unable to locate any "
-					 "HFS partitions.\n");
+		break;
+	  }
+	case HFS_NEW_PMAP_MAGIC:
+	  {
+		struct new_pmap *pm;
+
+		pm = (struct new_pmap *)bh->b_data;
+		size = be32_to_cpu(pm->pmMapBlkCnt);
+		for (i = 0; i < size;) {
+			if (!memcmp(pm->pmPartType,"Apple_HFS", 9) &&
+			    (HFS_SB(sb)->part < 0 || HFS_SB(sb)->part == i)) {
+				*part_start += be32_to_cpu(pm->pmPyPartStart);
+				*part_size = be32_to_cpu(pm->pmPartBlkCnt);
+				res = 0;
+				break;
 			}
-			retval = 1;
-		} else if (*size < 0) {
-			hfs_warn("hfs_fs: Partition size > 1 Terabyte.\n");
-			retval = 1;
-		} else if (*start < 0) {
-			hfs_warn("hfs_fs: Partition begins beyond 1 "
-				 "Terabyte.\n");
-			retval = 1;
+			brelse(bh);
+			bh = sb_bread512(sb, *part_start + HFS_PMAP_BLK + ++i, pm);
+			if (!bh)
+				return -EIO;
+			if (pm->pmSig != cpu_to_be16(HFS_NEW_PMAP_MAGIC))
+				break;
 		}
+		break;
+	  }
 	}
-done:
-	return retval;
+	brelse(bh);
+
+	return res;
 }
--- diff/fs/hfs/string.c	2002-10-16 04:27:51.000000000 +0100
+++ source/fs/hfs/string.c	2004-02-23 13:56:46.000000000 +0000
@@ -1,7 +1,8 @@
 /*
- * linux/fs/hfs/string.c
+ *  linux/fs/hfs/string.c
  *
  * Copyright (C) 1995-1997  Paul H. Hargrove
+ * (C) 2003 Ardis Technologies <roman@ardistech.com>
  * This file may be distributed under the terms of the GNU General Public License.
  *
  * This file contains the string comparison function for the
@@ -10,15 +11,10 @@
  * The code in this file is derived from code which is copyright
  * 1986, 1989, 1990 by Abacus Research and Development, Inc. (ARDI)
  * It is used here by the permission of ARDI's president Cliff Matthews.
- *
- * If you discover bugs in this code please notify both the author of the
- * Linux HFS file system: hargrove@sccm.stanford.edu (Paul H. Hargrove)
- * and the author of ARDI's HFS code: ctm@ardi.com (Clifford T. Matthews)
- *
- * "XXX" in a comment is a note to myself to consider changing something.
  */
 
-#include "hfs.h"
+#include "hfs_fs.h"
+#include <linux/dcache.h>
 
 /*================ File-local variables ================*/
 
@@ -32,48 +28,22 @@
  * special case for those two characters.
  */
 static unsigned char caseorder[256] = {
-0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,
-0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,
-0x20,0x22,0x23,0x28,0x29,0x2A,0x2B,0x2C,0x2F,0x30,0x31,0x32,0x33,0x34,0x35,0x36,
-0x37,0x38,0x39,0x3A,0x3B,0x3C,0x3D,0x3E,0x3F,0x40,0x41,0x42,0x43,0x44,0x45,0x46,
-0x47,0x48,0x57,0x59,0x5D,0x5F,0x66,0x68,0x6A,0x6C,0x72,0x74,0x76,0x78,0x7A,0x7E,
-0x8C,0x8E,0x90,0x92,0x95,0x97,0x9E,0xA0,0xA2,0xA4,0xA7,0xA9,0xAA,0xAB,0xAC,0xAD,
-0x4E,0x48,0x57,0x59,0x5D,0x5F,0x66,0x68,0x6A,0x6C,0x72,0x74,0x76,0x78,0x7A,0x7E,
-0x8C,0x8E,0x90,0x92,0x95,0x97,0x9E,0xA0,0xA2,0xA4,0xA7,0xAF,0xB0,0xB1,0xB2,0xB3,
-0x4A,0x4C,0x5A,0x60,0x7B,0x7F,0x98,0x4F,0x49,0x51,0x4A,0x4B,0x4C,0x5A,0x60,0x63,
-0x64,0x65,0x6E,0x6F,0x70,0x71,0x7B,0x84,0x85,0x86,0x7F,0x80,0x9A,0x9B,0x9C,0x98,
-0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0x94,0xBB,0xBC,0xBD,0xBE,0xBF,0xC0,0x4D,0x81,
-0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0x55,0x8A,0xCC,0x4D,0x81,
-0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0x26,0x27,0xD4,0x20,0x49,0x4B,0x80,0x82,0x82,
-0xD5,0xD6,0x24,0x25,0x2D,0x2E,0xD7,0xD8,0xA6,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF,
-0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF,
-0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF
-};
-
-/*
- * unsigned char casefold[]
- *
- * Defines the mapping to lowercase characters on the Macintosh
- *
- * "Inverse" of the 'casefold' from ARDI's code.
- */
-static unsigned char casefold[256] = {
-0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,
-0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,
-0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,
-0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x3A,0x3B,0x3C,0x3D,0x3E,0x3F,
-0x40,0x61,0x62,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6A,0x6B,0x6C,0x6D,0x6E,0x6F,
-0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7A,0x5B,0x5C,0x5D,0x5E,0x5F,
-0x41,0x61,0x62,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6A,0x6B,0x6C,0x6D,0x6E,0x6F,
-0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7A,0x7B,0x7C,0x7D,0x7E,0x7F,
-0x8A,0x8C,0x8D,0x8E,0x96,0x9A,0x9F,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,
-0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F,
-0xA0,0xA1,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xBE,0xBF,
-0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF,
-0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0x88,0x8B,0x9B,0xCF,0xCF,
-0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF,
-0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF,
-0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF
+	0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,
+	0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,
+	0x20,0x22,0x23,0x28,0x29,0x2A,0x2B,0x2C,0x2F,0x30,0x31,0x32,0x33,0x34,0x35,0x36,
+	0x37,0x38,0x39,0x3A,0x3B,0x3C,0x3D,0x3E,0x3F,0x40,0x41,0x42,0x43,0x44,0x45,0x46,
+	0x47,0x48,0x57,0x59,0x5D,0x5F,0x66,0x68,0x6A,0x6C,0x72,0x74,0x76,0x78,0x7A,0x7E,
+	0x8C,0x8E,0x90,0x92,0x95,0x97,0x9E,0xA0,0xA2,0xA4,0xA7,0xA9,0xAA,0xAB,0xAC,0xAD,
+	0x4E,0x48,0x57,0x59,0x5D,0x5F,0x66,0x68,0x6A,0x6C,0x72,0x74,0x76,0x78,0x7A,0x7E,
+	0x8C,0x8E,0x90,0x92,0x95,0x97,0x9E,0xA0,0xA2,0xA4,0xA7,0xAF,0xB0,0xB1,0xB2,0xB3,
+	0x4A,0x4C,0x5A,0x60,0x7B,0x7F,0x98,0x4F,0x49,0x51,0x4A,0x4B,0x4C,0x5A,0x60,0x63,
+	0x64,0x65,0x6E,0x6F,0x70,0x71,0x7B,0x84,0x85,0x86,0x7F,0x80,0x9A,0x9B,0x9C,0x98,
+	0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0x94,0xBB,0xBC,0xBD,0xBE,0xBF,0xC0,0x4D,0x81,
+	0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0x55,0x8A,0xCC,0x4D,0x81,
+	0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0x26,0x27,0xD4,0x20,0x49,0x4B,0x80,0x82,0x82,
+	0xD5,0xD6,0x24,0x25,0x2D,0x2E,0xD7,0xD8,0xA6,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF,
+	0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF,
+	0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF
 };
 
 /*================ Global functions ================*/
@@ -81,14 +51,19 @@ static unsigned char casefold[256] = {
 /*
  * Hash a string to an integer in a case-independent way
  */
-unsigned int hfs_strhash(const unsigned char *name, unsigned int len)
+int hfs_hash_dentry(struct dentry *dentry, struct qstr *this)
 {
-	unsigned long hash = init_name_hash();
+	const unsigned char *name = this->name;
+	unsigned int hash, len = this->len;
 
-	while (len--)
-	        hash = partial_name_hash(caseorder[*name++],
-					 hash);
-	return end_name_hash(hash);
+	if (len > HFS_NAMELEN)
+		len = HFS_NAMELEN;
+
+	hash = init_name_hash();
+	for (; len; len--)
+		hash = partial_name_hash(caseorder[*name++], hash);
+	this->hash = end_name_hash(hash);
+	return 0;
 }
 
 /*
@@ -106,39 +81,35 @@ int hfs_strcmp(const unsigned char *s1, 
 	len = (len1 > len2) ? len2 : len1;
 
 	while (len--) {
-		if ((tmp = (int)caseorder[*(s1++)] -
-		     (int)caseorder[*(s2++)])) {
+		tmp = (int)caseorder[*(s1++)] - (int)caseorder[*(s2++)];
+		if (tmp)
 			return tmp;
-		}
 	}
 	return len1 - len2;
 }
 
 /*
  * Test for equality of two strings in the HFS filename character ordering.
+ * return 1 on failure and 0 on success
  */
-int hfs_streq(const unsigned char *s1, unsigned int len1,
-	      const unsigned char *s2, unsigned int len2)
+int hfs_compare_dentry(struct dentry *dentry, struct qstr *s1, struct qstr *s2)
 {
-	if (len1 != len2) {
-		return 0;
-	}
+	const unsigned char *n1, *n2;
+	int len;
 
-	while (len1--) {
-		if (caseorder[*(s1++)] != caseorder[*(s2++)]) {
-			return 0;
-		}
-	}
-	return 1;
-}
+	len = s1->len;
+	if (len >= HFS_NAMELEN) {
+		if (s2->len < HFS_NAMELEN)
+			return 1;
+		len = HFS_NAMELEN;
+	} else if (len != s2->len)
+		return 1;
 
-/*
- * Convert a string to the Macintosh version of lower case.
- */
-void hfs_tolower(unsigned char *p, int len)
-{
+	n1 = s1->name;
+	n2 = s2->name;
 	while (len--) {
-		*p = casefold[*p];
-		++p;
+		if (caseorder[*n1++] != caseorder[*n2++])
+			return 1;
 	}
+	return 0;
 }
--- diff/fs/hfs/super.c	2003-10-09 09:47:34.000000000 +0100
+++ source/fs/hfs/super.c	2004-02-23 13:56:46.000000000 +0000
@@ -1,7 +1,8 @@
 /*
- * linux/fs/hfs/super.c
+ *  linux/fs/hfs/super.c
  *
  * Copyright (C) 1995-1997  Paul H. Hargrove
+ * (C) 2003 Ardis Technologies <roman@ardistech.com>
  * This file may be distributed under the terms of the GNU General Public License.
  *
  * This file contains hfs_read_super(), some of the super_ops and
@@ -9,123 +10,22 @@
  * inode.c since they deal with inodes.
  *
  * Based on the minix file system code, (C) 1991, 1992 by Linus Torvalds
- *
- * "XXX" in a comment is a note to myself to consider changing something.
- *
- * In function preconditions the term "valid" applied to a pointer to
- * a structure means that the pointer is non-NULL and the structure it
- * points to has all fields initialized to consistent values.
- *
- * The code in this file initializes some structures which contain
- * pointers by calling memset(&foo, 0, sizeof(foo)).
- * This produces the desired behavior only due to the non-ANSI
- * assumption that the machine representation of NULL is all zeros.
  */
 
-#include "hfs.h"
-#include <linux/hfs_fs_sb.h>
-#include <linux/hfs_fs_i.h>
-#include <linux/hfs_fs.h>
-
-#include <linux/config.h> /* for CONFIG_MAC_PARTITION */
-#include <linux/blkdev.h>
+#include <linux/config.h>
 #include <linux/module.h>
+#include <linux/blkdev.h>
 #include <linux/init.h>
-#include <linux/parser.h>
-#include <linux/smp_lock.h>
 #include <linux/vfs.h>
 
-MODULE_LICENSE("GPL");
-
-/*================ Forward declarations ================*/
-
-static void hfs_read_inode(struct inode *);
-static void hfs_put_super(struct super_block *);
-static int hfs_statfs(struct super_block *, struct kstatfs *);
-static void hfs_write_super(struct super_block *);
-
-static kmem_cache_t * hfs_inode_cachep;
-
-static struct inode *hfs_alloc_inode(struct super_block *sb)
-{
-	struct hfs_inode_info *ei;
-	ei = (struct hfs_inode_info *)kmem_cache_alloc(hfs_inode_cachep, SLAB_KERNEL);
-	if (!ei)
-		return NULL;
-	return &ei->vfs_inode;
-}
-
-static void hfs_destroy_inode(struct inode *inode)
-{
-	kmem_cache_free(hfs_inode_cachep, HFS_I(inode));
-}
-
-static void init_once(void * foo, kmem_cache_t * cachep, unsigned long flags)
-{
-	struct hfs_inode_info *ei = (struct hfs_inode_info *) foo;
-
-	if ((flags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) ==
-	    SLAB_CTOR_CONSTRUCTOR)
-		inode_init_once(&ei->vfs_inode);
-}
- 
-static int init_inodecache(void)
-{
-	hfs_inode_cachep = kmem_cache_create("hfs_inode_cache",
-					     sizeof(struct hfs_inode_info),
-					     0, SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT,
-					     init_once, NULL);
-	if (hfs_inode_cachep == NULL)
-		return -ENOMEM;
-	return 0;
-}
-
-static void destroy_inodecache(void)
-{
-	if (kmem_cache_destroy(hfs_inode_cachep))
-		printk(KERN_INFO "hfs_inode_cache: not all structures were freed\n");
-}
+#include "hfs_fs.h"
+#include "btree.h"
 
-/*================ Global variables ================*/
-
-static struct super_operations hfs_super_operations = { 
-	.alloc_inode	= hfs_alloc_inode,
-	.destroy_inode	= hfs_destroy_inode,
-	.read_inode	= hfs_read_inode,
-	.put_inode	= hfs_put_inode,
-	.put_super	= hfs_put_super,
-	.write_super	= hfs_write_super,
-	.statfs		= hfs_statfs,
-};
+const char hfs_version[]="0.96";
 
-/*================ File-local variables ================*/
+static kmem_cache_t *hfs_inode_cachep;
 
-static struct super_block *hfs_get_sb(struct file_system_type *fs_type,
-	int flags, const char *dev_name, void *data)
-{
-	return get_sb_bdev(fs_type, flags, dev_name, data, hfs_fill_super);
-}
-
-static struct file_system_type hfs_fs = {
-	.owner		= THIS_MODULE,
-	.name		= "hfs",
-	.get_sb		= hfs_get_sb,
-	.kill_sb	= kill_block_super,
-	.fs_flags	= FS_REQUIRES_DEV,
-};
-
-/*================ File-local functions ================*/
-
-/* 
- * hfs_read_inode()
- *
- * this doesn't actually do much. hfs_iget actually fills in the 
- * necessary inode information.
- */
-static void hfs_read_inode(struct inode *inode)
-{
-  inode->i_mode = 0;
-}
+MODULE_LICENSE("GPL");
 
 /*
  * hfs_write_super()
@@ -148,20 +48,11 @@ static void hfs_read_inode(struct inode 
  */
 static void hfs_write_super(struct super_block *sb)
 {
-	struct hfs_mdb *mdb = HFS_SB(sb)->s_mdb;
-	lock_kernel();
-	/* is this a valid hfs superblock? */
-	if (!sb || sb->s_magic != HFS_SUPER_MAGIC) {
-		unlock_kernel();
-		return;
-	}
-
-	if (!(sb->s_flags & MS_RDONLY)) {
-		/* sync everything to the buffers */
-		hfs_mdb_commit(mdb, 0);
-	}
 	sb->s_dirt = 0;
-	unlock_kernel();
+	if (sb->s_flags & MS_RDONLY)
+		return;
+	/* sync everything to the buffers */
+	hfs_mdb_commit(sb);
 }
 
 /*
@@ -173,18 +64,9 @@ static void hfs_write_super(struct super
  */
 static void hfs_put_super(struct super_block *sb)
 {
-	struct hfs_mdb *mdb = HFS_SB(sb)->s_mdb;
- 
-	if (!(sb->s_flags & MS_RDONLY)) {
-		hfs_mdb_commit(mdb, 0);
-		sb->s_dirt = 0;
-	}
-
+	hfs_mdb_close(sb);
 	/* release the MDB's resources */
-	hfs_mdb_put(mdb, sb->s_flags & MS_RDONLY);
-
-	kfree(sb->s_fs_info);
-	sb->s_fs_info = NULL;
+	hfs_mdb_put(sb);
 }
 
 /*
@@ -198,294 +80,161 @@ static void hfs_put_super(struct super_b
  */
 static int hfs_statfs(struct super_block *sb, struct kstatfs *buf)
 {
-	struct hfs_mdb *mdb = HFS_SB(sb)->s_mdb;
-
 	buf->f_type = HFS_SUPER_MAGIC;
-	buf->f_bsize = HFS_SECTOR_SIZE;
-	buf->f_blocks = mdb->alloc_blksz * mdb->fs_ablocks;
-	buf->f_bfree = mdb->alloc_blksz * mdb->free_ablocks;
+	buf->f_bsize = sb->s_blocksize;
+	buf->f_blocks = (u32)HFS_SB(sb)->fs_ablocks * HFS_SB(sb)->fs_div;
+	buf->f_bfree = (u32)HFS_SB(sb)->free_ablocks * HFS_SB(sb)->fs_div;
 	buf->f_bavail = buf->f_bfree;
-	buf->f_files = mdb->fs_ablocks;  
-	buf->f_ffree = mdb->free_ablocks;
+	buf->f_files = HFS_SB(sb)->fs_ablocks;
+	buf->f_ffree = HFS_SB(sb)->free_ablocks;
 	buf->f_namelen = HFS_NAMELEN;
 
 	return 0;
 }
 
-enum {
-	Opt_version, Opt_uid, Opt_gid, Opt_umask, Opt_part,
-	Opt_type, Opt_creator, Opt_quiet, Opt_afpd,
-	Opt_names_netatalk, Opt_names_trivial, Opt_names_alpha, Opt_names_latin,
-	Opt_names_7bit, Opt_names_8bit, Opt_names_cap,
-	Opt_fork_netatalk, Opt_fork_single, Opt_fork_double, Opt_fork_cap,
-	Opt_case_lower, Opt_case_asis,
-	Opt_conv_binary, Opt_conv_text, Opt_conv_auto,
-};
+int hfs_remount(struct super_block *sb, int *flags, char *data)
+{
+	if ((*flags & MS_RDONLY) == (sb->s_flags & MS_RDONLY))
+		return 0;
+	if (!(*flags & MS_RDONLY)) {
+		if (!(HFS_SB(sb)->mdb->drAtrb & cpu_to_be16(HFS_SB_ATTRIB_UNMNT))
+		    || (HFS_SB(sb)->mdb->drAtrb & cpu_to_be16(HFS_SB_ATTRIB_INCNSTNT))) {
+			printk("HFS-fs warning: Filesystem was not cleanly unmounted, "
+			       "running fsck.hfs is recommended.  leaving read-only.\n");
+			sb->s_flags |= MS_RDONLY;
+			*flags |= MS_RDONLY;
+		} else if (HFS_SB(sb)->mdb->drAtrb & cpu_to_be16(HFS_SB_ATTRIB_SLOCK)) {
+			printk("HFS-fs: Filesystem is marked locked, leaving read-only.\n");
+			sb->s_flags |= MS_RDONLY;
+			*flags |= MS_RDONLY;
+		}
+	}
+	return 0;
+}
+
+static struct inode *hfs_alloc_inode(struct super_block *sb)
+{
+	struct hfs_inode_info *i;
+
+	i = kmem_cache_alloc(hfs_inode_cachep, SLAB_KERNEL);
+	return i ? &i->vfs_inode : NULL;
+}
 
-static match_table_t tokens = {
-	{Opt_version, "version=%u"},
-	{Opt_uid, "uid=%u"},
-	{Opt_gid, "gid=%u"},
-	{Opt_umask, "umask=%o"},
-	{Opt_part, "part=%u"},
-	{Opt_type, "type=%s"},
-	{Opt_creator, "creator=%s"},
-	{Opt_quiet, "quiet"},
-	{Opt_afpd, "afpd"},
-	{Opt_names_netatalk, "names=netatalk"},
-	{Opt_names_trivial, "names=trivial"},
-	{Opt_names_alpha, "names=alpha"},
-	{Opt_names_latin, "names=latin"},
-	{Opt_names_7bit, "names=7bit"},
-	{Opt_names_8bit, "names=8bit"},
-	{Opt_names_cap, "names=cap"},
-	{Opt_names_netatalk, "names=n"},
-	{Opt_names_trivial, "names=t"},
-	{Opt_names_alpha, "names=a"},
-	{Opt_names_latin, "names=l"},
-	{Opt_names_7bit, "names=7"},
-	{Opt_names_8bit, "names=8"},
-	{Opt_names_cap, "names=c"},
-	{Opt_fork_netatalk, "fork=netatalk"},
-	{Opt_fork_single, "fork=single"},
-	{Opt_fork_double, "fork=double"},
-	{Opt_fork_cap, "fork=cap"},
-	{Opt_fork_netatalk, "fork=n"},
-	{Opt_fork_single, "fork=s"},
-	{Opt_fork_double, "fork=d"},
-	{Opt_fork_cap, "fork=c"},
-	{Opt_case_lower, "case=lower"},
-	{Opt_case_asis, "case=asis"},
-	{Opt_case_lower, "case=l"},
-	{Opt_case_asis, "case=a"},
-	{Opt_conv_binary, "conv=binary"},
-	{Opt_conv_text, "conv=text"},
-	{Opt_conv_auto, "conv=auto"},
-	{Opt_conv_binary, "conv=b"},
-	{Opt_conv_text, "conv=t"},
-	{Opt_conv_auto, "conv=a"},
+static void hfs_destroy_inode(struct inode *inode)
+{
+	kmem_cache_free(hfs_inode_cachep, HFS_I(inode));
+}
+
+static struct super_operations hfs_super_operations = {
+	.alloc_inode	= hfs_alloc_inode,
+	.destroy_inode	= hfs_destroy_inode,
+	.write_inode	= hfs_write_inode,
+	.clear_inode	= hfs_clear_inode,
+	.put_super	= hfs_put_super,
+	.write_super	= hfs_write_super,
+	.statfs		= hfs_statfs,
+	.remount_fs     = hfs_remount,
 };
 
 /*
  * parse_options()
- * 
+ *
  * adapted from linux/fs/msdos/inode.c written 1992,93 by Werner Almesberger
  * This function is called by hfs_read_super() to parse the mount options.
  */
-static int parse_options(char *options, struct hfs_sb_info *hsb, int *part)
+static int parse_options(char *options, struct hfs_sb_info *hsb)
 {
-	char *p;
-	char names, fork;
-	substring_t args[MAX_OPT_ARGS];
-	int option;
+	char *this_char, *value;
 
 	/* initialize the sb with defaults */
-	memset(hsb, 0, sizeof(*hsb));
-	hsb->magic = HFS_SB_MAGIC;
-	hsb->s_uid   = current->uid;
-	hsb->s_gid   = current->gid;
-	hsb->s_umask = current->fs->umask;
-	hsb->s_type    = 0x3f3f3f3f;	/* == '????' */
+	hsb->s_uid = current->uid;
+	hsb->s_gid = current->gid;
+	hsb->s_file_umask = 0644;
+	hsb->s_dir_umask = 0755;
+	hsb->s_type = 0x3f3f3f3f;	/* == '????' */
 	hsb->s_creator = 0x3f3f3f3f;	/* == '????' */
-	hsb->s_lowercase = 0;
-	hsb->s_quiet     = 0;
-	hsb->s_afpd      = 0;
-        /* default version. 0 just selects the defaults */
-	hsb->s_version   = 0; 
-	hsb->s_conv = 'b';
-	names = '?';
-	fork = '?';
-	*part = 0;
+	hsb->s_quiet = 0;
+	hsb->part = -1;
+	hsb->session = -1;
 
-	if (!options) {
-		goto done;
-	}
-	while ((p = strsep(&options,",")) != NULL) {
-		int token;
-		if (!*p)
-			continue;
+	if (!options)
+		return 1;
 
-		token = match_token(p, tokens, args);
-		switch (token) {
-		/* Numeric-valued options */
-		case Opt_version:
-			if (match_int(&args[0], &option))
-				return 0;
-			hsb->s_version = option;
-			break;
-		case Opt_uid:
-			if (match_int(&args[0], &option))
-				return 0;
-			hsb->s_uid = option;
-			break;
-		case Opt_gid:
-			if (match_int(&args[0], &option))
-				return 0;
-			hsb->s_gid = option;
-			break;
-		case Opt_umask:
-			if (match_octal(&args[0], &option))
-				return 0;
-			hsb->s_umask = option;
-			break;
-		case Opt_part:
-			if (match_int(&args[0], &option))
-				return 0;
-			*part = option;
-			break;
-		/* String-valued options */
-		case Opt_type:
-			if (strlen(args[0].from) != 4) {
-				return 0;
-			}
-			hsb->s_type = hfs_get_nl(args[0].from);
-			break;
-		case Opt_creator:
-			if (strlen(args[0].from) != 4) {
-				return 0;
-			}
-			hsb->s_creator = hfs_get_nl(args[0].from);
-			break;
-		/* Boolean-valued options */
-		case Opt_quiet:
+	while ((this_char = strsep(&options, ","))) {
+		if (!*this_char)
+			continue;
+		value = strchr(this_char, '=');
+		if (value)
+			*value++ = 0;
+
+	/* Numeric-valued options */
+		if (!strcmp(this_char, "uid")) {
+			if (!value || !*value)
+				return 0;
+			hsb->s_uid = simple_strtoul(value, &value, 0);
+			if (*value)
+				return 0;
+		} else if (!strcmp(this_char, "gid")) {
+			if (!value || !*value)
+				return 0;
+			hsb->s_gid = simple_strtoul(value, &value, 0);
+			if (*value)
+				return 0;
+		} else if (!strcmp(this_char, "umask")) {
+			if (!value || !*value)
+				return 0;
+			hsb->s_file_umask = simple_strtoul(value, &value, 8);
+			hsb->s_dir_umask = hsb->s_file_umask;
+			if (*value)
+				return 0;
+		} else if (!strcmp(this_char, "file_umask")) {
+			if (!value || !*value)
+				return 0;
+			hsb->s_file_umask = simple_strtoul(value, &value, 8);
+			if (*value)
+				return 0;
+		} else if (!strcmp(this_char, "dir_umask")) {
+			if (!value || !*value)
+				return 0;
+			hsb->s_dir_umask = simple_strtoul(value, &value, 8);
+			if (*value)
+				return 0;
+		} else if (!strcmp(this_char, "part")) {
+			if (!value || !*value)
+				return 0;
+			hsb->part = simple_strtoul(value, &value, 0);
+			if (*value)
+				return 0;
+		} else if (!strcmp(this_char, "session")) {
+			if (!value || !*value)
+				return 0;
+			hsb->session = simple_strtoul(value, &value, 0);
+			if (*value)
+				return 0;
+	/* String-valued options */
+		} else if (!strcmp(this_char, "type") && value) {
+			if (strlen(value) != 4)
+				return 0;
+			hsb->s_type = *(u32 *)value;
+		} else if (!strcmp(this_char, "creator") && value) {
+			if (strlen(value) != 4)
+				return 0;
+			hsb->s_creator = *(u32 *)value;
+	/* Boolean-valued options */
+		} else if (!strcmp(this_char, "quiet")) {
+			if (value)
+				return 0;
 			hsb->s_quiet = 1;
-			break;
-		case Opt_afpd:
-			hsb->s_afpd = 1;
-			break;
-		/* Multiple choice options */
-		case Opt_names_netatalk:
-			names = 'n';
-			break;
-		case Opt_names_trivial:
-			names = 't';
-			break;
-		case Opt_names_alpha:
-			names = 'a';
-			break;
-		case Opt_names_latin:
-			names = 'l';
-			break;
-		case Opt_names_7bit:
-			names = '7';
-			break;
-		case Opt_names_8bit:
-			names = '8';
-			break;
-		case Opt_names_cap:
-			names = 'c';
-			break;
-		case Opt_fork_netatalk:
-			fork = 'n';
-			break;
-		case Opt_fork_single:
-			fork = 's';
-			break;
-		case Opt_fork_double:
-			fork = 'd';
-			break;
-		case Opt_fork_cap:
-			fork = 'c';
-			break;
-		case Opt_case_lower:
-			hsb->s_lowercase = 1;
-			break;
-		case Opt_case_asis:
-			hsb->s_lowercase = 0;
-			break;
-		case Opt_conv_binary:
-			hsb->s_conv = 'b';
-			break;
-		case Opt_conv_text:
-			hsb->s_conv = 't';
-			break;
-		case Opt_conv_auto:
-			hsb->s_conv = 'a';
-			break;
-		default:
+		} else
 			return 0;
-		}
-	}
-
-done:
-	/* Parse the "fork" and "names" options */
-	if (fork == '?') {
-		fork = hsb->s_afpd ? 'n' : 'c';
-	}
-	switch (fork) {
-	default:
-	case 'c':
-		hsb->s_ifill = hfs_cap_ifill;
-		hsb->s_reserved1 = hfs_cap_reserved1;
-		hsb->s_reserved2 = hfs_cap_reserved2;
-		break;
-
-	case 's':
-		hfs_warn("hfs_fs: AppleSingle not yet implemented.\n");
-		return 0;
-		/* break; */
-	
-	case 'd':
-		hsb->s_ifill = hfs_dbl_ifill;
-		hsb->s_reserved1 = hfs_dbl_reserved1;
-		hsb->s_reserved2 = hfs_dbl_reserved2;
-		break;
-
-	case 'n':
-		hsb->s_ifill = hfs_nat_ifill;
-		hsb->s_reserved1 = hfs_nat_reserved1;
-		hsb->s_reserved2 = hfs_nat_reserved2;
-		break;
 	}
 
-	if (names == '?') {
-		names = fork;
-	}
-	switch (names) {
-	default:
-	case 'n':
-		hsb->s_nameout = hfs_colon2mac;
-		hsb->s_namein = hfs_mac2nat;
-		break;
-
-	case 'c':
-		hsb->s_nameout = hfs_colon2mac;
-		hsb->s_namein = hfs_mac2cap;
-		break;
-
-	case 't':
-		hsb->s_nameout = hfs_triv2mac;
-		hsb->s_namein = hfs_mac2triv;
-		break;
-
-	case '7':
-		hsb->s_nameout = hfs_prcnt2mac;
-		hsb->s_namein = hfs_mac2seven;
-		break;
-
-	case '8':
-		hsb->s_nameout = hfs_prcnt2mac;
-		hsb->s_namein = hfs_mac2eight;
-		break;
-
-	case 'l':
-		hsb->s_nameout = hfs_latin2mac;
-		hsb->s_namein = hfs_mac2latin;
-		break;
-
- 	case 'a':	/* 's' and 'd' are unadvertised aliases for 'alpha', */
- 	case 's':	/* since 'alpha' is the default if fork=s or fork=d. */
- 	case 'd':	/* (It is also helpful for poor typists!)           */
-		hsb->s_nameout = hfs_prcnt2mac;
-		hsb->s_namein = hfs_mac2alpha;
-		break;
-	}
+	hsb->s_dir_umask &= 0777;
+	hsb->s_file_umask &= 0777;
 
 	return 1;
 }
 
-/*================ Global functions ================*/
-
 /*
  * hfs_read_super()
  *
@@ -497,122 +246,113 @@ done:
  * hfs_btree_init() to get the necessary data about the extents and
  * catalog B-trees and, finally, reading the root inode into memory.
  */
-int hfs_fill_super(struct super_block *s, void *data, int silent)
+static int hfs_fill_super(struct super_block *sb, void *data, int silent)
 {
 	struct hfs_sb_info *sbi;
-	struct hfs_mdb *mdb;
-	struct hfs_cat_key key;
-	hfs_s32 part_size, part_start;
+	struct hfs_find_data fd;
+	hfs_cat_rec rec;
 	struct inode *root_inode;
-	int part;
+	int res;
 
 	sbi = kmalloc(sizeof(struct hfs_sb_info), GFP_KERNEL);
 	if (!sbi)
 		return -ENOMEM;
-	s->s_fs_info = sbi;
+	sb->s_fs_info = sbi;
 	memset(sbi, 0, sizeof(struct hfs_sb_info));
+	INIT_HLIST_HEAD(&sbi->rsrc_inodes);
 
-	if (!parse_options((char *)data, sbi, &part)) {
+	res = -EINVAL;
+	if (!parse_options((char *)data, sbi)) {
 		hfs_warn("hfs_fs: unable to parse mount options.\n");
-		goto bail2;
-	}
-
-	/* set the device driver to 512-byte blocks */
-	sb_set_blocksize(s, HFS_SECTOR_SIZE);
-
-#ifdef CONFIG_MAC_PARTITION
-	/* check to see if we're in a partition */
-	mdb = hfs_mdb_get(s, s->s_flags & MS_RDONLY, 0);
-
-	/* erk. try parsing the partition table ourselves */
-	if (!mdb) {
-		if (hfs_part_find(s, part, silent, &part_size, &part_start)) {
-	    		goto bail2;
-	  	}
-	  	mdb = hfs_mdb_get(s, s->s_flags & MS_RDONLY, part_start);
-	}
-#else
-	if (hfs_part_find(s, part, silent, &part_size, &part_start)) {
-		goto bail2;
+		goto bail3;
 	}
 
-	mdb = hfs_mdb_get(s, s->s_flags & MS_RDONLY, part_start);
-#endif
+	sb->s_op = &hfs_super_operations;
+	init_MUTEX(&sbi->bitmap_lock);
 
-	if (!mdb) {
-		if (!silent) {
+	res = hfs_mdb_get(sb);
+	if (res) {
+		if (!silent)
 			hfs_warn("VFS: Can't find a HFS filesystem on dev %s.\n",
-			       s->s_id);
-		}
+				hfs_mdb_name(sb));
 		goto bail2;
 	}
 
-	sbi->s_mdb = mdb;
-	if (HFS_ITYPE(mdb->next_id) != 0) {
-		hfs_warn("hfs_fs: too many files.\n");
-		goto bail1;
-	}
-
-	s->s_magic = HFS_SUPER_MAGIC;
-	s->s_op = &hfs_super_operations;
-
 	/* try to get the root inode */
-	hfs_cat_build_key(htonl(HFS_POR_CNID),
-			  (struct hfs_name *)(mdb->vname), &key);
-
-	root_inode = hfs_iget(hfs_cat_get(mdb, &key), HFS_ITYPE_NORM, NULL);
-	if (!root_inode) 
+	hfs_find_init(HFS_SB(sb)->cat_tree, &fd);
+	res = hfs_cat_find_brec(sb, HFS_ROOT_CNID, &fd);
+	if (!res)
+		hfs_bnode_read(fd.bnode, &rec, fd.entryoffset, fd.entrylength);
+	if (res) {
+		hfs_find_exit(&fd);
 		goto bail_no_root;
-	  
-	s->s_root = d_alloc_root(root_inode);
-	if (!s->s_root) 
+	}
+	root_inode = hfs_iget(sb, &fd.search_key->cat, &rec);
+	hfs_find_exit(&fd);
+	if (!root_inode)
 		goto bail_no_root;
 
-	/* fix up pointers. */
-	HFS_I(root_inode)->entry->sys_entry[HFS_ITYPE_TO_INT(HFS_ITYPE_NORM)] =
-	  s->s_root;
-	s->s_root->d_op = &hfs_dentry_operations;
+	sb->s_root = d_alloc_root(root_inode);
+	if (!sb->s_root)
+		goto bail_no_root;
+
+	sb->s_root->d_op = &hfs_dentry_operations;
 
 	/* everything's okay */
 	return 0;
 
-bail_no_root: 
+bail_no_root:
 	hfs_warn("hfs_fs: get root inode failed.\n");
-	iput(root_inode);
-bail1:
-	hfs_mdb_put(mdb, s->s_flags & MS_RDONLY);
+	hfs_mdb_put(sb);
 bail2:
+bail3:
 	kfree(sbi);
-	s->s_fs_info = NULL;
-	return -EINVAL;	
+	return res;
+}
+
+static struct super_block *hfs_get_sb(struct file_system_type *fs_type,
+				      int flags, const char *dev_name, void *data)
+{
+	return get_sb_bdev(fs_type, flags, dev_name, data, hfs_fill_super);
+}
+
+static struct file_system_type hfs_fs_type = {
+	.owner		= THIS_MODULE,
+	.name		= "hfs",
+	.get_sb		= hfs_get_sb,
+	.kill_sb	= kill_block_super,
+	.fs_flags	= FS_REQUIRES_DEV,
+};
+
+static void hfs_init_once(void *p, kmem_cache_t *cachep, unsigned long flags)
+{
+	struct hfs_inode_info *i = p;
+
+	if ((flags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) == SLAB_CTOR_CONSTRUCTOR)
+		inode_init_once(&i->vfs_inode);
 }
 
 static int __init init_hfs_fs(void)
 {
-	int err = init_inodecache();
-	if (err)
-		goto out1;
-        hfs_cat_init();
-	err = register_filesystem(&hfs_fs);
+	int err;
+
+	hfs_inode_cachep = kmem_cache_create("hfs_inode_cache",
+		sizeof(struct hfs_inode_info), 0, SLAB_HWCACHE_ALIGN,
+		hfs_init_once, NULL);
+	if (!hfs_inode_cachep)
+		return -ENOMEM;
+	err = register_filesystem(&hfs_fs_type);
 	if (err)
-		goto out;
-	return 0;
-out:
-	hfs_cat_free();
-	destroy_inodecache();
-out1:
+		kmem_cache_destroy(hfs_inode_cachep);
 	return err;
 }
 
-static void __exit exit_hfs_fs(void) {
-	hfs_cat_free();
-	unregister_filesystem(&hfs_fs);
-	destroy_inodecache();
+static void __exit exit_hfs_fs(void)
+{
+	unregister_filesystem(&hfs_fs_type);
+	if (kmem_cache_destroy(hfs_inode_cachep))
+		printk(KERN_INFO "hfs_inode_cache: not all structures were freed\n");
 }
 
 module_init(init_hfs_fs)
 module_exit(exit_hfs_fs)
-
-#if defined(DEBUG_ALL) || defined(DEBUG_MEM)
-long int hfs_alloc = 0;
-#endif
--- diff/fs/hfs/sysdep.c	2003-07-11 09:39:50.000000000 +0100
+++ source/fs/hfs/sysdep.c	2004-02-23 13:56:46.000000000 +0000
@@ -1,109 +1,40 @@
 /*
- * linux/fs/hfs/sysdep.c
+ *  linux/fs/hfs/sysdep.c
  *
  * Copyright (C) 1996  Paul H. Hargrove
+ * (C) 2003 Ardis Technologies <roman@ardistech.com>
  * This file may be distributed under the terms of the GNU General Public License.
  *
  * This file contains the code to do various system dependent things.
- *
- * "XXX" in a comment is a note to myself to consider changing something.
- *
- * In function preconditions the term "valid" applied to a pointer to
- * a structure means that the pointer is non-NULL and the structure it
- * points to has all fields initialized to consistent values.
- */
-
-#include "hfs.h"
-#include <linux/hfs_fs_sb.h>
-#include <linux/hfs_fs_i.h>
-#include <linux/hfs_fs.h>
-#include <linux/smp_lock.h>
-
-static int hfs_revalidate_dentry(struct dentry *, struct nameidata *);
-static int hfs_hash_dentry(struct dentry *, struct qstr *);
-static int hfs_compare_dentry(struct dentry *, struct qstr *, struct qstr *);
-static void hfs_dentry_iput(struct dentry *, struct inode *);
-struct dentry_operations hfs_dentry_operations =
-{
-	.d_revalidate	= hfs_revalidate_dentry,	
-	.d_hash		= hfs_hash_dentry,
-	.d_compare	= hfs_compare_dentry,
-	.d_iput		= hfs_dentry_iput,
-};
-
-/*
- * hfs_buffer_get()
- *
- * Return a buffer for the 'block'th block of the media.
- * If ('read'==0) then the buffer is not read from disk.
  */
-hfs_buffer hfs_buffer_get(hfs_sysmdb sys_mdb, int block, int read) {
-	hfs_buffer tmp = HFS_BAD_BUFFER;
 
-	if (read) {
-		tmp = sb_bread(sys_mdb, block);
-	} else {
-		tmp = sb_getblk(sys_mdb, block);
-		if (tmp) {
-			set_buffer_uptodate(tmp);
-		}
-	}
-	if (!tmp) {
-		hfs_error("hfs_fs: unable to read block 0x%08x from dev %s\n",
-			  block, hfs_mdb_name(sys_mdb));
-	}
-
-	return tmp;
-}
+#include "hfs_fs.h"
 
 /* dentry case-handling: just lowercase everything */
 
-/* hfs_strhash now uses the same hashing function as the dcache. */
-static int hfs_hash_dentry(struct dentry *dentry, struct qstr *this)
-{
-	if (this->len > HFS_NAMELEN)
-	        return 0;
-	
-	this->hash = hfs_strhash(this->name, this->len);
-	return 0;
-}
-
-/* return 1 on failure and 0 on success */
-static int hfs_compare_dentry(struct dentry *dentry, struct qstr *a, 
-			      struct qstr *b)
-{
-	if (a->len != b->len) return 1;
-
-	if (a->len > HFS_NAMELEN)
-	  return 1;
-
-	return !hfs_streq(a->name, a->len, b->name, b->len);
-}
-
-static void hfs_dentry_iput(struct dentry *dentry, struct inode *inode)
-{
-	struct hfs_cat_entry *entry = HFS_I(inode)->entry;
-
-	lock_kernel();
-	entry->sys_entry[HFS_ITYPE_TO_INT(HFS_ITYPE(inode->i_ino))] = NULL;
-	unlock_kernel();
-	iput(inode);
-}
-
 static int hfs_revalidate_dentry(struct dentry *dentry, struct nameidata *nd)
 {
 	struct inode *inode = dentry->d_inode;
 	int diff;
 
+	if(!inode)
+		return 1;
+
 	/* fix up inode on a timezone change */
-	lock_kernel();
-	if (inode && 
-	    (diff = (hfs_to_utc(0) - HFS_I(inode)->tz_secondswest))) {
+	diff = sys_tz.tz_minuteswest * 60 - HFS_I(inode)->tz_secondswest;
+	if (diff) {
 		inode->i_ctime.tv_sec += diff;
 		inode->i_atime.tv_sec += diff;
 		inode->i_mtime.tv_sec += diff;
 		HFS_I(inode)->tz_secondswest += diff;
 	}
-	unlock_kernel();
 	return 1;
 }
+
+struct dentry_operations hfs_dentry_operations =
+{
+	.d_revalidate	= hfs_revalidate_dentry,
+	.d_hash		= hfs_hash_dentry,
+	.d_compare	= hfs_compare_dentry,
+};
+
--- diff/fs/hfs/trans.c	2002-10-16 04:29:02.000000000 +0100
+++ source/fs/hfs/trans.c	2004-02-23 13:56:46.000000000 +0000
@@ -1,5 +1,5 @@
 /*
- * linux/fs/hfs/trans.c
+ *  linux/fs/hfs/trans.c
  *
  * Copyright (C) 1995-1997  Paul H. Hargrove
  * This file may be distributed under the terms of the GNU General Public License.
@@ -7,300 +7,13 @@
  * This file contains routines for converting between the Macintosh
  * character set and various other encodings.  This includes dealing
  * with ':' vs. '/' as the path-element separator.
- *
- * Latin-1 translation based on code contributed by Holger Schemel
- * (aeglos@valinor.owl.de).
- *
- * The '8-bit', '7-bit ASCII' and '7-bit alphanumeric' encodings are
- * implementations of the three encodings recommended by Apple in the
- * document "AppleSingle/AppleDouble Formats: Developer's Note
- * (9/94)".  This document is available from Apple's Technical
- * Information Library from the World Wide Web server
- * www.info.apple.com.
- *
- * The 'CAP' encoding is an implementation of the naming scheme used
- * by the Columbia AppleTalk Package, available for anonymous FTP from
- * ????.
- *
- * "XXX" in a comment is a note to myself to consider changing something.
- *
- * In function preconditions the term "valid" applied to a pointer to
- * a structure means that the pointer is non-NULL and the structure it
- * points to has all fields initialized to consistent values.
  */
 
-#include "hfs.h"
-#include <linux/hfs_fs_sb.h>
-#include <linux/hfs_fs_i.h>
-#include <linux/hfs_fs.h>
-
-/*================ File-local variables ================*/
-
-/* int->ASCII map for a single hex digit */
-static char hex[16] = {'0','1','2','3','4','5','6','7',
-		       '8','9','a','b','c','d','e','f'};
-/*
- * Latin-1 to Mac character set map
- *
- * For the sake of consistency this map is generated from the Mac to
- * Latin-1 map the first time it is needed.  This means there is just
- * one map to maintain.
- */
-static unsigned char latin2mac_map[128]; /* initially all zero */
-
-/*
- * Mac to Latin-1 map for the upper 128 characters (both have ASCII in
- * the lower 128 positions)
- */
-static unsigned char mac2latin_map[128] = {
-	0xC4, 0xC5, 0xC7, 0xC9, 0xD1, 0xD6, 0xDC, 0xE1,
-	0xE0, 0xE2, 0xE4, 0xE3, 0xE5, 0xE7, 0xE9, 0xE8,
-	0xEA, 0xEB, 0xED, 0xEC, 0xEE, 0xEF, 0xF1, 0xF3,
-	0xF2, 0xF4, 0xF6, 0xF5, 0xFA, 0xF9, 0xFB, 0xFC,
-	0x00, 0xB0, 0xA2, 0xA3, 0xA7, 0xB7, 0xB6, 0xDF,
-	0xAE, 0xA9, 0x00, 0xB4, 0xA8, 0x00, 0xC6, 0xD8,
-	0x00, 0xB1, 0x00, 0x00, 0xA5, 0xB5, 0xF0, 0x00, 
-	0x00, 0x00, 0x00, 0xAA, 0xBA, 0x00, 0xE6, 0xF8,
-	0xBF, 0xA1, 0xAC, 0x00, 0x00, 0x00, 0x00, 0xAB,
-	0xBB, 0x00, 0xA0, 0xC0, 0xC3, 0xD5, 0x00, 0x00, 
-	0xAD, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF7, 0x00, 
-	0xFF, 0x00, 0x00, 0xA4, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0xB8, 0x00, 0x00, 0xC2, 0xCA, 0xC1,
-	0xCB, 0xC8, 0xCD, 0xCE, 0xCF, 0xCC, 0xD3, 0xD4,
-	0x00, 0xD2, 0xDA, 0xDB, 0xD9, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
-};
-
-/*================ File-local functions ================*/
-
-/*
- * dehex()
- *
- * Given a hexadecimal digit in ASCII, return the integer representation.
- */
-static inline const unsigned char dehex(char c) {
-	if ((c>='0')&&(c<='9')) {
-		return c-'0';
-	}
-	if ((c>='a')&&(c<='f')) {
-		return c-'a'+10;
-	}
-	if ((c>='A')&&(c<='F')) {
-		return c-'A'+10;
-	}
-	return 0xff;
-}
+#include "hfs_fs.h"
 
 /*================ Global functions ================*/
 
 /*
- * hfs_mac2nat()
- *
- * Given a 'Pascal String' (a string preceded by a length byte) in
- * the Macintosh character set produce the corresponding filename using
- * the Netatalk name-mangling scheme, returning the length of the
- * mangled filename.  Note that the output string is not NULL terminated.
- *
- * The name-mangling works as follows:
- * Characters 32-126 (' '-'~') except '/' and any initial '.' are passed
- * unchanged from input to output.  The remaining characters are replaced
- * by three characters: ':xx' where xx is the hexadecimal representation
- * of the character, using lowercase 'a' through 'f'.
- */
-int hfs_mac2nat(char *out, const struct hfs_name *in) {
-	unsigned char c;
-	const unsigned char *p = in->Name;
-	int len = in->Len;
-	int count = 0;
-
-	/* Special case for .AppleDesktop which in the
-	   distant future may be a pseudodirectory. */
-	if (strncmp(".AppleDesktop", p, len) == 0) {
-		strncpy(out, p, 13);
-		return 13;
-	}
-
-	while (len--) {
-		c = *p++;
-		if ((c<32) || (c=='/') || (c>126) || (!count && (c=='.'))) {
-			*out++ = ':';
-			*out++ = hex[(c>>4) & 0xf];
-			*out++ = hex[c & 0xf];
-			count += 3;
-		} else {
-			*out++ = c;
-			count++;
-		}
-	}
-	return count;
-}
-
-/*
- * hfs_mac2cap()
- *
- * Given a 'Pascal String' (a string preceded by a length byte) in
- * the Macintosh character set produce the corresponding filename using
- * the CAP name-mangling scheme, returning the length of the mangled
- * filename.  Note that the output string is not NULL terminated.
- *
- * The name-mangling works as follows:
- * Characters 32-126 (' '-'~') except '/' are passed unchanged from
- * input to output.  The remaining characters are replaced by three
- * characters: ':xx' where xx is the hexadecimal representation of the
- * character, using lowercase 'a' through 'f'.
- */
-int hfs_mac2cap(char *out, const struct hfs_name *in) {
-	unsigned char c;
-	const unsigned char *p = in->Name;
-	int len = in->Len;
-	int count = 0;
-
-	while (len--) {
-		c = *p++;
-		if ((c<32) || (c=='/') || (c>126)) {
-			*out++ = ':';
-			*out++ = hex[(c>>4) & 0xf];
-			*out++ = hex[c & 0xf];
-			count += 3;
-		} else {
-			*out++ = c;
-			count++;
-		}
-	}
-	return count;
-}
-
-/*
- * hfs_mac2eight()
- *
- * Given a 'Pascal String' (a string preceded by a length byte) in
- * the Macintosh character set produce the corresponding filename using
- * the '8-bit' name-mangling scheme, returning the length of the
- * mangled filename.  Note that the output string is not NULL
- * terminated.
- *
- * This is one of the three recommended naming conventions described
- * in Apple's document "AppleSingle/AppleDouble Formats: Developer's
- * Note (9/94)"
- *
- * The name-mangling works as follows:
- * Characters 0, '%' and '/' are replaced by three characters: '%xx'
- * where xx is the hexadecimal representation of the character, using
- * lowercase 'a' through 'f'.  All other characters are passed
- * unchanged from input to output.  Note that this format is mainly
- * implemented for completeness and is rather hard to read.
- */
-int hfs_mac2eight(char *out, const struct hfs_name *in) {
-	unsigned char c;
-	const unsigned char *p = in->Name;
-	int len = in->Len;
-	int count = 0;
-
-	while (len--) {
-		c = *p++;
-		if (!c || (c=='/') || (c=='%')) {
-			*out++ = '%';
-			*out++ = hex[(c>>4) & 0xf];
-			*out++ = hex[c & 0xf];
-			count += 3;
-		} else {
-			*out++ = c;
-			count++;
-		}
-	}
-	return count;
-}
-
-/*
- * hfs_mac2seven()
- *
- * Given a 'Pascal String' (a string preceded by a length byte) in
- * the Macintosh character set produce the corresponding filename using
- * the '7-bit ASCII' name-mangling scheme, returning the length of the
- * mangled filename.  Note that the output string is not NULL
- * terminated.
- *
- * This is one of the three recommended naming conventions described
- * in Apple's document "AppleSingle/AppleDouble Formats: Developer's
- * Note (9/94)"
- *
- * The name-mangling works as follows:
- * Characters 0, '%', '/' and 128-255 are replaced by three
- * characters: '%xx' where xx is the hexadecimal representation of the
- * character, using lowercase 'a' through 'f'.	All other characters
- * are passed unchanged from input to output.  Note that control
- * characters (including newline) and space are unchanged make reading
- * these filenames difficult.
- */
-int hfs_mac2seven(char *out, const struct hfs_name *in) {
-	unsigned char c;
-	const unsigned char *p = in->Name;
-	int len = in->Len;
-	int count = 0;
-
-	while (len--) {
-		c = *p++;
-		if (!c || (c=='/') || (c=='%') || (c&0x80)) {
-			*out++ = '%';
-			*out++ = hex[(c>>4) & 0xf];
-			*out++ = hex[c & 0xf];
-			count += 3;
-		} else {
-			*out++ = c;
-			count++;
-		}
-	}
-	return count;
-}
-
-/*
- * hfs_mac2alpha()
- *
- * Given a 'Pascal String' (a string preceded by a length byte) in
- * the Macintosh character set produce the corresponding filename using
- * the '7-bit alphanumeric' name-mangling scheme, returning the length
- * of the mangled filename.  Note that the output string is not NULL
- * terminated.
- *
- * This is one of the three recommended naming conventions described
- * in Apple's document "AppleSingle/AppleDouble Formats: Developer's
- * Note (9/94)"
- *
- * The name-mangling works as follows:
- * The characters 'a'-'z', 'A'-'Z', '0'-'9', '_' and the last '.' in
- * the filename are passed unchanged from input to output.  All
- * remaining characters (including any '.'s other than the last) are
- * replaced by three characters: '%xx' where xx is the hexadecimal
- * representation of the character, using lowercase 'a' through 'f'.
- */
-int hfs_mac2alpha(char *out, const struct hfs_name *in) {
-	unsigned char c;
-	const unsigned char *p = in->Name;
-	int len = in->Len;
-	int count = 0;
-	const unsigned char *lp;	/* last period */
-
-	/* strrchr() would be good here, but 'in' is not null-terminated */
-	for (lp=p+len-1; (lp>=p)&&(*lp!='.'); --lp) {}
-	++lp;
-
-	while (len--) {
-		c = *p++;
-		if ((p==lp) || ((c>='0')&&(c<='9')) || ((c>='A')&&(c<='Z')) ||
-				((c>='a')&&(c<='z')) || (c=='_')) {
-			*out++ = c;
-			count++;
-		} else {
-			*out++ = '%';
-			*out++ = hex[(c>>4) & 0xf];
-			*out++ = hex[c & 0xf];
-			count += 3;
-		}
-	}
-	return count;
-}
-
-/*
  * hfs_mac2triv()
  *
  * Given a 'Pascal String' (a string preceded by a length byte) in
@@ -314,154 +27,19 @@ int hfs_mac2alpha(char *out, const struc
  * by ':' which never appears in HFS filenames.	 All other characters
  * are passed unchanged from input to output.
  */
-int hfs_mac2triv(char *out, const struct hfs_name *in) {
-	unsigned char c;
-	const unsigned char *p = in->Name;
-	int len = in->Len;
-	int count = 0;
-
-	while (len--) {
-		c = *p++;
-		if (c=='/') {
-			*out++ = ':';
-		} else {
-			*out++ = c;
-		}
-		count++;
-	}
-	return count;
-}
-
-/*
- * hfs_mac2latin()
- *
- * Given a 'Pascal String' (a string preceded by a length byte) in
- * the Macintosh character set produce the corresponding filename using
- * the 'Latin-1' name-mangling scheme, returning the length of the
- * mangled filename.  Note that the output string is not NULL
- * terminated.
- *
- * The Macintosh character set and Latin-1 are both extensions of the
- * ASCII character set.	 Some, but certainly not all, of the characters
- * in the Macintosh character set are also in Latin-1 but not with the
- * same encoding.  This name-mangling scheme replaces the characters in
- * the Macintosh character set that have Latin-1 equivalents by those
- * equivalents; the characters 32-126, excluding '/' and '%', are
- * passed unchanged from input to output.  The remaining characters
- * are replaced by three characters: '%xx' where xx is the hexadecimal
- * representation of the character, using lowercase 'a' through 'f'.
- *
- * The array mac2latin_map[] indicates the correspondence between the
- * two character sets.	The byte in element x-128 gives the Latin-1
- * encoding of the character with encoding x in the Macintosh
- * character set.  A value of zero indicates Latin-1 has no
- * corresponding character.
- */
-int hfs_mac2latin(char *out, const struct hfs_name *in) {
-	unsigned char c;
-	const unsigned char *p = in->Name;
-	int len = in->Len;
-	int count = 0;
+int hfs_mac2triv(char *out, const struct hfs_name *in)
+{
+	const char *p;
+	char c;
+	int i, len;
 
-	while (len--) {
+	len = in->len;
+	p = in->name;
+	for (i = 0; i < len; i++) {
 		c = *p++;
-
-		if ((c & 0x80) && mac2latin_map[c & 0x7f]) {
-			*out++ = mac2latin_map[c & 0x7f];
-			count++;
-		} else if ((c>=32) && (c<=126) && (c!='/') && (c!='%')) {
-			*out++ =  c;
-			count++;
-		} else {
-			*out++ = '%';
-			*out++ = hex[(c>>4) & 0xf];
-			*out++ = hex[c & 0xf];
-			count += 3;
-		}
-	}
-	return count;
-}
-
-/*
- * hfs_colon2mac()
- *
- * Given an ASCII string (not null-terminated) and its length,
- * generate the corresponding filename in the Macintosh character set
- * using the 'CAP' name-mangling scheme, returning the length of the
- * mangled filename.  Note that the output string is not NULL
- * terminated.
- *
- * This routine is a inverse to hfs_mac2cap() and hfs_mac2nat().
- * A ':' not followed by a 2-digit hexadecimal number (or followed
- * by the codes for NULL or ':') is replaced by a '|'.
- */
-void hfs_colon2mac(struct hfs_name *out, const char *in, int len) {
-	int hi, lo;
-	unsigned char code, c, *count;
-	unsigned char *p = out->Name;
-
-	out->Len = 0;
-	count = &out->Len;
-	while (len-- && (*count < HFS_NAMELEN)) {
-		c = *in++;
-		(*count)++;
-		if (c!=':') {
-			*p++ = c;
-		} else if ((len<2) ||
-			   ((hi=dehex(in[0])) & 0xf0) ||
-			   ((lo=dehex(in[1])) & 0xf0) ||
-			   !(code = (hi << 4) | lo) ||
-			   (code == ':')) {
-			*p++ = '|';
-		} else {
-			*p++ = code;
-			len -= 2;
-			in += 2;
-		}
-	}
-}
-
-/*
- * hfs_prcnt2mac()
- *
- * Given an ASCII string (not null-terminated) and its length,
- * generate the corresponding filename in the Macintosh character set
- * using Apple's three recommended name-mangling schemes, returning
- * the length of the mangled filename.	Note that the output string is
- * not NULL terminated.
- *
- * This routine is a inverse to hfs_mac2alpha(), hfs_mac2seven() and
- * hfs_mac2eight().
- * A '%' not followed by a 2-digit hexadecimal number (or followed
- * by the code for NULL or ':') is unchanged.
- * A ':' is replaced by a '|'.
- */
-void hfs_prcnt2mac(struct hfs_name *out, const char *in, int len) {
-	int hi, lo;
-	unsigned char code, c, *count;
-	unsigned char *p = out->Name;
-
-	out->Len = 0;
-	count = &out->Len;
-	while (len-- && (*count < HFS_NAMELEN)) {
-		c = *in++;
-		(*count)++;
-		if (c==':') {
-			*p++ = '|';
-		} else if (c!='%') {
-			*p++ = c;
-		} else if ((len<2) ||
-			   ((hi=dehex(in[0])) & 0xf0) ||
-			   ((lo=dehex(in[1])) & 0xf0) ||
-			   !(code = (hi << 4) | lo) ||
-			   (code == ':')) {
-			*p++ = '%';
-		} else {
-			*p++ = code;
-			len -= 2;
-			in += 2;
-		}
+		*out++ = c == '/' ? ':' : c;
 	}
+	return i;
 }
 
 /*
@@ -476,81 +54,19 @@ void hfs_prcnt2mac(struct hfs_name *out,
  * This routine is a inverse to hfs_mac2triv().
  * A ':' is replaced by a '/'.
  */
-void hfs_triv2mac(struct hfs_name *out, const char *in, int len) {
-	unsigned char c, *count;
-	unsigned char *p = out->Name;
-
-	out->Len = 0;
-	count = &out->Len;
-	while (len-- && (*count < HFS_NAMELEN)) {
-		c = *in++;
-		(*count)++;
-		if (c==':') {
-			*p++ = '/';
-		} else {
-			*p++ = c;
-		}
-	}
-}
-
-/*
- * hfs_latin2mac()
- *
- * Given an Latin-1 string (not null-terminated) and its length,
- * generate the corresponding filename in the Macintosh character set
- * using the 'Latin-1' name-mangling scheme, returning the length of
- * the mangled filename.  Note that the output string is not NULL
- * terminated.
- *
- * This routine is a inverse to hfs_latin2cap().
- * A '%' not followed by a 2-digit hexadecimal number (or followed
- * by the code for NULL or ':') is unchanged.
- * A ':' is replaced by a '|'.
- *
- * Note that the character map is built the first time it is needed.
- */
-void hfs_latin2mac(struct hfs_name *out, const char *in, int len)
+void hfs_triv2mac(struct hfs_name *out, struct qstr *in)
 {
-	int hi, lo;
-	unsigned char code, c, *count;
-	unsigned char *p = out->Name;
-	static int map_initialized;
-
-	if (!map_initialized) {
-		int i;
-
-		/* build the inverse mapping at run time */
-		for (i = 0; i < 128; i++) {
-			if ((c = mac2latin_map[i])) {
-				latin2mac_map[(int)c - 128] = i + 128;
-			}
-		}
-		map_initialized = 1;
-	}
-
-	out->Len = 0;
-	count = &out->Len;
-	while (len-- && (*count < HFS_NAMELEN)) {
-		c = *in++;
-		(*count)++;
-
-		if (c==':') {
-			*p++ = '|';
-		} else if (c!='%') {
-			if (c<128 || !(*p = latin2mac_map[c-128])) {
-				*p = c;
-			}
-			p++;
-		} else if ((len<2) ||
-			   ((hi=dehex(in[0])) & 0xf0) ||
-			   ((lo=dehex(in[1])) & 0xf0) ||
-			   !(code = (hi << 4) | lo) ||
-			   (code == ':')) {
-			*p++ = '%';
-		} else {
-			*p++ = code;
-			len -= 2;
-			in += 2;
-		}
+	const char *src;
+	char *dst, c;
+	int i, len;
+
+	out->len = len = min((unsigned int)HFS_NAMELEN, in->len);
+	src = in->name;
+	dst = out->name;
+	for (i = 0; i < len; i++) {
+		c = *src++;
+		*dst++ = c == ':' ? '/' : c;
 	}
+	for (; i < HFS_NAMELEN; i++)
+		*dst++ = 0;
 }
--- diff/fs/hugetlbfs/inode.c	2004-02-18 08:54:12.000000000 +0000
+++ source/fs/hugetlbfs/inode.c	2004-02-23 13:56:46.000000000 +0000
@@ -194,6 +194,7 @@ static void hugetlbfs_delete_inode(struc
 
 	hlist_del_init(&inode->i_hash);
 	list_del_init(&inode->i_list);
+	list_del_init(&inode->i_sb_list);
 	inode->i_state |= I_FREEING;
 	inodes_stat.nr_inodes--;
 	spin_unlock(&inode_lock);
@@ -236,6 +237,7 @@ static void hugetlbfs_forget_inode(struc
 	hlist_del_init(&inode->i_hash);
 out_truncate:
 	list_del_init(&inode->i_list);
+	list_del_init(&inode->i_sb_list);
 	inode->i_state |= I_FREEING;
 	inodes_stat.nr_inodes--;
 	spin_unlock(&inode_lock);
--- diff/fs/inode.c	2003-10-27 09:20:38.000000000 +0000
+++ source/fs/inode.c	2004-02-23 13:56:46.000000000 +0000
@@ -20,6 +20,7 @@
 #include <linux/security.h>
 #include <linux/pagemap.h>
 #include <linux/cdev.h>
+#include <linux/ext3_fs_i.h>
 
 /*
  * This is needed for the following functions:
@@ -183,6 +184,7 @@ void inode_init_once(struct inode *inode
 	INIT_LIST_HEAD(&inode->i_dentry);
 	INIT_LIST_HEAD(&inode->i_devices);
 	sema_init(&inode->i_sem, 1);
+	init_rwsem(&inode->i_alloc_sem);
 	INIT_RADIX_TREE(&inode->i_data.page_tree, GFP_ATOMIC);
 	spin_lock_init(&inode->i_data.page_lock);
 	init_MUTEX(&inode->i_data.i_shared_sem);
@@ -193,6 +195,7 @@ void inode_init_once(struct inode *inode
 	INIT_LIST_HEAD(&inode->i_data.i_mmap_shared);
 	spin_lock_init(&inode->i_lock);
 	i_size_ordered_init(inode);
+	init_rwsem(&inode->i_data.wb_rwsema);
 }
 
 EXPORT_SYMBOL(inode_init_once);
@@ -285,7 +288,7 @@ static void dispose_list(struct list_hea
 /*
  * Invalidate all inodes for a device.
  */
-static int invalidate_list(struct list_head *head, struct super_block * sb, struct list_head * dispose)
+static int invalidate_list(struct list_head *head, struct list_head *dispose)
 {
 	struct list_head *next;
 	int busy = 0, count = 0;
@@ -298,13 +301,12 @@ static int invalidate_list(struct list_h
 		next = next->next;
 		if (tmp == head)
 			break;
-		inode = list_entry(tmp, struct inode, i_list);
-		if (inode->i_sb != sb)
-			continue;
+		inode = list_entry(tmp, struct inode, i_sb_list);
 		invalidate_inode_buffers(inode);
 		if (!atomic_read(&inode->i_count)) {
 			hlist_del_init(&inode->i_hash);
 			list_del(&inode->i_list);
+			list_del(&inode->i_sb_list);
 			list_add(&inode->i_list, dispose);
 			inode->i_state |= I_FREEING;
 			count++;
@@ -340,10 +342,7 @@ int invalidate_inodes(struct super_block
 
 	down(&iprune_sem);
 	spin_lock(&inode_lock);
-	busy = invalidate_list(&inode_in_use, sb, &throw_away);
-	busy |= invalidate_list(&inode_unused, sb, &throw_away);
-	busy |= invalidate_list(&sb->s_dirty, sb, &throw_away);
-	busy |= invalidate_list(&sb->s_io, sb, &throw_away);
+	busy = invalidate_list(&sb->s_inodes, &throw_away);
 	spin_unlock(&inode_lock);
 
 	dispose_list(&throw_away);
@@ -443,6 +442,7 @@ static void prune_icache(int nr_to_scan)
 				continue;
 		}
 		hlist_del_init(&inode->i_hash);
+		list_del_init(&inode->i_sb_list);
 		list_move(&inode->i_list, &freeable);
 		inode->i_state |= I_FREEING;
 		nr_pruned++;
@@ -553,6 +553,7 @@ struct inode *new_inode(struct super_blo
 		spin_lock(&inode_lock);
 		inodes_stat.nr_inodes++;
 		list_add(&inode->i_list, &inode_in_use);
+		list_add(&inode->i_sb_list, &sb->s_inodes);
 		inode->i_ino = ++last_ino;
 		inode->i_state = 0;
 		spin_unlock(&inode_lock);
@@ -601,6 +602,7 @@ static struct inode * get_new_inode(stru
 
 			inodes_stat.nr_inodes++;
 			list_add(&inode->i_list, &inode_in_use);
+			list_add(&inode->i_sb_list, &sb->s_inodes);
 			hlist_add_head(&inode->i_hash, head);
 			inode->i_state = I_LOCK|I_NEW;
 			spin_unlock(&inode_lock);
@@ -649,6 +651,7 @@ static struct inode * get_new_inode_fast
 			inode->i_ino = ino;
 			inodes_stat.nr_inodes++;
 			list_add(&inode->i_list, &inode_in_use);
+			list_add(&inode->i_sb_list, &sb->s_inodes);
 			hlist_add_head(&inode->i_hash, head);
 			inode->i_state = I_LOCK|I_NEW;
 			spin_unlock(&inode_lock);
@@ -984,6 +987,7 @@ void generic_delete_inode(struct inode *
 	struct super_operations *op = inode->i_sb->s_op;
 
 	list_del_init(&inode->i_list);
+	list_del_init(&inode->i_sb_list);
 	inode->i_state|=I_FREEING;
 	inodes_stat.nr_inodes--;
 	spin_unlock(&inode_lock);
@@ -1018,6 +1022,14 @@ static void generic_forget_inode(struct 
 
 	if (!hlist_unhashed(&inode->i_hash)) {
 		if (!(inode->i_state & (I_DIRTY|I_LOCK))) {
+			if (!strcmp(inode->i_sb->s_type->name, "ext3")) {
+				struct ext3_inode_info *ext3_i;
+				ext3_i = container_of(inode,
+						struct ext3_inode_info,
+						vfs_inode);
+				if (!list_empty(&ext3_i->i_orphan))
+					WARN_ON(1);
+			}
 			list_del(&inode->i_list);
 			list_add(&inode->i_list, &inode_unused);
 		}
@@ -1031,6 +1043,7 @@ static void generic_forget_inode(struct 
 		hlist_del_init(&inode->i_hash);
 	}
 	list_del_init(&inode->i_list);
+	list_del_init(&inode->i_sb_list);
 	inode->i_state|=I_FREEING;
 	inodes_stat.nr_inodes--;
 	spin_unlock(&inode_lock);
@@ -1064,7 +1077,7 @@ static void generic_drop_inode(struct in
  * held, and the drop function is supposed to release
  * the lock!
  */
-static inline void iput_final(struct inode *inode)
+static void iput_final(struct inode *inode)
 {
 	struct super_operations *op = inode->i_sb->s_op;
 	void (*drop)(struct inode *) = generic_drop_inode;
@@ -1178,6 +1191,8 @@ void inode_update_time(struct inode *ino
 	struct timespec now;
 	int sync_it = 0;
 
+	if (IS_NOCMTIME(inode))
+		return;
 	if (IS_RDONLY(inode))
 		return;
 
@@ -1221,34 +1236,17 @@ int remove_inode_dquot_ref(struct inode 
 void remove_dquot_ref(struct super_block *sb, int type)
 {
 	struct inode *inode;
-	struct list_head *act_head;
 	LIST_HEAD(tofree_head);
 
 	if (!sb->dq_op)
 		return;	/* nothing to do */
 	spin_lock(&inode_lock);	/* This lock is for inodes code */
 	/* We don't have to lock against quota code - test IS_QUOTAINIT is just for speedup... */
- 
-	list_for_each(act_head, &inode_in_use) {
-		inode = list_entry(act_head, struct inode, i_list);
-		if (inode->i_sb == sb && IS_QUOTAINIT(inode))
-			remove_inode_dquot_ref(inode, type, &tofree_head);
-	}
-	list_for_each(act_head, &inode_unused) {
-		inode = list_entry(act_head, struct inode, i_list);
-		if (inode->i_sb == sb && IS_QUOTAINIT(inode))
-			remove_inode_dquot_ref(inode, type, &tofree_head);
-	}
-	list_for_each(act_head, &sb->s_dirty) {
-		inode = list_entry(act_head, struct inode, i_list);
-		if (IS_QUOTAINIT(inode))
-			remove_inode_dquot_ref(inode, type, &tofree_head);
-	}
-	list_for_each(act_head, &sb->s_io) {
-		inode = list_entry(act_head, struct inode, i_list);
+
+	list_for_each_entry(inode, &sb->s_inodes, i_sb_list)
 		if (IS_QUOTAINIT(inode))
 			remove_inode_dquot_ref(inode, type, &tofree_head);
-	}
+
 	spin_unlock(&inode_lock);
 
 	put_dquot_list(&tofree_head);
@@ -1327,6 +1325,16 @@ void wake_up_inode(struct inode *inode)
 		wake_up_all(wq);
 }
 
+static __initdata unsigned long ihash_entries;
+static int __init set_ihash_entries(char *str)
+{
+	if (!str)
+		return 0;
+	ihash_entries = simple_strtoul(str, &str, 0);
+	return 1;
+}
+__setup("ihash_entries=", set_ihash_entries);
+
 /*
  * Initialize the waitqueues and inode hash table.
  */
@@ -1340,9 +1348,13 @@ void __init inode_init(unsigned long mem
 	for (i = 0; i < ARRAY_SIZE(i_wait_queue_heads); i++)
 		init_waitqueue_head(&i_wait_queue_heads[i].wqh);
 
-	mempages >>= (14 - PAGE_SHIFT);
-	mempages *= sizeof(struct hlist_head);
-	for (order = 0; ((1UL << order) << PAGE_SHIFT) < mempages; order++)
+	if (!ihash_entries)
+		ihash_entries = PAGE_SHIFT < 14 ?
+				mempages >> (14 - PAGE_SHIFT) :
+				mempages << (PAGE_SHIFT - 14);
+
+	ihash_entries *= sizeof(struct hlist_head);
+	for (order = 0; ((1UL << order) << PAGE_SHIFT) < ihash_entries; order++)
 		;
 
 	do {
--- diff/fs/jffs/inode-v23.c	2003-10-09 09:47:17.000000000 +0100
+++ source/fs/jffs/inode-v23.c	2004-02-23 13:56:46.000000000 +0000
@@ -1807,13 +1807,25 @@ init_jffs_fs(void)
 	
 #ifdef CONFIG_JFFS_PROC_FS
 	jffs_proc_root = proc_mkdir("jffs", proc_root_fs);
+	if (!jffs_proc_root) {
+		printk(KERN_WARNING "cannot create /proc/jffs entry\n");
+	}
 #endif
 	fm_cache = kmem_cache_create("jffs_fm", sizeof(struct jffs_fm),
 				     0, SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT, 
 				     NULL, NULL);
+	if (!fm_cache) {
+		return -ENOMEM;
+	}
+
 	node_cache = kmem_cache_create("jffs_node",sizeof(struct jffs_node),
 				       0, SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT, 
 				       NULL, NULL);
+	if (!node_cache) {
+		kmem_cache_destroy(fm_cache);
+		return -ENOMEM;
+	}
+
 	return register_filesystem(&jffs_fs_type);
 }
 
--- diff/fs/jfs/acl.c	2003-10-09 09:47:17.000000000 +0100
+++ source/fs/jfs/acl.c	2004-02-23 13:56:46.000000000 +0000
@@ -191,7 +191,8 @@ check_capabilities:
 	 * Read/write DACs are always overridable.
 	 * Executable DACs are overridable if at least one exec bit is set.
 	 */
-	if ((mask & (MAY_READ|MAY_WRITE)) || (inode->i_mode & S_IXUGO))
+	if (!(mask & MAY_EXEC) ||
+	    (inode->i_mode & S_IXUGO) || S_ISDIR(inode->i_mode))
 		if (capable(CAP_DAC_OVERRIDE))
 			return 0;
 
--- diff/fs/jfs/jfs_logmgr.c	2004-02-18 08:54:12.000000000 +0000
+++ source/fs/jfs/jfs_logmgr.c	2004-02-23 13:56:46.000000000 +0000
@@ -1105,8 +1105,7 @@ int lmLogOpen(struct super_block *sb, st
 	 */
       externalLog:
 
-	bdev = open_by_devnum(JFS_SBI(sb)->logdev,
-					FMODE_READ|FMODE_WRITE, BDEV_FS);
+	bdev = open_by_devnum(JFS_SBI(sb)->logdev, FMODE_READ|FMODE_WRITE);
 	if (IS_ERR(bdev)) {
 		rc = -PTR_ERR(bdev);
 		goto free;
@@ -1145,7 +1144,7 @@ int lmLogOpen(struct super_block *sb, st
 	bd_release(bdev);
 
       close:		/* close external log device */
-	blkdev_put(bdev, BDEV_FS);
+	blkdev_put(bdev);
 
       free:		/* free log descriptor */
 	kfree(log);
@@ -1392,7 +1391,7 @@ int lmLogClose(struct super_block *sb, s
 	rc = lmLogShutdown(log);
 
 	bd_release(bdev);
-	blkdev_put(bdev, BDEV_FS);
+	blkdev_put(bdev);
 
       out:
 	jfs_info("lmLogClose: exit(%d)", rc);
--- diff/fs/jfs/jfs_unicode.c	2003-07-11 09:39:50.000000000 +0100
+++ source/fs/jfs/jfs_unicode.c	2004-02-23 13:56:46.000000000 +0000
@@ -1,5 +1,5 @@
 /*
- *   Copyright (c) International Business Machines Corp., 2000-2002
+ *   Copyright (C) International Business Machines Corp., 2000-2004
  *
  *   This program is free software;  you can redistribute it and/or modify
  *   it under the terms of the GNU General Public License as published by
@@ -18,7 +18,7 @@
 
 #include <linux/fs.h>
 #include <linux/slab.h>
-#include "jfs_types.h"
+#include "jfs_incore.h"
 #include "jfs_filsys.h"
 #include "jfs_unicode.h"
 #include "jfs_debug.h"
@@ -35,16 +35,22 @@ int jfs_strfromUCS_le(char *to, const wc
 	int i;
 	int outlen = 0;
 
-	for (i = 0; (i < len) && from[i]; i++) {
-		int charlen;
-		charlen =
-		    codepage->uni2char(le16_to_cpu(from[i]), &to[outlen],
-				       NLS_MAX_CHARSET_SIZE);
-		if (charlen > 0) {
-			outlen += charlen;
-		} else {
-			to[outlen++] = '?';
+	if (codepage) {
+		for (i = 0; (i < len) && from[i]; i++) {
+			int charlen;
+			charlen =
+			    codepage->uni2char(le16_to_cpu(from[i]),
+					       &to[outlen],
+					       NLS_MAX_CHARSET_SIZE);
+			if (charlen > 0)
+				outlen += charlen;
+			else
+				to[outlen++] = '?';
 		}
+	} else {
+		for (i = 0; (i < len) && from[i]; i++)
+			to[i] = (char) (le16_to_cpu(from[i]));
+		outlen = i;
 	}
 	to[outlen] = 0;
 	return outlen;
@@ -62,14 +68,22 @@ int jfs_strtoUCS(wchar_t * to,
 	int charlen;
 	int i;
 
-	for (i = 0; len && *from; i++, from += charlen, len -= charlen) {
-		charlen = codepage->char2uni(from, len, &to[i]);
-		if (charlen < 1) {
-			jfs_err("jfs_strtoUCS: char2uni returned %d.", charlen);
-			jfs_err("charset = %s, char = 0x%x",
-				codepage->charset, (unsigned char) *from);
-			return charlen;
+	if (codepage) {
+		for (i = 0; len && *from; i++, from += charlen, len -= charlen)
+		{
+			charlen = codepage->char2uni(from, len, &to[i]);
+			if (charlen < 1) {
+				jfs_err("jfs_strtoUCS: char2uni returned %d.",
+					charlen);
+				jfs_err("charset = %s, char = 0x%x",
+					codepage->charset,
+					(unsigned char) *from);
+				return charlen;
+			}
 		}
+	} else {
+		for (i = 0; (i < len) && from[i]; i++)
+			to[i] = (wchar_t) from[i];
 	}
 
 	to[i] = 0;
@@ -82,9 +96,9 @@ int jfs_strtoUCS(wchar_t * to,
  * FUNCTION:	Allocate and translate to unicode string
  *
  */
-int get_UCSname(struct component_name * uniName, struct dentry *dentry,
-		struct nls_table *nls_tab)
+int get_UCSname(struct component_name * uniName, struct dentry *dentry)
 {
+	struct nls_table *nls_tab = JFS_SBI(dentry->d_sb)->nls_tab;
 	int length = dentry->d_name.len;
 
 	if (length > JFS_NAME_MAX)
--- diff/fs/jfs/jfs_unicode.h	2002-10-16 04:27:08.000000000 +0100
+++ source/fs/jfs/jfs_unicode.h	2004-02-23 13:56:46.000000000 +0000
@@ -30,8 +30,7 @@ typedef struct {
 
 extern signed char UniUpperTable[512];
 extern UNICASERANGE UniUpperRange[];
-extern int get_UCSname(struct component_name *, struct dentry *,
-		       struct nls_table *);
+extern int get_UCSname(struct component_name *, struct dentry *);
 extern int jfs_strfromUCS_le(char *, const wchar_t *, int, struct nls_table *);
 
 #define free_UCSname(COMP) kfree((COMP)->name)
--- diff/fs/jfs/namei.c	2004-02-18 08:54:12.000000000 +0000
+++ source/fs/jfs/namei.c	2004-02-23 13:56:46.000000000 +0000
@@ -78,7 +78,7 @@ int jfs_create(struct inode *dip, struct
 	 * search parent directory for entry/freespace
 	 * (dtSearch() returns parent directory page pinned)
 	 */
-	if ((rc = get_UCSname(&dname, dentry, JFS_SBI(dip->i_sb)->nls_tab)))
+	if ((rc = get_UCSname(&dname, dentry)))
 		goto out1;
 
 	/*
@@ -204,7 +204,7 @@ int jfs_mkdir(struct inode *dip, struct 
 	 * search parent directory for entry/freespace
 	 * (dtSearch() returns parent directory page pinned)
 	 */
-	if ((rc = get_UCSname(&dname, dentry, JFS_SBI(dip->i_sb)->nls_tab)))
+	if ((rc = get_UCSname(&dname, dentry)))
 		goto out1;
 
 	/*
@@ -332,7 +332,7 @@ int jfs_rmdir(struct inode *dip, struct 
 		goto out;
 	}
 
-	if ((rc = get_UCSname(&dname, dentry, JFS_SBI(dip->i_sb)->nls_tab))) {
+	if ((rc = get_UCSname(&dname, dentry))) {
 		goto out;
 	}
 
@@ -451,7 +451,7 @@ int jfs_unlink(struct inode *dip, struct
 
 	jfs_info("jfs_unlink: dip:0x%p name:%s", dip, dentry->d_name.name);
 
-	if ((rc = get_UCSname(&dname, dentry, JFS_SBI(dip->i_sb)->nls_tab)))
+	if ((rc = get_UCSname(&dname, dentry)))
 		goto out;
 
 	IWRITE_LOCK(ip);
@@ -786,7 +786,7 @@ int jfs_link(struct dentry *old_dentry,
 	/*
 	 * scan parent directory for entry/freespace
 	 */
-	if ((rc = get_UCSname(&dname, dentry, JFS_SBI(ip->i_sb)->nls_tab)))
+	if ((rc = get_UCSname(&dname, dentry)))
 		goto out;
 
 	if ((rc = dtSearch(dir, &dname, &ino, &btstack, JFS_CREATE)))
@@ -866,7 +866,7 @@ int jfs_symlink(struct inode *dip, struc
 	 * (dtSearch() returns parent directory page pinned)
 	 */
 
-	if ((rc = get_UCSname(&dname, dentry, JFS_SBI(dip->i_sb)->nls_tab)))
+	if ((rc = get_UCSname(&dname, dentry)))
 		goto out1;
 
 	/*
@@ -1069,12 +1069,10 @@ int jfs_rename(struct inode *old_dir, st
 	old_ip = old_dentry->d_inode;
 	new_ip = new_dentry->d_inode;
 
-	if ((rc = get_UCSname(&old_dname, old_dentry,
-			      JFS_SBI(old_dir->i_sb)->nls_tab)))
+	if ((rc = get_UCSname(&old_dname, old_dentry)))
 		goto out1;
 
-	if ((rc = get_UCSname(&new_dname, new_dentry,
-			      JFS_SBI(old_dir->i_sb)->nls_tab)))
+	if ((rc = get_UCSname(&new_dname, new_dentry)))
 		goto out2;
 
 	/*
@@ -1329,7 +1327,7 @@ int jfs_mknod(struct inode *dir, struct 
 
 	jfs_info("jfs_mknod: %s", dentry->d_name.name);
 
-	if ((rc = get_UCSname(&dname, dentry, JFS_SBI(dir->i_sb)->nls_tab)))
+	if ((rc = get_UCSname(&dname, dentry)))
 		goto out;
 
 	ip = ialloc(dir, mode);
@@ -1411,8 +1409,7 @@ static struct dentry *jfs_lookup(struct 
 	else if (strcmp(name, "..") == 0)
 		inum = PARENT(dip);
 	else {
-		if ((rc =
-		     get_UCSname(&key, dentry, JFS_SBI(dip->i_sb)->nls_tab)))
+		if ((rc = get_UCSname(&key, dentry)))
 			return ERR_PTR(rc);
 		rc = dtSearch(dip, &key, &inum, &btstack, JFS_LOOKUP);
 		free_UCSname(&key);
--- diff/fs/jfs/super.c	2004-02-09 10:36:12.000000000 +0000
+++ source/fs/jfs/super.c	2004-02-23 13:56:46.000000000 +0000
@@ -195,7 +195,8 @@ static void jfs_put_super(struct super_b
 	rc = jfs_umount(sb);
 	if (rc)
 		jfs_err("jfs_umount failed with return code %d", rc);
-	unload_nls(sbi->nls_tab);
+	if (sbi->nls_tab)
+		unload_nls(sbi->nls_tab);
 	sbi->nls_tab = NULL;
 
 	kfree(sbi);
@@ -435,9 +436,6 @@ static int jfs_fill_super(struct super_b
 	if (!sb->s_root)
 		goto out_no_root;
 
-	if (!sbi->nls_tab)
-		sbi->nls_tab = load_nls_default();
-
 	/* logical blocks are represented by 40 bits in pxd_t, etc. */
 	sb->s_maxbytes = ((u64) sb->s_blocksize) << 40;
 #if BITS_PER_LONG == 32
--- diff/fs/namei.c	2004-02-18 08:54:12.000000000 +0000
+++ source/fs/namei.c	2004-02-23 13:56:46.000000000 +0000
@@ -190,7 +190,8 @@ int vfs_permission(struct inode * inode,
 	 * Read/write DACs are always overridable.
 	 * Executable DACs are overridable if at least one exec bit is set.
 	 */
-	if ((mask & (MAY_READ|MAY_WRITE)) || (inode->i_mode & S_IXUGO))
+	if (!(mask & MAY_EXEC) ||
+	    (inode->i_mode & S_IXUGO) || S_ISDIR(inode->i_mode))
 		if (capable(CAP_DAC_OVERRIDE))
 			return 0;
 
--- diff/fs/namespace.c	2004-02-18 08:54:12.000000000 +0000
+++ source/fs/namespace.c	2004-02-23 13:56:46.000000000 +0000
@@ -24,7 +24,15 @@
 #include <asm/uaccess.h>
 
 extern int __init init_rootfs(void);
+
+#ifdef CONFIG_SYSFS
 extern int __init sysfs_init(void);
+#else
+static inline int sysfs_init(void)
+{
+	return 0;
+}
+#endif
 
 /* spinlock for vfsmount related operations, inplace of dcache_lock */
 spinlock_t vfsmount_lock __cacheline_aligned_in_smp = SPIN_LOCK_UNLOCKED;
--- diff/fs/nfs/dir.c	2004-02-18 08:54:12.000000000 +0000
+++ source/fs/nfs/dir.c	2004-02-23 13:56:46.000000000 +0000
@@ -139,11 +139,13 @@ int nfs_readdir_filler(nfs_readdir_descr
 	struct file	*file = desc->file;
 	struct inode	*inode = file->f_dentry->d_inode;
 	struct rpc_cred	*cred = nfs_file_cred(file);
+	unsigned long	timestamp;
 	int		error;
 
 	dfprintk(VFS, "NFS: nfs_readdir_filler() reading cookie %Lu into page %lu.\n", (long long)desc->entry->cookie, page->index);
 
  again:
+	timestamp = jiffies;
 	error = NFS_PROTO(inode)->readdir(file->f_dentry, cred, desc->entry->cookie, page,
 					  NFS_SERVER(inode)->dtsize, desc->plus);
 	if (error < 0) {
@@ -157,18 +159,21 @@ int nfs_readdir_filler(nfs_readdir_descr
 		goto error;
 	}
 	SetPageUptodate(page);
+	NFS_FLAGS(inode) |= NFS_INO_INVALID_ATIME;
 	/* Ensure consistent page alignment of the data.
 	 * Note: assumes we have exclusive access to this mapping either
 	 *	 throught inode->i_sem or some other mechanism.
 	 */
-	if (page->index == 0)
+	if (page->index == 0) {
 		invalidate_inode_pages(inode->i_mapping);
+		NFS_I(inode)->readdir_timestamp = timestamp;
+	}
 	unlock_page(page);
 	return 0;
  error:
 	SetPageError(page);
 	unlock_page(page);
-	invalidate_inode_pages(inode->i_mapping);
+	nfs_zap_caches(inode);
 	desc->error = error;
 	return -EIO;
 }
@@ -381,6 +386,7 @@ int uncached_readdir(nfs_readdir_descrip
 						page,
 						NFS_SERVER(inode)->dtsize,
 						desc->plus);
+	NFS_FLAGS(inode) |= NFS_INO_INVALID_ATIME;
 	desc->page = page;
 	desc->ptr = kmap(page);		/* matching kunmap in nfs_do_filldir */
 	if (desc->error >= 0) {
@@ -459,7 +465,15 @@ static int nfs_readdir(struct file *filp
 			}
 			res = 0;
 			break;
-		} else if (res < 0)
+		}
+		if (res == -ETOOSMALL && desc->plus) {
+			NFS_FLAGS(inode) &= ~NFS_INO_ADVISE_RDPLUS;
+			nfs_zap_caches(inode);
+			desc->plus = 0;
+			desc->entry->eof = 0;
+			continue;
+		}
+		if (res < 0)
 			break;
 
 		res = nfs_do_filldir(desc, dirent, filldir);
@@ -481,14 +495,19 @@ static int nfs_readdir(struct file *filp
  * In the case it has, we assume that the dentries are untrustworthy
  * and may need to be looked up again.
  */
-static inline
-int nfs_check_verifier(struct inode *dir, struct dentry *dentry)
+static inline int nfs_check_verifier(struct inode *dir, struct dentry *dentry)
 {
 	if (IS_ROOT(dentry))
 		return 1;
-	if (nfs_revalidate_inode(NFS_SERVER(dir), dir))
+	if ((NFS_FLAGS(dir) & NFS_INO_INVALID_ATTR) != 0
+			|| nfs_attribute_timeout(dir))
 		return 0;
-	return time_after(dentry->d_time, NFS_MTIME_UPDATE(dir));
+	return nfs_verify_change_attribute(dir, (unsigned long)dentry->d_fsdata);
+}
+
+static inline void nfs_set_verifier(struct dentry * dentry, unsigned long verf)
+{
+	dentry->d_fsdata = (void *)verf;
 }
 
 /*
@@ -528,9 +547,7 @@ int nfs_neg_need_reval(struct inode *dir
 	/* Don't revalidate a negative dentry if we're creating a new file */
 	if ((ndflags & LOOKUP_CREATE) && !(ndflags & LOOKUP_CONTINUE))
 		return 0;
-	if (!nfs_check_verifier(dir, dentry))
-		return 1;
-	return time_after(jiffies, dentry->d_time + NFS_ATTRTIMEO(dir));
+	return !nfs_check_verifier(dir, dentry);
 }
 
 /*
@@ -552,6 +569,7 @@ static int nfs_lookup_revalidate(struct 
 	int error;
 	struct nfs_fh fhandle;
 	struct nfs_fattr fattr;
+	unsigned long verifier;
 	int isopen = 0;
 
 	parent = dget_parent(dentry);
@@ -574,6 +592,9 @@ static int nfs_lookup_revalidate(struct 
 		goto out_bad;
 	}
 
+	/* Revalidate parent directory attribute cache */
+	nfs_revalidate_inode(NFS_SERVER(dir), dir);
+
 	/* Force a full look up iff the parent directory has changed */
 	if (nfs_check_verifier(dir, dentry)) {
 		if (nfs_lookup_verify_inode(inode, isopen))
@@ -581,6 +602,12 @@ static int nfs_lookup_revalidate(struct 
 		goto out_valid;
 	}
 
+	/*
+	 * Note: we're not holding inode->i_sem and so may be racing with
+	 * operations that change the directory. We therefore save the
+	 * change attribute *before* we do the RPC call.
+	 */
+	verifier = nfs_save_change_attribute(dir);
 	error = nfs_cached_lookup(dir, dentry, &fhandle, &fattr);
 	if (!error) {
 		if (memcmp(NFS_FH(inode), &fhandle, sizeof(struct nfs_fh))!= 0)
@@ -603,6 +630,7 @@ static int nfs_lookup_revalidate(struct 
 
  out_valid_renew:
 	nfs_renew_times(dentry);
+	nfs_set_verifier(dentry, verifier);
  out_valid:
 	unlock_kernel();
 	dput(parent);
@@ -693,6 +721,8 @@ static struct dentry *nfs_lookup(struct 
 	dentry->d_op = NFS_PROTO(dir)->dentry_ops;
 
 	lock_kernel();
+	/* Revalidate parent directory attribute cache */
+	nfs_revalidate_inode(NFS_SERVER(dir), dir);
 
 	/* If we're doing an exclusive create, optimize away the lookup */
 	if (nfs_is_exclusive_create(dir, nd))
@@ -715,6 +745,7 @@ no_entry:
 	error = 0;
 	d_add(dentry, inode);
 	nfs_renew_times(dentry);
+	nfs_set_verifier(dentry, nfs_save_change_attribute(dir));
 out_unlock:
 	unlock_kernel();
 out:
@@ -768,7 +799,15 @@ static struct dentry *nfs_atomic_lookup(
 
 	/* Open the file on the server */
 	lock_kernel();
-	inode = nfs4_atomic_open(dir, dentry, nd);
+	/* Revalidate parent directory attribute cache */
+	nfs_revalidate_inode(NFS_SERVER(dir), dir);
+
+	if (nd->intent.open.flags & O_CREAT) {
+		nfs_begin_data_update(dir);
+		inode = nfs4_atomic_open(dir, dentry, nd);
+		nfs_end_data_update(dir);
+	} else
+		inode = nfs4_atomic_open(dir, dentry, nd);
 	unlock_kernel();
 	if (IS_ERR(inode)) {
 		error = PTR_ERR(inode);
@@ -790,6 +829,7 @@ static struct dentry *nfs_atomic_lookup(
 no_entry:
 	d_add(dentry, inode);
 	nfs_renew_times(dentry);
+	nfs_set_verifier(dentry, nfs_save_change_attribute(dir));
 out:
 	BUG_ON(error > 0);
 	return ERR_PTR(error);
@@ -801,13 +841,16 @@ static int nfs_open_revalidate(struct de
 {
 	struct dentry *parent = NULL;
 	struct inode *inode = dentry->d_inode;
+	struct inode *dir;
+	unsigned long verifier;
 	int openflags, ret = 0;
 
 	/* NFS only supports OPEN for regular files */
 	if (inode && !S_ISREG(inode->i_mode))
 		goto no_open;
 	parent = dget_parent(dentry);
-	if (!is_atomic_open(parent->d_inode, nd))
+	dir = parent->d_inode;
+	if (!is_atomic_open(dir, nd))
 		goto no_open;
 	openflags = nd->intent.open.flags;
 	if (openflags & O_CREAT) {
@@ -821,8 +864,16 @@ static int nfs_open_revalidate(struct de
 	/* We can't create new files, or truncate existing ones here */
 	openflags &= ~(O_CREAT|O_TRUNC);
 
+	/*
+	 * Note: we're not holding inode->i_sem and so may be racing with
+	 * operations that change the directory. We therefore save the
+	 * change attribute *before* we do the RPC call.
+	 */
 	lock_kernel();
-	ret = nfs4_open_revalidate(parent->d_inode, dentry, openflags);
+	verifier = nfs_save_change_attribute(dir);
+	ret = nfs4_open_revalidate(dir, dentry, openflags);
+	if (!ret)
+		nfs_set_verifier(dentry, verifier);
 	unlock_kernel();
 out:
 	dput(parent);
@@ -869,15 +920,20 @@ int nfs_cached_lookup(struct inode *dir,
 	struct nfs_server *server;
 	struct nfs_entry entry;
 	struct page *page;
-	unsigned long timestamp = NFS_MTIME_UPDATE(dir);
+	unsigned long timestamp;
 	int res;
 
 	if (!NFS_USE_READDIRPLUS(dir))
 		return -ENOENT;
 	server = NFS_SERVER(dir);
-	if (server->flags & NFS_MOUNT_NOAC)
+	/* Don't use readdirplus unless the cache is stable */
+	if ((server->flags & NFS_MOUNT_NOAC) != 0
+			|| nfs_caches_unstable(dir)
+			|| nfs_attribute_timeout(dir))
 		return -ENOENT;
-	nfs_revalidate_inode(server, dir);
+	if ((NFS_FLAGS(dir) & (NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA)) != 0)
+		return -ENOENT;
+	timestamp = NFS_I(dir)->readdir_timestamp;
 
 	entry.fh = fh;
 	entry.fattr = fattr;
@@ -931,9 +987,10 @@ static int nfs_instantiate(struct dentry
 	if (inode) {
 		d_instantiate(dentry, inode);
 		nfs_renew_times(dentry);
-		error = 0;
+		nfs_set_verifier(dentry, nfs_save_change_attribute(dentry->d_parent->d_inode));
+		return 0;
 	}
-	return error;
+	error = -ENOMEM;
 out_err:
 	d_drop(dentry);
 	return error;
@@ -969,11 +1026,13 @@ static int nfs_create(struct inode *dir,
 	 * does not pass the create flags.
 	 */
 	lock_kernel();
-	nfs_zap_caches(dir);
+	nfs_begin_data_update(dir);
 	inode = NFS_PROTO(dir)->create(dir, &dentry->d_name, &attr, open_flags);
+	nfs_end_data_update(dir);
 	if (!IS_ERR(inode)) {
 		d_instantiate(dentry, inode);
 		nfs_renew_times(dentry);
+		nfs_set_verifier(dentry, nfs_save_change_attribute(dir));
 		error = 0;
 	} else {
 		error = PTR_ERR(inode);
@@ -1004,9 +1063,10 @@ nfs_mknod(struct inode *dir, struct dent
 	attr.ia_valid = ATTR_MODE;
 
 	lock_kernel();
-	nfs_zap_caches(dir);
+	nfs_begin_data_update(dir);
 	error = NFS_PROTO(dir)->mknod(dir, &dentry->d_name, &attr, rdev,
 					&fhandle, &fattr);
+	nfs_end_data_update(dir);
 	if (!error)
 		error = nfs_instantiate(dentry, &fhandle, &fattr);
 	else
@@ -1041,9 +1101,10 @@ static int nfs_mkdir(struct inode *dir, 
 	 */
 	d_drop(dentry);
 #endif
-	nfs_zap_caches(dir);
+	nfs_begin_data_update(dir);
 	error = NFS_PROTO(dir)->mkdir(dir, &dentry->d_name, &attr, &fhandle,
 					&fattr);
+	nfs_end_data_update(dir);
 	if (!error)
 		error = nfs_instantiate(dentry, &fhandle, &fattr);
 	else
@@ -1060,10 +1121,12 @@ static int nfs_rmdir(struct inode *dir, 
 		dir->i_ino, dentry->d_name.name);
 
 	lock_kernel();
-	nfs_zap_caches(dir);
+	nfs_begin_data_update(dir);
 	error = NFS_PROTO(dir)->rmdir(dir, &dentry->d_name);
-	if (!error)
+	/* Ensure the VFS deletes this inode */
+	if (error == 0 && dentry->d_inode != NULL)
 		dentry->d_inode->i_nlink = 0;
+	nfs_end_data_update(dir);
 	unlock_kernel();
 
 	return error;
@@ -1119,12 +1182,21 @@ dentry->d_parent->d_name.name, dentry->d
 			goto out;
 	} while(sdentry->d_inode != NULL); /* need negative lookup */
 
-	nfs_zap_caches(dir);
 	qsilly.name = silly;
 	qsilly.len  = strlen(silly);
-	error = NFS_PROTO(dir)->rename(dir, &dentry->d_name, dir, &qsilly);
+	nfs_begin_data_update(dir);
+	if (dentry->d_inode) {
+		nfs_begin_data_update(dentry->d_inode);
+		error = NFS_PROTO(dir)->rename(dir, &dentry->d_name,
+				dir, &qsilly);
+		nfs_end_data_update(dentry->d_inode);
+	} else
+		error = NFS_PROTO(dir)->rename(dir, &dentry->d_name,
+				dir, &qsilly);
+	nfs_end_data_update(dir);
 	if (!error) {
 		nfs_renew_times(dentry);
+		nfs_set_verifier(dentry, nfs_save_change_attribute(dir));
 		d_move(dentry, sdentry);
 		error = nfs_async_unlink(dentry);
  		/* If we return 0 we don't unlink */
@@ -1156,14 +1228,17 @@ static int nfs_safe_remove(struct dentry
 		goto out;
 	}
 
-	nfs_zap_caches(dir);
-	if (inode)
-		NFS_CACHEINV(inode);
-	error = NFS_PROTO(dir)->remove(dir, &dentry->d_name);
-	if (error < 0)
-		goto out;
-	if (inode)
-		inode->i_nlink--;
+	nfs_begin_data_update(dir);
+	if (inode != NULL) {
+		nfs_begin_data_update(inode);
+		error = NFS_PROTO(dir)->remove(dir, &dentry->d_name);
+		/* The VFS may want to delete this inode */
+		if (error == 0)
+			inode->i_nlink--;
+		nfs_end_data_update(inode);
+	} else
+		error = NFS_PROTO(dir)->remove(dir, &dentry->d_name);
+	nfs_end_data_update(dir);
 out:
 	return error;
 }
@@ -1198,9 +1273,10 @@ static int nfs_unlink(struct inode *dir,
 	spin_unlock(&dentry->d_lock);
 	spin_unlock(&dcache_lock);
 	error = nfs_safe_remove(dentry);
-	if (!error)
+	if (!error) {
 		nfs_renew_times(dentry);
-	else if (need_rehash)
+		nfs_set_verifier(dentry, nfs_save_change_attribute(dir));
+	} else if (need_rehash)
 		d_rehash(dentry);
 	unlock_kernel();
 	return error;
@@ -1247,9 +1323,10 @@ dentry->d_parent->d_name.name, dentry->d
 	qsymname.len  = strlen(symname);
 
 	lock_kernel();
-	nfs_zap_caches(dir);
+	nfs_begin_data_update(dir);
 	error = NFS_PROTO(dir)->symlink(dir, &dentry->d_name, &qsymname,
 					  &attr, &sym_fh, &sym_attr);
+	nfs_end_data_update(dir);
 	if (!error) {
 		error = nfs_instantiate(dentry, &sym_fh, &sym_attr);
 	} else {
@@ -1281,9 +1358,12 @@ nfs_link(struct dentry *old_dentry, stru
 	 */
 	lock_kernel();
 	d_drop(dentry);
-	nfs_zap_caches(dir);
-	NFS_CACHEINV(inode);
+
+	nfs_begin_data_update(dir);
+	nfs_begin_data_update(inode);
 	error = NFS_PROTO(dir)->link(inode, dir, &dentry->d_name);
+	nfs_end_data_update(inode);
+	nfs_end_data_update(dir);
 	unlock_kernel();
 	return error;
 }
@@ -1388,16 +1468,23 @@ go_ahead:
 	if (new_inode)
 		d_delete(new_dentry);
 
-	nfs_zap_caches(new_dir);
-	nfs_zap_caches(old_dir);
+	nfs_begin_data_update(old_dir);
+	nfs_begin_data_update(new_dir);
+	nfs_begin_data_update(old_inode);
 	error = NFS_PROTO(old_dir)->rename(old_dir, &old_dentry->d_name,
 					   new_dir, &new_dentry->d_name);
+	nfs_end_data_update(old_inode);
+	nfs_end_data_update(new_dir);
+	nfs_end_data_update(old_dir);
 out:
 	if (rehash)
 		d_rehash(rehash);
-	if (!error && !S_ISDIR(old_inode->i_mode))
-		d_move(old_dentry, new_dentry);
-	nfs_renew_times(new_dentry);
+	if (!error) {
+		if (!S_ISDIR(old_inode->i_mode))
+			d_move(old_dentry, new_dentry);
+		nfs_renew_times(new_dentry);
+		nfs_set_verifier(new_dentry, nfs_save_change_attribute(new_dir));
+	}
 
 	/* new dentry created? */
 	if (dentry)
@@ -1451,7 +1538,8 @@ nfs_permission(struct inode *inode, int 
 
 	cred = rpcauth_lookupcred(NFS_CLIENT(inode)->cl_auth, 0);
 	if (cache->cred == cred
-	    && time_before(jiffies, cache->jiffies + NFS_ATTRTIMEO(inode))) {
+	    && time_before(jiffies, cache->jiffies + NFS_ATTRTIMEO(inode))
+	    && !(NFS_FLAGS(inode) & NFS_INO_INVALID_ATTR)) {
 		if (!(res = cache->err)) {
 			/* Is the mask a subset of an accepted mask? */
 			if ((cache->mask & mask) == mask)
--- diff/fs/nfs/direct.c	2003-10-27 09:20:39.000000000 +0000
+++ source/fs/nfs/direct.c	2004-02-23 13:56:46.000000000 +0000
@@ -269,6 +269,7 @@ nfs_direct_write_seg(struct inode *inode
 	if (IS_SYNC(inode) || NFS_PROTO(inode)->version == 2 || count <= wsize)
 		wdata.args.stable = NFS_FILE_SYNC;
 
+	nfs_begin_data_update(inode);
 retry:
 	need_commit = 0;
 	tot_bytes = 0;
@@ -334,6 +335,8 @@ retry:
 						VERF_SIZE) != 0)
 			goto sync_retry;
 	}
+	nfs_end_data_update(inode);
+	NFS_FLAGS(inode) |= NFS_INO_INVALID_DATA;
 
 	return tot_bytes;
 
--- diff/fs/nfs/file.c	2004-02-18 08:54:12.000000000 +0000
+++ source/fs/nfs/file.c	2004-02-23 13:56:46.000000000 +0000
@@ -104,11 +104,16 @@ nfs_file_flush(struct file *file)
 
 	dfprintk(VFS, "nfs: flush(%s/%ld)\n", inode->i_sb->s_id, inode->i_ino);
 
+	if ((file->f_mode & FMODE_WRITE) == 0)
+		return 0;
 	lock_kernel();
-	status = nfs_wb_file(inode, file);
+	/* Ensure that data+attribute caches are up to date after close() */
+	status = nfs_wb_all(inode);
 	if (!status) {
 		status = file->f_error;
 		file->f_error = 0;
+		if (!status)
+			__nfs_revalidate_inode(NFS_SERVER(inode), inode);
 	}
 	unlock_kernel();
 	return status;
--- diff/fs/nfs/inode.c	2004-02-18 08:54:12.000000000 +0000
+++ source/fs/nfs/inode.c	2004-02-23 13:56:46.000000000 +0000
@@ -53,8 +53,8 @@
  */
 #define NFS_MAX_READAHEAD	RPC_MAXREQS
 
-void nfs_zap_caches(struct inode *);
 static void nfs_invalidate_inode(struct inode *);
+static int nfs_update_inode(struct inode *, struct nfs_fattr *, unsigned long);
 
 static struct inode *nfs_alloc_inode(struct super_block *sb);
 static void nfs_destroy_inode(struct inode *);
@@ -151,6 +151,7 @@ nfs_clear_inode(struct inode *inode)
 	cred = nfsi->cache_access.cred;
 	if (cred)
 		put_rpccred(cred);
+	BUG_ON(atomic_read(&nfsi->data_updates) != 0);
 }
 
 void
@@ -300,18 +301,25 @@ nfs_sb_init(struct super_block *sb, rpc_
 	sb->s_magic      = NFS_SUPER_MAGIC;
 
 	/* Did getting the root inode fail? */
-	if (nfs_get_root(&root_inode, authflavor, sb, &server->fh) < 0)
-		goto out_no_root;
+	if (nfs_get_root(&root_inode, authflavor, sb, &server->fh) < 0) {
+		printk("nfs_read_super: get root inode failed\n");
+		goto out;
+	}
 	sb->s_root = d_alloc_root(root_inode);
-	if (!sb->s_root)
-		goto out_no_root;
+	if (!sb->s_root) {
+		printk("nfs_read_super: out of memory\n");
+		iput(root_inode);
+		goto out;
+	}
 
 	sb->s_root->d_op = server->rpc_ops->dentry_ops;
 
 	/* Get some general file system info */
         if (server->rpc_ops->fsinfo(server, &server->fh, &fsinfo) < 0) {
 		printk(KERN_NOTICE "NFS: cannot retrieve file system info.\n");
-		goto out_no_root;
+		dput(sb->s_root);
+		sb->s_root = NULL;
+		goto out;
         }
 	if (server->namelen == 0 &&
 	    server->rpc_ops->pathconf(server, &server->fh, &pathinfo) >= 0)
@@ -364,17 +372,16 @@ nfs_sb_init(struct super_block *sb, rpc_
 	if (sb->s_maxbytes > MAX_LFS_FILESIZE) 
 		sb->s_maxbytes = MAX_LFS_FILESIZE; 
 
+	server->wactive = 0;
+	init_waitqueue_head(&server->writerq);
+
 	/* We're airborne Set socket buffersize */
 	rpc_setbufsize(server->client, server->wsize + 100, server->rsize + 100);
 	return 0;
+
 	/* Yargs. It didn't work out. */
-out_free_all:
-	if (root_inode)
-		iput(root_inode);
+out:
 	return -EINVAL;
-out_no_root:
-	printk("nfs_read_super: get root inode failed\n");
-	goto out_free_all;
 }
 
 /*
@@ -627,13 +634,17 @@ static int nfs_show_options(struct seq_f
 void
 nfs_zap_caches(struct inode *inode)
 {
+	struct nfs_inode *nfsi = NFS_I(inode);
+	int mode = inode->i_mode;
+
 	NFS_ATTRTIMEO(inode) = NFS_MINATTRTIMEO(inode);
 	NFS_ATTRTIMEO_UPDATE(inode) = jiffies;
 
-	invalidate_remote_inode(inode);
-
 	memset(NFS_COOKIEVERF(inode), 0, sizeof(NFS_COOKIEVERF(inode)));
-	NFS_CACHEINV(inode);
+	if (S_ISREG(mode) || S_ISDIR(mode) || S_ISLNK(mode))
+		nfsi->flags |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA;
+	else
+		nfsi->flags |= NFS_INO_INVALID_ATTR;
 }
 
 /*
@@ -673,9 +684,6 @@ nfs_find_actor(struct inode *inode, void
 		return 0;
 	if (is_bad_inode(inode))
 		return 0;
-	/* Force an attribute cache update if inode->i_count == 0 */
-	if (!atomic_read(&inode->i_count))
-		NFS_CACHEINV(inode);
 	return 1;
 }
 
@@ -729,7 +737,7 @@ nfs_fhget(struct super_block *sb, struct
 		inode->i_ino = hash;
 
 		/* We can't support update_atime(), since the server will reset it */
-		inode->i_flags |= S_NOATIME;
+		inode->i_flags |= S_NOATIME|S_NOCMTIME;
 		inode->i_mode = fattr->mode;
 		/* Why so? Because we want revalidate for devices/FIFOs, and
 		 * that's precisely what we have in nfs_file_inode_operations.
@@ -754,10 +762,6 @@ nfs_fhget(struct super_block *sb, struct
 		inode->i_atime = fattr->atime;
 		inode->i_mtime = fattr->mtime;
 		inode->i_ctime = fattr->ctime;
-		nfsi->read_cache_ctime = fattr->ctime;
-		nfsi->read_cache_mtime = fattr->mtime;
-		nfsi->cache_mtime_jiffies = fattr->timestamp;
-		nfsi->read_cache_isize = fattr->size;
 		if (fattr->valid & NFS_ATTR_FATTR_V4)
 			nfsi->change_attr = fattr->change_attr;
 		inode->i_size = nfs_size_to_loff_t(fattr->size);
@@ -804,70 +808,50 @@ nfs_setattr(struct dentry *dentry, struc
 	struct nfs_fattr fattr;
 	int error;
 
+	if (attr->ia_valid & ATTR_SIZE) {
+		if (!S_ISREG(inode->i_mode) || attr->ia_size == i_size_read(inode))
+			attr->ia_valid &= ~ATTR_SIZE;
+	}
+
 	/* Optimization: if the end result is no change, don't RPC */
 	attr->ia_valid &= NFS_VALID_ATTRS;
 	if (attr->ia_valid == 0)
 		return 0;
 
 	lock_kernel();
-
-	/*
-	 * Make sure the inode is up-to-date.
-	 */
-	error = nfs_revalidate_inode(NFS_SERVER(inode),inode);
-	if (error) {
-#ifdef NFS_PARANOIA
-printk("nfs_setattr: revalidate failed, error=%d\n", error);
-#endif
-		goto out;
+	nfs_begin_data_update(inode);
+	/* Write all dirty data if we're changing file permissions or size */
+	if ((attr->ia_valid & (ATTR_MODE|ATTR_UID|ATTR_GID|ATTR_SIZE)) != 0) {
+		if (filemap_fdatawrite(inode->i_mapping) == 0)
+			filemap_fdatawait(inode->i_mapping);
+		nfs_wb_all(inode);
 	}
-
-	if (!S_ISREG(inode->i_mode)) {
-		attr->ia_valid &= ~ATTR_SIZE;
-		if (attr->ia_valid == 0)
-			goto out;
-	} else {
-		filemap_fdatawrite(inode->i_mapping);
-		error = nfs_wb_all(inode);
-		filemap_fdatawait(inode->i_mapping);
-		if (error)
-			goto out;
-		/* Optimize away unnecessary truncates */
-		if ((attr->ia_valid & ATTR_SIZE) && i_size_read(inode) == attr->ia_size)
-			attr->ia_valid &= ~ATTR_SIZE;
-	}
-	if (!attr->ia_valid)
-		goto out;
-
 	error = NFS_PROTO(inode)->setattr(dentry, &fattr, attr);
-	if (error)
-		goto out;
-	/*
-	 * If we changed the size or mtime, update the inode
-	 * now to avoid invalidating the page cache.
-	 */
-	if (attr->ia_valid & ATTR_SIZE) {
-		if (attr->ia_size != fattr.size)
-			printk("nfs_setattr: attr=%Ld, fattr=%Ld??\n",
-			       (long long) attr->ia_size, (long long)fattr.size);
-		vmtruncate(inode, attr->ia_size);
+	if (error == 0) {
+		nfs_refresh_inode(inode, &fattr);
+		if ((attr->ia_valid & ATTR_MODE) != 0) {
+			int mode;
+			mode = inode->i_mode & ~S_IALLUGO;
+			mode |= attr->ia_mode & S_IALLUGO;
+			inode->i_mode = mode;
+		}
+		if ((attr->ia_valid & ATTR_UID) != 0)
+			inode->i_uid = attr->ia_uid;
+		if ((attr->ia_valid & ATTR_GID) != 0)
+			inode->i_gid = attr->ia_gid;
+		if ((attr->ia_valid & ATTR_SIZE) != 0) {
+			inode->i_size = attr->ia_size;
+			vmtruncate(inode, attr->ia_size);
+		}
 	}
-
-	/*
-	 * If we changed the size or mtime, update the inode
-	 * now to avoid invalidating the page cache.
-	 */
-	if (!(fattr.valid & NFS_ATTR_WCC)) {
-		struct nfs_inode *nfsi = NFS_I(inode);
-		fattr.pre_size = nfsi->read_cache_isize;
-		fattr.pre_mtime = nfsi->read_cache_mtime;
-		fattr.pre_ctime = nfsi->read_cache_ctime;
-		fattr.valid |= NFS_ATTR_WCC;
-	}
-	/* Force an attribute cache update */
-	NFS_CACHEINV(inode);
-	error = nfs_refresh_inode(inode, &fattr);
-out:
+	if ((attr->ia_valid & (ATTR_MODE|ATTR_UID|ATTR_GID)) != 0) {
+		struct rpc_cred **cred = &NFS_I(inode)->cache_access.cred;
+		if (*cred) {
+			put_rpccred(*cred);
+			*cred = NULL;
+		}
+	}
+	nfs_end_data_update(inode);
 	unlock_kernel();
 	return error;
 }
@@ -895,7 +879,19 @@ nfs_wait_on_inode(struct inode *inode, i
 int nfs_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat)
 {
 	struct inode *inode = dentry->d_inode;
-	int err = nfs_revalidate_inode(NFS_SERVER(inode), inode);
+	struct nfs_inode *nfsi = NFS_I(inode);
+	int need_atime = nfsi->flags & NFS_INO_INVALID_ATIME;
+	int err;
+
+	if (__IS_FLG(inode, MS_NOATIME))
+		need_atime = 0;
+	else if (__IS_FLG(inode, MS_NODIRATIME) && S_ISDIR(inode->i_mode))
+		need_atime = 0;
+	/* We may force a getattr if the user cares about atime */
+	if (need_atime)
+		err = __nfs_revalidate_inode(NFS_SERVER(inode), inode);
+	else
+		err = nfs_revalidate_inode(NFS_SERVER(inode), inode);
 	if (!err)
 		generic_fillattr(inode, stat);
 	return err;
@@ -930,8 +926,10 @@ int nfs_open(struct inode *inode, struct
 	auth = NFS_CLIENT(inode)->cl_auth;
 	cred = rpcauth_lookupcred(auth, 0);
 	filp->private_data = cred;
-	if (filp->f_mode & FMODE_WRITE)
+	if ((filp->f_mode & FMODE_WRITE) != 0) {
 		nfs_set_mmcred(inode, cred);
+		nfs_begin_data_update(inode);
+	}
 	return 0;
 }
 
@@ -940,6 +938,8 @@ int nfs_release(struct inode *inode, str
 	struct rpc_cred *cred;
 
 	lock_kernel();
+	if ((filp->f_mode & FMODE_WRITE) != 0)
+		nfs_end_data_update(inode);
 	cred = nfs_file_cred(filp);
 	if (cred)
 		put_rpccred(cred);
@@ -956,6 +956,9 @@ __nfs_revalidate_inode(struct nfs_server
 {
 	int		 status = -ESTALE;
 	struct nfs_fattr fattr;
+	struct nfs_inode *nfsi = NFS_I(inode);
+	unsigned long verifier;
+	unsigned int flags;
 
 	dfprintk(PAGECACHE, "NFS: revalidating (%s/%Ld)\n",
 		inode->i_sb->s_id, (long long)NFS_FILEID(inode));
@@ -965,23 +968,16 @@ __nfs_revalidate_inode(struct nfs_server
  		goto out_nowait;
 	if (NFS_STALE(inode) && inode != inode->i_sb->s_root->d_inode)
  		goto out_nowait;
-	if (NFS_FAKE_ROOT(inode)) {
-		dfprintk(VFS, "NFS: not revalidating fake root\n");
-		status = 0;
-		goto out_nowait;
-	}
 
 	while (NFS_REVALIDATING(inode)) {
 		status = nfs_wait_on_inode(inode, NFS_INO_REVALIDATING);
 		if (status < 0)
 			goto out_nowait;
-		if (time_before(jiffies,NFS_READTIME(inode)+NFS_ATTRTIMEO(inode))) {
-			status = NFS_STALE(inode) ? -ESTALE : 0;
-			goto out_nowait;
-		}
 	}
 	NFS_FLAGS(inode) |= NFS_INO_REVALIDATING;
 
+	/* Protect against RPC races by saving the change attribute */
+	verifier = nfs_save_change_attribute(inode);
 	status = NFS_PROTO(inode)->getattr(inode, &fattr);
 	if (status) {
 		dfprintk(PAGECACHE, "nfs_revalidate_inode: (%s/%Ld) getattr failed, error=%d\n",
@@ -995,13 +991,34 @@ __nfs_revalidate_inode(struct nfs_server
 		goto out;
 	}
 
-	status = nfs_refresh_inode(inode, &fattr);
+	status = nfs_update_inode(inode, &fattr, verifier);
 	if (status) {
 		dfprintk(PAGECACHE, "nfs_revalidate_inode: (%s/%Ld) refresh failed, error=%d\n",
 			 inode->i_sb->s_id,
 			 (long long)NFS_FILEID(inode), status);
 		goto out;
 	}
+	flags = nfsi->flags;
+	/*
+	 * We may need to keep the attributes marked as invalid if
+	 * we raced with nfs_end_attr_update().
+	 */
+	if (verifier == nfsi->cache_change_attribute)
+		nfsi->flags &= ~(NFS_INO_INVALID_ATTR|NFS_INO_INVALID_ATIME);
+	/* Do the page cache invalidation */
+	if (flags & NFS_INO_INVALID_DATA) {
+		if (S_ISREG(inode->i_mode)) {
+			if (filemap_fdatawrite(inode->i_mapping) == 0)
+				filemap_fdatawait(inode->i_mapping);
+			nfs_wb_all(inode);
+		}
+		nfsi->flags &= ~NFS_INO_INVALID_DATA;
+		invalidate_inode_pages2(inode->i_mapping);
+		memset(NFS_COOKIEVERF(inode), 0, sizeof(NFS_COOKIEVERF(inode)));
+		dfprintk(PAGECACHE, "NFS: (%s/%Ld) data cache invalidated\n",
+				inode->i_sb->s_id,
+				(long long)NFS_FILEID(inode));
+	}
 	dfprintk(PAGECACHE, "NFS: (%s/%Ld) revalidation complete\n",
 		inode->i_sb->s_id,
 		(long long)NFS_FILEID(inode));
@@ -1009,41 +1026,104 @@ __nfs_revalidate_inode(struct nfs_server
 	NFS_FLAGS(inode) &= ~NFS_INO_STALE;
 out:
 	NFS_FLAGS(inode) &= ~NFS_INO_REVALIDATING;
-	wake_up(&NFS_I(inode)->nfs_i_wait);
+	wake_up(&nfsi->nfs_i_wait);
  out_nowait:
 	unlock_kernel();
 	return status;
 }
 
-/*
- * nfs_fattr_obsolete - Test if attribute data is newer than cached data
- * @inode: inode
- * @fattr: attributes to test
+/**
+ * nfs_begin_data_update
+ * @inode - pointer to inode
+ * Declare that a set of operations will update file data on the server
+ */
+void nfs_begin_data_update(struct inode *inode)
+{
+	atomic_inc(&NFS_I(inode)->data_updates);
+}
+
+/**
+ * nfs_end_data_update
+ * @inode - pointer to inode
+ * Declare end of the operations that will update file data
+ */
+void nfs_end_data_update(struct inode *inode)
+{
+	struct nfs_inode *nfsi = NFS_I(inode);
+
+	if (atomic_dec_and_test(&nfsi->data_updates)) {
+		nfsi->cache_change_attribute ++;
+		/* Mark the attribute cache for revalidation */
+		nfsi->flags |= NFS_INO_INVALID_ATTR;
+		/* Directories and symlinks: invalidate page cache too */
+		if (S_ISDIR(inode->i_mode) || S_ISLNK(inode->i_mode))
+			nfsi->flags |= NFS_INO_INVALID_DATA;
+	}
+}
+
+/**
+ * nfs_refresh_inode - verify consistency of the inode attribute cache
+ * @inode - pointer to inode
+ * @fattr - updated attributes
  *
- * Avoid stuffing the attribute cache with obsolete information.
- * We always accept updates if the attribute cache timed out, or if
- * fattr->ctime is newer than our cached value.
- * If fattr->ctime matches the cached value, we still accept the update
- * if it increases the file size.
+ * Verifies the attribute cache. If we have just changed the attributes,
+ * so that fattr carries weak cache consistency data, then it may
+ * also update the ctime/mtime/change_attribute.
  */
-static inline
-int nfs_fattr_obsolete(struct inode *inode, struct nfs_fattr *fattr)
+int nfs_refresh_inode(struct inode *inode, struct nfs_fattr *fattr)
 {
 	struct nfs_inode *nfsi = NFS_I(inode);
-	long cdif;
+	loff_t cur_size, new_isize;
+	int data_unstable;
+
+	/* Are we in the process of updating data on the server? */
+	data_unstable = nfs_caches_unstable(inode);
 
-	if (time_after(jiffies, nfsi->read_cache_jiffies + nfsi->attrtimeo))
-		goto out_valid;
-	cdif = fattr->ctime.tv_sec - nfsi->read_cache_ctime.tv_sec;
-	if (cdif == 0)
-		cdif = fattr->ctime.tv_nsec - nfsi->read_cache_ctime.tv_nsec;
-	if (cdif > 0)
-		goto out_valid;
-	/* Ugh... */
-	if (cdif == 0 && fattr->size > nfsi->read_cache_isize)
-		goto out_valid;
-	return -1;
- out_valid:
+	if (fattr->valid & NFS_ATTR_FATTR_V4) {
+		if ((fattr->valid & NFS_ATTR_PRE_CHANGE) != 0
+				&& nfsi->change_attr == fattr->pre_change_attr)
+			nfsi->change_attr = fattr->change_attr;
+		if (!data_unstable && nfsi->change_attr != fattr->change_attr)
+			nfsi->flags |= NFS_INO_INVALID_ATTR;
+	}
+
+	if ((fattr->valid & NFS_ATTR_FATTR) == 0)
+		return 0;
+
+	/* Has the inode gone and changed behind our back? */
+	if (nfsi->fileid != fattr->fileid
+			|| (inode->i_mode & S_IFMT) != (fattr->mode & S_IFMT))
+		return -EIO;
+
+	cur_size = i_size_read(inode);
+ 	new_isize = nfs_size_to_loff_t(fattr->size);
+
+	/* If we have atomic WCC data, we may update some attributes */
+	if ((fattr->valid & NFS_ATTR_WCC) != 0) {
+		if (timespec_equal(&inode->i_ctime, &fattr->pre_ctime))
+			memcpy(&inode->i_ctime, &fattr->ctime, sizeof(inode->i_ctime));
+		if (timespec_equal(&inode->i_mtime, &fattr->pre_mtime))
+			memcpy(&inode->i_mtime, &fattr->mtime, sizeof(inode->i_mtime));
+	}
+
+	/* Verify a few of the more important attributes */
+	if (!data_unstable) {
+		if (!timespec_equal(&inode->i_mtime, &fattr->mtime)
+				|| cur_size != new_isize)
+			nfsi->flags |= NFS_INO_INVALID_ATTR;
+	} else if (S_ISREG(inode->i_mode) && new_isize > cur_size)
+			nfsi->flags |= NFS_INO_INVALID_ATTR;
+
+	/* Have any file permissions changed? */
+	if ((inode->i_mode & S_IALLUGO) != (fattr->mode & S_IALLUGO)
+			|| inode->i_uid != fattr->uid
+			|| inode->i_gid != fattr->gid)
+		nfsi->flags |= NFS_INO_INVALID_ATTR;
+
+	if (!timespec_equal(&inode->i_atime, &fattr->atime))
+		nfsi->flags |= NFS_INO_INVALID_ATIME;
+
+	nfsi->read_cache_jiffies = fattr->timestamp;
 	return 0;
 }
 
@@ -1059,20 +1139,22 @@ int nfs_fattr_obsolete(struct inode *ino
  *
  * A very similar scenario holds for the dir cache.
  */
-int
-__nfs_refresh_inode(struct inode *inode, struct nfs_fattr *fattr)
+static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr, unsigned long verifier)
 {
 	struct nfs_inode *nfsi = NFS_I(inode);
 	__u64		new_size;
 	loff_t		new_isize;
-	int		invalid = 0;
-	int		mtime_update = 0;
+	unsigned int	invalid = 0;
 	loff_t		cur_isize;
+	int data_unstable;
 
-	dfprintk(VFS, "NFS: refresh_inode(%s/%ld ct=%d info=0x%x)\n",
-			inode->i_sb->s_id, inode->i_ino,
+	dfprintk(VFS, "NFS: %s(%s/%ld ct=%d info=0x%x)\n",
+			__FUNCTION__, inode->i_sb->s_id, inode->i_ino,
 			atomic_read(&inode->i_count), fattr->valid);
 
+	if ((fattr->valid & NFS_ATTR_FATTR) == 0)
+		return 0;
+
 	/* First successful call after mount, fill real data. */
 	if (NFS_FAKE_ROOT(inode)) {
 		dfprintk(VFS, "NFS: updating fake root\n");
@@ -1081,43 +1163,49 @@ __nfs_refresh_inode(struct inode *inode,
 	}
 
 	if (nfsi->fileid != fattr->fileid) {
-		printk(KERN_ERR "nfs_refresh_inode: inode number mismatch\n"
+		printk(KERN_ERR "%s: inode number mismatch\n"
 		       "expected (%s/0x%Lx), got (%s/0x%Lx)\n",
+		       __FUNCTION__,
 		       inode->i_sb->s_id, (long long)nfsi->fileid,
 		       inode->i_sb->s_id, (long long)fattr->fileid);
 		goto out_err;
 	}
 
-	/* Throw out obsolete READDIRPLUS attributes */
-	if (time_before(fattr->timestamp, NFS_READTIME(inode)))
-		return 0;
 	/*
 	 * Make sure the inode's type hasn't changed.
 	 */
 	if ((inode->i_mode & S_IFMT) != (fattr->mode & S_IFMT))
 		goto out_changed;
 
-	new_size = fattr->size;
- 	new_isize = nfs_size_to_loff_t(fattr->size);
-
-	/* Avoid races */
-	if (nfs_fattr_obsolete(inode, fattr))
-		goto out_nochange;
-
 	/*
 	 * Update the read time so we don't revalidate too often.
 	 */
 	nfsi->read_cache_jiffies = fattr->timestamp;
 
-	/*
-	 * Note: NFS_CACHE_ISIZE(inode) reflects the state of the cache.
-	 *       NOT inode->i_size!!!
-	 */
-	if (nfsi->read_cache_isize != new_size) {
+	/* Are we racing with known updates of the metadata on the server? */
+	data_unstable = ! nfs_verify_change_attribute(inode, verifier);
+
+	/* Check if the file size agrees */
+	new_size = fattr->size;
+ 	new_isize = nfs_size_to_loff_t(fattr->size);
+	cur_isize = i_size_read(inode);
+	if (cur_isize != new_size) {
 #ifdef NFS_DEBUG_VERBOSE
 		printk(KERN_DEBUG "NFS: isize change on %s/%ld\n", inode->i_sb->s_id, inode->i_ino);
 #endif
-		invalid = 1;
+		/*
+		 * If we have pending writebacks, things can get
+		 * messy.
+		 */
+		if (S_ISREG(inode->i_mode) && data_unstable) {
+			if (new_isize > cur_isize) {
+				inode->i_size = new_isize;
+				invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA;
+			}
+		} else {
+			inode->i_size = new_isize;
+			invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA;
+		}
 	}
 
 	/*
@@ -1125,12 +1213,13 @@ __nfs_refresh_inode(struct inode *inode,
 	 *       can change this value in VFS without requiring a
 	 *	 cache revalidation.
 	 */
-	if (!timespec_equal(&nfsi->read_cache_mtime, &fattr->mtime)) {
+	if (!timespec_equal(&inode->i_mtime, &fattr->mtime)) {
+		memcpy(&inode->i_mtime, &fattr->mtime, sizeof(inode->i_mtime));
 #ifdef NFS_DEBUG_VERBOSE
 		printk(KERN_DEBUG "NFS: mtime change on %s/%ld\n", inode->i_sb->s_id, inode->i_ino);
 #endif
-		invalid = 1;
-		mtime_update = 1;
+		if (!data_unstable)
+			invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA;
 	}
 
 	if ((fattr->valid & NFS_ATTR_FATTR_V4)
@@ -1139,47 +1228,15 @@ __nfs_refresh_inode(struct inode *inode,
 		printk(KERN_DEBUG "NFS: change_attr change on %s/%ld\n",
 		       inode->i_sb->s_id, inode->i_ino);
 #endif
-		invalid = 1;
-	}
-
-	/* Check Weak Cache Consistency data.
-	 * If size and mtime match the pre-operation values, we can
-	 * assume that any attribute changes were caused by our NFS
-         * operation, so there's no need to invalidate the caches.
-         */
-	if ((fattr->valid & NFS_ATTR_PRE_CHANGE)
-	    && nfsi->change_attr == fattr->pre_change_attr) {
-		invalid = 0;
-	}
-	else if ((fattr->valid & NFS_ATTR_WCC)
-	    && nfsi->read_cache_isize == fattr->pre_size
-	    && timespec_equal(&nfsi->read_cache_mtime, &fattr->pre_mtime)) {
-		invalid = 0;
-	}
-
-	/*
-	 * If we have pending writebacks, things can get
-	 * messy.
-	 */
-	cur_isize = i_size_read(inode);
-	if (nfs_have_writebacks(inode) && new_isize < cur_isize)
-		new_isize = cur_isize;
-
-	nfsi->read_cache_ctime = fattr->ctime;
-	inode->i_ctime = fattr->ctime;
-	inode->i_atime = fattr->atime;
-
-	if (mtime_update) {
-		if (invalid)
-			nfsi->cache_mtime_jiffies = fattr->timestamp;
-		nfsi->read_cache_mtime = fattr->mtime;
-		inode->i_mtime = fattr->mtime;
+		nfsi->change_attr = fattr->change_attr;
+		if (!data_unstable)
+			invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA;
 	}
 
-	nfsi->read_cache_isize = new_size;
-	i_size_write(inode, new_isize);
+	memcpy(&inode->i_ctime, &fattr->ctime, sizeof(inode->i_ctime));
+	memcpy(&inode->i_atime, &fattr->atime, sizeof(inode->i_atime));
 
-	if (inode->i_mode != fattr->mode ||
+	if ((inode->i_mode & S_IALLUGO) != (fattr->mode & S_IALLUGO) ||
 	    inode->i_uid != fattr->uid ||
 	    inode->i_gid != fattr->gid) {
 		struct rpc_cred **cred = &NFS_I(inode)->cache_access.cred;
@@ -1187,11 +1244,9 @@ __nfs_refresh_inode(struct inode *inode,
 			put_rpccred(*cred);
 			*cred = NULL;
 		}
+		invalid |= NFS_INO_INVALID_ATTR;
 	}
 
-	if (fattr->valid & NFS_ATTR_FATTR_V4)
-		nfsi->change_attr = fattr->change_attr;
-
 	inode->i_mode = fattr->mode;
 	inode->i_nlink = fattr->nlink;
 	inode->i_uid = fattr->uid;
@@ -1207,31 +1262,30 @@ __nfs_refresh_inode(struct inode *inode,
  		inode->i_blocks = fattr->du.nfs2.blocks;
  		inode->i_blksize = fattr->du.nfs2.blocksize;
  	}
- 
-	/* Update attrtimeo value */
-	if (invalid) {
+
+	/* Update attrtimeo value if we're out of the unstable period */
+	if (invalid & NFS_INO_INVALID_ATTR) {
 		nfsi->attrtimeo = NFS_MINATTRTIMEO(inode);
 		nfsi->attrtimeo_timestamp = jiffies;
-		invalidate_remote_inode(inode);
-		memset(NFS_COOKIEVERF(inode), 0, sizeof(NFS_COOKIEVERF(inode)));
 	} else if (time_after(jiffies, nfsi->attrtimeo_timestamp+nfsi->attrtimeo)) {
 		if ((nfsi->attrtimeo <<= 1) > NFS_MAXATTRTIMEO(inode))
 			nfsi->attrtimeo = NFS_MAXATTRTIMEO(inode);
 		nfsi->attrtimeo_timestamp = jiffies;
 	}
+	/* Don't invalidate the data if we were to blame */
+	if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode)
+				|| S_ISLNK(inode->i_mode)))
+		invalid &= ~NFS_INO_INVALID_DATA;
+	nfsi->flags |= invalid;
 
 	return 0;
- out_nochange:
-	if (!timespec_equal(&fattr->atime, &inode->i_atime))
-		inode->i_atime = fattr->atime;
-	return 0;
  out_changed:
 	/*
 	 * Big trouble! The inode has become a different object.
 	 */
 #ifdef NFS_PARANOIA
-	printk(KERN_DEBUG "nfs_refresh_inode: inode %ld mode changed, %07o to %07o\n",
-	       inode->i_ino, inode->i_mode, fattr->mode);
+	printk(KERN_DEBUG "%s: inode %ld mode changed, %07o to %07o\n",
+			__FUNCTION__, inode->i_ino, inode->i_mode, fattr->mode);
 #endif
 	/*
 	 * No need to worry about unhashing the dentry, as the
@@ -1718,6 +1772,7 @@ static void init_once(void * foo, kmem_c
 		INIT_LIST_HEAD(&nfsi->dirty);
 		INIT_LIST_HEAD(&nfsi->commit);
 		INIT_RADIX_TREE(&nfsi->nfs_page_tree, GFP_ATOMIC);
+		atomic_set(&nfsi->data_updates, 0);
 		nfsi->ndirty = 0;
 		nfsi->ncommit = 0;
 		nfsi->npages = 0;
--- diff/fs/nfs/nfs3proc.c	2004-02-18 08:54:12.000000000 +0000
+++ source/fs/nfs/nfs3proc.c	2004-02-23 13:56:46.000000000 +0000
@@ -68,20 +68,6 @@ nfs3_async_handle_jukebox(struct rpc_tas
 	return 1;
 }
 
-static void
-nfs3_write_refresh_inode(struct inode *inode, struct nfs_fattr *fattr)
-{
-	if (fattr->valid & NFS_ATTR_FATTR) {
-		if (!(fattr->valid & NFS_ATTR_WCC)) {
-			fattr->pre_size  = NFS_CACHE_ISIZE(inode);
-			fattr->pre_mtime = NFS_CACHE_MTIME(inode);
-			fattr->pre_ctime = NFS_CACHE_CTIME(inode);
-			fattr->valid |= NFS_ATTR_WCC;
-		}
-		nfs_refresh_inode(inode, fattr);
-	}
-}
-
 static struct rpc_cred *
 nfs_cred(struct inode *inode, struct file *filp)
 {
@@ -280,7 +266,7 @@ nfs3_proc_write(struct nfs_write_data *w
 	msg.rpc_cred = nfs_cred(inode, filp);
 	status = rpc_call_sync(NFS_CLIENT(inode), &msg, rpcflags);
 	if (status >= 0)
-		nfs3_write_refresh_inode(inode, fattr);
+		nfs_refresh_inode(inode, fattr);
 	dprintk("NFS reply write: %d\n", status);
 	return status < 0? status : wdata->res.count;
 }
@@ -303,7 +289,7 @@ nfs3_proc_commit(struct nfs_write_data *
 	msg.rpc_cred = nfs_cred(inode, filp);
 	status = rpc_call_sync(NFS_CLIENT(inode), &msg, 0);
 	if (status >= 0)
-		nfs3_write_refresh_inode(inode, fattr);
+		nfs_refresh_inode(inode, fattr);
 	dprintk("NFS reply commit: %d\n", status);
 	return status;
 }
@@ -777,12 +763,13 @@ nfs3_proc_read_setup(struct nfs_read_dat
 static void
 nfs3_write_done(struct rpc_task *task)
 {
-	struct nfs_write_data *data = (struct nfs_write_data *) task->tk_calldata;
+	struct nfs_write_data *data;
 
 	if (nfs3_async_handle_jukebox(task))
 		return;
+	data = (struct nfs_write_data *)task->tk_calldata;
 	if (task->tk_status >= 0)
-		nfs3_write_refresh_inode(data->inode, data->res.fattr);
+		nfs_refresh_inode(data->inode, data->res.fattr);
 	nfs_writeback_done(task);
 }
 
@@ -835,12 +822,13 @@ nfs3_proc_write_setup(struct nfs_write_d
 static void
 nfs3_commit_done(struct rpc_task *task)
 {
-	struct nfs_write_data *data = (struct nfs_write_data *) task->tk_calldata;
+	struct nfs_write_data *data;
 
 	if (nfs3_async_handle_jukebox(task))
 		return;
+	data = (struct nfs_write_data *)task->tk_calldata;
 	if (task->tk_status >= 0)
-		nfs3_write_refresh_inode(data->inode, data->res.fattr);
+		nfs_refresh_inode(data->inode, data->res.fattr);
 	nfs_commit_done(task);
 }
 
--- diff/fs/nfs/nfs4proc.c	2004-02-18 08:54:12.000000000 +0000
+++ source/fs/nfs/nfs4proc.c	2004-02-23 13:56:46.000000000 +0000
@@ -1088,12 +1088,8 @@ nfs4_proc_read(struct nfs_read_data *rda
 
 	fattr->valid = 0;
 	status = rpc_call_sync(server->client, &msg, flags);
-	if (!status) {
+	if (!status)
 		renew_lease(server, timestamp);
-		/* Check cache consistency */
-		if (fattr->change_attr != NFS_CHANGE_ATTR(inode))
-			nfs_zap_caches(inode);
-	}
 	dprintk("NFS reply read: %d\n", status);
 	return status;
 }
@@ -1130,7 +1126,6 @@ nfs4_proc_write(struct nfs_write_data *w
 
 	fattr->valid = 0;
 	status = rpc_call_sync(server->client, &msg, rpcflags);
-	NFS_CACHEINV(inode);
 	dprintk("NFS reply write: %d\n", status);
 	return status;
 }
@@ -1517,7 +1512,6 @@ nfs4_read_done(struct rpc_task *task)
 {
 	struct nfs_read_data *data = (struct nfs_read_data *) task->tk_calldata;
 	struct inode *inode = data->inode;
-	struct nfs_fattr *fattr = data->res.fattr;
 
 	if (nfs4_async_handle_error(task, NFS_SERVER(inode)) == -EAGAIN) {
 		task->tk_action = nfs4_restart_read;
@@ -1525,11 +1519,6 @@ nfs4_read_done(struct rpc_task *task)
 	}
 	if (task->tk_status > 0)
 		renew_lease(NFS_SERVER(inode), data->timestamp);
-	/* Check cache consistency */
-	if (fattr->change_attr != NFS_CHANGE_ATTR(inode))
-		nfs_zap_caches(inode);
-	if (fattr->bitmap[1] & FATTR4_WORD1_TIME_ACCESS)
-		inode->i_atime = fattr->atime;
 	/* Call back common NFS readpage processing */
 	nfs_readpage_result(task);
 }
@@ -1577,21 +1566,6 @@ nfs4_proc_read_setup(struct nfs_read_dat
 }
 
 static void
-nfs4_write_refresh_inode(struct inode *inode, struct nfs_fattr *fattr)
-{
-	/* Check cache consistency */
-	if (fattr->pre_change_attr != NFS_CHANGE_ATTR(inode))
-		nfs_zap_caches(inode);
-	NFS_CHANGE_ATTR(inode) = fattr->change_attr;
-	if (fattr->bitmap[1] & FATTR4_WORD1_SPACE_USED)
-		inode->i_blocks = (fattr->du.nfs3.used + 511) >> 9;
-	if (fattr->bitmap[1] & FATTR4_WORD1_TIME_METADATA)
-		inode->i_ctime = fattr->ctime;
-	if (fattr->bitmap[1] & FATTR4_WORD1_TIME_MODIFY)
-		inode->i_mtime = fattr->mtime;
-}
-
-static void
 nfs4_restart_write(struct rpc_task *task)
 {
 	struct nfs_write_data *data = (struct nfs_write_data *)task->tk_calldata;
@@ -1617,7 +1591,6 @@ nfs4_write_done(struct rpc_task *task)
 	}
 	if (task->tk_status >= 0)
 		renew_lease(NFS_SERVER(inode), data->timestamp);
-	nfs4_write_refresh_inode(inode, data->res.fattr);
 	/* Call back common NFS writeback processing */
 	nfs_writeback_done(task);
 }
@@ -1684,7 +1657,6 @@ nfs4_commit_done(struct rpc_task *task)
 		task->tk_action = nfs4_restart_write;
 		return;
 	}
-	nfs4_write_refresh_inode(inode, data->res.fattr);
 	/* Call back common NFS writeback processing */
 	nfs_commit_done(task);
 }
@@ -1807,6 +1779,7 @@ nfs4_proc_file_open(struct inode *inode,
 	if (filp->f_mode & FMODE_WRITE) {
 		lock_kernel();
 		nfs_set_mmcred(inode, state->owner->so_cred);
+		nfs_begin_data_update(inode);
 		unlock_kernel();
 	}
 	filp->private_data = state;
@@ -1823,6 +1796,11 @@ nfs4_proc_file_release(struct inode *ino
 
 	if (state)
 		nfs4_close_state(state, filp->f_mode);
+	if (filp->f_mode & FMODE_WRITE) {
+		lock_kernel();
+		nfs_end_data_update(inode);
+		unlock_kernel();
+	}
 	return 0;
 }
 
--- diff/fs/nfs/nfsroot.c	2003-08-26 10:00:54.000000000 +0100
+++ source/fs/nfs/nfsroot.c	2004-02-23 13:56:46.000000000 +0000
@@ -166,37 +166,6 @@ static struct nfs_bool_opts {
 
 
 /*
- *  Extract IP address from the parameter string if needed. Note that we
- *  need to have root_server_addr set _before_ IPConfig gets called as it
- *  can override it.
- */
-static void __init root_nfs_parse_addr(char *name)
-{
-	int octets = 0;
-	char *cp, *cq;
-
-	cp = cq = name;
-	while (octets < 4) {
-		while (*cp >= '0' && *cp <= '9')
-			cp++;
-		if (cp == cq || cp - cq > 3)
-			break;
-		if (*cp == '.' || octets == 3)
-			octets++;
-		if (octets < 4)
-			cp++;
-		cq = cp;
-	}
-	if (octets == 4 && (*cp == ':' || *cp == '\0')) {
-		if (*cp == ':')
-			*cp++ = '\0';
-		root_server_addr = in_aton(name);
-		strcpy(name, cp);
-	}
-}
-
-
-/*
  *  Parse option string.
  */
 static void __init root_nfs_parse(char *name, char *buf)
@@ -345,7 +314,7 @@ int __init nfs_root_setup(char *line)
 			line[sizeof(nfs_root_name) - strlen(NFS_ROOT) - 1] = '\0';
 		sprintf(nfs_root_name, NFS_ROOT, line);
 	}
-	root_nfs_parse_addr(nfs_root_name);
+	root_server_addr = root_nfs_parse_addr(nfs_root_name);
 	return 1;
 }
 
--- diff/fs/nfs/pagelist.c	2003-10-27 09:20:39.000000000 +0000
+++ source/fs/nfs/pagelist.c	2004-02-23 13:56:46.000000000 +0000
@@ -249,6 +249,8 @@ nfs_coalesce_requests(struct list_head *
  * @file: if set, ensure we match requests from this file
  * @idx_start: lower bound of page->index to scan
  * @npages: idx_start + npages sets the upper bound to scan.
+ * @max_req: if set, stop after this many coalesced requests.
+ * @wpages: if max_req is set, max # pages per coalesced request.
  *
  * Moves elements from one of the inode request lists.
  * If the number of requests is set to 0, the entire address_space
@@ -259,18 +261,22 @@ nfs_coalesce_requests(struct list_head *
 int
 nfs_scan_list(struct list_head *head, struct list_head *dst,
 	      struct file *file,
-	      unsigned long idx_start, unsigned int npages)
+	      unsigned long idx_start, unsigned int npages,
+	      unsigned int max_req, unsigned int wpages)
 {
 	struct list_head	*pos, *tmp;
-	struct nfs_page		*req;
+	struct nfs_page		*req, *prev;
 	unsigned long		idx_end;
-	int			res;
+	int			res, is_contig;
+	unsigned int		nreq, pages;
 
 	res = 0;
 	if (npages == 0)
 		idx_end = ~0;
 	else
 		idx_end = idx_start + npages - 1;
+	nreq = pages = 0;
+	prev = NULL;
 
 	list_for_each_safe(pos, tmp, head) {
 
@@ -284,11 +290,29 @@ nfs_scan_list(struct list_head *head, st
 		if (req->wb_index > idx_end)
 			break;
 
+		is_contig = (max_req &&
+			     prev &&
+			     pages < wpages &&
+			     req->wb_pgbase == 0 &&
+			     prev->wb_pgbase + prev->wb_bytes == PAGE_CACHE_SIZE &&
+			     req->wb_index == prev->wb_index + 1 &&
+			     req->wb_cred == prev->wb_cred);
+
+		if (max_req && !is_contig && nreq == max_req)
+			break;
+
 		if (!nfs_lock_request(req))
 			continue;
 		nfs_list_remove_request(req);
 		nfs_list_add_request(req, dst);
 		res++;
+
+		if (!is_contig) {
+			nreq++;
+			pages = 1;
+		} else
+			pages++;
+		prev = req;
 	}
 	return res;
 }
--- diff/fs/nfs/proc.c	2004-02-18 08:54:12.000000000 +0000
+++ source/fs/nfs/proc.c	2004-02-23 13:56:46.000000000 +0000
@@ -49,18 +49,6 @@
 
 extern struct rpc_procinfo nfs_procedures[];
 
-static void
-nfs_write_refresh_inode(struct inode *inode, struct nfs_fattr *fattr)
-{
-	if (!(fattr->valid & NFS_ATTR_WCC)) {
-		fattr->pre_size  = NFS_CACHE_ISIZE(inode);
-		fattr->pre_mtime = NFS_CACHE_MTIME(inode);
-		fattr->pre_ctime = NFS_CACHE_CTIME(inode);
-		fattr->valid |= NFS_ATTR_WCC;
-	}
-	nfs_refresh_inode(inode, fattr);
-}
-
 static struct rpc_cred *
 nfs_cred(struct inode *inode, struct file *filp)
 {
@@ -205,7 +193,7 @@ nfs_proc_write(struct nfs_write_data *wd
 	msg.rpc_cred = nfs_cred(inode, filp);
 	status = rpc_call_sync(NFS_CLIENT(inode), &msg, flags);
 	if (status >= 0) {
-		nfs_write_refresh_inode(inode, fattr);
+		nfs_refresh_inode(inode, fattr);
 		wdata->res.count = wdata->args.count;
 		wdata->verf.committed = NFS_FILE_SYNC;
 	}
@@ -331,10 +319,8 @@ nfs_proc_unlink_done(struct dentry *dir,
 {
 	struct rpc_message *msg = &task->tk_msg;
 	
-	if (msg->rpc_argp) {
-		NFS_CACHEINV(dir->d_inode);
+	if (msg->rpc_argp)
 		kfree(msg->rpc_argp);
-	}
 	return 0;
 }
 
@@ -584,7 +570,7 @@ nfs_write_done(struct rpc_task *task)
 	struct nfs_write_data *data = (struct nfs_write_data *) task->tk_calldata;
 
 	if (task->tk_status >= 0)
-		nfs_write_refresh_inode(data->inode, data->res.fattr);
+		nfs_refresh_inode(data->inode, data->res.fattr);
 	nfs_writeback_done(task);
 }
 
--- diff/fs/nfs/read.c	2003-10-09 09:47:34.000000000 +0100
+++ source/fs/nfs/read.c	2004-02-23 13:56:46.000000000 +0000
@@ -124,6 +124,7 @@ nfs_readpage_sync(struct file *file, str
 		if (result < rdata.args.count)	/* NFSv2ism */
 			break;
 	} while (count);
+	NFS_FLAGS(inode) |= NFS_INO_INVALID_ATIME;
 
 	if (count)
 		memclear_highpage_flush(page, rdata.args.pgbase, count);
@@ -266,6 +267,7 @@ nfs_readpage_result(struct rpc_task *tas
 	dprintk("NFS: %4d nfs_readpage_result, (status %d)\n",
 		task->tk_pid, task->tk_status);
 
+	NFS_FLAGS(data->inode) |= NFS_INO_INVALID_ATIME;
 	while (!list_empty(&data->pages)) {
 		struct nfs_page *req = nfs_list_entry(data->pages.next);
 		struct page *page = req->wb_page;
--- diff/fs/nfs/unlink.c	2003-06-30 10:07:24.000000000 +0100
+++ source/fs/nfs/unlink.c	2004-02-23 13:56:46.000000000 +0000
@@ -104,6 +104,7 @@ nfs_async_unlink_init(struct rpc_task *t
 	status = NFS_PROTO(dir->d_inode)->unlink_setup(&msg, dir, &data->name);
 	if (status < 0)
 		goto out_err;
+	nfs_begin_data_update(dir->d_inode);
 	rpc_call_setup(task, &msg, 0);
 	return;
  out_err:
@@ -126,7 +127,7 @@ nfs_async_unlink_done(struct rpc_task *t
 	if (!dir)
 		return;
 	dir_i = dir->d_inode;
-	nfs_zap_caches(dir_i);
+	nfs_end_data_update(dir_i);
 	if (NFS_PROTO(dir_i)->unlink_done(dir, task))
 		return;
 	put_rpccred(data->cred);
--- diff/fs/nfs/write.c	2004-02-09 10:36:12.000000000 +0000
+++ source/fs/nfs/write.c	2004-02-23 13:56:46.000000000 +0000
@@ -125,6 +125,66 @@ void nfs_commit_release(struct rpc_task 
 }
 
 /*
+ * The following definitions are for throttling write requests.
+ * Once # outstanding write requests reaches ASYNC_REQ_LIMIT,
+ * writers are forced to wait until # requests drops to ASYNC_REQ_RESUME.
+ */
+#define ASYNC_REQ_LIMIT		RPC_MAXREQS
+#define ASYNC_REQ_RESUME	(ASYNC_REQ_LIMIT * 3 / 4)
+#define NFS_BDI(inode)		(&NFS_SERVER(inode)->backing_dev_info)
+#define IS_CONGESTED(inode)	bdi_write_congested(NFS_BDI(inode))
+
+/*
+ * A write request is being initiated.  Increment active
+ * request count and check for congestion.
+ */
+static __inline__ void WRITE_START(struct inode *inode)
+{
+	spin_lock(&nfs_wreq_lock);
+	if (++NFS_SERVER(inode)->wactive >= ASYNC_REQ_LIMIT)
+		set_bit(BDI_write_congested, &NFS_BDI(inode)->state);
+	spin_unlock(&nfs_wreq_lock);
+}
+
+/*
+ * A write request has just completed on an inode.
+ * Check if congestion has now cleared.
+ */
+static __inline__ void WRITE_DONE(struct inode *inode)
+{
+	spin_lock(&nfs_wreq_lock);
+	NFS_SERVER(inode)->wactive--;
+	if (IS_CONGESTED(inode) && NFS_SERVER(inode)->wactive <= ASYNC_REQ_RESUME) {
+		clear_bit(BDI_write_congested, &NFS_BDI(inode)->state);
+		wake_up_all(&NFS_SERVER(inode)->writerq);
+	}
+	spin_unlock(&nfs_wreq_lock);
+}
+
+/*
+ * Wait for congestion to expire.
+ */
+static __inline__ int CONGESTION_WAIT(struct inode *inode)
+{
+	int err = 0;
+	int intr = NFS_SERVER(inode)->flags & NFS_MOUNT_INTR;
+	DECLARE_WAITQUEUE(wait, current);
+
+	do {
+		set_current_state(intr ? TASK_INTERRUPTIBLE : TASK_UNINTERRUPTIBLE);
+		add_wait_queue(&NFS_SERVER(inode)->writerq, &wait);
+		if (IS_CONGESTED(inode)) {
+			io_schedule();
+			if (intr && signalled())
+				err = -ERESTARTSYS;
+		}
+		set_current_state(TASK_RUNNING);
+		remove_wait_queue(&NFS_SERVER(inode)->writerq, &wait);
+	} while (!err && IS_CONGESTED(inode));
+	return err;
+}
+
+/*
  * Write a page synchronously.
  * Offset is the data offset within the page.
  */
@@ -157,12 +217,15 @@ nfs_writepage_sync(struct file *file, st
 		(long long)NFS_FILEID(inode),
 		count, (long long)(page_offset(page) + offset));
 
+	nfs_begin_data_update(inode);
 	do {
 		if (count < wsize && !swapfile)
 			wdata.args.count = count;
 		wdata.args.offset = page_offset(page) + wdata.args.pgbase;
 
+		WRITE_START(inode);
 		result = NFS_PROTO(inode)->write(&wdata, file);
+		WRITE_DONE(inode);
 
 		if (result < 0) {
 			/* Must mark the page invalid after I/O error */
@@ -185,6 +248,7 @@ nfs_writepage_sync(struct file *file, st
 		if (wdata.args.offset > i_size_read(inode))
 			i_size_write(inode, wdata.args.offset);
 	} while (count);
+	nfs_end_data_update(inode);
 
 	if (PageError(page))
 		ClearPageError(page);
@@ -204,6 +268,7 @@ nfs_writepage_async(struct file *file, s
 	loff_t		end;
 	int		status;
 
+	nfs_begin_data_update(inode);
 	req = nfs_update_request(file, inode, page, offset, count);
 	status = (IS_ERR(req)) ? PTR_ERR(req) : 0;
 	if (status < 0)
@@ -213,6 +278,7 @@ nfs_writepage_async(struct file *file, s
 	end = ((loff_t)page->index<<PAGE_CACHE_SHIFT) + (loff_t)(offset + count);
 	if (i_size_read(inode) < end)
 		i_size_write(inode, end);
+	nfs_end_data_update(inode);
 
  out:
 	return status;
@@ -282,20 +348,39 @@ nfs_writepages(struct address_space *map
 	struct inode *inode = mapping->host;
 	int is_sync = !wbc->nonblocking;
 	int err;
+	long npages = wbc->nr_to_write;
 
 	err = generic_writepages(mapping, wbc);
 	if (err)
 		goto out;
-	err = nfs_flush_file(inode, NULL, 0, 0, 0);
-	if (err < 0)
-		goto out;
-	if (wbc->sync_mode == WB_SYNC_HOLD)
-		goto out;
 	if (is_sync && wbc->sync_mode == WB_SYNC_ALL) {
+		npages -= NFS_I(inode)->ndirty + NFS_I(inode)->ncommit;
 		err = nfs_wb_all(inode);
-	} else
+		goto out;
+	}
+	if (wbc->sync_mode != WB_SYNC_HOLD)
+		npages -= NFS_I(inode)->ncommit;
+	while (npages > 0) {
+		if (IS_CONGESTED(inode)) {
+			if (wbc->nonblocking) {
+				wbc->encountered_congestion = 1;
+				break;
+			}
+			err = CONGESTION_WAIT(inode);
+			if (err)
+				goto out;
+		}
+		err = nfs_flush_file(inode, NULL, 0, 0, 0);
+		if (err < 0)
+			goto out;
+		if (err == 0)
+			break;
+		npages -= err;
+	}
+	if (wbc->sync_mode != WB_SYNC_HOLD)
 		nfs_commit_file(inode, NULL, 0, 0, 0);
 out:
+	wbc->nr_to_write = npages;
 	return err;
 }
 
@@ -312,8 +397,10 @@ nfs_inode_add_request(struct inode *inod
 	BUG_ON(error == -EEXIST);
 	if (error)
 		return error;
-	if (!nfsi->npages)
+	if (!nfsi->npages) {
 		igrab(inode);
+		nfs_begin_data_update(inode);
+	}
 	nfsi->npages++;
 	req->wb_count++;
 	return 0;
@@ -336,6 +423,7 @@ nfs_inode_remove_request(struct nfs_page
 	nfsi->npages--;
 	if (!nfsi->npages) {
 		spin_unlock(&nfs_wreq_lock);
+		nfs_end_data_update(inode);
 		iput(inode);
 	} else
 		spin_unlock(&nfs_wreq_lock);
@@ -472,11 +560,11 @@ nfs_wait_on_requests(struct inode *inode
  * The requests are *not* checked to ensure that they form a contiguous set.
  */
 static int
-nfs_scan_dirty(struct inode *inode, struct list_head *dst, struct file *file, unsigned long idx_start, unsigned int npages)
+nfs_scan_dirty(struct inode *inode, struct list_head *dst, struct file *file, unsigned long idx_start, unsigned int npages, unsigned int max_req)
 {
 	struct nfs_inode *nfsi = NFS_I(inode);
 	int	res;
-	res = nfs_scan_list(&nfsi->dirty, dst, file, idx_start, npages);
+	res = nfs_scan_list(&nfsi->dirty, dst, file, idx_start, npages, max_req, NFS_SERVER(inode)->wpages);
 	nfsi->ndirty -= res;
 	sub_page_state(nr_dirty,res);
 	if ((nfsi->ndirty == 0) != list_empty(&nfsi->dirty))
@@ -501,7 +589,7 @@ nfs_scan_commit(struct inode *inode, str
 {
 	struct nfs_inode *nfsi = NFS_I(inode);
 	int	res;
-	res = nfs_scan_list(&nfsi->commit, dst, file, idx_start, npages);
+	res = nfs_scan_list(&nfsi->commit, dst, file, idx_start, npages, 0, 0);
 	nfsi->ncommit -= res;
 	if ((nfsi->ncommit == 0) != list_empty(&nfsi->commit))
 		printk(KERN_ERR "NFS: desynchronized value of nfs_i.ncommit.\n");
@@ -626,6 +714,9 @@ nfs_strategy(struct inode *inode)
 {
 	unsigned int	dirty, wpages;
 
+	if (IS_CONGESTED(inode))
+		return;
+
 	dirty  = NFS_I(inode)->ndirty;
 	wpages = NFS_SERVER(inode)->wpages;
 #if defined(CONFIG_NFS_V3) || defined(CONFIG_NFS_V4)
@@ -696,6 +787,7 @@ nfs_updatepage(struct file *file, struct
 		return status;
 	}
 
+	nfs_begin_data_update(inode);
 	/*
 	 * Try to find an NFS request corresponding to this page
 	 * and update it.
@@ -729,6 +821,7 @@ nfs_updatepage(struct file *file, struct
 	} else
 		nfs_unlock_request(req);
 done:
+	nfs_end_data_update(inode);
         dprintk("NFS:      nfs_updatepage returns %d (isize %Ld)\n",
 			status, (long long)i_size_read(inode));
 	if (status < 0)
@@ -767,6 +860,8 @@ nfs_write_rpcsetup(struct list_head *hea
 
 	NFS_PROTO(inode)->write_setup(data, count, how);
 
+	WRITE_START(inode);
+
 	dprintk("NFS: %4d initiated write call (req %s/%Ld, %u bytes @ offset %Lu)\n",
 		task->tk_pid,
 		inode->i_sb->s_id,
@@ -856,6 +951,8 @@ nfs_writeback_done(struct rpc_task *task
 	dprintk("NFS: %4d nfs_writeback_done (status %d)\n",
 		task->tk_pid, task->tk_status);
 
+	WRITE_DONE(data->inode);
+
 	/* We can't handle that yet but we check for it nevertheless */
 	if (resp->count < argp->count && task->tk_status >= 0) {
 		static unsigned long    complain;
@@ -891,10 +988,7 @@ nfs_writeback_done(struct rpc_task *task
 #endif
 
 	/*
-	 * Update attributes as result of writeback.
-	 * FIXME: There is an inherent race with invalidate_inode_pages and
-	 *	  writebacks since the page->count is kept > 1 for as long
-	 *	  as the page has a write request pending.
+	 * Process the nfs_page list
 	 */
 	while (!list_empty(&data->pages)) {
 		req = nfs_list_entry(data->pages.next);
@@ -1066,10 +1160,14 @@ int nfs_flush_file(struct inode *inode, 
 {
 	LIST_HEAD(head);
 	int			res,
+				nreq,
 				error = 0;
 
+	nreq = ASYNC_REQ_LIMIT - NFS_SERVER(inode)->wactive;
+	if (nreq < 1)
+		nreq = 1;
 	spin_lock(&nfs_wreq_lock);
-	res = nfs_scan_dirty(inode, &head, file, idx_start, npages);
+	res = nfs_scan_dirty(inode, &head, file, idx_start, npages, nreq);
 	spin_unlock(&nfs_wreq_lock);
 	if (res)
 		error = nfs_flush_list(&head, NFS_SERVER(inode)->wpages, how);
@@ -1114,13 +1212,19 @@ int nfs_sync_file(struct inode *inode, s
 
 	do {
 		error = 0;
-		if (wait)
-			error = nfs_wait_on_requests(inode, file, idx_start, npages);
-		if (error == 0)
+		if (IS_CONGESTED(inode))
+			error = CONGESTION_WAIT(inode);
+		if (error == 0) {
 			error = nfs_flush_file(inode, file, idx_start, npages, how);
+			if (error == 0 && wait)
+				error = nfs_wait_on_requests(inode, file, idx_start, npages);
+		}
 #if defined(CONFIG_NFS_V3) || defined(CONFIG_NFS_V4)
-		if (error == 0)
+		if (error == 0 && NFS_PROTO(inode)->version > 2) {
 			error = nfs_commit_file(inode, file, idx_start, npages, how);
+			if (error == 0 && wait)
+				error = nfs_wait_on_requests(inode, file, idx_start, npages);
+		}
 #endif
 	} while (error > 0);
 	return error;
--- diff/fs/nfsd/auth.c	2003-10-09 09:47:17.000000000 +0100
+++ source/fs/nfsd/auth.c	2004-02-23 13:56:46.000000000 +0000
@@ -11,11 +11,26 @@
 #include <linux/nfsd/nfsd.h>
 
 #define	CAP_NFSD_MASK (CAP_FS_MASK|CAP_TO_MASK(CAP_SYS_RESOURCE))
-void
-nfsd_setuser(struct svc_rqst *rqstp, struct svc_export *exp)
+
+int nfsd_setuser(struct svc_rqst *rqstp, struct svc_export *exp)
 {
 	struct svc_cred	*cred = &rqstp->rq_cred;
-	int		i;
+	struct group_info *group_info;
+	int ngroups;
+	int i;
+	int ret;
+
+	ngroups = 0;
+	if (!(exp->ex_flags & NFSEXP_ALLSQUASH)) {
+		for (i = 0; i < SVC_CRED_NGROUPS; i++) {
+			if (cred->cr_groups[i] == (gid_t)NOGROUP)
+				break;
+			ngroups++;
+		}
+	}
+	group_info = groups_alloc(ngroups);
+	if (group_info == NULL)
+		return -ENOMEM;
 
 	if (exp->ex_flags & NFSEXP_ALLSQUASH) {
 		cred->cr_uid = exp->ex_anon_uid;
@@ -26,7 +41,7 @@ nfsd_setuser(struct svc_rqst *rqstp, str
 			cred->cr_uid = exp->ex_anon_uid;
 		if (!cred->cr_gid)
 			cred->cr_gid = exp->ex_anon_gid;
-		for (i = 0; i < NGROUPS; i++)
+		for (i = 0; i < SVC_CRED_NGROUPS; i++)
 			if (!cred->cr_groups[i])
 				cred->cr_groups[i] = exp->ex_anon_gid;
 	}
@@ -39,19 +54,24 @@ nfsd_setuser(struct svc_rqst *rqstp, str
 		current->fsgid = cred->cr_gid;
 	else
 		current->fsgid = exp->ex_anon_gid;
-	for (i = 0; i < NGROUPS; i++) {
+
+	for (i = 0; i < SVC_CRED_NGROUPS; i++) {
 		gid_t group = cred->cr_groups[i];
 		if (group == (gid_t) NOGROUP)
 			break;
-		current->groups[i] = group;
+		GROUP_AT(group_info, i) = group;
 	}
-	current->ngroups = i;
 
-	if ((cred->cr_uid)) {
-		cap_t(current->cap_effective) &= ~CAP_NFSD_MASK;
-	} else {
-		cap_t(current->cap_effective) |= (CAP_NFSD_MASK &
-						  current->cap_permitted);
+	ret = set_current_groups(group_info);
+	if (ret == 0) {
+		if ((cred->cr_uid)) {
+			cap_t(current->cap_effective) &= ~CAP_NFSD_MASK;
+		} else {
+			cap_t(current->cap_effective) |= (CAP_NFSD_MASK &
+							current->cap_permitted);
+		}
 	}
+	put_group_info(group_info);
 
+	return ret;
 }
--- diff/fs/nfsd/export.c	2003-09-30 15:46:18.000000000 +0100
+++ source/fs/nfsd/export.c	2004-02-23 13:56:46.000000000 +0000
@@ -20,6 +20,7 @@
 #include <linux/stat.h>
 #include <linux/in.h>
 #include <linux/seq_file.h>
+#include <linux/syscalls.h>
 #include <linux/rwsem.h>
 #include <linux/dcache.h>
 #include <linux/namei.h>
--- diff/fs/nfsd/nfs3proc.c	2003-02-26 16:01:09.000000000 +0000
+++ source/fs/nfsd/nfs3proc.c	2004-02-23 13:56:46.000000000 +0000
@@ -595,10 +595,10 @@ nfsd3_proc_commit(struct svc_rqst * rqst
 {
 	int	nfserr;
 
-	dprintk("nfsd: COMMIT(3)   %s %d@%ld\n",
+	dprintk("nfsd: COMMIT(3)   %s %u@%Lu\n",
 				SVCFH_fmt(&argp->fh),
 				argp->count,
-				(unsigned long) argp->offset);
+				(unsigned long long) argp->offset);
 
 	if (argp->offset > NFS_OFFSET_MAX)
 		RETURN_STATUS(nfserr_inval);
--- diff/fs/nfsd/nfs4state.c	2003-10-09 09:47:34.000000000 +0100
+++ source/fs/nfsd/nfs4state.c	2004-02-23 13:56:46.000000000 +0000
@@ -244,7 +244,7 @@ copy_cred(struct svc_cred *target, struc
 
 	target->cr_uid = source->cr_uid;
 	target->cr_gid = source->cr_gid;
-	for(i = 0; i < NGROUPS; i++)
+	for(i = 0; i < SVC_CRED_NGROUPS; i++)
 		target->cr_groups[i] = source->cr_groups[i];
 }
 
@@ -1793,7 +1793,8 @@ nfsd4_lock(struct svc_rqst *rqstp, struc
 	unsigned int strhashval;
 
 	dprintk("NFSD: nfsd4_lock: start=%Ld length=%Ld\n",
-		lock->lk_offset, lock->lk_length);
+		(long long) lock->lk_offset,
+		(long long) lock->lk_length);
 
 	lock->lk_stateowner = NULL;
 	nfs4_lock_state();
@@ -2042,7 +2043,8 @@ nfsd4_locku(struct svc_rqst *rqstp, stru
 	int status;
 						        
 	dprintk("NFSD: nfsd4_locku: start=%Ld length=%Ld\n",
-		locku->lu_offset, locku->lu_length);
+		(long long) locku->lu_offset,
+		(long long) locku->lu_length);
 	nfs4_lock_state();
 									        
 	if ((status = nfs4_preprocess_seqid_op(current_fh, 
--- diff/fs/nfsd/nfsctl.c	2003-10-09 09:47:34.000000000 +0100
+++ source/fs/nfsd/nfsctl.c	2004-02-23 13:56:46.000000000 +0000
@@ -16,6 +16,7 @@
 #include <linux/fcntl.h>
 #include <linux/net.h>
 #include <linux/in.h>
+#include <linux/syscalls.h>
 #include <linux/unistd.h>
 #include <linux/slab.h>
 #include <linux/proc_fs.h>
--- diff/fs/nfsd/stats.c	2002-11-11 11:09:30.000000000 +0000
+++ source/fs/nfsd/stats.c	2004-02-23 13:56:46.000000000 +0000
@@ -26,6 +26,7 @@
 #include <linux/kernel.h>
 #include <linux/time.h>
 #include <linux/proc_fs.h>
+#include <linux/seq_file.h>
 #include <linux/stat.h>
 #include <linux/module.h>
 
@@ -39,14 +40,11 @@ struct svc_stat		nfsd_svcstats = {
 	.program	= &nfsd_program,
 };
 
-static int
-nfsd_proc_read(char *buffer, char **start, off_t offset, int count,
-				int *eof, void *data)
+static int nfsd_proc_show(struct seq_file *seq, void *v)
 {
-	int	len;
-	int	i;
+	int i;
 
-	len = sprintf(buffer, "rc %u %u %u\nfh %u %u %u %u %u\nio %u %u\n",
+	seq_printf(seq, "rc %u %u %u\nfh %u %u %u %u %u\nio %u %u\n",
 		      nfsdstats.rchits,
 		      nfsdstats.rcmisses,
 		      nfsdstats.rcnocache,
@@ -58,57 +56,42 @@ nfsd_proc_read(char *buffer, char **star
 		      nfsdstats.io_read,
 		      nfsdstats.io_write);
 	/* thread usage: */
-	len += sprintf(buffer+len, "th %u %u", nfsdstats.th_cnt, nfsdstats.th_fullcnt);
+	seq_printf(seq, "th %u %u", nfsdstats.th_cnt, nfsdstats.th_fullcnt);
 	for (i=0; i<10; i++) {
 		unsigned int jifs = nfsdstats.th_usage[i];
 		unsigned int sec = jifs / HZ, msec = (jifs % HZ)*1000/HZ;
-		len += sprintf(buffer+len, " %u.%03u", sec, msec);
+		seq_printf(seq, " %u.%03u", sec, msec);
 	}
 
 	/* newline and ra-cache */
-	len += sprintf(buffer+len, "\nra %u", nfsdstats.ra_size);
+	seq_printf(seq, "\nra %u", nfsdstats.ra_size);
 	for (i=0; i<11; i++)
-		len += sprintf(buffer+len, " %u", nfsdstats.ra_depth[i]);
-	len += sprintf(buffer+len, "\n");
+		seq_printf(seq, " %u", nfsdstats.ra_depth[i]);
+	seq_putc(seq, '\n');
 	
+	/* show my rpc info */
+	svc_seq_show(seq, &nfsd_svcstats);
 
-	/* Assume we haven't hit EOF yet. Will be set by svc_proc_read. */
-	*eof = 0;
-
-	/*
-	 * Append generic nfsd RPC statistics if there's room for it.
-	 */
-	if (len <= offset) {
-		len = svc_proc_read(buffer, start, offset - len, count,
-				    eof, data);
-		return len;
-	}
-
-	if (len < count) {
-		len += svc_proc_read(buffer + len, start, 0, count - len,
-				     eof, data);
-	}
-
-	if (offset >= len) {
-		*start = buffer;
-		return 0;
-	}
+	return 0;
+}
 
-	*start = buffer + offset;
-	if ((len -= offset) > count)
-		return count;
-	return len;
+static int nfsd_proc_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, nfsd_proc_show, NULL);
 }
 
+static struct file_operations nfsd_proc_fops = {
+	.owner = THIS_MODULE,
+	.open = nfsd_proc_open,
+	.read  = seq_read,
+	.llseek = seq_lseek,
+	.release = single_release,
+};
+
 void
 nfsd_stat_init(void)
 {
-	struct proc_dir_entry	*ent;
-
-	if ((ent = svc_proc_register(&nfsd_svcstats)) != 0) {
-		ent->read_proc = nfsd_proc_read;
-		ent->owner = THIS_MODULE;
-	}
+	svc_proc_register(&nfsd_svcstats, &nfsd_proc_fops);
 }
 
 void
--- diff/fs/nfsd/vfs.c	2004-02-09 10:36:12.000000000 +0000
+++ source/fs/nfsd/vfs.c	2004-02-23 13:56:46.000000000 +0000
@@ -823,7 +823,7 @@ out:
  */
 int
 nfsd_commit(struct svc_rqst *rqstp, struct svc_fh *fhp,
-               off_t offset, unsigned long count)
+               loff_t offset, unsigned long count)
 {
 	struct file	file;
 	int		err;
--- diff/fs/open.c	2004-02-09 10:36:12.000000000 +0000
+++ source/fs/open.c	2004-02-23 13:56:46.000000000 +0000
@@ -192,7 +192,9 @@ int do_truncate(struct dentry *dentry, l
 	newattrs.ia_size = length;
 	newattrs.ia_valid = ATTR_SIZE | ATTR_CTIME;
 	down(&dentry->d_inode->i_sem);
+	down_write(&dentry->d_inode->i_alloc_sem);
 	err = notify_change(dentry, &newattrs);
+	up_write(&dentry->d_inode->i_alloc_sem);
 	up(&dentry->d_inode->i_sem);
 	return err;
 }
--- diff/fs/partitions/check.c	2004-02-18 08:54:12.000000000 +0000
+++ source/fs/partitions/check.c	2004-02-23 13:56:46.000000000 +0000
@@ -367,7 +367,7 @@ void register_disk(struct gendisk *disk)
 		return;
 
 	bdev = bdget_disk(disk, 0);
-	if (blkdev_get(bdev, FMODE_READ, 0, BDEV_RAW) < 0)
+	if (blkdev_get(bdev, FMODE_READ, 0) < 0)
 		return;
 	state = check_partition(disk, bdev);
 	if (state) {
@@ -385,7 +385,7 @@ void register_disk(struct gendisk *disk)
 		}
 		kfree(state);
 	}
-	blkdev_put(bdev, BDEV_RAW);
+	blkdev_put(bdev);
 }
 
 int rescan_partitions(struct gendisk *disk, struct block_device *bdev)
--- diff/fs/partitions/efi.c	2003-09-30 15:46:19.000000000 +0100
+++ source/fs/partitions/efi.c	2004-02-23 13:56:46.000000000 +0000
@@ -91,16 +91,6 @@
 #include "check.h"
 #include "efi.h"
 
-/* Handle printing of 64-bit values */
-/* Borrowed from /usr/include/inttypes.h */
-# if BITS_PER_LONG == 64 
-#  define __PRI64_PREFIX	"l"
-# else
-#  define __PRI64_PREFIX	"ll"
-# endif
-# define PRIx64		__PRI64_PREFIX "x"
-
-
 #undef EFI_DEBUG
 #ifdef EFI_DEBUG
 #define Dprintk(x...) printk(KERN_DEBUG x)
@@ -307,9 +297,10 @@ is_gpt_valid(struct block_device *bdev, 
 
 	/* Check the GUID Partition Table signature */
 	if (le64_to_cpu((*gpt)->signature) != GPT_HEADER_SIGNATURE) {
-		Dprintk("GUID Partition Table Header signature is wrong: %"
-			PRIx64 " != %" PRIx64 "\n", le64_to_cpu((*gpt)->signature),
-			GPT_HEADER_SIGNATURE);
+		Dprintk("GUID Partition Table Header signature is wrong:"
+			"%lld != %lld\n",
+			(unsigned long long)le64_to_cpu((*gpt)->signature),
+			(unsigned long long)GPT_HEADER_SIGNATURE);
 		kfree(*gpt);
 		*gpt = NULL;
 		return 0;
@@ -333,8 +324,9 @@ is_gpt_valid(struct block_device *bdev, 
 	/* Check that the my_lba entry points to the LBA that contains
 	 * the GUID Partition Table */
 	if (le64_to_cpu((*gpt)->my_lba) != lba) {
-		Dprintk("GPT my_lba incorrect: %" PRIx64 " != %" PRIx64 "\n",
-			le64_to_cpu((*gpt)->my_lba), lba);
+		Dprintk("GPT my_lba incorrect: %lld != %lld\n",
+			(unsigned long long)le64_to_cpu((*gpt)->my_lba),
+			(unsigned long long)lba);
 		kfree(*gpt);
 		*gpt = NULL;
 		return 0;
@@ -382,33 +374,33 @@ compare_gpts(gpt_header *pgpt, gpt_heade
 	if (le64_to_cpu(pgpt->my_lba) != le64_to_cpu(agpt->alternate_lba)) {
 		printk(KERN_WARNING
 		       "GPT:Primary header LBA != Alt. header alternate_lba\n");
-		printk(KERN_WARNING "GPT:%" PRIx64 " != %" PRIx64 "\n",
-		       le64_to_cpu(pgpt->my_lba),
-                       le64_to_cpu(agpt->alternate_lba));
+		printk(KERN_WARNING "GPT:%lld != %lld\n",
+		       (unsigned long long)le64_to_cpu(pgpt->my_lba),
+                       (unsigned long long)le64_to_cpu(agpt->alternate_lba));
 		error_found++;
 	}
 	if (le64_to_cpu(pgpt->alternate_lba) != le64_to_cpu(agpt->my_lba)) {
 		printk(KERN_WARNING
 		       "GPT:Primary header alternate_lba != Alt. header my_lba\n");
-		printk(KERN_WARNING "GPT:%" PRIx64 " != %" PRIx64 "\n",
-		       le64_to_cpu(pgpt->alternate_lba),
-                       le64_to_cpu(agpt->my_lba));
+		printk(KERN_WARNING "GPT:%lld != %lld\n",
+		       (unsigned long long)le64_to_cpu(pgpt->alternate_lba),
+                       (unsigned long long)le64_to_cpu(agpt->my_lba));
 		error_found++;
 	}
 	if (le64_to_cpu(pgpt->first_usable_lba) !=
             le64_to_cpu(agpt->first_usable_lba)) {
 		printk(KERN_WARNING "GPT:first_usable_lbas don't match.\n");
-		printk(KERN_WARNING "GPT:%" PRIx64 " != %" PRIx64 "\n",
-		       le64_to_cpu(pgpt->first_usable_lba),
-                       le64_to_cpu(agpt->first_usable_lba));
+		printk(KERN_WARNING "GPT:%lld != %lld\n",
+		       (unsigned long long)le64_to_cpu(pgpt->first_usable_lba),
+                       (unsigned long long)le64_to_cpu(agpt->first_usable_lba));
 		error_found++;
 	}
 	if (le64_to_cpu(pgpt->last_usable_lba) !=
             le64_to_cpu(agpt->last_usable_lba)) {
 		printk(KERN_WARNING "GPT:last_usable_lbas don't match.\n");
-		printk(KERN_WARNING "GPT:%" PRIx64 " != %" PRIx64 "\n",
-		       le64_to_cpu(pgpt->last_usable_lba),
-                       le64_to_cpu(agpt->last_usable_lba));
+		printk(KERN_WARNING "GPT:%lld != %lld\n",
+		       (unsigned long long)le64_to_cpu(pgpt->last_usable_lba),
+                       (unsigned long long)le64_to_cpu(agpt->last_usable_lba));
 		error_found++;
 	}
 	if (efi_guidcmp(pgpt->disk_guid, agpt->disk_guid)) {
@@ -444,16 +436,18 @@ compare_gpts(gpt_header *pgpt, gpt_heade
 	if (le64_to_cpu(pgpt->alternate_lba) != lastlba) {
 		printk(KERN_WARNING
 		       "GPT:Primary header thinks Alt. header is not at the end of the disk.\n");
-		printk(KERN_WARNING "GPT:%" PRIx64 " != %" PRIx64 "\n",
-		       le64_to_cpu(pgpt->alternate_lba), lastlba);
+		printk(KERN_WARNING "GPT:%lld != %lld\n",
+			(unsigned long long)le64_to_cpu(pgpt->alternate_lba),
+			(unsigned long long)lastlba);
 		error_found++;
 	}
 
 	if (le64_to_cpu(agpt->my_lba) != lastlba) {
 		printk(KERN_WARNING
 		       "GPT:Alternate GPT header not at the end of the disk.\n");
-		printk(KERN_WARNING "GPT:%" PRIx64 " != %" PRIx64 "\n",
-		       le64_to_cpu(agpt->my_lba), lastlba);
+		printk(KERN_WARNING "GPT:%lld != %lld\n",
+			(unsigned long long)le64_to_cpu(agpt->my_lba),
+			(unsigned long long)lastlba);
 		error_found++;
 	}
 
--- diff/fs/proc/array.c	2003-10-27 09:20:39.000000000 +0000
+++ source/fs/proc/array.c	2004-02-23 13:56:46.000000000 +0000
@@ -176,8 +176,10 @@ static inline char * task_state(struct t
 		p->files ? p->files->max_fds : 0);
 	task_unlock(p);
 
-	for (g = 0; g < p->ngroups; g++)
-		buffer += sprintf(buffer, "%d ", p->groups[g]);
+	get_group_info(p->group_info);
+	for (g = 0; g < min(p->group_info->ngroups,NGROUPS_SMALL); g++)
+		buffer += sprintf(buffer, "%d ", GROUP_AT(p->group_info,g));
+	put_group_info(p->group_info);
 
 	buffer += sprintf(buffer, "\n");
 	return buffer;
--- diff/fs/proc/base.c	2004-02-18 08:54:12.000000000 +0000
+++ source/fs/proc/base.c	2004-02-23 13:56:46.000000000 +0000
@@ -1582,14 +1582,13 @@ struct dentry *proc_pid_lookup(struct in
 	read_unlock(&tasklist_lock);
 	if (!task)
 		goto out;
+	if (!thread_group_leader(task))
+		goto out_drop_task;
 
 	inode = proc_pid_make_inode(dir->i_sb, task, PROC_TGID_INO);
 
-
-	if (!inode) {
-		put_task_struct(task);
-		goto out;
-	}
+	if (!inode)
+		goto out_drop_task;
 	inode->i_mode = S_IFDIR|S_IRUGO|S_IXUGO;
 	inode->i_op = &proc_tgid_base_inode_operations;
 	inode->i_fop = &proc_tgid_base_operations;
@@ -1614,6 +1613,8 @@ struct dentry *proc_pid_lookup(struct in
 		goto out;
 	}
 	return NULL;
+out_drop_task:
+	put_task_struct(task);
 out:
 	return ERR_PTR(-ENOENT);
 }
@@ -1622,6 +1623,7 @@ out:
 static struct dentry *proc_task_lookup(struct inode *dir, struct dentry * dentry, struct nameidata *nd)
 {
 	struct task_struct *task;
+	struct task_struct *leader = proc_task(dir);
 	struct inode *inode;
 	unsigned tid;
 
@@ -1636,14 +1638,14 @@ static struct dentry *proc_task_lookup(s
 	read_unlock(&tasklist_lock);
 	if (!task)
 		goto out;
+	if (leader->tgid != task->tgid)
+		goto out_drop_task;
 
 	inode = proc_pid_make_inode(dir->i_sb, task, PROC_TID_INO);
 
 
-	if (!inode) {
-		put_task_struct(task);
-		goto out;
-	}
+	if (!inode)
+		goto out_drop_task;
 	inode->i_mode = S_IFDIR|S_IRUGO|S_IXUGO;
 	inode->i_op = &proc_tid_base_inode_operations;
 	inode->i_fop = &proc_tid_base_operations;
@@ -1656,6 +1658,8 @@ static struct dentry *proc_task_lookup(s
 
 	put_task_struct(task);
 	return NULL;
+out_drop_task:
+	put_task_struct(task);
 out:
 	return ERR_PTR(-ENOENT);
 }
--- diff/fs/proc/proc_misc.c	2004-02-18 08:54:12.000000000 +0000
+++ source/fs/proc/proc_misc.c	2004-02-23 13:56:46.000000000 +0000
@@ -389,7 +389,7 @@ int show_stat(struct seq_file *p, void *
 		jiffies_to_clock_t(iowait),
 		jiffies_to_clock_t(irq),
 		jiffies_to_clock_t(softirq));
-	for_each_online_cpu(i) {
+	for_each_cpu(i) {
 		seq_printf(p, "cpu%d %u %u %u %u %u %u %u\n",
 			i,
 			jiffies_to_clock_t(kstat_cpu(i).cpustat.user),
@@ -424,7 +424,7 @@ int show_stat(struct seq_file *p, void *
 
 static int stat_open(struct inode *inode, struct file *file)
 {
-	unsigned size = 4096 * (1 + num_online_cpus() / 32);
+	unsigned size = 4096 * (1 + num_possible_cpus() / 32);
 	char *buf;
 	struct seq_file *m;
 	int res;
@@ -641,6 +641,36 @@ static void create_seq_entry(char *name,
 		entry->proc_fops = f;
 }
 
+#ifdef CONFIG_LOCKMETER
+extern ssize_t get_lockmeter_info(char *, size_t, loff_t *);
+extern ssize_t put_lockmeter_info(const char *, size_t);
+extern int get_lockmeter_info_size(void);
+
+/*
+ * This function accesses lock metering information.
+ */
+static ssize_t read_lockmeter(struct file *file, char *buf,
+			      size_t count, loff_t *ppos)
+{
+	return get_lockmeter_info(buf, count, ppos);
+}
+
+/*
+ * Writing to /proc/lockmeter resets the counters
+ */
+static ssize_t write_lockmeter(struct file * file, const char * buf,
+			       size_t count, loff_t *ppos)
+{
+	return put_lockmeter_info(buf, count);
+}
+
+static struct file_operations proc_lockmeter_operations = {
+	NULL,           /* lseek */
+	read:		read_lockmeter,
+	write:		write_lockmeter,
+};
+#endif  /* CONFIG_LOCKMETER */
+
 void __init proc_misc_init(void)
 {
 	struct proc_dir_entry *entry;
@@ -708,6 +738,13 @@ void __init proc_misc_init(void)
 	if (entry)
 		entry->proc_fops = &proc_sysrq_trigger_operations;
 #endif
+#ifdef CONFIG_LOCKMETER
+	entry = create_proc_entry("lockmeter", S_IWUSR | S_IRUGO, NULL);
+	if (entry) {
+		entry->proc_fops = &proc_lockmeter_operations;
+		entry->size = get_lockmeter_info_size();
+	}
+#endif
 #ifdef CONFIG_PPC32
 	{
 		extern struct file_operations ppc_htab_operations;
--- diff/fs/proc/task_mmu.c	2004-02-09 10:36:12.000000000 +0000
+++ source/fs/proc/task_mmu.c	2004-02-23 13:56:46.000000000 +0000
@@ -4,6 +4,22 @@
 #include <asm/elf.h>
 #include <asm/uaccess.h>
 
+#ifdef CONFIG_NUMA
+char *task_mem_pernode(struct mm_struct *mm, char *buffer)
+{
+	int nid;
+
+	for (nid = 0; nid < MAX_NUMNODES; nid++){
+		buffer += sprintf(buffer, "VmRSS-node_%d:\t%8lu kb\n",
+			nid, mm->pernode_rss[nid] << (PAGE_SHIFT-10));
+	}
+
+	return buffer;
+}
+#else /* !CONFIG_NUMA */
+#define task_mem_pernode(mm, buffer)	(buffer)
+#endif /* CONFIG_NUMA */
+
 char *task_mem(struct mm_struct *mm, char *buffer)
 {
 	unsigned long data = 0, stack = 0, exec = 0, lib = 0;
@@ -40,6 +56,7 @@ char *task_mem(struct mm_struct *mm, cha
 		mm->rss << (PAGE_SHIFT-10),
 		data - stack, stack,
 		exec - lib, lib);
+	buffer = task_mem_pernode(mm, buffer);
 	up_read(&mm->mmap_sem);
 	return buffer;
 }
--- diff/fs/quota_v1.c	2003-10-09 09:47:34.000000000 +0100
+++ source/fs/quota_v1.c	2004-02-23 13:56:46.000000000 +0000
@@ -60,13 +60,13 @@ static int v1_read_dqblk(struct dquot *d
 	v1_disk2mem_dqblk(&dquot->dq_dqb, &dqblk);
 	if (dquot->dq_dqb.dqb_bhardlimit == 0 && dquot->dq_dqb.dqb_bsoftlimit == 0 &&
 	    dquot->dq_dqb.dqb_ihardlimit == 0 && dquot->dq_dqb.dqb_isoftlimit == 0)
-		dquot->dq_flags |= DQ_FAKE;
+		set_bit(DQ_FAKE_B, &dquot->dq_flags);
 	dqstats.reads++;
 
 	return 0;
 }
 
-static int v1_commit_dqblk(struct dquot *dquot)
+static int v1_commit_dqblk(struct dquot *dquot, int init)
 {
 	short type = dquot->dq_type;
 	struct file *filp;
@@ -80,12 +80,7 @@ static int v1_commit_dqblk(struct dquot 
 	fs = get_fs();
 	set_fs(KERNEL_DS);
 
-	/*
-	 * Note: clear the DQ_MOD flag unconditionally,
-	 * so we don't loop forever on failure.
-	 */
 	v1_mem2disk_dqblk(&dqblk, &dquot->dq_dqb);
-	dquot->dq_flags &= ~DQ_MOD;
 	if (dquot->dq_id == 0) {
 		dqblk.dqb_btime = sb_dqopt(dquot->dq_sb)->info[type].dqi_bgrace;
 		dqblk.dqb_itime = sb_dqopt(dquot->dq_sb)->info[type].dqi_igrace;
--- diff/fs/quota_v2.c	2003-05-21 11:50:00.000000000 +0100
+++ source/fs/quota_v2.c	2004-02-23 13:56:46.000000000 +0000
@@ -65,7 +65,7 @@ static int v2_read_file_info(struct supe
 	set_fs(fs);
 	if (size != sizeof(struct v2_disk_dqinfo)) {
 		printk(KERN_WARNING "Can't read info structure on device %s.\n",
-			f->f_vfsmnt->mnt_sb->s_id);
+			f->f_dentry->d_sb->s_id);
 		return -1;
 	}
 	info->dqi_bgrace = le32_to_cpu(dinfo.dqi_bgrace);
@@ -87,10 +87,12 @@ static int v2_write_file_info(struct sup
 	ssize_t size;
 	loff_t offset = V2_DQINFOOFF;
 
+	spin_lock(&dq_data_lock);
 	info->dqi_flags &= ~DQF_INFO_DIRTY;
 	dinfo.dqi_bgrace = cpu_to_le32(info->dqi_bgrace);
 	dinfo.dqi_igrace = cpu_to_le32(info->dqi_igrace);
 	dinfo.dqi_flags = cpu_to_le32(info->dqi_flags & DQF_MASK);
+	spin_unlock(&dq_data_lock);
 	dinfo.dqi_blocks = cpu_to_le32(info->u.v2_i.dqi_blocks);
 	dinfo.dqi_free_blk = cpu_to_le32(info->u.v2_i.dqi_free_blk);
 	dinfo.dqi_free_entry = cpu_to_le32(info->u.v2_i.dqi_free_entry);
@@ -100,7 +102,7 @@ static int v2_write_file_info(struct sup
 	set_fs(fs);
 	if (size != sizeof(struct v2_disk_dqinfo)) {
 		printk(KERN_WARNING "Can't write info structure on device %s.\n",
-			f->f_vfsmnt->mnt_sb->s_id);
+			f->f_dentry->d_sb->s_id);
 		return -1;
 	}
 	return 0;
@@ -173,9 +175,10 @@ static ssize_t write_blk(struct file *fi
 }
 
 /* Remove empty block from list and return it */
-static int get_free_dqblk(struct file *filp, struct mem_dqinfo *info)
+static int get_free_dqblk(struct file *filp, int type)
 {
 	dqbuf_t buf = getdqbuf();
+	struct mem_dqinfo *info = sb_dqinfo(filp->f_dentry->d_sb, type);
 	struct v2_disk_dqdbheader *dh = (struct v2_disk_dqdbheader *)buf;
 	int ret, blk;
 
@@ -193,7 +196,7 @@ static int get_free_dqblk(struct file *f
 			goto out_buf;
 		blk = info->u.v2_i.dqi_blocks++;
 	}
-	mark_info_dirty(info);
+	mark_info_dirty(filp->f_dentry->d_sb, type);
 	ret = blk;
 out_buf:
 	freedqbuf(buf);
@@ -201,8 +204,9 @@ out_buf:
 }
 
 /* Insert empty block to the list */
-static int put_free_dqblk(struct file *filp, struct mem_dqinfo *info, dqbuf_t buf, uint blk)
+static int put_free_dqblk(struct file *filp, int type, dqbuf_t buf, uint blk)
 {
+	struct mem_dqinfo *info = sb_dqinfo(filp->f_dentry->d_sb, type);
 	struct v2_disk_dqdbheader *dh = (struct v2_disk_dqdbheader *)buf;
 	int err;
 
@@ -210,16 +214,17 @@ static int put_free_dqblk(struct file *f
 	dh->dqdh_prev_free = cpu_to_le32(0);
 	dh->dqdh_entries = cpu_to_le16(0);
 	info->u.v2_i.dqi_free_blk = blk;
-	mark_info_dirty(info);
+	mark_info_dirty(filp->f_dentry->d_sb, type);
 	if ((err = write_blk(filp, blk, buf)) < 0)	/* Some strange block. We had better leave it... */
 		return err;
 	return 0;
 }
 
 /* Remove given block from the list of blocks with free entries */
-static int remove_free_dqentry(struct file *filp, struct mem_dqinfo *info, dqbuf_t buf, uint blk)
+static int remove_free_dqentry(struct file *filp, int type, dqbuf_t buf, uint blk)
 {
 	dqbuf_t tmpbuf = getdqbuf();
+	struct mem_dqinfo *info = sb_dqinfo(filp->f_dentry->d_sb, type);
 	struct v2_disk_dqdbheader *dh = (struct v2_disk_dqdbheader *)buf;
 	uint nextblk = le32_to_cpu(dh->dqdh_next_free), prevblk = le32_to_cpu(dh->dqdh_prev_free);
 	int err;
@@ -242,7 +247,7 @@ static int remove_free_dqentry(struct fi
 	}
 	else {
 		info->u.v2_i.dqi_free_entry = nextblk;
-		mark_info_dirty(info);
+		mark_info_dirty(filp->f_dentry->d_sb, type);
 	}
 	freedqbuf(tmpbuf);
 	dh->dqdh_next_free = dh->dqdh_prev_free = cpu_to_le32(0);
@@ -255,9 +260,10 @@ out_buf:
 }
 
 /* Insert given block to the beginning of list with free entries */
-static int insert_free_dqentry(struct file *filp, struct mem_dqinfo *info, dqbuf_t buf, uint blk)
+static int insert_free_dqentry(struct file *filp, int type, dqbuf_t buf, uint blk)
 {
 	dqbuf_t tmpbuf = getdqbuf();
+	struct mem_dqinfo *info = sb_dqinfo(filp->f_dentry->d_sb, type);
 	struct v2_disk_dqdbheader *dh = (struct v2_disk_dqdbheader *)buf;
 	int err;
 
@@ -276,7 +282,7 @@ static int insert_free_dqentry(struct fi
 	}
 	freedqbuf(tmpbuf);
 	info->u.v2_i.dqi_free_entry = blk;
-	mark_info_dirty(info);
+	mark_info_dirty(filp->f_dentry->d_sb, type);
 	return 0;
 out_buf:
 	freedqbuf(tmpbuf);
@@ -307,7 +313,7 @@ static uint find_free_dqentry(struct dqu
 			goto out_buf;
 	}
 	else {
-		blk = get_free_dqblk(filp, info);
+		blk = get_free_dqblk(filp, dquot->dq_type);
 		if ((int)blk < 0) {
 			*err = blk;
 			freedqbuf(buf);
@@ -315,10 +321,10 @@ static uint find_free_dqentry(struct dqu
 		}
 		memset(buf, 0, V2_DQBLKSIZE);
 		info->u.v2_i.dqi_free_entry = blk;	/* This is enough as block is already zeroed and entry list is empty... */
-		mark_info_dirty(info);
+		mark_info_dirty(dquot->dq_sb, dquot->dq_type);
 	}
 	if (le16_to_cpu(dh->dqdh_entries)+1 >= V2_DQSTRINBLK)	/* Block will be full? */
-		if ((*err = remove_free_dqentry(filp, info, buf, blk)) < 0) {
+		if ((*err = remove_free_dqentry(filp, dquot->dq_type, buf, blk)) < 0) {
 			printk(KERN_ERR "VFS: find_free_dqentry(): Can't remove block (%u) from entry free list.\n", blk);
 			goto out_buf;
 		}
@@ -349,7 +355,6 @@ out_buf:
 static int do_insert_tree(struct dquot *dquot, uint *treeblk, int depth)
 {
 	struct file *filp = sb_dqopt(dquot->dq_sb)->files[dquot->dq_type];
-	struct mem_dqinfo *info = sb_dqopt(dquot->dq_sb)->info + dquot->dq_type;
 	dqbuf_t buf;
 	int ret = 0, newson = 0, newact = 0;
 	u32 *ref;
@@ -358,7 +363,7 @@ static int do_insert_tree(struct dquot *
 	if (!(buf = getdqbuf()))
 		return -ENOMEM;
 	if (!*treeblk) {
-		ret = get_free_dqblk(filp, info);
+		ret = get_free_dqblk(filp, dquot->dq_type);
 		if (ret < 0)
 			goto out_buf;
 		*treeblk = ret;
@@ -392,7 +397,7 @@ static int do_insert_tree(struct dquot *
 		ret = write_blk(filp, *treeblk, buf);
 	}
 	else if (newact && ret < 0)
-		put_free_dqblk(filp, info, buf, *treeblk);
+		put_free_dqblk(filp, dquot->dq_type, buf, *treeblk);
 out_buf:
 	freedqbuf(buf);
 	return ret;
@@ -417,6 +422,7 @@ static int v2_write_dquot(struct dquot *
 	ssize_t ret;
 	struct v2_disk_dqblk ddquot;
 
+	/* dq_off is guarded by dqio_sem */
 	if (!dquot->dq_off)
 		if ((ret = dq_insert_tree(dquot)) < 0) {
 			printk(KERN_ERR "VFS: Error %Zd occurred while creating quota.\n", ret);
@@ -424,7 +430,9 @@ static int v2_write_dquot(struct dquot *
 		}
 	filp = sb_dqopt(dquot->dq_sb)->files[type];
 	offset = dquot->dq_off;
+	spin_lock(&dq_data_lock);
 	mem2diskdqb(&ddquot, &dquot->dq_dqb, dquot->dq_id);
+	spin_unlock(&dq_data_lock);
 	fs = get_fs();
 	set_fs(KERNEL_DS);
 	ret = filp->f_op->write(filp, (char *)&ddquot, sizeof(struct v2_disk_dqblk), &offset);
@@ -445,7 +453,6 @@ static int v2_write_dquot(struct dquot *
 static int free_dqentry(struct dquot *dquot, uint blk)
 {
 	struct file *filp = sb_dqopt(dquot->dq_sb)->files[dquot->dq_type];
-	struct mem_dqinfo *info = sb_dqopt(dquot->dq_sb)->info + dquot->dq_type;
 	struct v2_disk_dqdbheader *dh;
 	dqbuf_t buf = getdqbuf();
 	int ret = 0;
@@ -463,8 +470,8 @@ static int free_dqentry(struct dquot *dq
 	dh = (struct v2_disk_dqdbheader *)buf;
 	dh->dqdh_entries = cpu_to_le16(le16_to_cpu(dh->dqdh_entries)-1);
 	if (!le16_to_cpu(dh->dqdh_entries)) {	/* Block got free? */
-		if ((ret = remove_free_dqentry(filp, info, buf, blk)) < 0 ||
-		    (ret = put_free_dqblk(filp, info, buf, blk)) < 0) {
+		if ((ret = remove_free_dqentry(filp, dquot->dq_type, buf, blk)) < 0 ||
+		    (ret = put_free_dqblk(filp, dquot->dq_type, buf, blk)) < 0) {
 			printk(KERN_ERR "VFS: Can't move quota data block (%u) to free list.\n", blk);
 			goto out_buf;
 		}
@@ -473,7 +480,7 @@ static int free_dqentry(struct dquot *dq
 		memset(buf+(dquot->dq_off & ((1 << V2_DQBLKSIZE_BITS)-1)), 0, sizeof(struct v2_disk_dqblk));
 		if (le16_to_cpu(dh->dqdh_entries) == V2_DQSTRINBLK-1) {
 			/* Insert will write block itself */
-			if ((ret = insert_free_dqentry(filp, info, buf, blk)) < 0) {
+			if ((ret = insert_free_dqentry(filp, dquot->dq_type, buf, blk)) < 0) {
 				printk(KERN_ERR "VFS: Can't insert quota data block (%u) to free entry list.\n", blk);
 				goto out_buf;
 			}
@@ -494,7 +501,6 @@ out_buf:
 static int remove_tree(struct dquot *dquot, uint *blk, int depth)
 {
 	struct file *filp = sb_dqopt(dquot->dq_sb)->files[dquot->dq_type];
-	struct mem_dqinfo *info = sb_dqopt(dquot->dq_sb)->info + dquot->dq_type;
 	dqbuf_t buf = getdqbuf();
 	int ret = 0;
 	uint newblk;
@@ -518,7 +524,7 @@ static int remove_tree(struct dquot *dqu
 		ref[GETIDINDEX(dquot->dq_id, depth)] = cpu_to_le32(0);
 		for (i = 0; i < V2_DQBLKSIZE && !buf[i]; i++);	/* Block got empty? */
 		if (i == V2_DQBLKSIZE) {
-			put_free_dqblk(filp, info, buf, *blk);
+			put_free_dqblk(filp, dquot->dq_type, buf, *blk);
 			*blk = 0;
 		}
 		else
@@ -632,7 +638,7 @@ static int v2_read_dquot(struct dquot *d
 		if (offset < 0)
 			printk(KERN_ERR "VFS: Can't read quota structure for id %u.\n", dquot->dq_id);
 		dquot->dq_off = 0;
-		dquot->dq_flags |= DQ_FAKE;
+		set_bit(DQ_FAKE_B, &dquot->dq_flags);
 		memset(&dquot->dq_dqb, 0, sizeof(struct mem_dqblk));
 		ret = offset;
 	}
@@ -650,6 +656,9 @@ static int v2_read_dquot(struct dquot *d
 			ret = 0;
 		set_fs(fs);
 		disk2memdqb(&dquot->dq_dqb, &ddquot);
+		if (!dquot->dq_dqb.dqb_bhardlimit && !dquot->dq_dqb.dqb_bsoftlimit && !dquot->dq_dqb.dqb_ihardlimit &&
+		    !dquot->dq_dqb.dqb_isoftlimit)
+			set_bit(DQ_FAKE_B, &dquot->dq_flags);
 	}
 	dqstats.reads++;
 
@@ -657,11 +666,14 @@ static int v2_read_dquot(struct dquot *d
 }
 
 /* Commit changes of dquot to disk - it might also mean deleting it when quota became fake one and user has no blocks... */
-static int v2_commit_dquot(struct dquot *dquot)
+static int v2_commit_dquot(struct dquot *dquot, int init)
 {
-	/* We clear the flag everytime so we don't loop when there was an IO error... */
-	dquot->dq_flags &= ~DQ_MOD;
-	if (dquot->dq_flags & DQ_FAKE && !(dquot->dq_dqb.dqb_curinodes | dquot->dq_dqb.dqb_curspace))
+	int test;
+
+	spin_lock(&dq_data_lock);
+	test = !init && test_bit(DQ_FAKE_B, &dquot->dq_flags) && !(dquot->dq_dqb.dqb_curinodes | dquot->dq_dqb.dqb_curspace);
+	spin_unlock(&dq_data_lock);
+	if (test)
 		return v2_delete_dquot(dquot);
 	else
 		return v2_write_dquot(dquot);
--- diff/fs/reiserfs/journal.c	2004-02-09 10:36:12.000000000 +0000
+++ source/fs/reiserfs/journal.c	2004-02-23 13:56:46.000000000 +0000
@@ -1895,7 +1895,7 @@ static int release_journal_dev( struct s
 	journal -> j_dev_file = NULL;
 	journal -> j_dev_bd = NULL;
     } else if( journal -> j_dev_bd != NULL ) {
-	result = blkdev_put( journal -> j_dev_bd, BDEV_FS );
+	result = blkdev_put( journal -> j_dev_bd );
 	journal -> j_dev_bd = NULL;
     }
 
@@ -1926,7 +1926,7 @@ static int journal_init_dev( struct supe
 
 	/* there is no "jdev" option and journal is on separate device */
 	if( ( !jdev_name || !jdev_name[ 0 ] ) ) {
-		journal->j_dev_bd = open_by_devnum(jdev, blkdev_mode, BDEV_FS);
+		journal->j_dev_bd = open_by_devnum(jdev, blkdev_mode);
 		if (IS_ERR(journal->j_dev_bd)) {
 			result = PTR_ERR(journal->j_dev_bd);
 			journal->j_dev_bd = NULL;
--- diff/fs/select.c	2003-10-09 09:47:34.000000000 +0100
+++ source/fs/select.c	2004-02-23 13:56:46.000000000 +0000
@@ -291,8 +291,6 @@ static void select_bits_free(void *bits,
  * Update: ERESTARTSYS breaks at least the xview clock binary, so
  * I'm trying ERESTARTNOHAND which restart only when you want to.
  */
-#define MAX_SELECT_SECONDS \
-	((unsigned long) (MAX_SCHEDULE_TIMEOUT / HZ)-1)
 
 asmlinkage long
 sys_select(int n, fd_set __user *inp, fd_set __user *outp, fd_set __user *exp, struct timeval __user *tvp)
@@ -315,9 +313,11 @@ sys_select(int n, fd_set __user *inp, fd
 		if (sec < 0 || usec < 0)
 			goto out_nofds;
 
-		if ((unsigned long) sec < MAX_SELECT_SECONDS) {
+		if ((unsigned long) sec < (MAX_SCHEDULE_TIMEOUT-1) / HZ - 1) {
 			timeout = ROUND_UP(usec, 1000000/HZ);
 			timeout += sec * (unsigned long) HZ;
+		} else {
+			timeout = MAX_SCHEDULE_TIMEOUT-1;
 		}
 	}
 
@@ -469,11 +469,17 @@ asmlinkage long sys_poll(struct pollfd _
 		return -EINVAL;
 
 	if (timeout) {
-		/* Careful about overflow in the intermediate values */
-		if ((unsigned long) timeout < MAX_SCHEDULE_TIMEOUT / HZ)
-			timeout = (unsigned long)(timeout*HZ+999)/1000+1;
-		else /* Negative or overflow */
+                if (timeout < 0) {
 			timeout = MAX_SCHEDULE_TIMEOUT;
+		} else {
+			/* Careful about overflow in the intermediate values */
+			long seconds = timeout/1000;
+			timeout = ((timeout - 1000*seconds)*HZ + 999)/1000 + 1;
+			if (seconds <= (MAX_SCHEDULE_TIMEOUT-2) / HZ - 1)
+				timeout += seconds*HZ;
+			else
+				timeout = MAX_SCHEDULE_TIMEOUT-1;
+		}
 	}
 
 	poll_initwait(&table);
--- diff/fs/smbfs/file.c	2004-02-09 10:36:12.000000000 +0000
+++ source/fs/smbfs/file.c	2004-02-23 13:56:46.000000000 +0000
@@ -257,6 +257,27 @@ out:
 	return status;
 }
 
+static ssize_t
+smb_file_sendfile(struct file *file, loff_t *ppos,
+		  size_t count, read_actor_t actor, void __user *target)
+{
+	struct dentry *dentry = file->f_dentry;
+	ssize_t status;
+
+	VERBOSE("file %s/%s, pos=%Ld, count=%d\n",
+		DENTRY_PATH(dentry), *ppos, count);
+
+	status = smb_revalidate_inode(dentry);
+	if (status) {
+		PARANOIA("%s/%s validation failed, error=%zd\n",
+			 DENTRY_PATH(dentry), status);
+		goto out;
+	}
+	status = generic_file_sendfile(file, ppos, count, actor, target);
+out:
+	return status;
+}
+
 /*
  * This does the "real" work of the write. The generic routine has
  * allocated the page, locked it, done all the page alignment stuff
@@ -388,6 +409,7 @@ struct file_operations smb_file_operatio
 	.open		= smb_file_open,
 	.release	= smb_file_release,
 	.fsync		= smb_fsync,
+	.sendfile	= smb_file_sendfile,
 };
 
 struct inode_operations smb_file_inode_operations =
--- diff/fs/smbfs/proc.c	2004-02-18 08:54:12.000000000 +0000
+++ source/fs/smbfs/proc.c	2004-02-23 13:56:46.000000000 +0000
@@ -1015,12 +1015,6 @@ smb_setup_header(struct smb_request *req
 	p += 19;
 	p += 8;
 
-	/* FIXME: the request will fail if the 'tid' is changed. This
-	   should perhaps be set just before transmitting ... */
-	WSET(req->rq_header, smb_tid, server->opt.tid);
-	WSET(req->rq_header, smb_pid, 1);
-	WSET(req->rq_header, smb_uid, server->opt.server_uid);
-
 	if (server->opt.protocol > SMB_PROTOCOL_CORE) {
 		int flags = SMB_FLAGS_CASELESS_PATHNAMES;
 		int flags2 = SMB_FLAGS2_LONG_PATH_COMPONENTS |
--- diff/fs/smbfs/request.c	2003-08-20 14:16:33.000000000 +0100
+++ source/fs/smbfs/request.c	2004-02-23 13:56:46.000000000 +0000
@@ -384,6 +384,12 @@ int smb_request_send_req(struct smb_requ
 	struct smb_sb_info *server = req->rq_server;
 	int result;
 
+	if (req->rq_bytes_sent == 0) {
+		WSET(req->rq_header, smb_tid, server->opt.tid);
+		WSET(req->rq_header, smb_pid, 1);
+		WSET(req->rq_header, smb_uid, server->opt.server_uid);
+	}
+
 	result = smb_send_request(req);
 	if (result < 0 && result != -EAGAIN)
 		goto out;
--- diff/fs/smbfs/smbiod.c	2003-09-30 15:46:19.000000000 +0100
+++ source/fs/smbfs/smbiod.c	2004-02-23 13:56:46.000000000 +0000
@@ -161,6 +161,8 @@ int smbiod_retry(struct smb_sb_info *ser
 	while (head != &server->xmitq) {
 		req = list_entry(head, struct smb_request, rq_queue);
 		head = head->next;
+
+		req->rq_bytes_sent = 0;
 		if (req->rq_flags & SMB_REQ_NORETRY) {
 			VERBOSE("aborting request %p on xmitq\n", req);
 			req->rq_errno = -EIO;
--- diff/fs/stat.c	2004-02-09 10:36:12.000000000 +0000
+++ source/fs/stat.c	2004-02-23 13:56:46.000000000 +0000
@@ -397,6 +397,7 @@ EXPORT_SYMBOL(inode_get_bytes);
 
 void inode_set_bytes(struct inode *inode, loff_t bytes)
 {
+	/* Caller is here resposible for sufficient locking (ie. inode->i_lock) */
 	inode->i_blocks = bytes >> 9;
 	inode->i_bytes = bytes & 511;
 }
--- diff/fs/super.c	2004-02-18 08:54:12.000000000 +0000
+++ source/fs/super.c	2004-02-23 13:56:46.000000000 +0000
@@ -23,6 +23,7 @@
 #include <linux/config.h>
 #include <linux/module.h>
 #include <linux/slab.h>
+#include <linux/init.h>
 #include <linux/smp_lock.h>
 #include <linux/acct.h>
 #include <linux/blkdev.h>
@@ -33,6 +34,7 @@
 #include <linux/security.h>
 #include <linux/vfs.h>
 #include <linux/writeback.h>		/* for the emergency remount stuff */
+#include <linux/idr.h>
 #include <asm/uaccess.h>
 
 
@@ -66,6 +68,7 @@ static struct super_block *alloc_super(v
 		INIT_LIST_HEAD(&s->s_files);
 		INIT_LIST_HEAD(&s->s_instances);
 		INIT_HLIST_HEAD(&s->s_anon);
+		INIT_LIST_HEAD(&s->s_inodes);
 		init_rwsem(&s->s_umount);
 		sema_init(&s->s_lock, 1);
 		down_write(&s->s_umount);
@@ -327,7 +330,7 @@ restart:
  * flags again, which will cause process A to resync everything.  Fix that with
  * a local mutex.
  *
- * FIXME: If wait==0, we only really need to call ->sync_fs if s_dirt is true.
+ * (Fabian) Avoid sync_fs with clean fs & wait mode 0
  */
 void sync_filesystems(int wait)
 {
@@ -358,7 +361,7 @@ restart:
 		sb->s_count++;
 		spin_unlock(&sb_lock);
 		down_read(&sb->s_umount);
-		if (sb->s_root)
+		if (sb->s_root && (wait || sb->s_dirt))
 			sb->s_op->sync_fs(sb, wait);
 		drop_super(sb);
 		goto restart;
@@ -448,6 +451,14 @@ out:
 	return err;
 }
 
+/**
+ *	mark_files_ro
+ *	@sb: superblock in question
+ *
+ *	All files are marked read/only.  We don't care about pending
+ *	delete files so this should be used in 'force' mode only
+ */
+
 static void mark_files_ro(struct super_block *sb)
 {
 	struct file *f;
@@ -480,7 +491,8 @@ int do_remount_sb(struct super_block *sb
 	shrink_dcache_sb(sb);
 	fsync_super(sb);
 
-	/* If we are remounting RDONLY, make sure there are no rw files open */
+	/* If we are remounting RDONLY and current sb is read/write,
+	   make sure there are no rw files opened */
 	if ((flags & MS_RDONLY) && !(sb->s_flags & MS_RDONLY)) {
 		if (force)
 			mark_files_ro(sb);
@@ -535,22 +547,26 @@ void emergency_remount(void)
  * filesystems which don't use real block-devices.  -- jrs
  */
 
-enum {Max_anon = 256};
-static unsigned long unnamed_dev_in_use[Max_anon/(8*sizeof(unsigned long))];
+static struct idr unnamed_dev_idr;
 static spinlock_t unnamed_dev_lock = SPIN_LOCK_UNLOCKED;/* protects the above */
 
 int set_anon_super(struct super_block *s, void *data)
 {
 	int dev;
+
 	spin_lock(&unnamed_dev_lock);
-	dev = find_first_zero_bit(unnamed_dev_in_use, Max_anon);
-	if (dev == Max_anon) {
+	if (idr_pre_get(&unnamed_dev_idr, GFP_ATOMIC) == 0) {
 		spin_unlock(&unnamed_dev_lock);
-		return -EMFILE;
+		return -ENOMEM;
 	}
-	set_bit(dev, unnamed_dev_in_use);
+	dev = idr_get_new(&unnamed_dev_idr, NULL);
 	spin_unlock(&unnamed_dev_lock);
-	s->s_dev = MKDEV(0, dev);
+
+	if ((dev & MAX_ID_MASK) == (1 << MINORBITS)) {
+		idr_remove(&unnamed_dev_idr, dev);
+		return -EMFILE;
+	}
+	s->s_dev = MKDEV(0, dev & MINORMASK);
 	return 0;
 }
 
@@ -559,14 +575,20 @@ EXPORT_SYMBOL(set_anon_super);
 void kill_anon_super(struct super_block *sb)
 {
 	int slot = MINOR(sb->s_dev);
+
 	generic_shutdown_super(sb);
 	spin_lock(&unnamed_dev_lock);
-	clear_bit(slot, unnamed_dev_in_use);
+	idr_remove(&unnamed_dev_idr, slot);
 	spin_unlock(&unnamed_dev_lock);
 }
 
 EXPORT_SYMBOL(kill_anon_super);
 
+void __init unnamed_dev_init(void)
+{
+	idr_init(&unnamed_dev_idr);
+}
+
 void kill_litter_super(struct super_block *sb)
 {
 	if (sb->s_root)
@@ -596,7 +618,7 @@ struct super_block *get_sb_bdev(struct f
 	struct super_block *s;
 	int error = 0;
 
-	bdev = open_bdev_excl(dev_name, flags, BDEV_FS, fs_type);
+	bdev = open_bdev_excl(dev_name, flags, fs_type);
 	if (IS_ERR(bdev))
 		return (struct super_block *)bdev;
 
@@ -630,7 +652,7 @@ struct super_block *get_sb_bdev(struct f
 	return s;
 
 out:
-	close_bdev_excl(bdev, BDEV_FS);
+	close_bdev_excl(bdev);
 	return s;
 }
 
@@ -641,7 +663,7 @@ void kill_block_super(struct super_block
 	struct block_device *bdev = sb->s_bdev;
 	generic_shutdown_super(sb);
 	set_blocksize(bdev, sb->s_old_blocksize);
-	close_bdev_excl(bdev, BDEV_FS);
+	close_bdev_excl(bdev);
 }
 
 EXPORT_SYMBOL(kill_block_super);
--- diff/fs/sysfs/dir.c	2004-01-19 10:22:59.000000000 +0000
+++ source/fs/sysfs/dir.c	2004-02-23 13:56:46.000000000 +0000
@@ -96,6 +96,8 @@ static void remove_dir(struct dentry * d
 void sysfs_remove_subdir(struct dentry * d)
 {
 	remove_dir(d);
+	/* release the "extra" ref taken during sysfs_create() */
+	dput(d);
 }
 
 
@@ -120,13 +122,14 @@ void sysfs_remove_dir(struct kobject * k
 	down(&dentry->d_inode->i_sem);
 
 	spin_lock(&dcache_lock);
+restart:
 	node = dentry->d_subdirs.next;
 	while (node != &dentry->d_subdirs) {
 		struct dentry * d = list_entry(node,struct dentry,d_child);
-		list_del_init(node);
 
+		node = node->next;
 		pr_debug(" o %s (%d): ",d->d_name.name,atomic_read(&d->d_count));
-		if (d->d_inode) {
+		if (!d_unhashed(d) && (d->d_inode)) {
 			d = dget_locked(d);
 			pr_debug("removing");
 
@@ -137,12 +140,12 @@ void sysfs_remove_dir(struct kobject * k
 			d_delete(d);
 			simple_unlink(dentry->d_inode,d);
 			dput(d);
+			pr_debug(" done\n");
 			spin_lock(&dcache_lock);
+			/* re-acquired dcache_lock, need to restart */
+			goto restart;
 		}
-		pr_debug(" done\n");
-		node = dentry->d_subdirs.next;
 	}
-	list_del_init(&dentry->d_child);
 	spin_unlock(&dcache_lock);
 	up(&dentry->d_inode->i_sem);
 
--- diff/fs/sysfs/group.c	2003-09-30 15:46:19.000000000 +0100
+++ source/fs/sysfs/group.c	2004-02-23 13:56:46.000000000 +0000
@@ -68,12 +68,13 @@ void sysfs_remove_group(struct kobject *
 	if (grp->name)
 		dir = sysfs_get_dentry(kobj->dentry,grp->name);
 	else
-		dir = kobj->dentry;
+		dir = dget(kobj->dentry);
 
 	remove_files(dir,grp);
-	dput(dir);
 	if (grp->name)
 		sysfs_remove_subdir(dir);
+	/* release the ref. taken in this routine */
+	dput(dir);
 }
 
 
--- diff/fs/ufs/inode.c	2003-09-17 12:28:12.000000000 +0100
+++ source/fs/ufs/inode.c	2004-02-23 13:56:47.000000000 +0000
@@ -82,7 +82,12 @@ static int ufs_block_to_path(struct inod
 	return n;
 }
 
-int ufs_frag_map(struct inode *inode, int frag)
+/*
+ * Returns the location of the fragment from
+ * the begining of the filesystem.
+ */
+
+u64  ufs_frag_map(struct inode *inode, int frag)
 {
 	struct ufs_inode_info *ufsi = UFS_I(inode);
 	struct super_block *sb = inode->i_sb;
@@ -93,6 +98,9 @@ int ufs_frag_map(struct inode *inode, in
 	int depth = ufs_block_to_path(inode, frag >> uspi->s_fpbshift, offsets);
 	int ret = 0;
 	u32 block;
+	u64 u2_block = 0;
+	unsigned flags = UFS_SB(sb)->s_flags;
+	u64 temp = 0;
 
 	if (depth == 0)
 		return 0;
@@ -100,6 +108,9 @@ int ufs_frag_map(struct inode *inode, in
 	p = offsets;
 
 	lock_kernel();
+	if ((flags & UFS_TYPE_MASK) == UFS_TYPE_UFS2)
+		goto ufs2;
+
 	block = ufsi->i_u1.i_data[*p++];
 	if (!block)
 		goto out;
@@ -116,6 +127,28 @@ int ufs_frag_map(struct inode *inode, in
 			goto out;
 	}
 	ret = uspi->s_sbbase + fs32_to_cpu(sb, block) + (frag & uspi->s_fpbmask);
+	goto out;
+ufs2:
+	u2_block = ufsi->i_u1.u2_i_data[*p++];
+	if (!u2_block)
+		goto out;
+
+	temp = (u64)uspi->s_sbbase + fs64_to_cpu(sb, u2_block);
+
+	while (--depth) {
+		struct buffer_head *bh;
+		u64 n = *p++;
+
+		bh = sb_bread(sb, temp +(n>>shift));
+		if (!bh)
+			goto out;
+		u2_block = ((u64*)bh->b_data)[n & mask];
+		brelse(bh);
+		if (!u2_block)
+			goto out;
+	}
+	ret = temp + (frag & uspi->s_fpbmask);
+
 out:
 	unlock_kernel();
 	return ret;
@@ -132,12 +165,20 @@ static struct buffer_head * ufs_inode_ge
 	unsigned block, blockoff, lastfrag, lastblock, lastblockoff;
 	unsigned tmp, goal;
 	u32 * p, * p2;
+	unsigned flags = 0;
 
 	UFSD(("ENTER, ino %lu, fragment %u, new_fragment %u, required %u\n",
 		inode->i_ino, fragment, new_fragment, required))         
 
 	sb = inode->i_sb;
 	uspi = UFS_SB(sb)->s_uspi;
+
+	flags = UFS_SB(sb)->s_flags;
+        /* TODO : to be done for write support
+        if ( (flags & UFS_TYPE_MASK) == UFS_TYPE_UFS2)
+             goto ufs2;
+         */
+
 	block = ufs_fragstoblks (fragment);
 	blockoff = ufs_fragnum (fragment);
 	p = ufsi->i_u1.i_data + block;
@@ -230,6 +271,21 @@ repeat:
 	mark_inode_dirty(inode);
 	UFSD(("EXIT, result %u\n", tmp + blockoff))
 	return result;
+
+     /* This part : To be implemented ....
+        Required only for writing, not required for READ-ONLY.
+ufs2:
+
+	u2_block = ufs_fragstoblks(fragment);
+	u2_blockoff = ufs_fragnum(fragment);
+	p = ufsi->i_u1.u2_i_data + block;
+	goal = 0;
+
+repeat2:
+	tmp = fs32_to_cpu(sb, *p);
+	lastfrag = ufsi->i_lastfrag;
+
+     */
 }
 
 static struct buffer_head * ufs_block_getfrag (struct inode *inode,
@@ -308,21 +364,28 @@ out:
 	return result;
 }
 
+/*
+ * This function gets the block which contains the fragment.
+ */
+
 static int ufs_getfrag_block (struct inode *inode, sector_t fragment, struct buffer_head *bh_result, int create)
 {
 	struct super_block * sb = inode->i_sb;
 	struct ufs_sb_private_info * uspi = UFS_SB(sb)->s_uspi;
 	struct buffer_head * bh;
 	int ret, err, new;
-	unsigned long ptr, phys;
+	unsigned long ptr,phys;
+	u64 phys64 = 0;
 	
 	if (!create) {
-		phys = ufs_frag_map(inode, fragment);
-		if (phys)
-			map_bh(bh_result, sb, phys);
+		phys64 = ufs_frag_map(inode, fragment);
+		if (phys64)
+			map_bh(bh_result, sb, phys64);
 		return 0;
 	}
 
+        /* This code entered only while writing ....? */
+
 	err = -EIO;
 	new = 0;
 	ret = 0;
@@ -474,6 +537,7 @@ void ufs_read_inode (struct inode * inod
 	struct super_block * sb;
 	struct ufs_sb_private_info * uspi;
 	struct ufs_inode * ufs_inode;	
+	struct ufs2_inode *ufs2_inode;
 	struct buffer_head * bh;
 	mode_t mode;
 	unsigned i;
@@ -496,6 +560,9 @@ void ufs_read_inode (struct inode * inod
 		ufs_warning (sb, "ufs_read_inode", "unable to read inode %lu\n", inode->i_ino);
 		goto bad_inode;
 	}
+	if ((flags & UFS_TYPE_MASK) == UFS_TYPE_UFS2)
+		goto ufs2_inode;
+
 	ufs_inode = (struct ufs_inode *) (bh->b_data + sizeof(struct ufs_inode) * ufs_inotofsbo(inode->i_ino));
 
 	/*
@@ -564,6 +631,78 @@ void ufs_read_inode (struct inode * inod
 bad_inode:
 	make_bad_inode(inode);
 	return;
+
+ufs2_inode :
+	UFSD(("Reading ufs2 inode, ino %lu\n", inode->i_ino))
+
+	ufs2_inode = (struct ufs2_inode *)(bh->b_data + sizeof(struct ufs2_inode) * ufs_inotofsbo(inode->i_ino));
+
+	/*
+	 * Copy data to the in-core inode.
+	 */
+	inode->i_mode = mode = fs16_to_cpu(sb, ufs2_inode->ui_mode);
+	inode->i_nlink = fs16_to_cpu(sb, ufs2_inode->ui_nlink);
+	if (inode->i_nlink == 0)
+		ufs_error (sb, "ufs_read_inode", "inode %lu has zero nlink\n", inode->i_ino);
+
+        /*
+         * Linux now has 32-bit uid and gid, so we can support EFT.
+         */
+	inode->i_uid = fs32_to_cpu(sb, ufs2_inode->ui_uid);
+	inode->i_gid = fs32_to_cpu(sb, ufs2_inode->ui_gid);
+
+	inode->i_size = fs64_to_cpu(sb, ufs2_inode->ui_size);
+	inode->i_atime.tv_sec = fs32_to_cpu(sb, ufs2_inode->ui_atime.tv_sec);
+	inode->i_ctime.tv_sec = fs32_to_cpu(sb, ufs2_inode->ui_ctime.tv_sec);
+	inode->i_mtime.tv_sec = fs32_to_cpu(sb, ufs2_inode->ui_mtime.tv_sec);
+	inode->i_mtime.tv_nsec = 0;
+	inode->i_atime.tv_nsec = 0;
+	inode->i_ctime.tv_nsec = 0;
+	inode->i_blocks = fs64_to_cpu(sb, ufs2_inode->ui_blocks);
+	inode->i_blksize = PAGE_SIZE; /*This is the optimal IO size(for stat)*/
+
+	inode->i_version++;
+	ufsi->i_flags = fs32_to_cpu(sb, ufs2_inode->ui_flags);
+	ufsi->i_gen = fs32_to_cpu(sb, ufs2_inode->ui_gen);
+	/*
+	ufsi->i_shadow = fs32_to_cpu(sb, ufs_inode->ui_u3.ui_sun.ui_shadow);
+	ufsi->i_oeftflag = fs32_to_cpu(sb, ufs_inode->ui_u3.ui_sun.ui_oeftflag);
+	*/
+	ufsi->i_lastfrag= (inode->i_size + uspi->s_fsize- 1) >> uspi->s_fshift;
+
+	if (S_ISCHR(mode) || S_ISBLK(mode) || inode->i_blocks) {
+		for (i = 0; i < (UFS_NDADDR + UFS_NINDIR); i++)
+			ufsi->i_u1.u2_i_data[i] =
+				ufs2_inode->ui_u2.ui_addr.ui_db[i];
+	}
+	else {
+		for (i = 0; i < (UFS_NDADDR + UFS_NINDIR) * 4; i++)
+			ufsi->i_u1.i_symlink[i] = ufs2_inode->ui_u2.ui_symlink[i];
+	}
+	ufsi->i_osync = 0;
+
+	if (S_ISREG(inode->i_mode)) {
+		inode->i_op = &ufs_file_inode_operations;
+		inode->i_fop = &ufs_file_operations;
+		inode->i_mapping->a_ops = &ufs_aops;
+	} else if (S_ISDIR(inode->i_mode)) {
+		inode->i_op = &ufs_dir_inode_operations;
+		inode->i_fop = &ufs_dir_operations;
+	} else if (S_ISLNK(inode->i_mode)) {
+		if (!inode->i_blocks)
+			inode->i_op = &ufs_fast_symlink_inode_operations;
+		else {
+			inode->i_op = &page_symlink_inode_operations;
+			inode->i_mapping->a_ops = &ufs_aops;
+		}
+	} else   /* TODO  : here ...*/
+		init_special_inode(inode, inode->i_mode,
+			old_decode_dev(fs32_to_cpu(sb, ufsi->i_u1.i_data[0])));
+
+	brelse(bh);
+
+	UFSD(("EXIT\n"))
+	return;
 }
 
 static int ufs_update_inode(struct inode * inode, int do_sync)
--- diff/fs/ufs/namei.c	2003-09-30 15:46:19.000000000 +0100
+++ source/fs/ufs/namei.c	2004-02-23 13:56:47.000000000 +0000
@@ -31,7 +31,10 @@
 #include <linux/buffer_head.h>
 #include "swab.h"	/* will go away - see comment in mknod() */
 
+/*
 #undef UFS_NAMEI_DEBUG
+*/
+#define UFS_NAMEI_DEBUG
 
 #ifdef UFS_NAMEI_DEBUG
 #define UFSD(x) printk("(%s, %d), %s: ", __FILE__, __LINE__, __FUNCTION__); printk x;
--- diff/fs/ufs/super.c	2004-02-18 08:54:12.000000000 +0000
+++ source/fs/ufs/super.c	2004-02-23 13:56:47.000000000 +0000
@@ -58,6 +58,9 @@
  * HP/UX hfs filesystem support added by
  * Martin K. Petersen <mkp@mkp.net>, August 1999
  *
+ * UFS2 (of FreeBSD 5.x) support added by
+ * Niraj Kumar <niraj17@iitbombay.org>, Jan 2004
+ *
  */
 
 
@@ -142,6 +145,28 @@ void ufs_print_super_stuff(struct super_
 	printk("\n");
 }
 
+/*
+ * Print contents of ufs2 ufs_super_block, useful for debugging
+ */
+void ufs2_print_super_stuff(
+     struct super_block *sb,
+      struct ufs_super_block *usb)
+{
+	printk("ufs_print_super_stuff\n");
+	printk("size of usb:     %u\n", sizeof(struct ufs_super_block));
+	printk("  magic:         0x%x\n", fs32_to_cpu(sb, usb->fs_magic));
+	printk("  fs_size:   %u\n",fs64_to_cpu(sb, usb->fs_u11.fs_u2.fs_size));
+	printk("  fs_dsize:  %u\n",fs64_to_cpu(sb, usb->fs_u11.fs_u2.fs_dsize));
+	printk("  fs_volname:  %s\n", usb->fs_u11.fs_u2.fs_volname);
+	printk("  fs_fsmnt:  %s\n", usb->fs_u11.fs_u2.fs_fsmnt);
+	printk("  fs_sblockloc: %u\n",fs64_to_cpu(sb,
+			usb->fs_u11.fs_u2.fs_sblockloc));
+	printk("  cs_ndir(No of dirs):  %u\n",fs64_to_cpu(sb,
+			usb->fs_u11.fs_u2.fs_cstotal.cs_ndir));
+	printk("  cs_nbfree(No of free blocks):  %u\n",fs64_to_cpu(sb,
+			usb->fs_u11.fs_u2.fs_cstotal.cs_nbfree));
+	printk("\n");
+}
 
 /*
  * Print contents of ufs_cylinder_group, useful for debugging
@@ -253,7 +278,7 @@ void ufs_warning (struct super_block * s
 
 enum {
 	Opt_type_old, Opt_type_sunx86, Opt_type_sun, Opt_type_44bsd,
-	Opt_type_hp, Opt_type_nextstepcd, Opt_type_nextstep,
+	Opt_type_ufs2, Opt_type_hp, Opt_type_nextstepcd, Opt_type_nextstep,
 	Opt_type_openstep, Opt_onerror_panic, Opt_onerror_lock,
 	Opt_onerror_umount, Opt_onerror_repair, Opt_err
 };
@@ -263,6 +288,8 @@ static match_table_t tokens = {
 	{Opt_type_sunx86, "ufstype=sunx86"},
 	{Opt_type_sun, "ufstype=sun"},
 	{Opt_type_44bsd, "ufstype=44bsd"},
+	{Opt_type_ufs2, "ufstype=ufs2"},
+	{Opt_type_ufs2, "ufstype=5xbsd"},
 	{Opt_type_hp, "ufstype=hp"},
 	{Opt_type_nextstepcd, "ufstype=nextstep-cd"},
 	{Opt_type_nextstep, "ufstype=nextstep"},
@@ -307,6 +334,10 @@ static int ufs_parse_options (char * opt
 			ufs_clear_opt (*mount_options, UFSTYPE);
 			ufs_set_opt (*mount_options, UFSTYPE_44BSD);
 			break;
+		case Opt_type_ufs2:
+			ufs_clear_opt(*mount_options, UFSTYPE);
+			ufs_set_opt(*mount_options, UFSTYPE_UFS2);
+			break;
 		case Opt_type_hp:
 			ufs_clear_opt (*mount_options, UFSTYPE);
 			ufs_set_opt (*mount_options, UFSTYPE_HP);
@@ -356,13 +387,20 @@ static int ufs_parse_options (char * opt
 int ufs_read_cylinder_structures (struct super_block * sb) {
 	struct ufs_sb_info * sbi = UFS_SB(sb);
 	struct ufs_sb_private_info * uspi;
+	struct ufs_super_block *usb;
 	struct ufs_buffer_head * ubh;
 	unsigned char * base, * space;
 	unsigned size, blks, i;
+	unsigned flags = 0;
 	
 	UFSD(("ENTER\n"))
 	
 	uspi = sbi->s_uspi;
+
+	usb  = (struct ufs_super_block *)
+		((struct ufs_buffer_head *)uspi)->bh[0]->b_data;
+
+        flags = UFS_SB(sb)->s_flags;
 	
 	/*
 	 * Read cs structures from (usually) first data block
@@ -377,11 +415,22 @@ int ufs_read_cylinder_structures (struct
 		size = uspi->s_bsize;
 		if (i + uspi->s_fpb > blks)
 			size = (blks - i) * uspi->s_fsize;
-		ubh = ubh_bread(sb, uspi->s_csaddr + i, size);
-		if (!ubh)
-			goto failed;
-		ubh_ubhcpymem (space, ubh, size);
-		sbi->s_csp[ufs_fragstoblks(i)] = (struct ufs_csum *)space;
+
+		if ((flags & UFS_TYPE_MASK) == UFS_TYPE_UFS2) {
+			ubh = ubh_bread(sb,
+				fs64_to_cpu(sb, usb->fs_u11.fs_u2.fs_csaddr) + i, size);
+			if (!ubh)
+				goto failed;
+			ubh_ubhcpymem (space, ubh, size);
+			sbi->s_csp[ufs_fragstoblks(i)]=(struct ufs_csum *)space;
+		}
+		else {
+			ubh = ubh_bread(sb, uspi->s_csaddr + i, size);
+			if (!ubh)
+				goto failed;
+			ubh_ubhcpymem(space, ubh, size);
+			sbi->s_csp[ufs_fragstoblks(i)]=(struct ufs_csum *)space;
+		}
 		space += size;
 		ubh_brelse (ubh);
 		ubh = NULL;
@@ -480,6 +529,7 @@ static int ufs_fill_super(struct super_b
 	struct ufs_super_block_first * usb1;
 	struct ufs_super_block_second * usb2;
 	struct ufs_super_block_third * usb3;
+	struct ufs_super_block *usb;
 	struct ufs_buffer_head * ubh;	
 	struct inode *inode;
 	unsigned block_size, super_block_size;
@@ -520,7 +570,7 @@ static int ufs_fill_super(struct super_b
 		if (!silent)
 			printk("You didn't specify the type of your ufs filesystem\n\n"
 			"mount -t ufs -o ufstype="
-			"sun|sunx86|44bsd|old|hp|nextstep|netxstep-cd|openstep ...\n\n"
+			"sun|sunx86|44bsd|ufs2|5xbsd|old|hp|nextstep|netxstep-cd|openstep ...\n\n"
 			">>>WARNING<<< Wrong ufstype may corrupt your filesystem, "
 			"default is ufstype=old\n");
 		ufs_set_opt (sbi->s_mount_opt, UFSTYPE_OLD);
@@ -545,6 +595,19 @@ static int ufs_fill_super(struct super_b
 		uspi->s_sbbase = 0;
 		flags |= UFS_DE_44BSD | UFS_UID_44BSD | UFS_ST_44BSD | UFS_CG_44BSD;
 		break;
+	case UFS_MOUNT_UFSTYPE_UFS2:
+		UFSD(("ufstype=ufs2\n"))
+		uspi->s_fsize = block_size = 512;
+		uspi->s_fmask = ~(512 - 1);
+		uspi->s_fshift = 9;
+		uspi->s_sbsize = super_block_size = 1536;
+		uspi->s_sbbase =  0;
+		flags |= UFS_TYPE_UFS2 | UFS_DE_44BSD | UFS_UID_44BSD | UFS_ST_44BSD | UFS_CG_44BSD;
+		if (!(sb->s_flags & MS_RDONLY)) {
+			printk(KERN_INFO "ufstype=ufs2 is supported read-only\n");
+			sb->s_flags |= MS_RDONLY;
+ 		}
+		break;
 		
 	case UFS_MOUNT_UFSTYPE_SUN:
 		UFSD(("ufstype=sun\n"))
@@ -657,27 +720,37 @@ again:	
 	/*
 	 * read ufs super block from device
 	 */
-	ubh = ubh_bread_uspi (uspi, sb, uspi->s_sbbase + UFS_SBLOCK/block_size, super_block_size);
+	if ( (flags & UFS_TYPE_MASK) == UFS_TYPE_UFS2) {
+		ubh = ubh_bread_uspi(uspi, sb, uspi->s_sbbase + SBLOCK_UFS2/block_size, super_block_size);
+	}
+	else {
+		ubh = ubh_bread_uspi(uspi, sb, uspi->s_sbbase + UFS_SBLOCK/block_size, super_block_size);
+	}
 	if (!ubh) 
-		goto failed;
+            goto failed;
+
 	
 	usb1 = ubh_get_usb_first(USPI_UBH);
 	usb2 = ubh_get_usb_second(USPI_UBH);
 	usb3 = ubh_get_usb_third(USPI_UBH);
+	usb  = (struct ufs_super_block *)
+		((struct ufs_buffer_head *)uspi)->bh[0]->b_data ;
 
 	/*
 	 * Check ufs magic number
 	 */
-	switch (__constant_le32_to_cpu(usb3->fs_magic)) {
+	switch ((uspi->fs_magic = __constant_le32_to_cpu(usb3->fs_magic))) {
 		case UFS_MAGIC:
+		case UFS2_MAGIC:
 		case UFS_MAGIC_LFN:
 	        case UFS_MAGIC_FEA:
 	        case UFS_MAGIC_4GB:
 			sbi->s_bytesex = BYTESEX_LE;
 			goto magic_found;
 	}
-	switch (__constant_be32_to_cpu(usb3->fs_magic)) {
+	switch ((uspi->fs_magic = __constant_be32_to_cpu(usb3->fs_magic))) {
 		case UFS_MAGIC:
+		case UFS2_MAGIC:
 		case UFS_MAGIC_LFN:
 	        case UFS_MAGIC_FEA:
 	        case UFS_MAGIC_4GB:
@@ -748,7 +821,10 @@ magic_found:
 	}
 
 #ifdef UFS_SUPER_DEBUG_MORE
-	ufs_print_super_stuff(sb, usb1, usb2, usb3);
+        if ((flags & UFS_TYPE_MASK) == UFS_TYPE_UFS2)
+		ufs2_print_super_stuff(sb,usb);
+        else
+		ufs_print_super_stuff(sb, usb1, usb2, usb3);
 #endif
 
 	/*
@@ -802,8 +878,16 @@ magic_found:
 	uspi->s_dblkno = fs32_to_cpu(sb, usb1->fs_dblkno);
 	uspi->s_cgoffset = fs32_to_cpu(sb, usb1->fs_cgoffset);
 	uspi->s_cgmask = fs32_to_cpu(sb, usb1->fs_cgmask);
-	uspi->s_size = fs32_to_cpu(sb, usb1->fs_size);
-	uspi->s_dsize = fs32_to_cpu(sb, usb1->fs_dsize);
+
+	if ((flags & UFS_TYPE_MASK) == UFS_TYPE_UFS2) {
+		uspi->s_u2_size  = fs64_to_cpu(sb, usb->fs_u11.fs_u2.fs_size);
+		uspi->s_u2_dsize = fs64_to_cpu(sb, usb->fs_u11.fs_u2.fs_dsize);
+	}
+	else {
+		uspi->s_size  =  fs32_to_cpu(sb, usb1->fs_size);
+		uspi->s_dsize =  fs32_to_cpu(sb, usb1->fs_dsize);
+	}
+
 	uspi->s_ncg = fs32_to_cpu(sb, usb1->fs_ncg);
 	/* s_bsize already set */
 	/* s_fsize already set */
@@ -1021,21 +1105,36 @@ int ufs_statfs (struct super_block * sb,
 {
 	struct ufs_sb_private_info * uspi;
 	struct ufs_super_block_first * usb1;
+	struct ufs_super_block * usb;
+	unsigned  flags = 0;
 
 	lock_kernel();
 
 	uspi = UFS_SB(sb)->s_uspi;
 	usb1 = ubh_get_usb_first (USPI_UBH);
+	usb  = (struct ufs_super_block *)
+		((struct ufs_buffer_head *)uspi)->bh[0]->b_data ;
 	
-	buf->f_type = UFS_MAGIC;
+	flags = UFS_SB(sb)->s_flags;
+	if ((flags & UFS_TYPE_MASK) == UFS_TYPE_UFS2) {
+		buf->f_type = UFS2_MAGIC;
+		buf->f_blocks = usb->fs_u11.fs_u2.fs_dsize;
+		buf->f_bfree = ufs_blkstofrags(fs64_to_cpu(sb, usb->fs_u11.fs_u2.fs_cstotal.cs_nbfree)) +
+			fs64_to_cpu(sb, usb->fs_u11.fs_u2.fs_cstotal.cs_nffree);
+		buf->f_ffree = fs64_to_cpu(sb,
+        		usb->fs_u11.fs_u2.fs_cstotal.cs_nifree);
+	}
+	else {
+		buf->f_type = UFS_MAGIC;
+		buf->f_blocks = uspi->s_dsize;
+		buf->f_bfree = ufs_blkstofrags(fs32_to_cpu(sb, usb1->fs_cstotal.cs_nbfree)) +
+			fs32_to_cpu(sb, usb1->fs_cstotal.cs_nffree);
+		buf->f_ffree = fs32_to_cpu(sb, usb1->fs_cstotal.cs_nifree);
+	}
 	buf->f_bsize = sb->s_blocksize;
-	buf->f_blocks = uspi->s_dsize;
-	buf->f_bfree = ufs_blkstofrags(fs32_to_cpu(sb, usb1->fs_cstotal.cs_nbfree)) +
-		fs32_to_cpu(sb, usb1->fs_cstotal.cs_nffree);
 	buf->f_bavail = (buf->f_bfree > (((long)buf->f_blocks / 100) * uspi->s_minfree))
 		? (buf->f_bfree - (((long)buf->f_blocks / 100) * uspi->s_minfree)) : 0;
 	buf->f_files = uspi->s_ncg * uspi->s_ipg;
-	buf->f_ffree = fs32_to_cpu(sb, usb1->fs_cstotal.cs_nifree);
 	buf->f_namelen = UFS_MAXNAMLEN;
 
 	unlock_kernel();
--- diff/fs/ufs/util.c	2003-05-21 11:49:55.000000000 +0100
+++ source/fs/ufs/util.c	2004-02-23 13:56:47.000000000 +0000
@@ -24,10 +24,11 @@
 
 
 struct ufs_buffer_head * _ubh_bread_ (struct ufs_sb_private_info * uspi,
-	struct super_block *sb, unsigned fragment, unsigned size)
+	struct super_block *sb, u64 fragment, u64 size)
 {
 	struct ufs_buffer_head * ubh;
-	unsigned i, j, count;
+	unsigned i, j ;
+	u64  count = 0;
 	if (size & ~uspi->s_fmask)
 		return NULL;
 	count = size >> uspi->s_fshift;
@@ -53,9 +54,10 @@ failed:
 }
 
 struct ufs_buffer_head * ubh_bread_uspi (struct ufs_sb_private_info * uspi,
-	struct super_block *sb, unsigned fragment, unsigned size)
+	struct super_block *sb, u64 fragment, u64 size)
 {
-	unsigned i, j, count;
+	unsigned i, j;
+	u64 count = 0;
 	if (size & ~uspi->s_fmask)
 		return NULL;
 	count = size >> uspi->s_fshift;
--- diff/fs/ufs/util.h	2003-05-21 11:49:46.000000000 +0100
+++ source/fs/ufs/util.h	2004-02-23 13:56:47.000000000 +0000
@@ -228,8 +228,8 @@ ufs_set_inode_gid(struct super_block *sb
  * These functions manipulate ufs buffers
  */
 #define ubh_bread(sb,fragment,size) _ubh_bread_(uspi,sb,fragment,size)  
-extern struct ufs_buffer_head * _ubh_bread_(struct ufs_sb_private_info *, struct super_block *, unsigned, unsigned);
-extern struct ufs_buffer_head * ubh_bread_uspi(struct ufs_sb_private_info *, struct super_block *, unsigned, unsigned);
+extern struct ufs_buffer_head * _ubh_bread_(struct ufs_sb_private_info *, struct super_block *, u64 , u64);
+extern struct ufs_buffer_head * ubh_bread_uspi(struct ufs_sb_private_info *, struct super_block *, u64, u64);
 extern void ubh_brelse (struct ufs_buffer_head *);
 extern void ubh_brelse_uspi (struct ufs_sb_private_info *);
 extern void ubh_mark_buffer_dirty (struct ufs_buffer_head *);
--- diff/fs/xfs/linux/xfs_aops.c	2004-02-18 08:54:12.000000000 +0000
+++ source/fs/xfs/linux/xfs_aops.c	2004-02-23 13:56:47.000000000 +0000
@@ -988,7 +988,8 @@ linvfs_direct_IO(
 	if (error)
 		return -error;
 
-	return blockdev_direct_IO(rw, iocb, inode, iomap.iomap_target->pbr_bdev,
+	return blockdev_direct_IO_no_locking(rw, iocb, inode,
+		iomap.iomap_target->pbr_bdev,
 		iov, offset, nr_segs,
 		linvfs_get_blocks_direct,
 		linvfs_unwritten_convert_direct);
--- diff/fs/xfs/linux/xfs_super.c	2004-02-09 10:36:12.000000000 +0000
+++ source/fs/xfs/linux/xfs_super.c	2004-02-23 13:56:47.000000000 +0000
@@ -266,7 +266,7 @@ xfs_blkdev_get(
 {
 	int			error = 0;
 
-	*bdevp = open_bdev_excl(name, 0, BDEV_FS, mp);
+	*bdevp = open_bdev_excl(name, 0, mp);
 	if (IS_ERR(*bdevp)) {
 		error = PTR_ERR(*bdevp);
 		printk("XFS: Invalid device [%s], error=%d\n", name, error);
@@ -280,7 +280,7 @@ xfs_blkdev_put(
 	struct block_device	*bdev)
 {
 	if (bdev)
-		close_bdev_excl(bdev, BDEV_FS);
+		close_bdev_excl(bdev);
 }
 
 void
--- diff/fs/xfs/xfs_inode.c	2004-02-09 10:36:12.000000000 +0000
+++ source/fs/xfs/xfs_inode.c	2004-02-23 13:56:47.000000000 +0000
@@ -3707,7 +3707,8 @@ xfs_iaccess(
 	 * Read/write DACs are always overridable.
 	 * Executable DACs are overridable if at least one exec bit is set.
 	 */
-	if ((orgmode & (S_IRUSR|S_IWUSR)) || (inode->i_mode & S_IXUGO))
+	if (!(orgmode & S_IXUSR) || (inode->i_mode & S_IXUGO) ||
+	    (ip->i_d.di_mode & S_IFMT) == S_IFDIR)
 		if (capable_cred(cr, CAP_DAC_OVERRIDE))
 			return 0;
 
--- diff/include/acpi/acconfig.h	2004-02-09 10:36:12.000000000 +0000
+++ source/include/acpi/acconfig.h	2004-02-23 13:56:47.000000000 +0000
@@ -64,7 +64,7 @@
 
 /* Version string */
 
-#define ACPI_CA_VERSION                 0x20040116
+#define ACPI_CA_VERSION                 0x20040211
 
 /* Maximum objects in the various object caches */
 
--- diff/include/asm-alpha/param.h	2002-10-16 04:27:55.000000000 +0100
+++ source/include/asm-alpha/param.h	2004-02-23 13:56:47.000000000 +0000
@@ -19,10 +19,6 @@
 
 #define EXEC_PAGESIZE	8192
 
-#ifndef NGROUPS
-#define NGROUPS		32
-#endif
-
 #ifndef NOGROUP
 #define NOGROUP		(-1)
 #endif
--- diff/include/asm-alpha/spinlock.h	2003-10-09 09:47:17.000000000 +0100
+++ source/include/asm-alpha/spinlock.h	2004-02-23 13:56:47.000000000 +0000
@@ -6,6 +6,10 @@
 #include <linux/kernel.h>
 #include <asm/current.h>
 
+#ifdef CONFIG_LOCKMETER
+#undef DEBUG_SPINLOCK
+#undef DEBUG_RWLOCK
+#endif
 
 /*
  * Simple spin lock operations.  There are two variants, one clears IRQ's
@@ -95,9 +99,18 @@ static inline int _raw_spin_trylock(spin
 
 typedef struct {
 	volatile int write_lock:1, read_counter:31;
+#ifdef CONFIG_LOCKMETER
+	/* required for LOCKMETER since all bits in lock are used */
+	/* need this storage for CPU and lock INDEX ............. */
+	unsigned magic;
+#endif
 } /*__attribute__((aligned(32)))*/ rwlock_t;
 
+#ifdef CONFIG_LOCKMETER
+#define RW_LOCK_UNLOCKED (rwlock_t) { 0, 0, 0 }
+#else
 #define RW_LOCK_UNLOCKED (rwlock_t) { 0, 0 }
+#endif
 
 #define rwlock_init(x)	do { *(x) = RW_LOCK_UNLOCKED; } while(0)
 #define rwlock_is_locked(x)	(*(volatile int *)(x) != 0)
@@ -169,4 +182,41 @@ static inline void _raw_read_unlock(rwlo
 	: "m" (*lock) : "memory");
 }
 
+#ifdef CONFIG_LOCKMETER
+static inline int _raw_write_trylock(rwlock_t *lock)
+{
+	long temp,result;
+
+	__asm__ __volatile__(
+	"	ldl_l %1,%0\n"
+	"	mov $31,%2\n"
+	"	bne %1,1f\n"
+	"	or $31,1,%2\n"
+	"	stl_c %2,%0\n"
+	"1:	mb\n"
+	: "=m" (*(volatile int *)lock), "=&r" (temp), "=&r" (result)
+	: "m" (*(volatile int *)lock)
+	);
+
+	return (result);
+}
+
+static inline int _raw_read_trylock(rwlock_t *lock)
+{
+	unsigned long temp,result;
+
+	__asm__ __volatile__(
+	"	ldl_l %1,%0\n"
+	"	mov $31,%2\n"
+	"	blbs %1,1f\n"
+	"	subl %1,2,%2\n"
+	"	stl_c %2,%0\n"
+	"1:	mb\n"
+	: "=m" (*(volatile int *)lock), "=&r" (temp), "=&r" (result)
+	: "m" (*(volatile int *)lock)
+	);
+	return (result);
+}
+#endif /* CONFIG_LOCKMETER */
+
 #endif /* _ALPHA_SPINLOCK_H */
--- diff/include/asm-alpha/unistd.h	2003-07-22 18:54:27.000000000 +0100
+++ source/include/asm-alpha/unistd.h	2004-02-23 13:56:47.000000000 +0000
@@ -548,15 +548,14 @@ type name (type1 arg1,type2 arg2,type3 a
 
 #include <linux/string.h>
 #include <linux/signal.h>
+#include <linux/syscalls.h>
 #include <asm/ptrace.h>
 
-extern long sys_open(const char *, int, int);
 static inline long open(const char * name, int mode, int flags)
 {
 	return sys_open(name, mode, flags);
 }
 
-extern long sys_dup(int);
 static inline long dup(int fd)
 {
 	return sys_dup(fd);
@@ -564,17 +563,14 @@ static inline long dup(int fd)
 
 static inline long close(int fd)
 {
-	extern long sys_close(unsigned int);
 	return sys_close(fd);
 }
 
-extern off_t sys_lseek(int, off_t, int);
 static inline off_t lseek(int fd, off_t off, int whence)
 {
 	return sys_lseek(fd, off, whence);
 }
 
-extern long sys_exit(int);
 static inline long _exit(int value)
 {
 	return sys_exit(value);
@@ -582,13 +578,11 @@ static inline long _exit(int value)
 
 #define exit(x) _exit(x)
 
-extern long sys_write(int, const char *, size_t);
 static inline long write(int fd, const char * buf, size_t nr)
 {
 	return sys_write(fd, buf, nr);
 }
 
-extern long sys_read(int, char *, size_t);
 static inline long read(int fd, char * buf, size_t nr)
 {
 	return sys_read(fd, buf, nr);
@@ -596,19 +590,20 @@ static inline long read(int fd, char * b
 
 extern long execve(char *, char **, char **);
 
-extern long sys_setsid(void);
 static inline long setsid(void)
 {
 	return sys_setsid();
 }
 
-struct rusage;
-extern asmlinkage long sys_wait4(pid_t, unsigned int *, int, struct rusage *);
 static inline pid_t waitpid(int pid, int * wait_stat, int flags)
 {
 	return sys_wait4(pid, wait_stat, flags, NULL);
 }
 
+asmlinkage int sys_execve(char *ufilename, char **argv, char **envp,
+			unsigned long a3, unsigned long a4, unsigned long a5,
+			struct pt_regs regs);
+
 #endif /* __KERNEL_SYSCALLS__ */
 
 /*
--- diff/include/asm-arm/param.h	2003-09-17 12:28:12.000000000 +0100
+++ source/include/asm-arm/param.h	2004-02-23 13:56:47.000000000 +0000
@@ -26,10 +26,6 @@
 
 #define EXEC_PAGESIZE	4096
 
-#ifndef NGROUPS
-#define NGROUPS         32
-#endif
-
 #ifndef NOGROUP
 #define NOGROUP         (-1)
 #endif
--- diff/include/asm-arm/pci.h	2004-02-18 08:54:12.000000000 +0000
+++ source/include/asm-arm/pci.h	2004-02-23 13:56:47.000000000 +0000
@@ -3,23 +3,10 @@
 
 #ifdef __KERNEL__
 #include <linux/config.h>
-#include <linux/dma-mapping.h>
+#include <asm-generic/pci-dma-compat.h>
 
 #include <asm/hardware.h> /* for PCIBIOS_MIN_* */
 
-#ifdef CONFIG_SA1111
-/*
- * Keep the SA1111 DMA-mapping tricks until the USB layer gets
- * properly converted to the new DMA-mapping API, at which time
- * most of this file can die.
- */
-#define SA1111_FAKE_PCIDEV ((struct pci_dev *) 1111)
-#define pcidev_is_sa1111(dev) (dev == SA1111_FAKE_PCIDEV)
-#else
-#define pcidev_is_sa1111(dev) (0)
-#endif
-
-
 #define pcibios_scan_all_fns(a, b)	0
 
 static inline void pcibios_set_master(struct pci_dev *dev)
@@ -39,144 +26,21 @@ static inline void pcibios_penalize_isa_
  */
 #define PCI_DMA_BUS_IS_PHYS     (0)
 
-static inline void *
-pci_alloc_consistent(struct pci_dev *hwdev, size_t size, dma_addr_t *handle)
-{
-	int gfp = GFP_ATOMIC;
-
-	if (hwdev == NULL || pcidev_is_sa1111(hwdev) ||
-	    hwdev->dma_mask != 0xffffffff)
-		gfp |= GFP_DMA;
-
-	return consistent_alloc(gfp, size, handle, 0);
-}
-
-static inline void
-pci_free_consistent(struct pci_dev *hwdev, size_t size, void *vaddr,
-		    dma_addr_t handle)
-{
-	dma_free_coherent(hwdev ? &hwdev->dev : NULL, size, vaddr, handle);
-}
-
-static inline dma_addr_t
-pci_map_single(struct pci_dev *hwdev, void *ptr, size_t size, int dir)
-{
-	if (pcidev_is_sa1111(hwdev))
-		return sa1111_map_single(ptr, size, dir);
-
-	return dma_map_single(hwdev ? &hwdev->dev : NULL, ptr, size, dir);
-}
-
-static inline void
-pci_unmap_single(struct pci_dev *hwdev, dma_addr_t handle, size_t size, int dir)
-{
-	if (pcidev_is_sa1111(hwdev)) {
-		sa1111_unmap_single(handle, size, dir);
-		return;
-	}
-
-	dma_unmap_single(hwdev ? &hwdev->dev : NULL, handle, size, dir);
-}
-
-static inline int
-pci_map_sg(struct pci_dev *hwdev, struct scatterlist *sg, int nents, int dir)
-{
-	if (pcidev_is_sa1111(hwdev))
-		return sa1111_map_sg(sg, nents, dir);
-
-	return dma_map_sg(hwdev ? &hwdev->dev : NULL, sg, nents, dir);
-}
-
-static inline void
-pci_unmap_sg(struct pci_dev *hwdev, struct scatterlist *sg, int nents, int dir)
-{
-	if (pcidev_is_sa1111(hwdev)) {
-		sa1111_unmap_sg(sg, nents, dir);
-		return;
-	}
-
-	return dma_unmap_sg(hwdev ? &hwdev->dev : NULL, sg, nents, dir);
-}
-
-static inline dma_addr_t
-pci_map_page(struct pci_dev *hwdev, struct page *page, unsigned long offset,
-		size_t size, int dir)
-{
-	return	pci_map_single(hwdev, page_address(page) + offset, size, dir);
-}
-
-static inline void
-pci_unmap_page(struct pci_dev *hwdev, dma_addr_t handle, size_t size, int dir)
-{
-	return pci_unmap_single(hwdev, handle, size, dir);
-}
-
-static inline void
-pci_dma_sync_single(struct pci_dev *hwdev, dma_addr_t handle, size_t size, int dir)
-{
-	if (pcidev_is_sa1111(hwdev)) {
-	  	sa1111_dma_sync_single(handle, size, dir);
-		return;
-	}
-
-	return dma_sync_single(hwdev ? &hwdev->dev : NULL, handle, size, dir);
-}
-
-static inline void
-pci_dma_sync_sg(struct pci_dev *hwdev, struct scatterlist *sg, int nelems, int dir)
-{
-	if (pcidev_is_sa1111(hwdev)) {
-	  	sa1111_dma_sync_sg(sg, nelems, dir);
-		return;
-	}
-
-	return dma_sync_sg(hwdev ? &hwdev->dev : NULL, sg, nelems, dir);
-}
-
-static inline int pci_dma_supported(struct pci_dev *hwdev, u64 mask)
-{
-	return 1;
-}
-
 /*
  * We don't support DAC DMA cycles.
  */
 #define pci_dac_dma_supported(pci_dev, mask)	(0)
 
-
-#if defined(CONFIG_SA1111) && !defined(CONFIG_PCI)
-/*
- * SA-1111 needs these prototypes even when !defined(CONFIG_PCI)
- *
- * kmem_cache style wrapper around pci_alloc_consistent()
- */
-struct pci_pool *pci_pool_create (const char *name, struct pci_dev *dev,
-		size_t size, size_t align, size_t allocation);
-void pci_pool_destroy (struct pci_pool *pool);
-
-void *pci_pool_alloc (struct pci_pool *pool, int flags, dma_addr_t *handle);
-void pci_pool_free (struct pci_pool *pool, void *vaddr, dma_addr_t addr);
-#endif
-
 /*
  * Whether pci_unmap_{single,page} is a nop depends upon the
  * configuration.
  */
-#if defined(CONFIG_PCI) || defined(CONFIG_SA1111)
 #define DECLARE_PCI_UNMAP_ADDR(ADDR_NAME)	dma_addr_t ADDR_NAME;
 #define DECLARE_PCI_UNMAP_LEN(LEN_NAME)		__u32 LEN_NAME;
 #define pci_unmap_addr(PTR, ADDR_NAME)		((PTR)->ADDR_NAME)
 #define pci_unmap_addr_set(PTR, ADDR_NAME, VAL)	(((PTR)->ADDR_NAME) = (VAL))
 #define pci_unmap_len(PTR, LEN_NAME)		((PTR)->LEN_NAME)
 #define pci_unmap_len_set(PTR, LEN_NAME, VAL)	(((PTR)->LEN_NAME) = (VAL))
-#else
-#define DECLARE_PCI_UNMAP_ADDR(ADDR_NAME)
-#define DECLARE_PCI_UNMAP_LEN(LEN_NAME)
-#define pci_unmap_addr(PTR, ADDR_NAME)		(0)
-#define pci_unmap_addr_set(PTR, ADDR_NAME, VAL)	do { } while (0)
-#define pci_unmap_len(PTR, LEN_NAME)		(0)
-#define pci_unmap_len_set(PTR, LEN_NAME, VAL)	do { } while (0)
-#endif
 
 #define HAVE_PCI_MMAP
 extern int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma,
--- diff/include/asm-arm/tlb.h	2003-06-09 14:18:20.000000000 +0100
+++ source/include/asm-arm/tlb.h	2004-02-23 13:56:47.000000000 +0000
@@ -70,6 +70,12 @@ tlb_finish_mmu(struct mmu_gather *tlb, u
 	check_pgt_cache();
 }
 
+static inline unsigned int
+tlb_is_full_mm(struct mmu_gather *tlb)
+{
+     return tlb->fullmm;
+}
+
 #define tlb_remove_tlb_entry(tlb,ptep,address)	do { } while (0)
 
 #define tlb_start_vma(tlb,vma)						\
--- diff/include/asm-arm/unistd.h	2004-02-18 08:54:12.000000000 +0000
+++ source/include/asm-arm/unistd.h	2004-02-23 13:56:47.000000000 +0000
@@ -450,54 +450,45 @@ type name(type1 arg1, type2 arg2, type3 
 
 #ifdef __KERNEL_SYSCALLS__
 
-struct rusage;
-asmlinkage long sys_wait4(pid_t pid,unsigned int * stat_addr, int options, struct rusage * ru);
+#include <linux/syscalls.h>
 
 static inline pid_t setsid(void)
 {
-	extern long sys_setsid(void);
 	return sys_setsid();
 }
 
 static inline long write(int fd, const char *buf, off_t count)
 {
-	extern long sys_write(int, const char *, int);
 	return sys_write(fd, buf, count);
 }
 
 static inline long read(int fd, char *buf, off_t count)
 {
-	extern long sys_read(int, char *, int);
 	return sys_read(fd, buf, count);
 }
 
 static inline off_t lseek(int fd, off_t offset, int count)
 {
-	extern off_t sys_lseek(int, off_t, int);
 	return sys_lseek(fd, offset, count);
 }
 
 static inline long dup(int fd)
 {
-	extern long sys_dup(int);
 	return sys_dup(fd);
 }
 
 static inline long open(const char *file, int flag, int mode)
 {
-	extern long sys_open(const char *, int, int);
 	return sys_open(file, flag, mode);
 }
 
 static inline long close(int fd)
 {
-	extern long sys_close(unsigned int);
 	return sys_close(fd);
 }
 
 static inline long _exit(int exitcode)
 {
-	extern long sys_exit(int) __attribute__((noreturn));
 	return sys_exit(exitcode);
 }
 
@@ -506,6 +497,16 @@ static inline pid_t waitpid(pid_t pid, i
 	return sys_wait4((int)pid, wait_stat, options, NULL);
 }
 
+struct pt_regs;
+asmlinkage int sys_execve(char *filenamei, char **argv, char **envp,
+			struct pt_regs *regs);
+asmlinkage int sys_clone(unsigned long clone_flags, unsigned long newsp,
+			struct pt_regs *regs);
+asmlinkage int sys_fork(struct pt_regs *regs);
+asmlinkage int sys_vfork(struct pt_regs *regs);
+asmlinkage int sys_pipe(unsigned long *fildes);
+asmlinkage int sys_ptrace(long request, long pid, long addr, long data);
+
 /*
  * The following two can't be eliminated yet - they rely on
  * specific conditions.
--- diff/include/asm-arm26/module.h	2003-06-30 10:07:24.000000000 +0100
+++ source/include/asm-arm26/module.h	2004-02-23 13:56:47.000000000 +0000
@@ -4,9 +4,4 @@
  * This file contains the arm architecture specific module code.
  */
 
-#define module_map(x)		vmalloc(x)
-#define module_unmap(x)		vfree(x)
-#define module_arch_init(x)	(0)
-#define arch_init_modules(x)	do { } while (0)
-
 #endif /* _ASM_ARM_MODULE_H */
--- diff/include/asm-arm26/param.h	2003-06-30 10:07:24.000000000 +0100
+++ source/include/asm-arm26/param.h	2004-02-23 13:56:47.000000000 +0000
@@ -22,10 +22,6 @@
 # define HZ		100
 #endif
 
-#ifndef NGROUPS
-#define NGROUPS         32
-#endif
-
 #ifndef NOGROUP
 #define NOGROUP         (-1)
 #endif
--- diff/include/asm-arm26/unistd.h	2003-06-30 10:07:24.000000000 +0100
+++ source/include/asm-arm26/unistd.h	2004-02-23 13:56:47.000000000 +0000
@@ -377,8 +377,7 @@ type name(type1 arg1, type2 arg2, type3 
 
 #ifdef __KERNEL_SYSCALLS__
 
-struct rusage;
-asmlinkage long sys_wait4(pid_t pid,unsigned int * stat_addr, int options, struct rusage * ru);
+#include <linux/syscalls.h>
 
 static inline long idle(void)
 {
@@ -388,61 +387,51 @@ static inline long idle(void)
 
 static inline long pause(void)
 {
-	extern long sys_pause(void);
 	return sys_pause();
 }
 
 static inline long sync(void)
 {
-	extern long sys_sync(void);
 	return sys_sync();
 }
 
 static inline pid_t setsid(void)
 {
-	extern long sys_setsid(void);
 	return sys_setsid();
 }
 
 static inline long write(int fd, const char *buf, off_t count)
 {
-	extern long sys_write(int, const char *, int);
 	return sys_write(fd, buf, count);
 }
 
 static inline long read(int fd, char *buf, off_t count)
 {
-	extern long sys_read(int, char *, int);
 	return sys_read(fd, buf, count);
 }
 
 static inline off_t lseek(int fd, off_t offset, int count)
 {
-	extern off_t sys_lseek(int, off_t, int);
 	return sys_lseek(fd, offset, count);
 }
 
 static inline long dup(int fd)
 {
-	extern long sys_dup(int);
 	return sys_dup(fd);
 }
 
 static inline long open(const char *file, int flag, int mode)
 {
-	extern long sys_open(const char *, int, int);
 	return sys_open(file, flag, mode);
 }
 
 static inline long close(int fd)
 {
-	extern long sys_close(unsigned int);
 	return sys_close(fd);
 }
 
 static inline long _exit(int exitcode)
 {
-	extern long sys_exit(int) __attribute__((noreturn));
 	return sys_exit(exitcode);
 }
 
@@ -453,8 +442,7 @@ static inline pid_t waitpid(pid_t pid, i
 
 static inline long delete_module(const char *name)
 {
-	extern long sys_delete_module(const char *name);
-	return sys_delete_module(name);
+	return sys_delete_module(name, 0);
 }
 
 static inline pid_t wait(int * wait_stat)
@@ -462,6 +450,16 @@ static inline pid_t wait(int * wait_stat
 	return sys_wait4(-1, wait_stat, 0, NULL);
 }
 
+struct pt_regs;
+asmlinkage int sys_execve(char *filenamei, char **argv, char **envp,
+			struct pt_regs *regs);
+asmlinkage int sys_clone(unsigned long clone_flags, unsigned long newsp,
+			struct pt_regs *regs);
+asmlinkage int sys_fork(struct pt_regs *regs);
+asmlinkage int sys_vfork(struct pt_regs *regs);
+asmlinkage int sys_pipe(unsigned long *fildes);
+asmlinkage int sys_ptrace(long request, long pid, long addr, long data);
+
 /*
  * The following two can't be eliminated yet - they rely on
  * specific conditions.
--- diff/include/asm-cris/param.h	2003-07-11 09:39:50.000000000 +0100
+++ source/include/asm-cris/param.h	2004-02-23 13:56:47.000000000 +0000
@@ -14,10 +14,6 @@
 
 #define EXEC_PAGESIZE	8192
 
-#ifndef NGROUPS
-#define NGROUPS		32
-#endif
-
 #ifndef NOGROUP
 #define NOGROUP		(-1)
 #endif
--- diff/include/asm-cris/unistd.h	2003-07-11 09:39:50.000000000 +0100
+++ source/include/asm-cris/unistd.h	2004-02-23 13:56:47.000000000 +0000
@@ -305,6 +305,23 @@ extern inline _syscall3(int,execve,const
 extern inline _syscall3(int,open,const char *,file,int,flag,int,mode)
 extern inline _syscall1(int,close,int,fd)
 
+asmlinkage long sys_mmap2(
+			unsigned long addr, unsigned long len,
+			unsigned long prot, unsigned long flags,
+			unsigned long fd, unsigned long pgoff);
+struct pt_regs;
+asmlinkage int sys_execve(const char *fname, char **argv, char **envp,
+			long r13, long mof, long srp, struct pt_regs *regs);
+asmlinkage int sys_clone(unsigned long newusp, unsigned long flags,
+			int* parent_tid, int* child_tid, long mof, long srp,
+			struct pt_regs *regs);
+asmlinkage int sys_fork(long r10, long r11, long r12, long r13,
+			long mof, long srp, struct pt_regs *regs);
+asmlinkage int sys_vfork(long r10, long r11, long r12, long r13,
+			long mof, long srp, struct pt_regs *regs);
+asmlinkage int sys_pipe(unsigned long __user *fildes);
+asmlinkage int sys_ptrace(long request, long pid, long addr, long data);
+
 /*
  * Since we define it "external", it collides with the built-in
  * definition, which has the "noreturn" attribute and will cause
--- diff/include/asm-generic/tlb.h	2003-08-26 10:00:54.000000000 +0100
+++ source/include/asm-generic/tlb.h	2004-02-23 13:56:47.000000000 +0000
@@ -39,7 +39,6 @@ struct mmu_gather {
 	unsigned int		nr;	/* set to ~0U means fast mode */
 	unsigned int		need_flush;/* Really unmapped some ptes? */
 	unsigned int		fullmm; /* non-zero means full mm flush */
-	unsigned long		freed;
 	struct page *		pages[FREE_PTE_NR];
 };
 
@@ -60,7 +59,6 @@ tlb_gather_mmu(struct mm_struct *mm, uns
 	tlb->nr = num_online_cpus() > 1 ? 0U : ~0U;
 
 	tlb->fullmm = full_mm_flush;
-	tlb->freed = 0;
 
 	return tlb;
 }
@@ -85,19 +83,17 @@ tlb_flush_mmu(struct mmu_gather *tlb, un
 static inline void
 tlb_finish_mmu(struct mmu_gather *tlb, unsigned long start, unsigned long end)
 {
-	int freed = tlb->freed;
-	struct mm_struct *mm = tlb->mm;
-	int rss = mm->rss;
-
-	if (rss < freed)
-		freed = rss;
-	mm->rss = rss - freed;
 	tlb_flush_mmu(tlb, start, end);
 
 	/* keep the page table cache within bounds */
 	check_pgt_cache();
 }
 
+static inline unsigned int
+tlb_is_full_mm(struct mmu_gather *tlb)
+{
+	return tlb->fullmm;
+}
 
 /* tlb_remove_page
  *	Must perform the equivalent to __free_pte(pte_get_and_clear(ptep)), while
@@ -141,4 +137,6 @@ static inline void tlb_remove_page(struc
 		__pmd_free_tlb(tlb, pmdp);			\
 	} while (0)
 
+#define tlb_migrate_prepare(mm) do { } while(0)
+
 #endif /* _ASM_GENERIC__TLB_H */
--- diff/include/asm-h8300/aki3068net/machine-depend.h	2003-08-26 10:00:54.000000000 +0100
+++ source/include/asm-h8300/aki3068net/machine-depend.h	2004-02-23 13:56:47.000000000 +0000
@@ -2,7 +2,6 @@
 
 /* TIMER rate define */
 #ifdef H8300_TIMER_DEFINE
-#include <linux/config.h>
 #define H8300_TIMER_COUNT_DATA 20000*10/8192
 #define H8300_TIMER_FREQ 20000*1000/8192
 #endif
@@ -12,13 +11,8 @@
 
 #define NE2000_ADDR		0x200000
 #define NE2000_IRQ              5
-#define NE2000_IRQ_VECTOR	(12 + NE2000_IRQ)
 #define	NE2000_BYTE		volatile unsigned short
 
-#define IER                     0xfee015
-#define ISR			0xfee016
-#define IRQ_MASK		(1 << NE2000_IRQ)
-
 #define WCRL                    0xfee023
 #define MAR0A                   0xffff20
 #define ETCR0A                  0xffff24
--- diff/include/asm-h8300/h8300_ne.h	2003-08-26 10:00:54.000000000 +0100
+++ source/include/asm-h8300/h8300_ne.h	2004-02-23 13:56:47.000000000 +0000
@@ -13,6 +13,7 @@
 
 #define H8300_NE_DEFINE
 #include <asm/machine-depend.h>
+#define NE2000_IRQ_VECTOR	(12 + NE2000_IRQ)
 #undef  H8300_NE_DEFINE
 
 /****************************************************************************/
--- diff/include/asm-h8300/h8max/machine-depend.h	2003-09-17 12:28:12.000000000 +0100
+++ source/include/asm-h8300/h8max/machine-depend.h	2004-02-23 13:56:47.000000000 +0000
@@ -14,9 +14,6 @@
 #define NE2000_IRQ_VECTOR	(12 + NE2000_IRQ)
 #define	NE2000_BYTE		volatile unsigned short
 
-#define IER                     0xfee015
-#define ISR			0xfee016
-#define IRQ_MASK		(1 << NE2000_IRQ)
 /* sorry quick hack */
 #if defined(outb)
 # undef outb
--- diff/include/asm-h8300/ide.h	2003-09-17 12:28:12.000000000 +0100
+++ source/include/asm-h8300/ide.h	2004-02-23 13:56:47.000000000 +0000
@@ -17,8 +17,8 @@
 /****************************************************************************/
 
 void h8300_ide_print_resource(char *name, hw_regs_t *hw);
-static inline int ide_default_irq(unsigned long base) { return 0; };
-static inline ide_ioreg_t ide_default_io_base(int index) { return 0; };
+static __inline__ int ide_default_irq(unsigned long base) { return 0; };
+static __inline__ unsigned long ide_default_io_base(int index) { return 0; };
 
 static __inline__ void ide_init_hwif_ports(hw_regs_t *hw, unsigned long data_port,
 	 unsigned long ctrl_port, int *irq)
--- diff/include/asm-h8300/io.h	2004-02-18 08:54:12.000000000 +0000
+++ source/include/asm-h8300/io.h	2004-02-23 13:56:47.000000000 +0000
@@ -6,6 +6,15 @@
 #include <linux/config.h>
 #include <asm/virtconvert.h>
 
+#if defined(CONFIG_H83007) || defined(CONFIG_H83068)
+#include <asm/regs306x.h>
+#elif defined(CONFIG_H8S2678)
+#include <asm/regs2678.h>
+#else
+#error UNKNOWN CPU TYPE
+#endif
+
+
 /*
  * These are for ISA/PCI shared memory _only_ and should never be used
  * on any other type of memory, including Zorro memory. They are meant to
@@ -30,6 +39,7 @@
  * 020325   Added some #define's for the COBRA5272 board
  *          (hede)
  */
+
 static inline unsigned short _swapw(volatile unsigned short v)
 {
     return ((v << 8) | (v >> 8));
@@ -41,20 +51,19 @@ static inline unsigned int _swapl(volati
 }
 
 #define readb(addr) \
-    ({ unsigned char __v = (*(volatile unsigned char *) (addr & 0x00ffffff)); __v; })
+    ({ unsigned char __v = (*(volatile unsigned char *) ((addr) & 0x00ffffff)); __v; })
 #define readw(addr) \
-    ({ unsigned short __v = (*(volatile unsigned short *) (addr & 0x00ffffff)); __v; })
+    ({ unsigned short __v = (*(volatile unsigned short *) ((addr) & 0x00ffffff)); __v; })
 #define readl(addr) \
-    ({ unsigned int __v = (*(volatile unsigned int *) (addr & 0x00ffffff)); __v; })
+    ({ unsigned int __v = (*(volatile unsigned int *) ((addr) & 0x00ffffff)); __v; })
 
+#define writeb(b,addr) (void)((*(volatile unsigned char *) ((addr) & 0x00ffffff)) = (b))
+#define writew(b,addr) (void)((*(volatile unsigned short *) ((addr) & 0x00ffffff)) = (b))
+#define writel(b,addr) (void)((*(volatile unsigned int *) ((addr) & 0x00ffffff)) = (b))
 #define readb_relaxed(addr) readb(addr)
 #define readw_relaxed(addr) readw(addr)
 #define readl_relaxed(addr) readl(addr)
 
-#define writeb(b,addr) (void)((*(volatile unsigned char *) (addr & 0x00ffffff)) = (b))
-#define writew(b,addr) (void)((*(volatile unsigned short *) (addr & 0x00ffffff)) = (b))
-#define writel(b,addr) (void)((*(volatile unsigned int *) (addr & 0x00ffffff)) = (b))
-
 #define __raw_readb readb
 #define __raw_readw readw
 #define __raw_readl readl
@@ -62,12 +71,24 @@ static inline unsigned int _swapl(volati
 #define __raw_writew writew
 #define __raw_writel writel
 
+static inline int h8300_buswidth(unsigned int addr)
+{
+	return (*(volatile unsigned char *)ABWCR & (1 << (addr >> 21) & 7)) == 0;
+}
+
 static inline void io_outsb(unsigned int addr, void *buf, int len)
 {
-	volatile unsigned char *ap = (volatile unsigned char *) addr;
+	volatile unsigned char  *ap_b = (volatile unsigned char *) addr;
+	volatile unsigned short *ap_w = (volatile unsigned short *) addr;
 	unsigned char *bp = (unsigned char *) buf;
-	while (len--)
-		*ap = *bp++;
+
+	if(h8300_buswidth(addr) && (addr & 1)) {
+		while (len--)
+			*ap_w = *bp++;
+	} else {
+		while (len--)
+			*ap_b = *bp++;
+	}
 }
 
 static inline void io_outsw(unsigned int addr, void *buf, int len)
@@ -75,7 +96,7 @@ static inline void io_outsw(unsigned int
 	volatile unsigned short *ap = (volatile unsigned short *) addr;
 	unsigned short *bp = (unsigned short *) buf;
 	while (len--)
-		*ap = _swapw(*bp++);
+		*ap = *bp++;
 }
 
 static inline void io_outsl(unsigned int addr, void *buf, int len)
@@ -83,13 +104,18 @@ static inline void io_outsl(unsigned int
 	volatile unsigned int *ap = (volatile unsigned int *) addr;
 	unsigned int *bp = (unsigned int *) buf;
 	while (len--)
-		*ap = _swapl(*bp++);
+		*ap = *bp++;
 }
 
 static inline void io_insb(unsigned int addr, void *buf, int len)
 {
-	volatile unsigned char *ap = (volatile unsigned char *) addr;
+	volatile unsigned char  *ap;
 	unsigned char *bp = (unsigned char *) buf;
+
+	if(h8300_buswidth(addr))
+		ap = (volatile unsigned char *)(addr ^ 1);
+	else
+		ap = (volatile unsigned char *)addr;
 	while (len--)
 		*bp++ = *ap;
 }
@@ -99,7 +125,7 @@ static inline void io_insw(unsigned int 
 	volatile unsigned short *ap = (volatile unsigned short *) addr;
 	unsigned short *bp = (unsigned short *) buf;
 	while (len--)
-		*bp++ = _swapw(*ap);
+		*bp++ = *ap;
 }
 
 static inline void io_insl(unsigned int addr, void *buf, int len)
@@ -107,7 +133,7 @@ static inline void io_insl(unsigned int 
 	volatile unsigned int *ap = (volatile unsigned int *) addr;
 	unsigned int *bp = (unsigned int *) buf;
 	while (len--)
-		*bp++ = _swapl(*ap);
+		*bp++ = *ap;
 }
 
 /*
@@ -119,12 +145,12 @@ static inline void io_insl(unsigned int 
 #define memcpy_fromio(a,b,c)	memcpy((a),(void *)(b),(c))
 #define memcpy_toio(a,b,c)	memcpy((void *)(a),(b),(c))
 
-#define inb(addr)      readb(addr)
-#define inw(addr)    readw(addr)
-#define inl(addr)    readl(addr)
-#define outb(x,addr) ((void) writeb(x,addr))
-#define outw(x,addr) ((void) writew(x,addr))
-#define outl(x,addr) ((void) writel(x,addr))
+#define inb(addr)    ((h8300_buswidth(addr))?readb(addr ^ 1) & 0xff:readb(addr))
+#define inw(addr)    _swapw(readw(addr))
+#define inl(addr)    _swapl(readl(addr))
+#define outb(x,addr) ((void)((h8300_buswidth(addr) && (addr & 1))?writew(x,addr):writeb(x,addr)))
+#define outw(x,addr) ((void) writew(_swapw(x),addr))
+#define outl(x,addr) ((void) writel(_swapl(x),addr))
 
 #define inb_p(addr)    inb(addr)
 #define inw_p(addr)    inw(addr)
@@ -153,19 +179,19 @@ static inline void io_insl(unsigned int 
 extern void *__ioremap(unsigned long physaddr, unsigned long size, int cacheflag);
 extern void __iounmap(void *addr, unsigned long size);
 
-extern inline void *ioremap(unsigned long physaddr, unsigned long size)
+static inline void *ioremap(unsigned long physaddr, unsigned long size)
 {
 	return __ioremap(physaddr, size, IOMAP_NOCACHE_SER);
 }
-extern inline void *ioremap_nocache(unsigned long physaddr, unsigned long size)
+static inline void *ioremap_nocache(unsigned long physaddr, unsigned long size)
 {
 	return __ioremap(physaddr, size, IOMAP_NOCACHE_SER);
 }
-extern inline void *ioremap_writethrough(unsigned long physaddr, unsigned long size)
+static inline void *ioremap_writethrough(unsigned long physaddr, unsigned long size)
 {
 	return __ioremap(physaddr, size, IOMAP_WRITETHROUGH);
 }
-extern inline void *ioremap_fullcache(unsigned long physaddr, unsigned long size)
+static inline void *ioremap_fullcache(unsigned long physaddr, unsigned long size)
 {
 	return __ioremap(physaddr, size, IOMAP_FULL_CACHING);
 }
--- diff/include/asm-h8300/module.h	2003-05-21 11:50:10.000000000 +0100
+++ source/include/asm-h8300/module.h	2004-02-23 13:56:47.000000000 +0000
@@ -4,9 +4,4 @@
  * This file contains the H8/300 architecture specific module code.
  */
 
-#define module_map(x)		vmalloc(x)
-#define module_unmap(x)		vfree(x)
-#define module_arch_init(x)	(0)
-#define arch_init_modules(x)	do { } while (0)
-
 #endif /* _ASM_H8/300_MODULE_H */
--- diff/include/asm-h8300/page.h	2003-05-21 11:50:10.000000000 +0100
+++ source/include/asm-h8300/page.h	2004-02-23 13:56:47.000000000 +0000
@@ -1,12 +1,12 @@
-#ifndef _H8300NOMMU_PAGE_H
-#define _H8300NOMMU_PAGE_H
+#ifndef _H8300_PAGE_H
+#define _H8300_PAGE_H
 
 #include <linux/config.h>
 
 /* PAGE_SHIFT determines the page size */
 
 #define PAGE_SHIFT	(12)
-#define PAGE_SIZE	(4096)
+#define PAGE_SIZE	(1UL << PAGE_SHIFT)
 #define PAGE_MASK	(~(PAGE_SIZE-1))
 
 #ifdef __KERNEL__
@@ -98,4 +98,4 @@ extern unsigned long memory_end;
 
 #endif /* __KERNEL__ */
 
-#endif /* _H8300NOMMU_PAGE_H */
+#endif /* _H8300_PAGE_H */
--- diff/include/asm-h8300/param.h	2003-05-21 11:50:10.000000000 +0100
+++ source/include/asm-h8300/param.h	2004-02-23 13:56:47.000000000 +0000
@@ -14,10 +14,6 @@
 
 #define EXEC_PAGESIZE	4096
 
-#ifndef NGROUPS
-#define NGROUPS		32
-#endif
-
 #ifndef NOGROUP
 #define NOGROUP		(-1)
 #endif
--- diff/include/asm-h8300/processor.h	2003-09-30 15:46:19.000000000 +0100
+++ source/include/asm-h8300/processor.h	2004-02-23 13:56:47.000000000 +0000
@@ -75,6 +75,7 @@ do {							        \
 	set_fs(USER_DS);           /* reads from user space */  \
   	(_regs)->pc = (_pc);				        \
 	(_regs)->ccr &= 0x00;	   /* clear kernel flag */      \
+	wrusp((unsigned long)(_usp) - sizeof(unsigned long)*3);	\
 } while(0)
 #endif
 #if defined(__H8300S__)
--- diff/include/asm-h8300/system.h	2003-08-26 10:00:54.000000000 +0100
+++ source/include/asm-h8300/system.h	2004-02-23 13:56:47.000000000 +0000
@@ -57,14 +57,14 @@ asmlinkage void resume(void);
 #define __cli() asm volatile ("orc  #0x80,ccr")
 
 #define __save_flags(x) \
-       asm volatile ("stc ccr,r0l\n\tmov.l er0,%0":"=r" (x) : : "er0")
+       asm volatile ("stc ccr,%w0":"=r" (x))
 
 #define __restore_flags(x) \
-       asm volatile ("mov.l %0,er0\n\tldc r0l,ccr": :"r" (x) : "er0")
+       asm volatile ("ldc %w0,ccr": :"r" (x))
 
 #define	irqs_disabled()			\
 ({					\
-	unsigned long flags;		\
+	unsigned char flags;		\
 	__save_flags(flags);	        \
 	((flags & 0x80) == 0x80);	\
 })
--- diff/include/asm-h8300/unistd.h	2003-08-20 14:16:33.000000000 +0100
+++ source/include/asm-h8300/unistd.h	2004-02-23 13:56:47.000000000 +0000
@@ -479,6 +479,14 @@ static inline pid_t wait(int * wait_stat
 {
 	return waitpid(-1,wait_stat,0);
 }
+asmlinkage long sys_mmap2(unsigned long addr, unsigned long len,
+			unsigned long prot, unsigned long flags,
+			unsigned long fd, unsigned long pgoff);
+asmlinkage int sys_execve(char *name, char **argv, char **envp,
+			int dummy, ...);
+asmlinkage int sys_pipe(unsigned long *fildes);
+asmlinkage int sys_ptrace(long request, long pid, long addr, long data);
+asmlinkage long sys_ioperm(unsigned long from, unsigned long num, int on);
 
 #endif
 
--- diff/include/asm-i386/bugs.h	2003-10-09 09:47:17.000000000 +0100
+++ source/include/asm-i386/bugs.h	2004-02-23 13:56:47.000000000 +0000
@@ -1,11 +1,11 @@
 /*
  *  include/asm-i386/bugs.h
  *
- *  Copyright (C) 1994  Linus Torvalds
+ *  Copyright (C) 1994	Linus Torvalds
  *
  *  Cyrix stuff, June 1998 by:
  *	- Rafael R. Reilova (moved everything from head.S),
- *        <rreilova@ececs.uc.edu>
+ *	  <rreilova@ececs.uc.edu>
  *	- Channing Corn (tests & fixes),
  *	- Andrew D. Balsa (code cleanup).
  *
@@ -25,7 +25,20 @@
 #include <asm/processor.h>
 #include <asm/i387.h>
 #include <asm/msr.h>
-
+#ifdef CONFIG_KGDB
+/*
+ * Provied the command line "gdb" initial break
+ */
+int __init kgdb_initial_break(char * str)
+{
+	if (*str == '\0'){
+		breakpoint();
+		return 1;
+	}
+	return 0;
+}
+__setup("gdb",kgdb_initial_break);
+#endif
 static int __init no_halt(char *s)
 {
 	boot_cpu_data.hlt_works_ok = 0;
@@ -140,7 +153,7 @@ static void __init check_popad(void)
 	  : "ecx", "edi" );
 	/* If this fails, it means that any user program may lock the CPU hard. Too bad. */
 	if (res != 12345678) printk( "Buggy.\n" );
-		        else printk( "OK.\n" );
+			else printk( "OK.\n" );
 #endif
 }
 
--- diff/include/asm-i386/checksum.h	2003-11-25 15:24:59.000000000 +0000
+++ source/include/asm-i386/checksum.h	2004-02-23 13:56:47.000000000 +0000
@@ -25,7 +25,7 @@ asmlinkage unsigned int csum_partial(con
  * better 64-bit) boundary
  */
 
-asmlinkage unsigned int csum_partial_copy_generic( const char *src, char *dst, int len, int sum,
+asmlinkage unsigned int direct_csum_partial_copy_generic( const char *src, char *dst, int len, int sum,
 						   int *src_err_ptr, int *dst_err_ptr);
 
 /*
@@ -39,14 +39,19 @@ static __inline__
 unsigned int csum_partial_copy_nocheck ( const char *src, char *dst,
 					int len, int sum)
 {
-	return csum_partial_copy_generic ( src, dst, len, sum, NULL, NULL);
+	/*
+	 * The direct function is OK for kernel-space => kernel-space copies:
+	 */
+	return direct_csum_partial_copy_generic ( src, dst, len, sum, NULL, NULL);
 }
 
 static __inline__
 unsigned int csum_partial_copy_from_user ( const char *src, char *dst,
 						int len, int sum, int *err_ptr)
 {
-	return csum_partial_copy_generic ( src, dst, len, sum, err_ptr, NULL);
+	if (copy_from_user(dst, src, len))
+		*err_ptr = -EFAULT;
+	return csum_partial(dst, len, sum);
 }
 
 /*
@@ -172,11 +177,26 @@ static __inline__ unsigned short int csu
  *	Copy and checksum to user
  */
 #define HAVE_CSUM_COPY_USER
-static __inline__ unsigned int csum_and_copy_to_user(const char *src, char *dst,
+static __inline__ unsigned int direct_csum_and_copy_to_user(const char *src, char *dst,
 				    int len, int sum, int *err_ptr)
 {
 	if (access_ok(VERIFY_WRITE, dst, len))
-		return csum_partial_copy_generic(src, dst, len, sum, NULL, err_ptr);
+		return direct_csum_partial_copy_generic(src, dst, len, sum, NULL, err_ptr);
+
+	if (len)
+		*err_ptr = -EFAULT;
+
+	return -1; /* invalid checksum */
+}
+
+static __inline__ unsigned int csum_and_copy_to_user(const char *src, char *dst,
+				    int len, int sum, int *err_ptr)
+{
+	if (access_ok(VERIFY_WRITE, dst, len)) {
+		if (copy_to_user(dst, src, len))
+			*err_ptr = -EFAULT;
+		return csum_partial(src, len, sum);
+	}
 
 	if (len)
 		*err_ptr = -EFAULT;
--- diff/include/asm-i386/cpufeature.h	2003-09-30 15:46:19.000000000 +0100
+++ source/include/asm-i386/cpufeature.h	2004-02-23 13:56:47.000000000 +0000
@@ -76,6 +76,9 @@
 
 /* VIA/Cyrix/Centaur-defined CPU features, CPUID level 0xC0000001, word 5 */
 #define X86_FEATURE_XSTORE	(5*32+ 2) /* on-CPU RNG present (xstore insn) */
+#define X86_FEATURE_XSTORE_EN	(5*32+ 3) /* on-CPU RNG enabled */
+#define X86_FEATURE_XCRYPT	(5*32+ 6) /* on-CPU crypto (xcrypt insn) */
+#define X86_FEATURE_XCRYPT_EN	(5*32+ 7) /* on-CPU crypto enabled */
 
 
 #define cpu_has(c, bit)		test_bit(bit, (c)->x86_capability)
@@ -101,6 +104,7 @@
 #define cpu_has_cyrix_arr	boot_cpu_has(X86_FEATURE_CYRIX_ARR)
 #define cpu_has_centaur_mcr	boot_cpu_has(X86_FEATURE_CENTAUR_MCR)
 #define cpu_has_xstore		boot_cpu_has(X86_FEATURE_XSTORE)
+#define cpu_has_xcrypt		boot_cpu_has(X86_FEATURE_XCRYPT)
 
 #endif /* __ASM_I386_CPUFEATURE_H */
 
--- diff/include/asm-i386/desc.h	2003-10-09 09:47:17.000000000 +0100
+++ source/include/asm-i386/desc.h	2004-02-23 13:56:47.000000000 +0000
@@ -21,6 +21,13 @@ struct Xgt_desc_struct {
 
 extern struct Xgt_desc_struct idt_descr, cpu_gdt_descr[NR_CPUS];
 
+extern void trap_init_virtual_IDT(void);
+extern void trap_init_virtual_GDT(void);
+
+asmlinkage int system_call(void);
+asmlinkage void lcall7(void);
+asmlinkage void lcall27(void);
+
 #define load_TR_desc() __asm__ __volatile__("ltr %%ax"::"a" (GDT_ENTRY_TSS*8))
 #define load_LDT_desc() __asm__ __volatile__("lldt %%ax"::"a" (GDT_ENTRY_LDT*8))
 
@@ -30,6 +37,7 @@ extern struct Xgt_desc_struct idt_descr,
  */
 extern struct desc_struct default_ldt[];
 extern void set_intr_gate(unsigned int irq, void * addr);
+extern void set_trap_gate(unsigned int n, void *addr);
 
 #define _set_tssldt_desc(n,addr,limit,type) \
 __asm__ __volatile__ ("movw %w3,0(%2)\n\t" \
@@ -90,31 +98,8 @@ static inline void load_TLS(struct threa
 #undef C
 }
 
-static inline void clear_LDT(void)
-{
-	int cpu = get_cpu();
-
-	set_ldt_desc(cpu, &default_ldt[0], 5);
-	load_LDT_desc();
-	put_cpu();
-}
-
-/*
- * load one particular LDT into the current CPU
- */
-static inline void load_LDT_nolock(mm_context_t *pc, int cpu)
-{
-	void *segments = pc->ldt;
-	int count = pc->size;
-
-	if (likely(!count)) {
-		segments = &default_ldt[0];
-		count = 5;
-	}
-		
-	set_ldt_desc(cpu, segments, count);
-	load_LDT_desc();
-}
+extern struct page *default_ldt_page;
+extern void load_LDT_nolock(mm_context_t *pc, int cpu);
 
 static inline void load_LDT(mm_context_t *pc)
 {
@@ -123,6 +108,6 @@ static inline void load_LDT(mm_context_t
 	put_cpu();
 }
 
-#endif /* !__ASSEMBLY__ */
 
+#endif /* !__ASSEMBLY__ */
 #endif
--- diff/include/asm-i386/fixmap.h	2003-10-09 09:47:17.000000000 +0100
+++ source/include/asm-i386/fixmap.h	2004-02-23 13:56:47.000000000 +0000
@@ -18,17 +18,15 @@
 #include <asm/acpi.h>
 #include <asm/apicdef.h>
 #include <asm/page.h>
-#ifdef CONFIG_HIGHMEM
 #include <linux/threads.h>
 #include <asm/kmap_types.h>
-#endif
 
 /*
  * Here we define all the compile-time 'special' virtual
  * addresses. The point is to have a constant address at
  * compile time, but to set the physical address only
- * in the boot process. We allocate these special addresses
- * from the end of virtual memory (0xfffff000) backwards.
+ * in the boot process. We allocate these special  addresses
+ * from the end of virtual memory (0xffffe000) backwards.
  * Also this lets us do fail-safe vmalloc(), we
  * can guarantee that these special addresses and
  * vmalloc()-ed addresses never overlap.
@@ -41,11 +39,20 @@
  * TLB entries of such buffers will not be flushed across
  * task switches.
  */
+
+/*
+ * on UP currently we will have no trace of the fixmap mechanizm,
+ * no page table allocations, etc. This might change in the
+ * future, say framebuffers for the console driver(s) could be
+ * fix-mapped?
+ */
 enum fixed_addresses {
 	FIX_HOLE,
 	FIX_VSYSCALL,
 #ifdef CONFIG_X86_LOCAL_APIC
 	FIX_APIC_BASE,	/* local (CPU) APIC) -- required for SMP or not */
+#else
+	FIX_VSTACK_HOLE_1,
 #endif
 #ifdef CONFIG_X86_IO_APIC
 	FIX_IO_APIC_BASE_0,
@@ -57,20 +64,28 @@ enum fixed_addresses {
 	FIX_LI_PCIA,	/* Lithium PCI Bridge A */
 	FIX_LI_PCIB,	/* Lithium PCI Bridge B */
 #endif
-#ifdef CONFIG_X86_F00F_BUG
-	FIX_F00F_IDT,	/* Virtual mapping for IDT */
-#endif
+	FIX_IDT,
+	FIX_GDT_1,
+	FIX_GDT_0,
+	FIX_TSS_3,
+	FIX_TSS_2,
+	FIX_TSS_1,
+	FIX_TSS_0,
+	FIX_ENTRY_TRAMPOLINE_1,
+	FIX_ENTRY_TRAMPOLINE_0,
 #ifdef CONFIG_X86_CYCLONE_TIMER
 	FIX_CYCLONE_TIMER, /*cyclone timer register*/
+	FIX_VSTACK_HOLE_2,
 #endif 
-#ifdef CONFIG_HIGHMEM
 	FIX_KMAP_BEGIN,	/* reserved pte's for temporary kernel mappings */
 	FIX_KMAP_END = FIX_KMAP_BEGIN+(KM_TYPE_NR*NR_CPUS)-1,
-#endif
 #ifdef CONFIG_ACPI_BOOT
 	FIX_ACPI_BEGIN,
 	FIX_ACPI_END = FIX_ACPI_BEGIN + FIX_ACPI_PAGES - 1,
 #endif
+#ifdef CONFIG_PCI_MMCONFIG
+	FIX_PCIE_MCFG,
+#endif
 	__end_of_permanent_fixed_addresses,
 	/* temporary boot-time mappings, used before ioremap() is functional */
 #define NR_FIX_BTMAPS	16
@@ -95,12 +110,15 @@ extern void __set_fixmap (enum fixed_add
 		__set_fixmap(idx, 0, __pgprot(0))
 
 /*
- * used by vmalloc.c.
+ * used by vmalloc.c and various other places.
  *
  * Leave one empty page between vmalloc'ed areas and
  * the start of the fixmap.
+ *
+ * IMPORTANT: dont change FIXADDR_TOP without adjusting KM_VSTACK0
+ * and KM_VSTACK1 so that the virtual stack is 8K aligned.
  */
-#define FIXADDR_TOP	(0xfffff000UL)
+#define FIXADDR_TOP	(0xffffe000UL)
 #define __FIXADDR_SIZE	(__end_of_permanent_fixed_addresses << PAGE_SHIFT)
 #define FIXADDR_START	(FIXADDR_TOP - __FIXADDR_SIZE)
 
--- diff/include/asm-i386/highmem.h	2003-10-09 09:47:34.000000000 +0100
+++ source/include/asm-i386/highmem.h	2004-02-23 13:56:47.000000000 +0000
@@ -25,26 +25,19 @@
 #include <linux/threads.h>
 #include <asm/kmap_types.h>
 #include <asm/tlbflush.h>
+#include <asm/atomic_kmap.h>
 
 /* declarations for highmem.c */
 extern unsigned long highstart_pfn, highend_pfn;
 
-extern pte_t *kmap_pte;
-extern pgprot_t kmap_prot;
 extern pte_t *pkmap_page_table;
-
-extern void kmap_init(void);
+extern void kmap_init(void) __init;
 
 /*
  * Right now we initialize only a single pte table. It can be extended
  * easily, subsequent pte tables have to be allocated in one physical
  * chunk of RAM.
  */
-#if NR_CPUS <= 32
-#define PKMAP_BASE (0xff800000UL)
-#else
-#define PKMAP_BASE (0xff600000UL)
-#endif
 #ifdef CONFIG_X86_PAE
 #define LAST_PKMAP 512
 #else
--- diff/include/asm-i386/kmap_types.h	2003-10-09 09:47:17.000000000 +0100
+++ source/include/asm-i386/kmap_types.h	2004-02-23 13:56:47.000000000 +0000
@@ -3,30 +3,36 @@
 
 #include <linux/config.h>
 
-#ifdef CONFIG_DEBUG_HIGHMEM
-# define D(n) __KM_FENCE_##n ,
-#else
-# define D(n)
-#endif
-
 enum km_type {
-D(0)	KM_BOUNCE_READ,
-D(1)	KM_SKB_SUNRPC_DATA,
-D(2)	KM_SKB_DATA_SOFTIRQ,
-D(3)	KM_USER0,
-D(4)	KM_USER1,
-D(5)	KM_BIO_SRC_IRQ,
-D(6)	KM_BIO_DST_IRQ,
-D(7)	KM_PTE0,
-D(8)	KM_PTE1,
-D(9)	KM_PTE2,
-D(10)	KM_IRQ0,
-D(11)	KM_IRQ1,
-D(12)	KM_SOFTIRQ0,
-D(13)	KM_SOFTIRQ1,
-D(14)	KM_TYPE_NR
-};
-
-#undef D
+	/*
+	 * IMPORTANT: don't move these 3 entries, and only add entries in
+	 * pairs: the 4G/4G virtual stack must be 8K aligned on each cpu.
+	 */
+	KM_BOUNCE_READ,
+	KM_VSTACK1,
+	KM_VSTACK0,
 
+	KM_LDT_PAGE15,
+	KM_LDT_PAGE0 = KM_LDT_PAGE15 + 16-1,
+	KM_USER_COPY,
+	KM_VSTACK_HOLE,
+	KM_SKB_SUNRPC_DATA,
+	KM_SKB_DATA_SOFTIRQ,
+	KM_USER0,
+	KM_USER1,
+	KM_BIO_SRC_IRQ,
+	KM_BIO_DST_IRQ,
+	KM_PTE0,
+	KM_PTE1,
+	KM_PTE2,
+	KM_IRQ0,
+	KM_IRQ1,
+	KM_SOFTIRQ0,
+	KM_SOFTIRQ1,
+	/*
+	 * Add new entries in pairs:
+	 * the 4G/4G virtual stack must be 8K aligned on each cpu.
+	 */
+	KM_TYPE_NR
+};
 #endif
--- diff/include/asm-i386/mmu.h	2003-10-09 09:47:17.000000000 +0100
+++ source/include/asm-i386/mmu.h	2004-02-23 13:56:47.000000000 +0000
@@ -8,10 +8,13 @@
  *
  * cpu_vm_mask is used to optimize ldt flushing.
  */
+
+#define MAX_LDT_PAGES 16
+
 typedef struct { 
 	int size;
 	struct semaphore sem;
-	void *ldt;
+	struct page *ldt_pages[MAX_LDT_PAGES];
 } mm_context_t;
 
 #endif
--- diff/include/asm-i386/mmu_context.h	2003-10-09 09:47:17.000000000 +0100
+++ source/include/asm-i386/mmu_context.h	2004-02-23 13:56:47.000000000 +0000
@@ -29,6 +29,10 @@ static inline void switch_mm(struct mm_s
 {
 	int cpu = smp_processor_id();
 
+#ifdef CONFIG_X86_SWITCH_PAGETABLES
+	if (tsk->mm)
+		tsk->thread_info->user_pgd = (void *)__pa(tsk->mm->pgd);
+#endif
 	if (likely(prev != next)) {
 		/* stop flush ipis for the previous mm */
 		cpu_clear(cpu, prev->cpu_vm_mask);
@@ -39,12 +43,14 @@ static inline void switch_mm(struct mm_s
 		cpu_set(cpu, next->cpu_vm_mask);
 
 		/* Re-load page tables */
+#if !defined(CONFIG_X86_SWITCH_PAGETABLES)
 		load_cr3(next->pgd);
+#endif
 
 		/*
 		 * load the LDT, if the LDT is different:
 		 */
-		if (unlikely(prev->context.ldt != next->context.ldt))
+		if (unlikely(prev->context.size + next->context.size))
 			load_LDT_nolock(&next->context, cpu);
 	}
 #ifdef CONFIG_SMP
@@ -56,7 +62,9 @@ static inline void switch_mm(struct mm_s
 			/* We were in lazy tlb mode and leave_mm disabled 
 			 * tlb flush IPI delivery. We must reload %cr3.
 			 */
+#if !defined(CONFIG_X86_SWITCH_PAGETABLES)
 			load_cr3(next->pgd);
+#endif
 			load_LDT_nolock(&next->context, cpu);
 		}
 	}
@@ -67,6 +75,6 @@ static inline void switch_mm(struct mm_s
 	asm("movl %0,%%fs ; movl %0,%%gs": :"r" (0))
 
 #define activate_mm(prev, next) \
-	switch_mm((prev),(next),NULL)
+	switch_mm((prev),(next),current)
 
 #endif
--- diff/include/asm-i386/mmzone.h	2004-02-18 08:54:12.000000000 +0000
+++ source/include/asm-i386/mmzone.h	2004-02-23 13:56:47.000000000 +0000
@@ -10,7 +10,49 @@
 
 #ifdef CONFIG_DISCONTIGMEM
 
+#ifdef CONFIG_NUMA
+	#ifdef CONFIG_X86_NUMAQ
+		#include <asm/numaq.h>
+	#else	/* summit or generic arch */
+		#include <asm/srat.h>
+	#endif
+#else /* !CONFIG_NUMA */
+	#define get_memcfg_numa get_memcfg_numa_flat
+	#define get_zholes_size(n) (0)
+#endif /* CONFIG_NUMA */
+
 extern struct pglist_data *node_data[];
+#define NODE_DATA(nid)		(node_data[nid])
+
+/*
+ * generic node memory support, the following assumptions apply:
+ *
+ * 1) memory comes in 256Mb contigious chunks which are either present or not
+ * 2) we will not have more than 64Gb in total
+ *
+ * for now assume that 64Gb is max amount of RAM for whole system
+ *    64Gb / 4096bytes/page = 16777216 pages
+ */
+#define MAX_NR_PAGES 16777216
+#define MAX_ELEMENTS 256
+#define PAGES_PER_ELEMENT (MAX_NR_PAGES/MAX_ELEMENTS)
+
+extern u8 physnode_map[];
+
+static inline int pfn_to_nid(unsigned long pfn)
+{
+#ifdef CONFIG_NUMA
+	return(physnode_map[(pfn) / PAGES_PER_ELEMENT]);
+#else
+	return 0;
+#endif
+}
+
+static inline struct pglist_data *pfn_to_pgdat(unsigned long pfn)
+{
+	return(NODE_DATA(pfn_to_nid(pfn)));
+}
+
 
 /*
  * Following are macros that are specific to this numa platform.
@@ -43,11 +85,6 @@ extern struct pglist_data *node_data[];
  */
 #define kvaddr_to_nid(kaddr)	pfn_to_nid(__pa(kaddr) >> PAGE_SHIFT)
 
-/*
- * Return a pointer to the node data for node n.
- */
-#define NODE_DATA(nid)		(node_data[nid])
-
 #define node_mem_map(nid)	(NODE_DATA(nid)->node_mem_map)
 #define node_start_pfn(nid)	(NODE_DATA(nid)->node_start_pfn)
 #define node_end_pfn(nid)						\
@@ -80,48 +117,19 @@ extern struct pglist_data *node_data[];
 		+ __zone->zone_start_pfn;				\
 })
 #define pmd_page(pmd)		(pfn_to_page(pmd_val(pmd) >> PAGE_SHIFT))
-/*
- * pfn_valid should be made as fast as possible, and the current definition 
- * is valid for machines that are NUMA, but still contiguous, which is what
- * is currently supported. A more generalised, but slower definition would
- * be something like this - mbligh:
- * ( pfn_to_pgdat(pfn) && ((pfn) < node_end_pfn(pfn_to_nid(pfn))) ) 
- */ 
-#define pfn_valid(pfn)          ((pfn) < num_physpages)
-
-/*
- * generic node memory support, the following assumptions apply:
- *
- * 1) memory comes in 256Mb contigious chunks which are either present or not
- * 2) we will not have more than 64Gb in total
- *
- * for now assume that 64Gb is max amount of RAM for whole system
- *    64Gb / 4096bytes/page = 16777216 pages
- */
-#define MAX_NR_PAGES 16777216
-#define MAX_ELEMENTS 256
-#define PAGES_PER_ELEMENT (MAX_NR_PAGES/MAX_ELEMENTS)
 
-extern u8 physnode_map[];
-
-static inline int pfn_to_nid(unsigned long pfn)
-{
-	return(physnode_map[(pfn) / PAGES_PER_ELEMENT]);
-}
-static inline struct pglist_data *pfn_to_pgdat(unsigned long pfn)
+#ifdef CONFIG_X86_NUMAQ            /* we have contiguous memory on NUMA-Q */
+#define pfn_valid(pfn)          ((pfn) < num_physpages)
+#else
+static inline int pfn_valid(int pfn)
 {
-	return(NODE_DATA(pfn_to_nid(pfn)));
-}
+	int nid = pfn_to_nid(pfn);
 
-#ifdef CONFIG_X86_NUMAQ
-#include <asm/numaq.h>
-#elif CONFIG_ACPI_SRAT
-#include <asm/srat.h>
-#elif CONFIG_X86_PC
-#define get_zholes_size(n) (0)
-#else
-#define pfn_to_nid(pfn)		(0)
-#endif /* CONFIG_X86_NUMAQ */
+	if (nid >= 0)
+		return (pfn < node_end_pfn(nid));
+	return 0;
+}
+#endif
 
 extern int get_memcfg_numa_flat(void );
 /*
--- diff/include/asm-i386/module.h	2003-02-26 16:01:02.000000000 +0000
+++ source/include/asm-i386/module.h	2004-02-23 13:56:47.000000000 +0000
@@ -26,6 +26,8 @@ struct mod_arch_specific
 #define MODULE_PROC_FAMILY "PENTIUMII "
 #elif defined CONFIG_MPENTIUMIII
 #define MODULE_PROC_FAMILY "PENTIUMIII "
+#elif defined CONFIG_MPENTIUMM
+#define MODULE_PROC_FAMILY "PENTIUMM "
 #elif defined CONFIG_MPENTIUM4
 #define MODULE_PROC_FAMILY "PENTIUM4 "
 #elif defined CONFIG_MK6
@@ -46,12 +48,18 @@ struct mod_arch_specific
 #define MODULE_PROC_FAMILY "WINCHIP3D "
 #elif defined CONFIG_MCYRIXIII
 #define MODULE_PROC_FAMILY "CYRIXIII "
-#elif CONFIG_MVIAC3_2
+#elif defined CONFIG_MVIAC3_2
 #define MODULE_PROC_FAMILY "VIAC3-2 "
 #else
 #error unknown processor family
 #endif
 
-#define MODULE_ARCH_VERMAGIC MODULE_PROC_FAMILY
+#ifdef CONFIG_REGPARM
+#define MODULE_REGPARM "REGPARM "
+#else
+#define MODULE_REGPARM ""
+#endif
+
+#define MODULE_ARCH_VERMAGIC MODULE_PROC_FAMILY MODULE_REGPARM
 
 #endif /* _ASM_I386_MODULE_H */
--- diff/include/asm-i386/page.h	2003-10-09 09:47:17.000000000 +0100
+++ source/include/asm-i386/page.h	2004-02-23 13:56:47.000000000 +0000
@@ -1,6 +1,8 @@
 #ifndef _I386_PAGE_H
 #define _I386_PAGE_H
 
+#include <linux/config.h>
+
 /* PAGE_SHIFT determines the page size */
 #define PAGE_SHIFT	12
 #define PAGE_SIZE	(1UL << PAGE_SHIFT)
@@ -9,11 +11,10 @@
 #define LARGE_PAGE_MASK (~(LARGE_PAGE_SIZE-1))
 #define LARGE_PAGE_SIZE (1UL << PMD_SHIFT)
 
-#ifdef __KERNEL__
-#ifndef __ASSEMBLY__
-
 #include <linux/config.h>
 
+#ifdef __KERNEL__
+#ifndef __ASSEMBLY__
 #ifdef CONFIG_X86_USE_3DNOW
 
 #include <asm/mmx.h>
@@ -88,8 +89,19 @@ typedef struct { unsigned long pgprot; }
  *
  * If you want more physical memory than this then see the CONFIG_HIGHMEM4G
  * and CONFIG_HIGHMEM64G options in the kernel configuration.
+ *
+ * Note: on PAE the kernel must never go below 32 MB, we use the
+ * first 8 entries of the 2-level boot pgd for PAE magic.
  */
 
+#ifdef CONFIG_X86_4G_VM_LAYOUT
+#define __PAGE_OFFSET		(0x02000000)
+#define TASK_SIZE		(0xff000000)
+#else
+#define __PAGE_OFFSET		(0xc0000000)
+#define TASK_SIZE		(0xc0000000)
+#endif
+
 /*
  * This much address space is reserved for vmalloc() and iomap()
  * as well as fixmap mappings.
@@ -114,16 +126,10 @@ static __inline__ int get_order(unsigned
 
 #endif /* __ASSEMBLY__ */
 
-#ifdef __ASSEMBLY__
-#define __PAGE_OFFSET		(0xC0000000)
-#else
-#define __PAGE_OFFSET		(0xC0000000UL)
-#endif
-
-
 #define PAGE_OFFSET		((unsigned long)__PAGE_OFFSET)
 #define VMALLOC_RESERVE		((unsigned long)__VMALLOC_RESERVE)
-#define MAXMEM			(-__PAGE_OFFSET-__VMALLOC_RESERVE)
+#define __MAXMEM		(-__PAGE_OFFSET-__VMALLOC_RESERVE)
+#define MAXMEM			((unsigned long)(-PAGE_OFFSET-VMALLOC_RESERVE))
 #define __pa(x)			((unsigned long)(x)-PAGE_OFFSET)
 #define __va(x)			((void *)((unsigned long)(x)+PAGE_OFFSET))
 #define pfn_to_kaddr(pfn)      __va((pfn) << PAGE_SHIFT)
--- diff/include/asm-i386/param.h	2002-10-16 04:27:19.000000000 +0100
+++ source/include/asm-i386/param.h	2004-02-23 13:56:47.000000000 +0000
@@ -13,10 +13,6 @@
 
 #define EXEC_PAGESIZE	4096
 
-#ifndef NGROUPS
-#define NGROUPS		32
-#endif
-
 #ifndef NOGROUP
 #define NOGROUP		(-1)
 #endif
--- diff/include/asm-i386/pgtable.h	2004-02-09 10:36:12.000000000 +0000
+++ source/include/asm-i386/pgtable.h	2004-02-23 13:56:47.000000000 +0000
@@ -32,16 +32,17 @@
 #define ZERO_PAGE(vaddr) (virt_to_page(empty_zero_page))
 extern unsigned long empty_zero_page[1024];
 extern pgd_t swapper_pg_dir[1024];
-extern kmem_cache_t *pgd_cache;
-extern kmem_cache_t *pmd_cache;
+extern kmem_cache_t *pgd_cache, *pmd_cache, *kpmd_cache;
 extern spinlock_t pgd_lock;
 extern struct list_head pgd_list;
 
 void pmd_ctor(void *, kmem_cache_t *, unsigned long);
+void kpmd_ctor(void *, kmem_cache_t *, unsigned long);
 void pgd_ctor(void *, kmem_cache_t *, unsigned long);
 void pgd_dtor(void *, kmem_cache_t *, unsigned long);
 void pgtable_cache_init(void);
 void paging_init(void);
+void setup_identity_mappings(pgd_t *pgd_base, unsigned long start, unsigned long end);
 
 #endif /* !__ASSEMBLY__ */
 
@@ -51,6 +52,11 @@ void paging_init(void);
  * newer 3-level PAE-mode page tables.
  */
 #ifndef __ASSEMBLY__
+
+extern void set_system_gate(unsigned int n, void *addr);
+extern void init_entry_mappings(void);
+extern void entry_trampoline_setup(void);
+
 #ifdef CONFIG_X86_PAE
 # include <asm/pgtable-3level.h>
 #else
@@ -63,7 +69,12 @@ void paging_init(void);
 #define PGDIR_SIZE	(1UL << PGDIR_SHIFT)
 #define PGDIR_MASK	(~(PGDIR_SIZE-1))
 
-#define USER_PTRS_PER_PGD	(TASK_SIZE/PGDIR_SIZE)
+#if defined(CONFIG_X86_PAE) && defined(CONFIG_X86_4G_VM_LAYOUT)
+# define USER_PTRS_PER_PGD	4
+#else
+# define USER_PTRS_PER_PGD	((TASK_SIZE/PGDIR_SIZE) + ((TASK_SIZE % PGDIR_SIZE) + PGDIR_SIZE-1)/PGDIR_SIZE)
+#endif
+
 #define FIRST_USER_PGD_NR	0
 
 #define USER_PGD_PTRS (PAGE_OFFSET >> PGDIR_SHIFT)
@@ -233,6 +244,7 @@ static inline void ptep_mkdirty(pte_t *p
 
 #define mk_pte(page, pgprot)	pfn_pte(page_to_pfn(page), (pgprot))
 #define mk_pte_huge(entry) ((entry).pte_low |= _PAGE_PRESENT | _PAGE_PSE)
+#define mk_pte_phys(physpage, pgprot) pfn_pte((physpage) >> PAGE_SHIFT, pgprot)
 
 static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
 {
--- diff/include/asm-i386/processor.h	2004-01-19 10:22:59.000000000 +0000
+++ source/include/asm-i386/processor.h	2004-02-23 13:56:47.000000000 +0000
@@ -291,11 +291,6 @@ extern unsigned int machine_submodel_id;
 extern unsigned int BIOS_revision;
 extern unsigned int mca_pentium_flag;
 
-/*
- * User space process size: 3GB (default).
- */
-#define TASK_SIZE	(PAGE_OFFSET)
-
 /* This decides where the kernel will search for a free chunk of vm
  * space during mmap's.
  */
@@ -406,6 +401,7 @@ struct tss_struct {
 struct thread_struct {
 /* cached TLS descriptors. */
 	struct desc_struct tls_array[GDT_ENTRY_TLS_ENTRIES];
+	void *stack_page0, *stack_page1;
 	unsigned long	esp0;
 	unsigned long	sysenter_cs;
 	unsigned long	eip;
@@ -449,7 +445,8 @@ struct thread_struct {
 	.io_bitmap	= { [ 0 ... IO_BITMAP_LONGS] = ~0 },		\
 }
 
-static inline void load_esp0(struct tss_struct *tss, struct thread_struct *thread)
+static inline void
+load_esp0(struct tss_struct *tss, struct thread_struct *thread)
 {
 	tss->esp0 = thread->esp0;
 	/* This can only happen when SEP is enabled, no need to test "SEP"arately */
@@ -485,12 +482,45 @@ extern void prepare_to_copy(struct task_
  */
 extern int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags);
 
+#ifdef CONFIG_X86_HIGH_ENTRY
+#define virtual_esp0(tsk) \
+	((unsigned long)(tsk)->thread_info->virtual_stack + ((tsk)->thread.esp0 - (unsigned long)(tsk)->thread_info->real_stack))
+#else
+# define virtual_esp0(tsk) ((tsk)->thread.esp0)
+#endif
+
+#define load_virtual_esp0(tss, task)					\
+	do {								\
+		tss->esp0 = virtual_esp0(task);				\
+		if (likely(cpu_has_sep) && unlikely(tss->ss1 != task->thread.sysenter_cs)) {	\
+			tss->ss1 = task->thread.sysenter_cs;		\
+			wrmsr(MSR_IA32_SYSENTER_CS,			\
+				task->thread.sysenter_cs, 0);		\
+		}							\
+	} while (0)
+
 extern unsigned long thread_saved_pc(struct task_struct *tsk);
 void show_trace(struct task_struct *task, unsigned long *stack);
 
 unsigned long get_wchan(struct task_struct *p);
-#define KSTK_EIP(tsk)	(((unsigned long *)(4096+(unsigned long)(tsk)->thread_info))[1019])
-#define KSTK_ESP(tsk)	(((unsigned long *)(4096+(unsigned long)(tsk)->thread_info))[1022])
+
+#define THREAD_SIZE_LONGS      (THREAD_SIZE/sizeof(unsigned long))
+#define KSTK_TOP(info)                                                 \
+({                                                                     \
+       unsigned long *__ptr = (unsigned long *)(info);                 \
+       (unsigned long)(&__ptr[THREAD_SIZE_LONGS]);                     \
+})
+
+#define task_pt_regs(task)                                             \
+({                                                                     \
+       struct pt_regs *__regs__;                                       \
+       __regs__ = (struct pt_regs *)KSTK_TOP((task)->thread_info);     \
+       __regs__ - 1;                                                   \
+})
+
+#define KSTK_EIP(task) (task_pt_regs(task)->eip)
+#define KSTK_ESP(task) (task_pt_regs(task)->esp)
+
 
 struct microcode_header {
 	unsigned int hdrver;
@@ -630,4 +660,9 @@ extern inline void prefetchw(const void 
 
 extern void select_idle_routine(const struct cpuinfo_x86 *c);
 
+#ifdef CONFIG_SCHED_SMT
+#define ARCH_HAS_SCHED_DOMAIN
+#define ARCH_HAS_SCHED_WAKE_BALANCE
+#endif
+
 #endif /* __ASM_I386_PROCESSOR_H */
--- diff/include/asm-i386/rwlock.h	2003-10-09 09:47:17.000000000 +0100
+++ source/include/asm-i386/rwlock.h	2004-02-23 13:56:47.000000000 +0000
@@ -20,28 +20,52 @@
 #define RW_LOCK_BIAS		 0x01000000
 #define RW_LOCK_BIAS_STR	"0x01000000"
 
-#define __build_read_lock_ptr(rw, helper)   \
-	asm volatile(LOCK "subl $1,(%0)\n\t" \
-		     "js 2f\n" \
-		     "1:\n" \
-		     LOCK_SECTION_START("") \
-		     "2:\tcall " helper "\n\t" \
-		     "jmp 1b\n" \
-		     LOCK_SECTION_END \
-		     ::"a" (rw) : "memory")
-
-#define __build_read_lock_const(rw, helper)   \
-	asm volatile(LOCK "subl $1,%0\n\t" \
-		     "js 2f\n" \
-		     "1:\n" \
-		     LOCK_SECTION_START("") \
-		     "2:\tpushl %%eax\n\t" \
-		     "leal %0,%%eax\n\t" \
-		     "call " helper "\n\t" \
-		     "popl %%eax\n\t" \
-		     "jmp 1b\n" \
-		     LOCK_SECTION_END \
-		     :"=m" (*(volatile int *)rw) : : "memory")
+#ifdef CONFIG_SPINLINE
+
+	#define __build_read_lock_ptr(rw, helper)   \
+		asm volatile(LOCK "subl $1,(%0)\n\t" \
+			     "jns 1f\n\t" \
+			     "call " helper "\n\t" \
+			     "1:\t" \
+			     ::"a" (rw) : "memory")
+
+	#define __build_read_lock_const(rw, helper)   \
+		asm volatile(LOCK "subl $1,%0\n\t" \
+			     "jns 1f\n\t" \
+			     "pushl %%eax\n\t" \
+			     "leal %0,%%eax\n\t" \
+			     "call " helper "\n\t" \
+			     "popl %%eax\n\t" \
+			     "1:\t" \
+			     :"=m" (*(volatile int *)rw) : : "memory")
+
+#else /* !CONFIG_SPINLINE */
+
+	#define __build_read_lock_ptr(rw, helper)   \
+		asm volatile(LOCK "subl $1,(%0)\n\t" \
+			     "js 2f\n" \
+			     "1:\n" \
+			     LOCK_SECTION_START("") \
+			     "2:\tcall " helper "\n\t" \
+			     "jmp 1b\n" \
+			     LOCK_SECTION_END \
+			     ::"a" (rw) : "memory")
+
+	#define __build_read_lock_const(rw, helper)   \
+		asm volatile(LOCK "subl $1,%0\n\t" \
+			     "js 2f\n" \
+			     "1:\n" \
+			     LOCK_SECTION_START("") \
+			     "2:\tpushl %%eax\n\t" \
+			     "leal %0,%%eax\n\t" \
+			     "call " helper "\n\t" \
+			     "popl %%eax\n\t" \
+			     "jmp 1b\n" \
+			     LOCK_SECTION_END \
+			     :"=m" (*(volatile int *)rw) : : "memory")
+
+#endif /* CONFIG_SPINLINE */
+
 
 #define __build_read_lock(rw, helper)	do { \
 						if (__builtin_constant_p(rw)) \
@@ -50,28 +74,51 @@
 							__build_read_lock_ptr(rw, helper); \
 					} while (0)
 
-#define __build_write_lock_ptr(rw, helper) \
-	asm volatile(LOCK "subl $" RW_LOCK_BIAS_STR ",(%0)\n\t" \
-		     "jnz 2f\n" \
-		     "1:\n" \
-		     LOCK_SECTION_START("") \
-		     "2:\tcall " helper "\n\t" \
-		     "jmp 1b\n" \
-		     LOCK_SECTION_END \
-		     ::"a" (rw) : "memory")
-
-#define __build_write_lock_const(rw, helper) \
-	asm volatile(LOCK "subl $" RW_LOCK_BIAS_STR ",%0\n\t" \
-		     "jnz 2f\n" \
-		     "1:\n" \
-		     LOCK_SECTION_START("") \
-		     "2:\tpushl %%eax\n\t" \
-		     "leal %0,%%eax\n\t" \
-		     "call " helper "\n\t" \
-		     "popl %%eax\n\t" \
-		     "jmp 1b\n" \
-		     LOCK_SECTION_END \
-		     :"=m" (*(volatile int *)rw) : : "memory")
+#ifdef CONFIG_SPINLINE
+
+	#define __build_write_lock_ptr(rw, helper) \
+		asm volatile(LOCK "subl $" RW_LOCK_BIAS_STR ",(%0)\n\t" \
+			     "jz 1f\n\t" \
+			     "call " helper "\n\t" \
+			     "1:\n" \
+			     ::"a" (rw) : "memory")
+
+	#define __build_write_lock_const(rw, helper) \
+		asm volatile(LOCK "subl $" RW_LOCK_BIAS_STR ",%0\n\t" \
+			     "jz 1f\n\t" \
+			     "pushl %%eax\n\t" \
+			     "leal %0,%%eax\n\t" \
+			     "call " helper "\n\t" \
+			     "popl %%eax\n\t" \
+			     "1:\n" \
+			     :"=m" (*(volatile int *)rw) : : "memory")
+
+#else /* !CONFIG_SPINLINE */
+
+	#define __build_write_lock_ptr(rw, helper) \
+		asm volatile(LOCK "subl $" RW_LOCK_BIAS_STR ",(%0)\n\t" \
+			     "jnz 2f\n" \
+			     "1:\n" \
+			     LOCK_SECTION_START("") \
+			     "2:\tcall " helper "\n\t" \
+			     "jmp 1b\n" \
+			     LOCK_SECTION_END \
+			     ::"a" (rw) : "memory")
+
+	#define __build_write_lock_const(rw, helper) \
+		asm volatile(LOCK "subl $" RW_LOCK_BIAS_STR ",%0\n\t" \
+			     "jnz 2f\n" \
+			     "1:\n" \
+			     LOCK_SECTION_START("") \
+			     "2:\tpushl %%eax\n\t" \
+			     "leal %0,%%eax\n\t" \
+			     "call " helper "\n\t" \
+			     "popl %%eax\n\t" \
+			     "jmp 1b\n" \
+			     LOCK_SECTION_END \
+			     :"=m" (*(volatile int *)rw) : : "memory")
+
+#endif /* CONFIG_SPINLINE */
 
 #define __build_write_lock(rw, helper)	do { \
 						if (__builtin_constant_p(rw)) \
--- diff/include/asm-i386/smp.h	2004-02-09 10:36:12.000000000 +0000
+++ source/include/asm-i386/smp.h	2004-02-23 13:56:47.000000000 +0000
@@ -34,7 +34,7 @@
 extern void smp_alloc_memory(void);
 extern int pic_mode;
 extern int smp_num_siblings;
-extern int cpu_sibling_map[];
+extern cpumask_t cpu_sibling_map[];
 
 extern void smp_flush_tlb(void);
 extern void smp_message_irq(int cpl, void *dev_id, struct pt_regs *regs);
--- diff/include/asm-i386/spinlock.h	2003-10-09 09:47:17.000000000 +0100
+++ source/include/asm-i386/spinlock.h	2004-02-23 13:56:47.000000000 +0000
@@ -43,18 +43,35 @@ typedef struct {
 #define spin_is_locked(x)	(*(volatile signed char *)(&(x)->lock) <= 0)
 #define spin_unlock_wait(x)	do { barrier(); } while(spin_is_locked(x))
 
-#define spin_lock_string \
-	"\n1:\t" \
-	"lock ; decb %0\n\t" \
-	"js 2f\n" \
-	LOCK_SECTION_START("") \
-	"2:\t" \
-	"rep;nop\n\t" \
-	"cmpb $0,%0\n\t" \
-	"jle 2b\n\t" \
-	"jmp 1b\n" \
-	LOCK_SECTION_END
+#ifdef CONFIG_SPINLINE
 
+	#define spin_lock_string \
+		"\n1:\t" \
+		"lock ; decb %0\n\t" \
+		"js 2f\n" \
+		"jmp 3f\n" \
+		"2:\t" \
+		"rep;nop\n\t" \
+		"cmpb $0,%0\n\t" \
+		"jle 2b\n\t" \
+		"jmp 1b\n" \
+		"3:\t"
+
+#else /* !CONFIG_SPINLINE */
+
+	#define spin_lock_string \
+		"\n1:\t" \
+		"lock ; decb %0\n\t" \
+		"js 2f\n" \
+		LOCK_SECTION_START("") \
+		"2:\t" \
+		"rep;nop\n\t" \
+		"cmpb $0,%0\n\t" \
+		"jle 2b\n\t" \
+		"jmp 1b\n" \
+		LOCK_SECTION_END
+
+#endif /* CONFIG_SPINLINE */
 /*
  * This works. Despite all the confusion.
  * (except on PPro SMP or if we are using OOSTORE)
@@ -138,6 +155,11 @@ here:
  */
 typedef struct {
 	volatile unsigned int lock;
+#ifdef CONFIG_LOCKMETER
+	/* required for LOCKMETER since all bits in lock are used */
+	/* and we need this storage for CPU and lock INDEX        */
+	unsigned lockmeter_magic;
+#endif
 #ifdef CONFIG_DEBUG_SPINLOCK
 	unsigned magic;
 #endif
@@ -145,11 +167,19 @@ typedef struct {
 
 #define RWLOCK_MAGIC	0xdeaf1eed
 
+#ifdef CONFIG_LOCKMETER
+#ifdef CONFIG_DEBUG_SPINLOCK
+#define RWLOCK_MAGIC_INIT	, 0, RWLOCK_MAGIC
+#else
+#define RWLOCK_MAGIC_INIT	, 0
+#endif
+#else /* !CONFIG_LOCKMETER */
 #ifdef CONFIG_DEBUG_SPINLOCK
 #define RWLOCK_MAGIC_INIT	, RWLOCK_MAGIC
 #else
 #define RWLOCK_MAGIC_INIT	/* */
 #endif
+#endif /* !CONFIG_LOCKMETER */
 
 #define RW_LOCK_UNLOCKED (rwlock_t) { RW_LOCK_BIAS RWLOCK_MAGIC_INIT }
 
@@ -196,4 +226,60 @@ static inline int _raw_write_trylock(rwl
 	return 0;
 }
 
+#ifdef CONFIG_LOCKMETER
+static inline int _raw_read_trylock(rwlock_t *lock)
+{
+/* FIXME -- replace with assembler */
+	atomic_t *count = (atomic_t *)lock;
+	atomic_dec(count);
+	if (count->counter > 0)
+		return 1;
+	atomic_inc(count);
+	return 0;
+}
+#endif
+
+#if defined(CONFIG_LOCKMETER) && defined(CONFIG_HAVE_DEC_LOCK)
+extern void _metered_spin_lock  (spinlock_t *lock);
+extern void _metered_spin_unlock(spinlock_t *lock);
+
+/*
+ *  Matches what is in arch/i386/lib/dec_and_lock.c, except this one is
+ *  "static inline" so that the spin_lock(), if actually invoked, is charged
+ *  against the real caller, not against the catch-all atomic_dec_and_lock
+ */
+static inline int atomic_dec_and_lock(atomic_t *atomic, spinlock_t *lock)
+{
+	int counter;
+	int newcount;
+
+repeat:
+	counter = atomic_read(atomic);
+	newcount = counter-1;
+
+	if (!newcount)
+		goto slow_path;
+
+	asm volatile("lock; cmpxchgl %1,%2"
+		:"=a" (newcount)
+		:"r" (newcount), "m" (atomic->counter), "0" (counter));
+
+	/* If the above failed, "eax" will have changed */
+	if (newcount != counter)
+		goto repeat;
+	return 0;
+
+slow_path:
+	preempt_disable();
+	_metered_spin_lock(lock);
+	if (atomic_dec_and_test(atomic))
+		return 1;
+	_metered_spin_unlock(lock);
+	preempt_enable();
+	return 0;
+}
+
+#define ATOMIC_DEC_AND_LOCK
+#endif
+
 #endif /* __ASM_SPINLOCK_H */
--- diff/include/asm-i386/string.h	2004-02-18 08:54:12.000000000 +0000
+++ source/include/asm-i386/string.h	2004-02-23 13:56:47.000000000 +0000
@@ -58,6 +58,29 @@ __asm__ __volatile__(
 return dest;
 }
 
+/*
+ * This is a more generic variant of strncpy_count() suitable for
+ * implementing string-access routines with all sorts of return
+ * code semantics. It's used by mm/usercopy.c.
+ */
+static inline size_t strncpy_count(char * dest,const char *src,size_t count)
+{
+	__asm__ __volatile__(
+
+	"1:\tdecl %0\n\t"
+	"js 2f\n\t"
+	"lodsb\n\t"
+	"stosb\n\t"
+	"testb %%al,%%al\n\t"
+	"jne 1b\n\t"
+	"2:"
+	"incl %0"
+	: "=c" (count)
+	:"S" (src),"D" (dest),"0" (count) : "memory");
+
+	return count;
+}
+
 static inline char * strcat(char * dest,const char * src)
 {
 int d0, d1, d2, d3;
--- diff/include/asm-i386/thread_info.h	2003-10-09 09:47:17.000000000 +0100
+++ source/include/asm-i386/thread_info.h	2004-02-23 13:56:47.000000000 +0000
@@ -33,23 +33,12 @@ struct thread_info {
 					 	   0-0xBFFFFFFF for user-thead
 						   0-0xFFFFFFFF for kernel-thread
 						*/
-	struct restart_block    restart_block;
+	void *real_stack, *virtual_stack, *user_pgd;
 
+	struct restart_block    restart_block;
 	__u8			supervisor_stack[0];
 };
 
-#else /* !__ASSEMBLY__ */
-
-/* offsets into the thread_info struct for assembly code access */
-#define TI_TASK		0x00000000
-#define TI_EXEC_DOMAIN	0x00000004
-#define TI_FLAGS	0x00000008
-#define TI_STATUS	0x0000000C
-#define TI_CPU		0x00000010
-#define TI_PRE_COUNT	0x00000014
-#define TI_ADDR_LIMIT	0x00000018
-#define TI_RESTART_BLOCK 0x000001C
-
 #endif
 
 #define PREEMPT_ACTIVE		0x4000000
@@ -61,7 +50,7 @@ struct thread_info {
  */
 #ifndef __ASSEMBLY__
 
-#define INIT_THREAD_INFO(tsk)			\
+#define INIT_THREAD_INFO(tsk, thread_info)	\
 {						\
 	.task		= &tsk,			\
 	.exec_domain	= &default_exec_domain,	\
@@ -72,33 +61,54 @@ struct thread_info {
 	.restart_block = {			\
 		.fn = do_no_restart_syscall,	\
 	},					\
+	.real_stack	= &thread_info,		\
 }
 
 #define init_thread_info	(init_thread_union.thread_info)
 #define init_stack		(init_thread_union.stack)
 
+#define THREAD_SIZE (2*PAGE_SIZE)
+
 /* how to get the thread information struct from C */
 static inline struct thread_info *current_thread_info(void)
 {
 	struct thread_info *ti;
-	__asm__("andl %%esp,%0; ":"=r" (ti) : "0" (~8191UL));
+	__asm__("andl %%esp,%0; ":"=r" (ti) : "0" (~(THREAD_SIZE - 1)));
 	return ti;
 }
 
 /* thread information allocation */
-#define THREAD_SIZE (2*PAGE_SIZE)
-#define alloc_thread_info(task) ((struct thread_info *)kmalloc(THREAD_SIZE, GFP_KERNEL))
+#ifdef CONFIG_DEBUG_STACK_USAGE
+#define alloc_thread_info(tsk)					\
+	({							\
+		struct thread_info *ret;			\
+								\
+		ret = kmalloc(THREAD_SIZE, GFP_KERNEL);		\
+		if (ret)					\
+			memset(ret, 0, THREAD_SIZE);		\
+		ret;						\
+	})
+#else
+#define alloc_thread_info(tsk) kmalloc(THREAD_SIZE, GFP_KERNEL)
+#endif
+
 #define free_thread_info(info)	kfree(info)
 #define get_thread_info(ti) get_task_struct((ti)->task)
 #define put_thread_info(ti) put_task_struct((ti)->task)
 
 #else /* !__ASSEMBLY__ */
 
+#define THREAD_SIZE	8192
+
 /* how to get the thread information struct from ASM */
 #define GET_THREAD_INFO(reg) \
-	movl $-8192, reg; \
+	movl $-THREAD_SIZE, reg; \
 	andl %esp, reg
 
+/* use this one if reg already contains %esp */
+#define GET_THREAD_INFO_WITH_ESP(reg) \
+	andl $-THREAD_SIZE, reg
+
 #endif
 
 /*
@@ -113,6 +123,7 @@ static inline struct thread_info *curren
 #define TIF_NEED_RESCHED	3	/* rescheduling necessary */
 #define TIF_SINGLESTEP		4	/* restore singlestep on return to user mode */
 #define TIF_IRET		5	/* return with iret */
+#define TIF_DB7			6	/* has debug registers */
 #define TIF_POLLING_NRFLAG	16	/* true if poll_idle() is polling TIF_NEED_RESCHED */
 
 #define _TIF_SYSCALL_TRACE	(1<<TIF_SYSCALL_TRACE)
@@ -121,6 +132,7 @@ static inline struct thread_info *curren
 #define _TIF_NEED_RESCHED	(1<<TIF_NEED_RESCHED)
 #define _TIF_SINGLESTEP		(1<<TIF_SINGLESTEP)
 #define _TIF_IRET		(1<<TIF_IRET)
+#define _TIF_DB7		(1<<TIF_DB7)
 #define _TIF_POLLING_NRFLAG	(1<<TIF_POLLING_NRFLAG)
 
 #define _TIF_WORK_MASK		0x0000FFFE	/* work to do on interrupt/exception return */
--- diff/include/asm-i386/timer.h	2004-01-19 10:22:59.000000000 +0000
+++ source/include/asm-i386/timer.h	2004-02-23 13:56:47.000000000 +0000
@@ -40,9 +40,13 @@ extern struct timer_opts timer_cyclone;
 #endif
 
 extern unsigned long calibrate_tsc(void);
+extern void init_cpu_khz(void);
 #ifdef CONFIG_HPET_TIMER
 extern struct timer_opts timer_hpet;
 extern unsigned long calibrate_tsc_hpet(unsigned long *tsc_hpet_quotient_ptr);
 #endif
 
+#ifdef CONFIG_X86_PM_TIMER
+extern struct timer_opts timer_pmtmr;
+#endif
 #endif
--- diff/include/asm-i386/timex.h	2003-06-30 10:07:29.000000000 +0100
+++ source/include/asm-i386/timex.h	2004-02-23 13:56:47.000000000 +0000
@@ -12,7 +12,7 @@
 #ifdef CONFIG_X86_PC9800
    extern int CLOCK_TICK_RATE;
 #else
-#ifdef CONFIG_MELAN
+#ifdef CONFIG_X86_ELAN
 #  define CLOCK_TICK_RATE 1189200 /* AMD Elan has different frequency! */
 #else
 #  define CLOCK_TICK_RATE 1193182 /* Underlying HZ */
--- diff/include/asm-i386/tlbflush.h	2003-10-09 09:47:17.000000000 +0100
+++ source/include/asm-i386/tlbflush.h	2004-02-23 13:56:47.000000000 +0000
@@ -85,22 +85,28 @@ extern unsigned long pgkern_mask;
 
 static inline void flush_tlb_mm(struct mm_struct *mm)
 {
+#ifndef CONFIG_X86_SWITCH_PAGETABLES
 	if (mm == current->active_mm)
 		__flush_tlb();
+#endif
 }
 
 static inline void flush_tlb_page(struct vm_area_struct *vma,
 	unsigned long addr)
 {
+#ifndef CONFIG_X86_SWITCH_PAGETABLES
 	if (vma->vm_mm == current->active_mm)
 		__flush_tlb_one(addr);
+#endif
 }
 
 static inline void flush_tlb_range(struct vm_area_struct *vma,
 	unsigned long start, unsigned long end)
 {
+#ifndef CONFIG_X86_SWITCH_PAGETABLES
 	if (vma->vm_mm == current->active_mm)
 		__flush_tlb();
+#endif
 }
 
 #else
@@ -111,11 +117,10 @@ static inline void flush_tlb_range(struc
 	__flush_tlb()
 
 extern void flush_tlb_all(void);
-extern void flush_tlb_current_task(void);
 extern void flush_tlb_mm(struct mm_struct *);
 extern void flush_tlb_page(struct vm_area_struct *, unsigned long);
 
-#define flush_tlb()	flush_tlb_current_task()
+#define flush_tlb()	flush_tlb_all()
 
 static inline void flush_tlb_range(struct vm_area_struct * vma, unsigned long start, unsigned long end)
 {
--- diff/include/asm-i386/uaccess.h	2003-10-09 09:47:17.000000000 +0100
+++ source/include/asm-i386/uaccess.h	2004-02-23 13:56:47.000000000 +0000
@@ -26,7 +26,7 @@
 
 
 #define KERNEL_DS	MAKE_MM_SEG(0xFFFFFFFFUL)
-#define USER_DS		MAKE_MM_SEG(PAGE_OFFSET)
+#define USER_DS		MAKE_MM_SEG(TASK_SIZE)
 
 #define get_ds()	(KERNEL_DS)
 #define get_fs()	(current_thread_info()->addr_limit)
@@ -149,6 +149,45 @@ extern void __get_user_4(void);
 		:"=a" (ret),"=d" (x) \
 		:"0" (ptr))
 
+extern int get_user_size(unsigned int size, void *val, const void *ptr);
+extern int put_user_size(unsigned int size, const void *val, void *ptr);
+extern int zero_user_size(unsigned int size, void *ptr);
+extern int copy_str_fromuser_size(unsigned int size, void *val, const void *ptr);
+extern int strlen_fromuser_size(unsigned int size, const void *ptr);
+
+
+# define indirect_get_user(x,ptr)					\
+({	int __ret_gu,__val_gu;						\
+	__typeof__(ptr) __ptr_gu = (ptr);				\
+	__ret_gu = get_user_size(sizeof(*__ptr_gu), &__val_gu,__ptr_gu) ? -EFAULT : 0;\
+	(x) = (__typeof__(*__ptr_gu))__val_gu;				\
+	__ret_gu;							\
+})
+#define indirect_put_user(x,ptr)					\
+({									\
+	__typeof__(*(ptr)) *__ptr_pu = (ptr), __x_pu = (x);		\
+	put_user_size(sizeof(*__ptr_pu), &__x_pu, __ptr_pu) ? -EFAULT : 0; \
+})
+#define __indirect_put_user indirect_put_user
+#define __indirect_get_user indirect_get_user
+
+#define indirect_copy_from_user(to,from,n) get_user_size(n,to,from)
+#define indirect_copy_to_user(to,from,n) put_user_size(n,from,to)
+
+#define __indirect_copy_from_user indirect_copy_from_user
+#define __indirect_copy_to_user indirect_copy_to_user
+
+#define indirect_strncpy_from_user(dst, src, count) \
+		copy_str_fromuser_size(count, dst, src)
+
+extern int strlen_fromuser_size(unsigned int size, const void *ptr);
+#define indirect_strnlen_user(str, n) strlen_fromuser_size(n, str)
+#define indirect_strlen_user(str) indirect_strnlen_user(str, ~0UL >> 1)
+
+extern int zero_user_size(unsigned int size, void *ptr);
+
+#define indirect_clear_user(mem, len) zero_user_size(len, mem)
+#define __indirect_clear_user clear_user
 
 /* Careful: we have to cast the result to the type of the pointer for sign reasons */
 /**
@@ -168,7 +207,7 @@ extern void __get_user_4(void);
  * Returns zero on success, or -EFAULT on error.
  * On error, the variable @x is set to zero.
  */
-#define get_user(x,ptr)							\
+#define direct_get_user(x,ptr)						\
 ({	int __ret_gu,__val_gu;						\
 	switch(sizeof (*(ptr))) {					\
 	case 1:  __get_user_x(1,__ret_gu,__val_gu,ptr); break;		\
@@ -198,7 +237,7 @@ extern void __put_user_bad(void);
  *
  * Returns zero on success, or -EFAULT on error.
  */
-#define put_user(x,ptr)							\
+#define direct_put_user(x,ptr)						\
   __put_user_check((__typeof__(*(ptr)))(x),(ptr),sizeof(*(ptr)))
 
 
@@ -222,7 +261,7 @@ extern void __put_user_bad(void);
  * Returns zero on success, or -EFAULT on error.
  * On error, the variable @x is set to zero.
  */
-#define __get_user(x,ptr) \
+#define __direct_get_user(x,ptr) \
   __get_user_nocheck((x),(ptr),sizeof(*(ptr)))
 
 
@@ -245,7 +284,7 @@ extern void __put_user_bad(void);
  *
  * Returns zero on success, or -EFAULT on error.
  */
-#define __put_user(x,ptr) \
+#define __direct_put_user(x,ptr) \
   __put_user_nocheck((__typeof__(*(ptr)))(x),(ptr),sizeof(*(ptr)))
 
 #define __put_user_nocheck(x,ptr,size)				\
@@ -396,7 +435,7 @@ unsigned long __copy_from_user_ll(void *
  * On success, this will be zero.
  */
 static inline unsigned long
-__copy_to_user(void __user *to, const void *from, unsigned long n)
+__direct_copy_to_user(void __user *to, const void *from, unsigned long n)
 {
 	if (__builtin_constant_p(n)) {
 		unsigned long ret;
@@ -434,7 +473,7 @@ __copy_to_user(void __user *to, const vo
  * data to the requested size using zero bytes.
  */
 static inline unsigned long
-__copy_from_user(void *to, const void __user *from, unsigned long n)
+__direct_copy_from_user(void *to, const void __user *from, unsigned long n)
 {
 	if (__builtin_constant_p(n)) {
 		unsigned long ret;
@@ -468,11 +507,11 @@ __copy_from_user(void *to, const void __
  * On success, this will be zero.
  */
 static inline unsigned long
-copy_to_user(void __user *to, const void *from, unsigned long n)
+direct_copy_to_user(void __user *to, const void *from, unsigned long n)
 {
 	might_sleep();
 	if (access_ok(VERIFY_WRITE, to, n))
-		n = __copy_to_user(to, from, n);
+		n = __direct_copy_to_user(to, from, n);
 	return n;
 }
 
@@ -493,11 +532,11 @@ copy_to_user(void __user *to, const void
  * data to the requested size using zero bytes.
  */
 static inline unsigned long
-copy_from_user(void *to, const void __user *from, unsigned long n)
+direct_copy_from_user(void *to, const void __user *from, unsigned long n)
 {
 	might_sleep();
 	if (access_ok(VERIFY_READ, from, n))
-		n = __copy_from_user(to, from, n);
+		n = __direct_copy_from_user(to, from, n);
 	else
 		memset(to, 0, n);
 	return n;
@@ -520,10 +559,68 @@ long __strncpy_from_user(char *dst, cons
  * If there is a limit on the length of a valid string, you may wish to
  * consider using strnlen_user() instead.
  */
-#define strlen_user(str) strnlen_user(str, ~0UL >> 1)
 
-long strnlen_user(const char __user *str, long n);
-unsigned long clear_user(void __user *mem, unsigned long len);
-unsigned long __clear_user(void __user *mem, unsigned long len);
+long direct_strncpy_from_user(char *dst, const char *src, long count);
+long __direct_strncpy_from_user(char *dst, const char *src, long count);
+#define direct_strlen_user(str) direct_strnlen_user(str, ~0UL >> 1)
+long direct_strnlen_user(const char *str, long n);
+unsigned long direct_clear_user(void *mem, unsigned long len);
+unsigned long __direct_clear_user(void *mem, unsigned long len);
+
+extern int indirect_uaccess;
+
+#ifdef CONFIG_X86_UACCESS_INDIRECT
+
+/*
+ * Return code and zeroing semantics:
+
+ __clear_user          0                      <-> bytes not done
+ clear_user            0                      <-> bytes not done
+ __copy_to_user        0                      <-> bytes not done
+ copy_to_user          0                      <-> bytes not done
+ __copy_from_user      0                      <-> bytes not done, zero rest
+ copy_from_user        0                      <-> bytes not done, zero rest
+ __get_user            0                      <-> -EFAULT
+ get_user              0                      <-> -EFAULT
+ __put_user            0                      <-> -EFAULT
+ put_user              0                      <-> -EFAULT
+ strlen_user           strlen + 1             <-> 0
+ strnlen_user          strlen + 1 (or n+1)    <-> 0
+ strncpy_from_user     strlen (or n)          <-> -EFAULT
+
+ */
+
+#define __clear_user(mem,len) __indirect_clear_user(mem,len)
+#define clear_user(mem,len) indirect_clear_user(mem,len)
+#define __copy_to_user(to,from,n) __indirect_copy_to_user(to,from,n)
+#define copy_to_user(to,from,n) indirect_copy_to_user(to,from,n)
+#define __copy_from_user(to,from,n) __indirect_copy_from_user(to,from,n)
+#define copy_from_user(to,from,n) indirect_copy_from_user(to,from,n)
+#define __get_user(val,ptr) __indirect_get_user(val,ptr)
+#define get_user(val,ptr) indirect_get_user(val,ptr)
+#define __put_user(val,ptr) __indirect_put_user(val,ptr)
+#define put_user(val,ptr) indirect_put_user(val,ptr)
+#define strlen_user(str) indirect_strlen_user(str)
+#define strnlen_user(src,count) indirect_strnlen_user(src,count)
+#define strncpy_from_user(dst,src,count) \
+			indirect_strncpy_from_user(dst,src,count)
+
+#else
+
+#define __clear_user __direct_clear_user
+#define clear_user direct_clear_user
+#define __copy_to_user __direct_copy_to_user
+#define copy_to_user direct_copy_to_user
+#define __copy_from_user __direct_copy_from_user
+#define copy_from_user direct_copy_from_user
+#define __get_user __direct_get_user
+#define get_user direct_get_user
+#define __put_user __direct_put_user
+#define put_user direct_put_user
+#define strlen_user direct_strlen_user
+#define strnlen_user direct_strnlen_user
+#define strncpy_from_user direct_strncpy_from_user
+
+#endif /* CONFIG_X86_UACCESS_INDIRECT */
 
 #endif /* __i386_UACCESS_H */
--- diff/include/asm-i386/unistd.h	2004-02-18 08:54:12.000000000 +0000
+++ source/include/asm-i386/unistd.h	2004-02-23 13:56:47.000000000 +0000
@@ -373,6 +373,8 @@ __syscall_return(type,__res); \
 
 #ifdef __KERNEL_SYSCALLS__
 
+#include <asm/ptrace.h>
+
 /*
  * we need this inline - forking from kernel space will result
  * in NO COPY ON WRITE (!!!), until an execve is executed. This
@@ -395,6 +397,18 @@ static inline _syscall3(int,open,const c
 static inline _syscall1(int,close,int,fd)
 static inline _syscall3(pid_t,waitpid,pid_t,pid,int *,wait_stat,int,options)
 
+asmlinkage int sys_modify_ldt(int func, void __user *ptr, unsigned long bytecount);
+asmlinkage long sys_mmap2(unsigned long addr, unsigned long len,
+			unsigned long prot, unsigned long flags,
+			unsigned long fd, unsigned long pgoff);
+asmlinkage int sys_execve(struct pt_regs regs);
+asmlinkage int sys_clone(struct pt_regs regs);
+asmlinkage int sys_fork(struct pt_regs regs);
+asmlinkage int sys_vfork(struct pt_regs regs);
+asmlinkage int sys_pipe(unsigned long __user *fildes);
+asmlinkage int sys_ptrace(long request, long pid, long addr, long data);
+asmlinkage long sys_iopl(unsigned long unused);
+
 #endif
 
 /*
--- diff/include/asm-ia64/compat.h	2003-08-20 14:16:33.000000000 +0100
+++ source/include/asm-ia64/compat.h	2004-02-23 13:56:47.000000000 +0000
@@ -26,6 +26,8 @@ typedef u16		compat_ipc_pid_t;
 typedef s32		compat_daddr_t;
 typedef u32		compat_caddr_t;
 typedef __kernel_fsid_t	compat_fsid_t;
+typedef s32		compat_key_t;
+typedef u32		compat_timer_t;
 
 typedef s32		compat_int_t;
 typedef s32		compat_long_t;
@@ -116,6 +118,64 @@ typedef u32		compat_sigset_word;
 #define COMPAT_OFF_T_MAX	0x7fffffff
 #define COMPAT_LOFF_T_MAX	0x7fffffffffffffffL
 
+struct compat_ipc64_perm {
+	compat_key_t key;
+	compat_uid32_t uid;
+	compat_gid32_t gid;
+	compat_uid32_t cuid;
+	compat_gid32_t cgid;
+	unsigned short mode;
+	unsigned short __pad1;
+	unsigned short seq;
+	unsigned short __pad2;
+	compat_ulong_t unused1;
+	compat_ulong_t unused2;
+};
+
+struct compat_semid64_ds {
+	struct compat_ipc64_perm sem_perm;
+	compat_time_t  sem_otime;
+	compat_ulong_t __unused1;
+	compat_time_t  sem_ctime;
+	compat_ulong_t __unused2;
+	compat_ulong_t sem_nsems;
+	compat_ulong_t __unused3;
+	compat_ulong_t __unused4;
+};
+
+struct compat_msqid64_ds {
+	struct compat_ipc64_perm msg_perm;
+	compat_time_t  msg_stime;
+	compat_ulong_t __unused1;
+	compat_time_t  msg_rtime;
+	compat_ulong_t __unused2;
+	compat_time_t  msg_ctime;
+	compat_ulong_t __unused3;
+	compat_ulong_t msg_cbytes;
+	compat_ulong_t msg_qnum;
+	compat_ulong_t msg_qbytes;
+	compat_pid_t   msg_lspid;
+	compat_pid_t   msg_lrpid;
+	compat_ulong_t __unused4;
+	compat_ulong_t __unused5;
+};
+
+struct compat_shmid64_ds {
+	struct compat_ipc64_perm shm_perm;
+	compat_size_t  shm_segsz;
+	compat_time_t  shm_atime;
+	compat_ulong_t __unused1;
+	compat_time_t  shm_dtime;
+	compat_ulong_t __unused2;
+	compat_time_t  shm_ctime;
+	compat_ulong_t __unused3;
+	compat_pid_t   shm_cpid;
+	compat_pid_t   shm_lpid;
+	compat_ulong_t shm_nattch;
+	compat_ulong_t __unused4;
+	compat_ulong_t __unused5;
+};
+
 /*
  * A pointer passed in from user mode. This should not be used for syscall parameters,
  * just declare them as pointers because the syscall entry code will have appropriately
--- diff/include/asm-ia64/param.h	2004-02-09 10:36:12.000000000 +0000
+++ source/include/asm-ia64/param.h	2004-02-23 13:56:47.000000000 +0000
@@ -12,10 +12,6 @@
 
 #define EXEC_PAGESIZE	65536
 
-#ifndef NGROUPS
-# define NGROUPS	32
-#endif
-
 #ifndef NOGROUP
 # define NOGROUP	(-1)
 #endif
--- diff/include/asm-ia64/pci.h	2004-02-18 08:54:12.000000000 +0000
+++ source/include/asm-ia64/pci.h	2004-02-23 13:56:47.000000000 +0000
@@ -97,6 +97,8 @@ struct pci_controller {
 
 	unsigned int windows;
 	struct pci_window *window;
+
+	void *platform_data;
 };
 
 #define PCI_CONTROLLER(busdev) ((struct pci_controller *) busdev->sysdata)
--- diff/include/asm-ia64/sal.h	2004-01-19 10:22:59.000000000 +0000
+++ source/include/asm-ia64/sal.h	2004-02-23 13:56:47.000000000 +0000
@@ -741,10 +741,10 @@ ia64_sal_mc_set_params (u64 param_type, 
 
 /* Read from PCI configuration space */
 static inline s64
-ia64_sal_pci_config_read (u64 pci_config_addr, u64 size, u64 *value)
+ia64_sal_pci_config_read (u64 pci_config_addr, int type, u64 size, u64 *value)
 {
 	struct ia64_sal_retval isrv;
-	SAL_CALL(isrv, SAL_PCI_CONFIG_READ, pci_config_addr, size, 0, 0, 0, 0, 0);
+	SAL_CALL(isrv, SAL_PCI_CONFIG_READ, pci_config_addr, size, type, 0, 0, 0, 0);
 	if (value)
 		*value = isrv.v0;
 	return isrv.status;
@@ -752,11 +752,11 @@ ia64_sal_pci_config_read (u64 pci_config
 
 /* Write to PCI configuration space */
 static inline s64
-ia64_sal_pci_config_write (u64 pci_config_addr, u64 size, u64 value)
+ia64_sal_pci_config_write (u64 pci_config_addr, int type, u64 size, u64 value)
 {
 	struct ia64_sal_retval isrv;
 	SAL_CALL(isrv, SAL_PCI_CONFIG_WRITE, pci_config_addr, size, value,
-	         0, 0, 0, 0);
+	         type, 0, 0, 0);
 	return isrv.status;
 }
 
--- diff/include/asm-ia64/sn/clksupport.h	2004-02-18 08:54:12.000000000 +0000
+++ source/include/asm-ia64/sn/clksupport.h	2004-02-23 13:56:47.000000000 +0000
@@ -24,17 +24,16 @@
 #define _ASM_IA64_SN_CLKSUPPORT_H
 
 #include <asm/sn/arch.h>
+#include <asm/sn/addrs.h>
+#include <asm/sn/sn2/addrs.h>
+#include <asm/sn/sn2/shubio.h>
+#include <asm/sn/sn2/shub_mmr.h>
 
 typedef long clkreg_t;
 
 extern unsigned long sn_rtc_cycles_per_second;
 extern unsigned long sn_rtc_per_itc;
 
-
-#include <asm/sn/addrs.h>
-#include <asm/sn/sn2/addrs.h>
-#include <asm/sn/sn2/shubio.h>
-#include <asm/sn/sn2/shub_mmr.h>
 #define RTC_MASK		SH_RTC_MASK
 #define RTC_COUNTER_ADDR	((clkreg_t*)LOCAL_MMR_ADDR(SH_RTC))
 #define RTC_COMPARE_A_ADDR      ((clkreg_t*)LOCAL_MMR_ADDR(SH_RTC))
--- diff/include/asm-ia64/sn/dmamap.h	2004-02-09 10:36:12.000000000 +0000
+++ source/include/asm-ia64/sn/dmamap.h	2004-02-23 13:56:47.000000000 +0000
@@ -8,12 +8,6 @@
 #ifndef _ASM_IA64_SN_DMAMAP_H
 #define _ASM_IA64_SN_DMAMAP_H
 
-#include <asm/sn/types.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
 /*
  * Definitions for allocating, freeing, and using DMA maps
  */
@@ -43,10 +37,6 @@ typedef struct dmamap {
 	unsigned long	dma_virtaddr;	/* Beginning virtual address that is mapped */
 } dmamap_t;
 
-#ifdef __cplusplus
-}
-#endif
-
 /* standard flags values for pio_map routines,
  * including {xtalk,pciio}_dmamap calls.
  * NOTE: try to keep these in step with PIOMAP flags.
--- diff/include/asm-ia64/sn/driver.h	2004-02-18 08:54:12.000000000 +0000
+++ source/include/asm-ia64/sn/driver.h	2004-02-23 13:56:47.000000000 +0000
@@ -23,10 +23,6 @@ typedef struct device_driver_s *device_d
 /* == Driver thread priority support == */
 typedef int ilvl_t;
 
-#ifdef __cplusplus
-extern "C" {
-#endif
-
 struct eframe_s;
 struct piomap;
 struct dmamap;
--- diff/include/asm-ia64/sn/intr.h	2004-02-09 10:36:12.000000000 +0000
+++ source/include/asm-ia64/sn/intr.h	2004-02-23 13:56:47.000000000 +0000
@@ -8,7 +8,6 @@
 #ifndef _ASM_IA64_SN_INTR_H
 #define _ASM_IA64_SN_INTR_H
 
-#include <linux/config.h>
 #include <asm/sn/sn2/intr.h>
 
 extern void sn_send_IPI_phys(long, int, int);
--- diff/include/asm-ia64/sn/io.h	2004-02-09 10:36:12.000000000 +0000
+++ source/include/asm-ia64/sn/io.h	2004-02-23 13:56:47.000000000 +0000
@@ -9,8 +9,6 @@
 #ifndef _ASM_IA64_SN_IO_H
 #define _ASM_IA64_SN_IO_H
 
-#include <linux/config.h>
-
 #include <asm/sn/addrs.h>
 
 /* Because we only have PCI I/O ports.  */
--- diff/include/asm-ia64/sn/ioc4.h	2004-02-09 10:36:12.000000000 +0000
+++ source/include/asm-ia64/sn/ioc4.h	2004-02-23 13:56:47.000000000 +0000
@@ -9,682 +9,6 @@
 #ifndef _ASM_IA64_SN_IOC4_H
 #define _ASM_IA64_SN_IOC4_H
 
-#if 0
-
-/*
- * ioc4.h - IOC4 chip header file
- */
-
-/* Notes:
- * The IOC4 chip is a 32-bit PCI device that provides 4 serial ports,
- * an IDE bus interface, a PC keyboard/mouse interface, and a real-time
- * external interrupt interface.
- *
- * It includes an optimized DMA buffer management, and a store-and-forward
- * buffer RAM.
- *
- * All IOC4 registers are 32 bits wide.
- */
-typedef __uint32_t ioc4reg_t;
-
-/*
- * PCI Configuration Space Register Address Map, use offset from IOC4 PCI
- * configuration base such that this can be used for multiple IOC4s
- */
-#define IOC4_PCI_ID		0x0	/* ID */
-
-#define IOC4_VENDOR_ID_NUM	0x10A9
-#define IOC4_DEVICE_ID_NUM	0x100A 
-#define IOC4_ADDRSPACE_MASK	0xfff00000ULL
-
-#define IOC4_PCI_SCR		0x4 /* Status/Command */
-#define IOC4_PCI_REV		0x8 /* Revision */
-#define IOC4_PCI_LAT		0xC /* Latency Timer */
-#define IOC4_PCI_BAR0		0x10 /* IOC4 base address 0 */
-#define IOC4_PCI_SIDV		0x2c /* Subsys ID and vendor */
-#define IOC4_PCI_CAP 		0x34 /* Capability pointer */
-#define IOC4_PCI_LATGNTINT      0x3c /* Max_lat, min_gnt, int_pin, int_line */
-
-/*
- * PCI Memory Space Map 
- */
-#define IOC4_PCI_ERR_ADDR_L     0x000	/* Low Error Address */
-#define IOC4_PCI_ERR_ADDR_VLD	     (0x1 << 0)
-#define IOC4_PCI_ERR_ADDR_MST_ID_MSK (0xf << 1)
-#define IOC4_PCI_ERR_ADDR_MUL_ERR    (0x1 << 5)
-#define IOC4_PCI_ERR_ADDR_ADDR_MSK   (0x3ffffff << 6)
-
-/* Master IDs contained in PCI_ERR_ADDR_MST_ID_MSK */
-#define IOC4_MST_ID_S0_TX		0
-#define IOC4_MST_ID_S0_RX		1
-#define IOC4_MST_ID_S1_TX		2
-#define IOC4_MST_ID_S1_RX		3
-#define IOC4_MST_ID_S2_TX		4
-#define IOC4_MST_ID_S2_RX		5
-#define IOC4_MST_ID_S3_TX		6
-#define IOC4_MST_ID_S3_RX		7
-#define IOC4_MST_ID_ATA 		8
-
-#define IOC4_PCI_ERR_ADDR_H	0x004	/* High Error Address */
-
-#define IOC4_SIO_IR	        0x008	/* SIO Interrupt Register */
-#define IOC4_OTHER_IR	        0x00C	/* Other Interrupt Register */
-
-/* These registers are read-only for general kernel code. To modify
- * them use the functions in ioc4.c
- */
-#define IOC4_SIO_IES_RO         0x010	/* SIO Interrupt Enable Set Reg */
-#define IOC4_OTHER_IES_RO       0x014	/* Other Interrupt Enable Set Reg */
-#define IOC4_SIO_IEC_RO         0x018	/* SIO Interrupt Enable Clear Reg */
-#define IOC4_OTHER_IEC_RO       0x01C	/* Other Interrupt Enable Clear Reg */
-
-#define IOC4_SIO_CR	        0x020	/* SIO Control Reg */
-#define IOC4_INT_OUT	        0x028	/* INT_OUT Reg (realtime interrupt) */
-#define IOC4_GPCR_S	        0x030	/* GenericPIO Cntrl Set Register */
-#define IOC4_GPCR_C	        0x034	/* GenericPIO Cntrl Clear Register */
-#define IOC4_GPDR	        0x038	/* GenericPIO Data Register */
-#define IOC4_GPPR_0	        0x040	/* GenericPIO Pin Registers */
-#define IOC4_GPPR_OFF	        0x4
-#define IOC4_GPPR(x)	        (IOC4_GPPR_0+(x)*IOC4_GPPR_OFF)
-
-/* ATAPI Registers */
-#define IOC4_ATA_0              0x100	/* Data w/timing */
-#define IOC4_ATA_1              0x104	/* Error/Features w/timing */
-#define IOC4_ATA_2              0x108	/* Sector Count w/timing */
-#define IOC4_ATA_3              0x10C	/* Sector Number w/timing */
-#define IOC4_ATA_4              0x110   /* Cyliner Low w/timing */
-#define IOC4_ATA_5              0x114	/* Cylinder High w/timing */
-#define IOC4_ATA_6              0x118	/* Device/Head w/timing */
-#define IOC4_ATA_7              0x11C	/* Status/Command w/timing */
-#define IOC4_ATA_0_AUX          0x120	/* Aux Status/Device Cntrl w/timing */
-#define IOC4_ATA_TIMING       	0x140	/* Timing value register 0 */
-#define IOC4_ATA_DMA_PTR_L      0x144   /* Low Memory Pointer to DMA List */
-#define IOC4_ATA_DMA_PTR_H      0x148   /* High Memory Pointer to DMA List */
-#define IOC4_ATA_DMA_ADDR_L     0x14C   /* Low Memory DMA Address */
-#define IOC4_ATA_DMA_ADDR_H     0x150   /* High Memory DMA Addresss */
-#define IOC4_ATA_BC_DEV         0x154	/* DMA Byte Count at Device */
-#define IOC4_ATA_BC_MEM         0x158	/* DMA Byte Count at Memory */
-#define IOC4_ATA_DMA_CTRL       0x15C	/* DMA Control/Status */
-
-/* Keyboard and Mouse Registers */
-#define IOC4_KM_CSR	        0x200	/* Kbd and Mouse Cntrl/Status Reg */
-#define IOC4_K_RD	        0x204	/* Kbd Read Data Register */
-#define IOC4_M_RD	        0x208	/* Mouse Read Data Register */
-#define IOC4_K_WD	        0x20C	/* Kbd Write Data Register */
-#define IOC4_M_WD	        0x210	/* Mouse Write Data Register */
-
-/* Serial Port Registers used for DMA mode serial I/O */
-#define IOC4_SBBR01_H	        0x300	/* Serial Port Ring Buffers 
-                                           Base Reg High for Channels 0 1*/
-#define IOC4_SBBR01_L	        0x304	/* Serial Port Ring Buffers 
-                                           Base Reg Low for Channels 0 1 */
-#define IOC4_SBBR23_H	        0x308	/* Serial Port Ring Buffers 
-                                           Base Reg High for Channels 2 3*/
-#define IOC4_SBBR23_L	        0x30C	/* Serial Port Ring Buffers 
-                                           Base Reg Low for Channels 2 3 */
-
-#define IOC4_SSCR_0	        0x310	/* Serial Port 0 Control */
-#define IOC4_STPIR_0	        0x314	/* Serial Port 0 TX Produce */
-#define IOC4_STCIR_0	        0x318	/* Serial Port 0 TX Consume */
-#define IOC4_SRPIR_0	        0x31C	/* Serial Port 0 RX Produce */
-#define IOC4_SRCIR_0	        0x320	/* Serial Port 0 RX Consume */
-#define IOC4_SRTR_0	        0x324	/* Serial Port 0 Receive Timer Reg */
-#define IOC4_SHADOW_0		0x328	/* Serial Port 0 16550 Shadow Reg */
-
-#define IOC4_SSCR_1	        0x32C	/* Serial Port 1 Control */
-#define IOC4_STPIR_1	        0x330	/* Serial Port 1 TX Produce */
-#define IOC4_STCIR_1	        0x334	/* Serial Port 1 TX Consume */
-#define IOC4_SRPIR_1	        0x338   /* Serial Port 1 RX Produce */
-#define IOC4_SRCIR_1	        0x33C	/* Serial Port 1 RX Consume */
-#define IOC4_SRTR_1	        0x340	/* Serial Port 1 Receive Timer Reg */
-#define IOC4_SHADOW_1		0x344	/* Serial Port 1 16550 Shadow Reg */
-
-#define IOC4_SSCR_2	        0x348	/* Serial Port 2 Control */
-#define IOC4_STPIR_2	        0x34C	/* Serial Port 2 TX Produce */
-#define IOC4_STCIR_2	        0x350	/* Serial Port 2 TX Consume */
-#define IOC4_SRPIR_2	        0x354	/* Serial Port 2 RX Produce */
-#define IOC4_SRCIR_2	        0x358	/* Serial Port 2 RX Consume */
-#define IOC4_SRTR_2	        0x35C	/* Serial Port 2 Receive Timer Reg */
-#define IOC4_SHADOW_2		0x360	/* Serial Port 2 16550 Shadow Reg */
-
-#define IOC4_SSCR_3	        0x364	/* Serial Port 3 Control */
-#define IOC4_STPIR_3	        0x368	/* Serial Port 3 TX Produce */
-#define IOC4_STCIR_3	        0x36C	/* Serial Port 3 TX Consume */
-#define IOC4_SRPIR_3	        0x370	/* Serial Port 3 RX Produce */
-#define IOC4_SRCIR_3	        0x374	/* Serial Port 3 RX Consume */
-#define IOC4_SRTR_3	        0x378	/* Serial Port 3 Receive Timer Reg */
-#define IOC4_SHADOW_3		0x37C	/* Serial Port 3 16550 Shadow Reg */
-
-#define IOC4_UART0_BASE         0x380   /* UART 0 */
-#define IOC4_UART1_BASE         0x388   /* UART 1 */
-#define IOC4_UART2_BASE         0x390   /* UART 2 */
-#define IOC4_UART3_BASE         0x398   /* UART 3 */
-
-/* Private page address aliases for usermode mapping */
-#define IOC4_INT_OUT_P	        0x04000	/* INT_OUT Reg */
-
-#define IOC4_SSCR_0_P	        0x08000 /* Serial Port 0 */
-#define IOC4_STPIR_0_P	        0x08004
-#define IOC4_STCIR_0_P	        0x08008	/* (read-only) */
-#define IOC4_SRPIR_0_P	        0x0800C	/* (read-only) */
-#define IOC4_SRCIR_0_P	        0x08010
-#define IOC4_SRTR_0_P	        0x08014
-#define IOC4_UART_LSMSMCR_0_P   0x08018	/* (read-only) */
-
-#define IOC4_SSCR_1_P	        0x0C000	/* Serial Port 1 */
-#define IOC4_STPIR_1_P	        0x0C004
-#define IOC4_STCIR_1_P	        0x0C008	/* (read-only) */
-#define IOC4_SRPIR_1_P	        0x0C00C	/* (read-only) */
-#define IOC4_SRCIR_1_P	        0x0C010
-#define IOC4_SRTR_1_P	        0x0C014
-#define IOC4_UART_LSMSMCR_1_P   0x0C018	/* (read-only) */
-
-#define IOC4_SSCR_2_P	        0x10000	/* Serial Port 2 */
-#define IOC4_STPIR_2_P	        0x10004
-#define IOC4_STCIR_2_P	        0x10008	/* (read-only) */
-#define IOC4_SRPIR_2_P	        0x1000C	/* (read-only) */
-#define IOC4_SRCIR_2_P	        0x10010
-#define IOC4_SRTR_2_P	        0x10014
-#define IOC4_UART_LSMSMCR_2_P   0x10018	/* (read-only) */
-
-#define IOC4_SSCR_3_P	        0x14000	/* Serial Port 3 */
-#define IOC4_STPIR_3_P	        0x14004
-#define IOC4_STCIR_3_P	        0x14008	/* (read-only) */
-#define IOC4_SRPIR_3_P	        0x1400C	/* (read-only) */
-#define IOC4_SRCIR_3_P	        0x14010
-#define IOC4_SRTR_3_P	        0x14014
-#define IOC4_UART_LSMSMCR_3_P   0x14018	/* (read-only) */
-
-#define IOC4_ALIAS_PAGE_SIZE	0x4000
-
-/* Interrupt types */
-typedef enum ioc4_intr_type_e {
-    ioc4_sio_intr_type,
-    ioc4_other_intr_type,
-    ioc4_num_intr_types
-} ioc4_intr_type_t;
-#define ioc4_first_intr_type    ioc4_sio_intr_type
-
-/* Bitmasks for IOC4_SIO_IR, IOC4_SIO_IEC, and IOC4_SIO_IES  */
-#define IOC4_SIO_IR_S0_TX_MT		0x00000001 /* Serial port 0 TX empty */
-#define IOC4_SIO_IR_S0_RX_FULL		0x00000002 /* Port 0 RX buf full */
-#define IOC4_SIO_IR_S0_RX_HIGH		0x00000004 /* Port 0 RX hiwat */
-#define IOC4_SIO_IR_S0_RX_TIMER		0x00000008 /* Port 0 RX timeout */
-#define IOC4_SIO_IR_S0_DELTA_DCD	0x00000010 /* Port 0 delta DCD */
-#define IOC4_SIO_IR_S0_DELTA_CTS	0x00000020 /* Port 0 delta CTS */
-#define IOC4_SIO_IR_S0_INT	        0x00000040 /* Port 0 pass-thru intr */
-#define IOC4_SIO_IR_S0_TX_EXPLICIT	0x00000080 /* Port 0 explicit TX thru */
-#define IOC4_SIO_IR_S1_TX_MT		0x00000100 /* Serial port 1 */
-#define IOC4_SIO_IR_S1_RX_FULL		0x00000200 /* */
-#define IOC4_SIO_IR_S1_RX_HIGH		0x00000400 /* */
-#define IOC4_SIO_IR_S1_RX_TIMER		0x00000800 /* */
-#define IOC4_SIO_IR_S1_DELTA_DCD	0x00001000 /* */
-#define IOC4_SIO_IR_S1_DELTA_CTS	0x00002000 /* */
-#define IOC4_SIO_IR_S1_INT		0x00004000 /* */
-#define IOC4_SIO_IR_S1_TX_EXPLICIT	0x00008000 /* */
-#define IOC4_SIO_IR_S2_TX_MT		0x00010000 /* Serial port 2 */
-#define IOC4_SIO_IR_S2_RX_FULL		0x00020000 /* */
-#define IOC4_SIO_IR_S2_RX_HIGH		0x00040000 /* */
-#define IOC4_SIO_IR_S2_RX_TIMER		0x00080000 /* */
-#define IOC4_SIO_IR_S2_DELTA_DCD	0x00100000 /* */
-#define IOC4_SIO_IR_S2_DELTA_CTS	0x00200000 /* */
-#define IOC4_SIO_IR_S2_INT		0x00400000 /* */
-#define IOC4_SIO_IR_S2_TX_EXPLICIT	0x00800000 /* */
-#define IOC4_SIO_IR_S3_TX_MT		0x01000000 /* Serial port 3 */
-#define IOC4_SIO_IR_S3_RX_FULL		0x02000000 /* */
-#define IOC4_SIO_IR_S3_RX_HIGH		0x04000000 /* */
-#define IOC4_SIO_IR_S3_RX_TIMER		0x08000000 /* */
-#define IOC4_SIO_IR_S3_DELTA_DCD	0x10000000 /* */
-#define IOC4_SIO_IR_S3_DELTA_CTS	0x20000000 /* */
-#define IOC4_SIO_IR_S3_INT		0x40000000 /* */
-#define IOC4_SIO_IR_S3_TX_EXPLICIT	0x80000000 /* */
-
-/* Per device interrupt masks */
-#define IOC4_SIO_IR_S0		(IOC4_SIO_IR_S0_TX_MT | \
-				 IOC4_SIO_IR_S0_RX_FULL | \
-				 IOC4_SIO_IR_S0_RX_HIGH | \
-				 IOC4_SIO_IR_S0_RX_TIMER | \
-				 IOC4_SIO_IR_S0_DELTA_DCD | \
-				 IOC4_SIO_IR_S0_DELTA_CTS | \
-				 IOC4_SIO_IR_S0_INT | \
-				 IOC4_SIO_IR_S0_TX_EXPLICIT)
-#define IOC4_SIO_IR_S1		(IOC4_SIO_IR_S1_TX_MT | \
-				 IOC4_SIO_IR_S1_RX_FULL | \
-				 IOC4_SIO_IR_S1_RX_HIGH | \
-				 IOC4_SIO_IR_S1_RX_TIMER | \
-				 IOC4_SIO_IR_S1_DELTA_DCD | \
-				 IOC4_SIO_IR_S1_DELTA_CTS | \
-				 IOC4_SIO_IR_S1_INT | \
-				 IOC4_SIO_IR_S1_TX_EXPLICIT)
-#define IOC4_SIO_IR_S2		(IOC4_SIO_IR_S2_TX_MT | \
-				 IOC4_SIO_IR_S2_RX_FULL | \
-				 IOC4_SIO_IR_S2_RX_HIGH | \
-				 IOC4_SIO_IR_S2_RX_TIMER | \
-				 IOC4_SIO_IR_S2_DELTA_DCD | \
-				 IOC4_SIO_IR_S2_DELTA_CTS | \
-				 IOC4_SIO_IR_S2_INT | \
-				 IOC4_SIO_IR_S2_TX_EXPLICIT)
-#define IOC4_SIO_IR_S3		(IOC4_SIO_IR_S3_TX_MT | \
-				 IOC4_SIO_IR_S3_RX_FULL | \
-				 IOC4_SIO_IR_S3_RX_HIGH | \
-				 IOC4_SIO_IR_S3_RX_TIMER | \
-				 IOC4_SIO_IR_S3_DELTA_DCD | \
-				 IOC4_SIO_IR_S3_DELTA_CTS | \
-				 IOC4_SIO_IR_S3_INT | \
-				 IOC4_SIO_IR_S3_TX_EXPLICIT)
-
-/* Bitmasks for IOC4_OTHER_IR, IOC4_OTHER_IEC, and IOC4_OTHER_IES  */
-#define IOC4_OTHER_IR_ATA_INT           0x00000001 /* ATAPI intr pass-thru */
-#define IOC4_OTHER_IR_ATA_MEMERR        0x00000002 /* ATAPI DMA PCI error */
-#define IOC4_OTHER_IR_S0_MEMERR         0x00000004 /* Port 0 PCI error */
-#define IOC4_OTHER_IR_S1_MEMERR         0x00000008 /* Port 1 PCI error */
-#define IOC4_OTHER_IR_S2_MEMERR         0x00000010 /* Port 2 PCI error */
-#define IOC4_OTHER_IR_S3_MEMERR         0x00000020 /* Port 3 PCI error */
-#define IOC4_OTHER_IR_KBD_INT		0x00000040 /* Kbd/mouse intr */
-#define IOC4_OTHER_IR_ATA_DMAINT        0x00000089 /* ATAPI DMA intr */
-#define IOC4_OTHER_IR_RT_INT		0x00800000 /* RT output pulse */
-#define IOC4_OTHER_IR_GEN_INT1		0x02000000 /* RT input pulse */
-#define IOC4_OTHER_IR_GEN_INT_SHIFT	        25
-
-/* Per device interrupt masks */
-#define IOC4_OTHER_IR_ATA       (IOC4_OTHER_IR_ATA_INT | \
-				 IOC4_OTHER_IR_ATA_MEMERR | \
-				 IOC4_OTHER_IR_ATA_DMAINT)
-#define IOC4_OTHER_IR_RT	(IOC4_OTHER_IR_RT_INT | IOC4_OTHER_IR_GEN_INT1)
-
-/* Macro to load pending interrupts */
-#define IOC4_PENDING_SIO_INTRS(mem)     (PCI_INW(&((mem)->sio_ir)) & \
-				         PCI_INW(&((mem)->sio_ies_ro)))
-#define IOC4_PENDING_OTHER_INTRS(mem)   (PCI_INW(&((mem)->other_ir)) & \
-				         PCI_INW(&((mem)->other_ies_ro)))
-
-/* Bitmasks for IOC4_SIO_CR */
-#define IOC4_SIO_SR_CMD_PULSE		0x00000004 /* Byte bus strobe length */
-#define IOC4_SIO_CR_CMD_PULSE_SHIFT              0
-#define IOC4_SIO_CR_ARB_DIAG		0x00000070 /* Current non-ATA PCI bus
-                                                      requester (ro) */
-#define IOC4_SIO_CR_ARB_DIAG_TX0	0x00000000
-#define IOC4_SIO_CR_ARB_DIAG_RX0	0x00000010
-#define IOC4_SIO_CR_ARB_DIAG_TX1	0x00000020
-#define IOC4_SIO_CR_ARB_DIAG_RX1	0x00000030
-#define IOC4_SIO_CR_ARB_DIAG_TX2	0x00000040
-#define IOC4_SIO_CR_ARB_DIAG_RX2	0x00000050
-#define IOC4_SIO_CR_ARB_DIAG_TX3	0x00000060
-#define IOC4_SIO_CR_ARB_DIAG_RX3	0x00000070
-#define IOC4_SIO_CR_SIO_DIAG_IDLE	0x00000080 /* 0 -> active request among
-                                                      serial ports (ro) */
-#define IOC4_SIO_CR_ATA_DIAG_IDLE	0x00000100 /* 0 -> active request from
-                                                      ATA port */
-#define IOC4_SIO_CR_ATA_DIAG_ACTIVE     0x00000200 /* 1 -> ATA request is winner */ 
-
-/* Bitmasks for IOC4_INT_OUT */
-#define IOC4_INT_OUT_COUNT	        0x0000ffff /* Pulse interval timer */
-#define IOC4_INT_OUT_MODE	        0x00070000 /* Mode mask */
-#define IOC4_INT_OUT_MODE_0             0x00000000 /* Set output to 0 */
-#define IOC4_INT_OUT_MODE_1             0x00040000 /* Set output to 1 */
-#define IOC4_INT_OUT_MODE_1PULSE        0x00050000 /* Send 1 pulse */
-#define IOC4_INT_OUT_MODE_PULSES        0x00060000 /* Send 1 pulse every interval */
-#define IOC4_INT_OUT_MODE_SQW           0x00070000 /* Toggle output every interval */
-#define IOC4_INT_OUT_DIAG	        0x40000000 /* Diag mode */
-#define IOC4_INT_OUT_INT_OUT            0x80000000 /* Current state of INT_OUT */
-
-/* Time constants for IOC4_INT_OUT */
-#define IOC4_INT_OUT_NS_PER_TICK        (15 * 520) /* 15 ns PCI clock, multi=520 */
-#define IOC4_INT_OUT_TICKS_PER_PULSE             3 /* Outgoing pulse lasts 3
-                                                      ticks */
-#define IOC4_INT_OUT_US_TO_COUNT(x)	           /* Convert uS to a count value */ \
-	(((x) * 10 + IOC4_INT_OUT_NS_PER_TICK / 200) *	\
-	 100 / IOC4_INT_OUT_NS_PER_TICK - 1)
-#define IOC4_INT_OUT_COUNT_TO_US(x)	           /* Convert count value to uS */ \
-	(((x) + 1) * IOC4_INT_OUT_NS_PER_TICK / 1000)
-#define IOC4_INT_OUT_MIN_TICKS                   3 /* Min period is width of
-                                                      pulse in "ticks" */
-#define IOC4_INT_OUT_MAX_TICKS  IOC4_INT_OUT_COUNT /* Largest possible count */
-
-/* Bitmasks for IOC4_GPCR */
-#define IOC4_GPCR_DIR	                0x000000ff /* Tristate pin in or out */
-#define IOC4_GPCR_DIR_PIN(x)              (1<<(x)) /* Access one of the DIR bits */
-#define IOC4_GPCR_EDGE	                0x0000ff00 /* Extint edge or level
-                                                      sensitive */
-#define IOC4_GPCR_EDGE_PIN(x)        (1<<((x)+7 )) /* Access one of the EDGE bits */
-
-/* Values for IOC4_GPCR */
-#define IOC4_GPCR_INT_OUT_EN            0x00100000 /* Enable INT_OUT to pin 0 */
-#define IOC4_GPCR_DIR_SER0_XCVR         0x00000010 /* Port 0 Transceiver select
-                                                      enable */
-#define IOC4_GPCR_DIR_SER1_XCVR         0x00000020 /* Port 1 Transceiver select
-                                                      enable */
-#define IOC4_GPCR_DIR_SER2_XCVR         0x00000040 /* Port 2 Transceiver select
-                                                      enable */
-#define IOC4_GPCR_DIR_SER3_XCVR         0x00000080 /* Port 3 Transceiver select
-                                                      enable */
-
-/* Defs for some of the generic I/O pins */
-#define IOC4_GPCR_UART0_MODESEL	              0x10 /* Pin is output to port 0
-                                                      mode sel */
-#define IOC4_GPCR_UART1_MODESEL	              0x20 /* Pin is output to port 1
-                                                      mode sel */
-#define IOC4_GPCR_UART2_MODESEL	              0x40 /* Pin is output to port 2
-                                                      mode sel */
-#define IOC4_GPCR_UART3_MODESEL	              0x80 /* Pin is output to port 3
-                                                      mode sel */
-
-#define IOC4_GPPR_UART0_MODESEL_PIN	         4 /* GIO pin controlling
-                                                      uart 0 mode select */
-#define IOC4_GPPR_UART1_MODESEL_PIN	         5 /* GIO pin controlling
-                                                      uart 1 mode select */
-#define IOC4_GPPR_UART2_MODESEL_PIN	         6 /* GIO pin controlling
-                                                      uart 2 mode select */
-#define IOC4_GPPR_UART3_MODESEL_PIN	         7 /* GIO pin controlling
-                                                      uart 3 mode select */
-
-/* Bitmasks for IOC4_ATA_TIMING */
-#define IOC4_ATA_TIMING_ADR_SETUP	0x00000003 /* Clocks of addr set-up */
-#define IOC4_ATA_TIMING_PULSE_WIDTH	0x000001f8 /* Clocks of read or write
-                                                      pulse width */
-#define IOC4_ATA_TIMING_RECOVERY	0x0000fe00 /* Clocks before next read
-                                                      or write */
-#define IOC4_ATA_TIMING_USE_IORDY	0x00010000 /* PIO uses IORDY */
-
-/* Bitmasks for address list elements pointed to by IOC4_ATA_DMA_PTR_<L|H> */
-#define IOC4_ATA_ALE_DMA_ADDRESS        0xfffffffffffffffe
-
-/* Bitmasks for byte count list elements pointed to by IOC4_ATA_DMA_PTR_<L|H> */
-#define IOC4_ATA_BCLE_BYTE_COUNT        0x000000000000fffe
-#define IOC4_ATA_BCLE_LIST_END          0x0000000080000000
-
-/* Bitmasks for IOC4_ATA_BC_<DEV|MEM> */
-#define IOC4_ATA_BC_BYTE_CNT            0x0001fffe /* Byte count */
-
-/* Bitmasks for IOC4_ATA_DMA_CTRL */
-#define IOC4_ATA_DMA_CTRL_STRAT		0x00000001 /* 1 -> start DMA engine */
-#define IOC4_ATA_DMA_CTRL_STOP		0x00000002 /* 1 -> stop DMA engine */
-#define IOC4_ATA_DMA_CTRL_DIR		0x00000004 /* 1 -> ATA bus data copied
-                                                      to memory */
-#define IOC4_ATA_DMA_CTRL_ACTIVE	0x00000008 /* DMA channel is active */
-#define IOC4_ATA_DMA_CTRL_MEM_ERROR	0x00000010 /* DMA engine encountered 
-						      a PCI error */
-/* Bitmasks for IOC4_KM_CSR */
-#define IOC4_KM_CSR_K_WRT_PEND  0x00000001 /* Kbd port xmitting or resetting */
-#define IOC4_KM_CSR_M_WRT_PEND  0x00000002 /* Mouse port xmitting or resetting */
-#define IOC4_KM_CSR_K_LCB       0x00000004 /* Line Cntrl Bit for last KBD write */
-#define IOC4_KM_CSR_M_LCB       0x00000008 /* Same for mouse */
-#define IOC4_KM_CSR_K_DATA      0x00000010 /* State of kbd data line */
-#define IOC4_KM_CSR_K_CLK       0x00000020 /* State of kbd clock line */
-#define IOC4_KM_CSR_K_PULL_DATA 0x00000040 /* Pull kbd data line low */
-#define IOC4_KM_CSR_K_PULL_CLK  0x00000080 /* Pull kbd clock line low */
-#define IOC4_KM_CSR_M_DATA      0x00000100 /* State of mouse data line */
-#define IOC4_KM_CSR_M_CLK       0x00000200 /* State of mouse clock line */
-#define IOC4_KM_CSR_M_PULL_DATA 0x00000400 /* Pull mouse data line low */
-#define IOC4_KM_CSR_M_PULL_CLK  0x00000800 /* Pull mouse clock line low */
-#define IOC4_KM_CSR_EMM_MODE	0x00001000 /* Emulation mode */
-#define IOC4_KM_CSR_SIM_MODE	0x00002000 /* Clock X8 */
-#define IOC4_KM_CSR_K_SM_IDLE   0x00004000 /* Keyboard is idle */
-#define IOC4_KM_CSR_M_SM_IDLE   0x00008000 /* Mouse is idle */
-#define IOC4_KM_CSR_K_TO	0x00010000 /* Keyboard trying to send/receive */
-#define IOC4_KM_CSR_M_TO        0x00020000 /* Mouse trying to send/receive */
-#define IOC4_KM_CSR_K_TO_EN     0x00040000 /* KM_CSR_K_TO + KM_CSR_K_TO_EN =
-                                              cause SIO_IR to assert */
-#define IOC4_KM_CSR_M_TO_EN	0x00080000 /* KM_CSR_M_TO + KM_CSR_M_TO_EN =
-                                              cause SIO_IR to assert */
-#define IOC4_KM_CSR_K_CLAMP_ONE	0x00100000 /* Pull K_CLK low after rec. one char */
-#define IOC4_KM_CSR_M_CLAMP_ONE	0x00200000 /* Pull M_CLK low after rec. one char */
-#define IOC4_KM_CSR_K_CLAMP_THREE \
-                           	0x00400000 /* Pull K_CLK low after rec. three chars */
-#define IOC4_KM_CSR_M_CLAMP_THREE \
-                            	0x00800000 /* Pull M_CLK low after rec. three char */
-
-/* Bitmasks for IOC4_K_RD and IOC4_M_RD */
-#define IOC4_KM_RD_DATA_2       0x000000ff /* 3rd char recvd since last read */
-#define IOC4_KM_RD_DATA_2_SHIFT          0
-#define IOC4_KM_RD_DATA_1       0x0000ff00 /* 2nd char recvd since last read */
-#define IOC4_KM_RD_DATA_1_SHIFT          8
-#define IOC4_KM_RD_DATA_0	0x00ff0000 /* 1st char recvd since last read */
-#define IOC4_KM_RD_DATA_0_SHIFT         16
-#define IOC4_KM_RD_FRAME_ERR_2  0x01000000 /* Framing or parity error in byte 2 */
-#define IOC4_KM_RD_FRAME_ERR_1  0x02000000 /* Same for byte 1 */
-#define IOC4_KM_RD_FRAME_ERR_0  0x04000000 /* Same for byte 0 */
-
-#define IOC4_KM_RD_KBD_MSE      0x08000000 /* 0 if from kbd, 1 if from mouse */
-#define IOC4_KM_RD_OFLO	        0x10000000 /* 4th char recvd before this read */
-#define IOC4_KM_RD_VALID_2      0x20000000 /* DATA_2 valid */
-#define IOC4_KM_RD_VALID_1      0x40000000 /* DATA_1 valid */
-#define IOC4_KM_RD_VALID_0      0x80000000 /* DATA_0 valid */
-#define IOC4_KM_RD_VALID_ALL    (IOC4_KM_RD_VALID_0 | IOC4_KM_RD_VALID_1 | \
-                                 IOC4_KM_RD_VALID_2)
-
-/* Bitmasks for IOC4_K_WD & IOC4_M_WD */
-#define IOC4_KM_WD_WRT_DATA     0x000000ff /* Write to keyboard/mouse port */
-#define IOC4_KM_WD_WRT_DATA_SHIFT        0
-
-/* Bitmasks for serial RX status byte */
-#define IOC4_RXSB_OVERRUN       0x01       /* Char(s) lost */
-#define IOC4_RXSB_PAR_ERR	0x02	   /* Parity error */
-#define IOC4_RXSB_FRAME_ERR	0x04	   /* Framing error */
-#define IOC4_RXSB_BREAK	        0x08	   /* Break character */
-#define IOC4_RXSB_CTS	        0x10	   /* State of CTS */
-#define IOC4_RXSB_DCD	        0x20	   /* State of DCD */
-#define IOC4_RXSB_MODEM_VALID   0x40	   /* DCD, CTS, and OVERRUN are valid */
-#define IOC4_RXSB_DATA_VALID    0x80	   /* Data byte, FRAME_ERR PAR_ERR & BREAK valid */
-
-/* Bitmasks for serial TX control byte */
-#define IOC4_TXCB_INT_WHEN_DONE 0x20       /* Interrupt after this byte is sent */
-#define IOC4_TXCB_INVALID	0x00	   /* Byte is invalid */
-#define IOC4_TXCB_VALID	        0x40	   /* Byte is valid */
-#define IOC4_TXCB_MCR	        0x80	   /* Data<7:0> to modem control register */
-#define IOC4_TXCB_DELAY	        0xc0	   /* Delay data<7:0> mSec */
-
-/* Bitmasks for IOC4_SBBR_L */
-#define IOC4_SBBR_L_SIZE	0x00000001 /* 0 == 1KB rings, 1 == 4KB rings */
-#define IOC4_SBBR_L_BASE	0xfffff000 /* Lower serial ring base addr */
-
-/* Bitmasks for IOC4_SSCR_<3:0> */
-#define IOC4_SSCR_RX_THRESHOLD  0x000001ff /* Hiwater mark */
-#define IOC4_SSCR_TX_TIMER_BUSY 0x00010000 /* TX timer in progress */
-#define IOC4_SSCR_HFC_EN	0x00020000 /* Hardware flow control enabled */
-#define IOC4_SSCR_RX_RING_DCD   0x00040000 /* Post RX record on delta-DCD */
-#define IOC4_SSCR_RX_RING_CTS   0x00080000 /* Post RX record on delta-CTS */
-#define IOC4_SSCR_DIAG	        0x00200000 /* Bypass clock divider for sim */
-#define IOC4_SSCR_RX_DRAIN	0x08000000 /* Drain RX buffer to memory */
-#define IOC4_SSCR_DMA_EN	0x10000000 /* Enable ring buffer DMA */
-#define IOC4_SSCR_DMA_PAUSE	0x20000000 /* Pause DMA */
-#define IOC4_SSCR_PAUSE_STATE   0x40000000 /* Sets when PAUSE takes effect */
-#define IOC4_SSCR_RESET	        0x80000000 /* Reset DMA channels */
-
-/* All producer/comsumer pointers are the same bitfield */
-#define IOC4_PROD_CONS_PTR_4K   0x00000ff8 /* For 4K buffers */
-#define IOC4_PROD_CONS_PTR_1K   0x000003f8 /* For 1K buffers */
-#define IOC4_PROD_CONS_PTR_OFF           3
-
-/* Bitmasks for IOC4_STPIR_<3:0> */
-/* Reserved for future register definitions */
-
-/* Bitmasks for IOC4_STCIR_<3:0> */
-#define IOC4_STCIR_BYTE_CNT     0x0f000000 /* Bytes in unpacker */
-#define IOC4_STCIR_BYTE_CNT_SHIFT       24
-
-/* Bitmasks for IOC4_SRPIR_<3:0> */
-#define IOC4_SRPIR_BYTE_CNT	0x0f000000 /* Bytes in packer */
-#define IOC4_SRPIR_BYTE_CNT_SHIFT       24
-
-/* Bitmasks for IOC4_SRCIR_<3:0> */
-#define IOC4_SRCIR_ARM	        0x80000000 /* Arm RX timer */
-
-/* Bitmasks for IOC4_SHADOW_<3:0> */
-#define IOC4_SHADOW_DR          0x00000001  /* Data ready */
-#define IOC4_SHADOW_OE          0x00000002  /* Overrun error */
-#define IOC4_SHADOW_PE          0x00000004  /* Parity error */
-#define IOC4_SHADOW_FE          0x00000008  /* Framing error */
-#define IOC4_SHADOW_BI          0x00000010  /* Break interrupt */
-#define IOC4_SHADOW_THRE        0x00000020  /* Xmit holding register empty */
-#define IOC4_SHADOW_TEMT        0x00000040  /* Xmit shift register empty */
-#define IOC4_SHADOW_RFCE        0x00000080  /* Char in RX fifo has an error */
-#define IOC4_SHADOW_DCTS        0x00010000  /* Delta clear to send */
-#define IOC4_SHADOW_DDCD        0x00080000  /* Delta data carrier detect */
-#define IOC4_SHADOW_CTS         0x00100000  /* Clear to send */
-#define IOC4_SHADOW_DCD         0x00800000  /* Data carrier detect */
-#define IOC4_SHADOW_DTR         0x01000000  /* Data terminal ready */
-#define IOC4_SHADOW_RTS         0x02000000  /* Request to send */
-#define IOC4_SHADOW_OUT1        0x04000000  /* 16550 OUT1 bit */
-#define IOC4_SHADOW_OUT2        0x08000000  /* 16550 OUT2 bit */
-#define IOC4_SHADOW_LOOP        0x10000000  /* Loopback enabled */
-
-/* Bitmasks for IOC4_SRTR_<3:0> */
-#define IOC4_SRTR_CNT	        0x00000fff /* Reload value for RX timer */
-#define IOC4_SRTR_CNT_VAL	0x0fff0000 /* Current value of RX timer */
-#define IOC4_SRTR_CNT_VAL_SHIFT         16
-#define IOC4_SRTR_HZ                 16000 /* SRTR clock frequency */
-
-/* Serial port register map used for DMA and PIO serial I/O */
-typedef volatile struct ioc4_serialregs {
-    ioc4reg_t		    sscr;
-    ioc4reg_t		    stpir;
-    ioc4reg_t		    stcir;
-    ioc4reg_t		    srpir;
-    ioc4reg_t		    srcir;
-    ioc4reg_t		    srtr;
-    ioc4reg_t		    shadow;
-} ioc4_sregs_t;
-
-/* IOC4 UART register map */
-typedef volatile struct ioc4_uartregs {
-    union {
-        char                    rbr;    /* read only, DLAB == 0 */
-        char                    thr;    /* write only, DLAB == 0 */
-        char                    dll;    /* DLAB == 1 */
-    } u1;
-    union {
-        char                    ier;    /* DLAB == 0 */
-        char                    dlm;    /* DLAB == 1 */
-    } u2;
-    union {
-        char                    iir;    /* read only */
-        char                    fcr;    /* write only */
-    } u3;
-    char                    i4u_lcr;
-    char                    i4u_mcr;
-    char                    i4u_lsr;
-    char                    i4u_msr;
-    char                    i4u_scr;
-} ioc4_uart_t;
-
-#define i4u_rbr u1.rbr
-#define i4u_thr u1.thr
-#define i4u_dll u1.dll
-#define i4u_ier u2.ier
-#define i4u_dlm u2.dlm
-#define i4u_iir u3.iir
-#define i4u_fcr u3.fcr
-
-/* PCI config space register map */
-typedef volatile struct ioc4_configregs {
-    ioc4reg_t		    pci_id;
-    ioc4reg_t		    pci_scr;
-    ioc4reg_t		    pci_rev;
-    ioc4reg_t		    pci_lat;
-    ioc4reg_t		    pci_bar0;
-    ioc4reg_t		    pci_bar1;
-    ioc4reg_t               pci_bar2_not_implemented;
-    ioc4reg_t               pci_cis_ptr_not_implemented;
-    ioc4reg_t		    pci_sidv;
-    ioc4reg_t		    pci_rom_bar_not_implemented;
-    ioc4reg_t		    pci_cap;
-    ioc4reg_t		    pci_rsv;
-    ioc4reg_t		    pci_latgntint;
-
-    char                    pci_fill1[0x58 - 0x3c - 4];
-
-    ioc4reg_t               pci_pcix;
-    ioc4reg_t               pci_pcixstatus;
-} ioc4_cfg_t;
-
-/* PCI memory space register map addressed using pci_bar0 */
-typedef volatile struct ioc4_memregs {
-
-    /* Miscellaneous IOC4  registers */
-    ioc4reg_t		    pci_err_addr_l;
-    ioc4reg_t		    pci_err_addr_h;
-    ioc4reg_t		    sio_ir;
-    ioc4reg_t		    other_ir;
-
-    /* These registers are read-only for general kernel code.  To
-     * modify them use the functions in ioc4.c.
-     */
-    ioc4reg_t		    sio_ies_ro;
-    ioc4reg_t		    other_ies_ro;
-    ioc4reg_t		    sio_iec_ro;
-    ioc4reg_t		    other_iec_ro;
-    ioc4reg_t		    sio_cr;
-    ioc4reg_t		    misc_fill1;
-    ioc4reg_t		    int_out;
-    ioc4reg_t		    misc_fill2;
-    ioc4reg_t		    gpcr_s;
-    ioc4reg_t		    gpcr_c;
-    ioc4reg_t		    gpdr;
-    ioc4reg_t		    misc_fill3;
-    ioc4reg_t		    gppr_0;
-    ioc4reg_t		    gppr_1;
-    ioc4reg_t		    gppr_2;
-    ioc4reg_t		    gppr_3;
-    ioc4reg_t		    gppr_4;
-    ioc4reg_t		    gppr_5;
-    ioc4reg_t		    gppr_6;
-    ioc4reg_t		    gppr_7;
-
-    char		    misc_fill4[0x100 - 0x5C - 4];
-
-    /* ATA/ATAP registers */
-    ioc4reg_t		    ata_0;
-    ioc4reg_t		    ata_1;
-    ioc4reg_t		    ata_2;
-    ioc4reg_t		    ata_3;
-    ioc4reg_t		    ata_4;
-    ioc4reg_t		    ata_5;
-    ioc4reg_t		    ata_6;
-    ioc4reg_t		    ata_7;
-    ioc4reg_t		    ata_aux;
-
-    char		    ata_fill1[0x140 - 0x120 - 4];
-
-    ioc4reg_t		    ata_timing;
-    ioc4reg_t		    ata_dma_ptr_l;
-    ioc4reg_t		    ata_dma_ptr_h;
-    ioc4reg_t		    ata_dma_addr_l;
-    ioc4reg_t		    ata_dma_addr_h;
-    ioc4reg_t		    ata_bc_dev;
-    ioc4reg_t		    ata_bc_mem;
-    ioc4reg_t		    ata_dma_ctrl;
-
-    char		    ata_fill2[0x200 - 0x15C - 4];
-
-    /* Keyboard and mouse registers */
-    ioc4reg_t		    km_csr;
-    ioc4reg_t		    k_rd;
-    ioc4reg_t		    m_rd;
-    ioc4reg_t		    k_wd;
-    ioc4reg_t		    m_wd;
-
-    char		    km_fill1[0x300 - 0x210 - 4];
-
-    /* Serial port registers used for DMA serial I/O */
-    ioc4reg_t		    sbbr01_l;
-    ioc4reg_t		    sbbr01_h;
-    ioc4reg_t		    sbbr23_l;
-    ioc4reg_t		    sbbr23_h;
-
-    ioc4_sregs_t	    port_0;
-    ioc4_sregs_t	    port_1;
-    ioc4_sregs_t	    port_2;
-    ioc4_sregs_t	    port_3;
-
-    ioc4_uart_t		    uart_0;
-    ioc4_uart_t		    uart_1;
-    ioc4_uart_t		    uart_2;
-    ioc4_uart_t		    uart_3;
-} ioc4_mem_t;
-
-#endif	/* 0 */
-
 /*
  * Bytebus device space
  */
@@ -693,88 +17,4 @@ typedef volatile struct ioc4_memregs {
 #define IOC4_BYTEBUS_DEV2	0xC0000L  /* Addressed using pci_bar0 */
 #define IOC4_BYTEBUS_DEV3	0xE0000L  /* Addressed using pci_bar0 */
 
-#if 0
-/* UART clock speed */
-#define IOC4_SER_XIN_CLK        66000000
-
-typedef enum ioc4_subdevs_e {
-    ioc4_subdev_generic,
-    ioc4_subdev_kbms,
-    ioc4_subdev_tty0,
-    ioc4_subdev_tty1,
-    ioc4_subdev_tty2,
-    ioc4_subdev_tty3,
-    ioc4_subdev_rt,
-    ioc4_nsubdevs
-} ioc4_subdev_t;
-
-/* Subdevice disable bits,
- * from the standard INFO_LBL_SUBDEVS
- */
-#define IOC4_SDB_TTY0		(1 << ioc4_subdev_tty0)
-#define IOC4_SDB_TTY1		(1 << ioc4_subdev_tty1)
-#define IOC4_SDB_TTY2		(1 << ioc4_subdev_tty2)
-#define IOC4_SDB_TTY3		(1 << ioc4_subdev_tty3)
-#define IOC4_SDB_KBMS		(1 << ioc4_subdev_kbms)
-#define IOC4_SDB_RT		(1 << ioc4_subdev_rt)
-#define IOC4_SDB_GENERIC	(1 << ioc4_subdev_generic)
-
-#define IOC4_ALL_SUBDEVS	((1 << ioc4_nsubdevs) - 1)
-
-#define IOC4_SDB_SERIAL		(IOC4_SDB_TTY0 | IOC4_SDB_TTY1 | IOC4_SDB_TTY2 | IOC4_SDB_TTY3)
-
-#define IOC4_STD_SUBDEVS	IOC4_ALL_SUBDEVS
-
-#define IOC4_INTA_SUBDEVS	(IOC4_SDB_SERIAL | IOC4_SDB_KBMS | IOC4_SDB_RT | IOC4_SDB_GENERIC)
-
-extern int		ioc4_subdev_enabled(vertex_hdl_t, ioc4_subdev_t);
-extern void		ioc4_subdev_enables(vertex_hdl_t, ulong_t);
-extern void		ioc4_subdev_enable(vertex_hdl_t, ioc4_subdev_t);
-extern void		ioc4_subdev_disable(vertex_hdl_t, ioc4_subdev_t);
-
-/* Macros to read and write the SIO_IEC and SIO_IES registers (see the
- * comments in ioc4.c for details on why this is necessary
- */
-#define IOC4_W_IES	0
-#define IOC4_W_IEC	1
-extern void		ioc4_write_ireg(void *, ioc4reg_t, int, ioc4_intr_type_t);
-
-#define IOC4_WRITE_IES(ioc4, val, type)	ioc4_write_ireg(ioc4, val, IOC4_W_IES, type)
-#define IOC4_WRITE_IEC(ioc4, val, type)	ioc4_write_ireg(ioc4, val, IOC4_W_IEC, type)
-
-typedef void
-ioc4_intr_func_f	(intr_arg_t, ioc4reg_t);
-
-typedef void
-ioc4_intr_connect_f	(vertex_hdl_t conn_vhdl,
-			 ioc4_intr_type_t,
-			 ioc4reg_t,
-			 ioc4_intr_func_f *,
-			 intr_arg_t info,
-			 vertex_hdl_t owner_vhdl,
-			 vertex_hdl_t intr_dev_vhdl,
-			 int (*)(intr_arg_t));
-
-typedef void
-ioc4_intr_disconnect_f	(vertex_hdl_t conn_vhdl,
-			 ioc4_intr_type_t,
-			 ioc4reg_t,
-			 ioc4_intr_func_f *,
-			 intr_arg_t info,
-			 vertex_hdl_t owner_vhdl);
-
-ioc4_intr_disconnect_f	ioc4_intr_disconnect;
-ioc4_intr_connect_f	ioc4_intr_connect;
-
-extern int		ioc4_is_console(vertex_hdl_t conn_vhdl);
-
-extern void		ioc4_mlreset(ioc4_cfg_t *, ioc4_mem_t *);
-
-extern intr_func_f	ioc4_intr;
-
-extern ioc4_mem_t      *ioc4_mem_ptr(void *ioc4_fastinfo);
-
-typedef ioc4_intr_func_f *ioc4_intr_func_t;
-
-#endif	/* 0 */
-#endif				/* _ASM_IA64_SN_IOC4_H */
+#endif	/* _ASM_IA64_SN_IOC4_H */
--- diff/include/asm-ia64/sn/ioconfig_bus.h	2004-02-09 10:36:12.000000000 +0000
+++ source/include/asm-ia64/sn/ioconfig_bus.h	2004-02-23 13:56:47.000000000 +0000
@@ -9,19 +9,19 @@
 #ifndef _ASM_IA64_SN_IOCONFIG_BUS_H
 #define _ASM_IA64_SN_IOCONFIG_BUS_H
 
-#define IOCONFIG_PCIBUS "/boot/efi/ioconfig_pcibus"
-#define POUND_CHAR                   '#'
+#define IOCONFIG_PCIBUS	"/boot/efi/ioconfig_pcibus"
+#define POUND_CHAR	'#'
 #define MAX_LINE_LEN	128
 #define MAXPATHLEN	128
 
 struct ioconfig_parm {
 	unsigned long ioconfig_activated;
-        unsigned long number;
-        void *buffer;
+	unsigned long number;
+	void *buffer;
 };
 
-struct  ascii_moduleid{
-                unsigned char   io_moduleid[8]; /* pci path name */
+struct ascii_moduleid {
+	unsigned char   io_moduleid[8]; /* pci path name */
 };
 
 #endif	/* _ASM_IA64_SN_IOCONFIG_BUS_H */
--- diff/include/asm-ia64/sn/ioerror_handling.h	2004-02-09 10:36:12.000000000 +0000
+++ source/include/asm-ia64/sn/ioerror_handling.h	2004-02-23 13:56:47.000000000 +0000
@@ -11,7 +11,7 @@
 #include <linux/types.h>
 #include <asm/sn/sgi.h>
 
-#if __KERNEL__
+#ifdef __KERNEL__
 
 /*
  * Basic types required for io error handling interfaces.
@@ -155,88 +155,5 @@ enum error_class_e {
 	ERROR_CLASS_BAD_RESP_PKT
 };
 
-typedef uint64_t  error_class_t;
-
-
-/* 
- * Error context which the error action can use.
- */
-typedef void			*error_context_t;
-#define ERROR_CONTEXT_IGNORE	((error_context_t)-1ll)
-
-
-/* 
- * Error action type.
- */
-typedef error_return_code_t 	(*error_action_f)( error_context_t);
-#define ERROR_ACTION_IGNORE	((error_action_f)-1ll)
-
-/* Typical set of error actions */
-typedef struct error_action_set_s {
-	error_action_f		eas_panic;
-	error_action_f		eas_shutdown;
-	error_action_f		eas_abort;
-	error_action_f		eas_retry;
-	error_action_f		eas_failover;
-	error_action_f		eas_log_n_ignore;
-	error_action_f		eas_reset;
-} error_action_set_t;
-
-
-/* Set of priorites for in case mutliple error actions/states
- * are trying to be prescribed for a device.
- * NOTE : The ordering below encapsulates the priorities. Highest value
- * corresponds to highest priority.
- */
-enum error_priority_e {
-	ERROR_PRIORITY_IGNORE,
-	ERROR_PRIORITY_NONE,
-	ERROR_PRIORITY_NORMAL,
-	ERROR_PRIORITY_LOG,
-	ERROR_PRIORITY_FAILOVER,
-	ERROR_PRIORITY_RETRY,
-	ERROR_PRIORITY_ABORT,
-	ERROR_PRIORITY_SHUTDOWN,
-	ERROR_PRIORITY_RESTART,
-	ERROR_PRIORITY_PANIC
-};
-
-typedef uint64_t  error_priority_t;
-
-/* Error action interfaces */
-
-extern error_return_code_t	error_action_set(vertex_hdl_t,
-						 error_action_f,
-						 error_context_t,
-						 error_priority_t);
-extern error_return_code_t	error_action_perform(vertex_hdl_t);
-
-
-#define INFO_LBL_ERROR_SKIP_ENV	"error_skip_env"
-
-#define v_error_skip_env_get(v, l)		\
-hwgraph_info_get_LBL(v, INFO_LBL_ERROR_SKIP_ENV, (arbitrary_info_t *)&l)
-
-#define v_error_skip_env_set(v, l, r)		\
-(r ? 						\
- hwgraph_info_replace_LBL(v, INFO_LBL_ERROR_SKIP_ENV, (arbitrary_info_t)l,0) :\
- hwgraph_info_add_LBL(v, INFO_LBL_ERROR_SKIP_ENV, (arbitrary_info_t)l))
-
-#define v_error_skip_env_clear(v)		\
-hwgraph_info_remove_LBL(v, INFO_LBL_ERROR_SKIP_ENV, 0)
-
-typedef uint64_t		counter_t;
-
-extern counter_t		error_retry_count_get(vertex_hdl_t);
-extern error_return_code_t	error_retry_count_set(vertex_hdl_t,counter_t);
-extern counter_t		error_retry_count_increment(vertex_hdl_t);
-extern counter_t		error_retry_count_decrement(vertex_hdl_t);
-
-/* Except for the PIO Read error typically the other errors are handled in
- * the context of an asynchronous error interrupt.
- */
-#define	IS_ERROR_INTR_CONTEXT(_ec)	((_ec & IOECODE_DMA) 		|| \
-					 (_ec == IOECODE_PIO_WRITE))
-
 #endif /* __KERNEL__ */
 #endif /* _ASM_IA64_SN_IOERROR_HANDLING_H */
--- diff/include/asm-ia64/sn/iograph.h	2004-02-18 08:54:12.000000000 +0000
+++ source/include/asm-ia64/sn/iograph.h	2004-02-23 13:56:47.000000000 +0000
@@ -8,6 +8,8 @@
 #ifndef _ASM_IA64_SN_IOGRAPH_H
 #define _ASM_IA64_SN_IOGRAPH_H
 
+#include <asm/sn/xtalk/xbow.h>	/* For get MAX_PORT_NUM */
+
 /*
  * During initialization, platform-dependent kernel code establishes some
  * basic elements of the hardware graph.  This file contains edge and
@@ -115,40 +117,13 @@
 #define INFO_LBL_XSWITCH_VOL		"_xswitch_volunteer"
 #define INFO_LBL_XFUNCS			"_xtalk_ops"	/* ops vector for gio providers */
 #define INFO_LBL_XWIDGET		"_xwidget"
-/* Device/Driver  Admin directive labels  */
-#define ADMIN_LBL_INTR_TARGET		"INTR_TARGET"	/* Target cpu for device interrupts*/
-#define ADMIN_LBL_INTR_SWLEVEL		"INTR_SWLEVEL"	/* Priority level of the ithread */
-
-#define	ADMIN_LBL_DMATRANS_NODE		"PCIBUS_DMATRANS_NODE" /* Node used for
-								* 32-bit Direct
-								* Mapping I/O
-								*/
-#define ADMIN_LBL_DISABLED		"DISABLE"	/* Device has been disabled */
-#define ADMIN_LBL_DETACH		"DETACH"	/* Device has been detached */
-
-#define ADMIN_LBL_THREAD_PRI		"thread_priority" 
-							/* Driver adminstrator
-							 * hint parameter for 
-							 * thread priority
-							 */
-#define ADMIN_LBL_THREAD_CLASS		"thread_class" 
-							/* Driver adminstrator
-							 * hint parameter for 
-							 * thread priority
-							 * default class
-							 */
-/* Info labels that begin with '_' cannot be overwritten by an attr_set call */
-#define INFO_LBL_RESERVED(name) ((name)[0] == '_')
 
-#if defined(__KERNEL__)
+
+#ifdef __KERNEL__
 void init_all_devices(void);
 #endif /* __KERNEL__ */
 
-#include <asm/sn/sgi.h>
-#include <asm/sn/xtalk/xbow.h>	/* For get MAX_PORT_NUM */
-
 int io_brick_map_widget(int, int);
-int io_path_map_widget(vertex_hdl_t);
 
 /*
  * Map a brick's widget number to a meaningful int
@@ -159,5 +134,4 @@ struct io_brick_map_s {
     int                 ibm_map_wid[MAX_PORT_NUM]; /* wid to int map */
 };
 
-
 #endif /* _ASM_IA64_SN_IOGRAPH_H */
--- diff/include/asm-ia64/sn/leds.h	2003-06-30 10:07:34.000000000 +0100
+++ source/include/asm-ia64/sn/leds.h	2004-02-23 13:56:47.000000000 +0000
@@ -8,10 +8,7 @@
  * Copyright (C) 2000-2003 Silicon Graphics, Inc. All rights reserved.
  */
 
-#include <linux/config.h>
-#include <asm/smp.h>
 #include <asm/sn/addrs.h>
-#include <asm/sn/sn_cpuid.h>
 #include <asm/sn/pda.h>
 #include <asm/sn/sn2/shub.h>
 
@@ -23,7 +20,7 @@
 #define LED_ALWAYS_SET		0x00
 
 /*
- * Basic macros for flashing the LEDS on an SGI, SN1.
+ * Basic macros for flashing the LEDS on an SGI SN.
  */
 
 static __inline__ void
--- diff/include/asm-ia64/sn/module.h	2004-02-18 08:54:12.000000000 +0000
+++ source/include/asm-ia64/sn/module.h	2004-02-23 13:56:47.000000000 +0000
@@ -8,12 +8,6 @@
 #ifndef _ASM_IA64_SN_MODULE_H
 #define _ASM_IA64_SN_MODULE_H
 
-#ifdef	__cplusplus
-extern "C" {
-#endif
-
-
-#include <asm/semaphore.h>
 #include <asm/sn/klconfig.h>
 #include <asm/sn/ksys/elsc.h>
 
--- diff/include/asm-ia64/sn/pci/pci_bus_cvlink.h	2004-02-18 08:54:12.000000000 +0000
+++ source/include/asm-ia64/sn/pci/pci_bus_cvlink.h	2004-02-23 13:56:47.000000000 +0000
@@ -31,22 +31,26 @@
 #define MAX_PCI_XWIDGET 256
 #define MAX_ATE_MAPS 1024
 
+#define SN_DEVICE_SYSDATA(dev) \
+	((struct sn_device_sysdata *) \
+	(((struct pci_controller *) ((dev)->sysdata))->platform_data))
+
 #define IS_PCI32G(dev)	((dev)->dma_mask >= 0xffffffff)
 #define IS_PCI32L(dev)	((dev)->dma_mask < 0xffffffff)
 
 #define PCIDEV_VERTEX(pci_dev) \
-	(((struct sn_device_sysdata *)((pci_dev)->sysdata))->vhdl)
-
-#define PCIBUS_VERTEX(pci_bus) \
-	(((struct sn_widget_sysdata *)((pci_bus)->sysdata))->vhdl)
+	((SN_DEVICE_SYSDATA(pci_dev))->vhdl)
 
 struct sn_widget_sysdata {
         vertex_hdl_t  vhdl;
 };
 
 struct sn_device_sysdata {
-        vertex_hdl_t  vhdl;
+        vertex_hdl_t		vhdl;
 	pciio_provider_t	*pci_provider;
+	pciio_intr_t		intr_handle;
+	struct sn_flush_device_list *dma_flush_list;
+        pciio_piomap_t		pio_map[PCI_ROM_RESOURCE];
 };
 
 struct ioports_to_tlbs_s {
--- diff/include/asm-ia64/sn/sgi.h	2004-02-18 08:54:12.000000000 +0000
+++ source/include/asm-ia64/sn/sgi.h	2004-02-23 13:56:47.000000000 +0000
@@ -13,7 +13,6 @@
 #include <linux/config.h>
 
 #include <asm/sn/types.h>
-#include <asm/uaccess.h>		/* for copy_??_user */
 #include <asm/sn/hwgfs.h>
 
 typedef hwgfs_handle_t vertex_hdl_t;
--- diff/include/asm-ia64/sn/sn2/sn_private.h	2004-02-18 08:54:12.000000000 +0000
+++ source/include/asm-ia64/sn/sn2/sn_private.h	2004-02-23 13:56:47.000000000 +0000
@@ -11,6 +11,7 @@
 #include <linux/wait.h>
 #include <asm/sn/nodepda.h>
 #include <asm/sn/io.h>
+#include <asm/sn/iograph.h>
 #include <asm/sn/xtalk/xwidget.h>
 #include <asm/sn/xtalk/xtalk_private.h>
 
--- diff/include/asm-ia64/spinlock.h	2004-01-19 10:22:59.000000000 +0000
+++ source/include/asm-ia64/spinlock.h	2004-02-23 13:56:47.000000000 +0000
@@ -110,8 +110,18 @@ do {											\
 typedef struct {
 	volatile int read_counter	: 31;
 	volatile int write_lock		:  1;
+#ifdef CONFIG_LOCKMETER
+	/* required for LOCKMETER since all bits in lock are used */
+	/* and we need this storage for CPU and lock INDEX        */
+	unsigned lockmeter_magic;
+#endif
 } rwlock_t;
+
+#ifdef CONFIG_LOCKMETER
+#define RW_LOCK_UNLOCKED (rwlock_t) { 0, 0, 0 }
+#else
 #define RW_LOCK_UNLOCKED (rwlock_t) { 0, 0 }
+#endif
 
 #define rwlock_init(x)		do { *(x) = RW_LOCK_UNLOCKED; } while(0)
 #define rwlock_is_locked(x)	(*(volatile int *) (x) != 0)
@@ -127,6 +137,48 @@ do {											\
 	}										\
 } while (0)
 
+#ifdef CONFIG_LOCKMETER
+/*
+ * HACK: This works, but still have a timing window that affects performance:
+ * we see that no one owns the Write lock, then someone * else grabs for Write
+ * lock before we do a read_lock().
+ * This means that on rare occasions our read_lock() will stall and spin-wait
+ * until we acquire for Read, instead of simply returning a trylock failure.
+ */
+static inline int _raw_read_trylock(rwlock_t *rw)
+{
+	if (rw->write_lock) {
+		return 0;
+	} else {
+		_raw_read_lock(rw);
+		return 1;
+	}
+}
+
+static inline int _raw_write_trylock(rwlock_t *rw)
+{
+	if (!(rw->write_lock)) {
+	    /* isn't currently write-locked... that looks promising... */
+	    if (test_and_set_bit(31, rw) == 0) {
+		/* now it is write-locked by me... */
+		if (rw->read_counter) {
+		    /* really read-locked, so release write-lock and fail */
+		    clear_bit(31, rw);
+		} else {
+		    /* we've the the write-lock, no read-lockers... success! */
+		    barrier();
+		    return 1;
+		}
+
+	    }
+	}
+
+	/* falls through ... fails to write-lock */
+	barrier();
+	return 0;
+}
+#endif
+
 #define _raw_read_unlock(rw)					\
 do {								\
 	rwlock_t *__read_lock_ptr = (rw);			\
@@ -190,4 +242,25 @@ do {										\
 	clear_bit(31, (x));								\
 })
 
+#ifdef CONFIG_LOCKMETER
+extern void _metered_spin_lock  (spinlock_t *lock);
+extern void _metered_spin_unlock(spinlock_t *lock);
+
+/*
+ *  Use a less efficient, and inline, atomic_dec_and_lock() if lockmetering
+ *  so we can see the callerPC of who is actually doing the spin_lock().
+ *  Otherwise, all we see is the generic rollup of all locks done by
+ *  atomic_dec_and_lock().
+ */
+static inline int atomic_dec_and_lock(atomic_t *atomic, spinlock_t *lock)
+{
+	_metered_spin_lock(lock);
+	if (atomic_dec_and_test(atomic))
+		return 1;
+	_metered_spin_unlock(lock);
+	return 0;
+}
+#define ATOMIC_DEC_AND_LOCK
+#endif
+
 #endif /*  _ASM_IA64_SPINLOCK_H */
--- diff/include/asm-ia64/tlb.h	2004-02-09 10:36:12.000000000 +0000
+++ source/include/asm-ia64/tlb.h	2004-02-23 13:56:47.000000000 +0000
@@ -41,6 +41,7 @@
 #include <linux/mm.h>
 #include <linux/swap.h>
 
+#include <asm/pgalloc.h>
 #include <asm/processor.h>
 #include <asm/tlbflush.h>
 
@@ -173,6 +174,12 @@ tlb_finish_mmu (struct mmu_gather *tlb, 
 	check_pgt_cache();
 }
 
+static inline unsigned int
+tlb_is_full_mm(struct mmu_gather *tlb)
+{
+     return tlb->fullmm;
+}
+
 /*
  * Logically, this routine frees PAGE.  On MP machines, the actual freeing of the page
  * must be delayed until after the TLB has been flushed (see comments at the beginning of
@@ -204,6 +211,8 @@ __tlb_remove_tlb_entry (struct mmu_gathe
 	tlb->end_addr = address + PAGE_SIZE;
 }
 
+#define tlb_migrate_prepare(mm) flush_tlb_mm(mm)
+
 #define tlb_start_vma(tlb, vma)			do { } while (0)
 #define tlb_end_vma(tlb, vma)			do { } while (0)
 
--- diff/include/asm-ia64/unistd.h	2003-10-27 09:20:39.000000000 +0000
+++ source/include/asm-ia64/unistd.h	2004-02-23 13:56:47.000000000 +0000
@@ -255,6 +255,9 @@
 
 #if !defined(__ASSEMBLY__) && !defined(ASSEMBLER)
 
+#include <linux/types.h>
+#include <linux/linkage.h>
+
 extern long __ia64_syscall (long a0, long a1, long a2, long a3, long a4, long nr);
 
 #ifdef __KERNEL_SYSCALLS__
@@ -263,39 +266,35 @@ extern long __ia64_syscall (long a0, lon
 #include <linux/signal.h>
 #include <asm/ptrace.h>
 #include <linux/stringify.h>
+#include <linux/syscalls.h>
 
 static inline long
 open (const char * name, int mode, int flags)
 {
-	extern long sys_open (const char *, int, int);
 	return sys_open(name, mode, flags);
 }
 
 static inline long
 dup (int fd)
 {
-	extern long sys_dup (int);
 	return sys_dup(fd);
 }
 
 static inline long
 close (int fd)
 {
-	extern long sys_close(unsigned int);
 	return sys_close(fd);
 }
 
 static inline off_t
 lseek (int fd, off_t off, int whence)
 {
-	extern off_t sys_lseek (int, off_t, int);
 	return sys_lseek(fd, off, whence);
 }
 
 static inline long
 _exit (int value)
 {
-	extern long sys_exit (int);
 	return sys_exit(value);
 }
 
@@ -304,14 +303,12 @@ _exit (int value)
 static inline long
 write (int fd, const char * buf, size_t nr)
 {
-	extern long sys_write (int, const char *, size_t);
 	return sys_write(fd, buf, nr);
 }
 
 static inline long
 read (int fd, char * buf, size_t nr)
 {
-	extern long sys_read (int, char *, size_t);
 	return sys_read(fd, buf, nr);
 }
 
@@ -319,17 +316,12 @@ read (int fd, char * buf, size_t nr)
 static inline long
 setsid (void)
 {
-	extern long sys_setsid (void);
 	return sys_setsid();
 }
 
-struct rusage;
-
 static inline pid_t
 waitpid (int pid, int * wait_stat, int flags)
 {
-	extern asmlinkage long sys_wait4 (pid_t, unsigned int *, int, struct rusage *);
-
 	return sys_wait4(pid, wait_stat, flags, NULL);
 }
 
@@ -339,6 +331,23 @@ extern pid_t clone (unsigned long flags,
 
 #endif /* __KERNEL_SYSCALLS__ */
 
+asmlinkage unsigned long sys_mmap(
+				unsigned long addr, unsigned long len,
+				int prot, int flags,
+				int fd, long off);
+asmlinkage unsigned long sys_mmap2(
+				unsigned long addr, unsigned long len,
+				int prot, int flags,
+				int fd, long pgoff);
+struct pt_regs;
+asmlinkage long sys_execve(char *filename, char **argv, char **envp,
+				struct pt_regs *regs);
+asmlinkage long sys_pipe(long arg0, long arg1, long arg2, long arg3,
+			long arg4, long arg5, long arg6, long arg7, long stack);
+asmlinkage long sys_ptrace(long request, pid_t pid,
+			unsigned long addr, unsigned long data,
+			long arg4, long arg5, long arg6, long arg7, long stack);
+
 /*
  * "Conditional" syscalls
  *
--- diff/include/asm-m68k/atarihw.h	2002-10-16 04:26:42.000000000 +0100
+++ source/include/asm-m68k/atarihw.h	2004-02-23 13:56:47.000000000 +0000
@@ -376,7 +376,7 @@ struct MATRIX
   u_char external_frequency_divider;
   u_char internal_frequency_divider;
 };
-#define matrix (*(volatile struct MATRIX *)MATRIX_BASE)
+#define falcon_matrix (*(volatile struct MATRIX *)MATRIX_BASE)
 
 #define CODEC_BASE (0xffff8936)
 struct CODEC
@@ -405,7 +405,7 @@ struct CODEC
   u_char unused6;
   u_char gpio_data;
 };
-#define codec (*(volatile struct CODEC *)CODEC_BASE)
+#define falcon_codec (*(volatile struct CODEC *)CODEC_BASE)
 
 /*
 ** Falcon Blitter
--- diff/include/asm-m68k/dma-mapping.h	2003-08-20 14:16:14.000000000 +0100
+++ source/include/asm-m68k/dma-mapping.h	2004-02-23 13:56:47.000000000 +0000
@@ -5,6 +5,8 @@
 
 #ifdef CONFIG_PCI
 #include <asm-generic/dma-mapping.h>
+#else
+#include <asm-generic/dma-mapping-broken.h>
 #endif
 
 #endif  /* _M68K_DMA_MAPPING_H */
--- diff/include/asm-m68k/irq.h	2003-06-09 14:18:20.000000000 +0100
+++ source/include/asm-m68k/irq.h	2004-02-23 13:56:47.000000000 +0000
@@ -76,11 +76,6 @@ extern void (*disable_irq)(unsigned int)
 
 struct pt_regs;
 
-extern int sys_request_irq(unsigned int, 
-	irqreturn_t (*)(int, void *, struct pt_regs *), 
-	unsigned long, const char *, void *);
-extern void sys_free_irq(unsigned int, void *);
-
 /*
  * various flags for request_irq() - the Amiga now uses the standard
  * mechanism like all other architectures - SA_INTERRUPT and SA_SHIRQ
--- diff/include/asm-m68k/param.h	2002-10-16 04:28:24.000000000 +0100
+++ source/include/asm-m68k/param.h	2004-02-23 13:56:47.000000000 +0000
@@ -13,10 +13,6 @@
 
 #define EXEC_PAGESIZE	8192
 
-#ifndef NGROUPS
-#define NGROUPS		32
-#endif
-
 #ifndef NOGROUP
 #define NOGROUP		(-1)
 #endif
--- diff/include/asm-m68k/processor.h	2004-02-09 10:36:12.000000000 +0000
+++ source/include/asm-m68k/processor.h	2004-02-23 13:56:47.000000000 +0000
@@ -55,11 +55,6 @@ static inline void wrusp(unsigned long u
 #endif
 #define TASK_UNMAPPED_ALIGN(addr, off)	PAGE_ALIGN(addr)
 
-/*
- * Bus types
- */
-#define MCA_bus 0
-
 struct task_work {
 	unsigned char sigpending;
 	unsigned char notify_resume;	/* request for notification on
--- diff/include/asm-m68k/sbus.h	2004-02-09 10:36:12.000000000 +0000
+++ source/include/asm-m68k/sbus.h	2004-02-23 13:56:47.000000000 +0000
@@ -36,8 +36,15 @@ static inline void _sbus_writel(unsigned
 
 }
 
+extern inline unsigned long _sbus_readl(unsigned long addr)
+{
+	return *(volatile unsigned long *)addr;
+}
+
+
 #define sbus_readb(a) _sbus_readb((unsigned long)a)
 #define sbus_writeb(v, a) _sbus_writeb(v, (unsigned long)a)
+#define sbus_readl(a) _sbus_readl((unsigned long)a)
 #define sbus_writel(v, a) _sbus_writel(v, (unsigned long)a)
 
 #endif
--- diff/include/asm-m68k/system.h	2004-02-09 10:36:12.000000000 +0000
+++ source/include/asm-m68k/system.h	2004-02-23 13:56:47.000000000 +0000
@@ -158,6 +158,42 @@ static inline unsigned long __xchg(unsig
 }
 #endif
 
+/*
+ * Atomic compare and exchange.  Compare OLD with MEM, if identical,
+ * store NEW in MEM.  Return the initial value in MEM.  Success is
+ * indicated by comparing RETURN with OLD.
+ */
+#ifdef CONFIG_RMW_INSNS
+#define __HAVE_ARCH_CMPXCHG	1
+
+static inline unsigned long __cmpxchg(volatile void *p, unsigned long old,
+				      unsigned long new, int size)
+{
+	switch (size) {
+	case 1:
+		__asm__ __volatile__ ("casb %0,%2,%1"
+				      : "=d" (old), "=m" (*(char *)p)
+				      : "d" (new), "0" (old), "m" (*(char *)p));
+		break;
+	case 2:
+		__asm__ __volatile__ ("casw %0,%2,%1"
+				      : "=d" (old), "=m" (*(short *)p)
+				      : "d" (new), "0" (old), "m" (*(short *)p));
+		break;
+	case 4:
+		__asm__ __volatile__ ("casl %0,%2,%1"
+				      : "=d" (old), "=m" (*(int *)p)
+				      : "d" (new), "0" (old), "m" (*(int *)p));
+		break;
+	}
+	return old;
+}
+
+#define cmpxchg(ptr,o,n)\
+	((__typeof__(*(ptr)))__cmpxchg((ptr),(unsigned long)(o),\
+					(unsigned long)(n),sizeof(*(ptr))))
+#endif
+
 #endif /* __KERNEL__ */
 
 #endif /* _M68K_SYSTEM_H */
--- diff/include/asm-m68k/unistd.h	2003-05-21 11:49:56.000000000 +0100
+++ source/include/asm-m68k/unistd.h	2004-02-23 13:56:47.000000000 +0000
@@ -339,6 +339,8 @@ __syscall_return(type,__res); \
 
 #ifdef __KERNEL_SYSCALLS__
 
+#include <linux/interrupt.h>
+
 /*
  * we need this inline - forking from kernel space will result
  * in NO COPY ON WRITE (!!!), until an execve is executed. This
@@ -363,6 +365,20 @@ static inline _syscall1(int,close,int,fd
 static inline _syscall1(int,_exit,int,exitcode)
 static inline _syscall3(pid_t,waitpid,pid_t,pid,int *,wait_stat,int,options)
 
+asmlinkage long sys_mmap2(
+			unsigned long addr, unsigned long len,
+			unsigned long prot, unsigned long flags,
+			unsigned long fd, unsigned long pgoff);
+asmlinkage int sys_execve(char *name, char **argv, char **envp);
+asmlinkage int sys_pipe(unsigned long *fildes);
+asmlinkage int sys_ptrace(long request, long pid, long addr, long data);
+asmlinkage long sys_ioperm(unsigned long from, unsigned long num, int on);
+struct pt_regs;
+int sys_request_irq(unsigned int,
+			irqreturn_t (*)(int, void *, struct pt_regs *),
+			unsigned long, const char *, void *);
+void sys_free_irq(unsigned int, void *);
+
 #endif
 
 /*
--- diff/include/asm-m68knommu/elf.h	2003-05-21 11:49:56.000000000 +0100
+++ source/include/asm-m68knommu/elf.h	2004-02-23 13:56:47.000000000 +0000
@@ -9,6 +9,33 @@
 #include <asm/ptrace.h>
 #include <asm/user.h>
 
+/*
+ * 68k ELF relocation types
+ */
+#define R_68K_NONE  0
+#define R_68K_32    1
+#define R_68K_16    2
+#define R_68K_8     3
+#define R_68K_PC32  4
+#define R_68K_PC16  5
+#define R_68K_PC8   6
+#define R_68K_GOT32 7
+#define R_68K_GOT16 8
+#define R_68K_GOT8  9
+#define R_68K_GOT32O    10
+#define R_68K_GOT16O    11
+#define R_68K_GOT8O 12
+#define R_68K_PLT32 13
+#define R_68K_PLT16 14
+#define R_68K_PLT8  15
+#define R_68K_PLT32O    16
+#define R_68K_PLT16O    17
+#define R_68K_PLT8O 18
+#define R_68K_COPY  19
+#define R_68K_GLOB_DAT  20
+#define R_68K_JMP_SLOT  21
+#define R_68K_RELATIVE  22
+
 typedef unsigned long elf_greg_t;
 
 #define ELF_NGREG (sizeof(struct user_regs_struct) / sizeof(elf_greg_t))
--- diff/include/asm-m68knommu/irq.h	2003-09-17 12:28:12.000000000 +0100
+++ source/include/asm-m68knommu/irq.h	2004-02-23 13:56:47.000000000 +0000
@@ -62,11 +62,6 @@
 extern void (*mach_enable_irq)(unsigned int);
 extern void (*mach_disable_irq)(unsigned int);
 
-extern int sys_request_irq(unsigned int, 
-	irqreturn_t (*)(int, void *, struct pt_regs *), 
-	unsigned long, const char *, void *);
-extern void sys_free_irq(unsigned int, void *);
-
 /*
  * various flags for request_irq() - the Amiga now uses the standard
  * mechanism like all other architectures - SA_INTERRUPT and SA_SHIRQ
--- diff/include/asm-m68knommu/param.h	2002-11-11 11:09:43.000000000 +0000
+++ source/include/asm-m68knommu/param.h	2004-02-23 13:56:47.000000000 +0000
@@ -44,10 +44,6 @@
 
 #define EXEC_PAGESIZE	4096
 
-#ifndef NGROUPS
-#define NGROUPS		32
-#endif
-
 #ifndef NOGROUP
 #define NOGROUP		(-1)
 #endif
--- diff/include/asm-m68knommu/unistd.h	2003-05-21 11:49:46.000000000 +0100
+++ source/include/asm-m68knommu/unistd.h	2004-02-23 13:56:47.000000000 +0000
@@ -371,10 +371,12 @@ type name(atype a, btype b, ctype c, dty
   }										\
   return (type)__res;								\
 }
-		
+
 
 #ifdef __KERNEL_SYSCALLS__
 
+#include <linux/interrupt.h>
+
 /*
  * we need this inline - forking from kernel space will result
  * in NO COPY ON WRITE (!!!), until an execve is executed. This
@@ -406,6 +408,18 @@ static inline pid_t wait(int * wait_stat
 {
 	return waitpid(-1,wait_stat,0);
 }
+asmlinkage long sys_mmap2(unsigned long addr, unsigned long len,
+			unsigned long prot, unsigned long flags,
+			unsigned long fd, unsigned long pgoff);
+asmlinkage int sys_execve(char *name, char **argv, char **envp);
+asmlinkage int sys_pipe(unsigned long *fildes);
+asmlinkage int sys_ptrace(long request, long pid, long addr, long data);
+asmlinkage long sys_ioperm(unsigned long from, unsigned long num, int on);
+struct pt_regs;
+int sys_request_irq(unsigned int,
+			irqreturn_t (*)(int, void *, struct pt_regs *),
+			unsigned long, const char *, void *);
+void sys_free_irq(unsigned int, void *);
 
 #endif
 
--- diff/include/asm-mips/addrspace.h	2003-08-20 14:16:33.000000000 +0100
+++ source/include/asm-mips/addrspace.h	2004-02-23 13:56:47.000000000 +0000
@@ -11,6 +11,7 @@
 #define _ASM_ADDRSPACE_H
 
 #include <linux/config.h>
+#include <spaces.h>
 
 /*
  *  Configure language
@@ -46,8 +47,6 @@
 #define KSEG2			0xc0000000
 #define KSEG3			0xe0000000
 
-//#define K0BASE			KSEG0
-
 /*
  * Returns the kernel segment base of a given address
  */
@@ -148,25 +147,23 @@
 #define KUBASE			0
 #define KUSIZE_32		0x0000000080000000	/* KUSIZE
 							   for a 32 bit proc */
-//#define K0BASE			0xa800000000000000
-#define K0BASE_EXL_WR		K0BASE			/* exclusive on write */
+#define K0BASE_EXL_WR		0xa800000000000000	/* exclusive on write */
 #define K0BASE_NONCOH		0x9800000000000000	/* noncoherent */
 #define K0BASE_EXL		0xa000000000000000	/* exclusive */
 
-#ifdef CONFIG_SGI_IP27
-#define K1BASE			0x9600000000000000	/* uncached attr 3,
-							   uncac */
-#else
-#define K1BASE			0x9000000000000000
-#endif
-#define K2BASE			0xc000000000000000
+#ifndef CONFIG_CPU_R8000
+
+/*
+ * The R8000 doesn't have the 32-bit compat spaces so we don't define them
+ * in order to catch bugs in the source code.
+ */
 
-#if !defined (CONFIG_CPU_R8000)
 #define COMPAT_K1BASE32		0xffffffffa0000000
 #define PHYS_TO_COMPATK1(x)	((x) | COMPAT_K1BASE32) /* 32-bit compat k1 */
+
 #endif
 
 #define KDM_TO_PHYS(x)		(_ACAST64_ (x) & TO_PHYS_MASK)
-#define PHYS_TO_K0(x)		(_ACAST64_ (x) | K0BASE)
+#define PHYS_TO_K0(x)		(_ACAST64_ (x) | CAC_BASE)
 
 #endif /* _ASM_ADDRSPACE_H */
--- diff/include/asm-mips/arc/types.h	2002-10-16 04:29:02.000000000 +0100
+++ source/include/asm-mips/arc/types.h	2004-02-23 13:56:47.000000000 +0000
@@ -69,4 +69,19 @@ typedef USHORT		*PUSHORT;
 typedef ULONG		*PULONG;
 typedef VOID		*PVOID;
 
+/*
+ * Return type of ArcGetDisplayStatus()
+ */
+typedef struct {
+	USHORT	CursorXPosition;
+	USHORT	CursorYPosition;
+	USHORT	CursorMaxXPosition;
+	USHORT	CursorMaxYPosition;
+	USHORT	ForegroundColor;
+	USHORT	BackgroundColor;
+	UCHAR	HighIntensity;
+	UCHAR	Underscored;
+	UCHAR	ReverseVideo;
+} DISPLAY_STATUS;
+
 #endif /* _ASM_ARC_TYPES_H */
--- diff/include/asm-mips/asm.h	2003-08-20 14:16:33.000000000 +0100
+++ source/include/asm-mips/asm.h	2004-02-23 13:56:47.000000000 +0000
@@ -6,6 +6,7 @@
  * Copyright (C) 1995, 1996, 1997, 1999, 2001 by Ralf Baechle
  * Copyright (C) 1999 by Silicon Graphics, Inc.
  * Copyright (C) 2001 MIPS Technologies, Inc.
+ * Copyright (C) 2002  Maciej W. Rozycki
  *
  * Some useful macros for MIPS assembler code
  *
@@ -13,8 +14,8 @@
  * away by gas in -O mode. These nops are however required to fill delay
  * slots in noreorder mode.
  */
-#ifndef	_ASM_ASM_H
-#define	_ASM_ASM_H
+#ifndef __ASM_ASM_H
+#define __ASM_ASM_H
 
 #include <linux/config.h>
 #include <asm/sgidefs.h>
@@ -204,13 +205,11 @@ symbol		=	value
 /*
  * Stack alignment
  */
-#if (_MIPS_ISA == _MIPS_ISA_MIPS1) || (_MIPS_ISA == _MIPS_ISA_MIPS2) || \
-    (_MIPS_ISA == _MIPS_ISA_MIPS32)
+#if (_MIPS_SIM == _MIPS_SIM_ABI32)
 #define ALSZ	7
 #define ALMASK	~7
 #endif
-#if (_MIPS_ISA == _MIPS_ISA_MIPS3) || (_MIPS_ISA == _MIPS_ISA_MIPS4) || \
-    (_MIPS_ISA == _MIPS_ISA_MIPS5) || (_MIPS_ISA == _MIPS_ISA_MIPS64)
+#if (_MIPS_SIM == _MIPS_SIM_ABIN32) || (_MIPS_SIM == _MIPS_SIM_ABI64)
 #define ALSZ	15
 #define ALMASK	~15
 #endif
@@ -232,15 +231,13 @@ symbol		=	value
  * Use the following macros in assemblercode to load/store registers,
  * pointers etc.
  */
-#if (_MIPS_ISA == _MIPS_ISA_MIPS1) || (_MIPS_ISA == _MIPS_ISA_MIPS2) || \
-    (_MIPS_ISA == _MIPS_ISA_MIPS32)
+#if (_MIPS_SIM == _MIPS_SIM_ABI32)
 #define REG_S		sw
 #define REG_L		lw
 #define REG_SUBU	subu
 #define REG_ADDU	addu
 #endif
-#if (_MIPS_ISA == _MIPS_ISA_MIPS3) || (_MIPS_ISA == _MIPS_ISA_MIPS4) || \
-    (_MIPS_ISA == _MIPS_ISA_MIPS5) || (_MIPS_ISA == _MIPS_ISA_MIPS64)
+#if (_MIPS_SIM == _MIPS_SIM_ABIN32) || (_MIPS_SIM == _MIPS_SIM_ABI64)
 #define REG_S		sd
 #define REG_L		ld
 #define REG_SUBU	dsubu
@@ -385,17 +382,15 @@ symbol		=	value
 /*
  * Some cp0 registers were extended to 64bit for MIPS III.
  */
-#if (_MIPS_ISA == _MIPS_ISA_MIPS1) || (_MIPS_ISA == _MIPS_ISA_MIPS2) || \
-    (_MIPS_ISA == _MIPS_ISA_MIPS32)
+#if (_MIPS_SIM == _MIPS_SIM_ABI32)
 #define MFC0		mfc0
 #define MTC0		mtc0
 #endif
-#if (_MIPS_ISA == _MIPS_ISA_MIPS3) || (_MIPS_ISA == _MIPS_ISA_MIPS4) || \
-    (_MIPS_ISA == _MIPS_ISA_MIPS5) || (_MIPS_ISA == _MIPS_ISA_MIPS64)
+#if (_MIPS_SIM == _MIPS_SIM_ABIN32) || (_MIPS_SIM == _MIPS_SIM_ABI64)
 #define MFC0		dmfc0
 #define MTC0		dmtc0
 #endif
 
 #define SSNOP		sll zero,zero,1
 
-#endif /* _ASM_ASM_H */
+#endif /* __ASM_ASM_H */
--- diff/include/asm-mips/asmmacro-32.h	2003-08-20 14:16:36.000000000 +0100
+++ source/include/asm-mips/asmmacro-32.h	2004-02-23 13:56:47.000000000 +0000
@@ -7,7 +7,6 @@
 #ifndef _ASM_ASMMACRO_32_H
 #define _ASM_ASMMACRO_32_H
 
-#include <linux/config.h>
 #include <asm/offset.h>
 #include <asm/regdef.h>
 #include <asm/fpregdef.h>
--- diff/include/asm-mips/asmmacro-64.h	2003-08-20 14:16:36.000000000 +0100
+++ source/include/asm-mips/asmmacro-64.h	2004-02-23 13:56:47.000000000 +0000
@@ -8,7 +8,6 @@
 #ifndef _ASM_ASMMACRO_64_H
 #define _ASM_ASMMACRO_64_H
 
-#include <linux/config.h>
 #include <asm/offset.h>
 #include <asm/regdef.h>
 #include <asm/fpregdef.h>
--- diff/include/asm-mips/atomic.h	2004-02-18 08:54:12.000000000 +0000
+++ source/include/asm-mips/atomic.h	2004-02-23 13:56:47.000000000 +0000
@@ -11,19 +11,23 @@
  *
  * Copyright (C) 1996, 97, 99, 2000, 03 by Ralf Baechle
  */
-#ifndef _ASM_ATOMIC_H
-#define _ASM_ATOMIC_H
 
+/*
+ * As workaround for the ATOMIC_DEC_AND_LOCK / atomic_dec_and_lock mess in
+ * <linux/spinlock.h> we have to include <linux/spinlock.h> outside the
+ * main big wrapper ...
+ */
 #include <linux/config.h>
+#include <linux/spinlock.h>
+
+#ifndef _ASM_ATOMIC_H
+#define _ASM_ATOMIC_H
 
-#include <asm/system.h>
+extern spinlock_t atomic_lock;
 
 typedef struct { volatile int counter; } atomic_t;
-typedef struct { volatile __s64 counter; } atomic64_t;
 
-#ifdef __KERNEL__
 #define ATOMIC_INIT(i)    { (i) }
-#define ATOMIC64_INIT(i)    { (i) }
 
 /*
  * atomic_read - read atomic variable
@@ -34,13 +38,6 @@ typedef struct { volatile __s64 counter;
 #define atomic_read(v)		((v)->counter)
 
 /*
- * atomic64_read - read atomic variable
- * @v: pointer of type atomic64_t
- *
- */
-#define atomic64_read(v)	((v)->counter)
-
-/*
  * atomic_set - set atomic variable
  * @v: pointer of type atomic_t
  * @i: required value
@@ -49,84 +46,7 @@ typedef struct { volatile __s64 counter;
  */
 #define atomic_set(v,i)		((v)->counter = (i))
 
-/*
- * atomic64_set - set atomic variable
- * @v: pointer of type atomic64_t
- * @i: required value
- */
-#define atomic64_set(v,i)	((v)->counter = (i))
-
-#ifndef CONFIG_CPU_HAS_LLSC
-
-/*
- * The MIPS I implementation is only atomic with respect to
- * interrupts.  R3000 based multiprocessor machines are rare anyway ...
- *
- * atomic_add - add integer to atomic variable
- * @i: integer value to add
- * @v: pointer of type atomic_t
- *
- * Atomically adds @i to @v.
- */
-static __inline__ void atomic_add(int i, atomic_t * v)
-{
-	unsigned long flags;
-
-	local_irq_save(flags);
-	v->counter += i;
-	local_irq_restore(flags);
-}
-
-/*
- * atomic_sub - subtract the atomic variable
- * @i: integer value to subtract
- * @v: pointer of type atomic_t
- *
- * Atomically subtracts @i from @v.
- */
-static __inline__ void atomic_sub(int i, atomic_t * v)
-{
-	unsigned long flags;
-
-	local_irq_save(flags);
-	v->counter -= i;
-	local_irq_restore(flags);
-}
-
-static __inline__ int atomic_add_return(int i, atomic_t * v)
-{
-	unsigned long flags;
-	int temp;
-
-	local_irq_save(flags);
-	temp = v->counter;
-	temp += i;
-	v->counter = temp;
-	local_irq_restore(flags);
-
-	return temp;
-}
-
-static __inline__ int atomic_sub_return(int i, atomic_t * v)
-{
-	unsigned long flags;
-	int temp;
-
-	local_irq_save(flags);
-	temp = v->counter;
-	temp -= i;
-	v->counter = temp;
-	local_irq_restore(flags);
-
-	return temp;
-}
-
-#else
-
-/*
- * ... while for MIPS II and better we can use ll/sc instruction.  This
- * implementation is SMP safe ...
- */
+#ifdef CONFIG_CPU_HAS_LLSC
 
 /*
  * atomic_add - add integer to atomic variable
@@ -160,12 +80,10 @@ static __inline__ void atomic_sub(int i,
 	unsigned long temp;
 
 	__asm__ __volatile__(
-	"	.set	noreorder	# atomic_sub		\n"
-	"1:	ll	%0, %1					\n"
+	"1:	ll	%0, %1		# atomic_sub		\n"
 	"	subu	%0, %2					\n"
 	"	sc	%0, %1					\n"
 	"	beqz	%0, 1b					\n"
-	"	.set	reorder					\n"
 	: "=&r" (temp), "=m" (v->counter)
 	: "Ir" (i), "m" (v->counter));
 }
@@ -178,14 +96,12 @@ static __inline__ int atomic_add_return(
 	unsigned long temp, result;
 
 	__asm__ __volatile__(
-	"	.set	noreorder	# atomic_add_return	\n"
-	"1:	ll	%1, %2					\n"
+	"1:	ll	%1, %2		# atomic_add_return	\n"
 	"	addu	%0, %1, %3				\n"
 	"	sc	%0, %2					\n"
 	"	beqz	%0, 1b					\n"
 	"	addu	%0, %1, %3				\n"
 	"	sync						\n"
-	"	.set	reorder					\n"
 	: "=&r" (result), "=&r" (temp), "=m" (v->counter)
 	: "Ir" (i), "m" (v->counter)
 	: "memory");
@@ -198,93 +114,168 @@ static __inline__ int atomic_sub_return(
 	unsigned long temp, result;
 
 	__asm__ __volatile__(
-	"	.set	noreorder	# atomic_sub_return	\n"
-	"1:	ll	%1, %2					\n"
+	"1:	ll	%1, %2		# atomic_sub_return	\n"
 	"	subu	%0, %1, %3				\n"
 	"	sc	%0, %2					\n"
 	"	beqz	%0, 1b					\n"
 	"	subu	%0, %1, %3				\n"
 	"	sync						\n"
-	"	.set	reorder					\n"
 	: "=&r" (result), "=&r" (temp), "=m" (v->counter)
 	: "Ir" (i), "m" (v->counter)
 	: "memory");
 
 	return result;
 }
-#endif
 
-#ifndef CONFIG_CPU_HAS_LLDSCD
+#else
 
 /*
- * This implementation is only atomic with respect to interrupts.  It can't
- * be used on SMP
+ * The MIPS I implementation is only atomic with respect to
+ * interrupts.  R3000 based multiprocessor machines are rare anyway ...
  *
- * atomic64_add - add integer to atomic variable
+ * atomic_add - add integer to atomic variable
  * @i: integer value to add
- * @v: pointer of type atomic64_t
+ * @v: pointer of type atomic_t
  *
  * Atomically adds @i to @v.
  */
-static __inline__ void atomic64_add(int i, atomic64_t * v)
+static __inline__ void atomic_add(int i, atomic_t * v)
 {
 	unsigned long flags;
 
-	local_irq_save(flags);
+	spin_lock_irqsave(&atomic_lock, flags);
 	v->counter += i;
-	local_irq_restore(flags);
+	spin_unlock_irqrestore(&atomic_lock, flags);
 }
 
 /*
- * atomic64_sub - subtract the atomic variable
+ * atomic_sub - subtract the atomic variable
  * @i: integer value to subtract
- * @v: pointer of type atomic64_t
+ * @v: pointer of type atomic_t
  *
  * Atomically subtracts @i from @v.
  */
-static __inline__ void atomic64_sub(int i, atomic64_t * v)
+static __inline__ void atomic_sub(int i, atomic_t * v)
 {
 	unsigned long flags;
 
-	local_irq_save(flags);
+	spin_lock_irqsave(&atomic_lock, flags);
 	v->counter -= i;
-	local_irq_restore(flags);
+	spin_unlock_irqrestore(&atomic_lock, flags);
 }
 
-static __inline__ int atomic64_add_return(int i, atomic64_t * v)
+static __inline__ int atomic_add_return(int i, atomic_t * v)
 {
 	unsigned long flags;
 	int temp;
 
-	local_irq_save(flags);
+	spin_lock_irqsave(&atomic_lock, flags);
 	temp = v->counter;
 	temp += i;
 	v->counter = temp;
-	local_irq_restore(flags);
+	spin_unlock_irqrestore(&atomic_lock, flags);
 
 	return temp;
 }
 
-static __inline__ int atomic64_sub_return(int i, atomic64_t * v)
+static __inline__ int atomic_sub_return(int i, atomic_t * v)
 {
 	unsigned long flags;
 	int temp;
 
-	local_irq_save(flags);
+	spin_lock_irqsave(&atomic_lock, flags);
 	temp = v->counter;
 	temp -= i;
 	v->counter = temp;
-	local_irq_restore(flags);
+	spin_unlock_irqrestore(&atomic_lock, flags);
 
 	return temp;
 }
 
-#else
+#endif /* CONFIG_CPU_HAS_LLSC */
+
+#define atomic_dec_return(v) atomic_sub_return(1,(v))
+#define atomic_inc_return(v) atomic_add_return(1,(v))
+
+/*
+ * atomic_sub_and_test - subtract value from variable and test result
+ * @i: integer value to subtract
+ * @v: pointer of type atomic_t
+ *
+ * Atomically subtracts @i from @v and returns
+ * true if the result is zero, or false for all
+ * other cases.
+ */
+#define atomic_sub_and_test(i,v) (atomic_sub_return((i), (v)) == 0)
+
+/*
+ * atomic_inc_and_test - increment and test
+ * @v: pointer of type atomic_t
+ *
+ * Atomically increments @v by 1
+ * and returns true if the result is zero, or false for all
+ * other cases.
+ */
+#define atomic_inc_and_test(v) (atomic_inc_return(v) == 0)
+
+/*
+ * atomic_dec_and_test - decrement by 1 and test
+ * @v: pointer of type atomic_t
+ *
+ * Atomically decrements @v by 1 and
+ * returns true if the result is 0, or false for all other
+ * cases.
+ */
+#define atomic_dec_and_test(v) (atomic_sub_return(1, (v)) == 0)
 
 /*
- * ... while for MIPS III and better we can use ll/sc instruction.  This
- * implementation is SMP safe ...
+ * atomic_inc - increment atomic variable
+ * @v: pointer of type atomic_t
+ *
+ * Atomically increments @v by 1.
  */
+#define atomic_inc(v) atomic_add(1,(v))
+
+/*
+ * atomic_dec - decrement and test
+ * @v: pointer of type atomic_t
+ *
+ * Atomically decrements @v by 1.
+ */
+#define atomic_dec(v) atomic_sub(1,(v))
+
+/*
+ * atomic_add_negative - add and test if negative
+ * @v: pointer of type atomic_t
+ * @i: integer value to add
+ *
+ * Atomically adds @i to @v and returns true
+ * if the result is negative, or false when
+ * result is greater than or equal to zero.
+ */
+#define atomic_add_negative(i,v) (atomic_add_return(i, (v)) < 0)
+
+#ifdef CONFIG_MIPS64
+
+typedef struct { volatile __s64 counter; } atomic64_t;
+
+#define ATOMIC64_INIT(i)    { (i) }
+
+/*
+ * atomic64_read - read atomic variable
+ * @v: pointer of type atomic64_t
+ *
+ */
+#define atomic64_read(v)	((v)->counter)
+
+/*
+ * atomic64_set - set atomic variable
+ * @v: pointer of type atomic64_t
+ * @i: required value
+ */
+#define atomic64_set(v,i)	((v)->counter = (i))
+
+#ifdef CONFIG_CPU_HAS_LLDSCD
 
 /*
  * atomic64_add - add integer to atomic variable
@@ -298,9 +289,9 @@ static __inline__ void atomic64_add(int 
 	unsigned long temp;
 
 	__asm__ __volatile__(
-	"1:	ll	%0, %1		# atomic64_add		\n"
+	"1:	lld	%0, %1		# atomic64_add		\n"
 	"	addu	%0, %2					\n"
-	"	sc	%0, %1					\n"
+	"	scd	%0, %1					\n"
 	"	beqz	%0, 1b					\n"
 	: "=&r" (temp), "=m" (v->counter)
 	: "Ir" (i), "m" (v->counter));
@@ -318,12 +309,10 @@ static __inline__ void atomic64_sub(int 
 	unsigned long temp;
 
 	__asm__ __volatile__(
-	"	.set	noreorder	# atomic64_sub		\n"
-	"1:	ll	%0, %1					\n"
+	"1:	lld	%0, %1		# atomic64_sub		\n"
 	"	subu	%0, %2					\n"
-	"	sc	%0, %1					\n"
+	"	scd	%0, %1					\n"
 	"	beqz	%0, 1b					\n"
-	"	.set	reorder					\n"
 	: "=&r" (temp), "=m" (v->counter)
 	: "Ir" (i), "m" (v->counter));
 }
@@ -336,14 +325,12 @@ static __inline__ int atomic64_add_retur
 	unsigned long temp, result;
 
 	__asm__ __volatile__(
-	"	.set	noreorder	# atomic64_add_return	\n"
-	"1:	ll	%1, %2					\n"
+	"1:	lld	%1, %2		# atomic64_add_return	\n"
 	"	addu	%0, %1, %3				\n"
-	"	sc	%0, %2					\n"
+	"	scd	%0, %2					\n"
 	"	beqz	%0, 1b					\n"
 	"	addu	%0, %1, %3				\n"
 	"	sync						\n"
-	"	.set	reorder					\n"
 	: "=&r" (result), "=&r" (temp), "=m" (v->counter)
 	: "Ir" (i), "m" (v->counter)
 	: "memory");
@@ -356,37 +343,88 @@ static __inline__ int atomic64_sub_retur
 	unsigned long temp, result;
 
 	__asm__ __volatile__(
-	"	.set	noreorder	# atomic64_sub_return	\n"
-	"1:	ll	%1, %2					\n"
+	"1:	lld	%1, %2		# atomic64_sub_return	\n"
 	"	subu	%0, %1, %3				\n"
-	"	sc	%0, %2					\n"
+	"	scd	%0, %2					\n"
 	"	beqz	%0, 1b					\n"
 	"	subu	%0, %1, %3				\n"
 	"	sync						\n"
-	"	.set	reorder					\n"
 	: "=&r" (result), "=&r" (temp), "=m" (v->counter)
 	: "Ir" (i), "m" (v->counter)
 	: "memory");
 
 	return result;
 }
-#endif
 
-#define atomic_dec_return(v) atomic_sub_return(1,(v))
-#define atomic64_dec_return(v) atomic64_sub_return(1,(v))
-#define atomic_inc_return(v) atomic_add_return(1,(v))
-#define atomic64_inc_return(v) atomic64_add_return(1,(v))
+#else
 
 /*
- * atomic_sub_and_test - subtract value from variable and test result
+ * This implementation is only atomic with respect to interrupts.  It can't
+ * be used on SMP
+ *
+ * atomic64_add - add integer to atomic variable
+ * @i: integer value to add
+ * @v: pointer of type atomic64_t
+ *
+ * Atomically adds @i to @v.
+ */
+static __inline__ void atomic64_add(int i, atomic64_t * v)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&atomic_lock, flags);
+	v->counter += i;
+	spin_unlock_irqrestore(&atomic_lock, flags);
+}
+
+/*
+ * atomic64_sub - subtract the atomic variable
  * @i: integer value to subtract
- * @v: pointer of type atomic_t
+ * @v: pointer of type atomic64_t
  *
- * Atomically subtracts @i from @v and returns
- * true if the result is zero, or false for all
- * other cases.
+ * Atomically subtracts @i from @v.
  */
-#define atomic_sub_and_test(i,v) (atomic_sub_return((i), (v)) == 0)
+static __inline__ void atomic64_sub(int i, atomic64_t * v)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&atomic_lock, flags);
+	v->counter -= i;
+	spin_unlock_irqrestore(&atomic_lock, flags);
+}
+
+static __inline__ int atomic64_add_return(int i, atomic64_t * v)
+{
+	unsigned long flags;
+	int temp;
+
+	spin_lock_irqsave(&atomic_lock, flags);
+	temp = v->counter;
+	temp += i;
+	v->counter = temp;
+	spin_unlock_irqrestore(&atomic_lock, flags);
+
+	return temp;
+}
+
+static __inline__ int atomic64_sub_return(int i, atomic64_t * v)
+{
+	unsigned long flags;
+	int temp;
+
+	spin_lock_irqsave(&atomic_lock, flags);
+	temp = v->counter;
+	temp -= i;
+	v->counter = temp;
+	spin_unlock_irqrestore(&atomic_lock, flags);
+
+	return temp;
+}
+
+#endif /* CONFIG_CPU_HAS_LLDSCD */
+
+#define atomic64_dec_return(v) atomic64_sub_return(1,(v))
+#define atomic64_inc_return(v) atomic64_add_return(1,(v))
 
 /*
  * atomic64_sub_and_test - subtract value from variable and test result
@@ -400,16 +438,6 @@ static __inline__ int atomic64_sub_retur
 #define atomic64_sub_and_test(i,v) (atomic64_sub_return((i), (v)) == 0)
 
 /*
- * atomic_inc_and_test - increment and test
- * @v: pointer of type atomic_t
- *
- * Atomically increments @v by 1
- * and returns true if the result is zero, or false for all
- * other cases.
- */
-#define atomic_inc_and_test(v) (atomic_inc_return(v) == 0)
-
-/*
  * atomic64_inc_and_test - increment and test
  * @v: pointer of type atomic64_t
  *
@@ -420,16 +448,6 @@ static __inline__ int atomic64_sub_retur
 #define atomic64_inc_and_test(v) (atomic64_inc_return(v) == 0)
 
 /*
- * atomic_dec_and_test - decrement by 1 and test
- * @v: pointer of type atomic_t
- *
- * Atomically decrements @v by 1 and
- * returns true if the result is 0, or false for all other
- * cases.
- */
-#define atomic_dec_and_test(v) (atomic_sub_return(1, (v)) == 0)
-
-/*
  * atomic64_dec_and_test - decrement by 1 and test
  * @v: pointer of type atomic64_t
  *
@@ -440,14 +458,6 @@ static __inline__ int atomic64_sub_retur
 #define atomic64_dec_and_test(v) (atomic64_sub_return(1, (v)) == 0)
 
 /*
- * atomic_inc - increment atomic variable
- * @v: pointer of type atomic_t
- *
- * Atomically increments @v by 1.
- */
-#define atomic_inc(v) atomic_add(1,(v))
-
-/*
  * atomic64_inc - increment atomic variable
  * @v: pointer of type atomic64_t
  *
@@ -456,14 +466,6 @@ static __inline__ int atomic64_sub_retur
 #define atomic64_inc(v) atomic64_add(1,(v))
 
 /*
- * atomic_dec - decrement and test
- * @v: pointer of type atomic_t
- *
- * Atomically decrements @v by 1.
- */
-#define atomic_dec(v) atomic_sub(1,(v))
-
-/*
  * atomic64_dec - decrement and test
  * @v: pointer of type atomic64_t
  *
@@ -472,17 +474,6 @@ static __inline__ int atomic64_sub_retur
 #define atomic64_dec(v) atomic64_sub(1,(v))
 
 /*
- * atomic_add_negative - add and test if negative
- * @v: pointer of type atomic_t
- * @i: integer value to add
- *
- * Atomically adds @i to @v and returns true
- * if the result is negative, or false when
- * result is greater than or equal to zero.
- */
-#define atomic_add_negative(i,v) (atomic_add_return(i, (v)) < 0)
-
-/*
  * atomic64_add_negative - add and test if negative
  * @v: pointer of type atomic64_t
  * @i: integer value to add
@@ -493,12 +484,15 @@ static __inline__ int atomic64_sub_retur
  */
 #define atomic64_add_negative(i,v) (atomic64_add_return(i, (v)) < 0)
 
-/* Atomic operations are already serializing */
+#endif /* CONFIG_MIPS64 */
+
+/*
+ * atomic*_return operations are serializing but not the non-*_return
+ * versions.
+ */
 #define smp_mb__before_atomic_dec()	smp_mb()
 #define smp_mb__after_atomic_dec()	smp_mb()
 #define smp_mb__before_atomic_inc()	smp_mb()
 #define smp_mb__after_atomic_inc()	smp_mb()
 
-#endif /* defined(__KERNEL__) */
-
 #endif /* _ASM_ATOMIC_H */
--- diff/include/asm-mips/bitops.h	2003-08-20 14:16:33.000000000 +0100
+++ source/include/asm-mips/bitops.h	2004-02-23 13:56:47.000000000 +0000
@@ -19,11 +19,13 @@
 #define SZLONG_MASK 31UL
 #define __LL	"ll"
 #define __SC	"sc"
+#define cpu_to_lelongp(x) cpu_to_le32p((__u32 *) (x)) 
 #elif (_MIPS_SZLONG == 64)
 #define SZLONG_LOG 6
 #define SZLONG_MASK 63UL
 #define __LL	"lld"
 #define __SC	"scd"
+#define cpu_to_lelongp(x) cpu_to_le64p((__u64 *) (x)) 
 #endif
 
 #ifdef __KERNEL__
@@ -627,7 +629,7 @@ static inline int __test_and_change_bit(
  */
 static inline int test_bit(unsigned long nr, const volatile unsigned long *addr)
 {
-	return 1UL & (((const volatile unsigned long *) addr)[nr >> SZLONG_LOG] >> (nr & SZLONG_MASK));
+	return 1UL & (addr[nr >> SZLONG_LOG] >> (nr & SZLONG_MASK));
 }
 
 /*
@@ -683,10 +685,10 @@ static inline unsigned long __ffs(unsign
  * @offset: The bitnumber to start searching at
  * @size: The maximum size to search
  */
-static inline unsigned long find_next_zero_bit(unsigned long *addr,
+static inline unsigned long find_next_zero_bit(const unsigned long *addr,
 	unsigned long size, unsigned long offset)
 {
-	unsigned long *p = ((unsigned long *) addr) + (offset >> SZLONG_LOG);
+	const unsigned long *p = addr + (offset >> SZLONG_LOG);
 	unsigned long result = offset & ~SZLONG_MASK;
 	unsigned long tmp;
 
@@ -731,10 +733,10 @@ found_middle:
  * @offset: The bitnumber to start searching at
  * @size: The maximum size to search
  */
-static inline unsigned long find_next_bit(unsigned long *addr,
+static inline unsigned long find_next_bit(const unsigned long *addr,
 	unsigned long size, unsigned long offset)
 {
-	unsigned long *p = addr + (offset >> SZLONG_LOG);
+	const unsigned long *p = addr + (offset >> SZLONG_LOG);
 	unsigned long result = offset & ~SZLONG_MASK;
 	unsigned long tmp;
 
@@ -789,7 +791,7 @@ found_middle:
  * unlikely to be set. It's guaranteed that at least one of the 140
  * bits is cleared.
  */
-static inline int sched_find_first_bit(unsigned long *b)
+static inline int sched_find_first_bit(const unsigned long *b)
 {
 #ifdef CONFIG_MIPS32
 	if (unlikely(b[0]))
@@ -829,6 +831,7 @@ static inline int sched_find_first_bit(u
  * The Hamming Weight of a number is the total number of bits set in it.
  */
 
+#define hweight64(x)	generic_hweight64(x)
 #define hweight32(x)	generic_hweight32(x)
 #define hweight16(x)	generic_hweight16(x)
 #define hweight8(x)	generic_hweight8(x)
@@ -870,59 +873,44 @@ static inline int test_le_bit(unsigned l
 	return ((mask & *ADDR) != 0);
 }
 
-static inline unsigned long ext2_ffz(unsigned int word)
-{
-	int b = 0, s;
-
-	word = ~word;
-	s = 16; if (word << 16 != 0) s = 0; b += s; word >>= s;
-	s =  8; if (word << 24 != 0) s = 0; b += s; word >>= s;
-	s =  4; if (word << 28 != 0) s = 0; b += s; word >>= s;
-	s =  2; if (word << 30 != 0) s = 0; b += s; word >>= s;
-	s =  1; if (word << 31 != 0) s = 0; b += s;
-
-	return b;
-}
-
 static inline unsigned long find_next_zero_le_bit(unsigned long *addr,
 	unsigned long size, unsigned long offset)
 {
-	unsigned int *p = ((unsigned int *) addr) + (offset >> SZLONG_LOG);
-	unsigned int result = offset & ~SZLONG_MASK;
-	unsigned int tmp;
+	unsigned long *p = ((unsigned long *) addr) + (offset >> SZLONG_LOG);
+	unsigned long result = offset & ~SZLONG_MASK;
+	unsigned long tmp;
 
 	if (offset >= size)
 		return size;
-
 	size -= result;
 	offset &= SZLONG_MASK;
 	if (offset) {
-		tmp = cpu_to_le32p(p++);
-		tmp |= ~0U >> (32-offset); /* bug or feature ? */
-		if (size < 32)
+		tmp = cpu_to_lelongp(p++);
+		tmp |= ~0UL >> (_MIPS_SZLONG-offset); /* bug or feature ? */
+		if (size < _MIPS_SZLONG)
 			goto found_first;
-		if (tmp != ~0U)
+		if (~tmp)
 			goto found_middle;
-		size -= 32;
-		result += 32;
+		size -= _MIPS_SZLONG;
+		result += _MIPS_SZLONG;
 	}
-	while (size >= 32) {
-		if ((tmp = cpu_to_le32p(p++)) != ~0U)
+	while (size & ~SZLONG_MASK) {
+		if (~(tmp = cpu_to_lelongp(p++)))
 			goto found_middle;
-		result += 32;
-		size -= 32;
+		result += _MIPS_SZLONG;
+		size -= _MIPS_SZLONG;
 	}
 	if (!size)
 		return result;
+	tmp = cpu_to_lelongp(p);
 
-	tmp = cpu_to_le32p(p);
 found_first:
-	tmp |= ~0 << size;
-	if (tmp == ~0U)			/* Are any bits zero? */
+	tmp |= ~0UL << size;
+	if (tmp == ~0UL)		/* Are any bits zero? */
 		return result + size;	/* Nope. */
 
 found_middle:
-	return result + ext2_ffz(tmp);
+	return result + ffz(tmp);
 }
 
 #define find_first_zero_le_bit(addr, size) \
--- diff/include/asm-mips/bootinfo.h	2003-07-08 09:55:19.000000000 +0100
+++ source/include/asm-mips/bootinfo.h	2004-02-23 13:56:47.000000000 +0000
@@ -3,8 +3,10 @@
  * License.  See the file COPYING in the main directory of this archive
  * for more details.
  *
- * Copyright (C) 1995, 1996 by Ralf Baechle, Andreas Busse,
- *                             Stoned Elipot and Paul M. Antoine.
+ * Copyright (C) 1995, 1996, 2003 by Ralf Baechle
+ * Copyright (C) 1995, 1996 Andreas Busse
+ * Copyright (C) 1995, 1996 Stoned Elipot
+ * Copyright (C) 1995, 1996 Paul M. Antoine.
  */
 #ifndef _ASM_BOOTINFO_H
 #define _ASM_BOOTINFO_H
@@ -12,180 +14,199 @@
 #include <linux/types.h>
 
 /*
- * Values for machgroup
+ * The MACH_GROUP_ IDs are the equivalent to PCI vendor IDs; the remaining
+ * MACH_ values equivalent to product IDs.  As such the numbers do not
+ * necessarily reflect technical relations or similarities between systems.
  */
-#define MACH_GROUP_UNKNOWN      0 /* whatever...                            */
-#define MACH_GROUP_JAZZ     	1 /* Jazz                                   */
-#define MACH_GROUP_DEC          2 /* Digital Equipment                      */
-#define MACH_GROUP_ARC		3 /* Wreckstation Tyne, rPC44, possibly other */
-#define MACH_GROUP_SNI_RM	4 /* Siemens Nixdorf RM series              */
-#define MACH_GROUP_ACN		5
-#define MACH_GROUP_SGI          6 /* Silicon Graphics                       */
-#define MACH_GROUP_COBALT       7 /* Cobalt servers		 	    */
-#define MACH_GROUP_NEC_DDB	8 /* NEC DDB                                */
-#define MACH_GROUP_BAGET	9 /* Baget                                  */
-#define MACH_GROUP_COSINE      10 /* CoSine Orion                           */
-#define MACH_GROUP_GALILEO     11 /* Galileo Eval Boards                    */
-#define MACH_GROUP_MOMENCO     12 /* Momentum Boards                        */
-#define MACH_GROUP_ITE         13 /* ITE Semi Eval Boards                   */
-#define MACH_GROUP_PHILIPS     14
-#define MACH_GROUP_GLOBESPAN   15 /* Globespan PVR Referrence Board         */
-#define MACH_GROUP_SIBYTE      16 /* Sibyte Eval Boards                     */
-#define MACH_GROUP_TOSHIBA     17 /* Toshiba Reference Systems TSBREF       */
-#define MACH_GROUP_ALCHEMY     18 /* Alchemy Semi Eval Boards               */
-#define MACH_GROUP_NEC_VR41XX  19 /* NEC Vr41xx based boards/gadgets        */
-#define MACH_GROUP_HP_LJ       20 /* Hewlett Packard LaserJet               */
-#define MACH_GROUP_LASAT       21
 
 /*
- * Valid machtype values for group unknown (low order halfword of mips_machtype)
+ * Valid machtype values for group unknown
  */
-#define MACH_UNKNOWN		0	/* whatever...			*/
+#define MACH_GROUP_UNKNOWN      0	/* whatever...			*/
+#define  MACH_UNKNOWN		0	/* whatever...			*/
 
 /*
  * Valid machtype values for group JAZZ
  */
-#define MACH_ACER_PICA_61	0	/* Acer PICA-61 (PICA1)		*/
-#define MACH_MIPS_MAGNUM_4000	1	/* Mips Magnum 4000 "RC4030"	*/
-#define MACH_OLIVETTI_M700      2	/* Olivetti M700-10 (-15 ??)    */
+#define MACH_GROUP_JAZZ		1 	/* Jazz				*/
+#define  MACH_ACER_PICA_61	0	/* Acer PICA-61 (PICA1)		*/
+#define  MACH_MIPS_MAGNUM_4000	1	/* Mips Magnum 4000 "RC4030"	*/
+#define  MACH_OLIVETTI_M700	2	/* Olivetti M700-10 (-15 ??)    */
 
 /*
  * Valid machtype for group DEC
  */
-#define MACH_DSUNKNOWN		0
-#define MACH_DS23100		1	/* DECstation 2100 or 3100	*/
-#define MACH_DS5100		2	/* DECsystem 5100		*/
-#define MACH_DS5000_200		3	/* DECstation 5000/200		*/
-#define MACH_DS5000_1XX		4	/* DECstation 5000/120, 125, 133, 150 */
-#define MACH_DS5000_XX		5	/* DECstation 5000/20, 25, 33, 50 */
-#define MACH_DS5000_2X0		6	/* DECstation 5000/240, 260	*/
-#define MACH_DS5400		7	/* DECsystem 5400		*/
-#define MACH_DS5500		8	/* DECsystem 5500		*/
-#define MACH_DS5800		9	/* DECsystem 5800		*/
-#define MACH_DS5900		10	/* DECsystem 5900		*/
+#define MACH_GROUP_DEC          2	/* Digital Equipment		*/
+#define  MACH_DSUNKNOWN		0
+#define  MACH_DS23100		1	/* DECstation 2100 or 3100	*/
+#define  MACH_DS5100		2	/* DECsystem 5100		*/
+#define  MACH_DS5000_200	3	/* DECstation 5000/200		*/
+#define  MACH_DS5000_1XX	4	/* DECstation 5000/120, 125, 133, 150 */
+#define  MACH_DS5000_XX		5	/* DECstation 5000/20, 25, 33, 50 */
+#define  MACH_DS5000_2X0	6	/* DECstation 5000/240, 260	*/
+#define  MACH_DS5400		7	/* DECsystem 5400		*/
+#define  MACH_DS5500		8	/* DECsystem 5500		*/
+#define  MACH_DS5800		9	/* DECsystem 5800		*/
+#define  MACH_DS5900		10	/* DECsystem 5900		*/
 
 /*
  * Valid machtype for group ARC
  */
+#define MACH_GROUP_ARC		3	/* Deskstation			*/
 #define MACH_DESKSTATION_RPC44  0	/* Deskstation rPC44 */
 #define MACH_DESKSTATION_TYNE	1	/* Deskstation Tyne */
 
 /*
  * Valid machtype for group SNI_RM
  */
-#define MACH_SNI_RM200_PCI	0	/* RM200/RM300/RM400 PCI series */
+#define MACH_GROUP_SNI_RM	4	/* Siemens Nixdorf RM series	*/
+#define  MACH_SNI_RM200_PCI	0	/* RM200/RM300/RM400 PCI series */
 
 /*
  * Valid machtype for group ACN
  */
-#define MACH_ACN_MIPS_BOARD	0       /* ACN MIPS single board        */
+#define MACH_GROUP_ACN		5
+#define  MACH_ACN_MIPS_BOARD	0       /* ACN MIPS single board        */
 
 /*
  * Valid machtype for group SGI
  */
-#define MACH_SGI_IP22		0	/* Indy, Indigo2, Challenge S */
-#define MACH_SGI_IP27		1	/* Origin 200, Origin 2000, Onyx 2 */
-#define MACH_SGI_IP28		2	/* Indigo2 Impact */
-#define MACH_SGI_IP32		3	/* O2 */
+#define MACH_GROUP_SGI          6	/* Silicon Graphics		*/
+#define  MACH_SGI_IP22		0	/* Indy, Indigo2, Challenge S	*/
+#define  MACH_SGI_IP27		1	/* Origin 200, Origin 2000, Onyx 2 */
+#define  MACH_SGI_IP28		2	/* Indigo2 Impact		*/
+#define  MACH_SGI_IP32		3	/* O2				*/
 
 /*
  * Valid machtype for group COBALT
  */
-#define MACH_COBALT_27		0	/* Proto "27" hardware */
+#define MACH_GROUP_COBALT       7	/* Cobalt servers		*/
+#define  MACH_COBALT_27		0	/* Proto "27" hardware		*/
 
 /*
  * Valid machtype for group NEC DDB
  */
-#define MACH_NEC_DDB5074	0	/* NEC DDB Vrc-5074 */
-#define MACH_NEC_DDB5476	1	/* NEC DDB Vrc-5476 */
-#define MACH_NEC_DDB5477	2	/* NEC DDB Vrc-5477 */
-#define MACH_NEC_ROCKHOPPER	3	/* Rockhopper base board */
-#define MACH_NEC_ROCKHOPPERII	4	/* Rockhopper II base board */
+#define MACH_GROUP_NEC_DDB	8	/* NEC DDB			*/
+#define  MACH_NEC_DDB5074	0	/* NEC DDB Vrc-5074 */
+#define  MACH_NEC_DDB5476	1	/* NEC DDB Vrc-5476 */
+#define  MACH_NEC_DDB5477	2	/* NEC DDB Vrc-5477 */
+#define  MACH_NEC_ROCKHOPPER	3	/* Rockhopper base board */
+#define  MACH_NEC_ROCKHOPPERII	4	/* Rockhopper II base board */
 
 /*
  * Valid machtype for group BAGET
  */
-#define MACH_BAGET201		0	/* BT23-201 */
-#define MACH_BAGET202		1	/* BT23-202 */
+#define MACH_GROUP_BAGET	9	/* Baget			*/
+#define  MACH_BAGET201		0	/* BT23-201 */
+#define  MACH_BAGET202		1	/* BT23-202 */
 
 /*
  * Cosine boards.
  */
-#define MACH_COSINE_ORION	0
+#define MACH_GROUP_COSINE      10	/* CoSine Orion			*/
+#define  MACH_COSINE_ORION	0
 
 /*
  * Valid machtype for group GALILEO
  */
-#define MACH_EV96100		0	/* EV96100 */
-#define MACH_EV64120A		1	/* EV64120A */
+#define MACH_GROUP_GALILEO     11	/* Galileo Eval Boards		*/
+#define  MACH_EV96100		0	/* EV96100 */
+#define  MACH_EV64120A		1	/* EV64120A */
 
 /*
  * Valid machtype for group MOMENCO
  */
-#define MACH_MOMENCO_OCELOT		0
-#define MACH_MOMENCO_OCELOT_G		1
-#define MACH_MOMENCO_OCELOT_C		2
+#define MACH_GROUP_MOMENCO	12	/* Momentum Boards		*/
+#define  MACH_MOMENCO_OCELOT	0
+#define  MACH_MOMENCO_OCELOT_G	1
+#define  MACH_MOMENCO_OCELOT_C	2
+#define  MACH_MOMENCO_JAGUAR_ATX 3
 
 /*
  * Valid machtype for group ITE
  */
-#define MACH_QED_4N_S01B	0	/* ITE8172 based eval board */
+#define MACH_GROUP_ITE		13	/* ITE Semi Eval Boards		*/
+#define  MACH_QED_4N_S01B	0	/* ITE8172 based eval board */
 
 /*
- * Valid machtype for group Globespan
+ * Valid machtype for group PHILIPS
  */
-#define MACH_IVR		0	/* IVR eval board */
+#define MACH_GROUP_PHILIPS     14
+#define  MACH_PHILIPS_NINO	0	/* Nino */
+#define  MACH_PHILIPS_VELO	1	/* Velo */
 
 /*
- * Valid machtype for group PHILIPS
+ * Valid machtype for group Globespan
  */
-#define MACH_PHILIPS_NINO	0	/* Nino */
-#define MACH_PHILIPS_VELO	1	/* Velo */
+#define MACH_GROUP_GLOBESPAN   15	/* Globespan */
+#define  MACH_IVR		0	/* IVR eval board */
 
 /*
  * Valid machtype for group SIBYTE
  */
-#define MACH_SWARM              0
+#define MACH_GROUP_SIBYTE	16	/* Sibyte / Broadcom */
+#define  MACH_SWARM              0
 
 /*
  * Valid machtypes for group Toshiba
  */
-#define MACH_PALLAS		0
-#define MACH_TOPAS		1
-#define MACH_JMR		2
-#define MACH_TOSHIBA_JMR3927	3	/* JMR-TX3927 CPU/IO board */
-#define MACH_TOSHIBA_RBTX4927	4
-#define MACH_TOSHIBA_RBTX4937	5
+#define MACH_GROUP_TOSHIBA	17 /* Toshiba Reference Systems TSBREF       */
+#define  MACH_PALLAS		0
+#define  MACH_TOPAS		1
+#define  MACH_JMR		2
+#define  MACH_TOSHIBA_JMR3927	3	/* JMR-TX3927 CPU/IO board */
+#define  MACH_TOSHIBA_RBTX4927	4
+#define  MACH_TOSHIBA_RBTX4937	5
+
 #define GROUP_TOSHIBA_NAMES	{ "Pallas", "TopasCE", "JMR", "JMR TX3927", \
 				  "RBTX4927", "RBTX4937" }
 
 /*
- * Valid machtype for group LASAT
+ * Valid machtype for group Alchemy
  */
-#define MACH_LASAT_100		0	/* Masquerade II/SP100/SP50/SP25 */
-#define MACH_LASAT_200		1	/* Masquerade PRO/SP200 */
+#define MACH_GROUP_ALCHEMY     18	/* AMD Alchemy	*/
+#define  MACH_PB1000		0	/* Au1000-based eval board */
+#define  MACH_PB1100		1	/* Au1100-based eval board */
+#define  MACH_PB1500		2	/* Au1500-based eval board */
+#define  MACH_DB1000		3       /* Au1000-based eval board */
+#define  MACH_DB1100		4       /* Au1100-based eval board */
+#define  MACH_DB1500		5       /* Au1500-based eval board */
+#define  MACH_XXS1500		6       /* Au1500-based eval board */
+#define  MACH_MTX1		7       /* 4G MTX-1 Au1500-based board */
 
 /*
- * Valid machtype for group Alchemy
+ * Valid machtype for group NEC_VR41XX
+ *
+ * Various NEC-based devices.
+ *
+ * FIXME: MACH_GROUPs should be by _MANUFACTURER_ of * the device, not by
+ *        technical properties, so no new additions to this group.
  */
-#define MACH_PB1000		0	/* Au1000-based eval board */
-#define MACH_PB1100		1	/* Au1100-based eval board */
-#define MACH_PB1500		2	/* Au1500-based eval board */
-#define MACH_DB1000		3       /* Au1000-based eval board */
-#define MACH_DB1100		4       /* Au1100-based eval board */
-#define MACH_DB1500		5       /* Au1500-based eval board */
+#define MACH_GROUP_NEC_VR41XX  19
+#define  MACH_NEC_OSPREY	0	/* Osprey eval board */
+#define  MACH_NEC_EAGLE		1	/* NEC Eagle/Hawk board */
+#define  MACH_ZAO_CAPCELLA	2	/* ZAO Networks Capcella */
+#define  MACH_VICTOR_MPC30X	3	/* Victor MP-C303/304 */
+#define  MACH_IBM_WORKPAD	4	/* IBM WorkPad z50 */
+#define  MACH_CASIO_E55		5	/* CASIO CASSIOPEIA E-10/15/55/65 */
+#define  MACH_TANBAC_TB0226	6	/* TANBAC TB0226 (Mbase) */
+#define  MACH_TANBAC_TB0229	7	/* TANBAC TB0229 (VR4131DIMM) */
+
+#define MACH_GROUP_HP_LJ	20	/* Hewlett Packard LaserJet	*/
+#define  MACH_HP_LASERJET	1
 
 /*
- * Valid machtype for group NEC_VR41XX
+ * Valid machtype for group LASAT
+ */
+#define MACH_GROUP_LASAT       21
+#define  MACH_LASAT_100		1	/* Masquerade II/SP100/SP50/SP25 */
+#define  MACH_LASAT_200		2	/* Masquerade PRO/SP200 */
+
+/*
+ * Valid machtype for group TITAN
  */
-#define MACH_NEC_OSPREY		0	/* Osprey eval board */
-#define MACH_NEC_EAGLE		1	/* NEC Eagle/Hawk board */
-#define MACH_ZAO_CAPCELLA	2	/* ZAO Networks Capcella */
-#define MACH_VICTOR_MPC30X	3	/* Victor MP-C303/304 */
-#define MACH_IBM_WORKPAD	4	/* IBM WorkPad z50 */
-#define MACH_CASIO_E55		5	/* CASIO CASSIOPEIA E-10/15/55/65 */
-#define MACH_TANBAC_TB0226	6	/* TANBAC TB0226 (Mbase) */
-#define MACH_TANBAC_TB0229	7	/* TANBAC TB0229 (VR4131DIMM) */
+#define MACH_GROUP_TITAN       22	/* PMC-Sierra Titan		*/
+#define  MACH_TITAN_YOSEMITE	1	/* PMC-Sierra Yosemite		*/
 
 #define CL_SIZE			(256)
 
@@ -205,7 +226,7 @@ extern unsigned long mips_machgroup;
  */
 struct boot_mem_map {
 	int nr_map;
-	struct {
+	struct boot_mem_map_entry {
 		phys_t addr;	/* start of memory segment */
 		phys_t size;	/* size of memory segment */
 		long type;		/* type of memory segment */
@@ -216,4 +237,15 @@ extern struct boot_mem_map boot_mem_map;
 
 extern void add_memory_region(phys_t start, phys_t size, long type);
 
+extern void prom_init(void);
+
+/*
+ * Initial kernel command line, usually setup by prom_init()
+ */
+extern char arcs_cmdline[CL_SIZE];
+
+/*
+ * Registers a0, a1, a3 and a4 as passed to the kenrel entry by firmware
+ */
+extern unsigned long fw_arg0, fw_arg1, fw_arg2, fw_arg3;
 #endif /* _ASM_BOOTINFO_H */
--- diff/include/asm-mips/bug.h	2003-07-08 09:55:19.000000000 +0100
+++ source/include/asm-mips/bug.h	2004-02-23 13:56:47.000000000 +0000
@@ -5,7 +5,6 @@
 
 #define BUG()								\
 do {									\
-	printk("kernel BUG at %s:%d!\n", __FILE__, __LINE__);		\
 	__asm__ __volatile__("break %0" : : "i" (BRK_BUG));		\
 } while (0)
 #define BUG_ON(condition) do { if (unlikely((condition)!=0)) BUG(); } while(0)
--- diff/include/asm-mips/cache.h	2003-07-08 09:55:19.000000000 +0100
+++ source/include/asm-mips/cache.h	2004-02-23 13:56:47.000000000 +0000
@@ -11,15 +11,11 @@
 
 #include <linux/config.h>
 
-#if defined(CONFIG_CPU_R3000) || defined(CONFIG_CPU_R6000) || \
-    defined(CONFIG_CPU_TX39XX)
-#define L1_CACHE_BYTES		16
-#define L1_CACHE_SHIFT_MAX	 4	/* largest L1 which this arch supports */
-#else
-#define L1_CACHE_BYTES 		32	/* A guess */
-#define L1_CACHE_SHIFT_MAX	 6	/* largest L1 which this arch supports */
-#endif
+#define L1_CACHE_SHIFT		CONFIG_MIPS_L1_CACHE_SHIFT
+#define L1_CACHE_BYTES		(1 << L1_CACHE_SHIFT)
 
+#define L1_CACHE_SHIFT_MAX	6
+#define SMP_CACHE_SHIFT		L1_CACHE_SHIFT
 #define SMP_CACHE_BYTES		L1_CACHE_BYTES
 
 #endif /* _ASM_CACHE_H */
--- diff/include/asm-mips/cacheflush.h	2003-10-09 09:47:34.000000000 +0100
+++ source/include/asm-mips/cacheflush.h	2004-02-23 13:56:47.000000000 +0000
@@ -9,8 +9,6 @@
 #ifndef _ASM_CACHEFLUSH_H
 #define _ASM_CACHEFLUSH_H
 
-#include <linux/config.h>
-
 /* Keep includes the same across arches.  */
 #include <linux/mm.h>
 
@@ -41,16 +39,15 @@ extern void flush_dcache_page(struct pag
 extern void (*flush_icache_page)(struct vm_area_struct *vma,
 	struct page *page);
 extern void (*flush_icache_range)(unsigned long start, unsigned long end);
-#define flush_icache_user_range(vma, page, addr, len)   \
-					flush_icache_page(vma, page)
 #define flush_cache_vmap(start, end)		flush_cache_all()
 #define flush_cache_vunmap(start, end)		flush_cache_all()
 
-#define copy_to_user_page(vma, page, vaddr, dst, src, len) \
-do { memcpy(dst, src, len); \
-     flush_icache_user_range(vma, page, vaddr, len); \
+#define copy_to_user_page(vma, page, vaddr, dst, src, len)		\
+do {									\
+	memcpy(dst, (void *) src, len);					\
+	flush_icache_page(vma, page);					\
 } while (0)
-#define copy_from_user_page(vma, page, vaddr, dst, src, len) \
+#define copy_from_user_page(vma, page, vaddr, dst, src, len)		\
 	memcpy(dst, src, len)
 
 extern void (*flush_cache_sigtramp)(unsigned long addr);
--- diff/include/asm-mips/checksum.h	2003-08-20 14:16:33.000000000 +0100
+++ source/include/asm-mips/checksum.h	2004-02-23 13:56:47.000000000 +0000
@@ -89,56 +89,43 @@ static inline unsigned short int csum_fo
  *	By Jorge Cwik <jorge@laser.satlink.net>, adapted for linux by
  *	Arnt Gulbrandsen.
  */
-static inline unsigned short ip_fast_csum(unsigned char *iph,
-					  unsigned int ihl)
+static inline unsigned short ip_fast_csum(unsigned char *iph, unsigned int ihl)
 {
-	unsigned int dummy, sum;
+	unsigned int *word = (unsigned int *) iph;
+	unsigned int *stop = word + ihl;
+	unsigned int csum;
+	int carry;
+
+	csum = word[0];
+	csum += word[1];
+	carry = (csum < word[1]);
+	csum += carry;
+
+	csum += word[2];
+	carry = (csum < word[2]);
+	csum += carry;
+
+	csum += word[3];
+	carry = (csum < word[3]);
+	csum += carry;
+
+	word += 4;
+	do {
+		csum += *word;
+		carry = (csum < *word);
+		csum += carry;
+		word++;
+	} while (word != stop);
 
-	/*
-	 * This is for 32-bit processors ...  but works just fine for 64-bit
-	 * processors for now ...  XXX
-	 */
-	__asm__ __volatile__(
-	".set\tnoreorder\t\t\t# ip_fast_csum\n\t"
-	".set\tnoat\n\t"
-	"lw\t%0, (%1)\n\t"
-	"subu\t%2, 4\n\t"
-	"sll\t%2, 2\n\t"
-	"lw\t%3, 4(%1)\n\t"
-	"addu\t%2, %1\n\t"
-	"addu\t%0, %3\n\t"
-	"sltu\t$1, %0, %3\n\t"
-	"lw\t%3, 8(%1)\n\t"
-	"addu\t%0, $1\n\t"
-	"addu\t%0, %3\n\t"
-	"sltu\t$1, %0, %3\n\t"
-	"lw\t%3, 12(%1)\n\t"
-	"addu\t%0, $1\n\t"
-	"addu\t%0, %3\n\t"
-	"sltu\t$1, %0, %3\n\t"
-	"addu\t%0, $1\n"
-
-	"1:\tlw\t%3, 16(%1)\n\t"
-	"addiu\t%1, 4\n\t"
-	"addu\t%0, %3\n\t"
-	"sltu\t$1, %0, %3\n\t"
-	"bne\t%2, %1, 1b\n\t"
-	" addu\t%0, $1\n"
-
-	"2:\t.set\tat\n\t"
-	".set\treorder"
-	: "=&r" (sum), "=&r" (iph), "=&r" (ihl), "=&r" (dummy)
-	: "1" (iph), "2" (ihl));
-
-	return csum_fold(sum);
+	return csum_fold(csum);
 }
 
 /*
  * computes the checksum of the TCP/UDP pseudo-header
  * returns a 16-bit checksum, already complemented
  */
-static inline unsigned int csum_tcpudp_nofold(unsigned int saddr,
-	unsigned int daddr, unsigned short len, unsigned short proto,
+static inline unsigned int csum_tcpudp_nofold(unsigned long saddr,
+	unsigned long daddr, unsigned short len, unsigned short proto,
 	unsigned int sum)
 {
 	__asm__(
@@ -168,9 +155,9 @@ static inline unsigned int csum_tcpudp_n
 	: "=r" (sum)
 	: "0" (daddr), "r"(saddr),
 #ifdef __MIPSEL__
-	  "r" ((ntohs(len)<<16)+proto*256),
+	  "r" (((unsigned long)htons(len)<<16) + proto*256),
 #else
-	  "r" (((proto)<<16)+len),
+	  "r" (((unsigned long)(proto)<<16) + len),
 #endif
 	  "r" (sum));
 
--- diff/include/asm-mips/cobalt/cobalt.h	2003-07-08 09:55:19.000000000 +0100
+++ source/include/asm-mips/cobalt/cobalt.h	2004-02-23 13:56:47.000000000 +0000
@@ -6,47 +6,31 @@
  * for more details.
  *
  * Copyright (C) 1997 Cobalt Microserver
- * Copyright (C) 1997 Ralf Baechle
+ * Copyright (C) 1997, 2003 Ralf Baechle
  * Copyright (C) 2001, 2002, 2003 Liam Davies (ldavies@agile.tv)
- *
- */
-#ifndef __ASM_MIPS_COBALT_H
-#define __ASM_MIPS_COBALT_H
-
-/*
- * COBALT interrupt enable bits
- */
-#define COBALT_IE_PCI          (1 << 0)
-#define COBALT_IE_FLOPPY       (1 << 1)
-#define COBALT_IE_KEYBOARD     (1 << 2)
-#define COBALT_IE_SERIAL1      (1 << 3)
-#define COBALT_IE_SERIAL2      (1 << 4)
-#define COBALT_IE_PARALLEL     (1 << 5)
-#define COBALT_IE_GPIO         (1 << 6)
-#define COBALT_IE_RTC          (1 << 7)
-
-/*
- * PCI defines
  */
-#define COBALT_IE_ETHERNET     (1 << 7)
-#define COBALT_IE_SCSI         (1 << 7)
+#ifndef __ASM_COBALT_H
+#define __ASM_COBALT_H
 
 /*
- * COBALT Interrupt Level definitions.
- * These should match the request IRQ id's.
+ * i8259 legacy interrupts used on Cobalt:
+ *
+ *     8  - RTC
+ *     9  - PCI
+ *    14  - IDE0
+ *    15  - IDE1
+ *
+ * CPU IRQs  are 16 ... 23
  */
-#define COBALT_TIMER_IRQ       0
-#define COBALT_KEYBOARD_IRQ    1
-#define COBALT_QUBE_SLOT_IRQ   9
-#define COBALT_ETH0_IRQ        4
-#define COBALT_ETH1_IRQ        13
-#define COBALT_SCC_IRQ         4
-#define COBALT_SERIAL2_IRQ     4
-#define COBALT_PARALLEL_IRQ    5
-#define COBALT_FLOPPY_IRQ      6 /* needs to be consistent with floppy driver! */
-#define COBALT_SCSI_IRQ        7
-#define COBALT_SERIAL_IRQ      7
-#define COBALT_RAQ_SCSI_IRQ    4
+#define COBALT_TIMER_IRQ	18
+#define COBALT_SCC_IRQ          19		/* pre-production has 85C30 */
+#define COBALT_RAQ_SCSI_IRQ	19
+#define COBALT_ETH0_IRQ		19
+#define COBALT_ETH1_IRQ		20
+#define COBALT_SERIAL_IRQ	21
+#define COBALT_SCSI_IRQ         21
+#define COBALT_VIA_IRQ		22		/* Chained to VIA ISA bridge */
+#define COBALT_QUBE_SLOT_IRQ	23
 
 /*
  * PCI configuration space manifest constants.  These are wired into
@@ -78,21 +62,29 @@
 #define COBALT_BRD_ID_QUBE2    0x5
 #define COBALT_BRD_ID_RAQ2     0x6
 
-
 /*
  * Galileo chipset access macros for the Cobalt. The base address for
  * the GT64111 chip is 0x14000000
+ *
+ * Most of this really should go into a separate GT64111 header file.
  */
-#define GT64111_BASE		0x04000000
-#define GALILEO_REG(ofs)	(GT64111_BASE + (ofs))
-
-#define GALILEO_INL(port)	(inl(GALILEO_REG(port)))
-#define GALILEO_OUTL(val, port)	outl(val, GALILEO_REG(port))
+#define GT64111_IO_BASE		0x10000000UL
+#define GT64111_BASE		0x14000000UL
+#define GALILEO_REG(ofs)	(KSEG0 + GT64111_BASE + (unsigned long)(ofs))
+
+#define GALILEO_INL(port)	(*(volatile unsigned int *) GALILEO_REG(port))
+#define GALILEO_OUTL(val, port)						\
+do {									\
+	*(volatile unsigned int *) GALILEO_REG(port) = (port);		\
+} while (0)
 
 #define GALILEO_T0EXP		0x0100
 #define GALILEO_ENTC0		0x01
 #define GALILEO_SELTC0		0x02
 
+#define PCI_CFG_SET(devfn,where)					\
+	GALILEO_OUTL((0x80000000 | (PCI_SLOT (devfn) << 11) |		\
+		(PCI_FUNC (devfn) << 8) | (where)), GT_PCI0_CFGADDR_OFS)
 
-#endif /* __ASM_MIPS_COBALT_H */
 
+#endif /* __ASM_COBALT_H */
--- diff/include/asm-mips/cpu.h	2003-07-08 09:55:19.000000000 +0100
+++ source/include/asm-mips/cpu.h	2004-02-23 13:56:47.000000000 +0000
@@ -7,8 +7,6 @@
 #ifndef _ASM_CPU_H
 #define _ASM_CPU_H
 
-#include <linux/cpu.h>
-
 /* Assigned Company values for bits 23:16 of the PRId Register
    (CP0 register 15, select 0).  As of the MIPS32 and MIPS64 specs from
    MTI, the PRId register is defined in this (backwards compatible)
@@ -59,6 +57,7 @@
 #define PRID_IMP_MAGIC		0x2500
 #define PRID_IMP_RM7000		0x2700
 #define PRID_IMP_NEVADA		0x2800		/* RM5260 ??? */
+#define PRID_IMP_RM9000		0x3400
 #define PRID_IMP_R5432		0x5400
 #define PRID_IMP_R5500		0x5500
 #define PRID_IMP_4KC		0x8000
@@ -66,7 +65,12 @@
 #define PRID_IMP_20KC		0x8200
 #define PRID_IMP_4KEC		0x8400
 #define PRID_IMP_4KSC		0x8600
-
+#define PRID_IMP_25KF		0x8800
+#define PRID_IMP_5KE		0x8900
+#define PRID_IMP_4KECR2		0x9000
+#define PRID_IMP_4KEMPR2	0x9100
+#define PRID_IMP_4KSD		0x9200
+#define PRID_IMP_24K		0x9300
 
 #define PRID_IMP_UNKNOWN	0xff00
 
@@ -101,7 +105,7 @@
 #define PRID_REV_VR4121		0x0060
 #define PRID_REV_VR4122		0x0070
 #define PRID_REV_VR4181A	0x0070	/* Same as VR4122 */
-#define PRID_REV_VR4131		0x0080
+#define PRID_REV_VR4130		0x0080
 
 /*
  * FPU implementation/revision register (CP1 control register 0).
@@ -168,7 +172,12 @@
 #define CPU_VR4181A		51
 #define CPU_AU1100		52
 #define CPU_SR71000		53
-#define CPU_LAST		53
+#define CPU_RM9000		54
+#define CPU_25KF		55
+#define CPU_VR4133		56
+#define CPU_AU1550		57
+#define CPU_24K			58
+#define CPU_LAST		58
 
 /*
  * ISA Level encodings
@@ -201,11 +210,13 @@
 #define MIPS_CPU_MIPS16		0x00000100 /* code compression */
 #define MIPS_CPU_DIVEC		0x00000200 /* dedicated interrupt vector */
 #define MIPS_CPU_VCE		0x00000400 /* virt. coherence conflict possible */
-#define MIPS_CPU_CACHE_CDEX	0x00000800 /* Create_Dirty_Exclusive CACHE op */
-#define MIPS_CPU_MCHECK		0x00001000 /* Machine check exception */
-#define MIPS_CPU_EJTAG		0x00002000 /* EJTAG exception */
-#define MIPS_CPU_NOFPUEX	0x00004000 /* no FPU exception */
-#define MIPS_CPU_LLSC		0x00008000 /* CPU has ll/sc instructions */
-#define MIPS_CPU_SUBSET_CACHES	0x00010000 /* P-cache subset enforced */
+#define MIPS_CPU_CACHE_CDEX_P	0x00000800 /* Create_Dirty_Exclusive CACHE op */
+#define MIPS_CPU_CACHE_CDEX_S	0x00001000 /* ... same for seconary cache ... */
+#define MIPS_CPU_MCHECK		0x00002000 /* Machine check exception */
+#define MIPS_CPU_EJTAG		0x00004000 /* EJTAG exception */
+#define MIPS_CPU_NOFPUEX	0x00008000 /* no FPU exception */
+#define MIPS_CPU_LLSC		0x00010000 /* CPU has ll/sc instructions */
+#define MIPS_CPU_SUBSET_CACHES	0x00020000 /* P-cache subset enforced */
+#define MIPS_CPU_PREFETCH	0x00040000 /* CPU has usable prefetch */
 
 #endif /* _ASM_CPU_H */
--- diff/include/asm-mips/dec/ecc.h	2003-07-08 09:55:19.000000000 +0100
+++ source/include/asm-mips/dec/ecc.h	2004-02-23 13:56:47.000000000 +0000
@@ -42,10 +42,14 @@
 
 
 #ifndef __ASSEMBLY__
+
+#include <linux/interrupt.h>
+
 struct pt_regs;
+
 extern void dec_ecc_be_init(void);
 extern int dec_ecc_be_handler(struct pt_regs *regs, int is_fixup);
-extern void dec_ecc_be_interrupt(int irq, void *dev_id, struct pt_regs *regs);
+extern irqreturn_t dec_ecc_be_interrupt(int irq, void *dev_id, struct pt_regs *regs);
 #endif
 
 #endif /* __ASM_MIPS_DEC_ECC_H */
--- diff/include/asm-mips/dec/kn05.h	2003-07-08 09:55:19.000000000 +0100
+++ source/include/asm-mips/dec/kn05.h	2004-02-23 13:56:47.000000000 +0000
@@ -50,6 +50,7 @@
  */
 #define KN05_MB_INT_TC		(1<<0)		/* TURBOchannel? */
 #define KN05_MB_INT_RTC		(1<<1)		/* RTC? */
+#define KN05_MB_INT_MT		(1<<3)		/* ??? */
 
 /*
  * Bits for the MB control & status register.
--- diff/include/asm-mips/dec/prom.h	2003-08-20 14:16:33.000000000 +0100
+++ source/include/asm-mips/dec/prom.h	2004-02-23 13:56:47.000000000 +0000
@@ -15,6 +15,7 @@
 #ifndef _ASM_DEC_PROM_H
 #define _ASM_DEC_PROM_H
 
+#include <linux/config.h>
 #include <linux/types.h>
 
 #include <asm/addrspace.h>
@@ -166,4 +167,7 @@ extern void prom_meminit(u32);
 extern void prom_identify_arch(u32);
 extern void prom_init_cmdline(s32, s32 *, u32);
 
+extern void register_prom_console(void);
+extern void unregister_prom_console(void);
+
 #endif /* _ASM_DEC_PROM_H */
--- diff/include/asm-mips/dma-mapping.h	2004-02-09 10:36:12.000000000 +0000
+++ source/include/asm-mips/dma-mapping.h	2004-02-23 13:56:47.000000000 +0000
@@ -1,10 +1,15 @@
 #ifndef _ASM_DMA_MAPPING_H
 #define _ASM_DMA_MAPPING_H
 
+#include <linux/device.h>
+#include <asm/scatterlist.h>
 #include <asm/cache.h>
 
-#define dma_alloc_noncoherent(d, s, h, f) dma_alloc_coherent(d, s, h, f)
-#define dma_free_noncoherent(d, s, v, h) dma_free_coherent(d, s, v, h)
+void *dma_alloc_noncoherent(struct device *dev, size_t size,
+			   dma_addr_t *dma_handle, int flag);
+
+void dma_free_noncoherent(struct device *dev, size_t size,
+			 void *vaddr, dma_addr_t dma_handle);
 
 void *dma_alloc_coherent(struct device *dev, size_t size,
 			   dma_addr_t *dma_handle, int flag);
@@ -12,8 +17,6 @@ void *dma_alloc_coherent(struct device *
 void dma_free_coherent(struct device *dev, size_t size,
 			 void *vaddr, dma_addr_t dma_handle);
 
-#ifdef CONFIG_MAPPED_DMA_IO
-
 extern dma_addr_t dma_map_single(struct device *dev, void *ptr, size_t size,
 	enum dma_data_direction direction);
 extern void dma_unmap_single(struct device *dev, dma_addr_t dma_addr,
@@ -33,162 +36,7 @@ extern void dma_sync_single_range(struct
 extern void dma_sync_sg(struct device *dev, struct scatterlist *sg, int nelems,
 	enum dma_data_direction direction);
 
-#else
-
-static inline dma_addr_t
-dma_map_single(struct device *dev, void *ptr, size_t size,
-	       enum dma_data_direction direction)
-{
-	unsigned long addr = (unsigned long) ptr;
-
-	BUG_ON(direction == DMA_NONE);
-
-	dma_cache_wback_inv(addr, size);
-
-	return bus_to_baddr(hwdev->bus, __pa(ptr));
-}
-
-static inline void
-dma_unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size,
-		 enum dma_data_direction direction)
-{
-	BUG_ON(direction == DMA_NONE);
-
-	if (direction != DMA_TO_DEVICE) {
-		unsigned long addr;
-
-		addr = baddr_to_bus(hwdev->bus, dma_addr) + PAGE_OFFSET;
-		dma_cache_wback_inv(addr, size);
-	}
-}
-
-static inline int
-dma_map_sg(struct device *dev, struct scatterlist *sg, int nents,
-	   enum dma_data_direction direction)
-{
-	int i;
-
-	BUG_ON(direction == DMA_NONE);
-
-	for (i = 0; i < nents; i++, sg++) {
-		unsigned long addr;
- 
-		addr = (unsigned long) page_address(sg->page);
-		if (addr)
-		        dma_cache_wback_inv(addr + sg->offset, sg->length);
-		sg->dma_address = (dma_addr_t) bus_to_baddr(hwdev->bus,
-			page_to_phys(sg->page) + sg->offset);
-	}
-
-	return nents;
-}
-
-static inline dma_addr_t
-dma_map_page(struct device *dev, struct page *page, unsigned long offset,
-	     size_t size, enum dma_data_direction direction)
-{
-	unsigned long addr;
-
-	BUG_ON(direction == DMA_NONE);
-	addr = (unsigned long) page_address(page) + offset;
-	dma_cache_wback_inv(addr, size);
-
-	return bus_to_baddr(hwdev->bus, page_to_phys(page) + offset);
-}
-
-static inline void
-dma_unmap_page(struct device *dev, dma_addr_t dma_address, size_t size,
-	       enum dma_data_direction direction)
-{
-	BUG_ON(direction == DMA_NONE);
-
-	if (direction != DMA_TO_DEVICE) {
-		unsigned long addr;
-
-		addr = baddr_to_bus(hwdev->bus, dma_address) + PAGE_OFFSET;
-		dma_cache_wback_inv(addr, size);
-	}
-}
-
-static inline void
-dma_unmap_sg(struct device *dev, struct scatterlist *sg, int nhwentries,
-	     enum dma_data_direction direction)
-{
-	int i;
-
-	BUG_ON(direction == DMA_NONE);
-
-	if (direction == DMA_TO_DEVICE)
-		return;
-
-	for (i = 0; i < nhwentries; i++, sg++) {
-		unsigned long addr;
-
-		BUG_ON(!sg->page);
-
-		addr = (unsigned long) page_address(sg->page);
-		if (addr)
-			dma_cache_wback_inv(addr + sg->offset, sg->length);
-	}
-}
-
-static inline void
-dma_sync_single(struct device *dev, dma_addr_t dma_handle, size_t size,
-		enum dma_data_direction direction)
-{
-	unsigned long addr;
- 
-	BUG_ON(direction == DMA_NONE);
- 
-	addr = baddr_to_bus(hwdev->bus, dma_handle) + PAGE_OFFSET;
-	dma_cache_wback_inv(addr, size);
-}
-
-static inline void
-dma_sync_single_range(struct device *dev, dma_addr_t dma_handle,
-		      unsigned long offset, size_t size,
-		      enum dma_data_direction direction)
-{
-	unsigned long addr;
-
-	BUG_ON(direction == DMA_NONE);
-
-	addr = baddr_to_bus(hwdev->bus, dma_handle) + PAGE_OFFSET;
-	dma_cache_wback_inv(addr, size);
-}
-
-static inline void
-dma_sync_sg(struct device *dev, struct scatterlist *sg, int nelems,
-		 enum dma_data_direction direction)
-{
-#ifdef CONFIG_NONCOHERENT_IO
-	int i;
-#endif
- 
-	BUG_ON(direction == DMA_NONE);
- 
-	/* Make sure that gcc doesn't leave the empty loop body.  */
-#ifdef CONFIG_NONCOHERENT_IO
-	for (i = 0; i < nelems; i++, sg++)
-		dma_cache_wback_inv((unsigned long)page_address(sg->page),
-		                    sg->length);
-#endif
-}
-#endif /* CONFIG_MAPPED_DMA_IO  */
-
-static inline int
-dma_supported(struct device *dev, u64 mask)
-{
-	/*
-	 * we fall back to GFP_DMA when the mask isn't all 1s,
-	 * so we can't guarantee allocations that must be
-	 * within a tighter range than GFP_DMA..
-	 */
-	if (mask < 0x00ffffff)
-		return 0;
-
-	return 1;
-}
+extern int dma_supported(struct device *dev, u64 mask);
 
 static inline int
 dma_set_mask(struct device *dev, u64 mask)
@@ -208,17 +56,9 @@ dma_get_cache_alignment(void)
 	return 128;
 }
 
-#ifdef CONFIG_NONCOHERENT_IO
-#define dma_is_consistent(d)	(0)
-#else
-#define dma_is_consistent(d)	(1)
-#endif
-
-static inline void
-dma_cache_sync(void *vaddr, size_t size,
-	       enum dma_data_direction direction)
-{
-	dma_cache_wback_inv((unsigned long)vaddr, size);
-}
+extern int dma_is_consistent(dma_addr_t dma_addr);
+
+extern void dma_cache_sync(void *vaddr, size_t size,
+	       enum dma_data_direction direction);
 
 #endif /* _ASM_DMA_MAPPING_H */
--- diff/include/asm-mips/ds1286.h	2003-07-08 09:55:19.000000000 +0100
+++ source/include/asm-mips/ds1286.h	2004-02-23 13:56:47.000000000 +0000
@@ -3,57 +3,13 @@
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  *
- * mc146818rtc.h - register definitions for the Real-Time-Clock / CMOS RAM
- * Copyright Torsten Duwe <duwe@informatik.uni-erlangen.de> 1993
- * derived from Data Sheet, Copyright Motorola 1984 (!).
- * It was written to be part of the Linux operating system.
+ * Machine dependent access functions for RTC registers.
  *
- * Copyright (C) 1998, 1999 Ralf Baechle
+ * Copyright (C) 2003 Ralf Baechle (ralf@linux-mips.org)
  */
-#ifndef _ASM_DS1286_h
-#define _ASM_DS1286_h
+#ifndef _ASM_DS1286_H
+#define _ASM_DS1286_H
 
-#include <asm/mc146818rtc.h>
+#include <ds1286.h>
 
-/**********************************************************************
- * register summary
- **********************************************************************/
-#define RTC_HUNDREDTH_SECOND	0
-#define RTC_SECONDS		1
-#define RTC_MINUTES		2
-#define RTC_MINUTES_ALARM	3
-#define RTC_HOURS		4
-#define RTC_HOURS_ALARM		5
-#define RTC_DAY			6
-#define RTC_DAY_ALARM		7
-#define RTC_DATE		8
-#define RTC_MONTH		9
-#define RTC_YEAR		10
-#define RTC_CMD			11
-#define RTC_WHSEC		12
-#define RTC_WSEC		13
-#define RTC_UNUSED		14
-
-/* RTC_*_alarm is always true if 2 MSBs are set */
-# define RTC_ALARM_DONT_CARE 	0xC0
-
-
-/*
- * Bits in the month register
- */
-#define RTC_EOSC		0x80
-#define RTC_ESQW		0x40
-
-/*
- * Bits in the Command register
- */
-#define RTC_TDF			0x01
-#define RTC_WAF			0x02
-#define RTC_TDM			0x04
-#define RTC_WAM			0x08
-#define RTC_PU_LVL		0x10
-#define RTC_IBH_LO		0x20
-#define RTC_IPSW		0x40
-#define RTC_TE			0x80
-
-#endif /* _ASM_DS1286_h */
+#endif /* _ASM_DS1286_H */
--- diff/include/asm-mips/elf.h	2003-08-20 14:16:33.000000000 +0100
+++ source/include/asm-mips/elf.h	2004-02-23 13:56:47.000000000 +0000
@@ -124,6 +124,7 @@ typedef double elf_fpreg_t;
 typedef elf_fpreg_t elf_fpregset_t[ELF_NFPREG];
 
 #ifdef CONFIG_MIPS32
+
 /*
  * This is used to ensure we don't load something for the wrong architecture.
  */
@@ -134,7 +135,12 @@ typedef elf_fpreg_t elf_fpregset_t[ELF_N
 									\
 	if (__h->e_machine != EM_MIPS)					\
 		__res = 0;						\
-	if (__h->e_ident[EI_CLASS] != ELFCLASS64) 			\
+	if (__h->e_ident[EI_CLASS] != ELFCLASS32)			\
+		__res = 0;						\
+	if ((__h->e_flags & EF_MIPS_ABI2) != 0)				\
+		__res = 0;						\
+	if (((__h->e_flags & EF_MIPS_ABI) != 0) &&			\
+	    ((__h->e_flags & EF_MIPS_ABI) != EF_MIPS_ABI_O32))		\
 		__res = 0;						\
 									\
 	__res;								\
@@ -148,7 +154,6 @@ typedef elf_fpreg_t elf_fpregset_t[ELF_N
 #endif /* CONFIG_MIPS32 */
 
 #ifdef CONFIG_MIPS64
-
 /*
  * This is used to ensure we don't load something for the wrong architecture.
  */
@@ -159,12 +164,7 @@ typedef elf_fpreg_t elf_fpregset_t[ELF_N
 									\
 	if (__h->e_machine != EM_MIPS)					\
 		__res = 0;						\
-	if (__h->e_ident[EI_CLASS] != ELFCLASS32)			\
-		__res = 0;						\
-	if ((__h->e_flags & EF_MIPS_ABI2) != 0)				\
-		__res = 0;						\
-	if (((__h->e_flags & EF_MIPS_ABI) != 0) &&			\
-	    ((__h->e_flags & EF_MIPS_ABI) != EF_MIPS_ABI_O32))		\
+	if (__h->e_ident[EI_CLASS] != ELFCLASS64) 			\
 		__res = 0;						\
 									\
 	__res;								\
@@ -228,7 +228,7 @@ do {	current->thread.mflags &= ~MF_ABI_M
 #define irix_elf_check_arch(hdr)	((hdr)->e_machine == EM_MIPS)
 
 #define USE_ELF_CORE_DUMP
-#define ELF_EXEC_PAGESIZE	4096
+#define ELF_EXEC_PAGESIZE	PAGE_SIZE
 
 #define ELF_CORE_COPY_REGS(_dest,_regs)				\
 	memcpy((char *) &_dest, (char *) _regs,			\
--- diff/include/asm-mips/floppy.h	2003-07-08 09:55:19.000000000 +0100
+++ source/include/asm-mips/floppy.h	2004-02-23 13:56:47.000000000 +0000
@@ -10,57 +10,10 @@
 #ifndef _ASM_FLOPPY_H
 #define _ASM_FLOPPY_H
 
-struct fd_ops {
-	unsigned char (*fd_inb)(unsigned int port);
-	void (*fd_outb)(unsigned char value, unsigned int port);
-
-	/*
-	 * How to access the floppy DMA functions.
-	 */
-	void (*fd_enable_dma)(int channel);
-	void (*fd_disable_dma)(int channel);
-	int (*fd_request_dma)(int channel);
-	void (*fd_free_dma)(int channel);
-	void (*fd_clear_dma_ff)(int channel);
-	void (*fd_set_dma_mode)(int channel, char mode);
-	void (*fd_set_dma_addr)(int channel, unsigned int a);
-	void (*fd_set_dma_count)(int channel, unsigned int count);
-	int (*fd_get_dma_residue)(int channel);
-	void (*fd_enable_irq)(int irq);
-	void (*fd_disable_irq)(int irq);
-	unsigned long (*fd_getfdaddr1)(void);
-	unsigned long (*fd_dma_mem_alloc)(unsigned long size);
-	void (*fd_dma_mem_free)(unsigned long addr, unsigned long size);
-	unsigned long (*fd_drive_type)(unsigned long);
-};
-
-extern struct fd_ops *fd_ops;
-
-#define fd_inb(port)		fd_ops->fd_inb(port)
-#define fd_outb(value,port)	fd_ops->fd_outb(value,port)
-
-#define fd_enable_dma()		fd_ops->fd_enable_dma(FLOPPY_DMA)
-#define fd_disable_dma()	fd_ops->fd_disable_dma(FLOPPY_DMA)
-#define fd_request_dma()	fd_ops->fd_request_dma(FLOPPY_DMA)
-#define fd_free_dma()		fd_ops->fd_free_dma(FLOPPY_DMA)
-#define fd_clear_dma_ff()	fd_ops->fd_clear_dma_ff(FLOPPY_DMA)
-#define fd_set_dma_mode(mode)	fd_ops->fd_set_dma_mode(FLOPPY_DMA, mode)
-#define fd_set_dma_addr(addr)	fd_ops->fd_set_dma_addr(FLOPPY_DMA, \
-				                       isa_virt_to_bus(addr))
-#define fd_set_dma_count(count)	fd_ops->fd_set_dma_count(FLOPPY_DMA,count)
-#define fd_get_dma_residue()	fd_ops->fd_get_dma_residue(FLOPPY_DMA)
-
-#define fd_enable_irq()		fd_ops->fd_enable_irq(FLOPPY_IRQ)
-#define fd_disable_irq()	fd_ops->fd_disable_irq(FLOPPY_IRQ)
-#define fd_request_irq()	request_irq(FLOPPY_IRQ, floppy_interrupt, \
-				            SA_INTERRUPT | SA_SAMPLE_RANDOM, \
-				            "floppy", NULL)
-#define fd_free_irq()		free_irq(FLOPPY_IRQ, NULL);
-#define fd_dma_mem_alloc(size)	fd_ops->fd_dma_mem_alloc(size)
-#define fd_dma_mem_free(mem,size) fd_ops->fd_dma_mem_free(mem,size)
-#define fd_drive_type(n)	fd_ops->fd_drive_type(n)
-#define fd_cacheflush(addr,size)	\
-			dma_cache_wback_inv((unsigned long)(addr),(size))
+static inline void fd_cacheflush(char * addr, long size)
+{
+	dma_cache_wback_inv((unsigned long)addr,size);
+}
 
 #define MAX_BUFFER_SECTORS 24
 
@@ -71,10 +24,10 @@ extern struct fd_ops *fd_ops;
  * FIXME: This information should come from the ARC configuration tree
  *        or whereever a particular machine has stored this ...
  */
-#define FLOPPY0_TYPE 			fd_drive_type(0)
-#define FLOPPY1_TYPE			fd_drive_type(1)
+#define FLOPPY0_TYPE 		fd_drive_type(0)
+#define FLOPPY1_TYPE		fd_drive_type(1)
 
-#define FDC1			fd_ops->fd_getfdaddr1();
+#define FDC1			fd_getfdaddr1();
 
 #define N_FDC 1			/* do you *really* want a second controller? */
 #define N_DRIVE 8
@@ -98,4 +51,6 @@ extern struct fd_ops *fd_ops;
 
 #define EXTRA_FLOPPY_PARAMS
 
+#include <floppy.h>
+
 #endif /* _ASM_FLOPPY_H */
--- diff/include/asm-mips/fpu.h	2003-08-20 14:16:33.000000000 +0100
+++ source/include/asm-mips/fpu.h	2004-02-23 13:56:47.000000000 +0000
@@ -16,6 +16,7 @@
 
 #include <asm/mipsregs.h>
 #include <asm/cpu.h>
+#include <asm/cpu-features.h>
 #include <asm/bitops.h>
 #include <asm/processor.h>
 #include <asm/current.h>
--- diff/include/asm-mips/galileo-boards/ev96100.h	2003-07-08 09:55:19.000000000 +0100
+++ source/include/asm-mips/galileo-boards/ev96100.h	2004-02-23 13:56:47.000000000 +0000
@@ -9,47 +9,47 @@
 /*
  *   GT64120 config space base address
  */
-#define GT64120_BASE    (KSEG1ADDR(0x14000000))
-#define MIPS_GT_BASE    GT64120_BASE
+#define GT64120_BASE	(KSEG1ADDR(0x14000000))
+#define MIPS_GT_BASE	GT64120_BASE
 
 /*
  *   PCI Bus allocation
  */
-#define GT_PCI_MEM_BASE    0x12000000
-#define GT_PCI_MEM_SIZE    0x02000000
-#define GT_PCI_IO_BASE     0x10000000
-#define GT_PCI_IO_SIZE     0x02000000
+#define GT_PCI_MEM_BASE    0x12000000UL
+#define GT_PCI_MEM_SIZE    0x02000000UL
+#define GT_PCI_IO_BASE     0x10000000UL
+#define GT_PCI_IO_SIZE     0x02000000UL
 #define GT_ISA_IO_BASE     PCI_IO_BASE
 
 /*
  *   Duart I/O ports.
  */
-#define EV96100_COM1_BASE_ADDR  (0xBD000000 + 0x20)
-#define EV96100_COM2_BASE_ADDR  (0xBD000000 + 0x00)
+#define EV96100_COM1_BASE_ADDR 	(0xBD000000 + 0x20)
+#define EV96100_COM2_BASE_ADDR	(0xBD000000 + 0x00)
 
 
 /*
  *   EV96100 interrupt controller register base.
  */
-#define EV96100_ICTRL_REGS_BASE   (KSEG1ADDR(0x1f000000))
+#define EV96100_ICTRL_REGS_BASE	(KSEG1ADDR(0x1f000000))
 
 /*
  *   EV96100 UART register base.
  */
-#define EV96100_UART0_REGS_BASE    EV96100_COM1_BASE_ADDR
-#define EV96100_UART1_REGS_BASE    EV96100_COM2_BASE_ADDR
-#define EV96100_BASE_BAUD ( 3686400 / 16 )
+#define EV96100_UART0_REGS_BASE	EV96100_COM1_BASE_ADDR
+#define EV96100_UART1_REGS_BASE	EV96100_COM2_BASE_ADDR
+#define EV96100_BASE_BAUD	( 3686400 / 16 )
 
 
 /*
  * Because of an error/peculiarity in the Galileo chip, we need to swap the
  * bytes when running bigendian.
  */
-
-#define GT_WRITE(ofs, data)  \
-             *(volatile u32 *)(MIPS_GT_BASE+ofs) = cpu_to_le32(data)
-#define GT_READ(ofs, data)   \
-             data = le32_to_cpu(*(volatile u32 *)(MIPS_GT_BASE+ofs))
-
+#define __GT_READ(ofs)							\
+	(*(volatile u32 *)(GT64120_BASE+(ofs)))
+#define __GT_WRITE(ofs, data)						\
+	do { *(volatile u32 *)(GT64120_BASE+(ofs)) = (data); } while (0)
+#define GT_READ(ofs)		le32_to_cpu(__GT_READ(ofs))
+#define GT_WRITE(ofs, data)	__GT_WRITE(ofs, cpu_to_le32(data))
 
 #endif /* !(_MIPS_EV96100_H) */
--- diff/include/asm-mips/galileo-boards/gt96100.h	2003-07-08 09:55:19.000000000 +0100
+++ source/include/asm-mips/galileo-boards/gt96100.h	2004-02-23 13:56:47.000000000 +0000
@@ -3,8 +3,6 @@
  * Author: MontaVista Software, Inc.
  *         	stevel@mvista.com or source@mvista.com
  *
- * ########################################################################
- *
  *  This program is free software; you can distribute it and/or modify it
  *  under the terms of the GNU General Public License (Version 2) as
  *  published by the Free Software Foundation.
@@ -18,10 +16,7 @@
  *  with this program; if not, write to the Free Software Foundation, Inc.,
  *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
  *
- * ########################################################################
- *
  * Register offsets of the MIPS GT96100 Advanced Communication Controller.
- *
  */
 #ifndef _GT96100_H
 #define _GT96100_H
--- diff/include/asm-mips/gdb-stub.h	2003-08-20 14:16:33.000000000 +0100
+++ source/include/asm-mips/gdb-stub.h	2004-02-23 13:56:47.000000000 +0000
@@ -22,11 +22,11 @@
  * Stack layout for the GDB exception handler
  * Derived from the stack layout described in asm-mips/stackframe.h
  *
- * The first PTRSIZE*5 bytes are argument save space for C subroutines.
+ * The first PTRSIZE*6 bytes are argument save space for C subroutines.
  */
 #define NUMREGS			90
 
-#define GDB_FR_REG0		(PTRSIZE*5)			/* 0 */
+#define GDB_FR_REG0		(PTRSIZE*6)			/* 0 */
 #define GDB_FR_REG1		((GDB_FR_REG0) + LONGSIZE)	/* 1 */
 #define GDB_FR_REG2		((GDB_FR_REG1) + LONGSIZE)	/* 2 */
 #define GDB_FR_REG3		((GDB_FR_REG2) + LONGSIZE)	/* 3 */
@@ -143,9 +143,9 @@
 struct gdb_regs {
 	/*
 	 * Pad bytes for argument save space on the stack
-	 * 20/40 Bytes for 32/64 bit code
+	 * 24/48 Bytes for 32/64 bit code
 	 */
-	unsigned long pad0[5];
+	unsigned long pad0[6];
 
 	/*
 	 * saved main processor registers
--- diff/include/asm-mips/gt64120.h	2003-07-08 09:55:19.000000000 +0100
+++ source/include/asm-mips/gt64120.h	2004-02-23 13:56:47.000000000 +0000
@@ -18,6 +18,10 @@
 #ifndef _ASM_GT64120_H
 #define _ASM_GT64120_H
 
+#include <linux/config.h>
+#include <asm/addrspace.h>
+#include <asm/byteorder.h>
+
 #define MSK(n)                    ((1 << (n)) - 1)
 
 /*
@@ -391,9 +395,36 @@
 /*
  *  Misc
  */
-#define GT_DEF_BASE		0x14000000
-#define GT_DEF_PCI0_MEM0_BASE	0x12000000
+#define GT_DEF_PCI0_IO_BASE	0x10000000UL
+#define GT_DEF_PCI0_IO_SIZE	0x02000000UL
+#define GT_DEF_PCI0_MEM0_BASE	0x12000000UL
+#define GT_DEF_PCI0_MEM0_SIZE	0x02000000UL
+#define GT_DEF_BASE		0x14000000UL
+
 #define GT_MAX_BANKSIZE		(256 * 1024 * 1024)   /* Max 256MB bank */
 #define GT_LATTIM_MIN    	6		      /* Minimum lat	*/
 
+/*
+ * The gt64120_dep.h file must define the following macros
+ *
+ *   GT_READ(ofs, data_pointer)
+ *   GT_WRITE(ofs, data)           - read/write GT64120 registers in 32bit
+ *
+ *   TIMER 	- gt64120 timer irq, temporary solution until
+ *		  full gt64120 cascade interrupt support is in place
+ */
+
+#include <mach-gt64120.h>
+
+/*
+ * Because of an error/peculiarity in the Galileo chip, we need to swap the
+ * bytes when running bigendian.  We also provide non-swapping versions.
+ */
+#define __GT_READ(ofs)							\
+	(*(volatile u32 *)(GT64120_BASE+(ofs)))
+#define __GT_WRITE(ofs, data)						\
+	do { *(volatile u32 *)(GT64120_BASE+(ofs)) = (data); } while (0)
+#define GT_READ(ofs)		le32_to_cpu(__GT_READ(ofs))
+#define GT_WRITE(ofs, data)	__GT_WRITE(ofs, cpu_to_le32(data))
+
 #endif /* _ASM_GT64120_H */
--- diff/include/asm-mips/hardirq.h	2003-08-20 14:16:33.000000000 +0100
+++ source/include/asm-mips/hardirq.h	2004-02-23 13:56:47.000000000 +0000
@@ -79,7 +79,8 @@ typedef struct {
 
 #define irq_enter()		(preempt_count() += HARDIRQ_OFFSET)
 
-#if CONFIG_PREEMPT
+#ifdef CONFIG_PREEMPT
+# include <linux/smp_lock.h>
 # define in_atomic()	(preempt_count() != kernel_locked())
 # define IRQ_EXIT_OFFSET (HARDIRQ_OFFSET-1)
 #else
--- diff/include/asm-mips/highmem.h	2003-10-09 09:47:34.000000000 +0100
+++ source/include/asm-mips/highmem.h	2004-02-23 13:56:47.000000000 +0000
@@ -19,7 +19,6 @@
 
 #ifdef __KERNEL__
 
-#include <linux/config.h>
 #include <linux/init.h>
 #include <linux/interrupt.h>
 #include <asm/kmap_types.h>
--- diff/include/asm-mips/hw_irq.h	2003-08-20 14:16:33.000000000 +0100
+++ source/include/asm-mips/hw_irq.h	2004-02-23 13:56:47.000000000 +0000
@@ -19,8 +19,6 @@ extern int i8259A_irq_pending(unsigned i
 extern void make_8259A_irq(unsigned int irq);
 extern void init_8259A(int aeoi);
 
-#include <asm/atomic.h>
-
 extern atomic_t irq_err_count;
 
 /* This may not be apropriate for all machines, we'll see ...  */
--- diff/include/asm-mips/i8259.h	2003-08-20 14:16:33.000000000 +0100
+++ source/include/asm-mips/i8259.h	2004-02-23 13:56:47.000000000 +0000
@@ -4,6 +4,7 @@
  *	i8259A interrupt definitions.
  *
  *	Copyright (C) 2003  Maciej W. Rozycki
+ *	Copyright (C) 2003  Ralf Baechle <ralf@linux-mips.org>
  *
  *	This program is free software; you can redistribute it and/or
  *	modify it under the terms of the GNU General Public License
@@ -13,11 +14,54 @@
 #ifndef _ASM_I8259_H
 #define _ASM_I8259_H
 
+#include <linux/compiler.h>
 #include <linux/spinlock.h>
 
 #include <asm/io.h>
-#include <asm/system.h>
+
+extern spinlock_t i8259A_lock;
 
 extern void init_i8259_irqs(void);
 
+/*
+ * Do the traditional i8259 interrupt polling thing.  This is for the few
+ * cases where no better interrupt acknowledge method is available and we
+ * absolutely must touch the i8259.
+ */
+static inline int i8259_irq(void)
+{
+	int irq;
+
+	spin_lock(&i8259A_lock);
+
+	/* Perform an interrupt acknowledge cycle on controller 1. */
+	outb(0x0C, 0x20);		/* prepare for poll */
+	irq = inb(0x20) & 7;
+	if (irq == 2) {
+		/*
+		 * Interrupt is cascaded so perform interrupt
+		 * acknowledge on controller 2.
+		 */
+		outb(0x0C, 0xA0);		/* prepare for poll */
+		irq = (inb(0xA0) & 7) + 8;
+	}
+
+	if (unlikely(irq == 7)) {
+		/*
+		 * This may be a spurious interrupt.
+		 *
+		 * Read the interrupt status register (ISR). If the most
+		 * significant bit is not set then there is no valid
+		 * interrupt.
+		 */
+		outb(0x0B, 0x20);		/* ISR register */
+		if(~inb(0x20) & 0x80)
+			irq = -1;
+	}
+
+	spin_unlock(&i8259A_lock);
+
+	return irq;
+}
+
 #endif /* _ASM_I8259_H */
--- diff/include/asm-mips/ide.h	2003-07-08 09:55:19.000000000 +0100
+++ source/include/asm-mips/ide.h	2004-02-23 13:56:47.000000000 +0000
@@ -13,56 +13,7 @@
 
 #ifdef __KERNEL__
 
-#include <linux/config.h>
-#include <asm/byteorder.h>
-#include <asm/io.h>
-
-#ifndef MAX_HWIFS
-# ifdef CONFIG_PCI
-#define MAX_HWIFS	10
-# else
-#define MAX_HWIFS	6
-# endif
-#endif
-
-struct ide_ops {
-	int (*ide_default_irq)(ide_ioreg_t base);
-	ide_ioreg_t (*ide_default_io_base)(int index);
-	void (*ide_init_hwif_ports)(hw_regs_t *hw, ide_ioreg_t data_port,
-	                            ide_ioreg_t ctrl_port, int *irq);
-};
-
-extern struct ide_ops *ide_ops;
-
-static __inline__ int ide_default_irq(ide_ioreg_t base)
-{
-	return ide_ops->ide_default_irq(base);
-}
-
-static __inline__ ide_ioreg_t ide_default_io_base(int index)
-{
-	return ide_ops->ide_default_io_base(index);
-}
-
-static inline void ide_init_hwif_ports(hw_regs_t *hw, ide_ioreg_t data_port,
-                                       ide_ioreg_t ctrl_port, int *irq)
-{
-	ide_ops->ide_init_hwif_ports(hw, data_port, ctrl_port, irq);
-}
-
-static __inline__ void ide_init_default_hwifs(void)
-{
-#ifndef CONFIG_PCI
-	hw_regs_t hw;
-	int index;
-
-	for(index = 0; index < MAX_HWIFS; index++) {
-		ide_init_hwif_ports(&hw, ide_default_io_base(index), 0, NULL);
-		hw.irq = ide_default_irq(ide_default_io_base(index));
-		ide_register_hw(&hw, NULL);
-	}
-#endif
-}
+#include <ide.h>
 
 #define __ide_mm_insw   ide_insw
 #define __ide_mm_insl   ide_insl
--- diff/include/asm-mips/io.h	2004-02-18 08:54:12.000000000 +0000
+++ source/include/asm-mips/io.h	2004-02-23 13:56:47.000000000 +0000
@@ -14,19 +14,13 @@
 #include <linux/types.h>
 
 #include <asm/addrspace.h>
+#include <asm/cpu.h>
+#include <asm/cpu-features.h>
 #include <asm/page.h>
 #include <asm/pgtable-bits.h>
+#include <asm/processor.h>
 #include <asm/byteorder.h>
-
-#ifdef CONFIG_SGI_IP27
-extern unsigned long bus_to_baddr[256];
-
-#define bus_to_baddr(bus, addr)	(bus_to_baddr[(bus)->number] + (addr))
-#define baddr_to_bus(bus, addr)	((addr) - bus_to_baddr[(bus)->number])
-#else
-#define bus_to_baddr(bus, addr)	(addr)
-#define baddr_to_bus(bus, addr)	(addr)
-#endif
+#include <mangle-port.h>
 
 /*
  * Slowdown I/O port space accesses for antique hardware.
@@ -177,6 +171,24 @@ extern unsigned long isa_slot_offset;
 extern void * __ioremap(phys_t offset, phys_t size, unsigned long flags);
 extern void __iounmap(void *addr);
 
+static inline void * __ioremap_mode(unsigned long offset, unsigned long size,
+	unsigned long flags)
+{
+	if (cpu_has_64bit_addresses) {
+		u64 base = UNCAC_BASE;
+
+		/*
+		 * R10000 supports a 2 bit uncached attribute therefore
+		 * UNCAC_BASE may not equal IO_BASE.
+		 */
+		if (flags == _CACHE_UNCACHED)
+			base = (u64) IO_BASE;
+		return (void *) (unsigned long) (base + offset);
+	}
+
+	return __ioremap(offset, size, flags);
+}
+
 /*
  * ioremap     -   map bus memory into CPU space
  * @offset:    bus address of the memory
@@ -189,7 +201,7 @@ extern void __iounmap(void *addr);
  * address.
  */
 #define ioremap(offset, size)						\
-	__ioremap((offset), (size), _CACHE_UNCACHED)
+	__ioremap_mode((offset), (size), _CACHE_UNCACHED)
 
 /*
  * ioremap_nocache     -   map bus memory into CPU space
@@ -211,19 +223,27 @@ extern void __iounmap(void *addr);
  * write combining or read caching is not desirable:
  */
 #define ioremap_nocache(offset, size)					\
-	__ioremap((offset), (size), _CACHE_UNCACHED)
+	__ioremap_mode((offset), (size), _CACHE_UNCACHED)
+
+/*
+ * These two are MIPS specific ioremap variant.  ioremap_cacheable_cow
+ * requests a cachable mapping, ioremap_uncached_accelerated requests a
+ * mapping using the uncached accelerated mode which isn't supported on
+ * all processors.
+ */
 #define ioremap_cacheable_cow(offset, size)				\
-	__ioremap((offset), (size), _CACHE_CACHABLE_COW)
+	__ioremap_mode((offset), (size), _CACHE_CACHABLE_COW)
 #define ioremap_uncached_accelerated(offset, size)			\
-	__ioremap((offset), (size), _CACHE_UNCACHED_ACCELERATED)
+	__ioremap_mode((offset), (size), _CACHE_UNCACHED_ACCELERATED)
 
-extern void iounmap(void *addr);
+static inline void iounmap(void *addr)
+{
+	if (cpu_has_64bits)
+		return;
+
+	__iounmap(addr);
+}
 
-/*
- * XXX We need system specific versions of these to handle EISA address bits
- * 24-31 on SNI.
- * XXX more SNI hacks.
- */
 #define __raw_readb(addr)	(*(volatile unsigned char *)(addr))
 #define __raw_readw(addr)	(*(volatile unsigned short *)(addr))
 #define __raw_readl(addr)	(*(volatile unsigned int *)(addr))
@@ -240,14 +260,8 @@ extern void iounmap(void *addr);
 		"	.set	mips0				\n"	\
 		: "=r" (__res)						\
 		: "r" (addr));						\
-									\
 	__res;								\
 })
-#endif
-#ifdef CONFIG_MIPS64
-#define ____raw_readq(addr)	(*(volatile unsigned long *)(addr))
-#endif
-
 #define __raw_readq(addr)						\
 ({									\
 	unsigned long __flags;						\
@@ -256,9 +270,13 @@ extern void iounmap(void *addr);
 	local_irq_save(__flags);					\
 	__res = ____raw_readq(addr);					\
 	local_irq_restore(__flags);					\
-									\
 	__res;								\
 })
+#endif
+#ifdef CONFIG_MIPS64
+#define ____raw_readq(addr)	(*(volatile unsigned long *)(addr))
+#define __raw_readq(addr)	____raw_readq(addr)
+#endif
 
 #define readb(addr)		__ioswab8(__raw_readb(addr))
 #define readw(addr)		__ioswab16(__raw_readw(addr))
@@ -273,7 +291,7 @@ extern void iounmap(void *addr);
 #define __raw_writew(w,addr)	((*(volatile unsigned short *)(addr)) = (w))
 #define __raw_writel(l,addr)	((*(volatile unsigned int *)(addr)) = (l))
 #ifdef CONFIG_MIPS32
-#define ____raw_writeq(val,addr)					\
+#define ____raw_writeq(val,addr)						\
 ({									\
 	u64 __tmp;							\
 									\
@@ -288,11 +306,6 @@ extern void iounmap(void *addr);
 		: "=r" (__tmp)						\
 		: "0" ((unsigned long long)val), "r" (addr));		\
 })
-#endif
-#ifdef CONFIG_MIPS64
-#define ____raw_writeq(l,addr)	((*(volatile unsigned long *)(addr)) = (l))
-#endif
-
 #define __raw_writeq(val,addr)						\
 ({									\
 	unsigned long __flags;						\
@@ -301,6 +314,11 @@ extern void iounmap(void *addr);
 	____raw_writeq(val, addr);					\
 	local_irq_restore(__flags);					\
 })
+#endif
+#ifdef CONFIG_MIPS64
+#define ____raw_writeq(q,addr)	((*(volatile unsigned long *)(addr)) = (q))
+#define __raw_writeq(q,addr)	____raw_writeq(q, addr)
+#endif
 
 #define writeb(b,addr)		__raw_writeb(__ioswab8(b),(addr))
 #define writew(w,addr)		__raw_writew(__ioswab16(w),(addr))
@@ -380,51 +398,76 @@ out:
  */
 #define isa_check_signature(io, s, l)	check_signature(i,s,l)
 
-#define outb(val,port)							\
-do {									\
-	*(volatile u8 *)(mips_io_port_base + (port)) = __ioswab8(val);	\
-} while(0)
-
-#define outw(val,port)							\
-do {									\
-	*(volatile u16 *)(mips_io_port_base + (port)) = __ioswab16(val);\
-} while(0)
-
-#define outl(val,port)							\
-do {									\
-	*(volatile u32 *)(mips_io_port_base + (port)) = __ioswab32(val);\
-} while(0)
-
-#define outb_p(val,port)						\
-do {									\
-	*(volatile u8 *)(mips_io_port_base + (port)) = __ioswab8(val);	\
-	SLOW_DOWN_IO;							\
-} while(0)
-
-#define outw_p(val,port)						\
-do {									\
-	*(volatile u16 *)(mips_io_port_base + (port)) = __ioswab16(val);\
-	SLOW_DOWN_IO;							\
-} while(0)
-
-#define outl_p(val,port)						\
-do {									\
-	*(volatile u32 *)(mips_io_port_base + (port)) = __ioswab32(val);\
-	SLOW_DOWN_IO;							\
-} while(0)
+static inline void __outb(unsigned char val, unsigned long port)
+{
+	port = __swizzle_addr_b(port);
+
+	*(volatile u8 *)(mips_io_port_base + port) = __ioswab8(val);
+}
+
+static inline void __outw(unsigned short val, unsigned long port)
+{
+	port = __swizzle_addr_w(port);
+
+	*(volatile u16 *)(mips_io_port_base + port) = __ioswab16(val);
+}
+
+static inline void __outl(unsigned int val, unsigned long port)
+{
+	port = __swizzle_addr_l(port);
+
+	*(volatile u32 *)(mips_io_port_base + port) = __ioswab32(val);
+}
+
+static inline void __outb_p(unsigned char val, unsigned long port)
+{
+	port = __swizzle_addr_b(port);
+
+	*(volatile u8 *)(mips_io_port_base + port) = __ioswab8(val);
+	SLOW_DOWN_IO;
+}
+
+static inline void __outw_p(unsigned short val, unsigned long port)
+{
+	port = __swizzle_addr_w(port);
+
+	*(volatile u16 *)(mips_io_port_base + port) = __ioswab16(val);
+	SLOW_DOWN_IO;
+}
+
+static inline void __outl_p(unsigned int val, unsigned long port)
+{
+	port = __swizzle_addr_l(port);
+
+	*(volatile u32 *)(mips_io_port_base + port) = __ioswab32(val);
+	SLOW_DOWN_IO;
+}
+
+#define outb(val, port)		__outb(val, port)
+#define outw(val, port)		__outw(val, port)
+#define outl(val, port)		__outl(val, port)
+#define outb_p(val, port)	__outb_p(val, port)
+#define outw_p(val, port)	__outw_p(val, port)
+#define outl_p(val, port)	__outl_p(val, port)
 
 static inline unsigned char __inb(unsigned long port)
 {
+	port = __swizzle_addr_b(port);
+
 	return __ioswab8(*(volatile u8 *)(mips_io_port_base + port));
 }
 
 static inline unsigned short __inw(unsigned long port)
 {
+	port = __swizzle_addr_w(port);
+
 	return __ioswab16(*(volatile u16 *)(mips_io_port_base + port));
 }
 
 static inline unsigned int __inl(unsigned long port)
 {
+	port = __swizzle_addr_l(port);
+
 	return __ioswab32(*(volatile u32 *)(mips_io_port_base + port));
 }
 
@@ -432,6 +475,8 @@ static inline unsigned char __inb_p(unsi
 {
 	u8 __val;
 
+	port = __swizzle_addr_b(port);
+
 	__val = *(volatile u8 *)(mips_io_port_base + port);
 	SLOW_DOWN_IO;
 
@@ -442,6 +487,8 @@ static inline unsigned short __inw_p(uns
 {
 	u16 __val;
 
+	port = __swizzle_addr_w(port);
+
 	__val = *(volatile u16 *)(mips_io_port_base + port);
 	SLOW_DOWN_IO;
 
@@ -452,8 +499,11 @@ static inline unsigned int __inl_p(unsig
 {
 	u32 __val;
 
+	port = __swizzle_addr_l(port);
+
 	__val = *(volatile u32 *)(mips_io_port_base + port);
 	SLOW_DOWN_IO;
+
 	return __ioswab32(__val);
 }
 
@@ -537,7 +587,7 @@ static inline void __insl(unsigned long 
  *    be discarded.  This operation is necessary before dma operations
  *    to the memory.
  */
-#ifdef CONFIG_NONCOHERENT_IO
+#ifdef CONFIG_DMA_NONCOHERENT
 
 extern void (*_dma_cache_wback_inv)(unsigned long start, unsigned long size);
 extern void (*_dma_cache_wback)(unsigned long start, unsigned long size);
@@ -556,7 +606,7 @@ extern void (*_dma_cache_inv)(unsigned l
 #define dma_cache_inv(start,size)	\
 	do { (void) (start); (void) (size); } while (0)
 
-#endif /* CONFIG_NONCOHERENT_IO */
+#endif /* CONFIG_DMA_NONCOHERENT */
 
 /*
  * Read a 32-bit register that requires a 64-bit read cycle on the bus.
--- diff/include/asm-mips/ioctl.h	2003-08-20 14:16:33.000000000 +0100
+++ source/include/asm-mips/ioctl.h	2004-02-23 13:56:47.000000000 +0000
@@ -65,11 +65,22 @@
 	 ((nr)   << _IOC_NRSHIFT) | \
 	 ((size) << _IOC_SIZESHIFT))
 
+/* provoke compile error for invalid uses of size argument */
+extern unsigned int __invalid_size_argument_for_IOC;
+#define _IOC_TYPECHECK(t) \
+	((sizeof(t) == sizeof(t[1]) && \
+	  sizeof(t) < (1 << _IOC_SIZEBITS)) ? \
+	  sizeof(t) : __invalid_size_argument_for_IOC)
+
 /* used to create numbers */
 #define _IO(type,nr)		_IOC(_IOC_NONE,(type),(nr),0)
-#define _IOR(type,nr,size)	_IOC(_IOC_READ,(type),(nr),sizeof(size))
-#define _IOW(type,nr,size)	_IOC(_IOC_WRITE,(type),(nr),sizeof(size))
-#define _IOWR(type,nr,size)	_IOC(_IOC_READ|_IOC_WRITE,(type),(nr),sizeof(size))
+#define _IOR(type,nr,size)	_IOC(_IOC_READ,(type),(nr),(_IOC_TYPECHECK(size)))
+#define _IOW(type,nr,size)	_IOC(_IOC_WRITE,(type),(nr),(_IOC_TYPECHECK(size)))
+#define _IOWR(type,nr,size)	_IOC(_IOC_READ|_IOC_WRITE,(type),(nr),(_IOC_TYPECHECK(size)))
+#define _IOR_BAD(type,nr,size)	_IOC(_IOC_READ,(type),(nr),sizeof(size))
+#define _IOW_BAD(type,nr,size)	_IOC(_IOC_WRITE,(type),(nr),sizeof(size))
+#define _IOWR_BAD(type,nr,size)	_IOC(_IOC_READ|_IOC_WRITE,(type),(nr),sizeof(size))
+
 
 /* used to decode them.. */
 #define _IOC_DIR(nr)		(((nr) >> _IOC_DIRSHIFT) & _IOC_DIRMASK)
--- diff/include/asm-mips/ip32/crime.h	2003-08-20 14:16:36.000000000 +0100
+++ source/include/asm-mips/ip32/crime.h	2004-02-23 13:56:47.000000000 +0000
@@ -11,32 +11,30 @@
 #ifndef __ASM_CRIME_H__
 #define __ASM_CRIME_H__
 
-#include <asm/types.h>
 #include <asm/addrspace.h>
+#include <asm/io.h>
 
 /*
  * Address map
  */
-#ifndef __ASSEMBLY__
-#define CRIME_BASE	KSEG1ADDR(0x14000000)
-#else
-#define CRIME_BASE	0xffffffffb4000000
-#endif
-
-#ifndef __ASSEMBLY__
-static inline u64 crime_read_64 (unsigned long __offset) {
-        return *((volatile u64 *) (CRIME_BASE + __offset));
+#define CRIME_BASE	0x14000000	/* physical */
+
+extern void *sgi_crime;
+
+static inline uint64_t crime_read(unsigned long offset)
+{
+        return readq(sgi_crime + offset);
 }
-static inline void crime_write_64 (unsigned long __offset, u64 __val) {
-        *((volatile u64 *) (CRIME_BASE + __offset)) = __val;
+static inline void crime_write(uint64_t val, unsigned long offset)
+{
+	writeq(val, sgi_crime + offset);
 }
-#endif
 
 #undef BIT
 #define BIT(x) (1UL << (x))
 
 /* All CRIME registers are 64 bits */
-#define CRIME_ID		0
+#define CRIME_ID		0x000
 
 #define CRIME_ID_MASK		0xff
 #define CRIME_ID_IDBITS		0xf0
@@ -48,8 +46,8 @@ static inline void crime_write_64 (unsig
 #define CRIME_REV_13		0x13
 #define CRIME_REV_14		0x14
 
-#define CRIME_CONTROL		(0x00000008)
-#define CRIME_CONTROL_MASK	0x3fff		/* 14-bit registers */
+#define CRIME_CONTROL		0x008
+#define CRIME_CONTROL_MASK	0x3fff
 
 /* CRIME_CONTROL register bits */
 #define CRIME_CONTROL_TRITON_SYSADC	0x2000
@@ -67,10 +65,10 @@ static inline void crime_write_64 (unsig
 #define CRIME_CONTROL_WBUF_HWM		0x00f0
 #define CRIME_CONTROL_WBUF_SHFT		8
 
-#define CRIME_INT_STAT			(0x00000010)
-#define CRIME_INT_MASK			(0x00000018)
-#define CRIME_SOFT_INT			(0x00000020)
-#define CRIME_HARD_INT			(0x00000028)
+#define CRIME_INT_STAT			0x010
+#define CRIME_INT_MASK			0x018
+#define CRIME_SOFT_INT			0x020
+#define CRIME_HARD_INT			0x028
 
 /* Bits in CRIME_INT_XXX and CRIME_HARD_INT */
 #define MACE_VID_IN1_INT		BIT (0)
@@ -113,40 +111,32 @@ static inline void crime_write_64 (unsig
 #define CRIME_MACEPCI_INT_MASK		0xff00
 #define CRIME_CRIME_INT_MASK		0xffff0000
 
-/*
- * XXX Todo
- */
-#define CRIME_DOG			(0x00000030)
-/* We are word-play compatible but not misspelling compatible */
-#define MC_GRUFF			CRIME_DOG
-#define CRIME_DOG_MASK			(0x001fffff)
+#define CRIME_DOG			0x030
+#define CRIME_DOG_MASK			0x001fffff
 
 /* CRIME_DOG register bits */
-#define CRIME_DOG_POWER_ON_RESET	(0x00010000)
-#define CRIME_DOG_WARM_RESET		(0x00080000)
+#define CRIME_DOG_POWER_ON_RESET	0x00010000
+#define CRIME_DOG_WARM_RESET		0x00080000
 #define CRIME_DOG_TIMEOUT		(CRIME_DOG_POWER_ON_RESET|CRIME_DOG_WARM_RESET)
-#define CRIME_DOG_VALUE			(0x00007fff)	/* ??? */
+#define CRIME_DOG_VALUE			0x00007fff
 
-#define CRIME_TIME			(0x00000038)
-#define CRIME_TIME_MASK			(0x0000ffffffffffff)
+#define CRIME_TIMER			0x038
+#define CRIME_TIMER_MASK		0x0000ffffffffffff
 
-#ifdef MASTER_FREQ
-#undef MASTER_FREQ
-#endif
 #define CRIME_MASTER_FREQ		66666500	/* Crime upcounter frequency */
-#define CRIME_NS_PER_TICK		15	/* for delay_calibrate */
+#define CRIME_NS_PER_TICK		15		/* for delay_calibrate */
 
-#define CRIME_CPU_ERROR_ADDR		(0x00000040)
-#define CRIME_CPU_ERROR_ADDR_MASK	(0x3ffffffff)
+#define CRIME_CPU_ERROR_ADDR		0x040
+#define CRIME_CPU_ERROR_ADDR_MASK	0x3ffffffff
 
-#define CRIME_CPU_ERROR_STAT		(0x00000048)
+#define CRIME_CPU_ERROR_STAT		0x048
 /* REV_PETTY only! */
-#define CRIME_CPU_ERROR_ENA		(0x00000050)
+#define CRIME_CPU_ERROR_ENA		0x050
 
 /*
  * bit definitions for CRIME/VICE error status and enable registers
  */
-#define CRIME_CPU_ERROR_MASK           0x7UL   /* cpu error stat is 3 bits */
+#define CRIME_CPU_ERROR_MASK           0x7	/* cpu error stat is 3 bits */
 #define CRIME_CPU_ERROR_CPU_ILL_ADDR   0x4
 #define CRIME_CPU_ERROR_VICE_WRT_PRTY  0x2
 #define CRIME_CPU_ERROR_CPU_WRT_PRTY   0x1
@@ -168,10 +158,10 @@ static inline void crime_write_64 (unsig
 #define CRIME_CPU_ERROR_CPU_INV_ADDR_WR		0x2
 #define CRIME_CPU_ERROR_CPU_INV_REG_ADDR	0x1
 
-#define CRIME_VICE_ERROR_ADDR		(0x00000058)
-#define CRIME_VICE_ERROR_ADDR_MASK	(0x3fffffff)
+#define CRIME_VICE_ERROR_ADDR		0x058
+#define CRIME_VICE_ERROR_ADDR_MASK	0x3fffffff
 
-#define CRIME_MEM_CONTROL		(0x00000200)
+#define CRIME_MEM_CONTROL		0x200
 #define CRIME_MEM_CONTROL_MASK		0x3	/* 25 cent register */
 #define CRIME_MEM_CONTROL_ECC_ENA	0x1
 #define CRIME_MEM_CONTROL_USE_ECC_REPL	0x2
@@ -179,20 +169,19 @@ static inline void crime_write_64 (unsig
 /*
  * macros for CRIME memory bank control registers.
  */
-#define CRIME_MEM_BANK_CONTROL(__bank)		(0x00000208 + ((__bank) << 3))
+#define CRIME_MEM_BANK_CONTROL(__bank)		(0x208 + ((__bank) << 3))
 #define CRIME_MEM_BANK_CONTROL_MASK		0x11f /* 9 bits 7:5 reserved */
 #define CRIME_MEM_BANK_CONTROL_ADDR		0x01f
 #define CRIME_MEM_BANK_CONTROL_SDRAM_SIZE	0x100
+#define CRIME_MAXBANKS				8
 
-#define CRIME_MEM_REFRESH_COUNTER	(0x00000248)
-#define CRIME_MEM_REFRESH_COUNTER_MASK	0x7ff	/* 11-bit register */
-
-#define CRIME_MAXBANKS                 8
+#define CRIME_MEM_REFRESH_COUNTER	0x248
+#define CRIME_MEM_REFRESH_COUNTER_MASK	0x7ff	
 
 /*
  * CRIME Memory error status register bit definitions
  */
-#define CRIME_MEM_ERROR_STAT		(0x00000250)
+#define CRIME_MEM_ERROR_STAT		0x250
 #define CRIME_MEM_ERROR_STAT_MASK       0x0ff7ffff    /* 28-bit register */
 #define CRIME_MEM_ERROR_MACE_ID		0x0000007f
 #define CRIME_MEM_ERROR_MACE_ACCESS	0x00000080
@@ -213,16 +202,16 @@ static inline void crime_write_64 (unsig
 #define CRIME_MEM_ERROR_INV_MEM_ADDR_WR	0x04000000
 #define CRIME_MEM_ERROR_INV_MEM_ADDR_RMW	0x08000000
 
-#define CRIME_MEM_ERROR_ADDR		(0x00000258)
+#define CRIME_MEM_ERROR_ADDR		0x258
 #define CRIME_MEM_ERROR_ADDR_MASK	0x3fffffff
 
-#define CRIME_MEM_ERROR_ECC_SYN		(0x00000260)
+#define CRIME_MEM_ERROR_ECC_SYN		0x260
 #define CRIME_MEM_ERROR_ECC_SYN_MASK	0xffffffff
 
-#define CRIME_MEM_ERROR_ECC_CHK		(0x00000268)
+#define CRIME_MEM_ERROR_ECC_CHK		0x268
 #define CRIME_MEM_ERROR_ECC_CHK_MASK    0xffffffff
 
-#define CRIME_MEM_ERROR_ECC_REPL	(0x00000270)
+#define CRIME_MEM_ERROR_ECC_REPL	0x270
 #define CRIME_MEM_ERROR_ECC_REPL_MASK	0xffffffff
 
 #endif /* __ASM_CRIME_H__ */
--- diff/include/asm-mips/ip32/mace.h	2003-08-20 14:16:36.000000000 +0100
+++ source/include/asm-mips/ip32/mace.h	2004-02-23 13:56:47.000000000 +0000
@@ -1,90 +1,63 @@
 /*
- * Definitions for the SGI O2 Mace chip.
+ * Definitions for the SGI MACE (Multimedia, Audio and Communications Engine)
  *
  * This file is subject to the terms and conditions of the GNU General Public
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  *
  * Copyright (C) 2000 Harald Koerfgen
+ * Copyright (C) 2004 Ladislav Michl
  */
 
 #ifndef __ASM_MACE_H__
 #define __ASM_MACE_H__
 
-#include <asm/addrspace.h>
-#include <asm/system.h>
+#include <linux/config.h>
+#include <asm/io.h>
+
 /*
  * Address map
  */
-#define MACE_BASE		KSEG1ADDR(0x1f000000)
-#define MACE_PCI		(0x00080000)
-#define MACE_VIN1		(0x00100000)
-#define MACE_VIN2		(0x00180000)
-#define MACE_VOUT		(0x00200000)
-#define MACE_ENET		(0x00280000)
-#define MACE_PERIF		(0x00300000)
-#define MACE_ISA_EXT		(0x00380000)
-
-#define MACE_AUDIO_BASE		(MACE_PERIF		)
-#define MACE_ISA_BASE		(MACE_PERIF + 0x00010000)
-#define MACE_KBDMS_BASE		(MACE_PERIF + 0x00020000)
-#define MACE_I2C_BASE		(MACE_PERIF + 0x00030000)
-#define MACE_UST_BASE		(MACE_PERIF + 0x00040000)
-
+#define MACE_BASE	0x1f000000	/* physical */
 
 #undef BIT
-#define BIT(__bit_offset) (1UL << (__bit_offset))
-
-/*
- * Mace MACEPCI interface, 32 bit regs
- */
-#define MACEPCI_ERROR_ADDR		(MACE_PCI	      )
-#define MACEPCI_ERROR_FLAGS		(MACE_PCI + 0x00000004)
-#define MACEPCI_CONTROL			(MACE_PCI + 0x00000008)
-#define MACEPCI_REV			(MACE_PCI + 0x0000000c)
-#define MACEPCI_WFLUSH			(MACE_PCI + 0x0000000c) /* ??? --IV !!! It's for flushing read buffers on PCI MEMORY accesses!!! */
-#define MACEPCI_CONFIG_ADDR		(MACE_PCI + 0x00000cf8)
-#define MACEPCI_CONFIG_DATA		(MACE_PCI + 0x00000cfc)
-#define MACEPCI_LOW_MEMORY		0x1a000000
-#define MACEPCI_LOW_IO			0x18000000
-#define MACEPCI_SWAPPED_VIEW		0
-#define MACEPCI_NATIVE_VIEW		0x40000000
-#define MACEPCI_IO			0x80000000
-/*#define MACEPCI_HI_MEMORY		0x0000000280000000UL * This mipght be just 0x0000000200000000UL 2G more :) (or maybe it is different between 1.1 & 1.5 */
-#define MACEPCI_HI_MEMORY		0x0000000200000000UL /* This mipght be just 0x0000000200000000UL 2G more :) (or maybe it is different between 1.1 & 1.5 */
-#define MACEPCI_HI_IO			0x0000000100000000UL
-
-/*
- * Bits in the MACEPCI_CONTROL register
- */
-#define MACEPCI_CONTROL_INT(x)		BIT(x)
-#define MACEPCI_CONTROL_INT_MASK	0xff
-#define MACEPCI_CONTROL_SERR_ENA	BIT(8)
-#define MACEPCI_CONTROL_ARB_N6		BIT(9)
-#define MACEPCI_CONTROL_PARITY_ERR	BIT(10)
-#define MACEPCI_CONTROL_MRMRA_ENA	BIT(11)
-#define MACEPCI_CONTROL_ARB_N3		BIT(12)
-#define MACEPCI_CONTROL_ARB_N4		BIT(13)
-#define MACEPCI_CONTROL_ARB_N5		BIT(14)
-#define MACEPCI_CONTROL_PARK_LIU	BIT(15)
-#define MACEPCI_CONTROL_INV_INT(x)	BIT(16+x)
-#define MACEPCI_CONTROL_INV_INT_MASK	0x00ff0000
-#define MACEPCI_CONTROL_OVERRUN_INT	BIT(24)
-#define MACEPCI_CONTROL_PARITY_INT	BIT(25)
-#define MACEPCI_CONTROL_SERR_INT	BIT(26)
-#define MACEPCI_CONTROL_IT_INT		BIT(27)
-#define MACEPCI_CONTROL_RE_INT		BIT(28)
-#define MACEPCI_CONTROL_DPED_INT	BIT(29)
-#define MACEPCI_CONTROL_TAR_INT		BIT(30)
-#define MACEPCI_CONTROL_MAR_INT		BIT(31)
+#define BIT(x) (1ULL << (x))
 
-/*
- * Bits in the MACE_PCI error register
- */
+#ifdef CONFIG_MIPS32
+typedef struct {
+	volatile unsigned long long reg;
+} mace64_t;
+
+typedef struct {
+	unsigned long pad;
+	volatile unsigned long reg;
+} mace32_t;
+#endif
+#ifdef CONFIG_MIPS64
+typedef struct {
+	volatile unsigned long reg;
+} mace64_t;
+
+typedef struct {
+	volatile unsigned long reg;
+} mace32_t;
+#endif
+
+#define mace_read(r)	\
+	(sizeof(r.reg) == 4 ? readl(&r.reg) : readq(&r.reg))
+#define mace_write(v,r)	\
+	(sizeof(r.reg) == 4 ? writel(v,&r.reg) : writeq(v,&r.reg))
+
+/*
+ * PCI interface
+ */
+struct mace_pci {
+	volatile unsigned int error_addr;
+	volatile unsigned int error;
 #define MACEPCI_ERROR_MASTER_ABORT		BIT(31)
 #define MACEPCI_ERROR_TARGET_ABORT		BIT(30)
 #define MACEPCI_ERROR_DATA_PARITY_ERR		BIT(29)
-#define MACEPCI_ERROR_RETRY_ERR		BIT(28)
+#define MACEPCI_ERROR_RETRY_ERR			BIT(28)
 #define MACEPCI_ERROR_ILLEGAL_CMD		BIT(27)
 #define MACEPCI_ERROR_SYSTEM_ERR		BIT(26)
 #define MACEPCI_ERROR_INTERRUPT_TEST		BIT(25)
@@ -104,210 +77,299 @@
 #define MACEPCI_ERROR_DEVSEL_SLOW		0x80
 #define MACEPCI_ERROR_FBB			BIT(1)
 #define MACEPCI_ERROR_66MHZ			BIT(0)
+	volatile unsigned int control;
+#define MACEPCI_CONTROL_INT(x)			BIT(x)
+#define MACEPCI_CONTROL_INT_MASK		0xff
+#define MACEPCI_CONTROL_SERR_ENA		BIT(8)
+#define MACEPCI_CONTROL_ARB_N6			BIT(9)
+#define MACEPCI_CONTROL_PARITY_ERR		BIT(10)
+#define MACEPCI_CONTROL_MRMRA_ENA		BIT(11)
+#define MACEPCI_CONTROL_ARB_N3			BIT(12)
+#define MACEPCI_CONTROL_ARB_N4			BIT(13)
+#define MACEPCI_CONTROL_ARB_N5			BIT(14)
+#define MACEPCI_CONTROL_PARK_LIU		BIT(15)
+#define MACEPCI_CONTROL_INV_INT(x)		BIT(16+x)
+#define MACEPCI_CONTROL_INV_INT_MASK		0x00ff0000
+#define MACEPCI_CONTROL_OVERRUN_INT		BIT(24)
+#define MACEPCI_CONTROL_PARITY_INT		BIT(25)
+#define MACEPCI_CONTROL_SERR_INT		BIT(26)
+#define MACEPCI_CONTROL_IT_INT			BIT(27)
+#define MACEPCI_CONTROL_RE_INT			BIT(28)
+#define MACEPCI_CONTROL_DPED_INT		BIT(29)
+#define MACEPCI_CONTROL_TAR_INT			BIT(30)
+#define MACEPCI_CONTROL_MAR_INT			BIT(31)
+	volatile unsigned int rev;
+	unsigned int _pad[0xcf8/4 - 4];
+	volatile unsigned int config_addr;
+	union {
+		volatile unsigned char b[4];
+		volatile unsigned short w[2];
+		volatile unsigned int l;
+	} config_data;
+};
+#define MACEPCI_LOW_MEMORY		0x1a000000
+#define MACEPCI_LOW_IO			0x18000000
+#define MACEPCI_SWAPPED_VIEW		0
+#define MACEPCI_NATIVE_VIEW		0x40000000
+#define MACEPCI_IO			0x80000000
+#define MACEPCI_HI_MEMORY		0x280000000
+#define MACEPCI_HI_IO			0x100000000
 
 /*
- * Mace timer registers - 64 bit regs (63:32 are UST, 31:0 are MSC)
+ * Video interface
  */
-#define MSC_PART(__reg) ((__reg) & 0x00000000ffffffff)
-#define UST_PART(__reg) (((__reg) & 0xffffffff00000000) >> 32)
+struct mace_video {
+	mace32_t xxx;	/* later... */
+};
+
+/* 
+ * Ethernet interface
+ */
+struct mace_ethernet {
+	mace32_t mac_ctrl;
+	mace32_t int_stat;
+	mace32_t dma_ctrl;
+	mace32_t timer;
+	mace32_t tx_int_al;
+	mace32_t rx_int_al;
+	mace32_t tx_info;
+	mace32_t tx_info_al;
+	mace32_t rx_buff;
+	mace32_t rx_buff_al1;
+	mace32_t rx_buff_al2;
+	mace64_t diag;
+	mace32_t phy_data;
+	mace32_t phy_regs;
+	mace32_t phy_trans_go;
+	mace32_t backoff_seed;
+	/*===================================*/
+	mace64_t imq_reserved[4];
+	mace64_t mac_addr;
+	mace64_t mac_addr2;
+	mace64_t mcast_filter;
+	mace32_t tx_ring_base;
+	/* Following are read-only registers for debugging */
+	mace64_t tx_pkt1_hdr;
+	mace64_t tx_pkt1_ptr[3];
+	mace64_t tx_pkt2_hdr;
+	mace64_t tx_pkt2_ptr[3];
+	/*===================================*/
+	mace32_t rx_fifo;
+};
+#define mace_eth_read(r)	\
+	mace_read(mace->eth.r)
+#define mace_eth_write(v,r)	\
+	mace_write(v,mace->eth.r)
+
+
+/* 
+ * Peripherals
+ */
+
+/* Audio registers */
+struct mace_audio {
+	mace32_t control;
+	mace32_t codec_control;		/* codec status control */
+	mace32_t codec_mask;		/* codec status input mask */
+	mace32_t codec_read;		/* codec status read data */
+	struct {
+		mace32_t control;	/* channel control */
+		mace32_t read_ptr;	/* channel read pointer */
+		mace32_t write_ptr;	/* channel write pointer */
+		mace32_t depth;		/* channel depth */
+	} channel[3];
+};
+#define mace_perif_audio_read(r)	\
+	mace_read(mace->perif.audio.r)
+#define mace_perif_audio_write(v,r)	\
+	mace_write(v,mace->perif.audio.r)
+
+/* ISA Control and DMA registers */
+struct mace_isactrl {
+	mace32_t ringbase;
+#define MACEISA_RINGBUFFERS_SIZE	(8 * 4096)
+
+	mace32_t misc;
+#define MACEISA_FLASH_WE		BIT(0)	/* 1=> Enable FLASH writes */
+#define MACEISA_PWD_CLEAR		BIT(1)	/* 1=> PWD CLEAR jumper detected */
+#define MACEISA_NIC_DEASSERT		BIT(2)
+#define MACEISA_NIC_DATA		BIT(3)
+#define MACEISA_LED_RED			BIT(4)	/* 0=> Illuminate red LED */
+#define MACEISA_LED_GREEN		BIT(5)	/* 0=> Illuminate green LED */
+#define MACEISA_DP_RAM_ENABLE		BIT(6)
+
+	mace32_t istat;
+	mace32_t imask;
+#define MACEISA_AUDIO_SW_INT		BIT(0)
+#define MACEISA_AUDIO_SC_INT		BIT(1)
+#define MACEISA_AUDIO1_DMAT_INT		BIT(2)
+#define MACEISA_AUDIO1_OF_INT		BIT(3)
+#define MACEISA_AUDIO2_DMAT_INT		BIT(4)
+#define MACEISA_AUDIO2_MERR_INT		BIT(5)
+#define MACEISA_AUDIO3_DMAT_INT		BIT(6)
+#define MACEISA_AUDIO3_MERR_INT		BIT(7)
+#define MACEISA_RTC_INT			BIT(8)
+#define MACEISA_KEYB_INT		BIT(9)
+#define MACEISA_KEYB_POLL_INT		BIT(10)
+#define MACEISA_MOUSE_INT		BIT(11)
+#define MACEISA_MOUSE_POLL_INT		BIT(12)
+#define MACEISA_TIMER0_INT		BIT(13)
+#define MACEISA_TIMER1_INT		BIT(14)
+#define MACEISA_TIMER2_INT		BIT(15)
+#define MACEISA_PARALLEL_INT		BIT(16)
+#define MACEISA_PAR_CTXA_INT		BIT(17)
+#define MACEISA_PAR_CTXB_INT		BIT(18)
+#define MACEISA_PAR_MERR_INT		BIT(19)
+#define MACEISA_SERIAL1_INT		BIT(20)
+#define MACEISA_SERIAL1_TDMAT_INT	BIT(21)
+#define MACEISA_SERIAL1_TDMAPR_INT	BIT(22)
+#define MACEISA_SERIAL1_TDMAME_INT	BIT(23)
+#define MACEISA_SERIAL1_RDMAT_INT	BIT(24)
+#define MACEISA_SERIAL1_RDMAOR_INT	BIT(25)
+#define MACEISA_SERIAL2_INT		BIT(26)
+#define MACEISA_SERIAL2_TDMAT_INT	BIT(27)
+#define MACEISA_SERIAL2_TDMAPR_INT	BIT(28)
+#define MACEISA_SERIAL2_TDMAME_INT	BIT(29)
+#define MACEISA_SERIAL2_RDMAT_INT	BIT(30)
+#define MACEISA_SERIAL2_RDMAOR_INT	BIT(31)
+
+	mace64_t _pad[0x2000/8 - 4];
+
+	mace64_t dp_ram[0x400];
+};
+#define mace_perif_ctrl_read(r)		\
+	mace_read(mace->perif.ctrl.r)
+#define mace_perif_ctrl_write(v,r)	\
+	mace_write(v,mace->perif.ctrl.r)
+
+/* Keyboard & Mouse registers
+ * -> drivers/input/serio/maceps2.c */
+struct mace_ps2port {
+	mace32_t tx;
+	mace32_t rx;
+	mace32_t control;
+	mace32_t status;
+};
+
+struct mace_ps2 {
+	struct mace_ps2port keyb;
+	struct mace_ps2port mouse;
+};
+
+/* I2C registers
+ * -> drivers/i2c/algos/i2c-algo-sgi.c */
+struct mace_i2c {
+	mace32_t config;
+#define MACEI2C_RESET           BIT(0)
+#define MACEI2C_FAST            BIT(1)
+#define MACEI2C_DATA_OVERRIDE   BIT(2)
+#define MACEI2C_CLOCK_OVERRIDE  BIT(3)
+#define MACEI2C_DATA_STATUS     BIT(4)
+#define MACEI2C_CLOCK_STATUS    BIT(5)
+	mace32_t control;
+	mace32_t data;
+};
 
-#define MACE_UST_UST		(MACE_UST_BASE		   ) /* Universial system time */
-#define MACE_UST_COMPARE1	(MACE_UST_BASE + 0x00000008) /* Interrupt compare reg 1 */
-#define MACE_UST_COMPARE2	(MACE_UST_BASE + 0x00000010) /* Interrupt compare reg 2 */
-#define MACE_UST_COMPARE3	(MACE_UST_BASE + 0x00000018) /* Interrupt compare reg 3 */
-#define MACE_UST_PERIOD_NS	960	/* UST Period in ns  */
-
-#define MACE_UST_AIN_MSC	(MACE_UST_BASE + 0x00000020) /* Audio in MSC/UST pair */
-#define MACE_UST_AOUT1_MSC	(MACE_UST_BASE + 0x00000028) /* Audio out 1 MSC/UST pair */
-#define MACE_UST_AOUT2_MSC	(MACE_UST_BASE + 0x00000030) /* Audio out 2 MSC/UST pair */
-#define MACE_VIN1_MSC_UST	(MACE_UST_BASE + 0x00000038) /* Video In 1 MSC/UST pair */
-#define MACE_VIN2_MSC_UST	(MACE_UST_BASE + 0x00000040) /* Video In 2 MSC/UST pair */
-#define MACE_VOUT_MSC_UST	(MACE_UST_BASE + 0x00000048) /* Video out MSC/UST pair */
+/* Timer registers */
+typedef union {
+	mace64_t ust_msc;
+	struct reg {
+		volatile unsigned int ust;
+		volatile unsigned int msc;
+	} reg;
+} timer_reg;
 
-/*
- * Mace "ISA" peripherals
- */
-#define MACEISA_EPP_BASE   	(MACE_ISA_EXT		  )
-#define MACEISA_ECP_BASE   	(MACE_ISA_EXT + 0x00008000)
-#define MACEISA_SER1_BASE	(MACE_ISA_EXT + 0x00010000)
-#define MACEISA_SER1_REGS       (MACE_ISA_BASE + 0x00020000)
-#define MACEISA_SER2_BASE	(MACE_ISA_EXT + 0x00018000)
-#define MACEISA_SER2_REGS       (MACE_ISA_BASE + 0x00030000)
-#define MACEISA_RTC_BASE	(MACE_ISA_EXT + 0x00020000)
-#define MACEISA_GAME_BASE	(MACE_ISA_EXT + 0x00030000)
+struct mace_timers {
+	mace32_t ust;
+#define MACE_UST_PERIOD_NS	960
 
-/*
- * Ringbase address and reset register - 64 bits
- */
-#define MACEISA_RINGBASE	MACE_ISA_BASE
-/* Ring buffers occupy 8 4K buffers */
-#define MACEISA_RINGBUFFERS_SIZE 8*4*1024
+	mace32_t compare1;
+	mace32_t compare2;
+	mace32_t compare3;
 
-/*
- * Flash-ROM/LED/DP-RAM/NIC Controller Register - 64 bits (?)
- */
-#define MACEISA_FLASH_NIC_REG	(MACE_ISA_BASE + 0x00000008)
+	timer_reg audio_in;
+	timer_reg audio_out1;
+	timer_reg audio_out2;
+	timer_reg video_in1;
+	timer_reg video_in2;
+	timer_reg video_out;	
+};
 
-/*
- * Bit definitions for that
- */
-#define MACEISA_FLASH_WE       BIT(0) /* 1=> Enable FLASH writes */
-#define MACEISA_PWD_CLEAR      BIT(1) /* 1=> PWD CLEAR jumper detected */
-#define MACEISA_NIC_DEASSERT   BIT(2)
-#define MACEISA_NIC_DATA       BIT(3)
-#define MACEISA_LED_RED        BIT(4) /* 0=> Illuminate RED LED */
-#define MACEISA_LED_GREEN      BIT(5) /* 0=> Illuminate GREEN LED */
-#define MACEISA_DP_RAM_ENABLE  BIT(6)
+struct mace_perif {
+	struct mace_audio audio;
+	char _pad0[0x10000 - sizeof(struct mace_audio)];
 
-/*
- * ISA interrupt and status registers - 32 bit
- */
-#define MACEISA_INT_STAT	(MACE_ISA_BASE + 0x00000014)
-#define MACEISA_INT_MASK	(MACE_ISA_BASE + 0x0000001c)
+	struct mace_isactrl ctrl;
+	char _pad1[0x10000 - sizeof(struct mace_isactrl)];
 
-/*
- * Bits in the status/mask registers
- */
-#define MACEISA_AUDIO_SW_INT		BIT (0)
-#define MACEISA_AUDIO_SC_INT		BIT (1)
-#define MACEISA_AUDIO1_DMAT_INT		BIT (2)
-#define MACEISA_AUDIO1_OF_INT		BIT (3)
-#define MACEISA_AUDIO2_DMAT_INT		BIT (4)
-#define MACEISA_AUDIO2_MERR_INT		BIT (5)
-#define MACEISA_AUDIO3_DMAT_INT		BIT (6)
-#define MACEISA_AUDIO3_MERR_INT		BIT (7)
-#define MACEISA_RTC_INT			BIT (8)
-#define MACEISA_KEYB_INT		BIT (9)
-#define MACEISA_KEYB_POLL_INT		BIT (10)
-#define MACEISA_MOUSE_INT		BIT (11)
-#define MACEISA_MOUSE_POLL_INT		BIT (12)
-#define MACEISA_TIMER0_INT		BIT (13)
-#define MACEISA_TIMER1_INT		BIT (14)
-#define MACEISA_TIMER2_INT		BIT (15)
-#define MACEISA_PARALLEL_INT		BIT (16)
-#define MACEISA_PAR_CTXA_INT		BIT (17)
-#define MACEISA_PAR_CTXB_INT		BIT (18)
-#define MACEISA_PAR_MERR_INT		BIT (19)
-#define MACEISA_SERIAL1_INT		BIT (20)
-#define MACEISA_SERIAL1_TDMAT_INT	BIT (21)
-#define MACEISA_SERIAL1_TDMAPR_INT	BIT (22)
-#define MACEISA_SERIAL1_TDMAME_INT	BIT (23)
-#define MACEISA_SERIAL1_RDMAT_INT	BIT (24)
-#define MACEISA_SERIAL1_RDMAOR_INT	BIT (25)
-#define MACEISA_SERIAL2_INT		BIT (26)
-#define MACEISA_SERIAL2_TDMAT_INT	BIT (27)
-#define MACEISA_SERIAL2_TDMAPR_INT	BIT (28)
-#define MACEISA_SERIAL2_TDMAME_INT	BIT (29)
-#define MACEISA_SERIAL2_RDMAT_INT	BIT (30)
-#define MACEISA_SERIAL2_RDMAOR_INT	BIT (31)
-
-#define MACEI2C_CONFIG	MACE_I2C_BASE
-#define MACEI2C_CONTROL	(MACE_I2C_BASE|0x10)
-#define MACEI2C_DATA	(MACE_I2C_BASE|0x18)
+	struct mace_ps2 ps2;
+	char _pad2[0x10000 - sizeof(struct mace_ps2)];
 
-/* Bits for I2C_CONFIG */
-#define MACEI2C_RESET           BIT(0)
-#define MACEI2C_FAST            BIT(1)
-#define MACEI2C_DATA_OVERRIDE   BIT(2)
-#define MACEI2C_CLOCK_OVERRIDE  BIT(3)
-#define MACEI2C_DATA_STATUS     BIT(4)
-#define MACEI2C_CLOCK_STATUS    BIT(5)
+	struct mace_i2c i2c;
+	char _pad3[0x10000 - sizeof(struct mace_i2c)];
 
-/* Bits for I2C_CONTROL */
-#define MACEI2C_NOT_IDLE        BIT(0)	/* write: 0=force idle
-				         * read: 0=idle 1=not idle */
-#define MACEI2C_DIR		BIT(1)	/* 0=write 1=read */
-#define MACEI2C_MORE_BYTES	BIT(2)	/* 0=last byte 1=more bytes */
-#define MACEI2C_TRANS_BUSY	BIT(4)	/* 0=trans done 1=trans busy */
-#define MACEI2C_NACK	        BIT(5)	/* 0=ack received 1=ack not */
-#define MACEI2C_BUS_ERROR	BIT(7)	/* 0=no bus err 1=bus err */
-
-
-#define MACEISA_AUDIO_INT (MACEISA_AUDIO_SW_INT |               \
-                           MACEISA_AUDIO_SC_INT |               \
-                           MACEISA_AUDIO1_DMAT_INT |            \
-                           MACEISA_AUDIO1_OF_INT |              \
-                           MACEISA_AUDIO2_DMAT_INT |            \
-                           MACEISA_AUDIO2_MERR_INT |            \
-                           MACEISA_AUDIO3_DMAT_INT |            \
-                           MACEISA_AUDIO3_MERR_INT)
-#define MACEISA_MISC_INT (MACEISA_RTC_INT |                     \
-                          MACEISA_KEYB_INT |                    \
-                          MACEISA_KEYB_POLL_INT |               \
-                          MACEISA_MOUSE_INT |                   \
-                          MACEISA_MOUSE_POLL_INT |              \
-                          MACEISA_TIMER0_INT |                  \
-                          MACEISA_TIMER1_INT |                  \
-                          MACEISA_TIMER2_INT)
-#define MACEISA_SUPERIO_INT (MACEISA_PARALLEL_INT |             \
-                             MACEISA_PAR_CTXA_INT |             \
-                             MACEISA_PAR_CTXB_INT |             \
-                             MACEISA_PAR_MERR_INT |             \
-                             MACEISA_SERIAL1_INT |              \
-                             MACEISA_SERIAL1_TDMAT_INT |        \
-                             MACEISA_SERIAL1_TDMAPR_INT |       \
-                             MACEISA_SERIAL1_TDMAME_INT |       \
-                             MACEISA_SERIAL1_RDMAT_INT |        \
-                             MACEISA_SERIAL1_RDMAOR_INT |       \
-                             MACEISA_SERIAL2_INT |              \
-                             MACEISA_SERIAL2_TDMAT_INT |        \
-                             MACEISA_SERIAL2_TDMAPR_INT |       \
-                             MACEISA_SERIAL2_TDMAME_INT |       \
-                             MACEISA_SERIAL2_RDMAT_INT |        \
-                             MACEISA_SERIAL2_RDMAOR_INT)
+	struct mace_timers timers;
+	char _pad4[0x10000 - sizeof(struct mace_timers)];
+};
 
-#ifndef __ASSEMBLY__
-#include <asm/types.h>
 
-/*
- * XXX Some of these are probably not needed (or even legal?)
+/* 
+ * ISA peripherals
  */
-static inline u8 mace_read_8 (unsigned long __offset)
-{
-	return *((volatile u8 *) (MACE_BASE + __offset));
-}
-
-static inline u16 mace_read_16 (unsigned long __offset)
-{
-	return *((volatile u16 *) (MACE_BASE + __offset));
-}
-
-static inline u32 mace_read_32 (unsigned long __offset)
-{
-	return *((volatile u32 *) (MACE_BASE + __offset));
-}
-
-static inline u64 mace_read_64 (unsigned long __offset)
-{
-	return *((volatile u64 *) (MACE_BASE + __offset));
-}
-
-static inline void mace_write_8 (unsigned long __offset, u8 __val)
-{
-	*((volatile u8 *) (MACE_BASE + __offset)) = __val;
-}
-
-static inline void mace_write_16 (unsigned long __offset, u16 __val)
-{
-	*((volatile u16 *) (MACE_BASE + __offset)) = __val;
-}
-
-static inline void mace_write_32 (unsigned long __offset, u32 __val)
-{
-	*((volatile u32 *) (MACE_BASE + __offset)) = __val;
-}
-
-static inline void mace_write_64 (unsigned long __offset, u64 __val)
-{
-	*((volatile u64 *) (MACE_BASE + __offset)) = __val;
-}
-
-/* Call it whenever device needs to read data from main memory coherently */
-static inline void mace_inv_read_buffers(void)
-{
-/*	mace_write_32(MACEPCI_WFLUSH,0xffffffff);*/
-}
-#endif /* !__ASSEMBLY__ */
 
+/* Parallel port */
+struct mace_parallel {	/* later... */
+};
+
+struct mace_ecp1284 {	/* later... */
+};
+
+/* Serial port */
+struct mace_serial {
+	mace64_t xxx;	/* later... */
+};
+
+struct mace_isa {
+	struct mace_parallel parallel;
+	char _pad1[0x8000 - sizeof(struct mace_parallel)];
+
+	struct mace_ecp1284 ecp1284;
+	char _pad2[0x8000 - sizeof(struct mace_ecp1284)];
+
+	struct mace_serial serial1;
+	char _pad3[0x8000 - sizeof(struct mace_serial)];
+
+	struct mace_serial serial2;
+	char _pad4[0x8000 - sizeof(struct mace_serial)];
+
+	mace32_t rtc[0x10000/8];
+};
+
+struct sgi_mace {
+	char _reserved[0x80000];
+
+	struct mace_pci pci;
+	char _pad0[0x80000 - sizeof(struct mace_pci)];
+
+	struct mace_video video_in1;
+	char _pad1[0x80000 - sizeof(struct mace_video)];
+
+	struct mace_video video_in2;
+	char _pad2[0x80000 - sizeof(struct mace_video)];
+
+	struct mace_video video_out;
+	char _pad3[0x80000 - sizeof(struct mace_video)];
+
+	struct mace_ethernet eth;
+	char _pad4[0x80000 - sizeof(struct mace_ethernet)];
+
+	struct mace_perif perif;
+	char _pad5[0x80000 - sizeof(struct mace_perif)];
+
+	struct mace_isa isa;
+	char _pad6[0x80000 - sizeof(struct mace_isa)];
+};
+
+extern struct sgi_mace *mace;
 
 #endif /* __ASM_MACE_H__ */
--- diff/include/asm-mips/irq.h	2003-08-20 14:16:33.000000000 +0100
+++ source/include/asm-mips/irq.h	2004-02-23 13:56:47.000000000 +0000
@@ -4,46 +4,14 @@
  * for more details.
  *
  * Copyright (C) 1994 by Waldorf GMBH, written by Ralf Baechle
- * Copyright (C) 1995, 96, 97, 98, 99, 2000, 01, 02 by Ralf Baechle
- * Copyright (C) 1999, 2000 Silicon Graphics, Inc.
- * Copyright (C) 2001 Kanoj Sarcar
+ * Copyright (C) 1995, 96, 97, 98, 99, 2000, 01, 02, 03 by Ralf Baechle
  */
 #ifndef _ASM_IRQ_H
 #define _ASM_IRQ_H
 
 #include <linux/config.h>
 #include <linux/linkage.h>
-#include <asm/sn/arch.h>
-
-#ifdef CONFIG_SGI_IP27
-
-#define NR_IRQS 256
-
-/*
- * Number of levels in INT_PEND0. Can be set to 128 if we also
- * consider INT_PEND1.
- */
-#define PERNODE_LEVELS	64
-
-extern int node_level_to_irq[MAX_COMPACT_NODES][PERNODE_LEVELS];
-
-/*
- * we need to map irq's up to at least bit 7 of the INT_MASK0_A register
- * since bits 0-6 are pre-allocated for other purposes.
- */
-#define LEAST_LEVEL	7
-#define FAST_IRQ_TO_LEVEL(i)	((i) + LEAST_LEVEL)
-#define LEVEL_TO_IRQ(c, l) \
-			(node_level_to_irq[CPUID_TO_COMPACT_NODEID(c)][(l)])
-
-#else
-
-/*
- * Largest number of ints of all machines except IP27
- */
-#define NR_IRQS 128
-
-#endif
+#include <irq.h>
 
 #ifdef CONFIG_I8259
 static inline int irq_canonicalize(int irq)
@@ -61,9 +29,6 @@ extern void enable_irq(unsigned int);
 struct pt_regs;
 extern asmlinkage unsigned int do_IRQ(int irq, struct pt_regs *regs);
 
-/* Machine specific interrupt initialization  */
-extern void (*irq_setup)(void);
-
 extern void init_generic_irq(void);
 
 #endif /* _ASM_IRQ_H */
--- diff/include/asm-mips/irq_cpu.h	2003-08-20 14:16:33.000000000 +0100
+++ source/include/asm-mips/irq_cpu.h	2004-02-23 13:56:47.000000000 +0000
@@ -14,5 +14,6 @@
 #define _ASM_IRQ_CPU_H
 
 extern void mips_cpu_irq_init(int irq_base);
+extern void rm7k_cpu_irq_init(int irq_base);
 
 #endif /* _ASM_IRQ_CPU_H */
--- diff/include/asm-mips/jazz.h	2003-08-20 14:16:33.000000000 +0100
+++ source/include/asm-mips/jazz.h	2004-02-23 13:56:47.000000000 +0000
@@ -203,7 +203,7 @@ typedef struct {
  * we remap the Jazz interrupts to the usual ISA style interrupt numbers.
  */
 #define JAZZ_PARALLEL_IRQ       16
-#define JAZZ_FLOPPY_IRQ          6 /* needs to be consistent with floppy driver! */
+#define JAZZ_FLOPPY_IRQ         17
 #define JAZZ_SOUND_IRQ          18
 #define JAZZ_VIDEO_IRQ          19
 #define JAZZ_ETHERNET_IRQ       20
@@ -283,27 +283,27 @@ __asm__ __volatile__(
 	".set\treorder");
 }
 
-static inline unsigned short r4030_read_reg16(unsigned addr)
+static inline unsigned short r4030_read_reg16(unsigned long addr)
 {
 	unsigned short ret = *((volatile unsigned short *)addr);
 	r4030_delay();
 	return ret;
 }
 
-static inline unsigned int r4030_read_reg32(unsigned addr)
+static inline unsigned int r4030_read_reg32(unsigned long addr)
 {
 	unsigned int ret = *((volatile unsigned int *)addr);
 	r4030_delay();
 	return ret;
 }
 
-static inline void r4030_write_reg16(unsigned addr, unsigned val)
+static inline void r4030_write_reg16(unsigned long addr, unsigned val)
 {
 	*((volatile unsigned short *)addr) = val;
 	r4030_delay();
 }
 
-static inline void r4030_write_reg32(unsigned addr, unsigned val)
+static inline void r4030_write_reg32(unsigned long addr, unsigned val)
 {
 	*((volatile unsigned int *)addr) = val;
 	r4030_delay();
--- diff/include/asm-mips/mc146818rtc.h	2003-07-08 09:55:19.000000000 +0100
+++ source/include/asm-mips/mc146818rtc.h	2004-02-23 13:56:47.000000000 +0000
@@ -11,56 +11,6 @@
 #ifndef _ASM_MC146818RTC_H
 #define _ASM_MC146818RTC_H
 
-#include <linux/config.h>
-
-#include <asm/io.h>
-
-
-/*
- * This structure defines how to access various features of
- * different machine types and how to access them.
- */
-struct rtc_ops {
-	/* How to access the RTC register in a DS1287.  */
-	unsigned char (*rtc_read_data)(unsigned long addr);
-	void (*rtc_write_data)(unsigned char data, unsigned long addr);
-	int (*rtc_bcd_mode)(void);
-};
-
-extern struct rtc_ops *rtc_ops;
-
-/*
- * Most supported machines access the RTC index register via an ISA
- * port access but the way to access the date register differs ...
- * The DECstation directly maps the RTC memory in the CPU's address
- * space with the chipset generating necessary index write/data access
- * cycles automagically.
- */
-#define CMOS_READ(addr) ({ \
-rtc_ops->rtc_read_data(addr); \
-})
-#define CMOS_WRITE(val, addr) ({ \
-rtc_ops->rtc_write_data(val, addr); \
-})
-#define RTC_ALWAYS_BCD \
-rtc_ops->rtc_bcd_mode()
-
-
-#ifdef CONFIG_DECSTATION
-
-#include <asm/dec/rtc-dec.h>
-
-#elif defined(CONFIG_MIPS_PB1500) || defined(CONFIG_MIPS_PB1100)
-
-#define RTC_PORT(x)	(0x0c000000 + (x))
-#define RTC_IOMAPPED	0
-#define RTC_IRQ		0
-
-#else
-
-#define RTC_PORT(x)	(0x70 + (x))
-#define RTC_IRQ		8
-
-#endif
+#include <mc146818rtc.h>
 
 #endif /* _ASM_MC146818RTC_H */
--- diff/include/asm-mips/mips-boards/atlas.h	2003-07-08 09:55:19.000000000 +0100
+++ source/include/asm-mips/mips-boards/atlas.h	2004-02-23 13:56:47.000000000 +0000
@@ -30,25 +30,25 @@
 /*
  * Atlas RTC-device indirect register access.
  */
-#define ATLAS_RTC_ADR_REG       (KSEG1ADDR(0x1f000800))
-#define ATLAS_RTC_DAT_REG       (KSEG1ADDR(0x1f000808))
+#define ATLAS_RTC_ADR_REG       0x1f000800
+#define ATLAS_RTC_DAT_REG       0x1f000808
 
 
 /*
  * Atlas interrupt controller register base.
  */
-#define ATLAS_ICTRL_REGS_BASE   (KSEG1ADDR(0x1f000000))
+#define ATLAS_ICTRL_REGS_BASE   0x1f000000
 
 /*
  * Atlas UART register base.
  */
-#define ATLAS_UART_REGS_BASE    (0x1f000900)
+#define ATLAS_UART_REGS_BASE    0x1f000900
 #define ATLAS_BASE_BAUD ( 3686400 / 16 )
 
 /*
  * Atlas PSU standby register.
  */
-#define ATLAS_PSUSTBY_REG       (KSEG1ADDR(0x1f000600))
+#define ATLAS_PSUSTBY_REG       0x1f000600
 #define ATLAS_GOSTBY            0x4d
 
 /*
@@ -57,6 +57,8 @@
  * This is not ideal, but is needed for setting up remote debugging as
  * soon as possible.
  */
-#define ATLAS_SAA9730_REG  (KSEG1ADDR(0x08800000))
+#define ATLAS_SAA9730_REG	0x10800000
+
+#define ATLAS_SAA9730_BAUDCLOCK	3692300
 
 #endif /* !(_MIPS_ATLAS_H) */
--- diff/include/asm-mips/mips-boards/atlasint.h	2003-07-08 09:55:19.000000000 +0100
+++ source/include/asm-mips/mips-boards/atlasint.h	2004-02-23 13:56:47.000000000 +0000
@@ -25,25 +25,58 @@
 #ifndef _MIPS_ATLASINT_H
 #define _MIPS_ATLASINT_H
 
-/* Number of IRQ supported on hw interrupt 0. */
-#define ATLASINT_UART      0
-#define ATLASINT_END      32
+#define ATLASINT_BASE		1
+#define ATLASINT_UART		(ATLASINT_BASE+0)
+#define ATLASINT_TIM0		(ATLASINT_BASE+1)
+#define ATLASINT_RES2		(ATLASINT_BASE+2)
+#define ATLASINT_RES3		(ATLASINT_BASE+3)
+#define ATLASINT_RTC		(ATLASINT_BASE+4)
+#define ATLASINT_COREHI		(ATLASINT_BASE+5)
+#define ATLASINT_CORELO		(ATLASINT_BASE+6)
+#define ATLASINT_RES7		(ATLASINT_BASE+7)
+#define ATLASINT_PCIA		(ATLASINT_BASE+8)
+#define ATLASINT_PCIB		(ATLASINT_BASE+9)
+#define ATLASINT_PCIC		(ATLASINT_BASE+10)
+#define ATLASINT_PCID		(ATLASINT_BASE+11)
+#define ATLASINT_ENUM		(ATLASINT_BASE+12)
+#define ATLASINT_DEG		(ATLASINT_BASE+13)
+#define ATLASINT_ATXFAIL	(ATLASINT_BASE+14)
+#define ATLASINT_INTA		(ATLASINT_BASE+15)
+#define ATLASINT_INTB		(ATLASINT_BASE+16)
+#define ATLASINT_ETH		ATLASINT_INTB
+#define ATLASINT_INTC		(ATLASINT_BASE+17)
+#define ATLASINT_SCSI		ATLASINT_INTC
+#define ATLASINT_INTD		(ATLASINT_BASE+18)
+#define ATLASINT_SERR		(ATLASINT_BASE+19)
+#define ATLASINT_RES20		(ATLASINT_BASE+20)
+#define ATLASINT_RES21		(ATLASINT_BASE+21)
+#define ATLASINT_RES22		(ATLASINT_BASE+22)
+#define ATLASINT_RES23		(ATLASINT_BASE+23)
+#define ATLASINT_RES24		(ATLASINT_BASE+24)
+#define ATLASINT_RES25		(ATLASINT_BASE+25)
+#define ATLASINT_RES26		(ATLASINT_BASE+26)
+#define ATLASINT_RES27		(ATLASINT_BASE+27)
+#define ATLASINT_RES28		(ATLASINT_BASE+28)
+#define ATLASINT_RES29		(ATLASINT_BASE+29)
+#define ATLASINT_RES30		(ATLASINT_BASE+30)
+#define ATLASINT_RES31		(ATLASINT_BASE+31)
+#define ATLASINT_END		(ATLASINT_BASE+31)
 
 /*
  * Atlas registers are memory mapped on 64-bit aligned boundaries and
  * only word access are allowed.
  */
 struct atlas_ictrl_regs {
-        volatile unsigned long intraw;
-        long dummy1;
-        volatile unsigned long intseten;
-        long dummy2;
-        volatile unsigned long intrsten;
-        long dummy3;
-        volatile unsigned long intenable;
-        long dummy4;
-        volatile unsigned long intstatus;
-        long dummy5;
+        volatile unsigned int intraw;
+        int dummy1;
+        volatile unsigned int intseten;
+        int dummy2;
+        volatile unsigned int intrsten;
+        int dummy3;
+        volatile unsigned int intenable;
+        int dummy4;
+        volatile unsigned int intstatus;
+        int dummy5;
 };
 
 extern void atlasint_init(void);
--- diff/include/asm-mips/mips-boards/bonito64.h	2003-07-08 09:55:19.000000000 +0100
+++ source/include/asm-mips/mips-boards/bonito64.h	2004-02-23 13:56:47.000000000 +0000
@@ -1,28 +1,18 @@
 /*
- * bonito.h
- *
- * Carsten Langgaard, carstenl@mips.com
- * Copyright (C) 2001 MIPS Technologies, Inc.  All rights reserved.
- *
- * ########################################################################
+ * Bonito Register Map
  *
  * This file is the original bonito.h from Algorithmics with minor changes
  * to fit into linux.
- */
-
-/*
- * Bonito Register Map
+ *
  * Copyright (c) 1999 Algorithmics Ltd
  *
+ * Carsten Langgaard, carstenl@mips.com
+ * Copyright (C) 2001 MIPS Technologies, Inc.  All rights reserved.
+ *
  * Algorithmics gives permission for anyone to use and modify this file
  * without any obligation or license condition except that you retain
  * this copyright message in any source redistribution in whole or part.
  *
- * Updated copies of this and other files can be found at
- * ftp://ftp.algor.co.uk/pub/bonito/
- *
- * Users of the Bonito controller are warmly recommended to contribute
- * any useful changes back to Algorithmics (mail to bonito@algor.co.uk).
  */
 
 /* Revision 1.48 autogenerated on 08/17/99 15:20:01 */
@@ -38,9 +28,13 @@
 
 #else /* !__ASSEMBLY__ */
 
-/* offsets from base pointer, this construct allows optimisation */
-/* static char * const _bonito = PA_TO_KVA1(BONITO_BASE); */
-#define BONITO(x)		*(volatile u32 *)(_bonito + (x))
+/*
+ * Algorithmics Bonito64 system controller register base.
+ */
+extern unsigned long _pcictrl_bonito;
+extern unsigned long _pcictrl_bonito_pcicfg;
+
+#define BONITO(x)		*(volatile u32 *)(_pcictrl_bonito + (x))
 
 #endif /* __ASSEMBLY__ */
 
@@ -312,6 +306,11 @@
 #define BONITO_PCICACHECTRL_CACHECMDLINE_SHIFT	3
 #define BONITO_PCICACHECTRL_CMDEXEC	0x00000020
 
+#define BONITO_PCICACHECTRL_IOBCCOH_PRES	0x00000100
+#define BONITO_PCICACHECTRL_IOBCCOH_EN	0x00000200
+#define BONITO_PCICACHECTRL_CPUCOH_PRES	0x00000400
+#define BONITO_PCICACHECTRL_CPUCOH_EN	0x00000800
+
 #define BONITO_IODEVCFG_BUFFBIT_CS0	0x00000001
 #define BONITO_IODEVCFG_SPEEDBIT_CS0	0x00000002
 #define BONITO_IODEVCFG_MOREABITS_CS0	0x00000004
--- diff/include/asm-mips/mips-boards/generic.h	2003-07-08 09:55:19.000000000 +0100
+++ source/include/asm-mips/mips-boards/generic.h	2004-02-23 13:56:47.000000000 +0000
@@ -2,28 +2,23 @@
  * Carsten Langgaard, carstenl@mips.com
  * Copyright (C) 2000 MIPS Technologies, Inc.  All rights reserved.
  *
- * ########################################################################
- *
- *  This program is free software; you can distribute it and/or modify it
- *  under the terms of the GNU General Public License (Version 2) as
- *  published by the Free Software Foundation.
- *
- *  This program is distributed in the hope it will be useful, but WITHOUT
- *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- *  for more details.
- *
- *  You should have received a copy of the GNU General Public License along
- *  with this program; if not, write to the Free Software Foundation, Inc.,
- *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
- *
- * ########################################################################
+ * This program is free software; you can distribute it and/or modify it
+ * under the terms of the GNU General Public License (Version 2) as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
  *
  * Defines of the MIPS boards specific address-MAP, registers, etc.
- *
  */
-#ifndef _MIPS_GENERIC_H
-#define _MIPS_GENERIC_H
+#ifndef __ASM_MIPS_BOARDS_GENERIC_H
+#define __ASM_MIPS_BOARDS_GENERIC_H
 
 #include <linux/config.h>
 #include <asm/addrspace.h>
@@ -33,79 +28,55 @@
 /*
  * Display register base.
  */
-#if defined(CONFIG_MIPS_SEAD)
-#define ASCII_DISPLAY_POS_BASE     (KSEG1ADDR(0x1f0005c0))
+#ifdef CONFIG_MIPS_SEAD
+#define ASCII_DISPLAY_POS_BASE     0x1f0005c0
 #else
-#define ASCII_DISPLAY_WORD_BASE    (KSEG1ADDR(0x1f000410))
-#define ASCII_DISPLAY_POS_BASE     (KSEG1ADDR(0x1f000418))
+#define ASCII_DISPLAY_WORD_BASE    0x1f000410
+#define ASCII_DISPLAY_POS_BASE     0x1f000418
 #endif
 
 
 /*
  * Yamon Prom print address.
  */
-#define YAMON_PROM_PRINT_ADDR      (KSEG1ADDR(0x1fc00504))
+#define YAMON_PROM_PRINT_ADDR      0x1fc00504
 
 
 /*
  * Reset register.
  */
-#if defined(CONFIG_MIPS_SEAD)
-#define SOFTRES_REG       (KSEG1ADDR(0x1e800050))
+#ifdef CONFIG_MIPS_SEAD
+#define SOFTRES_REG       0x1e800050
 #define GORESET           0x4d
 #else
-#define SOFTRES_REG       (KSEG1ADDR(0x1f000500))
+#define SOFTRES_REG       0x1f000500
 #define GORESET           0x42
 #endif
 
 /*
  * Revision register.
  */
-#define MIPS_REVISION_REG                  (KSEG1ADDR(0x1fc00010))
+#define MIPS_REVISION_REG                  0x1fc00010
 #define MIPS_REVISION_CORID_QED_RM5261     0
 #define MIPS_REVISION_CORID_CORE_LV        1
 #define MIPS_REVISION_CORID_BONITO64       2
 #define MIPS_REVISION_CORID_CORE_20K       3
 #define MIPS_REVISION_CORID_CORE_FPGA      4
 #define MIPS_REVISION_CORID_CORE_MSC       5
+#define MIPS_REVISION_CORID_CORE_EMUL      6
+#define MIPS_REVISION_CORID_CORE_FPGA2     7
+#define MIPS_REVISION_CORID_CORE_FPGAR2    8
 
-#define MIPS_REVISION_CORID (((*(volatile u32 *)(MIPS_REVISION_REG)) >> 10) & 0x3f)
-
-extern unsigned int mips_revision_corid;
-
-
+/**** Artificial corid defines ****/
 /*
- * Galileo GT64120 system controller register base.
+ *  CoreEMUL with   Bonito   System Controller is treated like a Core20K
+ *  CoreEMUL with SOC-it 101 System Controller is treated like a CoreMSC
  */
-#define MIPS_GT_BASE    (KSEG1ADDR(0x1be00000))
+#define MIPS_REVISION_CORID_CORE_EMUL_BON  0x63
+#define MIPS_REVISION_CORID_CORE_EMUL_MSC  0x65
 
-/*
- * Because of the way the internal register works on the Galileo chip,
- * we need to swap the bytes when running bigendian.
- */
-#define GT_WRITE(ofs, data)  \
-             *(volatile u32 *)(MIPS_GT_BASE+ofs) = cpu_to_le32(data)
-#define GT_READ(ofs, data)   \
-             data = le32_to_cpu(*(volatile u32 *)(MIPS_GT_BASE+ofs))
-
-#define GT_PCI_WRITE(ofs, data)  \
-	*(volatile u32 *)(MIPS_GT_BASE+ofs) = data
-#define GT_PCI_READ(ofs, data)   \
-	data = *(volatile u32 *)(MIPS_GT_BASE+ofs)
-
-/*
- * Algorithmics Bonito64 system controller register base.
- */
-static char * const _bonito = (char *)KSEG1ADDR(BONITO_REG_BASE);
+#define MIPS_REVISION_CORID (((*(volatile u32 *)ioremap(MIPS_REVISION_REG, 4)) >> 10) & 0x3f)
 
-/*
- * MIPS System controller PCI register base.
- */
-#define MSC01_PCI_REG_BASE  (KSEG1ADDR(0x1bd00000))
-
-#define MSC_WRITE(reg, data)  \
-	*(volatile u32 *)(reg) = data
-#define MSC_READ(reg, data)   \
-	data = *(volatile u32 *)(reg)
+extern unsigned int mips_revision_corid;
 
-#endif  /* !(_MIPS_GENERIC_H) */
+#endif  /* __ASM_MIPS_BOARDS_GENERIC_H */
--- diff/include/asm-mips/mips-boards/malta.h	2003-07-08 09:55:19.000000000 +0100
+++ source/include/asm-mips/mips-boards/malta.h	2004-02-23 13:56:47.000000000 +0000
@@ -17,33 +17,34 @@
  *
  * Defines of the Malta board specific address-MAP, registers, etc.
  */
-#ifndef __ASM_MIPS_MALTA_H
-#define __ASM_MIPS_MALTA_H
+#ifndef __ASM_MIPS_BOARDS_MALTA_H
+#define __ASM_MIPS_BOARDS_MALTA_H
 
 #include <asm/addrspace.h>
-#include <asm/gt64120/gt64120.h>
 #include <asm/io.h>
+#include <asm/mips-boards/msc01_pci.h>
+#include <asm/gt64120.h>
 
 /*
  * Malta I/O ports base address for the Galileo GT64120 and Algorithmics
  * Bonito system controllers.
  */
 #define MALTA_GT_PORT_BASE      get_gt_port_base(GT_PCI0IOLD_OFS)
-#define MALTA_BONITO_PORT_BASE  (KSEG1ADDR(0x1fd00000))
+#define MALTA_BONITO_PORT_BASE  ((unsigned long)ioremap (0x1fd00000, 0x10000))
 #define MALTA_MSC_PORT_BASE     get_msc_port_base(MSC01_PCI_SC2PIOBASL)
 
 static inline unsigned long get_gt_port_base(unsigned long reg)
 {
 	unsigned long addr;
-	GT_READ(reg, addr);
-	return KSEG1ADDR((addr & 0xffff) << 21);
+	addr = GT_READ(reg);
+	return (unsigned long) ioremap (((addr & 0xffff) << 21), 0x10000);
 }
 
 static inline unsigned long get_msc_port_base(unsigned long reg)
 {
 	unsigned long addr;
 	MSC_READ(reg, addr);
-	return KSEG1ADDR(addr);
+	return (unsigned long) ioremap(addr, 0x10000);
 }
 
 /*
@@ -69,6 +70,6 @@ static inline unsigned long get_msc_port
 
 #define SMSC_WRITE(x,a)     outb(x,a)
 
-#define MALTA_JMPRS_REG		(KSEG1ADDR(0x1f000210))
+#define MALTA_JMPRS_REG		0x1f000210
 
-#endif /* __ASM_MIPS_MALTA_H */
+#endif /* __ASM_MIPS_BOARDS_MALTA_H */
--- diff/include/asm-mips/mips-boards/msc01_pci.h	2003-07-08 09:55:19.000000000 +0100
+++ source/include/asm-mips/mips-boards/msc01_pci.h	2004-02-23 13:56:47.000000000 +0000
@@ -1,19 +1,19 @@
 /*
- * mcs01_pci.h
+ * PCI Register definitions for the MIPS System Controller.
  *
  * Carsten Langgaard, carstenl@mips.com
  * Copyright (C) 2002 MIPS Technologies, Inc.  All rights reserved.
  *
- * ########################################################################
- *
- * PCI Register definitions for the MIPS System Controller.
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
  */
-#ifndef MSC01_PCI_H
-#define MSC01_PCI_H
+#ifndef __ASM_MIPS_BOARDS_MSC01_PCI_H
+#define __ASM_MIPS_BOARDS_MSC01_PCI_H
 
-/*****************************************************************************
+/*
  * Register offset addresses
- ****************************************************************************/
+ */
 
 #define MSC01_PCI_ID_OFS		0x0000
 #define MSC01_PCI_SC2PMBASL_OFS		0x0208
@@ -200,9 +200,24 @@
 #define MSC01_PCI_SWAP_NOSWAP		0
 #define MSC01_PCI_SWAP_BYTESWAP		1
 
-/*****************************************************************************
+/*
+ * MIPS System controller PCI register base.
+ *
+ * FIXME - are these macros specific to Malta and co or to the MSC?  If the
+ * latter, they should be moved elsewhere.
+ */
+#define MIPS_MSC01_PCI_REG_BASE	0x1bd00000
+
+extern unsigned long _pcictrl_msc;
+
+#define MSC01_PCI_REG_BASE	_pcictrl_msc
+
+#define MSC_WRITE(reg, data)	do { *(volatile u32 *)(reg) = data; } while (0)
+#define MSC_READ(reg, data)	do { data = *(volatile u32 *)(reg); } while (0)
+
+/*
  * Registers absolute addresses
- ****************************************************************************/
+ */
 
 #define MSC01_PCI_ID            (MSC01_PCI_REG_BASE + MSC01_PCI_ID_OFS)
 #define MSC01_PCI_SC2PMBASL     (MSC01_PCI_REG_BASE + MSC01_PCI_SC2PMBASL_OFS)
@@ -238,7 +253,4 @@
 #define MSC01_PCI_CFG		(MSC01_PCI_REG_BASE + MSC01_PCI_CFG_OFS)
 #define MSC01_PCI_SWAP		(MSC01_PCI_REG_BASE + MSC01_PCI_SWAP_OFS)
 
-#endif
-/*****************************************************************************
- *  End of msc01_pci.h
- *****************************************************************************/
+#endif /* __ASM_MIPS_BOARDS_MSC01_PCI_H */
--- diff/include/asm-mips/mips-boards/piix4.h	2002-10-16 04:27:19.000000000 +0100
+++ source/include/asm-mips/mips-boards/piix4.h	2004-02-23 13:56:47.000000000 +0000
@@ -2,8 +2,6 @@
  * Carsten Langgaard, carstenl@mips.com
  * Copyright (C) 2000 MIPS Technologies, Inc.  All rights reserved.
  *
- * ########################################################################
- *
  *  This program is free software; you can distribute it and/or modify it
  *  under the terms of the GNU General Public License (Version 2) as
  *  published by the Free Software Foundation.
@@ -17,14 +15,10 @@
  *  with this program; if not, write to the Free Software Foundation, Inc.,
  *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
  *
- * ########################################################################
- *
  * Register definitions for Intel PIIX4 South Bridge Device.
- *
  */
-
-#ifndef PIIX4_H
-#define PIIX4_H
+#ifndef __ASM_MIPS_BOARDS_PIIX4_H
+#define __ASM_MIPS_BOARDS_PIIX4_H
 
 /************************************************************************
  *  IO register offsets
@@ -83,4 +77,4 @@
 #define PIIX4_OCW3_IRR          0x2
 #define PIIX4_OCW3_ISR          0x3
 
-#endif /* !(PIIX4_H) */
+#endif /* __ASM_MIPS_BOARDS_PIIX4_H */
--- diff/include/asm-mips/mips-boards/prom.h	2003-08-20 14:16:33.000000000 +0100
+++ source/include/asm-mips/mips-boards/prom.h	2004-02-23 13:56:47.000000000 +0000
@@ -2,6 +2,8 @@
  * Carsten Langgaard, carstenl@mips.com
  * Copyright (C) 2000 MIPS Technologies, Inc.  All rights reserved.
  *
+ * ########################################################################
+ *
  *  This program is free software; you can distribute it and/or modify it
  *  under the terms of the GNU General Public License (Version 2) as
  *  published by the Free Software Foundation.
@@ -15,10 +17,14 @@
  *  with this program; if not, write to the Free Software Foundation, Inc.,
  *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
  *
+ * ########################################################################
+ *
  * MIPS boards bootprom interface for the Linux kernel.
+ *
  */
-#ifndef _ASM_MIPS_BOARDS_PROM_H
-#define _ASM_MIPS_BOARDS_PROM_H
+
+#ifndef _MIPS_PROM_H
+#define _MIPS_PROM_H
 
 extern char *prom_getcmdline(void);
 extern char *prom_getenv(char *name);
@@ -27,7 +33,7 @@ extern void prom_printf(char *fmt, ...);
 extern void prom_init_cmdline(void);
 extern void prom_meminit(void);
 extern void prom_fixup_mem_map(unsigned long start_mem, unsigned long end_mem);
-extern void prom_free_prom_memory (void);
+extern unsigned long prom_free_prom_memory (void);
 extern void mips_display_message(const char *str);
 extern void mips_display_word(unsigned int num);
 extern int get_ethernet_addr(char *ethernet_addr);
@@ -35,9 +41,9 @@ extern int get_ethernet_addr(char *ether
 /* Memory descriptor management. */
 #define PROM_MAX_PMEMBLOCKS    32
 struct prom_pmemblock {
-        unsigned long base; /* Phys addr. */
+        unsigned long base; /* Within KSEG0. */
         unsigned int size;  /* In bytes. */
         unsigned int type;  /* free or prom memory */
 };
 
-#endif /* _ASM_MIPS_BOARDS_PROM_H */
+#endif /* !(_MIPS_PROM_H) */
--- diff/include/asm-mips/mips-boards/seadint.h	2003-07-08 09:55:19.000000000 +0100
+++ source/include/asm-mips/mips-boards/seadint.h	2004-02-23 13:56:47.000000000 +0000
@@ -2,8 +2,6 @@
  * Carsten Langgaard, carstenl@mips.com
  * Copyright (C) 2002 MIPS Technologies, Inc.  All rights reserved.
  *
- * ########################################################################
- *
  *  This program is free software; you can distribute it and/or modify it
  *  under the terms of the GNU General Public License (Version 2) as
  *  published by the Free Software Foundation.
@@ -17,18 +15,13 @@
  *  with this program; if not, write to the Free Software Foundation, Inc.,
  *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
  *
- * ########################################################################
- *
  * Defines for the SEAD interrupt controller.
- *
  */
 #ifndef _MIPS_SEADINT_H
 #define _MIPS_SEADINT_H
 
-/* Number of IRQ supported */
-#define SEADINT_UART0     0
-#define SEADINT_UART1     1
-#define SEADINT_END       2
+#define SEADINT_UART0     2
+#define SEADINT_UART1     3
 
 extern void seadint_init(void);
 
--- diff/include/asm-mips/mipsregs.h	2003-08-20 14:16:33.000000000 +0100
+++ source/include/asm-mips/mipsregs.h	2004-02-23 13:56:47.000000000 +0000
@@ -15,6 +15,7 @@
 
 #include <linux/config.h>
 #include <linux/linkage.h>
+#include <asm/hazards.h>
 
 /*
  * The following macros are especially useful for __asm__
@@ -185,6 +186,20 @@
 #endif
 
 /*
+ * Default page size for a given kernel configuration
+ */
+#ifdef CONFIG_PAGE_SIZE_4KB
+#define PM_DEFAULT_MASK	PM_4K
+#elif defined(CONFIG_PAGE_SIZE_16KB)
+#define PM_DEFAULT_MASK	PM_16K
+#elif defined(CONFIG_PAGE_SIZE_64KB)
+#define PM_DEFAULT_MASK	PM_64K
+#else
+#error Bad page size configuration!
+#endif
+
+
+/*
  * Values used for computation of new tlb entries
  */
 #define PL_4K		12
@@ -578,13 +593,13 @@ do {									\
 	if (sel == 0)							\
 		__asm__ __volatile__(					\
 			"mtc0\t%z0, " #register "\n\t"			\
-			: : "Jr" (value));				\
+			: : "Jr" ((unsigned int)value));		\
 	else								\
 		__asm__ __volatile__(					\
 			".set\tmips32\n\t"				\
 			"mtc0\t%z0, " #register ", " #sel "\n\t"	\
 			".set\tmips0"					\
-			: : "Jr" (value));				\
+			: : "Jr" ((unsigned int)value));		\
 } while (0)
 
 #define __write_64bit_c0_register(register, sel, value)			\
@@ -821,37 +836,47 @@ do {									\
         : "=r" (__res));                                        \
         __res;})
 
-/* TLB operations. */
+/*
+ * TLB operations.
+ */
 static inline void tlb_probe(void)
 {
+	rm9000_tlb_hazard();
 	__asm__ __volatile__(
 		".set noreorder\n\t"
 		"tlbp\n\t"
 		".set reorder");
+	rm9000_tlb_hazard();
 }
 
 static inline void tlb_read(void)
 {
+	rm9000_tlb_hazard();
 	__asm__ __volatile__(
 		".set noreorder\n\t"
 		"tlbr\n\t"
 		".set reorder");
+	rm9000_tlb_hazard();
 }
 
 static inline void tlb_write_indexed(void)
 {
+	rm9000_tlb_hazard();
 	__asm__ __volatile__(
 		".set noreorder\n\t"
 		"tlbwi\n\t"
 		".set reorder");
+	rm9000_tlb_hazard();
 }
 
 static inline void tlb_write_random(void)
 {
+	rm9000_tlb_hazard();
 	__asm__ __volatile__(
 		".set noreorder\n\t"
 		"tlbwr\n\t"
 		".set reorder");
+	rm9000_tlb_hazard();
 }
 
 /*
@@ -898,6 +923,7 @@ change_c0_##name(unsigned int change, un
 __BUILD_SET_C0(status,CP0_STATUS)
 __BUILD_SET_C0(cause,CP0_CAUSE)
 __BUILD_SET_C0(config,CP0_CONFIG)
+__BUILD_SET_C0(intcontrol,CP0_CONFIG)
 
 #endif /* !__ASSEMBLY__ */
 
--- diff/include/asm-mips/mmu_context.h	2003-08-20 14:16:33.000000000 +0100
+++ source/include/asm-mips/mmu_context.h	2004-02-23 13:56:47.000000000 +0000
@@ -30,12 +30,12 @@
 	pgd_current[smp_processor_id()] = (unsigned long)(pgd)
 #ifdef CONFIG_MIPS32
 #define TLBMISS_HANDLER_SETUP() \
-	write_c0_context((unsigned long) smp_processor_id() << (23 + 3)); \
+	write_c0_context((unsigned long) smp_processor_id() << 23); \
 	TLBMISS_HANDLER_SETUP_PGD(swapper_pg_dir)
 #endif
 #ifdef CONFIG_MIPS64
 #define TLBMISS_HANDLER_SETUP() \
-	write_c0_context((unsigned long) smp_processor_id() << 23); \
+	write_c0_context((unsigned long) &pgd_current[smp_processor_id()] << 23); \
 	TLBMISS_HANDLER_SETUP_PGD(swapper_pg_dir)
 #endif
 extern unsigned long pgd_current[];
--- diff/include/asm-mips/mmzone.h	2004-02-18 08:54:12.000000000 +0000
+++ source/include/asm-mips/mmzone.h	2004-02-23 13:56:47.000000000 +0000
@@ -1,94 +1,42 @@
 /*
  * Written by Kanoj Sarcar (kanoj@sgi.com) Aug 99
+ * Rewritten for Linux 2.6 by Christoph Hellwig (hch@lst.de) Jan 2004
  */
 #ifndef _ASM_MMZONE_H_
 #define _ASM_MMZONE_H_
 
-#include <linux/config.h>
-#include <asm/sn/types.h>
-#include <asm/sn/addrs.h>
-#include <asm/sn/arch.h>
-#include <asm/sn/klkernvars.h>
-
-typedef struct plat_pglist_data {
-	pg_data_t	gendata;
-	kern_vars_t	kern_vars;
-} plat_pg_data_t;
+#include <asm/page.h>
+#include <mmzone.h>
 
-/*
- * Following are macros that are specific to this numa platform.
- */
-
-extern int numa_debug(void);
-extern plat_pg_data_t *plat_node_data[];
-
-#define PHYSADDR_TO_NID(pa)		NASID_TO_COMPACT_NODEID(NASID_GET(pa))
-#define PLAT_NODE_DATA(n)		(plat_node_data[n])
-#define PLAT_NODE_DATA_SIZE(n)	     (PLAT_NODE_DATA(n)->gendata.node_spanned_pages)
-#define PLAT_NODE_DATA_LOCALNR(p, n) \
-		(((p) >> PAGE_SHIFT) - PLAT_NODE_DATA(n)->gendata.node_start_pfn)
-
-#ifdef CONFIG_DISCONTIGMEM
-
-/*
- * Following are macros that each numa implmentation must define.
- */
-
-/*
- * Given a kernel address, find the home node of the underlying memory.
- */
-#define KVADDR_TO_NID(kaddr) \
-	((NASID_TO_COMPACT_NODEID(NASID_GET(__pa(kaddr))) != -1) ? \
-	(NASID_TO_COMPACT_NODEID(NASID_GET(__pa(kaddr)))) : \
-	(printk("NUMABUG: %s line %d addr 0x%lx", __FILE__, __LINE__, kaddr), \
-	numa_debug(), -1))
-
-/*
- * Return a pointer to the node data for node n.
- */
-#define NODE_DATA(n)	(&((PLAT_NODE_DATA(n))->gendata))
+extern struct pglist_data *node_data[];
 
-/*
- * NODE_MEM_MAP gives the kaddr for the mem_map of the node.
- */
-#define NODE_MEM_MAP(nid)	(NODE_DATA(nid)->node_mem_map)
-
-/*
- * Given a kaddr, ADDR_TO_MAPBASE finds the owning node of the memory
- * and returns the mem_map of that node.
- */
-#define ADDR_TO_MAPBASE(kaddr) \
-			NODE_MEM_MAP(KVADDR_TO_NID((unsigned long)(kaddr)))
-
-/*
- * Given a kaddr, LOCAL_BASE_ADDR finds the owning node of the memory
- * and returns the kaddr corresponding to first physical page in the
- * node's mem_map.
- */
-#define LOCAL_BASE_ADDR(kaddr)	((unsigned long)(kaddr) & ~(NODE_MAX_MEM_SIZE-1))
-
-#define LOCAL_MAP_NR(kvaddr) \
-	(((unsigned long)(kvaddr)-LOCAL_BASE_ADDR((kvaddr))) >> PAGE_SHIFT)
-
-#define MIPS64_NR(kaddr) (((unsigned long)(kaddr) > (unsigned long)high_memory)\
-		? (max_mapnr + 1) : (LOCAL_MAP_NR((kaddr)) + \
-		(((unsigned long)ADDR_TO_MAPBASE((kaddr)) - PAGE_OFFSET) / \
-		sizeof(struct page))))
+#define NODE_DATA(n)		(node_data[(n)])
+#define kvaddr_to_nid(kvaddr)	pa_to_nid(__pa(kvaddr))
+#define pfn_to_nid(pfn)		pa_to_nid((pfn) << PAGE_SHIFT)
+
+#define pfn_valid(pfn)						\
+({								\
+ 	unsigned long __pfn = (pfn);				\
+ 	int __n = pfn_to_nid(__pfn);				\
+	((__n >= 0) ? (__pfn < NODE_DATA(__n)->node_start_pfn +	\
+		       NODE_DATA(__n)->node_spanned_pages) : 0);\
+})
+
+#define pfn_to_page(pfn)					\
+({								\
+ 	unsigned long __pfn = (pfn);				\
+	pg_data_t *__pg = NODE_DATA(pfn_to_nid(__pfn));		\
+	__pg->node_mem_map + (__pfn - __pg->node_start_pfn);	\
+})
+
+#define page_to_pfn(p)						\
+({								\
+	struct page *__p = (p);					\
+	struct zone *__z = page_zone(__p);			\
+	((__p - __z->zone_mem_map) + __z->zone_start_pfn);	\
+})
 
 /* XXX: FIXME -- wli */
 #define kern_addr_valid(addr)	(0)
 
-#define pfn_to_page(pfn)	(mem_map + (pfn))
-#define page_to_pfn(page) \
-	((((page)-(page)->zone->zone_mem_map) + (page)->zone->zone_start_pfn) \
-	 << PAGE_SHIFT)
-#define virt_to_page(kaddr)	pfn_to_page(MIPS64_NR(kaddr))
-
-#define pfn_valid(pfn)		((pfn) < max_mapnr)
-#define virt_addr_valid(kaddr)	pfn_valid(__pa(kaddr) >> PAGE_SHIFT)
-#define pte_pfn(x)		((unsigned long)((x).pte >> PAGE_SHIFT))
-#define pfn_pte(pfn, prot)	__pte(((pfn) << PAGE_SHIFT) | pgprot_val(prot))
-
-#endif /* CONFIG_DISCONTIGMEM */
-
 #endif /* _ASM_MMZONE_H_ */
--- diff/include/asm-mips/msgbuf.h	2003-07-08 09:55:19.000000000 +0100
+++ source/include/asm-mips/msgbuf.h	2004-02-23 13:56:47.000000000 +0000
@@ -1,23 +1,41 @@
 #ifndef _ASM_MSGBUF_H
 #define _ASM_MSGBUF_H
 
+#include <linux/config.h>
+
 /*
- * The msqid64_ds structure for alpha architecture.
+ * The msqid64_ds structure for the MIPS architecture.
  * Note extra padding because this structure is passed back and forth
  * between kernel and user space.
  *
  * Pad space is left for:
- * - 2 miscellaneous 64-bit values
+ * - extension of time_t to 64-bit on 32-bitsystem to solve the y2038 problem
+ * - 2 miscellaneous unsigned long values
  */
 
 struct msqid64_ds {
 	struct ipc64_perm msg_perm;
+#if defined(CONFIG_MIPS32) && !defined(CONFIG_CPU_LITTLE_ENDIAN)
+	unsigned long	__unused1;
+#endif
 	__kernel_time_t msg_stime;	/* last msgsnd time */
+#if defined(CONFIG_MIPS32) && defined(CONFIG_CPU_LITTLE_ENDIAN)
 	unsigned long	__unused1;
+#endif
+#if defined(CONFIG_MIPS32) && !defined(CONFIG_CPU_LITTLE_ENDIAN)
+	unsigned long	__unused2;
+#endif
 	__kernel_time_t msg_rtime;	/* last msgrcv time */
+#if defined(CONFIG_MIPS32) && defined(CONFIG_CPU_LITTLE_ENDIAN)
 	unsigned long	__unused2;
+#endif
+#if defined(CONFIG_MIPS32) && !defined(CONFIG_CPU_LITTLE_ENDIAN)
+	unsigned long	__unused3;
+#endif
 	__kernel_time_t msg_ctime;	/* last change time */
+#if defined(CONFIG_MIPS32) && defined(CONFIG_CPU_LITTLE_ENDIAN)
 	unsigned long	__unused3;
+#endif
 	unsigned long  msg_cbytes;	/* current number of bytes on queue */
 	unsigned long  msg_qnum;	/* number of messages in queue */
 	unsigned long  msg_qbytes;	/* max number of bytes on queue */
--- diff/include/asm-mips/mv64340.h	2003-07-08 09:55:19.000000000 +0100
+++ source/include/asm-mips/mv64340.h	2004-02-23 13:56:47.000000000 +0000
@@ -1,18 +1,17 @@
-/*******************************************************************************
-* mv64340.h - MV-64340 Internal registers definition file.
-*
-* Copyright 2002 Momentum Computer, Inc.
-* Copyright 2002 GALILEO TECHNOLOGY, LTD. 
-*
-* This program is free software; you can redistribute  it and/or modify it
-* under  the terms of  the GNU General  Public License as published by the
-* Free Software Foundation;  either version 2 of the  License, or (at your
-* option) any later version.
-*
-*******************************************************************************/
-
-#ifndef __MV64340_H__
-#define __MV64340_H__
+/*
+ * mv64340.h - MV-64340 Internal registers definition file.
+ *
+ * Copyright 2002 Momentum Computer, Inc.
+ * Copyright 2002 GALILEO TECHNOLOGY, LTD. 
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ *
+ */
+#ifndef __ASM_MV64340_H
+#define __ASM_MV64340_H
 
 #include <asm/mv64340_dep.h>
 
@@ -1034,4 +1033,9 @@
 #define MV64340_SERIAL_INIT_CONTROL                                 0xf328
 #define MV64340_SERIAL_INIT_STATUS                                  0xf32c
 
-#endif
+struct pci;
+
+extern mv64340_bus0_pci_ops;
+extern mv64340_bus1_pci_ops;
+
+#endif /* __ASM_MV64340_H */
--- diff/include/asm-mips/namei.h	2003-08-20 14:16:33.000000000 +0100
+++ source/include/asm-mips/namei.h	2004-02-23 13:56:47.000000000 +0000
@@ -1,27 +1,26 @@
-/*
- * Included from linux/fs/namei.c
- */
 #ifndef _ASM_NAMEI_H
 #define _ASM_NAMEI_H
 
-#include <linux/config.h>
+#include <linux/personality.h>
+#include <linux/stddef.h>
 
-/* Only one at this time. */
-#define IRIX32_EMUL "usr/gnemul/irix/"
-
-#ifdef CONFIG_BINFMT_IRIX
+#define IRIX_EMUL	"/usr/gnemul/irix/"
+#define RISCOS_EMUL	"/usr/gnemul/riscos/"
 
 static inline char *__emul_prefix(void)
 {
-	if (current->personality != PER_IRIX32)
-		return NULL;
-	return IRIX32_EMUL;
-}
+	switch (current->personality) {
+	case PER_IRIX32:
+	case PER_IRIXN32:
+	case PER_IRIX64:
+		return IRIX_EMUL;
 
-#else /* !defined(CONFIG_BINFMT_IRIX) */
+	case PER_RISCOS:
+		return RISCOS_EMUL;
 
-#define __emul_prefix() NULL
-
-#endif /* !defined(CONFIG_BINFMT_IRIX) */
+	default:
+		return NULL;
+	}
+}
 
 #endif /* _ASM_NAMEI_H */
--- diff/include/asm-mips/page-32.h	2003-08-20 14:16:36.000000000 +0100
+++ source/include/asm-mips/page-32.h	2004-02-23 13:56:47.000000000 +0000
@@ -9,14 +9,11 @@
 #ifndef _ASM_PAGE_32_H
 #define _ASM_PAGE_32_H
 
-#include <linux/config.h>
-
 /*
  * This handles the memory map.
  * We handle pages at KSEG0 for kernels with 32 bit address space.
  */
 #define PAGE_OFFSET		0x80000000UL
-#define UNCAC_BASE		0xa0000000UL
 
 /*
  * Memory above this physical address will be considered highmem.
--- diff/include/asm-mips/page-64.h	2003-08-20 14:16:36.000000000 +0100
+++ source/include/asm-mips/page-64.h	2004-02-23 13:56:47.000000000 +0000
@@ -14,13 +14,12 @@
 /*
  * This handles the memory map.
  */
-#ifdef CONFIG_NONCOHERENT_IO
+#ifdef CONFIG_DMA_NONCOHERENT
 #define PAGE_OFFSET	0x9800000000000000UL
 #else
 #define PAGE_OFFSET	0xa800000000000000UL
 #endif
 
-
 /*
  * Memory above this physical address will be considered highmem.
  * Fixme: 59 bits is a fictive number and makes assumptions about processors
--- diff/include/asm-mips/page.h	2003-08-20 14:16:33.000000000 +0100
+++ source/include/asm-mips/page.h	2004-02-23 13:56:47.000000000 +0000
@@ -18,20 +18,27 @@
 #include <asm/page-64.h>
 #endif
 
-/* PAGE_SHIFT determines the page size */
+#ifdef __KERNEL__
+
+/*
+ * PAGE_SHIFT determines the page size
+ */
+#ifdef CONFIG_PAGE_SIZE_4KB
 #define PAGE_SHIFT	12
+#endif
+#ifdef CONFIG_PAGE_SIZE_16KB
+#define PAGE_SHIFT	14
+#endif
+#ifdef CONFIG_PAGE_SIZE_64KB
+#define PAGE_SHIFT	16
+#endif
 #define PAGE_SIZE	(1UL << PAGE_SHIFT)
 #define PAGE_MASK	(~(PAGE_SIZE-1))
 
-#ifdef __KERNEL__
-
 #ifndef __ASSEMBLY__
 
-extern void (*_clear_page)(void * page);
-extern void (*_copy_page)(void * to, void * from);
-
-#define clear_page(addr)		_clear_page((void *)(addr))
-#define copy_page(to, from)		_copy_page((void *)(to), (void *)(from))
+extern void clear_page(void * page);
+extern void copy_page(void * to, void * from);
 
 extern unsigned long shm_align_mask;
 
@@ -114,12 +121,12 @@ static __inline__ int get_order(unsigned
 #ifndef CONFIG_DISCONTIGMEM
 #define pfn_to_page(pfn)	(mem_map + (pfn))
 #define page_to_pfn(page)	((unsigned long)((page) - mem_map))
-#define virt_to_page(kaddr)	pfn_to_page(__pa(kaddr) >> PAGE_SHIFT)
-
 #define pfn_valid(pfn)		((pfn) < max_mapnr)
-#define virt_addr_valid(kaddr)	pfn_valid(__pa(kaddr) >> PAGE_SHIFT)
 #endif
 
+#define virt_to_page(kaddr)	pfn_to_page(__pa(kaddr) >> PAGE_SHIFT)
+#define virt_addr_valid(kaddr)	pfn_valid(__pa(kaddr) >> PAGE_SHIFT)
+
 #define VM_DATA_DEFAULT_FLAGS	(VM_READ | VM_WRITE | VM_EXEC | \
 				 VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC)
 
--- diff/include/asm-mips/param.h	2003-07-08 09:55:19.000000000 +0100
+++ source/include/asm-mips/param.h	2004-02-23 13:56:47.000000000 +0000
@@ -11,18 +11,7 @@
 
 #ifdef __KERNEL__
 
-#include <linux/config.h>
-
-#ifdef CONFIG_DECSTATION
-   /*
-    * log2(HZ), change this here if you want another HZ value. This is also
-    * used in dec_time_init.  Minimum is 1, Maximum is 15.
-    */
-#  define LOG_2_HZ 7
-#  define HZ (1 << LOG_2_HZ)
-#else
-# define HZ		1000		/* Internal kernel timer frequency */
-#endif
+# include <param.h>			/* Internal kernel timer frequency */
 # define USER_HZ	100		/* .. some user interfaces are in "ticks" */
 # define CLOCKS_PER_SEC	(USER_HZ)	/* like times() */
 #endif
@@ -31,11 +20,7 @@
 #define HZ 100
 #endif
 
-#define EXEC_PAGESIZE	4096
-
-#ifndef NGROUPS
-#define NGROUPS		32
-#endif
+#define EXEC_PAGESIZE	65536
 
 #ifndef NOGROUP
 #define NOGROUP		(-1)
--- diff/include/asm-mips/pci.h	2004-02-18 08:54:12.000000000 +0000
+++ source/include/asm-mips/pci.h	2004-02-23 13:56:47.000000000 +0000
@@ -15,20 +15,16 @@
    already-configured bus numbers - to be used for buggy BIOSes
    or architectures with incomplete PCI setup by the loader */
 
-#ifdef CONFIG_PCI
 extern unsigned int pcibios_assign_all_busses(void);
-#else
-#define pcibios_assign_all_busses()	0
-#endif
+
 #define pcibios_scan_all_fns(a, b)	0
 
-#define PCIBIOS_MIN_IO		0x1000
-#define PCIBIOS_MIN_MEM		0x10000000
+extern unsigned long PCIBIOS_MIN_IO;
+extern unsigned long PCIBIOS_MIN_MEM;
 
-static inline void pcibios_set_master(struct pci_dev *dev)
-{
-	/* No special bus mastering setup handling */
-}
+#define PCIBIOS_MIN_CARDBUS_IO	0x4000
+
+extern void pcibios_set_master(struct pci_dev *dev);
 
 static inline void pcibios_penalize_isa_irq(int irq)
 {
@@ -46,21 +42,14 @@ static inline void pcibios_penalize_isa_
 #include <linux/string.h>
 #include <asm/io.h>
 
-#if defined(CONFIG_DDB5074) || defined(CONFIG_DDB5476)
-#undef PCIBIOS_MIN_IO
-#undef PCIBIOS_MIN_MEM
-#define PCIBIOS_MIN_IO		0x0100000
-#define PCIBIOS_MIN_MEM		0x1000000
-#endif
-
 struct pci_dev;
 
 /*
  * The PCI address space does equal the physical memory address space.  The
  * networking and block device layers use this boolean for bounce buffer
- * decisions.
+ * decisions.  This is set if any hose does not have an IOMMU.
  */
-#define PCI_DMA_BUS_IS_PHYS	(1)
+extern unsigned int PCI_DMA_BUS_IS_PHYS;
 
 #ifdef CONFIG_MAPPED_DMA_IO
 
@@ -87,49 +76,22 @@ struct pci_dev;
 /* This is always fine. */
 #define pci_dac_dma_supported(pci_dev, mask)	(1)
 
-static inline dma64_addr_t pci_dac_page_to_dma(struct pci_dev *pdev,
-	struct page *page, unsigned long offset, int direction)
-{
-	dma64_addr_t addr = page_to_phys(page) + offset;
-
-	return (dma64_addr_t) bus_to_baddr(pdev->bus, addr);
-}
-
-static inline struct page *pci_dac_dma_to_page(struct pci_dev *pdev,
-	dma64_addr_t dma_addr)
-{
-	unsigned long poff = baddr_to_bus(pdev->bus, dma_addr) >> PAGE_SHIFT;
-
-	return mem_map + poff;
-}
-
-static inline unsigned long pci_dac_dma_to_offset(struct pci_dev *pdev,
-	dma64_addr_t dma_addr)
-{
-	return dma_addr & ~PAGE_MASK;
-}
-
-static inline void pci_dac_dma_sync_single(struct pci_dev *pdev,
-	dma64_addr_t dma_addr, size_t len, int direction)
-{
-	unsigned long addr;
-
-	BUG_ON(direction == PCI_DMA_NONE);
-
-	addr = baddr_to_bus(pdev->bus, dma_addr) + PAGE_OFFSET;
-	dma_cache_wback_inv(addr, len);
-}
-
-static inline void pcibios_add_platform_entries(struct pci_dev *dev)
-{
-}
+extern dma64_addr_t pci_dac_page_to_dma(struct pci_dev *pdev,
+	struct page *page, unsigned long offset, int direction);
+extern struct page *pci_dac_dma_to_page(struct pci_dev *pdev,
+	dma64_addr_t dma_addr);
+extern unsigned long pci_dac_dma_to_offset(struct pci_dev *pdev,
+	dma64_addr_t dma_addr);
+extern void pci_dac_dma_sync_single(struct pci_dev *pdev,
+	dma64_addr_t dma_addr, size_t len, int direction);
 
 #endif /* __KERNEL__ */
 
 /* implement the pci_ DMA API in terms of the generic device dma_ one */
 #include <asm-generic/pci-dma-compat.h>
 
-/* generic pci stuff */
-#include <asm-generic/pci.h>
+static inline void pcibios_add_platform_entries(struct pci_dev *dev)
+{
+}
 
 #endif /* _ASM_PCI_H */
--- diff/include/asm-mips/pci/bridge.h	2003-08-20 14:16:36.000000000 +0100
+++ source/include/asm-mips/pci/bridge.h	2004-02-23 13:56:47.000000000 +0000
@@ -13,6 +13,7 @@
 #define _ASM_PCI_BRIDGE_H
 
 #include <linux/types.h>
+#include <asm/pci_channel.h>
 #include <asm/xtalk/xwidget.h>		/* generic widget header */
 
 /* I/O page size */
@@ -388,9 +389,11 @@ typedef struct bridge_err_cmdword_s {
 
 /* Widget part number of bridge */
 #define BRIDGE_WIDGET_PART_NUM		0xc002
+#define XBRIDGE_WIDGET_PART_NUM		0xd002
 
 /* Manufacturer of bridge */
 #define BRIDGE_WIDGET_MFGR_NUM		0x036
+#define XBRIDGE_WIDGET_MFGR_NUM		0x024
 
 /* Revision numbers for known Bridge revisions */
 #define BRIDGE_REV_A			0x1
@@ -827,11 +830,19 @@ typedef union ate_u {
 
 #define BRIDGE_INTERNAL_ATES	128
 
-/*
- * Linux pci bus mappings to sn physical id's
- */
-extern unsigned char bus_to_wid[];	/* widget id for linux pci bus */
-extern unsigned char bus_to_nid[];	/* nasid for linux pci bus */
-extern unsigned char num_bridges;	/* number of bridges in the system */
+
+struct bridge_controller {
+	struct pci_controller	pc;
+	struct resource		mem;
+	struct resource		io;
+	bridge_t		*base;
+	nasid_t			nasid;
+	unsigned int		widget_id;
+	unsigned int 		irq_cpu;
+	dma64_addr_t		baddr;
+};
+
+#define BRIDGE_CONTROLLER(bus) \
+	((struct bridge_controller *)((bus)->sysdata))
 
 #endif /* _ASM_PCI_BRIDGE_H */
--- diff/include/asm-mips/pci_channel.h	2003-07-08 09:55:19.000000000 +0100
+++ source/include/asm-mips/pci_channel.h	2004-02-23 13:56:47.000000000 +0000
@@ -15,27 +15,32 @@
  * multiple PCI channels may have multiple PCI host controllers or a
  * single controller supporting multiple channels.
  */
-struct pci_channel {
+struct pci_controller {
+	struct pci_controller *next;
+	struct pci_bus *bus;
+
 	struct pci_ops *pci_ops;
-	struct resource *io_resource;
 	struct resource *mem_resource;
-	int first_devfn;
-	int last_devfn;
+	unsigned long mem_offset;
+	struct resource *io_resource;
+	unsigned long io_offset;
+
+	/* For compatibility with current (as of July 2003) pciutils
+	   and XFree86. Eventually will be removed. */
+	unsigned int need_domain_info;
+
+	int iommu;
 };
 
 /*
- * each board defines an array of pci_channels, that ends with all NULL entry
+ * Used by boards to register their PCI interfaces before the actual scanning.
  */
-extern struct pci_channel mips_pci_channels[];
+extern struct pci_controller * alloc_pci_controller(void);
+extern void register_pci_controller(struct pci_controller *hose);
 
 /*
  * board supplied pci irq fixup routine
  */
-extern void pcibios_fixup_irqs(void);
-
-/*
- * board supplied pci fixup routines
- */
-extern void pcibios_fixup_resources(struct pci_dev *dev);
+extern int pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin);
 
 #endif  /* __ASM_PCI_CHANNEL_H */
--- diff/include/asm-mips/pgalloc.h	2003-08-20 14:16:33.000000000 +0100
+++ source/include/asm-mips/pgalloc.h	2004-02-23 13:56:47.000000000 +0000
@@ -86,7 +86,6 @@ static inline void pte_free(struct page 
 }
 
 #define __pte_free_tlb(tlb,pte)		tlb_remove_page((tlb),(pte))
-#define __pmd_free_tlb(tlb,x)		do { } while (0)
 
 #ifdef CONFIG_MIPS32
 #define pgd_populate(mm, pmd, pte)	BUG()
@@ -97,6 +96,7 @@ static inline void pte_free(struct page 
  */
 #define pmd_alloc_one(mm, addr)		({ BUG(); ((pmd_t *)2); })
 #define pmd_free(x)			do { } while (0)
+#define __pmd_free_tlb(tlb,x)		do { } while (0)
 #endif
 
 #ifdef CONFIG_MIPS64
@@ -118,6 +118,8 @@ static inline void pmd_free(pmd_t *pmd)
 	free_pages((unsigned long)pmd, PMD_ORDER);
 }
 
+#define __pmd_free_tlb(tlb,x)	pmd_free(x)
+
 #endif
 
 /*
--- diff/include/asm-mips/pgtable-32.h	2003-10-09 09:47:34.000000000 +0100
+++ source/include/asm-mips/pgtable-32.h	2004-02-23 13:56:47.000000000 +0000
@@ -60,27 +60,25 @@ extern int add_temporary_entry(unsigned 
  * we don't really have any PMD directory physically.
  */
 #ifdef CONFIG_64BIT_PHYS_ADDR
-#define PTRS_PER_PTE	512
-#define PTRS_PER_PMD	1
-#define PTRS_PER_PGD	2048
 #define PGD_ORDER	1
 #define PMD_ORDER	0
 #define PTE_ORDER	0
 #else
-#define PTRS_PER_PTE	1024
-#define PTRS_PER_PMD	1
-#define PTRS_PER_PGD	1024
 #define PGD_ORDER	0
 #define PMD_ORDER	0
 #define PTE_ORDER	0
 #endif
 
+#define PTRS_PER_PGD	((PAGE_SIZE << PGD_ORDER) / sizeof(pgd_t))
+#define PTRS_PER_PMD	1
+#define PTRS_PER_PTE	((PAGE_SIZE << PTE_ORDER) / sizeof(pte_t))
+
 #define USER_PTRS_PER_PGD	(0x80000000UL/PGDIR_SIZE)
 #define FIRST_USER_PGD_NR	0
 
 #define VMALLOC_START     KSEG2
 
-#if CONFIG_HIGHMEM
+#ifdef CONFIG_HIGHMEM
 # define VMALLOC_END	(PKMAP_BASE-2*PAGE_SIZE)
 #else
 # define VMALLOC_END	(FIXADDR_START-2*PAGE_SIZE)
@@ -133,8 +131,15 @@ static inline int pgd_present(pgd_t pgd)
 static inline void pgd_clear(pgd_t *pgdp)	{ }
 
 #define pte_page(x)		pfn_to_page(pte_pfn(x))
+
+
+#ifdef CONFIG_CPU_VR41XX
+#define pte_pfn(x)		((unsigned long)((x).pte >> (PAGE_SHIFT + 2)))
+#define pfn_pte(pfn, prot)	__pte(((pfn) << (PAGE_SHIFT + 2)) | pgprot_val(prot))
+#else
 #define pte_pfn(x)		((unsigned long)((x).pte >> PAGE_SHIFT))
 #define pfn_pte(pfn, prot)	__pte(((pfn) << PAGE_SHIFT) | pgprot_val(prot))
+#endif
 
 #if defined(CONFIG_CPU_R3000) || defined(CONFIG_CPU_TX39XX)
 
@@ -195,9 +200,6 @@ static inline pmd_t *pmd_offset(pgd_t *d
 #define pte_unmap(pte) ((void)(pte))
 #define pte_unmap_nested(pte) ((void)(pte))
 
-extern pgd_t swapper_pg_dir[1024];
-extern void paging_init(void);
-
 /* Swap entries must have VALID and GLOBAL bits cleared. */
 #if defined(CONFIG_CPU_R3000) || defined(CONFIG_CPU_TX39XX)
 
--- diff/include/asm-mips/pgtable-64.h	2003-10-09 09:47:34.000000000 +0100
+++ source/include/asm-mips/pgtable-64.h	2004-02-23 13:56:47.000000000 +0000
@@ -10,13 +10,10 @@
 #define _ASM_PGTABLE_64_H
 
 #include <linux/config.h>
+#include <linux/linkage.h>
+
 #include <asm/addrspace.h>
 #include <asm/page.h>
-
-#ifndef __ASSEMBLY__
-
-#include <linux/linkage.h>
-#include <linux/mmzone.h>
 #include <asm/cachectl.h>
 
 /*
@@ -39,8 +36,6 @@
  * vmalloc range translations, which the fault handler looks at.
  */
 
-#endif /* !__ASSEMBLY__ */
-
 /* PMD_SHIFT determines the size of the area a second-level page table can map */
 #define PMD_SHIFT	(PAGE_SHIFT + (PAGE_SHIFT - 3))
 #define PMD_SIZE	(1UL << PMD_SHIFT)
@@ -51,14 +46,39 @@
 #define PGDIR_SIZE	(1UL << PGDIR_SHIFT)
 #define PGDIR_MASK	(~(PGDIR_SIZE-1))
 
-/* Entries per page directory level: we use two-level, so we don't really
-   have any PMD directory physically.  */
-#define PTRS_PER_PGD		1024
-#define PTRS_PER_PMD		1024
-#define PTRS_PER_PTE		512
+/*
+ * For 4kB page size we use a 3 level page tree and a 8kB pmd and pgds which
+ * permits us mapping 40 bits of virtual address space.
+ *
+ * We used to implement 41 bits by having an order 1 pmd level but that seemed
+ * rather pointless.
+ *
+ * For 16kB page size we use a 2 level page tree which permit a total of
+ * 36 bits of virtual address space.  We could add a third leve. but it seems
+ * like at the moment there's no need for this.
+ *
+ * For 64kB page size we use a 2 level page table tree for a total of 42 bits
+ * of virtual address space.
+ */
+#ifdef CONFIG_PAGE_SIZE_4KB
 #define PGD_ORDER		1
 #define PMD_ORDER		1
 #define PTE_ORDER		0
+#endif
+#ifdef CONFIG_PAGE_SIZE_16KB
+#define PGD_ORDER		0
+#define PMD_ORDER		0
+#define PTE_ORDER		0
+#endif
+#ifdef CONFIG_PAGE_SIZE_64KB
+#define PGD_ORDER		0
+#define PMD_ORDER		0
+#define PTE_ORDER		0
+#endif
+
+#define PTRS_PER_PGD	((PAGE_SIZE << PGD_ORDER) / sizeof(pgd_t))
+#define PTRS_PER_PMD	((PAGE_SIZE << PMD_ORDER) / sizeof(pmd_t))
+#define PTRS_PER_PTE	((PAGE_SIZE << PTE_ORDER) / sizeof(pte_t))
 
 #define USER_PTRS_PER_PGD	(TASK_SIZE / PGDIR_SIZE)
 #define FIRST_USER_PGD_NR	0
@@ -67,8 +87,6 @@
 #define VMALLOC_END	\
 	(VMALLOC_START + ((1 << PGD_ORDER) * PTRS_PER_PTE * PAGE_SIZE))
 
-#ifndef __ASSEMBLY__
-
 #define pte_ERROR(e) \
 	printk("%s:%d: bad pte %016lx.\n", __FILE__, __LINE__, pte_val(e))
 #define pmd_ERROR(e) \
@@ -121,13 +139,11 @@ static inline void pgd_clear(pgd_t *pgdp
 	pgd_val(*pgdp) = ((unsigned long) invalid_pmd_table);
 }
 
-#ifdef CONFIG_DISCONTIGMEM
-
-#define pte_page(x) (NODE_MEM_MAP(PHYSADDR_TO_NID(pte_val(x))) +	\
-	PLAT_NODE_DATA_LOCALNR(pte_val(x), PHYSADDR_TO_NID(pte_val(x))))
-				  
+#define pte_page(x)		pfn_to_page((unsigned long)((pte_val(x) >> PAGE_SHIFT)))
+#ifdef CONFIG_CPU_VR41XX
+#define pte_pfn(x)		((unsigned long)((x).pte >> (PAGE_SHIFT + 2)))
+#define pfn_pte(pfn, prot)	__pte(((pfn) << (PAGE_SHIFT + 2)) | pgprot_val(prot))
 #else
-#define pte_page(x)		(mem_map+(unsigned long)((pte_val(x) >> PAGE_SHIFT)))
 #define pte_pfn(x)		((unsigned long)((x).pte >> PAGE_SHIFT))
 #define pfn_pte(pfn, prot)	__pte(((pfn) << PAGE_SHIFT) | pgprot_val(prot))
 #endif
@@ -185,9 +201,6 @@ static inline pmd_t *pmd_offset(pgd_t * 
 extern void pgd_init(unsigned long page);
 extern void pmd_init(unsigned long page, unsigned long pagetable);
 
-extern pgd_t swapper_pg_dir[1024];
-extern void paging_init(void);
-
 /*
  * Non-present pages:  high 24 bits are offset, next 8 bits type,
  * low 32 bits zero.
@@ -203,6 +216,4 @@ static inline pte_t mk_swap_pte(unsigned
 
 typedef pte_t *pte_addr_t;
 
-#endif /* !__ASSEMBLY__ */
-
 #endif /* _ASM_PGTABLE_64_H */
--- diff/include/asm-mips/pgtable-bits.h	2003-07-08 09:55:19.000000000 +0100
+++ source/include/asm-mips/pgtable-bits.h	2004-02-23 13:56:47.000000000 +0000
@@ -91,7 +91,7 @@
 
 #ifdef CONFIG_MIPS_UNCACHED
 #define PAGE_CACHABLE_DEFAULT	_CACHE_UNCACHED
-#elif defined(CONFIG_NONCOHERENT_IO)
+#elif defined(CONFIG_DMA_NONCOHERENT)
 #define PAGE_CACHABLE_DEFAULT	_CACHE_CACHABLE_NONCOHERENT
 #else
 #define PAGE_CACHABLE_DEFAULT	_CACHE_CACHABLE_COW
--- diff/include/asm-mips/pgtable.h	2003-08-20 14:16:33.000000000 +0100
+++ source/include/asm-mips/pgtable.h	2004-02-23 13:56:47.000000000 +0000
@@ -9,7 +9,6 @@
 #define _ASM_PGTABLE_H
 
 #include <linux/config.h>
-
 #ifdef CONFIG_MIPS32
 #include <asm/pgtable-32.h>
 #endif
@@ -67,6 +66,8 @@ extern unsigned long zero_page_mask;
 #define ZERO_PAGE(vaddr) \
 	(virt_to_page(empty_zero_page + (((unsigned long)(vaddr)) & zero_page_mask)))
 
+extern void paging_init(void);
+
 /*
  * Conversion functions: convert a page and protection to a page entry,
  * and a page entry and page directory to the page they refer to.
@@ -118,6 +119,11 @@ static inline void pte_clear(pte_t *ptep
 #define set_pmd(pmdptr, pmdval) do { *(pmdptr) = (pmdval); } while(0)
 #define set_pgd(pgdptr, pgdval) do { *(pgdptr) = (pgdval); } while(0)
 
+#define PGD_T_LOG2	ffz(~sizeof(pgd_t))
+#define PMD_T_LOG2	ffz(~sizeof(pmd_t))
+#define PTE_T_LOG2	ffz(~sizeof(pte_t))
+
+extern pgd_t swapper_pg_dir[PTRS_PER_PGD];
 
 #define PTE_FILE_MAX_BITS	27
 
--- diff/include/asm-mips/processor.h	2003-09-30 15:46:19.000000000 +0100
+++ source/include/asm-mips/processor.h	2004-02-23 13:56:47.000000000 +0000
@@ -12,21 +12,15 @@
 #define _ASM_PROCESSOR_H
 
 #include <linux/config.h>
-
-/*
- * Return current * instruction pointer ("program counter").
- */
-#define current_text_addr() ({ __label__ _l; _l: &&_l;})
-
-#ifndef __ASSEMBLY__
 #include <linux/cache.h>
 #include <linux/threads.h>
 
 #include <asm/cachectl.h>
+#include <asm/cpu.h>
 #include <asm/mipsregs.h>
 #include <asm/system.h>
 
-#if defined(CONFIG_SGI_IP27)
+#ifdef CONFIG_SGI_IP27
 #include <asm/sn/types.h>
 #include <asm/sn/intr_public.h>
 #endif
@@ -55,11 +49,11 @@ struct cpuinfo_mips {
 	unsigned long		udelay_val;
 	unsigned long		asid_cache;
 #if defined(CONFIG_SGI_IP27)
-	cpuid_t		p_cpuid;	/* PROM assigned cpuid */
+//	cpuid_t		p_cpuid;	/* PROM assigned cpuid */
 	cnodeid_t	p_nodeid;	/* my node ID in compact-id-space */
 	nasid_t		p_nasid;	/* my node ID in numa-as-id-space */
 	unsigned char	p_slice;	/* Physical position on node board */
-	hub_intmasks_t	p_intmasks;	/* SN0 per-CPU interrupt masks */
+	struct hub_intmasks_s p_intmasks; /* SN0 per-CPU interrupt masks */
 #endif
 #if 0
 	unsigned long		loops_per_sec;
@@ -85,40 +79,6 @@ struct cpuinfo_mips {
 	struct cache_desc	tcache;	/* Tertiary/split secondary cache */
 } __attribute__((aligned(SMP_CACHE_BYTES)));
 
-/*
- * Assumption: Options of CPU 0 are a superset of all processors.
- * This is true for all known MIPS systems.
- */
-#define cpu_has_tlb		(cpu_data[0].options & MIPS_CPU_TLB)
-#define cpu_has_4kex		(cpu_data[0].options & MIPS_CPU_4KEX)
-#define cpu_has_4ktlb		(cpu_data[0].options & MIPS_CPU_4KTLB)
-#define cpu_has_fpu		(cpu_data[0].options & MIPS_CPU_FPU)
-#define cpu_has_32fpr		(cpu_data[0].options & MIPS_CPU_32FPR)
-#define cpu_has_counter		(cpu_data[0].options & MIPS_CPU_COUNTER)
-#define cpu_has_watch		(cpu_data[0].options & MIPS_CPU_WATCH)
-#define cpu_has_mips16		(cpu_data[0].options & MIPS_CPU_MIPS16)
-#define cpu_has_divec		(cpu_data[0].options & MIPS_CPU_DIVEC)
-#define cpu_has_vce		(cpu_data[0].options & MIPS_CPU_VCE)
-#define cpu_has_cache_cdex	(cpu_data[0].options & MIPS_CPU_CACHE_CDEX)
-#define cpu_has_mcheck		(cpu_data[0].options & MIPS_CPU_MCHECK)
-#define cpu_has_ejtag		(cpu_data[0].options & MIPS_CPU_EJTAG)
-/* no FPU exception; never set on 64-bit */
-#ifdef CONFIG_MIPS64
-#define cpu_has_nofpuex		0
-#else
-#define cpu_has_nofpuex		(cpu_data[0].options & MIPS_CPU_NOFPUEX)
-#endif
-#define cpu_has_llsc		(cpu_data[0].options & MIPS_CPU_LLSC)
-#define cpu_has_vtag_icache	(cpu_data[0].icache.flags & MIPS_CACHE_VTAG)
-#define cpu_has_dc_aliases	(cpu_data[0].dcache.flags & MIPS_CACHE_ALIASES)
-#define cpu_has_ic_fills_f_dc	(cpu_data[0].dcache.flags & MIPS_CACHE_IC_F_DC)
-#ifdef CONFIG_MIPS64
-#define cpu_has_64bits		1
-#else
-#define cpu_has_64bits		(cpu_data[0].isa_level & MIPS_CPU_ISA_64BIT)
-#endif
-#define cpu_has_subset_pcaches	(cpu_data[0].options & MIPS_CPU_SUBSET_CACHES)
-
 extern struct cpuinfo_mips cpu_data[];
 #define current_cpu_data cpu_data[smp_processor_id()]
 
@@ -126,6 +86,11 @@ extern void cpu_probe(void);
 extern void cpu_report(void);
 
 /*
+ * Return current * instruction pointer ("program counter").
+ */
+#define current_text_addr() ({ __label__ _l; _l: &&_l;})
+
+/*
  * System setup and hardware flags..
  */
 extern void (*cpu_wait)(void);
@@ -244,8 +209,6 @@ struct thread_struct {
 #define MF_N32		MF_32BIT_ADDR
 #define MF_N64		0
 
-#endif /* !__ASSEMBLY__ */
-
 #define INIT_THREAD  { \
         /* \
          * saved main processor registers \
@@ -271,7 +234,6 @@ struct thread_struct {
 }
 
 #ifdef __KERNEL__
-#ifndef __ASSEMBLY__
 
 struct task_struct;
 
@@ -300,7 +262,6 @@ unsigned long get_wchan(struct task_stru
 
 #define cpu_relax()	barrier()
 
-#endif /* !__ASSEMBLY__ */
 #endif /* __KERNEL__ */
 
 /*
@@ -317,4 +278,13 @@ unsigned long get_wchan(struct task_stru
  */
 #define return_address() ({__asm__ __volatile__("":::"$31");__builtin_return_address(0);})
 
+/*
+ * For now.  The 32-bit cycle counter is screwed up so solving this nicely takes a little
+ * brainwork ...
+ */
+static inline unsigned long long sched_clock(void)
+{
+	return 0ULL;
+}
+
 #endif /* _ASM_PROCESSOR_H */
--- diff/include/asm-mips/ptrace.h	2003-08-20 14:16:33.000000000 +0100
+++ source/include/asm-mips/ptrace.h	2004-02-23 13:56:47.000000000 +0000
@@ -23,8 +23,6 @@
 #define FPC_CSR		69
 #define FPC_EIR		70
 
-#ifndef __ASSEMBLY__
-
 /*
  * This struct defines the way the registers are stored on the stack during a
  * system call/exception. As usual the registers k0/k1 aren't being saved.
@@ -38,21 +36,15 @@ struct pt_regs {
 	/* Saved main processor registers. */
 	unsigned long regs[32];
 
-	/* Other saved registers. */
+	/* Saved special registers. */
+	unsigned long cp0_status;
 	unsigned long lo;
 	unsigned long hi;
-
-	/*
-	 * saved cp0 registers
-	 */
-	unsigned long cp0_epc;
 	unsigned long cp0_badvaddr;
-	unsigned long cp0_status;
 	unsigned long cp0_cause;
+	unsigned long cp0_epc;
 };
 
-#endif /* !__ASSEMBLY__ */
-
 /* Arbitrarily choose the same ptrace numbers as used by the Sparc code. */
 /* #define PTRACE_GETREGS		12 */
 /* #define PTRACE_SETREGS		13 */
@@ -66,13 +58,8 @@ struct pt_regs {
 #define PTRACE_GET_THREAD_AREA	25
 #define PTRACE_SET_THREAD_AREA	26
 
-#ifdef __ASSEMBLY__
-#include <asm/offset.h>
-#endif
-
 #ifdef __KERNEL__
 
-#ifndef __ASSEMBLY__
 /*
  * Does the process account for user or for system time?
  */
@@ -81,7 +68,6 @@ struct pt_regs {
 #define instruction_pointer(regs) ((regs)->cp0_epc)
 
 extern void show_regs(struct pt_regs *);
-#endif /* !__ASSEMBLY__ */
 
 #endif
 
--- diff/include/asm-mips/r4kcache.h	2003-08-20 14:16:33.000000000 +0100
+++ source/include/asm-mips/r4kcache.h	2004-02-23 13:56:47.000000000 +0000
@@ -7,19 +7,33 @@
  *
  * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
  * Copyright (C) 1997 - 2002 Ralf Baechle (ralf@gnu.org)
+ * Copyright (C) 2004 Ralf Baechle (ralf@linux-mips.org)
  */
-#ifndef __ASM_R4KCACHE_H
-#define __ASM_R4KCACHE_H
+#ifndef _ASM_R4KCACHE_H
+#define _ASM_R4KCACHE_H
 
 #include <asm/asm.h>
 #include <asm/cacheops.h>
 
+/*
+ * This macro return a properly sign-extended address suitable as base address
+ * for indexed cache operations.  Two issues here:
+ *
+ *  - The MIPS32 and MIPS64 specs permit an implementation to directly derive
+ *    the index bits from the virtual address.  This breaks with tradition
+ *    set by the R4000.  To keep unpleassant surprises from happening we pick
+ *    an address in KSEG0 / CKSEG0.
+ *  - We need a properly sign extended address for 64-bit code.  To get away
+ *    without ifdefs we let the compiler do it by a type cast.
+ */
+#define INDEX_BASE	((int) KSEG0)
+
 #define cache_op(op,addr)						\
 	__asm__ __volatile__(						\
-	"	.set	noreorder		\n"			\
-	"	.set	mips3\n\t		\n"			\
-	"	cache	%0, %1			\n"			\
-	"	.set	mips0			\n"			\
+	"	.set	noreorder				\n"	\
+	"	.set	mips3\n\t				\n"	\
+	"	cache	%0, %1					\n"	\
+	"	.set	mips0					\n"	\
 	"	.set	reorder"					\
 	:								\
 	: "i" (op), "m" (*(unsigned char *)(addr)))
@@ -111,35 +125,35 @@ static inline void invalidate_tcache_pag
 	cache_op(Page_Invalidate_T, addr);
 }
 
-#define cache16_unroll32(base,op)				\
-	__asm__ __volatile__("					\
-		.set noreorder;					\
-		.set mips3;					\
-		cache %1, 0x000(%0); cache %1, 0x010(%0);	\
-		cache %1, 0x020(%0); cache %1, 0x030(%0);	\
-		cache %1, 0x040(%0); cache %1, 0x050(%0);	\
-		cache %1, 0x060(%0); cache %1, 0x070(%0);	\
-		cache %1, 0x080(%0); cache %1, 0x090(%0);	\
-		cache %1, 0x0a0(%0); cache %1, 0x0b0(%0);	\
-		cache %1, 0x0c0(%0); cache %1, 0x0d0(%0);	\
-		cache %1, 0x0e0(%0); cache %1, 0x0f0(%0);	\
-		cache %1, 0x100(%0); cache %1, 0x110(%0);	\
-		cache %1, 0x120(%0); cache %1, 0x130(%0);	\
-		cache %1, 0x140(%0); cache %1, 0x150(%0);	\
-		cache %1, 0x160(%0); cache %1, 0x170(%0);	\
-		cache %1, 0x180(%0); cache %1, 0x190(%0);	\
-		cache %1, 0x1a0(%0); cache %1, 0x1b0(%0);	\
-		cache %1, 0x1c0(%0); cache %1, 0x1d0(%0);	\
-		cache %1, 0x1e0(%0); cache %1, 0x1f0(%0);	\
-		.set mips0;					\
-		.set reorder"					\
-		:						\
-		: "r" (base),					\
+#define cache16_unroll32(base,op)					\
+	__asm__ __volatile__(						\
+	"	.set noreorder					\n"	\
+	"	.set mips3					\n"	\
+	"	cache %1, 0x000(%0); cache %1, 0x010(%0)	\n"	\
+	"	cache %1, 0x020(%0); cache %1, 0x030(%0)	\n"	\
+	"	cache %1, 0x040(%0); cache %1, 0x050(%0)	\n"	\
+	"	cache %1, 0x060(%0); cache %1, 0x070(%0)	\n"	\
+	"	cache %1, 0x080(%0); cache %1, 0x090(%0)	\n"	\
+	"	cache %1, 0x0a0(%0); cache %1, 0x0b0(%0)	\n"	\
+	"	cache %1, 0x0c0(%0); cache %1, 0x0d0(%0)	\n"	\
+	"	cache %1, 0x0e0(%0); cache %1, 0x0f0(%0)	\n"	\
+	"	cache %1, 0x100(%0); cache %1, 0x110(%0)	\n"	\
+	"	cache %1, 0x120(%0); cache %1, 0x130(%0)	\n"	\
+	"	cache %1, 0x140(%0); cache %1, 0x150(%0)	\n"	\
+	"	cache %1, 0x160(%0); cache %1, 0x170(%0)	\n"	\
+	"	cache %1, 0x180(%0); cache %1, 0x190(%0)	\n"	\
+	"	cache %1, 0x1a0(%0); cache %1, 0x1b0(%0)	\n"	\
+	"	cache %1, 0x1c0(%0); cache %1, 0x1d0(%0)	\n"	\
+	"	cache %1, 0x1e0(%0); cache %1, 0x1f0(%0)	\n"	\
+	"	.set mips0					\n"	\
+	"	.set reorder					\n"	\
+		:							\
+		: "r" (base),						\
 		  "i" (op));
 
 static inline void blast_dcache16(void)
 {
-	unsigned long start = KSEG0;
+	unsigned long start = INDEX_BASE;
 	unsigned long end = start + current_cpu_data.dcache.waysize;
 	unsigned long ws_inc = 1UL << current_cpu_data.dcache.waybit;
 	unsigned long ws_end = current_cpu_data.dcache.ways << 
@@ -156,10 +170,10 @@ static inline void blast_dcache16_page(u
 	unsigned long start = page;
 	unsigned long end = start + PAGE_SIZE;
 
-	while (start < end) {
+	do {
 		cache16_unroll32(start,Hit_Writeback_Inv_D);
 		start += 0x200;
-	}
+	} while (start < end);
 }
 
 static inline void blast_dcache16_page_indexed(unsigned long page)
@@ -178,7 +192,7 @@ static inline void blast_dcache16_page_i
 
 static inline void blast_icache16(void)
 {
-	unsigned long start = KSEG0;
+	unsigned long start = INDEX_BASE;
 	unsigned long end = start + current_cpu_data.icache.waysize;
 	unsigned long ws_inc = 1UL << current_cpu_data.icache.waybit;
 	unsigned long ws_end = current_cpu_data.icache.ways <<
@@ -195,10 +209,10 @@ static inline void blast_icache16_page(u
 	unsigned long start = page;
 	unsigned long end = start + PAGE_SIZE;
 
-	while (start < end) {
+	do {
 		cache16_unroll32(start,Hit_Invalidate_I);
 		start += 0x200;
-	}
+	} while (start < end);
 }
 
 static inline void blast_icache16_page_indexed(unsigned long page)
@@ -217,7 +231,7 @@ static inline void blast_icache16_page_i
 
 static inline void blast_scache16(void)
 {
-	unsigned long start = KSEG0;
+	unsigned long start = INDEX_BASE;
 	unsigned long end = start + current_cpu_data.scache.waysize;
 	unsigned long ws_inc = 1UL << current_cpu_data.scache.waybit;
 	unsigned long ws_end = current_cpu_data.scache.ways << 
@@ -234,10 +248,10 @@ static inline void blast_scache16_page(u
 	unsigned long start = page;
 	unsigned long end = page + PAGE_SIZE;
 
-	while (start < end) {
+	do {
 		cache16_unroll32(start,Hit_Writeback_Inv_SD);
 		start += 0x200;
-	}
+	} while (start < end);
 }
 
 static inline void blast_scache16_page_indexed(unsigned long page)
@@ -254,35 +268,35 @@ static inline void blast_scache16_page_i
 			cache16_unroll32(addr|ws,Index_Writeback_Inv_SD);
 }
 
-#define cache32_unroll32(base,op)				\
-	__asm__ __volatile__("					\
-		.set noreorder;					\
-		.set mips3;					\
-		cache %1, 0x000(%0); cache %1, 0x020(%0);	\
-		cache %1, 0x040(%0); cache %1, 0x060(%0);	\
-		cache %1, 0x080(%0); cache %1, 0x0a0(%0);	\
-		cache %1, 0x0c0(%0); cache %1, 0x0e0(%0);	\
-		cache %1, 0x100(%0); cache %1, 0x120(%0);	\
-		cache %1, 0x140(%0); cache %1, 0x160(%0);	\
-		cache %1, 0x180(%0); cache %1, 0x1a0(%0);	\
-		cache %1, 0x1c0(%0); cache %1, 0x1e0(%0);	\
-		cache %1, 0x200(%0); cache %1, 0x220(%0);	\
-		cache %1, 0x240(%0); cache %1, 0x260(%0);	\
-		cache %1, 0x280(%0); cache %1, 0x2a0(%0);	\
-		cache %1, 0x2c0(%0); cache %1, 0x2e0(%0);	\
-		cache %1, 0x300(%0); cache %1, 0x320(%0);	\
-		cache %1, 0x340(%0); cache %1, 0x360(%0);	\
-		cache %1, 0x380(%0); cache %1, 0x3a0(%0);	\
-		cache %1, 0x3c0(%0); cache %1, 0x3e0(%0);	\
-		.set mips0;					\
-		.set reorder"					\
-		:						\
-		: "r" (base),					\
+#define cache32_unroll32(base,op)					\
+	__asm__ __volatile__(						\
+	"	.set noreorder					\n"	\
+	"	.set mips3					\n"	\
+	"	cache %1, 0x000(%0); cache %1, 0x020(%0)	\n"	\
+	"	cache %1, 0x040(%0); cache %1, 0x060(%0)	\n"	\
+	"	cache %1, 0x080(%0); cache %1, 0x0a0(%0)	\n"	\
+	"	cache %1, 0x0c0(%0); cache %1, 0x0e0(%0)	\n"	\
+	"	cache %1, 0x100(%0); cache %1, 0x120(%0)	\n"	\
+	"	cache %1, 0x140(%0); cache %1, 0x160(%0)	\n"	\
+	"	cache %1, 0x180(%0); cache %1, 0x1a0(%0)	\n"	\
+	"	cache %1, 0x1c0(%0); cache %1, 0x1e0(%0)	\n"	\
+	"	cache %1, 0x200(%0); cache %1, 0x220(%0)	\n"	\
+	"	cache %1, 0x240(%0); cache %1, 0x260(%0)	\n"	\
+	"	cache %1, 0x280(%0); cache %1, 0x2a0(%0)	\n"	\
+	"	cache %1, 0x2c0(%0); cache %1, 0x2e0(%0)	\n"	\
+	"	cache %1, 0x300(%0); cache %1, 0x320(%0)	\n"	\
+	"	cache %1, 0x340(%0); cache %1, 0x360(%0)	\n"	\
+	"	cache %1, 0x380(%0); cache %1, 0x3a0(%0)	\n"	\
+	"	cache %1, 0x3c0(%0); cache %1, 0x3e0(%0)	\n"	\
+	"	.set mips0					\n"	\
+	"	.set reorder					\n"	\
+		:							\
+		: "r" (base),						\
 		  "i" (op));
 
 static inline void blast_dcache32(void)
 {
-	unsigned long start = KSEG0;
+	unsigned long start = INDEX_BASE;
 	unsigned long end = start + current_cpu_data.dcache.waysize;
 	unsigned long ws_inc = 1UL << current_cpu_data.dcache.waybit;
 	unsigned long ws_end = current_cpu_data.dcache.ways <<
@@ -299,10 +313,10 @@ static inline void blast_dcache32_page(u
 	unsigned long start = page;
 	unsigned long end = start + PAGE_SIZE;
 
-	while (start < end) {
+	do {
 		cache32_unroll32(start,Hit_Writeback_Inv_D);
 		start += 0x400;
-	}
+	} while (start < end);
 }
 
 static inline void blast_dcache32_page_indexed(unsigned long page)
@@ -321,7 +335,7 @@ static inline void blast_dcache32_page_i
 
 static inline void blast_icache32(void)
 {
-	unsigned long start = KSEG0;
+	unsigned long start = INDEX_BASE;
 	unsigned long end = start + current_cpu_data.icache.waysize;
 	unsigned long ws_inc = 1UL << current_cpu_data.icache.waybit;
 	unsigned long ws_end = current_cpu_data.icache.ways <<
@@ -338,10 +352,10 @@ static inline void blast_icache32_page(u
 	unsigned long start = page;
 	unsigned long end = start + PAGE_SIZE;
 
-	while (start < end) {
+	do {
 		cache32_unroll32(start,Hit_Invalidate_I);
 		start += 0x400;
-	}
+	} while (start < end);
 }
 
 static inline void blast_icache32_page_indexed(unsigned long page)
@@ -360,7 +374,7 @@ static inline void blast_icache32_page_i
 
 static inline void blast_scache32(void)
 {
-	unsigned long start = KSEG0;
+	unsigned long start = INDEX_BASE;
 	unsigned long end = start + current_cpu_data.scache.waysize;
 	unsigned long ws_inc = 1UL << current_cpu_data.scache.waybit;
 	unsigned long ws_end = current_cpu_data.scache.ways << 
@@ -377,10 +391,10 @@ static inline void blast_scache32_page(u
 	unsigned long start = page;
 	unsigned long end = page + PAGE_SIZE;
 
-	while (start < end) {
+	do {
 		cache32_unroll32(start,Hit_Writeback_Inv_SD);
 		start += 0x400;
-	}
+	} while (start < end);
 }
 
 static inline void blast_scache32_page_indexed(unsigned long page)
@@ -397,35 +411,35 @@ static inline void blast_scache32_page_i
 			cache32_unroll32(addr|ws,Index_Writeback_Inv_SD);
 }
 
-#define cache64_unroll32(base,op)				\
-	__asm__ __volatile__("					\
-		.set noreorder;					\
-		.set mips3;					\
-		cache %1, 0x000(%0); cache %1, 0x040(%0);	\
-		cache %1, 0x080(%0); cache %1, 0x0c0(%0);	\
-		cache %1, 0x100(%0); cache %1, 0x140(%0);	\
-		cache %1, 0x180(%0); cache %1, 0x1c0(%0);	\
-		cache %1, 0x200(%0); cache %1, 0x240(%0);	\
-		cache %1, 0x280(%0); cache %1, 0x2c0(%0);	\
-		cache %1, 0x300(%0); cache %1, 0x340(%0);	\
-		cache %1, 0x380(%0); cache %1, 0x3c0(%0);	\
-		cache %1, 0x400(%0); cache %1, 0x440(%0);	\
-		cache %1, 0x480(%0); cache %1, 0x4c0(%0);	\
-		cache %1, 0x500(%0); cache %1, 0x540(%0);	\
-		cache %1, 0x580(%0); cache %1, 0x5c0(%0);	\
-		cache %1, 0x600(%0); cache %1, 0x640(%0);	\
-		cache %1, 0x680(%0); cache %1, 0x6c0(%0);	\
-		cache %1, 0x700(%0); cache %1, 0x740(%0);	\
-		cache %1, 0x780(%0); cache %1, 0x7c0(%0);	\
-		.set mips0;					\
-		.set reorder"					\
-		:						\
-		: "r" (base),					\
+#define cache64_unroll32(base,op)					\
+	__asm__ __volatile__(						\
+	"	.set noreorder					\n"	\
+	"	.set mips3					\n"	\
+	"	cache %1, 0x000(%0); cache %1, 0x040(%0)	\n"	\
+	"	cache %1, 0x080(%0); cache %1, 0x0c0(%0)	\n"	\
+	"	cache %1, 0x100(%0); cache %1, 0x140(%0)	\n"	\
+	"	cache %1, 0x180(%0); cache %1, 0x1c0(%0)	\n"	\
+	"	cache %1, 0x200(%0); cache %1, 0x240(%0)	\n"	\
+	"	cache %1, 0x280(%0); cache %1, 0x2c0(%0)	\n"	\
+	"	cache %1, 0x300(%0); cache %1, 0x340(%0)	\n"	\
+	"	cache %1, 0x380(%0); cache %1, 0x3c0(%0)	\n"	\
+	"	cache %1, 0x400(%0); cache %1, 0x440(%0)	\n"	\
+	"	cache %1, 0x480(%0); cache %1, 0x4c0(%0)	\n"	\
+	"	cache %1, 0x500(%0); cache %1, 0x540(%0)	\n"	\
+	"	cache %1, 0x580(%0); cache %1, 0x5c0(%0)	\n"	\
+	"	cache %1, 0x600(%0); cache %1, 0x640(%0)	\n"	\
+	"	cache %1, 0x680(%0); cache %1, 0x6c0(%0)	\n"	\
+	"	cache %1, 0x700(%0); cache %1, 0x740(%0)	\n"	\
+	"	cache %1, 0x780(%0); cache %1, 0x7c0(%0)	\n"	\
+	"	.set mips0					\n"	\
+	"	.set reorder					\n"	\
+		:							\
+		: "r" (base),						\
 		  "i" (op));
 
 static inline void blast_icache64(void)
 {
-	unsigned long start = KSEG0;
+	unsigned long start = INDEX_BASE;
 	unsigned long end = start + current_cpu_data.icache.waysize;
 	unsigned long ws_inc = 1UL << current_cpu_data.icache.waybit;
 	unsigned long ws_end = current_cpu_data.icache.ways <<
@@ -442,10 +456,10 @@ static inline void blast_icache64_page(u
 	unsigned long start = page;
 	unsigned long end = start + PAGE_SIZE;
 
-	while (start < end) {
+	do {
 		cache64_unroll32(start,Hit_Invalidate_I);
 		start += 0x800;
-	}
+	} while (start < end);
 }
 
 static inline void blast_icache64_page_indexed(unsigned long page)
@@ -464,7 +478,7 @@ static inline void blast_icache64_page_i
 
 static inline void blast_scache64(void)
 {
-	unsigned long start = KSEG0;
+	unsigned long start = INDEX_BASE;
 	unsigned long end = start + current_cpu_data.scache.waysize;
 	unsigned long ws_inc = 1UL << current_cpu_data.scache.waybit;
 	unsigned long ws_end = current_cpu_data.scache.ways << 
@@ -481,10 +495,10 @@ static inline void blast_scache64_page(u
 	unsigned long start = page;
 	unsigned long end = page + PAGE_SIZE;
 
-	while (start < end) {
+	do {
 		cache64_unroll32(start,Hit_Writeback_Inv_SD);
 		start += 0x800;
-	}
+	} while (start < end);
 }
 
 static inline void blast_scache64_page_indexed(unsigned long page)
@@ -501,35 +515,35 @@ static inline void blast_scache64_page_i
 			cache64_unroll32(addr|ws,Index_Writeback_Inv_SD);
 }
 
-#define cache128_unroll32(base,op)				\
-	__asm__ __volatile__("					\
-		.set noreorder;					\
-		.set mips3;					\
-		cache %1, 0x000(%0); cache %1, 0x080(%0);	\
-		cache %1, 0x100(%0); cache %1, 0x180(%0);	\
-		cache %1, 0x200(%0); cache %1, 0x280(%0);	\
-		cache %1, 0x300(%0); cache %1, 0x380(%0);	\
-		cache %1, 0x400(%0); cache %1, 0x480(%0);	\
-		cache %1, 0x500(%0); cache %1, 0x580(%0);	\
-		cache %1, 0x600(%0); cache %1, 0x680(%0);	\
-		cache %1, 0x700(%0); cache %1, 0x780(%0);	\
-		cache %1, 0x800(%0); cache %1, 0x880(%0);	\
-		cache %1, 0x900(%0); cache %1, 0x980(%0);	\
-		cache %1, 0xa00(%0); cache %1, 0xa80(%0);	\
-		cache %1, 0xb00(%0); cache %1, 0xb80(%0);	\
-		cache %1, 0xc00(%0); cache %1, 0xc80(%0);	\
-		cache %1, 0xd00(%0); cache %1, 0xd80(%0);	\
-		cache %1, 0xe00(%0); cache %1, 0xe80(%0);	\
-		cache %1, 0xf00(%0); cache %1, 0xf80(%0);	\
-		.set mips0;					\
-		.set reorder"					\
-		:						\
-		: "r" (base),					\
+#define cache128_unroll32(base,op)					\
+	__asm__ __volatile__(						\
+	"	.set noreorder					\n"	\
+	"	.set mips3					\n"	\
+	"	cache %1, 0x000(%0); cache %1, 0x080(%0)	\n"	\
+	"	cache %1, 0x100(%0); cache %1, 0x180(%0)	\n"	\
+	"	cache %1, 0x200(%0); cache %1, 0x280(%0)	\n"	\
+	"	cache %1, 0x300(%0); cache %1, 0x380(%0)	\n"	\
+	"	cache %1, 0x400(%0); cache %1, 0x480(%0)	\n"	\
+	"	cache %1, 0x500(%0); cache %1, 0x580(%0)	\n"	\
+	"	cache %1, 0x600(%0); cache %1, 0x680(%0)	\n"	\
+	"	cache %1, 0x700(%0); cache %1, 0x780(%0)	\n"	\
+	"	cache %1, 0x800(%0); cache %1, 0x880(%0)	\n"	\
+	"	cache %1, 0x900(%0); cache %1, 0x980(%0)	\n"	\
+	"	cache %1, 0xa00(%0); cache %1, 0xa80(%0)	\n"	\
+	"	cache %1, 0xb00(%0); cache %1, 0xb80(%0)	\n"	\
+	"	cache %1, 0xc00(%0); cache %1, 0xc80(%0)	\n"	\
+	"	cache %1, 0xd00(%0); cache %1, 0xd80(%0)	\n"	\
+	"	cache %1, 0xe00(%0); cache %1, 0xe80(%0)	\n"	\
+	"	cache %1, 0xf00(%0); cache %1, 0xf80(%0)	\n"	\
+	"	.set mips0					\n"	\
+	"	.set reorder					\n"	\
+		:							\
+		: "r" (base),						\
 		  "i" (op));
 
 static inline void blast_scache128(void)
 {
-	unsigned long start = KSEG0;
+	unsigned long start = INDEX_BASE;
 	unsigned long end = start + current_cpu_data.scache.waysize;
 	unsigned long ws_inc = 1UL << current_cpu_data.scache.waybit;
 	unsigned long ws_end = current_cpu_data.scache.ways << 
@@ -546,10 +560,10 @@ static inline void blast_scache128_page(
 	unsigned long start = page;
 	unsigned long end = page + PAGE_SIZE;
 
-	while (start < end) {
+	do {
 		cache128_unroll32(start,Hit_Writeback_Inv_SD);
 		start += 0x1000;
-	}
+	} while (start < end);
 }
 
 static inline void blast_scache128_page_indexed(unsigned long page)
@@ -566,4 +580,4 @@ static inline void blast_scache128_page_
 			cache128_unroll32(addr|ws,Index_Writeback_Inv_SD);
 }
 
-#endif /* __ASM_R4KCACHE_H */
+#endif /* _ASM_R4KCACHE_H */
--- diff/include/asm-mips/rtc.h	2003-07-08 09:55:19.000000000 +0100
+++ source/include/asm-mips/rtc.h	2004-02-23 13:56:47.000000000 +0000
@@ -1,10 +1,37 @@
-#ifndef _I386_RTC_H
-#define _I386_RTC_H
-
 /*
- * x86 uses the default access methods for the RTC.
+ * include/asm-mips/rtc.h 
+ *
+ * (Really an interface for drivers/char/genrtc.c)
+ *
+ * Copyright (C) 2004 MontaVista Software Inc.
+ * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net
+ *
+ * Please read the COPYING file for all license details.
  */
 
-#include <asm-generic/rtc.h>
+#ifndef _MIPS_RTC_H
+#define _MIPS_RTC_H
+
+#ifdef __KERNEL__
+
+#include <linux/rtc.h>
+
+#define RTC_PIE 0x40            /* periodic interrupt enable */
+#define RTC_AIE 0x20            /* alarm interrupt enable */
+#define RTC_UIE 0x10            /* update-finished interrupt enable */
 
+/* some dummy definitions */
+#define RTC_BATT_BAD 0x100      /* battery bad */
+#define RTC_SQWE 0x08           /* enable square-wave output */
+#define RTC_DM_BINARY 0x04      /* all time/date values are BCD if clear */
+#define RTC_24H 0x02            /* 24 hour mode - else hours bit 7 means pm */
+#define RTC_DST_EN 0x01         /* auto switch DST - works f. USA only */
+
+unsigned int get_rtc_time(struct rtc_time *time);
+int set_rtc_time(struct rtc_time *time);
+unsigned int get_rtc_ss(void);
+int get_rtc_pll(struct rtc_pll_info *pll);
+int set_rtc_pll(struct rtc_pll_info *pll);
+
+#endif
 #endif
--- diff/include/asm-mips/semaphore.h	2003-09-17 12:28:12.000000000 +0100
+++ source/include/asm-mips/semaphore.h	2004-02-23 13:56:47.000000000 +0000
@@ -11,12 +11,12 @@
 #ifndef _ASM_SEMAPHORE_H
 #define _ASM_SEMAPHORE_H
 
+#include <linux/compiler.h>
 #include <linux/config.h>
-#include <asm/system.h>
-#include <asm/atomic.h>
 #include <linux/spinlock.h>
 #include <linux/wait.h>
 #include <linux/rwsem.h>
+#include <asm/atomic.h>
 
 struct semaphore {
 #ifdef __MIPSEB__
@@ -33,29 +33,24 @@ struct semaphore {
 } __attribute__((aligned(8)));
 
 #if WAITQUEUE_DEBUG
-# define __SEM_DEBUG_INIT(name) \
-		, (long)&(name).__magic
+# define __SEM_DEBUG_INIT(name) , .__magic = (long)&(name).__magic
 #else
 # define __SEM_DEBUG_INIT(name)
 #endif
 
-#ifdef __MIPSEB__
-#define __SEMAPHORE_INITIALIZER(name,count) \
-{ ATOMIC_INIT(count), ATOMIC_INIT(0), __WAIT_QUEUE_HEAD_INITIALIZER((name).wait) \
-	__SEM_DEBUG_INIT(name) }
-#else
-#define __SEMAPHORE_INITIALIZER(name,count) \
-{ ATOMIC_INIT(0), ATOMIC_INIT(count), __WAIT_QUEUE_HEAD_INITIALIZER((name).wait) \
-	__SEM_DEBUG_INIT(name) }
-#endif
+#define __SEMAPHORE_INITIALIZER(name,_count) {				\
+	.count	= ATOMIC_INIT(_count),					\
+	.waking	= ATOMIC_INIT(0),					\
+	.wait	= __WAIT_QUEUE_HEAD_INITIALIZER((name).wait)		\
+	__SEM_DEBUG_INIT(name)						\
+}
 
-#define __MUTEX_INITIALIZER(name) \
-	__SEMAPHORE_INITIALIZER(name,1)
+#define __MUTEX_INITIALIZER(name) __SEMAPHORE_INITIALIZER(name, 1)
 
 #define __DECLARE_SEMAPHORE_GENERIC(name,count) \
-	struct semaphore name = __SEMAPHORE_INITIALIZER(name,count)
+	struct semaphore name = __SEMAPHORE_INITIALIZER(name, count)
 
-#define DECLARE_MUTEX(name) __DECLARE_SEMAPHORE_GENERIC(name,1)
+#define DECLARE_MUTEX(name) __DECLARE_SEMAPHORE_GENERIC(name, 1)
 #define DECLARE_MUTEX_LOCKED(name) __DECLARE_SEMAPHORE_GENERIC(name,0)
 
 static inline void sema_init (struct semaphore *sem, int val)
@@ -78,19 +73,29 @@ static inline void init_MUTEX_LOCKED (st
 	sema_init(sem, 0);
 }
 
-asmlinkage void __down(struct semaphore * sem);
-asmlinkage int  __down_interruptible(struct semaphore * sem);
-asmlinkage int __down_trylock(struct semaphore * sem);
-asmlinkage void __up(struct semaphore * sem);
+#ifndef CONFIG_CPU_HAS_LLDSCD
+/*
+ * On machines without lld/scd we need a spinlock to make the manipulation of
+ * sem->count and sem->waking atomic.
+ */
+extern spinlock_t semaphore_lock;
+#endif
+
+extern void __down_failed(struct semaphore * sem);
+extern int  __down_failed_interruptible(struct semaphore * sem);
+extern void __up_wakeup(struct semaphore * sem);
 
 static inline void down(struct semaphore * sem)
 {
+	int count;
+
 #if WAITQUEUE_DEBUG
 	CHECK_MAGIC(sem->__magic);
 #endif
 	might_sleep();
-	if (atomic_dec_return(&sem->count) < 0)
-		__down(sem);
+	count = atomic_dec_return(&sem->count);
+	if (unlikely(count < 0))
+		__down_failed(sem);
 }
 
 /*
@@ -99,32 +104,20 @@ static inline void down(struct semaphore
  */
 static inline int down_interruptible(struct semaphore * sem)
 {
-	int ret = 0;
+	int count;
 
 #if WAITQUEUE_DEBUG
 	CHECK_MAGIC(sem->__magic);
 #endif
 	might_sleep();
-	if (atomic_dec_return(&sem->count) < 0)
-		ret = __down_interruptible(sem);
-	return ret;
-}
-
-#ifndef CONFIG_CPU_HAS_LLDSCD
+	count = atomic_dec_return(&sem->count);
+	if (unlikely(count < 0))
+		return __down_failed_interruptible(sem);
 
-/*
- * Non-blockingly attempt to down() a semaphore.
- * Returns zero if we acquired it
- */
-static inline int down_trylock(struct semaphore * sem)
-{
-	int ret = 0;
-	if (atomic_dec_return(&sem->count) < 0)
-		ret = __down_trylock(sem);
-	return ret;
+	return 0;
 }
 
-#else
+#ifdef CONFIG_CPU_HAS_LLDSCD
 
 /*
  * down_trylock returns 0 on success, 1 if we failed to get the lock.
@@ -156,21 +149,22 @@ static inline int down_trylock(struct se
 #endif
 
 	__asm__ __volatile__(
-	".set\tmips3\t\t\t# down_trylock\n"
-	"0:\tlld\t%1, %4\n\t"
-	"dli\t%3, 0x0000000100000000\n\t"
-	"dsubu\t%1, %3\n\t"
-	"li\t%0, 0\n\t"
-	"bgez\t%1, 2f\n\t"
-	"sll\t%2, %1, 0\n\t"
-	"blez\t%2, 1f\n\t"
-	"daddiu\t%1, %1, -1\n\t"
-	"b\t2f\n"
-	"1:\tdaddu\t%1, %1, %3\n\t"
-	"li\t%0, 1\n"
-	"2:\tscd\t%1, %4\n\t"
-	"beqz\t%1, 0b\n\t"
-	".set\tmips0"
+	"	.set	mips3			# down_trylock		\n"
+	"0:	lld	%1, %4						\n"
+	"	dli	%3, 0x0000000100000000	# count -= 1		\n"
+	"	dsubu	%1, %3						\n"
+	"	li	%0, 0			# ret = 0		\n"
+	"	bgez	%1, 2f			# if count >= 0		\n"
+	"	sll	%2, %1, 0		# extract waking	\n"
+	"	blez	%2, 1f			# if waking < 0 -> 1f	\n"
+	"	daddiu	%1, %1, -1		# waking -= 1		\n"
+	"	b	2f						\n"
+	"1:	daddu	%1, %1, %3		# count += 1		\n"
+	"	li	%0, 1			# ret = 1		\n"
+	"2:	scd	%1, %4						\n"
+	"	beqz	%1, 0b						\n"
+	"	sync							\n"
+	"	.set	mips0						\n"
 	: "=&r"(ret), "=&r"(tmp), "=&r"(tmp2), "=&r"(sub)
 	: "m"(*sem)
 	: "memory");
@@ -178,7 +172,80 @@ static inline int down_trylock(struct se
 	return ret;
 }
 
-#endif /* CONFIG_CPU_HAS_LLDSCD */
+/*
+ * Note! This is subtle. We jump to wake people up only if
+ * the semaphore was negative (== somebody was waiting on it).
+ */
+static inline void up(struct semaphore * sem)
+{
+	unsigned long tmp, tmp2;
+	int count;
+
+#if WAITQUEUE_DEBUG
+	CHECK_MAGIC(sem->__magic);
+#endif
+	/*
+	 * We must manipulate count and waking simultaneously and atomically.
+	 * Otherwise we have races between up and __down_failed_interruptible
+	 * waking up on a signal.
+	 */
+
+	__asm__ __volatile__(
+	"	.set	mips3					\n"
+	"	sync			# up			\n"
+	"1:	lld	%1, %3					\n"
+	"	dsra32	%0, %1, 0	# extract count to %0	\n"
+	"	daddiu	%0, 1		# count += 1		\n"
+	"	slti	%2, %0, 1	# %3 = (%0 <= 0)	\n"
+	"	daddu	%1, %2		# waking += %3		\n"
+	"	dsll32 %1, %1, 0	# zero-extend %1	\n"
+	"	dsrl32 %1, %1, 0				\n"
+	"	dsll32	%2, %0, 0	# Reassemble union	\n"
+	"	or	%1, %2		# from count and waking	\n"
+	"	scd	%1, %3					\n"
+	"	beqz	%1, 1b					\n"
+	"	.set	mips0					\n"
+	: "=&r"(count), "=&r"(tmp), "=&r"(tmp2), "+m"(*sem)
+	:
+	: "memory");
+
+	if (unlikely(count <= 0))
+		__up_wakeup(sem);
+}
+
+#else
+
+/*
+ * Non-blockingly attempt to down() a semaphore.
+ * Returns zero if we acquired it
+ */
+static inline int down_trylock(struct semaphore * sem)
+{
+	unsigned long flags;
+	int count, waking;
+	int ret = 0;
+
+#if WAITQUEUE_DEBUG
+	CHECK_MAGIC(sem->__magic);
+#endif
+
+	spin_lock_irqsave(&semaphore_lock, flags);
+	count = atomic_read(&sem->count) - 1;
+	atomic_set(&sem->count, count);
+	if (unlikely(count < 0)) {
+		waking = atomic_read(&sem->waking);
+		if (waking <= 0) {
+			atomic_set(&sem->count, count + 1);
+			ret = 1;
+		} else {
+			atomic_set(&sem->waking, waking - 1);
+			ret = 0;
+		}
+	}
+	spin_unlock_irqrestore(&semaphore_lock, flags);
+
+	return ret;
+}
 
 /*
  * Note! This is subtle. We jump to wake people up only if
@@ -186,11 +253,31 @@ static inline int down_trylock(struct se
  */
 static inline void up(struct semaphore * sem)
 {
+	unsigned long flags;
+	int count, waking;
+
 #if WAITQUEUE_DEBUG
 	CHECK_MAGIC(sem->__magic);
 #endif
-	if (atomic_inc_return(&sem->count) <= 0)
-		__up(sem);
+	/*
+	 * We must manipulate count and waking simultaneously and atomically.
+	 * Otherwise we have races between up and __down_failed_interruptible
+	 * waking up on a signal.
+	 */
+
+	spin_lock_irqsave(&semaphore_lock, flags);
+	count = atomic_read(&sem->count) + 1;
+	waking = atomic_read(&sem->waking);
+	if (count <= 0)
+		waking++;
+	atomic_set(&sem->count, count);
+	atomic_set(&sem->waking, waking);
+	spin_unlock_irqrestore(&semaphore_lock, flags);
+
+	if (unlikely(count <= 0))
+		__up_wakeup(sem);
 }
 
+#endif /* CONFIG_CPU_HAS_LLDSCD */
+
 #endif /* _ASM_SEMAPHORE_H */
--- diff/include/asm-mips/serial.h	2003-08-20 14:16:33.000000000 +0100
+++ source/include/asm-mips/serial.h	2004-02-23 13:56:47.000000000 +0000
@@ -10,7 +10,6 @@
 #define _ASM_SERIAL_H
 
 #include <linux/config.h>
-#include <asm/jazz.h>
 
 /*
  * This assumes you have a 1.8432 MHz clock for your UART.
@@ -21,15 +20,6 @@
  */
 #define BASE_BAUD (1843200 / 16)
 
-#ifndef CONFIG_OLIVETTI_M700
-   /* Some Jazz machines seem to have an 8MHz crystal clock but I don't know
-      exactly which ones ... XXX */
-#define JAZZ_BASE_BAUD ( 8000000 / 16 ) /* ( 3072000 / 16) */
-#else
-/* but the M700 isn't such a strange beast */
-#define JAZZ_BASE_BAUD BASE_BAUD
-#endif
-
 /* Standard COM flags (except for COM4, because of the 8514 problem) */
 #ifdef CONFIG_SERIAL_DETECT_IRQ
 #define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST | ASYNC_AUTO_IRQ)
@@ -66,6 +56,17 @@
 #define C_P(card,port) (((card)<<6|(port)<<3) + 1)
 
 #ifdef CONFIG_MIPS_JAZZ
+#include <asm/jazz.h>
+
+#ifndef CONFIG_OLIVETTI_M700
+   /* Some Jazz machines seem to have an 8MHz crystal clock but I don't know
+      exactly which ones ... XXX */
+#define JAZZ_BASE_BAUD ( 8000000 / 16 ) /* ( 3072000 / 16) */
+#else
+/* but the M700 isn't such a strange beast */
+#define JAZZ_BASE_BAUD BASE_BAUD
+#endif
+
 #define _JAZZ_SERIAL_INIT(int, base)					\
 	{ .baud_base = JAZZ_BASE_BAUD, .irq = int, .flags = STD_COM_FLAGS,	\
 	  .iomem_base = (u8 *) base, .iomem_reg_shift = 0,			\
@@ -77,26 +78,6 @@
 #define JAZZ_SERIAL_PORT_DEFNS
 #endif
 
-#ifdef CONFIG_MIPS_ATLAS
-#include <asm/mips-boards/atlas.h>
-#include <asm/mips-boards/atlasint.h>
-#define ATLAS_SERIAL_PORT_DEFNS			\
-	/* UART CLK   PORT IRQ     FLAGS        */			\
-	{ 0, ATLAS_BASE_BAUD, ATLAS_UART_REGS_BASE, ATLASINT_UART, STD_COM_FLAGS },     /* ttyS0 */
-#else
-#define ATLAS_SERIAL_PORT_DEFNS
-#endif
-
-#ifdef CONFIG_MIPS_SEAD
-#include <asm/mips-boards/sead.h>
-#include <asm/mips-boards/seadint.h>
-#define SEAD_SERIAL_PORT_DEFNS			\
-	/* UART CLK   PORT IRQ     FLAGS        */			\
-	{ 0, SEAD_BASE_BAUD, SEAD_UART0_REGS_BASE, SEADINT_UART0, STD_COM_FLAGS },     /* ttyS0 */
-#else
-#define SEAD_SERIAL_PORT_DEFNS
-#endif
-
 #ifdef CONFIG_MIPS_COBALT
 #include <asm/cobalt/cobalt.h>
 #define COBALT_BASE_BAUD  (18432000 / 16)
@@ -158,35 +139,6 @@
 #define IVR_SERIAL_PORT_DEFNS
 #endif
 
-#ifdef CONFIG_LASAT
-/* This dummy definition allocates one element in the SERIAL_PORT_DFNS
- * list below. This element is filled out by the the code in serial_init() 
- * in arch/mips/lasat/setup.c which autoselects the configuration based 
- * on machine type. */
-#define LASAT_SERIAL_PORT_DEFNS { },
-#else
-#define LASAT_SERIAL_PORT_DEFNS
-#endif
-
-#ifdef CONFIG_SERIAL_AU1X00
-#include <asm/au1000.h>
-#define AU1X00_SERIAL_PORT_DEFNS                                    \
-    { .baud_base = 0, .iomem_base = (u8 *)UART0_ADDR,               \
-	    .irq = AU1000_UART0_INT,  .flags = STD_COM_FLAGS,       \
-		    .iomem_reg_shift = 2, },                        \
-    { .baud_base = 0, .iomem_base = (u8 *)UART1_ADDR,               \
-	    .irq = AU1000_UART1_INT,  .flags = STD_COM_FLAGS,       \
-		    .iomem_reg_shift = 2 },                         \
-    { .baud_base = 0, .iomem_base = (u8 *)UART2_ADDR,               \
-	    .irq = AU1000_UART2_INT,  .flags = STD_COM_FLAGS,       \
-		    .iomem_reg_shift = 2},                          \
-    { .baud_base = 0, .iomem_base = (u8 *)UART3_ADDR,               \
-	    .irq = AU1000_UART3_INT,  .flags = STD_COM_FLAGS,       \
-		    .iomem_reg_shift = 2},
-#else
-#define AU1X00_SERIAL_PORT_DEFNS
-#endif
-
 #ifdef CONFIG_TOSHIBA_JMR3927
 #include <asm/jmr3927/jmr3927.h>
 #define TXX927_SERIAL_PORT_DEFNS                              \
@@ -198,6 +150,21 @@
 #define TXX927_SERIAL_PORT_DEFNS
 #endif
 
+#ifdef CONFIG_SERIAL_AU1X00
+#include <asm/mach-au1x00/au1000.h>
+#define AU1000_SERIAL_PORT_DEFNS                              \
+    { .baud_base = 0, .port = UART0_ADDR, .irq = AU1000_UART0_INT,  \
+      .flags = STD_COM_FLAGS, .type = 1 },                        \
+    { .baud_base = 0, .port = UART1_ADDR, .irq = AU1000_UART1_INT,  \
+      .flags = STD_COM_FLAGS, .type = 1 },     \
+    { .baud_base = 0, .port = UART2_ADDR, .irq = AU1000_UART2_INT,  \
+      .flags = STD_COM_FLAGS, .type = 1 },    \
+    { .baud_base = 0, .port = UART3_ADDR, .irq = AU1000_UART3_INT,  \
+      .flags = STD_COM_FLAGS, .type = 1 },
+#else
+#define AU1000_SERIAL_PORT_DEFNS
+#endif
+
 #ifdef CONFIG_HAVE_STD_PC_SERIAL_PORT
 #define STD_SERIAL_PORT_DEFNS			\
 	/* UART CLK   PORT IRQ     FLAGS        */			\
@@ -341,6 +308,24 @@
 #define MOMENCO_OCELOT_C_SERIAL_PORT_DEFNS
 #endif
 
+#ifdef CONFIG_TITAN_SERIAL
+/* 16552 20 MHz crystal */
+#define TITAN_SERIAL_BASE_BAUD	( 20000000 / 16 )
+#define	TITAN_SERIAL_IRQ	XXX
+#define	TITAN_SERIAL_BASE	0xffffffff
+
+#define	_TITAN_SERIAL_INIT(int, base)					\
+	{ baud_base: TITAN_SERIAL_BASE_BAUD, irq: int,			\
+	  flags: STD_COM_FLAGS,	iomem_base: (u8 *) base,		\
+	  iomem_reg_shift: 2, io_type: SERIAL_IO_MEM			\
+	}
+
+#define TITAN_SERIAL_PORT_DEFNS						\
+	_TITAN_SERIAL_INIT(TITAN_SERIAL_IRQ, TITAN_SERIAL_BASE)
+#else
+#define TITAN_SERIAL_PORT_DEFNS
+#endif
+
 #ifdef CONFIG_DDB5477
 #include <asm/ddb5xxx/ddb5477.h>
 #define DDB5477_SERIAL_PORT_DEFNS                                       \
@@ -354,95 +339,33 @@
 #define DDB5477_SERIAL_PORT_DEFNS
 #endif
 
-#ifdef CONFIG_SGI_IP27
-
-/*
- * Note about serial ports and consoles:
- * For console output, everyone uses the IOC3 UARTA (offset 0x178)
- * connected to the master node (look in ip27_setup_console() and
- * ip27prom_console_write()).
- *
- * For serial (/dev/ttyS0 etc), we can not have hardcoded serial port
- * addresses on a partitioned machine. Since we currently use the ioc3
- * serial ports, we use dynamic serial port discovery that the serial.c
- * driver uses for pci/pnp ports (there is an entry for the SGI ioc3
- * boards in pci_boards[]). Unfortunately, UARTA's pio address is greater
- * than UARTB's, although UARTA on o200s has traditionally been known as
- * port 0. So, we just use one serial port from each ioc3 (since the
- * serial driver adds addresses to get to higher ports).
- *
- * The first one to do a register_console becomes the preferred console
- * (if there is no kernel command line console= directive). /dev/console
- * (ie 5, 1) is then "aliased" into the device number returned by the
- * "device" routine referred to in this console structure
- * (ip27prom_console_dev).
- *
- * Also look in ip27-pci.c:pci_fixuop_ioc3() for some comments on working
- * around ioc3 oddities in this respect.
- *
- * The IOC3 serials use a 22MHz clock rate with an additional divider by 3.
- * (IOC3_BAUD = (22000000 / (3*16)))
- *
- * At the moment this is only a skeleton definition as we register all serials
- * at runtime.
- */
-
-#define IP27_SERIAL_PORT_DEFNS
-#else
-#define IP27_SERIAL_PORT_DEFNS
-#endif /* CONFIG_SGI_IP27 */
-
 #ifdef CONFIG_SGI_IP32
-
-#include <asm/ip32/ip32_ints.h>
-
 /*
  * The IP32 (SGI O2) has standard serial ports (UART 16550A) mapped in memory
+ * They are initialized in ip32_setup
  */
-
-/* Standard COM flags (except for COM4, because of the 8514 problem) */
-#ifdef CONFIG_SERIAL_DETECT_IRQ
-#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST | ASYNC_AUTO_IRQ)
-#define STD_COM4_FLAGS (ASYNC_BOOT_AUTOCONF | ASYNC_AUTO_IRQ)
-#else
-#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF/* | ASYNC_SKIP_TEST*/)
-#define STD_COM4_FLAGS ASYNC_BOOT_AUTOCONF
-#endif
-
 #define IP32_SERIAL_PORT_DEFNS				\
-        { .baud_base = BASE_BAUD,				\
-	  .irq = MACEISA_SERIAL1_IRQ,			\
-          .flags = STD_COM_FLAGS,				\
-          .iomem_base = (u8*)MACE_BASE+MACEISA_SER1_BASE,	\
-          .iomem_reg_shift = 8,				\
-          .io_type = SERIAL_IO_MEM},                      \
-        { .baud_base = BASE_BAUD,				\
-	  .irq = MACEISA_SERIAL2_IRQ,			\
-          .flags = STD_COM_FLAGS,				\
-          .iomem_base = (u8*)MACE_BASE+MACEISA_SER2_BASE,	\
-          .iomem_reg_shift = 8,				\
-          .io_type = SERIAL_IO_MEM},
+        {},{},
 #else
 #define IP32_SERIAL_PORT_DEFNS
-#endif /* CONFIG_SGI_IP31 */
+#endif /* CONFIG_SGI_IP32 */
 
 #define SERIAL_PORT_DFNS				\
-	IVR_SERIAL_PORT_DEFNS           		\
-	ITE_SERIAL_PORT_DEFNS           		\
-	ATLAS_SERIAL_PORT_DEFNS				\
-	SEAD_SERIAL_PORT_DEFNS				\
 	COBALT_SERIAL_PORT_DEFNS			\
-	LASAT_SERIAL_PORT_DEFNS				\
+	DDB5477_SERIAL_PORT_DEFNS			\
 	EV96100_SERIAL_PORT_DEFNS			\
-	JAZZ_SERIAL_PORT_DEFNS				\
-	STD_SERIAL_PORT_DEFNS				\
 	EXTRA_SERIAL_PORT_DEFNS				\
 	HUB6_SERIAL_PORT_DFNS				\
-	MOMENCO_OCELOT_SERIAL_PORT_DEFNS		\
+	IP32_SERIAL_PORT_DEFNS                          \
+	ITE_SERIAL_PORT_DEFNS           		\
+	IVR_SERIAL_PORT_DEFNS           		\
+	JAZZ_SERIAL_PORT_DEFNS				\
+	STD_SERIAL_PORT_DEFNS				\
 	MOMENCO_OCELOT_G_SERIAL_PORT_DEFNS		\
 	MOMENCO_OCELOT_C_SERIAL_PORT_DEFNS		\
-	AU1X00_SERIAL_PORT_DEFNS			\
-	TXX927_SERIAL_PORT_DEFNS        		\
-	DDB5477_SERIAL_PORT_DEFNS
+	MOMENCO_OCELOT_SERIAL_PORT_DEFNS		\
+	TITAN_SERIAL_PORT_DEFNS				\
+	TXX927_SERIAL_PORT_DEFNS                        \
+	AU1000_SERIAL_PORT_DEFNS
 
 #endif /* _ASM_SERIAL_H */
--- diff/include/asm-mips/sgi/ioc.h	2003-08-20 14:16:33.000000000 +0100
+++ source/include/asm-mips/sgi/ioc.h	2004-02-23 13:56:47.000000000 +0000
@@ -14,48 +14,13 @@
 #define _SGI_IOC_H
 
 #include <linux/types.h>
+#include <asm/sgi/pi1.h>
 
 /* 
  * All registers are 8-bit wide alligned on 32-bit boundary. Bad things
  * happen if you try word access them. You have been warned.
  */
 
-struct sgioc_pport_regs {
-	u8 _data[3];
-	volatile u8 data;
-	u8 _ctrl[3];
-	volatile u8 ctrl;
-#define SGIOC_PCTRL_STROBE	0x01
-#define SGIOC_PCTRL_AFD		0x02
-#define SGIOC_PCTRL_INIT	0x04
-#define SGIOC_PCTRL_SLIN	0x08
-#define SGIOC_PCTRL_DIRECTION	0x20
-#define SGIOC_PCTRL_SEL		0x40
-	u8 _status[3];
-	volatile u8 status;
-#define SGIOC_PSTAT_DEVID	0x03
-#define SGIOC_PSTAT_NOINK	0x04
-#define SGIOC_PSTAT_ERROR	0x08
-#define SGIOC_PSTAT_ONLINE	0x10
-#define SGIOC_PSTAT_PE		0x20
-#define SGIOC_PSTAT_ACK		0x40
-#define SGIOC_PSTAT_BUSY	0x80
-	u8 _dmactrl[3];
-	volatile u8 dmactrl;
-	u8 _intrstat[3];
-	volatile u8 intrstat;
-	u8 _intrmask[3];
-	volatile u8 intrmask;
-	u8 _timer1[3];
-	volatile u8 timer1;
-	u8 _timer2[3];
-	volatile u8 timer2;
-	u8 _timer3[3];
-	volatile u8 timer3;
-	u8 _timer4[3];
-	volatile u8 timer4;
-};
-
 struct sgioc_uart_regs {
 	u8 _ctrl1[3];
 	volatile u8 ctrl1;
@@ -153,7 +118,7 @@ struct sgint_regs {
 extern u8 sgi_ioc_reset, sgi_ioc_write;
 
 struct sgioc_regs {
-	struct sgioc_pport_regs pport;
+	struct pi1_regs pport;
 	u32 _unused0[2];
 	struct sgioc_uart_regs serport;
 	struct sgioc_keyb_regs kbdmouse;
--- diff/include/asm-mips/sgialib.h	2003-08-20 14:16:33.000000000 +0100
+++ source/include/asm-mips/sgialib.h	2004-02-23 13:56:47.000000000 +0000
@@ -24,11 +24,10 @@ extern LONG *_prom_argv, *_prom_envp;
 #define prom_argc(index) ((char *) (long) _prom_argc[(index)])
 
 extern int prom_flags;
+
 #define PROM_FLAG_ARCS			1
 #define PROM_FLAG_USE_AS_CONSOLE	2
-
-/* Init the PROM library and it's internal data structures. */
-extern void prom_init(int argc, char **argv, char **envp, int *prom_vec);
+#define PROM_FLAG_DONT_FREE_TEMP	4
 
 /* Simple char-by-char console I/O. */
 extern void prom_putchar(char c);
@@ -123,5 +122,6 @@ extern VOID ArcEnterInteractiveMode(VOID
 extern long prom_cfgsave(VOID);
 extern struct linux_sysid *prom_getsysid(VOID);
 extern VOID ArcFlushAllCaches(VOID);
+extern DISPLAY_STATUS *ArcGetDisplayStatus(ULONG FileID);
 
 #endif /* _ASM_SGIALIB_H */
--- diff/include/asm-mips/sgiarcs.h	2003-07-08 09:55:19.000000000 +0100
+++ source/include/asm-mips/sgiarcs.h	2004-02-23 13:56:47.000000000 +0000
@@ -236,6 +236,8 @@ struct linux_romvec {
 
 	/* Miscellaneous. */
 	LONG	cache_flush;
+	LONG	TestUnicodeCharacter;		/* ARC; not sure if ARCS too */
+	LONG	GetDisplayStatus;
 };
 
 /* The SGI ARCS parameter block is in a fixed location for standalone
--- diff/include/asm-mips/sibyte/board.h	2003-07-08 09:55:19.000000000 +0100
+++ source/include/asm-mips/sibyte/board.h	2004-02-23 13:56:47.000000000 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2000, 2001 Broadcom Corporation
+ * Copyright (C) 2000, 2001, 2002, 2003 Broadcom Corporation
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
@@ -19,10 +19,13 @@
 #ifndef _SIBYTE_BOARD_H
 #define _SIBYTE_BOARD_H
 
+#include <linux/config.h>
+
 #ifdef CONFIG_SIBYTE_BOARD
 
 #if defined(CONFIG_SIBYTE_SWARM) || defined(CONFIG_SIBYTE_PTSWARM) || \
-    defined(CONFIG_SIBYTE_CRHONE) || defined(CONFIG_SIBYTE_CRHINE)
+    defined(CONFIG_SIBYTE_CRHONE) || defined(CONFIG_SIBYTE_CRHINE) || \
+    defined(CONFIG_SIBYTE_LITTLESUR)
 #include <asm/sibyte/swarm.h>
 #endif
 
--- diff/include/asm-mips/sibyte/carmel.h	2003-07-08 09:55:19.000000000 +0100
+++ source/include/asm-mips/sibyte/carmel.h	2004-02-23 13:56:47.000000000 +0000
@@ -18,6 +18,8 @@
 #ifndef __ASM_SIBYTE_CARMEL_H
 #define __ASM_SIBYTE_CARMEL_H
 
+#include <linux/config.h>
+
 #include <asm/sibyte/sb1250.h>
 #include <asm/sibyte/sb1250_int.h>
 
--- diff/include/asm-mips/sibyte/sb1250.h	2003-08-20 14:16:33.000000000 +0100
+++ source/include/asm-mips/sibyte/sb1250.h	2004-02-23 13:56:47.000000000 +0000
@@ -58,6 +58,6 @@ extern void prom_printf(char *fmt, ...);
 
 #endif
 
-#define IO_SPACE_BASE KSEG1
+#define IOADDR(a) (UNCAC_BASE + (a))
 
 #endif
--- diff/include/asm-mips/sibyte/sentosa.h	2003-07-08 09:55:19.000000000 +0100
+++ source/include/asm-mips/sibyte/sentosa.h	2004-02-23 13:56:47.000000000 +0000
@@ -18,6 +18,7 @@
 #ifndef __ASM_SIBYTE_SENTOSA_H
 #define __ASM_SIBYTE_SENTOSA_H
 
+#include <linux/config.h>
 #include <asm/sibyte/sb1250.h>
 #include <asm/sibyte/sb1250_int.h>
 
--- diff/include/asm-mips/sibyte/swarm.h	2003-07-08 09:55:19.000000000 +0100
+++ source/include/asm-mips/sibyte/swarm.h	2004-02-23 13:56:47.000000000 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2000, 2001 Broadcom Corporation
+ * Copyright (C) 2000, 2001, 2002, 2003 Broadcom Corporation
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
@@ -18,36 +18,52 @@
 #ifndef __ASM_SIBYTE_SWARM_H
 #define __ASM_SIBYTE_SWARM_H
 
+#include <linux/config.h>
 #include <asm/sibyte/sb1250.h>
 #include <asm/sibyte/sb1250_int.h>
 
 #ifdef CONFIG_SIBYTE_SWARM
 #define SIBYTE_BOARD_NAME "BCM91250A (SWARM)"
+#define SIBYTE_HAVE_PCMCIA 1
+#define SIBYTE_HAVE_IDE    1
 #endif
 #ifdef CONFIG_SIBYTE_PTSWARM
 #define SIBYTE_BOARD_NAME "PTSWARM"
+#define SIBYTE_HAVE_PCMCIA 1
+#define SIBYTE_HAVE_IDE    1
+#define SIBYTE_DEFAULT_CONSOLE "ttyS0,115200"
+#endif
+#ifdef CONFIG_SIBYTE_LITTLESUR
+#define SIBYTE_BOARD_NAME "BCM1250C2 (LittleSur)"
+#define SIBYTE_HAVE_PCMCIA 0
+#define SIBYTE_HAVE_IDE    1
+#define SIBYTE_DEFAULT_CONSOLE "cfe0"
 #endif
 #ifdef CONFIG_SIBYTE_CRHONE
 #define SIBYTE_BOARD_NAME "BCM91125C (CRhone)"
+#define SIBYTE_HAVE_PCMCIA 0
+#define SIBYTE_HAVE_IDE    0
 #endif
 #ifdef CONFIG_SIBYTE_CRHINE
 #define SIBYTE_BOARD_NAME "BCM91120C (CRhine)"
+#define SIBYTE_HAVE_PCMCIA 0
+#define SIBYTE_HAVE_IDE    0
 #endif
 
 /* Generic bus chip selects */
 #define LEDS_CS         3
 #define LEDS_PHYS       0x100a0000
-#if defined(CONFIG_SIBYTE_SWARM) || defined(CONFIG_SIBYTE_PTSWARM)
+
+#ifdef SIBYTE_HAVE_IDE
 #define IDE_CS          4
 #define IDE_PHYS        0x100b0000
-#define PCMCIA_CS       6
-#define PCMCIA_PHYS     0x11000000
-#endif
-
-/* GPIOs */
-#if defined(CONFIG_SIBYTE_SWARM) || defined(CONFIG_SIBYTE_PTSWARM)
 #define K_GPIO_GB_IDE   4
 #define K_INT_GB_IDE    (K_INT_GPIO_0 + K_GPIO_GB_IDE)
+#endif
+
+#ifdef SIBYTE_HAVE_PCMCIA
+#define PCMCIA_CS       6
+#define PCMCIA_PHYS     0x11000000
 #define K_GPIO_PC_READY 9
 #define K_INT_PC_READY  (K_INT_GPIO_0 + K_GPIO_PC_READY)
 #endif
--- diff/include/asm-mips/sibyte/trace_prof.h	2003-07-08 09:55:19.000000000 +0100
+++ source/include/asm-mips/sibyte/trace_prof.h	2004-02-23 13:56:47.000000000 +0000
@@ -19,6 +19,7 @@
 #ifndef __ASM_SIBYTE_TRACE_PROF_H
 #define __ASM_SIBYTE_TRACE_PROF_H
 
+#undef DBG
 #if SBPROF_TB_DEBUG
 #define DBG(a) a
 #else
@@ -62,10 +63,10 @@ struct sbprof_tb {
 	     saturate 40 bits.  No subsequent use of SCD performance counters
 	     or trace buffer.
    Effect:   Starts gathering random ZBbus profiles using trace buffer. */
-static int sbprof_zbprof_start(struct file *filp);
+extern int sbprof_zbprof_start(struct file *filp);
 
 /* Effect: Stops collection of ZBbus profiles */
-static int sbprof_zbprof_stop(void);
+extern int sbprof_zbprof_stop(void);
 
 
 /***************************************************************************
--- diff/include/asm-mips/sigcontext.h	2003-08-20 14:16:33.000000000 +0100
+++ source/include/asm-mips/sigcontext.h	2004-02-23 13:56:47.000000000 +0000
@@ -65,6 +65,7 @@ struct sigcontext {
 	unsigned int	sc_cause;
 };
 
+#ifdef __KERNEL__
 struct sigcontext32 {
 	__u32	sc_regmask;		/* Unused */
 	__u32	sc_status;
@@ -84,6 +85,7 @@ struct sigcontext32 {
 
 	__u32	sc_sigset[4];		/* kernel's sigset_t */
 };
+#endif /* __KERNEL__ */
 
 #endif /* _MIPS_SIM == _MIPS_SIM_ABI64 || _MIPS_SIM == _MIPS_SIM_NABI32 */
 
--- diff/include/asm-mips/siginfo.h	2003-08-20 14:16:33.000000000 +0100
+++ source/include/asm-mips/siginfo.h	2004-02-23 13:56:47.000000000 +0000
@@ -3,7 +3,7 @@
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  *
- * Copyright (C) 1998, 1999, 2001 Ralf Baechle
+ * Copyright (C) 1998, 1999, 2001, 2003 Ralf Baechle
  * Copyright (C) 2000, 2001 Silicon Graphics, Inc.
  */
 #ifndef _ASM_SIGINFO_H
@@ -11,11 +11,11 @@
 
 #include <linux/config.h>
 
-#define SIGEV_PAD_SIZE	((SIGEV_MAX_SIZE/sizeof(int)) - 4)
+#define SIGEV_HEAD_SIZE	(sizeof(long) + 2*sizeof(int))
+#define SIGEV_PAD_SIZE	((SIGEV_MAX_SIZE-SIGEV_HEAD_SIZE) / sizeof(int))
 #define SI_PAD_SIZE	((SI_MAX_SIZE/sizeof(int)) - 4)
 
 #define HAVE_ARCH_SIGINFO_T
-#define HAVE_ARCH_SIGEVENT_T
 
 /*
  * We duplicate the generic versions - <asm-generic/siginfo.h> is just borked
@@ -177,38 +177,6 @@ typedef struct siginfo32 {
 #define SI_TIMER __SI_CODE(__SI_TIMER,-3) /* sent by timer expiration */
 #define SI_MESGQ	-4	/* sent by real time mesq state change */
 
-/*
- * sigevent definitions
- *
- * It seems likely that SIGEV_THREAD will have to be handled from
- * userspace, libpthread transmuting it to SIGEV_SIGNAL, which the
- * thread manager then catches and does the appropriate nonsense.
- * However, everything is written out here so as to not get lost.
- */
-#undef SIGEV_NONE
-#undef SIGEV_SIGNAL
-#undef SIGEV_THREAD
-#define SIGEV_NONE	128	/* other notification: meaningless */
-#define SIGEV_SIGNAL	129	/* notify via signal */
-#define SIGEV_CALLBACK	130	/* ??? */
-#define SIGEV_THREAD	131	/* deliver via thread creation */
-
-/* XXX This one isn't yet IRIX / ABI compatible.  */
-typedef struct sigevent {
-	int	sigev_notify;
-	sigval_t	sigev_value;
-	int	sigev_signo;
-	union {
-		int	_pad[SIGEV_PAD_SIZE];
-		int	_tid;
-
-		struct {
-			void	(*_function)(sigval_t);
-			void	*_attribute;	/* really pthread_attr_t */
-		} _sigev_thread;
-	} _sigev_un;
-} sigevent_t;
-
 #ifdef __KERNEL__
 
 /*
--- diff/include/asm-mips/sim.h	2003-08-20 14:16:36.000000000 +0100
+++ source/include/asm-mips/sim.h	2004-02-23 13:56:47.000000000 +0000
@@ -13,14 +13,14 @@
 
 #include <asm/offset.h>
 
-#ifdef CONFIG_MIPS32
-
 /* Used in declaration of save_static functions.  */
 #define static_unused static __attribute__((unused))
 
 #define __str2(x) #x
 #define __str(x) __str2(x)
 
+#ifdef CONFIG_MIPS32
+
 #define save_static_function(symbol)					\
 __asm__ (								\
 	".text\n\t"							\
@@ -42,20 +42,12 @@ __asm__ (								\
 	".end\t" #symbol "\n\t"						\
 	".size\t" #symbol",. - " #symbol)
 
-#define save_static(frame)	do { } while (0)
-
 #define nabi_no_regargs
 
 #endif /* CONFIG_MIPS32 */
 
 #ifdef CONFIG_MIPS64
 
-/* Used in declaration of save_static functions.  */
-#define static_unused static __attribute__((unused))
-
-#define __str2(x) #x
-#define __str(x) __str2(x)
-
 #define save_static_function(symbol)					\
 __asm__ (								\
 	".text\n\t"							\
@@ -65,23 +57,18 @@ __asm__ (								\
 	".ent\t" #symbol ", 0\n"					\
 	#symbol":\n\t"							\
 	".frame\t$29, 0, $31\n\t"					\
+	"sd\t$16,"__str(PT_R16)"($29)\t\t\t# save_static_function\n\t"	\
+	"sd\t$17,"__str(PT_R17)"($29)\n\t"				\
+	"sd\t$18,"__str(PT_R18)"($29)\n\t"				\
+	"sd\t$19,"__str(PT_R19)"($29)\n\t"				\
+	"sd\t$20,"__str(PT_R20)"($29)\n\t"				\
+	"sd\t$21,"__str(PT_R21)"($29)\n\t"				\
+	"sd\t$22,"__str(PT_R22)"($29)\n\t"				\
+	"sd\t$23,"__str(PT_R23)"($29)\n\t"				\
+	"sd\t$30,"__str(PT_R30)"($29)\n\t"				\
 	".end\t" #symbol "\n\t"						\
 	".size\t" #symbol",. - " #symbol)
 
-#define save_static(frame)						\
-	__asm__ __volatile__(						\
-		"sd\t$16,"__str(PT_R16)"(%0)\n\t"			\
-		"sd\t$17,"__str(PT_R17)"(%0)\n\t"			\
-		"sd\t$18,"__str(PT_R18)"(%0)\n\t"			\
-		"sd\t$19,"__str(PT_R19)"(%0)\n\t"			\
-		"sd\t$20,"__str(PT_R20)"(%0)\n\t"			\
-		"sd\t$21,"__str(PT_R21)"(%0)\n\t"			\
-		"sd\t$22,"__str(PT_R22)"(%0)\n\t"			\
-		"sd\t$23,"__str(PT_R23)"(%0)\n\t"			\
-		"sd\t$30,"__str(PT_R30)"(%0)\n\t"			\
-		: /* No outputs */					\
-		: "r" (frame))
-
 #define nabi_no_regargs							\
 	unsigned long __dummy0,						\
 	unsigned long __dummy1,						\
--- diff/include/asm-mips/smp.h	2004-02-09 10:36:12.000000000 +0000
+++ source/include/asm-mips/smp.h	2004-02-23 13:56:47.000000000 +0000
@@ -16,6 +16,7 @@
 #ifdef CONFIG_SMP
 
 #include <linux/bitops.h>
+#include <linux/linkage.h>
 #include <linux/threads.h>
 #include <linux/cpumask.h>
 #include <asm/atomic.h>
@@ -52,11 +53,6 @@ extern cpumask_t cpu_online_map;
 
 #define cpu_online(cpu)		cpu_isset(cpu, cpu_online_map)
 
-static inline unsigned int num_online_cpus(void)
-{
-	return cpus_weight(cpu_online_map);
-}
-
 extern cpumask_t cpu_callout_map;
 /* We don't mark CPUs online until __cpu_up(), so we need another measure */
 static inline int num_booting_cpus(void)
@@ -64,6 +60,63 @@ static inline int num_booting_cpus(void)
 	return cpus_weight(cpu_callout_map);
 }
 
+/* These are defined by the board-specific code. */
+
+/*
+ * Cause the function described by call_data to be executed on the passed
+ * cpu.  When the function has finished, increment the finished field of
+ * call_data.
+ */
+extern void core_send_ipi(int cpu, unsigned int action);
+
+/*
+ * Detect available CPUs, populate phys_cpu_present_map
+ */
+extern void prom_build_cpu_map(void);
+
+/*
+ * Firmware CPU startup hook
+ */
+extern void prom_boot_secondary(int cpu, struct task_struct *idle);
+
+/*
+ *  After we've done initial boot, this function is called to allow the
+ *  board code to clean up state, if needed
+ */
+extern void prom_init_secondary(void);
+
+/*
+ * Callout to firmware before smp_init
+ */
+extern void prom_prepare_cpus(unsigned int max_cpus);
+
+/*
+ * Do whatever setup needs to be done for SMP at the board level.  Return
+ * the number of cpus in the system, including this one
+ */
+extern int prom_setup_smp(void);
+
+/*
+ * Last chance for the board code to finish SMP initialization before
+ * the CPU is "online".
+ */
+extern void prom_smp_finish(void);
+
+/* Hook for after all CPUs are online */
+extern void prom_cpus_done(void);
+
+extern void asmlinkage smp_bootstrap(void);
+
+/*
+ * this function sends a 'reschedule' IPI to another CPU.
+ * it goes straight through and wastes no time serializing
+ * anything. Worst case is that we lose a reschedule ...
+ */
+static inline void smp_send_reschedule(int cpu)
+{
+	core_send_ipi(cpu, SMP_RESCHEDULE_YOURSELF);
+}
+
 #endif /* CONFIG_SMP */
 
 #endif /* __ASM_SMP_H */
--- diff/include/asm-mips/sn/addrs.h	2003-08-20 14:16:36.000000000 +0100
+++ source/include/asm-mips/sn/addrs.h	2004-02-23 13:56:47.000000000 +0000
@@ -16,7 +16,6 @@
 #endif /* !__ASSEMBLY__ */
 
 #include <asm/addrspace.h>
-#include <asm/reg.h>
 #include <asm/sn/kldir.h>
 
 #if defined(CONFIG_SGI_IP27)
@@ -439,9 +438,9 @@
 #define PI_ERROR_SIZE(nasid)	KLD_PI_ERROR(nasid)->size
 
 #define NODE_OFFSET_TO_K0(_nasid, _off)					\
-	PHYS_TO_K0((NODE_OFFSET(_nasid) + (_off)) | K0BASE)
+	PHYS_TO_K0((NODE_OFFSET(_nasid) + (_off)) | CAC_BASE)
 #define NODE_OFFSET_TO_K1(_nasid, _off)					\
-	TO_UNCAC((NODE_OFFSET(_nasid) + (_off)) | K1BASE)
+	TO_UNCAC((NODE_OFFSET(_nasid) + (_off)) | UNCAC_BASE)
 #define K0_TO_NODE_OFFSET(_k0addr)					\
 	((__psunsigned_t)(_k0addr) & NODE_ADDRSPACE_MASK)
 
--- diff/include/asm-mips/sn/arch.h	2003-08-20 14:16:36.000000000 +0100
+++ source/include/asm-mips/sn/arch.h	2004-02-23 13:56:47.000000000 +0000
@@ -35,12 +35,9 @@ typedef u64	nic_t;
 #define CNODE_NUM_CPUS(_cnode)		(NODEPDA(_cnode)->node_num_cpus)
 
 #define CNODE_TO_CPU_BASE(_cnode)	(NODEPDA(_cnode)->node_first_cpu)
-#define cputocnode(cpu)				\
-               (cpu_data[(cpu)].p_nodeid)
-#define cputonasid(cpu)				\
-               (cpu_data[(cpu)].p_nasid)
-#define cputoslice(cpu)				\
-               (cpu_data[(cpu)].p_slice)
+#define cputocnode(cpu)			(cpu_data[(cpu)].p_nodeid)
+#define cputonasid(cpu)			(cpu_data[(cpu)].p_nasid)
+#define cputoslice(cpu)			(cpu_data[(cpu)].p_slice)
 #define makespnum(_nasid, _slice)					\
 		(((_nasid) << CPUS_PER_NODE_SHFT) | (_slice))
 
@@ -100,8 +97,6 @@ nasid_t compact_to_nasid_nodeid(cnodeid_
 #define CPUID_TO_COMPACT_NODEID(cpu)	(cpuid_to_compact_node[(cpu)])
 #endif
 
-extern int node_getlastslot(cnodeid_t);
-
 #endif /* !__ASSEMBLY__ */
 
 #define SLOT_BITMASK    	(MAX_MEM_SLOTS - 1)
--- diff/include/asm-mips/sn/intr.h	2003-08-20 14:16:36.000000000 +0100
+++ source/include/asm-mips/sn/intr.h	2004-02-23 13:56:47.000000000 +0000
@@ -17,18 +17,14 @@
 #define	N_INTPENDJUNK_BITS	8
 #define	INTPENDJUNK_CLRBIT	0x80
 
-#include <asm/sn/intr_public.h>
-
-#ifndef __ASSEMBLY__
-
 /*
  * Macros to manipulate the interrupt register on the calling hub chip.
  */
 
-#define LOCAL_HUB_SEND_INTR(_level)	LOCAL_HUB_S(PI_INT_PEND_MOD, \
-						    (0x100|(_level)))
-#define REMOTE_HUB_SEND_INTR(_hub, _level) \
-		REMOTE_HUB_S((_hub), PI_INT_PEND_MOD, (0x100|(_level)))
+#define LOCAL_HUB_SEND_INTR(level)				\
+	LOCAL_HUB_S(PI_INT_PEND_MOD, (0x100 | (level)))
+#define REMOTE_HUB_SEND_INTR(hub, level)			\
+	REMOTE_HUB_S((hub), PI_INT_PEND_MOD, (0x100 | (level)))
 
 /*
  * When clearing the interrupt, make sure this clear does make it
@@ -36,16 +32,19 @@
  * We do an uncached load of the int_pend0 register to ensure this.
  */
 
-#define LOCAL_HUB_CLR_INTR(_level)	  \
-                LOCAL_HUB_S(PI_INT_PEND_MOD, (_level)),	\
-                LOCAL_HUB_L(PI_INT_PEND0)
-#define REMOTE_HUB_CLR_INTR(_hub, _level) \
-		REMOTE_HUB_S((_hub), PI_INT_PEND_MOD, (_level)),	\
-                REMOTE_HUB_L((_hub), PI_INT_PEND0)
-
-#else /* __ASSEMBLY__ */
-
-#endif /* __ASSEMBLY__ */
+#define LOCAL_HUB_CLR_INTR(level)	  			\
+do {								\
+	LOCAL_HUB_S(PI_INT_PEND_MOD, (level));			\
+	LOCAL_HUB_L(PI_INT_PEND0);				\
+} while (0);
+
+#define REMOTE_HUB_CLR_INTR(hub, level)				\
+do {								\
+	nasid_t  __hub = (hub);					\
+								\
+	REMOTE_HUB_S(__hub, PI_INT_PEND_MOD, (level));		\
+	REMOTE_HUB_L(__hub, PI_INT_PEND0);			\
+} while (0);
 
 /*
  * Hard-coded interrupt levels:
@@ -63,60 +62,68 @@
  */
 
 
-/* INT_PEND0 hard-coded bits. */
-#ifdef SABLE
-#define SDISK_INTR	63
-#endif
-#ifdef DEBUG_INTR_TSTAMP
-/* hard coded interrupt level for interrupt latency test interrupt */
-#define	CPU_INTRLAT_B	62
-#define	CPU_INTRLAT_A	61
-#endif
-
-/* Hardcoded bits required by software. */
-#define MSC_MESG_INTR	13
-#define CPU_ACTION_B	11
-#define CPU_ACTION_A	10
-
-/* These are determined by hardware: */
-#define CC_PEND_B	6
-#define CC_PEND_A	5
-#define UART_INTR	4
-#define PG_MIG_INTR	3
-#define GFX_INTR_B	2
-#define GFX_INTR_A	1
-#define RESERVED_INTR	0
-
-/* INT_PEND1 hard-coded bits: */
-#define MSC_PANIC_INTR	63
-#define NI_ERROR_INTR	62
-#define MD_COR_ERR_INTR	61
-#define COR_ERR_INTR_B	60
-#define COR_ERR_INTR_A	59
-#define CLK_ERR_INTR	58
-#define IO_ERROR_INTR	57	/* set up by prom */
-
-#define	DEBUG_INTR_B	55	/* used by symmon to stop all cpus */
-#define	DEBUG_INTR_A	54
-
-#define BRIDGE_ERROR_INTR 53	/* Setup by PROM to catch Bridge Errors */
-
-#define IP27_INTR_0	52	/* Reserved for PROM use */
-#define IP27_INTR_1	51	/*   (do not use in Kernel) */
-#define IP27_INTR_2	50
-#define IP27_INTR_3	49
-#define IP27_INTR_4	48
-#define IP27_INTR_5	47
-#define IP27_INTR_6	46
-#define IP27_INTR_7	45
+/*
+ * INT_PEND0 hard-coded bits.
+ */
+
+/*
+ * INT_PEND0 bits determined by hardware:
+ */
+#define RESERVED_INTR		 0	/* What is this bit? */
+#define GFX_INTR_A		 1
+#define GFX_INTR_B		 2
+#define PG_MIG_INTR		 3
+#define UART_INTR		 4
+#define CC_PEND_A		 5
+#define CC_PEND_B		 6
+
+/*
+ * INT_PEND0 used by the kernel for itself ...
+ */
+#define CPU_RESCHED_A_IRQ	 7
+#define CPU_RESCHED_B_IRQ	 8
+#define CPU_CALL_A_IRQ		 9
+#define CPU_CALL_B_IRQ		10
+#define MSC_MESG_INTR		11
+#define BASE_PCI_IRQ		12
+
+/*
+ * INT_PEND0 again, bits determined by hardware / hardcoded:
+ */
+#define SDISK_INTR		63	/* SABLE name */
+#define IP_PEND0_6_63		63	/* What is this bit? */
+
+/*
+ * INT_PEND1 hard-coded bits:
+ */
+#define NI_BRDCAST_ERR_A	39
+#define NI_BRDCAST_ERR_B	40
 
-#define	TLB_INTR_B	44	/* used for tlb flush random */
-#define	TLB_INTR_A	43
+#define LLP_PFAIL_INTR_A	41	/* see ml/SN/SN0/sysctlr.c */
+#define LLP_PFAIL_INTR_B	42
 
-#define LLP_PFAIL_INTR_B 42	/* see ml/SN/SN0/sysctlr.c */
-#define LLP_PFAIL_INTR_A 41
+#define	TLB_INTR_A		43	/* used for tlb flush random */
+#define	TLB_INTR_B		44
 
-#define NI_BRDCAST_ERR_B 40
-#define NI_BRDCAST_ERR_A 39
+#define IP27_INTR_0		45	/* Reserved for PROM use */
+#define IP27_INTR_1		46	/* do not use in Kernel */
+#define IP27_INTR_2		47
+#define IP27_INTR_3		48
+#define IP27_INTR_4		49
+#define IP27_INTR_5		50
+#define IP27_INTR_6		51
+#define IP27_INTR_7		52
+
+#define BRIDGE_ERROR_INTR	53	/* Setup by PROM to catch	*/
+					/* Bridge Errors */
+#define	DEBUG_INTR_A		54
+#define	DEBUG_INTR_B		55	/* Used by symmon to stop all cpus */
+#define IO_ERROR_INTR		57	/* Setup by PROM */
+#define CLK_ERR_INTR		58
+#define COR_ERR_INTR_A		59
+#define COR_ERR_INTR_B		60
+#define MD_COR_ERR_INTR		61
+#define NI_ERROR_INTR		62
+#define MSC_PANIC_INTR		63
 
 #endif /* __ASM_SN_INTR_H */
--- diff/include/asm-mips/sn/intr_public.h	2003-08-20 14:16:36.000000000 +0100
+++ source/include/asm-mips/sn/intr_public.h	2004-02-23 13:56:47.000000000 +0000
@@ -8,46 +8,24 @@
 #ifndef __ASM_SN_INTR_PUBLIC_H
 #define __ASM_SN_INTR_PUBLIC_H
 
-
-/* REMEMBER: If you change these, the whole world needs to be recompiled.
- * It would also require changing the hubspl.s code and SN0/intr.c
- * Currently, the spl code has no support for multiple INTPEND1 masks.
- */
-
-#define	N_INTPEND0_MASKS	1
-#define	N_INTPEND1_MASKS	1
-
-#define INTPEND0_MAXMASK	(N_INTPEND0_MASKS - 1)
-#define INTPEND1_MAXMASK	(N_INTPEND1_MASKS - 1)
-
-#ifndef __ASSEMBLY__
 #include <asm/sn/arch.h>
 
-struct intr_vecblk_s;	/* defined in asm/sn/intr.h */
-
 /*
- * The following are necessary to create the illusion of a CEL
- * on the SN0 hub.  We'll add more priority levels soon, but for
- * now, any interrupt in a particular band effectively does an spl.
- * These must be in the PDA since they're different for each processor.
- * Users of this structure must hold the vector_lock in the appropriate vector
- * block before modifying the mask arrays.  There's only one vector block
- * for each Hub so a lock in the PDA wouldn't be adequate.
+ * The following are necessary to create the illusion of a CEL on the SN0 hub.
+ * We'll add more priority levels soon, but for now, any interrupt in a
+ * particular band effectively does an spl.  These must be in the PDA since
+ * they're different for each processor.  Users of this structure must hold the
+ * vector_lock in the appropriate vector block before modifying the mask arrays.
+ * There's only one vector block for each Hub so a lock in the PDA wouldn't be
+ * adequate.
  */
-typedef struct hub_intmasks_s {
+struct hub_intmasks_s {
 	/*
 	 * The masks are stored with the lowest-priority (most inclusive)
 	 * in the lowest-numbered masks (i.e., 0, 1, 2...).
 	 */
-	/* INT_PEND0: */
-	hubreg_t		intpend0_masks[N_INTPEND0_MASKS];
-	/* INT_PEND1: */
-	hubreg_t		intpend1_masks[N_INTPEND1_MASKS];
-	/* INT_PEND0: */
-	struct intr_vecblk_s	*dispatch0;
-	/* INT_PEND1: */
-	struct intr_vecblk_s	*dispatch1;
-} hub_intmasks_t;
+	hubreg_t	intpend0_masks;		/* INT_PEND0 */
+	hubreg_t	intpend1_masks;		/* INT_PEND1 */
+};
 
-#endif /* !__ASSEMBLY__ */
 #endif /* __ASM_SN_INTR_PUBLIC_H */
--- diff/include/asm-mips/sn/klconfig.h	2003-08-20 14:16:36.000000000 +0100
+++ source/include/asm-mips/sn/klconfig.h	2004-02-23 13:56:47.000000000 +0000
@@ -30,7 +30,9 @@
 #include <linux/config.h>
 #include <linux/types.h>
 #include <asm/sn/types.h>
+
 #if defined(CONFIG_SGI_IP27)
+
 #include <asm/sn/sn0/addrs.h>
 //#include <sys/SN/router.h>
 // XXX Stolen from <sys/SN/router.h>:
@@ -38,12 +40,16 @@
 #include <asm/sn/sn0/sn0_fru.h>
 //#include <sys/graph.h>
 //#include <sys/xtalk/xbow.h>
+
 #elif defined(CONFIG_SGI_IP35)
+
 #include <asm/sn/sn1/addrs.h>
 #include <sys/sn/router.h>
 #include <sys/graph.h>
 #include <asm/xtalk/xbow.h>
+
 #endif /* !CONFIG_SGI_IP27 && !CONFIG_SGI_IP35 */
+
 #if defined(CONFIG_SGI_IP27) || defined(CONFIG_SGI_IP35)
 #include <asm/sn/agent.h>
 #include <asm/arc/types.h>
--- diff/include/asm-mips/sn/sn0/addrs.h	2003-08-20 14:16:36.000000000 +0100
+++ source/include/asm-mips/sn/sn0/addrs.h	2004-02-23 13:56:47.000000000 +0000
@@ -40,20 +40,6 @@
  * use some new ANSI preprocessor stuff to paste these on where needed.
  */
 
-#define CAC_BASE		0xa800000000000000
-
-#define HSPEC_BASE		0x9000000000000000
-#define IO_BASE			0x9200000000000000
-#define MSPEC_BASE		0x9400000000000000
-#define UNCAC_BASE		0x9600000000000000
-
-#define TO_PHYS(x)		(	      ((x) & TO_PHYS_MASK))
-#define TO_CAC(x)		(CAC_BASE   | ((x) & TO_PHYS_MASK))
-#define TO_UNCAC(x)		(UNCAC_BASE | ((x) & TO_PHYS_MASK))
-#define TO_MSPEC(x)		(MSPEC_BASE | ((x) & TO_PHYS_MASK))
-#define TO_HSPEC(x)		(HSPEC_BASE | ((x) & TO_PHYS_MASK))
-
-
 /*
  * The following couple of definitions will eventually need to be variables,
  * since the amount of address space assigned to each node depends on
@@ -192,7 +178,7 @@
 #define IP27PROM_DECOMP_SIZE	0xfff00
 
 #define IP27PROM_BASE		PHYS_TO_K0(0x01a00000)
-#define IP27PROM_BASE_MAPPED	(K2BASE | 0x1fc00000)
+#define IP27PROM_BASE_MAPPED	(UNCAC_BASE | 0x1fc00000)
 #define IP27PROM_SIZE_MAX	0x100000
 
 #define IP27PROM_PCFG		PHYS_TO_K0(0x01b00000)
@@ -223,7 +209,7 @@
 
 #define IO6PROM_BASE		PHYS_TO_K0(0x01c00000)
 #define IO6PROM_SIZE		0x400000
-#define	IO6PROM_BASE_MAPPED	(K2BASE | 0x11c00000)
+#define	IO6PROM_BASE_MAPPED	(UNCAC_BASE | 0x11c00000)
 #define IO6DPROM_BASE		PHYS_TO_K0(0x01c00000)
 #define IO6DPROM_SIZE		0x200000
 
--- diff/include/asm-mips/sn/sn0/ip27.h	2003-08-20 14:16:36.000000000 +0100
+++ source/include/asm-mips/sn/sn0/ip27.h	2004-02-23 13:56:47.000000000 +0000
@@ -84,14 +84,9 @@
 
 /* Sanity hazzard ...  Below all the Origin hacks are following.  */
 
-#define CPU_RESCHED_A_IRQ	0
-#define CPU_RESCHED_B_IRQ	1
-#define CPU_CALL_A_IRQ		2
-#define CPU_CALL_B_IRQ		3
-#define BASE_PCI_IRQ		4
-
 #define SN00_BRIDGE		0x9200000008000000
 #define SN00I_BRIDGE0		0x920000000b000000
 #define SN00I_BRIDGE1		0x920000000e000000
 #define SN00I_BRIDGE2		0x920000000f000000
+
 #endif /* _ASM_SN_SN0_IP27_H */
--- diff/include/asm-mips/sn/sn_private.h	2003-08-20 14:16:36.000000000 +0100
+++ source/include/asm-mips/sn/sn_private.h	2004-02-23 13:56:47.000000000 +0000
@@ -1,11 +1,20 @@
+#ifndef __ASM_SN_SN_PRIVATE_H
+#define __ASM_SN_SN_PRIVATE_H
+
+#include <asm/sn/types.h>
+
 extern nasid_t master_nasid;
 
+extern void cpu_node_probe(void);
 extern cnodeid_t get_compact_nodeid(void);
 extern void hub_rtc_init(cnodeid_t);
 extern void cpu_time_init(void);
 extern void per_cpu_init(void);
-extern void install_cpuintr(int cpu);
-extern void install_tlbintr(int cpu);
+extern void per_hub_init(cnodeid_t cnode);
+extern void install_cpu_nmi_handler(int slice);
+extern void install_ipi(void);
 extern void setup_replication_mask(int);
 extern void replicate_kernel_text(int);
 extern pfn_t node_getfirstfree(cnodeid_t);
+
+#endif /* __ASM_SN_SN_PRIVATE_H */
--- diff/include/asm-mips/sni.h	2003-08-20 14:16:33.000000000 +0100
+++ source/include/asm-mips/sni.h	2004-02-23 13:56:47.000000000 +0000
@@ -78,9 +78,12 @@
 /*
  * Interrupt 0-16 are EISA interrupts.  Interrupts from 16 on are assigned
  * to the other interrupts generated by ASIC PCI.
+ *
+ * INT2 is a wired-or of the push button interrupt, high temperature interrupt
+ * ASIC PCI interrupt.
  */
 #define PCIMT_KEYBOARD_IRQ	 1
-#define PCIMT_IRQ_INT2		16		/* What is that?  */
+#define PCIMT_IRQ_INT2		16
 #define PCIMT_IRQ_INTD		17
 #define PCIMT_IRQ_INTC		18
 #define PCIMT_IRQ_INTB		19
--- diff/include/asm-mips/socket.h	2004-02-09 10:36:12.000000000 +0000
+++ source/include/asm-mips/socket.h	2004-02-23 13:56:47.000000000 +0000
@@ -66,7 +66,7 @@ To add: #define SO_REUSEPORT 0x0200	/* A
 #define SO_TIMESTAMP		29
 #define SCM_TIMESTAMP		SO_TIMESTAMP
 
-#define SO_PEERSEC             30
+#define SO_PEERSEC		30
 
 /* Nast libc5 fixup - bletch */
 #if defined(__KERNEL__)
--- diff/include/asm-mips/spinlock.h	2003-10-09 09:47:17.000000000 +0100
+++ source/include/asm-mips/spinlock.h	2004-02-23 13:56:47.000000000 +0000
@@ -36,7 +36,7 @@ static inline void _raw_spin_lock(spinlo
 	unsigned int tmp;
 
 	__asm__ __volatile__(
-	".set\tnoreorder\t\t\t# spin_lock\n"
+	".set\tnoreorder\t\t\t# _raw_spin_lock\n"
 	"1:\tll\t%1, %2\n\t"
 	"bnez\t%1, 1b\n\t"
 	" li\t%1, 1\n\t"
@@ -52,7 +52,7 @@ static inline void _raw_spin_lock(spinlo
 static inline void _raw_spin_unlock(spinlock_t *lock)
 {
 	__asm__ __volatile__(
-	".set\tnoreorder\t\t\t# spin_unlock\n\t"
+	".set\tnoreorder\t\t\t# _raw_spin_unlock\n\t"
 	"sync\n\t"
 	"sw\t$0, %0\n\t"
 	".set\treorder"
@@ -66,7 +66,7 @@ static inline unsigned int _raw_spin_try
 	unsigned int temp, res;
 
 	__asm__ __volatile__(
-	".set\tnoreorder\t\t\t# spin_trylock\n\t"
+	".set\tnoreorder\t\t\t# _raw_spin_trylock\n\t"
 	"1:\tll\t%0, %3\n\t"
 	"ori\t%2, %0, 1\n\t"
 	"sc\t%2, %1\n\t"
@@ -91,9 +91,18 @@ static inline unsigned int _raw_spin_try
 
 typedef struct {
 	volatile unsigned int lock;
+#ifdef CONFIG_LOCKMETER
+	/* required for LOCKMETER since all bits in lock are used */
+	/* and we need this storage for CPU and lock INDEX        */
+	unsigned lockmeter_magic;
+#endif
 } rwlock_t;
 
+#ifdef CONFIG_LOCKMETER
+#define RW_LOCK_UNLOCKED (rwlock_t) { 0, 0 }
+#else
 #define RW_LOCK_UNLOCKED (rwlock_t) { 0 }
+#endif
 
 #define rwlock_init(x)  do { *(x) = RW_LOCK_UNLOCKED; } while(0)
 
@@ -104,7 +113,7 @@ static inline void _raw_read_lock(rwlock
 	unsigned int tmp;
 
 	__asm__ __volatile__(
-	".set\tnoreorder\t\t\t# read_lock\n"
+	".set\tnoreorder\t\t\t# _raw_read_lock\n"
 	"1:\tll\t%1, %2\n\t"
 	"bltz\t%1, 1b\n\t"
 	" addu\t%1, 1\n\t"
@@ -125,7 +134,7 @@ static inline void _raw_read_unlock(rwlo
 	unsigned int tmp;
 
 	__asm__ __volatile__(
-	".set\tnoreorder\t\t\t# read_unlock\n"
+	".set\tnoreorder\t\t\t# _raw_read_unlock\n"
 	"1:\tll\t%1, %2\n\t"
 	"sub\t%1, 1\n\t"
 	"sc\t%1, %0\n\t"
@@ -142,7 +151,7 @@ static inline void _raw_write_lock(rwloc
 	unsigned int tmp;
 
 	__asm__ __volatile__(
-	".set\tnoreorder\t\t\t# write_lock\n"
+	".set\tnoreorder\t\t\t# _raw_write_lock\n"
 	"1:\tll\t%1, %2\n\t"
 	"bnez\t%1, 1b\n\t"
 	" lui\t%1, 0x8000\n\t"
@@ -158,7 +167,7 @@ static inline void _raw_write_lock(rwloc
 static inline void _raw_write_unlock(rwlock_t *rw)
 {
 	__asm__ __volatile__(
-	".set\tnoreorder\t\t\t# write_unlock\n\t"
+	".set\tnoreorder\t\t\t# _raw_write_unlock\n\t"
 	"sync\n\t"
 	"sw\t$0, %0\n\t"
 	".set\treorder"
--- diff/include/asm-mips/stackframe.h	2003-08-20 14:16:33.000000000 +0100
+++ source/include/asm-mips/stackframe.h	2004-02-23 13:56:47.000000000 +0000
@@ -26,8 +26,10 @@
 
 		.macro	SAVE_TEMP
 		mfhi	v1
+#ifdef CONFIG_MIPS32
 		LONG_S	$8, PT_R8(sp)
 		LONG_S	$9, PT_R9(sp)
+#endif
 		LONG_S	v1, PT_HI(sp)
 		mflo	v1
 		LONG_S	$10, PT_R10(sp)
@@ -79,7 +81,7 @@
 		mfc0	\temp, CP0_CONTEXT
 		srl	\temp, 23
 		sll	\temp, 2
-		LONG_S	\stackp, kernelsp(temp)
+		LONG_S	\stackp, kernelsp(\temp)
 #endif
 #ifdef CONFIG_MIPS64
 		lw	\temp, TI_CPU(gp)
@@ -137,6 +139,10 @@
 		LONG_S	$6, PT_R6(sp)
 		MFC0	v1, CP0_EPC
 		LONG_S	$7, PT_R7(sp)
+#ifdef CONFIG_MIPS64
+		LONG_S	$8, PT_R8(sp)
+		LONG_S	$9, PT_R9(sp)
+#endif
 		LONG_S	v1, PT_EPC(sp)
 		LONG_S	$25, PT_R25(sp)
 		LONG_S	$28, PT_R28(sp)
@@ -163,8 +169,10 @@
 
 		.macro	RESTORE_TEMP
 		LONG_L	$24, PT_LO(sp)
+#ifdef CONFIG_MIPS32
 		LONG_L	$8, PT_R8(sp)
 		LONG_L	$9, PT_R9(sp)
+#endif
 		mtlo	$24
 		LONG_L	$24, PT_HI(sp)
 		LONG_L	$10, PT_R10(sp)
@@ -194,27 +202,32 @@
 		.macro	RESTORE_SOME
 		.set	push
 		.set	reorder
-		mfc0	t0, CP0_STATUS
-		.set	pop
-		ori	t0, 0x1f
-		xori	t0, 0x1f
-		mtc0	t0, CP0_STATUS
+		.set	noat
+		mfc0	a0, CP0_STATUS
+		ori	a0, 0x1f
+		xori	a0, 0x1f
+		mtc0	a0, CP0_STATUS
 		li	v1, 0xff00
-		and	t0, v1
+		and	a0, v1
 		LONG_L	v0, PT_STATUS(sp)
 		nor	v1, $0, v1
 		and	v0, v1
-		or	v0, t0
+		or	v0, a0
 		mtc0	v0, CP0_STATUS
 		LONG_L	$31, PT_R31(sp)
 		LONG_L	$28, PT_R28(sp)
 		LONG_L	$25, PT_R25(sp)
+#ifdef CONFIG_MIPS64
+		LONG_L	$8, PT_R8(sp)
+		LONG_L	$9, PT_R9(sp)
+#endif
 		LONG_L	$7,  PT_R7(sp)
 		LONG_L	$6,  PT_R6(sp)
 		LONG_L	$5,  PT_R5(sp)
 		LONG_L	$4,  PT_R4(sp)
 		LONG_L	$3,  PT_R3(sp)
 		LONG_L	$2,  PT_R2(sp)
+		.set	pop
 		.endm
 
 		.macro	RESTORE_SP_AND_RET
@@ -232,29 +245,34 @@
 		.macro	RESTORE_SOME
 		.set	push
 		.set	reorder
-		mfc0	t0, CP0_STATUS
-		.set	pop
-		ori	t0, 0x1f
-		xori	t0, 0x1f
-		mtc0	t0, CP0_STATUS
+		.set	noat
+		mfc0	a0, CP0_STATUS
+		ori	a0, 0x1f
+		xori	a0, 0x1f
+		mtc0	a0, CP0_STATUS
 		li	v1, 0xff00
-		and	t0, v1
+		and	a0, v1
 		LONG_L	v0, PT_STATUS(sp)
 		nor	v1, $0, v1
 		and	v0, v1
-		or	v0, t0
+		or	v0, a0
 		mtc0	v0, CP0_STATUS
 		LONG_L	v1, PT_EPC(sp)
 		MTC0	v1, CP0_EPC
 		LONG_L	$31, PT_R31(sp)
 		LONG_L	$28, PT_R28(sp)
 		LONG_L	$25, PT_R25(sp)
+#ifdef CONFIG_MIPS64
+		LONG_L	$8, PT_R8(sp)
+		LONG_L	$9, PT_R9(sp)
+#endif
 		LONG_L	$7,  PT_R7(sp)
 		LONG_L	$6,  PT_R6(sp)
 		LONG_L	$5,  PT_R5(sp)
 		LONG_L	$4,  PT_R4(sp)
 		LONG_L	$3,  PT_R3(sp)
 		LONG_L	$2,  PT_R2(sp)
+		.set	pop
 		.endm
 
 		.macro	RESTORE_SP_AND_RET
@@ -271,18 +289,18 @@
 		.endm
 
 		.macro	RESTORE_ALL
-		RESTORE_SOME
-		RESTORE_AT
 		RESTORE_TEMP
+		RESTORE_AT
 		RESTORE_STATIC
+		RESTORE_SOME
 		RESTORE_SP
 		.endm
 
 		.macro	RESTORE_ALL_AND_RET
-		RESTORE_SOME
-		RESTORE_AT
 		RESTORE_TEMP
+		RESTORE_AT
 		RESTORE_STATIC
+		RESTORE_SOME
 		RESTORE_SP_AND_RET
 		.endm
 
--- diff/include/asm-mips/system.h	2003-08-20 14:16:34.000000000 +0100
+++ source/include/asm-mips/system.h	2004-02-23 13:56:47.000000000 +0000
@@ -219,7 +219,7 @@ do {									\
 		"nop\n\t"			\
 		".set	pop"			\
 		: /* no output */		\
-		: "m" (*(int *)KSEG1)		\
+		: "m" (*(int *)CKSEG1)		\
 		: "memory")
 
 #define fast_wmb()	__sync()
@@ -237,8 +237,8 @@ do {									\
 
 #define wmb()		fast_wmb()
 #define rmb()		fast_rmb()
-#define mb()		wbflush();
-#define iob()		wbflush();
+#define mb()		wbflush()
+#define iob()		wbflush()
 
 #else /* !CONFIG_CPU_HAS_WB */
 
@@ -280,7 +280,7 @@ do { \
 	(last) = resume(prev, next, next->thread_info); \
 } while(0)
 
-static inline unsigned long xchg_u32(volatile int * m, unsigned int val)
+static inline unsigned long __xchg_u32(volatile int * m, unsigned int val)
 {
 	__u32 retval;
 
@@ -296,7 +296,9 @@ static inline unsigned long xchg_u32(vol
 		"sc\t%2, %1\n\t"
 		"beqzl\t%2, 1b\n\t"
 		" ll\t%0, %3\n\t"
+#ifdef CONFIG_SMP
 		"sync\n\t"
+#endif
 		".set\tpop"
 		: "=&r" (retval), "=m" (*m), "=&r" (dummy)
 		: "R" (*m), "Jr" (val)
@@ -314,7 +316,7 @@ static inline unsigned long xchg_u32(vol
 }
 
 #ifdef CONFIG_MIPS64
-static inline __u64 xchg_u64(volatile __u64 * m, __u64 long val)
+static inline __u64 __xchg_u64(volatile __u64 * m, __u64 val)
 {
 	__u64 retval;
 
@@ -330,7 +332,9 @@ static inline __u64 xchg_u64(volatile __
 		"scd\t%2, %1\n\t"
 		"beqzl\t%2, 1b\n\t"
 		" lld\t%0, %3\n\t"
+#ifdef CONFIG_SMP
 		"sync\n\t"
+#endif
 		".set\tpop"
 		: "=&r" (retval), "=m" (*m), "=&r" (dummy)
 		: "R" (*m), "Jr" (val)
@@ -348,28 +352,128 @@ static inline __u64 xchg_u64(volatile __
 }
 #else
 extern __u64 __xchg_u64_unsupported_on_32bit_kernels(volatile __u64 * m, __u64 val);
-#define xchg_u64 __xchg_u64_unsupported_on_32bit_kernels
+#define __xchg_u64 __xchg_u64_unsupported_on_32bit_kernels
 #endif
 
-#define xchg(ptr,x) ((__typeof__(*(ptr)))__xchg((unsigned long)(x),(ptr),sizeof(*(ptr))))
-#define tas(ptr) (xchg((ptr),1))
+/* This function doesn't exist, so you'll get a linker error
+   if something tries to do an invalid xchg().  */
+extern void __xchg_called_with_bad_pointer(void);
 
 static inline unsigned long __xchg(unsigned long x, volatile void * ptr, int size)
 {
 	switch (size) {
 		case 4:
-			return xchg_u32(ptr, x);
+			return __xchg_u32(ptr, x);
 		case 8:
-			return xchg_u64(ptr, x);
+			return __xchg_u64(ptr, x);
 	}
+	__xchg_called_with_bad_pointer();
 	return x;
 }
 
+#define xchg(ptr,x) ((__typeof__(*(ptr)))__xchg((unsigned long)(x),(ptr),sizeof(*(ptr))))
+#define tas(ptr) (xchg((ptr),1))
+
+#define __HAVE_ARCH_CMPXCHG 1
+
+static inline unsigned long __cmpxchg_u32(volatile int * m, unsigned long old,
+	unsigned long new)
+{
+	__u32 retval;
+
+#ifdef CONFIG_CPU_HAS_LLSC
+	__asm__ __volatile__(
+	"	.set	noat					\n"
+	"1:	ll	%0, %2			# __cmpxchg_u32	\n"
+	"	bne	%0, %z3, 2f				\n"
+	"	move	$1, %z4					\n"
+	"	sc	$1, %1					\n"
+	"	beqz	$1, 1b					\n"
+#ifdef CONFIG_SMP
+	"	sync						\n"
+#endif
+	"2:							\n"
+	"	.set	at					\n"
+	: "=&r" (retval), "=m" (*m)
+	: "R" (*m), "Jr" (old), "Jr" (new)
+	: "memory");
+#else
+	unsigned long flags;
+
+	local_irq_save(flags);
+	retval = *m;
+	if (retval == old)
+		*m = new;
+	local_irq_restore(flags);	/* implies memory barrier  */
+#endif
+
+	return retval;
+}
+
+#ifdef CONFIG_MIPS64
+static inline unsigned long __cmpxchg_u64(volatile int * m, unsigned long old,
+	unsigned long new)
+{
+	__u64 retval;
+
+#ifdef CONFIG_CPU_HAS_LLDSCD
+	__asm__ __volatile__(
+	"	.set	noat					\n"
+	"1:	lld	%0, %2			# __cmpxchg_u64	\n"
+	"	bne	%0, %z3, 2f				\n"
+	"	move	$1, %z4					\n"
+	"	scd	$1, %1					\n"
+	"	beqz	$1, 1b					\n"
+#ifdef CONFIG_SMP
+	"	sync						\n"
+#endif
+	"2:							\n"
+	"	.set	at					\n"
+	: "=&r" (retval), "=m" (*m)
+	: "R" (*m), "Jr" (old), "Jr" (new)
+	: "memory");
+#else
+	unsigned long flags;
+
+	local_irq_save(flags);
+	retval = *m;
+	if (retval == old)
+		*m = new;
+	local_irq_restore(flags);	/* implies memory barrier  */
+#endif
+
+	return retval;
+}
+#else
+extern unsigned long __cmpxchg_u64_unsupported_on_32bit_kernels(
+	volatile int * m, unsigned long old, unsigned long new);
+#define __cmpxchg_u64 __cmpxchg_u64_unsupported_on_32bit_kernels
+#endif
+
+/* This function doesn't exist, so you'll get a linker error
+   if something tries to do an invalid cmpxchg().  */
+extern void __cmpxchg_called_with_bad_pointer(void);
+
+static inline unsigned long __cmpxchg(volatile void * ptr, unsigned long old,
+	unsigned long new, int size)
+{
+	switch (size) {
+	case 4:
+		return __cmpxchg_u32(ptr, old, new);
+	case 8:
+		return __cmpxchg_u64(ptr, old, new);
+	}
+	__cmpxchg_called_with_bad_pointer();
+	return old;
+}
+
+#define cmpxchg(ptr,old,new) ((__typeof__(*(ptr)))__cmpxchg((ptr), (unsigned long)(old), (unsigned long)(new),sizeof(*(ptr))))
+
 extern void *set_except_vector(int n, void *addr);
 extern void per_cpu_trap_init(void);
 
-extern void __die(const char *, struct pt_regs *, const char *file,
-	const char *func, unsigned long line) __attribute__((noreturn));
+extern NORET_TYPE void __die(const char *, struct pt_regs *, const char *file,
+	const char *func, unsigned long line);
 extern void __die_if_kernel(const char *, struct pt_regs *, const char *file,
 	const char *func, unsigned long line);
 
@@ -386,4 +490,16 @@ static __inline__ int con_is_present(voi
 	return serial_console ? 0 : 1;
 }
 
+/*
+ * Taken from include/asm-ia64/system.h; prevents deadlock on SMP
+ * systems.
+ */
+#define prepare_arch_switch(rq, next)		\
+do {						\
+	spin_lock(&(next)->switch_lock);	\
+	spin_unlock(&(rq)->lock);		\
+} while (0)
+#define finish_arch_switch(rq, prev)	spin_unlock_irq(&(prev)->switch_lock)
+#define task_running(rq, p) 		((rq)->curr == (p) || spin_is_locked(&(p)->switch_lock))
+
 #endif /* _ASM_SYSTEM_H */
--- diff/include/asm-mips/termios.h	2003-08-20 14:16:34.000000000 +0100
+++ source/include/asm-mips/termios.h	2004-02-23 13:56:47.000000000 +0000
@@ -59,6 +59,8 @@ struct termio {
 };
 
 #ifdef __KERNEL__
+#include <linux/module.h>
+
 /*
  *	intr=^C		quit=^\		erase=del	kill=^U
  *	vmin=\1		vtime=\0	eol2=\0		swtc=\0
--- diff/include/asm-mips/thread_info.h	2003-08-20 14:16:34.000000000 +0100
+++ source/include/asm-mips/thread_info.h	2004-02-23 13:56:47.000000000 +0000
@@ -36,8 +36,6 @@ struct thread_info {
 	struct restart_block	restart_block;
 };
 
-#define PREEMPT_ACTIVE		0x4000000
-
 /*
  * macros/functions for gaining access to the thread information structure
  *
@@ -64,22 +62,44 @@ register struct thread_info *__current_t
 #define current_thread_info()  __current_thread_info
 
 /* thread information allocation */
-#ifdef CONFIG_MIPS32
+#if defined(CONFIG_PAGE_SIZE_4KB) && defined(CONFIG_MIPS32)
 #define THREAD_SIZE_ORDER (1)
 #endif
-#ifdef CONFIG_MIPS64
-#define THREAD_SIZE_ORDER (1)
+#if defined(CONFIG_PAGE_SIZE_4KB) && defined(CONFIG_MIPS64)
+#define THREAD_SIZE_ORDER (2)
 #endif
+#ifdef CONFIG_PAGE_SIZE_16KB
+#define THREAD_SIZE_ORDER (0)
+#endif
+#ifdef CONFIG_PAGE_SIZE_64KB
+#define THREAD_SIZE_ORDER (0)
+#endif
+
 #define THREAD_SIZE (PAGE_SIZE << THREAD_SIZE_ORDER)
 #define THREAD_MASK (THREAD_SIZE - 1UL)
-#define alloc_thread_info(task) \
-	((struct thread_info *)kmalloc(THREAD_SIZE, GFP_KERNEL))
+
+#ifdef CONFIG_DEBUG_STACK_USAGE
+#define alloc_thread_info(tsk)					\
+({								\
+	struct thread_info *ret;				\
+								\
+	ret = kmalloc(THREAD_SIZE, GFP_KERNEL);			\
+	if (ret)						\
+		memset(ret, 0, THREAD_SIZE);			\
+	ret;							\
+})
+#else
+#define alloc_thread_info(tsk) kmalloc(THREAD_SIZE, GFP_KERNEL)
+#endif
+
 #define free_thread_info(info) kfree(info)
 #define get_thread_info(ti) get_task_struct((ti)->task)
 #define put_thread_info(ti) put_task_struct((ti)->task)
 
 #endif /* !__ASSEMBLY__ */
 
+#define PREEMPT_ACTIVE		0x4000000
+
 /*
  * thread information flags
  * - these are process state flags that various assembly files may need to
--- diff/include/asm-mips/time.h	2003-08-20 14:16:34.000000000 +0100
+++ source/include/asm-mips/time.h	2004-02-23 13:56:47.000000000 +0000
@@ -33,6 +33,21 @@ extern int (*rtc_set_time)(unsigned long
 extern int (*rtc_set_mmss)(unsigned long);
 
 /*
+ * Timer interrupt functions.
+ * mips_timer_state is needed for high precision timer calibration.
+ * mips_timer_ack may be NULL if the interrupt is self-recoverable.
+ */
+extern int (*mips_timer_state)(void);
+extern void (*mips_timer_ack)(void);
+
+/*
+ * High precision timer functions.
+ * If mips_hpt_read is NULL, an R4k-compatible timer setup is attempted.
+ */
+extern unsigned int (*mips_hpt_read)(void);
+extern void (*mips_hpt_init)(unsigned int);
+
+/*
  * to_tm() converts system time back to (year, mon, day, hour, min, sec).
  * It is intended to help implement rtc_set_time() functions.
  * Copied from PPC implementation.
@@ -46,11 +61,6 @@ extern void to_tm(unsigned long tim, str
  */
 extern unsigned long (*do_gettimeoffset)(void);
 
-extern unsigned long null_gettimeoffset(void);
-extern unsigned long fixed_rate_gettimeoffset(void);
-extern unsigned long calibrate_div32_gettimeoffset(void);
-extern unsigned long calibrate_div64_gettimeoffset(void);
-
 /*
  * high-level timer interrupt routines.
  */
@@ -77,9 +87,10 @@ extern void (*board_time_init)(void);
 extern void (*board_timer_setup)(struct irqaction *irq);
 
 /*
- * mips_counter_frequency - must be set if you intend to use
- * counter as timer interrupt source or use fixed_rate_gettimeoffset.
+ * mips_hpt_frequency - must be set if you intend to use an R4k-compatible
+ * counter as a timer interrupt source; otherwise it can be set up
+ * automagically with an aid of mips_timer_state.
  */
-extern unsigned int mips_counter_frequency;
+extern unsigned int mips_hpt_frequency;
 
 #endif /* _ASM_TIME_H */
--- diff/include/asm-mips/timex.h	2003-08-20 14:16:34.000000000 +0100
+++ source/include/asm-mips/timex.h	2004-02-23 13:56:47.000000000 +0000
@@ -8,7 +8,6 @@
 #ifndef _ASM_TIMEX_H
 #define _ASM_TIMEX_H
 
-#include <linux/config.h>
 #include <asm/mipsregs.h>
 
 /*
@@ -16,25 +15,23 @@
  * The value should be defined as accurate as possible or under certain
  * circumstances Linux timekeeping might become inaccurate or fail.
  *
- * For IP22 we cheat and pretend to have a 1MHz timer whic isn't strictly
- * true - we only use the 8259 timer to calibrate the actual interrupt
- * timer, so after all it's the master clock source of the system.
+ * For many system the exact clockrate of the timer isn't known but due to
+ * the way this value is used we can get away with a wrong value as long
+ * as this value is:
+ *
+ *  - a multiple of HZ
+ *  - a divisor of the actual rate
+ *
+ * 500000 is a good such cheat value.
  *
  * The obscure number 1193182 is the same as used by the original i8254
  * time in legacy PC hardware; the chip unfortunately also found in a
- * bunch of MIPS systems.
+ * bunch of MIPS systems.  The last remaining user of the i8254 for the
+ * timer interrupt is the RM200; it's a very standard system so there is
+ * no reason to make this a separate architecture.
  */
-#ifdef CONFIG_ACER_PICA_61
-#define CLOCK_TICK_RATE		1193182
-#elif defined(CONFIG_MIPS_MAGNUM_4000)
-#define CLOCK_TICK_RATE		1193182
-#elif defined(CONFIG_OLIVETTI_M700)
-#define CLOCK_TICK_RATE		1193182
-#elif defined(CONFIG_SGI_IP22)
-#define CLOCK_TICK_RATE		1000000
-#elif defined(CONFIG_SNI_RM200_PCI)
-#define CLOCK_TICK_RATE		1193182
-#endif
+
+#include <timex.h>
 
 /*
  * Standard way to access the cycle counter.
--- diff/include/asm-mips/tlb.h	2003-07-08 09:55:19.000000000 +0100
+++ source/include/asm-mips/tlb.h	2004-02-23 13:56:47.000000000 +0000
@@ -2,9 +2,14 @@
 #define __ASM_TLB_H
 
 /*
- * MIPS doesn't need any special per-pte or per-vma handling..
+ * MIPS doesn't need any special per-pte or per-vma handling, except
+ * we need to flush cache for area to be unmapped.
  */
-#define tlb_start_vma(tlb, vma) do { } while (0)
+#define tlb_start_vma(tlb, vma) 				\
+	do {							\
+		if (!tlb->fullmm)				\
+			flush_cache_range(vma, vma->vm_start, vma->vm_end); \
+	}  while (0)
 #define tlb_end_vma(tlb, vma) do { } while (0)
 #define __tlb_remove_tlb_entry(tlb, ptep, address) do { } while (0)
 
--- diff/include/asm-mips/topology.h	2003-08-20 14:16:34.000000000 +0100
+++ source/include/asm-mips/topology.h	2004-02-23 13:56:47.000000000 +0000
@@ -1,7 +1,9 @@
 #ifndef __ASM_TOPOLOGY_H
 #define __ASM_TOPOLOGY_H
 
-#if CONFIG_SGI_IP27
+#include <linux/config.h>
+
+#ifdef CONFIG_SGI_IP27
 
 #include <asm/mmzone.h>
 
--- diff/include/asm-mips/tx4927/toshiba_rbtx4927.h	2003-07-08 09:55:19.000000000 +0100
+++ source/include/asm-mips/tx4927/toshiba_rbtx4927.h	2004-02-23 13:56:47.000000000 +0000
@@ -27,6 +27,7 @@
 #ifndef __ASM_TX4927_TOSHIBA_RBTX4927_H
 #define __ASM_TX4927_TOSHIBA_RBTX4927_H
 
+#include <linux/config.h>
 #include <asm/tx4927/tx4927.h>
 #include <asm/tx4927/tx4927_mips.h>
 #ifdef CONFIG_PCI
--- diff/include/asm-mips/tx4927/tx4927_pci.h	2003-07-08 09:55:19.000000000 +0100
+++ source/include/asm-mips/tx4927/tx4927_pci.h	2004-02-23 13:56:47.000000000 +0000
@@ -21,7 +21,7 @@
 #define TX4927_CCFG_REG         0xff1fe000
 #define TX4927_IRC_REG          0xff1ff600
 #define TX4927_CE3      0x17f00000      /* 1M */
-#define TX4927_PCIRESET_ADDR    0x1c00f006
+#define TX4927_PCIRESET_ADDR    0xbc00f006
 #define TX4927_PCI_CLK_ADDR     (KSEG1 + TX4927_CE3 + 0x00040020)
 
 #define TX4927_IMSTAT_ADDR(n)   (KSEG1 + TX4927_CE3 + 0x0004001a + (n))
--- diff/include/asm-mips/types.h	2003-08-20 14:16:34.000000000 +0100
+++ source/include/asm-mips/types.h	2004-02-23 13:56:47.000000000 +0000
@@ -9,16 +9,9 @@
 #ifndef _ASM_TYPES_H
 #define _ASM_TYPES_H
 
-#include <linux/config.h>
-
 #ifndef __ASSEMBLY__
 
-#ifdef CONFIG_MIPS32
 typedef unsigned short umode_t;
-#endif
-#ifdef CONFIG_MIPS64
-typedef unsigned int umode_t;
-#endif
 
 /*
  * __xx is ok: it doesn't pollute the POSIX namespace. Use these in the
@@ -59,6 +52,8 @@ typedef unsigned long long __u64;
 
 #ifndef __ASSEMBLY__
 
+#include <linux/config.h>
+
 typedef __signed char s8;
 typedef unsigned char u8;
 
--- diff/include/asm-mips/uaccess.h	2003-08-20 14:16:34.000000000 +0100
+++ source/include/asm-mips/uaccess.h	2004-02-23 13:56:47.000000000 +0000
@@ -3,12 +3,14 @@
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  *
- * Copyright (C) 1996, 1997, 1998, 1999, 2000 by Ralf Baechle
+ * Copyright (C) 1996, 1997, 1998, 1999, 2000, 03, 04 by Ralf Baechle
  * Copyright (C) 1999, 2000 Silicon Graphics, Inc.
  */
 #ifndef _ASM_UACCESS_H
 #define _ASM_UACCESS_H
 
+#include <linux/config.h>
+#include <linux/compiler.h>
 #include <linux/errno.h>
 #include <linux/thread_info.h>
 
@@ -20,47 +22,43 @@
  * For historical reasons, these macros are grossly misnamed.
  */
 #ifdef CONFIG_MIPS32
+
+#define __UA_LIMIT	0x80000000UL
+
 #define __UA_ADDR	".word"
 #define __UA_LA		"la"
 #define __UA_ADDU	"addu"
-
-#define KERNEL_DS	((mm_segment_t) { (unsigned long) 0L })
-#define USER_DS		((mm_segment_t) { (unsigned long) -1L })
-
-#define VERIFY_READ    0
-#define VERIFY_WRITE   1
-
-#define __access_ok(addr, size, mask)					\
-	(((signed long)((mask)&(addr | ((addr) + (size)) | __ua_size(size)))) >= 0)
- 
-#define __access_mask ((long)(get_fs().seg))
- 
-#define access_ok(type, addr, size)					\
-	__access_ok(((unsigned long)(addr)),(size),__access_mask)
+#define __UA_t0		"$8"
+#define __UA_t1		"$9"
 
 #endif /* CONFIG_MIPS32 */
 
 #ifdef CONFIG_MIPS64
+
+#define __UA_LIMIT	(- TASK_SIZE)
+
 #define __UA_ADDR	".dword"
 #define __UA_LA		"dla"
 #define __UA_ADDU	"daddu"
+#define __UA_t0		"$12"
+#define __UA_t1		"$13"
+
+#endif /* CONFIG_MIPS64 */
+
+/*
+ * USER_DS is a bitmask that has the bits set that may not be set in a valid
+ * userspace address.  Note that we limit 32-bit userspace to 0x7fff8000 but
+ * the arithmetic we're doing only works if the limit is a power of two, so
+ * we use 0x80000000 here on 32-bit kernels.  If a process passes an invalid
+ * address in this range it's the process's problem, not ours :-)
+ */
 
 #define KERNEL_DS	((mm_segment_t) { 0UL })
-#define USER_DS		((mm_segment_t) { -TASK_SIZE })
+#define USER_DS		((mm_segment_t) { __UA_LIMIT })
 
 #define VERIFY_READ    0
 #define VERIFY_WRITE   1
 
-#define __access_ok(addr, size, mask)					\
-	(((signed long)((mask) & ((addr) | ((addr) + (size)) | __ua_size(size)))) == 0)
-
-#define __access_mask get_fs().seg
-
-#define access_ok(type, addr, size)					\
-	__access_ok((unsigned long)(addr), (size), __access_mask)
-
-#endif /* CONFIG_MIPS64 */
-
 #define get_ds()	(KERNEL_DS)
 #define get_fs()	(current_thread_info()->addr_limit)
 #define set_fs(x)	(current_thread_info()->addr_limit = (x))
@@ -84,35 +82,137 @@
 #define __ua_size(size)							\
 	((__builtin_constant_p(size) && (signed long) (size) > 0) ? 0 : (size))
 
+/*
+ * access_ok: - Checks if a user space pointer is valid
+ * @type: Type of access: %VERIFY_READ or %VERIFY_WRITE.  Note that
+ *        %VERIFY_WRITE is a superset of %VERIFY_READ - if it is safe
+ *        to write to a block, it is always safe to read from it.
+ * @addr: User space pointer to start of block to check
+ * @size: Size of block to check
+ *
+ * Context: User context only.  This function may sleep.
+ *
+ * Checks if a pointer to a block of memory in user space is valid.
+ *
+ * Returns true (nonzero) if the memory block may be valid, false (zero)
+ * if it is definitely invalid.
+ *
+ * Note that, depending on architecture, this function probably just
+ * checks that the pointer is in the user space range - after calling
+ * this function, memory access functions may still return -EFAULT.
+ */
+
+#define __access_mask get_fs().seg
+
+#define __access_ok(addr, size, mask)					\
+	(((signed long)((mask) & ((addr) | ((addr) + (size)) | __ua_size(size)))) == 0)
+
+#define access_ok(type, addr, size)					\
+	likely(__access_ok((unsigned long)(addr), (size),__access_mask))
+
+/*
+ * verify_area: - Obsolete, use access_ok()
+ * @type: Type of access: %VERIFY_READ or %VERIFY_WRITE
+ * @addr: User space pointer to start of block to check
+ * @size: Size of block to check
+ *
+ * Context: User context only.  This function may sleep.
+ *
+ * This function has been replaced by access_ok().
+ *
+ * Checks if a pointer to a block of memory in user space is valid.
+ *
+ * Returns zero if the memory block may be valid, -EFAULT
+ * if it is definitely invalid.
+ *
+ * See access_ok() for more details.
+ */
 static inline int verify_area(int type, const void * addr, unsigned long size)
 {
 	return access_ok(type, addr, size) ? 0 : -EFAULT;
 }
 
 /*
- * Uh, these should become the main single-value transfer routines ...
- * They automatically use the right size if we just have the right
- * pointer type ...
- *
- * As MIPS uses the same address space for kernel and user data, we
- * can just do these as direct assignments.
- *
- * Careful to not
- * (a) re-use the arguments for side effects (sizeof is ok)
- * (b) require any knowledge of processes at this stage
+ * put_user: - Write a simple value into user space.
+ * @x:   Value to copy to user space.
+ * @ptr: Destination address, in user space.
+ *
+ * Context: User context only.  This function may sleep.
+ *
+ * This macro copies a single simple value from kernel space to user
+ * space.  It supports simple types like char and int, but not larger
+ * data types like structures or arrays.
+ *
+ * @ptr must have pointer-to-simple-variable type, and @x must be assignable
+ * to the result of dereferencing @ptr.
+ *
+ * Returns zero on success, or -EFAULT on error.
  */
 #define put_user(x,ptr)	\
 	__put_user_check((__typeof__(*(ptr)))(x),(ptr),sizeof(*(ptr)))
+
+/*
+ * get_user: - Get a simple variable from user space.
+ * @x:   Variable to store result.
+ * @ptr: Source address, in user space.
+ *
+ * Context: User context only.  This function may sleep.
+ *
+ * This macro copies a single simple variable from user space to kernel
+ * space.  It supports simple types like char and int, but not larger
+ * data types like structures or arrays.
+ *
+ * @ptr must have pointer-to-simple-variable type, and the result of
+ * dereferencing @ptr must be assignable to @x without a cast.
+ *
+ * Returns zero on success, or -EFAULT on error.
+ * On error, the variable @x is set to zero.
+ */
 #define get_user(x,ptr) \
 	__get_user_check((__typeof__(*(ptr)))(x),(ptr),sizeof(*(ptr)))
 
 /*
- * The "__xxx" versions do not do address space checking, useful when
- * doing multiple accesses to the same area (the user has to do the
- * checks by hand with "access_ok()")
+ * __put_user: - Write a simple value into user space, with less checking.
+ * @x:   Value to copy to user space.
+ * @ptr: Destination address, in user space.
+ *
+ * Context: User context only.  This function may sleep.
+ *
+ * This macro copies a single simple value from kernel space to user
+ * space.  It supports simple types like char and int, but not larger
+ * data types like structures or arrays.
+ *
+ * @ptr must have pointer-to-simple-variable type, and @x must be assignable
+ * to the result of dereferencing @ptr.
+ *
+ * Caller must check the pointer with access_ok() before calling this
+ * function.
+ *
+ * Returns zero on success, or -EFAULT on error.
  */
 #define __put_user(x,ptr) \
 	__put_user_nocheck((__typeof__(*(ptr)))(x),(ptr),sizeof(*(ptr)))
+
+/*
+ * __get_user: - Get a simple variable from user space, with less checking.
+ * @x:   Variable to store result.
+ * @ptr: Source address, in user space.
+ *
+ * Context: User context only.  This function may sleep.
+ *
+ * This macro copies a single simple variable from user space to kernel
+ * space.  It supports simple types like char and int, but not larger
+ * data types like structures or arrays.
+ *
+ * @ptr must have pointer-to-simple-variable type, and the result of
+ * dereferencing @ptr must be assignable to @x without a cast.
+ *
+ * Caller must check the pointer with access_ok() before calling this
+ * function.
+ *
+ * Returns zero on success, or -EFAULT on error.
+ * On error, the variable @x is set to zero.
+ */
 #define __get_user(x,ptr) \
 	__get_user_nocheck((__typeof__(*(ptr)))(x),(ptr),sizeof(*(ptr)))
 
@@ -134,6 +234,7 @@ struct __large_struct { unsigned long bu
 	long __gu_err;						\
 	__typeof(*(ptr)) __gu_val;				\
 	long __gu_addr;						\
+	might_sleep();						\
 	__asm__("":"=r" (__gu_val));				\
 	__gu_addr = (long) (ptr);				\
 	__asm__("":"=r" (__gu_err));				\
@@ -146,65 +247,66 @@ struct __large_struct { unsigned long bu
 	} x = (__typeof__(*(ptr))) __gu_val; __gu_err;		\
 })
 
-#define __get_user_check(x,ptr,size)				\
-({								\
-	long __gu_err;						\
-	__typeof__(*(ptr)) __gu_val;				\
-	long __gu_addr;						\
-	__asm__("":"=r" (__gu_val));				\
-	__gu_addr = (long) (ptr);				\
-	__asm__("":"=r" (__gu_err));				\
-	if (__access_ok(__gu_addr,size,__access_mask)) {	\
-		switch (size) {					\
-		case 1: __get_user_asm("lb"); break;		\
-		case 2: __get_user_asm("lh"); break;		\
-		case 4: __get_user_asm("lw"); break;		\
-		case 8: __GET_USER_DW; break;			\
-		default: __get_user_unknown(); break;		\
-		}						\
-	} x = (__typeof__(*(ptr))) __gu_val; __gu_err;		\
+#define __get_user_check(x,ptr,size)					\
+({									\
+	long __gu_err;							\
+	__typeof__(*(ptr)) __gu_val;					\
+	long __gu_addr;							\
+	might_sleep();							\
+	__asm__("":"=r" (__gu_val));					\
+	__gu_addr = (long) (ptr);					\
+	__asm__("":"=r" (__gu_err));					\
+	if (access_ok(VERIFY_READ,__gu_addr,size)) {			\
+		switch (size) {						\
+		case 1: __get_user_asm("lb"); break;			\
+		case 2: __get_user_asm("lh"); break;			\
+		case 4: __get_user_asm("lw"); break;			\
+		case 8: __GET_USER_DW; break;				\
+		default: __get_user_unknown(); break;			\
+		}							\
+	} x = (__typeof__(*(ptr))) __gu_val; __gu_err;			\
 })
 
-#define __get_user_asm(insn)					\
-({								\
-	__asm__ __volatile__(					\
-	"1:\t" insn "\t%1,%2\n\t"				\
-	"move\t%0,$0\n"						\
-	"2:\n\t"						\
-	".section\t.fixup,\"ax\"\n"				\
-	"3:\tli\t%0,%3\n\t"					\
-	"move\t%1,$0\n\t"					\
-	"j\t2b\n\t"						\
-	".previous\n\t"						\
-	".section\t__ex_table,\"a\"\n\t"			\
-	__UA_ADDR "\t1b,3b\n\t"					\
-	".previous"						\
-	:"=r" (__gu_err), "=r" (__gu_val)			\
-	:"o" (__m(__gu_addr)), "i" (-EFAULT));			\
+#define __get_user_asm(insn)						\
+({									\
+	__asm__ __volatile__(						\
+	"1:\t" insn "\t%1,%2\n\t"					\
+	"move\t%0,$0\n"							\
+	"2:\n\t"							\
+	".section\t.fixup,\"ax\"\n"					\
+	"3:\tli\t%0,%3\n\t"						\
+	"move\t%1,$0\n\t"						\
+	"j\t2b\n\t"							\
+	".previous\n\t"							\
+	".section\t__ex_table,\"a\"\n\t"				\
+	__UA_ADDR "\t1b,3b\n\t"						\
+	".previous"							\
+	:"=r" (__gu_err), "=r" (__gu_val)				\
+	:"o" (__m(__gu_addr)), "i" (-EFAULT));				\
 })
 
 /*
  * Get a long long 64 using 32 bit registers.
  */
-#define __get_user_asm_ll32					\
-({								\
-	__asm__ __volatile__(					\
-	"1:\tlw\t%1,%2\n"					\
-	"2:\tlw\t%D1,%3\n\t"					\
-	"move\t%0,$0\n"						\
-	"3:\t.section\t.fixup,\"ax\"\n"				\
-	"4:\tli\t%0,%4\n\t"					\
-	"move\t%1,$0\n\t"					\
-	"move\t%D1,$0\n\t"					\
-	"j\t3b\n\t"						\
-	".previous\n\t"						\
-	".section\t__ex_table,\"a\"\n\t"			\
-	__UA_ADDR "\t1b,4b\n\t"					\
-	__UA_ADDR "\t2b,4b\n\t"					\
-	".previous"						\
-	:"=r" (__gu_err), "=&r" (__gu_val)			\
-	:"o" (__m(__gu_addr)), "o" (__m(__gu_addr + 4)),	\
-	 "i" (-EFAULT));					\
+#define __get_user_asm_ll32						\
+({									\
+	__asm__ __volatile__(						\
+	"1:\tlw\t%1,%2\n"						\
+	"2:\tlw\t%D1,%3\n\t"						\
+	"move\t%0,$0\n"							\
+	"3:\t.section\t.fixup,\"ax\"\n"					\
+	"4:\tli\t%0,%4\n\t"						\
+	"move\t%1,$0\n\t"						\
+	"move\t%D1,$0\n\t"						\
+	"j\t3b\n\t"							\
+	".previous\n\t"							\
+	".section\t__ex_table,\"a\"\n\t"				\
+	__UA_ADDR "\t1b,4b\n\t"						\
+	__UA_ADDR "\t2b,4b\n\t"						\
+	".previous"							\
+	:"=r" (__gu_err), "=&r" (__gu_val)				\
+	:"o" (__m(__gu_addr)), "o" (__m(__gu_addr + 4)),		\
+	 "i" (-EFAULT));						\
 })
 
 extern void __get_user_unknown(void);
@@ -219,59 +321,61 @@ extern void __get_user_unknown(void);
 #define __PUT_USER_DW __put_user_asm_ll32
 #endif
 
-#define __put_user_nocheck(x,ptr,size)				\
-({								\
-	long __pu_err;						\
-	__typeof__(*(ptr)) __pu_val;				\
-	long __pu_addr;						\
-	__pu_val = (x);						\
-	__pu_addr = (long) (ptr);				\
-	__asm__("":"=r" (__pu_err));				\
-	switch (size) {						\
-	case 1: __put_user_asm("sb"); break;			\
-	case 2: __put_user_asm("sh"); break;			\
-	case 4: __put_user_asm("sw"); break;			\
-	case 8: __PUT_USER_DW; break;				\
-	default: __put_user_unknown(); break;			\
-	}							\
-	__pu_err;						\
+#define __put_user_nocheck(x,ptr,size)					\
+({									\
+	long __pu_err;							\
+	__typeof__(*(ptr)) __pu_val;					\
+	long __pu_addr;							\
+	might_sleep();							\
+	__pu_val = (x);							\
+	__pu_addr = (long) (ptr);					\
+	__asm__("":"=r" (__pu_err));					\
+	switch (size) {							\
+	case 1: __put_user_asm("sb"); break;				\
+	case 2: __put_user_asm("sh"); break;				\
+	case 4: __put_user_asm("sw"); break;				\
+	case 8: __PUT_USER_DW; break;					\
+	default: __put_user_unknown(); break;				\
+	}								\
+	__pu_err;							\
 })
 
-#define __put_user_check(x,ptr,size)				\
-({								\
-	long __pu_err;						\
-	__typeof__(*(ptr)) __pu_val;				\
-	long __pu_addr;						\
-	__pu_val = (x);						\
-	__pu_addr = (long) (ptr);				\
-	__asm__("":"=r" (__pu_err));				\
-	if (__access_ok(__pu_addr,size,__access_mask)) {	\
-		switch (size) {					\
-		case 1: __put_user_asm("sb"); break;		\
-		case 2: __put_user_asm("sh"); break;		\
-		case 4: __put_user_asm("sw"); break;		\
-		case 8: __PUT_USER_DW; break;			\
-		default: __put_user_unknown(); break;		\
-		}						\
-	}							\
-	__pu_err;						\
+#define __put_user_check(x,ptr,size)					\
+({									\
+	long __pu_err;							\
+	__typeof__(*(ptr)) __pu_val;					\
+	long __pu_addr;							\
+	might_sleep();							\
+	__pu_val = (x);							\
+	__pu_addr = (long) (ptr);					\
+	__asm__("":"=r" (__pu_err));					\
+	if (access_ok(VERIFY_WRITE, __pu_addr, size)) {			\
+		switch (size) {						\
+		case 1: __put_user_asm("sb"); break;			\
+		case 2: __put_user_asm("sh"); break;			\
+		case 4: __put_user_asm("sw"); break;			\
+		case 8: __PUT_USER_DW; break;				\
+		default: __put_user_unknown(); break;			\
+		}							\
+	}								\
+	__pu_err;							\
 })
 
-#define __put_user_asm(insn)					\
-({								\
-	__asm__ __volatile__(					\
-	"1:\t" insn "\t%z1, %2\t\t\t# __put_user_asm\n\t"	\
-	"move\t%0, $0\n"					\
-	"2:\n\t"						\
-	".section\t.fixup,\"ax\"\n"				\
-	"3:\tli\t%0,%3\n\t"					\
-	"j\t2b\n\t"						\
-	".previous\n\t"						\
-	".section\t__ex_table,\"a\"\n\t"			\
-	__UA_ADDR "\t1b,3b\n\t"					\
-	".previous"						\
-	:"=r" (__pu_err)					\
-	:"Jr" (__pu_val), "o" (__m(__pu_addr)), "i" (-EFAULT));	\
+#define __put_user_asm(insn)						\
+({									\
+	__asm__ __volatile__(						\
+	"1:\t" insn "\t%z1, %2\t\t\t# __put_user_asm\n\t"		\
+	"move\t%0, $0\n"						\
+	"2:\n\t"							\
+	".section\t.fixup,\"ax\"\n"					\
+	"3:\tli\t%0,%3\n\t"						\
+	"j\t2b\n\t"							\
+	".previous\n\t"							\
+	".section\t__ex_table,\"a\"\n\t"				\
+	__UA_ADDR "\t1b,3b\n\t"						\
+	".previous"							\
+	:"=r" (__pu_err)						\
+	:"Jr" (__pu_val), "o" (__m(__pu_addr)), "i" (-EFAULT));		\
 })
 
 #define __put_user_asm_ll32						\
@@ -331,12 +435,27 @@ extern size_t __copy_user(void *__to, co
 	__cu_len_r;							\
 })
 
+/*
+ * __copy_to_user: - Copy a block of data into user space, with less checking.
+ * @to:   Destination address, in user space.
+ * @from: Source address, in kernel space.
+ * @n:    Number of bytes to copy.
+ *
+ * Context: User context only.  This function may sleep.
+ *
+ * Copy data from kernel space to user space.  Caller must check
+ * the specified block with access_ok() before calling this function.
+ *
+ * Returns number of bytes that could not be copied.
+ * On success, this will be zero.
+ */
 #define __copy_to_user(to,from,n)					\
 ({									\
 	void *__cu_to;							\
 	const void *__cu_from;						\
 	long __cu_len;							\
 									\
+	might_sleep();							\
 	__cu_to = (to);							\
 	__cu_from = (from);						\
 	__cu_len = (n);							\
@@ -344,12 +463,26 @@ extern size_t __copy_user(void *__to, co
 	__cu_len;							\
 })
 
+/*
+ * copy_to_user: - Copy a block of data into user space.
+ * @to:   Destination address, in user space.
+ * @from: Source address, in kernel space.
+ * @n:    Number of bytes to copy.
+ *
+ * Context: User context only.  This function may sleep.
+ *
+ * Copy data from kernel space to user space.
+ *
+ * Returns number of bytes that could not be copied.
+ * On success, this will be zero.
+ */
 #define copy_to_user(to,from,n)						\
 ({									\
 	void *__cu_to;							\
 	const void *__cu_from;						\
 	long __cu_len;							\
 									\
+	might_sleep();							\
 	__cu_to = (to);							\
 	__cu_from = (from);						\
 	__cu_len = (n);							\
@@ -383,12 +516,29 @@ extern size_t __copy_user(void *__to, co
 	__cu_len_r;							\
 })
 
+/*
+ * __copy_from_user: - Copy a block of data from user space, with less checking. * @to:   Destination address, in kernel space.
+ * @from: Source address, in user space.
+ * @n:    Number of bytes to copy.
+ *
+ * Context: User context only.  This function may sleep.
+ *
+ * Copy data from user space to kernel space.  Caller must check
+ * the specified block with access_ok() before calling this function.
+ *
+ * Returns number of bytes that could not be copied.
+ * On success, this will be zero.
+ *
+ * If some data could not be copied, this function will pad the copied
+ * data to the requested size using zero bytes.
+ */
 #define __copy_from_user(to,from,n)					\
 ({									\
 	void *__cu_to;							\
 	const void *__cu_from;						\
 	long __cu_len;							\
 									\
+	might_sleep();							\
 	__cu_to = (to);							\
 	__cu_from = (from);						\
 	__cu_len = (n);							\
@@ -397,12 +547,29 @@ extern size_t __copy_user(void *__to, co
 	__cu_len;							\
 })
 
+/*
+ * copy_from_user: - Copy a block of data from user space.
+ * @to:   Destination address, in kernel space.
+ * @from: Source address, in user space.
+ * @n:    Number of bytes to copy.
+ *
+ * Context: User context only.  This function may sleep.
+ *
+ * Copy data from user space to kernel space.
+ *
+ * Returns number of bytes that could not be copied.
+ * On success, this will be zero.
+ *
+ * If some data could not be copied, this function will pad the copied
+ * data to the requested size using zero bytes.
+ */
 #define copy_from_user(to,from,n)					\
 ({									\
 	void *__cu_to;							\
 	const void *__cu_from;						\
 	long __cu_len;							\
 									\
+	might_sleep();							\
 	__cu_to = (to);							\
 	__cu_from = (from);						\
 	__cu_len = (n);							\
@@ -412,11 +579,25 @@ extern size_t __copy_user(void *__to, co
 	__cu_len;							\
 })
 
+#define __copy_in_user(to, from, n)	__copy_from_user(to, from, n)
+
+/*
+ * __clear_user: - Zero a block of memory in user space, with less checking.
+ * @to:   Destination address, in user space.
+ * @n:    Number of bytes to zero.
+ *
+ * Zero a block of memory in user space.  Caller must check
+ * the specified block with access_ok() before calling this function.
+ *
+ * Returns number of bytes that could not be cleared.
+ * On success, this will be zero.
+ */
 static inline __kernel_size_t
 __clear_user(void *addr, __kernel_size_t size)
 {
 	__kernel_size_t res;
 
+	might_sleep();
 	__asm__ __volatile__(
 		"move\t$4, %1\n\t"
 		"move\t$5, $0\n\t"
@@ -425,30 +606,47 @@ __clear_user(void *addr, __kernel_size_t
 		"move\t%0, $6"
 		: "=r" (res)
 		: "r" (addr), "r" (size)
-		: "$4", "$5", "$6", "$8", "$9", "$31");
+		: "$4", "$5", "$6", __UA_t0, __UA_t1, "$31");
 
 	return res;
 }
 
-#define clear_user(addr,n)					\
-({								\
-	void * __cl_addr = (addr);				\
-	unsigned long __cl_size = (n);				\
-	if (__cl_size && access_ok(VERIFY_WRITE,		\
-		((unsigned long)(__cl_addr)), __cl_size))	\
-		__cl_size = __clear_user(__cl_addr, __cl_size);	\
-	__cl_size;						\
+#define clear_user(addr,n)						\
+({									\
+	void * __cl_addr = (addr);					\
+	unsigned long __cl_size = (n);					\
+	if (__cl_size && access_ok(VERIFY_WRITE,			\
+		((unsigned long)(__cl_addr)), __cl_size))		\
+		__cl_size = __clear_user(__cl_addr, __cl_size);		\
+	__cl_size;							\
 })
 
 /*
- * Returns: -EFAULT if exception before terminator, N if the entire
- * buffer filled, else strlen.
+ * __strncpy_from_user: - Copy a NUL terminated string from userspace, with less checking.
+ * @dst:   Destination address, in kernel space.  This buffer must be at
+ *         least @count bytes long.
+ * @src:   Source address, in user space.
+ * @count: Maximum number of bytes to copy, including the trailing NUL.
+ *
+ * Copies a NUL-terminated string from userspace to kernel space.
+ * Caller must check the specified block with access_ok() before calling
+ * this function.
+ *
+ * On success, returns the length of the string (not including the trailing
+ * NUL).
+ *
+ * If access to userspace fails, returns -EFAULT (some data may have been
+ * copied).
+ *
+ * If @count is smaller than the length of the string, copies @count bytes
+ * and returns @count.
  */
 static inline long
 __strncpy_from_user(char *__to, const char *__from, long __len)
 {
 	long res;
 
+	might_sleep();
 	__asm__ __volatile__(
 		"move\t$4, %1\n\t"
 		"move\t$5, %2\n\t"
@@ -457,16 +655,35 @@ __strncpy_from_user(char *__to, const ch
 		"move\t%0, $2"
 		: "=r" (res)
 		: "r" (__to), "r" (__from), "r" (__len)
-		: "$2", "$3", "$4", "$5", "$6", "$8", "$31", "memory");
+		: "$2", "$3", "$4", "$5", "$6", __UA_t0, "$31", "memory");
 
 	return res;
 }
 
+/*
+ * strncpy_from_user: - Copy a NUL terminated string from userspace.
+ * @dst:   Destination address, in kernel space.  This buffer must be at
+ *         least @count bytes long.
+ * @src:   Source address, in user space.
+ * @count: Maximum number of bytes to copy, including the trailing NUL.
+ *
+ * Copies a NUL-terminated string from userspace to kernel space.
+ *
+ * On success, returns the length of the string (not including the trailing
+ * NUL).
+ *
+ * If access to userspace fails, returns -EFAULT (some data may have been
+ * copied).
+ *
+ * If @count is smaller than the length of the string, copies @count bytes
+ * and returns @count.
+ */
 static inline long
 strncpy_from_user(char *__to, const char *__from, long __len)
 {
 	long res;
 
+	might_sleep();
 	__asm__ __volatile__(
 		"move\t$4, %1\n\t"
 		"move\t$5, %2\n\t"
@@ -475,7 +692,7 @@ strncpy_from_user(char *__to, const char
 		"move\t%0, $2"
 		: "=r" (res)
 		: "r" (__to), "r" (__from), "r" (__len)
-		: "$2", "$3", "$4", "$5", "$6", "$8", "$31", "memory");
+		: "$2", "$3", "$4", "$5", "$6", __UA_t0, "$31", "memory");
 
 	return res;
 }
@@ -485,28 +702,44 @@ static inline long __strlen_user(const c
 {
 	long res;
 
+	might_sleep();
 	__asm__ __volatile__(
 		"move\t$4, %1\n\t"
 		__MODULE_JAL(__strlen_user_nocheck_asm)
 		"move\t%0, $2"
 		: "=r" (res)
 		: "r" (s)
-		: "$2", "$4", "$8", "$31");
+		: "$2", "$4", __UA_t0, "$31");
 
 	return res;
 }
 
+/*
+ * strlen_user: - Get the size of a string in user space.
+ * @str: The string to measure.
+ *
+ * Context: User context only.  This function may sleep.
+ *
+ * Get the size of a NUL-terminated string in user space.
+ *
+ * Returns the size of the string INCLUDING the terminating NUL.
+ * On exception, returns 0.
+ *
+ * If there is a limit on the length of a valid string, you may wish to
+ * consider using strnlen_user() instead.
+ */
 static inline long strlen_user(const char *s)
 {
 	long res;
 
+	might_sleep();
 	__asm__ __volatile__(
 		"move\t$4, %1\n\t"
 		__MODULE_JAL(__strlen_user_asm)
 		"move\t%0, $2"
 		: "=r" (res)
 		: "r" (s)
-		: "$2", "$4", "$8", "$31");
+		: "$2", "$4", __UA_t0, "$31");
 
 	return res;
 }
@@ -516,6 +749,7 @@ static inline long __strnlen_user(const 
 {
 	long res;
 
+	might_sleep();
 	__asm__ __volatile__(
 		"move\t$4, %1\n\t"
 		"move\t$5, %2\n\t"
@@ -523,15 +757,30 @@ static inline long __strnlen_user(const 
 		"move\t%0, $2"
 		: "=r" (res)
 		: "r" (s), "r" (n)
-		: "$2", "$4", "$5", "$8", "$31");
+		: "$2", "$4", "$5", __UA_t0, "$31");
 
 	return res;
 }
 
+/*
+ * strlen_user: - Get the size of a string in user space.
+ * @str: The string to measure.
+ *
+ * Context: User context only.  This function may sleep.
+ *
+ * Get the size of a NUL-terminated string in user space.
+ *
+ * Returns the size of the string INCLUDING the terminating NUL.
+ * On exception, returns 0.
+ *
+ * If there is a limit on the length of a valid string, you may wish to
+ * consider using strnlen_user() instead.
+ */
 static inline long strnlen_user(const char *s, long n)
 {
 	long res;
 
+	might_sleep();
 	__asm__ __volatile__(
 		"move\t$4, %1\n\t"
 		"move\t$5, %2\n\t"
@@ -539,7 +788,7 @@ static inline long strnlen_user(const ch
 		"move\t%0, $2"
 		: "=r" (res)
 		: "r" (s), "r" (n)
-		: "$2", "$4", "$5", "$8", "$31");
+		: "$2", "$4", "$5", __UA_t0, "$31");
 
 	return res;
 }
@@ -550,4 +799,6 @@ struct exception_table_entry
 	unsigned long nextinsn;
 };
 
+extern int fixup_exception(struct pt_regs *regs);
+
 #endif /* _ASM_UACCESS_H */
--- diff/include/asm-mips/unaligned.h	2003-08-20 14:16:34.000000000 +0100
+++ source/include/asm-mips/unaligned.h	2004-02-23 13:56:47.000000000 +0000
@@ -58,19 +58,19 @@ struct __una_u16 { __u16 x __attribute__
  * Elemental unaligned loads 
  */
 
-extern inline __u64 __uldq(const __u64 * r11)
+static inline __u64 __uldq(const __u64 * r11)
 {
 	const struct __una_u64 *ptr = (const struct __una_u64 *) r11;
 	return ptr->x;
 }
 
-extern inline __u32 __uldl(const __u32 * r11)
+static inline __u32 __uldl(const __u32 * r11)
 {
 	const struct __una_u32 *ptr = (const struct __una_u32 *) r11;
 	return ptr->x;
 }
 
-extern inline __u16 __uldw(const __u16 * r11)
+static inline __u16 __uldw(const __u16 * r11)
 {
 	const struct __una_u16 *ptr = (const struct __una_u16 *) r11;
 	return ptr->x;
@@ -80,25 +80,25 @@ extern inline __u16 __uldw(const __u16 *
  * Elemental unaligned stores 
  */
 
-extern inline void __ustq(__u64 r5, __u64 * r11)
+static inline void __ustq(__u64 r5, __u64 * r11)
 {
 	struct __una_u64 *ptr = (struct __una_u64 *) r11;
 	ptr->x = r5;
 }
 
-extern inline void __ustl(__u32 r5, __u32 * r11)
+static inline void __ustl(__u32 r5, __u32 * r11)
 {
 	struct __una_u32 *ptr = (struct __una_u32 *) r11;
 	ptr->x = r5;
 }
 
-extern inline void __ustw(__u16 r5, __u16 * r11)
+static inline void __ustw(__u16 r5, __u16 * r11)
 {
 	struct __una_u16 *ptr = (struct __una_u16 *) r11;
 	ptr->x = r5;
 }
 
-extern inline __u64 __get_unaligned(const void *ptr, size_t size)
+static inline __u64 __get_unaligned(const void *ptr, size_t size)
 {
 	__u64 val;
 
@@ -121,7 +121,7 @@ extern inline __u64 __get_unaligned(cons
 	return val;
 }
 
-extern inline void __put_unaligned(__u64 val, void *ptr, size_t size)
+static inline void __put_unaligned(__u64 val, void *ptr, size_t size)
 {
 	switch (size) {
 	      case 1:
--- diff/include/asm-mips/unistd.h	2003-08-20 14:16:34.000000000 +0100
+++ source/include/asm-mips/unistd.h	2004-02-23 13:56:47.000000000 +0000
@@ -498,7 +498,7 @@
 #define __NR_lremovexattr		(__NR_Linux + 190)
 #define __NR_fremovexattr		(__NR_Linux + 191)
 #define __NR_tkill			(__NR_Linux + 192)
-#define __NR_time			(__NR_Linux + 193)
+#define __NR_reserved193		(__NR_Linux + 193)
 #define __NR_futex			(__NR_Linux + 194)
 #define __NR_sched_setaffinity		(__NR_Linux + 195)
 #define __NR_sched_getaffinity		(__NR_Linux + 196)
@@ -742,7 +742,7 @@
 #define __NR_lremovexattr		(__NR_Linux + 190)
 #define __NR_fremovexattr		(__NR_Linux + 191)
 #define __NR_tkill			(__NR_Linux + 192)
-#define __NR_time			(__NR_Linux + 193)
+#define __NR_reserved193		(__NR_Linux + 193)
 #define __NR_futex			(__NR_Linux + 194)
 #define __NR_sched_setaffinity		(__NR_Linux + 195)
 #define __NR_sched_getaffinity		(__NR_Linux + 196)
@@ -769,27 +769,27 @@
 #define __NR_statfs64			(__NR_Linux + 217)
 #define __NR_fstatfs64			(__NR_Linux + 218)
 #define __NR_sendfile64			(__NR_Linux + 219)
-#define __NR_timer_create		(__NR_Linux + 221)
-#define __NR_timer_settime		(__NR_Linux + 222)
-#define __NR_timer_gettime		(__NR_Linux + 223)
-#define __NR_timer_getoverrun		(__NR_Linux + 224)
-#define __NR_timer_delete		(__NR_Linux + 225)
-#define __NR_clock_settime		(__NR_Linux + 226)
-#define __NR_clock_gettime		(__NR_Linux + 227)
-#define __NR_clock_getres		(__NR_Linux + 228)
-#define __NR_clock_nanosleep		(__NR_Linux + 229)
-#define __NR_tgkill			(__NR_Linux + 230)
-#define __NR_utimes			(__NR_Linux + 231)
+#define __NR_timer_create		(__NR_Linux + 220)
+#define __NR_timer_settime		(__NR_Linux + 221)
+#define __NR_timer_gettime		(__NR_Linux + 222)
+#define __NR_timer_getoverrun		(__NR_Linux + 223)
+#define __NR_timer_delete		(__NR_Linux + 224)
+#define __NR_clock_settime		(__NR_Linux + 225)
+#define __NR_clock_gettime		(__NR_Linux + 226)
+#define __NR_clock_getres		(__NR_Linux + 227)
+#define __NR_clock_nanosleep		(__NR_Linux + 228)
+#define __NR_tgkill			(__NR_Linux + 229)
+#define __NR_utimes			(__NR_Linux + 230)
 
 /*
  * Offset of the last N32 flavoured syscall
  */
-#define __NR_Linux_syscalls		231
+#define __NR_Linux_syscalls		230
 
 #endif /* _MIPS_SIM == _MIPS_SIM_NABI32 */
 
 #define __NR_N32_Linux			6000
-#define __NR_N32_Linux_syscalls		231
+#define __NR_N32_Linux_syscalls		230
 
 #ifndef __ASSEMBLY__
 
@@ -1047,6 +1047,9 @@ type name (atype a,btype b,ctype c,dtype
 
 #ifdef __KERNEL_SYSCALLS__
 
+#include <asm/ptrace.h>
+#include <asm/sim.h>
+
 /*
  * we need this inline - forking from kernel space will result
  * in NO COPY ON WRITE (!!!), until an execve is executed. This
@@ -1059,7 +1062,6 @@ type name (atype a,btype b,ctype c,dtype
  * won't be any messing with the stack from main(), but we define
  * some others too.
  */
-#define __NR__exit __NR_exit
 static inline _syscall0(pid_t,setsid)
 static inline _syscall3(int,write,int,fd,const char *,buf,off_t,count)
 static inline _syscall3(int,read,int,fd,char *,buf,off_t,count)
@@ -1068,7 +1070,6 @@ static inline _syscall1(int,dup,int,fd)
 static inline _syscall3(int,execve,const char *,file,char **,argv,char **,envp)
 static inline _syscall3(int,open,const char *,file,int,flag,int,mode)
 static inline _syscall1(int,close,int,fd)
-static inline _syscall1(int,_exit,int,exitcode)
 struct rusage;
 static inline _syscall4(pid_t,wait4,pid_t,pid,int *,stat_addr,int,options,struct rusage *,ru)
 
@@ -1077,6 +1078,18 @@ static inline pid_t waitpid(int pid, int
 	return wait4(pid, wait_stat, flags, NULL);
 }
 
+asmlinkage unsigned long sys_mmap(
+				unsigned long addr, size_t len,
+				int prot, int flags,
+				int fd, off_t offset);
+asmlinkage long sys_mmap2(
+			unsigned long addr, unsigned long len,
+			unsigned long prot, unsigned long flags,
+			unsigned long fd, unsigned long pgoff);
+asmlinkage int sys_execve(nabi_no_regargs struct pt_regs regs);
+asmlinkage int sys_pipe(nabi_no_regargs struct pt_regs regs);
+asmlinkage int sys_ptrace(long request, long pid, long addr, long data);
+
 #endif /* __KERNEL_SYSCALLS__ */
 #endif /* !__ASSEMBLY__ */
 
--- diff/include/asm-mips/vr41xx/mpc30x.h	2003-07-08 09:55:19.000000000 +0100
+++ source/include/asm-mips/vr41xx/mpc30x.h	2004-02-23 13:56:47.000000000 +0000
@@ -16,8 +16,6 @@
 #ifndef __VICTOR_MPC30X_H
 #define __VICTOR_MPC30X_H
 
-#include <linux/config.h>
-
 #include <asm/addrspace.h>
 #include <asm/vr41xx/vr41xx.h>
 
--- diff/include/asm-mips/vr41xx/vr41xx.h	2003-07-08 09:55:19.000000000 +0100
+++ source/include/asm-mips/vr41xx/vr41xx.h	2004-02-23 13:56:47.000000000 +0000
@@ -7,6 +7,7 @@
  * Copyright (C) 2001, 2002 Paul Mundt
  * Copyright (C) 2002 MontaVista Software, Inc.
  * Copyright (C) 2002 TimeSys Corp.
+ * Copyright (C) 2003 Yoichi Yuasa <yuasa@hh.iij4u.or.jp>
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the
@@ -32,23 +33,44 @@
 #define PRID_VR4181A_REV1_0	0x00000c73
 #define PRID_VR4181A_REV1_1	0x00000c74
 
-/* VR4131 0x00000c80-0x00000c8f */
+/* VR4131 0x00000c80-0x00000c83 */
 #define PRID_VR4131_REV1_2	0x00000c80
 #define PRID_VR4131_REV2_0	0x00000c81
 #define PRID_VR4131_REV2_1	0x00000c82
 #define PRID_VR4131_REV2_2	0x00000c83
 
+/* VR4133 0x00000c84- */
+#define PRID_VR4133		0x00000c84
+
 /*
  * Bus Control Uint
  */
 extern void vr41xx_bcu_init(void);
+extern unsigned long vr41xx_get_vtclock_frequency(void);
+extern unsigned long vr41xx_get_tclock_frequency(void);
 
 /*
  * Clock Mask Unit
  */
-extern void vr41xx_cmu_init(u16 mask);
-extern void vr41xx_clock_supply(u16 mask);
-extern void vr41xx_clock_mask(u16 mask);
+extern void vr41xx_cmu_init(void);
+extern void vr41xx_clock_supply(unsigned int clock);
+extern void vr41xx_clock_mask(unsigned int clock);
+
+enum {
+	PIU_CLOCK,
+	SIU_CLOCK,
+	AIU_CLOCK,
+	KIU_CLOCK,
+	FIR_CLOCK,
+	DSIU_CLOCK,
+	CSI_CLOCK,
+	PCIU_CLOCK,
+	HSP_CLOCK,
+	PCI_CLOCK,
+	CEU_CLOCK,
+	ETHER0_CLOCK,
+	ETHER1_CLOCK
+};
 
 /*
  * Interrupt Control Unit
@@ -58,59 +80,84 @@ extern void vr41xx_clock_mask(u16 mask);
 #define MIPS_CPU_IRQ(x)		(MIPS_CPU_IRQ_BASE + (x))
 #define MIPS_SOFTINT0_IRQ	MIPS_CPU_IRQ(0)
 #define MIPS_SOFTINT1_IRQ	MIPS_CPU_IRQ(1)
-#define ICU_CASCADE_IRQ		MIPS_CPU_IRQ(2)
-#define RTC_LONG1_IRQ		MIPS_CPU_IRQ(3)
-#define RTC_LONG2_IRQ		MIPS_CPU_IRQ(4)
-/* RFU */
-#define BATTERY_IRQ		MIPS_CPU_IRQ(6)
+#define INT0_CASCADE_IRQ	MIPS_CPU_IRQ(2)
+#define INT1_CASCADE_IRQ	MIPS_CPU_IRQ(3)
+#define INT2_CASCADE_IRQ	MIPS_CPU_IRQ(4)
+#define INT3_CASCADE_IRQ	MIPS_CPU_IRQ(5)
+#define INT4_CASCADE_IRQ	MIPS_CPU_IRQ(6)
 #define MIPS_COUNTER_IRQ	MIPS_CPU_IRQ(7)
 
 /* SYINT1 Interrupt Numbers */
 #define SYSINT1_IRQ_BASE	8
 #define SYSINT1_IRQ(x)		(SYSINT1_IRQ_BASE + (x))
-/* RFU */
+#define BATTRY_IRQ		SYSINT1_IRQ(0)
 #define POWER_IRQ		SYSINT1_IRQ(1)
+#define RTCLONG1_IRQ		SYSINT1_IRQ(2)
+#define ELAPSEDTIME_IRQ		SYSINT1_IRQ(3)
 /* RFU */
+#define PIU_IRQ			SYSINT1_IRQ(5)
+#define AIU_IRQ			SYSINT1_IRQ(6)
+#define KIU_IRQ			SYSINT1_IRQ(7)
 #define GIUINT_CASCADE_IRQ	SYSINT1_IRQ(8)
 #define SIU_IRQ			SYSINT1_IRQ(9)
-/* RFU */
+#define BUSERR_IRQ		SYSINT1_IRQ(10)
 #define SOFTINT_IRQ		SYSINT1_IRQ(11)
 #define CLKRUN_IRQ		SYSINT1_IRQ(12)
-#define SYSINT1_IRQ_LAST	CLKRUN_IRQ
+#define DOZEPIU_IRQ		SYSINT1_IRQ(13)
+#define SYSINT1_IRQ_LAST	DOZEPIU_IRQ
 
 /* SYSINT2 Interrupt Numbers */
 #define SYSINT2_IRQ_BASE	24
 #define SYSINT2_IRQ(x)		(SYSINT2_IRQ_BASE + (x))
-/* RFU */
+#define RTCLONG2_IRQ		SYSINT2_IRQ(0)
 #define LED_IRQ			SYSINT2_IRQ(1)
-/* RFU */
-#define VTCLOCK_IRQ		SYSINT2_IRQ(3)
+#define HSP_IRQ			SYSINT2_IRQ(2)
+#define TCLOCK_IRQ		SYSINT2_IRQ(3)
 #define FIR_IRQ			SYSINT2_IRQ(4)
+#define CEU_IRQ			SYSINT2_IRQ(4)	/* same number as FIR_IRQ */
 #define DSIU_IRQ		SYSINT2_IRQ(5)
 #define PCI_IRQ			SYSINT2_IRQ(6)
 #define SCU_IRQ			SYSINT2_IRQ(7)
 #define CSI_IRQ			SYSINT2_IRQ(8)
 #define BCU_IRQ			SYSINT2_IRQ(9)
-#define SYSINT2_IRQ_LAST	BCU_IRQ
+#define ETHERNET_IRQ		SYSINT2_IRQ(10)
+#define SYSINT2_IRQ_LAST	ETHERNET_IRQ
 
 /* GIU Interrupt Numbers */
 #define GIU_IRQ_BASE		40
 #define GIU_IRQ(x)		(GIU_IRQ_BASE + (x))	/* IRQ 40-71 */
 #define GIU_IRQ_LAST		GIU_IRQ(31)
+#define GIU_IRQ_TO_PIN(x)	((x) - GIU_IRQ_BASE)	/* Pin 0-31 */
 
 extern void (*board_irq_init)(void);
+extern int vr41xx_set_intassign(unsigned int irq, unsigned char intassign);
 extern int vr41xx_cascade_irq(unsigned int irq, int (*get_irq_number)(int irq));
 
 /*
- * Gegeral-Purpose I/O Unit
+ * Power Management Unit
  */
-extern void vr41xx_enable_giuint(int pin);
-extern void vr41xx_disable_giuint(int pin);
-extern void vr41xx_clear_giuint(int pin);
+extern void vr41xx_pmu_init(void);
 
+/*
+ * RTC
+ */
+extern void vr41xx_set_rtclong1_cycle(uint32_t cycles);
+extern uint32_t vr41xx_read_rtclong1_counter(void);
+
+extern void vr41xx_set_rtclong2_cycle(uint32_t cycles);
+extern uint32_t vr41xx_read_rtclong2_counter(void);
+
+extern void vr41xx_set_tclock_cycle(uint32_t cycles);
+extern uint32_t vr41xx_read_tclock_counter(void);
+
+/*
+ * General-Purpose I/O Unit
+ */
 enum {
 	TRIGGER_LEVEL,
-	TRIGGER_EDGE
+	TRIGGER_EDGE,
+	TRIGGER_EDGE_FALLING,
+	TRIGGER_EDGE_RISING
 };
 
 enum {
@@ -185,8 +232,4 @@ extern void vr41xx_pciu_init(struct vr41
 extern void vr41xx_time_init(void);
 extern void vr41xx_timer_setup(struct irqaction *irq);
 
-extern void vr41xx_restart(char *command);
-extern void vr41xx_halt(void);
-extern void vr41xx_power_off(void);
-
 #endif /* __NEC_VR41XX_H */
--- diff/include/asm-mips/vr41xx/vrc4173.h	2003-07-08 09:55:19.000000000 +0100
+++ source/include/asm-mips/vr41xx/vrc4173.h	2004-02-23 13:56:47.000000000 +0000
@@ -72,6 +72,19 @@ extern unsigned long vrc4173_io_offset;
 /*
  * Clock Mask Unit
  */
+#define VRC4173_PIU_CLOCK		0x0001
+#define VRC4173_KIU_CLOCK		0x0002
+#define VRC4173_AIU_CLOCK		0x0004
+#define VRC4173_PS2CH1_CLOCK		0x0008
+#define VRC4173_PS2CH2_CLOCK		0x0010
+#define VRC4173_USBU_PCI_CLOCK		0x0020
+#define VRC4173_CARDU1_PCI_CLOCK	0x0040
+#define VRC4173_CARDU2_PCI_CLOCK	0x0080
+#define VRC4173_AC97U_PCI_CLOCK		0x0100
+#define VRC4173_USBU_48MHz_CLOCK	0x0400
+#define VRC4173_EXT_48MHz_CLOCK		0x0800
+#define VRC4173_48MHz_CLOCK		0x1000
+
 extern void vrc4173_clock_supply(u16 mask);
 extern void vrc4173_clock_mask(u16 mask);
 
--- diff/include/asm-mips/vr41xx/workpad.h	2003-07-08 09:55:19.000000000 +0100
+++ source/include/asm-mips/vr41xx/workpad.h	2004-02-23 13:56:47.000000000 +0000
@@ -22,7 +22,7 @@
 /*
  * Board specific address mapping
  */
-#define VR41XX_ISA_MEM_BASE		0x100000000
+#define VR41XX_ISA_MEM_BASE		0x10000000
 #define VR41XX_ISA_MEM_SIZE		0x04000000
 
 /* VR41XX_ISA_IO_BASE includes offset from real base. */
--- diff/include/asm-mips/war.h	2003-07-08 09:55:19.000000000 +0100
+++ source/include/asm-mips/war.h	2004-02-23 13:56:47.000000000 +0000
@@ -3,7 +3,7 @@
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  *
- * Copyright (C) 2002 by Ralf Baechle
+ * Copyright (C) 2002, 2004 by Ralf Baechle
  */
 #ifndef _ASM_WAR_H
 #define _ASM_WAR_H
@@ -11,7 +11,16 @@
 #include <linux/config.h>
 
 /*
- * Pleassures of the R4600 V1.x.  Cite from the IDT R4600 V1.7 errata:
+ * Another R4600 erratum.  Due to the lack of errata information the exact
+ * technical details aren't known.  I've experimentally found that disabling
+ * interrupts during indexed I-cache flushes seems to be sufficient to deal
+ * with the issue.
+ *
+ * #define R4600_V1_INDEX_ICACHEOP_WAR 1
+ */
+
+/*
+ * Pleasures of the R4600 V1.x.  Cite from the IDT R4600 V1.7 errata:
  *
  *  18. The CACHE instructions Hit_Writeback_Invalidate_D, Hit_Writeback_D,
  *      Hit_Invalidate_D and Create_Dirty_Excl_D should only be
@@ -59,6 +68,7 @@
  */
 #ifdef CONFIG_SGI_IP22
 
+#define R4600_V1_INDEX_ICACHEOP_WAR	1
 #define R4600_V1_HIT_CACHEOP_WAR	1
 #define R4600_V2_HIT_CACHEOP_WAR	1
 
@@ -111,8 +121,59 @@
 #endif
 
 /*
+ * Fill buffers not flushed on CACHE instructions
+ * 
+ * Hit_Invalidate_I cacheops invalidate an icache line but the refill
+ * for that line can get stale data from the fill buffer instead of
+ * accessing memory if the previous icache miss was also to that line.
+ *
+ * Workaround: generate an icache refill from a different line
+ *
+ * Affects:
+ *  MIPS 4K		RTL revision <3.0, PRID revision <4
+ */
+#if defined(CONFIG_MIPS_MALTA) || defined(CONFIG_MIPS_ATLAS) || \
+    defined(CONFIG_MIPS_SEAD)
+#define MIPS4K_ICACHE_REFILL_WAR 1
+#endif
+
+/*
+ * Missing implicit forced flush of evictions caused by CACHE
+ * instruction
+ *
+ * Evictions caused by a CACHE instructions are not forced on to the
+ * bus. The BIU gives higher priority to fetches than to the data from
+ * the eviction buffer and no collision detection is performed between
+ * fetches and pending data from the eviction buffer.
+ *
+ * Workaround: Execute a SYNC instruction after the cache instruction
+ *
+ * Affects:
+ *   MIPS 5Kc,5Kf	RTL revision <2.3, PRID revision <8
+ *   MIPS 20Kc		RTL revision <4.0, PRID revision <?
+ */
+#if defined(CONFIG_MIPS_MALTA) || defined(CONFIG_MIPS_ATLAS) || \
+    defined(CONFIG_MIPS_SEAD)
+#define MIPS_CACHE_SYNC_WAR 1
+#endif
+
+/*
+ * From TX49/H2 manual: "If the instruction (i.e. CACHE) is issued for
+ * the line which this instruction itself exists, the following
+ * operation is not guaranteed."
+ *
+ * Workaround: do two phase flushing for Index_Invalidate_I
+ */
+#ifdef CONFIG_CPU_TX49XX
+#define TX49XX_ICACHE_INDEX_INV_WAR 1
+#endif
+
+/*
  * Workarounds default to off
  */
+#ifndef R4600_V1_INDEX_ICACHEOP_WAR
+#define R4600_V1_INDEX_ICACHEOP_WAR	0
+#endif
 #ifndef R4600_V1_HIT_CACHEOP_WAR
 #define R4600_V1_HIT_CACHEOP_WAR	0
 #endif
@@ -128,5 +189,14 @@
 #ifndef SIBYTE_1956_WAR
 #define SIBYTE_1956_WAR			0
 #endif
+#ifndef MIPS4K_ICACHE_REFILL_WAR
+#define MIPS4K_ICACHE_REFILL_WAR	0
+#endif
+#ifndef MIPS_CACHE_SYNC_WAR
+#define MIPS_CACHE_SYNC_WAR		0
+#endif
+#ifndef TX49XX_ICACHE_INDEX_INV_WAR
+#define TX49XX_ICACHE_INDEX_INV_WAR	0
+#endif
 
 #endif /* _ASM_WAR_H */
--- diff/include/asm-parisc/module.h	2003-06-30 10:07:29.000000000 +0100
+++ source/include/asm-parisc/module.h	2004-02-23 13:56:47.000000000 +0000
@@ -17,11 +17,6 @@
 #define Elf_Rela Elf32_Rela
 #endif
 
-#define module_map(x)		vmalloc(x)
-#define module_unmap(x)		vfree(x)
-#define module_arch_init(x)	(0)
-#define arch_init_modules(x)	do { } while (0)
-
 struct mod_arch_specific
 {
 	unsigned long got_offset, got_count, got_max;
--- diff/include/asm-parisc/param.h	2003-10-09 09:47:34.000000000 +0100
+++ source/include/asm-parisc/param.h	2004-02-23 13:56:47.000000000 +0000
@@ -18,10 +18,6 @@
 
 #define EXEC_PAGESIZE	4096
 
-#ifndef NGROUPS
-#define NGROUPS		32
-#endif
-
 #ifndef NOGROUP
 #define NOGROUP		(-1)
 #endif
--- diff/include/asm-parisc/unistd.h	2004-01-19 10:22:59.000000000 +0000
+++ source/include/asm-parisc/unistd.h	2004-02-23 13:56:47.000000000 +0000
@@ -840,34 +840,30 @@ type name(type1 arg1, type2 arg2, type3 
 #ifdef __KERNEL_SYSCALLS__
 
 #include <asm/current.h>
+#include <linux/syscalls.h>
 
 static inline pid_t setsid(void)
 {
-	extern long sys_setsid(void);
 	return sys_setsid();
 }
 
 static inline int write(int fd, const char *buf, off_t count)
 {
-	extern long sys_write(int, const char *, int);
 	return sys_write(fd, buf, count);
 }
 
 static inline int read(int fd, char *buf, off_t count)
 {
-	extern long sys_read(int, char *, int);
 	return sys_read(fd, buf, count);
 }
 
 static inline off_t lseek(int fd, off_t offset, int count)
 {
-	extern off_t sys_lseek(int, off_t, int);
 	return sys_lseek(fd, offset, count);
 }
 
 static inline int dup(int fd)
 {
-	extern long sys_dup(int);
 	return sys_dup(fd);
 }
 
@@ -880,30 +876,39 @@ static inline int execve(char *filename,
 
 static inline int open(const char *file, int flag, int mode)
 {
-	extern long sys_open(const char *, int, int);
 	return sys_open(file, flag, mode);
 }
 
 static inline int close(int fd)
 {
-	extern asmlinkage long sys_close(unsigned int);
 	return sys_close(fd);
 }
 
 static inline int _exit(int exitcode)
 {
-	extern long sys_exit(int) __attribute__((noreturn));
 	return sys_exit(exitcode);
 }
 
-struct rusage;
-extern asmlinkage long sys_wait4(pid_t, unsigned int *, int, struct rusage *);
-
 static inline pid_t waitpid(pid_t pid, int *wait_stat, int options)
 {
 	return sys_wait4(pid, wait_stat, options, NULL);
 }
 
+asmlinkage unsigned long sys_mmap(unsigned long addr, unsigned long len,
+				unsigned long prot, unsigned long flags,
+				unsigned long fd, unsigned long offset);
+asmlinkage unsigned long sys_mmap2(unsigned long addr, unsigned long len,
+				unsigned long prot, unsigned long flags,
+				unsigned long fd, unsigned long pgoff);
+struct pt_regs;
+asmlinkage int sys_execve(struct pt_regs *regs);
+int sys_clone(unsigned long clone_flags, unsigned long usp,
+		struct pt_regs *regs);
+int sys_vfork(struct pt_regs *regs);
+int sys_pipe(int *fildes);
+long sys_ptrace(long request, pid_t pid, long addr, long data);
+asmlinkage long sys_ioperm(unsigned long from, unsigned long num, int turn_on);
+
 #endif	/* __KERNEL_SYSCALLS__ */
 
 #endif /* __ASSEMBLY__ */
--- diff/include/asm-ppc/machdep.h	2004-02-18 08:54:12.000000000 +0000
+++ source/include/asm-ppc/machdep.h	2004-02-23 13:56:47.000000000 +0000
@@ -104,7 +104,8 @@ struct machdep_calls {
 };
 
 extern struct machdep_calls ppc_md;
-extern char cmd_line[512];
+#define COMMAND_LINE_SIZE 512
+extern char cmd_line[COMMAND_LINE_SIZE];
 
 extern void setup_pci_ptrs(void);
 
--- diff/include/asm-ppc/param.h	2004-02-18 08:54:12.000000000 +0000
+++ source/include/asm-ppc/param.h	2004-02-23 13:56:47.000000000 +0000
@@ -13,10 +13,6 @@
 
 #define EXEC_PAGESIZE	4096
 
-#ifndef NGROUPS
-#define NGROUPS		32
-#endif
-
 #ifndef NOGROUP
 #define NOGROUP		(-1)
 #endif
--- diff/include/asm-ppc/system.h	2003-09-30 15:46:19.000000000 +0100
+++ source/include/asm-ppc/system.h	2004-02-23 13:56:47.000000000 +0000
@@ -95,8 +95,6 @@ extern struct task_struct *_switch(struc
 
 extern unsigned int rtas_data;
 
-extern void dump_regs(struct pt_regs *);
-
 static __inline__ unsigned long
 xchg_u32(volatile void *p, unsigned long val)
 {
--- diff/include/asm-ppc/unistd.h	2004-02-09 10:36:12.000000000 +0000
+++ source/include/asm-ppc/unistd.h	2004-02-23 13:56:47.000000000 +0000
@@ -390,6 +390,27 @@ extern int open(const char *file, int fl
 extern int close(int fd);
 extern pid_t waitpid(pid_t pid, int *wait_stat, int options);
 
+unsigned long sys_mmap(unsigned long addr, size_t len,
+			unsigned long prot, unsigned long flags,
+			unsigned long fd, off_t offset);
+unsigned long sys_mmap2(unsigned long addr, size_t len,
+			unsigned long prot, unsigned long flags,
+			unsigned long fd, unsigned long pgoff);
+struct pt_regs;
+int sys_execve(unsigned long a0, unsigned long a1, unsigned long a2,
+		unsigned long a3, unsigned long a4, unsigned long a5,
+		struct pt_regs *regs);
+int sys_clone(unsigned long clone_flags, unsigned long usp,
+	      int __user *parent_tidp, void __user *child_threadptr,
+	      int __user *child_tidp, int p6,
+	      struct pt_regs *regs);
+int sys_fork(int p1, int p2, int p3, int p4, int p5, int p6,
+		struct pt_regs *regs);
+int sys_vfork(int p1, int p2, int p3, int p4, int p5, int p6,
+		struct pt_regs *regs);
+int sys_pipe(int __user *fildes);
+int sys_ptrace(long request, long pid, long addr, long data);
+
 #endif /* __KERNEL_SYSCALLS__ */
 
 /*
--- diff/include/asm-ppc64/compat.h	2004-02-09 10:36:12.000000000 +0000
+++ source/include/asm-ppc64/compat.h	2004-02-23 13:56:47.000000000 +0000
@@ -25,6 +25,7 @@ typedef u16		compat_ipc_pid_t;
 typedef s32		compat_daddr_t;
 typedef u32		compat_caddr_t;
 typedef __kernel_fsid_t	compat_fsid_t;
+typedef u32		compat_timer_t;
 
 typedef s32		compat_int_t;
 typedef s32		compat_long_t;
--- diff/include/asm-ppc64/iSeries/vio.h	2004-02-18 08:54:12.000000000 +0000
+++ source/include/asm-ppc64/iSeries/vio.h	2004-02-23 13:56:47.000000000 +0000
@@ -38,8 +38,8 @@
  * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  *
  */
-#ifndef _VIO_H
-#define _VIO_H
+#ifndef _ISERIES_VIO_H
+#define _ISERIES_VIO_H
 
 #include <asm/iSeries/HvTypes.h>
 #include <asm/iSeries/HvLpEvent.h>
@@ -127,4 +127,4 @@ enum viorc {
 	viorc_openRejected = 0x0301
 };
 
-#endif /* _VIO_H */
+#endif /* _ISERIES_VIO_H */
--- diff/include/asm-ppc64/lmb.h	2004-02-18 08:54:12.000000000 +0000
+++ source/include/asm-ppc64/lmb.h	2004-02-23 13:56:47.000000000 +0000
@@ -13,12 +13,12 @@
  * 2 of the License, or (at your option) any later version.
  */
 
-#include <linux/config.h>
+#include <linux/init.h>
 #include <asm/prom.h>
 
 extern unsigned long reloc_offset(void);
 
-#define MAX_LMB_REGIONS 64
+#define MAX_LMB_REGIONS 128
 
 union lmb_reg_property { 
 	struct reg_property32	 addr32[MAX_LMB_REGIONS];
@@ -26,24 +26,17 @@ union lmb_reg_property { 
 	struct reg_property_pmac addrPM[MAX_LMB_REGIONS];
 };
 
-#define LMB_MEMORY_AREA	1
-#define LMB_IO_AREA	2
-
 #define LMB_ALLOC_ANYWHERE	0
-#define LMB_ALLOC_FIRST4GBYTE	(1UL<<32)
 
 struct lmb_property {
 	unsigned long base;
 	unsigned long physbase;
 	unsigned long size;
-	unsigned long type;
 };
 
 struct lmb_region {
 	unsigned long cnt;
 	unsigned long size;
-	unsigned long iosize;
-	unsigned long lcd_size;		/* Least Common Denominator */
 	struct lmb_property region[MAX_LMB_REGIONS+1];
 };
 
@@ -54,63 +47,17 @@ struct lmb {
 	struct lmb_region reserved;
 };
 
-extern struct lmb lmb;
-
-extern void lmb_init(void);
-extern void lmb_analyze(void);
-extern long lmb_add(unsigned long, unsigned long);
-#ifdef CONFIG_MSCHUNKS
-extern long lmb_add_io(unsigned long base, unsigned long size);
-#endif /* CONFIG_MSCHUNKS */
-extern long lmb_reserve(unsigned long, unsigned long);
-extern unsigned long lmb_alloc(unsigned long, unsigned long);
-extern unsigned long lmb_alloc_base(unsigned long, unsigned long, unsigned long);
-extern unsigned long lmb_phys_mem_size(void);
-extern unsigned long lmb_end_of_DRAM(void);
-extern unsigned long lmb_abs_to_phys(unsigned long);
-extern void lmb_dump(char *);
-
-static inline unsigned long
-lmb_addrs_overlap(unsigned long base1, unsigned long size1,
-                  unsigned long base2, unsigned long size2)
-{
-        return ((base1 < (base2+size2)) && (base2 < (base1+size1)));
-}
-
-static inline long
-lmb_regions_overlap(struct lmb_region *rgn, unsigned long r1, unsigned long r2)
-{
-	unsigned long base1 = rgn->region[r1].base;
-        unsigned long size1 = rgn->region[r1].size;
-	unsigned long base2 = rgn->region[r2].base;
-        unsigned long size2 = rgn->region[r2].size;
-
-	return lmb_addrs_overlap(base1,size1,base2,size2);
-}
-
-static inline long
-lmb_addrs_adjacent(unsigned long base1, unsigned long size1,
-		   unsigned long base2, unsigned long size2)
-{
-	if ( base2 == base1 + size1 ) {
-		return 1;
-	} else if ( base1 == base2 + size2 ) {
-		return -1;
-	}
-	return 0;
-}
-
-static inline long
-lmb_regions_adjacent(struct lmb_region *rgn, unsigned long r1, unsigned long r2)
-{
-	unsigned long base1 = rgn->region[r1].base;
-        unsigned long size1 = rgn->region[r1].size;
-        unsigned long type1 = rgn->region[r1].type;
-	unsigned long base2 = rgn->region[r2].base;
-        unsigned long size2 = rgn->region[r2].size;
-        unsigned long type2 = rgn->region[r2].type;
+extern struct lmb lmb __initdata;
 
-	return (type1 == type2) && lmb_addrs_adjacent(base1,size1,base2,size2);
-}
+extern void __init lmb_init(void);
+extern void __init lmb_analyze(void);
+extern long __init lmb_add(unsigned long, unsigned long);
+extern long __init lmb_reserve(unsigned long, unsigned long);
+extern unsigned long __init lmb_alloc(unsigned long, unsigned long);
+extern unsigned long __init lmb_alloc_base(unsigned long, unsigned long,
+					   unsigned long);
+extern unsigned long __init lmb_phys_mem_size(void);
+extern unsigned long __init lmb_end_of_DRAM(void);
+extern unsigned long __init lmb_abs_to_phys(unsigned long);
 
 #endif /* _PPC64_LMB_H */
--- diff/include/asm-ppc64/machdep.h	2004-02-18 08:54:12.000000000 +0000
+++ source/include/asm-ppc64/machdep.h	2004-02-23 13:56:47.000000000 +0000
@@ -20,7 +20,7 @@ struct rtc_time;
 
 #ifdef CONFIG_SMP
 struct smp_ops_t {
-	void  (*message_pass)(int target, int msg, unsigned long data, int wait);
+	void  (*message_pass)(int target, int msg);
 	int   (*probe)(void);
 	void  (*kick_cpu)(int nr);
 	void  (*setup_cpu)(int nr);
@@ -109,7 +109,9 @@ struct machdep_calls {
 };
 
 extern struct machdep_calls ppc_md;
-extern char cmd_line[512];
+#define COMMAND_LINE_SIZE 512
+extern char cmd_line[COMMAND_LINE_SIZE];
+extern char saved_command_line[COMMAND_LINE_SIZE];
 
 /* Functions to produce codes on the leds.
  * The SRC code should be unique for the message category and should
--- diff/include/asm-ppc64/mmu_context.h	2004-02-09 10:36:12.000000000 +0000
+++ source/include/asm-ppc64/mmu_context.h	2004-02-23 13:56:47.000000000 +0000
@@ -156,6 +156,11 @@ static inline void switch_mm(struct mm_s
 	 : : );
 #endif /* CONFIG_ALTIVEC */
 
+	if (!cpu_isset(smp_processor_id(), next->cpu_vm_mask))
+		cpu_set(smp_processor_id(), next->cpu_vm_mask);
+
+	cpu_set(smp_processor_id(), next->cpu_vm_mask);
+
 	/* No need to flush userspace segments if the mm doesnt change */
 	if (prev == next)
 		return;
@@ -164,7 +169,6 @@ static inline void switch_mm(struct mm_s
 		flush_slb(tsk, next);
 	else
 		flush_stab(tsk, next);
-	cpu_set(smp_processor_id(), next->cpu_vm_mask);
 }
 
 #define deactivate_mm(tsk,mm)	do { } while (0)
--- diff/include/asm-ppc64/param.h	2002-10-16 04:29:02.000000000 +0100
+++ source/include/asm-ppc64/param.h	2004-02-23 13:56:47.000000000 +0000
@@ -20,10 +20,6 @@
 
 #define EXEC_PAGESIZE	4096
 
-#ifndef NGROUPS
-#define NGROUPS		32
-#endif
-
 #ifndef NOGROUP
 #define NOGROUP		(-1)
 #endif
--- diff/include/asm-ppc64/pci.h	2004-02-18 08:54:12.000000000 +0000
+++ source/include/asm-ppc64/pci.h	2004-02-23 13:56:47.000000000 +0000
@@ -19,8 +19,6 @@
 #define PCIBIOS_MIN_IO		0x1000
 #define PCIBIOS_MIN_MEM		0x10000000
 
-extern int pcibios_scan_all_fns(struct pci_bus *bus, int devfn);
-
 #ifdef CONFIG_PPC_ISERIES
 #define pcibios_scan_all_fns(a, b)	0
 #else
--- diff/include/asm-ppc64/ppc32.h	2004-02-09 10:36:12.000000000 +0000
+++ source/include/asm-ppc64/ppc32.h	2004-02-23 13:56:47.000000000 +0000
@@ -2,6 +2,7 @@
 #define _PPC64_PPC32_H
 
 #include <linux/compat.h>
+#include <linux/compat_siginfo.h>
 #include <asm/siginfo.h>
 #include <asm/signal.h>
 
@@ -40,55 +41,6 @@
 
 /* These are here to support 32-bit syscalls on a 64-bit kernel. */
 
-typedef struct compat_siginfo {
-	int si_signo;
-	int si_errno;
-	int si_code;
-
-	union {
-		int _pad[SI_PAD_SIZE32];
-
-		/* kill() */
-		struct {
-			compat_pid_t _pid;		/* sender's pid */
-			compat_uid_t _uid;		/* sender's uid */
-		} _kill;
-
-		/* POSIX.1b timers */
-		struct {
-			unsigned int _timer1;
-			unsigned int _timer2;
-		} _timer;
-
-		/* POSIX.1b signals */
-		struct {
-			compat_pid_t _pid;		/* sender's pid */
-			compat_uid_t _uid;		/* sender's uid */
-			compat_sigval_t _sigval;
-		} _rt;
-
-		/* SIGCHLD */
-		struct {
-			compat_pid_t _pid;		/* which child */
-			compat_uid_t _uid;		/* sender's uid */
-			int _status;			/* exit code */
-			compat_clock_t _utime;
-			compat_clock_t _stime;
-		} _sigchld;
-
-		/* SIGILL, SIGFPE, SIGSEGV, SIGBUS, SIGEMT */
-		struct {
-			unsigned int _addr; /* faulting insn/memory ref. */
-		} _sigfault;
-
-		/* SIGPOLL */
-		struct {
-			int _band;	/* POLL_IN, POLL_OUT, POLL_MSG */
-			int _fd;
-		} _sigpoll;
-	} _sifields;
-} compat_siginfo_t;
-
 #define __old_sigaction32	old_sigaction32
 
 struct __old_sigaction32 {
@@ -141,20 +93,6 @@ struct ucontext32 { 
 	struct mcontext32	uc_mcontext;
 };
 
-typedef struct compat_sigevent {
-	compat_sigval_t sigev_value;
-	int sigev_signo;
-	int sigev_notify;
-	union {
-		int _pad[SIGEV_PAD_SIZE];
-		int _tid;
-		struct {
-			compat_uptr_t _function;
-			compat_uptr_t _attribute;
-		} _sigev_thread;
-	} _sigev_un;
-} compat_sigevent_t;
-
 struct ipc_kludge_32 {
 	unsigned int msgp;
 	int msgtyp;
--- diff/include/asm-ppc64/processor.h	2004-02-18 08:54:12.000000000 +0000
+++ source/include/asm-ppc64/processor.h	2004-02-23 13:56:47.000000000 +0000
@@ -475,7 +475,8 @@ static inline void set_tb(unsigned int u
 	mttbl(lower);
 }
 
-extern unsigned long *_get_SP(void);
+#define __get_SP()	({unsigned long sp; \
+			asm volatile("mr %0,1": "=r" (sp)); sp;})
 
 extern int have_of;
 
--- diff/include/asm-ppc64/signal.h	2003-09-30 15:46:19.000000000 +0100
+++ source/include/asm-ppc64/signal.h	2004-02-23 13:56:47.000000000 +0000
@@ -148,15 +148,6 @@ struct pt_regs;
 struct timespec;
 extern int do_signal(sigset_t *oldset, struct pt_regs *regs);
 extern int do_signal32(sigset_t *oldset, struct pt_regs *regs);
-extern long sys_rt_sigprocmask(int how, sigset_t *set, sigset_t *oset,
-			       size_t sigsetsize);
-extern long sys_rt_sigpending(sigset_t *set, size_t sigsetsize);
-extern long sys_rt_sigtimedwait(const sigset_t *uthese, siginfo_t *uinfo,
-				const struct timespec *uts, size_t sigsetsize);
-extern long sys_rt_sigqueueinfo(int pid, int sig, siginfo_t *uinfo);
 #define ptrace_signal_deliver(regs, cookie) do { } while (0)
 
-struct pt_regs;
-int do_signal32(sigset_t *oldset, struct pt_regs *regs);
-
 #endif /* _ASMPPC64_SIGNAL_H */
--- diff/include/asm-ppc64/smp.h	2004-02-18 08:54:12.000000000 +0000
+++ source/include/asm-ppc64/smp.h	2004-02-23 13:56:47.000000000 +0000
@@ -28,7 +28,6 @@
 
 #ifdef CONFIG_SMP
 
-extern void smp_message_pass(int target, int msg, unsigned long data, int wait);
 extern void smp_send_debugger_break(int cpu);
 struct pt_regs;
 extern void smp_message_recv(int, struct pt_regs *);
--- diff/include/asm-ppc64/system.h	2004-02-18 08:54:12.000000000 +0000
+++ source/include/asm-ppc64/system.h	2004-02-23 13:56:47.000000000 +0000
@@ -53,6 +53,10 @@
 #define smp_read_barrier_depends()  do { } while(0)
 #endif /* CONFIG_SMP */
 
+#ifdef __KERNEL__
+struct task_struct;
+struct pt_regs;
+
 #ifdef CONFIG_DEBUGGER
 
 extern int (*__debugger)(struct pt_regs *regs);
@@ -82,12 +86,12 @@ extern void xmon_init(void);
 #endif
 
 #else
-#define debugger(regs)			0
-#define debugger_bpt(regs)		0
-#define debugger_sstep(regs)		0
-#define debugger_iabr_match(regs)	0
-#define debugger_dabr_match(regs)	0
-#define debugger_fault_handler(regs)	0
+static inline int debugger(struct pt_regs *regs) { return 0; }
+static inline int debugger_bpt(struct pt_regs *regs) { return 0; }
+static inline int debugger_sstep(struct pt_regs *regs) { return 0; }
+static inline int debugger_iabr_match(struct pt_regs *regs) { return 0; }
+static inline int debugger_dabr_match(struct pt_regs *regs) { return 0; }
+static inline int debugger_fault_handler(struct pt_regs *regs) { return 0; }
 #endif
 
 extern void show_regs(struct pt_regs * regs);
@@ -103,7 +107,6 @@ extern void cvt_fd(float *from, double *
 extern void cvt_df(double *from, float *to, unsigned long *fpscr);
 extern int abs(int);
 
-struct task_struct;
 extern struct task_struct *__switch_to(struct task_struct *,
 				       struct task_struct *);
 #define switch_to(prev, next, last)	((last) = __switch_to((prev), (next)))
@@ -112,9 +115,6 @@ struct thread_struct;
 extern struct task_struct * _switch(struct thread_struct *prev,
 				    struct thread_struct *next);
 
-struct pt_regs;
-extern void dump_regs(struct pt_regs *);
-
 static inline int __is_processor(unsigned long pv)
 {
 	unsigned long pvr;
@@ -265,4 +265,5 @@ __cmpxchg(volatile void *ptr, unsigned l
 				    (unsigned long)_n_, sizeof(*(ptr))); \
   })
 
+#endif /* __KERNEL__ */
 #endif
--- diff/include/asm-ppc64/thread_info.h	2003-10-27 09:20:39.000000000 +0000
+++ source/include/asm-ppc64/thread_info.h	2004-02-23 13:56:47.000000000 +0000
@@ -11,6 +11,7 @@
 #ifdef __KERNEL__
 
 #ifndef __ASSEMBLY__
+#include <linux/config.h>
 #include <asm/processor.h>
 #include <linux/stringify.h>
 
@@ -51,7 +52,19 @@ struct thread_info {
 #define THREAD_ORDER		2
 #define THREAD_SIZE		(PAGE_SIZE << THREAD_ORDER)
 #define THREAD_SHIFT		(PAGE_SHIFT + THREAD_ORDER)
-#define alloc_thread_info(task)	((struct thread_info *)kmalloc(THREAD_SIZE, GFP_KERNEL))
+#ifdef CONFIG_DEBUG_STACK_USAGE
+#define alloc_thread_info(tsk)					\
+	({							\
+		struct thread_info *ret;			\
+								\
+		ret = kmalloc(THREAD_SIZE, GFP_KERNEL);		\
+		if (ret)					\
+			memset(ret, 0, THREAD_SIZE);		\
+		ret;						\
+	})
+#else
+#define alloc_thread_info(tsk) kmalloc(THREAD_SIZE, GFP_KERNEL)
+#endif
 #define free_thread_info(ti)	kfree(ti)
 #define get_thread_info(ti)	get_task_struct((ti)->task)
 #define put_thread_info(ti)	put_task_struct((ti)->task)
--- diff/include/asm-ppc64/unistd.h	2004-02-09 10:36:12.000000000 +0000
+++ source/include/asm-ppc64/unistd.h	2004-02-23 13:56:47.000000000 +0000
@@ -274,6 +274,9 @@
 
 #ifndef __ASSEMBLY__
 
+#include <linux/types.h>
+#include <linux/linkage.h>
+
 /* On powerpc a system call basically clobbers the same registers like a
  * function call, with the exception of LR (which is needed for the
  * "sc; bnslr" sequence) and CR (where only CR0.SO is clobbered to signal
@@ -404,9 +407,27 @@ extern int execve(const char *file, char
 extern int open(const char *file, int flag, int mode);
 extern int close(int fd);
 extern pid_t waitpid(pid_t pid, int *wait_stat, int options);
-
 #endif /* __KERNEL_SYSCALLS__ */
 
+asmlinkage unsigned long sys_mmap(unsigned long addr, size_t len,
+				unsigned long prot, unsigned long flags,
+				unsigned long fd, off_t offset);
+struct pt_regs;
+int sys_execve(unsigned long a0, unsigned long a1, unsigned long a2,
+		unsigned long a3, unsigned long a4, unsigned long a5,
+		struct pt_regs *regs);
+int sys_clone(unsigned long clone_flags, unsigned long p2, unsigned long p3,
+		unsigned long p4, unsigned long p5, unsigned long p6,
+		struct pt_regs *regs);
+int sys_fork(unsigned long p1, unsigned long p2, unsigned long p3,
+		unsigned long p4, unsigned long p5, unsigned long p6,
+		struct pt_regs *regs);
+int sys_vfork(unsigned long p1, unsigned long p2, unsigned long p3,
+		unsigned long p4, unsigned long p5, unsigned long p6,
+		struct pt_regs *regs);
+asmlinkage int sys_pipe(int *fildes);
+int sys_ptrace(long request, long pid, long addr, long data);
+
 /*
  * "Conditional" syscalls
  *
--- diff/include/asm-s390/byteorder.h	2004-02-09 10:36:12.000000000 +0000
+++ source/include/asm-s390/byteorder.h	2004-02-23 13:56:47.000000000 +0000
@@ -67,7 +67,7 @@ static __inline__ __u32 ___arch__swab32(
 	
 	__asm__ __volatile__ (
 		"   lrvr  %0,%1"
-		: "=d" (result) : "d" (x), "m" (x) );
+		: "=d" (result) : "d" (x) );
 	return result;
 #endif /* __s390x__ */
 }
--- diff/include/asm-s390/ccwgroup.h	2004-02-09 10:36:12.000000000 +0000
+++ source/include/asm-s390/ccwgroup.h	2004-02-23 13:56:47.000000000 +0000
@@ -10,6 +10,7 @@ struct ccwgroup_device {
 		CCWGROUP_OFFLINE,
 		CCWGROUP_ONLINE,
 	} state;
+	atomic_t onoff;
 	unsigned int count;		/* number of attached slave devices */
 	struct device	dev;		/* master device		    */
 	struct ccw_device *cdev[0];	/* variable number, allocate as needed */
--- diff/include/asm-s390/compat.h	2003-07-08 09:55:19.000000000 +0100
+++ source/include/asm-s390/compat.h	2004-02-23 13:56:47.000000000 +0000
@@ -15,6 +15,8 @@ typedef s32		compat_clock_t;
 typedef s32		compat_pid_t;
 typedef u16		compat_uid_t;
 typedef u16		compat_gid_t;
+typedef u32		compat_uid32_t;
+typedef u32		compat_gid32_t;
 typedef u16		compat_mode_t;
 typedef u32		compat_ino_t;
 typedef u16		compat_dev_t;
@@ -25,6 +27,7 @@ typedef u16		compat_ipc_pid_t;
 typedef s32		compat_daddr_t;
 typedef u32		compat_caddr_t;
 typedef __kernel_fsid_t	compat_fsid_t;
+typedef s32		compat_key_t;
 
 typedef s32		compat_int_t;
 typedef s32		compat_long_t;
@@ -134,4 +137,61 @@ static inline void *compat_alloc_user_sp
 	return (void *) (stack - len);
 }
 
+struct compat_ipc64_perm {
+	compat_key_t key;
+	compat_uid32_t uid;
+	compat_gid32_t gid;
+	compat_uid32_t cuid;
+	compat_gid32_t cgid;
+	compat_mode_t mode;
+	unsigned short __pad1;
+	unsigned short seq;
+	unsigned short __pad2;
+	unsigned int __unused1;
+	unsigned int __unused2;
+};
+
+struct compat_semid64_ds {
+	struct compat_ipc64_perm sem_perm;
+	compat_time_t  sem_otime;
+	compat_ulong_t __pad1;
+	compat_time_t  sem_ctime;
+	compat_ulong_t __pad2;
+	compat_ulong_t sem_nsems;
+	compat_ulong_t __unused1;
+	compat_ulong_t __unused2;
+};
+
+struct compat_msqid64_ds {
+	struct compat_ipc64_perm msg_perm;
+	compat_time_t   msg_stime;
+	compat_ulong_t __pad1;
+	compat_time_t   msg_rtime;
+	compat_ulong_t __pad2;
+	compat_time_t   msg_ctime;
+	compat_ulong_t __pad3;
+	compat_ulong_t msg_cbytes;
+	compat_ulong_t msg_qnum;
+	compat_ulong_t msg_qbytes;
+	compat_pid_t   msg_lspid;
+	compat_pid_t   msg_lrpid;
+	compat_ulong_t __unused1;
+	compat_ulong_t __unused2;
+};
+
+struct compat_shmid64_ds {
+	struct compat_ipc64_perm shm_perm;
+	compat_size_t  shm_segsz;
+	compat_time_t  shm_atime;
+	compat_ulong_t __pad1;
+	compat_time_t  shm_dtime;
+	compat_ulong_t __pad2;
+	compat_time_t  shm_ctime;
+	compat_ulong_t __pad3;
+	compat_pid_t   shm_cpid;
+	compat_pid_t   shm_lpid;
+	compat_ulong_t shm_nattch;
+	compat_ulong_t __unused1;
+	compat_ulong_t __unused2;
+};
 #endif /* _ASM_S390X_COMPAT_H */
--- diff/include/asm-s390/debug.h	2002-11-28 11:30:26.000000000 +0000
+++ source/include/asm-s390/debug.h	2004-02-23 13:56:47.000000000 +0000
@@ -35,11 +35,7 @@ struct __debug_entry{
 
 #ifdef __KERNEL__
 #include <linux/version.h>
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0))
- #include <asm/spinlock.h>
-#else
- #include <linux/spinlock.h>
-#endif /* LINUX_VERSION_CODE */
+#include <linux/spinlock.h>
 #include <linux/kernel.h>
 #include <linux/time.h>
 #include <linux/proc_fs.h>
--- diff/include/asm-s390/dma-mapping.h	2003-08-20 14:16:14.000000000 +0100
+++ source/include/asm-s390/dma-mapping.h	2004-02-23 13:56:47.000000000 +0000
@@ -8,4 +8,18 @@
 
 #ifndef _ASM_DMA_MAPPING_H
 #define _ASM_DMA_MAPPING_H
+
+static inline void *dma_alloc_coherent(struct device *dev, size_t size,
+			 dma_addr_t *dma_handle, int flag)
+{
+	BUG();
+	return 0;
+}
+
+static inline void dma_free_coherent(struct device *dev, size_t size,
+		       void *vaddr, dma_addr_t dma_handle)
+{
+	BUG();
+}
+
 #endif /* _ASM_DMA_MAPPING_H */
--- diff/include/asm-s390/idals.h	2004-02-09 10:36:12.000000000 +0000
+++ source/include/asm-s390/idals.h	2004-02-23 13:56:47.000000000 +0000
@@ -228,7 +228,7 @@ idal_buffer_to_user(struct idal_buffer *
 		left = copy_to_user(to, ib->data[i], IDA_BLOCK_SIZE);
 		if (left)
 			return left + count - IDA_BLOCK_SIZE;
-		(addr_t) to += IDA_BLOCK_SIZE;
+		to = (void *) to + IDA_BLOCK_SIZE;
 		count -= IDA_BLOCK_SIZE;
 	}
 	return copy_to_user(to, ib->data[i], count);
@@ -248,7 +248,7 @@ idal_buffer_from_user(struct idal_buffer
 		left = copy_from_user(ib->data[i], from, IDA_BLOCK_SIZE);
 		if (left)
 			return left + count - IDA_BLOCK_SIZE;
-		(addr_t) from += IDA_BLOCK_SIZE;
+		from = (void *) from + IDA_BLOCK_SIZE;
 		count -= IDA_BLOCK_SIZE;
 	}
 	return copy_from_user(ib->data[i], from, count);
--- diff/include/asm-s390/param.h	2002-10-16 04:27:14.000000000 +0100
+++ source/include/asm-s390/param.h	2004-02-23 13:56:47.000000000 +0000
@@ -21,10 +21,6 @@
 
 #define EXEC_PAGESIZE	4096
 
-#ifndef NGROUPS
-#define NGROUPS		32
-#endif
-
 #ifndef NOGROUP
 #define NOGROUP		(-1)
 #endif
--- diff/include/asm-s390/pgalloc.h	2004-02-09 10:36:12.000000000 +0000
+++ source/include/asm-s390/pgalloc.h	2004-02-23 13:56:47.000000000 +0000
@@ -21,6 +21,8 @@
 
 #define check_pgt_cache()	do {} while (0)
 
+extern void diag10(unsigned long addr);
+
 /*
  * Allocate and free page tables. The xxx_kernel() versions are
  * used to allocate a kernel page table - this turns on ASN bits
--- diff/include/asm-s390/qdio.h	2003-09-30 15:46:20.000000000 +0100
+++ source/include/asm-s390/qdio.h	2004-02-23 13:56:47.000000000 +0000
@@ -17,6 +17,7 @@
 
 #include <linux/interrupt.h>
 #include <asm/cio.h>
+#include <asm/ccwdev.h>
 
 #define QDIO_NAME "qdio "
 
--- diff/include/asm-s390/smp.h	2004-02-09 10:36:12.000000000 +0000
+++ source/include/asm-s390/smp.h	2004-02-23 13:56:47.000000000 +0000
@@ -29,6 +29,9 @@ typedef struct
 	__u16      cpu;
 } sigp_info;
 
+extern int smp_call_function_on(void (*func) (void *info), void *info,
+				int nonatomic, int wait, int cpu);
+
 extern cpumask_t cpu_online_map;
 extern cpumask_t cpu_possible_map;
 
@@ -61,4 +64,9 @@ extern __inline__ __u16 hard_smp_process
 #define cpu_logical_map(cpu) (cpu)
 
 #endif
+
+#ifndef CONFIG_SMP
+#define smp_call_function_on(func,info,nonatomic,wait,cpu)      ({ 0; })
+#endif
+
 #endif
--- diff/include/asm-s390/unistd.h	2004-02-09 10:36:12.000000000 +0000
+++ source/include/asm-s390/unistd.h	2004-02-23 13:56:47.000000000 +0000
@@ -505,7 +505,10 @@ type name(type1 arg1, type2 arg2, type3 
 
 #ifdef __KERNEL_SYSCALLS__
 
+#include <linux/config.h>
+#include <asm/ptrace.h>
 #include <asm/stat.h>
+#include <linux/syscalls.h>
 
 /*
  * we need this inline - forking from kernel space will result
@@ -528,15 +531,27 @@ static inline _syscall1(int,dup,int,fd)
 static inline _syscall3(int,execve,const char *,file,char **,argv,char **,envp)
 static inline _syscall3(int,open,const char *,file,int,flag,int,mode)
 static inline _syscall1(int,close,int,fd)
-static inline _syscall1(int,_exit,int,exitcode)
 static inline _syscall2(long,stat,char *,filename,struct stat *,statbuf)
 
-struct rusage;
-extern long sys_wait4(pid_t, unsigned int *, int, struct rusage *);
 static inline pid_t waitpid(int pid, int *wait_stat, int flags)
 {
 	return sys_wait4(pid, wait_stat, flags, NULL);
 }
+struct mmap_arg_struct;
+asmlinkage long sys_mmap2(struct mmap_arg_struct *arg);
+
+asmlinkage int sys_execve(struct pt_regs regs);
+asmlinkage int sys_clone(struct pt_regs regs);
+asmlinkage int sys_fork(struct pt_regs regs);
+asmlinkage int sys_vfork(struct pt_regs regs);
+#ifndef CONFIG_ARCH_S390X
+#define __SYS_RETTYPE int
+#else
+#define __SYS_RETTYPE long
+#endif /* CONFIG_ARCH_S390X */
+asmlinkage __SYS_RETTYPE sys_pipe(unsigned long *fildes);
+asmlinkage int sys_ptrace(long request, long pid, long addr, long data);
+asmlinkage long sys_ioperm(unsigned long from, unsigned long num, int on);
 
 #endif
 
--- diff/include/asm-sh/hardirq.h	2004-02-09 10:36:12.000000000 +0000
+++ source/include/asm-sh/hardirq.h	2004-02-23 13:56:47.000000000 +0000
@@ -74,7 +74,7 @@ typedef struct {
 #define nmi_enter()		(irq_enter())
 #define nmi_exit()		(preempt_count() -= HARDIRQ_OFFSET)
 
-#if CONFIG_PREEMPT
+#ifdef CONFIG_PREEMPT
 # define in_atomic()	((preempt_count() & ~PREEMPT_ACTIVE) != kernel_locked())
 # define IRQ_EXIT_OFFSET (HARDIRQ_OFFSET-1)
 #else
--- diff/include/asm-sh/kmap_types.h	2003-07-08 09:55:19.000000000 +0100
+++ source/include/asm-sh/kmap_types.h	2004-02-23 13:56:47.000000000 +0000
@@ -5,7 +5,7 @@
 
 #include <linux/config.h>
 
-#if CONFIG_DEBUG_HIGHMEM
+#ifdef CONFIG_DEBUG_HIGHMEM
 # define D(n) __KM_FENCE_##n ,
 #else
 # define D(n)
--- diff/include/asm-sh/param.h	2003-07-08 09:55:19.000000000 +0100
+++ source/include/asm-sh/param.h	2004-02-23 13:56:47.000000000 +0000
@@ -17,10 +17,6 @@
 
 #define EXEC_PAGESIZE	4096
 
-#ifndef NGROUPS
-#define NGROUPS		32
-#endif
-
 #ifndef NOGROUP
 #define NOGROUP		(-1)
 #endif
--- diff/include/asm-sh/unistd.h	2004-02-09 10:36:12.000000000 +0000
+++ source/include/asm-sh/unistd.h	2004-02-23 13:56:47.000000000 +0000
@@ -402,6 +402,8 @@ __syscall_return(type,__sc0); \
 
 #ifdef __KERNEL_SYSCALLS__
 
+#include <asm/ptrace.h>
+
 /*
  * we need this inline - forking from kernel space will result
  * in NO COPY ON WRITE (!!!), until an execve is executed. This
@@ -433,6 +435,33 @@ static __inline__ pid_t wait(int * wait_
 {
 	return waitpid(-1,wait_stat,0);
 }
+
+asmlinkage long sys_mmap2(
+			unsigned long addr, unsigned long len,
+			unsigned long prot, unsigned long flags,
+			unsigned long fd, unsigned long pgoff);
+asmlinkage int sys_execve(char *ufilename, char **uargv,
+			char **uenvp, unsigned long r7,
+			struct pt_regs regs);
+asmlinkage int sys_clone(unsigned long clone_flags, unsigned long newsp,
+			unsigned long parent_tidptr,
+			unsigned long child_tidptr,
+			struct pt_regs regs);
+asmlinkage int sys_fork(unsigned long r4, unsigned long r5,
+			unsigned long r6, unsigned long r7,
+			struct pt_regs regs);
+asmlinkage int sys_vfork(unsigned long r4, unsigned long r5,
+			unsigned long r6, unsigned long r7,
+			struct pt_regs regs);
+asmlinkage int sys_pipe(unsigned long r4, unsigned long r5,
+			unsigned long r6, unsigned long r7,
+			struct pt_regs regs);
+asmlinkage int sys_ptrace(long request, long pid, long addr, long data);
+asmlinkage ssize_t sys_pread_wrapper(unsigned int fd, char *buf,
+				size_t count, long dummy, loff_t pos);
+asmlinkage ssize_t sys_pwrite_wrapper(unsigned int fd, const char *buf,
+				size_t count, long dummy, loff_t pos);
+
 #endif
 
 /*
--- diff/include/asm-sparc/asmmacro.h	2002-10-16 04:28:24.000000000 +0100
+++ source/include/asm-sparc/asmmacro.h	2004-02-23 13:56:47.000000000 +0000
@@ -26,17 +26,17 @@
 
 #define GET_PROCESSOR_MID(reg, tmp) \
 	rd	%tbr, %reg; \
-	sethi	%hi(C_LABEL(mid_xlate)), %tmp; \
+	sethi	%hi(mid_xlate), %tmp; \
 	srl	%reg, 12, %reg; \
-	or	%tmp, %lo(C_LABEL(mid_xlate)), %tmp; \
+	or	%tmp, %lo(mid_xlate), %tmp; \
 	and	%reg, 3, %reg; \
 	ldub	[%tmp + %reg], %reg;
 
 #define GET_PROCESSOR_OFFSET(reg, tmp) \
 	GET_PROCESSOR_ID(reg) \
-	sethi	%hi(C_LABEL(cpu_offset)), %tmp; \
+	sethi	%hi(cpu_offset), %tmp; \
 	sll	%reg, 2, %reg; \
-	or	%tmp, %lo(C_LABEL(cpu_offset)), %tmp; \
+	or	%tmp, %lo(cpu_offset), %tmp; \
 	ld	[%tmp + %reg], %reg;
 
 /* All trap entry points _must_ begin with this macro or else you
--- diff/include/asm-sparc/atomic.h	2004-02-18 08:54:12.000000000 +0000
+++ source/include/asm-sparc/atomic.h	2004-02-23 13:56:47.000000000 +0000
@@ -11,49 +11,16 @@
 #define __ARCH_SPARC_ATOMIC__
 
 #include <linux/config.h>
-#include <linux/spinlock.h>
 
 typedef struct { volatile int counter; } atomic_t;
 
 #ifdef __KERNEL__
 
-#ifdef CONFIG_SMP
-
-#define ATOMIC_HASH_SIZE	4
-#define ATOMIC_HASH(a)	(&__atomic_hash[(((unsigned long)a)>>8) & (ATOMIC_HASH_SIZE-1)])
-extern spinlock_t __atomic_hash[ATOMIC_HASH_SIZE];
-
-#else /* SMP */
-
-#define ATOMIC_HASH_SIZE	1
-#define ATOMIC_HASH(a)		0
-
-#endif /* SMP */
-
-static inline int __atomic_add_return(int i, atomic_t *v)
-{
-	int ret;
-	unsigned long flags;
-	spin_lock_irqsave(ATOMIC_HASH(v), flags);
-
-	ret = (v->counter += i);
-
-	spin_unlock_irqrestore(ATOMIC_HASH(v), flags);
-	return ret;
-}
-
-static inline void atomic_set(atomic_t *v, int i)
-{
-	unsigned long flags;
-	spin_lock_irqsave(ATOMIC_HASH(v), flags);
-
-	v->counter = i;
-
-	spin_unlock_irqrestore(ATOMIC_HASH(v), flags);
-}
-
 #define ATOMIC_INIT(i)  { (i) }
 
+extern int __atomic_add_return(int, atomic_t *);
+extern void atomic_set(atomic_t *, int);
+
 #define atomic_read(v)          ((v)->counter)
 
 #define atomic_add(i, v)	((void)__atomic_add_return( (int)(i), (v)))
--- diff/include/asm-sparc/checksum.h	2003-10-27 09:20:39.000000000 +0000
+++ source/include/asm-sparc/checksum.h	2004-02-23 13:56:47.000000000 +0000
@@ -18,7 +18,6 @@
  
 #include <linux/in6.h>
 #include <asm/uaccess.h>
-#include <asm/cprefix.h>
 
 /* computes the checksum of a memory block at buff, length len,
  * and adds in "sum" (32-bit)
@@ -51,7 +50,7 @@ csum_partial_copy_nocheck (const char *s
 	register int l asm("g1") = len;
 
 	__asm__ __volatile__ (
-		"call " C_LABEL_STR(__csum_partial_copy_sparc_generic) "\n\t"
+		"call __csum_partial_copy_sparc_generic\n\t"
 		" mov %6, %%g7\n"
 	: "=&r" (ret), "=&r" (d), "=&r" (l)
 	: "0" (ret), "1" (d), "2" (l), "r" (sum)
@@ -81,7 +80,7 @@ csum_partial_copy_from_user(const char *
 		".word 1f,2\n\t"
 		".previous\n"
 		"1:\n\t"
-		"call " C_LABEL_STR(__csum_partial_copy_sparc_generic) "\n\t"
+		"call __csum_partial_copy_sparc_generic\n\t"
 		" st %8, [%%sp + 64]\n"
 		: "=&r" (ret), "=&r" (d), "=&r" (l), "=&r" (s)
 		: "0" (ret), "1" (d), "2" (l), "3" (s), "r" (err)
@@ -110,7 +109,7 @@ csum_partial_copy_to_user(const char *sr
 		".word 1f,1\n\t"
 		".previous\n"
 		"1:\n\t"
-		"call " C_LABEL_STR(__csum_partial_copy_sparc_generic) "\n\t"
+		"call __csum_partial_copy_sparc_generic\n\t"
 		" st %8, [%%sp + 64]\n"
 		: "=&r" (ret), "=&r" (d), "=&r" (l), "=&r" (s)
 		: "0" (ret), "1" (d), "2" (l), "3" (s), "r" (err)
--- diff/include/asm-sparc/head.h	2002-10-16 04:27:55.000000000 +0100
+++ source/include/asm-sparc/head.h	2004-02-23 13:56:47.000000000 +0000
@@ -22,8 +22,8 @@
 /* Data/text faults. Defaults to sun4c version at boot time. */
 #define SPARC_TFAULT rd %psr, %l0; rd %wim, %l3; b sun4c_fault; mov 1, %l7;
 #define SPARC_DFAULT rd %psr, %l0; rd %wim, %l3; b sun4c_fault; mov 0, %l7;
-#define SRMMU_TFAULT rd %psr, %l0; rd %wim, %l3; b C_LABEL(srmmu_fault); mov 1, %l7;
-#define SRMMU_DFAULT rd %psr, %l0; rd %wim, %l3; b C_LABEL(srmmu_fault); mov 0, %l7;
+#define SRMMU_TFAULT rd %psr, %l0; rd %wim, %l3; b srmmu_fault; mov 1, %l7;
+#define SRMMU_DFAULT rd %psr, %l0; rd %wim, %l3; b srmmu_fault; mov 0, %l7;
 
 /* This is for traps we should NEVER get. */
 #define BAD_TRAP(num) \
@@ -41,17 +41,17 @@
 
 /* Software trap for Linux system calls. */
 #define LINUX_SYSCALL_TRAP \
-        sethi %hi(C_LABEL(sys_call_table)), %l7; \
-        or %l7, %lo(C_LABEL(sys_call_table)), %l7; \
+        sethi %hi(sys_call_table), %l7; \
+        or %l7, %lo(sys_call_table), %l7; \
         b linux_sparc_syscall; \
         rd %psr, %l0;
 
 /* Software trap for SunOS4.1.x system calls. */
 #define SUNOS_SYSCALL_TRAP \
         rd %psr, %l0; \
-        sethi %hi(C_LABEL(sunos_sys_table)), %l7; \
+        sethi %hi(sunos_sys_table), %l7; \
         b linux_sparc_syscall; \
-        or %l7, %lo(C_LABEL(sunos_sys_table)), %l7;
+        or %l7, %lo(sunos_sys_table), %l7;
 
 #define SUNOS_NO_SYSCALL_TRAP \
         b sunos_syscall; \
@@ -80,8 +80,8 @@
 
 /* Software trap for Sparc-netbsd system calls. */
 #define NETBSD_SYSCALL_TRAP \
-        sethi %hi(C_LABEL(sys_call_table)), %l7; \
-        or %l7, %lo(C_LABEL(sys_call_table)), %l7; \
+        sethi %hi(sys_call_table), %l7; \
+        or %l7, %lo(sys_call_table), %l7; \
         b bsd_syscall; \
         rd %psr, %l0;
 
--- diff/include/asm-sparc/io.h	2004-02-18 08:54:13.000000000 +0000
+++ source/include/asm-sparc/io.h	2004-02-23 13:56:47.000000000 +0000
@@ -11,16 +11,16 @@
 #include <asm/page.h>      /* IO address mapping routines need this */
 #include <asm/system.h>
 
-#define page_to_phys(page)	((page - mem_map) << PAGE_SHIFT)
+#define page_to_phys(page)	(((page) - mem_map) << PAGE_SHIFT)
 
-static inline u32 flip_dword (u32 d)
+static inline u32 flip_dword (u32 l)
 {
-	return ((d&0xff)<<24) | (((d>>8)&0xff)<<16) | (((d>>16)&0xff)<<8)| ((d>>24)&0xff);
+	return ((l&0xff)<<24) | (((l>>8)&0xff)<<16) | (((l>>16)&0xff)<<8)| ((l>>24)&0xff);
 }
 
-static inline u16 flip_word (u16 d)
+static inline u16 flip_word (u16 w)
 {
-	return ((d&0xff) << 8) | ((d>>8)&0xff);
+	return ((w&0xff) << 8) | ((w>>8)&0xff);
 }
 
 /*
@@ -56,14 +56,14 @@ static inline void __raw_writeb(u8 b, un
 	*(volatile u8 *)addr = b;
 }
 
-static inline void __raw_writew(u16 b, unsigned long addr)
+static inline void __raw_writew(u16 w, unsigned long addr)
 {
-	*(volatile u16 *)addr = b;
+	*(volatile u16 *)addr = w;
 }
 
-static inline void __raw_writel(u32 b, unsigned long addr)
+static inline void __raw_writel(u32 l, unsigned long addr)
 {
-	*(volatile u32 *)addr = b;
+	*(volatile u32 *)addr = l;
 }
 
 static inline u8 __readb(unsigned long addr)
@@ -86,26 +86,26 @@ static inline void __writeb(u8 b, unsign
 	*(volatile u8 *)addr = b;
 }
 
-static inline void __writew(u16 b, unsigned long addr)
+static inline void __writew(u16 w, unsigned long addr)
 {
-	*(volatile u16 *)addr = flip_word(b);
+	*(volatile u16 *)addr = flip_word(w);
 }
 
-static inline void __writel(u32 b, unsigned long addr)
+static inline void __writel(u32 l, unsigned long addr)
 {
-	*(volatile u32 *)addr = flip_dword(b);
+	*(volatile u32 *)addr = flip_dword(l);
 }
 
-#define readb(addr)	__readb((unsigned long)(addr))
-#define readw(addr)	__readw((unsigned long)(addr))
-#define readl(addr)	__readl((unsigned long)(addr))
-#define readb_relaxed(addr) readb(addr)
-#define readw_relaxed(addr) readw(addr)
-#define readl_relaxed(addr) readl(addr)
+#define readb(__addr)		__readb((unsigned long)(__addr))
+#define readw(__addr)		__readw((unsigned long)(__addr))
+#define readl(__addr)		__readl((unsigned long)(__addr))
+#define readb_relaxed(__addr)	readb(__addr)
+#define readw_relaxed(__addr)	readw(__addr)
+#define readl_relaxed(__addr)	readl(__addr)
 
-#define writeb(b, addr)	__writeb((b),(unsigned long)(addr))
-#define writew(b, addr)	__writew((b),(unsigned long)(addr))
-#define writel(b, addr)	__writel((b),(unsigned long)(addr))
+#define writeb(__b, __addr)	__writeb((__b),(unsigned long)(__addr))
+#define writew(__w, __addr)	__writew((__w),(unsigned long)(__addr))
+#define writel(__l, __addr)	__writel((__l),(unsigned long)(__addr))
 
 /*
  * I/O space operations
@@ -124,22 +124,22 @@ static inline void __writel(u32 b, unsig
  * mapped somewhere into virtual kernel space and we
  * can use inb/outb again.
  */
-#define inb_local(addr)		__readb(addr)
-#define inb(addr)		__readb(addr)
-#define inw(addr)		__readw(addr)
-#define inl(addr)		__readl(addr)
-
-#define outb_local(b, addr)	__writeb(b, addr)
-#define outb(b, addr)		__writeb(b, addr)
-#define outw(b, addr)		__writew(b, addr)
-#define outl(b, addr)		__writel(b, addr)
-
-#define inb_p inb
-#define outb_p outb
-#define inw_p inw
-#define outw_p outw
-#define inl_p inl
-#define outl_p outl
+#define inb_local(__addr)	__readb((unsigned long)(__addr))
+#define inb(__addr)		__readb((unsigned long)(__addr))
+#define inw(__addr)		__readw((unsigned long)(__addr))
+#define inl(__addr)		__readl((unsigned long)(__addr))
+
+#define outb_local(__b, __addr)	__writeb(__b, (unsigned long)(__addr))
+#define outb(__b, __addr)	__writeb(__b, (unsigned long)(__addr))
+#define outw(__w, __addr)	__writew(__w, (unsigned long)(__addr))
+#define outl(__l, __addr)	__writel(__l, (unsigned long)(__addr))
+
+#define inb_p(__addr)		inb(__addr)
+#define outb_p(__b, __addr)	outb(__b, __addr)
+#define inw_p(__addr)		inw(__addr)
+#define outw_p(__w, __addr)	outw(__w, __addr)
+#define inl_p(__addr)		inl(__addr)
+#define outl_p(__l, __addr)	outl(__l, __addr)
 
 extern void outsb(unsigned long addr, const void *src, unsigned long cnt);
 extern void outsw(unsigned long addr, const void *src, unsigned long cnt);
@@ -176,25 +176,25 @@ static inline void _sbus_writeb(u8 b, un
 	*(volatile u8 *)addr = b;
 }
 
-static inline void _sbus_writew(u16 b, unsigned long addr)
+static inline void _sbus_writew(u16 w, unsigned long addr)
 {
-	*(volatile u16 *)addr = b;
+	*(volatile u16 *)addr = w;
 }
 
-static inline void _sbus_writel(u32 b, unsigned long addr)
+static inline void _sbus_writel(u32 l, unsigned long addr)
 {
-	*(volatile u32 *)addr = b;
+	*(volatile u32 *)addr = l;
 }
 
 /*
  * The only reason for #define's is to hide casts to unsigned long.
  */
-#define sbus_readb(a)		_sbus_readb((unsigned long)(a))
-#define sbus_readw(a)		_sbus_readw((unsigned long)(a))
-#define sbus_readl(a)		_sbus_readl((unsigned long)(a))
-#define sbus_writeb(v, a)	_sbus_writeb(v, (unsigned long)(a))
-#define sbus_writew(v, a)	_sbus_writew(v, (unsigned long)(a))
-#define sbus_writel(v, a)	_sbus_writel(v, (unsigned long)(a))
+#define sbus_readb(__addr)		_sbus_readb((unsigned long)(__addr))
+#define sbus_readw(__addr)		_sbus_readw((unsigned long)(__addr))
+#define sbus_readl(__addr)		_sbus_readl((unsigned long)(__addr))
+#define sbus_writeb(__b, __addr)	_sbus_writeb(__b, (unsigned long)(__addr))
+#define sbus_writew(__w, __addr)	_sbus_writew(__w, (unsigned long)(__addr))
+#define sbus_writel(__l, __addr)	_sbus_writel(__l, (unsigned long)(__addr))
 
 static inline void *sbus_memset_io(void *__dst, int c, __kernel_size_t n)
 {
--- diff/include/asm-sparc/param.h	2002-10-16 04:27:19.000000000 +0100
+++ source/include/asm-sparc/param.h	2004-02-23 13:56:47.000000000 +0000
@@ -14,10 +14,6 @@
 
 #define EXEC_PAGESIZE	8192    /* Thanks for sun4's we carry baggage... */
 
-#ifndef NGROUPS
-#define NGROUPS		32
-#endif
-
 #ifndef NOGROUP
 #define NOGROUP		(-1)
 #endif
--- diff/include/asm-sparc/unistd.h	2004-02-18 08:54:13.000000000 +0000
+++ source/include/asm-sparc/unistd.h	2004-02-23 13:56:47.000000000 +0000
@@ -450,6 +450,16 @@ static __inline__ _syscall1(int,close,in
 static __inline__ _syscall1(int,_exit,int,exitcode)
 static __inline__ _syscall3(pid_t,waitpid,pid_t,pid,int *,wait_stat,int,options)
 
+asmlinkage unsigned long sys_mmap(
+				unsigned long addr, unsigned long len,
+				unsigned long prot, unsigned long flags,
+				unsigned long fd, unsigned long off);
+asmlinkage unsigned long sys_mmap2(
+				unsigned long addr, unsigned long len,
+				unsigned long prot, unsigned long flags,
+				unsigned long fd, unsigned long pgoff);
+asmlinkage int sys_ioperm(unsigned long from, unsigned long num, int on);
+
 #endif /* __KERNEL_SYSCALLS__ */
 
 /*
--- diff/include/asm-sparc/winmacro.h	2004-01-19 10:22:59.000000000 +0000
+++ source/include/asm-sparc/winmacro.h	2004-02-23 13:56:47.000000000 +0000
@@ -106,9 +106,9 @@
 #ifdef CONFIG_SMP
 #define LOAD_CURRENT4M(dest_reg, idreg) \
         rd       %tbr, %idreg; \
-	sethi    %hi(C_LABEL(current_set)), %dest_reg; \
+	sethi    %hi(current_set), %dest_reg; \
         srl      %idreg, 10, %idreg; \
-	or       %dest_reg, %lo(C_LABEL(current_set)), %dest_reg; \
+	or       %dest_reg, %lo(current_set), %dest_reg; \
 	and      %idreg, 0xc, %idreg; \
 	ld       [%idreg + %dest_reg], %dest_reg;
 
@@ -119,15 +119,15 @@
 /* Blackbox - take care with this... - check smp4m and smp4d before changing this. */
 #define LOAD_CURRENT(dest_reg, idreg) 					\
 	sethi	 %hi(___b_load_current), %idreg;			\
-	sethi    %hi(C_LABEL(current_set)), %dest_reg; 			\
-	sethi    %hi(C_LABEL(boot_cpu_id4)), %idreg; 			\
-	or       %dest_reg, %lo(C_LABEL(current_set)), %dest_reg; 	\
-	ldub	 [%idreg + %lo(C_LABEL(boot_cpu_id4))], %idreg;		\
+	sethi    %hi(current_set), %dest_reg; 			\
+	sethi    %hi(boot_cpu_id4), %idreg; 			\
+	or       %dest_reg, %lo(current_set), %dest_reg; 	\
+	ldub	 [%idreg + %lo(boot_cpu_id4)], %idreg;		\
 	ld       [%idreg + %dest_reg], %dest_reg;
 #else
 #define LOAD_CURRENT(dest_reg, idreg) \
-        sethi    %hi(C_LABEL(current_set)), %idreg; \
-        ld       [%idreg + %lo(C_LABEL(current_set))], %dest_reg;
+        sethi    %hi(current_set), %idreg; \
+        ld       [%idreg + %lo(current_set)], %dest_reg;
 #endif
 
 #endif /* !(_SPARC_WINMACRO_H) */
--- diff/include/asm-sparc64/io.h	2004-02-18 08:54:13.000000000 +0000
+++ source/include/asm-sparc64/io.h	2004-02-23 13:56:47.000000000 +0000
@@ -31,7 +31,7 @@ extern unsigned long pci_memspace_mask;
 
 #define bus_dvma_to_mem(__vaddr) ((__vaddr) & pci_memspace_mask)
 
-static __inline__ u8 inb(unsigned long addr)
+static __inline__ u8 _inb(unsigned long addr)
 {
 	u8 ret;
 
@@ -42,7 +42,7 @@ static __inline__ u8 inb(unsigned long a
 	return ret;
 }
 
-static __inline__ u16 inw(unsigned long addr)
+static __inline__ u16 _inw(unsigned long addr)
 {
 	u16 ret;
 
@@ -53,7 +53,7 @@ static __inline__ u16 inw(unsigned long 
 	return ret;
 }
 
-static __inline__ u32 inl(unsigned long addr)
+static __inline__ u32 _inl(unsigned long addr)
 {
 	u32 ret;
 
@@ -64,33 +64,40 @@ static __inline__ u32 inl(unsigned long 
 	return ret;
 }
 
-static __inline__ void outb(u8 b, unsigned long addr)
+static __inline__ void _outb(u8 b, unsigned long addr)
 {
 	__asm__ __volatile__("stba\t%r0, [%1] %2\t/* pci_outb */"
 			     : /* no outputs */
 			     : "Jr" (b), "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E_L));
 }
 
-static __inline__ void outw(u16 w, unsigned long addr)
+static __inline__ void _outw(u16 w, unsigned long addr)
 {
 	__asm__ __volatile__("stha\t%r0, [%1] %2\t/* pci_outw */"
 			     : /* no outputs */
 			     : "Jr" (w), "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E_L));
 }
 
-static __inline__ void outl(u32 l, unsigned long addr)
+static __inline__ void _outl(u32 l, unsigned long addr)
 {
 	__asm__ __volatile__("stwa\t%r0, [%1] %2\t/* pci_outl */"
 			     : /* no outputs */
 			     : "Jr" (l), "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E_L));
 }
 
-#define inb_p inb
-#define outb_p outb
-#define inw_p inw
-#define outw_p outw
-#define inl_p inl
-#define outl_p outl
+#define inb(__addr)		(_inb((unsigned long)(__addr)))
+#define inw(__addr)		(_inw((unsigned long)(__addr)))
+#define inl(__addr)		(_inl((unsigned long)(__addr)))
+#define outb(__b, __addr)	(_outb((u8)(__b), (unsigned long)(__addr)))
+#define outw(__w, __addr)	(_outw((u16)(__w), (unsigned long)(__addr)))
+#define outl(__l, __addr)	(_outl((u32)(__l), (unsigned long)(__addr)))
+
+#define inb_p(__addr) 		inb(__addr)
+#define outb_p(__b, __addr)	outb(__b, __addr)
+#define inw_p(__addr)		inw(__addr)
+#define outw_p(__w, __addr)	outw(__w, __addr)
+#define inl_p(__addr)		inl(__addr)
+#define outl_p(__l, __addr)	outl(__l, __addr)
 
 extern void outsb(unsigned long addr, const void *src, unsigned long count);
 extern void outsw(unsigned long addr, const void *src, unsigned long count);
--- diff/include/asm-sparc64/param.h	2002-10-16 04:27:09.000000000 +0100
+++ source/include/asm-sparc64/param.h	2004-02-23 13:56:47.000000000 +0000
@@ -14,10 +14,6 @@
 
 #define EXEC_PAGESIZE	8192    /* Thanks for sun4's we carry baggage... */
 
-#ifndef NGROUPS
-#define NGROUPS		32
-#endif
-
 #ifndef NOGROUP
 #define NOGROUP		(-1)
 #endif
--- diff/include/asm-sparc64/spinlock.h	2003-11-25 15:24:59.000000000 +0000
+++ source/include/asm-sparc64/spinlock.h	2004-02-23 13:56:47.000000000 +0000
@@ -30,15 +30,23 @@
 
 #ifndef CONFIG_DEBUG_SPINLOCK
 
-typedef unsigned char spinlock_t;
-#define SPIN_LOCK_UNLOCKED	0
+typedef struct {
+	unsigned char lock;
+	unsigned int  index;
+} spinlock_t;
 
-#define spin_lock_init(lock)	(*((unsigned char *)(lock)) = 0)
-#define spin_is_locked(lock)	(*((volatile unsigned char *)(lock)) != 0)
+#ifdef CONFIG_LOCKMETER
+#define SPIN_LOCK_UNLOCKED	(spinlock_t) {0, 0}
+#else
+#define SPIN_LOCK_UNLOCKED	(spinlock_t) { 0 }
+#endif
 
-#define spin_unlock_wait(lock)	\
+#define spin_lock_init(__lock)	do { *(__lock) = SPIN_LOCK_UNLOCKED; } while(0)
+#define spin_is_locked(__lock)	(*((volatile unsigned char *)(&((__lock)->lock))) != 0)
+
+#define spin_unlock_wait(__lock)	\
 do {	membar("#LoadLoad");	\
-} while(*((volatile unsigned char *)lock))
+} while(*((volatile unsigned char *)(&(((spinlock_t *)__lock)->lock))))
 
 static __inline__ void _raw_spin_lock(spinlock_t *lock)
 {
@@ -109,17 +117,31 @@ extern int _spin_trylock (spinlock_t *lo
 
 #ifndef CONFIG_DEBUG_SPINLOCK
 
-typedef unsigned int rwlock_t;
-#define RW_LOCK_UNLOCKED	0
-#define rwlock_init(lp) do { *(lp) = RW_LOCK_UNLOCKED; } while(0)
-#define rwlock_is_locked(x) (*(x) != RW_LOCK_UNLOCKED)
+#ifdef CONFIG_LOCKMETER
+typedef struct {
+	unsigned int lock;
+	unsigned int index;
+	unsigned int cpu;
+} rwlock_t;
+#define RW_LOCK_UNLOCKED       (rwlock_t) { 0, 0, 0xff }
+#else
+typedef struct {
+	unsigned int lock;
+} rwlock_t;
+#define RW_LOCK_UNLOCKED        (rwlock_t) { 0 }
+#endif
+
+#define rwlock_init(lp)		do { *(lp) = RW_LOCK_UNLOCKED; } while(0)
+#define rwlock_is_locked(x)	((x)->lock != 0)
 
+extern int __read_trylock(rwlock_t *);
 extern void __read_lock(rwlock_t *);
 extern void __read_unlock(rwlock_t *);
 extern void __write_lock(rwlock_t *);
 extern void __write_unlock(rwlock_t *);
 extern int __write_trylock(rwlock_t *);
 
+#define _raw_read_trylock(p)	__read_trylock(p)
 #define _raw_read_lock(p)	__read_lock(p)
 #define _raw_read_unlock(p)	__read_unlock(p)
 #define _raw_write_lock(p)	__write_lock(p)
--- diff/include/asm-sparc64/unistd.h	2004-02-18 08:54:13.000000000 +0000
+++ source/include/asm-sparc64/unistd.h	2004-02-23 13:56:47.000000000 +0000
@@ -440,6 +440,12 @@ static __inline__ _syscall1(int,close,in
 static __inline__ _syscall1(int,_exit,int,exitcode)
 static __inline__ _syscall3(pid_t,waitpid,pid_t,pid,int *,wait_stat,int,options)
 
+asmlinkage unsigned long sys_mmap(
+				unsigned long addr, unsigned long len,
+				unsigned long prot, unsigned long flags,
+				unsigned long fd, unsigned long off);
+asmlinkage long sys_ioperm(unsigned long from, unsigned long num, int on);
+
 #endif /* __KERNEL_SYSCALLS__ */
 
 #ifdef __KERNEL__
--- diff/include/asm-um/param.h	2002-10-16 04:27:18.000000000 +0100
+++ source/include/asm-um/param.h	2004-02-23 13:56:47.000000000 +0000
@@ -3,10 +3,6 @@
 
 #define EXEC_PAGESIZE   4096
 
-#ifndef NGROUPS
-#define NGROUPS         32
-#endif
-
 #ifndef NOGROUP
 #define NOGROUP         (-1)
 #endif
--- diff/include/asm-um/unistd.h	2002-11-18 10:11:55.000000000 +0000
+++ source/include/asm-um/unistd.h	2004-02-23 13:56:47.000000000 +0000
@@ -6,24 +6,11 @@
 #ifndef _UM_UNISTD_H_
 #define _UM_UNISTD_H_
 
+#include <linux/syscalls.h>
 #include "linux/resource.h"
 #include "asm/uaccess.h"
 
-extern long sys_open(const char *filename, int flags, int mode);
-extern long sys_dup(unsigned int fildes);
-extern long sys_close(unsigned int fd);
 extern int um_execve(const char *file, char *const argv[], char *const env[]);
-extern long sys_setsid(void);
-extern long sys_waitpid(pid_t pid, unsigned int * stat_addr, int options);
-extern long sys_wait4(pid_t pid,unsigned int *stat_addr, int options, 
-		      struct rusage *ru);
-extern long sys_mount(char *dev_name, char *dir_name, char *type, 
-		      unsigned long flags, void *data);
-extern long sys_select(int n, fd_set *inp, fd_set *outp, fd_set *exp, 
-		       struct timeval *tvp);
-extern long sys_lseek(unsigned int fildes, unsigned long offset, int whence);
-extern long sys_read(unsigned int fildes, char *buf, int len);
-extern long sys_write(int fildes, const char *buf, size_t len);
 
 #ifdef __KERNEL_SYSCALLS__
 
@@ -81,6 +68,17 @@ static inline int write(unsigned int fd,
 	KERNEL_CALL(int, sys_write, fd, buf, len)
 }
 
+long sys_mmap2(unsigned long addr, unsigned long len,
+		unsigned long prot, unsigned long flags,
+		unsigned long fd, unsigned long pgoff);
+int sys_execve(char *file, char **argv, char **env);
+long sys_clone(unsigned long clone_flags, unsigned long newsp,
+		int *parent_tid, int *child_tid);
+long sys_fork(void);
+long sys_vfork(void);
+int sys_pipe(unsigned long *fildes);
+int sys_ptrace(long request, long pid, long addr, long data);
+
 #endif
 
 /* Save the value of __KERNEL_SYSCALLS__, undefine it, include the underlying
--- diff/include/asm-v850/param.h	2002-11-11 11:09:43.000000000 +0000
+++ source/include/asm-v850/param.h	2004-02-23 13:56:47.000000000 +0000
@@ -18,10 +18,6 @@
 
 #define EXEC_PAGESIZE	4096
 
-#ifndef NGROUPS
-#define NGROUPS		32
-#endif
-
 #ifndef NOGROUP
 #define NOGROUP		(-1)
 #endif
--- diff/include/asm-v850/unistd.h	2003-05-21 11:50:10.000000000 +0100
+++ source/include/asm-v850/unistd.h	2004-02-23 13:56:47.000000000 +0000
@@ -417,6 +417,17 @@ extern inline pid_t wait(int * wait_stat
 	return waitpid (-1, wait_stat, 0);
 }
 
+unsigned long sys_mmap(unsigned long addr, size_t len,
+			unsigned long prot, unsigned long flags,
+			unsigned long fd, off_t offset);
+unsigned long sys_mmap2(unsigned long addr, size_t len,
+			unsigned long prot, unsigned long flags,
+			unsigned long fd, unsigned long pgoff);
+struct pt_regs;
+int sys_execve (char *name, char **argv, char **envp, struct pt_regs *regs);
+int sys_pipe (int *fildes);
+int sys_ptrace(long request, long pid, long addr, long data);
+
 #endif
 
 /*
--- diff/include/asm-x86_64/compat.h	2003-06-30 10:07:34.000000000 +0100
+++ source/include/asm-x86_64/compat.h	2004-02-23 13:56:47.000000000 +0000
@@ -28,6 +28,8 @@ typedef u16		compat_ipc_pid_t;
 typedef s32		compat_daddr_t;
 typedef u32		compat_caddr_t;
 typedef __kernel_fsid_t	compat_fsid_t;
+typedef u32		compat_timer_t;
+typedef s32		compat_key_t;
 
 typedef s32		compat_int_t;
 typedef s32		compat_long_t;
@@ -118,6 +120,64 @@ typedef u32               compat_sigset_
 #define COMPAT_OFF_T_MAX	0x7fffffff
 #define COMPAT_LOFF_T_MAX	0x7fffffffffffffff
 
+struct compat_ipc64_perm {
+	compat_key_t key;
+	compat_uid32_t uid;
+	compat_gid32_t gid;
+	compat_uid32_t cuid;
+	compat_gid32_t cgid;
+	unsigned short mode;
+	unsigned short __pad1;
+	unsigned short seq;
+	unsigned short __pad2;
+	compat_ulong_t unused1;
+	compat_ulong_t unused2;
+};
+
+struct compat_semid64_ds {
+	struct compat_ipc64_perm sem_perm;
+	compat_time_t  sem_otime;
+	compat_ulong_t __unused1;
+	compat_time_t  sem_ctime;
+	compat_ulong_t __unused2;
+	compat_ulong_t sem_nsems;
+	compat_ulong_t __unused3;
+	compat_ulong_t __unused4;
+};
+
+struct compat_msqid64_ds {
+	struct compat_ipc64_perm msg_perm;
+	compat_time_t  msg_stime;
+	compat_ulong_t __unused1;
+	compat_time_t  msg_rtime;
+	compat_ulong_t __unused2;
+	compat_time_t  msg_ctime;
+	compat_ulong_t __unused3;
+	compat_ulong_t msg_cbytes;
+	compat_ulong_t msg_qnum;
+	compat_ulong_t msg_qbytes;
+	compat_pid_t   msg_lspid;
+	compat_pid_t   msg_lrpid;
+	compat_ulong_t __unused4;
+	compat_ulong_t __unused5;
+};
+
+struct compat_shmid64_ds {
+	struct compat_ipc64_perm shm_perm;
+	compat_size_t  shm_segsz;
+	compat_time_t  shm_atime;
+	compat_ulong_t __unused1;
+	compat_time_t  shm_dtime;
+	compat_ulong_t __unused2;
+	compat_time_t  shm_ctime;
+	compat_ulong_t __unused3;
+	compat_pid_t   shm_cpid;
+	compat_pid_t   shm_lpid;
+	compat_ulong_t shm_nattch;
+	compat_ulong_t __unused4;
+	compat_ulong_t __unused5;
+};
+
 /*
  * A pointer passed in from user mode. This should not
  * be used for syscall parameters, just declare them
--- diff/include/asm-x86_64/cpufeature.h	2003-09-17 12:28:12.000000000 +0100
+++ source/include/asm-x86_64/cpufeature.h	2004-02-23 13:56:47.000000000 +0000
@@ -7,7 +7,7 @@
 #ifndef __ASM_X8664_CPUFEATURE_H
 #define __ASM_X8664_CPUFEATURE_H
 
-#define NCAPINTS	4	/* Currently we have 4 32-bit words worth of info */
+#define NCAPINTS	5	/* Currently we have 4 32-bit words worth of info */
 
 /* Intel-defined CPU features, CPUID level 0x00000001, word 0 */
 #define X86_FEATURE_FPU		(0*32+ 0) /* Onboard FPU */
@@ -37,6 +37,7 @@
 #define X86_FEATURE_XMM		(0*32+25) /* Streaming SIMD Extensions */
 #define X86_FEATURE_XMM2	(0*32+26) /* Streaming SIMD Extensions-2 */
 #define X86_FEATURE_SELFSNOOP	(0*32+27) /* CPU self snoop */
+#define X86_FEATURE_HT		(0*32+28) /* Hyper-Threading */
 #define X86_FEATURE_ACC		(0*32+29) /* Automatic clock control */
 #define X86_FEATURE_IA64	(0*32+30) /* IA-64 processor */
 
@@ -61,6 +62,10 @@
 #define X86_FEATURE_CENTAUR_MCR	(3*32+ 3) /* Centaur MCRs (= MTRRs) */
 #define X86_FEATURE_K8_C	(3*32+ 4) /* C stepping K8 */
 
+/* Intel-defined CPU features, CPUID level 0x00000001 (ecx), word 4 */
+#define X86_FEATURE_EST		(4*32+ 7) /* Enhanced SpeedStep */
+#define X86_FEATURE_MWAIT	(4*32+ 3) /* Monitor/Mwait support */
+
 #define cpu_has(c, bit)                test_bit(bit, (c)->x86_capability)
 #define boot_cpu_has(bit)      test_bit(bit, boot_cpu_data.x86_capability)
 
@@ -76,7 +81,7 @@
 #define cpu_has_mmx            1
 #define cpu_has_fxsr           1
 #define cpu_has_xmm            1
-#define cpu_has_ht             0 /* you need to report the support from i386. sorry */
+#define cpu_has_ht             boot_cpu_has(X86_FEATURE_HT)
 #define cpu_has_mp             1 /* XXX */
 #define cpu_has_k6_mtrr        0
 #define cpu_has_cyrix_arr      0
--- diff/include/asm-x86_64/msr.h	2003-12-19 09:51:11.000000000 +0000
+++ source/include/asm-x86_64/msr.h	2004-02-23 13:56:47.000000000 +0000
@@ -121,6 +121,9 @@ extern inline unsigned int cpuid_edx(uns
 	return edx;
 }
 
+#define MSR_IA32_UCODE_WRITE		0x79
+#define MSR_IA32_UCODE_REV		0x8b
+
 
 #endif
 
@@ -243,4 +246,123 @@ extern inline unsigned int cpuid_edx(uns
 #define MSR_IA32_APICBASE_ENABLE        (1<<11)
 #define MSR_IA32_APICBASE_BASE          (0xfffff<<12)
 
+/* P4/Xeon+ specific */
+#define MSR_IA32_MCG_EAX		0x180
+#define MSR_IA32_MCG_EBX		0x181
+#define MSR_IA32_MCG_ECX		0x182
+#define MSR_IA32_MCG_EDX		0x183
+#define MSR_IA32_MCG_ESI		0x184
+#define MSR_IA32_MCG_EDI		0x185
+#define MSR_IA32_MCG_EBP		0x186
+#define MSR_IA32_MCG_ESP		0x187
+#define MSR_IA32_MCG_EFLAGS		0x188
+#define MSR_IA32_MCG_EIP		0x189
+#define MSR_IA32_MCG_RESERVED		0x18A
+
+#define MSR_P6_EVNTSEL0			0x186
+#define MSR_P6_EVNTSEL1			0x187
+
+#define MSR_IA32_PERF_STATUS		0x198
+#define MSR_IA32_PERF_CTL		0x199
+
+#define MSR_IA32_THERM_CONTROL		0x19a
+#define MSR_IA32_THERM_INTERRUPT	0x19b
+#define MSR_IA32_THERM_STATUS		0x19c
+#define MSR_IA32_MISC_ENABLE		0x1a0
+
+#define MSR_IA32_DEBUGCTLMSR		0x1d9
+#define MSR_IA32_LASTBRANCHFROMIP	0x1db
+#define MSR_IA32_LASTBRANCHTOIP		0x1dc
+#define MSR_IA32_LASTINTFROMIP		0x1dd
+#define MSR_IA32_LASTINTTOIP		0x1de
+
+#define MSR_IA32_MC0_CTL		0x400
+#define MSR_IA32_MC0_STATUS		0x401
+#define MSR_IA32_MC0_ADDR		0x402
+#define MSR_IA32_MC0_MISC		0x403
+
+/* Pentium IV performance counter MSRs */
+#define MSR_P4_BPU_PERFCTR0 		0x300
+#define MSR_P4_BPU_PERFCTR1 		0x301
+#define MSR_P4_BPU_PERFCTR2 		0x302
+#define MSR_P4_BPU_PERFCTR3 		0x303
+#define MSR_P4_MS_PERFCTR0 		0x304
+#define MSR_P4_MS_PERFCTR1 		0x305
+#define MSR_P4_MS_PERFCTR2 		0x306
+#define MSR_P4_MS_PERFCTR3 		0x307
+#define MSR_P4_FLAME_PERFCTR0 		0x308
+#define MSR_P4_FLAME_PERFCTR1 		0x309
+#define MSR_P4_FLAME_PERFCTR2 		0x30a
+#define MSR_P4_FLAME_PERFCTR3 		0x30b
+#define MSR_P4_IQ_PERFCTR0 		0x30c
+#define MSR_P4_IQ_PERFCTR1 		0x30d
+#define MSR_P4_IQ_PERFCTR2 		0x30e
+#define MSR_P4_IQ_PERFCTR3 		0x30f
+#define MSR_P4_IQ_PERFCTR4 		0x310
+#define MSR_P4_IQ_PERFCTR5 		0x311
+#define MSR_P4_BPU_CCCR0 		0x360
+#define MSR_P4_BPU_CCCR1 		0x361
+#define MSR_P4_BPU_CCCR2 		0x362
+#define MSR_P4_BPU_CCCR3 		0x363
+#define MSR_P4_MS_CCCR0 		0x364
+#define MSR_P4_MS_CCCR1 		0x365
+#define MSR_P4_MS_CCCR2 		0x366
+#define MSR_P4_MS_CCCR3 		0x367
+#define MSR_P4_FLAME_CCCR0 		0x368
+#define MSR_P4_FLAME_CCCR1 		0x369
+#define MSR_P4_FLAME_CCCR2 		0x36a
+#define MSR_P4_FLAME_CCCR3 		0x36b
+#define MSR_P4_IQ_CCCR0 		0x36c
+#define MSR_P4_IQ_CCCR1 		0x36d
+#define MSR_P4_IQ_CCCR2 		0x36e
+#define MSR_P4_IQ_CCCR3 		0x36f
+#define MSR_P4_IQ_CCCR4 		0x370
+#define MSR_P4_IQ_CCCR5 		0x371
+#define MSR_P4_ALF_ESCR0 		0x3ca
+#define MSR_P4_ALF_ESCR1 		0x3cb
+#define MSR_P4_BPU_ESCR0 		0x3b2
+#define MSR_P4_BPU_ESCR1 		0x3b3
+#define MSR_P4_BSU_ESCR0 		0x3a0
+#define MSR_P4_BSU_ESCR1 		0x3a1
+#define MSR_P4_CRU_ESCR0 		0x3b8
+#define MSR_P4_CRU_ESCR1 		0x3b9
+#define MSR_P4_CRU_ESCR2 		0x3cc
+#define MSR_P4_CRU_ESCR3 		0x3cd
+#define MSR_P4_CRU_ESCR4 		0x3e0
+#define MSR_P4_CRU_ESCR5 		0x3e1
+#define MSR_P4_DAC_ESCR0 		0x3a8
+#define MSR_P4_DAC_ESCR1 		0x3a9
+#define MSR_P4_FIRM_ESCR0 		0x3a4
+#define MSR_P4_FIRM_ESCR1 		0x3a5
+#define MSR_P4_FLAME_ESCR0 		0x3a6
+#define MSR_P4_FLAME_ESCR1 		0x3a7
+#define MSR_P4_FSB_ESCR0 		0x3a2
+#define MSR_P4_FSB_ESCR1 		0x3a3
+#define MSR_P4_IQ_ESCR0 		0x3ba
+#define MSR_P4_IQ_ESCR1 		0x3bb
+#define MSR_P4_IS_ESCR0 		0x3b4
+#define MSR_P4_IS_ESCR1 		0x3b5
+#define MSR_P4_ITLB_ESCR0 		0x3b6
+#define MSR_P4_ITLB_ESCR1 		0x3b7
+#define MSR_P4_IX_ESCR0 		0x3c8
+#define MSR_P4_IX_ESCR1 		0x3c9
+#define MSR_P4_MOB_ESCR0 		0x3aa
+#define MSR_P4_MOB_ESCR1 		0x3ab
+#define MSR_P4_MS_ESCR0 		0x3c0
+#define MSR_P4_MS_ESCR1 		0x3c1
+#define MSR_P4_PMH_ESCR0 		0x3ac
+#define MSR_P4_PMH_ESCR1 		0x3ad
+#define MSR_P4_RAT_ESCR0 		0x3bc
+#define MSR_P4_RAT_ESCR1 		0x3bd
+#define MSR_P4_SAAT_ESCR0 		0x3ae
+#define MSR_P4_SAAT_ESCR1 		0x3af
+#define MSR_P4_SSU_ESCR0 		0x3be
+#define MSR_P4_SSU_ESCR1 		0x3bf    /* guess: not defined in manual */
+#define MSR_P4_TBPU_ESCR0 		0x3c2
+#define MSR_P4_TBPU_ESCR1 		0x3c3
+#define MSR_P4_TC_ESCR0 		0x3c4
+#define MSR_P4_TC_ESCR1 		0x3c5
+#define MSR_P4_U2L_ESCR0 		0x3b0
+#define MSR_P4_U2L_ESCR1 		0x3b1
+
 #endif
--- diff/include/asm-x86_64/param.h	2002-11-11 11:09:30.000000000 +0000
+++ source/include/asm-x86_64/param.h	2004-02-23 13:56:47.000000000 +0000
@@ -13,10 +13,6 @@
 
 #define EXEC_PAGESIZE	4096
 
-#ifndef NGROUPS
-#define NGROUPS		32
-#endif
-
 #ifndef NOGROUP
 #define NOGROUP		(-1)
 #endif
--- diff/include/asm-x86_64/pci.h	2004-02-18 08:54:13.000000000 +0000
+++ source/include/asm-x86_64/pci.h	2004-02-23 13:56:47.000000000 +0000
@@ -72,6 +72,23 @@ extern void *pci_alloc_consistent(struct
 extern void pci_free_consistent(struct pci_dev *hwdev, size_t size,
 				void *vaddr, dma_addr_t dma_handle);
 
+#ifdef CONFIG_SWIOTLB
+extern int swiotlb; 
+extern dma_addr_t swiotlb_map_single (struct device *hwdev, void *ptr, size_t size, 
+				      int dir);
+extern void swiotlb_unmap_single (struct device *hwdev, dma_addr_t dev_addr,
+				  size_t size, int dir);
+extern void swiotlb_sync_single (struct device *hwdev, dma_addr_t dev_addr, 
+				 size_t size, int dir);
+extern void swiotlb_sync_sg (struct device *hwdev, struct scatterlist *sg, int nelems, 
+			     int dir);
+extern int swiotlb_map_sg(struct device *hwdev, struct scatterlist *sg,
+		      int nents, int direction);
+extern void swiotlb_unmap_sg(struct device *hwdev, struct scatterlist *sg,
+			 int nents, int direction);
+
+#endif
+
 #ifdef CONFIG_GART_IOMMU
 
 /* Map a single buffer of the indicated size for DMA in streaming mode.
@@ -113,6 +130,13 @@ static inline void pci_dma_sync_single(s
 				       size_t size, int direction)
 {
 	BUG_ON(direction == PCI_DMA_NONE); 
+
+#ifdef CONFIG_SWIOTLB
+	if (swiotlb)
+		return swiotlb_sync_single(&hwdev->dev,dma_handle,size,direction);
+#endif
+
+	flush_write_buffers();
 } 
 
 static inline void pci_dma_sync_sg(struct pci_dev *hwdev, 
@@ -120,6 +144,12 @@ static inline void pci_dma_sync_sg(struc
 				   int nelems, int direction)
 { 
 	BUG_ON(direction == PCI_DMA_NONE); 
+
+#ifdef CONFIG_SWIOTLB
+	if (swiotlb)
+		return swiotlb_sync_sg(&hwdev->dev,sg,nelems,direction);
+#endif
+	flush_write_buffers();
 } 
 
 /* The PCI address space does equal the physical memory
@@ -272,4 +302,6 @@ static inline void pcibios_add_platform_
 /* generic pci stuff */
 #include <asm-generic/pci.h>
 
+#include <linux/dma-mapping.h>
+
 #endif /* __x8664_PCI_H */
--- diff/include/asm-x86_64/processor.h	2004-02-09 10:36:12.000000000 +0000
+++ source/include/asm-x86_64/processor.h	2004-02-23 13:56:47.000000000 +0000
@@ -303,6 +303,67 @@ extern unsigned long get_wchan(struct ta
 	(((struct pt_regs *)(tsk->thread.rsp0 - sizeof(struct pt_regs)))->rip)
 #define KSTK_ESP(tsk) -1 /* sorry. doesn't work for syscall. */
 
+
+struct microcode_header {
+	unsigned int hdrver;
+	unsigned int rev;
+	unsigned int date;
+	unsigned int sig;
+	unsigned int cksum;
+	unsigned int ldrver;
+	unsigned int pf;
+	unsigned int datasize;
+	unsigned int totalsize;
+	unsigned int reserved[3];
+};
+
+struct microcode {
+	struct microcode_header hdr;
+	unsigned int bits[0];
+};
+
+typedef struct microcode microcode_t;
+typedef struct microcode_header microcode_header_t;
+
+/* microcode format is extended from prescott processors */
+struct extended_signature {
+	unsigned int sig;
+	unsigned int pf;
+	unsigned int cksum;
+};
+
+struct extended_sigtable {
+	unsigned int count;
+	unsigned int cksum;
+	unsigned int reserved[3];
+	struct extended_signature sigs[0];
+};
+
+/* '6' because it used to be for P6 only (but now covers Pentium 4 as well) */
+#define MICROCODE_IOCFREE	_IO('6',0)
+
+
+#define ASM_NOP1 K8_NOP1
+#define ASM_NOP2 K8_NOP2
+#define ASM_NOP3 K8_NOP3
+#define ASM_NOP4 K8_NOP4
+#define ASM_NOP5 K8_NOP5
+#define ASM_NOP6 K8_NOP6
+#define ASM_NOP7 K8_NOP7
+#define ASM_NOP8 K8_NOP8
+
+/* Opteron nops */
+#define K8_NOP1 ".byte 0x90\n"
+#define K8_NOP2	".byte 0x66,0x90\n" 
+#define K8_NOP3	".byte 0x66,0x66,0x90\n" 
+#define K8_NOP4	".byte 0x66,0x66,0x66,0x90\n" 
+#define K8_NOP5	K8_NOP3 K8_NOP2 
+#define K8_NOP6	K8_NOP3 K8_NOP3
+#define K8_NOP7	K8_NOP4 K8_NOP3
+#define K8_NOP8	K8_NOP4 K8_NOP4
+
+#define ASM_NOP_MAX 8
+
 /* REP NOP (PAUSE) is a good thing to insert into busy-wait loops. */
 extern inline void rep_nop(void)
 {
@@ -318,31 +379,25 @@ extern inline void sync_core(void)
 
 #define cpu_has_fpu 1
 
-/* Some early Opteron versions incorrectly fault on prefetch (errata #91). 
-   If this happens just jump back. */
 #define ARCH_HAS_PREFETCH
 static inline void prefetch(void *x) 
 { 
-	asm volatile("2: prefetcht0 %0\n1:\t" 
-		    ".section __ex_table,\"a\"\n\t"
-		    "  .align 8\n\t"
-		    "  .quad  2b,1b\n\t"
-		    ".previous" :: "m" (*(unsigned long *)x));
+	asm volatile("prefetcht0 %0" :: "m" (*(unsigned long *)x));
 } 
 
-#define ARCH_HAS_PREFETCHW
+#define ARCH_HAS_PREFETCHW 1
 static inline void prefetchw(void *x) 
 { 
-	asm volatile("2: prefetchw %0\n1:\t" 
-		    ".section __ex_table,\"a\"\n\t"
-		    "  .align 8\n\t"
-		    "  .quad  2b,1b\n\t"
-		    ".previous" :: "m" (*(unsigned long *)x));
+	alternative_input(ASM_NOP4,
+			  "prefetchw (%1)",
+			  X86_FEATURE_3DNOW,
+			  "r" (x));
 } 
 
-#define ARCH_HAS_SPINLOCK_PREFETCH
+#define ARCH_HAS_SPINLOCK_PREFETCH 1
 
 #define spin_lock_prefetch(x)  prefetchw(x)
+
 #define cpu_relax()   rep_nop()
 
 /*
@@ -372,6 +427,23 @@ static inline void prefetchw(void *x) 
 	outb((data), 0x23); \
 } while (0)
 
+static inline void __monitor(const void *eax, unsigned long ecx,
+		unsigned long edx)
+{
+	/* "monitor %eax,%ecx,%edx;" */
+	asm volatile(
+		".byte 0x0f,0x01,0xc8;"
+		: :"a" (eax), "c" (ecx), "d"(edx));
+}
+
+static inline void __mwait(unsigned long eax, unsigned long ecx)
+{
+	/* "mwait %eax,%ecx;" */
+	asm volatile(
+		".byte 0x0f,0x01,0xc9;"
+		: :"a" (eax), "c" (ecx));
+}
+
 #define stack_current() \
 ({								\
 	struct thread_info *ti;					\
@@ -379,25 +451,4 @@ static inline void prefetchw(void *x) 
 	ti->task;					\
 })
 
-#define ASM_NOP1 K8_NOP1
-#define ASM_NOP2 K8_NOP2
-#define ASM_NOP3 K8_NOP3
-#define ASM_NOP4 K8_NOP4
-#define ASM_NOP5 K8_NOP5
-#define ASM_NOP6 K8_NOP6
-#define ASM_NOP7 K8_NOP7
-#define ASM_NOP8 K8_NOP8
-
-/* Opteron nops */
-#define K8_NOP1 ".byte 0x90\n"
-#define K8_NOP2	".byte 0x66,0x90\n" 
-#define K8_NOP3	".byte 0x66,0x66,0x90\n" 
-#define K8_NOP4	".byte 0x66,0x66,0x66,0x90\n" 
-#define K8_NOP5	K8_NOP3 K8_NOP2 
-#define K8_NOP6	K8_NOP3 K8_NOP3
-#define K8_NOP7	K8_NOP4 K8_NOP3
-#define K8_NOP8	K8_NOP4 K8_NOP4
-
-#define ASM_NOP_MAX 8
-
 #endif /* __ASM_X86_64_PROCESSOR_H */
--- diff/include/asm-x86_64/proto.h	2004-02-09 10:36:12.000000000 +0000
+++ source/include/asm-x86_64/proto.h	2004-02-23 13:56:47.000000000 +0000
@@ -24,7 +24,6 @@ extern void ia32_cstar_target(void); 
 
 extern void calibrate_delay(void);
 extern void cpu_idle(void);
-extern void sys_ni_syscall(void);
 extern void config_acpi_tables(void);
 extern void ia32_syscall(void);
 extern void iommu_hole_init(void);
@@ -76,6 +75,10 @@ extern void check_ioapic(void);
 
 extern int unhandled_signal(struct task_struct *tsk, int sig);
 
+extern void select_idle_routine(const struct cpuinfo_x86 *c);
+extern void swiotlb_init(void);
+extern int swiotlb;
+
 extern unsigned long max_mapnr;
 extern unsigned long end_pfn; 
 extern unsigned long table_start, table_end;
@@ -92,6 +95,7 @@ extern int acpi_disabled;
 
 extern int fallback_aper_order;
 extern int fallback_aper_force;
+extern int iommu_aperture;
 
 extern void smp_local_timer_interrupt(struct pt_regs * regs);
 
--- diff/include/asm-x86_64/segment.h	2003-06-09 14:18:20.000000000 +0100
+++ source/include/asm-x86_64/segment.h	2004-02-23 13:56:47.000000000 +0000
@@ -1,6 +1,8 @@
 #ifndef _ASM_SEGMENT_H
 #define _ASM_SEGMENT_H
 
+#include <asm/cache.h>
+
 #define __KERNEL_CS	0x10
 #define __KERNEL_DS	0x18
 
--- diff/include/asm-x86_64/smp.h	2004-02-09 10:36:12.000000000 +0000
+++ source/include/asm-x86_64/smp.h	2004-02-23 13:56:47.000000000 +0000
@@ -39,6 +39,7 @@ extern void smp_alloc_memory(void);
 extern cpumask_t cpu_online_map;
 extern volatile unsigned long smp_invalidate_needed;
 extern int pic_mode;
+extern int smp_num_siblings;
 extern void smp_flush_tlb(void);
 extern void smp_message_irq(int cpl, void *dev_id, struct pt_regs *regs);
 extern void smp_send_reschedule(int cpu);
@@ -46,7 +47,7 @@ extern void smp_invalidate_rcv(void);		/
 extern void (*mtrr_hook) (void);
 extern void zap_low_mappings(void);
 void smp_stop_cpu(void);
-
+extern int cpu_sibling_map[];
 
 #define SMP_TRAMPOLINE_BASE 0x6000
 
--- diff/include/asm-x86_64/system.h	2004-02-09 10:36:12.000000000 +0000
+++ source/include/asm-x86_64/system.h	2004-02-23 13:56:47.000000000 +0000
@@ -88,6 +88,56 @@ struct alt_instr { 
 #endif
 
 /*
+ * Alternative instructions for different CPU types or capabilities.
+ * 
+ * This allows to use optimized instructions even on generic binary
+ * kernels.
+ * 
+ * length of oldinstr must be longer or equal the length of newinstr
+ * It can be padded with nops as needed.
+ * 
+ * For non barrier like inlines please define new variants
+ * without volatile and memory clobber.
+ */
+#define alternative(oldinstr, newinstr, feature) 	\
+	asm volatile ("661:\n\t" oldinstr "\n662:\n" 		     \
+		      ".section .altinstructions,\"a\"\n"     	     \
+		      "  .align 8\n"				       \
+		      "  .quad 661b\n"            /* label */          \
+		      "  .quad 663f\n"		  /* new instruction */ \
+		      "  .byte %c0\n"             /* feature bit */    \
+		      "  .byte 662b-661b\n"       /* sourcelen */      \
+		      "  .byte 664f-663f\n"       /* replacementlen */ \
+		      ".previous\n"					\
+		      ".section .altinstr_replacement,\"ax\"\n"		\
+		      "663:\n\t" newinstr "\n664:\n"   /* replacement */ \
+		      ".previous" :: "i" (feature) : "memory")  
+
+/*
+ * Alternative inline assembly with input.
+ * 
+ * Pecularities:
+ * No memory clobber here. 
+ * Argument numbers start with 1.
+ * Best is to use constraints that are fixed size (like (%1) ... "r")
+ * If you use variable sized constraints like "m" or "g" in the 
+ * replacement maake sure to pad to the worst case length.
+ */
+#define alternative_input(oldinstr, newinstr, feature, input)		\
+	asm volatile ("661:\n\t" oldinstr "\n662:\n"			\
+		      ".section .altinstructions,\"a\"\n"		\
+		      "  .align 8\n"					\
+		      "  .quad 661b\n"            /* label */		\
+		      "  .quad 663f\n"		  /* new instruction */	\
+		      "  .byte %c0\n"             /* feature bit */	\
+		      "  .byte 662b-661b\n"       /* sourcelen */	\
+		      "  .byte 664f-663f\n"       /* replacementlen */	\
+		      ".previous\n"					\
+		      ".section .altinstr_replacement,\"ax\"\n"		\
+		      "663:\n\t" newinstr "\n664:\n"   /* replacement */ \
+		      ".previous" :: "i" (feature), input)
+
+/*
  * Clear and set 'TS' bit respectively
  */
 #define clts() __asm__ __volatile__ ("clts")
--- diff/include/asm-x86_64/unistd.h	2004-02-09 10:36:12.000000000 +0000
+++ source/include/asm-x86_64/unistd.h	2004-02-23 13:56:47.000000000 +0000
@@ -636,6 +636,9 @@ __syscall_return(type,__res); \
 
 #else /* __KERNEL_SYSCALLS__ */
 
+#include <linux/syscalls.h>
+#include <asm/ptrace.h>
+
 /*
  * we need this inline - forking from kernel space will result
  * in NO COPY ON WRITE (!!!), until an execve is executed. This
@@ -650,31 +653,26 @@ __syscall_return(type,__res); \
  */
 #define __NR__exit __NR_exit
 
-extern pid_t sys_setsid(void);
 static inline pid_t setsid(void)
 {
 	return sys_setsid();
 }
 
-long sys_write(int fd, const char *buf, size_t size);
 static inline ssize_t write(unsigned int fd, char * buf, size_t count)
 {
 	return sys_write(fd, buf, count);
 }
 
-extern ssize_t sys_read(unsigned int, char *, size_t);
 static inline ssize_t read(unsigned int fd, char * buf, size_t count)
 {
 	return sys_read(fd, buf, count);
 }
 
-extern off_t sys_lseek(unsigned int, off_t, unsigned int);
 static inline off_t lseek(unsigned int fd, off_t offset, unsigned int origin)
 {
 	return sys_lseek(fd, offset, origin);
 }
 
-extern long sys_dup(unsigned int);
 static inline long dup(unsigned int fd)
 {
 	return sys_dup(fd);
@@ -683,34 +681,50 @@ static inline long dup(unsigned int fd)
 /* implemented in asm in arch/x86_64/kernel/entry.S */
 extern long execve(char *, char **, char **);
 
-extern long sys_open(const char *, int, int);
 static inline long open(const char * filename, int flags, int mode)
 {
 	return sys_open(filename, flags, mode);
 }
 
-extern long sys_close(unsigned int);
 static inline long close(unsigned int fd)
 {
 	return sys_close(fd);
 }
 
-extern long sys_exit(int) __attribute__((noreturn));
-extern inline void exit(int error_code)
-{
-	sys_exit(error_code);
-}
-
-struct rusage; 
-long sys_wait4(pid_t pid,unsigned int * stat_addr, 
-			int options, struct rusage * ru);
 static inline pid_t waitpid(int pid, int * wait_stat, int flags)
 {
 	return sys_wait4(pid, wait_stat, flags, NULL);
 }
 
+extern long sys_mmap(unsigned long addr, unsigned long len,
+			unsigned long prot, unsigned long flags,
+			unsigned long fd, unsigned long off);
+
+extern int sys_modify_ldt(int func, void *ptr, unsigned long bytecount);
+
+asmlinkage long sys_execve(char *name, char **argv, char **envp,
+			struct pt_regs regs);
+asmlinkage long sys_clone(unsigned long clone_flags, unsigned long newsp,
+			void *parent_tid, void *child_tid,
+			struct pt_regs regs);
+asmlinkage long sys_fork(struct pt_regs regs);
+asmlinkage long sys_vfork(struct pt_regs regs);
+asmlinkage long sys_pipe(int *fildes);
+
 #endif /* __KERNEL_SYSCALLS__ */
 
+#ifndef __ASSEMBLY__
+
+#include <linux/linkage.h>
+#include <asm/ptrace.h>
+
+asmlinkage long sys_ptrace(long request, long pid,
+				unsigned long addr, long data);
+asmlinkage long sys_iopl(unsigned int level, struct pt_regs regs);
+asmlinkage long sys_ioperm(unsigned long from, unsigned long num, int turn_on);
+
+#endif	/* __ASSEMBLY__ */
+
 #endif /* __NO_STUBS */
 
 /*
--- diff/include/linux/acpi.h	2004-02-18 08:54:13.000000000 +0000
+++ source/include/linux/acpi.h	2004-02-23 13:56:47.000000000 +0000
@@ -317,6 +317,15 @@ struct acpi_table_ecdt {
 	char				ec_id[0];
 } __attribute__ ((packed));
 
+/* PCI MMCONFIG */
+
+struct acpi_table_mcfg {
+	struct acpi_table_header	header;
+	u8				reserved[8];
+	u32				base_address;
+	u32				base_reserved;
+} __attribute__ ((packed));
+
 /* Table Handlers */
 
 enum acpi_table_id {
@@ -338,6 +347,7 @@ enum acpi_table_id {
 	ACPI_SSDT,
 	ACPI_SPMI,
 	ACPI_HPET,
+	ACPI_MCFG,
 	ACPI_TABLE_COUNT
 };
 
@@ -369,6 +379,8 @@ void acpi_numa_arch_fixup(void);
 
 extern int acpi_mp_config;
 
+extern u32 pci_mmcfg_base_addr;
+
 #else	/*!CONFIG_ACPI_BOOT*/
 
 #define acpi_mp_config	0
--- diff/include/linux/aio.h	2003-10-09 09:47:17.000000000 +0100
+++ source/include/linux/aio.h	2004-02-23 13:56:47.000000000 +0000
@@ -167,6 +167,7 @@ static inline struct kiocb *list_kiocb(s
 }
 
 /* for sysctl: */
-extern unsigned aio_max_nr, aio_max_size, aio_max_pinned;
+extern atomic_t aio_nr;
+extern unsigned aio_max_nr;
 
 #endif /* __LINUX__AIO_H */
--- diff/include/linux/binfmts.h	2003-08-20 14:16:34.000000000 +0100
+++ source/include/linux/binfmts.h	2004-02-23 13:56:47.000000000 +0000
@@ -35,9 +35,13 @@ struct linux_binprm{
 	char * interp;		/* Name of the binary really executed. Most
 				   of the time same as filename, but could be
 				   different for binfmt_{misc,script} */
+	unsigned long interp_flags;
 	unsigned long loader, exec;
 };
 
+#define BINPRM_FLAGS_ENFORCE_NONDUMP_BIT 0
+#define BINPRM_FLAGS_ENFORCE_NONDUMP (1 << BINPRM_FLAGS_ENFORCE_NONDUMP_BIT)
+
 /*
  * This structure defines the functions that are used to load the binary formats that
  * linux accepts.
--- diff/include/linux/bitmap.h	2004-02-18 08:54:13.000000000 +0000
+++ source/include/linux/bitmap.h	2004-02-23 13:56:47.000000000 +0000
@@ -41,7 +41,7 @@ void bitmap_and(unsigned long *dst, cons
 void bitmap_or(unsigned long *dst, const unsigned long *bitmap1,
 			const unsigned long *bitmap2, int bits);
 int bitmap_weight(const unsigned long *bitmap, int bits);
-int bitmap_snprintf(char *buf, unsigned int buflen,
+int bitmap_scnprintf(char *buf, unsigned int buflen,
 			const unsigned long *maskp, int bits);
 int bitmap_parse(const char __user *ubuf, unsigned int ubuflen,
 			unsigned long *maskp, int bits);
--- diff/include/linux/blkdev.h	2004-02-18 08:54:13.000000000 +0000
+++ source/include/linux/blkdev.h	2004-02-23 13:56:47.000000000 +0000
@@ -586,7 +586,7 @@ extern int blk_queue_init_tags(request_q
 extern void blk_queue_free_tags(request_queue_t *);
 extern int blk_queue_resize_tags(request_queue_t *, int);
 extern void blk_queue_invalidate_tags(request_queue_t *);
-extern void blk_congestion_wait(int rw, long timeout);
+extern long blk_congestion_wait(int rw, long timeout);
 
 extern void blk_rq_bio_prep(request_queue_t *, struct request *, struct bio *);
 extern void blk_rq_prep_restart(struct request *);
--- diff/include/linux/compat.h	2004-02-09 10:36:12.000000000 +0000
+++ source/include/linux/compat.h	2004-02-23 13:56:47.000000000 +0000
@@ -6,15 +6,27 @@
  */
 #include <linux/config.h>
 
-#ifdef CONFIG_COMPAT
+#ifndef CONFIG_COMPAT
+
+/* Non-native task requiring compat... doesn't exist */
+#define is_compat_task(x) 0
+
+#else
 
 #include <linux/stat.h>
 #include <linux/param.h>	/* for HZ */
+#include <linux/sem.h>
+#include <linux/personality.h>  /* Conditional process compat */
 #include <asm/compat.h>
 
 #define compat_jiffies_to_clock_t(x)	\
 		(((unsigned long)(x) * COMPAT_USER_HZ) / HZ)
 
+/* Non-native task requiring compat */
+#ifndef HAVE_ARCH_IS_COMPAT_TASK
+#define is_compat_task(x) (x->personality == PER_LINUX32)
+#endif
+
 struct compat_itimerspec { 
 	struct compat_timespec it_interval;
 	struct compat_timespec it_value;
@@ -83,10 +95,15 @@ struct compat_dirent {
 	char		d_name[256];
 };
 
-typedef union compat_sigval {
-	compat_int_t	sival_int;
-	compat_uptr_t	sival_ptr;
-} compat_sigval_t;
-
+long compat_sys_semctl(int first, int second, int third, void __user *uptr);
+long compat_sys_msgsnd(int first, int second, int third, void __user *uptr);
+long compat_sys_msgrcv(int first, int second, int msgtyp, int third,
+		int version, void __user *uptr);
+long compat_sys_msgctl(int first, int second, void __user *uptr);
+long compat_sys_shmat(int first, int second, compat_uptr_t third, int version,
+		void __user *uptr);
+long compat_sys_shmctl(int first, int second, void __user *uptr);
+long compat_sys_semtimedop(int semid, struct sembuf __user *tsems,
+		unsigned nsems, const struct compat_timespec __user *timeout);
 #endif /* CONFIG_COMPAT */
 #endif /* _LINUX_COMPAT_H */
--- diff/include/linux/compat_ioctl.h	2004-02-09 10:36:12.000000000 +0000
+++ source/include/linux/compat_ioctl.h	2004-02-23 13:56:47.000000000 +0000
@@ -140,13 +140,6 @@ COMPATIBLE_IOCTL(DM_VERSION)
 COMPATIBLE_IOCTL(DM_REMOVE_ALL)
 COMPATIBLE_IOCTL(DM_DEV_CREATE)
 COMPATIBLE_IOCTL(DM_DEV_REMOVE)
-COMPATIBLE_IOCTL(DM_DEV_RELOAD)
-COMPATIBLE_IOCTL(DM_DEV_SUSPEND)
-COMPATIBLE_IOCTL(DM_DEV_RENAME)
-COMPATIBLE_IOCTL(DM_DEV_DEPS)
-COMPATIBLE_IOCTL(DM_DEV_STATUS)
-COMPATIBLE_IOCTL(DM_TARGET_STATUS)
-COMPATIBLE_IOCTL(DM_TARGET_WAIT)
 #endif
 /* Big K */
 COMPATIBLE_IOCTL(PIO_FONT)
--- diff/include/linux/compiler-gcc.h	2003-10-09 09:47:17.000000000 +0100
+++ source/include/linux/compiler-gcc.h	2004-02-23 13:56:47.000000000 +0000
@@ -13,5 +13,5 @@
    shouldn't recognize the original var, and make assumptions about it */
 #define RELOC_HIDE(ptr, off)					\
   ({ unsigned long __ptr;					\
-    __asm__ ("" : "=g"(__ptr) : "0"(ptr));		\
+	__asm__ ("" : "=r"(__ptr) : "0"(ptr));			\
     (typeof(ptr)) (__ptr + (off)); })
--- diff/include/linux/compiler-gcc3.h	2004-02-09 10:36:12.000000000 +0000
+++ source/include/linux/compiler-gcc3.h	2004-02-23 13:56:47.000000000 +0000
@@ -21,3 +21,7 @@
 
 #define __attribute_pure__	__attribute__((pure))
 #define __attribute_const__	__attribute__((__const__))
+
+#if __GNUC_MINOR__ >= 1
+#define  noinline __attribute__((noinline))
+#endif
--- diff/include/linux/compiler.h	2004-02-18 08:54:13.000000000 +0000
+++ source/include/linux/compiler.h	2004-02-23 13:56:47.000000000 +0000
@@ -96,6 +96,10 @@
 # define __attribute_const__	/* unimplemented */
 #endif
 
+#ifndef noinline
+#define noinline
+#endif
+
 /* Optimization barrier */
 #ifndef barrier
 # define barrier() __memory_barrier()
--- diff/include/linux/concap.h	2002-10-16 04:27:51.000000000 +0100
+++ source/include/linux/concap.h	2004-02-23 13:56:47.000000000 +0000
@@ -1,4 +1,4 @@
-/* $Id: concap.h,v 1.2.8.1 2001/09/23 22:25:05 kai Exp $
+/* $Id: concap.h,v 1.3.2.2 2004/01/12 23:08:35 keil Exp $
  *
  * Copyright 1997 by Henner Eisen <eis@baty.hanse.de>
  *
@@ -31,6 +31,7 @@ struct concap_proto{
 	struct net_device *net_dev;	/* net device using our service  */
 	struct concap_device_ops *dops;	/* callbacks provided by device */
  	struct concap_proto_ops  *pops;	/* callbacks provided by us */
+ 	spinlock_t lock;
 	int flags;
 	void *proto_data;		/* protocol specific private data, to
 					   be accessed via *pops methods only*/
--- diff/include/linux/config.h	2003-10-09 09:47:17.000000000 +0100
+++ source/include/linux/config.h	2004-02-23 13:56:47.000000000 +0000
@@ -2,5 +2,8 @@
 #define _LINUX_CONFIG_H
 
 #include <linux/autoconf.h>
+#ifdef CONFIG_X86
+#include <asm/kgdb.h>
+#endif
 
 #endif
--- diff/include/linux/cpu.h	2004-02-18 08:54:13.000000000 +0000
+++ source/include/linux/cpu.h	2004-02-23 13:56:47.000000000 +0000
@@ -21,6 +21,8 @@
 
 #include <linux/sysdev.h>
 #include <linux/node.h>
+#include <linux/compiler.h>
+#include <linux/cpumask.h>
 #include <asm/semaphore.h>
 
 struct cpu {
@@ -56,9 +58,21 @@ extern struct sysdev_class cpu_sysdev_cl
 extern struct semaphore cpucontrol;
 #define lock_cpu_hotplug()	down(&cpucontrol)
 #define unlock_cpu_hotplug()	up(&cpucontrol)
+#define lock_cpu_hotplug_interruptible() down_interruptible(&cpucontrol)
+int cpu_down(unsigned int cpu);
+#define hotcpu_notifier(fn, pri) {				\
+	static struct notifier_block fn##_nb = { fn, pri };	\
+	register_cpu_notifier(&fn##_nb);			\
+}
+#define cpu_is_offline(cpu) unlikely(!cpu_online(cpu))
 #else
 #define lock_cpu_hotplug()	do { } while (0)
 #define unlock_cpu_hotplug()	do { } while (0)
+#define lock_cpu_hotplug_interruptible() 0
+#define hotcpu_notifier(fn, pri)
+
+/* CPUs don't go offline once they're online w/o CONFIG_HOTPLUG_CPU */
+#define cpu_is_offline(cpu) 0
 #endif
 
 #endif /* _LINUX_CPU_H_ */
--- diff/include/linux/cpufreq.h	2004-01-19 10:22:59.000000000 +0000
+++ source/include/linux/cpufreq.h	2004-02-23 13:56:47.000000000 +0000
@@ -110,24 +110,24 @@ struct cpufreq_freqs {
  * @div:   divisor
  * @mult:  multiplier
  *
- * Needed for loops_per_jiffy and similar calculations.  We do it 
- * this way to avoid math overflow on 32-bit machines.  This will
- * become architecture dependent once high-resolution-timer is
- * merged (or any other thing that introduces sc_math.h).
  *
  *    new = old * mult / div
  */
 static inline unsigned long cpufreq_scale(unsigned long old, u_int div, u_int mult)
 {
-	unsigned long val, carry;
+#if BITS_PER_LONG == 32
 
-	mult /= 100;
-	div  /= 100;
-        val   = (old / div) * mult;
-        carry = old % div;
-	carry = carry * mult / div;
+	u64 result = ((u64) old) * ((u64) mult);
+	do_div(result, div);
+	return (unsigned long) result;
 
-	return carry + val;
+#elif BITS_PER_LONG == 64
+
+	unsigned long result = old * ((u64) mult);
+	result /= div;
+	return result;
+
+#endif
 };
 
 /*********************************************************************
--- diff/include/linux/cpumask.h	2004-02-18 08:54:13.000000000 +0000
+++ source/include/linux/cpumask.h	2004-02-23 13:56:47.000000000 +0000
@@ -12,6 +12,7 @@ extern cpumask_t cpu_online_map;
 extern cpumask_t cpu_possible_map;
 
 #define num_online_cpus()		cpus_weight(cpu_online_map)
+#define num_possible_cpus()		cpus_weight(cpu_possible_map)
 #define cpu_online(cpu)			cpu_isset(cpu, cpu_online_map)
 #define cpu_possible(cpu)		cpu_isset(cpu, cpu_possible_map)
 
@@ -24,7 +25,9 @@ extern cpumask_t cpu_possible_map;
 #define for_each_online_cpu(cpu) for_each_cpu_mask(cpu, cpu_online_map)
 #else
 #define	cpu_online_map			cpumask_of_cpu(0)
+#define	cpu_possible_map		cpumask_of_cpu(0)
 #define num_online_cpus()		1
+#define num_possible_cpus()		1
 #define cpu_online(cpu)			({ BUG_ON((cpu) != 0); 1; })
 #define cpu_possible(cpu)		({ BUG_ON((cpu) != 0); 1; })
 
@@ -32,8 +35,8 @@ extern cpumask_t cpu_possible_map;
 #define for_each_online_cpu(cpu) for (cpu = 0; cpu < 1; cpu++)
 #endif
 
-#define cpumask_snprintf(buf, buflen, map)				\
-	bitmap_snprintf(buf, buflen, cpus_addr(map), NR_CPUS)
+#define cpumask_scnprintf(buf, buflen, map)				\
+	bitmap_scnprintf(buf, buflen, cpus_addr(map), NR_CPUS)
 
 #define cpumask_parse(buf, buflen, map)					\
 	bitmap_parse(buf, buflen, cpus_addr(map), NR_CPUS)
--- diff/include/linux/device-mapper.h	2003-06-30 10:07:24.000000000 +0100
+++ source/include/linux/device-mapper.h	2004-02-23 13:56:47.000000000 +0000
@@ -13,6 +13,11 @@ struct dm_dev;
 
 typedef enum { STATUSTYPE_INFO, STATUSTYPE_TABLE } status_type_t;
 
+union map_info {
+	void *ptr;
+	unsigned long long ll;
+};
+
 /*
  * In the constructor the target parameter will already have the
  * table, type, begin and len fields filled in.
@@ -32,7 +37,19 @@ typedef void (*dm_dtr_fn) (struct dm_tar
  * = 0: The target will handle the io by resubmitting it later
  * > 0: simple remap complete
  */
-typedef int (*dm_map_fn) (struct dm_target *ti, struct bio *bio);
+typedef int (*dm_map_fn) (struct dm_target *ti, struct bio *bio,
+			  union map_info *map_context);
+
+/*
+ * Returns:
+ * < 0 : error (currently ignored)
+ * 0   : ended successfully
+ * 1   : for some reason the io has still not completed (eg,
+ *       multipath target might want to requeue a failed io).
+ */
+typedef int (*dm_endio_fn) (struct dm_target *ti,
+			    struct bio *bio, int error,
+			    union map_info *map_context);
 
 typedef void (*dm_suspend_fn) (struct dm_target *ti);
 typedef void (*dm_resume_fn) (struct dm_target *ti);
@@ -57,9 +74,11 @@ void dm_put_device(struct dm_target *ti,
 struct target_type {
 	const char *name;
 	struct module *module;
+        unsigned version[3];
 	dm_ctr_fn ctr;
 	dm_dtr_fn dtr;
 	dm_map_fn map;
+	dm_endio_fn end_io;
 	dm_suspend_fn suspend;
 	dm_resume_fn resume;
 	dm_status_fn status;
@@ -86,7 +105,7 @@ struct dm_target {
 	sector_t split_io;
 
 	/*
-	 * These are automaticall filled in by
+	 * These are automatically filled in by
 	 * dm_table_get_device.
 	 */
 	struct io_restrictions limits;
--- diff/include/linux/devpts_fs.h	2002-10-16 04:28:33.000000000 +0100
+++ source/include/linux/devpts_fs.h	2004-02-23 13:56:47.000000000 +0000
@@ -2,7 +2,7 @@
  *
  * linux/include/linux/devpts_fs.h
  *
- *  Copyright 1998 H. Peter Anvin -- All Rights Reserved
+ *  Copyright 1998-2004 H. Peter Anvin -- All Rights Reserved
  *
  * This file is part of the Linux kernel and is made available under
  * the terms of the GNU General Public License, version 2, or at your
@@ -13,21 +13,22 @@
 #ifndef _LINUX_DEVPTS_FS_H
 #define _LINUX_DEVPTS_FS_H 1
 
-#ifdef CONFIG_DEVPTS_FS
+#include <linux/errno.h>
 
-void devpts_pty_new(int, dev_t);	/* mknod in devpts */
-void devpts_pty_kill(int);		/* unlink */
+#if CONFIG_UNIX98_PTYS
+
+int devpts_pty_new(struct tty_struct *); /* mknod in devpts */
+struct tty_struct *devpts_get_tty(int);	 /* get tty structure */
+void devpts_pty_kill(int);		 /* unlink */
 
 #else
 
-static inline void devpts_pty_new(int line, dev_t device)
-{
-}
-
-static inline void devpts_pty_kill(int line)
-{
-}
+/* Dummy stubs in the no-pty case */
+static inline int devpts_pty_new(struct tty_struct *) { return -EINVAL; }
+static inline struct tty_struct *devpts_get_tty(int)  { return NULL; }
+static inline void devpts_pty_kill(int) { }
 
 #endif
 
+
 #endif /* _LINUX_DEVPTS_FS_H */
--- diff/include/linux/dm-ioctl.h	2003-08-20 14:16:14.000000000 +0100
+++ source/include/linux/dm-ioctl.h	2004-02-23 13:56:47.000000000 +0000
@@ -1,18 +1,252 @@
 /*
- * Copyright (C) 2003 Sistina Software (UK) Limited.
+ * Copyright (C) 2001 - 2003 Sistina Software (UK) Limited.
  *
  * This file is released under the LGPL.
  */
 
-#ifndef _LINUX_DM_IOCTL_H
-#define _LINUX_DM_IOCTL_H
+#ifndef _LINUX_DM_IOCTL_V4_H
+#define _LINUX_DM_IOCTL_V4_H
 
-#include <linux/config.h>
+#include <linux/types.h>
 
-#ifdef CONFIG_DM_IOCTL_V4
-#include "dm-ioctl-v4.h"
-#else
-#include "dm-ioctl-v1.h"
-#endif
+#define DM_DIR "mapper"		/* Slashes not supported */
+#define DM_MAX_TYPE_NAME 16
+#define DM_NAME_LEN 128
+#define DM_UUID_LEN 129
 
-#endif
+/*
+ * A traditional ioctl interface for the device mapper.
+ *
+ * Each device can have two tables associated with it, an
+ * 'active' table which is the one currently used by io passing
+ * through the device, and an 'inactive' one which is a table
+ * that is being prepared as a replacement for the 'active' one.
+ *
+ * DM_VERSION:
+ * Just get the version information for the ioctl interface.
+ *
+ * DM_REMOVE_ALL:
+ * Remove all dm devices, destroy all tables.  Only really used
+ * for debug.
+ *
+ * DM_LIST_DEVICES:
+ * Get a list of all the dm device names.
+ *
+ * DM_DEV_CREATE:
+ * Create a new device, neither the 'active' or 'inactive' table
+ * slots will be filled.  The device will be in suspended state
+ * after creation, however any io to the device will get errored
+ * since it will be out-of-bounds.
+ *
+ * DM_DEV_REMOVE:
+ * Remove a device, destroy any tables.
+ *
+ * DM_DEV_RENAME:
+ * Rename a device.
+ *
+ * DM_SUSPEND:
+ * This performs both suspend and resume, depending which flag is
+ * passed in.
+ * Suspend: This command will not return until all pending io to
+ * the device has completed.  Further io will be deferred until
+ * the device is resumed.
+ * Resume: It is no longer an error to issue this command on an
+ * unsuspended device.  If a table is present in the 'inactive'
+ * slot, it will be moved to the active slot, then the old table
+ * from the active slot will be _destroyed_.  Finally the device
+ * is resumed.
+ *
+ * DM_DEV_STATUS:
+ * Retrieves the status for the table in the 'active' slot.
+ *
+ * DM_DEV_WAIT:
+ * Wait for a significant event to occur to the device.  This
+ * could either be caused by an event triggered by one of the
+ * targets of the table in the 'active' slot, or a table change.
+ *
+ * DM_TABLE_LOAD:
+ * Load a table into the 'inactive' slot for the device.  The
+ * device does _not_ need to be suspended prior to this command.
+ *
+ * DM_TABLE_CLEAR:
+ * Destroy any table in the 'inactive' slot (ie. abort).
+ *
+ * DM_TABLE_DEPS:
+ * Return a set of device dependencies for the 'active' table.
+ *
+ * DM_TABLE_STATUS:
+ * Return the targets status for the 'active' table.
+ */
+
+/*
+ * All ioctl arguments consist of a single chunk of memory, with
+ * this structure at the start.  If a uuid is specified any
+ * lookup (eg. for a DM_INFO) will be done on that, *not* the
+ * name.
+ */
+struct dm_ioctl {
+	/*
+	 * The version number is made up of three parts:
+	 * major - no backward or forward compatibility,
+	 * minor - only backwards compatible,
+	 * patch - both backwards and forwards compatible.
+	 *
+	 * All clients of the ioctl interface should fill in the
+	 * version number of the interface that they were
+	 * compiled with.
+	 *
+	 * All recognised ioctl commands (ie. those that don't
+	 * return -ENOTTY) fill out this field, even if the
+	 * command failed.
+	 */
+	uint32_t version[3];	/* in/out */
+	uint32_t data_size;	/* total size of data passed in
+				 * including this struct */
+
+	uint32_t data_start;	/* offset to start of data
+				 * relative to start of this struct */
+
+	uint32_t target_count;	/* in/out */
+	int32_t open_count;	/* out */
+	uint32_t flags;		/* in/out */
+	uint32_t event_nr;      	/* in/out */
+	uint32_t padding;
+
+	uint64_t dev;		/* in/out */
+
+	char name[DM_NAME_LEN];	/* device name */
+	char uuid[DM_UUID_LEN];	/* unique identifier for
+				 * the block device */
+};
+
+/*
+ * Used to specify tables.  These structures appear after the
+ * dm_ioctl.
+ */
+struct dm_target_spec {
+	uint64_t sector_start;
+	uint64_t length;
+	int32_t status;		/* used when reading from kernel only */
+
+	/*
+	 * Offset in bytes (from the start of this struct) to
+	 * next target_spec.
+	 */
+	uint32_t next;
+
+	char target_type[DM_MAX_TYPE_NAME];
+
+	/*
+	 * Parameter string starts immediately after this object.
+	 * Be careful to add padding after string to ensure correct
+	 * alignment of subsequent dm_target_spec.
+	 */
+};
+
+/*
+ * Used to retrieve the target dependencies.
+ */
+struct dm_target_deps {
+	uint32_t count;	/* Array size */
+	uint32_t padding;	/* unused */
+	uint64_t dev[0];	/* out */
+};
+
+/*
+ * Used to get a list of all dm devices.
+ */
+struct dm_name_list {
+	uint64_t dev;
+	uint32_t next;		/* offset to the next record from
+				   the _start_ of this */
+	char name[0];
+};
+
+/*
+ * Used to retrieve the target versions
+ */
+struct dm_target_versions {
+        uint32_t next;
+        uint32_t version[3];
+
+        char name[0];
+};
+
+/*
+ * If you change this make sure you make the corresponding change
+ * to dm-ioctl.c:lookup_ioctl()
+ */
+enum {
+	/* Top level cmds */
+	DM_VERSION_CMD = 0,
+	DM_REMOVE_ALL_CMD,
+	DM_LIST_DEVICES_CMD,
+
+	/* device level cmds */
+	DM_DEV_CREATE_CMD,
+	DM_DEV_REMOVE_CMD,
+	DM_DEV_RENAME_CMD,
+	DM_DEV_SUSPEND_CMD,
+	DM_DEV_STATUS_CMD,
+	DM_DEV_WAIT_CMD,
+
+	/* Table level cmds */
+	DM_TABLE_LOAD_CMD,
+	DM_TABLE_CLEAR_CMD,
+	DM_TABLE_DEPS_CMD,
+	DM_TABLE_STATUS_CMD,
+
+	/* Added later */
+	DM_LIST_VERSIONS_CMD,
+};
+
+#define DM_IOCTL 0xfd
+
+#define DM_VERSION       _IOWR(DM_IOCTL, DM_VERSION_CMD, struct dm_ioctl)
+#define DM_REMOVE_ALL    _IOWR(DM_IOCTL, DM_REMOVE_ALL_CMD, struct dm_ioctl)
+#define DM_LIST_DEVICES  _IOWR(DM_IOCTL, DM_LIST_DEVICES_CMD, struct dm_ioctl)
+
+#define DM_DEV_CREATE    _IOWR(DM_IOCTL, DM_DEV_CREATE_CMD, struct dm_ioctl)
+#define DM_DEV_REMOVE    _IOWR(DM_IOCTL, DM_DEV_REMOVE_CMD, struct dm_ioctl)
+#define DM_DEV_RENAME    _IOWR(DM_IOCTL, DM_DEV_RENAME_CMD, struct dm_ioctl)
+#define DM_DEV_SUSPEND   _IOWR(DM_IOCTL, DM_DEV_SUSPEND_CMD, struct dm_ioctl)
+#define DM_DEV_STATUS    _IOWR(DM_IOCTL, DM_DEV_STATUS_CMD, struct dm_ioctl)
+#define DM_DEV_WAIT      _IOWR(DM_IOCTL, DM_DEV_WAIT_CMD, struct dm_ioctl)
+
+#define DM_TABLE_LOAD    _IOWR(DM_IOCTL, DM_TABLE_LOAD_CMD, struct dm_ioctl)
+#define DM_TABLE_CLEAR   _IOWR(DM_IOCTL, DM_TABLE_CLEAR_CMD, struct dm_ioctl)
+#define DM_TABLE_DEPS    _IOWR(DM_IOCTL, DM_TABLE_DEPS_CMD, struct dm_ioctl)
+#define DM_TABLE_STATUS  _IOWR(DM_IOCTL, DM_TABLE_STATUS_CMD, struct dm_ioctl)
+
+#define DM_LIST_VERSIONS _IOWR(DM_IOCTL, DM_LIST_VERSIONS_CMD, struct dm_ioctl)
+
+#define DM_VERSION_MAJOR	4
+#define DM_VERSION_MINOR	1
+#define DM_VERSION_PATCHLEVEL	0
+#define DM_VERSION_EXTRA	"-ioctl (2003-12-10)"
+
+/* Status bits */
+#define DM_READONLY_FLAG	(1 << 0) /* In/Out */
+#define DM_SUSPEND_FLAG		(1 << 1) /* In/Out */
+#define DM_PERSISTENT_DEV_FLAG	(1 << 3) /* In */
+
+/*
+ * Flag passed into ioctl STATUS command to get table information
+ * rather than current status.
+ */
+#define DM_STATUS_TABLE_FLAG	(1 << 4) /* In */
+
+/*
+ * Flags that indicate whether a table is present in either of
+ * the two table slots that a device has.
+ */
+#define DM_ACTIVE_PRESENT_FLAG   (1 << 5) /* Out */
+#define DM_INACTIVE_PRESENT_FLAG (1 << 6) /* Out */
+
+/*
+ * Indicates that the buffer passed in wasn't big enough for the
+ * results.
+ */
+#define DM_BUFFER_FULL_FLAG	(1 << 8) /* Out */
+
+#endif				/* _LINUX_DM_IOCTL_H */
--- diff/include/linux/elevator.h	2004-02-18 08:54:13.000000000 +0000
+++ source/include/linux/elevator.h	2004-02-23 13:56:47.000000000 +0000
@@ -94,6 +94,11 @@ extern elevator_t iosched_deadline;
  */
 extern elevator_t iosched_as;
 
+/*
+ * completely fair queueing I/O scheduler
+ */
+extern elevator_t iosched_cfq;
+
 extern int elevator_init(request_queue_t *, elevator_t *);
 extern void elevator_exit(request_queue_t *);
 extern int elv_rq_merge_ok(struct request *, struct bio *);
--- diff/include/linux/eventpoll.h	2004-02-09 10:36:12.000000000 +0000
+++ source/include/linux/eventpoll.h	2004-02-23 13:56:47.000000000 +0000
@@ -49,13 +49,6 @@ struct epoll_event {
 struct file;
 
 
-/* Kernel space functions implementing the user space "epoll" API */
-asmlinkage long sys_epoll_create(int size);
-asmlinkage long sys_epoll_ctl(int epfd, int op, int fd,
-			      struct epoll_event __user *event);
-asmlinkage long sys_epoll_wait(int epfd, struct epoll_event __user *events,
-			       int maxevents, int timeout);
-
 #ifdef CONFIG_EPOLL
 
 /* Used to initialize the epoll bits inside the "struct file" */
--- diff/include/linux/ext3_fs_sb.h	2004-02-09 10:36:12.000000000 +0000
+++ source/include/linux/ext3_fs_sb.h	2004-02-23 13:56:47.000000000 +0000
@@ -69,6 +69,10 @@ struct ext3_sb_info {
 	struct timer_list turn_ro_timer;	/* For turning read-only (crash simulation) */
 	wait_queue_head_t ro_wait_queue;	/* For people waiting for the fs to go read-only */
 #endif
+#ifdef CONFIG_QUOTA
+	char *s_qf_names[MAXQUOTAS];		/* Names of quota files with journalled quota */
+	int s_jquota_fmt;			/* Format of quota to use */
+#endif
 };
 
 #endif	/* _LINUX_EXT3_FS_SB */
--- diff/include/linux/ext3_jbd.h	2004-02-09 10:36:12.000000000 +0000
+++ source/include/linux/ext3_jbd.h	2004-02-23 13:56:47.000000000 +0000
@@ -42,8 +42,9 @@
  * superblock only gets updated once, of course, so don't bother
  * counting that again for the quota updates. */
 
-#define EXT3_DATA_TRANS_BLOCKS		(3 * EXT3_SINGLEDATA_TRANS_BLOCKS + \
-					 EXT3_XATTR_TRANS_BLOCKS - 2)
+#define EXT3_DATA_TRANS_BLOCKS		(EXT3_SINGLEDATA_TRANS_BLOCKS + \
+					 EXT3_XATTR_TRANS_BLOCKS - 2 + \
+					 2*EXT3_QUOTA_TRANS_BLOCKS)
 
 extern int ext3_writepage_trans_blocks(struct inode *inode);
 
@@ -72,6 +73,15 @@ extern int ext3_writepage_trans_blocks(s
 
 #define EXT3_INDEX_EXTRA_TRANS_BLOCKS	8
 
+#ifdef CONFIG_QUOTA
+/* Amount of blocks needed for quota update - we know that the structure was
+ * allocated so we need to update only inode+data */
+#define EXT3_QUOTA_TRANS_BLOCKS 2
+#define EXT3_QUOTA_INIT_BLOCKS (DQUOT_MAX_WRITES*(EXT3_SINGLEDATA_TRANS_BLOCKS-2)+2)
+#else
+#define EXT3_QUOTA_TRANS_BLOCKS 0
+#endif
+
 int
 ext3_mark_iloc_dirty(handle_t *handle, 
 		     struct inode *inode,
--- diff/include/linux/fb.h	2004-02-18 08:54:13.000000000 +0000
+++ source/include/linux/fb.h	2004-02-23 13:56:47.000000000 +0000
@@ -371,16 +371,16 @@ extern int fb_unregister_client(struct n
 #define FB_PIXMAP_SYNC    256   /* set if GPU can DMA       */
 
 struct fb_pixmap {
-	u8 *addr;		/* pointer to memory                    */
-	u32 size;		/* size of buffer in bytes              */
-	u32 offset;		/* current offset to buffer             */
-	u32 buf_align;		/* byte alignment of each bitmap        */
-	u32 scan_align;		/* alignment per scanline               */
-	u32 access_align;	/* alignment per read/write             */
-	u32 flags;		/* see FB_PIXMAP_*                      */
-					  /* access methods                */
-	void (*outbuf)(u8 *dst, u8 *addr, unsigned int size); 
-	u8   (*inbuf) (u8 *addr);
+	u8  *addr;		/* pointer to memory			*/
+	u32 size;		/* size of buffer in bytes		*/
+	u32 offset;		/* current offset to buffer		*/
+	u32 buf_align;		/* byte alignment of each bitmap	*/
+	u32 scan_align;		/* alignment per scanline		*/
+	u32 access_align;	/* alignment per read/write		*/
+	u32 flags;		/* see FB_PIXMAP_*			*/
+				/* access methods			*/
+	void (*outbuf)(struct fb_info *info, u8 *addr, u8 *src, unsigned int size);
+	u8   (*inbuf) (struct fb_info *info, u8 *addr);
 };
 
     /*
@@ -388,64 +388,53 @@ struct fb_pixmap {
      */
 
 struct fb_ops {
-    /* open/release and usage marking */
-    struct module *owner;
-    int (*fb_open)(struct fb_info *info, int user);
-    int (*fb_release)(struct fb_info *info, int user);
-
-    /* For framebuffers with strange non linear layouts */	
-	ssize_t(*fb_read) (struct file * file, char *buf, size_t count,
-			   loff_t * ppos);
-	ssize_t(*fb_write) (struct file * file, const char *buf,
-			    size_t count, loff_t * ppos);
+	/* open/release and usage marking */
+	struct module *owner;
+	int (*fb_open)(struct fb_info *info, int user);
+	int (*fb_release)(struct fb_info *info, int user);
+
+	/* For framebuffers with strange non linear layouts */
+	ssize_t (*fb_read)(struct file *file, char *buf, size_t count, loff_t *ppos);
+	ssize_t (*fb_write)(struct file *file, const char *buf, size_t count, loff_t *ppos);
 
 	/* checks var and eventually tweaks it to something supported,
 	 * DO NOT MODIFY PAR */
-	int (*fb_check_var) (struct fb_var_screeninfo * var,
-			     struct fb_info * info);
+	int (*fb_check_var)(struct fb_var_screeninfo *var, struct fb_info *info);
 	/* set the video mode according to info->var */
-    int (*fb_set_par)(struct fb_info *info);
+	int (*fb_set_par)(struct fb_info *info);
 
-    /* set color register */
-    int (*fb_setcolreg)(unsigned regno, unsigned red, unsigned green,
-			     unsigned blue, unsigned transp,
-			     struct fb_info * info);
-
-    /* blank display */
-    int (*fb_blank)(int blank, struct fb_info *info);
-
-    /* pan display */
-	int (*fb_pan_display) (struct fb_var_screeninfo * var,
-			       struct fb_info * info);
-
-    /* draws a rectangle */
-	void (*fb_fillrect) (struct fb_info * info,
-			     const struct fb_fillrect * rect);
-    /* Copy data from area to another */
-	void (*fb_copyarea) (struct fb_info * info,
-			     const struct fb_copyarea * region);
-    /* Draws a image to the display */
-	void (*fb_imageblit) (struct fb_info * info,
-			      const struct fb_image * image);
-
-    /* Draws cursor */
-	int (*fb_cursor) (struct fb_info * info,
-			  struct fb_cursor * cursor);
-
-    /* Rotates the display */
-    void (*fb_rotate)(struct fb_info *info, int angle);
-
-    /* wait for blit idle, optional */
-    int (*fb_sync)(struct fb_info *info);		
-
-    /* perform fb specific ioctl (optional) */
-	int (*fb_ioctl) (struct inode * inode, struct file * file,
-			 unsigned int cmd, unsigned long arg,
-			 struct fb_info * info);
-
-    /* perform fb specific mmap */
-	int (*fb_mmap) (struct fb_info * info, struct file * file,
-			struct vm_area_struct * vma);
+	/* set color register */
+	int (*fb_setcolreg)(unsigned regno, unsigned red, unsigned green,
+			    unsigned blue, unsigned transp, struct fb_info *info);
+
+	/* blank display */
+	int (*fb_blank)(int blank, struct fb_info *info);
+
+	/* pan display */
+	int (*fb_pan_display)(struct fb_var_screeninfo *var, struct fb_info *info);
+
+	/* Draws a rectangle */
+	void (*fb_fillrect) (struct fb_info *info, const struct fb_fillrect *rect);
+	/* Copy data from area to another */
+	void (*fb_copyarea) (struct fb_info *info, const struct fb_copyarea *region);
+	/* Draws a image to the display */
+	void (*fb_imageblit) (struct fb_info *info, const struct fb_image *image);
+
+	/* Draws cursor */
+	int (*fb_cursor) (struct fb_info *info, struct fb_cursor *cursor);
+
+	/* Rotates the display */
+	void (*fb_rotate)(struct fb_info *info, int angle);
+
+	/* wait for blit idle, optional */
+	int (*fb_sync)(struct fb_info *info);
+
+	/* perform fb specific ioctl (optional) */
+	int (*fb_ioctl)(struct inode *inode, struct file *file, unsigned int cmd,
+			unsigned long arg, struct fb_info *info);
+
+	/* perform fb specific mmap */
+	int (*fb_mmap)(struct fb_info *info, struct file *file, struct vm_area_struct *vma);
 };
 
 struct fb_info {
@@ -459,6 +448,7 @@ struct fb_info {
 	struct fb_cursor cursor;	/* Current cursor */	
 	struct work_struct queue;	/* Framebuffer event queue */
 	struct fb_pixmap pixmap;	/* Image Hardware Mapper */
+	struct fb_pixmap sprite;	/* Cursor hardware Mapper */
 	struct fb_cmap cmap;		/* Current cmap */
 	struct fb_ops *fbops;
 	char *screen_base;		/* Virtual address */
@@ -537,14 +527,16 @@ extern int register_framebuffer(struct f
 extern int unregister_framebuffer(struct fb_info *fb_info);
 extern int fb_prepare_logo(struct fb_info *fb_info);
 extern int fb_show_logo(struct fb_info *fb_info);
-extern u32 fb_get_buffer_offset(struct fb_info *info, u32 size);
-extern void move_buf_unaligned(struct fb_info *info, u8 * dst, u8 * src,
-				u32 d_pitch, u32 height, u32 mask,
-				u32 shift_high, u32 shift_low, u32 mod,
-				u32 idx);
-extern void move_buf_aligned(struct fb_info *info, u8 * dst, u8 * src,
-				u32 d_pitch, u32 s_pitch, u32 height);
+extern char* fb_get_buffer_offset(struct fb_info *info, struct fb_pixmap *buf, u32 size);
+extern void fb_move_buf_unaligned(struct fb_info *info, struct fb_pixmap *buf,
+				u8 *dst, u32 d_pitch, u8 *src, u32 idx,
+				u32 height, u32 shift_high, u32 shift_low, u32 mod);
+extern void fb_move_buf_aligned(struct fb_info *info, struct fb_pixmap *buf,
+				u8 *dst, u32 d_pitch, u8 *src, u32 s_pitch,
+				u32 height);
+extern void fb_load_cursor_image(struct fb_info *);
 extern void fb_set_suspend(struct fb_info *info, int state);
+
 extern struct fb_info *registered_fb[FB_MAX];
 extern int num_registered_fb;
 
--- diff/include/linux/fs.h	2004-02-18 08:54:13.000000000 +0000
+++ source/include/linux/fs.h	2004-02-23 13:56:47.000000000 +0000
@@ -137,6 +137,7 @@ extern int leases_enable, dir_notify_ena
 #define S_DEAD		32	/* removed, but still open directory */
 #define S_NOQUOTA	64	/* Inode is not counted to quota */
 #define S_DIRSYNC	128	/* Directory modifications are synchronous */
+#define S_NOCMTIME	256	/* Do not update file c/mtime */
 
 /*
  * Note that nosuid etc flags are inode-specific: setting some file-system
@@ -170,6 +171,7 @@ extern int leases_enable, dir_notify_ena
 #define IS_ONE_SECOND(inode)	__IS_FLG(inode, MS_ONE_SECOND)
 
 #define IS_DEADDIR(inode)	((inode)->i_flags & S_DEAD)
+#define IS_NOCMTIME(inode)	((inode)->i_flags & S_NOCMTIME)
 
 /* the read-only stuff doesn't really belong here, but any other place is
    probably as bad and I don't want to create yet another include file. */
@@ -336,6 +338,7 @@ struct address_space {
 	spinlock_t		private_lock;	/* for use by the address_space */
 	struct list_head	private_list;	/* ditto */
 	struct address_space	*assoc_mapping;	/* ditto */
+	struct rw_semaphore	wb_rwsema;	/* serialize SYNC writebacks */
 };
 
 struct block_device {
@@ -376,6 +379,7 @@ struct block_device {
 struct inode {
 	struct hlist_node	i_hash;
 	struct list_head	i_list;
+	struct list_head	i_sb_list;
 	struct list_head	i_dentry;
 	unsigned long		i_ino;
 	atomic_t		i_count;
@@ -395,6 +399,7 @@ struct inode {
 	unsigned short          i_bytes;
 	spinlock_t		i_lock;	/* i_blocks, i_bytes, maybe i_size */
 	struct semaphore	i_sem;
+	struct rw_semaphore	i_alloc_sem;
 	struct inode_operations	*i_op;
 	struct file_operations	*i_fop;	/* former ->i_op->default_file_ops */
 	struct super_block	*i_sb;
@@ -507,6 +512,8 @@ struct file_ra_state {
 	unsigned long prev_page;	/* Cache last read() position */
 	unsigned long ahead_start;	/* Ahead window */
 	unsigned long ahead_size;
+	unsigned long serial_cnt;	/* measure of sequentiality */
+	unsigned long average;		/* another measure of sequentiality */
 	unsigned long ra_pages;		/* Maximum readahead window */
 	unsigned long mmap_hit;		/* Cache hit stat for mmap accesses */
 	unsigned long mmap_miss;	/* Cache miss stat for mmap accesses */
@@ -700,6 +707,7 @@ struct super_block {
 	atomic_t		s_active;
 	void                    *s_security;
 
+	struct list_head	s_inodes;	/* all inodes */
 	struct list_head	s_dirty;	/* dirty inodes */
 	struct list_head	s_io;		/* parked for writeback */
 	struct hlist_head	s_anon;		/* anonymous dentries for (nfs) exporting */
@@ -1045,6 +1053,7 @@ struct super_block *sget(struct file_sys
 			void *data);
 struct super_block *get_sb_pseudo(struct file_system_type *, char *,
 			struct super_operations *ops, unsigned long);
+void unnamed_dev_init(void);
 
 /* Alas, no aliases. Too much hassle with bringing module.h everywhere */
 #define fops_get(fops) \
@@ -1117,10 +1126,7 @@ static inline int break_lease(struct ino
 
 /* fs/open.c */
 
-asmlinkage long sys_open(const char __user *, int, int);
-asmlinkage long sys_close(unsigned int);	/* yes, it's really unsigned */
 extern int do_truncate(struct dentry *, loff_t start);
-
 extern struct file *filp_open(const char *, int, int);
 extern struct file * dentry_open(struct dentry *, struct vfsmount *, int);
 extern int filp_close(struct file *, fl_owner_t id);
@@ -1132,14 +1138,13 @@ extern void vfs_caches_init(unsigned lon
 #define __getname()	kmem_cache_alloc(names_cachep, SLAB_KERNEL)
 #define putname(name)	kmem_cache_free(names_cachep, (void *)(name))
 
-enum {BDEV_FILE, BDEV_SWAP, BDEV_FS, BDEV_RAW};
 extern int register_blkdev(unsigned int, const char *);
 extern int unregister_blkdev(unsigned int, const char *);
 extern struct block_device *bdget(dev_t);
 extern void bd_forget(struct inode *inode);
 extern void bdput(struct block_device *);
 extern int blkdev_open(struct inode *, struct file *);
-extern struct block_device *open_by_devnum(dev_t, unsigned, int);
+extern struct block_device *open_by_devnum(dev_t, unsigned);
 extern struct file_operations def_blk_fops;
 extern struct address_space_operations def_blk_aops;
 extern struct file_operations def_chr_fops;
@@ -1147,8 +1152,8 @@ extern struct file_operations bad_sock_f
 extern struct file_operations def_fifo_fops;
 extern int ioctl_by_bdev(struct block_device *, unsigned, unsigned long);
 extern int blkdev_ioctl(struct inode *, struct file *, unsigned, unsigned long);
-extern int blkdev_get(struct block_device *, mode_t, unsigned, int);
-extern int blkdev_put(struct block_device *, int);
+extern int blkdev_get(struct block_device *, mode_t, unsigned);
+extern int blkdev_put(struct block_device *);
 extern int bd_claim(struct block_device *, void *);
 extern void bd_release(struct block_device *);
 extern void blk_run_queues(void);
@@ -1167,8 +1172,8 @@ extern int chrdev_open(struct inode *, s
 extern const char *__bdevname(dev_t, char *buffer);
 extern const char *bdevname(struct block_device *bdev, char *buffer);
 extern struct block_device *lookup_bdev(const char *);
-extern struct block_device *open_bdev_excl(const char *, int, int, void *);
-extern void close_bdev_excl(struct block_device *, int);
+extern struct block_device *open_bdev_excl(const char *, int, void *);
+extern void close_bdev_excl(struct block_device *);
 
 extern void init_special_inode(struct inode *, umode_t, dev_t);
 
@@ -1213,6 +1218,7 @@ extern void write_inode_now(struct inode
 extern int filemap_fdatawrite(struct address_space *);
 extern int filemap_flush(struct address_space *);
 extern int filemap_fdatawait(struct address_space *);
+extern int filemap_write_and_wait(struct address_space *mapping);
 extern void sync_supers(void);
 extern void sync_filesystems(int wait);
 extern void emergency_sync(void);
@@ -1324,9 +1330,6 @@ extern void
 file_ra_state_init(struct file_ra_state *ra, struct address_space *mapping);
 extern ssize_t generic_file_direct_IO(int rw, struct kiocb *iocb,
 	const struct iovec *iov, loff_t offset, unsigned long nr_segs);
-extern int blockdev_direct_IO(int rw, struct kiocb *iocb, struct inode *inode, 
-	struct block_device *bdev, const struct iovec *iov, loff_t offset, 
-	unsigned long nr_segs, get_blocks_t *get_blocks, dio_iodone_t *end_io);
 extern ssize_t generic_file_readv(struct file *filp, const struct iovec *iov, 
 	unsigned long nr_segs, loff_t *ppos);
 ssize_t generic_file_writev(struct file *filp, const struct iovec *iov, 
@@ -1348,6 +1351,32 @@ static inline void do_generic_file_read(
 				actor);
 }
 
+int __blockdev_direct_IO(int rw, struct kiocb *iocb, struct inode *inode,
+	struct block_device *bdev, const struct iovec *iov, loff_t offset,
+	unsigned long nr_segs, get_blocks_t get_blocks, dio_iodone_t end_io,
+	int needs_special_locking);
+
+/*
+ * For filesystems which need locking between buffered and direct access
+ */
+static inline int blockdev_direct_IO(int rw, struct kiocb *iocb,
+	struct inode *inode, struct block_device *bdev, const struct iovec *iov,
+	loff_t offset, unsigned long nr_segs, get_blocks_t get_blocks,
+	dio_iodone_t end_io)
+{
+	return __blockdev_direct_IO(rw, iocb, inode, bdev, iov, offset,
+				nr_segs, get_blocks, end_io, 1);
+}
+
+static inline int blockdev_direct_IO_no_locking(int rw, struct kiocb *iocb,
+	struct inode *inode, struct block_device *bdev, const struct iovec *iov,
+	loff_t offset, unsigned long nr_segs, get_blocks_t get_blocks,
+	dio_iodone_t end_io)
+{
+	return __blockdev_direct_IO(rw, iocb, inode, bdev, iov, offset,
+				nr_segs, get_blocks, end_io, 0);
+}
+
 extern struct file_operations generic_ro_fops;
 
 #define special_file(m) (S_ISCHR(m)||S_ISBLK(m)||S_ISFIFO(m)||S_ISSOCK(m))
--- diff/include/linux/futex.h	2003-06-09 14:18:20.000000000 +0100
+++ source/include/linux/futex.h	2004-02-23 13:56:47.000000000 +0000
@@ -10,10 +10,6 @@
 #define FUTEX_REQUEUE (3)
 
 
-asmlinkage long sys_futex(u32 __user *uaddr, int op, int val,
-			  struct timespec __user *utime, u32 __user *uaddr2);
-
-
 long do_futex(unsigned long uaddr, int op, int val,
 		unsigned long timeout, unsigned long uaddr2, int val2);
 
--- diff/include/linux/genhd.h	2004-02-09 10:36:12.000000000 +0000
+++ source/include/linux/genhd.h	2004-02-23 13:56:47.000000000 +0000
@@ -64,10 +64,11 @@ struct hd_struct {
 	int policy, partno;
 };
 
-#define GENHD_FL_REMOVABLE  1
-#define GENHD_FL_DRIVERFS  2
-#define GENHD_FL_CD	8
-#define GENHD_FL_UP	16
+#define GENHD_FL_REMOVABLE			1
+#define GENHD_FL_DRIVERFS			2
+#define GENHD_FL_CD				8
+#define GENHD_FL_UP				16
+#define GENHD_FL_SUPPRESS_PARTITION_INFO	32
 
 struct disk_stats {
 	unsigned read_sectors, write_sectors;
--- diff/include/linux/hdlc.h	2003-08-20 14:16:34.000000000 +0100
+++ source/include/linux/hdlc.h	2004-02-23 13:56:47.000000000 +0000
@@ -75,7 +75,7 @@ typedef struct {
 
 
 typedef struct pvc_device_struct {
-	struct hdlc_device_struct *master;
+	struct net_device *master;
 	struct net_device *main;
 	struct net_device *ether; /* bridged Ethernet interface */
 	struct pvc_device_struct *next;	/* Sorted in ascending DLCI order */
@@ -96,11 +96,10 @@ typedef struct pvc_device_struct {
 
 typedef struct hdlc_device_struct {
 	/* To be initialized by hardware driver */
-	struct net_device netdev; /* master net device - must be first */
 	struct net_device_stats stats;
 
 	/* used by HDLC layer to take control over HDLC device from hw driver*/
-	int (*attach)(struct hdlc_device_struct *hdlc,
+	int (*attach)(struct net_device *dev,
 		      unsigned short encoding, unsigned short parity);
 
 	/* hardware driver must handle this instead of dev->hard_start_xmit */
@@ -109,13 +108,13 @@ typedef struct hdlc_device_struct {
 
 	/* Things below are for HDLC layer internal use only */
 	struct {
-		int (*open)(struct hdlc_device_struct *hdlc);
-		void (*close)(struct hdlc_device_struct *hdlc);
+		int (*open)(struct net_device *dev);
+		void (*close)(struct net_device *dev);
 
 		/* if open & DCD */
-		void (*start)(struct hdlc_device_struct *hdlc);
+		void (*start)(struct net_device *dev);
 		/* if open & !DCD */
-		void (*stop)(struct hdlc_device_struct *hdlc);
+		void (*stop)(struct net_device *dev);
 
 		void (*detach)(struct hdlc_device_struct *hdlc);
 		int (*netif_rx)(struct sk_buff *skb);
@@ -167,16 +166,17 @@ typedef struct hdlc_device_struct {
 					      int new_mtu);
 		}ppp;
 	}state;
+	void *priv;
 }hdlc_device;
 
 
 
-int hdlc_raw_ioctl(hdlc_device *hdlc, struct ifreq *ifr);
-int hdlc_raw_eth_ioctl(hdlc_device *hdlc, struct ifreq *ifr);
-int hdlc_cisco_ioctl(hdlc_device *hdlc, struct ifreq *ifr);
-int hdlc_ppp_ioctl(hdlc_device *hdlc, struct ifreq *ifr);
-int hdlc_fr_ioctl(hdlc_device *hdlc, struct ifreq *ifr);
-int hdlc_x25_ioctl(hdlc_device *hdlc, struct ifreq *ifr);
+int hdlc_raw_ioctl(struct net_device *dev, struct ifreq *ifr);
+int hdlc_raw_eth_ioctl(struct net_device *dev, struct ifreq *ifr);
+int hdlc_cisco_ioctl(struct net_device *dev, struct ifreq *ifr);
+int hdlc_ppp_ioctl(struct net_device *dev, struct ifreq *ifr);
+int hdlc_fr_ioctl(struct net_device *dev, struct ifreq *ifr);
+int hdlc_x25_ioctl(struct net_device *dev, struct ifreq *ifr);
 
 
 /* Exported from hdlc.o */
@@ -185,19 +185,14 @@ int hdlc_x25_ioctl(hdlc_device *hdlc, st
 int hdlc_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd);
 
 /* Must be used by hardware driver on module startup/exit */
-int register_hdlc_device(hdlc_device *hdlc);
-void unregister_hdlc_device(hdlc_device *hdlc);
-
-
-static __inline__ struct net_device* hdlc_to_dev(hdlc_device *hdlc)
-{
-	return &hdlc->netdev;
-}
+int register_hdlc_device(struct net_device *dev);
+void unregister_hdlc_device(struct net_device *dev);
 
+struct net_device *alloc_hdlcdev(void *priv);
 
 static __inline__ hdlc_device* dev_to_hdlc(struct net_device *dev)
 {
-	return (hdlc_device*)dev;
+	return netdev_priv(dev);
 }
 
 
@@ -207,12 +202,6 @@ static __inline__ pvc_device* dev_to_pvc
 }
 
 
-static __inline__ const char *hdlc_to_name(hdlc_device *hdlc)
-{
-	return hdlc_to_dev(hdlc)->name;
-}
-
-
 static __inline__ void debug_frame(const struct sk_buff *skb)
 {
 	int i;
@@ -229,11 +218,11 @@ static __inline__ void debug_frame(const
 
 
 /* Must be called by hardware driver when HDLC device is being opened */
-int hdlc_open(hdlc_device *hdlc);
+int hdlc_open(struct net_device *dev);
 /* Must be called by hardware driver when HDLC device is being closed */
-void hdlc_close(hdlc_device *hdlc);
+void hdlc_close(struct net_device *dev);
 /* Called by hardware driver when DCD line level changes */
-void hdlc_set_carrier(int on, hdlc_device *hdlc);
+void hdlc_set_carrier(int on, struct net_device *dev);
 
 /* May be used by hardware driver to gain control over HDLC device */
 static __inline__ void hdlc_proto_detach(hdlc_device *hdlc)
@@ -244,6 +233,12 @@ static __inline__ void hdlc_proto_detach
 }
 
 
+static __inline__ struct net_device_stats *hdlc_stats(struct net_device *dev)
+{
+	return &dev_to_hdlc(dev)->stats;
+}
+
+
 static __inline__ unsigned short hdlc_type_trans(struct sk_buff *skb,
 						 struct net_device *dev)
 {
--- diff/include/linux/hiddev.h	2003-09-17 12:28:12.000000000 +0100
+++ source/include/linux/hiddev.h	2004-02-23 13:56:47.000000000 +0000
@@ -39,33 +39,33 @@ struct hiddev_event {
 };
 
 struct hiddev_devinfo {
-	unsigned int bustype;
-	unsigned int busnum;
-	unsigned int devnum;
-	unsigned int ifnum;
-	short vendor;
-	short product;
-	short version;
-	unsigned num_applications;
+	__u32 bustype;
+	__u32 busnum;
+	__u32 devnum;
+	__u32 ifnum;
+	__s16 vendor;
+	__s16 product;
+	__s16 version;
+	__u32 num_applications;
 };
 
 struct hiddev_collection_info {
-	unsigned index;
-	unsigned type;
-	unsigned usage;
-	unsigned level;
+	__u32 index;
+	__u32 type;
+	__u32 usage;
+	__u32 level;
 };
 
 #define HID_STRING_SIZE 256
 struct hiddev_string_descriptor {
-	int index;
+	__s32 index;
 	char value[HID_STRING_SIZE];
 };
 
 struct hiddev_report_info {
-	unsigned report_type;
-	unsigned report_id;
-	unsigned num_fields;
+	__u32 report_type;
+	__u32 report_id;
+	__u32 num_fields;
 };
 
 /* To do a GUSAGE/SUSAGE, fill in at least usage_code,  report_type and 
@@ -88,20 +88,20 @@ struct hiddev_report_info {
 #define HID_REPORT_TYPE_MAX     3
 
 struct hiddev_field_info {
-	unsigned report_type;
-	unsigned report_id;
-	unsigned field_index;
-	unsigned maxusage;
-	unsigned flags;
-	unsigned physical;		/* physical usage for this field */
-	unsigned logical;		/* logical usage for this field */
-	unsigned application;		/* application usage for this field */
+	__u32 report_type;
+	__u32 report_id;
+	__u32 field_index;
+	__u32 maxusage;
+	__u32 flags;
+	__u32 physical;		/* physical usage for this field */
+	__u32 logical;		/* logical usage for this field */
+	__u32 application;		/* application usage for this field */
 	__s32 logical_minimum;
 	__s32 logical_maximum;
 	__s32 physical_minimum;
 	__s32 physical_maximum;
-	unsigned unit_exponent;
-	unsigned unit;
+	__u32 unit_exponent;
+	__u32 unit;
 };
 
 /* Fill in report_type, report_id and field_index to get the information on a
@@ -118,14 +118,22 @@ struct hiddev_field_info {
 #define HID_FIELD_BUFFERED_BYTE		0x100
 
 struct hiddev_usage_ref {
-	unsigned report_type;
-	unsigned report_id;
-	unsigned field_index;
-	unsigned usage_index;
-	unsigned usage_code;
+	__u32 report_type;
+	__u32 report_id;
+	__u32 field_index;
+	__u32 usage_index;
+	__u32 usage_code;
 	__s32 value;
 };
 
+/* hiddev_usage_ref_multi is used for sending multiple bytes to a control.
+ * It really manifests itself as setting the value of consecutive usages */
+struct hiddev_usage_ref_multi {
+	struct hiddev_usage_ref uref;
+	__u32 num_values;
+	__s32 values[HID_MAX_USAGES];
+};
+
 /* FIELD_INDEX_NONE is returned in read() data from the kernel when flags
  * is set to (HIDDEV_FLAG_UREF | HIDDEV_FLAG_REPORT) and a new report has
  * been sent by the device 
@@ -161,6 +169,10 @@ struct hiddev_usage_ref {
 #define HIDIOCGCOLLECTIONINFO	_IOWR('H', 0x11, struct hiddev_collection_info)
 #define HIDIOCGPHYS(len)	_IOC(_IOC_READ, 'H', 0x12, len)
 
+/* For writing/reading to multiple/consecutive usages */
+#define HIDIOCGUSAGES		_IOWR('H', 0x13, struct hiddev_usage_ref_multi)
+#define HIDIOCSUSAGES		_IOW('H', 0x14, struct hiddev_usage_ref_multi)
+
 /* 
  * Flags to be used in HIDIOCSFLAG
  */
--- diff/include/linux/ide.h	2004-02-18 08:54:13.000000000 +0000
+++ source/include/linux/ide.h	2004-02-23 13:56:47.000000000 +0000
@@ -698,7 +698,6 @@ typedef struct ide_drive_s {
 	u8	state;			/* retry state */
 	u8	waiting_for_dma;	/* dma currently in progress */
 	u8	unmask;			/* okay to unmask other irqs */
-	u8	slow;			/* slow data port */
 	u8	bswap;			/* byte swap data */
 	u8	dsc_overlap;		/* DSC overlap */
 	u8	nice1;			/* give potential excess bandwidth */
@@ -713,14 +712,12 @@ typedef struct ide_drive_s {
 	unsigned forced_geom	: 1;	/* 1 if hdx=c,h,s was given at boot */
 	unsigned no_unmask	: 1;	/* disallow setting unmask bit */
 	unsigned no_io_32bit	: 1;	/* disallow enabling 32bit I/O */
-	unsigned nobios		: 1;	/* do not probe bios for drive */
 	unsigned atapi_overlap	: 1;	/* ATAPI overlap (not supported) */
 	unsigned nice0		: 1;	/* give obvious excess bandwidth */
 	unsigned nice2		: 1;	/* give a share in our own bandwidth */
 	unsigned doorlocking	: 1;	/* for removable only: door lock/unlock works */
 	unsigned autotune	: 2;	/* 0=default, 1=autotune, 2=noautotune */
 	unsigned remap_0_to_1	: 1;	/* 0=noremap, 1=remap 0->1 (for EZDrive) */
-	unsigned ata_flash	: 1;	/* 1=present, 0=default */
 	unsigned blocked        : 1;	/* 1=powermanagment told us not to do anything, so sleep nicely */
 	unsigned vdma		: 1;	/* 1=doing PIO over DMA 0=doing normal DMA */
 	unsigned addressing;		/*      : 3;
@@ -1090,6 +1087,8 @@ typedef struct {
 } ide_proc_entry_t;
 
 #ifdef CONFIG_PROC_FS
+extern struct proc_dir_entry *proc_ide_root;
+
 extern void proc_ide_create(void);
 extern void proc_ide_destroy(void);
 extern void destroy_proc_ide_device(ide_hwif_t *, ide_drive_t *);
@@ -1100,6 +1099,10 @@ extern void ide_remove_proc_entries(stru
 read_proc_t proc_ide_read_capacity;
 read_proc_t proc_ide_read_geometry;
 
+#ifdef CONFIG_BLK_DEV_IDEPCI
+void ide_pci_create_host_proc(const char *, get_info_t *);
+#endif
+
 /*
  * Standard exit stuff:
  */
@@ -1116,6 +1119,7 @@ read_proc_t proc_ide_read_geometry;
 	return len;			\
 }
 #else
+static inline void create_proc_ide_interfaces(void) { ; }
 #define PROC_IDE_READ_RETURN(page,start,off,count,eof,len) return 0;
 #endif
 
@@ -1155,8 +1159,6 @@ enum {
 /*
  * Subdrivers support.
  */
-#define IDE_SUBDRIVER_VERSION	1
-
 typedef struct ide_driver_s {
 	struct module			*owner;
 	const char			*name;
@@ -1165,8 +1167,6 @@ typedef struct ide_driver_s {
 	unsigned busy			: 1;
 	unsigned supports_dsc_overlap	: 1;
 	int		(*cleanup)(ide_drive_t *);
-	int		(*shutdown)(ide_drive_t *);
-	int		(*flushcache)(ide_drive_t *);
 	ide_startstop_t	(*do_request)(ide_drive_t *, struct request *, sector_t);
 	int		(*end_request)(ide_drive_t *, int, int);
 	u8		(*sense)(ide_drive_t *, const char *, u8);
@@ -1440,9 +1440,6 @@ extern int wait_for_ready(ide_drive_t *,
  */
 extern ide_startstop_t do_rw_taskfile(ide_drive_t *, ide_task_t *);
 
-/* (ide_drive_t *drive, u8 stat, u8 err) */
-extern void ide_end_taskfile(ide_drive_t *, u8, u8);
-
 /*
  * Special Flagged Register Validation Caller
  */
@@ -1528,22 +1525,10 @@ extern void default_hwif_transport(ide_h
 
 int ide_register_driver(ide_driver_t *driver);
 void ide_unregister_driver(ide_driver_t *driver);
-int ide_register_subdriver (ide_drive_t *drive, ide_driver_t *driver, int version);
+int ide_register_subdriver(ide_drive_t *, ide_driver_t *);
 int ide_unregister_subdriver (ide_drive_t *drive);
 int ide_replace_subdriver(ide_drive_t *drive, const char *driver);
 
-#ifdef CONFIG_PROC_FS
-typedef struct ide_pci_host_proc_s {
-	char				*name;
-	u8				set;
-	get_info_t			*get_info;
-	struct proc_dir_entry		*parent;
-	struct ide_pci_host_proc_s	*next;
-} ide_pci_host_proc_t;
-
-void ide_pci_register_host_proc(ide_pci_host_proc_t *);
-#endif /* CONFIG_PROC_FS */
-
 #define ON_BOARD		1
 #define NEVER_BOARD		0
 
--- diff/include/linux/idr.h	2003-05-21 11:50:00.000000000 +0100
+++ source/include/linux/idr.h	2004-02-23 13:56:47.000000000 +0000
@@ -58,7 +58,7 @@ struct idr {
  */
 
 void *idr_find(struct idr *idp, int id);
-int idr_pre_get(struct idr *idp);
+int idr_pre_get(struct idr *idp, unsigned gfp_mask);
 int idr_get_new(struct idr *idp, void *ptr);
 void idr_remove(struct idr *idp, int id);
 void idr_init(struct idr *idp);
--- diff/include/linux/if_bonding.h	2004-02-18 08:54:13.000000000 +0000
+++ source/include/linux/if_bonding.h	2004-02-23 13:56:47.000000000 +0000
@@ -32,6 +32,9 @@
  * 2003/05/01 - Amir Noam <amir.noam at intel dot com>
  *	- Added ABI version control to restore compatibility between
  *	  new/old ifenslave and new/old bonding.
+ *
+ * 2003/12/01 - Shmulik Hen <shmulik.hen at intel dot com>
+ *	- Code cleanup and style changes
  */
 
 #ifndef _LINUX_IF_BONDING_H
@@ -86,7 +89,7 @@ typedef struct ifbond {
 typedef struct ifslave
 {
 	__s32 slave_id; /* Used as an IN param to the BOND_SLAVE_INFO_QUERY ioctl */
-	__s8 slave_name[IFNAMSIZ];
+	char slave_name[IFNAMSIZ];
 	__s8 link;
 	__s8 state;
 	__u32  link_failure_count;
--- diff/include/linux/inetdevice.h	2004-02-18 08:54:13.000000000 +0000
+++ source/include/linux/inetdevice.h	2004-02-23 13:56:47.000000000 +0000
@@ -18,6 +18,8 @@ struct ipv4_devconf
 	int	mc_forwarding;
 	int	tag;
 	int     arp_filter;
+	int	arp_announce;
+	int	arp_ignore;
 	int	medium_id;
 	int	no_xfrm;
 	int	no_policy;
@@ -71,6 +73,8 @@ struct in_device
 	  (ipv4_devconf.accept_redirects || (in_dev)->cnf.accept_redirects)))
 
 #define IN_DEV_ARPFILTER(in_dev)	(ipv4_devconf.arp_filter || (in_dev)->cnf.arp_filter)
+#define IN_DEV_ARP_ANNOUNCE(in_dev)	(max(ipv4_devconf.arp_announce, (in_dev)->cnf.arp_announce))
+#define IN_DEV_ARP_IGNORE(in_dev)	(max(ipv4_devconf.arp_ignore, (in_dev)->cnf.arp_ignore))
 
 struct in_ifaddr
 {
@@ -97,6 +101,7 @@ extern void		devinet_init(void);
 extern struct in_device *inetdev_init(struct net_device *dev);
 extern struct in_device	*inetdev_by_index(int);
 extern u32		inet_select_addr(const struct net_device *dev, u32 dst, int scope);
+extern u32		inet_confirm_addr(const struct net_device *dev, u32 dst, u32 local, int scope);
 extern struct in_ifaddr *inet_ifa_byprefix(struct in_device *in_dev, u32 prefix, u32 mask);
 extern void		inet_forward_change(void);
 
--- diff/include/linux/init_task.h	2004-02-18 08:54:13.000000000 +0000
+++ source/include/linux/init_task.h	2004-02-23 13:56:47.000000000 +0000
@@ -57,6 +57,8 @@
 	.siglock	= SPIN_LOCK_UNLOCKED, 		\
 }
 
+extern struct group_info init_groups;
+
 /*
  *  INIT_TASK is used to set up the first task table, touch at
  * your own risk!. Base=0, limit=0x1fffff (=2MB)
@@ -88,6 +90,7 @@
 	.real_timer	= {						\
 		.function	= it_real_fn				\
 	},								\
+	.group_info	= &init_groups,					\
 	.cap_effective	= CAP_INIT_EFF_SET,				\
 	.cap_inheritable = CAP_INIT_INH_SET,				\
 	.cap_permitted	= CAP_FULL_SET,					\
--- diff/include/linux/interrupt.h	2003-09-30 15:46:20.000000000 +0100
+++ source/include/linux/interrupt.h	2004-02-23 13:56:47.000000000 +0000
@@ -211,6 +211,7 @@ static inline void tasklet_hi_enable(str
 }
 
 extern void tasklet_kill(struct tasklet_struct *t);
+extern void tasklet_kill_immediate(struct tasklet_struct *t, unsigned int cpu);
 extern void tasklet_init(struct tasklet_struct *t,
 			 void (*func)(unsigned long), unsigned long data);
 
--- diff/include/linux/ioctl32.h	2003-05-21 11:50:16.000000000 +0100
+++ source/include/linux/ioctl32.h	2004-02-23 13:56:47.000000000 +0000
@@ -3,8 +3,6 @@
 
 struct file;
 
-extern long sys_ioctl(unsigned int, unsigned int, unsigned long);
-
 /* 
  * Register an 32bit ioctl translation handler for ioctl cmd.
  *
--- diff/include/linux/ipv6.h	2004-02-18 08:54:13.000000000 +0000
+++ source/include/linux/ipv6.h	2004-02-23 13:56:47.000000000 +0000
@@ -136,6 +136,7 @@ struct ipv6_devconf {
 	__s32		rtr_solicits;
 	__s32		rtr_solicit_interval;
 	__s32		rtr_solicit_delay;
+	__s32		force_mld_version;
 #ifdef CONFIG_IPV6_PRIVACY
 	__s32		use_tempaddr;
 	__s32		temp_valid_lft;
@@ -165,6 +166,7 @@ enum {
 	DEVCONF_REGEN_MAX_RETRY,
 	DEVCONF_MAX_DESYNC_FACTOR,
 	DEVCONF_MAX_ADDRESSES,
+	DEVCONF_FORCE_MLD_VERSION,
 	DEVCONF_MAX
 };
 
--- diff/include/linux/ipv6_route.h	2003-09-17 12:28:12.000000000 +0100
+++ source/include/linux/ipv6_route.h	2004-02-23 13:56:47.000000000 +0000
@@ -24,7 +24,6 @@
 #define RTF_CACHE	0x01000000	/* cache entry			*/
 #define RTF_FLOW	0x02000000	/* flow significant route	*/
 #define RTF_POLICY	0x04000000	/* policy route			*/
-#define RTF_NDISC	0x08000000	/* ndisc route			*/
 
 #define RTF_LOCAL	0x80000000
 
--- diff/include/linux/isdn.h	2003-09-17 12:28:12.000000000 +0100
+++ source/include/linux/isdn.h	2004-02-23 13:56:47.000000000 +0000
@@ -1,9 +1,10 @@
-/* Linux ISDN subsystem, main header
+/* $Id: isdn.h,v 1.125.2.3 2004/02/10 01:07:14 keil Exp $
+ *
+ * Main header for the Linux ISDN subsystem (linklevel).
  *
  * Copyright 1994,95,96 by Fritz Elfert (fritz@isdn4linux.de)
  * Copyright 1995,96    by Thinking Objects Software GmbH Wuerzburg
  * Copyright 1995,96    by Michael Hipp (Michael.Hipp@student.uni-tuebingen.de)
- * Copyright 2000-2002  by Kai Germaschewski (kai@germaschewski.name)
  * 
  * This software may be used and distributed according to the terms
  * of the GNU General Public License, incorporated herein by reference.
@@ -14,7 +15,6 @@
 #define __ISDN_H__
 
 #include <linux/ioctl.h>
-#include <linux/isdn/fsm.h>
 
 #ifdef CONFIG_COBALT_MICRO_SERVER
 /* Save memory */
@@ -75,7 +75,7 @@
 #define ISDN_NET_ENCAP_UIHDLC     5
 #define ISDN_NET_ENCAP_CISCOHDLCK 6 /* With SLARP and keepalive    */
 #define ISDN_NET_ENCAP_X25IFACE   7 /* Documentation/networking/x25-iface.txt*/
-#define ISDN_NET_ENCAP_NR         8
+#define ISDN_NET_ENCAP_MAX_ENCAP  ISDN_NET_ENCAP_X25IFACE
 
 /* Facility which currently uses an ISDN-channel */
 #define ISDN_USAGE_NONE       0
@@ -94,48 +94,48 @@
 #define ISDN_CMSGLEN	     50	 /* Length of CONNECT-Message to add for Modem */
 
 #define ISDN_MSNLEN          32
-#define NET_DV	0x06  /* Data version for isdn_net_ioctl_cfg   */
-#define TTY_DV	0x06  /* Data version for iprofd etc.          */
+#define NET_DV 0x06  /* Data version for isdn_net_ioctl_cfg   */
+#define TTY_DV 0x06  /* Data version for iprofd etc.          */
 
-#define INF_DV	0x01  /* Data version for /dev/isdninfo        */
+#define INF_DV 0x01  /* Data version for /dev/isdninfo        */
 
 typedef struct {
-	char		drvid[25];
-	unsigned long	arg;
+  char drvid[25];
+  unsigned long arg;
 } isdn_ioctl_struct;
 
 typedef struct {
-	char	name[10];
-	char	phone[ISDN_MSNLEN];
-	int	outgoing;
+  char name[10];
+  char phone[ISDN_MSNLEN];
+  int  outgoing;
 } isdn_net_ioctl_phone;
 
 typedef struct {
-	char	name[10];	/* Name of interface                     */
-	char	master[10];	/* Name of Master for Bundling           */
-	char	slave[10];	/* Name of Slave for Bundling            */
-	char	eaz[256];	/* EAZ/MSN                               */
-	char	drvid[25];	/* DriverId for Bindings                 */
-	int	onhtime;	/* Hangup-Timeout                        */
-	int	charge;		/* Charge-Units                          */
-	int	l2_proto;	/* Layer-2 protocol                      */
-	int	l3_proto;	/* Layer-3 protocol                      */
-	int	p_encap;	/* Encapsulation                         */
-	int	exclusive;	/* Channel, if bound exclusive           */
-	int	dialmax;	/* Dial Retry-Counter                    */
-	int	slavedelay;	/* Delay until slave starts up           */
-	int	cbdelay;	/* Delay before Callback                 */
-	int	chargehup;	/* Flag: Charge-Hangup                   */
-	int	ihup;		/* Flag: Hangup-Timeout on incoming line */
-	int	secure;		/* Flag: Secure                          */
-	int	callback;	/* Flag: Callback                        */
-	int	cbhup;		/* Flag: Reject Call before Callback     */
-	int	pppbind;	/* ippp device for bindings              */
-	int	chargeint;	/* Use fixed charge interval length      */
-	int	triggercps;	/* BogoCPS needed for triggering slave   */
-	int	dialtimeout;	/* Dial-Timeout                          */
-	int	dialwait;	/* Time to wait after failed dial        */
-	int	dialmode;	/* Flag: off / on / auto                 */
+  char name[10];     /* Name of interface                     */
+  char master[10];   /* Name of Master for Bundling           */
+  char slave[10];    /* Name of Slave for Bundling            */
+  char eaz[256];     /* EAZ/MSN                               */
+  char drvid[25];    /* DriverId for Bindings                 */
+  int  onhtime;      /* Hangup-Timeout                        */
+  int  charge;       /* Charge-Units                          */
+  int  l2_proto;     /* Layer-2 protocol                      */
+  int  l3_proto;     /* Layer-3 protocol                      */
+  int  p_encap;      /* Encapsulation                         */
+  int  exclusive;    /* Channel, if bound exclusive           */
+  int  dialmax;      /* Dial Retry-Counter                    */
+  int  slavedelay;   /* Delay until slave starts up           */
+  int  cbdelay;      /* Delay before Callback                 */
+  int  chargehup;    /* Flag: Charge-Hangup                   */
+  int  ihup;         /* Flag: Hangup-Timeout on incoming line */
+  int  secure;       /* Flag: Secure                          */
+  int  callback;     /* Flag: Callback                        */
+  int  cbhup;        /* Flag: Reject Call before Callback     */
+  int  pppbind;      /* ippp device for bindings              */
+  int  chargeint;    /* Use fixed charge interval length      */
+  int  triggercps;   /* BogoCPS needed for triggering slave   */
+  int  dialtimeout;  /* Dial-Timeout                          */
+  int  dialwait;     /* Time to wait after failed dial        */
+  int  dialmode;     /* Flag: off / on / auto                 */
 } isdn_net_ioctl_cfg;
 
 #define ISDN_NET_DIALMODE_MASK  0xC0    /* bits for status                */
@@ -150,6 +150,7 @@ typedef struct {
 #include <linux/errno.h>
 #include <linux/fs.h>
 #include <linux/major.h>
+#include <asm/segment.h>
 #include <asm/io.h>
 #include <linux/kernel.h>
 #include <linux/signal.h>
@@ -178,6 +179,8 @@ typedef struct {
  * the correspondent code in isdn.c
  */
 
+#define ISDN_MINOR_B        0
+#define ISDN_MINOR_BMAX     (ISDN_MAX_CHANNELS-1)
 #define ISDN_MINOR_CTRL     64
 #define ISDN_MINOR_CTRLMAX  (64 + (ISDN_MAX_CHANNELS-1))
 #define ISDN_MINOR_PPP      128
@@ -192,7 +195,6 @@ typedef struct {
 
 #include <linux/ppp_defs.h>
 #include <linux/if_ppp.h>
-#include <linux/if_pppvar.h>
 
 #include <linux/isdn_ppp.h>
 #endif
@@ -231,9 +233,177 @@ typedef struct {
 #define USG_MODEMORVOICE(x) (((x & ISDN_USAGE_MASK)==ISDN_USAGE_MODEM) || \
                              ((x & ISDN_USAGE_MASK)==ISDN_USAGE_VOICE)     )
 
+/* Timer-delays and scheduling-flags */
+#define ISDN_TIMER_RES         4                         /* Main Timer-Resolution   */
+#define ISDN_TIMER_02SEC       (HZ/ISDN_TIMER_RES/5)     /* Slow-Timer1 .2 sec      */
+#define ISDN_TIMER_1SEC        (HZ/ISDN_TIMER_RES)       /* Slow-Timer2 1 sec       */
+#define ISDN_TIMER_RINGING     5 /* tty RINGs = ISDN_TIMER_1SEC * this factor       */
+#define ISDN_TIMER_KEEPINT    10 /* Cisco-Keepalive = ISDN_TIMER_1SEC * this factor */
+#define ISDN_TIMER_MODEMREAD   1
+#define ISDN_TIMER_MODEMPLUS   2
+#define ISDN_TIMER_MODEMRING   4
+#define ISDN_TIMER_MODEMXMIT   8
+#define ISDN_TIMER_NETDIAL    16 
+#define ISDN_TIMER_NETHANGUP  32
+#define ISDN_TIMER_CARRIER   256 /* Wait for Carrier */
+#define ISDN_TIMER_FAST      (ISDN_TIMER_MODEMREAD | ISDN_TIMER_MODEMPLUS | \
+                              ISDN_TIMER_MODEMXMIT)
+#define ISDN_TIMER_SLOW      (ISDN_TIMER_MODEMRING | ISDN_TIMER_NETHANGUP | \
+                              ISDN_TIMER_NETDIAL | ISDN_TIMER_CARRIER)
+
+/* Timeout-Values for isdn_net_dial() */
+#define ISDN_TIMER_DTIMEOUT10 (10*HZ/(ISDN_TIMER_02SEC*(ISDN_TIMER_RES+1)))
+#define ISDN_TIMER_DTIMEOUT15 (15*HZ/(ISDN_TIMER_02SEC*(ISDN_TIMER_RES+1)))
+#define ISDN_TIMER_DTIMEOUT60 (60*HZ/(ISDN_TIMER_02SEC*(ISDN_TIMER_RES+1)))
+
 /* GLOBAL_FLAGS */
 #define ISDN_GLOBAL_STOPPED 1
 
+/*=================== Start of ip-over-ISDN stuff =========================*/
+
+/* Feature- and status-flags for a net-interface */
+#define ISDN_NET_CONNECTED  0x01       /* Bound to ISDN-Channel             */
+#define ISDN_NET_SECURE     0x02       /* Accept calls from phonelist only  */
+#define ISDN_NET_CALLBACK   0x04       /* activate callback                 */
+#define ISDN_NET_CBHUP      0x08       /* hangup before callback            */
+#define ISDN_NET_CBOUT      0x10       /* remote machine does callback      */
+
+#define ISDN_NET_MAGIC      0x49344C02 /* for paranoia-checking             */
+
+/* Phone-list-element */
+typedef struct {
+  void *next;
+  char num[ISDN_MSNLEN];
+} isdn_net_phone;
+
+/*
+   Principles when extending structures for generic encapsulation protocol
+   ("concap") support:
+   - Stuff which is hardware specific (here i4l-specific) goes in 
+     the netdev -> local structure (here: isdn_net_local)
+   - Stuff which is encapsulation protocol specific goes in the structure
+     which holds the linux device structure (here: isdn_net_device)
+*/
+
+/* Local interface-data */
+typedef struct isdn_net_local_s {
+  ulong                  magic;
+  char                   name[10];     /* Name of device                   */
+  struct net_device_stats stats;       /* Ethernet Statistics              */
+  int                    isdn_device;  /* Index to isdn-device             */
+  int                    isdn_channel; /* Index to isdn-channel            */
+  int			 ppp_slot;     /* PPPD device slot number          */
+  int                    pre_device;   /* Preselected isdn-device          */
+  int                    pre_channel;  /* Preselected isdn-channel         */
+  int                    exclusive;    /* If non-zero idx to reserved chan.*/
+  int                    flags;        /* Connection-flags                 */
+  int                    dialretry;    /* Counter for Dialout-retries      */
+  int                    dialmax;      /* Max. Number of Dial-retries      */
+  int                    cbdelay;      /* Delay before Callback starts     */
+  int                    dtimer;       /* Timeout-counter for dialing      */
+  char                   msn[ISDN_MSNLEN]; /* MSNs/EAZs for this interface */
+  u_char                 cbhup;        /* Flag: Reject Call before Callback*/
+  u_char                 dialstate;    /* State for dialing                */
+  u_char                 p_encap;      /* Packet encapsulation             */
+                                       /*   0 = Ethernet over ISDN         */
+				       /*   1 = RAW-IP                     */
+                                       /*   2 = IP with type field         */
+  u_char                 l2_proto;     /* Layer-2-protocol                 */
+				       /* See ISDN_PROTO_L2..-constants in */
+                                       /* isdnif.h                         */
+                                       /*   0 = X75/LAPB with I-Frames     */
+				       /*   1 = X75/LAPB with UI-Frames    */
+				       /*   2 = X75/LAPB with BUI-Frames   */
+				       /*   3 = HDLC                       */
+  u_char                 l3_proto;     /* Layer-3-protocol                 */
+				       /* See ISDN_PROTO_L3..-constants in */
+                                       /* isdnif.h                         */
+                                       /*   0 = Transparent                */
+  int                    huptimer;     /* Timeout-counter for auto-hangup  */
+  int                    charge;       /* Counter for charging units       */
+  ulong                  chargetime;   /* Timer for Charging info          */
+  int                    hupflags;     /* Flags for charge-unit-hangup:    */
+				       /* bit0: chargeint is invalid       */
+				       /* bit1: Getting charge-interval    */
+                                       /* bit2: Do charge-unit-hangup      */
+                                       /* bit3: Do hangup even on incoming */
+  int                    outgoing;     /* Flag: outgoing call              */
+  int                    onhtime;      /* Time to keep link up             */
+  int                    chargeint;    /* Interval between charge-infos    */
+  int                    onum;         /* Flag: at least 1 outgoing number */
+  int                    cps;          /* current speed of this interface  */
+  int                    transcount;   /* byte-counter for cps-calculation */
+  int                    sqfull;       /* Flag: netdev-queue overloaded    */
+  ulong                  sqfull_stamp; /* Start-Time of overload           */
+  ulong                  slavedelay;   /* Dynamic bundling delaytime       */
+  int                    triggercps;   /* BogoCPS needed for trigger slave */
+  isdn_net_phone         *phone[2];    /* List of remote-phonenumbers      */
+				       /* phone[0] = Incoming Numbers      */
+				       /* phone[1] = Outgoing Numbers      */
+  isdn_net_phone         *dial;        /* Pointer to dialed number         */
+  struct net_device      *master;      /* Ptr to Master device for slaves  */
+  struct net_device      *slave;       /* Ptr to Slave device for masters  */
+  struct isdn_net_local_s *next;       /* Ptr to next link in bundle       */
+  struct isdn_net_local_s *last;       /* Ptr to last link in bundle       */
+  struct isdn_net_dev_s  *netdev;      /* Ptr to netdev                    */
+  struct sk_buff_head    super_tx_queue; /* List of supervisory frames to  */
+	                               /* be transmitted asap              */
+  atomic_t frame_cnt;                  /* number of frames currently       */
+                        	       /* queued in HL driver              */    
+                                       /* Ptr to orig. hard_header_cache   */
+  spinlock_t             xmit_lock;    /* used to protect the xmit path of */
+                                       /* a particular channel (including  */
+                                       /* the frame_cnt                    */
+
+  int                    (*org_hhc)(
+				    struct neighbour *neigh,
+				    struct hh_cache *hh);
+                                       /* Ptr to orig. header_cache_update */
+  void                   (*org_hcu)(struct hh_cache *,
+				    struct net_device *,
+                                    unsigned char *);
+  int  pppbind;                        /* ippp device for bindings         */
+  int					dialtimeout;	/* How long shall we try on dialing? (jiffies) */
+  int					dialwait;		/* How long shall we wait after failed attempt? (jiffies) */
+  ulong					dialstarted;	/* jiffies of first dialing-attempt */
+  ulong					dialwait_timer;	/* jiffies of earliest next dialing-attempt */
+  int					huptimeout;		/* How long will the connection be up? (seconds) */
+#ifdef CONFIG_ISDN_X25
+  struct concap_device_ops *dops;      /* callbacks used by encapsulator   */
+#endif
+  /* use an own struct for that in later versions */
+  ulong cisco_myseq;                   /* Local keepalive seq. for Cisco   */
+  ulong cisco_mineseen;                /* returned keepalive seq. from remote */
+  ulong cisco_yourseq;                 /* Remote keepalive seq. for Cisco  */
+  int cisco_keepalive_period;		/* keepalive period */
+  ulong cisco_last_slarp_in;		/* jiffie of last keepalive packet we received */
+  char cisco_line_state;		/* state of line according to keepalive packets */
+  char cisco_debserint;			/* debugging flag of cisco hdlc with slarp */
+  struct timer_list cisco_timer;
+  struct work_struct tqueue;
+} isdn_net_local;
+
+/* the interface itself */
+typedef struct isdn_net_dev_s {
+  isdn_net_local *local;
+  isdn_net_local *queue;               /* circular list of all bundled
+					  channels, which are currently
+					  online                           */
+  spinlock_t queue_lock;               /* lock to protect queue            */
+  void *next;                          /* Pointer to next isdn-interface   */
+  struct net_device dev;               /* interface to upper levels        */
+#ifdef CONFIG_ISDN_PPP
+  ippp_bundle * pb;		/* pointer to the common bundle structure
+   			         * with the per-bundle data */
+#endif
+#ifdef CONFIG_ISDN_X25
+  struct concap_proto  *cprot; /* connection oriented encapsulation protocol */
+#endif
+
+} isdn_net_dev;
+
+/*===================== End of ip-over-ISDN stuff ===========================*/
+
 /*======================= Start of ISDN-tty stuff ===========================*/
 
 #define ISDN_ASYNC_MAGIC          0x49344C01 /* for paranoia-checking        */
@@ -250,21 +420,22 @@ typedef struct {
 #define ISDN_ASYNC_SPLIT_TERMIOS      0x0008 /* Sep. termios for dialin/out  */
 #define ISDN_SERIAL_XMIT_SIZE           1024 /* Default bufsize for write    */
 #define ISDN_SERIAL_XMIT_MAX            4000 /* Maximum bufsize for write    */
+#define ISDN_SERIAL_TYPE_NORMAL            1
+#define ISDN_SERIAL_TYPE_CALLOUT           2
 
 #ifdef CONFIG_ISDN_AUDIO
 /* For using sk_buffs with audio we need some private variables
  * within each sk_buff. For this purpose, we declare a struct here,
- * and put it always at skb->head. A few macros help accessing the
- * variables. Of course, we need to check skb_headroom prior to
- * any access.
+ * and put it always at the private skb->cb data array. A few macros help
+ * accessing the variables.
  */
-typedef struct _isdnaudio_header {
+typedef struct _isdn_audio_data {
   unsigned short dle_count;
   unsigned char  lock;
-} isdnaudio_header;
+} isdn_audio_data_t;
 
-#define ISDN_AUDIO_SKB_DLECOUNT(skb) (((isdnaudio_header*)skb->head)->dle_count)
-#define ISDN_AUDIO_SKB_LOCK(skb) (((isdnaudio_header*)skb->head)->lock)
+#define ISDN_AUDIO_SKB_DLECOUNT(skb)	(((isdn_audio_data_t *)&skb->cb[0])->dle_count)
+#define ISDN_AUDIO_SKB_LOCK(skb)	(((isdn_audio_data_t *)&skb->cb[0])->lock)
 #endif
 
 /* Private data of AT-command-interpreter */
@@ -283,7 +454,8 @@ typedef struct atemu {
 #endif
 	int          mdmcmdl;                    /* Length of Modem-Commandbuffer      */
 	int          pluscount;                  /* Counter for +++ sequence           */
-	unsigned long lastplus;                  /* Timestamp of last +                */
+	u_long       lastplus;                   /* Timestamp of last +                */
+	int	     carrierwait;                /* Seconds of carrier waiting         */
 	char         mdmcmd[255];                /* Modem-Commandbuffer                */
 	unsigned int charge;                     /* Charge units of current connection */
 } atemu;
@@ -300,13 +472,15 @@ typedef struct modem_info {
   int			line;
   int			count;		 /* # of fd on device              */
   int			blocked_open;	 /* # of blocked opens             */
+  long			session;	 /* Session of opening process     */
+  long			pgrp;		 /* pgrp of opening process        */
   int                   online;          /* 1 = B-Channel is up, drop data */
 					 /* 2 = B-Channel is up, deliver d.*/
   int                   dialing;         /* Dial in progress or ATA        */
   int                   rcvsched;        /* Receive needs schedule         */
-  struct isdn_slot     *isdn_slot;	 /* Ptr to isdn-driver/channel     */
-  struct sk_buff_head   rpqueue;         /* Queue of recv'd packets        */
-  int                   rcvcount;        /* Byte-counters for B rx         */
+  int                   isdn_driver;	 /* Index to isdn-driver           */
+  int                   isdn_channel;    /* Index to isdn-channel          */
+  int                   drv_index;       /* Index to dev->usage            */
   int                   ncarrier;        /* Flag: schedule NO CARRIER      */
   unsigned char         last_cause[8];   /* Last cause message             */
   unsigned char         last_num[ISDN_MSNLEN];
@@ -323,7 +497,6 @@ typedef struct modem_info {
   struct sk_buff_head   xmit_queue;      /* transmit queue                 */
   atomic_t              xmit_lock;       /* Semaphore for isdn_tty_write   */
 #ifdef CONFIG_ISDN_AUDIO
-  unsigned long         DLEflag;         /* Insert DLE at next read     */
   int                   vonline;         /* Voice-channel status           */
 					 /* Bit 0 = recording              */
 					 /* Bit 1 = playback               */
@@ -340,16 +513,25 @@ typedef struct modem_info {
 #endif
   struct tty_struct 	*tty;            /* Pointer to corresponding tty   */
   atemu                 emu;             /* AT-emulator data               */
-  struct timer_list     escape_timer;    /* to recognize +++ escape        */
-  struct timer_list     ring_timer;      /* for writing 'RING' responses   */
-  struct timer_list     connect_timer;   /* waiting for CONNECT            */
-  struct timer_list     read_timer;      /* read incoming data             */
+  struct termios	normal_termios;  /* For saving termios structs     */
+  struct termios	callout_termios;
   wait_queue_head_t	open_wait, close_wait;
   struct semaphore      write_sem;
+  spinlock_t	        readlock;
 } modem_info;
 
 #define ISDN_MODEM_WINSIZE 8
 
+/* Description of one ISDN-tty */
+typedef struct _isdn_modem {
+  int                refcount;				/* Number of opens        */
+  struct tty_driver  *tty_modem;			/* tty-device             */
+  struct tty_struct  *modem_table[ISDN_MAX_CHANNELS];	/* ?? copied from Orig    */
+  struct termios     *modem_termios[ISDN_MAX_CHANNELS];
+  struct termios     *modem_termios_locked[ISDN_MAX_CHANNELS];
+  modem_info         info[ISDN_MAX_CHANNELS];	   /* Private data           */
+} isdn_modem_t;
+
 /*======================= End of ISDN-tty stuff ============================*/
 
 /*======================== Start of V.110 stuff ============================*/
@@ -384,23 +566,72 @@ typedef struct {
 	char *private;
 } infostruct;
 
+#define DRV_FLAG_RUNNING 1
+#define DRV_FLAG_REJBUS  2
+#define DRV_FLAG_LOADED  4
+
+/* Description of hardware-level-driver */
+typedef struct _isdn_driver {
+	ulong               online;           /* Channel-Online flags             */
+	ulong               flags;            /* Misc driver Flags                */
+	int                 locks;            /* Number of locks for this driver  */
+	int                 channels;         /* Number of channels               */
+	wait_queue_head_t   st_waitq;         /* Wait-Queue for status-read's     */
+	int                 maxbufsize;       /* Maximum Buffersize supported     */
+	unsigned long       pktcount;         /* Until now: unused                */
+	int                 stavail;          /* Chars avail on Status-device     */
+	isdn_if            *interface;        /* Interface to driver              */
+	int                *rcverr;           /* Error-counters for B-Ch.-receive */
+	int                *rcvcount;         /* Byte-counters for B-Ch.-receive  */
+#ifdef CONFIG_ISDN_AUDIO
+	unsigned long      DLEflag;           /* Flags: Insert DLE at next read   */
+#endif
+	struct sk_buff_head *rpqueue;         /* Pointers to start of Rcv-Queue   */
+	wait_queue_head_t  *rcv_waitq;       /* Wait-Queues for B-Channel-Reads  */
+	wait_queue_head_t  *snd_waitq;       /* Wait-Queue for B-Channel-Send's  */
+	char               msn2eaz[10][ISDN_MSNLEN];  /* Mapping-Table MSN->EAZ   */
+} isdn_driver_t;
+
 /* Main driver-data */
-typedef struct _isdn_dev_t {
-	unsigned short		flags;		/* Bitmapped Flags:           */
-	int			channels;	/* Current number of channels */
-	int			net_verbose;	/* Verbose-Flag               */
-	int			modempoll;	/* Flag: tty-read active      */
-	int			tflags;		/* Timer-Flags:               */
-						/*  see ISDN_TIMER_..defines  */
-	int			global_flags;
-	infostruct		*infochain;	/* List of open info-devs.    */
-	wait_queue_head_t	info_waitq;	/* Wait-Queue for isdninfo    */
-	struct task_struct	*profd;		/* For iprofd                 */
-	struct semaphore	sem;		/* serialize list access*/
-	unsigned long		global_features; 
-} isdn_dev_t;
+typedef struct isdn_devt {
+	struct module     *owner;
+	spinlock_t	  lock;
+	unsigned short    flags;		      /* Bitmapped Flags:           */
+	int               drivers;		      /* Current number of drivers  */
+	int               channels;		      /* Current number of channels */
+	int               net_verbose;                /* Verbose-Flag               */
+	int               modempoll;		      /* Flag: tty-read active      */
+	spinlock_t	  timerlock;
+	int               tflags;                     /* Timer-Flags:               */
+	/*  see ISDN_TIMER_..defines  */
+	int               global_flags;
+	infostruct        *infochain;                 /* List of open info-devs.    */
+	wait_queue_head_t info_waitq;                 /* Wait-Queue for isdninfo    */
+	struct timer_list timer;		      /* Misc.-function Timer       */
+	int               chanmap[ISDN_MAX_CHANNELS]; /* Map minor->device-channel  */
+	int               drvmap[ISDN_MAX_CHANNELS];  /* Map minor->driver-index    */
+	int               usage[ISDN_MAX_CHANNELS];   /* Used by tty/ip/voice       */
+	char              num[ISDN_MAX_CHANNELS][ISDN_MSNLEN];
+	/* Remote number of active ch.*/
+	int               m_idx[ISDN_MAX_CHANNELS];   /* Index for mdm....          */
+	isdn_driver_t     *drv[ISDN_MAX_DRIVERS];     /* Array of drivers           */
+	isdn_net_dev      *netdev;		      /* Linked list of net-if's    */
+	char              drvid[ISDN_MAX_DRIVERS][20];/* Driver-ID                 */
+	struct task_struct *profd;                    /* For iprofd                 */
+	isdn_modem_t      mdm;			      /* tty-driver-data            */
+	isdn_net_dev      *rx_netdev[ISDN_MAX_CHANNELS]; /* rx netdev-pointers     */
+	isdn_net_dev      *st_netdev[ISDN_MAX_CHANNELS]; /* stat netdev-pointers   */
+	ulong             ibytes[ISDN_MAX_CHANNELS];  /* Statistics incoming bytes  */
+	ulong             obytes[ISDN_MAX_CHANNELS];  /* Statistics outgoing bytes  */
+	int               v110emu[ISDN_MAX_CHANNELS]; /* V.110 emulator-mode 0=none */
+	atomic_t          v110use[ISDN_MAX_CHANNELS]; /* Usage-Semaphore for stream */
+	isdn_v110_stream  *v110[ISDN_MAX_CHANNELS];   /* V.110 private data         */
+	struct semaphore  sem;                        /* serialize list access*/
+	unsigned long     global_features;
+} isdn_dev;
+
+extern isdn_dev *dev;
 
-extern isdn_dev_t	*get_isdn_dev(void);
 
 #endif /* __KERNEL__ */
 
--- diff/include/linux/isdn/capilli.h	2003-09-17 12:28:12.000000000 +0100
+++ source/include/linux/isdn/capilli.h	2004-02-23 13:56:47.000000000 +0000
@@ -1,4 +1,4 @@
-/* $Id: capilli.h,v 1.4.8.1 2001/09/23 22:24:33 kai Exp $
+/* $Id: capilli.h,v 1.1.2.2 2004/01/16 21:09:27 keil Exp $
  * 
  * Kernel CAPI 2.0 Driver Interface for Linux
  * 
@@ -85,6 +85,22 @@ void capi_ctr_resume_output(struct capi_
 void capi_ctr_handle_message(struct capi_ctr * card, u16 appl, struct sk_buff *skb);
 
 // ---------------------------------------------------------------------------
+// needed for AVM capi drivers
+
+struct capi_driver {
+	char name[32];				/* driver name */
+	char revision[32];
+
+	int (*add_card)(struct capi_driver *driver, capicardparams *data);
+
+	/* management information for kcapi */
+	struct list_head list; 
+};
+
+void register_capi_driver(struct capi_driver *driver);
+void unregister_capi_driver(struct capi_driver *driver);
+
+// ---------------------------------------------------------------------------
 // library functions for use by hardware controller drivers
 
 void capilib_new_ncci(struct list_head *head, u16 applid, u32 ncci, u32 winsize);
--- diff/include/linux/isdn_ppp.h	2003-06-30 10:07:34.000000000 +0100
+++ source/include/linux/isdn_ppp.h	2004-02-23 13:56:47.000000000 +0000
@@ -21,46 +21,65 @@
 
 struct pppcallinfo
 {
-	int calltype;
-	unsigned char local_num[64];
-	unsigned char remote_num[64];
-	int charge_units;
+  int calltype;
+  unsigned char local_num[64];
+  unsigned char remote_num[64];
+  int charge_units;
 };
 
-#define PPPIOCGCALLINFO    _IOWR('t',128,struct pppcallinfo)
-#define PPPIOCBUNDLE       _IOW('t',129,int)
-#define PPPIOCGMPFLAGS     _IOR('t',130,int)
-#define PPPIOCSMPFLAGS     _IOW('t',131,int)
-#define PPPIOCSMPMTU       _IOW('t',132,int)
-#define PPPIOCSMPMRU       _IOW('t',133,int)
-#define PPPIOCGCOMPRESSORS _IOR('t',134,unsigned long[8])
-#define PPPIOCSCOMPRESSOR  _IOW('t',135,int)
-#define PPPIOCGIFNAME      _IOR('t',136,char[IFNAMSIZ])
+#define PPPIOCGCALLINFO _IOWR('t',128,struct pppcallinfo)
+#define PPPIOCBUNDLE   _IOW('t',129,int)
+#define PPPIOCGMPFLAGS _IOR('t',130,int)
+#define PPPIOCSMPFLAGS _IOW('t',131,int)
+#define PPPIOCSMPMTU   _IOW('t',132,int)
+#define PPPIOCSMPMRU   _IOW('t',133,int)
+#define PPPIOCGCOMPRESSORS _IOR('t',134,unsigned long [8])
+#define PPPIOCSCOMPRESSOR _IOW('t',135,int)
+#define PPPIOCGIFNAME      _IOR('t',136, char [IFNAMSIZ] )
+
 
 #define SC_MP_PROT       0x00000200
 #define SC_REJ_MP_PROT   0x00000400
 #define SC_OUT_SHORT_SEQ 0x00000800
 #define SC_IN_SHORT_SEQ  0x00004000
 
+#define SC_DECOMP_ON		0x01
+#define SC_COMP_ON		0x02
+#define SC_DECOMP_DISCARD	0x04
+#define SC_COMP_DISCARD		0x08
+#define SC_LINK_DECOMP_ON	0x10
+#define SC_LINK_COMP_ON		0x20
+#define SC_LINK_DECOMP_DISCARD	0x40
+#define SC_LINK_COMP_DISCARD	0x80
+
 #define ISDN_PPP_COMP_MAX_OPTIONS 16
 
 #define IPPP_COMP_FLAG_XMIT 0x1
 #define IPPP_COMP_FLAG_LINK 0x2
 
 struct isdn_ppp_comp_data {
-	int num;
-	unsigned char options[ISDN_PPP_COMP_MAX_OPTIONS];
-	int optlen;
-	int flags;
+  int num;
+  unsigned char options[ISDN_PPP_COMP_MAX_OPTIONS];
+  int optlen;
+  int flags;
 };
 
 #ifdef __KERNEL__
 
-#include <linux/skbuff.h>
-#include <linux/ppp_defs.h>
+
+#include <linux/config.h>
+
+#ifdef CONFIG_IPPP_FILTER
+#include <linux/filter.h>
+#endif
 
 #define DECOMP_ERR_NOMEM	(-10)
 
+#define MP_END_FRAG    0x40
+#define MP_BEGIN_FRAG  0x80
+
+#define MP_MAX_QUEUE_LEN	16
+
 /*
  * We need a way for the decompressor to influence the generation of CCP
  * Reset-Requests in a variety of ways. The decompressor is already returning
@@ -79,15 +98,15 @@ struct isdn_ppp_comp_data {
 #define IPPP_RESET_MAXDATABYTES	32
 
 struct isdn_ppp_resetparams {
-	unsigned char valid:1;	/* rw Is this structure filled at all ? */
-	unsigned char rsend:1;	/* rw Should we send one at all ? */
-	unsigned char idval:1;	/* rw Is the id field valid ? */
-	unsigned char dtval:1;	/* rw Is the data field valid ? */
-	unsigned char expra:1;	/* rw Is an Ack expected for this Req ? */
-	unsigned char id;		/* wo Send CCP ResetReq with this id */
-	unsigned short maxdlen;	/* ro Max bytes to be stored in data field */
-	unsigned short dlen;		/* rw Bytes stored in data field */
-	unsigned char *data;		/* wo Data for ResetReq info field */
+  unsigned char valid:1;	/* rw Is this structure filled at all ? */
+  unsigned char rsend:1;	/* rw Should we send one at all ? */
+  unsigned char idval:1;	/* rw Is the id field valid ? */
+  unsigned char dtval:1;	/* rw Is the data field valid ? */
+  unsigned char expra:1;	/* rw Is an Ack expected for this Req ? */
+  unsigned char id;		/* wo Send CCP ResetReq with this id */
+  unsigned short maxdlen;	/* ro Max bytes to be stored in data field */
+  unsigned short dlen;		/* rw Bytes stored in data field */
+  unsigned char *data;		/* wo Data for ResetReq info field */
 };
 
 /*
@@ -95,38 +114,135 @@ struct isdn_ppp_resetparams {
  * check the original include for more information
  */
 struct isdn_ppp_compressor {
-	struct module *owner;
-	struct list_head list;
-	int num; /* CCP compression protocol number */
-  
-	void *(*alloc) (struct isdn_ppp_comp_data *);
-	void (*free) (void *state);
-	int  (*init) (void *state, struct isdn_ppp_comp_data *,
-		      int unit,int debug);
-  
-	/* The reset entry needs to get more exact information about the
-	   ResetReq or ResetAck it was called with. The parameters are
-	   obvious. If reset is called without a Req or Ack frame which
-	   could be handed into it, code MUST be set to 0. Using rsparm,
-	   the reset entry can control if and how a ResetAck is returned. */
-  
-	void (*reset) (void *state, unsigned char code, unsigned char id,
-		       unsigned char *data, unsigned len,
-		       struct isdn_ppp_resetparams *rsparm);
+  struct isdn_ppp_compressor *next, *prev;
+  struct module *owner;
+  int num; /* CCP compression protocol number */
+  
+  void *(*alloc) (struct isdn_ppp_comp_data *);
+  void (*free) (void *state);
+  int  (*init) (void *state, struct isdn_ppp_comp_data *,
+		int unit,int debug);
+  
+  /* The reset entry needs to get more exact information about the
+     ResetReq or ResetAck it was called with. The parameters are
+     obvious. If reset is called without a Req or Ack frame which
+     could be handed into it, code MUST be set to 0. Using rsparm,
+     the reset entry can control if and how a ResetAck is returned. */
+  
+  void (*reset) (void *state, unsigned char code, unsigned char id,
+		 unsigned char *data, unsigned len,
+		 struct isdn_ppp_resetparams *rsparm);
   
-	int  (*compress) (void *state, struct sk_buff *in,
-			  struct sk_buff *skb_out, int proto);
+  int  (*compress) (void *state, struct sk_buff *in,
+		    struct sk_buff *skb_out, int proto);
   
 	int  (*decompress) (void *state,struct sk_buff *in,
 			    struct sk_buff *skb_out,
 			    struct isdn_ppp_resetparams *rsparm);
   
-	void (*incomp) (void *state, struct sk_buff *in,int proto);
-	void (*stat) (void *state, struct compstat *stats);
+  void (*incomp) (void *state, struct sk_buff *in,int proto);
+  void (*stat) (void *state, struct compstat *stats);
 };
 
 extern int isdn_ppp_register_compressor(struct isdn_ppp_compressor *);
 extern int isdn_ppp_unregister_compressor(struct isdn_ppp_compressor *);
+extern int isdn_ppp_dial_slave(char *);
+extern int isdn_ppp_hangup_slave(char *);
+
+typedef struct {
+  unsigned long seqerrs;
+  unsigned long frame_drops;
+  unsigned long overflows;
+  unsigned long max_queue_len;
+} isdn_mppp_stats;
+
+typedef struct {
+  int mp_mrru;                        /* unused                             */
+  struct sk_buff * frags;	/* fragments sl list -- use skb->next */
+  long frames;			/* number of frames in the frame list */
+  unsigned int seq;		/* last processed packet seq #: any packets
+  				 * with smaller seq # will be dropped
+				 * unconditionally */
+  spinlock_t lock;
+  int ref_ct;				 
+  /* statistics */
+  isdn_mppp_stats stats;
+} ippp_bundle;
+
+#define NUM_RCV_BUFFS     64
+
+struct ippp_buf_queue {
+  struct ippp_buf_queue *next;
+  struct ippp_buf_queue *last;
+  char *buf;                 /* NULL here indicates end of queue */
+  int len;
+};
+
+/* The data structure for one CCP reset transaction */
+enum ippp_ccp_reset_states {
+  CCPResetIdle,
+  CCPResetSentReq,
+  CCPResetRcvdReq,
+  CCPResetSentAck,
+  CCPResetRcvdAck
+};
+
+struct ippp_ccp_reset_state {
+  enum ippp_ccp_reset_states state;	/* State of this transaction */
+  struct ippp_struct *is;		/* Backlink to device stuff */
+  unsigned char id;			/* Backlink id index */
+  unsigned char ta:1;			/* The timer is active (flag) */
+  unsigned char expra:1;		/* We expect a ResetAck at all */
+  int dlen;				/* Databytes stored in data */
+  struct timer_list timer;		/* For timeouts/retries */
+  /* This is a hack but seems sufficient for the moment. We do not want
+     to have this be yet another allocation for some bytes, it is more
+     memory management overhead than the whole mess is worth. */
+  unsigned char data[IPPP_RESET_MAXDATABYTES];
+};
+
+/* The data structure keeping track of the currently outstanding CCP Reset
+   transactions. */
+struct ippp_ccp_reset {
+  struct ippp_ccp_reset_state *rs[256];	/* One per possible id */
+  unsigned char lastid;			/* Last id allocated by the engine */
+};
+
+struct ippp_struct {
+  struct ippp_struct *next_link;
+  int state;
+  spinlock_t buflock;
+  struct ippp_buf_queue rq[NUM_RCV_BUFFS]; /* packet queue for isdn_ppp_read() */
+  struct ippp_buf_queue *first;  /* pointer to (current) first packet */
+  struct ippp_buf_queue *last;   /* pointer to (current) last used packet in queue */
+  wait_queue_head_t wq;
+  struct task_struct *tk;
+  unsigned int mpppcfg;
+  unsigned int pppcfg;
+  unsigned int mru;
+  unsigned int mpmru;
+  unsigned int mpmtu;
+  unsigned int maxcid;
+  struct isdn_net_local_s *lp;
+  int unit;
+  int minor;
+  unsigned int last_link_seqno;
+  long mp_seqno;
+#ifdef CONFIG_ISDN_PPP_VJ
+  unsigned char *cbuf;
+  struct slcompress *slcomp;
+#endif
+#ifdef CONFIG_IPPP_FILTER
+  struct sock_fprog pass_filter;	/* filter for packets to pass */
+  struct sock_fprog active_filter;	/* filter for pkts to reset idle */
+#endif
+  unsigned long debug;
+  struct isdn_ppp_compressor *compressor,*decompressor;
+  struct isdn_ppp_compressor *link_compressor,*link_decompressor;
+  void *decomp_stat,*comp_stat,*link_decomp_stat,*link_comp_stat;
+  struct ippp_ccp_reset *reset;	/* Allocated on demand, may never be needed */
+  unsigned long compflags;
+};
 
 #endif /* __KERNEL__ */
 #endif /* _LINUX_ISDN_PPP_H */
--- diff/include/linux/isdnif.h	2003-02-13 11:46:55.000000000 +0000
+++ source/include/linux/isdnif.h	2004-02-23 13:56:47.000000000 +0000
@@ -1,4 +1,4 @@
-/* $Id: isdnif.h,v 1.37.6.6 2001/09/23 22:25:05 kai Exp $
+/* $Id: isdnif.h,v 1.43.2.2 2004/01/12 23:08:35 keil Exp $
  *
  * Linux ISDN subsystem
  * Definition of the interface between the subsystem and its low-level drivers.
@@ -166,8 +166,17 @@ typedef struct
 #define ISDN_CMD_HANGUP   4       /* Hangup                                */
 #define ISDN_CMD_CLREAZ   5       /* Clear EAZ(s) of channel               */
 #define ISDN_CMD_SETEAZ   6       /* Set EAZ(s) of channel                 */
+#define ISDN_CMD_GETEAZ   7       /* Get EAZ(s) of channel                 */
+#define ISDN_CMD_SETSIL   8       /* Set Service-Indicator-List of channel */
+#define ISDN_CMD_GETSIL   9       /* Get Service-Indicator-List of channel */
 #define ISDN_CMD_SETL2   10       /* Set B-Chan. Layer2-Parameter          */
+#define ISDN_CMD_GETL2   11       /* Get B-Chan. Layer2-Parameter          */
 #define ISDN_CMD_SETL3   12       /* Set B-Chan. Layer3-Parameter          */
+#define ISDN_CMD_GETL3   13       /* Get B-Chan. Layer3-Parameter          */
+// #define ISDN_CMD_LOCK    14       /* Signal usage by upper levels          */
+// #define ISDN_CMD_UNLOCK  15       /* Release usage-lock                    */
+#define ISDN_CMD_SUSPEND 16       /* Suspend connection                    */
+#define ISDN_CMD_RESUME  17       /* Resume connection                     */
 #define ISDN_CMD_PROCEED 18       /* Proceed with call establishment       */
 #define ISDN_CMD_ALERT   19       /* Alert after Proceeding                */
 #define ISDN_CMD_REDIR   20       /* Redir a incoming call                 */
@@ -193,12 +202,14 @@ typedef struct
 #define ISDN_STAT_LOAD    265    /* Signal new lowlevel-driver is loaded  */
 #define ISDN_STAT_UNLOAD  266    /* Signal unload of lowlevel-driver      */
 #define ISDN_STAT_BSENT   267    /* Signal packet sent                    */
+#define ISDN_STAT_NODCH   268    /* Signal no D-Channel                   */
 #define ISDN_STAT_ADDCH   269    /* Add more Channels                     */
 #define ISDN_STAT_CAUSE   270    /* Cause-Message                         */
 #define ISDN_STAT_ICALLW  271    /* Incoming call without B-chan waiting  */
 #define ISDN_STAT_REDIR   272    /* Redir result                          */
 #define ISDN_STAT_PROT    273    /* protocol IO specific callback         */
 #define ISDN_STAT_DISPLAY 274    /* deliver a received display message    */
+#define ISDN_STAT_L1ERR   275    /* Signal Layer-1 Error                  */
 #define ISDN_STAT_FAXIND  276    /* FAX indications from HL-driver        */
 #define ISDN_STAT_AUDIO   277    /* DTMF, DSP indications                 */
 #define ISDN_STAT_DISCH   278    /* Disable/Enable channel usage          */
@@ -210,6 +221,12 @@ typedef struct
 #define ISDN_AUDIO_DTMF		1	/* Rx/Tx DTMF                   */
 
 /*
+ * Values for errcode field
+ */
+#define ISDN_STAT_L1ERR_SEND 1
+#define ISDN_STAT_L1ERR_RECV 2
+
+/*
  * Values for feature-field of interface-struct.
  */
 /* Layer 2 */
@@ -258,6 +275,7 @@ typedef struct setup_parm {
 } setup_parm;
 
 
+#ifdef CONFIG_ISDN_TTY_FAX
 /* T.30 Fax G3 */
 
 #define FAXIDLEN 21
@@ -332,6 +350,8 @@ typedef struct T30_s {
 #define ISDN_FAX_PHASE_D   	4
 #define ISDN_FAX_PHASE_E   	5
 
+#endif /* TTY_FAX */
+
 #define ISDN_FAX_CLASS1_FAE	0
 #define ISDN_FAX_CLASS1_FTS	1
 #define ISDN_FAX_CLASS1_FRS	2
@@ -398,7 +418,9 @@ typedef struct {
 		char display[85];/* display message data		*/ 
 		isdn_cmd_stat isdn_io; /* ISDN IO-parameter/result	*/
 		aux_s aux;	/* for modem commands/indications	*/
+#ifdef CONFIG_ISDN_TTY_FAX
 		T30_s	*fax;	/* Pointer to ttys fax struct		*/
+#endif
 		ulong userdata;	/* User Data */
 	} parm;
 } isdn_ctrl;
--- diff/include/linux/istallion.h	2003-10-09 09:47:34.000000000 +0100
+++ source/include/linux/istallion.h	2004-02-23 13:56:47.000000000 +0000
@@ -70,15 +70,9 @@ typedef struct {
 	void			*argp;
 	unsigned int		rxmarkmsk;
 	struct tty_struct	*tty;
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0))
-	struct wait_queue	*open_wait;
-	struct wait_queue	*close_wait;
-	struct wait_queue	*raw_wait;
-#else
 	wait_queue_head_t	open_wait;
 	wait_queue_head_t	close_wait;
 	wait_queue_head_t	raw_wait;
-#endif
 	struct work_struct	tqhangup;
 	asysigs_t		asig;
 	unsigned long		addr;
--- diff/include/linux/kernel.h	2004-02-18 08:54:13.000000000 +0000
+++ source/include/linux/kernel.h	2004-02-23 13:56:47.000000000 +0000
@@ -72,6 +72,9 @@ extern int vsprintf(char *buf, const cha
 extern int snprintf(char * buf, size_t size, const char * fmt, ...)
 	__attribute__ ((format (printf, 3, 4)));
 extern int vsnprintf(char *buf, size_t size, const char *fmt, va_list args);
+extern int scnprintf(char * buf, size_t size, const char * fmt, ...)
+	__attribute__ ((format (printf, 3, 4)));
+extern int vscnprintf(char *buf, size_t size, const char *fmt, va_list args);
 
 extern int sscanf(const char *, const char *, ...)
 	__attribute__ ((format (scanf,2,3)));
--- diff/include/linux/lapb.h	2002-10-16 04:28:34.000000000 +0100
+++ source/include/linux/lapb.h	2004-02-23 13:56:47.000000000 +0000
@@ -24,12 +24,12 @@
 #define	LAPB_DCE		0x04
 
 struct lapb_register_struct {
-	void (*connect_confirmation)(void *token, int reason);
-	void (*connect_indication)(void *token, int reason);
-	void (*disconnect_confirmation)(void *token, int reason);
-	void (*disconnect_indication)(void *token, int reason);
-	int  (*data_indication)(void *token, struct sk_buff *skb);
-	void (*data_transmit)(void *token, struct sk_buff *skb);
+	void (*connect_confirmation)(struct net_device *dev, int reason);
+	void (*connect_indication)(struct net_device *dev, int reason);
+	void (*disconnect_confirmation)(struct net_device *dev, int reason);
+	void (*disconnect_indication)(struct net_device *dev, int reason);
+	int  (*data_indication)(struct net_device *dev, struct sk_buff *skb);
+	void (*data_transmit)(struct net_device *dev, struct sk_buff *skb);
 };
 
 struct lapb_parms_struct {
@@ -44,13 +44,13 @@ struct lapb_parms_struct {
 	unsigned int mode;
 };
 
-extern int lapb_register(void *token, struct lapb_register_struct *callbacks);
-extern int lapb_unregister(void *token);
-extern int lapb_getparms(void *token, struct lapb_parms_struct *parms);
-extern int lapb_setparms(void *token, struct lapb_parms_struct *parms);
-extern int lapb_connect_request(void *token);
-extern int lapb_disconnect_request(void *token);
-extern int lapb_data_request(void *token, struct sk_buff *skb);
-extern int lapb_data_received(void *token, struct sk_buff *skb);
+extern int lapb_register(struct net_device *dev, struct lapb_register_struct *callbacks);
+extern int lapb_unregister(struct net_device *dev);
+extern int lapb_getparms(struct net_device *dev, struct lapb_parms_struct *parms);
+extern int lapb_setparms(struct net_device *dev, struct lapb_parms_struct *parms);
+extern int lapb_connect_request(struct net_device *dev);
+extern int lapb_disconnect_request(struct net_device *dev);
+extern int lapb_data_request(struct net_device *dev, struct sk_buff *skb);
+extern int lapb_data_received(struct net_device *dev, struct sk_buff *skb);
 
 #endif
--- diff/include/linux/limits.h	2002-10-16 04:29:02.000000000 +0100
+++ source/include/linux/limits.h	2004-02-23 13:56:47.000000000 +0000
@@ -3,7 +3,7 @@
 
 #define NR_OPEN	        1024
 
-#define NGROUPS_MAX       32	/* supplemental group IDs are available */
+#define NGROUPS_MAX    65536	/* supplemental group IDs are available */
 #define ARG_MAX       131072	/* # bytes of args + environ for exec() */
 #define CHILD_MAX        999    /* no limit :-) */
 #define OPEN_MAX         256	/* # open files a process may have */
--- diff/include/linux/list.h	2004-02-18 08:54:13.000000000 +0000
+++ source/include/linux/list.h	2004-02-23 13:56:47.000000000 +0000
@@ -142,8 +142,11 @@ static inline void __list_del(struct lis
  * Note: list_empty on entry does not return true after this, the entry is
  * in an undefined state.
  */
+#include <linux/kernel.h>	/* BUG_ON */
 static inline void list_del(struct list_head *entry)
 {
+	BUG_ON(entry->prev->next != entry);
+	BUG_ON(entry->next->prev != entry);
 	__list_del(entry->prev, entry->next);
 	entry->next = LIST_POISON1;
 	entry->prev = LIST_POISON2;
--- diff/include/linux/loop.h	2003-08-20 14:16:34.000000000 +0100
+++ source/include/linux/loop.h	2004-02-23 13:56:47.000000000 +0000
@@ -34,8 +34,9 @@ struct loop_device {
 	loff_t		lo_sizelimit;
 	int		lo_flags;
 	int		(*transfer)(struct loop_device *, int cmd,
-				    char *raw_buf, char *loop_buf, int size,
-				    sector_t real_block);
+				    struct page *raw_page, unsigned raw_off,
+				    struct page *loop_page, unsigned loop_off,
+				    int size, sector_t real_block);
 	char		lo_file_name[LO_NAME_SIZE];
 	char		lo_crypt_name[LO_NAME_SIZE];
 	char		lo_encrypt_key[LO_KEY_SIZE];
@@ -70,8 +71,7 @@ struct loop_device {
 /*
  * Loop flags
  */
-#define LO_FLAGS_DO_BMAP	1
-#define LO_FLAGS_READ_ONLY	2
+#define LO_FLAGS_READ_ONLY	1
 
 #include <asm/posix_types.h>	/* for __kernel_old_dev_t */
 #include <asm/types.h>		/* for __u64 */
@@ -128,8 +128,10 @@ struct loop_info64 {
 /* Support for loadable transfer modules */
 struct loop_func_table {
 	int number;	/* filter type */ 
-	int (*transfer)(struct loop_device *lo, int cmd, char *raw_buf,
-			char *loop_buf, int size, sector_t real_block);
+	int (*transfer)(struct loop_device *lo, int cmd,
+			struct page *raw_page, unsigned raw_off,
+			struct page *loop_page, unsigned loop_off,
+			int size, sector_t real_block);
 	int (*init)(struct loop_device *, const struct loop_info64 *); 
 	/* release is called from loop_unregister_transfer or clr_fd */
 	int (*release)(struct loop_device *); 
--- diff/include/linux/miscdevice.h	2004-02-09 10:36:12.000000000 +0000
+++ source/include/linux/miscdevice.h	2004-02-23 13:56:47.000000000 +0000
@@ -3,7 +3,6 @@
 #include <linux/module.h>
 #include <linux/major.h>
 
-#define BUSMOUSE_MINOR 0
 #define PSMOUSE_MINOR  1
 #define MS_BUSMOUSE_MINOR 2
 #define ATIXL_BUSMOUSE_MINOR 3
--- diff/include/linux/mm.h	2004-02-18 08:54:13.000000000 +0000
+++ source/include/linux/mm.h	2004-02-23 13:56:47.000000000 +0000
@@ -455,8 +455,6 @@ extern int install_file_pte(struct mm_st
 extern int handle_mm_fault(struct mm_struct *mm,struct vm_area_struct *vma, unsigned long address, int write_access);
 extern int make_pages_present(unsigned long addr, unsigned long end);
 extern int access_process_vm(struct task_struct *tsk, unsigned long addr, void *buf, int len, int write);
-extern long sys_remap_file_pages(unsigned long start, unsigned long size, unsigned long prot, unsigned long pgoff, unsigned long nonblock);
-extern long sys_fadvise64_64(int fd, loff_t offset, loff_t len, int advice);
 void put_dirty_page(struct task_struct *tsk, struct page *page,
 			unsigned long address, pgprot_t prot);
 
@@ -635,6 +633,30 @@ extern struct page * follow_page(struct 
 extern int remap_page_range(struct vm_area_struct *vma, unsigned long from,
 		unsigned long to, unsigned long size, pgprot_t prot);
 
+#ifdef CONFIG_NUMA
+static inline void zero_rss(struct mm_struct *mm)
+{
+	mm->rss = 0;
+	memset(mm->pernode_rss, 0, MAX_NUMNODES * sizeof(*mm->pernode_rss));
+}
+
+static inline void inc_rss(struct mm_struct *mm, struct page *page)
+{
+	mm->rss++;
+	mm->pernode_rss[page_nodenum(page)]++;
+}
+
+static inline void dec_rss(struct mm_struct *mm, struct page *page)
+{
+	mm->rss--;
+	mm->pernode_rss[page_nodenum(page)]--;
+}
+#else /* !CONFIG_NUMA */
+#define zero_rss(mm)		((mm)->rss = 0)
+#define inc_rss(mm, page)	((mm)->rss++)
+#define dec_rss(mm, page)	((mm)->rss--)
+#endif /* CONFIG_NUMA */
+
 #ifndef CONFIG_DEBUG_PAGEALLOC
 static inline void
 kernel_map_pages(struct page *page, int numpages, int enable)
--- diff/include/linux/mmzone.h	2004-02-18 08:54:13.000000000 +0000
+++ source/include/linux/mmzone.h	2004-02-23 13:56:47.000000000 +0000
@@ -69,7 +69,10 @@ struct zone {
 	 */
 	spinlock_t		lock;
 	unsigned long		free_pages;
-	unsigned long		pages_min, pages_low, pages_high;
+	unsigned long		pages_min;
+	unsigned long		pages_low;
+	unsigned long		pages_high;
+	unsigned long		reclaim_batch;
 
 	ZONE_PADDING(_pad1_)
 
@@ -149,6 +152,12 @@ struct zone {
 	unsigned long		zone_start_pfn;
 
 	/*
+	 * dummy page used as place holder during scanning of
+	 * active_list in refill_inactive_zone()
+	 */
+	struct page *scan_page;
+
+	/*
 	 * rarely used fields:
 	 */
 	char			*name;
@@ -213,6 +222,7 @@ typedef struct pglist_data {
 	int node_id;
 	struct pglist_data *pgdat_next;
 	wait_queue_head_t       kswapd_wait;
+	struct task_struct *kswapd;
 } pg_data_t;
 
 #define node_present_pages(nid)	(NODE_DATA(nid)->node_present_pages)
@@ -304,6 +314,7 @@ extern struct pglist_data contig_page_da
 #define NODE_DATA(nid)		(&contig_page_data)
 #define NODE_MEM_MAP(nid)	mem_map
 #define MAX_NODES_SHIFT		1
+#define pfn_to_nid(pfn)		(0)
 
 #else /* CONFIG_DISCONTIGMEM */
 
--- diff/include/linux/module.h	2004-02-09 10:36:12.000000000 +0000
+++ source/include/linux/module.h	2004-02-23 13:56:47.000000000 +0000
@@ -127,6 +127,24 @@ extern const struct gtype##_id __mod_##g
 #define MODULE_DEVICE_TABLE(type,name)		\
   MODULE_GENERIC_TABLE(type##_device,name)
 
+/* Version of form [<epoch>:]<version>[-<extra-version>].
+   Or for CVS/RCS ID version, everything but the number is stripped.
+  <epoch>: A (small) unsigned integer which allows you to start versions
+           anew. If not mentioned, it's zero.  eg. "2:1.0" is after
+	   "1:2.0".
+  <version>: The <version> may contain only alphanumerics and the
+           character `.'.  Ordered by numeric sort for numeric parts,
+	   ascii sort for ascii parts (as per RPM or DEB algorithm).
+  <extraversion>: Like <version>, but inserted for local
+           customizations, eg "rh3" or "rusty1".
+
+  Using this automatically adds a checksum of the .c files and the
+  local headers to the end.  Use MODULE_VERSION("") if you want just
+  this.  Macro includes room for this.
+*/
+#define MODULE_VERSION(_version) \
+  MODULE_INFO(version, _version "\0xxxxxxxxxxxxxxxxxxxxxxxx")
+
 /* Given an address, look for it in the exception tables */
 const struct exception_table_entry *search_exception_tables(unsigned long add);
 
--- diff/include/linux/msg.h	2003-06-09 14:18:20.000000000 +0100
+++ source/include/linux/msg.h	2004-02-23 13:56:47.000000000 +0000
@@ -1,7 +1,9 @@
 #ifndef _LINUX_MSG_H
 #define _LINUX_MSG_H
 
+#include <linux/list.h>
 #include <linux/ipc.h>
+#include <linux/list.h>
 
 /* ipcs ctl commands */
 #define MSG_STAT 11
@@ -93,11 +95,6 @@ struct msg_queue {
 	struct list_head q_senders;
 };
 
-asmlinkage long sys_msgget (key_t key, int msgflg);
-asmlinkage long sys_msgsnd (int msqid, struct msgbuf __user *msgp, size_t msgsz, int msgflg);
-asmlinkage long sys_msgrcv (int msqid, struct msgbuf __user *msgp, size_t msgsz, long msgtyp, int msgflg);
-asmlinkage long sys_msgctl (int msqid, int cmd, struct msqid_ds __user *buf);
-
 #endif /* __KERNEL__ */
 
 #endif /* _LINUX_MSG_H */
--- diff/include/linux/nbd.h	2004-01-19 10:22:59.000000000 +0000
+++ source/include/linux/nbd.h	2004-02-23 13:56:47.000000000 +0000
@@ -8,6 +8,8 @@
  * 2003/06/24 Louis D. Langholtz <ldl@aros.net>
  *            Removed unneeded blksize_bits field from nbd_device struct.
  *            Cleanup PARANOIA usage & code.
+ * 2004/02/19 Paul Clements
+ *            Removed PARANOIA, plus various cleanup and comments
  */
 
 #ifndef LINUX_NBD_H
@@ -32,22 +34,19 @@ enum {
 #define nbd_cmd(req) ((req)->cmd[0])
 #define MAX_NBD 128
 
-/* Define PARANOIA to include extra sanity checking code in here & driver */
-#define PARANOIA
-
 /* userspace doesn't need the nbd_device structure */
 #ifdef __KERNEL__
 
+/* values for flags field */
+#define NBD_READ_ONLY 0x0001
+#define NBD_WRITE_NOCHK 0x0002
+
 struct nbd_device {
 	int flags;
 	int harderror;		/* Code of hard error			*/
-#define NBD_READ_ONLY 0x0001
-#define NBD_WRITE_NOCHK 0x0002
 	struct socket * sock;
 	struct file * file; 	/* If == NULL, device is not ready, yet	*/
-#ifdef PARANOIA
-	int magic;		/* FIXME: not if debugging is off	*/
-#endif
+	int magic;
 	spinlock_t queue_lock;
 	struct list_head queue_head;/* Requests are added here...	*/
 	struct semaphore tx_lock;
@@ -58,16 +57,14 @@ struct nbd_device {
 
 #endif
 
-/* This now IS in some kind of include file...	*/
-
-/* These are send over network in request/reply magic field */
+/* These are sent over the network in the request/reply magic fields */
 
 #define NBD_REQUEST_MAGIC 0x25609513
 #define NBD_REPLY_MAGIC 0x67446698
 /* Do *not* use magics: 0x12560953 0x96744668. */
 
 /*
- * This is packet used for communication between client and
+ * This is the packet used for communication between client and
  * server. All data are in network byte order.
  */
 struct nbd_request {
@@ -82,6 +79,10 @@ struct nbd_request {
 #endif
 ;
 
+/*
+ * This is the reply packet that nbd-server sends back to the client after
+ * it has completed an I/O request (or an error occurs).
+ */
 struct nbd_reply {
 	u32 magic;
 	u32 error;		/* 0 = ok, else error	*/
--- diff/include/linux/netdevice.h	2004-02-18 08:54:13.000000000 +0000
+++ source/include/linux/netdevice.h	2004-02-23 13:56:47.000000000 +0000
@@ -456,6 +456,12 @@ struct net_device
 						     unsigned char *haddr);
 	int			(*neigh_setup)(struct net_device *dev, struct neigh_parms *);
 	int			(*accept_fastpath)(struct net_device *, struct dst_entry*);
+#ifdef CONFIG_NETPOLL_RX
+	int			netpoll_rx;
+#endif
+#ifdef CONFIG_NET_POLL_CONTROLLER
+	void                    (*poll_controller)(struct net_device *dev);
+#endif
 
 	/* bridge stuff */
 	struct net_bridge_port	*br_port;
@@ -545,6 +551,9 @@ extern int		dev_new_index(void);
 extern struct net_device	*dev_get_by_index(int ifindex);
 extern struct net_device	*__dev_get_by_index(int ifindex);
 extern int		dev_restart(struct net_device *dev);
+#ifdef CONFIG_NETPOLL_TRAP
+extern int		netpoll_trap(void);
+#endif
 
 typedef int gifconf_func_t(struct net_device * dev, char * bufptr, int len);
 extern int		register_gifconf(unsigned int family, gifconf_func_t * gifconf);
@@ -603,12 +612,20 @@ static inline void netif_start_queue(str
 
 static inline void netif_wake_queue(struct net_device *dev)
 {
+#ifdef CONFIG_NETPOLL_TRAP
+	if (netpoll_trap())
+		return;
+#endif
 	if (test_and_clear_bit(__LINK_STATE_XOFF, &dev->state))
 		__netif_schedule(dev);
 }
 
 static inline void netif_stop_queue(struct net_device *dev)
 {
+#ifdef CONFIG_NETPOLL_TRAP
+	if (netpoll_trap())
+		return;
+#endif
 	set_bit(__LINK_STATE_XOFF, &dev->state);
 }
 
--- diff/include/linux/netfilter_ipv4/ip_nat.h	2003-09-30 15:46:20.000000000 +0100
+++ source/include/linux/netfilter_ipv4/ip_nat.h	2004-02-23 13:56:47.000000000 +0000
@@ -100,9 +100,6 @@ struct ip_nat_info
 	/* Manipulations to be done on this conntrack. */
 	struct ip_nat_info_manip manips[IP_NAT_MAX_MANIPS];
 
-	/* The mapping type which created us (NULL for null mapping). */
-	const struct ip_nat_mapping_type *mtype;
-
 	struct ip_nat_hash bysource, byipsproto;
 
 	/* Helper (NULL if none). */
--- diff/include/linux/netfilter_ipv4/listhelp.h	2003-07-08 09:55:19.000000000 +0100
+++ source/include/linux/netfilter_ipv4/listhelp.h	2004-02-23 13:56:47.000000000 +0000
@@ -11,48 +11,42 @@
    required to allow inlining of cmpfn. */
 #define LIST_FIND(head, cmpfn, type, args...)		\
 ({							\
-	const struct list_head *__i = (head);		\
+	const struct list_head *__i, *__j = NULL;	\
 							\
 	ASSERT_READ_LOCK(head);				\
-	do {						\
-		__i = __i->next;			\
-		if (__i == (head)) {			\
-			__i = NULL;			\
+	list_for_each(__i, (head))			\
+		if (cmpfn((const type)__i , ## args)) {	\
+			__j = __i;			\
 			break;				\
 		}					\
-	} while (!cmpfn((const type)__i , ## args));	\
-	(type)__i;					\
+	(type)__j;					\
 })
 
-#define LIST_FIND_W(head, cmpfn, type, args...)	\
-({						\
-	const struct list_head *__i = (head);	\
-						\
-	ASSERT_WRITE_LOCK(head);		\
-	do {					\
-		__i = __i->next;		\
-		if (__i == (head)) {		\
-			__i = NULL;		\
-			break;			\
-		}				\
-	} while (!cmpfn((type)__i , ## args));	\
-	(type)__i;				\
+#define LIST_FIND_W(head, cmpfn, type, args...)		\
+({							\
+	const struct list_head *__i, *__j = NULL;	\
+							\
+	ASSERT_WRITE_LOCK(head);			\
+	list_for_each(__i, (head))			\
+		if (cmpfn((type)__i , ## args)) {	\
+			__j = __i;			\
+			break;				\
+		}					\
+	(type)__j;					\
 })
 
 /* Just like LIST_FIND but we search backwards */
 #define LIST_FIND_B(head, cmpfn, type, args...)		\
 ({							\
-	const struct list_head *__i = (head);		\
+	const struct list_head *__i, *__j = NULL;	\
 							\
 	ASSERT_READ_LOCK(head);				\
-	do {						\
-		__i = __i->prev;			\
-		if (__i == (head)) {			\
-			__i = NULL;			\
+	list_for_each_prev(__i, (head))			\
+		if (cmpfn((const type)__i , ## args)) {	\
+			__j = __i;			\
 			break;				\
 		}					\
-	} while (!cmpfn((const type)__i , ## args));	\
-	(type)__i;					\
+	(type)__j;					\
 })
 
 static inline int
@@ -100,9 +94,9 @@ list_prepend(struct list_head *head, voi
 do {								\
 	struct list_head *__i;					\
 	ASSERT_WRITE_LOCK(head);				\
-	for (__i = (head)->next;				\
-	     !cmpfn((new), (typeof (new))__i) && __i != (head);	\
-	     __i = __i->next);					\
+	list_for_each(__i, (head))				\
+		if ((new), (typeof (new))__i)			\
+			break;					\
 	list_add((struct list_head *)(new), __i->prev);		\
 } while(0)
 
--- diff/include/linux/netlink.h	2003-10-09 09:47:34.000000000 +0100
+++ source/include/linux/netlink.h	2004-02-23 13:56:47.000000000 +0000
@@ -11,6 +11,7 @@
 #define NETLINK_TCPDIAG		4	/* TCP socket monitoring			*/
 #define NETLINK_NFLOG		5	/* netfilter/iptables ULOG */
 #define NETLINK_XFRM		6	/* ipsec */
+#define NETLINK_SELINUX		7	/* SELinux event notifications */
 #define NETLINK_ARPD		8
 #define NETLINK_ROUTE6		11	/* af_inet6 route comm channel */
 #define NETLINK_IP6_FW		13
--- diff/include/linux/nfs_fs.h	2004-02-18 08:54:13.000000000 +0000
+++ source/include/linux/nfs_fs.h	2004-02-23 13:56:47.000000000 +0000
@@ -99,7 +99,7 @@ struct nfs_inode {
 	/*
 	 * Various flags
 	 */
-	unsigned short		flags;
+	unsigned int		flags;
 
 	/*
 	 * read_cache_jiffies is when we started read-caching this inode,
@@ -118,19 +118,22 @@ struct nfs_inode {
 	 *
 	 *	mtime != read_cache_mtime
 	 */
+	unsigned long		readdir_timestamp;
 	unsigned long		read_cache_jiffies;
-	struct timespec		read_cache_ctime;
-	struct timespec		read_cache_mtime;
-	__u64			read_cache_isize;
 	unsigned long		attrtimeo;
 	unsigned long		attrtimeo_timestamp;
 	__u64			change_attr;		/* v4 only */
 
+	/* "Generation counter" for the attribute cache. This is
+	 * bumped whenever we update the metadata on the
+	 * server.
+	 */
+	unsigned long		cache_change_attribute;
 	/*
-	 * Timestamp that dates the change made to read_cache_mtime.
-	 * This is of use for dentry revalidation
+	 * Counter indicating the number of outstanding requests that
+	 * will cause a file data update.
 	 */
-	unsigned long		cache_mtime_jiffies;
+	atomic_t		data_updates;
 
 	struct nfs_access_cache	cache_access;
 
@@ -170,7 +173,9 @@ struct nfs_inode {
 #define NFS_INO_STALE		0x0001		/* possible stale inode */
 #define NFS_INO_ADVISE_RDPLUS   0x0002          /* advise readdirplus */
 #define NFS_INO_REVALIDATING	0x0004		/* revalidating attrs */
-#define NFS_INO_FLUSH		0x0008		/* inode is due for flushing */
+#define NFS_INO_INVALID_ATTR	0x0008		/* cached attrs are invalid */
+#define NFS_INO_INVALID_DATA	0x0010		/* cached data is invalid */
+#define NFS_INO_INVALID_ATIME	0x0020		/* cached atime is invalid */
 #define NFS_INO_FAKE_ROOT	0x0080		/* root inode placeholder */
 
 static inline struct nfs_inode *NFS_I(struct inode *inode)
@@ -186,15 +191,7 @@ static inline struct nfs_inode *NFS_I(st
 #define NFS_ADDR(inode)			(RPC_PEERADDR(NFS_CLIENT(inode)))
 #define NFS_COOKIEVERF(inode)		(NFS_I(inode)->cookieverf)
 #define NFS_READTIME(inode)		(NFS_I(inode)->read_cache_jiffies)
-#define NFS_MTIME_UPDATE(inode)		(NFS_I(inode)->cache_mtime_jiffies)
-#define NFS_CACHE_CTIME(inode)		(NFS_I(inode)->read_cache_ctime)
-#define NFS_CACHE_MTIME(inode)		(NFS_I(inode)->read_cache_mtime)
-#define NFS_CACHE_ISIZE(inode)		(NFS_I(inode)->read_cache_isize)
 #define NFS_CHANGE_ATTR(inode)		(NFS_I(inode)->change_attr)
-#define NFS_CACHEINV(inode) \
-do { \
-	NFS_READTIME(inode) = jiffies - NFS_MAXATTRTIMEO(inode) - 1; \
-} while (0)
 #define NFS_ATTRTIMEO(inode)		(NFS_I(inode)->attrtimeo)
 #define NFS_MINATTRTIMEO(inode) \
 	(S_ISDIR(inode->i_mode)? NFS_SERVER(inode)->acdirmin \
@@ -211,6 +208,17 @@ do { \
 
 #define NFS_FILEID(inode)		(NFS_I(inode)->fileid)
 
+static inline int nfs_caches_unstable(struct inode *inode)
+{
+	return atomic_read(&NFS_I(inode)->data_updates) != 0;
+}
+
+static inline void NFS_CACHEINV(struct inode *inode)
+{
+	if (!nfs_caches_unstable(inode))
+		NFS_FLAGS(inode) |= NFS_INO_INVALID_ATTR;
+}
+
 static inline int nfs_server_capable(struct inode *inode, int cap)
 {
 	return NFS_SERVER(inode)->caps & cap;
@@ -227,13 +235,37 @@ loff_t page_offset(struct page *page)
 	return ((loff_t)page->index) << PAGE_CACHE_SHIFT;
 }
 
+/**
+ * nfs_save_change_attribute - Returns the inode attribute change cookie
+ * @inode - pointer to inode
+ * The "change attribute" is updated every time we finish an operation
+ * that will result in a metadata change on the server.
+ */
+static inline long nfs_save_change_attribute(struct inode *inode)
+{
+	return NFS_I(inode)->cache_change_attribute;
+}
+
+/**
+ * nfs_verify_change_attribute - Detects NFS inode cache updates
+ * @inode - pointer to inode
+ * @chattr - previously saved change attribute
+ * Return "false" if metadata has been updated (or is in the process of
+ * being updated) since the change attribute was saved.
+ */
+static inline int nfs_verify_change_attribute(struct inode *inode, unsigned long chattr)
+{
+	return !nfs_caches_unstable(inode)
+		&& chattr == NFS_I(inode)->cache_change_attribute;
+}
+
 /*
  * linux/fs/nfs/inode.c
  */
 extern void nfs_zap_caches(struct inode *);
 extern struct inode *nfs_fhget(struct super_block *, struct nfs_fh *,
 				struct nfs_fattr *);
-extern int __nfs_refresh_inode(struct inode *, struct nfs_fattr *);
+extern int nfs_refresh_inode(struct inode *, struct nfs_fattr *);
 extern int nfs_getattr(struct vfsmount *, struct dentry *, struct kstat *);
 extern int nfs_permission(struct inode *, int, struct nameidata *);
 extern void nfs_set_mmcred(struct inode *, struct rpc_cred *);
@@ -241,6 +273,13 @@ extern int nfs_open(struct inode *, stru
 extern int nfs_release(struct inode *, struct file *);
 extern int __nfs_revalidate_inode(struct nfs_server *, struct inode *);
 extern int nfs_setattr(struct dentry *, struct iattr *);
+extern void nfs_begin_attr_update(struct inode *);
+extern void nfs_end_attr_update(struct inode *);
+extern void nfs_begin_data_update(struct inode *);
+extern void nfs_end_data_update(struct inode *);
+
+/* linux/net/ipv4/ipconfig.c: trims ip addr off front of name, too. */
+extern u32 root_nfs_parse_addr(char *name); /*__init*/
 
 /*
  * linux/fs/nfs/file.c
@@ -383,20 +422,27 @@ extern int  nfsroot_mount(struct sockadd
 /*
  * inline functions
  */
-static inline int
-nfs_revalidate_inode(struct nfs_server *server, struct inode *inode)
+
+static inline int nfs_attribute_timeout(struct inode *inode)
 {
-	if (time_before(jiffies, NFS_READTIME(inode)+NFS_ATTRTIMEO(inode)))
-		return NFS_STALE(inode) ? -ESTALE : 0;
-	return __nfs_revalidate_inode(server, inode);
+	struct nfs_inode *nfsi = NFS_I(inode);
+
+	return time_after(jiffies, nfsi->read_cache_jiffies+nfsi->attrtimeo);
 }
 
-static inline int
-nfs_refresh_inode(struct inode *inode, struct nfs_fattr *fattr)
+/**
+ * nfs_revalidate_inode - Revalidate the inode attributes
+ * @server - pointer to nfs_server struct
+ * @inode - pointer to inode struct
+ *
+ * Updates inode attribute information by retrieving the data from the server.
+ */
+static inline int nfs_revalidate_inode(struct nfs_server *server, struct inode *inode)
 {
-	if ((fattr->valid & NFS_ATTR_FATTR) == 0)
-		return 0;
-	return __nfs_refresh_inode(inode,fattr);
+	if (!(NFS_FLAGS(inode) & (NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA))
+			&& !nfs_attribute_timeout(inode))
+		return NFS_STALE(inode) ? -ESTALE : 0;
+	return __nfs_revalidate_inode(server, inode);
 }
 
 static inline loff_t
--- diff/include/linux/nfs_fs_sb.h	2004-02-18 08:54:13.000000000 +0000
+++ source/include/linux/nfs_fs_sb.h	2004-02-23 13:56:47.000000000 +0000
@@ -28,6 +28,8 @@ struct nfs_server {
 	char *			hostname;	/* remote hostname */
 	struct nfs_fh		fh;
 	struct sockaddr_in	addr;
+	unsigned int		wactive;	/* # write requests in progress */
+	wait_queue_head_t	writerq;	/* writers waiting to write */
 #ifdef CONFIG_NFS_V4
 	/* Our own IP address, as a null-terminated string.
 	 * This is used to generate the clientid, and the callback address.
--- diff/include/linux/nfs_page.h	2004-02-18 08:54:13.000000000 +0000
+++ source/include/linux/nfs_page.h	2004-02-23 13:56:47.000000000 +0000
@@ -53,7 +53,8 @@ extern	void nfs_release_request(struct n
 extern	void nfs_list_add_request(struct nfs_page *, struct list_head *);
 
 extern	int nfs_scan_list(struct list_head *, struct list_head *,
-			  struct file *, unsigned long, unsigned int);
+			  struct file *, unsigned long, unsigned int,
+			  unsigned int, unsigned int);
 extern	int nfs_coalesce_requests(struct list_head *, struct list_head *,
 				  unsigned int);
 extern  int nfs_wait_on_request(struct nfs_page *);
--- diff/include/linux/nfsd/auth.h	2002-10-16 04:27:48.000000000 +0100
+++ source/include/linux/nfsd/auth.h	2004-02-23 13:56:47.000000000 +0000
@@ -21,7 +21,7 @@
  * Set the current process's fsuid/fsgid etc to those of the NFS
  * client user
  */
-void		nfsd_setuser(struct svc_rqst *, struct svc_export *);
+int nfsd_setuser(struct svc_rqst *, struct svc_export *);
 
 #endif /* __KERNEL__ */
 #endif /* LINUX_NFSD_AUTH_H */
--- diff/include/linux/nfsd/nfsd.h	2003-09-30 15:46:20.000000000 +0100
+++ source/include/linux/nfsd/nfsd.h	2004-02-23 13:56:47.000000000 +0000
@@ -86,7 +86,7 @@ int		nfsd_create_v3(struct svc_rqst *, s
 				struct svc_fh *res, int createmode,
 				u32 *verifier, int *truncp);
 int		nfsd_commit(struct svc_rqst *, struct svc_fh *,
-				off_t, unsigned long);
+				loff_t, unsigned long);
 #endif /* CONFIG_NFSD_V3 */
 int		nfsd_open(struct svc_rqst *, struct svc_fh *, int,
 				int, struct file *);
--- diff/include/linux/nfsd/syscall.h	2003-05-21 11:50:16.000000000 +0100
+++ source/include/linux/nfsd/syscall.h	2004-02-23 13:56:47.000000000 +0000
@@ -115,7 +115,6 @@ union nfsctl_res {
 /*
  * Kernel syscall implementation.
  */
-extern asmlinkage long	sys_nfsservctl(int, struct nfsctl_arg __user *, void __user *);
 extern int		exp_addclient(struct nfsctl_client *ncp);
 extern int		exp_delclient(struct nfsctl_client *ncp);
 extern int		exp_export(struct nfsctl_export *nxp);
--- diff/include/linux/notifier.h	2002-11-11 11:09:38.000000000 +0000
+++ source/include/linux/notifier.h	2004-02-23 13:56:47.000000000 +0000
@@ -63,7 +63,6 @@ extern int notifier_call_chain(struct no
 #define CPU_ONLINE	0x0002 /* CPU (unsigned)v is up */
 #define CPU_UP_PREPARE	0x0003 /* CPU (unsigned)v coming up */
 #define CPU_UP_CANCELED	0x0004 /* CPU (unsigned)v NOT coming up */
-#define CPU_OFFLINE	0x0005 /* CPU (unsigned)v offline (still scheduling) */
 #define CPU_DEAD	0x0006 /* CPU (unsigned)v dead */
 
 #endif /* __KERNEL__ */
--- diff/include/linux/page-flags.h	2004-01-19 10:22:59.000000000 +0000
+++ source/include/linux/page-flags.h	2004-02-23 13:56:47.000000000 +0000
@@ -108,10 +108,11 @@ struct page_state {
 
 	unsigned long pgscan;		/* pages scanned by page reclaim */
 	unsigned long pgrefill;		/* inspected in refill_inactive_zone */
-	unsigned long pgsteal;		/* total pages reclaimed */
+	unsigned long pgsteal_hi;	/* total highmem pages reclaimed */
+	unsigned long pgsteal_lo;	/* total lowmem pages reclaimed */
 	unsigned long pginodesteal;	/* pages reclaimed via inode freeing */
-	unsigned long kswapd_steal;	/* pages reclaimed by kswapd */
 
+	unsigned long kswapd_steal;	/* pages reclaimed by kswapd */
 	unsigned long kswapd_inodesteal;/* reclaimed via kswapd inode freeing */
 	unsigned long pageoutrun;	/* kswapd's calls to page reclaim */
 	unsigned long allocstall;	/* direct reclaim calls */
--- diff/include/linux/parport.h	2004-02-18 08:54:13.000000000 +0000
+++ source/include/linux/parport.h	2004-02-23 13:56:47.000000000 +0000
@@ -294,7 +294,7 @@ struct parport {
 	struct pardevice *waithead;
 	struct pardevice *waittail;
 	
-	struct parport *next;
+	struct list_head list;
 	unsigned int flags;
 
 	void *sysctl_table;
@@ -313,6 +313,7 @@ struct parport {
 	atomic_t ref_count;
 
 	struct list_head full_list;
+	struct parport *slaves[3];
 };
 
 #define DEFAULT_SPIN_TIME 500 /* us */
@@ -321,7 +322,7 @@ struct parport_driver {
 	const char *name;
 	void (*attach) (struct parport *);
 	void (*detach) (struct parport *);
-	struct parport_driver *next;
+	struct list_head list;
 };
 
 /* parport_register_port registers a new parallel port at the given
@@ -339,12 +340,7 @@ struct parport *parport_register_port(un
 void parport_announce_port (struct parport *port);
 
 /* Unregister a port. */
-extern void parport_unregister_port(struct parport *port);
-
-/* parport_enumerate returns a pointer to the linked list of all the
-   ports in this machine.  DON'T USE THIS.  Use
-   parport_register_driver instead. */
-struct parport *parport_enumerate(void);
+extern void parport_remove_port(struct parport *port);
 
 /* Register a new high-level driver. */
 extern int parport_register_driver (struct parport_driver *);
@@ -451,9 +447,6 @@ static __inline__ int parport_yield_bloc
 
 #define PARPORT_FLAG_EXCL		(1<<1)	/* EXCL driver registered. */
 
-extern int parport_parse_irqs(int, const char *[], int irqval[]);
-extern int parport_parse_dmas(int, const char *[], int dmaval[]);
-
 /* IEEE1284 functions */
 extern void parport_ieee1284_interrupt (int, void *, struct pt_regs *);
 extern int parport_negotiate (struct parport *, int mode);
@@ -538,8 +531,6 @@ extern int parport_proc_register(struct 
 extern int parport_proc_unregister(struct parport *pp);
 extern int parport_device_proc_register(struct pardevice *device);
 extern int parport_device_proc_unregister(struct pardevice *device);
-extern int parport_default_proc_register(void);
-extern int parport_default_proc_unregister(void);
 
 /* If PC hardware is the only type supported, we can optimise a bit.  */
 #if (defined(CONFIG_PARPORT_PC) || defined(CONFIG_PARPORT_PC_MODULE)) && !(defined(CONFIG_PARPORT_ARC) || defined(CONFIG_PARPORT_ARC_MODULE)) && !(defined(CONFIG_PARPORT_AMIGA) || defined(CONFIG_PARPORT_AMIGA_MODULE)) && !(defined(CONFIG_PARPORT_MFC3) || defined(CONFIG_PARPORT_MFC3_MODULE)) && !(defined(CONFIG_PARPORT_ATARI) || defined(CONFIG_PARPORT_ATARI_MODULE)) && !(defined(CONFIG_USB_USS720) || defined(CONFIG_USB_USS720_MODULE)) && !(defined(CONFIG_PARPORT_SUNBPP) || defined(CONFIG_PARPORT_SUNBPP_MODULE)) && !defined(CONFIG_PARPORT_OTHER)
--- diff/include/linux/parport_pc.h	2004-02-18 08:54:13.000000000 +0000
+++ source/include/linux/parport_pc.h	2004-02-23 13:56:47.000000000 +0000
@@ -39,6 +39,8 @@ struct parport_pc_private {
 	char *dma_buf;
 	dma_addr_t dma_handle;
 	struct pci_dev *dev;
+	struct list_head list;
+	struct parport *port;
 };
 
 static __inline__ void parport_pc_write_data(struct parport *p, unsigned char d)
--- diff/include/linux/pci.h	2004-02-18 08:54:13.000000000 +0000
+++ source/include/linux/pci.h	2004-02-23 13:56:47.000000000 +0000
@@ -304,18 +304,60 @@
 #define  PCI_X_CMD_ERO		0x0002	/* Enable Relaxed Ordering */
 #define  PCI_X_CMD_MAX_READ	0x000c	/* Max Memory Read Byte Count */
 #define  PCI_X_CMD_MAX_SPLIT	0x0070	/* Max Outstanding Split Transactions */
-#define PCI_X_DEVFN		4	/* A copy of devfn. */
-#define PCI_X_BUSNR		5	/* Bus segment number */
-#define PCI_X_STATUS		6	/* PCI-X capabilities */
-#define  PCI_X_STATUS_64BIT	0x0001	/* 64-bit device */
-#define  PCI_X_STATUS_133MHZ	0x0002	/* 133 MHz capable */
-#define  PCI_X_STATUS_SPL_DISC	0x0004	/* Split Completion Discarded */
-#define  PCI_X_STATUS_UNX_SPL	0x0008	/* Unexpected Split Completion */
-#define  PCI_X_STATUS_COMPLEX	0x0010	/* Device Complexity */
-#define  PCI_X_STATUS_MAX_READ	0x0060	/* Designed Maximum Memory Read Count */
-#define  PCI_X_STATUS_MAX_SPLIT	0x0380	/* Design Max Outstanding Split Trans */
-#define  PCI_X_STATUS_MAX_CUM	0x1c00	/* Designed Max Cumulative Read Size */
-#define  PCI_X_STATUS_SPL_ERR	0x2000	/* Rcvd Split Completion Error Msg */
+#define PCI_X_STATUS		4	/* PCI-X capabilities */
+#define  PCI_X_STATUS_DEVFN	0x000000ff	/* A copy of devfn */
+#define  PCI_X_STATUS_BUS	0x0000ff00	/* A copy of bus nr */
+#define  PCI_X_STATUS_64BIT	0x00010000	/* 64-bit device */
+#define  PCI_X_STATUS_133MHZ	0x00020000	/* 133 MHz capable */
+#define  PCI_X_STATUS_SPL_DISC	0x00040000	/* Split Completion Discarded */
+#define  PCI_X_STATUS_UNX_SPL	0x00080000	/* Unexpected Split Completion */
+#define  PCI_X_STATUS_COMPLEX	0x00100000	/* Device Complexity */
+#define  PCI_X_STATUS_MAX_READ	0x00600000	/* Designed Max Memory Read Count */
+#define  PCI_X_STATUS_MAX_SPLIT	0x03800000	/* Designed Max Outstanding Split Transactions */
+#define  PCI_X_STATUS_MAX_CUM	0x1c000000	/* Designed Max Cumulative Read Size */
+#define  PCI_X_STATUS_SPL_ERR	0x20000000	/* Rcvd Split Completion Error Msg */
+#define  PCI_X_STATUS_266MHZ	0x40000000	/* 266 MHz capable */
+#define  PCI_X_STATUS_533MHZ	0x80000000	/* 533 MHz capable */
+
+/* Extended Capabilities (PCI-X 2.0 and Express) */
+#define PCI_EXT_CAP_ID_ERR	1
+#define PCI_EXT_CAP_ID_VC	2
+#define PCI_EXT_CAP_ID_DSN	3
+#define PCI_EXT_CAP_ID_PWR	4
+
+/* Advanced Error Reporting */
+#define PCI_ERR_UNCOR_STATUS	4
+#define PCI_ERR_UNCOR_MASK	8
+#define PCI_ERR_UNCOR_SEVER	12
+#define PCI_ERR_COR_STATUS	16
+#define PCI_ERR_COR_MASK	20
+#define PCI_ERR_CAP		24
+#define PCI_ERR_HEADER_LOG	28
+#define PCI_ERR_ROOT_COMMAND	44
+#define PCI_ERR_ROOT_STATUS	48
+#define PCI_ERR_ROOT_COR_SRC	52
+#define PCI_ERR_ROOT_SRC	54
+
+/* Virtual Channel */
+#define PCI_VC_PORT_REG1	4
+#define PCI_VC_PORT_REG2	8
+#define PCI_VC_PORT_CTRL	12
+#define PCI_VC_PORT_STATUS	14
+#define PCI_VC_RES_CAP		16
+#define PCI_VC_RES_CTRL		20
+#define PCI_VC_RES_STATUS	26
+
+/* Power Budgeting */
+#define PCI_PWR_DSR		4	/* Data Select Register */
+#define PCI_PWR_DATA		8	/* Data Register */
+#define  PCI_PWR_DATA_BASE	0x000000ff	/* Base Power */
+#define  PCI_PWR_DATA_SCALE	0x00000300	/* Data Scale */
+#define  PCI_PWR_DATA_PM_SUB	0x00001c00	/* PM Sub State */
+#define  PCI_PWR_DATA_PM_STATE	0x00006000	/* PM State */
+#define  PCI_PWR_DATA_TYPE	0x00038000	/* Type */
+#define  PCI_PWR_DATA_RAIL	0x000c0000	/* Power Rail */
+#define PCI_PWR_CAP		12	/* Capability */
+#define  PCI_PWR_CAP_BUDGET	0x01	/* Already included in system budget */
 
 /* Include the ID list */
 
@@ -362,8 +404,6 @@ enum pci_mmap_state {
 #define PCI_DMA_NONE		3
 
 #define DEVICE_COUNT_COMPATIBLE	4
-#define DEVICE_COUNT_IRQ	2
-#define DEVICE_COUNT_DMA	2
 #define DEVICE_COUNT_RESOURCE	12
 
 /*
@@ -409,6 +449,8 @@ struct pci_dev {
 	unsigned short vendor_compatible[DEVICE_COUNT_COMPATIBLE];
 	unsigned short device_compatible[DEVICE_COUNT_COMPATIBLE];
 
+	int		cfg_size;	/* Size of configuration space */
+
 	/*
 	 * Instead of touching interrupt line and base address registers
 	 * directly, use the values stored here. They might be different!
@@ -470,6 +512,8 @@ struct pci_bus {
 
 	char		name[48];
 
+	unsigned short  bridge_ctl;	/* manage NO_ISA/FBB/et al behaviors */
+	unsigned short  pad2;
 	struct device		*bridge;
 	struct class_device	class_dev;
 };
@@ -606,6 +650,7 @@ struct pci_dev *pci_find_subsys (unsigne
 struct pci_dev *pci_find_class (unsigned int class, const struct pci_dev *from);
 struct pci_dev *pci_find_slot (unsigned int bus, unsigned int devfn);
 int pci_find_capability (struct pci_dev *dev, int cap);
+int pci_find_ext_capability (struct pci_dev *dev, int cap);
 struct pci_bus * pci_find_next_bus(const struct pci_bus *from);
 
 struct pci_dev *pci_get_device (unsigned int vendor, unsigned int device, struct pci_dev *from);
@@ -768,6 +813,7 @@ static inline int pci_assign_resource(st
 static inline int pci_register_driver(struct pci_driver *drv) { return 0;}
 static inline void pci_unregister_driver(struct pci_driver *drv) { }
 static inline int pci_find_capability (struct pci_dev *dev, int cap) {return 0; }
+static inline int pci_find_ext_capability (struct pci_dev *dev, int cap) {return 0; }
 static inline const struct pci_device_id *pci_match_device(const struct pci_device_id *ids, const struct pci_dev *dev) { return NULL; }
 
 /* Power management related routines */
--- diff/include/linux/pci_ids.h	2004-02-18 08:54:13.000000000 +0000
+++ source/include/linux/pci_ids.h	2004-02-23 13:56:47.000000000 +0000
@@ -1422,11 +1422,14 @@
 #define PCI_SUBVENDOR_ID_KEYSPAN	0x11a9
 #define PCI_SUBDEVICE_ID_KEYSPAN_SX2	0x5334
 
-#define PCI_VENDOR_ID_GALILEO		0x11ab
-#define PCI_DEVICE_ID_GALILEO_GT64011	0x4146
-#define PCI_DEVICE_ID_GALILEO_GT64111	0x4146
-#define PCI_DEVICE_ID_GALILEO_GT96100	0x9652
-#define PCI_DEVICE_ID_GALILEO_GT96100A	0x9653
+#define PCI_VENDOR_ID_MARVELL		0x11ab
+#define PCI_DEVICE_ID_MARVELL_GT64011	0x4146
+#define PCI_DEVICE_ID_MARVELL_GT64111	0x4146
+#define PCI_DEVICE_ID_MARVELL_GT64260	0x6430
+#define PCI_DEVICE_ID_MARVELL_MV64360	0x6460
+#define PCI_DEVICE_ID_MARVELL_MV64460	0x6480
+#define PCI_DEVICE_ID_MARVELL_GT96100	0x9652
+#define PCI_DEVICE_ID_MARVELL_GT96100A	0x9653
 
 #define PCI_VENDOR_ID_LITEON		0x11ad
 #define PCI_DEVICE_ID_LITEON_LNE100TX	0x0002
@@ -1577,6 +1580,9 @@
 #define PCI_DEVICE_ID_ENSONIQ_ES1370	0x5000
 #define PCI_DEVICE_ID_ENSONIQ_ES1371	0x1371
 
+#define PCI_VENDOR_ID_TRANSMETA		0x1279
+#define PCI_DEVICE_ID_EFFICEON		0x0060
+
 #define PCI_VENDOR_ID_ROCKWELL		0x127A
 
 #define PCI_VENDOR_ID_ITE		0x1283
@@ -1922,6 +1928,7 @@
 #define PCI_DEVICE_ID_GENROCO_HFP832	0x0003
 
 #define PCI_VENDOR_ID_INTEL		0x8086
+#define PCI_DEVICE_ID_INTEL_EESSC	0x0008
 #define PCI_DEVICE_ID_INTEL_21145	0x0039
 #define PCI_DEVICE_ID_INTEL_82375	0x0482
 #define PCI_DEVICE_ID_INTEL_82424	0x0483
--- diff/include/linux/pmu.h	2003-09-30 15:46:20.000000000 +0100
+++ source/include/linux/pmu.h	2004-02-23 13:56:47.000000000 +0000
@@ -226,7 +226,7 @@ struct pmu_battery_info
 	unsigned int	flags;
 	unsigned int	charge;		/* current charge */
 	unsigned int	max_charge;	/* maximum charge */
-	signed int	current;	/* current, positive if charging */
+	signed int	amperage;	/* current, positive if charging */
 	unsigned int	voltage;	/* voltage */
 	unsigned int	time_remaining;	/* remaining time */
 };
--- diff/include/linux/quota.h	2004-01-19 10:22:59.000000000 +0000
+++ source/include/linux/quota.h	2004-02-23 13:56:47.000000000 +0000
@@ -138,6 +138,9 @@ struct if_dqinfo {
 #include <linux/dqblk_v1.h>
 #include <linux/dqblk_v2.h>
 
+/* Maximal numbers of writes for quota operations (over all formats) */
+#define DQUOT_MAX_WRITES	6	/* Number of writes needed when quota structure is written */
+
 /*
  * Data for one user/group kept in memory
  */
@@ -168,22 +171,21 @@ struct mem_dqinfo {
 	} u;
 };
 
+struct super_block;
+
 #define DQF_MASK 0xffff		/* Mask for format specific flags */
 #define DQF_INFO_DIRTY_B 16
 #define DQF_ANY_DQUOT_DIRTY_B 17
 #define DQF_INFO_DIRTY (1 << DQF_INFO_DIRTY_B)	/* Is info dirty? */
 #define DQF_ANY_DQUOT_DIRTY (1 << DQF_ANY_DQUOT_DIRTY_B) /* Is any dquot dirty? */
 
-extern inline void mark_info_dirty(struct mem_dqinfo *info)
-{
-	set_bit(DQF_INFO_DIRTY_B, &info->dqi_flags);
-}
-
+extern void mark_info_dirty(struct super_block *sb, int type);
 #define info_dirty(info) test_bit(DQF_INFO_DIRTY_B, &(info)->dqi_flags)
 #define info_any_dquot_dirty(info) test_bit(DQF_ANY_DQUOT_DIRTY_B, &(info)->dqi_flags)
 #define info_any_dirty(info) (info_dirty(info) || info_any_dquot_dirty(info))
 
 #define sb_dqopt(sb) (&(sb)->s_dquot)
+#define sb_dqinfo(sb, type) (sb_dqopt(sb)->info+(type))
 
 struct dqstats {
 	int lookups;
@@ -238,19 +240,21 @@ struct quota_format_ops {
 	int (*write_file_info)(struct super_block *sb, int type);	/* Write main info about file */
 	int (*free_file_info)(struct super_block *sb, int type);	/* Called on quotaoff() */
 	int (*read_dqblk)(struct dquot *dquot);		/* Read structure for one user */
-	int (*commit_dqblk)(struct dquot *dquot);	/* Write (or delete) structure for one user */
+	int (*commit_dqblk)(struct dquot *dquot, int init);	/* Write (or delete) structure for one user */
 };
 
 /* Operations working with dquots */
 struct dquot_operations {
-	void (*initialize) (struct inode *, int);
-	void (*drop) (struct inode *);
+	int (*initialize) (struct inode *, int);
+	int (*drop) (struct inode *);
 	int (*alloc_space) (struct inode *, qsize_t, int);
 	int (*alloc_inode) (const struct inode *, unsigned long);
-	void (*free_space) (struct inode *, qsize_t);
-	void (*free_inode) (const struct inode *, unsigned long);
+	int (*free_space) (struct inode *, qsize_t);
+	int (*free_inode) (const struct inode *, unsigned long);
 	int (*transfer) (struct inode *, struct iattr *);
-	int (*write_dquot) (struct dquot *);
+	int (*write_dquot) (struct dquot *, int);
+	int (*mark_dirty) (struct dquot *);
+	int (*write_info) (struct super_block *, int);
 };
 
 /* Operations handling requests from userspace */
@@ -289,10 +293,7 @@ struct quota_info {
 };
 
 /* Inline would be better but we need to dereference super_block which is not defined yet */
-#define mark_dquot_dirty(dquot) do {\
-	set_bit(DQF_ANY_DQUOT_DIRTY_B, &(sb_dqopt((dquot)->dq_sb)->info[(dquot)->dq_type].dqi_flags));\
-	set_bit(DQ_MOD_B, &(dquot)->dq_flags);\
-} while (0)
+int mark_dquot_dirty(struct dquot *dquot);
 
 #define dquot_dirty(dquot) test_bit(DQ_MOD_B, &(dquot)->dq_flags)
 
@@ -304,7 +305,6 @@ struct quota_info {
 
 int register_quota_format(struct quota_format_type *fmt);
 void unregister_quota_format(struct quota_format_type *fmt);
-void init_dquot_operations(struct dquot_operations *fsdqops);
 
 struct quota_module_name {
 	int qm_fmt_id;
--- diff/include/linux/quotaops.h	2004-02-09 10:36:12.000000000 +0000
+++ source/include/linux/quotaops.h	2004-02-23 13:56:47.000000000 +0000
@@ -22,16 +22,29 @@
  */
 extern void sync_dquots(struct super_block *sb, int type);
 
-extern void dquot_initialize(struct inode *inode, int type);
-extern void dquot_drop(struct inode *inode);
+extern int dquot_initialize(struct inode *inode, int type);
+extern int dquot_drop(struct inode *inode);
 
-extern int  dquot_alloc_space(struct inode *inode, qsize_t number, int prealloc);
-extern int  dquot_alloc_inode(const struct inode *inode, unsigned long number);
+extern int dquot_alloc_space(struct inode *inode, qsize_t number, int prealloc);
+extern int dquot_alloc_inode(const struct inode *inode, unsigned long number);
 
-extern void dquot_free_space(struct inode *inode, qsize_t number);
-extern void dquot_free_inode(const struct inode *inode, unsigned long number);
+extern int dquot_free_space(struct inode *inode, qsize_t number);
+extern int dquot_free_inode(const struct inode *inode, unsigned long number);
 
-extern int  dquot_transfer(struct inode *inode, struct iattr *iattr);
+extern int dquot_transfer(struct inode *inode, struct iattr *iattr);
+extern int dquot_commit(struct dquot *dquot, int init);
+extern int dquot_commit_info(struct super_block *sb, int type);
+extern int dquot_mark_dquot_dirty(struct dquot *dquot);
+
+extern int vfs_quota_on(struct super_block *sb, int type, int format_id, char *path);
+extern int vfs_quota_on_mount(int type, int format_id, struct dentry *dentry);
+extern int vfs_quota_off(struct super_block *sb, int type);
+extern int vfs_quota_off_mount(struct super_block *sb, int type);
+extern int vfs_quota_sync(struct super_block *sb, int type);
+extern int vfs_get_dqinfo(struct super_block *sb, int type, struct if_dqinfo *ii);
+extern int vfs_set_dqinfo(struct super_block *sb, int type, struct if_dqinfo *ii);
+extern int vfs_get_dqblk(struct super_block *sb, int type, qid_t id, struct if_dqblk *di);
+extern int vfs_set_dqblk(struct super_block *sb, int type, qid_t id, struct if_dqblk *di);
 
 /*
  * Operations supported for diskquotas.
@@ -64,11 +77,9 @@ static __inline__ int DQUOT_PREALLOC_SPA
 		if (inode->i_sb->dq_op->alloc_space(inode, nr, 1) == NO_QUOTA)
 			return 1;
 	}
-	else {
-		spin_lock(&dq_data_lock);
+	else
+		/* inode->i_lock will guard the update */
 		inode_add_bytes(inode, nr);
-		spin_unlock(&dq_data_lock);
-	}
 	return 0;
 }
 
@@ -87,11 +98,9 @@ static __inline__ int DQUOT_ALLOC_SPACE_
 		if (inode->i_sb->dq_op->alloc_space(inode, nr, 0) == NO_QUOTA)
 			return 1;
 	}
-	else {
-		spin_lock(&dq_data_lock);
+	else
+		/* inode->i_lock will guard the update */
 		inode_add_bytes(inode, nr);
-		spin_unlock(&dq_data_lock);
-	}
 	return 0;
 }
 
@@ -117,11 +126,9 @@ static __inline__ void DQUOT_FREE_SPACE_
 {
 	if (sb_any_quota_enabled(inode->i_sb))
 		inode->i_sb->dq_op->free_space(inode, nr);
-	else {
-		spin_lock(&dq_data_lock);
+	else
+		/* inode->i_lock will guard the update */
 		inode_sub_bytes(inode, nr);
-		spin_unlock(&dq_data_lock);
-	}
 }
 
 static __inline__ void DQUOT_FREE_SPACE(struct inode *inode, qsize_t nr)
--- diff/include/linux/raid/md_k.h	2004-02-18 08:54:13.000000000 +0000
+++ source/include/linux/raid/md_k.h	2004-02-23 13:56:47.000000000 +0000
@@ -186,7 +186,8 @@ struct mddev_s
 {
 	void				*private;
 	mdk_personality_t		*pers;
-	int				__minor;
+	dev_t				unit;
+	int				md_minor;
 	struct list_head 		disks;
 	int				sb_dirty;
 	int				ro;
@@ -235,6 +236,7 @@ struct mddev_s
 	struct semaphore		reconfig_sem;
 	atomic_t			active;
 
+	int				changed;	/* true if we might need to reread partition info */
 	int				degraded;	/* whether md should consider
 							 * adding a spare
 							 */
@@ -272,15 +274,6 @@ struct mdk_personality_s
 };
 
 
-/*
- * Currently we index md_array directly, based on the minor
- * number. This will have to change to dynamic allocation
- * once we start supporting partitioning of md devices.
- */
-static inline int mdidx (mddev_t * mddev)
-{
-	return mddev->__minor;
-}
 static inline char * mdname (mddev_t * mddev)
 {
 	return mddev->gendisk ? mddev->gendisk->disk_name : "mdX";
--- diff/include/linux/raid/raid1.h	2003-06-30 10:07:24.000000000 +0100
+++ source/include/linux/raid/raid1.h	2004-02-23 13:56:47.000000000 +0000
@@ -54,8 +54,8 @@ struct r1bio_s {
 	atomic_t		remaining; /* 'have we finished' count,
 					    * used from IRQ handlers
 					    */
-	int			cmd;
 	sector_t		sector;
+	int			sectors;
 	unsigned long		state;
 	mddev_t			*mddev;
 	/*
@@ -63,21 +63,19 @@ struct r1bio_s {
 	 */
 	struct bio		*master_bio;
 	/*
-	 * if the IO is in READ direction, then this bio is used:
+	 * if the IO is in READ direction, then this is where we read
 	 */
-	struct bio		*read_bio;
 	int			read_disk;
 
-	r1bio_t			*next_r1; /* next for retry or in free list */
 	struct list_head	retry_list;
 	/*
 	 * if the IO is in WRITE direction, then multiple bios are used.
 	 * We choose the number when they are allocated.
 	 */
-	struct bio		*write_bios[0];
+	struct bio		*bios[0];
 };
 
 /* bits for r1bio.state */
-#define	R1BIO_Uptodate	1
-
+#define	R1BIO_Uptodate	0
+#define	R1BIO_IsSync	1
 #endif
--- diff/include/linux/sched.h	2004-02-18 08:54:13.000000000 +0000
+++ source/include/linux/sched.h	2004-02-23 13:56:47.000000000 +0000
@@ -147,10 +147,12 @@ extern spinlock_t mmlist_lock;
 typedef struct task_struct task_t;
 
 extern void sched_init(void);
+extern void sched_init_smp(void);
 extern void init_idle(task_t *idle, int cpu);
 
 extern void show_state(void);
 extern void show_regs(struct pt_regs *);
+extern void show_trace_task(task_t *tsk);
 
 /*
  * TASK is a pointer to the task whose backtrace we want to see (or NULL for current
@@ -192,7 +194,7 @@ struct mm_struct {
 	atomic_t mm_count;			/* How many references to "struct mm_struct" (users count as 1) */
 	int map_count;				/* number of VMAs */
 	struct rw_semaphore mmap_sem;
-	spinlock_t page_table_lock;		/* Protects task page tables and mm->rss */
+	spinlock_t page_table_lock;		/* Protects task page tables and RSS data */
 
 	struct list_head mmlist;		/* List of all active mm's.  These are globally strung
 						 * together off init_mm.mmlist, and are protected
@@ -202,7 +204,11 @@ struct mm_struct {
 	unsigned long start_code, end_code, start_data, end_data;
 	unsigned long start_brk, brk, start_stack;
 	unsigned long arg_start, arg_end, env_start, env_end;
-	unsigned long rss, total_vm, locked_vm;
+	unsigned long total_vm, locked_vm;
+	unsigned long rss;
+#ifdef CONFIG_NUMA
+	unsigned long pernode_rss[MAX_NUMNODES];
+#endif
 	unsigned long def_flags;
 
 	unsigned long saved_auxv[40]; /* for /proc/PID/auxv */
@@ -330,6 +336,33 @@ struct k_itimer {
 struct io_context;			/* See blkdev.h */
 void exit_io_context(void);
 
+#define NGROUPS_SMALL		32
+#define NGROUPS_PER_BLOCK	((int)(EXEC_PAGESIZE / sizeof(gid_t)))
+struct group_info {
+	int ngroups;
+	atomic_t usage;
+	gid_t small_block[NGROUPS_SMALL];
+	int nblocks;
+	gid_t *blocks[0];
+};
+
+#define get_group_info(group_info) do { \
+	atomic_inc(&(group_info)->usage); \
+} while (0)
+
+#define put_group_info(group_info) do { \
+	if (atomic_dec_and_test(&(group_info)->usage)) \
+		groups_free(group_info); \
+} while (0)
+
+struct group_info *groups_alloc(int gidsetsize);
+void groups_free(struct group_info *group_info);
+int set_current_groups(struct group_info *group_info);
+/* access the groups "array" with this macro */
+#define GROUP_AT(gi, i) \
+    ((gi)->blocks[(i)/NGROUPS_PER_BLOCK][(i)%NGROUPS_PER_BLOCK])
+
+
 struct task_struct {
 	volatile long state;	/* -1 unrunnable, 0 runnable, >0 stopped */
 	struct thread_info *thread_info;
@@ -404,8 +437,7 @@ struct task_struct {
 /* process credentials */
 	uid_t uid,euid,suid,fsuid;
 	gid_t gid,egid,sgid,fsgid;
-	int ngroups;
-	gid_t	groups[NGROUPS];
+	struct group_info *group_info;
 	kernel_cap_t   cap_effective, cap_inheritable, cap_permitted;
 	int keep_capabilities:1;
 	struct user_struct *user;
@@ -500,8 +532,106 @@ do { if (atomic_dec_and_test(&(tsk)->usa
 #define PF_SWAPOFF	0x00080000	/* I am in swapoff */
 #define PF_LESS_THROTTLE 0x00100000	/* Throttle me less: I clean memory */
 #define PF_SYNCWRITE	0x00200000	/* I am doing a sync write */
+#define PF_FUTEX_DEBUG	0x00400000
 
 #ifdef CONFIG_SMP
+#define SCHED_LOAD_SHIFT 7	/* increase resolution of load calculations */
+#define SCHED_LOAD_SCALE (1UL << SCHED_LOAD_SHIFT)
+
+#define SD_FLAG_NEWIDLE		1	/* Balance when about to become idle */
+#define SD_FLAG_EXEC		2	/* Balance on exec */
+#define SD_FLAG_WAKE		4	/* Balance on task wakeup */
+#define SD_FLAG_FASTMIGRATE	8	/* Sync wakes put task on waking CPU */
+
+struct sched_group {
+	struct sched_group *next;	/* Must be a circular list */
+	cpumask_t cpumask;
+
+	/*
+	 * CPU power of this group, SCHED_LOAD_SCALE being max power for a
+	 * single CPU. This should be read only (except for setup). Although
+	 * it will need to be written to at cpu hot(un)plug time, perhaps the
+	 * cpucontrol semaphore will provide enough exclusion?
+	 */
+	unsigned long cpu_power;
+};
+
+struct sched_domain {
+	/* These fields must be setup */
+	struct sched_domain *parent;	/* top domain must be null terminated */
+	struct sched_group *groups;	/* the balancing groups of the domain */
+	cpumask_t span;			/* span of all CPUs in this domain */
+	unsigned long min_interval;	/* Minimum balance interval ms */
+	unsigned long max_interval;	/* Maximum balance interval ms */
+	unsigned int busy_factor;	/* less balancing by factor if busy */
+	unsigned int imbalance_pct;	/* No balance until over watermark */
+	unsigned long long cache_hot_time; /* Task considered cache hot (ns) */
+	unsigned int cache_nice_tries;	/* Leave cache hot tasks for # tries */
+	int flags;			/* See SD_FLAG_* */
+
+	/* Runtime fields. */
+	unsigned long last_balance;	/* init to jiffies. units in jiffies */
+	unsigned int balance_interval;	/* initialise to 1. units in ms. */
+	unsigned int nr_balance_failed; /* initialise to 0 */
+};
+
+/* Common values for SMT siblings */
+#define SD_SIBLING_INIT (struct sched_domain) {		\
+	.span			= CPU_MASK_NONE,	\
+	.parent			= NULL,			\
+	.groups			= NULL,			\
+	.min_interval		= 1,			\
+	.max_interval		= 2,			\
+	.busy_factor		= 8,			\
+	.imbalance_pct		= 110,			\
+	.cache_hot_time		= 0,			\
+	.cache_nice_tries	= 0,			\
+	.flags			= SD_FLAG_FASTMIGRATE | SD_FLAG_NEWIDLE | SD_FLAG_WAKE,\
+	.last_balance		= jiffies,		\
+	.balance_interval	= 1,			\
+	.nr_balance_failed	= 0,			\
+}
+
+/* Common values for CPUs */
+#define SD_CPU_INIT (struct sched_domain) {		\
+	.span			= CPU_MASK_NONE,	\
+	.parent			= NULL,			\
+	.groups			= NULL,			\
+	.min_interval		= 1,			\
+	.max_interval		= 8,			\
+	.busy_factor		= 32,			\
+	.imbalance_pct		= 125,			\
+	.cache_hot_time		= (5*1000000),		\
+	.cache_nice_tries	= 2,			\
+	.flags			= SD_FLAG_FASTMIGRATE | SD_FLAG_NEWIDLE,\
+	.last_balance		= jiffies,		\
+	.balance_interval	= 1,			\
+	.nr_balance_failed	= 0,			\
+}
+
+#ifdef CONFIG_NUMA
+/* Common values for NUMA nodes */
+#define SD_NODE_INIT (struct sched_domain) {		\
+	.span			= CPU_MASK_NONE,	\
+	.parent			= NULL,			\
+	.groups			= NULL,			\
+	.min_interval		= 20,			\
+	.max_interval		= 1000*fls(num_online_cpus()),\
+	.busy_factor		= 4,			\
+	.imbalance_pct		= 125,			\
+	.cache_hot_time		= (5*1000000),		\
+	.cache_nice_tries	= 1,			\
+	.flags			= SD_FLAG_EXEC,		\
+	.last_balance		= jiffies,		\
+	.balance_interval	= 1,			\
+	.nr_balance_failed	= 0,			\
+}
+#endif
+
+DECLARE_PER_CPU(struct sched_domain, base_domains);
+#define cpu_sched_domain(cpu)	(&per_cpu(base_domains, (cpu)))
+#define this_sched_domain()	(&__get_cpu_var(base_domains))
+
 extern int set_cpus_allowed(task_t *p, cpumask_t new_mask);
 #else
 static inline int set_cpus_allowed(task_t *p, cpumask_t new_mask)
@@ -514,12 +644,14 @@ extern unsigned long long sched_clock(vo
 
 #ifdef CONFIG_NUMA
 extern void sched_balance_exec(void);
-extern void node_nr_running_init(void);
 #else
 #define sched_balance_exec()   {}
-#define node_nr_running_init() {}
 #endif
 
+/* Move tasks off this (offline) CPU onto another. */
+extern void migrate_all_tasks(void);
+/* Try to move me here, if possible. */
+void migrate_to_cpu(int dest_cpu);
 extern void set_user_nice(task_t *p, long nice);
 extern int task_prio(task_t *p);
 extern int task_nice(task_t *p);
@@ -583,8 +715,6 @@ extern void FASTCALL(wake_up_forked_proc
 extern void FASTCALL(sched_fork(task_t * p));
 extern void FASTCALL(sched_exit(task_t * p));
 
-asmlinkage long sys_wait4(pid_t pid,unsigned int * stat_addr, int options, struct rusage * ru);
-
 extern int in_group_p(gid_t);
 extern int in_egroup_p(gid_t);
 
--- diff/include/linux/security.h	2004-02-18 08:54:13.000000000 +0000
+++ source/include/linux/security.h	2004-02-23 13:56:48.000000000 +0000
@@ -564,9 +564,8 @@ struct swap_info_struct;
  *	Return 0 if permission is granted.
  * @task_setgroups:
  *	Check permission before setting the supplementary group set of the
- *	current process to @grouplist.
- *	@gidsetsize contains the number of elements in @grouplist.
- *	@grouplist contains the array of gids.
+ *	current process.
+ *	@group_info contains the new group information.
  *	Return 0 if permission is granted.
  * @task_setnice:
  *	Check permission before setting the nice value of @p to @nice.
@@ -1127,7 +1126,7 @@ struct security_operations {
 	int (*task_setpgid) (struct task_struct * p, pid_t pgid);
 	int (*task_getpgid) (struct task_struct * p);
 	int (*task_getsid) (struct task_struct * p);
-	int (*task_setgroups) (int gidsetsize, gid_t * grouplist);
+	int (*task_setgroups) (struct group_info *group_info);
 	int (*task_setnice) (struct task_struct * p, int nice);
 	int (*task_setrlimit) (unsigned int resource, struct rlimit * new_rlim);
 	int (*task_setscheduler) (struct task_struct * p, int policy,
@@ -1686,9 +1685,9 @@ static inline int security_task_getsid (
 	return security_ops->task_getsid (p);
 }
 
-static inline int security_task_setgroups (int gidsetsize, gid_t *grouplist)
+static inline int security_task_setgroups (struct group_info *group_info)
 {
-	return security_ops->task_setgroups (gidsetsize, grouplist);
+	return security_ops->task_setgroups (group_info);
 }
 
 static inline int security_task_setnice (struct task_struct *p, int nice)
@@ -2320,7 +2319,7 @@ static inline int security_task_getsid (
 	return 0;
 }
 
-static inline int security_task_setgroups (int gidsetsize, gid_t *grouplist)
+static inline int security_task_setgroups (struct group_info *group_info)
 {
 	return 0;
 }
--- diff/include/linux/sem.h	2003-07-11 09:39:50.000000000 +0100
+++ source/include/linux/sem.h	2004-02-23 13:56:48.000000000 +0000
@@ -134,12 +134,6 @@ struct sysv_sem {
 	struct sem_undo_list *undo_list;
 };
 
-asmlinkage long sys_semget (key_t key, int nsems, int semflg);
-asmlinkage long sys_semop (int semid, struct sembuf __user *sops, unsigned nsops);
-asmlinkage long sys_semctl (int semid, int semnum, int cmd, union semun arg);
-asmlinkage long sys_semtimedop(int semid, struct sembuf __user *sops,
-			unsigned nsops, const struct timespec __user *timeout);
-
 void exit_sem(struct task_struct *p);
 
 #endif /* __KERNEL__ */
--- diff/include/linux/serial_core.h	2003-10-09 09:47:17.000000000 +0100
+++ source/include/linux/serial_core.h	2004-02-23 13:56:48.000000000 +0000
@@ -46,6 +46,7 @@
  * separate so any additions to the old serial.c that occur before
  * we are merged can be easily merged here.
  */
+#define PORT_PXA	31
 #define PORT_AMBA	32
 #define PORT_CLPS711X	33
 #define PORT_SA1100	34
@@ -158,7 +159,9 @@ struct uart_port {
 	unsigned char		x_char;			/* xon/xoff char */
 	unsigned char		regshift;		/* reg offset shift */
 	unsigned char		iotype;			/* io access style */
-
+#ifdef CONFIG_KGDB
+	int			kgdb;			/* in use by kgdb */
+#endif
 #define UPIO_PORT		(0)
 #define UPIO_HUB6		(1)
 #define UPIO_MEM		(2)
--- diff/include/linux/serial_reg.h	2002-10-16 04:28:32.000000000 +0100
+++ source/include/linux/serial_reg.h	2004-02-23 13:56:48.000000000 +0000
@@ -141,6 +141,21 @@
 #define UART_MSR_ANY_DELTA 0x0F	/* Any of the delta bits! */
 
 /*
+ * The Intel PXA2xx chip defines those bits
+ */
+#define UART_IER_DMAE	0x80	/* DMA Requests Enable */
+#define UART_IER_UUE	0x40	/* UART Unit Enable */
+#define UART_IER_NRZE	0x20	/* NRZ coding Enable */
+#define UART_IER_RTOIE	0x10	/* Receiver Time Out Interrupt Enable */
+
+#define UART_IIR_TOD	0x08	/* Character Timeout Indication Detected */
+
+#define UART_FCR_PXAR1	0x00	/* receive FIFO treshold = 1 */
+#define UART_FCR_PXAR8	0x40	/* receive FIFO treshold = 8 */
+#define UART_FCR_PXAR16	0x80	/* receive FIFO treshold = 16 */
+#define UART_FCR_PXAR32	0xc0	/* receive FIFO treshold = 32 */
+
+/*
  * These are the definitions for the Extended Features Register
  * (StarTech 16C660 only, when DLAB=1)
  */
--- diff/include/linux/shm.h	2003-06-09 14:18:20.000000000 +0100
+++ source/include/linux/shm.h	2004-02-23 13:56:48.000000000 +0000
@@ -90,11 +90,6 @@ struct shmid_kernel /* private to the ke
 #define SHM_LOCKED      02000   /* segment will not be swapped */
 #define SHM_HUGETLB     04000   /* segment will use huge TLB pages */
 
-long sys_shmat (int shmid, char __user *shmaddr, int shmflg, unsigned long *addr);
-asmlinkage long sys_shmget (key_t key, size_t size, int flag);
-asmlinkage long sys_shmdt (char __user *shmaddr);
-asmlinkage long sys_shmctl (int shmid, int cmd, struct shmid_ds __user *buf);
-
 #endif /* __KERNEL__ */
 
 #endif /* _LINUX_SHM_H_ */
--- diff/include/linux/skbuff.h	2004-02-09 10:36:12.000000000 +0000
+++ source/include/linux/skbuff.h	2004-02-23 13:56:48.000000000 +0000
@@ -163,6 +163,7 @@ struct skb_shared_info {
  *	@cb: Control buffer. Free for use by every layer. Put private vars here
  *	@len: Length of actual data
  *	@data_len: Data length
+ *	@mac_len: Length of link layer header
  *	@csum: Checksum
  *	@__unused: Dead field, may be reused
  *	@cloned: Head may be cloned (check refcnt to be sure)
@@ -204,6 +205,7 @@ struct sk_buff {
 		struct icmphdr	*icmph;
 		struct igmphdr	*igmph;
 		struct iphdr	*ipiph;
+		struct ipv6hdr	*ipv6h;
 		unsigned char	*raw;
 	} h;
 
@@ -232,6 +234,7 @@ struct sk_buff {
 
 	unsigned int		len,
 				data_len,
+				mac_len,
 				csum;
 	unsigned char		local_df,
 				cloned,
--- diff/include/linux/smp_lock.h	2004-02-09 10:36:12.000000000 +0000
+++ source/include/linux/smp_lock.h	2004-02-23 13:56:48.000000000 +0000
@@ -5,7 +5,9 @@
 #include <linux/sched.h>
 #include <linux/spinlock.h>
 
-#if defined(CONFIG_SMP) || defined(CONFIG_PREEMPT)
+#define BKL_DEBUG /* For testing for sleep_on() abuse */
+
+#if defined(CONFIG_SMP) || defined(CONFIG_PREEMPT) || defined(BKL_DEBUG)
 
 extern spinlock_t kernel_flag;
 
--- diff/include/linux/socket.h	2003-11-25 15:24:59.000000000 +0000
+++ source/include/linux/socket.h	2004-02-23 13:56:48.000000000 +0000
@@ -245,10 +245,6 @@ struct ucred {
 #define MSG_CMSG_COMPAT	0		/* We never have 32 bit fixups */
 #endif
 
-extern asmlinkage long sys_sendmsg(int fd, struct msghdr __user *msg, unsigned flags);
-extern asmlinkage long sys_recvmsg(int fd, struct msghdr __user *msg, unsigned flags);
-
-
 
 /* Setsockoptions(2) level. Thanks to BSD these must match IPPROTO_xxx */
 #define SOL_IP		0
--- diff/include/linux/spinlock.h	2003-10-09 09:47:17.000000000 +0100
+++ source/include/linux/spinlock.h	2004-02-23 13:56:48.000000000 +0000
@@ -15,6 +15,12 @@
 
 #include <asm/processor.h>	/* for cpu relax */
 #include <asm/system.h>
+#ifdef CONFIG_KGDB
+#include <asm/current.h>
+#define SET_WHO(x, him) (x)->who = him;
+#else
+#define SET_WHO(x, him)
+#endif
 
 /*
  * Must define these before including other files, inline functions need them
@@ -55,6 +61,9 @@ typedef struct {
 	const char *module;
 	char *owner;
 	int oline;
+#ifdef CONFIG_KGDB
+	struct task_struct *who;
+#endif
 } spinlock_t;
 #define SPIN_LOCK_UNLOCKED (spinlock_t) { SPINLOCK_MAGIC, 0, 10, __FILE__ , NULL, 0}
 
@@ -66,6 +75,7 @@ typedef struct {
 		(x)->module = __FILE__; \
 		(x)->owner = NULL; \
 		(x)->oline = 0; \
+                SET_WHO(x, NULL) \
 	} while (0)
 
 #define CHECK_LOCK(x) \
@@ -88,6 +98,7 @@ typedef struct {
 		(x)->lock = 1; \
 		(x)->owner = __FILE__; \
 		(x)->oline = __LINE__; \
+                SET_WHO(x, current)       \
 	} while (0)
 
 /* without debugging, spin_is_locked on UP always says
@@ -118,6 +129,7 @@ typedef struct {
 		(x)->lock = 1; \
 		(x)->owner = __FILE__; \
 		(x)->oline = __LINE__; \
+                SET_WHO(x, current)       \
 		1; \
 	})
 
@@ -184,6 +196,17 @@ typedef struct {
 
 #endif /* !SMP */
 
+#ifdef CONFIG_LOCKMETER
+extern void _metered_spin_lock   (spinlock_t *lock);
+extern void _metered_spin_unlock (spinlock_t *lock);
+extern int  _metered_spin_trylock(spinlock_t *lock);
+extern void _metered_read_lock    (rwlock_t *lock);
+extern void _metered_read_unlock  (rwlock_t *lock);
+extern void _metered_write_lock   (rwlock_t *lock);
+extern void _metered_write_unlock (rwlock_t *lock);
+extern int  _metered_write_trylock(rwlock_t *lock);
+#endif
+
 /*
  * Define the various spin_lock and rw_lock methods.  Note we define these
  * regardless of whether CONFIG_SMP or CONFIG_PREEMPT are set. The various
@@ -389,6 +412,141 @@ do { \
 				_raw_spin_trylock(lock) ? 1 : \
 				({preempt_enable(); local_bh_enable(); 0;});})
 
+#ifdef CONFIG_LOCKMETER
+#undef spin_lock
+#undef spin_trylock
+#undef spin_unlock
+#undef spin_lock_irqsave
+#undef spin_lock_irq
+#undef spin_lock_bh
+#undef read_lock
+#undef read_unlock
+#undef write_lock
+#undef write_unlock
+#undef write_trylock
+#undef spin_unlock_bh
+#undef read_lock_irqsave
+#undef read_lock_irq
+#undef read_lock_bh
+#undef read_unlock_bh
+#undef write_lock_irqsave
+#undef write_lock_irq
+#undef write_lock_bh
+#undef write_unlock_bh
+
+#define spin_lock(lock) \
+do { \
+	preempt_disable(); \
+	_metered_spin_lock(lock); \
+} while(0)
+
+#define spin_trylock(lock)     ({preempt_disable(); _metered_spin_trylock(lock) ? \
+				1 : ({preempt_enable(); 0;});})
+#define spin_unlock(lock) \
+do { \
+	_metered_spin_unlock(lock); \
+	preempt_enable(); \
+} while (0)
+
+#define spin_lock_irqsave(lock, flags) \
+do { \
+	local_irq_save(flags); \
+	preempt_disable(); \
+	_metered_spin_lock(lock); \
+} while (0)
+
+#define spin_lock_irq(lock) \
+do { \
+	local_irq_disable(); \
+	preempt_disable(); \
+	_metered_spin_lock(lock); \
+} while (0)
+
+#define spin_lock_bh(lock) \
+do { \
+	local_bh_disable(); \
+	preempt_disable(); \
+	_metered_spin_lock(lock); \
+} while (0)
+
+#define spin_unlock_bh(lock) \
+do { \
+	_metered_spin_unlock(lock); \
+	preempt_enable(); \
+	local_bh_enable(); \
+} while (0)
+
+
+#define read_lock(lock)                ({preempt_disable(); _metered_read_lock(lock);})
+#define read_unlock(lock)      ({_metered_read_unlock(lock); preempt_enable();})
+#define write_lock(lock)       ({preempt_disable(); _metered_write_lock(lock);})
+#define write_unlock(lock)     ({_metered_write_unlock(lock); preempt_enable();})
+#define write_trylock(lock)    ({preempt_disable();_metered_write_trylock(lock) ? \
+				1 : ({preempt_enable(); 0;});})
+#define spin_unlock_no_resched(lock) \
+do { \
+	_metered_spin_unlock(lock); \
+	preempt_enable_no_resched(); \
+} while (0)
+
+#define read_lock_irqsave(lock, flags) \
+do { \
+	local_irq_save(flags); \
+	preempt_disable(); \
+	_metered_read_lock(lock); \
+} while (0)
+
+#define read_lock_irq(lock) \
+do { \
+	local_irq_disable(); \
+	preempt_disable(); \
+	_metered_read_lock(lock); \
+} while (0)
+
+#define read_lock_bh(lock) \
+do { \
+	local_bh_disable(); \
+	preempt_disable(); \
+	_metered_read_lock(lock); \
+} while (0)
+
+#define read_unlock_bh(lock) \
+do { \
+	_metered_read_unlock(lock); \
+	preempt_enable(); \
+	local_bh_enable(); \
+} while (0)
+
+#define write_lock_irqsave(lock, flags) \
+do { \
+	local_irq_save(flags); \
+	preempt_disable(); \
+	_metered_write_lock(lock); \
+} while (0)
+
+#define write_lock_irq(lock) \
+do { \
+	local_irq_disable(); \
+	preempt_disable(); \
+	_metered_write_lock(lock); \
+} while (0)
+
+#define write_lock_bh(lock) \
+do { \
+	local_bh_disable(); \
+	preempt_disable(); \
+	_metered_write_lock(lock); \
+} while (0)
+
+#define write_unlock_bh(lock) \
+do { \
+	_metered_write_unlock(lock); \
+	preempt_enable(); \
+	local_bh_enable(); \
+} while (0)
+
+#endif /* !CONFIG_LOCKMETER */
+
 /* "lock on reference count zero" */
 #ifndef ATOMIC_DEC_AND_LOCK
 #include <asm/atomic.h>
--- diff/include/linux/stallion.h	2003-10-09 09:47:34.000000000 +0100
+++ source/include/linux/stallion.h	2004-02-23 13:56:48.000000000 +0000
@@ -95,13 +95,8 @@ typedef struct stlport {
 	unsigned long		hwid;
 	void			*uartp;
 	struct tty_struct	*tty;
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0))
-	struct wait_queue	*open_wait;
-	struct wait_queue	*close_wait;
-#else
 	wait_queue_head_t	open_wait;
 	wait_queue_head_t	close_wait;
-#endif
 	struct work_struct	tqueue;
 	comstats_t		stats;
 	stlrq_t			tx;
--- diff/include/linux/sunrpc/auth.h	2004-02-18 08:54:13.000000000 +0000
+++ source/include/linux/sunrpc/auth.h	2004-02-23 13:56:48.000000000 +0000
@@ -28,8 +28,7 @@
 struct auth_cred {
 	uid_t	uid;
 	gid_t	gid;
-	int	ngroups;
-	gid_t	*groups;
+	struct group_info *group_info;
 };
 
 /*
--- diff/include/linux/sunrpc/cache.h	2004-02-09 10:36:12.000000000 +0000
+++ source/include/linux/sunrpc/cache.h	2004-02-23 13:56:48.000000000 +0000
@@ -132,12 +132,14 @@ struct cache_deferred_req {
  * If "set" == 0 :
  *    If an entry is found, it is returned
  *    If no entry is found, a new non-VALID entry is created.
- * If "set" == 1 :
+ * If "set" == 1 and INPLACE == 0 :
  *    If no entry is found a new one is inserted with data from "template"
  *    If a non-CACHE_VALID entry is found, it is updated from template using UPDATE
  *    If a CACHE_VALID entry is found, a new entry is swapped in with data
  *       from "template"
- * If set == 2, we UPDATE, but don't swap. i.e. update in place
+ * If set == 1, and INPLACE == 1 :
+ *    As above, except that if a CACHE_VALID entry is found, we UPDATE in place
+ *       instead of swapping in a new entry.
  *
  * If the passed handle has the CACHE_NEGATIVE flag set, then UPDATE is not
  * run but insteead CACHE_NEGATIVE is set in any new item.
@@ -164,8 +166,8 @@ RTN *FNAME ARGS										\
 	RTN *tmp, *new=NULL;								\
 	struct cache_head **hp, **head;							\
 	SETUP;										\
- retry:											\
 	head = &(DETAIL)->hash_table[HASHFN];						\
+ retry:											\
 	if (set||new) write_lock(&(DETAIL)->hash_lock);					\
 	else read_lock(&(DETAIL)->hash_lock);						\
 	for(hp=head; *hp != NULL; hp = &tmp->MEMBER.next) {				\
@@ -175,6 +177,8 @@ RTN *FNAME ARGS										\
 			if (set && !INPLACE && test_bit(CACHE_VALID, &tmp->MEMBER.flags) && !new) \
 				break;							\
 											\
+			if (new)							\
+				{INIT;}							\
 			cache_get(&tmp->MEMBER);					\
 			if (set) {							\
 				if (!INPLACE && test_bit(CACHE_VALID, &tmp->MEMBER.flags))\
@@ -203,6 +207,7 @@ RTN *FNAME ARGS										\
 	}										\
 	/* Didn't find anything */							\
 	if (new) {									\
+		INIT;									\
 		new->MEMBER.next = *head;						\
 		*head = &new->MEMBER;							\
 		(DETAIL)->entries ++;							\
@@ -224,8 +229,6 @@ RTN *FNAME ARGS										\
 	if (new) {									\
 		cache_init(&new->MEMBER);						\
 		cache_get(&new->MEMBER);						\
-		INIT;									\
-		tmp = new;								\
 		goto retry;								\
 	}										\
 	return NULL;									\
--- diff/include/linux/sunrpc/stats.h	2002-12-11 11:50:26.000000000 +0000
+++ source/include/linux/sunrpc/stats.h	2004-02-23 13:56:48.000000000 +0000
@@ -48,14 +48,13 @@ void			rpc_modcount(struct inode *, int)
 #ifdef CONFIG_PROC_FS
 struct proc_dir_entry *	rpc_proc_register(struct rpc_stat *);
 void			rpc_proc_unregister(const char *);
-int			rpc_proc_read(char *, char **, off_t, int,
-					int *, void *);
 void			rpc_proc_zero(struct rpc_program *);
-struct proc_dir_entry *	svc_proc_register(struct svc_stat *);
+struct proc_dir_entry *	svc_proc_register(struct svc_stat *,
+					  struct file_operations *);
 void			svc_proc_unregister(const char *);
-int			svc_proc_read(char *, char **, off_t, int,
-					int *, void *);
-void			svc_proc_zero(struct svc_program *);
+
+void			svc_seq_show(struct seq_file *,
+				     const struct svc_stat *);
 
 extern struct proc_dir_entry	*proc_net_rpc;
 
@@ -63,13 +62,14 @@ extern struct proc_dir_entry	*proc_net_r
 
 static inline struct proc_dir_entry *rpc_proc_register(struct rpc_stat *s) { return NULL; }
 static inline void rpc_proc_unregister(const char *p) {}
-static inline int rpc_proc_read(char *a, char **b, off_t c, int d, int *e, void *f) { return 0; }
 static inline void rpc_proc_zero(struct rpc_program *p) {}
 
-static inline struct proc_dir_entry *svc_proc_register(struct svc_stat *s) { return NULL; }
+static inline struct proc_dir_entry *svc_proc_register(struct svc_stat *s,
+						       struct file_operations *f) { return NULL; }
 static inline void svc_proc_unregister(const char *p) {}
-static inline int svc_proc_read(char *a, char **b, off_t c, int d, int *e, void *f) { return 0; }
-static inline void svc_proc_zero(struct svc_program *p) {}
+
+static inline void svc_seq_show(struct seq_file *seq,
+				const struct svc_stat *st) {}
 
 #define proc_net_rpc NULL
 
--- diff/include/linux/sunrpc/svcauth.h	2003-01-16 11:30:37.000000000 +0000
+++ source/include/linux/sunrpc/svcauth.h	2004-02-23 13:56:48.000000000 +0000
@@ -16,10 +16,11 @@
 #include <linux/sunrpc/cache.h>
 #include <linux/hash.h>
 
+#define SVC_CRED_NGROUPS	32
 struct svc_cred {
 	uid_t			cr_uid;
 	gid_t			cr_gid;
-	gid_t			cr_groups[NGROUPS];
+	gid_t			cr_groups[SVC_CRED_NGROUPS];
 };
 
 struct svc_rqst;		/* forward decl */
--- diff/include/linux/sunrpc/xprt.h	2004-02-18 08:54:13.000000000 +0000
+++ source/include/linux/sunrpc/xprt.h	2004-02-23 13:56:48.000000000 +0000
@@ -164,6 +164,11 @@ struct rpc_xprt {
 	unsigned long		tcp_copied,	/* copied to request */
 				tcp_flags;
 	/*
+	 * Connection of sockets
+	 */
+	struct work_struct	sock_connect;
+	unsigned short		port;
+	/*
 	 * Disconnection of idle sockets
 	 */
 	struct work_struct	task_cleanup;
--- diff/include/linux/sysctl.h	2004-02-18 08:54:13.000000000 +0000
+++ source/include/linux/sysctl.h	2004-02-23 13:56:48.000000000 +0000
@@ -129,6 +129,8 @@ enum
 	KERN_HPPA_UNALIGNED=59,	/* int: hppa unaligned-trap enable */
 	KERN_PRINTK_RATELIMIT=60, /* int: tune printk ratelimiting */
 	KERN_PRINTK_RATELIMIT_BURST=61,	/* int: tune printk ratelimiting */
+	KERN_PTY=62,		/* dir: pty driver */
+	KERN_NGROUPS_MAX=62,	/* int: NGROUPS_MAX */
 };
 
 
@@ -156,6 +158,8 @@ enum
 	VM_SWAPPINESS=19,	/* Tendency to steal mapped memory */
 	VM_LOWER_ZONE_PROTECTION=20,/* Amount of protection of lower zones */
 	VM_MIN_FREE_KBYTES=21,	/* Minimum free kilobytes to maintain */
+	VM_LAPTOP_MODE=22,      /* vm laptop mode */
+	VM_BLOCK_DUMP=23,       /* block dump mode */
 };
 
 
@@ -192,6 +196,13 @@ enum
 	RANDOM_UUID=6
 };
 
+/* /proc/sys/kernel/pty */
+enum
+{
+	PTY_MAX=1,
+	PTY_NR=2
+};
+
 /* /proc/sys/bus/isa */
 enum
 {
@@ -362,6 +373,8 @@ enum
 	NET_IPV4_CONF_NOXFRM=15,
 	NET_IPV4_CONF_NOPOLICY=16,
 	NET_IPV4_CONF_FORCE_IGMP_VERSION=17,
+	NET_IPV4_CONF_ARP_ANNOUNCE=18,
+	NET_IPV4_CONF_ARP_IGNORE=19,
 };
 
 /* /proc/sys/net/ipv4/netfilter */
@@ -380,6 +393,7 @@ enum
 	NET_IPV4_NF_CONNTRACK_UDP_TIMEOUT_STREAM=11,
 	NET_IPV4_NF_CONNTRACK_ICMP_TIMEOUT=12,
 	NET_IPV4_NF_CONNTRACK_GENERIC_TIMEOUT=13,
+	NET_IPV4_NF_CONNTRACK_BUCKETS=14,
 };
  
 /* /proc/sys/net/ipv6 */
@@ -423,7 +437,8 @@ enum {
 	NET_IPV6_TEMP_PREFERED_LFT=13,
 	NET_IPV6_REGEN_MAX_RETRY=14,
 	NET_IPV6_MAX_DESYNC_FACTOR=15,
-	NET_IPV6_MAX_ADDRESSES=16
+	NET_IPV6_MAX_ADDRESSES=16,
+	NET_IPV6_FORCE_MLD_VERSION=17
 };
 
 /* /proc/sys/net/ipv6/icmp */
@@ -617,6 +632,8 @@ enum
 	FS_LEASE_TIME=15,	/* int: maximum time to wait for a lease break */
 	FS_DQSTATS=16,	/* disc quota usage statistics */
 	FS_XFS=17,	/* struct: control xfs parameters */
+	FS_AIO_NR=18,	/* current system-wide number of aio requests */
+	FS_AIO_MAX_NR=19,	/* system-wide maximum number of aio requests */
 };
 
 /* /proc/sys/fs/quota/ */
@@ -719,7 +736,6 @@ enum
 
 #ifdef __KERNEL__
 
-extern asmlinkage long sys_sysctl(struct __sysctl_args __user *);
 extern void sysctl_init(void);
 
 typedef struct ctl_table ctl_table;
--- diff/include/linux/sysdev.h	2003-08-26 10:00:54.000000000 +0100
+++ source/include/linux/sysdev.h	2004-02-23 13:56:48.000000000 +0000
@@ -70,8 +70,8 @@ struct sys_device {
 	struct kobject		kobj;
 };
 
-extern int sys_device_register(struct sys_device *);
-extern void sys_device_unregister(struct sys_device *);
+extern int sysdev_register(struct sys_device *);
+extern void sysdev_unregister(struct sys_device *);
 
 
 struct sysdev_attribute { 
--- diff/include/linux/sysfs.h	2003-08-26 10:00:54.000000000 +0100
+++ source/include/linux/sysfs.h	2004-02-23 13:56:48.000000000 +0000
@@ -18,6 +18,12 @@ struct attribute {
 	mode_t			mode;
 };
 
+struct attribute_group {
+	char			* name;
+	struct attribute	** attrs;
+};
+
+
 struct bin_attribute {
 	struct attribute	attr;
 	size_t			size;
@@ -25,14 +31,13 @@ struct bin_attribute {
 	ssize_t (*write)(struct kobject *, char *, loff_t, size_t);
 };
 
-int sysfs_create_bin_file(struct kobject * kobj, struct bin_attribute * attr);
-int sysfs_remove_bin_file(struct kobject * kobj, struct bin_attribute * attr);
-
 struct sysfs_ops {
 	ssize_t	(*show)(struct kobject *, struct attribute *,char *);
 	ssize_t	(*store)(struct kobject *,struct attribute *,const char *, size_t);
 };
 
+#ifdef CONFIG_SYSFS
+
 extern int
 sysfs_create_dir(struct kobject *);
 
@@ -57,13 +62,75 @@ sysfs_create_link(struct kobject * kobj,
 extern void
 sysfs_remove_link(struct kobject *, char * name);
 
-
-struct attribute_group {
-	char			* name;
-	struct attribute	** attrs;
-};
+int sysfs_create_bin_file(struct kobject * kobj, struct bin_attribute * attr);
+int sysfs_remove_bin_file(struct kobject * kobj, struct bin_attribute * attr);
 
 int sysfs_create_group(struct kobject *, const struct attribute_group *);
 void sysfs_remove_group(struct kobject *, const struct attribute_group *);
 
+#else /* CONFIG_SYSFS */
+
+static inline int sysfs_create_dir(struct kobject * k)
+{
+	return 0;
+}
+
+static inline void sysfs_remove_dir(struct kobject * k)
+{
+	;
+}
+
+static inline void sysfs_rename_dir(struct kobject * k, const char *new_name)
+{
+	;
+}
+
+static inline int sysfs_create_file(struct kobject * k, const struct attribute * a)
+{
+	return 0;
+}
+
+static inline int sysfs_update_file(struct kobject * k, const struct attribute * a)
+{
+	return 0;
+}
+
+static inline void sysfs_remove_file(struct kobject * k, const struct attribute * a)
+{
+	;
+}
+
+static inline int sysfs_create_link(struct kobject * k, struct kobject * t, char * n)
+{
+	return 0;
+}
+
+static inline void sysfs_remove_link(struct kobject * k, char * name)
+{
+	;
+}
+
+
+static inline int sysfs_create_bin_file(struct kobject * k, struct bin_attribute * a)
+{
+	return 0;
+}
+
+static inline int sysfs_remove_bin_file(struct kobject * k, struct bin_attribute * a)
+{
+	return 0;
+}
+
+static inline int sysfs_create_group(struct kobject * k, const struct attribute_group *g)
+{
+	return 0;
+}
+
+static inline void sysfs_remove_group(struct kobject * k, const struct attribute_group * g)
+{
+	;
+}
+
+#endif /* CONFIG_SYSFS */
+
 #endif /* _SYSFS_H_ */
--- diff/include/linux/tty.h	2003-09-30 15:46:20.000000000 +0100
+++ source/include/linux/tty.h	2004-02-23 13:56:48.000000000 +0000
@@ -28,29 +28,13 @@
 
 
 /*
- * Note: don't mess with NR_PTYS until you understand the tty minor 
- * number allocation game...
  * (Note: the *_driver.minor_start values 1, 64, 128, 192 are
  * hardcoded at present.)
  */
-#define NR_PTYS		256	/* ptys/major */
-#define NR_LDISCS	16
-
-/*
- * Unix98 PTY's can be defined as any multiple of NR_PTYS up to
- * UNIX98_PTY_MAJOR_COUNT; this section defines what we need from the
- * config options
- */
-#ifdef CONFIG_UNIX98_PTYS
-# define UNIX98_NR_MAJORS ((CONFIG_UNIX98_PTY_COUNT+NR_PTYS-1)/NR_PTYS)
-# if UNIX98_NR_MAJORS <= 0
-#  undef CONFIG_UNIX98_PTYS
-# elif UNIX98_NR_MAJORS > UNIX98_PTY_MAJOR_COUNT
-#  error  Too many Unix98 ptys defined
-#  undef  UNIX98_NR_MAJORS
-#  define UNIX98_NR_MAJORS UNIX98_PTY_MAJOR_COUNT
-# endif
-#endif
+#define NR_PTYS	CONFIG_LEGACY_PTY_COUNT   /* Number of legacy ptys */
+#define NR_UNIX98_PTY_DEFAULT	4096      /* Default maximum for Unix98 ptys */
+#define NR_UNIX98_PTY_MAX	(1 << MINORBITS) /* Absolute limit */
+#define NR_LDISCS		16
 
 /*
  * These are set up by the setup-routine at boot-time:
--- diff/include/linux/tty_driver.h	2003-06-30 10:07:24.000000000 +0100
+++ source/include/linux/tty_driver.h	2004-02-23 13:56:48.000000000 +0000
@@ -160,9 +160,10 @@ struct tty_driver {
 	const char	*devfs_name;
 	const char	*name;
 	int	name_base;	/* offset of printed name */
-	short	major;		/* major device number */
-	short	minor_start;	/* start of minor device number*/
-	short	num;		/* number of devices */
+	int	major;		/* major device number */
+	int	minor_start;	/* start of minor device number */
+	int	minor_num;	/* number of *possible* devices */
+	int	num;		/* number of devices allocated */
 	short	type;		/* type of tty driver */
 	short	subtype;	/* subtype of tty driver */
 	struct termios init_termios; /* Initial termios */
@@ -244,11 +245,15 @@ void tty_set_operations(struct tty_drive
  * TTY_DRIVER_NO_DEVFS --- if set, do not create devfs entries. This
  *	is only used by tty_register_driver().
  *
+ * TTY_DRIVER_DEVPTS_MEM -- don't use the standard arrays, instead
+ *	use dynamic memory keyed through the devpts filesystem.  This
+ *	is only applicable to the pty driver.
  */
 #define TTY_DRIVER_INSTALLED		0x0001
 #define TTY_DRIVER_RESET_TERMIOS	0x0002
 #define TTY_DRIVER_REAL_RAW		0x0004
 #define TTY_DRIVER_NO_DEVFS		0x0008
+#define TTY_DRIVER_DEVPTS_MEM		0x0010
 
 /* tty driver types */
 #define TTY_DRIVER_TYPE_SYSTEM		0x0001
--- diff/include/linux/ufs_fs.h	2002-10-16 04:28:33.000000000 +0100
+++ source/include/linux/ufs_fs.h	2004-02-23 13:56:48.000000000 +0000
@@ -22,6 +22,9 @@
  * HP/UX hfs filesystem support added by
  * Martin K. Petersen <mkp@mkp.net>, August 1999
  *
+ * UFS2 (of FreeBSD 5.x) support added by
+ * Niraj Kumar <niraj17@iitbombay.org>  , Jan 2004
+ *
  */
 
 #ifndef __LINUX_UFS_FS_H
@@ -43,8 +46,50 @@
 
 #define UFS_SECTOR_SIZE 512
 #define UFS_SECTOR_BITS 9
-#define UFS_MAGIC 0x00011954
-#define UFS_CIGAM 0x54190100 /* byteswapped MAGIC */
+#define UFS_MAGIC  0x00011954
+#define UFS2_MAGIC 0x19540119
+#define UFS_CIGAM  0x54190100 /* byteswapped MAGIC */
+
+/* Copied from FreeBSD */
+/*
+ * Each disk drive contains some number of filesystems.
+ * A filesystem consists of a number of cylinder groups.
+ * Each cylinder group has inodes and data.
+ *
+ * A filesystem is described by its super-block, which in turn
+ * describes the cylinder groups.  The super-block is critical
+ * data and is replicated in each cylinder group to protect against
+ * catastrophic loss.  This is done at `newfs' time and the critical
+ * super-block data does not change, so the copies need not be
+ * referenced further unless disaster strikes.
+ *
+ * For filesystem fs, the offsets of the various blocks of interest
+ * are given in the super block as:
+ *      [fs->fs_sblkno]         Super-block
+ *      [fs->fs_cblkno]         Cylinder group block
+ *      [fs->fs_iblkno]         Inode blocks
+ *      [fs->fs_dblkno]         Data blocks
+ * The beginning of cylinder group cg in fs, is given by
+ * the ``cgbase(fs, cg)'' macro.
+ *
+ * Depending on the architecture and the media, the superblock may
+ * reside in any one of four places. For tiny media where every block
+ * counts, it is placed at the very front of the partition. Historically,
+ * UFS1 placed it 8K from the front to leave room for the disk label and
+ * a small bootstrap. For UFS2 it got moved to 64K from the front to leave
+ * room for the disk label and a bigger bootstrap, and for really piggy
+ * systems we check at 256K from the front if the first three fail. In
+ * all cases the size of the superblock will be SBLOCKSIZE. All values are
+ * given in byte-offset form, so they do not imply a sector size. The
+ * SBLOCKSEARCH specifies the order in which the locations should be searched.
+ */
+#define SBLOCK_FLOPPY        0
+#define SBLOCK_UFS1       8192
+#define SBLOCK_UFS2      65536
+#define SBLOCK_PIGGY    262144
+#define SBLOCKSIZE        8192
+#define SBLOCKSEARCH \
+        { SBLOCK_UFS2, SBLOCK_UFS1, SBLOCK_FLOPPY, SBLOCK_PIGGY, -1 }
 
 
 /* HP specific MAGIC values */
@@ -120,6 +165,11 @@
 #define UFS_CG_OLD		0x00000000
 #define UFS_CG_44BSD		0x00002000
 #define UFS_CG_SUN		0x00001000
+/* filesystem type encoding */
+#define UFS_TYPE_MASK		0x00010000	/* mask for the following */
+#define UFS_TYPE_UFS1		0x00000000
+#define UFS_TYPE_UFS2		0x00010000
+
 
 /* fs_inodefmt options */
 #define UFS_42INODEFMT	-1
@@ -132,7 +182,7 @@
 #define UFS_MOUNT_ONERROR_UMOUNT	0x00000004
 #define UFS_MOUNT_ONERROR_REPAIR	0x00000008
 
-#define UFS_MOUNT_UFSTYPE		0x00000FF0
+#define UFS_MOUNT_UFSTYPE		0x0000FFF0
 #define UFS_MOUNT_UFSTYPE_OLD		0x00000010
 #define UFS_MOUNT_UFSTYPE_44BSD		0x00000020
 #define UFS_MOUNT_UFSTYPE_SUN		0x00000040
@@ -141,6 +191,7 @@
 #define UFS_MOUNT_UFSTYPE_OPENSTEP	0x00000200
 #define UFS_MOUNT_UFSTYPE_SUNx86	0x00000400
 #define UFS_MOUNT_UFSTYPE_HP	        0x00000800
+#define UFS_MOUNT_UFSTYPE_UFS2		0x00001000
 
 #define ufs_clear_opt(o,opt)	o &= ~UFS_MOUNT_##opt
 #define ufs_set_opt(o,opt)	o |= UFS_MOUNT_##opt
@@ -173,7 +224,8 @@
  * They calc file system addresses of cylinder group data structures.
  */
 #define	ufs_cgbase(c)	(uspi->s_fpg * (c))
-#define ufs_cgstart(c)	(ufs_cgbase(c)  + uspi->s_cgoffset * ((c) & ~uspi->s_cgmask))
+#define ufs_cgstart(c)	((uspi)->fs_magic == UFS2_MAGIC ?  ufs_cgbase(c) : \
+	(ufs_cgbase(c)  + uspi->s_cgoffset * ((c) & ~uspi->s_cgmask)))
 #define	ufs_cgsblock(c)	(ufs_cgstart(c) + uspi->s_sblkno)	/* super blk */
 #define	ufs_cgcmin(c)	(ufs_cgstart(c) + uspi->s_cblkno)	/* cg block */
 #define	ufs_cgimin(c)	(ufs_cgstart(c) + uspi->s_iblkno)	/* inode blk */
@@ -227,8 +279,14 @@
 
 #define	UFS_MAXNAMLEN 255
 #define UFS_MAXMNTLEN 512
+#define UFS2_MAXMNTLEN 468
+#define UFS2_MAXVOLLEN 32
 /* #define UFS_MAXCSBUFS 31 */
 #define UFS_LINK_MAX 32000
+/*
+#define	UFS2_NOCSPTRS	((128 / sizeof(void *)) - 4)
+*/
+#define	UFS2_NOCSPTRS	28
 
 /*
  * UFS_DIR_PAD defines the directory entries boundaries
@@ -262,6 +320,14 @@ struct ufs_csum {
 	__u32	cs_nifree;	/* number of free inodes */
 	__u32	cs_nffree;	/* number of free frags */
 };
+struct ufs2_csum_total {
+	__u64	cs_ndir;	/* number of directories */
+	__u64	cs_nbfree;	/* number of free blocks */
+	__u64	cs_nifree;	/* number of free inodes */
+	__u64	cs_nffree;	/* number of free frags */
+	__u64   cs_numclusters;	/* number of free clusters */
+	__u64   cs_spare[3];	/* future expansion */
+};
 
 /*
  * This is the actual superblock, as it is laid out on the disk.
@@ -333,7 +399,7 @@ struct ufs_super_block {
 	__u32	fs_ncyl;	/* cylinders in file system */
 /* these fields can be computed from the others */
 	__u32	fs_cpg;		/* cylinders per group */
-	__u32	fs_ipg;		/* inodes per group */
+	__u32	fs_ipg;		/* inodes per cylinder group */
 	__u32	fs_fpg;		/* blocks per group * fs_frag */
 /* this data must be re-computed after crashes */
 	struct ufs_csum fs_cstotal;	/* cylinder summary information */
@@ -342,13 +408,39 @@ struct ufs_super_block {
 	__s8	fs_clean;	/* file system is clean flag */
 	__s8	fs_ronly;	/* mounted read-only flag */
 	__s8	fs_flags;	/* currently unused flag */
-	__s8	fs_fsmnt[UFS_MAXMNTLEN];	/* name mounted on */
-/* these fields retain the current block allocation info */
-	__u32	fs_cgrotor;	/* last cg searched */
-	__u32	fs_csp[UFS_MAXCSBUFS];	/* list of fs_cs info buffers */
-	__u32	fs_maxcluster;
-	__u32	fs_cpc;		/* cyl per cycle in postbl */
-	__u16	fs_opostbl[16][8];	/* old rotation block list head */	
+	union {
+		struct {
+			__s8	fs_fsmnt[UFS_MAXMNTLEN];/* name mounted on */
+			__u32	fs_cgrotor;	/* last cg searched */
+			__u32	fs_csp[UFS_MAXCSBUFS];/*list of fs_cs info buffers */
+			__u32	fs_maxcluster;
+			__u32	fs_cpc;		/* cyl per cycle in postbl */
+			__u16	fs_opostbl[16][8]; /* old rotation block list head */
+		} fs_u1;
+		struct {
+			__s8  fs_fsmnt[UFS2_MAXMNTLEN];	/* name mounted on */
+			__u8   fs_volname[UFS2_MAXVOLLEN]; /* volume name */
+			__u64  fs_swuid;		/* system-wide uid */
+			__s32  fs_pad;	/* due to alignment of fs_swuid */
+			__u32   fs_cgrotor;     /* last cg searched */
+			__u32   fs_ocsp[UFS2_NOCSPTRS]; /*list of fs_cs info buffers */
+			__u32   fs_contigdirs;/*# of contiguously allocated dirs */
+			__u32   fs_csp;	/* cg summary info buffer for fs_cs */
+			__u32   fs_maxcluster;
+			__u32   fs_active;/* used by snapshots to track fs */
+			__s32   fs_old_cpc;	/* cyl per cycle in postbl */
+			__s32   fs_maxbsize;/*maximum blocking factor permitted */
+			__s64   fs_sparecon64[17];/*old rotation block list head */
+			__s64   fs_sblockloc; /* byte offset of standard superblock */
+			struct  ufs2_csum_total fs_cstotal;/*cylinder summary information*/
+			struct  ufs_timeval    fs_time;		/* last time written */
+			__s64    fs_size;		/* number of blocks in fs */
+			__s64    fs_dsize;	/* number of data blocks in fs */
+			__u64    fs_csaddr;	/* blk addr of cyl grp summary area */
+			__s64    fs_pendingblocks;/* blocks in process of being freed */
+			__s32    fs_pendinginodes;/*inodes in process of being freed */
+		} fs_u2;
+	}  fs_u11;
 	union {
 		struct {
 			__s32	fs_sparecon[53];/* reserved for future constants */
@@ -441,6 +533,16 @@ struct	ufs_cylinder_group {
 			__u32	cg_nclusterblks;	/* number of clusters this cg */
 			__u32	cg_sparecon[13];	/* reserved for future use */
 		} cg_44;
+		struct {
+			__u32	cg_clustersumoff;/* (u_int32) counts of avail clusters */
+			__u32	cg_clusteroff;	/* (u_int8) free cluster map */
+			__u32	cg_nclusterblks;/* number of clusters this cg */
+			__u32   cg_niblk; /* number of inode blocks this cg */
+			__u32   cg_initediblk;	/* last initialized inode */
+			__u32   cg_sparecon32[3];/* reserved for future use */
+			__u64   cg_time;	/* time last written */
+			__u64	cg_sparecon[3];	/* reserved for future use */
+		} cg_u2;
 		__u32	cg_sparecon[16];	/* reserved for future use */
 	} cg_u;
 	__u8	cg_space[1];		/* space for cylinder group maps */
@@ -497,6 +599,39 @@ struct ufs_inode {
 	} ui_u3;
 };
 
+#define UFS_NXADDR  2            /* External addresses in inode. */
+struct ufs2_inode {
+	__u16     ui_mode;        /*   0: IFMT, permissions; see below. */
+	__s16     ui_nlink;       /*   2: File link count. */
+	__u32     ui_uid;         /*   4: File owner. */
+	__u32     ui_gid;         /*   8: File group. */
+	__u32     ui_blksize;     /*  12: Inode blocksize. */
+	__u64     ui_size;        /*  16: File byte count. */
+	__u64     ui_blocks;      /*  24: Bytes actually held. */
+	struct ufs_timeval   ui_atime;       /*  32: Last access time. */
+	struct ufs_timeval   ui_mtime;       /*  40: Last modified time. */
+	struct ufs_timeval   ui_ctime;       /*  48: Last inode change time. */
+	struct ufs_timeval   ui_birthtime;   /*  56: Inode creation time. */
+	__s32     ui_mtimensec;   /*  64: Last modified time. */
+	__s32     ui_atimensec;   /*  68: Last access time. */
+	__s32     ui_ctimensec;   /*  72: Last inode change time. */
+	__s32     ui_birthnsec;   /*  76: Inode creation time. */
+	__s32     ui_gen;         /*  80: Generation number. */
+	__u32     ui_kernflags;   /*  84: Kernel flags. */
+	__u32     ui_flags;       /*  88: Status flags (chflags). */
+	__s32     ui_extsize;     /*  92: External attributes block. */
+	__s64     ui_extb[UFS_NXADDR];/*  96: External attributes block. */
+	union {
+		struct {
+			__s64     ui_db[UFS_NDADDR]; /* 112: Direct disk blocks. */
+			__s64     ui_ib[UFS_NINDIR];/* 208: Indirect disk blocks.*/
+		} ui_addr;
+	__u8	ui_symlink[2*4*(UFS_NDADDR+UFS_NINDIR)];/* 0x28 fast symlink */
+	} ui_u2;
+	__s64     ui_spare[3];    /* 232: Reserved; currently unused */
+};
+
+
 /* FreeBSD has these in sys/stat.h */
 /* ui_flags that can be set by a file owner */
 #define UFS_UF_SETTABLE   0x0000ffff
@@ -517,8 +652,8 @@ struct ufs_inode {
  * than the size of fragment.
  */
 struct ufs_buffer_head {
-	unsigned fragment;			/* first fragment */
-	unsigned count;				/* number of fragments */
+	__u64 fragment;			/* first fragment */
+	__u64 count;				/* number of fragments */
 	struct buffer_head * bh[UFS_MAXFRAG];	/* buffers */
 };
 
@@ -551,6 +686,8 @@ struct ufs_sb_private_info {
 	__u32	s_cgmask;	/* used to calc mod fs_ntrak */
 	__u32	s_size;		/* number of blocks (fragments) in fs */
 	__u32	s_dsize;	/* number of data blocks in fs */
+	__u64	s_u2_size;	/* ufs2: number of blocks (fragments) in fs */
+	__u64	s_u2_dsize;	/*ufs2:  number of data blocks in fs */
 	__u32	s_ncg;		/* number of cylinder groups */
 	__u32	s_bsize;	/* size of basic blocks */
 	__u32	s_fsize;	/* size of fragments */
@@ -577,7 +714,7 @@ struct ufs_sb_private_info {
 	__u32	s_ntrak;	/* tracks per cylinder */
 	__u32	s_nsect;	/* sectors per track */
 	__u32	s_spc;		/* sectors per cylinder */
-	__u32	s_ipg;		/* inodes per group */
+	__u32	s_ipg;		/* inodes per cylinder group */
 	__u32	s_fpg;		/* fragments per group */
 	__u32	s_cpc;		/* cyl per cycle in postbl */
 	__s32	s_contigsumsize;/* size of cluster summary array, 44bsd */
@@ -605,6 +742,7 @@ struct ufs_sb_private_info {
 	__u32	s_bpfmask;	/* bits per fragment mask */
 
 	__u32	s_maxsymlinklen;/* upper limit on fast symlinks' size */
+	__s32	fs_magic;       /* filesystem magic */
 };
 
 /*
@@ -758,7 +896,7 @@ extern void ufs_free_inode (struct inode
 extern struct inode * ufs_new_inode (struct inode *, int);
 
 /* inode.c */
-extern int ufs_frag_map (struct inode *, int);
+extern u64  ufs_frag_map (struct inode *, int);
 extern void ufs_read_inode (struct inode *);
 extern void ufs_put_inode (struct inode *);
 extern void ufs_write_inode (struct inode *, int);
--- diff/include/linux/ufs_fs_i.h	2002-10-16 04:27:08.000000000 +0100
+++ source/include/linux/ufs_fs_i.h	2004-02-23 13:56:48.000000000 +0000
@@ -17,6 +17,7 @@ struct ufs_inode_info {
 	union {
 		__u32	i_data[15];
 		__u8	i_symlink[4*15];
+		__u64	u2_i_data[15];
 	} i_u1;
 	__u32	i_flags;
 	__u32	i_gen;
--- diff/include/linux/workqueue.h	2003-05-21 11:50:10.000000000 +0100
+++ source/include/linux/workqueue.h	2004-02-23 13:56:48.000000000 +0000
@@ -60,6 +60,7 @@ extern int FASTCALL(schedule_work(struct
 extern int FASTCALL(schedule_delayed_work(struct work_struct *work, unsigned long delay));
 extern void flush_scheduled_work(void);
 extern int current_is_keventd(void);
+extern int keventd_up(void);
 
 extern void init_workqueues(void);
 
--- diff/include/linux/writeback.h	2003-10-09 09:47:17.000000000 +0100
+++ source/include/linux/writeback.h	2004-02-23 13:56:48.000000000 +0000
@@ -71,12 +71,15 @@ static inline void wait_on_inode(struct 
  * mm/page-writeback.c
  */
 int wakeup_bdflush(long nr_pages);
+void disk_is_spun_up(int postpone_writeback);
 
-/* These 5 are exported to sysctl. */
+/* These are exported to sysctl. */
 extern int dirty_background_ratio;
 extern int vm_dirty_ratio;
 extern int dirty_writeback_centisecs;
 extern int dirty_expire_centisecs;
+extern int block_dump;
+extern int laptop_mode;
 
 struct ctl_table;
 struct file;
--- diff/include/media/tuner.h	2004-02-09 10:36:12.000000000 +0000
+++ source/include/media/tuner.h	2004-02-23 13:56:48.000000000 +0000
@@ -67,7 +67,9 @@
 #define TUNER_HITACHI_NTSC       40
 #define TUNER_PHILIPS_PAL_MK     41
 #define TUNER_PHILIPS_ATSC       42
-#define TUNER_PHILIPS_FM1236_MK3  43
+#define TUNER_PHILIPS_FM1236_MK3 43
+#define TUNER_PHILIPS_4IN1       44	/* ATI TV Wonder Pro - Conexant */
+#define TUNER_MICROTUNE_4049FM5  45
 
 #define NOTUNER 0
 #define PAL     1	/* PAL_BG */
--- diff/include/net/addrconf.h	2004-02-09 10:36:12.000000000 +0000
+++ source/include/net/addrconf.h	2004-02-23 13:56:48.000000000 +0000
@@ -98,6 +98,7 @@ extern void addrconf_dad_failure(struct 
 
 extern int ipv6_chk_mcast_addr(struct net_device *dev, struct in6_addr *group,
 		struct in6_addr *src_addr);
+extern int ipv6_is_mld(struct sk_buff *skb, int nexthdr);
 
 extern void addrconf_prefix_rcv(struct net_device *dev, u8 *opt, int len);
 
--- diff/include/net/dn_nsp.h	2003-06-30 10:07:24.000000000 +0100
+++ source/include/net/dn_nsp.h	2004-02-23 13:56:48.000000000 +0000
@@ -37,7 +37,7 @@ extern int dn_nsp_rx(struct sk_buff *);
 extern int dn_nsp_backlog_rcv(struct sock *sk, struct sk_buff *skb);
 
 extern struct sk_buff *dn_alloc_skb(struct sock *sk, int size, int pri);
-extern struct sk_buff *dn_alloc_send_skb(struct sock *sk, int *size, int noblock, int *err);
+extern struct sk_buff *dn_alloc_send_skb(struct sock *sk, size_t *size, int noblock, int *err);
 
 #define NSP_REASON_OK 0		/* No error */
 #define NSP_REASON_NR 1		/* No resources */
--- diff/include/net/ip6_route.h	2003-08-20 14:16:14.000000000 +0100
+++ source/include/net/ip6_route.h	2004-02-23 13:56:48.000000000 +0000
@@ -64,6 +64,7 @@ extern struct rt6_info		*rt6_lookup(stru
 
 extern struct dst_entry *ndisc_dst_alloc(struct net_device *dev,
 					 struct neighbour *neigh,
+					 struct in6_addr *addr,
 					 int (*output)(struct sk_buff *));
 extern int ndisc_dst_gc(int *more);
 extern void fib6_force_start_gc(void);
--- diff/include/net/ip_vs.h	2003-10-09 09:47:34.000000000 +0100
+++ source/include/net/ip_vs.h	2004-02-23 13:56:48.000000000 +0000
@@ -8,7 +8,7 @@
 
 #include <asm/types.h>		/* For __uXX types */
 
-#define IP_VS_VERSION_CODE	0x010108
+#define IP_VS_VERSION_CODE	0x010200
 #define NVERSION(version)			\
 	(version >> 16) & 0xFF,			\
 	(version >> 8) & 0xFF,			\
--- diff/include/net/ipv6.h	2004-02-09 10:36:12.000000000 +0000
+++ source/include/net/ipv6.h	2004-02-23 13:56:48.000000000 +0000
@@ -355,6 +355,7 @@ extern int			ip6_dst_lookup(struct sock 
  */
 
 extern int			ip6_output(struct sk_buff *skb);
+extern int			ip6_output2(struct sk_buff *skb);
 extern int			ip6_forward(struct sk_buff *skb);
 extern int			ip6_input(struct sk_buff *skb);
 extern int			ip6_mc_input(struct sk_buff *skb);
@@ -379,7 +380,7 @@ extern void			ipv6_push_frag_opts(struct
 						    struct ipv6_txoptions *opt,
 						    u8 *proto);
 
-extern int			ipv6_skip_exthdr(struct sk_buff *, int start,
+extern int			ipv6_skip_exthdr(const struct sk_buff *, int start,
 					         u8 *nexthdrp, int len);
 
 extern int 			ipv6_ext_hdr(u8 nexthdr);
--- diff/include/net/lapb.h	2003-10-09 09:47:34.000000000 +0100
+++ source/include/net/lapb.h	2004-02-23 13:56:48.000000000 +0000
@@ -80,7 +80,7 @@ struct lapb_frame {
  */
 struct lapb_cb {
 	struct list_head	node;
-	void			*token;
+	struct net_device	*dev;
 
 	/* Link status fields */
 	unsigned int		mode;
--- diff/include/net/pkt_sched.h	2004-02-18 08:54:13.000000000 +0000
+++ source/include/net/pkt_sched.h	2004-02-23 13:56:48.000000000 +0000
@@ -440,9 +440,6 @@ int qdisc_new_estimator(struct tc_stats 
 void qdisc_kill_estimator(struct tc_stats *stats);
 struct qdisc_rate_table *qdisc_get_rtab(struct tc_ratespec *r, struct rtattr *tab);
 void qdisc_put_rtab(struct qdisc_rate_table *tab);
-int teql_init(void);
-int tc_filter_init(void);
-int pktsched_init(void);
 
 extern int qdisc_restart(struct net_device *dev);
 
--- diff/include/scsi/scsi.h	2004-02-09 10:36:12.000000000 +0000
+++ source/include/scsi/scsi.h	2004-02-23 13:56:48.000000000 +0000
@@ -12,13 +12,20 @@
 
 
 /*
- * SCSI command lengths
+ *	SCSI command lengths
  */
 
 extern const unsigned char scsi_command_size[8];
 #define COMMAND_SIZE(opcode) scsi_command_size[((opcode) >> 5) & 7]
 
 /*
+ *	SCSI device types
+ */
+
+#define MAX_SCSI_DEVICE_CODE 14
+extern const char *const scsi_device_types[MAX_SCSI_DEVICE_CODE];
+
+/*
  *      SCSI opcodes
  */
 
@@ -311,6 +318,42 @@ struct scsi_lun {
 #define SCSI_MLQUEUE_DEVICE_BUSY 0x1056
 #define SCSI_MLQUEUE_EH_RETRY    0x1057
 
+/*
+ *  Use these to separate status msg and our bytes
+ *
+ *  These are set by:
+ *
+ *      status byte = set from target device
+ *      msg_byte    = return status from host adapter itself.
+ *      host_byte   = set by low-level driver to indicate status.
+ *      driver_byte = set by mid-level.
+ */
+#define status_byte(result) (((result) >> 1) & 0x1f)
+#define msg_byte(result)    (((result) >> 8) & 0xff)
+#define host_byte(result)   (((result) >> 16) & 0xff)
+#define driver_byte(result) (((result) >> 24) & 0xff)
+#define suggestion(result)  (driver_byte(result) & SUGGEST_MASK)
+
+#define sense_class(sense)  (((sense) >> 4) & 0x7)
+#define sense_error(sense)  ((sense) & 0xf)
+#define sense_valid(sense)  ((sense) & 0x80);
+
+
+#define IDENTIFY_BASE       0x80
+#define IDENTIFY(can_disconnect, lun)   (IDENTIFY_BASE |\
+		     ((can_disconnect) ?  0x40 : 0) |\
+		     ((lun) & 0x07))
+
+/*
+ *  SCSI command sets
+ */
+
+#define SCSI_UNKNOWN    0
+#define SCSI_1          1
+#define SCSI_1_CCS      2
+#define SCSI_2          3
+#define SCSI_3          4
+
 
 /*
  * Here are some scsi specific ioctl commands which are sometimes useful.
--- diff/include/sound/pcm_oss.h	2004-02-18 08:54:13.000000000 +0000
+++ source/include/sound/pcm_oss.h	2004-02-23 13:56:48.000000000 +0000
@@ -50,6 +50,7 @@ typedef struct _snd_pcm_oss_runtime {
 	unsigned int maxfrags;
 	unsigned int subdivision;		/* requested subdivision */
 	size_t period_bytes;			/* requested period size */
+	size_t period_frames;			/* period frames for poll */
 	size_t period_ptr;			/* actual write pointer to period */
 	unsigned int periods;
 	size_t buffer_bytes;			/* requested buffer size */
--- diff/init/Kconfig	2004-01-19 10:22:59.000000000 +0000
+++ source/init/Kconfig	2004-02-23 13:56:48.000000000 +0000
@@ -43,7 +43,7 @@ config CLEAN_COMPILE
 
 config STANDALONE
 	bool "Select only drivers that don't need compile-time external firmware" if EXPERIMENTAL
-	default y
+	default n
 	help
 	  Select this option if you don't have magic firmware for drivers that
 	  need it.
@@ -137,6 +137,25 @@ config LOG_BUF_SHIFT
 		     13 =>  8 KB
 		     12 =>  4 KB
 
+config HOTPLUG
+	bool "Support for hot-pluggable devices" if !ARCH_S390
+	default ARCH_S390
+	help
+	  Say Y here if you want to plug devices into your computer while
+	  the system is running, and be able to use them quickly.  In many
+	  cases, the devices can likewise be unplugged at any time too.
+
+	  One well known example of this is PCMCIA- or PC-cards, credit-card
+	  size devices such as network cards, modems or hard drives which are
+	  plugged into slots found on all modern laptop computers.  Another
+	  example, used on modern desktops as well as laptops, is USB.
+
+	  Enable HOTPLUG and KMOD, and build a modular kernel.  Get agent
+	  software (at <http://linux-hotplug.sourceforge.net/>) and install it.
+	  Then your kernel will automatically call out to a user mode "policy
+	  agent" (/sbin/hotplug) to load modules and set up software needed
+	  to use devices as you hotplug them.
+
 config IKCONFIG
 	bool "Kernel .config support"
 	---help---
@@ -285,4 +304,10 @@ config KMOD
 	  runs modprobe with the appropriate arguments, thereby
 	  loading the module if it is available.  If unsure, say Y.
 
+config STOP_MACHINE
+	bool
+	default y
+	depends on (SMP && MODULE_UNLOAD) || HOTPLUG_CPU
+	help
+	  Need stop_machine() primitive.
 endmenu
--- diff/init/Makefile	2003-05-21 11:50:16.000000000 +0100
+++ source/init/Makefile	2004-02-23 13:56:48.000000000 +0000
@@ -23,4 +23,4 @@ $(obj)/version.o: include/linux/compile.
 
 include/linux/compile.h: FORCE
 	@echo '  CHK     $@'
-	@sh $(srctree)/scripts/mkcompile_h $@ "$(UTS_MACHINE)" "$(CONFIG_SMP)" "$(CC) $(CFLAGS)"
+	@$(CONFIG_SHELL) $(srctree)/scripts/mkcompile_h $@ "$(UTS_MACHINE)" "$(CONFIG_SMP)" "$(CC) $(CFLAGS)"
--- diff/init/do_mounts.c	2004-01-19 10:22:59.000000000 +0000
+++ source/init/do_mounts.c	2004-02-23 13:56:48.000000000 +0000
@@ -141,9 +141,11 @@ dev_t __init name_to_dev_t(char *name)
 	dev_t res = 0;
 	int part;
 
+#ifdef CONFIG_SYSFS
 	sys_mkdir("/sys", 0700);
 	if (sys_mount("sysfs", "/sys", "sysfs", 0, NULL) < 0)
 		goto out;
+#endif
 
 	if (strncmp(name, "/dev/", 5) != 0) {
 		unsigned maj, min;
--- diff/init/do_mounts.h	2003-10-09 09:47:34.000000000 +0100
+++ source/init/do_mounts.h	2004-02-23 13:56:48.000000000 +0000
@@ -3,25 +3,13 @@
 #include <linux/kernel.h>
 #include <linux/devfs_fs_kernel.h>
 #include <linux/init.h>
+#include <linux/syscalls.h>
 #include <linux/unistd.h>
 #include <linux/slab.h>
 #include <linux/mount.h>
 #include <linux/major.h>
 #include <linux/root_dev.h>
 
-asmlinkage long sys_unlink(const char *name);
-asmlinkage long sys_mknod(const char *name, int mode, unsigned dev);
-asmlinkage long sys_newstat(char * filename, struct stat * statbuf);
-asmlinkage long sys_ioctl(int fd, int cmd, unsigned long arg);
-asmlinkage long sys_mkdir(const char *name, int mode);
-asmlinkage long sys_rmdir(const char *name);
-asmlinkage long sys_chdir(const char *name);
-asmlinkage long sys_fchdir(int fd);
-asmlinkage long sys_chroot(const char *name);
-asmlinkage long sys_mount(char *dev_name, char *dir_name, char *type,
-				 unsigned long flags, void *data);
-asmlinkage long sys_umount(char *name, int flags);
-
 dev_t name_to_dev_t(char *name);
 void  change_floppy(char *fmt, ...);
 void  mount_block_root(char *name, int flags);
@@ -49,7 +37,6 @@ static inline int create_dev(char *name,
 #endif
 
 #if BITS_PER_LONG == 32
-asmlinkage long sys_stat64(char *name, struct stat64 *stat);
 static inline u32 bstat(char *name)
 {
 	struct stat64 stat;
--- diff/init/do_mounts_devfs.c	2003-09-30 15:46:21.000000000 +0100
+++ source/init/do_mounts_devfs.c	2004-02-23 13:56:48.000000000 +0000
@@ -2,14 +2,10 @@
 #include <linux/kernel.h>
 #include <linux/dirent.h>
 #include <linux/string.h>
+#include <linux/syscalls.h>
 
 #include "do_mounts.h"
 
-extern asmlinkage long sys_symlink(const char *old, const char *new);
-extern asmlinkage long sys_access(const char * filename, int mode);
-extern asmlinkage long sys_getdents64(unsigned int fd, void * dirent,
-				      unsigned int count);
-
 void __init mount_devfs(void)
 {
 	sys_mount("devfs", "/dev", "devfs", 0, NULL);
@@ -31,7 +27,8 @@ static int __init do_read_dir(int fd, vo
 	lseek(fd, 0, 0);
 
 	for (bytes = 0; bytes < len; bytes += n) {
-		n = sys_getdents64(fd, p + bytes, len - bytes);
+		n = sys_getdents64(fd, (struct linux_dirent64 *)(p + bytes),
+					len - bytes);
 		if (n < 0)
 			return n;
 		if (n == 0)
--- diff/init/initramfs.c	2003-10-27 09:20:44.000000000 +0000
+++ source/init/initramfs.c	2004-02-23 13:56:48.000000000 +0000
@@ -7,6 +7,7 @@
 #include <linux/unistd.h>
 #include <linux/delay.h>
 #include <linux/string.h>
+#include <linux/syscalls.h>
 
 static __initdata char *message;
 static void __init error(char *x)
@@ -25,17 +26,6 @@ static void __init free(void *where)
 	kfree(where);
 }
 
-asmlinkage long sys_mkdir(char *name, int mode);
-asmlinkage long sys_mknod(char *name, int mode, unsigned dev);
-asmlinkage long sys_symlink(char *old, char *new);
-asmlinkage long sys_link(char *old, char *new);
-asmlinkage long sys_write(int fd, const char *buf, size_t size);
-asmlinkage long sys_chown(char *name, uid_t uid, gid_t gid);
-asmlinkage long sys_lchown(char *name, uid_t uid, gid_t gid);
-asmlinkage long sys_fchown(int fd, uid_t uid, gid_t gid);
-asmlinkage long sys_chmod(char *name, mode_t mode);
-asmlinkage long sys_fchmod(int fd, mode_t mode);
-
 /* link hash */
 
 static struct hash {
--- diff/init/main.c	2004-02-18 08:54:13.000000000 +0000
+++ source/init/main.c	2004-02-23 13:56:48.000000000 +0000
@@ -12,10 +12,12 @@
 #define __KERNEL_SYSCALLS__
 
 #include <linux/config.h>
+#include <linux/types.h>
 #include <linux/module.h>
 #include <linux/proc_fs.h>
 #include <linux/devfs_fs_kernel.h>
 #include <linux/kernel.h>
+#include <linux/syscalls.h>
 #include <linux/unistd.h>
 #include <linux/string.h>
 #include <linux/ctype.h>
@@ -141,6 +143,7 @@ __setup("maxcpus=", maxcpus);
 
 static char * argv_init[MAX_INIT_ARGS+2] = { "init", NULL, };
 char * envp_init[MAX_INIT_ENVS+2] = { "HOME=/", "TERM=linux", NULL, };
+static const char *panic_later, *panic_param;
 
 __setup("profile=", profile_setup);
 
@@ -253,20 +256,27 @@ static int __init unknown_bootoption(cha
 		return 0;
 	}
 
+	if (panic_later)
+		return 0;
+
 	if (val) {
 		/* Environment option */
 		unsigned int i;
 		for (i = 0; envp_init[i]; i++) {
-			if (i == MAX_INIT_ENVS)
-				panic("Too many boot env vars at `%s'", param);
+			if (i == MAX_INIT_ENVS) {
+				panic_later = "Too many boot env vars at `%s'";
+				panic_param = param;
+			}
 		}
 		envp_init[i] = param;
 	} else {
 		/* Command line option */
 		unsigned int i;
 		for (i = 0; argv_init[i]; i++) {
-			if (i == MAX_INIT_ARGS)
-				panic("Too many boot init vars at `%s'",param);
+			if (i == MAX_INIT_ARGS) {
+				panic_later = "Too many boot init vars at `%s'";
+				panic_param = param;
+			}
 		}
 		argv_init[i] = param;
 	}
@@ -289,6 +299,15 @@ static int __init init_setup(char *str)
 }
 __setup("init=", init_setup);
 
+static char *kinit_command;
+
+static int __init kinit_setup(char *str)
+{
+	kinit_command = str;
+	return 1;
+}
+__setup("kinit=", kinit_setup);
+
 extern void setup_arch(char **);
 extern void cpu_idle(void);
 
@@ -370,9 +389,11 @@ static void __init smp_init(void)
  * between the root thread and the init thread may cause start_kernel to
  * be reaped by free_initmem before the root thread has proceeded to
  * cpu_idle.
+ *
+ * gcc-3.4 accidentally inlines this function, so use noinline.
  */
 
-static void rest_init(void)
+static void noinline rest_init(void)
 {
 	kernel_thread(init, NULL, CLONE_FS | CLONE_SIGHAND);
 	unlock_kernel();
@@ -405,12 +426,12 @@ asmlinkage void __init start_kernel(void
 
 	build_all_zonelists();
 	page_alloc_init();
+	trap_init();
 	printk("Kernel command line: %s\n", saved_command_line);
 	parse_args("Booting kernel", command_line, __start___param,
 		   __stop___param - __start___param,
 		   &unknown_bootoption);
 	sort_main_extable();
-	trap_init();
 	rcu_init();
 	init_IRQ();
 	pidhash_init();
@@ -424,6 +445,8 @@ asmlinkage void __init start_kernel(void
 	 * this. But we do want output early, in case something goes wrong.
 	 */
 	console_init();
+	if (panic_later)
+		panic(panic_later, panic_param);
 	profile_init();
 	local_irq_enable();
 #ifdef CONFIG_BLK_DEV_INITRD
@@ -450,6 +473,7 @@ asmlinkage void __init start_kernel(void
 	fork_init(num_physpages);
 	proc_caches_init();
 	buffer_init();
+	unnamed_dev_init();
 	security_scaffolding_startup();
 	vfs_caches_init(num_physpages);
 	radix_tree_init();
@@ -549,7 +573,6 @@ static void do_pre_smp_initcalls(void)
 
 	migration_init();
 #endif
-	node_nr_running_init();
 	spawn_ksoftirqd();
 }
 
@@ -580,8 +603,16 @@ static int init(void * unused)
 	do_pre_smp_initcalls();
 
 	smp_init();
+	sched_init_smp();
 	do_basic_setup();
 
+	/*
+	 * check if there is an early userspace init, if yes
+	 * let it do all the work
+	 */
+	if (kinit_command || sys_access("/sbin/init", 0) == 0)
+		execute_command = kinit_command ? kinit_command : 0;
+	else
 	prepare_namespace();
 
 	/*
--- diff/ipc/Makefile	2002-12-16 09:26:07.000000000 +0000
+++ source/ipc/Makefile	2004-02-23 13:56:48.000000000 +0000
@@ -4,4 +4,5 @@
 
 obj-y   := util.o
 
+obj-$(CONFIG_SYSVIPC_COMPAT) += compat.o
 obj-$(CONFIG_SYSVIPC) += msg.o sem.o shm.o
--- diff/ipc/sem.c	2004-01-19 10:22:59.000000000 +0000
+++ source/ipc/sem.c	2004-02-23 13:56:48.000000000 +0000
@@ -1011,11 +1011,6 @@ out:
 	return un;
 }
 
-asmlinkage long sys_semop (int semid, struct sembuf __user *tsops, unsigned nsops)
-{
-	return sys_semtimedop(semid, tsops, nsops, NULL);
-}
-
 asmlinkage long sys_semtimedop(int semid, struct sembuf __user *tsops,
 			unsigned nsops, const struct timespec __user *timeout)
 {
@@ -1181,6 +1176,11 @@ out_free:
 	return error;
 }
 
+asmlinkage long sys_semop (int semid, struct sembuf __user *tsops, unsigned nsops)
+{
+	return sys_semtimedop(semid, tsops, nsops, NULL);
+}
+
 /* If CLONE_SYSVSEM is set, establish sharing of SEM_UNDO state between
  * parent and child tasks.
  *
--- diff/ipc/shm.c	2003-10-09 09:47:17.000000000 +0100
+++ source/ipc/shm.c	2004-02-23 13:56:48.000000000 +0000
@@ -635,7 +635,7 @@ out:
  * "raddr" thing points to kernel space, and there has to be a wrapper around
  * this.
  */
-long sys_shmat(int shmid, char __user *shmaddr, int shmflg, ulong *raddr)
+asmlinkage long sys_shmat(int shmid, char __user *shmaddr, int shmflg, ulong *raddr)
 {
 	struct shmid_kernel *shp;
 	unsigned long addr;
--- diff/ipc/util.c	2004-02-18 08:54:13.000000000 +0000
+++ source/ipc/util.c	2004-02-23 13:56:48.000000000 +0000
@@ -547,67 +547,4 @@ void exit_sem(struct task_struct *tsk)
 	return;
 }
 
-asmlinkage long sys_semget (key_t key, int nsems, int semflg)
-{
-	return -ENOSYS;
-}
-
-asmlinkage long sys_semop (int semid, struct sembuf *sops, unsigned nsops)
-{
-	return -ENOSYS;
-}
-
-asmlinkage long sys_semtimedop(int semid, struct sembuf *sops, unsigned nsops,
-				const struct timespec *timeout)
-{
-	return -ENOSYS;
-}
-
-
-asmlinkage long sys_semctl (int semid, int semnum, int cmd, union semun arg)
-{
-	return -ENOSYS;
-}
-
-asmlinkage long sys_msgget (key_t key, int msgflg)
-{
-	return -ENOSYS;
-}
-
-asmlinkage long sys_msgsnd (int msqid, struct msgbuf *msgp, size_t msgsz, int msgflg)
-{
-	return -ENOSYS;
-}
-
-asmlinkage long sys_msgrcv (int msqid, struct msgbuf *msgp, size_t msgsz, long msgtyp,
-		       int msgflg)
-{
-	return -ENOSYS;
-}
-
-asmlinkage long sys_msgctl (int msqid, int cmd, struct msqid_ds *buf)
-{
-	return -ENOSYS;
-}
-
-asmlinkage long sys_shmget (key_t key, size_t size, int shmflag)
-{
-	return -ENOSYS;
-}
-
-asmlinkage long sys_shmat (int shmid, char *shmaddr, int shmflg, ulong *addr)
-{
-	return -ENOSYS;
-}
-
-asmlinkage long sys_shmdt (char *shmaddr)
-{
-	return -ENOSYS;
-}
-
-asmlinkage long sys_shmctl (int shmid, int cmd, struct shmid_ds *buf)
-{
-	return -ENOSYS;
-}
-
 #endif /* CONFIG_SYSVIPC */
--- diff/kernel/Makefile	2003-10-09 09:47:34.000000000 +0100
+++ source/kernel/Makefile	2004-02-23 13:56:48.000000000 +0000
@@ -6,19 +6,22 @@ obj-y     = sched.o fork.o exec_domain.o
 	    exit.o itimer.o time.o softirq.o resource.o \
 	    sysctl.o capability.o ptrace.o timer.o user.o \
 	    signal.o sys.o kmod.o workqueue.o pid.o \
-	    rcupdate.o intermodule.o extable.o params.o posix-timers.o
+	    rcupdate.o intermodule.o extable.o params.o posix-timers.o \
+	    kthread.o
 
 obj-$(CONFIG_FUTEX) += futex.o
 obj-$(CONFIG_GENERIC_ISA_DMA) += dma.o
 obj-$(CONFIG_SMP) += cpu.o
+obj-$(CONFIG_LOCKMETER) += lockmeter.o
 obj-$(CONFIG_UID16) += uid16.o
 obj-$(CONFIG_MODULES) += module.o
 obj-$(CONFIG_KALLSYMS) += kallsyms.o
 obj-$(CONFIG_PM) += power/
 obj-$(CONFIG_BSD_PROCESS_ACCT) += acct.o
-obj-$(CONFIG_COMPAT) += compat.o
+obj-$(CONFIG_COMPAT) += compat.o compat_signal.o
 obj-$(CONFIG_IKCONFIG) += configs.o
 obj-$(CONFIG_IKCONFIG_PROC) += configs.o
+obj-$(CONFIG_STOP_MACHINE) += stop_machine.o
 
 ifneq ($(CONFIG_IA64),y)
 # According to Alan Modra <alan@linuxcare.com.au>, the -fno-omit-frame-pointer is
--- diff/kernel/compat.c	2004-01-19 10:22:59.000000000 +0000
+++ source/kernel/compat.c	2004-02-23 13:56:48.000000000 +0000
@@ -18,6 +18,7 @@
 #include <linux/signal.h>
 #include <linux/sched.h>	/* for MAX_SCHEDULE_TIMEOUT */
 #include <linux/futex.h>	/* for FUTEX_WAIT */
+#include <linux/syscalls.h>
 #include <linux/unistd.h>
 
 #include <asm/uaccess.h>
@@ -172,8 +173,6 @@ asmlinkage long compat_sys_times(struct 
  * types that can be passed to put_user()/get_user().
  */
 
-extern asmlinkage long sys_sigpending(old_sigset_t *);
-
 asmlinkage long compat_sys_sigpending(compat_old_sigset_t *set)
 {
 	old_sigset_t s;
@@ -188,8 +187,6 @@ asmlinkage long compat_sys_sigpending(co
 	return ret;
 }
 
-extern asmlinkage long sys_sigprocmask(int, old_sigset_t *, old_sigset_t *);
-
 asmlinkage long compat_sys_sigprocmask(int how, compat_old_sigset_t *set,
 		compat_old_sigset_t *oset)
 {
@@ -230,8 +227,6 @@ asmlinkage long compat_sys_futex(u32 *ua
 }
 #endif
 
-asmlinkage long sys_setrlimit(unsigned int resource, struct rlimit *rlim);
-
 asmlinkage long compat_sys_setrlimit(unsigned int resource, struct compat_rlimit *rlim)
 {
 	struct rlimit r;
@@ -257,7 +252,6 @@ asmlinkage long compat_sys_setrlimit(uns
 }
 
 #ifdef COMPAT_RLIM_OLD_INFINITY
-asmlinkage long sys_old_getrlimit(unsigned int resource, struct rlimit *rlim);
 
 asmlinkage long compat_sys_old_getrlimit(unsigned int resource, struct compat_rlimit *rlim)
 {
@@ -282,9 +276,8 @@ asmlinkage long compat_sys_old_getrlimit
 	}
 	return ret;
 }
-#endif
 
-asmlinkage long sys_getrlimit (unsigned int resource, struct rlimit *rlim);
+#endif
 
 asmlinkage long compat_sys_getrlimit (unsigned int resource, struct compat_rlimit *rlim)
 {
@@ -334,8 +327,6 @@ static long put_compat_rusage (struct co
 	return 0;
 }
 
-asmlinkage long sys_getrusage(int who, struct rusage *ru);
-
 asmlinkage long compat_sys_getrusage(int who, struct compat_rusage *ru)
 {
 	struct rusage r;
@@ -381,9 +372,6 @@ compat_sys_wait4(compat_pid_t pid, compa
 	}
 }
 
-extern asmlinkage long sys_sched_setaffinity(pid_t pid, unsigned int len,
-					    unsigned long *user_mask_ptr);
-
 asmlinkage long compat_sys_sched_setaffinity(compat_pid_t pid, 
 					     unsigned int len,
 					     compat_ulong_t *user_mask_ptr)
@@ -405,9 +393,6 @@ asmlinkage long compat_sys_sched_setaffi
 	return ret;
 }
 
-extern asmlinkage long sys_sched_getaffinity(pid_t pid, unsigned int len,
-					    unsigned long *user_mask_ptr);
-
 asmlinkage int compat_sys_sched_getaffinity(compat_pid_t pid, unsigned int len,
 					    compat_ulong_t *user_mask_ptr)
 {
@@ -449,12 +434,6 @@ static int put_compat_itimerspec(struct 
 	return 0;
 } 
 
-extern asmlinkage long sys_timer_settime(timer_t timer_id, int flags,
-				  struct itimerspec __user *new_setting,
-				 struct itimerspec __user *old_setting);
-extern asmlinkage long sys_timer_gettime(timer_t timer_id, 
-					 struct itimerspec __user *setting);
-
 long compat_timer_settime(timer_t timer_id, int flags, 
 			  struct compat_itimerspec *new, 
 			  struct compat_itimerspec *old)
@@ -462,6 +441,9 @@ long compat_timer_settime(timer_t timer_
 	long err;
 	mm_segment_t oldfs;
 	struct itimerspec newts, oldts;
+
+	if (!new)
+		return -EINVAL;
 	if (get_compat_itimerspec(&newts, new))
 		return -EFAULT;	
 	oldfs = get_fs();
@@ -487,9 +469,6 @@ long compat_timer_gettime(timer_t timer_
 	return err;
 } 
 
-extern asmlinkage long
-sys_clock_settime(clockid_t which_clock, struct timespec __user *tp);
-
 long compat_clock_settime(clockid_t which_clock,  struct compat_timespec *tp)
 {
 	long err;
@@ -504,9 +483,6 @@ long compat_clock_settime(clockid_t whic
 	return err;
 } 
 
-extern asmlinkage long
-sys_clock_gettime(clockid_t which_clock, struct timespec __user *tp);
-
 long compat_clock_gettime(clockid_t which_clock,  struct compat_timespec *tp)
 {
 	long err;
@@ -521,9 +497,6 @@ long compat_clock_gettime(clockid_t whic
 	return err;
 } 
 
-extern asmlinkage long
-sys_clock_getres(clockid_t which_clock, struct timespec __user *tp);
-
 long compat_clock_getres(clockid_t which_clock,  struct compat_timespec *tp)
 {
 	long err;
@@ -538,11 +511,6 @@ long compat_clock_getres(clockid_t which
 	return err;
 } 
 
-extern asmlinkage long
-sys_clock_nanosleep(clockid_t which_clock, int flags,
-		     struct timespec __user *rqtp,
-		    struct timespec __user *rmtp);
-
 long compat_clock_nanosleep(clockid_t which_clock, int flags,
 			    struct compat_timespec __user *rqtp,
 			    struct compat_timespec __user *rmtp)
--- diff/kernel/cpu.c	2004-02-18 08:54:13.000000000 +0000
+++ source/kernel/cpu.c	2004-02-23 13:56:48.000000000 +0000
@@ -1,14 +1,19 @@
 /* CPU control.
- * (C) 2001 Rusty Russell
+ * (C) 2001, 2002, 2003, 2004 Rusty Russell
+ *
  * This code is licenced under the GPL.
  */
 #include <linux/proc_fs.h>
 #include <linux/smp.h>
 #include <linux/init.h>
-#include <linux/notifier.h>
 #include <linux/sched.h>
 #include <linux/unistd.h>
+#include <linux/kmod.h>		/* for hotplug_path */
 #include <linux/cpu.h>
+#include <linux/module.h>
+#include <linux/notifier.h>
+#include <linux/kthread.h>
+#include <linux/stop_machine.h>
 #include <asm/semaphore.h>
 
 /* This protects CPUs going up and down... */
@@ -19,20 +24,149 @@ static struct notifier_block *cpu_chain;
 /* Need to know about CPUs going up/down? */
 int register_cpu_notifier(struct notifier_block *nb)
 {
-	return notifier_chain_register(&cpu_chain, nb);
+	int ret;
+
+	if ((ret = down_interruptible(&cpucontrol)) != 0)
+		return ret;
+	ret = notifier_chain_register(&cpu_chain, nb);
+	up(&cpucontrol);
+	return ret;
 }
+EXPORT_SYMBOL(register_cpu_notifier);
 
 void unregister_cpu_notifier(struct notifier_block *nb)
 {
-	notifier_chain_unregister(&cpu_chain,nb);
+	down(&cpucontrol);
+	notifier_chain_unregister(&cpu_chain, nb);
+	up(&cpucontrol);
+}
+EXPORT_SYMBOL(unregister_cpu_notifier);
+
+#ifdef CONFIG_HOTPLUG_CPU
+static inline void check_for_tasks(int cpu, struct task_struct *k)
+{
+	struct task_struct *p;
+
+	write_lock_irq(&tasklist_lock);
+	for_each_process(p) {
+		if (task_cpu(p) == cpu && p != k)
+			printk(KERN_WARNING "Task %s is on cpu %d\n",
+				p->comm, cpu);
+	}
+	write_unlock_irq(&tasklist_lock);
+}
+
+/* Notify userspace when a cpu event occurs, by running '/sbin/hotplug
+ * cpu' with certain environment variables set.  */
+static int cpu_run_sbin_hotplug(unsigned int cpu, const char *action)
+{
+	char *argv[3], *envp[5], cpu_str[12], action_str[32];
+	int i;
+
+	sprintf(cpu_str, "CPU=%d", cpu);
+	sprintf(action_str, "ACTION=%s", action);
+	/* FIXME: Add DEVPATH. --RR */
+
+	i = 0;
+	argv[i++] = hotplug_path;
+	argv[i++] = "cpu";
+	argv[i] = NULL;
+
+	i = 0;
+	/* minimal command environment */
+	envp [i++] = "HOME=/";
+	envp [i++] = "PATH=/sbin:/bin:/usr/sbin:/usr/bin";
+	envp [i++] = cpu_str;
+	envp [i++] = action_str;
+	envp [i] = NULL;
+
+	return call_usermodehelper(argv[0], argv, envp, 0);
+}
+
+/* Take this CPU down. */
+static int take_cpu_down(void *unused)
+{
+	int err;
+
+	/* Take offline: makes arch_cpu_down somewhat easier. */
+	cpu_clear(smp_processor_id(), cpu_online_map);
+
+	/* Ensure this CPU doesn't handle any more interrupts. */
+	err = __cpu_disable();
+	if (err < 0)
+		cpu_set(smp_processor_id(), cpu_online_map);
+	else
+		/* Everyone else gets kicked off. */
+		migrate_all_tasks();
+
+	return err;
+}
+
+int cpu_down(unsigned int cpu)
+{
+	int err;
+	struct task_struct *p;
+
+	if ((err = lock_cpu_hotplug_interruptible()) != 0)
+		return err;
+
+	if (num_online_cpus() == 1) {
+		err = -EBUSY;
+		goto out;
+	}
+
+	if (!cpu_online(cpu)) {
+		err = -EINVAL;
+		goto out;
+	}
+
+	p = __stop_machine_run(take_cpu_down, NULL, cpu);
+	if (IS_ERR(p)) {
+		err = PTR_ERR(p);
+		goto out;
+	}
+
+	if (cpu_online(cpu))
+		goto out_thread;
+
+	check_for_tasks(cpu, p);
+
+	/* Wait for it to sleep (leaving idle task). */
+	while (!idle_cpu(cpu))
+		yield();
+
+	/* This actually kills the CPU. */
+	__cpu_die(cpu);
+
+	/* Move it here so it can run. */
+	kthread_bind(p, smp_processor_id());
+
+	/* CPU is completely dead: tell everyone.  Too late to complain. */
+	if (notifier_call_chain(&cpu_chain, CPU_DEAD, (void *)(long)cpu)
+	    == NOTIFY_BAD)
+		BUG();
+
+	cpu_run_sbin_hotplug(cpu, "offline");
+
+out_thread:
+	err = kthread_stop(p);
+out:
+	unlock_cpu_hotplug();
+	return err;
+}
+#else
+static inline int cpu_run_sbin_hotplug(unsigned int cpu, const char *action)
+{
+	return 0;
 }
+#endif /*CONFIG_HOTPLUG_CPU*/
 
 int __devinit cpu_up(unsigned int cpu)
 {
 	int ret;
 	void *hcpu = (void *)(long)cpu;
 
-	if ((ret = down_interruptible(&cpucontrol)) != 0)
+	if ((ret = lock_cpu_hotplug_interruptible()) != 0)
 		return ret;
 
 	if (cpu_online(cpu)) {
@@ -61,6 +195,6 @@ out_notify:
 	if (ret != 0)
 		notifier_call_chain(&cpu_chain, CPU_UP_CANCELED, hcpu);
 out:
-	up(&cpucontrol);
+	unlock_cpu_hotplug();
 	return ret;
 }
--- diff/kernel/fork.c	2004-02-18 08:54:13.000000000 +0000
+++ source/kernel/fork.c	2004-02-23 13:56:48.000000000 +0000
@@ -26,6 +26,7 @@
 #include <linux/mman.h>
 #include <linux/fs.h>
 #include <linux/security.h>
+#include <linux/syscalls.h>
 #include <linux/jiffies.h>
 #include <linux/futex.h>
 #include <linux/ptrace.h>
@@ -86,6 +87,7 @@ void __put_task_struct(struct task_struc
 
 	security_task_free(tsk);
 	free_uid(tsk->user);
+	put_group_info(tsk->group_info);
 	free_task(tsk);
 }
 
@@ -273,7 +275,7 @@ static inline int dup_mmap(struct mm_str
 	mm->mmap_cache = NULL;
 	mm->free_area_cache = TASK_UNMAPPED_BASE;
 	mm->map_count = 0;
-	mm->rss = 0;
+	zero_rss(mm);
 	cpus_clear(mm->cpu_vm_mask);
 	pprev = &mm->mmap;
 
@@ -878,6 +880,7 @@ struct task_struct *copy_process(unsigne
 
 	atomic_inc(&p->user->__count);
 	atomic_inc(&p->user->processes);
+	get_group_info(p->group_info);
 
 	/*
 	 * If multiple threads are within copy_process(), then this check
@@ -1084,6 +1087,7 @@ bad_fork_cleanup:
 bad_fork_cleanup_put_domain:
 	module_put(p->thread_info->exec_domain->module);
 bad_fork_cleanup_count:
+	put_group_info(p->group_info);
 	atomic_dec(&p->user->processes);
 	free_uid(p->user);
 bad_fork_free:
--- diff/kernel/futex.c	2004-02-18 08:54:13.000000000 +0000
+++ source/kernel/futex.c	2004-02-23 13:56:48.000000000 +0000
@@ -269,7 +269,11 @@ static void wake_futex(struct futex_q *q
 	 * The lock in wake_up_all() is a crucial memory barrier after the
 	 * list_del_init() and also before assigning to q->lock_ptr.
 	 */
+
+	current->flags |= PF_FUTEX_DEBUG;
 	wake_up_all(&q->waiters);
+	current->flags &= ~PF_FUTEX_DEBUG;
+
 	/*
 	 * The waiting task can free the futex_q as soon as this is written,
 	 * without taking any locks.  This must come last.
@@ -490,8 +494,11 @@ static int futex_wait(unsigned long uadd
 	 * !list_empty() is safe here without any lock.
 	 * q.lock_ptr != 0 is not safe, because of ordering against wakeup.
 	 */
-	if (likely(!list_empty(&q.list)))
+	if (likely(!list_empty(&q.list))) {
+		current->flags |= PF_FUTEX_DEBUG;
 		time = schedule_timeout(time);
+		current->flags &= ~PF_FUTEX_DEBUG;
+	}
 	__set_current_state(TASK_RUNNING);
 
 	/*
@@ -505,7 +512,11 @@ static int futex_wait(unsigned long uadd
 	if (time == 0)
 		return -ETIMEDOUT;
 	/* A spurious wakeup should never happen. */
-	WARN_ON(!signal_pending(current));
+	if (!signal_pending(current)) {
+		printk("futex_wait woken: %lu %i %lu\n",
+		       uaddr, val, time);
+		WARN_ON(1);
+	}
 	return -EINTR;
 
  out_unqueue:
--- diff/kernel/kmod.c	2004-02-18 08:54:13.000000000 +0000
+++ source/kernel/kmod.c	2004-02-23 13:56:48.000000000 +0000
@@ -23,6 +23,7 @@
 #include <linux/config.h>
 #include <linux/module.h>
 #include <linux/sched.h>
+#include <linux/syscalls.h>
 #include <linux/unistd.h>
 #include <linux/kmod.h>
 #include <linux/smp_lock.h>
@@ -149,6 +150,7 @@ static int ____call_usermodehelper(void 
 {
 	struct subprocess_info *sub_info = data;
 	int retval;
+	cpumask_t mask = CPU_MASK_ALL;
 
 	/* Unblock all signals. */
 	flush_signals(current);
@@ -158,6 +160,9 @@ static int ____call_usermodehelper(void 
 	recalc_sigpending();
 	spin_unlock_irq(&current->sighand->siglock);
 
+	/* We can run anywhere, unlike our parent keventd(). */
+	set_cpus_allowed(current, mask);
+
 	retval = -EPERM;
 	if (current->fs->root)
 		retval = execve(sub_info->path, sub_info->argv,sub_info->envp);
--- diff/kernel/module.c	2004-02-18 08:54:13.000000000 +0000
+++ source/kernel/module.c	2004-02-23 13:56:48.000000000 +0000
@@ -24,6 +24,7 @@
 #include <linux/vmalloc.h>
 #include <linux/elf.h>
 #include <linux/seq_file.h>
+#include <linux/syscalls.h>
 #include <linux/fcntl.h>
 #include <linux/rcupdate.h>
 #include <linux/cpu.h>
@@ -32,6 +33,7 @@
 #include <linux/err.h>
 #include <linux/vermagic.h>
 #include <linux/notifier.h>
+#include <linux/stop_machine.h>
 #include <asm/uaccess.h>
 #include <asm/semaphore.h>
 #include <asm/pgalloc.h>
@@ -457,157 +459,51 @@ static void module_unload_free(struct mo
 	}
 }
 
-#ifdef CONFIG_SMP
-/* Thread to stop each CPU in user context. */
-enum stopref_state {
-	STOPREF_WAIT,
-	STOPREF_PREPARE,
-	STOPREF_DISABLE_IRQ,
-	STOPREF_EXIT,
-};
-
-static enum stopref_state stopref_state;
-static unsigned int stopref_num_threads;
-static atomic_t stopref_thread_ack;
-
-static int stopref(void *cpu)
+#ifdef CONFIG_MODULE_FORCE_UNLOAD
+static inline int try_force(unsigned int flags)
 {
-	int irqs_disabled = 0;
-	int prepared = 0;
-
-	sprintf(current->comm, "kmodule%lu\n", (unsigned long)cpu);
-
-	/* Highest priority we can manage, and move to right CPU. */
-#if 0 /* FIXME */
-	struct sched_param param = { .sched_priority = MAX_RT_PRIO-1 };
-	setscheduler(current->pid, SCHED_FIFO, &param);
-#endif
-	set_cpus_allowed(current, cpumask_of_cpu((int)(long)cpu));
-
-	/* Ack: we are alive */
-	mb(); /* Theoretically the ack = 0 might not be on this CPU yet. */
-	atomic_inc(&stopref_thread_ack);
-
-	/* Simple state machine */
-	while (stopref_state != STOPREF_EXIT) {
-		if (stopref_state == STOPREF_DISABLE_IRQ && !irqs_disabled) {
-			local_irq_disable();
-			irqs_disabled = 1;
-			/* Ack: irqs disabled. */
-			mb(); /* Must read state first. */
-			atomic_inc(&stopref_thread_ack);
-		} else if (stopref_state == STOPREF_PREPARE && !prepared) {
-			/* Everyone is in place, hold CPU. */
-			preempt_disable();
-			prepared = 1;
-			mb(); /* Must read state first. */
-			atomic_inc(&stopref_thread_ack);
-		}
-		if (irqs_disabled || prepared)
-			cpu_relax();
-		else
-			yield();
-	}
-
-	/* Ack: we are exiting. */
-	mb(); /* Must read state first. */
-	atomic_inc(&stopref_thread_ack);
-
-	if (irqs_disabled)
-		local_irq_enable();
-	if (prepared)
-		preempt_enable();
-
-	return 0;
+	int ret = (flags & O_TRUNC);
+	if (ret)
+		tainted |= TAINT_FORCED_MODULE;
+	return ret;
 }
-
-/* Change the thread state */
-static void stopref_set_state(enum stopref_state state, int sleep)
+#else
+static inline int try_force(unsigned int flags)
 {
-	atomic_set(&stopref_thread_ack, 0);
-	wmb();
-	stopref_state = state;
-	while (atomic_read(&stopref_thread_ack) != stopref_num_threads) {
-		if (sleep)
-			yield();
-		else
-			cpu_relax();
-	}
+	return 0;
 }
+#endif /* CONFIG_MODULE_FORCE_UNLOAD */
 
-/* Stop the machine.  Disables irqs. */
-static int stop_refcounts(void)
+struct stopref
 {
-	unsigned int i, cpu;
-	cpumask_t old_allowed;
-	int ret = 0;
-
-	/* One thread per cpu.  We'll do our own. */
-	cpu = smp_processor_id();
-
-	/* FIXME: racy with set_cpus_allowed. */
-	old_allowed = current->cpus_allowed;
-	set_cpus_allowed(current, cpumask_of_cpu(cpu));
-
-	atomic_set(&stopref_thread_ack, 0);
-	stopref_num_threads = 0;
-	stopref_state = STOPREF_WAIT;
-
-	/* No CPUs can come up or down during this. */
-	lock_cpu_hotplug();
-
-	for (i = 0; i < NR_CPUS; i++) {
-		if (i == cpu || !cpu_online(i))
-			continue;
-		ret = kernel_thread(stopref, (void *)(long)i, CLONE_KERNEL);
-		if (ret < 0)
-			break;
-		stopref_num_threads++;
-	}
+	struct module *mod;
+	int flags;
+	int *forced;
+};
 
-	/* Wait for them all to come to life. */
-	while (atomic_read(&stopref_thread_ack) != stopref_num_threads)
-		yield();
+/* Whole machine is stopped with interrupts off when this runs. */
+static inline int __try_stop_module(void *_sref)
+{
+	struct stopref *sref = _sref;
 
-	/* If some failed, kill them all. */
-	if (ret < 0) {
-		stopref_set_state(STOPREF_EXIT, 1);
-		unlock_cpu_hotplug();
-		return ret;
+	/* If it's not unused, quit unless we are told to block. */
+	if ((sref->flags & O_NONBLOCK) && module_refcount(sref->mod) != 0) {
+		if (!(*sref->forced = try_force(sref->flags)))
+			return -EWOULDBLOCK;
 	}
 
-	/* Don't schedule us away at this point, please. */
-	preempt_disable();
-
-	/* Now they are all scheduled, make them hold the CPUs, ready. */
-	stopref_set_state(STOPREF_PREPARE, 0);
-
-	/* Make them disable irqs. */
-	stopref_set_state(STOPREF_DISABLE_IRQ, 0);
-
-	local_irq_disable();
+	/* Mark it as dying. */
+	sref->mod->waiter = current;
+	sref->mod->state = MODULE_STATE_GOING;
 	return 0;
 }
 
-/* Restart the machine.  Re-enables irqs. */
-static void restart_refcounts(void)
-{
-	stopref_set_state(STOPREF_EXIT, 0);
-	local_irq_enable();
-	preempt_enable();
-	unlock_cpu_hotplug();
-}
-#else /* ...!SMP */
-static inline int stop_refcounts(void)
-{
-	local_irq_disable();
-	return 0;
-}
-static inline void restart_refcounts(void)
+static int try_stop_module(struct module *mod, int flags, int *forced)
 {
-	local_irq_enable();
+	struct stopref sref = { mod, flags, forced };
+
+	return stop_machine_run(__try_stop_module, &sref, NR_CPUS);
 }
-#endif
 
 unsigned int module_refcount(struct module *mod)
 {
@@ -622,21 +518,6 @@ EXPORT_SYMBOL(module_refcount);
 /* This exists whether we can unload or not */
 static void free_module(struct module *mod);
 
-#ifdef CONFIG_MODULE_FORCE_UNLOAD
-static inline int try_force(unsigned int flags)
-{
-	int ret = (flags & O_TRUNC);
-	if (ret)
-		tainted |= TAINT_FORCED_MODULE;
-	return ret;
-}
-#else
-static inline int try_force(unsigned int flags)
-{
-	return 0;
-}
-#endif /* CONFIG_MODULE_FORCE_UNLOAD */
-
 /* Stub function for modules which don't have an exitfn */
 void cleanup_module(void)
 {
@@ -706,33 +587,18 @@ sys_delete_module(const char __user *nam
 			goto out;
 		}
 	}
-	/* Stop the machine so refcounts can't move: irqs disabled. */
-	DEBUGP("Stopping refcounts...\n");
-	ret = stop_refcounts();
-	if (ret != 0)
-		goto out;
-
-	/* If it's not unused, quit unless we are told to block. */
-	if ((flags & O_NONBLOCK) && module_refcount(mod) != 0) {
-		forced = try_force(flags);
-		if (!forced) {
-			ret = -EWOULDBLOCK;
-			restart_refcounts();
-			goto out;
-		}
-	}
 
-	/* Mark it as dying. */
-	mod->waiter = current;
-	mod->state = MODULE_STATE_GOING;
-	restart_refcounts();
+	/* Stop the machine so refcounts can't move and disable module. */
+	ret = try_stop_module(mod, flags, &forced);
 
 	/* Never wait if forced. */
 	if (!forced && module_refcount(mod) != 0)
 		wait_for_zero_refcount(mod);
 
 	/* Final destruction now noone is using it. */
+	up(&module_mutex);
 	mod->exit();
+	down(&module_mutex);
 	free_module(mod);
 
  out:
--- diff/kernel/panic.c	2003-10-09 09:47:34.000000000 +0100
+++ source/kernel/panic.c	2004-02-23 13:56:48.000000000 +0000
@@ -16,11 +16,10 @@
 #include <linux/notifier.h>
 #include <linux/init.h>
 #include <linux/sysrq.h>
+#include <linux/syscalls.h>
 #include <linux/interrupt.h>
 #include <linux/nmi.h>
 
-asmlinkage void sys_sync(void);	/* it's really int */
-
 int panic_timeout;
 int panic_on_oops;
 int tainted;
--- diff/kernel/pid.c	2003-10-27 09:20:39.000000000 +0000
+++ source/kernel/pid.c	2004-02-23 13:56:48.000000000 +0000
@@ -122,6 +122,8 @@ return_pid:
 	}
 	
 	if (!offset || !atomic_read(&map->nr_free)) {
+		if (!offset)
+			map--;
 next_map:
 		map = next_free_map(map, &max_steps);
 		if (!map)
@@ -268,6 +270,9 @@ void switch_exec_pids(task_t *leader, ta
  * machine.  From a minimum of 16 slots up to 4096 slots at one gigabyte or
  * more.
  */
+#ifdef CONFIG_KGDB
+int kgdb_pid_init_done; /* so we don't call prior to... */
+#endif
 void __init pidhash_init(void)
 {
 	int i, j, pidhash_size;
@@ -289,6 +294,9 @@ void __init pidhash_init(void)
 		for (j = 0; j < pidhash_size; j++)
 			INIT_LIST_HEAD(&pid_hash[i][j]);
 	}
+#ifdef CONFIG_KGDB
+	kgdb_pid_init_done++;
+#endif
 }
 
 void __init pidmap_init(void)
--- diff/kernel/posix-timers.c	2004-02-18 08:54:13.000000000 +0000
+++ source/kernel/posix-timers.c	2004-02-23 13:56:48.000000000 +0000
@@ -426,7 +426,7 @@ sys_timer_create(clockid_t which_clock,
 
 	spin_lock_init(&new_timer->it_lock);
 	do {
-		if (unlikely(!idr_pre_get(&posix_timers_id))) {
+		if (unlikely(!idr_pre_get(&posix_timers_id, GFP_KERNEL))) {
 			error = -EAGAIN;
 			new_timer->it_id = (timer_t)-1;
 			goto out;
--- diff/kernel/power/disk.c	2003-10-27 09:20:39.000000000 +0000
+++ source/kernel/power/disk.c	2004-02-23 13:56:48.000000000 +0000
@@ -12,6 +12,7 @@
 
 
 #include <linux/suspend.h>
+#include <linux/syscalls.h>
 #include <linux/reboot.h>
 #include <linux/string.h>
 #include <linux/delay.h>
@@ -28,8 +29,6 @@ extern int pmdisk_read(void);
 extern int pmdisk_restore(void);
 extern int pmdisk_free(void);
 
-extern long sys_sync(void);
-
 
 /**
  *	power_down - Shut machine down for hibernate.
--- diff/kernel/power/pmdisk.c	2004-02-09 10:36:12.000000000 +0000
+++ source/kernel/power/pmdisk.c	2004-02-23 13:56:48.000000000 +0000
@@ -1121,11 +1121,11 @@ int __init pmdisk_read(void)
 	resume_device = name_to_dev_t(resume_file);
 	pr_debug("pmdisk: Resume From Partition: %s\n", resume_file);
 
-	resume_bdev = open_by_devnum(resume_device, FMODE_READ, BDEV_RAW);
+	resume_bdev = open_by_devnum(resume_device, FMODE_READ);
 	if (!IS_ERR(resume_bdev)) {
 		set_blocksize(resume_bdev, PAGE_SIZE);
 		error = read_suspend_image();
-		blkdev_put(resume_bdev, BDEV_RAW);
+		blkdev_put(resume_bdev);
 	} else
 		error = PTR_ERR(resume_bdev);
 
--- diff/kernel/power/swsusp.c	2004-02-18 08:54:13.000000000 +0000
+++ source/kernel/power/swsusp.c	2004-02-23 13:56:48.000000000 +0000
@@ -59,6 +59,7 @@
 #include <linux/buffer_head.h>
 #include <linux/swapops.h>
 #include <linux/bootmem.h>
+#include <linux/syscalls.h>
 #include <linux/console.h>
 
 #include <asm/uaccess.h>
@@ -68,8 +69,6 @@
 
 #include "power.h"
 
-extern long sys_sync(void);
-
 unsigned char software_suspend_enabled = 0;
 
 extern void do_magic(int resume);
@@ -997,13 +996,13 @@ static int read_suspend_image(const char
 		struct block_device *bdev;
 		printk("Resuming from device %s\n",
 				__bdevname(resume_device, b));
-		bdev = open_by_devnum(resume_device, FMODE_READ, BDEV_RAW);
+		bdev = open_by_devnum(resume_device, FMODE_READ);
 		if (IS_ERR(bdev)) {
 			error = PTR_ERR(bdev);
 		} else {
 			set_blocksize(bdev, PAGE_SIZE);
 			error = __read_suspend_image(bdev, cur, noresume);
-			blkdev_put(bdev, BDEV_RAW);
+			blkdev_put(bdev);
 		}
 	} else error = -ENOMEM;
 
--- diff/kernel/printk.c	2004-02-18 08:54:13.000000000 +0000
+++ source/kernel/printk.c	2004-02-23 13:56:48.000000000 +0000
@@ -501,7 +501,7 @@ asmlinkage int printk(const char *fmt, .
 
 	/* Emit the output into the temporary buffer */
 	va_start(args, fmt);
-	printed_len = vsnprintf(printk_buf, sizeof(printk_buf), fmt, args);
+	printed_len = vscnprintf(printk_buf, sizeof(printk_buf), fmt, args);
 	va_end(args);
 
 	/*
@@ -522,7 +522,7 @@ asmlinkage int printk(const char *fmt, .
 			log_level_unknown = 1;
 	}
 
-	if (!cpu_online(smp_processor_id())) {
+	if (!cpu_online(smp_processor_id()) && !system_running) {
 		/*
 		 * Some console drivers may assume that per-cpu resources have
 		 * been allocated.  So don't allow them to be called by this
--- diff/kernel/rcupdate.c	2003-10-09 09:47:34.000000000 +0100
+++ source/kernel/rcupdate.c	2004-02-23 13:56:48.000000000 +0000
@@ -110,6 +110,7 @@ static void rcu_start_batch(long newbatc
 	    !cpus_empty(rcu_ctrlblk.rcu_cpu_mask)) {
 		return;
 	}
+	/* Can't change, since spin lock held. */
 	rcu_ctrlblk.rcu_cpu_mask = cpu_online_map;
 }
 
@@ -154,6 +155,60 @@ out_unlock:
 }
 
 
+#ifdef CONFIG_HOTPLUG_CPU
+
+/* warning! helper for rcu_offline_cpu. do not use elsewhere without reviewing
+ * locking requirements, the list it's pulling from has to belong to a cpu
+ * which is dead and hence not processing interrupts.
+ */
+static void rcu_move_batch(struct list_head *list)
+{
+	struct list_head *entry;
+	int cpu = smp_processor_id();
+
+	local_irq_disable();
+	while (!list_empty(list)) {
+		entry = list->next;
+		list_del(entry);
+		list_add_tail(entry, &RCU_nxtlist(cpu));
+	}
+	local_irq_enable();
+}
+
+static void rcu_offline_cpu(int cpu)
+{
+	/* if the cpu going offline owns the grace period
+	 * we can block indefinitely waiting for it, so flush
+	 * it here
+	 */
+	spin_lock_irq(&rcu_ctrlblk.mutex);
+	if (cpus_empty(rcu_ctrlblk.rcu_cpu_mask))
+		goto unlock;
+
+	cpu_clear(cpu, rcu_ctrlblk.rcu_cpu_mask);
+	if (cpus_empty(rcu_ctrlblk.rcu_cpu_mask)) {
+		rcu_ctrlblk.curbatch++;
+		/* We may avoid calling start batch if
+		 * we are starting the batch only
+		 * because of the DEAD CPU (the current
+		 * CPU will start a new batch anyway for
+		 * the callbacks we will move to current CPU).
+		 * However, we will avoid this optimisation
+		 * for now.
+		 */
+		rcu_start_batch(rcu_ctrlblk.maxbatch);
+	}
+unlock:
+	spin_unlock_irq(&rcu_ctrlblk.mutex);
+
+	rcu_move_batch(&RCU_curlist(cpu));
+	rcu_move_batch(&RCU_nxtlist(cpu));
+
+	tasklet_kill_immediate(&RCU_tasklet(cpu), cpu);
+}
+
+#endif
+
 /*
  * This does the RCU processing work from tasklet context. 
  */
@@ -214,7 +269,11 @@ static int __devinit rcu_cpu_notify(stru
 	case CPU_UP_PREPARE:
 		rcu_online_cpu(cpu);
 		break;
-	/* Space reserved for CPU_OFFLINE :) */
+#ifdef CONFIG_HOTPLUG_CPU
+	case CPU_DEAD:
+		rcu_offline_cpu(cpu);
+		break;
+#endif
 	default:
 		break;
 	}
--- diff/kernel/resource.c	2004-02-18 08:54:13.000000000 +0000
+++ source/kernel/resource.c	2004-02-23 13:56:48.000000000 +0000
@@ -306,11 +306,12 @@ EXPORT_SYMBOL(allocate_resource);
  *
  * Returns 0 on success, -EBUSY if the resource can't be inserted.
  *
- * This function is equivalent of request_resource when no
- * conflict happens. If a conflict happens, and the conflicting
- * resources entirely fit within the range of the new resource,
- * then the new resource is inserted and the conflicting resources
- * become childs of the new resource. 
+ * This function is equivalent of request_resource when no conflict
+ * happens. If a conflict happens, and the conflicting resources
+ * entirely fit within the range of the new resource, then the new
+ * resource is inserted and the conflicting resources become childs of
+ * the new resource.  Otherwise the new resource becomes the child of
+ * the conflicting resource
  */
 int insert_resource(struct resource *parent, struct resource *new)
 {
@@ -318,6 +319,7 @@ int insert_resource(struct resource *par
 	struct resource *first, *next;
 
 	write_lock(&resource_lock);
+ begin:
 	first = __request_resource(parent, new);
 	if (!first)
 		goto out;
@@ -331,8 +333,10 @@ int insert_resource(struct resource *par
 			break;
 
 	/* existing resource overlaps end of new resource */
-	if (next->end > new->end)
-		goto out;
+	if (next->end > new->end) {
+		parent = next;
+		goto begin;
+	}
 
 	result = 0;
 
@@ -475,6 +479,8 @@ void __release_region(struct resource *p
 	p = &parent->child;
 	end = start + n - 1;
 
+	write_lock(&resource_lock);
+
 	for (;;) {
 		struct resource *res = *p;
 
@@ -488,11 +494,15 @@ void __release_region(struct resource *p
 			if (res->start != start || res->end != end)
 				break;
 			*p = res->sibling;
+			write_unlock(&resource_lock);
 			kfree(res);
 			return;
 		}
 		p = &res->sibling;
 	}
+
+	write_unlock(&resource_lock);
+
 	printk(KERN_WARNING "Trying to free nonexistent resource <%08lx-%08lx>\n", start, end);
 }
 
--- diff/kernel/sched.c	2004-02-18 08:54:13.000000000 +0000
+++ source/kernel/sched.c	2004-02-23 13:56:48.000000000 +0000
@@ -25,6 +25,7 @@
 #include <linux/highmem.h>
 #include <linux/smp_lock.h>
 #include <asm/mmu_context.h>
+#include <asm/tlb.h>
 #include <linux/interrupt.h>
 #include <linux/completion.h>
 #include <linux/kernel_stat.h>
@@ -37,6 +38,7 @@
 #include <linux/rcupdate.h>
 #include <linux/cpu.h>
 #include <linux/percpu.h>
+#include <linux/kthread.h>
 
 #ifdef CONFIG_NUMA
 #define cpu_to_node_mask(cpu) node_to_cpumask(cpu_to_node(cpu))
@@ -89,7 +91,6 @@
 #define MAX_SLEEP_AVG		(AVG_TIMESLICE * MAX_BONUS)
 #define STARVATION_LIMIT	(MAX_SLEEP_AVG)
 #define NS_MAX_SLEEP_AVG	(JIFFIES_TO_NS(MAX_SLEEP_AVG))
-#define NODE_THRESHOLD		125
 #define CREDIT_LIMIT		100
 
 /*
@@ -185,7 +186,7 @@ static inline unsigned int task_timeslic
 typedef struct runqueue runqueue_t;
 
 struct prio_array {
-	int nr_active;
+	unsigned int nr_active;
 	unsigned long bitmap[BITMAP_SIZE];
 	struct list_head queue[MAX_PRIO];
 };
@@ -200,23 +201,33 @@ struct prio_array {
 struct runqueue {
 	spinlock_t lock;
 	unsigned long nr_running, nr_switches, expired_timestamp,
-		      nr_uninterruptible, timestamp_last_tick;
+		      nr_uninterruptible;
+	unsigned long long timestamp_last_tick;
 	task_t *curr, *idle;
 	struct mm_struct *prev_mm;
 	prio_array_t *active, *expired, arrays[2];
-	int best_expired_prio, prev_cpu_load[NR_CPUS];
-#ifdef CONFIG_NUMA
-	atomic_t *node_nr_running;
-	int prev_node_load[MAX_NUMNODES];
+	int best_expired_prio;
+
+	atomic_t nr_iowait;
+
+#ifdef CONFIG_SMP
+	unsigned long cpu_load[NR_CPUS];
 #endif
+	/* For active balancing */
+	int active_balance;
+	int push_cpu;
+
 	task_t *migration_thread;
 	struct list_head migration_queue;
-
-	atomic_t nr_iowait;
 };
 
 static DEFINE_PER_CPU(struct runqueue, runqueues);
 
+#ifdef CONFIG_SMP
+/* Mandatory scheduling domains */
+DEFINE_PER_CPU(struct sched_domain, base_domains);
+#endif
+
 #define cpu_rq(cpu)		(&per_cpu(runqueues, (cpu)))
 #define this_rq()		(&__get_cpu_var(runqueues))
 #define task_rq(p)		cpu_rq(task_cpu(p))
@@ -231,51 +242,16 @@ static DEFINE_PER_CPU(struct runqueue, r
 # define task_running(rq, p)		((rq)->curr == (p))
 #endif
 
-#ifdef CONFIG_NUMA
-
-/*
- * Keep track of running tasks.
- */
-
-static atomic_t node_nr_running[MAX_NUMNODES] ____cacheline_maxaligned_in_smp =
-	{[0 ...MAX_NUMNODES-1] = ATOMIC_INIT(0)};
-
-static inline void nr_running_init(struct runqueue *rq)
-{
-	rq->node_nr_running = &node_nr_running[0];
-}
-
 static inline void nr_running_inc(runqueue_t *rq)
 {
-	atomic_inc(rq->node_nr_running);
 	rq->nr_running++;
 }
 
 static inline void nr_running_dec(runqueue_t *rq)
 {
-	atomic_dec(rq->node_nr_running);
 	rq->nr_running--;
 }
 
-__init void node_nr_running_init(void)
-{
-	int i;
-
-	for (i = 0; i < NR_CPUS; i++) {
-		if (cpu_possible(i))
-			cpu_rq(i)->node_nr_running =
-				&node_nr_running[cpu_to_node(i)];
-	}
-}
-
-#else /* !CONFIG_NUMA */
-
-# define nr_running_init(rq)	do { } while (0)
-# define nr_running_inc(rq)	do { (rq)->nr_running++; } while (0)
-# define nr_running_dec(rq)	do { (rq)->nr_running--; } while (0)
-
-#endif /* CONFIG_NUMA */
-
 /*
  * task_rq_lock - lock the runqueue a given task resides on and disable
  * interrupts.  Note the ordering: we can safely lookup the task_rq without
@@ -543,37 +519,30 @@ inline int task_curr(task_t *p)
 typedef struct {
 	struct list_head list;
 	task_t *task;
+	int dest_cpu;
 	struct completion done;
 } migration_req_t;
 
 /*
- * The task's runqueue lock must be held, and the new mask must be valid.
+ * The task's runqueue lock must be held.
  * Returns true if you have to wait for migration thread.
  */
-static int __set_cpus_allowed(task_t *p, cpumask_t new_mask,
-				migration_req_t *req)
+static int migrate_task(task_t *p, int dest_cpu, migration_req_t *req)
 {
 	runqueue_t *rq = task_rq(p);
 
-	p->cpus_allowed = new_mask;
-	/*
-	 * Can the task run on the task's current CPU? If not then
-	 * migrate the thread off to a proper CPU.
-	 */
-	if (cpu_isset(task_cpu(p), new_mask))
-		return 0;
-
 	/*
 	 * If the task is not on a runqueue (and not running), then
 	 * it is sufficient to simply update the task's cpu field.
 	 */
 	if (!p->array && !task_running(rq, p)) {
-		set_task_cpu(p, any_online_cpu(p->cpus_allowed));
+		set_task_cpu(p, dest_cpu);
 		return 0;
 	}
 
 	init_completion(&req->done);
 	req->task = p;
+	req->dest_cpu = dest_cpu;
 	list_add(&req->list, &rq->migration_queue);
 	return 1;
 }
@@ -634,7 +603,76 @@ void kick_process(task_t *p)
 }
 
 EXPORT_SYMBOL_GPL(kick_process);
+/*
+ * Return a low guess at the load of cpu. Update previous history if update
+ * is true
+ */
+static inline unsigned long get_low_cpu_load(int cpu, int update)
+{
+	runqueue_t *rq = cpu_rq(cpu);
+	runqueue_t *this_rq = this_rq();
+	unsigned long nr = rq->nr_running << SCHED_LOAD_SHIFT;
+	unsigned long load = this_rq->cpu_load[cpu];
+	unsigned long ret = min(nr, load);
+
+	if (update)
+		this_rq->cpu_load[cpu] = (nr + load) / 2;
+
+	return ret;
+}
+
+static inline unsigned long get_high_cpu_load(int cpu, int update)
+{
+	runqueue_t *rq = cpu_rq(cpu);
+	runqueue_t *this_rq = this_rq();
+	unsigned long nr = rq->nr_running << SCHED_LOAD_SHIFT;
+	unsigned long load = this_rq->cpu_load[cpu];
+	unsigned long ret = max(nr, load);
+
+	if (update)
+		this_rq->cpu_load[cpu] = (nr + load) / 2;
+
+	return ret;
+}
+
+#endif
+
+/*
+ * sched_balance_wake can be used with SMT architectures to wake a
+ * task onto an idle sibling if cpu is not idle. Returns cpu if
+ * cpu is idle or no siblings are idle, otherwise returns an idle
+ * sibling.
+ */
+#if defined(CONFIG_SMP) && defined(ARCH_HAS_SCHED_WAKE_BALANCE)
+static int sched_balance_wake(int cpu, task_t *p)
+{
+	cpumask_t tmp;
+	struct sched_domain *domain;
+	int i;
+
+	if (idle_cpu(cpu))
+		return cpu;
+
+	domain = cpu_sched_domain(cpu);
+	if (!(domain->flags & SD_FLAG_WAKE))
+		return cpu;
+
+	cpus_and(tmp, domain->span, cpu_online_map);
+	for_each_cpu_mask(i, tmp) {
+		if (!cpu_isset(i, p->cpus_allowed))
+			continue;
+
+		if (idle_cpu(i))
+			return i;
+	}
 
+	return cpu;
+}
+#else
+static inline int sched_balance_wake(int cpu, task_t *p)
+{
+	return cpu;
+}
 #endif
 
 /***
@@ -657,44 +695,117 @@ static int try_to_wake_up(task_t * p, un
 	int success = 0;
 	long old_state;
 	runqueue_t *rq;
+	int cpu, this_cpu;
+#ifdef CONFIG_SMP
+	unsigned long long now;
+	unsigned long load, this_load;
+	int new_cpu;
+	struct sched_domain *sd;
+	runqueue_t *this_rq;
+#endif
 
-repeat_lock_task:
 	rq = task_rq_lock(p, &flags);
 	old_state = p->state;
-	if (old_state & state) {
-		if (!p->array) {
-			/*
-			 * Fast-migrate the task if it's not running or runnable
-			 * currently. Do not violate hard affinity.
-			 */
-			if (unlikely(sync && !task_running(rq, p) &&
-				(task_cpu(p) != smp_processor_id()) &&
-					cpu_isset(smp_processor_id(),
-							p->cpus_allowed))) {
-
-				set_task_cpu(p, smp_processor_id());
-				task_rq_unlock(rq, &flags);
-				goto repeat_lock_task;
-			}
-			if (old_state == TASK_UNINTERRUPTIBLE) {
-				rq->nr_uninterruptible--;
-				/*
-				 * Tasks on involuntary sleep don't earn
-				 * sleep_avg beyond just interactive state.
-				 */
-				p->activated = -1;
-			}
-			if (sync && (task_cpu(p) == smp_processor_id()))
-				__activate_task(p, rq);
-			else {
-				activate_task(p, rq);
-				if (TASK_PREEMPTS_CURR(p, rq))
-					resched_task(rq->curr);
-			}
-			success = 1;
+	if (!(old_state & state))
+		goto out;
+
+	if (p->array)
+		goto out_running;
+
+	this_cpu = smp_processor_id();
+	cpu = task_cpu(p);
+
+#ifdef CONFIG_SMP
+	if (cpu == this_cpu)
+		goto out_activate;
+
+	if (unlikely(!cpu_isset(this_cpu, p->cpus_allowed)
+		     || task_running(rq, p)
+		     || cpu_is_offline(this_cpu)))
+		goto out_activate;
+
+	/* Passive load balancing */
+	load = get_low_cpu_load(cpu, 1);
+	this_load = get_high_cpu_load(this_cpu, 1) + SCHED_LOAD_SCALE;
+	if (load > this_load) {
+		new_cpu = sched_balance_wake(this_cpu, p);
+		set_task_cpu(p, new_cpu);
+		goto repeat_lock_task;
+	}
+
+	this_rq = this_rq();
+	now = sched_clock();
+	sd = cpu_sched_domain(this_cpu);
+
+	/*
+	 * Fast-migrate the task if it's not running or
+	 * runnable currently. Do not violate hard affinity.
+	 */
+	do {
+		if (!(sd->flags & SD_FLAG_FASTMIGRATE))
+			break;
+		if (now - p->timestamp < sd->cache_hot_time)
+			break;
+
+		if (cpu_isset(cpu, sd->span)) {
+			new_cpu = sched_balance_wake(this_cpu, p);
+			set_task_cpu(p, new_cpu);
+			goto repeat_lock_task;
 		}
-		p->state = TASK_RUNNING;
+		sd = sd->parent;
+	} while (sd);
+
+	new_cpu = sched_balance_wake(cpu, p);
+	if (new_cpu != cpu) {
+		set_task_cpu(p, new_cpu);
+		goto repeat_lock_task;
 	}
+	goto out_activate;
+
+	if ((p->flags & PF_FUTEX_DEBUG)
+	    && !(current->flags & PF_FUTEX_DEBUG)) {
+		printk("%s %i waking %s: %i %i\n",
+		       current->comm, (int)in_interrupt(),
+		       p->comm, p->tgid, p->pid);
+		WARN_ON(1);
+	}
+
+repeat_lock_task:
+	task_rq_unlock(rq, &flags);
+	rq = task_rq_lock(p, &flags);
+	old_state = p->state;
+	if (!(old_state & state))
+		goto out;
+
+	if (p->array)
+		goto out_running;
+
+	this_cpu = smp_processor_id();
+	cpu = task_cpu(p);
+
+out_activate:
+#endif /* CONFIG_SMP */
+	if (old_state == TASK_UNINTERRUPTIBLE) {
+		rq->nr_uninterruptible--;
+		/*
+		 * Tasks on involuntary sleep don't earn
+		 * sleep_avg beyond just interactive state.
+		 */
+		p->activated = -1;
+	}
+
+	if (sync && cpu == this_cpu) {
+		__activate_task(p, rq);
+	} else {
+		activate_task(p, rq);
+		if (TASK_PREEMPTS_CURR(p, rq))
+			resched_task(rq->curr);
+	}
+	success = 1;
+
+out_running:
+	p->state = TASK_RUNNING;
+out:
 	task_rq_unlock(rq, &flags);
 
 	return success;
@@ -753,8 +864,8 @@ void sched_fork(task_t *p)
 	p->timestamp = sched_clock();
 	if (!current->time_slice) {
 		/*
-	 	 * This case is rare, it happens when the parent has only
-	 	 * a single jiffy left from its timeslice. Taking the
+		 * This case is rare, it happens when the parent has only
+		 * a single jiffy left from its timeslice. Taking the
 		 * runqueue lock is not a problem.
 		 */
 		current->time_slice = 1;
@@ -870,7 +981,7 @@ static inline void finish_task_switch(ta
 	 * still held, otherwise prev could be scheduled on another cpu, die
 	 * there before we look at prev->state, and then the reference would
 	 * be dropped twice.
-	 * 		Manfred Spraul <manfred@colorfullife.com>
+	 *		Manfred Spraul <manfred@colorfullife.com>
 	 */
 	prev_task_flags = prev->flags;
 	finish_arch_switch(rq, prev);
@@ -932,7 +1043,7 @@ unsigned long nr_running(void)
 {
 	unsigned long i, sum = 0;
 
-	for (i = 0; i < NR_CPUS; i++)
+	for_each_cpu(i)
 		sum += cpu_rq(i)->nr_running;
 
 	return sum;
@@ -1002,40 +1113,44 @@ static inline void double_rq_unlock(runq
 		spin_unlock(&rq2->lock);
 }
 
+enum idle_type
+{
+	IDLE,
+	NOT_IDLE,
+	NEWLY_IDLE,
+};
+
+#ifdef CONFIG_SMP
+
 #ifdef CONFIG_NUMA
 /*
- * If dest_cpu is allowed for this process, migrate the task to it.
- * This is accomplished by forcing the cpu_allowed mask to only
- * allow dest_cpu, which will force the cpu onto dest_cpu.  Then
- * the cpu_allowed mask is restored.
+ * If dest_cpu is allowed for this process, migrate us to it.
  */
-static void sched_migrate_task(task_t *p, int dest_cpu)
+void migrate_to_cpu(int dest_cpu)
 {
 	runqueue_t *rq;
 	migration_req_t req;
 	unsigned long flags;
-	cpumask_t old_mask, new_mask = cpumask_of_cpu(dest_cpu);
 
-	rq = task_rq_lock(p, &flags);
-	old_mask = p->cpus_allowed;
-	if (!cpu_isset(dest_cpu, old_mask) || !cpu_online(dest_cpu))
+	rq = task_rq_lock(current, &flags);
+	if (!cpu_isset(dest_cpu, current->cpus_allowed))
 		goto out;
 
 	/* force the process onto the specified CPU */
-	if (__set_cpus_allowed(p, new_mask, &req)) {
+	if (migrate_task(current, dest_cpu, &req)) {
 		/* Need to wait for migration thread. */
 		task_rq_unlock(rq, &flags);
 		wake_up_process(rq->migration_thread);
 		wait_for_completion(&req.done);
 
-		/* If we raced with sys_sched_setaffinity, don't
-		 * restore mask. */
-		rq = task_rq_lock(p, &flags);
-		if (likely(cpus_equal(p->cpus_allowed, new_mask))) {
-			/* Restore old mask: won't need migration
-			 * thread, since current cpu is allowed. */
-			BUG_ON(__set_cpus_allowed(p, old_mask, NULL));
-		}
+		/*
+		 * we want a new context here. This eliminates TLB
+		 * flushes on the cpus where the process executed prior to
+		 * the migration.
+		 */
+		tlb_migrate_prepare(current->mm);
+
+		return;
 	}
 out:
 	task_rq_unlock(rq, &flags);
@@ -1045,215 +1160,81 @@ out:
  * Find the least loaded CPU.  Slightly favor the current CPU by
  * setting its runqueue length as the minimum to start.
  */
-static int sched_best_cpu(struct task_struct *p)
+static int sched_best_cpu(struct task_struct *p, struct sched_domain *domain)
 {
-	int i, minload, load, best_cpu, node = 0;
-	cpumask_t cpumask;
+	cpumask_t tmp;
+	int i, min_load, this_cpu, best_cpu;
 
-	best_cpu = task_cpu(p);
-	if (cpu_rq(best_cpu)->nr_running <= 2)
-		return best_cpu;
+	best_cpu = this_cpu = task_cpu(p);
+	min_load = INT_MAX;
 
-	minload = 10000000;
-	for_each_node_with_cpus(i) {
-		/*
-		 * Node load is always divided by nr_cpus_node to normalise
-		 * load values in case cpu count differs from node to node.
-		 * We first multiply node_nr_running by 10 to get a little
-		 * better resolution.
-		 */
-		load = 10 * atomic_read(&node_nr_running[i]) / nr_cpus_node(i);
-		if (load < minload) {
-			minload = load;
-			node = i;
-		}
-	}
+	cpus_and(tmp, domain->span, cpu_online_map);
+	for_each_cpu_mask(i, tmp) {
+		unsigned long load;
+		if (i == this_cpu)
+			load = get_low_cpu_load(i, 0);
+		else
+			load = get_high_cpu_load(i, 0) + SCHED_LOAD_SCALE;
 
-	minload = 10000000;
-	cpumask = node_to_cpumask(node);
-	for (i = 0; i < NR_CPUS; ++i) {
-		if (!cpu_isset(i, cpumask))
-			continue;
-		if (cpu_rq(i)->nr_running < minload) {
+		if (min_load > load) {
 			best_cpu = i;
-			minload = cpu_rq(i)->nr_running;
+			min_load = load;
 		}
+
 	}
 	return best_cpu;
 }
 
 void sched_balance_exec(void)
 {
+	struct sched_domain *domain = this_sched_domain();
 	int new_cpu;
+	int this_cpu = smp_processor_id();
+	if (numnodes == 1)
+		return;
 
-	if (numnodes > 1) {
-		new_cpu = sched_best_cpu(current);
-		if (new_cpu != smp_processor_id())
-			sched_migrate_task(current, new_cpu);
-	}
-}
+	if (this_rq()->nr_running <= 1)
+		return;
 
-/*
- * Find the busiest node. All previous node loads contribute with a
- * geometrically deccaying weight to the load measure:
- *      load_{t} = load_{t-1}/2 + nr_node_running_{t}
- * This way sudden load peaks are flattened out a bit.
- * Node load is divided by nr_cpus_node() in order to compare nodes
- * of different cpu count but also [first] multiplied by 10 to
- * provide better resolution.
- */
-static int find_busiest_node(int this_node)
-{
-	int i, node = -1, load, this_load, maxload;
-
-	if (!nr_cpus_node(this_node))
-		return node;
-	this_load = maxload = (this_rq()->prev_node_load[this_node] >> 1)
-		+ (10 * atomic_read(&node_nr_running[this_node])
-		/ nr_cpus_node(this_node));
-	this_rq()->prev_node_load[this_node] = this_load;
-	for_each_node_with_cpus(i) {
-		if (i == this_node)
-			continue;
-		load = (this_rq()->prev_node_load[i] >> 1)
-			+ (10 * atomic_read(&node_nr_running[i])
-			/ nr_cpus_node(i));
-		this_rq()->prev_node_load[i] = load;
-		if (load > maxload && (100*load > NODE_THRESHOLD*this_load)) {
-			maxload = load;
-			node = i;
-		}
+	while (domain->parent && !(domain->flags & SD_FLAG_EXEC))
+		domain = domain->parent;
+
+	if (domain->flags & SD_FLAG_EXEC) {
+		new_cpu = sched_best_cpu(current, domain);
+		if (new_cpu != this_cpu)
+			migrate_to_cpu(new_cpu);
 	}
-	return node;
 }
-
 #endif /* CONFIG_NUMA */
 
-#ifdef CONFIG_SMP
-
 /*
- * double_lock_balance - lock the busiest runqueue
- *
- * this_rq is locked already. Recalculate nr_running if we have to
- * drop the runqueue lock.
+ * double_lock_balance - lock the busiest runqueue, this_rq is locked already.
  */
-static inline
-unsigned int double_lock_balance(runqueue_t *this_rq, runqueue_t *busiest,
-				 int this_cpu, int idle,
-				 unsigned int nr_running)
+static inline void double_lock_balance(runqueue_t *this_rq, runqueue_t *busiest)
 {
 	if (unlikely(!spin_trylock(&busiest->lock))) {
 		if (busiest < this_rq) {
 			spin_unlock(&this_rq->lock);
 			spin_lock(&busiest->lock);
 			spin_lock(&this_rq->lock);
-			/* Need to recalculate nr_running */
-			if (idle || (this_rq->nr_running >
-					this_rq->prev_cpu_load[this_cpu]))
-				nr_running = this_rq->nr_running;
-			else
-				nr_running = this_rq->prev_cpu_load[this_cpu];
 		} else
 			spin_lock(&busiest->lock);
 	}
-	return nr_running;
-}
-
-/*
- * find_busiest_queue - find the busiest runqueue among the cpus in cpumask.
- */
-static inline
-runqueue_t *find_busiest_queue(runqueue_t *this_rq, int this_cpu, int idle,
-			       int *imbalance, cpumask_t cpumask)
-{
-	int nr_running, load, max_load, i;
-	runqueue_t *busiest, *rq_src;
-
-	/*
-	 * We search all runqueues to find the most busy one.
-	 * We do this lockless to reduce cache-bouncing overhead,
-	 * we re-check the 'best' source CPU later on again, with
-	 * the lock held.
-	 *
-	 * We fend off statistical fluctuations in runqueue lengths by
-	 * saving the runqueue length (as seen by the balancing CPU) during
-	 * the previous load-balancing operation and using the smaller one
-	 * of the current and saved lengths. If a runqueue is long enough
-	 * for a longer amount of time then we recognize it and pull tasks
-	 * from it.
-	 *
-	 * The 'current runqueue length' is a statistical maximum variable,
-	 * for that one we take the longer one - to avoid fluctuations in
-	 * the other direction. So for a load-balance to happen it needs
-	 * stable long runqueue on the target CPU and stable short runqueue
-	 * on the local runqueue.
-	 *
-	 * We make an exception if this CPU is about to become idle - in
-	 * that case we are less picky about moving a task across CPUs and
-	 * take what can be taken.
-	 */
-	if (idle || (this_rq->nr_running > this_rq->prev_cpu_load[this_cpu]))
-		nr_running = this_rq->nr_running;
-	else
-		nr_running = this_rq->prev_cpu_load[this_cpu];
-
-	busiest = NULL;
-	max_load = 1;
-	for (i = 0; i < NR_CPUS; i++) {
-		if (!cpu_isset(i, cpumask))
-			continue;
-
-		rq_src = cpu_rq(i);
-		if (idle || (rq_src->nr_running < this_rq->prev_cpu_load[i]))
-			load = rq_src->nr_running;
-		else
-			load = this_rq->prev_cpu_load[i];
-		this_rq->prev_cpu_load[i] = rq_src->nr_running;
-
-		if ((load > max_load) && (rq_src != this_rq)) {
-			busiest = rq_src;
-			max_load = load;
-		}
-	}
-
-	if (likely(!busiest))
-		goto out;
-
-	*imbalance = max_load - nr_running;
-
-	/* It needs an at least ~25% imbalance to trigger balancing. */
-	if (!idle && ((*imbalance)*4 < max_load)) {
-		busiest = NULL;
-		goto out;
-	}
-
-	nr_running = double_lock_balance(this_rq, busiest, this_cpu,
-					 idle, nr_running);
-	/*
-	 * Make sure nothing changed since we checked the
-	 * runqueue length.
-	 */
-	if (busiest->nr_running <= nr_running) {
-		spin_unlock(&busiest->lock);
-		busiest = NULL;
-	}
-out:
-	return busiest;
 }
 
 /*
  * pull_task - move a task from a remote runqueue to the local runqueue.
  * Both runqueues must be locked.
  */
-static inline
-void pull_task(runqueue_t *src_rq, prio_array_t *src_array, task_t *p,
-	       runqueue_t *this_rq, int this_cpu)
+static inline void pull_task(runqueue_t *src_rq, prio_array_t *src_array,
+		task_t *p, runqueue_t *this_rq, prio_array_t *this_array,
+		int this_cpu)
 {
 	dequeue_task(p, src_array);
 	nr_running_dec(src_rq);
 	set_task_cpu(p, this_cpu);
 	nr_running_inc(this_rq);
-	enqueue_task(p, this_rq->active);
+	enqueue_task(p, this_array);
 	p->timestamp = sched_clock() -
 				(src_rq->timestamp_last_tick - p->timestamp);
 	/*
@@ -1261,69 +1242,71 @@ void pull_task(runqueue_t *src_rq, prio_
 	 * to be always true for them.
 	 */
 	if (TASK_PREEMPTS_CURR(p, this_rq))
-		set_need_resched();
+		resched_task(this_rq->curr);
 }
 
 /*
  * can_migrate_task - may task p from runqueue rq be migrated to this_cpu?
  */
 static inline
-int can_migrate_task(task_t *tsk, runqueue_t *rq, int this_cpu, int idle)
+int can_migrate_task(task_t *p, runqueue_t *rq, int this_cpu,
+		struct sched_domain *domain, enum idle_type idle)
 {
-	unsigned long delta = rq->timestamp_last_tick - tsk->timestamp;
-
 	/*
 	 * We do not migrate tasks that are:
 	 * 1) running (obviously), or
 	 * 2) cannot be migrated to this CPU due to cpus_allowed, or
 	 * 3) are cache-hot on their current CPU.
 	 */
-	if (task_running(rq, tsk))
+	if (task_running(rq, p))
 		return 0;
-	if (!cpu_isset(this_cpu, tsk->cpus_allowed))
-		return 0;
-	if (!idle && (delta <= JIFFIES_TO_NS(cache_decay_ticks)))
+	if (!cpu_isset(this_cpu, p->cpus_allowed))
 		return 0;
+
+	/* Aggressive migration if we've failed balancing */
+	if (idle == NEWLY_IDLE ||
+			domain->nr_balance_failed < domain->cache_nice_tries) {
+		if ((rq->timestamp_last_tick - p->timestamp)
+						< domain->cache_hot_time)
+			return 0;
+	}
+
 	return 1;
 }
 
 /*
- * Current runqueue is empty, or rebalance tick: if there is an
- * inbalance (current runqueue is too short) then pull from
- * busiest runqueue(s).
- *
- * We call this with the current runqueue locked,
- * irqs disabled.
- */
-static void load_balance(runqueue_t *this_rq, int idle, cpumask_t cpumask)
+ * move_tasks tries to move up to max_nr_move tasks from busiest to this_rq,
+ * as part of a balancing operation within "domain". Returns the number of
+ * tasks moved.
+ *
+ * Called with both runqueues locked.
+ */
+static int move_tasks(runqueue_t *this_rq, int this_cpu, runqueue_t *busiest,
+			unsigned long max_nr_move, struct sched_domain *domain,
+			enum idle_type idle)
 {
-	int imbalance, idx, this_cpu = smp_processor_id();
-	runqueue_t *busiest;
-	prio_array_t *array;
+	int idx;
+	int pulled = 0;
+	prio_array_t *array, *dst_array;
 	struct list_head *head, *curr;
 	task_t *tmp;
 
-	busiest = find_busiest_queue(this_rq, this_cpu, idle,
-				     &imbalance, cpumask);
-	if (!busiest)
+	if (max_nr_move <= 0 || busiest->nr_running <= 1)
 		goto out;
 
 	/*
-	 * We only want to steal a number of tasks equal to 1/2 the imbalance,
-	 * otherwise we'll just shift the imbalance to the new queue:
-	 */
-	imbalance /= 2;
-
-	/*
 	 * We first consider expired tasks. Those will likely not be
 	 * executed in the near future, and they are most likely to
 	 * be cache-cold, thus switching CPUs has the least effect
 	 * on them.
 	 */
-	if (busiest->expired->nr_active)
+	if (busiest->expired->nr_active) {
 		array = busiest->expired;
-	else
+		dst_array = this_rq->expired;
+	} else {
 		array = busiest->active;
+		dst_array = this_rq->active;
+	}
 
 new_array:
 	/* Start searching at priority 0: */
@@ -1336,9 +1319,10 @@ skip_bitmap:
 	if (idx >= MAX_PRIO) {
 		if (array == busiest->expired) {
 			array = busiest->active;
+			dst_array = this_rq->active;
 			goto new_array;
 		}
-		goto out_unlock;
+		goto out;
 	}
 
 	head = array->queue + idx;
@@ -1348,100 +1332,450 @@ skip_queue:
 
 	curr = curr->prev;
 
-	if (!can_migrate_task(tmp, busiest, this_cpu, idle)) {
+	if (!can_migrate_task(tmp, busiest, this_cpu, domain, idle)) {
 		if (curr != head)
 			goto skip_queue;
 		idx++;
 		goto skip_bitmap;
 	}
-	pull_task(busiest, array, tmp, this_rq, this_cpu);
+	pull_task(busiest, array, tmp, this_rq, dst_array, this_cpu);
+	pulled++;
 
-	/* Only migrate one task if we are idle */
-	if (!idle && --imbalance) {
+	/* We only want to steal up to the prescribed number of tasks. */
+	if (pulled < max_nr_move) {
 		if (curr != head)
 			goto skip_queue;
 		idx++;
 		goto skip_bitmap;
 	}
-out_unlock:
-	spin_unlock(&busiest->lock);
 out:
-	;
+	return pulled;
 }
 
 /*
- * One of the idle_cpu_tick() and busy_cpu_tick() functions will
- * get called every timer tick, on every CPU. Our balancing action
- * frequency and balancing agressivity depends on whether the CPU is
- * idle or not.
+ * find_busiest_group finds and returns the busiest CPU group within the
+ * domain. It calculates and returns the number of tasks which should be
+ * moved to restore balance via the imbalance parameter.
+ */
+static struct sched_group *
+find_busiest_group(struct sched_domain *domain, int this_cpu,
+				unsigned long *imbalance, enum idle_type idle)
+{
+	unsigned long max_load, avg_load, total_load, this_load;
+	unsigned int total_pwr;
+	int modify;
+	struct sched_group *busiest = NULL, *this = NULL, *group = domain->groups;
+
+	max_load = 0;
+	this_load = 0;
+	total_load = 0;
+	total_pwr = 0;
+
+	if (group == NULL)
+		goto out_balanced;
+
+	/*
+	 * Don't modify when we newly become idle because that ruins our
+	 * statistics: its triggered by some value of nr_running (ie. 0).
+	 * Timer based balancing is a good statistic though.
+	 */
+	if (idle == NEWLY_IDLE)
+		modify = 0;
+	else
+		modify = 1;
+
+	do {
+		cpumask_t tmp;
+		unsigned long load;
+		int local_group;
+		int i, nr_cpus = 0;
+
+		local_group = cpu_isset(this_cpu, group->cpumask);
+
+		/* Tally up the load of all CPUs in the group */
+		avg_load = 0;
+		cpus_and(tmp, group->cpumask, cpu_online_map);
+		for_each_cpu_mask(i, tmp) {
+			/* Bias balancing toward cpus of our domain */
+			if (local_group) {
+				load = get_high_cpu_load(i, modify);
+			} else
+				load = get_low_cpu_load(i, modify);
+
+			nr_cpus++;
+			avg_load += load;
+		}
+
+		if (!nr_cpus)
+			goto nextgroup;
+
+		total_load += avg_load;
+		total_pwr += group->cpu_power;
+
+		/* Adjust by relative CPU power of the group */
+		avg_load = (avg_load << SCHED_LOAD_SHIFT) / group->cpu_power;
+
+		if (local_group) {
+			this_load = avg_load;
+			this = group;
+			goto nextgroup;
+		}
+		if (avg_load > max_load) {
+			max_load = avg_load;
+			busiest = group;
+		}
+nextgroup:
+		group = group->next;
+	} while (group != domain->groups);
+
+	if (!busiest || this_load >= max_load)
+		goto out_balanced;
+
+	avg_load = (SCHED_LOAD_SCALE * total_load) / total_pwr;
+
+	if (idle == NOT_IDLE) {
+		if (this_load >= avg_load ||
+			100*max_load <= domain->imbalance_pct*this_load)
+		goto out_balanced;
+	}
+
+	/*
+	 * We're trying to get all the cpus to the average_load, so we don't
+	 * want to push ourselves above the average load, nor do we wish to
+	 * reduce the max loaded cpu below the average load, as either of these
+	 * actions would just result in more rebalancing later, and ping-pong
+	 * tasks around. Thus we look for the minimum possible imbalance.
+	 * Negative imbalances (*we* are more loaded than anyone else) will
+	 * be counted as no imbalance for these purposes -- we can't fix that
+	 * by pulling tasks to us.  Be careful of negative numbers as they'll
+	 * appear as very large values with unsigned longs.
+	 */
+	*imbalance = (min(max_load - avg_load, avg_load - this_load) + 1) / 2;
+
+	if (*imbalance <= SCHED_LOAD_SCALE/2) {
+		unsigned long pwr_now = 0, pwr_move = 0;
+		unsigned long tmp;
+
+		/*
+		 * OK, we don't have enough imbalance to justify moving tasks,
+		 * however we may be able to increase total CPU power used by
+		 * moving them.
+		 */
+
+		pwr_now += busiest->cpu_power*min(SCHED_LOAD_SCALE, max_load);
+		pwr_now += this->cpu_power*min(SCHED_LOAD_SCALE, this_load);
+		pwr_now >>= SCHED_LOAD_SHIFT;
+
+		/* Amount of load we'd subtract */
+		tmp = SCHED_LOAD_SCALE*SCHED_LOAD_SCALE/busiest->cpu_power;
+		if (max_load > tmp)
+			pwr_move += busiest->cpu_power*min(SCHED_LOAD_SCALE,
+							max_load - tmp);
+
+		/* Amount of load we'd add */
+		tmp = SCHED_LOAD_SCALE*SCHED_LOAD_SCALE/this->cpu_power;
+		pwr_move += this->cpu_power*min(this->cpu_power, this_load + tmp);
+		pwr_move >>= SCHED_LOAD_SHIFT;
+
+		/* Move if we gain another 8th of a CPU worth of throughput */
+		if (pwr_move < pwr_now + SCHED_LOAD_SCALE / 8)
+			goto out_balanced;
+		*imbalance = 1;
+		return busiest;
+	}
+
+	/* How many tasks to actually move to equalise the imbalance */
+	*imbalance = (*imbalance * min(busiest->cpu_power, this->cpu_power))
+				>> SCHED_LOAD_SHIFT;
+	/* Get rid of the scaling factor, rounding *up* as we divide */
+	*imbalance = (*imbalance + SCHED_LOAD_SCALE/2) >> SCHED_LOAD_SHIFT;
+
+	return busiest;
+
+out_balanced:
+	*imbalance = 0;
+	return NULL;
+}
+
+/*
+ * find_busiest_queue - find the busiest runqueue among the cpus in group.
+ */
+static runqueue_t *find_busiest_queue(struct sched_group *group)
+{
+	cpumask_t tmp;
+	int i;
+	unsigned long max_load = 0;
+	runqueue_t *busiest = NULL;
+
+	cpus_and(tmp, group->cpumask, cpu_online_map);
+	for_each_cpu_mask(i, tmp) {
+		unsigned long load;
+
+		load = get_low_cpu_load(i, 0);
+
+		if (load >= max_load) {
+			max_load = load;
+			busiest = cpu_rq(i);
+		}
+	}
+
+	return busiest;
+}
+
+/*
+ * Check this_cpu to ensure it is balanced within domain. Attempt to move
+ * tasks if there is an imbalance.
  *
- * busy-rebalance every 200 msecs. idle-rebalance every 1 msec. (or on
- * systems with HZ=100, every 10 msecs.)
+ * Called with this_rq unlocked.
+ */
+static int load_balance(int this_cpu, runqueue_t *this_rq,
+			struct sched_domain *domain, enum idle_type idle)
+{
+	struct sched_group *group;
+	runqueue_t *busiest = NULL;
+	unsigned long imbalance;
+	int balanced = 0, failed = 0;
+	int nr_moved = 0;
+
+	spin_lock(&this_rq->lock);
+
+	group = find_busiest_group(domain, this_cpu, &imbalance, idle);
+	if (!group) {
+		balanced = 1;
+		goto out;
+	}
+
+	busiest = find_busiest_queue(group);
+	if (!busiest || busiest == this_rq) {
+		balanced = 1;
+		goto out;
+	}
+
+	/* Attempt to move tasks */
+	double_lock_balance(this_rq, busiest);
+
+	nr_moved = move_tasks(this_rq, this_cpu, busiest,
+					imbalance, domain, idle);
+	spin_unlock(&busiest->lock);
+out:
+	spin_unlock(&this_rq->lock);
+
+	if (!balanced && nr_moved == 0)
+		failed = 1;
+
+	if (failed && busiest &&
+	   		domain->nr_balance_failed > domain->cache_nice_tries) {
+		int wake = 0;
+
+		spin_lock(&busiest->lock);
+		if (!busiest->active_balance) {
+			busiest->active_balance = 1;
+			busiest->push_cpu = this_cpu;
+			wake = 1;
+		}
+		spin_unlock(&busiest->lock);
+		if (wake)
+			wake_up_process(busiest->migration_thread);
+	}
+
+	if (failed)
+		domain->nr_balance_failed++;
+	else
+		domain->nr_balance_failed = 0;
+
+	if (balanced) {
+		if (domain->balance_interval < domain->max_interval)
+			domain->balance_interval *= 2;
+	} else {
+		domain->balance_interval = domain->min_interval;
+	}
+
+	return nr_moved;
+}
+
+/*
+ * Check this_cpu to ensure it is balanced within domain. Attempt to move
+ * tasks if there is an imbalance.
  *
- * On NUMA, do a node-rebalance every 400 msecs.
+ * Called from schedule when this_rq is about to become idle (NEWLY_IDLE).
+ * this_rq is locked.
  */
-#define IDLE_REBALANCE_TICK (HZ/1000 ?: 1)
-#define BUSY_REBALANCE_TICK (HZ/5 ?: 1)
-#define IDLE_NODE_REBALANCE_TICK (IDLE_REBALANCE_TICK * 5)
-#define BUSY_NODE_REBALANCE_TICK (BUSY_REBALANCE_TICK * 2)
+static int load_balance_newidle(int this_cpu, runqueue_t *this_rq,
+			struct sched_domain *domain)
+{
+	struct sched_group *group;
+	runqueue_t *busiest = NULL;
+	unsigned long imbalance;
+	int nr_moved = 0;
 
-#ifdef CONFIG_NUMA
-static void balance_node(runqueue_t *this_rq, int idle, int this_cpu)
+	group = find_busiest_group(domain, this_cpu, &imbalance, NEWLY_IDLE);
+	if (!group)
+		goto out;
+
+	busiest = find_busiest_queue(group);
+	if (!busiest || busiest == this_rq)
+		goto out;
+
+	/* Attempt to move tasks */
+	double_lock_balance(this_rq, busiest);
+
+	nr_moved = move_tasks(this_rq, this_cpu, busiest,
+					imbalance, domain, NEWLY_IDLE);
+
+	spin_unlock(&busiest->lock);
+
+out:
+	return nr_moved;
+}
+
+/*
+ * idle_balance is called by schedule() if this_cpu is about to become
+ * idle. Attempts to pull tasks from other CPUs.
+ */
+static inline void idle_balance(int this_cpu, runqueue_t *this_rq)
 {
-	int node = find_busiest_node(cpu_to_node(this_cpu));
+	struct sched_domain *domain = this_sched_domain();
 
-	if (node >= 0) {
-		cpumask_t cpumask = node_to_cpumask(node);
-		cpu_set(this_cpu, cpumask);
-		spin_lock(&this_rq->lock);
-		load_balance(this_rq, idle, cpumask);
-		spin_unlock(&this_rq->lock);
-	}
+	if (cpu_is_offline(this_cpu))
+		return;
+
+	do {
+		if (unlikely(!domain->groups))
+			/* hasn't been setup yet */
+			break;
+
+		if (domain->flags & SD_FLAG_NEWIDLE) {
+			if (load_balance_newidle(this_cpu, this_rq, domain)) {
+				/* We've pulled tasks over so stop searching */
+				break;
+			}
+		}
+
+		domain = domain->parent;
+	} while (domain);
 }
-#endif
 
-static void rebalance_tick(runqueue_t *this_rq, int idle)
+/*
+ * active_load_balance is run by migration threads. It pushes a running
+ * task off the cpu. It can be required to correctly have at least 1 task
+ * running on each physical CPU where possible, and not have a physical /
+ * logical imbalance.
+ *
+ * Called with busiest locked.
+ */
+static void active_load_balance(runqueue_t *busiest, int busiest_cpu)
 {
-#ifdef CONFIG_NUMA
-	int this_cpu = smp_processor_id();
-#endif
-	unsigned long j = jiffies;
+	int i;
+	struct sched_domain *sd = cpu_sched_domain(busiest_cpu);
+	struct sched_group *group, *busy_group;
 
-	/*
-	 * First do inter-node rebalancing, then intra-node rebalancing,
-	 * if both events happen in the same tick. The inter-node
-	 * rebalancing does not necessarily have to create a perfect
-	 * balance within the node, since we load-balance the most loaded
-	 * node with the current CPU. (ie. other CPUs in the local node
-	 * are not balanced.)
-	 */
-	if (idle) {
-#ifdef CONFIG_NUMA
-		if (!(j % IDLE_NODE_REBALANCE_TICK))
-			balance_node(this_rq, idle, this_cpu);
-#endif
-		if (!(j % IDLE_REBALANCE_TICK)) {
-			spin_lock(&this_rq->lock);
-			load_balance(this_rq, idle, cpu_to_node_mask(this_cpu));
-			spin_unlock(&this_rq->lock);
+	if (busiest->nr_running <= 1)
+		return;
+
+	/* sd->parent should never cause a NULL dereference, if it did so,
+ 	 * then push_cpu was set to a buggy value */
+	while (!cpu_isset(busiest->push_cpu, sd->span)) {
+ 		sd = sd->parent;
+		if (!sd->parent && !cpu_isset(busiest->push_cpu, sd->span)) {
+			WARN_ON(1);
+			return;
 		}
+	}
+
+	if (!sd->groups) {
+		WARN_ON(1);
 		return;
 	}
-#ifdef CONFIG_NUMA
-	if (!(j % BUSY_NODE_REBALANCE_TICK))
-		balance_node(this_rq, idle, this_cpu);
-#endif
-	if (!(j % BUSY_REBALANCE_TICK)) {
-		spin_lock(&this_rq->lock);
-		load_balance(this_rq, idle, cpu_to_node_mask(this_cpu));
-		spin_unlock(&this_rq->lock);
+
+ 	group = sd->groups;
+	while (!cpu_isset(busiest_cpu, group->cpumask)) {
+ 		group = group->next;
+		if (group == sd->groups) {
+			WARN_ON(1);
+			return;
+		}
 	}
+ 	busy_group = group;
+
+ 	group = sd->groups;
+ 	do {
+		cpumask_t tmp;
+		runqueue_t *rq;
+ 		int push_cpu = 0, nr = 0;
+
+ 		if (group == busy_group)
+ 			goto next_group;
+
+		cpus_and(tmp, group->cpumask, cpu_online_map);
+ 		for_each_cpu_mask(i, tmp) {
+			if (!idle_cpu(i))
+				goto next_group;
+ 			push_cpu = i;
+ 			nr++;
+ 		}
+ 		if (nr == 0)
+ 			goto next_group;
+
+		rq = cpu_rq(push_cpu);
+		double_lock_balance(busiest, rq);
+		move_tasks(rq, push_cpu, busiest, 1, sd, IDLE);
+		spin_unlock(&rq->lock);
+next_group:
+		group = group->next;
+	} while (group != sd->groups);
+}
+
+/*
+ * rebalance_tick will get called every timer tick, on every CPU.
+ *
+ * It checks each scheduling domain to see if it is due to be balanced,
+ * and initiates a balancing operation if so.
+ *
+ * Balancing parameters are set up in arch_init_sched_domains.
+ */
+
+/* Don't have all balancing operations going off at once */
+#define CPU_OFFSET(cpu) (HZ * cpu / NR_CPUS)
+
+static void rebalance_tick(int this_cpu, runqueue_t *this_rq, enum idle_type idle)
+{
+	unsigned long j = jiffies + CPU_OFFSET(this_cpu);
+	struct sched_domain *domain = this_sched_domain();
+
+	BUG_ON(cpu_is_offline(this_cpu) && system_running);
+
+	/* Run through all this CPU's domains */
+	do {
+		unsigned long interval;
+
+		if (unlikely(!domain->groups))
+			break;
+
+		interval = domain->balance_interval;
+		if (idle != IDLE)
+			interval *= domain->busy_factor;
+
+		/* scale ms to jiffies */
+		interval = interval * HZ / 1000;
+		if (unlikely(interval == 0))
+			interval = 1;
+
+		if (j - domain->last_balance >= interval) {
+			if (load_balance(this_cpu, this_rq, domain, idle)) {
+				/* We've pulled tasks over so no longer idle */
+				idle = NOT_IDLE;
+			}
+			domain->last_balance += interval;
+		}
+
+		domain = domain->parent;
+	} while (domain);
 }
 #else
 /*
  * on UP we do not need to balance between CPUs:
  */
-static inline void rebalance_tick(runqueue_t *this_rq, int idle)
+static inline void rebalance_tick(int this_cpu, runqueue_t *this_rq, enum idle_type idle)
 {
 }
 #endif
@@ -1499,7 +1833,7 @@ void scheduler_tick(int user_ticks, int 
 			cpustat->iowait += sys_ticks;
 		else
 			cpustat->idle += sys_ticks;
-		rebalance_tick(rq, 1);
+		rebalance_tick(cpu, rq, IDLE);
 		return;
 	}
 	if (TASK_NICE(p) > 0)
@@ -1583,7 +1917,7 @@ void scheduler_tick(int user_ticks, int 
 out_unlock:
 	spin_unlock(&rq->lock);
 out:
-	rebalance_tick(rq, 0);
+	rebalance_tick(cpu, rq, NOT_IDLE);
 }
 
 void scheduling_functions_start_here(void) { }
@@ -1652,7 +1986,7 @@ need_resched:
 
 	if (unlikely(!rq->nr_running)) {
 #ifdef CONFIG_SMP
-		load_balance(rq, 1, cpu_to_node_mask(smp_processor_id()));
+		idle_balance(smp_processor_id(), rq);
 #endif
 		if (!rq->nr_running) {
 			next = rq->idle;
@@ -1906,10 +2240,21 @@ EXPORT_SYMBOL(wait_for_completion);
 	__remove_wait_queue(q, &wait);			\
 	spin_unlock_irqrestore(&q->lock, flags);
 
+#define SLEEP_ON_BKLCHECK				\
+	if (unlikely(!kernel_locked()) &&		\
+	    sleep_on_bkl_warnings < 10) {		\
+		sleep_on_bkl_warnings++;		\
+		WARN_ON(1);				\
+	}
+
+static int sleep_on_bkl_warnings;
+
 void interruptible_sleep_on(wait_queue_head_t *q)
 {
 	SLEEP_ON_VAR
 
+	SLEEP_ON_BKLCHECK
+
 	current->state = TASK_INTERRUPTIBLE;
 
 	SLEEP_ON_HEAD
@@ -1923,6 +2268,8 @@ long interruptible_sleep_on_timeout(wait
 {
 	SLEEP_ON_VAR
 
+	SLEEP_ON_BKLCHECK
+
 	current->state = TASK_INTERRUPTIBLE;
 
 	SLEEP_ON_HEAD
@@ -1938,6 +2285,8 @@ void sleep_on(wait_queue_head_t *q)
 {
 	SLEEP_ON_VAR
 
+	SLEEP_ON_BKLCHECK
+
 	current->state = TASK_UNINTERRUPTIBLE;
 
 	SLEEP_ON_HEAD
@@ -2013,6 +2362,13 @@ out_unlock:
 
 EXPORT_SYMBOL(set_user_nice);
 
+#if defined( CONFIG_KGDB)
+struct task_struct * kgdb_get_idle(int this_cpu)
+{
+        return cpu_rq(this_cpu)->idle;
+}
+#endif
+
 #ifndef __alpha__
 
 /*
@@ -2310,11 +2666,13 @@ asmlinkage long sys_sched_setaffinity(pi
 	if (copy_from_user(&new_mask, user_mask_ptr, sizeof(new_mask)))
 		return -EFAULT;
 
+	lock_cpu_hotplug();
 	read_lock(&tasklist_lock);
 
 	p = find_process_by_pid(pid);
 	if (!p) {
 		read_unlock(&tasklist_lock);
+		unlock_cpu_hotplug();
 		return -ESRCH;
 	}
 
@@ -2335,6 +2693,7 @@ asmlinkage long sys_sched_setaffinity(pi
 
 out_unlock:
 	put_task_struct(p);
+	unlock_cpu_hotplug();
 	return retval;
 }
 
@@ -2364,7 +2723,7 @@ asmlinkage long sys_sched_getaffinity(pi
 		goto out_unlock;
 
 	retval = 0;
-	cpus_and(mask, p->cpus_allowed, cpu_online_map);
+	cpus_and(mask, p->cpus_allowed, cpu_possible_map);
 
 out_unlock:
 	read_unlock(&tasklist_lock);
@@ -2568,34 +2927,36 @@ static inline struct task_struct *younge
 
 static void show_task(task_t * p)
 {
-	unsigned long free = 0;
 	task_t *relative;
-	int state;
-	static const char * stat_nam[] = { "R", "S", "D", "T", "Z", "W" };
+	unsigned state;
+	unsigned long free = 0;
+	static const char *stat_nam[] = { "R", "S", "D", "T", "Z", "W" };
 
 	printk("%-13.13s ", p->comm);
 	state = p->state ? __ffs(p->state) + 1 : 0;
-	if (((unsigned) state) < sizeof(stat_nam)/sizeof(char *))
+	if (state < ARRAY_SIZE(stat_nam))
 		printk(stat_nam[state]);
 	else
-		printk(" ");
+		printk("?");
 #if (BITS_PER_LONG == 32)
-	if (p == current)
-		printk(" current  ");
+	if (state == TASK_RUNNING)
+		printk(" running ");
 	else
 		printk(" %08lX ", thread_saved_pc(p));
 #else
-	if (p == current)
-		printk("   current task   ");
+	if (state == TASK_RUNNING)
+		printk("  running task   ");
 	else
 		printk(" %016lx ", thread_saved_pc(p));
 #endif
+#ifdef CONFIG_DEBUG_STACK_USAGE
 	{
 		unsigned long * n = (unsigned long *) (p->thread_info+1);
 		while (!*n)
 			n++;
 		free = (unsigned long) n - (unsigned long)(p->thread_info+1);
 	}
+#endif
 	printk("%5lu %5d %6d ", free, p->pid, p->parent->pid);
 	if ((relative = eldest_child(p)))
 		printk("%5d ", relative->pid);
@@ -2614,7 +2975,8 @@ static void show_task(task_t * p)
 	else
 		printk(" (NOTLB)\n");
 
-	show_stack(p, NULL);
+	if (state != TASK_RUNNING)
+		show_stack(p, NULL);
 }
 
 void show_state(void)
@@ -2623,12 +2985,12 @@ void show_state(void)
 
 #if (BITS_PER_LONG == 32)
 	printk("\n"
-	       "                         free                        sibling\n");
-	printk("  task             PC    stack   pid father child younger older\n");
+	       "                                               sibling\n");
+	printk("  task             PC      pid father child younger older\n");
 #else
 	printk("\n"
-	       "                                 free                        sibling\n");
-	printk("  task                 PC        stack   pid father child younger older\n");
+	       "                                                       sibling\n");
+	printk("  task                 PC          pid father child younger older\n");
 #endif
 	read_lock(&tasklist_lock);
 	do_each_thread(g, p) {
@@ -2708,7 +3070,12 @@ int set_cpus_allowed(task_t *p, cpumask_
 		goto out;
 	}
 
-	if (__set_cpus_allowed(p, new_mask, &req)) {
+	p->cpus_allowed = new_mask;
+	/* Can the task run on the task's current CPU? If so, we're done */
+	if (cpu_isset(task_cpu(p), new_mask))
+		goto out;
+
+	if (migrate_task(p, any_online_cpu(new_mask), &req)) {
 		/* Need help from migration thread: drop lock and wait. */
 		task_rq_unlock(rq, &flags);
 		wake_up_process(rq->migration_thread);
@@ -2722,8 +3089,16 @@ out:
 
 EXPORT_SYMBOL_GPL(set_cpus_allowed);
 
-/* Move (not current) task off this cpu, onto dest cpu. */
-static void move_task_away(struct task_struct *p, int dest_cpu)
+/*
+ * Move (not current) task off this cpu, onto dest cpu.  We're doing
+ * this because either it can't run here any more (set_cpus_allowed()
+ * away from this CPU, or CPU going down), or because we're
+ * attempting to rebalance this task on exec (sched_balance_exec).
+ *
+ * So we race with normal scheduler movements, but that's OK, as long
+ * as the task is no longer on this CPU.
+ */
+static void __migrate_task(struct task_struct *p, int dest_cpu)
 {
 	runqueue_t *rq_dest;
 	unsigned long flags;
@@ -2732,14 +3107,21 @@ static void move_task_away(struct task_s
 
 	local_irq_save(flags);
 	double_rq_lock(this_rq(), rq_dest);
+	/* Already moved. */
 	if (task_cpu(p) != smp_processor_id())
-		goto out; /* Already moved */
+		goto out;
+	/* Affinity changed (again). */
+	if (!cpu_isset(dest_cpu, p->cpus_allowed))
+		goto out;
+	/* CPU went down. */
+	if (cpu_is_offline(dest_cpu))
+		goto out;
 
 	set_task_cpu(p, dest_cpu);
 	if (p->array) {
 		deactivate_task(p, this_rq());
 		activate_task(p, rq_dest);
-		if (p->prio < rq_dest->curr->prio)
+		if (TASK_PREEMPTS_CURR(p, rq_dest))
 			resched_task(rq_dest->curr);
 	}
 	p->timestamp = rq_dest->timestamp_last_tick;
@@ -2749,12 +3131,6 @@ out:
 	local_irq_restore(flags);
 }
 
-typedef struct {
-	int cpu;
-	struct completion startup_done;
-	task_t *task;
-} migration_startup_t;
-
 /*
  * migration_thread - this is a highprio system thread that performs
  * thread migration by bumping thread off CPU then 'pushing' onto
@@ -2764,27 +3140,16 @@ static int migration_thread(void * data)
 {
 	/* Marking "param" __user is ok, since we do a set_fs(KERNEL_DS); */
 	struct sched_param __user param = { .sched_priority = MAX_RT_PRIO-1 };
-	migration_startup_t *startup = data;
-	int cpu = startup->cpu;
 	runqueue_t *rq;
+	int cpu = (long)data;
 	int ret;
 
-	startup->task = current;
-	complete(&startup->startup_done);
-	set_current_state(TASK_UNINTERRUPTIBLE);
-	schedule();
-
-	BUG_ON(smp_processor_id() != cpu);
-
-	daemonize("migration/%d", cpu);
-	set_fs(KERNEL_DS);
-
 	ret = setscheduler(0, SCHED_FIFO, &param);
 
-	rq = this_rq();
-	rq->migration_thread = current;
+	rq = cpu_rq(cpu);
+	BUG_ON(rq->migration_thread != current);
 
-	for (;;) {
+	while (!kthread_should_stop()) {
 		struct list_head *head;
 		migration_req_t *req;
 
@@ -2792,7 +3157,13 @@ static int migration_thread(void * data)
 			refrigerator(PF_IOTHREAD);
 
 		spin_lock_irq(&rq->lock);
+		if (rq->active_balance) {
+			active_load_balance(rq, cpu);
+			rq->active_balance = 0;
+		}
+
 		head = &rq->migration_queue;
+
 		current->state = TASK_INTERRUPTIBLE;
 		if (list_empty(head)) {
 			spin_unlock_irq(&rq->lock);
@@ -2803,12 +3174,69 @@ static int migration_thread(void * data)
 		list_del_init(head->next);
 		spin_unlock_irq(&rq->lock);
 
-		move_task_away(req->task,
-			       any_online_cpu(req->task->cpus_allowed));
+		__migrate_task(req->task, req->dest_cpu);
 		complete(&req->done);
 	}
+	return 0;
 }
 
+#ifdef CONFIG_HOTPLUG_CPU
+/* migrate_all_tasks - function to migrate all the tasks from the
+ * current cpu caller must have already scheduled this to the target
+ * cpu via set_cpus_allowed.  Machine is stopped.  */
+void migrate_all_tasks(void)
+{
+	struct task_struct *tsk, *t;
+	int dest_cpu, src_cpu;
+	unsigned int node;
+
+	/* We're nailed to this CPU. */
+	src_cpu = smp_processor_id();
+
+	/* Not required, but here for neatness. */
+	write_lock(&tasklist_lock);
+
+	/* watch out for per node tasks, let's stay on this node */
+	node = cpu_to_node(src_cpu);
+
+	do_each_thread(t, tsk) {
+		cpumask_t mask;
+		if (tsk == current)
+			continue;
+
+		if (task_cpu(tsk) != src_cpu)
+			continue;
+
+		/* Figure out where this task should go (attempting to
+		 * keep it on-node), and check if it can be migrated
+		 * as-is.  NOTE that kernel threads bound to more than
+		 * one online cpu will be migrated. */
+		mask = node_to_cpumask(node);
+		cpus_and(mask, mask, tsk->cpus_allowed);
+		dest_cpu = any_online_cpu(mask);
+		if (dest_cpu == NR_CPUS)
+			dest_cpu = any_online_cpu(tsk->cpus_allowed);
+		if (dest_cpu == NR_CPUS) {
+			cpus_clear(tsk->cpus_allowed);
+			cpus_complement(tsk->cpus_allowed);
+			dest_cpu = any_online_cpu(tsk->cpus_allowed);
+
+			/* Don't tell them about moving exiting tasks
+			   or kernel threads (both mm NULL), since
+			   they never leave kernel. */
+			if (tsk->mm && printk_ratelimit())
+				printk(KERN_INFO "process %d (%s) no "
+				       "longer affine to cpu%d\n",
+				       tsk->pid, tsk->comm, src_cpu);
+		}
+
+		__migrate_task(tsk, dest_cpu);
+	} while_each_thread(t, tsk);
+
+	write_unlock(&tasklist_lock);
+}
+#endif /* CONFIG_HOTPLUG_CPU */
+
 /*
  * migration_call - callback that gets triggered when a CPU is added.
  * Here we can start up the necessary migration thread for the new CPU.
@@ -2816,47 +3244,48 @@ static int migration_thread(void * data)
 static int migration_call(struct notifier_block *nfb, unsigned long action,
 			  void *hcpu)
 {
-	long cpu = (long)hcpu;
-	migration_startup_t startup;
+	int cpu = (long)hcpu;
+	struct task_struct *p;
 
 	switch (action) {
+	case CPU_UP_PREPARE:
+		p = kthread_create(migration_thread, hcpu, "migration/%d",cpu);
+		if (IS_ERR(p))
+			return NOTIFY_BAD;
+		kthread_bind(p, cpu);
+		cpu_rq(cpu)->migration_thread = p;
+		break;
 	case CPU_ONLINE:
-
-		printk("Starting migration thread for cpu %li\n", cpu);
-
-		startup.cpu = cpu;
-		startup.task = NULL;
-		init_completion(&startup.startup_done);
-
-		kernel_thread(migration_thread, &startup, CLONE_KERNEL);
-		wait_for_completion(&startup.startup_done);
-		wait_task_inactive(startup.task);
-
-		startup.task->thread_info->cpu = cpu;
-		startup.task->cpus_allowed = cpumask_of_cpu(cpu);
-
-		wake_up_process(startup.task);
-
-		while (!cpu_rq(cpu)->migration_thread)
-			yield();
-
+		/* Strictly unneccessary, as first user will wake it. */
+		wake_up_process(cpu_rq(cpu)->migration_thread);
 		break;
+#ifdef CONFIG_HOTPLUG_CPU
+	case CPU_UP_CANCELED:
+		/* Unbind it from offline cpu so it can run.  Fall thru. */
+		kthread_bind(cpu_rq(cpu)->migration_thread,smp_processor_id());
+	case CPU_DEAD:
+		kthread_stop(cpu_rq(cpu)->migration_thread);
+		cpu_rq(cpu)->migration_thread = NULL;
+ 		BUG_ON(cpu_rq(cpu)->nr_running != 0);
+ 		break;
+#endif
 	}
 	return NOTIFY_OK;
 }
 
-static struct notifier_block migration_notifier
-			= { .notifier_call = &migration_call };
+static struct notifier_block __devinitdata migration_notifier = {
+	.notifier_call = migration_call,
+};
 
-__init int migration_init(void)
+int __init migration_init(void)
 {
+	void *cpu = (void *)(long)smp_processor_id();
 	/* Start one for boot CPU. */
-	migration_call(&migration_notifier, CPU_ONLINE,
-		       (void *)(long)smp_processor_id());
+	migration_call(&migration_notifier, CPU_UP_PREPARE, cpu);
+	migration_call(&migration_notifier, CPU_ONLINE, cpu);
 	register_cpu_notifier(&migration_notifier);
 	return 0;
 }
-
 #endif
 
 /*
@@ -2874,47 +3303,222 @@ __init int migration_init(void)
 spinlock_t kernel_flag __cacheline_aligned_in_smp = SPIN_LOCK_UNLOCKED;
 EXPORT_SYMBOL(kernel_flag);
 
-static void kstat_init_cpu(int cpu)
+#ifdef CONFIG_SMP
+#ifdef ARCH_HAS_SCHED_DOMAIN
+extern void __init arch_init_sched_domains(void);
+#else
+static struct sched_group sched_group_cpus[NR_CPUS];
+#ifdef CONFIG_NUMA
+static struct sched_group sched_group_nodes[MAX_NUMNODES];
+DEFINE_PER_CPU(struct sched_domain, node_domains);
+static void __init arch_init_sched_domains(void)
 {
-	/* Add any initialisation to kstat here */
-	/* Useful when cpu offlining logic is added.. */
+	int i;
+	struct sched_group *first_node = NULL, *last_node = NULL;
+
+	/* Set up domains */
+	for_each_cpu(i) {
+		int node = cpu_to_node(i);
+		cpumask_t nodemask = node_to_cpumask(node);
+		struct sched_domain *node_domain = &per_cpu(node_domains, i);
+		struct sched_domain *cpu_domain = cpu_sched_domain(i);
+
+		*node_domain = SD_NODE_INIT;
+		node_domain->span = cpu_possible_map;
+
+		*cpu_domain = SD_CPU_INIT;
+		cpus_and(cpu_domain->span, nodemask, cpu_possible_map);
+		cpu_domain->parent = node_domain;
+	}
+
+	/* Set up groups */
+	for (i = 0; i < MAX_NUMNODES; i++) {
+		struct sched_group *first_cpu = NULL, *last_cpu = NULL;
+		int j;
+		cpumask_t nodemask;
+		struct sched_group *node = &sched_group_nodes[i];
+		cpumask_t tmp = node_to_cpumask(i);
+
+		cpus_and(nodemask, tmp, cpu_possible_map);
+
+		if (cpus_empty(nodemask))
+			continue;
+
+		node->cpumask = nodemask;
+		node->cpu_power = SCHED_LOAD_SCALE * cpus_weight(node->cpumask);
+
+		for_each_cpu_mask(j, node->cpumask) {
+			struct sched_group *cpu = &sched_group_cpus[j];
+
+			cpus_clear(cpu->cpumask);
+			cpu_set(j, cpu->cpumask);
+			cpu->cpu_power = SCHED_LOAD_SCALE;
+
+			if (!first_cpu)
+				first_cpu = cpu;
+			if (last_cpu)
+				last_cpu->next = cpu;
+			last_cpu = cpu;
+		}
+		last_cpu->next = first_cpu;
+
+		if (!first_node)
+			first_node = node;
+		if (last_node)
+			last_node->next = node;
+		last_node = node;
+	}
+	last_node->next = first_node;
+
+	mb();
+	for_each_cpu(i) {
+		struct sched_domain *node_domain = &per_cpu(node_domains, i);
+		struct sched_domain *cpu_domain = cpu_sched_domain(i);
+		node_domain->groups = &sched_group_nodes[cpu_to_node(i)];
+		cpu_domain->groups = &sched_group_cpus[i];
+	}
 }
 
-static int __devinit kstat_cpu_notify(struct notifier_block *self,
-				      unsigned long action, void *hcpu)
+#else /* CONFIG_NUMA */
+static void __init arch_init_sched_domains(void)
 {
-	int cpu = (unsigned long)hcpu;
-	switch(action) {
-	case CPU_UP_PREPARE:
-		kstat_init_cpu(cpu);
-		break;
-	default:
-		break;
+	int i;
+	struct sched_group *first_cpu = NULL, *last_cpu = NULL;
+
+	/* Set up domains */
+	for_each_cpu(i) {
+		struct sched_domain *cpu_domain = cpu_sched_domain(i);
+
+		*cpu_domain = SD_CPU_INIT;
+		cpu_domain->span = cpu_possible_map;
+	}
+
+	/* Set up CPU groups */
+	for_each_cpu_mask(i, cpu_possible_map) {
+		struct sched_group *cpu = &sched_group_cpus[i];
+
+		cpus_clear(cpu->cpumask);
+		cpu_set(i, cpu->cpumask);
+		cpu->cpu_power = SCHED_LOAD_SCALE;
+
+		if (!first_cpu)
+			first_cpu = cpu;
+		if (last_cpu)
+			last_cpu->next = cpu;
+		last_cpu = cpu;
+	}
+	last_cpu->next = first_cpu;
+
+	mb();
+	for_each_cpu(i) {
+		struct sched_domain *cpu_domain = cpu_sched_domain(i);
+		cpu_domain->groups = &sched_group_cpus[i];
 	}
-	return NOTIFY_OK;
 }
 
-static struct notifier_block __devinitdata kstat_nb = {
-	.notifier_call	= kstat_cpu_notify,
-	.next		= NULL,
-};
+#endif /* CONFIG_NUMA */
+#endif /* ARCH_HAS_SCHED_DOMAIN */
 
-__init static void init_kstat(void)
+#undef SCHED_DOMAIN_DEBUG
+#ifdef SCHED_DOMAIN_DEBUG
+void sched_domain_debug(void)
 {
-	kstat_cpu_notify(&kstat_nb, (unsigned long)CPU_UP_PREPARE,
-			 (void *)(long)smp_processor_id());
-	register_cpu_notifier(&kstat_nb);
+	int i;
+
+	for_each_cpu(i) {
+		int level = 0;
+		struct sched_domain *cpu_domain = cpu_sched_domain(i);
+
+		printk(KERN_DEBUG "CPU%d: %s\n",
+				i, (cpu_online(i) ? " online" : "offline"));
+
+		do {
+			int j;
+			char str[NR_CPUS];
+			struct sched_group *group = cpu_domain->groups;
+			cpumask_t groupmask, tmp;
+
+			cpumask_snprintf(str, NR_CPUS, cpu_domain->span);
+			cpus_clear(groupmask);
+
+			printk(KERN_DEBUG);
+			for (j = 0; j < level + 1; j++)
+				printk(" ");
+			printk("domain %d: span %s\n", level, str);
+
+			if (!cpu_isset(i, cpu_domain->span))
+				printk(KERN_DEBUG "ERROR domain->span does not contain CPU%d\n", i);
+			if (!cpu_isset(i, group->cpumask))
+				printk(KERN_DEBUG "ERROR domain->groups does not contain CPU%d\n", i);
+
+			printk(KERN_DEBUG);
+			for (j = 0; j < level + 2; j++)
+				printk(" ");
+			printk("groups:");
+			do {
+				if (group == NULL) {
+					printk(" ERROR: NULL");
+					break;
+				}
+
+				if (cpus_weight(group->cpumask) == 0)
+					printk(" ERROR empty group:");
+
+				cpus_and(tmp, groupmask, group->cpumask);
+				if (cpus_weight(tmp) > 0)
+					printk(" ERROR repeated CPUs:");
+
+				cpus_or(groupmask, groupmask, group->cpumask);
+
+				cpumask_snprintf(str, NR_CPUS, group->cpumask);
+				printk(" %s", str);
+
+				group = group->next;
+			} while (group != cpu_domain->groups);
+			printk("\n");
+
+			if (!cpus_equal(cpu_domain->span, groupmask))
+				printk(KERN_DEBUG "ERROR groups don't span domain->span\n");
+
+			level++;
+			cpu_domain = cpu_domain->parent;
+
+			if (cpu_domain) {
+				cpus_and(tmp, groupmask, cpu_domain->span);
+				if (!cpus_equal(tmp, groupmask))
+					printk(KERN_DEBUG "ERROR parent span is not a superset of domain->span\n");
+			}
+
+		} while (cpu_domain);
+	}
+}
+#else
+#define sched_domain_debug() {}
+#endif
+
+void __init sched_init_smp(void)
+{
+	arch_init_sched_domains();
+	sched_domain_debug();
 }
+#else
+void __init sched_init_smp(void)
+{
+}
+#endif /* CONFIG_SMP */
 
 void __init sched_init(void)
 {
 	runqueue_t *rq;
 	int i, j, k;
 
-	/* Init the kstat counters */
-	init_kstat();
 	for (i = 0; i < NR_CPUS; i++) {
 		prio_array_t *array;
+#ifdef CONFIG_SMP
+		struct sched_domain *domain;
+		domain = cpu_sched_domain(i);
+		memset(domain, 0, sizeof(struct sched_domain));
+#endif
 
 		rq = cpu_rq(i);
 		rq->active = rq->arrays;
@@ -2924,7 +3528,6 @@ void __init sched_init(void)
 		spin_lock_init(&rq->lock);
 		INIT_LIST_HEAD(&rq->migration_queue);
 		atomic_set(&rq->nr_iowait, 0);
-		nr_running_init(rq);
 
 		for (j = 0; j < 2; j++) {
 			array = rq->arrays + j;
--- diff/kernel/signal.c	2003-11-25 15:24:59.000000000 +0000
+++ source/kernel/signal.c	2004-02-23 13:56:48.000000000 +0000
@@ -24,6 +24,7 @@
 #include <linux/binfmts.h>
 #include <linux/security.h>
 #include <linux/ptrace.h>
+#include <linux/compat_siginfo.h>
 #include <asm/param.h>
 #include <asm/uaccess.h>
 #include <asm/siginfo.h>
@@ -2006,6 +2007,12 @@ int copy_siginfo_to_user(siginfo_t __use
 	if (from->si_code < 0)
 		return __copy_to_user(to, from, sizeof(siginfo_t))
 			? -EFAULT : 0;
+
+	/* Use compat_siginfo_t with 32-bit signals */
+	if(is_compat_task(current)){
+		return compat_copy_siginfo_to_user((compat_siginfo_t __user *)to,from);
+	}
+
 	/*
 	 * If you change siginfo_t structure, please be sure
 	 * this code is fixed accordingly.
--- diff/kernel/softirq.c	2003-10-09 09:47:34.000000000 +0100
+++ source/kernel/softirq.c	2004-02-23 13:56:48.000000000 +0000
@@ -14,6 +14,7 @@
 #include <linux/notifier.h>
 #include <linux/percpu.h>
 #include <linux/cpu.h>
+#include <linux/kthread.h>
 
 /*
    - No shared variables, all the data are CPU local.
@@ -117,11 +118,22 @@ EXPORT_SYMBOL(do_softirq);
 
 void local_bh_enable(void)
 {
+	if (in_irq()) {
+		printk("local_bh_enable() was called in hard irq context.   "
+			"This is probably a bug\n");
+		dump_stack();
+	}
+
 	__local_bh_enable();
-	WARN_ON(irqs_disabled());
-	if (unlikely(!in_interrupt() &&
-		     local_softirq_pending()))
+	if (unlikely(!in_interrupt() && local_softirq_pending())) {
+		if (irqs_disabled()) {
+			printk("local_bh_enable() was called with local "
+				"interrupts disabled.  This is probably a"
+				" bug\n");
+			dump_stack();
+		}
 		invoke_softirq();
+	}
 	preempt_check_resched();
 }
 EXPORT_SYMBOL(local_bh_enable);
@@ -299,86 +311,136 @@ void tasklet_kill(struct tasklet_struct 
 
 EXPORT_SYMBOL(tasklet_kill);
 
-static void tasklet_init_cpu(int cpu)
-{
-	per_cpu(tasklet_vec, cpu).list = NULL;
-	per_cpu(tasklet_hi_vec, cpu).list = NULL;
-}
-	
-static int tasklet_cpu_notify(struct notifier_block *self, 
-				unsigned long action, void *hcpu)
-{
-	long cpu = (long)hcpu;
-	switch(action) {
-	case CPU_UP_PREPARE:
-		tasklet_init_cpu(cpu);
-		break;
-	default:
-		break;
-	}
-	return 0;
-}
-
-static struct notifier_block tasklet_nb = {
-	.notifier_call	= tasklet_cpu_notify,
-	.next		= NULL,
-};
-
 void __init softirq_init(void)
 {
 	open_softirq(TASKLET_SOFTIRQ, tasklet_action, NULL);
 	open_softirq(HI_SOFTIRQ, tasklet_hi_action, NULL);
-	tasklet_cpu_notify(&tasklet_nb, (unsigned long)CPU_UP_PREPARE,
-				(void *)(long)smp_processor_id());
-	register_cpu_notifier(&tasklet_nb);
 }
 
 static int ksoftirqd(void * __bind_cpu)
 {
-	int cpu = (int) (long) __bind_cpu;
-
-	daemonize("ksoftirqd/%d", cpu);
 	set_user_nice(current, 19);
 	current->flags |= PF_IOTHREAD;
 
-	/* Migrate to the right CPU */
-	set_cpus_allowed(current, cpumask_of_cpu(cpu));
-	BUG_ON(smp_processor_id() != cpu);
+	set_current_state(TASK_INTERRUPTIBLE);
 
-	__set_current_state(TASK_INTERRUPTIBLE);
-	mb();
-
-	__get_cpu_var(ksoftirqd) = current;
-
-	for (;;) {
+	while (!kthread_should_stop()) {
 		if (!local_softirq_pending())
 			schedule();
 
 		__set_current_state(TASK_RUNNING);
 
 		while (local_softirq_pending()) {
+			/* Preempt disable stops cpu going offline.
+			   If already offline, we'll be on wrong CPU:
+			   don't process */
+			preempt_disable();
+			if (cpu_is_offline((long)__bind_cpu))
+				goto wait_to_die;
 			do_softirq();
+			preempt_enable();
 			cond_resched();
 		}
 
 		__set_current_state(TASK_INTERRUPTIBLE);
 	}
+	return 0;
+
+wait_to_die:
+	preempt_enable();
+	/* Wait for kthread_stop */
+	while (!kthread_should_stop()) {
+		__set_current_state(TASK_INTERRUPTIBLE);
+		schedule();
+	}
+	return 0;
 }
 
+#ifdef CONFIG_HOTPLUG_CPU
+/*
+ * tasklet_kill_immediate is called to remove a tasklet which can already be
+ * scheduled for execution on @cpu.
+ *
+ * Unlike tasklet_kill, this function removes the tasklet
+ * _immediately_, even if the tasklet is in TASKLET_STATE_SCHED state.
+ *
+ * When this function is called, @cpu must be in the CPU_DEAD state.
+ */
+void tasklet_kill_immediate(struct tasklet_struct *t, unsigned int cpu)
+{
+	struct tasklet_struct **i;
+
+	BUG_ON(cpu_online(cpu));
+	BUG_ON(test_bit(TASKLET_STATE_RUN, &t->state));
+
+	if (!test_bit(TASKLET_STATE_SCHED, &t->state))
+		return;
+
+	/* CPU is dead, so no lock needed. */
+	for (i = &per_cpu(tasklet_vec, cpu).list; *i; i = &(*i)->next) {
+		if (*i == t) {
+			*i = t->next;
+			return;
+		}
+	}
+	BUG();
+}
+
+static void takeover_tasklets(unsigned int cpu)
+{
+	struct tasklet_struct **i;
+
+	/* CPU is dead, so no lock needed. */
+	local_irq_disable();
+
+	/* Find end, append list for that CPU. */
+	for (i = &__get_cpu_var(tasklet_vec).list; *i; i = &(*i)->next);
+	*i = per_cpu(tasklet_vec, cpu).list;
+	per_cpu(tasklet_vec, cpu).list = NULL;
+	raise_softirq_irqoff(TASKLET_SOFTIRQ);
+
+	for (i = &__get_cpu_var(tasklet_hi_vec).list; *i; i = &(*i)->next);
+	*i = per_cpu(tasklet_hi_vec, cpu).list;
+	per_cpu(tasklet_hi_vec, cpu).list = NULL;
+	raise_softirq_irqoff(HI_SOFTIRQ);
+
+	local_irq_enable();
+}
+#endif /* CONFIG_HOTPLUG_CPU */
+
 static int __devinit cpu_callback(struct notifier_block *nfb,
 				  unsigned long action,
 				  void *hcpu)
 {
 	int hotcpu = (unsigned long)hcpu;
+	struct task_struct *p;
 
-	if (action == CPU_ONLINE) {
-		if (kernel_thread(ksoftirqd, hcpu, CLONE_KERNEL) < 0) {
+	switch (action) {
+	case CPU_UP_PREPARE:
+		BUG_ON(per_cpu(tasklet_vec, hotcpu).list);
+		BUG_ON(per_cpu(tasklet_hi_vec, hotcpu).list);
+		p = kthread_create(ksoftirqd, hcpu, "ksoftirqd/%d", hotcpu);
+		if (IS_ERR(p)) {
 			printk("ksoftirqd for %i failed\n", hotcpu);
 			return NOTIFY_BAD;
 		}
-
-		while (!per_cpu(ksoftirqd, hotcpu))
-			yield();
+		kthread_bind(p, hotcpu);
+  		per_cpu(ksoftirqd, hotcpu) = p;
+ 		break;
+	case CPU_ONLINE:
+		wake_up_process(per_cpu(ksoftirqd, hotcpu));
+		break;
+#ifdef CONFIG_HOTPLUG_CPU
+	case CPU_UP_CANCELED:
+		/* Unbind so it can run.  Fall thru. */
+		kthread_bind(per_cpu(ksoftirqd, hotcpu), smp_processor_id());
+	case CPU_DEAD:
+		p = per_cpu(ksoftirqd, hotcpu);
+		per_cpu(ksoftirqd, hotcpu) = NULL;
+		kthread_stop(p);
+		takeover_tasklets(hotcpu);
+		break;
+#endif /* CONFIG_HOTPLUG_CPU */
  	}
 	return NOTIFY_OK;
 }
@@ -389,7 +451,9 @@ static struct notifier_block __devinitda
 
 __init int spawn_ksoftirqd(void)
 {
-	cpu_callback(&cpu_nfb, CPU_ONLINE, (void *)(long)smp_processor_id());
+	void *cpu = (void *)(long)smp_processor_id();
+	cpu_callback(&cpu_nfb, CPU_UP_PREPARE, cpu);
+	cpu_callback(&cpu_nfb, CPU_ONLINE, cpu);
 	register_cpu_notifier(&cpu_nfb);
 	return 0;
 }
--- diff/kernel/sys.c	2004-02-18 08:54:13.000000000 +0000
+++ source/kernel/sys.c	2004-02-23 13:56:48.000000000 +0000
@@ -249,6 +249,18 @@ cond_syscall(compat_sys_futex)
 cond_syscall(sys_epoll_create)
 cond_syscall(sys_epoll_ctl)
 cond_syscall(sys_epoll_wait)
+cond_syscall(sys_semget)
+cond_syscall(sys_semop)
+cond_syscall(sys_semtimedop)
+cond_syscall(sys_semctl)
+cond_syscall(sys_msgget)
+cond_syscall(sys_msgsnd)
+cond_syscall(sys_msgrcv)
+cond_syscall(sys_msgctl)
+cond_syscall(sys_shmget)
+cond_syscall(sys_shmat)
+cond_syscall(sys_shmdt)
+cond_syscall(sys_shmctl)
 
 /* arch-specific weak syscall entries */
 cond_syscall(sys_pciconfig_read)
@@ -1089,10 +1101,178 @@ out:
 /*
  * Supplementary group IDs
  */
-asmlinkage long sys_getgroups(int gidsetsize, gid_t __user *grouplist)
+
+/* init to 2 - one for init_task, one to ensure it is never freed */
+struct group_info init_groups = { .usage = ATOMIC_INIT(2) };
+
+struct group_info *groups_alloc(int gidsetsize)
 {
+	struct group_info *group_info;
+	int nblocks;
 	int i;
-	
+
+	nblocks = (gidsetsize/NGROUPS_PER_BLOCK) +
+	    (gidsetsize%NGROUPS_PER_BLOCK?1:0);
+	group_info = kmalloc(sizeof(*group_info) + nblocks*sizeof(gid_t *),
+	    GFP_USER);
+	if (!group_info)
+		return NULL;
+	group_info->ngroups = gidsetsize;
+	group_info->nblocks = nblocks;
+	atomic_set(&group_info->usage, 1);
+
+	if (gidsetsize <= NGROUPS_SMALL) {
+		group_info->blocks[0] = group_info->small_block;
+	} else {
+		for (i = 0; i < nblocks; i++) {
+			gid_t *b;
+			b = (void *)__get_free_page(GFP_USER);
+			if (!b)
+				goto out_undo_partial_alloc;
+			group_info->blocks[i] = b;
+		}
+	}
+	return group_info;
+
+out_undo_partial_alloc:
+	while (--i >= 0) {
+		free_page((unsigned long)group_info->blocks[i]);
+	}
+	kfree(group_info);
+	return NULL;
+}
+
+EXPORT_SYMBOL(groups_alloc);
+
+void groups_free(struct group_info *group_info)
+{
+	if (group_info->blocks[0] != group_info->small_block) {
+		int i;
+		for (i = 0; i < group_info->nblocks; i++)
+			free_page((unsigned long)group_info->blocks[i]);
+	}
+	kfree(group_info);
+}
+
+EXPORT_SYMBOL(groups_free);
+
+/* export the group_info to a user-space array */
+static int groups_to_user(gid_t __user *grouplist,
+    struct group_info *group_info)
+{
+	int i;
+	int count = group_info->ngroups;
+
+	for (i = 0; i < group_info->nblocks; i++) {
+		int cp_count = min(NGROUPS_PER_BLOCK, count);
+		int off = i * NGROUPS_PER_BLOCK;
+		int len = cp_count * sizeof(*grouplist);
+
+		if (copy_to_user(grouplist+off, group_info->blocks[i], len))
+			return -EFAULT;
+
+		count -= cp_count;
+	}
+	return 0;
+}
+
+/* fill a group_info from a user-space array - it must be allocated already */
+static int groups_from_user(struct group_info *group_info,
+    gid_t __user *grouplist)
+ {
+	int i;
+	int count = group_info->ngroups;
+
+	for (i = 0; i < group_info->nblocks; i++) {
+		int cp_count = min(NGROUPS_PER_BLOCK, count);
+		int off = i * NGROUPS_PER_BLOCK;
+		int len = cp_count * sizeof(*grouplist);
+
+		if (copy_from_user(group_info->blocks[i], grouplist+off, len))
+			return -EFAULT;
+
+		count -= cp_count;
+	}
+	return 0;
+}
+
+/* a simple shell-metzner sort */
+static void groups_sort(struct group_info *group_info)
+{
+	int base, max, stride;
+	int gidsetsize = group_info->ngroups;
+
+	for (stride = 1; stride < gidsetsize; stride = 3 * stride + 1)
+		; /* nothing */
+	stride /= 3;
+
+	while (stride) {
+		max = gidsetsize - stride;
+		for (base = 0; base < max; base++) {
+			int left = base;
+			int right = left + stride;
+			gid_t tmp = GROUP_AT(group_info, right);
+
+			while (left >= 0 && GROUP_AT(group_info, left) > tmp) {
+				GROUP_AT(group_info, right) =
+				    GROUP_AT(group_info, left);
+				right = left;
+				left -= stride;
+			}
+			GROUP_AT(group_info, right) = tmp;
+		}
+		stride /= 3;
+	}
+}
+
+/* a simple bsearch */
+static int groups_search(struct group_info *group_info, gid_t grp)
+{
+	int left, right;
+
+	if (!group_info)
+		return 0;
+
+	left = 0;
+	right = group_info->ngroups;
+	while (left < right) {
+		int mid = (left+right)/2;
+		int cmp = grp - GROUP_AT(group_info, mid);
+		if (cmp > 0)
+			left = mid + 1;
+		else if (cmp < 0)
+			right = mid;
+		else
+			return 1;
+	}
+	return 0;
+}
+
+/* validate and set current->group_info */
+int set_current_groups(struct group_info *group_info)
+{
+	int retval;
+	struct group_info *old_info;
+
+	retval = security_task_setgroups(group_info);
+	if (retval)
+		return retval;
+
+	groups_sort(group_info);
+	get_group_info(group_info);
+	old_info = current->group_info;
+	current->group_info = group_info;
+	put_group_info(old_info);
+
+	return 0;
+}
+
+EXPORT_SYMBOL(set_current_groups);
+
+asmlinkage long sys_getgroups(int gidsetsize, gid_t __user *grouplist)
+{
+	int i = 0;
+
 	/*
 	 *	SMP: Nobody else can change our grouplist. Thus we are
 	 *	safe.
@@ -1100,54 +1280,52 @@ asmlinkage long sys_getgroups(int gidset
 
 	if (gidsetsize < 0)
 		return -EINVAL;
-	i = current->ngroups;
+
+	get_group_info(current->group_info);
+	i = current->group_info->ngroups;
 	if (gidsetsize) {
-		if (i > gidsetsize)
-			return -EINVAL;
-		if (copy_to_user(grouplist, current->groups, sizeof(gid_t)*i))
-			return -EFAULT;
+		if (i > gidsetsize) {
+			i = -EINVAL;
+			goto out;
+		}
+		if (groups_to_user(grouplist, current->group_info)) {
+			i = -EFAULT;
+			goto out;
+		}
 	}
+out:
+	put_group_info(current->group_info);
 	return i;
 }
 
 /*
- *	SMP: Our groups are not shared. We can copy to/from them safely
+ *	SMP: Our groups are copy-on-write. We can set them safely
  *	without another task interfering.
  */
  
 asmlinkage long sys_setgroups(int gidsetsize, gid_t __user *grouplist)
 {
-	gid_t groups[NGROUPS];
+	struct group_info *group_info;
 	int retval;
 
 	if (!capable(CAP_SETGID))
 		return -EPERM;
-	if ((unsigned) gidsetsize > NGROUPS)
+	if ((unsigned)gidsetsize > NGROUPS_MAX)
 		return -EINVAL;
-	if (copy_from_user(groups, grouplist, gidsetsize * sizeof(gid_t)))
-		return -EFAULT;
-	retval = security_task_setgroups(gidsetsize, groups);
-	if (retval)
+
+	group_info = groups_alloc(gidsetsize);
+	if (!group_info)
+		return -ENOMEM;
+	retval = groups_from_user(group_info, grouplist);
+	if (retval) {
+		put_group_info(group_info);
 		return retval;
-	memcpy(current->groups, groups, gidsetsize * sizeof(gid_t));
-	current->ngroups = gidsetsize;
-	return 0;
-}
+	}
 
-static int supplemental_group_member(gid_t grp)
-{
-	int i = current->ngroups;
+	retval = set_current_groups(group_info);
+	put_group_info(group_info);
 
-	if (i) {
-		gid_t *groups = current->groups;
-		do {
-			if (*groups == grp)
-				return 1;
-			groups++;
-			i--;
-		} while (i);
-	}
-	return 0;
+	return retval;
 }
 
 /*
@@ -1156,8 +1334,11 @@ static int supplemental_group_member(gid
 int in_group_p(gid_t grp)
 {
 	int retval = 1;
-	if (grp != current->fsgid)
-		retval = supplemental_group_member(grp);
+	if (grp != current->fsgid) {
+		get_group_info(current->group_info);
+		retval = groups_search(current->group_info, grp);
+		put_group_info(current->group_info);
+	}
 	return retval;
 }
 
@@ -1166,8 +1347,11 @@ EXPORT_SYMBOL(in_group_p);
 int in_egroup_p(gid_t grp)
 {
 	int retval = 1;
-	if (grp != current->egid)
-		retval = supplemental_group_member(grp);
+	if (grp != current->egid) {
+		get_group_info(current->group_info);
+		retval = groups_search(current->group_info, grp);
+		put_group_info(current->group_info);
+	}
 	return retval;
 }
 
--- diff/kernel/sysctl.c	2004-02-18 08:54:13.000000000 +0000
+++ source/kernel/sysctl.c	2004-02-23 13:56:48.000000000 +0000
@@ -38,6 +38,7 @@
 #include <linux/security.h>
 #include <linux/initrd.h>
 #include <linux/times.h>
+#include <linux/limits.h>
 #include <asm/uaccess.h>
 
 #ifdef CONFIG_ROOT_NFS
@@ -68,6 +69,8 @@ extern int printk_ratelimit_burst;
 static int maxolduid = 65535;
 static int minolduid;
 
+static int ngroups_max = NGROUPS_MAX;
+
 #ifdef CONFIG_KMOD
 extern char modprobe_path[];
 #endif
@@ -133,6 +136,9 @@ static ctl_table fs_table[];
 static ctl_table debug_table[];
 static ctl_table dev_table[];
 extern ctl_table random_table[];
+#ifdef CONFIG_UNIX98_PTYS
+extern ctl_table pty_table[];
+#endif
 
 /* /proc declarations: */
 
@@ -518,6 +524,14 @@ static ctl_table kern_table[] = {
 		.mode		= 0555,
 		.child		= random_table,
 	},
+#ifdef CONFIG_UNIX98_PTYS
+	{
+		.ctl_name	= KERN_PTY,
+		.procname	= "pty",
+		.mode		= 0555,
+		.child		= pty_table,
+	},
+#endif
 	{
 		.ctl_name	= KERN_OVERFLOWUID,
 		.procname	= "overflowuid",
@@ -593,6 +607,14 @@ static ctl_table kern_table[] = {
 		.mode		= 0644,
 		.proc_handler	= &proc_dointvec,
 	},
+	{
+		.ctl_name	= KERN_NGROUPS_MAX,
+		.procname	= "ngroups_max",
+		.data		= &ngroups_max,
+		.maxlen		= sizeof (int),
+		.mode		= 0444,
+		.proc_handler	= &proc_dointvec,
+	},
 	{ .ctl_name = 0 }
 };
 
@@ -714,6 +736,26 @@ static ctl_table vm_table[] = {
 		.strategy	= &sysctl_intvec,
 		.extra1		= &zero,
 	},
+	{
+		.ctl_name	= VM_LAPTOP_MODE,
+		.procname	= "laptop_mode",
+		.data		= &laptop_mode,
+		.maxlen		= sizeof(laptop_mode),
+		.mode		= 0644,
+		.proc_handler	= &proc_dointvec,
+		.strategy	= &sysctl_intvec,
+		.extra1		= &zero,
+	},
+	{
+		.ctl_name	= VM_BLOCK_DUMP,
+		.procname	= "block_dump",
+		.data		= &block_dump,
+		.maxlen		= sizeof(block_dump),
+		.mode		= 0644,
+		.proc_handler	= &proc_dointvec,
+		.strategy	= &sysctl_intvec,
+		.extra1		= &zero,
+	},
 	{ .ctl_name = 0 }
 };
 
@@ -808,6 +850,22 @@ static ctl_table fs_table[] = {
 		.mode		= 0644,
 		.proc_handler	= &proc_dointvec,
 	},
+	{
+		.ctl_name	= FS_AIO_NR,
+		.procname	= "aio-nr",
+		.data		= &aio_nr,
+		.maxlen		= sizeof(aio_nr),
+		.mode		= 0444,
+		.proc_handler	= &proc_dointvec,
+	},
+	{
+		.ctl_name	= FS_AIO_MAX_NR,
+		.procname	= "aio-max-nr",
+		.data		= &aio_max_nr,
+		.maxlen		= sizeof(aio_max_nr),
+		.mode		= 0644,
+		.proc_handler	= &proc_dointvec,
+	},
 	{ .ctl_name = 0 }
 };
 
@@ -861,27 +919,13 @@ int do_sysctl(int __user *name, int nlen
 asmlinkage long sys_sysctl(struct __sysctl_args __user *args)
 {
 	struct __sysctl_args tmp;
-	int name[2];
 	int error;
 
 	if (copy_from_user(&tmp, args, sizeof(tmp)))
 		return -EFAULT;
-	
-	if (tmp.nlen != 2 || copy_from_user(name, tmp.name, sizeof(name)) ||
-	    name[0] != CTL_KERN || name[1] != KERN_VERSION) { 
-		int i;
-		printk(KERN_INFO "%s: numerical sysctl ", current->comm); 
-		for (i = 0; i < tmp.nlen; i++) {
-			int n;
-			
-			if (get_user(n, tmp.name+i)) {
-				printk("? ");
-			} else {
-				printk("%d ", n);
-			}
-		}
-		printk("is obsolete.\n");
-	} 
+
+	if (tmp.nlen < 0 || tmp.nlen > CTL_MAXNAME)
+		return -EINVAL;
 
 	lock_kernel();
 	error = do_sysctl(tmp.name, tmp.nlen, tmp.oldval, tmp.oldlenp,
@@ -2008,7 +2052,7 @@ int sysctl_jiffies(ctl_table *table, int
 #else /* CONFIG_SYSCTL */
 
 
-extern asmlinkage long sys_sysctl(struct __sysctl_args __user *args)
+asmlinkage long sys_sysctl(struct __sysctl_args __user *args)
 {
 	return -ENOSYS;
 }
--- diff/kernel/timer.c	2004-02-09 10:36:12.000000000 +0000
+++ source/kernel/timer.c	2004-02-23 13:56:48.000000000 +0000
@@ -971,6 +971,13 @@ static void process_timeout(unsigned lon
 	wake_up_process((task_t *)__data);
 }
 
+static void futex_timeout(unsigned long __data)
+{
+	current->flags |= PF_FUTEX_DEBUG;
+	wake_up_process((task_t *)__data);
+	current->flags &= ~PF_FUTEX_DEBUG;
+}
+
 /**
  * schedule_timeout - sleep until timeout
  * @timeout: timeout value in jiffies
@@ -1037,7 +1044,10 @@ signed long schedule_timeout(signed long
 	init_timer(&timer);
 	timer.expires = expire;
 	timer.data = (unsigned long) current;
-	timer.function = process_timeout;
+	if (current->flags & PF_FUTEX_DEBUG)
+		timer.function = futex_timeout;
+	else
+		timer.function = process_timeout;
 
 	add_timer(&timer);
 	schedule();
@@ -1223,7 +1233,73 @@ static void __devinit init_timers_cpu(in
 
 	base->timer_jiffies = jiffies;
 }
-	
+
+#ifdef CONFIG_HOTPLUG_CPU
+static int migrate_timer_list(tvec_base_t *new_base, struct list_head *head)
+{
+	struct timer_list *timer;
+
+	while (!list_empty(head)) {
+		timer = list_entry(head->next, struct timer_list, entry);
+		/* We're locking backwards from __mod_timer order here,
+		   beware deadlock. */
+		if (!spin_trylock(&timer->lock))
+			return 0;
+		list_del(&timer->entry);
+		internal_add_timer(new_base, timer);
+		timer->base = new_base;
+		spin_unlock(&timer->lock);
+	}
+	return 1;
+}
+
+static void __devinit migrate_timers(int cpu)
+{
+	tvec_base_t *old_base;
+	tvec_base_t *new_base;
+	int i;
+
+	BUG_ON(cpu_online(cpu));
+	old_base = &per_cpu(tvec_bases, cpu);
+	new_base = &get_cpu_var(tvec_bases);
+
+	local_irq_disable();
+again:
+	/* Prevent deadlocks via ordering by old_base < new_base. */
+	if (old_base < new_base) {
+		spin_lock(&new_base->lock);
+		spin_lock(&old_base->lock);
+	} else {
+		spin_lock(&old_base->lock);
+		spin_lock(&new_base->lock);
+	}
+
+	if (old_base->running_timer)
+		BUG();
+	for (i = 0; i < TVR_SIZE; i++)
+		if (!migrate_timer_list(new_base, old_base->tv1.vec + i))
+			goto unlock_again;
+	for (i = 0; i < TVN_SIZE; i++)
+		if (!migrate_timer_list(new_base, old_base->tv2.vec + i)
+		    || !migrate_timer_list(new_base, old_base->tv3.vec + i)
+		    || !migrate_timer_list(new_base, old_base->tv4.vec + i)
+		    || !migrate_timer_list(new_base, old_base->tv5.vec + i))
+			goto unlock_again;
+	spin_unlock(&old_base->lock);
+	spin_unlock(&new_base->lock);
+	local_irq_enable();
+	put_cpu_var(tvec_bases);
+	return;
+
+unlock_again:
+	/* Avoid deadlock with __mod_timer, by backing off. */
+	spin_unlock(&old_base->lock);
+	spin_unlock(&new_base->lock);
+	cpu_relax();
+	goto again;
+}
+#endif /* CONFIG_HOTPLUG_CPU */
+
 static int __devinit timer_cpu_notify(struct notifier_block *self, 
 				unsigned long action, void *hcpu)
 {
@@ -1232,6 +1308,11 @@ static int __devinit timer_cpu_notify(st
 	case CPU_UP_PREPARE:
 		init_timers_cpu(cpu);
 		break;
+#ifdef CONFIG_HOTPLUG_CPU
+	case CPU_DEAD:
+		migrate_timers(cpu);
+		break;
+#endif
 	default:
 		break;
 	}
--- diff/kernel/uid16.c	2003-10-09 09:47:17.000000000 +0100
+++ source/kernel/uid16.c	2004-02-23 13:56:48.000000000 +0000
@@ -13,21 +13,10 @@
 #include <linux/init.h>
 #include <linux/highuid.h>
 #include <linux/security.h>
+#include <linux/syscalls.h>
 
 #include <asm/uaccess.h>
 
-extern asmlinkage long sys_chown(const char *, uid_t,gid_t);
-extern asmlinkage long sys_lchown(const char *, uid_t,gid_t);
-extern asmlinkage long sys_fchown(unsigned int, uid_t,gid_t);
-extern asmlinkage long sys_setregid(gid_t, gid_t);
-extern asmlinkage long sys_setgid(gid_t);
-extern asmlinkage long sys_setreuid(uid_t, uid_t);
-extern asmlinkage long sys_setuid(uid_t);
-extern asmlinkage long sys_setresuid(uid_t, uid_t, uid_t);
-extern asmlinkage long sys_setresgid(gid_t, gid_t, gid_t);
-extern asmlinkage long sys_setfsuid(uid_t);
-extern asmlinkage long sys_setfsgid(gid_t);
- 
 asmlinkage long sys_chown16(const char * filename, old_uid_t user, old_gid_t group)
 {
 	return sys_chown(filename, low2highuid(user), low2highgid(group));
@@ -107,45 +96,83 @@ asmlinkage long sys_setfsgid16(old_gid_t
 	return sys_setfsgid((gid_t)gid);
 }
 
+static int groups16_to_user(old_gid_t __user *grouplist,
+    struct group_info *group_info)
+{
+	int i;
+	old_gid_t group;
+
+	for (i = 0; i < group_info->ngroups; i++) {
+		group = (old_gid_t)GROUP_AT(group_info, i);
+		if (put_user(group, grouplist+i))
+			return -EFAULT;
+	}
+
+	return 0;
+}
+
+static int groups16_from_user(struct group_info *group_info,
+    old_gid_t __user *grouplist)
+{
+	int i;
+	old_gid_t group;
+
+	for (i = 0; i < group_info->ngroups; i++) {
+		if (get_user(group, grouplist+i))
+			return  -EFAULT;
+		GROUP_AT(group_info, i) = (gid_t)group;
+	}
+
+	return 0;
+}
+
 asmlinkage long sys_getgroups16(int gidsetsize, old_gid_t __user *grouplist)
 {
-	old_gid_t groups[NGROUPS];
-	int i,j;
+	int i = 0;
 
 	if (gidsetsize < 0)
 		return -EINVAL;
-	i = current->ngroups;
+
+	get_group_info(current->group_info);
+	i = current->group_info->ngroups;
 	if (gidsetsize) {
-		if (i > gidsetsize)
-			return -EINVAL;
-		for(j=0;j<i;j++)
-			groups[j] = current->groups[j];
-		if (copy_to_user(grouplist, groups, sizeof(old_gid_t)*i))
-			return -EFAULT;
+		if (i > gidsetsize) {
+			i = -EINVAL;
+			goto out;
+		}
+		if (groups16_to_user(grouplist, current->group_info)) {
+			i = -EFAULT;
+			goto out;
+		}
 	}
+out:
+	put_group_info(current->group_info);
 	return i;
 }
 
 asmlinkage long sys_setgroups16(int gidsetsize, old_gid_t __user *grouplist)
 {
-	old_gid_t groups[NGROUPS];
-	gid_t new_groups[NGROUPS];
-	int i;
+	struct group_info *group_info;
+	int retval;
 
 	if (!capable(CAP_SETGID))
 		return -EPERM;
-	if ((unsigned) gidsetsize > NGROUPS)
+	if ((unsigned)gidsetsize > NGROUPS_MAX)
 		return -EINVAL;
-	if (copy_from_user(groups, grouplist, gidsetsize * sizeof(old_gid_t)))
-		return -EFAULT;
-	for (i = 0 ; i < gidsetsize ; i++)
-		new_groups[i] = (gid_t)groups[i];
-	i = security_task_setgroups(gidsetsize, new_groups);
-	if (i)
-		return i;
-	memcpy(current->groups, new_groups, gidsetsize * sizeof(gid_t));
-	current->ngroups = gidsetsize;
-	return 0;
+
+	group_info = groups_alloc(gidsetsize);
+	if (!group_info)
+		return -ENOMEM;
+	retval = groups16_from_user(group_info, grouplist);
+	if (retval) {
+		put_group_info(group_info);
+		return retval;
+	}
+
+	retval = set_current_groups(group_info);
+	put_group_info(group_info);
+
+	return retval;
 }
 
 asmlinkage long sys_getuid16(void)
--- diff/kernel/workqueue.c	2004-02-09 10:36:12.000000000 +0000
+++ source/kernel/workqueue.c	2004-02-23 13:56:48.000000000 +0000
@@ -22,6 +22,9 @@
 #include <linux/completion.h>
 #include <linux/workqueue.h>
 #include <linux/slab.h>
+#include <linux/cpu.h>
+#include <linux/notifier.h>
+#include <linux/kthread.h>
 
 /*
  * The per-CPU workqueue.
@@ -45,7 +48,6 @@ struct cpu_workqueue_struct {
 
 	struct workqueue_struct *wq;
 	task_t *thread;
-	struct completion exit;
 
 } ____cacheline_aligned;
 
@@ -55,8 +57,36 @@ struct cpu_workqueue_struct {
  */
 struct workqueue_struct {
 	struct cpu_workqueue_struct cpu_wq[NR_CPUS];
+	const char *name;
+	struct list_head list;
 };
 
+#ifdef CONFIG_HOTPLUG_CPU
+/* All the workqueues on the system, for hotplug cpu to add/remove
+   threads to each one as cpus come/go.  Protected by cpucontrol
+   sem. */
+static LIST_HEAD(workqueues);
+#define add_workqueue(wq) list_add(&(wq)->list, &workqueues)
+#define del_workqueue(wq) list_del(&(wq)->list)
+#else
+#define add_workqueue(wq)
+#define del_workqueue(wq)
+#endif /* CONFIG_HOTPLUG_CPU */
+
+/* Preempt must be disabled. */
+static void __queue_work(struct cpu_workqueue_struct *cwq,
+			 struct work_struct *work)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&cwq->lock, flags);
+	work->wq_data = cwq;
+	list_add_tail(&work->entry, &cwq->worklist);
+	cwq->insert_sequence++;
+	wake_up(&cwq->more_work);
+	spin_unlock_irqrestore(&cwq->lock, flags);
+}
+
 /*
  * Queue work on a workqueue. Return non-zero if it was successfully
  * added.
@@ -66,19 +96,11 @@ struct workqueue_struct {
  */
 int queue_work(struct workqueue_struct *wq, struct work_struct *work)
 {
-	unsigned long flags;
 	int ret = 0, cpu = get_cpu();
-	struct cpu_workqueue_struct *cwq = wq->cpu_wq + cpu;
 
 	if (!test_and_set_bit(0, &work->pending)) {
 		BUG_ON(!list_empty(&work->entry));
-		work->wq_data = cwq;
-
-		spin_lock_irqsave(&cwq->lock, flags);
-		list_add_tail(&work->entry, &cwq->worklist);
-		cwq->insert_sequence++;
-		wake_up(&cwq->more_work);
-		spin_unlock_irqrestore(&cwq->lock, flags);
+		__queue_work(wq->cpu_wq + cpu, work);
 		ret = 1;
 	}
 	put_cpu();
@@ -88,39 +110,29 @@ int queue_work(struct workqueue_struct *
 static void delayed_work_timer_fn(unsigned long __data)
 {
 	struct work_struct *work = (struct work_struct *)__data;
-	struct cpu_workqueue_struct *cwq = work->wq_data;
-	unsigned long flags;
+	struct workqueue_struct *wq = work->wq_data;
 
-	/*
-	 * Do the wakeup within the spinlock, so that flushing
-	 * can be done in a guaranteed way.
-	 */
-	spin_lock_irqsave(&cwq->lock, flags);
-	list_add_tail(&work->entry, &cwq->worklist);
-	cwq->insert_sequence++;
-	wake_up(&cwq->more_work);
-	spin_unlock_irqrestore(&cwq->lock, flags);
+	__queue_work(wq->cpu_wq + smp_processor_id(), work);
 }
 
 int queue_delayed_work(struct workqueue_struct *wq,
 			struct work_struct *work, unsigned long delay)
 {
-	int ret = 0, cpu = get_cpu();
+	int ret = 0;
 	struct timer_list *timer = &work->timer;
-	struct cpu_workqueue_struct *cwq = wq->cpu_wq + cpu;
 
 	if (!test_and_set_bit(0, &work->pending)) {
 		BUG_ON(timer_pending(timer));
 		BUG_ON(!list_empty(&work->entry));
 
-		work->wq_data = cwq;
+		/* This stores wq for the moment, for the timer_fn */
+		work->wq_data = wq;
 		timer->expires = jiffies + delay;
 		timer->data = (unsigned long)work;
 		timer->function = delayed_work_timer_fn;
 		add_timer(timer);
 		ret = 1;
 	}
-	put_cpu();
 	return ret;
 }
 
@@ -153,28 +165,21 @@ static inline void run_workqueue(struct 
 	spin_unlock_irqrestore(&cwq->lock, flags);
 }
 
-typedef struct startup_s {
-	struct cpu_workqueue_struct *cwq;
-	struct completion done;
-	const char *name;
-} startup_t;
-
-static int worker_thread(void *__startup)
+static int worker_thread(void *__cwq)
 {
-	startup_t *startup = __startup;
-	struct cpu_workqueue_struct *cwq = startup->cwq;
-	int cpu = cwq - cwq->wq->cpu_wq;
+	struct cpu_workqueue_struct *cwq = __cwq;
 	DECLARE_WAITQUEUE(wait, current);
 	struct k_sigaction sa;
+	sigset_t blocked;
 
-	daemonize("%s/%d", startup->name, cpu);
 	current->flags |= PF_IOTHREAD;
-	cwq->thread = current;
 
 	set_user_nice(current, -10);
-	set_cpus_allowed(current, cpumask_of_cpu(cpu));
 
-	complete(&startup->done);
+	/* Block and flush all signals */
+	sigfillset(&blocked);
+	sigprocmask(SIG_BLOCK, &blocked, NULL);
+	flush_signals(current);
 
 	/* SIG_IGN makes children autoreap: see do_notify_parent(). */
 	sa.sa.sa_handler = SIG_IGN;
@@ -182,12 +187,10 @@ static int worker_thread(void *__startup
 	siginitset(&sa.sa.sa_mask, sigmask(SIGCHLD));
 	do_sigaction(SIGCHLD, &sa, (struct k_sigaction *)0);
 
-	for (;;) {
+	while (!kthread_should_stop()) {
 		set_task_state(current, TASK_INTERRUPTIBLE);
 
 		add_wait_queue(&cwq->more_work, &wait);
-		if (!cwq->thread)
-			break;
 		if (list_empty(&cwq->worklist))
 			schedule();
 		else
@@ -197,9 +200,6 @@ static int worker_thread(void *__startup
 		if (!list_empty(&cwq->worklist))
 			run_workqueue(cwq);
 	}
-	remove_wait_queue(&cwq->more_work, &wait);
-	complete(&cwq->exit);
-
 	return 0;
 }
 
@@ -224,6 +224,7 @@ void flush_workqueue(struct workqueue_st
 
 	might_sleep();
 
+	lock_cpu_hotplug();
 	for (cpu = 0; cpu < NR_CPUS; cpu++) {
 		DEFINE_WAIT(wait);
 		long sequence_needed;
@@ -245,15 +246,13 @@ void flush_workqueue(struct workqueue_st
 		finish_wait(&cwq->work_done, &wait);
 		spin_unlock_irq(&cwq->lock);
 	}
+	unlock_cpu_hotplug();
 }
 
-static int create_workqueue_thread(struct workqueue_struct *wq,
-				   const char *name,
-				   int cpu)
+static int create_workqueue_thread(struct workqueue_struct *wq, int cpu)
 {
-	startup_t startup;
 	struct cpu_workqueue_struct *cwq = wq->cpu_wq + cpu;
-	int ret;
+	struct task_struct *p;
 
 	spin_lock_init(&cwq->lock);
 	cwq->wq = wq;
@@ -263,17 +262,13 @@ static int create_workqueue_thread(struc
 	INIT_LIST_HEAD(&cwq->worklist);
 	init_waitqueue_head(&cwq->more_work);
 	init_waitqueue_head(&cwq->work_done);
-	init_completion(&cwq->exit);
 
-	init_completion(&startup.done);
-	startup.cwq = cwq;
-	startup.name = name;
-	ret = kernel_thread(worker_thread, &startup, CLONE_FS | CLONE_FILES);
-	if (ret >= 0) {
-		wait_for_completion(&startup.done);
-		BUG_ON(!cwq->thread);
-	}
-	return ret;
+	p = kthread_create(worker_thread, cwq, "%s/%d", wq->name, cpu);
+	if (IS_ERR(p))
+		return PTR_ERR(p);
+	cwq->thread = p;
+	kthread_bind(p, cpu);
+	return 0;
 }
 
 struct workqueue_struct *create_workqueue(const char *name)
@@ -287,12 +282,19 @@ struct workqueue_struct *create_workqueu
 	if (!wq)
 		return NULL;
 
+	wq->name = name;
+	/* We don't need the distraction of CPUs appearing and vanishing. */
+	lock_cpu_hotplug();
 	for (cpu = 0; cpu < NR_CPUS; cpu++) {
 		if (!cpu_online(cpu))
 			continue;
-		if (create_workqueue_thread(wq, name, cpu) < 0)
+		if (create_workqueue_thread(wq, cpu) < 0)
 			destroy = 1;
+		else
+			wake_up_process(wq->cpu_wq[cpu].thread);
 	}
+	add_workqueue(wq);
+
 	/*
 	 * Was there any error during startup? If yes then clean up:
 	 */
@@ -300,21 +302,23 @@ struct workqueue_struct *create_workqueu
 		destroy_workqueue(wq);
 		wq = NULL;
 	}
+	unlock_cpu_hotplug();
 	return wq;
 }
 
 static void cleanup_workqueue_thread(struct workqueue_struct *wq, int cpu)
 {
 	struct cpu_workqueue_struct *cwq;
+	unsigned long flags;
+	struct task_struct *p;
 
 	cwq = wq->cpu_wq + cpu;
-	if (cwq->thread) {
-		/* Tell thread to exit and wait for it. */
-		cwq->thread = NULL;
-		wake_up(&cwq->more_work);
-
-		wait_for_completion(&cwq->exit);
-	}
+	spin_lock_irqsave(&cwq->lock, flags);
+	p = cwq->thread;
+	cwq->thread = NULL;
+	spin_unlock_irqrestore(&cwq->lock, flags);
+	if (p)
+		kthread_stop(p);
 }
 
 void destroy_workqueue(struct workqueue_struct *wq)
@@ -323,10 +327,14 @@ void destroy_workqueue(struct workqueue_
 
 	flush_workqueue(wq);
 
+	/* We don't need the distraction of CPUs appearing and vanishing. */
+	lock_cpu_hotplug();
 	for (cpu = 0; cpu < NR_CPUS; cpu++) {
 		if (cpu_online(cpu))
 			cleanup_workqueue_thread(wq, cpu);
 	}
+	del_workqueue(wq);
+	unlock_cpu_hotplug();
 	kfree(wq);
 }
 
@@ -347,6 +355,11 @@ void flush_scheduled_work(void)
 	flush_workqueue(keventd_wq);
 }
 
+int keventd_up(void)
+{
+	return keventd_wq != NULL;
+}
+
 int current_is_keventd(void)
 {
 	struct cpu_workqueue_struct *cwq;
@@ -362,8 +375,75 @@ int current_is_keventd(void)
 	return 0;
 }
 
+#ifdef CONFIG_HOTPLUG_CPU
+/* Take the work from this (downed) CPU. */
+static void take_over_work(struct workqueue_struct *wq, unsigned int cpu)
+{
+	struct cpu_workqueue_struct *cwq = wq->cpu_wq + cpu;
+	LIST_HEAD(list);
+	struct work_struct *work;
+
+	spin_lock_irq(&cwq->lock);
+	list_splice_init(&cwq->worklist, &list);
+
+	while (!list_empty(&list)) {
+		printk("Taking work for %s\n", wq->name);
+		work = list_entry(list.next,struct work_struct,entry);
+		list_del(&work->entry);
+		__queue_work(wq->cpu_wq + smp_processor_id(), work);
+	}
+	spin_unlock_irq(&cwq->lock);
+}
+
+/* We're holding the cpucontrol mutex here */
+static int __devinit workqueue_cpu_callback(struct notifier_block *nfb,
+				  unsigned long action,
+				  void *hcpu)
+{
+	unsigned int hotcpu = (unsigned long)hcpu;
+	struct workqueue_struct *wq;
+
+	switch (action) {
+	case CPU_UP_PREPARE:
+		/* Create a new workqueue thread for it. */
+		list_for_each_entry(wq, &workqueues, list) {
+			if (create_workqueue_thread(wq, hotcpu) < 0) {
+				printk("workqueue for %i failed\n", hotcpu);
+				return NOTIFY_BAD;
+			}
+		}
+		break;
+
+	case CPU_ONLINE:
+		/* Kick off worker threads. */
+		list_for_each_entry(wq, &workqueues, list)
+			wake_up_process(wq->cpu_wq[hotcpu].thread);
+		break;
+
+	case CPU_UP_CANCELED:
+		list_for_each_entry(wq, &workqueues, list) {
+			/* Unbind so it can run. */
+			kthread_bind(wq->cpu_wq[hotcpu].thread,
+				     smp_processor_id());
+			cleanup_workqueue_thread(wq, hotcpu);
+		}
+		break;
+
+	case CPU_DEAD:
+		list_for_each_entry(wq, &workqueues, list)
+			cleanup_workqueue_thread(wq, hotcpu);
+		list_for_each_entry(wq, &workqueues, list)
+			take_over_work(wq, hotcpu);
+		break;
+	}
+
+	return NOTIFY_OK;
+}
+#endif
+
 void init_workqueues(void)
 {
+	hotcpu_notifier(workqueue_cpu_callback, 0);
 	keventd_wq = create_workqueue("events");
 	BUG_ON(!keventd_wq);
 }
--- diff/lib/bitmap.c	2004-02-18 08:54:13.000000000 +0000
+++ source/lib/bitmap.c	2004-02-23 13:56:48.000000000 +0000
@@ -165,7 +165,7 @@ EXPORT_SYMBOL(bitmap_weight);
 #define unhex(c)			(isdigit(c) ? (c - '0') : (toupper(c) - 'A' + 10))
 
 /**
- * bitmap_snprintf - convert bitmap to an ASCII hex string.
+ * bitmap_scnprintf - convert bitmap to an ASCII hex string.
  * @buf: byte buffer into which string is placed
  * @buflen: reserved size of @buf, in bytes
  * @maskp: pointer to bitmap to convert
@@ -174,7 +174,7 @@ EXPORT_SYMBOL(bitmap_weight);
  * Exactly @nmaskbits bits are displayed.  Hex digits are grouped into
  * comma-separated sets of eight digits per set.
  */
-int bitmap_snprintf(char *buf, unsigned int buflen,
+int bitmap_scnprintf(char *buf, unsigned int buflen,
 	const unsigned long *maskp, int nmaskbits)
 {
 	int i, word, bit, len = 0;
@@ -193,14 +193,14 @@ int bitmap_snprintf(char *buf, unsigned 
 		word = i / BITS_PER_LONG;
 		bit = i % BITS_PER_LONG;
 		val = (maskp[word] >> bit) & chunkmask;
-		len += snprintf(buf+len, buflen-len, "%s%0*lx", sep,
+		len += scnprintf(buf+len, buflen-len, "%s%0*lx", sep,
 			(chunksz+3)/4, val);
 		chunksz = CHUNKSZ;
 		sep = ",";
 	}
 	return len;
 }
-EXPORT_SYMBOL(bitmap_snprintf);
+EXPORT_SYMBOL(bitmap_scnprintf);
 
 /**
  * bitmap_parse - convert an ASCII hex string into a bitmap.
--- diff/lib/crc32.c	2004-02-18 08:54:13.000000000 +0000
+++ source/lib/crc32.c	2004-02-23 13:56:48.000000000 +0000
@@ -1,6 +1,9 @@
-/* 
+/*
  * Oct 15, 2000 Matt Domsch <Matt_Domsch@dell.com>
  * Nicer crc32 functions/docs submitted by linux@horizon.com.  Thanks!
+ * Code was from the public domain, copyright abandoned.  Code was
+ * subsequently included in the kernel, thus was re-licensed under the
+ * GNU GPL v2.
  *
  * Oct 12, 2000 Matt Domsch <Matt_Domsch@dell.com>
  * Same crc32 function was used in 5 other places in the kernel.
@@ -12,7 +15,9 @@
  *   drivers/net/smc9194.c uses seed ~0, doesn't xor with ~0.
  *   fs/jffs2 uses seed 0, doesn't xor with ~0.
  *   fs/partitions/efi.c uses seed ~0, xor's with ~0.
- * 
+ *
+ * This source code is licensed under the GNU General Public License,
+ * Version 2.  See the file COPYING for more details.
  */
 
 #include <linux/crc32.h>
@@ -38,16 +43,10 @@
 #define attribute(x)
 #endif
 
-/*
- * This code is in the public domain; copyright abandoned.
- * Liability for non-performance of this code is limited to the amount
- * you paid for it.  Since it is distributed for free, your refund will
- * be very very small.  If it breaks, you get to keep both pieces.
- */
 
 MODULE_AUTHOR("Matt Domsch <Matt_Domsch@dell.com>");
 MODULE_DESCRIPTION("Ethernet CRC32 calculations");
-MODULE_LICENSE("GPL and additional rights");
+MODULE_LICENSE("GPL");
 
 #if CRC_LE_BITS == 1
 /*
@@ -397,7 +396,7 @@ EXPORT_SYMBOL(bitreverse);
  * the same way on decoding, it doesn't make a difference.
  */
 
-#if UNITTEST
+#ifdef UNITTEST
 
 #include <stdlib.h>
 #include <stdio.h>
--- diff/lib/idr.c	2003-05-21 11:50:01.000000000 +0100
+++ source/lib/idr.c	2004-02-23 13:56:48.000000000 +0000
@@ -62,13 +62,13 @@
  *   to the rest of the functions.  The structure is defined in the
  *   header.
 
- * int idr_pre_get(struct idr *idp)
+ * int idr_pre_get(struct idr *idp, unsigned gfp_mask)
 
  *   This function should be called prior to locking and calling the
  *   following function.  It pre allocates enough memory to satisfy the
- *   worst possible allocation.  It can sleep, so must not be called
- *   with any spinlocks held.  If the system is REALLY out of memory
- *   this function returns 0, other wise 1.
+ *   worst possible allocation.  Unless gfp_mask is GFP_ATOMIC, it can
+ *   sleep, so must not be called with any spinlocks held.  If the system is
+ *   REALLY out of memory this function returns 0, other wise 1.
 
  * int idr_get_new(struct idr *idp, void *ptr);
  
@@ -135,11 +135,11 @@ static inline void free_layer(struct idr
 	spin_unlock(&idp->lock);
 }
 
-int idr_pre_get(struct idr *idp)
+int idr_pre_get(struct idr *idp, unsigned gfp_mask)
 {
 	while (idp->id_free_cnt < idp->layers + 1) {
 		struct idr_layer *new;
-		new = kmem_cache_alloc(idr_layer_cache, GFP_KERNEL);
+		new = kmem_cache_alloc(idr_layer_cache, gfp_mask);
 		if(new == NULL)
 			return (0);
 		free_layer(idp, new);
--- diff/lib/vsprintf.c	2004-02-18 08:54:13.000000000 +0000
+++ source/lib/vsprintf.c	2004-02-23 13:56:48.000000000 +0000
@@ -12,6 +12,8 @@
 /* 
  * Fri Jul 13 2001 Crutcher Dunnavant <crutcher+kernel@datastacks.com>
  * - changed to provide snprintf and vsnprintf functions
+ * So Feb  1 16:51:32 CET 2004 Juergen Quade <quade@hsnr.de>
+ * - scnprintf and vscnprintf
  */
 
 #include <stdarg.h>
@@ -228,19 +230,22 @@ static char * number(char * buf, char * 
 }
 
 /**
-* vsnprintf - Format a string and place it in a buffer
-* @buf: The buffer to place the result into
-* @size: The size of the buffer, including the trailing null space
-* @fmt: The format string to use
-* @args: Arguments for the format string
-*
-* The return value is the number of characters which would be
-* generated for the given input, excluding the trailing null,
-* as per ISO C99.  If the return is greater than or equal to
-* @size, the resulting string is truncated.
-*
-* Call this function if you are already dealing with a va_list.
-* You probably want snprintf instead.
+ * vsnprintf - Format a string and place it in a buffer
+ * @buf: The buffer to place the result into
+ * @size: The size of the buffer, including the trailing null space
+ * @fmt: The format string to use
+ * @args: Arguments for the format string
+ *
+ * The return value is the number of characters which would
+ * be generated for the given input, excluding the trailing
+ * '\0', as per ISO C99. If you want to have the exact
+ * number of characters written into @buf as return value
+ * (not including the trailing '\0'), use vscnprintf. If the
+ * return is greater than or equal to @size, the resulting
+ * string is truncated.
+ *
+ * Call this function if you are already dealing with a va_list.
+ * You probably want snprintf instead.
  */
 int vsnprintf(char *buf, size_t size, const char *fmt, va_list args)
 {
@@ -482,6 +487,30 @@ int vsnprintf(char *buf, size_t size, co
 EXPORT_SYMBOL(vsnprintf);
 
 /**
+ * vscnprintf - Format a string and place it in a buffer
+ * @buf: The buffer to place the result into
+ * @size: The size of the buffer, including the trailing null space
+ * @fmt: The format string to use
+ * @args: Arguments for the format string
+ *
+ * The return value is the number of characters which have been written into
+ * the @buf not including the trailing '\0'. If @size is <= 0 the function
+ * returns 0.
+ *
+ * Call this function if you are already dealing with a va_list.
+ * You probably want scnprintf instead.
+ */
+int vscnprintf(char *buf, size_t size, const char *fmt, va_list args)
+{
+	int i;
+
+	i=vsnprintf(buf,size,fmt,args);
+	return (i >= size) ? (size - 1) : i;
+}
+
+EXPORT_SYMBOL(vscnprintf);
+
+/**
  * snprintf - Format a string and place it in a buffer
  * @buf: The buffer to place the result into
  * @size: The size of the buffer, including the trailing null space
@@ -507,11 +536,39 @@ int snprintf(char * buf, size_t size, co
 EXPORT_SYMBOL(snprintf);
 
 /**
+ * scnprintf - Format a string and place it in a buffer
+ * @buf: The buffer to place the result into
+ * @size: The size of the buffer, including the trailing null space
+ * @fmt: The format string to use
+ * @...: Arguments for the format string
+ *
+ * The return value is the number of characters written into @buf not including
+ * the trailing '\0'. If @size is <= 0 the function returns 0. If the return is
+ * greater than or equal to @size, the resulting string is truncated.
+ */
+
+int scnprintf(char * buf, size_t size, const char *fmt, ...)
+{
+	va_list args;
+	int i;
+
+	va_start(args, fmt);
+	i = vsnprintf(buf, size, fmt, args);
+	va_end(args);
+	return (i >= size) ? (size - 1) : i;
+}
+EXPORT_SYMBOL(scnprintf);
+
+/**
  * vsprintf - Format a string and place it in a buffer
  * @buf: The buffer to place the result into
  * @fmt: The format string to use
  * @args: Arguments for the format string
  *
+ * The function returns the number of characters written
+ * into @buf. Use vsnprintf or vscnprintf in order to avoid
+ * buffer overflows.
+ *
  * Call this function if you are already dealing with a va_list.
  * You probably want sprintf instead.
  */
@@ -527,6 +584,10 @@ EXPORT_SYMBOL(vsprintf);
  * @buf: The buffer to place the result into
  * @fmt: The format string to use
  * @...: Arguments for the format string
+ *
+ * The function returns the number of characters written
+ * into @buf. Use snprintf or scnprintf in order to avoid
+ * buffer overflows.
  */
 int sprintf(char * buf, const char *fmt, ...)
 {
--- diff/mm/Makefile	2003-10-09 09:47:17.000000000 +0100
+++ source/mm/Makefile	2004-02-23 13:56:48.000000000 +0000
@@ -12,3 +12,4 @@ obj-y			:= bootmem.o filemap.o mempool.o
 			   slab.o swap.o truncate.o vmscan.o $(mmu-y)
 
 obj-$(CONFIG_SWAP)	+= page_io.o swap_state.o swapfile.o
+obj-$(CONFIG_X86_4G)	+= usercopy.o
--- diff/mm/bootmem.c	2003-11-25 15:24:59.000000000 +0000
+++ source/mm/bootmem.c	2004-02-23 13:56:48.000000000 +0000
@@ -91,8 +91,11 @@ static void __init reserve_bootmem_core(
 	if (end > bdata->node_low_pfn)
 		BUG();
 	for (i = sidx; i < eidx; i++)
-		if (test_and_set_bit(i, bdata->node_bootmem_map))
+		if (test_and_set_bit(i, bdata->node_bootmem_map)) {
+#ifdef CONFIG_DEBUG_BOOTMEM
 			printk("hm, page %08lx reserved twice.\n", i*PAGE_SIZE);
+#endif
+		}
 }
 
 static void __init free_bootmem_core(bootmem_data_t *bdata, unsigned long addr, unsigned long size)
--- diff/mm/filemap.c	2004-02-18 08:54:13.000000000 +0000
+++ source/mm/filemap.c	2004-02-23 13:56:48.000000000 +0000
@@ -73,6 +73,9 @@
  *  ->mmap_sem
  *    ->i_sem			(msync)
  *
+ *  ->i_sem
+ *    ->i_alloc_sem             (various)
+ *
  *  ->inode_lock
  *    ->sb_lock			(fs/fs-writeback.c)
  *    ->mapping->page_lock	(__sync_single_inode)
@@ -226,6 +229,18 @@ restart:
 
 EXPORT_SYMBOL(filemap_fdatawait);
 
+int filemap_write_and_wait(struct address_space *mapping)
+{
+	int retval = 0;
+
+	if (mapping->nrpages) {
+		retval = filemap_fdatawrite(mapping);
+		if (retval == 0)
+			retval = filemap_fdatawait(mapping);
+	}
+	return retval;
+}
+
 /*
  * This adds a page to the page cache, starting out as locked, unreferenced,
  * not uptodate and with no errors.
@@ -1713,6 +1728,7 @@ EXPORT_SYMBOL(generic_write_checks);
 
 /*
  * Write to a file through the page cache. 
+ * Called under i_sem for S_ISREG files.
  *
  * We put everything into the page cache prior to writing it. This is not a
  * problem when writing full pages. With partial pages, however, we first have
@@ -1801,12 +1817,21 @@ generic_file_aio_write_nolock(struct kio
 		/*
 		 * Sync the fs metadata but not the minor inode changes and
 		 * of course not the data as we did direct DMA for the IO.
+		 * i_sem is held, which protects generic_osync_inode() from
+		 * livelocking.
 		 */
 		if (written >= 0 && file->f_flags & O_SYNC)
 			status = generic_osync_inode(inode, mapping, OSYNC_METADATA);
-		if (written >= 0 && !is_sync_kiocb(iocb))
+		if (written == count && !is_sync_kiocb(iocb))
 			written = -EIOCBQUEUED;
-		goto out_status;
+		if (written < 0 || written == count)
+			goto out_status;
+		/*
+		 * direct-io write to a hole: fall through to buffered I/O
+		 * for completing the rest of the request.
+		 */
+		pos += written;
+		count -= written;
 	}
 
 	buf = iov->iov_base;
@@ -1895,6 +1920,14 @@ generic_file_aio_write_nolock(struct kio
 					OSYNC_METADATA|OSYNC_DATA);
 	}
 	
+	/*
+	 * If we get here for O_DIRECT writes then we must have fallen through
+	 * to buffered writes (block instantiation inside i_size).  So we sync
+	 * the file data here, to try to honour O_DIRECT expectations.
+	 */
+	if (unlikely(file->f_flags & O_DIRECT) && written)
+		status = filemap_write_and_wait(mapping);
+
 out_status:	
 	err = written ? written : status;
 out:
@@ -1986,6 +2019,9 @@ ssize_t generic_file_writev(struct file 
 
 EXPORT_SYMBOL(generic_file_writev);
 
+/*
+ * Called under i_sem for writes to S_ISREG files
+ */
 ssize_t
 generic_file_direct_IO(int rw, struct kiocb *iocb, const struct iovec *iov,
 	loff_t offset, unsigned long nr_segs)
@@ -1994,18 +2030,13 @@ generic_file_direct_IO(int rw, struct ki
 	struct address_space *mapping = file->f_mapping;
 	ssize_t retval;
 
-	if (mapping->nrpages) {
-		retval = filemap_fdatawrite(mapping);
-		if (retval == 0)
-			retval = filemap_fdatawait(mapping);
-		if (retval)
-			goto out;
+	retval = filemap_write_and_wait(mapping);
+	if (retval == 0) {
+		retval = mapping->a_ops->direct_IO(rw, iocb, iov,
+						offset, nr_segs);
+		if (rw == WRITE && mapping->nrpages)
+			invalidate_inode_pages2(mapping);
 	}
-
-	retval = mapping->a_ops->direct_IO(rw, iocb, iov, offset, nr_segs);
-	if (rw == WRITE && mapping->nrpages)
-		invalidate_inode_pages2(mapping);
-out:
 	return retval;
 }
 
--- diff/mm/fremap.c	2004-02-09 10:36:12.000000000 +0000
+++ source/mm/fremap.c	2004-02-23 13:56:48.000000000 +0000
@@ -38,7 +38,7 @@ static inline void zap_pte(struct mm_str
 					set_page_dirty(page);
 				page_remove_rmap(page, ptep);
 				page_cache_release(page);
-				mm->rss--;
+				dec_rss(mm, page);
 			}
 		}
 	} else {
@@ -78,7 +78,7 @@ int install_page(struct mm_struct *mm, s
 
 	zap_pte(mm, vma, addr, pte);
 
-	mm->rss++;
+	inc_rss(mm, page);
 	flush_icache_page(vma, page);
 	set_pte(pte, mk_pte(page, prot));
 	pte_chain = page_add_rmap(page, pte, pte_chain);
--- diff/mm/memory.c	2004-02-18 08:54:13.000000000 +0000
+++ source/mm/memory.c	2004-02-23 13:56:48.000000000 +0000
@@ -109,7 +109,8 @@ static inline void free_one_pmd(struct m
 	pte_free_tlb(tlb, page);
 }
 
-static inline void free_one_pgd(struct mmu_gather *tlb, pgd_t * dir)
+static inline void free_one_pgd(struct mmu_gather *tlb, pgd_t * dir,
+							int pgd_idx)
 {
 	int j;
 	pmd_t * pmd;
@@ -123,8 +124,11 @@ static inline void free_one_pgd(struct m
 	}
 	pmd = pmd_offset(dir, 0);
 	pgd_clear(dir);
-	for (j = 0; j < PTRS_PER_PMD ; j++)
+	for (j = 0; j < PTRS_PER_PMD ; j++) {
+		if (pgd_idx * PGDIR_SIZE + j * PMD_SIZE >= TASK_SIZE)
+			break;
 		free_one_pmd(tlb, pmd+j);
+	}
 	pmd_free_tlb(tlb, pmd);
 }
 
@@ -137,11 +141,13 @@ static inline void free_one_pgd(struct m
 void clear_page_tables(struct mmu_gather *tlb, unsigned long first, int nr)
 {
 	pgd_t * page_dir = tlb->mm->pgd;
+	int pgd_idx = first;
 
 	page_dir += first;
 	do {
-		free_one_pgd(tlb, page_dir);
+		free_one_pgd(tlb, page_dir, pgd_idx);
 		page_dir++;
+		pgd_idx++;
 	} while (--nr);
 }
 
@@ -328,7 +334,7 @@ skip_copy_pte_range:
 					pte = pte_mkclean(pte);
 				pte = pte_mkold(pte);
 				get_page(page);
-				dst->rss++;
+				inc_rss(dst, page);
 
 				set_pte(dst_pte, pte);
 				pte_chain = page_add_rmap(page, dst_pte,
@@ -420,7 +426,14 @@ zap_pte_range(struct mmu_gather *tlb, pm
 					if (page->mapping && pte_young(pte) &&
 							!PageSwapCache(page))
 						mark_page_accessed(page);
-					tlb->freed++;
+					/*
+					 * While we have the page that is being
+					 * freed handy, make sure we decrement
+					 * the mm's RSS accordingly.  This is
+					 * only important for NUMA per-node
+					 * RSS accounting.
+					 */
+					dec_rss(tlb->mm, page);
 					page_remove_rmap(page, ptep);
 					tlb_remove_page(tlb, page);
 				}
@@ -439,7 +452,7 @@ zap_pmd_range(struct mmu_gather *tlb, pg
 		unsigned long address, unsigned long size)
 {
 	pmd_t * pmd;
-	unsigned long end;
+	unsigned long end, pgd_boundary;
 
 	if (pgd_none(*dir))
 		return;
@@ -450,8 +463,9 @@ zap_pmd_range(struct mmu_gather *tlb, pg
 	}
 	pmd = pmd_offset(dir, address);
 	end = address + size;
-	if (end > ((address + PGDIR_SIZE) & PGDIR_MASK))
-		end = ((address + PGDIR_SIZE) & PGDIR_MASK);
+	pgd_boundary = ((address + PGDIR_SIZE) & PGDIR_MASK);
+	if (pgd_boundary && (end > pgd_boundary))
+		end = pgd_boundary;
 	do {
 		zap_pte_range(tlb, pmd, address, end - address);
 		address = (address + PMD_SIZE) & PMD_MASK; 
@@ -574,9 +588,10 @@ int unmap_vmas(struct mmu_gather **tlbp,
 			if ((long)zap_bytes > 0)
 				continue;
 			if (need_resched()) {
+				int fullmm = tlb_is_full_mm(*tlbp);
 				tlb_finish_mmu(*tlbp, tlb_start, start);
 				cond_resched_lock(&mm->page_table_lock);
-				*tlbp = tlb_gather_mmu(mm, 0);
+				*tlbp = tlb_gather_mmu(mm, fullmm);
 				tlb_start_valid = 0;
 			}
 			zap_bytes = ZAP_BLOCK_SIZE;
@@ -605,6 +620,11 @@ void zap_page_range(struct vm_area_struc
 	might_sleep();
 
 	if (is_vm_hugetlb_page(vma)) {
+		static int x;
+		if (x < 10) {
+			x++;
+			dump_stack();
+		}
 		zap_hugepage_range(vma, address, size);
 		return;
 	}
@@ -692,6 +712,7 @@ int get_user_pages(struct task_struct *t
 		struct page **pages, struct vm_area_struct **vmas)
 {
 	int i;
+	int vm_io;
 	unsigned int flags;
 
 	/* 
@@ -735,8 +756,10 @@ int get_user_pages(struct task_struct *t
 			continue;
 		}
 
-		if (!vma || (pages && (vma->vm_flags & VM_IO))
-				|| !(flags & vma->vm_flags))
+		if (!vma)
+			return i ? : -EFAULT;
+		vm_io = vma->vm_flags & VM_IO;
+		if ((pages && vm_io) || !(flags & vma->vm_flags))
 			return i ? : -EFAULT;
 
 		if (is_vm_hugetlb_page(vma)) {
@@ -746,8 +769,16 @@ int get_user_pages(struct task_struct *t
 		}
 		spin_lock(&mm->page_table_lock);
 		do {
-			struct page *map;
-			while (!(map = follow_page(mm, start, write))) {
+			struct page *map = NULL;
+			int lookup_write = write;
+
+			/*
+			 * We don't follow pagetables for VM_IO regions - they
+			 * may have no pageframes.
+			 */
+			if (vm_io)
+				goto no_follow;
+			while (!(map = follow_page(mm, start, lookup_write))) {
 				spin_unlock(&mm->page_table_lock);
 				switch (handle_mm_fault(mm,vma,start,write)) {
 				case VM_FAULT_MINOR:
@@ -763,6 +794,14 @@ int get_user_pages(struct task_struct *t
 				default:
 					BUG();
 				}
+				/*
+				 * Now that we have performed a write fault
+				 * and surely no longer have a shared page we
+				 * shouldn't write, we shouldn't ignore an
+				 * unwritable page in the page table if
+				 * we are forcing write access.
+				 */
+				lookup_write = write && !force;
 				spin_lock(&mm->page_table_lock);
 			}
 			if (pages) {
@@ -778,6 +817,7 @@ int get_user_pages(struct task_struct *t
 				if (!PageReserved(pages[i]))
 					page_cache_get(pages[i]);
 			}
+no_follow:
 			if (vmas)
 				vmas[i] = vma;
 			i++;
@@ -952,6 +992,19 @@ int remap_page_range(struct vm_area_stru
 EXPORT_SYMBOL(remap_page_range);
 
 /*
+ * Do pte_mkwrite, but only if the vma says VM_WRITE.  We do this when
+ * servicing faults for write access.  In the normal case, do always want
+ * pte_mkwrite.  But get_user_pages can cause write faults for mappings
+ * that do not have writing enabled, when used by access_process_vm.
+ */
+static inline pte_t maybe_mkwrite(pte_t pte, struct vm_area_struct *vma)
+{
+	if (likely(vma->vm_flags & VM_WRITE))
+		pte = pte_mkwrite(pte);
+	return pte;
+}
+
+/*
  * We hold the mm semaphore for reading and vma->vm_mm->page_table_lock
  */
 static inline void break_cow(struct vm_area_struct * vma, struct page * new_page, unsigned long address, 
@@ -960,7 +1013,8 @@ static inline void break_cow(struct vm_a
 	pte_t entry;
 
 	flush_cache_page(vma, address);
-	entry = pte_mkwrite(pte_mkdirty(mk_pte(new_page, vma->vm_page_prot)));
+	entry = maybe_mkwrite(pte_mkdirty(mk_pte(new_page, vma->vm_page_prot)),
+			      vma);
 	ptep_establish(vma, address, page_table, entry);
 	update_mmu_cache(vma, address, entry);
 }
@@ -1012,7 +1066,8 @@ static int do_wp_page(struct mm_struct *
 		unlock_page(old_page);
 		if (reuse) {
 			flush_cache_page(vma, address);
-			entry = pte_mkyoung(pte_mkdirty(pte_mkwrite(pte)));
+			entry = maybe_mkwrite(pte_mkyoung(pte_mkdirty(pte)),
+					      vma);
 			ptep_establish(vma, address, page_table, entry);
 			update_mmu_cache(vma, address, entry);
 			pte_unmap(page_table);
@@ -1043,7 +1098,7 @@ static int do_wp_page(struct mm_struct *
 	page_table = pte_offset_map(pmd, address);
 	if (pte_same(*page_table, pte)) {
 		if (PageReserved(old_page))
-			++mm->rss;
+			inc_rss(mm, new_page);
 		page_remove_rmap(old_page, page_table);
 		break_cow(vma, new_page, address, page_table);
 		pte_chain = page_add_rmap(new_page, page_table, pte_chain);
@@ -1251,7 +1306,7 @@ static int do_swap_page(struct mm_struct
 	mark_page_accessed(page);
 	pte_chain = pte_chain_alloc(GFP_KERNEL);
 	if (!pte_chain) {
-		ret = -ENOMEM;
+		ret = VM_FAULT_OOM;
 		goto out;
 	}
 	lock_page(page);
@@ -1277,10 +1332,10 @@ static int do_swap_page(struct mm_struct
 	if (vm_swap_full())
 		remove_exclusive_swap_page(page);
 
-	mm->rss++;
+	inc_rss(mm, page);
 	pte = mk_pte(page, vma->vm_page_prot);
 	if (write_access && can_share_swap_page(page))
-		pte = pte_mkdirty(pte_mkwrite(pte));
+		pte = maybe_mkwrite(pte_mkdirty(pte), vma);
 	unlock_page(page);
 
 	flush_icache_page(vma, page);
@@ -1346,8 +1401,10 @@ do_anonymous_page(struct mm_struct *mm, 
 			ret = VM_FAULT_MINOR;
 			goto out;
 		}
-		mm->rss++;
-		entry = pte_mkwrite(pte_mkdirty(mk_pte(page, vma->vm_page_prot)));
+		inc_rss(mm, page);
+		entry = maybe_mkwrite(pte_mkdirty(mk_pte(page,
+							 vma->vm_page_prot)),
+				      vma);
 		lru_cache_add_active(page);
 		mark_page_accessed(page);
 	}
@@ -1459,11 +1516,11 @@ retry:
 	/* Only go through if we didn't race with anybody else... */
 	if (pte_none(*page_table)) {
 		if (!PageReserved(new_page))
-			++mm->rss;
+			inc_rss(mm, new_page);
 		flush_icache_page(vma, new_page);
 		entry = mk_pte(new_page, vma->vm_page_prot);
 		if (write_access)
-			entry = pte_mkwrite(pte_mkdirty(entry));
+			entry = maybe_mkwrite(pte_mkdirty(entry), vma);
 		set_pte(page_table, entry);
 		pte_chain = page_add_rmap(new_page, page_table, pte_chain);
 		pte_unmap(page_table);
--- diff/mm/mmap.c	2004-02-09 10:36:12.000000000 +0000
+++ source/mm/mmap.c	2004-02-23 13:56:48.000000000 +0000
@@ -11,6 +11,7 @@
 #include <linux/mman.h>
 #include <linux/pagemap.h>
 #include <linux/swap.h>
+#include <linux/syscalls.h>
 #include <linux/init.h>
 #include <linux/file.h>
 #include <linux/fs.h>
@@ -1445,7 +1446,7 @@ void exit_mmap(struct mm_struct *mm)
 	vma = mm->mmap;
 	mm->mmap = mm->mmap_cache = NULL;
 	mm->mm_rb = RB_ROOT;
-	mm->rss = 0;
+	zero_rss(mm);
 	mm->total_vm = 0;
 	mm->locked_vm = 0;
 
--- diff/mm/page-writeback.c	2004-02-09 10:36:12.000000000 +0000
+++ source/mm/page-writeback.c	2004-02-23 13:56:48.000000000 +0000
@@ -28,6 +28,7 @@
 #include <linux/smp.h>
 #include <linux/sysctl.h>
 #include <linux/cpu.h>
+#include <linux/quotaops.h>
 
 /*
  * The maximum number of pages to writeout in a single bdflush/kupdate
@@ -81,6 +82,16 @@ int dirty_writeback_centisecs = 5 * 100;
  */
 int dirty_expire_centisecs = 30 * 100;
 
+/*
+ * Flag that makes the machine dump writes/reads and block dirtyings.
+ */
+int block_dump;
+
+/*
+ * Flag that puts the machine in "laptop mode".
+ */
+int laptop_mode;
+
 /* End of sysctl-exported parameters */
 
 
@@ -195,7 +206,7 @@ static void balance_dirty_pages(struct a
 	if (nr_reclaimable + ps.nr_writeback <= dirty_thresh)
 		dirty_exceeded = 0;
 
-	if (!writeback_in_progress(bdi) && nr_reclaimable > background_thresh)
+	if (!unlikely(laptop_mode) && !writeback_in_progress(bdi) && nr_reclaimable > background_thresh)
 		pdflush_operation(background_writeout, 0);
 }
 
@@ -289,7 +300,17 @@ int wakeup_bdflush(long nr_pages)
 	return pdflush_operation(background_writeout, nr_pages);
 }
 
-static struct timer_list wb_timer;
+
+static void wb_timer_fn(unsigned long unused);
+
+/*
+ * Both timers share the same handler
+ */
+static struct timer_list wb_timer =
+			TIMER_INITIALIZER(wb_timer_fn, 0, 0);
+static struct timer_list laptop_mode_wb_timer =
+			TIMER_INITIALIZER(wb_timer_fn, 0, 0);
+
 
 /*
  * Periodic writeback of "old" data.
@@ -328,6 +349,8 @@ static void wb_kupdate(unsigned long arg
 	oldest_jif = jiffies - (dirty_expire_centisecs * HZ) / 100;
 	start_jif = jiffies;
 	next_jif = start_jif + (dirty_writeback_centisecs * HZ) / 100;
+	if (laptop_mode)
+		wbc.older_than_this = NULL;
 	nr_to_write = ps.nr_dirty + ps.nr_unstable +
 			(inodes_stat.nr_inodes - inodes_stat.nr_unused);
 	while (nr_to_write > 0) {
@@ -346,8 +369,10 @@ static void wb_kupdate(unsigned long arg
 		next_jif = jiffies + HZ;
 	if (dirty_writeback_centisecs)
 		mod_timer(&wb_timer, next_jif);
+	del_timer(&laptop_mode_wb_timer); /* May have been set as a result of our writes. */
 }
 
+
 /*
  * sysctl handler for /proc/sys/vm/dirty_writeback_centisecs
  */
@@ -364,13 +389,31 @@ int dirty_writeback_centisecs_handler(ct
 	return 0;
 }
 
+/*
+ * We've spun up the disk and we're in laptop mode: schedule writeback
+ * of all dirty data in 5 seconds.
+ *
+ * Laptop mode writeback will be delayed if it has previously been
+ * scheduled to occur within 5 seconds. That way, the writeback will
+ * only be triggered if the system is truly quiet again.
+ */
+void disk_is_spun_up(int postpone_writeback)
+{
+	if (postpone_writeback || !timer_pending(&laptop_mode_wb_timer))
+		mod_timer(&laptop_mode_wb_timer, jiffies + 5 * HZ);
+}
+
+
+/*
+ * Handler for wb_timer and laptop_mode_wb_timer.
+ */
 static void wb_timer_fn(unsigned long unused)
 {
 	if (pdflush_operation(wb_kupdate, 0) < 0)
 		mod_timer(&wb_timer, jiffies + HZ); /* delay 1 second */
-
 }
 
+
 /*
  * If ratelimit_pages is too high then we can get into dirty-data overload
  * if a large number of processes all perform writes at the same time.
@@ -430,20 +473,41 @@ void __init page_writeback_init(void)
 		vm_dirty_ratio /= 100;
 	}
 
-	init_timer(&wb_timer);
 	wb_timer.expires = jiffies + (dirty_writeback_centisecs * HZ) / 100;
-	wb_timer.data = 0;
-	wb_timer.function = wb_timer_fn;
 	add_timer(&wb_timer);
+
 	set_ratelimit();
 	register_cpu_notifier(&ratelimit_nb);
 }
 
 int do_writepages(struct address_space *mapping, struct writeback_control *wbc)
 {
+	int ret;
+	if (wbc->sync_mode == WB_SYNC_NONE) {
+		if (!down_read_trylock(&mapping->wb_rwsema))
+			/*
+			 * SYNC writeback in progress
+			 */
+			return 0;
+	} else {
+		/*
+		 * Only allow 1 SYNC writeback at a time, to be able
+		 * to wait for all i/o without worrying about racing
+		 * WB_SYNC_NONE writers.
+		 */
+		down_write(&mapping->wb_rwsema);
+	}
+
 	if (mapping->a_ops->writepages)
-		return mapping->a_ops->writepages(mapping, wbc);
-	return generic_writepages(mapping, wbc);
+		ret = mapping->a_ops->writepages(mapping, wbc);
+	else
+		ret = generic_writepages(mapping, wbc);
+	if (wbc->sync_mode == WB_SYNC_NONE) {
+		up_read(&mapping->wb_rwsema);
+	} else {
+		up_write(&mapping->wb_rwsema);
+	}
+	return ret;
 }
 
 /**
@@ -526,6 +590,8 @@ int __set_page_dirty_nobuffers(struct pa
 				__mark_inode_dirty(mapping->host,
 							I_DIRTY_PAGES);
 		}
+		if (unlikely(block_dump))
+			printk("%s(%d): dirtied page\n", current->comm, current->pid);
 	}
 	return ret;
 }
--- diff/mm/page_alloc.c	2004-02-18 08:54:13.000000000 +0000
+++ source/mm/page_alloc.c	2004-02-23 13:56:48.000000000 +0000
@@ -390,6 +390,27 @@ static int rmqueue_bulk(struct zone *zon
 	return allocated;
 }
 
+#if defined(CONFIG_PM) || defined(CONFIG_HOTPLUG_CPU)
+static void __drain_pages(unsigned int cpu)
+{
+	struct zone *zone;
+	int i;
+
+	for_each_zone(zone) {
+		struct per_cpu_pageset *pset;
+
+		pset = &zone->pageset[cpu];
+		for (i = 0; i < ARRAY_SIZE(pset->pcp); i++) {
+			struct per_cpu_pages *pcp;
+
+			pcp = &pset->pcp[i];
+			pcp->count -= free_pages_bulk(zone, pcp->count,
+						&pcp->list, 0);
+		}
+	}
+}
+#endif /* CONFIG_PM || CONFIG_HOTPLUG_CPU */
+
 #ifdef CONFIG_PM
 int is_head_of_free_region(struct page *page)
 {
@@ -419,22 +440,9 @@ int is_head_of_free_region(struct page *
 void drain_local_pages(void)
 {
 	unsigned long flags;
-	struct zone *zone;
-	int i;
 
 	local_irq_save(flags);	
-	for_each_zone(zone) {
-		struct per_cpu_pageset *pset;
-
-		pset = &zone->pageset[smp_processor_id()];
-		for (i = 0; i < ARRAY_SIZE(pset->pcp); i++) {
-			struct per_cpu_pages *pcp;
-
-			pcp = &pset->pcp[i];
-			pcp->count -= free_pages_bulk(zone, pcp->count,
-						&pcp->list, 0);
-		}
-	}
+	__drain_pages(smp_processor_id());
 	local_irq_restore(flags);	
 }
 #endif /* CONFIG_PM */
@@ -682,6 +690,42 @@ got_pg:
 
 EXPORT_SYMBOL(__alloc_pages);
 
+#ifdef CONFIG_NUMA
+/* Early boot: Everything is done by one cpu, but the data structures will be
+ * used by all cpus - spread them on all nodes.
+ */
+static __init unsigned long get_boot_pages(unsigned int gfp_mask, unsigned int order)
+{
+static int nodenr;
+	int i = nodenr;
+	struct page *page;
+
+	for (;;) {
+		if (i > nodenr + numnodes)
+			return 0;
+		if (node_present_pages(i%numnodes)) {
+			struct zone **z;
+			/* The node contains memory. Check that there is
+			 * memory in the intended zonelist.
+			 */
+			z = NODE_DATA(i%numnodes)->node_zonelists[gfp_mask & GFP_ZONEMASK].zones;
+			while (*z) {
+				if ( (*z)->free_pages > (1UL<<order))
+					goto found_node;
+				z++;
+			}
+		}
+		i++;
+	}
+found_node:
+	nodenr = i+1;
+	page = alloc_pages_node(i%numnodes, gfp_mask, order);
+	if (!page)
+		return 0;
+	return (unsigned long) page_address(page);
+}
+#endif
+
 /*
  * Common helper functions.
  */
@@ -689,6 +733,10 @@ unsigned long __get_free_pages(unsigned 
 {
 	struct page * page;
 
+#ifdef CONFIG_NUMA
+	if (unlikely(!system_running))
+		return get_boot_pages(gfp_mask, order);
+#endif
 	page = alloc_pages(gfp_mask, order);
 	if (!page)
 		return 0;
@@ -971,7 +1019,13 @@ void show_free_areas(void)
 			printk("\n");
 
 		for (cpu = 0; cpu < NR_CPUS; ++cpu) {
-			struct per_cpu_pageset *pageset = zone->pageset + cpu;
+			struct per_cpu_pageset *pageset;
+
+			if (!cpu_possible(cpu))
+				continue;
+
+			pageset = zone->pageset + cpu;
+
 			for (temperature = 0; temperature < 2; temperature++)
 				printk("cpu %d %s: low %d, high %d, batch %d\n",
 					cpu,
@@ -1005,6 +1059,7 @@ void show_free_areas(void)
 			" min:%lukB"
 			" low:%lukB"
 			" high:%lukB"
+			" batch:%lukB"
 			" active:%lukB"
 			" inactive:%lukB"
 			"\n",
@@ -1013,6 +1068,7 @@ void show_free_areas(void)
 			K(zone->pages_min),
 			K(zone->pages_low),
 			K(zone->pages_high),
+			K(zone->reclaim_batch),
 			K(zone->nr_active),
 			K(zone->nr_inactive)
 			);
@@ -1212,6 +1268,15 @@ void __init memmap_init_zone(struct page
 #endif
 
 /*
+ * Dummy pages used to scan active lists. It would be cleaner if these
+ * could be part of struct zone directly, but include dependencies currently
+ * prevent that.
+ */
+static struct {
+	struct page zone[MAX_NR_ZONES];
+} ____cacheline_aligned scan_pages[MAX_NUMNODES];
+
+/*
  * Set up the zone data structures:
  *   - mark all pages reserved
  *   - mark all memory queues empty
@@ -1233,6 +1298,7 @@ static void __init free_area_init_core(s
 		struct zone *zone = pgdat->node_zones + j;
 		unsigned long size, realsize;
 		unsigned long batch;
+		struct page *scan_page;
 
 		zone_table[NODEZONE(nid, j)] = zone;
 		realsize = size = zones_size[j];
@@ -1287,6 +1353,22 @@ static void __init free_area_init_core(s
 		atomic_set(&zone->refill_counter, 0);
 		zone->nr_active = 0;
 		zone->nr_inactive = 0;
+
+		/* initialize dummy page used for scanning */
+		scan_page = &(scan_pages[nid].zone[j]);
+		zone->scan_page = scan_page;
+		memset(scan_page, 0, sizeof *scan_page);
+		scan_page->flags =
+			(1 << PG_locked) |
+			(1 << PG_error) |
+			(1 << PG_lru) |
+			(1 << PG_active) |
+			(1 << PG_reserved);
+		set_page_zone(scan_page, j);
+		page_cache_get(scan_page);
+		INIT_LIST_HEAD(&scan_page->list);
+		list_add(&scan_page->lru, &zone->active_list);
+
 		if (!size)
 			continue;
 
@@ -1477,10 +1559,11 @@ static char *vmstat_text[] = {
 
 	"pgscan",
 	"pgrefill",
-	"pgsteal",
+	"pgsteal_hi",
+	"pgsteal_lo",
 	"pginodesteal",
-	"kswapd_steal",
 
+	"kswapd_steal",
 	"kswapd_inodesteal",
 	"pageoutrun",
 	"allocstall",
@@ -1536,34 +1619,27 @@ struct seq_operations vmstat_op = {
 
 #endif /* CONFIG_PROC_FS */
 
-static void __devinit init_page_alloc_cpu(int cpu)
-{
-	struct page_state *ps = &per_cpu(page_states, cpu);
-	memset(ps, 0, sizeof(*ps));
-}
-	
-static int __devinit page_alloc_cpu_notify(struct notifier_block *self, 
-				unsigned long action, void *hcpu)
+#ifdef CONFIG_HOTPLUG_CPU
+static int page_alloc_cpu_notify(struct notifier_block *self,
+				 unsigned long action, void *hcpu)
 {
 	int cpu = (unsigned long)hcpu;
-	switch(action) {
-	case CPU_UP_PREPARE:
-		init_page_alloc_cpu(cpu);
-		break;
-	default:
-		break;
+	long *count;
+
+	if (action == CPU_DEAD) {
+		/* Drain local pagecache count. */
+		count = &per_cpu(nr_pagecache_local, cpu);
+		atomic_add(*count, &nr_pagecache);
+		*count = 0;
+		__drain_pages(cpu);
 	}
 	return NOTIFY_OK;
 }
-
-static struct notifier_block __devinitdata page_alloc_nb = {
-	.notifier_call	= page_alloc_cpu_notify,
-};
+#endif /* CONFIG_HOTPLUG_CPU */
 
 void __init page_alloc_init(void)
 {
-	init_page_alloc_cpu(smp_processor_id());
-	register_cpu_notifier(&page_alloc_nb);
+	hotcpu_notifier(page_alloc_cpu_notify, 0);
 }
 
 /*
@@ -1584,6 +1660,8 @@ static void setup_per_zone_pages_min(voi
 			lowmem_pages += zone->present_pages;
 
 	for_each_zone(zone) {
+		unsigned long long reclaim_batch;
+
 		spin_lock_irqsave(&zone->lru_lock, flags);
 		if (is_highmem(zone)) {
 			/*
@@ -1610,6 +1688,13 @@ static void setup_per_zone_pages_min(voi
 
 		zone->pages_low = zone->pages_min * 2;
 		zone->pages_high = zone->pages_min * 3;
+
+		reclaim_batch = zone->present_pages * SWAP_CLUSTER_MAX;
+		do_div(reclaim_batch, lowmem_pages);
+		zone->reclaim_batch = reclaim_batch;
+		if (zone->reclaim_batch < 4)
+			zone->reclaim_batch = 4;
+
 		spin_unlock_irqrestore(&zone->lru_lock, flags);
 	}
 }
--- diff/mm/pdflush.c	2003-10-09 09:47:17.000000000 +0100
+++ source/mm/pdflush.c	2004-02-23 13:56:48.000000000 +0000
@@ -84,6 +84,8 @@ struct pdflush_work {
 	unsigned long when_i_went_to_sleep;
 };
 
+static int wakeup_count = 100;
+
 static int __pdflush(struct pdflush_work *my_work)
 {
 	daemonize("pdflush");
@@ -112,7 +114,10 @@ static int __pdflush(struct pdflush_work
 
 		spin_lock_irq(&pdflush_lock);
 		if (!list_empty(&my_work->list)) {
-			printk("pdflush: bogus wakeup!\n");
+			if (wakeup_count > 0) {
+				wakeup_count--;
+				printk("pdflush: bogus wakeup!\n");
+			}
 			my_work->fn = NULL;
 			continue;
 		}
@@ -182,6 +187,7 @@ int pdflush_operation(void (*fn)(unsigne
 {
 	unsigned long flags;
 	int ret = 0;
+	static int poke_count = 0;
 
 	if (fn == NULL)
 		BUG();		/* Hard to diagnose if it's deferred */
@@ -190,9 +196,19 @@ int pdflush_operation(void (*fn)(unsigne
 	if (list_empty(&pdflush_list)) {
 		spin_unlock_irqrestore(&pdflush_lock, flags);
 		ret = -1;
+		if (wakeup_count < 100 && poke_count < 10) {
+			printk("%s: no threads\n", __FUNCTION__);
+			dump_stack();
+			poke_count++;
+		}
 	} else {
 		struct pdflush_work *pdf;
 
+		if (wakeup_count < 100 && poke_count < 10) {
+			printk("%s: found a thread\n", __FUNCTION__);
+			dump_stack();
+			poke_count++;
+		}
 		pdf = list_entry(pdflush_list.next, struct pdflush_work, list);
 		list_del_init(&pdf->list);
 		if (list_empty(&pdflush_list))
--- diff/mm/readahead.c	2004-02-09 10:36:12.000000000 +0000
+++ source/mm/readahead.c	2004-02-23 13:56:48.000000000 +0000
@@ -30,6 +30,7 @@ file_ra_state_init(struct file_ra_state 
 {
 	memset(ra, 0, sizeof(*ra));
 	ra->ra_pages = mapping->backing_dev_info->ra_pages;
+	ra->average = ra->ra_pages / 2;
 }
 
 EXPORT_SYMBOL(file_ra_state_init);
@@ -380,9 +381,18 @@ page_cache_readahead(struct address_spac
 		 */
 		first_access=1;
 		ra->next_size = max / 2;
+		ra->prev_page = offset;
+		ra->serial_cnt++;
 		goto do_io;
 	}
 
+	if (offset == ra->prev_page + 1) {
+		if (ra->serial_cnt <= (max * 2))
+			ra->serial_cnt++;
+	} else {
+		ra->average = (ra->average + ra->serial_cnt) / 2;
+		ra->serial_cnt = 1;
+	}
 	preoffset = ra->prev_page;
 	ra->prev_page = offset;
 
@@ -449,8 +459,12 @@ do_io:
 			  * accessed in the current window, there
 			  * is a high probability that around 'n' pages
 			  * shall be used in the next current window.
+			  *
+			  * To minimize lazy-readahead triggered
+			  * in the next current window, read in
+			  * an extra page.
 			  */
-			ra->next_size = preoffset - ra->start + 1;
+			ra->next_size = preoffset - ra->start + 2;
 		}
 		ra->start = offset;
 		ra->size = ra->next_size;
@@ -468,17 +482,34 @@ do_io:
 		}
 	} else {
 		/*
-		 * This read request is within the current window.  It is time
-		 * to submit I/O for the ahead window while the application is
-		 * crunching through the current window.
+		 * This read request is within the current window.  It may be
+		 * time to submit I/O for the ahead window while the
+		 * application is about to step into the ahead window.
 		 */
 		if (ra->ahead_start == 0) {
-			ra->ahead_start = ra->start + ra->size;
-			ra->ahead_size = ra->next_size;
-			actual = do_page_cache_readahead(mapping, filp,
+			/*
+			 * if the average io-size is less than maximum
+			 * readahead size of the file the io pattern is
+			 * sequential. Hence  bring in the readahead window
+			 * immediately.
+			 * Else the i/o pattern is random. Bring
+			 * in the readahead window only if the last page of
+			 * the current window is accessed (lazy readahead).
+			 */
+			unsigned long average = ra->average;
+
+			if (ra->serial_cnt > average)
+				average = (ra->serial_cnt + ra->average) / 2;
+
+			if ((average >= max) || (offset == (ra->start +
+							ra->size - 1))) {
+				ra->ahead_start = ra->start + ra->size;
+				ra->ahead_size = ra->next_size;
+				actual = do_page_cache_readahead(mapping, filp,
 					ra->ahead_start, ra->ahead_size);
-			check_ra_success(ra, ra->ahead_size,
-					actual, orig_next_size);
+				check_ra_success(ra, ra->ahead_size,
+						actual, orig_next_size);
+			}
 		}
 	}
 out:
--- diff/mm/rmap.c	2004-02-09 10:36:12.000000000 +0000
+++ source/mm/rmap.c	2004-02-23 13:56:48.000000000 +0000
@@ -171,7 +171,7 @@ page_add_rmap(struct page *page, pte_t *
 	pte_addr_t pte_paddr = ptep_to_paddr(ptep);
 	struct pte_chain *cur_pte_chain;
 
-	if (!pfn_valid(page_to_pfn(page)) || PageReserved(page))
+	if (PageReserved(page))
 		return pte_chain;
 
 	pte_chain_lock(page);
@@ -360,7 +360,7 @@ static int try_to_unmap_one(struct page 
 	if (pte_dirty(pte))
 		set_page_dirty(page);
 
-	mm->rss--;
+	dec_rss(mm, page);
 	page_cache_release(page);
 	ret = SWAP_SUCCESS;
 
--- diff/mm/slab.c	2004-02-18 08:54:13.000000000 +0000
+++ source/mm/slab.c	2004-02-23 13:56:48.000000000 +0000
@@ -357,8 +357,8 @@ struct kmem_cache_s {
 #define	RED_ACTIVE	0x170FC2A5UL	/* when obj is active */
 
 /* ...and for poisoning */
-#define	POISON_BEFORE	0x5a	/* for use-uninitialised poisoning */
-#define POISON_AFTER	0x6b	/* for use-after-free poisoning */
+#define	POISON_INUSE	0x5a	/* for use-uninitialised poisoning */
+#define POISON_FREE	0x6b	/* for use-after-free poisoning */
 #define	POISON_END	0xa5	/* end-byte of poisoning */
 
 /* memory layout of objects:
@@ -521,9 +521,19 @@ enum {
 static DEFINE_PER_CPU(struct timer_list, reap_timers);
 
 static void reap_timer_fnc(unsigned long data);
-
+static void free_block (kmem_cache_t* cachep, void** objpp, int len);
 static void enable_cpucache (kmem_cache_t *cachep);
 
+static inline void ** ac_entry(struct array_cache *ac)
+{
+	return (void**)(ac+1);
+}
+
+static inline struct array_cache *ac_data(kmem_cache_t *cachep)
+{
+	return cachep->array[smp_processor_id()];
+}
+
 /* Cal the num objs, wastage, and bytes left over for a given slab size. */
 static void cache_estimate (unsigned long gfporder, size_t size,
 		 int flags, size_t *left_over, unsigned int *num)
@@ -573,32 +583,39 @@ static void start_cpu_timer(int cpu)
 	if (rt->function == NULL) {
 		init_timer(rt);
 		rt->expires = jiffies + HZ + 3*cpu;
+		rt->data = cpu;
 		rt->function = reap_timer_fnc;
 		add_timer_on(rt, cpu);
 	}
 }
 
-/*
- * Note: if someone calls kmem_cache_alloc() on the new
- * cpu before the cpuup callback had a chance to allocate
- * the head arrays, it will oops.
- * Is CPU_ONLINE early enough?
- */
+#ifdef CONFIG_HOTPLUG_CPU
+static void stop_cpu_timer(int cpu)
+{
+	struct timer_list *rt = &per_cpu(reap_timers, cpu);
+
+	if (rt->function) {
+		del_timer_sync(rt);
+		WARN_ON(timer_pending(rt));
+		rt->function = NULL;
+	}
+}
+#endif
+
 static int __devinit cpuup_callback(struct notifier_block *nfb,
 				  unsigned long action,
 				  void *hcpu)
 {
 	long cpu = (long)hcpu;
-	struct list_head *p;
+	kmem_cache_t* cachep;
 
 	switch (action) {
 	case CPU_UP_PREPARE:
 		down(&cache_chain_sem);
-		list_for_each(p, &cache_chain) {
+		list_for_each_entry(cachep, &cache_chain, next) {
 			int memsize;
 			struct array_cache *nc;
 
-			kmem_cache_t* cachep = list_entry(p, kmem_cache_t, next);
 			memsize = sizeof(void*)*cachep->limit+sizeof(struct array_cache);
 			nc = kmalloc(memsize, GFP_KERNEL);
 			if (!nc)
@@ -618,22 +635,30 @@ static int __devinit cpuup_callback(stru
 		up(&cache_chain_sem);
 		break;
 	case CPU_ONLINE:
-		if (g_cpucache_up == FULL)
-			start_cpu_timer(cpu);
+		start_cpu_timer(cpu);
 		break;
+
+#ifdef CONFIG_HOTPLUG_CPU
+	case CPU_DEAD:
+		stop_cpu_timer(cpu);
+		/* fall thru */
 	case CPU_UP_CANCELED:
 		down(&cache_chain_sem);
-
-		list_for_each(p, &cache_chain) {
+		list_for_each_entry(cachep, &cache_chain, next) {
 			struct array_cache *nc;
-			kmem_cache_t* cachep = list_entry(p, kmem_cache_t, next);
 
+			spin_lock_irq(&cachep->spinlock);
+			/* cpu is dead; no one can alloc from it. */
 			nc = cachep->array[cpu];
 			cachep->array[cpu] = NULL;
+			cachep->free_limit -= cachep->batchcount;
+			free_block(cachep, ac_entry(nc), nc->avail);
+			spin_unlock_irq(&cachep->spinlock);
 			kfree(nc);
 		}
 		up(&cache_chain_sem);
 		break;
+#endif /* CONFIG_HOTPLUG_CPU */
 	}
 	return NOTIFY_OK;
 bad:
@@ -643,16 +668,6 @@ bad:
 
 static struct notifier_block cpucache_notifier = { &cpuup_callback, NULL, 0 };
 
-static inline void ** ac_entry(struct array_cache *ac)
-{
-	return (void**)(ac+1);
-}
-
-static inline struct array_cache *ac_data(kmem_cache_t *cachep)
-{
-	return cachep->array[smp_processor_id()];
-}
-
 /* Initialisation.
  * Called after the gfp() functions have been enabled, and before smp_init().
  */
@@ -887,60 +902,105 @@ static void poison_obj(kmem_cache_t *cac
 	*(unsigned char *)(addr+size-1) = POISON_END;
 }
 
-static void *scan_poisoned_obj(unsigned char* addr, unsigned int size)
+static void dump_line(char *data, int offset, int limit)
 {
-	unsigned char *end;
-	
-	end = addr + size - 1;
-
-	for (; addr < end; addr++) {
-		if (*addr != POISON_BEFORE && *addr != POISON_AFTER)
-			return addr;
+	int i;
+	printk(KERN_ERR "%03x:", offset);
+	for (i=0;i<limit;i++) {
+		printk(" %02x", (unsigned char)data[offset+i]);
 	}
-	if (*addr != POISON_END)
-		return addr;
-	return NULL;
+	printk("\n");
 }
+#endif
 
-static void check_poison_obj(kmem_cache_t *cachep, void *objp)
+static void print_objinfo(kmem_cache_t *cachep, void *objp, int lines)
 {
-	void *end;
-	void *realobj;
-	int size = obj_reallen(cachep);
+#if DEBUG
+	int i, size;
+	char *realobj;
 
-	realobj = objp+obj_dbghead(cachep);
+	if (cachep->flags & SLAB_RED_ZONE) {
+		printk(KERN_ERR "Redzone: 0x%lx/0x%lx.\n",
+			*dbg_redzone1(cachep, objp),
+			*dbg_redzone2(cachep, objp));
+	}
 
-	end = scan_poisoned_obj(realobj, size);
-	if (end) {
-		int s;
-		printk(KERN_ERR "Slab corruption: start=%p, expend=%p, "
-				"problemat=%p\n", realobj, realobj+size-1, end);
-		if (cachep->flags & SLAB_STORE_USER) {
-			printk(KERN_ERR "Last user: [<%p>]", *dbg_userword(cachep, objp));
-			print_symbol("(%s)", (unsigned long)*dbg_userword(cachep, objp));
-			printk("\n");
-		}
-		printk(KERN_ERR "Data: ");
-		for (s = 0; s < size; s++) {
-			if (((char*)realobj)[s] == POISON_BEFORE)
-				printk(".");
-			else if (((char*)realobj)[s] == POISON_AFTER)
-				printk("*");
-			else
-				printk("%02X ", ((unsigned char*)realobj)[s]);
-		}
+	if (cachep->flags & SLAB_STORE_USER) {
+		printk(KERN_ERR "Last user: [<%p>]", *dbg_userword(cachep, objp));
+		print_symbol("(%s)", (unsigned long)*dbg_userword(cachep, objp));
 		printk("\n");
-		printk(KERN_ERR "Next: ");
-		for (; s < size + 32; s++) {
-			if (((char*)realobj)[s] == POISON_BEFORE)
-				printk(".");
-			else if (((char*)realobj)[s] == POISON_AFTER)
-				printk("*");
-			else
-				printk("%02X ", ((unsigned char*)realobj)[s]);
+	}
+	realobj = (char*)objp+obj_dbghead(cachep);
+	size = cachep->objsize;
+	for (i=0; i<size && lines;i+=16, lines--) {
+		int limit;
+		limit = 16;
+		if (i+limit > size)
+			limit = size-i;
+		dump_line(realobj, i, limit);
+	}
+#endif
+}
+
+#if DEBUG
+
+static void check_poison_obj(kmem_cache_t *cachep, void *objp)
+{
+	char *realobj;
+	int size, i;
+	int lines = 0;
+
+	realobj = (char*)objp+obj_dbghead(cachep);
+	size = obj_reallen(cachep);
+
+	for (i=0;i<size;i++) {
+		char exp = POISON_FREE;
+		if (i == size-1)
+			exp = POISON_END;
+		if (realobj[i] != exp) {
+			int limit;
+			/* Mismatch ! */
+			/* Print header */
+			if (lines == 0) {
+				printk(KERN_ERR "Slab corruption: start=%p, len=%d\n",
+						realobj, size);
+				print_objinfo(cachep, objp, 0);
+			}
+			/* Hexdump the affected line */
+			i = (i/16)*16;
+			limit = 16;
+			if (i+limit > size)
+				limit = size-i;
+			dump_line(realobj, i, limit);
+			i += 16;
+			lines++;
+			/* Limit to 5 lines */
+			if (lines > 5)
+				break;
+		}
+	}
+	if (lines != 0) {
+		/* Print some data about the neighboring objects, if they
+		 * exist:
+		 */
+		struct slab *slabp = GET_PAGE_SLAB(virt_to_page(objp));
+		int objnr;
+
+		objnr = (objp-slabp->s_mem)/cachep->objsize;
+		if (objnr) {
+			objp = slabp->s_mem+(objnr-1)*cachep->objsize;
+			realobj = (char*)objp+obj_dbghead(cachep);
+			printk(KERN_ERR "Prev obj: start=%p, len=%d\n",
+						realobj, size);
+			print_objinfo(cachep, objp, 2);
+		}
+		if (objnr+1 < cachep->num) {
+			objp = slabp->s_mem+(objnr+1)*cachep->objsize;
+			realobj = (char*)objp+obj_dbghead(cachep);
+			printk(KERN_ERR "Next obj: start=%p, len=%d\n",
+						realobj, size);
+			print_objinfo(cachep, objp, 2);
 		}
-		printk("\n");
-		slab_error(cachep, "object was modified after freeing");
 	}
 }
 #endif
@@ -1030,7 +1090,6 @@ kmem_cache_create (const char *name, siz
 	unsigned long flags, void (*ctor)(void*, kmem_cache_t *, unsigned long),
 	void (*dtor)(void*, kmem_cache_t *, unsigned long))
 {
-	const char *func_nm = KERN_ERR "kmem_create: ";
 	size_t left_over, align, slab_size;
 	kmem_cache_t *cachep = NULL;
 
@@ -1042,14 +1101,18 @@ kmem_cache_create (const char *name, siz
 		(size < BYTES_PER_WORD) ||
 		(size > (1<<MAX_OBJ_ORDER)*PAGE_SIZE) ||
 		(dtor && !ctor) ||
-		(offset < 0 || offset > size))
+		(offset < 0 || offset > size)) {
+			printk(KERN_ERR "%s: Early error in slab %s\n",
+					__FUNCTION__, name);
 			BUG();
+		}
 
 #if DEBUG
 	WARN_ON(strchr(name, ' '));	/* It confuses parsers */
 	if ((flags & SLAB_DEBUG_INITIAL) && !ctor) {
 		/* No constructor, but inital state check requested */
-		printk("%sNo con, but init state check requested - %s\n", func_nm, name);
+		printk(KERN_ERR "%s: No con, but init state check "
+				"requested - %s\n", __FUNCTION__, name);
 		flags &= ~SLAB_DEBUG_INITIAL;
 	}
 
@@ -1094,7 +1157,6 @@ kmem_cache_create (const char *name, siz
 	if (size & (BYTES_PER_WORD-1)) {
 		size += (BYTES_PER_WORD-1);
 		size &= ~(BYTES_PER_WORD-1);
-		printk("%sForcing size word alignment - %s\n", func_nm, name);
 	}
 	
 #if DEBUG
@@ -1181,7 +1243,8 @@ next:
 		cachep = NULL;
 		goto opps;
 	}
-	slab_size = L1_CACHE_ALIGN(cachep->num*sizeof(kmem_bufctl_t)+sizeof(struct slab));
+	slab_size = L1_CACHE_ALIGN(cachep->num*sizeof(kmem_bufctl_t) +
+			sizeof(struct slab));
 
 	/*
 	 * If the slab has been placed off-slab, and we have enough space then
@@ -1225,10 +1288,13 @@ next:
 			 * the cache that's used by kmalloc(24), otherwise
 			 * the creation of further caches will BUG().
 			 */
-			cachep->array[smp_processor_id()] = &initarray_generic.cache;
+			cachep->array[smp_processor_id()] =
+					&initarray_generic.cache;
 			g_cpucache_up = PARTIAL;
 		} else {
-			cachep->array[smp_processor_id()] = kmalloc(sizeof(struct arraycache_init),GFP_KERNEL);
+			cachep->array[smp_processor_id()] =
+				kmalloc(sizeof(struct arraycache_init),
+					GFP_KERNEL);
 		}
 		BUG_ON(!ac_data(cachep));
 		ac_data(cachep)->avail = 0;
@@ -1242,7 +1308,7 @@ next:
 	} 
 
 	cachep->lists.next_reap = jiffies + REAPTIMEOUT_LIST3 +
-					((unsigned long)cachep)%REAPTIMEOUT_LIST3;
+				((unsigned long)cachep)%REAPTIMEOUT_LIST3;
 
 	/* Need the semaphore to access the chain. */
 	down(&cache_chain_sem);
@@ -1255,16 +1321,24 @@ next:
 		list_for_each(p, &cache_chain) {
 			kmem_cache_t *pc = list_entry(p, kmem_cache_t, next);
 			char tmp;
-			/* This happens when the module gets unloaded and doesn't
-			   destroy its slab cache and noone else reuses the vmalloc
-			   area of the module. Print a warning. */
-			if (__get_user(tmp,pc->name)) { 
-				printk("SLAB: cache with size %d has lost its name\n", 
-					pc->objsize); 
+
+			/*
+			 * This happens when the module gets unloaded and
+			 * doesn't destroy its slab cache and noone else reuses
+			 * the vmalloc area of the module. Print a warning.
+			 */
+#ifdef CONFIG_X86_UACCESS_INDIRECT
+			if (__direct_get_user(tmp,pc->name)) {
+#else
+			if (__get_user(tmp,pc->name)) {
+#endif
+				printk("SLAB: cache with size %d has lost its "
+						"name\n", pc->objsize);
 				continue; 
 			} 	
 			if (!strcmp(pc->name,name)) { 
-				printk("kmem_cache_create: duplicate cache %s\n",name); 
+				printk("kmem_cache_create: duplicate "
+						"cache %s\n",name);
 				up(&cache_chain_sem); 
 				BUG(); 
 			}	
@@ -1321,7 +1395,6 @@ static void smp_call_function_all_cpus(v
 	preempt_enable();
 }
 
-static void free_block (kmem_cache_t* cachep, void** objpp, int len);
 static void drain_array_locked(kmem_cache_t* cachep,
 				struct array_cache *ac, int force);
 
@@ -1442,6 +1515,9 @@ int kmem_cache_destroy (kmem_cache_t * c
 		return 1;
 	}
 
+	/* no cpu_online check required here since we clear the percpu
+	 * array on cpu offline and set this to NULL.
+	 */
 	for (i = 0; i < NR_CPUS; i++)
 		kfree(cachep->array[i]);
 
@@ -1493,7 +1569,7 @@ static void cache_init_objs (kmem_cache_
 #if DEBUG
 		/* need to poison the objs? */
 		if (cachep->flags & SLAB_POISON)
-			poison_obj(cachep, objp, POISON_BEFORE);
+			poison_obj(cachep, objp, POISON_FREE);
 		if (cachep->flags & SLAB_STORE_USER)
 			*dbg_userword(cachep, objp) = NULL;
 
@@ -1712,13 +1788,13 @@ static inline void *cache_free_debugchec
 	if (cachep->flags & SLAB_POISON) {
 #ifdef CONFIG_DEBUG_PAGEALLOC
 		if ((cachep->objsize % PAGE_SIZE) == 0 && OFF_SLAB(cachep)) {
-			store_stackinfo(cachep, objp, POISON_AFTER);
+			store_stackinfo(cachep, objp, (unsigned long)caller);
 	       		kernel_map_pages(virt_to_page(objp), cachep->objsize/PAGE_SIZE, 0);
 		} else {
-			poison_obj(cachep, objp, POISON_AFTER);
+			poison_obj(cachep, objp, POISON_FREE);
 		}
 #else
-		poison_obj(cachep, objp, POISON_AFTER);
+		poison_obj(cachep, objp, POISON_FREE);
 #endif
 	}
 #endif
@@ -1875,7 +1951,7 @@ cache_alloc_debugcheck_after(kmem_cache_
 #else
 		check_poison_obj(cachep, objp);
 #endif
-		poison_obj(cachep, objp, POISON_BEFORE);
+		poison_obj(cachep, objp, POISON_INUSE);
 	}
 	if (cachep->flags & SLAB_STORE_USER)
 		*dbg_userword(cachep, objp) = caller;
@@ -1890,6 +1966,15 @@ cache_alloc_debugcheck_after(kmem_cache_
 		*dbg_redzone1(cachep, objp) = RED_ACTIVE;
 		*dbg_redzone2(cachep, objp) = RED_ACTIVE;
 	}
+	{
+		int objnr;
+		struct slab *slabp;
+
+		slabp = GET_PAGE_SLAB(virt_to_page(objp));
+
+		objnr = (objp - slabp->s_mem) / cachep->objsize;
+		slab_bufctl(slabp)[objnr] = (int)caller;
+	}
 	objp += obj_dbghead(cachep);
 	if (cachep->ctor && cachep->flags & SLAB_POISON) {
 		unsigned long	ctor_flags = SLAB_CTOR_CONSTRUCTOR;
@@ -1951,12 +2036,14 @@ static void free_block(kmem_cache_t *cac
 		objnr = (objp - slabp->s_mem) / cachep->objsize;
 		check_slabp(cachep, slabp);
 #if DEBUG
+#if 0
 		if (slab_bufctl(slabp)[objnr] != BUFCTL_FREE) {
 			printk(KERN_ERR "slab: double free detected in cache '%s', objp %p.\n",
 						cachep->name, objp);
 			BUG();
 		}
 #endif
+#endif
 		slab_bufctl(slabp)[objnr] = slabp->free;
 		slabp->free = objnr;
 		STATS_DEC_ACTIVE(cachep);
@@ -2554,17 +2641,19 @@ next:
 }
 
 /*
- * This is a timer handler.  There is on per CPU.  It is called periodially
+ * This is a timer handler.  There is one per CPU.  It is called periodially
  * to shrink this CPU's caches.  Otherwise there could be memory tied up
  * for long periods (or for ever) due to load changes.
  */
-static void reap_timer_fnc(unsigned long data)
+static void reap_timer_fnc(unsigned long cpu)
 {
-	int cpu = smp_processor_id();
 	struct timer_list *rt = &__get_cpu_var(reap_timers);
 
-	cache_reap();
-	mod_timer(rt, jiffies + REAPTIMEOUT_CPUC + cpu);
+	/* CPU hotplug can drag us off cpu: don't run on wrong CPU */
+	if (!cpu_is_offline(cpu)) {
+		cache_reap();
+		mod_timer(rt, jiffies + REAPTIMEOUT_CPUC + cpu);
+	}
 }
 
 #ifdef CONFIG_PROC_FS
@@ -2735,6 +2824,29 @@ struct seq_operations slabinfo_op = {
 	.show	= s_show,
 };
 
+static void do_dump_slabp(kmem_cache_t *cachep)
+{
+#if DEBUG
+	struct list_head *q;
+
+	check_irq_on();
+	spin_lock_irq(&cachep->spinlock);
+	list_for_each(q,&cachep->lists.slabs_full) {
+		struct slab *slabp;
+		int i;
+		slabp = list_entry(q, struct slab, list);
+		for (i = 0; i < cachep->num; i++) {
+			unsigned long sym = slab_bufctl(slabp)[i];
+
+			printk("obj %p/%d: %p", slabp, i, (void *)sym);
+			print_symbol(" <%s>", sym);
+			printk("\n");
+		}
+	}
+	spin_unlock_irq(&cachep->spinlock);
+#endif
+}
+
 #define MAX_SLABINFO_WRITE 128
 /**
  * slabinfo_write - Tuning for the slab allocator
@@ -2775,9 +2887,11 @@ ssize_t slabinfo_write(struct file *file
 			    batchcount < 1 ||
 			    batchcount > limit ||
 			    shared < 0) {
-				res = -EINVAL;
+				do_dump_slabp(cachep);
+				res = 0;
 			} else {
-				res = do_tune_cpucache(cachep, limit, batchcount, shared);
+				res = do_tune_cpucache(cachep, limit,
+							batchcount, shared);
 			}
 			break;
 		}
@@ -2866,14 +2980,7 @@ void ptrinfo(unsigned long addr)
 			kernel_map_pages(virt_to_page(objp),
 					c->objsize/PAGE_SIZE, 1);
 
-			if (c->flags & SLAB_RED_ZONE)
-				printk("redzone: 0x%lx/0x%lx.\n",
-					*dbg_redzone1(c, objp),
-					*dbg_redzone2(c, objp));
-
-			if (c->flags & SLAB_STORE_USER)
-				printk("Last user: %p.\n",
-					*dbg_userword(c, objp));
+			print_objinfo(c, objp, 2);
 		}
 		spin_unlock_irqrestore(&c->spinlock, flags);
 
--- diff/mm/swap.c	2004-01-19 10:22:59.000000000 +0000
+++ source/mm/swap.c	2004-02-23 13:56:48.000000000 +0000
@@ -27,6 +27,9 @@
 #include <linux/module.h>
 #include <linux/percpu_counter.h>
 #include <linux/percpu.h>
+#include <linux/cpu.h>
+#include <linux/notifier.h>
+#include <linux/init.h>
 
 /* How many pages do we try to swap or page in/out together? */
 int page_cluster;
@@ -381,7 +384,37 @@ void vm_acct_memory(long pages)
 	preempt_enable();
 }
 EXPORT_SYMBOL(vm_acct_memory);
-#endif
+
+#ifdef CONFIG_HOTPLUG_CPU
+static void lru_drain_cache(unsigned int cpu)
+{
+	struct pagevec *pvec = &per_cpu(lru_add_pvecs, cpu);
+
+	/* CPU is dead, so no locking needed. */
+	if (pagevec_count(pvec))
+		__pagevec_lru_add(pvec);
+	pvec = &per_cpu(lru_add_active_pvecs, cpu);
+	if (pagevec_count(pvec))
+		__pagevec_lru_add_active(pvec);
+}
+
+/* Drop the CPU's cached committed space back into the central pool. */
+static int cpu_swap_callback(struct notifier_block *nfb,
+			     unsigned long action,
+			     void *hcpu)
+{
+	long *committed;
+
+	committed = &per_cpu(committed_space, (long)hcpu);
+	if (action == CPU_DEAD) {
+		atomic_add(*committed, &vm_committed_space);
+		*committed = 0;
+		lru_drain_cache((long)hcpu);
+	}
+	return NOTIFY_OK;
+}
+#endif /* CONFIG_HOTPLUG_CPU */
+#endif /* CONFIG_SMP */
 
 #ifdef CONFIG_SMP
 void percpu_counter_mod(struct percpu_counter *fbc, long amount)
@@ -420,4 +453,5 @@ void __init swap_setup(void)
 	 * Right now other parts of the system means that we
 	 * _really_ don't want to cluster much more
 	 */
+	hotcpu_notifier(cpu_swap_callback, 0);
 }
--- diff/mm/swap_state.c	2003-08-20 14:16:34.000000000 +0100
+++ source/mm/swap_state.c	2004-02-23 13:56:48.000000000 +0000
@@ -38,6 +38,7 @@ struct address_space swapper_space = {
 	.truncate_count  = ATOMIC_INIT(0),
 	.private_lock	= SPIN_LOCK_UNLOCKED,
 	.private_list	= LIST_HEAD_INIT(swapper_space.private_list),
+	.wb_rwsema	= __RWSEM_INITIALIZER(swapper_space.wb_rwsema)
 };
 
 #define INC_CACHE_INFO(x)	do { swap_cache_info.x++; } while (0)
--- diff/mm/swapfile.c	2004-02-18 08:54:13.000000000 +0000
+++ source/mm/swapfile.c	2004-02-23 13:56:48.000000000 +0000
@@ -387,7 +387,7 @@ static void
 unuse_pte(struct vm_area_struct *vma, unsigned long address, pte_t *dir,
 	swp_entry_t entry, struct page *page, struct pte_chain **pte_chainp)
 {
-	vma->vm_mm->rss++;
+	inc_rss(vma->vm_mm, page);
 	get_page(page);
 	set_pte(dir, pte_mkold(mk_pte(page, vma->vm_page_prot)));
 	*pte_chainp = page_add_rmap(page, dir, *pte_chainp);
--- diff/mm/truncate.c	2003-10-09 09:47:34.000000000 +0100
+++ source/mm/truncate.c	2004-02-23 13:56:48.000000000 +0000
@@ -174,6 +174,14 @@ void truncate_inode_pages(struct address
 		}
 		pagevec_release(&pvec);
 	}
+
+	if (lstart == 0) {
+		WARN_ON(mapping->nrpages);
+		WARN_ON(!list_empty(&mapping->clean_pages));
+		WARN_ON(!list_empty(&mapping->dirty_pages));
+		WARN_ON(!list_empty(&mapping->locked_pages));
+		WARN_ON(!list_empty(&mapping->io_pages));
+	}
 }
 
 EXPORT_SYMBOL(truncate_inode_pages);
--- diff/mm/vmscan.c	2004-02-18 08:54:13.000000000 +0000
+++ source/mm/vmscan.c	2004-02-23 13:56:48.000000000 +0000
@@ -30,6 +30,8 @@
 #include <linux/backing-dev.h>
 #include <linux/rmap-locking.h>
 #include <linux/topology.h>
+#include <linux/cpu.h>
+#include <linux/notifier.h>
 
 #include <asm/pgalloc.h>
 #include <asm/tlbflush.h>
@@ -43,14 +45,15 @@
 int vm_swappiness = 60;
 static long total_memory;
 
+#define lru_to_page(_head) (list_entry((_head)->prev, struct page, lru))
+
 #ifdef ARCH_HAS_PREFETCH
 #define prefetch_prev_lru_page(_page, _base, _field)			\
 	do {								\
 		if ((_page)->lru.prev != _base) {			\
 			struct page *prev;				\
 									\
-			prev = list_entry(_page->lru.prev,		\
-					struct page, lru);		\
+			prev = lru_to_page(&(_page)->lru);		\
 			prefetch(&prev->_field);			\
 		}							\
 	} while (0)
@@ -64,8 +67,7 @@ static long total_memory;
 		if ((_page)->lru.prev != _base) {			\
 			struct page *prev;				\
 									\
-			prev = list_entry(_page->lru.prev,		\
-					struct page, lru);		\
+			prev = lru_to_page(&(_page)->lru);		\
 			prefetchw(&prev->_field);			\
 		}							\
 	} while (0)
@@ -135,7 +137,7 @@ EXPORT_SYMBOL(remove_shrinker);
  *
  * We do weird things to avoid (scanned*seeks*entries) overflowing 32 bits.
  */
-static int shrink_slab(long scanned, unsigned int gfp_mask)
+static int shrink_slab(unsigned long scanned, unsigned int gfp_mask)
 {
 	struct shrinker *shrinker;
 	long pages;
@@ -147,7 +149,7 @@ static int shrink_slab(long scanned, uns
 	list_for_each_entry(shrinker, &shrinker_list, list) {
 		unsigned long long delta;
 
-		delta = 4 * (scanned / shrinker->seeks);
+		delta = 4 * scanned / shrinker->seeks;
 		delta *= (*shrinker->shrinker)(0, gfp_mask);
 		do_div(delta, pages + 1);
 		shrinker->nr += delta;
@@ -243,8 +245,7 @@ static void handle_write_error(struct ad
  * shrink_list returns the number of reclaimed pages
  */
 static int
-shrink_list(struct list_head *page_list, unsigned int gfp_mask,
-		int *max_scan, int *nr_mapped)
+shrink_list(struct list_head *page_list, unsigned int gfp_mask, int *nr_mapped)
 {
 	struct address_space *mapping;
 	LIST_HEAD(ret_pages);
@@ -260,7 +261,7 @@ shrink_list(struct list_head *page_list,
 		int may_enter_fs;
 		int referenced;
 
-		page = list_entry(page_list->prev, struct page, lru);
+		page = lru_to_page(page_list);
 		list_del(&page->lru);
 
 		if (TestSetPageLocked(page))
@@ -459,9 +460,6 @@ keep:
 	list_splice(&ret_pages, page_list);
 	if (pagevec_count(&freed_pvec))
 		__pagevec_release_nonlru(&freed_pvec);
-	mod_page_state(pgsteal, ret);
-	if (current_is_kswapd())
-		mod_page_state(kswapd_steal, ret);
 	mod_page_state(pgactivate, pgactivate);
 	return ret;
 }
@@ -479,13 +477,15 @@ keep:
  */
 static int
 shrink_cache(const int nr_pages, struct zone *zone,
-		unsigned int gfp_mask, int max_scan, int *nr_mapped)
+		unsigned int gfp_mask, int max_scan, int *nr_scanned)
 {
 	LIST_HEAD(page_list);
 	struct pagevec pvec;
 	int nr_to_process;
 	int ret = 0;
 
+	*nr_scanned = 0;
+
 	/*
 	 * Try to ensure that we free `nr_pages' pages in one pass of the loop.
 	 */
@@ -496,8 +496,9 @@ shrink_cache(const int nr_pages, struct 
 	pagevec_init(&pvec, 1);
 
 	lru_add_drain();
+again:
 	spin_lock_irq(&zone->lru_lock);
-	while (max_scan > 0 && ret < nr_pages) {
+	while (*nr_scanned < max_scan && ret < nr_pages) {
 		struct page *page;
 		int nr_taken = 0;
 		int nr_scan = 0;
@@ -505,8 +506,7 @@ shrink_cache(const int nr_pages, struct 
 
 		while (nr_scan++ < nr_to_process &&
 				!list_empty(&zone->inactive_list)) {
-			page = list_entry(zone->inactive_list.prev,
-						struct page, lru);
+			page = lru_to_page(&zone->inactive_list);
 
 			prefetchw_prev_lru_page(page,
 						&zone->inactive_list, flags);
@@ -528,23 +528,29 @@ shrink_cache(const int nr_pages, struct 
 		zone->pages_scanned += nr_taken;
 		spin_unlock_irq(&zone->lru_lock);
 
+		*nr_scanned += nr_scan;
 		if (nr_taken == 0)
-			goto done;
+			goto again;
 
 		max_scan -= nr_scan;
 		mod_page_state(pgscan, nr_scan);
-		nr_freed = shrink_list(&page_list, gfp_mask,
-					&max_scan, nr_mapped);
+		nr_freed = shrink_list(&page_list, gfp_mask, nr_scanned);
+		if (current_is_kswapd())
+			mod_page_state(kswapd_steal, nr_freed);
+		if (is_highmem(zone))
+			mod_page_state(pgsteal_hi, nr_freed);
+		else
+			mod_page_state(pgsteal_lo, nr_freed);
 		ret += nr_freed;
 		if (nr_freed <= 0 && list_empty(&page_list))
-			goto done;
+			goto again;
 
-		spin_lock_irq(&zone->lru_lock);
 		/*
 		 * Put back any unfreeable pages.
 		 */
+		spin_lock_irq(&zone->lru_lock);
 		while (!list_empty(&page_list)) {
-			page = list_entry(page_list.prev, struct page, lru);
+			page = lru_to_page(&page_list);
 			if (TestSetPageLRU(page))
 				BUG();
 			list_del(&page->lru);
@@ -560,11 +566,42 @@ shrink_cache(const int nr_pages, struct 
 		}
   	}
 	spin_unlock_irq(&zone->lru_lock);
-done:
 	pagevec_release(&pvec);
 	return ret;
 }
 
+
+/* move pages from @page_list to the @spot, that should be somewhere on the
+ * @zone->active_list */
+static int
+spill_on_spot(struct zone *zone, struct list_head *page_list,
+		struct list_head *spot, struct pagevec *pvec)
+{
+	struct page *page;
+	int          moved;
+
+	moved = 0;
+	while (!list_empty(page_list)) {
+		page = lru_to_page(page_list);
+		prefetchw_prev_lru_page(page, page_list, flags);
+		if (TestSetPageLRU(page))
+			BUG();
+		BUG_ON(!PageActive(page));
+		list_move(&page->lru, spot);
+		moved++;
+		if (!pagevec_add(pvec, page)) {
+			zone->nr_active += moved;
+			moved = 0;
+			spin_unlock_irq(&zone->lru_lock);
+			__pagevec_release(pvec);
+			spin_lock_irq(&zone->lru_lock);
+		}
+	}
+	return moved;
+}
+
+
+
 /*
  * This moves pages from the active list to the inactive list.
  *
@@ -584,44 +621,25 @@ done:
  */
 static void
 refill_inactive_zone(struct zone *zone, const int nr_pages_in,
-			struct page_state *ps, int priority)
+			struct page_state *ps)
 {
 	int pgmoved;
 	int pgdeactivate = 0;
 	int nr_pages = nr_pages_in;
 	LIST_HEAD(l_hold);	/* The pages which were snipped off */
 	LIST_HEAD(l_inactive);	/* Pages to go onto the inactive_list */
-	LIST_HEAD(l_active);	/* Pages to go onto the active_list */
+	LIST_HEAD(l_ignore);	/* Pages to be returned to the active_list */
+	LIST_HEAD(l_active);	/* Pages to go onto the head of the
+				 * active_list */
+
 	struct page *page;
+	struct page *scan;
 	struct pagevec pvec;
 	int reclaim_mapped = 0;
 	long mapped_ratio;
 	long distress;
 	long swap_tendency;
 
-	lru_add_drain();
-	pgmoved = 0;
-	spin_lock_irq(&zone->lru_lock);
-	while (nr_pages && !list_empty(&zone->active_list)) {
-		page = list_entry(zone->active_list.prev, struct page, lru);
-		prefetchw_prev_lru_page(page, &zone->active_list, flags);
-		if (!TestClearPageLRU(page))
-			BUG();
-		list_del(&page->lru);
-		if (page_count(page) == 0) {
-			/* It is currently in pagevec_release() */
-			SetPageLRU(page);
-			list_add(&page->lru, &zone->active_list);
-		} else {
-			page_cache_get(page);
-			list_add(&page->lru, &l_hold);
-			pgmoved++;
-		}
-		nr_pages--;
-	}
-	zone->nr_active -= pgmoved;
-	spin_unlock_irq(&zone->lru_lock);
-
 	/*
 	 * `distress' is a measure of how much trouble we're having reclaiming
 	 * pages.  0 -> no problems.  100 -> great trouble.
@@ -653,10 +671,63 @@ refill_inactive_zone(struct zone *zone, 
 	if (swap_tendency >= 100)
 		reclaim_mapped = 1;
 
+	scan = zone->scan_page;
+	lru_add_drain();
+	pgmoved = 0;
+	spin_lock_irq(&zone->lru_lock);
+	if (reclaim_mapped) {
+		/*
+		 * When scanning active_list with !reclaim_mapped mapped
+		 * inactive pages are left behind zone->scan_page. If zone is
+		 * switched to reclaim_mapped mode reset zone->scan_page to
+		 * the end of inactive list so that inactive mapped pages are
+		 * re-scanned.
+		 */
+		list_move_tail(&scan->lru, &zone->active_list);
+	}
+	while (nr_pages && zone->active_list.prev != zone->active_list.next) {
+		/*
+		 * if head of active list reached---wrap to the tail
+		 */
+		if (scan->lru.prev == &zone->active_list)
+			list_move_tail(&scan->lru, &zone->active_list);
+		page = lru_to_page(&scan->lru);
+		prefetchw_prev_lru_page(page, &zone->active_list, flags);
+		if (!TestClearPageLRU(page))
+			BUG();
+		list_del(&page->lru);
+		if (page_count(page) == 0) {
+			/* It is currently in pagevec_release() */
+			SetPageLRU(page);
+			list_add(&page->lru, &zone->active_list);
+		} else {
+			page_cache_get(page);
+			list_add(&page->lru, &l_hold);
+			pgmoved++;
+		}
+		nr_pages--;
+	}
+	zone->nr_active -= pgmoved;
+	spin_unlock_irq(&zone->lru_lock);
+
 	while (!list_empty(&l_hold)) {
-		page = list_entry(l_hold.prev, struct page, lru);
+		page = lru_to_page(&l_hold);
 		list_del(&page->lru);
 		if (page_mapped(page)) {
+
+			/*
+			 * Don't clear page referenced if we're not going
+			 * to use it.
+			 */
+			if (!reclaim_mapped) {
+				list_add(&page->lru, &l_ignore);
+				continue;
+			}
+
+			/*
+			 * probably it would be useful to transfer dirty bit
+			 * from pte to the @page here.
+			 */
 			pte_chain_lock(page);
 			if (page_mapped(page) && page_referenced(page)) {
 				pte_chain_unlock(page);
@@ -664,10 +735,6 @@ refill_inactive_zone(struct zone *zone, 
 				continue;
 			}
 			pte_chain_unlock(page);
-			if (!reclaim_mapped) {
-				list_add(&page->lru, &l_active);
-				continue;
-			}
 		}
 		/*
 		 * FIXME: need to consider page_count(page) here if/when we
@@ -685,7 +752,7 @@ refill_inactive_zone(struct zone *zone, 
 	pgmoved = 0;
 	spin_lock_irq(&zone->lru_lock);
 	while (!list_empty(&l_inactive)) {
-		page = list_entry(l_inactive.prev, struct page, lru);
+		page = lru_to_page(&l_inactive);
 		prefetchw_prev_lru_page(page, &l_inactive, flags);
 		if (TestSetPageLRU(page))
 			BUG();
@@ -712,23 +779,9 @@ refill_inactive_zone(struct zone *zone, 
 		spin_lock_irq(&zone->lru_lock);
 	}
 
-	pgmoved = 0;
-	while (!list_empty(&l_active)) {
-		page = list_entry(l_active.prev, struct page, lru);
-		prefetchw_prev_lru_page(page, &l_active, flags);
-		if (TestSetPageLRU(page))
-			BUG();
-		BUG_ON(!PageActive(page));
-		list_move(&page->lru, &zone->active_list);
-		pgmoved++;
-		if (!pagevec_add(&pvec, page)) {
+	pgmoved = spill_on_spot(zone, &l_active, &zone->active_list, &pvec);
 			zone->nr_active += pgmoved;
-			pgmoved = 0;
-			spin_unlock_irq(&zone->lru_lock);
-			__pagevec_release(&pvec);
-			spin_lock_irq(&zone->lru_lock);
-		}
-	}
+	pgmoved = spill_on_spot(zone, &l_ignore, &scan->lru, &pvec);
 	zone->nr_active += pgmoved;
 	spin_unlock_irq(&zone->lru_lock);
 	pagevec_release(&pvec);
@@ -743,41 +796,49 @@ refill_inactive_zone(struct zone *zone, 
  * direct reclaim.
  */
 static int
-shrink_zone(struct zone *zone, int max_scan, unsigned int gfp_mask,
-	const int nr_pages, int *nr_mapped, struct page_state *ps, int priority)
+shrink_zone(struct zone *zone, unsigned int gfp_mask,
+	int nr_pages, int *nr_scanned, struct page_state *ps, int priority)
 {
-	unsigned long ratio;
+	unsigned long imbalance;
+	unsigned long nr_refill_inact;
+	unsigned long max_scan;
 
 	/*
 	 * Try to keep the active list 2/3 of the size of the cache.  And
 	 * make sure that refill_inactive is given a decent number of pages.
 	 *
-	 * The "ratio+1" here is important.  With pagecache-intensive workloads
-	 * the inactive list is huge, and `ratio' evaluates to zero all the
-	 * time.  Which pins the active list memory.  So we add one to `ratio'
-	 * just to make sure that the kernel will slowly sift through the
-	 * active list.
+	 * Keeping imbalance > 0 is important.  With pagecache-intensive loads
+	 * the inactive list is huge, and imbalance evaluates to zero all the
+	 * time which would pin the active list memory.
 	 */
-	ratio = (unsigned long)nr_pages * zone->nr_active /
-				((zone->nr_inactive | 1) * 2);
-	atomic_add(ratio+1, &zone->refill_counter);
-	if (atomic_read(&zone->refill_counter) > SWAP_CLUSTER_MAX) {
-		int count;
+	if (zone->nr_active >= zone->nr_inactive * 4) {
+		/* ratio will be >= 2 */
+		imbalance = 8*nr_pages;
+	} else if (zone->nr_active >= zone->nr_inactive * 2) {
+		/* 1 < ratio < 2 */
+		imbalance = 4 * nr_pages*zone->nr_active /
+				(zone->nr_inactive * 2 + 1);
+	} else {
+		imbalance = nr_pages / 2;
+	}
 
-		/*
-		 * Don't try to bring down too many pages in one attempt.
-		 * If this fails, the caller will increase `priority' and
-		 * we'll try again, with an increased chance of reclaiming
-		 * mapped memory.
-		 */
-		count = atomic_read(&zone->refill_counter);
-		if (count > SWAP_CLUSTER_MAX * 4)
-			count = SWAP_CLUSTER_MAX * 4;
-		atomic_set(&zone->refill_counter, 0);
-		refill_inactive_zone(zone, count, ps, priority);
+	imbalance++;
+
+	nr_refill_inact = atomic_read(&zone->refill_counter) + imbalance;
+	if (nr_refill_inact > SWAP_CLUSTER_MAX) {
+		refill_inactive_zone(zone, nr_refill_inact, ps);
+		nr_refill_inact = 0;
 	}
-	return shrink_cache(nr_pages, zone, gfp_mask,
-				max_scan, nr_mapped);
+	atomic_set(&zone->refill_counter, nr_refill_inact);
+
+	/*
+	 * Now pull pages from the inactive list
+	 */
+	max_scan = zone->nr_inactive >> priority;
+	if (max_scan < nr_pages * 2)
+		max_scan = nr_pages * 2;
+
+	return shrink_cache(nr_pages, zone, gfp_mask, max_scan, nr_scanned);
 }
 
 /*
@@ -798,16 +859,14 @@ shrink_zone(struct zone *zone, int max_s
  */
 static int
 shrink_caches(struct zone **zones, int priority, int *total_scanned,
-		int gfp_mask, int nr_pages, struct page_state *ps)
+		int gfp_mask, struct page_state *ps)
 {
 	int ret = 0;
 	int i;
 
 	for (i = 0; zones[i] != NULL; i++) {
-		int to_reclaim = max(nr_pages, SWAP_CLUSTER_MAX);
 		struct zone *zone = zones[i];
-		int nr_mapped = 0;
-		int max_scan;
+		int nr_scanned;
 
 		if (zone->free_pages < zone->pages_high)
 			zone->temp_priority = priority;
@@ -815,18 +874,9 @@ shrink_caches(struct zone **zones, int p
 		if (zone->all_unreclaimable && priority != DEF_PRIORITY)
 			continue;	/* Let kswapd poll it */
 
-		/*
-		 * If we cannot reclaim `nr_pages' pages by scanning twice
-		 * that many pages then fall back to the next zone.
-		 */
-		max_scan = zone->nr_inactive >> priority;
-		if (max_scan < to_reclaim * 2)
-			max_scan = to_reclaim * 2;
-		ret += shrink_zone(zone, max_scan, gfp_mask,
-				to_reclaim, &nr_mapped, ps, priority);
-		*total_scanned += max_scan + nr_mapped;
-		if (ret >= nr_pages)
-			break;
+		ret += shrink_zone(zone, gfp_mask, zone->reclaim_batch,
+				&nr_scanned, ps, priority);
+		*total_scanned += nr_scanned;
 	}
 	return ret;
 }
@@ -853,7 +903,6 @@ int try_to_free_pages(struct zone **zone
 {
 	int priority;
 	int ret = 0;
-	const int nr_pages = SWAP_CLUSTER_MAX;
 	int nr_reclaimed = 0;
 	struct reclaim_state *reclaim_state = current->reclaim_state;
 	int i;
@@ -869,32 +918,43 @@ int try_to_free_pages(struct zone **zone
 
 		get_page_state(&ps);
 		nr_reclaimed += shrink_caches(zones, priority, &total_scanned,
-						gfp_mask, nr_pages, &ps);
-		if (nr_reclaimed >= nr_pages) {
+						gfp_mask, &ps);
+
+		shrink_slab(total_scanned, gfp_mask);
+		if (reclaim_state) {
+			nr_reclaimed += reclaim_state->reclaimed_slab;
+			reclaim_state->reclaimed_slab = 0;
+		}
+
+		if (nr_reclaimed >= SWAP_CLUSTER_MAX) {
 			ret = 1;
+			if (gfp_mask & __GFP_FS)
+				wakeup_bdflush(total_scanned);
 			goto out;
 		}
+
+		/* Don't stall on the first run - it might be bad luck */
+		if (likely(priority == DEF_PRIORITY))
+			continue;
+
+		/* Let the caller handle it */
 		if (!(gfp_mask & __GFP_FS))
-			break;		/* Let the caller handle it */
+			goto out;
+
 		/*
-		 * Try to write back as many pages as we just scanned.  Not
-		 * sure if that makes sense, but it's an attempt to avoid
-		 * creating IO storms unnecessarily
+		 * Try to write back as many pages as we just scanned.
+		 * Not sure if that makes sense, but it's an attempt
+		 * to avoid creating IO storms unnecessarily
 		 */
 		wakeup_bdflush(total_scanned);
 
 		/* Take a nap, wait for some writeback to complete */
 		blk_congestion_wait(WRITE, HZ/10);
-		if (zones[0] - zones[0]->zone_pgdat->node_zones < ZONE_HIGHMEM) {
-			shrink_slab(total_scanned, gfp_mask);
-			if (reclaim_state) {
-				nr_reclaimed += reclaim_state->reclaimed_slab;
-				reclaim_state->reclaimed_slab = 0;
-			}
-		}
 	}
-	if ((gfp_mask & __GFP_FS) && !(gfp_mask & __GFP_NORETRY))
+
+	if (!(gfp_mask & __GFP_NORETRY))
 		out_of_memory();
+
 out:
 	for (i = 0; zones[i] != 0; i++)
 		zones[i]->prev_priority = zones[i]->temp_priority;
@@ -939,42 +999,41 @@ static int balance_pgdat(pg_data_t *pgda
 
 		for (i = 0; i < pgdat->nr_zones; i++) {
 			struct zone *zone = pgdat->node_zones + i;
-			int nr_mapped = 0;
-			int max_scan;
+			int nr_scanned;
 			int to_reclaim;
+			int reclaimed;
 
 			if (zone->all_unreclaimable && priority != DEF_PRIORITY)
 				continue;
 
-			if (nr_pages && to_free > 0) {	/* Software suspend */
+			if (nr_pages)		/* Software suspend */
 				to_reclaim = min(to_free, SWAP_CLUSTER_MAX*8);
-			} else {			/* Zone balancing */
-				to_reclaim = zone->pages_high-zone->free_pages;
-				if (to_reclaim <= 0)
-					continue;
-			}
-			zone->temp_priority = priority;
+			else			/* Zone balancing */
+				to_reclaim = zone->reclaim_batch;
+
 			all_zones_ok = 0;
-			max_scan = zone->nr_inactive >> priority;
-			if (max_scan < to_reclaim * 2)
-				max_scan = to_reclaim * 2;
-			if (max_scan < SWAP_CLUSTER_MAX)
-				max_scan = SWAP_CLUSTER_MAX;
-			to_free -= shrink_zone(zone, max_scan, GFP_KERNEL,
-					to_reclaim, &nr_mapped, ps, priority);
-			if (i < ZONE_HIGHMEM) {
-				reclaim_state->reclaimed_slab = 0;
-				shrink_slab(max_scan + nr_mapped, GFP_KERNEL);
-				to_free -= reclaim_state->reclaimed_slab;
-			}
+			zone->temp_priority = priority;
+			reclaimed = shrink_zone(zone, GFP_KERNEL,
+					to_reclaim, &nr_scanned, ps, priority);
+			reclaim_state->reclaimed_slab = 0;
+			shrink_slab(nr_scanned, GFP_KERNEL);
+			reclaimed += reclaim_state->reclaimed_slab;
+			to_free -= reclaimed;
 			if (zone->all_unreclaimable)
 				continue;
 			if (zone->pages_scanned > zone->present_pages * 2)
 				zone->all_unreclaimable = 1;
 		}
+		if (nr_pages && to_free > 0)
+			continue;	/* swsusp: need to do more work */
 		if (all_zones_ok)
-			break;
-		if (to_free > 0)
+			break;		/* kswapd: all done */
+		/*
+		 * OK, kswapd is getting into trouble.  Take a nap, then take
+		 * another pass across the zones. Don't stall on the first
+		 * pass.
+		 */
+		if (priority < DEF_PRIORITY)
 			blk_congestion_wait(WRITE, HZ/10);
 	}
 
@@ -1085,13 +1144,39 @@ int shrink_all_memory(int nr_pages)
 }
 #endif
 
+#ifdef CONFIG_HOTPLUG_CPU
+/* It's optimal to keep kswapds on the same CPUs as their memory, but
+   not required for correctness.  So if the last cpu in a node goes
+   away, we get changed to run anywhere: as the first one comes back,
+   restore their cpu bindings. */
+static int __devinit cpu_callback(struct notifier_block *nfb,
+				  unsigned long action,
+				  void *hcpu)
+{
+	pg_data_t *pgdat;
+	cpumask_t mask;
+
+	if (action == CPU_ONLINE) {
+		for_each_pgdat(pgdat) {
+			mask = node_to_cpumask(pgdat->node_id);
+			if (any_online_cpu(mask) != NR_CPUS)
+				/* One of our CPUs online: restore mask */
+				set_cpus_allowed(pgdat->kswapd, mask);
+		}
+	}
+	return NOTIFY_OK;
+}
+#endif /* CONFIG_HOTPLUG_CPU */
+
 static int __init kswapd_init(void)
 {
 	pg_data_t *pgdat;
 	swap_setup();
 	for_each_pgdat(pgdat)
-		kernel_thread(kswapd, pgdat, CLONE_KERNEL);
+		pgdat->kswapd
+		= find_task_by_pid(kernel_thread(kswapd, pgdat, CLONE_KERNEL));
 	total_memory = nr_free_pagecache_pages();
+	hotcpu_notifier(cpu_callback, 0);
 	return 0;
 }
 
--- diff/net/8021q/vlan.c	2003-10-09 09:47:34.000000000 +0100
+++ source/net/8021q/vlan.c	2004-02-23 13:56:48.000000000 +0000
@@ -566,7 +566,7 @@ out_free_unregister:
 	goto out_put_dev;
 
 out_free_newdev:
-	kfree(new_dev);
+	free_netdev(new_dev);
 
 out_unlock:
 	rtnl_unlock();
--- diff/net/Kconfig	2004-02-18 08:54:13.000000000 +0000
+++ source/net/Kconfig	2004-02-23 13:56:48.000000000 +0000
@@ -32,8 +32,7 @@ config PACKET
 	  to work, choose Y.
 
 	  To compile this driver as a module, choose M here: the module will
-	  be called af_packet. If you use modprobe or kmod, you may also
-	  want to add "alias net-pf-17 af_packet" to /etc/modules.conf.
+	  be called af_packet.
 
 	  If unsure, say Y.
 
@@ -67,11 +66,8 @@ config UNIX
 	  want to say Y here.
 
 	  To compile this driver as a module, choose M here: the module will be
-	  called unix.  If you try building this as a module and you have
-	  said Y to "Kernel module loader support" above, be sure to add
-	  'alias net-pf-1 unix' to your /etc/modules.conf file. Note that
-	  several important services won't work correctly if you say M here
-	  and then neglect to load the module.
+	  called unix.  Note that several important services won't work
+	  correctly if you say M here and then neglect to load the module.
 
 	  Say Y unless you know what you are doing.
 
@@ -127,9 +123,7 @@ config IPV6
 	  in the kernel source.
 
 	  To compile this protocol support as a module, choose M here: the 
-	  module will be called ipv6.  If you try building this as a module 
-	  and you have said Y to "Kernel module loader support" above, 
-	  be sure to add 'alias net-pf-10 ipv6' to your /etc/modules.conf file.
+	  module will be called ipv6.
 
 	  It is safe to say N here for now.
 
@@ -664,4 +658,19 @@ source "net/irda/Kconfig"
 
 source "net/bluetooth/Kconfig"
 
+config KGDBOE
+	def_bool X86 && KGDB
+
+config NETPOLL
+	def_bool NETCONSOLE || KGDBOE
+
+config NETPOLL_RX
+	def_bool KGDBOE
+
+config NETPOLL_TRAP
+	def_bool KGDBOE
+
+config NET_POLL_CONTROLLER
+	def_bool NETPOLL
+
 endmenu
--- diff/net/appletalk/ddp.c	2004-02-18 08:54:13.000000000 +0000
+++ source/net/appletalk/ddp.c	2004-02-23 13:56:48.000000000 +0000
@@ -1659,7 +1659,7 @@ static int atalk_sendmsg(struct kiocb *i
 	ddp->deh_dport = usat->sat_port;
 	ddp->deh_sport = at->src_port;
 
-	SOCK_DEBUG(sk, "SK %p: Copy user data (%d bytes).\n", sk, len);
+	SOCK_DEBUG(sk, "SK %p: Copy user data (%Zd bytes).\n", sk, len);
 
 	err = memcpy_fromiovec(skb_put(skb, len), msg->msg_iov, len);
 	if (err) {
@@ -1706,7 +1706,7 @@ static int atalk_sendmsg(struct kiocb *i
 			kfree_skb(skb);
 		/* else queued/sent above in the aarp queue */
 	}
-	SOCK_DEBUG(sk, "SK %p: Done write (%d).\n", sk, len);
+	SOCK_DEBUG(sk, "SK %p: Done write (%Zd).\n", sk, len);
 
 	return len;
 }
--- diff/net/atm/clip.c	2004-02-18 08:54:13.000000000 +0000
+++ source/net/atm/clip.c	2004-02-23 13:56:48.000000000 +0000
@@ -829,7 +829,7 @@ static void atmarp_info(struct seq_file 
 	    !clip_vcc || clip_vcc->encap ? "LLC" : "NULL",
 	    (jiffies-(clip_vcc ? clip_vcc->last_use : entry->neigh->used))/HZ);
 
-	off = snprintf(buf, sizeof(buf) - 1, "%d.%d.%d.%d", NIPQUAD(entry->ip));
+	off = scnprintf(buf, sizeof(buf) - 1, "%d.%d.%d.%d", NIPQUAD(entry->ip));
 	while (off < 16)
 		buf[off++] = ' ';
 	buf[off] = '\0';
--- diff/net/atm/lec.c	2003-09-30 15:46:21.000000000 +0100
+++ source/net/atm/lec.c	2004-02-23 13:56:48.000000000 +0000
@@ -798,7 +798,7 @@ lecd_attach(struct atm_vcc *vcc, int arg
                         return -ENOMEM;
                 snprintf(dev_lec[i]->name, IFNAMSIZ, "lec%d", i);
                 if (register_netdev(dev_lec[i])) {
-                        kfree(dev_lec[i]);
+                        free_netdev(dev_lec[i]);
                         return -EINVAL;
                 }
 
--- diff/net/bluetooth/bnep/core.c	2004-02-09 10:36:12.000000000 +0000
+++ source/net/bluetooth/bnep/core.c	2004-02-23 13:56:48.000000000 +0000
@@ -501,7 +501,7 @@ static int bnep_session(void *arg)
 	__bnep_unlink_session(s);
 
 	up_write(&bnep_session_sem);
-	kfree(dev);
+	free_netdev(dev);
 	return 0;
 }
 
@@ -588,7 +588,7 @@ int bnep_add_connection(struct bnep_conn
 
 failed:
 	up_write(&bnep_session_sem);
-	kfree(dev);
+	free_netdev(dev);
 	return err;
 }
 
--- diff/net/bluetooth/rfcomm/sock.c	2004-02-09 10:36:12.000000000 +0000
+++ source/net/bluetooth/rfcomm/sock.c	2004-02-23 13:56:48.000000000 +0000
@@ -501,7 +501,7 @@ static int rfcomm_sock_sendmsg(struct ki
 	lock_sock(sk);
 
 	while (len) {
-		size_t size = min(len, d->mtu);
+		size_t size = min_t(size_t, len, d->mtu);
 		
 		skb = sock_alloc_send_skb(sk, size + RFCOMM_SKB_RESERVE,
 				msg->msg_flags & MSG_DONTWAIT, &err);
--- diff/net/bridge/netfilter/ebt_vlan.c	2003-10-09 09:47:34.000000000 +0100
+++ source/net/bridge/netfilter/ebt_vlan.c	2004-02-23 13:56:48.000000000 +0000
@@ -25,13 +25,13 @@
 #include <linux/netfilter_bridge/ebt_vlan.h>
 
 static unsigned char debug;
-#define MODULE_VERSION "0.6"
+#define MODULE_VERS "0.6"
 
 MODULE_PARM(debug, "0-1b");
 MODULE_PARM_DESC(debug, "debug=1 is turn on debug messages");
 MODULE_AUTHOR("Nick Fedchik <nick@fedchik.org.ua>");
 MODULE_DESCRIPTION("802.1Q match module (ebtables extension), v"
-		   MODULE_VERSION);
+		   MODULE_VERS);
 MODULE_LICENSE("GPL");
 
 
@@ -179,7 +179,7 @@ static struct ebt_match filter_vlan = {
 static int __init init(void)
 {
 	DEBUG_MSG("ebtables 802.1Q extension module v"
-		  MODULE_VERSION "\n");
+		  MODULE_VERS "\n");
 	DEBUG_MSG("module debug=%d\n", !!debug);
 	return ebt_register_match(&filter_vlan);
 }
--- diff/net/compat.c	2004-01-19 10:22:59.000000000 +0000
+++ source/net/compat.c	2004-02-23 13:56:48.000000000 +0000
@@ -18,6 +18,7 @@
 #include <linux/file.h>
 #include <linux/icmpv6.h>
 #include <linux/socket.h>
+#include <linux/syscalls.h>
 #include <linux/filter.h>
 #include <linux/compat.h>
 #include <linux/netfilter_ipv4/ip_tables.h>
@@ -304,9 +305,6 @@ void scm_detach_fds_compat(struct msghdr
 	__scm_destroy(scm);
 }
 
-extern asmlinkage long sys_setsockopt(int fd, int level, int optname,
-				     char *optval, int optlen);
-
 /*
  * For now, we assume that the compatibility and native version
  * of struct ipt_entry are the same - sfr.  FIXME
@@ -471,9 +469,6 @@ asmlinkage long compat_sys_setsockopt(in
 	return sys_setsockopt(fd, level, optname, optval, optlen);
 }
 
-extern asmlinkage long sys_getsockopt(int fd, int level, int optname,
-				       void * optval, int *optlen);
-
 static int do_get_sock_timeout(int fd, int level, int optname, char *optval,
 		int *optlen)
 {
@@ -517,22 +512,6 @@ static unsigned char nas[18]={AL(0),AL(3
 				AL(6),AL(2),AL(5),AL(5),AL(3),AL(3)};
 #undef AL
 
-extern asmlinkage long sys_bind(int, struct sockaddr *, int);
-extern asmlinkage long sys_connect(int, struct sockaddr *, int);
-extern asmlinkage long sys_accept(int, struct sockaddr *, int *); 
-extern asmlinkage long sys_getsockname(int, struct sockaddr *, int *);
-extern asmlinkage long sys_getpeername(int, struct sockaddr *, int *);
-extern asmlinkage long sys_send(int, void *, size_t, unsigned);
-extern asmlinkage long sys_sendto(int, void *, size_t, unsigned,
-		struct sockaddr *, int);
-extern asmlinkage long sys_recv(int, void *, size_t, unsigned);
-extern asmlinkage long sys_recvfrom(int, void *, size_t, unsigned,
-		struct sockaddr *, int *);
-extern asmlinkage long sys_socket(int, int, int);
-extern asmlinkage long sys_socketpair(int, int, int, int [2]);
-extern asmlinkage long sys_shutdown(int, int);
-extern asmlinkage long sys_listen(int, int);
-
 asmlinkage long compat_sys_sendmsg(int fd, struct compat_msghdr *msg, unsigned flags)
 {
 	return sys_sendmsg(fd, (struct msghdr *)msg, flags | MSG_CMSG_COMPAT);
--- diff/net/core/Makefile	2003-09-17 12:28:12.000000000 +0100
+++ source/net/core/Makefile	2004-02-23 13:56:48.000000000 +0000
@@ -13,3 +13,4 @@ obj-$(CONFIG_NETFILTER) += netfilter.o
 obj-$(CONFIG_NET_DIVERT) += dv.o
 obj-$(CONFIG_NET_PKTGEN) += pktgen.o
 obj-$(CONFIG_NET_RADIO) += wireless.o
+obj-$(CONFIG_NETPOLL) += netpoll.o
--- diff/net/core/dev.c	2004-02-18 08:54:13.000000000 +0000
+++ source/net/core/dev.c	2004-02-23 13:56:48.000000000 +0000
@@ -105,6 +105,8 @@
 #include <linux/kmod.h>
 #include <linux/module.h>
 #include <linux/kallsyms.h>
+#include <linux/cpu.h>
+#include <linux/netpoll.h>
 #ifdef CONFIG_NET_RADIO
 #include <linux/wireless.h>		/* Note : will define WIRELESS_EXT */
 #include <net/iw_handler.h>
@@ -1547,7 +1549,6 @@ static void sample_queue(unsigned long d
 }
 #endif
 
-
 /**
  *	netif_rx	-	post buffer to the network code
  *	@skb: buffer to post
@@ -1572,6 +1573,13 @@ int netif_rx(struct sk_buff *skb)
 	struct softnet_data *queue;
 	unsigned long flags;
 
+#ifdef CONFIG_NETPOLL_RX
+	if (skb->dev->netpoll_rx && netpoll_rx(skb)) {
+		kfree_skb(skb);
+		return NET_RX_DROP;
+	}
+#endif
+
 	if (!skb->stamp.tv_sec)
 		do_gettimeofday(&skb->stamp);
 
@@ -1727,6 +1735,13 @@ int netif_receive_skb(struct sk_buff *sk
 	int ret = NET_RX_DROP;
 	unsigned short type = skb->protocol;
 
+#ifdef CONFIG_NETPOLL_RX
+	if (skb->dev->netpoll_rx && skb->dev->poll && netpoll_rx(skb)) {
+		kfree_skb(skb);
+		return NET_RX_DROP;
+	}
+#endif
+
 	if (!skb->stamp.tv_sec)
 		do_gettimeofday(&skb->stamp);
 
@@ -1742,6 +1757,7 @@ int netif_receive_skb(struct sk_buff *sk
 #endif
 
 	skb->h.raw = skb->nh.raw = skb->data;
+	skb->mac_len = skb->nh.raw - skb->mac.raw;
 
 	pt_prev = NULL;
 	rcu_read_lock();
@@ -1851,7 +1867,6 @@ static void net_rx_action(struct softirq
 	unsigned long start_time = jiffies;
 	int budget = netdev_max_backlog;
 
-	
 	preempt_disable();
 	local_irq_disable();
 
@@ -1878,6 +1893,10 @@ static void net_rx_action(struct softirq
 			dev_put(dev);
 			local_irq_disable();
 		}
+
+#ifdef CONFIG_KGDBOE
+		kgdb_process_breakpoint();
+#endif
 	}
 out:
 	local_irq_enable();
@@ -3150,6 +3169,52 @@ int unregister_netdevice(struct net_devi
 	return 0;
 }
 
+#ifdef CONFIG_HOTPLUG_CPU
+static int dev_cpu_callback(struct notifier_block *nfb,
+			    unsigned long action,
+			    void *ocpu)
+{
+	struct sk_buff **list_skb;
+	struct net_device **list_net;
+	struct sk_buff *skb;
+	unsigned int cpu, oldcpu = (unsigned long)ocpu;
+	struct softnet_data *sd, *oldsd;
+
+	if (action != CPU_DEAD)
+		return NOTIFY_OK;
+
+	local_irq_disable();
+	cpu = smp_processor_id();
+	sd = &per_cpu(softnet_data, cpu);
+	oldsd = &per_cpu(softnet_data, oldcpu);
+
+	/* Find end of our completion_queue. */
+	list_skb = &sd->completion_queue;
+	while (*list_skb)
+		list_skb = &(*list_skb)->next;
+	/* Append completion queue from offline CPU. */
+	*list_skb = oldsd->completion_queue;
+	oldsd->completion_queue = NULL;
+
+	/* Find end of our output_queue. */
+	list_net = &sd->output_queue;
+	while (*list_net)
+		list_net = &(*list_net)->next_sched;
+	/* Append output queue from offline CPU. */
+	*list_net = oldsd->output_queue;
+	oldsd->output_queue = NULL;
+
+	raise_softirq_irqoff(NET_TX_SOFTIRQ);
+	local_irq_enable();
+
+	/* Process offline CPU's input_pkt_queue */
+	while ((skb = __skb_dequeue(&oldsd->input_pkt_queue)))
+		netif_rx(skb);
+
+	return NOTIFY_OK;
+}
+#endif /* CONFIG_HOTPLUG_CPU */
+
 
 /*
  *	Initialize the DEV module. At boot time this walks the device list and
@@ -3216,10 +3281,7 @@ static int __init net_dev_init(void)
 
 	dst_init();
 	dev_mcast_init();
-
-#ifdef CONFIG_NET_SCHED
-	pktsched_init();
-#endif
+	hotcpu_notifier(dev_cpu_callback, 0);
 	rc = 0;
 out:
 	return rc;
--- diff/net/core/ethtool.c	2003-10-27 09:20:39.000000000 +0000
+++ source/net/core/ethtool.c	2004-02-23 13:56:48.000000000 +0000
@@ -374,7 +374,7 @@ static int ethtool_set_ringparam(struct 
 {
 	struct ethtool_ringparam ringparam;
 
-	if (!dev->ethtool_ops->get_ringparam)
+	if (!dev->ethtool_ops->set_ringparam)
 		return -EOPNOTSUPP;
 
 	if (copy_from_user(&ringparam, useraddr, sizeof(ringparam)))
--- diff/net/core/filter.c	2003-10-09 09:47:34.000000000 +0100
+++ source/net/core/filter.c	2004-02-23 13:56:48.000000000 +0000
@@ -332,7 +332,7 @@ int sk_chk_filter(struct sock_filter *fi
 	struct sock_filter *ftest;
 	int pc;
 
-	if ((unsigned int)flen >= (~0U / sizeof(struct sock_filter)))
+	if (((unsigned int)flen >= (~0U / sizeof(struct sock_filter))) || flen == 0)
 		return -EINVAL;
 
 	/* check the filter code now */
--- diff/net/core/flow.c	2004-02-18 08:54:13.000000000 +0000
+++ source/net/core/flow.c	2004-02-23 13:56:48.000000000 +0000
@@ -326,6 +326,17 @@ static void __devinit flow_cache_cpu_pre
 	tasklet_init(tasklet, flow_cache_flush_tasklet, 0);
 }
 
+#ifdef CONFIG_HOTPLUG_CPU
+static int flow_cache_cpu(struct notifier_block *nfb,
+			  unsigned long action,
+			  void *hcpu)
+{
+	if (action == CPU_DEAD)
+		__flow_cache_shrink((unsigned long)hcpu, 0);
+	return NOTIFY_OK;
+}
+#endif /* CONFIG_HOTPLUG_CPU */
+
 static int __init flow_cache_init(void)
 {
 	int i;
@@ -350,6 +361,7 @@ static int __init flow_cache_init(void)
 	for_each_cpu(i)
 		flow_cache_cpu_prepare(i);
 
+	hotcpu_notifier(flow_cache_cpu, 0);
 	return 0;
 }
 
--- diff/net/core/neighbour.c	2004-02-09 10:36:12.000000000 +0000
+++ source/net/core/neighbour.c	2004-02-23 13:56:48.000000000 +0000
@@ -1164,8 +1164,7 @@ void neigh_table_init(struct neigh_table
 
 	if (!tbl->kmem_cachep)
 		tbl->kmem_cachep = kmem_cache_create(tbl->id,
-						     (tbl->entry_size +
-						      15) & ~15,
+						     tbl->entry_size,
 						     0, SLAB_HWCACHE_ALIGN,
 						     NULL, NULL);
 	tbl->lock	       = RW_LOCK_UNLOCKED;
--- diff/net/core/pktgen.c	2004-02-09 10:36:12.000000000 +0000
+++ source/net/core/pktgen.c	2004-02-23 13:56:48.000000000 +0000
@@ -50,6 +50,8 @@
  * Fix refcount off by one if first packet fails, potential null deref, 
  * memleak 030710- KJP
  *
+ * Fixed unaligned access on IA-64 Grant Grundler <grundler@parisc-linux.org>
+ *
  * See Documentation/networking/pktgen.txt for how to use this.
  */
 
@@ -88,7 +90,7 @@
 #define cycles()	((u32)get_cycles())
 
 
-#define VERSION "pktgen version 1.31"
+#define VERSION "pktgen version 1.32"
 static char version[] __initdata = 
   "pktgen.c: v1.3: Packet Generator for packet performance testing.\n";
 
@@ -193,7 +195,8 @@ struct pktgen_info {
 struct pktgen_hdr {
 	__u32 pgh_magic;
 	__u32 seq_num;
-	struct timeval timestamp;
+	__u32 tv_sec;
+	__u32 tv_usec;
 };
 
 static int cpu_speed;
@@ -563,11 +566,14 @@ static struct sk_buff *fill_packet(struc
 
 	/* Stamp the time, and sequence number, convert them to network byte order */
 	if (pgh) {
+		struct timeval timestamp;
+
 		pgh->pgh_magic = htonl(PKTGEN_MAGIC);
-		do_gettimeofday(&(pgh->timestamp));
-		pgh->timestamp.tv_usec = htonl(pgh->timestamp.tv_usec);
-		pgh->timestamp.tv_sec = htonl(pgh->timestamp.tv_sec);
-		pgh->seq_num = htonl(info->seq_num);
+		pgh->seq_num   = htonl(info->seq_num);
+		
+		do_gettimeofday(&timestamp);
+		pgh->tv_sec    = htonl(timestamp.tv_sec);
+		pgh->tv_usec   = htonl(timestamp.tv_usec);
 	}
 	
 	return skb;
--- diff/net/decnet/dn_nsp_out.c	2003-06-30 10:07:24.000000000 +0100
+++ source/net/decnet/dn_nsp_out.c	2004-02-23 13:56:48.000000000 +0000
@@ -141,7 +141,7 @@ struct sk_buff *dn_alloc_skb(struct sock
  * whole size thats been asked for (plus 11 bytes of header). If this
  * fails, then we try for any size over 16 bytes for SOCK_STREAMS.
  */
-struct sk_buff *dn_alloc_send_skb(struct sock *sk, int *size, int noblock, int *err)
+struct sk_buff *dn_alloc_send_skb(struct sock *sk, size_t *size, int noblock, int *err)
 {
 	int space;
 	int len;
--- diff/net/decnet/dn_rules.c	2003-06-09 14:18:20.000000000 +0100
+++ source/net/decnet/dn_rules.c	2004-02-23 13:56:48.000000000 +0000
@@ -381,7 +381,7 @@ static int dn_fib_fill_rule(struct sk_bu
 
 nlmsg_failure:
 rtattr_failure:
-	skb_put(skb, b - skb->tail);
+	skb_trim(skb, b - skb->data);
 	return -1;
 }
 
--- diff/net/ipv4/arp.c	2004-02-18 08:54:13.000000000 +0000
+++ source/net/ipv4/arp.c	2004-02-23 13:56:48.000000000 +0000
@@ -325,15 +325,40 @@ static void arp_error_report(struct neig
 
 static void arp_solicit(struct neighbour *neigh, struct sk_buff *skb)
 {
-	u32 saddr;
+	u32 saddr = 0;
 	u8  *dst_ha = NULL;
 	struct net_device *dev = neigh->dev;
 	u32 target = *(u32*)neigh->primary_key;
 	int probes = atomic_read(&neigh->probes);
+	struct in_device *in_dev = in_dev_get(dev);
+
+	if (!in_dev)
+		return;
 
-	if (skb && inet_addr_type(skb->nh.iph->saddr) == RTN_LOCAL)
+	switch (IN_DEV_ARP_ANNOUNCE(in_dev)) {
+	default:
+	case 0:		/* By default announce any local IP */
+		if (skb && inet_addr_type(skb->nh.iph->saddr) == RTN_LOCAL)
+			saddr = skb->nh.iph->saddr;
+		break;
+	case 1:		/* Restrict announcements of saddr in same subnet */
+		if (!skb)
+			break;
 		saddr = skb->nh.iph->saddr;
-	else
+		if (inet_addr_type(saddr) == RTN_LOCAL) {
+			/* saddr should be known to target */
+			if (inet_addr_onlink(in_dev, target, saddr))
+				break;
+		}
+		saddr = 0;
+		break;
+	case 2:		/* Avoid secondary IPs, get a primary/preferred one */
+		break;
+	}
+
+	if (in_dev)
+		in_dev_put(in_dev);
+	if (!saddr)
 		saddr = inet_select_addr(dev, target, RT_SCOPE_LINK);
 
 	if ((probes -= neigh->parms->ucast_probes) < 0) {
@@ -354,6 +379,42 @@ static void arp_solicit(struct neighbour
 		read_unlock_bh(&neigh->lock);
 }
 
+static int arp_ignore(struct in_device *in_dev, struct net_device *dev,
+		      u32 sip, u32 tip)
+{
+	int scope;
+
+	switch (IN_DEV_ARP_IGNORE(in_dev)) {
+	case 0:	/* Reply, the tip is already validated */
+		return 0;
+	case 1:	/* Reply only if tip is configured on the incoming interface */
+		sip = 0;
+		scope = RT_SCOPE_HOST;
+		break;
+	case 2:	/*
+		 * Reply only if tip is configured on the incoming interface
+		 * and is in same subnet as sip
+		 */
+		scope = RT_SCOPE_HOST;
+		break;
+	case 3:	/* Do not reply for scope host addresses */
+		sip = 0;
+		scope = RT_SCOPE_LINK;
+		dev = NULL;
+		break;
+	case 4:	/* Reserved */
+	case 5:
+	case 6:
+	case 7:
+		return 0;
+	case 8:	/* Do not reply */
+		return 1;
+	default:
+		return 0;
+	}
+	return !inet_confirm_addr(dev, sip, tip, scope);
+}
+
 static int arp_filter(__u32 sip, __u32 tip, struct net_device *dev)
 {
 	struct flowi fl = { .nl_u = { .ip4_u = { .daddr = sip,
@@ -764,7 +825,8 @@ int arp_process(struct sk_buff *skb)
 	/* Special case: IPv4 duplicate address detection packet (RFC2131) */
 	if (sip == 0) {
 		if (arp->ar_op == htons(ARPOP_REQUEST) &&
-		    inet_addr_type(tip) == RTN_LOCAL)
+		    inet_addr_type(tip) == RTN_LOCAL &&
+		    !arp_ignore(in_dev,dev,sip,tip))
 			arp_send(ARPOP_REPLY,ETH_P_ARP,tip,dev,tip,sha,dev->dev_addr,dev->dev_addr);
 		goto out;
 	}
@@ -779,7 +841,10 @@ int arp_process(struct sk_buff *skb)
 			n = neigh_event_ns(&arp_tbl, sha, &sip, dev);
 			if (n) {
 				int dont_send = 0;
-				if (IN_DEV_ARPFILTER(in_dev))
+
+				if (!dont_send)
+					dont_send |= arp_ignore(in_dev,dev,sip,tip);
+				if (!dont_send && IN_DEV_ARPFILTER(in_dev))
 					dont_send |= arp_filter(sip,tip,dev); 
 				if (!dont_send)
 					arp_send(ARPOP_REPLY,ETH_P_ARP,sip,dev,tip,sha,dev->dev_addr,sha);
--- diff/net/ipv4/devinet.c	2004-02-18 08:54:13.000000000 +0000
+++ source/net/ipv4/devinet.c	2004-02-23 13:56:48.000000000 +0000
@@ -809,6 +809,84 @@ out_unlock_inetdev:
 	goto out;
 }
 
+static u32 confirm_addr_indev(struct in_device *in_dev, u32 dst,
+			      u32 local, int scope)
+{
+	int same = 0;
+	u32 addr = 0;
+
+	for_ifa(in_dev) {
+		if (!addr &&
+		    (local == ifa->ifa_local || !local) &&
+		    ifa->ifa_scope <= scope) {
+			addr = ifa->ifa_local;
+			if (same)
+				break;
+		}
+		if (!same) {
+			same = (!local || inet_ifa_match(local, ifa)) &&
+				(!dst || inet_ifa_match(dst, ifa));
+			if (same && addr) {
+				if (local || !dst)
+					break;
+				/* Is the selected addr into dst subnet? */
+				if (inet_ifa_match(addr, ifa))
+					break;
+				/* No, then can we use new local src? */
+				if (ifa->ifa_scope <= scope) {
+					addr = ifa->ifa_local;
+					break;
+				}
+				/* search for large dst subnet for addr */
+				same = 0;
+			}
+		}
+	} endfor_ifa(in_dev);
+
+	return same? addr : 0;
+}
+
+/*
+ * Confirm that local IP address exists using wildcards:
+ * - dev: only on this interface, 0=any interface
+ * - dst: only in the same subnet as dst, 0=any dst
+ * - local: address, 0=autoselect the local address
+ * - scope: maximum allowed scope value for the local address
+ */
+u32 inet_confirm_addr(const struct net_device *dev, u32 dst, u32 local, int scope)
+{
+	u32 addr = 0;
+	struct in_device *in_dev;
+
+	if (dev) {
+		read_lock(&inetdev_lock);
+		if ((in_dev = __in_dev_get(dev))) {
+			read_lock(&in_dev->lock);
+			addr = confirm_addr_indev(in_dev, dst, local, scope);
+			read_unlock(&in_dev->lock);
+		}
+		read_unlock(&inetdev_lock);
+
+		return addr;
+	}
+
+	read_lock(&dev_base_lock);
+	read_lock(&inetdev_lock);
+	for (dev = dev_base; dev; dev = dev->next) {
+		if ((in_dev = __in_dev_get(dev))) {
+			read_lock(&in_dev->lock);
+			addr = confirm_addr_indev(in_dev, dst, local, scope);
+			read_unlock(&in_dev->lock);
+			if (addr)
+				break;
+		}
+	}
+	read_unlock(&inetdev_lock);
+	read_unlock(&dev_base_lock);
+
+	return addr;
+}
+
 /*
  *	Device notifier
  */
@@ -1132,7 +1210,7 @@ int ipv4_doint_and_flush_strategy(ctl_ta
 
 static struct devinet_sysctl_table {
 	struct ctl_table_header *sysctl_header;
-	ctl_table		devinet_vars[18];
+	ctl_table		devinet_vars[20];
 	ctl_table		devinet_dev[2];
 	ctl_table		devinet_conf_dir[2];
 	ctl_table		devinet_proto_dir[2];
@@ -1252,6 +1330,22 @@ static struct devinet_sysctl_table {
 			.proc_handler	= &proc_dointvec,
 		},
 		{
+			.ctl_name	= NET_IPV4_CONF_ARP_ANNOUNCE,
+			.procname	= "arp_announce",
+			.data		= &ipv4_devconf.arp_announce,
+			.maxlen		= sizeof(int),
+			.mode		= 0644,
+			.proc_handler	= &proc_dointvec,
+		},
+		{
+			.ctl_name	= NET_IPV4_CONF_ARP_IGNORE,
+			.procname	= "arp_ignore",
+			.data		= &ipv4_devconf.arp_ignore,
+			.maxlen		= sizeof(int),
+			.mode		= 0644,
+			.proc_handler	= &proc_dointvec,
+		},
+		{
 			.ctl_name	= NET_IPV4_CONF_NOXFRM,
 			.procname	= "disable_xfrm",
 			.data		= &ipv4_devconf.no_xfrm,
--- diff/net/ipv4/fib_rules.c	2002-10-16 04:28:24.000000000 +0100
+++ source/net/ipv4/fib_rules.c	2004-02-23 13:56:48.000000000 +0000
@@ -438,7 +438,7 @@ static __inline__ int inet_fill_rule(str
 
 nlmsg_failure:
 rtattr_failure:
-	skb_put(skb, b - skb->tail);
+	skb_trim(skb, b - skb->data);
 	return -1;
 }
 
--- diff/net/ipv4/ip_gre.c	2003-11-25 15:24:59.000000000 +0000
+++ source/net/ipv4/ip_gre.c	2004-02-23 13:56:48.000000000 +0000
@@ -280,7 +280,7 @@ static struct ip_tunnel * ipgre_tunnel_l
 	nt->parms = *parms;
 
 	if (register_netdevice(dev) < 0) {
-		kfree(dev);
+		free_netdev(dev);
 		goto failed;
 	}
 
@@ -1276,7 +1276,7 @@ out:
 	return err;
 fail:
 	inet_del_protocol(&ipgre_protocol, IPPROTO_GRE);
-	kfree(ipgre_fb_tunnel_dev);
+	free_netdev(ipgre_fb_tunnel_dev);
 	goto out;
 }
 
--- diff/net/ipv4/ip_sockglue.c	2003-10-09 09:47:34.000000000 +0100
+++ source/net/ipv4/ip_sockglue.c	2004-02-23 13:56:48.000000000 +0000
@@ -631,6 +631,11 @@ int ip_setsockopt(struct sock *sk, int l
 				kfree(msf);
 				break;
 			}
+			if (IP_MSFILTER_SIZE(msf->imsf_numsrc) > optlen) {
+				kfree(msf);
+				err = -EINVAL;
+				break;
+			}
 			err = ip_mc_msfilter(sk, msf, 0);
 			kfree(msf);
 			break;
--- diff/net/ipv4/ipconfig.c	2003-10-09 09:47:34.000000000 +0100
+++ source/net/ipv4/ipconfig.c	2004-02-23 13:56:48.000000000 +0000
@@ -1189,12 +1189,47 @@ static struct file_operations pnp_seq_fo
 #endif /* CONFIG_PROC_FS */
 
 /*
+ *  Extract IP address from the parameter string if needed. Note that we
+ *  need to have root_server_addr set _before_ IPConfig gets called as it
+ *  can override it.
+ */
+u32 __init root_nfs_parse_addr(char *name)
+{
+	u32 addr;
+	int octets = 0;
+	char *cp, *cq;
+
+	cp = cq = name;
+	while (octets < 4) {
+		while (*cp >= '0' && *cp <= '9')
+			cp++;
+		if (cp == cq || cp - cq > 3)
+			break;
+		if (*cp == '.' || octets == 3)
+			octets++;
+		if (octets < 4)
+			cp++;
+		cq = cp;
+	}
+	if (octets == 4 && (*cp == ':' || *cp == '\0')) {
+		if (*cp == ':')
+			*cp++ = '\0';
+		addr = in_aton(name);
+		strcpy(name, cp);
+	} else
+		addr = INADDR_NONE;
+
+	return addr;
+}
+
+/*
  *	IP Autoconfig dispatcher.
  */
 
 static int __init ip_auto_config(void)
 {
 	unsigned long jiff;
+	u32 addr;
 
 #ifdef CONFIG_PROC_FS
 	proc_net_fops_create("pnp", S_IRUGO, &pnp_seq_fops);
@@ -1283,6 +1318,10 @@ static int __init ip_auto_config(void)
 		ic_dev = ic_first_dev->dev;
 	}
 
+	addr = root_nfs_parse_addr(root_server_path);
+	if (root_server_addr == INADDR_NONE)
+		root_server_addr = addr;
+
 	/*
 	 * Use defaults whereever applicable.
 	 */
@@ -1324,7 +1363,7 @@ static int __init ip_auto_config(void)
 	return 0;
 }
 
-module_init(ip_auto_config);
+late_initcall(ip_auto_config);
 
 
 /*
--- diff/net/ipv4/ipip.c	2003-10-27 09:20:44.000000000 +0000
+++ source/net/ipv4/ipip.c	2004-02-23 13:56:48.000000000 +0000
@@ -250,7 +250,7 @@ static struct ip_tunnel * ipip_tunnel_lo
 	nt->parms = *parms;
 
 	if (register_netdevice(dev) < 0) {
-		kfree(dev);
+		free_netdev(dev);
 		goto failed;
 	}
 
@@ -899,7 +899,7 @@ int __init ipip_init(void)
 	return err;
  fail:
 	xfrm4_tunnel_deregister(&ipip_handler);
-	kfree(ipip_fb_tunnel_dev);
+	free_netdev(ipip_fb_tunnel_dev);
 	goto out;
 }
 
--- diff/net/ipv4/ipmr.c	2004-02-09 10:36:12.000000000 +0000
+++ source/net/ipv4/ipmr.c	2004-02-23 13:56:48.000000000 +0000
@@ -209,7 +209,7 @@ static struct net_device *ipmr_reg_vif(v
 		return NULL;
 
 	if (register_netdevice(dev)) {
-		kfree(dev);
+		free_netdev(dev);
 		return NULL;
 	}
 	dev->iflink = 0;
--- diff/net/ipv4/ipvs/ip_vs_app.c	2003-10-09 09:47:34.000000000 +0100
+++ source/net/ipv4/ipvs/ip_vs_app.c	2004-02-23 13:56:48.000000000 +0000
@@ -20,18 +20,12 @@
  *
  */
 
-#include <linux/config.h>
 #include <linux/module.h>
-#include <linux/types.h>
 #include <linux/kernel.h>
-#include <linux/errno.h>
 #include <linux/skbuff.h>
 #include <linux/in.h>
 #include <linux/ip.h>
-#include <linux/init.h>
 #include <net/protocol.h>
-#include <net/tcp.h>
-#include <net/udp.h>
 #include <asm/system.h>
 #include <linux/stat.h>
 #include <linux/proc_fs.h>
--- diff/net/ipv4/ipvs/ip_vs_conn.c	2003-11-25 15:24:59.000000000 +0000
+++ source/net/ipv4/ipvs/ip_vs_conn.c	2004-02-23 13:56:48.000000000 +0000
@@ -24,10 +24,7 @@
  *
  */
 
-#include <linux/config.h>
-#include <linux/types.h>
 #include <linux/kernel.h>
-#include <linux/compiler.h>
 #include <linux/vmalloc.h>
 #include <linux/proc_fs.h>		/* for proc_net_* */
 #include <linux/seq_file.h>
--- diff/net/ipv4/ipvs/ip_vs_core.c	2003-10-27 09:20:39.000000000 +0000
+++ source/net/ipv4/ipvs/ip_vs_core.c	2004-02-23 13:56:48.000000000 +0000
@@ -25,12 +25,8 @@
  *
  */
 
-#include <linux/config.h>
 #include <linux/module.h>
-#include <linux/types.h>
 #include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/compiler.h>
 #include <linux/ip.h>
 #include <linux/tcp.h>
 #include <linux/icmp.h>
--- diff/net/ipv4/ipvs/ip_vs_ctl.c	2003-10-27 09:20:39.000000000 +0000
+++ source/net/ipv4/ipvs/ip_vs_ctl.c	2004-02-23 13:56:48.000000000 +0000
@@ -20,12 +20,9 @@
  *
  */
 
-#include <linux/config.h>
-#include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/types.h>
-#include <linux/errno.h>
 #include <linux/fs.h>
 #include <linux/sysctl.h>
 #include <linux/proc_fs.h>
--- diff/net/ipv4/ipvs/ip_vs_dh.c	2003-10-09 09:47:34.000000000 +0100
+++ source/net/ipv4/ipvs/ip_vs_dh.c	2004-02-23 13:56:48.000000000 +0000
@@ -37,12 +37,8 @@
  *
  */
 
-#include <linux/config.h>
 #include <linux/module.h>
-#include <linux/init.h>
-#include <linux/types.h>
 #include <linux/kernel.h>
-#include <linux/errno.h>
 
 #include <net/ip_vs.h>
 
--- diff/net/ipv4/ipvs/ip_vs_ftp.c	2003-10-09 09:47:34.000000000 +0100
+++ source/net/ipv4/ipvs/ip_vs_ftp.c	2004-02-23 13:56:48.000000000 +0000
@@ -24,15 +24,11 @@
  *
  */
 
-#include <linux/config.h>
 #include <linux/module.h>
-#include <asm/system.h>
-#include <linux/types.h>
 #include <linux/kernel.h>
 #include <linux/skbuff.h>
 #include <linux/in.h>
 #include <linux/ip.h>
-#include <linux/init.h>
 #include <net/protocol.h>
 #include <net/tcp.h>
 
--- diff/net/ipv4/ipvs/ip_vs_lblc.c	2003-10-09 09:47:34.000000000 +0100
+++ source/net/ipv4/ipvs/ip_vs_lblc.c	2004-02-23 13:56:48.000000000 +0000
@@ -41,14 +41,10 @@
  * me to write this module.
  */
 
-#include <linux/config.h>
 #include <linux/module.h>
-#include <linux/init.h>
-#include <linux/types.h>
 #include <linux/kernel.h>
-#include <linux/errno.h>
 
-/* for systcl */
+/* for sysctl */
 #include <linux/fs.h>
 #include <linux/sysctl.h>
 
@@ -69,7 +65,7 @@
  *    entries that haven't been touched for a day.
  */
 #define COUNT_FOR_FULL_EXPIRATION   30
-int sysctl_ip_vs_lblc_expiration = 24*60*60*HZ;
+static int sysctl_ip_vs_lblc_expiration = 24*60*60*HZ;
 
 
 /*
--- diff/net/ipv4/ipvs/ip_vs_lblcr.c	2003-10-09 09:47:34.000000000 +0100
+++ source/net/ipv4/ipvs/ip_vs_lblcr.c	2004-02-23 13:56:48.000000000 +0000
@@ -39,14 +39,10 @@
  *
  */
 
-#include <linux/config.h>
 #include <linux/module.h>
-#include <linux/init.h>
-#include <linux/types.h>
 #include <linux/kernel.h>
-#include <linux/errno.h>
 
-/* for systcl */
+/* for sysctl */
 #include <linux/fs.h>
 #include <linux/sysctl.h>
 /* for proc_net_create/proc_net_remove */
@@ -69,7 +65,7 @@
  *    entries that haven't been touched for a day.
  */
 #define COUNT_FOR_FULL_EXPIRATION   30
-int sysctl_ip_vs_lblcr_expiration = 24*60*60*HZ;
+static int sysctl_ip_vs_lblcr_expiration = 24*60*60*HZ;
 
 
 /*
--- diff/net/ipv4/ipvs/ip_vs_lc.c	2003-10-09 09:47:34.000000000 +0100
+++ source/net/ipv4/ipvs/ip_vs_lc.c	2004-02-23 13:56:48.000000000 +0000
@@ -16,12 +16,8 @@
  *
  */
 
-#include <linux/config.h>
 #include <linux/module.h>
-#include <linux/init.h>
-#include <linux/types.h>
 #include <linux/kernel.h>
-#include <linux/errno.h>
 
 #include <net/ip_vs.h>
 
--- diff/net/ipv4/ipvs/ip_vs_nq.c	2003-10-09 09:47:34.000000000 +0100
+++ source/net/ipv4/ipvs/ip_vs_nq.c	2004-02-23 13:56:48.000000000 +0000
@@ -33,12 +33,8 @@
  *
  */
 
-#include <linux/config.h>
 #include <linux/module.h>
-#include <linux/init.h>
-#include <linux/types.h>
 #include <linux/kernel.h>
-#include <linux/errno.h>
 
 #include <net/ip_vs.h>
 
--- diff/net/ipv4/ipvs/ip_vs_proto.c	2003-10-09 09:47:34.000000000 +0100
+++ source/net/ipv4/ipvs/ip_vs_proto.c	2004-02-23 13:56:48.000000000 +0000
@@ -15,15 +15,11 @@
  *
  */
 
-#include <linux/config.h>
 #include <linux/module.h>
-#include <linux/types.h>
 #include <linux/kernel.h>
-#include <linux/errno.h>
 #include <linux/skbuff.h>
 #include <linux/in.h>
 #include <linux/ip.h>
-#include <linux/init.h>
 #include <net/protocol.h>
 #include <net/tcp.h>
 #include <net/udp.h>
--- diff/net/ipv4/ipvs/ip_vs_proto_ah.c	2003-10-09 09:47:34.000000000 +0100
+++ source/net/ipv4/ipvs/ip_vs_proto_ah.c	2004-02-23 13:56:48.000000000 +0000
@@ -12,13 +12,8 @@
  *
  */
 
-#include <linux/config.h>
 #include <linux/module.h>
-#include <linux/types.h>
 #include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/compiler.h>
-#include <linux/vmalloc.h>
 #include <linux/netfilter.h>
 #include <linux/netfilter_ipv4.h>
 
--- diff/net/ipv4/ipvs/ip_vs_proto_esp.c	2003-10-09 09:47:34.000000000 +0100
+++ source/net/ipv4/ipvs/ip_vs_proto_esp.c	2004-02-23 13:56:48.000000000 +0000
@@ -12,13 +12,8 @@
  *
  */
 
-#include <linux/config.h>
 #include <linux/module.h>
-#include <linux/types.h>
 #include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/compiler.h>
-#include <linux/vmalloc.h>
 #include <linux/netfilter.h>
 #include <linux/netfilter_ipv4.h>
 
--- diff/net/ipv4/ipvs/ip_vs_proto_icmp.c	2003-10-09 09:47:34.000000000 +0100
+++ source/net/ipv4/ipvs/ip_vs_proto_icmp.c	2004-02-23 13:56:48.000000000 +0000
@@ -9,13 +9,8 @@
  *
  */
 
-#include <linux/config.h>
 #include <linux/module.h>
-#include <linux/types.h>
 #include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/compiler.h>
-#include <linux/vmalloc.h>
 #include <linux/icmp.h>
 #include <linux/netfilter.h>
 #include <linux/netfilter_ipv4.h>
--- diff/net/ipv4/ipvs/ip_vs_proto_tcp.c	2003-10-09 09:47:34.000000000 +0100
+++ source/net/ipv4/ipvs/ip_vs_proto_tcp.c	2004-02-23 13:56:48.000000000 +0000
@@ -15,8 +15,7 @@
  *
  */
 
-#include <linux/config.h>
-#include <linux/compiler.h>
+#include <linux/kernel.h>
 #include <linux/ip.h>
 #include <linux/tcp.h>                  /* for tcphdr */
 #include <net/ip.h>
--- diff/net/ipv4/ipvs/ip_vs_rr.c	2003-10-09 09:47:34.000000000 +0100
+++ source/net/ipv4/ipvs/ip_vs_rr.c	2004-02-23 13:56:48.000000000 +0000
@@ -21,12 +21,8 @@
  *
  */
 
-#include <linux/config.h>
 #include <linux/module.h>
-#include <linux/init.h>
-#include <linux/types.h>
 #include <linux/kernel.h>
-#include <linux/errno.h>
 
 #include <net/ip_vs.h>
 
--- diff/net/ipv4/ipvs/ip_vs_sched.c	2003-09-30 15:46:21.000000000 +0100
+++ source/net/ipv4/ipvs/ip_vs_sched.c	2004-02-23 13:56:48.000000000 +0000
@@ -19,10 +19,7 @@
  *
  */
 
-#include <linux/config.h>
 #include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
 #include <linux/sched.h>
 #include <linux/spinlock.h>
 #include <asm/string.h>
--- diff/net/ipv4/ipvs/ip_vs_sed.c	2003-10-09 09:47:34.000000000 +0100
+++ source/net/ipv4/ipvs/ip_vs_sed.c	2004-02-23 13:56:48.000000000 +0000
@@ -37,12 +37,8 @@
  *
  */
 
-#include <linux/config.h>
 #include <linux/module.h>
-#include <linux/init.h>
-#include <linux/types.h>
 #include <linux/kernel.h>
-#include <linux/errno.h>
 
 #include <net/ip_vs.h>
 
--- diff/net/ipv4/ipvs/ip_vs_sh.c	2003-10-09 09:47:34.000000000 +0100
+++ source/net/ipv4/ipvs/ip_vs_sh.c	2004-02-23 13:56:48.000000000 +0000
@@ -34,12 +34,8 @@
  *
  */
 
-#include <linux/config.h>
 #include <linux/module.h>
-#include <linux/init.h>
-#include <linux/types.h>
 #include <linux/kernel.h>
-#include <linux/errno.h>
 
 #include <net/ip_vs.h>
 
--- diff/net/ipv4/ipvs/ip_vs_sync.c	2003-10-09 09:47:34.000000000 +0100
+++ source/net/ipv4/ipvs/ip_vs_sync.c	2004-02-23 13:56:48.000000000 +0000
@@ -18,17 +18,9 @@
  *					messages filtering.
  */
 
-#define __KERNEL_SYSCALLS__             /*  for waitpid */
-
-#include <linux/config.h>
 #include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
 #include <linux/slab.h>
 #include <linux/net.h>
-#include <linux/sched.h>
-#include <linux/wait.h>
-#include <linux/unistd.h>
 #include <linux/completion.h>
 
 #include <linux/skbuff.h>
@@ -621,8 +613,6 @@ ip_vs_receive(struct socket *sock, char 
 }
 
 
-static int errno;
-
 static DECLARE_WAIT_QUEUE_HEAD(sync_wait);
 static pid_t sync_master_pid = 0;
 static pid_t sync_backup_pid = 0;
@@ -769,10 +759,10 @@ static int sync_thread(void *startup)
 
 	if (ip_vs_sync_state & IP_VS_STATE_MASTER && !sync_master_pid) {
 		state = IP_VS_STATE_MASTER;
-		name = "ipvs syncmaster";
+		name = "ipvs_syncmaster";
 	} else if (ip_vs_sync_state & IP_VS_STATE_BACKUP && !sync_backup_pid) {
 		state = IP_VS_STATE_BACKUP;
-		name = "ipvs syncbackup";
+		name = "ipvs_syncbackup";
 	} else {
 		IP_VS_BUG();
 		ip_vs_use_count_dec();
@@ -830,10 +820,19 @@ static int sync_thread(void *startup)
 
 static int fork_sync_thread(void *startup)
 {
+	pid_t pid;
+
 	/* fork the sync thread here, then the parent process of the
 	   sync thread is the init process after this thread exits. */
-	if (kernel_thread(sync_thread, startup, 0) < 0)
-		IP_VS_BUG();
+  repeat:
+	if ((pid = kernel_thread(sync_thread, startup, 0)) < 0) {
+		IP_VS_ERR("could not create sync_thread due to %d... "
+			  "retrying.\n", pid);
+		current->state = TASK_UNINTERRUPTIBLE;
+		schedule_timeout(HZ);
+		goto repeat;
+	}
+
 	return 0;
 }
 
@@ -842,7 +841,6 @@ int start_sync_thread(int state, char *m
 {
 	DECLARE_COMPLETION(startup);
 	pid_t pid;
-	int waitpid_result;
 
 	if ((state == IP_VS_STATE_MASTER && sync_master_pid) ||
 	    (state == IP_VS_STATE_BACKUP && sync_backup_pid))
@@ -861,12 +859,13 @@ int start_sync_thread(int state, char *m
 		ip_vs_backup_syncid = syncid;
 	}
 
-	if ((pid = kernel_thread(fork_sync_thread, &startup, 0)) < 0)
-		IP_VS_BUG();
-
-	if ((waitpid_result = waitpid(pid, NULL, __WCLONE)) != pid) {
-		IP_VS_ERR("%s: waitpid(%d,...) failed, errno %d\n",
-			  __FUNCTION__, pid, -waitpid_result);
+  repeat:
+	if ((pid = kernel_thread(fork_sync_thread, &startup, 0)) < 0) {
+		IP_VS_ERR("could not create fork_sync_thread due to %d... "
+			  "retrying.\n", pid);
+		current->state = TASK_UNINTERRUPTIBLE;
+		schedule_timeout(HZ);
+		goto repeat;
 	}
 
 	wait_for_completion(&startup);
--- diff/net/ipv4/ipvs/ip_vs_wlc.c	2003-10-09 09:47:34.000000000 +0100
+++ source/net/ipv4/ipvs/ip_vs_wlc.c	2004-02-23 13:56:48.000000000 +0000
@@ -21,12 +21,8 @@
  *
  */
 
-#include <linux/config.h>
 #include <linux/module.h>
-#include <linux/init.h>
-#include <linux/types.h>
 #include <linux/kernel.h>
-#include <linux/errno.h>
 
 #include <net/ip_vs.h>
 
--- diff/net/ipv4/ipvs/ip_vs_wrr.c	2003-10-09 09:47:34.000000000 +0100
+++ source/net/ipv4/ipvs/ip_vs_wrr.c	2004-02-23 13:56:48.000000000 +0000
@@ -20,12 +20,8 @@
  *
  */
 
-#include <linux/config.h>
 #include <linux/module.h>
-#include <linux/init.h>
-#include <linux/types.h>
 #include <linux/kernel.h>
-#include <linux/errno.h>
 
 #include <net/ip_vs.h>
 
--- diff/net/ipv4/ipvs/ip_vs_xmit.c	2004-02-18 08:54:13.000000000 +0000
+++ source/net/ipv4/ipvs/ip_vs_xmit.c	2004-02-23 13:56:48.000000000 +0000
@@ -15,10 +15,7 @@
  *
  */
 
-#include <linux/config.h>
-#include <linux/types.h>
 #include <linux/kernel.h>
-#include <linux/compiler.h>
 #include <linux/ip.h>
 #include <linux/tcp.h>                  /* for tcphdr */
 #include <net/tcp.h>                    /* for csum_tcpudp_magic */
--- diff/net/ipv4/netfilter/ip_conntrack_core.c	2004-02-18 08:54:13.000000000 +0000
+++ source/net/ipv4/netfilter/ip_conntrack_core.c	2004-02-23 13:56:48.000000000 +0000
@@ -1240,14 +1240,13 @@ do_kill(const struct ip_conntrack_tuple_
 /* Bring out ya dead! */
 static struct ip_conntrack_tuple_hash *
 get_next_corpse(int (*kill)(const struct ip_conntrack *i, void *data),
-		void *data)
+		void *data, unsigned int *bucket)
 {
 	struct ip_conntrack_tuple_hash *h = NULL;
-	unsigned int i;
 
 	READ_LOCK(&ip_conntrack_lock);
-	for (i = 0; !h && i < ip_conntrack_htable_size; i++) {
-		h = LIST_FIND(&ip_conntrack_hash[i], do_kill,
+	for (; !h && *bucket < ip_conntrack_htable_size; (*bucket)++) {
+		h = LIST_FIND(&ip_conntrack_hash[*bucket], do_kill,
 			      struct ip_conntrack_tuple_hash *, kill, data);
 	}
 	if (h)
@@ -1262,9 +1261,9 @@ ip_ct_selective_cleanup(int (*kill)(cons
 			void *data)
 {
 	struct ip_conntrack_tuple_hash *h;
+	unsigned int bucket = 0;
 
-	/* This is order n^2, by the way. */
-	while ((h = get_next_corpse(kill, data)) != NULL) {
+	while ((h = get_next_corpse(kill, data, &bucket)) != NULL) {
 		/* Time to push up daises... */
 		if (del_timer(&h->ctrack->timeout))
 			death_by_timeout((unsigned long)h->ctrack);
--- diff/net/ipv4/netfilter/ip_conntrack_standalone.c	2004-02-18 08:54:13.000000000 +0000
+++ source/net/ipv4/netfilter/ip_conntrack_standalone.c	2004-02-23 13:56:48.000000000 +0000
@@ -275,6 +275,7 @@ static struct nf_hook_ops ip_conntrack_l
 
 /* From ip_conntrack_core.c */
 extern int ip_conntrack_max;
+extern unsigned int ip_conntrack_htable_size;
 
 /* From ip_conntrack_proto_tcp.c */
 extern unsigned long ip_ct_tcp_timeout_syn_sent;
@@ -299,66 +300,159 @@ extern unsigned long ip_ct_generic_timeo
 static struct ctl_table_header *ip_ct_sysctl_header;
 
 static ctl_table ip_ct_sysctl_table[] = {
-	{NET_IPV4_NF_CONNTRACK_MAX, "ip_conntrack_max",
-	 &ip_conntrack_max, sizeof(int), 0644, NULL,
-	 &proc_dointvec},
-	{NET_IPV4_NF_CONNTRACK_TCP_TIMEOUT_SYN_SENT, "ip_conntrack_tcp_timeout_syn_sent",
-	 &ip_ct_tcp_timeout_syn_sent, sizeof(unsigned int), 0644, NULL,
-	 &proc_dointvec_jiffies},
-	{NET_IPV4_NF_CONNTRACK_TCP_TIMEOUT_SYN_RECV, "ip_conntrack_tcp_timeout_syn_recv",
-	 &ip_ct_tcp_timeout_syn_recv, sizeof(unsigned int), 0644, NULL,
-	 &proc_dointvec_jiffies},
-	{NET_IPV4_NF_CONNTRACK_TCP_TIMEOUT_ESTABLISHED, "ip_conntrack_tcp_timeout_established",
-	 &ip_ct_tcp_timeout_established, sizeof(unsigned int), 0644, NULL,
-	 &proc_dointvec_jiffies},
-	{NET_IPV4_NF_CONNTRACK_TCP_TIMEOUT_FIN_WAIT, "ip_conntrack_tcp_timeout_fin_wait",
-	 &ip_ct_tcp_timeout_fin_wait, sizeof(unsigned int), 0644, NULL,
-	 &proc_dointvec_jiffies},
-	{NET_IPV4_NF_CONNTRACK_TCP_TIMEOUT_CLOSE_WAIT, "ip_conntrack_tcp_timeout_close_wait",
-	 &ip_ct_tcp_timeout_close_wait, sizeof(unsigned int), 0644, NULL,
-	 &proc_dointvec_jiffies},
-	{NET_IPV4_NF_CONNTRACK_TCP_TIMEOUT_LAST_ACK, "ip_conntrack_tcp_timeout_last_ack",
-	 &ip_ct_tcp_timeout_last_ack, sizeof(unsigned int), 0644, NULL,
-	 &proc_dointvec_jiffies},
-	{NET_IPV4_NF_CONNTRACK_TCP_TIMEOUT_TIME_WAIT, "ip_conntrack_tcp_timeout_time_wait",
-	 &ip_ct_tcp_timeout_time_wait, sizeof(unsigned int), 0644, NULL,
-	 &proc_dointvec_jiffies},
-	{NET_IPV4_NF_CONNTRACK_TCP_TIMEOUT_CLOSE, "ip_conntrack_tcp_timeout_close",
-	 &ip_ct_tcp_timeout_close, sizeof(unsigned int), 0644, NULL,
-	 &proc_dointvec_jiffies},
-	{NET_IPV4_NF_CONNTRACK_UDP_TIMEOUT, "ip_conntrack_udp_timeout",
-	 &ip_ct_udp_timeout, sizeof(unsigned int), 0644, NULL,
-	 &proc_dointvec_jiffies},
-	{NET_IPV4_NF_CONNTRACK_UDP_TIMEOUT_STREAM, "ip_conntrack_udp_timeout_stream",
-	 &ip_ct_udp_timeout_stream, sizeof(unsigned int), 0644, NULL,
-	 &proc_dointvec_jiffies},
-	{NET_IPV4_NF_CONNTRACK_ICMP_TIMEOUT, "ip_conntrack_icmp_timeout",
-	 &ip_ct_icmp_timeout, sizeof(unsigned int), 0644, NULL,
-	 &proc_dointvec_jiffies},
-	{NET_IPV4_NF_CONNTRACK_GENERIC_TIMEOUT, "ip_conntrack_generic_timeout",
-	 &ip_ct_generic_timeout, sizeof(unsigned int), 0644, NULL,
-	 &proc_dointvec_jiffies},
-	{0}
+	{
+		.ctl_name	= NET_IPV4_NF_CONNTRACK_MAX,
+		.procname	= "ip_conntrack_max",
+		.data		= &ip_conntrack_max,
+		.maxlen		= sizeof(int),
+		.mode		= 0644,
+		.proc_handler	= &proc_dointvec,
+	},
+	{
+		.ctl_name	= NET_IPV4_NF_CONNTRACK_BUCKETS,
+		.procname	= "ip_conntrack_buckets",
+		.data		= &ip_conntrack_htable_size,
+		.maxlen		= sizeof(unsigned int),
+		.mode		= 0444,
+		.proc_handler	= &proc_dointvec,
+	},
+	{
+		.ctl_name	= NET_IPV4_NF_CONNTRACK_TCP_TIMEOUT_SYN_SENT,
+		.procname	= "ip_conntrack_tcp_timeout_syn_sent",
+		.data		= &ip_ct_tcp_timeout_syn_sent,
+		.maxlen		= sizeof(unsigned int),
+		.mode		= 0644,
+		.proc_handler	= &proc_dointvec_jiffies,
+	},
+	{
+		.ctl_name	= NET_IPV4_NF_CONNTRACK_TCP_TIMEOUT_SYN_RECV,
+		.procname	= "ip_conntrack_tcp_timeout_syn_recv",
+		.data		= &ip_ct_tcp_timeout_syn_recv,
+		.maxlen		= sizeof(unsigned int),
+		.mode		= 0644,
+		.proc_handler	= &proc_dointvec_jiffies,
+	},
+	{
+		.ctl_name	= NET_IPV4_NF_CONNTRACK_TCP_TIMEOUT_ESTABLISHED,
+		.procname	= "ip_conntrack_tcp_timeout_established",
+		.data		= &ip_ct_tcp_timeout_established,
+		.maxlen		= sizeof(unsigned int),
+		.mode		= 0644,
+		.proc_handler	= &proc_dointvec_jiffies,
+	},
+	{
+		.ctl_name	= NET_IPV4_NF_CONNTRACK_TCP_TIMEOUT_FIN_WAIT,
+		.procname	= "ip_conntrack_tcp_timeout_fin_wait",
+		.data		= &ip_ct_tcp_timeout_fin_wait,
+		.maxlen		= sizeof(unsigned int),
+		.mode		= 0644,
+		.proc_handler	= &proc_dointvec_jiffies,
+	},
+	{
+		.ctl_name	= NET_IPV4_NF_CONNTRACK_TCP_TIMEOUT_CLOSE_WAIT,
+		.procname	= "ip_conntrack_tcp_timeout_close_wait",
+		.data		= &ip_ct_tcp_timeout_close_wait,
+		.maxlen		= sizeof(unsigned int),
+		.mode		= 0644,
+		.proc_handler	= &proc_dointvec_jiffies,
+	},
+	{
+		.ctl_name	= NET_IPV4_NF_CONNTRACK_TCP_TIMEOUT_LAST_ACK,
+		.procname	= "ip_conntrack_tcp_timeout_last_ack",
+		.data		= &ip_ct_tcp_timeout_last_ack,
+		.maxlen		= sizeof(unsigned int),
+		.mode		= 0644,
+		.proc_handler	= &proc_dointvec_jiffies,
+	},
+	{
+		.ctl_name	= NET_IPV4_NF_CONNTRACK_TCP_TIMEOUT_TIME_WAIT,
+		.procname	= "ip_conntrack_tcp_timeout_time_wait",
+		.data		= &ip_ct_tcp_timeout_time_wait,
+		.maxlen		= sizeof(unsigned int),
+		.mode		= 0644,
+		.proc_handler	= &proc_dointvec_jiffies,
+	},
+	{
+		.ctl_name	= NET_IPV4_NF_CONNTRACK_TCP_TIMEOUT_CLOSE,
+		.procname	= "ip_conntrack_tcp_timeout_close",
+		.data		= &ip_ct_tcp_timeout_close,
+		.maxlen		= sizeof(unsigned int),
+		.mode		= 0644,
+		.proc_handler	= &proc_dointvec_jiffies,
+	},
+	{
+		.ctl_name	= NET_IPV4_NF_CONNTRACK_UDP_TIMEOUT,
+		.procname	= "ip_conntrack_udp_timeout",
+		.data		= &ip_ct_udp_timeout,
+		.maxlen		= sizeof(unsigned int),
+		.mode		= 0644,
+		.proc_handler	= &proc_dointvec_jiffies,
+	},
+	{
+		.ctl_name	= NET_IPV4_NF_CONNTRACK_UDP_TIMEOUT_STREAM,
+		.procname	= "ip_conntrack_udp_timeout_stream",
+		.data		= &ip_ct_udp_timeout_stream,
+		.maxlen		= sizeof(unsigned int),
+		.mode		= 0644,
+		.proc_handler	= &proc_dointvec_jiffies,
+	},
+	{
+		.ctl_name	= NET_IPV4_NF_CONNTRACK_ICMP_TIMEOUT,
+		.procname	= "ip_conntrack_icmp_timeout",
+		.data		= &ip_ct_icmp_timeout,
+		.maxlen		= sizeof(unsigned int),
+		.mode		= 0644,
+		.proc_handler	= &proc_dointvec_jiffies,
+	},
+	{
+		.ctl_name	= NET_IPV4_NF_CONNTRACK_GENERIC_TIMEOUT,
+		.procname	= "ip_conntrack_generic_timeout",
+		.data		= &ip_ct_generic_timeout,
+		.maxlen		= sizeof(unsigned int),
+		.mode		= 0644,
+		.proc_handler	= &proc_dointvec_jiffies,
+	},
+	{ .ctl_name = 0 }
 };
 
 #define NET_IP_CONNTRACK_MAX 2089
 
 static ctl_table ip_ct_netfilter_table[] = {
-	{NET_IPV4_NETFILTER, "netfilter", NULL, 0, 0555, ip_ct_sysctl_table, 0, 0, 0, 0, 0},
-	{NET_IP_CONNTRACK_MAX, "ip_conntrack_max",
-	 &ip_conntrack_max, sizeof(int), 0644, NULL,
-	 &proc_dointvec},
-	{0}
+	{
+		.ctl_name	= NET_IPV4_NETFILTER,
+		.procname	= "netfilter",
+		.mode		= 0555,
+		.child		= ip_ct_sysctl_table,
+	},
+	{
+		.ctl_name	= NET_IP_CONNTRACK_MAX,
+		.procname	= "ip_conntrack_max",
+		.data		= &ip_conntrack_max,
+		.maxlen		= sizeof(int),
+		.mode		= 0644,
+		.proc_handler	= &proc_dointvec
+	},
+	{ .ctl_name = 0 }
 };
 
 static ctl_table ip_ct_ipv4_table[] = {
-	{NET_IPV4, "ipv4", NULL, 0, 0555, ip_ct_netfilter_table, 0, 0, 0, 0, 0},
-	{0}
+	{
+		.ctl_name	= NET_IPV4,
+		.procname	= "ipv4",
+		.mode		= 0555,
+		.child		= ip_ct_netfilter_table,
+	},
+	{ .ctl_name = 0 }
 };
 
 static ctl_table ip_ct_net_table[] = {
-	{CTL_NET, "net", NULL, 0, 0555, ip_ct_ipv4_table, 0, 0, 0, 0, 0},
-	{0}
+	{
+		.ctl_name	= CTL_NET,
+		.procname	= "net",
+		.mode		= 0555, 
+		.child		= ip_ct_ipv4_table,
+	},
+	{ .ctl_name = 0 }
 };
 #endif
 static int init_or_cleanup(int init)
--- diff/net/ipv4/route.c	2004-02-09 10:36:12.000000000 +0000
+++ source/net/ipv4/route.c	2004-02-23 13:56:48.000000000 +0000
@@ -2717,6 +2717,16 @@ static int ip_rt_acct_read(char *buffer,
 #endif /* CONFIG_PROC_FS */
 #endif /* CONFIG_NET_CLS_ROUTE */
 
+static __initdata unsigned long rhash_entries;
+static int __init set_rhash_entries(char *str)
+{
+	if (!str)
+		return 0;
+	rhash_entries = simple_strtoul(str, &str, 0);
+	return 1;
+}
+__setup("rhash_entries=", set_rhash_entries);
+
 int __init ip_rt_init(void)
 {
 	int i, order, goal, rc = 0;
@@ -2743,7 +2753,10 @@ int __init ip_rt_init(void)
 		panic("IP: failed to allocate ip_dst_cache\n");
 
 	goal = num_physpages >> (26 - PAGE_SHIFT);
-
+	if (!rhash_entries)
+		goal = min(10, goal);
+	else
+		goal = (rhash_entries * sizeof(struct rt_hash_bucket)) >> PAGE_SHIFT;
 	for (order = 0; (1UL << order) < goal; order++)
 		/* NOTHING */;
 
--- diff/net/ipv4/tcp.c	2004-02-18 08:54:13.000000000 +0000
+++ source/net/ipv4/tcp.c	2004-02-23 13:56:48.000000000 +0000
@@ -2570,6 +2570,16 @@ int tcp_getsockopt(struct sock *sk, int 
 extern void __skb_cb_too_small_for_tcp(int, int);
 extern void tcpdiag_init(void);
 
+static __initdata unsigned long thash_entries;
+static int __init set_thash_entries(char *str)
+{
+	if (!str)
+		return 0;
+	thash_entries = simple_strtoul(str, &str, 0);
+	return 1;
+}
+__setup("thash_entries=", set_thash_entries);
+
 void __init tcp_init(void)
 {
 	struct sk_buff *skb = NULL;
@@ -2611,6 +2621,10 @@ void __init tcp_init(void)
 	else
 		goal = num_physpages >> (23 - PAGE_SHIFT);
 
+	if (!thash_entries)
+		goal = min(10UL, goal);
+	else
+		goal = (thash_entries * sizeof(struct tcp_ehash_bucket)) >> PAGE_SHIFT;
 	for (order = 0; (1UL << order) < goal; order++)
 		;
 	do {
--- diff/net/ipv4/udp.c	2004-02-09 10:36:12.000000000 +0000
+++ source/net/ipv4/udp.c	2004-02-23 13:56:48.000000000 +0000
@@ -787,6 +787,7 @@ int udp_recvmsg(struct kiocb *iocb, stru
 	if (flags & MSG_ERRQUEUE)
 		return ip_recv_error(sk, msg, len);
 
+try_again:
 	skb = skb_recv_datagram(sk, flags, noblock, &err);
 	if (!skb)
 		goto out;
@@ -852,7 +853,9 @@ csum_copy_err:
 
 	skb_free_datagram(sk, skb);
 
-	return -EAGAIN;	
+	if (noblock)
+		return -EAGAIN;	
+	goto try_again;
 }
 
 int udp_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
--- diff/net/ipv4/xfrm4_input.c	2003-08-26 10:00:54.000000000 +0100
+++ source/net/ipv4/xfrm4_input.c	2004-02-23 13:56:48.000000000 +0000
@@ -9,6 +9,7 @@
  * 	
  */
 
+#include <linux/string.h>
 #include <net/inet_ecn.h>
 #include <net/ip.h>
 #include <net/xfrm.h>
@@ -18,9 +19,10 @@ int xfrm4_rcv(struct sk_buff *skb)
 	return xfrm4_rcv_encap(skb, 0);
 }
 
-static inline void ipip_ecn_decapsulate(struct iphdr *outer_iph, struct sk_buff *skb)
+static inline void ipip_ecn_decapsulate(struct sk_buff *skb)
 {
-	struct iphdr *inner_iph = skb->nh.iph;
+	struct iphdr *outer_iph = skb->nh.iph;
+	struct iphdr *inner_iph = skb->h.ipiph;
 
 	if (INET_ECN_is_ce(outer_iph->tos) &&
 	    INET_ECN_is_not_ce(inner_iph->tos))
@@ -95,10 +97,16 @@ int xfrm4_rcv_encap(struct sk_buff *skb,
 		if (x->props.mode) {
 			if (iph->protocol != IPPROTO_IPIP)
 				goto drop;
-			skb->nh.raw = skb->data;
+			if (!pskb_may_pull(skb, sizeof(struct iphdr)))
+				goto drop;
+			if (skb_cloned(skb) &&
+			    pskb_expand_head(skb, 0, 0, GFP_ATOMIC))
+				goto drop;
 			if (!(x->props.flags & XFRM_STATE_NOECN))
-				ipip_ecn_decapsulate(iph, skb);
-			iph = skb->nh.iph;
+				ipip_ecn_decapsulate(skb);
+			skb->mac.raw = memmove(skb->data - skb->mac_len,
+					       skb->mac.raw, skb->mac_len);
+			skb->nh.raw = skb->data;
 			memset(&(IPCB(skb)->opt), 0, sizeof(struct ip_options));
 			decaps = 1;
 			break;
--- diff/net/ipv6/addrconf.c	2004-02-18 08:54:13.000000000 +0000
+++ source/net/ipv6/addrconf.c	2004-02-23 13:56:48.000000000 +0000
@@ -149,6 +149,7 @@ struct ipv6_devconf ipv6_devconf = {
 	.accept_ra		= 1,
 	.accept_redirects	= 1,
 	.autoconf		= 1,
+	.force_mld_version	= 0,
 	.dad_transmits		= 1,
 	.rtr_solicits		= MAX_RTR_SOLICITATIONS,
 	.rtr_solicit_interval	= RTR_SOLICITATION_INTERVAL,
@@ -231,7 +232,7 @@ int ipv6_addr_type(const struct in6_addr
 
 	if ((addr->s6_addr32[0] | addr->s6_addr32[1]) == 0) {
 		if (addr->s6_addr32[2] == 0) {
-			if (addr->in6_u.u6_addr32[3] == 0)
+			if (addr->s6_addr32[3] == 0)
 				return IPV6_ADDR_ANY;
 
 			if (addr->s6_addr32[3] == htonl(0x00000001))
@@ -1071,7 +1072,7 @@ static int ipv6_generate_eui64(u8 *eui, 
 		eui[0] ^= 2;
 		return 0;
 	case ARPHRD_ARCNET:
-		/* XXX: inherit EUI-64 fro mother interface -- yoshfuji */
+		/* XXX: inherit EUI-64 from other interface -- yoshfuji */
 		if (dev->addr_len != ARCNET_ALEN)
 			return -1;
 		memset(eui, 0, 7);
@@ -2739,6 +2740,7 @@ static void inline ipv6_store_devconf(st
 	array[DEVCONF_RTR_SOLICITS] = cnf->rtr_solicits;
 	array[DEVCONF_RTR_SOLICIT_INTERVAL] = cnf->rtr_solicit_interval;
 	array[DEVCONF_RTR_SOLICIT_DELAY] = cnf->rtr_solicit_delay;
+	array[DEVCONF_FORCE_MLD_VERSION] = cnf->force_mld_version;
 #ifdef CONFIG_IPV6_PRIVACY
 	array[DEVCONF_USE_TEMPADDR] = cnf->use_tempaddr;
 	array[DEVCONF_TEMP_VALID_LFT] = cnf->temp_valid_lft;
@@ -3042,7 +3044,7 @@ static int addrconf_sysctl_forward_strat
 static struct addrconf_sysctl_table
 {
 	struct ctl_table_header *sysctl_header;
-	ctl_table addrconf_vars[17];
+	ctl_table addrconf_vars[18];
 	ctl_table addrconf_dev[2];
 	ctl_table addrconf_conf_dir[2];
 	ctl_table addrconf_proto_dir[2];
@@ -3133,6 +3135,14 @@ static struct addrconf_sysctl_table
          		.proc_handler	=	&proc_dointvec_jiffies,
 			.strategy	=	&sysctl_jiffies,
 		},
+		{
+			.ctl_name	=	NET_IPV6_FORCE_MLD_VERSION,
+			.procname	=	"force_mld_version",
+         		.data		=	&ipv6_devconf.force_mld_version,
+			.maxlen		=	sizeof(int),
+			.mode		=	0644,
+         		.proc_handler	=	&proc_dointvec,
+		},
 #ifdef CONFIG_IPV6_PRIVACY
 		{
 			.ctl_name	=	NET_IPV6_USE_TEMPADDR,
@@ -3345,8 +3355,7 @@ void __init addrconf_init(void)
 #endif
 }
 
-#ifdef MODULE
-void addrconf_cleanup(void)
+void __exit addrconf_cleanup(void)
 {
  	struct net_device *dev;
  	struct inet6_dev *idev;
@@ -3407,5 +3416,3 @@ void addrconf_cleanup(void)
 	proc_net_remove("if_inet6");
 #endif
 }
-#endif	/* MODULE */
-
--- diff/net/ipv6/af_inet6.c	2004-02-18 08:54:13.000000000 +0000
+++ source/net/ipv6/af_inet6.c	2004-02-23 13:56:48.000000000 +0000
@@ -56,7 +56,7 @@
 #include <net/transp_v6.h>
 #include <net/ip6_route.h>
 #include <net/addrconf.h>
-#if CONFIG_IPV6_TUNNEL
+#ifdef CONFIG_IPV6_TUNNEL
 #include <net/ip6_tunnel.h>
 #endif
 
@@ -90,11 +90,6 @@ extern int if6_proc_init(void);
 extern void if6_proc_exit(void);
 #endif
 
-#ifdef CONFIG_SYSCTL
-extern void ipv6_sysctl_register(void);
-extern void ipv6_sysctl_unregister(void);
-#endif
-
 int sysctl_ipv6_bindv6only;
 
 #ifdef INET_REFCNT_DEBUG
@@ -573,7 +568,7 @@ int ipv6_unload(void)
 #endif
 #endif
 
-#if defined(MODULE) && defined(CONFIG_SYSCTL)
+#ifdef CONFIG_SYSCTL
 extern void ipv6_sysctl_register(void);
 extern void ipv6_sysctl_unregister(void);
 #endif
@@ -784,7 +779,7 @@ static int __init inet6_init(void)
 	 *	able to communicate via both network protocols.
 	 */
 
-#if defined(MODULE) && defined(CONFIG_SYSCTL)
+#ifdef CONFIG_SYSCTL
 	ipv6_sysctl_register();
 #endif
 	err = icmpv6_init(&inet6_family_ops);
@@ -859,7 +854,7 @@ ip6_tunnel_fail:
 ndisc_fail:
 	icmpv6_cleanup();
 icmp_fail:
-#if defined(MODULE) && defined(CONFIG_SYSCTL)
+#ifdef CONFIG_SYSCTL
 	ipv6_sysctl_unregister();
 #endif
 	cleanup_ipv6_mibs();
@@ -868,9 +863,7 @@ init_mib_fail:
 }
 module_init(inet6_init);
 
-
-#ifdef MODULE
-static void inet6_exit(void)
+static void __exit inet6_exit(void)
 {
 	/* First of all disallow new sockets creation. */
 	sock_unregister(PF_INET6);
@@ -903,6 +896,5 @@ static void inet6_exit(void)
 	kmem_cache_destroy(raw6_sk_cachep);
 }
 module_exit(inet6_exit);
-#endif /* MODULE */
 
 MODULE_ALIAS_NETPROTO(PF_INET6);
--- diff/net/ipv6/exthdrs.c	2004-02-18 08:54:13.000000000 +0000
+++ source/net/ipv6/exthdrs.c	2004-02-23 13:56:48.000000000 +0000
@@ -120,7 +120,7 @@ static int ip6_parse_tlv(struct tlvtype_
 			for (curr=procs; curr->type >= 0; curr++) {
 				if (curr->type == skb->nh.raw[off]) {
 					/* type specific length/alignment 
-					   checks will be perfomed in the 
+					   checks will be performed in the 
 					   func(). */
 					if (curr->func(skb, off) == 0)
 						return 0;
@@ -694,7 +694,7 @@ int ipv6_ext_hdr(u8 nexthdr)
  * --ANK (980726)
  */
 
-int ipv6_skip_exthdr(struct sk_buff *skb, int start, u8 *nexthdrp, int len)
+int ipv6_skip_exthdr(const struct sk_buff *skb, int start, u8 *nexthdrp, int len)
 {
 	u8 nexthdr = *nexthdrp;
 
@@ -709,8 +709,16 @@ int ipv6_skip_exthdr(struct sk_buff *skb
 		if (skb_copy_bits(skb, start, &hdr, sizeof(hdr)))
 			BUG();
 		if (nexthdr == NEXTHDR_FRAGMENT) {
-			struct frag_hdr *fhdr = (struct frag_hdr *) &hdr;
-			if (ntohs(fhdr->frag_off) & ~0x7)
+			unsigned short frag_off;
+			if (skb_copy_bits(skb,
+					  start+offsetof(struct frag_hdr,
+							 frag_off),
+					  &frag_off,
+					  sizeof(frag_off))) {
+				return -1;
+			}
+
+			if (ntohs(frag_off) & ~0x7)
 				break;
 			hdrlen = 8;
 		} else if (nexthdr == NEXTHDR_AUTH)
--- diff/net/ipv6/ip6_fib.c	2004-02-09 10:36:12.000000000 +0000
+++ source/net/ipv6/ip6_fib.c	2004-02-23 13:56:48.000000000 +0000
@@ -85,7 +85,7 @@ static struct fib6_node * fib6_repair_tr
 
 /*
  *	A routing update causes an increase of the serial number on the
- *	afected subtree. This allows for cached routes to be asynchronously
+ *	affected subtree. This allows for cached routes to be asynchronously
  *	tested when modifications are made to the destination cache as a
  *	result of redirects, path MTU changes, etc.
  */
@@ -1241,12 +1241,8 @@ void __init fib6_init(void)
 					   NULL, NULL);
 }
 
-#ifdef MODULE
-void fib6_gc_cleanup(void)
+void __exit fib6_gc_cleanup(void)
 {
 	del_timer(&ip6_fib_timer);
 	kmem_cache_destroy(fib6_node_kmem);
 }
-#endif
-
-
--- diff/net/ipv6/ip6_input.c	2003-06-30 10:07:29.000000000 +0100
+++ source/net/ipv6/ip6_input.c	2004-02-23 13:56:48.000000000 +0000
@@ -168,11 +168,19 @@ resubmit:
 		
 		smp_read_barrier_depends();
 		if (ipprot->flags & INET6_PROTO_FINAL) {
+			struct ipv6hdr *hdr;	
+
 			if (!cksum_sub && skb->ip_summed == CHECKSUM_HW) {
 				skb->csum = csum_sub(skb->csum,
 						     csum_partial(skb->nh.raw, skb->h.raw-skb->nh.raw, 0));
 				cksum_sub++;
 			}
+			hdr = skb->nh.ipv6h;
+			if (ipv6_addr_is_multicast(&hdr->daddr) &&
+			    !ipv6_chk_mcast_addr(skb->dev, &hdr->daddr,
+			    &hdr->saddr) &&
+			    !ipv6_is_mld(skb, nexthdr))
+				goto discard;
 		}
 		if (!(ipprot->flags & INET6_PROTO_NOPOLICY) &&
 		    !xfrm6_policy_check(NULL, XFRM_POLICY_IN, skb)) 
@@ -211,15 +219,14 @@ int ip6_input(struct sk_buff *skb)
 
 int ip6_mc_input(struct sk_buff *skb)
 {
-	struct ipv6hdr *hdr;	
-	int deliver = 0;
-	int discard = 1;
+	struct ipv6hdr *hdr;
+	int deliver;
 
 	IP6_INC_STATS_BH(Ip6InMcastPkts);
 
 	hdr = skb->nh.ipv6h;
-	if (ipv6_chk_mcast_addr(skb->dev, &hdr->daddr, &hdr->saddr))
-		deliver = 1;
+	deliver = likely(!(skb->dev->flags & (IFF_PROMISC|IFF_ALLMULTI))) ||
+	    ipv6_chk_mcast_addr(skb->dev, &hdr->daddr, NULL);
 
 	/*
 	 *	IPv6 multicast router mode isnt currently supported.
@@ -238,23 +245,21 @@ int ip6_mc_input(struct sk_buff *skb)
 			
 			if (deliver) {
 				skb2 = skb_clone(skb, GFP_ATOMIC);
+				dst_output(skb2);
 			} else {
-				discard = 0;
-				skb2 = skb;
+				dst_output(skb);
+				return 0;
 			}
-
-			dst_output(skb2);
 		}
 	}
 #endif
 
-	if (deliver) {
-		discard = 0;
+	if (likely(deliver)) {
 		ip6_input(skb);
+		return 0;
 	}
-
-	if (discard)
-		kfree_skb(skb);
+	/* discard */
+	kfree_skb(skb);
 
 	return 0;
 }
--- diff/net/ipv6/ip6_tunnel.c	2004-02-09 10:36:12.000000000 +0000
+++ source/net/ipv6/ip6_tunnel.c	2004-02-23 13:56:48.000000000 +0000
@@ -245,7 +245,7 @@ ip6_tnl_create(struct ip6_tnl_parm *p, s
 	t->parms = *p;
 
 	if ((err = register_netdevice(dev)) < 0) {
-		kfree(dev);
+		free_netdev(dev);
 		return err;
 	}
 	dev_hold(dev);
@@ -399,7 +399,7 @@ void ip6ip6_err(struct sk_buff *skb, str
 	__u16 len;
 
 	/* If the packet doesn't contain the original IPv6 header we are 
-	   in trouble since we might need the source address for furter 
+	   in trouble since we might need the source address for further 
 	   processing of the error. */
 
 	read_lock(&ip6ip6_lock);
@@ -1118,7 +1118,7 @@ int __init ip6_tunnel_init(void)
 	ip6ip6_fb_tnl_dev->init = ip6ip6_fb_tnl_dev_init;
 
 	if ((err = register_netdev(ip6ip6_fb_tnl_dev))) {
-		kfree(ip6ip6_fb_tnl_dev);
+		free_netdev(ip6ip6_fb_tnl_dev);
 		goto fail;
 	}
 	return 0;
--- diff/net/ipv6/ipv6_sockglue.c	2004-02-18 08:54:13.000000000 +0000
+++ source/net/ipv6/ipv6_sockglue.c	2004-02-23 13:56:48.000000000 +0000
@@ -450,6 +450,11 @@ done:
 			kfree(gsf);
 			break;
 		}
+		if (GROUP_FILTER_SIZE(gsf->gf_numsrc) > optlen) {
+			kfree(gsf);
+			retv = -EINVAL;
+			break;
+		}
 		retv = ip6_mc_msfilter(sk, gsf);
 		kfree(gsf);
 
@@ -675,24 +680,12 @@ int ipv6_getsockopt(struct sock *sk, int
 	return 0;
 }
 
-#if defined(MODULE) && defined(CONFIG_SYSCTL)
-
-/*
- *	sysctl registration functions defined in sysctl_net_ipv6.c
- */
-
-extern void ipv6_sysctl_register(void);
-extern void ipv6_sysctl_unregister(void);
-#endif
-
 void __init ipv6_packet_init(void)
 {
 	dev_add_pack(&ipv6_packet_type);
 }
 
-#ifdef MODULE
-void ipv6_packet_cleanup(void)
+void __exit ipv6_packet_cleanup(void)
 {
 	dev_remove_pack(&ipv6_packet_type);
 }
-#endif
--- diff/net/ipv6/ipv6_syms.c	2003-09-17 12:28:12.000000000 +0100
+++ source/net/ipv6/ipv6_syms.c	2004-02-23 13:56:48.000000000 +0000
@@ -46,3 +46,4 @@ EXPORT_SYMBOL(ip6_append_data);
 EXPORT_SYMBOL(ip6_flush_pending_frames);
 EXPORT_SYMBOL(ip6_push_pending_frames);
 EXPORT_SYMBOL(ipv6_push_nfrag_opts);
+EXPORT_SYMBOL(ipv6_skip_exthdr);
--- diff/net/ipv6/mcast.c	2004-02-18 08:54:13.000000000 +0000
+++ source/net/ipv6/mcast.c	2004-02-23 13:56:48.000000000 +0000
@@ -152,8 +152,10 @@ int ip6_mc_leave_src(struct sock *sk, st
 #define IGMP6_UNSOLICITED_IVAL	(10*HZ)
 #define MLD_QRV_DEFAULT		2
 
-#define MLD_V1_SEEN(idev) ((idev)->mc_v1_seen && \
-		time_before(jiffies, (idev)->mc_v1_seen))
+#define MLD_V1_SEEN(idev) (ipv6_devconf.force_mld_version == 1 || \
+		(idev)->cnf.force_mld_version == 1 || \
+		((idev)->mc_v1_seen && \
+		time_before(jiffies, (idev)->mc_v1_seen)))
 
 #define MLDV2_MASK(value, nb) ((nb)>=32 ? (value) : ((1<<(nb))-1) & (value))
 #define MLDV2_EXP(thresh, nbmant, nbexp, value) \
@@ -901,6 +903,33 @@ int ipv6_dev_mc_dec(struct net_device *d
 }
 
 /*
+ * identify MLD packets for MLD filter exceptions
+ */
+int ipv6_is_mld(struct sk_buff *skb, int nexthdr)
+{
+	struct icmp6hdr *pic;
+
+	if (nexthdr != IPPROTO_ICMPV6)
+		return 0;
+
+	if (!pskb_may_pull(skb, sizeof(struct icmp6hdr)))
+		return 0;
+
+	pic = (struct icmp6hdr *)skb->h.raw;
+
+	switch (pic->icmp6_type) {
+	case ICMPV6_MGM_QUERY:
+	case ICMPV6_MGM_REPORT:
+	case ICMPV6_MGM_REDUCTION:
+	case ICMPV6_MLD2_REPORT:
+		return 1;
+	default:
+		break;
+	}
+	return 0;
+}
+
+/*
  *	check if the interface/address pair is valid
  */
 int ipv6_chk_mcast_addr(struct net_device *dev, struct in6_addr *group,
@@ -918,7 +947,7 @@ int ipv6_chk_mcast_addr(struct net_devic
 				break;
 		}
 		if (mc) {
-			if (!ipv6_addr_any(src_addr)) {
+			if (src_addr && !ipv6_addr_any(src_addr)) {
 				struct ip6_sf_list *psf;
 
 				spin_lock_bh(&mc->mca_lock);
--- diff/net/ipv6/ndisc.c	2004-02-18 08:54:13.000000000 +0000
+++ source/net/ipv6/ndisc.c	2004-02-23 13:56:48.000000000 +0000
@@ -28,11 +28,12 @@
 /* Set to 3 to get tracing... */
 #define ND_DEBUG 1
 
-#define ND_PRINTK(x...) printk(KERN_DEBUG x)
+#define ND_PRINTK(fmt, args...) do { if (net_ratelimit()) { printk(fmt, ## args); } } while(0)
 #define ND_NOPRINTK(x...) do { ; } while(0)
 #define ND_PRINTK0 ND_PRINTK
 #define ND_PRINTK1 ND_NOPRINTK
 #define ND_PRINTK2 ND_NOPRINTK
+#define ND_PRINTK3 ND_NOPRINTK
 #if ND_DEBUG >= 1
 #undef ND_PRINTK1
 #define ND_PRINTK1 ND_PRINTK
@@ -41,6 +42,10 @@
 #undef ND_PRINTK2
 #define ND_PRINTK2 ND_PRINTK
 #endif
+#if ND_DEBUG >= 3
+#undef ND_PRINTK3
+#define ND_PRINTK3 ND_PRINTK
+#endif
 
 #include <linux/module.h>
 #include <linux/config.h>
@@ -210,8 +215,10 @@ static struct ndisc_options *ndisc_parse
 		case ND_OPT_MTU:
 		case ND_OPT_REDIRECT_HDR:
 			if (ndopts->nd_opt_array[nd_opt->nd_opt_type]) {
-				ND_PRINTK2("ndisc_parse_options(): duplicated ND6 option found: type=%d\n",
-					    nd_opt->nd_opt_type);
+				ND_PRINTK2(KERN_WARNING
+					   "%s(): duplicated ND6 option found: type=%d\n",
+					   __FUNCTION__,
+					   nd_opt->nd_opt_type);
 			} else {
 				ndopts->nd_opt_array[nd_opt->nd_opt_type] = nd_opt;
 			}
@@ -226,8 +233,9 @@ static struct ndisc_options *ndisc_parse
 			 * Unknown options must be silently ignored,
 			 * to accommodate future extension to the protocol.
 			 */
-			ND_PRINTK2(KERN_WARNING
-				   "ndisc_parse_options(): ignored unsupported option; type=%d, len=%d\n",
+			ND_PRINTK2(KERN_NOTICE
+				   "%s(): ignored unsupported option; type=%d, len=%d\n",
+				   __FUNCTION__,
 				   nd_opt->nd_opt_type, nd_opt->nd_opt_len);
 		}
 		opt_len -= l;
@@ -341,65 +349,10 @@ static void pndisc_destructor(struct pne
 	ipv6_dev_mc_dec(dev, &maddr);
 }
 
-
-
-static int
-ndisc_build_ll_hdr(struct sk_buff *skb, struct net_device *dev,
-		   struct in6_addr *daddr, struct neighbour *neigh, int len)
-{
-	unsigned char ha[MAX_ADDR_LEN];
-	unsigned char *h_dest = NULL;
-
-	if (dev->hard_header) {
-		if (ipv6_addr_is_multicast(daddr)) {
-			ndisc_mc_map(daddr, ha, dev, 1);
-			h_dest = ha;
-		} else if (neigh) {
-			read_lock_bh(&neigh->lock);
-			if (neigh->nud_state&NUD_VALID) {
-				memcpy(ha, neigh->ha, dev->addr_len);
-				h_dest = ha;
-			}
-			read_unlock_bh(&neigh->lock);
-		} else {
-			neigh = neigh_lookup(&nd_tbl, daddr, dev);
-			if (neigh) {
-				read_lock_bh(&neigh->lock);
-				if (neigh->nud_state&NUD_VALID) {
-					memcpy(ha, neigh->ha, dev->addr_len);
-					h_dest = ha;
-				}
-				read_unlock_bh(&neigh->lock);
-				neigh_release(neigh);
-			}
-		}
-
-		if (dev->hard_header(skb, dev, ETH_P_IPV6, h_dest, NULL, len) < 0)
-			return 0;
-	}
-
-	return 1;
-}
-
-
 /*
  *	Send a Neighbour Advertisement
  */
 
-static int ndisc_output(struct sk_buff *skb)
-{
-	if (skb) {
-		struct neighbour *neigh = (skb->dst ? skb->dst->neighbour : NULL);
-		if (ndisc_build_ll_hdr(skb, skb->dev, &skb->nh.ipv6h->daddr, neigh, skb->len) == 0) {
-			kfree_skb(skb);
-			return -EINVAL;
-		}
-		dev_queue_xmit(skb);
-		return 0;
-	}
-	return -EINVAL;
-}
-
 static inline void ndisc_flow_init(struct flowi *fl, u8 type,
 			    struct in6_addr *saddr, struct in6_addr *daddr)
 {
@@ -442,7 +395,7 @@ static void ndisc_send_na(struct net_dev
 
 	ndisc_flow_init(&fl, NDISC_NEIGHBOUR_ADVERTISEMENT, src_addr, daddr);
 
-	dst = ndisc_dst_alloc(dev, neigh, ndisc_output);
+	dst = ndisc_dst_alloc(dev, neigh, daddr, ip6_output2);
 	if (!dst)
 		return;
 
@@ -463,7 +416,9 @@ static void ndisc_send_na(struct net_dev
 				  1, &err);
 
 	if (skb == NULL) {
-		ND_PRINTK1("send_na: alloc skb failed\n");
+		ND_PRINTK0(KERN_ERR
+			   "ICMPv6 NA: %s() failed to allocate an skb.\n", 
+			   __FUNCTION__);
 		dst_release(dst);
 		return;
 	}
@@ -530,7 +485,7 @@ void ndisc_send_ns(struct net_device *de
 
 	ndisc_flow_init(&fl, NDISC_NEIGHBOUR_SOLICITATION, saddr, daddr);
 
-	dst = ndisc_dst_alloc(dev, neigh, ndisc_output);
+	dst = ndisc_dst_alloc(dev, neigh, daddr, ip6_output2);
 	if (!dst)
 		return;
 
@@ -548,7 +503,9 @@ void ndisc_send_ns(struct net_device *de
 	skb = sock_alloc_send_skb(sk, MAX_HEADER + len + LL_RESERVED_SPACE(dev),
 				  1, &err);
 	if (skb == NULL) {
-		ND_PRINTK1("send_ns: alloc skb failed\n");
+		ND_PRINTK0(KERN_ERR
+			   "ICMPv6 NA: %s() failed to allocate an skb.\n", 
+			   __FUNCTION__);
 		dst_release(dst);
 		return;
 	}
@@ -603,7 +560,7 @@ void ndisc_send_rs(struct net_device *de
 
 	ndisc_flow_init(&fl, NDISC_ROUTER_SOLICITATION, saddr, daddr);
 
-	dst = ndisc_dst_alloc(dev, NULL, ndisc_output);
+	dst = ndisc_dst_alloc(dev, NULL, daddr, ip6_output2);
 	if (!dst)
 		return;
 
@@ -620,7 +577,9 @@ void ndisc_send_rs(struct net_device *de
         skb = sock_alloc_send_skb(sk, MAX_HEADER + len + LL_RESERVED_SPACE(dev),
 				  1, &err);
 	if (skb == NULL) {
-		ND_PRINTK1("send_ns: alloc skb failed\n");
+		ND_PRINTK0(KERN_ERR
+			   "ICMPv6 RS: %s() failed to allocate an skb.\n", 
+			   __FUNCTION__);
 		dst_release(dst);
 		return;
 	}
@@ -683,8 +642,13 @@ static void ndisc_solicit(struct neighbo
 		saddr = &skb->nh.ipv6h->saddr;
 
 	if ((probes -= neigh->parms->ucast_probes) < 0) {
-		if (!(neigh->nud_state&NUD_VALID))
-			ND_PRINTK1("trying to ucast probe in NUD_INVALID\n");
+		if (!(neigh->nud_state & NUD_VALID)) {
+			ND_PRINTK1(KERN_DEBUG
+				   "%s(): trying to ucast probe in NUD_INVALID: "
+				   "%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x\n",
+				   __FUNCTION__,
+				   NIP6(*target));
+		}
 		ndisc_send_ns(dev, neigh, target, target, saddr);
 	} else if ((probes -= neigh->parms->app_probes) < 0) {
 #ifdef CONFIG_ARPD
@@ -713,8 +677,8 @@ static void ndisc_recv_ns(struct sk_buff
 	int inc;
 
 	if (ipv6_addr_is_multicast(&msg->target)) {
-		if (net_ratelimit())
-			printk(KERN_WARNING "ICMP NS: target address is multicast\n");
+		ND_PRINTK2(KERN_WARNING 
+			   "ICMPv6 NS: multicast target address");
 		return;
 	}
 
@@ -727,14 +691,14 @@ static void ndisc_recv_ns(struct sk_buff
 	      daddr->s6_addr32[1] == htonl(0x00000000) &&
 	      daddr->s6_addr32[2] == htonl(0x00000001) &&
 	      daddr->s6_addr [12] == 0xff )) {
-		if (net_ratelimit())
-			printk(KERN_DEBUG "ICMP6 NS: bad DAD packet (wrong destination)\n");
+		ND_PRINTK2(KERN_WARNING
+			   "ICMPv6 NS: bad DAD packet (wrong destination)\n");
 		return;
 	}
 
 	if (!ndisc_parse_options(msg->opt, ndoptlen, &ndopts)) {
-		if (net_ratelimit())
-			printk(KERN_WARNING "ICMP NS: invalid ND option, ignored.\n");
+		ND_PRINTK2(KERN_WARNING 
+			   "ICMPv6 NS: invalid ND options\n");
 		return;
 	}
 
@@ -742,19 +706,19 @@ static void ndisc_recv_ns(struct sk_buff
 		lladdr = (u8*)(ndopts.nd_opts_src_lladdr + 1);
 		lladdrlen = ndopts.nd_opts_src_lladdr->nd_opt_len << 3;
 		if (lladdrlen != NDISC_OPT_SPACE(dev->addr_len)) {
-			if (net_ratelimit())
-				printk(KERN_WARNING "ICMP NS: bad lladdr length.\n");
+			ND_PRINTK2(KERN_WARNING
+				   "ICMPv6 NS: invalid link-layer address length\n");
 			return;
 		}
 
-		/* XXX: RFC2461 7.1.1:
+		/* RFC2461 7.1.1:
 	 	 *	If the IP source address is the unspecified address, 
 		 *	there MUST NOT be source link-layer address option 
 		 *	in the message.
 		 */
 		if (dad) {
-			if (net_ratelimit())
-				printk(KERN_WARNING "ICMP6 NS: bad DAD packet (link-layer address option)\n");
+			ND_PRINTK2(KERN_WARNING 
+				   "ICMPv6 NS: bad DAD packet (link-layer address option)\n");
 			return;
 		}
 	}
@@ -868,34 +832,35 @@ static void ndisc_recv_na(struct sk_buff
 	struct neighbour *neigh;
 
 	if (skb->len < sizeof(struct nd_msg)) {
-		if (net_ratelimit())
-			printk(KERN_WARNING "ICMP NA: packet too short\n");
+		ND_PRINTK2(KERN_WARNING
+			   "ICMPv6 NA: packet too short\n");
 		return;
 	}
 
 	if (ipv6_addr_is_multicast(&msg->target)) {
-		if (net_ratelimit())
-			printk(KERN_WARNING "NDISC NA: target address is multicast\n");
+		ND_PRINTK2(KERN_WARNING
+			   "ICMPv6 NA: target address is multicast.\n");
 		return;
 	}
 
 	if (ipv6_addr_is_multicast(daddr) &&
 	    msg->icmph.icmp6_solicited) {
-		ND_PRINTK0("NDISC: solicited NA is multicasted\n");
+		ND_PRINTK2(KERN_WARNING
+			   "ICMPv6 NA: solicited NA is multicasted.\n");
 		return;
 	}
 		
 	if (!ndisc_parse_options(msg->opt, ndoptlen, &ndopts)) {
-		if (net_ratelimit())
-			printk(KERN_WARNING "ICMP NS: invalid ND option, ignored.\n");
+		ND_PRINTK2(KERN_WARNING
+			   "ICMPv6 NS: invalid ND option\n");
 		return;
 	}
 	if (ndopts.nd_opts_tgt_lladdr) {
 		lladdr = (u8*)(ndopts.nd_opts_tgt_lladdr + 1);
 		lladdrlen = ndopts.nd_opts_tgt_lladdr->nd_opt_len << 3;
 		if (lladdrlen != NDISC_OPT_SPACE(dev->addr_len)) {
-			if (net_ratelimit())
-				printk(KERN_WARNING "NDISC NA: invalid lladdr length.\n");
+			ND_PRINTK2(KERN_WARNING
+				   "ICMPv6 NA: invalid link-layer address length\n");
 			return;
 		}
 	}
@@ -909,7 +874,8 @@ static void ndisc_recv_na(struct sk_buff
 		   about it. It could be misconfiguration, or
 		   an smart proxy agent tries to help us :-)
 		 */
-		ND_PRINTK0("%s: someone advertises our address!\n",
+		ND_PRINTK1(KERN_WARNING
+			   "ICMPv6 NA: someone advertises our address on %s!\n",
 			   ifp->idev->dev->name);
 		in6_ifa_put(ifp);
 		return;
@@ -954,13 +920,13 @@ static void ndisc_router_discovery(struc
 	optlen = (skb->tail - skb->h.raw) - sizeof(struct ra_msg);
 
 	if (!(ipv6_addr_type(&skb->nh.ipv6h->saddr) & IPV6_ADDR_LINKLOCAL)) {
-		if (net_ratelimit())
-			printk(KERN_WARNING "ICMP RA: source address is not linklocal\n");
+		ND_PRINTK2(KERN_WARNING
+			   "ICMPv6 RA: source address is not link-local.\n");
 		return;
 	}
 	if (optlen < 0) {
-		if (net_ratelimit())
-			printk(KERN_WARNING "ICMP RA: packet too short\n");
+		ND_PRINTK2(KERN_WARNING 
+			   "ICMPv6 RA: packet too short\n");
 		return;
 	}
 
@@ -970,7 +936,9 @@ static void ndisc_router_discovery(struc
 
 	in6_dev = in6_dev_get(skb->dev);
 	if (in6_dev == NULL) {
-		ND_PRINTK1("RA: can't find in6 device\n");
+		ND_PRINTK0(KERN_ERR
+			   "ICMPv6 RA: can't find inet6 device for %s.\n",
+			   skb->dev->name);
 		return;
 	}
 	if (in6_dev->cnf.forwarding || !in6_dev->cnf.accept_ra) {
@@ -980,9 +948,8 @@ static void ndisc_router_discovery(struc
 
 	if (!ndisc_parse_options(opt, optlen, &ndopts)) {
 		in6_dev_put(in6_dev);
-		if (net_ratelimit())
-			ND_PRINTK2(KERN_WARNING
-				   "ICMP6 RA: invalid ND option, ignored.\n");
+		ND_PRINTK2(KERN_WARNING
+			   "ICMP6 RA: invalid ND options\n");
 		return;
 	}
 
@@ -1015,18 +982,23 @@ static void ndisc_router_discovery(struc
 	}
 
 	if (rt == NULL && lifetime) {
-		ND_PRINTK2("ndisc_rdisc: adding default router\n");
+		ND_PRINTK3(KERN_DEBUG
+			   "ICMPv6 RA: adding default router.\n");
 
 		rt = rt6_add_dflt_router(&skb->nh.ipv6h->saddr, skb->dev);
 		if (rt == NULL) {
-			ND_PRINTK1("route_add failed\n");
+			ND_PRINTK0(KERN_ERR
+				   "ICMPv6 RA: %s() failed to add default route.\n",
+				   __FUNCTION__);
 			in6_dev_put(in6_dev);
 			return;
 		}
 
 		neigh = rt->rt6i_nexthop;
 		if (neigh == NULL) {
-			ND_PRINTK1("nd: add default router: null neighbour\n");
+			ND_PRINTK0(KERN_ERR
+				   "ICMPv6 RA: %s() got default router without neighbour.\n",
+				   __FUNCTION__);
 			dst_release(&rt->u.dst);
 			in6_dev_put(in6_dev);
 			return;
@@ -1052,7 +1024,7 @@ static void ndisc_router_discovery(struc
 	 */
 
 	if (in6_dev->nd_parms) {
-		__u32 rtime = ntohl(ra_msg->retrans_timer);
+		unsigned long rtime = ntohl(ra_msg->retrans_timer);
 
 		if (rtime && rtime/1000 < MAX_SCHEDULE_TIMEOUT/HZ) {
 			rtime = (rtime*HZ)/1000;
@@ -1091,9 +1063,8 @@ static void ndisc_router_discovery(struc
 			lladdr = (u8*)((ndopts.nd_opts_src_lladdr)+1);
 			lladdrlen = ndopts.nd_opts_src_lladdr->nd_opt_len << 3;
 			if (lladdrlen != NDISC_OPT_SPACE(skb->dev->addr_len)) {
-				if (net_ratelimit())
-					ND_PRINTK2(KERN_WARNING
-						   "ICMP6 RA: Invalid lladdr length.\n");
+				ND_PRINTK2(KERN_WARNING
+					   "ICMPv6 RA: invalid link-layer address length\n");
 				goto out;
 			}
 		}
@@ -1116,10 +1087,9 @@ static void ndisc_router_discovery(struc
 		mtu = ntohl(mtu);
 
 		if (mtu < IPV6_MIN_MTU || mtu > skb->dev->mtu) {
-			if (net_ratelimit()) {
-				ND_PRINTK0("NDISC: router announcement with mtu = %d\n",
-					   mtu);
-			}
+			ND_PRINTK2(KERN_WARNING
+				   "ICMPv6 RA: invalid mtu: %d\n",
+				   mtu);
 		} else if (in6_dev->cnf.mtu6 != mtu) {
 			in6_dev->cnf.mtu6 = mtu;
 
@@ -1131,9 +1101,8 @@ static void ndisc_router_discovery(struc
 	}
 			
 	if (ndopts.nd_opts_tgt_lladdr || ndopts.nd_opts_rh) {
-		if (net_ratelimit())
-			ND_PRINTK0(KERN_WARNING
-				   "ICMP6 RA: got invalid option with RA");
+		ND_PRINTK2(KERN_WARNING
+			   "ICMPv6 RA: invalid RA options");
 	}
 out:
 	if (rt)
@@ -1155,8 +1124,8 @@ static void ndisc_redirect_rcv(struct sk
 	int lladdrlen;
 
 	if (!(ipv6_addr_type(&skb->nh.ipv6h->saddr) & IPV6_ADDR_LINKLOCAL)) {
-		if (net_ratelimit())
-			printk(KERN_WARNING "ICMP redirect: source address is not linklocal\n");
+		ND_PRINTK2(KERN_WARNING
+			   "ICMPv6 Redirect: source address is not link-local.\n");
 		return;
 	}
 
@@ -1164,8 +1133,8 @@ static void ndisc_redirect_rcv(struct sk
 	optlen -= sizeof(struct icmp6hdr) + 2 * sizeof(struct in6_addr);
 
 	if (optlen < 0) {
-		if (net_ratelimit())
-			printk(KERN_WARNING "ICMP redirect: packet too small\n");
+		ND_PRINTK2(KERN_WARNING
+			   "ICMPv6 Redirect: packet too short\n");
 		return;
 	}
 
@@ -1174,16 +1143,16 @@ static void ndisc_redirect_rcv(struct sk
 	dest = target + 1;
 
 	if (ipv6_addr_is_multicast(dest)) {
-		if (net_ratelimit())
-			printk(KERN_WARNING "ICMP redirect for multicast addr\n");
+		ND_PRINTK2(KERN_WARNING
+			   "ICMPv6 Redirect: destination address is multicast.\n");
 		return;
 	}
 
 	if (ipv6_addr_cmp(dest, target) == 0) {
 		on_link = 1;
 	} else if (!(ipv6_addr_type(target) & IPV6_ADDR_LINKLOCAL)) {
-		if (net_ratelimit())
-			printk(KERN_WARNING "ICMP redirect: target address is not linklocal\n");
+		ND_PRINTK2(KERN_WARNING 
+			   "ICMPv6 Redirect: target address is not link-local.\n");
 		return;
 	}
 
@@ -1195,15 +1164,14 @@ static void ndisc_redirect_rcv(struct sk
 		return;
 	}
 
-	/* XXX: RFC2461 8.1: 
+	/* RFC2461 8.1: 
 	 *	The IP source address of the Redirect MUST be the same as the current
 	 *	first-hop router for the specified ICMP Destination Address.
 	 */
 		
 	if (!ndisc_parse_options((u8*)(dest + 1), optlen, &ndopts)) {
-		if (net_ratelimit())
-			ND_PRINTK2(KERN_WARNING
-				   "ICMP6 Redirect: invalid ND options, rejected.\n");
+		ND_PRINTK2(KERN_WARNING
+			   "ICMPv6 Redirect: invalid ND options\n");
 		in6_dev_put(in6_dev);
 		return;
 	}
@@ -1211,9 +1179,8 @@ static void ndisc_redirect_rcv(struct sk
 		lladdr = (u8*)(ndopts.nd_opts_tgt_lladdr + 1);
 		lladdrlen = ndopts.nd_opts_tgt_lladdr->nd_opt_len << 3;
 		if (lladdrlen != NDISC_OPT_SPACE(skb->dev->addr_len)) {
-			if (net_ratelimit())
-				ND_PRINTK2(KERN_WARNING
-					   "ICMP6 Redirect: invalid lladdr length.\n");
+			ND_PRINTK2(KERN_WARNING
+				   "ICMPv6 Redirect: invalid link-layer address length\n");
 			in6_dev_put(in6_dev);
 			return;
 		}
@@ -1258,7 +1225,9 @@ void ndisc_send_redirect(struct sk_buff 
 	dev = skb->dev;
 
 	if (ipv6_get_lladdr(dev, &saddr_buf)) {
- 		ND_PRINTK1("redirect: no link_local addr for dev\n");
+		ND_PRINTK2(KERN_WARNING
+			   "ICMPv6 Redirect: no link-local address on %s\n",
+			   dev->name);
  		return;
  	}
 
@@ -1278,7 +1247,8 @@ void ndisc_send_redirect(struct sk_buff 
 	rt = (struct rt6_info *) dst;
 
 	if (rt->rt6i_flags & RTF_GATEWAY) {
-		ND_PRINTK1("ndisc_send_redirect: not a neighbour\n");
+		ND_PRINTK2(KERN_WARNING
+			   "ICMPv6 Redirect: destination is not a neighbour.\n");
 		dst_release(dst);
 		return;
 	}
@@ -1308,7 +1278,9 @@ void ndisc_send_redirect(struct sk_buff 
 	buff = sock_alloc_send_skb(sk, MAX_HEADER + len + LL_RESERVED_SPACE(dev),
 				   1, &err);
 	if (buff == NULL) {
-		ND_PRINTK1("ndisc_send_redirect: alloc_skb failed\n");
+		ND_PRINTK0(KERN_ERR
+			   "ICMPv6 Redirect: %s() failed to allocate an skb.\n",
+			   __FUNCTION__);
 		dst_release(dst);
 		return;
 	}
@@ -1388,16 +1360,16 @@ int ndisc_rcv(struct sk_buff *skb)
 	__skb_push(skb, skb->data-skb->h.raw);
 
 	if (skb->nh.ipv6h->hop_limit != 255) {
-		if (net_ratelimit())
-			printk(KERN_WARNING
-			       "ICMP NDISC: fake message with non-255 Hop Limit received: %d\n",
-			       		skb->nh.ipv6h->hop_limit);
+		ND_PRINTK2(KERN_WARNING
+			   "ICMPv6 NDISC: invalid hop-limit: %d\n",
+			   skb->nh.ipv6h->hop_limit);
 		return 0;
 	}
 
 	if (msg->icmph.icmp6_code != 0) {
-		if (net_ratelimit())
-			printk(KERN_WARNING "ICMP NDISC: code is not zero\n");
+		ND_PRINTK2(KERN_WARNING 
+			   "ICMPv6 NDISC: invalid ICMPv6 code: %d\n",
+			   msg->icmph.icmp6_code);
 		return 0;
 	}
 
@@ -1465,9 +1437,9 @@ int __init ndisc_init(struct net_proto_f
 
 	err = sock_create(PF_INET6, SOCK_RAW, IPPROTO_ICMPV6, &ndisc_socket);
 	if (err < 0) {
-		printk(KERN_ERR
-		       "Failed to initialize the NDISC control socket (err %d).\n",
-		       err);
+		ND_PRINTK0(KERN_ERR
+			   "ICMPv6 NDISC: Failed to initialize the control socket (err %d).\n", 
+			   err);
 		ndisc_socket = NULL; /* For safety. */
 		return err;
 	}
--- diff/net/ipv6/netfilter/ip6_tables.c	2004-02-18 08:54:13.000000000 +0000
+++ source/net/ipv6/netfilter/ip6_tables.c	2004-02-23 13:56:48.000000000 +0000
@@ -24,6 +24,7 @@
 #include <linux/udp.h>
 #include <linux/icmpv6.h>
 #include <net/ip.h>
+#include <net/ipv6.h>
 #include <asm/uaccess.h>
 #include <asm/semaphore.h>
 #include <linux/proc_fs.h>
@@ -1570,8 +1571,10 @@ tcp_match(const struct sk_buff *skb,
 	  u_int16_t datalen,
 	  int *hotdrop)
 {
-	const struct tcphdr *tcp = hdr;
+	const struct tcphdr *tcp;
 	const struct ip6t_tcp *tcpinfo = matchinfo;
+	int tcpoff;
+	u8 nexthdr = skb->nh.ipv6h->nexthdr;
 
 	/* To quote Alan:
 
@@ -1592,6 +1595,24 @@ tcp_match(const struct sk_buff *skb,
 		return 0;
 	}
 
+	tcpoff = (u8*)(skb->nh.ipv6h + 1) - skb->data;
+	tcpoff = ipv6_skip_exthdr(skb, tcpoff, &nexthdr, skb->len - tcpoff);
+	if (tcpoff < 0 || tcpoff > skb->len) {
+		duprintf("tcp_match: cannot skip exthdr. Dropping.\n");
+		*hotdrop = 1;
+		return 0;
+	} else if (nexthdr == IPPROTO_FRAGMENT)
+		return 0;
+	else if (nexthdr != IPPROTO_TCP ||
+		 skb->len - tcpoff < sizeof(struct tcphdr)) {
+		/* cannot be occured */
+		duprintf("tcp_match: cannot get TCP header. Dropping.\n");
+		*hotdrop = 1;
+		return 0;
+	}
+
+	tcp = (struct tcphdr *)(skb->data + tcpoff);
+
 	/* FIXME: Try tcp doff >> packet len against various stacks --RR */
 
 #define FWINVTCP(bool,invflg) ((bool) ^ !!(tcpinfo->invflags & invflg))
@@ -1642,8 +1663,10 @@ udp_match(const struct sk_buff *skb,
 	  u_int16_t datalen,
 	  int *hotdrop)
 {
-	const struct udphdr *udp = hdr;
+	const struct udphdr *udp;
 	const struct ip6t_udp *udpinfo = matchinfo;
+	int udpoff;
+	u8 nexthdr = skb->nh.ipv6h->nexthdr;
 
 	if (offset == 0 && datalen < sizeof(struct udphdr)) {
 		/* We've been asked to examine this packet, and we
@@ -1653,6 +1676,23 @@ udp_match(const struct sk_buff *skb,
 		return 0;
 	}
 
+	udpoff = (u8*)(skb->nh.ipv6h + 1) - skb->data;
+	udpoff = ipv6_skip_exthdr(skb, udpoff, &nexthdr, skb->len - udpoff);
+	if (udpoff < 0 || udpoff > skb->len) {
+		duprintf("udp_match: cannot skip exthdr. Dropping.\n");
+		*hotdrop = 1;
+		return 0;
+	} else if (nexthdr == IPPROTO_FRAGMENT)
+		return 0;
+	else if (nexthdr != IPPROTO_UDP ||
+		 skb->len - udpoff < sizeof(struct udphdr)) {
+		duprintf("udp_match: cannot get UDP header. Dropping.\n");
+		*hotdrop = 1;
+		return 0;
+	}
+
+	udp = (struct udphdr *)(skb->data + udpoff);
+
 	/* Must not be a fragment. */
 	return !offset
 		&& port_match(udpinfo->spts[0], udpinfo->spts[1],
--- diff/net/ipv6/netfilter/ip6t_eui64.c	2004-02-18 08:54:13.000000000 +0000
+++ source/net/ipv6/netfilter/ip6t_eui64.c	2004-02-23 13:56:48.000000000 +0000
@@ -50,7 +50,7 @@ match(const struct sk_buff *skb,
 	 eui64[0] |= 0x02;
 
 	 i=0;
-	 while ((skb->nh.ipv6h->saddr.in6_u.u6_addr8[8+i] ==
+	 while ((skb->nh.ipv6h->saddr.s6_addr[8+i] ==
 			 eui64[i]) && (i<8)) i++;
 
 	 if ( i == 8 )
--- diff/net/ipv6/raw.c	2004-02-18 08:54:13.000000000 +0000
+++ source/net/ipv6/raw.c	2004-02-23 13:56:48.000000000 +0000
@@ -222,7 +222,7 @@ static int rawv6_bind(struct sock *sk, s
 		}
 		
 		/* ipv4 addr of the socket is invalid.  Only the
-		 * unpecified and mapped address have a v4 equivalent.
+		 * unspecified and mapped address have a v4 equivalent.
 		 */
 		v4addr = LOOPBACK4_IPV6;
 		if (!(addr_type & IPV6_ADDR_MULTICAST))	{
@@ -306,7 +306,7 @@ static inline int rawv6_rcv_skb(struct s
  *	This is next to useless... 
  *	if we demultiplex in network layer we don't need the extra call
  *	just to queue the skb... 
- *	maybe we could have the network decide uppon a hint if it 
+ *	maybe we could have the network decide upon a hint if it 
  *	should call raw_rcv for demultiplexing
  */
 int rawv6_rcv(struct sock *sk, struct sk_buff *skb)
@@ -627,7 +627,7 @@ static int rawv6_sendmsg(struct kiocb *i
 
 	if (ipv6_addr_any(daddr)) {
 		/* 
-		 * unspecfied destination address 
+		 * unspecified destination address 
 		 * treated as error... is this correct ?
 		 */
 		fl6_sock_release(flowlabel);
--- diff/net/ipv6/route.c	2004-02-09 10:36:12.000000000 +0000
+++ source/net/ipv6/route.c	2004-02-23 13:56:48.000000000 +0000
@@ -223,7 +223,7 @@ static struct rt6_info *rt6_best_dflt(st
 			match = sprt;
 			mpri = m;
 			if (m >= 12) {
-				/* we choose the lastest default router if it
+				/* we choose the last default router if it
 				 * is in (probably) reachable state.
 				 * If route changed, we should do pmtu
 				 * discovery. --yoshfuji
@@ -563,6 +563,7 @@ static struct dst_entry *ndisc_dst_gc_li
 
 struct dst_entry *ndisc_dst_alloc(struct net_device *dev, 
 				  struct neighbour *neigh,
+				  struct in6_addr *addr,
 				  int (*output)(struct sk_buff *))
 {
 	struct rt6_info *rt = ip6_dst_alloc();
@@ -574,11 +575,13 @@ struct dst_entry *ndisc_dst_alloc(struct
 		dev_hold(dev);
 	if (neigh)
 		neigh_hold(neigh);
+	else
+		neigh = ndisc_get_neigh(dev, addr);
 
 	rt->rt6i_dev	  = dev;
 	rt->rt6i_nexthop  = neigh;
 	rt->rt6i_expires  = 0;
-	rt->rt6i_flags    = RTF_LOCAL | RTF_NDISC;
+	rt->rt6i_flags    = RTF_LOCAL;
 	rt->rt6i_metric   = 0;
 	atomic_set(&rt->u.dst.__refcnt, 1);
 	rt->u.dst.metrics[RTAX_HOPLIMIT-1] = 255;
@@ -832,7 +835,7 @@ int ip6_route_add(struct in6_rtmsg *rtms
 		}
 	}
 
-	rt->rt6i_flags = rtmsg->rtmsg_flags & ~RTF_NDISC;
+	rt->rt6i_flags = rtmsg->rtmsg_flags;
 
 install_route:
 	if (rta && rta[RTA_METRICS-1]) {
@@ -1125,8 +1128,6 @@ static struct rt6_info * ip6_rt_copy(str
 {
 	struct rt6_info *rt = ip6_dst_alloc();
 
-	BUG_ON(ort->rt6i_flags & RTF_NDISC);
-
 	if (rt) {
 		rt->u.dst.input = ort->u.dst.input;
 		rt->u.dst.output = ort->u.dst.output;
@@ -2000,8 +2001,7 @@ void __init ip6_route_init(void)
 #endif
 }
 
-#ifdef MODULE
-void ip6_route_cleanup(void)
+void __exit ip6_route_cleanup(void)
 {
 #ifdef CONFIG_PROC_FS
 	proc_net_remove("ipv6_route");
@@ -2014,4 +2014,3 @@ void ip6_route_cleanup(void)
 	fib6_gc_cleanup();
 	kmem_cache_destroy(ip6_dst_ops.kmem_cachep);
 }
-#endif	/* MODULE */
--- diff/net/ipv6/sit.c	2004-02-09 10:36:12.000000000 +0000
+++ source/net/ipv6/sit.c	2004-02-23 13:56:48.000000000 +0000
@@ -187,7 +187,7 @@ static struct ip_tunnel * ipip6_tunnel_l
 	nt->parms = *parms;
 
 	if (register_netdevice(dev) < 0) {
-		kfree(dev);
+		free_netdev(dev);
 		goto failed;
 	}
 
@@ -805,13 +805,11 @@ static struct inet_protocol sit_protocol
 	.err_handler	=	ipip6_err,
 };
 
-#ifdef MODULE
-void sit_cleanup(void)
+void __exit sit_cleanup(void)
 {
 	inet_del_protocol(&sit_protocol, IPPROTO_IPV6);
 	unregister_netdev(ipip6_fb_tunnel_dev);
 }
-#endif
 
 int __init sit_init(void)
 {
@@ -840,6 +838,6 @@ int __init sit_init(void)
 	return err;
  fail:
 	inet_del_protocol(&sit_protocol, IPPROTO_IPV6);
-	kfree(ipip6_fb_tunnel_dev);
+	free_netdev(ipip6_fb_tunnel_dev);
 	goto out;
 }
--- diff/net/ipv6/sysctl_net_ipv6.c	2003-11-25 15:24:59.000000000 +0000
+++ source/net/ipv6/sysctl_net_ipv6.c	2004-02-23 13:56:48.000000000 +0000
@@ -79,7 +79,6 @@ ctl_table ipv6_table[] = {
 	{ .ctl_name = 0 }
 };
 
-#ifdef MODULE
 static struct ctl_table_header *ipv6_sysctl_header;
 
 static ctl_table ipv6_net_table[] = {
@@ -111,7 +110,6 @@ void ipv6_sysctl_unregister(void)
 {
 	unregister_sysctl_table(ipv6_sysctl_header);
 }
-#endif	/* MODULE */
 
 #endif /* CONFIG_SYSCTL */
 
--- diff/net/ipv6/udp.c	2004-02-18 08:54:13.000000000 +0000
+++ source/net/ipv6/udp.c	2004-02-23 13:56:48.000000000 +0000
@@ -591,12 +591,12 @@ static void udpv6_mcast_deliver(struct u
 			if (!buff)
 				continue;
 		}
-		if (sock_queue_rcv_skb(sk2, buff) >= 0)
+		if (udpv6_queue_rcv_skb(sk2, buff) >= 0)
 			buff = NULL;
 	}
 	if (buff)
 		kfree_skb(buff);
-	if (sock_queue_rcv_skb(sk, skb) < 0) {
+	if (udpv6_queue_rcv_skb(sk, skb) < 0) {
 free_skb:
 		kfree_skb(skb);
 	}
--- diff/net/ipv6/xfrm6_input.c	2003-08-20 14:16:34.000000000 +0100
+++ source/net/ipv6/xfrm6_input.c	2004-02-23 13:56:48.000000000 +0000
@@ -9,17 +9,20 @@
  *		IPv6 support
  */
 
+#include <linux/string.h>
 #include <net/inet_ecn.h>
 #include <net/ip.h>
 #include <net/ipv6.h>
 #include <net/xfrm.h>
 
-static inline void ipip6_ecn_decapsulate(struct ipv6hdr *iph,
-					 struct sk_buff *skb)
+static inline void ipip6_ecn_decapsulate(struct sk_buff *skb)
 {
-	if (INET_ECN_is_ce(ip6_get_dsfield(iph)) &&
-	    INET_ECN_is_not_ce(ip6_get_dsfield(skb->nh.ipv6h)))
-		IP6_ECN_set_ce(skb->nh.ipv6h);
+	struct ipv6hdr *outer_iph = skb->nh.ipv6h;
+	struct ipv6hdr *inner_iph = skb->h.ipv6h;
+
+	if (INET_ECN_is_ce(ip6_get_dsfield(outer_iph)) &&
+	    INET_ECN_is_not_ce(ip6_get_dsfield(inner_iph)))
+		IP6_ECN_set_ce(inner_iph);
 }
 
 int xfrm6_rcv(struct sk_buff **pskb, unsigned int *nhoffp)
@@ -77,10 +80,16 @@ int xfrm6_rcv(struct sk_buff **pskb, uns
 		if (x->props.mode) { /* XXX */
 			if (nexthdr != IPPROTO_IPV6)
 				goto drop;
-			skb->nh.raw = skb->data;
+			if (!pskb_may_pull(skb, sizeof(struct ipv6hdr)))
+				goto drop;
+			if (skb_cloned(skb) &&
+			    pskb_expand_head(skb, 0, 0, GFP_ATOMIC))
+				goto drop;
 			if (!(x->props.flags & XFRM_STATE_NOECN))
-				ipip6_ecn_decapsulate(iph, skb);
-			iph = skb->nh.ipv6h;
+				ipip6_ecn_decapsulate(skb);
+			skb->mac.raw = memmove(skb->data - skb->mac_len,
+					       skb->mac.raw, skb->mac_len);
+			skb->nh.raw = skb->data;
 			decaps = 1;
 			break;
 		}
--- diff/net/ipv6/xfrm6_policy.c	2003-11-25 15:24:59.000000000 +0000
+++ source/net/ipv6/xfrm6_policy.c	2004-02-23 13:56:48.000000000 +0000
@@ -55,13 +55,6 @@ static struct dst_entry *
 __xfrm6_find_bundle(struct flowi *fl, struct rtable *rt, struct xfrm_policy *policy)
 {
 	struct dst_entry *dst;
-	u32 ndisc_bit = 0;
-
-	if (fl->proto == IPPROTO_ICMPV6 &&
-	    (fl->fl_icmp_type == NDISC_NEIGHBOUR_ADVERTISEMENT ||
-	     fl->fl_icmp_type == NDISC_NEIGHBOUR_SOLICITATION  ||
-	     fl->fl_icmp_type == NDISC_ROUTER_SOLICITATION))
-		ndisc_bit = RTF_NDISC;
 
 	/* Still not clear if we should set fl->fl6_{src,dst}... */
 	read_lock_bh(&policy->lock);
@@ -69,9 +62,6 @@ __xfrm6_find_bundle(struct flowi *fl, st
 		struct xfrm_dst *xdst = (struct xfrm_dst*)dst;
 		struct in6_addr fl_dst_prefix, fl_src_prefix;
 
-		if ((xdst->u.rt6.rt6i_flags & RTF_NDISC) != ndisc_bit)
-			continue;
-
 		ipv6_addr_prefix(&fl_dst_prefix,
 				 &fl->fl6_dst,
 				 xdst->u.rt6.rt6i_dst.plen);
@@ -169,7 +159,7 @@ __xfrm6_bundle_create(struct xfrm_policy
 		dst_prev->output	= dst_prev->xfrm->type->output;
 		/* Sheit... I remember I did this right. Apparently,
 		 * it was magically lost, so this code needs audit */
-		x->u.rt6.rt6i_flags    = rt0->rt6i_flags&(RTCF_BROADCAST|RTCF_MULTICAST|RTCF_LOCAL|RTF_NDISC);
+		x->u.rt6.rt6i_flags    = rt0->rt6i_flags&(RTCF_BROADCAST|RTCF_MULTICAST|RTCF_LOCAL);
 		x->u.rt6.rt6i_metric   = rt0->rt6i_metric;
 		x->u.rt6.rt6i_node     = rt0->rt6i_node;
 		x->u.rt6.rt6i_gateway  = rt0->rt6i_gateway;
--- diff/net/irda/irlan/irlan_common.c	2003-09-30 15:46:21.000000000 +0100
+++ source/net/irda/irlan/irlan_common.c	2004-02-23 13:56:48.000000000 +0000
@@ -224,7 +224,7 @@ struct irlan_cb *irlan_open(__u32 saddr,
 		IRDA_DEBUG(2, "%s(), register_netdev() failed!\n", 
 			   __FUNCTION__ );
 		self = NULL;
-		kfree(dev);
+		free_netdev(dev);
 	} else {
 		rtnl_lock();
 		list_add_rcu(&self->dev_list, &irlans);
--- diff/net/irda/irlan/irlan_eth.c	2003-08-26 10:00:54.000000000 +0100
+++ source/net/irda/irlan/irlan_eth.c	2004-02-23 13:56:48.000000000 +0000
@@ -60,7 +60,7 @@ void irlan_eth_setup(struct net_device *
 	dev->hard_start_xmit    = irlan_eth_xmit; 
 	dev->get_stats	        = irlan_eth_get_stats;
 	dev->set_multicast_list = irlan_eth_set_multicast_list;
-	dev->destructor		= (void (*)(struct net_device *)) kfree;
+	dev->destructor		= free_netdev;
 
 	SET_MODULE_OWNER(dev);
 
--- diff/net/lapb/lapb_iface.c	2003-09-17 12:28:12.000000000 +0100
+++ source/net/lapb/lapb_iface.c	2004-02-23 13:56:48.000000000 +0000
@@ -81,18 +81,14 @@ static void __lapb_insert_cb(struct lapb
 	lapb_hold(lapb);
 }
 
-/*
- *	Convert the integer token used by the device driver into a pointer
- *	to a LAPB control structure.
- */
-static struct lapb_cb *__lapb_tokentostruct(void *token)
+static struct lapb_cb *__lapb_devtostruct(struct net_device *dev)
 {
 	struct list_head *entry;
 	struct lapb_cb *lapb, *use = NULL;
 
 	list_for_each(entry, &lapb_list) {
 		lapb = list_entry(entry, struct lapb_cb, node);
-		if (lapb->token == token) {
+		if (lapb->dev == dev) {
 			use = lapb;
 			break;
 		}
@@ -104,12 +100,12 @@ static struct lapb_cb *__lapb_tokentostr
 	return use;
 }
 
-static struct lapb_cb *lapb_tokentostruct(void *token)
+static struct lapb_cb *lapb_devtostruct(struct net_device *dev)
 {
 	struct lapb_cb *rc;
 
 	read_lock_bh(&lapb_list_lock);
-	rc = __lapb_tokentostruct(token);
+	rc = __lapb_devtostruct(dev);
 	read_unlock_bh(&lapb_list_lock);
 
 	return rc;
@@ -144,14 +140,14 @@ out:
 	return lapb;
 }
 
-int lapb_register(void *token, struct lapb_register_struct *callbacks)
+int lapb_register(struct net_device *dev, struct lapb_register_struct *callbacks)
 {
 	struct lapb_cb *lapb;
 	int rc = LAPB_BADTOKEN;
 
 	write_lock_bh(&lapb_list_lock);
 
-	lapb = __lapb_tokentostruct(token);
+	lapb = __lapb_devtostruct(dev);
 	if (lapb) {
 		lapb_put(lapb);
 		goto out;
@@ -162,7 +158,7 @@ int lapb_register(void *token, struct la
 	if (!lapb)
 		goto out;
 
-	lapb->token     = token;
+	lapb->dev       = dev;
 	lapb->callbacks = *callbacks;
 
 	__lapb_insert_cb(lapb);
@@ -175,13 +171,13 @@ out:
 	return rc;
 }
 
-int lapb_unregister(void *token)
+int lapb_unregister(struct net_device *dev)
 {
 	struct lapb_cb *lapb;
 	int rc = LAPB_BADTOKEN;
 
 	write_unlock_bh(&lapb_list_lock);
-	lapb = __lapb_tokentostruct(token);
+	lapb = __lapb_devtostruct(dev);
 	if (!lapb)
 		goto out;
 
@@ -199,10 +195,10 @@ out:
 	return rc;
 }
 
-int lapb_getparms(void *token, struct lapb_parms_struct *parms)
+int lapb_getparms(struct net_device *dev, struct lapb_parms_struct *parms)
 {
 	int rc = LAPB_BADTOKEN;
-	struct lapb_cb *lapb = lapb_tokentostruct(token);
+	struct lapb_cb *lapb = lapb_devtostruct(dev);
 
 	if (!lapb)
 		goto out;
@@ -231,10 +227,10 @@ out:
 	return rc;
 }
 
-int lapb_setparms(void *token, struct lapb_parms_struct *parms)
+int lapb_setparms(struct net_device *dev, struct lapb_parms_struct *parms)
 {
 	int rc = LAPB_BADTOKEN;
-	struct lapb_cb *lapb = lapb_tokentostruct(token);
+	struct lapb_cb *lapb = lapb_devtostruct(dev);
 
 	if (!lapb)
 		goto out;
@@ -264,9 +260,9 @@ out:
 	return rc;
 }
 
-int lapb_connect_request(void *token)
+int lapb_connect_request(struct net_device *dev)
 {
-	struct lapb_cb *lapb = lapb_tokentostruct(token);
+	struct lapb_cb *lapb = lapb_devtostruct(dev);
 	int rc = LAPB_BADTOKEN;
 
 	if (!lapb)
@@ -283,7 +279,7 @@ int lapb_connect_request(void *token)
 	lapb_establish_data_link(lapb);
 
 #if LAPB_DEBUG > 0
-	printk(KERN_DEBUG "lapb: (%p) S0 -> S1\n", lapb->token);
+	printk(KERN_DEBUG "lapb: (%p) S0 -> S1\n", lapb->dev);
 #endif
 	lapb->state = LAPB_STATE_1;
 
@@ -294,9 +290,9 @@ out:
 	return rc;
 }
 
-int lapb_disconnect_request(void *token)
+int lapb_disconnect_request(struct net_device *dev)
 {
-	struct lapb_cb *lapb = lapb_tokentostruct(token);
+	struct lapb_cb *lapb = lapb_devtostruct(dev);
 	int rc = LAPB_BADTOKEN;
 
 	if (!lapb)
@@ -309,10 +305,10 @@ int lapb_disconnect_request(void *token)
 
 		case LAPB_STATE_1:
 #if LAPB_DEBUG > 1
-			printk(KERN_DEBUG "lapb: (%p) S1 TX DISC(1)\n", lapb->token);
+			printk(KERN_DEBUG "lapb: (%p) S1 TX DISC(1)\n", lapb->dev);
 #endif
 #if LAPB_DEBUG > 0
-			printk(KERN_DEBUG "lapb: (%p) S1 -> S0\n", lapb->token);
+			printk(KERN_DEBUG "lapb: (%p) S1 -> S0\n", lapb->dev);
 #endif
 			lapb_send_control(lapb, LAPB_DISC, LAPB_POLLON, LAPB_COMMAND);
 			lapb->state = LAPB_STATE_0;
@@ -333,10 +329,10 @@ int lapb_disconnect_request(void *token)
 	lapb->state = LAPB_STATE_2;
 
 #if LAPB_DEBUG > 1
-	printk(KERN_DEBUG "lapb: (%p) S3 DISC(1)\n", lapb->token);
+	printk(KERN_DEBUG "lapb: (%p) S3 DISC(1)\n", lapb->dev);
 #endif
 #if LAPB_DEBUG > 0
-	printk(KERN_DEBUG "lapb: (%p) S3 -> S2\n", lapb->token);
+	printk(KERN_DEBUG "lapb: (%p) S3 -> S2\n", lapb->dev);
 #endif
 
 	rc = LAPB_OK;
@@ -346,9 +342,9 @@ out:
 	return rc;
 }
 
-int lapb_data_request(void *token, struct sk_buff *skb)
+int lapb_data_request(struct net_device *dev, struct sk_buff *skb)
 {
-	struct lapb_cb *lapb = lapb_tokentostruct(token);
+	struct lapb_cb *lapb = lapb_devtostruct(dev);
 	int rc = LAPB_BADTOKEN;
 
 	if (!lapb)
@@ -367,9 +363,9 @@ out:
 	return rc;
 }
 
-int lapb_data_received(void *token, struct sk_buff *skb)
+int lapb_data_received(struct net_device *dev, struct sk_buff *skb)
 {
-	struct lapb_cb *lapb = lapb_tokentostruct(token);
+	struct lapb_cb *lapb = lapb_devtostruct(dev);
 	int rc = LAPB_BADTOKEN;
 
 	if (lapb) {
@@ -384,31 +380,31 @@ int lapb_data_received(void *token, stru
 void lapb_connect_confirmation(struct lapb_cb *lapb, int reason)
 {
 	if (lapb->callbacks.connect_confirmation)
-		lapb->callbacks.connect_confirmation(lapb->token, reason);
+		lapb->callbacks.connect_confirmation(lapb->dev, reason);
 }
 
 void lapb_connect_indication(struct lapb_cb *lapb, int reason)
 {
 	if (lapb->callbacks.connect_indication)
-		lapb->callbacks.connect_indication(lapb->token, reason);
+		lapb->callbacks.connect_indication(lapb->dev, reason);
 }
 
 void lapb_disconnect_confirmation(struct lapb_cb *lapb, int reason)
 {
 	if (lapb->callbacks.disconnect_confirmation)
-		lapb->callbacks.disconnect_confirmation(lapb->token, reason);
+		lapb->callbacks.disconnect_confirmation(lapb->dev, reason);
 }
 
 void lapb_disconnect_indication(struct lapb_cb *lapb, int reason)
 {
 	if (lapb->callbacks.disconnect_indication)
-		lapb->callbacks.disconnect_indication(lapb->token, reason);
+		lapb->callbacks.disconnect_indication(lapb->dev, reason);
 }
 
 int lapb_data_indication(struct lapb_cb *lapb, struct sk_buff *skb)
 {
 	if (lapb->callbacks.data_indication)
-		return lapb->callbacks.data_indication(lapb->token, skb);
+		return lapb->callbacks.data_indication(lapb->dev, skb);
 
 	kfree_skb(skb);
 	return NET_RX_CN_HIGH; /* For now; must be != NET_RX_DROP */ 
@@ -419,7 +415,7 @@ int lapb_data_transmit(struct lapb_cb *l
 	int used = 0;
 
 	if (lapb->callbacks.data_transmit) {
-		lapb->callbacks.data_transmit(lapb->token, skb);
+		lapb->callbacks.data_transmit(lapb->dev, skb);
 		used = 1;
 	}
 
--- diff/net/lapb/lapb_in.c	2003-10-09 09:47:34.000000000 +0100
+++ source/net/lapb/lapb_in.c	2004-02-23 13:56:48.000000000 +0000
@@ -47,23 +47,23 @@ static void lapb_state0_machine(struct l
 		case LAPB_SABM:
 #if LAPB_DEBUG > 1
 			printk(KERN_DEBUG "lapb: (%p) S0 RX SABM(%d)\n",
-			       lapb->token, frame->pf);
+			       lapb->dev, frame->pf);
 #endif
 			if (lapb->mode & LAPB_EXTENDED) {
 #if LAPB_DEBUG > 1
 				printk(KERN_DEBUG "lapb: (%p) S0 TX DM(%d)\n",
-				       lapb->token, frame->pf);
+				       lapb->dev, frame->pf);
 #endif
 				lapb_send_control(lapb, LAPB_DM, frame->pf,
 						  LAPB_RESPONSE);
 			} else {
 #if LAPB_DEBUG > 1
 				printk(KERN_DEBUG "lapb: (%p) S0 TX UA(%d)\n",
-				       lapb->token, frame->pf);
+				       lapb->dev, frame->pf);
 #endif
 #if LAPB_DEBUG > 0
 				printk(KERN_DEBUG "lapb: (%p) S0 -> S3\n",
-				       lapb->token);
+				       lapb->dev);
 #endif
 				lapb_send_control(lapb, LAPB_UA, frame->pf,
 						  LAPB_RESPONSE);
@@ -82,16 +82,16 @@ static void lapb_state0_machine(struct l
 		case LAPB_SABME:
 #if LAPB_DEBUG > 1
 			printk(KERN_DEBUG "lapb: (%p) S0 RX SABME(%d)\n",
-			       lapb->token, frame->pf);
+			       lapb->dev, frame->pf);
 #endif
 			if (lapb->mode & LAPB_EXTENDED) {
 #if LAPB_DEBUG > 1
 				printk(KERN_DEBUG "lapb: (%p) S0 TX UA(%d)\n",
-				       lapb->token, frame->pf);
+				       lapb->dev, frame->pf);
 #endif
 #if LAPB_DEBUG > 0
 				printk(KERN_DEBUG "lapb: (%p) S0 -> S3\n",
-				       lapb->token);
+				       lapb->dev);
 #endif
 				lapb_send_control(lapb, LAPB_UA, frame->pf,
 						  LAPB_RESPONSE);
@@ -107,7 +107,7 @@ static void lapb_state0_machine(struct l
 			} else {
 #if LAPB_DEBUG > 1
 				printk(KERN_DEBUG "lapb: (%p) S0 TX DM(%d)\n",
-				       lapb->token, frame->pf);
+				       lapb->dev, frame->pf);
 #endif
 				lapb_send_control(lapb, LAPB_DM, frame->pf,
 						  LAPB_RESPONSE);
@@ -117,9 +117,9 @@ static void lapb_state0_machine(struct l
 		case LAPB_DISC:
 #if LAPB_DEBUG > 1
 			printk(KERN_DEBUG "lapb: (%p) S0 RX DISC(%d)\n",
-			       lapb->token, frame->pf);
+			       lapb->dev, frame->pf);
 			printk(KERN_DEBUG "lapb: (%p) S0 TX UA(%d)\n",
-			       lapb->token, frame->pf);
+			       lapb->dev, frame->pf);
 #endif
 			lapb_send_control(lapb, LAPB_UA, frame->pf,
 					  LAPB_RESPONSE);
@@ -143,19 +143,19 @@ static void lapb_state1_machine(struct l
 		case LAPB_SABM:
 #if LAPB_DEBUG > 1
 			printk(KERN_DEBUG "lapb: (%p) S1 RX SABM(%d)\n",
-			       lapb->token, frame->pf);
+			       lapb->dev, frame->pf);
 #endif
 			if (lapb->mode & LAPB_EXTENDED) {
 #if LAPB_DEBUG > 1
 				printk(KERN_DEBUG "lapb: (%p) S1 TX DM(%d)\n",
-				       lapb->token, frame->pf);
+				       lapb->dev, frame->pf);
 #endif
 				lapb_send_control(lapb, LAPB_DM, frame->pf,
 						  LAPB_RESPONSE);
 			} else {
 #if LAPB_DEBUG > 1
 				printk(KERN_DEBUG "lapb: (%p) S1 TX UA(%d)\n",
-				       lapb->token, frame->pf);
+				       lapb->dev, frame->pf);
 #endif
 				lapb_send_control(lapb, LAPB_UA, frame->pf,
 						  LAPB_RESPONSE);
@@ -165,19 +165,19 @@ static void lapb_state1_machine(struct l
 		case LAPB_SABME:
 #if LAPB_DEBUG > 1
 			printk(KERN_DEBUG "lapb: (%p) S1 RX SABME(%d)\n",
-			       lapb->token, frame->pf);
+			       lapb->dev, frame->pf);
 #endif
 			if (lapb->mode & LAPB_EXTENDED) {
 #if LAPB_DEBUG > 1
 				printk(KERN_DEBUG "lapb: (%p) S1 TX UA(%d)\n",
-				       lapb->token, frame->pf);
+				       lapb->dev, frame->pf);
 #endif
 				lapb_send_control(lapb, LAPB_UA, frame->pf,
 						  LAPB_RESPONSE);
 			} else {
 #if LAPB_DEBUG > 1
 				printk(KERN_DEBUG "lapb: (%p) S1 TX DM(%d)\n",
-				       lapb->token, frame->pf);
+				       lapb->dev, frame->pf);
 #endif
 				lapb_send_control(lapb, LAPB_DM, frame->pf,
 						  LAPB_RESPONSE);
@@ -187,9 +187,9 @@ static void lapb_state1_machine(struct l
 		case LAPB_DISC:
 #if LAPB_DEBUG > 1
 			printk(KERN_DEBUG "lapb: (%p) S1 RX DISC(%d)\n",
-			       lapb->token, frame->pf);
+			       lapb->dev, frame->pf);
 			printk(KERN_DEBUG "lapb: (%p) S1 TX DM(%d)\n",
-			       lapb->token, frame->pf);
+			       lapb->dev, frame->pf);
 #endif
 			lapb_send_control(lapb, LAPB_DM, frame->pf,
 					  LAPB_RESPONSE);
@@ -198,12 +198,12 @@ static void lapb_state1_machine(struct l
 		case LAPB_UA:
 #if LAPB_DEBUG > 1
 			printk(KERN_DEBUG "lapb: (%p) S1 RX UA(%d)\n",
-			       lapb->token, frame->pf);
+			       lapb->dev, frame->pf);
 #endif
 			if (frame->pf) {
 #if LAPB_DEBUG > 0
 				printk(KERN_DEBUG "lapb: (%p) S1 -> S3\n",
-				       lapb->token);
+				       lapb->dev);
 #endif
 				lapb_stop_t1timer(lapb);
 				lapb_stop_t2timer(lapb);
@@ -220,12 +220,12 @@ static void lapb_state1_machine(struct l
 		case LAPB_DM:
 #if LAPB_DEBUG > 1
 			printk(KERN_DEBUG "lapb: (%p) S1 RX DM(%d)\n",
-			       lapb->token, frame->pf);
+			       lapb->dev, frame->pf);
 #endif
 			if (frame->pf) {
 #if LAPB_DEBUG > 0
 				printk(KERN_DEBUG "lapb: (%p) S1 -> S0\n",
-				       lapb->token);
+				       lapb->dev);
 #endif
 				lapb_clear_queues(lapb);
 				lapb->state = LAPB_STATE_0;
@@ -251,9 +251,9 @@ static void lapb_state2_machine(struct l
 		case LAPB_SABME:
 #if LAPB_DEBUG > 1
 			printk(KERN_DEBUG "lapb: (%p) S2 RX {SABM,SABME}(%d)\n",
-			       lapb->token, frame->pf);
+			       lapb->dev, frame->pf);
 			printk(KERN_DEBUG "lapb: (%p) S2 TX DM(%d)\n",
-			       lapb->token, frame->pf);
+			       lapb->dev, frame->pf);
 #endif
 			lapb_send_control(lapb, LAPB_DM, frame->pf,
 					  LAPB_RESPONSE);
@@ -262,9 +262,9 @@ static void lapb_state2_machine(struct l
 		case LAPB_DISC:
 #if LAPB_DEBUG > 1
 			printk(KERN_DEBUG "lapb: (%p) S2 RX DISC(%d)\n",
-			       lapb->token, frame->pf);
+			       lapb->dev, frame->pf);
 			printk(KERN_DEBUG "lapb: (%p) S2 TX UA(%d)\n",
-			       lapb->token, frame->pf);
+			       lapb->dev, frame->pf);
 #endif
 			lapb_send_control(lapb, LAPB_UA, frame->pf,
 					  LAPB_RESPONSE);
@@ -273,12 +273,12 @@ static void lapb_state2_machine(struct l
 		case LAPB_UA:
 #if LAPB_DEBUG > 1
 			printk(KERN_DEBUG "lapb: (%p) S2 RX UA(%d)\n",
-			       lapb->token, frame->pf);
+			       lapb->dev, frame->pf);
 #endif
 			if (frame->pf) {
 #if LAPB_DEBUG > 0
 				printk(KERN_DEBUG "lapb: (%p) S2 -> S0\n",
-				       lapb->token);
+				       lapb->dev);
 #endif
 				lapb->state = LAPB_STATE_0;
 				lapb_start_t1timer(lapb);
@@ -290,12 +290,12 @@ static void lapb_state2_machine(struct l
 		case LAPB_DM:
 #if LAPB_DEBUG > 1
 			printk(KERN_DEBUG "lapb: (%p) S2 RX DM(%d)\n",
-			       lapb->token, frame->pf);
+			       lapb->dev, frame->pf);
 #endif
 			if (frame->pf) {
 #if LAPB_DEBUG > 0
 				printk(KERN_DEBUG "lapb: (%p) S2 -> S0\n",
-				       lapb->token);
+				       lapb->dev);
 #endif
 				lapb->state = LAPB_STATE_0;
 				lapb_start_t1timer(lapb);
@@ -311,9 +311,9 @@ static void lapb_state2_machine(struct l
 		case LAPB_RR:
 #if LAPB_DEBUG > 1
 			printk(KERN_DEBUG "lapb: (%p) S2 RX {I,REJ,RNR,RR}"
-			       "(%d)\n", lapb->token, frame->pf);
+			       "(%d)\n", lapb->dev, frame->pf);
 			printk(KERN_DEBUG "lapb: (%p) S2 RX DM(%d)\n",
-			       lapb->token, frame->pf);
+			       lapb->dev, frame->pf);
 #endif
 			if (frame->pf)
 				lapb_send_control(lapb, LAPB_DM, frame->pf,
@@ -339,19 +339,19 @@ static void lapb_state3_machine(struct l
 		case LAPB_SABM:
 #if LAPB_DEBUG > 1
 			printk(KERN_DEBUG "lapb: (%p) S3 RX SABM(%d)\n",
-			       lapb->token, frame->pf);
+			       lapb->dev, frame->pf);
 #endif
 			if (lapb->mode & LAPB_EXTENDED) {
 #if LAPB_DEBUG > 1
 				printk(KERN_DEBUG "lapb: (%p) S3 TX DM(%d)\n",
-				       lapb->token, frame->pf);
+				       lapb->dev, frame->pf);
 #endif
 				lapb_send_control(lapb, LAPB_DM, frame->pf,
 						  LAPB_RESPONSE);
 			} else {
 #if LAPB_DEBUG > 1
 				printk(KERN_DEBUG "lapb: (%p) S3 TX UA(%d)\n",
-				       lapb->token, frame->pf);
+				       lapb->dev, frame->pf);
 #endif
 				lapb_send_control(lapb, LAPB_UA, frame->pf,
 						  LAPB_RESPONSE);
@@ -369,12 +369,12 @@ static void lapb_state3_machine(struct l
 		case LAPB_SABME:
 #if LAPB_DEBUG > 1
 			printk(KERN_DEBUG "lapb: (%p) S3 RX SABME(%d)\n",
-			       lapb->token, frame->pf);
+			       lapb->dev, frame->pf);
 #endif
 			if (lapb->mode & LAPB_EXTENDED) {
 #if LAPB_DEBUG > 1
 				printk(KERN_DEBUG "lapb: (%p) S3 TX UA(%d)\n",
-				       lapb->token, frame->pf);
+				       lapb->dev, frame->pf);
 #endif
 				lapb_send_control(lapb, LAPB_UA, frame->pf,
 						  LAPB_RESPONSE);
@@ -389,7 +389,7 @@ static void lapb_state3_machine(struct l
 			} else {
 #if LAPB_DEBUG > 1
 				printk(KERN_DEBUG "lapb: (%p) S3 TX DM(%d)\n",
-				       lapb->token, frame->pf);
+				       lapb->dev, frame->pf);
 #endif
 				lapb_send_control(lapb, LAPB_DM, frame->pf,
 						  LAPB_RESPONSE);
@@ -399,11 +399,11 @@ static void lapb_state3_machine(struct l
 		case LAPB_DISC:
 #if LAPB_DEBUG > 1
 			printk(KERN_DEBUG "lapb: (%p) S3 RX DISC(%d)\n",
-			       lapb->token, frame->pf);
+			       lapb->dev, frame->pf);
 #endif
 #if LAPB_DEBUG > 0
 			printk(KERN_DEBUG "lapb: (%p) S3 -> S0\n",
-			       lapb->token);
+			       lapb->dev);
 #endif
 			lapb_clear_queues(lapb);
 			lapb_send_control(lapb, LAPB_UA, frame->pf,
@@ -417,11 +417,11 @@ static void lapb_state3_machine(struct l
 		case LAPB_DM:
 #if LAPB_DEBUG > 1
 			printk(KERN_DEBUG "lapb: (%p) S3 RX DM(%d)\n",
-			       lapb->token, frame->pf);
+			       lapb->dev, frame->pf);
 #endif
 #if LAPB_DEBUG > 0
 			printk(KERN_DEBUG "lapb: (%p) S3 -> S0\n",
-			       lapb->token);
+			       lapb->dev);
 #endif
 			lapb_clear_queues(lapb);
 			lapb->state = LAPB_STATE_0;
@@ -433,7 +433,7 @@ static void lapb_state3_machine(struct l
 		case LAPB_RNR:
 #if LAPB_DEBUG > 1
 			printk(KERN_DEBUG "lapb: (%p) S3 RX RNR(%d) R%d\n",
-			       lapb->token, frame->pf, frame->nr);
+			       lapb->dev, frame->pf, frame->nr);
 #endif
 			lapb->condition |= LAPB_PEER_RX_BUSY_CONDITION;
 			lapb_check_need_response(lapb, frame->cr, frame->pf);
@@ -445,7 +445,7 @@ static void lapb_state3_machine(struct l
 				lapb_transmit_frmr(lapb);
 #if LAPB_DEBUG > 0
 				printk(KERN_DEBUG "lapb: (%p) S3 -> S4\n",
-				       lapb->token);
+				       lapb->dev);
 #endif
 				lapb_start_t1timer(lapb);
 				lapb_stop_t2timer(lapb);
@@ -457,7 +457,7 @@ static void lapb_state3_machine(struct l
 		case LAPB_RR:
 #if LAPB_DEBUG > 1
 			printk(KERN_DEBUG "lapb: (%p) S3 RX RR(%d) R%d\n",
-			       lapb->token, frame->pf, frame->nr);
+			       lapb->dev, frame->pf, frame->nr);
 #endif
 			lapb->condition &= ~LAPB_PEER_RX_BUSY_CONDITION;
 			lapb_check_need_response(lapb, frame->cr, frame->pf);
@@ -469,7 +469,7 @@ static void lapb_state3_machine(struct l
 				lapb_transmit_frmr(lapb);
 #if LAPB_DEBUG > 0
 				printk(KERN_DEBUG "lapb: (%p) S3 -> S4\n",
-				       lapb->token);
+				       lapb->dev);
 #endif
 				lapb_start_t1timer(lapb);
 				lapb_stop_t2timer(lapb);
@@ -481,7 +481,7 @@ static void lapb_state3_machine(struct l
 		case LAPB_REJ:
 #if LAPB_DEBUG > 1
 			printk(KERN_DEBUG "lapb: (%p) S3 RX REJ(%d) R%d\n",
-			       lapb->token, frame->pf, frame->nr);
+			       lapb->dev, frame->pf, frame->nr);
 #endif
 			lapb->condition &= ~LAPB_PEER_RX_BUSY_CONDITION;
 			lapb_check_need_response(lapb, frame->cr, frame->pf);
@@ -496,7 +496,7 @@ static void lapb_state3_machine(struct l
 				lapb_transmit_frmr(lapb);
 #if LAPB_DEBUG > 0
 				printk(KERN_DEBUG "lapb: (%p) S3 -> S4\n",
-				       lapb->token);
+				       lapb->dev);
 #endif
 				lapb_start_t1timer(lapb);
 				lapb_stop_t2timer(lapb);
@@ -508,7 +508,7 @@ static void lapb_state3_machine(struct l
 		case LAPB_I:
 #if LAPB_DEBUG > 1
 			printk(KERN_DEBUG "lapb: (%p) S3 RX I(%d) S%d R%d\n",
-			       lapb->token, frame->pf, frame->ns, frame->nr);
+			       lapb->dev, frame->pf, frame->ns, frame->nr);
 #endif
 			if (!lapb_validate_nr(lapb, frame->nr)) {
 				lapb->frmr_data = *frame;
@@ -516,7 +516,7 @@ static void lapb_state3_machine(struct l
 				lapb_transmit_frmr(lapb);
 #if LAPB_DEBUG > 0
 				printk(KERN_DEBUG "lapb: (%p) S3 -> S4\n",
-				       lapb->token);
+				       lapb->dev);
 #endif
 				lapb_start_t1timer(lapb);
 				lapb_stop_t2timer(lapb);
@@ -564,7 +564,7 @@ static void lapb_state3_machine(struct l
 #if LAPB_DEBUG > 1
 					printk(KERN_DEBUG
 					       "lapb: (%p) S3 TX REJ(%d) R%d\n",
-					       lapb->token, frame->pf, lapb->vr);
+					       lapb->dev, frame->pf, lapb->vr);
 #endif
 					lapb->condition |= LAPB_REJECT_CONDITION;
 					lapb_send_control(lapb, LAPB_REJ,
@@ -578,14 +578,14 @@ static void lapb_state3_machine(struct l
 		case LAPB_FRMR:
 #if LAPB_DEBUG > 1
 			printk(KERN_DEBUG "lapb: (%p) S3 RX FRMR(%d) %02X "
-			       "%02X %02X %02X %02X\n", lapb->token, frame->pf,
+			       "%02X %02X %02X %02X\n", lapb->dev, frame->pf,
 			       skb->data[0], skb->data[1], skb->data[2],
 			       skb->data[3], skb->data[4]);
 #endif
 			lapb_establish_data_link(lapb);
 #if LAPB_DEBUG > 0
 			printk(KERN_DEBUG "lapb: (%p) S3 -> S1\n",
-			       lapb->token);
+			       lapb->dev);
 #endif
 			lapb_requeue_frames(lapb);
 			lapb->state = LAPB_STATE_1;
@@ -594,13 +594,13 @@ static void lapb_state3_machine(struct l
 		case LAPB_ILLEGAL:
 #if LAPB_DEBUG > 1
 			printk(KERN_DEBUG "lapb: (%p) S3 RX ILLEGAL(%d)\n",
-			       lapb->token, frame->pf);
+			       lapb->dev, frame->pf);
 #endif
 			lapb->frmr_data = *frame;
 			lapb->frmr_type = LAPB_FRMR_W;
 			lapb_transmit_frmr(lapb);
 #if LAPB_DEBUG > 0
-			printk(KERN_DEBUG "lapb: (%p) S3 -> S4\n", lapb->token);
+			printk(KERN_DEBUG "lapb: (%p) S3 -> S4\n", lapb->dev);
 #endif
 			lapb_start_t1timer(lapb);
 			lapb_stop_t2timer(lapb);
@@ -624,23 +624,23 @@ static void lapb_state4_machine(struct l
 		case LAPB_SABM:
 #if LAPB_DEBUG > 1
 			printk(KERN_DEBUG "lapb: (%p) S4 RX SABM(%d)\n",
-			       lapb->token, frame->pf);
+			       lapb->dev, frame->pf);
 #endif
 			if (lapb->mode & LAPB_EXTENDED) {
 #if LAPB_DEBUG > 1
 				printk(KERN_DEBUG "lapb: (%p) S4 TX DM(%d)\n",
-				       lapb->token, frame->pf);
+				       lapb->dev, frame->pf);
 #endif
 				lapb_send_control(lapb, LAPB_DM, frame->pf,
 						  LAPB_RESPONSE);
 			} else {
 #if LAPB_DEBUG > 1
 				printk(KERN_DEBUG "lapb: (%p) S4 TX UA(%d)\n",
-				       lapb->token, frame->pf);
+				       lapb->dev, frame->pf);
 #endif
 #if LAPB_DEBUG > 0
 				printk(KERN_DEBUG "lapb: (%p) S4 -> S3\n",
-				       lapb->token);
+				       lapb->dev);
 #endif
 				lapb_send_control(lapb, LAPB_UA, frame->pf,
 						  LAPB_RESPONSE);
@@ -659,16 +659,16 @@ static void lapb_state4_machine(struct l
 		case LAPB_SABME:
 #if LAPB_DEBUG > 1
 			printk(KERN_DEBUG "lapb: (%p) S4 RX SABME(%d)\n",
-			       lapb->token, frame->pf);
+			       lapb->dev, frame->pf);
 #endif
 			if (lapb->mode & LAPB_EXTENDED) {
 #if LAPB_DEBUG > 1
 				printk(KERN_DEBUG "lapb: (%p) S4 TX UA(%d)\n",
-				       lapb->token, frame->pf);
+				       lapb->dev, frame->pf);
 #endif
 #if LAPB_DEBUG > 0
 				printk(KERN_DEBUG "lapb: (%p) S4 -> S3\n",
-				       lapb->token);
+				       lapb->dev);
 #endif
 				lapb_send_control(lapb, LAPB_UA, frame->pf,
 						  LAPB_RESPONSE);
@@ -684,7 +684,7 @@ static void lapb_state4_machine(struct l
 			} else {
 #if LAPB_DEBUG > 1
 				printk(KERN_DEBUG "lapb: (%p) S4 TX DM(%d)\n",
-				       lapb->token, frame->pf);
+				       lapb->dev, frame->pf);
 #endif
 				lapb_send_control(lapb, LAPB_DM, frame->pf,
 						  LAPB_RESPONSE);
--- diff/net/lapb/lapb_out.c	2002-10-16 04:28:27.000000000 +0100
+++ source/net/lapb/lapb_out.c	2004-02-23 13:56:48.000000000 +0000
@@ -63,7 +63,7 @@ static void lapb_send_iframe(struct lapb
 
 #if LAPB_DEBUG > 1
 	printk(KERN_DEBUG "lapb: (%p) S%d TX I(%d) S%d R%d\n",
-	       lapb->token, lapb->state, poll_bit, lapb->vs, lapb->vr);
+	       lapb->dev, lapb->state, poll_bit, lapb->vs, lapb->vr);
 #endif
 
 	lapb_transmit_buffer(lapb, skb, LAPB_COMMAND);	
@@ -151,7 +151,7 @@ void lapb_transmit_buffer(struct lapb_cb
 
 #if LAPB_DEBUG > 2
 	printk(KERN_DEBUG "lapb: (%p) S%d TX %02X %02X %02X\n",
-	       lapb->token, lapb->state,
+	       lapb->dev, lapb->state,
 	       skb->data[0], skb->data[1], skb->data[2]);
 #endif
 
@@ -167,13 +167,13 @@ void lapb_establish_data_link(struct lap
 	if (lapb->mode & LAPB_EXTENDED) {
 #if LAPB_DEBUG > 1
 		printk(KERN_DEBUG "lapb: (%p) S%d TX SABME(1)\n",
-		       lapb->token, lapb->state);
+		       lapb->dev, lapb->state);
 #endif
 		lapb_send_control(lapb, LAPB_SABME, LAPB_POLLON, LAPB_COMMAND);
 	} else {
 #if LAPB_DEBUG > 1
 		printk(KERN_DEBUG "lapb: (%p) S%d TX SABM(1)\n",
-		       lapb->token, lapb->state);
+		       lapb->dev, lapb->state);
 #endif
 		lapb_send_control(lapb, LAPB_SABM, LAPB_POLLON, LAPB_COMMAND);
 	}
@@ -186,7 +186,7 @@ void lapb_enquiry_response(struct lapb_c
 {
 #if LAPB_DEBUG > 1
 	printk(KERN_DEBUG "lapb: (%p) S%d TX RR(1) R%d\n",
-	       lapb->token, lapb->state, lapb->vr);
+	       lapb->dev, lapb->state, lapb->vr);
 #endif
 
 	lapb_send_control(lapb, LAPB_RR, LAPB_POLLON, LAPB_RESPONSE);
@@ -198,7 +198,7 @@ void lapb_timeout_response(struct lapb_c
 {
 #if LAPB_DEBUG > 1
 	printk(KERN_DEBUG "lapb: (%p) S%d TX RR(0) R%d\n",
-	       lapb->token, lapb->state, lapb->vr);
+	       lapb->dev, lapb->state, lapb->vr);
 #endif
 	lapb_send_control(lapb, LAPB_RR, LAPB_POLLOFF, LAPB_RESPONSE);
 
--- diff/net/lapb/lapb_subr.c	2003-10-09 09:47:34.000000000 +0100
+++ source/net/lapb/lapb_subr.c	2004-02-23 13:56:48.000000000 +0000
@@ -114,7 +114,7 @@ int lapb_decode(struct lapb_cb *lapb, st
 
 #if LAPB_DEBUG > 2
 	printk(KERN_DEBUG "lapb: (%p) S%d RX %02X %02X %02X\n",
-	       lapb->token, lapb->state,
+	       lapb->dev, lapb->state,
 	       skb->data[0], skb->data[1], skb->data[2]);
 #endif
 
@@ -287,7 +287,7 @@ void lapb_transmit_frmr(struct lapb_cb *
 
 #if LAPB_DEBUG > 1
 	printk(KERN_DEBUG "lapb: (%p) S%d TX FRMR %02X %02X %02X %02X %02X\n",
-	       lapb->token, lapb->state,
+	       lapb->dev, lapb->state,
 	       skb->data[1], skb->data[2], skb->data[3],
 	       skb->data[4], skb->data[5]);
 #endif
@@ -304,7 +304,7 @@ void lapb_transmit_frmr(struct lapb_cb *
 
 #if LAPB_DEBUG > 1
 	printk(KERN_DEBUG "lapb: (%p) S%d TX FRMR %02X %02X %02X\n",
-	       lapb->token, lapb->state, skb->data[1],
+	       lapb->dev, lapb->state, skb->data[1],
 	       skb->data[2], skb->data[3]);
 #endif
 	}
--- diff/net/lapb/lapb_timer.c	2002-10-16 04:27:21.000000000 +0100
+++ source/net/lapb/lapb_timer.c	2004-02-23 13:56:48.000000000 +0000
@@ -107,19 +107,19 @@ static void lapb_t1timer_expiry(unsigned
 				lapb->state = LAPB_STATE_0;
 				lapb_disconnect_indication(lapb, LAPB_TIMEDOUT);
 #if LAPB_DEBUG > 0
-				printk(KERN_DEBUG "lapb: (%p) S1 -> S0\n", lapb->token);
+				printk(KERN_DEBUG "lapb: (%p) S1 -> S0\n", lapb->dev);
 #endif
 				return;
 			} else {
 				lapb->n2count++;
 				if (lapb->mode & LAPB_EXTENDED) {
 #if LAPB_DEBUG > 1
-					printk(KERN_DEBUG "lapb: (%p) S1 TX SABME(1)\n", lapb->token);
+					printk(KERN_DEBUG "lapb: (%p) S1 TX SABME(1)\n", lapb->dev);
 #endif
 					lapb_send_control(lapb, LAPB_SABME, LAPB_POLLON, LAPB_COMMAND);
 				} else {
 #if LAPB_DEBUG > 1
-					printk(KERN_DEBUG "lapb: (%p) S1 TX SABM(1)\n", lapb->token);
+					printk(KERN_DEBUG "lapb: (%p) S1 TX SABM(1)\n", lapb->dev);
 #endif
 					lapb_send_control(lapb, LAPB_SABM, LAPB_POLLON, LAPB_COMMAND);
 				}
@@ -135,13 +135,13 @@ static void lapb_t1timer_expiry(unsigned
 				lapb->state = LAPB_STATE_0;
 				lapb_disconnect_confirmation(lapb, LAPB_TIMEDOUT);
 #if LAPB_DEBUG > 0
-				printk(KERN_DEBUG "lapb: (%p) S2 -> S0\n", lapb->token);
+				printk(KERN_DEBUG "lapb: (%p) S2 -> S0\n", lapb->dev);
 #endif
 				return;
 			} else {
 				lapb->n2count++;
 #if LAPB_DEBUG > 1
-				printk(KERN_DEBUG "lapb: (%p) S2 TX DISC(1)\n", lapb->token);
+				printk(KERN_DEBUG "lapb: (%p) S2 TX DISC(1)\n", lapb->dev);
 #endif
 				lapb_send_control(lapb, LAPB_DISC, LAPB_POLLON, LAPB_COMMAND);
 			}
@@ -157,7 +157,7 @@ static void lapb_t1timer_expiry(unsigned
 				lapb_stop_t2timer(lapb);
 				lapb_disconnect_indication(lapb, LAPB_TIMEDOUT);
 #if LAPB_DEBUG > 0
-				printk(KERN_DEBUG "lapb: (%p) S3 -> S0\n", lapb->token);
+				printk(KERN_DEBUG "lapb: (%p) S3 -> S0\n", lapb->dev);
 #endif
 				return;
 			} else {
@@ -175,7 +175,7 @@ static void lapb_t1timer_expiry(unsigned
 				lapb->state = LAPB_STATE_0;
 				lapb_disconnect_indication(lapb, LAPB_TIMEDOUT);
 #if LAPB_DEBUG > 0
-				printk(KERN_DEBUG "lapb: (%p) S4 -> S0\n", lapb->token);
+				printk(KERN_DEBUG "lapb: (%p) S4 -> S0\n", lapb->dev);
 #endif
 				return;
 			} else {
--- diff/net/sched/Makefile	2002-12-16 09:26:07.000000000 +0000
+++ source/net/sched/Makefile	2004-02-23 13:56:48.000000000 +0000
@@ -8,23 +8,23 @@ obj-$(CONFIG_NET_SCHED)		+= sch_api.o sc
 obj-$(CONFIG_NET_ESTIMATOR)	+= estimator.o
 obj-$(CONFIG_NET_CLS)		+= cls_api.o
 obj-$(CONFIG_NET_CLS_POLICE)	+= police.o
-obj-$(CONFIG_NET_SCH_INGRESS)	+= sch_ingress.o 
 obj-$(CONFIG_NET_SCH_CBQ)	+= sch_cbq.o
+obj-$(CONFIG_NET_SCH_HTB)	+= sch_htb.o
 obj-$(CONFIG_NET_SCH_CSZ)	+= sch_csz.o
 obj-$(CONFIG_NET_SCH_HPFQ)	+= sch_hpfq.o
 obj-$(CONFIG_NET_SCH_HFSC)	+= sch_hfsc.o
-obj-$(CONFIG_NET_SCH_HTB)	+= sch_htb.o
-obj-$(CONFIG_NET_SCH_SFQ)	+= sch_sfq.o
 obj-$(CONFIG_NET_SCH_RED)	+= sch_red.o
-obj-$(CONFIG_NET_SCH_TBF)	+= sch_tbf.o
-obj-$(CONFIG_NET_SCH_PRIO)	+= sch_prio.o
-obj-$(CONFIG_NET_SCH_TEQL)	+= sch_teql.o
 obj-$(CONFIG_NET_SCH_GRED)	+= sch_gred.o
+obj-$(CONFIG_NET_SCH_INGRESS)	+= sch_ingress.o 
 obj-$(CONFIG_NET_SCH_DSMARK)	+= sch_dsmark.o
-obj-$(CONFIG_NET_CLS_TCINDEX)	+= cls_tcindex.o
+obj-$(CONFIG_NET_SCH_SFQ)	+= sch_sfq.o
+obj-$(CONFIG_NET_SCH_TBF)	+= sch_tbf.o
+obj-$(CONFIG_NET_SCH_TEQL)	+= sch_teql.o
+obj-$(CONFIG_NET_SCH_PRIO)	+= sch_prio.o
 obj-$(CONFIG_NET_SCH_ATM)	+= sch_atm.o
 obj-$(CONFIG_NET_CLS_U32)	+= cls_u32.o
-obj-$(CONFIG_NET_CLS_RSVP)	+= cls_rsvp.o
-obj-$(CONFIG_NET_CLS_RSVP6)	+= cls_rsvp6.o
 obj-$(CONFIG_NET_CLS_ROUTE4)	+= cls_route.o
 obj-$(CONFIG_NET_CLS_FW)	+= cls_fw.o
+obj-$(CONFIG_NET_CLS_RSVP)	+= cls_rsvp.o
+obj-$(CONFIG_NET_CLS_TCINDEX)	+= cls_tcindex.o
+obj-$(CONFIG_NET_CLS_RSVP6)	+= cls_rsvp6.o
--- diff/net/sched/cls_api.c	2004-01-19 10:22:59.000000000 +0000
+++ source/net/sched/cls_api.c	2004-02-23 13:56:48.000000000 +0000
@@ -425,7 +425,7 @@ out:
 }
 
 
-int __init tc_filter_init(void)
+static int __init tc_filter_init(void)
 {
 	struct rtnetlink_link *link_p = rtnetlink_links[PF_UNSPEC];
 
@@ -439,31 +439,10 @@ int __init tc_filter_init(void)
 		link_p[RTM_GETTFILTER-RTM_BASE].doit = tc_ctl_tfilter;
 		link_p[RTM_GETTFILTER-RTM_BASE].dumpit = tc_dump_tfilter;
 	}
-#define INIT_TC_FILTER(name) { \
-          extern struct tcf_proto_ops cls_##name##_ops; \
-          register_tcf_proto_ops(&cls_##name##_ops); \
-	}
-
-#ifdef CONFIG_NET_CLS_U32
-	INIT_TC_FILTER(u32);
-#endif
-#ifdef CONFIG_NET_CLS_ROUTE4
-	INIT_TC_FILTER(route4);
-#endif
-#ifdef CONFIG_NET_CLS_FW
-	INIT_TC_FILTER(fw);
-#endif
-#ifdef CONFIG_NET_CLS_RSVP
-	INIT_TC_FILTER(rsvp);
-#endif
-#ifdef CONFIG_NET_CLS_TCINDEX
-	INIT_TC_FILTER(tcindex);
-#endif
-#ifdef CONFIG_NET_CLS_RSVP6
-	INIT_TC_FILTER(rsvp6);
-#endif
 	return 0;
 }
 
+subsys_initcall(tc_filter_init);
+
 EXPORT_SYMBOL(register_tcf_proto_ops);
 EXPORT_SYMBOL(unregister_tcf_proto_ops);
--- diff/net/sched/cls_fw.c	2003-05-21 11:50:17.000000000 +0100
+++ source/net/sched/cls_fw.c	2004-02-23 13:56:48.000000000 +0000
@@ -347,7 +347,7 @@ rtattr_failure:
 	return -1;
 }
 
-struct tcf_proto_ops cls_fw_ops = {
+static struct tcf_proto_ops cls_fw_ops = {
 	.next		=	NULL,
 	.kind		=	"fw",
 	.classify	=	fw_classify,
@@ -362,15 +362,16 @@ struct tcf_proto_ops cls_fw_ops = {
 	.owner		=	THIS_MODULE,
 };
 
-#ifdef MODULE
-int init_module(void)
+static int __init init_fw(void)
 {
 	return register_tcf_proto_ops(&cls_fw_ops);
 }
 
-void cleanup_module(void) 
+static void __exit exit_fw(void) 
 {
 	unregister_tcf_proto_ops(&cls_fw_ops);
 }
-#endif
+
+module_init(init_fw)
+module_exit(exit_fw)
 MODULE_LICENSE("GPL");
--- diff/net/sched/cls_route.c	2003-05-21 11:50:17.000000000 +0100
+++ source/net/sched/cls_route.c	2004-02-23 13:56:48.000000000 +0000
@@ -602,7 +602,7 @@ rtattr_failure:
 	return -1;
 }
 
-struct tcf_proto_ops cls_route4_ops = {
+static struct tcf_proto_ops cls_route4_ops = {
 	.next		=	NULL,
 	.kind		=	"route",
 	.classify	=	route4_classify,
@@ -617,15 +617,16 @@ struct tcf_proto_ops cls_route4_ops = {
 	.owner		=	THIS_MODULE,
 };
 
-#ifdef MODULE
-int init_module(void)
+static int __init init_route4(void)
 {
 	return register_tcf_proto_ops(&cls_route4_ops);
 }
 
-void cleanup_module(void)
+static void __exit exit_route4(void)
 {
 	unregister_tcf_proto_ops(&cls_route4_ops);
 }
-#endif
+
+module_init(init_route4)
+module_exit(exit_route4)
 MODULE_LICENSE("GPL");
--- diff/net/sched/cls_rsvp.h	2003-07-08 09:55:19.000000000 +0100
+++ source/net/sched/cls_rsvp.h	2004-02-23 13:56:48.000000000 +0000
@@ -667,7 +667,7 @@ rtattr_failure:
 	return -1;
 }
 
-struct tcf_proto_ops RSVP_OPS = {
+static struct tcf_proto_ops RSVP_OPS = {
 	.next		=	NULL,
 	.kind		=	RSVP_ID,
 	.classify	=	rsvp_classify,
@@ -682,14 +682,15 @@ struct tcf_proto_ops RSVP_OPS = {
 	.owner		=	THIS_MODULE,
 };
 
-#ifdef MODULE
-int init_module(void)
+static int __init init_rsvp(void)
 {
 	return register_tcf_proto_ops(&RSVP_OPS);
 }
 
-void cleanup_module(void) 
+static void __exit exit_rsvp(void) 
 {
 	unregister_tcf_proto_ops(&RSVP_OPS);
 }
-#endif
+
+module_init(init_rsvp)
+module_exit(exit_rsvp)
--- diff/net/sched/cls_tcindex.c	2003-05-21 11:50:17.000000000 +0100
+++ source/net/sched/cls_tcindex.c	2004-02-23 13:56:48.000000000 +0000
@@ -476,7 +476,7 @@ rtattr_failure:
 	return -1;
 }
 
-struct tcf_proto_ops cls_tcindex_ops = {
+static struct tcf_proto_ops cls_tcindex_ops = {
 	.next		=	NULL,
 	.kind		=	"tcindex",
 	.classify	=	tcindex_classify,
@@ -491,16 +491,16 @@ struct tcf_proto_ops cls_tcindex_ops = {
 	.owner		=	THIS_MODULE,
 };
 
-
-#ifdef MODULE
-int init_module(void)
+static int __init init_tcindex(void)
 {
 	return register_tcf_proto_ops(&cls_tcindex_ops);
 }
 
-void cleanup_module(void) 
+static void __exit exit_tcindex(void) 
 {
 	unregister_tcf_proto_ops(&cls_tcindex_ops);
 }
-#endif
+
+module_init(init_tcindex)
+module_exit(exit_tcindex)
 MODULE_LICENSE("GPL");
--- diff/net/sched/cls_u32.c	2003-05-21 11:50:17.000000000 +0100
+++ source/net/sched/cls_u32.c	2004-02-23 13:56:48.000000000 +0000
@@ -684,7 +684,7 @@ rtattr_failure:
 	return -1;
 }
 
-struct tcf_proto_ops cls_u32_ops = {
+static struct tcf_proto_ops cls_u32_ops = {
 	.next		=	NULL,
 	.kind		=	"u32",
 	.classify	=	u32_classify,
@@ -699,15 +699,16 @@ struct tcf_proto_ops cls_u32_ops = {
 	.owner		=	THIS_MODULE,
 };
 
-#ifdef MODULE
-int init_module(void)
+static int __init init_u32(void)
 {
 	return register_tcf_proto_ops(&cls_u32_ops);
 }
 
-void cleanup_module(void) 
+static void __exit exit_u32(void) 
 {
 	unregister_tcf_proto_ops(&cls_u32_ops);
 }
-#endif
+
+module_init(init_u32)
+module_exit(exit_u32)
 MODULE_LICENSE("GPL");
--- diff/net/sched/sch_api.c	2003-10-09 09:47:34.000000000 +0100
+++ source/net/sched/sch_api.c	2004-02-23 13:56:48.000000000 +0000
@@ -1165,7 +1165,7 @@ int __init psched_calibrate_clock(void)
 }
 #endif
 
-int __init pktsched_init(void)
+static int __init pktsched_init(void)
 {
 	struct rtnetlink_link *link_p;
 
@@ -1197,65 +1197,15 @@ int __init pktsched_init(void)
 		link_p[RTM_GETTCLASS-RTM_BASE].dumpit = tc_dump_tclass;
 	}
 
-#define INIT_QDISC(name) { \
-          extern struct Qdisc_ops name##_qdisc_ops; \
-          register_qdisc(& name##_qdisc_ops);       \
-	}
-
-	INIT_QDISC(pfifo);
-	INIT_QDISC(bfifo);
-
-#ifdef CONFIG_NET_SCH_CBQ
-	INIT_QDISC(cbq);
-#endif
-#ifdef CONFIG_NET_SCH_HTB
-	INIT_QDISC(htb);
-#endif
-#ifdef CONFIG_NET_SCH_CSZ
-	INIT_QDISC(csz);
-#endif
-#ifdef CONFIG_NET_SCH_HPFQ
-	INIT_QDISC(hpfq);
-#endif
-#ifdef CONFIG_NET_SCH_HFSC
-	INIT_QDISC(hfsc);
-#endif
-#ifdef CONFIG_NET_SCH_RED
-	INIT_QDISC(red);
-#endif
-#ifdef CONFIG_NET_SCH_GRED
-       INIT_QDISC(gred);
-#endif
-#ifdef CONFIG_NET_SCH_INGRESS
-       INIT_QDISC(ingress);
-#endif
-#ifdef CONFIG_NET_SCH_DSMARK
-       INIT_QDISC(dsmark);
-#endif
-#ifdef CONFIG_NET_SCH_SFQ
-	INIT_QDISC(sfq);
-#endif
-#ifdef CONFIG_NET_SCH_TBF
-	INIT_QDISC(tbf);
-#endif
-#ifdef CONFIG_NET_SCH_TEQL
-	teql_init();
-#endif
-#ifdef CONFIG_NET_SCH_PRIO
-	INIT_QDISC(prio);
-#endif
-#ifdef CONFIG_NET_SCH_ATM
-	INIT_QDISC(atm);
-#endif
-#ifdef CONFIG_NET_CLS
-	tc_filter_init();
-#endif
-
+	register_qdisc(&pfifo_qdisc_ops);
+	register_qdisc(&bfifo_qdisc_ops);
 	proc_net_fops_create("psched", 0, &psched_fops);
 
 	return 0;
 }
 
+subsys_initcall(pktsched_init);
+
 EXPORT_SYMBOL(qdisc_copy_stats);
 EXPORT_SYMBOL(qdisc_get_rtab);
 EXPORT_SYMBOL(qdisc_put_rtab);
--- diff/net/sched/sch_atm.c	2004-01-19 10:22:59.000000000 +0000
+++ source/net/sched/sch_atm.c	2004-02-23 13:56:48.000000000 +0000
@@ -5,6 +5,7 @@
 
 #include <linux/config.h>
 #include <linux/module.h>
+#include <linux/init.h>
 #include <linux/string.h>
 #include <linux/errno.h>
 #include <linux/skbuff.h>
@@ -682,7 +683,7 @@ static struct Qdisc_class_ops atm_class_
 	.dump		=	atm_tc_dump_class,
 };
 
-struct Qdisc_ops atm_qdisc_ops = {
+static struct Qdisc_ops atm_qdisc_ops = {
 	.next		=	NULL,
 	.cl_ops		=	&atm_class_ops,
 	.id		=	"atm",
@@ -700,15 +701,15 @@ struct Qdisc_ops atm_qdisc_ops = {
 };
 
 
-#ifdef MODULE
-int init_module(void)
+static int __init atm_init(void)
 {
 	return register_qdisc(&atm_qdisc_ops);
 }
 
-
-void cleanup_module(void) 
+static void __exit atm_exit(void) 
 {
 	unregister_qdisc(&atm_qdisc_ops);
 }
-#endif
+
+module_init(atm_init)
+module_exit(atm_exit)
--- diff/net/sched/sch_cbq.c	2004-01-19 10:22:59.000000000 +0000
+++ source/net/sched/sch_cbq.c	2004-02-23 13:56:48.000000000 +0000
@@ -2074,7 +2074,7 @@ static struct Qdisc_class_ops cbq_class_
 	.dump		=	cbq_dump_class,
 };
 
-struct Qdisc_ops cbq_qdisc_ops = {
+static struct Qdisc_ops cbq_qdisc_ops = {
 	.next		=	NULL,
 	.cl_ops		=	&cbq_class_ops,
 	.id		=	"cbq",
@@ -2091,15 +2091,14 @@ struct Qdisc_ops cbq_qdisc_ops = {
 	.owner		=	THIS_MODULE,
 };
 
-#ifdef MODULE
-int init_module(void)
+static int __init cbq_module_init(void)
 {
 	return register_qdisc(&cbq_qdisc_ops);
 }
-
-void cleanup_module(void) 
+static void __exit cbq_module_exit(void) 
 {
 	unregister_qdisc(&cbq_qdisc_ops);
 }
-#endif
+module_init(cbq_module_init)
+module_exit(cbq_module_exit)
 MODULE_LICENSE("GPL");
--- diff/net/sched/sch_csz.c	2004-01-19 10:22:59.000000000 +0000
+++ source/net/sched/sch_csz.c	2004-02-23 13:56:48.000000000 +0000
@@ -1027,7 +1027,7 @@ struct Qdisc_class_ops csz_class_ops = {
 	.dump		=	csz_dump_class,
 };
 
-struct Qdisc_ops csz_qdisc_ops = {
+static struct Qdisc_ops csz_qdisc_ops = {
 	.next		=	NULL,
 	.cl_ops		=	&csz_class_ops,
 	.id		=	"csz",
@@ -1044,16 +1044,14 @@ struct Qdisc_ops csz_qdisc_ops = {
 	.owner		=	THIS_MODULE,
 };
 
-
-#ifdef MODULE
-int init_module(void)
+static int __init csz_module_init(void)
 {
 	return register_qdisc(&csz_qdisc_ops);
 }
-
-void cleanup_module(void) 
+static void __exit csz_module_exit(void) 
 {
 	unregister_qdisc(&csz_qdisc_ops);
 }
-#endif
+module_init(csz_module_init)
+module_exit(csz_module_exit)
 MODULE_LICENSE("GPL");
--- diff/net/sched/sch_dsmark.c	2004-01-19 10:22:59.000000000 +0000
+++ source/net/sched/sch_dsmark.c	2004-02-23 13:56:48.000000000 +0000
@@ -5,6 +5,7 @@
 
 #include <linux/config.h>
 #include <linux/module.h>
+#include <linux/init.h>
 #include <linux/types.h>
 #include <linux/string.h>
 #include <linux/errno.h>
@@ -447,7 +448,7 @@ static struct Qdisc_class_ops dsmark_cla
 	.dump		=	dsmark_dump_class,
 };
 
-struct Qdisc_ops dsmark_qdisc_ops = {
+static struct Qdisc_ops dsmark_qdisc_ops = {
 	.next		=	NULL,
 	.cl_ops		=	&dsmark_class_ops,
 	.id		=	"dsmark",
@@ -464,16 +465,14 @@ struct Qdisc_ops dsmark_qdisc_ops = {
 	.owner		=	THIS_MODULE,
 };
 
-#ifdef MODULE
-int init_module(void)
+static int __init dsmark_module_init(void)
 {
 	return register_qdisc(&dsmark_qdisc_ops);
 }
-
-
-void cleanup_module(void) 
+static void __exit dsmark_module_exit(void) 
 {
 	unregister_qdisc(&dsmark_qdisc_ops);
 }
-#endif
+module_init(dsmark_module_init)
+module_exit(dsmark_module_exit)
 MODULE_LICENSE("GPL");
--- diff/net/sched/sch_fifo.c	2003-11-25 15:24:59.000000000 +0000
+++ source/net/sched/sch_fifo.c	2004-02-23 13:56:48.000000000 +0000
@@ -141,10 +141,12 @@ static int fifo_init(struct Qdisc *sch, 
 	struct fifo_sched_data *q = (void*)sch->data;
 
 	if (opt == NULL) {
+		unsigned int limit = sch->dev->tx_queue_len ? : 1;
+
 		if (sch->ops == &bfifo_qdisc_ops)
-			q->limit = sch->dev->tx_queue_len*sch->dev->mtu;
+			q->limit = limit*sch->dev->mtu;
 		else	
-			q->limit = sch->dev->tx_queue_len;
+			q->limit = limit;
 	} else {
 		struct tc_fifo_qopt *ctl = RTA_DATA(opt);
 		if (opt->rta_len < RTA_LENGTH(sizeof(*ctl)))
--- diff/net/sched/sch_gred.c	2003-11-25 15:24:59.000000000 +0000
+++ source/net/sched/sch_gred.c	2004-02-23 13:56:48.000000000 +0000
@@ -110,7 +110,7 @@ gred_enqueue(struct sk_buff *skb, struct
 	unsigned long	qave=0;	
 	int i=0;
 
-	if (!t->initd && skb_queue_len(&sch->q) < sch->dev->tx_queue_len) {
+	if (!t->initd && skb_queue_len(&sch->q) < (sch->dev->tx_queue_len ? : 1)) {
 		D2PRINTK("NO GRED Queues setup yet! Enqueued anyway\n");
 		goto do_enqueue;
 	}
@@ -602,7 +602,7 @@ static void gred_destroy(struct Qdisc *s
 	}
 }
 
-struct Qdisc_ops gred_qdisc_ops = {
+static struct Qdisc_ops gred_qdisc_ops = {
 	.next		=	NULL,
 	.cl_ops		=	NULL,
 	.id		=	"gred",
@@ -619,16 +619,14 @@ struct Qdisc_ops gred_qdisc_ops = {
 	.owner		=	THIS_MODULE,
 };
 
-
-#ifdef MODULE
-int init_module(void)
+static int __init gred_module_init(void)
 {
 	return register_qdisc(&gred_qdisc_ops);
 }
-
-void cleanup_module(void) 
+static void __exit gred_module_exit(void) 
 {
 	unregister_qdisc(&gred_qdisc_ops);
 }
-#endif
+module_init(gred_module_init)
+module_exit(gred_module_exit)
 MODULE_LICENSE("GPL");
--- diff/net/sched/sch_hfsc.c	2004-02-18 08:54:13.000000000 +0000
+++ source/net/sched/sch_hfsc.c	2004-02-23 13:56:48.000000000 +0000
@@ -1831,7 +1831,7 @@ static struct Qdisc_class_ops hfsc_class
 	.walk		= hfsc_walk
 };
 
-struct Qdisc_ops hfsc_qdisc_ops = {
+static struct Qdisc_ops hfsc_qdisc_ops = {
 	.id		= "hfsc",
 	.init		= hfsc_init_qdisc,
 	.change		= hfsc_change_qdisc,
--- diff/net/sched/sch_htb.c	2004-01-19 10:22:59.000000000 +0000
+++ source/net/sched/sch_htb.c	2004-02-23 13:56:48.000000000 +0000
@@ -1646,7 +1646,7 @@ static struct Qdisc_class_ops htb_class_
 	.dump		=	htb_dump_class,
 };
 
-struct Qdisc_ops htb_qdisc_ops = {
+static struct Qdisc_ops htb_qdisc_ops = {
 	.next		=	NULL,
 	.cl_ops		=	&htb_class_ops,
 	.id		=	"htb",
@@ -1663,15 +1663,14 @@ struct Qdisc_ops htb_qdisc_ops = {
 	.owner		=	THIS_MODULE,
 };
 
-#ifdef MODULE
-int init_module(void)
+static int __init htb_module_init(void)
 {
     return register_qdisc(&htb_qdisc_ops);
 }
-
-void cleanup_module(void) 
+static void __exit htb_module_exit(void) 
 {
     unregister_qdisc(&htb_qdisc_ops);
 }
+module_init(htb_module_init)
+module_exit(htb_module_exit)
 MODULE_LICENSE("GPL");
-#endif
--- diff/net/sched/sch_ingress.c	2004-01-19 10:22:59.000000000 +0000
+++ source/net/sched/sch_ingress.c	2004-02-23 13:56:48.000000000 +0000
@@ -333,7 +333,7 @@ static struct Qdisc_class_ops ingress_cl
 	.dump		=	NULL,
 };
 
-struct Qdisc_ops ingress_qdisc_ops = {
+static struct Qdisc_ops ingress_qdisc_ops = {
 	.next		=	NULL,
 	.cl_ops		=	&ingress_class_ops,
 	.id		=	"ingress",
@@ -350,9 +350,7 @@ struct Qdisc_ops ingress_qdisc_ops = {
 	.owner		=	THIS_MODULE,
 };
 
-
-#ifdef MODULE
-int init_module(void)
+static int __init ingress_module_init(void)
 {
 	int ret = 0;
 
@@ -363,13 +361,12 @@ int init_module(void)
 
 	return ret;
 }
-
-
-void cleanup_module(void) 
+static void __exit ingress_module_exit(void) 
 {
 	unregister_qdisc(&ingress_qdisc_ops);
 	if (nf_registered)
 		nf_unregister_hook(&ing_ops);
 }
-#endif
+module_init(ingress_module_init)
+module_exit(ingress_module_exit)
 MODULE_LICENSE("GPL");
--- diff/net/sched/sch_prio.c	2004-01-19 10:22:59.000000000 +0000
+++ source/net/sched/sch_prio.c	2004-02-23 13:56:48.000000000 +0000
@@ -382,7 +382,7 @@ static struct Qdisc_class_ops prio_class
 	.dump		=	prio_dump_class,
 };
 
-struct Qdisc_ops prio_qdisc_ops = {
+static struct Qdisc_ops prio_qdisc_ops = {
 	.next		=	NULL,
 	.cl_ops		=	&prio_class_ops,
 	.id		=	"prio",
@@ -399,17 +399,17 @@ struct Qdisc_ops prio_qdisc_ops = {
 	.owner		=	THIS_MODULE,
 };
 
-#ifdef MODULE
-
-int init_module(void)
+static int __init prio_module_init(void)
 {
 	return register_qdisc(&prio_qdisc_ops);
 }
 
-void cleanup_module(void) 
+static void __exit prio_module_exit(void) 
 {
 	unregister_qdisc(&prio_qdisc_ops);
 }
 
-#endif
+module_init(prio_module_init)
+module_exit(prio_module_exit)
+
 MODULE_LICENSE("GPL");
--- diff/net/sched/sch_red.c	2003-11-25 15:24:59.000000000 +0000
+++ source/net/sched/sch_red.c	2004-02-23 13:56:48.000000000 +0000
@@ -453,7 +453,7 @@ static void red_destroy(struct Qdisc *sc
 {
 }
 
-struct Qdisc_ops red_qdisc_ops = {
+static struct Qdisc_ops red_qdisc_ops = {
 	.next		=	NULL,
 	.cl_ops		=	NULL,
 	.id		=	"red",
@@ -470,16 +470,14 @@ struct Qdisc_ops red_qdisc_ops = {
 	.owner		=	THIS_MODULE,
 };
 
-
-#ifdef MODULE
-int init_module(void)
+static int __init red_module_init(void)
 {
 	return register_qdisc(&red_qdisc_ops);
 }
-
-void cleanup_module(void) 
+static void __exit red_module_exit(void) 
 {
 	unregister_qdisc(&red_qdisc_ops);
 }
-#endif
+module_init(red_module_init)
+module_exit(red_module_exit)
 MODULE_LICENSE("GPL");
--- diff/net/sched/sch_sfq.c	2003-07-11 09:39:50.000000000 +0100
+++ source/net/sched/sch_sfq.c	2004-02-23 13:56:48.000000000 +0000
@@ -341,6 +341,7 @@ sfq_dequeue(struct Qdisc* sch)
 
 	/* Is the slot empty? */
 	if (q->qs[a].qlen == 0) {
+		q->ht[q->hash[a]] = SFQ_DEPTH;
 		a = q->next[a];
 		if (a == old_a) {
 			q->tail = SFQ_DEPTH;
@@ -465,7 +466,7 @@ rtattr_failure:
 	return -1;
 }
 
-struct Qdisc_ops sfq_qdisc_ops = {
+static struct Qdisc_ops sfq_qdisc_ops = {
 	.next		=	NULL,
 	.cl_ops		=	NULL,
 	.id		=	"sfq",
@@ -482,15 +483,14 @@ struct Qdisc_ops sfq_qdisc_ops = {
 	.owner		=	THIS_MODULE,
 };
 
-#ifdef MODULE
-int init_module(void)
+static int __init sfq_module_init(void)
 {
 	return register_qdisc(&sfq_qdisc_ops);
 }
-
-void cleanup_module(void) 
+static void __exit sfq_module_exit(void) 
 {
 	unregister_qdisc(&sfq_qdisc_ops);
 }
-#endif
+module_init(sfq_module_init)
+module_exit(sfq_module_exit)
 MODULE_LICENSE("GPL");
--- diff/net/sched/sch_tbf.c	2004-01-19 10:22:59.000000000 +0000
+++ source/net/sched/sch_tbf.c	2004-02-23 13:56:48.000000000 +0000
@@ -510,7 +510,7 @@ static struct Qdisc_class_ops tbf_class_
 	.dump		=	tbf_dump_class,
 };
 
-struct Qdisc_ops tbf_qdisc_ops = {
+static struct Qdisc_ops tbf_qdisc_ops = {
 	.next		=	NULL,
 	.cl_ops		=	&tbf_class_ops,
 	.id		=	"tbf",
@@ -527,16 +527,15 @@ struct Qdisc_ops tbf_qdisc_ops = {
 	.owner		=	THIS_MODULE,
 };
 
-
-#ifdef MODULE
-int init_module(void)
+static int __init tbf_module_init(void)
 {
 	return register_qdisc(&tbf_qdisc_ops);
 }
 
-void cleanup_module(void) 
+static void __exit tbf_module_exit(void) 
 {
 	unregister_qdisc(&tbf_qdisc_ops);
 }
-#endif
+module_init(tbf_module_init)
+module_exit(tbf_module_exit)
 MODULE_LICENSE("GPL");
--- diff/net/sched/sch_teql.c	2004-02-09 10:36:12.000000000 +0000
+++ source/net/sched/sch_teql.c	2004-02-23 13:56:48.000000000 +0000
@@ -418,14 +418,12 @@ static int teql_master_mtu(struct net_de
 	return 0;
 }
 
-static __init int teql_master_init(struct net_device *dev)
+static __init void teql_master_setup(struct net_device *dev)
 {
 	struct teql_master *master = dev->priv;
 	struct Qdisc_ops *ops = &master->qops;
 
 	master->dev	= dev;
-
-	strlcpy(ops->id, dev->name, IFNAMSIZ);
 	ops->priv_size  = sizeof(struct teql_sched_data);
 	
 	ops->enqueue	=	teql_enqueue;
@@ -436,12 +434,6 @@ static __init int teql_master_init(struc
 	ops->destroy	=	teql_destroy;
 	ops->owner	=	THIS_MODULE;
 
-	return register_qdisc(ops);
-}
-
-static __init void teql_master_setup(struct net_device *dev)
-{
-	dev->init		= teql_master_init;
 	dev->open		= teql_master_open;
 	dev->hard_start_xmit	= teql_master_xmit;
 	dev->stop		= teql_master_close;
@@ -460,10 +452,10 @@ static int max_equalizers = 1;
 MODULE_PARM(max_equalizers, "i");
 MODULE_PARM_DESC(max_equalizers, "Max number of link equalizers");
 
-int __init teql_init(void)
+static int __init teql_init(void)
 {
 	int i;
-	int err = 0;
+	int err = -ENODEV;
 
 	for (i = 0; i < max_equalizers; i++) {
 		struct net_device *dev;
@@ -471,19 +463,30 @@ int __init teql_init(void)
 
 		dev = alloc_netdev(sizeof(struct teql_master),
 				  "teql%d", teql_master_setup);
-		if (!dev)
-			return -ENOMEM;
+		if (!dev) {
+			err = -ENOMEM;
+			break;
+		}
 
 		if ((err = register_netdev(dev))) {
 			free_netdev(dev);
-			goto out;
+			break;
 		}
 
 		master = dev->priv;
+
+		strlcpy(master->qops.id, dev->name, IFNAMSIZ);
+		err = register_qdisc(&master->qops);
+
+		if (err) {
+			unregister_netdev(dev);
+			free_netdev(dev);
+			break;
+		}
+
 		list_add_tail(&master->master_list, &master_dev_list);
 	}
- out:
-	return err;
+	return i ? 0 : err;
 }
 
 static void __exit teql_exit(void) 
--- diff/net/sctp/Kconfig	2004-02-18 08:54:13.000000000 +0000
+++ source/net/sctp/Kconfig	2004-02-23 13:56:48.000000000 +0000
@@ -74,13 +74,19 @@ config SCTP_HMAC_NONE
 	  establishment.  It is advised to use either HMAC-MD5 or HMAC-SHA1.
 
 config SCTP_HMAC_SHA1
-	bool "HMAC-SHA1" if CRYPTO_HMAC=y && CRYPTO_SHA1=y || CRYPTO_SHA1=m
+	bool "HMAC-SHA1"
+	select CRYPTO
+	select CRYPTO_HMAC
+	select CRYPTO_SHA1
 	help 
 	  Enable the use of HMAC-SHA1 during association establishment.  It 
 	  is advised to use either HMAC-MD5 or HMAC-SHA1.
 
 config SCTP_HMAC_MD5
-	bool "HMAC-MD5" if CRYPTO_HMAC=y && CRYPTO_MD5=y || CRYPTO_MD5=m
+	bool "HMAC-MD5"
+	select CRYPTO
+	select CRYPTO_HMAC
+	select CRYPTO_MD5
 	help
 	  Enable the use of HMAC-MD5 during association establishment.  It is 
 	  advised to use either HMAC-MD5 or HMAC-SHA1.
--- diff/net/sctp/ssnmap.c	2004-02-18 08:54:13.000000000 +0000
+++ source/net/sctp/ssnmap.c	2004-02-23 13:56:48.000000000 +0000
@@ -40,6 +40,7 @@
 #include <net/sctp/sctp.h>
 #include <net/sctp/sm.h>
 
+#define MAX_KMALLOC_SIZE	131072
 
 /* Storage size needed for map includes 2 headers and then the
  * specific needs of in or out streams.
@@ -56,11 +57,14 @@ static inline size_t sctp_ssnmap_size(__
 struct sctp_ssnmap *sctp_ssnmap_new(__u16 in, __u16 out, int gfp)
 {
 	struct sctp_ssnmap *retval;
-	int order;
-
-	order = get_order(sctp_ssnmap_size(in,out));
-	retval = (struct sctp_ssnmap *)__get_free_pages(gfp, order);
+	int size;
 
+	size = sctp_ssnmap_size(in, out);
+	if (size <= MAX_KMALLOC_SIZE)
+		retval = kmalloc(size, gfp);
+	else
+		retval = (struct sctp_ssnmap *)
+			  __get_free_pages(gfp, get_order(size));
 	if (!retval)
 		goto fail;
 
@@ -73,7 +77,10 @@ struct sctp_ssnmap *sctp_ssnmap_new(__u1
 	return retval;
 
 fail_map:
-	free_pages((unsigned long)retval, order);
+	if (size <= MAX_KMALLOC_SIZE)
+		kfree(retval);
+	else
+		free_pages((unsigned long)retval, get_order(size));
 fail:
 	return NULL;
 }
@@ -109,9 +116,13 @@ void sctp_ssnmap_clear(struct sctp_ssnma
 void sctp_ssnmap_free(struct sctp_ssnmap *map)
 {
 	if (map && map->malloced) {
-		free_pages((unsigned long)map,
-			   get_order(sctp_ssnmap_size(map->in.len,
-						      map->out.len)));
+		int size;
+
+		size = sctp_ssnmap_size(map->in.len, map->out.len);
+		if (size <= MAX_KMALLOC_SIZE)
+			kfree(map);
+		else
+			free_pages((unsigned long)map, get_order(size));
 		SCTP_DBG_OBJCNT_DEC(ssnmap);
 	}
 }
--- diff/net/socket.c	2004-02-09 10:36:12.000000000 +0000
+++ source/net/socket.c	2004-02-23 13:56:48.000000000 +0000
@@ -78,6 +78,7 @@
 #include <linux/divert.h>
 #include <linux/mount.h>
 #include <linux/security.h>
+#include <linux/syscalls.h>
 #include <linux/compat.h>
 #include <linux/kmod.h>
 
--- diff/net/sunrpc/auth.c	2004-02-18 08:54:13.000000000 +0000
+++ source/net/sunrpc/auth.c	2004-02-23 13:56:48.000000000 +0000
@@ -255,34 +255,41 @@ retry:
 struct rpc_cred *
 rpcauth_lookupcred(struct rpc_auth *auth, int taskflags)
 {
-	struct auth_cred acred = {
-		.uid = current->fsuid,
-		.gid = current->fsgid,
-		.ngroups = current->ngroups,
-		.groups = current->groups,
-	};
+	struct auth_cred acred;
+	struct rpc_cred *ret;
+
+	get_group_info(current->group_info);
+	acred.uid = current->fsuid;
+	acred.gid = current->fsgid;
+	acred.group_info = current->group_info;
+
 	dprintk("RPC:     looking up %s cred\n",
 		auth->au_ops->au_name);
-	return rpcauth_lookup_credcache(auth, &acred, taskflags);
+	ret = rpcauth_lookup_credcache(auth, &acred, taskflags);
+	put_group_info(current->group_info);
+	return ret;
 }
 
 struct rpc_cred *
 rpcauth_bindcred(struct rpc_task *task)
 {
 	struct rpc_auth *auth = task->tk_auth;
-	struct auth_cred acred = {
-		.uid = current->fsuid,
-		.gid = current->fsgid,
-		.ngroups = current->ngroups,
-		.groups = current->groups,
-	};
+	struct auth_cred acred;
+	struct rpc_cred *ret;
+
+	get_group_info(current->group_info);
+	acred.uid = current->fsuid;
+	acred.gid = current->fsgid;
+	acred.group_info = current->group_info;
 
 	dprintk("RPC: %4d looking up %s cred\n",
 		task->tk_pid, task->tk_auth->au_ops->au_name);
 	task->tk_msg.rpc_cred = rpcauth_lookup_credcache(auth, &acred, task->tk_flags);
 	if (task->tk_msg.rpc_cred == 0)
 		task->tk_status = -ENOMEM;
-	return task->tk_msg.rpc_cred;
+	ret = task->tk_msg.rpc_cred;
+	put_group_info(current->group_info);
+	return ret;
 }
 
 void
--- diff/net/sunrpc/auth_unix.c	2003-10-09 09:47:17.000000000 +0100
+++ source/net/sunrpc/auth_unix.c	2004-02-23 13:56:48.000000000 +0000
@@ -82,7 +82,7 @@ unx_create_cred(struct rpc_auth *auth, s
 		cred->uc_gid = cred->uc_pgid = 0;
 		cred->uc_gids[0] = NOGROUP;
 	} else {
-		int groups = acred->ngroups;
+		int groups = acred->group_info->ngroups;
 		if (groups > NFS_NGROUPS)
 			groups = NFS_NGROUPS;
 
@@ -91,7 +91,7 @@ unx_create_cred(struct rpc_auth *auth, s
 		cred->uc_puid = current->uid;
 		cred->uc_pgid = current->gid;
 		for (i = 0; i < groups; i++)
-			cred->uc_gids[i] = (gid_t) acred->groups[i];
+			cred->uc_gids[i] = GROUP_AT(acred->group_info, i);
 		if (i < NFS_NGROUPS)
 		  cred->uc_gids[i] = NOGROUP;
 	}
@@ -126,11 +126,11 @@ unx_match(struct auth_cred *acred, struc
 		 || cred->uc_pgid != current->gid)
 			return 0;
 
-		groups = acred->ngroups;
+		groups = acred->group_info->ngroups;
 		if (groups > NFS_NGROUPS)
 			groups = NFS_NGROUPS;
 		for (i = 0; i < groups ; i++)
-			if (cred->uc_gids[i] != (gid_t) acred->groups[i])
+			if (cred->uc_gids[i] != GROUP_AT(acred->group_info, i))
 				return 0;
 		return 1;
 	}
--- diff/net/sunrpc/cache.c	2004-02-09 10:36:12.000000000 +0000
+++ source/net/sunrpc/cache.c	2004-02-23 13:56:48.000000000 +0000
@@ -325,6 +325,7 @@ int cache_clean(void)
 	
 	if (current_detail && current_index < current_detail->hash_size) {
 		struct cache_head *ch, **cp;
+		struct cache_detail *d;
 		
 		write_lock(&current_detail->hash_lock);
 
@@ -354,12 +355,14 @@ int cache_clean(void)
 			rv = 1;
 		}
 		write_unlock(&current_detail->hash_lock);
-		if (ch)
-			current_detail->cache_put(ch, current_detail);
-		else
+		d = current_detail;
+		if (!ch)
 			current_index ++;
-	}
-	spin_unlock(&cache_list_lock);
+		spin_unlock(&cache_list_lock);
+		if (ch)
+			d->cache_put(ch, d);
+	} else
+		spin_unlock(&cache_list_lock);
 
 	return rv;
 }
--- diff/net/sunrpc/stats.c	2003-09-17 12:28:13.000000000 +0100
+++ source/net/sunrpc/stats.c	2004-02-23 13:56:48.000000000 +0000
@@ -18,6 +18,7 @@
 #include <linux/kernel.h>
 #include <linux/sched.h>
 #include <linux/proc_fs.h>
+#include <linux/seq_file.h>
 #include <linux/sunrpc/clnt.h>
 #include <linux/sunrpc/svcsock.h>
 
@@ -28,70 +29,66 @@ struct proc_dir_entry	*proc_net_rpc = NU
 /*
  * Get RPC client stats
  */
-int
-rpc_proc_read(char *buffer, char **start, off_t offset, int count,
-				int *eof, void *data)
-{
-	struct rpc_stat	*statp = (struct rpc_stat *) data;
-	struct rpc_program *prog = statp->program;
-	struct rpc_version *vers;
-	int		len, i, j;
+static int rpc_proc_show(struct seq_file *seq, void *v) {
+	const struct rpc_stat	*statp = seq->private;
+	const struct rpc_program *prog = statp->program;
+	int		i, j;
 
-	len = sprintf(buffer,
+	seq_printf(seq,
 		"net %d %d %d %d\n",
 			statp->netcnt,
 			statp->netudpcnt,
 			statp->nettcpcnt,
 			statp->nettcpconn);
-	len += sprintf(buffer + len,
+	seq_printf(seq,
 		"rpc %d %d %d\n",
 			statp->rpccnt,
 			statp->rpcretrans,
 			statp->rpcauthrefresh);
 
 	for (i = 0; i < prog->nrvers; i++) {
-		if (!(vers = prog->version[i]))
+		const struct rpc_version *vers = prog->version[i];
+		if (!vers)
 			continue;
-		len += sprintf(buffer + len, "proc%d %d",
+		seq_printf(seq, "proc%d %d",
 					vers->number, vers->nrprocs);
 		for (j = 0; j < vers->nrprocs; j++)
-			len += sprintf(buffer + len, " %d",
+			seq_printf(seq, " %d",
 					vers->procs[j].p_count);
-		buffer[len++] = '\n';
+		seq_putc(seq, '\n');
 	}
+	return 0;
+}
 
-	if (offset >= len) {
-		*start = buffer;
-		*eof = 1;
-		return 0;
-	}
-	*start = buffer + offset;
-	if ((len -= offset) > count)
-		return count;
-	*eof = 1;
-	return len;
+static int rpc_proc_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, rpc_proc_show, PDE(inode)->data);
 }
 
+static struct file_operations rpc_proc_fops = {
+	.owner = THIS_MODULE,
+	.open = rpc_proc_open,
+	.read  = seq_read,
+	.llseek = seq_lseek,
+	.release = single_release,
+};
+
 /*
  * Get RPC server stats
  */
-int
-svc_proc_read(char *buffer, char **start, off_t offset, int count,
-				int *eof, void *data)
-{
-	struct svc_stat *statp	= (struct svc_stat *) data;
-	struct svc_program *prog = statp->program;
-	struct svc_procedure *proc;
-	struct svc_version *vers;
-	int		len, i, j;
+void svc_seq_show(struct seq_file *seq, const struct svc_stat *statp) {
+	const struct svc_program *prog = statp->program;
+	const struct svc_procedure *proc;
+	const struct svc_version *vers;
+	int		i, j;
 
-	len = sprintf(buffer,
+	seq_printf(seq,
 		"net %d %d %d %d\n",
 			statp->netcnt,
 			statp->netudpcnt,
 			statp->nettcpcnt,
 			statp->nettcpconn);
-	len += sprintf(buffer + len,
+	seq_printf(seq,
 		"rpc %d %d %d %d %d\n",
 			statp->rpccnt,
 			statp->rpcbadfmt+statp->rpcbadauth+statp->rpcbadclnt,
@@ -102,41 +99,36 @@ svc_proc_read(char *buffer, char **start
 	for (i = 0; i < prog->pg_nvers; i++) {
 		if (!(vers = prog->pg_vers[i]) || !(proc = vers->vs_proc))
 			continue;
-		len += sprintf(buffer + len, "proc%d %d", i, vers->vs_nproc);
+		seq_printf(seq, "proc%d %d", i, vers->vs_nproc);
 		for (j = 0; j < vers->vs_nproc; j++, proc++)
-			len += sprintf(buffer + len, " %d", proc->pc_count);
-		buffer[len++] = '\n';
+			seq_printf(seq, " %d", proc->pc_count);
+		seq_putc(seq, '\n');
 	}
-
-	if (offset >= len) {
-		*start = buffer;
-		*eof = 1;
-		return 0;
-	}
-	*start = buffer + offset;
-	if ((len -= offset) > count)
-		return count;
-	*eof = 1;
-	return len;
 }
 
 /*
  * Register/unregister RPC proc files
  */
 static inline struct proc_dir_entry *
-do_register(const char *name, void *data, int issvc)
+do_register(const char *name, void *data, struct file_operations *fops)
 {
+	struct proc_dir_entry *ent;
+
 	rpc_proc_init();
 	dprintk("RPC: registering /proc/net/rpc/%s\n", name);
-	return create_proc_read_entry(name, 0, proc_net_rpc, 
-				      issvc? svc_proc_read : rpc_proc_read,
-				      data);
+
+	ent = create_proc_entry(name, 0, proc_net_rpc);
+	if (ent) {
+		ent->proc_fops = fops;
+		ent->data = data;
+	}
+	return ent;
 }
 
 struct proc_dir_entry *
 rpc_proc_register(struct rpc_stat *statp)
 {
-	return do_register(statp->program->name, statp, 0);
+	return do_register(statp->program->name, statp, &rpc_proc_fops);
 }
 
 void
@@ -146,9 +138,9 @@ rpc_proc_unregister(const char *name)
 }
 
 struct proc_dir_entry *
-svc_proc_register(struct svc_stat *statp)
+svc_proc_register(struct svc_stat *statp, struct file_operations *fops)
 {
-	return do_register(statp->program->pg_name, statp, 1);
+	return do_register(statp->program->pg_name, statp, fops);
 }
 
 void
@@ -163,7 +155,7 @@ rpc_proc_init(void)
 	dprintk("RPC: registering /proc/net/rpc\n");
 	if (!proc_net_rpc) {
 		struct proc_dir_entry *ent;
-		ent = proc_mkdir("net/rpc", 0);
+		ent = proc_mkdir("rpc", proc_net);
 		if (ent) {
 			ent->owner = THIS_MODULE;
 			proc_net_rpc = ent;
--- diff/net/sunrpc/sunrpc_syms.c	2004-02-18 08:54:13.000000000 +0000
+++ source/net/sunrpc/sunrpc_syms.c	2004-02-23 13:56:48.000000000 +0000
@@ -90,10 +90,9 @@ EXPORT_SYMBOL(svc_reserve);
 #ifdef CONFIG_PROC_FS
 EXPORT_SYMBOL(rpc_proc_register);
 EXPORT_SYMBOL(rpc_proc_unregister);
-EXPORT_SYMBOL(rpc_proc_read);
 EXPORT_SYMBOL(svc_proc_register);
 EXPORT_SYMBOL(svc_proc_unregister);
-EXPORT_SYMBOL(svc_proc_read);
+EXPORT_SYMBOL(svc_seq_show);
 #endif
 
 /* caching... */
--- diff/net/sunrpc/svcauth.c	2003-07-08 09:55:20.000000000 +0100
+++ source/net/sunrpc/svcauth.c	2004-02-23 13:56:48.000000000 +0000
@@ -150,7 +150,13 @@ DefineCacheLookup(struct auth_domain,
 		  &auth_domain_cache,
 		  auth_domain_hash(item),
 		  auth_domain_match(tmp, item),
-		  kfree(new); if(!set) return NULL;
+		  kfree(new); if(!set) {
+			if (new)
+				write_unlock(&auth_domain_cache.hash_lock);
+			else
+				read_unlock(&auth_domain_cache.hash_lock);
+			return NULL;
+		  }
 		  new=item; atomic_inc(&new->h.refcnt),
 		  /* no update */,
 		  0 /* no inplace updates */
--- diff/net/sunrpc/svcauth_unix.c	2003-07-08 09:55:20.000000000 +0100
+++ source/net/sunrpc/svcauth_unix.c	2004-02-23 13:56:48.000000000 +0000
@@ -119,7 +119,8 @@ static inline int ip_map_match(struct ip
 }
 static inline void ip_map_init(struct ip_map *new, struct ip_map *item)
 {
-	new->m_class = strdup(item->m_class);
+	new->m_class = item->m_class;
+	item->m_class = NULL;
 	new->m_addr.s_addr = item->m_addr.s_addr;
 }
 static inline void ip_map_update(struct ip_map *new, struct ip_map *item)
@@ -191,7 +192,9 @@ static int ip_map_parse(struct cache_det
 	} else
 		dom = NULL;
 
-	ipm.m_class = class;
+	ipm.m_class = strdup(class);
+	if (ipm.m_class == NULL)
+		return -ENOMEM;
 	ipm.m_addr.s_addr =
 		htonl((((((b1<<8)|b2)<<8)|b3)<<8)|b4);
 	ipm.h.flags = 0;
@@ -207,6 +210,7 @@ static int ip_map_parse(struct cache_det
 		ip_map_put(&ipmp->h, &ip_map_cache);
 	if (dom)
 		auth_domain_put(dom);
+	if (ipm.m_class) kfree(ipm.m_class);
 	if (!ipmp)
 		return -ENOMEM;
 	cache_flush();
@@ -266,7 +270,9 @@ int auth_unix_add_addr(struct in_addr ad
 	if (dom->flavour != RPC_AUTH_UNIX)
 		return -EINVAL;
 	udom = container_of(dom, struct unix_domain, h);
-	ip.m_class = "nfsd";
+	ip.m_class = strdup("nfsd");
+	if (!ip.m_class)
+		return -ENOMEM;
 	ip.m_addr = addr;
 	ip.m_client = udom;
 	ip.m_add_change = udom->addr_changes+1;
@@ -274,6 +280,7 @@ int auth_unix_add_addr(struct in_addr ad
 	ip.h.expiry_time = NEVER;
 	
 	ipmp = ip_map_lookup(&ip, 1);
+	if (ip.m_class) kfree(ip.m_class);
 	if (ipmp) {
 		ip_map_put(&ipmp->h, &ip_map_cache);
 		return 0;
@@ -434,11 +441,11 @@ svcauth_unix_accept(struct svc_rqst *rqs
 	if (slen > 16 || (len -= (slen + 2)*4) < 0)
 		goto badcred;
 	for (i = 0; i < slen; i++)
-		if (i < NGROUPS)
+		if (i < SVC_CRED_NGROUPS)
 			cred->cr_groups[i] = ntohl(svc_getu32(argv));
 		else
 			svc_getu32(argv);
-	if (i < NGROUPS)
+	if (i < SVC_CRED_NGROUPS)
 		cred->cr_groups[i] = NOGROUP;
 
 	if (svc_getu32(argv) != RPC_AUTH_NULL || svc_getu32(argv) != 0) {
--- diff/net/sunrpc/xprt.c	2004-02-18 08:54:13.000000000 +0000
+++ source/net/sunrpc/xprt.c	2004-02-23 13:56:48.000000000 +0000
@@ -77,6 +77,7 @@
 
 #define XPRT_MAX_BACKOFF	(8)
 #define XPRT_IDLE_TIMEOUT	(5*60*HZ)
+#define XPRT_MAX_RESVPORT	(800)
 
 /*
  * Local functions
@@ -87,7 +88,7 @@ static void	xprt_disconnect(struct rpc_x
 static void	xprt_connect_status(struct rpc_task *task);
 static struct rpc_xprt * xprt_setup(int proto, struct sockaddr_in *ap,
 						struct rpc_timeout *to);
-static struct socket *xprt_create_socket(int, struct rpc_timeout *, int);
+static struct socket *xprt_create_socket(struct rpc_xprt *, int, int);
 static void	xprt_bind_socket(struct rpc_xprt *, struct socket *);
 static int      __xprt_get_cong(struct rpc_xprt *, struct rpc_task *);
 
@@ -455,6 +456,68 @@ out_abort:
 	spin_unlock(&xprt->sock_lock);
 }
 
+static void
+xprt_socket_connect(void *args)
+{
+	struct rpc_xprt *xprt = (struct rpc_xprt *)args;
+	struct socket *sock = xprt->sock;
+	int status = -EIO;
+
+	if (xprt->shutdown) {
+		rpc_wake_up_status(&xprt->pending, -EIO);
+		return;
+	}
+	if (!xprt->addr.sin_port)
+		goto out_err;
+
+	/*
+	 * Start by resetting any existing state
+	 */
+	xprt_close(xprt);
+	sock = xprt_create_socket(xprt, xprt->prot, xprt->resvport);
+	if (sock == NULL) {
+		/* couldn't create socket or bind to reserved port;
+		 * this is likely a permanent error, so cause an abort */
+		goto out_err;
+		return;
+	}
+	xprt_bind_socket(xprt, sock);
+	xprt_sock_setbufsize(xprt);
+
+	if (!xprt->stream)
+		goto out;
+
+	/*
+	 * Tell the socket layer to start connecting...
+	 */
+	status = sock->ops->connect(sock, (struct sockaddr *) &xprt->addr,
+			sizeof(xprt->addr), O_NONBLOCK);
+	dprintk("RPC: %p  connect status %d connected %d sock state %d\n",
+			xprt, -status, xprt_connected(xprt), sock->sk->sk_state);
+	if (status >= 0)
+		goto out;
+	switch (status) {
+		case -EINPROGRESS:
+		case -EALREADY:
+			return;
+		default:
+			goto out_err;
+	}
+out:
+	spin_lock_bh(&xprt->sock_lock);
+	if (xprt->snd_task)
+		rpc_wake_up_task(xprt->snd_task);
+	spin_unlock_bh(&xprt->sock_lock);
+	return;
+out_err:
+	spin_lock_bh(&xprt->sock_lock);
+	if (xprt->snd_task) {
+		xprt->snd_task->tk_status = status;
+		rpc_wake_up_task(xprt->snd_task);
+	}
+	spin_unlock_bh(&xprt->sock_lock);
+}
+
 /*
  * Attempt to connect a TCP socket.
  *
@@ -463,9 +526,6 @@ void
 xprt_connect(struct rpc_task *task)
 {
 	struct rpc_xprt	*xprt = task->tk_xprt;
-	struct socket	*sock = xprt->sock;
-	struct sock	*inet;
-	int		status;
 
 	dprintk("RPC: %4d xprt_connect xprt %p %s connected\n", task->tk_pid,
 			xprt, (xprt_connected(xprt) ? "is" : "is not"));
@@ -486,79 +546,9 @@ xprt_connect(struct rpc_task *task)
 	if (task->tk_rqstp)
 		task->tk_rqstp->rq_bytes_sent = 0;
 
-	/*
-	 * We're here because the xprt was marked disconnected.
-	 * Start by resetting any existing state.
-	 */
-	xprt_close(xprt);
-	if (!(sock = xprt_create_socket(xprt->prot, &xprt->timeout, xprt->resvport))) {
-		/* couldn't create socket or bind to reserved port;
-		 * this is likely a permanent error, so cause an abort */
-		task->tk_status = -EIO;
-		goto out_write;
-	}
-	xprt_bind_socket(xprt, sock);
-	xprt_sock_setbufsize(xprt);
-
-	if (!xprt->stream)
-		goto out_write;
-
-	inet = sock->sk;
-
-	/*
-	 * Tell the socket layer to start connecting...
-	 */
-	status = sock->ops->connect(sock, (struct sockaddr *) &xprt->addr,
-				sizeof(xprt->addr), O_NONBLOCK);
-	dprintk("RPC: %4d  connect status %d connected %d sock state %d\n",
-		task->tk_pid, -status, xprt_connected(xprt), inet->sk_state);
-
-	if (status >= 0)
-		return;
-
-	switch (status) {
-	case -EINPROGRESS:
-	case -EALREADY:
-		/* Protect against TCP socket state changes */
-		lock_sock(inet);
-		if (inet->sk_state != TCP_ESTABLISHED) {
-			dprintk("RPC: %4d  waiting for connection\n",
-					task->tk_pid);
-			task->tk_timeout = RPC_CONNECT_TIMEOUT;
-			/* if the socket is already closing, delay briefly */
-			if ((1 << inet->sk_state) &
-			    ~(TCPF_SYN_SENT | TCPF_SYN_RECV))
-				task->tk_timeout = RPC_REESTABLISH_TIMEOUT;
-			rpc_sleep_on(&xprt->pending, task, xprt_connect_status,
-									NULL);
-		}
-		release_sock(inet);
-		break;
-	case -ECONNREFUSED:
-	case -ECONNRESET:
-	case -ENOTCONN:
-		if (!RPC_IS_SOFT(task)) {
-			rpc_delay(task, RPC_REESTABLISH_TIMEOUT);
-			task->tk_status = -ENOTCONN;
-			break;
-		}
-	default:
-		/* Report myriad other possible returns.  If this file
-		 * system is soft mounted, just error out, like Solaris.  */
-		if (RPC_IS_SOFT(task)) {
-			printk(KERN_WARNING
-			"RPC: error %d connecting to server %s, exiting\n",
-					-status, task->tk_client->cl_server);
-			task->tk_status = -EIO;
-			goto out_write;
-		}
-		printk(KERN_WARNING "RPC: error %d connecting to server %s\n",
-				-status, task->tk_client->cl_server);
-		/* This will prevent anybody else from reconnecting */
-		rpc_delay(task, RPC_REESTABLISH_TIMEOUT);
-		task->tk_status = status;
-		break;
-	}
+	task->tk_timeout = RPC_CONNECT_TIMEOUT;
+	rpc_sleep_on(&xprt->pending, task, xprt_connect_status, NULL);
+	schedule_work(&xprt->sock_connect);
 	return;
  out_write:
 	xprt_release_write(xprt, task);
@@ -583,6 +573,8 @@ xprt_connect_status(struct rpc_task *tas
 		task->tk_status = -EIO;
 
 	switch (task->tk_status) {
+	case -ECONNREFUSED:
+	case -ECONNRESET:
 	case -ENOTCONN:
 		rpc_delay(task, RPC_REESTABLISH_TIMEOUT);
 		return;
@@ -1457,11 +1449,13 @@ xprt_setup(int proto, struct sockaddr_in
 	init_waitqueue_head(&xprt->cong_wait);
 
 	INIT_LIST_HEAD(&xprt->recv);
+	INIT_WORK(&xprt->sock_connect, xprt_socket_connect, xprt);
 	INIT_WORK(&xprt->task_cleanup, xprt_socket_autoclose, xprt);
 	init_timer(&xprt->timer);
 	xprt->timer.function = xprt_init_autodisconnect;
 	xprt->timer.data = (unsigned long) xprt;
 	xprt->last_used = jiffies;
+	xprt->port = XPRT_MAX_RESVPORT;
 
 	/* Set timeout parameters */
 	if (to) {
@@ -1493,30 +1487,28 @@ xprt_setup(int proto, struct sockaddr_in
  * Bind to a reserved port
  */
 static inline int
-xprt_bindresvport(struct socket *sock)
+xprt_bindresvport(struct rpc_xprt *xprt, struct socket *sock)
 {
-	struct sockaddr_in myaddr;
+	struct sockaddr_in myaddr = {
+		.sin_family = AF_INET,
+	};
 	int		err, port;
-	kernel_cap_t saved_cap = current->cap_effective;
 
-	/* Override capabilities.
-	 * They were checked in xprt_create_proto i.e. at mount time
-	 */
-	cap_raise(current->cap_effective, CAP_NET_BIND_SERVICE);
-
-	memset(&myaddr, 0, sizeof(myaddr));
-	myaddr.sin_family = AF_INET;
-	port = 800;
+	/* Were we already bound to a given port? Try to reuse it */
+	port = xprt->port;
 	do {
 		myaddr.sin_port = htons(port);
 		err = sock->ops->bind(sock, (struct sockaddr *) &myaddr,
 						sizeof(myaddr));
-	} while (err == -EADDRINUSE && --port > 0);
-	current->cap_effective = saved_cap;
-
-	if (err < 0)
-		printk("RPC: Can't bind to reserved port (%d).\n", -err);
+		if (err == 0) {
+			xprt->port = port;
+			return 0;
+		}
+		if (--port == 0)
+			port = XPRT_MAX_RESVPORT;
+	} while (err == -EADDRINUSE && port != xprt->port);
 
+	printk("RPC: Can't bind to reserved port (%d).\n", -err);
 	return err;
 }
 
@@ -1580,7 +1572,7 @@ xprt_sock_setbufsize(struct rpc_xprt *xp
  * and connect stream sockets.
  */
 static struct socket *
-xprt_create_socket(int proto, struct rpc_timeout *to, int resvport)
+xprt_create_socket(struct rpc_xprt *xprt, int proto, int resvport)
 {
 	struct socket	*sock;
 	int		type, err;
@@ -1596,7 +1588,7 @@ xprt_create_socket(int proto, struct rpc
 	}
 
 	/* If the caller has the capability, bind to a reserved port */
-	if (resvport && xprt_bindresvport(sock) < 0) {
+	if (resvport && xprt_bindresvport(xprt, sock) < 0) {
 		printk("RPC: can't bind to reserved port.\n");
 		goto failed;
 	}
--- diff/net/sysctl_net.c	2002-10-16 04:29:05.000000000 +0100
+++ source/net/sysctl_net.c	2004-02-23 13:56:48.000000000 +0000
@@ -26,10 +26,6 @@ extern struct ctl_table core_table[];
 extern struct ctl_table ether_table[];
 #endif
 
-#ifdef CONFIG_IPV6
-extern struct ctl_table ipv6_table[];
-#endif
-
 #ifdef CONFIG_TR
 extern struct ctl_table tr_table[];
 #endif
@@ -57,14 +53,6 @@ struct ctl_table net_table[] = {
 		.child		= ipv4_table
 	},
 #endif
-#ifdef CONFIG_IPV6
-	{
-		.ctl_name	= NET_IPV6,
-		.procname	= "ipv6",
-		.mode		= 0555,
-		.child		= ipv6_table,
-	},
-#endif
 #ifdef CONFIG_TR
 	{
 		.ctl_name	= NET_TR,
--- diff/net/wanrouter/wanproc.c	2003-09-30 15:46:21.000000000 +0100
+++ source/net/wanrouter/wanproc.c	2004-02-23 13:56:48.000000000 +0000
@@ -207,7 +207,7 @@ static struct file_operations status_fop
 
 static int wandev_show(struct seq_file *m, void *v)
 {
-	struct wan_device *wandev = v;
+	struct wan_device *wandev = m->private;
 
 	if (wandev->magic != ROUTER_MAGIC)
 		return 0;
--- diff/scripts/Makefile	2003-09-30 15:46:21.000000000 +0100
+++ source/scripts/Makefile	2004-02-23 13:56:48.000000000 +0000
@@ -12,7 +12,7 @@ host-progs	:= fixdep split-include conma
 		   mk_elfconfig pnmtologo bin2c
 always		:= $(host-progs) empty.o
 
-modpost-objs	:= modpost.o file2alias.o
+modpost-objs	:= modpost.o file2alias.o sumversion.o
 
 subdir-$(CONFIG_MODVERSIONS)	+= genksyms
 
--- diff/scripts/Makefile.build	2003-10-09 09:47:34.000000000 +0100
+++ source/scripts/Makefile.build	2004-02-23 13:56:48.000000000 +0000
@@ -64,8 +64,6 @@ endif
 
 # We keep a list of all modules in $(MODVERDIR)
 
-touch-module = @echo $(@:.o=.ko) > $(MODVERDIR)/$(@F:.o=.mod)
-
 __build: $(if $(KBUILD_BUILTIN),$(builtin-target) $(lib-target) $(extra-y)) \
 	 $(if $(KBUILD_MODULES),$(obj-m)) \
 	 $(subdir-ym) $(always)
@@ -178,7 +176,7 @@ endef
 
 $(single-used-m): %.o: %.c FORCE
 	$(call if_changed_rule,cc_o_c)
-	$(touch-module)
+	@{ echo $(@:.o=.ko); echo $<; } > $(MODVERDIR)/$(@F:.o=.mod)
 
 quiet_cmd_cc_lst_c = MKLST   $@
       cmd_cc_lst_c = $(CC) $(c_flags) -g -c -o $*.o $< && \
@@ -273,7 +271,7 @@ $(multi-used-y) : %.o: $(multi-objs-y) F
 
 $(multi-used-m) : %.o: $(multi-objs-m) FORCE
 	$(call if_changed,link_multi-m)
-	$(touch-module)
+	@{ echo $(@:.o=.ko); echo $(link_multi_deps:.o=.c); } > $(MODVERDIR)/$(@F:.o=.mod)
 
 targets += $(multi-used-y) $(multi-used-m)
 
--- diff/scripts/Makefile.modpost	2003-09-30 15:46:21.000000000 +0100
+++ source/scripts/Makefile.modpost	2004-02-23 13:56:48.000000000 +0000
@@ -10,10 +10,11 @@ include scripts/Makefile.lib
 
 #
 
-__modules := $(shell cat /dev/null $(wildcard $(MODVERDIR)/*.mod))
+__modules := $(shell head -q -n1 /dev/null $(wildcard $(MODVERDIR)/*.mod))
 modules := $(patsubst %.o,%.ko,$(wildcard $(__modules:.ko=.o)))
 
 ifneq ($(filter-out $(modules),$(__modules)),)
+  $(warning Trouble: $(__modules) )
   $(warning *** Uh-oh, you have stale module entries. You messed with SUBDIRS,)
   $(warning     do not complain if something goes wrong.)
 endif
--- diff/scripts/kconfig/Makefile	2003-09-30 15:46:21.000000000 +0100
+++ source/scripts/kconfig/Makefile	2004-02-23 13:56:48.000000000 +0000
@@ -95,7 +95,7 @@ clean-files	:= libkconfig.so lkc_defs.h 
 HOSTCFLAGS_lex.zconf.o	:= -I$(src)
 HOSTCFLAGS_zconf.tab.o	:= -I$(src)
 
-HOSTLOADLIBES_qconf	= -L$(QTDIR)/lib -Wl,-rpath,$(QTDIR)/lib -l$(QTLIB) -ldl
+HOSTLOADLIBES_qconf	= -L$(QTDIR)/lib -L$(QTDIR)/lib64 -Wl,-rpath,$(QTDIR)/lib -l$(QTLIB) -ldl
 HOSTCXXFLAGS_qconf.o	= -I$(QTDIR)/include 
 
 HOSTLOADLIBES_gconf	= `pkg-config gtk+-2.0 gmodule-2.0 libglade-2.0 --libs`
--- diff/scripts/lxdialog/Makefile	2003-05-21 11:49:51.000000000 +0100
+++ source/scripts/lxdialog/Makefile	2004-02-23 13:56:48.000000000 +0000
@@ -16,15 +16,13 @@ endif
 endif
 
 host-progs	:= lxdialog
-always		:= $(host-progs)
+always		:= ncurses $(host-progs)
 
 lxdialog-objs := checklist.o menubox.o textbox.o yesno.o inputbox.o \
 		 util.o lxdialog.o msgbox.o
 
-first_rule: ncurses
-
-.PHONY: ncurses
-ncurses:
+.PHONY: $(obj)/ncurses
+$(obj)/ncurses:
 	@echo "main() {}" > lxtemp.c
 	@if $(HOSTCC) lxtemp.c  $(HOST_LOADLIBES); then \
 		rm -f lxtemp.c a.out; \
@@ -33,7 +31,7 @@ ncurses:
 		echo -e "\007" ;\
 		echo ">> Unable to find the Ncurses libraries." ;\
 		echo ">>" ;\
-		echo ">> You must have Ncurses installed in order" ;\
+		echo ">> You must install ncurses-devel in order" ;\
 		echo ">> to use 'make menuconfig'" ;\
 		echo ;\
 		exit 1 ;\
--- diff/scripts/mkspec	2004-01-19 10:22:59.000000000 +0000
+++ source/scripts/mkspec	2004-02-23 13:56:48.000000000 +0000
@@ -37,6 +37,7 @@ echo "$EXTRAVERSION.tar.gz" | sed -e "s/
 echo "BuildRoot: /var/tmp/%{name}-%{PACKAGE_VERSION}-root"
 echo "Provides: $PROVIDES"
 echo "%define __spec_install_post /usr/lib/rpm/brp-compress || :"
+echo "%define debug_package %{nil}"
 echo ""
 echo "%description"
 echo "The Linux Kernel, the operating system core itself"
--- diff/scripts/modpost.c	2004-02-18 08:54:13.000000000 +0000
+++ source/scripts/modpost.c	2004-02-23 13:56:48.000000000 +0000
@@ -65,15 +65,15 @@ new_module(char *modname)
 	struct module *mod;
 	char *p;
 	
+	mod = NOFAIL(malloc(sizeof(*mod)));
+	memset(mod, 0, sizeof(*mod));
+	mod->name = NOFAIL(strdup(modname));
+
 	/* strip trailing .o */
-	p = strstr(modname, ".o");
+	p = strstr(mod->name, ".o");
 	if (p)
 		*p = 0;
 
-	mod = NOFAIL(malloc(sizeof(*mod)));
-	memset(mod, 0, sizeof(*mod));
-	mod->name = modname;
-
 	/* add to list */
 	mod->next = modules;
 	modules = mod;
@@ -194,26 +194,25 @@ grab_file(const char *filename, unsigned
 	int fd;
 
 	fd = open(filename, O_RDONLY);
-	if (fd < 0) {
-		perror(filename);
-		abort();
-	}
-	if (fstat(fd, &st) != 0) {
-		perror(filename);
-		abort();
-	}
+	if (fstat(fd, &st) != 0)
+		return NULL;
 
 	*size = st.st_size;
 	map = mmap(NULL, *size, PROT_READ|PROT_WRITE, MAP_PRIVATE, fd, 0);
-	if (map == MAP_FAILED) {
-		perror(filename);
-		abort();
-	}
 	close(fd);
+
+	if (map == MAP_FAILED)
+		return NULL;
 	return map;
 }
 
 void
+release_file(void *file, unsigned long size)
+{
+	munmap(file, size);
+}
+
+void
 parse_elf(struct elf_info *info, const char *filename)
 {
 	unsigned int i;
@@ -222,6 +221,10 @@ parse_elf(struct elf_info *info, const c
 	Elf_Sym  *sym;
 
 	hdr = grab_file(filename, &info->size);
+	if (!hdr) {
+		perror(filename);
+		abort();
+	}
 	info->hdr = hdr;
 	if (info->size < sizeof(*hdr))
 		goto truncated;
@@ -239,11 +242,19 @@ parse_elf(struct elf_info *info, const c
 		sechdrs[i].sh_offset = TO_NATIVE(sechdrs[i].sh_offset);
 		sechdrs[i].sh_size   = TO_NATIVE(sechdrs[i].sh_size);
 		sechdrs[i].sh_link   = TO_NATIVE(sechdrs[i].sh_link);
+		sechdrs[i].sh_name   = TO_NATIVE(sechdrs[i].sh_name);
 	}
 	/* Find symbol table. */
 	for (i = 1; i < hdr->e_shnum; i++) {
+		const char *secstrings
+			= (void *)hdr + sechdrs[hdr->e_shstrndx].sh_offset;
+
 		if (sechdrs[i].sh_offset > info->size)
 			goto truncated;
+		if (strcmp(secstrings+sechdrs[i].sh_name, ".modinfo") == 0) {
+			info->modinfo = (void *)hdr + sechdrs[i].sh_offset;
+			info->modinfo_len = sechdrs[i].sh_size;
+		}
 		if (sechdrs[i].sh_type != SHT_SYMTAB)
 			continue;
 
@@ -274,7 +285,7 @@ parse_elf(struct elf_info *info, const c
 void
 parse_elf_finish(struct elf_info *info)
 {
-	munmap(info->hdr, info->size);
+	release_file(info->hdr, info->size);
 }
 
 #define CRC_PFX     MODULE_SYMBOL_PREFIX "__crc_"
@@ -372,6 +383,8 @@ read_symbols(char *modname)
 		handle_modversions(mod, &info, sym, symname);
 		handle_moddevtable(mod, &info, sym, symname);
 	}
+	maybe_frob_version(modname, info.modinfo, info.modinfo_len,
+			   (void *)info.modinfo - (void *)info.hdr);
 	parse_elf_finish(&info);
 
 	/* Our trick to get versioning for struct_module - it's
--- diff/scripts/modpost.h	2003-05-21 11:50:01.000000000 +0100
+++ source/scripts/modpost.h	2004-02-23 13:56:48.000000000 +0000
@@ -80,9 +80,19 @@ struct elf_info {
 	Elf_Sym      *symtab_start;
 	Elf_Sym      *symtab_stop;
 	const char   *strtab;
+	char	     *modinfo;
+	unsigned int modinfo_len;
 };
 
 void handle_moddevtable(struct module *mod, struct elf_info *info,
 			Elf_Sym *sym, const char *symname);
 
 void add_moddevtable(struct buffer *buf, struct module *mod);
+
+void maybe_frob_version(const char *modfilename,
+			void *modinfo,
+			unsigned long modinfo_len,
+			unsigned long modinfo_offset);
+
+void *grab_file(const char *filename, unsigned long *size);
+void release_file(void *file, unsigned long size);
--- diff/security/dummy.c	2004-02-18 08:54:13.000000000 +0000
+++ source/security/dummy.c	2004-02-23 13:56:48.000000000 +0000
@@ -544,7 +544,7 @@ static int dummy_task_getsid (struct tas
 	return 0;
 }
 
-static int dummy_task_setgroups (int gidsetsize, gid_t * grouplist)
+static int dummy_task_setgroups (struct group_info *group_info)
 {
 	return 0;
 }
--- diff/security/selinux/Makefile	2004-02-09 10:36:12.000000000 +0000
+++ source/security/selinux/Makefile	2004-02-23 13:56:48.000000000 +0000
@@ -4,7 +4,7 @@
 
 obj-$(CONFIG_SECURITY_SELINUX) := selinux.o ss/
 
-selinux-y := avc.o hooks.o selinuxfs.o
+selinux-y := avc.o hooks.o selinuxfs.o netlink.o
 
 selinux-$(CONFIG_SECURITY_NETWORK) += netif.o
 
--- diff/security/selinux/hooks.c	2004-02-18 08:54:13.000000000 +0000
+++ source/security/selinux/hooks.c	2004-02-23 13:56:48.000000000 +0000
@@ -34,6 +34,7 @@
 #include <linux/swap.h>
 #include <linux/smp_lock.h>
 #include <linux/spinlock.h>
+#include <linux/syscalls.h>
 #include <linux/file.h>
 #include <linux/namei.h>
 #include <linux/mount.h>
@@ -750,6 +751,7 @@ static int inode_doinit_with_dentry(stru
 			       inode->i_ino);
 			goto out;
 		}
+               BUG_ON(inode != dentry->d_inode);
 
 		len = INITCONTEXTLEN;
 		context = kmalloc(len, GFP_KERNEL);
@@ -2539,7 +2541,7 @@ static int selinux_task_getsid(struct ta
 	return task_has_perm(current, p, PROCESS__GETSESSION);
 }
 
-static int selinux_task_setgroups(int gidsetsize, gid_t *grouplist)
+static int selinux_task_setgroups(struct group_info *group_info)
 {
 	/* See the comment for setuid above. */
 	return 0;
--- diff/security/selinux/selinuxfs.c	2004-02-18 08:54:13.000000000 +0000
+++ source/security/selinux/selinuxfs.c	2004-02-23 13:56:48.000000000 +0000
@@ -17,6 +17,8 @@
 #include "security.h"
 #include "objsec.h"
 
+extern void selnl_notify_setenforce(int val);
+
 /* Check whether a task is allowed to use a security operation. */
 int task_has_security(struct task_struct *tsk,
 		      u32 perms)
@@ -54,7 +56,7 @@ static ssize_t sel_read_enforce(struct f
 		return -ENOMEM;
 	memset(page, 0, PAGE_SIZE);
 
-	length = snprintf(page, PAGE_SIZE, "%d", selinux_enforcing);
+	length = scnprintf(page, PAGE_SIZE, "%d", selinux_enforcing);
 	if (length < 0) {
 		free_page((unsigned long)page);
 		return length;
@@ -111,6 +113,7 @@ static ssize_t sel_write_enforce(struct 
 		selinux_enforcing = new_value;
 		if (selinux_enforcing)
 			avc_ss_reset(0);
+		selnl_notify_setenforce(selinux_enforcing);
 	}
 	length = count;
 out:
@@ -139,7 +142,7 @@ static ssize_t sel_read_policyvers(struc
 		return -ENOMEM;
 	memset(page, 0, PAGE_SIZE);
 
-	length = snprintf(page, PAGE_SIZE, "%u", POLICYDB_VERSION);
+	length = scnprintf(page, PAGE_SIZE, "%u", POLICYDB_VERSION);
 	if (length < 0) {
 		free_page((unsigned long)page);
 		return length;
@@ -404,7 +407,7 @@ static ssize_t sel_write_access(struct f
 	if (length < 0)
 		goto out2;
 
-	length = snprintf(buf, PAYLOAD_SIZE, "%x %x %x %x %u",
+	length = scnprintf(buf, PAYLOAD_SIZE, "%x %x %x %x %u",
 			  avd.allowed, avd.decided,
 			  avd.auditallow, avd.auditdeny,
 			  avd.seqno);
--- diff/security/selinux/ss/services.c	2004-02-18 08:54:13.000000000 +0000
+++ source/security/selinux/ss/services.c	2004-02-23 13:56:48.000000000 +0000
@@ -28,6 +28,8 @@
 #include "services.h"
 #include "mls.h"
 
+extern void selnl_notify_policyload(u32 seqno);
+
 static rwlock_t policy_rwlock = RW_LOCK_UNLOCKED;
 #define POLICY_RDLOCK read_lock(&policy_rwlock)
 #define POLICY_WRLOCK write_lock_irq(&policy_rwlock)
@@ -1052,6 +1054,7 @@ int security_load_policy(void *data, siz
 	sidtab_destroy(&oldsidtab);
 
 	avc_ss_reset(seqno);
+	selnl_notify_policyload(seqno);
 
 	return 0;
 
--- diff/sound/core/Makefile	2004-02-18 08:54:13.000000000 +0000
+++ source/sound/core/Makefile	2004-02-23 13:56:48.000000000 +0000
@@ -107,5 +107,6 @@ obj-$(CONFIG_SND_VXPOCKET) += snd-pcm.o 
 obj-$(CONFIG_SND_VXP440) += snd-pcm.o snd-timer.o snd-page-alloc.o snd.o snd-hwdep.o
 obj-$(CONFIG_SND_VX222) += snd-pcm.o snd-timer.o snd-page-alloc.o snd.o snd-hwdep.o
 obj-$(CONFIG_SND_BT87X) += snd-pcm.o snd-timer.o snd-page-alloc.o snd.o
+obj-$(CONFIG_SND_MIXART) += snd-pcm.o snd-timer.o snd-page-alloc.o snd.o snd-hwdep.o
 
 obj-m := $(sort $(obj-m))
--- diff/sound/core/info.c	2003-09-30 15:46:21.000000000 +0100
+++ source/sound/core/info.c	2004-02-23 13:56:48.000000000 +0000
@@ -99,7 +99,7 @@ int snd_iprintf(snd_info_buffer_t * buff
 	if (buffer->stop || buffer->error)
 		return 0;
 	va_start(args, fmt);
-	res = vsnprintf(sbuffer, sizeof(sbuffer), fmt, args);
+	res = vscnprintf(sbuffer, sizeof(sbuffer), fmt, args);
 	va_end(args);
 	if (buffer->size + res >= buffer->len) {
 		buffer->stop = 1;
--- diff/sound/core/oss/pcm_oss.c	2004-02-18 08:54:13.000000000 +0000
+++ source/sound/core/oss/pcm_oss.c	2004-02-23 13:56:48.000000000 +0000
@@ -133,6 +133,15 @@ static long snd_pcm_oss_bytes(snd_pcm_su
 	return (runtime->oss.buffer_bytes * frames) / buffer_size;
 }
 
+static long snd_pcm_alsa_frames(snd_pcm_substream_t *substream, long bytes)
+{
+	snd_pcm_runtime_t *runtime = substream->runtime;
+	snd_pcm_uframes_t buffer_size = snd_pcm_lib_buffer_bytes(substream);
+	if (buffer_size == runtime->oss.buffer_bytes)
+		return bytes_to_frames(runtime, bytes);
+	return bytes_to_frames(runtime, (buffer_size * bytes) / runtime->oss.buffer_bytes);
+}
+
 static int snd_pcm_oss_format_from(int format)
 {
 	switch (format) {
@@ -254,6 +263,7 @@ static int snd_pcm_oss_period_size(snd_p
 
 	snd_assert(oss_period_size >= 16, return -EINVAL);
 	runtime->oss.period_bytes = oss_period_size;
+	runtime->oss.period_frames = 1;
 	runtime->oss.periods = oss_periods;
 	return 0;
 }
@@ -511,6 +521,8 @@ static int snd_pcm_oss_change_params(snd
 	if (runtime->dma_area)
 		snd_pcm_format_set_silence(runtime->format, runtime->dma_area, bytes_to_samples(runtime, runtime->dma_bytes));
 
+	runtime->oss.period_frames = snd_pcm_alsa_frames(substream, oss_period_size);
+
 	err = 0;
 failure:
 	if (sw_params)
@@ -2098,7 +2110,7 @@ static int snd_pcm_oss_playback_ready(sn
 	if (atomic_read(&runtime->mmap_count))
 		return runtime->oss.prev_hw_ptr_interrupt != runtime->hw_ptr_interrupt;
 	else
-		return snd_pcm_playback_ready(substream);
+		return snd_pcm_playback_avail(runtime) >= runtime->oss.period_frames;
 }
 
 static int snd_pcm_oss_capture_ready(snd_pcm_substream_t *substream)
@@ -2107,7 +2119,7 @@ static int snd_pcm_oss_capture_ready(snd
 	if (atomic_read(&runtime->mmap_count))
 		return runtime->oss.prev_hw_ptr_interrupt != runtime->hw_ptr_interrupt;
 	else
-		return snd_pcm_capture_ready(substream);
+		return snd_pcm_capture_avail(runtime) >= runtime->oss.period_frames;
 }
 
 static unsigned int snd_pcm_oss_poll(struct file *file, poll_table * wait)
--- diff/sound/core/pcm.c	2004-02-18 08:54:13.000000000 +0000
+++ source/sound/core/pcm.c	2004-02-23 13:56:48.000000000 +0000
@@ -327,8 +327,9 @@ static void snd_pcm_substream_proc_hw_pa
 		snd_iprintf(buffer, "OSS format: %s\n", snd_pcm_oss_format_name(runtime->oss.format));
 		snd_iprintf(buffer, "OSS channels: %u\n", runtime->oss.channels);	
 		snd_iprintf(buffer, "OSS rate: %u\n", runtime->oss.rate);
-		snd_iprintf(buffer, "OSS period bytes: %lu\n", (unsigned long)runtime->oss.period_bytes);	
+		snd_iprintf(buffer, "OSS period bytes: %lu\n", (unsigned long)runtime->oss.period_bytes);
 		snd_iprintf(buffer, "OSS periods: %u\n", runtime->oss.periods);
+		snd_iprintf(buffer, "OSS period frames: %lu\n", (unsigned long)runtime->oss.period_frames);
 	}
 #endif
 	snd_pcm_stream_unlock_irq(substream);
--- diff/sound/core/seq/oss/seq_oss_midi.c	2003-06-09 14:18:21.000000000 +0100
+++ source/sound/core/seq/oss/seq_oss_midi.c	2004-02-23 13:56:48.000000000 +0000
@@ -491,7 +491,7 @@ snd_seq_oss_midi_reset(seq_oss_devinfo_t
 			}
 		}
 	}
-	snd_seq_oss_midi_close(dp, dev);
+	// snd_seq_oss_midi_close(dp, dev);
 	snd_use_lock_free(&mdev->use_lock);
 }
 
--- diff/sound/core/seq/oss/seq_oss_synth.c	2003-06-09 14:18:21.000000000 +0100
+++ source/sound/core/seq/oss/seq_oss_synth.c	2004-02-23 13:56:48.000000000 +0000
@@ -410,6 +410,8 @@ snd_seq_oss_synth_reset(seq_oss_devinfo_
 		if (midi_synth_dev.opened <= 0)
 			return;
 		snd_seq_oss_midi_reset(dp, info->midi_mapped);
+		/* reopen the device */
+		snd_seq_oss_midi_close(dp, dev);
 		if (snd_seq_oss_midi_open(dp, info->midi_mapped,
 					  dp->file_mode) < 0) {
 			midi_synth_dev.opened--;
--- diff/sound/core/seq/seq_dummy.c	2004-02-18 08:54:13.000000000 +0000
+++ source/sound/core/seq/seq_dummy.c	2004-02-23 13:56:48.000000000 +0000
@@ -46,7 +46,7 @@
 
   The number of ports to be created can be specified via the module
   parameter "ports".  For example, to create four ports, add the
-  following option in /etc/modules.conf:
+  following option in /etc/modprobe.conf:
 
 	option snd-seq-dummy ports=4
 
--- diff/sound/core/seq/seq_fifo.c	2004-02-18 08:54:13.000000000 +0000
+++ source/sound/core/seq/seq_fifo.c	2004-02-23 13:56:48.000000000 +0000
@@ -171,10 +171,12 @@ int snd_seq_fifo_cell_out(fifo_t *f, snd
 {
 	snd_seq_event_cell_t *cell;
 	unsigned long flags;
+	wait_queue_t wait;
 
 	snd_assert(f != NULL, return -EINVAL);
 
 	*cellp = NULL;
+	init_waitqueue_entry(&wait, current);
 	spin_lock_irqsave(&f->lock, flags);
 	while ((cell = fifo_cell_out(f)) == NULL) {
 		if (nonblock) {
@@ -182,17 +184,19 @@ int snd_seq_fifo_cell_out(fifo_t *f, snd
 			spin_unlock_irqrestore(&f->lock, flags);
 			return -EAGAIN;
 		}
-		spin_unlock(&f->lock);
-		interruptible_sleep_on(&f->input_sleep);
-		spin_lock(&f->lock);
-
+		set_current_state(TASK_INTERRUPTIBLE);
+		add_wait_queue(&f->input_sleep, &wait);
+		spin_unlock_irq(&f->lock);
+		schedule();
+		spin_lock_irq(&f->lock);
+		remove_wait_queue(&f->input_sleep, &wait);
 		if (signal_pending(current)) {
 			spin_unlock_irqrestore(&f->lock, flags);
 			return -ERESTARTSYS;
 		}
 	}
-	*cellp = cell;
 	spin_unlock_irqrestore(&f->lock, flags);
+	*cellp = cell;
 
 	return 0;
 }
--- diff/sound/core/seq/seq_memory.c	2004-02-18 08:54:13.000000000 +0000
+++ source/sound/core/seq/seq_memory.c	2004-02-23 13:56:48.000000000 +0000
@@ -220,12 +220,14 @@ int snd_seq_cell_alloc(pool_t *pool, snd
 	snd_seq_event_cell_t *cell;
 	unsigned long flags;
 	int err = -EAGAIN;
+	wait_queue_t wait;
 
 	if (pool == NULL)
 		return -EINVAL;
 
 	*cellp = NULL;
 
+	init_waitqueue_entry(&wait, current);
 	spin_lock_irqsave(&pool->lock, flags);
 	if (pool->ptr == NULL) {	/* not initialized */
 		snd_printd("seq: pool is not initialized\n");
@@ -234,9 +236,12 @@ int snd_seq_cell_alloc(pool_t *pool, snd
 	}
 	while (pool->free == NULL && ! nonblock && ! pool->closing) {
 
-		spin_unlock(&pool->lock);
-		interruptible_sleep_on(&pool->output_sleep);
-		spin_lock(&pool->lock);
+		set_current_state(TASK_INTERRUPTIBLE);
+		add_wait_queue(&pool->output_sleep, &wait);
+		spin_unlock_irq(&pool->lock);
+		schedule();
+		spin_lock_irq(&pool->lock);
+		remove_wait_queue(&pool->output_sleep, &wait);
 		/* interrupted? */
 		if (signal_pending(current)) {
 			err = -ERESTARTSYS;
--- diff/sound/drivers/vx/vx_core.c	2004-02-18 08:54:13.000000000 +0000
+++ source/sound/drivers/vx/vx_core.c	2004-02-23 13:56:48.000000000 +0000
@@ -355,11 +355,12 @@ int vx_send_msg_nolock(vx_core_t *chip, 
  */
 int vx_send_msg(vx_core_t *chip, struct vx_rmh *rmh)
 {
+	unsigned long flags;
 	int err;
 
-	spin_lock_bh(&chip->lock);
+	spin_lock_irqsave(&chip->lock, flags);
 	err = vx_send_msg_nolock(chip, rmh);
-	spin_unlock_bh(&chip->lock);
+	spin_unlock_irqrestore(&chip->lock, flags);
 	return err;
 }
 
@@ -414,11 +415,12 @@ int vx_send_rih_nolock(vx_core_t *chip, 
  */
 int vx_send_rih(vx_core_t *chip, int cmd)
 {
+	unsigned long flags;
 	int err;
 
-	spin_lock_bh(&chip->lock);
+	spin_lock_irqsave(&chip->lock, flags);
 	err = vx_send_rih_nolock(chip, cmd);
-	spin_unlock_bh(&chip->lock);
+	spin_unlock_irqrestore(&chip->lock, flags);
 	return err;
 }
 
--- diff/sound/drivers/vx/vx_mixer.c	2003-06-30 10:07:24.000000000 +0100
+++ source/sound/drivers/vx/vx_mixer.c	2004-02-23 13:56:48.000000000 +0000
@@ -919,7 +919,7 @@ int snd_vx_mixer_new(vx_core_t *chip)
 	if ((err = snd_ctl_add(card, snd_ctl_new1(&vx_control_iec958, chip))) < 0)
 		return err;
 	/* VU, peak, saturation meters */
-	for (c = 0; c < 1; c++) {
+	for (c = 0; c < 2; c++) {
 		static char *dir[2] = { "Output", "Input" };
 		for (i = 0; i < chip->hw->num_ins; i++) {
 			int val = (i * 2) | (c << 8);
--- diff/sound/drivers/vx/vx_pcm.c	2004-02-18 08:54:13.000000000 +0000
+++ source/sound/drivers/vx/vx_pcm.c	2004-02-23 13:56:48.000000000 +0000
@@ -561,7 +561,7 @@ static snd_pcm_hardware_t vx_pcm_playbac
 	.rates =		SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_48000,
 	.rate_min =		5000,
 	.rate_max =		48000,
-	.channels_min =		2,
+	.channels_min =		1,
 	.channels_max =		2,
 	.buffer_bytes_max =	(128*1024),
 	.period_bytes_min =	126,
@@ -958,7 +958,7 @@ static snd_pcm_hardware_t vx_pcm_capture
 	.rates =		SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_48000,
 	.rate_min =		5000,
 	.rate_max =		48000,
-	.channels_min =		2,
+	.channels_min =		1,
 	.channels_max =		2,
 	.buffer_bytes_max =	(128*1024),
 	.period_bytes_min =	126,
--- diff/sound/oss/msnd.c	2002-10-16 04:27:50.000000000 +0100
+++ source/sound/oss/msnd.c	2004-02-23 13:56:48.000000000 +0000
@@ -25,9 +25,6 @@
  ********************************************************************/
 
 #include <linux/version.h>
-#if LINUX_VERSION_CODE < 0x020101
-#  define LINUX20
-#endif
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/slab.h>
@@ -35,18 +32,10 @@
 #include <linux/types.h>
 #include <linux/delay.h>
 #include <linux/mm.h>
-#ifdef LINUX20
-#  include <linux/major.h>
-#  include <linux/fs.h>
-#  include <linux/sound.h>
-#  include <asm/segment.h>
-#  include "sound_config.h"
-#else
-#  include <linux/init.h>
-#  include <asm/io.h>
-#  include <asm/uaccess.h>
-#  include <linux/spinlock.h>
-#endif
+#include <linux/init.h>
+#include <asm/io.h>
+#include <asm/uaccess.h>
+#include <linux/spinlock.h>
 #include <asm/irq.h>
 #include "msnd.h"
 
--- diff/sound/oss/os.h	2003-05-21 11:50:17.000000000 +0100
+++ source/sound/oss/os.h	2004-02-23 13:56:48.000000000 +0000
@@ -7,10 +7,6 @@
 #include <linux/module.h>
 #include <linux/version.h>
 
-#if LINUX_VERSION_CODE > 131328
-#define LINUX21X
-#endif
-
 #ifdef __KERNEL__
 #include <linux/utsname.h>
 #include <linux/string.h>
--- diff/sound/oss/vidc.c	2004-01-19 10:22:59.000000000 +0000
+++ source/sound/oss/vidc.c	2004-02-23 13:56:48.000000000 +0000
@@ -324,9 +324,10 @@ static int vidc_audio_prepare_for_input(
 	return -EINVAL;
 }
 
-static void vidc_audio_dma_interrupt(void)
+static irqreturn_t vidc_audio_dma_interrupt(void)
 {
 	DMAbuf_outputintr(vidc_adev, 1);
+	return IRQ_HANDLED;
 }
 
 /*
--- diff/sound/oss/vidc.h	2003-05-21 11:50:17.000000000 +0100
+++ source/sound/oss/vidc.h	2004-02-23 13:56:48.000000000 +0000
@@ -50,7 +50,7 @@ extern unsigned long (*vidc_filler) (uns
  * Virtual DMA buffer exhausted
  */
 
-extern void     (*dma_interrupt) (void);
+extern irqreturn_t (*dma_interrupt) (void);
 
 /*
  * Virtual DMA buffer addresses
--- diff/sound/oss/vidc_fill.S	2003-05-21 11:50:17.000000000 +0100
+++ source/sound/oss/vidc_fill.S	2004-02-23 13:56:48.000000000 +0000
@@ -133,10 +133,6 @@ ENTRY(vidc_clear)
  *  ip = corrupted
  */
 
-%%%%%%%%%%%%%%%%%%%
-fixme!  This funtion needs to return IRQ_HANDLED
-%%%%%%%%%%%%%%%%%%%
-
 ENTRY(vidc_sound_dma_irq)
 		stmfd	sp!, {r4 - r8, lr}
 		ldr	r8, =dma_start
@@ -189,6 +185,7 @@ ENTRY(vidc_sound_dma_irq)
 		mov	r0, #0x10
 		strneb	r0, [ip, #IOMD_SD0CR]
 		ldmfd	sp!, {r4 - r8, lr}
+		mov	r0, #1				@ IRQ_HANDLED
 		teq	r1, #0				@ If we have no more
 		movne	pc, lr
 		teq	r3, #0
--- diff/sound/pci/Kconfig	2004-02-18 08:54:13.000000000 +0000
+++ source/sound/pci/Kconfig	2004-02-23 13:56:48.000000000 +0000
@@ -55,6 +55,12 @@ config SND_KORG1212
 	help
 	  Say 'Y' or 'M' to include support for Korg 1212IO.
 
+config SND_MIXART
+	tristate "Digigram miXart"
+	depends on SND
+	help
+	  Say 'Y' or 'M' to include support for Digigram miXart soundcard.
+
 config SND_NM256
 	tristate "NeoMagic NM256AV/ZX"
 	depends on SND
--- diff/sound/pci/Makefile	2004-02-18 08:54:13.000000000 +0000
+++ source/sound/pci/Makefile	2004-02-23 13:56:48.000000000 +0000
@@ -38,4 +38,16 @@ obj-$(CONFIG_SND_RME96) += snd-rme96.o
 obj-$(CONFIG_SND_SONICVIBES) += snd-sonicvibes.o
 obj-$(CONFIG_SND_VIA82XX) += snd-via82xx.o
 
-obj-$(CONFIG_SND) += ac97/ ali5451/ cs46xx/ emu10k1/ korg1212/ nm256/ rme9652/ trident/ ymfpci/ ice1712/ vx222/
+obj-$(CONFIG_SND) += \
+	ac97/ \
+	ali5451/ \
+	cs46xx/ \
+	emu10k1/ \
+	ice1712/ \
+	korg1212/ \
+	mixart/ \
+	nm256/ \
+	rme9652/ \
+	trident/ \
+	ymfpci/ \
+	vx222/
--- diff/sound/pci/ac97/ac97_codec.c	2004-02-18 08:54:13.000000000 +0000
+++ source/sound/pci/ac97/ac97_codec.c	2004-02-23 13:56:48.000000000 +0000
@@ -100,6 +100,7 @@ static const ac97_codec_id_t snd_ac97_co
 { 0x41445361, 0xffffffff, "AD1886",		patch_ad1886,	NULL },
 { 0x41445362, 0xffffffff, "AD1887",		patch_ad1881,	NULL },
 { 0x41445363, 0xffffffff, "AD1886A",		patch_ad1881,	NULL },
+{ 0x41445368, 0xffffffff, "AD1888",		patch_ad1888,	NULL },
 { 0x41445370, 0xffffffff, "AD1980",		patch_ad1980,	NULL },
 { 0x41445372, 0xffffffff, "AD1981A",		patch_ad1981a,	NULL },
 { 0x41445374, 0xffffffff, "AD1981B",		patch_ad1981b,	NULL },
@@ -1526,38 +1527,40 @@ static int snd_ac97_modem_build(snd_card
 	return 0;
 }
 
-static int snd_ac97_test_rate(ac97_t *ac97, int reg, int rate)
+static int snd_ac97_test_rate(ac97_t *ac97, int reg, int shadow_reg, int rate)
 {
 	unsigned short val;
 	unsigned int tmp;
 
 	tmp = ((unsigned int)rate * ac97->bus->clock) / 48000;
 	snd_ac97_write_cache(ac97, reg, tmp & 0xffff);
+	if (shadow_reg)
+		snd_ac97_write_cache(ac97, shadow_reg, tmp & 0xffff);
 	val = snd_ac97_read(ac97, reg);
 	return val == (tmp & 0xffff);
 }
 
-static void snd_ac97_determine_rates(ac97_t *ac97, int reg, unsigned int *r_result)
+static void snd_ac97_determine_rates(ac97_t *ac97, int reg, int shadow_reg, unsigned int *r_result)
 {
 	unsigned int result = 0;
 
 	/* test a non-standard rate */
-	if (snd_ac97_test_rate(ac97, reg, 11000))
+	if (snd_ac97_test_rate(ac97, reg, shadow_reg, 11000))
 		result |= SNDRV_PCM_RATE_CONTINUOUS;
 	/* let's try to obtain standard rates */
-	if (snd_ac97_test_rate(ac97, reg, 8000))
+	if (snd_ac97_test_rate(ac97, reg, shadow_reg, 8000))
 		result |= SNDRV_PCM_RATE_8000;
-	if (snd_ac97_test_rate(ac97, reg, 11025))
+	if (snd_ac97_test_rate(ac97, reg, shadow_reg, 11025))
 		result |= SNDRV_PCM_RATE_11025;
-	if (snd_ac97_test_rate(ac97, reg, 16000))
+	if (snd_ac97_test_rate(ac97, reg, shadow_reg, 16000))
 		result |= SNDRV_PCM_RATE_16000;
-	if (snd_ac97_test_rate(ac97, reg, 22050))
+	if (snd_ac97_test_rate(ac97, reg, shadow_reg, 22050))
 		result |= SNDRV_PCM_RATE_22050;
-	if (snd_ac97_test_rate(ac97, reg, 32000))
+	if (snd_ac97_test_rate(ac97, reg, shadow_reg, 32000))
 		result |= SNDRV_PCM_RATE_32000;
-	if (snd_ac97_test_rate(ac97, reg, 44100))
+	if (snd_ac97_test_rate(ac97, reg, shadow_reg, 44100))
 		result |= SNDRV_PCM_RATE_44100;
-	if (snd_ac97_test_rate(ac97, reg, 48000))
+	if (snd_ac97_test_rate(ac97, reg, shadow_reg, 48000))
 		result |= SNDRV_PCM_RATE_48000;
 	*r_result = result;
 }
@@ -1866,8 +1869,8 @@ int snd_ac97_mixer(ac97_bus_t * bus, ac9
 	if (ac97->ext_id & 0x0189)	/* L/R, MIC, SDAC, LDAC VRA support */
 		snd_ac97_write_cache(ac97, AC97_EXTENDED_STATUS, ac97->ext_id & 0x0189);
 	if (ac97->ext_id & AC97_EI_VRA) {	/* VRA support */
-		snd_ac97_determine_rates(ac97, AC97_PCM_FRONT_DAC_RATE, &ac97->rates[AC97_RATES_FRONT_DAC]);
-		snd_ac97_determine_rates(ac97, AC97_PCM_LR_ADC_RATE, &ac97->rates[AC97_RATES_ADC]);
+		snd_ac97_determine_rates(ac97, AC97_PCM_FRONT_DAC_RATE, 0, &ac97->rates[AC97_RATES_FRONT_DAC]);
+		snd_ac97_determine_rates(ac97, AC97_PCM_LR_ADC_RATE, 0, &ac97->rates[AC97_RATES_ADC]);
 	} else {
 		ac97->rates[AC97_RATES_FRONT_DAC] = SNDRV_PCM_RATE_48000;
 		ac97->rates[AC97_RATES_ADC] = SNDRV_PCM_RATE_48000;
@@ -1884,16 +1887,16 @@ int snd_ac97_mixer(ac97_bus_t * bus, ac9
 						SNDRV_PCM_RATE_32000;
 	}
 	if (ac97->ext_id & AC97_EI_VRM) {	/* MIC VRA support */
-		snd_ac97_determine_rates(ac97, AC97_PCM_MIC_ADC_RATE, &ac97->rates[AC97_RATES_MIC_ADC]);
+		snd_ac97_determine_rates(ac97, AC97_PCM_MIC_ADC_RATE, 0, &ac97->rates[AC97_RATES_MIC_ADC]);
 	} else {
 		ac97->rates[AC97_RATES_MIC_ADC] = SNDRV_PCM_RATE_48000;
 	}
 	if (ac97->ext_id & AC97_EI_SDAC) {	/* SDAC support */
-		snd_ac97_determine_rates(ac97, AC97_PCM_SURR_DAC_RATE, &ac97->rates[AC97_RATES_SURR_DAC]);
+		snd_ac97_determine_rates(ac97, AC97_PCM_SURR_DAC_RATE, AC97_PCM_FRONT_DAC_RATE, &ac97->rates[AC97_RATES_SURR_DAC]);
 		ac97->scaps |= AC97_SCAP_SURROUND_DAC;
 	}
 	if (ac97->ext_id & AC97_EI_LDAC) {	/* LDAC support */
-		snd_ac97_determine_rates(ac97, AC97_PCM_LFE_DAC_RATE, &ac97->rates[AC97_RATES_LFE_DAC]);
+		snd_ac97_determine_rates(ac97, AC97_PCM_LFE_DAC_RATE, AC97_PCM_FRONT_DAC_RATE, &ac97->rates[AC97_RATES_LFE_DAC]);
 		ac97->scaps |= AC97_SCAP_CENTER_LFE_DAC;
 	}
 	/* additional initializations */
@@ -2112,6 +2115,8 @@ static int swap_headphone(ac97_t *ac97, 
 {
 	/* FIXME: error checks.. */
 	if (remove_master) {
+		if (ctl_find(ac97, "Headphone Playback Switch") == NULL)
+			return 0;
 		snd_ac97_remove_ctl(ac97, "Master Playback Switch");
 		snd_ac97_remove_ctl(ac97, "Master Playback Volume");
 	} else {
--- diff/sound/pci/ac97/ac97_patch.c	2004-02-18 08:54:13.000000000 +0000
+++ source/sound/pci/ac97/ac97_patch.c	2004-02-23 13:56:48.000000000 +0000
@@ -652,7 +652,7 @@ int patch_ad1881(ac97_t * ac97)
 
 static const snd_kcontrol_new_t snd_ac97_controls_ad1885[] = {
 	AC97_SINGLE("Digital Mono Direct", AC97_AD_MISC, 11, 1, 0),
-	AC97_SINGLE("Digital Audio Mode", AC97_AD_MISC, 12, 1, 0),
+	/* AC97_SINGLE("Digital Audio Mode", AC97_AD_MISC, 12, 1, 0), */ /* seems problematic */
 	AC97_SINGLE("Low Power Mixer", AC97_AD_MISC, 14, 1, 0),
 	AC97_SINGLE("Zero Fill DAC", AC97_AD_MISC, 15, 1, 0),
 };
@@ -682,6 +682,9 @@ int patch_ad1885(ac97_t * ac97)
 	jack = snd_ac97_read(ac97, AC97_AD_JACK_SPDIF);
 	snd_ac97_write_cache(ac97, AC97_AD_JACK_SPDIF, jack | 0x0300);
 
+	/* set default */
+	snd_ac97_write_cache(ac97, AC97_AD_MISC, 0x0404);
+
 	ac97->build_ops = &patch_ad1885_build_ops;
 	return 0;
 }
@@ -799,7 +802,7 @@ int patch_ad1981b(ac97_t *ac97)
 	return 0;
 }
 
-static int snd_ac97_ad1980_lohpsel_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
+static int snd_ac97_ad1888_lohpsel_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
 {
 	uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
 	uinfo->count = 1;
@@ -808,7 +811,7 @@ static int snd_ac97_ad1980_lohpsel_info(
 	return 0;
 }
 
-static int snd_ac97_ad1980_lohpsel_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t* ucontrol)
+static int snd_ac97_ad1888_lohpsel_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t* ucontrol)
 {
 	ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
 	unsigned short val;
@@ -818,7 +821,7 @@ static int snd_ac97_ad1980_lohpsel_get(s
 	return 0;
 }
 
-static int snd_ac97_ad1980_lohpsel_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int snd_ac97_ad1888_lohpsel_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
 {
 	ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
 	unsigned short val;
@@ -829,7 +832,7 @@ static int snd_ac97_ad1980_lohpsel_put(s
 				    AC97_AD198X_LOSEL | AC97_AD198X_HPSEL, val);
 }
 
-static int snd_ac97_ad1980_downmix_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
+static int snd_ac97_ad1888_downmix_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
 {
 	static char *texts[3] = {"Off", "6 -> 4", "6 -> 2"};
 
@@ -842,7 +845,7 @@ static int snd_ac97_ad1980_downmix_info(
 	return 0;
 }
 
-static int snd_ac97_ad1980_downmix_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t* ucontrol)
+static int snd_ac97_ad1888_downmix_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t* ucontrol)
 {
 	ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
 	unsigned short val;
@@ -855,7 +858,7 @@ static int snd_ac97_ad1980_downmix_get(s
 	return 0;
 }
 
-static int snd_ac97_ad1980_downmix_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int snd_ac97_ad1888_downmix_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
 {
 	ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
 	unsigned short val;
@@ -871,51 +874,47 @@ static int snd_ac97_ad1980_downmix_put(s
 				    AC97_AD198X_DMIX0 | AC97_AD198X_DMIX1, val);
 }
 
-static const snd_kcontrol_new_t snd_ac97_ad1980_controls[] = {
+static const snd_kcontrol_new_t snd_ac97_ad1888_controls[] = {
 	{
 		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 		.name = "Exchange Front/Surround",
-		.info = snd_ac97_ad1980_lohpsel_info,
-		.get = snd_ac97_ad1980_lohpsel_get,
-		.put = snd_ac97_ad1980_lohpsel_put
+		.info = snd_ac97_ad1888_lohpsel_info,
+		.get = snd_ac97_ad1888_lohpsel_get,
+		.put = snd_ac97_ad1888_lohpsel_put
 	},
 	AC97_SINGLE("Spread Front to Surround and Center/LFE", AC97_AD_MISC, 7, 1, 0),
 	{
 		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 		.name = "Downmix",
-		.info = snd_ac97_ad1980_downmix_info,
-		.get = snd_ac97_ad1980_downmix_get,
-		.put = snd_ac97_ad1980_downmix_put
+		.info = snd_ac97_ad1888_downmix_info,
+		.get = snd_ac97_ad1888_downmix_get,
+		.put = snd_ac97_ad1888_downmix_put
 	},
 	AC97_SINGLE("Surround Jack as Input", AC97_AD_MISC, 12, 1, 0),
 	AC97_SINGLE("Center/LFE Jack as Input", AC97_AD_MISC, 11, 1, 0),
 };
 
-static int patch_ad1980_specific(ac97_t *ac97)
+static int patch_ad1888_specific(ac97_t *ac97)
 {
-	int err;
-
 	/* rename 0x04 as "Master" and 0x02 as "Master Surround" */
 	snd_ac97_rename_ctl(ac97, "Master Playback Switch", "Master Surround Playback Switch");
 	snd_ac97_rename_ctl(ac97, "Master Playback Volume", "Master Surround Playback Volume");
 	snd_ac97_rename_ctl(ac97, "Headphone Playback Switch", "Master Playback Switch");
 	snd_ac97_rename_ctl(ac97, "Headphone Playback Volume", "Master Playback Volume");
-	if ((err = patch_build_controls(ac97, &snd_ac97_ad198x_2cmic, 1)) < 0)
-		return err;
-	return patch_build_controls(ac97, snd_ac97_ad1980_controls, ARRAY_SIZE(snd_ac97_ad1980_controls));
+	return patch_build_controls(ac97, snd_ac97_ad1888_controls, ARRAY_SIZE(snd_ac97_ad1888_controls));
 }
 
-static struct snd_ac97_build_ops patch_ad1980_build_ops = {
+static struct snd_ac97_build_ops patch_ad1888_build_ops = {
 	.build_post_spdif = patch_ad198x_post_spdif,
-	.build_specific = patch_ad1980_specific
+	.build_specific = patch_ad1888_specific
 };
 
-int patch_ad1980(ac97_t * ac97)
+int patch_ad1888(ac97_t * ac97)
 {
 	unsigned short misc;
 	
 	patch_ad1881(ac97);
-	ac97->build_ops = &patch_ad1980_build_ops;
+	ac97->build_ops = &patch_ad1888_build_ops;
 	/* Switch FRONT/SURROUND LINE-OUT/HP-OUT default connection */
 	/* it seems that most vendors connect line-out connector to headphone out of AC'97 */
 	/* AD-compatible mode */
@@ -930,6 +929,27 @@ int patch_ad1980(ac97_t * ac97)
 	return 0;
 }
 
+static int patch_ad1980_specific(ac97_t *ac97)
+{
+	int err;
+
+	if ((err = patch_ad1888_specific(ac97)) < 0)
+		return err;
+	return patch_build_controls(ac97, &snd_ac97_ad198x_2cmic, 1);
+}
+
+static struct snd_ac97_build_ops patch_ad1980_build_ops = {
+	.build_post_spdif = patch_ad198x_post_spdif,
+	.build_specific = patch_ad1980_specific
+};
+
+int patch_ad1980(ac97_t * ac97)
+{
+	patch_ad1888(ac97);
+	ac97->build_ops = &patch_ad1980_build_ops;
+	return 0;
+}
+
 static const snd_kcontrol_new_t snd_ac97_ad1985_controls[] = {
 	AC97_SINGLE("Center/LFE Jack as Mic", AC97_AD_SERIAL_CFG, 9, 1, 0),
 	AC97_SINGLE("Exchange Center/LFE", AC97_AD_SERIAL_CFG, 3, 1, 0)
@@ -1014,8 +1034,7 @@ static int snd_ac97_alc650_mic_gpio_put(
                                       ucontrol->value.integer.value[0] ? (1 << 10) : 0);
         if (change) {
                 /* GPIO0 write for mic */
-                snd_ac97_update_bits(ac97, 0x76, 0x01,
-                                     ucontrol->value.integer.value[0] ? 0 : 0x01);
+                snd_ac97_update_bits(ac97, 0x76, 0x01, 0x01);
                 /* GPIO0 high for mic */
                 snd_ac97_update_bits(ac97, 0x78, 0x100,
                                      ucontrol->value.integer.value[0] ? 0 : 0x100);
@@ -1092,10 +1111,7 @@ int patch_alc650(ac97_t * ac97)
 		mic_off = snd_ac97_read(ac97, AC97_ALC650_MULTICH) & (1 << 10);
 		/* GPIO0 direction */
 		val = snd_ac97_read(ac97, AC97_ALC650_GPIO_SETUP);
-		if (mic_off)
-			val &= ~0x01;
-		else
-			val |= 0x01;
+		val |= 0x01;
 		snd_ac97_write_cache(ac97, AC97_ALC650_GPIO_SETUP, val);
 		val = snd_ac97_read(ac97, AC97_ALC650_GPIO_STATUS);
 		if (mic_off)
@@ -1111,10 +1127,36 @@ int patch_alc650(ac97_t * ac97)
 	return 0;
 }
 
+static int snd_ac97_alc655_mic_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t * ucontrol)
+{
+        ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
+        ucontrol->value.integer.value[0] = (ac97->regs[AC97_ALC650_MULTICH] >> 10) & 1;
+        return 0;
+}
+
+static int snd_ac97_alc655_mic_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t * ucontrol)
+{
+        ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
+        int change;
+
+	snd_ac97_update_bits(ac97, 0x7a, 1 << 12, /* misc control; vrefout disable */
+			     ucontrol->value.integer.value[0] ? (1 << 12) : 0);
+	change = snd_ac97_update_bits(ac97, AC97_ALC650_MULTICH, 1 << 10,
+				      ucontrol->value.integer.value[0] ? (1 << 10) : 0);
+	return change;
+}
+
+
 static const snd_kcontrol_new_t snd_ac97_controls_alc655[] = {
 	AC97_SINGLE("Duplicate Front", AC97_ALC650_MULTICH, 0, 1, 0),
 	AC97_SINGLE("Line-In As Surround", AC97_ALC650_MULTICH, 9, 1, 0),
-	AC97_SINGLE("Mic As Center/LFE", AC97_ALC650_MULTICH, 10, 1, 0),
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+		.name = "Mic As Center/LFE",
+		.info = snd_ac97_info_single,
+		.get = snd_ac97_alc655_mic_get,
+		.put = snd_ac97_alc655_mic_put,
+	},
 };
 
 static int alc655_iec958_route_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
@@ -1187,15 +1229,21 @@ static struct snd_ac97_build_ops patch_a
 
 int patch_alc655(ac97_t * ac97)
 {
+	unsigned int val;
+
 	ac97->spec.dev_flags = (ac97->id == 0x414c4780); /* ALC658 */
 
 	ac97->build_ops = &patch_alc655_ops;
 
-	/* enable spdif in */
-	snd_ac97_write_cache(ac97, AC97_ALC650_CLOCK,
-			     snd_ac97_read(ac97, AC97_ALC650_MULTICH) | 0x8000);
-	snd_ac97_write_cache(ac97, AC97_ALC650_CLOCK,
-			     snd_ac97_read(ac97, AC97_ALC650_CLOCK) | 0x02);
+	/* adjust default values */
+	val = snd_ac97_read(ac97, 0x7a); /* misc control */
+	val |= (1 << 1); /* spdif input pin */
+	val &= ~(1 << 12); /* vref enable */
+	snd_ac97_write_cache(ac97, 0x7a, val);
+	val = snd_ac97_read(ac97, AC97_ALC650_MULTICH);
+	val |= (1 << 15); /* enable spdif in */
+	val &= ~(1 << 10); /* disable center on mic */
+	snd_ac97_write_cache(ac97, AC97_ALC650_MULTICH, val);
 
 	/* full DAC volume */
 	snd_ac97_write_cache(ac97, AC97_ALC650_SURR_DAC_VOL, 0x0808);
--- diff/sound/pci/ac97/ac97_patch.h	2004-02-18 08:54:13.000000000 +0000
+++ source/sound/pci/ac97/ac97_patch.h	2004-02-23 13:56:48.000000000 +0000
@@ -41,6 +41,7 @@ int patch_ad1819(ac97_t * ac97);
 int patch_ad1881(ac97_t * ac97);
 int patch_ad1885(ac97_t * ac97);
 int patch_ad1886(ac97_t * ac97);
+int patch_ad1888(ac97_t * ac97);
 int patch_ad1980(ac97_t * ac97);
 int patch_ad1981a(ac97_t * ac97);
 int patch_ad1981b(ac97_t * ac97);
--- diff/sound/pci/ice1712/ice1712.c	2004-02-18 08:54:13.000000000 +0000
+++ source/sound/pci/ice1712/ice1712.c	2004-02-23 13:56:48.000000000 +0000
@@ -2375,6 +2375,7 @@ static int __devinit snd_ice1712_create(
 	ice->omni = omni ? 1 : 0;
 	spin_lock_init(&ice->reg_lock);
 	init_MUTEX(&ice->gpio_mutex);
+	init_MUTEX(&ice->open_mutex);
 	ice->gpio.set_mask = snd_ice1712_set_gpio_mask;
 	ice->gpio.set_dir = snd_ice1712_set_gpio_dir;
 	ice->gpio.set_data = snd_ice1712_set_gpio_data;
--- diff/sound/pci/ice1712/ice1712.h	2004-02-18 08:54:13.000000000 +0000
+++ source/sound/pci/ice1712/ice1712.h	2004-02-23 13:56:48.000000000 +0000
@@ -335,6 +335,9 @@ struct _snd_ice1712 {
 	unsigned short hoontech_boxconfig[4];
 	unsigned int cur_rate;		/* current rate */
 
+	struct semaphore open_mutex;
+	snd_pcm_substream_t *pcm_reserved[4];
+
 	unsigned int akm_codecs;
 	akm4xxx_t *akm;
 	struct snd_ice1712_spdif spdif;
--- diff/sound/pci/ice1712/ice1724.c	2004-02-18 08:54:13.000000000 +0000
+++ source/sound/pci/ice1712/ice1724.c	2004-02-23 13:56:48.000000000 +0000
@@ -237,6 +237,18 @@ static irqreturn_t snd_vt1724_interrupt(
 				if (ice->capture_pro_substream)
 					snd_pcm_period_elapsed(ice->capture_pro_substream);
 			}
+			if (mtstat & VT1724_MULTI_PDMA1) {
+				if (ice->playback_con_substream_ds[0])
+					snd_pcm_period_elapsed(ice->playback_con_substream_ds[0]);
+			}
+			if (mtstat & VT1724_MULTI_PDMA2) {
+				if (ice->playback_con_substream_ds[1])
+					snd_pcm_period_elapsed(ice->playback_con_substream_ds[1]);
+			}
+			if (mtstat & VT1724_MULTI_PDMA3) {
+				if (ice->playback_con_substream_ds[2])
+					snd_pcm_period_elapsed(ice->playback_con_substream_ds[2]);
+			}
 			if (mtstat & VT1724_MULTI_PDMA4) {
 				if (ice->playback_con_substream)
 					snd_pcm_period_elapsed(ice->playback_con_substream);
@@ -282,16 +294,6 @@ static snd_pcm_hw_constraint_list_t hw_c
 	.mask = 0,
 };
 
-static unsigned int hw_channels[] = {
-	2, 4, 6, 8
-};
-
-static snd_pcm_hw_constraint_list_t hw_constraints_channels = {
-	.count = ARRAY_SIZE(hw_channels),
-	.list = hw_channels,
-	.mask = 0,
-};
-
 static int snd_vt1724_pcm_trigger(snd_pcm_substream_t *substream, int cmd)
 {
 	ice1712_t *ice = snd_pcm_substream_chip(substream);
@@ -300,21 +302,16 @@ static int snd_vt1724_pcm_trigger(snd_pc
 	struct list_head *pos;
 	snd_pcm_substream_t *s;
 
+	what = 0;
+	snd_pcm_group_for_each(pos, substream) {
+		s = snd_pcm_group_substream_entry(pos);
+		what |= (unsigned long)(s->runtime->private_data);
+		snd_pcm_trigger_done(s, substream);
+	}
+
 	switch (cmd) {
 	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
 	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
-		what = 0;
-		snd_pcm_group_for_each(pos, substream) {
-			s = snd_pcm_group_substream_entry(pos);
-			if (s == ice->playback_pro_substream)
-				what |= VT1724_PDMA0_PAUSE;
-			else if (s == ice->capture_pro_substream)
-				what |= VT1724_RDMA0_PAUSE;
-			else if (s == ice->playback_con_substream)
-				what |= VT1724_PDMA4_PAUSE;
-			else if (s == ice->capture_con_substream)
-				what |= VT1724_RDMA1_PAUSE;
-		}
 		spin_lock(&ice->reg_lock);
 		old = inb(ICEMT1724(ice, DMA_PAUSE));
 		if (cmd == SNDRV_PCM_TRIGGER_PAUSE_PUSH)
@@ -327,24 +324,6 @@ static int snd_vt1724_pcm_trigger(snd_pc
 
 	case SNDRV_PCM_TRIGGER_START:
 	case SNDRV_PCM_TRIGGER_STOP:
-		what = 0;
-		s = substream;
-		snd_pcm_group_for_each(pos, substream) {
-			s = snd_pcm_group_substream_entry(pos);
-			if (s == ice->playback_pro_substream) {
-				what |= VT1724_PDMA0_START;
-				snd_pcm_trigger_done(s, substream);
-			} else if (s == ice->capture_pro_substream) {
-				what |= VT1724_RDMA0_START;
-				snd_pcm_trigger_done(s, substream);
-			} else if (s == ice->playback_con_substream) {
-				what |= VT1724_PDMA4_START;
-				snd_pcm_trigger_done(s, substream);
-			} else if (s == ice->capture_con_substream) {
-				what |= VT1724_RDMA1_START;
-				snd_pcm_trigger_done(s, substream);
-			}
-		}
 		spin_lock(&ice->reg_lock);
 		old = inb(ICEMT1724(ice, DMA_CONTROL));
 		if (cmd == SNDRV_PCM_TRIGGER_START)
@@ -364,8 +343,10 @@ static int snd_vt1724_pcm_trigger(snd_pc
 /*
  */
 
-#define DMA_STARTS	(VT1724_RDMA0_START|VT1724_PDMA0_START|VT1724_RDMA1_START|VT1724_PDMA4_START)
-#define DMA_PAUSES	(VT1724_RDMA0_PAUSE|VT1724_PDMA0_PAUSE|VT1724_RDMA1_PAUSE|VT1724_PDMA4_PAUSE)
+#define DMA_STARTS	(VT1724_RDMA0_START|VT1724_PDMA0_START|VT1724_RDMA1_START|\
+	VT1724_PDMA1_START|VT1724_PDMA2_START|VT1724_PDMA3_START|VT1724_PDMA4_START)
+#define DMA_PAUSES	(VT1724_RDMA0_PAUSE|VT1724_PDMA0_PAUSE|VT1724_RDMA1_PAUSE|\
+	VT1724_PDMA1_PAUSE|VT1724_PDMA2_PAUSE|VT1724_PDMA3_PAUSE|VT1724_PDMA4_PAUSE)
 
 static void snd_vt1724_set_pro_rate(ice1712_t *ice, unsigned int rate, int force)
 {
@@ -448,13 +429,52 @@ static int snd_vt1724_pcm_hw_params(snd_
 				    snd_pcm_hw_params_t * hw_params)
 {
 	ice1712_t *ice = snd_pcm_substream_chip(substream);
+	int i, chs;
 
+	chs = params_channels(hw_params);
+	down(&ice->open_mutex);
+	/* mark surround channels */
+	if (substream == ice->playback_pro_substream) {
+		chs = chs / 2 - 1;
+		for (i = 0; i < chs; i++) {
+			if (ice->pcm_reserved[i] && ice->pcm_reserved[i] != substream) {
+				up(&ice->open_mutex);
+				return -EBUSY;
+			}
+			ice->pcm_reserved[i] = substream;
+		}
+		for (; i < 3; i++) {
+			if (ice->pcm_reserved[i] == substream)
+				ice->pcm_reserved[i] = NULL;
+		}
+	} else {
+		for (i = 0; i < 3; i++) {
+			if (ice->playback_con_substream_ds[i] == substream) {
+				if (ice->pcm_reserved[i] && ice->pcm_reserved[i] != substream) {
+					up(&ice->open_mutex);
+					return -EBUSY;
+				}
+				ice->pcm_reserved[i] = substream;
+				break;
+			}
+		}
+	}
+	up(&ice->open_mutex);
 	snd_vt1724_set_pro_rate(ice, params_rate(hw_params), 0);
 	return snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params));
 }
 
 static int snd_vt1724_pcm_hw_free(snd_pcm_substream_t * substream)
 {
+	ice1712_t *ice = snd_pcm_substream_chip(substream);
+	int i;
+
+	down(&ice->open_mutex);
+	/* unmark surround channels */
+	for (i = 0; i < 3; i++)
+		if (ice->pcm_reserved[i] == substream)
+			ice->pcm_reserved[i] = NULL;
+	up(&ice->open_mutex);
 	return snd_pcm_lib_free_pages(substream);
 }
 
@@ -593,14 +613,14 @@ static snd_pcm_hardware_t snd_vt1724_pla
 	.rate_max =		192000,
 	.channels_min =		2,
 	.channels_max =		8,
-	.buffer_bytes_max =	(1UL << 21),	/* 18bits dword */
+	.buffer_bytes_max =	(1UL << 21),	/* 19bits dword */
 	.period_bytes_min =	8 * 4 * 2,	/* FIXME: constraints needed */
 	.period_bytes_max =	(1UL << 21),
-	.periods_min =		1,
+	.periods_min =		2,
 	.periods_max =		1024,
 };
 
-static snd_pcm_hardware_t snd_vt1724_capture_pro =
+static snd_pcm_hardware_t snd_vt1724_2ch_stereo =
 {
 	.info =			(SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
 				 SNDRV_PCM_INFO_BLOCK_TRANSFER |
@@ -612,10 +632,10 @@ static snd_pcm_hardware_t snd_vt1724_cap
 	.rate_max =		192000,
 	.channels_min =		2,
 	.channels_max =		2,
-	.buffer_bytes_max =	(256*1024),
+	.buffer_bytes_max =	(1UL << 18),	/* 16bits dword */
 	.period_bytes_min =	2 * 4 * 2,
-	.period_bytes_max =	(256*1024),
-	.periods_min =		1,
+	.period_bytes_max =	(1UL << 18),
+	.periods_min =		2,
 	.periods_max =		1024,
 };
 
@@ -628,7 +648,9 @@ static int snd_vt1724_playback_pro_open(
 {
 	snd_pcm_runtime_t *runtime = substream->runtime;
 	ice1712_t *ice = snd_pcm_substream_chip(substream);
+	int chs;
 
+	runtime->private_data = (void*)VT1724_PDMA0_START; /* irq/status/trigger bit */
 	ice->playback_pro_substream = substream;
 	runtime->hw = snd_vt1724_playback_pro;
 	snd_pcm_set_sync(substream);
@@ -639,7 +661,17 @@ static int snd_vt1724_playback_pro_open(
 	else
 		snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, &hw_constraints_rates_96);
 
-	snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, &hw_constraints_channels);
+	down(&ice->open_mutex);
+	/* calculate the currently available channels */
+	for (chs = 0; chs < 3; chs++) {
+		if (ice->pcm_reserved[chs])
+			break;
+	}
+	chs = (chs + 1) * 2;
+	runtime->hw.channels_max = chs;
+	if (chs > 2) /* channels must be even */
+		snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, 2);
+	up(&ice->open_mutex);
 	snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES,
 				   VT1724_BUFFER_ALIGN);
 	snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_BYTES,
@@ -652,8 +684,9 @@ static int snd_vt1724_capture_pro_open(s
 	ice1712_t *ice = snd_pcm_substream_chip(substream);
 	snd_pcm_runtime_t *runtime = substream->runtime;
 
+	runtime->private_data = (void*)VT1724_RDMA0_START; /* irq/status/trigger bit */
 	ice->capture_pro_substream = substream;
-	runtime->hw = snd_vt1724_capture_pro;
+	runtime->hw = snd_vt1724_2ch_stereo;
 	snd_pcm_set_sync(substream);
 	snd_pcm_hw_constraint_msbits(runtime, 0, 32, 24);
 	if ((ice->eeprom.data[ICE_EEP2_ACLINK] & 0x80) &&
@@ -735,25 +768,6 @@ static int __devinit snd_vt1724_pcm_prof
  * SPDIF PCM
  */
 
-static snd_pcm_hardware_t snd_vt1724_playback_spdif =
-{
-	.info =			(SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
-				 SNDRV_PCM_INFO_BLOCK_TRANSFER |
-				 SNDRV_PCM_INFO_MMAP_VALID |
-				 SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_SYNC_START),
-	.formats =		SNDRV_PCM_FMTBIT_S32_LE,
-	.rates =		SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_8000_192000,
-	.rate_min =		4000,
-	.rate_max =		192000,
-	.channels_min =		2,
-	.channels_max =		2,
-	.buffer_bytes_max =	(256*1024),
-	.period_bytes_min =	2 * 4 * 2,
-	.period_bytes_max =	(256*1024),
-	.periods_min =		1,
-	.periods_max =		1024,
-};
-
 const static struct vt1724_pcm_reg vt1724_playback_spdif_reg = {
 	.addr = VT1724_MT_PDMA4_ADDR,
 	.size = VT1724_MT_PDMA4_SIZE,
@@ -795,8 +809,9 @@ static int snd_vt1724_playback_spdif_ope
 	ice1712_t *ice = snd_pcm_substream_chip(substream);
 	snd_pcm_runtime_t *runtime = substream->runtime;
 
+	runtime->private_data = (void*)VT1724_PDMA4_START; /* irq/status/trigger bit */
 	ice->playback_con_substream = substream;
-	runtime->hw = snd_vt1724_playback_spdif;
+	runtime->hw = snd_vt1724_2ch_stereo;
 	snd_pcm_set_sync(substream);
 	snd_pcm_hw_constraint_msbits(runtime, 0, 32, 24);
 
@@ -820,8 +835,9 @@ static int snd_vt1724_capture_spdif_open
 	ice1712_t *ice = snd_pcm_substream_chip(substream);
 	snd_pcm_runtime_t *runtime = substream->runtime;
 
+	runtime->private_data = (void*)VT1724_RDMA1_START; /* irq/status/trigger bit */
 	ice->capture_con_substream = substream;
-	runtime->hw = snd_vt1724_playback_spdif;
+	runtime->hw = snd_vt1724_2ch_stereo;
 	snd_pcm_set_sync(substream);
 	snd_pcm_hw_constraint_msbits(runtime, 0, 32, 24);
 	snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, &hw_constraints_rates_96);
@@ -903,6 +919,127 @@ static int __devinit snd_vt1724_pcm_spdi
 
 
 /*
+ * independent surround PCMs
+ */
+
+const static struct vt1724_pcm_reg vt1724_playback_dma_regs[3] = {
+	{
+		.addr = VT1724_MT_PDMA1_ADDR,
+		.size = VT1724_MT_PDMA1_SIZE,
+		.count = VT1724_MT_PDMA1_COUNT,
+		.start = VT1724_PDMA1_START,
+		.pause = VT1724_PDMA1_PAUSE,
+	},
+	{
+		.addr = VT1724_MT_PDMA2_ADDR,
+		.size = VT1724_MT_PDMA2_SIZE,
+		.count = VT1724_MT_PDMA2_COUNT,
+		.start = VT1724_PDMA2_START,
+		.pause = VT1724_PDMA2_PAUSE,
+	},
+	{
+		.addr = VT1724_MT_PDMA3_ADDR,
+		.size = VT1724_MT_PDMA3_SIZE,
+		.count = VT1724_MT_PDMA3_COUNT,
+		.start = VT1724_PDMA3_START,
+		.pause = VT1724_PDMA3_PAUSE,
+	},
+};
+
+static int snd_vt1724_playback_indep_prepare(snd_pcm_substream_t * substream)
+{
+	ice1712_t *ice = snd_pcm_substream_chip(substream);
+	unsigned char val;
+
+	spin_lock(&ice->reg_lock);
+	val = 3 - substream->number;
+	if (inb(ICEMT1724(ice, BURST)) < val)
+		outb(val, ICEMT1724(ice, BURST));
+	spin_unlock(&ice->reg_lock);
+	return snd_vt1724_pcm_prepare(substream, &vt1724_playback_dma_regs[substream->number]);
+}
+
+static snd_pcm_uframes_t snd_vt1724_playback_indep_pointer(snd_pcm_substream_t * substream)
+{
+	return snd_vt1724_pcm_pointer(substream, &vt1724_playback_dma_regs[substream->number]);
+}
+
+static int snd_vt1724_playback_indep_open(snd_pcm_substream_t *substream)
+{
+	ice1712_t *ice = snd_pcm_substream_chip(substream);
+	snd_pcm_runtime_t *runtime = substream->runtime;
+
+	down(&ice->open_mutex);
+	/* already used by PDMA0? */
+	if (ice->pcm_reserved[substream->number]) {
+		up(&ice->open_mutex);
+		return -EBUSY; /* FIXME: should handle blocking mode properly */
+	}
+	up(&ice->open_mutex);
+	runtime->private_data = (void*)(1 << (substream->number + 4));
+	ice->playback_con_substream_ds[substream->number] = substream;
+	runtime->hw = snd_vt1724_2ch_stereo;
+	snd_pcm_set_sync(substream);
+	snd_pcm_hw_constraint_msbits(runtime, 0, 32, 24);
+
+	snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, &hw_constraints_rates_192);
+	return 0;
+}
+
+static int snd_vt1724_playback_indep_close(snd_pcm_substream_t * substream)
+{
+	ice1712_t *ice = snd_pcm_substream_chip(substream);
+
+	if (PRO_RATE_RESET)
+		snd_vt1724_set_pro_rate(ice, PRO_RATE_DEFAULT, 0);
+	ice->playback_con_substream_ds[substream->number] = NULL;
+	ice->pcm_reserved[substream->number] = NULL;
+
+	return 0;
+}
+
+static snd_pcm_ops_t snd_vt1724_playback_indep_ops = {
+	.open =		snd_vt1724_playback_indep_open,
+	.close =	snd_vt1724_playback_indep_close,
+	.ioctl =	snd_pcm_lib_ioctl,
+	.hw_params =	snd_vt1724_pcm_hw_params,
+	.hw_free =	snd_vt1724_pcm_hw_free,
+	.prepare =	snd_vt1724_playback_indep_prepare,
+	.trigger =	snd_vt1724_pcm_trigger,
+	.pointer =	snd_vt1724_playback_indep_pointer,
+};
+
+
+static int __devinit snd_vt1724_pcm_indep(ice1712_t * ice, int device)
+{
+	snd_pcm_t *pcm;
+	int play;
+	int err;
+
+	play = ice->num_total_dacs / 2 - 1;
+	if (play <= 0)
+		return 0;
+
+	err = snd_pcm_new(ice->card, "ICE1724 Surrounds", device, play, 0, &pcm);
+	if (err < 0)
+		return err;
+
+	snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK,
+			&snd_vt1724_playback_indep_ops);
+
+	pcm->private_data = ice;
+	pcm->info_flags = 0;
+	strcpy(pcm->name, "ICE1724 Surround PCM");
+
+	snd_pcm_lib_preallocate_pci_pages_for_all(ice->pci, pcm, 64*1024, 64*1024);
+
+	ice->pcm_ds = pcm;
+
+	return 0;
+}
+
+
+/*
  *  Mixer section
  */
 
@@ -1808,6 +1945,7 @@ static int __devinit snd_vt1724_create(s
 	ice->vt1724 = 1;
 	spin_lock_init(&ice->reg_lock);
 	init_MUTEX(&ice->gpio_mutex);
+	init_MUTEX(&ice->open_mutex);
 	ice->gpio.set_mask = snd_vt1724_set_gpio_mask;
 	ice->gpio.set_dir = snd_vt1724_set_gpio_dir;
 	ice->gpio.set_data = snd_vt1724_set_gpio_data;
@@ -1932,6 +2070,11 @@ static int __devinit snd_vt1724_probe(st
 		return err;
 	}
 	
+	if ((err = snd_vt1724_pcm_indep(ice, pcm_dev++)) < 0) {
+		snd_card_free(card);
+		return err;
+	}
+
 	if ((err = snd_vt1724_ac97_mixer(ice)) < 0) {
 		snd_card_free(card);
 		return err;
--- diff/sound/pci/intel8x0.c	2004-02-18 08:54:13.000000000 +0000
+++ source/sound/pci/intel8x0.c	2004-02-23 13:56:48.000000000 +0000
@@ -143,6 +143,9 @@ MODULE_PARM_SYNTAX(mpu_port, SNDRV_ENABL
 #ifndef PCI_DEVICE_ID_NVIDIA_MCP3_AUDIO
 #define PCI_DEVICE_ID_NVIDIA_MCP3_AUDIO	0x00da
 #endif
+#ifndef PCI_DEVICE_ID_NVIDIA_CK8S_AUDIO
+#define PCI_DEVICE_ID_NVIDIA_CK8S_AUDIO	0x00ea
+#endif
 
 enum { DEVICE_INTEL, DEVICE_INTEL_ICH4, DEVICE_SIS, DEVICE_ALI, DEVICE_NFORCE };
 
@@ -443,6 +446,7 @@ static struct pci_device_id snd_intel8x0
 	{ 0x10de, 0x01b1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_NFORCE },	/* NFORCE */
 	{ 0x10de, 0x006a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_NFORCE },	/* NFORCE2 */
 	{ 0x10de, 0x00da, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_NFORCE },	/* NFORCE3 */
+	{ 0x10de, 0x00ea, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_NFORCE },	/* CK8S */
 	{ 0x1022, 0x746d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_INTEL },	/* AMD8111 */
 	{ 0x1022, 0x7445, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_INTEL },	/* AMD768 */
 	{ 0x10b9, 0x5455, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_ALI },   /* Ali5455 */
@@ -804,10 +808,19 @@ static irqreturn_t snd_intel8x0_interrup
 	spin_lock(&chip->reg_lock);
 	status = igetdword(chip, chip->int_sta_reg);
 	if ((status & chip->int_sta_mask) == 0) {
-		if (status)
+		static int err_count = 10;
+		if (status) {
+			/* ack */
 			iputdword(chip, chip->int_sta_reg, status);
+			status ^= igetdword(chip, chip->int_sta_reg);
+		}
 		spin_unlock(&chip->reg_lock);
-		return IRQ_NONE;
+		if (status && err_count) {
+			err_count--;
+			snd_printd("intel8x0: unknown IRQ bits 0x%x (sta_mask=0x%x)\n",
+				   status, chip->int_sta_mask);
+		}
+		return IRQ_RETVAL(status);
 	}
 
 	for (i = 0; i < chip->bdbars_count; i++) {
@@ -1017,6 +1030,7 @@ static snd_pcm_uframes_t snd_intel8x0_pc
 {
 	intel8x0_t *chip = snd_pcm_substream_chip(substream);
 	ichdev_t *ichdev = get_ichdev(substream);
+	unsigned long flags;
 	size_t ptr1, ptr;
 
 	ptr1 = igetword(chip, ichdev->reg_offset + ichdev->roff_picb) << chip->pcm_pos_shift;
@@ -1024,7 +1038,9 @@ static snd_pcm_uframes_t snd_intel8x0_pc
 		ptr = ichdev->fragsize1 - ptr1;
 	else
 		ptr = 0;
+	spin_lock_irqsave(&chip->reg_lock, flags);
 	ptr += ichdev->position;
+	spin_unlock_irqrestore(&chip->reg_lock, flags);
 	if (ptr >= ichdev->size)
 		return 0;
 	return bytes_to_frames(substream->runtime, ptr);
@@ -1741,6 +1757,12 @@ static struct ac97_quirk ac97_quirks[] _
 	},
 	{
 		.vendor = 0x8086,
+		.device = 0x4856,
+		.name = "Intel D845WN (82801BA)",
+		.type = AC97_TUNE_SWAP_HP
+	},
+	{
+		.vendor = 0x8086,
 		.device = 0x4d44,
 		.name = "Intel D850EMV2",	/* AD1885 */
 		.type = AC97_TUNE_HP_ONLY
@@ -2567,6 +2589,7 @@ static struct shortname_table {
 	{ PCI_DEVICE_ID_NVIDIA_MCP_AUDIO, "NVidia nForce" },
 	{ PCI_DEVICE_ID_NVIDIA_MCP2_AUDIO, "NVidia nForce2" },
 	{ PCI_DEVICE_ID_NVIDIA_MCP3_AUDIO, "NVidia nForce3" },
+	{ PCI_DEVICE_ID_NVIDIA_CK8S_AUDIO, "NVidia CK8S" },
 	{ 0x746d, "AMD AMD8111" },
 	{ 0x7445, "AMD AMD768" },
 	{ 0x5455, "ALi M5455" },
--- diff/sound/pci/via82xx.c	2004-02-18 08:54:13.000000000 +0000
+++ source/sound/pci/via82xx.c	2004-02-23 13:56:48.000000000 +0000
@@ -922,12 +922,10 @@ static int snd_via8233_playback_prepare(
 				  chip->no_vra ? 48000 : runtime->rate);
 		snd_ac97_set_rate(chip->ac97, AC97_SPDIF, runtime->rate);
 	}
-#if 0
-	if (chip->revision == VIA_REV_8233A)
-		rbits = 0;
+	if (runtime->rate == 48000)
+		rbits = 0xfffff;
 	else
-#endif
-		rbits = (0xfffff / 48000) * runtime->rate + ((0xfffff % 48000) * runtime->rate) / 48000;
+		rbits = (0x100000 / 48000) * runtime->rate + ((0x100000 % 48000) * runtime->rate) / 48000;
 	snd_assert((rbits & ~0xfffff) == 0, return -EINVAL);
 	snd_via82xx_channel_reset(chip, viadev);
 	snd_via82xx_set_table_ptr(chip, viadev);
@@ -1989,11 +1987,12 @@ static int __devinit check_dxs_list(stru
 		{ .vendor = 0x1106, .device = 0x4161, .action = VIA_DXS_NO_VRA }, /* ASRock K7VT2 */
 		{ .vendor = 0x1297, .device = 0xa232, .action = VIA_DXS_ENABLE }, /* Shuttle ?? */
 		{ .vendor = 0x1297, .device = 0xc160, .action = VIA_DXS_ENABLE }, /* Shuttle SK41G */
-		{ .vendor = 0x1458, .device = 0xa002, .action = VIA_DXS_ENABLE }, /* Gigabyte GA-7VAXP */
+		{ .vendor = 0x1458, .device = 0xa002, .action = VIA_DXS_NO_VRA }, /* Gigabyte GA-7VAXP (FIXME: or DXS_ENABLE?) */
 		{ .vendor = 0x147b, .device = 0x1401, .action = VIA_DXS_ENABLE }, /* ABIT KD7(-RAID) */
 		{ .vendor = 0x14ff, .device = 0x0403, .action = VIA_DXS_ENABLE }, /* Twinhead mobo */
 		{ .vendor = 0x1462, .device = 0x3800, .action = VIA_DXS_ENABLE }, /* MSI KT266 */
 		{ .vendor = 0x1462, .device = 0x7120, .action = VIA_DXS_ENABLE }, /* MSI KT4V */
+		{ .vendor = 0x1462, .device = 0x5901, .action = VIA_DXS_NO_VRA }, /* MSI KT6 Delta-SR */
 		{ .vendor = 0x1631, .device = 0xe004, .action = VIA_DXS_ENABLE }, /* Easy Note 3174, Packard Bell */
 		{ .vendor = 0x1695, .device = 0x3005, .action = VIA_DXS_ENABLE }, /* EPoX EP-8K9A */
 		{ .vendor = 0x1849, .device = 0x3059, .action = VIA_DXS_NO_VRA }, /* ASRock K7VM2 */
--- diff/sound/usb/usbaudio.c	2004-02-18 08:54:13.000000000 +0000
+++ source/sound/usb/usbaudio.c	2004-02-23 13:56:48.000000000 +0000
@@ -117,7 +117,7 @@ struct audioformat {
 	struct list_head list;
 	snd_pcm_format_t format;	/* format type */
 	unsigned int channels;		/* # channels */
-	unsigned int nonaudio: 1;	/* non-audio (type II) */
+	unsigned int fmt_type;		/* USB audio format type (1-3) */
 	unsigned int frame_size;	/* samples per frame for non-audio */
 	int iface;			/* interface number */
 	unsigned char altsetting;	/* corresponding alternate setting */
@@ -171,7 +171,7 @@ struct snd_usb_substream {
 	unsigned int curpacksize;	/* current packet size in bytes (for capture) */
 	unsigned int curframesize;	/* current packet size in frames (for capture) */
 	unsigned int fill_max: 1;	/* fill max packet size always */
-	unsigned int nonaudio: 1;	/* Type II format (MPEG, AC3) */
+	unsigned int fmt_type;		/* USB audio format type (1-3) */
 
 	unsigned int running: 1;	/* running status */
 
@@ -201,6 +201,7 @@ struct snd_usb_stream {
 	snd_usb_audio_t *chip;
 	snd_pcm_t *pcm;
 	int pcm_index;
+	unsigned int fmt_type;		/* USB audio format type (1-3) */
 	snd_usb_substream_t substream[2];
 	struct list_head list;
 };
@@ -477,7 +478,7 @@ static int prepare_playback_urb(snd_usb_
 		subs->transfer_sched += counts;
 		if (subs->transfer_sched >= runtime->period_size) {
 			subs->transfer_sched -= runtime->period_size;
-			if (subs->nonaudio) {
+			if (subs->fmt_type == USB_FORMAT_TYPE_II) {
 				if (subs->transfer_sched > 0) {
 					/* FIXME: fill-max mode is not supported yet */
 					offs -= subs->transfer_sched;
@@ -894,7 +895,7 @@ static int init_substream_urbs(snd_usb_s
 		u->subs = subs;
 		u->transfer = 0;
 		u->packets = npacks[i];
-		if (subs->nonaudio)
+		if (subs->fmt_type == USB_FORMAT_TYPE_II)
 			u->packets++; /* for transfer delimiter */
 		if (! is_playback) {
 			/* allocate a capture buffer per urb */
@@ -1588,7 +1589,7 @@ static int setup_hw_info(snd_pcm_runtime
 			runtime->hw.channels_min = fp->channels;
 		if (runtime->hw.channels_max < fp->channels)
 			runtime->hw.channels_max = fp->channels;
-		if (fp->nonaudio && fp->frame_size > 0) {
+		if (fp->fmt_type == USB_FORMAT_TYPE_II && fp->frame_size > 0) {
 			/* FIXME: there might be more than one audio formats... */
 			runtime->hw.period_bytes_min = runtime->hw.period_bytes_max =
 				fp->frame_size;
@@ -1895,7 +1896,7 @@ static void init_substream(snd_usb_strea
 	subs->formats |= 1ULL << fp->format;
 	subs->endpoint = fp->endpoint;
 	subs->num_formats++;
-	subs->nonaudio = fp->nonaudio;
+	subs->fmt_type = fp->fmt_type;
 }
 
 
@@ -1954,17 +1955,12 @@ static int add_audio_endpoint(snd_usb_au
 
 	list_for_each(p, &chip->pcm_list) {
 		as = list_entry(p, snd_usb_stream_t, list);
+		if (as->fmt_type != fp->fmt_type)
+			continue;
 		subs = &as->substream[stream];
 		if (! subs->endpoint)
-			break;
+			continue;
 		if (subs->endpoint == fp->endpoint) {
-			if (fp->nonaudio) {
-				if (!subs->nonaudio || subs->formats != (1ULL << fp->format))
-					continue; /* non-linear formats are handled exclusively */
-			} else {
-				if (subs->nonaudio)
-					continue;
-			}
 			list_add_tail(&fp->list, &subs->fmt_list);
 			subs->num_formats++;
 			subs->formats |= 1ULL << fp->format;
@@ -1974,6 +1970,8 @@ static int add_audio_endpoint(snd_usb_au
 	/* look for an empty stream */
 	list_for_each(p, &chip->pcm_list) {
 		as = list_entry(p, snd_usb_stream_t, list);
+		if (as->fmt_type != fp->fmt_type)
+			continue;
 		subs = &as->substream[stream];
 		if (subs->endpoint)
 			continue;
@@ -1991,6 +1989,7 @@ static int add_audio_endpoint(snd_usb_au
 	memset(as, 0, sizeof(*as));
 	as->pcm_index = chip->pcm_devs;
 	as->chip = chip;
+	as->fmt_type = fp->fmt_type;
 	err = snd_pcm_new(chip->card, "USB Audio", chip->pcm_devs,
 			  stream == SNDRV_PCM_STREAM_PLAYBACK ? 1 : 0,
 			  stream == SNDRV_PCM_STREAM_PLAYBACK ? 0 : 1,
@@ -2216,7 +2215,6 @@ static int parse_audio_format_ii(struct 
 		break;
 	}
 	fp->channels = 1;
-	fp->nonaudio = 1;
 	brate = combine_word(&fmt[4]); 	/* fmt[4,5] : wMaxBitRate (in kbps) */
 	framesize = combine_word(&fmt[6]); /* fmt[6,7]: wSamplesPerFrame */
 	snd_printd(KERN_INFO "found format II with max.bitrate = %d, frame size=%d\n", brate, framesize);
@@ -2242,6 +2240,7 @@ static int parse_audio_format(struct usb
 			   dev->devnum, fp->iface, fp->altsetting, fmt[3]);
 		return -1;
 	}
+	fp->fmt_type = fmt[3];
 	if (err < 0)
 		return err;
 #if 1
--- diff/sound/usb/usbquirks.h	2004-02-18 08:54:13.000000000 +0000
+++ source/sound/usb/usbquirks.h	2004-02-23 13:56:48.000000000 +0000
@@ -502,6 +502,32 @@ YAMAHA_DEVICE(0x5008, "01V96"),
 	}
 },
 {
+	/*
+	 * This quirk is for the "Advanced Driver" mode. If off, the UA-3FX
+	 * is standard compliant, but has only 16-bit PCM.
+	 */
+	USB_DEVICE(0x0582, 0x0050),
+	.driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) {
+		.vendor_name = "EDIROL",
+		.product_name = "UA-3FX",
+		.ifnum = QUIRK_ANY_INTERFACE,
+		.type = QUIRK_COMPOSITE,
+		.data = & (const snd_usb_audio_quirk_t[]) {
+			{
+				.ifnum = 1,
+				.type = QUIRK_AUDIO_STANDARD_INTERFACE
+			},
+			{
+				.ifnum = 2,
+				.type = QUIRK_AUDIO_STANDARD_INTERFACE
+			},
+			{
+				.ifnum = -1
+			}
+		}
+	}
+},
+{
 	USB_DEVICE(0x0582, 0x0052),
 	.driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) {
 		.vendor_name = "EDIROL",
@@ -688,4 +714,14 @@ YAMAHA_DEVICE(0x5008, "01V96"),
 	
 },
 
+{
+	USB_DEVICE_VENDOR_SPEC(0x0ccd, 0x0013),
+	.driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) {
+		.vendor_name = "Terratec",
+		.product_name = "PHASE 26",
+		.ifnum = 3,
+		.type = QUIRK_MIDI_STANDARD_INTERFACE
+	}
+},
+
 #undef USB_DEVICE_VENDOR_SPEC
--- diff/usr/gen_init_cpio.c	2004-01-19 10:22:59.000000000 +0000
+++ source/usr/gen_init_cpio.c	2004-02-23 13:56:48.000000000 +0000
@@ -56,7 +56,7 @@ static void cpio_trailer(void)
 	const char name[] = "TRAILER!!!";
 
 	sprintf(s, "%s%08X%08X%08lX%08lX%08X%08lX"
-	       "%08X%08X%08X%08X%08X%08ZX%08X",
+	       "%08X%08X%08X%08X%08X%08X%08X",
 		"070701",		/* magic */
 		0,			/* ino */
 		0,			/* mode */
@@ -69,7 +69,7 @@ static void cpio_trailer(void)
 		0,			/* minor */
 		0,			/* rmajor */
 		0,			/* rminor */
-		strlen(name) + 1,	/* namesize */
+		(unsigned)strlen(name) + 1, /* namesize */
 		0);			/* chksum */
 	push_hdr(s);
 	push_rest(name);
@@ -87,7 +87,7 @@ static void cpio_mkdir(const char *name,
 	time_t mtime = time(NULL);
 
 	sprintf(s,"%s%08X%08X%08lX%08lX%08X%08lX"
-	       "%08X%08X%08X%08X%08X%08ZX%08X",
+	       "%08X%08X%08X%08X%08X%08X%08X",
 		"070701",		/* magic */
 		ino++,			/* ino */
 		S_IFDIR | mode,		/* mode */
@@ -100,7 +100,7 @@ static void cpio_mkdir(const char *name,
 		1,			/* minor */
 		0,			/* rmajor */
 		0,			/* rminor */
-		strlen(name) + 1,	/* namesize */
+		(unsigned)strlen(name) + 1,/* namesize */
 		0);			/* chksum */
 	push_hdr(s);
 	push_rest(name);
@@ -119,7 +119,7 @@ static void cpio_mknod(const char *name,
 		mode |= S_IFCHR;
 
 	sprintf(s,"%s%08X%08X%08lX%08lX%08X%08lX"
-	       "%08X%08X%08X%08X%08X%08ZX%08X",
+	       "%08X%08X%08X%08X%08X%08X%08X",
 		"070701",		/* magic */
 		ino++,			/* ino */
 		mode,			/* mode */
@@ -132,7 +132,7 @@ static void cpio_mknod(const char *name,
 		1,			/* minor */
 		maj,			/* rmajor */
 		min,			/* rminor */
-		strlen(name) + 1,	/* namesize */
+		(unsigned)strlen(name) + 1,/* namesize */
 		0);			/* chksum */
 	push_hdr(s);
 	push_rest(name);
@@ -176,7 +176,7 @@ void cpio_mkfile(const char *filename, c
 	}
 
 	sprintf(s,"%s%08X%08X%08lX%08lX%08X%08lX"
-	       "%08X%08X%08X%08X%08X%08ZX%08X",
+	       "%08X%08X%08X%08X%08X%08X%08X",
 		"070701",		/* magic */
 		ino++,			/* ino */
 		mode,			/* mode */
@@ -189,7 +189,7 @@ void cpio_mkfile(const char *filename, c
 		1,			/* minor */
 		0,			/* rmajor */
 		0,			/* rminor */
-		strlen(location) + 1,	/* namesize */
+		(unsigned)strlen(location) + 1,/* namesize */
 		0);			/* chksum */
 	push_hdr(s);
 	push_string(location);
--- diff/usr/initramfs_data.S	2003-08-20 14:16:15.000000000 +0100
+++ source/usr/initramfs_data.S	2004-02-23 13:56:48.000000000 +0000
@@ -1,28 +1,6 @@
 /*
   initramfs_data includes the compressed binary that is the
   filesystem used for early user space.
-  Note: Older versions of "as" (prior to binutils 2.11.90.0.23
-  released on 2001-07-14) dit not support .incbin.
-  If you are forced to use older binutils than that then the
-  following trick can be applied to create the resulting binary:
-
-
-  ld -m elf_i386  --format binary --oformat elf32-i386 -r \
-  -T initramfs_data.scr initramfs_data.cpio.gz -o initramfs_data.o
-   ld -m elf_i386  -r -o built-in.o initramfs_data.o
-
-  initramfs_data.scr looks like this:
-SECTIONS
-{
-       .init.ramfs : { *(.data) }
-}
-
-  The above example is for i386 - the parameters vary from architectures.
-  Eventually look up LDFLAGS_BLOB in an older version of the
-  arch/$(ARCH)/Makefile to see the flags used before .incbin was introduced.
-
-  Using .incbin has the advantage over ld that the correct flags are set
-  in the ELF header, as required by certain architectures.
 */
 
 .section .init.ramfs,"a"
--- diff/Documentation/debugging-modules.txt	1970-01-01 01:00:00.000000000 +0100
+++ source/Documentation/debugging-modules.txt	2004-02-23 13:56:39.000000000 +0000
@@ -0,0 +1,18 @@
+Debugging Modules after 2.6.3
+-----------------------------
+
+In almost all distributions, the kernel asks for modules which don't
+exist, such as "net-pf-10" or whatever.  Changing "modprobe -q" to
+"succeed" in this case is hacky and breaks some setups, and also we
+want to know if it failed for the fallback code for old aliases in
+fs/char_dev.c, for example.
+
+In the past a debugging message which would fill people's logs was
+emitted.  This debugging message has been removed.  The correct way
+of debugging module problems is something like this:
+
+echo '#! /bin/sh' > /tmp/modprobe
+echo 'echo "$@" >> /tmp/modprobe.log' >> /tmp/modprobe
+echo 'exec /sbin/modprobe "$@"' >> /tmp/modprobe
+chmod a+x /tmp/modprobe
+echo /tmp/modprobe > /proc/sys/kernel/modprobe
--- diff/Documentation/filesystems/hfs.txt	1970-01-01 01:00:00.000000000 +0100
+++ source/Documentation/filesystems/hfs.txt	2004-02-23 13:56:39.000000000 +0000
@@ -0,0 +1,83 @@
+
+Macintosh HFS Filesystem for Linux
+==================================
+
+HFS stands for ``Hierarchical File System'' and is the filesystem used
+by the Mac Plus and all later Macintosh models.  Earlier Macintosh
+models used MFS (``Macintosh File System''), which is not supported,
+MacOS 8.1 and newer support a filesystem called HFS+ that's similar to
+HFS but is extended in various areas.  Use the hfsplus filesystem driver
+to access such filesystems from Linux.
+
+
+Mount options
+=============
+
+When mounting an HFS filesystem, the following options are accepted:
+
+  creator=cccc, type=cccc
+	Specifies the creator/type values as shown by the MacOS finder
+	used for creating new files.  Default values: '????'.
+
+  uid=n, gid=n
+  	Specifies the user/group that owns all files on the filesystems.
+	Default:  user/group id of the mounting process.
+
+  dir_umask=n, file_umask=n, umask=n
+	Specifies the umask used for all files , all directories or all
+	files and directories.  Defaults to the umask of the mounting process.
+
+  session=n
+  	Select the CDROM session to mount as HFS filesystem.  Defaults to
+	leaving that decision to the CDROM driver.  This option will fail
+	with anything but a CDROM as underlying devices.
+
+  part=n
+  	Select partition number n from the devices.  Does only makes
+	sense for CDROMS because they can't be partitioned under Linux.
+	For disk devices the generic partition parsing code does this
+	for us.  Defaults to not parsing the partition table at all.
+
+  quiet
+  	Ignore invalid mount options instead of complaining.
+
+
+Writing to HFS Filesystems
+==========================
+
+HFS is not a UNIX filesystem, thus it does not have the usual features you'd
+expect:
+
+ o You can't modify the set-uid, set-gid, sticky or executable bits or the uid
+   and gid of files.
+ o You can't create hard- or symlinks, device files, sockets or FIFOs.
+
+HFS does on the other have the concepts of multiple forks per file.  These
+non-standard forks are represented as hidden additional files in the normal
+filesystems namespace which is kind of a cludge and makes the semantics for
+the a little strange:
+
+ o You can't create, delete or rename resource forks of files or the
+   Finder's metadata.
+ o They are however created (with default values), deleted and renamed
+   along with the corresponding data fork or directory.
+ o Copying files to a different filesystem will loose those attributes
+   that are essential for MacOS to work.
+
+
+Creating HFS filesystems
+===================================
+
+The hfsutils package from Robert Leslie contains a program called
+hformat that can be used to create HFS filesystem. See
+<http://www.mars.org/home/rob/proj/hfs/> for details.
+
+
+Credits
+=======
+
+The HFS drivers was written by Paul H. Hargrovea (hargrove@sccm.Stanford.EDU)
+and is now maintained by Roman Zippel (roman@ardistech.com) at Ardis
+Technologies.
+Roman rewrote large parts of the code and brought in btree routines derived
+from Brad Boyer's hfsplus driver (also maintained by Roman now).
--- diff/Documentation/i386/kgdb/andthen	1970-01-01 01:00:00.000000000 +0100
+++ source/Documentation/i386/kgdb/andthen	2004-02-23 13:56:39.000000000 +0000
@@ -0,0 +1,100 @@
+
+define	set_andthen
+	set var $thp=0
+	set var $thp=(struct kgdb_and_then_struct *)&kgdb_data[0]
+	set var $at_size = (sizeof kgdb_data)/(sizeof *$thp)
+	set var $at_oc=kgdb_and_then_count
+	set var $at_cc=$at_oc
+end
+
+define andthen_next
+	set var $at_cc=$arg0
+end
+
+define andthen
+	andthen_set_edge
+	if ($at_cc >= $at_oc)
+		printf "Outside window.  Window size is %d\n",($at_oc-$at_low)
+	else
+		printf "%d: ",$at_cc
+		output *($thp+($at_cc++ % $at_size ))
+		printf "\n"
+	end
+end
+define andthen_set_edge
+	set var $at_oc=kgdb_and_then_count
+	set var $at_low = $at_oc - $at_size
+	if ($at_low < 0 )
+		set var $at_low = 0
+	end
+	if (( $at_cc > $at_oc) || ($at_cc < $at_low))
+		printf "Count outside of window, setting count to "
+		if ($at_cc >= $at_oc)
+			set var $at_cc = $at_oc
+		else
+			set var $at_cc = $at_low
+		end
+		printf "%d\n",$at_cc
+	end
+end
+
+define beforethat
+	andthen_set_edge
+	if ($at_cc <= $at_low)
+		printf "Outside window.  Window size is %d\n",($at_oc-$at_low)
+	else
+		printf "%d: ",$at_cc-1
+		output *($thp+(--$at_cc % $at_size ))
+		printf "\n"
+	end
+end
+
+document andthen_next
+	andthen_next <count>
+	.	sets the number of the event to display next. If this event
+	.	is not in the event pool, either andthen or beforethat will
+	.	correct it to the nearest event pool edge.  The event pool
+	.	ends at the last event recorded and begins <number of events>
+	.	prior to that.  If beforethat is used next, it will display
+	.	event <count> -1.
+.
+	andthen commands are: set_andthen, andthen_next, andthen and beforethat
+end
+
+
+document andthen
+	andthen
+.	displays the next event in the list.  <set_andthen> sets up to display
+.	the oldest saved event first.
+.	<count> (optional) count of the event to display.
+.	note the number of events saved is specified at configure time.
+.	if events are saved between calls to andthen the index will change
+.	but the displayed event will be the next one (unless the event buffer
+.	is overrun).
+.
+.	andthen commands are: set_andthen, andthen_next, andthen and beforethat
+end
+
+document set_andthen
+	set_andthen
+.	sets up to use the <andthen> and <beforethat> commands.
+.		if you have defined your own struct, use the above and
+.		then enter the following:
+.		p $thp=(struct kgdb_and_then_structX *)&kgdb_data[0]
+.		where <kgdb_and_then_structX> is the name of your structure.
+.
+.	andthen commands are: set_andthen, andthen_next, andthen and beforethat
+end
+
+document beforethat
+	beforethat
+.	displays the next prior event in the list. <set_andthen> sets up to
+.	display the last occuring event first.
+.
+.	note the number of events saved is specified at configure time.
+.	if events are saved between calls to beforethat the index will change
+.	but the displayed event will be the next one (unless the event buffer
+.	is overrun).
+.
+.	andthen commands are: set_andthen, andthen_next, andthen and beforethat
+end
--- diff/Documentation/i386/kgdb/debug-nmi.txt	1970-01-01 01:00:00.000000000 +0100
+++ source/Documentation/i386/kgdb/debug-nmi.txt	2004-02-23 13:56:39.000000000 +0000
@@ -0,0 +1,37 @@
+Subject: Debugging with NMI
+Date: Mon, 12 Jul 1999 11:28:31 -0500
+From: David Grothe <dave@gcom.com>
+Organization: Gcom, Inc
+To: David Grothe <dave@gcom.com>
+
+Kernel hackers:
+
+Maybe this is old hat, but it is new to me --
+
+On an ISA bus machine, if you short out the A1 and B1 pins of an ISA
+slot you will generate an NMI to the CPU.  This interrupts even a
+machine that is hung in a loop with interrupts disabled.  Used in
+conjunction with kgdb <
+ftp://ftp.gcom.com/pub/linux/src/kgdb-2.3.35/kgdb-2.3.35.tgz > you can
+gain debugger control of a machine that is hung in the kernel!  Even
+without kgdb the kernel will print a stack trace so you can find out
+where it was hung.
+
+The A1/B1 pins are directly opposite one another and the farthest pins
+towards the bracket end of the ISA bus socket.  You can stick a paper
+clip or multi-meter probe between them to short them out.
+
+I had a spare ISA bus to PC104 bus adapter around.  The PC104 end of the
+board consists of two rows of wire wrap pins.  So I wired a push button
+between the A1/B1 pins and now have an ISA board that I can stick into
+any ISA bus slot for debugger entry.
+
+Microsoft has a circuit diagram of a PCI card at
+http://www.microsoft.com/hwdev/DEBUGGING/DMPSW.HTM.  If you want to
+build one you will have to mail them and ask for the PAL equations.
+Nobody makes one comercially.
+
+[THIS TIP COMES WITH NO WARRANTY WHATSOEVER.  It works for me, but if
+your machine catches fire, it is your problem, not mine.]
+
+-- Dave (the kgdb guy)
--- diff/Documentation/i386/kgdb/gdb-globals.txt	1970-01-01 01:00:00.000000000 +0100
+++ source/Documentation/i386/kgdb/gdb-globals.txt	2004-02-23 13:56:39.000000000 +0000
@@ -0,0 +1,71 @@
+Sender: akale@veritas.com
+Date: Fri, 23 Jun 2000 19:26:35 +0530
+From: "Amit S. Kale" <akale@veritas.com>
+Organization: Veritas Software (India)
+To: Dave Grothe <dave@gcom.com>, linux-kernel@vger.rutgers.edu
+CC: David Milburn <dmilburn@wirespeed.com>,
+        "Edouard G. Parmelan" <Edouard.Parmelan@quadratec.fr>,
+        ezannoni@cygnus.com, Keith Owens <kaos@ocs.com.au>
+Subject: Re: Module debugging using kgdb
+
+Dave Grothe wrote:
+>
+> Amit:
+>
+> There is a 2.4.0 version of kgdb on our ftp site:
+> ftp://ftp.gcom.com/pub/linux/src/kgdb.  I mirrored your version of gdb
+> and loadmodule.sh there.
+>
+> Have a look at the README file and see if I go it right.  If not, send
+> me some corrections and I will update it.
+>
+> Does your version of gdb solve the global variable problem?
+
+Yes.
+Thanks to Elena Zanoni, gdb (developement version) can now calculate
+correctly addresses  of dynamically loaded object files. I have not been
+following gdb developement for sometime and am not sure when symbol
+address calculation fix is going to appear in a gdb stable version.
+
+Elena, any idea when the fix will make it to a prebuilt gdb from a
+redhat release?
+
+For the time being I have built a gdb developement version. It can be
+used for module debugging with loadmodule.sh script.
+
+The problem with calculating of module addresses with previous versions
+of gdb was as follows:
+gdb did not use base address of a section while calculating address of
+a symbol in the section in an object file loaded via 'add-symbol-file'.
+It used address of .text segment instead. Due to this addresses of
+symbols in .data, .bss etc. (e.g. global variables) were calculated incorrectly.
+
+Above mentioned fix allow gdb to use base address of a segment while
+calculating address of a symbol in it. It adds a parameter '-s' to
+'add-symbol-file' command for specifying base address of a segment.
+
+loadmodule.sh script works as follows.
+
+1. Copy a module file to target machine.
+2. Load the module on the target machine using insmod with -m parameter.
+insmod produces a module load map which contains base addresses of all
+sections in the module and addresses of symbols in the module file.
+3. Find all sections and their base addresses in the module from
+the module map.
+4. Generate a script that loads the module file. The script uses
+'add-symbol-file' and specifies address of text segment followed by
+addresses of all segments in the module.
+
+Here is an example gdb script produced by loadmodule.sh script.
+
+add-symbol-file foo 0xd082c060 -s .text.lock 0xd08cbfb5
+-s .fixup 0xd08cfbdf -s .rodata 0xd08cfde0 -s __ex_table 0xd08e3b38
+-s .data 0xd08e3d00 -s .bss 0xd08ec8c0 -s __ksymtab 0xd08ee838
+
+With this command gdb can calculate addresses of symbols in ANY segment
+in a module file.
+
+Regards.
+--
+Amit Kale
+Veritas Software ( http://www.veritas.com )
--- diff/Documentation/i386/kgdb/gdbinit	1970-01-01 01:00:00.000000000 +0100
+++ source/Documentation/i386/kgdb/gdbinit	2004-02-23 13:56:39.000000000 +0000
@@ -0,0 +1,14 @@
+shell echo -e "\003" >/dev/ttyS0
+set remotebaud 38400
+target remote /dev/ttyS0
+define si
+stepi
+printf "EAX=%08x EBX=%08x ECX=%08x EDX=%08x\n", $eax, $ebx, $ecx, $edx
+printf "ESI=%08x EDI=%08x EBP=%08x ESP=%08x\n", $esi, $edi, $ebp, $esp
+x/i $eip
+end
+define ni
+nexti
+printf "EAX=%08x EBX=%08x ECX=%08x EDX=%08x\n", $eax, $ebx, $ecx, $edx
+printf "ESI=%08x EDI=%08x EBP=%08x ESP=%08x\n", $esi, $edi, $ebp, $esp
+x/i $eip
--- diff/Documentation/i386/kgdb/gdbinit-modules	1970-01-01 01:00:00.000000000 +0100
+++ source/Documentation/i386/kgdb/gdbinit-modules	2004-02-23 13:56:39.000000000 +0000
@@ -0,0 +1,146 @@
+#
+# Usefull GDB user-command to debug Linux Kernel Modules with gdbstub.
+#
+# This don't work for Linux-2.0 or older.
+#
+# Author Edouard G. Parmelan <Edouard.Parmelan@quadratec.fr>
+#
+#
+# Fri Apr 30 20:33:29 CEST 1999
+#   First public release.
+#
+#   Major cleanup after experiment Linux-2.0 kernel without success.
+#   Symbols of a module are not in the correct order, I can't explain
+#   why :(
+#
+# Fri Mar 19 15:41:40 CET 1999
+#   Initial version.
+#
+# Thu Jan  6 16:29:03 CST 2000
+#   A little fixing by Dave Grothe <dave@gcom.com>
+#
+# Mon Jun 19 09:33:13 CDT 2000
+#   Alignment changes from Edouard Parmelan
+#
+# The basic idea is to find where insmod load the module and inform
+# GDB to load the symbol table of the module with the GDB command
+# ``add-symbol-file <object> <address>''.
+#
+# The Linux kernel holds the list of all loaded modules in module_list,
+# this list end with &kernel_module (exactly with module->next == NULL,
+# but the last module is not a real module).
+#
+# Insmod allocates the struct module before the object file.  Since
+# Linux-2.1, this structure contain his size.  The real address of
+# the object file is then (char*)module + module->size_of_struct.
+#
+# You can use three user functions ``mod-list'', ``mod-print-symbols''
+# and ``add-module-symbols''.
+#
+# mod-list list all loaded modules with the format:
+#    <module-address> <module-name>
+#
+# As soon as you have found the address of your module, you can
+# print its exported symbols (mod-print-symbols) or inform GDB to add
+# symbols from your module file (mod-add-symbols).
+#
+# The argument that you give to mod-print-symbols or mod-add-symbols
+# is the <module-address> from the mod-list command.
+#
+# When using the mod-add-symbols command you must also give the full
+# pathname of the modules object code file.
+#
+# The command mod-add-lis is an example of how to make this easier.
+# You can edit this macro to contain the path name of your own
+# favorite module and then use it as a shorthand to load it.  You
+# still need the module-address, however.
+#
+# The internal function ``mod-validate'' set the GDB variable $mod
+# as a ``struct module*'' if the kernel known the module otherwise
+# $mod is set to NULL.  This ensure to not add symbols for a wrong
+# address.
+#
+# Have a nice hacking day !
+#
+#
+define mod-list
+    set $mod = (struct module*)module_list
+    # the last module is the kernel, ignore it
+    while $mod != &kernel_module
+    	printf "%p\t%s\n", (long)$mod, ($mod)->name
+	set $mod = $mod->next
+    end
+end
+document mod-list
+List all modules in the form: <module-address> <module-name>
+Use the <module-address> as the argument for the other
+mod-commands: mod-print-symbols, mod-add-symbols.
+end
+
+define mod-validate
+    set $mod = (struct module*)module_list
+    while ($mod != $arg0) && ($mod != &kernel_module)
+    	set $mod = $mod->next
+    end
+    if $mod == &kernel_module
+	set $mod = 0
+    	printf "%p is not a module\n", $arg0
+    end
+end
+document mod-validate
+mod-validate <module-address>
+Internal user-command used to validate the module parameter.
+If <module> is a real loaded module, set $mod to it otherwise set $mod to 0.
+end
+
+
+define mod-print-symbols
+    mod-validate $arg0
+    if $mod != 0
+	set $i = 0
+	while $i < $mod->nsyms
+	    set $sym = $mod->syms[$i]
+	    printf "%p\t%s\n", $sym->value, $sym->name
+	    set $i = $i + 1
+	end
+    end
+end
+document mod-print-symbols
+mod-print-symbols <module-address>
+Print all exported symbols of the module.  see mod-list
+end
+
+
+define mod-add-symbols-align
+    mod-validate $arg0
+    if $mod != 0
+	set $mod_base = ($mod->size_of_struct + (long)$mod)
+	if ($arg2 != 0) && (($mod_base & ($arg2 - 1)) != 0)
+	    set $mod_base = ($mod_base | ($arg2 - 1)) + 1
+	end
+	add-symbol-file $arg1 $mod_base
+    end
+end
+document mod-add-symbols-align
+mod-add-symbols-align <module-address> <object file path name> <align>
+Load the symbols table of the module from the object file where
+first section aligment is <align>.
+To retreive alignment, use `objdump -h <object file path name>'.
+end
+
+define mod-add-symbols
+    mod-add-symbols-align $arg0 $arg1 sizeof(long)
+end
+document mod-add-symbols
+mod-add-symbols <module-address> <object file path name>
+Load the symbols table of the module from the object file.
+Default alignment is 4.  See mod-add-symbols-align.
+end
+
+define mod-add-lis
+    mod-add-symbols-align $arg0 /usr/src/LiS/streams.o 16
+end
+document mod-add-lis
+mod-add-lis <module-address>
+Does mod-add-symbols <module-address> /usr/src/LiS/streams.o
+end
--- diff/Documentation/i386/kgdb/gdbinit.hw	1970-01-01 01:00:00.000000000 +0100
+++ source/Documentation/i386/kgdb/gdbinit.hw	2004-02-23 13:56:39.000000000 +0000
@@ -0,0 +1,117 @@
+
+#Using ia-32 hardware breakpoints.
+#
+#4 hardware breakpoints are available in ia-32 processors. These breakpoints
+#do not need code modification. They are set using debug registers.
+#
+#Each hardware breakpoint can be of one of the
+#three types: execution, write, access.
+#1. An Execution breakpoint is triggered when code at the breakpoint address is
+#executed.
+#2. A write breakpoint ( aka watchpoints ) is triggered when memory location
+#at the breakpoint address is written.
+#3. An access breakpoint is triggered when memory location at the breakpoint
+#address is either read or written.
+#
+#As hardware breakpoints are available in limited number, use software
+#breakpoints ( br command in gdb ) instead of execution hardware breakpoints.
+#
+#Length of an access or a write breakpoint defines length of the datatype to
+#be watched. Length is 1 for char, 2 short , 3 int.
+#
+#For placing execution, write and access breakpoints, use commands
+#hwebrk, hwwbrk, hwabrk
+#To remove a breakpoint use hwrmbrk command.
+#
+#These commands take following types of arguments. For arguments associated
+#with each command, use help command.
+#1. breakpointno: 0 to 3
+#2. length: 1 to 3
+#3. address: Memory location in hex ( without 0x ) e.g c015e9bc
+#
+#Use the command exinfo to find which hardware breakpoint occured.
+
+#hwebrk breakpointno address
+define hwebrk
+	maintenance packet Y$arg0,0,0,$arg1
+end
+document hwebrk
+	hwebrk <breakpointno> <address>
+	Places a hardware execution breakpoint
+	<breakpointno> = 0 - 3
+	<address> = Hex digits without leading "0x".
+end
+
+#hwwbrk breakpointno length address
+define hwwbrk
+	maintenance packet Y$arg0,1,$arg1,$arg2
+end
+document hwwbrk
+	hwwbrk <breakpointno> <length> <address>
+	Places a hardware write breakpoint
+	<breakpointno> = 0 - 3
+	<length> = 1 (1 byte), 2 (2 byte), 3 (4 byte)
+	<address> = Hex digits without leading "0x".
+end
+
+#hwabrk breakpointno length address
+define hwabrk
+	maintenance packet Y$arg0,1,$arg1,$arg2
+end
+document hwabrk
+	hwabrk <breakpointno> <length> <address>
+	Places a hardware access breakpoint
+	<breakpointno> = 0 - 3
+	<length> = 1 (1 byte), 2 (2 byte), 3 (4 byte)
+	<address> = Hex digits without leading "0x".
+end
+
+#hwrmbrk breakpointno
+define hwrmbrk
+	maintenance packet y$arg0
+end
+document hwrmbrk
+	hwrmbrk <breakpointno>
+	<breakpointno> = 0 - 3
+	Removes a hardware breakpoint
+end
+
+define reboot
+        maintenance packet r
+end
+#exinfo
+define exinfo
+	maintenance packet qE
+end
+document exinfo
+	exinfo
+	Gives information about a breakpoint.
+end
+define get_th
+	p $th=(struct thread_info *)((int)$esp & ~8191)
+end
+document get_th
+	get_tu
+	Gets and prints the current thread_info pointer, Defines th to be it.
+end
+define get_cu
+	p $cu=((struct thread_info *)((int)$esp & ~8191))->task
+end
+document get_cu
+	get_cu
+	Gets and print the "current" value.  Defines $cu to be it.
+end
+define int_off
+	set var $flags=$eflags
+	set $eflags=$eflags&~0x200
+	end
+define int_on
+	set var $eflags|=$flags&0x200
+	end
+document int_off
+	saves the current interrupt state and clears the processor interrupt
+	flag.  Use int_on to restore the saved flag.
+end
+document int_on
+	Restores the interrupt flag saved by int_off.
+end
--- diff/Documentation/i386/kgdb/kgdb.txt	1970-01-01 01:00:00.000000000 +0100
+++ source/Documentation/i386/kgdb/kgdb.txt	2004-02-23 13:56:39.000000000 +0000
@@ -0,0 +1,775 @@
+Last edit: <20030806.1637.12>
+This file has information specific to the i386 kgdb option.  Other
+platforms with the kgdb option may behave in a similar fashion.
+
+New features:
+============
+20030806.1557.37
+This version was made against the 2.6.0-test2 kernel. We have made the
+following changes:
+
+- The getthread() code in the stub calls find_task_by_pid().  It fails
+  if we are early in the bring up such that the pid arrays have yet to
+  be allocated.  We have added a line to kernel/pid.c to make
+  "kgdb_pid_init_done" true once the arrays are allocated.  This way the
+  getthread() code knows not to call.  This is only used by the thread
+  debugging stuff and threads will not yet exist at this point in the
+  boot.
+
+- For some reason, gdb was not asking for a new thread list when the
+  "info thread" command was given.  We changed to the newer version of
+  the thread info command and gdb now seems to ask when needed.  Result,
+  we now get all threads in the thread list.
+
+- We now respond to the ThreadExtraInfo request from gdb with the thread
+  name from task_struct .comm.  This then appears in the thread list.
+  Thoughts on additional options for this are welcome.  Things such as
+  "has BKL" and "Preempted" come to mind.  I think we could have a flag
+  word that could enable different bits of info here.
+
+- We now honor, sort of, the C and S commands.  These are continue and
+  single set after delivering a signal.  We ignore the signal and do the
+  requested action.  This only happens when we told gdb that a signal
+  was the reason for entry, which is only done on memory faults.  The
+  result is that you can now continue into the Oops.
+
+- We changed the -g to -gdwarf-2.  This seems to be the same as -ggdb,
+  but it is more exact on what language to use.
+
+- We added two dwarf2 include files and a bit of code at the end of
+  entry.S.  This does not yet work, so it is disabled.  Still we want to
+  keep track of the code and "maybe" someone out there can fix it.
+
+- Randy Dunlap sent some fix ups for this file which are now merged.
+
+- Hugh Dickins sent a fix to a bit of code in traps.c that prevents a
+  compiler warning if CONFIG_KGDB is off (now who would do that :).
+
+- Andrew Morton sent a fix for the serial driver which is now merged.
+
+- Andrew also sent a change to the stub around the cpu managment code
+  which is also merged.
+
+- Andrew also sent a patch to make "f" as well as "g" work as SysRq
+  commands to enter kgdb, merged.
+
+- If CONFIG_KGDB and CONFIG_DEBUG_SPINLOCKS are both set we added a
+  "who" field to the spinlock data struct.  This is filled with
+  "current" when ever the spinlock suceeds.  Useful if you want to know
+  who has the lock.
+
+_ And last, but not least, we fixed the "get_cu" macro to properly get
+  the current value of "current".
+
+New features:
+============
+20030505.1827.27
+We are starting to align with the sourceforge version, at least in
+commands.  To this end, the boot command string to start kgdb at
+boot time has been changed from "kgdb" to "gdb".
+
+Andrew Morton sent a couple of patches which are now included as follows:
+1.) We now return a flag to the interrupt handler.
+2.) We no longer use smp_num_cpus (a conflict with the lock meter).
+3.) And from William Lee Irwin III <wli@holomorphy.com> code to make
+    sure high-mem is set up before we attempt to register our interrupt
+    handler.
+We now include asm/kgdb.h from config.h so you will most likely never
+have to include it.  It also 'NULLS' the kgdb macros you might have in
+your code when CONFIG_KGDB is not defined.  This allows you to just
+turn off CONFIG_KGDB to turn off all the kgdb_ts() calls and such.
+This include is conditioned on the machine being an x86 so as to not
+mess with other archs.
+
+20020801.1129.03
+This is currently the version for the 2.4.18 (and beyond?) kernel.
+
+We have several new "features" beginning with this version:
+
+1.) Kgdb now syncs the "other" CPUs with a cross-CPU NMI.  No more
+    waiting and it will pull that guy out of an IRQ off spin lock :)
+
+2.) We doctored up the code that tells where a task is waiting and
+    included it so that the "info thread" command will show a bit more
+    than "schedule()".  Try it...
+
+3.) Added the ability to call a function from gdb.  All the standard gdb
+    issues apply, i.e. if you hit a breakpoint in the function, you are
+    not allowed to call another (gdb limitation, not kgdb).  To help
+    this capability we added a memory allocation function.  Gdb does not
+    return this memory (it is used for strings that you pass to that function
+    you are calling from gdb) so we fixed up a way to allow you to
+    manually return the memory (see below).
+
+4.) Kgdb time stamps (kgdb_ts()) are enhanced to expand what was the
+    interrupt flag to now also include the preemption count and the
+    "in_interrupt" info.  The flag is now called "with_pif" to indicate
+    the order, preempt_count, in_interrupt, flag.  The preempt_count is
+    shifted left by 4 bits so you can read the count in hex by dropping
+    the low order digit.  In_interrupt is in bit 1, and the flag is in
+    bit 0.
+
+5.) The command: "p kgdb_info" is now expanded and prints something
+    like:
+(gdb) p kgdb_info
+$2 = {used_malloc = 0, called_from = 0xc0107506, entry_tsc = 67468627259,
+  errcode = 0, vector = 3, print_debug_info = 0, hold_on_sstep = 1,
+  cpus_waiting = {{task = 0xc027a000, pid = 32768, hold = 0,
+      regs = 0xc027bf84}, {task = 0x0, pid = 0, hold = 0, regs = 0x0}}}
+
+    Things to note here: a.) used_malloc is the amount of memory that
+    has been malloc'ed to do calls from gdb.  You can reclaim this
+    memory like this: "p kgdb_info.used_malloc=0" Cool, huh?  b.)
+    cpus_waiting is now "sized" by the number of CPUs you enter at
+    configure time in the kgdb configure section.  This is NOT used
+    anywhere else in the system, but it is "nice" here.  c.)  The task's
+    "pid" is now in the structure.  This is the pid you will need to use
+    to decode to the thread id to get gdb to look at that thread.
+    Remember that the "info thread" command prints a list of threads
+    wherein it numbers each thread with its reference number followed
+    by the thread's pid.  Note that the per-CPU idle threads actually
+    have pids of 0 (yes, there is more than one pid 0 in an SMP system).
+    To avoid confusion, kgdb numbers these threads with numbers beyond
+    the MAX_PID.  That is why you see 32768 and above.
+
+6.) A subtle change, we now provide the complete register set for tasks
+    that are active on the other CPUs.  This allows better trace back on
+    those tasks.
+
+    And, let's mention what we could not fix.  Back-trace from all but the
+    thread that we trapped will, most likely, have a bogus entry in it.
+    The problem is that gdb does not recognize the entry code for
+    functions that use "current" near (at all?) the entry.  The compiler
+    is putting the "current" decode as the first two instructions of the
+    function where gdb expects to find %ebp changing code.  Back trace
+    also has trouble with interrupt frames.  I am talking with Daniel
+    Jacobowitz about some way to fix this, but don't hold your breath.
+
+20011220.0050.35
+Major enhancement with this version is the ability to hold one or more
+CPUs in an SMP system while allowing the others to continue.  Also, by
+default only the current CPU is enabled on single-step commands (please
+note that gdb issues single-step commands at times other than when you
+use the si command).
+
+Another change is to collect some useful information in
+a global structure called "kgdb_info".  You should be able to just:
+
+p kgdb_info
+
+although I have seen cases where the first time this is done gdb just
+prints the first member but prints the whole structure if you then enter
+CR (carriage return or enter).  This also works:
+
+p *&kgdb_info
+
+Here is a sample:
+(gdb) p kgdb_info
+$4 = {called_from = 0xc010732c, entry_tsc = 32804123790856, errcode = 0,
+  vector = 3, print_debug_info = 0}
+
+"Called_from" is the return address from the current entry into kgdb.
+Sometimes it is useful to know why you are in kgdb, for example, was
+it an NMI or a real breakpoint?  The simple way to interrogate this
+return address is:
+
+l *0xc010732c
+
+which will print the surrounding few lines of source code.
+
+"Entry_tsc" is the CPU TSC on entry to kgdb (useful to compare to the
+kgdb_ts entries).
+
+"errcode" and "vector" are other entry parameters which may be helpful on
+some traps.
+
+"print_debug_info" is the internal debugging kgdb print enable flag.  Yes,
+you can modify it.
+
+In SMP systems kgdb_info also includes the "cpus_waiting" structure and
+"hold_on_step":
+
+(gdb) p kgdb_info
+$7 = {called_from = 0xc0112739, entry_tsc = 1034936624074, errcode = 0,
+  vector = 2, print_debug_info = 0, hold_on_sstep = 1, cpus_waiting = {{
+      task = 0x0, hold = 0, regs = 0x0}, {task = 0xc71b8000, hold = 0,
+      regs = 0xc71b9f70}, {task = 0x0, hold = 0, regs = 0x0}, {task = 0x0,
+      hold = 0, regs = 0x0}, {task = 0x0, hold = 0, regs = 0x0}, {task = 0x0,
+      hold = 0, regs = 0x0}, {task = 0x0, hold = 0, regs = 0x0}, {task = 0x0,
+      hold = 0, regs = 0x0}}}
+
+"Cpus_waiting" has an entry for each CPU other than the current one that
+has been stopped.  Each entry contains the task_struct address for that
+CPU, the address of the regs for that task and a hold flag.  All these
+have the proper typing so that, for example:
+
+p *kgdb_info.cpus_waiting[1].regs
+
+will print the registers for CPU 1.
+
+"Hold_on_sstep" is a new feature with this version and comes up set or
+true.  What this means is that whenever kgdb is asked to single-step all
+other CPUs are held (i.e. not allowed to execute).  The flag applies to
+all but the current CPU and, again, can be changed:
+
+p kgdb_info.hold_on_sstep=0
+
+restores the old behavior of letting all CPUs run during single-stepping.
+
+Likewise, each CPU has a "hold" flag, which if set, locks that CPU out
+of execution.  Note that this has some risk in cases where the CPUs need
+to communicate with each other.  If kgdb finds no CPU available on exit,
+it will push a message thru gdb and stay in kgdb.  Note that it is legal
+to hold the current CPU as long as at least one CPU can execute.
+
+20010621.1117.09
+This version implements an event queue.  Events are signaled by calling
+a function in the kgdb stub and may be examined from gdb.  See EVENTS
+below for details.  This version also tightens up the interrupt and SMP
+handling to not allow interrupts on the way to kgdb from a breakpoint
+trap.  It is fine to allow these interrupts for user code, but not
+system debugging.
+
+Version
+=======
+
+This version of the kgdb package was developed and tested on
+kernel version 2.4.16.  It will not install on any earlier kernels.
+It is possible that it will continue to work on later versions
+of 2.4 and then versions of 2.5 (I hope).
+
+
+Debugging Setup
+===============
+
+Designate one machine as the "development" machine.  This is the
+machine on which you run your compiles and which has your source
+code for the kernel.  Designate a second machine as the "target"
+machine.  This is the machine that will run your experimental
+kernel.
+
+The two machines will be connected together via a serial line out
+one or the other of the COM ports of the PC.  You will need the
+appropriate modem eliminator (null modem) cable(s) for this.
+
+Decide on which tty port you want the machines to communicate, then
+connect them up back-to-back using the null modem cable.  COM1 is
+/dev/ttyS0 and COM2 is /dev/ttyS1. You should test this connection
+with the two machines prior to trying to debug a kernel.  Once you
+have it working, on the TARGET machine, enter:
+
+setserial /dev/ttyS0 (or what ever tty you are using)
+
+and record the port address and the IRQ number.
+
+On the DEVELOPMENT machine you need to apply the patch for the kgdb
+hooks.  You have probably already done that if you are reading this
+file.
+
+On your DEVELOPMENT machine, go to your kernel source directory and do
+"make Xconfig" where X is one of "x", "menu", or "".  If you are
+configuring in the standard serial driver, it must not be a module.
+Either yes or no is ok, but making the serial driver a module means it
+will initialize after kgdb has set up the UART interrupt code and may
+cause a failure of the control-C option discussed below.  The configure
+question for the serial driver is under the "Character devices" heading
+and is:
+
+"Standard/generic (8250/16550 and compatible UARTs) serial support"
+
+Go down to the kernel debugging menu item and open it up.  Enable the
+kernel kgdb stub code by selecting that item.  You can also choose to
+turn on the "-ggdb -O1" compile options.  The -ggdb causes the compiler
+to put more debug info (like local symbols) in the object file.  On the
+i386 -g and -ggdb are the same so this option just reduces to "O1".  The
+-O1 reduces the optimization level.  This may be helpful in some cases,
+be aware, however, that this may also mask the problem you are looking
+for.
+
+The baud rate.  Default is 115200.  What ever you choose be sure that
+the host machine is set to the same speed.  I recommend the default.
+
+The port.  This is the I/O address of the serial UART that you should
+have gotten using setserial as described above.  The standard COM1 port
+(3f8) using IRQ 4 is default.  COM2 is 2f8 which by convention uses IRQ
+3.
+
+The port IRQ (see above).
+
+Stack overflow test.  This option makes a minor change in the trap,
+system call and interrupt code to detect stack overflow and transfer
+control to kgdb if it happens.  (Some platforms have this in the
+baseline code, but the i386 does not.)
+
+You can also configure the system to recognize the boot option
+"console=kgdb" which if given will cause all console output during
+booting to be put thru gdb as well as other consoles.  This option
+requires that gdb and kgdb be connected prior to sending console output
+so, if they are not, a breakpoint is executed to force the connection.
+This will happen before any kernel output (it is going thru gdb, right),
+and will stall the boot until the connection is made.
+
+You can also configure in a patch to SysRq to enable the kGdb SysRq.
+This request generates a breakpoint.  Since the serial port IRQ line is
+set up after any serial drivers, it is possible that this command will
+work when the control-C will not.
+
+Save and exit the Xconfig program.  Then do "make clean" , "make dep"
+and "make bzImage" (or whatever target you want to make).  This gets the
+kernel compiled with the "-g" option set -- necessary for debugging.
+
+You have just built the kernel on your DEVELOPMENT machine that you
+intend to run on your TARGET machine.
+
+To install this new kernel, use the following installation procedure.
+Remember, you are on the DEVELOPMENT machine patching the kernel source
+for the kernel that you intend to run on the TARGET machine.
+
+Copy this kernel to your target machine using your usual procedures.  I
+usually arrange to copy development:
+/usr/src/linux/arch/i386/boot/bzImage to /vmlinuz on the TARGET machine
+via a LAN based NFS access.  That is, I run the cp command on the target
+and copy from the development machine via the LAN.  Run Lilo (see "man
+lilo" for details on how to set this up) on the new kernel on the target
+machine so that it will boot!  Then boot the kernel on the target
+machine.
+
+On the DEVELOPMENT machine, create a file called .gdbinit in the
+directory /usr/src/linux.  An example .gdbinit file looks like this:
+
+shell echo -e "\003" >/dev/ttyS0
+set remotebaud 38400 (or what ever speed you have chosen)
+target remote /dev/ttyS0
+
+
+Change the "echo" and "target" definition so that it specifies the tty
+port that you intend to use.  Change the "remotebaud" definition to
+match the data rate that you are going to use for the com line.
+
+You are now ready to try it out.
+
+Boot your target machine with "kgdb" in the boot command i.e. something
+like:
+
+lilo> test kgdb
+
+or if you also want console output thru gdb:
+
+lilo> test kgdb console=kgdb
+
+You should see the lilo message saying it has loaded the kernel and then
+all output stops.  The kgdb stub is trying to connect with gdb.  Start
+gdb something like this:
+
+
+On your DEVELOPMENT machine, cd /usr/src/linux and enter "gdb vmlinux".
+When gdb gets the symbols loaded it will read your .gdbinit file and, if
+everything is working correctly, you should see gdb print out a few
+lines indicating that a breakpoint has been taken.  It will actually
+show a line of code in the target kernel inside the kgdb activation
+code.
+
+The gdb interaction should look something like this:
+
+    linux-dev:/usr/src/linux# gdb vmlinux
+    GDB is free software and you are welcome to distribute copies of it
+     under certain conditions; type "show copying" to see the conditions.
+    There is absolutely no warranty for GDB; type "show warranty" for details.
+    GDB 4.15.1 (i486-slackware-linux),
+    Copyright 1995 Free Software Foundation, Inc...
+    breakpoint () at i386-stub.c:750
+    750     }
+    (gdb)
+
+You can now use whatever gdb commands you like to set breakpoints.
+Enter "continue" to start your target machine executing again.  At this
+point the target system will run at full speed until it encounters
+your breakpoint or gets a segment violation in the kernel, or whatever.
+
+If you have the kgdb console enabled when you continue, gdb will print
+out all the console messages.
+
+The above example caused a breakpoint relatively early in the boot
+process.  For the i386 kgdb it is possible to code a break instruction
+as the first C-language point in init/main.c, i.e. as the first instruction
+in start_kernel().  This could be done as follows:
+
+#include <asm/kgdb.h>
+	 breakpoint();
+
+This breakpoint() is really a function that sets up the breakpoint and
+single-step hardware trap cells and then executes a breakpoint.  Any
+early hard coded breakpoint will need to use this function.  Once the
+trap cells are set up they need not be set again, but doing it again
+does not hurt anything, so you don't need to be concerned about which
+breakpoint is hit first.  Once the trap cells are set up (and the kernel
+sets them up in due course even if breakpoint() is never called) the
+macro:
+
+BREAKPOINT;
+
+will generate an inline breakpoint.  This may be more useful as it stops
+the processor at the instruction instead of in a function a step removed
+from the location of interest.  In either case <asm/kgdb.h> must be
+included to define both breakpoint() and BREAKPOINT.
+
+Triggering kgdbstub at other times
+==================================
+
+Often you don't need to enter the debugger until much later in the boot
+or even after the machine has been running for some time.  Once the
+kernel is booted and interrupts are on, you can force the system to
+enter the debugger by sending a control-C to the debug port. This is
+what the first line of the recommended .gdbinit file does.  This allows
+you to start gdb any time after the system is up as well as when the
+system is already at a breakpoint.  (In the case where the system is
+already at a breakpoint the control-C is not needed, however, it will
+be ignored by the target so no harm is done.  Also note the the echo
+command assumes that the port speed is already set.  This will be true
+once gdb has connected, but it is best to set the port speed before you
+run gdb.)
+
+Another simple way to do this is to put the following file in you ~/bin
+directory:
+
+#!/bin/bash
+echo  -e "\003"  > /dev/ttyS0
+
+Here, the ttyS0 should be replaced with what ever port you are using.
+The "\003" is control-C.  Once you are connected with gdb, you can enter
+control-C at the command prompt.
+
+An alternative way to get control to the debugger is to enable the kGdb
+SysRq command.  Then you would enter Alt-SysRq-g (all three keys at the
+same time, but push them down in the order given).  To refresh your
+memory of the available SysRq commands try Alt-SysRq-=.  Actually any
+undefined command could replace the "=", but I like to KNOW that what I
+am pushing will never be defined.
+
+Debugging hints
+===============
+
+You can break into the target machine at any time from the development
+machine by typing ^C (see above paragraph).  If the target machine has
+interrupts enabled this will stop it in the kernel and enter the
+debugger.
+
+There is unfortunately no way of breaking into the kernel if it is
+in a loop with interrupts disabled, so if this happens to you then
+you need to place exploratory breakpoints or printk's into the kernel
+to find out where it is looping.  The exploratory breakpoints can be
+entered either thru gdb or hard coded into the source.  This is very
+handy if you do something like:
+
+if (<it hurts>) BREAKPOINT;
+
+
+There is a copy of an e-mail in the Documentation/i386/kgdb/ directory
+(debug-nmi.txt) which describes how to create an NMI on an ISA bus
+machine using a paper clip.  I have a sophisticated version of this made
+by wiring a push button switch into a PC104/ISA bus adapter card.  The
+adapter card nicely furnishes wire wrap pins for all the ISA bus
+signals.
+
+When you are done debugging the kernel on the target machine it is a
+good idea to leave it in a running state.  This makes reboots faster,
+bypassing the fsck.  So do a gdb "continue" as the last gdb command if
+this is possible.  To terminate gdb itself on the development machine
+and leave the target machine running, first clear all breakpoints and
+continue, then type ^Z to suspend gdb and then kill it with "kill %1" or
+something similar.
+
+If gdbstub Does Not Work
+========================
+
+If it doesn't work, you will have to troubleshoot it.  Do the easy
+things first like double checking your cabling and data rates.  You
+might try some non-kernel based programs to see if the back-to-back
+connection works properly.  Just something simple like cat /etc/hosts
+>/dev/ttyS0 on one machine and cat /dev/ttyS0 on the other will tell you
+if you can send data from one machine to the other.  Make sure it works
+in both directions.  There is no point in tearing out your hair in the
+kernel if the line doesn't work.
+
+All of the real action takes place in the file
+/usr/src/linux/arch/i386/kernel/kgdb_stub.c.  That is the code on the target
+machine that interacts with gdb on the development machine.  In gdb you can
+turn on a debug switch with the following command:
+
+	set remotedebug
+
+This will print out the protocol messages that gdb is exchanging with
+the target machine.
+
+Another place to look is /usr/src/arch/i386/lib/kgdb_serial.c. This is
+the code that talks to the serial port on the target side.  There might
+be a problem there.  In particular there is a section of this code that
+tests the UART which will tell you what UART you have if you define
+"PRNT" (just remove "_off" from the #define PRNT_off).  To view this
+report you will need to boot the system without any beakpoints.  This
+allows the kernel to run to the point where it calls kgdb to set up
+interrupts.  At this time kgdb will test the UART and print out the type
+it finds.  (You need to wait so that the printks are actually being
+printed.  Early in the boot they are cached, waiting for the console to
+be enabled.  Also, if kgdb is entered thru a breakpoint it is possible
+to cause a dead lock by calling printk when the console is locked.  The
+stub thus avoids doing printks from breakpoints, especially in the
+serial code.)  At this time, if the UART fails to do the expected thing,
+kgdb will print out (using printk) information on what failed.  (These
+messages will be buried in all the other boot up messages.  Look for
+lines that start with "gdb_hook_interrupt:".  You may want to use dmesg
+once the system is up to view the log.  If this fails or if you still
+don't connect, review your answers for the port address.  Use:
+
+setserial /dev/ttyS0
+
+to get the current port and IRQ information.  This command will also
+tell you what the system found for the UART type. The stub recognizes
+the following UART types:
+
+16450, 16550, and 16550A
+
+If you are really desperate you can use printk debugging in the
+kgdbstub code in the target kernel until you get it working.  In particular,
+there is a global variable in /usr/src/linux/arch/i386/kernel/kgdb_stub.c
+named "remote_debug".  Compile your kernel with this set to 1, rather
+than 0 and the debug stub will print out lots of stuff as it does
+what it does.  Likewise there are debug printks in the kgdb_serial.c
+code that can be turned on with simple changes in the macro defines.
+
+
+Debugging Loadable Modules
+==========================
+
+This technique comes courtesy of Edouard Parmelan
+<Edouard.Parmelan@quadratec.fr>
+
+When you run gdb, enter the command
+
+source gdbinit-modules
+
+This will read in a file of gdb macros that was installed in your
+kernel source directory when kgdb was installed.  This file implements
+the following commands:
+
+mod-list
+    Lists the loaded modules in the form <module-address> <module-name>
+
+mod-print-symbols <module-address>
+    Prints all the symbols in the indicated module.
+
+mod-add-symbols <module-address> <object-file-path-name>
+    Loads the symbols from the object file and associates them
+    with the indicated module.
+
+After you have loaded the module that you want to debug, use the command
+mod-list to find the <module-address> of your module.  Then use that
+address in the mod-add-symbols command to load your module's symbols.
+From that point onward you can debug your module as if it were a part
+of the kernel.
+
+The file gdbinit-modules also contains a command named mod-add-lis as
+an example of how to construct a command of your own to load your
+favorite module.  The idea is to "can" the pathname of the module
+in the command so you don't have to type so much.
+
+Threads
+=======
+
+Each process in a target machine is seen as a gdb thread. gdb thread
+related commands (info threads, thread n) can be used.
+
+ia-32 hardware breakpoints
+==========================
+
+kgdb stub contains support for hardware breakpoints using debugging features
+of ia-32(x86) processors. These breakpoints do not need code modification.
+They use debugging registers. 4 hardware breakpoints are available in ia-32
+processors.
+
+Each hardware breakpoint can be of one of the following three types.
+
+1. Execution breakpoint - An Execution breakpoint is triggered when code
+	at the breakpoint address is executed.
+
+	As limited number of hardware breakpoints are available, it is
+	advisable to use software breakpoints ( break command ) instead
+	of execution hardware breakpoints, unless modification of code
+	is to be avoided.
+
+2. Write breakpoint - A write breakpoint is triggered when memory
+	location at the breakpoint address is written.
+
+	A write or can be placed for data of variable length. Length of
+	a write breakpoint indicates length of the datatype to be
+	watched. Length is 1 for 1 byte data , 2 for 2 byte data, 3 for
+	4 byte data.
+
+3. Access breakpoint - An access breakpoint is triggered when memory
+	location at the breakpoint address is either read or written.
+
+	Access breakpoints also have lengths similar to write breakpoints.
+
+IO breakpoints in ia-32 are not supported.
+
+Since gdb stub at present does not use the protocol used by gdb for hardware
+breakpoints, hardware breakpoints are accessed through gdb macros. gdb macros
+for hardware breakpoints are described below.
+
+hwebrk	- Places an execution breakpoint
+	hwebrk breakpointno address
+hwwbrk	- Places a write breakpoint
+	hwwbrk breakpointno length address
+hwabrk	- Places an access breakpoint
+	hwabrk breakpointno length address
+hwrmbrk	- Removes a breakpoint
+	hwrmbrk breakpointno
+exinfo	- Tells whether a software or hardware breakpoint has occurred.
+	Prints number of the hardware breakpoint if a hardware breakpoint has
+	occurred.
+
+Arguments required by these commands are as follows
+breakpointno	- 0 to 3
+length		- 1 to 3
+address		- Memory location in hex digits ( without 0x ) e.g c015e9bc
+
+SMP support
+==========
+
+When a breakpoint occurs or user issues a break ( Ctrl + C ) to gdb
+client, all the processors are forced to enter the debugger. Current
+thread corresponds to the thread running on the processor where
+breakpoint occurred.  Threads running on other processor(s) appear
+similar to other non-running threads in the 'info threads' output.
+Within the kgdb stub there is a structure "waiting_cpus" in which kgdb
+records the values of "current" and "regs" for each CPU other than the
+one that hit the breakpoint.  "current" is a pointer to the task
+structure for the task that CPU is running, while "regs" points to the
+saved registers for the task.  This structure can be examined with the
+gdb "p" command.
+
+ia-32 hardware debugging registers on all processors are set to same
+values.  Hence any hardware breakpoints may occur on any processor.
+
+gdb troubleshooting
+===================
+
+1. gdb hangs
+Kill it. restart gdb. Connect to target machine.
+
+2. gdb cannot connect to target machine (after killing a gdb and
+restarting another) If the target machine was not inside debugger when
+you killed gdb, gdb cannot connect because the target machine won't
+respond.  In this case echo "Ctrl+C"(ASCII 3) to the serial line.
+e.g. echo -e "\003" > /dev/ttyS1
+This forces that target machine into the debugger, after which you
+can connect.
+
+3. gdb cannot connect even after echoing Ctrl+C into serial line
+Try changing serial line settings min to 1 and time to 0
+e.g. stty min 1 time 0 < /dev/ttyS1
+Try echoing again
+
+Check serial line speed and set it to correct value if required
+e.g. stty ispeed 115200 ospeed 115200 < /dev/ttyS1
+
+EVENTS
+======
+
+Ever want to know the order of things happening?  Which CPU did what and
+when?  How did the spinlock get the way it is?  Then events are for
+you.  Events are defined by calls to an event collection interface and
+saved for later examination.  In this case, kgdb events are saved by a
+very fast bit of code in kgdb which is fully SMP and interrupt protected
+and they are examined by using gdb to display them.  Kgdb keeps only
+the last N events, where N must be a power of two and is defined at
+configure time.
+
+
+Events are signaled to kgdb by calling:
+
+kgdb_ts(data0,data1)
+
+For each call kgdb records each call in an array along with other info.
+Here is the array definition:
+
+struct kgdb_and_then_struct {
+#ifdef CONFIG_SMP
+	int	on_cpu;
+#endif
+	long long at_time;
+	int  	from_ln;
+	char	* in_src;
+	void	*from;
+        int     with_if;
+	int	data0;
+	int	data1;
+};
+
+For SMP machines the CPU is recorded, for all machines the TSC is
+recorded (gets a time stamp) as well as the line number and source file
+the call was made from.  The address of the (from), the "if" (interrupt
+flag) and the two data items are also recorded.  The macro kgdb_ts casts
+the types to int, so you can put any 32-bit values here.  There is a
+configure option to select the number of events you want to keep.  A
+nice number might be 128, but you can keep up to 1024 if you want.  The
+number must be a power of two.  An "andthen" macro library is provided
+for gdb to help you look at these events.  It is also possible to define
+a different structure for the event storage and cast the data to this
+structure.  For example the following structure is defined in kgdb:
+
+struct kgdb_and_then_struct2 {
+#ifdef CONFIG_SMP
+	int	on_cpu;
+#endif
+	long long at_time;
+	int  	from_ln;
+	char	* in_src;
+	void	*from;
+        int     with_if;
+	struct task_struct *t1;
+	struct task_struct *t2;
+};
+
+If you use this for display, the data elements will be displayed as
+pointers to task_struct entries.  You may want to define your own
+structure to use in casting.  You should only change the last two items
+and you must keep the structure size the same.  Kgdb will handle these
+as 32-bit ints, but within that constraint you can define a structure to
+cast to any 32-bit quantity.  This need only be available to gdb and is
+only used for casting in the display code.
+
+Final Items
+===========
+
+I picked up this code from Amit S. Kale and enhanced it.
+
+If you make some really cool modification to this stuff, or if you
+fix a bug, please let me know.
+
+George Anzinger
+<george@mvista.com>
+
+Amit S. Kale
+<akale@veritas.com>
+
+(First kgdb by David Grothe <dave@gcom.com>)
+
+(modified by Tigran Aivazian <tigran@sco.com>)
+    Putting gdbstub into the kernel config menu.
+
+(modified by Scott Foehner <sfoehner@engr.sgi.com>)
+    Hooks for entering gdbstub at boot time.
+
+(modified by Amit S. Kale <akale@veritas.com>)
+    Threads, ia-32 hw debugging, mp support, console support,
+    nmi watchdog handling.
+
+(modified by George Anzinger <george@mvista.com>)
+    Extended threads to include the idle threads.
+    Enhancements to allow breakpoint() at first C code.
+    Use of module_init() and __setup() to automate the configure.
+    Enhanced the cpu "collection" code to work in early bring-up.
+    Added ability to call functions from gdb
+    Print info thread stuff without going back to schedule()
+    Now collect the "other" cpus with an IPI/ NMI.
--- diff/Documentation/i386/kgdb/kgdbeth.txt	1970-01-01 01:00:00.000000000 +0100
+++ source/Documentation/i386/kgdb/kgdbeth.txt	2004-02-23 13:56:39.000000000 +0000
@@ -0,0 +1,92 @@
+KGDB over ethernet
+==================
+
+Authors
+-------
+
+Robert Walsh <rjwalsh@durables.org>  (2.6 port)
+wangdi <wangdi@clusterfs.com>        (2.6 port)
+Matt Mackall <mpm@selenic.com>       (netpoll api)
+San Mehat                            (original 2.4 code)
+
+
+Introduction
+------------
+
+KGDB supports debugging over ethernet (kgdboe) via polling of a given
+network interface. Most cards should be supported automatically.
+Debugging facilities are available as soon as the network driver and
+kgdboe have initialized. Unfortunately, this is too late in the boot
+process for debugging some issues, but works quite well for many
+others. This should not interfere with normal network usage and
+doesn't require a dedicated NIC.
+
+Terminology
+-----------
+
+This document uses the following terms:
+
+  TARGET: the machine being debugged.
+  HOST:   the machine running gdb.
+
+
+Usage
+-----
+
+You need to use the following command-line option on the TARGET kernel:
+
+  kgdboe=[tgt-port]@<tgt-ip>/[dev],[host-port]@<host-ip>/[host-macaddr]
+
+    where
+        tgt-port      source for UDP packets (defaults to 6443)
+        tgt-ip        source IP to use (interface address)
+        dev           network interface (eth0)
+        host-port     HOST UDP port (6442) (not really used)
+        host-ip       IP address for HOST machine
+        host-macaddr  ethernet MAC address for HOST (ff:ff:ff:ff:ff:ff)
+
+  examples:
+
+    kgdboe=7000@192.168.0.1/eth1,7001@192.168.0.2/00:05:3C:04:47:5D
+        this machine is 192.168.0.1 on eth1
+        remote machine is 192.168.0.2 with MAC address 00:05:3C:04:47:5D
+        listen for gdb packets on port 7000
+        send unsolicited gdb packets to port 7001
+
+    kgdboe=@192.168.0.1/,@192.168.0.2/
+        this machine is 192.168.0.1 on default interface eth0
+        remote machine is 192.168.0.2, use default broadcast MAC address
+        listen for gdb packets on default port 6443
+        send unsolicited gdb packets to port 6442
+
+Only packets originating from the configured HOST IP address will be
+accepted by the debugger.
+
+On the HOST side, run gdb as normal and use a remote UDP host as the
+target:
+
+   % gdb ./vmlinux
+   GNU gdb Red Hat Linux (5.3post-0.20021129.18rh)
+   Copyright 2003 Free Software Foundation, Inc.
+   GDB is free software, covered by the GNU General Public License, and you are
+   welcome to change it and/or distribute copies of it under certain conditions.
+   Type "show copying" to see the conditions.
+   There is absolutely no warranty for GDB.  Type "show warranty" for details.
+   This GDB was configured as "i386-redhat-linux-gnu"...
+   (gdb) target remote udp:HOSTNAME:6443
+
+You can now continue as if you were debugging over a serial line.
+
+Limitations
+-----------
+
+The current release of this code is exclusive of using kgdb on a
+serial interface, so you must boot without the kgdboe option to use
+serial debugging. Trying to debug the network driver while using it
+will prove interesting.
+
+Bug reports
+-----------
+
+Send bug reports to Robert Walsh <rjwalsh@durables.org> and Matt
+Mackall <mpm@selenic.com>.
--- diff/Documentation/i386/kgdb/loadmodule.sh	1970-01-01 01:00:00.000000000 +0100
+++ source/Documentation/i386/kgdb/loadmodule.sh	2004-02-23 13:56:39.000000000 +0000
@@ -0,0 +1,78 @@
+#/bin/sh
+# This script loads a module on a target machine and generates a gdb script.
+# source generated gdb script to load the module file at appropriate addresses
+# in gdb.
+#
+# Usage:
+# Loading the module on target machine and generating gdb script)
+#	[foo]$ loadmodule.sh <modulename>
+#
+# Loading the module file into gdb
+#	(gdb) source <gdbscriptpath>
+#
+# Modify following variables according to your setup.
+#	TESTMACHINE - Name of the target machine
+#	GDBSCRIPTS - The directory where a gdb script will be generated
+#
+# Author: Amit S. Kale (akale@veritas.com).
+#
+# If you run into problems, please check files pointed to by following
+# variables.
+#	ERRFILE - /tmp/<modulename>.errs contains stderr output of insmod
+#	MAPFILE - /tmp/<modulename>.map contains stdout output of insmod
+#	GDBSCRIPT - $GDBSCRIPTS/load<modulename> gdb script.
+
+TESTMACHINE=foo
+GDBSCRIPTS=/home/bar
+
+if [ $# -lt 1 ] ; then {
+	echo Usage: $0 modulefile
+	exit
+} ; fi
+
+MODULEFILE=$1
+MODULEFILEBASENAME=`basename $1`
+
+if [ $MODULEFILE = $MODULEFILEBASENAME ] ; then {
+	MODULEFILE=`pwd`/$MODULEFILE
+} fi
+
+ERRFILE=/tmp/$MODULEFILEBASENAME.errs
+MAPFILE=/tmp/$MODULEFILEBASENAME.map
+GDBSCRIPT=$GDBSCRIPTS/load$MODULEFILEBASENAME
+
+function findaddr() {
+	local ADDR=0x$(echo "$SEGMENTS" | \
+		grep "$1" | sed 's/^[^ ]*[ ]*[^ ]*[ ]*//' | \
+		sed 's/[ ]*[^ ]*$//')
+	echo $ADDR
+}
+
+function checkerrs() {
+	if [ "`cat $ERRFILE`" != "" ] ; then {
+		cat $ERRFILE
+		exit
+	} fi
+}
+
+#load the module
+echo Copying $MODULEFILE to $TESTMACHINE
+rcp $MODULEFILE root@${TESTMACHINE}:
+
+echo Loading module $MODULEFILE
+rsh -l root $TESTMACHINE  /sbin/insmod -m ./`basename $MODULEFILE` \
+	> $MAPFILE 2> $ERRFILE
+checkerrs
+
+SEGMENTS=`head -n 11 $MAPFILE | tail -n 10`
+TEXTADDR=$(findaddr "\\.text[^.]")
+LOADSTRING="add-symbol-file $MODULEFILE $TEXTADDR"
+SEGADDRS=`echo "$SEGMENTS" | awk '//{
+	if ($1 != ".text" && $1 != ".this" &&
+	    $1 != ".kstrtab" && $1 != ".kmodtab") {
+		print " -s " $1 " 0x" $3 " "
+	}
+}'`
+LOADSTRING="$LOADSTRING $SEGADDRS"
+echo Generating script $GDBSCRIPT
+echo $LOADSTRING > $GDBSCRIPT
--- diff/Documentation/laptop-mode.txt	1970-01-01 01:00:00.000000000 +0100
+++ source/Documentation/laptop-mode.txt	2004-02-23 13:56:39.000000000 +0000
@@ -0,0 +1,480 @@
+How to conserve battery power using laptop-mode
+-----------------------------------------------
+
+Document Author: Bart Samwel (bart@samwel.tk)
+Date created: January 2, 2004
+
+Introduction
+------------
+
+Laptopmode is used to minimize the time that the hard disk needs to be spun up,
+to conserve battery power on laptops. It has been reported to cause significant
+power savings.
+
+Contents
+--------
+
+* Introduction
+* The short story
+* Caveats
+* The details
+* Tips & Tricks
+* Control script
+* ACPI integration
+* Monitoring tool
+
+
+The short story
+---------------
+
+If you just want to use it, run the laptop_mode control script (which is included
+at the end of this document) as follows:
+
+# laptop_mode start
+
+Then set your harddisk spindown time to a relatively low value with hdparm:
+
+hdparm -S 4 /dev/hda
+
+The value -S 4 means 20 seconds idle time before spindown. Your harddisk will
+now only spin up when a disk cache miss occurs, or at least once every 10
+minutes to write back any pending changes.
+
+To stop laptop_mode, remount your filesystems with regular commit intervals
+(e.g., 5 seconds), and run "laptop_mode stop".
+
+
+Caveats
+-------
+
+* The downside of laptop mode is that you have a chance of losing up
+  to 10 minutes of work. If you cannot afford this, don't use it!
+
+* Most desktop hard drives have a very limited lifetime measured in spindown
+  cycles, typically about 50.000 times (it's usually listed on the spec sheet).
+  Check your drive's rating, and don't wear down your drive's lifetime if you
+  don't need to.
+
+* If you mount some of your ext3/reiserfs filesystems with the -n option, then
+  the control script will not be able to remount them correctly. You must set
+  DO_REMOUNTS=0 in the control script, otherwise it will remount them with the
+  wrong options -- or it will fail because it cannot write to /etc/mtab.
+
+* If you have your filesystems listed as type "auto" in fstab, like I did, then
+  the control script will not recognize them as filesystems that need remounting.
+
+The details
+-----------
+
+Laptop-mode is controlled by the flag /proc/sys/vm/laptop_mode. When this
+flag is set, any physical disk read operation (that might have caused the
+hard disk to spin up) causes Linux to flush all dirty blocks. The result
+of this is that after a disk has spun down, it will not be spun up anymore
+to write dirty blocks, because those blocks had already been written
+immediately after the most recent read operation
+
+To increase the effectiveness of the laptop_mode strategy, the laptop_mode
+control script increases dirty_expire_centisecs and dirty_writeback_centisecs in
+/proc/sys/vm to about 10 minutes (by default), which means that pages that are
+dirtied are not forced to be written to disk as often. The control script also
+changes the dirty background ratio, so that background writeback of dirty pages
+is not done anymore. Combined with a higher commit value (also 10 minutes) for
+ext3 or ReiserFS filesystems (also done automatically by the control script),
+this results in concentration of disk activity in a small time interval which
+occurs only once every 10 minutes, or whenever the disk is forced to spin up by
+a cache miss. The disk can then be spun down in the periods of inactivity.
+
+If you want to find out which process caused the disk to spin up, you can
+gather information by setting the flag /proc/sys/vm/block_dump. When this flag
+is set, Linux reports all disk read and write operations that take place, and
+all block dirtyings done to files. This makes it possible to debug why a disk
+needs to spin up, and to increase battery life even more.
+
+If 10 minutes is too much or too little downtime for you, you can configure
+this downtime as follows. In the control script, set the MAX_AGE value to the
+maximum number of seconds of disk downtime that you would like. You should
+then set your filesystem's commit interval to the same value. The dirty ratio
+is also configurable from the control script.
+
+If you don't like the idea of the control script remounting your filesystems
+for you, you can change DO_REMOUNTS to 0 in the script.
+
+Thanks to Kiko Piris, the control script can be used to enable laptop mode on
+both the Linux 2.4 and 2.6 series.
+
+
+Tips & Tricks
+-------------
+
+* Bartek Kania reports getting up to 50 minutes of extra battery life (on top
+  of his regular 3 to 3.5 hours) using very aggressive power management (hdparm
+  -B1) and a spindown time of 5 seconds (hdparm -S1).
+
+* You can spin down the disk while playing MP3, by setting the disk readahead
+  to 8MB (hdparm -a 16384). Effectively, the disk will read a complete MP3 at
+  once, and will then spin down while the MP3 is playing. (Thanks to Bartek
+  Kania.)
+
+* Drew Scott Daniels observed: "I don't know why, but when I decrease the number
+  of colours that my display uses it consumes less battery power. I've seen
+  this on powerbooks too. I hope that this is a piece of information that
+  might be useful to the Laptop Mode patch or it's users."
+
+
+Control script
+--------------
+
+Please note that this control script works for the Linux 2.4 and 2.6 series.
+
+--------------------CONTROL SCRIPT BEGIN------------------------------------------
+#!/bin/sh
+
+# start or stop laptop_mode, best run by a power management daemon when
+# ac gets connected/disconnected from a laptop
+#
+# install as /sbin/laptop_mode
+#
+# Contributors to this script:   Kiko Piris
+#				 Bart Samwel
+#				 Dax Kelson
+# Original Linux 2.4 version by: Jens Axboe
+
+parse_mount_opts () {
+	echo "$*"			| \
+	sed 's/commit=[0-9]*//g'	| \
+	sed 's/,,*/,/g'			| \
+	sed 's/^,//'			| \
+	sed 's/,$//'			| \
+	cat -
+}
+
+KLEVEL="$(uname -r | cut -c1-3)"
+case "$KLEVEL" in
+	"2.4")
+		true
+		;;
+	"2.6")
+		true
+		;;
+	*)
+		echo "Unhandled kernel level: $KLEVEL ('uname -r' = '$(uname -r)')"
+		exit 1
+		;;
+esac
+
+# Shall we remount journaled fs. with appropiate commit interval? (1=yes)
+DO_REMOUNTS=1
+
+# age time, in seconds. should be put into a sysconfig file
+MAX_AGE=600
+
+# Allowed dirty ratio, in pct. should be put into a sysconfig file as well.
+DIRTY_RATIO=40
+
+# kernel default dirty buffer age
+DEF_AGE=30
+DEF_UPDATE=5
+DEF_DIRTY_BACKGROUND_RATIO=10
+DEF_DIRTY_RATIO=40
+
+
+if [ ! -e /proc/sys/vm/laptop_mode ]; then
+	echo "Kernel is not patched with laptop_mode patch."
+	exit 1
+fi
+
+if [ ! -w /proc/sys/vm/laptop_mode ]; then
+	echo "You do not have enough privileges to enable laptop_mode."
+	exit 1
+fi
+
+case "$1" in
+	start)
+		AGE=$((100*$MAX_AGE))
+		echo -n "Starting laptop_mode"
+		case "$KLEVEL" in
+			"2.4")
+				echo "1"				> /proc/sys/vm/laptop_mode
+				echo "30 500 0 0 $AGE $AGE 60 20 0"	> /proc/sys/vm/bdflush
+				;;
+			"2.6")
+				echo "1"				> /proc/sys/vm/laptop_mode
+				echo "$AGE"				> /proc/sys/vm/dirty_writeback_centisecs
+				echo "$AGE"				> /proc/sys/vm/dirty_expire_centisecs
+				echo "$DIRTY_RATIO"			> /proc/sys/vm/dirty_ratio
+				echo "$DIRTY_RATIO"			> /proc/sys/vm/dirty_background_ratio
+				;;
+		esac
+		if [ $DO_REMOUNTS -eq 1 ]; then
+			cat /etc/mtab | while read DEV MP FST OPTS DUMP PASS ; do
+				PARSEDOPTS="$(parse_mount_opts "$OPTS")"
+				case "$FST" in
+					"ext3")		mount $DEV -t $FST $MP -o remount,$PARSEDOPTS,commit=$MAX_AGE ;;
+					"reiserfs")	mount $DEV -t $FST $MP -o remount,$PARSEDOPTS,commit=$MAX_AGE ;;
+					"xfs")		mount $DEV -t $FST $MP -o remount,$PARSEDOPTS,commit=$MAX_AGE ;;
+				esac
+			done
+		fi
+		echo "."
+		;;
+	stop)
+		U_AGE=$((100*$DEF_UPDATE))
+		B_AGE=$((100*$DEF_AGE))
+		echo -n "Stopping laptop_mode"
+		case "$KLEVEL" in
+			"2.4")
+				echo "0"				> /proc/sys/vm/laptop_mode
+				echo "30 500 0 0 $U_AGE $B_AGE 60 20 0"	> /proc/sys/vm/bdflush
+				;;
+			"2.6")
+				echo "0"				> /proc/sys/vm/laptop_mode
+				echo "$U_AGE"				> /proc/sys/vm/dirty_writeback_centisecs
+				echo "$B_AGE"				> /proc/sys/vm/dirty_expire_centisecs
+				echo "$DEF_DIRTY_RATIO"			> /proc/sys/vm/dirty_ratio
+				echo "$DEF_DIRTY_BACKGROUND_RATIO"	> /proc/sys/vm/dirty_background_ratio
+				;;
+		esac
+		if [ $DO_REMOUNTS -eq 1 ]; then
+			cat /etc/mtab | while read DEV MP FST OPTS DUMP PASS ; do
+				PARSEDOPTS="$(parse_mount_opts "$OPTS")"
+				case "$FST" in
+					"ext3")		mount $DEV -t $FST $MP -o remount,$PARSEDOPTS ;;
+					"reiserfs")	mount $DEV -t $FST $MP -o remount,$PARSEDOPTS ;;
+					"xfs")		mount $DEV -t $FST $MP -o remount,$PARSEDOPTS ;;
+				esac
+			done
+		fi
+		echo "."
+		;;
+	*)
+		echo "$0 {start|stop}"
+		;;
+
+esac
+
+exit 0
+
+--------------------CONTROL SCRIPT END--------------------------------------------
+
+
+ACPI integration
+----------------
+
+Dax Kelson submitted this so that the ACPI acpid daemon will
+kick off the laptop_mode script and run hdparm.
+
+---------------------------/etc/acpi/events/ac_adapter BEGIN-------------------------------------------
+event=ac_adapter
+action=/etc/acpi/actions/battery.sh
+---------------------------/etc/acpi/events/ac_adapter END-------------------------------------------
+
+---------------------------/etc/acpi/actions/battery.sh BEGIN-------------------------------------------
+#!/bin/sh
+
+# cpu throttling
+# cat /proc/acpi/processor/CPU0/throttling for more info
+ACAD_THR=0
+BATT_THR=2
+
+# spindown time for HD (man hdparm for valid values)
+# I prefer 2 hours for acad and 20 seconds for batt
+ACAD_HD=244
+BATT_HD=4
+
+# ac/battery event handler
+
+status=`awk '/^state: / { print $2 }' /proc/acpi/ac_adapter/AC/state`
+
+case $status in
+        "on-line")
+                echo "Setting HD spindown to 2 hours"
+                /sbin/laptop-mode stop
+                /sbin/hdparm -S $ACAD_HD /dev/hda > /dev/null 2>&1
+                /sbin/hdparm -B 255 /dev/hda > /dev/null 2>&1
+                #echo -n $ACAD_CPU:$ACAD_THR > /proc/acpi/processor/CPU0/limit
+                exit 0
+        ;;
+        "off-line")
+                echo "Setting HD spindown to 20 seconds"
+                /sbin/laptop-mode start
+                /sbin/hdparm -S $BATT_HD /dev/hda > /dev/null 2>&1
+                /sbin/hdparm -B 1 /dev/hda > /dev/null 2>&1
+                #echo -n $BATT_CPU:$BATT_THR > /proc/acpi/processor/CPU0/limit
+                exit 0
+        ;;
+esac
+---------------------------/etc/acpi/actions/battery.sh END-------------------------------------------
+
+Monitoring tool
+---------------
+
+Bartek Kania submitted this, it can be used to measure how much time your disk
+spends spun up/down.
+
+---------------------------dslm.c BEGIN-------------------------------------------
+/*
+ * Simple Disk SLeep Monitor
+ *  by Bartek Kania
+ * Licenced under the GPL
+ */
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <time.h>
+#include <string.h>
+#include <signal.h>
+#include <sys/ioctl.h>
+#include <linux/hdreg.h>
+
+#ifdef DEBUG
+#define D(x) x
+#else
+#define D(x)
+#endif
+
+int endit = 0;
+
+/* Check if the disk is in powersave-mode
+ * Most of the code is stolen from hdparm.
+ * 1 = active, 0 = standby/sleep, -1 = unknown */
+int check_powermode(int fd)
+{
+    unsigned char args[4] = {WIN_CHECKPOWERMODE1,0,0,0};
+    int state;
+
+    if (ioctl(fd, HDIO_DRIVE_CMD, &args)
+	&& (args[0] = WIN_CHECKPOWERMODE2) /* try again with 0x98 */
+	&& ioctl(fd, HDIO_DRIVE_CMD, &args)) {
+	if (errno != EIO || args[0] != 0 || args[1] != 0) {
+	    state = -1; /* "unknown"; */
+	} else
+	    state = 0; /* "sleeping"; */
+    } else {
+	state = (args[2] == 255) ? 1 : 0;
+    }
+    D(printf(" drive state is:  %s\n", state));
+
+    return state;
+}
+
+char *state_name(int i)
+{
+    if (i == -1) return "unknown";
+    if (i == 0) return "sleeping";
+    if (i == 1) return "active";
+
+    return "internal error";
+}
+
+char *myctime(time_t time)
+{
+    char *ts = ctime(&time);
+    ts[strlen(ts) - 1] = 0;
+
+    return ts;
+}
+
+void measure(int fd)
+{
+    time_t start_time;
+    int last_state;
+    time_t last_time;
+    int curr_state;
+    time_t curr_time = 0;
+    time_t time_diff;
+    time_t active_time = 0;
+    time_t sleep_time = 0;
+    time_t unknown_time = 0;
+    time_t total_time = 0;
+    int changes = 0;
+    float tmp;
+
+    printf("Starting measurements\n");
+
+    last_state = check_powermode(fd);
+    start_time = last_time = time(0);
+    printf("  System is in state %s\n\n", state_name(last_state));
+
+    while(!endit) {
+	sleep(1);
+	curr_state = check_powermode(fd);
+
+	if (curr_state != last_state || endit) {
+	    changes++;
+	    curr_time = time(0);
+	    time_diff = curr_time - last_time;
+
+	    if (last_state == 1) active_time += time_diff;
+	    else if (last_state == 0) sleep_time += time_diff;
+	    else unknown_time += time_diff;
+
+	    last_state = curr_state;
+	    last_time = curr_time;
+
+	    printf("%s: State-change to %s\n", myctime(curr_time),
+		   state_name(curr_state));
+	}
+    }
+    changes--; /* Compensate for SIGINT */
+
+    total_time = time(0) - start_time;
+    printf("\nTotal running time:  %lus\n", curr_time - start_time);
+    printf(" State changed %d times\n", changes);
+
+    tmp = (float)sleep_time / (float)total_time * 100;
+    printf(" Time in sleep state:   %lus (%.2f%%)\n", sleep_time, tmp);
+    tmp = (float)active_time / (float)total_time * 100;
+    printf(" Time in active state:  %lus (%.2f%%)\n", active_time, tmp);
+    tmp = (float)unknown_time / (float)total_time * 100;
+    printf(" Time in unknown state: %lus (%.2f%%)\n", unknown_time, tmp);
+}
+
+void ender(int s)
+{
+    endit = 1;
+}
+
+void usage()
+{
+    puts("usage: dslm [-w <time>] <disk>");
+    exit(0);
+}
+
+int main(int ac, char **av)
+{
+    int fd;
+    char *disk = 0;
+    int settle_time = 60;
+
+    /* Parse the simple command-line */
+    if (ac == 2)
+	disk = av[1];
+    else if (ac == 4) {
+	settle_time = atoi(av[2]);
+	disk = av[3];
+    } else
+	usage();
+
+    if (!(fd = open(disk, O_RDONLY|O_NONBLOCK))) {
+	printf("Can't open %s, because: %s\n", disk, strerror(errno));
+	exit(-1);
+    }
+
+    if (settle_time) {
+	printf("Waiting %d seconds for the system to settle down to "
+	       "'normal'\n", settle_time);
+	sleep(settle_time);
+    } else
+	puts("Not waiting for system to settle down");
+
+    signal(SIGINT, ender);
+
+    measure(fd);
+
+    close(fd);
+
+    return 0;
+}
+---------------------------dslm.c END---------------------------------------------
--- diff/Documentation/must-fix.txt	1970-01-01 01:00:00.000000000 +0100
+++ source/Documentation/must-fix.txt	2004-02-23 13:56:39.000000000 +0000
@@ -0,0 +1,288 @@
+
+Must-fix bugs
+=============
+
+drivers/char/
+~~~~~~~~~~~~~
+
+o TTY locking is broken.
+
+  o see FIXME in do_tty_hangup().  This causes ppp BUGs in local_bh_enable()
+
+  o Other problems: aviro, dipankar, Alan have details.
+
+  o somebody will have to document the tty driver and ldisc API
+
+drivers/tty
+~~~~~~~~~~~
+
+o viro: tty_driver refcounting, tty/misc/upper levels of sound still not
+  completely fixed.
+
+drivers/block/
+~~~~~~~~~~~~~~
+
+o loop.c: Concurrent write access on block devices might cause a deadlock
+  of the complete system. See:
+  http://marc.theaimsgroup.com/?l=linux-kernel&m=106275365925769&w==
+  http://bugzilla.kernel.org/show_bug.cgi?id=1198
+  Thread of possible fix:
+  http://www.kerneli.org/pipermail/cryptoapi-devel/2003-October/000676.html
+
+  (Fruhwirth Clemens)
+
+o ideraid hasn't been ported to 2.5 at all yet.
+
+  We need to understand whether the proposed BIO split code will suffice
+  for this.
+
+drivers/input/
+~~~~~~~~~~~~~~
+
+o rmk: unconverted keyboard/mouse drivers (there's a deadline of 2.6.0
+  currently on these remaining in my/Linus' tree.)
+
+o viro: large absence of locking.
+
+o viro: parport is nearly as bad as that and there the code is more hairy.
+  IMO parport is more of "figure out what API changes are needed for its
+  users, get them done ASAP, then fix generic layer at leisure"
+
+o (Albert Cahalan) Lots of people (check Google) get this message from the
+  kernel:
+
+  psmouse.c: Lost synchronization, throwing 2 bytes away.
+
+  (the number of bytes will be 1, 2, or 3)
+
+  At work, I get it when there is heavy NFS traffic.  The mouse goes crazy,
+  jumping around and doing random cut-and-paste all over everything.  This
+  is with a decently fast and modern PC.
+
+o There seem to be too many reports of keyboards and mice failing or acting
+  strangely.
+
+
+drivers/misc/
+~~~~~~~~~~~~~
+
+o rmk: UCB1[23]00 drivers, currently sitting in drivers/misc in the ARM
+  tree.  (touchscreen, audio, gpio, type device.)
+
+  These need to be moved out of drivers/misc/ and into real places
+
+o viro: actually, misc.c has a good chance to die.  With cdev-cidr that's
+  trivial.
+
+drivers/net/
+~~~~~~~~~~~~
+
+drivers/net/irda/
+~~~~~~~~~~~~~~~~~
+
+  (Jean Tourrilhes)
+
+o irport need to be converted to sir-kthread
+
+o dongle drivers need to be converted to sir-dev (in progress)
+
+o new drivers (irtty-sir/smsc-ircc2/donauboe) need more testing (in progress)
+
+
+drivers/pci/
+~~~~~~~~~~~~
+
+o alan: Some cardbus crashes the system
+
+  (bugzilla, please?)
+
+drivers/pcmcia/
+~~~~~~~~~~~~~~~
+
+o alan: This is a locking disaster.
+
+  (rmk, brodo: in progress)
+
+drivers/pld/
+~~~~~~~~~~~~
+
+o rmk: EPXA (ARM platform) PLD hotswap drivers (drivers/pld)
+
+  (rmk: will work out what to do here.  maybe drivers/arm/)
+
+drivers/video/
+~~~~~~~~~~~~~~
+
+o Lots of drivers don't compile, others do but don't work.
+
+drivers/scsi/
+~~~~~~~~~~~~~
+
+o Convert am53c974, dpt_i2o, initio and pci2220i to DMA-mapping
+
+o Make inia100, cpqfc, pci2000 and dc390t compile
+
+o Convert
+
+   wd33c99 based: a2091 a3000 gpv11 mvme174 sgiwd93
+
+   53c7xx based: amiga7xxx bvme6000 mvme16x initio am53c974 pci2000
+   pci2220i dc390t
+
+  To new error handling
+
+  It also might be possible to shift the 53c7xx based drivers over to
+  53c700 which does the new EH stuff, but I don't have the hardware to check
+  such a shift.
+
+  For the non-compiling stuff, I've probably missed a few that just aren't
+  compilable on my platforms, so any updates would be welcome.  Also, are
+  some of our non-compiling or unconverted drivers obsolete?
+
+fs/
+~~~
+
+o AIO/direct-IO writes can race with truncate and wreck filesystems.
+  (Badari has a patch)
+
+o viro: fs/char_dev.c needs removal of aeb stuff and merge of cdev-cidr.
+  In progress.
+
+o forward-port sct's O_DIRECT fixes (Badari has a patch)
+
+o viro: there is some generic stuff for namei/namespace/super, but that's a
+  slow-merge and can go in 2.6 just fine
+
+o trond: NFS has a mmap-versus-truncate problem (fixed? needs testing)
+
+o trond: NFSv4 client, bugs in lockd, RPSEC_GSS for NFSv[23], some atomic open
+  bits. more info: http://www.fys.uio.no/~trondmy/src/Linux-2.6.x/2.6.0-test11/
+
+kernel/sched.c
+~~~~~~~~~~~~~~
+
+o Starvation, general interactivity need close monitoring.
+
+o SMT aware scheduler (Ingo, Rusty, Nick have implementations)
+
+kernel/
+~~~~~~~
+
+o Alan: 32bit uid support is *still* broken for process accounting.
+
+  Create a 32bit uid, turn accounting on.  Shock horror it doesn't work
+  because the field is 16bit.  We need an acct structure flag day for 2.6
+  IMHO
+
+  (alan has patch)
+
+o viro: core sysctl code is racy.  And its interaction wiuth sysfs
+
+o (ingo) rwsems (on x86) are limited to 32766 waiting processes.  This
+  means that setting pid_max to above 32K is unsafe :-(
+
+  An option is to use CONFIG_RWSEM_GENERIC_SPINLOCK variant all the time,
+  for all archs, and not inline any part of the ops.
+
+lib/kobject.c
+~~~~~~~~~~~~~
+
+o kobject refcounting (comments from Al Viro):
+
+  _anything_ can grab a temporary reference to kobject.  IOW, if kobject is
+  embedded into something that could be freed - it _MUST_ have a destructor
+  and that destructor _MUST_ be the destructor for containing object.
+
+  Any violation of the above (and we already have a bunch of those) is a
+  user-triggerable memory corruption.
+
+  We can tolerate it for a while in 2.5 (e.g.  during work on susbsystem we
+  can decide to switch to that way of handling objects and have subsystem
+  vulnerable for a while), but all such windows must be closed before 2.6
+  and during 2.6 we can't open them at all.
+
+o All block drivers which control multiple gendisks with a single
+  request_queue are broken, due to one-to-one assumptions in the request
+  queue sysfs hookup.
+
+mm/
+~~~
+
+o GFP_DMA32 (or something like that).  Lots of ideas.  jejb, zaitcev,
+  willy, arjan, wli.
+
+  Specifically, 64-bit systems need to be able to enforce 32-bit addressing
+  limits for device metadata like network cards' ring buffers and SCSI
+  command descriptors.
+
+o access_process_vm() doesn't flush right.  We probably need new flushing
+  primitives to do this (davem?)
+
+
+modules
+~~~~~~~
+
+  (Rusty)
+
+net/
+~~~~
+
+  (davem)
+
+o UDP apps can in theory deadlock, because the ip_append_data path can end
+  up sleeping while the socket lock is held.
+
+  It is OK to sleep with the socket held held, normally.  But in this case
+  the sleep happens while waiting for socket memory/space to become
+  available, if another context needs to take the socket lock to free up the
+  space we could hang.
+
+  I sent a rough patch on how to fix this to Alexey, and he is analyzing
+  the situation.  I expect a final fix from him next week or so.
+
+o Semantics for IPSEC during operations such as TCP connect suck currently.
+
+  When we first try to connect to a destination, we may need to ask the
+  IPSEC key management daemon to resolve the IPSEC routes for us.  For the
+  purposes of what the kernel needs to do, you can think of it like ARP.  We
+  can't send the packet out properly until we resolve the path.
+
+  What happens now for IPSEC is basically this:
+
+  O_NONBLOCK: returns -EAGAIN over and over until route is resolved
+
+  !O_NONBLOCK: Sleeps until route is resolved
+
+  These semantics are total crap.  The solution, which Alexey is working
+  on, is to allow incomplete routes to exist.  These "incomplete" routes
+  merely put the packet onto a "resolution queue", and once the key manager
+  does it's thing we finish the output of the packet.  This is precisely how
+  ARP works.
+
+  I don't know when Alexey will be done with this.
+
+net/*/netfilter/
+~~~~~~~~~~~~~~~~
+
+  (Rusty)
+
+sound/
+~~~~~~
+
+global
+~~~~~~
+
+o viro: 64-bit dev_t (not a mustfix for 2.6.0). 32-bit dev_t is done, 64-bit
+  means extra work on nfsd/raid/etc.
+
+o alan: Forward port 2.4 fixes
+  - Chris Wright: Security fixes including execve holes, execve vs proc races
+
+o There are about 60 or 70 security related checks that need doing
+  (copy_user etc) from Stanford tools.  (badari is looking into this, and
+  hollisb)
+
+o A couple of hundred real looking bugzilla bugs
+
+o viro: cdev rework. Mostly done.
+
--- diff/Documentation/networking/netconsole.txt	1970-01-01 01:00:00.000000000 +0100
+++ source/Documentation/networking/netconsole.txt	2004-02-23 13:56:39.000000000 +0000
@@ -0,0 +1,57 @@
+
+started by Ingo Molnar <mingo@redhat.com>, 2001.09.17
+2.6 port and netpoll api by Matt Mackall <mpm@selenic.com>, Sep 9 2003
+
+Please send bug reports to Matt Mackall <mpm@selenic.com>
+
+This module logs kernel printk messages over UDP allowing debugging of
+problem where disk logging fails and serial consoles are impractical.
+
+It can be used either built-in or as a module. As a built-in,
+netconsole initializes immediately after NIC cards and will bring up
+the specified interface as soon as possible. While this doesn't allow
+capture of early kernel panics, it does capture most of the boot
+process.
+
+It takes a string configuration parameter "netconsole" in the
+following format:
+
+ netconsole=[src-port]@[src-ip]/[<dev>],[tgt-port]@<tgt-ip>/[tgt-macaddr]
+
+   where
+        src-port      source for UDP packets (defaults to 6665)
+        src-ip        source IP to use (interface address)
+        dev           network interface (eth0)
+        tgt-port      port for logging agent (6666)
+        tgt-ip        IP address for logging agent
+        tgt-macaddr   ethernet MAC address for logging agent (broadcast)
+
+Examples:
+
+ linux netconsole=4444@10.0.0.1/eth1,9353@10.0.0.2/12:34:56:78:9a:bc
+
+  or
+
+ insmod netconsole netconsole=@/,@10.0.0.2/
+
+Built-in netconsole starts immediately after the TCP stack is
+initialized and attempts to bring up the supplied dev at the supplied
+address.
+
+The remote host can run either 'netcat -u -l -p <port>' or syslogd.
+
+WARNING: the default target ethernet setting uses the broadcast
+ethernet address to send packets, which can cause increased load on
+other systems on the same ethernet segment.
+
+NOTE: the network device (eth1 in the above case) can run any kind
+of other network traffic, netconsole is not intrusive. Netconsole
+might cause slight delays in other traffic if the volume of kernel
+messages is high, but should have no other impact.
+
+Netconsole was designed to be as instantaneous as possible, to
+enable the logging of even the most critical kernel bugs. It works
+from IRQ contexts as well, and does not enable interrupts while
+sending packets. Due to these unique needs, configuration can not
+be more automatic, and some fundamental limitations will remain:
+only IP networks, UDP packets and ethernet devices are supported.
--- diff/Documentation/sched-domains.txt	1970-01-01 01:00:00.000000000 +0100
+++ source/Documentation/sched-domains.txt	2004-02-23 13:56:40.000000000 +0000
@@ -0,0 +1,55 @@
+Each CPU has a "base" scheduling domain (struct sched_domain). These are
+accessed via cpu_sched_domain(i) and this_sched_domain() macros. The domain
+hierarchy is built from these base domains via the ->parent pointer. ->parent
+MUST be NULL terminated, and domain structures should be per-CPU as they
+are locklessly updated.
+
+Each scheduling domain spans a number of CPUs (stored in the ->span field).
+A domain's span MUST be a superset of it child's span, and a base domain
+for CPU i MUST span at least i. The top domain for each CPU will generally
+span all CPUs in the system although strictly it doesn't have to, but this
+could lead to a case where some CPUs will never be given tasks to run unless
+the CPUs allowed mask is explicitly set. A sched domain's span means "balance
+process load among these CPUs".
+
+Each scheduling domain must have one or more CPU groups (struct sched_group)
+which are organised as a circular one way linked list from the ->groups
+pointer. The union of cpumasks of these groups MUST be the same as the
+domain's span. The intersection of cpumasks from any two of these groups
+MUST be the empty set. The group pointed to by the ->groups pointer MUST
+contain the CPU to which the domain belongs. Groups may be shared among
+CPUs as they contain read only data after they have been set up.
+
+Balancing within a sched domain occurs between groups. That is, each group
+is treated as one entity. The load of a group is defined as the sum of the
+load of each of its member CPUs, and only when the load of a group becomes
+out of balance are tasks moved between groups.
+
+In kernel/sched.c, rebalance_tick is run periodically on each CPU. This
+function takes its CPU's base sched domain and checks to see if has reached
+its rebalance interval. If so, then it will run load_balance on that domain.
+rebalance_tick then checks the parent sched_domain (if it exists), and the
+parent of the parent and so forth.
+
+*** Implementing sched domains ***
+The "base" domain will "span" the first level of the hierarchy. In the case
+of SMT, you'll span all siblings of the physical CPU, with each group being
+a single virtual CPU.
+
+In SMP, the parent of the base domain will span all physical CPUs in the
+node. Each group being a single physical CPU. Then with NUMA, the parent
+of the SMP domain will span the entire machine, with each group having the
+cpumask of a node. Or, you could do multi-level NUMA or Opteron, for example,
+might have just one domain covering its one NUMA level.
+
+The implementor should read comments in include/linux/sched.h:
+struct sched_domain fields, SD_FLAG_*, SD_*_INIT to get an idea of
+the specifics and what to tune.
+
+Implementors should change the line
+#undef SCHED_DOMAIN_DEBUG
+to
+#define SCHED_DOMAIN_DEBUG
+in kernel/sched.c as this enables an error checking parse of the sched domains
+which should catch most possible errors (described above). It also prints out
+the domain structure in a visual format.
--- diff/Documentation/should-fix.txt	1970-01-01 01:00:00.000000000 +0100
+++ source/Documentation/should-fix.txt	2004-02-23 13:56:40.000000000 +0000
@@ -0,0 +1,545 @@
+Not-ready features and speedups
+===============================
+
+Legend:
+
+PRI1:	We're totally lame if this doesn't get in
+PRI2:	Would be nice
+PRI3:	Not very important
+
+drivers/block/
+~~~~~~~~~~~~~~
+
+o viro: paride drivers need a big cleanup. Partially done, but ATAPI drivers
+  need serious work and bug fixing.
+
+  PRI2
+
+drivers/char/rtc/
+~~~~~~~~~~~~~~~~~
+
+o rmk, trini: add support for alarms to the existing generic rtc driver.
+
+  PRI2
+
+console drivers
+~~~~~~~~~~~~~~~
+  (Pavel Machek <pavel@ucw.cz>)
+
+o There are few must-fix bugs in cursor handling.
+
+o Play with gpm selection for a while and your cursor gets corrupted with
+  random dots. Ouch.
+
+device mapper
+~~~~~~~~~~~~~
+
+o ioctl interface cleanup patch is ready (redo the structure layouts)
+
+  PRI1
+
+o A port of the 2.4 snapshot and mirror targets is in progress
+
+  PRI1
+
+o the fs interface to dm needs to be redone.  gregkh was going to work on
+  this.  viro is interested in seeing work thus-far.
+
+  PRI2
+
+drivers/net/wireless/
+~~~~~~~~~~~~~~~~~~~~~
+
+  (Jean Tourrilhes <jt@bougret.hpl.hp.com>)
+
+o get HostAP driver in the kernel.  No consolidation of the 802.11
+  management across driver can happen until this one is in (which is probably
+  2.7.X material).  I think Jouni is mostly ready but didn't find time for
+  it.
+
+  PRI2
+
+o get more wireless drivers into the kernel.  The most "integrable" drivers
+  at this point seem the NWN driver, Pavel's Spectrum driver.
+
+  PRI1
+
+drivers/usb/gadget/
+~~~~~~~~~~~~~~~~~~~
+
+o rmk: SA11xx USB client/gadget code (David B has been doing some work on
+  this, and keeps trying to prod me, but unfortunately I haven't had the time
+  to look at his work, sorry David.)
+
+  PRI3
+
+fs/
+~~~
+
+o ext3 and ext2 block allocators have serious failure modes - interleaved
+  allocations.
+
+  PRI3
+
+o Integrate Chris Mason's 2.4 reiserfs ordered data and data journaling
+  patches.  They make reiserfs a lot safer.
+
+  Ordered: PRI2
+  data journalled: PRI3
+
+o viro: convert more filesystems to use lib/parser.c for options.
+
+  PRI2
+
+o aio: fs IO isn't async at present.  suparna has restart patches, they're
+  in -mm.  Need to get Ben to review/comment.
+
+  PRI1.
+
+o drepper: various filesystems use ->pid wrongly
+
+  PRI1
+
+o hch: devfs: there's a fundamental lookup vs devfsd race that's only
+  fixable by introducing a lookup vs devfs deadlock.  I can't see how this is
+  fixable without getting rid of the current devfsd design.  Mandrake seems
+  to have a workaround for this so this is at least not triggered so easily,
+  but that's not what I'd consider a fix..
+
+  PRI2
+
+kernel/
+~~~~~~~
+
+o rusty: Zippel's Reference count simplification.  Tricky code, but cuts
+  about 120 lines from module.c.  Patch exists, needs stressing.
+
+  PRI3
+
+o rusty: Fix module-failed-init races by starting module "disabled".  Patch
+  exists, requires some subsystems (ie.  add_partition) to explicitly say
+  "make module live now".  Without patch we are no worse off than 2.4 etc.
+
+  PRI1
+
+o Integrate userspace irq balancing daemon.
+
+  PRI2
+
+o kexec.  Seems to work, was in -mm.
+
+  PRI3
+
+o rmk: lib/inflate.c must not use static variables (causes these to be
+  referenced via GOTOFF relocations in PIC decompressor.  We have a PIC
+  decompressor to avoid having to hard code a per platform zImage link
+  address into the makefiles.)
+
+  PRI2
+
+o klibc merge?
+
+  PRI2
+
+mm/
+~~~
+
+o dropbehind for large files
+
+  PRI2
+
+net/
+~~~~
+
+  (davem)
+
+o Real serious use of IPSEC is hampered by lack of MPLS support.  MPLS is a
+  switching technology that works by switching based upon fixed length labels
+  prepended to packets.  Many people use this and IPSEC to implement VPNs
+  over public networks, it is also used for things like traffic engineering.
+
+  A good reference site is:
+
+	http://www.mplsrc.com/
+
+  Anyways, an existing (crappy) implementation exists.  I've almost
+  completed a rewrite, I should have something in the tree next week.
+
+  PRI1
+
+o Sometimes we generate IP fragments when it truly isn't necessary.
+
+  The way IP fragmentation is specified, each fragment must be modulo 8
+  bytes in length.  So suppose the device has an MTU that is not 0 modulo 8,
+  ethernet even classifies in this way.  1500 == (8 * 187) + 4
+
+  Our IP fragmenting engine can fragment on packets that are sized within
+  the last modulo 8 bytes of the MTU.  This happens in obscure cases, but it
+  does happen.
+
+  I've proposed a fix to Alexey, whereby very late in the output path we
+  check the packet, if we fragmented but the data length would fit into the
+  MTU we unfragment the packet.
+
+  This is low priority, because technically it creates suboptimal behavior
+  rather than mis-operation.
+
+  PRI1
+
+net/*/netfilter/
+~~~~~~~~~~~~~~~~
+
+o Lots of misc. cleanups, which are happening slowly.
+
+  PRI2
+
+power management
+~~~~~~~~~~~~~~~~
+
+o Pat and Pavel disagree over swsusp. Need to sort that out.
+
+  PRI2
+
+o Frame buffer restore codepaths (that requires some deep PCI magic)
+
+  PRI2
+
+o XFree86 hooks
+
+  PRI2
+
+o AGP restoration
+
+  PRI2
+
+o DRI restoration
+
+  (davej/Alan: not super-critical, can crash laptop on restore.  davej
+  looking into it.)
+
+  PRI2
+
+o IDE suspend/resume without races (Ben is looking at this a little)
+
+  PRI2
+
+o Pat: There are already CPU device structures; MTRRs should be a
+  dynamically registered interface of CPUs, which implies there needs
+  to be some other glue to know that there are MTRRs that need to be
+  saved/restored.
+
+  PRI1
+
+global
+~~~~~~
+
+o We need a kernel side API for reporting error events to userspace (could
+  be async to 2.6 itself)
+
+  (Prototype core based on netlink exists)
+
+  PRI2
+
+o Kai: Introduce a sane, easy and standard way to build external modules
+  - make clean and make modules_install are both broken
+
+  PRI2
+
+drivers
+~~~~~~~
+
+o Alan: Cardbus/PCMCIA requires all Russell's stuff is merged to do
+  multiheader right and so on
+
+  PRI1
+
+drivers/acpi/
+~~~~~~~~~~~~~
+
+o Fix acpi for all newer IBM Thinkpads see
+  http://bugme.osdl.org/show_bug.cgi?id=1038 for more information
+
+o alan: VIA APIC stuff is one bit of this, there are also some other
+  reports that were caused by ACPI not setting level v edge trigger some
+  times
+
+  PRI1
+
+o mochel: it seems the acpi irq routing code could use a serious rewrite.
+
+  grover: The problem is the ACPI irq routing code is trying to piggyback
+  on the existing MPS-specific data structures, and it's generally a hack.
+  So yes mochel is right, but it is also purging MPS-ities from common code
+  as well.  I've done some preliminary work in this area and it doesn't seem
+  to break anything (yet) but a rewrite in this area imho should not be
+  rushed out the door.  And, I think the above bugs can be fixed w/o the
+  rewrite.
+
+  PRI2
+
+o mochel: ACPI suspend doesn't work.  Important, not cricital.  Pat is
+  working it.
+
+  PRI2
+
+drivers/block/
+~~~~~~~~~~~~~~
+
+o More testing of floppy
+
+  PRI3
+
+drivers/char/
+~~~~~~~~~~~~~
+
+
+drivers/ide/
+~~~~~~~~~~~~
+
+  (Alan)
+
+o IDE PIO has occasional unexplained PIO disk eating reports
+
+  PRI1
+
+o IDE has multiple zillions of races/hangs in 2.5 still
+
+  PRI1
+
+o IDE scsi needs rewriting
+
+  PRI2
+
+o IDE needs significant reworking to handle Simplex right
+
+  PRI2
+
+o IDE hotplug handling for 2.5 is completely broken still
+
+  PRI2
+
+o There are lots of other IDE bugs that wont go away until the taskfile
+  stuff is included, the locking bugs that allow any user to hang the IDE
+  layer in 2.5, and some other updates are forward ported.  (esp.  HPT372N).
+
+  PRI1
+
+drivers/isdn/
+~~~~~~~~~~~~~
+
+  (Kai, rmk)
+
+o isdn_tty locking is completely broken (cli() and friends)
+
+  PRI2
+
+o fix other drivers
+
+  PRI2
+
+o lots more cleanups, adaption to recent APIs etc
+
+  PRI3
+
+o fixup tty-based ISDN drivers which provide TIOCM* ioctls (see my recent
+  3-set patch for serial stuff)
+
+  Alternatively, we could re-introduce the fallback to driver ioctl parsing
+  for these if not enough drivers get updated.
+
+  PRI3
+
+drivers/net/
+~~~~~~~~~~~~
+
+o davej: Either Wireless network drivers or PCMCIA broke somewhen.  A
+  configuration that worked fine under 2.4 doesn't receive any packets.  Need
+  to look into this more to make sure I don't have any misconfiguration that
+  just 'happened to work' under 2.4
+
+  PRI1
+
+drivers/scsi/
+~~~~~~~~~~~~~
+
+o jejb: qlogic -
+
+  o Merge the feral driver.  It covers all qlogic chips: 1020 all the way
+    up to 23xxx. http://linux-scsi.bkbits.net/scsi-isp-2.5
+
+  o qla2xxx: only for FC chips.  Has significant build issues.  hch
+    promises to send me a "must fix" list for this.
+    http://linux-scsi.bkbits.net/scsi-qla2xxx-2.5
+
+  PRI2
+
+o hch, Mike Anderson, Badari Pulavarty: scsi locking issues
+
+  o there are lots of members of struct Scsi_Host/scsi_device/scsi_cmnd
+    with very unclear locking, many of them probably want to become
+    atomic_t's or bitmaps (for the 1bit bitfields).
+
+  o there's lots of volatile abuse in the scsi code that needs to be
+    thought about.
+
+  o there's some global variables incremented without any locks
+
+  PRI2
+
+sound/
+~~~~~~
+
+o rmk: several OSS drivers for SA11xx-based hardware in need of
+  ALSA-ification and L3 bus support code for these.
+
+o rmk: need to complete ALSA-ification of the WaveArtist driver for both
+  NetWinder and other stuff (there's some fairly fundamental differences in
+  the way the mixer needs to be handled for the NetWinder.)
+
+  (Issues with forward-porting 2.4 bugfixes.)
+  (Killing off OSS is 2.7 material)
+
+PRI2
+
+arch/i386/
+~~~~~~~~~~
+
+o Also PC9800 merge needs finishing to the point we want for 2.6 (not all).
+
+  PRI3
+
+o davej: PAT support (for mtrr exhaustion w/ AGP)
+
+  PRI2
+
+o 2.5.x won't boot on some 440GX
+
+  alan: Problem understood now, feasible fix in 2.4/2.4-ac.  (440GX has two
+  IRQ routers, we use the $PIR table with the PIIX, but the 440GX doesnt use
+  the PIIX for its IRQ routing).  Fall back to BIOS for 440GX works and Intel
+  concurs.
+
+  PRI1
+
+o 2.5.x doesn't handle VIA APIC right yet.
+
+  1. We must write the PCI_INTERRUPT_LINE
+
+  2. We have quirk handlers that seem to trash it.
+
+  PRI1
+
+o ECC driver questions are not yet sorted (DaveJ is working on this) (Dan
+  Hollis)
+
+  alan: ECC - I have some test bits from Dan's stuff - they need no kernel
+  core changes for most platforms.  That means we can treat it as a random
+  driver merge.
+
+  PRI3
+
+o alan: 2.4 has some fixes for tsc handling bugs.  One where some bioses in
+  SMM mode mess up our toggle on the time high/low or mangle the counter and
+  one where a few chips need religious use of _p for timer access and we
+  don't do that.  This is forward porting little bits of fixup.
+
+  ACPI HZ stuff we can't trap - a lot of ACPI is implemented as outb's
+  triggering SMM traps
+
+  PRI1
+
+arch/x86_64/
+~~~~~~~~~~~~
+
+  (Andi)
+
+o time handling is broken. Need to move up 2.4 time.c code.
+
+  PRI1
+
+o NMI watchdog seems to tick too fast
+
+  PRI2
+
+o need to coredump 64bit vsyscall code with dwarf2
+
+  PRI2
+
+o move 64bit signal trampolines into vsyscall code and add dwarf2 for it.
+  (in progress)
+
+  PRI1
+
+o describe kernel assembly with dwarf2 annotations for kgdb
+
+  PRI3
+
+arch/alpha/
+~~~~~~~~~~~
+
+o rth: Ptrace writes are broken.  This means we can't (reliably) set
+  breakpoints or modify variables from gdb.
+
+  PRI1
+
+arch/arm/
+~~~~~~~~~
+
+o rmk: missing raw keyboard translation tables for all ARM machines.
+  Haven't even looked into this at all.  This could be messy since there
+  isn't an ARM architecture standard.  I'm presently hoping that it won't be
+  an issue.  If it does, I guess we'll see drivers/char/keyboard.c explode.
+
+  PRI2
+
+arch/others/
+~~~~~~~~~~~~
+
+o SH needs resyncing, as do some other ports. SH64 needs merging.
+  No impact on mainstream platforms hopefully.
+
+  PRI2
+
+arch/s390/
+~~~~~~~~~
+
+o A nastly memory management problem causes random crashes.  These appear
+  to be fixed/hidden by the objrmap patch, more investigation is needed.
+
+  PRI1
+
+drivers/s390/
+~~~~~~~~~~~~~
+
+o Early userspace and 64 bit dev_t will allow the removal of most of
+  dasd_devmap.c and dasd_genhd.c.
+
+  PRI2
+
+o The 3270 console driver needs to be replaced with a working one
+  (prototype is there, needs to be finished).
+
+  PRI2
+
+o Minor interface changes are pending in cio/ when the z990 machines are
+  out.
+
+  PRI2
+
+o Jan Glauber is working on a fix for the timer issues related to running
+  on virtualized CPUs (wall-clock vs.  cpu time).
+
+  PRI1
+
+o a block device driver for ramdisks shared among virtual machines
+
+  PRI3
+
+o driver for crypto hardware
+
+  PRI3
+
+o 'claw' network device driver
+
+  PRI3
+
--- diff/Documentation/sound/alsa/MIXART.txt	1970-01-01 01:00:00.000000000 +0100
+++ source/Documentation/sound/alsa/MIXART.txt	2004-02-23 13:56:40.000000000 +0000
@@ -0,0 +1,96 @@
+    Alsa driver for Digigram miXart8 and miXart8AES/EBU soundcards
+	    Digigram <alsa@digigram.com>
+
+
+GENERAL
+=======
+
+The miXart8 is a multichannel audio processing and mixing soundcard
+that has 4 stereo audio inputs and 4 stereo audio outputs.
+The miXart8AES/EBU is the same with a add-on card that offers further
+4 digital stereo audio inputs and outputs.
+Furthermore the add-on card offers external clock synchronisation
+(AES/EBU, Word Clock, Time Code and Video Synchro)
+
+The mainboard has a PowerPC that offers onboard mpeg encoding and
+decoding, samplerate conversions and various effects.
+
+The driver don't work properly at all until the certain firmwares
+are loaded, i.e. no PCM nor mixer devices will appear.
+Use the mixartloader that can be found in the alsa-tools package.
+
+
+VERSION 0.1.0
+=============
+
+One miXart8 board will be represented as 4 alsa cards, each with 1
+stereo analog capture 'pcm0c' and 1 stereo analog playback 'pcm0p' device.
+With a miXart8AES/EBU there is in addition 1 stereo digital input
+'pcm1c' and 1 stereo digital output 'pcm1p' per card.
+
+Formats
+-------
+U8, S16_LE, S16_BE, S24_3LE, S24_3BE, FLOAT_LE, FLOAT_BE
+Sample rates : 8000 - 48000 Hz continously
+
+Playback
+--------
+For instance the playback devices are configured to have max. 4
+substreams performing hardware mixing. This could be changed to a
+maximum of 24 substreams if wished.
+Mono files will be played on the left and right channel. Each channel
+can be muted for each stream to use 8 analog/digital outputs seperately.
+
+Capture
+-------
+There is one substream per capture device. For instance only stereo
+formats are supported.
+
+Mixer
+-----
+<Master> and <Master Capture> : analog volume control of playback and capture PCM.
+<PCM 0-3> and <PCM Capture> : digital volume control of each analog substream.
+<AES 0-3> and <AES Capture> : digital volume control of each AES/EBU substream.
+<Monitoring> : Loopback from 'pcm0c' to 'pcm0p' with digital volume
+and mute control.
+
+Rem : for best audio quality try to keep a 0 attenuation on the PCM
+and AES volume controls which is set by 219 in the range from 0 to 255
+(about 86% with alsamixer)
+
+
+NOT YET IMPLEMENTED
+===================
+
+- external clock support (AES/EBU, Word Clock, Time Code, Video Sync)
+- MPEG audio formats
+- mono record
+- on-board effects and samplerate conversions
+- linked streams
+
+
+FIRMWARE
+========
+
+For loading the firmware automatically after the module is loaded, use
+the post-install command.  For example, add the following entry to
+/etc/modprobe.conf for miXart driver:
+
+	install snd-mixart /sbin/modprobe --first-time -i snd-mixart && \
+			   /usr/bin/mixartloader
+(for 2.2/2.4 kernels, add "post-install snd-mixart /usr/bin/vxloader" to
+ /etc/modules.conf, instead.)
+
+The firmware binaries are installed on /usr/share/alsa/firmware
+(or /usr/local/share/alsa/firmware, depending to the prefix option of
+configure).  There will be a miXart.conf file, which define the dsp image
+files.
+
+The firmware files are copyright by Digigram SA
+
+
+COPYRIGHT
+=========
+
+Copyright (c) 2003 Digigram SA <alsa@digigram.com>
+Distributalbe under GPL.
--- diff/Documentation/video4linux/bttv/Modprobe.conf	1970-01-01 01:00:00.000000000 +0100
+++ source/Documentation/video4linux/bttv/Modprobe.conf	2004-02-23 13:56:40.000000000 +0000
@@ -0,0 +1,11 @@
+# i2c
+alias char-major-89	i2c-dev
+options i2c-core	i2c_debug=1
+options i2c-algo-bit	bit_test=1
+
+# bttv
+alias char-major-81	videodev
+alias char-major-81-0	bttv
+options	bttv		card=2 radio=1
+options	tuner		debug=1
+
--- diff/arch/arm/mm/proc-arm925.S	1970-01-01 01:00:00.000000000 +0100
+++ source/arch/arm/mm/proc-arm925.S	2004-02-23 13:56:37.000000000 +0000
@@ -0,0 +1,551 @@
+/*
+ *  linux/arch/arm/mm/arm925.S: MMU functions for ARM925
+ *
+ *  Copyright (C) 1999,2000 ARM Limited
+ *  Copyright (C) 2000 Deep Blue Solutions Ltd.
+ *  Copyright (C) 2002 RidgeRun, Inc.
+ *  Copyright (C) 2002-2003 MontaVista Software, Inc.
+ *
+ *  Update for Linux-2.6 and cache flush improvements
+ *  Copyright (C) 2004 Nokia Corporation by Tony Lindgren <tony@atomide.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ *
+ * These are the low level assembler for performing cache and TLB
+ * functions on the arm925.
+ *
+ *  CONFIG_CPU_ARM925_CPU_IDLE -> nohlt
+ *
+ * Some additional notes based on deciphering the TI TRM on OMAP-5910:
+ *
+ * NOTE1: The TI925T Configuration Register bit "D-cache clean and flush
+ *	  entry mode" must be 0 to flush the entries in both segments
+ *	  at once. This is the default value. See TRM 2-20 and 2-24 for
+ *	  more information.
+ *
+ * NOTE2: Default is the "D-cache clean and flush entry mode". It looks
+ *	  like the "Transparent mode" must be on for partial cache flushes
+ *	  to work in this mode. This mode only works with 16-bit external
+ *	  memory. See TRM 2-24 for more information.
+ *
+ * NOTE3: Write-back cache flushing seems to be flakey with devices using
+ *        direct memory access, such as USB OHCI. The workaround is to use
+ *        write-through cache with CONFIG_CPU_DCACHE_WRITETHROUGH (this is
+ *        the default for OMAP-1510).
+ */
+
+#include <linux/linkage.h>
+#include <linux/config.h>
+#include <linux/init.h>
+#include <asm/assembler.h>
+#include <asm/pgtable.h>
+#include <asm/procinfo.h>
+#include <asm/hardware.h>
+#include <asm/page.h>
+#include <asm/ptrace.h>
+#include "proc-macros.S"
+
+/*
+ * The size of one data cache line.
+ */
+#define CACHE_DLINESIZE	16
+
+/*
+ * The number of data cache segments.
+ */
+#define CACHE_DSEGMENTS	2
+
+/*
+ * The number of lines in a cache segment.
+ */
+#define CACHE_DENTRIES	256
+
+/*
+ * This is the size at which it becomes more efficient to
+ * clean the whole cache, rather than using the individual
+ * cache line maintainence instructions.
+ */
+#define CACHE_DLIMIT	8192
+
+	.text
+/*
+ * cpu_arm925_proc_init()
+ */
+ENTRY(cpu_arm925_proc_init)
+	mov	pc, lr
+
+/*
+ * cpu_arm925_proc_fin()
+ */
+ENTRY(cpu_arm925_proc_fin)
+	stmfd	sp!, {lr}
+	mov	ip, #PSR_F_BIT | PSR_I_BIT | SVC_MODE
+	msr	cpsr_c, ip
+	bl	arm925_flush_kern_cache_all
+	mrc	p15, 0, r0, c1, c0, 0		@ ctrl register
+	bic	r0, r0, #0x1000			@ ...i............
+	bic	r0, r0, #0x000e			@ ............wca.
+	mcr	p15, 0, r0, c1, c0, 0		@ disable caches
+	ldmfd	sp!, {pc}
+
+/*
+ * cpu_arm925_reset(loc)
+ *
+ * Perform a soft reset of the system.  Put the CPU into the
+ * same state as it would be if it had been reset, and branch
+ * to what would be the reset vector.
+ *
+ * loc: location to jump to for soft reset
+ */
+	.align	5
+ENTRY(cpu_arm925_reset)
+	/* Send software reset to MPU and DSP */
+	mov	ip, #0xff000000
+	orr	ip, ip, #0x00fe0000
+	orr	ip, ip, #0x0000ce00
+	mov	r4, #1
+	strh	r4, [ip, #0x10]
+
+	mov	ip, #0
+	mcr	p15, 0, ip, c7, c7, 0		@ invalidate I,D caches
+	mcr	p15, 0, ip, c7, c10, 4		@ drain WB
+	mcr	p15, 0, ip, c8, c7, 0		@ invalidate I & D TLBs
+	mrc	p15, 0, ip, c1, c0, 0		@ ctrl register
+	bic	ip, ip, #0x000f			@ ............wcam
+	bic	ip, ip, #0x1100			@ ...i...s........
+	mcr	p15, 0, ip, c1, c0, 0		@ ctrl register
+	mov	pc, r0
+
+/*
+ * cpu_arm925_do_idle()
+ *
+ * Called with IRQs disabled
+ */
+	.align	10
+ENTRY(cpu_arm925_do_idle)
+	mov	r0, #0
+	mrc	p15, 0, r1, c1, c0, 0		@ Read control register
+	mcr	p15, 0, r0, c7, c10, 4		@ Drain write buffer
+	bic	r2, r1, #1 << 12
+	mcr	p15, 0, r2, c1, c0, 0		@ Disable I cache
+	mcr	p15, 0, r0, c7, c0, 4		@ Wait for interrupt
+	mcr	p15, 0, r1, c1, c0, 0		@ Restore ICache enable
+	mov	pc, lr
+
+/*
+ *	flush_user_cache_all()
+ *
+ *	Clean and invalidate all cache entries in a particular
+ *	address space.
+ */
+ENTRY(arm925_flush_user_cache_all)
+	/* FALLTHROUGH */
+
+/*
+ *	flush_kern_cache_all()
+ *
+ *	Clean and invalidate the entire cache.
+ */
+ENTRY(arm925_flush_kern_cache_all)
+	mov	r2, #VM_EXEC
+	mov	ip, #0
+__flush_whole_cache:
+#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
+	mcr	p15, 0, ip, c7, c6, 0		@ invalidate D cache
+#else
+	/* Flush entries in both segments at once, see NOTE1 above */
+	mov	r3, #(CACHE_DENTRIES - 1) << 4	@ 256 entries in segment
+2:	mcr	p15, 0, r3, c7, c14, 2		@ clean+invalidate D index
+	subs	r3, r3, #1 << 4
+	bcs	2b				@ entries 255 to 0
+#endif
+	tst	r2, #VM_EXEC
+	mcrne	p15, 0, ip, c7, c5, 0		@ invalidate I cache
+	mcrne	p15, 0, ip, c7, c10, 4		@ drain WB
+	mov	pc, lr
+
+/*
+ *	flush_user_cache_range(start, end, flags)
+ *
+ *	Clean and invalidate a range of cache entries in the
+ *	specified address range.
+ *
+ *	- start	- start address (inclusive)
+ *	- end	- end address (exclusive)
+ *	- flags	- vm_flags describing address space
+ */
+ENTRY(arm925_flush_user_cache_range)
+	mov	ip, #0
+	sub	r3, r1, r0			@ calculate total size
+	cmp	r3, #CACHE_DLIMIT
+	bgt	__flush_whole_cache
+1:	tst	r2, #VM_EXEC
+#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
+	mcr	p15, 0, r0, c7, c6, 1		@ invalidate D entry
+	mcrne	p15, 0, r0, c7, c5, 1		@ invalidate I entry
+	add	r0, r0, #CACHE_DLINESIZE
+	mcr	p15, 0, r0, c7, c6, 1		@ invalidate D entry
+	mcrne	p15, 0, r0, c7, c5, 1		@ invalidate I entry
+	add	r0, r0, #CACHE_DLINESIZE
+#else
+	mcr	p15, 0, r0, c7, c14, 1		@ clean and invalidate D entry
+	mcrne	p15, 0, r0, c7, c5, 1		@ invalidate I entry
+	add	r0, r0, #CACHE_DLINESIZE
+	mcr	p15, 0, r0, c7, c14, 1		@ clean and invalidate D entry
+	mcrne	p15, 0, r0, c7, c5, 1		@ invalidate I entry
+	add	r0, r0, #CACHE_DLINESIZE
+#endif
+	cmp	r0, r1
+	blo	1b
+	tst	r2, #VM_EXEC
+	mcrne	p15, 0, ip, c7, c10, 4		@ drain WB
+	mov	pc, lr
+
+/*
+ *	coherent_kern_range(start, end)
+ *
+ *	Ensure coherency between the Icache and the Dcache in the
+ *	region described by start, end.  If you have non-snooping
+ *	Harvard caches, you need to implement this function.
+ *
+ *	- start	- virtual start address
+ *	- end	- virtual end address
+ */
+ENTRY(arm925_coherent_kern_range)
+	bic	r0, r0, #CACHE_DLINESIZE - 1
+1:	mcr	p15, 0, r0, c7, c10, 1		@ clean D entry
+	mcr	p15, 0, r0, c7, c5, 1		@ invalidate I entry
+	add	r0, r0, #CACHE_DLINESIZE
+	cmp	r0, r1
+	blo	1b
+	mcr	p15, 0, r0, c7, c10, 4		@ drain WB
+	mov	pc, lr
+
+/*
+ *	flush_kern_dcache_page(void *page)
+ *
+ *	Ensure no D cache aliasing occurs, either with itself or
+ *	the I cache
+ *
+ *	- addr	- page aligned address
+ */
+ENTRY(arm925_flush_kern_dcache_page)
+	add	r1, r0, #PAGE_SZ
+1:	mcr	p15, 0, r0, c7, c14, 1		@ clean+invalidate D entry
+	add	r0, r0, #CACHE_DLINESIZE
+	cmp	r0, r1
+	blo	1b
+	mov	r0, #0
+	mcr	p15, 0, r0, c7, c5, 0		@ invalidate I cache
+	mcr	p15, 0, r0, c7, c10, 4		@ drain WB
+	mov	pc, lr
+
+/*
+ *	dma_inv_range(start, end)
+ *
+ *	Invalidate (discard) the specified virtual address range.
+ *	May not write back any entries.  If 'start' or 'end'
+ *	are not cache line aligned, those lines must be written
+ *	back.
+ *
+ *	- start	- virtual start address
+ *	- end	- virtual end address
+ *
+ * (same as v4wb)
+ */
+ENTRY(arm925_dma_inv_range)
+#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
+	tst	r0, #CACHE_DLINESIZE - 1
+	mcrne	p15, 0, r0, c7, c10, 1		@ clean D entry
+	tst	r1, #CACHE_DLINESIZE - 1
+	mcrne	p15, 0, r1, c7, c10, 1		@ clean D entry
+#endif
+	bic	r0, r0, #CACHE_DLINESIZE - 1
+1:	mcr	p15, 0, r0, c7, c6, 1		@ invalidate D entry
+	add	r0, r0, #CACHE_DLINESIZE
+	cmp	r0, r1
+	blo	1b
+	mcr	p15, 0, r0, c7, c10, 4		@ drain WB
+	mov	pc, lr
+
+/*
+ *	dma_clean_range(start, end)
+ *
+ *	Clean the specified virtual address range.
+ *
+ *	- start	- virtual start address
+ *	- end	- virtual end address
+ *
+ * (same as v4wb)
+ */
+ENTRY(arm925_dma_clean_range)
+#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
+	bic	r0, r0, #CACHE_DLINESIZE - 1
+1:	mcr	p15, 0, r0, c7, c10, 1		@ clean D entry
+	add	r0, r0, #CACHE_DLINESIZE
+	cmp	r0, r1
+	blo	1b
+#endif
+	mcr	p15, 0, r0, c7, c10, 4		@ drain WB
+	mov	pc, lr
+
+/*
+ *	dma_flush_range(start, end)
+ *
+ *	Clean and invalidate the specified virtual address range.
+ *
+ *	- start	- virtual start address
+ *	- end	- virtual end address
+ */
+ENTRY(arm925_dma_flush_range)
+	bic	r0, r0, #CACHE_DLINESIZE - 1
+1:
+#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
+	mcr	p15, 0, r0, c7, c14, 1		@ clean+invalidate D entry
+#else
+	mcr	p15, 0, r0, c7, c10, 1		@ clean D entry
+#endif
+	add	r0, r0, #CACHE_DLINESIZE
+	cmp	r0, r1
+	blo	1b
+	mcr	p15, 0, r0, c7, c10, 4		@ drain WB
+	mov	pc, lr
+
+ENTRY(arm925_cache_fns)
+	.long	arm925_flush_kern_cache_all
+	.long	arm925_flush_user_cache_all
+	.long	arm925_flush_user_cache_range
+	.long	arm925_coherent_kern_range
+	.long	arm925_flush_kern_dcache_page
+	.long	arm925_dma_inv_range
+	.long	arm925_dma_clean_range
+	.long	arm925_dma_flush_range
+
+ENTRY(cpu_arm925_dcache_clean_area)
+#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
+1:	mcr	p15, 0, r0, c7, c10, 1		@ clean D entry
+	add	r0, r0, #CACHE_DLINESIZE
+	subs	r1, r1, #CACHE_DLINESIZE
+	bhi	1b
+#endif
+	mcr	p15, 0, r0, c7, c10, 4		@ drain WB
+	mov	pc, lr
+
+/* =============================== PageTable ============================== */
+
+/*
+ * cpu_arm925_switch_mm(pgd)
+ *
+ * Set the translation base pointer to be as described by pgd.
+ *
+ * pgd: new page tables
+ */
+	.align	5
+ENTRY(cpu_arm925_switch_mm)
+	mov	ip, #0
+#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
+	mcr	p15, 0, ip, c7, c6, 0		@ invalidate D cache
+#else
+	/* Flush entries in bothe segments at once, see NOTE1 above */
+	mov	r3, #(CACHE_DENTRIES - 1) << 4	@ 256 entries in segment
+2:	mcr	p15, 0, r3, c7, c14, 2		@ clean & invalidate D index
+	subs	r3, r3, #1 << 4
+	bcs	2b				@ entries 255 to 0
+#endif
+	mcr	p15, 0, ip, c7, c5, 0		@ invalidate I cache
+	mcr	p15, 0, ip, c7, c10, 4		@ drain WB
+	mcr	p15, 0, r0, c2, c0, 0		@ load page table pointer
+	mcr	p15, 0, ip, c8, c7, 0		@ invalidate I & D TLBs
+	mov	pc, lr
+
+/*
+ * cpu_arm925_set_pte(ptep, pte)
+ *
+ * Set a PTE and flush it out
+ */
+	.align	5
+ENTRY(cpu_arm925_set_pte)
+	str	r1, [r0], #-2048		@ linux version
+
+	eor	r1, r1, #L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_WRITE | L_PTE_DIRTY
+
+	bic	r2, r1, #PTE_SMALL_AP_MASK
+	bic	r2, r2, #PTE_TYPE_MASK
+	orr	r2, r2, #PTE_TYPE_SMALL
+
+	tst	r1, #L_PTE_USER			@ User?
+	orrne	r2, r2, #PTE_SMALL_AP_URO_SRW
+
+	tst	r1, #L_PTE_WRITE | L_PTE_DIRTY	@ Write and Dirty?
+	orreq	r2, r2, #PTE_SMALL_AP_UNO_SRW
+
+	tst	r1, #L_PTE_PRESENT | L_PTE_YOUNG	@ Present and Young?
+	movne	r2, #0
+
+#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
+	eor	r3, r2, #0x0a			@ C & small page?
+	tst	r3, #0x0b
+	biceq	r2, r2, #4
+#endif
+	str	r2, [r0]			@ hardware version
+	mov	r0, r0
+#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
+	mcr	p15, 0, r0, c7, c10, 1		@ clean D entry
+#endif
+	mcr	p15, 0, r0, c7, c10, 4		@ drain WB
+	mov	pc, lr
+
+	__INIT
+
+	.type	__arm925_setup, #function
+__arm925_setup:
+	mov	r0, #0
+#if defined(CONFIG_CPU_ICACHE_STREAMING_DISABLE)
+        orr     r0,r0,#1 << 7
+#endif
+
+	/* Transparent on, D-cache clean & flush mode. See  NOTE2 above */
+        orr     r0,r0,#1 << 1			@ transparent mode on
+        mcr     p15, 0, r0, c15, c1, 0          @ write TI config register
+
+	mov	r0, #0
+	mcr	p15, 0, r0, c7, c7		@ invalidate I,D caches on v4
+	mcr	p15, 0, r0, c7, c10, 4		@ drain write buffer on v4
+	mcr	p15, 0, r0, c8, c7		@ invalidate I,D TLBs on v4
+	mcr	p15, 0, r4, c2, c0		@ load page table pointer
+
+#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
+	mov	r0, #4				@ disable write-back on caches explicitly
+	mcr	p15, 7, r0, c15, c0, 0
+#endif
+
+	mov	r0, #0x1f			@ Domains 0, 1 = client
+	mcr	p15, 0, r0, c3, c0		@ load domain access register
+	mrc	p15, 0, r0, c1, c0		@ get control register v4
+/*
+ * Clear out 'unwanted' bits (then put them in if we need them)
+ */
+						@   VI ZFRS BLDP WCAM
+	bic	r0, r0, #0x0e00
+	bic	r0, r0, #0x0002
+	bic	r0, r0, #0x000c
+	bic	r0, r0, #0x1000			@ ...0 000. .... 000.
+/*
+ * Turn on what we want
+ */
+	orr	r0, r0, #0x0031
+	orr	r0, r0, #0x2100			@ ..1. ...1 ..11 ...1
+
+	/* Writebuffer on */
+	orr	r0, r0, #0x0008			@ .... .... .... 1...
+
+#ifdef CONFIG_CPU_CACHE_ROUND_ROBIN
+	orr	r0, r0, #0x4000			@ .1.. .... .... ....
+#endif
+#ifndef CONFIG_CPU_DCACHE_DISABLE
+	orr	r0, r0, #0x0004			@ .... .... .... .1..
+#endif
+#ifndef CONFIG_CPU_ICACHE_DISABLE
+	orr	r0, r0, #0x1000			@ ...1 .... .... ....
+#endif
+	mov	pc, lr
+	.size	__arm925_setup, . - __arm925_setup
+
+	__INITDATA
+
+/*
+ * Purpose : Function pointers used to access above functions - all calls
+ *	     come through these
+ */
+	.type	arm925_processor_functions, #object
+arm925_processor_functions:
+	.word	v4t_early_abort
+	.word	cpu_arm925_proc_init
+	.word	cpu_arm925_proc_fin
+	.word	cpu_arm925_reset
+	.word   cpu_arm925_do_idle
+	.word	cpu_arm925_dcache_clean_area
+	.word	cpu_arm925_switch_mm
+	.word	cpu_arm925_set_pte
+	.size	arm925_processor_functions, . - arm925_processor_functions
+
+	.section ".rodata"
+
+	.type	cpu_arch_name, #object
+cpu_arch_name:
+	.asciz	"armv4t"
+	.size	cpu_arch_name, . - cpu_arch_name
+
+	.type	cpu_elf_name, #object
+cpu_elf_name:
+	.asciz	"v4"
+	.size	cpu_elf_name, . - cpu_elf_name
+
+	.type	cpu_arm925_name, #object
+cpu_arm925_name:
+	.ascii	"ARM925T"
+#ifndef CONFIG_CPU_ICACHE_DISABLE
+	.ascii	"i"
+#endif
+#ifndef CONFIG_CPU_DCACHE_DISABLE
+	.ascii	"d"
+#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
+	.ascii	"(wt)"
+#else
+	.ascii	"(wb)"
+#endif
+#ifdef CONFIG_CPU_CACHE_ROUND_ROBIN
+	.ascii	"RR"
+#endif
+#endif
+	.ascii	"\0"
+	.size	cpu_arm925_name, . - cpu_arm925_name
+
+	.align
+
+	.section ".proc.info", #alloc, #execinstr
+
+	.type	__arm925_proc_info,#object
+__arm925_proc_info:
+	.long	0x54029250
+	.long	0xfffffff0
+	.long	0x00000c12			@ mmuflags
+	b	__arm925_setup
+	.long	cpu_arch_name
+	.long	cpu_elf_name
+	.long	HWCAP_SWP | HWCAP_HALF | HWCAP_THUMB
+	.long	cpu_arm925_name
+	.long	arm925_processor_functions
+	.long	v4wbi_tlb_fns
+	.long	v4wb_user_fns
+	.long	arm925_cache_fns
+	.size	__arm925_proc_info, . - __arm925_proc_info
+
+	.type	__arm915_proc_info,#object
+__arm915_proc_info:
+	.long	0x54029150
+	.long	0xfffffff0
+	.long	0x00000c12			@ mmuflags
+	b	__arm925_setup
+	.long	cpu_arch_name
+	.long	cpu_elf_name
+	.long	HWCAP_SWP | HWCAP_HALF | HWCAP_THUMB
+	.long	cpu_arm925_name
+	.long	arm925_processor_functions
+	.long	v4wbi_tlb_fns
+	.long	v4wb_user_fns
+	.long	arm925_cache_fns
+	.size	__arm925_proc_info, . - __arm925_proc_info
--- diff/arch/arm/oprofile/Kconfig	1970-01-01 01:00:00.000000000 +0100
+++ source/arch/arm/oprofile/Kconfig	2004-02-23 13:56:37.000000000 +0000
@@ -0,0 +1,23 @@
+
+menu "Profiling support"
+	depends on EXPERIMENTAL
+
+config PROFILING
+	bool "Profiling support (EXPERIMENTAL)"
+	help
+	  Say Y here to enable the extended profiling support mechanisms used
+	  by profilers such as OProfile.
+
+
+config OPROFILE
+	tristate "OProfile system profiling (EXPERIMENTAL)"
+	depends on PROFILING
+	help
+	  OProfile is a profiling system capable of profiling the
+	  whole system, include the kernel, kernel modules, libraries,
+	  and applications.
+
+	  If unsure, say N.
+
+endmenu
+
--- diff/arch/arm/oprofile/Makefile	1970-01-01 01:00:00.000000000 +0100
+++ source/arch/arm/oprofile/Makefile	2004-02-23 13:56:37.000000000 +0000
@@ -0,0 +1,9 @@
+obj-$(CONFIG_OPROFILE) += oprofile.o
+
+DRIVER_OBJS = $(addprefix ../../../drivers/oprofile/, \
+		oprof.o cpu_buffer.o buffer_sync.o \
+		event_buffer.o oprofile_files.o \
+		oprofilefs.o oprofile_stats.o \
+		timer_int.o )
+
+oprofile-y				:= $(DRIVER_OBJS) init.o
--- diff/arch/arm/oprofile/init.c	1970-01-01 01:00:00.000000000 +0100
+++ source/arch/arm/oprofile/init.c	2004-02-23 13:56:37.000000000 +0000
@@ -0,0 +1,22 @@
+/**
+ * @file init.c
+ *
+ * @remark Copyright 2004 Oprofile Authors
+ *
+ * @author Zwane Mwaikambo
+ */
+
+#include <linux/oprofile.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+
+int oprofile_arch_init(struct oprofile_operations **ops)
+{
+	int ret = -ENODEV;
+
+	return ret;
+}
+
+void oprofile_arch_exit(void)
+{
+}
--- diff/arch/h8300/Kconfig.ide	1970-01-01 01:00:00.000000000 +0100
+++ source/arch/h8300/Kconfig.ide	2004-02-23 13:56:37.000000000 +0000
@@ -0,0 +1,23 @@
+# uClinux H8/300 Target Board Selection Menu (IDE)
+
+menu "IDE Extra configuration"
+
+config H8300_IDE_BASE
+	hex "IDE regitser base address"
+	depends on IDE
+	help
+	  IDE registers base address
+
+config H8300_IDE_ALT
+	hex "IDE regitser alternate address"
+	depends on IDE
+	help
+	  IDE alternate registers address
+
+config H8300_IDE_IRQNO
+	int "IDE IRQ no"
+	depends on IDE
+	help
+	  IDE I/F using IRQ no
+
+endmenu
--- diff/arch/i386/kernel/early_printk.c	1970-01-01 01:00:00.000000000 +0100
+++ source/arch/i386/kernel/early_printk.c	2004-02-23 13:56:37.000000000 +0000
@@ -0,0 +1,2 @@
+
+#include "../../x86_64/kernel/early_printk.c"
--- diff/arch/i386/kernel/entry_trampoline.c	1970-01-01 01:00:00.000000000 +0100
+++ source/arch/i386/kernel/entry_trampoline.c	2004-02-23 13:56:37.000000000 +0000
@@ -0,0 +1,73 @@
+/*
+ * linux/arch/i386/kernel/entry_trampoline.c
+ *
+ * (C) Copyright 2003 Ingo Molnar
+ *
+ * This file contains the needed support code for 4GB userspace
+ */
+
+#include <linux/init.h>
+#include <linux/smp.h>
+#include <linux/mm.h>
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/highmem.h>
+#include <asm/desc.h>
+#include <asm/atomic_kmap.h>
+
+extern char __entry_tramp_start, __entry_tramp_end, __start___entry_text;
+
+void __init init_entry_mappings(void)
+{
+#ifdef CONFIG_X86_HIGH_ENTRY
+	void *tramp;
+
+	/*
+	 * We need a high IDT and GDT for the 4G/4G split:
+	 */
+	trap_init_virtual_IDT();
+
+	__set_fixmap(FIX_ENTRY_TRAMPOLINE_0, __pa((unsigned long)&__entry_tramp_start), PAGE_KERNEL);
+	__set_fixmap(FIX_ENTRY_TRAMPOLINE_1, __pa((unsigned long)&__entry_tramp_start) + PAGE_SIZE, PAGE_KERNEL);
+	tramp = (void *)fix_to_virt(FIX_ENTRY_TRAMPOLINE_0);
+
+	printk("mapped 4G/4G trampoline to %p.\n", tramp);
+	BUG_ON((void *)&__start___entry_text != tramp);
+	/*
+	 * Virtual kernel stack:
+	 */
+	BUG_ON(__kmap_atomic_vaddr(KM_VSTACK0) & (THREAD_SIZE-1));
+	BUG_ON(sizeof(struct desc_struct)*NR_CPUS*GDT_ENTRIES > 2*PAGE_SIZE);
+	BUG_ON((unsigned int)&__entry_tramp_end - (unsigned int)&__entry_tramp_start > 2*PAGE_SIZE);
+
+	/*
+	 * set up the initial thread's virtual stack related
+	 * fields:
+	 */
+	current->thread.stack_page0 = virt_to_page((char *)current->thread_info);
+	current->thread.stack_page1 = virt_to_page((char *)current->thread_info + PAGE_SIZE);
+	current->thread_info->virtual_stack = (void *)__kmap_atomic_vaddr(KM_VSTACK0);
+
+	__kunmap_atomic_type(KM_VSTACK0);
+	__kunmap_atomic_type(KM_VSTACK1);
+        __kmap_atomic(current->thread.stack_page0, KM_VSTACK0);
+        __kmap_atomic(current->thread.stack_page1, KM_VSTACK1);
+
+#endif
+	current->thread_info->real_stack = (void *)current->thread_info;
+	current->thread_info->user_pgd = NULL;
+	current->thread.esp0 = (unsigned long)current->thread_info->real_stack + THREAD_SIZE;
+}
+
+
+
+void __init entry_trampoline_setup(void)
+{
+	/*
+	 * old IRQ entries set up by the boot code will still hang
+	 * around - they are a sign of hw trouble anyway, now they'll
+	 * produce a double fault message.
+	 */
+	trap_init_virtual_GDT();
+}
--- diff/arch/i386/kernel/kgdb_stub.c	1970-01-01 01:00:00.000000000 +0100
+++ source/arch/i386/kernel/kgdb_stub.c	2004-02-23 13:56:37.000000000 +0000
@@ -0,0 +1,2457 @@
+/*
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2, or (at your option) any
+ * later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the GNU
+ * General Public License for more details.
+ *
+ */
+
+/*
+ * Copyright (c) 2000 VERITAS Software Corporation.
+ *
+ */
+/****************************************************************************
+ *  Header: remcom.c,v 1.34 91/03/09 12:29:49 glenne Exp $
+ *
+ *  Module name: remcom.c $
+ *  Revision: 1.34 $
+ *  Date: 91/03/09 12:29:49 $
+ *  Contributor:     Lake Stevens Instrument Division$
+ *
+ *  Description:     low level support for gdb debugger. $
+ *
+ *  Considerations:  only works on target hardware $
+ *
+ *  Written by:	     Glenn Engel $
+ *  Updated by:	     David Grothe <dave@gcom.com>
+ *  Updated by:	     Robert Walsh <rjwalsh@durables.org>
+ *  Updated by:	     wangdi <wangdi@clusterfs.com>
+ *  ModuleState:     Experimental $
+ *
+ *  NOTES:	     See Below $
+ *
+ *  Modified for 386 by Jim Kingdon, Cygnus Support.
+ *  Compatibility with 2.1.xx kernel by David Grothe <dave@gcom.com>
+ *
+ *  Changes to allow auto initilization.  All that is needed is that it
+ *  be linked with the kernel and a break point (int 3) be executed.
+ *  The header file <asm/kgdb.h> defines BREAKPOINT to allow one to do
+ *  this. It should also be possible, once the interrupt system is up, to
+ *  call putDebugChar("+").  Once this is done, the remote debugger should
+ *  get our attention by sending a ^C in a packet. George Anzinger
+ *  <george@mvista.com>
+ *  Integrated into 2.2.5 kernel by Tigran Aivazian <tigran@sco.com>
+ *  Added thread support, support for multiple processors,
+ *	support for ia-32(x86) hardware debugging.
+ *	Amit S. Kale ( akale@veritas.com )
+ *
+ *  Modified to support debugging over ethernet by Robert Walsh
+ *  <rjwalsh@durables.org> and wangdi <wangdi@clusterfs.com>, based on
+ *  code by San Mehat.
+ *
+ *
+ *  To enable debugger support, two things need to happen.  One, a
+ *  call to set_debug_traps() is necessary in order to allow any breakpoints
+ *  or error conditions to be properly intercepted and reported to gdb.
+ *  Two, a breakpoint needs to be generated to begin communication.  This
+ *  is most easily accomplished by a call to breakpoint().  Breakpoint()
+ *  simulates a breakpoint by executing an int 3.
+ *
+ *************
+ *
+ *    The following gdb commands are supported:
+ *
+ * command	    function				   Return value
+ *
+ *    g		    return the value of the CPU registers  hex data or ENN
+ *    G		    set the value of the CPU registers	   OK or ENN
+ *
+ *    mAA..AA,LLLL  Read LLLL bytes at address AA..AA	   hex data or ENN
+ *    MAA..AA,LLLL: Write LLLL bytes at address AA.AA	   OK or ENN
+ *
+ *    c		    Resume at current address		   SNN	 ( signal NN)
+ *    cAA..AA	    Continue at address AA..AA		   SNN
+ *
+ *    s		    Step one instruction		   SNN
+ *    sAA..AA	    Step one instruction from AA..AA	   SNN
+ *
+ *    k		    kill
+ *
+ *    ?		    What was the last sigval ?		   SNN	 (signal NN)
+ *
+ * All commands and responses are sent with a packet which includes a
+ * checksum.  A packet consists of
+ *
+ * $<packet info>#<checksum>.
+ *
+ * where
+ * <packet info> :: <characters representing the command or response>
+ * <checksum>	 :: < two hex digits computed as modulo 256 sum of <packetinfo>>
+ *
+ * When a packet is received, it is first acknowledged with either '+' or '-'.
+ * '+' indicates a successful transfer.	 '-' indicates a failed transfer.
+ *
+ * Example:
+ *
+ * Host:		  Reply:
+ * $m0,10#2a		   +$00010203040506070809101112131415#42
+ *
+ ****************************************************************************/
+#define KGDB_VERSION "<20030915.1651.33>"
+#include <linux/config.h>
+#include <linux/types.h>
+#include <asm/string.h>		/* for strcpy */
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <asm/vm86.h>
+#include <asm/system.h>
+#include <asm/ptrace.h>		/* for linux pt_regs struct */
+#include <asm/kgdb_local.h>
+#include <linux/list.h>
+#include <asm/atomic.h>
+#include <asm/processor.h>
+#include <linux/irq.h>
+#include <asm/desc.h>
+#include <linux/inet.h>
+#include <linux/netpoll.h>
+
+/************************************************************************
+ *
+ * external low-level support routines
+ */
+typedef void (*Function) (void);	/* pointer to a function */
+
+/* Thread reference */
+typedef unsigned char threadref[8];
+
+extern int tty_putDebugChar(int);     /* write a single character      */
+extern int tty_getDebugChar(void);    /* read and return a single char */
+extern void tty_flushDebugChar(void); /* flush pending characters      */
+extern int eth_putDebugChar(int);     /* write a single character      */
+extern int eth_getDebugChar(void);    /* read and return a single char */
+extern void eth_flushDebugChar(void); /* flush pending characters      */
+
+/************************************************************************/
+/* BUFMAX defines the maximum number of characters in inbound/outbound buffers*/
+/* at least NUMREGBYTES*2 are needed for register packets */
+/* Longer buffer is needed to list all threads */
+#define BUFMAX 400
+
+char *kgdb_version = KGDB_VERSION;
+
+/*  debug >  0 prints ill-formed commands in valid packets & checksum errors */
+int debug_regs = 0;		/* set to non-zero to print registers */
+
+/* filled in by an external module */
+char *gdb_module_offsets;
+
+static const char hexchars[] = "0123456789abcdef";
+
+/* Number of bytes of registers.  */
+#define NUMREGBYTES 64
+/*
+ * Note that this register image is in a different order than
+ * the register image that Linux produces at interrupt time.
+ *
+ * Linux's register image is defined by struct pt_regs in ptrace.h.
+ * Just why GDB uses a different order is a historical mystery.
+ */
+enum regnames { _EAX,		/* 0 */
+	_ECX,			/* 1 */
+	_EDX,			/* 2 */
+	_EBX,			/* 3 */
+	_ESP,			/* 4 */
+	_EBP,			/* 5 */
+	_ESI,			/* 6 */
+	_EDI,			/* 7 */
+	_PC /* 8 also known as eip */ ,
+	_PS /* 9 also known as eflags */ ,
+	_CS,			/* 10 */
+	_SS,			/* 11 */
+	_DS,			/* 12 */
+	_ES,			/* 13 */
+	_FS,			/* 14 */
+	_GS			/* 15 */
+};
+
+/***************************  ASSEMBLY CODE MACROS *************************/
+/*
+ * Put the error code here just in case the user cares.
+ * Likewise, the vector number here (since GDB only gets the signal
+ * number through the usual means, and that's not very specific).
+ * The called_from is the return address so he can tell how we entered kgdb.
+ * This will allow him to seperate out the various possible entries.
+ */
+#define REMOTE_DEBUG 0		/* set != to turn on printing (also available in info) */
+
+#define PID_MAX PID_MAX_DEFAULT
+
+#ifdef CONFIG_SMP
+void smp_send_nmi_allbutself(void);
+#define IF_SMP(x) x
+#undef MAX_NO_CPUS
+#ifndef CONFIG_NO_KGDB_CPUS
+#define CONFIG_NO_KGDB_CPUS 2
+#endif
+#if CONFIG_NO_KGDB_CPUS > NR_CPUS
+#define MAX_NO_CPUS NR_CPUS
+#else
+#define MAX_NO_CPUS CONFIG_NO_KGDB_CPUS
+#endif
+#define hold_init hold_on_sstep: 1,
+#define MAX_CPU_MASK (unsigned long)((1LL << MAX_NO_CPUS) - 1LL)
+#define NUM_CPUS num_online_cpus()
+#else
+#define IF_SMP(x)
+#define hold_init
+#undef MAX_NO_CPUS
+#define MAX_NO_CPUS 1
+#define NUM_CPUS 1
+#endif
+#define NOCPU (struct task_struct *)0xbad1fbad
+/* *INDENT-OFF*	 */
+struct kgdb_info {
+	int used_malloc;
+	void *called_from;
+	long long entry_tsc;
+	int errcode;
+	int vector;
+	int print_debug_info;
+#ifdef CONFIG_SMP
+	int hold_on_sstep;
+	struct {
+		volatile struct task_struct *task;
+		int pid;
+		int hold;
+		struct pt_regs *regs;
+	} cpus_waiting[MAX_NO_CPUS];
+#endif
+} kgdb_info = {hold_init print_debug_info:REMOTE_DEBUG, vector:-1};
+
+/* *INDENT-ON*	*/
+
+#define used_m kgdb_info.used_malloc
+/*
+ * This is little area we set aside to contain the stack we
+ * need to build to allow gdb to call functions.  We use one
+ * per cpu to avoid locking issues.  We will do all this work
+ * with interrupts off so that should take care of the protection
+ * issues.
+ */
+#define LOOKASIDE_SIZE 200	/* should be more than enough */
+#define MALLOC_MAX   200	/* Max malloc size */
+struct {
+	unsigned int esp;
+	int array[LOOKASIDE_SIZE];
+} fn_call_lookaside[MAX_NO_CPUS];
+
+static int trap_cpu;
+static unsigned int OLD_esp;
+
+#define END_OF_LOOKASIDE  &fn_call_lookaside[trap_cpu].array[LOOKASIDE_SIZE]
+#define IF_BIT 0x200
+#define TF_BIT 0x100
+
+#define MALLOC_ROUND 8-1
+
+static char malloc_array[MALLOC_MAX];
+IF_SMP(static void to_gdb(const char *mess));
+void *
+malloc(int size)
+{
+
+	if (size <= (MALLOC_MAX - used_m)) {
+		int old_used = used_m;
+		used_m += ((size + MALLOC_ROUND) & (~MALLOC_ROUND));
+		return &malloc_array[old_used];
+	} else {
+		return NULL;
+	}
+}
+
+/*
+ * I/O dispatch functions...
+ * Based upon kgdboe, either call the ethernet
+ * handler or the serial one..
+ */
+void
+putDebugChar(int c)
+{
+	if (!kgdboe) {
+		tty_putDebugChar(c);
+	} else {
+		eth_putDebugChar(c);
+	}
+}
+
+int
+getDebugChar(void)
+{
+	if (!kgdboe) {
+		return tty_getDebugChar();
+	} else {
+		return eth_getDebugChar();
+	}
+}
+
+void
+flushDebugChar(void)
+{
+	if (!kgdboe) {
+		tty_flushDebugChar();
+	} else {
+		eth_flushDebugChar();
+	}
+}
+
+/*
+ * Gdb calls functions by pushing agruments, including a return address
+ * on the stack and the adjusting EIP to point to the function.	 The
+ * whole assumption in GDB is that we are on a different stack than the
+ * one the "user" i.e. code that hit the break point, is on.  This, of
+ * course is not true in the kernel.  Thus various dodges are needed to
+ * do the call without directly messing with EIP (which we can not change
+ * as it is just a location and not a register.	 To adjust it would then
+ * require that we move every thing below EIP up or down as needed.  This
+ * will not work as we may well have stack relative pointer on the stack
+ * (such as the pointer to regs, for example).
+
+ * So here is what we do:
+ * We detect gdb attempting to store into the stack area and instead, store
+ * into the fn_call_lookaside.array at the same relative location as if it
+ * were the area ESP pointed at.  We also trap ESP modifications
+ * and uses these to adjust fn_call_lookaside.esp.  On entry
+ * fn_call_lookaside.esp will be set to point at the last entry in
+ * fn_call_lookaside.array.  This allows us to check if it has changed, and
+ * if so, on exit, we add the registers we will use to do the move and a
+ * trap/ interrupt return exit sequence.  We then adjust the eflags in the
+ * regs array (remember we now have a copy in the fn_call_lookaside.array) to
+ * kill the interrupt bit, AND we change EIP to point at our set up stub.
+ * As part of the register set up we preset the registers to point at the
+ * begining and end of the fn_call_lookaside.array, so all the stub needs to
+ * do is move words from the array to the stack until ESP= the desired value
+ * then do the rti.  This will then transfer to the desired function with
+ * all the correct registers.  Nifty huh?
+ */
+extern asmlinkage void fn_call_stub(void);
+extern asmlinkage void fn_rtn_stub(void);
+/*					   *INDENT-OFF*	 */
+__asm__("fn_rtn_stub:\n\t"
+	"movl %eax,%esp\n\t"
+	"fn_call_stub:\n\t"
+	"1:\n\t"
+	"addl $-4,%ebx\n\t"
+	"movl (%ebx), %eax\n\t"
+	"pushl %eax\n\t"
+	"cmpl %esp,%ecx\n\t"
+	"jne  1b\n\t"
+	"popl %eax\n\t"
+	"popl %ebx\n\t"
+	"popl %ecx\n\t"
+	"iret \n\t");
+/*					     *INDENT-ON*  */
+#define gdb_i386vector	kgdb_info.vector
+#define gdb_i386errcode kgdb_info.errcode
+#define waiting_cpus	kgdb_info.cpus_waiting
+#define remote_debug	kgdb_info.print_debug_info
+#define hold_cpu(cpu)	kgdb_info.cpus_waiting[cpu].hold
+/* gdb locks */
+
+#ifdef CONFIG_SMP
+static int in_kgdb_called;
+static spinlock_t waitlocks[MAX_NO_CPUS] =
+    {[0 ... MAX_NO_CPUS - 1] = SPIN_LOCK_UNLOCKED };
+/*
+ * The following array has the thread pointer of each of the "other"
+ * cpus.  We make it global so it can be seen by gdb.
+ */
+volatile int in_kgdb_entry_log[MAX_NO_CPUS];
+volatile struct pt_regs *in_kgdb_here_log[MAX_NO_CPUS];
+/*
+static spinlock_t continuelocks[MAX_NO_CPUS];
+*/
+spinlock_t kgdb_spinlock = SPIN_LOCK_UNLOCKED;
+/* waiters on our spinlock plus us */
+static atomic_t spinlock_waiters = ATOMIC_INIT(1);
+static int spinlock_count = 0;
+static int spinlock_cpu = 0;
+/*
+ * Note we use nested spin locks to account for the case where a break
+ * point is encountered when calling a function by user direction from
+ * kgdb. Also there is the memory exception recursion to account for.
+ * Well, yes, but this lets other cpus thru too.  Lets add a
+ * cpu id to the lock.
+ */
+#define KGDB_SPIN_LOCK(x) if( spinlock_count == 0 || \
+			      spinlock_cpu != smp_processor_id()){\
+				      atomic_inc(&spinlock_waiters); \
+				      while (! spin_trylock(x)) {\
+					    in_kgdb(&regs);\
+				      }\
+				      atomic_dec(&spinlock_waiters); \
+				      spinlock_count = 1; \
+				      spinlock_cpu = smp_processor_id(); \
+			  }else{  \
+				      spinlock_count++; \
+			  }
+#define KGDB_SPIN_UNLOCK(x) if( --spinlock_count == 0) spin_unlock(x)
+#else
+unsigned kgdb_spinlock = 0;
+#define KGDB_SPIN_LOCK(x) --*x
+#define KGDB_SPIN_UNLOCK(x) ++*x
+#endif
+
+int
+hex(char ch)
+{
+	if ((ch >= 'a') && (ch <= 'f'))
+		return (ch - 'a' + 10);
+	if ((ch >= '0') && (ch <= '9'))
+		return (ch - '0');
+	if ((ch >= 'A') && (ch <= 'F'))
+		return (ch - 'A' + 10);
+	return (-1);
+}
+
+/* scan for the sequence $<data>#<checksum>	*/
+void
+getpacket(char *buffer)
+{
+	unsigned char checksum;
+	unsigned char xmitcsum;
+	int i;
+	int count;
+	char ch;
+
+	do {
+		/* wait around for the start character, ignore all other characters */
+		while ((ch = (getDebugChar() & 0x7f)) != '$') ;
+		checksum = 0;
+		xmitcsum = -1;
+
+		count = 0;
+
+		/* now, read until a # or end of buffer is found */
+		while (count < BUFMAX) {
+			ch = getDebugChar() & 0x7f;
+			if (ch == '#')
+				break;
+			checksum = checksum + ch;
+			buffer[count] = ch;
+			count = count + 1;
+		}
+		buffer[count] = 0;
+
+		if (ch == '#') {
+			xmitcsum = hex(getDebugChar() & 0x7f) << 4;
+			xmitcsum += hex(getDebugChar() & 0x7f);
+			if ((remote_debug) && (checksum != xmitcsum)) {
+				printk
+				    ("bad checksum.	My count = 0x%x, sent=0x%x. buf=%s\n",
+				     checksum, xmitcsum, buffer);
+			}
+
+			if (checksum != xmitcsum)
+				putDebugChar('-');	/* failed checksum */
+			else {
+				putDebugChar('+');	/* successful transfer */
+				/* if a sequence char is present, reply the sequence ID */
+				if (buffer[2] == ':') {
+					putDebugChar(buffer[0]);
+					putDebugChar(buffer[1]);
+					/* remove sequence chars from buffer */
+					count = strlen(buffer);
+					for (i = 3; i <= count; i++)
+						buffer[i - 3] = buffer[i];
+				}
+			}
+		}
+	} while (checksum != xmitcsum);
+
+	if (remote_debug)
+		printk("R:%s\n", buffer);
+	flushDebugChar();
+}
+
+/* send the packet in buffer.  */
+
+void
+putpacket(char *buffer)
+{
+	unsigned char checksum;
+	int count;
+	char ch;
+
+	/*  $<packet info>#<checksum>. */
+
+	if (!kgdboe) {
+		do {
+			if (remote_debug)
+				printk("T:%s\n", buffer);
+			putDebugChar('$');
+			checksum = 0;
+			count = 0;
+
+			while ((ch = buffer[count])) {
+				putDebugChar(ch);
+				checksum += ch;
+				count += 1;
+			}
+
+			putDebugChar('#');
+			putDebugChar(hexchars[checksum >> 4]);
+			putDebugChar(hexchars[checksum % 16]);
+			flushDebugChar();
+
+		} while ((getDebugChar() & 0x7f) != '+');
+	} else {
+		/*
+		 * For udp, we can not transfer too much bytes once.
+		 * We only transfer MAX_SEND_COUNT size bytes each time
+		 */
+
+#define MAX_SEND_COUNT 30
+
+		int send_count = 0, i = 0;
+		char send_buf[MAX_SEND_COUNT];
+
+		do {
+			if (remote_debug)
+				printk("T:%s\n", buffer);
+			putDebugChar('$');
+			checksum = 0;
+			count = 0;
+			send_count = 0;
+			while ((ch = buffer[count])) {
+				if (send_count >= MAX_SEND_COUNT) {
+					for(i = 0; i < MAX_SEND_COUNT; i++) {
+						putDebugChar(send_buf[i]);
+					}
+					flushDebugChar();
+					send_count = 0;
+				} else {
+					send_buf[send_count] = ch;
+					checksum += ch;
+					count ++;
+					send_count++;
+				}
+			}
+			for(i = 0; i < send_count; i++)
+				putDebugChar(send_buf[i]);
+			putDebugChar('#');
+			putDebugChar(hexchars[checksum >> 4]);
+			putDebugChar(hexchars[checksum % 16]);
+			flushDebugChar();
+		} while ((getDebugChar() & 0x7f) != '+');
+	}
+}
+
+static char remcomInBuffer[BUFMAX];
+static char remcomOutBuffer[BUFMAX];
+static short error;
+
+void
+debug_error(char *format, char *parm)
+{
+	if (remote_debug)
+		printk(format, parm);
+}
+
+static void
+print_regs(struct pt_regs *regs)
+{
+	printk("EAX=%08lx ", regs->eax);
+	printk("EBX=%08lx ", regs->ebx);
+	printk("ECX=%08lx ", regs->ecx);
+	printk("EDX=%08lx ", regs->edx);
+	printk("\n");
+	printk("ESI=%08lx ", regs->esi);
+	printk("EDI=%08lx ", regs->edi);
+	printk("EBP=%08lx ", regs->ebp);
+	printk("ESP=%08lx ", (long) &regs->esp);
+	printk("\n");
+	printk(" DS=%08x ", regs->xds);
+	printk(" ES=%08x ", regs->xes);
+	printk(" SS=%08x ", __KERNEL_DS);
+	printk(" FL=%08lx ", regs->eflags);
+	printk("\n");
+	printk(" CS=%08x ", regs->xcs);
+	printk(" IP=%08lx ", regs->eip);
+#if 0
+	printk(" FS=%08x ", regs->fs);
+	printk(" GS=%08x ", regs->gs);
+#endif
+	printk("\n");
+
+}				/* print_regs */
+
+#define NEW_esp fn_call_lookaside[trap_cpu].esp
+
+static void
+regs_to_gdb_regs(int *gdb_regs, struct pt_regs *regs)
+{
+	gdb_regs[_EAX] = regs->eax;
+	gdb_regs[_EBX] = regs->ebx;
+	gdb_regs[_ECX] = regs->ecx;
+	gdb_regs[_EDX] = regs->edx;
+	gdb_regs[_ESI] = regs->esi;
+	gdb_regs[_EDI] = regs->edi;
+	gdb_regs[_EBP] = regs->ebp;
+	gdb_regs[_DS] = regs->xds;
+	gdb_regs[_ES] = regs->xes;
+	gdb_regs[_PS] = regs->eflags;
+	gdb_regs[_CS] = regs->xcs;
+	gdb_regs[_PC] = regs->eip;
+	/* Note, as we are a debugging the kernel, we will always
+	 * trap in kernel code, this means no priviledge change,
+	 * and so the pt_regs structure is not completely valid.  In a non
+	 * privilege change trap, only EFLAGS, CS and EIP are put on the stack,
+	 * SS and ESP are not stacked, this means that the last 2 elements of
+	 * pt_regs is not valid (they would normally refer to the user stack)
+	 * also, using regs+1 is no good because you end up will a value that is
+	 * 2 longs (8) too high.  This used to cause stepping over functions
+	 * to fail, so my fix is to use the address of regs->esp, which
+	 * should point at the end of the stack frame.	Note I have ignored
+	 * completely exceptions that cause an error code to be stacked, such
+	 * as double fault.  Stuart Hughes, Zentropix.
+	 * original code: gdb_regs[_ESP] =  (int) (regs + 1) ;
+
+	 * this is now done on entry and moved to OLD_esp (as well as NEW_esp).
+	 */
+	gdb_regs[_ESP] = NEW_esp;
+	gdb_regs[_SS] = __KERNEL_DS;
+	gdb_regs[_FS] = 0xFFFF;
+	gdb_regs[_GS] = 0xFFFF;
+}				/* regs_to_gdb_regs */
+
+static void
+gdb_regs_to_regs(int *gdb_regs, struct pt_regs *regs)
+{
+	regs->eax = gdb_regs[_EAX];
+	regs->ebx = gdb_regs[_EBX];
+	regs->ecx = gdb_regs[_ECX];
+	regs->edx = gdb_regs[_EDX];
+	regs->esi = gdb_regs[_ESI];
+	regs->edi = gdb_regs[_EDI];
+	regs->ebp = gdb_regs[_EBP];
+	regs->xds = gdb_regs[_DS];
+	regs->xes = gdb_regs[_ES];
+	regs->eflags = gdb_regs[_PS];
+	regs->xcs = gdb_regs[_CS];
+	regs->eip = gdb_regs[_PC];
+	NEW_esp = gdb_regs[_ESP];	/* keep the value */
+#if 0				/* can't change these */
+	regs->esp = gdb_regs[_ESP];
+	regs->xss = gdb_regs[_SS];
+	regs->fs = gdb_regs[_FS];
+	regs->gs = gdb_regs[_GS];
+#endif
+
+}				/* gdb_regs_to_regs */
+extern void scheduling_functions_start_here(void);
+extern void scheduling_functions_end_here(void);
+#define first_sched	((unsigned long) scheduling_functions_start_here)
+#define last_sched	((unsigned long) scheduling_functions_end_here)
+
+int thread_list = 0;
+
+void
+get_gdb_regs(struct task_struct *p, struct pt_regs *regs, int *gdb_regs)
+{
+	unsigned long stack_page;
+	int count = 0;
+	IF_SMP(int i);
+	if (!p || p == current) {
+		regs_to_gdb_regs(gdb_regs, regs);
+		return;
+	}
+#ifdef CONFIG_SMP
+	for (i = 0; i < MAX_NO_CPUS; i++) {
+		if (p == kgdb_info.cpus_waiting[i].task) {
+			regs_to_gdb_regs(gdb_regs,
+					 kgdb_info.cpus_waiting[i].regs);
+			gdb_regs[_ESP] =
+			    (int) &kgdb_info.cpus_waiting[i].regs->esp;
+
+			return;
+		}
+	}
+#endif
+	memset(gdb_regs, 0, NUMREGBYTES);
+	gdb_regs[_ESP] = p->thread.esp;
+	gdb_regs[_PC] = p->thread.eip;
+	gdb_regs[_EBP] = *(int *) gdb_regs[_ESP];
+	gdb_regs[_EDI] = *(int *) (gdb_regs[_ESP] + 4);
+	gdb_regs[_ESI] = *(int *) (gdb_regs[_ESP] + 8);
+
+/*
+ * This code is to give a more informative notion of where a process
+ * is waiting.	It is used only when the user asks for a thread info
+ * list.  If he then switches to the thread, s/he will find the task
+ * is in schedule, but a back trace should show the same info we come
+ * up with.  This code was shamelessly purloined from process.c.  It was
+ * then enhanced to provide more registers than simply the program
+ * counter.
+ */
+
+	if (!thread_list) {
+		return;
+	}
+
+	if (p->state == TASK_RUNNING)
+		return;
+	stack_page = (unsigned long) p->thread_info;
+	if (gdb_regs[_ESP] < stack_page || gdb_regs[_ESP] > 8188 + stack_page)
+		return;
+	/* include/asm-i386/system.h:switch_to() pushes ebp last. */
+	do {
+		if (gdb_regs[_EBP] < stack_page ||
+		    gdb_regs[_EBP] > 8184 + stack_page)
+			return;
+		gdb_regs[_PC] = *(unsigned long *) (gdb_regs[_EBP] + 4);
+		gdb_regs[_ESP] = gdb_regs[_EBP] + 8;
+		gdb_regs[_EBP] = *(unsigned long *) gdb_regs[_EBP];
+		if (gdb_regs[_PC] < first_sched || gdb_regs[_PC] >= last_sched)
+			return;
+	} while (count++ < 16);
+	return;
+}
+
+/* Indicate to caller of mem2hex or hex2mem that there has been an
+   error.  */
+static volatile int mem_err = 0;
+static volatile int mem_err_expected = 0;
+static volatile int mem_err_cnt = 0;
+static int garbage_loc = -1;
+
+int
+get_char(char *addr)
+{
+	return *addr;
+}
+
+void
+set_char(char *addr, int val, int may_fault)
+{
+	/*
+	 * This code traps references to the area mapped to the kernel
+	 * stack as given by the regs and, instead, stores to the
+	 * fn_call_lookaside[cpu].array
+	 */
+	if (may_fault &&
+	    (unsigned int) addr < OLD_esp &&
+	    ((unsigned int) addr > (OLD_esp - (unsigned int) LOOKASIDE_SIZE))) {
+		addr = (char *) END_OF_LOOKASIDE - ((char *) OLD_esp - addr);
+	}
+	*addr = val;
+}
+
+/* convert the memory pointed to by mem into hex, placing result in buf */
+/* return a pointer to the last char put in buf (null) */
+/* If MAY_FAULT is non-zero, then we should set mem_err in response to
+   a fault; if zero treat a fault like any other fault in the stub.  */
+char *
+mem2hex(char *mem, char *buf, int count, int may_fault)
+{
+	int i;
+	unsigned char ch;
+
+	if (may_fault) {
+		mem_err_expected = 1;
+		mem_err = 0;
+	}
+	for (i = 0; i < count; i++) {
+		/* printk("%lx = ", mem) ; */
+
+		ch = get_char(mem++);
+
+		/* printk("%02x\n", ch & 0xFF) ; */
+		if (may_fault && mem_err) {
+			if (remote_debug)
+				printk("Mem fault fetching from addr %lx\n",
+				       (long) (mem - 1));
+			*buf = 0;	/* truncate buffer */
+			return (buf);
+		}
+		*buf++ = hexchars[ch >> 4];
+		*buf++ = hexchars[ch % 16];
+	}
+	*buf = 0;
+	if (may_fault)
+		mem_err_expected = 0;
+	return (buf);
+}
+
+/* convert the hex array pointed to by buf into binary to be placed in mem */
+/* return a pointer to the character AFTER the last byte written */
+/* NOTE: We use the may fault flag to also indicate if the write is to
+ * the registers (0) or "other" memory (!=0)
+ */
+char *
+hex2mem(char *buf, char *mem, int count, int may_fault)
+{
+	int i;
+	unsigned char ch;
+
+	if (may_fault) {
+		mem_err_expected = 1;
+		mem_err = 0;
+	}
+	for (i = 0; i < count; i++) {
+		ch = hex(*buf++) << 4;
+		ch = ch + hex(*buf++);
+		set_char(mem++, ch, may_fault);
+
+		if (may_fault && mem_err) {
+			if (remote_debug)
+				printk("Mem fault storing to addr %lx\n",
+				       (long) (mem - 1));
+			return (mem);
+		}
+	}
+	if (may_fault)
+		mem_err_expected = 0;
+	return (mem);
+}
+
+/**********************************************/
+/* WHILE WE FIND NICE HEX CHARS, BUILD AN INT */
+/* RETURN NUMBER OF CHARS PROCESSED	      */
+/**********************************************/
+int
+hexToInt(char **ptr, int *intValue)
+{
+	int numChars = 0;
+	int hexValue;
+
+	*intValue = 0;
+
+	while (**ptr) {
+		hexValue = hex(**ptr);
+		if (hexValue >= 0) {
+			*intValue = (*intValue << 4) | hexValue;
+			numChars++;
+		} else
+			break;
+
+		(*ptr)++;
+	}
+
+	return (numChars);
+}
+
+#define stubhex(h) hex(h)
+#ifdef old_thread_list
+
+static int
+stub_unpack_int(char *buff, int fieldlength)
+{
+	int nibble;
+	int retval = 0;
+
+	while (fieldlength) {
+		nibble = stubhex(*buff++);
+		retval |= nibble;
+		fieldlength--;
+		if (fieldlength)
+			retval = retval << 4;
+	}
+	return retval;
+}
+#endif
+static char *
+pack_hex_byte(char *pkt, int byte)
+{
+	*pkt++ = hexchars[(byte >> 4) & 0xf];
+	*pkt++ = hexchars[(byte & 0xf)];
+	return pkt;
+}
+
+#define BUF_THREAD_ID_SIZE 16
+
+static char *
+pack_threadid(char *pkt, threadref * id)
+{
+	char *limit;
+	unsigned char *altid;
+
+	altid = (unsigned char *) id;
+	limit = pkt + BUF_THREAD_ID_SIZE;
+	while (pkt < limit)
+		pkt = pack_hex_byte(pkt, *altid++);
+	return pkt;
+}
+
+#ifdef old_thread_list
+static char *
+unpack_byte(char *buf, int *value)
+{
+	*value = stub_unpack_int(buf, 2);
+	return buf + 2;
+}
+
+static char *
+unpack_threadid(char *inbuf, threadref * id)
+{
+	char *altref;
+	char *limit = inbuf + BUF_THREAD_ID_SIZE;
+	int x, y;
+
+	altref = (char *) id;
+
+	while (inbuf < limit) {
+		x = stubhex(*inbuf++);
+		y = stubhex(*inbuf++);
+		*altref++ = (x << 4) | y;
+	}
+	return inbuf;
+}
+#endif
+void
+int_to_threadref(threadref * id, int value)
+{
+	unsigned char *scan;
+
+	scan = (unsigned char *) id;
+	{
+		int i = 4;
+		while (i--)
+			*scan++ = 0;
+	}
+	*scan++ = (value >> 24) & 0xff;
+	*scan++ = (value >> 16) & 0xff;
+	*scan++ = (value >> 8) & 0xff;
+	*scan++ = (value & 0xff);
+}
+int
+int_to_hex_v(unsigned char * id, int value)
+{
+	unsigned char *start = id;
+	int shift;
+	int ch;
+
+	for (shift = 28; shift >= 0; shift -= 4) {
+		if ((ch = (value >> shift) & 0xf) || (id != start)) {
+			*id = hexchars[ch];
+			id++;
+		}
+	}
+	if (id == start)
+		*id++ = '0';
+	return id - start;
+}
+#ifdef old_thread_list
+
+static int
+threadref_to_int(threadref * ref)
+{
+	int i, value = 0;
+	unsigned char *scan;
+
+	scan = (char *) ref;
+	scan += 4;
+	i = 4;
+	while (i-- > 0)
+		value = (value << 8) | ((*scan++) & 0xff);
+	return value;
+}
+#endif
+static int
+cmp_str(char *s1, char *s2, int count)
+{
+	while (count--) {
+		if (*s1++ != *s2++)
+			return 0;
+	}
+	return 1;
+}
+
+#if 1				/* this is a hold over from 2.4 where O(1) was "sometimes" */
+extern struct task_struct *kgdb_get_idle(int cpu);
+#define idle_task(cpu) kgdb_get_idle(cpu)
+#else
+#define idle_task(cpu) init_tasks[cpu]
+#endif
+
+extern int kgdb_pid_init_done;
+
+struct task_struct *
+getthread(int pid)
+{
+	struct task_struct *thread;
+	if (pid >= PID_MAX && pid <= (PID_MAX + MAX_NO_CPUS)) {
+
+		return idle_task(pid - PID_MAX);
+	} else {
+		/*
+		 * find_task_by_pid is relatively safe all the time
+		 * Other pid functions require lock downs which imply
+		 * that we may be interrupting them (as we get here
+		 * in the middle of most any lock down).
+		 * Still we don't want to call until the table exists!
+		 */
+		if (kgdb_pid_init_done){
+			thread = find_task_by_pid(pid);
+			if (thread) {
+				return thread;
+			}
+		}
+	}
+	return NULL;
+}
+/* *INDENT-OFF*	 */
+struct hw_breakpoint {
+	unsigned enabled;
+	unsigned type;
+	unsigned len;
+	unsigned addr;
+} breakinfo[4] = { {enabled:0},
+		   {enabled:0},
+		   {enabled:0},
+		   {enabled:0}};
+/* *INDENT-ON*	*/
+unsigned hw_breakpoint_status;
+void
+correct_hw_break(void)
+{
+	int breakno;
+	int correctit;
+	int breakbit;
+	unsigned dr7;
+
+	asm volatile ("movl %%db7, %0\n":"=r" (dr7)
+		      :);
+	/* *INDENT-OFF*	 */
+	do {
+		unsigned addr0, addr1, addr2, addr3;
+		asm volatile ("movl %%db0, %0\n"
+			      "movl %%db1, %1\n"
+			      "movl %%db2, %2\n"
+			      "movl %%db3, %3\n"
+			      :"=r" (addr0), "=r"(addr1),
+			      "=r"(addr2), "=r"(addr3)
+			      :);
+	} while (0);
+	/* *INDENT-ON*	*/
+	correctit = 0;
+	for (breakno = 0; breakno < 3; breakno++) {
+		breakbit = 2 << (breakno << 1);
+		if (!(dr7 & breakbit) && breakinfo[breakno].enabled) {
+			correctit = 1;
+			dr7 |= breakbit;
+			dr7 &= ~(0xf0000 << (breakno << 2));
+			dr7 |= (((breakinfo[breakno].len << 2) |
+				 breakinfo[breakno].type) << 16) <<
+			    (breakno << 2);
+			switch (breakno) {
+			case 0:
+				asm volatile ("movl %0, %%dr0\n"::"r"
+					      (breakinfo[breakno].addr));
+				break;
+
+			case 1:
+				asm volatile ("movl %0, %%dr1\n"::"r"
+					      (breakinfo[breakno].addr));
+				break;
+
+			case 2:
+				asm volatile ("movl %0, %%dr2\n"::"r"
+					      (breakinfo[breakno].addr));
+				break;
+
+			case 3:
+				asm volatile ("movl %0, %%dr3\n"::"r"
+					      (breakinfo[breakno].addr));
+				break;
+			}
+		} else if ((dr7 & breakbit) && !breakinfo[breakno].enabled) {
+			correctit = 1;
+			dr7 &= ~breakbit;
+			dr7 &= ~(0xf0000 << (breakno << 2));
+		}
+	}
+	if (correctit) {
+		asm volatile ("movl %0, %%db7\n"::"r" (dr7));
+	}
+}
+
+int
+remove_hw_break(unsigned breakno)
+{
+	if (!breakinfo[breakno].enabled) {
+		return -1;
+	}
+	breakinfo[breakno].enabled = 0;
+	return 0;
+}
+
+int
+set_hw_break(unsigned breakno, unsigned type, unsigned len, unsigned addr)
+{
+	if (breakinfo[breakno].enabled) {
+		return -1;
+	}
+	breakinfo[breakno].enabled = 1;
+	breakinfo[breakno].type = type;
+	breakinfo[breakno].len = len;
+	breakinfo[breakno].addr = addr;
+	return 0;
+}
+
+#ifdef CONFIG_SMP
+static int in_kgdb_console = 0;
+
+int
+in_kgdb(struct pt_regs *regs)
+{
+	unsigned flags;
+	int cpu = smp_processor_id();
+	in_kgdb_called = 1;
+	if (!spin_is_locked(&kgdb_spinlock)) {
+		if (in_kgdb_here_log[cpu] ||	/* we are holding this cpu */
+		    in_kgdb_console) {	/* or we are doing slow i/o */
+			return 1;
+		}
+		return 0;
+	}
+
+	/* As I see it the only reason not to let all cpus spin on
+	 * the same spin_lock is to allow selected ones to proceed.
+	 * This would be a good thing, so we leave it this way.
+	 * Maybe someday....  Done !
+
+	 * in_kgdb() is called from an NMI so we don't pretend
+	 * to have any resources, like printk() for example.
+	 */
+
+	kgdb_local_irq_save(flags);	/* only local here, to avoid hanging */
+	/*
+	 * log arival of this cpu
+	 * The NMI keeps on ticking.  Protect against recurring more
+	 * than once, and ignor the cpu that has the kgdb lock
+	 */
+	in_kgdb_entry_log[cpu]++;
+	in_kgdb_here_log[cpu] = regs;
+	if (cpu == spinlock_cpu || waiting_cpus[cpu].task)
+		goto exit_in_kgdb;
+
+	/*
+	 * For protection of the initilization of the spin locks by kgdb
+	 * it locks the kgdb spinlock before it gets the wait locks set
+	 * up.	We wait here for the wait lock to be taken.  If the
+	 * kgdb lock goes away first??	Well, it could be a slow exit
+	 * sequence where the wait lock is removed prior to the kgdb lock
+	 * so if kgdb gets unlocked, we just exit.
+	 */
+
+	while (spin_is_locked(&kgdb_spinlock) &&
+	       !spin_is_locked(waitlocks + cpu)) ;
+	if (!spin_is_locked(&kgdb_spinlock))
+		goto exit_in_kgdb;
+
+	waiting_cpus[cpu].task = current;
+	waiting_cpus[cpu].pid = (current->pid) ? : (PID_MAX + cpu);
+	waiting_cpus[cpu].regs = regs;
+
+	spin_unlock_wait(waitlocks + cpu);
+
+	/*
+	 * log departure of this cpu
+	 */
+	waiting_cpus[cpu].task = 0;
+	waiting_cpus[cpu].pid = 0;
+	waiting_cpus[cpu].regs = 0;
+	correct_hw_break();
+      exit_in_kgdb:
+	in_kgdb_here_log[cpu] = 0;
+	kgdb_local_irq_restore(flags);
+	return 1;
+	/*
+	   spin_unlock(continuelocks + smp_processor_id());
+	 */
+}
+
+void
+smp__in_kgdb(struct pt_regs regs)
+{
+	ack_APIC_irq();
+	in_kgdb(&regs);
+}
+#else
+int
+in_kgdb(struct pt_regs *regs)
+{
+	return (kgdb_spinlock);
+}
+#endif
+
+void
+printexceptioninfo(int exceptionNo, int errorcode, char *buffer)
+{
+	unsigned dr6;
+	int i;
+	switch (exceptionNo) {
+	case 1:		/* debug exception */
+		break;
+	case 3:		/* breakpoint */
+		sprintf(buffer, "Software breakpoint");
+		return;
+	default:
+		sprintf(buffer, "Details not available");
+		return;
+	}
+	asm volatile ("movl %%db6, %0\n":"=r" (dr6)
+		      :);
+	if (dr6 & 0x4000) {
+		sprintf(buffer, "Single step");
+		return;
+	}
+	for (i = 0; i < 4; ++i) {
+		if (dr6 & (1 << i)) {
+			sprintf(buffer, "Hardware breakpoint %d", i);
+			return;
+		}
+	}
+	sprintf(buffer, "Unknown trap");
+	return;
+}
+
+/*
+ * This function does all command procesing for interfacing to gdb.
+ *
+ * NOTE:  The INT nn instruction leaves the state of the interrupt
+ *	  enable flag UNCHANGED.  That means that when this routine
+ *	  is entered via a breakpoint (INT 3) instruction from code
+ *	  that has interrupts enabled, then interrupts will STILL BE
+ *	  enabled when this routine is entered.	 The first thing that
+ *	  we do here is disable interrupts so as to prevent recursive
+ *	  entries and bothersome serial interrupts while we are
+ *	  trying to run the serial port in polled mode.
+ *
+ * For kernel version 2.1.xx the kgdb_cli() actually gets a spin lock so
+ * it is always necessary to do a restore_flags before returning
+ * so as to let go of that lock.
+ */
+int
+kgdb_handle_exception(int exceptionVector,
+		      int signo, int err_code, struct pt_regs *linux_regs)
+{
+	struct task_struct *usethread = NULL;
+	struct task_struct *thread_list_start = 0, *thread = NULL;
+	int addr, length;
+	int breakno, breaktype;
+	char *ptr;
+	int newPC;
+	threadref thref;
+	int threadid;
+	int thread_min = PID_MAX + MAX_NO_CPUS;
+#ifdef old_thread_list
+	int maxthreads;
+#endif
+	int nothreads;
+	unsigned long flags;
+	int gdb_regs[NUMREGBYTES / 4];
+	int dr6;
+	IF_SMP(int entry_state = 0);	/* 0, ok, 1, no nmi, 2 sync failed */
+#define NO_NMI 1
+#define NO_SYNC 2
+#define	regs	(*linux_regs)
+#define NUMREGS NUMREGBYTES/4
+	/*
+	 * If the entry is not from the kernel then return to the Linux
+	 * trap handler and let it process the interrupt normally.
+	 */
+	if ((linux_regs->eflags & VM_MASK) || (3 & linux_regs->xcs)) {
+		printk("ignoring non-kernel exception\n");
+		print_regs(&regs);
+		return (0);
+	}
+	/*
+	 * If we're using eth mode, set the 'mode' in the netdevice.
+	 */
+
+	if (kgdboe)
+		netpoll_set_trap(1);
+
+	kgdb_local_irq_save(flags);
+
+	/* Get kgdb spinlock */
+
+	KGDB_SPIN_LOCK(&kgdb_spinlock);
+	rdtscll(kgdb_info.entry_tsc);
+	/*
+	 * We depend on this spinlock and the NMI watch dog to control the
+	 * other cpus.	They will arrive at "in_kgdb()" as a result of the
+	 * NMI and will wait there for the following spin locks to be
+	 * released.
+	 */
+#ifdef CONFIG_SMP
+
+#if 0
+	if (cpu_callout_map & ~MAX_CPU_MASK) {
+		printk("kgdb : too many cpus, possibly not mapped"
+		       " in contiguous space, change MAX_NO_CPUS"
+		       " in kgdb_stub and make new kernel.\n"
+		       " cpu_callout_map is %lx\n", cpu_callout_map);
+		goto exit_just_unlock;
+	}
+#endif
+	if (spinlock_count == 1) {
+		int time = 0, end_time, dum = 0;
+		int i;
+		int cpu_logged_in[MAX_NO_CPUS] = {[0 ... MAX_NO_CPUS - 1] = (0)
+		};
+		if (remote_debug) {
+			printk("kgdb : cpu %d entry, syncing others\n",
+			       smp_processor_id());
+		}
+		for (i = 0; i < MAX_NO_CPUS; i++) {
+			/*
+			 * Use trylock as we may already hold the lock if
+			 * we are holding the cpu.  Net result is all
+			 * locked.
+			 */
+			spin_trylock(&waitlocks[i]);
+		}
+		for (i = 0; i < MAX_NO_CPUS; i++)
+			cpu_logged_in[i] = 0;
+		/*
+		 * Wait for their arrival.  We know the watch dog is active if
+		 * in_kgdb() has ever been called, as it is always called on a
+		 * watchdog tick.
+		 */
+		rdtsc(dum, time);
+		end_time = time + 2;	/* Note: we use the High order bits! */
+		i = 1;
+		if (num_online_cpus() > 1) {
+			int me_in_kgdb = in_kgdb_entry_log[smp_processor_id()];
+			smp_send_nmi_allbutself();
+
+			while (i < num_online_cpus() && time != end_time) {
+				int j;
+				for (j = 0; j < MAX_NO_CPUS; j++) {
+					if (waiting_cpus[j].task &&
+					    waiting_cpus[j].task != NOCPU &&
+					    !cpu_logged_in[j]) {
+						i++;
+						cpu_logged_in[j] = 1;
+						if (remote_debug) {
+							printk
+							    ("kgdb : cpu %d arrived at kgdb\n",
+							     j);
+						}
+						break;
+					} else if (!waiting_cpus[j].task &&
+						   !cpu_online(j)) {
+						waiting_cpus[j].task = NOCPU;
+						cpu_logged_in[j] = 1;
+						waiting_cpus[j].hold = 1;
+						break;
+					}
+					if (!waiting_cpus[j].task &&
+					    in_kgdb_here_log[j]) {
+
+						int wait = 100000;
+						while (wait--) ;
+						if (!waiting_cpus[j].task &&
+						    in_kgdb_here_log[j]) {
+							printk
+							    ("kgdb : cpu %d stall"
+							     " in in_kgdb\n",
+							     j);
+							i++;
+							cpu_logged_in[j] = 1;
+							waiting_cpus[j].task =
+							    (struct task_struct
+							     *) 1;
+						}
+					}
+				}
+
+				if (in_kgdb_entry_log[smp_processor_id()] >
+				    (me_in_kgdb + 10)) {
+					break;
+				}
+
+				rdtsc(dum, time);
+			}
+			if (i < num_online_cpus()) {
+				printk
+				    ("kgdb : time out, proceeding without sync\n");
+#if 0
+				printk("kgdb : Waiting_cpus: 0 = %d, 1 = %d\n",
+				       waiting_cpus[0].task != 0,
+				       waiting_cpus[1].task != 0);
+				printk("kgdb : Cpu_logged in: 0 = %d, 1 = %d\n",
+				       cpu_logged_in[0], cpu_logged_in[1]);
+				printk
+				    ("kgdb : in_kgdb_here_log in: 0 = %d, 1 = %d\n",
+				     in_kgdb_here_log[0] != 0,
+				     in_kgdb_here_log[1] != 0);
+#endif
+				entry_state = NO_SYNC;
+			} else {
+#if 0
+				int ent =
+				    in_kgdb_entry_log[smp_processor_id()] -
+				    me_in_kgdb;
+				printk("kgdb : sync after %d entries\n", ent);
+#endif
+			}
+		} else {
+			if (remote_debug) {
+				printk
+				    ("kgdb : %d cpus, but watchdog not active\n"
+				     "proceeding without locking down other cpus\n",
+				     num_online_cpus());
+				entry_state = NO_NMI;
+			}
+		}
+	}
+#endif
+
+	if (remote_debug) {
+		unsigned long *lp = (unsigned long *) &linux_regs;
+
+		printk("handle_exception(exceptionVector=%d, "
+		       "signo=%d, err_code=%d, linux_regs=%p)\n",
+		       exceptionVector, signo, err_code, linux_regs);
+		if (debug_regs) {
+			print_regs(&regs);
+			printk("Stk: %8lx %8lx %8lx %8lx"
+			       "  %8lx %8lx %8lx %8lx\n",
+			       lp[0], lp[1], lp[2], lp[3],
+			       lp[4], lp[5], lp[6], lp[7]);
+			printk("     %8lx %8lx %8lx %8lx"
+			       "  %8lx %8lx %8lx %8lx\n",
+			       lp[8], lp[9], lp[10], lp[11],
+			       lp[12], lp[13], lp[14], lp[15]);
+			printk("     %8lx %8lx %8lx %8lx  "
+			       "%8lx %8lx %8lx %8lx\n",
+			       lp[16], lp[17], lp[18], lp[19],
+			       lp[20], lp[21], lp[22], lp[23]);
+			printk("     %8lx %8lx %8lx %8lx  "
+			       "%8lx %8lx %8lx %8lx\n",
+			       lp[24], lp[25], lp[26], lp[27],
+			       lp[28], lp[29], lp[30], lp[31]);
+		}
+	}
+
+	/* Disable hardware debugging while we are in kgdb */
+	/* Get the debug register status register */
+/*				       *INDENT-OFF*  */
+      __asm__("movl %0,%%db7"
+	      :	/* no output */
+	      :"r"(0));
+
+	asm volatile ("movl %%db6, %0\n"
+		      :"=r" (hw_breakpoint_status)
+		      :);
+
+/*				       *INDENT-ON*  */
+	switch (exceptionVector) {
+	case 0:		/* divide error */
+	case 1:		/* debug exception */
+	case 2:		/* NMI */
+	case 3:		/* breakpoint */
+	case 4:		/* overflow */
+	case 5:		/* bounds check */
+	case 6:		/* invalid opcode */
+	case 7:		/* device not available */
+	case 8:		/* double fault (errcode) */
+	case 10:		/* invalid TSS (errcode) */
+	case 12:		/* stack fault (errcode) */
+	case 16:		/* floating point error */
+	case 17:		/* alignment check (errcode) */
+	default:		/* any undocumented */
+		break;
+	case 11:		/* segment not present (errcode) */
+	case 13:		/* general protection (errcode) */
+	case 14:		/* page fault (special errcode) */
+	case 19:		/* cache flush denied */
+		if (mem_err_expected) {
+			/*
+			 * This fault occured because of the
+			 * get_char or set_char routines.  These
+			 * two routines use either eax of edx to
+			 * indirectly reference the location in
+			 * memory that they are working with.
+			 * For a page fault, when we return the
+			 * instruction will be retried, so we
+			 * have to make sure that these
+			 * registers point to valid memory.
+			 */
+			mem_err = 1;	/* set mem error flag */
+			mem_err_expected = 0;
+			mem_err_cnt++;	/* helps in debugging */
+			/* make valid address */
+			regs.eax = (long) &garbage_loc;
+			/* make valid address */
+			regs.edx = (long) &garbage_loc;
+			if (remote_debug)
+				printk("Return after memory error: "
+				       "mem_err_cnt=%d\n", mem_err_cnt);
+			if (debug_regs)
+				print_regs(&regs);
+			goto exit_kgdb;
+		}
+		break;
+	}
+	if (remote_debug)
+		printk("kgdb : entered kgdb on cpu %d\n", smp_processor_id());
+
+	gdb_i386vector = exceptionVector;
+	gdb_i386errcode = err_code;
+	kgdb_info.called_from = __builtin_return_address(0);
+#ifdef CONFIG_SMP
+	/*
+	 * OK, we can now communicate, lets tell gdb about the sync.
+	 * but only if we had a problem.
+	 */
+	switch (entry_state) {
+	case NO_NMI:
+		to_gdb("NMI not active, other cpus not stopped\n");
+		break;
+	case NO_SYNC:
+		to_gdb("Some cpus not stopped, see 'kgdb_info' for details\n");
+	default:;
+	}
+
+#endif
+/*
+ * Set up the gdb function call area.
+ */
+	trap_cpu = smp_processor_id();
+	OLD_esp = NEW_esp = (int) (&linux_regs->esp);
+
+      IF_SMP(once_again:)
+	    /* reply to host that an exception has occurred */
+	    remcomOutBuffer[0] = 'S';
+	remcomOutBuffer[1] = hexchars[signo >> 4];
+	remcomOutBuffer[2] = hexchars[signo % 16];
+	remcomOutBuffer[3] = 0;
+
+	putpacket(remcomOutBuffer);
+
+	while (1 == 1) {
+		error = 0;
+		remcomOutBuffer[0] = 0;
+		getpacket(remcomInBuffer);
+		switch (remcomInBuffer[0]) {
+		case '?':
+			remcomOutBuffer[0] = 'S';
+			remcomOutBuffer[1] = hexchars[signo >> 4];
+			remcomOutBuffer[2] = hexchars[signo % 16];
+			remcomOutBuffer[3] = 0;
+			break;
+		case 'd':
+			remote_debug = !(remote_debug);	/* toggle debug flag */
+			printk("Remote debug %s\n",
+			       remote_debug ? "on" : "off");
+			break;
+		case 'g':	/* return the value of the CPU registers */
+			get_gdb_regs(usethread, &regs, gdb_regs);
+			mem2hex((char *) gdb_regs,
+				remcomOutBuffer, NUMREGBYTES, 0);
+			break;
+		case 'G':	/* set the value of the CPU registers - return OK */
+			hex2mem(&remcomInBuffer[1],
+				(char *) gdb_regs, NUMREGBYTES, 0);
+			if (!usethread || usethread == current) {
+				gdb_regs_to_regs(gdb_regs, &regs);
+				strcpy(remcomOutBuffer, "OK");
+			} else {
+				strcpy(remcomOutBuffer, "E00");
+			}
+			break;
+
+		case 'P':{	/* set the value of a single CPU register -
+				   return OK */
+				/*
+				 * For some reason, gdb wants to talk about psudo
+				 * registers (greater than 15).	 These may have
+				 * meaning for ptrace, but for us it is safe to
+				 * ignor them.	We do this by dumping them into
+				 * _GS which we also ignor, but do have memory for.
+				 */
+				int regno;
+
+				ptr = &remcomInBuffer[1];
+				regs_to_gdb_regs(gdb_regs, &regs);
+				if ((!usethread || usethread == current) &&
+				    hexToInt(&ptr, &regno) &&
+				    *ptr++ == '=' && (regno >= 0)) {
+					regno =
+					    (regno >= NUMREGS ? _GS : regno);
+					hex2mem(ptr, (char *) &gdb_regs[regno],
+						4, 0);
+					gdb_regs_to_regs(gdb_regs, &regs);
+					strcpy(remcomOutBuffer, "OK");
+					break;
+				}
+				strcpy(remcomOutBuffer, "E01");
+				break;
+			}
+
+			/* mAA..AA,LLLL	 Read LLLL bytes at address AA..AA */
+		case 'm':
+			/* TRY TO READ %x,%x.  IF SUCCEED, SET PTR = 0 */
+			ptr = &remcomInBuffer[1];
+			if (hexToInt(&ptr, &addr) &&
+			    (*(ptr++) == ',') && (hexToInt(&ptr, &length))) {
+				ptr = 0;
+				/*
+				 * hex doubles the byte count
+				 */
+				if (length > (BUFMAX / 2))
+					length = BUFMAX / 2;
+				mem2hex((char *) addr,
+					remcomOutBuffer, length, 1);
+				if (mem_err) {
+					strcpy(remcomOutBuffer, "E03");
+					debug_error("memory fault\n", NULL);
+				}
+			}
+
+			if (ptr) {
+				strcpy(remcomOutBuffer, "E01");
+				debug_error
+				    ("malformed read memory command: %s\n",
+				     remcomInBuffer);
+			}
+			break;
+
+			/* MAA..AA,LLLL:
+			   Write LLLL bytes at address AA.AA return OK */
+		case 'M':
+			/* TRY TO READ '%x,%x:'.  IF SUCCEED, SET PTR = 0 */
+			ptr = &remcomInBuffer[1];
+			if (hexToInt(&ptr, &addr) &&
+			    (*(ptr++) == ',') &&
+			    (hexToInt(&ptr, &length)) && (*(ptr++) == ':')) {
+				hex2mem(ptr, (char *) addr, length, 1);
+
+				if (mem_err) {
+					strcpy(remcomOutBuffer, "E03");
+					debug_error("memory fault\n", NULL);
+				} else {
+					strcpy(remcomOutBuffer, "OK");
+				}
+
+				ptr = 0;
+			}
+			if (ptr) {
+				strcpy(remcomOutBuffer, "E02");
+				debug_error
+				    ("malformed write memory command: %s\n",
+				     remcomInBuffer);
+			}
+			break;
+		case 'S':
+			remcomInBuffer[0] = 's';
+		case 'C':
+			/* Csig;AA..AA where ;AA..AA is optional
+			 * continue with signal
+			 * Since signals are meaning less to us, delete that
+			 * part and then fall into the 'c' code.
+			 */
+			ptr = &remcomInBuffer[1];
+			length = 2;
+			while (*ptr && *ptr != ';') {
+				length++;
+				ptr++;
+			}
+			if (*ptr) {
+				do {
+					ptr++;
+					*(ptr - length++) = *ptr;
+				} while (*ptr);
+			} else {
+				remcomInBuffer[1] = 0;
+			}
+
+			/* cAA..AA  Continue at address AA..AA(optional) */
+			/* sAA..AA  Step one instruction from AA..AA(optional) */
+			/* D	    detach, reply OK and then continue */
+		case 'c':
+		case 's':
+		case 'D':
+
+			/* try to read optional parameter,
+			   pc unchanged if no parm */
+			ptr = &remcomInBuffer[1];
+			if (hexToInt(&ptr, &addr)) {
+				if (remote_debug)
+					printk("Changing EIP to 0x%x\n", addr);
+
+				regs.eip = addr;
+			}
+
+			newPC = regs.eip;
+
+			/* clear the trace bit */
+			regs.eflags &= 0xfffffeff;
+
+			/* set the trace bit if we're stepping */
+			if (remcomInBuffer[0] == 's')
+				regs.eflags |= 0x100;
+
+			/* detach is a friendly version of continue. Note that
+			   debugging is still enabled (e.g hit control C)
+			 */
+			if (remcomInBuffer[0] == 'D') {
+				strcpy(remcomOutBuffer, "OK");
+				putpacket(remcomOutBuffer);
+			}
+
+			if (remote_debug) {
+				printk("Resuming execution\n");
+				print_regs(&regs);
+			}
+			asm volatile ("movl %%db6, %0\n":"=r" (dr6)
+				      :);
+			if (!(dr6 & 0x4000)) {
+				for (breakno = 0; breakno < 4; ++breakno) {
+					if (dr6 & (1 << breakno) &&
+					    (breakinfo[breakno].type == 0)) {
+						/* Set restore flag */
+						regs.eflags |= 0x10000;
+						break;
+					}
+				}
+			}
+
+			if (kgdboe)
+				netpoll_set_trap(0);
+
+			correct_hw_break();
+			asm volatile ("movl %0, %%db6\n"::"r" (0));
+			goto exit_kgdb;
+
+			/* kill the program */
+		case 'k':	/* do nothing */
+			break;
+
+			/* query */
+		case 'q':
+			nothreads = 0;
+			switch (remcomInBuffer[1]) {
+			case 'f':
+				threadid = 1;
+				thread_list = 2;
+				thread_list_start = (usethread ? : current);
+			case 's':
+				if (!cmp_str(&remcomInBuffer[2],
+					     "ThreadInfo", 10))
+					break;
+
+				remcomOutBuffer[nothreads++] = 'm';
+				for (; threadid < PID_MAX + MAX_NO_CPUS;
+				     threadid++) {
+					thread = getthread(threadid);
+					if (thread) {
+						nothreads += int_to_hex_v(
+							&remcomOutBuffer[
+								nothreads],
+							threadid);
+						if (thread_min > threadid)
+							thread_min = threadid;
+						remcomOutBuffer[
+							nothreads] = ',';
+						nothreads++;
+						if (nothreads > BUFMAX - 10)
+							break;
+					}
+				}
+				if (remcomOutBuffer[nothreads - 1] == 'm') {
+					remcomOutBuffer[nothreads - 1] = 'l';
+				} else {
+					nothreads--;
+				}
+				remcomOutBuffer[nothreads] = 0;
+				break;
+
+#ifdef old_thread_list /* Old thread info request */
+			case 'L':
+				/* List threads */
+				thread_list = 2;
+				thread_list_start = (usethread ? : current);
+				unpack_byte(remcomInBuffer + 3, &maxthreads);
+				unpack_threadid(remcomInBuffer + 5, &thref);
+				do {
+					int buf_thread_limit =
+					    (BUFMAX - 22) / BUF_THREAD_ID_SIZE;
+					if (maxthreads > buf_thread_limit) {
+						maxthreads = buf_thread_limit;
+					}
+				} while (0);
+				remcomOutBuffer[0] = 'q';
+				remcomOutBuffer[1] = 'M';
+				remcomOutBuffer[4] = '0';
+				pack_threadid(remcomOutBuffer + 5, &thref);
+
+				threadid = threadref_to_int(&thref);
+				for (nothreads = 0;
+				     nothreads < maxthreads &&
+				     threadid < PID_MAX + MAX_NO_CPUS;
+				     threadid++) {
+					thread = getthread(threadid);
+					if (thread) {
+						int_to_threadref(&thref,
+								 threadid);
+						pack_threadid(remcomOutBuffer +
+							      21 +
+							      nothreads * 16,
+							      &thref);
+						nothreads++;
+						if (thread_min > threadid)
+							thread_min = threadid;
+					}
+				}
+
+				if (threadid == PID_MAX + MAX_NO_CPUS) {
+					remcomOutBuffer[4] = '1';
+				}
+				pack_hex_byte(remcomOutBuffer + 2, nothreads);
+				remcomOutBuffer[21 + nothreads * 16] = '\0';
+				break;
+#endif
+			case 'C':
+				/* Current thread id */
+				remcomOutBuffer[0] = 'Q';
+				remcomOutBuffer[1] = 'C';
+				threadid = current->pid;
+				if (!threadid) {
+					/*
+					 * idle thread
+					 */
+					for (threadid = PID_MAX;
+					     threadid < PID_MAX + MAX_NO_CPUS;
+					     threadid++) {
+						if (current ==
+						    idle_task(threadid -
+							      PID_MAX))
+							break;
+					}
+				}
+				int_to_threadref(&thref, threadid);
+				pack_threadid(remcomOutBuffer + 2, &thref);
+				remcomOutBuffer[18] = '\0';
+				break;
+
+			case 'E':
+				/* Print exception info */
+				printexceptioninfo(exceptionVector,
+						   err_code, remcomOutBuffer);
+				break;
+			case 'T':{
+				char * nptr;
+				/* Thread extra info */
+				if (!cmp_str(&remcomInBuffer[2],
+					    "hreadExtraInfo,", 15)) {
+					break;
+				}
+				ptr = &remcomInBuffer[17];
+				hexToInt(&ptr, &threadid);
+				thread = getthread(threadid);
+				nptr = &thread->comm[0];
+				length = 0;
+				ptr = &remcomOutBuffer[0];
+				do {
+					length++;
+					ptr = pack_hex_byte(ptr, *nptr++);
+				 } while (*nptr && length < 16);
+				/*
+				 * would like that 16 to be the size of
+				 * task_struct.comm but don't know the
+				 * syntax..
+				 */
+				*ptr = 0;
+			}
+			}
+			break;
+
+			/* task related */
+		case 'H':
+			switch (remcomInBuffer[1]) {
+			case 'g':
+				ptr = &remcomInBuffer[2];
+				hexToInt(&ptr, &threadid);
+				thread = getthread(threadid);
+				if (!thread) {
+					remcomOutBuffer[0] = 'E';
+					remcomOutBuffer[1] = '\0';
+					break;
+				}
+				/*
+				 * Just in case I forget what this is all about,
+				 * the "thread info" command to gdb causes it
+				 * to ask for a thread list.  It then switches
+				 * to each thread and asks for the registers.
+				 * For this (and only this) usage, we want to
+				 * fudge the registers of tasks not on the run
+				 * list (i.e. waiting) to show the routine that
+				 * called schedule. Also, gdb, is a minimalist
+				 * in that if the current thread is the last
+				 * it will not re-read the info when done.
+				 * This means that in this case we must show
+				 * the real registers. So here is how we do it:
+				 * Each entry we keep track of the min
+				 * thread in the list (the last that gdb will)
+				 * get info for.  We also keep track of the
+				 * starting thread.
+				 * "thread_list" is cleared when switching back
+				 * to the min thread if it is was current, or
+				 * if it was not current, thread_list is set
+				 * to 1.  When the switch to current comes,
+				 * if thread_list is 1, clear it, else do
+				 * nothing.
+				 */
+				usethread = thread;
+				if ((thread_list == 1) &&
+				    (thread == thread_list_start)) {
+					thread_list = 0;
+				}
+				if (thread_list && (threadid == thread_min)) {
+					if (thread == thread_list_start) {
+						thread_list = 0;
+					} else {
+						thread_list = 1;
+					}
+				}
+				/* follow through */
+			case 'c':
+				remcomOutBuffer[0] = 'O';
+				remcomOutBuffer[1] = 'K';
+				remcomOutBuffer[2] = '\0';
+				break;
+			}
+			break;
+
+			/* Query thread status */
+		case 'T':
+			ptr = &remcomInBuffer[1];
+			hexToInt(&ptr, &threadid);
+			thread = getthread(threadid);
+			if (thread) {
+				remcomOutBuffer[0] = 'O';
+				remcomOutBuffer[1] = 'K';
+				remcomOutBuffer[2] = '\0';
+				if (thread_min > threadid)
+					thread_min = threadid;
+			} else {
+				remcomOutBuffer[0] = 'E';
+				remcomOutBuffer[1] = '\0';
+			}
+			break;
+
+		case 'Y': /* set up a hardware breakpoint */
+			ptr = &remcomInBuffer[1];
+			hexToInt(&ptr, &breakno);
+			ptr++;
+			hexToInt(&ptr, &breaktype);
+			ptr++;
+			hexToInt(&ptr, &length);
+			ptr++;
+			hexToInt(&ptr, &addr);
+			if (set_hw_break(breakno & 0x3,
+					 breaktype & 0x3,
+					 length & 0x3, addr) == 0) {
+				strcpy(remcomOutBuffer, "OK");
+			} else {
+				strcpy(remcomOutBuffer, "ERROR");
+			}
+			break;
+
+			/* Remove hardware breakpoint */
+		case 'y':
+			ptr = &remcomInBuffer[1];
+			hexToInt(&ptr, &breakno);
+			if (remove_hw_break(breakno & 0x3) == 0) {
+				strcpy(remcomOutBuffer, "OK");
+			} else {
+				strcpy(remcomOutBuffer, "ERROR");
+			}
+			break;
+
+		case 'r':	/* reboot */
+			strcpy(remcomOutBuffer, "OK");
+			putpacket(remcomOutBuffer);
+			/*to_gdb("Rebooting\n"); */
+			/* triplefault	 no return from here */
+			{
+				static long no_idt[2];
+				__asm__ __volatile__("lidt %0"::"m"(no_idt[0]));
+				BREAKPOINT;
+			}
+
+		}		/* switch */
+
+		/* reply to the request */
+		putpacket(remcomOutBuffer);
+	}			/* while(1==1) */
+	/*
+	 *  reached by goto only.
+	 */
+      exit_kgdb:
+	/*
+	 * Here is where we set up to trap a gdb function call.	 NEW_esp
+	 * will be changed if we are trying to do this.	 We handle both
+	 * adding and subtracting, thus allowing gdb to put grung on
+	 * the stack which it removes later.
+	 */
+	if (NEW_esp != OLD_esp) {
+		int *ptr = END_OF_LOOKASIDE;
+		if (NEW_esp < OLD_esp)
+			ptr -= (OLD_esp - NEW_esp) / sizeof (int);
+		*--ptr = linux_regs->eflags;
+		*--ptr = linux_regs->xcs;
+		*--ptr = linux_regs->eip;
+		*--ptr = linux_regs->ecx;
+		*--ptr = linux_regs->ebx;
+		*--ptr = linux_regs->eax;
+		linux_regs->ecx = NEW_esp - (sizeof (int) * 6);
+		linux_regs->ebx = (unsigned int) END_OF_LOOKASIDE;
+		if (NEW_esp < OLD_esp) {
+			linux_regs->eip = (unsigned int) fn_call_stub;
+		} else {
+			linux_regs->eip = (unsigned int) fn_rtn_stub;
+			linux_regs->eax = NEW_esp;
+		}
+		linux_regs->eflags &= ~(IF_BIT | TF_BIT);
+	}
+#ifdef CONFIG_SMP
+	/*
+	 * Release gdb wait locks
+	 * Sanity check time.  Must have at least one cpu to run.  Also single
+	 * step must not be done if the current cpu is on hold.
+	 */
+	if (spinlock_count == 1) {
+		int ss_hold = (regs.eflags & 0x100) && kgdb_info.hold_on_sstep;
+		int cpu_avail = 0;
+		int i;
+
+		for (i = 0; i < MAX_NO_CPUS; i++) {
+			if (!cpu_online(i))
+				break;
+			if (!hold_cpu(i)) {
+				cpu_avail = 1;
+			}
+		}
+		/*
+		 * Early in the bring up there will be NO cpus on line...
+		 */
+		if (!cpu_avail && !cpus_empty(cpu_online_map)) {
+			to_gdb("No cpus unblocked, see 'kgdb_info.hold_cpu'\n");
+			goto once_again;
+		}
+		if (hold_cpu(smp_processor_id()) && (regs.eflags & 0x100)) {
+			to_gdb
+			    ("Current cpu must be unblocked to single step\n");
+			goto once_again;
+		}
+		if (!(ss_hold)) {
+			int i;
+			for (i = 0; i < MAX_NO_CPUS; i++) {
+				if (!hold_cpu(i)) {
+					spin_unlock(&waitlocks[i]);
+				}
+			}
+		} else {
+			spin_unlock(&waitlocks[smp_processor_id()]);
+		}
+		/* Release kgdb spinlock */
+		KGDB_SPIN_UNLOCK(&kgdb_spinlock);
+		/*
+		 * If this cpu is on hold, this is where we
+		 * do it.  Note, the NMI will pull us out of here,
+		 * but will return as the above lock is not held.
+		 * We will stay here till another cpu releases the lock for us.
+		 */
+		spin_unlock_wait(waitlocks + smp_processor_id());
+		kgdb_local_irq_restore(flags);
+		return (0);
+	}
+#if 0
+exit_just_unlock:
+#endif
+#endif
+	/* Release kgdb spinlock */
+	KGDB_SPIN_UNLOCK(&kgdb_spinlock);
+	kgdb_local_irq_restore(flags);
+	return (0);
+}
+
+/* this function is used to set up exception handlers for tracing and
+ * breakpoints.
+ * This function is not needed as the above line does all that is needed.
+ * We leave it for backward compatitability...
+ */
+void
+set_debug_traps(void)
+{
+	/*
+	 * linux_debug_hook is defined in traps.c.  We store a pointer
+	 * to our own exception handler into it.
+
+	 * But really folks, every hear of labeled common, an old Fortran
+	 * concept.  Lots of folks can reference it and it is define if
+	 * anyone does.	 Only one can initialize it at link time.  We do
+	 * this with the hook.	See the statement above.  No need for any
+	 * executable code and it is ready as soon as the kernel is
+	 * loaded.  Very desirable in kernel debugging.
+
+	 linux_debug_hook = handle_exception ;
+	 */
+
+	/* In case GDB is started before us, ack any packets (presumably
+	   "$?#xx") sitting there.
+	   putDebugChar ('+');
+
+	   initialized = 1;
+	 */
+}
+
+/* This function will generate a breakpoint exception.	It is used at the
+   beginning of a program to sync up with a debugger and can be used
+   otherwise as a quick means to stop program execution and "break" into
+   the debugger. */
+/* But really, just use the BREAKPOINT macro.  We will handle the int stuff
+ */
+
+#ifdef later
+/*
+ * possibly we should not go thru the traps.c code at all?  Someday.
+ */
+void
+do_kgdb_int3(struct pt_regs *regs, long error_code)
+{
+	kgdb_handle_exception(3, 5, error_code, regs);
+	return;
+}
+#endif
+#undef regs
+#ifdef CONFIG_TRAP_BAD_SYSCALL_EXITS
+asmlinkage void
+bad_sys_call_exit(int stuff)
+{
+	struct pt_regs *regs = (struct pt_regs *) &stuff;
+	printk("Sys call %d return with %x preempt_count\n",
+	       (int) regs->orig_eax, preempt_count());
+}
+#endif
+#ifdef CONFIG_STACK_OVERFLOW_TEST
+#include <asm/kgdb.h>
+asmlinkage void
+stack_overflow(void)
+{
+#ifdef BREAKPOINT
+	BREAKPOINT;
+#else
+	printk("Kernel stack overflow, looping forever\n");
+#endif
+	while (1) {
+	}
+}
+#endif
+
+#if defined(CONFIG_SMP) || defined(CONFIG_KGDB_CONSOLE)
+char gdbconbuf[BUFMAX];
+
+static void
+kgdb_gdb_message(const char *s, unsigned count)
+{
+	int i;
+	int wcount;
+	char *bufptr;
+	/*
+	 * This takes care of NMI while spining out chars to gdb
+	 */
+	IF_SMP(in_kgdb_console = 1);
+	gdbconbuf[0] = 'O';
+	bufptr = gdbconbuf + 1;
+	while (count > 0) {
+		if ((count << 1) > (BUFMAX - 2)) {
+			wcount = (BUFMAX - 2) >> 1;
+		} else {
+			wcount = count;
+		}
+		count -= wcount;
+		for (i = 0; i < wcount; i++) {
+			bufptr = pack_hex_byte(bufptr, s[i]);
+		}
+		*bufptr = '\0';
+		s += wcount;
+
+		putpacket(gdbconbuf);
+
+	}
+	IF_SMP(in_kgdb_console = 0);
+}
+#endif
+#ifdef CONFIG_SMP
+static void
+to_gdb(const char *s)
+{
+	int count = 0;
+	while (s[count] && (count++ < BUFMAX)) ;
+	kgdb_gdb_message(s, count);
+}
+#endif
+#ifdef CONFIG_KGDB_CONSOLE
+#include <linux/console.h>
+#include <linux/init.h>
+#include <linux/fs.h>
+#include <asm/uaccess.h>
+#include <asm/semaphore.h>
+
+void
+kgdb_console_write(struct console *co, const char *s, unsigned count)
+{
+
+	if (gdb_i386vector == -1) {
+		/*
+		 * We have not yet talked to gdb.  What to do...
+		 * lets break, on continue we can do the write.
+		 * But first tell him whats up. Uh, well no can do,
+		 * as this IS the console.  Oh well...
+		 * We do need to wait or the messages will be lost.
+		 * Other option would be to tell the above code to
+		 * ignore this breakpoint and do an auto return,
+		 * but that might confuse gdb.	Also this happens
+		 * early enough in boot up that we don't have the traps
+		 * set up yet, so...
+		 */
+		breakpoint();
+	}
+	kgdb_gdb_message(s, count);
+}
+
+/*
+ * ------------------------------------------------------------
+ * Serial KGDB driver
+ * ------------------------------------------------------------
+ */
+
+static struct console kgdbcons = {
+	name:"kgdb",
+	write:kgdb_console_write,
+#ifdef CONFIG_KGDB_USER_CONSOLE
+	device:kgdb_console_device,
+#endif
+	flags:CON_PRINTBUFFER | CON_ENABLED,
+	index:-1,
+};
+
+/*
+ * The trick here is that this file gets linked before printk.o
+ * That means we get to peer at the console info in the command
+ * line before it does.	 If we are up, we register, otherwise,
+ * do nothing.	By returning 0, we allow printk to look also.
+ */
+static int kgdb_console_enabled;
+
+int __init
+kgdb_console_init(char *str)
+{
+	if ((strncmp(str, "kgdb", 4) == 0) || (strncmp(str, "gdb", 3) == 0)) {
+		register_console(&kgdbcons);
+		kgdb_console_enabled = 1;
+	}
+	return 0;		/* let others look at the string */
+}
+
+__setup("console=", kgdb_console_init);
+
+#ifdef CONFIG_KGDB_USER_CONSOLE
+static kdev_t kgdb_console_device(struct console *c);
+/* This stuff sort of works, but it knocks out telnet devices
+ * we are leaving it here in case we (or you) find time to figure it out
+ * better..
+ */
+
+/*
+ * We need a real char device as well for when the console is opened for user
+ * space activities.
+ */
+
+static int
+kgdb_consdev_open(struct inode *inode, struct file *file)
+{
+	return 0;
+}
+
+static ssize_t
+kgdb_consdev_write(struct file *file, const char *buf,
+		   size_t count, loff_t * ppos)
+{
+	int size, ret = 0;
+	static char kbuf[128];
+	static DECLARE_MUTEX(sem);
+
+	/* We are not reentrant... */
+	if (down_interruptible(&sem))
+		return -ERESTARTSYS;
+
+	while (count > 0) {
+		/* need to copy the data from user space */
+		size = count;
+		if (size > sizeof (kbuf))
+			size = sizeof (kbuf);
+		if (copy_from_user(kbuf, buf, size)) {
+			ret = -EFAULT;
+			break;;
+		}
+		kgdb_console_write(&kgdbcons, kbuf, size);
+		count -= size;
+		ret += size;
+		buf += size;
+	}
+
+	up(&sem);
+
+	return ret;
+}
+
+struct file_operations kgdb_consdev_fops = {
+	open:kgdb_consdev_open,
+	write:kgdb_consdev_write
+};
+static kdev_t
+kgdb_console_device(struct console *c)
+{
+	return MKDEV(TTYAUX_MAJOR, 1);
+}
+
+/*
+ * This routine gets called from the serial stub in the i386/lib
+ * This is so it is done late in bring up (just before the console open).
+ */
+void
+kgdb_console_finit(void)
+{
+	if (kgdb_console_enabled) {
+		char *cptr = cdevname(MKDEV(TTYAUX_MAJOR, 1));
+		char *cp = cptr;
+		while (*cptr && *cptr != '(')
+			cptr++;
+		*cptr = 0;
+		unregister_chrdev(TTYAUX_MAJOR, cp);
+		register_chrdev(TTYAUX_MAJOR, "kgdb", &kgdb_consdev_fops);
+	}
+}
+#endif
+#endif
+#ifdef CONFIG_KGDB_TS
+#include <asm/msr.h>		/* time stamp code */
+#include <asm/hardirq.h>	/* in_interrupt */
+#ifdef CONFIG_KGDB_TS_64
+#define DATA_POINTS 64
+#endif
+#ifdef CONFIG_KGDB_TS_128
+#define DATA_POINTS 128
+#endif
+#ifdef CONFIG_KGDB_TS_256
+#define DATA_POINTS 256
+#endif
+#ifdef CONFIG_KGDB_TS_512
+#define DATA_POINTS 512
+#endif
+#ifdef CONFIG_KGDB_TS_1024
+#define DATA_POINTS 1024
+#endif
+#ifndef DATA_POINTS
+#define DATA_POINTS 128		/* must be a power of two */
+#endif
+#define INDEX_MASK (DATA_POINTS - 1)
+#if (INDEX_MASK & DATA_POINTS)
+#error "CONFIG_KGDB_TS_COUNT must be a power of 2"
+#endif
+struct kgdb_and_then_struct {
+#ifdef CONFIG_SMP
+	int on_cpu;
+#endif
+	struct task_struct *task;
+	long long at_time;
+	int from_ln;
+	char *in_src;
+	void *from;
+	int *with_shpf;
+	int data0;
+	int data1;
+};
+struct kgdb_and_then_struct2 {
+#ifdef CONFIG_SMP
+	int on_cpu;
+#endif
+	struct task_struct *task;
+	long long at_time;
+	int from_ln;
+	char *in_src;
+	void *from;
+	int *with_shpf;
+	struct task_struct *t1;
+	struct task_struct *t2;
+};
+struct kgdb_and_then_struct kgdb_data[DATA_POINTS];
+
+struct kgdb_and_then_struct *kgdb_and_then = &kgdb_data[0];
+int kgdb_and_then_count;
+
+void
+kgdb_tstamp(int line, char *source, int data0, int data1)
+{
+	static spinlock_t ts_spin = SPIN_LOCK_UNLOCKED;
+	int flags;
+	kgdb_local_irq_save(flags);
+	spin_lock(&ts_spin);
+	rdtscll(kgdb_and_then->at_time);
+#ifdef CONFIG_SMP
+	kgdb_and_then->on_cpu = smp_processor_id();
+#endif
+	kgdb_and_then->task = current;
+	kgdb_and_then->from_ln = line;
+	kgdb_and_then->in_src = source;
+	kgdb_and_then->from = __builtin_return_address(0);
+	kgdb_and_then->with_shpf = (int *) (((flags & IF_BIT) >> 9) |
+					    (preempt_count() << 8));
+	kgdb_and_then->data0 = data0;
+	kgdb_and_then->data1 = data1;
+	kgdb_and_then = &kgdb_data[++kgdb_and_then_count & INDEX_MASK];
+	spin_unlock(&ts_spin);
+	kgdb_local_irq_restore(flags);
+#ifdef CONFIG_PREEMPT
+
+#endif
+	return;
+}
+#endif
+typedef int gdb_debug_hook(int exceptionVector,
+			   int signo, int err_code, struct pt_regs *linux_regs);
+gdb_debug_hook *linux_debug_hook = &kgdb_handle_exception;	/* histerical reasons... */
+
+static int kgdb_need_breakpoint[NR_CPUS];
+
+void kgdb_schedule_breakpoint(void)
+{
+	kgdb_need_breakpoint[smp_processor_id()] = 1;
+}
+
+void kgdb_process_breakpoint(void)
+{
+	/*
+	 * Handle a breakpoint queued from inside network driver code
+         * to avoid reentrancy issues
+	 */
+	if (kgdb_need_breakpoint[smp_processor_id()]) {
+		kgdb_need_breakpoint[smp_processor_id()] = 0;
+		BREAKPOINT;
+	}
+}
+
--- diff/arch/i386/kernel/timers/timer_pm.c	1970-01-01 01:00:00.000000000 +0100
+++ source/arch/i386/kernel/timers/timer_pm.c	2004-02-23 13:56:37.000000000 +0000
@@ -0,0 +1,217 @@
+/*
+ * (C) Dominik Brodowski <linux@brodo.de> 2003
+ *
+ * Driver to use the Power Management Timer (PMTMR) available in some
+ * southbridges as primary timing source for the Linux kernel.
+ *
+ * Based on parts of linux/drivers/acpi/hardware/hwtimer.c, timer_pit.c,
+ * timer_hpet.c, and on Arjan van de Ven's implementation for 2.4.
+ *
+ * This file is licensed under the GPL v2.
+ */
+
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/init.h>
+#include <asm/types.h>
+#include <asm/timer.h>
+#include <asm/smp.h>
+#include <asm/io.h>
+#include <asm/arch_hooks.h>
+
+
+/* The I/O port the PMTMR resides at.
+ * The location is detected during setup_arch(),
+ * in arch/i386/acpi/boot.c */
+u32 pmtmr_ioport = 0;
+
+
+/* value of the Power timer at last timer interrupt */
+static u32 offset_tick;
+static u32 offset_delay;
+
+static unsigned long long monotonic_base;
+static seqlock_t monotonic_lock = SEQLOCK_UNLOCKED;
+
+#define ACPI_PM_MASK 0xFFFFFF /* limit it to 24 bits */
+
+/*helper function to safely read acpi pm timesource*/
+static inline u32 read_pmtmr(void)
+{
+	u32 v1=0,v2=0,v3=0;
+	/* It has been reported that because of various broken
+	 * chipsets (ICH4, PIIX4 and PIIX4E) where the ACPI PM time
+	 * source is not latched, so you must read it multiple
+	 * times to insure a safe value is read.
+	 */
+	do {
+		v1 = inl(pmtmr_ioport);
+		v2 = inl(pmtmr_ioport);
+		v3 = inl(pmtmr_ioport);
+	} while ((v1 > v2 && v1 < v3) || (v2 > v3 && v2 < v1)
+			|| (v3 > v1 && v3 < v2));
+
+	/* mask the output to 24 bits */
+	return v2 & ACPI_PM_MASK;
+}
+
+static int init_pmtmr(char* override)
+{
+	u32 value1, value2;
+	unsigned int i;
+
+ 	if (override[0] && strncmp(override,"pmtmr",5))
+		return -ENODEV;
+
+	if (!pmtmr_ioport)
+		return -ENODEV;
+
+	/* we use the TSC for delay_pmtmr, so make sure it exists */
+	if (!cpu_has_tsc)
+		return -ENODEV;
+
+	/* "verify" this timing source */
+	value1 = read_pmtmr();
+	for (i = 0; i < 10000; i++) {
+		value2 = read_pmtmr();
+		if (value2 == value1)
+			continue;
+		if (value2 > value1)
+			goto pm_good;
+		if ((value2 < value1) && ((value2) < 0xFFF))
+			goto pm_good;
+		printk(KERN_INFO "PM-Timer had inconsistent results: 0x%#x, 0x%#x - aborting.\n", value1, value2);
+		return -EINVAL;
+	}
+	printk(KERN_INFO "PM-Timer had no reasonable result: 0x%#x - aborting.\n", value1);
+	return -ENODEV;
+
+pm_good:
+	init_cpu_khz();
+	return 0;
+}
+
+static inline u32 cyc2us(u32 cycles)
+{
+	/* The Power Management Timer ticks at 3.579545 ticks per microsecond.
+	 * 1 / PM_TIMER_FREQUENCY == 0.27936511 =~ 286/1024 [error: 0.024%]
+	 *
+	 * Even with HZ = 100, delta is at maximum 35796 ticks, so it can
+	 * easily be multiplied with 286 (=0x11E) without having to fear
+	 * u32 overflows.
+	 */
+	cycles *= 286;
+	return (cycles >> 10);
+}
+
+/*
+ * this gets called during each timer interrupt
+ *   - Called while holding the writer xtime_lock
+ */
+static void mark_offset_pmtmr(void)
+{
+	u32 lost, delta, last_offset;
+	static int first_run = 1;
+	last_offset = offset_tick;
+
+	write_seqlock(&monotonic_lock);
+
+	offset_tick = read_pmtmr();
+
+	/* calculate tick interval */
+	delta = (offset_tick - last_offset) & ACPI_PM_MASK;
+
+	/* convert to usecs */
+	delta = cyc2us(delta);
+
+	/* update the monotonic base value */
+	monotonic_base += delta * NSEC_PER_USEC;
+	write_sequnlock(&monotonic_lock);
+
+	/* convert to ticks */
+	delta += offset_delay;
+	lost = delta / (USEC_PER_SEC / HZ);
+	offset_delay = delta % (USEC_PER_SEC / HZ);
+
+
+	/* compensate for lost ticks */
+	if (lost >= 2)
+		jiffies_64 += lost - 1;
+
+	/* don't calculate delay for first run,
+	   or if we've got less then a tick */
+	if (first_run || (lost < 1)) {
+		first_run = 0;
+		offset_delay = 0;
+	}
+}
+
+
+static unsigned long long monotonic_clock_pmtmr(void)
+{
+	u32 last_offset, this_offset;
+	unsigned long long base, ret;
+	unsigned seq;
+
+
+	/* atomically read monotonic base & last_offset */
+	do {
+		seq = read_seqbegin(&monotonic_lock);
+		last_offset = offset_tick;
+		base = monotonic_base;
+	} while (read_seqretry(&monotonic_lock, seq));
+
+	/* Read the pmtmr */
+	this_offset =  read_pmtmr();
+
+	/* convert to nanoseconds */
+	ret = (this_offset - last_offset) & ACPI_PM_MASK;
+	ret = base + (cyc2us(ret) * NSEC_PER_USEC);
+	return ret;
+}
+
+static void delay_pmtmr(unsigned long loops)
+{
+	unsigned long bclock, now;
+
+	rdtscl(bclock);
+	do
+	{
+		rep_nop();
+		rdtscl(now);
+	} while ((now-bclock) < loops);
+}
+
+
+/*
+ * get the offset (in microseconds) from the last call to mark_offset()
+ *	- Called holding a reader xtime_lock
+ */
+static unsigned long get_offset_pmtmr(void)
+{
+	u32 now, offset, delta = 0;
+
+	offset = offset_tick;
+	now = read_pmtmr();
+	delta = (now - offset)&ACPI_PM_MASK;
+
+	return (unsigned long) offset_delay + cyc2us(delta);
+}
+
+
+/* acpi timer_opts struct */
+struct timer_opts timer_pmtmr = {
+	.name			= "pmtmr",
+	.init 			= init_pmtmr,
+	.mark_offset		= mark_offset_pmtmr,
+	.get_offset		= get_offset_pmtmr,
+	.monotonic_clock 	= monotonic_clock_pmtmr,
+	.delay 			= delay_pmtmr,
+};
+
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Dominik Brodowski <linux@brodo.de>");
+MODULE_DESCRIPTION("Power Management Timer (PMTMR) as primary timing source for x86");
--- diff/arch/i386/lib/kgdb_serial.c	1970-01-01 01:00:00.000000000 +0100
+++ source/arch/i386/lib/kgdb_serial.c	2004-02-23 13:56:37.000000000 +0000
@@ -0,0 +1,499 @@
+/*
+ * Serial interface GDB stub
+ *
+ * Written (hacked together) by David Grothe (dave@gcom.com)
+ * Modified to allow invokation early in boot see also
+ * kgdb.h for instructions by George Anzinger(george@mvista.com)
+ * Modified to handle debugging over ethernet by Robert Walsh
+ * <rjwalsh@durables.org> and wangdi <wangdi@clusterfs.com>, based on
+ * code by San Mehat.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/errno.h>
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/timer.h>
+#include <linux/interrupt.h>
+#include <linux/tty.h>
+#include <linux/tty_flip.h>
+#include <linux/serial.h>
+#include <linux/serial_reg.h>
+#include <linux/config.h>
+#include <linux/major.h>
+#include <linux/string.h>
+#include <linux/fcntl.h>
+#include <linux/ptrace.h>
+#include <linux/ioport.h>
+#include <linux/mm.h>
+#include <linux/init.h>
+#include <linux/highmem.h>
+#include <asm/system.h>
+#include <asm/io.h>
+#include <asm/segment.h>
+#include <asm/bitops.h>
+#include <asm/system.h>
+#include <asm/kgdb_local.h>
+#ifdef CONFIG_KGDB_USER_CONSOLE
+extern void kgdb_console_finit(void);
+#endif
+#define PRNT_off
+#define TEST_EXISTANCE
+#ifdef PRNT
+#define dbprintk(s) printk s
+#else
+#define dbprintk(s)
+#endif
+#define TEST_INTERRUPT_off
+#ifdef TEST_INTERRUPT
+#define intprintk(s) printk s
+#else
+#define intprintk(s)
+#endif
+
+#define IRQ_T(info) ((info->flags & ASYNC_SHARE_IRQ) ? SA_SHIRQ : SA_INTERRUPT)
+
+#define	GDB_BUF_SIZE	512	/* power of 2, please */
+
+static char gdb_buf[GDB_BUF_SIZE];
+static int gdb_buf_in_inx;
+static atomic_t gdb_buf_in_cnt;
+static int gdb_buf_out_inx;
+
+struct async_struct *gdb_async_info;
+static int gdb_async_irq;
+
+#define outb_px(a,b) outb_p(b,a)
+
+static void program_uart(struct async_struct *info);
+static void write_char(struct async_struct *info, int chr);
+/*
+ * Get a byte from the hardware data buffer and return it
+ */
+static int
+read_data_bfr(struct async_struct *info)
+{
+	char it = inb_p(info->port + UART_LSR);
+
+	if (it & UART_LSR_DR)
+		return (inb_p(info->port + UART_RX));
+	/*
+	 * If we have a framing error assume somebody messed with
+	 * our uart.  Reprogram it and send '-' both ways...
+	 */
+	if (it & 0xc) {
+		program_uart(info);
+		write_char(info, '-');
+		return ('-');
+	}
+	return (-1);
+
+}				/* read_data_bfr */
+
+/*
+ * Get a char if available, return -1 if nothing available.
+ * Empty the receive buffer first, then look at the interface hardware.
+
+ * Locking here is a bit of a problem.	We MUST not lock out communication
+ * if we are trying to talk to gdb about a kgdb entry.	ON the other hand
+ * we can loose chars in the console pass thru if we don't lock.  It is also
+ * possible that we could hold the lock or be waiting for it when kgdb
+ * NEEDS to talk.  Since kgdb locks down the world, it does not need locks.
+ * We do, of course have possible issues with interrupting a uart operation,
+ * but we will just depend on the uart status to help keep that straight.
+
+ */
+static spinlock_t uart_interrupt_lock = SPIN_LOCK_UNLOCKED;
+#ifdef CONFIG_SMP
+extern spinlock_t kgdb_spinlock;
+#endif
+
+static int
+read_char(struct async_struct *info)
+{
+	int chr;
+	unsigned long flags;
+	local_irq_save(flags);
+#ifdef CONFIG_SMP
+	if (!spin_is_locked(&kgdb_spinlock)) {
+		spin_lock(&uart_interrupt_lock);
+	}
+#endif
+	if (atomic_read(&gdb_buf_in_cnt) != 0) {	/* intr routine has q'd chars */
+		chr = gdb_buf[gdb_buf_out_inx++];
+		gdb_buf_out_inx &= (GDB_BUF_SIZE - 1);
+		atomic_dec(&gdb_buf_in_cnt);
+	} else {
+		chr = read_data_bfr(info);
+	}
+#ifdef CONFIG_SMP
+	if (!spin_is_locked(&kgdb_spinlock)) {
+		spin_unlock(&uart_interrupt_lock);
+	}
+#endif
+	local_irq_restore(flags);
+	return (chr);
+}
+
+/*
+ * Wait until the interface can accept a char, then write it.
+ */
+static void
+write_char(struct async_struct *info, int chr)
+{
+	while (!(inb_p(info->port + UART_LSR) & UART_LSR_THRE)) ;
+
+	outb_p(chr, info->port + UART_TX);
+
+}				/* write_char */
+
+/*
+ * Mostly we don't need a spinlock, but since the console goes
+ * thru here with interrutps on, well, we need to catch those
+ * chars.
+ */
+/*
+ * This is the receiver interrupt routine for the GDB stub.
+ * It will receive a limited number of characters of input
+ * from the gdb  host machine and save them up in a buffer.
+ *
+ * When the gdb stub routine tty_getDebugChar() is called it
+ * draws characters out of the buffer until it is empty and
+ * then reads directly from the serial port.
+ *
+ * We do not attempt to write chars from the interrupt routine
+ * since the stubs do all of that via tty_putDebugChar() which
+ * writes one byte after waiting for the interface to become
+ * ready.
+ *
+ * The debug stubs like to run with interrupts disabled since,
+ * after all, they run as a consequence of a breakpoint in
+ * the kernel.
+ *
+ * Perhaps someone who knows more about the tty driver than I
+ * care to learn can make this work for any low level serial
+ * driver.
+ */
+static irqreturn_t
+gdb_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+	struct async_struct *info;
+	unsigned long flags;
+
+	info = gdb_async_info;
+	if (!info || !info->tty || irq != gdb_async_irq)
+		return IRQ_NONE;
+
+	local_irq_save(flags);
+	spin_lock(&uart_interrupt_lock);
+	do {
+		int chr = read_data_bfr(info);
+		intprintk(("Debug char on int: %x hex\n", chr));
+		if (chr < 0)
+			continue;
+
+		if (chr == 3) {	/* Ctrl-C means remote interrupt */
+			BREAKPOINT;
+			continue;
+		}
+
+		if (atomic_read(&gdb_buf_in_cnt) >= GDB_BUF_SIZE) {
+			/* buffer overflow tosses early char */
+			read_char(info);
+		}
+		gdb_buf[gdb_buf_in_inx++] = chr;
+		gdb_buf_in_inx &= (GDB_BUF_SIZE - 1);
+	} while (inb_p(info->port + UART_IIR) & UART_IIR_RDI);
+	spin_unlock(&uart_interrupt_lock);
+	local_irq_restore(flags);
+	return IRQ_HANDLED;
+}				/* gdb_interrupt */
+
+/*
+ * Just a NULL routine for testing.
+ */
+void
+gdb_null(void)
+{
+}				/* gdb_null */
+
+/* These structure are filled in with values defined in asm/kgdb_local.h
+ */
+static struct serial_state state = SB_STATE;
+static struct async_struct local_info = SB_INFO;
+static int ok_to_enable_ints = 0;
+static void kgdb_enable_ints_now(void);
+
+extern char *kgdb_version;
+/*
+ * Hook an IRQ for KGDB.
+ *
+ * This routine is called from tty_putDebugChar, below.
+ */
+static int ints_disabled = 1;
+int
+gdb_hook_interrupt(struct async_struct *info, int verb)
+{
+	struct serial_state *state = info->state;
+	unsigned long flags;
+	int port;
+#ifdef TEST_EXISTANCE
+	int scratch, scratch2;
+#endif
+
+	/* The above fails if memory managment is not set up yet.
+	 * Rather than fail the set up, just keep track of the fact
+	 * and pick up the interrupt thing later.
+	 */
+	gdb_async_info = info;
+	port = gdb_async_info->port;
+	gdb_async_irq = state->irq;
+	if (verb) {
+		printk("kgdb %s : port =%x, IRQ=%d, divisor =%d\n",
+		       kgdb_version,
+		       port,
+		       gdb_async_irq, gdb_async_info->state->custom_divisor);
+	}
+	local_irq_save(flags);
+#ifdef TEST_EXISTANCE
+	/* Existance test */
+	/* Should not need all this, but just in case.... */
+
+	scratch = inb_p(port + UART_IER);
+	outb_px(port + UART_IER, 0);
+	outb_px(0xff, 0x080);
+	scratch2 = inb_p(port + UART_IER);
+	outb_px(port + UART_IER, scratch);
+	if (scratch2) {
+		printk
+		    ("gdb_hook_interrupt: Could not clear IER, not a UART!\n");
+		local_irq_restore(flags);
+		return 1;	/* We failed; there's nothing here */
+	}
+	scratch2 = inb_p(port + UART_LCR);
+	outb_px(port + UART_LCR, 0xBF);	/* set up for StarTech test */
+	outb_px(port + UART_EFR, 0);	/* EFR is the same as FCR */
+	outb_px(port + UART_LCR, 0);
+	outb_px(port + UART_FCR, UART_FCR_ENABLE_FIFO);
+	scratch = inb_p(port + UART_IIR) >> 6;
+	if (scratch == 1) {
+		printk("gdb_hook_interrupt: Undefined UART type!"
+		       "  Not a UART! \n");
+		local_irq_restore(flags);
+		return 1;
+	} else {
+		dbprintk(("gdb_hook_interrupt: UART type "
+			  "is %d where 0=16450, 2=16550 3=16550A\n", scratch));
+	}
+	scratch = inb_p(port + UART_MCR);
+	outb_px(port + UART_MCR, UART_MCR_LOOP | scratch);
+	outb_px(port + UART_MCR, UART_MCR_LOOP | 0x0A);
+	scratch2 = inb_p(port + UART_MSR) & 0xF0;
+	outb_px(port + UART_MCR, scratch);
+	if (scratch2 != 0x90) {
+		printk("gdb_hook_interrupt: "
+		       "Loop back test failed! Not a UART!\n");
+		local_irq_restore(flags);
+		return scratch2 + 1000;	/* force 0 to fail */
+	}
+#endif				/* test existance */
+	program_uart(info);
+	local_irq_restore(flags);
+
+	return (0);
+
+}				/* gdb_hook_interrupt */
+
+static void
+program_uart(struct async_struct *info)
+{
+	int port = info->port;
+
+	(void) inb_p(port + UART_RX);
+	outb_px(port + UART_IER, 0);
+
+	(void) inb_p(port + UART_RX);	/* serial driver comments say */
+	(void) inb_p(port + UART_IIR);	/* this clears the interrupt regs */
+	(void) inb_p(port + UART_MSR);
+	outb_px(port + UART_LCR, UART_LCR_WLEN8 | UART_LCR_DLAB);
+	outb_px(port + UART_DLL, info->state->custom_divisor & 0xff);	/* LS */
+	outb_px(port + UART_DLM, info->state->custom_divisor >> 8);	/* MS  */
+	outb_px(port + UART_MCR, info->MCR);
+
+	outb_px(port + UART_FCR, UART_FCR_ENABLE_FIFO | UART_FCR_TRIGGER_1 | UART_FCR_CLEAR_XMIT | UART_FCR_CLEAR_RCVR);	/* set fcr */
+	outb_px(port + UART_LCR, UART_LCR_WLEN8);	/* reset DLAB */
+	outb_px(port + UART_FCR, UART_FCR_ENABLE_FIFO | UART_FCR_TRIGGER_1);	/* set fcr */
+	if (!ints_disabled) {
+		intprintk(("KGDB: Sending %d to port %x offset %d\n",
+			   gdb_async_info->IER,
+			   (int) gdb_async_info->port, UART_IER));
+		outb_px(gdb_async_info->port + UART_IER, gdb_async_info->IER);
+	}
+	return;
+}
+
+/*
+ * tty_getDebugChar
+ *
+ * This is a GDB stub routine.	It waits for a character from the
+ * serial interface and then returns it.  If there is no serial
+ * interface connection then it returns a bogus value which will
+ * almost certainly cause the system to hang.  In the
+ */
+int kgdb_in_isr = 0;
+int kgdb_in_lsr = 0;
+extern spinlock_t kgdb_spinlock;
+
+/* Caller takes needed protections */
+
+int
+tty_getDebugChar(void)
+{
+	volatile int chr, dum, time, end_time;
+
+	dbprintk(("tty_getDebugChar(port %x): ", gdb_async_info->port));
+
+	if (gdb_async_info == NULL) {
+		gdb_hook_interrupt(&local_info, 0);
+	}
+	/*
+	 * This trick says if we wait a very long time and get
+	 * no char, return the -1 and let the upper level deal
+	 * with it.
+	 */
+	rdtsc(dum, time);
+	end_time = time + 2;
+	while (((chr = read_char(gdb_async_info)) == -1) &&
+	       (end_time - time) > 0) {
+		rdtsc(dum, time);
+	};
+	/*
+	 * This covers our butts if some other code messes with
+	 * our uart, hay, it happens :o)
+	 */
+	if (chr == -1)
+		program_uart(gdb_async_info);
+
+	dbprintk(("%c\n", chr > ' ' && chr < 0x7F ? chr : ' '));
+	return (chr);
+
+}				/* tty_getDebugChar */
+
+static int count = 3;
+static spinlock_t one_at_atime = SPIN_LOCK_UNLOCKED;
+
+static int __init
+kgdb_enable_ints(void)
+{
+	if (kgdboe) {
+		return 0;
+	}
+	if (gdb_async_info == NULL) {
+		gdb_hook_interrupt(&local_info, 1);
+	}
+	ok_to_enable_ints = 1;
+	kgdb_enable_ints_now();
+#ifdef CONFIG_KGDB_USER_CONSOLE
+	kgdb_console_finit();
+#endif
+	return 0;
+}
+
+#ifdef CONFIG_SERIAL_8250
+void shutdown_for_kgdb(struct async_struct *gdb_async_info);
+#endif
+
+#ifdef CONFIG_DISCONTIGMEM
+static inline int kgdb_mem_init_done(void)
+{
+	return highmem_start_page != NULL;
+}
+#else
+static inline int kgdb_mem_init_done(void)
+{
+	return max_mapnr != 0;
+}
+#endif
+
+static void
+kgdb_enable_ints_now(void)
+{
+	if (!spin_trylock(&one_at_atime))
+		return;
+	if (!ints_disabled)
+		goto exit;
+	if (kgdb_mem_init_done() &&
+			ints_disabled) {	/* don't try till mem init */
+#ifdef CONFIG_SERIAL_8250
+		/*
+		 * The ifdef here allows the system to be configured
+		 * without the serial driver.
+		 * Don't make it a module, however, it will steal the port
+		 */
+		shutdown_for_kgdb(gdb_async_info);
+#endif
+		ints_disabled = request_irq(gdb_async_info->state->irq,
+					    gdb_interrupt,
+					    IRQ_T(gdb_async_info),
+					    "KGDB-stub", NULL);
+		intprintk(("KGDB: request_irq returned %d\n", ints_disabled));
+	}
+	if (!ints_disabled) {
+		intprintk(("KGDB: Sending %d to port %x offset %d\n",
+			   gdb_async_info->IER,
+			   (int) gdb_async_info->port, UART_IER));
+		outb_px(gdb_async_info->port + UART_IER, gdb_async_info->IER);
+	}
+      exit:
+	spin_unlock(&one_at_atime);
+}
+
+/*
+ * tty_putDebugChar
+ *
+ * This is a GDB stub routine.	It waits until the interface is ready
+ * to transmit a char and then sends it.  If there is no serial
+ * interface connection then it simply returns to its caller, having
+ * pretended to send the char.	Caller takes needed protections.
+ */
+void
+tty_putDebugChar(int chr)
+{
+	dbprintk(("tty_putDebugChar(port %x): chr=%02x '%c', ints_on=%d\n",
+		  gdb_async_info->port,
+		  chr,
+		  chr > ' ' && chr < 0x7F ? chr : ' ', ints_disabled ? 0 : 1));
+
+	if (gdb_async_info == NULL) {
+		gdb_hook_interrupt(&local_info, 0);
+	}
+
+	write_char(gdb_async_info, chr);	/* this routine will wait */
+	count = (chr == '#') ? 0 : count + 1;
+	if ((count == 2)) {	/* try to enable after */
+		if (ints_disabled & ok_to_enable_ints)
+			kgdb_enable_ints_now();	/* try to enable after */
+
+		/* We do this a lot because, well we really want to get these
+		 * interrupts.	The serial driver will clear these bits when it
+		 * initializes the chip.  Every thing else it does is ok,
+		 * but this.
+		 */
+		if (!ints_disabled) {
+			outb_px(gdb_async_info->port + UART_IER,
+				gdb_async_info->IER);
+		}
+	}
+
+}				/* tty_putDebugChar */
+
+/*
+ * This does nothing for the serial port, since it doesn't buffer.
+ */
+
+void tty_flushDebugChar(void)
+{
+}
+
+module_init(kgdb_enable_ints);
--- diff/arch/i386/pci/mmconfig.c	1970-01-01 01:00:00.000000000 +0100
+++ source/arch/i386/pci/mmconfig.c	2004-02-23 13:56:37.000000000 +0000
@@ -0,0 +1,109 @@
+/*
+ * mmconfig.c - Low-level direct PCI config space access via MMCONFIG
+ */
+
+#include <linux/pci.h>
+#include <linux/init.h>
+#include "pci.h"
+
+/* The physical address of the MMCONFIG aperture.  Set from ACPI tables. */
+u32 pci_mmcfg_base_addr;
+
+#define mmcfg_virt_addr (fix_to_virt(FIX_PCIE_MCFG))
+
+/* The base address of the last MMCONFIG device accessed */
+static u32 mmcfg_last_accessed_device;
+
+/*
+ * Functions for accessing PCI configuration space with MMCONFIG accesses
+ */
+
+static inline void pci_exp_set_dev_base(int bus, int devfn)
+{
+	u32 dev_base = pci_mmcfg_base_addr | (bus << 20) | (devfn << 12);
+	if (dev_base != mmcfg_last_accessed_device) {
+		mmcfg_last_accessed_device = dev_base;
+		set_fixmap(FIX_PCIE_MCFG, dev_base);
+	}
+}
+
+static int pci_mmcfg_read(int seg, int bus, int devfn, int reg, int len, u32 *value)
+{
+	unsigned long flags;
+
+	if (!value || (bus > 255) || (devfn > 255) || (reg > 4095))
+		return -EINVAL;
+
+	spin_lock_irqsave(&pci_config_lock, flags);
+
+	pci_exp_set_dev_base(bus, devfn);
+
+	switch (len) {
+	case 1:
+		*value = readb(mmcfg_virt_addr + reg);
+		break;
+	case 2:
+		*value = readw(mmcfg_virt_addr + reg);
+		break;
+	case 4:
+		*value = readl(mmcfg_virt_addr + reg);
+		break;
+	}
+
+	spin_unlock_irqrestore(&pci_config_lock, flags);
+
+	return 0;
+}
+
+static int pci_mmcfg_write(int seg, int bus, int devfn, int reg, int len, u32 value)
+{
+	unsigned long flags;
+
+	if ((bus > 255) || (devfn > 255) || (reg > 4095))
+		return -EINVAL;
+
+	spin_lock_irqsave(&pci_config_lock, flags);
+
+	pci_exp_set_dev_base(bus, devfn);
+
+	switch (len) {
+	case 1:
+		writeb(value, mmcfg_virt_addr + reg);
+		break;
+	case 2:
+		writew(value, mmcfg_virt_addr + reg);
+		break;
+	case 4:
+		writel(value, mmcfg_virt_addr + reg);
+		break;
+	}
+
+	/* Dummy read to flush PCI write */
+	readl(mmcfg_virt_addr);
+
+	spin_unlock_irqrestore(&pci_config_lock, flags);
+
+	return 0;
+}
+
+static struct pci_raw_ops pci_mmcfg = {
+	.read =		pci_mmcfg_read,
+	.write =	pci_mmcfg_write,
+};
+
+static int __init pci_mmcfg_init(void)
+{
+	if ((pci_probe & PCI_PROBE_MMCONF) == 0)
+		goto out;
+	if (!pci_mmcfg_base_addr)
+		goto out;
+
+	printk(KERN_INFO "PCI: Using MMCONFIG\n");
+	raw_pci_ops = &pci_mmcfg;
+	pci_probe = (pci_probe & ~PCI_PROBE_MASK) | PCI_PROBE_MMCONF;
+
+ out:
+	return 0;
+}
+
+arch_initcall(pci_mmcfg_init);
--- diff/arch/ia64/kernel/cyclone.c	1970-01-01 01:00:00.000000000 +0100
+++ source/arch/ia64/kernel/cyclone.c	2004-02-23 13:56:37.000000000 +0000
@@ -0,0 +1,158 @@
+#include <linux/smp.h>
+#include <linux/time.h>
+#include <linux/errno.h>
+
+/* IBM Summit (EXA) Cyclone counter code*/
+#define CYCLONE_CBAR_ADDR 0xFEB00CD0
+#define CYCLONE_PMCC_OFFSET 0x51A0
+#define CYCLONE_MPMC_OFFSET 0x51D0
+#define CYCLONE_MPCS_OFFSET 0x51A8
+#define CYCLONE_TIMER_FREQ 100000000
+
+int use_cyclone;
+int __init cyclone_setup(char *str)
+{
+	use_cyclone = 1;
+	return 1;
+}
+
+static u32* volatile cyclone_timer;	/* Cyclone MPMC0 register */
+static u32 last_update_cyclone;
+
+static unsigned long offset_base;
+
+static unsigned long get_offset_cyclone(void)
+{
+	u32 now;
+	unsigned long offset;
+
+	/* Read the cyclone timer */
+	now = readl(cyclone_timer);
+	/* .. relative to previous update*/
+	offset = now - last_update_cyclone;
+
+	/* convert cyclone ticks to nanoseconds */
+	offset = (offset*NSEC_PER_SEC)/CYCLONE_TIMER_FREQ;
+
+	/* our adjusted time in nanoseconds */
+	return offset_base + offset;
+}
+
+static void update_cyclone(long delta_nsec)
+{
+	u32 now;
+	unsigned long offset;
+
+	/* Read the cyclone timer */
+	now = readl(cyclone_timer);
+	/* .. relative to previous update*/
+	offset = now - last_update_cyclone;
+
+	/* convert cyclone ticks to nanoseconds */
+	offset = (offset*NSEC_PER_SEC)/CYCLONE_TIMER_FREQ;
+
+	offset += offset_base;
+
+	/* Be careful about signed/unsigned comparisons here: */
+	if (delta_nsec < 0 || (unsigned long) delta_nsec < offset)
+		offset_base = offset - delta_nsec;
+	else
+		offset_base = 0;
+
+	last_update_cyclone = now;
+}
+
+static void reset_cyclone(void)
+{
+	offset_base = 0;
+	last_update_cyclone = readl(cyclone_timer);
+}
+
+struct time_interpolator cyclone_interpolator = {
+	.get_offset =	get_offset_cyclone,
+	.update =	update_cyclone,
+	.reset =	reset_cyclone,
+	.frequency =	CYCLONE_TIMER_FREQ,
+	.drift =	-100,
+};
+
+int __init init_cyclone_clock(void)
+{
+	u64* reg;
+	u64 base;	/* saved cyclone base address */
+	u64 offset;	/* offset from pageaddr to cyclone_timer register */
+	int i;
+
+	if (!use_cyclone)
+		return -ENODEV;
+
+	printk(KERN_INFO "Summit chipset: Starting Cyclone Counter.\n");
+
+	/* find base address */
+	offset = (CYCLONE_CBAR_ADDR);
+	reg = (u64*)ioremap_nocache(offset, sizeof(u64));
+	if(!reg){
+		printk(KERN_ERR "Summit chipset: Could not find valid CBAR register.\n");
+		use_cyclone = 0;
+		return -ENODEV;
+	}
+	base = readq(reg);
+	if(!base){
+		printk(KERN_ERR "Summit chipset: Could not find valid CBAR value.\n");
+		use_cyclone = 0;
+		return -ENODEV;
+	}
+	iounmap(reg);
+
+	/* setup PMCC */
+	offset = (base + CYCLONE_PMCC_OFFSET);
+	reg = (u64*)ioremap_nocache(offset, sizeof(u64));
+	if(!reg){
+		printk(KERN_ERR "Summit chipset: Could not find valid PMCC register.\n");
+		use_cyclone = 0;
+		return -ENODEV;
+	}
+	writel(0x00000001,reg);
+	iounmap(reg);
+
+	/* setup MPCS */
+	offset = (base + CYCLONE_MPCS_OFFSET);
+	reg = (u64*)ioremap_nocache(offset, sizeof(u64));
+	if(!reg){
+		printk(KERN_ERR "Summit chipset: Could not find valid MPCS register.\n");
+		use_cyclone = 0;
+		return -ENODEV;
+	}
+	writel(0x00000001,reg);
+	iounmap(reg);
+
+	/* map in cyclone_timer */
+	offset = (base + CYCLONE_MPMC_OFFSET);
+	cyclone_timer = (u32*)ioremap_nocache(offset, sizeof(u32));
+	if(!cyclone_timer){
+		printk(KERN_ERR "Summit chipset: Could not find valid MPMC register.\n");
+		use_cyclone = 0;
+		return -ENODEV;
+	}
+
+	/*quick test to make sure its ticking*/
+	for(i=0; i<3; i++){
+		u32 old = readl(cyclone_timer);
+		int stall = 100;
+		while(stall--) barrier();
+		if(readl(cyclone_timer) == old){
+			printk(KERN_ERR "Summit chipset: Counter not counting! DISABLED\n");
+			iounmap(cyclone_timer);
+			cyclone_timer = 0;
+			use_cyclone = 0;
+			return -ENODEV;
+		}
+	}
+	/* initialize last tick */
+	last_update_cyclone = readl(cyclone_timer);
+	register_time_interpolator(&cyclone_interpolator);
+
+	return 0;
+}
+
+__initcall(init_cyclone_clock);
--- diff/arch/m68k/kernel/asm-offsets.c	1970-01-01 01:00:00.000000000 +0100
+++ source/arch/m68k/kernel/asm-offsets.c	2004-02-23 13:56:37.000000000 +0000
@@ -0,0 +1,109 @@
+/*
+ * This program is used to generate definitions needed by
+ * assembly language modules.
+ *
+ * We use the technique used in the OSF Mach kernel code:
+ * generate asm statements containing #defines,
+ * compile this file to assembler, and then extract the
+ * #defines from the assembly-language output.
+ */
+
+#include <linux/stddef.h>
+#include <linux/sched.h>
+#include <linux/kernel_stat.h>
+#include <asm/bootinfo.h>
+#include <asm/irq.h>
+#include <asm/amigahw.h>
+#include <linux/font.h>
+
+#define DEFINE(sym, val) \
+	asm volatile("\n->" #sym " %0 " #val : : "i" (val))
+
+int main(void)
+{
+	/* offsets into the task struct */
+	DEFINE(TASK_STATE, offsetof(struct task_struct, state));
+	DEFINE(TASK_FLAGS, offsetof(struct task_struct, flags));
+	DEFINE(TASK_PTRACE, offsetof(struct task_struct, ptrace));
+	DEFINE(TASK_WORK, offsetof(struct task_struct, thread.work));
+	DEFINE(TASK_NEEDRESCHED, offsetof(struct task_struct, thread.work.need_resched));
+	DEFINE(TASK_SYSCALL_TRACE, offsetof(struct task_struct, thread.work.syscall_trace));
+	DEFINE(TASK_SIGPENDING, offsetof(struct task_struct, thread.work.sigpending));
+	DEFINE(TASK_NOTIFY_RESUME, offsetof(struct task_struct, thread.work.notify_resume));
+	DEFINE(TASK_THREAD, offsetof(struct task_struct, thread));
+	DEFINE(TASK_MM, offsetof(struct task_struct, mm));
+	DEFINE(TASK_ACTIVE_MM, offsetof(struct task_struct, active_mm));
+
+	/* offsets into the thread struct */
+	DEFINE(THREAD_KSP, offsetof(struct thread_struct, ksp));
+	DEFINE(THREAD_USP, offsetof(struct thread_struct, usp));
+	DEFINE(THREAD_SR, offsetof(struct thread_struct, sr));
+	DEFINE(THREAD_FS, offsetof(struct thread_struct, fs));
+	DEFINE(THREAD_CRP, offsetof(struct thread_struct, crp));
+	DEFINE(THREAD_ESP0, offsetof(struct thread_struct, esp0));
+	DEFINE(THREAD_FPREG, offsetof(struct thread_struct, fp));
+	DEFINE(THREAD_FPCNTL, offsetof(struct thread_struct, fpcntl));
+	DEFINE(THREAD_FPSTATE, offsetof(struct thread_struct, fpstate));
+
+	/* offsets into the pt_regs */
+	DEFINE(PT_D0, offsetof(struct pt_regs, d0));
+	DEFINE(PT_ORIG_D0, offsetof(struct pt_regs, orig_d0));
+	DEFINE(PT_D1, offsetof(struct pt_regs, d1));
+	DEFINE(PT_D2, offsetof(struct pt_regs, d2));
+	DEFINE(PT_D3, offsetof(struct pt_regs, d3));
+	DEFINE(PT_D4, offsetof(struct pt_regs, d4));
+	DEFINE(PT_D5, offsetof(struct pt_regs, d5));
+	DEFINE(PT_A0, offsetof(struct pt_regs, a0));
+	DEFINE(PT_A1, offsetof(struct pt_regs, a1));
+	DEFINE(PT_A2, offsetof(struct pt_regs, a2));
+	DEFINE(PT_PC, offsetof(struct pt_regs, pc));
+	DEFINE(PT_SR, offsetof(struct pt_regs, sr));
+	/* bitfields are a bit difficult */
+	DEFINE(PT_VECTOR, offsetof(struct pt_regs, pc) + 4);
+
+	/* offsets into the irq_handler struct */
+	DEFINE(IRQ_HANDLER, offsetof(struct irq_node, handler));
+	DEFINE(IRQ_DEVID, offsetof(struct irq_node, dev_id));
+	DEFINE(IRQ_NEXT, offsetof(struct irq_node, next));
+
+	/* offsets into the kernel_stat struct */
+	DEFINE(STAT_IRQ, offsetof(struct kernel_stat, irqs));
+
+	/* offsets into the irq_cpustat_t struct */
+	DEFINE(CPUSTAT_SOFTIRQ_PENDING, offsetof(irq_cpustat_t, __softirq_pending));
+
+	/* offsets into the bi_record struct */
+	DEFINE(BIR_TAG, offsetof(struct bi_record, tag));
+	DEFINE(BIR_SIZE, offsetof(struct bi_record, size));
+	DEFINE(BIR_DATA, offsetof(struct bi_record, data));
+
+	/* offsets into font_desc (drivers/video/console/font.h) */
+	DEFINE(FONT_DESC_IDX, offsetof(struct font_desc, idx));
+	DEFINE(FONT_DESC_NAME, offsetof(struct font_desc, name));
+	DEFINE(FONT_DESC_WIDTH, offsetof(struct font_desc, width));
+	DEFINE(FONT_DESC_HEIGHT, offsetof(struct font_desc, height));
+	DEFINE(FONT_DESC_DATA, offsetof(struct font_desc, data));
+	DEFINE(FONT_DESC_PREF, offsetof(struct font_desc, pref));
+
+	/* signal defines */
+	DEFINE(SIGSEGV, SIGSEGV);
+	DEFINE(SEGV_MAPERR, SEGV_MAPERR);
+	DEFINE(SIGTRAP, SIGTRAP);
+	DEFINE(TRAP_TRACE, TRAP_TRACE);
+
+	/* offsets into the custom struct */
+	DEFINE(CUSTOMBASE, &custom);
+	DEFINE(C_INTENAR, offsetof(struct CUSTOM, intenar));
+	DEFINE(C_INTREQR, offsetof(struct CUSTOM, intreqr));
+	DEFINE(C_INTENA, offsetof(struct CUSTOM, intena));
+	DEFINE(C_INTREQ, offsetof(struct CUSTOM, intreq));
+	DEFINE(C_SERDATR, offsetof(struct CUSTOM, serdatr));
+	DEFINE(C_SERDAT, offsetof(struct CUSTOM, serdat));
+	DEFINE(C_SERPER, offsetof(struct CUSTOM, serper));
+	DEFINE(CIAABASE, &ciaa);
+	DEFINE(CIABBASE, &ciab);
+	DEFINE(C_PRA, offsetof(struct CIA, pra));
+	DEFINE(ZTWOBASE, zTwoBase);
+
+	return 0;
+}
--- diff/arch/mips/au1000/common/pci.c	1970-01-01 01:00:00.000000000 +0100
+++ source/arch/mips/au1000/common/pci.c	2004-02-23 13:56:38.000000000 +0000
@@ -0,0 +1,112 @@
+/*
+ * BRIEF MODULE DESCRIPTION
+ *	Alchemy/AMD Au1x00 pci support.
+ *
+ * Copyright 2001,2002,2003 MontaVista Software Inc.
+ * Author: MontaVista Software, Inc.
+ *         	ppopov@mvista.com or source@mvista.com
+ *
+ *  Support for all devices (greater than 16) added by David Gathright.
+ *
+ *  This program is free software; you can redistribute  it and/or modify it
+ *  under  the terms of  the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the  License, or (at your
+ *  option) any later version.
+ *
+ *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
+ *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
+ *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
+ *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
+ *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
+ *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *  You should have received a copy of the  GNU General Public License along
+ *  with this program; if not, write  to the Free Software Foundation, Inc.,
+ *  675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+
+#include <asm/mach-au1x00/au1000.h>
+//#include <asm/pb1500.h>
+#ifdef CONFIG_MIPS_PB1000
+#include <asm/mach-pb1x00/pb1000.h>
+#endif
+#include <asm/pci_channel.h>
+
+/* TBD */
+static struct resource pci_io_resource = {
+	"pci IO space", 
+	(u32)PCI_IO_START,
+	(u32)PCI_IO_END,
+	IORESOURCE_IO
+};
+
+static struct resource pci_mem_resource = {
+	"pci memory space", 
+	(u32)PCI_MEM_START,
+	(u32)PCI_MEM_END,
+	IORESOURCE_MEM
+};
+
+extern struct pci_ops au1x_pci_ops;
+
+static struct pci_controller au1x_controller = {
+	.pci_ops	= &au1x_pci_ops,
+	.io_resource	= &pci_io_resource,
+	.mem_resource	= &pci_mem_resource,
+};
+
+#ifdef CONFIG_SOC_AU1500
+static unsigned long virt_io_addr;
+#endif
+
+static int __init au1x_pci_setup(void)
+{
+#ifdef CONFIG_SOC_AU1500
+	int i;
+	struct pci_dev *dev;
+	
+	virt_io_addr = (unsigned long)ioremap(Au1500_PCI_IO_START, 
+			Au1500_PCI_IO_END - Au1500_PCI_IO_START + 1);
+
+	if (!virt_io_addr) {
+		printk(KERN_ERR "Unable to ioremap pci space\n");
+		return;
+	}
+
+#ifdef CONFIG_DMA_NONCOHERENT
+	/* 
+	 *  Set the NC bit in controller for pre-AC silicon
+	 */
+	au_writel( 1<<16 | au_readl(Au1500_PCI_CFG), Au1500_PCI_CFG);
+	printk("Non-coherent PCI accesses enabled\n");
+#endif
+
+	set_io_port_base(virt_io_addr);
+#endif
+
+#ifdef CONFIG_MIPS_PB1000 /* This is truly board specific */
+	unsigned long pci_mem_start = (unsigned long) PCI_MEM_START;
+
+	au_writel(0, PCI_BRIDGE_CONFIG); // set extend byte to 0
+	au_writel(0, SDRAM_MBAR);        // set mbar to 0
+	au_writel(0x2, SDRAM_CMD);       // enable memory accesses
+	au_sync_delay(1);
+
+	// set extend byte to mbar of ext slot
+	au_writel(((pci_mem_start >> 24) & 0xff) |
+	       (1 << 8 | 1 << 9 | 1 << 10 | 1 << 27), PCI_BRIDGE_CONFIG);
+#endif
+
+	register_pci_controller(&au1x_controller);
+}
+
+arch_initcall(au1x_pci_setup);
--- diff/arch/mips/au1000/common/setup.c	1970-01-01 01:00:00.000000000 +0100
+++ source/arch/mips/au1000/common/setup.c	2004-02-23 13:56:38.000000000 +0000
@@ -0,0 +1,194 @@
+/*
+ * Copyright 2000 MontaVista Software Inc.
+ * Author: MontaVista Software, Inc.
+ *         	ppopov@mvista.com or source@mvista.com
+ *
+ *  This program is free software; you can redistribute  it and/or modify it
+ *  under  the terms of  the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the  License, or (at your
+ *  option) any later version.
+ *
+ *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
+ *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
+ *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
+ *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
+ *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
+ *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *  You should have received a copy of the  GNU General Public License along
+ *  with this program; if not, write  to the Free Software Foundation, Inc.,
+ *  675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/ioport.h>
+#include <linux/mm.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+
+#include <asm/cpu.h>
+#include <asm/bootinfo.h>
+#include <asm/irq.h>
+#include <asm/mipsregs.h>
+#include <asm/reboot.h>
+#include <asm/pgtable.h>
+#include <asm/mach-au1x00/au1000.h>
+#include <asm/time.h>
+
+#ifdef CONFIG_BLK_DEV_INITRD
+extern unsigned long initrd_start, initrd_end;
+extern void * __rd_start, * __rd_end;
+#endif
+
+extern char * __init prom_getcmdline(void);
+extern void __init board_setup(void);
+extern void au1000_restart(char *);
+extern void au1000_halt(void);
+extern void au1000_power_off(void);
+extern struct resource ioport_resource;
+extern struct resource iomem_resource;
+extern void (*board_time_init)(void);
+extern void au1x_time_init(void);
+extern void (*board_timer_setup)(struct irqaction *irq);
+extern void au1x_timer_setup(struct irqaction *irq);
+#if defined(CONFIG_64BIT_PHYS_ADDR) && defined(CONFIG_SOC_AU1500)
+extern phys_t (*fixup_bigphys_addr)(phys_t phys_addr, phys_t size);
+static phys_t au1500_fixup_bigphys_addr(phys_t phys_addr, phys_t size);
+#endif
+extern void au1xxx_time_init(void);
+extern void au1xxx_timer_setup(struct irqaction *irq);
+
+static int __init au1x00_setup(void)
+{
+	char *argptr;
+
+	/* Various early Au1000 Errata corrected by this */
+	set_c0_config(1<<19); /* Config[OD] */
+
+	board_setup();  /* board specific setup */
+
+	argptr = prom_getcmdline();
+
+#ifdef CONFIG_SERIAL_AU1X00_CONSOLE
+	if ((argptr = strstr(argptr, "console=")) == NULL) {
+		argptr = prom_getcmdline();
+		strcat(argptr, " console=ttyS0,115200");
+	}
+#endif	  
+
+#ifdef CONFIG_FB_AU1100
+    if ((argptr = strstr(argptr, "video=")) == NULL) {
+        argptr = prom_getcmdline();
+        /* default panel */
+        /*strcat(argptr, " video=au1100fb:panel:Sharp_320x240_16");*/
+#ifdef CONFIG_MIPS_HYDROGEN3
+         strcat(argptr, " video=au1100fb:panel:Hydrogen_3_NEC_panel_320x240,nohwcursor");
+#else
+        strcat(argptr, " video=au1100fb:panel:s10,nohwcursor");
+#endif
+    }
+#endif
+
+#ifdef CONFIG_FB_E1356
+	if ((argptr = strstr(argptr, "video=")) == NULL) {
+		argptr = prom_getcmdline();
+#ifdef CONFIG_MIPS_PB1000
+		strcat(argptr, " video=e1356fb:system:pb1000,mmunalign:1");
+#else
+		strcat(argptr, " video=e1356fb:system:pb1500");
+#endif
+	}
+#endif
+
+#ifdef CONFIG_FB_XPERT98
+	if ((argptr = strstr(argptr, "video=")) == NULL) {
+		argptr = prom_getcmdline();
+		strcat(argptr, " video=atyfb:1024x768-8@70");
+	}
+#endif
+
+#if defined(CONFIG_SOUND_AU1X00) && !defined(CONFIG_SOC_AU1000)
+	/* au1000 does not support vra, au1500 and au1100 do */
+	strcat(argptr, " au1000_audio=vra");
+	argptr = prom_getcmdline();
+#endif
+	_machine_restart = au1000_restart;
+	_machine_halt = au1000_halt;
+	_machine_power_off = au1000_power_off;
+	board_time_init = au1xxx_time_init;
+	board_timer_setup = au1xxx_timer_setup;
+#if defined(CONFIG_64BIT_PHYS_ADDR) && defined(CONFIG_SOC_AU1500)
+	fixup_bigphys_addr = au1500_fixup_bigphys_addr;
+#endif
+
+	/* IO/MEM resources. */
+	set_io_port_base(0);
+	ioport_resource.start = IOPORT_RESOURCE_START;
+	ioport_resource.end = IOPORT_RESOURCE_END;
+	iomem_resource.start = IOMEM_RESOURCE_START;
+	iomem_resource.end = IOMEM_RESOURCE_END;
+
+#ifdef CONFIG_BLK_DEV_INITRD
+	ROOT_DEV = MKDEV(RAMDISK_MAJOR, 0);
+	initrd_start = (unsigned long)&__rd_start;
+	initrd_end = (unsigned long)&__rd_end;
+#endif
+
+#if defined (CONFIG_USB_OHCI) || defined (CONFIG_AU1X00_USB_DEVICE)
+#ifdef CONFIG_USB_OHCI
+	if ((argptr = strstr(argptr, "usb_ohci=")) == NULL) {
+	        char usb_args[80];
+		argptr = prom_getcmdline();
+		memset(usb_args, 0, sizeof(usb_args));
+		sprintf(usb_args, " usb_ohci=base:0x%x,len:0x%x,irq:%d",
+			USB_OHCI_BASE, USB_OHCI_LEN, AU1000_USB_HOST_INT);
+		strcat(argptr, usb_args);
+	}
+#endif
+
+#ifdef CONFIG_USB_OHCI
+	/* enable host controller and wait for reset done */
+	au_writel(0x08, USB_HOST_CONFIG);
+	udelay(1000);
+	au_writel(0x0E, USB_HOST_CONFIG);
+	udelay(1000);
+	au_readl(USB_HOST_CONFIG); /* throw away first read */
+	while (!(au_readl(USB_HOST_CONFIG) & 0x10))
+		au_readl(USB_HOST_CONFIG);
+#endif
+#endif /* defined (CONFIG_USB_OHCI) || defined (CONFIG_AU1X00_USB_DEVICE) */
+
+	while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_E0S);
+	au_writel(SYS_CNTRL_E0 | SYS_CNTRL_EN0, SYS_COUNTER_CNTRL);
+	au_sync();
+	while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_T0S);
+	au_writel(0, SYS_TOYTRIM);
+	return 0;
+}
+
+early_initcall(au1x00_setup);
+
+#if defined(CONFIG_64BIT_PHYS_ADDR) && defined(CONFIG_SOC_AU1500)
+/* This routine should be valid for all Au1500 based boards */
+static phys_t au1500_fixup_bigphys_addr(phys_t phys_addr, phys_t size)
+{
+	u32 pci_start = (u32)Au1500_PCI_MEM_START;
+	u32 pci_end = (u32)Au1500_PCI_MEM_END;
+
+	/* Don't fixup 36 bit addresses */
+	if ((phys_addr >> 32) != 0) return phys_addr;
+
+	/* check for pci memory window */
+	if ((phys_addr >= pci_start) && ((phys_addr + size) < pci_end)) {
+		return (phys_t)((phys_addr - pci_start) +
+				     Au1500_PCI_MEM_START);
+	}
+	else 
+		return phys_addr;
+}
+#endif
--- diff/arch/mips/au1000/common/sleeper.S	1970-01-01 01:00:00.000000000 +0100
+++ source/arch/mips/au1000/common/sleeper.S	2004-02-23 13:56:38.000000000 +0000
@@ -0,0 +1,150 @@
+/*
+ * Copyright 2002 Embedded Edge, LLC
+ * Author: dan@embeddededge.com
+ *
+ * Sleep helper for Au1xxx sleep mode.
+ *
+ * This program is free software; you can redistribute	it and/or modify it
+ * under  the terms of	the GNU General	 Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+#include <linux/config.h>
+#include <asm/asm.h>
+#include <asm/mipsregs.h>
+#include <asm/addrspace.h>
+#include <asm/regdef.h>
+#include <asm/stackframe.h>
+
+	.text
+	.set	macro
+	.set	noat
+	.align	5
+
+/* Save all of the processor general registers and go to sleep.
+ * A wakeup condition will get us back here to restore the registers.
+ */
+LEAF(save_and_sleep)
+
+	subu	sp, PT_SIZE
+	sw	$1, PT_R1(sp)
+	sw	$2, PT_R2(sp)
+	sw	$3, PT_R3(sp)
+	sw	$4, PT_R4(sp)
+	sw	$5, PT_R5(sp)
+	sw	$6, PT_R6(sp)
+	sw	$7, PT_R7(sp)
+	sw	$8, PT_R8(sp)
+	sw	$9, PT_R9(sp)
+	sw	$10, PT_R10(sp)
+	sw	$11, PT_R11(sp)
+	sw	$12, PT_R12(sp)
+	sw	$13, PT_R13(sp)
+	sw	$14, PT_R14(sp)
+	sw	$15, PT_R15(sp)
+	sw	$16, PT_R16(sp)
+	sw	$17, PT_R17(sp)
+	sw	$18, PT_R18(sp)
+	sw	$19, PT_R19(sp)
+	sw	$20, PT_R20(sp)
+	sw	$21, PT_R21(sp)
+	sw	$22, PT_R22(sp)
+	sw	$23, PT_R23(sp)
+	sw	$24, PT_R24(sp)
+	sw	$25, PT_R25(sp)
+	sw	$26, PT_R26(sp)
+	sw	$27, PT_R27(sp)
+	sw	$28, PT_R28(sp)
+	sw	$29, PT_R29(sp)
+	sw	$30, PT_R30(sp)
+	sw	$31, PT_R31(sp)
+	mfc0	k0, CP0_STATUS
+	sw	k0, 0x20(sp)
+	mfc0	k0, CP0_CONTEXT
+	sw	k0, 0x1c(sp)
+	mfc0	k0, CP0_PAGEMASK
+	sw	k0, 0x18(sp)
+	mfc0	k0, CP0_CONFIG
+	sw	k0, 0x14(sp)
+
+	/* Now set up the scratch registers so the boot rom will
+	 * return to this point upon wakeup.
+	 */
+	la	k0, 1f
+	lui	k1, 0xb190
+	ori	k1, 0x18
+	sw	sp, 0(k1)
+	ori 	k1, 0x1c
+	sw	k0, 0(k1)
+
+/* Put SDRAM into self refresh.  Preload instructions into cache,
+ * issue a precharge, then auto refresh, then sleep commands to it.
+ */
+ 	la	t0, sdsleep
+	.set	mips3
+ 	cache	0x14, 0(t0)
+ 	cache	0x14, 32(t0)
+ 	cache	0x14, 64(t0)
+ 	cache	0x14, 96(t0)
+	.set	mips0
+
+sdsleep:
+	lui 	k0, 0xb400
+	sw	zero, 0x001c(k0)	/* Precharge */
+	sw	zero, 0x0020(k0)	/* Auto refresh */
+	sw	zero, 0x0030(k0)	/* SDRAM sleep */
+	sync
+
+	lui 	k1, 0xb190
+	sw	zero, 0x0078(k1)	/* get ready  to sleep */
+	sync
+	sw	zero, 0x007c(k1)	/* Put processor to sleep */
+	sync
+
+	/* This is where we return upon wakeup.
+	 * Reload all of the registers and return.
+	 */
+1:	nop
+	lw	k0, 0x20(sp)
+	mtc0	k0, CP0_STATUS
+	lw	k0, 0x1c(sp)
+	mtc0	k0, CP0_CONTEXT
+	lw	k0, 0x18(sp)
+	mtc0	k0, CP0_PAGEMASK
+	lw	k0, 0x14(sp)
+	mtc0	k0, CP0_CONFIG
+	lw	$1, PT_R1(sp)
+	lw	$2, PT_R2(sp)
+	lw	$3, PT_R3(sp)
+	lw	$4, PT_R4(sp)
+	lw	$5, PT_R5(sp)
+	lw	$6, PT_R6(sp)
+	lw	$7, PT_R7(sp)
+	lw	$8, PT_R8(sp)
+	lw	$9, PT_R9(sp)
+	lw	$10, PT_R10(sp)
+	lw	$11, PT_R11(sp)
+	lw	$12, PT_R12(sp)
+	lw	$13, PT_R13(sp)
+	lw	$14, PT_R14(sp)
+	lw	$15, PT_R15(sp)
+	lw	$16, PT_R16(sp)
+	lw	$17, PT_R17(sp)
+	lw	$18, PT_R18(sp)
+	lw	$19, PT_R19(sp)
+	lw	$20, PT_R20(sp)
+	lw	$21, PT_R21(sp)
+	lw	$22, PT_R22(sp)
+	lw	$23, PT_R23(sp)
+	lw	$24, PT_R24(sp)
+	lw	$25, PT_R25(sp)
+	lw	$26, PT_R26(sp)
+	lw	$27, PT_R27(sp)
+	lw	$28, PT_R28(sp)
+	lw	$29, PT_R29(sp)
+	lw	$30, PT_R30(sp)
+	lw	$31, PT_R31(sp)
+	addiu	sp, PT_SIZE
+
+	jr	ra
+END(save_and_sleep)
--- diff/arch/mips/au1000/csb250/Makefile	1970-01-01 01:00:00.000000000 +0100
+++ source/arch/mips/au1000/csb250/Makefile	2004-02-23 13:56:38.000000000 +0000
@@ -0,0 +1,18 @@
+#
+#  Copyright 2002 Cogent Computer Systems
+#     	dan@embeddededge.com
+#
+# Makefile for the Cogent CSB250 Au1500 board.  Copied from Pb1500.
+#
+# 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).
+#
+
+USE_STANDARD_AS_RULE := true
+
+O_TARGET := csb250.o
+
+obj-y := init.o board_setup.o irqmap.o
+
+include $(TOPDIR)/Rules.make
--- diff/arch/mips/au1000/csb250/board_setup.c	1970-01-01 01:00:00.000000000 +0100
+++ source/arch/mips/au1000/csb250/board_setup.c	2004-02-23 13:56:38.000000000 +0000
@@ -0,0 +1,250 @@
+/*
+ *
+ * BRIEF MODULE DESCRIPTION
+ *	Cogent CSB250 board setup.
+ *
+ * Copyright 2002 Cogent Computer Systems, Inc.
+ *	dan@embeddededge.com
+ *
+ *  This program is free software; you can redistribute  it and/or modify it
+ *  under  the terms of  the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the  License, or (at your
+ *  option) any later version.
+ *
+ *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
+ *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
+ *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
+ *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
+ *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
+ *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *  You should have received a copy of the  GNU General Public License along
+ *  with this program; if not, write  to the Free Software Foundation, Inc.,
+ *  675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/ioport.h>
+#include <linux/mm.h>
+#include <linux/console.h>
+#include <linux/mc146818rtc.h>
+#include <linux/delay.h>
+
+#include <asm/cpu.h>
+#include <asm/bootinfo.h>
+#include <asm/irq.h>
+#include <asm/keyboard.h>
+#include <asm/mipsregs.h>
+#include <asm/reboot.h>
+#include <asm/pgtable.h>
+#include <asm/au1000.h>
+#include <asm/csb250.h>
+
+#ifdef CONFIG_USB_OHCI
+// Enable the workaround for the OHCI DoneHead
+// register corruption problem.
+#define CONFIG_AU1000_OHCI_FIX
+#endif
+
+#ifdef CONFIG_RTC
+extern struct rtc_ops csb250_rtc_ops;
+#endif
+
+extern int (*board_pci_idsel)(unsigned int devsel, int assert);
+int	csb250_pci_idsel(unsigned int devsel, int assert);
+
+void __init board_setup(void)
+{
+	u32 pin_func, pin_val;
+	u32 sys_freqctrl, sys_clksrc;
+
+
+	// set AUX clock to 12MHz * 8 = 96 MHz
+	au_writel(8, SYS_AUXPLL);
+	au_writel(0, SYS_PINSTATERD);
+	udelay(100);
+
+#if defined (CONFIG_USB_OHCI) || defined (CONFIG_AU1X00_USB_DEVICE)
+
+	/* GPIO201 is input for PCMCIA card detect */
+	/* GPIO203 is input for PCMCIA interrupt request */
+	au_writel(au_readl(GPIO2_DIR) & (u32)(~((1<<1)|(1<<3))), GPIO2_DIR);
+
+	/* zero and disable FREQ2 */
+	sys_freqctrl = au_readl(SYS_FREQCTRL0);
+	sys_freqctrl &= ~0xFFF00000;
+	au_writel(sys_freqctrl, SYS_FREQCTRL0);
+
+	/* zero and disable USBH/USBD clocks */
+	sys_clksrc = au_readl(SYS_CLKSRC);
+	sys_clksrc &= ~0x00007FE0;
+	au_writel(sys_clksrc, SYS_CLKSRC);
+
+	sys_freqctrl = au_readl(SYS_FREQCTRL0);
+	sys_freqctrl &= ~0xFFF00000;
+
+	sys_clksrc = au_readl(SYS_CLKSRC);
+	sys_clksrc &= ~0x00007FE0;
+
+	// FREQ2 = aux/2 = 48 MHz
+	sys_freqctrl |= ((0<<22) | (1<<21) | (1<<20));
+	au_writel(sys_freqctrl, SYS_FREQCTRL0);
+
+	/*
+	 * Route 48MHz FREQ2 into USB Host and/or Device
+	 */
+#ifdef CONFIG_USB_OHCI
+	sys_clksrc |= ((4<<12) | (0<<11) | (0<<10));
+#endif
+#ifdef CONFIG_AU1X00_USB_DEVICE
+	sys_clksrc |= ((4<<7) | (0<<6) | (0<<5));
+#endif
+	au_writel(sys_clksrc, SYS_CLKSRC);
+
+
+	pin_func = au_readl(SYS_PINFUNC) & (u32)(~0x8000);
+#ifndef CONFIG_AU1X00_USB_DEVICE
+	// 2nd USB port is USB host
+	pin_func |= 0x8000;
+#endif
+	au_writel(pin_func, SYS_PINFUNC);
+#endif // defined (CONFIG_USB_OHCI) || defined (CONFIG_AU1X00_USB_DEVICE)
+
+	/* Configure GPIO2....it's used by PCI among other things.
+	*/
+
+	/* Make everything but GP200 (PCI RST) an input until we get
+	 * the pins set correctly.
+	 */
+	au_writel(0x00000001, GPIO2_DIR);
+
+	/* Set the pins used for output.
+	 * A zero bit will leave PCI reset, LEDs off, power up USB,
+	 * IDSEL disabled.
+	 */
+	pin_val = ((3 << 30) | (7 << 19) | (1 << 17) | (1 << 16));
+	au_writel(pin_val, GPIO2_OUTPUT);
+
+	/* Set the output direction.
+	*/
+	pin_val = ((3 << 14) | (7 << 3) | (1 << 1) | (1 << 0));
+	au_writel(pin_val, GPIO2_DIR);
+
+#ifdef CONFIG_PCI
+	/* Use FREQ1 for the PCI output clock.  We use the
+	 * CPU clock of 384 MHz divided by 12 to get 32 MHz PCI.
+	 * If Michael changes the CPU speed, we need to adjust
+	 * that here as well :-).
+	 */
+
+	/* zero and disable FREQ1
+	*/
+	sys_freqctrl = au_readl(SYS_FREQCTRL0);
+	sys_freqctrl &= ~0x000ffc00;
+	au_writel(sys_freqctrl, SYS_FREQCTRL0);
+
+	/* zero and disable PCI clock
+	*/
+	sys_clksrc = au_readl(SYS_CLKSRC);
+	sys_clksrc &= ~0x000f8000;
+	au_writel(sys_clksrc, SYS_CLKSRC);
+
+	/* Get current values (which really should match above).
+	*/
+	sys_freqctrl = au_readl(SYS_FREQCTRL0);
+	sys_freqctrl &= ~0x000ffc00;
+
+	sys_clksrc = au_readl(SYS_CLKSRC);
+	sys_clksrc &= ~0x000f8000;
+
+	/* FREQ1 = cpu/12 = 32 MHz
+	*/
+	sys_freqctrl |= ((5<<12) | (1<<11) | (0<<10));
+	au_writel(sys_freqctrl, SYS_FREQCTRL0);
+
+	/* Just connect the clock without further dividing.
+	*/
+	sys_clksrc |= ((3<<17) | (0<<16) | (0<<15));
+	au_writel(sys_clksrc, SYS_CLKSRC);
+
+	udelay(1);
+
+	/* Now that clocks should be running, take PCI out of reset.
+	*/
+	pin_val = au_readl(GPIO2_OUTPUT);
+	pin_val |= ((1 << 16) | 1);
+	au_writel(pin_val, GPIO2_OUTPUT);
+
+	// Setup PCI bus controller
+	au_writel(0, Au1500_PCI_CMEM);
+	au_writel(0x00003fff, Au1500_CFG_BASE);
+
+	/* We run big endian without any of the software byte swapping,
+	 * so configure the PCI bridge to help us out.
+	 */
+	au_writel(0xf | (2<<6) | (1<<5) | (1<<4), Au1500_PCI_CFG);
+
+	au_writel(0xf0000000, Au1500_PCI_MWMASK_DEV);
+	au_writel(0, Au1500_PCI_MWBASE_REV_CCL);
+	au_writel(0x02a00356, Au1500_PCI_STATCMD);
+	au_writel(0x00003c04, Au1500_PCI_HDRTYPE);	
+	au_writel(0x00000008, Au1500_PCI_MBAR);
+	au_sync();
+
+	board_pci_idsel = csb250_pci_idsel;
+#endif
+
+	/* Enable sys bus clock divider when IDLE state or no bus activity. */
+	au_writel(au_readl(SYS_POWERCTRL) | (0x3 << 5), SYS_POWERCTRL);
+
+#ifdef CONFIG_RTC
+	rtc_ops = &csb250_rtc_ops;
+	// Enable the RTC if not already enabled
+	if (!(au_readl(0xac000028) & 0x20)) {
+		printk("enabling clock ...\n");
+		au_writel((au_readl(0xac000028) | 0x20), 0xac000028);
+	}
+	// Put the clock in BCD mode
+	if (readl(0xac00002C) & 0x4) { /* reg B */
+		au_writel(au_readl(0xac00002c) & ~0x4, 0xac00002c);
+		au_sync();
+	}
+#endif
+}
+
+/* The IDSEL is selected in the GPIO2 register.  We will make device
+ * 12 appear in slot 0 and device 13 appear in slot 1.
+ */
+int
+csb250_pci_idsel(unsigned int devsel, int assert)
+{
+	int		retval;
+	unsigned int	gpio2_pins;
+
+	retval = 1;
+	
+	/* First, disable both selects, then assert the one requested.
+	*/
+	au_writel(0xc000c000, GPIO2_OUTPUT);
+	au_sync();
+
+	if (assert) {
+		if (devsel == 12)
+			gpio2_pins = 0x40000000;
+		else if (devsel == 13)
+			gpio2_pins = 0x80000000;
+		else {
+			gpio2_pins = 0xc000c000;
+			retval = 0;
+		}
+		au_writel(gpio2_pins, GPIO2_OUTPUT);
+	}
+	au_sync();
+
+	return retval;
+}
--- diff/arch/mips/au1000/csb250/init.c	1970-01-01 01:00:00.000000000 +0100
+++ source/arch/mips/au1000/csb250/init.c	2004-02-23 13:56:38.000000000 +0000
@@ -0,0 +1,95 @@
+/*
+ *
+ * BRIEF MODULE DESCRIPTION
+ *	Cogent CSB250 board setup
+ *
+ * Copyright 2002 Cogent Computer Systems, Inc.
+ * 	dan@embeddededge.com
+ *
+ *  This program is free software; you can redistribute  it and/or modify it
+ *  under  the terms of  the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the  License, or (at your
+ *  option) any later version.
+ *
+ *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
+ *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
+ *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
+ *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
+ *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
+ *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *  You should have received a copy of the  GNU General Public License along
+ *  with this program; if not, write  to the Free Software Foundation, Inc.,
+ *  675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/init.h>
+#include <linux/mm.h>
+#include <linux/sched.h>
+#include <linux/bootmem.h>
+#include <asm/addrspace.h>
+#include <asm/bootinfo.h>
+#include <linux/string.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+
+int prom_argc;
+char **prom_argv, **prom_envp;
+extern void  __init prom_init_cmdline(void);
+extern char *prom_getenv(char *envname);
+
+/* When we get initrd working someday.........
+*/
+int	my_initrd_start, my_initrd_size;
+
+/* Start arguments and environment.
+*/
+static char	*csb_env[2];
+static char	*csb_arg[4];
+static char	*arg1 = "console=ttyS3,38400";
+static char	*arg2 = "root=/dev/nfs rw ip=any";
+static char	*env1 = "ethaddr=00:30:23:50:00:00";
+
+const char *get_system_type(void)
+{
+	return "Cogent CSB250";
+}
+
+int __init prom_init(int argc, char **argv, char **envp, int *prom_vec)
+{
+	unsigned char *memsize_str;
+	unsigned long memsize;
+
+	/* We use a0 and a1 to pass initrd start and size.
+	*/
+	if (((uint) argc > 0) && ((uint)argv > 0)) {
+		my_initrd_start = (uint)argc;
+		my_initrd_size = (uint)argv;
+	}
+
+	/* First argv is ignored.
+	*/
+	prom_argc = 3;
+	prom_argv = csb_arg;
+	prom_envp = csb_env;
+	csb_arg[1] = arg1;
+	csb_arg[2] = arg2;
+	csb_env[0] = env1;
+
+	mips_machgroup = MACH_GROUP_ALCHEMY;
+	mips_machtype = MACH_CSB250;  
+
+	prom_init_cmdline();
+	memsize_str = prom_getenv("memsize");
+	if (!memsize_str) {
+		memsize = 0x02000000;
+	} else {
+		memsize = simple_strtol(memsize_str, NULL, 0);
+	}
+	add_memory_region(0, memsize, BOOT_MEM_RAM);
+	return 0;
+}
--- diff/arch/mips/au1000/csb250/irqmap.c	1970-01-01 01:00:00.000000000 +0100
+++ source/arch/mips/au1000/csb250/irqmap.c	2004-02-23 13:56:38.000000000 +0000
@@ -0,0 +1,100 @@
+/*
+ * BRIEF MODULE DESCRIPTION
+ *	Au1xxx irq map table
+ *
+ * Copyright 2003 Embedded Edge, LLC
+ *		dan@embeddededge.com
+ *
+ *  This program is free software; you can redistribute	 it and/or modify it
+ *  under  the terms of	 the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the	License, or (at your
+ *  option) any later version.
+ *
+ *  THIS  SOFTWARE  IS PROVIDED	  ``AS	IS'' AND   ANY	EXPRESS OR IMPLIED
+ *  WARRANTIES,	  INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
+ *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
+ *  NO	EVENT  SHALL   THE AUTHOR  BE	 LIABLE FOR ANY	  DIRECT, INDIRECT,
+ *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ *  NOT LIMITED	  TO, PROCUREMENT OF  SUBSTITUTE GOODS	OR SERVICES; LOSS OF
+ *  USE, DATA,	OR PROFITS; OR	BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ *  ANY THEORY OF LIABILITY, WHETHER IN	 CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *  You should have received a copy of the  GNU General Public License along
+ *  with this program; if not, write  to the Free Software Foundation, Inc.,
+ *  675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/irq.h>
+#include <linux/kernel_stat.h>
+#include <linux/module.h>
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/types.h>
+#include <linux/interrupt.h>
+#include <linux/ioport.h>
+#include <linux/timex.h>
+#include <linux/slab.h>
+#include <linux/random.h>
+#include <linux/delay.h>
+
+#include <asm/bitops.h>
+#include <asm/bootinfo.h>
+#include <asm/io.h>
+#include <asm/mipsregs.h>
+#include <asm/system.h>
+#include <asm/au1000.h>
+
+au1xxx_irq_map_t au1xxx_irq_map[] = {
+	{ AU1000_UART0_INT, INTC_INT_HIGH_LEVEL, 0},
+	{ AU1000_UART3_INT, INTC_INT_HIGH_LEVEL, 0},
+	{ AU1000_DMA_INT_BASE, INTC_INT_HIGH_LEVEL, 0},
+	{ AU1000_DMA_INT_BASE+1, INTC_INT_HIGH_LEVEL, 0},
+	{ AU1000_DMA_INT_BASE+2, INTC_INT_HIGH_LEVEL, 0},
+	{ AU1000_DMA_INT_BASE+3, INTC_INT_HIGH_LEVEL, 0},
+	{ AU1000_DMA_INT_BASE+4, INTC_INT_HIGH_LEVEL, 0},
+	{ AU1000_DMA_INT_BASE+5, INTC_INT_HIGH_LEVEL, 0},
+	{ AU1000_DMA_INT_BASE+6, INTC_INT_HIGH_LEVEL, 0},
+	{ AU1000_DMA_INT_BASE+7, INTC_INT_HIGH_LEVEL, 0},
+
+	{ AU1000_IRDA_TX_INT, INTC_INT_HIGH_LEVEL, 0},
+	{ AU1000_IRDA_RX_INT, INTC_INT_HIGH_LEVEL, 0},
+
+	{ AU1000_MAC0_DMA_INT, INTC_INT_HIGH_LEVEL, 0},
+	{ AU1000_MAC1_DMA_INT, INTC_INT_HIGH_LEVEL, 0},
+	{ AU1500_GPIO_204, INTC_INT_HIGH_LEVEL, 0},
+
+	{ AU1000_USB_HOST_INT, INTC_INT_LOW_LEVEL, 0 },
+
+	{ AU1000_PCI_INTA, INTC_INT_LOW_LEVEL, 0 },
+	{ AU1000_PCI_INTB, INTC_INT_LOW_LEVEL, 0 },
+	{ AU1000_PCI_INTC, INTC_INT_LOW_LEVEL, 0 },
+	{ AU1000_PCI_INTD, INTC_INT_LOW_LEVEL, 0 },
+	{ AU1500_GPIO_201, INTC_INT_LOW_LEVEL, 0 },
+	{ AU1500_GPIO_202, INTC_INT_LOW_LEVEL, 0 },
+	{ AU1500_GPIO_203, INTC_INT_LOW_LEVEL, 0 },
+	{ AU1500_GPIO_205, INTC_INT_LOW_LEVEL, 0 },
+	{ AU1500_GPIO_207, INTC_INT_LOW_LEVEL, 0 },
+
+	{ AU1000_ACSYNC_INT, INTC_INT_RISE_EDGE, 0 },
+	{ AU1000_AC97C_INT, INTC_INT_RISE_EDGE, 0 },
+	{ AU1000_TOY_INT, INTC_INT_RISE_EDGE, 0 },
+	{ AU1000_TOY_MATCH0_INT, INTC_INT_RISE_EDGE, 0 },
+	{ AU1000_TOY_MATCH1_INT, INTC_INT_RISE_EDGE, 0 },
+	{ AU1000_USB_DEV_SUS_INT, INTC_INT_RISE_EDGE, 0 },
+	{ AU1000_USB_DEV_REQ_INT, INTC_INT_RISE_EDGE, 0 },
+	{ AU1000_RTC_INT, INTC_INT_RISE_EDGE, 0 },
+	{ AU1000_RTC_MATCH0_INT, INTC_INT_RISE_EDGE, 0 },
+	{ AU1000_RTC_MATCH1_INT, INTC_INT_RISE_EDGE, 0 },
+	{ AU1000_RTC_MATCH2_INT, INTC_INT_RISE_EDGE, 0 },
+
+	/* Careful if you change match 2 request!
+	 * The interrupt handler is called directly
+	 * from the low level dispatch code.
+	 */
+	{ AU1000_TOY_MATCH2_INT, INTC_INT_RISE_EDGE, 1 },
+};
+
+int au1xxx_nr_irqs = sizeof(au1xxx_irq_map)/sizeof(au1xxx_irq_map_t);
--- diff/arch/mips/au1000/db1x00/board_setup.c	1970-01-01 01:00:00.000000000 +0100
+++ source/arch/mips/au1000/db1x00/board_setup.c	2004-02-23 13:56:38.000000000 +0000
@@ -0,0 +1,87 @@
+/*
+ *
+ * BRIEF MODULE DESCRIPTION
+ *	Alchemy Db1x00 board setup.
+ *
+ * Copyright 2000 MontaVista Software Inc.
+ * Author: MontaVista Software, Inc.
+ *         	ppopov@mvista.com or source@mvista.com
+ *
+ *  This program is free software; you can redistribute  it and/or modify it
+ *  under  the terms of  the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the  License, or (at your
+ *  option) any later version.
+ *
+ *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
+ *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
+ *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
+ *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
+ *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
+ *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *  You should have received a copy of the  GNU General Public License along
+ *  with this program; if not, write  to the Free Software Foundation, Inc.,
+ *  675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/ioport.h>
+#include <linux/mm.h>
+#include <linux/console.h>
+#include <linux/mc146818rtc.h>
+#include <linux/delay.h>
+
+#include <asm/cpu.h>
+#include <asm/bootinfo.h>
+#include <asm/irq.h>
+#include <asm/mipsregs.h>
+#include <asm/reboot.h>
+#include <asm/pgtable.h>
+#include <asm/mach-au1x00/au1000.h>
+#include <asm/mach-db1x00/db1x00.h>
+
+static BCSR * const bcsr = (BCSR *)0xAE000000;
+
+void __init board_setup(void)
+{
+	u32 pin_func;
+
+	pin_func = 0;
+#ifdef CONFIG_AU1X00_USB_DEVICE
+	// 2nd USB port is USB device
+	pin_func = au_readl(SYS_PINFUNC) & (u32)(~0x8000);
+	au_writel(pin_func, SYS_PINFUNC);
+#endif
+
+#if defined(CONFIG_IRDA) && (defined(CONFIG_SOC_AU1000) || defined(CONFIG_SOC_AU1100))
+	/* set IRFIRSEL instead of GPIO15 */
+	pin_func = au_readl(SYS_PINFUNC) | (u32)((1<<8));
+	au_writel(pin_func, SYS_PINFUNC);
+	/* power off until the driver is in use */
+	bcsr->resets &= ~BCSR_RESETS_IRDA_MODE_MASK;
+	bcsr->resets |= BCSR_RESETS_IRDA_MODE_OFF;
+	au_sync();
+#endif
+	au_writel(0, 0xAE000010); /* turn off pcmcia power */
+
+#ifdef CONFIG_MIPS_DB1000
+    printk("AMD Alchemy Au1000/Db1000 Board\n");
+#endif
+#ifdef CONFIG_MIPS_DB1500
+    printk("AMD Alchemy Au1500/Db1500 Board\n");
+#endif
+#ifdef CONFIG_MIPS_DB1100
+    printk("AMD Alchemy Au1100/Db1100 Board\n");
+#endif
+#ifdef CONFIG_MIPS_BOSPORUS
+    printk("AMD Alchemy Bosporus Board\n");
+#endif
+#ifdef CONFIG_MIPS_MIRAGE
+    printk("AMD Alchemy Mirage Board\n");
+#endif
+}
--- diff/arch/mips/au1000/db1x00/irqmap.c	1970-01-01 01:00:00.000000000 +0100
+++ source/arch/mips/au1000/db1x00/irqmap.c	2004-02-23 13:56:38.000000000 +0000
@@ -0,0 +1,123 @@
+/*
+ * BRIEF MODULE DESCRIPTION
+ *	Au1xxx irq map table
+ *
+ * Copyright 2003 Embedded Edge, LLC
+ *		dan@embeddededge.com
+ *
+ *  This program is free software; you can redistribute	 it and/or modify it
+ *  under  the terms of	 the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the	License, or (at your
+ *  option) any later version.
+ *
+ *  THIS  SOFTWARE  IS PROVIDED	  ``AS	IS'' AND   ANY	EXPRESS OR IMPLIED
+ *  WARRANTIES,	  INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
+ *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
+ *  NO	EVENT  SHALL   THE AUTHOR  BE	 LIABLE FOR ANY	  DIRECT, INDIRECT,
+ *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ *  NOT LIMITED	  TO, PROCUREMENT OF  SUBSTITUTE GOODS	OR SERVICES; LOSS OF
+ *  USE, DATA,	OR PROFITS; OR	BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ *  ANY THEORY OF LIABILITY, WHETHER IN	 CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *  You should have received a copy of the  GNU General Public License along
+ *  with this program; if not, write  to the Free Software Foundation, Inc.,
+ *  675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <linux/config.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/irq.h>
+#include <linux/kernel_stat.h>
+#include <linux/module.h>
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/types.h>
+#include <linux/interrupt.h>
+#include <linux/ioport.h>
+#include <linux/timex.h>
+#include <linux/slab.h>
+#include <linux/random.h>
+#include <linux/delay.h>
+
+#include <asm/bitops.h>
+#include <asm/bootinfo.h>
+#include <asm/io.h>
+#include <asm/mipsregs.h>
+#include <asm/system.h>
+#include <asm/mach-au1x00/au1000.h>
+
+au1xxx_irq_map_t au1xxx_irq_map[] = {
+	{ AU1000_UART0_INT, INTC_INT_HIGH_LEVEL, 0},
+	{ AU1000_UART3_INT, INTC_INT_HIGH_LEVEL, 0},
+	{ AU1000_DMA_INT_BASE, INTC_INT_HIGH_LEVEL, 0},
+	{ AU1000_DMA_INT_BASE+1, INTC_INT_HIGH_LEVEL, 0},
+	{ AU1000_DMA_INT_BASE+2, INTC_INT_HIGH_LEVEL, 0},
+	{ AU1000_DMA_INT_BASE+3, INTC_INT_HIGH_LEVEL, 0},
+	{ AU1000_DMA_INT_BASE+4, INTC_INT_HIGH_LEVEL, 0},
+	{ AU1000_DMA_INT_BASE+5, INTC_INT_HIGH_LEVEL, 0},
+	{ AU1000_DMA_INT_BASE+6, INTC_INT_HIGH_LEVEL, 0},
+	{ AU1000_DMA_INT_BASE+7, INTC_INT_HIGH_LEVEL, 0},
+
+	{ AU1000_IRDA_TX_INT, INTC_INT_HIGH_LEVEL, 0},
+	{ AU1000_IRDA_RX_INT, INTC_INT_HIGH_LEVEL, 0},
+
+	{ AU1000_MAC0_DMA_INT, INTC_INT_HIGH_LEVEL, 0},
+#if defined(CONFIG_MIPS_DB1000) || defined(CONFIG_MIPS_DB1500) || defined(CONFIG_MIPS_MIRAGE)
+	{ AU1000_MAC1_DMA_INT, INTC_INT_HIGH_LEVEL, 0},
+#endif
+#ifndef CONFIG_MIPS_MIRAGE
+	{ AU1500_GPIO_204, INTC_INT_HIGH_LEVEL, 0},
+#endif
+
+	{ AU1000_USB_HOST_INT, INTC_INT_LOW_LEVEL, 0 },
+
+#ifdef CONFIG_SOC_AU1500
+	{ AU1000_PCI_INTA, INTC_INT_LOW_LEVEL, 0 },
+	{ AU1000_PCI_INTB, INTC_INT_LOW_LEVEL, 0 },
+	{ AU1000_PCI_INTC, INTC_INT_LOW_LEVEL, 0 },
+	{ AU1000_PCI_INTD, INTC_INT_LOW_LEVEL, 0 },
+#endif
+
+#ifdef CONFIG_MIPS_DB1500
+	{ AU1500_GPIO_201, INTC_INT_LOW_LEVEL, 0 },
+	{ AU1500_GPIO_202, INTC_INT_LOW_LEVEL, 0 },
+	{ AU1500_GPIO_203, INTC_INT_LOW_LEVEL, 0 },
+	{ AU1500_GPIO_205, INTC_INT_LOW_LEVEL, 0 },
+	{ AU1500_GPIO_207, INTC_INT_LOW_LEVEL, 0 },
+#endif
+
+#ifndef CONFIG_MIPS_MIRAGE
+	{ AU1000_GPIO_0, INTC_INT_LOW_LEVEL, 0 }, // PCMCIA Card 0 Fully_Interted#
+	{ AU1000_GPIO_1, INTC_INT_LOW_LEVEL, 0 }, // PCMCIA Card 0 STSCHG#
+	{ AU1000_GPIO_2, INTC_INT_LOW_LEVEL, 0 }, // PCMCIA Card 0 IRQ#
+
+	{ AU1000_GPIO_3, INTC_INT_LOW_LEVEL, 0 }, // PCMCIA Card 1 Fully_Interted#
+	{ AU1000_GPIO_4, INTC_INT_LOW_LEVEL, 0 }, // PCMCIA Card 1 STSCHG#
+	{ AU1000_GPIO_5, INTC_INT_LOW_LEVEL, 0 }, // PCMCIA Card 1 IRQ#
+#endif
+
+	{ AU1000_GPIO_2, INTC_INT_LOW_LEVEL, 0 }, // PCMCIA Card 0 IRQ#
+	{ AU1000_GPIO_5, INTC_INT_LOW_LEVEL, 0 }, // PCMCIA Card 1 IRQ#
+
+	{ AU1000_ACSYNC_INT, INTC_INT_RISE_EDGE, 0 },
+	{ AU1000_AC97C_INT, INTC_INT_RISE_EDGE, 0 },
+	{ AU1000_TOY_INT, INTC_INT_RISE_EDGE, 0 },
+	{ AU1000_TOY_MATCH0_INT, INTC_INT_RISE_EDGE, 0 },
+	{ AU1000_TOY_MATCH1_INT, INTC_INT_RISE_EDGE, 0 },
+	{ AU1000_USB_DEV_SUS_INT, INTC_INT_RISE_EDGE, 0 },
+	{ AU1000_USB_DEV_REQ_INT, INTC_INT_RISE_EDGE, 0 },
+	{ AU1000_RTC_INT, INTC_INT_RISE_EDGE, 0 },
+	{ AU1000_RTC_MATCH0_INT, INTC_INT_RISE_EDGE, 0 },
+	{ AU1000_RTC_MATCH1_INT, INTC_INT_RISE_EDGE, 0 },
+	{ AU1000_RTC_MATCH2_INT, INTC_INT_RISE_EDGE, 0 },
+
+	/* Careful if you change match 2 request!
+	 * The interrupt handler is called directly
+	 * from the low level dispatch code.
+	 */
+	{ AU1000_TOY_MATCH2_INT, INTC_INT_RISE_EDGE, 1 },
+};
+
+int au1xxx_nr_irqs = sizeof(au1xxx_irq_map)/sizeof(au1xxx_irq_map_t);
--- diff/arch/mips/au1000/hydrogen3/Makefile	1970-01-01 01:00:00.000000000 +0100
+++ source/arch/mips/au1000/hydrogen3/Makefile	2004-02-23 13:56:38.000000000 +0000
@@ -0,0 +1,22 @@
+#
+#  Copyright 2000 MontaVista Software Inc.
+#  Author: MontaVista Software, Inc.
+#     	ppopov@mvista.com or source@mvista.com
+#
+# Makefile for the Alchemy Semiconductor PB1000 board.
+#
+# 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).
+#
+
+.S.s:
+	$(CPP) $(CFLAGS) $< -o $*.s
+.S.o:
+	$(CC) $(CFLAGS) -c $< -o $*.o
+
+O_TARGET := hydrogen3.o
+
+obj-y := init.o board_setup.o irqmap.o
+
+include $(TOPDIR)/Rules.make
--- diff/arch/mips/au1000/hydrogen3/board_setup.c	1970-01-01 01:00:00.000000000 +0100
+++ source/arch/mips/au1000/hydrogen3/board_setup.c	2004-02-23 13:56:38.000000000 +0000
@@ -0,0 +1,71 @@
+/*
+ *
+ * BRIEF MODULE DESCRIPTION
+ *	Alchemy Db1x00 board setup.
+ *
+ * Copyright 2000 MontaVista Software Inc.
+ * Author: MontaVista Software, Inc.
+ *         	ppopov@mvista.com or source@mvista.com
+ *
+ *  This program is free software; you can redistribute  it and/or modify it
+ *  under  the terms of  the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the  License, or (at your
+ *  option) any later version.
+ *
+ *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
+ *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
+ *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
+ *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
+ *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
+ *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *  You should have received a copy of the  GNU General Public License along
+ *  with this program; if not, write  to the Free Software Foundation, Inc.,
+ *  675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/ioport.h>
+#include <linux/mm.h>
+#include <linux/console.h>
+#include <linux/mc146818rtc.h>
+#include <linux/delay.h>
+
+#include <asm/cpu.h>
+#include <asm/bootinfo.h>
+#include <asm/irq.h>
+#include <asm/keyboard.h>
+#include <asm/mipsregs.h>
+#include <asm/reboot.h>
+#include <asm/pgtable.h>
+#include <asm/au1000.h>
+#include <asm/db1x00.h>
+
+extern struct rtc_ops no_rtc_ops;
+
+void __init board_setup(void)
+{
+	u32 pin_func;
+
+	rtc_ops = &no_rtc_ops;
+
+#ifdef CONFIG_AU1X00_USB_DEVICE
+	// 2nd USB port is USB device
+	pin_func = au_readl(SYS_PINFUNC) & (u32)(~0x8000);
+	au_writel(pin_func, SYS_PINFUNC);
+#endif
+
+#if defined(CONFIG_IRDA) && (defined(CONFIG_SOC_AU1000) || defined(CONFIG_SOC_AU1100))
+	/* set IRFIRSEL instead of GPIO15 */
+	pin_func = au_readl(SYS_PINFUNC) | (u32)((1<<8));
+	au_writel(pin_func, SYS_PINFUNC);
+	au_sync();
+#endif
+
+    printk("AMD Alchemy Hydrogen3 Board\n");
+}
--- diff/arch/mips/au1000/hydrogen3/init.c	1970-01-01 01:00:00.000000000 +0100
+++ source/arch/mips/au1000/hydrogen3/init.c	2004-02-23 13:56:38.000000000 +0000
@@ -0,0 +1,77 @@
+/*
+ *
+ * BRIEF MODULE DESCRIPTION
+ *	PB1000 board setup
+ *
+ * Copyright 2001 MontaVista Software Inc.
+ * Author: MontaVista Software, Inc.
+ *         	ppopov@mvista.com or source@mvista.com
+ *
+ *  This program is free software; you can redistribute  it and/or modify it
+ *  under  the terms of  the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the  License, or (at your
+ *  option) any later version.
+ *
+ *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
+ *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
+ *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
+ *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
+ *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
+ *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *  You should have received a copy of the  GNU General Public License along
+ *  with this program; if not, write  to the Free Software Foundation, Inc.,
+ *  675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/init.h>
+#include <linux/mm.h>
+#include <linux/sched.h>
+#include <linux/bootmem.h>
+#include <asm/addrspace.h>
+#include <asm/bootinfo.h>
+#include <linux/config.h>
+#include <linux/string.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+
+int prom_argc;
+char **prom_argv, **prom_envp;
+extern void  __init prom_init_cmdline(void);
+extern char *prom_getenv(char *envname);
+
+const char *get_system_type(void)
+{
+#ifdef CONFIG_MIPS_BOSPORUS
+	return "Alchemy Bosporus Gateway Reference";
+#else
+	return "Alchemy Db1x00";
+#endif
+}
+
+int __init prom_init(int argc, char **argv, char **envp, int *prom_vec)
+{
+	unsigned char *memsize_str;
+	unsigned long memsize;
+
+	prom_argc = argc;
+	prom_argv = argv;
+	prom_envp = envp;
+
+	mips_machgroup = MACH_GROUP_ALCHEMY;
+	mips_machtype = MACH_DB1000;	/* set the platform # */   
+	prom_init_cmdline();
+
+	memsize_str = prom_getenv("memsize");
+	if (!memsize_str) {
+		memsize = 0x04000000;
+	} else {
+		memsize = simple_strtol(memsize_str, NULL, 0);
+	}
+	add_memory_region(0, memsize, BOOT_MEM_RAM);
+	return 0;
+}
--- diff/arch/mips/au1000/hydrogen3/irqmap.c	1970-01-01 01:00:00.000000000 +0100
+++ source/arch/mips/au1000/hydrogen3/irqmap.c	2004-02-23 13:56:38.000000000 +0000
@@ -0,0 +1,90 @@
+/*
+ * BRIEF MODULE DESCRIPTION
+ *	Au1xxx irq map table
+ *
+ * Copyright 2003 Embedded Edge, LLC
+ *		dan@embeddededge.com
+ *
+ *  This program is free software; you can redistribute	 it and/or modify it
+ *  under  the terms of	 the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the	License, or (at your
+ *  option) any later version.
+ *
+ *  THIS  SOFTWARE  IS PROVIDED	  ``AS	IS'' AND   ANY	EXPRESS OR IMPLIED
+ *  WARRANTIES,	  INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
+ *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
+ *  NO	EVENT  SHALL   THE AUTHOR  BE	 LIABLE FOR ANY	  DIRECT, INDIRECT,
+ *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ *  NOT LIMITED	  TO, PROCUREMENT OF  SUBSTITUTE GOODS	OR SERVICES; LOSS OF
+ *  USE, DATA,	OR PROFITS; OR	BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ *  ANY THEORY OF LIABILITY, WHETHER IN	 CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *  You should have received a copy of the  GNU General Public License along
+ *  with this program; if not, write  to the Free Software Foundation, Inc.,
+ *  675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/irq.h>
+#include <linux/kernel_stat.h>
+#include <linux/module.h>
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/types.h>
+#include <linux/interrupt.h>
+#include <linux/ioport.h>
+#include <linux/timex.h>
+#include <linux/slab.h>
+#include <linux/random.h>
+#include <linux/delay.h>
+
+#include <asm/bitops.h>
+#include <asm/bootinfo.h>
+#include <asm/io.h>
+#include <asm/mipsregs.h>
+#include <asm/system.h>
+#include <asm/au1000.h>
+
+au1xxx_irq_map_t au1xxx_irq_map[] = {
+	{ AU1000_UART0_INT, INTC_INT_HIGH_LEVEL, 0},
+	{ AU1000_UART3_INT, INTC_INT_HIGH_LEVEL, 0},
+	{ AU1000_DMA_INT_BASE, INTC_INT_HIGH_LEVEL, 0},
+	{ AU1000_DMA_INT_BASE+1, INTC_INT_HIGH_LEVEL, 0},
+	{ AU1000_DMA_INT_BASE+2, INTC_INT_HIGH_LEVEL, 0},
+	{ AU1000_DMA_INT_BASE+3, INTC_INT_HIGH_LEVEL, 0},
+	{ AU1000_DMA_INT_BASE+4, INTC_INT_HIGH_LEVEL, 0},
+	{ AU1000_DMA_INT_BASE+5, INTC_INT_HIGH_LEVEL, 0},
+	{ AU1000_DMA_INT_BASE+6, INTC_INT_HIGH_LEVEL, 0},
+	{ AU1000_DMA_INT_BASE+7, INTC_INT_HIGH_LEVEL, 0},
+
+	{ AU1000_IRDA_TX_INT, INTC_INT_HIGH_LEVEL, 0},
+	{ AU1000_IRDA_RX_INT, INTC_INT_HIGH_LEVEL, 0},
+
+	{ AU1000_MAC0_DMA_INT, INTC_INT_HIGH_LEVEL, 0},
+
+	{ AU1000_USB_HOST_INT, INTC_INT_LOW_LEVEL, 0 },
+
+//	{ AU1500_GPIO_205, INTC_INT_LOW_LEVEL, 0 },
+
+	{ AU1000_ACSYNC_INT, INTC_INT_RISE_EDGE, 0 },
+	{ AU1000_AC97C_INT, INTC_INT_RISE_EDGE, 0 },
+	{ AU1000_TOY_INT, INTC_INT_RISE_EDGE, 0 },
+	{ AU1000_TOY_MATCH0_INT, INTC_INT_RISE_EDGE, 0 },
+	{ AU1000_TOY_MATCH1_INT, INTC_INT_RISE_EDGE, 0 },
+	{ AU1000_USB_DEV_SUS_INT, INTC_INT_RISE_EDGE, 0 },
+	{ AU1000_USB_DEV_REQ_INT, INTC_INT_RISE_EDGE, 0 },
+	{ AU1000_RTC_INT, INTC_INT_RISE_EDGE, 0 },
+	{ AU1000_RTC_MATCH0_INT, INTC_INT_RISE_EDGE, 0 },
+	{ AU1000_RTC_MATCH1_INT, INTC_INT_RISE_EDGE, 0 },
+	{ AU1000_RTC_MATCH2_INT, INTC_INT_RISE_EDGE, 0 },
+
+	/* Careful if you change match 2 request!
+	 * The interrupt handler is called directly
+	 * from the low level dispatch code.
+	 */
+	{ AU1000_TOY_MATCH2_INT, INTC_INT_RISE_EDGE, 1 },
+};
+
+int au1xxx_nr_irqs = sizeof(au1xxx_irq_map)/sizeof(au1xxx_irq_map_t);
--- diff/arch/mips/au1000/mtx-1/Makefile	1970-01-01 01:00:00.000000000 +0100
+++ source/arch/mips/au1000/mtx-1/Makefile	2004-02-23 13:56:38.000000000 +0000
@@ -0,0 +1,14 @@
+#
+#  Copyright 2003 MontaVista Software Inc.
+#  Author: MontaVista Software, Inc.
+#     	ppopov@mvista.com or source@mvista.com
+#       Bruno Randolf <bruno.randolf@4g-systems.biz>
+#
+# Makefile for 4G Systems MTX-1 board.
+#
+# 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).
+#
+
+lib-y := init.o board_setup.o irqmap.o
--- diff/arch/mips/au1000/mtx-1/board_setup.c	1970-01-01 01:00:00.000000000 +0100
+++ source/arch/mips/au1000/mtx-1/board_setup.c	2004-02-23 13:56:38.000000000 +0000
@@ -0,0 +1,89 @@
+/*
+ *
+ * BRIEF MODULE DESCRIPTION
+ *	4G Systems MTX-1 board setup.
+ *
+ * Copyright 2003 MontaVista Software Inc.
+ * Author: MontaVista Software, Inc.
+ *         	ppopov@mvista.com or source@mvista.com
+ *         Bruno Randolf <bruno.randolf@4g-systems.biz>
+ *
+ *  This program is free software; you can redistribute  it and/or modify it
+ *  under  the terms of  the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the  License, or (at your
+ *  option) any later version.
+ *
+ *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
+ *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
+ *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
+ *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
+ *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
+ *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *  You should have received a copy of the  GNU General Public License along
+ *  with this program; if not, write  to the Free Software Foundation, Inc.,
+ *  675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/ioport.h>
+#include <linux/mm.h>
+#include <linux/console.h>
+#include <linux/mc146818rtc.h>
+#include <linux/delay.h>
+
+#include <asm/cpu.h>
+#include <asm/bootinfo.h>
+#include <asm/irq.h>
+#include <asm/keyboard.h>
+#include <asm/mipsregs.h>
+#include <asm/reboot.h>
+#include <asm/pgtable.h>
+#include <asm/au1000.h>
+
+extern struct rtc_ops no_rtc_ops;
+
+void __init board_setup(void)
+{
+	rtc_ops = &no_rtc_ops;
+
+#if defined (CONFIG_USB_OHCI) || defined (CONFIG_AU1X00_USB_DEVICE)
+#ifdef CONFIG_AU1X00_USB_DEVICE
+	// 2nd USB port is USB device
+	au_writel(au_readl(SYS_PINFUNC) & (u32)(~0x8000), SYS_PINFUNC);
+#endif
+	// enable USB power switch
+	au_writel( au_readl(GPIO2_DIR) | 0x10, GPIO2_DIR );
+	au_writel( 0x100000, GPIO2_OUTPUT );
+#endif // defined (CONFIG_USB_OHCI) || defined (CONFIG_AU1000_USB_DEVICE)
+
+#ifdef CONFIG_PCI
+#if defined(__MIPSEB__)
+	au_writel(0xf | (2<<6) | (1<<4), Au1500_PCI_CFG);
+#else
+	au_writel(0xf, Au1500_PCI_CFG);
+#endif
+#endif
+
+	// initialize sys_pinfunc:
+	// disable second ethernet port (SYS_PF_NI2)
+	// set U3/GPIO23 to GPIO23 (SYS_PF_U3)
+	au_writel( SYS_PF_NI2 | SYS_PF_U3, SYS_PINFUNC );
+
+	// initialize GPIO
+	au_writel( 0xFFFFFFFF, SYS_TRIOUTCLR );
+	au_writel( 0x00000001, SYS_OUTPUTCLR ); // set M66EN (PCI 66MHz) to OFF
+	au_writel( 0x00000008, SYS_OUTPUTSET ); // set PCI CLKRUN# to OFF
+	au_writel( 0x00000020, SYS_OUTPUTCLR ); // set eth PHY TX_ER to OFF
+
+	// enable LED and set it to green
+	au_writel( au_readl(GPIO2_DIR) | 0x1800, GPIO2_DIR );
+	au_writel( 0x18000800, GPIO2_OUTPUT );
+
+	printk("4G Systems MTX-1 Board\n");
+}
--- diff/arch/mips/au1000/mtx-1/init.c	1970-01-01 01:00:00.000000000 +0100
+++ source/arch/mips/au1000/mtx-1/init.c	2004-02-23 13:56:38.000000000 +0000
@@ -0,0 +1,74 @@
+/*
+ *
+ * BRIEF MODULE DESCRIPTION
+ *	4G Systems MTX-1 board setup
+ *
+ * Copyright 2003 MontaVista Software Inc.
+ * Author: MontaVista Software, Inc.
+ *         	ppopov@mvista.com or source@mvista.com
+ *         Bruno Randolf <bruno.randolf@4g-systems.biz>
+ *
+ *  This program is free software; you can redistribute  it and/or modify it
+ *  under  the terms of  the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the  License, or (at your
+ *  option) any later version.
+ *
+ *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
+ *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
+ *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
+ *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
+ *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
+ *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *  You should have received a copy of the  GNU General Public License along
+ *  with this program; if not, write  to the Free Software Foundation, Inc.,
+ *  675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/init.h>
+#include <linux/mm.h>
+#include <linux/sched.h>
+#include <linux/bootmem.h>
+#include <asm/addrspace.h>
+#include <asm/bootinfo.h>
+#include <linux/config.h>
+#include <linux/string.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+
+int prom_argc;
+char **prom_argv, **prom_envp;
+extern void  __init prom_init_cmdline(void);
+extern char *prom_getenv(char *envname);
+
+const char *get_system_type(void)
+{
+	return "MTX-1";
+}
+
+int __init prom_init(int argc, char **argv, char **envp, int *prom_vec)
+{
+	unsigned char *memsize_str;
+	unsigned long memsize;
+
+	prom_argc = argc;
+	prom_argv = argv;
+	prom_envp = envp;
+
+	mips_machgroup = MACH_GROUP_ALCHEMY;
+	mips_machtype = MACH_MTX1;	/* set the platform # */
+	prom_init_cmdline();
+
+	memsize_str = prom_getenv("memsize");
+	if (!memsize_str) {
+		memsize = 0x04000000;
+	} else {
+		memsize = simple_strtol(memsize_str, NULL, 0);
+	}
+	add_memory_region(0, memsize, BOOT_MEM_RAM);
+	return 0;
+}
--- diff/arch/mips/au1000/mtx-1/irqmap.c	1970-01-01 01:00:00.000000000 +0100
+++ source/arch/mips/au1000/mtx-1/irqmap.c	2004-02-23 13:56:38.000000000 +0000
@@ -0,0 +1,93 @@
+/*
+ * BRIEF MODULE DESCRIPTION
+ *	Au1xxx irq map table
+ *
+ * Copyright 2003 Embedded Edge, LLC
+ *		dan@embeddededge.com
+ *
+ *  This program is free software; you can redistribute	 it and/or modify it
+ *  under  the terms of	 the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the	License, or (at your
+ *  option) any later version.
+ *
+ *  THIS  SOFTWARE  IS PROVIDED	  ``AS	IS'' AND   ANY	EXPRESS OR IMPLIED
+ *  WARRANTIES,	  INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
+ *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
+ *  NO	EVENT  SHALL   THE AUTHOR  BE	 LIABLE FOR ANY	  DIRECT, INDIRECT,
+ *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ *  NOT LIMITED	  TO, PROCUREMENT OF  SUBSTITUTE GOODS	OR SERVICES; LOSS OF
+ *  USE, DATA,	OR PROFITS; OR	BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ *  ANY THEORY OF LIABILITY, WHETHER IN	 CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *  You should have received a copy of the  GNU General Public License along
+ *  with this program; if not, write  to the Free Software Foundation, Inc.,
+ *  675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/irq.h>
+#include <linux/kernel_stat.h>
+#include <linux/module.h>
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/types.h>
+#include <linux/interrupt.h>
+#include <linux/ioport.h>
+#include <linux/timex.h>
+#include <linux/slab.h>
+#include <linux/random.h>
+#include <linux/delay.h>
+
+#include <asm/bitops.h>
+#include <asm/bootinfo.h>
+#include <asm/io.h>
+#include <asm/mipsregs.h>
+#include <asm/system.h>
+#include <asm/au1000.h>
+
+au1xxx_irq_map_t au1xxx_irq_map[] = {
+	{ AU1000_UART0_INT, INTC_INT_HIGH_LEVEL, 0},
+
+	{ AU1000_DMA_INT_BASE, INTC_INT_HIGH_LEVEL, 0},
+	{ AU1000_DMA_INT_BASE+1, INTC_INT_HIGH_LEVEL, 0},
+	{ AU1000_DMA_INT_BASE+2, INTC_INT_HIGH_LEVEL, 0},
+	{ AU1000_DMA_INT_BASE+3, INTC_INT_HIGH_LEVEL, 0},
+	{ AU1000_DMA_INT_BASE+4, INTC_INT_HIGH_LEVEL, 0},
+	{ AU1000_DMA_INT_BASE+5, INTC_INT_HIGH_LEVEL, 0},
+	{ AU1000_DMA_INT_BASE+6, INTC_INT_HIGH_LEVEL, 0},
+	{ AU1000_DMA_INT_BASE+7, INTC_INT_HIGH_LEVEL, 0},
+
+	{ AU1000_MAC0_DMA_INT, INTC_INT_HIGH_LEVEL, 0},
+
+	{ AU1000_USB_HOST_INT, INTC_INT_LOW_LEVEL, 0 },
+
+	{ AU1000_PCI_INTA, INTC_INT_LOW_LEVEL, 0 },
+	{ AU1000_PCI_INTB, INTC_INT_LOW_LEVEL, 0 },
+	{ AU1000_PCI_INTC, INTC_INT_LOW_LEVEL, 0 },
+	{ AU1000_PCI_INTD, INTC_INT_LOW_LEVEL, 0 },
+
+	{ AU1000_ACSYNC_INT, INTC_INT_RISE_EDGE, 0 },
+	{ AU1000_AC97C_INT, INTC_INT_RISE_EDGE, 0 },
+
+	{ AU1000_TOY_INT, INTC_INT_RISE_EDGE, 0 },
+	{ AU1000_TOY_MATCH0_INT, INTC_INT_RISE_EDGE, 0 },
+	{ AU1000_TOY_MATCH1_INT, INTC_INT_RISE_EDGE, 0 },
+
+	{ AU1000_USB_DEV_SUS_INT, INTC_INT_RISE_EDGE, 0 },
+	{ AU1000_USB_DEV_REQ_INT, INTC_INT_RISE_EDGE, 0 },
+
+	{ AU1000_RTC_INT, INTC_INT_RISE_EDGE, 0 },
+	{ AU1000_RTC_MATCH0_INT, INTC_INT_RISE_EDGE, 0 },
+	{ AU1000_RTC_MATCH1_INT, INTC_INT_RISE_EDGE, 0 },
+	{ AU1000_RTC_MATCH2_INT, INTC_INT_RISE_EDGE, 0 },
+
+	/* Careful if you change match 2 request!
+	 * The interrupt handler is called directly
+	 * from the low level dispatch code.
+	 */
+	{ AU1000_TOY_MATCH2_INT, INTC_INT_RISE_EDGE, 1 },
+};
+
+int au1xxx_nr_irqs = sizeof(au1xxx_irq_map)/sizeof(au1xxx_irq_map_t);
--- diff/arch/mips/au1000/pb1000/board_setup.c	1970-01-01 01:00:00.000000000 +0100
+++ source/arch/mips/au1000/pb1000/board_setup.c	2004-02-23 13:56:38.000000000 +0000
@@ -0,0 +1,186 @@
+/*
+ * Copyright 2000 MontaVista Software Inc.
+ * Author: MontaVista Software, Inc.
+ *         	ppopov@mvista.com or source@mvista.com
+ *
+ *  This program is free software; you can redistribute  it and/or modify it
+ *  under  the terms of  the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the  License, or (at your
+ *  option) any later version.
+ *
+ *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
+ *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
+ *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
+ *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
+ *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
+ *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *  You should have received a copy of the  GNU General Public License along
+ *  with this program; if not, write  to the Free Software Foundation, Inc.,
+ *  675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/ioport.h>
+#include <linux/mm.h>
+#include <linux/console.h>
+#include <linux/delay.h>
+
+#include <asm/cpu.h>
+#include <asm/bootinfo.h>
+#include <asm/irq.h>
+#include <asm/mipsregs.h>
+#include <asm/reboot.h>
+#include <asm/pgtable.h>
+#include <asm/au1000.h>
+#include <asm/pb1000.h>
+
+#ifdef CONFIG_USB_OHCI
+// Enable the workaround for the OHCI DoneHead
+// register corruption problem.
+#define CONFIG_AU1000_OHCI_FIX
+        ^^^^^^^^^^^^^^^^^^^^^^
+    !!! I shall not define symbols starting with CONFIG_ !!!
+#endif
+
+void __init board_setup(void)
+{
+	u32 pin_func, static_cfg0;
+	u32 sys_freqctrl, sys_clksrc;
+	u32 prid = read_c0_prid();
+
+	// set AUX clock to 12MHz * 8 = 96 MHz
+	au_writel(8, SYS_AUXPLL);
+	au_writel(0, SYS_PINSTATERD);
+	udelay(100);
+
+#if defined (CONFIG_USB_OHCI) || defined (CONFIG_AU1X00_USB_DEVICE)
+	/* zero and disable FREQ2 */
+	sys_freqctrl = au_readl(SYS_FREQCTRL0);
+	sys_freqctrl &= ~0xFFF00000;
+	au_writel(sys_freqctrl, SYS_FREQCTRL0);
+
+	/* zero and disable USBH/USBD clocks */
+	sys_clksrc = au_readl(SYS_CLKSRC);
+	sys_clksrc &= ~0x00007FE0;
+	au_writel(sys_clksrc, SYS_CLKSRC);
+
+	sys_freqctrl = au_readl(SYS_FREQCTRL0);
+	sys_freqctrl &= ~0xFFF00000;
+
+	sys_clksrc = au_readl(SYS_CLKSRC);
+	sys_clksrc &= ~0x00007FE0;
+
+	switch (prid & 0x000000FF)
+	{
+	case 0x00: /* DA */
+	case 0x01: /* HA */
+	case 0x02: /* HB */
+	/* CPU core freq to 48MHz to slow it way down... */
+	au_writel(4, SYS_CPUPLL);
+
+	/*
+	 * Setup 48MHz FREQ2 from CPUPLL for USB Host
+	 */
+	/* FRDIV2=3 -> div by 8 of 384MHz -> 48MHz */
+	sys_freqctrl |= ((3<<22) | (1<<21) | (0<<20));
+	au_writel(sys_freqctrl, SYS_FREQCTRL0);
+
+	/* CPU core freq to 384MHz */
+	au_writel(0x20, SYS_CPUPLL);
+
+	printk("Au1000: 48MHz OHCI workaround enabled\n");
+		break;
+
+	default:  /* HC and newer */
+	// FREQ2 = aux/2 = 48 MHz
+	sys_freqctrl |= ((0<<22) | (1<<21) | (1<<20));
+	au_writel(sys_freqctrl, SYS_FREQCTRL0);
+		break;
+	}
+
+	/*
+	 * Route 48MHz FREQ2 into USB Host and/or Device
+	 */
+#ifdef CONFIG_USB_OHCI
+	sys_clksrc |= ((4<<12) | (0<<11) | (0<<10));
+#endif
+#ifdef CONFIG_AU1X00_USB_DEVICE
+	sys_clksrc |= ((4<<7) | (0<<6) | (0<<5));
+#endif
+	au_writel(sys_clksrc, SYS_CLKSRC);
+
+	// configure pins GPIO[14:9] as GPIO
+	pin_func = au_readl(SYS_PINFUNC) & (u32)(~0x8080);
+
+#ifndef CONFIG_AU1X00_USB_DEVICE
+	// 2nd USB port is USB host
+	pin_func |= 0x8000;
+#endif
+	au_writel(pin_func, SYS_PINFUNC);
+	au_writel(0x2800, SYS_TRIOUTCLR);
+	au_writel(0x0030, SYS_OUTPUTCLR);
+#endif // defined (CONFIG_USB_OHCI) || defined (CONFIG_AU1X00_USB_DEVICE)
+
+	// make gpio 15 an input (for interrupt line)
+	pin_func = au_readl(SYS_PINFUNC) & (u32)(~0x100);
+	// we don't need I2S, so make it available for GPIO[31:29]
+	pin_func |= (1<<5);
+	au_writel(pin_func, SYS_PINFUNC);
+
+	au_writel(0x8000, SYS_TRIOUTCLR);
+
+	static_cfg0 = au_readl(MEM_STCFG0) & (u32)(~0xc00);
+	au_writel(static_cfg0, MEM_STCFG0);
+
+	// configure RCE2* for LCD
+	au_writel(0x00000004, MEM_STCFG2);
+
+	// MEM_STTIME2
+	au_writel(0x09000000, MEM_STTIME2);
+
+	// Set 32-bit base address decoding for RCE2*
+	au_writel(0x10003ff0, MEM_STADDR2);
+
+	// PCI CPLD setup
+	// expand CE0 to cover PCI
+	au_writel(0x11803e40, MEM_STADDR1);
+
+	// burst visibility on
+	au_writel(au_readl(MEM_STCFG0) | 0x1000, MEM_STCFG0);
+
+	au_writel(0x83, MEM_STCFG1);         // ewait enabled, flash timing
+	au_writel(0x33030a10, MEM_STTIME1);   // slower timing for FPGA
+
+	/* setup the static bus controller */
+	au_writel(0x00000002, MEM_STCFG3);  /* type = PCMCIA */
+	au_writel(0x280E3D07, MEM_STTIME3); /* 250ns cycle time */
+	au_writel(0x10000000, MEM_STADDR3); /* any PCMCIA select */
+
+#ifdef CONFIG_PCI
+	au_writel(0, PCI_BRIDGE_CONFIG); // set extend byte to 0
+	au_writel(0, SDRAM_MBAR);        // set mbar to 0
+	au_writel(0x2, SDRAM_CMD);       // enable memory accesses
+	au_sync_delay(1);
+#endif
+
+	/* Enable Au1000 BCLK switching - note: sed1356 must not use
+	 * its BCLK (Au1000 LCLK) for any timings */
+	switch (prid & 0x000000FF)
+	{
+	case 0x00: /* DA */
+	case 0x01: /* HA */
+	case 0x02: /* HB */
+		break;
+	default:  /* HC and newer */
+		/* Enable sys bus clock divider when IDLE state or no bus 
+		   activity. */
+		au_writel(au_readl(SYS_POWERCTRL) | (0x3 << 5), SYS_POWERCTRL);
+		break;
+	}
+}
--- diff/arch/mips/au1000/pb1000/irqmap.c	1970-01-01 01:00:00.000000000 +0100
+++ source/arch/mips/au1000/pb1000/irqmap.c	2004-02-23 13:56:38.000000000 +0000
@@ -0,0 +1,96 @@
+/*
+ * BRIEF MODULE DESCRIPTION
+ *	Au1xxx irq map table
+ *
+ * Copyright 2003 Embedded Edge, LLC
+ *		dan@embeddededge.com
+ *
+ *  This program is free software; you can redistribute	 it and/or modify it
+ *  under  the terms of	 the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the	License, or (at your
+ *  option) any later version.
+ *
+ *  THIS  SOFTWARE  IS PROVIDED	  ``AS	IS'' AND   ANY	EXPRESS OR IMPLIED
+ *  WARRANTIES,	  INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
+ *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
+ *  NO	EVENT  SHALL   THE AUTHOR  BE	 LIABLE FOR ANY	  DIRECT, INDIRECT,
+ *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ *  NOT LIMITED	  TO, PROCUREMENT OF  SUBSTITUTE GOODS	OR SERVICES; LOSS OF
+ *  USE, DATA,	OR PROFITS; OR	BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ *  ANY THEORY OF LIABILITY, WHETHER IN	 CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *  You should have received a copy of the  GNU General Public License along
+ *  with this program; if not, write  to the Free Software Foundation, Inc.,
+ *  675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/irq.h>
+#include <linux/kernel_stat.h>
+#include <linux/module.h>
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/types.h>
+#include <linux/interrupt.h>
+#include <linux/ioport.h>
+#include <linux/timex.h>
+#include <linux/slab.h>
+#include <linux/random.h>
+#include <linux/delay.h>
+
+#include <asm/bitops.h>
+#include <asm/bootinfo.h>
+#include <asm/io.h>
+#include <asm/mipsregs.h>
+#include <asm/system.h>
+#include <asm/au1000.h>
+
+au1xxx_irq_map_t au1xxx_irq_map[] = {
+	{ AU1000_UART0_INT, INTC_INT_HIGH_LEVEL, 0},
+	{ AU1000_UART1_INT, INTC_INT_HIGH_LEVEL, 0},
+	{ AU1000_UART2_INT, INTC_INT_HIGH_LEVEL, 0},
+	{ AU1000_UART3_INT, INTC_INT_HIGH_LEVEL, 0},
+	{ AU1000_SSI0_INT, INTC_INT_HIGH_LEVEL, 0},
+	{ AU1000_SSI1_INT, INTC_INT_HIGH_LEVEL, 0},
+
+	{ AU1000_DMA_INT_BASE, INTC_INT_HIGH_LEVEL, 0},
+	{ AU1000_DMA_INT_BASE+1, INTC_INT_HIGH_LEVEL, 0},
+	{ AU1000_DMA_INT_BASE+2, INTC_INT_HIGH_LEVEL, 0},
+	{ AU1000_DMA_INT_BASE+3, INTC_INT_HIGH_LEVEL, 0},
+	{ AU1000_DMA_INT_BASE+4, INTC_INT_HIGH_LEVEL, 0},
+	{ AU1000_DMA_INT_BASE+5, INTC_INT_HIGH_LEVEL, 0},
+	{ AU1000_DMA_INT_BASE+6, INTC_INT_HIGH_LEVEL, 0},
+	{ AU1000_DMA_INT_BASE+7, INTC_INT_HIGH_LEVEL, 0},
+
+	{ AU1000_IRDA_TX_INT, INTC_INT_HIGH_LEVEL, 0},
+	{ AU1000_IRDA_RX_INT, INTC_INT_HIGH_LEVEL, 0},
+
+	{ AU1000_MAC0_DMA_INT, INTC_INT_HIGH_LEVEL, 0},
+	{ AU1000_MAC1_DMA_INT, INTC_INT_HIGH_LEVEL, 0},
+	{ AU1500_GPIO_204, INTC_INT_HIGH_LEVEL, 0},
+
+	{ AU1000_GPIO_15, INTC_INT_LOW_LEVEL, 0 },
+	{ AU1000_USB_HOST_INT, INTC_INT_LOW_LEVEL, 0 },
+
+	{ AU1000_ACSYNC_INT, INTC_INT_RISE_EDGE, 0 },
+	{ AU1000_AC97C_INT, INTC_INT_RISE_EDGE, 0 },
+	{ AU1000_TOY_INT, INTC_INT_RISE_EDGE, 0 },
+	{ AU1000_TOY_MATCH0_INT, INTC_INT_RISE_EDGE, 0 },
+	{ AU1000_TOY_MATCH1_INT, INTC_INT_RISE_EDGE, 0 },
+	{ AU1000_USB_DEV_SUS_INT, INTC_INT_RISE_EDGE, 0 },
+	{ AU1000_USB_DEV_REQ_INT, INTC_INT_RISE_EDGE, 0 },
+	{ AU1000_RTC_INT, INTC_INT_RISE_EDGE, 0 },
+	{ AU1000_RTC_MATCH0_INT, INTC_INT_RISE_EDGE, 0 },
+	{ AU1000_RTC_MATCH1_INT, INTC_INT_RISE_EDGE, 0 },
+	{ AU1000_RTC_MATCH2_INT, INTC_INT_RISE_EDGE, 0 },
+
+	/* Careful if you change match 2 request!
+	 * The interrupt handler is called directly
+	 * from the low level dispatch code.
+	 */
+	{ AU1000_TOY_MATCH2_INT, INTC_INT_RISE_EDGE, 1 },
+};
+
+int au1xxx_nr_irqs = sizeof(au1xxx_irq_map)/sizeof(au1xxx_irq_map_t);
--- diff/arch/mips/au1000/pb1100/board_setup.c	1970-01-01 01:00:00.000000000 +0100
+++ source/arch/mips/au1000/pb1100/board_setup.c	2004-02-23 13:56:38.000000000 +0000
@@ -0,0 +1,118 @@
+/*
+ * Copyright 2002 MontaVista Software Inc.
+ * Author: MontaVista Software, Inc.
+ *         	ppopov@mvista.com or source@mvista.com
+ *
+ *  This program is free software; you can redistribute  it and/or modify it
+ *  under  the terms of  the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the  License, or (at your
+ *  option) any later version.
+ *
+ *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
+ *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
+ *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
+ *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
+ *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
+ *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *  You should have received a copy of the  GNU General Public License along
+ *  with this program; if not, write  to the Free Software Foundation, Inc.,
+ *  675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/ioport.h>
+#include <linux/mm.h>
+#include <linux/console.h>
+#include <linux/delay.h>
+
+#include <asm/cpu.h>
+#include <asm/bootinfo.h>
+#include <asm/irq.h>
+#include <asm/mipsregs.h>
+#include <asm/reboot.h>
+#include <asm/pgtable.h>
+#include <asm/au1000.h>
+#include <asm/pb1100.h>
+
+#ifdef CONFIG_USB_OHCI
+// Enable the workaround for the OHCI DoneHead
+// register corruption problem.
+#define CONFIG_AU1000_OHCI_FIX
+        ^^^^^^^^^^^^^^^^^^^^^^
+    !!! I shall not define symbols starting with CONFIG_ !!!
+#endif
+
+void __init board_setup(void)
+{
+	u32 pin_func;
+	u32 sys_freqctrl, sys_clksrc;
+
+	// set AUX clock to 12MHz * 8 = 96 MHz
+	au_writel(8, SYS_AUXPLL);
+	au_writel(0, SYS_PININPUTEN);
+	udelay(100);
+
+#if defined (CONFIG_USB_OHCI) || defined (CONFIG_AU1X00_USB_DEVICE)
+	// configure pins GPIO[14:9] as GPIO
+	pin_func = au_readl(SYS_PINFUNC) & (u32)(~0x80);
+
+	/* zero and disable FREQ2 */
+	sys_freqctrl = au_readl(SYS_FREQCTRL0);
+	sys_freqctrl &= ~0xFFF00000;
+	au_writel(sys_freqctrl, SYS_FREQCTRL0);
+
+	/* zero and disable USBH/USBD/IrDA clock */
+	sys_clksrc = au_readl(SYS_CLKSRC);
+	sys_clksrc &= ~0x0000001F;
+	au_writel(sys_clksrc, SYS_CLKSRC);
+
+	sys_freqctrl = au_readl(SYS_FREQCTRL0);
+	sys_freqctrl &= ~0xFFF00000;
+
+	sys_clksrc = au_readl(SYS_CLKSRC);
+	sys_clksrc &= ~0x0000001F;
+
+	// FREQ2 = aux/2 = 48 MHz
+	sys_freqctrl |= ((0<<22) | (1<<21) | (1<<20));
+	au_writel(sys_freqctrl, SYS_FREQCTRL0);
+
+	/*
+	 * Route 48MHz FREQ2 into USBH/USBD/IrDA
+	 */
+	sys_clksrc |= ((4<<2) | (0<<1) | 0 );
+	au_writel(sys_clksrc, SYS_CLKSRC);
+
+	/* setup the static bus controller */
+	au_writel(0x00000002, MEM_STCFG3);  /* type = PCMCIA */
+	au_writel(0x280E3D07, MEM_STTIME3); /* 250ns cycle time */
+	au_writel(0x10000000, MEM_STADDR3); /* any PCMCIA select */
+
+	// get USB Functionality pin state (device vs host drive pins)
+	pin_func = au_readl(SYS_PINFUNC) & (u32)(~0x8000);
+#ifndef CONFIG_AU1X00_USB_DEVICE
+	// 2nd USB port is USB host
+	pin_func |= 0x8000;
+#endif
+	au_writel(pin_func, SYS_PINFUNC);
+#endif // defined (CONFIG_USB_OHCI) || defined (CONFIG_AU1X00_USB_DEVICE)
+
+	/* Enable sys bus clock divider when IDLE state or no bus activity. */
+	au_writel(au_readl(SYS_POWERCTRL) | (0x3 << 5), SYS_POWERCTRL);
+
+	// Enable the RTC if not already enabled
+	if (!(readb(0xac000028) & 0x20)) {
+		writeb(readb(0xac000028) | 0x20, 0xac000028);
+		au_sync();
+	}
+	// Put the clock in BCD mode
+	if (readb(0xac00002C) & 0x4) { /* reg B */
+		writeb(readb(0xac00002c) & ~0x4, 0xac00002c);
+		au_sync();
+	}
+}
--- diff/arch/mips/au1000/pb1100/irqmap.c	1970-01-01 01:00:00.000000000 +0100
+++ source/arch/mips/au1000/pb1100/irqmap.c	2004-02-23 13:56:38.000000000 +0000
@@ -0,0 +1,100 @@
+/*
+ * BRIEF MODULE DESCRIPTION
+ *	Au1xxx irq map table
+ *
+ * Copyright 2003 Embedded Edge, LLC
+ *		dan@embeddededge.com
+ *
+ *  This program is free software; you can redistribute	 it and/or modify it
+ *  under  the terms of	 the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the	License, or (at your
+ *  option) any later version.
+ *
+ *  THIS  SOFTWARE  IS PROVIDED	  ``AS	IS'' AND   ANY	EXPRESS OR IMPLIED
+ *  WARRANTIES,	  INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
+ *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
+ *  NO	EVENT  SHALL   THE AUTHOR  BE	 LIABLE FOR ANY	  DIRECT, INDIRECT,
+ *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ *  NOT LIMITED	  TO, PROCUREMENT OF  SUBSTITUTE GOODS	OR SERVICES; LOSS OF
+ *  USE, DATA,	OR PROFITS; OR	BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ *  ANY THEORY OF LIABILITY, WHETHER IN	 CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *  You should have received a copy of the  GNU General Public License along
+ *  with this program; if not, write  to the Free Software Foundation, Inc.,
+ *  675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/irq.h>
+#include <linux/kernel_stat.h>
+#include <linux/module.h>
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/types.h>
+#include <linux/interrupt.h>
+#include <linux/ioport.h>
+#include <linux/timex.h>
+#include <linux/slab.h>
+#include <linux/random.h>
+#include <linux/delay.h>
+
+#include <asm/bitops.h>
+#include <asm/bootinfo.h>
+#include <asm/io.h>
+#include <asm/mipsregs.h>
+#include <asm/system.h>
+#include <asm/au1000.h>
+
+au1xxx_irq_map_t au1xxx_irq_map[] = {
+	{ AU1000_UART0_INT, INTC_INT_HIGH_LEVEL, 0},
+	{ AU1000_UART1_INT, INTC_INT_HIGH_LEVEL, 0},
+	{ AU1000_UART3_INT, INTC_INT_HIGH_LEVEL, 0},
+
+	{ AU1000_SSI0_INT, INTC_INT_HIGH_LEVEL, 0},
+	{ AU1000_SSI1_INT, INTC_INT_HIGH_LEVEL, 0},
+
+	{ AU1000_DMA_INT_BASE, INTC_INT_HIGH_LEVEL, 0},
+	{ AU1000_DMA_INT_BASE+1, INTC_INT_HIGH_LEVEL, 0},
+	{ AU1000_DMA_INT_BASE+2, INTC_INT_HIGH_LEVEL, 0},
+	{ AU1000_DMA_INT_BASE+3, INTC_INT_HIGH_LEVEL, 0},
+	{ AU1000_DMA_INT_BASE+4, INTC_INT_HIGH_LEVEL, 0},
+	{ AU1000_DMA_INT_BASE+5, INTC_INT_HIGH_LEVEL, 0},
+	{ AU1000_DMA_INT_BASE+6, INTC_INT_HIGH_LEVEL, 0},
+	{ AU1000_DMA_INT_BASE+7, INTC_INT_HIGH_LEVEL, 0},
+
+	{ AU1000_IRDA_TX_INT, INTC_INT_HIGH_LEVEL, 0},
+	{ AU1000_IRDA_RX_INT, INTC_INT_HIGH_LEVEL, 0},
+
+	{ AU1000_MAC0_DMA_INT, INTC_INT_HIGH_LEVEL, 0},
+
+	{ AU1500_GPIO_204, INTC_INT_HIGH_LEVEL, 0},
+
+	{ AU1000_USB_HOST_INT, INTC_INT_LOW_LEVEL, 0 },
+	{ AU1000_GPIO_9, INTC_INT_LOW_LEVEL, 0 }, // PCMCIA Card Fully_Interted#
+	{ AU1000_GPIO_10, INTC_INT_LOW_LEVEL, 0 }, // PCMCIA Card STSCHG#
+	{ AU1000_GPIO_11, INTC_INT_LOW_LEVEL, 0 }, // PCMCIA Card IRQ#
+	{ AU1000_GPIO_13, INTC_INT_LOW_LEVEL, 0 }, // DC_IRQ#
+	{ AU1000_GPIO_23, INTC_INT_LOW_LEVEL, 0 }, // 2-wire SCL
+
+	{ AU1000_ACSYNC_INT, INTC_INT_RISE_EDGE, 0 },
+	{ AU1000_AC97C_INT, INTC_INT_RISE_EDGE, 0 },
+	{ AU1000_TOY_INT, INTC_INT_RISE_EDGE, 0 },
+	{ AU1000_TOY_MATCH0_INT, INTC_INT_RISE_EDGE, 0 },
+	{ AU1000_TOY_MATCH1_INT, INTC_INT_RISE_EDGE, 0 },
+	{ AU1000_USB_DEV_SUS_INT, INTC_INT_RISE_EDGE, 0 },
+	{ AU1000_USB_DEV_REQ_INT, INTC_INT_RISE_EDGE, 0 },
+	{ AU1000_RTC_INT, INTC_INT_RISE_EDGE, 0 },
+	{ AU1000_RTC_MATCH0_INT, INTC_INT_RISE_EDGE, 0 },
+	{ AU1000_RTC_MATCH1_INT, INTC_INT_RISE_EDGE, 0 },
+	{ AU1000_RTC_MATCH2_INT, INTC_INT_RISE_EDGE, 0 },
+
+	/* Careful if you change match 2 request!
+	 * The interrupt handler is called directly
+	 * from the low level dispatch code.
+	 */
+	{ AU1000_TOY_MATCH2_INT, INTC_INT_RISE_EDGE, 1 },
+};
+
+int au1xxx_nr_irqs = sizeof(au1xxx_irq_map)/sizeof(au1xxx_irq_map_t);
--- diff/arch/mips/au1000/pb1500/board_setup.c	1970-01-01 01:00:00.000000000 +0100
+++ source/arch/mips/au1000/pb1500/board_setup.c	2004-02-23 13:56:38.000000000 +0000
@@ -0,0 +1,140 @@
+/*
+ * Copyright 2000 MontaVista Software Inc.
+ * Author: MontaVista Software, Inc.
+ *         	ppopov@mvista.com or source@mvista.com
+ *
+ *  This program is free software; you can redistribute  it and/or modify it
+ *  under  the terms of  the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the  License, or (at your
+ *  option) any later version.
+ *
+ *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
+ *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
+ *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
+ *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
+ *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
+ *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *  You should have received a copy of the  GNU General Public License along
+ *  with this program; if not, write  to the Free Software Foundation, Inc.,
+ *  675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/ioport.h>
+#include <linux/mm.h>
+#include <linux/console.h>
+#include <linux/delay.h>
+
+#include <asm/cpu.h>
+#include <asm/bootinfo.h>
+#include <asm/irq.h>
+#include <asm/mipsregs.h>
+#include <asm/reboot.h>
+#include <asm/pgtable.h>
+#include <asm/mach-au1x00/au1000.h>
+#include <asm/mach-pb1x00/pb1500.h>
+
+#ifdef CONFIG_USB_OHCI
+// Enable the workaround for the OHCI DoneHead
+// register corruption problem.
+#define CONFIG_AU1000_OHCI_FIX
+        ^^^^^^^^^^^^^^^^^^^^^^
+    !!! I shall not define symbols starting with CONFIG_ !!!
+#endif
+
+void __init board_setup(void)
+{
+	u32 pin_func;
+	u32 sys_freqctrl, sys_clksrc;
+
+	sys_clksrc = sys_freqctrl = pin_func = 0;
+	// set AUX clock to 12MHz * 8 = 96 MHz
+	au_writel(8, SYS_AUXPLL);
+	au_writel(0, SYS_PINSTATERD);
+	udelay(100);
+
+#if defined (CONFIG_USB_OHCI) || defined (CONFIG_AU1X00_USB_DEVICE)
+
+	/* GPIO201 is input for PCMCIA card detect */
+	/* GPIO203 is input for PCMCIA interrupt request */
+	au_writel(au_readl(GPIO2_DIR) & (u32)(~((1<<1)|(1<<3))), GPIO2_DIR);
+
+	/* zero and disable FREQ2 */
+	sys_freqctrl = au_readl(SYS_FREQCTRL0);
+	sys_freqctrl &= ~0xFFF00000;
+	au_writel(sys_freqctrl, SYS_FREQCTRL0);
+
+	/* zero and disable USBH/USBD clocks */
+	sys_clksrc = au_readl(SYS_CLKSRC);
+	sys_clksrc &= ~0x00007FE0;
+	au_writel(sys_clksrc, SYS_CLKSRC);
+
+	sys_freqctrl = au_readl(SYS_FREQCTRL0);
+	sys_freqctrl &= ~0xFFF00000;
+
+	sys_clksrc = au_readl(SYS_CLKSRC);
+	sys_clksrc &= ~0x00007FE0;
+
+	// FREQ2 = aux/2 = 48 MHz
+	sys_freqctrl |= ((0<<22) | (1<<21) | (1<<20));
+	au_writel(sys_freqctrl, SYS_FREQCTRL0);
+
+	/*
+	 * Route 48MHz FREQ2 into USB Host and/or Device
+	 */
+#ifdef CONFIG_USB_OHCI
+	sys_clksrc |= ((4<<12) | (0<<11) | (0<<10));
+#endif
+#ifdef CONFIG_AU1X00_USB_DEVICE
+	sys_clksrc |= ((4<<7) | (0<<6) | (0<<5));
+#endif
+	au_writel(sys_clksrc, SYS_CLKSRC);
+
+
+	pin_func = au_readl(SYS_PINFUNC) & (u32)(~0x8000);
+#ifndef CONFIG_AU1X00_USB_DEVICE
+	// 2nd USB port is USB host
+	pin_func |= 0x8000;
+#endif
+	au_writel(pin_func, SYS_PINFUNC);
+#endif // defined (CONFIG_USB_OHCI) || defined (CONFIG_AU1X00_USB_DEVICE)
+
+
+
+#ifdef CONFIG_PCI
+	// Setup PCI bus controller
+	au_writel(0, Au1500_PCI_CMEM);
+	au_writel(0x00003fff, Au1500_CFG_BASE);
+#if defined(__MIPSEB__)
+	au_writel(0xf | (2<<6) | (1<<4), Au1500_PCI_CFG);
+#else
+	au_writel(0xf, Au1500_PCI_CFG);
+#endif
+	au_writel(0xf0000000, Au1500_PCI_MWMASK_DEV);
+	au_writel(0, Au1500_PCI_MWBASE_REV_CCL);
+	au_writel(0x02a00356, Au1500_PCI_STATCMD);
+	au_writel(0x00003c04, Au1500_PCI_HDRTYPE);
+	au_writel(0x00000008, Au1500_PCI_MBAR);
+	au_sync();
+#endif
+
+	/* Enable sys bus clock divider when IDLE state or no bus activity. */
+	au_writel(au_readl(SYS_POWERCTRL) | (0x3 << 5), SYS_POWERCTRL);
+
+	/* Enable the RTC if not already enabled */
+	if (!(au_readl(0xac000028) & 0x20)) {
+		printk("enabling clock ...\n");
+		au_writel((au_readl(0xac000028) | 0x20), 0xac000028);
+	}
+	/* Put the clock in BCD mode */
+	if (readl(0xac00002C) & 0x4) { /* reg B */
+		au_writel(au_readl(0xac00002c) & ~0x4, 0xac00002c);
+		au_sync();
+	}
+}
--- diff/arch/mips/au1000/pb1500/irqmap.c	1970-01-01 01:00:00.000000000 +0100
+++ source/arch/mips/au1000/pb1500/irqmap.c	2004-02-23 13:56:38.000000000 +0000
@@ -0,0 +1,100 @@
+/*
+ * BRIEF MODULE DESCRIPTION
+ *	Au1xxx irq map table
+ *
+ * Copyright 2003 Embedded Edge, LLC
+ *		dan@embeddededge.com
+ *
+ *  This program is free software; you can redistribute	 it and/or modify it
+ *  under  the terms of	 the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the	License, or (at your
+ *  option) any later version.
+ *
+ *  THIS  SOFTWARE  IS PROVIDED	  ``AS	IS'' AND   ANY	EXPRESS OR IMPLIED
+ *  WARRANTIES,	  INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
+ *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
+ *  NO	EVENT  SHALL   THE AUTHOR  BE	 LIABLE FOR ANY	  DIRECT, INDIRECT,
+ *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ *  NOT LIMITED	  TO, PROCUREMENT OF  SUBSTITUTE GOODS	OR SERVICES; LOSS OF
+ *  USE, DATA,	OR PROFITS; OR	BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ *  ANY THEORY OF LIABILITY, WHETHER IN	 CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *  You should have received a copy of the  GNU General Public License along
+ *  with this program; if not, write  to the Free Software Foundation, Inc.,
+ *  675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/irq.h>
+#include <linux/kernel_stat.h>
+#include <linux/module.h>
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/types.h>
+#include <linux/interrupt.h>
+#include <linux/ioport.h>
+#include <linux/timex.h>
+#include <linux/slab.h>
+#include <linux/random.h>
+#include <linux/delay.h>
+
+#include <asm/bitops.h>
+#include <asm/bootinfo.h>
+#include <asm/io.h>
+#include <asm/mipsregs.h>
+#include <asm/system.h>
+#include <asm/mach-au1x00/au1000.h>
+
+au1xxx_irq_map_t au1xxx_irq_map[] = {
+	{ AU1000_UART0_INT, INTC_INT_HIGH_LEVEL, 0},
+	{ AU1000_UART3_INT, INTC_INT_HIGH_LEVEL, 0},
+	{ AU1000_DMA_INT_BASE, INTC_INT_HIGH_LEVEL, 0},
+	{ AU1000_DMA_INT_BASE+1, INTC_INT_HIGH_LEVEL, 0},
+	{ AU1000_DMA_INT_BASE+2, INTC_INT_HIGH_LEVEL, 0},
+	{ AU1000_DMA_INT_BASE+3, INTC_INT_HIGH_LEVEL, 0},
+	{ AU1000_DMA_INT_BASE+4, INTC_INT_HIGH_LEVEL, 0},
+	{ AU1000_DMA_INT_BASE+5, INTC_INT_HIGH_LEVEL, 0},
+	{ AU1000_DMA_INT_BASE+6, INTC_INT_HIGH_LEVEL, 0},
+	{ AU1000_DMA_INT_BASE+7, INTC_INT_HIGH_LEVEL, 0},
+
+	{ AU1000_IRDA_TX_INT, INTC_INT_HIGH_LEVEL, 0},
+	{ AU1000_IRDA_RX_INT, INTC_INT_HIGH_LEVEL, 0},
+
+	{ AU1000_MAC0_DMA_INT, INTC_INT_HIGH_LEVEL, 0},
+	{ AU1000_MAC1_DMA_INT, INTC_INT_HIGH_LEVEL, 0},
+	{ AU1500_GPIO_204, INTC_INT_HIGH_LEVEL, 0},
+
+	{ AU1000_USB_HOST_INT, INTC_INT_LOW_LEVEL, 0 },
+
+	{ AU1000_PCI_INTA, INTC_INT_LOW_LEVEL, 0 },
+	{ AU1000_PCI_INTB, INTC_INT_LOW_LEVEL, 0 },
+	{ AU1000_PCI_INTC, INTC_INT_LOW_LEVEL, 0 },
+	{ AU1000_PCI_INTD, INTC_INT_LOW_LEVEL, 0 },
+	{ AU1500_GPIO_201, INTC_INT_LOW_LEVEL, 0 },
+	{ AU1500_GPIO_202, INTC_INT_LOW_LEVEL, 0 },
+	{ AU1500_GPIO_203, INTC_INT_LOW_LEVEL, 0 },
+	{ AU1500_GPIO_205, INTC_INT_LOW_LEVEL, 0 },
+	{ AU1500_GPIO_207, INTC_INT_LOW_LEVEL, 0 },
+
+	{ AU1000_ACSYNC_INT, INTC_INT_RISE_EDGE, 0 },
+	{ AU1000_AC97C_INT, INTC_INT_RISE_EDGE, 0 },
+	{ AU1000_TOY_INT, INTC_INT_RISE_EDGE, 0 },
+	{ AU1000_TOY_MATCH0_INT, INTC_INT_RISE_EDGE, 0 },
+	{ AU1000_TOY_MATCH1_INT, INTC_INT_RISE_EDGE, 0 },
+	{ AU1000_USB_DEV_SUS_INT, INTC_INT_RISE_EDGE, 0 },
+	{ AU1000_USB_DEV_REQ_INT, INTC_INT_RISE_EDGE, 0 },
+	{ AU1000_RTC_INT, INTC_INT_RISE_EDGE, 0 },
+	{ AU1000_RTC_MATCH0_INT, INTC_INT_RISE_EDGE, 0 },
+	{ AU1000_RTC_MATCH1_INT, INTC_INT_RISE_EDGE, 0 },
+	{ AU1000_RTC_MATCH2_INT, INTC_INT_RISE_EDGE, 0 },
+
+	/* Careful if you change match 2 request!
+	 * The interrupt handler is called directly
+	 * from the low level dispatch code.
+	 */
+	{ AU1000_TOY_MATCH2_INT, INTC_INT_RISE_EDGE, 1 },
+};
+
+int au1xxx_nr_irqs = sizeof(au1xxx_irq_map)/sizeof(au1xxx_irq_map_t);
--- diff/arch/mips/au1000/pb1550/Makefile	1970-01-01 01:00:00.000000000 +0100
+++ source/arch/mips/au1000/pb1550/Makefile	2004-02-23 13:56:38.000000000 +0000
@@ -0,0 +1,22 @@
+#
+#  Copyright 2000 MontaVista Software Inc.
+#  Author: MontaVista Software, Inc.
+#     	ppopov@mvista.com or source@mvista.com
+#
+# Makefile for the Alchemy Semiconductor PB1000 board.
+#
+# 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).
+#
+
+.S.s:
+	$(CPP) $(CFLAGS) $< -o $*.s
+.S.o:
+	$(CC) $(CFLAGS) -c $< -o $*.o
+
+O_TARGET := pb1550.o
+
+obj-y := init.o board_setup.o irqmap.o
+
+include $(TOPDIR)/Rules.make
--- diff/arch/mips/au1000/pb1550/board_setup.c	1970-01-01 01:00:00.000000000 +0100
+++ source/arch/mips/au1000/pb1550/board_setup.c	2004-02-23 13:56:38.000000000 +0000
@@ -0,0 +1,67 @@
+/*
+ *
+ * BRIEF MODULE DESCRIPTION
+ *	Alchemy Pb1550 board setup.
+ *
+ * Copyright 2000 MontaVista Software Inc.
+ * Author: MontaVista Software, Inc.
+ *         	ppopov@mvista.com or source@mvista.com
+ *
+ *  This program is free software; you can redistribute  it and/or modify it
+ *  under  the terms of  the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the  License, or (at your
+ *  option) any later version.
+ *
+ *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
+ *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
+ *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
+ *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
+ *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
+ *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *  You should have received a copy of the  GNU General Public License along
+ *  with this program; if not, write  to the Free Software Foundation, Inc.,
+ *  675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/ioport.h>
+#include <linux/mm.h>
+#include <linux/console.h>
+#include <linux/mc146818rtc.h>
+#include <linux/delay.h>
+
+#include <asm/cpu.h>
+#include <asm/bootinfo.h>
+#include <asm/irq.h>
+#include <asm/keyboard.h>
+#include <asm/mipsregs.h>
+#include <asm/reboot.h>
+#include <asm/pgtable.h>
+#include <asm/au1000.h>
+#include <asm/db1x00.h>
+
+extern struct rtc_ops no_rtc_ops;
+
+static BCSR * const bcsr = (BCSR *)0xB3000000;
+
+void __init board_setup(void)
+{
+	u32 pin_func;
+	rtc_ops = &no_rtc_ops;
+
+#ifdef CONFIG_AU1X00_USB_DEVICE
+	// 2nd USB port is USB device
+	pin_func = au_readl(SYS_PINFUNC) & (u32)(~0x8000);
+	au_writel(pin_func, SYS_PINFUNC);
+#endif
+
+	au_writel(0, (u32)bcsr|0x10); /* turn off pcmcia power */
+
+    printk("AMD Alchemy Pb1550 Board\n");
+}
--- diff/arch/mips/au1000/pb1550/init.c	1970-01-01 01:00:00.000000000 +0100
+++ source/arch/mips/au1000/pb1550/init.c	2004-02-23 13:56:38.000000000 +0000
@@ -0,0 +1,73 @@
+/*
+ *
+ * BRIEF MODULE DESCRIPTION
+ *	PB1550 board setup
+ *
+ * Copyright 2001 MontaVista Software Inc.
+ * Author: MontaVista Software, Inc.
+ *         	ppopov@mvista.com or source@mvista.com
+ *
+ *  This program is free software; you can redistribute  it and/or modify it
+ *  under  the terms of  the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the  License, or (at your
+ *  option) any later version.
+ *
+ *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
+ *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
+ *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
+ *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
+ *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
+ *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *  You should have received a copy of the  GNU General Public License along
+ *  with this program; if not, write  to the Free Software Foundation, Inc.,
+ *  675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/init.h>
+#include <linux/mm.h>
+#include <linux/sched.h>
+#include <linux/bootmem.h>
+#include <asm/addrspace.h>
+#include <asm/bootinfo.h>
+#include <linux/config.h>
+#include <linux/string.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+
+int prom_argc;
+char **prom_argv, **prom_envp;
+extern void  __init prom_init_cmdline(void);
+extern char *prom_getenv(char *envname);
+
+const char *get_system_type(void)
+{
+	return "AMD Alchemy PbAu1550";
+}
+
+int __init prom_init(int argc, char **argv, char **envp, int *prom_vec)
+{
+	unsigned char *memsize_str;
+	unsigned long memsize;
+
+	prom_argc = argc;
+	prom_argv = argv;
+	prom_envp = envp;
+
+	mips_machgroup = MACH_GROUP_ALCHEMY;
+	mips_machtype = MACH_PB1000;	/* set the platform # */   
+	prom_init_cmdline();
+
+	memsize_str = prom_getenv("memsize");
+	if (!memsize_str) {
+		memsize = 0x04000000;
+	} else {
+		memsize = simple_strtol(memsize_str, NULL, 0);
+	}
+	add_memory_region(0, memsize, BOOT_MEM_RAM);
+	return 0;
+}
--- diff/arch/mips/au1000/pb1550/irqmap.c	1970-01-01 01:00:00.000000000 +0100
+++ source/arch/mips/au1000/pb1550/irqmap.c	2004-02-23 13:56:38.000000000 +0000
@@ -0,0 +1,93 @@
+/*
+ * BRIEF MODULE DESCRIPTION
+ *	Au1xxx irq map table
+ *
+ * Copyright 2003 Embedded Edge, LLC
+ *		dan@embeddededge.com
+ *
+ *  This program is free software; you can redistribute	 it and/or modify it
+ *  under  the terms of	 the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the	License, or (at your
+ *  option) any later version.
+ *
+ *  THIS  SOFTWARE  IS PROVIDED	  ``AS	IS'' AND   ANY	EXPRESS OR IMPLIED
+ *  WARRANTIES,	  INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
+ *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
+ *  NO	EVENT  SHALL   THE AUTHOR  BE	 LIABLE FOR ANY	  DIRECT, INDIRECT,
+ *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ *  NOT LIMITED	  TO, PROCUREMENT OF  SUBSTITUTE GOODS	OR SERVICES; LOSS OF
+ *  USE, DATA,	OR PROFITS; OR	BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ *  ANY THEORY OF LIABILITY, WHETHER IN	 CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *  You should have received a copy of the  GNU General Public License along
+ *  with this program; if not, write  to the Free Software Foundation, Inc.,
+ *  675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/irq.h>
+#include <linux/kernel_stat.h>
+#include <linux/module.h>
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/types.h>
+#include <linux/interrupt.h>
+#include <linux/ioport.h>
+#include <linux/timex.h>
+#include <linux/slab.h>
+#include <linux/random.h>
+#include <linux/delay.h>
+
+#include <asm/bitops.h>
+#include <asm/bootinfo.h>
+#include <asm/io.h>
+#include <asm/mipsregs.h>
+#include <asm/system.h>
+#include <asm/au1000.h>
+
+au1xxx_irq_map_t au1xxx_irq_map[] = {
+	{ AU1550_UART0_INT, 	INTC_INT_HIGH_LEVEL, 0},
+	{ AU1550_PCI_INTA, 		INTC_INT_LOW_LEVEL, 0 },
+	{ AU1550_PCI_INTB, 		INTC_INT_LOW_LEVEL, 0 },
+	{ AU1550_DDMA_INT, 		INTC_INT_HIGH_LEVEL, 0},
+	{ AU1550_CRYPTO_INT, 	INTC_INT_HIGH_LEVEL, 0},
+	{ AU1550_PCI_INTC, 		INTC_INT_LOW_LEVEL, 0 },
+	{ AU1550_PCI_INTD, 		INTC_INT_LOW_LEVEL, 0 },
+	{ AU1550_PCI_RST_INT, 	INTC_INT_LOW_LEVEL, 0 },
+	{ AU1550_UART1_INT, 	INTC_INT_HIGH_LEVEL, 0},
+	{ AU1550_UART3_INT, 	INTC_INT_HIGH_LEVEL, 0},
+	{ AU1550_PSC0_INT, 		INTC_INT_HIGH_LEVEL, 0},
+	{ AU1550_PSC1_INT, 		INTC_INT_HIGH_LEVEL, 0},
+	{ AU1550_PSC2_INT, 		INTC_INT_HIGH_LEVEL, 0},
+	{ AU1550_PSC3_INT, 		INTC_INT_HIGH_LEVEL, 0},
+	{ AU1550_TOY_INT, 		INTC_INT_RISE_EDGE, 0 },
+	{ AU1550_TOY_MATCH0_INT,INTC_INT_RISE_EDGE, 0 },
+	{ AU1550_TOY_MATCH1_INT,INTC_INT_RISE_EDGE, 0 },
+	/* Careful if you change match 2 request!
+	 * The interrupt handler is called directly
+	 * from the low level dispatch code.
+	 */
+	{ AU1550_TOY_MATCH2_INT,INTC_INT_RISE_EDGE, 0 },
+	{ AU1550_RTC_INT, 		INTC_INT_RISE_EDGE, 0 },
+	{ AU1550_RTC_MATCH0_INT,INTC_INT_RISE_EDGE, 0 },
+	{ AU1550_RTC_MATCH1_INT,INTC_INT_RISE_EDGE, 0 },
+	{ AU1550_RTC_MATCH2_INT,INTC_INT_RISE_EDGE, 0 },
+	{ AU1550_RTC_MATCH2_INT,INTC_INT_RISE_EDGE, 0 },
+	{ AU1550_NAND_INT, 		INTC_INT_RISE_EDGE, 0 },
+	{ AU1550_USB_DEV_REQ_INT, INTC_INT_RISE_EDGE, 0 },
+	{ AU1550_USB_DEV_SUS_INT, INTC_INT_RISE_EDGE, 0 },
+	{ AU1550_USB_HOST_INT,  INTC_INT_LOW_LEVEL, 0 },
+	{ AU1550_MAC0_DMA_INT,  INTC_INT_HIGH_LEVEL, 0},
+	{ AU1550_MAC1_DMA_INT,  INTC_INT_HIGH_LEVEL, 0},
+
+
+	/*
+	 *  Need to define platform dependant GPIO ints here
+	 */
+	#warning PbAu1550 needs GPIO Interrupts defined
+
+};
+
+int au1xxx_nr_irqs = sizeof(au1xxx_irq_map)/sizeof(au1xxx_irq_map_t);
--- diff/arch/mips/au1000/xxs1500/Makefile	1970-01-01 01:00:00.000000000 +0100
+++ source/arch/mips/au1000/xxs1500/Makefile	2004-02-23 13:56:38.000000000 +0000
@@ -0,0 +1,13 @@
+#
+#  Copyright 2003 MontaVista Software Inc.
+#  Author: MontaVista Software, Inc.
+#     	ppopov@mvista.com or source@mvista.com
+#
+# Makefile for MyCable XXS1500 board.
+#
+# 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).
+#
+
+lib-y := init.o board_setup.o irqmap.o
--- diff/arch/mips/au1000/xxs1500/board_setup.c	1970-01-01 01:00:00.000000000 +0100
+++ source/arch/mips/au1000/xxs1500/board_setup.c	2004-02-23 13:56:38.000000000 +0000
@@ -0,0 +1,85 @@
+/*
+ * Copyright 2000-2003 MontaVista Software Inc.
+ * Author: MontaVista Software, Inc.
+ *         	ppopov@mvista.com or source@mvista.com
+ *
+ *  This program is free software; you can redistribute  it and/or modify it
+ *  under  the terms of  the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the  License, or (at your
+ *  option) any later version.
+ *
+ *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
+ *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
+ *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
+ *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
+ *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
+ *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *  You should have received a copy of the  GNU General Public License along
+ *  with this program; if not, write  to the Free Software Foundation, Inc.,
+ *  675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/ioport.h>
+#include <linux/mm.h>
+#include <linux/console.h>
+#include <linux/delay.h>
+
+#include <asm/cpu.h>
+#include <asm/bootinfo.h>
+#include <asm/irq.h>
+#include <asm/keyboard.h>
+#include <asm/mipsregs.h>
+#include <asm/reboot.h>
+#include <asm/pgtable.h>
+#include <asm/au1000.h>
+
+void __init board_setup(void)
+{
+	u32 pin_func;
+	
+	// set multiple use pins (UART3/GPIO) to UART (it's used as UART too)
+	pin_func = au_readl(SYS_PINFUNC) & (u32)(~SYS_PF_UR3);
+	pin_func |= SYS_PF_UR3;
+	au_writel(pin_func, SYS_PINFUNC);
+
+	// enable UART
+	au_writel(0x01, UART3_ADDR+UART_MOD_CNTRL); // clock enable (CE)
+	mdelay(10);
+	au_writel(0x03, UART3_ADDR+UART_MOD_CNTRL); // CE and "enable"
+	mdelay(10);
+
+	// enable DTR = USB power up
+	au_writel(0x01, UART3_ADDR+UART_MCR); //? UART_MCR_DTR is 0x01???
+
+#ifdef CONFIG_PCMCIA_XXS1500
+	/* setup pcmcia signals */
+	au_writel(0, SYS_PININPUTEN);
+
+	/* gpio 0, 1, and 4 are inputs */
+	au_writel(1 | (1<<1) | (1<<4), SYS_TRIOUTCLR);
+
+	/* enable GPIO2 if not already enabled */
+	au_writel(1, GPIO2_ENABLE);
+	/* gpio2 208/9/10/11 are inputs */
+	au_writel((1<<8) | (1<<9) | (1<<10) | (1<<11), GPIO2_DIR);
+	
+	/* turn off power */
+	au_writel((au_readl(GPIO2_PINSTATE) & ~(1<<14))|(1<<30), GPIO2_OUTPUT);
+#endif
+	
+
+#ifdef CONFIG_PCI
+#if defined(__MIPSEB__)
+	au_writel(0xf | (2<<6) | (1<<4), Au1500_PCI_CFG);
+#else
+	au_writel(0xf, Au1500_PCI_CFG);
+#endif
+#endif
+}
--- diff/arch/mips/au1000/xxs1500/init.c	1970-01-01 01:00:00.000000000 +0100
+++ source/arch/mips/au1000/xxs1500/init.c	2004-02-23 13:56:38.000000000 +0000
@@ -0,0 +1,68 @@
+/*
+ * BRIEF MODULE DESCRIPTION
+ *	XXS1500 board setup
+ *
+ * Copyright 2003 MontaVista Software Inc.
+ * Author: MontaVista Software, Inc.
+ *         	ppopov@mvista.com or source@mvista.com
+ *
+ *  This program is free software; you can redistribute  it and/or modify it
+ *  under  the terms of  the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the  License, or (at your
+ *  option) any later version.
+ *
+ *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
+ *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
+ *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
+ *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
+ *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
+ *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *  You should have received a copy of the  GNU General Public License along
+ *  with this program; if not, write  to the Free Software Foundation, Inc.,
+ *  675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <linux/init.h>
+#include <linux/mm.h>
+#include <linux/sched.h>
+#include <linux/bootmem.h>
+#include <asm/addrspace.h>
+#include <asm/bootinfo.h>
+#include <linux/string.h>
+#include <linux/kernel.h>
+
+int prom_argc;
+char **prom_argv, **prom_envp;
+extern void  __init prom_init_cmdline(void);
+extern char *prom_getenv(char *envname);
+
+const char *get_system_type(void)
+{
+	return "XXS1500";
+}
+
+void __init prom_init(void)
+{
+	unsigned char *memsize_str;
+	unsigned long memsize;
+
+	prom_argc = fw_arg0;
+	prom_argv = (char **) fw_arg1;
+	prom_envp = (char **) fw_arg2;
+
+	mips_machgroup = MACH_GROUP_ALCHEMY;
+	mips_machtype = MACH_XXS1500;	/* set the platform # */   
+
+	prom_init_cmdline();
+
+	memsize_str = prom_getenv("memsize");
+	if (!memsize_str)
+		memsize = 0x04000000;
+	else
+		memsize = simple_strtol(memsize_str, NULL, 0);
+	add_memory_region(0, memsize, BOOT_MEM_RAM);
+}
--- diff/arch/mips/au1000/xxs1500/irqmap.c	1970-01-01 01:00:00.000000000 +0100
+++ source/arch/mips/au1000/xxs1500/irqmap.c	2004-02-23 13:56:38.000000000 +0000
@@ -0,0 +1,106 @@
+/*
+ * BRIEF MODULE DESCRIPTION
+ *	Au1xxx irq map table
+ *
+ * Copyright 2003 Embedded Edge, LLC
+ *		dan@embeddededge.com
+ *
+ *  This program is free software; you can redistribute	 it and/or modify it
+ *  under  the terms of	 the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the	License, or (at your
+ *  option) any later version.
+ *
+ *  THIS  SOFTWARE  IS PROVIDED	  ``AS	IS'' AND   ANY	EXPRESS OR IMPLIED
+ *  WARRANTIES,	  INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
+ *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
+ *  NO	EVENT  SHALL   THE AUTHOR  BE	 LIABLE FOR ANY	  DIRECT, INDIRECT,
+ *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ *  NOT LIMITED	  TO, PROCUREMENT OF  SUBSTITUTE GOODS	OR SERVICES; LOSS OF
+ *  USE, DATA,	OR PROFITS; OR	BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ *  ANY THEORY OF LIABILITY, WHETHER IN	 CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *  You should have received a copy of the  GNU General Public License along
+ *  with this program; if not, write  to the Free Software Foundation, Inc.,
+ *  675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/irq.h>
+#include <linux/kernel_stat.h>
+#include <linux/module.h>
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/types.h>
+#include <linux/interrupt.h>
+#include <linux/ioport.h>
+#include <linux/timex.h>
+#include <linux/slab.h>
+#include <linux/random.h>
+#include <linux/delay.h>
+
+#include <asm/bitops.h>
+#include <asm/bootinfo.h>
+#include <asm/io.h>
+#include <asm/mipsregs.h>
+#include <asm/system.h>
+#include <asm/au1000.h>
+
+au1xxx_irq_map_t au1xxx_irq_map[] = {
+	{ AU1000_UART0_INT, INTC_INT_HIGH_LEVEL, 0},
+	{ AU1000_UART3_INT, INTC_INT_HIGH_LEVEL, 0},
+	{ AU1000_DMA_INT_BASE, INTC_INT_HIGH_LEVEL, 0},
+	{ AU1000_DMA_INT_BASE+1, INTC_INT_HIGH_LEVEL, 0},
+	{ AU1000_DMA_INT_BASE+2, INTC_INT_HIGH_LEVEL, 0},
+	{ AU1000_DMA_INT_BASE+3, INTC_INT_HIGH_LEVEL, 0},
+	{ AU1000_DMA_INT_BASE+4, INTC_INT_HIGH_LEVEL, 0},
+	{ AU1000_DMA_INT_BASE+5, INTC_INT_HIGH_LEVEL, 0},
+	{ AU1000_DMA_INT_BASE+6, INTC_INT_HIGH_LEVEL, 0},
+	{ AU1000_DMA_INT_BASE+7, INTC_INT_HIGH_LEVEL, 0},
+
+	{ AU1000_IRDA_TX_INT, INTC_INT_HIGH_LEVEL, 0},
+	{ AU1000_IRDA_RX_INT, INTC_INT_HIGH_LEVEL, 0},
+
+	{ AU1000_MAC0_DMA_INT, INTC_INT_HIGH_LEVEL, 0},
+	{ AU1000_MAC1_DMA_INT, INTC_INT_HIGH_LEVEL, 0},
+	{ AU1500_GPIO_204, INTC_INT_HIGH_LEVEL, 0},
+
+	{ AU1000_USB_HOST_INT, INTC_INT_LOW_LEVEL, 0 },
+	{ AU1000_PCI_INTA, INTC_INT_LOW_LEVEL, 0 },
+	{ AU1000_PCI_INTB, INTC_INT_LOW_LEVEL, 0 },
+	{ AU1000_PCI_INTC, INTC_INT_LOW_LEVEL, 0 },
+	{ AU1000_PCI_INTD, INTC_INT_LOW_LEVEL, 0 },
+	{ AU1500_GPIO_201, INTC_INT_LOW_LEVEL, 0 },
+	{ AU1500_GPIO_202, INTC_INT_LOW_LEVEL, 0 },
+	{ AU1500_GPIO_203, INTC_INT_LOW_LEVEL, 0 },
+	{ AU1500_GPIO_205, INTC_INT_LOW_LEVEL, 0 },
+	{ AU1500_GPIO_207, INTC_INT_LOW_LEVEL, 0 },
+
+	{ AU1000_GPIO_0, INTC_INT_LOW_LEVEL, 0 },
+	{ AU1000_GPIO_1, INTC_INT_LOW_LEVEL, 0 }, 
+	{ AU1000_GPIO_2, INTC_INT_LOW_LEVEL, 0 },
+	{ AU1000_GPIO_3, INTC_INT_LOW_LEVEL, 0 },
+	{ AU1000_GPIO_4, INTC_INT_LOW_LEVEL, 0 }, /* CF interrupt */
+	{ AU1000_GPIO_5, INTC_INT_LOW_LEVEL, 0 },
+
+	{ AU1000_ACSYNC_INT, INTC_INT_RISE_EDGE, 0 },
+	{ AU1000_AC97C_INT, INTC_INT_RISE_EDGE, 0 },
+	{ AU1000_TOY_INT, INTC_INT_RISE_EDGE, 0 },
+	{ AU1000_TOY_MATCH0_INT, INTC_INT_RISE_EDGE, 0 },
+	{ AU1000_TOY_MATCH1_INT, INTC_INT_RISE_EDGE, 0 },
+	{ AU1000_USB_DEV_SUS_INT, INTC_INT_RISE_EDGE, 0 },
+	{ AU1000_USB_DEV_REQ_INT, INTC_INT_RISE_EDGE, 0 },
+	{ AU1000_RTC_INT, INTC_INT_RISE_EDGE, 0 },
+	{ AU1000_RTC_MATCH0_INT, INTC_INT_RISE_EDGE, 0 },
+	{ AU1000_RTC_MATCH1_INT, INTC_INT_RISE_EDGE, 0 },
+	{ AU1000_RTC_MATCH2_INT, INTC_INT_RISE_EDGE, 0 },
+
+	/* Careful if you change match 2 request!
+	 * The interrupt handler is called directly
+	 * from the low level dispatch code.
+	 */
+	{ AU1000_TOY_MATCH2_INT, INTC_INT_RISE_EDGE, 1 },
+};
+
+int au1xxx_nr_irqs = sizeof(au1xxx_irq_map)/sizeof(au1xxx_irq_map_t);
--- diff/arch/mips/configs/atlas_defconfig	1970-01-01 01:00:00.000000000 +0100
+++ source/arch/mips/configs/atlas_defconfig	2004-02-23 13:56:38.000000000 +0000
@@ -0,0 +1,659 @@
+#
+# Automatically generated make config: don't edit
+#
+CONFIG_MIPS=y
+# CONFIG_MIPS64 is not set
+# CONFIG_64BIT is not set
+CONFIG_MIPS32=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_CLEAN_COMPILE=y
+CONFIG_STANDALONE=y
+CONFIG_BROKEN_ON_SMP=y
+
+#
+# General setup
+#
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_IKCONFIG is not set
+CONFIG_EMBEDDED=y
+CONFIG_KALLSYMS=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+
+#
+# Loadable module support
+#
+# CONFIG_MODULES is not set
+
+#
+# Machine selection
+#
+# CONFIG_MACH_JAZZ is not set
+# CONFIG_BAGET_MIPS is not set
+# CONFIG_MACH_VR41XX is not set
+# CONFIG_TOSHIBA_JMR3927 is not set
+# CONFIG_MIPS_COBALT is not set
+# CONFIG_MACH_DECSTATION is not set
+# CONFIG_MIPS_EV64120 is not set
+# CONFIG_MIPS_EV96100 is not set
+# CONFIG_MIPS_IVR is not set
+# CONFIG_LASAT is not set
+# CONFIG_HP_LASERJET is not set
+# CONFIG_MIPS_ITE8172 is not set
+CONFIG_MIPS_ATLAS=y
+# CONFIG_MIPS_MALTA is not set
+# CONFIG_MIPS_SEAD is not set
+# CONFIG_MOMENCO_OCELOT is not set
+# CONFIG_MOMENCO_OCELOT_G is not set
+# CONFIG_MOMENCO_OCELOT_C is not set
+# CONFIG_MOMENCO_JAGUAR_ATX is not set
+# CONFIG_PMC_YOSEMITE is not set
+# CONFIG_DDB5074 is not set
+# CONFIG_DDB5476 is not set
+# CONFIG_DDB5477 is not set
+# CONFIG_NEC_OSPREY is not set
+# CONFIG_SGI_IP22 is not set
+# CONFIG_SGI_IP32 is not set
+# CONFIG_SOC_AU1X00 is not set
+# CONFIG_SIBYTE_SB1xxx_SOC is not set
+# CONFIG_SNI_RM200_PCI is not set
+# CONFIG_TOSHIBA_RBTX4927 is not set
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_HAVE_DEC_LOCK=y
+CONFIG_DMA_NONCOHERENT=y
+CONFIG_MIPS_BONITO64=y
+CONFIG_MIPS_MSC=y
+# CONFIG_CPU_LITTLE_ENDIAN is not set
+CONFIG_MIPS_BOARDS_GEN=y
+CONFIG_MIPS_GT64120=y
+CONFIG_SWAP_IO_SPACE=y
+CONFIG_BOOT_ELF32=y
+CONFIG_MIPS_L1_CACHE_SHIFT=5
+# CONFIG_FB is not set
+
+#
+# CPU selection
+#
+CONFIG_CPU_MIPS32=y
+# CONFIG_CPU_MIPS64 is not set
+# CONFIG_CPU_R3000 is not set
+# CONFIG_CPU_TX39XX is not set
+# CONFIG_CPU_VR41XX is not set
+# CONFIG_CPU_R4300 is not set
+# CONFIG_CPU_R4X00 is not set
+# CONFIG_CPU_TX49XX is not set
+# CONFIG_CPU_R5000 is not set
+# CONFIG_CPU_R5432 is not set
+# CONFIG_CPU_R6000 is not set
+# CONFIG_CPU_NEVADA is not set
+# CONFIG_CPU_R8000 is not set
+# CONFIG_CPU_R10000 is not set
+# CONFIG_CPU_RM7000 is not set
+# CONFIG_CPU_RM9000 is not set
+# CONFIG_CPU_SB1 is not set
+CONFIG_PAGE_SIZE_4KB=y
+# CONFIG_PAGE_SIZE_16KB is not set
+# CONFIG_PAGE_SIZE_64KB is not set
+CONFIG_CPU_HAS_PREFETCH=y
+# CONFIG_VTAG_ICACHE is not set
+# CONFIG_64BIT_PHYS_ADDR is not set
+# CONFIG_CPU_ADVANCED is not set
+CONFIG_CPU_HAS_LLSC=y
+CONFIG_CPU_HAS_SYNC=y
+# CONFIG_PREEMPT is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+
+#
+# Bus options (PCI, PCMCIA, EISA, ISA, TC)
+#
+CONFIG_PCI=y
+CONFIG_PCI_LEGACY_PROC=y
+CONFIG_PCI_NAMES=y
+CONFIG_MMU=y
+# CONFIG_HOTPLUG is not set
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_MISC is not set
+CONFIG_TRAD_SIGNALS=y
+# CONFIG_BINFMT_IRIX is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_UMEM is not set
+CONFIG_BLK_DEV_LOOP=y
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_SIZE=4096
+# CONFIG_BLK_DEV_INITRD is not set
+# CONFIG_LBD is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+CONFIG_SCSI=y
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=y
+# CONFIG_CHR_DEV_ST is not set
+# CONFIG_CHR_DEV_OSST is not set
+# CONFIG_BLK_DEV_SR is not set
+# CONFIG_CHR_DEV_SG is not set
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+# CONFIG_SCSI_MULTI_LUN is not set
+# CONFIG_SCSI_REPORT_LUNS is not set
+# CONFIG_SCSI_CONSTANTS is not set
+# CONFIG_SCSI_LOGGING is not set
+
+#
+# SCSI low-level drivers
+#
+# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
+# CONFIG_SCSI_ACARD is not set
+# CONFIG_SCSI_AACRAID is not set
+# CONFIG_SCSI_AIC7XXX is not set
+# CONFIG_SCSI_AIC7XXX_OLD is not set
+# CONFIG_SCSI_AIC79XX is not set
+# CONFIG_SCSI_ADVANSYS is not set
+# CONFIG_SCSI_MEGARAID is not set
+# CONFIG_SCSI_SATA is not set
+# CONFIG_SCSI_BUSLOGIC is not set
+# CONFIG_SCSI_CPQFCTS is not set
+# CONFIG_SCSI_DMX3191D is not set
+# CONFIG_SCSI_EATA is not set
+# CONFIG_SCSI_EATA_PIO is not set
+# CONFIG_SCSI_FUTURE_DOMAIN is not set
+# CONFIG_SCSI_GDTH is not set
+# CONFIG_SCSI_IPS is not set
+# CONFIG_SCSI_INIA100 is not set
+# CONFIG_SCSI_SYM53C8XX_2 is not set
+# CONFIG_SCSI_QLOGIC_ISP is not set
+# CONFIG_SCSI_QLOGIC_FC is not set
+# CONFIG_SCSI_QLOGIC_1280 is not set
+CONFIG_SCSI_QLA2XXX=y
+# CONFIG_SCSI_QLA21XX is not set
+# CONFIG_SCSI_QLA22XX is not set
+# CONFIG_SCSI_QLA2300 is not set
+# CONFIG_SCSI_QLA2322 is not set
+# CONFIG_SCSI_QLA6312 is not set
+# CONFIG_SCSI_QLA6322 is not set
+# CONFIG_SCSI_DC395x is not set
+# CONFIG_SCSI_DC390T is not set
+# CONFIG_SCSI_NSP32 is not set
+# CONFIG_SCSI_DEBUG is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+# CONFIG_FUSION is not set
+
+#
+# IEEE 1394 (FireWire) support (EXPERIMENTAL)
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+
+#
+# Macintosh device drivers
+#
+
+#
+# Networking support
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+CONFIG_NETLINK_DEV=y
+CONFIG_UNIX=y
+CONFIG_NET_KEY=y
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_PNP=y
+# CONFIG_IP_PNP_DHCP is not set
+# CONFIG_IP_PNP_BOOTP is not set
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_ARPD is not set
+# CONFIG_INET_ECN is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_IPV6 is not set
+# CONFIG_DECNET is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_NETFILTER is not set
+CONFIG_XFRM=y
+# CONFIG_XFRM_USER is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+CONFIG_IPV6_SCTP__=y
+# CONFIG_IP_SCTP is not set
+# CONFIG_ATM is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_FASTROUTE is not set
+# CONFIG_NET_HW_FLOWCONTROL is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+CONFIG_NETDEVICES=y
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+# CONFIG_ETHERTAP is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+# CONFIG_MII is not set
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_SUNGEM is not set
+# CONFIG_NET_VENDOR_3COM is not set
+
+#
+# Tulip family network device support
+#
+# CONFIG_NET_TULIP is not set
+# CONFIG_HP100 is not set
+# CONFIG_NET_PCI is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+# CONFIG_E1000 is not set
+# CONFIG_NS83820 is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+# CONFIG_R8169 is not set
+# CONFIG_SIS190 is not set
+# CONFIG_SK98LIN is not set
+# CONFIG_TIGON3 is not set
+
+#
+# Ethernet (10000 Mbit)
+#
+# CONFIG_IXGB is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Token Ring devices
+#
+# CONFIG_TR is not set
+# CONFIG_NET_FC is not set
+# CONFIG_RCPCI is not set
+# CONFIG_SHAPER is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+
+#
+# Amateur Radio support
+#
+# CONFIG_HAMRADIO is not set
+
+#
+# IrDA (infrared) support
+#
+# CONFIG_IRDA is not set
+
+#
+# Bluetooth support
+#
+# CONFIG_BT is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN_BOOL is not set
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+CONFIG_INPUT_MOUSEDEV_PSAUX=y
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+# CONFIG_INPUT_EVDEV is not set
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input I/O drivers
+#
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+CONFIG_SERIO=y
+# CONFIG_SERIO_I8042 is not set
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_CT82C710 is not set
+# CONFIG_SERIO_PCIPS2 is not set
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=4
+# CONFIG_SERIAL_8250_EXTENDED is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+CONFIG_UNIX98_PTY_COUNT=256
+
+#
+# Mice
+#
+# CONFIG_BUSMOUSE is not set
+# CONFIG_QIC02_TAPE is not set
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_NVRAM is not set
+# CONFIG_RTC is not set
+# CONFIG_GEN_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_FTAPE is not set
+# CONFIG_AGP is not set
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+# CONFIG_MDA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+# CONFIG_USB is not set
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_JBD is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_QUOTA is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_FAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+# CONFIG_DEVFS_FS is not set
+CONFIG_DEVPTS_FS=y
+CONFIG_DEVPTS_FS_XATTR=y
+CONFIG_DEVPTS_FS_SECURITY=y
+# CONFIG_TMPFS is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
+# CONFIG_NFSD is not set
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+# CONFIG_EXPORTFS is not set
+CONFIG_SUNRPC=y
+# CONFIG_SUNRPC_GSS is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_INTERMEZZO_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+
+#
+# Native Language Support
+#
+# CONFIG_NLS is not set
+
+#
+# Kernel hacking
+#
+CONFIG_CROSSCOMPILE=y
+CONFIG_CMDLINE=""
+# CONFIG_DEBUG_KERNEL is not set
+
+#
+# Security options
+#
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
+# Library routines
+#
+# CONFIG_CRC32 is not set
--- diff/arch/mips/configs/bosporus_defconfig	1970-01-01 01:00:00.000000000 +0100
+++ source/arch/mips/configs/bosporus_defconfig	2004-02-23 13:56:38.000000000 +0000
@@ -0,0 +1,673 @@
+#
+# Automatically generated make config: don't edit
+#
+CONFIG_MIPS=y
+# CONFIG_MIPS64 is not set
+# CONFIG_64BIT is not set
+CONFIG_MIPS32=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_CLEAN_COMPILE=y
+CONFIG_STANDALONE=y
+CONFIG_BROKEN_ON_SMP=y
+
+#
+# General setup
+#
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_IKCONFIG is not set
+CONFIG_EMBEDDED=y
+CONFIG_KALLSYMS=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+CONFIG_OBSOLETE_MODPARM=y
+CONFIG_MODVERSIONS=y
+CONFIG_KMOD=y
+
+#
+# Machine selection
+#
+# CONFIG_MACH_JAZZ is not set
+# CONFIG_BAGET_MIPS is not set
+# CONFIG_MACH_VR41XX is not set
+# CONFIG_TOSHIBA_JMR3927 is not set
+# CONFIG_MIPS_COBALT is not set
+# CONFIG_MACH_DECSTATION is not set
+# CONFIG_MIPS_EV64120 is not set
+# CONFIG_MIPS_EV96100 is not set
+# CONFIG_MIPS_IVR is not set
+# CONFIG_LASAT is not set
+# CONFIG_HP_LASERJET is not set
+# CONFIG_MIPS_ITE8172 is not set
+# CONFIG_MIPS_ATLAS is not set
+# CONFIG_MIPS_MALTA is not set
+# CONFIG_MIPS_SEAD is not set
+# CONFIG_MOMENCO_OCELOT is not set
+# CONFIG_MOMENCO_OCELOT_G is not set
+# CONFIG_MOMENCO_OCELOT_C is not set
+# CONFIG_MOMENCO_JAGUAR_ATX is not set
+# CONFIG_PMC_YOSEMITE is not set
+# CONFIG_DDB5074 is not set
+# CONFIG_DDB5476 is not set
+# CONFIG_DDB5477 is not set
+# CONFIG_NEC_OSPREY is not set
+# CONFIG_SGI_IP22 is not set
+# CONFIG_SGI_IP32 is not set
+# CONFIG_SOC_AU1X00 is not set
+# CONFIG_SIBYTE_SB1xxx_SOC is not set
+# CONFIG_SNI_RM200_PCI is not set
+# CONFIG_TOSHIBA_RBTX4927 is not set
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_HAVE_DEC_LOCK=y
+CONFIG_CPU_LITTLE_ENDIAN=y
+CONFIG_MIPS_L1_CACHE_SHIFT=5
+# CONFIG_FB is not set
+
+#
+# CPU selection
+#
+CONFIG_CPU_MIPS32=y
+# CONFIG_CPU_MIPS64 is not set
+# CONFIG_CPU_R3000 is not set
+# CONFIG_CPU_TX39XX is not set
+# CONFIG_CPU_VR41XX is not set
+# CONFIG_CPU_R4300 is not set
+# CONFIG_CPU_R4X00 is not set
+# CONFIG_CPU_TX49XX is not set
+# CONFIG_CPU_R5000 is not set
+# CONFIG_CPU_R5432 is not set
+# CONFIG_CPU_R6000 is not set
+# CONFIG_CPU_NEVADA is not set
+# CONFIG_CPU_R8000 is not set
+# CONFIG_CPU_R10000 is not set
+# CONFIG_CPU_RM7000 is not set
+# CONFIG_CPU_RM9000 is not set
+# CONFIG_CPU_SB1 is not set
+CONFIG_PAGE_SIZE_4KB=y
+# CONFIG_PAGE_SIZE_16KB is not set
+# CONFIG_PAGE_SIZE_64KB is not set
+CONFIG_CPU_HAS_PREFETCH=y
+# CONFIG_VTAG_ICACHE is not set
+# CONFIG_64BIT_PHYS_ADDR is not set
+# CONFIG_CPU_ADVANCED is not set
+CONFIG_CPU_HAS_LLSC=y
+CONFIG_CPU_HAS_SYNC=y
+# CONFIG_PREEMPT is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+
+#
+# Bus options (PCI, PCMCIA, EISA, ISA, TC)
+#
+CONFIG_MMU=y
+CONFIG_HOTPLUG=y
+
+#
+# PCMCIA/CardBus support
+#
+CONFIG_PCMCIA=m
+# CONFIG_TCIC is not set
+
+#
+# PCI Hotplug Support
+#
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_MISC is not set
+CONFIG_TRAD_SIGNALS=y
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+# CONFIG_FW_LOADER is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+CONFIG_BLK_DEV_LOOP=y
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_RAM is not set
+# CONFIG_BLK_DEV_INITRD is not set
+# CONFIG_LBD is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_SCSI is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+
+#
+# IEEE 1394 (FireWire) support (EXPERIMENTAL)
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+
+#
+# Macintosh device drivers
+#
+
+#
+# Networking support
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+CONFIG_NETLINK_DEV=y
+CONFIG_UNIX=y
+CONFIG_NET_KEY=y
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_PNP=y
+# CONFIG_IP_PNP_DHCP is not set
+CONFIG_IP_PNP_BOOTP=y
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_IP_MROUTE is not set
+# CONFIG_ARPD is not set
+# CONFIG_INET_ECN is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+
+#
+# IP: Virtual Server Configuration
+#
+# CONFIG_IP_VS is not set
+# CONFIG_IPV6 is not set
+# CONFIG_DECNET is not set
+# CONFIG_BRIDGE is not set
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
+
+#
+# IP: Netfilter Configuration
+#
+# CONFIG_IP_NF_CONNTRACK is not set
+# CONFIG_IP_NF_QUEUE is not set
+# CONFIG_IP_NF_IPTABLES is not set
+# CONFIG_IP_NF_ARPTABLES is not set
+# CONFIG_IP_NF_COMPAT_IPCHAINS is not set
+# CONFIG_IP_NF_COMPAT_IPFWADM is not set
+CONFIG_XFRM=y
+# CONFIG_XFRM_USER is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+CONFIG_IPV6_SCTP__=y
+# CONFIG_IP_SCTP is not set
+# CONFIG_ATM is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_FASTROUTE is not set
+# CONFIG_NET_HW_FLOWCONTROL is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+# CONFIG_ETHERTAP is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+# CONFIG_MII is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+
+#
+# Ethernet (10000 Mbit)
+#
+CONFIG_PPP=m
+CONFIG_PPP_MULTILINK=y
+# CONFIG_PPP_FILTER is not set
+CONFIG_PPP_ASYNC=m
+# CONFIG_PPP_SYNC_TTY is not set
+CONFIG_PPP_DEFLATE=m
+# CONFIG_PPP_BSDCOMP is not set
+CONFIG_PPPOE=m
+# CONFIG_SLIP is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Token Ring devices
+#
+# CONFIG_SHAPER is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+
+#
+# PCMCIA network device support
+#
+CONFIG_NET_PCMCIA=y
+CONFIG_PCMCIA_3C589=m
+# CONFIG_PCMCIA_3C574 is not set
+# CONFIG_PCMCIA_FMVJ18X is not set
+# CONFIG_PCMCIA_PCNET is not set
+# CONFIG_PCMCIA_NMCLAN is not set
+# CONFIG_PCMCIA_SMC91C92 is not set
+# CONFIG_PCMCIA_XIRC2PS is not set
+# CONFIG_PCMCIA_AXNET is not set
+
+#
+# Amateur Radio support
+#
+# CONFIG_HAMRADIO is not set
+
+#
+# IrDA (infrared) support
+#
+# CONFIG_IRDA is not set
+
+#
+# Bluetooth support
+#
+# CONFIG_BT is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN_BOOL is not set
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+CONFIG_INPUT_MOUSEDEV_PSAUX=y
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input I/O drivers
+#
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+CONFIG_SERIO=y
+# CONFIG_SERIO_I8042 is not set
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_CT82C710 is not set
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_UNIX98_PTYS=y
+CONFIG_UNIX98_PTY_COUNT=256
+
+#
+# Mice
+#
+# CONFIG_BUSMOUSE is not set
+# CONFIG_QIC02_TAPE is not set
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_NVRAM is not set
+CONFIG_RTC=y
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_FTAPE is not set
+# CONFIG_AGP is not set
+# CONFIG_DRM is not set
+
+#
+# PCMCIA character devices
+#
+# CONFIG_SYNCLINK_CS is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+# CONFIG_MDA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+CONFIG_EXT2_FS_XATTR=y
+CONFIG_EXT2_FS_POSIX_ACL=y
+# CONFIG_EXT2_FS_SECURITY is not set
+CONFIG_EXT3_FS=y
+CONFIG_EXT3_FS_XATTR=y
+CONFIG_EXT3_FS_POSIX_ACL=y
+CONFIG_EXT3_FS_SECURITY=y
+CONFIG_JBD=y
+# CONFIG_JBD_DEBUG is not set
+CONFIG_FS_MBCACHE=y
+CONFIG_REISERFS_FS=m
+# CONFIG_REISERFS_CHECK is not set
+# CONFIG_REISERFS_PROC_INFO is not set
+# CONFIG_JFS_FS is not set
+CONFIG_FS_POSIX_ACL=y
+# CONFIG_XFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_QUOTA is not set
+CONFIG_AUTOFS_FS=m
+CONFIG_AUTOFS4_FS=m
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_FAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+# CONFIG_DEVFS_FS is not set
+CONFIG_DEVPTS_FS=y
+CONFIG_DEVPTS_FS_XATTR=y
+CONFIG_DEVPTS_FS_SECURITY=y
+CONFIG_TMPFS=y
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+CONFIG_CRAMFS=m
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+# CONFIG_NFS_V3 is not set
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
+CONFIG_NFSD=m
+# CONFIG_NFSD_V3 is not set
+# CONFIG_NFSD_TCP is not set
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+CONFIG_EXPORTFS=m
+CONFIG_SUNRPC=y
+# CONFIG_SUNRPC_GSS is not set
+CONFIG_SMB_FS=m
+# CONFIG_SMB_NLS_DEFAULT is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_INTERMEZZO_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+
+#
+# Native Language Support
+#
+CONFIG_NLS=m
+CONFIG_NLS_DEFAULT="iso8859-1"
+# CONFIG_NLS_CODEPAGE_437 is not set
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ISO8859_1 is not set
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+# CONFIG_NLS_UTF8 is not set
+
+#
+# Kernel hacking
+#
+CONFIG_CROSSCOMPILE=y
+CONFIG_CMDLINE=""
+# CONFIG_DEBUG_KERNEL is not set
+
+#
+# Security options
+#
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+CONFIG_CRYPTO=y
+CONFIG_CRYPTO_HMAC=y
+CONFIG_CRYPTO_NULL=y
+# CONFIG_CRYPTO_MD4 is not set
+# CONFIG_CRYPTO_MD5 is not set
+# CONFIG_CRYPTO_SHA1 is not set
+# CONFIG_CRYPTO_SHA256 is not set
+CONFIG_CRYPTO_SHA512=y
+# CONFIG_CRYPTO_DES is not set
+# CONFIG_CRYPTO_BLOWFISH is not set
+CONFIG_CRYPTO_TWOFISH=y
+# CONFIG_CRYPTO_SERPENT is not set
+CONFIG_CRYPTO_AES=y
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+CONFIG_CRYPTO_DEFLATE=y
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Library routines
+#
+CONFIG_CRC32=y
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
--- diff/arch/mips/configs/capcella_defconfig	1970-01-01 01:00:00.000000000 +0100
+++ source/arch/mips/configs/capcella_defconfig	2004-02-23 13:56:38.000000000 +0000
@@ -0,0 +1,640 @@
+#
+# Automatically generated make config: don't edit
+#
+CONFIG_MIPS=y
+# CONFIG_MIPS64 is not set
+# CONFIG_64BIT is not set
+CONFIG_MIPS32=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_CLEAN_COMPILE=y
+CONFIG_STANDALONE=y
+CONFIG_BROKEN_ON_SMP=y
+
+#
+# General setup
+#
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_IKCONFIG is not set
+CONFIG_EMBEDDED=y
+CONFIG_KALLSYMS=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+CONFIG_OBSOLETE_MODPARM=y
+CONFIG_MODVERSIONS=y
+CONFIG_KMOD=y
+
+#
+# Machine selection
+#
+# CONFIG_MACH_JAZZ is not set
+# CONFIG_BAGET_MIPS is not set
+CONFIG_MACH_VR41XX=y
+# CONFIG_CASIO_E55 is not set
+# CONFIG_IBM_WORKPAD is not set
+# CONFIG_NEC_EAGLE is not set
+# CONFIG_TANBAC_TB0226 is not set
+# CONFIG_TANBAC_TB0229 is not set
+# CONFIG_VICTOR_MPC30X is not set
+CONFIG_ZAO_CAPCELLA=y
+# CONFIG_TOSHIBA_JMR3927 is not set
+# CONFIG_MIPS_COBALT is not set
+# CONFIG_MACH_DECSTATION is not set
+# CONFIG_MIPS_EV64120 is not set
+# CONFIG_MIPS_EV96100 is not set
+# CONFIG_MIPS_IVR is not set
+# CONFIG_LASAT is not set
+# CONFIG_HP_LASERJET is not set
+# CONFIG_MIPS_ITE8172 is not set
+# CONFIG_MIPS_ATLAS is not set
+# CONFIG_MIPS_MALTA is not set
+# CONFIG_MIPS_SEAD is not set
+# CONFIG_MOMENCO_OCELOT is not set
+# CONFIG_MOMENCO_OCELOT_G is not set
+# CONFIG_MOMENCO_OCELOT_C is not set
+# CONFIG_MOMENCO_JAGUAR_ATX is not set
+# CONFIG_PMC_YOSEMITE is not set
+# CONFIG_DDB5074 is not set
+# CONFIG_DDB5476 is not set
+# CONFIG_DDB5477 is not set
+# CONFIG_NEC_OSPREY is not set
+# CONFIG_SGI_IP22 is not set
+# CONFIG_SGI_IP32 is not set
+# CONFIG_SOC_AU1X00 is not set
+# CONFIG_SIBYTE_SB1xxx_SOC is not set
+# CONFIG_SNI_RM200_PCI is not set
+# CONFIG_TOSHIBA_RBTX4927 is not set
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_HAVE_DEC_LOCK=y
+CONFIG_DMA_NONCOHERENT=y
+CONFIG_CPU_LITTLE_ENDIAN=y
+CONFIG_IRQ_CPU=y
+CONFIG_DUMMY_KEYB=y
+CONFIG_MIPS_L1_CACHE_SHIFT=5
+# CONFIG_FB is not set
+
+#
+# CPU selection
+#
+# CONFIG_CPU_MIPS32 is not set
+# CONFIG_CPU_MIPS64 is not set
+# CONFIG_CPU_R3000 is not set
+# CONFIG_CPU_TX39XX is not set
+CONFIG_CPU_VR41XX=y
+# CONFIG_CPU_R4300 is not set
+# CONFIG_CPU_R4X00 is not set
+# CONFIG_CPU_TX49XX is not set
+# CONFIG_CPU_R5000 is not set
+# CONFIG_CPU_R5432 is not set
+# CONFIG_CPU_R6000 is not set
+# CONFIG_CPU_NEVADA is not set
+# CONFIG_CPU_R8000 is not set
+# CONFIG_CPU_R10000 is not set
+# CONFIG_CPU_RM7000 is not set
+# CONFIG_CPU_RM9000 is not set
+# CONFIG_CPU_SB1 is not set
+CONFIG_PAGE_SIZE_4KB=y
+# CONFIG_PAGE_SIZE_16KB is not set
+# CONFIG_PAGE_SIZE_64KB is not set
+# CONFIG_CPU_ADVANCED is not set
+CONFIG_CPU_HAS_SYNC=y
+# CONFIG_PREEMPT is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+
+#
+# Bus options (PCI, PCMCIA, EISA, ISA, TC)
+#
+CONFIG_PCI=y
+CONFIG_PCI_LEGACY_PROC=y
+CONFIG_PCI_NAMES=y
+CONFIG_MMU=y
+# CONFIG_HOTPLUG is not set
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_MISC is not set
+CONFIG_TRAD_SIGNALS=y
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_UMEM is not set
+# CONFIG_BLK_DEV_LOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_RAM is not set
+# CONFIG_BLK_DEV_INITRD is not set
+# CONFIG_LBD is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+CONFIG_IDE=y
+CONFIG_BLK_DEV_IDE=y
+
+#
+# Please see Documentation/ide.txt for help/info on IDE drives
+#
+CONFIG_BLK_DEV_IDEDISK=y
+# CONFIG_IDEDISK_MULTI_MODE is not set
+# CONFIG_IDEDISK_STROKE is not set
+# CONFIG_BLK_DEV_IDECD is not set
+# CONFIG_BLK_DEV_IDETAPE is not set
+# CONFIG_BLK_DEV_IDEFLOPPY is not set
+# CONFIG_IDE_TASK_IOCTL is not set
+CONFIG_IDE_TASKFILE_IO=y
+
+#
+# IDE chipset support/bugfixes
+#
+CONFIG_IDE_GENERIC=y
+# CONFIG_BLK_DEV_IDEPCI is not set
+# CONFIG_BLK_DEV_IDEDMA is not set
+# CONFIG_IDEDMA_AUTO is not set
+# CONFIG_DMA_NONPCI is not set
+# CONFIG_BLK_DEV_HD is not set
+
+#
+# SCSI device support
+#
+# CONFIG_SCSI is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+
+#
+# IEEE 1394 (FireWire) support (EXPERIMENTAL)
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+
+#
+# Macintosh device drivers
+#
+
+#
+# Networking support
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+CONFIG_PACKET_MMAP=y
+CONFIG_NETLINK_DEV=y
+CONFIG_UNIX=y
+CONFIG_NET_KEY=y
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_PNP=y
+# CONFIG_IP_PNP_DHCP is not set
+CONFIG_IP_PNP_BOOTP=y
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_IP_MROUTE is not set
+# CONFIG_ARPD is not set
+# CONFIG_INET_ECN is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_IPV6 is not set
+# CONFIG_DECNET is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_NETFILTER is not set
+CONFIG_XFRM=y
+# CONFIG_XFRM_USER is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+CONFIG_IPV6_SCTP__=y
+# CONFIG_IP_SCTP is not set
+# CONFIG_ATM is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_FASTROUTE is not set
+# CONFIG_NET_HW_FLOWCONTROL is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+CONFIG_NETDEVICES=y
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+# CONFIG_ETHERTAP is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+# CONFIG_MII is not set
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_SUNGEM is not set
+# CONFIG_NET_VENDOR_3COM is not set
+
+#
+# Tulip family network device support
+#
+# CONFIG_NET_TULIP is not set
+# CONFIG_HP100 is not set
+# CONFIG_NET_PCI is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+# CONFIG_E1000 is not set
+# CONFIG_NS83820 is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+# CONFIG_R8169 is not set
+# CONFIG_SIS190 is not set
+# CONFIG_SK98LIN is not set
+# CONFIG_TIGON3 is not set
+
+#
+# Ethernet (10000 Mbit)
+#
+# CONFIG_IXGB is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Token Ring devices
+#
+# CONFIG_TR is not set
+# CONFIG_RCPCI is not set
+# CONFIG_SHAPER is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+
+#
+# Amateur Radio support
+#
+# CONFIG_HAMRADIO is not set
+
+#
+# IrDA (infrared) support
+#
+# CONFIG_IRDA is not set
+
+#
+# Bluetooth support
+#
+# CONFIG_BT is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN_BOOL is not set
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+CONFIG_INPUT_MOUSEDEV_PSAUX=y
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+# CONFIG_INPUT_EVDEV is not set
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input I/O drivers
+#
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+CONFIG_SERIO=y
+CONFIG_SERIO_I8042=y
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_CT82C710 is not set
+# CONFIG_SERIO_PCIPS2 is not set
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=4
+# CONFIG_SERIAL_8250_EXTENDED is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+CONFIG_UNIX98_PTY_COUNT=256
+
+#
+# Mice
+#
+# CONFIG_BUSMOUSE is not set
+# CONFIG_QIC02_TAPE is not set
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+CONFIG_WATCHDOG=y
+# CONFIG_WATCHDOG_NOWAYOUT is not set
+
+#
+# Watchdog Device Drivers
+#
+# CONFIG_SOFT_WATCHDOG is not set
+
+#
+# PCI-based Watchdog Cards
+#
+# CONFIG_PCIPCWATCHDOG is not set
+# CONFIG_WDTPCI is not set
+# CONFIG_NVRAM is not set
+# CONFIG_RTC is not set
+# CONFIG_GEN_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_FTAPE is not set
+# CONFIG_AGP is not set
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+# CONFIG_MDA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+# CONFIG_USB is not set
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_JBD is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_QUOTA is not set
+CONFIG_AUTOFS_FS=y
+CONFIG_AUTOFS4_FS=y
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_FAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+# CONFIG_DEVFS_FS is not set
+CONFIG_DEVPTS_FS=y
+CONFIG_DEVPTS_FS_XATTR=y
+CONFIG_DEVPTS_FS_SECURITY=y
+# CONFIG_TMPFS is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+# CONFIG_NFS_V3 is not set
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
+CONFIG_NFSD=y
+# CONFIG_NFSD_V3 is not set
+# CONFIG_NFSD_TCP is not set
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+CONFIG_EXPORTFS=y
+CONFIG_SUNRPC=y
+# CONFIG_SUNRPC_GSS is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_INTERMEZZO_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+
+#
+# Native Language Support
+#
+# CONFIG_NLS is not set
+
+#
+# Kernel hacking
+#
+CONFIG_CROSSCOMPILE=y
+CONFIG_CMDLINE=""
+# CONFIG_DEBUG_KERNEL is not set
+
+#
+# Security options
+#
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
+# Library routines
+#
+# CONFIG_CRC32 is not set
--- diff/arch/mips/configs/cobalt_defconfig	1970-01-01 01:00:00.000000000 +0100
+++ source/arch/mips/configs/cobalt_defconfig	2004-02-23 13:56:38.000000000 +0000
@@ -0,0 +1,617 @@
+#
+# Automatically generated make config: don't edit
+#
+CONFIG_MIPS=y
+# CONFIG_MIPS64 is not set
+# CONFIG_64BIT is not set
+CONFIG_MIPS32=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_CLEAN_COMPILE=y
+CONFIG_STANDALONE=y
+CONFIG_BROKEN_ON_SMP=y
+
+#
+# General setup
+#
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_IKCONFIG is not set
+CONFIG_EMBEDDED=y
+CONFIG_KALLSYMS=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+
+#
+# Loadable module support
+#
+# CONFIG_MODULES is not set
+
+#
+# Machine selection
+#
+# CONFIG_MACH_JAZZ is not set
+# CONFIG_BAGET_MIPS is not set
+# CONFIG_MACH_VR41XX is not set
+# CONFIG_TOSHIBA_JMR3927 is not set
+CONFIG_MIPS_COBALT=y
+# CONFIG_MACH_DECSTATION is not set
+# CONFIG_MIPS_EV64120 is not set
+# CONFIG_MIPS_EV96100 is not set
+# CONFIG_MIPS_IVR is not set
+# CONFIG_LASAT is not set
+# CONFIG_HP_LASERJET is not set
+# CONFIG_MIPS_ITE8172 is not set
+# CONFIG_MIPS_ATLAS is not set
+# CONFIG_MIPS_MALTA is not set
+# CONFIG_MIPS_SEAD is not set
+# CONFIG_MOMENCO_OCELOT is not set
+# CONFIG_MOMENCO_OCELOT_G is not set
+# CONFIG_MOMENCO_OCELOT_C is not set
+# CONFIG_MOMENCO_JAGUAR_ATX is not set
+# CONFIG_PMC_YOSEMITE is not set
+# CONFIG_DDB5074 is not set
+# CONFIG_DDB5476 is not set
+# CONFIG_DDB5477 is not set
+# CONFIG_NEC_OSPREY is not set
+# CONFIG_SGI_IP22 is not set
+# CONFIG_SGI_IP32 is not set
+# CONFIG_SOC_AU1X00 is not set
+# CONFIG_SIBYTE_SB1xxx_SOC is not set
+# CONFIG_SNI_RM200_PCI is not set
+# CONFIG_TOSHIBA_RBTX4927 is not set
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_HAVE_DEC_LOCK=y
+CONFIG_DMA_NONCOHERENT=y
+CONFIG_I8259=y
+CONFIG_CPU_LITTLE_ENDIAN=y
+CONFIG_IRQ_CPU=y
+CONFIG_MIPS_GT64111=y
+CONFIG_COBALT_LCD=y
+CONFIG_MIPS_L1_CACHE_SHIFT=5
+# CONFIG_FB is not set
+
+#
+# CPU selection
+#
+# CONFIG_CPU_MIPS32 is not set
+# CONFIG_CPU_MIPS64 is not set
+# CONFIG_CPU_R3000 is not set
+# CONFIG_CPU_TX39XX is not set
+# CONFIG_CPU_VR41XX is not set
+# CONFIG_CPU_R4300 is not set
+# CONFIG_CPU_R4X00 is not set
+# CONFIG_CPU_TX49XX is not set
+# CONFIG_CPU_R5000 is not set
+# CONFIG_CPU_R5432 is not set
+# CONFIG_CPU_R6000 is not set
+CONFIG_CPU_NEVADA=y
+# CONFIG_CPU_R8000 is not set
+# CONFIG_CPU_R10000 is not set
+# CONFIG_CPU_RM7000 is not set
+# CONFIG_CPU_RM9000 is not set
+# CONFIG_CPU_SB1 is not set
+CONFIG_PAGE_SIZE_4KB=y
+# CONFIG_PAGE_SIZE_16KB is not set
+# CONFIG_PAGE_SIZE_64KB is not set
+# CONFIG_CPU_ADVANCED is not set
+CONFIG_CPU_HAS_LLSC=y
+CONFIG_CPU_HAS_LLDSCD=y
+CONFIG_CPU_HAS_SYNC=y
+# CONFIG_PREEMPT is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+
+#
+# Bus options (PCI, PCMCIA, EISA, ISA, TC)
+#
+CONFIG_PCI=y
+CONFIG_PCI_LEGACY_PROC=y
+CONFIG_PCI_NAMES=y
+CONFIG_MMU=y
+# CONFIG_HOTPLUG is not set
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_MISC is not set
+CONFIG_TRAD_SIGNALS=y
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_UMEM is not set
+CONFIG_BLK_DEV_LOOP=y
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_RAM is not set
+# CONFIG_BLK_DEV_INITRD is not set
+# CONFIG_LBD is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+CONFIG_IDE=y
+CONFIG_BLK_DEV_IDE=y
+
+#
+# Please see Documentation/ide.txt for help/info on IDE drives
+#
+CONFIG_BLK_DEV_IDEDISK=y
+# CONFIG_IDEDISK_MULTI_MODE is not set
+# CONFIG_IDEDISK_STROKE is not set
+# CONFIG_BLK_DEV_IDECD is not set
+# CONFIG_BLK_DEV_IDETAPE is not set
+# CONFIG_BLK_DEV_IDEFLOPPY is not set
+# CONFIG_IDE_TASK_IOCTL is not set
+CONFIG_IDE_TASKFILE_IO=y
+
+#
+# IDE chipset support/bugfixes
+#
+CONFIG_IDE_GENERIC=y
+# CONFIG_BLK_DEV_IDEPCI is not set
+# CONFIG_BLK_DEV_IDEDMA is not set
+# CONFIG_IDEDMA_AUTO is not set
+# CONFIG_DMA_NONPCI is not set
+# CONFIG_BLK_DEV_HD is not set
+
+#
+# SCSI device support
+#
+# CONFIG_SCSI is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+
+#
+# IEEE 1394 (FireWire) support (EXPERIMENTAL)
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+
+#
+# Macintosh device drivers
+#
+
+#
+# Networking support
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+CONFIG_NETLINK_DEV=y
+CONFIG_UNIX=y
+CONFIG_NET_KEY=y
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+# CONFIG_IP_PNP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_ARPD is not set
+# CONFIG_INET_ECN is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_IPV6 is not set
+# CONFIG_DECNET is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_NETFILTER is not set
+CONFIG_XFRM=y
+# CONFIG_XFRM_USER is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+CONFIG_IPV6_SCTP__=y
+# CONFIG_IP_SCTP is not set
+# CONFIG_ATM is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_FASTROUTE is not set
+# CONFIG_NET_HW_FLOWCONTROL is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+CONFIG_NETDEVICES=y
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+# CONFIG_ETHERTAP is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+# CONFIG_MII is not set
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_SUNGEM is not set
+# CONFIG_NET_VENDOR_3COM is not set
+
+#
+# Tulip family network device support
+#
+# CONFIG_NET_TULIP is not set
+# CONFIG_HP100 is not set
+# CONFIG_NET_PCI is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+# CONFIG_E1000 is not set
+# CONFIG_NS83820 is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+# CONFIG_R8169 is not set
+# CONFIG_SIS190 is not set
+# CONFIG_SK98LIN is not set
+# CONFIG_TIGON3 is not set
+
+#
+# Ethernet (10000 Mbit)
+#
+# CONFIG_IXGB is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Token Ring devices
+#
+# CONFIG_TR is not set
+# CONFIG_RCPCI is not set
+# CONFIG_SHAPER is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+
+#
+# Amateur Radio support
+#
+# CONFIG_HAMRADIO is not set
+
+#
+# IrDA (infrared) support
+#
+# CONFIG_IRDA is not set
+
+#
+# Bluetooth support
+#
+# CONFIG_BT is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN_BOOL is not set
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+CONFIG_INPUT_MOUSEDEV_PSAUX=y
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+# CONFIG_INPUT_EVDEV is not set
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input I/O drivers
+#
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+CONFIG_SERIO=y
+# CONFIG_SERIO_I8042 is not set
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_CT82C710 is not set
+# CONFIG_SERIO_PCIPS2 is not set
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=4
+# CONFIG_SERIAL_8250_EXTENDED is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+CONFIG_UNIX98_PTY_COUNT=16
+
+#
+# Mice
+#
+# CONFIG_BUSMOUSE is not set
+# CONFIG_QIC02_TAPE is not set
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_NVRAM is not set
+CONFIG_RTC=y
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_FTAPE is not set
+# CONFIG_AGP is not set
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+# CONFIG_MDA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+# CONFIG_USB is not set
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+CONFIG_EXT2_FS_XATTR=y
+CONFIG_EXT2_FS_POSIX_ACL=y
+CONFIG_EXT2_FS_SECURITY=y
+# CONFIG_EXT3_FS is not set
+# CONFIG_JBD is not set
+CONFIG_FS_MBCACHE=y
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+CONFIG_FS_POSIX_ACL=y
+# CONFIG_XFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_QUOTA is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_FAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+# CONFIG_DEVFS_FS is not set
+CONFIG_DEVPTS_FS=y
+CONFIG_DEVPTS_FS_XATTR=y
+CONFIG_DEVPTS_FS_SECURITY=y
+# CONFIG_TMPFS is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+# CONFIG_NFS_V3 is not set
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
+# CONFIG_NFSD is not set
+CONFIG_LOCKD=y
+# CONFIG_EXPORTFS is not set
+CONFIG_SUNRPC=y
+# CONFIG_SUNRPC_GSS is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_INTERMEZZO_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+
+#
+# Native Language Support
+#
+# CONFIG_NLS is not set
+
+#
+# Kernel hacking
+#
+CONFIG_CROSSCOMPILE=y
+CONFIG_CMDLINE=""
+# CONFIG_DEBUG_KERNEL is not set
+
+#
+# Security options
+#
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
+# Library routines
+#
+# CONFIG_CRC32 is not set
--- diff/arch/mips/configs/db1000_defconfig	1970-01-01 01:00:00.000000000 +0100
+++ source/arch/mips/configs/db1000_defconfig	2004-02-23 13:56:38.000000000 +0000
@@ -0,0 +1,696 @@
+#
+# Automatically generated make config: don't edit
+#
+CONFIG_MIPS=y
+# CONFIG_MIPS64 is not set
+# CONFIG_64BIT is not set
+CONFIG_MIPS32=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_CLEAN_COMPILE=y
+CONFIG_STANDALONE=y
+CONFIG_BROKEN_ON_SMP=y
+
+#
+# General setup
+#
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_IKCONFIG is not set
+CONFIG_EMBEDDED=y
+CONFIG_KALLSYMS=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+CONFIG_OBSOLETE_MODPARM=y
+CONFIG_MODVERSIONS=y
+CONFIG_KMOD=y
+
+#
+# Machine selection
+#
+# CONFIG_MACH_JAZZ is not set
+# CONFIG_BAGET_MIPS is not set
+# CONFIG_MACH_VR41XX is not set
+# CONFIG_TOSHIBA_JMR3927 is not set
+# CONFIG_MIPS_COBALT is not set
+# CONFIG_MACH_DECSTATION is not set
+# CONFIG_MIPS_EV64120 is not set
+# CONFIG_MIPS_EV96100 is not set
+# CONFIG_MIPS_IVR is not set
+# CONFIG_LASAT is not set
+# CONFIG_HP_LASERJET is not set
+# CONFIG_MIPS_ITE8172 is not set
+# CONFIG_MIPS_ATLAS is not set
+# CONFIG_MIPS_MALTA is not set
+# CONFIG_MIPS_SEAD is not set
+# CONFIG_MOMENCO_OCELOT is not set
+# CONFIG_MOMENCO_OCELOT_G is not set
+# CONFIG_MOMENCO_OCELOT_C is not set
+# CONFIG_MOMENCO_JAGUAR_ATX is not set
+# CONFIG_PMC_YOSEMITE is not set
+# CONFIG_DDB5074 is not set
+# CONFIG_DDB5476 is not set
+# CONFIG_DDB5477 is not set
+# CONFIG_NEC_OSPREY is not set
+# CONFIG_SGI_IP22 is not set
+# CONFIG_SGI_IP32 is not set
+CONFIG_SOC_AU1X00=y
+CONFIG_SOC_AU1000=y
+# CONFIG_SOC_AU1100 is not set
+# CONFIG_SOC_AU1500 is not set
+# CONFIG_MIPS_PB1000 is not set
+# CONFIG_MIPS_PB1100 is not set
+# CONFIG_MIPS_PB1500 is not set
+CONFIG_MIPS_DB1000=y
+# CONFIG_MIPS_DB1100 is not set
+# CONFIG_MIPS_DB1500 is not set
+# CONFIG_MIPS_BOSPORUS is not set
+# CONFIG_MIPS_MIRAGE is not set
+# CONFIG_MIPS_XXS1500 is not set
+# CONFIG_MIPS_MTX1 is not set
+# CONFIG_SIBYTE_SB1xxx_SOC is not set
+# CONFIG_SNI_RM200_PCI is not set
+# CONFIG_TOSHIBA_RBTX4927 is not set
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_HAVE_DEC_LOCK=y
+CONFIG_DMA_NONCOHERENT=y
+CONFIG_CPU_LITTLE_ENDIAN=y
+CONFIG_MIPS_L1_CACHE_SHIFT=5
+# CONFIG_FB is not set
+
+#
+# CPU selection
+#
+CONFIG_CPU_MIPS32=y
+# CONFIG_CPU_MIPS64 is not set
+# CONFIG_CPU_R3000 is not set
+# CONFIG_CPU_TX39XX is not set
+# CONFIG_CPU_VR41XX is not set
+# CONFIG_CPU_R4300 is not set
+# CONFIG_CPU_R4X00 is not set
+# CONFIG_CPU_TX49XX is not set
+# CONFIG_CPU_R5000 is not set
+# CONFIG_CPU_R5432 is not set
+# CONFIG_CPU_R6000 is not set
+# CONFIG_CPU_NEVADA is not set
+# CONFIG_CPU_R8000 is not set
+# CONFIG_CPU_R10000 is not set
+# CONFIG_CPU_RM7000 is not set
+# CONFIG_CPU_RM9000 is not set
+# CONFIG_CPU_SB1 is not set
+CONFIG_PAGE_SIZE_4KB=y
+# CONFIG_PAGE_SIZE_16KB is not set
+# CONFIG_PAGE_SIZE_64KB is not set
+CONFIG_CPU_HAS_PREFETCH=y
+# CONFIG_VTAG_ICACHE is not set
+CONFIG_64BIT_PHYS_ADDR=y
+# CONFIG_CPU_ADVANCED is not set
+CONFIG_CPU_HAS_LLSC=y
+CONFIG_CPU_HAS_SYNC=y
+# CONFIG_PREEMPT is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+
+#
+# Bus options (PCI, PCMCIA, EISA, ISA, TC)
+#
+# CONFIG_PCI is not set
+CONFIG_MMU=y
+CONFIG_HOTPLUG=y
+
+#
+# PCMCIA/CardBus support
+#
+CONFIG_PCMCIA=m
+# CONFIG_TCIC is not set
+# CONFIG_PCMCIA_AU1X00 is not set
+
+#
+# PCI Hotplug Support
+#
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_MISC is not set
+CONFIG_TRAD_SIGNALS=y
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+# CONFIG_FW_LOADER is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+CONFIG_BLK_DEV_LOOP=y
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_RAM is not set
+# CONFIG_BLK_DEV_INITRD is not set
+# CONFIG_LBD is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_SCSI is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+
+#
+# IEEE 1394 (FireWire) support (EXPERIMENTAL)
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+
+#
+# Macintosh device drivers
+#
+
+#
+# Networking support
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+CONFIG_NETLINK_DEV=y
+CONFIG_UNIX=y
+CONFIG_NET_KEY=y
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_PNP=y
+# CONFIG_IP_PNP_DHCP is not set
+CONFIG_IP_PNP_BOOTP=y
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_IP_MROUTE is not set
+# CONFIG_ARPD is not set
+# CONFIG_INET_ECN is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+
+#
+# IP: Virtual Server Configuration
+#
+# CONFIG_IP_VS is not set
+# CONFIG_IPV6 is not set
+# CONFIG_DECNET is not set
+# CONFIG_BRIDGE is not set
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
+
+#
+# IP: Netfilter Configuration
+#
+# CONFIG_IP_NF_CONNTRACK is not set
+# CONFIG_IP_NF_QUEUE is not set
+# CONFIG_IP_NF_IPTABLES is not set
+# CONFIG_IP_NF_ARPTABLES is not set
+# CONFIG_IP_NF_COMPAT_IPCHAINS is not set
+# CONFIG_IP_NF_COMPAT_IPFWADM is not set
+CONFIG_XFRM=y
+# CONFIG_XFRM_USER is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+CONFIG_IPV6_SCTP__=y
+# CONFIG_IP_SCTP is not set
+# CONFIG_ATM is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_FASTROUTE is not set
+# CONFIG_NET_HW_FLOWCONTROL is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+# CONFIG_ETHERTAP is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+# CONFIG_MII is not set
+CONFIG_MIPS_AU1X00_ENET=y
+
+#
+# Ethernet (1000 Mbit)
+#
+
+#
+# Ethernet (10000 Mbit)
+#
+CONFIG_PPP=m
+CONFIG_PPP_MULTILINK=y
+# CONFIG_PPP_FILTER is not set
+CONFIG_PPP_ASYNC=m
+# CONFIG_PPP_SYNC_TTY is not set
+CONFIG_PPP_DEFLATE=m
+# CONFIG_PPP_BSDCOMP is not set
+CONFIG_PPPOE=m
+# CONFIG_SLIP is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Token Ring devices
+#
+# CONFIG_SHAPER is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+
+#
+# PCMCIA network device support
+#
+CONFIG_NET_PCMCIA=y
+CONFIG_PCMCIA_3C589=m
+# CONFIG_PCMCIA_3C574 is not set
+# CONFIG_PCMCIA_FMVJ18X is not set
+# CONFIG_PCMCIA_PCNET is not set
+# CONFIG_PCMCIA_NMCLAN is not set
+# CONFIG_PCMCIA_SMC91C92 is not set
+# CONFIG_PCMCIA_XIRC2PS is not set
+# CONFIG_PCMCIA_AXNET is not set
+
+#
+# Amateur Radio support
+#
+# CONFIG_HAMRADIO is not set
+
+#
+# IrDA (infrared) support
+#
+# CONFIG_IRDA is not set
+
+#
+# Bluetooth support
+#
+# CONFIG_BT is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN_BOOL is not set
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+CONFIG_INPUT_MOUSEDEV_PSAUX=y
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input I/O drivers
+#
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+CONFIG_SERIO=y
+# CONFIG_SERIO_I8042 is not set
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_CT82C710 is not set
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+# CONFIG_AU1X00_GPIO is not set
+# CONFIG_TS_AU1X00_ADS7846 is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_AU1X00=y
+CONFIG_SERIAL_AU1X00_CONSOLE=y
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+CONFIG_UNIX98_PTY_COUNT=256
+
+#
+# Mice
+#
+# CONFIG_BUSMOUSE is not set
+# CONFIG_QIC02_TAPE is not set
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_NVRAM is not set
+CONFIG_RTC=y
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_FTAPE is not set
+# CONFIG_AGP is not set
+# CONFIG_DRM is not set
+
+#
+# PCMCIA character devices
+#
+# CONFIG_SYNCLINK_CS is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+# CONFIG_MDA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+CONFIG_EXT2_FS_XATTR=y
+CONFIG_EXT2_FS_POSIX_ACL=y
+# CONFIG_EXT2_FS_SECURITY is not set
+CONFIG_EXT3_FS=y
+CONFIG_EXT3_FS_XATTR=y
+CONFIG_EXT3_FS_POSIX_ACL=y
+CONFIG_EXT3_FS_SECURITY=y
+CONFIG_JBD=y
+# CONFIG_JBD_DEBUG is not set
+CONFIG_FS_MBCACHE=y
+CONFIG_REISERFS_FS=m
+# CONFIG_REISERFS_CHECK is not set
+# CONFIG_REISERFS_PROC_INFO is not set
+# CONFIG_JFS_FS is not set
+CONFIG_FS_POSIX_ACL=y
+# CONFIG_XFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_QUOTA is not set
+CONFIG_AUTOFS_FS=m
+CONFIG_AUTOFS4_FS=m
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_FAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+# CONFIG_DEVFS_FS is not set
+CONFIG_DEVPTS_FS=y
+CONFIG_DEVPTS_FS_XATTR=y
+CONFIG_DEVPTS_FS_SECURITY=y
+CONFIG_TMPFS=y
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+CONFIG_CRAMFS=m
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+# CONFIG_NFS_V3 is not set
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
+CONFIG_NFSD=m
+# CONFIG_NFSD_V3 is not set
+# CONFIG_NFSD_TCP is not set
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+CONFIG_EXPORTFS=m
+CONFIG_SUNRPC=y
+# CONFIG_SUNRPC_GSS is not set
+CONFIG_SMB_FS=m
+# CONFIG_SMB_NLS_DEFAULT is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_INTERMEZZO_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+
+#
+# Native Language Support
+#
+CONFIG_NLS=m
+CONFIG_NLS_DEFAULT="iso8859-1"
+# CONFIG_NLS_CODEPAGE_437 is not set
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ISO8859_1 is not set
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+# CONFIG_NLS_UTF8 is not set
+
+#
+# Kernel hacking
+#
+CONFIG_CROSSCOMPILE=y
+CONFIG_CMDLINE=""
+# CONFIG_DEBUG_KERNEL is not set
+
+#
+# Security options
+#
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+CONFIG_CRYPTO=y
+CONFIG_CRYPTO_HMAC=y
+CONFIG_CRYPTO_NULL=y
+# CONFIG_CRYPTO_MD4 is not set
+# CONFIG_CRYPTO_MD5 is not set
+# CONFIG_CRYPTO_SHA1 is not set
+# CONFIG_CRYPTO_SHA256 is not set
+CONFIG_CRYPTO_SHA512=y
+# CONFIG_CRYPTO_DES is not set
+# CONFIG_CRYPTO_BLOWFISH is not set
+CONFIG_CRYPTO_TWOFISH=y
+# CONFIG_CRYPTO_SERPENT is not set
+CONFIG_CRYPTO_AES=y
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+CONFIG_CRYPTO_DEFLATE=y
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Library routines
+#
+CONFIG_CRC32=y
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
--- diff/arch/mips/configs/db1100_defconfig	1970-01-01 01:00:00.000000000 +0100
+++ source/arch/mips/configs/db1100_defconfig	2004-02-23 13:56:38.000000000 +0000
@@ -0,0 +1,692 @@
+#
+# Automatically generated make config: don't edit
+#
+CONFIG_MIPS=y
+# CONFIG_MIPS64 is not set
+# CONFIG_64BIT is not set
+CONFIG_MIPS32=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_CLEAN_COMPILE=y
+CONFIG_STANDALONE=y
+CONFIG_BROKEN_ON_SMP=y
+
+#
+# General setup
+#
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_IKCONFIG is not set
+CONFIG_EMBEDDED=y
+CONFIG_KALLSYMS=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+CONFIG_OBSOLETE_MODPARM=y
+CONFIG_MODVERSIONS=y
+CONFIG_KMOD=y
+
+#
+# Machine selection
+#
+# CONFIG_MACH_JAZZ is not set
+# CONFIG_BAGET_MIPS is not set
+# CONFIG_MACH_VR41XX is not set
+# CONFIG_TOSHIBA_JMR3927 is not set
+# CONFIG_MIPS_COBALT is not set
+# CONFIG_MACH_DECSTATION is not set
+# CONFIG_MIPS_EV64120 is not set
+# CONFIG_MIPS_EV96100 is not set
+# CONFIG_MIPS_IVR is not set
+# CONFIG_LASAT is not set
+# CONFIG_HP_LASERJET is not set
+# CONFIG_MIPS_ITE8172 is not set
+# CONFIG_MIPS_ATLAS is not set
+# CONFIG_MIPS_MALTA is not set
+# CONFIG_MIPS_SEAD is not set
+# CONFIG_MOMENCO_OCELOT is not set
+# CONFIG_MOMENCO_OCELOT_G is not set
+# CONFIG_MOMENCO_OCELOT_C is not set
+# CONFIG_MOMENCO_JAGUAR_ATX is not set
+# CONFIG_PMC_YOSEMITE is not set
+# CONFIG_DDB5074 is not set
+# CONFIG_DDB5476 is not set
+# CONFIG_DDB5477 is not set
+# CONFIG_NEC_OSPREY is not set
+# CONFIG_SGI_IP22 is not set
+# CONFIG_SGI_IP32 is not set
+CONFIG_SOC_AU1X00=y
+# CONFIG_SOC_AU1000 is not set
+CONFIG_SOC_AU1100=y
+# CONFIG_SOC_AU1500 is not set
+# CONFIG_MIPS_PB1000 is not set
+# CONFIG_MIPS_PB1100 is not set
+# CONFIG_MIPS_PB1500 is not set
+# CONFIG_MIPS_DB1000 is not set
+CONFIG_MIPS_DB1100=y
+# CONFIG_MIPS_DB1500 is not set
+# CONFIG_MIPS_BOSPORUS is not set
+# CONFIG_MIPS_MIRAGE is not set
+# CONFIG_MIPS_XXS1500 is not set
+# CONFIG_MIPS_MTX1 is not set
+# CONFIG_SIBYTE_SB1xxx_SOC is not set
+# CONFIG_SNI_RM200_PCI is not set
+# CONFIG_TOSHIBA_RBTX4927 is not set
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_HAVE_DEC_LOCK=y
+CONFIG_DMA_NONCOHERENT=y
+CONFIG_CPU_LITTLE_ENDIAN=y
+CONFIG_MIPS_L1_CACHE_SHIFT=5
+# CONFIG_FB is not set
+
+#
+# CPU selection
+#
+CONFIG_CPU_MIPS32=y
+# CONFIG_CPU_MIPS64 is not set
+# CONFIG_CPU_R3000 is not set
+# CONFIG_CPU_TX39XX is not set
+# CONFIG_CPU_VR41XX is not set
+# CONFIG_CPU_R4300 is not set
+# CONFIG_CPU_R4X00 is not set
+# CONFIG_CPU_TX49XX is not set
+# CONFIG_CPU_R5000 is not set
+# CONFIG_CPU_R5432 is not set
+# CONFIG_CPU_R6000 is not set
+# CONFIG_CPU_NEVADA is not set
+# CONFIG_CPU_R8000 is not set
+# CONFIG_CPU_R10000 is not set
+# CONFIG_CPU_RM7000 is not set
+# CONFIG_CPU_RM9000 is not set
+# CONFIG_CPU_SB1 is not set
+CONFIG_PAGE_SIZE_4KB=y
+# CONFIG_PAGE_SIZE_16KB is not set
+# CONFIG_PAGE_SIZE_64KB is not set
+CONFIG_CPU_HAS_PREFETCH=y
+# CONFIG_VTAG_ICACHE is not set
+# CONFIG_64BIT_PHYS_ADDR is not set
+# CONFIG_CPU_ADVANCED is not set
+CONFIG_CPU_HAS_LLSC=y
+CONFIG_CPU_HAS_SYNC=y
+# CONFIG_PREEMPT is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+
+#
+# Bus options (PCI, PCMCIA, EISA, ISA, TC)
+#
+CONFIG_MMU=y
+CONFIG_HOTPLUG=y
+
+#
+# PCMCIA/CardBus support
+#
+CONFIG_PCMCIA=m
+# CONFIG_TCIC is not set
+# CONFIG_PCMCIA_AU1X00 is not set
+
+#
+# PCI Hotplug Support
+#
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_MISC is not set
+CONFIG_TRAD_SIGNALS=y
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+# CONFIG_FW_LOADER is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+CONFIG_BLK_DEV_LOOP=y
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_RAM is not set
+# CONFIG_BLK_DEV_INITRD is not set
+# CONFIG_LBD is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_SCSI is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+
+#
+# IEEE 1394 (FireWire) support (EXPERIMENTAL)
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+
+#
+# Macintosh device drivers
+#
+
+#
+# Networking support
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+CONFIG_NETLINK_DEV=y
+CONFIG_UNIX=y
+CONFIG_NET_KEY=y
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_PNP=y
+# CONFIG_IP_PNP_DHCP is not set
+CONFIG_IP_PNP_BOOTP=y
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_IP_MROUTE is not set
+# CONFIG_ARPD is not set
+# CONFIG_INET_ECN is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+
+#
+# IP: Virtual Server Configuration
+#
+# CONFIG_IP_VS is not set
+# CONFIG_IPV6 is not set
+# CONFIG_DECNET is not set
+# CONFIG_BRIDGE is not set
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
+
+#
+# IP: Netfilter Configuration
+#
+# CONFIG_IP_NF_CONNTRACK is not set
+# CONFIG_IP_NF_QUEUE is not set
+# CONFIG_IP_NF_IPTABLES is not set
+# CONFIG_IP_NF_ARPTABLES is not set
+# CONFIG_IP_NF_COMPAT_IPCHAINS is not set
+# CONFIG_IP_NF_COMPAT_IPFWADM is not set
+CONFIG_XFRM=y
+# CONFIG_XFRM_USER is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+CONFIG_IPV6_SCTP__=y
+# CONFIG_IP_SCTP is not set
+# CONFIG_ATM is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_FASTROUTE is not set
+# CONFIG_NET_HW_FLOWCONTROL is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+# CONFIG_ETHERTAP is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+# CONFIG_MII is not set
+# CONFIG_MIPS_AU1X00_ENET is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+
+#
+# Ethernet (10000 Mbit)
+#
+CONFIG_PPP=m
+CONFIG_PPP_MULTILINK=y
+# CONFIG_PPP_FILTER is not set
+CONFIG_PPP_ASYNC=m
+# CONFIG_PPP_SYNC_TTY is not set
+CONFIG_PPP_DEFLATE=m
+# CONFIG_PPP_BSDCOMP is not set
+CONFIG_PPPOE=m
+# CONFIG_SLIP is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Token Ring devices
+#
+# CONFIG_SHAPER is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+
+#
+# PCMCIA network device support
+#
+CONFIG_NET_PCMCIA=y
+CONFIG_PCMCIA_3C589=m
+# CONFIG_PCMCIA_3C574 is not set
+# CONFIG_PCMCIA_FMVJ18X is not set
+# CONFIG_PCMCIA_PCNET is not set
+# CONFIG_PCMCIA_NMCLAN is not set
+# CONFIG_PCMCIA_SMC91C92 is not set
+# CONFIG_PCMCIA_XIRC2PS is not set
+# CONFIG_PCMCIA_AXNET is not set
+
+#
+# Amateur Radio support
+#
+# CONFIG_HAMRADIO is not set
+
+#
+# IrDA (infrared) support
+#
+# CONFIG_IRDA is not set
+
+#
+# Bluetooth support
+#
+# CONFIG_BT is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN_BOOL is not set
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+CONFIG_INPUT_MOUSEDEV_PSAUX=y
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input I/O drivers
+#
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+CONFIG_SERIO=y
+# CONFIG_SERIO_I8042 is not set
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_CT82C710 is not set
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+# CONFIG_AU1X00_GPIO is not set
+# CONFIG_TS_AU1X00_ADS7846 is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+# CONFIG_SERIAL_AU1X00 is not set
+CONFIG_UNIX98_PTYS=y
+CONFIG_UNIX98_PTY_COUNT=256
+
+#
+# Mice
+#
+# CONFIG_BUSMOUSE is not set
+# CONFIG_QIC02_TAPE is not set
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_NVRAM is not set
+CONFIG_RTC=y
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_FTAPE is not set
+# CONFIG_AGP is not set
+# CONFIG_DRM is not set
+
+#
+# PCMCIA character devices
+#
+# CONFIG_SYNCLINK_CS is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+# CONFIG_MDA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+CONFIG_EXT2_FS_XATTR=y
+CONFIG_EXT2_FS_POSIX_ACL=y
+# CONFIG_EXT2_FS_SECURITY is not set
+CONFIG_EXT3_FS=y
+CONFIG_EXT3_FS_XATTR=y
+CONFIG_EXT3_FS_POSIX_ACL=y
+CONFIG_EXT3_FS_SECURITY=y
+CONFIG_JBD=y
+# CONFIG_JBD_DEBUG is not set
+CONFIG_FS_MBCACHE=y
+CONFIG_REISERFS_FS=m
+# CONFIG_REISERFS_CHECK is not set
+# CONFIG_REISERFS_PROC_INFO is not set
+# CONFIG_JFS_FS is not set
+CONFIG_FS_POSIX_ACL=y
+# CONFIG_XFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_QUOTA is not set
+CONFIG_AUTOFS_FS=m
+CONFIG_AUTOFS4_FS=m
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_FAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+# CONFIG_DEVFS_FS is not set
+CONFIG_DEVPTS_FS=y
+CONFIG_DEVPTS_FS_XATTR=y
+CONFIG_DEVPTS_FS_SECURITY=y
+CONFIG_TMPFS=y
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+CONFIG_CRAMFS=m
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+# CONFIG_NFS_V3 is not set
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
+CONFIG_NFSD=m
+# CONFIG_NFSD_V3 is not set
+# CONFIG_NFSD_TCP is not set
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+CONFIG_EXPORTFS=m
+CONFIG_SUNRPC=y
+# CONFIG_SUNRPC_GSS is not set
+CONFIG_SMB_FS=m
+# CONFIG_SMB_NLS_DEFAULT is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_INTERMEZZO_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+
+#
+# Native Language Support
+#
+CONFIG_NLS=m
+CONFIG_NLS_DEFAULT="iso8859-1"
+# CONFIG_NLS_CODEPAGE_437 is not set
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ISO8859_1 is not set
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+# CONFIG_NLS_UTF8 is not set
+
+#
+# Kernel hacking
+#
+CONFIG_CROSSCOMPILE=y
+CONFIG_CMDLINE=""
+# CONFIG_DEBUG_KERNEL is not set
+
+#
+# Security options
+#
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+CONFIG_CRYPTO=y
+CONFIG_CRYPTO_HMAC=y
+CONFIG_CRYPTO_NULL=y
+# CONFIG_CRYPTO_MD4 is not set
+# CONFIG_CRYPTO_MD5 is not set
+# CONFIG_CRYPTO_SHA1 is not set
+# CONFIG_CRYPTO_SHA256 is not set
+CONFIG_CRYPTO_SHA512=y
+# CONFIG_CRYPTO_DES is not set
+# CONFIG_CRYPTO_BLOWFISH is not set
+CONFIG_CRYPTO_TWOFISH=y
+# CONFIG_CRYPTO_SERPENT is not set
+CONFIG_CRYPTO_AES=y
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+CONFIG_CRYPTO_DEFLATE=y
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Library routines
+#
+CONFIG_CRC32=y
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
--- diff/arch/mips/configs/db1500_defconfig	1970-01-01 01:00:00.000000000 +0100
+++ source/arch/mips/configs/db1500_defconfig	2004-02-23 13:56:38.000000000 +0000
@@ -0,0 +1,769 @@
+#
+# Automatically generated make config: don't edit
+#
+CONFIG_MIPS=y
+# CONFIG_MIPS64 is not set
+# CONFIG_64BIT is not set
+CONFIG_MIPS32=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_CLEAN_COMPILE=y
+CONFIG_STANDALONE=y
+CONFIG_BROKEN_ON_SMP=y
+
+#
+# General setup
+#
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_IKCONFIG is not set
+CONFIG_EMBEDDED=y
+CONFIG_KALLSYMS=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+CONFIG_OBSOLETE_MODPARM=y
+CONFIG_MODVERSIONS=y
+CONFIG_KMOD=y
+
+#
+# Machine selection
+#
+# CONFIG_MACH_JAZZ is not set
+# CONFIG_BAGET_MIPS is not set
+# CONFIG_MACH_VR41XX is not set
+# CONFIG_TOSHIBA_JMR3927 is not set
+# CONFIG_MIPS_COBALT is not set
+# CONFIG_MACH_DECSTATION is not set
+# CONFIG_MIPS_EV64120 is not set
+# CONFIG_MIPS_EV96100 is not set
+# CONFIG_MIPS_IVR is not set
+# CONFIG_LASAT is not set
+# CONFIG_HP_LASERJET is not set
+# CONFIG_MIPS_ITE8172 is not set
+# CONFIG_MIPS_ATLAS is not set
+# CONFIG_MIPS_MALTA is not set
+# CONFIG_MIPS_SEAD is not set
+# CONFIG_MOMENCO_OCELOT is not set
+# CONFIG_MOMENCO_OCELOT_G is not set
+# CONFIG_MOMENCO_OCELOT_C is not set
+# CONFIG_MOMENCO_JAGUAR_ATX is not set
+# CONFIG_PMC_YOSEMITE is not set
+# CONFIG_DDB5074 is not set
+# CONFIG_DDB5476 is not set
+# CONFIG_DDB5477 is not set
+# CONFIG_NEC_OSPREY is not set
+# CONFIG_SGI_IP22 is not set
+# CONFIG_SGI_IP32 is not set
+CONFIG_SOC_AU1X00=y
+# CONFIG_SOC_AU1000 is not set
+# CONFIG_SOC_AU1100 is not set
+CONFIG_SOC_AU1500=y
+# CONFIG_MIPS_PB1000 is not set
+# CONFIG_MIPS_PB1100 is not set
+# CONFIG_MIPS_PB1500 is not set
+# CONFIG_MIPS_DB1000 is not set
+# CONFIG_MIPS_DB1100 is not set
+CONFIG_MIPS_DB1500=y
+# CONFIG_MIPS_BOSPORUS is not set
+# CONFIG_MIPS_MIRAGE is not set
+# CONFIG_MIPS_XXS1500 is not set
+# CONFIG_MIPS_MTX1 is not set
+# CONFIG_SIBYTE_SB1xxx_SOC is not set
+# CONFIG_SNI_RM200_PCI is not set
+# CONFIG_TOSHIBA_RBTX4927 is not set
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_HAVE_DEC_LOCK=y
+CONFIG_DMA_NONCOHERENT=y
+CONFIG_CPU_LITTLE_ENDIAN=y
+CONFIG_MIPS_L1_CACHE_SHIFT=5
+# CONFIG_FB is not set
+
+#
+# CPU selection
+#
+CONFIG_CPU_MIPS32=y
+# CONFIG_CPU_MIPS64 is not set
+# CONFIG_CPU_R3000 is not set
+# CONFIG_CPU_TX39XX is not set
+# CONFIG_CPU_VR41XX is not set
+# CONFIG_CPU_R4300 is not set
+# CONFIG_CPU_R4X00 is not set
+# CONFIG_CPU_TX49XX is not set
+# CONFIG_CPU_R5000 is not set
+# CONFIG_CPU_R5432 is not set
+# CONFIG_CPU_R6000 is not set
+# CONFIG_CPU_NEVADA is not set
+# CONFIG_CPU_R8000 is not set
+# CONFIG_CPU_R10000 is not set
+# CONFIG_CPU_RM7000 is not set
+# CONFIG_CPU_RM9000 is not set
+# CONFIG_CPU_SB1 is not set
+CONFIG_PAGE_SIZE_4KB=y
+# CONFIG_PAGE_SIZE_16KB is not set
+# CONFIG_PAGE_SIZE_64KB is not set
+CONFIG_CPU_HAS_PREFETCH=y
+# CONFIG_VTAG_ICACHE is not set
+CONFIG_64BIT_PHYS_ADDR=y
+# CONFIG_CPU_ADVANCED is not set
+CONFIG_CPU_HAS_LLSC=y
+CONFIG_CPU_HAS_SYNC=y
+# CONFIG_PREEMPT is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+
+#
+# Bus options (PCI, PCMCIA, EISA, ISA, TC)
+#
+# CONFIG_PCI is not set
+CONFIG_MMU=y
+CONFIG_HOTPLUG=y
+
+#
+# PCMCIA/CardBus support
+#
+CONFIG_PCMCIA=m
+# CONFIG_TCIC is not set
+# CONFIG_PCMCIA_AU1X00 is not set
+
+#
+# PCI Hotplug Support
+#
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_MISC is not set
+CONFIG_TRAD_SIGNALS=y
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+# CONFIG_FW_LOADER is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_CONCAT is not set
+# CONFIG_MTD_REDBOOT_PARTS is not set
+# CONFIG_MTD_CMDLINE_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+CONFIG_MTD_CFI=y
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_GEN_PROBE=y
+# CONFIG_MTD_CFI_ADV_OPTIONS is not set
+CONFIG_MTD_CFI_INTELEXT=y
+CONFIG_MTD_CFI_AMDSTD=y
+# CONFIG_MTD_CFI_STAA is not set
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+# CONFIG_MTD_OBSOLETE_CHIPS is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+# CONFIG_MTD_PHYSMAP is not set
+CONFIG_MTD_DB1X00=y
+CONFIG_MTD_DB1X00_BOOT=y
+CONFIG_MTD_DB1X00_USER=y
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLKMTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+
+#
+# NAND Flash Device Drivers
+#
+# CONFIG_MTD_NAND is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+CONFIG_BLK_DEV_LOOP=y
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_RAM is not set
+# CONFIG_BLK_DEV_INITRD is not set
+# CONFIG_LBD is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+CONFIG_IDE=y
+CONFIG_BLK_DEV_IDE=y
+
+#
+# Please see Documentation/ide.txt for help/info on IDE drives
+#
+CONFIG_BLK_DEV_IDEDISK=y
+# CONFIG_IDEDISK_MULTI_MODE is not set
+# CONFIG_IDEDISK_STROKE is not set
+CONFIG_BLK_DEV_IDECS=m
+# CONFIG_BLK_DEV_IDECD is not set
+# CONFIG_BLK_DEV_IDETAPE is not set
+# CONFIG_BLK_DEV_IDEFLOPPY is not set
+# CONFIG_IDE_TASK_IOCTL is not set
+# CONFIG_IDE_TASKFILE_IO is not set
+
+#
+# IDE chipset support/bugfixes
+#
+CONFIG_IDE_GENERIC=y
+# CONFIG_BLK_DEV_IDEDMA is not set
+# CONFIG_IDEDMA_AUTO is not set
+# CONFIG_DMA_NONPCI is not set
+# CONFIG_BLK_DEV_HD is not set
+
+#
+# SCSI device support
+#
+# CONFIG_SCSI is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+
+#
+# IEEE 1394 (FireWire) support (EXPERIMENTAL)
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+
+#
+# Macintosh device drivers
+#
+
+#
+# Networking support
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+CONFIG_NETLINK_DEV=y
+CONFIG_UNIX=y
+CONFIG_NET_KEY=y
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_PNP=y
+# CONFIG_IP_PNP_DHCP is not set
+CONFIG_IP_PNP_BOOTP=y
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_IP_MROUTE is not set
+# CONFIG_ARPD is not set
+# CONFIG_INET_ECN is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+
+#
+# IP: Virtual Server Configuration
+#
+# CONFIG_IP_VS is not set
+# CONFIG_IPV6 is not set
+# CONFIG_DECNET is not set
+# CONFIG_BRIDGE is not set
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
+
+#
+# IP: Netfilter Configuration
+#
+# CONFIG_IP_NF_CONNTRACK is not set
+# CONFIG_IP_NF_QUEUE is not set
+# CONFIG_IP_NF_IPTABLES is not set
+# CONFIG_IP_NF_ARPTABLES is not set
+# CONFIG_IP_NF_COMPAT_IPCHAINS is not set
+# CONFIG_IP_NF_COMPAT_IPFWADM is not set
+CONFIG_XFRM=y
+# CONFIG_XFRM_USER is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+CONFIG_IPV6_SCTP__=y
+# CONFIG_IP_SCTP is not set
+# CONFIG_ATM is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_FASTROUTE is not set
+# CONFIG_NET_HW_FLOWCONTROL is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+# CONFIG_ETHERTAP is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+# CONFIG_MII is not set
+CONFIG_MIPS_AU1X00_ENET=y
+
+#
+# Ethernet (1000 Mbit)
+#
+
+#
+# Ethernet (10000 Mbit)
+#
+CONFIG_PPP=m
+CONFIG_PPP_MULTILINK=y
+# CONFIG_PPP_FILTER is not set
+CONFIG_PPP_ASYNC=m
+# CONFIG_PPP_SYNC_TTY is not set
+CONFIG_PPP_DEFLATE=m
+# CONFIG_PPP_BSDCOMP is not set
+CONFIG_PPPOE=m
+# CONFIG_SLIP is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Token Ring devices
+#
+# CONFIG_SHAPER is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+
+#
+# PCMCIA network device support
+#
+CONFIG_NET_PCMCIA=y
+CONFIG_PCMCIA_3C589=m
+# CONFIG_PCMCIA_3C574 is not set
+# CONFIG_PCMCIA_FMVJ18X is not set
+# CONFIG_PCMCIA_PCNET is not set
+# CONFIG_PCMCIA_NMCLAN is not set
+# CONFIG_PCMCIA_SMC91C92 is not set
+# CONFIG_PCMCIA_XIRC2PS is not set
+# CONFIG_PCMCIA_AXNET is not set
+
+#
+# Amateur Radio support
+#
+# CONFIG_HAMRADIO is not set
+
+#
+# IrDA (infrared) support
+#
+# CONFIG_IRDA is not set
+
+#
+# Bluetooth support
+#
+# CONFIG_BT is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN_BOOL is not set
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+CONFIG_INPUT_MOUSEDEV_PSAUX=y
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input I/O drivers
+#
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+CONFIG_SERIO=y
+# CONFIG_SERIO_I8042 is not set
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_CT82C710 is not set
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Character devices
+#
+# CONFIG_VT is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+# CONFIG_AU1X00_GPIO is not set
+# CONFIG_TS_AU1X00_ADS7846 is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_AU1X00=y
+CONFIG_SERIAL_AU1X00_CONSOLE=y
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+CONFIG_UNIX98_PTY_COUNT=256
+
+#
+# Mice
+#
+# CONFIG_BUSMOUSE is not set
+# CONFIG_QIC02_TAPE is not set
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_NVRAM is not set
+CONFIG_RTC=y
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_FTAPE is not set
+# CONFIG_AGP is not set
+# CONFIG_DRM is not set
+
+#
+# PCMCIA character devices
+#
+# CONFIG_SYNCLINK_CS is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+CONFIG_EXT2_FS_XATTR=y
+CONFIG_EXT2_FS_POSIX_ACL=y
+# CONFIG_EXT2_FS_SECURITY is not set
+CONFIG_EXT3_FS=y
+CONFIG_EXT3_FS_XATTR=y
+CONFIG_EXT3_FS_POSIX_ACL=y
+CONFIG_EXT3_FS_SECURITY=y
+CONFIG_JBD=y
+# CONFIG_JBD_DEBUG is not set
+CONFIG_FS_MBCACHE=y
+CONFIG_REISERFS_FS=m
+# CONFIG_REISERFS_CHECK is not set
+# CONFIG_REISERFS_PROC_INFO is not set
+# CONFIG_JFS_FS is not set
+CONFIG_FS_POSIX_ACL=y
+# CONFIG_XFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_QUOTA is not set
+CONFIG_AUTOFS_FS=m
+CONFIG_AUTOFS4_FS=m
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_FAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+# CONFIG_DEVFS_FS is not set
+CONFIG_DEVPTS_FS=y
+CONFIG_DEVPTS_FS_XATTR=y
+CONFIG_DEVPTS_FS_SECURITY=y
+CONFIG_TMPFS=y
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_JFFS_FS is not set
+# CONFIG_JFFS2_FS is not set
+CONFIG_CRAMFS=m
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+# CONFIG_NFS_V3 is not set
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
+CONFIG_NFSD=m
+# CONFIG_NFSD_V3 is not set
+# CONFIG_NFSD_TCP is not set
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+CONFIG_EXPORTFS=m
+CONFIG_SUNRPC=y
+# CONFIG_SUNRPC_GSS is not set
+CONFIG_SMB_FS=m
+# CONFIG_SMB_NLS_DEFAULT is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_INTERMEZZO_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+
+#
+# Native Language Support
+#
+CONFIG_NLS=m
+CONFIG_NLS_DEFAULT="iso8859-1"
+# CONFIG_NLS_CODEPAGE_437 is not set
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ISO8859_1 is not set
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+# CONFIG_NLS_UTF8 is not set
+
+#
+# Kernel hacking
+#
+CONFIG_CROSSCOMPILE=y
+CONFIG_CMDLINE=""
+# CONFIG_DEBUG_KERNEL is not set
+
+#
+# Security options
+#
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+CONFIG_CRYPTO=y
+CONFIG_CRYPTO_HMAC=y
+CONFIG_CRYPTO_NULL=y
+# CONFIG_CRYPTO_MD4 is not set
+# CONFIG_CRYPTO_MD5 is not set
+# CONFIG_CRYPTO_SHA1 is not set
+# CONFIG_CRYPTO_SHA256 is not set
+CONFIG_CRYPTO_SHA512=y
+# CONFIG_CRYPTO_DES is not set
+# CONFIG_CRYPTO_BLOWFISH is not set
+CONFIG_CRYPTO_TWOFISH=y
+# CONFIG_CRYPTO_SERPENT is not set
+CONFIG_CRYPTO_AES=y
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+CONFIG_CRYPTO_DEFLATE=y
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Library routines
+#
+CONFIG_CRC32=y
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
--- diff/arch/mips/configs/ddb5476_defconfig	1970-01-01 01:00:00.000000000 +0100
+++ source/arch/mips/configs/ddb5476_defconfig	2004-02-23 13:56:38.000000000 +0000
@@ -0,0 +1,639 @@
+#
+# Automatically generated make config: don't edit
+#
+CONFIG_MIPS=y
+# CONFIG_MIPS64 is not set
+# CONFIG_64BIT is not set
+CONFIG_MIPS32=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_CLEAN_COMPILE=y
+CONFIG_STANDALONE=y
+CONFIG_BROKEN_ON_SMP=y
+
+#
+# General setup
+#
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_IKCONFIG is not set
+CONFIG_EMBEDDED=y
+CONFIG_KALLSYMS=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+
+#
+# Loadable module support
+#
+# CONFIG_MODULES is not set
+
+#
+# Machine selection
+#
+# CONFIG_MACH_JAZZ is not set
+# CONFIG_BAGET_MIPS is not set
+# CONFIG_MACH_VR41XX is not set
+# CONFIG_TOSHIBA_JMR3927 is not set
+# CONFIG_MIPS_COBALT is not set
+# CONFIG_MACH_DECSTATION is not set
+# CONFIG_MIPS_EV64120 is not set
+# CONFIG_MIPS_EV96100 is not set
+# CONFIG_MIPS_IVR is not set
+# CONFIG_LASAT is not set
+# CONFIG_HP_LASERJET is not set
+# CONFIG_MIPS_ITE8172 is not set
+# CONFIG_MIPS_ATLAS is not set
+# CONFIG_MIPS_MALTA is not set
+# CONFIG_MIPS_SEAD is not set
+# CONFIG_MOMENCO_OCELOT is not set
+# CONFIG_MOMENCO_OCELOT_G is not set
+# CONFIG_MOMENCO_OCELOT_C is not set
+# CONFIG_MOMENCO_JAGUAR_ATX is not set
+# CONFIG_PMC_YOSEMITE is not set
+# CONFIG_DDB5074 is not set
+CONFIG_DDB5476=y
+# CONFIG_DDB5477 is not set
+# CONFIG_NEC_OSPREY is not set
+# CONFIG_SGI_IP22 is not set
+# CONFIG_SGI_IP32 is not set
+# CONFIG_SOC_AU1X00 is not set
+# CONFIG_SIBYTE_SB1xxx_SOC is not set
+# CONFIG_SNI_RM200_PCI is not set
+# CONFIG_TOSHIBA_RBTX4927 is not set
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_HAVE_DEC_LOCK=y
+CONFIG_DMA_NONCOHERENT=y
+CONFIG_I8259=y
+CONFIG_CPU_LITTLE_ENDIAN=y
+CONFIG_IRQ_CPU=y
+CONFIG_DDB5XXX_COMMON=y
+CONFIG_MIPS_L1_CACHE_SHIFT=5
+CONFIG_FB=y
+CONFIG_HAVE_STD_PC_SERIAL_PORT=y
+
+#
+# CPU selection
+#
+# CONFIG_CPU_MIPS32 is not set
+# CONFIG_CPU_MIPS64 is not set
+# CONFIG_CPU_R3000 is not set
+# CONFIG_CPU_TX39XX is not set
+# CONFIG_CPU_VR41XX is not set
+# CONFIG_CPU_R4300 is not set
+# CONFIG_CPU_R4X00 is not set
+# CONFIG_CPU_TX49XX is not set
+# CONFIG_CPU_R5000 is not set
+CONFIG_CPU_R5432=y
+# CONFIG_CPU_R6000 is not set
+# CONFIG_CPU_NEVADA is not set
+# CONFIG_CPU_R8000 is not set
+# CONFIG_CPU_R10000 is not set
+# CONFIG_CPU_RM7000 is not set
+# CONFIG_CPU_RM9000 is not set
+# CONFIG_CPU_SB1 is not set
+CONFIG_PAGE_SIZE_4KB=y
+# CONFIG_PAGE_SIZE_16KB is not set
+# CONFIG_PAGE_SIZE_64KB is not set
+# CONFIG_CPU_ADVANCED is not set
+CONFIG_CPU_HAS_LLSC=y
+CONFIG_CPU_HAS_LLDSCD=y
+CONFIG_CPU_HAS_SYNC=y
+# CONFIG_PREEMPT is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+
+#
+# Bus options (PCI, PCMCIA, EISA, ISA, TC)
+#
+CONFIG_PCI=y
+CONFIG_PCI_LEGACY_PROC=y
+CONFIG_PCI_NAMES=y
+CONFIG_MMU=y
+# CONFIG_HOTPLUG is not set
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_MISC is not set
+CONFIG_TRAD_SIGNALS=y
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_UMEM is not set
+# CONFIG_BLK_DEV_LOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_RAM is not set
+# CONFIG_BLK_DEV_INITRD is not set
+# CONFIG_LBD is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+CONFIG_IDE=y
+CONFIG_BLK_DEV_IDE=y
+
+#
+# Please see Documentation/ide.txt for help/info on IDE drives
+#
+CONFIG_BLK_DEV_IDEDISK=y
+# CONFIG_IDEDISK_MULTI_MODE is not set
+# CONFIG_IDEDISK_STROKE is not set
+# CONFIG_BLK_DEV_IDECD is not set
+# CONFIG_BLK_DEV_IDETAPE is not set
+# CONFIG_BLK_DEV_IDEFLOPPY is not set
+# CONFIG_IDE_TASK_IOCTL is not set
+CONFIG_IDE_TASKFILE_IO=y
+
+#
+# IDE chipset support/bugfixes
+#
+CONFIG_IDE_GENERIC=y
+# CONFIG_BLK_DEV_IDEPCI is not set
+# CONFIG_BLK_DEV_IDEDMA is not set
+# CONFIG_IDEDMA_AUTO is not set
+# CONFIG_DMA_NONPCI is not set
+# CONFIG_BLK_DEV_HD is not set
+
+#
+# SCSI device support
+#
+# CONFIG_SCSI is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+
+#
+# IEEE 1394 (FireWire) support (EXPERIMENTAL)
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+
+#
+# Macintosh device drivers
+#
+
+#
+# Networking support
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+CONFIG_NETLINK_DEV=y
+CONFIG_UNIX=y
+CONFIG_NET_KEY=y
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_PNP=y
+# CONFIG_IP_PNP_DHCP is not set
+CONFIG_IP_PNP_BOOTP=y
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_ARPD is not set
+# CONFIG_INET_ECN is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_IPV6 is not set
+# CONFIG_DECNET is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_NETFILTER is not set
+CONFIG_XFRM=y
+# CONFIG_XFRM_USER is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+CONFIG_IPV6_SCTP__=y
+# CONFIG_IP_SCTP is not set
+# CONFIG_ATM is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_FASTROUTE is not set
+# CONFIG_NET_HW_FLOWCONTROL is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+CONFIG_NETDEVICES=y
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+# CONFIG_ETHERTAP is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+# CONFIG_MII is not set
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_SUNGEM is not set
+# CONFIG_NET_VENDOR_3COM is not set
+
+#
+# Tulip family network device support
+#
+# CONFIG_NET_TULIP is not set
+# CONFIG_HP100 is not set
+# CONFIG_NET_PCI is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+# CONFIG_E1000 is not set
+# CONFIG_NS83820 is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+# CONFIG_R8169 is not set
+# CONFIG_SIS190 is not set
+# CONFIG_SK98LIN is not set
+# CONFIG_TIGON3 is not set
+
+#
+# Ethernet (10000 Mbit)
+#
+# CONFIG_IXGB is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Token Ring devices
+#
+# CONFIG_TR is not set
+# CONFIG_RCPCI is not set
+# CONFIG_SHAPER is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+
+#
+# Amateur Radio support
+#
+# CONFIG_HAMRADIO is not set
+
+#
+# IrDA (infrared) support
+#
+# CONFIG_IRDA is not set
+
+#
+# Bluetooth support
+#
+# CONFIG_BT is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN_BOOL is not set
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+CONFIG_INPUT_MOUSEDEV_PSAUX=y
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+# CONFIG_INPUT_EVDEV is not set
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input I/O drivers
+#
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+CONFIG_SERIO=y
+# CONFIG_SERIO_I8042 is not set
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_CT82C710 is not set
+# CONFIG_SERIO_PCIPS2 is not set
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=4
+# CONFIG_SERIAL_8250_EXTENDED is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+CONFIG_UNIX98_PTY_COUNT=256
+
+#
+# Mice
+#
+# CONFIG_BUSMOUSE is not set
+# CONFIG_QIC02_TAPE is not set
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_NVRAM is not set
+# CONFIG_RTC is not set
+# CONFIG_GEN_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_FTAPE is not set
+# CONFIG_AGP is not set
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+# CONFIG_FB_CYBER2000 is not set
+# CONFIG_FB_IMSTT is not set
+# CONFIG_FB_RIVA is not set
+# CONFIG_FB_MATROX is not set
+# CONFIG_FB_RADEON_OLD is not set
+# CONFIG_FB_RADEON is not set
+# CONFIG_FB_ATY128 is not set
+# CONFIG_FB_ATY is not set
+# CONFIG_FB_SIS is not set
+# CONFIG_FB_NEOMAGIC is not set
+# CONFIG_FB_KYRO is not set
+# CONFIG_FB_3DFX is not set
+# CONFIG_FB_VOODOO1 is not set
+# CONFIG_FB_TRIDENT is not set
+# CONFIG_FB_E1356 is not set
+# CONFIG_FB_VIRTUAL is not set
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+# CONFIG_MDA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+# CONFIG_FRAMEBUFFER_CONSOLE is not set
+
+#
+# Logo configuration
+#
+# CONFIG_LOGO is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+# CONFIG_USB is not set
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_JBD is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_QUOTA is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_FAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+# CONFIG_DEVFS_FS is not set
+CONFIG_DEVPTS_FS=y
+CONFIG_DEVPTS_FS_XATTR=y
+CONFIG_DEVPTS_FS_SECURITY=y
+# CONFIG_TMPFS is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+# CONFIG_NFS_V3 is not set
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
+# CONFIG_NFSD is not set
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+# CONFIG_EXPORTFS is not set
+CONFIG_SUNRPC=y
+# CONFIG_SUNRPC_GSS is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_INTERMEZZO_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+
+#
+# Native Language Support
+#
+# CONFIG_NLS is not set
+
+#
+# Kernel hacking
+#
+CONFIG_CROSSCOMPILE=y
+CONFIG_CMDLINE="ip=any"
+# CONFIG_DEBUG_KERNEL is not set
+
+#
+# Security options
+#
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
+# Library routines
+#
+# CONFIG_CRC32 is not set
--- diff/arch/mips/configs/ddb5477_defconfig	1970-01-01 01:00:00.000000000 +0100
+++ source/arch/mips/configs/ddb5477_defconfig	2004-02-23 13:56:38.000000000 +0000
@@ -0,0 +1,616 @@
+#
+# Automatically generated make config: don't edit
+#
+CONFIG_MIPS=y
+# CONFIG_MIPS64 is not set
+# CONFIG_64BIT is not set
+CONFIG_MIPS32=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_CLEAN_COMPILE=y
+CONFIG_STANDALONE=y
+CONFIG_BROKEN_ON_SMP=y
+
+#
+# General setup
+#
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_IKCONFIG is not set
+CONFIG_EMBEDDED=y
+CONFIG_KALLSYMS=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+
+#
+# Loadable module support
+#
+# CONFIG_MODULES is not set
+
+#
+# Machine selection
+#
+# CONFIG_MACH_JAZZ is not set
+# CONFIG_BAGET_MIPS is not set
+# CONFIG_MACH_VR41XX is not set
+# CONFIG_TOSHIBA_JMR3927 is not set
+# CONFIG_MIPS_COBALT is not set
+# CONFIG_MACH_DECSTATION is not set
+# CONFIG_MIPS_EV64120 is not set
+# CONFIG_MIPS_EV96100 is not set
+# CONFIG_MIPS_IVR is not set
+# CONFIG_LASAT is not set
+# CONFIG_HP_LASERJET is not set
+# CONFIG_MIPS_ITE8172 is not set
+# CONFIG_MIPS_ATLAS is not set
+# CONFIG_MIPS_MALTA is not set
+# CONFIG_MIPS_SEAD is not set
+# CONFIG_MOMENCO_OCELOT is not set
+# CONFIG_MOMENCO_OCELOT_G is not set
+# CONFIG_MOMENCO_OCELOT_C is not set
+# CONFIG_MOMENCO_JAGUAR_ATX is not set
+# CONFIG_PMC_YOSEMITE is not set
+# CONFIG_DDB5074 is not set
+# CONFIG_DDB5476 is not set
+CONFIG_DDB5477=y
+CONFIG_DDB5477_BUS_FREQUENCY=0
+# CONFIG_NEC_OSPREY is not set
+# CONFIG_SGI_IP22 is not set
+# CONFIG_SGI_IP32 is not set
+# CONFIG_SOC_AU1X00 is not set
+# CONFIG_SIBYTE_SB1xxx_SOC is not set
+# CONFIG_SNI_RM200_PCI is not set
+# CONFIG_TOSHIBA_RBTX4927 is not set
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_HAVE_DEC_LOCK=y
+CONFIG_DMA_NONCOHERENT=y
+CONFIG_I8259=y
+CONFIG_CPU_LITTLE_ENDIAN=y
+CONFIG_IRQ_CPU=y
+CONFIG_DUMMY_KEYB=y
+CONFIG_DDB5XXX_COMMON=y
+CONFIG_MIPS_L1_CACHE_SHIFT=5
+# CONFIG_FB is not set
+
+#
+# CPU selection
+#
+# CONFIG_CPU_MIPS32 is not set
+# CONFIG_CPU_MIPS64 is not set
+# CONFIG_CPU_R3000 is not set
+# CONFIG_CPU_TX39XX is not set
+# CONFIG_CPU_VR41XX is not set
+# CONFIG_CPU_R4300 is not set
+# CONFIG_CPU_R4X00 is not set
+# CONFIG_CPU_TX49XX is not set
+# CONFIG_CPU_R5000 is not set
+CONFIG_CPU_R5432=y
+# CONFIG_CPU_R6000 is not set
+# CONFIG_CPU_NEVADA is not set
+# CONFIG_CPU_R8000 is not set
+# CONFIG_CPU_R10000 is not set
+# CONFIG_CPU_RM7000 is not set
+# CONFIG_CPU_RM9000 is not set
+# CONFIG_CPU_SB1 is not set
+CONFIG_PAGE_SIZE_4KB=y
+# CONFIG_PAGE_SIZE_16KB is not set
+# CONFIG_PAGE_SIZE_64KB is not set
+# CONFIG_CPU_ADVANCED is not set
+CONFIG_CPU_HAS_LLSC=y
+CONFIG_CPU_HAS_LLDSCD=y
+CONFIG_CPU_HAS_SYNC=y
+# CONFIG_PREEMPT is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+
+#
+# Bus options (PCI, PCMCIA, EISA, ISA, TC)
+#
+CONFIG_PCI=y
+CONFIG_PCI_LEGACY_PROC=y
+CONFIG_PCI_NAMES=y
+CONFIG_MMU=y
+# CONFIG_HOTPLUG is not set
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_MISC is not set
+CONFIG_TRAD_SIGNALS=y
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_UMEM is not set
+# CONFIG_BLK_DEV_LOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_RAM is not set
+# CONFIG_BLK_DEV_INITRD is not set
+# CONFIG_LBD is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_SCSI is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+
+#
+# IEEE 1394 (FireWire) support (EXPERIMENTAL)
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+
+#
+# Macintosh device drivers
+#
+
+#
+# Networking support
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+CONFIG_NETLINK_DEV=y
+CONFIG_UNIX=y
+CONFIG_NET_KEY=y
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_PNP=y
+# CONFIG_IP_PNP_DHCP is not set
+CONFIG_IP_PNP_BOOTP=y
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_ARPD is not set
+# CONFIG_INET_ECN is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_IPV6 is not set
+# CONFIG_DECNET is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_NETFILTER is not set
+CONFIG_XFRM=y
+# CONFIG_XFRM_USER is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+CONFIG_IPV6_SCTP__=y
+# CONFIG_IP_SCTP is not set
+# CONFIG_ATM is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_FASTROUTE is not set
+# CONFIG_NET_HW_FLOWCONTROL is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+CONFIG_NETDEVICES=y
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+# CONFIG_ETHERTAP is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_SUNGEM is not set
+# CONFIG_NET_VENDOR_3COM is not set
+
+#
+# Tulip family network device support
+#
+# CONFIG_NET_TULIP is not set
+# CONFIG_HP100 is not set
+CONFIG_NET_PCI=y
+CONFIG_PCNET32=y
+# CONFIG_AMD8111_ETH is not set
+# CONFIG_ADAPTEC_STARFIRE is not set
+# CONFIG_B44 is not set
+# CONFIG_FORCEDETH is not set
+# CONFIG_DGRS is not set
+# CONFIG_EEPRO100 is not set
+# CONFIG_E100 is not set
+# CONFIG_FEALNX is not set
+# CONFIG_NATSEMI is not set
+# CONFIG_NE2K_PCI is not set
+# CONFIG_8139CP is not set
+# CONFIG_8139TOO is not set
+# CONFIG_SIS900 is not set
+# CONFIG_EPIC100 is not set
+# CONFIG_SUNDANCE is not set
+# CONFIG_TLAN is not set
+# CONFIG_VIA_RHINE is not set
+# CONFIG_LAN_SAA9730 is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+# CONFIG_E1000 is not set
+# CONFIG_NS83820 is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+# CONFIG_R8169 is not set
+# CONFIG_SIS190 is not set
+# CONFIG_SK98LIN is not set
+# CONFIG_TIGON3 is not set
+
+#
+# Ethernet (10000 Mbit)
+#
+# CONFIG_IXGB is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Token Ring devices
+#
+# CONFIG_TR is not set
+# CONFIG_RCPCI is not set
+# CONFIG_SHAPER is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+
+#
+# Amateur Radio support
+#
+# CONFIG_HAMRADIO is not set
+
+#
+# IrDA (infrared) support
+#
+# CONFIG_IRDA is not set
+
+#
+# Bluetooth support
+#
+# CONFIG_BT is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN_BOOL is not set
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+CONFIG_INPUT_MOUSEDEV_PSAUX=y
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+# CONFIG_INPUT_EVDEV is not set
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input I/O drivers
+#
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+CONFIG_SERIO=y
+# CONFIG_SERIO_I8042 is not set
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_CT82C710 is not set
+# CONFIG_SERIO_PCIPS2 is not set
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=4
+# CONFIG_SERIAL_8250_EXTENDED is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+CONFIG_UNIX98_PTY_COUNT=256
+
+#
+# Mice
+#
+# CONFIG_BUSMOUSE is not set
+# CONFIG_QIC02_TAPE is not set
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_NVRAM is not set
+# CONFIG_RTC is not set
+# CONFIG_GEN_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_FTAPE is not set
+# CONFIG_AGP is not set
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+# CONFIG_MDA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+# CONFIG_USB is not set
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_JBD is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_QUOTA is not set
+CONFIG_AUTOFS_FS=y
+CONFIG_AUTOFS4_FS=y
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_FAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+# CONFIG_DEVFS_FS is not set
+CONFIG_DEVPTS_FS=y
+CONFIG_DEVPTS_FS_XATTR=y
+CONFIG_DEVPTS_FS_SECURITY=y
+# CONFIG_TMPFS is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+# CONFIG_NFS_V3 is not set
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
+CONFIG_NFSD=y
+# CONFIG_NFSD_V3 is not set
+# CONFIG_NFSD_TCP is not set
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+CONFIG_EXPORTFS=y
+CONFIG_SUNRPC=y
+# CONFIG_SUNRPC_GSS is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_INTERMEZZO_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+
+#
+# Native Language Support
+#
+# CONFIG_NLS is not set
+
+#
+# Kernel hacking
+#
+CONFIG_CROSSCOMPILE=y
+CONFIG_CMDLINE="ip=any"
+# CONFIG_DEBUG_KERNEL is not set
+
+#
+# Security options
+#
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
+# Library routines
+#
+CONFIG_CRC32=y
--- diff/arch/mips/configs/decstation_defconfig	1970-01-01 01:00:00.000000000 +0100
+++ source/arch/mips/configs/decstation_defconfig	2004-02-23 13:56:38.000000000 +0000
@@ -0,0 +1,598 @@
+#
+# Automatically generated make config: don't edit
+#
+CONFIG_MIPS=y
+# CONFIG_MIPS64 is not set
+# CONFIG_64BIT is not set
+CONFIG_MIPS32=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_CLEAN_COMPILE=y
+CONFIG_STANDALONE=y
+CONFIG_BROKEN_ON_SMP=y
+
+#
+# General setup
+#
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_IKCONFIG is not set
+CONFIG_EMBEDDED=y
+CONFIG_KALLSYMS=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+CONFIG_OBSOLETE_MODPARM=y
+CONFIG_MODVERSIONS=y
+CONFIG_KMOD=y
+
+#
+# Machine selection
+#
+# CONFIG_MACH_JAZZ is not set
+# CONFIG_BAGET_MIPS is not set
+# CONFIG_MACH_VR41XX is not set
+# CONFIG_TOSHIBA_JMR3927 is not set
+# CONFIG_MIPS_COBALT is not set
+CONFIG_MACH_DECSTATION=y
+# CONFIG_MIPS_EV64120 is not set
+# CONFIG_MIPS_EV96100 is not set
+# CONFIG_MIPS_IVR is not set
+# CONFIG_LASAT is not set
+# CONFIG_HP_LASERJET is not set
+# CONFIG_MIPS_ITE8172 is not set
+# CONFIG_MIPS_ATLAS is not set
+# CONFIG_MIPS_MALTA is not set
+# CONFIG_MIPS_SEAD is not set
+# CONFIG_MOMENCO_OCELOT is not set
+# CONFIG_MOMENCO_OCELOT_G is not set
+# CONFIG_MOMENCO_OCELOT_C is not set
+# CONFIG_MOMENCO_JAGUAR_ATX is not set
+# CONFIG_PMC_YOSEMITE is not set
+# CONFIG_DDB5074 is not set
+# CONFIG_DDB5476 is not set
+# CONFIG_DDB5477 is not set
+# CONFIG_NEC_OSPREY is not set
+# CONFIG_SGI_IP22 is not set
+# CONFIG_SGI_IP32 is not set
+# CONFIG_SOC_AU1X00 is not set
+# CONFIG_SIBYTE_SB1xxx_SOC is not set
+# CONFIG_SNI_RM200_PCI is not set
+# CONFIG_TOSHIBA_RBTX4927 is not set
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_HAVE_DEC_LOCK=y
+CONFIG_DMA_NONCOHERENT=y
+CONFIG_EARLY_PRINTK=y
+CONFIG_CPU_LITTLE_ENDIAN=y
+CONFIG_IRQ_CPU=y
+CONFIG_BOOT_ELF32=y
+CONFIG_MIPS_L1_CACHE_SHIFT=4
+# CONFIG_FB is not set
+
+#
+# CPU selection
+#
+# CONFIG_CPU_MIPS32 is not set
+# CONFIG_CPU_MIPS64 is not set
+CONFIG_CPU_R3000=y
+# CONFIG_CPU_TX39XX is not set
+# CONFIG_CPU_VR41XX is not set
+# CONFIG_CPU_R4300 is not set
+# CONFIG_CPU_R4X00 is not set
+# CONFIG_CPU_TX49XX is not set
+# CONFIG_CPU_R5000 is not set
+# CONFIG_CPU_R5432 is not set
+# CONFIG_CPU_R6000 is not set
+# CONFIG_CPU_NEVADA is not set
+# CONFIG_CPU_R8000 is not set
+# CONFIG_CPU_R10000 is not set
+# CONFIG_CPU_RM7000 is not set
+# CONFIG_CPU_RM9000 is not set
+# CONFIG_CPU_SB1 is not set
+CONFIG_PAGE_SIZE_4KB=y
+# CONFIG_PAGE_SIZE_16KB is not set
+# CONFIG_PAGE_SIZE_64KB is not set
+# CONFIG_CPU_ADVANCED is not set
+CONFIG_CPU_HAS_WB=y
+# CONFIG_PREEMPT is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+
+#
+# Bus options (PCI, PCMCIA, EISA, ISA, TC)
+#
+CONFIG_TC=y
+CONFIG_MMU=y
+# CONFIG_HOTPLUG is not set
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_MISC is not set
+CONFIG_TRAD_SIGNALS=y
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+# CONFIG_BLK_DEV_LOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_RAM is not set
+# CONFIG_BLK_DEV_INITRD is not set
+# CONFIG_LBD is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+CONFIG_SCSI=y
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=y
+# CONFIG_CHR_DEV_ST is not set
+# CONFIG_CHR_DEV_OSST is not set
+# CONFIG_BLK_DEV_SR is not set
+# CONFIG_CHR_DEV_SG is not set
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+# CONFIG_SCSI_MULTI_LUN is not set
+# CONFIG_SCSI_REPORT_LUNS is not set
+CONFIG_SCSI_CONSTANTS=y
+# CONFIG_SCSI_LOGGING is not set
+
+#
+# SCSI low-level drivers
+#
+CONFIG_SCSI_DECNCR=y
+# CONFIG_SCSI_DECSII is not set
+# CONFIG_SCSI_AIC7XXX_OLD is not set
+# CONFIG_SCSI_SATA is not set
+# CONFIG_SCSI_EATA_PIO is not set
+# CONFIG_SCSI_DEBUG is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+# CONFIG_FUSION is not set
+
+#
+# IEEE 1394 (FireWire) support (EXPERIMENTAL)
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+
+#
+# Macintosh device drivers
+#
+
+#
+# Networking support
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+CONFIG_NETLINK_DEV=y
+CONFIG_UNIX=y
+CONFIG_NET_KEY=y
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_PNP=y
+# CONFIG_IP_PNP_DHCP is not set
+CONFIG_IP_PNP_BOOTP=y
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_ARPD is not set
+# CONFIG_INET_ECN is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_IPV6 is not set
+# CONFIG_DECNET is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_NETFILTER is not set
+CONFIG_XFRM=y
+# CONFIG_XFRM_USER is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+CONFIG_IPV6_SCTP__=y
+# CONFIG_IP_SCTP is not set
+# CONFIG_ATM is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_FASTROUTE is not set
+# CONFIG_NET_HW_FLOWCONTROL is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+# CONFIG_ETHERTAP is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+# CONFIG_MII is not set
+CONFIG_DECLANCE=y
+
+#
+# Ethernet (1000 Mbit)
+#
+
+#
+# Ethernet (10000 Mbit)
+#
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Token Ring devices
+#
+# CONFIG_SHAPER is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+
+#
+# Amateur Radio support
+#
+# CONFIG_HAMRADIO is not set
+
+#
+# IrDA (infrared) support
+#
+# CONFIG_IRDA is not set
+
+#
+# Bluetooth support
+#
+# CONFIG_BT is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN_BOOL is not set
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+CONFIG_INPUT_MOUSEDEV_PSAUX=y
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+# CONFIG_INPUT_EVDEV is not set
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input I/O drivers
+#
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+CONFIG_SERIO=y
+# CONFIG_SERIO_I8042 is not set
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_CT82C710 is not set
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_DZ=y
+CONFIG_SERIAL_DZ_CONSOLE=y
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+CONFIG_UNIX98_PTY_COUNT=256
+
+#
+# Mice
+#
+# CONFIG_BUSMOUSE is not set
+# CONFIG_QIC02_TAPE is not set
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_NVRAM is not set
+# CONFIG_RTC is not set
+# CONFIG_GEN_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_FTAPE is not set
+# CONFIG_AGP is not set
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+# CONFIG_MDA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+CONFIG_EXT2_FS_XATTR=y
+CONFIG_EXT2_FS_POSIX_ACL=y
+CONFIG_EXT2_FS_SECURITY=y
+# CONFIG_EXT3_FS is not set
+# CONFIG_JBD is not set
+CONFIG_FS_MBCACHE=y
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+CONFIG_FS_POSIX_ACL=y
+# CONFIG_XFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_QUOTA is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_FAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+# CONFIG_DEVFS_FS is not set
+CONFIG_DEVPTS_FS=y
+CONFIG_DEVPTS_FS_XATTR=y
+CONFIG_DEVPTS_FS_SECURITY=y
+# CONFIG_TMPFS is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+# CONFIG_NFS_FS is not set
+# CONFIG_NFSD is not set
+# CONFIG_EXPORTFS is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_INTERMEZZO_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+CONFIG_OSF_PARTITION=y
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+# CONFIG_MAC_PARTITION is not set
+CONFIG_MSDOS_PARTITION=y
+# CONFIG_BSD_DISKLABEL is not set
+# CONFIG_MINIX_SUBPARTITION is not set
+# CONFIG_SOLARIS_X86_PARTITION is not set
+# CONFIG_UNIXWARE_DISKLABEL is not set
+# CONFIG_LDM_PARTITION is not set
+# CONFIG_NEC98_PARTITION is not set
+# CONFIG_SGI_PARTITION is not set
+CONFIG_ULTRIX_PARTITION=y
+# CONFIG_SUN_PARTITION is not set
+# CONFIG_EFI_PARTITION is not set
+
+#
+# Native Language Support
+#
+# CONFIG_NLS is not set
+
+#
+# Kernel hacking
+#
+CONFIG_CROSSCOMPILE=y
+CONFIG_CMDLINE=""
+# CONFIG_DEBUG_KERNEL is not set
+
+#
+# Security options
+#
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
+# Library routines
+#
+CONFIG_CRC32=y
--- diff/arch/mips/configs/e55_defconfig	1970-01-01 01:00:00.000000000 +0100
+++ source/arch/mips/configs/e55_defconfig	2004-02-23 13:56:38.000000000 +0000
@@ -0,0 +1,589 @@
+#
+# Automatically generated make config: don't edit
+#
+CONFIG_MIPS=y
+# CONFIG_MIPS64 is not set
+# CONFIG_64BIT is not set
+CONFIG_MIPS32=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_CLEAN_COMPILE=y
+CONFIG_STANDALONE=y
+CONFIG_BROKEN_ON_SMP=y
+
+#
+# General setup
+#
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_IKCONFIG is not set
+CONFIG_EMBEDDED=y
+CONFIG_KALLSYMS=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+CONFIG_OBSOLETE_MODPARM=y
+CONFIG_MODVERSIONS=y
+CONFIG_KMOD=y
+
+#
+# Machine selection
+#
+# CONFIG_MACH_JAZZ is not set
+# CONFIG_BAGET_MIPS is not set
+CONFIG_MACH_VR41XX=y
+CONFIG_CASIO_E55=y
+# CONFIG_IBM_WORKPAD is not set
+# CONFIG_NEC_EAGLE is not set
+# CONFIG_TANBAC_TB0226 is not set
+# CONFIG_TANBAC_TB0229 is not set
+# CONFIG_VICTOR_MPC30X is not set
+# CONFIG_ZAO_CAPCELLA is not set
+# CONFIG_TOSHIBA_JMR3927 is not set
+# CONFIG_MIPS_COBALT is not set
+# CONFIG_MACH_DECSTATION is not set
+# CONFIG_MIPS_EV64120 is not set
+# CONFIG_MIPS_EV96100 is not set
+# CONFIG_MIPS_IVR is not set
+# CONFIG_LASAT is not set
+# CONFIG_HP_LASERJET is not set
+# CONFIG_MIPS_ITE8172 is not set
+# CONFIG_MIPS_ATLAS is not set
+# CONFIG_MIPS_MALTA is not set
+# CONFIG_MIPS_SEAD is not set
+# CONFIG_MOMENCO_OCELOT is not set
+# CONFIG_MOMENCO_OCELOT_G is not set
+# CONFIG_MOMENCO_OCELOT_C is not set
+# CONFIG_MOMENCO_JAGUAR_ATX is not set
+# CONFIG_PMC_YOSEMITE is not set
+# CONFIG_DDB5074 is not set
+# CONFIG_DDB5476 is not set
+# CONFIG_DDB5477 is not set
+# CONFIG_NEC_OSPREY is not set
+# CONFIG_SGI_IP22 is not set
+# CONFIG_SGI_IP32 is not set
+# CONFIG_SOC_AU1X00 is not set
+# CONFIG_SIBYTE_SB1xxx_SOC is not set
+# CONFIG_SNI_RM200_PCI is not set
+# CONFIG_TOSHIBA_RBTX4927 is not set
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_HAVE_DEC_LOCK=y
+CONFIG_DMA_NONCOHERENT=y
+CONFIG_CPU_LITTLE_ENDIAN=y
+CONFIG_IRQ_CPU=y
+CONFIG_DUMMY_KEYB=y
+CONFIG_MIPS_L1_CACHE_SHIFT=5
+# CONFIG_FB is not set
+
+#
+# CPU selection
+#
+# CONFIG_CPU_MIPS32 is not set
+# CONFIG_CPU_MIPS64 is not set
+# CONFIG_CPU_R3000 is not set
+# CONFIG_CPU_TX39XX is not set
+CONFIG_CPU_VR41XX=y
+# CONFIG_CPU_R4300 is not set
+# CONFIG_CPU_R4X00 is not set
+# CONFIG_CPU_TX49XX is not set
+# CONFIG_CPU_R5000 is not set
+# CONFIG_CPU_R5432 is not set
+# CONFIG_CPU_R6000 is not set
+# CONFIG_CPU_NEVADA is not set
+# CONFIG_CPU_R8000 is not set
+# CONFIG_CPU_R10000 is not set
+# CONFIG_CPU_RM7000 is not set
+# CONFIG_CPU_RM9000 is not set
+# CONFIG_CPU_SB1 is not set
+CONFIG_PAGE_SIZE_4KB=y
+# CONFIG_PAGE_SIZE_16KB is not set
+# CONFIG_PAGE_SIZE_64KB is not set
+# CONFIG_CPU_ADVANCED is not set
+CONFIG_CPU_HAS_SYNC=y
+# CONFIG_PREEMPT is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+
+#
+# Bus options (PCI, PCMCIA, EISA, ISA, TC)
+#
+CONFIG_MMU=y
+# CONFIG_HOTPLUG is not set
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_MISC is not set
+CONFIG_TRAD_SIGNALS=y
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+# CONFIG_BLK_DEV_LOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_RAM is not set
+# CONFIG_BLK_DEV_INITRD is not set
+# CONFIG_LBD is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+CONFIG_IDE=y
+CONFIG_BLK_DEV_IDE=y
+
+#
+# Please see Documentation/ide.txt for help/info on IDE drives
+#
+CONFIG_BLK_DEV_IDEDISK=y
+# CONFIG_IDEDISK_MULTI_MODE is not set
+# CONFIG_IDEDISK_STROKE is not set
+# CONFIG_BLK_DEV_IDECD is not set
+# CONFIG_BLK_DEV_IDETAPE is not set
+# CONFIG_BLK_DEV_IDEFLOPPY is not set
+# CONFIG_IDE_TASK_IOCTL is not set
+CONFIG_IDE_TASKFILE_IO=y
+
+#
+# IDE chipset support/bugfixes
+#
+CONFIG_IDE_GENERIC=y
+# CONFIG_BLK_DEV_IDEDMA is not set
+# CONFIG_IDEDMA_AUTO is not set
+# CONFIG_DMA_NONPCI is not set
+# CONFIG_BLK_DEV_HD is not set
+
+#
+# SCSI device support
+#
+# CONFIG_SCSI is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+
+#
+# IEEE 1394 (FireWire) support (EXPERIMENTAL)
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+
+#
+# Macintosh device drivers
+#
+
+#
+# Networking support
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+CONFIG_PACKET_MMAP=y
+CONFIG_NETLINK_DEV=y
+CONFIG_UNIX=y
+CONFIG_NET_KEY=y
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+# CONFIG_IP_ADVANCED_ROUTER is not set
+# CONFIG_IP_PNP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_IP_MROUTE is not set
+# CONFIG_ARPD is not set
+# CONFIG_INET_ECN is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_IPV6 is not set
+# CONFIG_DECNET is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_NETFILTER is not set
+CONFIG_XFRM=y
+# CONFIG_XFRM_USER is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+CONFIG_IPV6_SCTP__=y
+# CONFIG_IP_SCTP is not set
+# CONFIG_ATM is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_FASTROUTE is not set
+# CONFIG_NET_HW_FLOWCONTROL is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+# CONFIG_ETHERTAP is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+# CONFIG_MII is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+
+#
+# Ethernet (10000 Mbit)
+#
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Token Ring devices
+#
+# CONFIG_SHAPER is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+
+#
+# Amateur Radio support
+#
+# CONFIG_HAMRADIO is not set
+
+#
+# IrDA (infrared) support
+#
+# CONFIG_IRDA is not set
+
+#
+# Bluetooth support
+#
+# CONFIG_BT is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN_BOOL is not set
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+CONFIG_INPUT_MOUSEDEV_PSAUX=y
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+# CONFIG_INPUT_EVDEV is not set
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input I/O drivers
+#
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+CONFIG_SERIO=y
+CONFIG_SERIO_I8042=y
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_CT82C710 is not set
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=4
+# CONFIG_SERIAL_8250_EXTENDED is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+CONFIG_UNIX98_PTY_COUNT=256
+
+#
+# Mice
+#
+# CONFIG_BUSMOUSE is not set
+# CONFIG_QIC02_TAPE is not set
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+CONFIG_WATCHDOG=y
+# CONFIG_WATCHDOG_NOWAYOUT is not set
+
+#
+# Watchdog Device Drivers
+#
+# CONFIG_SOFT_WATCHDOG is not set
+# CONFIG_NVRAM is not set
+# CONFIG_RTC is not set
+# CONFIG_GEN_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_FTAPE is not set
+# CONFIG_AGP is not set
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+# CONFIG_MDA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_JBD is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_QUOTA is not set
+CONFIG_AUTOFS_FS=y
+CONFIG_AUTOFS4_FS=y
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_FAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+# CONFIG_DEVFS_FS is not set
+CONFIG_DEVPTS_FS=y
+CONFIG_DEVPTS_FS_XATTR=y
+CONFIG_DEVPTS_FS_SECURITY=y
+# CONFIG_TMPFS is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+# CONFIG_NFS_V3 is not set
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
+CONFIG_NFSD=y
+# CONFIG_NFSD_V3 is not set
+# CONFIG_NFSD_TCP is not set
+CONFIG_LOCKD=y
+CONFIG_EXPORTFS=y
+CONFIG_SUNRPC=y
+# CONFIG_SUNRPC_GSS is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_INTERMEZZO_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+
+#
+# Native Language Support
+#
+# CONFIG_NLS is not set
+
+#
+# Kernel hacking
+#
+CONFIG_CROSSCOMPILE=y
+CONFIG_CMDLINE=""
+# CONFIG_DEBUG_KERNEL is not set
+
+#
+# Security options
+#
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
+# Library routines
+#
+# CONFIG_CRC32 is not set
--- diff/arch/mips/configs/eagle_defconfig	1970-01-01 01:00:00.000000000 +0100
+++ source/arch/mips/configs/eagle_defconfig	2004-02-23 13:56:38.000000000 +0000
@@ -0,0 +1,759 @@
+#
+# Automatically generated make config: don't edit
+#
+CONFIG_MIPS=y
+# CONFIG_MIPS64 is not set
+# CONFIG_64BIT is not set
+CONFIG_MIPS32=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_CLEAN_COMPILE=y
+CONFIG_STANDALONE=y
+CONFIG_BROKEN_ON_SMP=y
+
+#
+# General setup
+#
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_IKCONFIG is not set
+CONFIG_EMBEDDED=y
+CONFIG_KALLSYMS=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+CONFIG_OBSOLETE_MODPARM=y
+CONFIG_MODVERSIONS=y
+CONFIG_KMOD=y
+
+#
+# Machine selection
+#
+# CONFIG_MACH_JAZZ is not set
+# CONFIG_BAGET_MIPS is not set
+CONFIG_MACH_VR41XX=y
+# CONFIG_CASIO_E55 is not set
+# CONFIG_IBM_WORKPAD is not set
+CONFIG_NEC_EAGLE=y
+# CONFIG_TANBAC_TB0226 is not set
+# CONFIG_TANBAC_TB0229 is not set
+# CONFIG_VICTOR_MPC30X is not set
+# CONFIG_ZAO_CAPCELLA is not set
+# CONFIG_TOSHIBA_JMR3927 is not set
+# CONFIG_MIPS_COBALT is not set
+# CONFIG_MACH_DECSTATION is not set
+# CONFIG_MIPS_EV64120 is not set
+# CONFIG_MIPS_EV96100 is not set
+# CONFIG_MIPS_IVR is not set
+# CONFIG_LASAT is not set
+# CONFIG_HP_LASERJET is not set
+# CONFIG_MIPS_ITE8172 is not set
+# CONFIG_MIPS_ATLAS is not set
+# CONFIG_MIPS_MALTA is not set
+# CONFIG_MIPS_SEAD is not set
+# CONFIG_MOMENCO_OCELOT is not set
+# CONFIG_MOMENCO_OCELOT_G is not set
+# CONFIG_MOMENCO_OCELOT_C is not set
+# CONFIG_MOMENCO_JAGUAR_ATX is not set
+# CONFIG_PMC_YOSEMITE is not set
+# CONFIG_DDB5074 is not set
+# CONFIG_DDB5476 is not set
+# CONFIG_DDB5477 is not set
+# CONFIG_NEC_OSPREY is not set
+# CONFIG_SGI_IP22 is not set
+# CONFIG_SGI_IP32 is not set
+# CONFIG_SOC_AU1X00 is not set
+# CONFIG_SIBYTE_SB1xxx_SOC is not set
+# CONFIG_SNI_RM200_PCI is not set
+# CONFIG_TOSHIBA_RBTX4927 is not set
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_HAVE_DEC_LOCK=y
+CONFIG_DMA_NONCOHERENT=y
+CONFIG_CPU_LITTLE_ENDIAN=y
+CONFIG_IRQ_CPU=y
+CONFIG_DUMMY_KEYB=y
+CONFIG_VRC4173=y
+CONFIG_MIPS_L1_CACHE_SHIFT=5
+# CONFIG_FB is not set
+
+#
+# CPU selection
+#
+# CONFIG_CPU_MIPS32 is not set
+# CONFIG_CPU_MIPS64 is not set
+# CONFIG_CPU_R3000 is not set
+# CONFIG_CPU_TX39XX is not set
+CONFIG_CPU_VR41XX=y
+# CONFIG_CPU_R4300 is not set
+# CONFIG_CPU_R4X00 is not set
+# CONFIG_CPU_TX49XX is not set
+# CONFIG_CPU_R5000 is not set
+# CONFIG_CPU_R5432 is not set
+# CONFIG_CPU_R6000 is not set
+# CONFIG_CPU_NEVADA is not set
+# CONFIG_CPU_R8000 is not set
+# CONFIG_CPU_R10000 is not set
+# CONFIG_CPU_RM7000 is not set
+# CONFIG_CPU_RM9000 is not set
+# CONFIG_CPU_SB1 is not set
+CONFIG_PAGE_SIZE_4KB=y
+# CONFIG_PAGE_SIZE_16KB is not set
+# CONFIG_PAGE_SIZE_64KB is not set
+# CONFIG_CPU_ADVANCED is not set
+CONFIG_CPU_HAS_SYNC=y
+# CONFIG_PREEMPT is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+
+#
+# Bus options (PCI, PCMCIA, EISA, ISA, TC)
+#
+CONFIG_PCI=y
+CONFIG_PCI_LEGACY_PROC=y
+CONFIG_PCI_NAMES=y
+CONFIG_MMU=y
+CONFIG_HOTPLUG=y
+
+#
+# PCMCIA/CardBus support
+#
+CONFIG_PCMCIA=y
+# CONFIG_YENTA is not set
+# CONFIG_I82092 is not set
+# CONFIG_TCIC is not set
+# CONFIG_PCMCIA_VRC4173 is not set
+
+#
+# PCI Hotplug Support
+#
+# CONFIG_HOTPLUG_PCI is not set
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_MISC is not set
+CONFIG_TRAD_SIGNALS=y
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+# CONFIG_FW_LOADER is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+# CONFIG_MTD_PARTITIONS is not set
+# CONFIG_MTD_CONCAT is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+CONFIG_MTD_CFI=y
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_GEN_PROBE=y
+CONFIG_MTD_CFI_ADV_OPTIONS=y
+CONFIG_MTD_CFI_NOSWAP=y
+# CONFIG_MTD_CFI_BE_BYTE_SWAP is not set
+# CONFIG_MTD_CFI_LE_BYTE_SWAP is not set
+# CONFIG_MTD_CFI_GEOMETRY is not set
+CONFIG_MTD_CFI_INTELEXT=y
+# CONFIG_MTD_CFI_AMDSTD is not set
+# CONFIG_MTD_CFI_STAA is not set
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+# CONFIG_MTD_OBSOLETE_CHIPS is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+CONFIG_MTD_PHYSMAP=y
+CONFIG_MTD_PHYSMAP_START=0x1c000000
+CONFIG_MTD_PHYSMAP_LEN=0x2000000
+CONFIG_MTD_PHYSMAP_BUSWIDTH=4
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_PMC551 is not set
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLKMTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+
+#
+# NAND Flash Device Drivers
+#
+# CONFIG_MTD_NAND is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_UMEM is not set
+# CONFIG_BLK_DEV_LOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_RAM is not set
+# CONFIG_BLK_DEV_INITRD is not set
+# CONFIG_LBD is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+CONFIG_IDE=y
+CONFIG_BLK_DEV_IDE=y
+
+#
+# Please see Documentation/ide.txt for help/info on IDE drives
+#
+CONFIG_BLK_DEV_IDEDISK=y
+CONFIG_IDEDISK_MULTI_MODE=y
+# CONFIG_IDEDISK_STROKE is not set
+CONFIG_BLK_DEV_IDECS=y
+# CONFIG_BLK_DEV_IDECD is not set
+# CONFIG_BLK_DEV_IDETAPE is not set
+# CONFIG_BLK_DEV_IDEFLOPPY is not set
+# CONFIG_IDE_TASK_IOCTL is not set
+CONFIG_IDE_TASKFILE_IO=y
+
+#
+# IDE chipset support/bugfixes
+#
+CONFIG_IDE_GENERIC=y
+# CONFIG_BLK_DEV_IDEPCI is not set
+# CONFIG_BLK_DEV_IDEDMA is not set
+# CONFIG_IDEDMA_AUTO is not set
+# CONFIG_DMA_NONPCI is not set
+# CONFIG_BLK_DEV_HD is not set
+
+#
+# SCSI device support
+#
+# CONFIG_SCSI is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+
+#
+# IEEE 1394 (FireWire) support (EXPERIMENTAL)
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+
+#
+# Macintosh device drivers
+#
+
+#
+# Networking support
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+CONFIG_PACKET_MMAP=y
+CONFIG_NETLINK_DEV=y
+CONFIG_UNIX=y
+CONFIG_NET_KEY=y
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_PNP=y
+# CONFIG_IP_PNP_DHCP is not set
+CONFIG_IP_PNP_BOOTP=y
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_IP_MROUTE is not set
+# CONFIG_ARPD is not set
+# CONFIG_INET_ECN is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_IPV6 is not set
+# CONFIG_DECNET is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_NETFILTER is not set
+CONFIG_XFRM=y
+# CONFIG_XFRM_USER is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+CONFIG_IPV6_SCTP__=y
+# CONFIG_IP_SCTP is not set
+# CONFIG_ATM is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_FASTROUTE is not set
+# CONFIG_NET_HW_FLOWCONTROL is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+CONFIG_NETDEVICES=y
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+# CONFIG_ETHERTAP is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+# CONFIG_MII is not set
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_SUNGEM is not set
+# CONFIG_NET_VENDOR_3COM is not set
+
+#
+# Tulip family network device support
+#
+# CONFIG_NET_TULIP is not set
+# CONFIG_HP100 is not set
+# CONFIG_NET_PCI is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+# CONFIG_E1000 is not set
+# CONFIG_NS83820 is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+# CONFIG_R8169 is not set
+# CONFIG_SIS190 is not set
+# CONFIG_SK98LIN is not set
+# CONFIG_TIGON3 is not set
+
+#
+# Ethernet (10000 Mbit)
+#
+# CONFIG_IXGB is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Token Ring devices
+#
+# CONFIG_TR is not set
+# CONFIG_RCPCI is not set
+# CONFIG_SHAPER is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+
+#
+# PCMCIA network device support
+#
+CONFIG_NET_PCMCIA=y
+# CONFIG_PCMCIA_3C589 is not set
+# CONFIG_PCMCIA_3C574 is not set
+CONFIG_PCMCIA_FMVJ18X=y
+CONFIG_PCMCIA_PCNET=m
+# CONFIG_PCMCIA_NMCLAN is not set
+# CONFIG_PCMCIA_SMC91C92 is not set
+# CONFIG_PCMCIA_XIRC2PS is not set
+# CONFIG_PCMCIA_AXNET is not set
+
+#
+# Amateur Radio support
+#
+# CONFIG_HAMRADIO is not set
+
+#
+# IrDA (infrared) support
+#
+# CONFIG_IRDA is not set
+
+#
+# Bluetooth support
+#
+# CONFIG_BT is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN_BOOL is not set
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+CONFIG_INPUT_MOUSEDEV_PSAUX=y
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+# CONFIG_INPUT_EVDEV is not set
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input I/O drivers
+#
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+CONFIG_SERIO=y
+CONFIG_SERIO_I8042=y
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_CT82C710 is not set
+# CONFIG_SERIO_PCIPS2 is not set
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+# CONFIG_SERIAL_8250_CS is not set
+CONFIG_SERIAL_8250_NR_UARTS=4
+# CONFIG_SERIAL_8250_EXTENDED is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+CONFIG_UNIX98_PTY_COUNT=256
+
+#
+# Mice
+#
+# CONFIG_BUSMOUSE is not set
+# CONFIG_QIC02_TAPE is not set
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+CONFIG_WATCHDOG=y
+# CONFIG_WATCHDOG_NOWAYOUT is not set
+
+#
+# Watchdog Device Drivers
+#
+# CONFIG_SOFT_WATCHDOG is not set
+
+#
+# PCI-based Watchdog Cards
+#
+# CONFIG_PCIPCWATCHDOG is not set
+# CONFIG_WDTPCI is not set
+# CONFIG_NVRAM is not set
+# CONFIG_RTC is not set
+# CONFIG_GEN_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_FTAPE is not set
+# CONFIG_AGP is not set
+# CONFIG_DRM is not set
+
+#
+# PCMCIA character devices
+#
+# CONFIG_SYNCLINK_CS is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+# CONFIG_MDA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+# CONFIG_USB is not set
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_JBD is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_QUOTA is not set
+CONFIG_AUTOFS_FS=y
+CONFIG_AUTOFS4_FS=y
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_FAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+# CONFIG_DEVFS_FS is not set
+CONFIG_DEVPTS_FS=y
+CONFIG_DEVPTS_FS_XATTR=y
+CONFIG_DEVPTS_FS_SECURITY=y
+# CONFIG_TMPFS is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+CONFIG_JFFS_FS=y
+CONFIG_JFFS_FS_VERBOSE=0
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_FS_DEBUG=0
+# CONFIG_JFFS2_FS_NAND is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+# CONFIG_NFS_V3 is not set
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
+CONFIG_NFSD=y
+# CONFIG_NFSD_V3 is not set
+# CONFIG_NFSD_TCP is not set
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+CONFIG_EXPORTFS=y
+CONFIG_SUNRPC=y
+# CONFIG_SUNRPC_GSS is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_INTERMEZZO_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+
+#
+# Native Language Support
+#
+# CONFIG_NLS is not set
+
+#
+# Kernel hacking
+#
+CONFIG_CROSSCOMPILE=y
+CONFIG_CMDLINE=""
+# CONFIG_DEBUG_KERNEL is not set
+
+#
+# Security options
+#
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+CONFIG_CRYPTO=y
+CONFIG_CRYPTO_HMAC=y
+CONFIG_CRYPTO_NULL=y
+# CONFIG_CRYPTO_MD4 is not set
+# CONFIG_CRYPTO_MD5 is not set
+# CONFIG_CRYPTO_SHA1 is not set
+# CONFIG_CRYPTO_SHA256 is not set
+CONFIG_CRYPTO_SHA512=y
+# CONFIG_CRYPTO_DES is not set
+# CONFIG_CRYPTO_BLOWFISH is not set
+CONFIG_CRYPTO_TWOFISH=y
+# CONFIG_CRYPTO_SERPENT is not set
+CONFIG_CRYPTO_AES=y
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+CONFIG_CRYPTO_DEFLATE=y
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Library routines
+#
+CONFIG_CRC32=y
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
--- diff/arch/mips/configs/ev64120_defconfig	1970-01-01 01:00:00.000000000 +0100
+++ source/arch/mips/configs/ev64120_defconfig	2004-02-23 13:56:38.000000000 +0000
@@ -0,0 +1,608 @@
+#
+# Automatically generated make config: don't edit
+#
+CONFIG_MIPS=y
+# CONFIG_MIPS64 is not set
+# CONFIG_64BIT is not set
+CONFIG_MIPS32=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_CLEAN_COMPILE=y
+CONFIG_STANDALONE=y
+CONFIG_BROKEN_ON_SMP=y
+
+#
+# General setup
+#
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_IKCONFIG is not set
+CONFIG_EMBEDDED=y
+CONFIG_KALLSYMS=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+CONFIG_OBSOLETE_MODPARM=y
+CONFIG_MODVERSIONS=y
+# CONFIG_KMOD is not set
+
+#
+# Machine selection
+#
+# CONFIG_MACH_JAZZ is not set
+# CONFIG_BAGET_MIPS is not set
+# CONFIG_MACH_VR41XX is not set
+# CONFIG_TOSHIBA_JMR3927 is not set
+# CONFIG_MIPS_COBALT is not set
+# CONFIG_MACH_DECSTATION is not set
+CONFIG_MIPS_EV64120=y
+# CONFIG_EVB_PCI1 is not set
+# CONFIG_MIPS_EV96100 is not set
+# CONFIG_MIPS_IVR is not set
+# CONFIG_LASAT is not set
+# CONFIG_HP_LASERJET is not set
+# CONFIG_MIPS_ITE8172 is not set
+# CONFIG_MIPS_ATLAS is not set
+# CONFIG_MIPS_MALTA is not set
+# CONFIG_MIPS_SEAD is not set
+# CONFIG_MOMENCO_OCELOT is not set
+# CONFIG_MOMENCO_OCELOT_G is not set
+# CONFIG_MOMENCO_OCELOT_C is not set
+# CONFIG_MOMENCO_JAGUAR_ATX is not set
+# CONFIG_PMC_YOSEMITE is not set
+# CONFIG_DDB5074 is not set
+# CONFIG_DDB5476 is not set
+# CONFIG_DDB5477 is not set
+# CONFIG_NEC_OSPREY is not set
+# CONFIG_SGI_IP22 is not set
+# CONFIG_SGI_IP32 is not set
+# CONFIG_SOC_AU1X00 is not set
+# CONFIG_SIBYTE_SB1xxx_SOC is not set
+# CONFIG_SNI_RM200_PCI is not set
+# CONFIG_TOSHIBA_RBTX4927 is not set
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_HAVE_DEC_LOCK=y
+CONFIG_DMA_NONCOHERENT=y
+# CONFIG_CPU_LITTLE_ENDIAN is not set
+CONFIG_MIPS_GT64120=y
+# CONFIG_SYSCLK_75 is not set
+# CONFIG_SYSCLK_83 is not set
+CONFIG_SYSCLK_100=y
+CONFIG_MIPS_L1_CACHE_SHIFT=5
+# CONFIG_FB is not set
+
+#
+# CPU selection
+#
+# CONFIG_CPU_MIPS32 is not set
+# CONFIG_CPU_MIPS64 is not set
+# CONFIG_CPU_R3000 is not set
+# CONFIG_CPU_TX39XX is not set
+# CONFIG_CPU_VR41XX is not set
+# CONFIG_CPU_R4300 is not set
+# CONFIG_CPU_R4X00 is not set
+# CONFIG_CPU_TX49XX is not set
+CONFIG_CPU_R5000=y
+# CONFIG_CPU_R5432 is not set
+# CONFIG_CPU_R6000 is not set
+# CONFIG_CPU_NEVADA is not set
+# CONFIG_CPU_R8000 is not set
+# CONFIG_CPU_R10000 is not set
+# CONFIG_CPU_RM7000 is not set
+# CONFIG_CPU_RM9000 is not set
+# CONFIG_CPU_SB1 is not set
+CONFIG_PAGE_SIZE_4KB=y
+# CONFIG_PAGE_SIZE_16KB is not set
+# CONFIG_PAGE_SIZE_64KB is not set
+# CONFIG_64BIT_PHYS_ADDR is not set
+# CONFIG_CPU_ADVANCED is not set
+CONFIG_CPU_HAS_LLSC=y
+CONFIG_CPU_HAS_LLDSCD=y
+CONFIG_CPU_HAS_SYNC=y
+# CONFIG_PREEMPT is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+
+#
+# Bus options (PCI, PCMCIA, EISA, ISA, TC)
+#
+CONFIG_PCI=y
+CONFIG_PCI_LEGACY_PROC=y
+CONFIG_PCI_NAMES=y
+CONFIG_MMU=y
+# CONFIG_HOTPLUG is not set
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_MISC is not set
+CONFIG_TRAD_SIGNALS=y
+# CONFIG_BINFMT_IRIX is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_UMEM is not set
+# CONFIG_BLK_DEV_LOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_RAM is not set
+# CONFIG_BLK_DEV_INITRD is not set
+# CONFIG_LBD is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_SCSI is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+
+#
+# IEEE 1394 (FireWire) support (EXPERIMENTAL)
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+
+#
+# Macintosh device drivers
+#
+
+#
+# Networking support
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+# CONFIG_PACKET is not set
+CONFIG_NETLINK_DEV=y
+CONFIG_UNIX=y
+CONFIG_NET_KEY=y
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_PNP=y
+# CONFIG_IP_PNP_DHCP is not set
+# CONFIG_IP_PNP_BOOTP is not set
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_ARPD is not set
+# CONFIG_INET_ECN is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_IPV6 is not set
+# CONFIG_DECNET is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_NETFILTER is not set
+CONFIG_XFRM=y
+# CONFIG_XFRM_USER is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+CONFIG_IPV6_SCTP__=y
+# CONFIG_IP_SCTP is not set
+# CONFIG_ATM is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_FASTROUTE is not set
+# CONFIG_NET_HW_FLOWCONTROL is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+CONFIG_NETDEVICES=y
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+# CONFIG_ETHERTAP is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+# CONFIG_MII is not set
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_SUNGEM is not set
+# CONFIG_NET_VENDOR_3COM is not set
+
+#
+# Tulip family network device support
+#
+# CONFIG_NET_TULIP is not set
+# CONFIG_HP100 is not set
+# CONFIG_NET_PCI is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+# CONFIG_E1000 is not set
+# CONFIG_NS83820 is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+# CONFIG_R8169 is not set
+# CONFIG_SIS190 is not set
+# CONFIG_SK98LIN is not set
+# CONFIG_TIGON3 is not set
+
+#
+# Ethernet (10000 Mbit)
+#
+# CONFIG_IXGB is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+CONFIG_PPP=y
+# CONFIG_PPP_MULTILINK is not set
+# CONFIG_PPP_FILTER is not set
+CONFIG_PPP_ASYNC=y
+# CONFIG_PPP_SYNC_TTY is not set
+# CONFIG_PPP_DEFLATE is not set
+# CONFIG_PPP_BSDCOMP is not set
+# CONFIG_PPPOE is not set
+# CONFIG_SLIP is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Token Ring devices
+#
+# CONFIG_TR is not set
+# CONFIG_RCPCI is not set
+# CONFIG_SHAPER is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+
+#
+# Amateur Radio support
+#
+# CONFIG_HAMRADIO is not set
+
+#
+# IrDA (infrared) support
+#
+# CONFIG_IRDA is not set
+
+#
+# Bluetooth support
+#
+# CONFIG_BT is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN_BOOL is not set
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+CONFIG_INPUT_MOUSEDEV_PSAUX=y
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+# CONFIG_INPUT_EVDEV is not set
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input I/O drivers
+#
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+CONFIG_SERIO=y
+# CONFIG_SERIO_I8042 is not set
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_CT82C710 is not set
+# CONFIG_SERIO_PCIPS2 is not set
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=4
+# CONFIG_SERIAL_8250_EXTENDED is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+CONFIG_UNIX98_PTY_COUNT=256
+
+#
+# Mice
+#
+# CONFIG_BUSMOUSE is not set
+# CONFIG_QIC02_TAPE is not set
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_NVRAM is not set
+# CONFIG_RTC is not set
+# CONFIG_GEN_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_FTAPE is not set
+# CONFIG_AGP is not set
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+# CONFIG_MDA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+# CONFIG_USB is not set
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_JBD is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_QUOTA is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_FAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+# CONFIG_DEVFS_FS is not set
+CONFIG_DEVPTS_FS=y
+CONFIG_DEVPTS_FS_XATTR=y
+CONFIG_DEVPTS_FS_SECURITY=y
+# CONFIG_TMPFS is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+# CONFIG_NFS_V3 is not set
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
+# CONFIG_NFSD is not set
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+# CONFIG_EXPORTFS is not set
+CONFIG_SUNRPC=y
+# CONFIG_SUNRPC_GSS is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_INTERMEZZO_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+
+#
+# Native Language Support
+#
+# CONFIG_NLS is not set
+
+#
+# Kernel hacking
+#
+CONFIG_CROSSCOMPILE=y
+CONFIG_CMDLINE="console=ttyS0,115200 root=/dev/nfs rw nfsroot=192.168.1.1:/mnt/disk2/fs.gal ip=192.168.1.211:192.168.1.1:::gt::"
+# CONFIG_DEBUG_KERNEL is not set
+
+#
+# Security options
+#
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
+# Library routines
+#
+# CONFIG_CRC32 is not set
--- diff/arch/mips/configs/ev96100_defconfig	1970-01-01 01:00:00.000000000 +0100
+++ source/arch/mips/configs/ev96100_defconfig	2004-02-23 13:56:38.000000000 +0000
@@ -0,0 +1,564 @@
+#
+# Automatically generated make config: don't edit
+#
+CONFIG_MIPS=y
+# CONFIG_MIPS64 is not set
+# CONFIG_64BIT is not set
+CONFIG_MIPS32=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_CLEAN_COMPILE=y
+CONFIG_STANDALONE=y
+CONFIG_BROKEN_ON_SMP=y
+
+#
+# General setup
+#
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_IKCONFIG is not set
+CONFIG_EMBEDDED=y
+CONFIG_KALLSYMS=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+CONFIG_OBSOLETE_MODPARM=y
+CONFIG_MODVERSIONS=y
+# CONFIG_KMOD is not set
+
+#
+# Machine selection
+#
+# CONFIG_MACH_JAZZ is not set
+# CONFIG_BAGET_MIPS is not set
+# CONFIG_MACH_VR41XX is not set
+# CONFIG_TOSHIBA_JMR3927 is not set
+# CONFIG_MIPS_COBALT is not set
+# CONFIG_MACH_DECSTATION is not set
+# CONFIG_MIPS_EV64120 is not set
+CONFIG_MIPS_EV96100=y
+# CONFIG_MIPS_IVR is not set
+# CONFIG_LASAT is not set
+# CONFIG_HP_LASERJET is not set
+# CONFIG_MIPS_ITE8172 is not set
+# CONFIG_MIPS_ATLAS is not set
+# CONFIG_MIPS_MALTA is not set
+# CONFIG_MIPS_SEAD is not set
+# CONFIG_MOMENCO_OCELOT is not set
+# CONFIG_MOMENCO_OCELOT_G is not set
+# CONFIG_MOMENCO_OCELOT_C is not set
+# CONFIG_MOMENCO_JAGUAR_ATX is not set
+# CONFIG_PMC_YOSEMITE is not set
+# CONFIG_DDB5074 is not set
+# CONFIG_DDB5476 is not set
+# CONFIG_DDB5477 is not set
+# CONFIG_NEC_OSPREY is not set
+# CONFIG_SGI_IP22 is not set
+# CONFIG_SGI_IP32 is not set
+# CONFIG_SOC_AU1X00 is not set
+# CONFIG_SIBYTE_SB1xxx_SOC is not set
+# CONFIG_SNI_RM200_PCI is not set
+# CONFIG_TOSHIBA_RBTX4927 is not set
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_HAVE_DEC_LOCK=y
+CONFIG_DMA_NONCOHERENT=y
+# CONFIG_CPU_LITTLE_ENDIAN is not set
+CONFIG_IRQ_CPU=y
+CONFIG_MIPS_GT64120=y
+CONFIG_SWAP_IO_SPACE=y
+CONFIG_MIPS_GT96100=y
+CONFIG_MIPS_L1_CACHE_SHIFT=5
+# CONFIG_FB is not set
+CONFIG_BOARD_SCACHE=y
+
+#
+# CPU selection
+#
+# CONFIG_CPU_MIPS32 is not set
+# CONFIG_CPU_MIPS64 is not set
+# CONFIG_CPU_R3000 is not set
+# CONFIG_CPU_TX39XX is not set
+# CONFIG_CPU_VR41XX is not set
+# CONFIG_CPU_R4300 is not set
+# CONFIG_CPU_R4X00 is not set
+# CONFIG_CPU_TX49XX is not set
+# CONFIG_CPU_R5000 is not set
+# CONFIG_CPU_R5432 is not set
+# CONFIG_CPU_R6000 is not set
+# CONFIG_CPU_NEVADA is not set
+# CONFIG_CPU_R8000 is not set
+# CONFIG_CPU_R10000 is not set
+CONFIG_CPU_RM7000=y
+# CONFIG_CPU_RM9000 is not set
+# CONFIG_CPU_SB1 is not set
+CONFIG_PAGE_SIZE_4KB=y
+# CONFIG_PAGE_SIZE_16KB is not set
+# CONFIG_PAGE_SIZE_64KB is not set
+CONFIG_CPU_HAS_PREFETCH=y
+# CONFIG_64BIT_PHYS_ADDR is not set
+# CONFIG_CPU_ADVANCED is not set
+CONFIG_CPU_HAS_LLSC=y
+CONFIG_CPU_HAS_LLDSCD=y
+CONFIG_CPU_HAS_SYNC=y
+# CONFIG_PREEMPT is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+
+#
+# Bus options (PCI, PCMCIA, EISA, ISA, TC)
+#
+# CONFIG_PCI is not set
+CONFIG_MMU=y
+# CONFIG_HOTPLUG is not set
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_MISC is not set
+CONFIG_TRAD_SIGNALS=y
+# CONFIG_BINFMT_IRIX is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+# CONFIG_BLK_DEV_LOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_RAM is not set
+# CONFIG_BLK_DEV_INITRD is not set
+# CONFIG_LBD is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_SCSI is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+
+#
+# IEEE 1394 (FireWire) support (EXPERIMENTAL)
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+
+#
+# Macintosh device drivers
+#
+
+#
+# Networking support
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+# CONFIG_PACKET is not set
+CONFIG_NETLINK_DEV=y
+CONFIG_UNIX=y
+CONFIG_NET_KEY=y
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_PNP=y
+# CONFIG_IP_PNP_DHCP is not set
+CONFIG_IP_PNP_BOOTP=y
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_ARPD is not set
+# CONFIG_INET_ECN is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_IPV6 is not set
+# CONFIG_DECNET is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_NETFILTER is not set
+CONFIG_XFRM=y
+# CONFIG_XFRM_USER is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+CONFIG_IPV6_SCTP__=y
+# CONFIG_IP_SCTP is not set
+# CONFIG_ATM is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_FASTROUTE is not set
+# CONFIG_NET_HW_FLOWCONTROL is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+# CONFIG_ETHERTAP is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+# CONFIG_MII is not set
+CONFIG_MIPS_GT96100ETH=y
+
+#
+# Ethernet (1000 Mbit)
+#
+
+#
+# Ethernet (10000 Mbit)
+#
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Token Ring devices
+#
+# CONFIG_SHAPER is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+
+#
+# Amateur Radio support
+#
+# CONFIG_HAMRADIO is not set
+
+#
+# IrDA (infrared) support
+#
+# CONFIG_IRDA is not set
+
+#
+# Bluetooth support
+#
+# CONFIG_BT is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN_BOOL is not set
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+CONFIG_INPUT_MOUSEDEV_PSAUX=y
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+# CONFIG_INPUT_EVDEV is not set
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input I/O drivers
+#
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+CONFIG_SERIO=y
+# CONFIG_SERIO_I8042 is not set
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_CT82C710 is not set
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=4
+# CONFIG_SERIAL_8250_EXTENDED is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+CONFIG_UNIX98_PTY_COUNT=256
+
+#
+# Mice
+#
+# CONFIG_BUSMOUSE is not set
+# CONFIG_QIC02_TAPE is not set
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_NVRAM is not set
+# CONFIG_RTC is not set
+# CONFIG_GEN_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_FTAPE is not set
+# CONFIG_AGP is not set
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+# CONFIG_MDA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_JBD is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_QUOTA is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_FAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+# CONFIG_DEVFS_FS is not set
+CONFIG_DEVPTS_FS=y
+CONFIG_DEVPTS_FS_XATTR=y
+CONFIG_DEVPTS_FS_SECURITY=y
+# CONFIG_TMPFS is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+# CONFIG_NFS_V3 is not set
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
+# CONFIG_NFSD is not set
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+# CONFIG_EXPORTFS is not set
+CONFIG_SUNRPC=y
+# CONFIG_SUNRPC_GSS is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_INTERMEZZO_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+
+#
+# Native Language Support
+#
+# CONFIG_NLS is not set
+
+#
+# Kernel hacking
+#
+CONFIG_CROSSCOMPILE=y
+CONFIG_CMDLINE=""
+# CONFIG_DEBUG_KERNEL is not set
+
+#
+# Security options
+#
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
+# Library routines
+#
+# CONFIG_CRC32 is not set
--- diff/arch/mips/configs/hp-lj_defconfig	1970-01-01 01:00:00.000000000 +0100
+++ source/arch/mips/configs/hp-lj_defconfig	2004-02-23 13:56:38.000000000 +0000
@@ -0,0 +1,650 @@
+#
+# Automatically generated make config: don't edit
+#
+CONFIG_MIPS=y
+# CONFIG_MIPS64 is not set
+# CONFIG_64BIT is not set
+CONFIG_MIPS32=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_CLEAN_COMPILE=y
+CONFIG_STANDALONE=y
+CONFIG_BROKEN_ON_SMP=y
+
+#
+# General setup
+#
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_IKCONFIG is not set
+CONFIG_EMBEDDED=y
+CONFIG_KALLSYMS=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+CONFIG_OBSOLETE_MODPARM=y
+CONFIG_MODVERSIONS=y
+CONFIG_KMOD=y
+
+#
+# Machine selection
+#
+# CONFIG_MACH_JAZZ is not set
+# CONFIG_BAGET_MIPS is not set
+# CONFIG_MACH_VR41XX is not set
+# CONFIG_TOSHIBA_JMR3927 is not set
+# CONFIG_MIPS_COBALT is not set
+# CONFIG_MACH_DECSTATION is not set
+# CONFIG_MIPS_EV64120 is not set
+# CONFIG_MIPS_EV96100 is not set
+# CONFIG_MIPS_IVR is not set
+# CONFIG_LASAT is not set
+CONFIG_HP_LASERJET=y
+# CONFIG_MIPS_ITE8172 is not set
+# CONFIG_MIPS_ATLAS is not set
+# CONFIG_MIPS_MALTA is not set
+# CONFIG_MIPS_SEAD is not set
+# CONFIG_MOMENCO_OCELOT is not set
+# CONFIG_MOMENCO_OCELOT_G is not set
+# CONFIG_MOMENCO_OCELOT_C is not set
+# CONFIG_MOMENCO_JAGUAR_ATX is not set
+# CONFIG_PMC_YOSEMITE is not set
+# CONFIG_DDB5074 is not set
+# CONFIG_DDB5476 is not set
+# CONFIG_DDB5477 is not set
+# CONFIG_NEC_OSPREY is not set
+# CONFIG_SGI_IP22 is not set
+# CONFIG_SGI_IP32 is not set
+# CONFIG_SOC_AU1X00 is not set
+# CONFIG_SIBYTE_SB1xxx_SOC is not set
+# CONFIG_SNI_RM200_PCI is not set
+# CONFIG_TOSHIBA_RBTX4927 is not set
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_HAVE_DEC_LOCK=y
+CONFIG_DMA_NONCOHERENT=y
+CONFIG_CPU_LITTLE_ENDIAN=y
+CONFIG_IRQ_CPU=y
+CONFIG_MIPS_L1_CACHE_SHIFT=5
+# CONFIG_FB is not set
+
+#
+# CPU selection
+#
+# CONFIG_CPU_MIPS32 is not set
+# CONFIG_CPU_MIPS64 is not set
+# CONFIG_CPU_R3000 is not set
+# CONFIG_CPU_TX39XX is not set
+# CONFIG_CPU_VR41XX is not set
+# CONFIG_CPU_R4300 is not set
+# CONFIG_CPU_R4X00 is not set
+# CONFIG_CPU_TX49XX is not set
+CONFIG_CPU_R5000=y
+# CONFIG_CPU_R5432 is not set
+# CONFIG_CPU_R6000 is not set
+# CONFIG_CPU_NEVADA is not set
+# CONFIG_CPU_R8000 is not set
+# CONFIG_CPU_R10000 is not set
+# CONFIG_CPU_RM7000 is not set
+# CONFIG_CPU_RM9000 is not set
+# CONFIG_CPU_SB1 is not set
+CONFIG_PAGE_SIZE_4KB=y
+# CONFIG_PAGE_SIZE_16KB is not set
+# CONFIG_PAGE_SIZE_64KB is not set
+# CONFIG_64BIT_PHYS_ADDR is not set
+# CONFIG_CPU_ADVANCED is not set
+CONFIG_CPU_HAS_LLSC=y
+CONFIG_CPU_HAS_LLDSCD=y
+CONFIG_CPU_HAS_SYNC=y
+# CONFIG_PREEMPT is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+
+#
+# Bus options (PCI, PCMCIA, EISA, ISA, TC)
+#
+# CONFIG_PCI is not set
+CONFIG_MMU=y
+# CONFIG_HOTPLUG is not set
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_MISC is not set
+CONFIG_TRAD_SIGNALS=y
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+
+#
+# Memory Technology Devices (MTD)
+#
+CONFIG_MTD=y
+CONFIG_MTD_DEBUG=y
+CONFIG_MTD_DEBUG_VERBOSE=3
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_CONCAT is not set
+# CONFIG_MTD_REDBOOT_PARTS is not set
+# CONFIG_MTD_CMDLINE_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+CONFIG_MTD_CFI=y
+CONFIG_MTD_JEDECPROBE=y
+CONFIG_MTD_GEN_PROBE=y
+# CONFIG_MTD_CFI_ADV_OPTIONS is not set
+CONFIG_MTD_CFI_INTELEXT=y
+CONFIG_MTD_CFI_AMDSTD=y
+# CONFIG_MTD_CFI_STAA is not set
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+# CONFIG_MTD_OBSOLETE_CHIPS is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+CONFIG_MTD_PHYSMAP=y
+CONFIG_MTD_PHYSMAP_START=0x10040000
+CONFIG_MTD_PHYSMAP_LEN=0x00fc0000
+CONFIG_MTD_PHYSMAP_BUSWIDTH=4
+# CONFIG_MTD_CSTM_MIPS_IXX is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLKMTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+
+#
+# NAND Flash Device Drivers
+#
+CONFIG_MTD_NAND=y
+# CONFIG_MTD_NAND_VERIFY_WRITE is not set
+CONFIG_MTD_NAND_IDS=y
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+# CONFIG_BLK_DEV_LOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_RAM is not set
+# CONFIG_BLK_DEV_INITRD is not set
+# CONFIG_LBD is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+CONFIG_IDE=y
+CONFIG_BLK_DEV_IDE=y
+
+#
+# Please see Documentation/ide.txt for help/info on IDE drives
+#
+CONFIG_BLK_DEV_IDEDISK=y
+# CONFIG_IDEDISK_MULTI_MODE is not set
+# CONFIG_IDEDISK_STROKE is not set
+# CONFIG_BLK_DEV_IDECD is not set
+# CONFIG_BLK_DEV_IDETAPE is not set
+# CONFIG_BLK_DEV_IDEFLOPPY is not set
+# CONFIG_IDE_TASK_IOCTL is not set
+CONFIG_IDE_TASKFILE_IO=y
+
+#
+# IDE chipset support/bugfixes
+#
+CONFIG_IDE_GENERIC=y
+# CONFIG_BLK_DEV_IDEDMA is not set
+# CONFIG_IDEDMA_AUTO is not set
+# CONFIG_DMA_NONPCI is not set
+# CONFIG_BLK_DEV_HD is not set
+
+#
+# SCSI device support
+#
+# CONFIG_SCSI is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+
+#
+# IEEE 1394 (FireWire) support (EXPERIMENTAL)
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+
+#
+# Macintosh device drivers
+#
+
+#
+# Networking support
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+CONFIG_NETLINK_DEV=y
+CONFIG_UNIX=y
+CONFIG_NET_KEY=y
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+# CONFIG_IP_PNP_BOOTP is not set
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_ARPD is not set
+# CONFIG_INET_ECN is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_IPV6 is not set
+# CONFIG_DECNET is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_NETFILTER is not set
+CONFIG_XFRM=y
+# CONFIG_XFRM_USER is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+CONFIG_IPV6_SCTP__=y
+# CONFIG_IP_SCTP is not set
+# CONFIG_ATM is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_FASTROUTE is not set
+# CONFIG_NET_HW_FLOWCONTROL is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+# CONFIG_ETHERTAP is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+# CONFIG_MII is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+
+#
+# Ethernet (10000 Mbit)
+#
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+CONFIG_NET_RADIO=y
+
+#
+# Obsolete Wireless cards support (pre-802.11)
+#
+# CONFIG_STRIP is not set
+# CONFIG_ATMEL is not set
+
+#
+# Token Ring devices
+#
+# CONFIG_SHAPER is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+
+#
+# Amateur Radio support
+#
+# CONFIG_HAMRADIO is not set
+
+#
+# IrDA (infrared) support
+#
+# CONFIG_IRDA is not set
+
+#
+# Bluetooth support
+#
+# CONFIG_BT is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN_BOOL is not set
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+CONFIG_INPUT_MOUSEDEV_PSAUX=y
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+# CONFIG_INPUT_EVDEV is not set
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input I/O drivers
+#
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+CONFIG_SERIO=y
+# CONFIG_SERIO_I8042 is not set
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_CT82C710 is not set
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=4
+# CONFIG_SERIAL_8250_EXTENDED is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_UNIX98_PTYS is not set
+
+#
+# Mice
+#
+# CONFIG_BUSMOUSE is not set
+# CONFIG_QIC02_TAPE is not set
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_NVRAM is not set
+# CONFIG_RTC is not set
+# CONFIG_GEN_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_FTAPE is not set
+# CONFIG_AGP is not set
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+# CONFIG_MDA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_JBD is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_QUOTA is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_FAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+# CONFIG_DEVFS_FS is not set
+# CONFIG_TMPFS is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_JFFS_FS is not set
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_FS_DEBUG=3
+# CONFIG_JFFS2_FS_NAND is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
+# CONFIG_NFSD is not set
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+# CONFIG_EXPORTFS is not set
+CONFIG_SUNRPC=y
+# CONFIG_SUNRPC_GSS is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_INTERMEZZO_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+
+#
+# Native Language Support
+#
+# CONFIG_NLS is not set
+
+#
+# Kernel hacking
+#
+CONFIG_CROSSCOMPILE=y
+CONFIG_CMDLINE=""
+# CONFIG_DEBUG_KERNEL is not set
+
+#
+# Security options
+#
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
+# Library routines
+#
+CONFIG_CRC32=y
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
--- diff/arch/mips/configs/ip22_defconfig	1970-01-01 01:00:00.000000000 +0100
+++ source/arch/mips/configs/ip22_defconfig	2004-02-23 13:56:38.000000000 +0000
@@ -0,0 +1,861 @@
+#
+# Automatically generated make config: don't edit
+#
+CONFIG_MIPS=y
+# CONFIG_MIPS64 is not set
+# CONFIG_64BIT is not set
+CONFIG_MIPS32=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_CLEAN_COMPILE=y
+CONFIG_STANDALONE=y
+CONFIG_BROKEN_ON_SMP=y
+
+#
+# General setup
+#
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_EMBEDDED=y
+CONFIG_KALLSYMS=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+CONFIG_OBSOLETE_MODPARM=y
+CONFIG_MODVERSIONS=y
+CONFIG_KMOD=y
+
+#
+# Machine selection
+#
+# CONFIG_MACH_JAZZ is not set
+# CONFIG_BAGET_MIPS is not set
+# CONFIG_MACH_VR41XX is not set
+# CONFIG_TOSHIBA_JMR3927 is not set
+# CONFIG_MIPS_COBALT is not set
+# CONFIG_MACH_DECSTATION is not set
+# CONFIG_MIPS_EV64120 is not set
+# CONFIG_MIPS_EV96100 is not set
+# CONFIG_MIPS_IVR is not set
+# CONFIG_LASAT is not set
+# CONFIG_HP_LASERJET is not set
+# CONFIG_MIPS_ITE8172 is not set
+# CONFIG_MIPS_ATLAS is not set
+# CONFIG_MIPS_MALTA is not set
+# CONFIG_MIPS_SEAD is not set
+# CONFIG_MOMENCO_OCELOT is not set
+# CONFIG_MOMENCO_OCELOT_G is not set
+# CONFIG_MOMENCO_OCELOT_C is not set
+# CONFIG_MOMENCO_JAGUAR_ATX is not set
+# CONFIG_PMC_YOSEMITE is not set
+# CONFIG_DDB5074 is not set
+# CONFIG_DDB5476 is not set
+# CONFIG_DDB5477 is not set
+# CONFIG_NEC_OSPREY is not set
+CONFIG_SGI_IP22=y
+# CONFIG_SGI_IP32 is not set
+# CONFIG_SOC_AU1X00 is not set
+# CONFIG_SIBYTE_SB1xxx_SOC is not set
+# CONFIG_SNI_RM200_PCI is not set
+# CONFIG_TOSHIBA_RBTX4927 is not set
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_HAVE_DEC_LOCK=y
+CONFIG_ARC=y
+CONFIG_DMA_NONCOHERENT=y
+# CONFIG_CPU_LITTLE_ENDIAN is not set
+CONFIG_IRQ_CPU=y
+CONFIG_SWAP_IO_SPACE=y
+CONFIG_BOOT_ELF32=y
+CONFIG_MIPS_L1_CACHE_SHIFT=5
+CONFIG_ARC32=y
+# CONFIG_FB is not set
+CONFIG_ARC_CONSOLE=y
+CONFIG_ARC_PROMLIB=y
+CONFIG_BOARD_SCACHE=y
+
+#
+# CPU selection
+#
+# CONFIG_CPU_MIPS32 is not set
+# CONFIG_CPU_MIPS64 is not set
+# CONFIG_CPU_R3000 is not set
+# CONFIG_CPU_TX39XX is not set
+# CONFIG_CPU_VR41XX is not set
+# CONFIG_CPU_R4300 is not set
+# CONFIG_CPU_R4X00 is not set
+# CONFIG_CPU_TX49XX is not set
+CONFIG_CPU_R5000=y
+# CONFIG_CPU_R5432 is not set
+# CONFIG_CPU_R6000 is not set
+# CONFIG_CPU_NEVADA is not set
+# CONFIG_CPU_R8000 is not set
+# CONFIG_CPU_R10000 is not set
+# CONFIG_CPU_RM7000 is not set
+# CONFIG_CPU_RM9000 is not set
+# CONFIG_CPU_SB1 is not set
+CONFIG_PAGE_SIZE_4KB=y
+# CONFIG_PAGE_SIZE_16KB is not set
+# CONFIG_PAGE_SIZE_64KB is not set
+CONFIG_R5000_CPU_SCACHE=y
+# CONFIG_64BIT_PHYS_ADDR is not set
+# CONFIG_CPU_ADVANCED is not set
+CONFIG_CPU_HAS_LLSC=y
+CONFIG_CPU_HAS_LLDSCD=y
+CONFIG_CPU_HAS_SYNC=y
+# CONFIG_PREEMPT is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+
+#
+# Bus options (PCI, PCMCIA, EISA, ISA, TC)
+#
+# CONFIG_ISA is not set
+CONFIG_MMU=y
+# CONFIG_HOTPLUG is not set
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+CONFIG_BINFMT_MISC=m
+CONFIG_TRAD_SIGNALS=y
+CONFIG_BINFMT_IRIX=y
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+# CONFIG_BLK_DEV_LOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_RAM is not set
+# CONFIG_BLK_DEV_INITRD is not set
+# CONFIG_LBD is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+CONFIG_SCSI=y
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=y
+CONFIG_CHR_DEV_ST=y
+# CONFIG_CHR_DEV_OSST is not set
+CONFIG_BLK_DEV_SR=y
+# CONFIG_BLK_DEV_SR_VENDOR is not set
+# CONFIG_CHR_DEV_SG is not set
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+# CONFIG_SCSI_MULTI_LUN is not set
+# CONFIG_SCSI_REPORT_LUNS is not set
+CONFIG_SCSI_CONSTANTS=y
+# CONFIG_SCSI_LOGGING is not set
+
+#
+# SCSI low-level drivers
+#
+CONFIG_SGIWD93_SCSI=y
+# CONFIG_SCSI_AIC7XXX_OLD is not set
+# CONFIG_SCSI_SATA is not set
+# CONFIG_SCSI_EATA_PIO is not set
+# CONFIG_SCSI_DEBUG is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+# CONFIG_FUSION is not set
+
+#
+# IEEE 1394 (FireWire) support (EXPERIMENTAL)
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+
+#
+# Macintosh device drivers
+#
+
+#
+# Networking support
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+CONFIG_PACKET_MMAP=y
+CONFIG_NETLINK_DEV=y
+CONFIG_UNIX=y
+CONFIG_NET_KEY=y
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_PNP=y
+# CONFIG_IP_PNP_DHCP is not set
+CONFIG_IP_PNP_BOOTP=y
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_IP_MROUTE is not set
+# CONFIG_ARPD is not set
+CONFIG_INET_ECN=y
+# CONFIG_SYN_COOKIES is not set
+CONFIG_INET_AH=m
+CONFIG_INET_ESP=m
+CONFIG_INET_IPCOMP=m
+
+#
+# IP: Virtual Server Configuration
+#
+CONFIG_IP_VS=m
+# CONFIG_IP_VS_DEBUG is not set
+CONFIG_IP_VS_TAB_BITS=12
+
+#
+# IPVS transport protocol load balancing support
+#
+CONFIG_IP_VS_PROTO_TCP=y
+CONFIG_IP_VS_PROTO_UDP=y
+CONFIG_IP_VS_PROTO_ESP=y
+CONFIG_IP_VS_PROTO_AH=y
+
+#
+# IPVS scheduler
+#
+CONFIG_IP_VS_RR=m
+CONFIG_IP_VS_WRR=m
+CONFIG_IP_VS_LC=m
+CONFIG_IP_VS_WLC=m
+CONFIG_IP_VS_LBLC=m
+CONFIG_IP_VS_LBLCR=m
+CONFIG_IP_VS_DH=m
+CONFIG_IP_VS_SH=m
+CONFIG_IP_VS_SED=m
+CONFIG_IP_VS_NQ=m
+
+#
+# IPVS application helper
+#
+CONFIG_IP_VS_FTP=m
+CONFIG_IPV6=m
+CONFIG_IPV6_PRIVACY=y
+CONFIG_INET6_AH=m
+CONFIG_INET6_ESP=m
+CONFIG_INET6_IPCOMP=m
+CONFIG_IPV6_TUNNEL=m
+# CONFIG_DECNET is not set
+# CONFIG_BRIDGE is not set
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
+
+#
+# IP: Netfilter Configuration
+#
+CONFIG_IP_NF_CONNTRACK=m
+CONFIG_IP_NF_FTP=m
+CONFIG_IP_NF_IRC=m
+CONFIG_IP_NF_TFTP=m
+CONFIG_IP_NF_AMANDA=m
+CONFIG_IP_NF_QUEUE=m
+CONFIG_IP_NF_IPTABLES=m
+CONFIG_IP_NF_MATCH_LIMIT=m
+CONFIG_IP_NF_MATCH_IPRANGE=m
+CONFIG_IP_NF_MATCH_MAC=m
+CONFIG_IP_NF_MATCH_PKTTYPE=m
+CONFIG_IP_NF_MATCH_MARK=m
+CONFIG_IP_NF_MATCH_MULTIPORT=m
+CONFIG_IP_NF_MATCH_TOS=m
+CONFIG_IP_NF_MATCH_RECENT=m
+CONFIG_IP_NF_MATCH_ECN=m
+CONFIG_IP_NF_MATCH_DSCP=m
+CONFIG_IP_NF_MATCH_AH_ESP=m
+CONFIG_IP_NF_MATCH_LENGTH=m
+CONFIG_IP_NF_MATCH_TTL=m
+CONFIG_IP_NF_MATCH_TCPMSS=m
+CONFIG_IP_NF_MATCH_HELPER=m
+CONFIG_IP_NF_MATCH_STATE=m
+CONFIG_IP_NF_MATCH_CONNTRACK=m
+CONFIG_IP_NF_MATCH_OWNER=m
+CONFIG_IP_NF_FILTER=m
+CONFIG_IP_NF_TARGET_REJECT=m
+CONFIG_IP_NF_NAT=m
+CONFIG_IP_NF_NAT_NEEDED=y
+CONFIG_IP_NF_TARGET_MASQUERADE=m
+CONFIG_IP_NF_TARGET_REDIRECT=m
+CONFIG_IP_NF_TARGET_NETMAP=m
+CONFIG_IP_NF_TARGET_SAME=m
+CONFIG_IP_NF_NAT_LOCAL=y
+CONFIG_IP_NF_NAT_SNMP_BASIC=m
+CONFIG_IP_NF_NAT_IRC=m
+CONFIG_IP_NF_NAT_FTP=m
+CONFIG_IP_NF_NAT_TFTP=m
+CONFIG_IP_NF_NAT_AMANDA=m
+CONFIG_IP_NF_MANGLE=m
+CONFIG_IP_NF_TARGET_TOS=m
+CONFIG_IP_NF_TARGET_ECN=m
+CONFIG_IP_NF_TARGET_DSCP=m
+CONFIG_IP_NF_TARGET_MARK=m
+CONFIG_IP_NF_TARGET_CLASSIFY=m
+CONFIG_IP_NF_TARGET_LOG=m
+CONFIG_IP_NF_TARGET_ULOG=m
+CONFIG_IP_NF_TARGET_TCPMSS=m
+CONFIG_IP_NF_ARPTABLES=m
+CONFIG_IP_NF_ARPFILTER=m
+CONFIG_IP_NF_ARP_MANGLE=m
+CONFIG_IP_NF_COMPAT_IPCHAINS=m
+CONFIG_IP_NF_COMPAT_IPFWADM=m
+
+#
+# IPv6: Netfilter Configuration
+#
+CONFIG_IP6_NF_QUEUE=m
+CONFIG_IP6_NF_IPTABLES=m
+CONFIG_IP6_NF_MATCH_LIMIT=m
+CONFIG_IP6_NF_MATCH_MAC=m
+CONFIG_IP6_NF_MATCH_RT=m
+CONFIG_IP6_NF_MATCH_OPTS=m
+CONFIG_IP6_NF_MATCH_FRAG=m
+CONFIG_IP6_NF_MATCH_HL=m
+CONFIG_IP6_NF_MATCH_MULTIPORT=m
+CONFIG_IP6_NF_MATCH_OWNER=m
+CONFIG_IP6_NF_MATCH_MARK=m
+CONFIG_IP6_NF_MATCH_IPV6HEADER=m
+CONFIG_IP6_NF_MATCH_AHESP=m
+CONFIG_IP6_NF_MATCH_LENGTH=m
+CONFIG_IP6_NF_MATCH_EUI64=m
+CONFIG_IP6_NF_FILTER=m
+CONFIG_IP6_NF_TARGET_LOG=m
+CONFIG_IP6_NF_MANGLE=m
+CONFIG_IP6_NF_TARGET_MARK=m
+CONFIG_XFRM=y
+CONFIG_XFRM_USER=m
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+CONFIG_IPV6_SCTP__=m
+CONFIG_IP_SCTP=m
+# CONFIG_SCTP_DBG_MSG is not set
+# CONFIG_SCTP_DBG_OBJCNT is not set
+# CONFIG_SCTP_HMAC_NONE is not set
+# CONFIG_SCTP_HMAC_SHA1 is not set
+CONFIG_SCTP_HMAC_MD5=y
+# CONFIG_ATM is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+CONFIG_NET_DIVERT=y
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_FASTROUTE is not set
+# CONFIG_NET_HW_FLOWCONTROL is not set
+
+#
+# QoS and/or fair queueing
+#
+CONFIG_NET_SCHED=y
+CONFIG_NET_SCH_CBQ=m
+CONFIG_NET_SCH_HTB=m
+CONFIG_NET_SCH_HFSC=m
+CONFIG_NET_SCH_CSZ=m
+CONFIG_NET_SCH_PRIO=m
+CONFIG_NET_SCH_RED=m
+CONFIG_NET_SCH_SFQ=m
+CONFIG_NET_SCH_TEQL=m
+CONFIG_NET_SCH_TBF=m
+CONFIG_NET_SCH_GRED=m
+CONFIG_NET_SCH_DSMARK=m
+CONFIG_NET_SCH_INGRESS=m
+CONFIG_NET_QOS=y
+CONFIG_NET_ESTIMATOR=y
+CONFIG_NET_CLS=y
+CONFIG_NET_CLS_TCINDEX=m
+CONFIG_NET_CLS_ROUTE4=m
+CONFIG_NET_CLS_ROUTE=y
+CONFIG_NET_CLS_FW=m
+CONFIG_NET_CLS_U32=m
+CONFIG_NET_CLS_RSVP=m
+CONFIG_NET_CLS_RSVP6=m
+CONFIG_NET_CLS_POLICE=y
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+CONFIG_NETDEVICES=y
+CONFIG_DUMMY=m
+CONFIG_BONDING=m
+CONFIG_EQUALIZER=m
+CONFIG_TUN=m
+CONFIG_ETHERTAP=m
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+# CONFIG_MII is not set
+CONFIG_SGISEEQ=y
+
+#
+# Ethernet (1000 Mbit)
+#
+
+#
+# Ethernet (10000 Mbit)
+#
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Token Ring devices
+#
+# CONFIG_SHAPER is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+
+#
+# Amateur Radio support
+#
+# CONFIG_HAMRADIO is not set
+
+#
+# IrDA (infrared) support
+#
+# CONFIG_IRDA is not set
+
+#
+# Bluetooth support
+#
+# CONFIG_BT is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN_BOOL is not set
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+CONFIG_INPUT_MOUSEDEV_PSAUX=y
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+# CONFIG_INPUT_EVDEV is not set
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input I/O drivers
+#
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+CONFIG_SERIO=y
+CONFIG_SERIO_I8042=y
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_CT82C710 is not set
+
+#
+# Input Device Drivers
+#
+CONFIG_INPUT_KEYBOARD=y
+CONFIG_KEYBOARD_ATKBD=y
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_XTKBD is not set
+# CONFIG_KEYBOARD_NEWTON is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_IP22_ZILOG=m
+CONFIG_SERIAL_CORE=m
+CONFIG_UNIX98_PTYS=y
+CONFIG_UNIX98_PTY_COUNT=256
+
+#
+# Mice
+#
+# CONFIG_BUSMOUSE is not set
+# CONFIG_QIC02_TAPE is not set
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+CONFIG_WATCHDOG=y
+# CONFIG_WATCHDOG_NOWAYOUT is not set
+
+#
+# Watchdog Device Drivers
+#
+# CONFIG_SOFT_WATCHDOG is not set
+CONFIG_INDYDOG=m
+# CONFIG_NVRAM is not set
+# CONFIG_RTC is not set
+# CONFIG_GEN_RTC is not set
+CONFIG_SGI_DS1286=y
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_FTAPE is not set
+# CONFIG_AGP is not set
+# CONFIG_DRM is not set
+CONFIG_RAW_DRIVER=m
+CONFIG_MAX_RAW_DEVS=256
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+# CONFIG_MDA_CONSOLE is not set
+CONFIG_SGI_NEWPORT_CONSOLE=y
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_FONT_8x16=y
+
+#
+# Logo configuration
+#
+CONFIG_LOGO=y
+# CONFIG_LOGO_LINUX_MONO is not set
+# CONFIG_LOGO_LINUX_VGA16 is not set
+# CONFIG_LOGO_LINUX_CLUT224 is not set
+CONFIG_LOGO_SGI_CLUT224=y
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=m
+# CONFIG_EXT2_FS_XATTR is not set
+CONFIG_EXT3_FS=y
+CONFIG_EXT3_FS_XATTR=y
+CONFIG_EXT3_FS_POSIX_ACL=y
+CONFIG_EXT3_FS_SECURITY=y
+CONFIG_JBD=y
+# CONFIG_JBD_DEBUG is not set
+CONFIG_FS_MBCACHE=y
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+CONFIG_FS_POSIX_ACL=y
+CONFIG_XFS_FS=m
+# CONFIG_XFS_RT is not set
+CONFIG_XFS_QUOTA=y
+CONFIG_XFS_SECURITY=y
+# CONFIG_XFS_POSIX_ACL is not set
+CONFIG_MINIX_FS=m
+# CONFIG_ROMFS_FS is not set
+CONFIG_QUOTA=y
+# CONFIG_QFMT_V1 is not set
+CONFIG_QFMT_V2=m
+CONFIG_QUOTACTL=y
+CONFIG_AUTOFS_FS=m
+CONFIG_AUTOFS4_FS=m
+
+#
+# CD-ROM/DVD Filesystems
+#
+CONFIG_ISO9660_FS=m
+CONFIG_JOLIET=y
+CONFIG_ZISOFS=y
+CONFIG_ZISOFS_FS=m
+CONFIG_UDF_FS=m
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=m
+CONFIG_MSDOS_FS=m
+CONFIG_VFAT_FS=m
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+# CONFIG_DEVFS_FS is not set
+CONFIG_DEVPTS_FS=y
+CONFIG_DEVPTS_FS_XATTR=y
+CONFIG_DEVPTS_FS_SECURITY=y
+# CONFIG_TMPFS is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+CONFIG_EFS_FS=m
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+CONFIG_UFS_FS=m
+# CONFIG_UFS_FS_WRITE is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=m
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
+CONFIG_NFSD=m
+CONFIG_NFSD_V3=y
+# CONFIG_NFSD_V4 is not set
+CONFIG_NFSD_TCP=y
+CONFIG_LOCKD=m
+CONFIG_LOCKD_V4=y
+CONFIG_EXPORTFS=m
+CONFIG_SUNRPC=m
+# CONFIG_SUNRPC_GSS is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_INTERMEZZO_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+# CONFIG_MAC_PARTITION is not set
+CONFIG_MSDOS_PARTITION=y
+# CONFIG_BSD_DISKLABEL is not set
+# CONFIG_MINIX_SUBPARTITION is not set
+# CONFIG_SOLARIS_X86_PARTITION is not set
+# CONFIG_UNIXWARE_DISKLABEL is not set
+# CONFIG_LDM_PARTITION is not set
+# CONFIG_NEC98_PARTITION is not set
+CONFIG_SGI_PARTITION=y
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+# CONFIG_EFI_PARTITION is not set
+
+#
+# Native Language Support
+#
+CONFIG_NLS=m
+CONFIG_NLS_DEFAULT="iso8859-1"
+CONFIG_NLS_CODEPAGE_437=m
+CONFIG_NLS_CODEPAGE_737=m
+CONFIG_NLS_CODEPAGE_775=m
+CONFIG_NLS_CODEPAGE_850=m
+CONFIG_NLS_CODEPAGE_852=m
+CONFIG_NLS_CODEPAGE_855=m
+CONFIG_NLS_CODEPAGE_857=m
+CONFIG_NLS_CODEPAGE_860=m
+CONFIG_NLS_CODEPAGE_861=m
+CONFIG_NLS_CODEPAGE_862=m
+CONFIG_NLS_CODEPAGE_863=m
+CONFIG_NLS_CODEPAGE_864=m
+CONFIG_NLS_CODEPAGE_865=m
+CONFIG_NLS_CODEPAGE_866=m
+CONFIG_NLS_CODEPAGE_869=m
+CONFIG_NLS_CODEPAGE_936=m
+CONFIG_NLS_CODEPAGE_950=m
+CONFIG_NLS_CODEPAGE_932=m
+CONFIG_NLS_CODEPAGE_949=m
+CONFIG_NLS_CODEPAGE_874=m
+CONFIG_NLS_ISO8859_8=m
+CONFIG_NLS_CODEPAGE_1250=m
+CONFIG_NLS_CODEPAGE_1251=m
+CONFIG_NLS_ISO8859_1=m
+CONFIG_NLS_ISO8859_2=m
+CONFIG_NLS_ISO8859_3=m
+CONFIG_NLS_ISO8859_4=m
+CONFIG_NLS_ISO8859_5=m
+CONFIG_NLS_ISO8859_6=m
+CONFIG_NLS_ISO8859_7=m
+CONFIG_NLS_ISO8859_9=m
+CONFIG_NLS_ISO8859_13=m
+CONFIG_NLS_ISO8859_14=m
+CONFIG_NLS_ISO8859_15=m
+CONFIG_NLS_KOI8_R=m
+CONFIG_NLS_KOI8_U=m
+CONFIG_NLS_UTF8=m
+
+#
+# Kernel hacking
+#
+CONFIG_CROSSCOMPILE=y
+CONFIG_CMDLINE=""
+# CONFIG_DEBUG_KERNEL is not set
+
+#
+# Security options
+#
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+CONFIG_CRYPTO=y
+CONFIG_CRYPTO_HMAC=y
+CONFIG_CRYPTO_NULL=y
+CONFIG_CRYPTO_MD4=y
+CONFIG_CRYPTO_MD5=y
+CONFIG_CRYPTO_SHA1=y
+CONFIG_CRYPTO_SHA256=y
+CONFIG_CRYPTO_SHA512=y
+CONFIG_CRYPTO_DES=y
+CONFIG_CRYPTO_BLOWFISH=y
+CONFIG_CRYPTO_TWOFISH=y
+CONFIG_CRYPTO_SERPENT=y
+CONFIG_CRYPTO_AES=y
+CONFIG_CRYPTO_CAST5=m
+CONFIG_CRYPTO_CAST6=m
+CONFIG_CRYPTO_DEFLATE=y
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Library routines
+#
+# CONFIG_CRC32 is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
--- diff/arch/mips/configs/ip27_defconfig	1970-01-01 01:00:00.000000000 +0100
+++ source/arch/mips/configs/ip27_defconfig	2004-02-23 13:56:38.000000000 +0000
@@ -0,0 +1,665 @@
+#
+# Automatically generated make config: don't edit
+#
+CONFIG_MIPS=y
+CONFIG_MIPS64=y
+CONFIG_64BIT=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_CLEAN_COMPILE=y
+CONFIG_STANDALONE=y
+CONFIG_BROKEN_ON_SMP=y
+
+#
+# General setup
+#
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_EMBEDDED=y
+CONFIG_KALLSYMS=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+
+#
+# Loadable module support
+#
+# CONFIG_MODULES is not set
+
+#
+# Machine selection
+#
+# CONFIG_MACH_JAZZ is not set
+# CONFIG_MACH_VR41XX is not set
+# CONFIG_MIPS_COBALT is not set
+# CONFIG_MACH_DECSTATION is not set
+# CONFIG_MIPS_EV64120 is not set
+# CONFIG_MIPS_EV96100 is not set
+# CONFIG_MIPS_IVR is not set
+# CONFIG_LASAT is not set
+# CONFIG_HP_LASERJET is not set
+# CONFIG_MIPS_ITE8172 is not set
+# CONFIG_MIPS_ATLAS is not set
+# CONFIG_MIPS_MALTA is not set
+# CONFIG_MIPS_SEAD is not set
+# CONFIG_MOMENCO_OCELOT is not set
+# CONFIG_MOMENCO_OCELOT_G is not set
+# CONFIG_MOMENCO_OCELOT_C is not set
+# CONFIG_MOMENCO_JAGUAR_ATX is not set
+# CONFIG_PMC_YOSEMITE is not set
+# CONFIG_DDB5074 is not set
+# CONFIG_DDB5476 is not set
+# CONFIG_DDB5477 is not set
+# CONFIG_NEC_OSPREY is not set
+# CONFIG_SGI_IP22 is not set
+CONFIG_SGI_IP27=y
+# CONFIG_SGI_SN0_N_MODE is not set
+CONFIG_DISCONTIGMEM=y
+# CONFIG_NUMA is not set
+# CONFIG_MAPPED_KERNEL is not set
+# CONFIG_REPLICATE_KTEXT is not set
+# CONFIG_REPLICATE_EXHANDLERS is not set
+# CONFIG_SGI_IP32 is not set
+# CONFIG_SIBYTE_SB1xxx_SOC is not set
+# CONFIG_SNI_RM200_PCI is not set
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_HAVE_DEC_LOCK=y
+CONFIG_ARC=y
+CONFIG_DMA_IP27=y
+# CONFIG_CPU_LITTLE_ENDIAN is not set
+CONFIG_MIPS_L1_CACHE_SHIFT=7
+# CONFIG_FB is not set
+CONFIG_ARC64=y
+CONFIG_BOOT_ELF64=y
+CONFIG_QL_ISP_A64=y
+
+#
+# CPU selection
+#
+# CONFIG_CPU_MIPS32 is not set
+# CONFIG_CPU_MIPS64 is not set
+# CONFIG_CPU_R3000 is not set
+# CONFIG_CPU_TX39XX is not set
+# CONFIG_CPU_VR41XX is not set
+# CONFIG_CPU_R4300 is not set
+# CONFIG_CPU_R4X00 is not set
+# CONFIG_CPU_TX49XX is not set
+# CONFIG_CPU_R5000 is not set
+# CONFIG_CPU_R5432 is not set
+# CONFIG_CPU_R6000 is not set
+# CONFIG_CPU_NEVADA is not set
+# CONFIG_CPU_R8000 is not set
+CONFIG_CPU_R10000=y
+# CONFIG_CPU_RM7000 is not set
+# CONFIG_CPU_RM9000 is not set
+# CONFIG_CPU_SB1 is not set
+CONFIG_PAGE_SIZE_4KB=y
+# CONFIG_PAGE_SIZE_16KB is not set
+# CONFIG_PAGE_SIZE_64KB is not set
+CONFIG_CPU_HAS_LLSC=y
+CONFIG_CPU_HAS_LLDSCD=y
+CONFIG_CPU_HAS_SYNC=y
+# CONFIG_SMP is not set
+# CONFIG_PREEMPT is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_MIPS_INSANE_LARGE is not set
+
+#
+# Bus options (PCI, PCMCIA, EISA, ISA, TC)
+#
+CONFIG_PCI=y
+CONFIG_PCI_LEGACY_PROC=y
+CONFIG_PCI_NAMES=y
+CONFIG_MMU=y
+# CONFIG_HOTPLUG is not set
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_MISC is not set
+CONFIG_MIPS32_COMPAT=y
+CONFIG_COMPAT=y
+CONFIG_MIPS32_O32=y
+# CONFIG_MIPS32_N32 is not set
+CONFIG_BINFMT_ELF32=y
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_UMEM is not set
+# CONFIG_BLK_DEV_LOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_RAM is not set
+# CONFIG_BLK_DEV_INITRD is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+CONFIG_SCSI=y
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=y
+CONFIG_CHR_DEV_ST=y
+# CONFIG_CHR_DEV_OSST is not set
+# CONFIG_BLK_DEV_SR is not set
+# CONFIG_CHR_DEV_SG is not set
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+# CONFIG_SCSI_MULTI_LUN is not set
+# CONFIG_SCSI_REPORT_LUNS is not set
+CONFIG_SCSI_CONSTANTS=y
+CONFIG_SCSI_LOGGING=y
+
+#
+# SCSI low-level drivers
+#
+# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
+# CONFIG_SCSI_ACARD is not set
+# CONFIG_SCSI_AACRAID is not set
+# CONFIG_SCSI_AIC7XXX is not set
+# CONFIG_SCSI_AIC7XXX_OLD is not set
+# CONFIG_SCSI_AIC79XX is not set
+# CONFIG_SCSI_ADVANSYS is not set
+# CONFIG_SCSI_MEGARAID is not set
+# CONFIG_SCSI_SATA is not set
+# CONFIG_SCSI_BUSLOGIC is not set
+# CONFIG_SCSI_CPQFCTS is not set
+# CONFIG_SCSI_DMX3191D is not set
+# CONFIG_SCSI_EATA is not set
+# CONFIG_SCSI_EATA_PIO is not set
+# CONFIG_SCSI_FUTURE_DOMAIN is not set
+# CONFIG_SCSI_GDTH is not set
+# CONFIG_SCSI_IPS is not set
+# CONFIG_SCSI_INIA100 is not set
+# CONFIG_SCSI_SYM53C8XX_2 is not set
+CONFIG_SCSI_QLOGIC_ISP=y
+# CONFIG_SCSI_QLOGIC_FC is not set
+# CONFIG_SCSI_QLOGIC_1280 is not set
+CONFIG_SCSI_QLA2XXX=y
+# CONFIG_SCSI_QLA21XX is not set
+# CONFIG_SCSI_QLA22XX is not set
+# CONFIG_SCSI_QLA2300 is not set
+# CONFIG_SCSI_QLA2322 is not set
+# CONFIG_SCSI_QLA6312 is not set
+# CONFIG_SCSI_QLA6322 is not set
+# CONFIG_SCSI_DC395x is not set
+# CONFIG_SCSI_DC390T is not set
+# CONFIG_SCSI_DEBUG is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+# CONFIG_FUSION is not set
+
+#
+# IEEE 1394 (FireWire) support (EXPERIMENTAL)
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+
+#
+# Macintosh device drivers
+#
+
+#
+# Networking support
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+CONFIG_PACKET_MMAP=y
+CONFIG_NETLINK_DEV=y
+CONFIG_UNIX=y
+CONFIG_NET_KEY=y
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_PNP=y
+# CONFIG_IP_PNP_DHCP is not set
+# CONFIG_IP_PNP_BOOTP is not set
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_IP_MROUTE is not set
+# CONFIG_ARPD is not set
+# CONFIG_INET_ECN is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_IPV6 is not set
+# CONFIG_DECNET is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_NETFILTER is not set
+CONFIG_XFRM=y
+# CONFIG_XFRM_USER is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+CONFIG_IPV6_SCTP__=y
+# CONFIG_IP_SCTP is not set
+# CONFIG_ATM is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_FASTROUTE is not set
+# CONFIG_NET_HW_FLOWCONTROL is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+CONFIG_NETDEVICES=y
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+# CONFIG_ETHERTAP is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+# CONFIG_MII is not set
+CONFIG_SGI_IOC3_ETH=y
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_SUNGEM is not set
+# CONFIG_NET_VENDOR_3COM is not set
+
+#
+# Tulip family network device support
+#
+# CONFIG_NET_TULIP is not set
+# CONFIG_HP100 is not set
+# CONFIG_NET_PCI is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+# CONFIG_E1000 is not set
+# CONFIG_NS83820 is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+# CONFIG_R8169 is not set
+# CONFIG_SIS190 is not set
+# CONFIG_SK98LIN is not set
+# CONFIG_TIGON3 is not set
+
+#
+# Ethernet (10000 Mbit)
+#
+# CONFIG_IXGB is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Token Ring devices
+#
+# CONFIG_TR is not set
+# CONFIG_NET_FC is not set
+# CONFIG_SHAPER is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+
+#
+# Amateur Radio support
+#
+# CONFIG_HAMRADIO is not set
+
+#
+# IrDA (infrared) support
+#
+# CONFIG_IRDA is not set
+
+#
+# Bluetooth support
+#
+# CONFIG_BT is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN_BOOL is not set
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+# CONFIG_INPUT is not set
+
+#
+# Userland interfaces
+#
+
+#
+# Input I/O drivers
+#
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+CONFIG_SERIO=y
+# CONFIG_SERIO_I8042 is not set
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_CT82C710 is not set
+# CONFIG_SERIO_PCIPS2 is not set
+
+#
+# Input Device Drivers
+#
+
+#
+# Character devices
+#
+# CONFIG_VT is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=4
+CONFIG_SERIAL_8250_EXTENDED=y
+CONFIG_SERIAL_8250_MANY_PORTS=y
+CONFIG_SERIAL_8250_SHARE_IRQ=y
+# CONFIG_SERIAL_8250_DETECT_IRQ is not set
+# CONFIG_SERIAL_8250_MULTIPORT is not set
+# CONFIG_SERIAL_8250_RSA is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+CONFIG_UNIX98_PTY_COUNT=256
+
+#
+# Mice
+#
+# CONFIG_BUSMOUSE is not set
+# CONFIG_QIC02_TAPE is not set
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_NVRAM is not set
+# CONFIG_RTC is not set
+# CONFIG_GEN_RTC is not set
+CONFIG_SGI_IP27_RTC=y
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_FTAPE is not set
+# CONFIG_AGP is not set
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+# CONFIG_USB is not set
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+CONFIG_EXT2_FS_XATTR=y
+CONFIG_EXT2_FS_POSIX_ACL=y
+CONFIG_EXT2_FS_SECURITY=y
+CONFIG_EXT3_FS=y
+CONFIG_EXT3_FS_XATTR=y
+CONFIG_EXT3_FS_POSIX_ACL=y
+CONFIG_EXT3_FS_SECURITY=y
+CONFIG_JBD=y
+CONFIG_JBD_DEBUG=y
+CONFIG_FS_MBCACHE=y
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+CONFIG_FS_POSIX_ACL=y
+# CONFIG_XFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_QUOTA is not set
+CONFIG_AUTOFS_FS=y
+# CONFIG_AUTOFS4_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_FAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+# CONFIG_DEVFS_FS is not set
+CONFIG_DEVPTS_FS=y
+CONFIG_DEVPTS_FS_XATTR=y
+CONFIG_DEVPTS_FS_SECURITY=y
+# CONFIG_TMPFS is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
+# CONFIG_NFSD is not set
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+# CONFIG_EXPORTFS is not set
+CONFIG_SUNRPC=y
+# CONFIG_SUNRPC_GSS is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_INTERMEZZO_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+# CONFIG_MAC_PARTITION is not set
+CONFIG_MSDOS_PARTITION=y
+# CONFIG_BSD_DISKLABEL is not set
+# CONFIG_MINIX_SUBPARTITION is not set
+# CONFIG_SOLARIS_X86_PARTITION is not set
+# CONFIG_UNIXWARE_DISKLABEL is not set
+# CONFIG_LDM_PARTITION is not set
+# CONFIG_NEC98_PARTITION is not set
+CONFIG_SGI_PARTITION=y
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+# CONFIG_EFI_PARTITION is not set
+
+#
+# Native Language Support
+#
+# CONFIG_NLS is not set
+
+#
+# Kernel hacking
+#
+CONFIG_CROSSCOMPILE=y
+CONFIG_CMDLINE=""
+# CONFIG_DEBUG_KERNEL is not set
+
+#
+# Security options
+#
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
+# Library routines
+#
+CONFIG_CRC32=y
--- diff/arch/mips/configs/ip32_defconfig	1970-01-01 01:00:00.000000000 +0100
+++ source/arch/mips/configs/ip32_defconfig	2004-02-23 13:56:38.000000000 +0000
@@ -0,0 +1,671 @@
+#
+# Automatically generated make config: don't edit
+#
+CONFIG_MIPS=y
+CONFIG_MIPS64=y
+CONFIG_64BIT=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_CLEAN_COMPILE=y
+CONFIG_STANDALONE=y
+CONFIG_BROKEN_ON_SMP=y
+
+#
+# General setup
+#
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+CONFIG_BSD_PROCESS_ACCT=y
+CONFIG_SYSCTL=y
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_IKCONFIG is not set
+CONFIG_EMBEDDED=y
+CONFIG_KALLSYMS=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+
+#
+# Loadable module support
+#
+# CONFIG_MODULES is not set
+
+#
+# Machine selection
+#
+# CONFIG_MACH_JAZZ is not set
+# CONFIG_MACH_VR41XX is not set
+# CONFIG_MIPS_COBALT is not set
+# CONFIG_MACH_DECSTATION is not set
+# CONFIG_MIPS_EV64120 is not set
+# CONFIG_MIPS_EV96100 is not set
+# CONFIG_MIPS_IVR is not set
+# CONFIG_LASAT is not set
+# CONFIG_HP_LASERJET is not set
+# CONFIG_MIPS_ITE8172 is not set
+# CONFIG_MIPS_ATLAS is not set
+# CONFIG_MIPS_MALTA is not set
+# CONFIG_MIPS_SEAD is not set
+# CONFIG_MOMENCO_OCELOT is not set
+# CONFIG_MOMENCO_OCELOT_G is not set
+# CONFIG_MOMENCO_OCELOT_C is not set
+# CONFIG_MOMENCO_JAGUAR_ATX is not set
+# CONFIG_PMC_YOSEMITE is not set
+# CONFIG_DDB5074 is not set
+# CONFIG_DDB5476 is not set
+# CONFIG_DDB5477 is not set
+# CONFIG_NEC_OSPREY is not set
+# CONFIG_SGI_IP22 is not set
+# CONFIG_SGI_IP27 is not set
+CONFIG_SGI_IP32=y
+# CONFIG_SIBYTE_SB1xxx_SOC is not set
+# CONFIG_SNI_RM200_PCI is not set
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_HAVE_DEC_LOCK=y
+CONFIG_ARC=y
+CONFIG_DMA_NONCOHERENT=y
+# CONFIG_CPU_LITTLE_ENDIAN is not set
+CONFIG_BOOT_ELF32=y
+CONFIG_MIPS_L1_CACHE_SHIFT=5
+CONFIG_ARC32=y
+# CONFIG_FB is not set
+CONFIG_ARC_MEMORY=y
+CONFIG_ARC_PROMLIB=y
+CONFIG_BOARD_SCACHE=y
+
+#
+# CPU selection
+#
+# CONFIG_CPU_MIPS32 is not set
+# CONFIG_CPU_MIPS64 is not set
+# CONFIG_CPU_R3000 is not set
+# CONFIG_CPU_TX39XX is not set
+# CONFIG_CPU_VR41XX is not set
+# CONFIG_CPU_R4300 is not set
+# CONFIG_CPU_R4X00 is not set
+# CONFIG_CPU_TX49XX is not set
+CONFIG_CPU_R5000=y
+# CONFIG_CPU_R5432 is not set
+# CONFIG_CPU_R6000 is not set
+# CONFIG_CPU_NEVADA is not set
+# CONFIG_CPU_R8000 is not set
+# CONFIG_CPU_R10000 is not set
+# CONFIG_CPU_RM7000 is not set
+# CONFIG_CPU_RM9000 is not set
+# CONFIG_CPU_SB1 is not set
+CONFIG_PAGE_SIZE_4KB=y
+# CONFIG_PAGE_SIZE_16KB is not set
+# CONFIG_PAGE_SIZE_64KB is not set
+CONFIG_R5000_CPU_SCACHE=y
+CONFIG_CPU_HAS_LLSC=y
+CONFIG_CPU_HAS_LLDSCD=y
+CONFIG_CPU_HAS_SYNC=y
+# CONFIG_PREEMPT is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+
+#
+# Bus options (PCI, PCMCIA, EISA, ISA, TC)
+#
+CONFIG_PCI=y
+CONFIG_PCI_LEGACY_PROC=y
+CONFIG_PCI_NAMES=y
+CONFIG_MMU=y
+# CONFIG_HOTPLUG is not set
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+CONFIG_BINFMT_MISC=y
+CONFIG_MIPS32_COMPAT=y
+CONFIG_COMPAT=y
+CONFIG_MIPS32_O32=y
+# CONFIG_MIPS32_N32 is not set
+CONFIG_BINFMT_ELF32=y
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_UMEM is not set
+CONFIG_BLK_DEV_LOOP=y
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_RAM is not set
+# CONFIG_BLK_DEV_INITRD is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+CONFIG_SCSI=y
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=y
+CONFIG_CHR_DEV_ST=y
+CONFIG_CHR_DEV_OSST=y
+CONFIG_BLK_DEV_SR=y
+CONFIG_BLK_DEV_SR_VENDOR=y
+CONFIG_CHR_DEV_SG=y
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+CONFIG_SCSI_MULTI_LUN=y
+# CONFIG_SCSI_REPORT_LUNS is not set
+CONFIG_SCSI_CONSTANTS=y
+CONFIG_SCSI_LOGGING=y
+
+#
+# SCSI low-level drivers
+#
+# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
+# CONFIG_SCSI_ACARD is not set
+# CONFIG_SCSI_AACRAID is not set
+CONFIG_SCSI_AIC7XXX=y
+CONFIG_AIC7XXX_CMDS_PER_DEVICE=8
+CONFIG_AIC7XXX_RESET_DELAY_MS=15000
+# CONFIG_AIC7XXX_BUILD_FIRMWARE is not set
+CONFIG_AIC7XXX_DEBUG_ENABLE=y
+CONFIG_AIC7XXX_DEBUG_MASK=0
+CONFIG_AIC7XXX_REG_PRETTY_PRINT=y
+# CONFIG_SCSI_AIC7XXX_OLD is not set
+# CONFIG_SCSI_AIC79XX is not set
+# CONFIG_SCSI_ADVANSYS is not set
+# CONFIG_SCSI_MEGARAID is not set
+# CONFIG_SCSI_SATA is not set
+# CONFIG_SCSI_BUSLOGIC is not set
+# CONFIG_SCSI_CPQFCTS is not set
+# CONFIG_SCSI_DMX3191D is not set
+# CONFIG_SCSI_EATA is not set
+# CONFIG_SCSI_EATA_PIO is not set
+# CONFIG_SCSI_FUTURE_DOMAIN is not set
+# CONFIG_SCSI_GDTH is not set
+# CONFIG_SCSI_IPS is not set
+# CONFIG_SCSI_INIA100 is not set
+# CONFIG_SCSI_SYM53C8XX_2 is not set
+# CONFIG_SCSI_QLOGIC_ISP is not set
+# CONFIG_SCSI_QLOGIC_FC is not set
+# CONFIG_SCSI_QLOGIC_1280 is not set
+CONFIG_SCSI_QLA2XXX=y
+# CONFIG_SCSI_QLA21XX is not set
+# CONFIG_SCSI_QLA22XX is not set
+# CONFIG_SCSI_QLA2300 is not set
+# CONFIG_SCSI_QLA2322 is not set
+# CONFIG_SCSI_QLA6312 is not set
+# CONFIG_SCSI_QLA6322 is not set
+# CONFIG_SCSI_DC395x is not set
+# CONFIG_SCSI_DC390T is not set
+# CONFIG_SCSI_DEBUG is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+# CONFIG_FUSION is not set
+
+#
+# IEEE 1394 (FireWire) support (EXPERIMENTAL)
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+
+#
+# Macintosh device drivers
+#
+
+#
+# Networking support
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+CONFIG_PACKET_MMAP=y
+CONFIG_NETLINK_DEV=y
+CONFIG_UNIX=y
+CONFIG_NET_KEY=y
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_PNP=y
+# CONFIG_IP_PNP_DHCP is not set
+CONFIG_IP_PNP_BOOTP=y
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_ARPD is not set
+# CONFIG_INET_ECN is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_IPV6 is not set
+# CONFIG_DECNET is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_NETFILTER is not set
+CONFIG_XFRM=y
+# CONFIG_XFRM_USER is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+CONFIG_IPV6_SCTP__=y
+# CONFIG_IP_SCTP is not set
+# CONFIG_ATM is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_FASTROUTE is not set
+# CONFIG_NET_HW_FLOWCONTROL is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+CONFIG_NETDEVICES=y
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+# CONFIG_ETHERTAP is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+# CONFIG_MII is not set
+CONFIG_SGI_O2MACE_ETH=y
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_SUNGEM is not set
+# CONFIG_NET_VENDOR_3COM is not set
+
+#
+# Tulip family network device support
+#
+# CONFIG_NET_TULIP is not set
+# CONFIG_HP100 is not set
+# CONFIG_NET_PCI is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+# CONFIG_E1000 is not set
+# CONFIG_NS83820 is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+# CONFIG_R8169 is not set
+# CONFIG_SIS190 is not set
+# CONFIG_SK98LIN is not set
+# CONFIG_TIGON3 is not set
+
+#
+# Ethernet (10000 Mbit)
+#
+# CONFIG_IXGB is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Token Ring devices
+#
+# CONFIG_TR is not set
+# CONFIG_NET_FC is not set
+# CONFIG_SHAPER is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+
+#
+# Amateur Radio support
+#
+# CONFIG_HAMRADIO is not set
+
+#
+# IrDA (infrared) support
+#
+# CONFIG_IRDA is not set
+
+#
+# Bluetooth support
+#
+# CONFIG_BT is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN_BOOL is not set
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+CONFIG_INPUT_MOUSEDEV_PSAUX=y
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+# CONFIG_INPUT_EVDEV is not set
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input I/O drivers
+#
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+CONFIG_SERIO=y
+# CONFIG_SERIO_I8042 is not set
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_CT82C710 is not set
+# CONFIG_SERIO_PCIPS2 is not set
+# CONFIG_SERIO_MACEPS2 is not set
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=4
+# CONFIG_SERIAL_8250_EXTENDED is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+CONFIG_UNIX98_PTY_COUNT=256
+
+#
+# Mice
+#
+# CONFIG_BUSMOUSE is not set
+# CONFIG_QIC02_TAPE is not set
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_NVRAM is not set
+# CONFIG_RTC is not set
+# CONFIG_GEN_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_FTAPE is not set
+# CONFIG_AGP is not set
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+# CONFIG_MDA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+# CONFIG_USB is not set
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_JBD is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_QUOTA is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_FAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+# CONFIG_DEVFS_FS is not set
+CONFIG_DEVPTS_FS=y
+CONFIG_DEVPTS_FS_XATTR=y
+CONFIG_DEVPTS_FS_SECURITY=y
+CONFIG_TMPFS=y
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
+# CONFIG_NFSD is not set
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+# CONFIG_EXPORTFS is not set
+CONFIG_SUNRPC=y
+# CONFIG_SUNRPC_GSS is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_INTERMEZZO_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+# CONFIG_MAC_PARTITION is not set
+# CONFIG_MSDOS_PARTITION is not set
+# CONFIG_LDM_PARTITION is not set
+# CONFIG_NEC98_PARTITION is not set
+CONFIG_SGI_PARTITION=y
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+# CONFIG_EFI_PARTITION is not set
+
+#
+# Native Language Support
+#
+# CONFIG_NLS is not set
+
+#
+# Kernel hacking
+#
+CONFIG_CROSSCOMPILE=y
+CONFIG_CMDLINE=""
+# CONFIG_DEBUG_KERNEL is not set
+
+#
+# Security options
+#
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
+# Library routines
+#
+# CONFIG_CRC32 is not set
--- diff/arch/mips/configs/it8172_defconfig	1970-01-01 01:00:00.000000000 +0100
+++ source/arch/mips/configs/it8172_defconfig	2004-02-23 13:56:38.000000000 +0000
@@ -0,0 +1,667 @@
+#
+# Automatically generated make config: don't edit
+#
+CONFIG_MIPS=y
+# CONFIG_MIPS64 is not set
+# CONFIG_64BIT is not set
+CONFIG_MIPS32=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_CLEAN_COMPILE=y
+CONFIG_STANDALONE=y
+CONFIG_BROKEN_ON_SMP=y
+
+#
+# General setup
+#
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+CONFIG_BSD_PROCESS_ACCT=y
+CONFIG_SYSCTL=y
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_IKCONFIG is not set
+CONFIG_EMBEDDED=y
+CONFIG_KALLSYMS=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+CONFIG_OBSOLETE_MODPARM=y
+CONFIG_MODVERSIONS=y
+CONFIG_KMOD=y
+
+#
+# Machine selection
+#
+# CONFIG_MACH_JAZZ is not set
+# CONFIG_BAGET_MIPS is not set
+# CONFIG_MACH_VR41XX is not set
+# CONFIG_TOSHIBA_JMR3927 is not set
+# CONFIG_MIPS_COBALT is not set
+# CONFIG_MACH_DECSTATION is not set
+# CONFIG_MIPS_EV64120 is not set
+# CONFIG_MIPS_EV96100 is not set
+# CONFIG_MIPS_IVR is not set
+# CONFIG_LASAT is not set
+# CONFIG_HP_LASERJET is not set
+CONFIG_MIPS_ITE8172=y
+# CONFIG_IT8172_REVC is not set
+# CONFIG_MIPS_ATLAS is not set
+# CONFIG_MIPS_MALTA is not set
+# CONFIG_MIPS_SEAD is not set
+# CONFIG_MOMENCO_OCELOT is not set
+# CONFIG_MOMENCO_OCELOT_G is not set
+# CONFIG_MOMENCO_OCELOT_C is not set
+# CONFIG_MOMENCO_JAGUAR_ATX is not set
+# CONFIG_PMC_YOSEMITE is not set
+# CONFIG_DDB5074 is not set
+# CONFIG_DDB5476 is not set
+# CONFIG_DDB5477 is not set
+# CONFIG_NEC_OSPREY is not set
+# CONFIG_SGI_IP22 is not set
+# CONFIG_SGI_IP32 is not set
+# CONFIG_SOC_AU1X00 is not set
+# CONFIG_SIBYTE_SB1xxx_SOC is not set
+# CONFIG_SNI_RM200_PCI is not set
+# CONFIG_TOSHIBA_RBTX4927 is not set
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_HAVE_DEC_LOCK=y
+CONFIG_DMA_NONCOHERENT=y
+CONFIG_CPU_LITTLE_ENDIAN=y
+CONFIG_ITE_BOARD_GEN=y
+CONFIG_IT8172_CIR=y
+CONFIG_IT8712=y
+CONFIG_MIPS_L1_CACHE_SHIFT=5
+# CONFIG_FB is not set
+
+#
+# CPU selection
+#
+# CONFIG_CPU_MIPS32 is not set
+# CONFIG_CPU_MIPS64 is not set
+# CONFIG_CPU_R3000 is not set
+# CONFIG_CPU_TX39XX is not set
+# CONFIG_CPU_VR41XX is not set
+# CONFIG_CPU_R4300 is not set
+# CONFIG_CPU_R4X00 is not set
+# CONFIG_CPU_TX49XX is not set
+# CONFIG_CPU_R5000 is not set
+# CONFIG_CPU_R5432 is not set
+# CONFIG_CPU_R6000 is not set
+CONFIG_CPU_NEVADA=y
+# CONFIG_CPU_R8000 is not set
+# CONFIG_CPU_R10000 is not set
+# CONFIG_CPU_RM7000 is not set
+# CONFIG_CPU_RM9000 is not set
+# CONFIG_CPU_SB1 is not set
+CONFIG_PAGE_SIZE_4KB=y
+# CONFIG_PAGE_SIZE_16KB is not set
+# CONFIG_PAGE_SIZE_64KB is not set
+# CONFIG_CPU_ADVANCED is not set
+CONFIG_CPU_HAS_LLSC=y
+CONFIG_CPU_HAS_LLDSCD=y
+CONFIG_CPU_HAS_SYNC=y
+# CONFIG_PREEMPT is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+
+#
+# Bus options (PCI, PCMCIA, EISA, ISA, TC)
+#
+# CONFIG_PCI is not set
+CONFIG_MMU=y
+# CONFIG_HOTPLUG is not set
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_MISC is not set
+CONFIG_TRAD_SIGNALS=y
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+
+#
+# Memory Technology Devices (MTD)
+#
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+# CONFIG_MTD_PARTITIONS is not set
+# CONFIG_MTD_CONCAT is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+# CONFIG_MTD_BLOCK is not set
+# CONFIG_MTD_BLOCK_RO is not set
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+CONFIG_MTD_CFI=y
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_GEN_PROBE=y
+# CONFIG_MTD_CFI_ADV_OPTIONS is not set
+CONFIG_MTD_CFI_INTELEXT=y
+# CONFIG_MTD_CFI_AMDSTD is not set
+# CONFIG_MTD_CFI_STAA is not set
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+# CONFIG_MTD_OBSOLETE_CHIPS is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+CONFIG_MTD_PHYSMAP=y
+CONFIG_MTD_PHYSMAP_START=0x8000000
+CONFIG_MTD_PHYSMAP_LEN=0x2000000
+CONFIG_MTD_PHYSMAP_BUSWIDTH=4
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLKMTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+
+#
+# NAND Flash Device Drivers
+#
+# CONFIG_MTD_NAND is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+CONFIG_BLK_DEV_LOOP=y
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_RAM is not set
+# CONFIG_BLK_DEV_INITRD is not set
+# CONFIG_LBD is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+CONFIG_IDE=y
+CONFIG_BLK_DEV_IDE=y
+
+#
+# Please see Documentation/ide.txt for help/info on IDE drives
+#
+CONFIG_BLK_DEV_IDEDISK=y
+# CONFIG_IDEDISK_MULTI_MODE is not set
+# CONFIG_IDEDISK_STROKE is not set
+# CONFIG_BLK_DEV_IDECD is not set
+# CONFIG_BLK_DEV_IDETAPE is not set
+# CONFIG_BLK_DEV_IDEFLOPPY is not set
+# CONFIG_IDE_TASK_IOCTL is not set
+CONFIG_IDE_TASKFILE_IO=y
+
+#
+# IDE chipset support/bugfixes
+#
+CONFIG_IDE_GENERIC=y
+# CONFIG_BLK_DEV_IDEDMA is not set
+# CONFIG_IDEDMA_AUTO is not set
+# CONFIG_DMA_NONPCI is not set
+# CONFIG_BLK_DEV_HD is not set
+
+#
+# SCSI device support
+#
+# CONFIG_SCSI is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+
+#
+# IEEE 1394 (FireWire) support (EXPERIMENTAL)
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+
+#
+# Macintosh device drivers
+#
+
+#
+# Networking support
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+CONFIG_PACKET_MMAP=y
+CONFIG_NETLINK_DEV=y
+CONFIG_UNIX=y
+CONFIG_NET_KEY=y
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_PNP=y
+# CONFIG_IP_PNP_DHCP is not set
+CONFIG_IP_PNP_BOOTP=y
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_ARPD is not set
+# CONFIG_INET_ECN is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_IPV6 is not set
+# CONFIG_DECNET is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_NETFILTER is not set
+CONFIG_XFRM=y
+# CONFIG_XFRM_USER is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+CONFIG_IPV6_SCTP__=y
+# CONFIG_IP_SCTP is not set
+# CONFIG_ATM is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_FASTROUTE is not set
+# CONFIG_NET_HW_FLOWCONTROL is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+# CONFIG_ETHERTAP is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+# CONFIG_MII is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+
+#
+# Ethernet (10000 Mbit)
+#
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Token Ring devices
+#
+# CONFIG_SHAPER is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+
+#
+# Amateur Radio support
+#
+# CONFIG_HAMRADIO is not set
+
+#
+# IrDA (infrared) support
+#
+# CONFIG_IRDA is not set
+
+#
+# Bluetooth support
+#
+# CONFIG_BT is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN_BOOL is not set
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+CONFIG_INPUT_MOUSEDEV_PSAUX=y
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+# CONFIG_INPUT_EVDEV is not set
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input I/O drivers
+#
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+CONFIG_SERIO=y
+# CONFIG_SERIO_I8042 is not set
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_CT82C710 is not set
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+# CONFIG_QTRONIX_KEYBOARD is not set
+# CONFIG_IT8172_SCR0 is not set
+# CONFIG_IT8172_SCR1 is not set
+# CONFIG_ITE_GPIO is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=4
+# CONFIG_SERIAL_8250_EXTENDED is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+CONFIG_UNIX98_PTY_COUNT=256
+
+#
+# Mice
+#
+# CONFIG_BUSMOUSE is not set
+# CONFIG_QIC02_TAPE is not set
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_NVRAM is not set
+# CONFIG_RTC is not set
+# CONFIG_GEN_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_FTAPE is not set
+# CONFIG_AGP is not set
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+# CONFIG_MDA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+
+#
+# Sound
+#
+CONFIG_SOUND=y
+
+#
+# Advanced Linux Sound Architecture
+#
+# CONFIG_SND is not set
+
+#
+# Open Sound System
+#
+CONFIG_SOUND_PRIME=y
+# CONFIG_SOUND_BT878 is not set
+# CONFIG_SOUND_FUSION is not set
+# CONFIG_SOUND_CS4281 is not set
+# CONFIG_SOUND_ESSSOLO1 is not set
+# CONFIG_SOUND_MAESTRO is not set
+# CONFIG_SOUND_SONICVIBES is not set
+CONFIG_SOUND_IT8172=y
+# CONFIG_SOUND_TRIDENT is not set
+# CONFIG_SOUND_MSNDCLAS is not set
+# CONFIG_SOUND_MSNDPIN is not set
+# CONFIG_SOUND_OSS is not set
+# CONFIG_SOUND_AD1980 is not set
+
+#
+# USB support
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_JBD is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_QUOTA is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_FAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+# CONFIG_DEVFS_FS is not set
+CONFIG_DEVPTS_FS=y
+CONFIG_DEVPTS_FS_XATTR=y
+CONFIG_DEVPTS_FS_SECURITY=y
+# CONFIG_TMPFS is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_JFFS_FS is not set
+# CONFIG_JFFS2_FS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+# CONFIG_NFS_V3 is not set
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
+# CONFIG_NFSD is not set
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+# CONFIG_EXPORTFS is not set
+CONFIG_SUNRPC=y
+# CONFIG_SUNRPC_GSS is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_INTERMEZZO_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+
+#
+# Native Language Support
+#
+# CONFIG_NLS is not set
+
+#
+# Kernel hacking
+#
+CONFIG_CROSSCOMPILE=y
+CONFIG_CMDLINE=""
+# CONFIG_DEBUG_KERNEL is not set
+
+#
+# Security options
+#
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
+# Library routines
+#
+# CONFIG_CRC32 is not set
--- diff/arch/mips/configs/ivr_defconfig	1970-01-01 01:00:00.000000000 +0100
+++ source/arch/mips/configs/ivr_defconfig	2004-02-23 13:56:38.000000000 +0000
@@ -0,0 +1,621 @@
+#
+# Automatically generated make config: don't edit
+#
+CONFIG_MIPS=y
+# CONFIG_MIPS64 is not set
+# CONFIG_64BIT is not set
+CONFIG_MIPS32=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_CLEAN_COMPILE=y
+CONFIG_STANDALONE=y
+CONFIG_BROKEN_ON_SMP=y
+
+#
+# General setup
+#
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+CONFIG_BSD_PROCESS_ACCT=y
+CONFIG_SYSCTL=y
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_IKCONFIG is not set
+CONFIG_EMBEDDED=y
+CONFIG_KALLSYMS=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+CONFIG_OBSOLETE_MODPARM=y
+CONFIG_MODVERSIONS=y
+CONFIG_KMOD=y
+
+#
+# Machine selection
+#
+# CONFIG_MACH_JAZZ is not set
+# CONFIG_BAGET_MIPS is not set
+# CONFIG_MACH_VR41XX is not set
+# CONFIG_TOSHIBA_JMR3927 is not set
+# CONFIG_MIPS_COBALT is not set
+# CONFIG_MACH_DECSTATION is not set
+# CONFIG_MIPS_EV64120 is not set
+# CONFIG_MIPS_EV96100 is not set
+CONFIG_MIPS_IVR=y
+# CONFIG_LASAT is not set
+# CONFIG_HP_LASERJET is not set
+# CONFIG_MIPS_ITE8172 is not set
+# CONFIG_MIPS_ATLAS is not set
+# CONFIG_MIPS_MALTA is not set
+# CONFIG_MIPS_SEAD is not set
+# CONFIG_MOMENCO_OCELOT is not set
+# CONFIG_MOMENCO_OCELOT_G is not set
+# CONFIG_MOMENCO_OCELOT_C is not set
+# CONFIG_MOMENCO_JAGUAR_ATX is not set
+# CONFIG_PMC_YOSEMITE is not set
+# CONFIG_DDB5074 is not set
+# CONFIG_DDB5476 is not set
+# CONFIG_DDB5477 is not set
+# CONFIG_NEC_OSPREY is not set
+# CONFIG_SGI_IP22 is not set
+# CONFIG_SGI_IP32 is not set
+# CONFIG_SOC_AU1X00 is not set
+# CONFIG_SIBYTE_SB1xxx_SOC is not set
+# CONFIG_SNI_RM200_PCI is not set
+# CONFIG_TOSHIBA_RBTX4927 is not set
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_HAVE_DEC_LOCK=y
+CONFIG_DMA_NONCOHERENT=y
+CONFIG_CPU_LITTLE_ENDIAN=y
+CONFIG_ITE_BOARD_GEN=y
+CONFIG_IT8172_CIR=y
+CONFIG_MIPS_L1_CACHE_SHIFT=5
+# CONFIG_FB is not set
+
+#
+# CPU selection
+#
+# CONFIG_CPU_MIPS32 is not set
+# CONFIG_CPU_MIPS64 is not set
+# CONFIG_CPU_R3000 is not set
+# CONFIG_CPU_TX39XX is not set
+# CONFIG_CPU_VR41XX is not set
+# CONFIG_CPU_R4300 is not set
+# CONFIG_CPU_R4X00 is not set
+# CONFIG_CPU_TX49XX is not set
+# CONFIG_CPU_R5000 is not set
+# CONFIG_CPU_R5432 is not set
+# CONFIG_CPU_R6000 is not set
+CONFIG_CPU_NEVADA=y
+# CONFIG_CPU_R8000 is not set
+# CONFIG_CPU_R10000 is not set
+# CONFIG_CPU_RM7000 is not set
+# CONFIG_CPU_RM9000 is not set
+# CONFIG_CPU_SB1 is not set
+CONFIG_PAGE_SIZE_4KB=y
+# CONFIG_PAGE_SIZE_16KB is not set
+# CONFIG_PAGE_SIZE_64KB is not set
+# CONFIG_CPU_ADVANCED is not set
+CONFIG_CPU_HAS_LLSC=y
+CONFIG_CPU_HAS_LLDSCD=y
+CONFIG_CPU_HAS_SYNC=y
+# CONFIG_PREEMPT is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+
+#
+# Bus options (PCI, PCMCIA, EISA, ISA, TC)
+#
+CONFIG_PCI=y
+CONFIG_PCI_LEGACY_PROC=y
+CONFIG_PCI_NAMES=y
+CONFIG_MMU=y
+# CONFIG_HOTPLUG is not set
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_MISC is not set
+CONFIG_TRAD_SIGNALS=y
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_UMEM is not set
+# CONFIG_BLK_DEV_LOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_RAM is not set
+# CONFIG_BLK_DEV_INITRD is not set
+# CONFIG_LBD is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+CONFIG_IDE=y
+CONFIG_BLK_DEV_IDE=y
+
+#
+# Please see Documentation/ide.txt for help/info on IDE drives
+#
+CONFIG_BLK_DEV_IDEDISK=y
+# CONFIG_IDEDISK_MULTI_MODE is not set
+# CONFIG_IDEDISK_STROKE is not set
+# CONFIG_BLK_DEV_IDECD is not set
+# CONFIG_BLK_DEV_IDETAPE is not set
+# CONFIG_BLK_DEV_IDEFLOPPY is not set
+# CONFIG_IDE_TASK_IOCTL is not set
+CONFIG_IDE_TASKFILE_IO=y
+
+#
+# IDE chipset support/bugfixes
+#
+CONFIG_IDE_GENERIC=y
+# CONFIG_BLK_DEV_IDEPCI is not set
+# CONFIG_BLK_DEV_IDEDMA is not set
+# CONFIG_IDEDMA_AUTO is not set
+# CONFIG_DMA_NONPCI is not set
+# CONFIG_BLK_DEV_HD is not set
+
+#
+# SCSI device support
+#
+# CONFIG_SCSI is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+
+#
+# IEEE 1394 (FireWire) support (EXPERIMENTAL)
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+
+#
+# Macintosh device drivers
+#
+
+#
+# Networking support
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+CONFIG_PACKET_MMAP=y
+CONFIG_NETLINK_DEV=y
+CONFIG_UNIX=y
+CONFIG_NET_KEY=y
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_PNP=y
+# CONFIG_IP_PNP_DHCP is not set
+CONFIG_IP_PNP_BOOTP=y
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_ARPD is not set
+# CONFIG_INET_ECN is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_IPV6 is not set
+# CONFIG_DECNET is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_NETFILTER is not set
+CONFIG_XFRM=y
+# CONFIG_XFRM_USER is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+CONFIG_IPV6_SCTP__=y
+# CONFIG_IP_SCTP is not set
+# CONFIG_ATM is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_FASTROUTE is not set
+# CONFIG_NET_HW_FLOWCONTROL is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+CONFIG_NETDEVICES=y
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+# CONFIG_ETHERTAP is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+# CONFIG_MII is not set
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_SUNGEM is not set
+# CONFIG_NET_VENDOR_3COM is not set
+
+#
+# Tulip family network device support
+#
+# CONFIG_NET_TULIP is not set
+# CONFIG_HP100 is not set
+# CONFIG_NET_PCI is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+# CONFIG_E1000 is not set
+# CONFIG_NS83820 is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+# CONFIG_R8169 is not set
+# CONFIG_SIS190 is not set
+# CONFIG_SK98LIN is not set
+# CONFIG_TIGON3 is not set
+
+#
+# Ethernet (10000 Mbit)
+#
+# CONFIG_IXGB is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Token Ring devices
+#
+# CONFIG_TR is not set
+# CONFIG_RCPCI is not set
+# CONFIG_SHAPER is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+
+#
+# Amateur Radio support
+#
+# CONFIG_HAMRADIO is not set
+
+#
+# IrDA (infrared) support
+#
+# CONFIG_IRDA is not set
+
+#
+# Bluetooth support
+#
+# CONFIG_BT is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN_BOOL is not set
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+CONFIG_INPUT_MOUSEDEV_PSAUX=y
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+# CONFIG_INPUT_EVDEV is not set
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input I/O drivers
+#
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+CONFIG_SERIO=y
+# CONFIG_SERIO_I8042 is not set
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_CT82C710 is not set
+# CONFIG_SERIO_PCIPS2 is not set
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+CONFIG_QTRONIX_KEYBOARD=y
+# CONFIG_IT8172_SCR0 is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=4
+# CONFIG_SERIAL_8250_EXTENDED is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+CONFIG_UNIX98_PTY_COUNT=256
+
+#
+# Mice
+#
+# CONFIG_BUSMOUSE is not set
+# CONFIG_QIC02_TAPE is not set
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_NVRAM is not set
+CONFIG_RTC=y
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_FTAPE is not set
+# CONFIG_AGP is not set
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+# CONFIG_MDA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+# CONFIG_USB is not set
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_JBD is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_QUOTA is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_FAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+# CONFIG_DEVFS_FS is not set
+CONFIG_DEVPTS_FS=y
+CONFIG_DEVPTS_FS_XATTR=y
+CONFIG_DEVPTS_FS_SECURITY=y
+# CONFIG_TMPFS is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+# CONFIG_NFS_V3 is not set
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
+# CONFIG_NFSD is not set
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+# CONFIG_EXPORTFS is not set
+CONFIG_SUNRPC=y
+# CONFIG_SUNRPC_GSS is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_INTERMEZZO_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+
+#
+# Native Language Support
+#
+# CONFIG_NLS is not set
+
+#
+# Kernel hacking
+#
+CONFIG_CROSSCOMPILE=y
+CONFIG_CMDLINE=""
+# CONFIG_DEBUG_KERNEL is not set
+
+#
+# Security options
+#
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
+# Library routines
+#
+# CONFIG_CRC32 is not set
--- diff/arch/mips/configs/jaguar-atx_defconfig	1970-01-01 01:00:00.000000000 +0100
+++ source/arch/mips/configs/jaguar-atx_defconfig	2004-02-23 13:56:38.000000000 +0000
@@ -0,0 +1,540 @@
+#
+# Automatically generated make config: don't edit
+#
+CONFIG_MIPS=y
+# CONFIG_MIPS64 is not set
+# CONFIG_64BIT is not set
+CONFIG_MIPS32=y
+
+#
+# Code maturity level options
+#
+# CONFIG_EXPERIMENTAL is not set
+CONFIG_CLEAN_COMPILE=y
+CONFIG_STANDALONE=y
+CONFIG_BROKEN_ON_SMP=y
+
+#
+# General setup
+#
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_EMBEDDED=y
+CONFIG_KALLSYMS=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+
+#
+# Loadable module support
+#
+# CONFIG_MODULES is not set
+
+#
+# Machine selection
+#
+# CONFIG_MACH_JAZZ is not set
+# CONFIG_MACH_VR41XX is not set
+# CONFIG_TOSHIBA_JMR3927 is not set
+# CONFIG_MACH_DECSTATION is not set
+# CONFIG_MIPS_IVR is not set
+# CONFIG_LASAT is not set
+# CONFIG_HP_LASERJET is not set
+# CONFIG_MIPS_ITE8172 is not set
+# CONFIG_MIPS_ATLAS is not set
+# CONFIG_MIPS_MALTA is not set
+# CONFIG_MOMENCO_OCELOT is not set
+# CONFIG_MOMENCO_OCELOT_G is not set
+# CONFIG_MOMENCO_OCELOT_C is not set
+CONFIG_MOMENCO_JAGUAR_ATX=y
+# CONFIG_PMC_YOSEMITE is not set
+# CONFIG_DDB5476 is not set
+# CONFIG_DDB5477 is not set
+# CONFIG_NEC_OSPREY is not set
+# CONFIG_SGI_IP22 is not set
+# CONFIG_SOC_AU1X00 is not set
+# CONFIG_SNI_RM200_PCI is not set
+# CONFIG_TOSHIBA_RBTX4927 is not set
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_HAVE_DEC_LOCK=y
+CONFIG_DMA_NONCOHERENT=y
+# CONFIG_CPU_LITTLE_ENDIAN is not set
+CONFIG_IRQ_CPU_RM7K=y
+CONFIG_MIPS_MV64340=y
+CONFIG_SWAP_IO_SPACE=y
+CONFIG_BOOT_ELF32=y
+CONFIG_MIPS_L1_CACHE_SHIFT=5
+# CONFIG_FB is not set
+CONFIG_BOARD_SCACHE=y
+
+#
+# CPU selection
+#
+# CONFIG_CPU_MIPS32 is not set
+# CONFIG_CPU_MIPS64 is not set
+# CONFIG_CPU_R3000 is not set
+# CONFIG_CPU_TX39XX is not set
+# CONFIG_CPU_VR41XX is not set
+# CONFIG_CPU_R4300 is not set
+# CONFIG_CPU_R4X00 is not set
+# CONFIG_CPU_TX49XX is not set
+# CONFIG_CPU_R5000 is not set
+# CONFIG_CPU_R5432 is not set
+# CONFIG_CPU_R6000 is not set
+# CONFIG_CPU_NEVADA is not set
+# CONFIG_CPU_R8000 is not set
+# CONFIG_CPU_R10000 is not set
+# CONFIG_CPU_RM7000 is not set
+CONFIG_CPU_RM9000=y
+# CONFIG_CPU_SB1 is not set
+CONFIG_PAGE_SIZE_4KB=y
+# CONFIG_PAGE_SIZE_16KB is not set
+# CONFIG_PAGE_SIZE_64KB is not set
+CONFIG_CPU_HAS_PREFETCH=y
+# CONFIG_64BIT_PHYS_ADDR is not set
+# CONFIG_CPU_ADVANCED is not set
+CONFIG_CPU_HAS_LLSC=y
+CONFIG_CPU_HAS_LLDSCD=y
+CONFIG_CPU_HAS_SYNC=y
+# CONFIG_SMP is not set
+# CONFIG_PREEMPT is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+
+#
+# Bus options (PCI, PCMCIA, EISA, ISA, TC)
+#
+CONFIG_PCI=y
+CONFIG_PCI_LEGACY_PROC=y
+CONFIG_PCI_NAMES=y
+CONFIG_MMU=y
+# CONFIG_HOTPLUG is not set
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_MISC is not set
+CONFIG_TRAD_SIGNALS=y
+# CONFIG_BINFMT_IRIX is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_LOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_RAM is not set
+# CONFIG_BLK_DEV_INITRD is not set
+# CONFIG_LBD is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_SCSI is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+
+#
+# Macintosh device drivers
+#
+
+#
+# Networking support
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+# CONFIG_PACKET is not set
+# CONFIG_NETLINK_DEV is not set
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_PNP=y
+# CONFIG_IP_PNP_DHCP is not set
+CONFIG_IP_PNP_BOOTP=y
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_INET_ECN is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_DECNET is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_NETFILTER is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+CONFIG_NETDEVICES=y
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_SUNGEM is not set
+# CONFIG_NET_VENDOR_3COM is not set
+
+#
+# Tulip family network device support
+#
+# CONFIG_NET_TULIP is not set
+# CONFIG_HP100 is not set
+CONFIG_NET_PCI=y
+# CONFIG_PCNET32 is not set
+# CONFIG_AMD8111_ETH is not set
+# CONFIG_ADAPTEC_STARFIRE is not set
+# CONFIG_DGRS is not set
+CONFIG_EEPRO100=y
+# CONFIG_EEPRO100_PIO is not set
+# CONFIG_E100 is not set
+# CONFIG_FEALNX is not set
+# CONFIG_NATSEMI is not set
+# CONFIG_NE2K_PCI is not set
+# CONFIG_8139TOO is not set
+# CONFIG_SIS900 is not set
+# CONFIG_EPIC100 is not set
+# CONFIG_SUNDANCE is not set
+# CONFIG_TLAN is not set
+# CONFIG_VIA_RHINE is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+# CONFIG_E1000 is not set
+# CONFIG_NS83820 is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_R8169 is not set
+# CONFIG_SK98LIN is not set
+# CONFIG_TIGON3 is not set
+CONFIG_MV64340_ETH=y
+CONFIG_MV64340_ETH_0=y
+# CONFIG_MV64340_ETH_1 is not set
+# CONFIG_MV64340_ETH_2 is not set
+
+#
+# Ethernet (10000 Mbit)
+#
+# CONFIG_IXGB is not set
+# CONFIG_FDDI is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Token Ring devices
+#
+# CONFIG_TR is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+
+#
+# Amateur Radio support
+#
+# CONFIG_HAMRADIO is not set
+
+#
+# IrDA (infrared) support
+#
+# CONFIG_IRDA is not set
+
+#
+# Bluetooth support
+#
+# CONFIG_BT is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN_BOOL is not set
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+# CONFIG_INPUT is not set
+
+#
+# Userland interfaces
+#
+
+#
+# Input I/O drivers
+#
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+CONFIG_SERIO=y
+CONFIG_SERIO_I8042=y
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_CT82C710 is not set
+# CONFIG_SERIO_PCIPS2 is not set
+
+#
+# Input Device Drivers
+#
+
+#
+# Character devices
+#
+# CONFIG_VT is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_UNIX98_PTYS=y
+CONFIG_UNIX98_PTY_COUNT=256
+
+#
+# Mice
+#
+# CONFIG_BUSMOUSE is not set
+# CONFIG_QIC02_TAPE is not set
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_NVRAM is not set
+# CONFIG_RTC is not set
+# CONFIG_GEN_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_FTAPE is not set
+# CONFIG_AGP is not set
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+# CONFIG_USB is not set
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# File systems
+#
+# CONFIG_EXT2_FS is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_JBD is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_QUOTA is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_FAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_DEVPTS_FS=y
+# CONFIG_DEVPTS_FS_XATTR is not set
+# CONFIG_TMPFS is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+# CONFIG_NFS_V3 is not set
+# CONFIG_NFSD is not set
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+# CONFIG_EXPORTFS is not set
+CONFIG_SUNRPC=y
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+
+#
+# Native Language Support
+#
+# CONFIG_NLS is not set
+
+#
+# Kernel hacking
+#
+CONFIG_CROSSCOMPILE=y
+CONFIG_CMDLINE=""
+# CONFIG_DEBUG_KERNEL is not set
+
+#
+# Security options
+#
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
+# Library routines
+#
+# CONFIG_CRC32 is not set
--- diff/arch/mips/configs/jmr3927_defconfig	1970-01-01 01:00:00.000000000 +0100
+++ source/arch/mips/configs/jmr3927_defconfig	2004-02-23 13:56:38.000000000 +0000
@@ -0,0 +1,624 @@
+#
+# Automatically generated make config: don't edit
+#
+CONFIG_MIPS=y
+# CONFIG_MIPS64 is not set
+# CONFIG_64BIT is not set
+CONFIG_MIPS32=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_CLEAN_COMPILE=y
+CONFIG_STANDALONE=y
+CONFIG_BROKEN_ON_SMP=y
+
+#
+# General setup
+#
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_IKCONFIG is not set
+CONFIG_EMBEDDED=y
+CONFIG_KALLSYMS=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+
+#
+# Loadable module support
+#
+# CONFIG_MODULES is not set
+
+#
+# Machine selection
+#
+# CONFIG_MACH_JAZZ is not set
+# CONFIG_BAGET_MIPS is not set
+# CONFIG_MACH_VR41XX is not set
+CONFIG_TOSHIBA_JMR3927=y
+# CONFIG_MIPS_COBALT is not set
+# CONFIG_MACH_DECSTATION is not set
+# CONFIG_MIPS_EV64120 is not set
+# CONFIG_MIPS_EV96100 is not set
+# CONFIG_MIPS_IVR is not set
+# CONFIG_LASAT is not set
+# CONFIG_HP_LASERJET is not set
+# CONFIG_MIPS_ITE8172 is not set
+# CONFIG_MIPS_ATLAS is not set
+# CONFIG_MIPS_MALTA is not set
+# CONFIG_MIPS_SEAD is not set
+# CONFIG_MOMENCO_OCELOT is not set
+# CONFIG_MOMENCO_OCELOT_G is not set
+# CONFIG_MOMENCO_OCELOT_C is not set
+# CONFIG_MOMENCO_JAGUAR_ATX is not set
+# CONFIG_PMC_YOSEMITE is not set
+# CONFIG_DDB5074 is not set
+# CONFIG_DDB5476 is not set
+# CONFIG_DDB5477 is not set
+# CONFIG_NEC_OSPREY is not set
+# CONFIG_SGI_IP22 is not set
+# CONFIG_SGI_IP32 is not set
+# CONFIG_SOC_AU1X00 is not set
+# CONFIG_SIBYTE_SB1xxx_SOC is not set
+# CONFIG_SNI_RM200_PCI is not set
+# CONFIG_TOSHIBA_RBTX4927 is not set
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_HAVE_DEC_LOCK=y
+CONFIG_DMA_NONCOHERENT=y
+# CONFIG_CPU_LITTLE_ENDIAN is not set
+CONFIG_MIPS_TX3927=y
+CONFIG_SWAP_IO_SPACE=y
+CONFIG_MIPS_L1_CACHE_SHIFT=5
+CONFIG_FB=y
+CONFIG_TOSHIBA_BOARDS=y
+
+#
+# CPU selection
+#
+# CONFIG_CPU_MIPS32 is not set
+# CONFIG_CPU_MIPS64 is not set
+# CONFIG_CPU_R3000 is not set
+CONFIG_CPU_TX39XX=y
+# CONFIG_CPU_VR41XX is not set
+# CONFIG_CPU_R4300 is not set
+# CONFIG_CPU_R4X00 is not set
+# CONFIG_CPU_TX49XX is not set
+# CONFIG_CPU_R5000 is not set
+# CONFIG_CPU_R5432 is not set
+# CONFIG_CPU_R6000 is not set
+# CONFIG_CPU_NEVADA is not set
+# CONFIG_CPU_R8000 is not set
+# CONFIG_CPU_R10000 is not set
+# CONFIG_CPU_RM7000 is not set
+# CONFIG_CPU_RM9000 is not set
+# CONFIG_CPU_SB1 is not set
+CONFIG_PAGE_SIZE_4KB=y
+# CONFIG_PAGE_SIZE_16KB is not set
+# CONFIG_PAGE_SIZE_64KB is not set
+# CONFIG_CPU_ADVANCED is not set
+CONFIG_CPU_HAS_SYNC=y
+# CONFIG_PREEMPT is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+CONFIG_RTC_DS1742=y
+
+#
+# Bus options (PCI, PCMCIA, EISA, ISA, TC)
+#
+CONFIG_PCI=y
+CONFIG_PCI_LEGACY_PROC=y
+CONFIG_PCI_NAMES=y
+CONFIG_MMU=y
+# CONFIG_HOTPLUG is not set
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_MISC is not set
+CONFIG_TRAD_SIGNALS=y
+# CONFIG_BINFMT_IRIX is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_UMEM is not set
+# CONFIG_BLK_DEV_LOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_RAM is not set
+# CONFIG_BLK_DEV_INITRD is not set
+# CONFIG_LBD is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_SCSI is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+
+#
+# IEEE 1394 (FireWire) support (EXPERIMENTAL)
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+
+#
+# Macintosh device drivers
+#
+
+#
+# Networking support
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+CONFIG_NETLINK_DEV=y
+CONFIG_UNIX=y
+CONFIG_NET_KEY=y
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_PNP=y
+# CONFIG_IP_PNP_DHCP is not set
+CONFIG_IP_PNP_BOOTP=y
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_ARPD is not set
+# CONFIG_INET_ECN is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_IPV6 is not set
+# CONFIG_DECNET is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_NETFILTER is not set
+CONFIG_XFRM=y
+# CONFIG_XFRM_USER is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+CONFIG_IPV6_SCTP__=y
+# CONFIG_IP_SCTP is not set
+# CONFIG_ATM is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_FASTROUTE is not set
+# CONFIG_NET_HW_FLOWCONTROL is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+CONFIG_NETDEVICES=y
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+# CONFIG_ETHERTAP is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+# CONFIG_MII is not set
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_SUNGEM is not set
+# CONFIG_NET_VENDOR_3COM is not set
+
+#
+# Tulip family network device support
+#
+# CONFIG_NET_TULIP is not set
+# CONFIG_HP100 is not set
+# CONFIG_NET_PCI is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+# CONFIG_E1000 is not set
+# CONFIG_NS83820 is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+# CONFIG_R8169 is not set
+# CONFIG_SIS190 is not set
+# CONFIG_SK98LIN is not set
+# CONFIG_TIGON3 is not set
+
+#
+# Ethernet (10000 Mbit)
+#
+# CONFIG_IXGB is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Token Ring devices
+#
+# CONFIG_TR is not set
+# CONFIG_RCPCI is not set
+# CONFIG_SHAPER is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+
+#
+# Amateur Radio support
+#
+# CONFIG_HAMRADIO is not set
+
+#
+# IrDA (infrared) support
+#
+# CONFIG_IRDA is not set
+
+#
+# Bluetooth support
+#
+# CONFIG_BT is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN_BOOL is not set
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+CONFIG_INPUT_MOUSEDEV_PSAUX=y
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+# CONFIG_INPUT_EVDEV is not set
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input I/O drivers
+#
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+CONFIG_SERIO=y
+# CONFIG_SERIO_I8042 is not set
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_CT82C710 is not set
+# CONFIG_SERIO_PCIPS2 is not set
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+CONFIG_SERIAL_NONSTANDARD=y
+# CONFIG_COMPUTONE is not set
+# CONFIG_ROCKETPORT is not set
+# CONFIG_CYCLADES is not set
+# CONFIG_DIGIEPCA is not set
+# CONFIG_DIGI is not set
+# CONFIG_MOXA_INTELLIO is not set
+# CONFIG_MOXA_SMARTIO is not set
+# CONFIG_SYNCLINK is not set
+# CONFIG_SYNCLINKMP is not set
+# CONFIG_N_HDLC is not set
+# CONFIG_RISCOM8 is not set
+# CONFIG_SPECIALIX is not set
+# CONFIG_SX is not set
+# CONFIG_RIO is not set
+# CONFIG_STALDRV is not set
+# CONFIG_SERIAL_TX3912 is not set
+CONFIG_TXX927_SERIAL=y
+CONFIG_TXX927_SERIAL_CONSOLE=y
+# CONFIG_SERIAL_TXX9 is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+# CONFIG_UNIX98_PTYS is not set
+
+#
+# Mice
+#
+# CONFIG_BUSMOUSE is not set
+# CONFIG_QIC02_TAPE is not set
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_NVRAM is not set
+# CONFIG_RTC is not set
+# CONFIG_GEN_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_FTAPE is not set
+# CONFIG_AGP is not set
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+# CONFIG_FB_CYBER2000 is not set
+# CONFIG_FB_IMSTT is not set
+# CONFIG_FB_RIVA is not set
+# CONFIG_FB_MATROX is not set
+# CONFIG_FB_RADEON_OLD is not set
+# CONFIG_FB_RADEON is not set
+# CONFIG_FB_ATY128 is not set
+# CONFIG_FB_ATY is not set
+# CONFIG_FB_SIS is not set
+# CONFIG_FB_NEOMAGIC is not set
+# CONFIG_FB_KYRO is not set
+# CONFIG_FB_3DFX is not set
+# CONFIG_FB_VOODOO1 is not set
+# CONFIG_FB_TRIDENT is not set
+# CONFIG_FB_E1356 is not set
+# CONFIG_FB_VIRTUAL is not set
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+# CONFIG_MDA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+# CONFIG_FRAMEBUFFER_CONSOLE is not set
+
+#
+# Logo configuration
+#
+# CONFIG_LOGO is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+# CONFIG_USB is not set
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# File systems
+#
+# CONFIG_EXT2_FS is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_JBD is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_QUOTA is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_FAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+# CONFIG_DEVFS_FS is not set
+# CONFIG_TMPFS is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+# CONFIG_NFS_V3 is not set
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
+# CONFIG_NFSD is not set
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+# CONFIG_EXPORTFS is not set
+CONFIG_SUNRPC=y
+# CONFIG_SUNRPC_GSS is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_INTERMEZZO_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+
+#
+# Native Language Support
+#
+# CONFIG_NLS is not set
+
+#
+# Kernel hacking
+#
+CONFIG_CROSSCOMPILE=y
+CONFIG_CMDLINE=""
+# CONFIG_DEBUG_KERNEL is not set
+
+#
+# Security options
+#
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
+# Library routines
+#
+# CONFIG_CRC32 is not set
--- diff/arch/mips/configs/lasat200_defconfig	1970-01-01 01:00:00.000000000 +0100
+++ source/arch/mips/configs/lasat200_defconfig	2004-02-23 13:56:38.000000000 +0000
@@ -0,0 +1,715 @@
+#
+# Automatically generated make config: don't edit
+#
+CONFIG_MIPS=y
+# CONFIG_MIPS64 is not set
+# CONFIG_64BIT is not set
+CONFIG_MIPS32=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_CLEAN_COMPILE=y
+CONFIG_STANDALONE=y
+CONFIG_BROKEN_ON_SMP=y
+
+#
+# General setup
+#
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_IKCONFIG is not set
+CONFIG_EMBEDDED=y
+CONFIG_KALLSYMS=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+CONFIG_OBSOLETE_MODPARM=y
+CONFIG_MODVERSIONS=y
+CONFIG_KMOD=y
+
+#
+# Machine selection
+#
+# CONFIG_MACH_JAZZ is not set
+# CONFIG_BAGET_MIPS is not set
+# CONFIG_MACH_VR41XX is not set
+# CONFIG_TOSHIBA_JMR3927 is not set
+# CONFIG_MIPS_COBALT is not set
+# CONFIG_MACH_DECSTATION is not set
+# CONFIG_MIPS_EV64120 is not set
+# CONFIG_MIPS_EV96100 is not set
+# CONFIG_MIPS_IVR is not set
+CONFIG_LASAT=y
+CONFIG_PICVUE=y
+CONFIG_PICVUE_PROC=y
+CONFIG_DS1603=y
+CONFIG_LASAT_SYSCTL=y
+# CONFIG_HP_LASERJET is not set
+# CONFIG_MIPS_ITE8172 is not set
+# CONFIG_MIPS_ATLAS is not set
+# CONFIG_MIPS_MALTA is not set
+# CONFIG_MIPS_SEAD is not set
+# CONFIG_MOMENCO_OCELOT is not set
+# CONFIG_MOMENCO_OCELOT_G is not set
+# CONFIG_MOMENCO_OCELOT_C is not set
+# CONFIG_MOMENCO_JAGUAR_ATX is not set
+# CONFIG_PMC_YOSEMITE is not set
+# CONFIG_DDB5074 is not set
+# CONFIG_DDB5476 is not set
+# CONFIG_DDB5477 is not set
+# CONFIG_NEC_OSPREY is not set
+# CONFIG_SGI_IP22 is not set
+# CONFIG_SGI_IP32 is not set
+# CONFIG_SOC_AU1X00 is not set
+# CONFIG_SIBYTE_SB1xxx_SOC is not set
+# CONFIG_SNI_RM200_PCI is not set
+# CONFIG_TOSHIBA_RBTX4927 is not set
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_HAVE_DEC_LOCK=y
+CONFIG_DMA_NONCOHERENT=y
+CONFIG_MIPS_NILE4=y
+CONFIG_CPU_LITTLE_ENDIAN=y
+CONFIG_MIPS_GT64120=y
+CONFIG_MIPS_L1_CACHE_SHIFT=5
+# CONFIG_FB is not set
+CONFIG_BOARD_SCACHE=y
+
+#
+# CPU selection
+#
+# CONFIG_CPU_MIPS32 is not set
+# CONFIG_CPU_MIPS64 is not set
+# CONFIG_CPU_R3000 is not set
+# CONFIG_CPU_TX39XX is not set
+# CONFIG_CPU_VR41XX is not set
+# CONFIG_CPU_R4300 is not set
+# CONFIG_CPU_R4X00 is not set
+# CONFIG_CPU_TX49XX is not set
+CONFIG_CPU_R5000=y
+# CONFIG_CPU_R5432 is not set
+# CONFIG_CPU_R6000 is not set
+# CONFIG_CPU_NEVADA is not set
+# CONFIG_CPU_R8000 is not set
+# CONFIG_CPU_R10000 is not set
+# CONFIG_CPU_RM7000 is not set
+# CONFIG_CPU_RM9000 is not set
+# CONFIG_CPU_SB1 is not set
+CONFIG_PAGE_SIZE_4KB=y
+# CONFIG_PAGE_SIZE_16KB is not set
+# CONFIG_PAGE_SIZE_64KB is not set
+CONFIG_R5000_CPU_SCACHE=y
+# CONFIG_64BIT_PHYS_ADDR is not set
+# CONFIG_CPU_ADVANCED is not set
+CONFIG_CPU_HAS_LLSC=y
+CONFIG_CPU_HAS_LLDSCD=y
+CONFIG_CPU_HAS_SYNC=y
+# CONFIG_PREEMPT is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+
+#
+# Bus options (PCI, PCMCIA, EISA, ISA, TC)
+#
+CONFIG_PCI=y
+CONFIG_PCI_LEGACY_PROC=y
+# CONFIG_PCI_NAMES is not set
+CONFIG_MMU=y
+# CONFIG_HOTPLUG is not set
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_MISC is not set
+CONFIG_TRAD_SIGNALS=y
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+
+#
+# Memory Technology Devices (MTD)
+#
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_CONCAT is not set
+# CONFIG_MTD_REDBOOT_PARTS is not set
+# CONFIG_MTD_CMDLINE_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+CONFIG_MTD_CFI=y
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_GEN_PROBE=y
+# CONFIG_MTD_CFI_ADV_OPTIONS is not set
+# CONFIG_MTD_CFI_INTELEXT is not set
+CONFIG_MTD_CFI_AMDSTD=y
+# CONFIG_MTD_CFI_STAA is not set
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+# CONFIG_MTD_OBSOLETE_CHIPS is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+# CONFIG_MTD_PHYSMAP is not set
+CONFIG_MTD_LASAT=y
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_PMC551 is not set
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLKMTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+
+#
+# NAND Flash Device Drivers
+#
+# CONFIG_MTD_NAND is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_UMEM is not set
+# CONFIG_BLK_DEV_LOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_RAM is not set
+# CONFIG_BLK_DEV_INITRD is not set
+# CONFIG_LBD is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+CONFIG_IDE=y
+CONFIG_BLK_DEV_IDE=y
+
+#
+# Please see Documentation/ide.txt for help/info on IDE drives
+#
+CONFIG_BLK_DEV_IDEDISK=y
+CONFIG_IDEDISK_MULTI_MODE=y
+# CONFIG_IDEDISK_STROKE is not set
+# CONFIG_BLK_DEV_IDECD is not set
+# CONFIG_BLK_DEV_IDETAPE is not set
+# CONFIG_BLK_DEV_IDEFLOPPY is not set
+# CONFIG_IDE_TASK_IOCTL is not set
+CONFIG_IDE_TASKFILE_IO=y
+
+#
+# IDE chipset support/bugfixes
+#
+CONFIG_IDE_GENERIC=y
+CONFIG_BLK_DEV_IDEPCI=y
+# CONFIG_IDEPCI_SHARE_IRQ is not set
+# CONFIG_BLK_DEV_OFFBOARD is not set
+CONFIG_BLK_DEV_GENERIC=y
+# CONFIG_BLK_DEV_OPTI621 is not set
+CONFIG_BLK_DEV_IDEDMA_PCI=y
+# CONFIG_BLK_DEV_IDEDMA_FORCED is not set
+CONFIG_IDEDMA_PCI_AUTO=y
+# CONFIG_IDEDMA_ONLYDISK is not set
+CONFIG_BLK_DEV_ADMA=y
+# CONFIG_BLK_DEV_AEC62XX is not set
+# CONFIG_BLK_DEV_ALI15X3 is not set
+# CONFIG_BLK_DEV_AMD74XX is not set
+CONFIG_BLK_DEV_CMD64X=y
+# CONFIG_BLK_DEV_TRIFLEX is not set
+# CONFIG_BLK_DEV_CY82C693 is not set
+# CONFIG_BLK_DEV_CS5520 is not set
+# CONFIG_BLK_DEV_CS5530 is not set
+# CONFIG_BLK_DEV_HPT34X is not set
+# CONFIG_BLK_DEV_HPT366 is not set
+# CONFIG_BLK_DEV_SC1200 is not set
+# CONFIG_BLK_DEV_PIIX is not set
+# CONFIG_BLK_DEV_NS87415 is not set
+# CONFIG_BLK_DEV_PDC202XX_OLD is not set
+# CONFIG_BLK_DEV_PDC202XX_NEW is not set
+# CONFIG_BLK_DEV_SVWKS is not set
+# CONFIG_BLK_DEV_SIIMAGE is not set
+# CONFIG_BLK_DEV_SLC90E66 is not set
+# CONFIG_BLK_DEV_TRM290 is not set
+# CONFIG_BLK_DEV_VIA82CXXX is not set
+CONFIG_BLK_DEV_IDEDMA=y
+# CONFIG_IDEDMA_IVB is not set
+CONFIG_IDEDMA_AUTO=y
+# CONFIG_DMA_NONPCI is not set
+# CONFIG_BLK_DEV_HD is not set
+
+#
+# SCSI device support
+#
+# CONFIG_SCSI is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+
+#
+# IEEE 1394 (FireWire) support (EXPERIMENTAL)
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+
+#
+# Macintosh device drivers
+#
+
+#
+# Networking support
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+# CONFIG_PACKET is not set
+# CONFIG_NETLINK_DEV is not set
+CONFIG_UNIX=y
+CONFIG_NET_KEY=y
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+# CONFIG_IP_PNP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_ARPD is not set
+# CONFIG_INET_ECN is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_IPV6 is not set
+# CONFIG_DECNET is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_NETFILTER is not set
+CONFIG_XFRM=y
+# CONFIG_XFRM_USER is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+CONFIG_IPV6_SCTP__=y
+# CONFIG_IP_SCTP is not set
+# CONFIG_ATM is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_FASTROUTE is not set
+# CONFIG_NET_HW_FLOWCONTROL is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+CONFIG_NETDEVICES=y
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+# CONFIG_MII is not set
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_SUNGEM is not set
+# CONFIG_NET_VENDOR_3COM is not set
+
+#
+# Tulip family network device support
+#
+# CONFIG_NET_TULIP is not set
+# CONFIG_HP100 is not set
+# CONFIG_NET_PCI is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+# CONFIG_E1000 is not set
+# CONFIG_NS83820 is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+# CONFIG_R8169 is not set
+# CONFIG_SIS190 is not set
+# CONFIG_SK98LIN is not set
+# CONFIG_TIGON3 is not set
+
+#
+# Ethernet (10000 Mbit)
+#
+# CONFIG_IXGB is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Token Ring devices
+#
+# CONFIG_TR is not set
+# CONFIG_RCPCI is not set
+# CONFIG_SHAPER is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+
+#
+# Amateur Radio support
+#
+# CONFIG_HAMRADIO is not set
+
+#
+# IrDA (infrared) support
+#
+# CONFIG_IRDA is not set
+
+#
+# Bluetooth support
+#
+# CONFIG_BT is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN_BOOL is not set
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+CONFIG_INPUT_MOUSEDEV_PSAUX=y
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+# CONFIG_INPUT_EVDEV is not set
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input I/O drivers
+#
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+CONFIG_SERIO=y
+CONFIG_SERIO_I8042=y
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_CT82C710 is not set
+# CONFIG_SERIO_PCIPS2 is not set
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=4
+# CONFIG_SERIAL_8250_EXTENDED is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+CONFIG_UNIX98_PTY_COUNT=256
+
+#
+# Mice
+#
+# CONFIG_BUSMOUSE is not set
+# CONFIG_QIC02_TAPE is not set
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_NVRAM is not set
+# CONFIG_RTC is not set
+# CONFIG_GEN_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_FTAPE is not set
+# CONFIG_AGP is not set
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+# CONFIG_MDA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+# CONFIG_USB is not set
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+CONFIG_EXT3_FS=y
+CONFIG_EXT3_FS_XATTR=y
+# CONFIG_EXT3_FS_POSIX_ACL is not set
+CONFIG_EXT3_FS_SECURITY=y
+CONFIG_JBD=y
+# CONFIG_JBD_DEBUG is not set
+CONFIG_FS_MBCACHE=y
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_QUOTA is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_FAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+# CONFIG_DEVFS_FS is not set
+CONFIG_DEVPTS_FS=y
+CONFIG_DEVPTS_FS_XATTR=y
+CONFIG_DEVPTS_FS_SECURITY=y
+# CONFIG_TMPFS is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_JFFS_FS is not set
+# CONFIG_JFFS2_FS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
+# CONFIG_NFSD is not set
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+# CONFIG_EXPORTFS is not set
+CONFIG_SUNRPC=y
+# CONFIG_SUNRPC_GSS is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_INTERMEZZO_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+
+#
+# Native Language Support
+#
+# CONFIG_NLS is not set
+
+#
+# Kernel hacking
+#
+CONFIG_CROSSCOMPILE=y
+CONFIG_CMDLINE=""
+# CONFIG_DEBUG_KERNEL is not set
+
+#
+# Security options
+#
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
+# Library routines
+#
+CONFIG_CRC32=y
--- diff/arch/mips/configs/malta_defconfig	1970-01-01 01:00:00.000000000 +0100
+++ source/arch/mips/configs/malta_defconfig	2004-02-23 13:56:38.000000000 +0000
@@ -0,0 +1,628 @@
+#
+# Automatically generated make config: don't edit
+#
+CONFIG_MIPS=y
+# CONFIG_MIPS64 is not set
+# CONFIG_64BIT is not set
+CONFIG_MIPS32=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_CLEAN_COMPILE=y
+CONFIG_STANDALONE=y
+CONFIG_BROKEN_ON_SMP=y
+
+#
+# General setup
+#
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_IKCONFIG is not set
+CONFIG_EMBEDDED=y
+CONFIG_KALLSYMS=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+CONFIG_OBSOLETE_MODPARM=y
+CONFIG_MODVERSIONS=y
+CONFIG_KMOD=y
+
+#
+# Machine selection
+#
+# CONFIG_MACH_JAZZ is not set
+# CONFIG_BAGET_MIPS is not set
+# CONFIG_MACH_VR41XX is not set
+# CONFIG_TOSHIBA_JMR3927 is not set
+# CONFIG_MIPS_COBALT is not set
+# CONFIG_MACH_DECSTATION is not set
+# CONFIG_MIPS_EV64120 is not set
+# CONFIG_MIPS_EV96100 is not set
+# CONFIG_MIPS_IVR is not set
+# CONFIG_LASAT is not set
+# CONFIG_HP_LASERJET is not set
+# CONFIG_MIPS_ITE8172 is not set
+# CONFIG_MIPS_ATLAS is not set
+CONFIG_MIPS_MALTA=y
+# CONFIG_MIPS_SEAD is not set
+# CONFIG_MOMENCO_OCELOT is not set
+# CONFIG_MOMENCO_OCELOT_G is not set
+# CONFIG_MOMENCO_OCELOT_C is not set
+# CONFIG_MOMENCO_JAGUAR_ATX is not set
+# CONFIG_PMC_YOSEMITE is not set
+# CONFIG_DDB5074 is not set
+# CONFIG_DDB5476 is not set
+# CONFIG_DDB5477 is not set
+# CONFIG_NEC_OSPREY is not set
+# CONFIG_SGI_IP22 is not set
+# CONFIG_SGI_IP32 is not set
+# CONFIG_SOC_AU1X00 is not set
+# CONFIG_SIBYTE_SB1xxx_SOC is not set
+# CONFIG_SNI_RM200_PCI is not set
+# CONFIG_TOSHIBA_RBTX4927 is not set
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_HAVE_DEC_LOCK=y
+CONFIG_DMA_NONCOHERENT=y
+CONFIG_GENERIC_ISA_DMA=y
+CONFIG_I8259=y
+CONFIG_MIPS_BONITO64=y
+CONFIG_MIPS_MSC=y
+CONFIG_CPU_LITTLE_ENDIAN=y
+CONFIG_MIPS_BOARDS_GEN=y
+CONFIG_MIPS_GT64120=y
+CONFIG_SWAP_IO_SPACE=y
+CONFIG_BOOT_ELF32=y
+CONFIG_MIPS_L1_CACHE_SHIFT=5
+# CONFIG_FB is not set
+CONFIG_HAVE_STD_PC_SERIAL_PORT=y
+
+#
+# CPU selection
+#
+CONFIG_CPU_MIPS32=y
+# CONFIG_CPU_MIPS64 is not set
+# CONFIG_CPU_R3000 is not set
+# CONFIG_CPU_TX39XX is not set
+# CONFIG_CPU_VR41XX is not set
+# CONFIG_CPU_R4300 is not set
+# CONFIG_CPU_R4X00 is not set
+# CONFIG_CPU_TX49XX is not set
+# CONFIG_CPU_R5000 is not set
+# CONFIG_CPU_R5432 is not set
+# CONFIG_CPU_R6000 is not set
+# CONFIG_CPU_NEVADA is not set
+# CONFIG_CPU_R8000 is not set
+# CONFIG_CPU_R10000 is not set
+# CONFIG_CPU_RM7000 is not set
+# CONFIG_CPU_RM9000 is not set
+# CONFIG_CPU_SB1 is not set
+CONFIG_PAGE_SIZE_4KB=y
+# CONFIG_PAGE_SIZE_16KB is not set
+# CONFIG_PAGE_SIZE_64KB is not set
+CONFIG_CPU_HAS_PREFETCH=y
+# CONFIG_VTAG_ICACHE is not set
+# CONFIG_64BIT_PHYS_ADDR is not set
+# CONFIG_CPU_ADVANCED is not set
+CONFIG_CPU_HAS_LLSC=y
+CONFIG_CPU_HAS_SYNC=y
+# CONFIG_PREEMPT is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+
+#
+# Bus options (PCI, PCMCIA, EISA, ISA, TC)
+#
+CONFIG_PCI=y
+CONFIG_PCI_LEGACY_PROC=y
+CONFIG_PCI_NAMES=y
+CONFIG_MMU=y
+# CONFIG_HOTPLUG is not set
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_MISC is not set
+CONFIG_TRAD_SIGNALS=y
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_UMEM is not set
+# CONFIG_BLK_DEV_LOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_SIZE=4096
+# CONFIG_BLK_DEV_INITRD is not set
+# CONFIG_LBD is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_SCSI is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+
+#
+# IEEE 1394 (FireWire) support (EXPERIMENTAL)
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+
+#
+# Macintosh device drivers
+#
+
+#
+# Networking support
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+# CONFIG_PACKET is not set
+CONFIG_NETLINK_DEV=y
+CONFIG_UNIX=y
+CONFIG_NET_KEY=y
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_BOOTP=y
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_ARPD is not set
+# CONFIG_INET_ECN is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_IPV6 is not set
+# CONFIG_DECNET is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_NETFILTER is not set
+CONFIG_XFRM=y
+# CONFIG_XFRM_USER is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+CONFIG_IPV6_SCTP__=y
+# CONFIG_IP_SCTP is not set
+# CONFIG_ATM is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_FASTROUTE is not set
+# CONFIG_NET_HW_FLOWCONTROL is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+CONFIG_NETDEVICES=y
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+# CONFIG_ETHERTAP is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_SUNGEM is not set
+# CONFIG_NET_VENDOR_3COM is not set
+
+#
+# Tulip family network device support
+#
+# CONFIG_NET_TULIP is not set
+# CONFIG_HP100 is not set
+CONFIG_NET_PCI=y
+CONFIG_PCNET32=y
+# CONFIG_AMD8111_ETH is not set
+# CONFIG_ADAPTEC_STARFIRE is not set
+# CONFIG_B44 is not set
+# CONFIG_FORCEDETH is not set
+# CONFIG_DGRS is not set
+# CONFIG_EEPRO100 is not set
+# CONFIG_E100 is not set
+# CONFIG_FEALNX is not set
+# CONFIG_NATSEMI is not set
+# CONFIG_NE2K_PCI is not set
+# CONFIG_8139CP is not set
+# CONFIG_8139TOO is not set
+# CONFIG_SIS900 is not set
+# CONFIG_EPIC100 is not set
+# CONFIG_SUNDANCE is not set
+# CONFIG_TLAN is not set
+# CONFIG_VIA_RHINE is not set
+# CONFIG_LAN_SAA9730 is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+# CONFIG_E1000 is not set
+# CONFIG_NS83820 is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+# CONFIG_R8169 is not set
+# CONFIG_SIS190 is not set
+# CONFIG_SK98LIN is not set
+# CONFIG_TIGON3 is not set
+
+#
+# Ethernet (10000 Mbit)
+#
+# CONFIG_IXGB is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Token Ring devices
+#
+# CONFIG_TR is not set
+# CONFIG_RCPCI is not set
+# CONFIG_SHAPER is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+
+#
+# Amateur Radio support
+#
+# CONFIG_HAMRADIO is not set
+
+#
+# IrDA (infrared) support
+#
+# CONFIG_IRDA is not set
+
+#
+# Bluetooth support
+#
+# CONFIG_BT is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN_BOOL is not set
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+CONFIG_INPUT_MOUSEDEV_PSAUX=y
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+# CONFIG_INPUT_EVDEV is not set
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input I/O drivers
+#
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+CONFIG_SERIO=y
+# CONFIG_SERIO_I8042 is not set
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_CT82C710 is not set
+# CONFIG_SERIO_PCIPS2 is not set
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=4
+# CONFIG_SERIAL_8250_EXTENDED is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+CONFIG_UNIX98_PTY_COUNT=256
+
+#
+# Mice
+#
+# CONFIG_BUSMOUSE is not set
+# CONFIG_QIC02_TAPE is not set
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_NVRAM is not set
+CONFIG_RTC=y
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_FTAPE is not set
+# CONFIG_AGP is not set
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+# CONFIG_MDA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+# CONFIG_USB is not set
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_JBD is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_QUOTA is not set
+CONFIG_AUTOFS_FS=y
+# CONFIG_AUTOFS4_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_FAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+# CONFIG_DEVFS_FS is not set
+CONFIG_DEVPTS_FS=y
+CONFIG_DEVPTS_FS_XATTR=y
+CONFIG_DEVPTS_FS_SECURITY=y
+# CONFIG_TMPFS is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+CONFIG_EFS_FS=y
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
+CONFIG_NFSD=y
+CONFIG_NFSD_V3=y
+# CONFIG_NFSD_V4 is not set
+# CONFIG_NFSD_TCP is not set
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_EXPORTFS=y
+CONFIG_SUNRPC=y
+# CONFIG_SUNRPC_GSS is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_INTERMEZZO_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+
+#
+# Native Language Support
+#
+# CONFIG_NLS is not set
+
+#
+# Kernel hacking
+#
+CONFIG_CROSSCOMPILE=y
+CONFIG_CMDLINE=""
+# CONFIG_DEBUG_KERNEL is not set
+
+#
+# Security options
+#
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
+# Library routines
+#
+CONFIG_CRC32=y
--- diff/arch/mips/configs/mirage_defconfig	1970-01-01 01:00:00.000000000 +0100
+++ source/arch/mips/configs/mirage_defconfig	2004-02-23 13:56:38.000000000 +0000
@@ -0,0 +1,673 @@
+#
+# Automatically generated make config: don't edit
+#
+CONFIG_MIPS=y
+# CONFIG_MIPS64 is not set
+# CONFIG_64BIT is not set
+CONFIG_MIPS32=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_CLEAN_COMPILE=y
+CONFIG_STANDALONE=y
+CONFIG_BROKEN_ON_SMP=y
+
+#
+# General setup
+#
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_IKCONFIG is not set
+CONFIG_EMBEDDED=y
+CONFIG_KALLSYMS=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+CONFIG_OBSOLETE_MODPARM=y
+CONFIG_MODVERSIONS=y
+CONFIG_KMOD=y
+
+#
+# Machine selection
+#
+# CONFIG_MACH_JAZZ is not set
+# CONFIG_BAGET_MIPS is not set
+# CONFIG_MACH_VR41XX is not set
+# CONFIG_TOSHIBA_JMR3927 is not set
+# CONFIG_MIPS_COBALT is not set
+# CONFIG_MACH_DECSTATION is not set
+# CONFIG_MIPS_EV64120 is not set
+# CONFIG_MIPS_EV96100 is not set
+# CONFIG_MIPS_IVR is not set
+# CONFIG_LASAT is not set
+# CONFIG_HP_LASERJET is not set
+# CONFIG_MIPS_ITE8172 is not set
+# CONFIG_MIPS_ATLAS is not set
+# CONFIG_MIPS_MALTA is not set
+# CONFIG_MIPS_SEAD is not set
+# CONFIG_MOMENCO_OCELOT is not set
+# CONFIG_MOMENCO_OCELOT_G is not set
+# CONFIG_MOMENCO_OCELOT_C is not set
+# CONFIG_MOMENCO_JAGUAR_ATX is not set
+# CONFIG_PMC_YOSEMITE is not set
+# CONFIG_DDB5074 is not set
+# CONFIG_DDB5476 is not set
+# CONFIG_DDB5477 is not set
+# CONFIG_NEC_OSPREY is not set
+# CONFIG_SGI_IP22 is not set
+# CONFIG_SGI_IP32 is not set
+# CONFIG_SOC_AU1X00 is not set
+# CONFIG_SIBYTE_SB1xxx_SOC is not set
+# CONFIG_SNI_RM200_PCI is not set
+# CONFIG_TOSHIBA_RBTX4927 is not set
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_HAVE_DEC_LOCK=y
+CONFIG_CPU_LITTLE_ENDIAN=y
+CONFIG_MIPS_L1_CACHE_SHIFT=5
+# CONFIG_FB is not set
+
+#
+# CPU selection
+#
+CONFIG_CPU_MIPS32=y
+# CONFIG_CPU_MIPS64 is not set
+# CONFIG_CPU_R3000 is not set
+# CONFIG_CPU_TX39XX is not set
+# CONFIG_CPU_VR41XX is not set
+# CONFIG_CPU_R4300 is not set
+# CONFIG_CPU_R4X00 is not set
+# CONFIG_CPU_TX49XX is not set
+# CONFIG_CPU_R5000 is not set
+# CONFIG_CPU_R5432 is not set
+# CONFIG_CPU_R6000 is not set
+# CONFIG_CPU_NEVADA is not set
+# CONFIG_CPU_R8000 is not set
+# CONFIG_CPU_R10000 is not set
+# CONFIG_CPU_RM7000 is not set
+# CONFIG_CPU_RM9000 is not set
+# CONFIG_CPU_SB1 is not set
+CONFIG_PAGE_SIZE_4KB=y
+# CONFIG_PAGE_SIZE_16KB is not set
+# CONFIG_PAGE_SIZE_64KB is not set
+CONFIG_CPU_HAS_PREFETCH=y
+# CONFIG_VTAG_ICACHE is not set
+# CONFIG_64BIT_PHYS_ADDR is not set
+# CONFIG_CPU_ADVANCED is not set
+CONFIG_CPU_HAS_LLSC=y
+CONFIG_CPU_HAS_SYNC=y
+# CONFIG_PREEMPT is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+
+#
+# Bus options (PCI, PCMCIA, EISA, ISA, TC)
+#
+CONFIG_MMU=y
+CONFIG_HOTPLUG=y
+
+#
+# PCMCIA/CardBus support
+#
+CONFIG_PCMCIA=m
+# CONFIG_TCIC is not set
+
+#
+# PCI Hotplug Support
+#
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_MISC is not set
+CONFIG_TRAD_SIGNALS=y
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+# CONFIG_FW_LOADER is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+CONFIG_BLK_DEV_LOOP=y
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_RAM is not set
+# CONFIG_BLK_DEV_INITRD is not set
+# CONFIG_LBD is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_SCSI is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+
+#
+# IEEE 1394 (FireWire) support (EXPERIMENTAL)
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+
+#
+# Macintosh device drivers
+#
+
+#
+# Networking support
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+CONFIG_NETLINK_DEV=y
+CONFIG_UNIX=y
+CONFIG_NET_KEY=y
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_PNP=y
+# CONFIG_IP_PNP_DHCP is not set
+CONFIG_IP_PNP_BOOTP=y
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_IP_MROUTE is not set
+# CONFIG_ARPD is not set
+# CONFIG_INET_ECN is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+
+#
+# IP: Virtual Server Configuration
+#
+# CONFIG_IP_VS is not set
+# CONFIG_IPV6 is not set
+# CONFIG_DECNET is not set
+# CONFIG_BRIDGE is not set
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
+
+#
+# IP: Netfilter Configuration
+#
+# CONFIG_IP_NF_CONNTRACK is not set
+# CONFIG_IP_NF_QUEUE is not set
+# CONFIG_IP_NF_IPTABLES is not set
+# CONFIG_IP_NF_ARPTABLES is not set
+# CONFIG_IP_NF_COMPAT_IPCHAINS is not set
+# CONFIG_IP_NF_COMPAT_IPFWADM is not set
+CONFIG_XFRM=y
+# CONFIG_XFRM_USER is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+CONFIG_IPV6_SCTP__=y
+# CONFIG_IP_SCTP is not set
+# CONFIG_ATM is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_FASTROUTE is not set
+# CONFIG_NET_HW_FLOWCONTROL is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+# CONFIG_ETHERTAP is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+# CONFIG_MII is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+
+#
+# Ethernet (10000 Mbit)
+#
+CONFIG_PPP=m
+CONFIG_PPP_MULTILINK=y
+# CONFIG_PPP_FILTER is not set
+CONFIG_PPP_ASYNC=m
+# CONFIG_PPP_SYNC_TTY is not set
+CONFIG_PPP_DEFLATE=m
+# CONFIG_PPP_BSDCOMP is not set
+CONFIG_PPPOE=m
+# CONFIG_SLIP is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Token Ring devices
+#
+# CONFIG_SHAPER is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+
+#
+# PCMCIA network device support
+#
+CONFIG_NET_PCMCIA=y
+CONFIG_PCMCIA_3C589=m
+# CONFIG_PCMCIA_3C574 is not set
+# CONFIG_PCMCIA_FMVJ18X is not set
+# CONFIG_PCMCIA_PCNET is not set
+# CONFIG_PCMCIA_NMCLAN is not set
+# CONFIG_PCMCIA_SMC91C92 is not set
+# CONFIG_PCMCIA_XIRC2PS is not set
+# CONFIG_PCMCIA_AXNET is not set
+
+#
+# Amateur Radio support
+#
+# CONFIG_HAMRADIO is not set
+
+#
+# IrDA (infrared) support
+#
+# CONFIG_IRDA is not set
+
+#
+# Bluetooth support
+#
+# CONFIG_BT is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN_BOOL is not set
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+CONFIG_INPUT_MOUSEDEV_PSAUX=y
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input I/O drivers
+#
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+CONFIG_SERIO=y
+# CONFIG_SERIO_I8042 is not set
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_CT82C710 is not set
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_UNIX98_PTYS=y
+CONFIG_UNIX98_PTY_COUNT=256
+
+#
+# Mice
+#
+# CONFIG_BUSMOUSE is not set
+# CONFIG_QIC02_TAPE is not set
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_NVRAM is not set
+CONFIG_RTC=y
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_FTAPE is not set
+# CONFIG_AGP is not set
+# CONFIG_DRM is not set
+
+#
+# PCMCIA character devices
+#
+# CONFIG_SYNCLINK_CS is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+# CONFIG_MDA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+CONFIG_EXT2_FS_XATTR=y
+CONFIG_EXT2_FS_POSIX_ACL=y
+# CONFIG_EXT2_FS_SECURITY is not set
+CONFIG_EXT3_FS=y
+CONFIG_EXT3_FS_XATTR=y
+CONFIG_EXT3_FS_POSIX_ACL=y
+CONFIG_EXT3_FS_SECURITY=y
+CONFIG_JBD=y
+# CONFIG_JBD_DEBUG is not set
+CONFIG_FS_MBCACHE=y
+CONFIG_REISERFS_FS=m
+# CONFIG_REISERFS_CHECK is not set
+# CONFIG_REISERFS_PROC_INFO is not set
+# CONFIG_JFS_FS is not set
+CONFIG_FS_POSIX_ACL=y
+# CONFIG_XFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_QUOTA is not set
+CONFIG_AUTOFS_FS=m
+CONFIG_AUTOFS4_FS=m
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_FAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+# CONFIG_DEVFS_FS is not set
+CONFIG_DEVPTS_FS=y
+CONFIG_DEVPTS_FS_XATTR=y
+CONFIG_DEVPTS_FS_SECURITY=y
+CONFIG_TMPFS=y
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+CONFIG_CRAMFS=m
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+# CONFIG_NFS_V3 is not set
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
+CONFIG_NFSD=m
+# CONFIG_NFSD_V3 is not set
+# CONFIG_NFSD_TCP is not set
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+CONFIG_EXPORTFS=m
+CONFIG_SUNRPC=y
+# CONFIG_SUNRPC_GSS is not set
+CONFIG_SMB_FS=m
+# CONFIG_SMB_NLS_DEFAULT is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_INTERMEZZO_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+
+#
+# Native Language Support
+#
+CONFIG_NLS=m
+CONFIG_NLS_DEFAULT="iso8859-1"
+# CONFIG_NLS_CODEPAGE_437 is not set
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ISO8859_1 is not set
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+# CONFIG_NLS_UTF8 is not set
+
+#
+# Kernel hacking
+#
+CONFIG_CROSSCOMPILE=y
+CONFIG_CMDLINE=""
+# CONFIG_DEBUG_KERNEL is not set
+
+#
+# Security options
+#
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+CONFIG_CRYPTO=y
+CONFIG_CRYPTO_HMAC=y
+CONFIG_CRYPTO_NULL=y
+# CONFIG_CRYPTO_MD4 is not set
+# CONFIG_CRYPTO_MD5 is not set
+# CONFIG_CRYPTO_SHA1 is not set
+# CONFIG_CRYPTO_SHA256 is not set
+CONFIG_CRYPTO_SHA512=y
+# CONFIG_CRYPTO_DES is not set
+# CONFIG_CRYPTO_BLOWFISH is not set
+CONFIG_CRYPTO_TWOFISH=y
+# CONFIG_CRYPTO_SERPENT is not set
+CONFIG_CRYPTO_AES=y
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+CONFIG_CRYPTO_DEFLATE=y
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Library routines
+#
+CONFIG_CRC32=y
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
--- diff/arch/mips/configs/mpc30x_defconfig	1970-01-01 01:00:00.000000000 +0100
+++ source/arch/mips/configs/mpc30x_defconfig	2004-02-23 13:56:38.000000000 +0000
@@ -0,0 +1,583 @@
+#
+# Automatically generated make config: don't edit
+#
+CONFIG_MIPS=y
+# CONFIG_MIPS64 is not set
+# CONFIG_64BIT is not set
+CONFIG_MIPS32=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_CLEAN_COMPILE=y
+CONFIG_STANDALONE=y
+CONFIG_BROKEN_ON_SMP=y
+
+#
+# General setup
+#
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_IKCONFIG is not set
+CONFIG_EMBEDDED=y
+CONFIG_KALLSYMS=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+CONFIG_OBSOLETE_MODPARM=y
+CONFIG_MODVERSIONS=y
+CONFIG_KMOD=y
+
+#
+# Machine selection
+#
+# CONFIG_MACH_JAZZ is not set
+# CONFIG_BAGET_MIPS is not set
+CONFIG_MACH_VR41XX=y
+# CONFIG_CASIO_E55 is not set
+# CONFIG_IBM_WORKPAD is not set
+# CONFIG_NEC_EAGLE is not set
+# CONFIG_TANBAC_TB0226 is not set
+# CONFIG_TANBAC_TB0229 is not set
+CONFIG_VICTOR_MPC30X=y
+# CONFIG_ZAO_CAPCELLA is not set
+# CONFIG_TOSHIBA_JMR3927 is not set
+# CONFIG_MIPS_COBALT is not set
+# CONFIG_MACH_DECSTATION is not set
+# CONFIG_MIPS_EV64120 is not set
+# CONFIG_MIPS_EV96100 is not set
+# CONFIG_MIPS_IVR is not set
+# CONFIG_LASAT is not set
+# CONFIG_HP_LASERJET is not set
+# CONFIG_MIPS_ITE8172 is not set
+# CONFIG_MIPS_ATLAS is not set
+# CONFIG_MIPS_MALTA is not set
+# CONFIG_MIPS_SEAD is not set
+# CONFIG_MOMENCO_OCELOT is not set
+# CONFIG_MOMENCO_OCELOT_G is not set
+# CONFIG_MOMENCO_OCELOT_C is not set
+# CONFIG_MOMENCO_JAGUAR_ATX is not set
+# CONFIG_PMC_YOSEMITE is not set
+# CONFIG_DDB5074 is not set
+# CONFIG_DDB5476 is not set
+# CONFIG_DDB5477 is not set
+# CONFIG_NEC_OSPREY is not set
+# CONFIG_SGI_IP22 is not set
+# CONFIG_SGI_IP32 is not set
+# CONFIG_SOC_AU1X00 is not set
+# CONFIG_SIBYTE_SB1xxx_SOC is not set
+# CONFIG_SNI_RM200_PCI is not set
+# CONFIG_TOSHIBA_RBTX4927 is not set
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_HAVE_DEC_LOCK=y
+CONFIG_DMA_NONCOHERENT=y
+CONFIG_CPU_LITTLE_ENDIAN=y
+CONFIG_IRQ_CPU=y
+CONFIG_DUMMY_KEYB=y
+CONFIG_VRC4173=y
+CONFIG_MIPS_L1_CACHE_SHIFT=5
+# CONFIG_FB is not set
+
+#
+# CPU selection
+#
+# CONFIG_CPU_MIPS32 is not set
+# CONFIG_CPU_MIPS64 is not set
+# CONFIG_CPU_R3000 is not set
+# CONFIG_CPU_TX39XX is not set
+CONFIG_CPU_VR41XX=y
+# CONFIG_CPU_R4300 is not set
+# CONFIG_CPU_R4X00 is not set
+# CONFIG_CPU_TX49XX is not set
+# CONFIG_CPU_R5000 is not set
+# CONFIG_CPU_R5432 is not set
+# CONFIG_CPU_R6000 is not set
+# CONFIG_CPU_NEVADA is not set
+# CONFIG_CPU_R8000 is not set
+# CONFIG_CPU_R10000 is not set
+# CONFIG_CPU_RM7000 is not set
+# CONFIG_CPU_RM9000 is not set
+# CONFIG_CPU_SB1 is not set
+CONFIG_PAGE_SIZE_4KB=y
+# CONFIG_PAGE_SIZE_16KB is not set
+# CONFIG_PAGE_SIZE_64KB is not set
+# CONFIG_CPU_ADVANCED is not set
+CONFIG_CPU_HAS_SYNC=y
+# CONFIG_PREEMPT is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+
+#
+# Bus options (PCI, PCMCIA, EISA, ISA, TC)
+#
+# CONFIG_PCI is not set
+CONFIG_MMU=y
+# CONFIG_HOTPLUG is not set
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_MISC is not set
+CONFIG_TRAD_SIGNALS=y
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+# CONFIG_BLK_DEV_LOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_RAM is not set
+# CONFIG_BLK_DEV_INITRD is not set
+# CONFIG_LBD is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_SCSI is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+
+#
+# IEEE 1394 (FireWire) support (EXPERIMENTAL)
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+
+#
+# Macintosh device drivers
+#
+
+#
+# Networking support
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+CONFIG_PACKET_MMAP=y
+CONFIG_NETLINK_DEV=y
+CONFIG_UNIX=y
+CONFIG_NET_KEY=y
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_PNP=y
+# CONFIG_IP_PNP_DHCP is not set
+CONFIG_IP_PNP_BOOTP=y
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_IP_MROUTE is not set
+# CONFIG_ARPD is not set
+# CONFIG_INET_ECN is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_IPV6 is not set
+# CONFIG_DECNET is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_NETFILTER is not set
+CONFIG_XFRM=y
+# CONFIG_XFRM_USER is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+CONFIG_IPV6_SCTP__=y
+# CONFIG_IP_SCTP is not set
+# CONFIG_ATM is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_FASTROUTE is not set
+# CONFIG_NET_HW_FLOWCONTROL is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+# CONFIG_ETHERTAP is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+# CONFIG_MII is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+
+#
+# Ethernet (10000 Mbit)
+#
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Token Ring devices
+#
+# CONFIG_SHAPER is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+
+#
+# Amateur Radio support
+#
+# CONFIG_HAMRADIO is not set
+
+#
+# IrDA (infrared) support
+#
+# CONFIG_IRDA is not set
+
+#
+# Bluetooth support
+#
+# CONFIG_BT is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN_BOOL is not set
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+CONFIG_INPUT_MOUSEDEV_PSAUX=y
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+# CONFIG_INPUT_EVDEV is not set
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input I/O drivers
+#
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+CONFIG_SERIO=y
+CONFIG_SERIO_I8042=y
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_CT82C710 is not set
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=4
+# CONFIG_SERIAL_8250_EXTENDED is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+CONFIG_UNIX98_PTY_COUNT=256
+
+#
+# Mice
+#
+# CONFIG_BUSMOUSE is not set
+# CONFIG_QIC02_TAPE is not set
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_NVRAM is not set
+# CONFIG_RTC is not set
+# CONFIG_GEN_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_FTAPE is not set
+# CONFIG_AGP is not set
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+# CONFIG_MDA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_JBD is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_QUOTA is not set
+CONFIG_AUTOFS_FS=y
+CONFIG_AUTOFS4_FS=y
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_FAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+# CONFIG_DEVFS_FS is not set
+CONFIG_DEVPTS_FS=y
+CONFIG_DEVPTS_FS_XATTR=y
+CONFIG_DEVPTS_FS_SECURITY=y
+# CONFIG_TMPFS is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+# CONFIG_NFS_V3 is not set
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
+# CONFIG_NFSD is not set
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+# CONFIG_EXPORTFS is not set
+CONFIG_SUNRPC=y
+# CONFIG_SUNRPC_GSS is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_INTERMEZZO_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+
+#
+# Native Language Support
+#
+# CONFIG_NLS is not set
+
+#
+# Kernel hacking
+#
+CONFIG_CROSSCOMPILE=y
+CONFIG_CMDLINE=""
+# CONFIG_DEBUG_KERNEL is not set
+
+#
+# Security options
+#
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+CONFIG_CRYPTO=y
+CONFIG_CRYPTO_HMAC=y
+CONFIG_CRYPTO_NULL=y
+# CONFIG_CRYPTO_MD4 is not set
+# CONFIG_CRYPTO_MD5 is not set
+# CONFIG_CRYPTO_SHA1 is not set
+# CONFIG_CRYPTO_SHA256 is not set
+CONFIG_CRYPTO_SHA512=y
+# CONFIG_CRYPTO_DES is not set
+# CONFIG_CRYPTO_BLOWFISH is not set
+CONFIG_CRYPTO_TWOFISH=y
+# CONFIG_CRYPTO_SERPENT is not set
+CONFIG_CRYPTO_AES=y
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+CONFIG_CRYPTO_DEFLATE=y
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Library routines
+#
+# CONFIG_CRC32 is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
--- diff/arch/mips/configs/mtx1_defconfig	1970-01-01 01:00:00.000000000 +0100
+++ source/arch/mips/configs/mtx1_defconfig	2004-02-23 13:56:38.000000000 +0000
@@ -0,0 +1,673 @@
+#
+# Automatically generated make config: don't edit
+#
+CONFIG_MIPS=y
+# CONFIG_MIPS64 is not set
+# CONFIG_64BIT is not set
+CONFIG_MIPS32=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_CLEAN_COMPILE=y
+CONFIG_STANDALONE=y
+CONFIG_BROKEN_ON_SMP=y
+
+#
+# General setup
+#
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_IKCONFIG is not set
+CONFIG_EMBEDDED=y
+CONFIG_KALLSYMS=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+CONFIG_OBSOLETE_MODPARM=y
+CONFIG_MODVERSIONS=y
+CONFIG_KMOD=y
+
+#
+# Machine selection
+#
+# CONFIG_MACH_JAZZ is not set
+# CONFIG_BAGET_MIPS is not set
+# CONFIG_MACH_VR41XX is not set
+# CONFIG_TOSHIBA_JMR3927 is not set
+# CONFIG_MIPS_COBALT is not set
+# CONFIG_MACH_DECSTATION is not set
+# CONFIG_MIPS_EV64120 is not set
+# CONFIG_MIPS_EV96100 is not set
+# CONFIG_MIPS_IVR is not set
+# CONFIG_LASAT is not set
+# CONFIG_HP_LASERJET is not set
+# CONFIG_MIPS_ITE8172 is not set
+# CONFIG_MIPS_ATLAS is not set
+# CONFIG_MIPS_MALTA is not set
+# CONFIG_MIPS_SEAD is not set
+# CONFIG_MOMENCO_OCELOT is not set
+# CONFIG_MOMENCO_OCELOT_G is not set
+# CONFIG_MOMENCO_OCELOT_C is not set
+# CONFIG_MOMENCO_JAGUAR_ATX is not set
+# CONFIG_PMC_YOSEMITE is not set
+# CONFIG_DDB5074 is not set
+# CONFIG_DDB5476 is not set
+# CONFIG_DDB5477 is not set
+# CONFIG_NEC_OSPREY is not set
+# CONFIG_SGI_IP22 is not set
+# CONFIG_SGI_IP32 is not set
+# CONFIG_SOC_AU1X00 is not set
+# CONFIG_SIBYTE_SB1xxx_SOC is not set
+# CONFIG_SNI_RM200_PCI is not set
+# CONFIG_TOSHIBA_RBTX4927 is not set
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_HAVE_DEC_LOCK=y
+CONFIG_CPU_LITTLE_ENDIAN=y
+CONFIG_MIPS_L1_CACHE_SHIFT=5
+# CONFIG_FB is not set
+
+#
+# CPU selection
+#
+CONFIG_CPU_MIPS32=y
+# CONFIG_CPU_MIPS64 is not set
+# CONFIG_CPU_R3000 is not set
+# CONFIG_CPU_TX39XX is not set
+# CONFIG_CPU_VR41XX is not set
+# CONFIG_CPU_R4300 is not set
+# CONFIG_CPU_R4X00 is not set
+# CONFIG_CPU_TX49XX is not set
+# CONFIG_CPU_R5000 is not set
+# CONFIG_CPU_R5432 is not set
+# CONFIG_CPU_R6000 is not set
+# CONFIG_CPU_NEVADA is not set
+# CONFIG_CPU_R8000 is not set
+# CONFIG_CPU_R10000 is not set
+# CONFIG_CPU_RM7000 is not set
+# CONFIG_CPU_RM9000 is not set
+# CONFIG_CPU_SB1 is not set
+CONFIG_PAGE_SIZE_4KB=y
+# CONFIG_PAGE_SIZE_16KB is not set
+# CONFIG_PAGE_SIZE_64KB is not set
+CONFIG_CPU_HAS_PREFETCH=y
+# CONFIG_VTAG_ICACHE is not set
+# CONFIG_64BIT_PHYS_ADDR is not set
+# CONFIG_CPU_ADVANCED is not set
+CONFIG_CPU_HAS_LLSC=y
+CONFIG_CPU_HAS_SYNC=y
+# CONFIG_PREEMPT is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+
+#
+# Bus options (PCI, PCMCIA, EISA, ISA, TC)
+#
+CONFIG_MMU=y
+CONFIG_HOTPLUG=y
+
+#
+# PCMCIA/CardBus support
+#
+CONFIG_PCMCIA=m
+# CONFIG_TCIC is not set
+
+#
+# PCI Hotplug Support
+#
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_MISC is not set
+CONFIG_TRAD_SIGNALS=y
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+# CONFIG_FW_LOADER is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+CONFIG_BLK_DEV_LOOP=y
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_RAM is not set
+# CONFIG_BLK_DEV_INITRD is not set
+# CONFIG_LBD is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_SCSI is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+
+#
+# IEEE 1394 (FireWire) support (EXPERIMENTAL)
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+
+#
+# Macintosh device drivers
+#
+
+#
+# Networking support
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+CONFIG_NETLINK_DEV=y
+CONFIG_UNIX=y
+CONFIG_NET_KEY=y
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_PNP=y
+# CONFIG_IP_PNP_DHCP is not set
+CONFIG_IP_PNP_BOOTP=y
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_IP_MROUTE is not set
+# CONFIG_ARPD is not set
+# CONFIG_INET_ECN is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+
+#
+# IP: Virtual Server Configuration
+#
+# CONFIG_IP_VS is not set
+# CONFIG_IPV6 is not set
+# CONFIG_DECNET is not set
+# CONFIG_BRIDGE is not set
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
+
+#
+# IP: Netfilter Configuration
+#
+# CONFIG_IP_NF_CONNTRACK is not set
+# CONFIG_IP_NF_QUEUE is not set
+# CONFIG_IP_NF_IPTABLES is not set
+# CONFIG_IP_NF_ARPTABLES is not set
+# CONFIG_IP_NF_COMPAT_IPCHAINS is not set
+# CONFIG_IP_NF_COMPAT_IPFWADM is not set
+CONFIG_XFRM=y
+# CONFIG_XFRM_USER is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+CONFIG_IPV6_SCTP__=y
+# CONFIG_IP_SCTP is not set
+# CONFIG_ATM is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_FASTROUTE is not set
+# CONFIG_NET_HW_FLOWCONTROL is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+# CONFIG_ETHERTAP is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+# CONFIG_MII is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+
+#
+# Ethernet (10000 Mbit)
+#
+CONFIG_PPP=m
+CONFIG_PPP_MULTILINK=y
+# CONFIG_PPP_FILTER is not set
+CONFIG_PPP_ASYNC=m
+# CONFIG_PPP_SYNC_TTY is not set
+CONFIG_PPP_DEFLATE=m
+# CONFIG_PPP_BSDCOMP is not set
+CONFIG_PPPOE=m
+# CONFIG_SLIP is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Token Ring devices
+#
+# CONFIG_SHAPER is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+
+#
+# PCMCIA network device support
+#
+CONFIG_NET_PCMCIA=y
+CONFIG_PCMCIA_3C589=m
+# CONFIG_PCMCIA_3C574 is not set
+# CONFIG_PCMCIA_FMVJ18X is not set
+# CONFIG_PCMCIA_PCNET is not set
+# CONFIG_PCMCIA_NMCLAN is not set
+# CONFIG_PCMCIA_SMC91C92 is not set
+# CONFIG_PCMCIA_XIRC2PS is not set
+# CONFIG_PCMCIA_AXNET is not set
+
+#
+# Amateur Radio support
+#
+# CONFIG_HAMRADIO is not set
+
+#
+# IrDA (infrared) support
+#
+# CONFIG_IRDA is not set
+
+#
+# Bluetooth support
+#
+# CONFIG_BT is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN_BOOL is not set
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+CONFIG_INPUT_MOUSEDEV_PSAUX=y
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input I/O drivers
+#
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+CONFIG_SERIO=y
+# CONFIG_SERIO_I8042 is not set
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_CT82C710 is not set
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_UNIX98_PTYS=y
+CONFIG_UNIX98_PTY_COUNT=256
+
+#
+# Mice
+#
+# CONFIG_BUSMOUSE is not set
+# CONFIG_QIC02_TAPE is not set
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_NVRAM is not set
+CONFIG_RTC=y
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_FTAPE is not set
+# CONFIG_AGP is not set
+# CONFIG_DRM is not set
+
+#
+# PCMCIA character devices
+#
+# CONFIG_SYNCLINK_CS is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+# CONFIG_MDA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+CONFIG_EXT2_FS_XATTR=y
+CONFIG_EXT2_FS_POSIX_ACL=y
+# CONFIG_EXT2_FS_SECURITY is not set
+CONFIG_EXT3_FS=y
+CONFIG_EXT3_FS_XATTR=y
+CONFIG_EXT3_FS_POSIX_ACL=y
+CONFIG_EXT3_FS_SECURITY=y
+CONFIG_JBD=y
+# CONFIG_JBD_DEBUG is not set
+CONFIG_FS_MBCACHE=y
+CONFIG_REISERFS_FS=m
+# CONFIG_REISERFS_CHECK is not set
+# CONFIG_REISERFS_PROC_INFO is not set
+# CONFIG_JFS_FS is not set
+CONFIG_FS_POSIX_ACL=y
+# CONFIG_XFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_QUOTA is not set
+CONFIG_AUTOFS_FS=m
+CONFIG_AUTOFS4_FS=m
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_FAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+# CONFIG_DEVFS_FS is not set
+CONFIG_DEVPTS_FS=y
+CONFIG_DEVPTS_FS_XATTR=y
+CONFIG_DEVPTS_FS_SECURITY=y
+CONFIG_TMPFS=y
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+CONFIG_CRAMFS=m
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+# CONFIG_NFS_V3 is not set
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
+CONFIG_NFSD=m
+# CONFIG_NFSD_V3 is not set
+# CONFIG_NFSD_TCP is not set
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+CONFIG_EXPORTFS=m
+CONFIG_SUNRPC=y
+# CONFIG_SUNRPC_GSS is not set
+CONFIG_SMB_FS=m
+# CONFIG_SMB_NLS_DEFAULT is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_INTERMEZZO_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+
+#
+# Native Language Support
+#
+CONFIG_NLS=m
+CONFIG_NLS_DEFAULT="iso8859-1"
+# CONFIG_NLS_CODEPAGE_437 is not set
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ISO8859_1 is not set
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+# CONFIG_NLS_UTF8 is not set
+
+#
+# Kernel hacking
+#
+CONFIG_CROSSCOMPILE=y
+CONFIG_CMDLINE=""
+# CONFIG_DEBUG_KERNEL is not set
+
+#
+# Security options
+#
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+CONFIG_CRYPTO=y
+CONFIG_CRYPTO_HMAC=y
+CONFIG_CRYPTO_NULL=y
+# CONFIG_CRYPTO_MD4 is not set
+# CONFIG_CRYPTO_MD5 is not set
+# CONFIG_CRYPTO_SHA1 is not set
+# CONFIG_CRYPTO_SHA256 is not set
+CONFIG_CRYPTO_SHA512=y
+# CONFIG_CRYPTO_DES is not set
+# CONFIG_CRYPTO_BLOWFISH is not set
+CONFIG_CRYPTO_TWOFISH=y
+# CONFIG_CRYPTO_SERPENT is not set
+CONFIG_CRYPTO_AES=y
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+CONFIG_CRYPTO_DEFLATE=y
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Library routines
+#
+CONFIG_CRC32=y
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
--- diff/arch/mips/configs/ocelot_defconfig	1970-01-01 01:00:00.000000000 +0100
+++ source/arch/mips/configs/ocelot_defconfig	2004-02-23 13:56:38.000000000 +0000
@@ -0,0 +1,563 @@
+#
+# Automatically generated make config: don't edit
+#
+CONFIG_MIPS=y
+# CONFIG_MIPS64 is not set
+# CONFIG_64BIT is not set
+CONFIG_MIPS32=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_CLEAN_COMPILE=y
+CONFIG_STANDALONE=y
+CONFIG_BROKEN_ON_SMP=y
+
+#
+# General setup
+#
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_IKCONFIG is not set
+CONFIG_EMBEDDED=y
+CONFIG_KALLSYMS=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+
+#
+# Loadable module support
+#
+# CONFIG_MODULES is not set
+
+#
+# Machine selection
+#
+# CONFIG_MACH_JAZZ is not set
+# CONFIG_BAGET_MIPS is not set
+# CONFIG_MACH_VR41XX is not set
+# CONFIG_TOSHIBA_JMR3927 is not set
+# CONFIG_MIPS_COBALT is not set
+# CONFIG_MACH_DECSTATION is not set
+# CONFIG_MIPS_EV64120 is not set
+# CONFIG_MIPS_EV96100 is not set
+# CONFIG_MIPS_IVR is not set
+# CONFIG_LASAT is not set
+# CONFIG_HP_LASERJET is not set
+# CONFIG_MIPS_ITE8172 is not set
+# CONFIG_MIPS_ATLAS is not set
+# CONFIG_MIPS_MALTA is not set
+# CONFIG_MIPS_SEAD is not set
+CONFIG_MOMENCO_OCELOT=y
+# CONFIG_MOMENCO_OCELOT_G is not set
+# CONFIG_MOMENCO_OCELOT_C is not set
+# CONFIG_MOMENCO_JAGUAR_ATX is not set
+# CONFIG_PMC_YOSEMITE is not set
+# CONFIG_DDB5074 is not set
+# CONFIG_DDB5476 is not set
+# CONFIG_DDB5477 is not set
+# CONFIG_NEC_OSPREY is not set
+# CONFIG_SGI_IP22 is not set
+# CONFIG_SGI_IP32 is not set
+# CONFIG_SOC_AU1X00 is not set
+# CONFIG_SIBYTE_SB1xxx_SOC is not set
+# CONFIG_SNI_RM200_PCI is not set
+# CONFIG_TOSHIBA_RBTX4927 is not set
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_HAVE_DEC_LOCK=y
+CONFIG_DMA_NONCOHERENT=y
+# CONFIG_CPU_LITTLE_ENDIAN is not set
+CONFIG_IRQ_CPU=y
+CONFIG_IRQ_CPU_RM7K=y
+CONFIG_MIPS_GT64120=y
+CONFIG_SWAP_IO_SPACE=y
+# CONFIG_SYSCLK_75 is not set
+# CONFIG_SYSCLK_83 is not set
+CONFIG_SYSCLK_100=y
+CONFIG_MIPS_L1_CACHE_SHIFT=5
+# CONFIG_FB is not set
+CONFIG_BOARD_SCACHE=y
+
+#
+# CPU selection
+#
+# CONFIG_CPU_MIPS32 is not set
+# CONFIG_CPU_MIPS64 is not set
+# CONFIG_CPU_R3000 is not set
+# CONFIG_CPU_TX39XX is not set
+# CONFIG_CPU_VR41XX is not set
+# CONFIG_CPU_R4300 is not set
+# CONFIG_CPU_R4X00 is not set
+# CONFIG_CPU_TX49XX is not set
+# CONFIG_CPU_R5000 is not set
+# CONFIG_CPU_R5432 is not set
+# CONFIG_CPU_R6000 is not set
+# CONFIG_CPU_NEVADA is not set
+# CONFIG_CPU_R8000 is not set
+# CONFIG_CPU_R10000 is not set
+CONFIG_CPU_RM7000=y
+# CONFIG_CPU_RM9000 is not set
+# CONFIG_CPU_SB1 is not set
+CONFIG_PAGE_SIZE_4KB=y
+# CONFIG_PAGE_SIZE_16KB is not set
+# CONFIG_PAGE_SIZE_64KB is not set
+CONFIG_CPU_HAS_PREFETCH=y
+# CONFIG_64BIT_PHYS_ADDR is not set
+# CONFIG_CPU_ADVANCED is not set
+CONFIG_CPU_HAS_LLSC=y
+CONFIG_CPU_HAS_LLDSCD=y
+CONFIG_CPU_HAS_SYNC=y
+# CONFIG_PREEMPT is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+
+#
+# Bus options (PCI, PCMCIA, EISA, ISA, TC)
+#
+# CONFIG_PCI is not set
+CONFIG_MMU=y
+# CONFIG_HOTPLUG is not set
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_MISC is not set
+CONFIG_TRAD_SIGNALS=y
+# CONFIG_BINFMT_IRIX is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+# CONFIG_BLK_DEV_LOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_RAM is not set
+# CONFIG_BLK_DEV_INITRD is not set
+# CONFIG_LBD is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_SCSI is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+
+#
+# IEEE 1394 (FireWire) support (EXPERIMENTAL)
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+
+#
+# Macintosh device drivers
+#
+
+#
+# Networking support
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+# CONFIG_PACKET is not set
+CONFIG_NETLINK_DEV=y
+CONFIG_UNIX=y
+CONFIG_NET_KEY=y
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_PNP=y
+# CONFIG_IP_PNP_DHCP is not set
+CONFIG_IP_PNP_BOOTP=y
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_ARPD is not set
+# CONFIG_INET_ECN is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_IPV6 is not set
+# CONFIG_DECNET is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_NETFILTER is not set
+CONFIG_XFRM=y
+# CONFIG_XFRM_USER is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+CONFIG_IPV6_SCTP__=y
+# CONFIG_IP_SCTP is not set
+# CONFIG_ATM is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_FASTROUTE is not set
+# CONFIG_NET_HW_FLOWCONTROL is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+# CONFIG_ETHERTAP is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+# CONFIG_MII is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+
+#
+# Ethernet (10000 Mbit)
+#
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Token Ring devices
+#
+# CONFIG_SHAPER is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+
+#
+# Amateur Radio support
+#
+# CONFIG_HAMRADIO is not set
+
+#
+# IrDA (infrared) support
+#
+# CONFIG_IRDA is not set
+
+#
+# Bluetooth support
+#
+# CONFIG_BT is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN_BOOL is not set
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+CONFIG_INPUT_MOUSEDEV_PSAUX=y
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+# CONFIG_INPUT_EVDEV is not set
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input I/O drivers
+#
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+CONFIG_SERIO=y
+# CONFIG_SERIO_I8042 is not set
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_CT82C710 is not set
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=4
+# CONFIG_SERIAL_8250_EXTENDED is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+CONFIG_UNIX98_PTY_COUNT=256
+
+#
+# Mice
+#
+# CONFIG_BUSMOUSE is not set
+# CONFIG_QIC02_TAPE is not set
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_NVRAM is not set
+# CONFIG_RTC is not set
+# CONFIG_GEN_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_FTAPE is not set
+# CONFIG_AGP is not set
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+# CONFIG_MDA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_JBD is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_QUOTA is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_FAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+# CONFIG_DEVFS_FS is not set
+CONFIG_DEVPTS_FS=y
+CONFIG_DEVPTS_FS_XATTR=y
+CONFIG_DEVPTS_FS_SECURITY=y
+# CONFIG_TMPFS is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+# CONFIG_NFS_V3 is not set
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
+CONFIG_NFSD=y
+# CONFIG_NFSD_V3 is not set
+# CONFIG_NFSD_TCP is not set
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+CONFIG_EXPORTFS=y
+CONFIG_SUNRPC=y
+# CONFIG_SUNRPC_GSS is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_INTERMEZZO_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+
+#
+# Native Language Support
+#
+# CONFIG_NLS is not set
+
+#
+# Kernel hacking
+#
+CONFIG_CROSSCOMPILE=y
+CONFIG_CMDLINE=""
+# CONFIG_DEBUG_KERNEL is not set
+
+#
+# Security options
+#
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
+# Library routines
+#
+# CONFIG_CRC32 is not set
--- diff/arch/mips/configs/osprey_defconfig	1970-01-01 01:00:00.000000000 +0100
+++ source/arch/mips/configs/osprey_defconfig	2004-02-23 13:56:38.000000000 +0000
@@ -0,0 +1,558 @@
+#
+# Automatically generated make config: don't edit
+#
+CONFIG_MIPS=y
+# CONFIG_MIPS64 is not set
+# CONFIG_64BIT is not set
+CONFIG_MIPS32=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_CLEAN_COMPILE=y
+CONFIG_STANDALONE=y
+CONFIG_BROKEN_ON_SMP=y
+
+#
+# General setup
+#
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_IKCONFIG is not set
+CONFIG_EMBEDDED=y
+CONFIG_KALLSYMS=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+CONFIG_OBSOLETE_MODPARM=y
+CONFIG_MODVERSIONS=y
+CONFIG_KMOD=y
+
+#
+# Machine selection
+#
+# CONFIG_MACH_JAZZ is not set
+# CONFIG_BAGET_MIPS is not set
+# CONFIG_MACH_VR41XX is not set
+# CONFIG_TOSHIBA_JMR3927 is not set
+# CONFIG_MIPS_COBALT is not set
+# CONFIG_MACH_DECSTATION is not set
+# CONFIG_MIPS_EV64120 is not set
+# CONFIG_MIPS_EV96100 is not set
+# CONFIG_MIPS_IVR is not set
+# CONFIG_LASAT is not set
+# CONFIG_HP_LASERJET is not set
+# CONFIG_MIPS_ITE8172 is not set
+# CONFIG_MIPS_ATLAS is not set
+# CONFIG_MIPS_MALTA is not set
+# CONFIG_MIPS_SEAD is not set
+# CONFIG_MOMENCO_OCELOT is not set
+# CONFIG_MOMENCO_OCELOT_G is not set
+# CONFIG_MOMENCO_OCELOT_C is not set
+# CONFIG_MOMENCO_JAGUAR_ATX is not set
+# CONFIG_PMC_YOSEMITE is not set
+# CONFIG_DDB5074 is not set
+# CONFIG_DDB5476 is not set
+# CONFIG_DDB5477 is not set
+CONFIG_NEC_OSPREY=y
+# CONFIG_SGI_IP22 is not set
+# CONFIG_SGI_IP32 is not set
+# CONFIG_SOC_AU1X00 is not set
+# CONFIG_SIBYTE_SB1xxx_SOC is not set
+# CONFIG_SNI_RM200_PCI is not set
+# CONFIG_TOSHIBA_RBTX4927 is not set
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_HAVE_DEC_LOCK=y
+CONFIG_DMA_NONCOHERENT=y
+CONFIG_CPU_LITTLE_ENDIAN=y
+CONFIG_IRQ_CPU=y
+CONFIG_DUMMY_KEYB=y
+CONFIG_MIPS_L1_CACHE_SHIFT=5
+# CONFIG_FB is not set
+CONFIG_VR4181=y
+
+#
+# CPU selection
+#
+# CONFIG_CPU_MIPS32 is not set
+# CONFIG_CPU_MIPS64 is not set
+# CONFIG_CPU_R3000 is not set
+# CONFIG_CPU_TX39XX is not set
+CONFIG_CPU_VR41XX=y
+# CONFIG_CPU_R4300 is not set
+# CONFIG_CPU_R4X00 is not set
+# CONFIG_CPU_TX49XX is not set
+# CONFIG_CPU_R5000 is not set
+# CONFIG_CPU_R5432 is not set
+# CONFIG_CPU_R6000 is not set
+# CONFIG_CPU_NEVADA is not set
+# CONFIG_CPU_R8000 is not set
+# CONFIG_CPU_R10000 is not set
+# CONFIG_CPU_RM7000 is not set
+# CONFIG_CPU_RM9000 is not set
+# CONFIG_CPU_SB1 is not set
+CONFIG_PAGE_SIZE_4KB=y
+# CONFIG_PAGE_SIZE_16KB is not set
+# CONFIG_PAGE_SIZE_64KB is not set
+# CONFIG_CPU_ADVANCED is not set
+CONFIG_CPU_HAS_SYNC=y
+# CONFIG_PREEMPT is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+
+#
+# Bus options (PCI, PCMCIA, EISA, ISA, TC)
+#
+CONFIG_MMU=y
+# CONFIG_HOTPLUG is not set
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_MISC is not set
+CONFIG_TRAD_SIGNALS=y
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+# CONFIG_BLK_DEV_LOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_RAM is not set
+# CONFIG_BLK_DEV_INITRD is not set
+# CONFIG_LBD is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_SCSI is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+
+#
+# IEEE 1394 (FireWire) support (EXPERIMENTAL)
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+
+#
+# Macintosh device drivers
+#
+
+#
+# Networking support
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+CONFIG_NETLINK_DEV=y
+CONFIG_UNIX=y
+CONFIG_NET_KEY=y
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_PNP=y
+# CONFIG_IP_PNP_DHCP is not set
+CONFIG_IP_PNP_BOOTP=y
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_ARPD is not set
+# CONFIG_INET_ECN is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_IPV6 is not set
+# CONFIG_DECNET is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_NETFILTER is not set
+CONFIG_XFRM=y
+# CONFIG_XFRM_USER is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+CONFIG_IPV6_SCTP__=y
+# CONFIG_IP_SCTP is not set
+# CONFIG_ATM is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_FASTROUTE is not set
+# CONFIG_NET_HW_FLOWCONTROL is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+# CONFIG_ETHERTAP is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+# CONFIG_MII is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+
+#
+# Ethernet (10000 Mbit)
+#
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Token Ring devices
+#
+# CONFIG_SHAPER is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+
+#
+# Amateur Radio support
+#
+# CONFIG_HAMRADIO is not set
+
+#
+# IrDA (infrared) support
+#
+# CONFIG_IRDA is not set
+
+#
+# Bluetooth support
+#
+# CONFIG_BT is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN_BOOL is not set
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+CONFIG_INPUT_MOUSEDEV_PSAUX=y
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+# CONFIG_INPUT_EVDEV is not set
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input I/O drivers
+#
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+CONFIG_SERIO=y
+# CONFIG_SERIO_I8042 is not set
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_CT82C710 is not set
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=4
+# CONFIG_SERIAL_8250_EXTENDED is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+CONFIG_UNIX98_PTY_COUNT=256
+
+#
+# Mice
+#
+# CONFIG_BUSMOUSE is not set
+# CONFIG_QIC02_TAPE is not set
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_NVRAM is not set
+# CONFIG_RTC is not set
+# CONFIG_GEN_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_FTAPE is not set
+# CONFIG_AGP is not set
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+# CONFIG_MDA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_JBD is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_QUOTA is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_FAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+# CONFIG_DEVFS_FS is not set
+CONFIG_DEVPTS_FS=y
+CONFIG_DEVPTS_FS_XATTR=y
+CONFIG_DEVPTS_FS_SECURITY=y
+# CONFIG_TMPFS is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+# CONFIG_NFS_V3 is not set
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
+CONFIG_NFSD=y
+# CONFIG_NFSD_V3 is not set
+# CONFIG_NFSD_TCP is not set
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+CONFIG_EXPORTFS=y
+CONFIG_SUNRPC=y
+# CONFIG_SUNRPC_GSS is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_INTERMEZZO_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+
+#
+# Native Language Support
+#
+# CONFIG_NLS is not set
+
+#
+# Kernel hacking
+#
+CONFIG_CROSSCOMPILE=y
+CONFIG_CMDLINE="ip=bootp ether=46,0x03fe0300,eth0"
+# CONFIG_DEBUG_KERNEL is not set
+
+#
+# Security options
+#
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
+# Library routines
+#
+# CONFIG_CRC32 is not set
--- diff/arch/mips/configs/pb1000_defconfig	1970-01-01 01:00:00.000000000 +0100
+++ source/arch/mips/configs/pb1000_defconfig	2004-02-23 13:56:38.000000000 +0000
@@ -0,0 +1,673 @@
+#
+# Automatically generated make config: don't edit
+#
+CONFIG_MIPS=y
+# CONFIG_MIPS64 is not set
+# CONFIG_64BIT is not set
+CONFIG_MIPS32=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_CLEAN_COMPILE=y
+CONFIG_STANDALONE=y
+CONFIG_BROKEN_ON_SMP=y
+
+#
+# General setup
+#
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_IKCONFIG is not set
+CONFIG_EMBEDDED=y
+CONFIG_KALLSYMS=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+CONFIG_OBSOLETE_MODPARM=y
+CONFIG_MODVERSIONS=y
+CONFIG_KMOD=y
+
+#
+# Machine selection
+#
+# CONFIG_MACH_JAZZ is not set
+# CONFIG_BAGET_MIPS is not set
+# CONFIG_MACH_VR41XX is not set
+# CONFIG_TOSHIBA_JMR3927 is not set
+# CONFIG_MIPS_COBALT is not set
+# CONFIG_MACH_DECSTATION is not set
+# CONFIG_MIPS_EV64120 is not set
+# CONFIG_MIPS_EV96100 is not set
+# CONFIG_MIPS_IVR is not set
+# CONFIG_LASAT is not set
+# CONFIG_HP_LASERJET is not set
+# CONFIG_MIPS_ITE8172 is not set
+# CONFIG_MIPS_ATLAS is not set
+# CONFIG_MIPS_MALTA is not set
+# CONFIG_MIPS_SEAD is not set
+# CONFIG_MOMENCO_OCELOT is not set
+# CONFIG_MOMENCO_OCELOT_G is not set
+# CONFIG_MOMENCO_OCELOT_C is not set
+# CONFIG_MOMENCO_JAGUAR_ATX is not set
+# CONFIG_PMC_YOSEMITE is not set
+# CONFIG_DDB5074 is not set
+# CONFIG_DDB5476 is not set
+# CONFIG_DDB5477 is not set
+# CONFIG_NEC_OSPREY is not set
+# CONFIG_SGI_IP22 is not set
+# CONFIG_SGI_IP32 is not set
+# CONFIG_SOC_AU1X00 is not set
+# CONFIG_SIBYTE_SB1xxx_SOC is not set
+# CONFIG_SNI_RM200_PCI is not set
+# CONFIG_TOSHIBA_RBTX4927 is not set
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_HAVE_DEC_LOCK=y
+CONFIG_CPU_LITTLE_ENDIAN=y
+CONFIG_MIPS_L1_CACHE_SHIFT=5
+# CONFIG_FB is not set
+
+#
+# CPU selection
+#
+CONFIG_CPU_MIPS32=y
+# CONFIG_CPU_MIPS64 is not set
+# CONFIG_CPU_R3000 is not set
+# CONFIG_CPU_TX39XX is not set
+# CONFIG_CPU_VR41XX is not set
+# CONFIG_CPU_R4300 is not set
+# CONFIG_CPU_R4X00 is not set
+# CONFIG_CPU_TX49XX is not set
+# CONFIG_CPU_R5000 is not set
+# CONFIG_CPU_R5432 is not set
+# CONFIG_CPU_R6000 is not set
+# CONFIG_CPU_NEVADA is not set
+# CONFIG_CPU_R8000 is not set
+# CONFIG_CPU_R10000 is not set
+# CONFIG_CPU_RM7000 is not set
+# CONFIG_CPU_RM9000 is not set
+# CONFIG_CPU_SB1 is not set
+CONFIG_PAGE_SIZE_4KB=y
+# CONFIG_PAGE_SIZE_16KB is not set
+# CONFIG_PAGE_SIZE_64KB is not set
+CONFIG_CPU_HAS_PREFETCH=y
+# CONFIG_VTAG_ICACHE is not set
+# CONFIG_64BIT_PHYS_ADDR is not set
+# CONFIG_CPU_ADVANCED is not set
+CONFIG_CPU_HAS_LLSC=y
+CONFIG_CPU_HAS_SYNC=y
+# CONFIG_PREEMPT is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+
+#
+# Bus options (PCI, PCMCIA, EISA, ISA, TC)
+#
+CONFIG_MMU=y
+CONFIG_HOTPLUG=y
+
+#
+# PCMCIA/CardBus support
+#
+CONFIG_PCMCIA=m
+# CONFIG_TCIC is not set
+
+#
+# PCI Hotplug Support
+#
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_MISC is not set
+CONFIG_TRAD_SIGNALS=y
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+# CONFIG_FW_LOADER is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+CONFIG_BLK_DEV_LOOP=y
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_RAM is not set
+# CONFIG_BLK_DEV_INITRD is not set
+# CONFIG_LBD is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_SCSI is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+
+#
+# IEEE 1394 (FireWire) support (EXPERIMENTAL)
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+
+#
+# Macintosh device drivers
+#
+
+#
+# Networking support
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+CONFIG_NETLINK_DEV=y
+CONFIG_UNIX=y
+CONFIG_NET_KEY=y
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_PNP=y
+# CONFIG_IP_PNP_DHCP is not set
+CONFIG_IP_PNP_BOOTP=y
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_IP_MROUTE is not set
+# CONFIG_ARPD is not set
+# CONFIG_INET_ECN is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+
+#
+# IP: Virtual Server Configuration
+#
+# CONFIG_IP_VS is not set
+# CONFIG_IPV6 is not set
+# CONFIG_DECNET is not set
+# CONFIG_BRIDGE is not set
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
+
+#
+# IP: Netfilter Configuration
+#
+# CONFIG_IP_NF_CONNTRACK is not set
+# CONFIG_IP_NF_QUEUE is not set
+# CONFIG_IP_NF_IPTABLES is not set
+# CONFIG_IP_NF_ARPTABLES is not set
+# CONFIG_IP_NF_COMPAT_IPCHAINS is not set
+# CONFIG_IP_NF_COMPAT_IPFWADM is not set
+CONFIG_XFRM=y
+# CONFIG_XFRM_USER is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+CONFIG_IPV6_SCTP__=y
+# CONFIG_IP_SCTP is not set
+# CONFIG_ATM is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_FASTROUTE is not set
+# CONFIG_NET_HW_FLOWCONTROL is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+# CONFIG_ETHERTAP is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+# CONFIG_MII is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+
+#
+# Ethernet (10000 Mbit)
+#
+CONFIG_PPP=m
+CONFIG_PPP_MULTILINK=y
+# CONFIG_PPP_FILTER is not set
+CONFIG_PPP_ASYNC=m
+# CONFIG_PPP_SYNC_TTY is not set
+CONFIG_PPP_DEFLATE=m
+# CONFIG_PPP_BSDCOMP is not set
+CONFIG_PPPOE=m
+# CONFIG_SLIP is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Token Ring devices
+#
+# CONFIG_SHAPER is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+
+#
+# PCMCIA network device support
+#
+CONFIG_NET_PCMCIA=y
+CONFIG_PCMCIA_3C589=m
+# CONFIG_PCMCIA_3C574 is not set
+# CONFIG_PCMCIA_FMVJ18X is not set
+# CONFIG_PCMCIA_PCNET is not set
+# CONFIG_PCMCIA_NMCLAN is not set
+# CONFIG_PCMCIA_SMC91C92 is not set
+# CONFIG_PCMCIA_XIRC2PS is not set
+# CONFIG_PCMCIA_AXNET is not set
+
+#
+# Amateur Radio support
+#
+# CONFIG_HAMRADIO is not set
+
+#
+# IrDA (infrared) support
+#
+# CONFIG_IRDA is not set
+
+#
+# Bluetooth support
+#
+# CONFIG_BT is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN_BOOL is not set
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+CONFIG_INPUT_MOUSEDEV_PSAUX=y
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input I/O drivers
+#
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+CONFIG_SERIO=y
+# CONFIG_SERIO_I8042 is not set
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_CT82C710 is not set
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_UNIX98_PTYS=y
+CONFIG_UNIX98_PTY_COUNT=256
+
+#
+# Mice
+#
+# CONFIG_BUSMOUSE is not set
+# CONFIG_QIC02_TAPE is not set
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_NVRAM is not set
+CONFIG_RTC=y
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_FTAPE is not set
+# CONFIG_AGP is not set
+# CONFIG_DRM is not set
+
+#
+# PCMCIA character devices
+#
+# CONFIG_SYNCLINK_CS is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+# CONFIG_MDA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+CONFIG_EXT2_FS_XATTR=y
+CONFIG_EXT2_FS_POSIX_ACL=y
+# CONFIG_EXT2_FS_SECURITY is not set
+CONFIG_EXT3_FS=y
+CONFIG_EXT3_FS_XATTR=y
+CONFIG_EXT3_FS_POSIX_ACL=y
+CONFIG_EXT3_FS_SECURITY=y
+CONFIG_JBD=y
+# CONFIG_JBD_DEBUG is not set
+CONFIG_FS_MBCACHE=y
+CONFIG_REISERFS_FS=m
+# CONFIG_REISERFS_CHECK is not set
+# CONFIG_REISERFS_PROC_INFO is not set
+# CONFIG_JFS_FS is not set
+CONFIG_FS_POSIX_ACL=y
+# CONFIG_XFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_QUOTA is not set
+CONFIG_AUTOFS_FS=m
+CONFIG_AUTOFS4_FS=m
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_FAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+# CONFIG_DEVFS_FS is not set
+CONFIG_DEVPTS_FS=y
+CONFIG_DEVPTS_FS_XATTR=y
+CONFIG_DEVPTS_FS_SECURITY=y
+CONFIG_TMPFS=y
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+CONFIG_CRAMFS=m
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+# CONFIG_NFS_V3 is not set
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
+CONFIG_NFSD=m
+# CONFIG_NFSD_V3 is not set
+# CONFIG_NFSD_TCP is not set
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+CONFIG_EXPORTFS=m
+CONFIG_SUNRPC=y
+# CONFIG_SUNRPC_GSS is not set
+CONFIG_SMB_FS=m
+# CONFIG_SMB_NLS_DEFAULT is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_INTERMEZZO_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+
+#
+# Native Language Support
+#
+CONFIG_NLS=m
+CONFIG_NLS_DEFAULT="iso8859-1"
+# CONFIG_NLS_CODEPAGE_437 is not set
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ISO8859_1 is not set
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+# CONFIG_NLS_UTF8 is not set
+
+#
+# Kernel hacking
+#
+CONFIG_CROSSCOMPILE=y
+CONFIG_CMDLINE=""
+# CONFIG_DEBUG_KERNEL is not set
+
+#
+# Security options
+#
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+CONFIG_CRYPTO=y
+CONFIG_CRYPTO_HMAC=y
+CONFIG_CRYPTO_NULL=y
+# CONFIG_CRYPTO_MD4 is not set
+# CONFIG_CRYPTO_MD5 is not set
+# CONFIG_CRYPTO_SHA1 is not set
+# CONFIG_CRYPTO_SHA256 is not set
+CONFIG_CRYPTO_SHA512=y
+# CONFIG_CRYPTO_DES is not set
+# CONFIG_CRYPTO_BLOWFISH is not set
+CONFIG_CRYPTO_TWOFISH=y
+# CONFIG_CRYPTO_SERPENT is not set
+CONFIG_CRYPTO_AES=y
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+CONFIG_CRYPTO_DEFLATE=y
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Library routines
+#
+CONFIG_CRC32=y
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
--- diff/arch/mips/configs/pb1100_defconfig	1970-01-01 01:00:00.000000000 +0100
+++ source/arch/mips/configs/pb1100_defconfig	2004-02-23 13:56:38.000000000 +0000
@@ -0,0 +1,673 @@
+#
+# Automatically generated make config: don't edit
+#
+CONFIG_MIPS=y
+# CONFIG_MIPS64 is not set
+# CONFIG_64BIT is not set
+CONFIG_MIPS32=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_CLEAN_COMPILE=y
+CONFIG_STANDALONE=y
+CONFIG_BROKEN_ON_SMP=y
+
+#
+# General setup
+#
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_IKCONFIG is not set
+CONFIG_EMBEDDED=y
+CONFIG_KALLSYMS=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+CONFIG_OBSOLETE_MODPARM=y
+CONFIG_MODVERSIONS=y
+CONFIG_KMOD=y
+
+#
+# Machine selection
+#
+# CONFIG_MACH_JAZZ is not set
+# CONFIG_BAGET_MIPS is not set
+# CONFIG_MACH_VR41XX is not set
+# CONFIG_TOSHIBA_JMR3927 is not set
+# CONFIG_MIPS_COBALT is not set
+# CONFIG_MACH_DECSTATION is not set
+# CONFIG_MIPS_EV64120 is not set
+# CONFIG_MIPS_EV96100 is not set
+# CONFIG_MIPS_IVR is not set
+# CONFIG_LASAT is not set
+# CONFIG_HP_LASERJET is not set
+# CONFIG_MIPS_ITE8172 is not set
+# CONFIG_MIPS_ATLAS is not set
+# CONFIG_MIPS_MALTA is not set
+# CONFIG_MIPS_SEAD is not set
+# CONFIG_MOMENCO_OCELOT is not set
+# CONFIG_MOMENCO_OCELOT_G is not set
+# CONFIG_MOMENCO_OCELOT_C is not set
+# CONFIG_MOMENCO_JAGUAR_ATX is not set
+# CONFIG_PMC_YOSEMITE is not set
+# CONFIG_DDB5074 is not set
+# CONFIG_DDB5476 is not set
+# CONFIG_DDB5477 is not set
+# CONFIG_NEC_OSPREY is not set
+# CONFIG_SGI_IP22 is not set
+# CONFIG_SGI_IP32 is not set
+# CONFIG_SOC_AU1X00 is not set
+# CONFIG_SIBYTE_SB1xxx_SOC is not set
+# CONFIG_SNI_RM200_PCI is not set
+# CONFIG_TOSHIBA_RBTX4927 is not set
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_HAVE_DEC_LOCK=y
+CONFIG_CPU_LITTLE_ENDIAN=y
+CONFIG_MIPS_L1_CACHE_SHIFT=5
+# CONFIG_FB is not set
+
+#
+# CPU selection
+#
+CONFIG_CPU_MIPS32=y
+# CONFIG_CPU_MIPS64 is not set
+# CONFIG_CPU_R3000 is not set
+# CONFIG_CPU_TX39XX is not set
+# CONFIG_CPU_VR41XX is not set
+# CONFIG_CPU_R4300 is not set
+# CONFIG_CPU_R4X00 is not set
+# CONFIG_CPU_TX49XX is not set
+# CONFIG_CPU_R5000 is not set
+# CONFIG_CPU_R5432 is not set
+# CONFIG_CPU_R6000 is not set
+# CONFIG_CPU_NEVADA is not set
+# CONFIG_CPU_R8000 is not set
+# CONFIG_CPU_R10000 is not set
+# CONFIG_CPU_RM7000 is not set
+# CONFIG_CPU_RM9000 is not set
+# CONFIG_CPU_SB1 is not set
+CONFIG_PAGE_SIZE_4KB=y
+# CONFIG_PAGE_SIZE_16KB is not set
+# CONFIG_PAGE_SIZE_64KB is not set
+CONFIG_CPU_HAS_PREFETCH=y
+# CONFIG_VTAG_ICACHE is not set
+# CONFIG_64BIT_PHYS_ADDR is not set
+# CONFIG_CPU_ADVANCED is not set
+CONFIG_CPU_HAS_LLSC=y
+CONFIG_CPU_HAS_SYNC=y
+# CONFIG_PREEMPT is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+
+#
+# Bus options (PCI, PCMCIA, EISA, ISA, TC)
+#
+CONFIG_MMU=y
+CONFIG_HOTPLUG=y
+
+#
+# PCMCIA/CardBus support
+#
+CONFIG_PCMCIA=m
+# CONFIG_TCIC is not set
+
+#
+# PCI Hotplug Support
+#
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_MISC is not set
+CONFIG_TRAD_SIGNALS=y
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+# CONFIG_FW_LOADER is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+CONFIG_BLK_DEV_LOOP=y
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_RAM is not set
+# CONFIG_BLK_DEV_INITRD is not set
+# CONFIG_LBD is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_SCSI is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+
+#
+# IEEE 1394 (FireWire) support (EXPERIMENTAL)
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+
+#
+# Macintosh device drivers
+#
+
+#
+# Networking support
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+CONFIG_NETLINK_DEV=y
+CONFIG_UNIX=y
+CONFIG_NET_KEY=y
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_PNP=y
+# CONFIG_IP_PNP_DHCP is not set
+CONFIG_IP_PNP_BOOTP=y
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_IP_MROUTE is not set
+# CONFIG_ARPD is not set
+# CONFIG_INET_ECN is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+
+#
+# IP: Virtual Server Configuration
+#
+# CONFIG_IP_VS is not set
+# CONFIG_IPV6 is not set
+# CONFIG_DECNET is not set
+# CONFIG_BRIDGE is not set
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
+
+#
+# IP: Netfilter Configuration
+#
+# CONFIG_IP_NF_CONNTRACK is not set
+# CONFIG_IP_NF_QUEUE is not set
+# CONFIG_IP_NF_IPTABLES is not set
+# CONFIG_IP_NF_ARPTABLES is not set
+# CONFIG_IP_NF_COMPAT_IPCHAINS is not set
+# CONFIG_IP_NF_COMPAT_IPFWADM is not set
+CONFIG_XFRM=y
+# CONFIG_XFRM_USER is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+CONFIG_IPV6_SCTP__=y
+# CONFIG_IP_SCTP is not set
+# CONFIG_ATM is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_FASTROUTE is not set
+# CONFIG_NET_HW_FLOWCONTROL is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+# CONFIG_ETHERTAP is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+# CONFIG_MII is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+
+#
+# Ethernet (10000 Mbit)
+#
+CONFIG_PPP=m
+CONFIG_PPP_MULTILINK=y
+# CONFIG_PPP_FILTER is not set
+CONFIG_PPP_ASYNC=m
+# CONFIG_PPP_SYNC_TTY is not set
+CONFIG_PPP_DEFLATE=m
+# CONFIG_PPP_BSDCOMP is not set
+CONFIG_PPPOE=m
+# CONFIG_SLIP is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Token Ring devices
+#
+# CONFIG_SHAPER is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+
+#
+# PCMCIA network device support
+#
+CONFIG_NET_PCMCIA=y
+CONFIG_PCMCIA_3C589=m
+# CONFIG_PCMCIA_3C574 is not set
+# CONFIG_PCMCIA_FMVJ18X is not set
+# CONFIG_PCMCIA_PCNET is not set
+# CONFIG_PCMCIA_NMCLAN is not set
+# CONFIG_PCMCIA_SMC91C92 is not set
+# CONFIG_PCMCIA_XIRC2PS is not set
+# CONFIG_PCMCIA_AXNET is not set
+
+#
+# Amateur Radio support
+#
+# CONFIG_HAMRADIO is not set
+
+#
+# IrDA (infrared) support
+#
+# CONFIG_IRDA is not set
+
+#
+# Bluetooth support
+#
+# CONFIG_BT is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN_BOOL is not set
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+CONFIG_INPUT_MOUSEDEV_PSAUX=y
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input I/O drivers
+#
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+CONFIG_SERIO=y
+# CONFIG_SERIO_I8042 is not set
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_CT82C710 is not set
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_UNIX98_PTYS=y
+CONFIG_UNIX98_PTY_COUNT=256
+
+#
+# Mice
+#
+# CONFIG_BUSMOUSE is not set
+# CONFIG_QIC02_TAPE is not set
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_NVRAM is not set
+CONFIG_RTC=y
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_FTAPE is not set
+# CONFIG_AGP is not set
+# CONFIG_DRM is not set
+
+#
+# PCMCIA character devices
+#
+# CONFIG_SYNCLINK_CS is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+# CONFIG_MDA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+CONFIG_EXT2_FS_XATTR=y
+CONFIG_EXT2_FS_POSIX_ACL=y
+# CONFIG_EXT2_FS_SECURITY is not set
+CONFIG_EXT3_FS=y
+CONFIG_EXT3_FS_XATTR=y
+CONFIG_EXT3_FS_POSIX_ACL=y
+CONFIG_EXT3_FS_SECURITY=y
+CONFIG_JBD=y
+# CONFIG_JBD_DEBUG is not set
+CONFIG_FS_MBCACHE=y
+CONFIG_REISERFS_FS=m
+# CONFIG_REISERFS_CHECK is not set
+# CONFIG_REISERFS_PROC_INFO is not set
+# CONFIG_JFS_FS is not set
+CONFIG_FS_POSIX_ACL=y
+# CONFIG_XFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_QUOTA is not set
+CONFIG_AUTOFS_FS=m
+CONFIG_AUTOFS4_FS=m
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_FAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+# CONFIG_DEVFS_FS is not set
+CONFIG_DEVPTS_FS=y
+CONFIG_DEVPTS_FS_XATTR=y
+CONFIG_DEVPTS_FS_SECURITY=y
+CONFIG_TMPFS=y
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+CONFIG_CRAMFS=m
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+# CONFIG_NFS_V3 is not set
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
+CONFIG_NFSD=m
+# CONFIG_NFSD_V3 is not set
+# CONFIG_NFSD_TCP is not set
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+CONFIG_EXPORTFS=m
+CONFIG_SUNRPC=y
+# CONFIG_SUNRPC_GSS is not set
+CONFIG_SMB_FS=m
+# CONFIG_SMB_NLS_DEFAULT is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_INTERMEZZO_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+
+#
+# Native Language Support
+#
+CONFIG_NLS=m
+CONFIG_NLS_DEFAULT="iso8859-1"
+# CONFIG_NLS_CODEPAGE_437 is not set
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ISO8859_1 is not set
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+# CONFIG_NLS_UTF8 is not set
+
+#
+# Kernel hacking
+#
+CONFIG_CROSSCOMPILE=y
+CONFIG_CMDLINE=""
+# CONFIG_DEBUG_KERNEL is not set
+
+#
+# Security options
+#
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+CONFIG_CRYPTO=y
+CONFIG_CRYPTO_HMAC=y
+CONFIG_CRYPTO_NULL=y
+# CONFIG_CRYPTO_MD4 is not set
+# CONFIG_CRYPTO_MD5 is not set
+# CONFIG_CRYPTO_SHA1 is not set
+# CONFIG_CRYPTO_SHA256 is not set
+CONFIG_CRYPTO_SHA512=y
+# CONFIG_CRYPTO_DES is not set
+# CONFIG_CRYPTO_BLOWFISH is not set
+CONFIG_CRYPTO_TWOFISH=y
+# CONFIG_CRYPTO_SERPENT is not set
+CONFIG_CRYPTO_AES=y
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+CONFIG_CRYPTO_DEFLATE=y
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Library routines
+#
+CONFIG_CRC32=y
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
--- diff/arch/mips/configs/pb1500_defconfig	1970-01-01 01:00:00.000000000 +0100
+++ source/arch/mips/configs/pb1500_defconfig	2004-02-23 13:56:38.000000000 +0000
@@ -0,0 +1,784 @@
+#
+# Automatically generated make config: don't edit
+#
+CONFIG_MIPS=y
+# CONFIG_MIPS64 is not set
+# CONFIG_64BIT is not set
+CONFIG_MIPS32=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_CLEAN_COMPILE=y
+CONFIG_STANDALONE=y
+CONFIG_BROKEN_ON_SMP=y
+
+#
+# General setup
+#
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_IKCONFIG is not set
+CONFIG_EMBEDDED=y
+CONFIG_KALLSYMS=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+CONFIG_OBSOLETE_MODPARM=y
+CONFIG_MODVERSIONS=y
+CONFIG_KMOD=y
+
+#
+# Machine selection
+#
+# CONFIG_MACH_JAZZ is not set
+# CONFIG_BAGET_MIPS is not set
+# CONFIG_MACH_VR41XX is not set
+# CONFIG_TOSHIBA_JMR3927 is not set
+# CONFIG_MIPS_COBALT is not set
+# CONFIG_MACH_DECSTATION is not set
+# CONFIG_MIPS_EV64120 is not set
+# CONFIG_MIPS_EV96100 is not set
+# CONFIG_MIPS_IVR is not set
+# CONFIG_LASAT is not set
+# CONFIG_HP_LASERJET is not set
+# CONFIG_MIPS_ITE8172 is not set
+# CONFIG_MIPS_ATLAS is not set
+# CONFIG_MIPS_MALTA is not set
+# CONFIG_MIPS_SEAD is not set
+# CONFIG_MOMENCO_OCELOT is not set
+# CONFIG_MOMENCO_OCELOT_G is not set
+# CONFIG_MOMENCO_OCELOT_C is not set
+# CONFIG_MOMENCO_JAGUAR_ATX is not set
+# CONFIG_PMC_YOSEMITE is not set
+# CONFIG_DDB5074 is not set
+# CONFIG_DDB5476 is not set
+# CONFIG_DDB5477 is not set
+# CONFIG_NEC_OSPREY is not set
+# CONFIG_SGI_IP22 is not set
+# CONFIG_SGI_IP32 is not set
+CONFIG_SOC_AU1X00=y
+# CONFIG_SOC_AU1000 is not set
+# CONFIG_SOC_AU1100 is not set
+CONFIG_SOC_AU1500=y
+# CONFIG_MIPS_PB1000 is not set
+# CONFIG_MIPS_PB1100 is not set
+CONFIG_MIPS_PB1500=y
+# CONFIG_MIPS_DB1000 is not set
+# CONFIG_MIPS_DB1100 is not set
+# CONFIG_MIPS_DB1500 is not set
+# CONFIG_MIPS_BOSPORUS is not set
+# CONFIG_MIPS_MIRAGE is not set
+# CONFIG_MIPS_XXS1500 is not set
+# CONFIG_MIPS_MTX1 is not set
+# CONFIG_SIBYTE_SB1xxx_SOC is not set
+# CONFIG_SNI_RM200_PCI is not set
+# CONFIG_TOSHIBA_RBTX4927 is not set
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_HAVE_DEC_LOCK=y
+CONFIG_DMA_NONCOHERENT=y
+CONFIG_CPU_LITTLE_ENDIAN=y
+# CONFIG_AU1000_USB_DEVICE is not set
+CONFIG_MIPS_L1_CACHE_SHIFT=5
+# CONFIG_FB is not set
+
+#
+# CPU selection
+#
+CONFIG_CPU_MIPS32=y
+# CONFIG_CPU_MIPS64 is not set
+# CONFIG_CPU_R3000 is not set
+# CONFIG_CPU_TX39XX is not set
+# CONFIG_CPU_VR41XX is not set
+# CONFIG_CPU_R4300 is not set
+# CONFIG_CPU_R4X00 is not set
+# CONFIG_CPU_TX49XX is not set
+# CONFIG_CPU_R5000 is not set
+# CONFIG_CPU_R5432 is not set
+# CONFIG_CPU_R6000 is not set
+# CONFIG_CPU_NEVADA is not set
+# CONFIG_CPU_R8000 is not set
+# CONFIG_CPU_R10000 is not set
+# CONFIG_CPU_RM7000 is not set
+# CONFIG_CPU_RM9000 is not set
+# CONFIG_CPU_SB1 is not set
+CONFIG_PAGE_SIZE_4KB=y
+# CONFIG_PAGE_SIZE_16KB is not set
+# CONFIG_PAGE_SIZE_64KB is not set
+CONFIG_CPU_HAS_PREFETCH=y
+# CONFIG_VTAG_ICACHE is not set
+CONFIG_64BIT_PHYS_ADDR=y
+# CONFIG_CPU_ADVANCED is not set
+CONFIG_CPU_HAS_LLSC=y
+CONFIG_CPU_HAS_SYNC=y
+# CONFIG_PREEMPT is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+
+#
+# Bus options (PCI, PCMCIA, EISA, ISA, TC)
+#
+CONFIG_PCI=y
+CONFIG_PCI_LEGACY_PROC=y
+CONFIG_PCI_NAMES=y
+CONFIG_MMU=y
+CONFIG_HOTPLUG=y
+
+#
+# PCMCIA/CardBus support
+#
+CONFIG_PCMCIA=m
+# CONFIG_YENTA is not set
+# CONFIG_I82092 is not set
+# CONFIG_TCIC is not set
+# CONFIG_PCMCIA_AU1X00 is not set
+
+#
+# PCI Hotplug Support
+#
+# CONFIG_HOTPLUG_PCI is not set
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_MISC is not set
+CONFIG_TRAD_SIGNALS=y
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+# CONFIG_FW_LOADER is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_UMEM is not set
+CONFIG_BLK_DEV_LOOP=y
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_RAM is not set
+# CONFIG_BLK_DEV_INITRD is not set
+# CONFIG_LBD is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+CONFIG_IDE=y
+CONFIG_BLK_DEV_IDE=y
+
+#
+# Please see Documentation/ide.txt for help/info on IDE drives
+#
+CONFIG_BLK_DEV_IDEDISK=y
+# CONFIG_IDEDISK_MULTI_MODE is not set
+# CONFIG_IDEDISK_STROKE is not set
+# CONFIG_BLK_DEV_IDECS is not set
+# CONFIG_BLK_DEV_IDECD is not set
+# CONFIG_BLK_DEV_IDETAPE is not set
+# CONFIG_BLK_DEV_IDEFLOPPY is not set
+# CONFIG_IDE_TASK_IOCTL is not set
+# CONFIG_IDE_TASKFILE_IO is not set
+
+#
+# IDE chipset support/bugfixes
+#
+CONFIG_IDE_GENERIC=y
+CONFIG_BLK_DEV_IDEPCI=y
+# CONFIG_IDEPCI_SHARE_IRQ is not set
+# CONFIG_BLK_DEV_OFFBOARD is not set
+CONFIG_BLK_DEV_GENERIC=y
+# CONFIG_BLK_DEV_OPTI621 is not set
+CONFIG_BLK_DEV_IDEDMA_PCI=y
+# CONFIG_BLK_DEV_IDEDMA_FORCED is not set
+# CONFIG_IDEDMA_PCI_AUTO is not set
+CONFIG_BLK_DEV_ADMA=y
+# CONFIG_BLK_DEV_AEC62XX is not set
+# CONFIG_BLK_DEV_ALI15X3 is not set
+# CONFIG_BLK_DEV_AMD74XX is not set
+# CONFIG_BLK_DEV_CMD64X is not set
+# CONFIG_BLK_DEV_TRIFLEX is not set
+# CONFIG_BLK_DEV_CY82C693 is not set
+# CONFIG_BLK_DEV_CS5520 is not set
+# CONFIG_BLK_DEV_CS5530 is not set
+# CONFIG_BLK_DEV_HPT34X is not set
+CONFIG_BLK_DEV_HPT366=y
+# CONFIG_BLK_DEV_SC1200 is not set
+# CONFIG_BLK_DEV_PIIX is not set
+# CONFIG_BLK_DEV_NS87415 is not set
+# CONFIG_BLK_DEV_PDC202XX_OLD is not set
+# CONFIG_BLK_DEV_PDC202XX_NEW is not set
+# CONFIG_BLK_DEV_SVWKS is not set
+# CONFIG_BLK_DEV_SIIMAGE is not set
+# CONFIG_BLK_DEV_SLC90E66 is not set
+# CONFIG_BLK_DEV_TRM290 is not set
+# CONFIG_BLK_DEV_VIA82CXXX is not set
+CONFIG_BLK_DEV_IDEDMA=y
+# CONFIG_IDEDMA_IVB is not set
+# CONFIG_IDEDMA_AUTO is not set
+# CONFIG_DMA_NONPCI is not set
+# CONFIG_BLK_DEV_HD is not set
+
+#
+# SCSI device support
+#
+# CONFIG_SCSI is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+
+#
+# IEEE 1394 (FireWire) support (EXPERIMENTAL)
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+
+#
+# Macintosh device drivers
+#
+
+#
+# Networking support
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+CONFIG_NETLINK_DEV=y
+CONFIG_UNIX=y
+CONFIG_NET_KEY=y
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_PNP=y
+# CONFIG_IP_PNP_DHCP is not set
+CONFIG_IP_PNP_BOOTP=y
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_IP_MROUTE is not set
+# CONFIG_ARPD is not set
+# CONFIG_INET_ECN is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+
+#
+# IP: Virtual Server Configuration
+#
+# CONFIG_IP_VS is not set
+# CONFIG_IPV6 is not set
+# CONFIG_DECNET is not set
+# CONFIG_BRIDGE is not set
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
+
+#
+# IP: Netfilter Configuration
+#
+# CONFIG_IP_NF_CONNTRACK is not set
+# CONFIG_IP_NF_QUEUE is not set
+# CONFIG_IP_NF_IPTABLES is not set
+# CONFIG_IP_NF_ARPTABLES is not set
+# CONFIG_IP_NF_COMPAT_IPCHAINS is not set
+# CONFIG_IP_NF_COMPAT_IPFWADM is not set
+CONFIG_XFRM=y
+# CONFIG_XFRM_USER is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+CONFIG_IPV6_SCTP__=y
+# CONFIG_IP_SCTP is not set
+# CONFIG_ATM is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_FASTROUTE is not set
+# CONFIG_NET_HW_FLOWCONTROL is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+CONFIG_NETDEVICES=y
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+# CONFIG_ETHERTAP is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+# CONFIG_MII is not set
+CONFIG_MIPS_AU1X00_ENET=y
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_SUNGEM is not set
+# CONFIG_NET_VENDOR_3COM is not set
+
+#
+# Tulip family network device support
+#
+# CONFIG_NET_TULIP is not set
+# CONFIG_HP100 is not set
+# CONFIG_NET_PCI is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+# CONFIG_E1000 is not set
+# CONFIG_NS83820 is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+# CONFIG_R8169 is not set
+# CONFIG_SIS190 is not set
+# CONFIG_SK98LIN is not set
+# CONFIG_TIGON3 is not set
+
+#
+# Ethernet (10000 Mbit)
+#
+# CONFIG_IXGB is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+CONFIG_PPP=m
+CONFIG_PPP_MULTILINK=y
+# CONFIG_PPP_FILTER is not set
+CONFIG_PPP_ASYNC=m
+# CONFIG_PPP_SYNC_TTY is not set
+CONFIG_PPP_DEFLATE=m
+# CONFIG_PPP_BSDCOMP is not set
+CONFIG_PPPOE=m
+# CONFIG_SLIP is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Token Ring devices
+#
+# CONFIG_TR is not set
+# CONFIG_RCPCI is not set
+# CONFIG_SHAPER is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+
+#
+# PCMCIA network device support
+#
+CONFIG_NET_PCMCIA=y
+CONFIG_PCMCIA_3C589=m
+# CONFIG_PCMCIA_3C574 is not set
+# CONFIG_PCMCIA_FMVJ18X is not set
+# CONFIG_PCMCIA_PCNET is not set
+# CONFIG_PCMCIA_NMCLAN is not set
+# CONFIG_PCMCIA_SMC91C92 is not set
+# CONFIG_PCMCIA_XIRC2PS is not set
+# CONFIG_PCMCIA_AXNET is not set
+
+#
+# Amateur Radio support
+#
+# CONFIG_HAMRADIO is not set
+
+#
+# IrDA (infrared) support
+#
+# CONFIG_IRDA is not set
+
+#
+# Bluetooth support
+#
+# CONFIG_BT is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN_BOOL is not set
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+CONFIG_INPUT_MOUSEDEV_PSAUX=y
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input I/O drivers
+#
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+CONFIG_SERIO=y
+# CONFIG_SERIO_I8042 is not set
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_CT82C710 is not set
+# CONFIG_SERIO_PCIPS2 is not set
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Character devices
+#
+# CONFIG_VT is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+# CONFIG_AU1X00_GPIO is not set
+# CONFIG_TS_AU1X00_ADS7846 is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_AU1X00=y
+CONFIG_SERIAL_AU1X00_CONSOLE=y
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+CONFIG_UNIX98_PTY_COUNT=256
+
+#
+# Mice
+#
+# CONFIG_BUSMOUSE is not set
+# CONFIG_QIC02_TAPE is not set
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_NVRAM is not set
+# CONFIG_RTC is not set
+# CONFIG_GEN_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_FTAPE is not set
+# CONFIG_AGP is not set
+# CONFIG_DRM is not set
+
+#
+# PCMCIA character devices
+#
+# CONFIG_SYNCLINK_CS is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+# CONFIG_USB is not set
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+CONFIG_EXT2_FS_XATTR=y
+CONFIG_EXT2_FS_POSIX_ACL=y
+# CONFIG_EXT2_FS_SECURITY is not set
+CONFIG_EXT3_FS=y
+CONFIG_EXT3_FS_XATTR=y
+CONFIG_EXT3_FS_POSIX_ACL=y
+CONFIG_EXT3_FS_SECURITY=y
+CONFIG_JBD=y
+# CONFIG_JBD_DEBUG is not set
+CONFIG_FS_MBCACHE=y
+CONFIG_REISERFS_FS=m
+# CONFIG_REISERFS_CHECK is not set
+# CONFIG_REISERFS_PROC_INFO is not set
+# CONFIG_JFS_FS is not set
+CONFIG_FS_POSIX_ACL=y
+# CONFIG_XFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_QUOTA is not set
+CONFIG_AUTOFS_FS=m
+CONFIG_AUTOFS4_FS=m
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_FAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+# CONFIG_DEVFS_FS is not set
+CONFIG_DEVPTS_FS=y
+CONFIG_DEVPTS_FS_XATTR=y
+CONFIG_DEVPTS_FS_SECURITY=y
+CONFIG_TMPFS=y
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+CONFIG_CRAMFS=m
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+# CONFIG_NFS_V3 is not set
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
+CONFIG_NFSD=m
+# CONFIG_NFSD_V3 is not set
+# CONFIG_NFSD_TCP is not set
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+CONFIG_EXPORTFS=m
+CONFIG_SUNRPC=y
+# CONFIG_SUNRPC_GSS is not set
+CONFIG_SMB_FS=m
+# CONFIG_SMB_NLS_DEFAULT is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_INTERMEZZO_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+
+#
+# Native Language Support
+#
+CONFIG_NLS=m
+CONFIG_NLS_DEFAULT="iso8859-1"
+# CONFIG_NLS_CODEPAGE_437 is not set
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ISO8859_1 is not set
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+# CONFIG_NLS_UTF8 is not set
+
+#
+# Kernel hacking
+#
+CONFIG_CROSSCOMPILE=y
+CONFIG_CMDLINE=""
+# CONFIG_DEBUG_KERNEL is not set
+
+#
+# Security options
+#
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+CONFIG_CRYPTO=y
+CONFIG_CRYPTO_HMAC=y
+CONFIG_CRYPTO_NULL=y
+# CONFIG_CRYPTO_MD4 is not set
+# CONFIG_CRYPTO_MD5 is not set
+# CONFIG_CRYPTO_SHA1 is not set
+# CONFIG_CRYPTO_SHA256 is not set
+CONFIG_CRYPTO_SHA512=y
+# CONFIG_CRYPTO_DES is not set
+# CONFIG_CRYPTO_BLOWFISH is not set
+CONFIG_CRYPTO_TWOFISH=y
+# CONFIG_CRYPTO_SERPENT is not set
+CONFIG_CRYPTO_AES=y
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+CONFIG_CRYPTO_DEFLATE=y
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Library routines
+#
+CONFIG_CRC32=y
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
--- diff/arch/mips/configs/rm200_defconfig	1970-01-01 01:00:00.000000000 +0100
+++ source/arch/mips/configs/rm200_defconfig	2004-02-23 13:56:38.000000000 +0000
@@ -0,0 +1,1230 @@
+#
+# Automatically generated make config: don't edit
+#
+CONFIG_MIPS=y
+# CONFIG_MIPS64 is not set
+# CONFIG_64BIT is not set
+CONFIG_MIPS32=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_CLEAN_COMPILE=y
+CONFIG_STANDALONE=y
+CONFIG_BROKEN_ON_SMP=y
+
+#
+# General setup
+#
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+CONFIG_BSD_PROCESS_ACCT=y
+CONFIG_SYSCTL=y
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_EMBEDDED=y
+CONFIG_KALLSYMS=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+CONFIG_OBSOLETE_MODPARM=y
+CONFIG_MODVERSIONS=y
+CONFIG_KMOD=y
+
+#
+# Machine selection
+#
+# CONFIG_MACH_JAZZ is not set
+# CONFIG_BAGET_MIPS is not set
+# CONFIG_MACH_VR41XX is not set
+# CONFIG_TOSHIBA_JMR3927 is not set
+# CONFIG_MIPS_COBALT is not set
+# CONFIG_MACH_DECSTATION is not set
+# CONFIG_MIPS_EV64120 is not set
+# CONFIG_MIPS_EV96100 is not set
+# CONFIG_MIPS_IVR is not set
+# CONFIG_LASAT is not set
+# CONFIG_HP_LASERJET is not set
+# CONFIG_MIPS_ITE8172 is not set
+# CONFIG_MIPS_ATLAS is not set
+# CONFIG_MIPS_MALTA is not set
+# CONFIG_MIPS_SEAD is not set
+# CONFIG_MOMENCO_OCELOT is not set
+# CONFIG_MOMENCO_OCELOT_G is not set
+# CONFIG_MOMENCO_OCELOT_C is not set
+# CONFIG_MOMENCO_JAGUAR_ATX is not set
+# CONFIG_PMC_YOSEMITE is not set
+# CONFIG_DDB5074 is not set
+# CONFIG_DDB5476 is not set
+# CONFIG_DDB5477 is not set
+# CONFIG_NEC_OSPREY is not set
+# CONFIG_SGI_IP22 is not set
+# CONFIG_SGI_IP32 is not set
+# CONFIG_SOC_AU1X00 is not set
+# CONFIG_SIBYTE_SB1xxx_SOC is not set
+CONFIG_SNI_RM200_PCI=y
+# CONFIG_TOSHIBA_RBTX4927 is not set
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_HAVE_DEC_LOCK=y
+CONFIG_ARC=y
+CONFIG_DMA_NONCOHERENT=y
+CONFIG_GENERIC_ISA_DMA=y
+CONFIG_I8259=y
+CONFIG_CPU_LITTLE_ENDIAN=y
+CONFIG_BOOT_ELF32=y
+CONFIG_MIPS_L1_CACHE_SHIFT=5
+CONFIG_ARC32=y
+# CONFIG_FB is not set
+CONFIG_ARC_CONSOLE=y
+CONFIG_ARC_MEMORY=y
+CONFIG_ARC_PROMLIB=y
+
+#
+# CPU selection
+#
+# CONFIG_CPU_MIPS32 is not set
+# CONFIG_CPU_MIPS64 is not set
+# CONFIG_CPU_R3000 is not set
+# CONFIG_CPU_TX39XX is not set
+# CONFIG_CPU_VR41XX is not set
+# CONFIG_CPU_R4300 is not set
+CONFIG_CPU_R4X00=y
+# CONFIG_CPU_TX49XX is not set
+# CONFIG_CPU_R5000 is not set
+# CONFIG_CPU_R5432 is not set
+# CONFIG_CPU_R6000 is not set
+# CONFIG_CPU_NEVADA is not set
+# CONFIG_CPU_R8000 is not set
+# CONFIG_CPU_R10000 is not set
+# CONFIG_CPU_RM7000 is not set
+# CONFIG_CPU_RM9000 is not set
+# CONFIG_CPU_SB1 is not set
+CONFIG_PAGE_SIZE_4KB=y
+# CONFIG_PAGE_SIZE_16KB is not set
+# CONFIG_PAGE_SIZE_64KB is not set
+# CONFIG_64BIT_PHYS_ADDR is not set
+# CONFIG_CPU_ADVANCED is not set
+CONFIG_CPU_HAS_LLSC=y
+CONFIG_CPU_HAS_LLDSCD=y
+CONFIG_CPU_HAS_SYNC=y
+# CONFIG_PREEMPT is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+
+#
+# Bus options (PCI, PCMCIA, EISA, ISA, TC)
+#
+CONFIG_PCI=y
+CONFIG_PCI_LEGACY_PROC=y
+# CONFIG_PCI_NAMES is not set
+CONFIG_ISA=y
+# CONFIG_EISA is not set
+CONFIG_MMU=y
+# CONFIG_HOTPLUG is not set
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+CONFIG_BINFMT_MISC=m
+CONFIG_TRAD_SIGNALS=y
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
+# Parallel port support
+#
+CONFIG_PARPORT=m
+CONFIG_PARPORT_PC=m
+CONFIG_PARPORT_PC_CML1=m
+CONFIG_PARPORT_SERIAL=m
+# CONFIG_PARPORT_PC_FIFO is not set
+# CONFIG_PARPORT_PC_SUPERIO is not set
+# CONFIG_PARPORT_OTHER is not set
+CONFIG_PARPORT_1284=y
+
+#
+# Plug and Play support
+#
+# CONFIG_PNP is not set
+
+#
+# Block devices
+#
+CONFIG_BLK_DEV_FD=m
+# CONFIG_BLK_DEV_XD is not set
+CONFIG_PARIDE=m
+CONFIG_PARIDE_PARPORT=m
+
+#
+# Parallel IDE high-level drivers
+#
+CONFIG_PARIDE_PD=m
+CONFIG_PARIDE_PCD=m
+CONFIG_PARIDE_PF=m
+CONFIG_PARIDE_PT=m
+CONFIG_PARIDE_PG=m
+
+#
+# Parallel IDE protocol modules
+#
+CONFIG_PARIDE_ATEN=m
+CONFIG_PARIDE_BPCK=m
+CONFIG_PARIDE_BPCK6=m
+CONFIG_PARIDE_COMM=m
+CONFIG_PARIDE_DSTR=m
+CONFIG_PARIDE_FIT2=m
+CONFIG_PARIDE_FIT3=m
+CONFIG_PARIDE_EPAT=m
+# CONFIG_PARIDE_EPATC8 is not set
+CONFIG_PARIDE_EPIA=m
+CONFIG_PARIDE_FRIQ=m
+CONFIG_PARIDE_FRPW=m
+CONFIG_PARIDE_KBIC=m
+CONFIG_PARIDE_KTTI=m
+CONFIG_PARIDE_ON20=m
+CONFIG_PARIDE_ON26=m
+# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_UMEM is not set
+CONFIG_BLK_DEV_LOOP=m
+CONFIG_BLK_DEV_CRYPTOLOOP=m
+CONFIG_BLK_DEV_NBD=m
+CONFIG_BLK_DEV_RAM=m
+CONFIG_BLK_DEV_RAM_SIZE=4096
+# CONFIG_BLK_DEV_INITRD is not set
+# CONFIG_LBD is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+CONFIG_SCSI=y
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=y
+CONFIG_CHR_DEV_ST=m
+# CONFIG_CHR_DEV_OSST is not set
+CONFIG_BLK_DEV_SR=m
+CONFIG_BLK_DEV_SR_VENDOR=y
+# CONFIG_CHR_DEV_SG is not set
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+# CONFIG_SCSI_MULTI_LUN is not set
+# CONFIG_SCSI_REPORT_LUNS is not set
+CONFIG_SCSI_CONSTANTS=y
+# CONFIG_SCSI_LOGGING is not set
+
+#
+# SCSI low-level drivers
+#
+# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
+# CONFIG_SCSI_7000FASST is not set
+# CONFIG_SCSI_ACARD is not set
+# CONFIG_SCSI_AHA152X is not set
+# CONFIG_SCSI_AHA1542 is not set
+# CONFIG_SCSI_AACRAID is not set
+# CONFIG_SCSI_AIC7XXX is not set
+# CONFIG_SCSI_AIC7XXX_OLD is not set
+# CONFIG_SCSI_AIC79XX is not set
+# CONFIG_SCSI_ADVANSYS is not set
+# CONFIG_SCSI_IN2000 is not set
+# CONFIG_SCSI_MEGARAID is not set
+# CONFIG_SCSI_SATA is not set
+# CONFIG_SCSI_BUSLOGIC is not set
+# CONFIG_SCSI_CPQFCTS is not set
+# CONFIG_SCSI_DMX3191D is not set
+# CONFIG_SCSI_DTC3280 is not set
+# CONFIG_SCSI_EATA is not set
+# CONFIG_SCSI_EATA_PIO is not set
+# CONFIG_SCSI_FUTURE_DOMAIN is not set
+# CONFIG_SCSI_GDTH is not set
+# CONFIG_SCSI_GENERIC_NCR5380 is not set
+# CONFIG_SCSI_GENERIC_NCR5380_MMIO is not set
+# CONFIG_SCSI_IPS is not set
+# CONFIG_SCSI_INIA100 is not set
+CONFIG_SCSI_PPA=m
+CONFIG_SCSI_IMM=m
+# CONFIG_SCSI_IZIP_EPP16 is not set
+# CONFIG_SCSI_IZIP_SLOW_CTR is not set
+# CONFIG_SCSI_NCR53C406A is not set
+CONFIG_SCSI_SYM53C8XX_2=y
+CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=1
+CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=16
+CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64
+# CONFIG_SCSI_SYM53C8XX_IOMAPPED is not set
+# CONFIG_SCSI_PAS16 is not set
+# CONFIG_SCSI_PSI240I is not set
+# CONFIG_SCSI_QLOGIC_FAS is not set
+# CONFIG_SCSI_QLOGIC_ISP is not set
+# CONFIG_SCSI_QLOGIC_FC is not set
+# CONFIG_SCSI_QLOGIC_1280 is not set
+CONFIG_SCSI_QLA2XXX=y
+# CONFIG_SCSI_QLA21XX is not set
+# CONFIG_SCSI_QLA22XX is not set
+# CONFIG_SCSI_QLA2300 is not set
+# CONFIG_SCSI_QLA2322 is not set
+# CONFIG_SCSI_QLA6312 is not set
+# CONFIG_SCSI_QLA6322 is not set
+# CONFIG_SCSI_SYM53C416 is not set
+# CONFIG_SCSI_DC395x is not set
+# CONFIG_SCSI_DC390T is not set
+# CONFIG_SCSI_T128 is not set
+# CONFIG_SCSI_U14_34F is not set
+# CONFIG_SCSI_NSP32 is not set
+# CONFIG_SCSI_DEBUG is not set
+
+#
+# Old CD-ROM drivers (not SCSI, not IDE)
+#
+# CONFIG_CD_NO_IDESCSI is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+CONFIG_MD=y
+CONFIG_BLK_DEV_MD=m
+CONFIG_MD_LINEAR=m
+CONFIG_MD_RAID0=m
+CONFIG_MD_RAID1=m
+CONFIG_MD_RAID5=m
+# CONFIG_MD_RAID6 is not set
+CONFIG_MD_MULTIPATH=m
+CONFIG_BLK_DEV_DM=m
+CONFIG_DM_IOCTL_V4=y
+
+#
+# Fusion MPT device support
+#
+# CONFIG_FUSION is not set
+
+#
+# IEEE 1394 (FireWire) support (EXPERIMENTAL)
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+
+#
+# Macintosh device drivers
+#
+
+#
+# Networking support
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=m
+CONFIG_PACKET_MMAP=y
+CONFIG_NETLINK_DEV=m
+CONFIG_UNIX=y
+CONFIG_NET_KEY=m
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+# CONFIG_IP_ADVANCED_ROUTER is not set
+# CONFIG_IP_PNP is not set
+CONFIG_NET_IPIP=m
+CONFIG_NET_IPGRE=m
+CONFIG_NET_IPGRE_BROADCAST=y
+CONFIG_IP_MROUTE=y
+CONFIG_IP_PIMSM_V1=y
+CONFIG_IP_PIMSM_V2=y
+# CONFIG_ARPD is not set
+CONFIG_INET_ECN=y
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+
+#
+# IP: Virtual Server Configuration
+#
+# CONFIG_IP_VS is not set
+CONFIG_IPV6=m
+CONFIG_IPV6_PRIVACY=y
+CONFIG_INET6_AH=m
+CONFIG_INET6_ESP=m
+CONFIG_INET6_IPCOMP=m
+CONFIG_IPV6_TUNNEL=m
+CONFIG_DECNET=m
+# CONFIG_DECNET_SIOCGIFCONF is not set
+# CONFIG_DECNET_ROUTER is not set
+CONFIG_BRIDGE=m
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
+CONFIG_BRIDGE_NETFILTER=y
+
+#
+# IP: Netfilter Configuration
+#
+CONFIG_IP_NF_CONNTRACK=m
+CONFIG_IP_NF_FTP=m
+CONFIG_IP_NF_IRC=m
+CONFIG_IP_NF_TFTP=m
+CONFIG_IP_NF_AMANDA=m
+CONFIG_IP_NF_QUEUE=m
+CONFIG_IP_NF_IPTABLES=m
+CONFIG_IP_NF_MATCH_LIMIT=m
+CONFIG_IP_NF_MATCH_IPRANGE=m
+CONFIG_IP_NF_MATCH_MAC=m
+CONFIG_IP_NF_MATCH_PKTTYPE=m
+CONFIG_IP_NF_MATCH_MARK=m
+CONFIG_IP_NF_MATCH_MULTIPORT=m
+CONFIG_IP_NF_MATCH_TOS=m
+CONFIG_IP_NF_MATCH_RECENT=m
+CONFIG_IP_NF_MATCH_ECN=m
+CONFIG_IP_NF_MATCH_DSCP=m
+CONFIG_IP_NF_MATCH_AH_ESP=m
+CONFIG_IP_NF_MATCH_LENGTH=m
+CONFIG_IP_NF_MATCH_TTL=m
+CONFIG_IP_NF_MATCH_TCPMSS=m
+CONFIG_IP_NF_MATCH_HELPER=m
+CONFIG_IP_NF_MATCH_STATE=m
+CONFIG_IP_NF_MATCH_CONNTRACK=m
+CONFIG_IP_NF_MATCH_OWNER=m
+CONFIG_IP_NF_MATCH_PHYSDEV=m
+CONFIG_IP_NF_FILTER=m
+CONFIG_IP_NF_TARGET_REJECT=m
+CONFIG_IP_NF_NAT=m
+CONFIG_IP_NF_NAT_NEEDED=y
+CONFIG_IP_NF_TARGET_MASQUERADE=m
+CONFIG_IP_NF_TARGET_REDIRECT=m
+CONFIG_IP_NF_TARGET_NETMAP=m
+CONFIG_IP_NF_TARGET_SAME=m
+CONFIG_IP_NF_NAT_LOCAL=y
+CONFIG_IP_NF_NAT_SNMP_BASIC=m
+CONFIG_IP_NF_NAT_IRC=m
+CONFIG_IP_NF_NAT_FTP=m
+CONFIG_IP_NF_NAT_TFTP=m
+CONFIG_IP_NF_NAT_AMANDA=m
+CONFIG_IP_NF_MANGLE=m
+CONFIG_IP_NF_TARGET_TOS=m
+CONFIG_IP_NF_TARGET_ECN=m
+CONFIG_IP_NF_TARGET_DSCP=m
+CONFIG_IP_NF_TARGET_MARK=m
+CONFIG_IP_NF_TARGET_CLASSIFY=m
+CONFIG_IP_NF_TARGET_LOG=m
+CONFIG_IP_NF_TARGET_ULOG=m
+CONFIG_IP_NF_TARGET_TCPMSS=m
+CONFIG_IP_NF_ARPTABLES=m
+CONFIG_IP_NF_ARPFILTER=m
+CONFIG_IP_NF_ARP_MANGLE=m
+CONFIG_IP_NF_COMPAT_IPCHAINS=m
+CONFIG_IP_NF_COMPAT_IPFWADM=m
+
+#
+# IPv6: Netfilter Configuration
+#
+CONFIG_IP6_NF_QUEUE=m
+CONFIG_IP6_NF_IPTABLES=m
+CONFIG_IP6_NF_MATCH_LIMIT=m
+CONFIG_IP6_NF_MATCH_MAC=m
+CONFIG_IP6_NF_MATCH_RT=m
+CONFIG_IP6_NF_MATCH_OPTS=m
+CONFIG_IP6_NF_MATCH_FRAG=m
+CONFIG_IP6_NF_MATCH_HL=m
+CONFIG_IP6_NF_MATCH_MULTIPORT=m
+CONFIG_IP6_NF_MATCH_OWNER=m
+CONFIG_IP6_NF_MATCH_MARK=m
+CONFIG_IP6_NF_MATCH_IPV6HEADER=m
+CONFIG_IP6_NF_MATCH_AHESP=m
+CONFIG_IP6_NF_MATCH_LENGTH=m
+CONFIG_IP6_NF_MATCH_EUI64=m
+CONFIG_IP6_NF_FILTER=m
+CONFIG_IP6_NF_TARGET_LOG=m
+CONFIG_IP6_NF_MANGLE=m
+CONFIG_IP6_NF_TARGET_MARK=m
+
+#
+# DECnet: Netfilter Configuration
+#
+CONFIG_DECNET_NF_GRABULATOR=m
+
+#
+# Bridge: Netfilter Configuration
+#
+CONFIG_BRIDGE_NF_EBTABLES=m
+CONFIG_BRIDGE_EBT_BROUTE=m
+CONFIG_BRIDGE_EBT_T_FILTER=m
+CONFIG_BRIDGE_EBT_T_NAT=m
+CONFIG_BRIDGE_EBT_802_3=m
+CONFIG_BRIDGE_EBT_AMONG=m
+CONFIG_BRIDGE_EBT_ARP=m
+CONFIG_BRIDGE_EBT_IP=m
+CONFIG_BRIDGE_EBT_LIMIT=m
+CONFIG_BRIDGE_EBT_MARK=m
+CONFIG_BRIDGE_EBT_PKTTYPE=m
+CONFIG_BRIDGE_EBT_STP=m
+CONFIG_BRIDGE_EBT_VLAN=m
+CONFIG_BRIDGE_EBT_ARPREPLY=m
+CONFIG_BRIDGE_EBT_DNAT=m
+CONFIG_BRIDGE_EBT_MARK_T=m
+CONFIG_BRIDGE_EBT_REDIRECT=m
+CONFIG_BRIDGE_EBT_SNAT=m
+CONFIG_BRIDGE_EBT_LOG=m
+CONFIG_XFRM=y
+# CONFIG_XFRM_USER is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+CONFIG_IPV6_SCTP__=m
+# CONFIG_IP_SCTP is not set
+# CONFIG_ATM is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_FASTROUTE is not set
+# CONFIG_NET_HW_FLOWCONTROL is not set
+
+#
+# QoS and/or fair queueing
+#
+CONFIG_NET_SCHED=y
+CONFIG_NET_SCH_CBQ=m
+CONFIG_NET_SCH_HTB=m
+CONFIG_NET_SCH_HFSC=m
+CONFIG_NET_SCH_CSZ=m
+CONFIG_NET_SCH_PRIO=m
+CONFIG_NET_SCH_RED=m
+CONFIG_NET_SCH_SFQ=m
+CONFIG_NET_SCH_TEQL=m
+CONFIG_NET_SCH_TBF=m
+CONFIG_NET_SCH_GRED=m
+CONFIG_NET_SCH_DSMARK=m
+CONFIG_NET_SCH_INGRESS=m
+CONFIG_NET_QOS=y
+CONFIG_NET_ESTIMATOR=y
+CONFIG_NET_CLS=y
+CONFIG_NET_CLS_TCINDEX=m
+CONFIG_NET_CLS_ROUTE4=m
+CONFIG_NET_CLS_ROUTE=y
+CONFIG_NET_CLS_FW=m
+CONFIG_NET_CLS_U32=m
+CONFIG_NET_CLS_RSVP=m
+CONFIG_NET_CLS_RSVP6=m
+CONFIG_NET_CLS_POLICE=y
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+CONFIG_NETDEVICES=y
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+CONFIG_DUMMY=m
+CONFIG_BONDING=m
+CONFIG_EQUALIZER=m
+CONFIG_TUN=m
+CONFIG_ETHERTAP=m
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_SUNGEM is not set
+# CONFIG_NET_VENDOR_3COM is not set
+# CONFIG_LANCE is not set
+# CONFIG_NET_VENDOR_SMC is not set
+# CONFIG_NET_VENDOR_RACAL is not set
+
+#
+# Tulip family network device support
+#
+# CONFIG_NET_TULIP is not set
+# CONFIG_AT1700 is not set
+# CONFIG_DEPCA is not set
+# CONFIG_HP100 is not set
+CONFIG_NET_ISA=y
+# CONFIG_E2100 is not set
+# CONFIG_EWRK3 is not set
+# CONFIG_EEXPRESS is not set
+# CONFIG_EEXPRESS_PRO is not set
+# CONFIG_HPLAN_PLUS is not set
+# CONFIG_HPLAN is not set
+# CONFIG_LP486E is not set
+# CONFIG_ETH16I is not set
+CONFIG_NE2000=m
+# CONFIG_ZNET is not set
+# CONFIG_SEEQ8005 is not set
+CONFIG_NET_PCI=y
+CONFIG_PCNET32=y
+# CONFIG_AMD8111_ETH is not set
+# CONFIG_ADAPTEC_STARFIRE is not set
+# CONFIG_AC3200 is not set
+# CONFIG_APRICOT is not set
+# CONFIG_B44 is not set
+# CONFIG_FORCEDETH is not set
+# CONFIG_CS89x0 is not set
+# CONFIG_DGRS is not set
+CONFIG_EEPRO100=m
+# CONFIG_EEPRO100_PIO is not set
+# CONFIG_E100 is not set
+# CONFIG_FEALNX is not set
+# CONFIG_NATSEMI is not set
+# CONFIG_NE2K_PCI is not set
+# CONFIG_8139CP is not set
+# CONFIG_8139TOO is not set
+# CONFIG_SIS900 is not set
+# CONFIG_EPIC100 is not set
+# CONFIG_SUNDANCE is not set
+# CONFIG_TLAN is not set
+# CONFIG_VIA_RHINE is not set
+# CONFIG_LAN_SAA9730 is not set
+# CONFIG_NET_POCKET is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+# CONFIG_E1000 is not set
+# CONFIG_NS83820 is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+# CONFIG_R8169 is not set
+# CONFIG_SIS190 is not set
+# CONFIG_SK98LIN is not set
+# CONFIG_TIGON3 is not set
+
+#
+# Ethernet (10000 Mbit)
+#
+# CONFIG_IXGB is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+CONFIG_PLIP=m
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Token Ring devices
+#
+# CONFIG_TR is not set
+# CONFIG_NET_FC is not set
+# CONFIG_RCPCI is not set
+# CONFIG_SHAPER is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+
+#
+# Amateur Radio support
+#
+# CONFIG_HAMRADIO is not set
+
+#
+# IrDA (infrared) support
+#
+# CONFIG_IRDA is not set
+
+#
+# Bluetooth support
+#
+# CONFIG_BT is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN_BOOL is not set
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+CONFIG_INPUT_MOUSEDEV_PSAUX=y
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+# CONFIG_INPUT_EVDEV is not set
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input I/O drivers
+#
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+CONFIG_SERIO=y
+CONFIG_SERIO_I8042=y
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_CT82C710 is not set
+CONFIG_SERIO_PARKBD=m
+# CONFIG_SERIO_PCIPS2 is not set
+
+#
+# Input Device Drivers
+#
+CONFIG_INPUT_KEYBOARD=y
+CONFIG_KEYBOARD_ATKBD=y
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_XTKBD is not set
+# CONFIG_KEYBOARD_NEWTON is not set
+CONFIG_INPUT_MOUSE=y
+CONFIG_MOUSE_PS2=y
+# CONFIG_MOUSE_SERIAL is not set
+# CONFIG_MOUSE_INPORT is not set
+# CONFIG_MOUSE_LOGIBM is not set
+# CONFIG_MOUSE_PC110PAD is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=m
+CONFIG_SERIAL_8250_NR_UARTS=4
+CONFIG_SERIAL_8250_EXTENDED=y
+# CONFIG_SERIAL_8250_MANY_PORTS is not set
+CONFIG_SERIAL_8250_SHARE_IRQ=y
+CONFIG_SERIAL_8250_DETECT_IRQ=y
+CONFIG_SERIAL_8250_MULTIPORT=y
+CONFIG_SERIAL_8250_RSA=y
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=m
+CONFIG_UNIX98_PTYS=y
+CONFIG_UNIX98_PTY_COUNT=256
+CONFIG_PRINTER=m
+# CONFIG_LP_CONSOLE is not set
+CONFIG_PPDEV=m
+CONFIG_TIPAR=m
+
+#
+# Mice
+#
+# CONFIG_BUSMOUSE is not set
+# CONFIG_QIC02_TAPE is not set
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_NVRAM is not set
+CONFIG_RTC=m
+# CONFIG_GEN_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_FTAPE is not set
+# CONFIG_AGP is not set
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+
+#
+# Console display driver support
+#
+CONFIG_VGA_CONSOLE=y
+# CONFIG_MDA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+CONFIG_USB=m
+# CONFIG_USB_DEBUG is not set
+
+#
+# Miscellaneous USB options
+#
+CONFIG_USB_DEVICEFS=y
+# CONFIG_USB_BANDWIDTH is not set
+# CONFIG_USB_DYNAMIC_MINORS is not set
+
+#
+# USB Host Controller Drivers
+#
+CONFIG_USB_EHCI_HCD=m
+CONFIG_USB_OHCI_HCD=m
+CONFIG_USB_UHCI_HCD=m
+
+#
+# USB Device Class drivers
+#
+CONFIG_USB_BLUETOOTH_TTY=m
+CONFIG_USB_ACM=m
+CONFIG_USB_PRINTER=m
+CONFIG_USB_STORAGE=m
+# CONFIG_USB_STORAGE_DEBUG is not set
+CONFIG_USB_STORAGE_DATAFAB=y
+CONFIG_USB_STORAGE_FREECOM=y
+CONFIG_USB_STORAGE_DPCM=y
+CONFIG_USB_STORAGE_HP8200e=y
+CONFIG_USB_STORAGE_SDDR09=y
+CONFIG_USB_STORAGE_SDDR55=y
+CONFIG_USB_STORAGE_JUMPSHOT=y
+
+#
+# USB Human Interface Devices (HID)
+#
+CONFIG_USB_HID=m
+CONFIG_USB_HIDINPUT=y
+CONFIG_HID_FF=y
+CONFIG_HID_PID=y
+CONFIG_LOGITECH_FF=y
+CONFIG_THRUSTMASTER_FF=y
+CONFIG_USB_HIDDEV=y
+
+#
+# USB HID Boot Protocol drivers
+#
+CONFIG_USB_KBD=m
+CONFIG_USB_MOUSE=m
+CONFIG_USB_AIPTEK=m
+CONFIG_USB_WACOM=m
+CONFIG_USB_KBTAB=m
+CONFIG_USB_POWERMATE=m
+CONFIG_USB_XPAD=m
+
+#
+# USB Imaging devices
+#
+CONFIG_USB_MDC800=m
+CONFIG_USB_MICROTEK=m
+CONFIG_USB_HPUSBSCSI=m
+
+#
+# USB Multimedia devices
+#
+CONFIG_USB_DABUSB=m
+
+#
+# Video4Linux support is needed for USB Multimedia device support
+#
+
+#
+# USB Network adaptors
+#
+CONFIG_USB_CATC=m
+CONFIG_USB_KAWETH=m
+CONFIG_USB_PEGASUS=m
+CONFIG_USB_RTL8150=m
+CONFIG_USB_USBNET=m
+
+#
+# USB Host-to-Host Cables
+#
+CONFIG_USB_AN2720=y
+CONFIG_USB_BELKIN=y
+CONFIG_USB_GENESYS=y
+CONFIG_USB_NET1080=y
+CONFIG_USB_PL2301=y
+
+#
+# Intelligent USB Devices/Gadgets
+#
+CONFIG_USB_ARMLINUX=y
+CONFIG_USB_EPSON2888=y
+CONFIG_USB_ZAURUS=y
+CONFIG_USB_CDCETHER=y
+
+#
+# USB Network Adapters
+#
+CONFIG_USB_AX8817X=y
+
+#
+# USB port drivers
+#
+CONFIG_USB_USS720=m
+
+#
+# USB Serial Converter support
+#
+CONFIG_USB_SERIAL=m
+CONFIG_USB_SERIAL_GENERIC=y
+CONFIG_USB_SERIAL_BELKIN=m
+CONFIG_USB_SERIAL_WHITEHEAT=m
+CONFIG_USB_SERIAL_DIGI_ACCELEPORT=m
+CONFIG_USB_SERIAL_EMPEG=m
+CONFIG_USB_SERIAL_FTDI_SIO=m
+CONFIG_USB_SERIAL_VISOR=m
+CONFIG_USB_SERIAL_IPAQ=m
+CONFIG_USB_SERIAL_IR=m
+CONFIG_USB_SERIAL_EDGEPORT=m
+CONFIG_USB_SERIAL_EDGEPORT_TI=m
+CONFIG_USB_SERIAL_KEYSPAN_PDA=m
+CONFIG_USB_SERIAL_KEYSPAN=m
+CONFIG_USB_SERIAL_KEYSPAN_MPR=y
+# CONFIG_USB_SERIAL_KEYSPAN_USA28 is not set
+CONFIG_USB_SERIAL_KEYSPAN_USA28X=y
+CONFIG_USB_SERIAL_KEYSPAN_USA28XA=y
+CONFIG_USB_SERIAL_KEYSPAN_USA28XB=y
+# CONFIG_USB_SERIAL_KEYSPAN_USA19 is not set
+# CONFIG_USB_SERIAL_KEYSPAN_USA18X is not set
+CONFIG_USB_SERIAL_KEYSPAN_USA19W=y
+CONFIG_USB_SERIAL_KEYSPAN_USA19QW=y
+CONFIG_USB_SERIAL_KEYSPAN_USA19QI=y
+CONFIG_USB_SERIAL_KEYSPAN_USA49W=y
+CONFIG_USB_SERIAL_KEYSPAN_USA49WLC=y
+CONFIG_USB_SERIAL_KLSI=m
+CONFIG_USB_SERIAL_KOBIL_SCT=m
+CONFIG_USB_SERIAL_MCT_U232=m
+CONFIG_USB_SERIAL_PL2303=m
+CONFIG_USB_SERIAL_SAFE=m
+CONFIG_USB_SERIAL_SAFE_PADDED=y
+CONFIG_USB_SERIAL_CYBERJACK=m
+CONFIG_USB_SERIAL_XIRCOM=m
+CONFIG_USB_SERIAL_OMNINET=m
+CONFIG_USB_EZUSB=y
+
+#
+# USB Miscellaneous drivers
+#
+# CONFIG_USB_EMI62 is not set
+# CONFIG_USB_EMI26 is not set
+CONFIG_USB_TIGL=m
+CONFIG_USB_AUERSWALD=m
+CONFIG_USB_RIO500=m
+CONFIG_USB_LEGOTOWER=m
+CONFIG_USB_BRLVGER=m
+CONFIG_USB_LCD=m
+# CONFIG_USB_LED is not set
+CONFIG_USB_TEST=m
+
+#
+# USB Gadget Support
+#
+CONFIG_USB_GADGET=m
+CONFIG_USB_GADGET_NET2280=y
+CONFIG_USB_NET2280=m
+# CONFIG_USB_GADGET_PXA2XX is not set
+# CONFIG_USB_GADGET_GOKU is not set
+# CONFIG_USB_GADGET_SA1100 is not set
+CONFIG_USB_ZERO=m
+CONFIG_USB_ETH=m
+CONFIG_USB_GADGETFS=m
+# CONFIG_USB_FILE_STORAGE is not set
+# CONFIG_USB_G_SERIAL is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=m
+# CONFIG_EXT2_FS_XATTR is not set
+CONFIG_EXT3_FS=y
+CONFIG_EXT3_FS_XATTR=y
+# CONFIG_EXT3_FS_POSIX_ACL is not set
+# CONFIG_EXT3_FS_SECURITY is not set
+CONFIG_JBD=y
+# CONFIG_JBD_DEBUG is not set
+CONFIG_FS_MBCACHE=y
+CONFIG_REISERFS_FS=m
+# CONFIG_REISERFS_CHECK is not set
+# CONFIG_REISERFS_PROC_INFO is not set
+CONFIG_JFS_FS=m
+# CONFIG_JFS_POSIX_ACL is not set
+# CONFIG_JFS_DEBUG is not set
+# CONFIG_JFS_STATISTICS is not set
+CONFIG_XFS_FS=m
+# CONFIG_XFS_RT is not set
+CONFIG_XFS_QUOTA=y
+CONFIG_XFS_SECURITY=y
+# CONFIG_XFS_POSIX_ACL is not set
+CONFIG_MINIX_FS=m
+CONFIG_ROMFS_FS=m
+# CONFIG_QUOTA is not set
+CONFIG_QUOTACTL=y
+CONFIG_AUTOFS_FS=m
+CONFIG_AUTOFS4_FS=m
+
+#
+# CD-ROM/DVD Filesystems
+#
+CONFIG_ISO9660_FS=m
+CONFIG_JOLIET=y
+CONFIG_ZISOFS=y
+CONFIG_ZISOFS_FS=m
+CONFIG_UDF_FS=m
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=m
+CONFIG_MSDOS_FS=m
+CONFIG_VFAT_FS=m
+CONFIG_NTFS_FS=m
+# CONFIG_NTFS_DEBUG is not set
+# CONFIG_NTFS_RW is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+# CONFIG_DEVFS_FS is not set
+CONFIG_DEVPTS_FS=y
+CONFIG_DEVPTS_FS_XATTR=y
+CONFIG_DEVPTS_FS_SECURITY=y
+# CONFIG_TMPFS is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+
+#
+# Miscellaneous filesystems
+#
+CONFIG_ADFS_FS=m
+# CONFIG_ADFS_FS_RW is not set
+CONFIG_AFFS_FS=m
+CONFIG_HFS_FS=m
+CONFIG_BEFS_FS=m
+# CONFIG_BEFS_DEBUG is not set
+CONFIG_BFS_FS=m
+CONFIG_EFS_FS=m
+CONFIG_CRAMFS=m
+CONFIG_VXFS_FS=m
+CONFIG_HPFS_FS=m
+CONFIG_QNX4FS_FS=m
+# CONFIG_QNX4FS_RW is not set
+CONFIG_SYSV_FS=m
+CONFIG_UFS_FS=m
+# CONFIG_UFS_FS_WRITE is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=m
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
+CONFIG_NFSD=m
+CONFIG_NFSD_V3=y
+# CONFIG_NFSD_V4 is not set
+CONFIG_NFSD_TCP=y
+CONFIG_LOCKD=m
+CONFIG_LOCKD_V4=y
+CONFIG_EXPORTFS=m
+CONFIG_SUNRPC=m
+CONFIG_SUNRPC_GSS=m
+CONFIG_RPCSEC_GSS_KRB5=m
+CONFIG_SMB_FS=m
+# CONFIG_SMB_NLS_DEFAULT is not set
+CONFIG_CIFS=m
+CONFIG_NCP_FS=m
+CONFIG_NCPFS_PACKET_SIGNING=y
+CONFIG_NCPFS_IOCTL_LOCKING=y
+CONFIG_NCPFS_STRONG=y
+CONFIG_NCPFS_NFS_NS=y
+CONFIG_NCPFS_OS2_NS=y
+CONFIG_NCPFS_SMALLDOS=y
+CONFIG_NCPFS_NLS=y
+CONFIG_NCPFS_EXTRAS=y
+CONFIG_CODA_FS=m
+CONFIG_CODA_FS_OLD_API=y
+# CONFIG_INTERMEZZO_FS is not set
+CONFIG_AFS_FS=m
+CONFIG_RXRPC=m
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+# CONFIG_MAC_PARTITION is not set
+CONFIG_MSDOS_PARTITION=y
+# CONFIG_BSD_DISKLABEL is not set
+# CONFIG_MINIX_SUBPARTITION is not set
+# CONFIG_SOLARIS_X86_PARTITION is not set
+# CONFIG_UNIXWARE_DISKLABEL is not set
+# CONFIG_LDM_PARTITION is not set
+# CONFIG_NEC98_PARTITION is not set
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+# CONFIG_EFI_PARTITION is not set
+
+#
+# Native Language Support
+#
+CONFIG_NLS=m
+CONFIG_NLS_DEFAULT="iso8859-1"
+CONFIG_NLS_CODEPAGE_437=m
+CONFIG_NLS_CODEPAGE_737=m
+CONFIG_NLS_CODEPAGE_775=m
+CONFIG_NLS_CODEPAGE_850=m
+CONFIG_NLS_CODEPAGE_852=m
+CONFIG_NLS_CODEPAGE_855=m
+CONFIG_NLS_CODEPAGE_857=m
+CONFIG_NLS_CODEPAGE_860=m
+CONFIG_NLS_CODEPAGE_861=m
+CONFIG_NLS_CODEPAGE_862=m
+CONFIG_NLS_CODEPAGE_863=m
+CONFIG_NLS_CODEPAGE_864=m
+CONFIG_NLS_CODEPAGE_865=m
+CONFIG_NLS_CODEPAGE_866=m
+CONFIG_NLS_CODEPAGE_869=m
+CONFIG_NLS_CODEPAGE_936=m
+CONFIG_NLS_CODEPAGE_950=m
+CONFIG_NLS_CODEPAGE_932=m
+CONFIG_NLS_CODEPAGE_949=m
+CONFIG_NLS_CODEPAGE_874=m
+CONFIG_NLS_ISO8859_8=m
+CONFIG_NLS_CODEPAGE_1250=m
+CONFIG_NLS_CODEPAGE_1251=m
+CONFIG_NLS_ISO8859_1=m
+CONFIG_NLS_ISO8859_2=m
+CONFIG_NLS_ISO8859_3=m
+CONFIG_NLS_ISO8859_4=m
+CONFIG_NLS_ISO8859_5=m
+CONFIG_NLS_ISO8859_6=m
+CONFIG_NLS_ISO8859_7=m
+CONFIG_NLS_ISO8859_9=m
+CONFIG_NLS_ISO8859_13=m
+CONFIG_NLS_ISO8859_14=m
+CONFIG_NLS_ISO8859_15=m
+CONFIG_NLS_KOI8_R=m
+CONFIG_NLS_KOI8_U=m
+CONFIG_NLS_UTF8=m
+
+#
+# Kernel hacking
+#
+CONFIG_CROSSCOMPILE=y
+CONFIG_CMDLINE=""
+# CONFIG_DEBUG_KERNEL is not set
+
+#
+# Security options
+#
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+CONFIG_CRYPTO=y
+CONFIG_CRYPTO_HMAC=y
+CONFIG_CRYPTO_NULL=m
+CONFIG_CRYPTO_MD4=m
+CONFIG_CRYPTO_MD5=m
+CONFIG_CRYPTO_SHA1=m
+CONFIG_CRYPTO_SHA256=m
+CONFIG_CRYPTO_SHA512=m
+CONFIG_CRYPTO_DES=m
+CONFIG_CRYPTO_BLOWFISH=m
+CONFIG_CRYPTO_TWOFISH=m
+CONFIG_CRYPTO_SERPENT=m
+CONFIG_CRYPTO_AES=m
+CONFIG_CRYPTO_CAST5=m
+CONFIG_CRYPTO_CAST6=m
+CONFIG_CRYPTO_DEFLATE=m
+CONFIG_CRYPTO_TEST=m
+
+#
+# Library routines
+#
+CONFIG_CRC32=y
+CONFIG_ZLIB_INFLATE=m
+CONFIG_ZLIB_DEFLATE=m
--- diff/arch/mips/configs/sb1250-swarm_defconfig	1970-01-01 01:00:00.000000000 +0100
+++ source/arch/mips/configs/sb1250-swarm_defconfig	2004-02-23 13:56:38.000000000 +0000
@@ -0,0 +1,636 @@
+#
+# Automatically generated make config: don't edit
+#
+CONFIG_MIPS=y
+# CONFIG_MIPS64 is not set
+# CONFIG_64BIT is not set
+CONFIG_MIPS32=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_CLEAN_COMPILE=y
+CONFIG_STANDALONE=y
+
+#
+# General setup
+#
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+CONFIG_LOG_BUF_SHIFT=15
+# CONFIG_IKCONFIG is not set
+CONFIG_EMBEDDED=y
+CONFIG_KALLSYMS=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+CONFIG_OBSOLETE_MODPARM=y
+CONFIG_MODVERSIONS=y
+CONFIG_KMOD=y
+
+#
+# Machine selection
+#
+# CONFIG_MACH_JAZZ is not set
+# CONFIG_BAGET_MIPS is not set
+# CONFIG_MACH_VR41XX is not set
+# CONFIG_TOSHIBA_JMR3927 is not set
+# CONFIG_MIPS_COBALT is not set
+# CONFIG_MACH_DECSTATION is not set
+# CONFIG_MIPS_EV64120 is not set
+# CONFIG_MIPS_EV96100 is not set
+# CONFIG_MIPS_IVR is not set
+# CONFIG_LASAT is not set
+# CONFIG_HP_LASERJET is not set
+# CONFIG_MIPS_ITE8172 is not set
+# CONFIG_MIPS_ATLAS is not set
+# CONFIG_MIPS_MALTA is not set
+# CONFIG_MIPS_SEAD is not set
+# CONFIG_MOMENCO_OCELOT is not set
+# CONFIG_MOMENCO_OCELOT_G is not set
+# CONFIG_MOMENCO_OCELOT_C is not set
+# CONFIG_MOMENCO_JAGUAR_ATX is not set
+# CONFIG_PMC_YOSEMITE is not set
+# CONFIG_DDB5074 is not set
+# CONFIG_DDB5476 is not set
+# CONFIG_DDB5477 is not set
+# CONFIG_NEC_OSPREY is not set
+# CONFIG_SGI_IP22 is not set
+# CONFIG_SGI_IP32 is not set
+# CONFIG_SOC_AU1X00 is not set
+CONFIG_SIBYTE_SB1xxx_SOC=y
+CONFIG_SIBYTE_SWARM=y
+# CONFIG_SIBYTE_SENTOSA is not set
+# CONFIG_SIBYTE_RHONE is not set
+# CONFIG_SIBYTE_CARMEL is not set
+# CONFIG_SIBYTE_PTSWARM is not set
+# CONFIG_SIBYTE_LITTLESUR is not set
+# CONFIG_SIBYTE_CRHINE is not set
+# CONFIG_SIBYTE_CRHONE is not set
+# CONFIG_SIBYTE_UNKNOWN is not set
+CONFIG_SIBYTE_BOARD=y
+CONFIG_SIBYTE_SB1250=y
+CONFIG_CPU_SB1_PASS_1=y
+# CONFIG_CPU_SB1_PASS_2_1250 is not set
+# CONFIG_CPU_SB1_PASS_2_2 is not set
+# CONFIG_CPU_SB1_PASS_4 is not set
+# CONFIG_CPU_SB1_PASS_2_112x is not set
+# CONFIG_CPU_SB1_PASS_3 is not set
+CONFIG_SIBYTE_HAS_PCI=y
+CONFIG_SIBYTE_HAS_LDT=y
+# CONFIG_SIMULATION is not set
+CONFIG_SIBYTE_CFE=y
+# CONFIG_SIBYTE_CFE_CONSOLE is not set
+# CONFIG_SIBYTE_BUS_WATCHER is not set
+# CONFIG_SIBYTE_SB1250_PROF is not set
+# CONFIG_SIBYTE_TBPROF is not set
+# CONFIG_SNI_RM200_PCI is not set
+# CONFIG_TOSHIBA_RBTX4927 is not set
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_HAVE_DEC_LOCK=y
+CONFIG_DMA_COHERENT=y
+# CONFIG_CPU_LITTLE_ENDIAN is not set
+CONFIG_DUMMY_KEYB=y
+CONFIG_SWAP_IO_SPACE=y
+CONFIG_BOOT_ELF32=y
+CONFIG_MIPS_L1_CACHE_SHIFT=5
+# CONFIG_FB is not set
+
+#
+# CPU selection
+#
+# CONFIG_CPU_MIPS32 is not set
+# CONFIG_CPU_MIPS64 is not set
+# CONFIG_CPU_R3000 is not set
+# CONFIG_CPU_TX39XX is not set
+# CONFIG_CPU_VR41XX is not set
+# CONFIG_CPU_R4300 is not set
+# CONFIG_CPU_R4X00 is not set
+# CONFIG_CPU_TX49XX is not set
+# CONFIG_CPU_R5000 is not set
+# CONFIG_CPU_R5432 is not set
+# CONFIG_CPU_R6000 is not set
+# CONFIG_CPU_NEVADA is not set
+# CONFIG_CPU_R8000 is not set
+# CONFIG_CPU_R10000 is not set
+# CONFIG_CPU_RM7000 is not set
+# CONFIG_CPU_RM9000 is not set
+CONFIG_CPU_SB1=y
+CONFIG_PAGE_SIZE_4KB=y
+# CONFIG_PAGE_SIZE_16KB is not set
+# CONFIG_PAGE_SIZE_64KB is not set
+# CONFIG_SIBYTE_DMA_PAGEOPS is not set
+# CONFIG_CPU_HAS_PREFETCH is not set
+CONFIG_VTAG_ICACHE=y
+CONFIG_SB1_PASS_1_WORKAROUNDS=y
+# CONFIG_64BIT_PHYS_ADDR is not set
+# CONFIG_CPU_ADVANCED is not set
+CONFIG_CPU_HAS_LLSC=y
+CONFIG_CPU_HAS_LLDSCD=y
+CONFIG_CPU_HAS_SYNC=y
+# CONFIG_HIGHMEM is not set
+CONFIG_SMP=y
+CONFIG_NR_CPUS=2
+# CONFIG_PREEMPT is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+
+#
+# Bus options (PCI, PCMCIA, EISA, ISA, TC)
+#
+CONFIG_PCI=y
+CONFIG_PCI_LEGACY_PROC=y
+CONFIG_PCI_NAMES=y
+CONFIG_MMU=y
+# CONFIG_HOTPLUG is not set
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_MISC is not set
+CONFIG_TRAD_SIGNALS=y
+# CONFIG_BINFMT_IRIX is not set
+
+#
+# MIPS initrd options
+#
+# CONFIG_EMBEDDED_RAMDISK is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_UMEM is not set
+# CONFIG_BLK_DEV_LOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_SIZE=9220
+CONFIG_BLK_DEV_INITRD=y
+# CONFIG_LBD is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_SCSI is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+
+#
+# IEEE 1394 (FireWire) support (EXPERIMENTAL)
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+
+#
+# Macintosh device drivers
+#
+
+#
+# Networking support
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+CONFIG_PACKET_MMAP=y
+CONFIG_NETLINK_DEV=y
+CONFIG_UNIX=y
+CONFIG_NET_KEY=y
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_BOOTP=y
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_ARPD is not set
+# CONFIG_INET_ECN is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_IPV6 is not set
+# CONFIG_DECNET is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_NETFILTER is not set
+CONFIG_XFRM=y
+# CONFIG_XFRM_USER is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+CONFIG_IPV6_SCTP__=y
+# CONFIG_IP_SCTP is not set
+# CONFIG_ATM is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_FASTROUTE is not set
+# CONFIG_NET_HW_FLOWCONTROL is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+CONFIG_NETDEVICES=y
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+# CONFIG_ETHERTAP is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+# CONFIG_MII is not set
+CONFIG_NET_SB1250_MAC=y
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_SUNGEM is not set
+# CONFIG_NET_VENDOR_3COM is not set
+
+#
+# Tulip family network device support
+#
+# CONFIG_NET_TULIP is not set
+# CONFIG_HP100 is not set
+# CONFIG_NET_PCI is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+# CONFIG_E1000 is not set
+# CONFIG_NS83820 is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+# CONFIG_R8169 is not set
+# CONFIG_SIS190 is not set
+# CONFIG_SK98LIN is not set
+# CONFIG_TIGON3 is not set
+
+#
+# Ethernet (10000 Mbit)
+#
+# CONFIG_IXGB is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Token Ring devices
+#
+# CONFIG_TR is not set
+# CONFIG_RCPCI is not set
+# CONFIG_SHAPER is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+
+#
+# Amateur Radio support
+#
+# CONFIG_HAMRADIO is not set
+
+#
+# IrDA (infrared) support
+#
+# CONFIG_IRDA is not set
+
+#
+# Bluetooth support
+#
+# CONFIG_BT is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN_BOOL is not set
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+# CONFIG_INPUT is not set
+
+#
+# Userland interfaces
+#
+
+#
+# Input I/O drivers
+#
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+CONFIG_SERIO=y
+CONFIG_SERIO_I8042=y
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_CT82C710 is not set
+# CONFIG_SERIO_PCIPS2 is not set
+
+#
+# Input Device Drivers
+#
+
+#
+# Character devices
+#
+# CONFIG_VT is not set
+CONFIG_SERIAL_NONSTANDARD=y
+# CONFIG_ROCKETPORT is not set
+# CONFIG_SYNCLINK is not set
+# CONFIG_SYNCLINKMP is not set
+# CONFIG_N_HDLC is not set
+# CONFIG_STALDRV is not set
+CONFIG_SIBYTE_SB1250_DUART=y
+CONFIG_SIBYTE_SB1250_DUART_CONSOLE=y
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+# CONFIG_UNIX98_PTYS is not set
+
+#
+# Mice
+#
+# CONFIG_BUSMOUSE is not set
+# CONFIG_QIC02_TAPE is not set
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_NVRAM is not set
+# CONFIG_RTC is not set
+# CONFIG_GEN_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_AGP is not set
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+# CONFIG_USB is not set
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+CONFIG_EXT2_FS_XATTR=y
+CONFIG_EXT2_FS_POSIX_ACL=y
+CONFIG_EXT2_FS_SECURITY=y
+# CONFIG_EXT3_FS is not set
+# CONFIG_JBD is not set
+CONFIG_FS_MBCACHE=y
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+CONFIG_FS_POSIX_ACL=y
+# CONFIG_XFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_QUOTA is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_FAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+# CONFIG_DEVFS_FS is not set
+# CONFIG_TMPFS is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
+# CONFIG_NFSD is not set
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+# CONFIG_EXPORTFS is not set
+CONFIG_SUNRPC=y
+# CONFIG_SUNRPC_GSS is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_INTERMEZZO_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+
+#
+# Native Language Support
+#
+# CONFIG_NLS is not set
+
+#
+# Kernel hacking
+#
+CONFIG_CROSSCOMPILE=y
+CONFIG_CMDLINE=""
+# CONFIG_DEBUG_KERNEL is not set
+
+#
+# Security options
+#
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+CONFIG_CRYPTO=y
+CONFIG_CRYPTO_HMAC=y
+CONFIG_CRYPTO_NULL=y
+CONFIG_CRYPTO_MD4=y
+CONFIG_CRYPTO_MD5=y
+CONFIG_CRYPTO_SHA1=y
+CONFIG_CRYPTO_SHA256=y
+CONFIG_CRYPTO_SHA512=y
+CONFIG_CRYPTO_DES=y
+CONFIG_CRYPTO_BLOWFISH=y
+CONFIG_CRYPTO_TWOFISH=y
+CONFIG_CRYPTO_SERPENT=y
+CONFIG_CRYPTO_AES=y
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+CONFIG_CRYPTO_DEFLATE=y
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Library routines
+#
+# CONFIG_CRC32 is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
--- diff/arch/mips/configs/sead_defconfig	1970-01-01 01:00:00.000000000 +0100
+++ source/arch/mips/configs/sead_defconfig	2004-02-23 13:56:38.000000000 +0000
@@ -0,0 +1,434 @@
+#
+# Automatically generated make config: don't edit
+#
+CONFIG_MIPS=y
+# CONFIG_MIPS64 is not set
+# CONFIG_64BIT is not set
+CONFIG_MIPS32=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_CLEAN_COMPILE=y
+CONFIG_STANDALONE=y
+CONFIG_BROKEN_ON_SMP=y
+
+#
+# General setup
+#
+CONFIG_SWAP=y
+# CONFIG_SYSVIPC is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_IKCONFIG is not set
+CONFIG_EMBEDDED=y
+CONFIG_KALLSYMS=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+
+#
+# Loadable module support
+#
+# CONFIG_MODULES is not set
+
+#
+# Machine selection
+#
+# CONFIG_MACH_JAZZ is not set
+# CONFIG_BAGET_MIPS is not set
+# CONFIG_MACH_VR41XX is not set
+# CONFIG_TOSHIBA_JMR3927 is not set
+# CONFIG_MIPS_COBALT is not set
+# CONFIG_MACH_DECSTATION is not set
+# CONFIG_MIPS_EV64120 is not set
+# CONFIG_MIPS_EV96100 is not set
+# CONFIG_MIPS_IVR is not set
+# CONFIG_LASAT is not set
+# CONFIG_HP_LASERJET is not set
+# CONFIG_MIPS_ITE8172 is not set
+# CONFIG_MIPS_ATLAS is not set
+# CONFIG_MIPS_MALTA is not set
+CONFIG_MIPS_SEAD=y
+# CONFIG_MOMENCO_OCELOT is not set
+# CONFIG_MOMENCO_OCELOT_G is not set
+# CONFIG_MOMENCO_OCELOT_C is not set
+# CONFIG_MOMENCO_JAGUAR_ATX is not set
+# CONFIG_PMC_YOSEMITE is not set
+# CONFIG_DDB5074 is not set
+# CONFIG_DDB5476 is not set
+# CONFIG_DDB5477 is not set
+# CONFIG_NEC_OSPREY is not set
+# CONFIG_SGI_IP22 is not set
+# CONFIG_SGI_IP32 is not set
+# CONFIG_SOC_AU1X00 is not set
+# CONFIG_SIBYTE_SB1xxx_SOC is not set
+# CONFIG_SNI_RM200_PCI is not set
+# CONFIG_TOSHIBA_RBTX4927 is not set
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_HAVE_DEC_LOCK=y
+CONFIG_DMA_NONCOHERENT=y
+CONFIG_CPU_LITTLE_ENDIAN=y
+CONFIG_IRQ_CPU=y
+CONFIG_MIPS_BOARDS_GEN=y
+CONFIG_MIPS_L1_CACHE_SHIFT=5
+# CONFIG_FB is not set
+
+#
+# CPU selection
+#
+CONFIG_CPU_MIPS32=y
+# CONFIG_CPU_MIPS64 is not set
+# CONFIG_CPU_R3000 is not set
+# CONFIG_CPU_TX39XX is not set
+# CONFIG_CPU_VR41XX is not set
+# CONFIG_CPU_R4300 is not set
+# CONFIG_CPU_R4X00 is not set
+# CONFIG_CPU_TX49XX is not set
+# CONFIG_CPU_R5000 is not set
+# CONFIG_CPU_R5432 is not set
+# CONFIG_CPU_R6000 is not set
+# CONFIG_CPU_NEVADA is not set
+# CONFIG_CPU_R8000 is not set
+# CONFIG_CPU_R10000 is not set
+# CONFIG_CPU_RM7000 is not set
+# CONFIG_CPU_RM9000 is not set
+# CONFIG_CPU_SB1 is not set
+CONFIG_PAGE_SIZE_4KB=y
+# CONFIG_PAGE_SIZE_16KB is not set
+# CONFIG_PAGE_SIZE_64KB is not set
+CONFIG_CPU_HAS_PREFETCH=y
+# CONFIG_VTAG_ICACHE is not set
+# CONFIG_64BIT_PHYS_ADDR is not set
+# CONFIG_CPU_ADVANCED is not set
+CONFIG_CPU_HAS_LLSC=y
+CONFIG_CPU_HAS_SYNC=y
+# CONFIG_PREEMPT is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+
+#
+# Bus options (PCI, PCMCIA, EISA, ISA, TC)
+#
+CONFIG_MMU=y
+# CONFIG_HOTPLUG is not set
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_MISC is not set
+CONFIG_TRAD_SIGNALS=y
+
+#
+# MIPS initrd options
+#
+CONFIG_EMBEDDED_RAMDISK=y
+CONFIG_EMBEDDED_RAMDISK_IMAGE="ramdisk.gz"
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+CONFIG_BLK_DEV_LOOP=y
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_SIZE=18432
+CONFIG_BLK_DEV_INITRD=y
+# CONFIG_LBD is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_SCSI is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+
+#
+# IEEE 1394 (FireWire) support (EXPERIMENTAL)
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+
+#
+# Macintosh device drivers
+#
+
+#
+# Networking support
+#
+# CONFIG_NET is not set
+
+#
+# Amateur Radio support
+#
+# CONFIG_HAMRADIO is not set
+
+#
+# ISDN subsystem
+#
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+CONFIG_INPUT_MOUSEDEV_PSAUX=y
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+# CONFIG_INPUT_EVDEV is not set
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input I/O drivers
+#
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+CONFIG_SERIO=y
+# CONFIG_SERIO_I8042 is not set
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_CT82C710 is not set
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=4
+# CONFIG_SERIAL_8250_EXTENDED is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_UNIX98_PTYS is not set
+
+#
+# Mice
+#
+# CONFIG_BUSMOUSE is not set
+# CONFIG_QIC02_TAPE is not set
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_NVRAM is not set
+# CONFIG_RTC is not set
+# CONFIG_GEN_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_FTAPE is not set
+# CONFIG_AGP is not set
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+
+#
+# Graphics support
+#
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+# CONFIG_MDA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+CONFIG_EXT2_FS_XATTR=y
+CONFIG_EXT2_FS_POSIX_ACL=y
+CONFIG_EXT2_FS_SECURITY=y
+# CONFIG_EXT3_FS is not set
+# CONFIG_JBD is not set
+CONFIG_FS_MBCACHE=y
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+CONFIG_FS_POSIX_ACL=y
+# CONFIG_XFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_QUOTA is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_FAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+# CONFIG_DEVFS_FS is not set
+# CONFIG_TMPFS is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+
+#
+# Native Language Support
+#
+# CONFIG_NLS is not set
+
+#
+# Kernel hacking
+#
+CONFIG_CROSSCOMPILE=y
+CONFIG_CMDLINE=""
+# CONFIG_DEBUG_KERNEL is not set
+
+#
+# Security options
+#
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
+# Library routines
+#
+# CONFIG_CRC32 is not set
--- diff/arch/mips/configs/tb0226_defconfig	1970-01-01 01:00:00.000000000 +0100
+++ source/arch/mips/configs/tb0226_defconfig	2004-02-23 13:56:38.000000000 +0000
@@ -0,0 +1,695 @@
+#
+# Automatically generated make config: don't edit
+#
+CONFIG_MIPS=y
+# CONFIG_MIPS64 is not set
+# CONFIG_64BIT is not set
+CONFIG_MIPS32=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_CLEAN_COMPILE=y
+CONFIG_STANDALONE=y
+CONFIG_BROKEN_ON_SMP=y
+
+#
+# General setup
+#
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_IKCONFIG is not set
+CONFIG_EMBEDDED=y
+CONFIG_KALLSYMS=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+CONFIG_OBSOLETE_MODPARM=y
+CONFIG_MODVERSIONS=y
+CONFIG_KMOD=y
+
+#
+# Machine selection
+#
+# CONFIG_MACH_JAZZ is not set
+# CONFIG_BAGET_MIPS is not set
+CONFIG_MACH_VR41XX=y
+# CONFIG_CASIO_E55 is not set
+# CONFIG_IBM_WORKPAD is not set
+# CONFIG_NEC_EAGLE is not set
+CONFIG_TANBAC_TB0226=y
+# CONFIG_TANBAC_TB0229 is not set
+# CONFIG_VICTOR_MPC30X is not set
+# CONFIG_ZAO_CAPCELLA is not set
+# CONFIG_TOSHIBA_JMR3927 is not set
+# CONFIG_MIPS_COBALT is not set
+# CONFIG_MACH_DECSTATION is not set
+# CONFIG_MIPS_EV64120 is not set
+# CONFIG_MIPS_EV96100 is not set
+# CONFIG_MIPS_IVR is not set
+# CONFIG_LASAT is not set
+# CONFIG_HP_LASERJET is not set
+# CONFIG_MIPS_ITE8172 is not set
+# CONFIG_MIPS_ATLAS is not set
+# CONFIG_MIPS_MALTA is not set
+# CONFIG_MIPS_SEAD is not set
+# CONFIG_MOMENCO_OCELOT is not set
+# CONFIG_MOMENCO_OCELOT_G is not set
+# CONFIG_MOMENCO_OCELOT_C is not set
+# CONFIG_MOMENCO_JAGUAR_ATX is not set
+# CONFIG_PMC_YOSEMITE is not set
+# CONFIG_DDB5074 is not set
+# CONFIG_DDB5476 is not set
+# CONFIG_DDB5477 is not set
+# CONFIG_NEC_OSPREY is not set
+# CONFIG_SGI_IP22 is not set
+# CONFIG_SGI_IP32 is not set
+# CONFIG_SOC_AU1X00 is not set
+# CONFIG_SIBYTE_SB1xxx_SOC is not set
+# CONFIG_SNI_RM200_PCI is not set
+# CONFIG_TOSHIBA_RBTX4927 is not set
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_HAVE_DEC_LOCK=y
+CONFIG_DMA_NONCOHERENT=y
+CONFIG_CPU_LITTLE_ENDIAN=y
+CONFIG_IRQ_CPU=y
+CONFIG_DUMMY_KEYB=y
+CONFIG_MIPS_L1_CACHE_SHIFT=5
+CONFIG_FB=y
+
+#
+# CPU selection
+#
+# CONFIG_CPU_MIPS32 is not set
+# CONFIG_CPU_MIPS64 is not set
+# CONFIG_CPU_R3000 is not set
+# CONFIG_CPU_TX39XX is not set
+CONFIG_CPU_VR41XX=y
+# CONFIG_CPU_R4300 is not set
+# CONFIG_CPU_R4X00 is not set
+# CONFIG_CPU_TX49XX is not set
+# CONFIG_CPU_R5000 is not set
+# CONFIG_CPU_R5432 is not set
+# CONFIG_CPU_R6000 is not set
+# CONFIG_CPU_NEVADA is not set
+# CONFIG_CPU_R8000 is not set
+# CONFIG_CPU_R10000 is not set
+# CONFIG_CPU_RM7000 is not set
+# CONFIG_CPU_RM9000 is not set
+# CONFIG_CPU_SB1 is not set
+CONFIG_PAGE_SIZE_4KB=y
+# CONFIG_PAGE_SIZE_16KB is not set
+# CONFIG_PAGE_SIZE_64KB is not set
+# CONFIG_CPU_ADVANCED is not set
+CONFIG_CPU_HAS_SYNC=y
+# CONFIG_PREEMPT is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+
+#
+# Bus options (PCI, PCMCIA, EISA, ISA, TC)
+#
+# CONFIG_PCI is not set
+CONFIG_MMU=y
+# CONFIG_HOTPLUG is not set
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_MISC is not set
+CONFIG_TRAD_SIGNALS=y
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+CONFIG_BLK_DEV_LOOP=m
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+CONFIG_BLK_DEV_NBD=m
+CONFIG_BLK_DEV_RAM=m
+CONFIG_BLK_DEV_RAM_SIZE=4096
+# CONFIG_BLK_DEV_INITRD is not set
+# CONFIG_LBD is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+CONFIG_IDE=y
+CONFIG_BLK_DEV_IDE=y
+
+#
+# Please see Documentation/ide.txt for help/info on IDE drives
+#
+CONFIG_BLK_DEV_IDEDISK=y
+CONFIG_IDEDISK_MULTI_MODE=y
+# CONFIG_IDEDISK_STROKE is not set
+# CONFIG_BLK_DEV_IDECD is not set
+# CONFIG_BLK_DEV_IDETAPE is not set
+# CONFIG_BLK_DEV_IDEFLOPPY is not set
+CONFIG_BLK_DEV_IDESCSI=y
+# CONFIG_IDE_TASK_IOCTL is not set
+CONFIG_IDE_TASKFILE_IO=y
+
+#
+# IDE chipset support/bugfixes
+#
+CONFIG_IDE_GENERIC=y
+# CONFIG_BLK_DEV_IDEDMA is not set
+# CONFIG_IDEDMA_AUTO is not set
+# CONFIG_DMA_NONPCI is not set
+# CONFIG_BLK_DEV_HD is not set
+
+#
+# SCSI device support
+#
+CONFIG_SCSI=y
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=y
+# CONFIG_CHR_DEV_ST is not set
+# CONFIG_CHR_DEV_OSST is not set
+CONFIG_BLK_DEV_SR=y
+# CONFIG_BLK_DEV_SR_VENDOR is not set
+CONFIG_CHR_DEV_SG=y
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+CONFIG_SCSI_MULTI_LUN=y
+# CONFIG_SCSI_REPORT_LUNS is not set
+CONFIG_SCSI_CONSTANTS=y
+# CONFIG_SCSI_LOGGING is not set
+
+#
+# SCSI low-level drivers
+#
+# CONFIG_SCSI_AIC7XXX_OLD is not set
+# CONFIG_SCSI_SATA is not set
+# CONFIG_SCSI_EATA_PIO is not set
+# CONFIG_SCSI_DEBUG is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+# CONFIG_FUSION is not set
+
+#
+# IEEE 1394 (FireWire) support (EXPERIMENTAL)
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+
+#
+# Macintosh device drivers
+#
+
+#
+# Networking support
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+CONFIG_NETLINK_DEV=m
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+CONFIG_IP_ADVANCED_ROUTER=y
+CONFIG_IP_MULTIPLE_TABLES=y
+CONFIG_IP_ROUTE_NAT=y
+CONFIG_IP_ROUTE_MULTIPATH=y
+CONFIG_IP_ROUTE_TOS=y
+CONFIG_IP_ROUTE_VERBOSE=y
+CONFIG_IP_PNP=y
+# CONFIG_IP_PNP_DHCP is not set
+CONFIG_IP_PNP_BOOTP=y
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_IP_MROUTE is not set
+# CONFIG_ARPD is not set
+# CONFIG_INET_ECN is not set
+CONFIG_SYN_COOKIES=y
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_IPV6 is not set
+# CONFIG_DECNET is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_NETFILTER is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+CONFIG_IPV6_SCTP__=y
+# CONFIG_IP_SCTP is not set
+# CONFIG_ATM is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_FASTROUTE is not set
+# CONFIG_NET_HW_FLOWCONTROL is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+# CONFIG_ETHERTAP is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+# CONFIG_MII is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+
+#
+# Ethernet (10000 Mbit)
+#
+CONFIG_PPP=m
+CONFIG_PPP_MULTILINK=y
+# CONFIG_PPP_FILTER is not set
+CONFIG_PPP_ASYNC=m
+CONFIG_PPP_SYNC_TTY=m
+CONFIG_PPP_DEFLATE=m
+CONFIG_PPP_BSDCOMP=m
+CONFIG_PPPOE=m
+# CONFIG_SLIP is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Token Ring devices
+#
+# CONFIG_SHAPER is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+
+#
+# Amateur Radio support
+#
+# CONFIG_HAMRADIO is not set
+
+#
+# IrDA (infrared) support
+#
+# CONFIG_IRDA is not set
+
+#
+# Bluetooth support
+#
+# CONFIG_BT is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN_BOOL is not set
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+CONFIG_INPUT_MOUSEDEV_PSAUX=y
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+# CONFIG_INPUT_EVDEV is not set
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input I/O drivers
+#
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+CONFIG_SERIO=y
+CONFIG_SERIO_I8042=y
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_CT82C710 is not set
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=4
+# CONFIG_SERIAL_8250_EXTENDED is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+CONFIG_UNIX98_PTY_COUNT=256
+
+#
+# Mice
+#
+# CONFIG_BUSMOUSE is not set
+# CONFIG_QIC02_TAPE is not set
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_NVRAM is not set
+# CONFIG_RTC is not set
+# CONFIG_GEN_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_FTAPE is not set
+# CONFIG_AGP is not set
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+# CONFIG_FB_VIRTUAL is not set
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+# CONFIG_MDA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+# CONFIG_FRAMEBUFFER_CONSOLE is not set
+
+#
+# Logo configuration
+#
+# CONFIG_LOGO is not set
+
+#
+# Sound
+#
+CONFIG_SOUND=y
+
+#
+# Advanced Linux Sound Architecture
+#
+# CONFIG_SND is not set
+
+#
+# Open Sound System
+#
+# CONFIG_SOUND_PRIME is not set
+
+#
+# USB support
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_JBD is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_MINIX_FS is not set
+CONFIG_ROMFS_FS=m
+# CONFIG_QUOTA is not set
+# CONFIG_AUTOFS_FS is not set
+CONFIG_AUTOFS4_FS=y
+
+#
+# CD-ROM/DVD Filesystems
+#
+CONFIG_ISO9660_FS=y
+CONFIG_JOLIET=y
+CONFIG_ZISOFS=y
+CONFIG_ZISOFS_FS=y
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=m
+CONFIG_MSDOS_FS=m
+CONFIG_VFAT_FS=m
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+# CONFIG_DEVFS_FS is not set
+CONFIG_DEVPTS_FS=y
+CONFIG_DEVPTS_FS_XATTR=y
+CONFIG_DEVPTS_FS_SECURITY=y
+CONFIG_TMPFS=y
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+CONFIG_CRAMFS=m
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
+CONFIG_NFSD=m
+CONFIG_NFSD_V3=y
+# CONFIG_NFSD_V4 is not set
+# CONFIG_NFSD_TCP is not set
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_EXPORTFS=m
+CONFIG_SUNRPC=y
+# CONFIG_SUNRPC_GSS is not set
+CONFIG_SMB_FS=m
+CONFIG_SMB_NLS_DEFAULT=y
+CONFIG_SMB_NLS_REMOTE="cp932"
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_INTERMEZZO_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+
+#
+# Native Language Support
+#
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="iso8859-1"
+CONFIG_NLS_CODEPAGE_437=m
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+CONFIG_NLS_CODEPAGE_932=m
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+CONFIG_NLS_ISO8859_1=m
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+# CONFIG_NLS_UTF8 is not set
+
+#
+# Kernel hacking
+#
+CONFIG_CROSSCOMPILE=y
+CONFIG_CMDLINE=""
+# CONFIG_DEBUG_KERNEL is not set
+
+#
+# Security options
+#
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
+# Library routines
+#
+# CONFIG_CRC32 is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=m
--- diff/arch/mips/configs/tb0229_defconfig	1970-01-01 01:00:00.000000000 +0100
+++ source/arch/mips/configs/tb0229_defconfig	2004-02-23 13:56:38.000000000 +0000
@@ -0,0 +1,686 @@
+#
+# Automatically generated make config: don't edit
+#
+CONFIG_MIPS=y
+# CONFIG_MIPS64 is not set
+# CONFIG_64BIT is not set
+CONFIG_MIPS32=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_CLEAN_COMPILE=y
+CONFIG_STANDALONE=y
+CONFIG_BROKEN_ON_SMP=y
+
+#
+# General setup
+#
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_IKCONFIG is not set
+CONFIG_EMBEDDED=y
+CONFIG_KALLSYMS=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+CONFIG_OBSOLETE_MODPARM=y
+CONFIG_MODVERSIONS=y
+CONFIG_KMOD=y
+
+#
+# Machine selection
+#
+# CONFIG_MACH_JAZZ is not set
+# CONFIG_BAGET_MIPS is not set
+CONFIG_MACH_VR41XX=y
+# CONFIG_CASIO_E55 is not set
+# CONFIG_IBM_WORKPAD is not set
+# CONFIG_NEC_EAGLE is not set
+# CONFIG_TANBAC_TB0226 is not set
+CONFIG_TANBAC_TB0229=y
+# CONFIG_VICTOR_MPC30X is not set
+# CONFIG_ZAO_CAPCELLA is not set
+# CONFIG_TOSHIBA_JMR3927 is not set
+# CONFIG_MIPS_COBALT is not set
+# CONFIG_MACH_DECSTATION is not set
+# CONFIG_MIPS_EV64120 is not set
+# CONFIG_MIPS_EV96100 is not set
+# CONFIG_MIPS_IVR is not set
+# CONFIG_LASAT is not set
+# CONFIG_HP_LASERJET is not set
+# CONFIG_MIPS_ITE8172 is not set
+# CONFIG_MIPS_ATLAS is not set
+# CONFIG_MIPS_MALTA is not set
+# CONFIG_MIPS_SEAD is not set
+# CONFIG_MOMENCO_OCELOT is not set
+# CONFIG_MOMENCO_OCELOT_G is not set
+# CONFIG_MOMENCO_OCELOT_C is not set
+# CONFIG_MOMENCO_JAGUAR_ATX is not set
+# CONFIG_PMC_YOSEMITE is not set
+# CONFIG_DDB5074 is not set
+# CONFIG_DDB5476 is not set
+# CONFIG_DDB5477 is not set
+# CONFIG_NEC_OSPREY is not set
+# CONFIG_SGI_IP22 is not set
+# CONFIG_SGI_IP32 is not set
+# CONFIG_SOC_AU1X00 is not set
+# CONFIG_SIBYTE_SB1xxx_SOC is not set
+# CONFIG_SNI_RM200_PCI is not set
+# CONFIG_TOSHIBA_RBTX4927 is not set
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_HAVE_DEC_LOCK=y
+CONFIG_DMA_NONCOHERENT=y
+CONFIG_CPU_LITTLE_ENDIAN=y
+CONFIG_IRQ_CPU=y
+CONFIG_DUMMY_KEYB=y
+CONFIG_MIPS_L1_CACHE_SHIFT=5
+# CONFIG_FB is not set
+CONFIG_TANBAC_TB0219=y
+
+#
+# CPU selection
+#
+# CONFIG_CPU_MIPS32 is not set
+# CONFIG_CPU_MIPS64 is not set
+# CONFIG_CPU_R3000 is not set
+# CONFIG_CPU_TX39XX is not set
+CONFIG_CPU_VR41XX=y
+# CONFIG_CPU_R4300 is not set
+# CONFIG_CPU_R4X00 is not set
+# CONFIG_CPU_TX49XX is not set
+# CONFIG_CPU_R5000 is not set
+# CONFIG_CPU_R5432 is not set
+# CONFIG_CPU_R6000 is not set
+# CONFIG_CPU_NEVADA is not set
+# CONFIG_CPU_R8000 is not set
+# CONFIG_CPU_R10000 is not set
+# CONFIG_CPU_RM7000 is not set
+# CONFIG_CPU_RM9000 is not set
+# CONFIG_CPU_SB1 is not set
+CONFIG_PAGE_SIZE_4KB=y
+# CONFIG_PAGE_SIZE_16KB is not set
+# CONFIG_PAGE_SIZE_64KB is not set
+# CONFIG_CPU_ADVANCED is not set
+CONFIG_CPU_HAS_SYNC=y
+# CONFIG_PREEMPT is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+
+#
+# Bus options (PCI, PCMCIA, EISA, ISA, TC)
+#
+CONFIG_PCI=y
+CONFIG_PCI_LEGACY_PROC=y
+CONFIG_PCI_NAMES=y
+CONFIG_MMU=y
+# CONFIG_HOTPLUG is not set
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_MISC is not set
+CONFIG_TRAD_SIGNALS=y
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_UMEM is not set
+CONFIG_BLK_DEV_LOOP=m
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+CONFIG_BLK_DEV_NBD=m
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_SIZE=4096
+# CONFIG_BLK_DEV_INITRD is not set
+# CONFIG_LBD is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_SCSI is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+
+#
+# IEEE 1394 (FireWire) support (EXPERIMENTAL)
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+
+#
+# Macintosh device drivers
+#
+
+#
+# Networking support
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+CONFIG_NETLINK_DEV=m
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+CONFIG_IP_ADVANCED_ROUTER=y
+CONFIG_IP_MULTIPLE_TABLES=y
+CONFIG_IP_ROUTE_NAT=y
+CONFIG_IP_ROUTE_MULTIPATH=y
+CONFIG_IP_ROUTE_TOS=y
+CONFIG_IP_ROUTE_VERBOSE=y
+CONFIG_IP_PNP=y
+# CONFIG_IP_PNP_DHCP is not set
+CONFIG_IP_PNP_BOOTP=y
+# CONFIG_IP_PNP_RARP is not set
+CONFIG_NET_IPIP=m
+CONFIG_NET_IPGRE=m
+# CONFIG_NET_IPGRE_BROADCAST is not set
+# CONFIG_IP_MROUTE is not set
+# CONFIG_ARPD is not set
+# CONFIG_INET_ECN is not set
+CONFIG_SYN_COOKIES=y
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_IPV6 is not set
+# CONFIG_DECNET is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_NETFILTER is not set
+CONFIG_XFRM=y
+# CONFIG_XFRM_USER is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+CONFIG_IPV6_SCTP__=y
+# CONFIG_IP_SCTP is not set
+# CONFIG_ATM is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_FASTROUTE is not set
+# CONFIG_NET_HW_FLOWCONTROL is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+CONFIG_NETDEVICES=y
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+CONFIG_DUMMY=m
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+# CONFIG_ETHERTAP is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+# CONFIG_MII is not set
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_SUNGEM is not set
+# CONFIG_NET_VENDOR_3COM is not set
+
+#
+# Tulip family network device support
+#
+# CONFIG_NET_TULIP is not set
+# CONFIG_HP100 is not set
+# CONFIG_NET_PCI is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+# CONFIG_E1000 is not set
+# CONFIG_NS83820 is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+# CONFIG_R8169 is not set
+# CONFIG_SIS190 is not set
+# CONFIG_SK98LIN is not set
+# CONFIG_TIGON3 is not set
+
+#
+# Ethernet (10000 Mbit)
+#
+# CONFIG_IXGB is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+CONFIG_PPP=m
+CONFIG_PPP_MULTILINK=y
+CONFIG_PPP_FILTER=y
+CONFIG_PPP_ASYNC=m
+CONFIG_PPP_SYNC_TTY=m
+CONFIG_PPP_DEFLATE=m
+CONFIG_PPP_BSDCOMP=m
+CONFIG_PPPOE=m
+CONFIG_SLIP=m
+CONFIG_SLIP_COMPRESSED=y
+CONFIG_SLIP_SMART=y
+CONFIG_SLIP_MODE_SLIP6=y
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Token Ring devices
+#
+# CONFIG_TR is not set
+# CONFIG_RCPCI is not set
+# CONFIG_SHAPER is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+
+#
+# Amateur Radio support
+#
+# CONFIG_HAMRADIO is not set
+
+#
+# IrDA (infrared) support
+#
+# CONFIG_IRDA is not set
+
+#
+# Bluetooth support
+#
+# CONFIG_BT is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN_BOOL is not set
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+CONFIG_INPUT_MOUSEDEV_PSAUX=y
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+# CONFIG_INPUT_EVDEV is not set
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input I/O drivers
+#
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+CONFIG_SERIO=y
+CONFIG_SERIO_I8042=y
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_CT82C710 is not set
+# CONFIG_SERIO_PCIPS2 is not set
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=4
+# CONFIG_SERIAL_8250_EXTENDED is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+CONFIG_UNIX98_PTY_COUNT=256
+
+#
+# Mice
+#
+# CONFIG_BUSMOUSE is not set
+# CONFIG_QIC02_TAPE is not set
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_NVRAM is not set
+# CONFIG_RTC is not set
+# CONFIG_GEN_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_FTAPE is not set
+# CONFIG_AGP is not set
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+# CONFIG_MDA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+# CONFIG_USB is not set
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+CONFIG_EXT3_FS=m
+CONFIG_EXT3_FS_XATTR=y
+# CONFIG_EXT3_FS_POSIX_ACL is not set
+CONFIG_EXT3_FS_SECURITY=y
+CONFIG_JBD=m
+# CONFIG_JBD_DEBUG is not set
+CONFIG_FS_MBCACHE=y
+# CONFIG_REISERFS_FS is not set
+CONFIG_JFS_FS=m
+# CONFIG_JFS_POSIX_ACL is not set
+# CONFIG_JFS_DEBUG is not set
+# CONFIG_JFS_STATISTICS is not set
+CONFIG_XFS_FS=y
+# CONFIG_XFS_RT is not set
+CONFIG_XFS_QUOTA=y
+# CONFIG_XFS_SECURITY is not set
+CONFIG_XFS_POSIX_ACL=y
+# CONFIG_MINIX_FS is not set
+CONFIG_ROMFS_FS=m
+# CONFIG_QUOTA is not set
+CONFIG_QUOTACTL=y
+# CONFIG_AUTOFS_FS is not set
+CONFIG_AUTOFS4_FS=y
+
+#
+# CD-ROM/DVD Filesystems
+#
+CONFIG_ISO9660_FS=y
+CONFIG_JOLIET=y
+CONFIG_ZISOFS=y
+CONFIG_ZISOFS_FS=y
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=m
+CONFIG_MSDOS_FS=m
+CONFIG_VFAT_FS=m
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+# CONFIG_DEVFS_FS is not set
+CONFIG_DEVPTS_FS=y
+CONFIG_DEVPTS_FS_XATTR=y
+CONFIG_DEVPTS_FS_SECURITY=y
+CONFIG_TMPFS=y
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+CONFIG_CRAMFS=m
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
+CONFIG_NFSD=y
+CONFIG_NFSD_V3=y
+# CONFIG_NFSD_V4 is not set
+CONFIG_NFSD_TCP=y
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_EXPORTFS=y
+CONFIG_SUNRPC=y
+# CONFIG_SUNRPC_GSS is not set
+CONFIG_SMB_FS=m
+CONFIG_SMB_NLS_DEFAULT=y
+CONFIG_SMB_NLS_REMOTE="cp932"
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_INTERMEZZO_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+
+#
+# Native Language Support
+#
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="iso8859-1"
+CONFIG_NLS_CODEPAGE_437=m
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+CONFIG_NLS_CODEPAGE_932=m
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+CONFIG_NLS_ISO8859_1=m
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+# CONFIG_NLS_UTF8 is not set
+
+#
+# Kernel hacking
+#
+CONFIG_CROSSCOMPILE=y
+CONFIG_CMDLINE=""
+# CONFIG_DEBUG_KERNEL is not set
+
+#
+# Security options
+#
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
+# Library routines
+#
+# CONFIG_CRC32 is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=m
--- diff/arch/mips/configs/workpad_defconfig	1970-01-01 01:00:00.000000000 +0100
+++ source/arch/mips/configs/workpad_defconfig	2004-02-23 13:56:38.000000000 +0000
@@ -0,0 +1,593 @@
+#
+# Automatically generated make config: don't edit
+#
+CONFIG_MIPS=y
+# CONFIG_MIPS64 is not set
+# CONFIG_64BIT is not set
+CONFIG_MIPS32=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_CLEAN_COMPILE=y
+CONFIG_STANDALONE=y
+CONFIG_BROKEN_ON_SMP=y
+
+#
+# General setup
+#
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_IKCONFIG is not set
+CONFIG_EMBEDDED=y
+CONFIG_KALLSYMS=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+CONFIG_OBSOLETE_MODPARM=y
+CONFIG_MODVERSIONS=y
+CONFIG_KMOD=y
+
+#
+# Machine selection
+#
+# CONFIG_MACH_JAZZ is not set
+# CONFIG_BAGET_MIPS is not set
+CONFIG_MACH_VR41XX=y
+# CONFIG_CASIO_E55 is not set
+CONFIG_IBM_WORKPAD=y
+# CONFIG_NEC_EAGLE is not set
+# CONFIG_TANBAC_TB0226 is not set
+# CONFIG_TANBAC_TB0229 is not set
+# CONFIG_VICTOR_MPC30X is not set
+# CONFIG_ZAO_CAPCELLA is not set
+# CONFIG_TOSHIBA_JMR3927 is not set
+# CONFIG_MIPS_COBALT is not set
+# CONFIG_MACH_DECSTATION is not set
+# CONFIG_MIPS_EV64120 is not set
+# CONFIG_MIPS_EV96100 is not set
+# CONFIG_MIPS_IVR is not set
+# CONFIG_LASAT is not set
+# CONFIG_HP_LASERJET is not set
+# CONFIG_MIPS_ITE8172 is not set
+# CONFIG_MIPS_ATLAS is not set
+# CONFIG_MIPS_MALTA is not set
+# CONFIG_MIPS_SEAD is not set
+# CONFIG_MOMENCO_OCELOT is not set
+# CONFIG_MOMENCO_OCELOT_G is not set
+# CONFIG_MOMENCO_OCELOT_C is not set
+# CONFIG_MOMENCO_JAGUAR_ATX is not set
+# CONFIG_PMC_YOSEMITE is not set
+# CONFIG_DDB5074 is not set
+# CONFIG_DDB5476 is not set
+# CONFIG_DDB5477 is not set
+# CONFIG_NEC_OSPREY is not set
+# CONFIG_SGI_IP22 is not set
+# CONFIG_SGI_IP32 is not set
+# CONFIG_SOC_AU1X00 is not set
+# CONFIG_SIBYTE_SB1xxx_SOC is not set
+# CONFIG_SNI_RM200_PCI is not set
+# CONFIG_TOSHIBA_RBTX4927 is not set
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_HAVE_DEC_LOCK=y
+CONFIG_DMA_NONCOHERENT=y
+CONFIG_CPU_LITTLE_ENDIAN=y
+CONFIG_IRQ_CPU=y
+CONFIG_VRC4171=y
+CONFIG_MIPS_L1_CACHE_SHIFT=5
+# CONFIG_FB is not set
+
+#
+# CPU selection
+#
+# CONFIG_CPU_MIPS32 is not set
+# CONFIG_CPU_MIPS64 is not set
+# CONFIG_CPU_R3000 is not set
+# CONFIG_CPU_TX39XX is not set
+CONFIG_CPU_VR41XX=y
+# CONFIG_CPU_R4300 is not set
+# CONFIG_CPU_R4X00 is not set
+# CONFIG_CPU_TX49XX is not set
+# CONFIG_CPU_R5000 is not set
+# CONFIG_CPU_R5432 is not set
+# CONFIG_CPU_R6000 is not set
+# CONFIG_CPU_NEVADA is not set
+# CONFIG_CPU_R8000 is not set
+# CONFIG_CPU_R10000 is not set
+# CONFIG_CPU_RM7000 is not set
+# CONFIG_CPU_RM9000 is not set
+# CONFIG_CPU_SB1 is not set
+CONFIG_PAGE_SIZE_4KB=y
+# CONFIG_PAGE_SIZE_16KB is not set
+# CONFIG_PAGE_SIZE_64KB is not set
+# CONFIG_CPU_ADVANCED is not set
+CONFIG_CPU_HAS_SYNC=y
+# CONFIG_PREEMPT is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+
+#
+# Bus options (PCI, PCMCIA, EISA, ISA, TC)
+#
+CONFIG_MMU=y
+# CONFIG_HOTPLUG is not set
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_MISC is not set
+CONFIG_TRAD_SIGNALS=y
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+# CONFIG_BLK_DEV_LOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_RAM is not set
+# CONFIG_BLK_DEV_INITRD is not set
+# CONFIG_LBD is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+CONFIG_IDE=y
+CONFIG_BLK_DEV_IDE=y
+
+#
+# Please see Documentation/ide.txt for help/info on IDE drives
+#
+CONFIG_BLK_DEV_IDEDISK=y
+# CONFIG_IDEDISK_MULTI_MODE is not set
+# CONFIG_IDEDISK_STROKE is not set
+# CONFIG_BLK_DEV_IDECD is not set
+# CONFIG_BLK_DEV_IDETAPE is not set
+# CONFIG_BLK_DEV_IDEFLOPPY is not set
+# CONFIG_IDE_TASK_IOCTL is not set
+CONFIG_IDE_TASKFILE_IO=y
+
+#
+# IDE chipset support/bugfixes
+#
+CONFIG_IDE_GENERIC=y
+# CONFIG_BLK_DEV_IDEDMA is not set
+# CONFIG_IDEDMA_AUTO is not set
+# CONFIG_DMA_NONPCI is not set
+# CONFIG_BLK_DEV_HD is not set
+
+#
+# SCSI device support
+#
+# CONFIG_SCSI is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+
+#
+# IEEE 1394 (FireWire) support (EXPERIMENTAL)
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+
+#
+# Macintosh device drivers
+#
+
+#
+# Networking support
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+CONFIG_PACKET_MMAP=y
+CONFIG_NETLINK_DEV=y
+CONFIG_UNIX=y
+CONFIG_NET_KEY=y
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+# CONFIG_IP_ADVANCED_ROUTER is not set
+# CONFIG_IP_PNP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_IP_MROUTE is not set
+# CONFIG_ARPD is not set
+# CONFIG_INET_ECN is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_IPV6 is not set
+# CONFIG_DECNET is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_NETFILTER is not set
+CONFIG_XFRM=y
+# CONFIG_XFRM_USER is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+CONFIG_IPV6_SCTP__=y
+# CONFIG_IP_SCTP is not set
+# CONFIG_ATM is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_FASTROUTE is not set
+# CONFIG_NET_HW_FLOWCONTROL is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+# CONFIG_ETHERTAP is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+# CONFIG_MII is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+
+#
+# Ethernet (10000 Mbit)
+#
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Token Ring devices
+#
+# CONFIG_SHAPER is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+
+#
+# Amateur Radio support
+#
+# CONFIG_HAMRADIO is not set
+
+#
+# IrDA (infrared) support
+#
+# CONFIG_IRDA is not set
+
+#
+# Bluetooth support
+#
+# CONFIG_BT is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN_BOOL is not set
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+CONFIG_INPUT_MOUSEDEV_PSAUX=y
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+# CONFIG_INPUT_EVDEV is not set
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input I/O drivers
+#
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+CONFIG_SERIO=y
+CONFIG_SERIO_I8042=y
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_CT82C710 is not set
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=4
+# CONFIG_SERIAL_8250_EXTENDED is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+CONFIG_UNIX98_PTY_COUNT=256
+
+#
+# Mice
+#
+# CONFIG_BUSMOUSE is not set
+# CONFIG_QIC02_TAPE is not set
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+CONFIG_WATCHDOG=y
+# CONFIG_WATCHDOG_NOWAYOUT is not set
+
+#
+# Watchdog Device Drivers
+#
+# CONFIG_SOFT_WATCHDOG is not set
+# CONFIG_NVRAM is not set
+# CONFIG_RTC is not set
+# CONFIG_GEN_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_FTAPE is not set
+# CONFIG_AGP is not set
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+# CONFIG_MDA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+CONFIG_EXT2_FS_XATTR=y
+CONFIG_EXT2_FS_POSIX_ACL=y
+CONFIG_EXT2_FS_SECURITY=y
+# CONFIG_EXT3_FS is not set
+# CONFIG_JBD is not set
+CONFIG_FS_MBCACHE=y
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+CONFIG_FS_POSIX_ACL=y
+# CONFIG_XFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_QUOTA is not set
+CONFIG_AUTOFS_FS=y
+CONFIG_AUTOFS4_FS=y
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_FAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+# CONFIG_DEVFS_FS is not set
+CONFIG_DEVPTS_FS=y
+CONFIG_DEVPTS_FS_XATTR=y
+CONFIG_DEVPTS_FS_SECURITY=y
+# CONFIG_TMPFS is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+# CONFIG_NFS_V3 is not set
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
+CONFIG_NFSD=y
+# CONFIG_NFSD_V3 is not set
+# CONFIG_NFSD_TCP is not set
+CONFIG_LOCKD=y
+CONFIG_EXPORTFS=y
+CONFIG_SUNRPC=y
+# CONFIG_SUNRPC_GSS is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_INTERMEZZO_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+
+#
+# Native Language Support
+#
+# CONFIG_NLS is not set
+
+#
+# Kernel hacking
+#
+CONFIG_CROSSCOMPILE=y
+CONFIG_CMDLINE=""
+# CONFIG_DEBUG_KERNEL is not set
+
+#
+# Security options
+#
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
+# Library routines
+#
+# CONFIG_CRC32 is not set
--- diff/arch/mips/configs/xxs1500_defconfig	1970-01-01 01:00:00.000000000 +0100
+++ source/arch/mips/configs/xxs1500_defconfig	2004-02-23 13:56:38.000000000 +0000
@@ -0,0 +1,673 @@
+#
+# Automatically generated make config: don't edit
+#
+CONFIG_MIPS=y
+# CONFIG_MIPS64 is not set
+# CONFIG_64BIT is not set
+CONFIG_MIPS32=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_CLEAN_COMPILE=y
+CONFIG_STANDALONE=y
+CONFIG_BROKEN_ON_SMP=y
+
+#
+# General setup
+#
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_IKCONFIG is not set
+CONFIG_EMBEDDED=y
+CONFIG_KALLSYMS=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+CONFIG_OBSOLETE_MODPARM=y
+CONFIG_MODVERSIONS=y
+CONFIG_KMOD=y
+
+#
+# Machine selection
+#
+# CONFIG_MACH_JAZZ is not set
+# CONFIG_BAGET_MIPS is not set
+# CONFIG_MACH_VR41XX is not set
+# CONFIG_TOSHIBA_JMR3927 is not set
+# CONFIG_MIPS_COBALT is not set
+# CONFIG_MACH_DECSTATION is not set
+# CONFIG_MIPS_EV64120 is not set
+# CONFIG_MIPS_EV96100 is not set
+# CONFIG_MIPS_IVR is not set
+# CONFIG_LASAT is not set
+# CONFIG_HP_LASERJET is not set
+# CONFIG_MIPS_ITE8172 is not set
+# CONFIG_MIPS_ATLAS is not set
+# CONFIG_MIPS_MALTA is not set
+# CONFIG_MIPS_SEAD is not set
+# CONFIG_MOMENCO_OCELOT is not set
+# CONFIG_MOMENCO_OCELOT_G is not set
+# CONFIG_MOMENCO_OCELOT_C is not set
+# CONFIG_MOMENCO_JAGUAR_ATX is not set
+# CONFIG_PMC_YOSEMITE is not set
+# CONFIG_DDB5074 is not set
+# CONFIG_DDB5476 is not set
+# CONFIG_DDB5477 is not set
+# CONFIG_NEC_OSPREY is not set
+# CONFIG_SGI_IP22 is not set
+# CONFIG_SGI_IP32 is not set
+# CONFIG_SOC_AU1X00 is not set
+# CONFIG_SIBYTE_SB1xxx_SOC is not set
+# CONFIG_SNI_RM200_PCI is not set
+# CONFIG_TOSHIBA_RBTX4927 is not set
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_HAVE_DEC_LOCK=y
+CONFIG_CPU_LITTLE_ENDIAN=y
+CONFIG_MIPS_L1_CACHE_SHIFT=5
+# CONFIG_FB is not set
+
+#
+# CPU selection
+#
+CONFIG_CPU_MIPS32=y
+# CONFIG_CPU_MIPS64 is not set
+# CONFIG_CPU_R3000 is not set
+# CONFIG_CPU_TX39XX is not set
+# CONFIG_CPU_VR41XX is not set
+# CONFIG_CPU_R4300 is not set
+# CONFIG_CPU_R4X00 is not set
+# CONFIG_CPU_TX49XX is not set
+# CONFIG_CPU_R5000 is not set
+# CONFIG_CPU_R5432 is not set
+# CONFIG_CPU_R6000 is not set
+# CONFIG_CPU_NEVADA is not set
+# CONFIG_CPU_R8000 is not set
+# CONFIG_CPU_R10000 is not set
+# CONFIG_CPU_RM7000 is not set
+# CONFIG_CPU_RM9000 is not set
+# CONFIG_CPU_SB1 is not set
+CONFIG_PAGE_SIZE_4KB=y
+# CONFIG_PAGE_SIZE_16KB is not set
+# CONFIG_PAGE_SIZE_64KB is not set
+CONFIG_CPU_HAS_PREFETCH=y
+# CONFIG_VTAG_ICACHE is not set
+# CONFIG_64BIT_PHYS_ADDR is not set
+# CONFIG_CPU_ADVANCED is not set
+CONFIG_CPU_HAS_LLSC=y
+CONFIG_CPU_HAS_SYNC=y
+# CONFIG_PREEMPT is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+
+#
+# Bus options (PCI, PCMCIA, EISA, ISA, TC)
+#
+CONFIG_MMU=y
+CONFIG_HOTPLUG=y
+
+#
+# PCMCIA/CardBus support
+#
+CONFIG_PCMCIA=m
+# CONFIG_TCIC is not set
+
+#
+# PCI Hotplug Support
+#
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_MISC is not set
+CONFIG_TRAD_SIGNALS=y
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+# CONFIG_FW_LOADER is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+CONFIG_BLK_DEV_LOOP=y
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_RAM is not set
+# CONFIG_BLK_DEV_INITRD is not set
+# CONFIG_LBD is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_SCSI is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+
+#
+# IEEE 1394 (FireWire) support (EXPERIMENTAL)
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+
+#
+# Macintosh device drivers
+#
+
+#
+# Networking support
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+CONFIG_NETLINK_DEV=y
+CONFIG_UNIX=y
+CONFIG_NET_KEY=y
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_PNP=y
+# CONFIG_IP_PNP_DHCP is not set
+CONFIG_IP_PNP_BOOTP=y
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_IP_MROUTE is not set
+# CONFIG_ARPD is not set
+# CONFIG_INET_ECN is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+
+#
+# IP: Virtual Server Configuration
+#
+# CONFIG_IP_VS is not set
+# CONFIG_IPV6 is not set
+# CONFIG_DECNET is not set
+# CONFIG_BRIDGE is not set
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
+
+#
+# IP: Netfilter Configuration
+#
+# CONFIG_IP_NF_CONNTRACK is not set
+# CONFIG_IP_NF_QUEUE is not set
+# CONFIG_IP_NF_IPTABLES is not set
+# CONFIG_IP_NF_ARPTABLES is not set
+# CONFIG_IP_NF_COMPAT_IPCHAINS is not set
+# CONFIG_IP_NF_COMPAT_IPFWADM is not set
+CONFIG_XFRM=y
+# CONFIG_XFRM_USER is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+CONFIG_IPV6_SCTP__=y
+# CONFIG_IP_SCTP is not set
+# CONFIG_ATM is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_FASTROUTE is not set
+# CONFIG_NET_HW_FLOWCONTROL is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+# CONFIG_ETHERTAP is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+# CONFIG_MII is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+
+#
+# Ethernet (10000 Mbit)
+#
+CONFIG_PPP=m
+CONFIG_PPP_MULTILINK=y
+# CONFIG_PPP_FILTER is not set
+CONFIG_PPP_ASYNC=m
+# CONFIG_PPP_SYNC_TTY is not set
+CONFIG_PPP_DEFLATE=m
+# CONFIG_PPP_BSDCOMP is not set
+CONFIG_PPPOE=m
+# CONFIG_SLIP is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Token Ring devices
+#
+# CONFIG_SHAPER is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+
+#
+# PCMCIA network device support
+#
+CONFIG_NET_PCMCIA=y
+CONFIG_PCMCIA_3C589=m
+# CONFIG_PCMCIA_3C574 is not set
+# CONFIG_PCMCIA_FMVJ18X is not set
+# CONFIG_PCMCIA_PCNET is not set
+# CONFIG_PCMCIA_NMCLAN is not set
+# CONFIG_PCMCIA_SMC91C92 is not set
+# CONFIG_PCMCIA_XIRC2PS is not set
+# CONFIG_PCMCIA_AXNET is not set
+
+#
+# Amateur Radio support
+#
+# CONFIG_HAMRADIO is not set
+
+#
+# IrDA (infrared) support
+#
+# CONFIG_IRDA is not set
+
+#
+# Bluetooth support
+#
+# CONFIG_BT is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN_BOOL is not set
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+CONFIG_INPUT_MOUSEDEV_PSAUX=y
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input I/O drivers
+#
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+CONFIG_SERIO=y
+# CONFIG_SERIO_I8042 is not set
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_CT82C710 is not set
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_UNIX98_PTYS=y
+CONFIG_UNIX98_PTY_COUNT=256
+
+#
+# Mice
+#
+# CONFIG_BUSMOUSE is not set
+# CONFIG_QIC02_TAPE is not set
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_NVRAM is not set
+CONFIG_RTC=y
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_FTAPE is not set
+# CONFIG_AGP is not set
+# CONFIG_DRM is not set
+
+#
+# PCMCIA character devices
+#
+# CONFIG_SYNCLINK_CS is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+# CONFIG_MDA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+CONFIG_EXT2_FS_XATTR=y
+CONFIG_EXT2_FS_POSIX_ACL=y
+# CONFIG_EXT2_FS_SECURITY is not set
+CONFIG_EXT3_FS=y
+CONFIG_EXT3_FS_XATTR=y
+CONFIG_EXT3_FS_POSIX_ACL=y
+CONFIG_EXT3_FS_SECURITY=y
+CONFIG_JBD=y
+# CONFIG_JBD_DEBUG is not set
+CONFIG_FS_MBCACHE=y
+CONFIG_REISERFS_FS=m
+# CONFIG_REISERFS_CHECK is not set
+# CONFIG_REISERFS_PROC_INFO is not set
+# CONFIG_JFS_FS is not set
+CONFIG_FS_POSIX_ACL=y
+# CONFIG_XFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_QUOTA is not set
+CONFIG_AUTOFS_FS=m
+CONFIG_AUTOFS4_FS=m
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_FAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+# CONFIG_DEVFS_FS is not set
+CONFIG_DEVPTS_FS=y
+CONFIG_DEVPTS_FS_XATTR=y
+CONFIG_DEVPTS_FS_SECURITY=y
+CONFIG_TMPFS=y
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+CONFIG_CRAMFS=m
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+# CONFIG_NFS_V3 is not set
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
+CONFIG_NFSD=m
+# CONFIG_NFSD_V3 is not set
+# CONFIG_NFSD_TCP is not set
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+CONFIG_EXPORTFS=m
+CONFIG_SUNRPC=y
+# CONFIG_SUNRPC_GSS is not set
+CONFIG_SMB_FS=m
+# CONFIG_SMB_NLS_DEFAULT is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_INTERMEZZO_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+
+#
+# Native Language Support
+#
+CONFIG_NLS=m
+CONFIG_NLS_DEFAULT="iso8859-1"
+# CONFIG_NLS_CODEPAGE_437 is not set
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ISO8859_1 is not set
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+# CONFIG_NLS_UTF8 is not set
+
+#
+# Kernel hacking
+#
+CONFIG_CROSSCOMPILE=y
+CONFIG_CMDLINE=""
+# CONFIG_DEBUG_KERNEL is not set
+
+#
+# Security options
+#
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+CONFIG_CRYPTO=y
+CONFIG_CRYPTO_HMAC=y
+CONFIG_CRYPTO_NULL=y
+# CONFIG_CRYPTO_MD4 is not set
+# CONFIG_CRYPTO_MD5 is not set
+# CONFIG_CRYPTO_SHA1 is not set
+# CONFIG_CRYPTO_SHA256 is not set
+CONFIG_CRYPTO_SHA512=y
+# CONFIG_CRYPTO_DES is not set
+# CONFIG_CRYPTO_BLOWFISH is not set
+CONFIG_CRYPTO_TWOFISH=y
+# CONFIG_CRYPTO_SERPENT is not set
+CONFIG_CRYPTO_AES=y
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+CONFIG_CRYPTO_DEFLATE=y
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Library routines
+#
+CONFIG_CRC32=y
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
--- diff/arch/mips/configs/yosemite_defconfig	1970-01-01 01:00:00.000000000 +0100
+++ source/arch/mips/configs/yosemite_defconfig	2004-02-23 13:56:38.000000000 +0000
@@ -0,0 +1,567 @@
+#
+# Automatically generated make config: don't edit
+#
+CONFIG_MIPS=y
+# CONFIG_MIPS64 is not set
+# CONFIG_64BIT is not set
+CONFIG_MIPS32=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_CLEAN_COMPILE=y
+CONFIG_STANDALONE=y
+
+#
+# General setup
+#
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+CONFIG_LOG_BUF_SHIFT=15
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_EMBEDDED=y
+CONFIG_KALLSYMS=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+CONFIG_OBSOLETE_MODPARM=y
+CONFIG_MODVERSIONS=y
+CONFIG_KMOD=y
+
+#
+# Machine selection
+#
+# CONFIG_MACH_JAZZ is not set
+# CONFIG_BAGET_MIPS is not set
+# CONFIG_MACH_VR41XX is not set
+# CONFIG_TOSHIBA_JMR3927 is not set
+# CONFIG_MIPS_COBALT is not set
+# CONFIG_MACH_DECSTATION is not set
+# CONFIG_MIPS_EV64120 is not set
+# CONFIG_MIPS_EV96100 is not set
+# CONFIG_MIPS_IVR is not set
+# CONFIG_LASAT is not set
+# CONFIG_HP_LASERJET is not set
+# CONFIG_MIPS_ITE8172 is not set
+# CONFIG_MIPS_ATLAS is not set
+# CONFIG_MIPS_MALTA is not set
+# CONFIG_MIPS_SEAD is not set
+# CONFIG_MOMENCO_OCELOT is not set
+# CONFIG_MOMENCO_OCELOT_G is not set
+# CONFIG_MOMENCO_OCELOT_C is not set
+# CONFIG_MOMENCO_JAGUAR_ATX is not set
+# CONFIG_PMC_YOSEMITE is not set
+# CONFIG_DDB5074 is not set
+# CONFIG_DDB5476 is not set
+# CONFIG_DDB5477 is not set
+# CONFIG_NEC_OSPREY is not set
+# CONFIG_SGI_IP22 is not set
+# CONFIG_SGI_IP32 is not set
+# CONFIG_SOC_AU1X00 is not set
+# CONFIG_SIBYTE_SB1xxx_SOC is not set
+# CONFIG_SNI_RM200_PCI is not set
+# CONFIG_TOSHIBA_RBTX4927 is not set
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_HAVE_DEC_LOCK=y
+# CONFIG_CPU_LITTLE_ENDIAN is not set
+CONFIG_MIPS_L1_CACHE_SHIFT=5
+# CONFIG_FB is not set
+CONFIG_BOARD_SCACHE=y
+
+#
+# CPU selection
+#
+# CONFIG_CPU_MIPS32 is not set
+# CONFIG_CPU_MIPS64 is not set
+# CONFIG_CPU_R3000 is not set
+# CONFIG_CPU_TX39XX is not set
+# CONFIG_CPU_VR41XX is not set
+# CONFIG_CPU_R4300 is not set
+# CONFIG_CPU_R4X00 is not set
+# CONFIG_CPU_TX49XX is not set
+# CONFIG_CPU_R5000 is not set
+# CONFIG_CPU_R5432 is not set
+# CONFIG_CPU_R6000 is not set
+# CONFIG_CPU_NEVADA is not set
+# CONFIG_CPU_R8000 is not set
+# CONFIG_CPU_R10000 is not set
+# CONFIG_CPU_RM7000 is not set
+CONFIG_CPU_RM9000=y
+# CONFIG_CPU_SB1 is not set
+CONFIG_PAGE_SIZE_4KB=y
+# CONFIG_PAGE_SIZE_16KB is not set
+# CONFIG_PAGE_SIZE_64KB is not set
+CONFIG_CPU_HAS_PREFETCH=y
+# CONFIG_64BIT_PHYS_ADDR is not set
+# CONFIG_CPU_ADVANCED is not set
+CONFIG_CPU_HAS_LLSC=y
+CONFIG_CPU_HAS_LLDSCD=y
+CONFIG_CPU_HAS_SYNC=y
+CONFIG_SMP=y
+CONFIG_NR_CPUS=2
+# CONFIG_PREEMPT is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+
+#
+# Bus options (PCI, PCMCIA, EISA, ISA, TC)
+#
+CONFIG_MMU=y
+# CONFIG_HOTPLUG is not set
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_MISC is not set
+CONFIG_TRAD_SIGNALS=y
+# CONFIG_BINFMT_IRIX is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+CONFIG_BLK_DEV_LOOP=y
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_RAM is not set
+# CONFIG_BLK_DEV_INITRD is not set
+CONFIG_LBD=y
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+CONFIG_SCSI=y
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=y
+# CONFIG_CHR_DEV_ST is not set
+# CONFIG_CHR_DEV_OSST is not set
+CONFIG_BLK_DEV_SR=y
+# CONFIG_BLK_DEV_SR_VENDOR is not set
+CONFIG_CHR_DEV_SG=y
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+# CONFIG_SCSI_MULTI_LUN is not set
+CONFIG_SCSI_REPORT_LUNS=y
+# CONFIG_SCSI_CONSTANTS is not set
+# CONFIG_SCSI_LOGGING is not set
+
+#
+# SCSI low-level drivers
+#
+# CONFIG_SCSI_AIC7XXX_OLD is not set
+# CONFIG_SCSI_SATA is not set
+# CONFIG_SCSI_EATA_PIO is not set
+# CONFIG_SCSI_DEBUG is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+# CONFIG_FUSION is not set
+
+#
+# IEEE 1394 (FireWire) support (EXPERIMENTAL)
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+
+#
+# Macintosh device drivers
+#
+
+#
+# Networking support
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+CONFIG_PACKET_MMAP=y
+# CONFIG_NETLINK_DEV is not set
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+# CONFIG_IP_PNP_BOOTP is not set
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_ARPD is not set
+# CONFIG_INET_ECN is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_IPV6 is not set
+# CONFIG_DECNET is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_NETFILTER is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+CONFIG_IPV6_SCTP__=y
+# CONFIG_IP_SCTP is not set
+# CONFIG_ATM is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_FASTROUTE is not set
+# CONFIG_NET_HW_FLOWCONTROL is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+# CONFIG_MII is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+
+#
+# Ethernet (10000 Mbit)
+#
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Token Ring devices
+#
+# CONFIG_SHAPER is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+
+#
+# Amateur Radio support
+#
+# CONFIG_HAMRADIO is not set
+
+#
+# IrDA (infrared) support
+#
+# CONFIG_IRDA is not set
+
+#
+# Bluetooth support
+#
+# CONFIG_BT is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN_BOOL is not set
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+# CONFIG_INPUT is not set
+
+#
+# Userland interfaces
+#
+
+#
+# Input I/O drivers
+#
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+CONFIG_SERIO=y
+CONFIG_SERIO_I8042=y
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_CT82C710 is not set
+
+#
+# Input Device Drivers
+#
+
+#
+# Character devices
+#
+# CONFIG_VT is not set
+CONFIG_SERIAL_NONSTANDARD=y
+# CONFIG_ROCKETPORT is not set
+# CONFIG_SYNCLINK is not set
+# CONFIG_SYNCLINKMP is not set
+# CONFIG_N_HDLC is not set
+# CONFIG_STALDRV is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_UNIX98_PTYS=y
+CONFIG_UNIX98_PTY_COUNT=256
+
+#
+# Mice
+#
+# CONFIG_BUSMOUSE is not set
+# CONFIG_QIC02_TAPE is not set
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_NVRAM is not set
+# CONFIG_RTC is not set
+# CONFIG_GEN_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_AGP is not set
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# File systems
+#
+# CONFIG_EXT2_FS is not set
+CONFIG_EXT3_FS=y
+CONFIG_EXT3_FS_XATTR=y
+# CONFIG_EXT3_FS_POSIX_ACL is not set
+# CONFIG_EXT3_FS_SECURITY is not set
+CONFIG_JBD=y
+# CONFIG_JBD_DEBUG is not set
+CONFIG_FS_MBCACHE=y
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_QUOTA is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_FAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+# CONFIG_DEVFS_FS is not set
+CONFIG_DEVPTS_FS=y
+# CONFIG_DEVPTS_FS_XATTR is not set
+CONFIG_TMPFS=y
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
+# CONFIG_NFSD is not set
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+# CONFIG_EXPORTFS is not set
+CONFIG_SUNRPC=y
+# CONFIG_SUNRPC_GSS is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_INTERMEZZO_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+
+#
+# Native Language Support
+#
+# CONFIG_NLS is not set
+
+#
+# Kernel hacking
+#
+CONFIG_CROSSCOMPILE=y
+CONFIG_CMDLINE=""
+# CONFIG_DEBUG_KERNEL is not set
+
+#
+# Security options
+#
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
+# Library routines
+#
+# CONFIG_CRC32 is not set
--- diff/arch/mips/dec/prom/console.c	1970-01-01 01:00:00.000000000 +0100
+++ source/arch/mips/dec/prom/console.c	2004-02-23 13:56:38.000000000 +0000
@@ -0,0 +1,55 @@
+/*
+ *	arch/mips/dec/prom/console.c
+ *
+ *	DECstation PROM-based early console support.
+ *
+ *	Copyright (C) 2004  Maciej W. Rozycki
+ *
+ *	This program is free software; you can redistribute it and/or
+ *	modify it under the terms of the GNU General Public License
+ *	as published by the Free Software Foundation; either version
+ *	2 of the License, or (at your option) any later version.
+ */
+#include <linux/console.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+
+#include <asm/dec/prom.h>
+
+static void __init prom_console_write(struct console *con, const char *s,
+				      unsigned int c)
+{
+	static char sfmt[] __initdata = "%%%us";
+	char fmt[13];
+
+	snprintf(fmt, sizeof(fmt), sfmt, c);
+	prom_printf(fmt, s);
+}
+
+static struct console promcons __initdata = {
+	.name	= "prom",
+	.write	= prom_console_write,
+	.flags	= CON_PRINTBUFFER,
+	.index	= -1,
+};
+
+static int promcons_output __initdata = 0;
+
+void __init register_prom_console(void)
+{
+	if (!promcons_output) {
+		promcons_output = 1;
+		register_console(&promcons);
+	}
+}
+
+void __init unregister_prom_console(void)
+{
+	if (promcons_output) {
+		unregister_console(&promcons);
+		promcons_output = 0;
+	}
+}
+
+void disable_early_printk(void)
+	__attribute__((alias("unregister_prom_console")));
--- diff/arch/mips/galileo-boards/ev96100/reset.c	1970-01-01 01:00:00.000000000 +0100
+++ source/arch/mips/galileo-boards/ev96100/reset.c	2004-02-23 13:56:38.000000000 +0000
@@ -0,0 +1,70 @@
+/*
+ * BRIEF MODULE DESCRIPTION
+ *	Galileo EV96100 reset routines.
+ *
+ * Copyright 2000 MontaVista Software Inc.
+ * Author: MontaVista Software, Inc.
+ *         	ppopov@mvista.com or source@mvista.com
+ *
+ * This file was derived from Carsten Langgaard's
+ * arch/mips/mips-boards/generic/reset.c
+ *
+ * Carsten Langgaard, carstenl@mips.com
+ * Copyright (C) 1999,2000 MIPS Technologies, Inc.  All rights reserved.
+ *
+ *  This program is free software; you can redistribute  it and/or modify it
+ *  under  the terms of  the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the  License, or (at your
+ *  option) any later version.
+ *
+ *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
+ *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
+ *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
+ *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
+ *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
+ *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *  You should have received a copy of the  GNU General Public License along
+ *  with this program; if not, write  to the Free Software Foundation, Inc.,
+ *  675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <asm/io.h>
+#include <asm/pgtable.h>
+#include <asm/processor.h>
+#include <asm/reboot.h>
+#include <asm/system.h>
+#include <asm/gt64120.h>
+
+static void mips_machine_restart(char *command);
+static void mips_machine_halt(void);
+
+static void mips_machine_restart(char *command)
+{
+	set_c0_status(ST0_BEV | ST0_ERL);
+	change_c0_config(CONF_CM_CMASK, CONF_CM_UNCACHED);
+	flush_cache_all();
+	write_c0_wired(0);
+	__asm__ __volatile__("jr\t%0"::"r"(0xbfc00000));
+	while (1);
+}
+
+static void mips_machine_halt(void)
+{
+	printk(KERN_NOTICE "You can safely turn off the power\n");
+	while (1)
+		__asm__(".set\tmips3\n\t"
+	                "wait\n\t"
+			".set\tmips0");
+}
+
+void mips_reboot_setup(void)
+{
+	_machine_restart = mips_machine_restart;
+	_machine_halt = mips_machine_halt;
+}
--- diff/arch/mips/gt64120/common/pci.c	1970-01-01 01:00:00.000000000 +0100
+++ source/arch/mips/gt64120/common/pci.c	2004-02-23 13:56:38.000000000 +0000
@@ -0,0 +1,147 @@
+/*
+ * BRIEF MODULE DESCRIPTION
+ * Galileo Evaluation Boards PCI support.
+ *
+ * The general-purpose functions to read/write and configure the GT64120A's
+ * PCI registers (function names start with pci0 or pci1) are either direct
+ * copies of functions written by Galileo Technology, or are modifications
+ * of their functions to work with Linux 2.4 vs Linux 2.2.  These functions
+ * are Copyright - Galileo Technology.
+ *
+ * Other functions are derived from other MIPS PCI implementations, or were
+ * written by RidgeRun, Inc,  Copyright (C) 2000 RidgeRun, Inc.
+ *   glonnon@ridgerun.com, skranz@ridgerun.com, stevej@ridgerun.com
+ *
+ *  This program is free software; you can redistribute  it and/or modify it
+ *  under  the terms of  the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the  License, or (at your
+ *  option) any later version.
+ *
+ *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
+ *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
+ *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
+ *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
+ *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
+ *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *  You should have received a copy of the  GNU General Public License along
+ *  with this program; if not, write  to the Free Software Foundation, Inc.,
+ *  675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <linux/kernel.h>
+#include <asm/gt64120.h>
+
+#define SELF 0
+
+/*
+ * pciXReadConfigReg  - Read from a PCI configuration register
+ *                    - Make sure the GT is configured as a master before
+ *                      reading from another device on the PCI.
+ *                   - The function takes care of Big/Little endian conversion.
+ * INPUTS:   regOffset: The register offset as it apears in the GT spec (or PCI
+ *                        spec)
+ *           pciDevNum: The device number needs to be addressed.
+ * RETURNS: data , if the data == 0xffffffff check the master abort bit in the
+ *                 cause register to make sure the data is valid
+ *
+ *  Configuration Address 0xCF8:
+ *
+ *       31 30    24 23  16 15  11 10     8 7      2  0     <=bit Number
+ *  |congif|Reserved|  Bus |Device|Function|Register|00|
+ *  |Enable|        |Number|Number| Number | Number |  |    <=field Name
+ *
+ */
+static unsigned int pci0ReadConfigReg(int offset, struct pci_dev *device)
+{
+	unsigned int DataForRegCf8;
+	unsigned int data;
+
+	DataForRegCf8 = ((PCI_SLOT(device->devfn) << 11) |
+			 (PCI_FUNC(device->devfn) << 8) |
+			 (offset & ~0x3)) | 0x80000000;
+	GT_WRITE(GT_PCI0_CFGADDR_OFS, DataForRegCf8);
+
+	/*
+	 * The casual observer might wonder why the READ is duplicated here,
+	 * rather than immediately following the WRITE, and just have the swap
+	 * in the "if".  That's because there is a latency problem with trying
+	 * to read immediately after setting up the address register.  The "if"
+	 * check gives enough time for the address to stabilize, so the READ
+	 * can work.
+	 */
+	if (PCI_SLOT(device->devfn) == SELF)	/* This board */
+		return GT_READ(GT_PCI0_CFGDATA_OFS);
+	else		/* PCI is little endian so swap the Data. */
+		return __GT_READ(GT_PCI0_CFGDATA_OFS);
+}
+
+/*
+ * pciXWriteConfigReg - Write to a PCI configuration register
+ *                    - Make sure the GT is configured as a master before
+ *                      writingto another device on the PCI.
+ *                    - The function takes care of Big/Little endian conversion.
+ * Inputs:   unsigned int regOffset: The register offset as it apears in the
+ *           GT spec
+ *                   (or any other PCI device spec)
+ *           pciDevNum: The device number needs to be addressed.
+ *
+ *  Configuration Address 0xCF8:
+ *
+ *       31 30    24 23  16 15  11 10     8 7      2  0     <=bit Number
+ *  |congif|Reserved|  Bus |Device|Function|Register|00|
+ *  |Enable|        |Number|Number| Number | Number |  |    <=field Name
+ *
+ */
+static void pci0WriteConfigReg(unsigned int offset,
+			       struct pci_dev *device, unsigned int data)
+{
+	unsigned int DataForRegCf8;
+
+	DataForRegCf8 = ((PCI_SLOT(device->devfn) << 11) |
+			 (PCI_FUNC(device->devfn) << 8) |
+			 (offset & ~0x3)) | 0x80000000;
+	GT_WRITE(GT_PCI0_CFGADDR_OFS, DataForRegCf8);
+
+	if (PCI_SLOT(device->devfn) == SELF) 	/* This board */
+		GT_WRITE(GT_PCI0_CFGDATA_OFS, data);
+	else 			/* configuration Transaction over the pci. */
+		__GT_WRITE(GT_PCI0_CFGDATA_OFS, data);
+}
+
+extern struct pci_ops gt64120_pci_ops;
+
+void __init pcibios_init(void)
+{
+	u32 tmp;
+	struct pci_dev controller;
+
+	controller.devfn = SELF;
+
+	tmp = GT_READ(GT_PCI0_CMD_OFS);		/* Huh??? -- Ralf  */
+	tmp = GT_READ(GT_PCI0_BARE_OFS);
+
+	/*
+	 * You have to enable bus mastering to configure any other
+	 * card on the bus.
+	 */
+	tmp = pci0ReadConfigReg(PCI_COMMAND, &controller);
+	tmp |= PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER | PCI_COMMAND_SERR;
+	pci0WriteConfigReg(PCI_COMMAND, &controller, tmp);
+
+	/*
+	 *  Reset PCI I/O and PCI MEM values to ones supported by EVM.
+	 */
+	ioport_resource.start	= GT_PCI_IO_BASE;
+	ioport_resource.end	= GT_PCI_IO_BASE + GT_PCI_IO_SIZE - 1;
+	iomem_resource.start	= GT_PCI_MEM_BASE;
+	iomem_resource.end	= GT_PCI_MEM_BASE + GT_PCI_MEM_SIZE - 1;
+
+	pci_scan_bus(0, &gt64120_pci_ops, NULL);
+}
--- diff/arch/mips/gt64120/common/time.c	1970-01-01 01:00:00.000000000 +0100
+++ source/arch/mips/gt64120/common/time.c	2004-02-23 13:56:38.000000000 +0000
@@ -0,0 +1,98 @@
+/*
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ *
+ * Galileo Technology chip interrupt handler
+ */
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/config.h>
+#include <linux/sched.h>
+#include <linux/kernel_stat.h>
+#include <asm/ptrace.h>
+#include <asm/gt64120.h>
+
+/*
+ * These are interrupt handlers for the GT on-chip interrupts.  They all come
+ * in to the MIPS on a single interrupt line, and have to be handled and ack'ed
+ * differently than other MIPS interrupts.
+ */
+
+static void gt64120_irq(int irq, void *dev_id, struct pt_regs *regs)
+{
+	unsigned int irq_src, int_high_src, irq_src_mask, int_high_src_mask;
+	int handled = 0;
+
+	irq_src = GT_READ(GT_INTRCAUSE_OFS);
+	irq_src_mask = GT_READ(GT_INTRMASK_OFS);
+	int_high_src = GT_READ(GT_HINTRCAUSE_OFS);
+	int_high_src_mask = GT_READ(GT_HINTRMASK_OFS);
+	irq_src = irq_src & irq_src_mask;
+	int_high_src = int_high_src & int_high_src_mask;
+
+	if (irq_src & 0x00000800) {	/* Check for timer interrupt */
+		handled = 1;
+		irq_src &= ~0x00000800;
+		do_timer(regs);
+	}
+
+	GT_WRITE(GT_INTRCAUSE_OFS, 0);
+	GT_WRITE(GT_HINTRCAUSE_OFS, 0);
+}
+
+/*
+ * Initializes timer using galileo's built in timer.
+ */
+#ifdef CONFIG_SYSCLK_100
+#define Sys_clock (100 * 1000000)	// 100 MHz
+#endif
+#ifdef CONFIG_SYSCLK_83
+#define Sys_clock (83.333 * 1000000)	// 83.333 MHz
+#endif
+#ifdef CONFIG_SYSCLK_75
+#define Sys_clock (75 * 1000000)	// 75 MHz
+#endif
+
+/*
+ * This will ignore the standard MIPS timer interrupt handler that is passed in
+ * as *irq (=irq0 in ../kernel/time.c).  We will do our own timer interrupt
+ * handling.
+ */
+void gt64120_time_init(void)
+{
+	extern irq_desc_t irq_desc[NR_IRQS];
+	static struct irqaction timer;
+
+	/* Disable timer first */
+	GT_WRITE(GT_TC_CONTROL_OFS, 0);
+	/* Load timer value for 100 Hz */
+	GT_WRITE(GT_TC3_OFS, Sys_clock / 100);
+
+	/*
+	 * Create the IRQ structure entry for the timer.  Since we're too early
+	 * in the boot process to use the "request_irq()" call, we'll hard-code
+	 * the values to the correct interrupt line.
+	 */
+	timer.handler = gt64120_irq;
+	timer.flags = SA_SHIRQ | SA_INTERRUPT;
+	timer.name = "timer";
+	timer.dev_id = NULL;
+	timer.next = NULL;
+	timer.mask = 0;
+	irq_desc[GT_TIMER].action = &timer;
+
+	enable_irq(GT_TIMER);
+
+	/* Enable timer ints */
+	GT_WRITE(GT_TC_CONTROL_OFS, 0xc0);
+	/* clear Cause register first */
+	GT_WRITE(GT_INTRCAUSE_OFS, 0x0);
+	/* Unmask timer int */
+	GT_WRITE(GT_INTRMASK_OFS, 0x800);
+	/* Clear High int register */
+	GT_WRITE(GT_HINTRCAUSE_OFS, 0x0);
+	/* Mask All interrupts at High cause interrupt */
+	GT_WRITE(GT_HINTRMASK_OFS, 0x0);
+}
--- diff/arch/mips/gt64120/ev64120/Makefile	1970-01-01 01:00:00.000000000 +0100
+++ source/arch/mips/gt64120/ev64120/Makefile	2004-02-23 13:56:38.000000000 +0000
@@ -0,0 +1,11 @@
+#
+#  Copyright 2000 RidgeRun, Inc.
+#  Author: RidgeRun, Inc.
+#     	glonnon@ridgerun.com, skranz@ridgerun.com, stevej@ridgerun.com
+#
+# Makefile for the Galileo EV64120 board.
+#
+
+obj-y	+= int-handler.o irq.o promcon.o reset.o serialGT.o setup.o
+
+EXTRA_AFLAGS := $(CFLAGS)
--- diff/arch/mips/gt64120/ev64120/int-handler.S	1970-01-01 01:00:00.000000000 +0100
+++ source/arch/mips/gt64120/ev64120/int-handler.S	2004-02-23 13:56:38.000000000 +0000
@@ -0,0 +1,113 @@
+/*
+ * int-handler.S
+ *
+ * Based on the cobalt handler.
+ */
+#include <asm/asm.h>
+#include <asm/mipsregs.h>
+#include <asm/addrspace.h>
+#include <asm/regdef.h>
+#include <asm/stackframe.h>
+
+/*
+ * galileo_handle_int -
+ *      We check for the timer first, then check PCI ints A and D.
+ *      Then check for serial IRQ and fall through.
+ */
+		.align	5
+		.set	reorder
+		.set	noat
+		NESTED(galileo_handle_int, PT_SIZE, sp)
+		SAVE_ALL
+		CLI
+		.set	at
+		mfc0	t0,CP0_CAUSE
+		mfc0	t2,CP0_STATUS
+
+		and	t0,t2
+
+		andi	t1,t0,STATUSF_IP4 /* int2 hardware line (timer) */
+		bnez	t1,ll_gt64120_irq
+		andi	t1,t0,STATUSF_IP2 /* int0 hardware line */
+		bnez	t1,ll_pci_intA
+		andi	t1,t0,STATUSF_IP5 /* int3 hardware line */
+		bnez	t1,ll_pci_intD
+		andi	t1,t0,STATUSF_IP6 /* int4 hardware line */
+		bnez	t1,ll_serial_irq
+		andi	t1,t0,STATUSF_IP7 /* compare int */
+		bnez	t1,ll_compare_irq
+		nop
+
+    /* wrong alarm or masked ... */
+		j	spurious_interrupt
+		nop
+		END(galileo_handle_int)
+
+
+		.align	5
+		.set	reorder
+ll_gt64120_irq:
+		li	a0,4
+		move	a1,sp
+		jal	do_IRQ
+		nop
+		j	ret_from_irq
+		nop
+
+		.align	5
+		.set	reorder
+ll_compare_irq:
+		li 	a0,7
+		move	a1,sp
+		jal	do_IRQ
+		nop
+		j	ret_from_irq
+		nop
+
+		.align	5
+		.set	reorder
+ll_pci_intA:
+		move	a0,sp
+		jal	pci_intA
+		nop
+		j	ret_from_irq
+		nop
+
+#if 0
+		.align	5
+		.set	reorder
+ll_pci_intB:
+		move 	a0,sp
+		jal	pci_intB
+		nop
+		j	ret_from_irq
+		nop
+
+		.align	5
+		.set	reorder
+ll_pci_intC:
+		move 	a0,sp
+		jal	pci_intC
+		nop
+		j	ret_from_irq
+		nop
+#endif
+
+		.align	5
+		.set	reorder
+ll_pci_intD:
+		move 	a0,sp
+		jal	pci_intD
+		nop
+		j	ret_from_irq
+		nop
+
+		.align	5
+		.set	reorder
+ll_serial_irq:
+		li	a0,6
+		move	a1,sp
+		jal	do_IRQ
+		nop
+		j	ret_from_irq
+		nop
--- diff/arch/mips/gt64120/ev64120/irq.c	1970-01-01 01:00:00.000000000 +0100
+++ source/arch/mips/gt64120/ev64120/irq.c	2004-02-23 13:56:38.000000000 +0000
@@ -0,0 +1,145 @@
+/*
+ * BRIEF MODULE DESCRIPTION
+ * Code to handle irqs on GT64120A boards
+ *  Derived from mips/orion and Cort <cort@fsmlabs.com>
+ *
+ * Copyright (C) 2000 RidgeRun, Inc.
+ * Author: RidgeRun, Inc.
+ *   glonnon@ridgerun.com, skranz@ridgerun.com, stevej@ridgerun.com
+ *
+ *  This program is free software; you can redistribute  it and/or modify it
+ *  under  the terms of  the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the  License, or (at your
+ *  option) any later version.
+ *
+ *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
+ *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
+ *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
+ *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
+ *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
+ *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *  You should have received a copy of the  GNU General Public License along
+ *  with this program; if not, write  to the Free Software Foundation, Inc.,
+ *  675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/kernel_stat.h>
+#include <linux/module.h>
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/types.h>
+#include <linux/interrupt.h>
+#include <linux/ioport.h>
+#include <linux/timex.h>
+#include <linux/slab.h>
+#include <linux/random.h>
+#include <asm/bitops.h>
+#include <asm/bootinfo.h>
+#include <asm/io.h>
+#include <asm/mipsregs.h>
+#include <asm/system.h>
+#include <asm/gt64120.h>
+
+asmlinkage inline void pci_intA(struct pt_regs *regs)
+{
+	do_IRQ(GT_INTA, regs);
+}
+
+asmlinkage inline void pci_intD(struct pt_regs *regs)
+{
+	do_IRQ(GT_INTD, regs);
+}
+
+static void disable_ev64120_irq(unsigned int irq_nr)
+{
+	unsigned long flags;
+
+	local_irq_save(flags);
+	if (irq_nr >= 8) {	// All PCI interrupts are on line 5 or 2
+		clear_c0_status(9 << 10);
+	} else {
+		clear_c0_status(1 << (irq_nr + 8));
+	}
+	local_irq_restore(flags);
+}
+
+static void enable_ev64120_irq(unsigned int irq_nr)
+{
+	unsigned long flags;
+
+	local_irq_save(flags);
+	if (irq_nr >= 8)	// All PCI interrupts are on line 5 or 2
+		set_c0_status(9 << 10);
+	else
+		set_c0_status(1 << (irq_nr + 8));
+	local_irq_restore(flags);
+}
+
+static unsigned int startup_ev64120_irq(unsigned int irq)
+{
+	enable_ev64120_irq(irq);
+	return 0;		/* Never anything pending  */
+}
+
+#define shutdown_ev64120_irq     disable_ev64120_irq
+#define mask_and_ack_ev64120_irq disable_ev64120_irq
+
+static void end_ev64120_irq(unsigned int irq)
+{
+	if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
+		enable_ev64120_irq(irq);
+}
+
+static struct hw_interrupt_type ev64120_irq_type = {
+	.typename	= "EV64120",
+	.startup	= startup_ev64120_irq,
+	.shutdown	= shutdown_ev64120_irq,
+	.enable		= enable_ev64120_irq,
+	.disable	= disable_ev64120_irq,
+	.ack		= mask_and_ack_ev64120_irq,
+	.end		= end_ev64120_irq,
+	.set_affinity	= NULL
+};
+
+void gt64120_irq_setup(void)
+{
+	extern asmlinkage void galileo_handle_int(void);
+
+	/*
+	 * Clear all of the interrupts while we change the able around a bit.
+	 */
+	clear_c0_status(ST0_IM);
+
+	/* Sets the exception_handler array. */
+	set_except_vector(0, galileo_handle_int);
+
+	cli();
+
+	/*
+	 * Enable timer.  Other interrupts will be enabled as they are
+	 * registered.
+	 */
+	set_c0_status(IE_IRQ2);
+}
+
+void __init init_IRQ(void)
+{
+	int i;
+
+	/*  Let's initialize our IRQ descriptors  */
+	for (i = 0; i < NR_IRQS; i++) {
+		irq_desc[i].status = 0;
+		irq_desc[i].handler = &no_irq_type;
+		irq_desc[i].action = NULL;
+		irq_desc[i].depth = 0;
+		irq_desc[i].lock = SPIN_LOCK_UNLOCKED;
+	}
+
+	gt64120_irq_setup();
+}
--- diff/arch/mips/gt64120/ev64120/promcon.c	1970-01-01 01:00:00.000000000 +0100
+++ source/arch/mips/gt64120/ev64120/promcon.c	2004-02-23 13:56:38.000000000 +0000
@@ -0,0 +1,53 @@
+/*
+ * Wrap-around code for a console using the
+ * SGI PROM io-routines.
+ *
+ * Copyright (c) 1999 Ulf Carlsson
+ *
+ * Derived from DECstation promcon.c
+ * Copyright (c) 1998 Harald Koerfgen
+ */
+#include <linux/tty.h>
+#include <linux/init.h>
+#include <linux/console.h>
+
+static void prom_console_write(struct console *co, const char *s,
+			       unsigned count)
+{
+	extern int CONSOLE_CHANNEL;	// The default serial port
+	unsigned i;
+
+	for (i = 0; i < count; i++) {
+		if (*s == 10)
+			serial_putc(CONSOLE_CHANNEL, 13);
+		serial_putc(CONSOLE_CHANNEL, *s++);
+	}
+}
+
+int prom_getchar(void)
+{
+	return 0;
+}
+
+static struct console sercons = {
+    .name	= "ttyS",
+    .write	= prom_console_write,
+    .flags	= CON_PRINTBUFFER,
+    .index	= -1,
+};
+
+/*
+ *    Register console.
+ */
+
+static int gal_serial_console_init(void)
+{
+	//  serial_init();
+	//serial_set(115200);
+
+	register_console(&sercons);
+
+	return 0;
+}
+
+console_initcall(gal_serial_console_init);
--- diff/arch/mips/gt64120/ev64120/reset.c	1970-01-01 01:00:00.000000000 +0100
+++ source/arch/mips/gt64120/ev64120/reset.c	2004-02-23 13:56:38.000000000 +0000
@@ -0,0 +1,45 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 1997 Ralf Baechle
+ */
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <asm/io.h>
+#include <asm/pgtable.h>
+#include <asm/processor.h>
+#include <asm/reboot.h>
+#include <asm/system.h>
+
+void galileo_machine_restart(char *command)
+{
+	*(volatile char *) 0xbc000000 = 0x0f;
+	/*
+	 * Ouch, we're still alive ... This time we take the silver bullet ...
+	 * ... and find that we leave the hardware in a state in which the
+	 * kernel in the flush locks up somewhen during of after the PCI
+	 * detection stuff.
+	 */
+	set_c0_status(ST0_BEV | ST0_ERL);
+	change_c0_config(CONF_CM_CMASK, CONF_CM_UNCACHED);
+	flush_cache_all();
+	write_c0_wired(0);
+	__asm__ __volatile__("jr\t%0"::"r"(0xbfc00000));
+}
+
+void galileo_machine_halt(void)
+{
+	printk(KERN_NOTICE "You can safely turn off the power\n");
+	while (1)
+		__asm__(".set\tmips3\n\t"
+	                "wait\n\t"
+			".set\tmips0");
+
+}
+
+void galileo_machine_power_off(void)
+{
+	galileo_machine_halt();
+}
--- diff/arch/mips/gt64120/ev64120/serialGT.c	1970-01-01 01:00:00.000000000 +0100
+++ source/arch/mips/gt64120/ev64120/serialGT.c	2004-02-23 13:56:38.000000000 +0000
@@ -0,0 +1,212 @@
+/*
+ * serialGT.c
+ *
+ * BRIEF MODULE DESCRIPTION
+ *  Low Level Serial Port control for use
+ *  with the Galileo EVB64120A MIPS eval board and
+ *  its on board two channel 16552 Uart.
+ *
+ * Copyright (C) 2000 RidgeRun, Inc.
+ * Author: RidgeRun, Inc.
+ *   glonnon@ridgerun.com, skranz@ridgerun.com, stevej@ridgerun.com
+ *
+ *  This program is free software; you can redistribute  it and/or modify it
+ *  under  the terms of  the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the  License, or (at your
+ *  option) any later version.
+ *
+ *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
+ *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
+ *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
+ *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
+ *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
+ *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *  You should have received a copy of the  GNU General Public License along
+ *  with this program; if not, write  to the Free Software Foundation, Inc.,
+ *  675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+// Note:
+//   Serial CHANNELS - 0 is the bottom connector of evb64120A.
+//                       (The one that maps to the "B" channel of the
+//                       board's uart)
+//                     1 is the top connector of evb64120A.
+//                       (The one that maps to the "A" channel of the
+//                       board's uart)
+int DEBUG_CHANNEL = 0;		// See Note Above
+int CONSOLE_CHANNEL = 1;	// See Note Above
+
+#define DUART 0xBD000000	/* Base address of Uart. */
+#define CHANNELOFFSET 0x20	/* DUART+CHANNELOFFSET gets you to the ChanA
+				   register set of the 16552 Uart device.
+				   DUART+0 gets you to the ChanB register set.
+				 */
+#define DUART_DELTA 0x4
+#define FIFO_ENABLE 0x07
+#define INT_ENABLE  0x04	/* default interrupt mask */
+
+#define RBR 0x00
+#define THR 0x00
+#define DLL 0x00
+#define IER 0x01
+#define DLM 0x01
+#define IIR 0x02
+#define FCR 0x02
+#define LCR 0x03
+#define MCR 0x04
+#define LSR 0x05
+#define MSR 0x06
+#define SCR 0x07
+
+#define LCR_DLAB 0x80
+#define XTAL 1843200
+#define LSR_THRE 0x20
+#define LSR_BI   0x10
+#define LSR_DR   0x01
+#define MCR_LOOP 0x10
+#define ACCESS_DELAY 0x10000
+
+/******************************
+ Routine:
+ Description:
+ ******************************/
+int inreg(int channel, int reg)
+{
+	int val;
+	val =
+	    *((volatile unsigned char *) DUART +
+	      (channel * CHANNELOFFSET) + (reg * DUART_DELTA));
+	return val;
+}
+
+/******************************
+ Routine:
+ Description:
+ ******************************/
+void outreg(int channel, int reg, unsigned char val)
+{
+	*((volatile unsigned char *) DUART + (channel * CHANNELOFFSET)
+	  + (reg * DUART_DELTA)) = val;
+}
+
+/******************************
+ Routine:
+ Description:
+   Initialize the device driver.
+ ******************************/
+void serial_init(int channel)
+{
+	/*
+	 * Configure active port, (CHANNELOFFSET already set.)
+	 *
+	 * Set 8 bits, 1 stop bit, no parity.
+	 *
+	 * LCR<7>       0       divisor latch access bit
+	 * LCR<6>       0       break control (1=send break)
+	 * LCR<5>       0       stick parity (0=space, 1=mark)
+	 * LCR<4>       0       parity even (0=odd, 1=even)
+	 * LCR<3>       0       parity enable (1=enabled)
+	 * LCR<2>       0       # stop bits (0=1, 1=1.5)
+	 * LCR<1:0>     11      bits per character(00=5, 01=6, 10=7, 11=8)
+	 */
+	outreg(channel, LCR, 0x3);
+
+	outreg(channel, FCR, FIFO_ENABLE);	/* Enable the FIFO */
+
+	outreg(channel, IER, INT_ENABLE);	/* Enable appropriate interrupts */
+}
+
+/******************************
+ Routine:
+ Description:
+   Set the baud rate.
+ ******************************/
+void serial_set(int channel, unsigned long baud)
+{
+	unsigned char sav_lcr;
+
+	/*
+	 * Enable access to the divisor latches by setting DLAB in LCR.
+	 *
+	 */
+	sav_lcr = inreg(channel, LCR);
+
+#if 0
+	/*
+	 * Set baud rate
+	 */
+	outreg(channel, LCR, LCR_DLAB | sav_lcr);
+	//  outreg(DLL,(XTAL/(16*2*(baud))-2));
+	outreg(channel, DLL, XTAL / (16 * baud));
+	//  outreg(DLM,(XTAL/(16*2*(baud))-2)>>8);
+	outreg(channel, DLM, (XTAL / (16 * baud)) >> 8);
+#else
+	/*
+	 * Note: Set baud rate, hardcoded here for rate of 115200
+	 * since became unsure of above "buad rate" algorithm (??).
+	 */
+	outreg(channel, LCR, 0x83);
+	outreg(channel, DLM, 0x00);	// See note above
+	outreg(channel, DLL, 0x02);	// See note above.
+	outreg(channel, LCR, 0x03);
+#endif
+
+	/*
+	 * Restore line control register
+	 */
+	outreg(channel, LCR, sav_lcr);
+}
+
+
+/******************************
+ Routine:
+ Description:
+   Transmit a character.
+ ******************************/
+void serial_putc(int channel, int c)
+{
+	while ((inreg(channel, LSR) & LSR_THRE) == 0);
+	outreg(channel, THR, c);
+}
+
+/******************************
+ Routine:
+ Description:
+    Read a received character if one is
+    available.  Return -1 otherwise.
+ ******************************/
+int serial_getc(int channel)
+{
+	if (inreg(channel, LSR) & LSR_DR) {
+		return inreg(channel, RBR);
+	}
+	return -1;
+}
+
+/******************************
+ Routine:
+ Description:
+   Used by embedded gdb client. (example; gdb-stub.c)
+ ******************************/
+char getDebugChar()
+{
+	int val;
+	while ((val = serial_getc(DEBUG_CHANNEL)) == -1);	// loop until we get a character in.
+	return (char) val;
+}
+
+/******************************
+ Routine:
+ Description:
+   Used by embedded gdb target. (example; gdb-stub.c)
+ ******************************/
+void putDebugChar(char c)
+{
+	serial_putc(DEBUG_CHANNEL, (int) c);
+}
--- diff/arch/mips/gt64120/ev64120/setup.c	1970-01-01 01:00:00.000000000 +0100
+++ source/arch/mips/gt64120/ev64120/setup.c	2004-02-23 13:56:38.000000000 +0000
@@ -0,0 +1,103 @@
+/*
+ * Copyright (C) 2000 RidgeRun, Inc.
+ * Author: RidgeRun, Inc.
+ *   glonnon@ridgerun.com, skranz@ridgerun.com, stevej@ridgerun.com
+ *
+ *  This program is free software; you can redistribute  it and/or modify it
+ *  under  the terms of  the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the  License, or (at your
+ *  option) any later version.
+ *
+ *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
+ *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
+ *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
+ *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
+ *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
+ *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *  You should have received a copy of the  GNU General Public License along
+ *  with this program; if not, write  to the Free Software Foundation, Inc.,
+ *  675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/mm.h>
+#include <linux/swap.h>
+#include <linux/ioport.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <linux/pci.h>
+#include <linux/timex.h>
+#include <asm/bootinfo.h>
+#include <asm/page.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/pci.h>
+#include <asm/processor.h>
+#include <asm/ptrace.h>
+#include <asm/time.h>
+#include <asm/reboot.h>
+#include <asm/traps.h>
+#include <linux/bootmem.h>
+
+unsigned long gt64120_base = KSEG1ADDR(0x14000000);
+
+/* These functions are used for rebooting or halting the machine*/
+extern void galileo_machine_restart(char *command);
+extern void galileo_machine_halt(void);
+extern void galileo_machine_power_off(void);
+/*
+ *This structure holds pointers to the pci configuration space accesses
+ *and interrupts allocating routine for device over the PCI
+ */
+extern struct pci_ops galileo_pci_ops;
+
+unsigned long __init prom_free_prom_memory(void)
+{
+	return 0;
+}
+
+/*
+ * Initializes basic routines and structures pointers, memory size (as
+ * given by the bios and saves the command line.
+ */
+extern void gt64120_time_init(void);
+
+static void __init ev64120_setup(void)
+{
+	_machine_restart = galileo_machine_restart;
+	_machine_halt = galileo_machine_halt;
+	_machine_power_off = galileo_machine_power_off;
+
+	board_time_init = gt64120_time_init;
+	set_io_port_base(KSEG1);
+}
+
+early_initcall(ev64120_setup);
+
+const char *get_system_type(void)
+{
+	return "Galileo EV64120A";
+}
+
+/*
+ * Kernel arguments passed by the firmware
+ *
+ * $a0 - nothing
+ * $a1 - holds a pointer to the eprom parameters
+ * $a2 - nothing
+ */
+
+void __init prom_init(void)
+{
+	mips_machgroup = MACH_GROUP_GALILEO;
+	mips_machtype = MACH_EV64120A;
+
+	add_memory_region(0, 32 << 20, BOOT_MEM_RAM);
+}
--- diff/arch/mips/jaguar-atx_defconfig	1970-01-01 01:00:00.000000000 +0100
+++ source/arch/mips/jaguar-atx_defconfig	2004-02-23 13:56:38.000000000 +0000
@@ -0,0 +1,537 @@
+#
+# Automatically generated make config: don't edit
+#
+CONFIG_MIPS=y
+# CONFIG_MIPS64 is not set
+# CONFIG_64BIT is not set
+CONFIG_MIPS32=y
+
+#
+# Code maturity level options
+#
+# CONFIG_EXPERIMENTAL is not set
+CONFIG_CLEAN_COMPILE=y
+CONFIG_STANDALONE=y
+CONFIG_BROKEN_ON_SMP=y
+
+#
+# General setup
+#
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_EMBEDDED=y
+CONFIG_KALLSYMS=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+
+#
+# Loadable module support
+#
+# CONFIG_MODULES is not set
+
+#
+# Machine selection
+#
+# CONFIG_MACH_JAZZ is not set
+# CONFIG_MACH_VR41XX is not set
+# CONFIG_TOSHIBA_JMR3927 is not set
+# CONFIG_MACH_DECSTATION is not set
+# CONFIG_MIPS_IVR is not set
+# CONFIG_LASAT is not set
+# CONFIG_HP_LASERJET is not set
+# CONFIG_MIPS_ITE8172 is not set
+# CONFIG_MIPS_ATLAS is not set
+# CONFIG_MIPS_MALTA is not set
+# CONFIG_MOMENCO_OCELOT is not set
+# CONFIG_MOMENCO_OCELOT_G is not set
+# CONFIG_MOMENCO_OCELOT_C is not set
+CONFIG_MOMENCO_JAGUAR_ATX=y
+# CONFIG_PMC_YOSEMITE is not set
+# CONFIG_DDB5476 is not set
+# CONFIG_DDB5477 is not set
+# CONFIG_NEC_OSPREY is not set
+# CONFIG_SGI_IP22 is not set
+# CONFIG_SOC_AU1X00 is not set
+# CONFIG_SNI_RM200_PCI is not set
+# CONFIG_TOSHIBA_RBTX4927 is not set
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_HAVE_DEC_LOCK=y
+CONFIG_DMA_NONCOHERENT=y
+# CONFIG_CPU_LITTLE_ENDIAN is not set
+CONFIG_IRQ_CPU=y
+CONFIG_IRQ_CPU_RM7K=y
+CONFIG_MIPS_MV64340=y
+CONFIG_SWAP_IO_SPACE=y
+CONFIG_BOOT_ELF32=y
+CONFIG_MIPS_L1_CACHE_SHIFT=5
+# CONFIG_FB is not set
+CONFIG_BOARD_SCACHE=y
+
+#
+# CPU selection
+#
+# CONFIG_CPU_MIPS32 is not set
+# CONFIG_CPU_MIPS64 is not set
+# CONFIG_CPU_R3000 is not set
+# CONFIG_CPU_TX39XX is not set
+# CONFIG_CPU_VR41XX is not set
+# CONFIG_CPU_R4300 is not set
+# CONFIG_CPU_R4X00 is not set
+# CONFIG_CPU_TX49XX is not set
+# CONFIG_CPU_R5000 is not set
+# CONFIG_CPU_R5432 is not set
+# CONFIG_CPU_R6000 is not set
+# CONFIG_CPU_NEVADA is not set
+# CONFIG_CPU_R8000 is not set
+# CONFIG_CPU_R10000 is not set
+# CONFIG_CPU_RM7000 is not set
+CONFIG_CPU_RM9000=y
+# CONFIG_CPU_SB1 is not set
+CONFIG_PAGE_SIZE_4KB=y
+# CONFIG_PAGE_SIZE_16KB is not set
+# CONFIG_PAGE_SIZE_64KB is not set
+CONFIG_CPU_HAS_PREFETCH=y
+# CONFIG_64BIT_PHYS_ADDR is not set
+# CONFIG_CPU_ADVANCED is not set
+CONFIG_CPU_HAS_LLSC=y
+CONFIG_CPU_HAS_LLDSCD=y
+CONFIG_CPU_HAS_SYNC=y
+# CONFIG_SMP is not set
+# CONFIG_PREEMPT is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+
+#
+# Bus options (PCI, PCMCIA, EISA, ISA, TC)
+#
+CONFIG_PCI=y
+CONFIG_PCI_LEGACY_PROC=y
+CONFIG_PCI_NAMES=y
+CONFIG_MMU=y
+# CONFIG_HOTPLUG is not set
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_MISC is not set
+CONFIG_TRAD_SIGNALS=y
+# CONFIG_BINFMT_IRIX is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_LOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_RAM is not set
+# CONFIG_BLK_DEV_INITRD is not set
+# CONFIG_LBD is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_SCSI is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+
+#
+# Networking support
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+# CONFIG_PACKET is not set
+# CONFIG_NETLINK_DEV is not set
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_PNP=y
+# CONFIG_IP_PNP_DHCP is not set
+CONFIG_IP_PNP_BOOTP=y
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_INET_ECN is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_DECNET is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_NETFILTER is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+CONFIG_NETDEVICES=y
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_SUNGEM is not set
+# CONFIG_NET_VENDOR_3COM is not set
+
+#
+# Tulip family network device support
+#
+# CONFIG_NET_TULIP is not set
+# CONFIG_HP100 is not set
+CONFIG_NET_PCI=y
+# CONFIG_PCNET32 is not set
+# CONFIG_AMD8111_ETH is not set
+# CONFIG_ADAPTEC_STARFIRE is not set
+# CONFIG_DGRS is not set
+CONFIG_EEPRO100=y
+# CONFIG_EEPRO100_PIO is not set
+# CONFIG_E100 is not set
+# CONFIG_FEALNX is not set
+# CONFIG_NATSEMI is not set
+# CONFIG_NE2K_PCI is not set
+# CONFIG_8139TOO is not set
+# CONFIG_SIS900 is not set
+# CONFIG_EPIC100 is not set
+# CONFIG_SUNDANCE is not set
+# CONFIG_TLAN is not set
+# CONFIG_VIA_RHINE is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+# CONFIG_E1000 is not set
+# CONFIG_NS83820 is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_R8169 is not set
+# CONFIG_SK98LIN is not set
+# CONFIG_TIGON3 is not set
+CONFIG_MV64340_ETH=y
+CONFIG_MV64340_ETH_0=y
+# CONFIG_MV64340_ETH_1 is not set
+# CONFIG_MV64340_ETH_2 is not set
+
+#
+# Ethernet (10000 Mbit)
+#
+# CONFIG_IXGB is not set
+# CONFIG_FDDI is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Token Ring devices
+#
+# CONFIG_TR is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+
+#
+# Amateur Radio support
+#
+# CONFIG_HAMRADIO is not set
+
+#
+# IrDA (infrared) support
+#
+# CONFIG_IRDA is not set
+
+#
+# Bluetooth support
+#
+# CONFIG_BT is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN_BOOL is not set
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+# CONFIG_INPUT is not set
+
+#
+# Userland interfaces
+#
+
+#
+# Input I/O drivers
+#
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+CONFIG_SERIO=y
+CONFIG_SERIO_I8042=y
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_CT82C710 is not set
+# CONFIG_SERIO_PCIPS2 is not set
+
+#
+# Input Device Drivers
+#
+
+#
+# Character devices
+#
+# CONFIG_VT is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_UNIX98_PTYS=y
+CONFIG_UNIX98_PTY_COUNT=256
+
+#
+# Mice
+#
+# CONFIG_BUSMOUSE is not set
+# CONFIG_QIC02_TAPE is not set
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_NVRAM is not set
+# CONFIG_RTC is not set
+# CONFIG_GEN_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_FTAPE is not set
+# CONFIG_AGP is not set
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+# CONFIG_USB is not set
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# File systems
+#
+# CONFIG_EXT2_FS is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_JBD is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_QUOTA is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_FAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_DEVPTS_FS=y
+# CONFIG_DEVPTS_FS_XATTR is not set
+# CONFIG_TMPFS is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+# CONFIG_NFS_V3 is not set
+# CONFIG_NFSD is not set
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+# CONFIG_EXPORTFS is not set
+CONFIG_SUNRPC=y
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+
+#
+# Native Language Support
+#
+# CONFIG_NLS is not set
+
+#
+# Kernel hacking
+#
+CONFIG_CROSSCOMPILE=y
+CONFIG_CMDLINE=""
+# CONFIG_DEBUG_KERNEL is not set
+
+#
+# Security options
+#
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
+# Library routines
+#
+# CONFIG_CRC32 is not set
--- diff/arch/mips/kernel/genrtc.c	1970-01-01 01:00:00.000000000 +0100
+++ source/arch/mips/kernel/genrtc.c	2004-02-23 13:56:38.000000000 +0000
@@ -0,0 +1,64 @@
+/*
+ * A glue layer that provides RTC read/write to drivers/char/genrtc.c driver
+ * based on MIPS internal RTC routines.  It does take care locking
+ * issues so that we are SMP/Preemption safe.
+ *
+ * Copyright (C) 2004 MontaVista Software Inc.
+ * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net
+ *
+ * Please read the COPYING file for all license details.
+ */
+
+#include <linux/spinlock.h>
+
+#include <asm/rtc.h>
+#include <asm/time.h>
+
+static spinlock_t mips_rtc_lock = SPIN_LOCK_UNLOCKED;
+
+unsigned int get_rtc_time(struct rtc_time *time)
+{
+	unsigned long nowtime;
+
+	spin_lock(&mips_rtc_lock);
+	nowtime = rtc_get_time();
+	to_tm(nowtime, time);
+	time->tm_year -= 1900;
+	spin_unlock(&mips_rtc_lock);
+
+	return RTC_24H;
+}
+
+int set_rtc_time(struct rtc_time *time)
+{
+	unsigned long nowtime;
+	int ret;
+
+	spin_lock(&mips_rtc_lock);
+	nowtime = mktime(time->tm_year+1900, time->tm_mon+1,
+			time->tm_mday, time->tm_hour, time->tm_min,
+			time->tm_sec);
+	ret = rtc_set_time(nowtime);
+	spin_unlock(&mips_rtc_lock);
+
+	return ret;
+}
+
+unsigned int get_rtc_ss(void)
+{
+	struct rtc_time h;
+
+	get_rtc_time(&h);
+	return h.tm_sec;
+}
+
+int get_rtc_pll(struct rtc_pll_info *pll)
+{
+	return -EINVAL;
+}
+
+int set_rtc_pll(struct rtc_pll_info *pll)
+{
+	return -EINVAL;
+}
+
--- diff/arch/mips/kernel/irq-rm7000.c	1970-01-01 01:00:00.000000000 +0100
+++ source/arch/mips/kernel/irq-rm7000.c	2004-02-23 13:56:38.000000000 +0000
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2003 Ralf Baechle
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ *
+ * Handler for RM7000 extended interrupts.  These are a non-standard
+ * feature so we handle them separately from standard interrupts.
+ */
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+
+#include <asm/irq_cpu.h>
+#include <asm/mipsregs.h>
+#include <asm/system.h>
+
+static int irq_base;
+
+static inline void unmask_rm7k_irq(unsigned int irq)
+{
+	set_c0_intcontrol(1 << (irq - irq_base));
+}
+
+static inline void mask_rm7k_irq(unsigned int irq)
+{
+	clear_c0_intcontrol(1 << (irq - irq_base));
+}
+
+static inline void rm7k_cpu_irq_enable(unsigned int irq)
+{
+	unsigned long flags;
+
+	local_irq_save(flags);
+	unmask_rm7k_irq(irq);
+	local_irq_restore(flags);
+}
+
+static void rm7k_cpu_irq_disable(unsigned int irq)
+{
+	unsigned long flags;
+
+	local_irq_save(flags);
+	mask_rm7k_irq(irq);
+	local_irq_restore(flags);
+}
+
+static unsigned int rm7k_cpu_irq_startup(unsigned int irq)
+{
+	rm7k_cpu_irq_enable(irq);
+
+	return 0;
+}
+
+#define	rm7k_cpu_irq_shutdown	rm7k_cpu_irq_disable
+
+/*
+ * While we ack the interrupt interrupts are disabled and thus we don't need
+ * to deal with concurrency issues.  Same for rm7k_cpu_irq_end.
+ */
+static void rm7k_cpu_irq_ack(unsigned int irq)
+{
+	mask_rm7k_irq(irq);
+}
+
+static void rm7k_cpu_irq_end(unsigned int irq)
+{
+	if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS)))
+		unmask_rm7k_irq(irq);
+}
+
+static hw_irq_controller rm7k_irq_controller = {
+	"RM7000",
+	rm7k_cpu_irq_startup,
+	rm7k_cpu_irq_shutdown,
+	rm7k_cpu_irq_enable,
+	rm7k_cpu_irq_disable,
+	rm7k_cpu_irq_ack,
+	rm7k_cpu_irq_end,
+};
+
+void __init rm7k_cpu_irq_init(int base)
+{
+	int i;
+
+	for (i = base; i < base + 4; i++) {
+		irq_desc[i].status = IRQ_DISABLED;
+		irq_desc[i].action = NULL;
+		irq_desc[i].depth = 1;
+		irq_desc[i].handler = &rm7k_irq_controller;
+	}
+
+	irq_base = base;
+}
--- diff/arch/mips/lasat/pci.c	1970-01-01 01:00:00.000000000 +0100
+++ source/arch/mips/lasat/pci.c	2004-02-23 13:56:38.000000000 +0000
@@ -0,0 +1,25 @@
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <asm/bootinfo.h>
+
+extern struct pci_ops nile4_pci_ops;
+extern struct pci_ops gt64120_pci_ops;
+
+void __init pcibios_init(void)
+{
+	struct pci_ops *pci_ops;
+
+	switch (mips_machtype) {
+	case MACH_LASAT_100:
+		pci_ops = &gt64120_pci_ops;
+		break;
+	case MACH_LASAT_200:
+		pci_ops = &nile4_pci_ops;
+		break;
+	default:
+		panic("pcibios_init: mips_machtype incorrect");
+	}
+
+	pci_scan_bus(0, pci_ops, NULL);
+}
--- diff/arch/mips/lib/dec_and_lock.c	1970-01-01 01:00:00.000000000 +0100
+++ source/arch/mips/lib/dec_and_lock.c	2004-02-23 13:56:38.000000000 +0000
@@ -0,0 +1,55 @@
+/*
+ * MIPS version of atomic_dec_and_lock() using cmpxchg
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#include <linux/module.h>
+#include <linux/spinlock.h>
+#include <asm/atomic.h>
+#include <asm/system.h>
+
+/*
+ * This is an implementation of the notion of "decrement a
+ * reference count, and return locked if it decremented to zero".
+ *
+ * This implementation can be used on any architecture that
+ * has a cmpxchg, and where atomic->value is an int holding
+ * the value of the atomic (i.e. the high bits aren't used
+ * for a lock or anything like that).
+ *
+ * N.B. ATOMIC_DEC_AND_LOCK gets defined in include/linux/spinlock.h
+ * if spinlocks are empty and thus atomic_dec_and_lock is defined
+ * to be atomic_dec_and_test - in that case we don't need it
+ * defined here as well.
+ */
+
+#ifndef ATOMIC_DEC_AND_LOCK
+int atomic_dec_and_lock(atomic_t *atomic, spinlock_t *lock)
+{
+	int counter;
+	int newcount;
+
+	for (;;) {
+		counter = atomic_read(atomic);
+		newcount = counter - 1;
+		if (!newcount)
+			break;		/* do it the slow way */
+
+		newcount = cmpxchg(&atomic->counter, counter, newcount);
+		if (newcount == counter)
+			return 0;
+	}
+
+	spin_lock(lock);
+	if (atomic_dec_and_test(atomic))
+		return 1;
+	spin_unlock(lock);
+	return 0;
+}
+
+EXPORT_SYMBOL(atomic_dec_and_lock);
+#endif /* ATOMIC_DEC_AND_LOCK */
--- diff/arch/mips/lib/strlen_user.S	1970-01-01 01:00:00.000000000 +0100
+++ source/arch/mips/lib/strlen_user.S	2004-02-23 13:56:38.000000000 +0000
@@ -0,0 +1,40 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (c) 1996, 1998, 1999 by Ralf Baechle
+ * Copyright (c) 1999 Silicon Graphics, Inc.
+ */
+#include <asm/asm.h>
+#include <asm/offset.h>
+#include <asm/regdef.h>
+#include <asm/sgidefs.h>
+
+#define EX(insn,reg,addr,handler)			\
+9:	insn	reg, addr;				\
+	.section __ex_table,"a";			\
+	PTR	9b, handler;				\
+	.previous
+
+/*
+ * Return the size of a string (including the ending 0)
+ *
+ * Return 0 for error
+ */
+LEAF(__strlen_user_asm)
+	LONG_L		v0, TI_ADDR_LIMIT($28)	# pointer ok?
+	and		v0, a0
+	bnez		v0, fault
+
+FEXPORT(__strlen_user_nocheck_asm)
+	move		v0, a0
+1:	EX(lb, t0, (v0), fault)
+	PTR_ADDIU	v0, 1
+	bnez		t0, 1b
+	PTR_SUBU	v0, a0
+	jr		ra
+	END(__strlen_user_asm)
+
+fault:	move		v0, zero
+	jr		ra
--- diff/arch/mips/lib/strncpy_user.S	1970-01-01 01:00:00.000000000 +0100
+++ source/arch/mips/lib/strncpy_user.S	2004-02-23 13:56:38.000000000 +0000
@@ -0,0 +1,58 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (c) 1996, 1999 by Ralf Baechle
+ */
+#include <linux/errno.h>
+#include <asm/asm.h>
+#include <asm/offset.h>
+#include <asm/regdef.h>
+
+#define EX(insn,reg,addr,handler)			\
+9:	insn	reg, addr;				\
+	.section __ex_table,"a";			\
+	PTR	9b, handler;				\
+	.previous
+
+/*
+ * Returns: -EFAULT if exception before terminator, N if the entire
+ * buffer filled, else strlen.
+ */
+
+/*
+ * Ugly special case have to check: we might get passed a user space
+ * pointer which wraps into the kernel space.  We don't deal with that.  If
+ * it happens at most some bytes of the exceptions handlers will be copied.
+ */
+
+LEAF(__strncpy_from_user_asm)
+	LONG_L		v0, TI_ADDR_LIMIT($28)	# pointer ok?
+	and		v0, a1
+	bnez		v0, fault
+
+FEXPORT(__strncpy_from_user_nocheck_asm)
+	move		v0, zero
+	move		v1, a1
+	.set		noreorder
+1:	EX(lbu, t0, (v1), fault)
+	PTR_ADDIU	v1, 1
+	beqz		t0, 2f
+	 sb		t0, (a0)
+	PTR_ADDIU	v0, 1
+	bne		v0, a2, 1b
+	 PTR_ADDIU	a0, 1
+	.set		reorder
+2:	PTR_ADDU	t0, a1, v0
+	xor		t0, a1
+	bltz		t0, fault
+	jr		ra			# return n
+	END(__strncpy_from_user_asm)
+
+fault:	li		v0, -EFAULT
+	jr		ra
+
+	.section	__ex_table,"a"
+	PTR		1b, fault
+	.previous
--- diff/arch/mips/lib/strnlen_user.S	1970-01-01 01:00:00.000000000 +0100
+++ source/arch/mips/lib/strnlen_user.S	2004-02-23 13:56:38.000000000 +0000
@@ -0,0 +1,46 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (c) 1996, 1998, 1999 by Ralf Baechle
+ * Copyright (c) 1999 Silicon Graphics, Inc.
+ */
+#include <asm/asm.h>
+#include <asm/offset.h>
+#include <asm/regdef.h>
+#include <asm/sgidefs.h>
+
+#define EX(insn,reg,addr,handler)			\
+9:	insn	reg, addr;				\
+	.section __ex_table,"a";			\
+	PTR	9b, handler;				\
+	.previous
+
+/*
+ * Return the size of a string including the ending NUL character upto a
+ * maximum of a1 or 0 in case of error.
+ *
+ * Note: for performance reasons we deliberately accept that a user may
+ *       make strlen_user and strnlen_user access the first few KSEG0
+ *       bytes.  There's nothing secret there.  On 64-bit accessing beyond
+ *       the maximum is a tad hairier ...
+ */
+LEAF(__strnlen_user_asm)
+	LONG_L		v0, TI_ADDR_LIMIT($28)	# pointer ok?
+	and		v0, a0
+	bnez		v0, fault
+
+FEXPORT(__strnlen_user_nocheck_asm)
+	move		v0, a0
+	PTR_ADDU	a1, a0			# stop pointer
+1:	beq		v0, a1, 1f		# limit reached?
+	EX(lb, t0, (v0), fault)
+	PTR_ADDU	v0, 1
+	bnez		t0, 1b
+1:	PTR_SUBU	v0, a0
+	jr		ra
+	END(__strnlen_user_asm)
+
+fault:	move		v0, zero
+	jr		ra
--- diff/arch/mips/mips-boards/atlas/atlas_gdb.c	1970-01-01 01:00:00.000000000 +0100
+++ source/arch/mips/mips-boards/atlas/atlas_gdb.c	2004-02-23 13:56:38.000000000 +0000
@@ -0,0 +1,97 @@
+/*
+ * Carsten Langgaard, carstenl@mips.com
+ * Copyright (C) 2000 MIPS Technologies, Inc.  All rights reserved.
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * This is the interface to the remote debugger stub.
+ */
+#include <asm/io.h>
+#include <asm/mips-boards/atlas.h>
+#include <asm/mips-boards/saa9730_uart.h>
+
+#define INB(a)     inb((unsigned long)a)
+#define OUTB(x,a)  outb(x,(unsigned long)a)
+
+/*
+ * This is the interface to the remote debugger stub
+ * if the Philips part is used for the debug port,
+ * called from the platform setup code.
+ */
+void *saa9730_base = (void *)ATLAS_SAA9730_REG;
+
+static int saa9730_kgdb_active = 0;
+
+#define SAA9730_BAUDCLOCK(baud) (((ATLAS_SAA9730_BAUDCLOCK/(baud))/16)-1)
+
+int saa9730_kgdb_hook(int speed)
+{
+	int baudclock;
+	t_uart_saa9730_regmap *kgdb_uart = (t_uart_saa9730_regmap *)(saa9730_base + SAA9730_UART_REGS_ADDR);
+
+        /*
+         * Clear all interrupts
+         */
+	(void) INB(&kgdb_uart->Lsr);
+	(void) INB(&kgdb_uart->Msr);
+	(void) INB(&kgdb_uart->Thr_Rbr);
+	(void) INB(&kgdb_uart->Iir_Fcr);
+
+        /*
+         * Now, initialize the UART
+         */
+	/* 8 data bits, one stop bit, no parity */
+	OUTB(SAA9730_LCR_DATA8, &kgdb_uart->Lcr);
+
+	baudclock = SAA9730_BAUDCLOCK(speed);
+
+	OUTB((baudclock >> 16) & 0xff, &kgdb_uart->BaudDivMsb);
+	OUTB( baudclock        & 0xff, &kgdb_uart->BaudDivLsb);
+
+	/* Set RTS/DTR active */
+	OUTB(SAA9730_MCR_DTR | SAA9730_MCR_RTS, &kgdb_uart->Mcr);
+	saa9730_kgdb_active = 1;
+
+	return speed;
+}
+
+int saa9730_putDebugChar(char c)
+{
+	t_uart_saa9730_regmap *kgdb_uart = (t_uart_saa9730_regmap *)(saa9730_base + SAA9730_UART_REGS_ADDR);
+
+        if (!saa9730_kgdb_active) {     /* need to init device first */
+                return 0;
+        }
+
+        while (!(INB(&kgdb_uart->Lsr) & SAA9730_LSR_THRE))
+                ;
+	OUTB(c, &kgdb_uart->Thr_Rbr);
+
+        return 1;
+}
+
+char saa9730_getDebugChar(void)
+{
+	t_uart_saa9730_regmap *kgdb_uart = (t_uart_saa9730_regmap *)(saa9730_base + SAA9730_UART_REGS_ADDR);
+	char c;
+
+        if (!saa9730_kgdb_active) {     /* need to init device first */
+                return 0;
+        }
+        while (!(INB(&kgdb_uart->Lsr) & SAA9730_LSR_DR))
+                ;
+
+	c = INB(&kgdb_uart->Thr_Rbr);
+	return(c);
+}
--- diff/arch/mips/mips-boards/generic/pci.c	1970-01-01 01:00:00.000000000 +0100
+++ source/arch/mips/mips-boards/generic/pci.c	2004-02-23 13:56:38.000000000 +0000
@@ -0,0 +1,162 @@
+/*
+ * Carsten Langgaard, carstenl@mips.com
+ * Copyright (C) 1999, 2000 MIPS Technologies, Inc.  All rights reserved.
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * MIPS boards specific PCI support.
+ */
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+
+#include <asm/mips-boards/generic.h>
+#include <asm/pci_channel.h>
+#include <asm/gt64120.h>
+#include <asm/mips-boards/bonito64.h>
+#include <asm/mips-boards/msc01_pci.h>
+#ifdef CONFIG_MIPS_MALTA
+#include <asm/mips-boards/malta.h>
+#endif
+
+static struct resource bonito64_mem_resource = {
+	.name	= "Bonito PCI MEM",
+	.start	= 0x10000000UL,
+	.end	= 0x1bffffffUL,
+	.flags	= IORESOURCE_MEM,
+};
+
+static struct resource bonito64_io_resource = {
+	.name	= "Bonito IO MEM",
+	.start	= 0x00002000UL,	/* avoid conflicts with YAMON allocated I/O addresses */
+	.end	= 0x000fffffUL,
+	.flags	= IORESOURCE_IO,
+};
+
+static struct resource gt64120_mem_resource = {
+	.name	= "GT64120 PCI MEM",
+	.start	= 0x10000000UL,
+	.end	= 0x1bdfffffUL,
+	.flags	= IORESOURCE_MEM,
+};
+
+static struct resource gt64120_io_resource = {
+	.name	= "GT64120 IO MEM",
+#ifdef CONFIG_MIPS_ATLAS
+	.start	= 0x18000000UL,
+	.end	= 0x181fffffUL,
+#endif
+#ifdef CONFIG_MIPS_MALTA
+	.start	= 0x00002000UL,
+	.end	= 0x001fffffUL,
+#endif
+	.flags	= IORESOURCE_IO,
+};
+
+static struct resource msc_mem_resource = {
+	.name	= "MSC PCI MEM",
+	.start	= 0x10000000UL,
+	.end	= 0x1fffffffUL,
+	.flags	= IORESOURCE_MEM,
+};
+
+static struct resource msc_io_resource = {
+	.name	= "MSC IO MEM",
+	.start	= 0x00002000UL,
+	.end	= 0x007fffffUL,
+	.flags	= IORESOURCE_IO,
+};
+
+extern struct pci_ops bonito64_pci_ops;
+extern struct pci_ops gt64120_pci_ops;
+extern struct pci_ops msc_pci_ops;
+
+static struct pci_controller bonito64_controller = {
+	.pci_ops	= &bonito64_pci_ops,
+	.io_resource	= &bonito64_io_resource,
+	.mem_resource	= &bonito64_mem_resource,
+	.mem_offset	= 0x10000000UL,
+	.io_offset	= 0x00000000UL,
+};
+
+static struct pci_controller gt64120_controller = {
+	.pci_ops	= &gt64120_pci_ops,
+	.io_resource	= &gt64120_io_resource,
+	.mem_resource	= &gt64120_mem_resource,
+	.mem_offset	= 0x00000000UL,
+	.io_offset	= 0x00000000UL,
+};
+
+static struct pci_controller  msc_controller = {
+	.pci_ops	= &msc_pci_ops,
+	.io_resource	= &msc_io_resource,
+	.mem_resource	= &msc_mem_resource,
+	.mem_offset	= 0x10000000UL,
+	.io_offset	= 0x00000000UL,
+};
+
+static int __init pcibios_init(void)
+{
+	struct pci_controller *controller;
+
+	switch (mips_revision_corid) {
+	case MIPS_REVISION_CORID_QED_RM5261:
+	case MIPS_REVISION_CORID_CORE_LV:
+	case MIPS_REVISION_CORID_CORE_FPGA:
+	case MIPS_REVISION_CORID_CORE_FPGAR2:
+		/*
+		 * Due to a bug in the Galileo system controller, we need
+		 * to setup the PCI BAR for the Galileo internal registers.
+		 * This should be done in the bios/bootprom and will be
+		 * fixed in a later revision of YAMON (the MIPS boards
+		 * boot prom).
+		 */
+		GT_WRITE(GT_PCI0_CFGADDR_OFS,
+			 (0 << GT_PCI0_CFGADDR_BUSNUM_SHF) | /* Local bus */
+			 (0 << GT_PCI0_CFGADDR_DEVNUM_SHF) | /* GT64120 dev */
+			 (0 << GT_PCI0_CFGADDR_FUNCTNUM_SHF) | /* Function 0*/
+			 ((0x20/4) << GT_PCI0_CFGADDR_REGNUM_SHF) | /* BAR 4*/
+			 GT_PCI0_CFGADDR_CONFIGEN_BIT );
+
+		/* Perform the write */
+		GT_WRITE(GT_PCI0_CFGDATA_OFS, CPHYSADDR(MIPS_GT_BASE));
+
+		controller = &gt64120_controller;
+		break;
+
+	case MIPS_REVISION_CORID_BONITO64:
+	case MIPS_REVISION_CORID_CORE_20K:
+	case MIPS_REVISION_CORID_CORE_EMUL_BON:
+		controller = &bonito64_controller;
+		break;
+
+	case MIPS_REVISION_CORID_CORE_MSC:
+	case MIPS_REVISION_CORID_CORE_FPGA2:
+	case MIPS_REVISION_CORID_CORE_EMUL_MSC:
+		controller = &msc_controller;
+		break;
+	default:
+		return 1;
+	}
+
+	ioport_resource.end = controller->io_resource->end;
+
+	register_pci_controller (controller);
+
+	return 0;
+}
+
+early_initcall(pcibios_init);
--- diff/arch/mips/mm/dma-coherent.c	1970-01-01 01:00:00.000000000 +0100
+++ source/arch/mips/mm/dma-coherent.c	2004-02-23 13:56:38.000000000 +0000
@@ -0,0 +1,215 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2000  Ani Joshi <ajoshi@unixbox.com>
+ * Copyright (C) 2000, 2001  Ralf Baechle <ralf@gnu.org>
+ * swiped from i386, and cloned for MIPS by Geert, polished by Ralf.
+ */
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/string.h>
+#include <linux/pci.h>
+
+#include <asm/cache.h>
+#include <asm/io.h>
+
+void *dma_alloc_noncoherent(struct device *dev, size_t size,
+	dma_addr_t * dma_handle, int gfp)
+{
+	void *ret;
+	/* ignore region specifiers */
+	gfp &= ~(__GFP_DMA | __GFP_HIGHMEM);
+
+	if (dev == NULL || (*dev->dma_mask < 0xffffffff))
+		gfp |= GFP_DMA;
+	ret = (void *) __get_free_pages(gfp, get_order(size));
+
+	if (ret != NULL) {
+		memset(ret, 0, size);
+		*dma_handle = virt_to_phys(ret);
+	}
+
+	return ret;
+}
+
+EXPORT_SYMBOL(dma_alloc_noncoherent);
+
+void *dma_alloc_coherent(struct device *dev, size_t size,
+	dma_addr_t * dma_handle, int gfp)
+	__attribute__((alias("dma_alloc_noncoherent")));
+
+EXPORT_SYMBOL(dma_alloc_coherent);
+
+void dma_free_noncoherent(struct device *dev, size_t size, void *vaddr,
+	dma_addr_t dma_handle)
+{
+	unsigned long addr = (unsigned long) vaddr;
+
+	free_pages(addr, get_order(size));
+}
+
+EXPORT_SYMBOL(dma_free_noncoherent);
+
+void dma_free_coherent(struct device *dev, size_t size, void *vaddr,
+	dma_addr_t dma_handle) __attribute__((alias("dma_free_noncoherent")));
+
+EXPORT_SYMBOL(dma_free_coherent);
+
+dma_addr_t dma_map_single(struct device *dev, void *ptr, size_t size,
+	enum dma_data_direction direction)
+{
+	BUG_ON(direction == DMA_NONE);
+
+	return __pa(ptr);
+}
+
+EXPORT_SYMBOL(dma_map_single);
+
+void dma_unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size,
+		 enum dma_data_direction direction)
+{
+	BUG_ON(direction == DMA_NONE);
+}
+
+EXPORT_SYMBOL(dma_unmap_single);
+
+int dma_map_sg(struct device *dev, struct scatterlist *sg, int nents,
+	enum dma_data_direction direction)
+{
+	int i;
+
+	BUG_ON(direction == DMA_NONE);
+
+	for (i = 0; i < nents; i++, sg++) {
+		sg->dma_address = (dma_addr_t)page_to_phys(sg->page) + sg->offset;
+	}
+
+	return nents;
+}
+
+EXPORT_SYMBOL(dma_map_sg);
+
+dma_addr_t dma_map_page(struct device *dev, struct page *page,
+	unsigned long offset, size_t size, enum dma_data_direction direction)
+{
+	BUG_ON(direction == DMA_NONE);
+
+	return page_to_phys(page) + offset;
+}
+
+EXPORT_SYMBOL(dma_map_page);
+
+void dma_unmap_page(struct device *dev, dma_addr_t dma_address, size_t size,
+	       enum dma_data_direction direction)
+{
+	BUG_ON(direction == DMA_NONE);
+}
+
+EXPORT_SYMBOL(dma_unmap_page);
+
+void dma_unmap_sg(struct device *dev, struct scatterlist *sg, int nhwentries,
+	     enum dma_data_direction direction)
+{
+	BUG_ON(direction == DMA_NONE);
+}
+
+EXPORT_SYMBOL(dma_unmap_sg);
+
+void dma_sync_single(struct device *dev, dma_addr_t dma_handle, size_t size,
+		enum dma_data_direction direction)
+{
+	BUG_ON(direction == DMA_NONE);
+}
+
+EXPORT_SYMBOL(dma_sync_single);
+
+void dma_sync_single_range(struct device *dev, dma_addr_t dma_handle,
+		      unsigned long offset, size_t size,
+		      enum dma_data_direction direction)
+{
+	BUG_ON(direction == DMA_NONE);
+}
+
+EXPORT_SYMBOL(dma_sync_single_range);
+
+void dma_sync_sg(struct device *dev, struct scatterlist *sg, int nelems,
+		 enum dma_data_direction direction)
+{
+	BUG_ON(direction == DMA_NONE);
+}
+
+EXPORT_SYMBOL(dma_sync_sg);
+
+int dma_supported(struct device *dev, u64 mask)
+{
+	/*
+	 * we fall back to GFP_DMA when the mask isn't all 1s,
+	 * so we can't guarantee allocations that must be
+	 * within a tighter range than GFP_DMA..
+	 */
+	if (mask < 0x00ffffff)
+		return 0;
+
+	return 1;
+}
+
+EXPORT_SYMBOL(dma_supported);
+
+int dma_is_consistent(dma_addr_t dma_addr)
+{
+	return 1;
+}
+
+EXPORT_SYMBOL(dma_is_consistent);
+
+void dma_cache_sync(void *vaddr, size_t size,
+	       enum dma_data_direction direction)
+{
+	BUG_ON(direction == DMA_NONE);
+}
+
+EXPORT_SYMBOL(dma_cache_sync);
+
+/* The DAC routines are a PCIism.. */
+
+#ifdef CONFIG_PCI
+
+#include <linux/pci.h>
+
+dma64_addr_t pci_dac_page_to_dma(struct pci_dev *pdev,
+	struct page *page, unsigned long offset, int direction)
+{
+	return (dma64_addr_t)page_to_phys(page) + offset;
+}
+
+EXPORT_SYMBOL(pci_dac_page_to_dma);
+
+struct page *pci_dac_dma_to_page(struct pci_dev *pdev,
+	dma64_addr_t dma_addr)
+{
+	return mem_map + (dma_addr >> PAGE_SHIFT);
+}
+
+EXPORT_SYMBOL(pci_dac_dma_to_page);
+
+unsigned long pci_dac_dma_to_offset(struct pci_dev *pdev,
+	dma64_addr_t dma_addr)
+{
+	return dma_addr & ~PAGE_MASK;
+}
+
+EXPORT_SYMBOL(pci_dac_dma_to_offset);
+
+void pci_dac_dma_sync_single(struct pci_dev *pdev,
+	dma64_addr_t dma_addr, size_t len, int direction)
+{
+	BUG_ON(direction == PCI_DMA_NONE);
+}
+
+EXPORT_SYMBOL(pci_dac_dma_sync_single);
+
+#endif /* CONFIG_PCI */
--- diff/arch/mips/mm/dma-ip27.c	1970-01-01 01:00:00.000000000 +0100
+++ source/arch/mips/mm/dma-ip27.c	2004-02-23 13:56:38.000000000 +0000
@@ -0,0 +1,217 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2000  Ani Joshi <ajoshi@unixbox.com>
+ * Copyright (C) 2000, 2001  Ralf Baechle <ralf@gnu.org>
+ * swiped from i386, and cloned for MIPS by Geert, polished by Ralf.
+ */
+#include <linux/types.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/string.h>
+#include <linux/pci.h>
+
+#include <asm/cache.h>
+#include <asm/pci/bridge.h>
+
+#define pdev_to_baddr(pdev, addr) \
+	(BRIDGE_CONTROLLER(pdev->bus)->baddr + (addr))
+#define dev_to_baddr(dev, addr) \
+	pdev_to_baddr(to_pci_dev(dev), (addr))
+
+void *dma_alloc_noncoherent(struct device *dev, size_t size,
+	dma_addr_t * dma_handle, int gfp)
+{
+	void *ret;
+
+	/* ignore region specifiers */
+	gfp &= ~(__GFP_DMA | __GFP_HIGHMEM);
+
+	if (dev == NULL || (*dev->dma_mask < 0xffffffff))
+		gfp |= GFP_DMA;
+	ret = (void *) __get_free_pages(gfp, get_order(size));
+
+	if (ret != NULL) {
+		memset(ret, 0, size);
+		*dma_handle = dev_to_baddr(dev, virt_to_phys(ret));
+	}
+
+	return ret;
+}
+
+EXPORT_SYMBOL(dma_alloc_noncoherent);
+
+void *dma_alloc_coherent(struct device *dev, size_t size,
+	dma_addr_t * dma_handle, int gfp)
+	__attribute__((alias("dma_alloc_noncoherent")));
+
+EXPORT_SYMBOL(dma_alloc_coherent);
+
+void dma_free_noncoherent(struct device *dev, size_t size, void *vaddr,
+	dma_addr_t dma_handle)
+{
+	unsigned long addr = (unsigned long) vaddr;
+
+	free_pages(addr, get_order(size));
+}
+
+EXPORT_SYMBOL(dma_free_noncoherent);
+
+void dma_free_coherent(struct device *dev, size_t size, void *vaddr,
+	dma_addr_t dma_handle) __attribute__((alias("dma_free_noncoherent")));
+
+EXPORT_SYMBOL(dma_free_coherent);
+
+dma_addr_t dma_map_single(struct device *dev, void *ptr, size_t size,
+	enum dma_data_direction direction)
+{
+	BUG_ON(direction == DMA_NONE);
+
+	return dev_to_baddr(dev, __pa(ptr));
+}
+
+EXPORT_SYMBOL(dma_map_single);
+
+void dma_unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size,
+		 enum dma_data_direction direction)
+{
+	BUG_ON(direction == DMA_NONE);
+}
+
+EXPORT_SYMBOL(dma_unmap_single);
+
+int dma_map_sg(struct device *dev, struct scatterlist *sg, int nents,
+	enum dma_data_direction direction)
+{
+	int i;
+
+	BUG_ON(direction == DMA_NONE);
+
+	for (i = 0; i < nents; i++, sg++) {
+		sg->dma_address = (dma_addr_t) dev_to_baddr(dev,
+			page_to_phys(sg->page) + sg->offset);
+	}
+
+	return nents;
+}
+
+EXPORT_SYMBOL(dma_map_sg);
+
+dma_addr_t dma_map_page(struct device *dev, struct page *page,
+	unsigned long offset, size_t size, enum dma_data_direction direction)
+{
+	BUG_ON(direction == DMA_NONE);
+
+	return dev_to_baddr(dev, page_to_phys(page) + offset);
+}
+
+EXPORT_SYMBOL(dma_map_page);
+
+void dma_unmap_page(struct device *dev, dma_addr_t dma_address, size_t size,
+	       enum dma_data_direction direction)
+{
+	BUG_ON(direction == DMA_NONE);
+}
+
+EXPORT_SYMBOL(dma_unmap_page);
+
+void dma_unmap_sg(struct device *dev, struct scatterlist *sg, int nhwentries,
+	     enum dma_data_direction direction)
+{
+	BUG_ON(direction == DMA_NONE);
+}
+
+EXPORT_SYMBOL(dma_unmap_sg);
+
+void dma_sync_single(struct device *dev, dma_addr_t dma_handle, size_t size,
+		enum dma_data_direction direction)
+{
+	BUG_ON(direction == DMA_NONE);
+}
+
+EXPORT_SYMBOL(dma_sync_single);
+
+void dma_sync_single_range(struct device *dev, dma_addr_t dma_handle,
+		      unsigned long offset, size_t size,
+		      enum dma_data_direction direction)
+{
+	BUG_ON(direction == DMA_NONE);
+}
+
+EXPORT_SYMBOL(dma_sync_single_range);
+
+void dma_sync_sg(struct device *dev, struct scatterlist *sg, int nelems,
+		 enum dma_data_direction direction)
+{
+	BUG_ON(direction == DMA_NONE);
+}
+
+EXPORT_SYMBOL(dma_sync_sg);
+
+int dma_supported(struct device *dev, u64 mask)
+{
+	/*
+	 * we fall back to GFP_DMA when the mask isn't all 1s,
+	 * so we can't guarantee allocations that must be
+	 * within a tighter range than GFP_DMA..
+	 */
+	if (mask < 0x00ffffff)
+		return 0;
+
+	return 1;
+}
+
+EXPORT_SYMBOL(dma_supported);
+
+int dma_is_consistent(dma_addr_t dma_addr)
+{
+	return 1;
+}
+
+EXPORT_SYMBOL(dma_is_consistent);
+
+void dma_cache_sync(void *vaddr, size_t size,
+	       enum dma_data_direction direction)
+{
+	BUG_ON(direction == DMA_NONE);
+}
+
+EXPORT_SYMBOL(dma_cache_sync);
+
+dma64_addr_t pci_dac_page_to_dma(struct pci_dev *pdev,
+	struct page *page, unsigned long offset, int direction)
+{
+	dma64_addr_t addr = page_to_phys(page) + offset;
+
+	return (dma64_addr_t) pdev_to_baddr(pdev, addr);
+}
+
+EXPORT_SYMBOL(dma_cache_sync);
+
+struct page *pci_dac_dma_to_page(struct pci_dev *pdev,
+	dma64_addr_t dma_addr)
+{
+	struct bridge_controller *bc = BRIDGE_CONTROLLER(pdev->bus);
+
+	return pfn_to_page((dma_addr - bc->baddr) >> PAGE_SHIFT);
+}
+
+EXPORT_SYMBOL(pci_dac_dma_to_page);
+
+unsigned long pci_dac_dma_to_offset(struct pci_dev *pdev,
+	dma64_addr_t dma_addr)
+{
+	return dma_addr & ~PAGE_MASK;
+}
+
+EXPORT_SYMBOL(pci_dac_dma_to_offset);
+
+void pci_dac_dma_sync_single(struct pci_dev *pdev,
+	dma64_addr_t dma_addr, size_t len, int direction)
+{
+	BUG_ON(direction == PCI_DMA_NONE);
+}
+
+EXPORT_SYMBOL(pci_dac_dma_sync_single);
--- diff/arch/mips/mm/dma-noncoherent.c	1970-01-01 01:00:00.000000000 +0100
+++ source/arch/mips/mm/dma-noncoherent.c	2004-02-23 13:56:38.000000000 +0000
@@ -0,0 +1,342 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2000  Ani Joshi <ajoshi@unixbox.com>
+ * Copyright (C) 2000, 2001  Ralf Baechle <ralf@gnu.org>
+ * swiped from i386, and cloned for MIPS by Geert, polished by Ralf.
+ */
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/string.h>
+#include <linux/dma-mapping.h>
+
+#include <asm/cache.h>
+#include <asm/io.h>
+
+/*
+ * Warning on the terminology - Linux calls an uncached area coherent;
+ * MIPS terminology calls memory areas with hardware maintained coherency
+ * coherent.
+ */
+
+void *dma_alloc_noncoherent(struct device *dev, size_t size,
+	dma_addr_t * dma_handle, int gfp)
+{
+	void *ret;
+	/* ignore region specifiers */
+	gfp &= ~(__GFP_DMA | __GFP_HIGHMEM);
+
+	if (dev == NULL || (*dev->dma_mask < 0xffffffff))
+		gfp |= GFP_DMA;
+	ret = (void *) __get_free_pages(gfp, get_order(size));
+
+	if (ret != NULL) {
+		memset(ret, 0, size);
+		*dma_handle = virt_to_phys(ret);
+	}
+
+	return ret;
+}
+
+EXPORT_SYMBOL(dma_alloc_noncoherent);
+
+void *dma_alloc_coherent(struct device *dev, size_t size,
+	dma_addr_t * dma_handle, int gfp)
+{
+	void *ret;
+
+	ret = dma_alloc_noncoherent(dev, size, dma_handle, gfp);
+	if (ret) {
+		dma_cache_wback_inv((unsigned long) ret, size);
+		ret = UNCAC_ADDR(ret);
+	}
+
+	return ret;
+}
+
+EXPORT_SYMBOL(dma_alloc_coherent);
+
+void dma_free_noncoherent(struct device *dev, size_t size, void *vaddr,
+	dma_addr_t dma_handle)
+{
+	free_pages((unsigned long) vaddr, get_order(size));
+}
+
+EXPORT_SYMBOL(dma_free_noncoherent);
+
+void dma_free_coherent(struct device *dev, size_t size, void *vaddr,
+	dma_addr_t dma_handle)
+{
+	unsigned long addr = (unsigned long) vaddr;
+
+	addr = CAC_ADDR(addr);
+	free_pages(addr, get_order(size));
+}
+
+EXPORT_SYMBOL(dma_free_coherent);
+
+static inline void __dma_sync(unsigned long addr, size_t size,
+	enum dma_data_direction direction)
+{
+	switch (direction) {
+	case DMA_TO_DEVICE:
+		dma_cache_wback(addr, size);
+		break;
+
+	case DMA_FROM_DEVICE:
+		dma_cache_inv(addr, size);
+		break;
+
+	case DMA_BIDIRECTIONAL:
+		dma_cache_wback_inv(addr, size);
+		break;
+
+	default:
+		BUG();
+	}
+}
+
+dma_addr_t dma_map_single(struct device *dev, void *ptr, size_t size,
+	enum dma_data_direction direction)
+{
+	unsigned long addr = (unsigned long) ptr;
+
+	switch (direction) {
+	case DMA_TO_DEVICE:
+		dma_cache_wback(addr, size);
+		break;
+
+	case DMA_FROM_DEVICE:
+		dma_cache_inv(addr, size);
+		break;
+
+	case DMA_BIDIRECTIONAL:
+		dma_cache_wback_inv(addr, size);
+		break;
+
+	default:
+		BUG();
+	}
+
+	return virt_to_phys(ptr);
+}
+
+EXPORT_SYMBOL(dma_map_single);
+
+void dma_unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size,
+	enum dma_data_direction direction)
+{
+	unsigned long addr;
+	addr = dma_addr + PAGE_OFFSET;
+
+	switch (direction) {
+	case DMA_TO_DEVICE:
+		//dma_cache_wback(addr, size);
+		break;
+
+	case DMA_FROM_DEVICE:
+		//dma_cache_inv(addr, size);
+		break;
+
+	case DMA_BIDIRECTIONAL:
+		//dma_cache_wback_inv(addr, size);
+		break;
+
+	default:
+		BUG();
+	}
+}
+
+EXPORT_SYMBOL(dma_unmap_single);
+
+int dma_map_sg(struct device *dev, struct scatterlist *sg, int nents,
+	enum dma_data_direction direction)
+{
+	int i;
+
+	BUG_ON(direction == DMA_NONE);
+
+	for (i = 0; i < nents; i++, sg++) {
+		unsigned long addr;
+ 
+		addr = (unsigned long) page_address(sg->page);
+		if (addr)
+			__dma_sync(addr + sg->offset, sg->length, direction);
+		sg->dma_address = (dma_addr_t)
+			(page_to_phys(sg->page) + sg->offset);
+	}
+
+	return nents;
+}
+
+EXPORT_SYMBOL(dma_map_sg);
+
+dma_addr_t dma_map_page(struct device *dev, struct page *page,
+	unsigned long offset, size_t size, enum dma_data_direction direction)
+{
+	unsigned long addr;
+
+	BUG_ON(direction == DMA_NONE);
+
+	addr = (unsigned long) page_address(page) + offset;
+	dma_cache_wback_inv(addr, size);
+
+	return page_to_phys(page) + offset;
+}
+
+EXPORT_SYMBOL(dma_map_page);
+
+void dma_unmap_page(struct device *dev, dma_addr_t dma_address, size_t size,
+	enum dma_data_direction direction)
+{
+	BUG_ON(direction == DMA_NONE);
+
+	if (direction != DMA_TO_DEVICE) {
+		unsigned long addr;
+
+		addr = dma_address + PAGE_OFFSET;
+		dma_cache_wback_inv(addr, size);
+	}
+}
+
+EXPORT_SYMBOL(dma_unmap_page);
+
+void dma_unmap_sg(struct device *dev, struct scatterlist *sg, int nhwentries,
+	enum dma_data_direction direction)
+{
+	unsigned long addr;
+	int i;
+
+	BUG_ON(direction == DMA_NONE);
+
+	if (direction == DMA_TO_DEVICE)
+		return;
+
+	for (i = 0; i < nhwentries; i++, sg++) {
+		addr = (unsigned long) page_address(sg->page);
+		if (!addr)
+			continue;
+		dma_cache_wback_inv(addr + sg->offset, sg->length);
+	}
+}
+
+EXPORT_SYMBOL(dma_unmap_sg);
+
+void dma_sync_single(struct device *dev, dma_addr_t dma_handle, size_t size,
+	enum dma_data_direction direction)
+{
+	unsigned long addr;
+ 
+	BUG_ON(direction == DMA_NONE);
+ 
+	addr = dma_handle + PAGE_OFFSET;
+	__dma_sync(addr, size, direction);
+}
+
+EXPORT_SYMBOL(dma_sync_single);
+
+void dma_sync_single_range(struct device *dev, dma_addr_t dma_handle,
+	unsigned long offset, size_t size, enum dma_data_direction direction)
+{
+	unsigned long addr;
+
+	BUG_ON(direction == DMA_NONE);
+
+	addr = dma_handle + offset + PAGE_OFFSET;
+	__dma_sync(addr, size, direction);
+}
+
+EXPORT_SYMBOL(dma_sync_single_range);
+
+void dma_sync_sg(struct device *dev, struct scatterlist *sg, int nelems,
+	enum dma_data_direction direction)
+{
+	int i;
+ 
+	BUG_ON(direction == DMA_NONE);
+ 
+	/* Make sure that gcc doesn't leave the empty loop body.  */
+	for (i = 0; i < nelems; i++, sg++)
+		__dma_sync((unsigned long)page_address(sg->page),
+		           sg->length, direction);
+}
+
+EXPORT_SYMBOL(dma_sync_sg);
+
+int dma_supported(struct device *dev, u64 mask)
+{
+	/*
+	 * we fall back to GFP_DMA when the mask isn't all 1s,
+	 * so we can't guarantee allocations that must be
+	 * within a tighter range than GFP_DMA..
+	 */
+	if (mask < 0x00ffffff)
+		return 0;
+
+	return 1;
+}
+
+EXPORT_SYMBOL(dma_supported);
+
+int dma_is_consistent(dma_addr_t dma_addr)
+{
+	return 1;
+}
+
+EXPORT_SYMBOL(dma_is_consistent);
+
+void dma_cache_sync(void *vaddr, size_t size, enum dma_data_direction direction)
+{
+	if (direction == DMA_NONE)
+		return;
+
+	dma_cache_wback_inv((unsigned long)vaddr, size);
+}
+
+EXPORT_SYMBOL(dma_cache_sync);
+
+/* The DAC routines are a PCIism.. */
+
+#ifdef CONFIG_PCI
+
+#include <linux/pci.h>
+
+dma64_addr_t pci_dac_page_to_dma(struct pci_dev *pdev,
+	struct page *page, unsigned long offset, int direction)
+{
+	return (dma64_addr_t)page_to_phys(page) + offset;
+}
+
+EXPORT_SYMBOL(pci_dac_page_to_dma);
+
+struct page *pci_dac_dma_to_page(struct pci_dev *pdev,
+	dma64_addr_t dma_addr)
+{
+	return mem_map + (dma_addr >> PAGE_SHIFT);
+}
+
+EXPORT_SYMBOL(pci_dac_dma_to_page);
+
+unsigned long pci_dac_dma_to_offset(struct pci_dev *pdev,
+	dma64_addr_t dma_addr)
+{
+	return dma_addr & ~PAGE_MASK;
+}
+
+EXPORT_SYMBOL(pci_dac_dma_to_offset);
+
+void pci_dac_dma_sync_single(struct pci_dev *pdev,
+	dma64_addr_t dma_addr, size_t len, int direction)
+{
+	BUG_ON(direction == PCI_DMA_NONE);
+
+	dma_cache_wback_inv(dma_addr + PAGE_OFFSET, len);
+}
+
+EXPORT_SYMBOL(pci_dac_dma_sync_single);
+
+#endif /* CONFIG_PCI */
--- diff/arch/mips/mm/extable.c	1970-01-01 01:00:00.000000000 +0100
+++ source/arch/mips/mm/extable.c	2004-02-23 13:56:38.000000000 +0000
@@ -0,0 +1,21 @@
+/*
+ * linux/arch/mips/mm/extable.c
+ */
+#include <linux/module.h>
+#include <linux/spinlock.h>
+#include <asm/branch.h>
+#include <asm/uaccess.h>
+
+int fixup_exception(struct pt_regs *regs)
+{
+	const struct exception_table_entry *fixup;
+
+	fixup = search_exception_tables(exception_epc(regs));
+	if (fixup) {
+		regs->cp0_epc = fixup->nextinsn;
+
+		return 1;
+	}
+
+	return 0;
+}
--- diff/arch/mips/mm/init.c	1970-01-01 01:00:00.000000000 +0100
+++ source/arch/mips/mm/init.c	2004-02-23 13:56:38.000000000 +0000
@@ -0,0 +1,306 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 1994 - 2000 Ralf Baechle
+ * Copyright (C) 1999, 2000 Silicon Graphics, Inc.
+ * Kevin D. Kissell, kevink@mips.com and Carsten Langgaard, carstenl@mips.com
+ * Copyright (C) 2000 MIPS Technologies, Inc.  All rights reserved.
+ */
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/types.h>
+#include <linux/pagemap.h>
+#include <linux/ptrace.h>
+#include <linux/mman.h>
+#include <linux/mm.h>
+#include <linux/bootmem.h>
+#include <linux/highmem.h>
+#include <linux/swap.h>
+
+#include <asm/bootinfo.h>
+#include <asm/cachectl.h>
+#include <asm/cpu.h>
+#include <asm/dma.h>
+#include <asm/pgalloc.h>
+#include <asm/mmu_context.h>
+#include <asm/sections.h>
+#include <asm/tlb.h>
+
+DEFINE_PER_CPU(struct mmu_gather, mmu_gathers);
+
+unsigned long highstart_pfn, highend_pfn;
+
+/*
+ * We have up to 8 empty zeroed pages so we can map one of the right colour
+ * when needed.  This is necessary only on R4000 / R4400 SC and MC versions
+ * where we have to avoid VCED / VECI exceptions for good performance at
+ * any price.  Since page is never written to after the initialization we
+ * don't have to care about aliases on other CPUs.
+ */
+unsigned long empty_zero_page, zero_page_mask;
+
+/*
+ * Not static inline because used by IP27 special magic initialization code
+ */
+unsigned long setup_zero_pages(void)
+{
+	unsigned long order, size;
+	struct page *page;
+
+	if (cpu_has_vce)
+		order = 3;
+	else
+		order = 0;
+
+	empty_zero_page = __get_free_pages(GFP_KERNEL, order);
+	if (!empty_zero_page)
+		panic("Oh boy, that early out of memory?");
+
+	page = virt_to_page(empty_zero_page);
+	while (page < virt_to_page(empty_zero_page + (PAGE_SIZE << order))) {
+		set_bit(PG_reserved, &page->flags);
+		set_page_count(page, 0);
+		page++;
+	}
+
+	size = PAGE_SIZE << order;
+	zero_page_mask = (size - 1) & PAGE_MASK;
+	memset((void *)empty_zero_page, 0, size);
+
+	return 1UL << order;
+}
+
+#ifdef CONFIG_HIGHMEM
+pte_t *kmap_pte;
+pgprot_t kmap_prot;
+
+EXPORT_SYMBOL(kmap_prot);
+EXPORT_SYMBOL(kmap_pte);
+
+#define kmap_get_fixmap_pte(vaddr)					\
+	pte_offset_kernel(pmd_offset(pgd_offset_k(vaddr), (vaddr)), (vaddr))
+
+static void __init kmap_init(void)
+{
+	unsigned long kmap_vstart;
+
+	/* cache the first kmap pte */
+	kmap_vstart = __fix_to_virt(FIX_KMAP_BEGIN);
+	kmap_pte = kmap_get_fixmap_pte(kmap_vstart);
+
+	kmap_prot = PAGE_KERNEL;
+}
+
+#ifdef CONFIG_MIPS64
+static void __init fixrange_init(unsigned long start, unsigned long end,
+	pgd_t *pgd_base)
+{
+	pgd_t *pgd;
+	pmd_t *pmd;
+	pte_t *pte;
+	int i, j;
+	unsigned long vaddr;
+
+	vaddr = start;
+	i = __pgd_offset(vaddr);
+	j = __pmd_offset(vaddr);
+	pgd = pgd_base + i;
+
+	for ( ; (i < PTRS_PER_PGD) && (vaddr != end); pgd++, i++) {
+		pmd = (pmd_t *)pgd;
+		for (; (j < PTRS_PER_PMD) && (vaddr != end); pmd++, j++) {
+			if (pmd_none(*pmd)) {
+				pte = (pte_t *) alloc_bootmem_low_pages(PAGE_SIZE);
+				set_pmd(pmd, __pmd(pte));
+				if (pte != pte_offset_kernel(pmd, 0))
+					BUG();
+			}
+			vaddr += PMD_SIZE;
+		}
+		j = 0;
+	}
+}
+#endif /* CONFIG_MIPS64 */
+#endif /* CONFIG_HIGHMEM */
+
+#ifndef CONFIG_DISCONTIGMEM
+extern void pagetable_init(void);
+
+void __init paging_init(void)
+{
+	unsigned long zones_size[MAX_NR_ZONES] = {0, 0, 0};
+	unsigned long max_dma, high, low;
+
+	pagetable_init();
+
+#ifdef CONFIG_HIGHMEM
+	kmap_init();
+#endif
+
+	max_dma = virt_to_phys((char *)MAX_DMA_ADDRESS) >> PAGE_SHIFT;
+	low = max_low_pfn;
+	high = highend_pfn;
+
+#ifdef CONFIG_ISA
+	if (low < max_dma)
+		zones_size[ZONE_DMA] = low;
+	else {
+		zones_size[ZONE_DMA] = max_dma;
+		zones_size[ZONE_NORMAL] = low - max_dma;
+	}
+#else
+	zones_size[ZONE_DMA] = low;
+#endif
+#ifdef CONFIG_HIGHMEM
+	if (cpu_has_dc_aliases) {
+		printk(KERN_WARNING "This processor doesn't support highmem.");
+		if (high - low)
+			printk(" %dk highmem ignored", high - low);
+		printk("\n");
+	} else
+		zones_size[ZONE_HIGHMEM] = high - low;
+#endif
+
+	free_area_init(zones_size);
+}
+
+#define PFN_UP(x)	(((x) + PAGE_SIZE - 1) >> PAGE_SHIFT)
+#define PFN_DOWN(x)	((x) >> PAGE_SHIFT)
+
+static inline int page_is_ram(unsigned long pagenr)
+{
+	int i;
+
+	for (i = 0; i < boot_mem_map.nr_map; i++) {
+		unsigned long addr, end;
+
+		if (boot_mem_map.map[i].type != BOOT_MEM_RAM)
+			/* not usable memory */
+			continue;
+
+		addr = PFN_UP(boot_mem_map.map[i].addr);
+		end = PFN_DOWN(boot_mem_map.map[i].addr +
+			       boot_mem_map.map[i].size);
+
+		if (pagenr >= addr && pagenr < end)
+			return 1;
+	}
+
+	return 0;
+}
+
+void __init mem_init(void)
+{
+	unsigned long codesize, reservedpages, datasize, initsize;
+	unsigned long tmp, ram;
+
+#ifdef CONFIG_HIGHMEM
+	highstart_pfn = (KSEG1 - KSEG0) >> PAGE_SHIFT;
+	highmem_start_page = mem_map + highstart_pfn;
+#ifdef CONFIG_DISCONTIGMEM
+#error "CONFIG_HIGHMEM and CONFIG_DISCONTIGMEM dont work together yet"
+#endif
+	max_mapnr = num_physpages = highend_pfn;
+#else
+	max_mapnr = num_physpages = max_low_pfn;
+#endif
+	high_memory = (void *) __va(max_low_pfn << PAGE_SHIFT);
+
+	totalram_pages += free_all_bootmem();
+	totalram_pages -= setup_zero_pages();	/* Setup zeroed pages.  */
+
+	reservedpages = ram = 0;
+	for (tmp = 0; tmp < max_low_pfn; tmp++)
+		if (page_is_ram(tmp)) {
+			ram++;
+			if (PageReserved(mem_map+tmp))
+				reservedpages++;
+		}
+
+#ifdef CONFIG_HIGHMEM
+	for (tmp = highstart_pfn; tmp < highend_pfn; tmp++) {
+		struct page *page = mem_map + tmp;
+
+		if (!page_is_ram(tmp)) {
+			SetPageReserved(page);
+			continue;
+		}
+		ClearPageReserved(page);
+		set_bit(PG_highmem, &page->flags);
+		atomic_set(&page->count, 1);
+		__free_page(page);
+		totalhigh_pages++;
+	}
+	totalram_pages += totalhigh_pages;
+#endif
+
+	codesize =  (unsigned long) &_etext - (unsigned long) &_text;
+	datasize =  (unsigned long) &_edata - (unsigned long) &_etext;
+	initsize =  (unsigned long) &__init_end - (unsigned long) &__init_begin;
+
+	printk(KERN_INFO "Memory: %luk/%luk available (%ldk kernel code, "
+	       "%ldk reserved, %ldk data, %ldk init, %ldk highmem)\n",
+	       (unsigned long) nr_free_pages() << (PAGE_SHIFT-10),
+	       ram << (PAGE_SHIFT-10),
+	       codesize >> 10,
+	       reservedpages << (PAGE_SHIFT-10),
+	       datasize >> 10,
+	       initsize >> 10,
+	       (unsigned long) (totalhigh_pages << (PAGE_SHIFT-10)));
+}
+#endif /* !CONFIG_DISCONTIGMEM */
+
+#ifdef CONFIG_BLK_DEV_INITRD
+void free_initrd_mem(unsigned long start, unsigned long end)
+{
+#ifdef CONFIG_MIPS64
+	/* Switch from KSEG0 to XKPHYS addresses */
+	start = (unsigned long)phys_to_virt(CPHYSADDR(start));
+	end = (unsigned long)phys_to_virt(CPHYSADDR(end));
+#endif
+	if (start < end)
+		printk(KERN_INFO "Freeing initrd memory: %ldk freed\n",
+		       (end - start) >> 10);
+
+	for (; start < end; start += PAGE_SIZE) {
+		ClearPageReserved(virt_to_page(start));
+		set_page_count(virt_to_page(start), 1);
+		free_page(start);
+		totalram_pages++;
+	}
+}
+#endif
+
+extern unsigned long prom_free_prom_memory(void);
+
+void free_initmem(void)
+{
+	unsigned long addr, page, freed;
+
+	freed = prom_free_prom_memory();
+
+	addr = (unsigned long) &__init_begin;
+	while (addr < (unsigned long) &__init_end) {
+#ifdef CONFIG_MIPS64
+		page = PAGE_OFFSET | CPHYSADDR(addr);
+#else
+		page = addr;
+#endif
+		ClearPageReserved(virt_to_page(page));
+		set_page_count(virt_to_page(page), 1);
+		free_page(page);
+		totalram_pages++;
+		freed += PAGE_SIZE;
+		addr += PAGE_SIZE;
+	}
+	printk(KERN_INFO "Freeing unused kernel memory: %ldk freed\n",
+	       freed >> 10);
+}
--- diff/arch/mips/mm/pg-r4k.c	1970-01-01 01:00:00.000000000 +0100
+++ source/arch/mips/mm/pg-r4k.c	2004-02-23 13:56:38.000000000 +0000
@@ -0,0 +1,486 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2003, 2004 Ralf Baechle (ralf@linux-mips.org)
+ */
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/proc_fs.h>
+
+#include <asm/cacheops.h>
+#include <asm/inst.h>
+#include <asm/io.h>
+#include <asm/page.h>
+#include <asm/pgtable.h>
+#include <asm/prefetch.h>
+#include <asm/system.h>
+#include <asm/bootinfo.h>
+#include <asm/mipsregs.h>
+#include <asm/mmu_context.h>
+#include <asm/cpu.h>
+#include <asm/war.h>
+
+#define half_scache_line_size()		(cpu_scache_line_size() >> 1)
+
+/*
+ * Maximum sizes:
+ *
+ * R4000 128 bytes S-cache:		0x58 bytes
+ * R4600 v1.7:				0x5c bytes
+ * R4600 v2.0:				0x60 bytes
+ * With prefetching, 16 byte strides	0xa0 bytes
+ */
+
+static unsigned int clear_page_array[0x130 / 4];
+
+void clear_page(void * page) __attribute__((alias("clear_page_array")));
+
+EXPORT_SYMBOL(clear_page);
+
+/*
+ * Maximum sizes:
+ *
+ * R4000 128 bytes S-cache:		0x11c bytes
+ * R4600 v1.7:				0x080 bytes
+ * R4600 v2.0:				0x07c bytes
+ * With prefetching, 16 byte strides	0x0b8 bytes
+ */
+static unsigned int copy_page_array[0x148 / 4];
+
+void copy_page(void *to, void *from) __attribute__((alias("copy_page_array")));
+
+EXPORT_SYMBOL(copy_page);
+
+/*
+ * An address fits into a single register so it's safe to use 64-bit registers
+ * if we have 64-bit adresses.
+ */
+#define cpu_has_64bit_registers	cpu_has_64bit_addresses
+
+/*
+ * This is suboptimal for 32-bit kernels; we assume that R10000 is only used
+ * with 64-bit kernels.  The prefetch offsets have been experimentally tuned
+ * an Origin 200.
+ */
+static int pref_offset_clear __initdata = 512;
+static int pref_offset_copy  __initdata = 256;
+
+static unsigned int pref_src_mode __initdata;
+static unsigned int pref_dst_mode __initdata;
+
+static int load_offset __initdata;
+static int store_offset __initdata;
+
+static unsigned int __initdata *dest, *epc;
+
+static unsigned int instruction_pending;
+static union mips_instruction delayed_mi;
+
+static void __init emit_instruction(union mips_instruction mi)
+{
+	if (instruction_pending)
+		*epc++ = delayed_mi.word;
+
+	instruction_pending = 1;
+	delayed_mi = mi;
+}
+
+static inline void flush_delay_slot_or_nop(void)
+{
+	if (instruction_pending) {
+		*epc++ = delayed_mi.word;
+		instruction_pending = 0;
+		return;
+	}
+
+	*epc++ = 0;
+}
+
+static inline unsigned int *label(void)
+{
+	if (instruction_pending) {
+		*epc++ = delayed_mi.word;
+		instruction_pending = 0;
+	}
+
+	return epc;
+}
+
+static inline void build_insn_word(unsigned int word)
+{
+	union mips_instruction mi;
+
+	mi.word		 = word;
+
+	emit_instruction(mi);
+}
+
+static inline void build_nop(void)
+{
+	build_insn_word(0);			/* nop */
+}
+
+static inline void build_src_pref(int advance)
+{
+	if (!(load_offset & (cpu_dcache_line_size() - 1))) {
+		union mips_instruction mi;
+
+		mi.i_format.opcode     = pref_op;
+		mi.i_format.rs         = 5;		/* $a1 */
+		mi.i_format.rt         = pref_src_mode;
+		mi.i_format.simmediate = load_offset + advance;
+
+		emit_instruction(mi);
+	}
+}
+
+static inline void __build_load_reg(int reg)
+{
+	union mips_instruction mi;
+	unsigned int width;
+
+	if (cpu_has_64bit_registers) {
+		mi.i_format.opcode     = ld_op;
+		width = 8;
+	} else {
+		mi.i_format.opcode     = lw_op;
+		width = 4;
+	}
+	mi.i_format.rs         = 5;		/* $a1 */
+	mi.i_format.rt         = reg;		/* $reg */
+	mi.i_format.simmediate = load_offset;
+
+	load_offset += width;
+	emit_instruction(mi);
+}
+
+static inline void build_load_reg(int reg)
+{
+	if (cpu_has_prefetch)
+		build_src_pref(pref_offset_copy);
+
+	__build_load_reg(reg);
+}
+
+static inline void build_dst_pref(int advance)
+{
+	if (!(store_offset & (cpu_dcache_line_size() - 1))) {
+		union mips_instruction mi;
+
+		mi.i_format.opcode     = pref_op;
+		mi.i_format.rs         = 4;		/* $a0 */
+		mi.i_format.rt         = pref_dst_mode;
+		mi.i_format.simmediate = store_offset + advance;
+
+		emit_instruction(mi);
+	}
+}
+
+static inline void build_cdex_s(void)
+{
+	union mips_instruction mi;
+
+	if ((store_offset & (cpu_scache_line_size() - 1)))
+		return;
+
+	mi.c_format.opcode     = cache_op;
+	mi.c_format.rs         = 4;		/* $a0 */
+	mi.c_format.c_op       = 3;		/* Create Dirty Exclusive */
+	mi.c_format.cache      = 3;		/* Secondary Data Cache */
+	mi.c_format.simmediate = store_offset;
+
+	emit_instruction(mi);
+}
+
+static inline void build_cdex_p(void)
+{
+	union mips_instruction mi;
+
+	if (store_offset & (cpu_dcache_line_size() - 1))
+		return;
+
+	if (R4600_V1_HIT_CACHEOP_WAR && ((read_c0_prid() & 0xfff0) == 0x2010)) {
+		build_nop();
+		build_nop();
+		build_nop();
+		build_nop();
+	}
+
+	if (R4600_V2_HIT_CACHEOP_WAR && ((read_c0_prid() & 0xfff0) == 0x2020))
+		build_insn_word(0x8c200000);	/* lw      $zero, ($at) */
+
+	mi.c_format.opcode     = cache_op;
+	mi.c_format.rs         = 4;		/* $a0 */
+	mi.c_format.c_op       = 3;		/* Create Dirty Exclusive */
+	mi.c_format.cache      = 1;		/* Data Cache */
+	mi.c_format.simmediate = store_offset;
+
+	emit_instruction(mi);
+}
+
+static void __build_store_reg(int reg)
+{
+	union mips_instruction mi;
+	unsigned int width;
+
+	if (cpu_has_64bit_gp_regs ||
+	    (cpu_has_64bit_zero_reg && reg == 0)) {
+		mi.i_format.opcode     = sd_op;
+		width = 8;
+	} else {
+		mi.i_format.opcode     = sw_op;
+		width = 4;
+	}
+	mi.i_format.rs         = 4;		/* $a0 */
+	mi.i_format.rt         = reg;		/* $reg */
+	mi.i_format.simmediate = store_offset;
+
+	store_offset += width;
+	emit_instruction(mi);
+}
+
+static inline void build_store_reg(int reg)
+{
+	if (cpu_has_prefetch)
+		if (reg)
+			build_dst_pref(pref_offset_copy);
+		else
+			build_dst_pref(pref_offset_clear);
+	else if (cpu_has_cache_cdex_s)
+		build_cdex_s();
+	else if (cpu_has_cache_cdex_p)
+		build_cdex_p();
+
+	__build_store_reg(reg);
+}
+
+static inline void build_addiu_a2_a0(unsigned long offset)
+{
+	union mips_instruction mi;
+
+	BUG_ON(offset > 0x7fff);
+
+	mi.i_format.opcode     = cpu_has_64bit_addresses ? daddiu_op : addiu_op;
+	mi.i_format.rs         = 4;		/* $a0 */
+	mi.i_format.rt         = 6;		/* $a2 */
+	mi.i_format.simmediate = offset;
+
+	emit_instruction(mi);
+}
+
+static inline void build_addiu_a1(unsigned long offset)
+{
+	union mips_instruction mi;
+
+	BUG_ON(offset > 0x7fff);
+
+	mi.i_format.opcode     = cpu_has_64bit_addresses ? daddiu_op : addiu_op;
+	mi.i_format.rs         = 5;		/* $a1 */
+	mi.i_format.rt         = 5;		/* $a1 */
+	mi.i_format.simmediate = offset;
+
+	load_offset -= offset;
+
+	emit_instruction(mi);
+}
+
+static inline void build_addiu_a0(unsigned long offset)
+{
+	union mips_instruction mi;
+
+	BUG_ON(offset > 0x7fff);
+
+	mi.i_format.opcode     = cpu_has_64bit_addresses ? daddiu_op : addiu_op;
+	mi.i_format.rs         = 4;		/* $a0 */
+	mi.i_format.rt         = 4;		/* $a0 */
+	mi.i_format.simmediate = offset;
+
+	store_offset -= offset;
+
+	emit_instruction(mi);
+}
+
+static inline void build_bne(unsigned int *dest)
+{
+	union mips_instruction mi;
+
+	mi.i_format.opcode = bne_op;
+	mi.i_format.rs     = 6;			/* $a2 */
+	mi.i_format.rt     = 4;			/* $a0 */
+	mi.i_format.simmediate = dest - epc - 1;
+
+	*epc++ = mi.word;
+	flush_delay_slot_or_nop();
+}
+
+static inline void build_jr_ra(void)
+{
+	union mips_instruction mi;
+
+	mi.r_format.opcode = spec_op;
+	mi.r_format.rs     = 31;
+	mi.r_format.rt     = 0;
+	mi.r_format.rd     = 0;
+	mi.r_format.re     = 0;
+	mi.r_format.func   = jr_op;
+
+	*epc++ = mi.word;
+	flush_delay_slot_or_nop();
+}
+
+void __init build_clear_page(void)
+{
+	unsigned int loop_start;
+
+	epc = (unsigned int *) &clear_page_array;
+	instruction_pending = 0;
+	store_offset = 0;
+
+	if (cpu_has_prefetch) {
+		switch (current_cpu_data.cputype) {
+		case CPU_R10000:
+		case CPU_R12000:
+			pref_src_mode = Pref_LoadStreamed;
+			pref_dst_mode = Pref_StoreRetained;
+			break;
+		default:
+			pref_src_mode = Pref_LoadStreamed;
+			pref_dst_mode = Pref_PrepareForStore;
+			break;
+		}
+	}
+
+	build_addiu_a2_a0(PAGE_SIZE - (cpu_has_prefetch ? pref_offset_clear : 0));
+
+	if (R4600_V2_HIT_CACHEOP_WAR && ((read_c0_prid() & 0xfff0) == 0x2020))
+		build_insn_word(0x3c01a000);	/* lui     $at, 0xa000  */
+
+dest = label();
+	do {
+		build_store_reg(0);
+		build_store_reg(0);
+		build_store_reg(0);
+		build_store_reg(0);
+	} while (store_offset < half_scache_line_size());
+	build_addiu_a0(2 * store_offset);
+	loop_start = store_offset;
+	do {
+		build_store_reg(0);
+		build_store_reg(0);
+		build_store_reg(0);
+		build_store_reg(0);
+	} while ((store_offset - loop_start) < half_scache_line_size());
+	build_bne(dest);
+
+	if (cpu_has_prefetch && pref_offset_clear) {
+		build_addiu_a2_a0(pref_offset_clear);
+	dest = label();
+		loop_start = store_offset;
+		do {
+			__build_store_reg(0);
+			__build_store_reg(0);
+			__build_store_reg(0);
+			__build_store_reg(0);
+		} while ((store_offset - loop_start) < half_scache_line_size());
+		build_addiu_a0(2 * store_offset);
+		loop_start = store_offset;
+		do {
+			__build_store_reg(0);
+			__build_store_reg(0);
+			__build_store_reg(0);
+			__build_store_reg(0);
+		} while ((store_offset - loop_start) < half_scache_line_size());
+		build_bne(dest);
+	}
+
+	build_jr_ra();
+
+	flush_icache_range((unsigned long)&clear_page_array,
+	                   (unsigned long) epc);
+
+	BUG_ON(epc > clear_page_array + ARRAY_SIZE(clear_page_array));
+}
+
+void __init build_copy_page(void)
+{
+	unsigned int loop_start;
+
+	epc = (unsigned int *) &copy_page_array;
+	store_offset = load_offset = 0;
+	instruction_pending = 0;
+
+	build_addiu_a2_a0(PAGE_SIZE - (cpu_has_prefetch ? pref_offset_copy : 0));
+
+	if (R4600_V2_HIT_CACHEOP_WAR && ((read_c0_prid() & 0xfff0) == 0x2020))
+		build_insn_word(0x3c01a000);	/* lui     $at, 0xa000  */
+
+dest = label();
+	loop_start = store_offset;
+	do {
+		build_load_reg( 8);
+		build_load_reg( 9);
+		build_load_reg(10);
+		build_load_reg(11);
+		build_store_reg( 8);
+		build_store_reg( 9);
+		build_store_reg(10);
+		build_store_reg(11);
+	} while ((store_offset - loop_start) < half_scache_line_size());
+	build_addiu_a0(2 * store_offset);
+	build_addiu_a1(2 * load_offset);
+	loop_start = store_offset;
+	do {
+		build_load_reg( 8);
+		build_load_reg( 9);
+		build_load_reg(10);
+		build_load_reg(11);
+		build_store_reg( 8);
+		build_store_reg( 9);
+		build_store_reg(10);
+		build_store_reg(11);
+	} while ((store_offset - loop_start) < half_scache_line_size());
+	build_bne(dest);
+
+	if (cpu_has_prefetch && pref_offset_copy) {
+		build_addiu_a2_a0(pref_offset_copy);
+	dest = label();
+		loop_start = store_offset;
+		do {
+			__build_load_reg( 8);
+			__build_load_reg( 9);
+			__build_load_reg(10);
+			__build_load_reg(11);
+			__build_store_reg( 8);
+			__build_store_reg( 9);
+			__build_store_reg(10);
+			__build_store_reg(11);
+		} while ((store_offset - loop_start) < half_scache_line_size());
+		build_addiu_a0(2 * store_offset);
+		build_addiu_a1(2 * load_offset);
+		loop_start = store_offset;
+		do {
+			__build_load_reg( 8);
+			__build_load_reg( 9);
+			__build_load_reg(10);
+			__build_load_reg(11);
+			__build_store_reg( 8);
+			__build_store_reg( 9);
+			__build_store_reg(10);
+			__build_store_reg(11);
+		} while ((store_offset - loop_start) < half_scache_line_size());
+		build_bne(dest);
+	}
+
+	build_jr_ra();
+
+	flush_icache_range((unsigned long)&copy_page_array,
+	                   (unsigned long) epc);
+
+	BUG_ON(epc > copy_page_array + ARRAY_SIZE(copy_page_array));
+}
--- diff/arch/mips/momentum/jaguar_atx/Makefile	1970-01-01 01:00:00.000000000 +0100
+++ source/arch/mips/momentum/jaguar_atx/Makefile	2004-02-23 13:56:38.000000000 +0000
@@ -0,0 +1,12 @@
+#
+# Makefile for Momentum Computer's Jaguar-ATX board.
+#
+# 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).
+#
+
+obj-y	 		+= mv-irq.o int-handler.o irq.o pci-irq.o prom.o reset.o setup.o
+obj-$(CONFIG_PCI)	+= pci.o
+
+obj-$(CONFIG_REMOTE_DEBUG) += dbg_io.o
--- diff/arch/mips/momentum/jaguar_atx/dbg_io.c	1970-01-01 01:00:00.000000000 +0100
+++ source/arch/mips/momentum/jaguar_atx/dbg_io.c	2004-02-23 13:56:38.000000000 +0000
@@ -0,0 +1,126 @@
+#include <linux/config.h>
+
+#if defined(CONFIG_REMOTE_DEBUG)
+
+#include <asm/serial.h> /* For the serial port location and base baud */
+
+/* --- CONFIG --- */
+
+typedef unsigned char uint8;
+typedef unsigned int uint32;
+
+/* --- END OF CONFIG --- */
+
+#define         UART16550_BAUD_2400             2400
+#define         UART16550_BAUD_4800             4800
+#define         UART16550_BAUD_9600             9600
+#define         UART16550_BAUD_19200            19200
+#define         UART16550_BAUD_38400            38400
+#define         UART16550_BAUD_57600            57600
+#define         UART16550_BAUD_115200           115200
+
+#define         UART16550_PARITY_NONE           0
+#define         UART16550_PARITY_ODD            0x08
+#define         UART16550_PARITY_EVEN           0x18
+#define         UART16550_PARITY_MARK           0x28
+#define         UART16550_PARITY_SPACE          0x38
+
+#define         UART16550_DATA_5BIT             0x0
+#define         UART16550_DATA_6BIT             0x1
+#define         UART16550_DATA_7BIT             0x2
+#define         UART16550_DATA_8BIT             0x3
+
+#define         UART16550_STOP_1BIT             0x0
+#define         UART16550_STOP_2BIT             0x4
+
+/* ----------------------------------------------------- */
+
+/* === CONFIG === */
+
+/* [jsun] we use the second serial port for kdb */
+#define         BASE                    OCELOT_SERIAL1_BASE
+#define         MAX_BAUD                OCELOT_BASE_BAUD
+
+/* === END OF CONFIG === */
+
+#define         REG_OFFSET              4
+
+/* register offset */
+#define         OFS_RCV_BUFFER          0
+#define         OFS_TRANS_HOLD          0
+#define         OFS_SEND_BUFFER         0
+#define         OFS_INTR_ENABLE         (1*REG_OFFSET)
+#define         OFS_INTR_ID             (2*REG_OFFSET)
+#define         OFS_DATA_FORMAT         (3*REG_OFFSET)
+#define         OFS_LINE_CONTROL        (3*REG_OFFSET)
+#define         OFS_MODEM_CONTROL       (4*REG_OFFSET)
+#define         OFS_RS232_OUTPUT        (4*REG_OFFSET)
+#define         OFS_LINE_STATUS         (5*REG_OFFSET)
+#define         OFS_MODEM_STATUS        (6*REG_OFFSET)
+#define         OFS_RS232_INPUT         (6*REG_OFFSET)
+#define         OFS_SCRATCH_PAD         (7*REG_OFFSET)
+
+#define         OFS_DIVISOR_LSB         (0*REG_OFFSET)
+#define         OFS_DIVISOR_MSB         (1*REG_OFFSET)
+
+
+/* memory-mapped read/write of the port */
+#define         UART16550_READ(y)    (*((volatile uint8*)(BASE + y)))
+#define         UART16550_WRITE(y, z)  ((*((volatile uint8*)(BASE + y))) = z)
+
+void debugInit(uint32 baud, uint8 data, uint8 parity, uint8 stop)
+{
+	/* disable interrupts */
+	UART16550_WRITE(OFS_INTR_ENABLE, 0);
+
+	/* set up buad rate */
+	{
+		uint32 divisor;
+
+		/* set DIAB bit */
+		UART16550_WRITE(OFS_LINE_CONTROL, 0x80);
+
+		/* set divisor */
+		divisor = MAX_BAUD / baud;
+		UART16550_WRITE(OFS_DIVISOR_LSB, divisor & 0xff);
+		UART16550_WRITE(OFS_DIVISOR_MSB, (divisor & 0xff00) >> 8);
+
+		/* clear DIAB bit */
+		UART16550_WRITE(OFS_LINE_CONTROL, 0x0);
+	}
+
+	/* set data format */
+	UART16550_WRITE(OFS_DATA_FORMAT, data | parity | stop);
+}
+
+static int remoteDebugInitialized = 0;
+
+uint8 getDebugChar(void)
+{
+	if (!remoteDebugInitialized) {
+		remoteDebugInitialized = 1;
+		debugInit(UART16550_BAUD_38400,
+			  UART16550_DATA_8BIT,
+			  UART16550_PARITY_NONE, UART16550_STOP_1BIT);
+	}
+
+	while ((UART16550_READ(OFS_LINE_STATUS) & 0x1) == 0);
+	return UART16550_READ(OFS_RCV_BUFFER);
+}
+
+
+int putDebugChar(uint8 byte)
+{
+	if (!remoteDebugInitialized) {
+		remoteDebugInitialized = 1;
+		debugInit(UART16550_BAUD_38400,
+			  UART16550_DATA_8BIT,
+			  UART16550_PARITY_NONE, UART16550_STOP_1BIT);
+	}
+
+	while ((UART16550_READ(OFS_LINE_STATUS) & 0x20) == 0);
+	UART16550_WRITE(OFS_SEND_BUFFER, byte);
+	return 1;
+}
+
+#endif
--- diff/arch/mips/momentum/jaguar_atx/int-handler.S	1970-01-01 01:00:00.000000000 +0100
+++ source/arch/mips/momentum/jaguar_atx/int-handler.S	2004-02-23 13:56:38.000000000 +0000
@@ -0,0 +1,129 @@
+/*
+ * Copyright 2002 Momentum Computer Inc.
+ * Author: Matthew Dharm <mdharm@momenco.com>
+ *
+ * Based on work:
+ *   Copyright 2001 MontaVista Software Inc.
+ *   Author: jsun@mvista.com or jsun@junsun.net
+ *
+ * First-level interrupt dispatcher for Jaguar-ATX board.
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+#include <asm/asm.h>
+#include <asm/mipsregs.h>
+#include <asm/addrspace.h>
+#include <asm/regdef.h>
+#include <asm/stackframe.h>
+#include "jaguar_atx_fpga.h"
+
+/*
+ * First level interrupt dispatcher for Ocelot-CS board
+ */
+		.align	5
+		NESTED(jaguar_handle_int, PT_SIZE, sp)
+		SAVE_ALL
+		CLI
+		.set	at
+		mfc0	t0, CP0_CAUSE  
+		mfc0	t2, CP0_STATUS
+
+		and	t0, t2
+        
+		andi	t1, t0, STATUSF_IP0	/* sw0 software interrupt */
+		bnez	t1, ll_sw0_irq
+		andi	t1, t0, STATUSF_IP1	/* sw1 software interrupt */
+		bnez	t1, ll_sw1_irq
+		andi	t1, t0, STATUSF_IP2	/* int0 hardware line */
+		bnez	t1, ll_pcixa_irq
+		andi	t1, t0, STATUSF_IP3	/* int1 hardware line */
+		bnez	t1, ll_pcixb_irq
+		andi	t1, t0, STATUSF_IP4	/* int2 hardware line */
+		bnez	t1, ll_pcia_irq
+		andi	t1, t0, STATUSF_IP5	/* int3 hardware line */
+		bnez	t1, ll_pcib_irq
+		andi	t1, t0, STATUSF_IP6	/* int4 hardware line */
+		bnez	t1, ll_uart_irq
+		andi	t1, t0, STATUSF_IP7	/* cpu timer */
+		bnez	t1, ll_cputimer_irq
+
+		nop
+		nop
+
+		/* now look at extended interrupts */
+		mfc0	t0, CP0_CAUSE
+		cfc0	t1, CP0_S1_INTCONTROL
+
+		/* shift the mask 8 bits left to line up the bits */
+		sll	t2, t1, 8
+
+		and	t0, t2
+		srl	t0, t0, 16
+
+		andi	t1, t0, STATUSF_IP8	/* int6 hardware line */
+		bnez	t1, ll_mv64340_decode_irq
+
+		nop
+		nop
+
+		.set	reorder
+
+		/* wrong alarm or masked ... */
+		j	spurious_interrupt
+		nop
+		END(jaguar_handle_int)
+
+		.align	5
+ll_sw0_irq:
+		li	a0, 0
+		move	a1, sp
+		jal	do_IRQ
+		j	ret_from_irq
+ll_sw1_irq:
+		li	a0, 1
+		move	a1, sp
+		jal	do_IRQ
+		j	ret_from_irq
+ll_pcixa_irq:
+		li	a0, 2
+		move	a1, sp
+		jal	do_IRQ
+		j	ret_from_irq
+
+ll_pcixb_irq:
+		li	a0, 3
+		move	a1, sp
+		jal	do_IRQ
+		j	ret_from_irq
+
+ll_pcia_irq:
+		li	a0, 4
+		move	a1, sp
+		jal	do_IRQ
+		j	ret_from_irq
+	
+ll_pcib_irq:
+		li	a0, 5
+		move	a1, sp
+		jal	do_IRQ
+		j	ret_from_irq
+	
+ll_uart_irq:
+		li	a0, 6
+		move	a1, sp
+		jal	do_IRQ
+		j	ret_from_irq
+	
+ll_cputimer_irq:
+		li	a0, 7
+		move	a1, sp
+		jal	do_IRQ
+		j	ret_from_irq
+	
+ll_mv64340_decode_irq:
+		move	a0, sp
+		jal	ll_mv64340_irq
+		j	ret_from_irq
--- diff/arch/mips/momentum/jaguar_atx/irq.c	1970-01-01 01:00:00.000000000 +0100
+++ source/arch/mips/momentum/jaguar_atx/irq.c	2004-02-23 13:56:38.000000000 +0000
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2002 Momentum Computer, Inc.
+ * Author: Matthew Dharm, mdharm@momenco.com
+ *
+ * Based on work by:
+ *   Copyright (C) 2000 RidgeRun, Inc.
+ *   Author: RidgeRun, Inc.
+ *   glonnon@ridgerun.com, skranz@ridgerun.com, stevej@ridgerun.com
+ *
+ *   Copyright 2001 MontaVista Software Inc.
+ *   Author: Jun Sun, jsun@mvista.com or jsun@junsun.net
+ *
+ *   Copyright (C) 2000, 2001 Ralf Baechle (ralf@gnu.org)
+ *
+ *  This program is free software; you can redistribute  it and/or modify it
+ *  under  the terms of  the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the  License, or (at your
+ *  option) any later version.
+ *
+ *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
+ *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
+ *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
+ *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
+ *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
+ *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *  You should have received a copy of the  GNU General Public License along
+ *  with this program; if not, write  to the Free Software Foundation, Inc.,
+ *  675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <linux/config.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/types.h>
+#include <linux/interrupt.h>
+#include <linux/ioport.h>
+#include <linux/timex.h>
+#include <linux/slab.h>
+#include <asm/bootinfo.h>
+#include <asm/mipsregs.h>
+
+extern asmlinkage void jaguar_handle_int(void);
+extern void mv64340_irq_init(void);
+
+static struct irqaction cascade_mv64340 = {
+	no_action, SA_INTERRUPT, 0, "cascade via MV64340", NULL, NULL
+};
+
+static struct irqaction unused_irq = {
+	no_action, SA_INTERRUPT, 0, "unused", NULL, NULL
+};
+
+void __init init_IRQ(void)
+{
+	/*
+	 * Clear all of the interrupts while we change the able around a bit.
+	 * int-handler is not on bootstrap
+	 */
+	clear_c0_status(ST0_IM);
+
+	/* Sets the first-level interrupt dispatcher. */
+	set_except_vector(0, jaguar_handle_int);
+	init_generic_irq();
+	mips_cpu_irq_init(0);
+	rm7k_cpu_irq_init(8);
+
+	/* set up the cascading interrupts */
+	setup_irq(8, &cascade_mv64340);
+
+	/* mark unconnected IRQs as unconnected */
+	setup_irq(9, &unused_irq);
+
+	/* mark un-used IRQ numbers as unconnected */
+	setup_irq(10, &unused_irq);
+	setup_irq(13, &unused_irq);
+	setup_irq(14, &unused_irq);
+
+	mv64340_irq_init();
+
+#ifdef CONFIG_REMOTE_DEBUG
+	printk("start kgdb ...\n");
+	set_debug_traps();
+	breakpoint();	/* you may move this line to whereever you want :-) */
+#endif
+}
--- diff/arch/mips/momentum/jaguar_atx/jaguar_atx_fpga.h	1970-01-01 01:00:00.000000000 +0100
+++ source/arch/mips/momentum/jaguar_atx/jaguar_atx_fpga.h	2004-02-23 13:56:38.000000000 +0000
@@ -0,0 +1,56 @@
+/*
+ * Jaguar-ATX Board Register Definitions
+ *
+ * (C) 2002 Momentum Computer Inc.
+ *
+ *  This program is free software; you can redistribute  it and/or modify it
+ *  under  the terms of  the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the  License, or (at your
+ *  option) any later version.
+ *
+ *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
+ *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
+ *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
+ *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
+ *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
+ *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *  You should have received a copy of the  GNU General Public License along
+ *  with this program; if not, write  to the Free Software Foundation, Inc.,
+ *  675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#ifndef __JAGUAR_ATX_FPGA_H__
+#define __JAGUAR_ATX_FPGA_H__
+
+#include <linux/config.h>
+
+#ifdef CONFIG_MIPS64
+#define JAGUAR_ATX_CS0_ADDR (0xfffffffffc000000)
+#else
+#define JAGUAR_ATX_CS0_ADDR (0xfc000000)
+#endif
+
+#define JAGUAR_ATX_REG_BOARDREV		0x0
+#define JAGUAR_ATX_REG_FPGA_REV		0x1
+#define JAGUAR_ATX_REG_FPGA_TYPE	0x2
+#define JAGUAR_ATX_REG_RESET_STATUS	0x3
+#define JAGUAR_ATX_REG_BOARD_STATUS	0x4
+#define JAGUAR_ATX_REG_RESERVED1	0x5
+#define JAGUAR_ATX_REG_SET		0x6
+#define JAGUAR_ATX_REG_CLR		0x7
+#define JAGUAR_ATX_REG_EEPROM_MODE	0x9
+#define JAGUAR_ATX_REG_RESERVED2	0xa
+#define JAGUAR_ATX_REG_RESERVED3	0xb
+#define JAGUAR_ATX_REG_RESERVED4	0xc
+#define JAGUAR_ATX_REG_PHY_INTSTAT	0xd
+#define JAGUAR_ATX_REG_RESERVED5	0xe
+#define JAGUAR_ATX_REG_RESERVED6	0xf
+
+#define JAGUAR_FPGA_WRITE(x,y) writeb(x,JAGUAR_ATX_CS0_ADDR+JAGUAR_ATX_REG_##y)
+#define JAGUAR_FPGA_READ(x) readb(JAGUAR_ATX_CS0_ADDR + JAGUAR_ATX_REG_##x)
+
+#endif
--- diff/arch/mips/momentum/jaguar_atx/mv-irq.c	1970-01-01 01:00:00.000000000 +0100
+++ source/arch/mips/momentum/jaguar_atx/mv-irq.c	2004-02-23 13:56:38.000000000 +0000
@@ -0,0 +1,162 @@
+/*
+ * Copyright 2002 Momentum Computer
+ * Author: mdharm@momenco.com
+ *
+ * arch/mips/momentum/jaguar_atx/mv-irq.c
+ *     Interrupt routines for mv64340.  Interrupt numbers are assigned from
+ *     MV64340_IRQ_BASE to MV64340_IRQ_BASE + 63.
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <asm/ptrace.h>
+#include <linux/sched.h>
+#include <linux/kernel_stat.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/mv64340.h>
+
+#define MV64340_IRQ_BASE	16
+
+static inline int ls1bit32(unsigned int x)
+{
+        int b = 31, s;
+
+        s = 16; if (x << 16 == 0) s = 0; b -= s; x <<= s;
+        s =  8; if (x <<  8 == 0) s = 0; b -= s; x <<= s;
+        s =  4; if (x <<  4 == 0) s = 0; b -= s; x <<= s;
+        s =  2; if (x <<  2 == 0) s = 0; b -= s; x <<= s;
+        s =  1; if (x <<  1 == 0) s = 0; b -= s;
+
+        return b;
+}
+
+/* mask off an interrupt -- 1 is enable, 0 is disable */
+static inline void mask_mv64340_irq(unsigned int irq)
+{
+	uint32_t value;
+
+	if (irq < (MV64340_IRQ_BASE + 32)) {
+		MV_READ(MV64340_INTERRUPT0_MASK_0_LOW, &value);
+		value &= ~(1 << (irq - MV64340_IRQ_BASE));
+		MV_WRITE(MV64340_INTERRUPT0_MASK_0_LOW, value);
+	} else {
+		MV_READ(MV64340_INTERRUPT0_MASK_0_HIGH, &value);
+		value &= ~(1 << (irq - (MV64340_IRQ_BASE - 32)));
+		MV_WRITE(MV64340_INTERRUPT0_MASK_0_HIGH, value);
+	}
+}
+
+/* unmask an interrupt -- 1 is enable, 0 is disable */
+static inline void unmask_mv64340_irq(unsigned int irq)
+{
+	uint32_t value;
+
+	if (irq < (MV64340_IRQ_BASE + 32)) {
+		MV_READ(MV64340_INTERRUPT0_MASK_0_LOW, &value);
+		value |= 1 << (irq - MV64340_IRQ_BASE);
+		MV_WRITE(MV64340_INTERRUPT0_MASK_0_LOW, value);
+	} else {
+		MV_READ(MV64340_INTERRUPT0_MASK_0_HIGH, &value);
+		value |= 1 << (irq - (MV64340_IRQ_BASE - 32));
+		MV_WRITE(MV64340_INTERRUPT0_MASK_0_HIGH, value);
+	}
+}
+
+/*
+ * Enables the IRQ on Marvell Chip
+ */
+static void enable_mv64340_irq(unsigned int irq)
+{
+	unmask_mv64340_irq(irq);
+}
+
+/*
+ * Initialize the IRQ on Marvell Chip
+ */
+static unsigned int startup_mv64340_irq(unsigned int irq)
+{
+	unmask_mv64340_irq(irq);
+	return 0;
+}
+
+/*
+ * Disables the IRQ on Marvell Chip
+ */
+static void disable_mv64340_irq(unsigned int irq)
+{
+	mask_mv64340_irq(irq);
+}
+
+/*
+ * Masks and ACKs an IRQ
+ */
+static void mask_and_ack_mv64340_irq(unsigned int irq)
+{
+	mask_mv64340_irq(irq);
+}
+
+/*
+ * End IRQ processing
+ */
+static void end_mv64340_irq(unsigned int irq)
+{
+	if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
+		unmask_mv64340_irq(irq);
+}
+
+/*
+ * Interrupt handler for interrupts coming from the Marvell chip.
+ * It could be built in ethernet ports etc...
+ */
+void ll_mv64340_irq(struct pt_regs *regs)
+{
+	unsigned int irq_src_low, irq_src_high;
+ 	unsigned int irq_mask_low, irq_mask_high;
+
+	/* read the interrupt status registers */
+	MV_READ(MV64340_INTERRUPT0_MASK_0_LOW, &irq_mask_low);
+	MV_READ(MV64340_INTERRUPT0_MASK_0_HIGH, &irq_mask_high);
+	MV_READ(MV64340_MAIN_INTERRUPT_CAUSE_LOW, &irq_src_low);
+	MV_READ(MV64340_MAIN_INTERRUPT_CAUSE_HIGH, &irq_src_high);
+
+	/* mask for just the interrupts we want */
+	irq_src_low &= irq_mask_low;
+	irq_src_high &= irq_mask_high;
+
+	if (irq_src_low) 
+		do_IRQ(ls1bit32(irq_src_low) + MV64340_IRQ_BASE, regs);
+	else
+		do_IRQ(ls1bit32(irq_src_high) + MV64340_IRQ_BASE + 32, regs);
+}
+
+#define shutdown_mv64340_irq	disable_mv64340_irq
+
+struct hw_interrupt_type mv64340_irq_type = {
+	"MV-64340",
+	startup_mv64340_irq,
+	shutdown_mv64340_irq,
+	enable_mv64340_irq,
+	disable_mv64340_irq,
+	mask_and_ack_mv64340_irq,
+	end_mv64340_irq,
+	NULL
+};
+
+void mv64340_irq_init(void)
+{
+	int i;
+
+	/* Reset irq handlers pointers to NULL */
+	for (i = MV64340_IRQ_BASE; i < (MV64340_IRQ_BASE + 64); i++) {
+		irq_desc[i].status = IRQ_DISABLED;
+		irq_desc[i].action = 0;
+		irq_desc[i].depth = 2;
+		irq_desc[i].handler = &mv64340_irq_type;
+	}
+}
--- diff/arch/mips/momentum/jaguar_atx/pci-irq.c	1970-01-01 01:00:00.000000000 +0100
+++ source/arch/mips/momentum/jaguar_atx/pci-irq.c	2004-02-23 13:56:38.000000000 +0000
@@ -0,0 +1,70 @@
+/*
+ * Copyright 2002 Momentum Computer Inc.
+ * Author: Matthew Dharm <mdharm@momenco.com> 
+ *
+ * Based on work for the Linux port to the Ocelot board, which is
+ * Copyright 2001 MontaVista Software Inc.
+ * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net
+ *
+ * arch/mips/momentum/jaguar/pci.c
+ *     Board-specific PCI routines for mv64340 controller.
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <asm/pci.h>
+
+
+void __init mv64340_board_pcibios_fixup_bus(struct pci_bus *bus)
+{
+	struct pci_bus *current_bus = bus;
+	struct pci_dev *devices;
+	struct list_head *devices_link;
+	u16 cmd;
+
+	/* loop over all known devices on this bus */
+	list_for_each(devices_link, &(current_bus->devices)) {
+
+		devices = pci_dev_b(devices_link);
+		if (devices == NULL)
+			continue;
+
+		if ((current_bus->number == 0) &&
+			(PCI_SLOT(devices->devfn) == 1)) {
+			/* PCI-X A */
+			devices->irq = 3;
+		} else if ((current_bus->number == 0) &&
+			(PCI_SLOT(devices->devfn) == 2)) {
+			/* PCI-X B */
+			devices->irq = 4;
+		} else if ((current_bus->number == 1) &&
+			(PCI_SLOT(devices->devfn) == 1)) {
+			/* PCI A */
+			devices->irq = 5;
+		} else if ((current_bus->number == 1) &&
+			(PCI_SLOT(devices->devfn) == 2)) {
+			/* PCI B */
+			devices->irq = 6;
+		} else {
+			/* We don't have assign interrupts for other devices. */
+			devices->irq = 0xff;
+		}
+
+		/* Assign an interrupt number for the device */
+		bus->ops->write_byte(devices, PCI_INTERRUPT_LINE, devices->irq);
+
+		/* enable master for everything but the MV-64340 */
+		if (((current_bus->number != 0) && (current_bus->number != 1))
+				|| (PCI_SLOT(devices->devfn) != 0)) {
+			bus->ops->read_word(devices, PCI_COMMAND, &cmd);
+			cmd |= PCI_COMMAND_MASTER;
+			bus->ops->write_word(devices, PCI_COMMAND, cmd);
+		}
+	}
+}
--- diff/arch/mips/momentum/jaguar_atx/pci.c	1970-01-01 01:00:00.000000000 +0100
+++ source/arch/mips/momentum/jaguar_atx/pci.c	2004-02-23 13:56:38.000000000 +0000
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2002 Momentum Computer
+ * Author: Matthew Dharm <mdharm@momenco.com>
+ *
+ *  This program is free software; you can redistribute  it and/or modify it
+ *  under  the terms of  the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the  License, or (at your
+ *  option) any later version.
+ *
+ *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
+ *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
+ *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
+ *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
+ *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
+ *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *  You should have received a copy of the  GNU General Public License along
+ *  with this program; if not, write  to the Free Software Foundation, Inc.,
+ *  675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <asm/pci.h>
+#include <asm/io.h>
+#include <asm/mv64340.h>
+
+void mv64340_board_pcibios_fixup_bus(struct pci_bus* c);
+
+struct pci_fixup pcibios_fixups[] = {
+	{0}
+};
+
+void __init pcibios_fixup_bus(struct pci_bus *c)
+{
+	mv64340_board_pcibios_fixup_bus(c);
+}
+
+void __init pcibios_init(void)
+{
+	/* Reset PCI I/O and PCI MEM values */
+	ioport_resource.start = 0xe0000000;
+	ioport_resource.end   = 0xe0000000 + 0x20000000 - 1;
+	iomem_resource.start  = 0xc0000000;
+	iomem_resource.end    = 0xc0000000 + 0x20000000 - 1;
+
+	pci_scan_bus(0, &mv64340_bus0_pci_ops, NULL);
+	pci_scan_bus(1, &mv64340_bus1_pci_ops, NULL);
+}
--- diff/arch/mips/momentum/jaguar_atx/prom.c	1970-01-01 01:00:00.000000000 +0100
+++ source/arch/mips/momentum/jaguar_atx/prom.c	2004-02-23 13:56:38.000000000 +0000
@@ -0,0 +1,248 @@
+/*
+ * Copyright 2002 Momentum Computer Inc.
+ * Author: Matthew Dharm <mdharm@momenco.com>
+ *
+ * Louis Hamilton, Red Hat, Inc.
+ * hamilton@redhat.com  [MIPS64 modifications]
+ *
+ * Based on Ocelot Linux port, which is
+ * Copyright 2001 MontaVista Software Inc.
+ * Author: jsun@mvista.com or jsun@junsun.net
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/mm.h>
+#include <linux/sched.h>
+#include <linux/bootmem.h>
+
+#include <asm/addrspace.h>
+#include <asm/bootinfo.h>
+#include <asm/mv64340.h>
+
+#include "jaguar_atx_fpga.h"
+
+
+struct callvectors {
+	int	(*open) (char*, int, int);
+	int	(*close) (int);
+	int	(*read) (int, void*, int);
+	int	(*write) (int, void*, int);
+	off_t	(*lseek) (int, off_t, int);
+	int	(*printf) (const char*, ...);
+	void	(*cacheflush) (void);
+	char*	(*gets) (char*);
+};
+
+struct callvectors* debug_vectors;
+
+extern unsigned long mv64340_base;
+extern unsigned long cpu_clock;
+
+#ifdef CONFIG_MV64340_ETH
+extern unsigned char prom_mac_addr_base[6];
+#endif
+
+const char *get_system_type(void)
+{
+	return "Momentum Jaguar-ATX";
+}
+
+#ifdef CONFIG_MV64340_ETH
+static void burn_clocks(void)
+{
+	int i;
+
+	/* this loop should burn at least 1us -- this should be plenty */
+	for (i = 0; i < 0x10000; i++)
+		;
+}
+
+static u8 exchange_bit(u8 val, u8 cs)
+{
+	/* place the data */
+	JAGUAR_FPGA_WRITE((val << 2) | cs, EEPROM_MODE);
+	burn_clocks();
+
+	/* turn the clock on */
+	JAGUAR_FPGA_WRITE((val << 2) | cs | 0x2, EEPROM_MODE);
+	burn_clocks();
+
+	/* turn the clock off and read-strobe */
+	JAGUAR_FPGA_WRITE((val << 2) | cs | 0x10, EEPROM_MODE);
+	
+	/* return the data */
+	return ((JAGUAR_FPGA_READ(EEPROM_MODE) >> 3) & 0x1);
+}
+
+void get_mac(char dest[6])
+{
+	u8 read_opcode[12] = {1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+	int i,j;
+
+	for (i = 0; i < 12; i++)
+		exchange_bit(read_opcode[i], 1);
+
+	for (j = 0; j < 6; j++) {
+		dest[j] = 0;
+		for (i = 0; i < 8; i++) {
+			dest[j] <<= 1;
+			dest[j] |= exchange_bit(0, 1);
+		}
+	}
+
+	/* turn off CS */
+	exchange_bit(0,0);
+}
+#endif
+
+
+#ifdef CONFIG_MIPS64
+
+unsigned long signext(unsigned long addr)
+{
+  addr &= 0xffffffff;
+  return (unsigned long)((int)addr);
+}
+
+void *get_arg(unsigned long args, int arc)
+{
+  unsigned long ul;
+  unsigned char *puc, uc;
+
+  args += (arc * 4);
+  ul = (unsigned long)signext(args);
+  puc = (unsigned char *)ul;
+  if (puc == 0)
+    return (void *)0;
+
+#ifdef CONFIG_CPU_LITTLE_ENDIAN
+  uc = *puc++;
+  ul = (unsigned long)uc;
+  uc = *puc++;
+  ul |= (((unsigned long)uc) << 8);
+  uc = *puc++;
+  ul |= (((unsigned long)uc) << 16);
+  uc = *puc++;
+  ul |= (((unsigned long)uc) << 24);
+#else
+  uc = *puc++;
+  ul = ((unsigned long)uc) << 24;
+  uc = *puc++;
+  ul |= (((unsigned long)uc) << 16);
+  uc = *puc++;
+  ul |= (((unsigned long)uc) << 8);
+  uc = *puc++;
+  ul |= ((unsigned long)uc);
+#endif
+  ul = signext(ul);
+  return (void *)ul;
+}
+
+char *arg64(unsigned long addrin, int arg_index)
+{
+  unsigned long args;
+  char *p;
+  args = signext(addrin);
+  p = (char *)get_arg(args, arg_index);
+  return p;
+}
+#endif  /* CONFIG_MIPS64 */
+
+/* PMON passes arguments in C main() style */
+void __init prom_init(void)
+{
+	int argc = fw_arg0;
+	char **arg = (char **) fw_arg1;
+	char **env = (char **) fw_arg2;
+	int i;
+#ifdef CONFIG_MIPS64
+	char *ptr;
+
+	printk("Mips64 Jaguar-ATX\n");
+	/* save the PROM vectors for debugging use */
+	debug_vectors = (struct callvectors *)signext((unsigned long)cv);
+
+	/* arg[0] is "g", the rest is boot parameters */
+	arcs_cmdline[0] = '\0';
+
+	for (i = 1; i < argc; i++) {
+		ptr = (char *)arg64((unsigned long)arg, i);
+		if ((strlen(arcs_cmdline) + strlen(ptr) + 1) >=
+		    sizeof(arcs_cmdline))
+			break;
+		strcat(arcs_cmdline, ptr);
+		strcat(arcs_cmdline, " ");
+	}
+
+	i = 0;
+	while (1) {
+		ptr = (char *)arg64((unsigned long)env, i);
+		if (! ptr)
+			break;
+
+		if (strncmp("gtbase", ptr, strlen("gtbase")) == 0) {
+			mv64340_base = simple_strtol(ptr + strlen("gtbase="),
+							NULL, 16);
+
+			if ((mv64340_base & 0xffffffff00000000) == 0)
+				mv64340_base |= 0xffffffff00000000;
+
+			printk("mv64340_base set to 0x%016lx\n", mv64340_base);
+		}
+		if (strncmp("cpuclock", ptr, strlen("cpuclock")) == 0) {
+			cpu_clock = simple_strtol(ptr + strlen("cpuclock="),
+							NULL, 10);
+			printk("cpu_clock set to %d\n", cpu_clock);
+		}
+		i++;
+	}
+	printk("arcs_cmdline: %s\n", arcs_cmdline);
+
+#else   /* CONFIG_MIPS64 */
+	/* save the PROM vectors for debugging use */
+	debug_vectors = cv;
+
+	/* arg[0] is "g", the rest is boot parameters */
+	arcs_cmdline[0] = '\0';
+	for (i = 1; i < argc; i++) {
+		if (strlen(arcs_cmdline) + strlen(arg[i] + 1)
+		    >= sizeof(arcs_cmdline))
+			break;
+		strcat(arcs_cmdline, arg[i]);
+		strcat(arcs_cmdline, " ");
+	}
+
+	while (*env) {
+		if (strncmp("gtbase", *env, strlen("gtbase")) == 0) {
+			mv64340_base = simple_strtol(*env + strlen("gtbase="),
+							NULL, 16);
+		}
+		if (strncmp("cpuclock", *env, strlen("cpuclock")) == 0) {
+			cpu_clock = simple_strtol(*env + strlen("cpuclock="),
+							NULL, 10);
+		}
+		env++;
+	}
+#endif /* CONFIG_MIPS64 */
+	mips_machgroup = MACH_GROUP_MOMENCO;
+	mips_machtype = MACH_MOMENCO_JAGUAR_ATX;
+
+#ifdef CONFIG_MV64340_ETH
+	/* get the base MAC address for on-board ethernet ports */
+	get_mac(prom_mac_addr_base);
+#endif
+
+#ifndef CONFIG_MIPS64
+	debug_vectors->printf("Booting Linux kernel...\n");
+#endif
+}
+
+unsigned long __init prom_free_prom_memory(void)
+{
+	return 0;
+}
--- diff/arch/mips/momentum/jaguar_atx/reset.c	1970-01-01 01:00:00.000000000 +0100
+++ source/arch/mips/momentum/jaguar_atx/reset.c	2004-02-23 13:56:38.000000000 +0000
@@ -0,0 +1,57 @@
+/*
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ *
+ * Copyright (C) 1997, 2001 Ralf Baechle
+ * Copyright 2001 MontaVista Software Inc.
+ * Author: jsun@mvista.com or jsun@junsun.net
+ *
+ * Copyright (C) 2002 Momentum Computer Inc.
+ * Author: Matthew Dharm <mdharm@momenco.com>
+ *
+ * Louis Hamilton, Red Hat, Inc.
+ * hamilton@redhat.com  [MIPS64 modifications]
+ */
+#include <linux/config.h>
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <asm/io.h>
+#include <asm/pgtable.h>
+#include <asm/processor.h>
+#include <asm/reboot.h>
+#include <asm/system.h>
+#include <linux/delay.h>
+
+void momenco_jaguar_restart(char *command)
+{
+	/* base address of timekeeper portion of part */
+#ifdef CONFIG_MIPS64
+	void *nvram = (void*) 0xfffffffffc807000;
+#else
+	void *nvram = (void*) 0xfc807000;
+#endif
+ 	/* Ask the NVRAM/RTC/watchdog chip to assert reset in 1/16 second */
+	writeb(0x84, nvram + 0xff7);
+
+	/* wait for the watchdog to go off */
+	mdelay(100+(1000/16));
+
+	/* if the watchdog fails for some reason, let people know */
+	printk(KERN_NOTICE "Watchdog reset failed\n");
+}
+
+void momenco_jaguar_halt(void)
+{
+	printk(KERN_NOTICE "\n** You can safely turn off the power\n");
+	while (1)
+		__asm__(".set\tmips3\n\t"
+	                "wait\n\t"
+			".set\tmips0");
+}
+
+void momenco_jaguar_power_off(void)
+{
+	momenco_jaguar_halt();
+}
--- diff/arch/mips/momentum/jaguar_atx/setup.c	1970-01-01 01:00:00.000000000 +0100
+++ source/arch/mips/momentum/jaguar_atx/setup.c	2004-02-23 13:56:38.000000000 +0000
@@ -0,0 +1,360 @@
+/*
+ * setup.c
+ *
+ * BRIEF MODULE DESCRIPTION
+ * Momentum Computer Jaguar-ATX board dependent boot routines
+ *
+ * Copyright (C) 1996, 1997, 2001  Ralf Baechle
+ * Copyright (C) 2000 RidgeRun, Inc.
+ * Copyright (C) 2001 Red Hat, Inc.
+ * Copyright (C) 2002 Momentum Computer
+ *
+ * Author: Matthew Dharm, Momentum Computer
+ *   mdharm@momenco.com
+ *
+ * Louis Hamilton, Red Hat, Inc.
+ *   hamilton@redhat.com  [MIPS64 modifications]
+ *
+ * Author: RidgeRun, Inc.
+ *   glonnon@ridgerun.com, skranz@ridgerun.com, stevej@ridgerun.com
+ *
+ * Copyright 2001 MontaVista Software Inc.
+ * Author: jsun@mvista.com or jsun@junsun.net
+ *
+ *  This program is free software; you can redistribute  it and/or modify it
+ *  under  the terms of  the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the  License, or (at your
+ *  option) any later version.
+ *
+ *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
+ *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
+ *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
+ *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
+ *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
+ *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *  You should have received a copy of the  GNU General Public License along
+ *  with this program; if not, write  to the Free Software Foundation, Inc.,
+ *  675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/mm.h>
+#include <linux/swap.h>
+#include <linux/ioport.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <linux/pci.h>
+#include <linux/timex.h>
+#include <linux/vmalloc.h>
+#include <asm/time.h>
+#include <asm/bootinfo.h>
+#include <asm/page.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/pci.h>
+#include <asm/processor.h>
+#include <asm/ptrace.h>
+#include <asm/reboot.h>
+#include <linux/bootmem.h>
+#include <linux/blk.h>
+#include <asm/mv64340.h>
+#include "jaguar_atx_fpga.h"
+
+
+unsigned long mv64340_base;
+extern unsigned long mv64340_sram_base;
+unsigned long cpu_clock;
+
+/* These functions are used for rebooting or halting the machine*/
+extern void momenco_jaguar_restart(char *command);
+extern void momenco_jaguar_halt(void);
+extern void momenco_jaguar_power_off(void);
+
+void momenco_time_init(void);
+
+static char reset_reason;
+
+#define ENTRYLO(x) ((pte_val(mk_pte_phys((x), PAGE_KERNEL_UNCACHED)) >> 6)|1)
+
+void __init bus_error_init(void) { /* nothing */ }
+
+/* setup code for a handoff from a version 2 PMON 2000 PROM */
+void PMON_v2_setup(void)
+{
+	/* Some wired TLB entries for the MV64340 and perhiperals. The
+	   MV64340 is going to be hit on every IRQ anyway - there's
+	   absolutely no point in letting it be a random TLB entry, as
+	   it'll just cause needless churning of the TLB. And we use
+	   the other half for the serial port, which is just a PITA
+	   otherwise :)
+
+		Device			Physical	Virtual
+		MV64340 Internal Regs	0xf4000000	0xf4000000
+		Ocelot-C[S] PLD (CS0)	0xfc000000	0xfc000000
+		NVRAM (CS1)		0xfc800000	0xfc800000
+		UARTs (CS2)		0xfd000000	0xfd000000
+		Internal SRAM		0xfe000000	0xfe000000
+		M-Systems DOC (CS3)	0xff000000	0xff000000
+	*/
+  printk("PMON_v2_setup\n");
+
+#ifdef CONFIG_MIPS64
+	/* marvell and extra space */
+	add_wired_entry(ENTRYLO(0xf4000000), ENTRYLO(0xf4010000), 0xfffffffff4000000, PM_64K);
+	/* fpga, rtc, and uart */
+	add_wired_entry(ENTRYLO(0xfc000000), ENTRYLO(0xfd000000), 0xfffffffffc000000, PM_16M);
+	/* m-sys and internal SRAM */
+	add_wired_entry(ENTRYLO(0xfe000000), ENTRYLO(0xff000000), 0xfffffffffe000000, PM_16M);
+
+	mv64340_base = 0xfffffffff4000000;
+	mv64340_sram_base = 0xfffffffffe000000;
+#else
+	/* marvell and extra space */
+	add_wired_entry(ENTRYLO(0xf4000000), ENTRYLO(0xf4010000), 0xf4000000, PM_64K);
+	/* fpga, rtc, and uart */
+	add_wired_entry(ENTRYLO(0xfc000000), ENTRYLO(0xfd000000), 0xfc000000, PM_16M);
+	/* m-sys and internal SRAM */
+	add_wired_entry(ENTRYLO(0xfe000000), ENTRYLO(0xff000000), 0xfe000000, PM_16M);
+
+	mv64340_base = 0xf4000000;
+	mv64340_sram_base = 0xfe000000;
+#endif
+}
+
+#define CONV_BCD_TO_BIN(val)	(((val) & 0xf) + (((val) >> 4) * 10))
+#define CONV_BIN_TO_BCD(val)	(((val) % 10) + (((val) / 10) << 4))
+
+unsigned long m48t37y_get_time(void)
+{
+#ifdef CONFIG_MIPS64
+	unsigned char *rtc_base = (unsigned char*)0xfffffffffc800000;
+#else
+	unsigned char *rtc_base = (unsigned char*)0xfc800000;
+#endif
+	unsigned int year, month, day, hour, min, sec;
+
+	/* stop the update */
+	rtc_base[0x7ff8] = 0x40;
+
+	year = CONV_BCD_TO_BIN(rtc_base[0x7fff]);
+	year += CONV_BCD_TO_BIN(rtc_base[0x7ff1]) * 100;
+
+	month = CONV_BCD_TO_BIN(rtc_base[0x7ffe]);
+
+	day = CONV_BCD_TO_BIN(rtc_base[0x7ffd]);
+
+	hour = CONV_BCD_TO_BIN(rtc_base[0x7ffb]);
+	min = CONV_BCD_TO_BIN(rtc_base[0x7ffa]);
+	sec = CONV_BCD_TO_BIN(rtc_base[0x7ff9]);
+
+	/* start the update */
+	rtc_base[0x7ff8] = 0x00;
+
+	return mktime(year, month, day, hour, min, sec);
+}
+
+int m48t37y_set_time(unsigned long sec)
+{
+#ifdef CONFIG_MIPS64
+	unsigned char *rtc_base = (unsigned char*)0xfffffffffc800000;
+#else
+	unsigned char *rtc_base = (unsigned char*)0xfc800000;
+#endif
+	struct rtc_time tm;
+
+	/* convert to a more useful format -- note months count from 0 */
+	to_tm(sec, &tm);
+	tm.tm_mon += 1;
+
+	/* enable writing */
+	rtc_base[0x7ff8] = 0x80;
+
+	/* year */
+	rtc_base[0x7fff] = CONV_BIN_TO_BCD(tm.tm_year % 100);
+	rtc_base[0x7ff1] = CONV_BIN_TO_BCD(tm.tm_year / 100);
+
+	/* month */
+	rtc_base[0x7ffe] = CONV_BIN_TO_BCD(tm.tm_mon);
+
+	/* day */
+	rtc_base[0x7ffd] = CONV_BIN_TO_BCD(tm.tm_mday);
+
+	/* hour/min/sec */
+	rtc_base[0x7ffb] = CONV_BIN_TO_BCD(tm.tm_hour);
+	rtc_base[0x7ffa] = CONV_BIN_TO_BCD(tm.tm_min);
+	rtc_base[0x7ff9] = CONV_BIN_TO_BCD(tm.tm_sec);
+
+	/* day of week -- not really used, but let's keep it up-to-date */
+	rtc_base[0x7ffc] = CONV_BIN_TO_BCD(tm.tm_wday + 1);
+
+	/* disable writing */
+	rtc_base[0x7ff8] = 0x00;
+
+	return 0;
+}
+
+void momenco_timer_setup(struct irqaction *irq)
+{
+	setup_irq(8, irq);
+}
+
+void momenco_time_init(void)
+{
+	mips_hpt_frequency = cpu_clock / 2;
+	board_timer_setup = momenco_timer_setup;
+
+	rtc_get_time = m48t37y_get_time;
+	rtc_set_time = m48t37y_set_time;
+}
+
+static void __init momenco_jaguar_atx_setup(void)
+{
+	unsigned int tmpword;
+
+	board_time_init = momenco_time_init;
+
+	_machine_restart = momenco_jaguar_restart;
+	_machine_halt = momenco_jaguar_halt;
+	_machine_power_off = momenco_jaguar_power_off;
+
+	/*
+	 * initrd_start = (ulong)jaguar_initrd_start;
+	 * initrd_end = (ulong)jaguar_initrd_start + (ulong)jaguar_initrd_size;
+	 * initrd_below_start_ok = 1;
+	 */
+
+	/* do handoff reconfiguration */
+	PMON_v2_setup();
+
+	/* shut down ethernet ports, just to be sure our memory doesn't get
+	 * corrupted by random ethernet traffic.
+	 */
+	MV_WRITE(MV64340_ETH_TRANSMIT_QUEUE_COMMAND_REG(0), 0xff << 8);
+	MV_WRITE(MV64340_ETH_TRANSMIT_QUEUE_COMMAND_REG(1), 0xff << 8);
+	MV_WRITE(MV64340_ETH_TRANSMIT_QUEUE_COMMAND_REG(2), 0xff << 8);
+	MV_WRITE(MV64340_ETH_RECEIVE_QUEUE_COMMAND_REG(0), 0xff << 8);
+	MV_WRITE(MV64340_ETH_RECEIVE_QUEUE_COMMAND_REG(1), 0xff << 8);
+	MV_WRITE(MV64340_ETH_RECEIVE_QUEUE_COMMAND_REG(2), 0xff << 8);
+	do {}
+	  while (MV_READ_DATA(MV64340_ETH_RECEIVE_QUEUE_COMMAND_REG(0)) & 0xff);
+	do {}
+	  while (MV_READ_DATA(MV64340_ETH_RECEIVE_QUEUE_COMMAND_REG(1)) & 0xff);
+	do {}
+	  while (MV_READ_DATA(MV64340_ETH_RECEIVE_QUEUE_COMMAND_REG(2)) & 0xff);
+	do {}
+	  while (MV_READ_DATA(MV64340_ETH_TRANSMIT_QUEUE_COMMAND_REG(0)) & 0xff);
+	do {}
+	  while (MV_READ_DATA(MV64340_ETH_TRANSMIT_QUEUE_COMMAND_REG(1)) & 0xff);
+	do {}
+	  while (MV_READ_DATA(MV64340_ETH_TRANSMIT_QUEUE_COMMAND_REG(2)) & 0xff);
+	MV_WRITE(MV64340_ETH_PORT_SERIAL_CONTROL_REG(0), MV_READ_DATA(MV64340_ETH_PORT_SERIAL_CONTROL_REG(0)) & ~1);
+	MV_WRITE(MV64340_ETH_PORT_SERIAL_CONTROL_REG(1), MV_READ_DATA(MV64340_ETH_PORT_SERIAL_CONTROL_REG(1)) & ~1);
+	MV_WRITE(MV64340_ETH_PORT_SERIAL_CONTROL_REG(2), MV_READ_DATA(MV64340_ETH_PORT_SERIAL_CONTROL_REG(2)) & ~1);
+
+	/* Turn off the Bit-Error LED */
+	JAGUAR_FPGA_WRITE(0x80, CLR);
+
+	tmpword = JAGUAR_FPGA_READ(BOARDREV);
+	if (tmpword < 26)
+		printk("Momentum Jaguar-ATX: Board Assembly Rev. %c\n",
+			'A'+tmpword);
+	else
+		printk("Momentum Jaguar-ATX: Board Assembly Revision #0x%x\n",
+			tmpword);
+
+	tmpword = JAGUAR_FPGA_READ(FPGA_REV);
+	printk("FPGA Rev: %d.%d\n", tmpword>>4, tmpword&15);
+	tmpword = JAGUAR_FPGA_READ(RESET_STATUS);
+	printk("Reset reason: 0x%x\n", tmpword);
+	switch (tmpword) {
+		case 0x1:
+			printk("  - Power-up reset\n");
+			break;
+		case 0x2:
+			printk("  - Push-button reset\n");
+			break;
+		case 0x8:
+			printk("  - Watchdog reset\n");
+			break;
+		case 0x10:
+			printk("  - JTAG reset\n");
+			break;
+		default:
+			printk("  - Unknown reset cause\n");
+	}
+	reset_reason = tmpword;
+	JAGUAR_FPGA_WRITE(0xff, RESET_STATUS);
+
+	tmpword = JAGUAR_FPGA_READ(BOARD_STATUS);
+	printk("Board Status register: 0x%02x\n", tmpword);
+	printk("  - User jumper: %s\n", (tmpword & 0x80)?"installed":"absent");
+	printk("  - Boot flash write jumper: %s\n", (tmpword&0x40)?"installed":"absent");
+
+	/* 256MiB of RM9000x2 DDR */
+//	add_memory_region(0x0, 0x100<<20, BOOT_MEM_RAM);
+
+	/* 128MiB of MV-64340 DDR */
+//	add_memory_region(0x100<<20, 0x80<<20, BOOT_MEM_RAM);
+
+	/* XXX Memory configuration should be picked up from PMON2k */
+#ifdef CONFIG_JAGUAR_DMALOW
+	printk("Jaguar ATX DMA-low mode set\n");
+	add_memory_region(0x00000000, 0x08000000, BOOT_MEM_RAM);
+	add_memory_region(0x08000000, 0x10000000, BOOT_MEM_RAM);
+#else
+	/* 128MiB of MV-64340 DDR RAM */
+	printk("Jaguar ATX DMA-low mode is not set\n");
+	add_memory_region(0x100<<20, 0x80<<20, BOOT_MEM_RAM);
+#endif
+
+#ifdef GEMDEBUG_TRACEBUFFER
+	{
+	  unsigned int tbControl;
+	  tbControl = 
+	    0 << 26 |  /* post trigger delay 0 */
+	    	    0x2 << 16 |		/* sequential trace mode */
+	    //	    0x0 << 16 |		/* non-sequential trace mode */
+	    //	    0xf << 4 |		/* watchpoints disabled */
+	    2 << 2 |		/* armed */
+	    2 ;			/* interrupt disabled  */
+	  printk ("setting     tbControl = %08lx\n", tbControl);
+	  write_32bit_cp0_set1_register($22, tbControl);
+	  __asm__ __volatile__(".set noreorder\n\t" \
+			       "nop; nop; nop; nop; nop; nop;\n\t" \
+			       "nop; nop; nop; nop; nop; nop;\n\t" \
+			       ".set reorder\n\t");
+
+	}
+#endif
+}
+
+early_initcall(momenco_jaguar_atx_setup);
+
+
+#ifndef CONFIG_MIPS64
+/* This needs to be one of the first initcalls, because no I/O port access
+   can work before this */
+static int io_base_ioremap(void)
+{
+	/* we're mapping PCI accesses from 0xc0000000 to 0xf0000000 */
+	void *io_remap_range = ioremap(0xc0000000, 0x30000000);
+
+	printk("*** io_base_ioremap\n");
+	if (!io_remap_range) {
+		panic("Could not ioremap I/O port range");
+	}
+	printk("io_remap_range set at 0x%08x\n", (uint32_t)io_remap_range);
+	set_io_port_base(io_remap_range - 0xc0000000);
+
+	return 0;
+}
+
+module_init(io_base_ioremap);
+#endif
--- diff/arch/mips/pci/fixup-atlas.c	1970-01-01 01:00:00.000000000 +0100
+++ source/arch/mips/pci/fixup-atlas.c	2004-02-23 13:56:38.000000000 +0000
@@ -0,0 +1,72 @@
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <asm/mips-boards/atlasint.h>
+
+#define INTD		ATLASINT_INTD
+#define INTC		ATLASINT_INTC
+#define INTB		ATLASINT_INTB
+#define INTA		ATLASINT_INTA
+#define SCSI		ATLASINT_SCSI
+#define ETH		ATLASINT_ETH
+
+static char irq_tab[][5] __initdata = {
+	/*      INTA    INTB    INTC    INTD */
+	{0,	0,	0,	0,	0 },	/*  0: Unused */
+	{0,	0,	0,	0,	0 },	/*  1: Unused */
+	{0,	0,	0,	0,	0 },	/*  2: Unused */
+	{0,	0,	0,	0,	0 },	/*  3: Unused */
+	{0,	0,	0,	0,	0 },	/*  4: Unused */
+	{0,	0,	0,	0,	0 },	/*  5: Unused */
+	{0,	0,	0,	0,	0 },	/*  6: Unused */
+	{0,	0,	0,	0,	0 },	/*  7: Unused */
+	{0,	0,	0,	0,	0 },	/*  8: Unused */
+	{0,	0,	0,	0,	0 },	/*  9: Unused */
+	{0,	0,	0,	0,	0 },	/* 10: Unused */
+	{0,	0,	0,	0,	0 },	/* 11: Unused */
+	{0,	0,	0,	0,	0 },	/* 12: Unused */
+	{0,	0,	0,	0,	0 },	/* 13: Unused */
+	{0,	0,	0,	0,	0 },	/* 14: Unused */
+	{0,	0,	0,	0,	0 },	/* 15: Unused */
+	{0,	SCSI,	0,	0,	0 },	/* 16: SYM53C810A SCSI */
+	{0,	0,	0,	0,	0 },	/* 17: Core */
+	{0,	INTA,	INTB,	INTC,	INTD },	/* 18: PCI Slot 1 */
+	{0,	ETH,	0,	0,	0 },	/* 19: SAA9730 Ethernet */
+	{0,	0,	0,	0,	0 },	/* 20: PCI Slot 3 */
+	{0,	0,	0,	0,	0 }	/* 21: PCI Slot 4 */
+};
+
+int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+{
+	return irq_tab[slot][pin];
+}
+
+void __init pcibios_fixup_irqs(void)
+{
+}
+
+#if CONFIG_KGDB
+/*
+ * The PCI scan may have moved the saa9730 I/O address, so reread
+ * the address here.
+ * This does mean that it's not possible to debug the PCI bus configuration
+ * code, but it is better than nothing...
+ */
+
+static void atlas_saa9730_base_fixup (struct pci_dev *pdev)
+{
+	extern void *saa9730_base;
+	if (pdev->bus == 0 && PCI_SLOT(pdev->devfn) == 19)
+		(void) pci_read_config_dword (pdev, 0x14, (u32 *)&saa9730_base);
+	printk ("saa9730_base = %x\n", saa9730_base);
+}
+
+#endif
+
+
+struct pci_fixup pcibios_fixups[] __initdata = {
+#ifdef CONFIG_KGDB
+	{PCI_FIXUP_HEADER, PCI_VENDOR_ID_PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA9730,
+	 atlas_saa9730_base_fixup},
+#endif
+	{ 0 }
+};
--- diff/arch/mips/pci/fixup-cobalt.c	1970-01-01 01:00:00.000000000 +0100
+++ source/arch/mips/pci/fixup-cobalt.c	2004-02-23 13:56:38.000000000 +0000
@@ -0,0 +1,108 @@
+/*
+ * Cobalt Qube/Raq PCI support
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 1995, 1996, 1997, 2002, 2003 by Ralf Baechle
+ * Copyright (C) 2001, 2002, 2003 by Liam Davies (ldavies@agile.tv)
+ */
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+
+#include <asm/pci.h>
+#include <asm/io.h>
+#include <asm/gt64120.h>
+
+#include <asm/cobalt/cobalt.h>
+
+extern int cobalt_board_id;
+
+static void qube_raq_via_bmIDE_fixup(struct pci_dev *dev)
+{
+	unsigned short cfgword;
+	unsigned char lt;
+
+	/* Enable Bus Mastering and fast back to back. */
+	pci_read_config_word(dev, PCI_COMMAND, &cfgword);
+	cfgword |= (PCI_COMMAND_FAST_BACK | PCI_COMMAND_MASTER);
+	pci_write_config_word(dev, PCI_COMMAND, cfgword);
+
+	/* Enable both ide interfaces. ROM only enables primary one.  */
+	pci_write_config_byte(dev, 0x40, 0xb);
+
+	/* Set latency timer to reasonable value. */
+	pci_read_config_byte(dev, PCI_LATENCY_TIMER, &lt);
+	if (lt < 64)
+		pci_write_config_byte(dev, PCI_LATENCY_TIMER, 64);
+	pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, 7);
+}
+
+static void qube_raq_galileo_fixup(struct pci_dev *dev)
+{
+	unsigned short galileo_id;
+
+	/* Fix PCI latency-timer and cache-line-size values in Galileo
+	 * host bridge.
+	 */
+	pci_write_config_byte(dev, PCI_LATENCY_TIMER, 64);
+	pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, 7);
+
+	/*
+	 * On all machines prior to Q2, we had the STOP line disconnected
+	 * from Galileo to VIA on PCI.  The new Galileo does not function
+	 * correctly unless we have it connected.
+	 *
+	 * Therefore we must set the disconnect/retry cycle values to
+	 * something sensible when using the new Galileo.
+	 */
+	pci_read_config_word(dev, PCI_REVISION_ID, &galileo_id);
+	galileo_id &= 0xff;	/* mask off class info */
+	if (galileo_id >= 0x10) {
+		/* New Galileo, assumes PCI stop line to VIA is connected. */
+		GALILEO_OUTL(0x4020, GT_PCI0_TOR_OFS);
+	} else if (galileo_id == 0x1 || galileo_id == 0x2) {
+		signed int timeo;
+		/* XXX WE MUST DO THIS ELSE GALILEO LOCKS UP! -DaveM */
+		timeo = GALILEO_INL(GT_PCI0_TOR_OFS);
+		/* Old Galileo, assumes PCI STOP line to VIA is disconnected. */
+		GALILEO_OUTL(0xffff, GT_PCI0_TOR_OFS);
+	}
+}
+
+struct pci_fixup pcibios_fixups[] __initdata = {
+	{PCI_FIXUP_HEADER, PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_1,
+	 qube_raq_via_bmIDE_fixup},
+	{PCI_FIXUP_HEADER, PCI_VENDOR_ID_GALILEO, PCI_ANY_ID,
+	 qube_raq_galileo_fixup},
+	0
+};
+
+static char irq_tab_cobalt[] __initdata = {
+  [COBALT_PCICONF_CPU]     = 0,
+  [COBALT_PCICONF_ETH0]    = COBALT_ETH0_IRQ,
+  [COBALT_PCICONF_RAQSCSI] = COBALT_SCSI_IRQ,
+  [COBALT_PCICONF_VIA]     = 0,
+  [COBALT_PCICONF_PCISLOT] = COBALT_QUBE_SLOT_IRQ,
+  [COBALT_PCICONF_ETH1]    = COBALT_ETH1_IRQ
+};
+
+static char irq_tab_raq2[] __initdata = {
+  [COBALT_PCICONF_CPU]     = 0,
+  [COBALT_PCICONF_ETH0]    = COBALT_ETH0_IRQ,
+  [COBALT_PCICONF_RAQSCSI] = COBALT_RAQ_SCSI_IRQ,
+  [COBALT_PCICONF_VIA]     = 0,
+  [COBALT_PCICONF_PCISLOT] = COBALT_QUBE_SLOT_IRQ,
+  [COBALT_PCICONF_ETH1]    = COBALT_ETH1_IRQ
+};
+
+int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+{
+	if (cobalt_board_id == COBALT_BRD_ID_RAQ2)
+		return irq_tab_raq2[slot];
+
+	return irq_tab_cobalt[slot];
+}
--- diff/arch/mips/pci/fixup-ddb5074.c	1970-01-01 01:00:00.000000000 +0100
+++ source/arch/mips/pci/fixup-ddb5074.c	2004-02-23 13:56:38.000000000 +0000
@@ -0,0 +1,24 @@
+/*
+ * It's nice to have the LEDs on the GPIO pins available for debugging
+ */
+static void ddb5074_fixup(struct pci_dev *dev)
+{
+	extern struct pci_dev *pci_pmu;
+	u8 t8;
+                                                                
+	pci_pmu = dev;  /* for LEDs D2 and D3 */
+	/* Program the lines for LEDs D2 and D3 to output */
+	pci_read_config_byte(dev, 0x7d, &t8);
+	t8 |= 0xc0;
+	pci_write_config_byte(dev, 0x7d, t8);
+	/* Turn LEDs D2 and D3 off */
+	pci_read_config_byte(dev, 0x7e, &t8);
+	t8 |= 0xc0;
+	pci_write_config_byte(dev, 0x7e, t8);
+}
+
+struct pci_fixup pcibios_fixups[] __initdata = {
+	{ PCI_FIXUP_FINAL, PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M7101,
+	  ddb5074_fixup },
+	{0}
+};
--- diff/arch/mips/pci/fixup-ddb5477.c	1970-01-01 01:00:00.000000000 +0100
+++ source/arch/mips/pci/fixup-ddb5477.c	2004-02-23 13:56:38.000000000 +0000
@@ -0,0 +1,80 @@
+/*
+ *
+ * BRIEF MODULE DESCRIPTION
+ *	Board specific pci fixups.
+ *
+ * Copyright 2001, 2002, 2003 MontaVista Software Inc.
+ * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net
+ *
+ *  This program is free software; you can redistribute  it and/or modify it
+ *  under  the terms of  the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the  License, or (at your
+ *  option) any later version.
+ *
+ *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
+ *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
+ *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
+ *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
+ *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
+ *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *  You should have received a copy of the  GNU General Public License along
+ *  with this program; if not, write  to the Free Software Foundation, Inc.,
+ *  675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+
+static void ddb5477_fixup(struct pci_dev *dev)
+{
+	u8 old;
+
+	printk(KERN_NOTICE "Enabling ALI M1533/35 PS2 keyboard/mouse.\n");
+	pci_read_config_byte(dev, 0x41, &old);
+	pci_write_config_byte(dev, 0x41, old | 0xd0);
+}
+
+/*
+ * Fixup baseboard AMD chip so that tx does not underflow.
+ *      bcr_18 |= 0x0800
+ * This sets NOUFLO bit which makes tx not start until whole pkt
+ * is fetched to the chip.
+ */
+#define PCNET32_WIO_RDP		0x10
+#define PCNET32_WIO_RAP		0x12
+#define PCNET32_WIO_RESET	0x14
+#define PCNET32_WIO_BDP		0x16
+
+static void ddb5477_amd_lance_fixup(struct pci_dev *dev)
+{
+	unsigned long ioaddr;
+	u16 temp;
+
+	ioaddr = pci_resource_start(dev, 0);
+
+	inw(ioaddr + PCNET32_WIO_RESET);	/* reset chip */
+                                                                                
+	/* bcr_18 |= 0x0800 */
+	outw(18, ioaddr + PCNET32_WIO_RAP);
+	temp = inw(ioaddr + PCNET32_WIO_BDP);
+	temp |= 0x0800;
+	outw(18, ioaddr + PCNET32_WIO_RAP);
+	outw(temp, ioaddr + PCNET32_WIO_BDP);
+}
+
+struct pci_fixup pcibios_fixups[] __initdata = {
+	{ PCI_FIXUP_FINAL, PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1533,
+	  ddb5477_fixup },
+	{ PCI_FIXUP_FINAL, PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1535,
+	  ddb5477_fixup },
+	{ PCI_FIXUP_FINAL, PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_LANCE,
+	  ddb5477_amd_lance_fixup },
+	{0}
+};
--- diff/arch/mips/pci/fixup-ev64120.c	1970-01-01 01:00:00.000000000 +0100
+++ source/arch/mips/pci/fixup-ev64120.c	2004-02-23 13:56:38.000000000 +0000
@@ -0,0 +1,34 @@
+#include <linux/pci.h>
+#include <linux/init.h>
+
+int pci_range_ck(unsigned char bus, unsigned char dev)
+{
+	if (((bus == 0) || (bus == 1)) && (dev >= 6) && (dev <= 8))
+		return 0;
+
+	return -1;
+}
+
+/*
+ * After detecting all agents over the PCI , this function is called
+ * in order to give an interrupt number for each PCI device starting
+ * from IRQ 20. It does also enables master for each device.
+ */
+void __devinit pcibios_fixup_bus(struct pci_bus *bus)
+{
+	unsigned int irq = 20;
+	struct pci_bus *current_bus = bus;
+	struct pci_dev *dev;
+	struct list_head *devices_link;
+
+	list_for_each(devices_link, &(current_bus->devices)) {
+		dev = pci_dev_b(devices_link);
+		if (dev != NULL) {
+			dev->irq = irq++;
+
+			/* Assign an interrupt number for the device */
+			pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq);
+			pcibios_set_master(dev);
+		}
+	}
+}
--- diff/arch/mips/pci/fixup-ev96100.c	1970-01-01 01:00:00.000000000 +0100
+++ source/arch/mips/pci/fixup-ev96100.c	2004-02-23 13:56:38.000000000 +0000
@@ -0,0 +1,42 @@
+/*
+ *
+ * BRIEF MODULE DESCRIPTION
+ *	EV96100 Board specific pci fixups.
+ *
+ * Copyright 2001 MontaVista Software Inc.
+ * Author: MontaVista Software, Inc.
+ *         	ppopov@mvista.com or source@mvista.com
+ *
+ *  This program is free software; you can redistribute  it and/or modify it
+ *  under  the terms of  the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the  License, or (at your
+ *  option) any later version.
+ *
+ *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
+ *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
+ *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
+ *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
+ *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
+ *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *  You should have received a copy of the  GNU General Public License along
+ *  with this program; if not, write  to the Free Software Foundation, Inc.,
+ *  675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/pci.h>
+
+static char irq_tab_ev96100[][5] __initdata = {
+ [8] = { 0, 5, 5, 5, 5 },
+ [9] = { 0, 2, 2, 2, 2 }
+};
+
+int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+{
+	return irq_tab_ev96100[slot][pin];
+}
--- diff/arch/mips/pci/fixup-ip32.c	1970-01-01 01:00:00.000000000 +0100
+++ source/arch/mips/pci/fixup-ip32.c	2004-02-23 13:56:38.000000000 +0000
@@ -0,0 +1,50 @@
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <asm/pci_channel.h>
+#include <asm/ip32/ip32_ints.h>
+/*
+ * O2 has up to 5 PCI devices connected into the MACE bridge.  The device
+ * map looks like this:
+ *
+ * 0  aic7xxx 0
+ * 1  aic7xxx 1
+ * 2  expansion slot
+ * 3  N/C
+ * 4  N/C
+ */
+
+#define SCSI0  MACEPCI_SCSI0_IRQ
+#define SCSI1  MACEPCI_SCSI1_IRQ
+#define INTA0  MACEPCI_SLOT0_IRQ
+#define INTA1  MACEPCI_SLOT1_IRQ
+#define INTA2  MACEPCI_SLOT2_IRQ
+#define INTB   MACEPCI_SHARED0_IRQ
+#define INTC   MACEPCI_SHARED1_IRQ
+#define INTD   MACEPCI_SHARED2_IRQ
+static char irq_tab_mace[][5] __initdata = {
+      /* Dummy  INT#A  INT#B  INT#C  INT#D */
+	{0,         0,     0,     0,     0}, /* This is placeholder row - never used */
+	{0,     SCSI0, SCSI0, SCSI0, SCSI0},
+	{0,     SCSI1, SCSI1, SCSI1, SCSI1},
+	{0,     INTA0,  INTB,  INTC,  INTD},
+	{0,     INTA1,  INTC,  INTD,  INTB},
+	{0,     INTA2,  INTD,  INTB,  INTC},
+};
+
+
+/*
+ * Given a PCI slot number (a la PCI_SLOT(...)) and the interrupt pin of
+ * the device (1-4 => A-D), tell what irq to use.  Note that we don't
+ * in theory have slots 4 and 5, and we never normally use the shared
+ * irqs.  I suppose a device without a pin A will thank us for doing it
+ * right if there exists such a broken piece of crap.
+ */
+int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+{
+	return irq_tab_mace[slot][pin];
+}
+
+struct pci_fixup pcibios_fixups[] = {
+	{0}
+};
--- diff/arch/mips/pci/fixup-malta.c	1970-01-01 01:00:00.000000000 +0100
+++ source/arch/mips/pci/fixup-malta.c	2004-02-23 13:56:38.000000000 +0000
@@ -0,0 +1,105 @@
+#include <linux/init.h>
+#include <linux/pci.h>
+
+/* PCI interrupt pins */
+#define PCIA		1
+#define PCIB		2
+#define PCIC		3
+#define PCID		4
+
+/* This table is filled in by interrogating the PIIX4 chip */
+static char pci_irq[5] __initdata;
+
+static char irq_tab[][5] __initdata = {
+	/*      INTA    INTB    INTC    INTD */
+	{0,	0,	0,	0,	0 },	/*  0: GT64120 PCI bridge */
+	{0,	0,	0,	0,	0 },	/*  1: Unused */
+	{0,	0,	0,	0,	0 },	/*  2: Unused */
+	{0,	0,	0,	0,	0 },	/*  3: Unused */
+	{0,	0,	0,	0,	0 },	/*  4: Unused */
+	{0,	0,	0,	0,	0 },	/*  5: Unused */
+	{0,	0,	0,	0,	0 },	/*  6: Unused */
+	{0,	0,	0,	0,	0 },	/*  7: Unused */
+	{0,	0,	0,	0,	0 },	/*  8: Unused */
+	{0,	0,	0,	0,	0 },	/*  9: Unused */
+	{0,	0,	0,	0,	PCID },	/* 10: PIIX4 USB */
+	{0,	PCIB,	0,	0,	0 },	/* 11: AMD 79C973 Ethernet */
+	{0,	PCIC,	0,	0,	0 },	/* 12: Crystal 4281 Sound */
+	{0,	0,	0,	0,	0 },	/* 13: Unused */
+	{0,	0,	0,	0,	0 },	/* 14: Unused */
+	{0,	0,	0,	0,	0 },	/* 15: Unused */
+	{0,	0,	0,	0,	0 },	/* 16: Unused */
+	{0,	0,	0,	0,	0 },	/* 17: Bonito/SOC-it PCI Bridge*/
+	{0,	PCIA,	PCIB,	PCIC,	PCID },	/* 18: PCI Slot 1 */
+	{0,	PCIB,	PCIC,	PCID,	PCIA },	/* 19: PCI Slot 2 */
+	{0,	PCIC,	PCID,	PCIA,	PCIB },	/* 20: PCI Slot 3 */
+	{0,	PCID,	PCIA,	PCIB,	PCIC }	/* 21: PCI Slot 4 */
+};
+
+int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+{
+	int virq;
+	virq = irq_tab[slot][pin];
+	return pci_irq[virq];
+}
+
+void __init pcibios_fixup_irqs(void)
+{
+}
+
+
+static void __init malta_piix_func0_fixup(struct pci_dev *pdev)
+{
+	unsigned char reg_val;
+	static int piixirqmap[16] __initdata = {  /* PIIX PIRQC[A:D] irq mappings */
+		0,  0, 	0,  3,
+		4,  5,  6,  7,
+		0,  9, 10, 11,
+		12, 0, 14, 15 
+	};
+	int i;
+
+	/* Interrogate PIIX4 to get PCI IRQ mapping */
+	for (i = 0; i <= 3; i++) {
+		pci_read_config_byte(pdev, 0x60+i, &reg_val);
+		if (reg_val & 0x80)
+			pci_irq[PCIA+i] = 0;	/* Disabled */
+		else
+			pci_irq[PCIA+i] = piixirqmap[reg_val & 15];
+	}
+
+	/* Done by YAMON 2.00 onwards */
+	if (PCI_SLOT(pdev->devfn) == 10) {
+		/*
+		 * Set top of main memory accessible by ISA or DMA
+		 * devices to 16 Mb.
+		 */
+		pci_read_config_byte(pdev, 0x69, &reg_val);
+		pci_write_config_byte(pdev, 0x69, reg_val | 0xf0);
+	}
+}
+
+
+static void __init malta_piix_func1_fixup(struct pci_dev *pdev)
+{
+	unsigned char reg_val;
+
+	/* Done by YAMON 2.02 onwards */
+	if (PCI_SLOT(pdev->devfn) == 10) {
+		/*
+		 * IDE Decode enable.
+		 */
+		pci_read_config_byte(pdev, 0x41, &reg_val);
+		pci_write_config_byte(pdev, 0x41, reg_val|0x80);
+		pci_read_config_byte(pdev, 0x43, &reg_val);
+		pci_write_config_byte(pdev, 0x43, reg_val|0x80);
+	}
+}
+
+struct pci_fixup pcibios_fixups[] __initdata = {
+	{PCI_FIXUP_HEADER, PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB_0,
+	 malta_piix_func0_fixup},
+	{PCI_FIXUP_HEADER, PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB,
+	 malta_piix_func1_fixup},
+	{ 0 }
+};
--- diff/arch/mips/pci/fixup-rbtx4927.c	1970-01-01 01:00:00.000000000 +0100
+++ source/arch/mips/pci/fixup-rbtx4927.c	2004-02-23 13:56:38.000000000 +0000
@@ -0,0 +1,223 @@
+/*
+ *
+ * BRIEF MODULE DESCRIPTION
+ *      Board specific pci fixups for the Toshiba rbtx4927
+ *
+ * Copyright 2001 MontaVista Software Inc.
+ * Author: MontaVista Software, Inc.
+ *              ppopov@mvista.com or source@mvista.com
+ *
+ * Copyright (C) 2000-2001 Toshiba Corporation 
+ *
+ *  This program is free software; you can redistribute  it and/or modify it
+ *  under  the terms of  the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the  License, or (at your
+ *  option) any later version.
+ *
+ *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
+ *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
+ *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
+ *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
+ *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
+ *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *  You should have received a copy of the  GNU General Public License along
+ *  with this program; if not, write  to the Free Software Foundation, Inc.,
+ *  675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+
+#include <asm/tx4927/tx4927.h>
+#include <asm/tx4927/tx4927_pci.h>
+
+#undef  DEBUG
+#ifdef  DEBUG
+#define DBG(x...)       printk(x)
+#else
+#define DBG(x...)
+#endif
+
+/* look up table for backplane pci irq for slots 17-20 by pin # */
+static unsigned char backplane_pci_irq[4][4] = {
+	/* PJ6 SLOT:  17, PIN: 1 */ {TX4927_IRQ_IOC_PCIA,
+				     /* PJ6 SLOT:  17, PIN: 2 */
+				     TX4927_IRQ_IOC_PCIB,
+				     /* PJ6 SLOT:  17, PIN: 3 */
+				     TX4927_IRQ_IOC_PCIC,
+				     /* PJ6 SLOT:  17, PIN: 4 */
+				     TX4927_IRQ_IOC_PCID},
+	/* SB  SLOT:  18, PIN: 1 */ {TX4927_IRQ_IOC_PCIB,
+				     /* SB  SLOT:  18, PIN: 2 */
+				     TX4927_IRQ_IOC_PCIC,
+				     /* SB  SLOT:  18, PIN: 3 */
+				     TX4927_IRQ_IOC_PCID,
+				     /* SB  SLOT:  18, PIN: 4 */
+				     TX4927_IRQ_IOC_PCIA},
+	/* PJ5 SLOT:  19, PIN: 1 */ {TX4927_IRQ_IOC_PCIC,
+				     /* PJ5 SLOT:  19, PIN: 2 */
+				     TX4927_IRQ_IOC_PCID,
+				     /* PJ5 SLOT:  19, PIN: 3 */
+				     TX4927_IRQ_IOC_PCIA,
+				     /* PJ5 SLOT:  19, PIN: 4 */
+				     TX4927_IRQ_IOC_PCIB},
+	/* PJ4 SLOT:  20, PIN: 1 */ {TX4927_IRQ_IOC_PCID,
+				     /* PJ4 SLOT:  20, PIN: 2 */
+				     TX4927_IRQ_IOC_PCIA,
+				     /* PJ4 SLOT:  20, PIN: 3 */
+				     TX4927_IRQ_IOC_PCIB,
+				     /* PJ4 SLOT:  20, PIN: 4 */
+				     TX4927_IRQ_IOC_PCIC}
+};
+
+int pci_get_irq(struct pci_dev *dev, int pin)
+{
+	unsigned char irq = pin;
+
+	DBG("pci_get_irq: pin is %d\n", pin);
+	/* IRQ rotation */
+	irq--;			/* 0-3 */
+	if (dev->bus->parent == NULL &&
+	    PCI_SLOT(dev->devfn) == TX4927_PCIC_IDSEL_AD_TO_SLOT(23)) {
+		printk("Onboard PCI_SLOT(dev->devfn) is %d\n",
+		       PCI_SLOT(dev->devfn));
+		/* IDSEL=A23 is tx4927 onboard pci slot */
+		irq = (irq + PCI_SLOT(dev->devfn)) % 4;
+		irq++;		/* 1-4 */
+		DBG("irq is now %d\n", irq);
+
+		switch (irq) {
+		case 1:
+			irq = TX4927_IRQ_IOC_PCIA;
+			break;
+		case 2:
+			irq = TX4927_IRQ_IOC_PCIB;
+			break;
+		case 3:
+			irq = TX4927_IRQ_IOC_PCIC;
+			break;
+		case 4:
+			irq = TX4927_IRQ_IOC_PCID;
+			break;
+		}
+	} else {
+		/* PCI Backplane */
+		DBG("PCI Backplane PCI_SLOT(dev->devfn) is %d\n",
+		    PCI_SLOT(dev->devfn));
+		irq = backplane_pci_irq[PCI_SLOT(dev->devfn) - 17][irq];
+	}
+	DBG("assigned irq %d\n", irq);
+	return irq;
+}
+
+
+#ifdef  TX4927_SUPPORT_PCI_66
+extern int tx4927_pci66;
+extern void tx4927_pci66_setup(void);
+#endif
+extern void tx4927_pci_setup(void);
+
+#ifdef  TX4927_SUPPORT_PCI_66
+int tx4927_pci66_check(void)
+{
+	struct pci_dev *dev;
+	unsigned short stat;
+	int cap66 = 1;
+
+	if (tx4927_pci66 < 0)
+		return 0;
+
+	/* check 66MHz capability */
+	pci_for_each_dev(dev) {
+		if (cap66) {
+			pci_read_config_word(dev, PCI_STATUS, &stat);
+			if (!(stat & PCI_STATUS_66MHZ)) {
+				printk(KERN_INFO
+				       "PCI: %02x:%02x not 66MHz capable.\n",
+				       dev->bus->number, dev->devfn);
+				cap66 = 0;
+			}
+		}
+	}
+	return cap66;
+}
+#endif
+
+void __init pcibios_fixup_irqs(void)
+{
+	unsigned char pin;
+	unsigned char irq;
+	struct pci_dev *dev;
+	unsigned int id;
+
+#ifdef  TX4927_SUPPORT_PCI_66
+	if (tx4927_pci66_check()) {
+		tx4927_pci66_setup();
+		tx4927_pci_setup();	/* Reinitialize PCIC */
+	}
+#endif
+
+	pci_for_each_dev(dev) {
+		DBG("FIXUP:\n");
+		DBG(" devfn=0x%02x (0x%02x:0x%02x)\n",
+		    dev->devfn, PCI_SLOT(dev->devfn),
+		    PCI_FUNC(dev->devfn));
+
+		pci_read_config_dword(dev, PCI_VENDOR_ID, &id);
+		DBG(" id=0x%08x\n", id);
+
+		pci_read_config_byte(dev, PCI_INTERRUPT_LINE, &irq);
+		DBG(" line=0x%02x/%d\n", irq, irq);
+
+		pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin);
+		DBG(" pin=%d\n", pin);
+
+#ifdef DEBUG
+		{
+			unsigned int tmp;
+			pci_read_config_dword(dev, 0x10, &tmp);
+			DBG(" bar0:0x10=0x%08x\n", tmp);
+			pci_read_config_dword(dev, 0x14, &tmp);
+			DBG(" bar1:0x14=0x%08x\n", tmp);
+			pci_read_config_dword(dev, 0x1c, &tmp);
+			DBG(" bar2:0x1c=0x%08x\n", tmp);
+			pci_read_config_dword(dev, 0x20, &tmp);
+			DBG(" bar3:0x20=0x%08x\n", tmp);
+			pci_read_config_dword(dev, 0x24, &tmp);
+			DBG(" bar4:0x24=0x%08x\n", tmp);
+		}
+#endif
+
+		irq = 0;
+
+		if (id == 0x91301055) {	/* ide */
+			irq = 14;
+		}
+
+		if (pin == 0) {
+			DBG(" auto irq (now=%d) -- skipping pin=0\n", irq);
+		} else if (irq) {
+			DBG(" auto irq (now=%d) -- skipping hardcoded irq\n", irq);
+		} else {
+			DBG(" auto irq (was=%d)\n", irq);
+			irq = pci_get_irq(dev, pin);
+			pci_write_config_byte(dev, PCI_INTERRUPT_LINE,
+					      irq);
+			dev->irq = irq;
+			DBG(" auto irq (now=%d)\n", irq);
+		}
+
+		pci_read_config_byte(dev, PCI_INTERRUPT_LINE, &irq);
+		printk(KERN_INFO
+		       "PCI: 0x%02x:0x%02x(0x%02x,0x%02x) IRQ=%d\n",
+		       dev->bus->number, dev->devfn, PCI_SLOT(dev->devfn),
+		       PCI_FUNC(dev->devfn), irq);
+
+	}
+}
--- diff/arch/mips/pci/fixup-sni.c	1970-01-01 01:00:00.000000000 +0100
+++ source/arch/mips/pci/fixup-sni.c	2004-02-23 13:56:38.000000000 +0000
@@ -0,0 +1,88 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * SNI specific PCI support for RM200/RM300.
+ *
+ * Copyright (C) 1997 - 2000, 2003 Ralf Baechle
+ */
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+
+#include <asm/mipsregs.h>
+#include <asm/pci_channel.h>
+#include <asm/sni.h>
+
+/*
+ * Shortcuts ...
+ */
+#define SCSI	PCIMT_IRQ_SCSI
+#define ETH	PCIMT_IRQ_ETHERNET
+#define INTA	PCIMT_IRQ_INTA
+#define INTB	PCIMT_IRQ_INTB
+#define INTC	PCIMT_IRQ_INTC
+#define INTD	PCIMT_IRQ_INTD
+
+/*
+ * Device 0: PCI EISA Bridge	(directly routed)
+ * Device 1: NCR53c810 SCSI	(directly routed)
+ * Device 2: PCnet32 Ethernet	(directly routed)
+ * Device 3: VGA		(routed to INTB)
+ * Device 4: Unused
+ * Device 5: Slot 2
+ * Device 6: Slot 3
+ * Device 7: Slot 4	
+ *
+ * Documentation says the VGA is device 5 and device 3 is unused but that
+ * seem to be a documentation error.  At least on my RM200C the Cirrus
+ * Logic CL-GD5434 VGA is device 3.
+ */
+static char irq_tab_rm200[8][5] __initdata = {
+	/*       INTA  INTB  INTC  INTD */
+	{     0,    0,    0,    0,    0 },	/* EISA bridge */
+	{  SCSI, SCSI, SCSI, SCSI, SCSI },	/* SCSI */
+	{   ETH,  ETH,  ETH,  ETH,  ETH },	/* Ethernet */
+	{  INTB, INTB, INTB, INTB, INTB },	/* VGA */
+	{     0,    0,    0,    0,    0 },	/* Unused */
+	{     0, INTB, INTC, INTD, INTA },	/* Slot 2 */
+	{     0, INTC, INTD, INTA, INTB },	/* Slot 3 */
+	{     0, INTD, INTA, INTB, INTC },	/* Slot 4 */
+};
+
+/*
+ * In Revision D of the RM300 Device 2 has become a normal purpose Slot 1
+ *
+ * The VGA card is optional for RM300 systems.
+ */
+static char irq_tab_rm300d[8][5] __initdata = {
+	/*       INTA  INTB  INTC  INTD */
+	{     0,    0,    0,    0,    0 },	/* EISA bridge */
+	{  SCSI, SCSI, SCSI, SCSI, SCSI },	/* SCSI */
+	{     0, INTC, INTD, INTA, INTB },	/* Slot 1 */
+	{  INTB, INTB, INTB, INTB, INTB },	/* VGA */
+	{     0,    0,    0,    0,    0 },	/* Unused */
+	{     0, INTB, INTC, INTD, INTA },	/* Slot 2 */
+	{     0, INTC, INTD, INTA, INTB },	/* Slot 3 */
+	{     0, INTD, INTA, INTB, INTC },	/* Slot 4 */
+};
+
+static inline int is_rm300_revd(void)
+{
+	unsigned char csmsr = *(volatile unsigned char *)PCIMT_CSMSR;
+
+	return (csmsr & 0xa0) == 0x20;
+}
+
+int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+{
+	if (is_rm300_revd())
+		return irq_tab_rm300d[slot][pin];
+
+	return irq_tab_rm200[slot][pin];
+}
+
+struct pci_fixup pcibios_fixups[] = {
+	{0}
+};
--- diff/arch/mips/pci/fixup-yosemite.c	1970-01-01 01:00:00.000000000 +0100
+++ source/arch/mips/pci/fixup-yosemite.c	2004-02-23 13:56:38.000000000 +0000
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2003 PMC-Sierra
+ * Author: Manish Lachwani (lachwani@pmc-sierra.com)
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ *
+ *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
+ *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
+ *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
+ *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
+ *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
+ *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *  You should have received a copy of the  GNU General Public License along
+ *  with this program; if not, write  to the Free Software Foundation, Inc.,
+ *  675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+
+static char irq_tab_yosemite[8][5] __initdata = {
+	/*       INTA  INTB  INTC  INTD */
+	{    -1,   -1,   -1,   -1,   -1 },
+	{    -1,    3,    3,    3,    3 },
+	{    -1,    4,    4,    4,    4 },
+	{    -1,   -1,   -1,   -1,   -1 },
+	{    -1,   -1,   -1,   -1,   -1 },
+	{    -1,   -1,   -1,   -1,   -1 },
+	{    -1,   -1,   -1,   -1,   -1 },
+	{    -1,   -1,   -1,   -1,   -1 },
+};
+
+int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+{
+	return irq_tab_yosemite[slot][pin];
+}
+
+struct pci_fixup pcibios_fixups[] = {
+	{0}
+};
--- diff/arch/mips/pci/ops-bonito64.c	1970-01-01 01:00:00.000000000 +0100
+++ source/arch/mips/pci/ops-bonito64.c	2004-02-23 13:56:38.000000000 +0000
@@ -0,0 +1,196 @@
+/*
+ * Carsten Langgaard, carstenl@mips.com
+ * Copyright (C) 1999, 2000 MIPS Technologies, Inc.  All rights reserved.
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * MIPS boards specific PCI support.
+ */
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+
+#include <asm/mips-boards/bonito64.h>
+
+#define PCI_ACCESS_READ  0
+#define PCI_ACCESS_WRITE 1
+
+/*
+ *  PCI configuration cycle AD bus definition
+ */
+/* Type 0 */
+#define PCI_CFG_TYPE0_REG_SHF           0
+#define PCI_CFG_TYPE0_FUNC_SHF          8
+
+/* Type 1 */
+#define PCI_CFG_TYPE1_REG_SHF           0
+#define PCI_CFG_TYPE1_FUNC_SHF          8
+#define PCI_CFG_TYPE1_DEV_SHF           11
+#define PCI_CFG_TYPE1_BUS_SHF           16
+
+static int bonito64_pcibios_config_access(unsigned char access_type,
+				      struct pci_bus *bus,
+				      unsigned int devfn, int where,
+				      u32 * data)
+{
+	unsigned char busnum = bus->number;
+	u32 dummy;
+	u64 pci_addr;
+
+	/* Algorithmics Bonito64 system controller. */
+
+	if ((busnum == 0) && (PCI_SLOT(devfn) > 21)) {
+		/* We number bus 0 devices from 0..21 */
+		return -1;
+	}
+
+#ifdef CONFIG_MIPS_BOARDS_GEN
+	if ((busnum == 0) && (PCI_SLOT(devfn) == 17)) {
+		/* MIPS Core boards have Bonito connected as device 17 */
+		return -1;
+	}
+#endif
+
+	/* Clear cause register bits */
+	BONITO_PCICMD |= (BONITO_PCICMD_MABORT_CLR |
+			  BONITO_PCICMD_MTABORT_CLR);
+
+	/*
+	 * Setup pattern to be used as PCI "address" for
+	 * Type 0 cycle
+	 */
+	if (busnum == 0) {
+		/* IDSEL */
+		pci_addr = (u64) 1 << (PCI_SLOT(devfn) + 10);
+	} else {
+		/* Bus number */
+		pci_addr = busnum << PCI_CFG_TYPE1_BUS_SHF;
+
+		/* Device number */
+		pci_addr |=
+		    PCI_SLOT(devfn) << PCI_CFG_TYPE1_DEV_SHF;
+	}
+
+	/* Function (same for Type 0/1) */
+	pci_addr |= PCI_FUNC(devfn) << PCI_CFG_TYPE0_FUNC_SHF;
+
+	/* Register number (same for Type 0/1) */
+	pci_addr |= (where & ~0x3) << PCI_CFG_TYPE0_REG_SHF;
+
+	if (busnum == 0) {
+		/* Type 0 */
+		BONITO_PCIMAP_CFG = pci_addr >> 16;
+	} else {
+		/* Type 1 */
+		BONITO_PCIMAP_CFG = (pci_addr >> 16) | 0x10000;
+	}
+
+	pci_addr &= 0xffff;
+
+	/* Flush Bonito register block */
+	dummy = BONITO_PCIMAP_CFG;
+	iob();		/* sync */
+
+	/* Perform access */
+	if (access_type == PCI_ACCESS_WRITE) {
+		*(volatile u32 *) (_pcictrl_bonito_pcicfg + (u32)pci_addr) = *(u32 *) data;
+
+		/* Wait till done */
+		while (BONITO_PCIMSTAT & 0xF);
+	} else {
+		*(u32 *) data = *(volatile u32 *) (_pcictrl_bonito_pcicfg + (u32)pci_addr);
+	}
+
+	/* Detect Master/Target abort */
+	if (BONITO_PCICMD & (BONITO_PCICMD_MABORT_CLR |
+			     BONITO_PCICMD_MTABORT_CLR)) {
+		/* Error occurred */
+
+		/* Clear bits */
+		BONITO_PCICMD |= (BONITO_PCICMD_MABORT_CLR |
+				  BONITO_PCICMD_MTABORT_CLR);
+
+		return -1;
+	}
+
+	return 0;
+}
+
+
+/*
+ * We can't address 8 and 16 bit words directly.  Instead we have to
+ * read/write a 32bit word and mask/modify the data we actually want.
+ */
+static int bonito64_pcibios_read(struct pci_bus *bus, unsigned int devfn,
+			     int where, int size, u32 * val)
+{
+	u32 data = 0;
+
+	if ((size == 2) && (where & 1))
+		return PCIBIOS_BAD_REGISTER_NUMBER;
+	else if ((size == 4) && (where & 3))
+		return PCIBIOS_BAD_REGISTER_NUMBER;
+
+	if (bonito64_pcibios_config_access(PCI_ACCESS_READ, bus, devfn, where,
+				       &data))
+		return -1;
+
+	if (size == 1)
+		*val = (data >> ((where & 3) << 3)) & 0xff;
+	else if (size == 2)
+		*val = (data >> ((where & 3) << 3)) & 0xffff;
+	else
+		*val = data;
+
+	return PCIBIOS_SUCCESSFUL;
+}
+
+static int bonito64_pcibios_write(struct pci_bus *bus, unsigned int devfn,
+			      int where, int size, u32 val)
+{
+	u32 data = 0;
+
+	if ((size == 2) && (where & 1))
+		return PCIBIOS_BAD_REGISTER_NUMBER;
+	else if ((size == 4) && (where & 3))
+		return PCIBIOS_BAD_REGISTER_NUMBER;
+
+	if (size == 4)
+		data = val;
+	else {
+		if (bonito64_pcibios_config_access(PCI_ACCESS_READ, bus, devfn,
+		                               where, &data))
+			return -1;
+
+		if (size == 1)
+			data = (data & ~(0xff << ((where & 3) << 3))) |
+				(val << ((where & 3) << 3));
+		else if (size == 2)
+			data = (data & ~(0xffff << ((where & 3) << 3))) |
+				(val << ((where & 3) << 3));
+	}
+
+	if (bonito64_pcibios_config_access(PCI_ACCESS_WRITE, bus, devfn, where,
+				       &data))
+		return -1;
+
+	return PCIBIOS_SUCCESSFUL;
+}
+
+struct pci_ops bonito64_pci_ops = {
+	.read = bonito64_pcibios_read,
+	.write = bonito64_pcibios_write
+};
--- diff/arch/mips/pci/ops-gt64111.c	1970-01-01 01:00:00.000000000 +0100
+++ source/arch/mips/pci/ops-gt64111.c	2004-02-23 13:56:38.000000000 +0000
@@ -0,0 +1,100 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 1995, 1996, 1997, 2002 by Ralf Baechle
+ * Copyright (C) 2001, 2002, 2003 by Liam Davies (ldavies@agile.tv)
+ */
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+
+#include <asm/pci.h>
+#include <asm/io.h>
+#include <asm/gt64120.h>
+
+#include <asm/cobalt/cobalt.h>
+
+/*
+ * Accessing device 31 hangs the GT64120.  Not sure if this will also hang
+ * the GT64111, let's be paranoid for now.
+ */
+static inline int pci_range_ck(struct pci_bus *bus, unsigned int devfn)
+{
+	if (bus->number == 0 && devfn == PCI_DEVFN(31, 0))
+		return -1;
+
+	return 0;
+}
+
+static int gt64111_pci_read_config(struct pci_bus *bus, unsigned int devfn,
+	int where, int size, u32 * val)
+{
+	if (pci_range_ck(bus, devfn))
+		return PCIBIOS_DEVICE_NOT_FOUND;
+
+	switch (size) {
+	case 4:
+		PCI_CFG_SET(devfn, where);
+		*val = GALILEO_INL(GT_PCI0_CFGDATA_OFS);
+		return PCIBIOS_SUCCESSFUL;
+
+	case 2:
+		PCI_CFG_SET(devfn, (where & ~0x3));
+		*val = GALILEO_INL(GT_PCI0_CFGDATA_OFS)
+		    >> ((where & 3) * 8);
+		return PCIBIOS_SUCCESSFUL;
+
+	case 1:
+		PCI_CFG_SET(devfn, (where & ~0x3));
+		*val = GALILEO_INL(GT_PCI0_CFGDATA_OFS)
+		    >> ((where & 3) * 8);
+		return PCIBIOS_SUCCESSFUL;
+	}
+
+	return PCIBIOS_BAD_REGISTER_NUMBER;
+}
+
+static int gt64111_pci_write_config(struct pci_bus *bus, unsigned int devfn,
+	int where, int size, u32 val)
+{
+	u32 tmp;
+
+	if (pci_range_ck(bus, devfn))
+		return PCIBIOS_DEVICE_NOT_FOUND;
+
+	switch (size) {
+	case 4:
+		PCI_CFG_SET(devfn, where);
+		GALILEO_OUTL(val, GT_PCI0_CFGDATA_OFS);
+
+		return PCIBIOS_SUCCESSFUL;
+
+	case 2:
+		PCI_CFG_SET(devfn, (where & ~0x3));
+		tmp = GALILEO_INL(GT_PCI0_CFGDATA_OFS);
+		tmp &= ~(0xffff << ((where & 0x3) * 8));
+		tmp |= (val << ((where & 0x3) * 8));
+		GALILEO_OUTL(tmp, GT_PCI0_CFGDATA_OFS);
+
+		return PCIBIOS_SUCCESSFUL;
+
+	case 1:
+		PCI_CFG_SET(devfn, (where & ~0x3));
+		tmp = GALILEO_INL(GT_PCI0_CFGDATA_OFS);
+		tmp &= ~(0xff << ((where & 0x3) * 8));
+		tmp |= (val << ((where & 0x3) * 8));
+		GALILEO_OUTL(tmp, GT_PCI0_CFGDATA_OFS);
+
+		return PCIBIOS_SUCCESSFUL;
+	}
+
+	return PCIBIOS_BAD_REGISTER_NUMBER;
+}
+
+struct pci_ops gt64111_pci_ops = {
+	.read = gt64111_pci_read_config,
+	.write = gt64111_pci_write_config,
+};
--- diff/arch/mips/pci/ops-gt64120.c	1970-01-01 01:00:00.000000000 +0100
+++ source/arch/mips/pci/ops-gt64120.c	2004-02-23 13:56:38.000000000 +0000
@@ -0,0 +1,154 @@
+/*
+ * Carsten Langgaard, carstenl@mips.com
+ * Copyright (C) 1999, 2000 MIPS Technologies, Inc.  All rights reserved.
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ */
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <linux/kernel.h>
+
+#include <asm/gt64120.h>
+
+#define PCI_ACCESS_READ  0
+#define PCI_ACCESS_WRITE 1
+
+/*
+ *  PCI configuration cycle AD bus definition
+ */
+/* Type 0 */
+#define PCI_CFG_TYPE0_REG_SHF           0
+#define PCI_CFG_TYPE0_FUNC_SHF          8
+
+/* Type 1 */
+#define PCI_CFG_TYPE1_REG_SHF           0
+#define PCI_CFG_TYPE1_FUNC_SHF          8
+#define PCI_CFG_TYPE1_DEV_SHF           11
+#define PCI_CFG_TYPE1_BUS_SHF           16
+
+static int gt64120_pcibios_config_access(unsigned char access_type,
+	struct pci_bus *bus, unsigned int devfn, int where, u32 * data)
+{
+	unsigned char busnum = bus->number;
+	u32 intr;
+
+	if ((busnum == 0) && (PCI_SLOT(devfn) == 0))
+		/* Galileo itself is devfn 0, don't move it around */
+		return -1;
+
+	if ((busnum == 0) && (devfn >= PCI_DEVFN(31, 0)))
+		return -1;	/* Because of a bug in the galileo (for slot 31). */
+
+	/* Clear cause register bits */
+	GT_WRITE(GT_INTRCAUSE_OFS, ~(GT_INTRCAUSE_MASABORT0_BIT |
+	                             GT_INTRCAUSE_TARABORT0_BIT));
+
+	/* Setup address */
+	GT_WRITE(GT_PCI0_CFGADDR_OFS,
+		 (busnum << GT_PCI0_CFGADDR_BUSNUM_SHF) |
+		 (devfn << GT_PCI0_CFGADDR_FUNCTNUM_SHF) |
+		 ((where / 4) << GT_PCI0_CFGADDR_REGNUM_SHF) |
+		 GT_PCI0_CFGADDR_CONFIGEN_BIT);
+
+	if (access_type == PCI_ACCESS_WRITE) {
+		if (busnum == 0 && PCI_SLOT(devfn) == 0) {
+			/*
+			 * The Galileo system controller is acting
+			 * differently than other devices.
+			 */
+			GT_WRITE(GT_PCI0_CFGDATA_OFS, *data);
+		} else
+			__GT_WRITE(GT_PCI0_CFGDATA_OFS, *data);
+	} else {
+		if (busnum == 0 && PCI_SLOT(devfn) == 0) {
+			/*
+			 * The Galileo system controller is acting
+			 * differently than other devices.
+			 */
+			*data = GT_READ(GT_PCI0_CFGDATA_OFS);
+		} else
+			*data = __GT_READ(GT_PCI0_CFGDATA_OFS);
+	}
+
+	/* Check for master or target abort */
+	intr = GT_READ(GT_INTRCAUSE_OFS);
+
+	if (intr & (GT_INTRCAUSE_MASABORT0_BIT | GT_INTRCAUSE_TARABORT0_BIT)) {
+		/* Error occurred */
+
+		/* Clear bits */
+		GT_WRITE(GT_INTRCAUSE_OFS, ~(GT_INTRCAUSE_MASABORT0_BIT |
+		                             GT_INTRCAUSE_TARABORT0_BIT));
+
+		return -1;
+	}
+
+	return 0;
+}
+
+
+/*
+ * We can't address 8 and 16 bit words directly.  Instead we have to
+ * read/write a 32bit word and mask/modify the data we actually want.
+ */
+static int gt64120_pcibios_read(struct pci_bus *bus, unsigned int devfn,
+                                int where, int size, u32 * val)
+{
+	u32 data = 0;
+
+	if (gt64120_pcibios_config_access(PCI_ACCESS_READ, bus, devfn, where,
+				          &data))
+		return PCIBIOS_DEVICE_NOT_FOUND;
+
+	if (size == 1)
+		*val = (data >> ((where & 3) << 3)) & 0xff;
+	else if (size == 2)
+		*val = (data >> ((where & 3) << 3)) & 0xffff;
+	else
+		*val = data;
+
+	return PCIBIOS_SUCCESSFUL;
+}
+
+static int gt64120_pcibios_write(struct pci_bus *bus, unsigned int devfn,
+			      int where, int size, u32 val)
+{
+	u32 data = 0;
+
+	if (size == 4)
+		data = val;
+	else {
+		if (gt64120_pcibios_config_access(PCI_ACCESS_READ, bus, devfn,
+		                                  where, &data))
+			return PCIBIOS_DEVICE_NOT_FOUND;
+
+		if (size == 1)
+			data = (data & ~(0xff << ((where & 3) << 3))) |
+				(val << ((where & 3) << 3));
+		else if (size == 2)
+			data = (data & ~(0xffff << ((where & 3) << 3))) |
+				(val << ((where & 3) << 3));
+	}
+
+	if (gt64120_pcibios_config_access(PCI_ACCESS_WRITE, bus, devfn, where,
+				       &data))
+		return PCIBIOS_DEVICE_NOT_FOUND;
+
+	return PCIBIOS_SUCCESSFUL;
+}
+
+struct pci_ops gt64120_pci_ops = {
+	.read = gt64120_pcibios_read,
+	.write = gt64120_pcibios_write
+};
--- diff/arch/mips/pci/ops-gt96100.c	1970-01-01 01:00:00.000000000 +0100
+++ source/arch/mips/pci/ops-gt96100.c	2004-02-23 13:56:38.000000000 +0000
@@ -0,0 +1,169 @@
+/*
+ *
+ * BRIEF MODULE DESCRIPTION
+ *	Galileo EV96100 board specific pci support.
+ *
+ * Copyright 2000 MontaVista Software Inc.
+ * Author: MontaVista Software, Inc.
+ *         	ppopov@mvista.com or source@mvista.com
+ *
+ * This file was derived from Carsten Langgaard's
+ * arch/mips/mips-boards/generic/pci.c
+ *
+ * Carsten Langgaard, carstenl@mips.com
+ * Copyright (C) 1999,2000 MIPS Technologies, Inc.  All rights reserved.
+ *
+ *  This program is free software; you can redistribute  it and/or modify it
+ *  under  the terms of  the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the  License, or (at your
+ *  option) any later version.
+ *
+ *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
+ *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
+ *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
+ *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
+ *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
+ *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *  You should have received a copy of the  GNU General Public License along
+ *  with this program; if not, write  to the Free Software Foundation, Inc.,
+ *  675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+
+#include <asm/delay.h>
+#include <asm/gt64120.h>
+#include <asm/galileo-boards/ev96100.h>
+
+#define PCI_ACCESS_READ  0
+#define PCI_ACCESS_WRITE 1
+
+static int static gt96100_config_access(unsigned char access_type,
+	struct pci_bus *bus, unsigned int devfn, int where, u32 * data)
+{
+	unsigned char bus = bus->number;
+	u32 intr;
+
+	/*
+	 * Because of a bug in the galileo (for slot 31).
+	 */
+	if (bus == 0 && devfn >= PCI_DEVFN(31, 0))
+		return PCIBIOS_DEVICE_NOT_FOUND;
+
+	/* Clear cause register bits */
+	GT_WRITE(GT_INTRCAUSE_OFS, ~(GT_INTRCAUSE_MASABORT0_BIT |
+				     GT_INTRCAUSE_TARABORT0_BIT));
+
+	/* Setup address */
+	GT_WRITE(GT_PCI0_CFGADDR_OFS,
+		 (bus << GT_PCI0_CFGADDR_BUSNUM_SHF) |
+		 (devfn << GT_PCI0_CFGADDR_FUNCTNUM_SHF) |
+		 ((where / 4) << GT_PCI0_CFGADDR_REGNUM_SHF) |
+		 GT_PCI0_CFGADDR_CONFIGEN_BIT);
+	udelay(2);
+
+
+	if (access_type == PCI_ACCESS_WRITE) {
+		if (devfn != 0)
+			*data = le32_to_cpu(*data);
+		GT_WRITE(GT_PCI0_CFGDATA_OFS, *data);
+	} else {
+		*data = GT_READ(GT_PCI0_CFGDATA_OFS);
+		if (devfn != 0)
+			*data = le32_to_cpu(*data);
+	}
+
+	udelay(2);
+
+	/* Check for master or target abort */
+	intr = GT_READ(GT_INTRCAUSE_OFS);
+
+	if (intr & (GT_INTRCAUSE_MASABORT0_BIT | GT_INTRCAUSE_TARABORT0_BIT)) {
+		/* Error occured */
+
+		/* Clear bits */
+		GT_WRITE(GT_INTRCAUSE_OFS, ~(GT_INTRCAUSE_MASABORT0_BIT |
+					     GT_INTRCAUSE_TARABORT0_BIT));
+		return -1;
+	}
+	return 0;
+}
+
+/*
+ * We can't address 8 and 16 bit words directly.  Instead we have to
+ * read/write a 32bit word and mask/modify the data we actually want.
+ */
+static int gt96100_pcibios_read(struct pci_bus *bus, unsigned int devfn,
+	int where, int size, u32 * val)
+{
+	u32 data = 0;
+
+	if (gt96100_config_access(PCI_ACCESS_READ, bus, devfn, where, &data))
+		return PCIBIOS_DEVICE_NOT_FOUND;
+
+	switch (size) {
+	case 1:
+		*val = (data >> ((where & 3) << 3)) & 0xff;
+		break;
+
+	case 2:
+		*val = (data >> ((where & 3) << 3)) & 0xffff;
+		break;
+
+	case 4:
+		*val = data;
+		break;
+	}
+	return PCIBIOS_SUCCESSFUL;
+}
+
+static int gt96100_pcibios_write(struct pci_bus *bus, unsigned int devfn,
+	int where, int size, u32 val)
+{
+	u32 data = 0;
+
+	switch (size) {
+	case 1:
+		if (gt96100_config_access(PCI_ACCESS_READ, bus, devfn, where, &data))
+			return -1;
+
+		data = (data & ~(0xff << ((where & 3) << 3))) |
+		       (val << ((where & 3) << 3));
+
+		if (gt96100_config_access(PCI_ACCESS_WRITE, bus, devfn, where, &data))
+			return -1;
+
+		return PCIBIOS_SUCCESSFUL;
+
+	case 2:
+		if (gt96100_config_access(PCI_ACCESS_READ, bus, devfn, where, &data))
+			return -1;
+
+		data = (data & ~(0xffff << ((where & 3) << 3))) |
+		       (val << ((where & 3) << 3));
+
+		if (gt96100_config_access(PCI_ACCESS_WRITE, dev, where, &data))
+			return -1;
+
+
+		return PCIBIOS_SUCCESSFUL;
+
+	case 4:
+		if (gt96100_config_access(PCI_ACCESS_WRITE, dev, where, &val))
+			return -1;
+
+		return PCIBIOS_SUCCESSFUL;
+	}
+}
+
+struct pci_ops gt96100_pci_ops = {
+	.read	= gt96100_pcibios_read,
+	.write	= gt96100_pcibios_write
+};
--- diff/arch/mips/pci/ops-mace.c	1970-01-01 01:00:00.000000000 +0100
+++ source/arch/mips/pci/ops-mace.c	2004-02-23 13:56:38.000000000 +0000
@@ -0,0 +1,91 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2000, 2001 Keith M Wesolowski
+ */
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/types.h>
+#include <asm/pci.h>
+#include <asm/ip32/mace.h>
+
+#if 0
+# define DPRINTK(args...) printk(args);
+#else
+# define DPRINTK(args...)
+#endif
+
+/*
+ * O2 has up to 5 PCI devices connected into the MACE bridge.  The device
+ * map looks like this:
+ *
+ * 0  aic7xxx 0
+ * 1  aic7xxx 1
+ * 2  expansion slot
+ * 3  N/C
+ * 4  N/C
+ */
+
+#define chkslot(_bus,_devfn)					\
+do {							        \
+	if ((_bus)->number > 0 || PCI_SLOT (_devfn) < 1	\
+	    || PCI_SLOT (_devfn) > 3)			        \
+		return PCIBIOS_DEVICE_NOT_FOUND;		\
+} while (0)
+
+#define mkaddr(_devfn, _reg) \
+((((_devfn) & 0xffUL) << 8) | ((_reg) & 0xfcUL))
+
+static int
+mace_pci_read_config(struct pci_bus *bus, unsigned int devfn,
+		     int reg, int size, u32 *val)
+{
+	chkslot(bus, devfn);
+	mace->pci.config_addr = mkaddr(devfn, reg);
+	switch (size) {
+	case 1:
+		*val = mace->pci.config_data.b[(reg & 3) ^ 3];
+		break;
+	case 2:
+		*val = mace->pci.config_data.w[((reg >> 1) & 1) ^ 1];
+		break;
+	case 4:
+		*val = mace->pci.config_data.l;
+		break;
+	}
+
+	DPRINTK("read%d: reg=%08x,val=%02x\n", size * 8, reg, *val);
+
+	return PCIBIOS_SUCCESSFUL;
+}
+
+static int
+mace_pci_write_config(struct pci_bus *bus, unsigned int devfn,
+		      int reg, int size, u32 val)
+{
+	chkslot(bus, devfn);
+	mace->pci.config_addr = mkaddr(devfn, reg);
+	switch (size) {
+	case 1:
+		mace->pci.config_data.b[(reg & 3) ^ 3] = val;
+		break;
+	case 2:
+		mace->pci.config_data.w[((reg >> 1) & 1) ^ 1] = val;
+		break;
+	case 4:
+		mace->pci.config_data.l = val;
+		break;
+	}
+
+	DPRINTK("write%d: reg=%08x,val=%02x\n", size * 8, reg, val);
+
+	return PCIBIOS_SUCCESSFUL;
+}
+
+struct pci_ops mace_pci_ops = {
+	.read = mace_pci_read_config,
+	.write = mace_pci_write_config,
+};
--- diff/arch/mips/pci/ops-msc.c	1970-01-01 01:00:00.000000000 +0100
+++ source/arch/mips/pci/ops-msc.c	2004-02-23 13:56:38.000000000 +0000
@@ -0,0 +1,161 @@
+/*
+ * Carsten Langgaard, carstenl@mips.com
+ * Copyright (C) 1999, 2000 MIPS Technologies, Inc.  All rights reserved.
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * MIPS boards specific PCI support.
+ *
+ */
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+
+#include <asm/mips-boards/msc01_pci.h>
+
+#define PCI_ACCESS_READ  0
+#define PCI_ACCESS_WRITE 1
+
+/*
+ *  PCI configuration cycle AD bus definition
+ */
+/* Type 0 */
+#define PCI_CFG_TYPE0_REG_SHF           0
+#define PCI_CFG_TYPE0_FUNC_SHF          8
+
+/* Type 1 */
+#define PCI_CFG_TYPE1_REG_SHF           0
+#define PCI_CFG_TYPE1_FUNC_SHF          8
+#define PCI_CFG_TYPE1_DEV_SHF           11
+#define PCI_CFG_TYPE1_BUS_SHF           16
+
+static int msc_pcibios_config_access(unsigned char access_type,
+	struct pci_bus *bus, unsigned int devfn, int where, u32 * data)
+{
+	unsigned char busnum = bus->number;
+	unsigned char type;
+	u32 intr;
+
+	if ((busnum == 0) && (PCI_SLOT(devfn) == 0))
+		return -1;
+
+	/* Clear status register bits. */
+	MSC_WRITE(MSC01_PCI_INTSTAT,
+		  (MSC01_PCI_INTCFG_MA_BIT | MSC01_PCI_INTCFG_TA_BIT));
+
+	/* Setup address */
+	if (busnum == 0)
+		type = 0;	/* Type 0 */
+	else
+		type = 1;	/* Type 1 */
+
+	MSC_WRITE(MSC01_PCI_CFGADDR,
+		  ((busnum << MSC01_PCI_CFGADDR_BNUM_SHF) |
+		   (PCI_SLOT(devfn) << MSC01_PCI_CFGADDR_DNUM_SHF)
+		   | (PCI_FUNC(devfn) <<
+		      MSC01_PCI_CFGADDR_FNUM_SHF) | ((where /
+						      4) <<
+						     MSC01_PCI_CFGADDR_RNUM_SHF)
+		   | (type)));
+
+	/* Perform access */
+	if (access_type == PCI_ACCESS_WRITE)
+		MSC_WRITE(MSC01_PCI_CFGDATA, *data);
+	else
+		MSC_READ(MSC01_PCI_CFGDATA, *data);
+
+	/* Detect Master/Target abort */
+	MSC_READ(MSC01_PCI_INTSTAT, intr);
+	if (intr & (MSC01_PCI_INTCFG_MA_BIT |
+		    MSC01_PCI_INTCFG_TA_BIT)) {
+		/* Error occurred */
+
+		/* Clear bits */
+		MSC_READ(MSC01_PCI_INTSTAT, intr);
+		MSC_WRITE(MSC01_PCI_INTSTAT,
+			  (MSC01_PCI_INTCFG_MA_BIT |
+			   MSC01_PCI_INTCFG_TA_BIT));
+
+		return -1;
+	}
+
+	return 0;
+}
+
+
+/*
+ * We can't address 8 and 16 bit words directly.  Instead we have to
+ * read/write a 32bit word and mask/modify the data we actually want.
+ */
+static int msc_pcibios_read(struct pci_bus *bus, unsigned int devfn,
+			     int where, int size, u32 * val)
+{
+	u32 data = 0;
+
+	if ((size == 2) && (where & 1))
+		return PCIBIOS_BAD_REGISTER_NUMBER;
+	else if ((size == 4) && (where & 3))
+		return PCIBIOS_BAD_REGISTER_NUMBER;
+
+	if (msc_pcibios_config_access(PCI_ACCESS_READ, bus, devfn, where,
+	                              &data))
+		return -1;
+
+	if (size == 1)
+		*val = (data >> ((where & 3) << 3)) & 0xff;
+	else if (size == 2)
+		*val = (data >> ((where & 3) << 3)) & 0xffff;
+	else
+		*val = data;
+
+	return PCIBIOS_SUCCESSFUL;
+}
+
+static int msc_pcibios_write(struct pci_bus *bus, unsigned int devfn,
+			      int where, int size, u32 val)
+{
+	u32 data = 0;
+
+	if ((size == 2) && (where & 1))
+		return PCIBIOS_BAD_REGISTER_NUMBER;
+	else if ((size == 4) && (where & 3))
+		return PCIBIOS_BAD_REGISTER_NUMBER;
+
+	if (size == 4)
+		data = val;
+	else {
+		if (msc_pcibios_config_access(PCI_ACCESS_READ, bus, devfn,
+		                              where, &data))
+			return -1;
+
+		if (size == 1)
+			data = (data & ~(0xff << ((where & 3) << 3))) |
+				(val << ((where & 3) << 3));
+		else if (size == 2)
+			data = (data & ~(0xffff << ((where & 3) << 3))) |
+				(val << ((where & 3) << 3));
+	}
+
+	if (msc_pcibios_config_access(PCI_ACCESS_WRITE, bus, devfn, where,
+				       &data))
+		return -1;
+
+	return PCIBIOS_SUCCESSFUL;
+}
+
+struct pci_ops msc_pci_ops = {
+	.read = msc_pcibios_read,
+	.write = msc_pcibios_write
+};
--- diff/arch/mips/pci/ops-mv64340.c	1970-01-01 01:00:00.000000000 +0100
+++ source/arch/mips/pci/ops-mv64340.c	2004-02-23 13:56:38.000000000 +0000
@@ -0,0 +1,145 @@
+/*
+ * Copyright 2002 Momentum Computer
+ * Author: Matthew Dharm <mdharm@momenco.com>
+ *
+ * Copyright (C) 2003 Ralf Baechle (ralf@linux-mips.org)
+ *
+ *  This program is free software; you can redistribute  it and/or modify it
+ *  under  the terms of  the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the  License, or (at your
+ *  option) any later version.
+ *
+ *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
+ *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
+ *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
+ *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
+ *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
+ *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *  You should have received a copy of the  GNU General Public License along
+ *  with this program; if not, write  to the Free Software Foundation, Inc.,
+ *  675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <linux/kernel.h>
+#include <asm/mv64340.h>
+
+/*
+ * galileo_pcibios_(read/write)_config_(dword/word/byte) -
+ *
+ * reads/write a dword/word/byte register from the configuration space
+ * of a device.
+ *
+ * Note that bus 0 and bus 1 are local, and we assume all other busses are
+ * bridged from bus 1.  This is a safe assumption, since any other
+ * configuration will require major modifications to the CP7000G
+ *
+ * Inputs :
+ * bus - bus number
+ * dev - device number
+ * offset - register offset in the configuration space
+ * val - value to be written / read
+ *
+ * Outputs :
+ * PCIBIOS_SUCCESSFUL when operation was succesfull
+ * PCIBIOS_DEVICE_NOT_FOUND when the bus or dev is errorneous
+ * PCIBIOS_BAD_REGISTER_NUMBER when accessing non aligned
+ */
+
+static int mv64340_read_config(struct pci_bus *bus, unsigned int devfn, int reg,
+	int size, u32 * val, u32 address_reg, u32 data_reg)
+{
+	u32 address;
+
+	/* Accessing device 31 crashes the MV-64340. */
+	if (PCI_SLOT(devfn) > 5)
+		return PCIBIOS_DEVICE_NOT_FOUND;
+
+	address = (bus->number << 16) | (dev << 11) | (func << 8) |
+		  (offset & 0xfc) | 0x80000000;
+
+	/* start the configuration cycle */
+	MV_WRITE(address_reg, address);
+
+	switch (size) {
+	case 1:
+		MV_READ_8(data_reg + (offset & 0x3), val);
+		break;
+
+	case 2:
+		MV_READ_16(data_reg + (offset & 0x3), val);
+		break;
+
+	case 4:
+		MV_READ(data_reg, val);
+		break;
+	}
+
+	return PCIBIOS_SUCCESSFUL;
+}
+
+static int mv64340_write_config(struct pci_bus *bus, unsigned int devfn,
+	int reg, int size, u32 val, u32 address_reg, u32 data_reg)
+{
+	u32 address;
+
+	/* Accessing device 31 crashes the MV-64340. */
+	if (PCI_SLOT(devfn) > 5)
+		return PCIBIOS_DEVICE_NOT_FOUND;
+
+	address = (bus->number << 16) | (devfn << 8) |
+		  (offset & 0xfc) | 0x80000000;
+
+	/* start the configuration cycle */
+	MV_WRITE(address_reg, address);
+
+	switch (size) {
+	case 1:
+		/* write the data */
+		MV_WRITE_8(data_reg + (offset & 0x3), val);
+		break;
+
+	case 2:
+		/* write the data */
+		MV_WRITE_16(data_reg + (offset & 0x3), val);
+		break;
+
+	case 4:
+		/* write the data */
+		MV_WRITE(data_reg, val);
+		break;
+	}
+
+	return PCIBIOS_SUCCESSFUL;
+}
+
+#define BUILD_PCI_OPS(host)						\
+									\
+static int mv64340_bus ## host ## _read_config(struct pci_bus *bus,	\
+	unsigned int devfn, int reg, int size, u32 * val)		\
+{									\
+	return mv64340_read_config(bus, devfn, reg, size, val,		\
+	           MV64340_PCI_ ## host ## _CONFIG_ADDR;		\
+	           MV64340_PCI_ ## host ## _CONFIG_DATA_VIRTUAL_REG);	\
+}									\
+									\
+static int mv64340_bus ## host ## _write_config(struct pci_bus *bus,	\
+	unsigned int devfn, int reg, int size, u32 val)			\
+{									\
+	return mv64340_write_config(bus, devfn, reg, size, val,		\
+	           MV64340_PCI_ ## host ## _CONFIG_ADDR;		\
+	           MV64340_PCI_ ## host ## _CONFIG_DATA_VIRTUAL_REG);	\
+}									\
+									\
+struct pci_ops mv64340_bus ## host ## _pci_ops = {			\
+	.read	= mv64340_bus ## host ## _read_config,			\
+	.write	= mv64340_bus ## host ## _write_config			\
+};
+
+BUILD_PCI_OPS(0)
+BUILD_PCI_OPS(1)
--- diff/arch/mips/pci/ops-nile4.c	1970-01-01 01:00:00.000000000 +0100
+++ source/arch/mips/pci/ops-nile4.c	2004-02-23 13:56:38.000000000 +0000
@@ -0,0 +1,147 @@
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <asm/bootinfo.h>
+
+#include <asm/lasat/lasat.h>
+#include <asm/gt64120.h>
+#include <asm/nile4.h>
+
+#define PCI_ACCESS_READ  0
+#define PCI_ACCESS_WRITE 1
+
+#define LO(reg) (reg / 4)
+#define HI(reg) (reg / 4 + 1)
+
+volatile unsigned long *const vrc_pciregs = (void *) Vrc5074_BASE;
+
+static spinlock_t nile4_pci_lock;
+
+static int nile4_pcibios_config_access(unsigned char access_type,
+	struct pci_bus *bus, unsigned int devfn, int where, u32 * val)
+{
+	unsigned char busnum = bus->number;
+	u32 adr, mask, err;
+
+	if ((busnum == 0) && (PCI_SLOT(devfn) > 8))
+		/* The addressing scheme chosen leaves room for just
+		 * 8 devices on the first busnum (besides the PCI
+		 * controller itself) */
+		return PCIBIOS_DEVICE_NOT_FOUND;
+
+	if ((busnum == 0) && (devfn == PCI_DEVFN(0, 0))) {
+		/* Access controller registers directly */
+		if (access_type == PCI_ACCESS_WRITE) {
+			vrc_pciregs[(0x200 + where) >> 2] = *val;
+		} else {
+			*val = vrc_pciregs[(0x200 + where) >> 2];
+		}
+		return PCIBIOS_SUCCESSFUL;
+	}
+
+	/* Temporarily map PCI Window 1 to config space */
+	mask = vrc_pciregs[LO(NILE4_PCIINIT1)];
+	vrc_pciregs[LO(NILE4_PCIINIT1)] = 0x0000001a | (busnum ? 0x200 : 0);
+
+	/* Clear PCI Error register. This also clears the Error Type
+	 * bits in the Control register */
+	vrc_pciregs[LO(NILE4_PCIERR)] = 0;
+	vrc_pciregs[HI(NILE4_PCIERR)] = 0;
+
+	/* Setup address */
+	if (busnum == 0)
+		adr =
+		    KSEG1ADDR(PCI_WINDOW1) +
+		    ((1 << (PCI_SLOT(devfn) + 15)) | (PCI_FUNC(devfn) << 8)
+		     | (where & ~3));
+	else
+		adr = KSEG1ADDR(PCI_WINDOW1) | (busnum << 16) | (devfn << 8) |
+		      (where & ~3);
+
+	if (access_type == PCI_ACCESS_WRITE)
+		*(u32 *) adr = *val;
+	else
+		*val = *(u32 *) adr;
+
+	/* Check for master or target abort */
+	err = (vrc_pciregs[HI(NILE4_PCICTRL)] >> 5) & 0x7;
+
+	/* Restore PCI Window 1 */
+	vrc_pciregs[LO(NILE4_PCIINIT1)] = mask;
+
+	if (err)
+		return PCIBIOS_DEVICE_NOT_FOUND;
+
+	return PCIBIOS_SUCCESSFUL;
+}
+
+static int nile4_pcibios_read(struct pci_bus *bus, unsigned int devfn,
+	int where, int size, u32 * val)
+{
+	unsigned long flags;
+	u32 data = 0;
+	int err;
+
+	if ((size == 2) && (where & 1))
+		return PCIBIOS_BAD_REGISTER_NUMBER;
+	else if ((size == 4) && (where & 3))
+		return PCIBIOS_BAD_REGISTER_NUMBER;
+
+	spin_lock_irqsave(&nile4_pci_lock, flags);
+	err = nile4_pcibios_config_access(PCI_ACCESS_READ, bus, devfn, where,
+					&data);
+	spin_unlock_irqrestore(&nile4_pci_lock, flags);
+
+	if (err)
+		return err;
+
+	if (size == 1)
+		*val = (data >> ((where & 3) << 3)) & 0xff;
+	else if (size == 2)
+		*val = (data >> ((where & 3) << 3)) & 0xffff;
+	else
+		*val = data;
+
+	return PCIBIOS_SUCCESSFUL;
+}
+
+static int nile4_pcibios_write(struct pci_bus *bus, unsigned int devfn,
+	int where, int size, u32 val)
+{
+	unsigned long flags;
+	u32 data = 0;
+	int err;
+
+	if ((size == 2) && (where & 1))
+		return PCIBIOS_BAD_REGISTER_NUMBER;
+	else if ((size == 4) && (where & 3))
+		return PCIBIOS_BAD_REGISTER_NUMBER;
+
+	spin_lock_irqsave(&nile4_pci_lock, flags);
+	err = nile4_pcibios_config_access(PCI_ACCESS_READ, bus, devfn, where,
+	                                  &data);
+	spin_unlock_irqrestore(&nile4_pci_lock, flags);
+
+	if (err)
+		return err;
+
+	if (size == 1)
+		data = (data & ~(0xff << ((where & 3) << 3))) |
+		    (val << ((where & 3) << 3));
+	else if (size == 2)
+		data = (data & ~(0xffff << ((where & 3) << 3))) |
+		    (val << ((where & 3) << 3));
+	else
+		data = val;
+
+	if (nile4_pcibios_config_access
+	    (PCI_ACCESS_WRITE, bus, devfn, where, &data))
+		return -1;
+
+	return PCIBIOS_SUCCESSFUL;
+}
+
+struct pci_ops nile4_pci_ops = {
+	.read = nile4_pcibios_read,
+	.write = nile4_pcibios_write,
+};
--- diff/arch/mips/pci/ops-sni.c	1970-01-01 01:00:00.000000000 +0100
+++ source/arch/mips/pci/ops-sni.c	2004-02-23 13:56:38.000000000 +0000
@@ -0,0 +1,89 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * SNI specific PCI support for RM200/RM300.
+ *
+ * Copyright (C) 1997 - 2000, 2003 Ralf Baechle <ralf@linux-mips.org>
+ */
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/types.h>
+#include <asm/sni.h>
+
+/*
+ * It seems that on the RM200 only lower 3 bits of the 5 bit PCI device
+ * address are decoded.  We therefore manually have to reject attempts at
+ * reading outside this range.  Being on the paranoid side we only do this
+ * test for bus 0 and hope forwarding and decoding work properly for any
+ * subordinated busses.
+ *
+ * ASIC PCI only supports type 1 config cycles.
+ */
+static int set_config_address(unsigned char busno, unsigned int devfn, int reg)
+{
+	if ((busno > 255) || (devfn > 255) || (reg > 255))
+		return PCIBIOS_BAD_REGISTER_NUMBER;
+
+	if (busno == 0 && devfn >= PCI_DEVFN(8, 0))
+		return PCIBIOS_DEVICE_NOT_FOUND;
+
+	*(volatile u32 *)PCIMT_CONFIG_ADDRESS =
+		 ((busno    & 0xff) << 16) |
+	         ((devfn    & 0xff) <<  8) |
+	          (reg      & 0xfc);
+
+	return PCIBIOS_SUCCESSFUL;
+}
+
+static int pcimt_read(struct pci_bus *bus, unsigned int devfn, int reg,
+		      int size, u32 * val)
+{
+	int res;
+
+	if ((res = set_config_address(bus->number, devfn, reg)))
+		return res;
+
+	switch (size) {
+	case 1:
+		*val = *(volatile  u8 *) (PCIMT_CONFIG_DATA + (reg & 3));
+		break;
+	case 2:
+		*val = *(volatile u16 *) (PCIMT_CONFIG_DATA + (reg & 2));
+		break;
+	case 4:
+		*val = *(volatile u32 *) PCIMT_CONFIG_DATA;
+		break;
+	}
+
+	return 0;
+}
+
+static int pcimt_write(struct pci_bus *bus, unsigned int devfn, int reg,
+		       int size, u32 val)
+{
+	int res;
+
+	if ((res = set_config_address(bus->number, devfn, reg)))
+		return res;
+
+	switch (size) {
+	case 1:
+		*(volatile  u8 *) (PCIMT_CONFIG_DATA + (reg & 3)) = val;
+		break;
+	case 2:
+		*(volatile u16 *) (PCIMT_CONFIG_DATA + (reg & 2)) = val;
+		break;
+	case 4:
+		*(volatile u32 *) PCIMT_CONFIG_DATA = val;
+		break;
+	}
+
+	return 0;
+}
+
+struct pci_ops sni_pci_ops = {
+	.read = pcimt_read,
+	.write = pcimt_write,
+};
--- diff/arch/mips/pci/ops-titan.c	1970-01-01 01:00:00.000000000 +0100
+++ source/arch/mips/pci/ops-titan.c	2004-02-23 13:56:38.000000000 +0000
@@ -0,0 +1,135 @@
+/*
+ * Copyright 2003 PMC-Sierra
+ * Author: Manish Lachwani (lachwani@pmc-sierra.com)
+ *
+ *  This program is free software; you can redistribute	 it and/or modify it
+ *  under  the terms of	 the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the	License, or (at your
+ *  option) any later version.
+ *
+ *  THIS  SOFTWARE  IS PROVIDED	  ``AS	IS'' AND   ANY	EXPRESS OR IMPLIED
+ *  WARRANTIES,	  INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
+ *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
+ *  NO	EVENT  SHALL   THE AUTHOR  BE	 LIABLE FOR ANY	  DIRECT, INDIRECT,
+ *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ *  NOT LIMITED	  TO, PROCUREMENT OF  SUBSTITUTE GOODS	OR SERVICES; LOSS OF
+ *  USE, DATA,	OR PROFITS; OR	BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ *  ANY THEORY OF LIABILITY, WHETHER IN	 CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *  You should have received a copy of the  GNU General Public License along
+ *  with this program; if not, write  to the Free Software Foundation, Inc.,
+ *  675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/version.h>
+
+#include <asm/pci.h>
+#include <asm/io.h>
+#include <asm/titan_dep.h>
+
+/*
+ * Titan PCI Config Read Byte
+ */
+static int titan_read_config(struct pci_bus *bus, unsigned int devfn, int reg,
+	int size, u32 * val)
+{
+	int dev, bus, func;
+	uint32_t address_reg, data_reg;
+	uint32_t address;
+
+	bus = device->bus->number;
+	dev = PCI_SLOT(device->devfn);
+	func = PCI_FUNC(device->devfn);
+
+	address_reg = TITAN_PCI_0_CONFIG_ADDRESS;
+	data_reg = TITAN_PCI_0_CONFIG_DATA;
+
+	address = (bus << 16) | (dev << 11) | (func << 8) |
+		(offset & 0xfc) | 0x80000000;
+
+	/* start the configuration cycle */
+	TITAN_WRITE(address_reg, address);
+
+	switch (size) {
+	case 1:
+		TITAN_READ_8(data_reg + (offset & 0x3), val);
+		break;
+
+	case 2:
+		TITAN_READ_16(data_reg + (offset & 0x2), val);
+		break;
+
+	case 4:
+		TITAN_READ(data_reg, val);
+		break;
+	}
+
+	return PCIBIOS_SUCCESSFUL;
+}
+
+/*
+ * Titan PCI Config Byte Write
+ */
+static int titan_write_config(struct pci_bus *bus, unsigned int devfn, int reg,
+	int size, u32 val)
+{
+	uint32_t address_reg, data_reg, address;
+	int dev, bus, func;
+
+	bus = device->bus->number;
+	dev = PCI_SLOT(device->devfn);
+	func = PCI_FUNC(device->devfn);
+
+	address_reg = TITAN_PCI_0_CONFIG_ADDRESS;
+	data_reg = TITAN_PCI_0_CONFIG_DATA;
+
+	address = (bus << 16) | (dev << 11) | (func << 8) |
+		(offset & 0xfc) | 0x80000000;
+
+	/* start the configuration cycle */
+	TITAN_WRITE(address_reg, address);
+
+	/* write the data */
+	switch (size) {
+	case 1:
+		TITAN_WRITE_8(data_reg + (offset & 0x3), val);
+		break;
+
+	case 2:
+		TITAN_WRITE_16(data_reg + (offset & 0x2), val);
+		break;
+
+	case 4:
+		TITAN_WRITE(data_reg, val);
+		break;
+	}
+
+	return PCIBIOS_SUCCESSFUL;
+}
+
+/*
+ * Titan PCI structure
+ */
+struct pci_ops titan_pci_ops = {
+	titan_read_config,
+	titan_write_config,
+};
+
+void __init pcibios_init(void)
+{
+	/* 
+	 * XXX These values below need to change
+	 */
+	ioport_resource.start = 0xe0000000;
+	ioport_resource.end   = 0xe0000000 + 0x20000000 - 1;
+	iomem_resource.start  = 0xc0000000;
+	iomem_resource.end    = 0xc0000000 + 0x20000000 - 1;
+
+	pci_scan_bus(0, &titan_pci_ops, NULL);
+}
--- diff/arch/mips/pci/ops-tx3927.c	1970-01-01 01:00:00.000000000 +0100
+++ source/arch/mips/pci/ops-tx3927.c	2004-02-23 13:56:38.000000000 +0000
@@ -0,0 +1,391 @@
+/*
+ * Copyright 2001 MontaVista Software Inc.
+ * Author: MontaVista Software, Inc.
+ *              ahennessy@mvista.com
+ *
+ * Copyright (C) 2000-2001 Toshiba Corporation
+ *
+ * Based on arch/mips/ddb5xxx/ddb5477/pci_ops.c
+ *
+ *     Define the pci_ops for JMR3927.
+ *
+ * Much of the code is derived from the original DDB5074 port by
+ * Geert Uytterhoeven <geert@sonycom.com>
+ *
+ *  This program is free software; you can redistribute  it and/or modify it
+ *  under  the terms of  the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the  License, or (at your
+ *  option) any later version.
+ *
+ *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
+ *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
+ *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
+ *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
+ *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
+ *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *  You should have received a copy of the  GNU General Public License along
+ *  with this program; if not, write  to the Free Software Foundation, Inc.,
+ *  675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+
+#include <asm/addrspace.h>
+#include <asm/pci_channel.h>
+#include <asm/jmr3927/jmr3927.h>
+#include <asm/debug.h>
+
+static inline int mkaddr(unsigned char bus, unsigned char dev_fn,
+	unsigned char where)
+{
+	if (bus == 0 && dev_fn >= PCI_DEVFN(TX3927_PCIC_MAX_DEVNU, 0))
+		return PCIBIOS_DEVICE_NOT_FOUND;
+
+	tx3927_pcicptr->ica = ((bus & 0xff) << 0x10) |
+	                      ((dev_fn & 0xff) << 0x08) |
+	                      (where & 0xfc);
+
+	/* clear M_ABORT and Disable M_ABORT Int. */
+	tx3927_pcicptr->pcistat |= PCI_STATUS_REC_MASTER_ABORT;
+	tx3927_pcicptr->pcistatim &= ~PCI_STATUS_REC_MASTER_ABORT;
+
+	return PCIBIOS_SUCCESSFUL;
+}
+
+static inline int check_abort(void)
+{
+	if (tx3927_pcicptr->pcistat & PCI_STATUS_REC_MASTER_ABORT)
+		tx3927_pcicptr->pcistat |= PCI_STATUS_REC_MASTER_ABORT;
+		tx3927_pcicptr->pcistatim |= PCI_STATUS_REC_MASTER_ABORT;
+		return PCIBIOS_DEVICE_NOT_FOUND;
+
+	return PCIBIOS_SUCCESSFUL;
+}
+
+static int jmr3927_pci_read_config(struct pci_bus *bus, unsigned int devfn,
+	int where, int size, u32 * val)
+{
+	int ret, busno;
+
+	/* check if the bus is top-level */
+	if (bus->parent != NULL)
+		busno = bus->number;
+
+	ret = mkaddr(busno, devfn, where);
+	if (ret)
+		return ret;
+
+	switch (size) {
+	case 1:
+		*val = *(volatile u8 *) ((unsigned long) & tx3927_pcicptr->icd | (where & 3));
+		break;
+
+	case 2:
+		*val = le16_to_cpu(*(volatile u16 *) ((unsigned long) & tx3927_pcicptr->icd | (where & 3)));
+		break;
+
+	case 4:
+		*val = le32_to_cpu(tx3927_pcicptr->icd);
+		break;
+	}
+
+	return check_abort();
+}
+
+static int jmr3927_pci_write_config(struct pci_bus *bus, unsigned int devfn,
+	int where, int size, u32 val)
+{
+	int ret, busno;
+
+	/* check if the bus is top-level */
+	if (bus->parent != NULL)
+		bus = bus->number;
+	else
+		bus = 0;
+
+	ret = mkaddr(busno, devfn, where);
+	if (ret)
+		return ret;
+
+	switch (size) {
+	case 1:
+		*(volatile u8 *) ((unsigned long) & tx3927_pcicptr->icd | (where & 3)) = val;
+		break;
+
+	case 2:
+		*(volatile u16 *) (unsigned longulong) & tx3927_pcicptr->icd | (where & 2)) =
+	    cpu_to_le16(val);
+		break;
+
+	case 4:
+		tx3927_pcicptr->icd = cpu_to_le32(val);
+	}
+
+	if (tx3927_pcicptr->pcistat & PCI_STATUS_REC_MASTER_ABORT)
+		tx3927_pcicptr->pcistat |= PCI_STATUS_REC_MASTER_ABORT;
+		tx3927_pcicptr->pcistatim |= PCI_STATUS_REC_MASTER_ABORT;
+		return PCIBIOS_DEVICE_NOT_FOUND;
+
+	return check_abort();
+}
+
+struct pci_ops jmr3927_pci_ops = {
+	jmr3927_pcibios_read_config,
+	jmr3927_pcibios_write_config,
+};
+
+
+#ifndef JMR3927_INIT_INDIRECT_PCI
+
+inline unsigned long tc_readl(volatile __u32 * addr)
+{
+	return readl(addr);
+}
+
+inline void tc_writel(unsigned long data, volatile __u32 * addr)
+{
+	writel(data, addr);
+}
+#else
+
+unsigned long tc_readl(volatile __u32 * addr)
+{
+	unsigned long val;
+
+	addr = PHYSADDR(addr);
+	*(volatile u32 *) (ulong) & tx3927_pcicptr->ipciaddr =
+	    (unsigned long) addr;
+	*(volatile u32 *) (ulong) & tx3927_pcicptr->ipcibe =
+	    (PCI_IPCIBE_ICMD_MEMREAD << PCI_IPCIBE_ICMD_SHIFT) |
+	    PCI_IPCIBE_IBE_LONG;
+	while (!(tx3927_pcicptr->istat & PCI_ISTAT_IDICC));
+	val =
+	    le32_to_cpu(*(volatile u32 *) (ulong) & tx3927_pcicptr->
+			ipcidata);
+	/* clear by setting */
+	tx3927_pcicptr->istat |= PCI_ISTAT_IDICC;
+	return val;
+}
+
+void tc_writel(unsigned long data, volatile __u32 * addr)
+{
+	addr = PHYSADDR(addr);
+	*(volatile u32 *) (ulong) & tx3927_pcicptr->ipcidata =
+	    cpu_to_le32(data);
+	*(volatile u32 *) (ulong) & tx3927_pcicptr->ipciaddr =
+	    (unsigned long) addr;
+	*(volatile u32 *) (ulong) & tx3927_pcicptr->ipcibe =
+	    (PCI_IPCIBE_ICMD_MEMWRITE << PCI_IPCIBE_ICMD_SHIFT) |
+	    PCI_IPCIBE_IBE_LONG;
+	while (!(tx3927_pcicptr->istat & PCI_ISTAT_IDICC));
+	/* clear by setting */
+	tx3927_pcicptr->istat |= PCI_ISTAT_IDICC;
+}
+
+unsigned char tx_ioinb(unsigned char *addr)
+{
+	unsigned long val;
+	__u32 ioaddr;
+	int offset;
+	int byte;
+
+	ioaddr = (unsigned long) addr;
+	offset = ioaddr & 0x3;
+	if (offset == 0)
+		byte = 0x7;
+	else if (offset == 1)
+		byte = 0xb;
+	else if (offset == 2)
+		byte = 0xd;
+	else if (offset == 3)
+		byte = 0xe;
+	*(volatile u32 *) (ulong) & tx3927_pcicptr->ipciaddr =
+	    (unsigned long) ioaddr;
+	*(volatile u32 *) (ulong) & tx3927_pcicptr->ipcibe =
+	    (PCI_IPCIBE_ICMD_IOREAD << PCI_IPCIBE_ICMD_SHIFT) | byte;
+	while (!(tx3927_pcicptr->istat & PCI_ISTAT_IDICC));
+	val =
+	    le32_to_cpu(*(volatile u32 *) (ulong) & tx3927_pcicptr->
+			ipcidata);
+	val = val & 0xff;
+	/* clear by setting */
+	tx3927_pcicptr->istat |= PCI_ISTAT_IDICC;
+	return val;
+}
+
+void tx_iooutb(unsigned long data, unsigned char *addr)
+{
+	__u32 ioaddr;
+	int offset;
+	int byte;
+
+	data = data | (data << 8) | (data << 16) | (data << 24);
+	ioaddr = (unsigned long) addr;
+	offset = ioaddr & 0x3;
+	if (offset == 0)
+		byte = 0x7;
+	else if (offset == 1)
+		byte = 0xb;
+	else if (offset == 2)
+		byte = 0xd;
+	else if (offset == 3)
+		byte = 0xe;
+	*(volatile u32 *) (ulong) & tx3927_pcicptr->ipcidata = data;
+	*(volatile u32 *) (ulong) & tx3927_pcicptr->ipciaddr =
+	    (unsigned long) ioaddr;
+	*(volatile u32 *) (ulong) & tx3927_pcicptr->ipcibe =
+	    (PCI_IPCIBE_ICMD_IOWRITE << PCI_IPCIBE_ICMD_SHIFT) | byte;
+	while (!(tx3927_pcicptr->istat & PCI_ISTAT_IDICC));
+	/* clear by setting */
+	tx3927_pcicptr->istat |= PCI_ISTAT_IDICC;
+}
+
+unsigned short tx_ioinw(unsigned short *addr)
+{
+	unsigned long val;
+	__u32 ioaddr;
+	int offset;
+	int byte;
+
+	ioaddr = (unsigned long) addr;
+	offset = ioaddr & 0x3;
+	if (offset == 0)
+		byte = 0x3;
+	else if (offset == 2)
+		byte = 0xc;
+	*(volatile u32 *) (ulong) & tx3927_pcicptr->ipciaddr =
+	    (unsigned long) ioaddr;
+	*(volatile u32 *) (ulong) & tx3927_pcicptr->ipcibe =
+	    (PCI_IPCIBE_ICMD_IOREAD << PCI_IPCIBE_ICMD_SHIFT) | byte;
+	while (!(tx3927_pcicptr->istat & PCI_ISTAT_IDICC));
+	val =
+	    le32_to_cpu(*(volatile u32 *) (ulong) & tx3927_pcicptr->
+			ipcidata);
+	val = val & 0xffff;
+	/* clear by setting */
+	tx3927_pcicptr->istat |= PCI_ISTAT_IDICC;
+	return val;
+
+}
+
+void tx_iooutw(unsigned long data, unsigned short *addr)
+{
+	__u32 ioaddr;
+	int offset;
+	int byte;
+
+	data = data | (data << 16);
+	ioaddr = (unsigned long) addr;
+	offset = ioaddr & 0x3;
+	if (offset == 0)
+		byte = 0x3;
+	else if (offset == 2)
+		byte = 0xc;
+	*(volatile u32 *) (ulong) & tx3927_pcicptr->ipcidata = data;
+	*(volatile u32 *) (ulong) & tx3927_pcicptr->ipciaddr =
+	    (unsigned long) ioaddr;
+	*(volatile u32 *) (ulong) & tx3927_pcicptr->ipcibe =
+	    (PCI_IPCIBE_ICMD_IOWRITE << PCI_IPCIBE_ICMD_SHIFT) | byte;
+	while (!(tx3927_pcicptr->istat & PCI_ISTAT_IDICC));
+	/* clear by setting */
+	tx3927_pcicptr->istat |= PCI_ISTAT_IDICC;
+}
+
+unsigned long tx_ioinl(unsigned int *addr)
+{
+	unsigned long val;
+	__u32 ioaddr;
+
+	ioaddr = (unsigned long) addr;
+	*(volatile u32 *) (ulong) & tx3927_pcicptr->ipciaddr =
+	    (unsigned long) ioaddr;
+	*(volatile u32 *) (ulong) & tx3927_pcicptr->ipcibe =
+	    (PCI_IPCIBE_ICMD_IOREAD << PCI_IPCIBE_ICMD_SHIFT) |
+	    PCI_IPCIBE_IBE_LONG;
+	while (!(tx3927_pcicptr->istat & PCI_ISTAT_IDICC));
+	val =
+	    le32_to_cpu(*(volatile u32 *) (ulong) & tx3927_pcicptr->
+			ipcidata);
+	/* clear by setting */
+	tx3927_pcicptr->istat |= PCI_ISTAT_IDICC;
+	return val;
+}
+
+void tx_iooutl(unsigned long data, unsigned int *addr)
+{
+	__u32 ioaddr;
+
+	ioaddr = (unsigned long) addr;
+	*(volatile u32 *) (ulong) & tx3927_pcicptr->ipcidata =
+	    cpu_to_le32(data);
+	*(volatile u32 *) (ulong) & tx3927_pcicptr->ipciaddr =
+	    (unsigned long) ioaddr;
+	*(volatile u32 *) (ulong) & tx3927_pcicptr->ipcibe =
+	    (PCI_IPCIBE_ICMD_IOWRITE << PCI_IPCIBE_ICMD_SHIFT) |
+	    PCI_IPCIBE_IBE_LONG;
+	while (!(tx3927_pcicptr->istat & PCI_ISTAT_IDICC));
+	/* clear by setting */
+	tx3927_pcicptr->istat |= PCI_ISTAT_IDICC;
+}
+
+void tx_insbyte(unsigned char *addr, void *buffer, unsigned int count)
+{
+	unsigned char *ptr = (unsigned char *) buffer;
+
+	while (count--) {
+		*ptr++ = tx_ioinb(addr);
+	}
+}
+
+void tx_insword(unsigned short *addr, void *buffer, unsigned int count)
+{
+	unsigned short *ptr = (unsigned short *) buffer;
+
+	while (count--) {
+		*ptr++ = tx_ioinw(addr);
+	}
+}
+
+void tx_inslong(unsigned int *addr, void *buffer, unsigned int count)
+{
+	unsigned long *ptr = (unsigned long *) buffer;
+
+	while (count--) {
+		*ptr++ = tx_ioinl(addr);
+	}
+}
+
+void tx_outsbyte(unsigned char *addr, void *buffer, unsigned int count)
+{
+	unsigned char *ptr = (unsigned char *) buffer;
+
+	while (count--) {
+		tx_iooutb(*ptr++, addr);
+	}
+}
+
+void tx_outsword(unsigned short *addr, void *buffer, unsigned int count)
+{
+	unsigned short *ptr = (unsigned short *) buffer;
+
+	while (count--) {
+		tx_iooutw(*ptr++, addr);
+	}
+}
+
+void tx_outslong(unsigned int *addr, void *buffer, unsigned int count)
+{
+	unsigned long *ptr = (unsigned long *) buffer;
+
+	while (count--) {
+		tx_iooutl(*ptr++, addr);
+	}
+}
+#endif
--- diff/arch/mips/pci/ops-tx4927.c	1970-01-01 01:00:00.000000000 +0100
+++ source/arch/mips/pci/ops-tx4927.c	2004-02-23 13:56:38.000000000 +0000
@@ -0,0 +1,306 @@
+/*
+ * Copyright 2001 MontaVista Software Inc.
+ * Author: MontaVista Software, Inc.
+ *              ahennessy@mvista.com       
+ *
+ * Copyright (C) 2000-2001 Toshiba Corporation 
+ *
+ * Based on arch/mips/ddb5xxx/ddb5477/pci_ops.c
+ *
+ *     Define the pci_ops for the Toshiba rbtx4927
+ *
+ * Much of the code is derived from the original DDB5074 port by 
+ * Geert Uytterhoeven <geert@sonycom.com>
+ *
+ *  This program is free software; you can redistribute  it and/or modify it
+ *  under  the terms of  the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the  License, or (at your
+ *  option) any later version.
+ *
+ *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
+ *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
+ *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
+ *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
+ *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
+ *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *  You should have received a copy of the  GNU General Public License along
+ *  with this program; if not, write  to the Free Software Foundation, Inc.,
+ *  675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+
+#include <asm/addrspace.h>
+#include <asm/pci_channel.h>
+#include <asm/tx4927/tx4927_pci.h>
+#include <asm/debug.h>
+
+/* initialize in setup */
+struct resource pci_io_resource = {
+	"pci IO space",
+	(PCIBIOS_MIN_IO),
+	((PCIBIOS_MIN_IO) + (TX4927_PCIIO_SIZE)) - 1,
+	IORESOURCE_IO
+};
+
+/* initialize in setup */
+struct resource pci_mem_resource = {
+	"pci memory space",
+	TX4927_PCIMEM,
+	TX4927_PCIMEM + TX4927_PCIMEM_SIZE - 1,
+	IORESOURCE_MEM
+};
+
+extern struct pci_ops tx4927_pci_ops;
+
+/*
+ * h/w only supports devices 0x00 to 0x14
+ */
+struct pci_controller tx4927_controller = {
+	.pci_ops	= &tx4927_pci_ops,
+	.io_resource	= &pci_io_resource,
+	.mem_resource	= &pci_mem_resource,
+};
+
+static int mkaddr(unsigned char bus, unsigned char dev_fn,
+	unsigned char where, int *flagsp)
+{
+	if (bus > 0) {
+		/* Type 1 configuration */
+		tx4927_pcicptr->g2pcfgadrs = ((bus & 0xff) << 0x10) |
+		    ((dev_fn & 0xff) << 0x08) | (where & 0xfc) | 1;
+	} else {
+		if (dev_fn >= PCI_DEVFN(TX4927_PCIC_MAX_DEVNU, 0))
+			return -1;
+
+		/* Type 0 configuration */
+		tx4927_pcicptr->g2pcfgadrs = ((bus & 0xff) << 0x10) |
+		    ((dev_fn & 0xff) << 0x08) | (where & 0xfc);
+	}
+	/* clear M_ABORT and Disable M_ABORT Int. */
+	tx4927_pcicptr->pcistatus =
+	    (tx4927_pcicptr->pcistatus & 0x0000ffff) |
+	    (PCI_STATUS_REC_MASTER_ABORT << 16);
+	tx4927_pcicptr->pcimask &= ~PCI_STATUS_REC_MASTER_ABORT;
+	return 0;
+}
+
+static int check_abort(int flags)
+{
+	int code = PCIBIOS_SUCCESSFUL;
+	if (tx4927_pcicptr->
+	    pcistatus & (PCI_STATUS_REC_MASTER_ABORT << 16)) {
+		tx4927_pcicptr->pcistatus =
+		    (tx4927_pcicptr->
+		     pcistatus & 0x0000ffff) | (PCI_STATUS_REC_MASTER_ABORT
+						<< 16);
+		tx4927_pcicptr->pcimask |= PCI_STATUS_REC_MASTER_ABORT;
+		code = PCIBIOS_DEVICE_NOT_FOUND;
+	}
+	return code;
+}
+
+/*
+ * We can't address 8 and 16 bit words directly.  Instead we have to
+ * read/write a 32bit word and mask/modify the data we actually want.
+ */
+static int tx4927_pcibios_read_config_byte(struct pci_dev *dev,
+					   int where, unsigned char *val)
+{
+	int flags, retval;
+	unsigned char bus, func_num;
+
+	db_assert((where & 3) == 0);
+	db_assert(where < (1 << 8));
+
+	/* check if the bus is top-level */
+	if (dev->bus->parent != NULL) {
+		bus = dev->bus->number;
+		db_assert(bus != 0);
+	} else {
+		bus = 0;
+	}
+
+	func_num = PCI_FUNC(dev->devfn);
+	if (mkaddr(bus, dev->devfn, where, &flags))
+		return -1;
+#ifdef __BIG_ENDIAN
+	*val =
+	    *(volatile u8 *) ((ulong) & tx4927_pcicptr->
+			      g2pcfgdata | ((where & 3) ^ 3));
+#else
+	*val =
+	    *(volatile u8 *) ((ulong) & tx4927_pcicptr->
+			      g2pcfgdata | (where & 3));
+#endif
+	retval = check_abort(flags);
+	if (retval == PCIBIOS_DEVICE_NOT_FOUND)
+		*val = 0xff;
+	return retval;
+}
+
+static int tx4927_pcibios_read_config_word(struct pci_dev *dev,
+					   int where, unsigned short *val)
+{
+	int flags, retval;
+	unsigned char bus, func_num;
+
+	if (where & 1)
+		return PCIBIOS_BAD_REGISTER_NUMBER;
+
+	db_assert((where & 3) == 0);
+	db_assert(where < (1 << 8));
+
+	/* check if the bus is top-level */
+	if (dev->bus->parent != NULL) {
+		bus = dev->bus->number;
+		db_assert(bus != 0);
+	} else {
+		bus = 0;
+	}
+
+	func_num = PCI_FUNC(dev->devfn);
+	if (mkaddr(bus, dev->devfn, where, &flags))
+		return -1;
+#ifdef __BIG_ENDIAN
+	*val =
+	    *(volatile u16 *) ((ulong) & tx4927_pcicptr->
+			       g2pcfgdata | ((where & 3) ^ 2));
+#else
+	*val =
+	    *(volatile u16 *) ((ulong) & tx4927_pcicptr->
+			       g2pcfgdata | (where & 3));
+#endif
+	retval = check_abort(flags);
+	if (retval == PCIBIOS_DEVICE_NOT_FOUND)
+		*val = 0xffff;
+	return retval;
+}
+
+static int tx4927_pcibios_read_config_dword(struct pci_dev *dev,
+					    int where, unsigned int *val)
+{
+	int flags, retval;
+	unsigned char bus, func_num;
+
+	if (where & 3)
+		return PCIBIOS_BAD_REGISTER_NUMBER;
+
+	db_assert((where & 3) == 0);
+	db_assert(where < (1 << 8));
+
+	/* check if the bus is top-level */
+	if (dev->bus->parent != NULL) {
+		bus = dev->bus->number;
+		db_assert(bus != 0);
+	} else {
+		bus = 0;
+	}
+
+	func_num = PCI_FUNC(dev->devfn);
+	if (mkaddr(bus, dev->devfn, where, &flags))
+		return -1;
+	*val = tx4927_pcicptr->g2pcfgdata;
+	retval = check_abort(flags);
+	if (retval == PCIBIOS_DEVICE_NOT_FOUND)
+		*val = 0xffffffff;
+
+	return retval;
+}
+
+static int tx4927_pcibios_write_config_byte(struct pci_dev *dev,
+					    int where, unsigned char val)
+{
+	int flags;
+	unsigned char bus, func_num;
+
+	/* check if the bus is top-level */
+	if (dev->bus->parent != NULL) {
+		bus = dev->bus->number;
+		db_assert(bus != 0);
+	} else {
+		bus = 0;
+	}
+
+	func_num = PCI_FUNC(dev->devfn);
+	if (mkaddr(bus, dev->devfn, where, &flags))
+		return -1;
+#ifdef __BIG_ENDIAN
+	*(volatile u8 *) ((ulong) & tx4927_pcicptr->
+			  g2pcfgdata | ((where & 3) ^ 3)) = val;
+#else
+	*(volatile u8 *) ((ulong) & tx4927_pcicptr->
+			  g2pcfgdata | (where & 3)) = val;
+#endif
+	return check_abort(flags);
+}
+
+static int tx4927_pcibios_write_config_word(struct pci_dev *dev,
+					    int where, unsigned short val)
+{
+	int flags;
+	unsigned char bus, func_num;
+
+	if (where & 1)
+		return PCIBIOS_BAD_REGISTER_NUMBER;
+
+	/* check if the bus is top-level */
+	if (dev->bus->parent != NULL) {
+		bus = dev->bus->number;
+		db_assert(bus != 0);
+	} else {
+		bus = 0;
+	}
+
+	func_num = PCI_FUNC(dev->devfn);
+	if (mkaddr(bus, dev->devfn, where, &flags))
+		return -1;
+#ifdef __BIG_ENDIAN
+	*(volatile u16 *) ((ulong) & tx4927_pcicptr->
+			   g2pcfgdata | ((where & 3) ^ 2)) = val;
+#else
+	*(volatile u16 *) ((ulong) & tx4927_pcicptr->
+			   g2pcfgdata | (where & 3)) = val;
+#endif
+	return check_abort(flags);
+}
+
+static int tx4927_pcibios_write_config_dword(struct pci_dev *dev,
+					     int where, unsigned int val)
+{
+	int flags;
+	unsigned char bus, func_num;
+
+	if (where & 3)
+		return PCIBIOS_BAD_REGISTER_NUMBER;
+
+	/* check if the bus is top-level */
+	if (dev->bus->parent != NULL) {
+		bus = dev->bus->number;
+		db_assert(bus != 0);
+	} else {
+		bus = 0;
+	}
+
+	func_num = PCI_FUNC(dev->devfn);
+	if (mkaddr(bus, dev->devfn, where, &flags))
+		return -1;
+	tx4927_pcicptr->g2pcfgdata = val;
+	return check_abort(flags);
+}
+
+struct pci_ops tx4927_pci_ops = {
+	tx4927_pcibios_read_config_byte,
+	tx4927_pcibios_read_config_word,
+	tx4927_pcibios_read_config_dword,
+	tx4927_pcibios_write_config_byte,
+	tx4927_pcibios_write_config_word,
+	tx4927_pcibios_write_config_dword
+};
--- diff/arch/mips/pci/pci-ev96100.c	1970-01-01 01:00:00.000000000 +0100
+++ source/arch/mips/pci/pci-ev96100.c	2004-02-23 13:56:38.000000000 +0000
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2000 MontaVista Software Inc.
+ * Author: MontaVista Software, Inc.
+ *         	ppopov@mvista.com or source@mvista.com
+ *
+ * Carsten Langgaard, carstenl@mips.com
+ * Copyright (C) 1999,2000 MIPS Technologies, Inc.  All rights reserved.
+ *
+ *  This program is free software; you can redistribute  it and/or modify it
+ *  under  the terms of  the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the  License, or (at your
+ *  option) any later version.
+ *
+ *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
+ *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
+ *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
+ *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
+ *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
+ *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *  You should have received a copy of the  GNU General Public License along
+ *  with this program; if not, write  to the Free Software Foundation, Inc.,
+ *  675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+
+#include <asm/pci_channel.h>
+
+static struct resource pci_io_resource = {
+	.name	= "io pci IO space",
+	.start	= 0x10000000,
+	.end	= 0x11ffffff,
+	.flags	= IORESOURCE_IO
+};
+
+static struct resource pci_mem_resource = {
+	.name	= "ext pci memory space",
+	.start	= 0x12000000,
+	.end	= 0x13ffffff,
+	.flags	= IORESOURCE_MEM
+};
+
+extern struct pci_ops gt96100_pci_ops;
+
+struct pci_controller ev96100_controller = {
+	.pci_ops	= &gt96100_pci_ops,
+	.io_resource	= &pci_io_resource,
+	.mem_resource	= &pci_mem_resource,
+};
+
+static void ev96100_pci_init(void)
+{
+	register_pci_controller(&ev96100_controller);
+}
+
+arch_initcall(ev96100_pci_init);
--- diff/arch/mips/pci/pci-jmr3927.c	1970-01-01 01:00:00.000000000 +0100
+++ source/arch/mips/pci/pci-jmr3927.c	2004-02-23 13:56:38.000000000 +0000
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2001 MontaVista Software Inc.
+ * Author: MontaVista Software, Inc.
+ *              ahennessy@mvista.com
+ *
+ * Copyright (C) 2000-2001 Toshiba Corporation
+ *
+ *  This program is free software; you can redistribute  it and/or modify it
+ *  under  the terms of  the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the  License, or (at your
+ *  option) any later version.
+ *
+ *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
+ *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
+ *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
+ *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
+ *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
+ *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *  You should have received a copy of the  GNU General Public License along
+ *  with this program; if not, write  to the Free Software Foundation, Inc.,
+ *  675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+
+#include <asm/pci_channel.h>
+#include <asm/jmr3927/jmr3927.h>
+#include <asm/debug.h>
+
+struct resource pci_io_resource = {
+	"IO MEM",
+	0x1000,			/* reserve regacy I/O space */
+	0x1000 + JMR3927_PCIIO_SIZE - 1,
+	IORESOURCE_IO
+};
+
+struct resource pci_mem_resource = {
+	"PCI MEM",
+	JMR3927_PCIMEM,
+	JMR3927_PCIMEM + JMR3927_PCIMEM_SIZE - 1,
+	IORESOURCE_MEM
+};
+
+extern struct pci_ops jmr3927_pci_ops;
+
+struct pci_controller jmr3927_controller = {
+	.pci_ops	= &jmr3927_pci_ops,
+	.io_resource	= &pci_io_resource,
+	.mem_resource	= &pci_mem_resource,
+	.mem_offset	= JMR3927_PCIMEM;
+};
--- diff/arch/mips/pci/pci-ocelot.c	1970-01-01 01:00:00.000000000 +0100
+++ source/arch/mips/pci/pci-ocelot.c	2004-02-23 13:56:38.000000000 +0000
@@ -0,0 +1,107 @@
+/*
+ * BRIEF MODULE DESCRIPTION
+ * Galileo Evaluation Boards PCI support.
+ *
+ * The general-purpose functions to read/write and configure the GT64120A's
+ * PCI registers (function names start with pci0 or pci1) are either direct
+ * copies of functions written by Galileo Technology, or are modifications
+ * of their functions to work with Linux 2.4 vs Linux 2.2.  These functions
+ * are Copyright - Galileo Technology.
+ *
+ * Other functions are derived from other MIPS PCI implementations, or were
+ * written by RidgeRun, Inc,  Copyright (C) 2000 RidgeRun, Inc.
+ *   glonnon@ridgerun.com, skranz@ridgerun.com, stevej@ridgerun.com
+ *
+ * Copyright 2001 MontaVista Software Inc.
+ * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net
+ *
+ *  This program is free software; you can redistribute  it and/or modify it
+ *  under  the terms of  the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the  License, or (at your
+ *  option) any later version.
+ *
+ *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
+ *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
+ *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
+ *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
+ *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
+ *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *  You should have received a copy of the  GNU General Public License along
+ *  with this program; if not, write  to the Free Software Foundation, Inc.,
+ *  675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/cache.h>
+#include <asm/pci.h>
+#include <asm/io.h>
+#include <asm/gt64120.h>
+
+static inline unsigned int pci0ReadConfigReg(unsigned int offset)
+{
+	unsigned int DataForRegCf8;
+	unsigned int data;
+
+	DataForRegCf8 = ((PCI_SLOT(device->devfn) << 11) |
+			 (PCI_FUNC(device->devfn) << 8) |
+			 (offset & ~0x3)) | 0x80000000;
+	GT_WRITE(GT_PCI0_CFGADDR_OFS, DataForRegCf8);
+	GT_READ(GT_PCI0_CFGDATA_OFS, &data);
+
+	return data;
+}
+
+static inline void pci0WriteConfigReg(unsigned int offset, unsigned int data)
+{
+	unsigned int DataForRegCf8;
+
+	DataForRegCf8 = ((PCI_SLOT(device->devfn) << 11) |
+			 (PCI_FUNC(device->devfn) << 8) |
+			 (offset & ~0x3)) | 0x80000000;
+	GT_WRITE(GT_PCI0_CFGADDR_OFS, DataForRegCf8);
+	GT_WRITE(GT_PCI0_CFGDATA_OFS, data);
+}
+
+static struct resource ocelot_mem_resource = {
+	iomem_resource.start = GT_PCI_MEM_BASE;
+	iomem_resource.end = GT_PCI_MEM_BASE + GT_PCI_MEM_BASE - 1;
+};
+
+static struct resource ocelot_io_resource = {
+	ioport_resource.start = GT_PCI_IO_BASE;
+	ioport_resource.end = GT_PCI_IO_BASE + GT_PCI_IO_SIZE - 1;
+};
+
+static struct pci_controller ocelot_pci_controller = {
+	.pci_ops	= gt64120_pci_ops;
+	.mem_resource	= &ocelot_mem_resource;
+	.io_resource	= &ocelot_io_resource;
+};
+
+static int __init ocelot_pcibios_init(void)
+{
+	u32 tmp;
+
+	GT_READ(GT_PCI0_CMD_OFS, &tmp);
+	GT_READ(GT_PCI0_BARE_OFS, &tmp);
+
+	/*
+	 * You have to enable bus mastering to configure any other
+	 * card on the bus.
+	 */
+	tmp = pci0ReadConfigReg(PCI_COMMAND);
+	tmp |= PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER | PCI_COMMAND_SERR;
+	pci0WriteConfigReg(PCI_COMMAND, tmp);
+
+	register_pci_controller(&ocelot_pci_controller);
+}
+
+arch_initcall(ocelot_pcibios_init);
--- diff/arch/mips/pmc-sierra/yosemite/Makefile	1970-01-01 01:00:00.000000000 +0100
+++ source/arch/mips/pmc-sierra/yosemite/Makefile	2004-02-23 13:56:38.000000000 +0000
@@ -0,0 +1,8 @@
+#
+# Makefile for the PMC-Sierra Titan 
+#
+
+obj-y    += irq-handler.o irq.o i2c-yosemite.o prom.o setup.o
+
+obj-$(CONFIG_SMP)          	+= smp.o
+obj-$(CONFIG_HYPERTRANSPORT)	+= ht-irq.o ht.o
--- diff/arch/mips/pmc-sierra/yosemite/atmel_read_eeprom.c	1970-01-01 01:00:00.000000000 +0100
+++ source/arch/mips/pmc-sierra/yosemite/atmel_read_eeprom.c	2004-02-23 13:56:38.000000000 +0000
@@ -0,0 +1,171 @@
+/*
+ *  arch/mips/pmc-sierra/yosemite/atmel_read_eeprom.c
+ *
+ *  Copyright (C) 2003 PMC-Sierra Inc.
+ *  Author: Manish Lachwani (lachwani@pmc-sierra.com)
+ *
+ *  This program is free software; you can redistribute  it and/or modify it
+ *  under  the terms of  the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the  License, or (at your
+ *  option) any later version.
+ *
+ *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
+ *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
+ *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
+ *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
+ *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
+ *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *  You should have received a copy of the  GNU General Public License along
+ *  with this program; if not, write  to the Free Software Foundation, Inc.,
+ *  675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/*
+ * Description:
+ *
+ * This code reads the ATMEL 24CXX EEPROM. The PMC-Sierra Yosemite board uses the ATMEL
+ * 24C32/24C64 which uses two byte addressing as compared to 24C16. Note that this program
+ * uses the serial port like /dev/ttyS0, to communicate with the EEPROM. Hence, you are 
+ * expected to have a connectivity from the EEPROM to the serial port. This program does
+ * __not__ communicate using the I2C protocol
+ */
+
+#include "atmel_read_eeprom.h"
+
+static void delay(int delay)
+{
+	while (delay--);
+}
+
+static void send_bit(unsigned char bit)
+{
+	scl_lo;
+	delay(TXX);
+	if (bit)
+		sda_hi;
+	else
+		sda_lo;
+
+	delay(TXX);
+	scl_hi;
+	delay(TXX);
+}
+
+static void send_ack(void)
+{
+	send_bit(0);
+}
+
+static void send_byte(unsigned char byte)
+{
+	int	i = 0;
+	
+	for (i = 7; i >= 0; i--) 
+		send_bit((byte >> i) & 0x01);
+}
+	
+static void send_start(void)
+{
+	sda_hi; 
+	delay(TXX);
+	scl_hi;
+	delay(TXX);
+	sda_lo;
+	delay(TXX);
+}
+
+static void send_stop(void)
+{
+	sda_lo;
+	delay(TXX);
+	scl_hi;
+	delay(TXX);
+	sda_hi;
+	delay(TXX);
+}
+
+static void do_idle(void)
+{
+	sda_hi;
+	scl_hi;
+	vcc_off;
+}
+
+static int recv_bit(void)
+{
+	int	status;
+
+	scl_lo;
+	delay(TXX);
+	sda_hi;
+	delay(TXX);
+	scl_hi;
+	delay(TXX);
+
+	return 1;
+}
+
+static unsigned char recv_byte(void) {
+        int i;
+        unsigned char byte=0;
+
+        for (i=7;i>=0;i--)                             
+                byte |= (recv_bit() << i);
+ 
+        return byte;
+}
+
+static int recv_ack(void)
+{
+	unsigned int	ack;
+
+	ack = (unsigned int)recv_bit();
+	scl_lo;
+
+	if (ack) {
+		do_idle();
+		printk(KERN_ERR "Error reading the Atmel 24C32/24C64 EEPROM \n");
+		return -1;
+	}
+
+	return ack;
+}
+
+/*
+ * This function does the actual read of the EEPROM. It needs the buffer into which the
+ * read data is copied, the size of the EEPROM being read and the buffer size
+ */
+int read_eeprom(char *buffer, int eeprom_size, int size)
+{
+	int	i = 0, err;
+
+	send_start();
+	send_byte(W_HEADER);
+	recv_ack();
+
+	/* EEPROM with size of more then 2K need two byte addressing */
+	if (eeprom_size > 2048) {
+		send_byte(0x00);
+		recv_ack();
+	}
+
+	send_start();
+	send_byte(R_HEADER);
+	err = recv_ack();
+	if (err == -1)
+		return err;
+
+	for (i = 0; i < size; i++) {
+		*buffer++ = recv_byte();
+		send_ack();
+	}
+
+	/* Note : We should do some check if the buffer contains correct information */
+
+	send_stop();
+}
--- diff/arch/mips/pmc-sierra/yosemite/atmel_read_eeprom.h	1970-01-01 01:00:00.000000000 +0100
+++ source/arch/mips/pmc-sierra/yosemite/atmel_read_eeprom.h	2004-02-23 13:56:38.000000000 +0000
@@ -0,0 +1,69 @@
+/*
+ *  arch/mips/pmc-sierra/yosemite/atmel_read_eeprom.c
+ *
+ *  Copyright (C) 2003 PMC-Sierra Inc.
+ *  Author: Manish Lachwani (lachwani@pmc-sierra.com)
+ *
+ *  This program is free software; you can redistribute  it and/or modify it
+ *  under  the terms of  the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the  License, or (at your
+ *  option) any later version.
+ *
+ *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
+ *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
+ *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
+ *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
+ *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
+ *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *  You should have received a copy of the  GNU General Public License along
+ *  with this program; if not, write  to the Free Software Foundation, Inc.,
+ *  675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/*
+ * Header file for atmel_read_eeprom.c 
+ */
+
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/version.h>
+#include <asm/pci.h>
+#include <asm/io.h>
+#include <linux/init.h>
+#include <asm/termios.h>
+#include <asm/ioctls.h>
+#include <linux/ioctl.h>
+#include <linux/fcntl.h>
+
+#define	DEFAULT_PORT 	"/dev/ttyS0"	/* Port to open */
+#define	TXX		0 		/* Dummy loop for spinning */
+
+#define	BLOCK_SEL	0x00		
+#define	SLAVE_ADDR	0xa0
+#define	READ_BIT	0x01
+#define	WRITE_BIT	0x00
+#define	R_HEADER	SLAVE_ADDR + BLOCK_SEL + READ_BIT
+#define	W_HEADER	SLAVE_ADDR + BLOCK_SEL + WRITE_BIT
+
+/*
+ * Clock, Voltages and Data
+ */
+#define	vcc_off		(ioctl(fd, TIOCSBRK, 0))
+#define	vcc_on		(ioctl(fd, TIOCCBRK, 0))
+#define	sda_hi		(ioctl(fd, TIOCMBIS, &dtr))
+#define	sda_lo		(ioctl(fd, TIOCMBIC, &dtr))
+#define	scl_lo		(ioctl(fd, TIOCMBIC, &rts))
+#define	scl_hi		(ioctl(fd, TIOCMBIS, &rts))
+
+const char rts = TIOCM_RTS;
+const char dtr = TIOCM_DTR;
+int fd;
+
--- diff/arch/mips/pmc-sierra/yosemite/ht-irq.c	1970-01-01 01:00:00.000000000 +0100
+++ source/arch/mips/pmc-sierra/yosemite/ht-irq.c	2004-02-23 13:56:38.000000000 +0000
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2003 PMC-Sierra
+ * Author: Manish Lachwani (lachwani@pmc-sierra.com)
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ *
+ *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
+ *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
+ *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
+ *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
+ *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
+ *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *  You should have received a copy of the  GNU General Public License along
+ *  with this program; if not, write  to the Free Software Foundation, Inc.,
+ *  675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <linux/kernel.h>
+#include <linux/version.h>
+#include <linux/init.h>
+#include <asm/pci.h>
+
+/*
+ * HT Bus fixup for the Titan
+ * XXX IRQ values need to change based on the board layout
+ */
+void __init titan_ht_pcibios_fixup_bus(struct pci_bus *bus)
+{
+        struct pci_bus *current_bus = bus;
+        struct pci_dev *devices;
+        struct list_head *devices_link;
+
+	list_for_each(devices_link, &(current_bus->devices)) {
+                devices = pci_dev_b(devices_link);
+                if (devices == NULL)
+                        continue;
+	}
+
+	/*
+	 * PLX and SPKT related changes go here
+	 */
+
+}
--- diff/arch/mips/pmc-sierra/yosemite/ht.c	1970-01-01 01:00:00.000000000 +0100
+++ source/arch/mips/pmc-sierra/yosemite/ht.c	2004-02-23 13:56:38.000000000 +0000
@@ -0,0 +1,459 @@
+/*
+ * Copyright 2003 PMC-Sierra
+ * Author: Manish Lachwani (lachwani@pmc-sierra.com)
+ *
+ *  This program is free software; you can redistribute  it and/or modify it
+ *  under  the terms of  the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the  License, or (at your
+ *  option) any later version.
+ *
+ *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
+ *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
+ *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
+ *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
+ *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
+ *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *  You should have received a copy of the  GNU General Public License along
+ *  with this program; if not, write  to the Free Software Foundation, Inc.,
+ *  675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/version.h>
+#include <asm/pci.h>
+#include <asm/io.h>
+
+#include <linux/init.h>
+#include <asm/titan_dep.h>
+
+#ifdef CONFIG_HYPERTRANSPORT
+
+
+/*
+ * This function check if the Hypertransport Link Initialization completed. If
+ * it did, then proceed further with scanning bus #2
+ */
+static __inline__ int check_titan_htlink(void)
+{
+        u32 val;
+
+        val = *(volatile u_int32_t *)(RM9000x2_HTLINK_REG);
+        if (val & 0x00000020)
+                /* HT Link Initialization completed */
+                return 1;
+        else
+                return 0;
+}
+
+static int titan_ht_config_read_dword(struct pci_dev *device,
+                                             int offset, u32* val)
+{
+        int dev, bus, func;
+        uint32_t address_reg, data_reg;
+        uint32_t address;
+
+        bus = device->bus->number;
+        dev = PCI_SLOT(device->devfn);
+        func = PCI_FUNC(device->devfn);
+
+	/* XXX Need to change the Bus # */
+        if (bus > 2)
+                address = (bus << 16) | (dev << 11) | (func << 8) | (offset & 0xfc) |
+                                                        0x80000000 | 0x1;
+        else
+                address = (dev << 11) | (func << 8) | (offset & 0xfc) | 0x80000000;
+
+        address_reg = RM9000x2_OCD_HTCFGA;
+        data_reg =  RM9000x2_OCD_HTCFGD;
+
+        RM9K_WRITE(address_reg, address);
+        RM9K_READ(data_reg, val);
+
+        return PCIBIOS_SUCCESSFUL;
+}
+
+
+static int titan_ht_config_read_word(struct pci_dev *device,
+                                             int offset, u16* val)
+{
+        int dev, bus, func;
+        uint32_t address_reg, data_reg;
+        uint32_t address;
+
+        bus = device->bus->number;
+        dev = PCI_SLOT(device->devfn);
+        func = PCI_FUNC(device->devfn);
+
+	/* XXX Need to change the Bus # */
+        if (bus > 2)
+                address = (bus << 16) | (dev << 11) | (func << 8) | (offset & 0xfc) |
+                                                0x80000000 | 0x1;
+        else
+                address = (dev << 11) | (func << 8) | (offset & 0xfc) | 0x80000000;
+
+        address_reg = RM9000x2_OCD_HTCFGA;
+        data_reg =  RM9000x2_OCD_HTCFGD;
+
+        if ((offset & 0x3) == 0)
+                offset = 0x2;
+        else
+                offset = 0x0;
+
+        RM9K_WRITE(address_reg, address);
+        RM9K_READ_16(data_reg + offset, val);
+
+        return PCIBIOS_SUCCESSFUL;
+}
+
+
+u32 longswap(unsigned long l)
+{
+        unsigned char b1,b2,b3,b4;
+
+        b1 = l&255;
+        b2 = (l>>8)&255;
+        b3 = (l>>16)&255;
+        b4 = (l>>24)&255;
+
+        return ((b1<<24) + (b2<<16) + (b3<<8) + b4);
+}
+
+
+static int titan_ht_config_read_byte(struct pci_dev *device,
+                                             int offset, u8* val)
+{
+        int dev, bus, func;
+        uint32_t address_reg, data_reg;
+        uint32_t address;
+        int offset1;
+
+        bus = device->bus->number;
+        dev = PCI_SLOT(device->devfn);
+        func = PCI_FUNC(device->devfn);
+
+	/* XXX Need to change the Bus # */
+        if (bus > 2)
+                address = (bus << 16) | (dev << 11) | (func << 8) | (offset & 0xfc) |
+                                                        0x80000000 | 0x1;
+        else
+                address = (dev << 11) | (func << 8) | (offset & 0xfc) | 0x80000000;
+
+        address_reg = RM9000x2_OCD_HTCFGA;
+        data_reg =  RM9000x2_OCD_HTCFGD;
+
+        RM9K_WRITE(address_reg, address);
+
+        if ((offset & 0x3) == 0) {
+                offset1 = 0x3;
+        }
+        if ((offset & 0x3) == 1) {
+                offset1 = 0x2;
+        }
+        if ((offset & 0x3) == 2) {
+                offset1 = 0x1;
+        }
+        if ((offset & 0x3) == 3) {
+                offset1 = 0x0;
+        }
+        RM9K_READ_8(data_reg + offset1, val);
+
+        return PCIBIOS_SUCCESSFUL;
+}
+
+
+static int titan_ht_config_write_dword(struct pci_dev *device,
+                                             int offset, u8 val)
+{
+        int dev, bus, func;
+        uint32_t address_reg, data_reg;
+        uint32_t address;
+
+        bus = device->bus->number;
+        dev = PCI_SLOT(device->devfn);
+        func = PCI_FUNC(device->devfn);
+
+	/* XXX Need to change the Bus # */
+        if (bus > 2)
+                address = (bus << 16) | (dev << 11) | (func << 8) | (offset & 0xfc) |
+                                                        0x80000000 | 0x1;
+        else
+              address = (dev << 11) | (func << 8) | (offset & 0xfc) | 0x80000000;
+
+        address_reg = RM9000x2_OCD_HTCFGA;
+        data_reg =  RM9000x2_OCD_HTCFGD;
+
+        RM9K_WRITE(address_reg, address);
+        RM9K_WRITE(data_reg, val);
+
+        return PCIBIOS_SUCCESSFUL;
+}
+
+static int titan_ht_config_write_word(struct pci_dev *device,
+                                             int offset, u8 val)
+{
+        int dev, bus, func;
+        uint32_t address_reg, data_reg;
+        uint32_t address;
+
+        bus = device->bus->number;
+        dev = PCI_SLOT(device->devfn);
+        func = PCI_FUNC(device->devfn);
+
+	/* XXX Need to change the Bus # */
+        if (bus > 2)
+                address = (bus << 16) | (dev << 11) | (func << 8) | (offset & 0xfc) |
+                                0x80000000 | 0x1;
+        else
+                address = (dev << 11) | (func << 8) | (offset & 0xfc) | 0x80000000;
+
+        address_reg = RM9000x2_OCD_HTCFGA;
+        data_reg =  RM9000x2_OCD_HTCFGD;
+
+        if ((offset & 0x3) == 0)
+                offset = 0x2;
+        else
+                offset = 0x0;
+
+        RM9K_WRITE(address_reg, address);
+        RM9K_WRITE_16(data_reg + offset, val);
+
+        return PCIBIOS_SUCCESSFUL;
+}
+
+static int titan_ht_config_write_byte(struct pci_dev *device,
+                                             int offset, u8 val)
+{
+        int dev, bus, func;
+        uint32_t address_reg, data_reg;
+        uint32_t address;
+        int offset1;
+
+        bus = device->bus->number;
+        dev = PCI_SLOT(device->devfn);
+        func = PCI_FUNC(device->devfn);
+
+	/* XXX Need to change the Bus # */
+        if (bus > 2)
+                address = (bus << 16) | (dev << 11) | (func << 8) | (offset & 0xfc) |
+                                0x80000000 | 0x1;
+        else
+                address = (dev << 11) | (func << 8) | (offset & 0xfc) | 0x80000000;
+
+        address_reg = RM9000x2_OCD_HTCFGA;
+        data_reg =  RM9000x2_OCD_HTCFGD;
+
+        RM9K_WRITE(address_reg, address);
+
+        if ((offset & 0x3) == 0) {
+             offset1 = 0x3;
+        }
+        if ((offset & 0x3) == 1) {
+             offset1 = 0x2;
+        }
+        if ((offset & 0x3) == 2) {
+             offset1 = 0x1;
+        }
+        if ((offset & 0x3) == 3) {
+            offset1 = 0x0;
+        }
+
+        RM9K_WRITE_8(data_reg + offset1, val);
+        return PCIBIOS_SUCCESSFUL;
+}
+
+
+static void titan_pcibios_set_master(struct pci_dev *dev)
+{
+        u16 cmd;
+        int bus = dev->bus->number;
+
+	if (check_titan_htlink())
+            titan_ht_config_read_word(dev, PCI_COMMAND, &cmd);
+
+	cmd |= PCI_COMMAND_MASTER;
+
+	if (check_titan_htlink())
+            titan_ht_config_write_word(dev, PCI_COMMAND, cmd);
+}
+
+
+int pcibios_enable_resources(struct pci_dev *dev)
+{
+        u16 cmd, old_cmd;
+        u8 tmp1;
+        int idx;
+        struct resource *r;
+        int bus = dev->bus->number;
+
+	if (check_titan_htlink())
+            titan_ht_config_read_word(dev, PCI_COMMAND, &cmd);
+
+	old_cmd = cmd;
+        for (idx = 0; idx < 6; idx++) {
+                r = &dev->resource[idx];
+                if (!r->start && r->end) {
+                        printk(KERN_ERR
+                               "PCI: Device %s not available because of "
+                               "resource collisions\n", dev->slot_name);
+                        return -EINVAL;
+                }
+                if (r->flags & IORESOURCE_IO)
+                        cmd |= PCI_COMMAND_IO;
+                if (r->flags & IORESOURCE_MEM)
+                        cmd |= PCI_COMMAND_MEMORY;
+        }
+        if (cmd != old_cmd) {
+		if (check_titan_htlink())
+                   titan_ht_config_write_word(dev, PCI_COMMAND, cmd);
+	}
+
+	if (check_titan_htlink())
+		titan_ht_config_read_byte(dev, PCI_CACHE_LINE_SIZE, &tmp1);
+
+	if (tmp1 != 8) {
+                printk(KERN_WARNING "PCI setting cache line size to 8 from "
+                       "%d\n", tmp1);
+	}
+
+	if (check_titan_htlink())
+		titan_ht_config_write_byte(dev, PCI_CACHE_LINE_SIZE, 8);
+
+	if (check_titan_htlink())
+		titan_ht_config_read_byte(dev, PCI_LATENCY_TIMER, &tmp1);
+
+	if (tmp1 < 32 || tmp1 == 0xff) {
+                printk(KERN_WARNING "PCI setting latency timer to 32 from %d\n",
+                       tmp1);
+	}
+
+	if (check_titan_htlink())
+		titan_ht_config_write_byte(dev, PCI_LATENCY_TIMER, 32);
+
+	return 0;
+}
+
+
+int pcibios_enable_device(struct pci_dev *dev, int mask)
+{
+        return pcibios_enable_resources(dev);
+}
+
+
+
+void pcibios_update_resource(struct pci_dev *dev, struct resource *root,
+                             struct resource *res, int resource)
+{
+        u32 new, check;
+        int reg;
+
+        return;
+
+        new = res->start | (res->flags & PCI_REGION_FLAG_MASK);
+        if (resource < 6) {
+                reg = PCI_BASE_ADDRESS_0 + 4 * resource;
+        } else if (resource == PCI_ROM_RESOURCE) {
+                res->flags |= PCI_ROM_ADDRESS_ENABLE;
+                reg = dev->rom_base_reg;
+        } else {
+                /*
+                 * Somebody might have asked allocation of a non-standard
+                 * resource
+                 */
+                return;
+        }
+
+        pci_write_config_dword(dev, reg, new);
+        pci_read_config_dword(dev, reg, &check);
+        if ((new ^ check) &
+            ((new & PCI_BASE_ADDRESS_SPACE_IO) ? PCI_BASE_ADDRESS_IO_MASK :
+             PCI_BASE_ADDRESS_MEM_MASK)) {
+                printk(KERN_ERR "PCI: Error while updating region "
+                       "%s/%d (%08x != %08x)\n", dev->slot_name, resource,
+                       new, check);
+        }
+}
+
+
+void pcibios_align_resource(void *data, struct resource *res,
+                            unsigned long size, unsigned long align)
+{
+        struct pci_dev *dev = data;
+
+        if (res->flags & IORESOURCE_IO) {
+                unsigned long start = res->start;
+
+                /* We need to avoid collisions with `mirrored' VGA ports
+                   and other strange ISA hardware, so we always want the
+                   addresses kilobyte aligned.  */
+                if (size > 0x100) {
+                        printk(KERN_ERR "PCI: I/O Region %s/%d too large"
+                               " (%ld bytes)\n", dev->slot_name,
+                                dev->resource - res, size);
+                }
+
+                start = (start + 1024 - 1) & ~(1024 - 1);
+                res->start = start;
+        }
+}
+
+struct pci_ops titan_pci_ops = {
+        titan_ht_config_read_byte,
+        titan_ht_config_read_word,
+        titan_ht_config_read_dword,
+        titan_ht_config_write_byte,
+        titan_ht_config_write_word,
+        titan_ht_config_write_dword
+};
+
+
+struct pci_fixup pcibios_fixups[] = {
+        {0}
+};
+
+void __init pcibios_fixup_bus(struct pci_bus *c)
+{
+        titan_ht_pcibios_fixup_bus(c);
+}
+
+void __init pcibios_init(void)
+{
+
+        /* Reset PCI I/O and PCI MEM values */
+	/* XXX Need to add the proper values here */
+        ioport_resource.start = 0xe0000000;
+        ioport_resource.end   = 0xe0000000 + 0x20000000 - 1;
+        iomem_resource.start  = 0xc0000000;
+        iomem_resource.end    = 0xc0000000 + 0x20000000 - 1;
+
+	/* XXX Need to add bus values */
+        pci_scan_bus(2, &titan_pci_ops, NULL);
+        pci_scan_bus(3, &titan_pci_ops, NULL);
+}
+
+/*
+ * for parsing "pci=" kernel boot arguments.
+ */
+char *pcibios_setup(char *str)
+{
+        printk(KERN_INFO "rr: pcibios_setup\n");
+        /* Nothing to do for now.  */
+
+        return str;
+}
+
+unsigned __init int pcibios_assign_all_busses(void)
+{
+        /* We want to use the PCI bus detection done by PMON */
+        return 0;
+}
+
+#endif /* CONFIG_HYPERTRANSPORT */
--- diff/arch/mips/pmc-sierra/yosemite/i2c-yosemite.c	1970-01-01 01:00:00.000000000 +0100
+++ source/arch/mips/pmc-sierra/yosemite/i2c-yosemite.c	2004-02-23 13:56:38.000000000 +0000
@@ -0,0 +1,186 @@
+/*
+ *  arch/mips/pmc-sierra/yosemite/i2c-yosemite.c
+ *
+ *  Copyright (C) 2003 PMC-Sierra Inc.
+ *  Author: Manish Lachwani (lachwani@pmc-sierra.com)
+ *
+ *  This program is free software; you can redistribute  it and/or modify it
+ *  under  the terms of  the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the  License, or (at your
+ *  option) any later version.
+ *
+ *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
+ *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
+ *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
+ *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
+ *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
+ *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *  You should have received a copy of the  GNU General Public License along
+ *  with this program; if not, write  to the Free Software Foundation, Inc.,
+ *  675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/*
+ * Detailed Description:
+ *
+ * This block implements the I2C interface to the slave devices like the Atmel 24C32
+ * EEPROM and the MAX 1619 Sensors device. The I2C Master interface can be controlled
+ * by the SCMB block. And the SCMB block kicks in only when using the Ethernet Mode of
+ * operation and __not__ the SysAD mode
+ *
+ * The SCMB controls the two modes: MDIO and the I2C. The MDIO mode is used to communicate
+ * with the Quad-PHY from Marvel. The I2C is used to communicate with the I2C slave devices.
+ * It seems that the driver does not explicitly deal with the control of SDA and SCL serial
+ * lines. So, the driver will set the slave address, drive the command and then the data. 
+ * The SCMB will then control the two serial lines as required. 
+ *
+ * It seems the documents are very unclear abt this. Hence, I took some time out to write
+ * the desciption to have an idea of how the I2C can actually work. Currently, this Linux 
+ * driver wont be integrated into the generic Linux I2C framework. And finally, the I2C 
+ * interface is also known as the 2BI interface. 2BI means 2-bit interface referring to
+ * SDA and SCL serial lines respectively.
+ *
+ * - Manish Lachwani (12/09/2003)
+ */
+
+#include "i2c-yosemite.h"
+
+/*
+ * Poll the I2C interface for the BUSY bit. 
+ */
+static int titan_i2c_poll(void)
+{
+	int		i = 0;
+	unsigned long	val = 0;
+
+	for (i = 0; i < TITAN_I2C_MAX_POLL; i++) {
+		val = TITAN_I2C_READ(TITAN_I2C_COMMAND);
+
+		if ( !(val & 0x8000))
+			return 0;
+	}
+
+	return TITAN_I2C_ERR_TIMEOUT;
+}
+
+/*
+ * Execute the I2C command
+ */
+int titan_i2c_xfer(unsigned int slave_addr, titan_i2c_command *cmd, 
+						int size, unsigned int *addr)
+{
+	int		loop = 0, bytes, i;
+	unsigned int	*write_data, data, *read_data;
+	unsigned long	reg_val, val;
+
+	write_data = cmd->data;
+	read_data = addr;
+
+	TITAN_I2C_WRITE(TITAN_I2C_SLAVE_ADDRESS, slave_addr);
+
+	if (cmd->type == TITAN_I2C_CMD_WRITE) 
+		loop = cmd->write_size;
+	else
+		loop = size;
+
+	while (loop > 0) {
+		if ( (cmd->type == TITAN_I2C_CMD_WRITE)  || 
+			(cmd->type == TITAN_I2C_CMD_READ_WRITE) ) {
+			
+			reg_val = TITAN_I2C_DATA;
+			for (i = 0; i < TITAN_I2C_MAX_WORDS_PER_RW; ++i,write_data += 2,
+								reg_val += 4) {
+				if (bytes < cmd->write_size) {
+					data = write_data[0];
+					++data;
+				}
+
+				if (bytes < cmd->write_size) {
+					data = write_data[1];
+					++data;
+				}
+
+				TITAN_I2C_WRITE(reg_val, data);
+			}
+		}
+
+		TITAN_I2C_WRITE(TITAN_I2C_COMMAND, (unsigned int)(cmd->type << 13));
+		if (titan_i2c_poll() != TITAN_I2C_ERR_OK)
+			return TITAN_I2C_ERR_TIMEOUT;
+
+		if ( (cmd->type == TITAN_I2C_CMD_READ)  ||
+			(cmd->type == TITAN_I2C_CMD_READ_WRITE) ) {
+			
+			reg_val = TITAN_I2C_DATA;
+			for (i = 0; i < TITAN_I2C_MAX_WORDS_PER_RW; ++i,read_data += 2,
+								reg_val += 4) {
+				data = TITAN_I2C_READ(reg_val);
+				
+				if (bytes < size) {
+					read_data[0] = data & 0xff;
+					++bytes;
+				}
+
+				if (bytes < size) {
+					read_data[1] = ((data >> 8) & 0xff);
+					++bytes;
+				}
+			}
+		}
+
+		loop -= (TITAN_I2C_MAX_WORDS_PER_RW * 2);
+	}
+						
+	/*
+	 * Read the Interrupt status and then return the appropriate error code 
+	 */
+
+	val = TITAN_I2C_READ(TITAN_I2C_INTERRUPTS);
+	if (val & 0x0020)
+		return TITAN_I2C_ERR_ARB_LOST;
+
+	if (val & 0x0040)
+		return TITAN_I2C_ERR_NO_RESP;
+
+	if (val & 0x0080)
+		return TITAN_I2C_ERR_DATA_COLLISION;
+
+	return TITAN_I2C_ERR_OK;
+}
+
+/*
+ * Init the I2C subsystem of the PMC-Sierra Yosemite board
+ */
+int titan_i2c_init(titan_i2c_config *config)
+{
+	unsigned int	val;
+
+	/*
+	 * Reset the SCMB and program into the I2C mode
+	 */
+	TITAN_I2C_WRITE(TITAN_I2C_SCMB_CONTROL, 0xA000);
+	TITAN_I2C_WRITE(TITAN_I2C_SCMB_CONTROL, 0x2000);
+
+	/*
+	 * Configure the filtera and clka values
+	 */
+	val = TITAN_I2C_READ(TITAN_I2C_SCMB_CLOCK_A);
+	val |= ( (val & ~(0xF000)) | ( (config->filtera << 12) & 0xF000));
+	val |= ( (val & ~(0x03FF)) | ( config->clka & 0x03FF));
+	TITAN_I2C_WRITE(TITAN_I2C_SCMB_CLOCK_A, val);
+
+	/*
+	 * Configure the filterb and clkb values
+	 */
+	val = TITAN_I2C_READ(TITAN_I2C_SCMB_CLOCK_B);
+	val |= ( (val & ~(0xF000)) | ( (config->filterb << 12) & 0xF000));
+	val |= ( (val & ~(0x03FF)) | ( config->clkb & 0x03FF));
+	TITAN_I2C_WRITE(TITAN_I2C_SCMB_CLOCK_B, val);
+
+	return TITAN_I2C_ERR_OK;
+}
--- diff/arch/mips/pmc-sierra/yosemite/i2c-yosemite.h	1970-01-01 01:00:00.000000000 +0100
+++ source/arch/mips/pmc-sierra/yosemite/i2c-yosemite.h	2004-02-23 13:56:38.000000000 +0000
@@ -0,0 +1,96 @@
+/*
+ *  arch/mips/pmc-sierra/yosemite/i2c-yosemite.h
+ *
+ *  Copyright (C) 2003 PMC-Sierra Inc.
+ *  Author: Manish Lachwani (lachwani@pmc-sierra.com)
+ *
+ *  This program is free software; you can redistribute  it and/or modify it
+ *  under  the terms of  the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the  License, or (at your
+ *  option) any later version.
+ *
+ *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
+ *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
+ *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
+ *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
+ *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
+ *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *  You should have received a copy of the  GNU General Public License along
+ *  with this program; if not, write  to the Free Software Foundation, Inc.,
+ *  675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef __I2C_YOSEMITE_H
+#define __I2C_YOSEMITE_H
+
+/* Read and Write operations to the chip */
+
+#define TITAN_I2C_BASE			0xbb000000	/* XXX Needs to change */
+	
+#define	TITAN_I2C_WRITE(offset, data)	\
+					*(volatile unsigned long *)(TITAN_I2C_BASE + offset) = data
+
+#define	TITAN_I2C_READ(offset) *(volatile unsigned long *)(TITAN_I2C_BASE + offset)
+
+
+/* Local constansts*/
+#define TITAN_I2C_MAX_FILTER            15
+#define TITAN_I2C_MAX_CLK               1023
+#define TITAN_I2C_MAX_ARBF              15
+#define TITAN_I2C_MAX_NAK               15
+#define TITAN_I2C_MAX_MASTERCODE        7
+#define TITAN_I2C_MAX_WORDS_PER_RW      4
+#define TITAN_I2C_MAX_POLL		100
+
+/* Registers used for I2C work */
+#define TITAN_I2C_SCMB_CONTROL		0x0180  /* SCMB Control */
+#define TITAN_I2C_SCMB_CLOCK_A		0x0184  /* SCMB Clock A */
+#define TITAN_I2C_SCMB_CLOCK_B		0x0188  /* SCMB Clock B */
+#define	TITAN_I2C_CONFIG		0x01A0  /* I2C Config */
+#define TITAN_I2C_COMMAND		0x01A4  /* I2C Command */
+#define	TITAN_I2C_SLAVE_ADDRESS		0x01A8	/* I2C Slave Address */
+#define TITAN_I2C_DATA			0x01AC  /* I2C Data [15:0] */
+#define TITAN_I2C_INTERRUPTS		0x01BC  /* I2C Interrupts */
+
+/* Error */
+#define	TITAN_I2C_ERR_ARB_LOST		(-9220)
+#define	TITAN_I2C_ERR_NO_RESP		(-9221)
+#define	TITAN_I2C_ERR_DATA_COLLISION	(-9222)
+#define	TITAN_I2C_ERR_TIMEOUT		(-9223)
+#define	TITAN_I2C_ERR_OK		0
+
+/* I2C Command Type */
+typedef enum {
+	TITAN_I2C_CMD_WRITE		= 0,
+	TITAN_I2C_CMD_READ		= 1,
+	TITAN_I2C_CMD_READ_WRITE	= 2
+} titan_i2c_cmd_type;
+
+/* I2C structures */
+typedef struct {
+	int	filtera; 		/* Register 0x0184, bits 15 - 12*/
+	int	clka;			/* Register 0x0184, bits 9 - 0 */
+	int	filterb;		/* Register 0x0188, bits 15 - 12 */
+	int	clkb;			/* Register 0x0188, bits 9 - 0 */
+} titan_i2c_config;
+
+/* I2C command type */
+typedef struct {
+	titan_i2c_cmd_type	type;		/* Type of command */
+	int			num_arb;	/* Register 0x01a0, bits 15 - 12 */
+	int			num_nak;	/* Register 0x01a0, bits 11 - 8 */
+	int			addr_size;	/* Register 0x01a0, bit 7 */
+	int			mst_code;	/* Register 0x01a0, bits 6 - 4 */
+	int			arb_en;		/* Register 0x01a0, bit 1 */
+	int			speed;		/* Register 0x01a0, bit 0 */
+	int			slave_addr;	/* Register 0x01a8 */
+	int			write_size;	/* Register 0x01a4, bits 10 - 8 */
+	unsigned int		*data;		/* Register 0x01ac */
+} titan_i2c_command;
+
+#endif /* __I2C_YOSEMITE_H */ 
--- diff/arch/mips/pmc-sierra/yosemite/irq-handler.S	1970-01-01 01:00:00.000000000 +0100
+++ source/arch/mips/pmc-sierra/yosemite/irq-handler.S	2004-02-23 13:56:38.000000000 +0000
@@ -0,0 +1,125 @@
+/*
+ * Copyright 2003 PMC-Sierra Inc.
+ * Author: Manish Lachwani (lachwani@pmc-sierra.com
+ *
+ * First-level interrupt router for the PMC-Sierra Titan board
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+
+#include <linux/config.h>
+#include <asm/asm.h>
+#include <asm/mipsregs.h>
+#include <asm/addrspace.h>
+#include <asm/regdef.h>
+#include <asm/stackframe.h>
+
+/*
+ * IRQ router for the Titan board
+ */
+
+		.align	5
+		NESTED(titan_handle_int, PT_SIZE, sp)
+		SAVE_ALL
+		CLI
+		.set	at
+		mfc0	t0, CP0_CAUSE
+		mfc0	t2, CP0_STATUS
+
+		and	t0, t2
+	
+		andi	t1, t0, STATUSF_IP0	/* INTB0 hardware line */
+		bnez	t1, ll_pcia_irq		/* 64-bit PCI */
+		andi	t1, t0, STATUSF_IP1	/* INTB1 hardware line */
+		bnez	t1, ll_pcib_irq		/* second 64-bit PCI slot */
+		andi	t1, t0, STATUSF_IP2	/* INTB2 hardware line */
+		bnez	t1, ll_duart_irq	/* UART	*/
+		andi	t1, t0, STATUSF_IP3	/* INTB3 hardware line*/
+		bnez	t1, ll_ht_smp_irq		/* Hypertransport */
+		andi	t1, t0, STATUSF_IP5	/* INTB5 hardware line */
+		bnez	t1, ll_timer_irq	/* Timer */
+
+		nop
+		nop
+
+		/* Extended interrupts */
+		mfc0	t0, CPU_CAUSE
+		cfc0	t1, CP0_S1_INTCONTROL
+
+		sll	t2, t1, 8
+		
+		and	t0, t2
+		srl	t0, t0, 16
+
+		
+		andi	t1, t0, STATUSF_IP6	/* INTB6 hardware line */
+		bnez	t1, ll_phy0_irq		/* Ethernet port 0 */
+		andi	t1, t0, STATUSF_IP7	/* INTB7 hardware line */
+		bnez	t1, ll_phy1_irq		/* Ethernet port 1 */
+		andi	t1, t0, STATUSF_IP8	/* INTB8 hardware line */
+		bnez	t1, ll_phy2_irq		/* Ethernet Port 2 */
+
+		nop
+		nop
+
+		.set	reorder
+
+		/* No handler */
+		j	spurious_interrupt
+		nop
+		END(titan_handle_int)
+
+		.align	5
+
+/* Individual Handlers */
+
+ll_pcia_irq:
+		li	a0, 1
+		move	a2, sp
+		jal	do_IRQ
+		j	ret_from_irq
+
+ll_pcib_irq:
+		li      a0, 2
+                move    a1, sp
+                jal     do_IRQ
+                j       ret_from_irq
+
+ll_duart_irq:
+		li	a0, 3
+		move	a1, sp
+		jal	do_IRQ
+		j	ret_from_irq
+
+ll_ht_irq:
+		li	a0, 4
+		move	a1, sp
+		jal	ll_ht_smp_irq_handler 	/* Detailed HT & SMP IRQ handling */
+		j	ret_from_irq
+
+ll_timer_irq:
+		li	a0, 5
+		move	a1, sp
+		jal	do_IRQ
+		j	ret_from_irq
+
+ll_phy0_irq:
+		li	a0, 6
+		move	a1, sp
+		jal	do_IRQ
+		j	ret_from_irq	
+
+ll_phy1_irq:
+		li	a0, 7
+		move	a1, sp
+		jal	do_IRQ
+		j	ret_from_irq
+
+ll_phy2_irq:
+		li	a0, 8
+		move	a1, sp
+		jal	do_IRQ
+		j	ret_from_irq
--- diff/arch/mips/pmc-sierra/yosemite/irq.c	1970-01-01 01:00:00.000000000 +0100
+++ source/arch/mips/pmc-sierra/yosemite/irq.c	2004-02-23 13:56:38.000000000 +0000
@@ -0,0 +1,247 @@
+/*
+ * Copyright (C) 2003 PMC-Sierra Inc.
+ * Author: Manish Lachwani (lachwani@pmc-sierra.com)
+ *
+ *  This program is free software; you can redistribute  it and/or modify it
+ *  under  the terms of  the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the  License, or (at your
+ *  option) any later version.
+ *
+ *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
+ *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
+ *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
+ *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
+ *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
+ *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *  You should have received a copy of the  GNU General Public License along
+ *  with this program; if not, write  to the Free Software Foundation, Inc.,
+ *  675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Second level Interrupt handlers for the PMC-Sierra Titan/Yosemite board
+ */
+
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/kernel_stat.h>
+#include <linux/module.h>
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/types.h>
+#include <linux/interrupt.h>
+#include <linux/ioport.h>
+#include <linux/timex.h>
+#include <linux/slab.h>
+#include <linux/random.h>
+#include <asm/bitops.h>
+#include <asm/bootinfo.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/mipsregs.h>
+#include <asm/system.h>
+
+/* Hypertransport specific */
+#define IRQ_STATUS_REG_CPU0     0xbb001b30 	/* INT# 3 status register on CPU 0*/
+#define	IRQ_STATUS_REG_CPU1	0xbb002b30	/* INT# 3 status register on CPU 1*/
+#define IRQ_ACK_BITS            0x00000000 	/* Ack bits */
+#define IRQ_CLEAR_REG_CPU0      0xbb002b3c 	/* IRQ clear register on CPU 0*/
+#define IRQ_CLEAR_REG_CPU0      0xbb002b3c      /* IRQ clear register on CPU 1*/
+
+#define HYPERTRANSPORT_EOI      0xbb0006E0 	/* End of Interrupt */
+#define HYPERTRANSPORT_INTA     0x78    	/* INTA# */
+#define HYPERTRANSPORT_INTB     0x79    	/* INTB# */
+#define HYPERTRANSPORT_INTC     0x7a    	/* INTC# */
+#define HYPERTRANSPORT_INTD     0x7b    	/* INTD# */
+
+#define read_32bit_cp0_set1_register(source)                    \
+({ int __res;                                                   \
+        __asm__ __volatile__(                                   \
+        ".set\tpush\n\t"                                        \
+        ".set\treorder\n\t"                                     \
+        "cfc0\t%0,"STR(source)"\n\t"                            \
+        ".set\tpop"                                             \
+        : "=r" (__res));                                        \
+        __res;})
+
+#define write_32bit_cp0_set1_register(register,value)           \
+        __asm__ __volatile__(                                   \
+        "ctc0\t%0,"STR(register)"\n\t"                          \
+        "nop"                                                   \
+        : : "r" (value));
+
+static spinlock_t irq_lock = SPIN_LOCK_UNLOCKED;
+
+/* Function for careful CP0 interrupt mask access */
+static inline void modify_cp0_intmask(unsigned clr_mask_in, unsigned set_mask_in)
+{
+        unsigned long status;
+        unsigned clr_mask;
+        unsigned set_mask;
+
+        /* do the low 8 bits first */
+        clr_mask = 0xff & clr_mask_in;
+        set_mask = 0xff & set_mask_in;
+        status = read_c0_status();
+        status &= ~((clr_mask & 0xFF) << 8);
+        status |= (set_mask & 0xFF) << 8 | 0x0000FF00;
+        write_c0_status(status);
+
+        /* do the high 8 bits */
+        clr_mask = 0xff & (clr_mask_in >> 8);
+        set_mask = 0xff & (set_mask_in >> 8);
+        status = read_32bit_cp0_set1_register(CP0_S1_INTCONTROL);
+        status &= ~((clr_mask & 0xFF) << 8);
+        status |= (set_mask & 0xFF) << 8;
+        write_32bit_cp0_set1_register(CP0_S1_INTCONTROL, status);
+}
+
+static inline void mask_irq(unsigned int irq)
+{
+        modify_cp0_intmask(irq, 0);
+}
+
+static inline void unmask_irq(unsigned int irq)
+{
+        modify_cp0_intmask(0, irq);
+}
+
+static void enable_rm9000_irq(unsigned int irq)
+{
+        unsigned long flags;
+
+        spin_lock_irqsave(&irq_lock, flags);
+        unmask_irq(1 << (irq-1));
+        spin_unlock_irqrestore(&irq_lock, flags);
+}
+
+static unsigned int startup_rm9000_irq(unsigned int irq)
+{
+        enable_rm9000_irq(irq);
+
+        return 0;                               /* never anything pending */
+}
+
+static void disable_rm9000_irq(unsigned int irq)
+{
+        unsigned long flags;
+
+        spin_lock_irqsave(&irq_lock, flags);
+        mask_irq(1 << (irq-1));
+        spin_unlock_irqrestore(&irq_lock, flags);
+}
+
+#define shutdown_rm9000_irq disable_rm9000_irq
+
+static void mask_and_ack_rm9000_irq(unsigned int irq)
+{
+        mask_irq(1 << (irq-1));
+}
+
+static void end_rm9000_irq(unsigned int irq)
+{
+        if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
+                unmask_irq(1 << (irq-1));
+}
+
+static struct hw_interrupt_type rm9000_hpcdma_irq_type = {
+        "RM9000",
+        startup_rm9000_irq,
+        shutdown_rm9000_irq,
+        enable_rm9000_irq,
+        disable_rm9000_irq,
+        mask_and_ack_rm9000_irq,
+        end_rm9000_irq,
+        NULL
+};
+
+extern asmlinkage void titan_handle_int(void);
+extern void jaguar_mailbox_irq(struct pt_regs *);
+
+/* 
+ * Handle hypertransport & SMP interrupts. The interrupt lines are scarce. For interprocessor
+ * interrupts, the best thing to do is to use the INTMSG register. We use the same external
+ * interrupt line, i.e. INTB3 and monitor another status bit
+ */
+asmlinkage void ll_ht_smp_irq_handler(int irq, struct pt_regs *regs)
+{
+        u32 status;
+        status = *(volatile u_int32_t *)(IRQ_STATUS_REG_CPU0);
+
+	/* Ack all the bits that correspond to the interrupt sources */
+	if (status != 0)
+	        *(volatile u_int32_t *)(IRQ_STATUS_REG_CPU0) = IRQ_ACK_BITS;
+
+	status = *(volatile u_int32_t *)(IRQ_STATUS_REG_CPU1);
+	if (status != 0)
+                *(volatile u_int32_t *)(IRQ_STATUS_REG_CPU1) = IRQ_ACK_BITS;
+
+#ifdef CONFIG_SMP
+	if (status == 0x2) {
+		/* This is an SMP IPI sent from one core to another */
+		jaguar_mailbox_irq(regs);
+		goto done;
+	}
+#endif
+	
+#ifdef CONFIG_HT_LEVEL_TRIGGER
+        /*
+         * Level Trigger Mode only. Send the HT EOI message back to the source.
+         */
+        switch (status) {
+                case 0x1000000:
+                        *(volatile u_int32_t *)(HYPERTRANSPORT_EOI) = HYPERTRANSPORT_INTA;
+                        break;
+                case 0x2000000:
+                        *(volatile u_int32_t *)(HYPERTRANSPORT_EOI) = HYPERTRANSPORT_INTB;
+                        break;
+                case 0x4000000:
+                        *(volatile u_int32_t *)(HYPERTRANSPORT_EOI) = HYPERTRANSPORT_INTC;
+                        break;
+                case 0x8000000:
+                        *(volatile u_int32_t *)(HYPERTRANSPORT_EOI) = HYPERTRANSPORT_INTD;
+                        break;
+                case 0x0000001:
+                        /* PLX */
+                        *(volatile u_int32_t *)(HYPERTRANSPORT_EOI) = 0x20;
+                        *(volatile u_int32_t *)(IRQ_CLEAR_REG) = IRQ_ACK_BITS;
+                        break;
+                case 0xf000000:
+                        *(volatile u_int32_t *)(HYPERTRANSPORT_EOI) = HYPERTRANSPORT_INTA;
+                        *(volatile u_int32_t *)(HYPERTRANSPORT_EOI) = HYPERTRANSPORT_INTB;
+                        *(volatile u_int32_t *)(HYPERTRANSPORT_EOI) = HYPERTRANSPORT_INTC;
+                        *(volatile u_int32_t *)(HYPERTRANSPORT_EOI) = HYPERTRANSPORT_INTD;
+                        break;
+        }
+#endif /* CONFIG_HT_LEVEL_TRIGGER */
+
+done:
+	if (status != 0x2)
+		/* Not for SMP */
+		do_IRQ(irq, regs);	
+}
+
+/*
+ * Initialize the next level interrupt handler
+ */
+void __init init_IRQ(void)
+{
+	int	i;
+
+	clear_c0_status(ST0_IM | ST0_BEV);
+	__cli();
+
+	set_except_vector(0, titan_handle_int);
+	init_generic_irq();
+
+	for (i = 0; i < 13; i++) {
+                irq_desc[i].status      = IRQ_DISABLED;
+                irq_desc[i].action      = 0;
+                irq_desc[i].depth       = 1;
+                irq_desc[i].handler     = &rm9000_hpcdma_irq_type;
+        }
+}
+
--- diff/arch/mips/pmc-sierra/yosemite/prom.c	1970-01-01 01:00:00.000000000 +0100
+++ source/arch/mips/pmc-sierra/yosemite/prom.c	2004-02-23 13:56:38.000000000 +0000
@@ -0,0 +1,189 @@
+/*
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ *
+ * Copyright (C) 2003 PMC-Sierra Inc.
+ * Author: Manish Lachwani (lachwani@pmc-sierra.com)
+ */
+
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <asm/io.h>
+#include <asm/pgtable.h>
+#include <asm/processor.h>
+#include <asm/reboot.h>
+#include <asm/system.h>
+#include <linux/delay.h>
+#include <linux/smp.h>
+#include <asm/bootinfo.h>
+
+#include "setup.h"
+
+/* Call Vectors */
+struct callvectors {
+        int     (*open) (char*, int, int);
+        int     (*close) (int);
+        int     (*read) (int, void*, int);
+        int     (*write) (int, void*, int);
+        off_t   (*lseek) (int, off_t, int);
+        int     (*printf) (const char*, ...);
+        void    (*cacheflush) (void);
+        char*   (*gets) (char*);
+};
+
+struct callvectors* debug_vectors;
+
+extern unsigned long yosemite_base;
+extern unsigned long cpu_clock;
+unsigned char titan_ge_mac_addr_base[6];
+
+const char *get_system_type(void)
+{
+        return "PMC-Sierra Yosemite";
+}
+
+static void prom_cpu0_exit(void)
+{
+	void	*nvram = YOSEMITE_NVRAM_BASE_ADDR;
+	
+	/* Ask the NVRAM/RTC/watchdog chip to assert reset in 1/16 second */
+        writeb(0x84, nvram + 0xff7);
+
+        /* wait for the watchdog to go off */
+        mdelay(100+(1000/16));
+
+        /* if the watchdog fails for some reason, let people know */
+        printk(KERN_NOTICE "Watchdog reset failed\n");
+}
+
+/*
+ * Reset the NVRAM over the local bus
+ */
+static void prom_exit(void)
+{
+#ifdef CONFIG_SMP
+	if (smp_processor_id())
+		/* CPU 1 */
+		smp_call_function(prom_cpu0_exit, NULL, 1, 1);
+#endif
+	prom_cpu0_exit;
+}
+
+/*
+ * Get the MAC address from the EEPROM using the I2C protocol
+ */
+void get_mac_address(char dest[6])
+{
+	/* Use the I2C command code in the i2c-yosemite */
+}
+
+/*
+ * Halt the system 
+ */
+static void prom_halt(void)
+{
+	printk(KERN_NOTICE "\n** You can safely turn off the power\n");
+	while (1)
+                __asm__(".set\tmips3\n\t"
+                        "wait\n\t"
+                        ".set\tmips0");
+}
+
+/*
+ * Init routine which accepts the variables from PMON
+ */
+__init prom_init(int argc, char **arg, char **env, struct callvectors *cv)
+{
+	int	i = 0;
+
+	/* Callbacks for halt, restart */
+	_machine_restart = (void (*)(char *))prom_exit;	
+	_machine_halt = prom_halt;
+	_machine_power_off = prom_halt;
+
+#ifdef CONFIG_MIPS64
+
+	/* Do nothing for the 64-bit for now. Just implement for the 32-bit */
+
+#else /* CONFIG_MIPS64 */
+
+	debug_vectors = cv;
+	arcs_cmdline[0] = '\0';
+
+	/* Get the boot parameters */
+	for (i = 1; i < argc; i++) {
+                if (strlen(arcs_cmdline) + strlen(arg[i] + 1) >= sizeof(arcs_cmdline))
+                        break;
+
+		strcat(arcs_cmdline, arg[i]);
+		strcat(arcs_cmdline, " ");
+	}
+
+	while (*env) {
+		if (strncmp("ocd_base", *env, strlen("ocd_base")) == 0) 
+			yosemite_base = simple_strtol(*env + strlen("ocd_base="),
+							NULL, 16);
+
+		if (strncmp("cpuclock", *env, strlen("cpuclock")) == 0) 
+			cpu_clock = simple_strtol(*env + strlen("cpuclock="),
+							NULL, 10);
+		
+		env++;
+	}
+#endif /* CONFIG_MIPS64 */
+
+	mips_machgroup = MACH_GROUP_TITAN;
+	mips_machtype = MACH_TITAN_YOSEMITE;
+
+	get_mac_address(titan_ge_mac_addr_base);
+
+	debug_vectors->printf("Booting Linux kernel...\n");
+}
+
+void __init prom_free_prom_memory(void)
+{
+}
+
+void __init prom_fixup_mem_map(unsigned long start, unsigned long end)
+{
+}
+
+extern void asmlinkage smp_bootstrap(void);
+
+/*
+ * SMP support
+ */
+int prom_setup_smp(void)
+{
+        int     num_cpus = 2;
+
+        /*
+         * We know that the RM9000 on the Jaguar ATX board has 2 cores. Hence, this
+         * can be hardcoded for now.
+         */
+        return num_cpus;
+}
+
+int prom_boot_secondary(int cpu, unsigned long sp, unsigned long gp)
+{
+        /* Clear the semaphore */
+        *(volatile u_int32_t *)(0xbb000a68) = 0x80000000;
+
+        return 1;
+}
+
+void prom_init_secondary(void)
+{
+        clear_c0_config(CONF_CM_CMASK);
+        set_c0_config(0x2);
+
+        clear_c0_status(ST0_IM);
+        set_c0_status(0x1ffff);
+}
+
+void prom_smp_finish(void)
+{
+}
+	
--- diff/arch/mips/pmc-sierra/yosemite/setup.c	1970-01-01 01:00:00.000000000 +0100
+++ source/arch/mips/pmc-sierra/yosemite/setup.c	2004-02-23 13:56:38.000000000 +0000
@@ -0,0 +1,170 @@
+/*
+ *  arch/mips/pmc-sierra/yosemite/setup.c
+ *
+ *  Copyright (C) 2003 PMC-Sierra Inc.
+ *  Author: Manish Lachwani (lachwani@pmc-sierra.com)
+ *
+ *  This program is free software; you can redistribute  it and/or modify it
+ *  under  the terms of  the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the  License, or (at your
+ *  option) any later version.
+ *
+ *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
+ *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
+ *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
+ *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
+ *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
+ *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *  You should have received a copy of the  GNU General Public License along
+ *  with this program; if not, write  to the Free Software Foundation, Inc.,
+ *  675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/mc146818rtc.h>
+#include <linux/mm.h>
+#include <linux/swap.h>
+#include <linux/ioport.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <linux/pci.h>
+#include <linux/timex.h>
+#include <linux/vmalloc.h>
+#include <asm/time.h>
+#include <asm/bootinfo.h>
+#include <asm/page.h>
+#include <asm/bootinfo.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/processor.h>
+#include <asm/ptrace.h>
+#include <asm/reboot.h>
+#include <linux/version.h>
+#include <linux/bootmem.h>
+#include <linux/blk.h>
+
+#include "setup.h"
+
+unsigned long cpu_clock;
+unsigned long yosemite_base;
+
+void __init bus_error_init(void) 
+{ 
+	/* Do nothing */ 
+}
+
+unsigned long m48t37y_get_time(void)
+{
+	unsigned char	*rtc_base = YOSEMITE_RTC_BASE;
+	unsigned int	year, month, day, hour, min, sec;
+
+	/* Stop the update to the time */
+	rtc_base[0x7ff8] = 0x40;
+
+	year = CONV_BCD_TO_BIN(rtc_base[0x7fff]);
+	year += CONV_BCD_TO_BIN(rtc_base[0x7fff1]) * 100;
+
+	month = CONV_BCD_TO_BIN(rtc_base[0x7ffe]);
+	day = CONV_BCD_TO_BIN(rtc_base[0x7ffd]);
+	hour = CONV_BCD_TO_BIN(rtc_base[0x7ffb]);
+	min = CONV_BCD_TO_BIN(rtc_base[0x7ffa]);
+	sec = CONV_BCD_TO_BIN(rtc_base[0x7ff9]);
+
+	/* Start the update to the time again */
+	rtc_base[0x7ff8] = 0x00;
+
+	return mktime(year, month, day, hour, min, sec);
+}
+
+int m48t37y_set_time(unsigned long sec)
+{
+	unsigned char   *rtc_base = YOSEMITE_RTC_BASE;
+        unsigned int    year, month, day, hour, min, sec;
+
+        struct rtc_time tm;
+
+        /* convert to a more useful format -- note months count from 0 */
+        to_tm(sec, &tm);
+        tm.tm_mon += 1;
+
+        /* enable writing */
+        rtc_base[0x7ff8] = 0x80;
+
+        /* year */
+        rtc_base[0x7fff] = CONV_BIN_TO_BCD(tm.tm_year % 100);
+        rtc_base[0x7ff1] = CONV_BIN_TO_BCD(tm.tm_year / 100);
+
+        /* month */
+        rtc_base[0x7ffe] = CONV_BIN_TO_BCD(tm.tm_mon);
+
+        /* day */
+        rtc_base[0x7ffd] = CONV_BIN_TO_BCD(tm.tm_mday);
+
+        /* hour/min/sec */
+        rtc_base[0x7ffb] = CONV_BIN_TO_BCD(tm.tm_hour);
+        rtc_base[0x7ffa] = CONV_BIN_TO_BCD(tm.tm_min);
+        rtc_base[0x7ff9] = CONV_BIN_TO_BCD(tm.tm_sec);
+
+        /* day of week -- not really used, but let's keep it up-to-date */
+        rtc_base[0x7ffc] = CONV_BIN_TO_BCD(tm.tm_wday + 1);
+
+        /* disable writing */
+        rtc_base[0x7ff8] = 0x00;
+
+        return 0;
+}
+
+void yosemite_timer_setup(struct irqaction *irq)
+{
+	setup_irq(6, irq);
+}
+
+void yosemite_time_init(void)
+{
+	mips_counter_frequency = cpu_clock / 2;
+	board_timer_setup = yosemite_timer_setup;
+
+	rtc_get_time = m48t37y_get_time;
+	rtc_set_time = m48t37y_set_time;
+}
+
+static int __init pmc_yosemite_setup(void)
+{
+	unsigned long	val = 0;
+
+	printk("PMC-Sierra Yosemite Board Setup  \n");
+	board_time_init = yosemite_time_init;
+
+	/* Add memory regions */
+	add_memory_region(0x00000000, 0x10000000, BOOT_MEM_RAM);
+	add_memory_region(0x10000000, 0x10000000, BOOT_MEM_RAM);
+
+	/* Setup the HT controller */
+	val = *(volatile u_int32_t *)(HYPERTRANSPORT_CONFIG_REG);
+	val |= HYPERTRANSPORT_ENABLE;
+        *(volatile u_int32_t *)(HYPERTRANSPORT_CONFIG_REG) = val;
+
+        /* Set the BAR. Shifted mode */
+        *(volatile u_int32_t *)(HYPERTRANSPORT_BAR0_REG) = HYPERTRANSPORT_BAR0_ADDR;
+        *(volatile u_int32_t *)(HYPERTRANSPORT_SIZE0_REG) = HYPERTRANSPORT_SIZE0;
+
+#ifdef CONFIG_PCI
+	ioport_resource.start = 0xe0000000;
+	ioport_resource.end   = 0xe0000000 + 0x20000000 - 1;
+	iomem_resource.start  = 0xc0000000;
+	iomem_resource.end    = 0xc0000000 + 0x20000000 - 1;
+
+	pci_scan_bus(0, &titan_pci_ops, NULL);
+#endif
+
+	return 0;
+}
+
+early_initcall(pmc_yosemite_setup);
--- diff/arch/mips/pmc-sierra/yosemite/setup.h	1970-01-01 01:00:00.000000000 +0100
+++ source/arch/mips/pmc-sierra/yosemite/setup.h	2004-02-23 13:56:38.000000000 +0000
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2003 PMC-Sierra
+ * Author: Manish Lachwani (lachwani@pmc-sierra.com)
+ *
+ * Board specific definititions for the PMC-Sierra Yosemite
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+
+#ifndef __SETUP_H__
+#define __SETUP_H__
+
+/* Real Time Clock base */
+#define	YOSEMITE_RTC_BASE
+#define CONV_BCD_TO_BIN(val)    (((val) & 0xf) + (((val) >> 4) * 10))
+#define CONV_BIN_TO_BCD(val)    (((val) % 10) + (((val) / 10) << 4))
+
+/* NVRAM Base */
+#define	YOSEMITE_NVRAM_BASE_ADDR	0xbb000678	/* XXX Need change */
+#define	YOSEMITE_RTC_BASE		0xbb000679	/* XXX Need change */
+
+/*
+ * Hypertransport Specific 
+ */
+#define HYPERTRANSPORT_CONFIG_REG       0xbb000604
+#define HYPERTRANSPORT_BAR0_REG         0xbb000610
+#define HYPERTRANSPORT_SIZE0_REG        0xbb000688
+#define HYPERTRANSPORT_BAR0_ATTR_REG    0xbb000680
+
+#define HYPERTRANSPORT_BAR0_ADDR        0x00000006
+#define HYPERTRANSPORT_SIZE0            0x0fffffff
+#define HYPERTRANSPORT_BAR0_ATTR        0x00002000
+
+#define HYPERTRANSPORT_ENABLE           0x6
+
+/*
+ * EEPROM Size 
+ */
+#define	TITAN_ATMEL_24C32_SIZE		32768
+#define	TITAN_ATMEL_24C64_SIZE		65536
+
+
+#endif /* __SETUP_H__ */
+
--- diff/arch/mips/pmc-sierra/yosemite/smp.c	1970-01-01 01:00:00.000000000 +0100
+++ source/arch/mips/pmc-sierra/yosemite/smp.c	2004-02-23 13:56:38.000000000 +0000
@@ -0,0 +1,179 @@
+/*
+ * Copyright 2003 PMC-Sierra
+ * Author: Manish Lachwani (lachwani@pmc-sierra.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/smp.h>
+#include <linux/kernel_stat.h>
+
+#include <asm/mmu_context.h>
+#include <asm/trace.h>
+
+extern void smp_call_function_interrupt(void);
+extern void asmlinkage smp_bootstrap(void);
+
+/*
+ * Send inter-processor interrupt
+ */
+void core_send_ipi(int cpu, unsigned int action)
+{
+        /*
+         * Generate and INTMSG so that it can be sent over to the destination CPU
+         * The INTMSG will put the STATUS bits based on the action desired
+         */
+        switch(action) {
+                case SMP_RESCHEDULE_YOURSELF:
+                        /* Do nothing */
+                        break;
+                case SMP_CALL_FUNCTION:
+                        if (cpu == 1)
+                                *(volatile u_int32_t *)(0xbb000a00) = 0x00610002;
+                        else
+                                *(volatile u_int32_t *)(0xbb000a00) = 0x00610001;
+                        break;
+
+                default:
+                        panic("core_send_ipi \n");
+        }
+}
+
+/*
+ * Mailbox interrupt to handle IPI
+ */
+void jaguar_mailbox_irq(struct pt_regs *regs)
+{
+        int cpu = smp_processor_id();
+
+        /* SMP_CALL_FUNCTION */
+        smp_call_function_interrupt();
+}
+
+extern atomic_t cpus_booted;
+
+void __init start_secondary(void)
+{
+        unsigned int cpu = smp_processor_id();
+        extern atomic_t smp_commenced;
+
+        if (current->processor != 1) {
+                printk("Impossible CPU %d \n", cpu);
+                current->processor = 1;
+                current->cpus_runnable = 1 << 1;
+                cpu = current->processor;
+        }
+
+        if (current->mm)
+                current->mm = NULL;
+
+        prom_init_secondary();
+        per_cpu_trap_init();
+
+        /*
+         * XXX parity protection should be folded in here when it's converted
+         * to an option instead of something based on .cputype
+         */
+        pgd_current[cpu] = init_mm.pgd;
+        cpu_data[cpu].udelay_val = loops_per_jiffy;
+        prom_smp_finish();
+        CPUMASK_SETB(cpu_online_map, cpu);
+        atomic_inc(&cpus_booted);
+        __flush_cache_all();
+
+        printk("Slave cpu booted successfully  \n");
+        *(volatile u_int32_t *)(0xbb000a68) = 0x00000000;
+        *(volatile u_int32_t *)(0xbb000a68) = 0x80000000;
+
+        while (*(volatile u_int32_t *)(0xbb000a68) != 0x00000000);
+
+        return cpu_idle();
+}
+
+void __init smp_boot_cpus(void)
+{
+        int i;
+        int cur_cpu = 0;
+
+        smp_num_cpus = prom_setup_smp();
+        printk("Detected %d available CPUs \n", smp_num_cpus);
+
+        init_new_context(current, &init_mm);
+        current->processor = 0;
+        cpu_data[0].udelay_val = loops_per_jiffy;
+        cpu_data[0].asid_cache = ASID_FIRST_VERSION;
+        CPUMASK_CLRALL(cpu_online_map);
+        CPUMASK_SETB(cpu_online_map, 0);
+        atomic_set(&cpus_booted, 1);  /* Master CPU is already booted... */
+        init_idle();
+
+        __cpu_number_map[0] = 0;
+        __cpu_logical_map[0] = 0;
+
+        /*
+         * This loop attempts to compensate for "holes" in the CPU
+         * numbering.  It's overkill, but general.
+         */
+        for (i = 1; i < smp_num_cpus; ) {
+                struct task_struct *p;
+                struct pt_regs regs;
+                int retval;
+                printk("Starting CPU %d... \n", i);
+
+                /* Spawn a new process normally.  Grab a pointer to
+                   its task struct so we can mess with it */
+                do_fork(CLONE_VM|CLONE_PID, 0, &regs, 0);
+
+                p = init_task.prev_task;
+                if (!p)
+                        panic("failed fork for CPU %d", i);
+
+                /* This is current for the second processor */
+                p->processor = i;
+                p->cpus_runnable = 1 << i; /* we schedule the first task manually */
+                p->thread.reg31 = (unsigned long) start_secondary;
+
+                del_from_runqueue(p);
+                unhash_process(p);
+                init_tasks[i] = p;
+
+                __flush_cache_all();
+
+                do {
+                        /* Iterate until we find a CPU that comes up */
+                        cur_cpu++;
+                        retval = prom_boot_secondary(cur_cpu,
+                                            (unsigned long)p + KERNEL_STACK_SIZE - 32,
+                                            (unsigned long)p);
+
+                } while (!retval && (cur_cpu < NR_CPUS));
+                if (retval) {
+                        __cpu_number_map[cur_cpu] = i;
+                        __cpu_logical_map[i] = cur_cpu;
+                        i++;
+                } else {
+                        panic("CPU discovery disaster");
+                }
+        }
+
+        /* Local semaphore to both the CPUs */
+
+        *(volatile u_int32_t *)(0xbb000a68) = 0x80000000;
+        while (*(volatile u_int32_t *)(0xbb000a68) != 0x00000000);
+
+        smp_threads_ready = 1;
+}
--- diff/arch/mips/sgi-ip27/ip27-smp.c	1970-01-01 01:00:00.000000000 +0100
+++ source/arch/mips/sgi-ip27/ip27-smp.c	2004-02-23 13:56:38.000000000 +0000
@@ -0,0 +1,227 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General
+ * Public License.  See the file "COPYING" in the main directory of this
+ * archive for more details.
+ *
+ * Copyright (C) 2000 - 2001 by Kanoj Sarcar (kanoj@sgi.com)
+ * Copyright (C) 2000 - 2001 by Silicon Graphics, Inc.
+ */
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <asm/page.h>
+#include <asm/processor.h>
+#include <asm/sn/arch.h>
+#include <asm/sn/gda.h>
+#include <asm/sn/intr.h>
+#include <asm/sn/klconfig.h>
+#include <asm/sn/launch.h>
+#include <asm/sn/mapped_kernel.h>
+#include <asm/sn/sn_private.h>
+#include <asm/sn/types.h>
+#include <asm/sn/sn0/hubpi.h>
+#include <asm/sn/sn0/hubio.h>
+#include <asm/sn/sn0/ip27.h>
+
+/*
+ * Takes as first input the PROM assigned cpu id, and the kernel
+ * assigned cpu id as the second.
+ */
+static void alloc_cpupda(cpuid_t cpu, int cpunum)
+{
+	cnodeid_t node = get_cpu_cnode(cpu);
+	nasid_t nasid = COMPACT_TO_NASID_NODEID(node);
+
+	cputonasid(cpunum) = nasid;
+	cputocnode(cpunum) = node;
+	cputoslice(cpunum) = get_cpu_slice(cpu);
+}
+
+static nasid_t get_actual_nasid(lboard_t *brd)
+{
+	klhub_t *hub;
+
+	if (!brd)
+		return INVALID_NASID;
+
+	/* find out if we are a completely disabled brd. */
+	hub  = (klhub_t *)find_first_component(brd, KLSTRUCT_HUB);
+	if (!hub)
+		return INVALID_NASID;
+	if (!(hub->hub_info.flags & KLINFO_ENABLE))	/* disabled node brd */
+		return hub->hub_info.physid;
+	else
+		return brd->brd_nasid;
+}
+
+static int do_cpumask(cnodeid_t cnode, nasid_t nasid, int highest)
+{
+	static int tot_cpus_found = 0;
+	lboard_t *brd;
+	klcpu_t *acpu;
+	int cpus_found = 0;
+	cpuid_t cpuid;
+
+	brd = find_lboard((lboard_t *)KL_CONFIG_INFO(nasid), KLTYPE_IP27);
+
+	do {
+		acpu = (klcpu_t *)find_first_component(brd, KLSTRUCT_CPU);
+		while (acpu) {
+			cpuid = acpu->cpu_info.virtid;
+			/* cnode is not valid for completely disabled brds */
+			if (get_actual_nasid(brd) == brd->brd_nasid)
+				cpuid_to_compact_node[cpuid] = cnode;
+			if (cpuid > highest)
+				highest = cpuid;
+			/* Only let it join in if it's marked enabled */
+			if ((acpu->cpu_info.flags & KLINFO_ENABLE) &&
+			    (tot_cpus_found != NR_CPUS)) {
+				cpu_set(cpuid, phys_cpu_present_map);
+				alloc_cpupda(cpuid, tot_cpus_found);
+				cpus_found++;
+				tot_cpus_found++;
+			}
+			acpu = (klcpu_t *)find_component(brd, (klinfo_t *)acpu,
+								KLSTRUCT_CPU);
+		}
+		brd = KLCF_NEXT(brd);
+		if (!brd)
+			break;
+
+		brd = find_lboard(brd, KLTYPE_IP27);
+	} while (brd);
+
+	return highest;
+}
+
+void cpu_node_probe(void)
+{
+	int i, highest = 0;
+	gda_t *gdap = GDA;
+
+	/*
+	 * Initialize the arrays to invalid nodeid (-1)
+	 */
+	for (i = 0; i < MAX_COMPACT_NODES; i++)
+		compact_to_nasid_node[i] = INVALID_NASID;
+	for (i = 0; i < MAX_NASIDS; i++)
+		nasid_to_compact_node[i] = INVALID_CNODEID;
+	for (i = 0; i < MAXCPUS; i++)
+		cpuid_to_compact_node[i] = INVALID_CNODEID;
+
+	numnodes = 0;
+	for (i = 0; i < MAX_COMPACT_NODES; i++) {
+		nasid_t nasid = gdap->g_nasidtable[i];
+		if (nasid == INVALID_NASID)
+			break;
+		compact_to_nasid_node[i] = nasid;
+		nasid_to_compact_node[nasid] = i;
+		numnodes++;
+		highest = do_cpumask(i, nasid, highest);
+	}
+
+	printk("Discovered %d cpus on %d nodes\n", highest + 1, numnodes);
+}
+
+void __init prom_build_cpu_map(void)
+{
+}
+
+static void intr_clear_bits(nasid_t nasid, volatile hubreg_t *pend,
+	int base_level)
+{
+	volatile hubreg_t bits;
+	int i;
+
+	/* Check pending interrupts */
+	if ((bits = HUB_L(pend)) != 0)
+		for (i = 0; i < N_INTPEND_BITS; i++)
+			if (bits & (1 << i))
+				LOCAL_HUB_CLR_INTR(base_level + i);
+}
+
+static void intr_clear_all(nasid_t nasid)
+{
+	REMOTE_HUB_S(nasid, PI_INT_MASK0_A, 0);
+	REMOTE_HUB_S(nasid, PI_INT_MASK0_B, 0);
+	REMOTE_HUB_S(nasid, PI_INT_MASK1_A, 0);
+	REMOTE_HUB_S(nasid, PI_INT_MASK1_B, 0);
+	intr_clear_bits(nasid, REMOTE_HUB_ADDR(nasid, PI_INT_PEND0),
+	                INT_PEND0_BASELVL);
+	intr_clear_bits(nasid, REMOTE_HUB_ADDR(nasid, PI_INT_PEND1),
+	                INT_PEND1_BASELVL);
+}
+
+void __init prom_prepare_cpus(unsigned int max_cpus)
+{
+	cnodeid_t	cnode;
+
+	for (cnode = 0; cnode < numnodes; cnode++)
+		intr_clear_all(COMPACT_TO_NASID_NODEID(cnode));
+
+	/* Master has already done per_cpu_init() */
+	install_ipi();
+
+	replicate_kernel_text(numnodes);
+
+	/*
+	 * Assumption to be fixed: we're always booted on logical / physical
+	 * processor 0.  While we're always running on logical processor 0
+	 * this still means this is physical processor zero; it might for
+	 * example be disabled in the firwware.
+	 */
+	alloc_cpupda(0, 0);
+}
+
+/*
+ * Launch a slave into smp_bootstrap().  It doesn't take an argument, and we
+ * set sp to the kernel stack of the newly created idle process, gp to the proc
+ * struct so that current_thread_info() will work.
+ */
+void __init prom_boot_secondary(int cpu, struct task_struct *idle)
+{
+	unsigned long gp = (unsigned long) idle->thread_info;
+	unsigned long sp = gp + THREAD_SIZE - 32;
+
+	LAUNCH_SLAVE(cputonasid(cpu),cputoslice(cpu),
+		(launch_proc_t)MAPPED_KERN_RW_TO_K0(smp_bootstrap),
+		0, (void *) sp, (void *) gp);
+}
+
+void prom_init_secondary(void)
+{
+	per_cpu_init();
+	local_irq_enable();
+}
+
+void __init prom_cpus_done(void)
+{
+}
+
+void prom_smp_finish(void)
+{
+}
+
+void core_send_ipi(int destid, unsigned int action)
+{
+	int irq;
+
+	switch (action) {
+	case SMP_RESCHEDULE_YOURSELF:
+		irq = CPU_RESCHED_A_IRQ;
+		break;
+	case SMP_CALL_FUNCTION:
+		irq = CPU_CALL_A_IRQ;
+		break;
+	default:
+		panic("sendintr");
+	}
+
+	irq += cputoslice(destid);
+
+	/*
+	 * Convert the compact hub number to the NASID to get the correct
+	 * part of the address space.  Then set the interrupt bit associated
+	 * with the CPU we want to send the interrupt to.
+	 */
+	REMOTE_HUB_SEND_INTR(COMPACT_TO_NASID_NODEID(cputocnode(destid)), irq);
+}
--- diff/arch/mips/vr41xx/common/ksyms.c	1970-01-01 01:00:00.000000000 +0100
+++ source/arch/mips/vr41xx/common/ksyms.c	2004-02-23 13:56:38.000000000 +0000
@@ -0,0 +1,35 @@
+/*
+ *   ksyms.c, Export NEC VR4100 series specific functions needed for loadable modules.
+ *
+ *  Copyright (C) 2003  Yoichi Yuasa <yuasa@hh.iij4u.or.jp>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+#include <linux/config.h>
+#include <linux/module.h>
+
+#include <asm/vr41xx/vr41xx.h>
+
+EXPORT_SYMBOL(vr41xx_get_vtclock_frequency);
+EXPORT_SYMBOL(vr41xx_get_tclock_frequency);
+
+EXPORT_SYMBOL(vr41xx_set_intassign);
+
+EXPORT_SYMBOL(vr41xx_set_rtclong1_cycle);
+EXPORT_SYMBOL(vr41xx_read_rtclong1_counter);
+EXPORT_SYMBOL(vr41xx_set_rtclong2_cycle);
+EXPORT_SYMBOL(vr41xx_read_rtclong2_counter);
+EXPORT_SYMBOL(vr41xx_set_tclock_cycle);
+EXPORT_SYMBOL(vr41xx_read_tclock_counter);
--- diff/arch/mips/vr41xx/common/pmu.c	1970-01-01 01:00:00.000000000 +0100
+++ source/arch/mips/vr41xx/common/pmu.c	2004-02-23 13:56:38.000000000 +0000
@@ -0,0 +1,76 @@
+/*
+ *  pmu.c, Power Management Unit routines for NEC VR4100 series.
+ *
+ *  Copyright (C) 2003  Yoichi Yuasa <yuasa@hh.iij4u.or.jp>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+#include <linux/init.h>
+#include <linux/smp.h>
+#include <linux/types.h>
+
+#include <asm/cpu.h>
+#include <asm/io.h>
+#include <asm/reboot.h>
+#include <asm/system.h>
+
+#define PMUCNT2REG	KSEG1ADDR(0x0f0000c6)
+ #define SOFTRST	0x0010
+
+static inline void software_reset(void)
+{
+	uint16_t val;
+
+	switch (current_cpu_data.cputype) {
+	case CPU_VR4122:
+	case CPU_VR4131:
+	case CPU_VR4133:
+		val = readw(PMUCNT2REG);
+		val |= SOFTRST;
+		writew(val, PMUCNT2REG);
+		break;
+	default:
+		break;
+	}
+}
+
+static void vr41xx_restart(char *command)
+{
+	local_irq_disable();
+	software_reset();
+	printk(KERN_NOTICE "\nYou can reset your system\n");
+	while (1) ;
+}
+
+static void vr41xx_halt(void)
+{
+	local_irq_disable();
+	printk(KERN_NOTICE "\nYou can turn off the power supply\n");
+	while (1) ;
+}
+
+static void vr41xx_power_off(void)
+{
+	local_irq_disable();
+	printk(KERN_NOTICE "\nYou can turn off the power supply\n");
+	while (1) ;
+}
+
+void __init vr41xx_pmu_init(void)
+{
+	_machine_restart = vr41xx_restart;
+	_machine_halt = vr41xx_halt;
+	_machine_power_off = vr41xx_power_off;
+}
--- diff/arch/mips/vr41xx/common/rtc.c	1970-01-01 01:00:00.000000000 +0100
+++ source/arch/mips/vr41xx/common/rtc.c	2004-02-23 13:56:38.000000000 +0000
@@ -0,0 +1,311 @@
+/*
+ *  rtc.c, RTC(has only timer function) routines for NEC VR4100 series.
+ *
+ *  Copyright (C) 2003  Yoichi Yuasa <yuasa@hh.iij4u.or.jp>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+#include <linux/init.h>
+#include <linux/irq.h>
+#include <linux/smp.h>
+#include <linux/types.h>
+
+#include <asm/io.h>
+#include <asm/time.h>
+#include <asm/vr41xx/vr41xx.h>
+
+static uint32_t rtc1_base;
+static uint32_t rtc2_base;
+
+static uint64_t previous_elapsedtime;
+static unsigned int remainder_per_sec;
+static unsigned int cycles_per_sec;
+static unsigned int cycles_per_jiffy;
+static unsigned long epoch_time;
+
+#define CYCLES_PER_JIFFY	(CLOCK_TICK_RATE / HZ)
+#define REMAINDER_PER_SEC	(CLOCK_TICK_RATE - (CYCLES_PER_JIFFY * HZ))
+#define CYCLES_PER_100USEC	((CLOCK_TICK_RATE + (10000 / 2)) / 10000)
+
+#define ETIMELREG_TYPE1		KSEG1ADDR(0x0b0000c0)
+#define TCLKLREG_TYPE1		KSEG1ADDR(0x0b0001c0)
+
+#define ETIMELREG_TYPE2		KSEG1ADDR(0x0f000100)
+#define TCLKLREG_TYPE2		KSEG1ADDR(0x0f000120)
+
+/* RTC 1 registers */
+#define ETIMELREG		0x00
+#define ETIMEMREG		0x02
+#define ETIMEHREG		0x04
+/* RFU */
+#define ECMPLREG		0x08
+#define ECMPMREG		0x0a
+#define ECMPHREG		0x0c
+/* RFU */
+#define RTCL1LREG		0x10
+#define RTCL1HREG		0x12
+#define RTCL1CNTLREG		0x14
+#define RTCL1CNTHREG		0x16
+#define RTCL2LREG		0x18
+#define RTCL2HREG		0x1a
+#define RTCL2CNTLREG		0x1c
+#define RTCL2CNTHREG		0x1e
+
+/* RTC 2 registers */
+#define TCLKLREG		0x00
+#define TCLKHREG		0x02
+#define TCLKCNTLREG		0x04
+#define TCLKCNTHREG		0x06
+/* RFU */
+#define RTCINTREG		0x1e
+ #define TCLOCK_INT		0x08
+ #define RTCLONG2_INT		0x04
+ #define RTCLONG1_INT		0x02
+ #define ELAPSEDTIME_INT	0x01
+
+#define read_rtc1(offset)	readw(rtc1_base + (offset))
+#define write_rtc1(val, offset)	writew((val), rtc1_base + (offset))
+
+#define read_rtc2(offset)	readw(rtc2_base + (offset))
+#define write_rtc2(val, offset)	writew((val), rtc2_base + (offset))
+
+static inline uint64_t read_elapsedtime_counter(void)
+{
+	uint64_t first, second;
+	uint32_t first_mid, first_low;
+	uint32_t second_mid, second_low;
+
+	do {
+		first_low = (uint32_t)read_rtc1(ETIMELREG);
+		first_mid = (uint32_t)read_rtc1(ETIMEMREG);
+		first = (uint64_t)read_rtc1(ETIMEHREG);
+		second_low = (uint32_t)read_rtc1(ETIMELREG);
+		second_mid = (uint32_t)read_rtc1(ETIMEMREG);
+		second = (uint64_t)read_rtc1(ETIMEHREG);
+	} while (first_low != second_low || first_mid != second_mid ||
+	         first != second);
+
+	return (first << 32) | (uint64_t)((first_mid << 16) | first_low);
+}
+
+static inline void write_elapsedtime_counter(uint64_t time)
+{
+	write_rtc1((uint16_t)time, ETIMELREG);
+	write_rtc1((uint16_t)(time >> 16), ETIMEMREG);
+	write_rtc1((uint16_t)(time >> 32), ETIMEHREG);
+}
+
+static inline void write_elapsedtime_compare(uint64_t time)
+{
+	write_rtc1((uint16_t)time, ECMPLREG);
+	write_rtc1((uint16_t)(time >> 16), ECMPMREG);
+	write_rtc1((uint16_t)(time >> 32), ECMPHREG);
+}
+
+void vr41xx_set_rtclong1_cycle(uint32_t cycles)
+{
+	write_rtc1((uint16_t)cycles, RTCL1LREG);
+	write_rtc1((uint16_t)(cycles >> 16), RTCL1HREG);
+}
+
+uint32_t vr41xx_read_rtclong1_counter(void)
+{
+	uint32_t first_high, first_low;
+	uint32_t second_high, second_low;
+
+	do {
+		first_low = (uint32_t)read_rtc1(RTCL1CNTLREG);
+		first_high = (uint32_t)read_rtc1(RTCL1CNTHREG);
+		second_low = (uint32_t)read_rtc1(RTCL1CNTLREG);
+		second_high = (uint32_t)read_rtc1(RTCL1CNTHREG);
+	} while (first_low != second_low || first_high != second_high);
+
+	return (first_high << 16) | first_low;
+}
+
+void vr41xx_set_rtclong2_cycle(uint32_t cycles)
+{
+	write_rtc1((uint16_t)cycles, RTCL2LREG);
+	write_rtc1((uint16_t)(cycles >> 16), RTCL2HREG);
+}
+
+uint32_t vr41xx_read_rtclong2_counter(void)
+{
+	uint32_t first_high, first_low;
+	uint32_t second_high, second_low;
+
+	do {
+		first_low = (uint32_t)read_rtc1(RTCL2CNTLREG);
+		first_high = (uint32_t)read_rtc1(RTCL2CNTHREG);
+		second_low = (uint32_t)read_rtc1(RTCL2CNTLREG);
+		second_high = (uint32_t)read_rtc1(RTCL2CNTHREG);
+	} while (first_low != second_low || first_high != second_high);
+
+	return (first_high << 16) | first_low;
+}
+
+void vr41xx_set_tclock_cycle(uint32_t cycles)
+{
+	write_rtc2((uint16_t)cycles, TCLKLREG);
+	write_rtc2((uint16_t)(cycles >> 16), TCLKHREG);
+}
+
+uint32_t vr41xx_read_tclock_counter(void)
+{
+	uint32_t first_high, first_low;
+	uint32_t second_high, second_low;
+
+	do {
+		first_low = (uint32_t)read_rtc2(TCLKCNTLREG);
+		first_high = (uint32_t)read_rtc2(TCLKCNTHREG);
+		second_low = (uint32_t)read_rtc2(TCLKCNTLREG);
+		second_high = (uint32_t)read_rtc2(TCLKCNTHREG);
+	} while (first_low != second_low || first_high != second_high);
+
+	return (first_high << 16) | first_low;
+}
+
+static void vr41xx_timer_ack(void)
+{
+	uint64_t cur;
+
+	write_rtc2(ELAPSEDTIME_INT, RTCINTREG);
+
+	previous_elapsedtime += (uint64_t)cycles_per_jiffy;
+	cycles_per_sec += cycles_per_jiffy;
+
+	if (cycles_per_sec >= CLOCK_TICK_RATE) {
+		cycles_per_sec = 0;
+		remainder_per_sec = REMAINDER_PER_SEC;
+	}
+
+	cycles_per_jiffy = 0;
+
+	do {
+		cycles_per_jiffy += CYCLES_PER_JIFFY;
+		if (remainder_per_sec > 0) {
+			cycles_per_jiffy++;
+			remainder_per_sec--;
+		}
+
+		cur = read_elapsedtime_counter();
+	} while (cur >= previous_elapsedtime + (uint64_t)cycles_per_jiffy);
+
+	write_elapsedtime_compare(previous_elapsedtime + (uint64_t)cycles_per_jiffy);
+}
+
+static void vr41xx_hpt_init(unsigned int count)
+{
+}
+
+static unsigned int vr41xx_hpt_read(void)
+{
+	uint64_t cur;
+
+	cur = read_elapsedtime_counter();
+
+	return (unsigned int)cur;
+}
+
+static unsigned long vr41xx_gettimeoffset(void)
+{
+	uint64_t cur;
+	unsigned long gap;
+
+	cur = read_elapsedtime_counter();
+	gap = (unsigned long)(cur - previous_elapsedtime);
+	gap = gap / CYCLES_PER_100USEC * 100;	/* usec */
+
+	return gap;
+}
+
+static unsigned long vr41xx_get_time(void)
+{
+	uint64_t counts;
+
+	counts = read_elapsedtime_counter();
+	counts >>= 15;
+
+	return epoch_time + (unsigned long)counts;
+
+}
+
+static int vr41xx_set_time(unsigned long sec)
+{
+	if (sec < epoch_time)
+		return -EINVAL;
+
+	sec -= epoch_time;
+
+	write_elapsedtime_counter((uint64_t)sec << 15);
+
+	return 0;
+}
+
+void vr41xx_set_epoch_time(unsigned long time)
+{
+	epoch_time = time;
+}
+
+void __init vr41xx_time_init(void)
+{
+	switch (current_cpu_data.cputype) {
+	case CPU_VR4111:
+	case CPU_VR4121:
+		rtc1_base = ETIMELREG_TYPE1;
+		rtc2_base = TCLKLREG_TYPE1;
+		break;
+	case CPU_VR4122:
+	case CPU_VR4131:
+	case CPU_VR4133:
+		rtc1_base = ETIMELREG_TYPE2;
+		rtc2_base = TCLKLREG_TYPE2;
+		break;
+	default:
+		panic("Unexpected CPU of NEC VR4100 series");
+		break;
+	}
+
+	mips_timer_ack = vr41xx_timer_ack;
+
+	mips_hpt_init = vr41xx_hpt_init;
+	mips_hpt_read = vr41xx_hpt_read;
+	mips_hpt_frequency = CLOCK_TICK_RATE;
+
+	if (epoch_time == 0)
+		epoch_time = mktime(1970, 1, 1, 0, 0, 0);
+
+	rtc_get_time = vr41xx_get_time;
+	rtc_set_time = vr41xx_set_time;
+}
+
+void __init vr41xx_timer_setup(struct irqaction *irq)
+{
+	do_gettimeoffset = vr41xx_gettimeoffset;
+
+	remainder_per_sec = REMAINDER_PER_SEC;
+	cycles_per_jiffy = CYCLES_PER_JIFFY;
+
+	if (remainder_per_sec > 0) {
+		cycles_per_jiffy++;
+		remainder_per_sec--;
+	}
+
+	previous_elapsedtime = read_elapsedtime_counter();
+	write_elapsedtime_compare(previous_elapsedtime + (uint64_t)cycles_per_jiffy);
+	write_rtc2(ELAPSEDTIME_INT, RTCINTREG);
+
+	setup_irq(ELAPSEDTIME_IRQ, irq);
+}
--- diff/arch/mips/vr41xx/common/vrc4171.c	1970-01-01 01:00:00.000000000 +0100
+++ source/arch/mips/vr41xx/common/vrc4171.c	2004-02-23 13:56:38.000000000 +0000
@@ -0,0 +1,106 @@
+/*
+ *  vrc4171.c, NEC VRC4171 base driver.
+ *
+ *  Copyright (C) 2003  Yoichi Yuasa <yuasa@hh.iij4u.or.jp>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/module.h>
+#include <linux/types.h>
+
+#include <asm/io.h>
+#include <asm/vr41xx/vrc4171.h>
+
+MODULE_DESCRIPTION("NEC VRC4171 base driver");
+MODULE_AUTHOR("Yoichi Yuasa <yuasa@hh.iij4u.or.jp>");
+MODULE_LICENSE("GPL");
+
+EXPORT_SYMBOL_GPL(vrc4171_get_irq_status);
+EXPORT_SYMBOL_GPL(vrc4171_set_multifunction_pin);
+
+#define CONFIGURATION1		0x05fe
+ #define SLOTB_CONFIG		0xc000
+ #define SLOTB_NONE		0x0000
+ #define SLOTB_PCCARD		0x4000
+ #define SLOTB_CF		0x8000
+ #define SLOTB_FLASHROM		0xc000
+
+#define CONFIGURATION2		0x05fc
+#define INTERRUPT_STATUS	0x05fa
+#define PCS_CONTROL		0x05ee
+#define GPIO_DATA		PCS_CONTROL
+#define PCS0_UPPER_START	0x05ec
+#define PCS0_LOWER_START	0x05ea
+#define PCS0_UPPER_STOP		0x05e8
+#define PCS0_LOWER_STOP		0x05e6
+#define PCS1_UPPER_START	0x05e4
+#define PCS1_LOWER_START	0x05e2
+#define PCS1_UPPER_STOP		0x05de
+#define PCS1_LOWER_STOP		0x05dc
+
+#define VRC4171_REGS_BASE	PCS1_LOWER_STOP
+#define VRC4171_REGS_SIZE	0x24
+
+uint16_t vrc4171_get_irq_status(void)
+{
+	return inw(INTERRUPT_STATUS);
+}
+
+void vrc4171_set_multifunction_pin(int config)
+{
+	uint16_t config1;
+
+	config1 = inw(CONFIGURATION1);
+	config1 &= ~SLOTB_CONFIG;
+
+	switch (config) {
+	case SLOTB_IS_NONE:
+		config1 |= SLOTB_NONE;
+		break;
+	case SLOTB_IS_PCCARD:
+		config1 |= SLOTB_PCCARD;
+		break;
+	case SLOTB_IS_CF:
+		config1 |= SLOTB_CF;
+		break;
+	case SLOTB_IS_FLASHROM:
+		config1 |= SLOTB_FLASHROM;
+		break;
+	default:
+		break;
+	}
+
+	outw(config1, CONFIGURATION1);
+}
+
+static int __devinit vrc4171_init(void)
+{
+	if (request_region(VRC4171_REGS_BASE, VRC4171_REGS_SIZE, "NEC VRC4171") == NULL)
+		return -EBUSY;
+
+	printk(KERN_INFO "NEC VRC4171 base driver\n");
+
+	return 0;
+}
+
+static void __devexit vrc4171_exit(void)
+{
+	release_region(VRC4171_REGS_BASE, VRC4171_REGS_SIZE);
+}
+
+module_init(vrc4171_init);
+module_exit(vrc4171_exit);
--- diff/arch/s390/appldata/Makefile	1970-01-01 01:00:00.000000000 +0100
+++ source/arch/s390/appldata/Makefile	2004-02-23 13:56:39.000000000 +0000
@@ -0,0 +1,8 @@
+#
+# Makefile for the Linux - z/VM Monitor Stream.
+#
+
+obj-$(CONFIG_APPLDATA_BASE) += appldata_base.o
+obj-$(CONFIG_APPLDATA_MEM) += appldata_mem.o
+obj-$(CONFIG_APPLDATA_OS) += appldata_os.o
+obj-$(CONFIG_APPLDATA_NET_SUM) += appldata_net_sum.o
--- diff/arch/s390/appldata/appldata.h	1970-01-01 01:00:00.000000000 +0100
+++ source/arch/s390/appldata/appldata.h	2004-02-23 13:56:39.000000000 +0000
@@ -0,0 +1,59 @@
+/*
+ * arch/s390/appldata/appldata.h
+ *
+ * Definitions and interface for Linux - z/VM Monitor Stream.
+ *
+ * Copyright (C) 2003 IBM Corporation, IBM Deutschland Entwicklung GmbH.
+ *
+ * Author: Gerald Schaefer <geraldsc@de.ibm.com>
+ */
+
+//#define APPLDATA_DEBUG			/* Debug messages on/off */
+
+#define APPLDATA_MAX_REC_SIZE	  4024	/* Maximum size of the */
+					/* data buffer */
+#define APPLDATA_MAX_PROCS 100
+
+#define APPLDATA_PROC_NAME_LENGTH 16	/* Max. length of /proc name */
+
+#define APPLDATA_RECORD_MEM_ID		0x01	/* IDs to identify the */
+#define APPLDATA_RECORD_OS_ID		0x02	/* individual records, */
+#define APPLDATA_RECORD_NET_SUM_ID	0x03	/* must be < 256 !     */
+#define APPLDATA_RECORD_PROC_ID		0x04
+
+#define CTL_APPLDATA 		2120	/* sysctl IDs, must be unique */
+#define CTL_APPLDATA_TIMER 	2121
+#define CTL_APPLDATA_INTERVAL 	2122
+#define CTL_APPLDATA_MEM	2123
+#define CTL_APPLDATA_OS		2124
+#define CTL_APPLDATA_NET_SUM	2125
+#define CTL_APPLDATA_PROC	2126
+
+#define P_INFO(x...)	printk(KERN_INFO MY_PRINT_NAME " info: " x)
+#define P_ERROR(x...)	printk(KERN_ERR MY_PRINT_NAME " error: " x)
+#define P_WARNING(x...)	printk(KERN_WARNING MY_PRINT_NAME " status: " x)
+
+#ifdef APPLDATA_DEBUG
+#define P_DEBUG(x...)   printk(KERN_DEBUG MY_PRINT_NAME " debug: " x)
+#else
+#define P_DEBUG(x...)   do {} while (0)
+#endif
+
+struct appldata_ops {
+	struct list_head list;
+	struct ctl_table_header *sysctl_header;
+	struct ctl_table *ctl_table;
+	int    active;				/* monitoring status */
+
+	/* fill in from here */
+	unsigned int ctl_nr;			/* sysctl ID */
+	char name[APPLDATA_PROC_NAME_LENGTH];	/* name of /proc fs node */
+	unsigned char record_nr;		/* Record Nr. for Product ID */
+	void (*callback)(void *data);		/* callback function */
+	void *data;				/* record data */
+	unsigned int size;			/* size of record */
+	struct module *owner;			/* THIS_MODULE */
+};
+
+extern int appldata_register_ops(struct appldata_ops *ops);
+extern void appldata_unregister_ops(struct appldata_ops *ops);
--- diff/arch/s390/appldata/appldata_base.c	1970-01-01 01:00:00.000000000 +0100
+++ source/arch/s390/appldata/appldata_base.c	2004-02-23 13:56:39.000000000 +0000
@@ -0,0 +1,677 @@
+/*
+ * arch/s390/appldata/appldata_base.c
+ *
+ * Base infrastructure for Linux-z/VM Monitor Stream, Stage 1.
+ * Exports appldata_register_ops() and appldata_unregister_ops() for the
+ * data gathering modules.
+ *
+ * Copyright (C) 2003 IBM Corporation, IBM Deutschland Entwicklung GmbH.
+ *
+ * Author: Gerald Schaefer <geraldsc@de.ibm.com>
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/errno.h>
+#include <asm/uaccess.h>
+#include <asm/io.h>
+#include <linux/interrupt.h>
+#include <linux/proc_fs.h>
+#include <linux/page-flags.h>
+#include <linux/swap.h>
+#include <linux/pagemap.h>
+#include <linux/sysctl.h>
+#include <asm/timer.h>
+//#include <linux/kernel_stat.h>
+
+#include "appldata.h"
+
+
+#define MY_PRINT_NAME	"appldata"		/* for debug messages, etc. */
+#define APPLDATA_CPU_INTERVAL	10000		/* default (CPU) time for
+						   sampling interval in
+						   milliseconds */
+
+#define TOD_MICRO	0x01000			/* nr. of TOD clock units
+						   for 1 microsecond */
+#ifndef CONFIG_ARCH_S390X
+
+#define APPLDATA_START_INTERVAL_REC 0x00   	/* Function codes for */
+#define APPLDATA_STOP_REC	    0x01	/* DIAG 0xDC	  */
+#define APPLDATA_GEN_EVENT_RECORD   0x02
+#define APPLDATA_START_CONFIG_REC   0x03
+
+#else
+
+#define APPLDATA_START_INTERVAL_REC 0x80
+#define APPLDATA_STOP_REC   	    0x81
+#define APPLDATA_GEN_EVENT_RECORD   0x82
+#define APPLDATA_START_CONFIG_REC   0x83
+
+#endif /* CONFIG_ARCH_S390X */
+
+
+/*
+ * Parameter list for DIAGNOSE X'DC'
+ */
+#ifndef CONFIG_ARCH_S390X
+struct appldata_parameter_list {
+	u16 diag;		/* The DIAGNOSE code X'00DC'          */
+	u8  function;		/* The function code for the DIAGNOSE */
+	u8  parlist_length;	/* Length of the parameter list       */
+	u32 product_id_addr;	/* Address of the 16-byte product ID  */
+	u16 reserved;
+	u16 buffer_length;	/* Length of the application data buffer  */
+	u32 buffer_addr;	/* Address of the application data buffer */
+};
+#else
+struct appldata_parameter_list {
+	u16 diag;
+	u8  function;
+	u8  parlist_length;
+	u32 unused01;
+	u16 reserved;
+	u16 buffer_length;
+	u32 unused02;
+	u64 product_id_addr;
+	u64 buffer_addr;
+};
+#endif /* CONFIG_ARCH_S390X */
+
+/*
+ * /proc entries (sysctl)
+ */
+static const char appldata_proc_name[APPLDATA_PROC_NAME_LENGTH] = "appldata";
+static int appldata_timer_handler(ctl_table *ctl, int write, struct file *filp,
+		   		  void *buffer, size_t *lenp);
+static int appldata_interval_handler(ctl_table *ctl, int write,
+					 struct file *filp, void *buffer,
+					 size_t *lenp);
+
+static struct ctl_table_header *appldata_sysctl_header;
+static struct ctl_table appldata_table[] = {
+	{
+		.ctl_name	= CTL_APPLDATA_TIMER,
+		.procname	= "timer",
+		.mode		= S_IRUGO | S_IWUSR,
+		.proc_handler	= &appldata_timer_handler,
+	},
+	{
+		.ctl_name	= CTL_APPLDATA_INTERVAL,
+		.procname	= "interval",
+		.mode		= S_IRUGO | S_IWUSR,
+		.proc_handler	= &appldata_interval_handler,
+	},
+	{ .ctl_name = 0 }
+};
+
+static struct ctl_table appldata_dir_table[] = {
+	{
+		.ctl_name	= CTL_APPLDATA,
+		.procname	= appldata_proc_name,
+		.maxlen		= 0,
+		.mode		= S_IRUGO | S_IXUGO,
+		.child		= appldata_table,
+	},
+	{ .ctl_name = 0 }
+};
+
+/*
+ * Timer
+ */
+DEFINE_PER_CPU(struct vtimer_list, appldata_timer);
+static atomic_t appldata_expire_count = ATOMIC_INIT(0);
+static struct appldata_mod_vtimer_args {
+	struct vtimer_list *timer;
+	u64    expires;
+} appldata_mod_vtimer_args;
+
+static spinlock_t appldata_timer_lock = SPIN_LOCK_UNLOCKED;
+static int appldata_interval = APPLDATA_CPU_INTERVAL;
+static int appldata_timer_active;
+
+/*
+ * Tasklet
+ */
+static struct tasklet_struct appldata_tasklet_struct;
+
+/*
+ * Ops list
+ */
+static spinlock_t appldata_ops_lock = SPIN_LOCK_UNLOCKED;
+static LIST_HEAD(appldata_ops_list);
+
+
+/************************* timer, tasklet, DIAG ******************************/
+/*
+ * appldata_timer_function()
+ *
+ * schedule tasklet and reschedule timer
+ */
+static void appldata_timer_function(unsigned long data, struct pt_regs *regs)
+{
+	P_DEBUG("   -= Timer =-\n");
+	P_DEBUG("CPU: %i, expire: %i\n", smp_processor_id(),
+		atomic_read(&appldata_expire_count));
+	if (atomic_dec_and_test(&appldata_expire_count)) {
+		atomic_set(&appldata_expire_count, num_online_cpus());
+		tasklet_schedule((struct tasklet_struct *) data);
+	}
+}
+
+/*
+ * appldata_tasklet_function()
+ *
+ * call data gathering function for each (active) module
+ */
+static void appldata_tasklet_function(unsigned long data)
+{
+	struct list_head *lh;
+	struct appldata_ops *ops;
+	int i;
+
+	P_DEBUG("  -= Tasklet =-\n");
+	i = 0;
+	spin_lock(&appldata_ops_lock);
+	list_for_each(lh, &appldata_ops_list) {
+		ops = list_entry(lh, struct appldata_ops, list);
+		P_DEBUG("list_for_each loop: %i) active = %u, name = %s\n",
+			++i, ops->active, ops->name);
+		if (ops->active == 1) {
+			ops->callback(ops->data);
+		}
+	}
+	spin_unlock(&appldata_ops_lock);
+}
+
+/*
+ * appldata_mod_vtimer_wrap()
+ *
+ * wrapper function for mod_virt_timer(), because smp_call_function_on()
+ * accepts only one parameter.
+ */
+static void appldata_mod_vtimer_wrap(struct appldata_mod_vtimer_args *args) {
+	mod_virt_timer(args->timer, args->expires);
+}
+
+/*
+ * appldata_diag()
+ *
+ * prepare parameter list, issue DIAG 0xDC
+ */
+static int appldata_diag(char record_nr, u16 function, unsigned long buffer,
+			u16 length)
+{
+	unsigned long ry;
+	struct appldata_product_id {
+		char prod_nr[7];			/* product nr. */
+		char prod_fn[2];			/* product function */
+		char record_nr;				/* record nr. */
+		char version_nr[2];			/* version */
+		char release_nr[2];			/* release */
+		char mod_lvl[2];			/* modification lvl. */
+	} appldata_product_id = {
+	/* all strings are EBCDIC, record_nr is byte */
+		.prod_nr    = {0xD3, 0xC9, 0xD5, 0xE4,
+				0xE7, 0xD2, 0xD9},	/* "LINUXKR" */
+		.prod_fn    = {0xD5, 0xD3},		/* "NL" */
+		.record_nr  = record_nr,
+		.version_nr = {0xF2, 0xF6},		/* "26" */
+		.release_nr = {0xF0, 0xF1},		/* "01" */
+		.mod_lvl    = {0xF0, 0xF0},		/* "00" */
+	};
+	struct appldata_parameter_list appldata_parameter_list = {
+				.diag = 0xDC,
+				.function = function,
+				.parlist_length =
+					sizeof(appldata_parameter_list),
+				.buffer_length = length,
+				.product_id_addr =
+					(unsigned long) &appldata_product_id,
+				.buffer_addr = virt_to_phys((void *) buffer)
+	};
+
+        if (!MACHINE_IS_VM)
+                return -ENOSYS;
+	ry = -1;
+	asm volatile(
+			"diag %1,%0,0xDC\n\t"
+			: "=d" (ry) : "d" (&(appldata_parameter_list)) : "cc");
+	return (int) ry;
+}
+/********************** timer, tasklet, DIAG <END> ***************************/
+
+
+/****************************** /proc stuff **********************************/
+/*
+ * appldata_timer_handler()
+ *
+ * Start/Stop timer, show status of timer (0 = not active, 1 = active)
+ */
+static int
+appldata_timer_handler(ctl_table *ctl, int write, struct file *filp,
+			   void *buffer, size_t *lenp)
+{
+	int len, i;
+	char buf[2];
+	u64 per_cpu_interval;
+
+	if (!*lenp || filp->f_pos) {
+		*lenp = 0;
+		return 0;
+	}
+	if (!write) {
+		len = sprintf(buf, appldata_timer_active ? "1\n" : "0\n");
+		if (len > *lenp)
+			len = *lenp;
+		if (copy_to_user(buffer, buf, len))
+			return -EFAULT;
+		goto out;
+	}
+	per_cpu_interval = (u64) (appldata_interval*1000 /
+				 num_online_cpus()) * TOD_MICRO;
+	len = *lenp;
+	if (copy_from_user(buf, buffer, len > sizeof(buf) ? sizeof(buf) : len))
+		return -EFAULT;
+	spin_lock(&appldata_timer_lock);
+	per_cpu_interval = (u64) (appldata_interval*1000 /
+				 num_online_cpus()) * TOD_MICRO;
+	if ((buf[0] == '1') && (!appldata_timer_active)) {
+		for (i = 0; i < num_online_cpus(); i++) {
+			per_cpu(appldata_timer, i).expires = per_cpu_interval;
+			smp_call_function_on(add_virt_timer_periodic,
+						&per_cpu(appldata_timer, i),
+						0, 1, i);
+		}
+		appldata_timer_active = 1;
+		P_INFO("Monitoring timer started.\n");
+	} else if ((buf[0] == '0') && (appldata_timer_active)) {
+		for (i = 0; i < num_online_cpus(); i++) {
+			del_virt_timer(&per_cpu(appldata_timer, i));
+		}
+		appldata_timer_active = 0;
+		P_INFO("Monitoring timer stopped.\n");
+	}
+	spin_unlock(&appldata_timer_lock);
+out:
+	*lenp = len;
+	filp->f_pos += len;
+	return 0;
+}
+
+/*
+ * appldata_interval_handler()
+ *
+ * Set (CPU) timer interval for collection of data (in milliseconds), show
+ * current timer interval.
+ */
+static int
+appldata_interval_handler(ctl_table *ctl, int write, struct file *filp,
+			   void *buffer, size_t *lenp)
+{
+	int len, i, interval;
+	char buf[16];
+	u64 per_cpu_interval;
+
+	if (!*lenp || filp->f_pos) {
+		*lenp = 0;
+		return 0;
+	}
+	if (!write) {
+		len = sprintf(buf, "%i\n", appldata_interval);
+		if (len > *lenp)
+			len = *lenp;
+		if (copy_to_user(buffer, buf, len))
+			return -EFAULT;
+		goto out;
+	}
+	len = *lenp;
+	if (copy_from_user(buf, buffer, len > sizeof(buf) ? sizeof(buf) : len)) {
+		return -EFAULT;
+	}
+	sscanf(buf, "%i", &interval);
+	if (interval <= 0) {
+		P_ERROR("Timer CPU interval has to be > 0!\n");
+		return -EINVAL;
+	}
+	per_cpu_interval = (u64) (interval*1000 / num_online_cpus()) * TOD_MICRO;
+
+	spin_lock(&appldata_timer_lock);
+	appldata_interval = interval;
+	if (appldata_timer_active) {
+		for (i = 0; i < num_online_cpus(); i++) {
+			appldata_mod_vtimer_args.timer =
+					&per_cpu(appldata_timer, i);
+			appldata_mod_vtimer_args.expires =
+					per_cpu_interval;
+			smp_call_function_on(
+				(void *) appldata_mod_vtimer_wrap,
+				&appldata_mod_vtimer_args,
+				0, 1, i);
+		}
+	}
+	spin_unlock(&appldata_timer_lock);
+
+	P_INFO("Monitoring CPU interval set to %u milliseconds.\n",
+		 interval);
+out:
+	*lenp = len;
+	filp->f_pos += len;
+	return 0;
+}
+
+/*
+ * appldata_generic_handler()
+ *
+ * Generic start/stop monitoring and DIAG, show status of
+ * monitoring (0 = not in process, 1 = in process)
+ */
+static int
+appldata_generic_handler(ctl_table *ctl, int write, struct file *filp,
+			   void *buffer, size_t *lenp)
+{
+	struct appldata_ops *ops;
+	int rc, len;
+	char buf[2];
+
+	ops = ctl->data;
+	if (!*lenp || filp->f_pos) {
+		*lenp = 0;
+		return 0;
+	}
+	if (!write) {
+		len = sprintf(buf, ops->active ? "1\n" : "0\n");
+		if (len > *lenp)
+			len = *lenp;
+		if (copy_to_user(buffer, buf, len))
+			return -EFAULT;
+		goto out;
+	}
+	len = *lenp;
+	if (copy_from_user(buf, buffer, len > sizeof(buf) ? sizeof(buf) : len))
+		return -EFAULT;
+
+	spin_lock_bh(&appldata_ops_lock);
+	if ((buf[0] == '1') && (ops->active == 0)) {
+		ops->active = 1;
+		ops->callback(ops->data);	// init record
+		rc = appldata_diag(ops->record_nr,
+					APPLDATA_START_INTERVAL_REC,
+					(unsigned long) ops->data, ops->size);
+		if (rc != 0) {
+			P_ERROR("START DIAG 0xDC for %s failed, "
+				"return code: %d\n", ops->name, rc);
+			ops->active = 0;
+		} else {
+			P_INFO("Monitoring %s data enabled, "
+				"DIAG 0xDC started.\n", ops->name);
+		}
+	} else if ((buf[0] == '0') && (ops->active == 1)) {
+		ops->active = 0;
+		rc = appldata_diag(ops->record_nr, APPLDATA_STOP_REC,
+				(unsigned long) ops->data, ops->size);
+		if (rc != 0) {
+			P_ERROR("STOP DIAG 0xDC for %s failed, "
+				"return code: %d\n", ops->name, rc);
+		} else {
+			P_INFO("Monitoring %s data disabled, "
+				"DIAG 0xDC stopped.\n", ops->name);
+		}
+	}
+	spin_unlock_bh(&appldata_ops_lock);
+out:
+	*lenp = len;
+	filp->f_pos += len;
+	return 0;
+}
+
+/*************************** /proc stuff <END> *******************************/
+
+
+/************************* module-ops management *****************************/
+/*
+ * appldata_register_ops()
+ *
+ * update ops list, register /proc/sys entries
+ */
+int appldata_register_ops(struct appldata_ops *ops)
+{
+	struct list_head *lh;
+	struct appldata_ops *tmp_ops;
+	int rc, i;
+
+	rc = 0;
+	i = 0;
+
+	if ((ops->size > APPLDATA_MAX_REC_SIZE) ||
+		(ops->size < 0)){
+		P_ERROR("Invalid size of %s record = %i, maximum = %i!\n",
+			ops->name, ops->size, APPLDATA_MAX_REC_SIZE);
+		rc = -ENOMEM;
+		goto out;
+	}
+	if ((ops->ctl_nr == CTL_APPLDATA) ||
+	    (ops->ctl_nr == CTL_APPLDATA_TIMER) ||
+	    (ops->ctl_nr == CTL_APPLDATA_INTERVAL)) {
+		P_ERROR("ctl_nr %i already in use!\n", ops->ctl_nr);
+		rc = -EBUSY;
+		goto out;
+	}
+	ops->ctl_table = kmalloc(4*sizeof(struct ctl_table), GFP_KERNEL);
+	if (ops->ctl_table == NULL) {
+		P_ERROR("Not enough memory for %s ctl_table!\n", ops->name);
+		rc = -ENOMEM;
+		goto out;
+	}
+	memset(ops->ctl_table, 0, 4*sizeof(struct ctl_table));
+
+	spin_lock_bh(&appldata_ops_lock);
+	list_for_each(lh, &appldata_ops_list) {
+		tmp_ops = list_entry(lh, struct appldata_ops, list);
+		P_DEBUG("register_ops loop: %i) name = %s, ctl = %i\n",
+			++i, tmp_ops->name, tmp_ops->ctl_nr);
+		P_DEBUG("Comparing %s (ctl %i) with %s (ctl %i)\n",
+			tmp_ops->name, tmp_ops->ctl_nr, ops->name,
+			ops->ctl_nr);
+		if (strncmp(tmp_ops->name, ops->name,
+				APPLDATA_PROC_NAME_LENGTH) == 0) {
+			spin_unlock_bh(&appldata_ops_lock);
+			P_ERROR("Name \"%s\" already registered!\n", ops->name);
+			kfree(ops->ctl_table);
+			rc = -EBUSY;
+			goto out;
+		}
+		if (tmp_ops->ctl_nr == ops->ctl_nr) {
+			spin_unlock_bh(&appldata_ops_lock);
+			P_ERROR("ctl_nr %i already registered!\n", ops->ctl_nr);
+			kfree(ops->ctl_table);
+			rc = -EBUSY;
+			goto out;
+		}
+	}
+	list_add(&ops->list, &appldata_ops_list);
+	spin_unlock_bh(&appldata_ops_lock);
+
+	ops->ctl_table[0].ctl_name = CTL_APPLDATA;
+	ops->ctl_table[0].procname = appldata_proc_name;
+	ops->ctl_table[0].maxlen   = 0;
+	ops->ctl_table[0].mode     = S_IRUGO | S_IXUGO;
+	ops->ctl_table[0].child    = &ops->ctl_table[2];
+
+	ops->ctl_table[1].ctl_name = 0;
+
+	ops->ctl_table[2].ctl_name = ops->ctl_nr;
+	ops->ctl_table[2].procname = ops->name;
+	ops->ctl_table[2].mode     = S_IRUGO | S_IWUSR;
+	ops->ctl_table[2].proc_handler = appldata_generic_handler;
+	ops->ctl_table[2].data = ops;
+
+	ops->ctl_table[3].ctl_name = 0;
+
+	ops->sysctl_header = register_sysctl_table(ops->ctl_table,1);
+	ops->ctl_table[2].de->owner = ops->owner;
+	P_INFO("%s-ops registered!\n", ops->name);
+out:
+	return rc;
+}
+
+/*
+ * appldata_unregister_ops()
+ *
+ * update ops list, unregister /proc entries, stop DIAG if necessary
+ */
+void appldata_unregister_ops(struct appldata_ops *ops)
+{
+	int rc;
+
+	unregister_sysctl_table(ops->sysctl_header);
+	kfree(ops->ctl_table);
+	if (ops->active == 1) {
+		ops->active = 0;
+		rc = appldata_diag(ops->record_nr, APPLDATA_STOP_REC,
+				(unsigned long) ops->data, ops->size);
+		if (rc != 0) {
+			P_ERROR("STOP DIAG 0xDC for %s failed, "
+				"return code: %d\n", ops->name, rc);
+		} else {
+			P_INFO("Monitoring %s data disabled, "
+				"DIAG 0xDC stopped.\n", ops->name);
+		}
+
+	}
+	spin_lock_bh(&appldata_ops_lock);
+	list_del(&ops->list);
+	spin_unlock_bh(&appldata_ops_lock);
+	P_INFO("%s-ops unregistered!\n", ops->name);
+}
+/********************** module-ops management <END> **************************/
+
+
+/******************************* init / exit *********************************/
+/*
+ * appldata_init()
+ *
+ * init timer and tasklet, register /proc entries
+ */
+static int __init appldata_init(void)
+{
+	int i;
+
+	P_DEBUG("sizeof(parameter_list) = %lu\n",
+		sizeof(struct appldata_parameter_list));
+
+	for (i = 0; i < num_online_cpus(); i++) {
+		init_virt_timer(&per_cpu(appldata_timer, i));
+		per_cpu(appldata_timer, i).function = appldata_timer_function;
+		per_cpu(appldata_timer, i).data = (unsigned long)
+						&appldata_tasklet_struct;
+	}
+	atomic_set(&appldata_expire_count, num_online_cpus());
+
+	appldata_sysctl_header = register_sysctl_table(appldata_dir_table, 1);
+#ifdef MODULE
+	appldata_dir_table[0].de->owner = THIS_MODULE;
+	appldata_table[0].de->owner = THIS_MODULE;
+	appldata_table[1].de->owner = THIS_MODULE;
+#endif
+
+	tasklet_init(&appldata_tasklet_struct, appldata_tasklet_function, 0);
+	P_DEBUG("Base interface initialized.\n");
+	return 0;
+}
+
+/*
+ * appldata_exit()
+ *
+ * stop timer and tasklet, unregister /proc entries
+ */
+static void __exit appldata_exit(void)
+{
+	struct list_head *lh;
+	struct appldata_ops *ops;
+	int rc, i;
+
+	P_DEBUG("Unloading module ...\n");
+	/*
+	 * ops list should be empty, but just in case something went wrong...
+	 */
+	spin_lock_bh(&appldata_ops_lock);
+	list_for_each(lh, &appldata_ops_list) {
+		ops = list_entry(lh, struct appldata_ops, list);
+		rc = appldata_diag(ops->record_nr, APPLDATA_STOP_REC,
+				(unsigned long) ops->data, ops->size);
+		if (rc != 0) {
+			P_ERROR("STOP DIAG 0xDC for %s failed, "
+				"return code: %d\n", ops->name, rc);
+		}
+	}
+	spin_unlock_bh(&appldata_ops_lock);
+
+	for (i = 0; i < num_online_cpus(); i++) {
+		del_virt_timer(&per_cpu(appldata_timer, i));
+	}
+	appldata_timer_active = 0;
+
+	unregister_sysctl_table(appldata_sysctl_header);
+
+	tasklet_kill(&appldata_tasklet_struct);
+	P_DEBUG("... module unloaded!\n");
+}
+/**************************** init / exit <END> ******************************/
+
+
+module_init(appldata_init);
+module_exit(appldata_exit);
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Gerald Schaefer");
+MODULE_DESCRIPTION("Linux-VM Monitor Stream, base infrastructure");
+
+EXPORT_SYMBOL_GPL(appldata_register_ops);
+EXPORT_SYMBOL_GPL(appldata_unregister_ops);
+
+#ifdef MODULE
+/*
+ * Kernel symbols needed by appldata_mem and appldata_os modules.
+ * However, if this file is compiled as a module (for testing only), these
+ * symbols are not exported. In this case, we define them locally and export
+ * those.
+ */
+void si_swapinfo(struct sysinfo *val)
+{
+	val->freeswap = -1ul;
+	val->totalswap = -1ul;
+}
+
+unsigned long avenrun[3] = {-1 - FIXED_1/200, -1 - FIXED_1/200,
+				-1 - FIXED_1/200};
+int nr_threads = -1;
+
+void get_full_page_state(struct page_state *ps)
+{
+	memset(ps, -1, sizeof(struct page_state));
+}
+
+unsigned long nr_running(void)
+{
+	return -1;
+}
+
+unsigned long nr_iowait(void)
+{
+	return -1;
+}
+
+/*unsigned long nr_context_switches(void)
+{
+	return -1;
+}*/
+#endif /* MODULE */
+EXPORT_SYMBOL_GPL(si_swapinfo);
+EXPORT_SYMBOL_GPL(nr_threads);
+EXPORT_SYMBOL_GPL(avenrun);
+EXPORT_SYMBOL_GPL(get_full_page_state);
+EXPORT_SYMBOL_GPL(nr_running);
+EXPORT_SYMBOL_GPL(nr_iowait);
+//EXPORT_SYMBOL_GPL(nr_context_switches);
--- diff/arch/s390/appldata/appldata_mem.c	1970-01-01 01:00:00.000000000 +0100
+++ source/arch/s390/appldata/appldata_mem.c	2004-02-23 13:56:39.000000000 +0000
@@ -0,0 +1,183 @@
+/*
+ * arch/s390/appldata/appldata_mem.c
+ *
+ * Data gathering module for Linux-VM Monitor Stream, Stage 1.
+ * Collects data related to memory management.
+ *
+ * Copyright (C) 2003 IBM Corporation, IBM Deutschland Entwicklung GmbH.
+ *
+ * Author: Gerald Schaefer <geraldsc@de.ibm.com>
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/errno.h>
+#include <linux/kernel_stat.h>
+#include <asm/io.h>
+#include <linux/pagemap.h>
+#include <linux/swap.h>
+
+#include "appldata.h"
+
+
+#define MY_PRINT_NAME "appldata_mem"		/* for debug messages, etc. */
+#define P2K(x) ((x) << (PAGE_SHIFT - 10))	/* Converts #Pages to KB */
+
+/*
+ * Memory data
+ */
+struct appldata_mem_data {
+	u64 timestamp;
+	u32 sync_count_1;       /* after VM collected the record data, */
+	u32 sync_count_2;	/* sync_count_1 and sync_count_2 should be the
+				   same. If not, the record has been updated on
+				   the Linux side while VM was collecting the
+				   (possibly corrupt) data */
+
+	u64 pgpgin;		/* data read from disk  */
+	u64 pgpgout;		/* data written to disk */
+	u64 pswpin;		/* pages swapped in  */
+	u64 pswpout;		/* pages swapped out */
+
+	u64 sharedram;		/* sharedram is currently set to 0 */
+
+	u64 totalram;		/* total main memory size */
+	u64 freeram;		/* free main memory size  */
+	u64 totalhigh;		/* total high memory size */
+	u64 freehigh;		/* free high memory size  */
+
+	u64 bufferram;		/* memory reserved for buffers, free cache */
+	u64 cached;		/* size of (used) cache, w/o buffers */
+	u64 totalswap;		/* total swap space size */
+	u64 freeswap;		/* free swap space */
+
+// New in 2.6 -->
+	u64 pgalloc;		/* page allocations */
+	u64 pgfault;		/* page faults (major+minor) */
+	u64 pgmajfault;		/* page faults (major only) */
+// <-- New in 2.6
+
+} appldata_mem_data;
+
+
+static inline void appldata_debug_print(struct appldata_mem_data *mem_data)
+{
+	P_DEBUG("--- MEM - RECORD ---\n");
+	P_DEBUG("pgpgin     = %8lu KB\n", mem_data->pgpgin);
+	P_DEBUG("pgpgout    = %8lu KB\n", mem_data->pgpgout);
+	P_DEBUG("pswpin     = %8lu Pages\n", mem_data->pswpin);
+	P_DEBUG("pswpout    = %8lu Pages\n", mem_data->pswpout);
+	P_DEBUG("pgalloc    = %8lu \n", mem_data->pgalloc);
+	P_DEBUG("pgfault    = %8lu \n", mem_data->pgfault);
+	P_DEBUG("pgmajfault = %8lu \n", mem_data->pgmajfault);
+	P_DEBUG("sharedram  = %8lu KB\n", mem_data->sharedram);
+	P_DEBUG("totalram   = %8lu KB\n", mem_data->totalram);
+	P_DEBUG("freeram    = %8lu KB\n", mem_data->freeram);
+	P_DEBUG("totalhigh  = %8lu KB\n", mem_data->totalhigh);
+	P_DEBUG("freehigh   = %8lu KB\n", mem_data->freehigh);
+	P_DEBUG("bufferram  = %8lu KB\n", mem_data->bufferram);
+	P_DEBUG("cached     = %8lu KB\n", mem_data->cached);
+	P_DEBUG("totalswap  = %8lu KB\n", mem_data->totalswap);
+	P_DEBUG("freeswap   = %8lu KB\n", mem_data->freeswap);
+	P_DEBUG("sync_count_1 = %u\n", mem_data->sync_count_1);
+	P_DEBUG("sync_count_2 = %u\n", mem_data->sync_count_2);
+	P_DEBUG("timestamp    = %lX\n", mem_data->timestamp);
+}
+
+/*
+ * appldata_get_mem_data()
+ *
+ * gather memory data
+ */
+static void appldata_get_mem_data(void *data)
+{
+	struct sysinfo val;
+	struct page_state ps;
+	struct appldata_mem_data *mem_data;
+
+	mem_data = data;
+	mem_data->sync_count_1++;
+
+	get_full_page_state(&ps);
+	mem_data->pgpgin     = ps.pgpgin >> 1;
+	mem_data->pgpgout    = ps.pgpgout >> 1;
+	mem_data->pswpin     = ps.pswpin;
+	mem_data->pswpout    = ps.pswpout;
+	mem_data->pgalloc    = ps.pgalloc;
+	mem_data->pgfault    = ps.pgfault;
+	mem_data->pgmajfault = ps.pgmajfault;
+
+P_DEBUG("pgalloc = %lu, pgfree = %lu\n", ps.pgalloc, ps.pgfree);
+
+	si_meminfo(&val);
+	mem_data->sharedram = val.sharedram;
+	mem_data->totalram  = P2K(val.totalram);
+	mem_data->freeram   = P2K(val.freeram);
+	mem_data->totalhigh = P2K(val.totalhigh);
+	mem_data->freehigh  = P2K(val.freehigh);
+	mem_data->bufferram = P2K(val.bufferram);
+	mem_data->cached    = P2K(atomic_read(&nr_pagecache) - val.bufferram);
+
+	si_swapinfo(&val);
+	mem_data->totalswap = P2K(val.totalswap);
+	mem_data->freeswap  = P2K(val.freeswap);
+
+	mem_data->timestamp = get_clock();
+	mem_data->sync_count_2++;
+#ifdef APPLDATA_DEBUG
+	appldata_debug_print(mem_data);
+#endif
+}
+
+
+static struct appldata_ops ops = {
+	.ctl_nr    = CTL_APPLDATA_MEM,
+	.name      = "mem",
+	.record_nr = APPLDATA_RECORD_MEM_ID,
+	.size	   = sizeof(struct appldata_mem_data),
+	.callback  = &appldata_get_mem_data,
+	.data      = &appldata_mem_data,
+	.owner     = THIS_MODULE,
+};
+
+
+/*
+ * appldata_mem_init()
+ *
+ * init_data, register ops
+ */
+static int __init appldata_mem_init(void)
+{
+	int rc;
+
+	P_DEBUG("sizeof(mem) = %lu\n", sizeof(struct appldata_mem_data));
+
+	rc = appldata_register_ops(&ops);
+	if (rc != 0) {
+		P_ERROR("Error registering ops, rc = %i\n", rc);
+	} else {
+		P_DEBUG("%s-ops registered!\n", ops.name);
+	}
+	return rc;
+}
+
+/*
+ * appldata_mem_exit()
+ *
+ * unregister ops
+ */
+static void __exit appldata_mem_exit(void)
+{
+	appldata_unregister_ops(&ops);
+	P_DEBUG("%s-ops unregistered!\n", ops.name);
+}
+
+
+module_init(appldata_mem_init);
+module_exit(appldata_mem_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Gerald Schaefer");
+MODULE_DESCRIPTION("Linux-VM Monitor Stream, MEMORY statistics");
--- diff/arch/s390/appldata/appldata_net_sum.c	1970-01-01 01:00:00.000000000 +0100
+++ source/arch/s390/appldata/appldata_net_sum.c	2004-02-23 13:56:39.000000000 +0000
@@ -0,0 +1,187 @@
+/*
+ * arch/s390/appldata/appldata_net_sum.c
+ *
+ * Data gathering module for Linux-VM Monitor Stream, Stage 1.
+ * Collects accumulated network statistics (Packets received/transmitted,
+ * dropped, errors, ...).
+ *
+ * Copyright (C) 2003 IBM Corporation, IBM Deutschland Entwicklung GmbH.
+ *
+ * Author: Gerald Schaefer <geraldsc@de.ibm.com>
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/errno.h>
+#include <linux/kernel_stat.h>
+#include <linux/netdevice.h>
+
+#include "appldata.h"
+
+
+#define MY_PRINT_NAME	"appldata_net_sum"	/* for debug messages, etc. */
+
+
+/*
+ * Network data
+ */
+struct appldata_net_sum_data {
+	u64 timestamp;
+	u32 sync_count_1;	/* after VM collected the record data, */
+	u32 sync_count_2;	/* sync_count_1 and sync_count_2 should be the
+				   same. If not, the record has been updated on
+				   the Linux side while VM was collecting the
+				   (possibly corrupt) data */
+
+	u32 nr_interfaces;	/* nr. of network interfaces being monitored */
+
+	u32 padding;		/* next value is 64-bit aligned, so these */
+				/* 4 byte would be padded out by compiler */
+
+	u64 rx_packets;		/* total packets received        */
+	u64 tx_packets;		/* total packets transmitted     */
+	u64 rx_bytes;		/* total bytes received          */
+	u64 tx_bytes;		/* total bytes transmitted       */
+	u64 rx_errors;		/* bad packets received          */
+	u64 tx_errors;		/* packet transmit problems      */
+	u64 rx_dropped;		/* no space in linux buffers     */
+	u64 tx_dropped;		/* no space available in linux   */
+	u64 collisions;		/* collisions while transmitting */
+} appldata_net_sum_data;
+
+
+static inline void appldata_print_debug(struct appldata_net_sum_data *net_data)
+{
+	P_DEBUG("--- NET - RECORD ---\n");
+
+	P_DEBUG("nr_interfaces = %u\n", net_data->nr_interfaces);
+	P_DEBUG("rx_packets    = %8lu\n", net_data->rx_packets);
+	P_DEBUG("tx_packets    = %8lu\n", net_data->tx_packets);
+	P_DEBUG("rx_bytes      = %8lu\n", net_data->rx_bytes);
+	P_DEBUG("tx_bytes      = %8lu\n", net_data->tx_bytes);
+	P_DEBUG("rx_errors     = %8lu\n", net_data->rx_errors);
+	P_DEBUG("tx_errors     = %8lu\n", net_data->tx_errors);
+	P_DEBUG("rx_dropped    = %8lu\n", net_data->rx_dropped);
+	P_DEBUG("tx_dropped    = %8lu\n", net_data->tx_dropped);
+	P_DEBUG("collisions    = %8lu\n", net_data->collisions);
+
+	P_DEBUG("sync_count_1 = %u\n", net_data->sync_count_1);
+	P_DEBUG("sync_count_2 = %u\n", net_data->sync_count_2);
+	P_DEBUG("timestamp    = %lX\n", net_data->timestamp);
+}
+
+/*
+ * appldata_get_net_sum_data()
+ *
+ * gather accumulated network statistics
+ */
+static void appldata_get_net_sum_data(void *data)
+{
+	int i;
+	struct appldata_net_sum_data *net_data;
+	struct net_device *dev;
+	struct net_device_stats *stats;
+	unsigned long rx_packets, tx_packets, rx_bytes, tx_bytes, rx_errors,
+			tx_errors, rx_dropped, tx_dropped, collisions;
+
+	net_data = data;
+	net_data->sync_count_1++;
+
+	i = 0;
+	rx_packets = 0;
+	tx_packets = 0;
+	rx_bytes   = 0;
+	tx_bytes   = 0;
+	rx_errors  = 0;
+	tx_errors  = 0;
+	rx_dropped = 0;
+	tx_dropped = 0;
+	collisions = 0;
+	read_lock(&dev_base_lock);
+	for (dev = dev_base; dev != NULL; dev = dev->next) {
+		if (dev->get_stats == NULL) {
+			continue;
+		}
+		stats = dev->get_stats(dev);
+		rx_packets += stats->rx_packets;
+		tx_packets += stats->tx_packets;
+		rx_bytes   += stats->rx_bytes;
+		tx_bytes   += stats->tx_bytes;
+		rx_errors  += stats->rx_errors;
+		tx_errors  += stats->tx_errors;
+		rx_dropped += stats->rx_dropped;
+		tx_dropped += stats->tx_dropped;
+		collisions += stats->collisions;
+		i++;
+	}
+	read_unlock(&dev_base_lock);
+	net_data->nr_interfaces = i;
+	net_data->rx_packets = rx_packets;
+	net_data->tx_packets = tx_packets;
+	net_data->rx_bytes   = rx_bytes;
+	net_data->tx_bytes   = tx_bytes;
+	net_data->rx_errors  = rx_errors;
+	net_data->tx_errors  = tx_errors;
+	net_data->rx_dropped = rx_dropped;
+	net_data->tx_dropped = tx_dropped;
+	net_data->collisions = collisions;
+
+	net_data->timestamp = get_clock();
+	net_data->sync_count_2++;
+#ifdef APPLDATA_DEBUG
+	appldata_print_debug(net_data);
+#endif
+}
+
+
+static struct appldata_ops ops = {
+	.ctl_nr    = CTL_APPLDATA_NET_SUM,
+	.name	   = "net_sum",
+	.record_nr = APPLDATA_RECORD_NET_SUM_ID,
+	.size	   = sizeof(struct appldata_net_sum_data),
+	.callback  = &appldata_get_net_sum_data,
+	.data      = &appldata_net_sum_data,
+	.owner     = THIS_MODULE,
+};
+
+
+/*
+ * appldata_net_init()
+ *
+ * init data, register ops
+ */
+static int __init appldata_net_init(void)
+{
+	int rc;
+
+	P_DEBUG("sizeof(net) = %lu\n", sizeof(struct appldata_net_sum_data));
+
+	rc = appldata_register_ops(&ops);
+	if (rc != 0) {
+		P_ERROR("Error registering ops, rc = %i\n", rc);
+	} else {
+		P_DEBUG("%s-ops registered!\n", ops.name);
+	}
+	return rc;
+}
+
+/*
+ * appldata_net_exit()
+ *
+ * unregister ops
+ */
+static void __exit appldata_net_exit(void)
+{
+	appldata_unregister_ops(&ops);
+	P_DEBUG("%s-ops unregistered!\n", ops.name);
+}
+
+
+module_init(appldata_net_init);
+module_exit(appldata_net_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Gerald Schaefer");
+MODULE_DESCRIPTION("Linux-VM Monitor Stream, accumulated network statistics");
--- diff/arch/s390/appldata/appldata_os.c	1970-01-01 01:00:00.000000000 +0100
+++ source/arch/s390/appldata/appldata_os.c	2004-02-23 13:56:39.000000000 +0000
@@ -0,0 +1,231 @@
+/*
+ * arch/s390/appldata/appldata_os.c
+ *
+ * Data gathering module for Linux-VM Monitor Stream, Stage 1.
+ * Collects misc. OS related data (CPU utilization, running processes).
+ *
+ * Copyright (C) 2003 IBM Corporation, IBM Deutschland Entwicklung GmbH.
+ *
+ * Author: Gerald Schaefer <geraldsc@de.ibm.com>
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/errno.h>
+#include <linux/kernel_stat.h>
+#include <linux/netdevice.h>
+#include <linux/sched.h>
+#include <asm/smp.h>
+
+#include "appldata.h"
+
+
+#define MY_PRINT_NAME	"appldata_os"		/* for debug messages, etc. */
+#define LOAD_INT(x) ((x) >> FSHIFT)
+#define LOAD_FRAC(x) LOAD_INT(((x) & (FIXED_1-1)) * 100)
+
+/*
+ * OS data
+ */
+struct appldata_os_per_cpu {
+	u32 per_cpu_user;	/* timer ticks spent in user mode   */
+	u32 per_cpu_nice;	/* ... spent with modified priority */
+	u32 per_cpu_system;	/* ... spent in kernel mode         */
+	u32 per_cpu_idle;	/* ... spent in idle mode           */
+
+// New in 2.6 -->
+	u32 per_cpu_irq;	/* ... spent in interrupts          */
+	u32 per_cpu_softirq;	/* ... spent in softirqs            */
+	u32 per_cpu_iowait;	/* ... spent while waiting for I/O  */
+// <-- New in 2.6
+};
+
+struct appldata_os_data {
+	u64 timestamp;
+	u32 sync_count_1;	/* after VM collected the record data, */
+	u32 sync_count_2;	/* sync_count_1 and sync_count_2 should be the
+				   same. If not, the record has been updated on
+				   the Linux side while VM was collecting the
+				   (possibly corrupt) data */
+
+	u32 nr_cpus;		/* number of (virtual) CPUs        */
+	u32 per_cpu_size;	/* size of the per-cpu data struct */
+	u32 cpu_offset;		/* offset of the first per-cpu data struct */
+
+	u32 nr_running;		/* number of runnable threads      */
+	u32 nr_threads;		/* number of threads               */
+	u32 avenrun[3];		/* average nr. of running processes during */
+				/* the last 1, 5 and 15 minutes */
+
+// New in 2.6 -->
+	u32 nr_iowait;		/* number of blocked threads
+				   (waiting for I/O)               */
+// <-- New in 2.6
+
+	/* per cpu data */
+	struct appldata_os_per_cpu os_cpu[0];
+};
+
+static struct appldata_os_data *appldata_os_data;
+
+
+static inline void appldata_print_debug(struct appldata_os_data *os_data)
+{
+	int a0, a1, a2, i;
+
+	P_DEBUG("--- OS - RECORD ---\n");
+	P_DEBUG("nr_threads   = %u\n", os_data->nr_threads);
+	P_DEBUG("nr_running   = %u\n", os_data->nr_running);
+	P_DEBUG("nr_iowait    = %u\n", os_data->nr_iowait);
+	P_DEBUG("avenrun(int) = %8x / %8x / %8x\n", os_data->avenrun[0],
+		os_data->avenrun[1], os_data->avenrun[2]);
+	a0 = os_data->avenrun[0];
+	a1 = os_data->avenrun[1];
+	a2 = os_data->avenrun[2];
+	P_DEBUG("avenrun(float) = %d.%02d / %d.%02d / %d.%02d\n",
+		LOAD_INT(a0), LOAD_FRAC(a0), LOAD_INT(a1), LOAD_FRAC(a1),
+		LOAD_INT(a2), LOAD_FRAC(a2));
+
+	P_DEBUG("nr_cpus = %u\n", os_data->nr_cpus);
+	for (i = 0; i < NR_CPUS; i++) {
+		if (!cpu_online(i)) continue;
+		P_DEBUG("cpu%u : user = %u, nice = %u, system = %u, "
+			"idle = %u, irq = %u, softirq = %u, iowait = %u\n",
+				i,
+				os_data->os_cpu[i].per_cpu_user,
+				os_data->os_cpu[i].per_cpu_nice,
+				os_data->os_cpu[i].per_cpu_system,
+				os_data->os_cpu[i].per_cpu_idle,
+				os_data->os_cpu[i].per_cpu_irq,
+				os_data->os_cpu[i].per_cpu_softirq,
+				os_data->os_cpu[i].per_cpu_iowait);
+	}
+
+	P_DEBUG("sync_count_1 = %u\n", os_data->sync_count_1);
+	P_DEBUG("sync_count_2 = %u\n", os_data->sync_count_2);
+	P_DEBUG("timestamp    = %lX\n", os_data->timestamp);
+}
+
+/*
+ * appldata_get_os_data()
+ *
+ * gather OS data
+ */
+static void appldata_get_os_data(void *data)
+{
+	int i;
+	struct appldata_os_data *os_data;
+
+	os_data = data;
+	os_data->sync_count_1++;
+
+	os_data->nr_cpus = num_online_cpus();
+
+	os_data->nr_threads = nr_threads;
+	os_data->nr_running = nr_running();
+	os_data->nr_iowait  = nr_iowait();
+	os_data->avenrun[0] = avenrun[0] + (FIXED_1/200);
+	os_data->avenrun[1] = avenrun[1] + (FIXED_1/200);
+	os_data->avenrun[2] = avenrun[2] + (FIXED_1/200);
+
+	for (i = 0; i < num_online_cpus(); i++) {
+		os_data->os_cpu[i].per_cpu_user =
+					kstat_cpu(i).cpustat.user;
+		os_data->os_cpu[i].per_cpu_nice =
+					kstat_cpu(i).cpustat.nice;
+		os_data->os_cpu[i].per_cpu_system =
+					kstat_cpu(i).cpustat.system;
+		os_data->os_cpu[i].per_cpu_idle =
+					kstat_cpu(i).cpustat.idle;
+		os_data->os_cpu[i].per_cpu_irq =
+					kstat_cpu(i).cpustat.irq;
+		os_data->os_cpu[i].per_cpu_softirq =
+					kstat_cpu(i).cpustat.softirq;
+		os_data->os_cpu[i].per_cpu_iowait =
+					kstat_cpu(i).cpustat.iowait;
+	}
+
+	os_data->timestamp = get_clock();
+	os_data->sync_count_2++;
+#ifdef APPLDATA_DEBUG
+	appldata_print_debug(os_data);
+#endif
+}
+
+
+static struct appldata_ops ops = {
+	.ctl_nr    = CTL_APPLDATA_OS,
+	.name	   = "os",
+	.record_nr = APPLDATA_RECORD_OS_ID,
+	.callback  = &appldata_get_os_data,
+	.owner     = THIS_MODULE,
+};
+
+
+/*
+ * appldata_os_init()
+ *
+ * init data, register ops
+ */
+static int __init appldata_os_init(void)
+{
+	int rc, size;
+
+	size = sizeof(struct appldata_os_data) +
+		(NR_CPUS * sizeof(struct appldata_os_per_cpu));
+	if (size > APPLDATA_MAX_REC_SIZE) {
+		P_ERROR("Size of record = %i, bigger than maximum (%i)!\n",
+			size, APPLDATA_MAX_REC_SIZE);
+		rc = -ENOMEM;
+		goto out;
+	}
+	P_DEBUG("sizeof(os) = %i, sizeof(os_cpu) = %lu\n", size,
+		sizeof(struct appldata_os_per_cpu));
+
+	appldata_os_data = kmalloc(size, GFP_DMA);
+	if (appldata_os_data == NULL) {
+		P_ERROR("No memory for %s!\n", ops.name);
+		rc = -ENOMEM;
+		goto out;
+	}
+	memset(appldata_os_data, 0, size);
+
+	appldata_os_data->per_cpu_size = sizeof(struct appldata_os_per_cpu);
+	appldata_os_data->cpu_offset   = offsetof(struct appldata_os_data,
+							os_cpu);
+	P_DEBUG("cpu offset = %u\n", appldata_os_data->cpu_offset);
+
+	ops.data = appldata_os_data;
+	ops.size = size;
+	rc = appldata_register_ops(&ops);
+	if (rc != 0) {
+		P_ERROR("Error registering ops, rc = %i\n", rc);
+		kfree(appldata_os_data);
+	} else {
+		P_DEBUG("%s-ops registered!\n", ops.name);
+	}
+out:
+	return rc;
+}
+
+/*
+ * appldata_os_exit()
+ *
+ * unregister ops
+ */
+static void __exit appldata_os_exit(void)
+{
+	appldata_unregister_ops(&ops);
+	kfree(appldata_os_data);
+	P_DEBUG("%s-ops unregistered!\n", ops.name);
+}
+
+
+module_init(appldata_os_init);
+module_exit(appldata_os_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Gerald Schaefer");
+MODULE_DESCRIPTION("Linux-VM Monitor Stream, OS statistics");
--- diff/arch/s390/lib/strcpy.S	1970-01-01 01:00:00.000000000 +0100
+++ source/arch/s390/lib/strcpy.S	2004-02-23 13:56:39.000000000 +0000
@@ -0,0 +1,20 @@
+/*
+ *  arch/s390/kernel/strcpy.S
+ *    S390 strcpy routine
+ *
+ *  S390 version
+ *    Copyright (C) 2004 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ *    Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com),
+ */
+
+/*
+ * R2 = address of destination
+ * R3 = address of source string
+ */
+        .globl   strcpy
+strcpy:
+	sr	%r0,%r0
+0:	mvst	%r2,%r3
+	jo	0b
+	br	%r14
+
--- diff/arch/s390/lib/strcpy64.S	1970-01-01 01:00:00.000000000 +0100
+++ source/arch/s390/lib/strcpy64.S	2004-02-23 13:56:39.000000000 +0000
@@ -0,0 +1,20 @@
+/*
+ *  arch/s390/kernel/strcpy.S
+ *    S390 strcpy routine
+ *
+ *  S390 version
+ *    Copyright (C) 2004 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ *    Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com),
+ */
+
+/*
+ * R2 = address of destination
+ * R3 = address of source string
+ */
+        .globl   strcpy
+strcpy:
+	sgr	%r0,%r0
+0:	mvst	%r2,%r3
+	jo	0b
+	br	%r14
+
--- diff/arch/s390/mm/cmm.c	1970-01-01 01:00:00.000000000 +0100
+++ source/arch/s390/mm/cmm.c	2004-02-23 13:56:39.000000000 +0000
@@ -0,0 +1,445 @@
+/*
+ *  arch/s390/mm/cmm.c
+ *
+ *  S390 version
+ *    Copyright (C) 2003 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ *    Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com)
+ *
+ *  Collaborative memory management interface.
+ */
+
+#include <linux/config.h>
+#include <linux/errno.h>
+#include <linux/fs.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/sysctl.h>
+#include <linux/ctype.h>
+
+#include <asm/pgalloc.h>
+#include <asm/uaccess.h>
+
+#include "../../../drivers/s390/net/smsgiucv.h"
+
+#define CMM_NR_PAGES ((PAGE_SIZE / sizeof(unsigned long)) - 2)
+
+struct cmm_page_array {
+	struct cmm_page_array *next;
+	unsigned long index;
+	unsigned long pages[CMM_NR_PAGES];
+};
+
+static long cmm_pages = 0;
+static long cmm_timed_pages = 0;
+static volatile long cmm_pages_target = 0;
+static volatile long cmm_timed_pages_target = 0;
+static long cmm_timeout_pages = 0;
+static long cmm_timeout_seconds = 0;
+
+static struct cmm_page_array *cmm_page_list = 0;
+static struct cmm_page_array *cmm_timed_page_list = 0;
+
+static unsigned long cmm_thread_active = 0;
+static struct work_struct cmm_thread_starter;
+static wait_queue_head_t cmm_thread_wait;
+static struct timer_list cmm_timer;
+
+static void cmm_timer_fn(unsigned long);
+static void cmm_set_timer(void);
+
+static long
+cmm_strtoul(const char *cp, char **endp)
+{
+	unsigned int base = 10;
+
+	if (*cp == '0') {
+		base = 8;
+		cp++;
+		if ((*cp == 'x' || *cp == 'X') && isxdigit(cp[1])) {
+			base = 16;
+			cp++;
+		}
+	}
+	return simple_strtoul(cp, endp, base);
+}
+
+static long
+cmm_alloc_pages(long pages, long *counter, struct cmm_page_array **list)
+{
+	struct cmm_page_array *pa;
+	unsigned long page;
+
+	pa = *list;
+	while (pages) {
+		page = __get_free_page(GFP_NOIO);
+		if (!page)
+			break;
+		if (!pa || pa->index >= CMM_NR_PAGES) {
+			/* Need a new page for the page list. */
+			pa = (struct cmm_page_array *)
+				__get_free_page(GFP_NOIO);
+			if (!pa) {
+				free_page(page);
+				break;
+			}
+			pa->next = *list;
+			pa->index = 0;
+			*list = pa;
+		}
+		if (page < 0x80000000UL)
+			diag10(page);
+		pa->pages[pa->index++] = page;
+		(*counter)++;
+		pages--;
+	}
+	return pages;
+}
+
+static void
+cmm_free_pages(long pages, long *counter, struct cmm_page_array **list)
+{
+	struct cmm_page_array *pa;
+	unsigned long page;
+
+	pa = *list;
+	while (pages) {
+		if (!pa || pa->index <= 0)
+			break;
+		page = pa->pages[--pa->index];
+		if (pa->index == 0) {
+			pa = pa->next;
+			free_page((unsigned long) *list);
+			*list = pa;
+		}
+		free_page(page);
+		(*counter)--;
+		pages--;
+	}
+}
+
+static int
+cmm_thread(void *dummy)
+{
+	int rc;
+
+	daemonize("cmmthread");
+	set_cpus_allowed(current, cpumask_of_cpu(0));
+	while (1) {
+		rc = wait_event_interruptible(cmm_thread_wait,
+			(cmm_pages != cmm_pages_target ||
+			 cmm_timed_pages != cmm_timed_pages_target));
+		if (rc == -ERESTARTSYS) {
+			/* Got kill signal. End thread. */
+			clear_bit(0, &cmm_thread_active);
+			cmm_pages_target = cmm_pages;
+			cmm_timed_pages_target = cmm_timed_pages;
+			break;
+		}
+		if (cmm_pages_target > cmm_pages) {
+			if (cmm_alloc_pages(1, &cmm_pages, &cmm_page_list))
+				cmm_pages_target = cmm_pages;
+		} else if (cmm_pages_target < cmm_pages) {
+			cmm_free_pages(1, &cmm_pages, &cmm_page_list);
+		}
+		if (cmm_timed_pages_target > cmm_timed_pages) {
+			if (cmm_alloc_pages(1, &cmm_timed_pages,
+					   &cmm_timed_page_list))
+				cmm_timed_pages_target = cmm_timed_pages;
+		} else if (cmm_timed_pages_target < cmm_timed_pages) {
+			cmm_free_pages(1, &cmm_timed_pages,
+			       	       &cmm_timed_page_list);
+		}
+		if (cmm_timed_pages > 0 && !timer_pending(&cmm_timer))
+			cmm_set_timer();
+	}
+	return 0;
+}
+
+static void
+cmm_start_thread(void)
+{
+	kernel_thread(cmm_thread, 0, 0);
+}
+
+static void
+cmm_kick_thread(void)
+{
+	if (!test_and_set_bit(0, &cmm_thread_active))
+		schedule_work(&cmm_thread_starter);
+	wake_up(&cmm_thread_wait);
+}
+
+static void
+cmm_set_timer(void)
+{
+	if (cmm_timed_pages_target <= 0 || cmm_timeout_seconds <= 0) {
+		if (timer_pending(&cmm_timer))
+			del_timer(&cmm_timer);
+		return;
+	}
+	if (timer_pending(&cmm_timer)) {
+		if (mod_timer(&cmm_timer, jiffies + cmm_timeout_seconds*HZ))
+			return;
+	}
+	cmm_timer.function = cmm_timer_fn;
+	cmm_timer.data = 0;
+	cmm_timer.expires = jiffies + cmm_timeout_seconds*HZ;
+	add_timer(&cmm_timer);
+}
+
+static void
+cmm_timer_fn(unsigned long ignored)
+{
+	long pages;
+
+	pages = cmm_timed_pages_target - cmm_timeout_pages;
+	if (pages < 0)
+		cmm_timed_pages_target = 0;
+	else
+		cmm_timed_pages_target = pages;
+	cmm_kick_thread();
+	cmm_set_timer();
+}
+
+void
+cmm_set_pages(long pages)
+{
+	cmm_pages_target = pages;
+	cmm_kick_thread();
+}
+
+long
+cmm_get_pages(void)
+{
+	return cmm_pages;
+}
+
+void
+cmm_add_timed_pages(long pages)
+{
+	cmm_timed_pages_target += pages;
+	cmm_kick_thread();
+}
+
+long
+cmm_get_timed_pages(void)
+{
+	return cmm_timed_pages;
+}
+
+void
+cmm_set_timeout(long pages, long seconds)
+{
+	cmm_timeout_pages = pages;
+	cmm_timeout_seconds = seconds;
+	cmm_set_timer();
+}
+
+static inline int
+cmm_skip_blanks(char *cp, char **endp)
+{
+	char *str;
+
+	for (str = cp; *str == ' ' || *str == '\t'; str++);
+	*endp = str;
+	return str != cp;
+}
+
+#ifdef CONFIG_CMM_PROC
+/* These will someday get removed. */
+#define VM_CMM_PAGES		1111
+#define VM_CMM_TIMED_PAGES	1112
+#define VM_CMM_TIMEOUT		1113
+
+static struct ctl_table cmm_table[];
+
+static int
+cmm_pages_handler(ctl_table *ctl, int write, struct file *filp,
+		  void *buffer, size_t *lenp)
+{
+	char buf[16], *p;
+	long pages;
+	int len;
+
+	if (!*lenp || (filp->f_pos && !write)) {
+		*lenp = 0;
+		return 0;
+	}
+
+	if (write) {
+		len = *lenp;
+		if (copy_from_user(buf, buffer,
+				   len > sizeof(buf) ? sizeof(buf) : len))
+			return -EFAULT;
+		buf[sizeof(buf) - 1] = '\0';
+		cmm_skip_blanks(buf, &p);
+		pages = cmm_strtoul(p, &p);
+		if (ctl == &cmm_table[0])
+			cmm_set_pages(pages);
+		else
+			cmm_add_timed_pages(pages);
+	} else {
+		if (ctl == &cmm_table[0])
+			pages = cmm_get_pages();
+		else
+			pages = cmm_get_timed_pages();
+		len = sprintf(buf, "%ld\n", pages);
+		if (len > *lenp)
+			len = *lenp;
+		if (copy_to_user(buffer, buf, len))
+			return -EFAULT;
+	}
+	*lenp = len;
+	filp->f_pos += len;
+	return 0;
+}
+
+static int
+cmm_timeout_handler(ctl_table *ctl, int write, struct file *filp,
+		    void *buffer, size_t *lenp)
+{
+	char buf[64], *p;
+	long pages, seconds;
+	int len;
+
+	if (!*lenp || (filp->f_pos && !write)) {
+		*lenp = 0;
+		return 0;
+	}
+
+	if (write) {
+		len = *lenp;
+		if (copy_from_user(buf, buffer,
+				   len > sizeof(buf) ? sizeof(buf) : len))
+			return -EFAULT;
+		buf[sizeof(buf) - 1] = '\0';
+		cmm_skip_blanks(buf, &p);
+		pages = cmm_strtoul(p, &p);
+		cmm_skip_blanks(p, &p);
+		seconds = cmm_strtoul(p, &p);
+		cmm_set_timeout(pages, seconds);
+	} else {
+		len = sprintf(buf, "%ld %ld\n",
+			      cmm_timeout_pages, cmm_timeout_seconds);
+		if (len > *lenp)
+			len = *lenp;
+		if (copy_to_user(buffer, buf, len))
+			return -EFAULT;
+	}
+	*lenp = len;
+	filp->f_pos += len;
+	return 0;
+}
+
+static struct ctl_table cmm_table[] = {
+	{
+		.ctl_name	= VM_CMM_PAGES,
+		.procname	= "cmm_pages",
+		.mode		= 0600,
+		.proc_handler	= &cmm_pages_handler,
+	},
+	{
+		.ctl_name	= VM_CMM_TIMED_PAGES,
+		.procname	= "cmm_timed_pages",
+		.mode		= 0600,
+		.proc_handler	= &cmm_pages_handler,
+	},
+	{
+		.ctl_name	= VM_CMM_TIMEOUT,
+		.procname	= "cmm_timeout",
+		.mode		= 0600,
+		.proc_handler	= &cmm_timeout_handler,
+	},
+	{ .ctl_name = 0 }
+};
+
+static struct ctl_table cmm_dir_table[] = {
+	{
+		.ctl_name	= CTL_VM,
+		.procname	= "vm",
+		.maxlen		= 0,
+		.mode		= 0555,
+		.child		= cmm_table,
+	},
+	{ .ctl_name = 0 }
+};
+#endif
+
+#ifdef CONFIG_CMM_IUCV
+#define SMSG_PREFIX "CMM"
+static void
+cmm_smsg_target(char *msg)
+{
+	long pages, seconds;
+
+	if (!cmm_skip_blanks(msg + strlen(SMSG_PREFIX), &msg))
+		return;
+	if (strncmp(msg, "SHRINK", 6) == 0) {
+		if (!cmm_skip_blanks(msg + 6, &msg))
+			return;
+		pages = cmm_strtoul(msg, &msg);
+		cmm_skip_blanks(msg, &msg);
+		if (*msg == '\0')
+			cmm_set_pages(pages);
+	} else if (strncmp(msg, "RELEASE", 7) == 0) {
+		if (!cmm_skip_blanks(msg + 7, &msg))
+			return;
+		pages = cmm_strtoul(msg, &msg);
+		cmm_skip_blanks(msg, &msg);
+		if (*msg == '\0')
+			cmm_add_timed_pages(pages);
+	} else if (strncmp(msg, "REUSE", 5) == 0) {
+		if (!cmm_skip_blanks(msg + 5, &msg))
+			return;
+		pages = cmm_strtoul(msg, &msg);
+		if (!cmm_skip_blanks(msg, &msg))
+			return;
+		seconds = cmm_strtoul(msg, &msg);
+		cmm_skip_blanks(msg, &msg);
+		if (*msg == '\0')
+			cmm_set_timeout(pages, seconds);
+	}
+}
+#endif
+
+struct ctl_table_header *cmm_sysctl_header;
+
+static int
+cmm_init (void)
+{
+#ifdef CONFIG_CMM_PROC
+	cmm_sysctl_header = register_sysctl_table(cmm_dir_table, 1);
+#endif
+#ifdef CONFIG_CMM_IUCV
+	smsg_register_callback(SMSG_PREFIX, cmm_smsg_target);
+#endif
+	INIT_WORK(&cmm_thread_starter, (void *) cmm_start_thread, 0);
+	init_waitqueue_head(&cmm_thread_wait);
+	init_timer(&cmm_timer);
+	return 0;
+}
+
+static void
+cmm_exit(void)
+{
+	cmm_free_pages(cmm_pages, &cmm_pages, &cmm_page_list);
+	cmm_free_pages(cmm_timed_pages, &cmm_timed_pages, &cmm_timed_page_list);
+#ifdef CONFIG_CMM_PROC
+	unregister_sysctl_table(cmm_sysctl_header);
+#endif
+#ifdef CONFIG_CMM_IUCV
+	smsg_unregister_callback(SMSG_PREFIX, cmm_smsg_target);
+#endif
+}
+
+module_init(cmm_init);
+module_exit(cmm_exit);
+
+EXPORT_SYMBOL(cmm_set_pages);
+EXPORT_SYMBOL(cmm_get_pages);
+EXPORT_SYMBOL(cmm_add_timed_pages);
+EXPORT_SYMBOL(cmm_get_timed_pages);
+EXPORT_SYMBOL(cmm_set_timeout);
+
+MODULE_LICENSE("GPL");
--- diff/arch/s390/mm/extmem.c	1970-01-01 01:00:00.000000000 +0100
+++ source/arch/s390/mm/extmem.c	2004-02-23 13:56:39.000000000 +0000
@@ -0,0 +1,503 @@
+/*
+ * File...........: arch/s390/mm/dcss.c
+ * Author(s)......: Steven Shultz <shultzss@us.ibm.com>
+ *                  Carsten Otte <cotte@de.ibm.com>
+ * Bugreports.to..: <Linux390@de.ibm.com>
+ * thanks to Rob M van der Heij
+ * - he wrote the diag64 function
+ * (C) IBM Corporation 2002
+ */
+
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/spinlock.h>
+#include <linux/list.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/bootmem.h>
+#include <asm/page.h>
+#include <asm/ebcdic.h>
+#include <asm/errno.h>
+#include <asm/extmem.h>
+#include <asm/cpcmd.h>
+#include <linux/ctype.h>
+
+#define DCSS_DEBUG	/* Debug messages on/off */
+
+#define DCSS_NAME "extmem"
+#ifdef DCSS_DEBUG
+#define PRINT_DEBUG(x...)	printk(KERN_DEBUG DCSS_NAME " debug:" x)
+#else
+#define PRINT_DEBUG(x...)   do {} while (0)
+#endif
+#define PRINT_INFO(x...)	printk(KERN_INFO DCSS_NAME " info:" x)
+#define PRINT_WARN(x...)	printk(KERN_WARNING DCSS_NAME " warning:" x)
+#define PRINT_ERR(x...)		printk(KERN_ERR DCSS_NAME " error:" x)
+
+
+#define DCSS_LOADSHR    0x00
+#define DCSS_LOADNSR    0x04
+#define DCSS_PURGESEG   0x08
+#define DCSS_FINDSEG    0x0c
+#define DCSS_LOADNOLY   0x10
+#define DCSS_SEGEXT     0x18
+#define DCSS_QACTV      0x0c
+
+struct dcss_segment {
+        struct list_head list;
+        char dcss_name[8];
+        unsigned long start_addr;
+        unsigned long end;
+        atomic_t ref_count;
+        int dcss_attr;
+	int shared_attr;
+};
+
+static spinlock_t dcss_lock = SPIN_LOCK_UNLOCKED;
+static struct list_head dcss_list = LIST_HEAD_INIT(dcss_list);
+extern struct {unsigned long addr, size, type;} memory_chunk[16];
+
+/*
+ * Create the 8 bytes, ebcdic VM segment name from
+ * an ascii name.
+ */
+static void inline dcss_mkname(char *name, char *dcss_name)
+{
+        int i;
+
+        for (i = 0; i <= 8; i++) {
+                if (name[i] == '\0')
+                        break;
+                dcss_name[i] = toupper(name[i]);
+        };
+        for (; i <= 8; i++)
+                dcss_name[i] = ' ';
+        ASCEBC(dcss_name, 8);
+}
+
+/*
+ * Perform a function on a dcss segment.
+ */
+static inline int
+dcss_diag (__u8 func, void *parameter,
+           unsigned long *ret1, unsigned long *ret2)
+{
+        unsigned long rx, ry;
+        int rc;
+
+        rx = (unsigned long) parameter;
+        ry = (unsigned long) func;
+        __asm__ __volatile__(
+#ifdef CONFIG_ARCH_S390X
+                             "   sam31\n" // switch to 31 bit
+                             "   diag    %0,%1,0x64\n"
+                             "   sam64\n" // switch back to 64 bit
+#else
+                             "   diag    %0,%1,0x64\n"
+#endif
+                             "   ipm     %2\n"
+                             "   srl     %2,28\n"
+                             : "+d" (rx), "+d" (ry), "=d" (rc) : : "cc" );
+        *ret1 = rx;
+        *ret2 = ry;
+        return rc;
+}
+
+
+/* use to issue "extended" dcss query */
+static inline int
+dcss_diag_query(char *name, int *rwattr, int *shattr, unsigned long *segstart, unsigned long *segend)
+{
+        int i,j,rc;
+        unsigned long  rx, ry;
+
+        typedef struct segentry {
+                char thisseg[8];
+        } segentry;
+
+        struct qout64 {
+                int segstart;
+                int segend;
+                int segcnt;
+                int segrcnt;
+                segentry segout[6];
+        };
+
+        struct qin64 {
+                char qopcode;
+                char rsrv1[3];
+                char qrcode;
+                char rsrv2[3];
+                char qname[8];
+                unsigned int qoutptr;
+                short int qoutlen;
+        };
+
+
+        struct qin64  *qinarea;
+        struct qout64 *qoutarea;
+
+        qinarea = (struct qin64*) get_zeroed_page (GFP_DMA);
+        if (!qinarea) {
+                rc =-ENOMEM;
+                goto out;
+        }
+        qoutarea = (struct qout64*) get_zeroed_page (GFP_DMA);
+        if (!qoutarea) {
+                rc = -ENOMEM;
+                free_page ((unsigned long) qinarea);
+                goto out;
+        }
+        memset (qinarea,0,PAGE_SIZE);
+        memset (qoutarea,0,PAGE_SIZE);
+
+        qinarea->qopcode = DCSS_QACTV; /* do a query for active
+                                          segments */
+        qinarea->qoutptr = (unsigned long) qoutarea;
+        qinarea->qoutlen = sizeof(struct qout64);
+
+        /* Move segment name into double word aligned
+           field and pad with blanks to 8 long.
+         */
+
+        for (i = j = 0 ; i < 8; i++) {
+                qinarea->qname[i] = (name[j] == '\0') ? ' ' : name[j++];
+        }
+
+        /* name already in EBCDIC */
+        /* ASCEBC ((void *)&qinarea.qname, 8); */
+
+        /* set the assembler variables */
+        rx = (unsigned long) qinarea;
+        ry = DCSS_SEGEXT; /* this is extended function */
+
+        /* issue diagnose x'64' */
+        __asm__ __volatile__(
+#ifdef CONFIG_ARCH_S390X
+                             "   sam31\n" // switch to 31 bit
+                             "   diag    %0,%1,0x64\n"
+                             "   sam64\n" // switch back to 64 bit
+#else
+                             "   diag    %0,%1,0x64\n"
+#endif
+                             "   ipm     %2\n"
+                             "   srl     %2,28\n"
+                             : "+d" (rx), "+d" (ry), "=d" (rc) : : "cc" );
+
+        /* parse the query output area */
+	*segstart=qoutarea->segstart;
+	*segend=qoutarea->segend;
+
+        if (rc > 1)
+                {
+                        *rwattr = 2;
+                        *shattr = 2;
+                        rc = 0;
+                        goto free;
+                }
+
+        if (qoutarea->segcnt > 6)
+                {
+                        *rwattr = 3;
+                        *shattr = 3;
+                        rc = 0;
+                        goto free;
+                }
+
+        *rwattr = 1;
+        *shattr = 1;
+
+        for (i=0; i < qoutarea->segrcnt; i++) {
+                if (qoutarea->segout[i].thisseg[3] == 2 ||
+                    qoutarea->segout[i].thisseg[3] == 3 ||
+                    qoutarea->segout[i].thisseg[3] == 6 )
+                        *rwattr = 0;
+                if (qoutarea->segout[i].thisseg[3] == 1 ||
+                    qoutarea->segout[i].thisseg[3] == 3 ||
+                    qoutarea->segout[i].thisseg[3] == 5 )
+                        *shattr = 0;
+        } /* end of for statement */
+        rc = 0;
+ free:
+        free_page ((unsigned long) qoutarea);
+        free_page ((unsigned long) qinarea);
+ out:
+        return rc;
+}
+
+/*
+ * Load a DCSS segment via the diag 0x64.
+ */
+int segment_load(char *name, int segtype, unsigned long *addr,
+                 unsigned long *end)
+{
+        char dcss_name[8];
+        struct list_head *l;
+        struct dcss_segment *seg, *tmp;
+	unsigned long dummy;
+	unsigned long segstart, segend;
+        int rc = 0,i;
+        int rwattr, shattr;
+
+        if (!MACHINE_IS_VM)
+                return -ENOSYS;
+        dcss_mkname(name, dcss_name);
+	/* search for the dcss in list of currently loaded segments */
+        spin_lock(&dcss_lock);
+        seg = NULL;
+        list_for_each(l, &dcss_list) {
+                tmp = list_entry(l, struct dcss_segment, list);
+                if (memcmp(tmp->dcss_name, dcss_name, 8) == 0) {
+                        seg = tmp;
+                        break;
+                }
+        }
+
+        if (seg == NULL) {
+                /* find out the attributes of this
+                   shared segment */
+                dcss_diag_query(dcss_name, &rwattr, &shattr, &segstart, &segend);
+		/* does segment collide with main memory? */
+		for (i=0; i<16; i++) {
+					if (memory_chunk[i].type != 0)
+						continue;
+					if (memory_chunk[i].addr > segend)
+						continue;
+					if (memory_chunk[i].addr + memory_chunk[i].size <= segstart)
+						continue;
+					spin_unlock(&dcss_lock);
+				        return -ENOENT;
+				}
+		/* or does it collide with other (loaded) segments? */
+        	list_for_each(l, &dcss_list) {
+                	tmp = list_entry(l, struct dcss_segment, list);
+	                if ((segstart <= tmp->end && segstart >= tmp->start_addr) ||
+				(segend <= tmp->end && segend >= tmp->start_addr) ||
+				(segstart <= tmp->start_addr && segend >= tmp->end)) {
+				PRINT_ERR("Segment Overlap!\n");
+			        spin_unlock(&dcss_lock);
+				return -ENOENT;
+	                }
+        	}
+
+                /* do case statement on segtype */
+                /* if asking for shared ro,
+                   shared rw works */
+                /* if asking for exclusive ro,
+                   exclusive rw works */
+
+                switch(segtype) {
+                case SEGMENT_SHARED_RO:
+                        if (shattr > 1 || rwattr > 1) {
+                                spin_unlock(&dcss_lock);
+                                return -ENOENT;
+                        } else {
+                                if (shattr == 0 && rwattr == 0)
+                                        rc = SEGMENT_EXCLUSIVE_RO;
+                                if (shattr == 0 && rwattr == 1)
+                                        rc = SEGMENT_EXCLUSIVE_RW;
+                                if (shattr == 1 && rwattr == 0)
+                                        rc = SEGMENT_SHARED_RO;
+                                if (shattr == 1 && rwattr == 1)
+                                        rc = SEGMENT_SHARED_RW;
+                        }
+                        break;
+                case SEGMENT_SHARED_RW:
+                        if (shattr > 1 || rwattr != 1) {
+                                spin_unlock(&dcss_lock);
+                                return -ENOENT;
+                        } else {
+                                if (shattr == 0)
+                                        rc = SEGMENT_EXCLUSIVE_RW;
+                                if (shattr == 1)
+                                        rc = SEGMENT_SHARED_RW;
+                        }
+                        break;
+
+                case SEGMENT_EXCLUSIVE_RO:
+                        if (shattr > 0 || rwattr > 1) {
+                                spin_unlock(&dcss_lock);
+                                return -ENOENT;
+                        } else {
+                                if (rwattr == 0)
+                                        rc = SEGMENT_EXCLUSIVE_RO;
+                                if (rwattr == 1)
+                                        rc = SEGMENT_EXCLUSIVE_RW;
+                        }
+                        break;
+
+                case SEGMENT_EXCLUSIVE_RW:
+/*                        if (shattr != 0 || rwattr != 1) {
+                                spin_unlock(&dcss_lock);
+                                return -ENOENT;
+                        } else {
+*/
+                                rc = SEGMENT_EXCLUSIVE_RW;
+//                        }
+                        break;
+
+                default:
+                        spin_unlock(&dcss_lock);
+                        return -ENOENT;
+                } /* end switch */
+
+                seg = kmalloc(sizeof(struct dcss_segment), GFP_DMA);
+                if (seg != NULL) {
+                        memcpy(seg->dcss_name, dcss_name, 8);
+			if (rc == SEGMENT_EXCLUSIVE_RW) {
+				if (dcss_diag(DCSS_LOADNSR, seg->dcss_name,
+						&seg->start_addr, &seg->end) == 0) {
+					if (seg->end < max_low_pfn*PAGE_SIZE ) {
+						atomic_set(&seg->ref_count, 1);
+						list_add(&seg->list, &dcss_list);
+						*addr = seg->start_addr;
+						*end = seg->end;
+						seg->dcss_attr = rc;
+						if (shattr == 1 && rwattr == 1)
+							seg->shared_attr = SEGMENT_SHARED_RW;
+						else if (shattr == 1 && rwattr == 0)
+							seg->shared_attr = SEGMENT_SHARED_RO;
+						else
+							seg->shared_attr = SEGMENT_EXCLUSIVE_RW;
+					} else {
+						dcss_diag(DCSS_PURGESEG, seg->dcss_name, &dummy, &dummy);
+						kfree (seg);
+						rc = -ENOENT;
+					}
+				} else {
+					kfree(seg);
+					rc = -ENOENT;
+			        }
+				goto out;
+                        }
+			if (dcss_diag(DCSS_LOADNOLY, seg->dcss_name,
+                                      &seg->start_addr, &seg->end) == 0) {
+				if (seg->end < max_low_pfn*PAGE_SIZE ) {
+		                        atomic_set(&seg->ref_count, 1);
+					list_add(&seg->list, &dcss_list);
+					*addr = seg->start_addr;
+					*end = seg->end;
+					seg->dcss_attr = rc;
+					seg->shared_attr = rc;
+				} else {
+					dcss_diag(DCSS_PURGESEG, seg->dcss_name, &dummy, &dummy);
+					kfree (seg);
+					rc = -ENOENT;
+				}
+                        } else {
+                                kfree(seg);
+                                rc = -ENOENT;
+                        }
+                } else rc = -ENOMEM;
+        } else {
+		/* found */
+		if ((segtype == SEGMENT_EXCLUSIVE_RW) && (seg->dcss_attr != SEGMENT_EXCLUSIVE_RW)) {
+			PRINT_ERR("Segment already loaded in other mode than EXCLUSIVE_RW!\n");
+			rc = -EPERM;
+			goto out;
+			/* reload segment in exclusive mode */
+/*			dcss_diag(DCSS_LOADNSR, seg->dcss_name,
+				  &seg->start_addr, &seg->end);
+			seg->dcss_attr = SEGMENT_EXCLUSIVE_RW;*/
+		}
+		if ((segtype != SEGMENT_EXCLUSIVE_RW) && (seg->dcss_attr == SEGMENT_EXCLUSIVE_RW)) {
+			PRINT_ERR("Segment already loaded in EXCLUSIVE_RW mode!\n");
+			rc = -EPERM;
+			goto out;
+		}
+                atomic_inc(&seg->ref_count);
+                *addr = seg->start_addr;
+                *end = seg->end;
+                rc = seg->dcss_attr;
+        }
+out:
+        spin_unlock(&dcss_lock);
+        return rc;
+}
+
+/*
+ * Decrease the use count of a DCSS segment and remove
+ * it from the address space if nobody is using it
+ * any longer.
+ */
+void segment_unload(char *name)
+{
+        char dcss_name[8];
+        unsigned long dummy;
+        struct list_head *l,*l_tmp;
+        struct dcss_segment *seg;
+
+        if (!MACHINE_IS_VM)
+                return;
+        dcss_mkname(name, dcss_name);
+        spin_lock(&dcss_lock);
+        list_for_each_safe(l, l_tmp, &dcss_list) {
+                seg = list_entry(l, struct dcss_segment, list);
+                if (memcmp(seg->dcss_name, dcss_name, 8) == 0) {
+                        if (atomic_dec_return(&seg->ref_count) == 0) {
+                                /* Last user of the segment is
+                                   gone. */
+                                list_del(&seg->list);
+                                dcss_diag(DCSS_PURGESEG, seg->dcss_name,
+                                          &dummy, &dummy);
+				kfree(seg);
+                        }
+                        break;
+                }
+        }
+        spin_unlock(&dcss_lock);
+}
+
+/*
+ * Replace an existing DCSS segment, so that machines
+ * that load it anew will see the new version.
+ */
+void segment_replace(char *name)
+{
+        char dcss_name[8];
+        struct list_head *l;
+        struct dcss_segment *seg;
+        int mybeg = 0;
+        int myend = 0;
+        char mybuff1[80];
+        char mybuff2[80];
+
+        if (!MACHINE_IS_VM)
+                return;
+        dcss_mkname(name, dcss_name);
+
+        memset (mybuff1, 0, sizeof(mybuff1));
+        memset (mybuff2, 0, sizeof(mybuff2));
+
+        spin_lock(&dcss_lock);
+        list_for_each(l, &dcss_list) {
+                seg = list_entry(l, struct dcss_segment, list);
+                if (memcmp(seg->dcss_name, dcss_name, 8) == 0) {
+                        mybeg = seg->start_addr >> 12;
+                        myend = (seg->end) >> 12;
+                        if (seg->shared_attr == SEGMENT_EXCLUSIVE_RW)
+                                sprintf(mybuff1, "DEFSEG %s %X-%X EW",
+                                        name, mybeg, myend);
+                        if (seg->shared_attr == SEGMENT_EXCLUSIVE_RO)
+                                sprintf(mybuff1, "DEFSEG %s %X-%X RO",
+                                        name, mybeg, myend);
+                        if (seg->shared_attr == SEGMENT_SHARED_RW)
+                                sprintf(mybuff1, "DEFSEG %s %X-%X SW",
+                                        name, mybeg, myend);
+                        if (seg->shared_attr == SEGMENT_SHARED_RO)
+                                sprintf(mybuff1, "DEFSEG %s %X-%X SR",
+                                        name, mybeg, myend);
+                        spin_unlock(&dcss_lock);
+                        sprintf(mybuff2, "SAVESEG %s", name);
+                        cpcmd(mybuff1, NULL, 80);
+                        cpcmd(mybuff2, NULL, 80);
+                        break;
+                }
+
+        }
+        if (myend == 0) spin_unlock(&dcss_lock);
+}
+
+EXPORT_SYMBOL(segment_load);
+EXPORT_SYMBOL(segment_unload);
+EXPORT_SYMBOL(segment_replace);
--- diff/arch/sparc/lib/atomic32.c	1970-01-01 01:00:00.000000000 +0100
+++ source/arch/sparc/lib/atomic32.c	2004-02-23 13:56:39.000000000 +0000
@@ -0,0 +1,52 @@
+/*
+ * atomic32.c: 32-bit atomic_t implementation
+ *
+ * Copyright (C) 2004 Keith M Wesolowski
+ * 
+ * Based on asm-parisc/atomic.h Copyright (C) 2000 Philipp Rumpf
+ */
+
+#include <asm/atomic.h>
+#include <linux/spinlock.h>
+#include <linux/module.h>
+
+#ifdef CONFIG_SMP
+#define ATOMIC_HASH_SIZE	4
+#define ATOMIC_HASH(a)	(&__atomic_hash[(((unsigned long)a)>>8) & (ATOMIC_HASH_SIZE-1)])
+
+spinlock_t __atomic_hash[ATOMIC_HASH_SIZE] = {
+	[0 ... (ATOMIC_HASH_SIZE-1)] = SPIN_LOCK_UNLOCKED
+};
+
+#else /* SMP */
+
+#define ATOMIC_HASH_SIZE	1
+#define ATOMIC_HASH(a)		0
+
+#endif /* SMP */
+
+int __atomic_add_return(int i, atomic_t *v)
+{
+	int ret;
+	unsigned long flags;
+	spin_lock_irqsave(ATOMIC_HASH(v), flags);
+
+	ret = (v->counter += i);
+
+	spin_unlock_irqrestore(ATOMIC_HASH(v), flags);
+	return ret;
+}
+
+void atomic_set(atomic_t *v, int i)
+{
+	unsigned long flags;
+	spin_lock_irqsave(ATOMIC_HASH(v), flags);
+
+	v->counter = i;
+
+	spin_unlock_irqrestore(ATOMIC_HASH(v), flags);
+}
+
+EXPORT_SYMBOL(__atomic_add_return);
+EXPORT_SYMBOL(atomic_set);
+
--- diff/arch/x86_64/Kconfig.kgdb	1970-01-01 01:00:00.000000000 +0100
+++ source/arch/x86_64/Kconfig.kgdb	2004-02-23 13:56:39.000000000 +0000
@@ -0,0 +1,176 @@
+config KGDB
+	bool "Include kgdb kernel debugger"
+	depends on DEBUG_KERNEL
+	select DEBUG_INFO
+	help
+	  If you say Y here, the system will be compiled with the debug
+	  option (-g) and a debugging stub will be included in the
+	  kernel.  This stub communicates with gdb on another (host)
+	  computer via a serial port.  The host computer should have
+	  access to the kernel binary file (vmlinux) and a serial port
+	  that is connected to the target machine.  Gdb can be made to
+	  configure the serial port or you can use stty and setserial to
+	  do this. See the 'target' command in gdb. This option also
+	  configures in the ability to request a breakpoint early in the
+	  boot process.  To request the breakpoint just include 'kgdb'
+	  as a boot option when booting the target machine.  The system
+	  will then break as soon as it looks at the boot options.  This
+	  option also installs a breakpoint in panic and sends any
+	  kernel faults to the debugger. For more information see the
+	  Documentation/i386/kgdb.txt file.
+
+choice
+	depends on KGDB
+    	prompt "Debug serial port BAUD"
+	default KGDB_115200BAUD
+	help
+	  Gdb and the kernel stub need to agree on the baud rate to be
+	  used.  Some systems (x86 family at this writing) allow this to
+	  be configured.
+
+config KGDB_9600BAUD
+	bool "9600"
+
+config KGDB_19200BAUD
+	bool "19200"
+
+config KGDB_38400BAUD
+	bool "38400"
+
+config KGDB_57600BAUD
+	bool "57600"
+
+config KGDB_115200BAUD
+	bool "115200"
+endchoice
+
+config KGDB_PORT
+	hex "hex I/O port address of the debug serial port"
+	depends on KGDB
+	default  3f8
+	help
+	  Some systems (x86 family at this writing) allow the port
+	  address to be configured.  The number entered is assumed to be
+	  hex, don't put 0x in front of it.  The standard address are:
+	  COM1 3f8 , irq 4 and COM2 2f8 irq 3.  Setserial /dev/ttySx
+	  will tell you what you have.  It is good to test the serial
+	  connection with a live system before trying to debug.
+
+config KGDB_IRQ
+	int "IRQ of the debug serial port"
+	depends on KGDB
+	default 4
+	help
+	  This is the irq for the debug port.  If everything is working
+	  correctly and the kernel has interrupts on a control C to the
+	  port should cause a break into the kernel debug stub.
+
+config DEBUG_INFO
+	bool
+	depends on KGDB
+	default y
+
+config KGDB_MORE
+	bool "Add any additional compile options"
+	depends on KGDB
+	default n
+	help
+	  Saying yes here turns on the ability to enter additional
+	  compile options.
+
+
+config KGDB_OPTIONS
+	depends on KGDB_MORE
+	string "Additional compile arguments"
+	default "-O1"
+	help
+	  This option allows you enter additional compile options for
+	  the whole kernel compile.  Each platform will have a default
+	  that seems right for it.  For example on PPC "-ggdb -O1", and
+	  for i386 "-O1".  Note that by configuring KGDB "-g" is already
+	  turned on.  In addition, on i386 platforms
+	  "-fomit-frame-pointer" is deleted from the standard compile
+	  options.
+
+config NO_KGDB_CPUS
+	int "Number of CPUs"
+	depends on KGDB && SMP
+	default NR_CPUS
+	help
+
+	  This option sets the number of cpus for kgdb ONLY.  It is used
+	  to prune some internal structures so they look "nice" when
+	  displayed with gdb.  This is to overcome possibly larger
+	  numbers that may have been entered above.  Enter the real
+	  number to get nice clean kgdb_info displays.
+
+config KGDB_TS
+	bool "Enable kgdb time stamp macros?"
+	depends on KGDB
+	default n
+	help
+	  Kgdb event macros allow you to instrument your code with calls
+	  to the kgdb event recording function.  The event log may be
+	  examined with gdb at a break point.  Turning on this
+	  capability also allows you to choose how many events to
+	  keep. Kgdb always keeps the lastest events.
+
+choice
+	depends on KGDB_TS
+	prompt "Max number of time stamps to save?"
+	default KGDB_TS_128
+
+config KGDB_TS_64
+	bool "64"
+
+config KGDB_TS_128
+	bool "128"
+
+config KGDB_TS_256
+	bool "256"
+
+config KGDB_TS_512
+	bool "512"
+
+config KGDB_TS_1024
+	bool "1024"
+
+endchoice
+
+config STACK_OVERFLOW_TEST
+	bool "Turn on kernel stack overflow testing?"
+	depends on KGDB
+	default n
+	help
+	  This option enables code in the front line interrupt handlers
+	  to check for kernel stack overflow on interrupts and system
+	  calls.  This is part of the kgdb code on x86 systems.
+
+config KGDB_CONSOLE
+	bool "Enable serial console thru kgdb port"
+	depends on KGDB
+	default n
+	help
+	  This option enables the command line "console=kgdb" option.
+	  When the system is booted with this option in the command line
+	  all kernel printk output is sent to gdb (as well as to other
+	  consoles).  For this to work gdb must be connected.  For this
+	  reason, this command line option will generate a breakpoint if
+	  gdb has not yet connected.  After the gdb continue command is
+	  given all pent up console output will be printed by gdb on the
+	  host machine.  Neither this option, nor KGDB require the
+	  serial driver to be configured.
+
+config KGDB_SYSRQ
+	bool "Turn on SysRq 'G' command to do a break?"
+	depends on KGDB
+	default y
+	help
+	  This option includes an option in the SysRq code that allows
+	  you to enter SysRq G which generates a breakpoint to the KGDB
+	  stub.  This will work if the keyboard is alive and can
+	  interrupt the system.  Because of constraints on when the
+	  serial port interrupt can be enabled, this code may allow you
+	  to interrupt the system before the serial port control C is
+	  available.  Just say yes here.
+
--- diff/arch/x86_64/kernel/kgdb_stub.c	1970-01-01 01:00:00.000000000 +0100
+++ source/arch/x86_64/kernel/kgdb_stub.c	2004-02-23 13:56:39.000000000 +0000
@@ -0,0 +1,2595 @@
+/*
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2, or (at your option) any
+ * later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the GNU
+ * General Public License for more details.
+ *
+ */
+
+/*
+ * Copyright (c) 2000 VERITAS Software Corporation.
+ *
+ */
+/****************************************************************************
+ *  Header: remcom.c,v 1.34 91/03/09 12:29:49 glenne Exp $
+ *
+ *  Module name: remcom.c $
+ *  Revision: 1.34 $
+ *  Date: 91/03/09 12:29:49 $
+ *  Contributor:     Lake Stevens Instrument Division$
+ *
+ *  Description:     low level support for gdb debugger. $
+ *
+ *  Considerations:  only works on target hardware $
+ *
+ *  Written by:	     Glenn Engel $
+ *  Updated by:	     David Grothe <dave@gcom.com>
+ *  Updated by:	     Robert Walsh <rjwalsh@durables.org>
+ *  Updated by:	     wangdi <wangdi@clusterfs.com>
+ *  ModuleState:     Experimental $
+ *
+ *  NOTES:	     See Below $
+ *
+ *  Modified for 386 by Jim Kingdon, Cygnus Support.
+ *  Compatibility with 2.1.xx kernel by David Grothe <dave@gcom.com>
+ *
+ *  Changes to allow auto initilization.  All that is needed is that it
+ *  be linked with the kernel and a break point (int 3) be executed.
+ *  The header file <asm/kgdb.h> defines BREAKPOINT to allow one to do
+ *  this. It should also be possible, once the interrupt system is up, to
+ *  call putDebugChar("+").  Once this is done, the remote debugger should
+ *  get our attention by sending a ^C in a packet. George Anzinger
+ *  <george@mvista.com>
+ *  Integrated into 2.2.5 kernel by Tigran Aivazian <tigran@sco.com>
+ *  Added thread support, support for multiple processors,
+ *	support for ia-32(x86) hardware debugging.
+ *	Amit S. Kale ( akale@veritas.com )
+ *
+ *  Modified to support debugging over ethernet by Robert Walsh
+ *  <rjwalsh@durables.org> and wangdi <wangdi@clusterfs.com>, based on
+ *  code by San Mehat.
+ *
+ *  X86_64 changes from Andi Kleen's patch merged by Jim Houston
+ * 	(jim.houston@ccur.com).  If it works thank Andi if its broken
+ * 	blame me.
+ *
+ *  To enable debugger support, two things need to happen.  One, a
+ *  call to set_debug_traps() is necessary in order to allow any breakpoints
+ *  or error conditions to be properly intercepted and reported to gdb.
+ *  Two, a breakpoint needs to be generated to begin communication.  This
+ *  is most easily accomplished by a call to breakpoint().  Breakpoint()
+ *  simulates a breakpoint by executing an int 3.
+ *
+ *************
+ *
+ *    The following gdb commands are supported:
+ *
+ * command	    function				   Return value
+ *
+ *    g		    return the value of the CPU registers  hex data or ENN
+ *    G		    set the value of the CPU registers	   OK or ENN
+ *
+ *    mAA..AA,LLLL  Read LLLL bytes at address AA..AA	   hex data or ENN
+ *    MAA..AA,LLLL: Write LLLL bytes at address AA.AA	   OK or ENN
+ *
+ *    c		    Resume at current address		   SNN	 ( signal NN)
+ *    cAA..AA	    Continue at address AA..AA		   SNN
+ *
+ *    s		    Step one instruction		   SNN
+ *    sAA..AA	    Step one instruction from AA..AA	   SNN
+ *
+ *    k		    kill
+ *
+ *    ?		    What was the last sigval ?		   SNN	 (signal NN)
+ *
+ * All commands and responses are sent with a packet which includes a
+ * checksum.  A packet consists of
+ *
+ * $<packet info>#<checksum>.
+ *
+ * where
+ * <packet info> :: <characters representing the command or response>
+ * <checksum>	 :: < two hex digits computed as modulo 256 sum of <packetinfo>>
+ *
+ * When a packet is received, it is first acknowledged with either '+' or '-'.
+ * '+' indicates a successful transfer.	 '-' indicates a failed transfer.
+ *
+ * Example:
+ *
+ * Host:		  Reply:
+ * $m0,10#2a		   +$00010203040506070809101112131415#42
+ *
+ ****************************************************************************/
+#define KGDB_VERSION "<20030915.1651.33>"
+#include <linux/config.h>
+#include <linux/types.h>
+#include <asm/string.h>		/* for strcpy */
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <asm/system.h>
+#include <asm/ptrace.h>		/* for linux pt_regs struct */
+#include <asm/kgdb_local.h>
+#include <linux/list.h>
+#include <asm/atomic.h>
+#include <asm/processor.h>
+#include <linux/irq.h>
+#include <asm/desc.h>
+#include <linux/inet.h>
+#include <linux/netpoll.h>
+#include <linux/cpumask.h>
+#include <linux/bitops.h>
+#include <linux/notifier.h>
+#include <asm/kdebug.h>
+#include <asm/uaccess.h>
+#include <linux/ptrace.h>
+
+#define Dearly_printk(x...)
+int kgdb_enabled = 0;
+
+/************************************************************************
+ *
+ * external low-level support routines
+ */
+typedef void (*Function) (void);	/* pointer to a function */
+
+/* Thread reference */
+typedef unsigned char threadref[8];
+
+extern int tty_putDebugChar(int);     /* write a single character      */
+extern int tty_getDebugChar(void);    /* read and return a single char */
+extern void tty_flushDebugChar(void); /* flush pending characters      */
+extern int eth_putDebugChar(int);     /* write a single character      */
+extern int eth_getDebugChar(void);    /* read and return a single char */
+extern void eth_flushDebugChar(void); /* flush pending characters      */
+
+/************************************************************************/
+/* BUFMAX defines the maximum number of characters in inbound/outbound buffers*/
+/* at least NUMREGBYTES*2 are needed for register packets */
+/* Longer buffer is needed to list all threads */
+#define BUFMAX 400
+
+char *kgdb_version = KGDB_VERSION;
+
+/*  debug >  0 prints ill-formed commands in valid packets & checksum errors */
+int debug_regs = 0;		/* set to non-zero to print registers */
+
+/* filled in by an external module */
+char *gdb_module_offsets;
+
+static const char hexchars[] = "0123456789abcdef";
+
+/* Number of bytes of registers.  */
+#define NUMREGBYTES (NUMREGS * sizeof(unsigned long))
+/*
+ * Note that this register image is in a different order than
+ * the register image that Linux produces at interrupt time.
+ *
+ * Linux's register image is defined by struct pt_regs in ptrace.h.
+ * Just why GDB uses a different order is a historical mystery.
+ *
+ * Could add XMM and segment registers here.
+ */
+enum regnames {_RAX,
+	       _RBX,
+	       _RCX,
+	       _RDX,
+	       _RSI,
+	       _RDI,
+	       _RBP,
+	       _RSP,
+	       _R8,
+	       _R9,
+	       _R10,
+	       _R11,
+	       _R12,
+	       _R13,
+	       _R14,
+	       _R15,
+	       _PC,
+	       _PS,
+	       NUMREGS };
+
+
+/***************************  ASSEMBLY CODE MACROS *************************/
+/*
+ * Put the error code here just in case the user cares.
+ * Likewise, the vector number here (since GDB only gets the signal
+ * number through the usual means, and that's not very specific).
+ * The called_from is the return address so he can tell how we entered kgdb.
+ * This will allow him to seperate out the various possible entries.
+ */
+#define REMOTE_DEBUG 0		/* set != to turn on printing (also available in info) */
+
+#define PID_MAX PID_MAX_DEFAULT
+
+#ifdef CONFIG_SMP
+void smp_send_nmi_allbutself(void);
+#define IF_SMP(x) x
+#undef MAX_NO_CPUS
+#ifndef CONFIG_NO_KGDB_CPUS
+#define CONFIG_NO_KGDB_CPUS 2
+#endif
+#if CONFIG_NO_KGDB_CPUS > NR_CPUS
+#define MAX_NO_CPUS NR_CPUS
+#else
+#define MAX_NO_CPUS CONFIG_NO_KGDB_CPUS
+#endif
+#define hold_init hold_on_sstep: 1,
+#define MAX_CPU_MASK (unsigned long)((1LL << MAX_NO_CPUS) - 1LL)
+#define NUM_CPUS num_online_cpus()
+#else
+#define IF_SMP(x)
+#define hold_init
+#undef MAX_NO_CPUS
+#define MAX_NO_CPUS 1
+#define NUM_CPUS 1
+#endif
+#define NOCPU (struct task_struct *)0xbad1fbad
+/* *INDENT-OFF*	 */
+struct kgdb_info {
+	int used_malloc;
+	void *called_from;
+	long long entry_tsc;
+	int errcode;
+	int vector;
+	int print_debug_info;
+#ifdef CONFIG_SMP
+	int hold_on_sstep;
+	struct {
+		volatile struct task_struct *task;
+		int pid;
+		int hold;
+		struct pt_regs *regs;
+	} cpus_waiting[MAX_NO_CPUS];
+#endif
+} kgdb_info = {hold_init print_debug_info:REMOTE_DEBUG, vector:-1};
+
+/* *INDENT-ON*	*/
+
+#define used_m kgdb_info.used_malloc
+/*
+ * This is little area we set aside to contain the stack we
+ * need to build to allow gdb to call functions.  We use one
+ * per cpu to avoid locking issues.  We will do all this work
+ * with interrupts off so that should take care of the protection
+ * issues.
+ */
+#define LOOKASIDE_SIZE 200	/* should be more than enough */
+#define MALLOC_MAX   200	/* Max malloc size */
+struct {
+	unsigned long rsp;
+	unsigned long array[LOOKASIDE_SIZE];
+} fn_call_lookaside[MAX_NO_CPUS];
+
+static int trap_cpu;
+static unsigned long OLD_esp;
+
+#define END_OF_LOOKASIDE  &fn_call_lookaside[trap_cpu].array[LOOKASIDE_SIZE]
+#define IF_BIT 0x200
+#define TF_BIT 0x100
+
+#define MALLOC_ROUND 8-1
+
+static char malloc_array[MALLOC_MAX];
+IF_SMP(static void to_gdb(const char *mess));
+void *
+malloc(int size)
+{
+
+	if (size <= (MALLOC_MAX - used_m)) {
+		int old_used = used_m;
+		used_m += ((size + MALLOC_ROUND) & (~MALLOC_ROUND));
+		return &malloc_array[old_used];
+	} else {
+		return NULL;
+	}
+}
+
+/*
+ * I/O dispatch functions...
+ * Based upon kgdboe, either call the ethernet
+ * handler or the serial one..
+ */
+void
+putDebugChar(int c)
+{
+	if (!kgdboe) {
+		tty_putDebugChar(c);
+	} else {
+		eth_putDebugChar(c);
+	}
+}
+
+int
+getDebugChar(void)
+{
+	if (!kgdboe) {
+		return tty_getDebugChar();
+	} else {
+		return eth_getDebugChar();
+	}
+}
+
+void
+flushDebugChar(void)
+{
+	if (!kgdboe) {
+		tty_flushDebugChar();
+	} else {
+		eth_flushDebugChar();
+	}
+}
+
+/*
+ * Gdb calls functions by pushing agruments, including a return address
+ * on the stack and the adjusting EIP to point to the function.	 The
+ * whole assumption in GDB is that we are on a different stack than the
+ * one the "user" i.e. code that hit the break point, is on.  This, of
+ * course is not true in the kernel.  Thus various dodges are needed to
+ * do the call without directly messing with EIP (which we can not change
+ * as it is just a location and not a register.	 To adjust it would then
+ * require that we move every thing below EIP up or down as needed.  This
+ * will not work as we may well have stack relative pointer on the stack
+ * (such as the pointer to regs, for example).
+
+ * So here is what we do:
+ * We detect gdb attempting to store into the stack area and instead, store
+ * into the fn_call_lookaside.array at the same relative location as if it
+ * were the area ESP pointed at.  We also trap ESP modifications
+ * and uses these to adjust fn_call_lookaside.esp.  On entry
+ * fn_call_lookaside.esp will be set to point at the last entry in
+ * fn_call_lookaside.array.  This allows us to check if it has changed, and
+ * if so, on exit, we add the registers we will use to do the move and a
+ * trap/ interrupt return exit sequence.  We then adjust the eflags in the
+ * regs array (remember we now have a copy in the fn_call_lookaside.array) to
+ * kill the interrupt bit, AND we change EIP to point at our set up stub.
+ * As part of the register set up we preset the registers to point at the
+ * begining and end of the fn_call_lookaside.array, so all the stub needs to
+ * do is move words from the array to the stack until ESP= the desired value
+ * then do the rti.  This will then transfer to the desired function with
+ * all the correct registers.  Nifty huh?
+ */
+extern asmlinkage void fn_call_stub(void);
+extern asmlinkage void fn_rtn_stub(void);
+/*					   *INDENT-OFF*	 */
+__asm__("fn_rtn_stub:\n\t"
+	"movq %rax,%rsp\n\t"
+	"fn_call_stub:\n\t"
+	"1:\n\t"
+	"addq $-8,%rbx\n\t"
+	"movq (%rbx), %rax\n\t"
+	"pushq %rax\n\t"
+	"cmpq %rsp,%rcx\n\t"
+	"jne  1b\n\t"
+	"popq %rax\n\t"
+	"popq %rbx\n\t"
+	"popq %rcx\n\t"
+	"iret \n\t");
+/*					     *INDENT-ON*  */
+#define gdb_i386vector	kgdb_info.vector
+#define gdb_i386errcode kgdb_info.errcode
+#define waiting_cpus	kgdb_info.cpus_waiting
+#define remote_debug	kgdb_info.print_debug_info
+#define hold_cpu(cpu)	kgdb_info.cpus_waiting[cpu].hold
+/* gdb locks */
+
+#ifdef CONFIG_SMP
+static int in_kgdb_called;
+static spinlock_t waitlocks[MAX_NO_CPUS] =
+    {[0 ... MAX_NO_CPUS - 1] = SPIN_LOCK_UNLOCKED };
+/*
+ * The following array has the thread pointer of each of the "other"
+ * cpus.  We make it global so it can be seen by gdb.
+ */
+volatile int in_kgdb_entry_log[MAX_NO_CPUS];
+volatile struct pt_regs *in_kgdb_here_log[MAX_NO_CPUS];
+/*
+static spinlock_t continuelocks[MAX_NO_CPUS];
+*/
+spinlock_t kgdb_spinlock = SPIN_LOCK_UNLOCKED;
+/* waiters on our spinlock plus us */
+static atomic_t spinlock_waiters = ATOMIC_INIT(1);
+static int spinlock_count = 0;
+static int spinlock_cpu = 0;
+/*
+ * Note we use nested spin locks to account for the case where a break
+ * point is encountered when calling a function by user direction from
+ * kgdb. Also there is the memory exception recursion to account for.
+ * Well, yes, but this lets other cpus thru too.  Lets add a
+ * cpu id to the lock.
+ */
+#define KGDB_SPIN_LOCK(x) if( spinlock_count == 0 || \
+			      spinlock_cpu != smp_processor_id()){\
+				      atomic_inc(&spinlock_waiters); \
+				      while (! spin_trylock(x)) {\
+					    in_kgdb(&regs);\
+				      }\
+				      atomic_dec(&spinlock_waiters); \
+				      spinlock_count = 1; \
+				      spinlock_cpu = smp_processor_id(); \
+			  }else{  \
+				      spinlock_count++; \
+			  }
+#define KGDB_SPIN_UNLOCK(x) if( --spinlock_count == 0) spin_unlock(x)
+#else
+unsigned kgdb_spinlock = 0;
+#define KGDB_SPIN_LOCK(x) --*x
+#define KGDB_SPIN_UNLOCK(x) ++*x
+#endif
+
+int
+hex(char ch)
+{
+	if ((ch >= 'a') && (ch <= 'f'))
+		return (ch - 'a' + 10);
+	if ((ch >= '0') && (ch <= '9'))
+		return (ch - '0');
+	if ((ch >= 'A') && (ch <= 'F'))
+		return (ch - 'A' + 10);
+	return (-1);
+}
+
+/* scan for the sequence $<data>#<checksum>	*/
+void
+getpacket(char *buffer)
+{
+	unsigned char checksum;
+	unsigned char xmitcsum;
+	int i;
+	int count;
+	char ch;
+
+	do {
+		/* wait around for the start character, ignore all other characters */
+		while ((ch = (getDebugChar() & 0x7f)) != '$') ;
+		checksum = 0;
+		xmitcsum = -1;
+
+		count = 0;
+
+		/* now, read until a # or end of buffer is found */
+		while (count < BUFMAX) {
+			ch = getDebugChar() & 0x7f;
+			if (ch == '#')
+				break;
+			checksum = checksum + ch;
+			buffer[count] = ch;
+			count = count + 1;
+		}
+		buffer[count] = 0;
+
+		if (ch == '#') {
+			xmitcsum = hex(getDebugChar() & 0x7f) << 4;
+			xmitcsum += hex(getDebugChar() & 0x7f);
+			if ((remote_debug) && (checksum != xmitcsum)) {
+				printk
+				    ("bad checksum.	My count = 0x%x, sent=0x%x. buf=%s\n",
+				     checksum, xmitcsum, buffer);
+			}
+
+			if (checksum != xmitcsum)
+				putDebugChar('-');	/* failed checksum */
+			else {
+				putDebugChar('+');	/* successful transfer */
+				/* if a sequence char is present, reply the sequence ID */
+				if (buffer[2] == ':') {
+					putDebugChar(buffer[0]);
+					putDebugChar(buffer[1]);
+					/* remove sequence chars from buffer */
+					count = strlen(buffer);
+					for (i = 3; i <= count; i++)
+						buffer[i - 3] = buffer[i];
+				}
+			}
+		}
+	} while (checksum != xmitcsum);
+
+	if (remote_debug)
+		printk("R:%s\n", buffer);
+	flushDebugChar();
+}
+
+/* send the packet in buffer.  */
+
+void
+putpacket(char *buffer)
+{
+	unsigned char checksum;
+	int count;
+	char ch;
+
+	/*  $<packet info>#<checksum>. */
+
+	if (!kgdboe) {
+		do {
+			if (remote_debug)
+				printk("T:%s\n", buffer);
+			putDebugChar('$');
+			checksum = 0;
+			count = 0;
+
+			while ((ch = buffer[count])) {
+				putDebugChar(ch);
+				checksum += ch;
+				count += 1;
+			}
+
+			putDebugChar('#');
+			putDebugChar(hexchars[checksum >> 4]);
+			putDebugChar(hexchars[checksum % 16]);
+			flushDebugChar();
+
+		} while ((getDebugChar() & 0x7f) != '+');
+	} else {
+		/*
+		 * For udp, we can not transfer too much bytes once.
+		 * We only transfer MAX_SEND_COUNT size bytes each time
+		 */
+
+#define MAX_SEND_COUNT 30
+
+		int send_count = 0, i = 0;
+		char send_buf[MAX_SEND_COUNT];
+
+		do {
+			if (remote_debug)
+				printk("T:%s\n", buffer);
+			putDebugChar('$');
+			checksum = 0;
+			count = 0;
+			send_count = 0;
+			while ((ch = buffer[count])) {
+				if (send_count >= MAX_SEND_COUNT) {
+					for(i = 0; i < MAX_SEND_COUNT; i++) {
+						putDebugChar(send_buf[i]);
+					}
+					flushDebugChar();
+					send_count = 0;
+				} else {
+					send_buf[send_count] = ch;
+					checksum += ch;
+					count ++;
+					send_count++;
+				}
+			}
+			for(i = 0; i < send_count; i++)
+				putDebugChar(send_buf[i]);
+			putDebugChar('#');
+			putDebugChar(hexchars[checksum >> 4]);
+			putDebugChar(hexchars[checksum % 16]);
+			flushDebugChar();
+		} while ((getDebugChar() & 0x7f) != '+');
+	}
+}
+
+static char remcomInBuffer[BUFMAX];
+static char remcomOutBuffer[BUFMAX];
+static char lbuf[BUFMAX];
+static short error;
+
+void
+debug_error(char *format, char *parm)
+{
+	if (remote_debug)
+		printk(format, parm);
+}
+
+static void
+print_regs(struct pt_regs *regs)
+{
+	printk("RAX=%016lx RBX=%016lx RCX=%016lx\n",
+		regs->rax, regs->rbx, regs->rcx);
+	printk("RDX=%016lx RSI=%016lx RDI=%016lx\n",
+		regs->rdx, regs->rsi, regs->rdi);
+	printk("RBP=%016lx PS=%016lx PC=%016lx\n",
+		regs->rbp, regs->eflags, regs->rip);
+ 	printk("R8=%016lx R9=%016lx R10=%016lx\n",
+		regs->r8, regs->r9, regs->r10);
+	printk("R11=%016lx R12=%016lx R13=%016lx\n",
+		regs->r11, regs->r12, regs->r13);
+	printk("R14=%016lx R15=%016lx RSP=%016lx\n",
+		regs->r14, regs->r15, regs->rsp);
+}
+
+#define NEW_esp fn_call_lookaside[trap_cpu].rsp
+
+static void
+regs_to_gdb_regs(unsigned long *gdb_regs, struct pt_regs *regs)
+{
+	gdb_regs[_RAX] =  regs->rax;
+	gdb_regs[_RBX] =  regs->rbx;
+	gdb_regs[_RCX] =  regs->rcx;
+	gdb_regs[_RDX] =  regs->rdx;
+	gdb_regs[_RSI] =  regs->rsi;
+	gdb_regs[_RDI] =  regs->rdi;
+	gdb_regs[_RBP] =  regs->rbp;
+	gdb_regs[ _PS] =  regs->eflags;
+	gdb_regs[ _PC] =  regs->rip;
+	gdb_regs[ _R8] =  regs->r8;
+	gdb_regs[ _R9] =  regs->r9;
+	gdb_regs[_R10] = regs->r10;
+	gdb_regs[_R11] = regs->r11;
+	gdb_regs[_R12] = regs->r12;
+	gdb_regs[_R13] = regs->r13;
+	gdb_regs[_R14] = regs->r14;
+	gdb_regs[_R15] = regs->r15;
+	gdb_regs[_RSP] =  regs->rsp;
+
+	/* Note, as we are a debugging the kernel, we will always
+	 * trap in kernel code, this means no priviledge change,
+	 * and so the pt_regs structure is not completely valid.  In a non
+	 * privilege change trap, only EFLAGS, CS and EIP are put on the stack,
+	 * SS and ESP are not stacked, this means that the last 2 elements of
+	 * pt_regs is not valid (they would normally refer to the user stack)
+	 * also, using regs+1 is no good because you end up will a value that is
+	 * 2 longs (8) too high.  This used to cause stepping over functions
+	 * to fail, so my fix is to use the address of regs->esp, which
+	 * should point at the end of the stack frame.	Note I have ignored
+	 * completely exceptions that cause an error code to be stacked, such
+	 * as double fault.  Stuart Hughes, Zentropix.
+	 * original code: gdb_regs[_ESP] =  (int) (regs + 1) ;
+
+	 * this is now done on entry and moved to OLD_esp (as well as NEW_esp).
+	 */
+}
+
+static void
+gdb_regs_to_regs(unsigned long *gdb_regs, struct pt_regs *regs)
+{
+	regs->rax	=     gdb_regs[_RAX] ;
+	regs->rbx	=     gdb_regs[_RBX] ;
+	regs->rcx	=     gdb_regs[_RCX] ;
+	regs->rdx	=     gdb_regs[_RDX] ;
+	regs->rsi	=     gdb_regs[_RSI] ;
+	regs->rdi	=     gdb_regs[_RDI] ;
+	regs->rbp	=     gdb_regs[_RBP] ;
+	regs->eflags	=     gdb_regs[ _PS] ;
+	regs->rip	=     gdb_regs[ _PC] ;
+	regs->r8	=     gdb_regs[ _R8] ;
+	regs->r9	=     gdb_regs[ _R9] ;
+	regs->r10	=     gdb_regs[ _R10] ;
+	regs->r11	=     gdb_regs[ _R11] ;
+	regs->r12	=     gdb_regs[ _R12] ;
+	regs->r13	=     gdb_regs[ _R13] ;
+	regs->r14	=     gdb_regs[ _R14] ;
+	regs->r15	=     gdb_regs[ _R15] ;
+ #if 0					/* can't change these */
+	regs->rsp	=     gdb_regs[_RSP] ;
+	regs->ss	=     gdb_regs[ _SS] ;
+	regs->fs = gdb_regs[_FS];
+	regs->gs = gdb_regs[_GS];
+#endif
+}				/* gdb_regs_to_regs */
+
+extern void scheduling_functions_start_here(void);
+extern void scheduling_functions_end_here(void);
+#define first_sched	((unsigned long) scheduling_functions_start_here)
+#define last_sched	((unsigned long) scheduling_functions_end_here)
+
+int thread_list = 0;
+extern void thread_return(void);
+
+void
+get_gdb_regs(struct task_struct *p, struct pt_regs *regs, unsigned long *gdb_regs)
+{
+	unsigned long **rbp, *rsp, *rsp0, pc;
+	int count = 0;
+	IF_SMP(int i);
+	if (!p || p == current) {
+		regs_to_gdb_regs(gdb_regs, regs);
+		return;
+	}
+#ifdef CONFIG_SMP
+	for (i = 0; i < MAX_NO_CPUS; i++) {
+		if (p == kgdb_info.cpus_waiting[i].task) {
+			regs_to_gdb_regs(gdb_regs,
+					 kgdb_info.cpus_waiting[i].regs);
+			gdb_regs[_RSP] =
+			    (unsigned long)&kgdb_info.cpus_waiting[i].regs->rsp;
+
+			return;
+		}
+	}
+#endif
+	memset(gdb_regs, 0, NUMREGBYTES);
+	rsp = (unsigned long *)p->thread.rsp;
+	rbp = (unsigned long **)rsp[0];
+	rsp += 2;
+	gdb_regs[_PC] =  (unsigned long)thread_return;
+	gdb_regs[_RBP] = (unsigned long)rbp;
+	gdb_regs[_RSP] = (unsigned long)rsp;
+
+/*
+ * This code is to give a more informative notion of where a process
+ * is waiting.	It is used only when the user asks for a thread info
+ * list.  If he then switches to the thread, s/he will find the task
+ * is in schedule, but a back trace should show the same info we come
+ * up with.  This code was shamelessly purloined from process.c.  It was
+ * then enhanced to provide more registers than simply the program
+ * counter.
+ */
+
+	if (!thread_list) {
+		return;
+	}
+
+	if (p->state == TASK_RUNNING)
+		return;
+	rsp0 = (unsigned long *)p->thread.rsp0;
+	if (rsp < (unsigned long *) p->thread_info || rsp > rsp0)
+		return;
+	/* include/asm-i386/system.h:switch_to() pushes ebp last. */
+	do {
+		if (*rbp < rsp || *rbp > rsp0)
+			break;
+		rbp = (unsigned long **)*rbp;
+		rsp = (unsigned long *)rbp;
+		pc = rsp[1];
+
+		if (pc < first_sched || pc >= last_sched)
+			break;
+		gdb_regs[_PC] = (unsigned long)pc;
+		gdb_regs[_RSP] = (unsigned long)rsp;
+		gdb_regs[_RBP] = (unsigned long)rbp;
+	} while (count++ < 16);
+	return;
+}
+
+/* convert the memory pointed to by mem into hex, placing result in buf */
+/* returns nonzero if any memory access fails. */
+int mem2hex( char* mem, char* buf, int   count)
+{
+	int i;
+	unsigned char ch;
+	int ret = 0;
+
+	for (i=0;i<count;i++) {
+		ch = 0;
+		ret |= __get_user(ch, mem);
+		mem++;
+		*buf++ = hexchars[ch >> 4];
+		*buf++ = hexchars[ch % 16];
+	}
+	*buf = 0;
+	if (ret) {
+		Dearly_printk("mem2hex: fault at accessing %p\n", mem);
+	}
+	return(ret);
+}
+
+/* convert the hex array pointed to by buf into binary to be placed in mem */
+/* return nonzero if any memory access fails. */
+int hex2mem( char* buf, char* mem, int count)
+{
+	int i;
+	unsigned char ch;
+	int ret = 0;
+
+	for (i=0;i<count;i++) {
+		ch = hex(*buf++) << 4;
+		ch = ch + hex(*buf++);
+		ret |= __put_user(ch, mem);
+		mem++;
+	}
+	if (ret) {
+		Dearly_printk("hex2mem: fault at %p\n", mem);
+	}
+	return(ret);
+}
+
+#if 0
+/* Indicate to caller of mem2hex or hex2mem that there has been an
+   error.  */
+static volatile int mem_err = 0;
+static volatile int mem_err_expected = 0;
+static volatile int mem_err_cnt = 0;
+static int garbage_loc = -1;
+
+int
+get_char(char *addr)
+{
+	return *addr;
+}
+
+void
+set_char(char *addr, int val, int may_fault)
+{
+	/*
+	 * This code traps references to the area mapped to the kernel
+	 * stack as given by the regs and, instead, stores to the
+	 * fn_call_lookaside[cpu].array
+	 */
+	if (may_fault &&
+	    (unsigned int) addr < OLD_esp &&
+	    ((unsigned int) addr > (OLD_esp - (unsigned int) LOOKASIDE_SIZE))) {
+		addr = (char *) END_OF_LOOKASIDE - ((char *) OLD_esp - addr);
+	}
+	*addr = val;
+}
+
+/* convert the memory pointed to by mem into hex, placing result in buf */
+/* return a pointer to the last char put in buf (null) */
+/* If MAY_FAULT is non-zero, then we should set mem_err in response to
+   a fault; if zero treat a fault like any other fault in the stub.  */
+char *
+mem2hex(char *mem, char *buf, int count, int may_fault)
+{
+	int i;
+	unsigned char ch;
+
+	if (may_fault) {
+		mem_err_expected = 1;
+		mem_err = 0;
+	}
+	for (i = 0; i < count; i++) {
+		/* printk("%lx = ", mem) ; */
+
+		ch = get_char(mem++);
+
+		/* printk("%02x\n", ch & 0xFF) ; */
+		if (may_fault && mem_err) {
+			if (remote_debug)
+				printk("Mem fault fetching from addr %lx\n",
+				       (long) (mem - 1));
+			*buf = 0;	/* truncate buffer */
+			return (buf);
+		}
+		*buf++ = hexchars[ch >> 4];
+		*buf++ = hexchars[ch % 16];
+	}
+	*buf = 0;
+	if (may_fault)
+		mem_err_expected = 0;
+	return (buf);
+}
+
+/* convert the hex array pointed to by buf into binary to be placed in mem */
+/* return a pointer to the character AFTER the last byte written */
+/* NOTE: We use the may fault flag to also indicate if the write is to
+ * the registers (0) or "other" memory (!=0)
+ */
+char *
+hex2mem(char *buf, char *mem, int count, int may_fault)
+{
+	int i;
+	unsigned char ch;
+
+	if (may_fault) {
+		mem_err_expected = 1;
+		mem_err = 0;
+	}
+	for (i = 0; i < count; i++) {
+		ch = hex(*buf++) << 4;
+		ch = ch + hex(*buf++);
+		set_char(mem++, ch, may_fault);
+
+		if (may_fault && mem_err) {
+			if (remote_debug)
+				printk("Mem fault storing to addr %lx\n",
+				       (long) (mem - 1));
+			return (mem);
+		}
+	}
+	if (may_fault)
+		mem_err_expected = 0;
+	return (mem);
+}
+#endif
+
+/**********************************************/
+/* WHILE WE FIND NICE HEX CHARS, BUILD AN INT */
+/* RETURN NUMBER OF CHARS PROCESSED	      */
+/**********************************************/
+int
+hexToLong(char **ptr, unsigned long *value)
+{
+	int numChars = 0;
+	int hexValue;
+
+	*value = 0;
+
+	while (**ptr) {
+		hexValue = hex(**ptr);
+		if (hexValue >= 0) {
+			*value = (*value << 4) | hexValue;
+			numChars++;
+		} else
+			break;
+
+		(*ptr)++;
+	}
+
+	return (numChars);
+}
+
+#define stubhex(h) hex(h)
+#ifdef old_thread_list
+
+static int
+stub_unpack_int(char *buff, int fieldlength)
+{
+	int nibble;
+	int retval = 0;
+
+	while (fieldlength) {
+		nibble = stubhex(*buff++);
+		retval |= nibble;
+		fieldlength--;
+		if (fieldlength)
+			retval = retval << 4;
+	}
+	return retval;
+}
+#endif
+static char *
+pack_hex_byte(char *pkt, int byte)
+{
+	*pkt++ = hexchars[(byte >> 4) & 0xf];
+	*pkt++ = hexchars[(byte & 0xf)];
+	return pkt;
+}
+
+#define BUF_THREAD_ID_SIZE 16
+
+static char *
+pack_threadid(char *pkt, threadref * id)
+{
+	char *limit;
+	unsigned char *altid;
+
+	altid = (unsigned char *) id;
+	limit = pkt + BUF_THREAD_ID_SIZE;
+	while (pkt < limit)
+		pkt = pack_hex_byte(pkt, *altid++);
+	return pkt;
+}
+
+#ifdef old_thread_list
+static char *
+unpack_byte(char *buf, int *value)
+{
+	*value = stub_unpack_int(buf, 2);
+	return buf + 2;
+}
+
+static char *
+unpack_threadid(char *inbuf, threadref * id)
+{
+	char *altref;
+	char *limit = inbuf + BUF_THREAD_ID_SIZE;
+	int x, y;
+
+	altref = (char *) id;
+
+	while (inbuf < limit) {
+		x = stubhex(*inbuf++);
+		y = stubhex(*inbuf++);
+		*altref++ = (x << 4) | y;
+	}
+	return inbuf;
+}
+#endif
+void
+int_to_threadref(threadref * id, int value)
+{
+	unsigned char *scan;
+
+	scan = (unsigned char *) id;
+	{
+		int i = 4;
+		while (i--)
+			*scan++ = 0;
+	}
+	*scan++ = (value >> 24) & 0xff;
+	*scan++ = (value >> 16) & 0xff;
+	*scan++ = (value >> 8) & 0xff;
+	*scan++ = (value & 0xff);
+}
+int
+int_to_hex_v(unsigned char * id, int value)
+{
+	unsigned char *start = id;
+	int shift;
+	int ch;
+
+	for (shift = 28; shift >= 0; shift -= 4) {
+		if ((ch = (value >> shift) & 0xf) || (id != start)) {
+			*id = hexchars[ch];
+			id++;
+		}
+	}
+	if (id == start)
+		*id++ = '0';
+	return id - start;
+}
+#ifdef old_thread_list
+
+static int
+threadref_to_int(threadref * ref)
+{
+	int i, value = 0;
+	unsigned char *scan;
+
+	scan = (char *) ref;
+	scan += 4;
+	i = 4;
+	while (i-- > 0)
+		value = (value << 8) | ((*scan++) & 0xff);
+	return value;
+}
+#endif
+static int
+cmp_str(char *s1, char *s2, int count)
+{
+	while (count--) {
+		if (*s1++ != *s2++)
+			return 0;
+	}
+	return 1;
+}
+
+#if 1				/* this is a hold over from 2.4 where O(1) was "sometimes" */
+extern struct task_struct *kgdb_get_idle(int cpu);
+#define idle_task(cpu) kgdb_get_idle(cpu)
+#else
+#define idle_task(cpu) init_tasks[cpu]
+#endif
+
+extern int kgdb_pid_init_done;
+
+struct task_struct *
+getthread(int pid)
+{
+	struct task_struct *thread;
+	if (pid >= PID_MAX && pid <= (PID_MAX + MAX_NO_CPUS)) {
+		if (!cpu_online(pid - PID_MAX))
+			return NULL;
+
+		return idle_task(pid - PID_MAX);
+	} else {
+		/*
+		 * find_task_by_pid is relatively safe all the time
+		 * Other pid functions require lock downs which imply
+		 * that we may be interrupting them (as we get here
+		 * in the middle of most any lock down).
+		 * Still we don't want to call until the table exists!
+		 */
+		if (kgdb_pid_init_done){
+			thread = find_task_by_pid(pid);
+			if (thread) {
+				return thread;
+			}
+		}
+	}
+	return NULL;
+}
+/* *INDENT-OFF*	 */
+struct hw_breakpoint {
+	unsigned enabled;
+	unsigned type;
+	unsigned len;
+	unsigned long addr;
+} breakinfo[4] = { {enabled:0},
+		   {enabled:0},
+		   {enabled:0},
+		   {enabled:0}};
+/* *INDENT-ON*	*/
+unsigned long hw_breakpoint_status;
+void
+correct_hw_break(void)
+{
+	int breakno;
+	int correctit;
+	int breakbit;
+	unsigned long dr7;
+
+	asm volatile ("movq %%db7, %0\n":"=r" (dr7)
+		      :);
+	/* *INDENT-OFF*	 */
+	do {
+		unsigned long addr0, addr1, addr2, addr3;
+		asm volatile ("movq %%db0, %0\n"
+			      "movq %%db1, %1\n"
+			      "movq %%db2, %2\n"
+			      "movq %%db3, %3\n"
+			      :"=r" (addr0), "=r"(addr1),
+			      "=r"(addr2), "=r"(addr3)
+			      :);
+	} while (0);
+	/* *INDENT-ON*	*/
+	correctit = 0;
+	for (breakno = 0; breakno < 3; breakno++) {
+		breakbit = 2 << (breakno << 1);
+		if (!(dr7 & breakbit) && breakinfo[breakno].enabled) {
+			correctit = 1;
+			dr7 |= breakbit;
+			dr7 &= ~(0xf0000 << (breakno << 2));
+			dr7 |= (((breakinfo[breakno].len << 2) |
+				 breakinfo[breakno].type) << 16) <<
+			    (breakno << 2);
+			switch (breakno) {
+			case 0:
+				asm volatile ("movq %0, %%dr0\n"::"r"
+					      (breakinfo[breakno].addr));
+				break;
+
+			case 1:
+				asm volatile ("movq %0, %%dr1\n"::"r"
+					      (breakinfo[breakno].addr));
+				break;
+
+			case 2:
+				asm volatile ("movq %0, %%dr2\n"::"r"
+					      (breakinfo[breakno].addr));
+				break;
+
+			case 3:
+				asm volatile ("movq %0, %%dr3\n"::"r"
+					      (breakinfo[breakno].addr));
+				break;
+			}
+		} else if ((dr7 & breakbit) && !breakinfo[breakno].enabled) {
+			correctit = 1;
+			dr7 &= ~breakbit;
+			dr7 &= ~(0xf0000 << (breakno << 2));
+		}
+	}
+	if (correctit) {
+		asm volatile ("movq %0, %%db7\n"::"r" (dr7));
+	}
+}
+
+int
+remove_hw_break(unsigned breakno)
+{
+	if (!breakinfo[breakno].enabled) {
+		return -1;
+	}
+	breakinfo[breakno].enabled = 0;
+	return 0;
+}
+
+int
+set_hw_break(unsigned breakno, unsigned type, unsigned len, unsigned addr)
+{
+	if (breakinfo[breakno].enabled) {
+		return -1;
+	}
+	breakinfo[breakno].enabled = 1;
+	breakinfo[breakno].type = type;
+	breakinfo[breakno].len = len;
+	breakinfo[breakno].addr = addr;
+	return 0;
+}
+
+#ifdef CONFIG_SMP
+static int in_kgdb_console = 0;
+
+int
+in_kgdb(struct pt_regs *regs)
+{
+	unsigned long flags;
+	int cpu;
+	if (!kgdb_enabled)
+		return 0;
+	cpu = smp_processor_id();
+	in_kgdb_called = 1;
+	if (!spin_is_locked(&kgdb_spinlock)) {
+		if (in_kgdb_here_log[cpu] ||	/* we are holding this cpu */
+		    in_kgdb_console) {	/* or we are doing slow i/o */
+			return 1;
+		}
+		return 0;
+	}
+
+	/* As I see it the only reason not to let all cpus spin on
+	 * the same spin_lock is to allow selected ones to proceed.
+	 * This would be a good thing, so we leave it this way.
+	 * Maybe someday....  Done !
+
+	 * in_kgdb() is called from an NMI so we don't pretend
+	 * to have any resources, like printk() for example.
+	 */
+
+	local_irq_save(flags);	/* only local here, to avoid hanging */
+	/*
+	 * log arival of this cpu
+	 * The NMI keeps on ticking.  Protect against recurring more
+	 * than once, and ignor the cpu that has the kgdb lock
+	 */
+	in_kgdb_entry_log[cpu]++;
+	in_kgdb_here_log[cpu] = regs;
+	if (cpu == spinlock_cpu || waiting_cpus[cpu].task)
+		goto exit_in_kgdb;
+
+	/*
+	 * For protection of the initilization of the spin locks by kgdb
+	 * it locks the kgdb spinlock before it gets the wait locks set
+	 * up.	We wait here for the wait lock to be taken.  If the
+	 * kgdb lock goes away first??	Well, it could be a slow exit
+	 * sequence where the wait lock is removed prior to the kgdb lock
+	 * so if kgdb gets unlocked, we just exit.
+	 */
+
+	while (spin_is_locked(&kgdb_spinlock) &&
+	       !spin_is_locked(waitlocks + cpu)) ;
+	if (!spin_is_locked(&kgdb_spinlock))
+		goto exit_in_kgdb;
+
+	waiting_cpus[cpu].task = current;
+	waiting_cpus[cpu].pid = (current->pid) ? : (PID_MAX + cpu);
+	waiting_cpus[cpu].regs = regs;
+
+	spin_unlock_wait(waitlocks + cpu);
+
+	/*
+	 * log departure of this cpu
+	 */
+	waiting_cpus[cpu].task = 0;
+	waiting_cpus[cpu].pid = 0;
+	waiting_cpus[cpu].regs = 0;
+	correct_hw_break();
+      exit_in_kgdb:
+	in_kgdb_here_log[cpu] = 0;
+	local_irq_restore(flags);
+	return 1;
+	/*
+	   spin_unlock(continuelocks + smp_processor_id());
+	 */
+}
+
+void
+smp__in_kgdb(struct pt_regs regs)
+{
+	ack_APIC_irq();
+	in_kgdb(&regs);
+}
+#else
+int
+in_kgdb(struct pt_regs *regs)
+{
+	return (kgdb_spinlock);
+}
+#endif
+
+void
+printexceptioninfo(int exceptionNo, int errorcode, char *buffer)
+{
+	unsigned long dr6;
+	int i;
+	switch (exceptionNo) {
+	case 1:		/* debug exception */
+		break;
+	case 3:		/* breakpoint */
+		sprintf(buffer, "Software breakpoint");
+		return;
+	default:
+		sprintf(buffer, "Details not available");
+		return;
+	}
+	asm volatile ("movq %%db6, %0\n":"=r" (dr6)
+		      :);
+	if (dr6 & 0x4000) {
+		sprintf(buffer, "Single step");
+		return;
+	}
+	for (i = 0; i < 4; ++i) {
+		if (dr6 & (1 << i)) {
+			sprintf(buffer, "Hardware breakpoint %d", i);
+			return;
+		}
+	}
+	sprintf(buffer, "Unknown trap");
+	return;
+}
+
+/*
+ * The ThreadExtraInfo query allows us to pass an arbitrary string
+ * for display with the "info threads" command.
+ */
+
+void
+print_extra_info(task_t *p, char *buf)
+{
+	if (!p) {
+		sprintf(buf, "Invalid thread");
+		return;
+	}
+	sprintf(buf, "0x%p %8d %4d  %c  %s",
+		   (void *)p,  p->parent->pid,
+		   task_cpu(p),
+		   (p->state == 0) ? (task_curr(p)?'R':'r') :
+		     (p->state < 0) ? 'U' :
+		     (p->state & TASK_UNINTERRUPTIBLE) ? 'D' :
+		     (p->state & TASK_STOPPED || p->ptrace & PT_PTRACED) ? 'T' :
+		     (p->state & (TASK_ZOMBIE | TASK_DEAD)) ? 'Z' :
+		     (p->state & TASK_INTERRUPTIBLE) ? 'S' : '?',
+		   p->comm);
+}
+
+/*
+ * This function does all command procesing for interfacing to gdb.
+ *
+ * NOTE:  The INT nn instruction leaves the state of the interrupt
+ *	  enable flag UNCHANGED.  That means that when this routine
+ *	  is entered via a breakpoint (INT 3) instruction from code
+ *	  that has interrupts enabled, then interrupts will STILL BE
+ *	  enabled when this routine is entered.	 The first thing that
+ *	  we do here is disable interrupts so as to prevent recursive
+ *	  entries and bothersome serial interrupts while we are
+ *	  trying to run the serial port in polled mode.
+ *
+ * For kernel version 2.1.xx the kgdb_cli() actually gets a spin lock so
+ * it is always necessary to do a restore_flags before returning
+ * so as to let go of that lock.
+ */
+int
+kgdb_handle_exception(int exceptionVector,
+		      int signo, int err_code, struct pt_regs *linux_regs)
+{
+	struct task_struct *usethread = NULL;
+	struct task_struct *thread_list_start = 0, *thread = NULL;
+	struct task_struct *p;
+	unsigned long addr, length;
+	unsigned long breakno, breaktype;
+	char *ptr;
+	unsigned long newPC;
+	threadref thref;
+	unsigned long threadid, tmpid;
+	int thread_min = PID_MAX + MAX_NO_CPUS;
+#ifdef old_thread_list
+	int maxthreads;
+#endif
+	int nothreads;
+	unsigned long flags;
+	unsigned long gdb_regs[NUMREGS];
+	unsigned long dr6;
+	IF_SMP(int entry_state = 0);	/* 0, ok, 1, no nmi, 2 sync failed */
+#define NO_NMI 1
+#define NO_SYNC 2
+#define	regs	(*linux_regs)
+	/*
+	 * If the entry is not from the kernel then return to the Linux
+	 * trap handler and let it process the interrupt normally.
+	 */
+	if ((linux_regs->eflags & VM_MASK) || (3 & linux_regs->cs)) {
+		printk("ignoring non-kernel exception\n");
+		print_regs(&regs);
+		return (0);
+	}
+	/*
+	 * If we're using eth mode, set the 'mode' in the netdevice.
+	 */
+
+	if (kgdboe)
+		netpoll_set_trap(1);
+
+	local_irq_save(flags);
+
+	/* Get kgdb spinlock */
+
+	KGDB_SPIN_LOCK(&kgdb_spinlock);
+	rdtscll(kgdb_info.entry_tsc);
+	/*
+	 * We depend on this spinlock and the NMI watch dog to control the
+	 * other cpus.	They will arrive at "in_kgdb()" as a result of the
+	 * NMI and will wait there for the following spin locks to be
+	 * released.
+	 */
+#ifdef CONFIG_SMP
+
+#if 0
+	if (cpu_callout_map & ~MAX_CPU_MASK) {
+		printk("kgdb : too many cpus, possibly not mapped"
+		       " in contiguous space, change MAX_NO_CPUS"
+		       " in kgdb_stub and make new kernel.\n"
+		       " cpu_callout_map is %lx\n", cpu_callout_map);
+		goto exit_just_unlock;
+	}
+#endif
+	if (spinlock_count == 1) {
+		int time, end_time, dum;
+		int i;
+		int cpu_logged_in[MAX_NO_CPUS] = {[0 ... MAX_NO_CPUS - 1] = (0)
+		};
+		if (remote_debug) {
+			printk("kgdb : cpu %d entry, syncing others\n",
+			       smp_processor_id());
+		}
+		for (i = 0; i < MAX_NO_CPUS; i++) {
+			/*
+			 * Use trylock as we may already hold the lock if
+			 * we are holding the cpu.  Net result is all
+			 * locked.
+			 */
+			spin_trylock(&waitlocks[i]);
+		}
+		for (i = 0; i < MAX_NO_CPUS; i++)
+			cpu_logged_in[i] = 0;
+		/*
+		 * Wait for their arrival.  We know the watch dog is active if
+		 * in_kgdb() has ever been called, as it is always called on a
+		 * watchdog tick.
+		 */
+		rdtsc(dum, time);
+		end_time = time + 2;	/* Note: we use the High order bits! */
+		i = 1;
+		if (num_online_cpus() > 1) {
+			int me_in_kgdb = in_kgdb_entry_log[smp_processor_id()];
+			smp_send_nmi_allbutself();
+
+			while (i < num_online_cpus() && time != end_time) {
+				int j;
+				for (j = 0; j < MAX_NO_CPUS; j++) {
+					if (waiting_cpus[j].task &&
+					    waiting_cpus[j].task != NOCPU &&
+					    !cpu_logged_in[j]) {
+						i++;
+						cpu_logged_in[j] = 1;
+						if (remote_debug) {
+							printk
+							    ("kgdb : cpu %d arrived at kgdb\n",
+							     j);
+						}
+						break;
+					} else if (!waiting_cpus[j].task &&
+						   !cpu_online(j)) {
+						waiting_cpus[j].task = NOCPU;
+						cpu_logged_in[j] = 1;
+						waiting_cpus[j].hold = 1;
+						break;
+					}
+					if (!waiting_cpus[j].task &&
+					    in_kgdb_here_log[j]) {
+
+						int wait = 100000;
+						while (wait--) ;
+						if (!waiting_cpus[j].task &&
+						    in_kgdb_here_log[j]) {
+							printk
+							    ("kgdb : cpu %d stall"
+							     " in in_kgdb\n",
+							     j);
+							i++;
+							cpu_logged_in[j] = 1;
+							waiting_cpus[j].task =
+							    (struct task_struct
+							     *) 1;
+						}
+					}
+				}
+
+				if (in_kgdb_entry_log[smp_processor_id()] >
+				    (me_in_kgdb + 10)) {
+					break;
+				}
+
+				rdtsc(dum, time);
+			}
+			if (i < num_online_cpus()) {
+				printk
+				    ("kgdb : time out, proceeding without sync\n");
+#if 0
+				printk("kgdb : Waiting_cpus: 0 = %d, 1 = %d\n",
+				       waiting_cpus[0].task != 0,
+				       waiting_cpus[1].task != 0);
+				printk("kgdb : Cpu_logged in: 0 = %d, 1 = %d\n",
+				       cpu_logged_in[0], cpu_logged_in[1]);
+				printk
+				    ("kgdb : in_kgdb_here_log in: 0 = %d, 1 = %d\n",
+				     in_kgdb_here_log[0] != 0,
+				     in_kgdb_here_log[1] != 0);
+#endif
+				entry_state = NO_SYNC;
+			} else {
+#if 0
+				int ent =
+				    in_kgdb_entry_log[smp_processor_id()] -
+				    me_in_kgdb;
+				printk("kgdb : sync after %d entries\n", ent);
+#endif
+			}
+		} else {
+			if (remote_debug) {
+				printk
+				    ("kgdb : %d cpus, but watchdog not active\n"
+				     "proceeding without locking down other cpus\n",
+				     num_online_cpus());
+				entry_state = NO_NMI;
+			}
+		}
+	}
+#endif
+
+	if (remote_debug) {
+		unsigned long *lp = (unsigned long *) &linux_regs;
+
+		printk("handle_exception(exceptionVector=%d, "
+		       "signo=%d, err_code=%d, linux_regs=%p)\n",
+		       exceptionVector, signo, err_code, linux_regs);
+		if (debug_regs) {
+			print_regs(&regs);
+			printk("Stk: %8lx %8lx %8lx %8lx"
+			       "  %8lx %8lx %8lx %8lx\n",
+			       lp[0], lp[1], lp[2], lp[3],
+			       lp[4], lp[5], lp[6], lp[7]);
+			printk("     %8lx %8lx %8lx %8lx"
+			       "  %8lx %8lx %8lx %8lx\n",
+			       lp[8], lp[9], lp[10], lp[11],
+			       lp[12], lp[13], lp[14], lp[15]);
+			printk("     %8lx %8lx %8lx %8lx  "
+			       "%8lx %8lx %8lx %8lx\n",
+			       lp[16], lp[17], lp[18], lp[19],
+			       lp[20], lp[21], lp[22], lp[23]);
+			printk("     %8lx %8lx %8lx %8lx  "
+			       "%8lx %8lx %8lx %8lx\n",
+			       lp[24], lp[25], lp[26], lp[27],
+			       lp[28], lp[29], lp[30], lp[31]);
+		}
+	}
+
+	/* Disable hardware debugging while we are in kgdb */
+	/* Get the debug register status register */
+/*				       *INDENT-OFF*  */
+      __asm__("movq %0,%%db7"
+	      :	/* no output */
+	      :"r"(0UL));
+
+	asm volatile ("movq %%db6, %0\n"
+		      :"=r" (hw_breakpoint_status)
+		      :);
+
+#if 0
+/*				       *INDENT-ON*  */
+	switch (exceptionVector) {
+	case 0:		/* divide error */
+	case 1:		/* debug exception */
+	case 2:		/* NMI */
+	case 3:		/* breakpoint */
+	case 4:		/* overflow */
+	case 5:		/* bounds check */
+	case 6:		/* invalid opcode */
+	case 7:		/* device not available */
+	case 8:		/* double fault (errcode) */
+	case 10:		/* invalid TSS (errcode) */
+	case 12:		/* stack fault (errcode) */
+	case 16:		/* floating point error */
+	case 17:		/* alignment check (errcode) */
+	default:		/* any undocumented */
+		break;
+	case 11:		/* segment not present (errcode) */
+	case 13:		/* general protection (errcode) */
+	case 14:		/* page fault (special errcode) */
+	case 19:		/* cache flush denied */
+		if (mem_err_expected) {
+			/*
+			 * This fault occured because of the
+			 * get_char or set_char routines.  These
+			 * two routines use either eax of edx to
+			 * indirectly reference the location in
+			 * memory that they are working with.
+			 * For a page fault, when we return the
+			 * instruction will be retried, so we
+			 * have to make sure that these
+			 * registers point to valid memory.
+			 */
+			mem_err = 1;	/* set mem error flag */
+			mem_err_expected = 0;
+			mem_err_cnt++;	/* helps in debugging */
+			/* make valid address */
+			regs.eax = (long) &garbage_loc;
+			/* make valid address */
+			regs.edx = (long) &garbage_loc;
+			if (remote_debug)
+				printk("Return after memory error: "
+				       "mem_err_cnt=%d\n", mem_err_cnt);
+			if (debug_regs)
+				print_regs(&regs);
+			goto exit_kgdb;
+		}
+		break;
+	}
+#endif
+	if (remote_debug)
+		printk("kgdb : entered kgdb on cpu %d\n", smp_processor_id());
+
+	gdb_i386vector = exceptionVector;
+	gdb_i386errcode = err_code;
+	kgdb_info.called_from = __builtin_return_address(0);
+#ifdef CONFIG_SMP
+	/*
+	 * OK, we can now communicate, lets tell gdb about the sync.
+	 * but only if we had a problem.
+	 */
+	switch (entry_state) {
+	case NO_NMI:
+		to_gdb("NMI not active, other cpus not stopped\n");
+		break;
+	case NO_SYNC:
+		to_gdb("Some cpus not stopped, see 'kgdb_info' for details\n");
+	default:;
+	}
+
+#endif
+/*
+ * Set up the gdb function call area.
+ */
+	trap_cpu = smp_processor_id();
+	OLD_esp = NEW_esp = (unsigned long) (&linux_regs->rsp);
+
+      IF_SMP(once_again:)
+	    /* reply to host that an exception has occurred */
+	    remcomOutBuffer[0] = 'S';
+	remcomOutBuffer[1] = hexchars[signo >> 4];
+	remcomOutBuffer[2] = hexchars[signo % 16];
+	remcomOutBuffer[3] = 0;
+
+	putpacket(remcomOutBuffer);
+
+	while (1 == 1) {
+		error = 0;
+		remcomOutBuffer[0] = 0;
+		getpacket(remcomInBuffer);
+		switch (remcomInBuffer[0]) {
+		case '?':
+			remcomOutBuffer[0] = 'S';
+			remcomOutBuffer[1] = hexchars[signo >> 4];
+			remcomOutBuffer[2] = hexchars[signo % 16];
+			remcomOutBuffer[3] = 0;
+			break;
+		case 'd':
+			remote_debug = !(remote_debug);	/* toggle debug flag */
+			printk("Remote debug %s\n",
+			       remote_debug ? "on" : "off");
+			break;
+		case 'g':	/* return the value of the CPU registers */
+			get_gdb_regs(usethread, &regs, gdb_regs);
+			mem2hex((char *) gdb_regs,
+				remcomOutBuffer, NUMREGBYTES);
+			break;
+		case 'G':	/* set the value of the CPU registers - return OK */
+			hex2mem(&remcomInBuffer[1],
+				(char *) gdb_regs, NUMREGBYTES);
+			if (!usethread || usethread == current) {
+				gdb_regs_to_regs(gdb_regs, &regs);
+				strcpy(remcomOutBuffer, "OK");
+			} else {
+				strcpy(remcomOutBuffer, "E00");
+			}
+			break;
+
+		case 'P':{	/* set the value of a single CPU register -
+				   return OK */
+				/*
+				 * For some reason, gdb wants to talk about psudo
+				 * registers (greater than 15).
+				 */
+				unsigned long regno;
+
+				ptr = &remcomInBuffer[1];
+				regs_to_gdb_regs(gdb_regs, &regs);
+				if ((!usethread || usethread == current) &&
+				    hexToLong(&ptr, &regno) &&
+				    *ptr++ == '=' && (regno >= 0)) {
+					if (regno >= NUMREGS)
+						break;
+					hex2mem(ptr, (char *) &gdb_regs[regno],
+						8);
+					gdb_regs_to_regs(gdb_regs, &regs);
+					strcpy(remcomOutBuffer, "OK");
+					break;
+				}
+				strcpy(remcomOutBuffer, "E01");
+				break;
+			}
+
+			/* mAA..AA,LLLL	 Read LLLL bytes at address AA..AA */
+		case 'm':
+			/* TRY TO READ %x,%x.  IF SUCCEED, SET PTR = 0 */
+			ptr = &remcomInBuffer[1];
+			if (hexToLong(&ptr, &addr) &&
+			    (*(ptr++) == ',') && (hexToLong(&ptr, &length))) {
+				ptr = 0;
+				/*
+				 * hex doubles the byte count
+				 */
+				if (length > (BUFMAX / 2))
+					length = BUFMAX / 2;
+				if (mem2hex((char *) addr,
+					remcomOutBuffer, length)) {
+					strcpy(remcomOutBuffer, "E03");
+					debug_error("memory fault\n", NULL);
+				}
+			}
+
+			if (ptr) {
+				strcpy(remcomOutBuffer, "E01");
+				debug_error
+				    ("malformed read memory command: %s\n",
+				     remcomInBuffer);
+			}
+			break;
+
+			/* MAA..AA,LLLL:
+			   Write LLLL bytes at address AA.AA return OK */
+		case 'M':
+			/* TRY TO READ '%x,%x:'.  IF SUCCEED, SET PTR = 0 */
+			ptr = &remcomInBuffer[1];
+			if (hexToLong(&ptr, &addr) &&
+			    (*(ptr++) == ',') &&
+			    (hexToLong(&ptr, &length)) && (*(ptr++) == ':')) {
+				if (hex2mem(ptr, (char *) addr, length)) {
+					strcpy(remcomOutBuffer, "E03");
+					debug_error("memory fault\n", NULL);
+				} else {
+					strcpy(remcomOutBuffer, "OK");
+				}
+
+				ptr = 0;
+			}
+			if (ptr) {
+				strcpy(remcomOutBuffer, "E02");
+				debug_error
+				    ("malformed write memory command: %s\n",
+				     remcomInBuffer);
+			}
+			break;
+		case 'S':
+			remcomInBuffer[0] = 's';
+		case 'C':
+			/* Csig;AA..AA where ;AA..AA is optional
+			 * continue with signal
+			 * Since signals are meaning less to us, delete that
+			 * part and then fall into the 'c' code.
+			 */
+			ptr = &remcomInBuffer[1];
+			length = 2;
+			while (*ptr && *ptr != ';') {
+				length++;
+				ptr++;
+			}
+			if (*ptr) {
+				do {
+					ptr++;
+					*(ptr - length++) = *ptr;
+				} while (*ptr);
+			} else {
+				remcomInBuffer[1] = 0;
+			}
+
+			/* cAA..AA  Continue at address AA..AA(optional) */
+			/* sAA..AA  Step one instruction from AA..AA(optional) */
+			/* D	    detach, reply OK and then continue */
+		case 'c':
+		case 's':
+		case 'D':
+
+			/* try to read optional parameter,
+			   pc unchanged if no parm */
+			ptr = &remcomInBuffer[1];
+			if (hexToLong(&ptr, &addr)) {
+				if (remote_debug)
+					printk("Changing EIP to 0x%lx\n", addr);
+
+				regs.rip = addr;
+			}
+
+			newPC = regs.rip;
+
+			/* clear the trace bit */
+			regs.eflags &= 0xfffffeff;
+
+			/* set the trace bit if we're stepping */
+			if (remcomInBuffer[0] == 's')
+				regs.eflags |= 0x100;
+
+			/* detach is a friendly version of continue. Note that
+			   debugging is still enabled (e.g hit control C)
+			 */
+			if (remcomInBuffer[0] == 'D') {
+				strcpy(remcomOutBuffer, "OK");
+				putpacket(remcomOutBuffer);
+			}
+
+			if (remote_debug) {
+				printk("Resuming execution\n");
+				print_regs(&regs);
+			}
+			asm volatile ("movq %%db6, %0\n":"=r" (dr6)
+				      :);
+			if (!(dr6 & 0x4000)) {
+				for (breakno = 0; breakno < 4; ++breakno) {
+					if (dr6 & (1 << breakno) &&
+					    (breakinfo[breakno].type == 0)) {
+						/* Set restore flag */
+						regs.eflags |= 0x10000;
+						break;
+					}
+				}
+			}
+
+			if (kgdboe)
+				netpoll_set_trap(0);
+
+			correct_hw_break();
+			asm volatile ("movq %0, %%db6\n"::"r" (0UL));
+			goto exit_kgdb;
+
+			/* kill the program */
+		case 'k':	/* do nothing */
+			break;
+
+			/* query */
+		case 'q':
+			nothreads = 0;
+			switch (remcomInBuffer[1]) {
+			case 'f':
+				threadid = 1;
+				thread_list = 2;
+				thread_list_start = (usethread ? : current);
+			case 's':
+				if (!cmp_str(&remcomInBuffer[2],
+					     "ThreadInfo", 10))
+					break;
+
+				remcomOutBuffer[nothreads++] = 'm';
+				for (; threadid < PID_MAX + MAX_NO_CPUS;
+				     threadid++) {
+					thread = getthread(threadid);
+					if (thread) {
+						nothreads += int_to_hex_v(
+							&remcomOutBuffer[
+								nothreads],
+							threadid);
+						if (thread_min > threadid)
+							thread_min = threadid;
+						remcomOutBuffer[
+							nothreads] = ',';
+						nothreads++;
+						if (nothreads > BUFMAX - 10)
+							break;
+					}
+				}
+				if (remcomOutBuffer[nothreads - 1] == 'm') {
+					remcomOutBuffer[nothreads - 1] = 'l';
+				} else {
+					nothreads--;
+				}
+				remcomOutBuffer[nothreads] = 0;
+				break;
+
+#ifdef old_thread_list /* Old thread info request */
+			case 'L':
+				/* List threads */
+				thread_list = 2;
+				thread_list_start = (usethread ? : current);
+				unpack_byte(remcomInBuffer + 3, &maxthreads);
+				unpack_threadid(remcomInBuffer + 5, &thref);
+				do {
+					int buf_thread_limit =
+					    (BUFMAX - 22) / BUF_THREAD_ID_SIZE;
+					if (maxthreads > buf_thread_limit) {
+						maxthreads = buf_thread_limit;
+					}
+				} while (0);
+				remcomOutBuffer[0] = 'q';
+				remcomOutBuffer[1] = 'M';
+				remcomOutBuffer[4] = '0';
+				pack_threadid(remcomOutBuffer + 5, &thref);
+
+				/* If start flag set start at 0. */
+				if (remcomInBuffer[2] == '1')
+					threadid = 0;
+				else
+					threadid = threadref_to_int(&thref);
+				for (nothreads = 0;
+				     nothreads < maxthreads &&
+				     threadid < PID_MAX + MAX_NO_CPUS;
+				     threadid++) {
+					thread = getthread(threadid);
+					if (thread) {
+						int_to_threadref(&thref,
+								 threadid);
+						pack_threadid(remcomOutBuffer +
+							      21 +
+							      nothreads * 16,
+							      &thref);
+						nothreads++;
+						if (thread_min > threadid)
+							thread_min = threadid;
+					}
+				}
+
+				if (threadid == PID_MAX + MAX_NO_CPUS) {
+					remcomOutBuffer[4] = '1';
+				}
+				pack_hex_byte(remcomOutBuffer + 2, nothreads);
+				remcomOutBuffer[21 + nothreads * 16] = '\0';
+				break;
+#endif
+			case 'C':
+				/* Current thread id */
+				remcomOutBuffer[0] = 'Q';
+				remcomOutBuffer[1] = 'C';
+				threadid = current->pid;
+				if (!threadid) {
+					/*
+					 * idle thread
+					 */
+					for (threadid = PID_MAX;
+					     threadid < PID_MAX + MAX_NO_CPUS;
+					     threadid++) {
+						if (current ==
+						    idle_task(threadid -
+							      PID_MAX))
+							break;
+					}
+				}
+				int_to_threadref(&thref, threadid);
+				pack_threadid(remcomOutBuffer + 2, &thref);
+				remcomOutBuffer[18] = '\0';
+				break;
+
+			case 'E':
+				/* Print exception info */
+				printexceptioninfo(exceptionVector,
+						   err_code, remcomOutBuffer);
+				break;
+			case 'T':
+				ptr = &remcomInBuffer[0];
+				if (strncmp(ptr, "qThreadExtraInfo,",
+					strlen("qThreadExtraInfo,")) == 0) {
+					ptr += strlen("qThreadExtraInfo,");
+					hexToLong(&ptr, &tmpid);
+					p = getthread(tmpid);
+					print_extra_info(p, lbuf);
+					mem2hex(lbuf, remcomOutBuffer,
+						strlen(lbuf));
+				}
+				break;
+#if 0
+			case 'T':{
+				char * nptr;
+				/* Thread extra info */
+				if (!cmp_str(&remcomInBuffer[2],
+					    "hreadExtraInfo,", 15)) {
+					break;
+				}
+				ptr = &remcomInBuffer[17];
+				hexToLong(&ptr, &threadid);
+				thread = getthread(threadid);
+				nptr = &thread->comm[0];
+				length = 0;
+				ptr = &remcomOutBuffer[0];
+				do {
+					length++;
+					ptr = pack_hex_byte(ptr, *nptr++);
+				 } while (*nptr && length < 16);
+				/*
+				 * would like that 16 to be the size of
+				 * task_struct.comm but don't know the
+				 * syntax..
+				 */
+				*ptr = 0;
+			}
+#endif
+			}
+			break;
+
+			/* task related */
+		case 'H':
+			switch (remcomInBuffer[1]) {
+			case 'g':
+				ptr = &remcomInBuffer[2];
+				hexToLong(&ptr, &threadid);
+				thread = getthread(threadid);
+				if (!thread) {
+					remcomOutBuffer[0] = 'E';
+					remcomOutBuffer[1] = '\0';
+					break;
+				}
+				/*
+				 * Just in case I forget what this is all about,
+				 * the "thread info" command to gdb causes it
+				 * to ask for a thread list.  It then switches
+				 * to each thread and asks for the registers.
+				 * For this (and only this) usage, we want to
+				 * fudge the registers of tasks not on the run
+				 * list (i.e. waiting) to show the routine that
+				 * called schedule. Also, gdb, is a minimalist
+				 * in that if the current thread is the last
+				 * it will not re-read the info when done.
+				 * This means that in this case we must show
+				 * the real registers. So here is how we do it:
+				 * Each entry we keep track of the min
+				 * thread in the list (the last that gdb will)
+				 * get info for.  We also keep track of the
+				 * starting thread.
+				 * "thread_list" is cleared when switching back
+				 * to the min thread if it is was current, or
+				 * if it was not current, thread_list is set
+				 * to 1.  When the switch to current comes,
+				 * if thread_list is 1, clear it, else do
+				 * nothing.
+				 */
+				usethread = thread;
+				if ((thread_list == 1) &&
+				    (thread == thread_list_start)) {
+					thread_list = 0;
+				}
+				if (thread_list && (threadid == thread_min)) {
+					if (thread == thread_list_start) {
+						thread_list = 0;
+					} else {
+						thread_list = 1;
+					}
+				}
+				/* follow through */
+			case 'c':
+				remcomOutBuffer[0] = 'O';
+				remcomOutBuffer[1] = 'K';
+				remcomOutBuffer[2] = '\0';
+				break;
+			}
+			break;
+
+			/* Query thread status */
+		case 'T':
+			ptr = &remcomInBuffer[1];
+			hexToLong(&ptr, &threadid);
+			thread = getthread(threadid);
+			if (thread) {
+				remcomOutBuffer[0] = 'O';
+				remcomOutBuffer[1] = 'K';
+				remcomOutBuffer[2] = '\0';
+				if (thread_min > threadid)
+					thread_min = threadid;
+			} else {
+				remcomOutBuffer[0] = 'E';
+				remcomOutBuffer[1] = '\0';
+			}
+			break;
+
+		case 'Y': /* set up a hardware breakpoint */
+			ptr = &remcomInBuffer[1];
+			hexToLong(&ptr, &breakno);
+			ptr++;
+			hexToLong(&ptr, &breaktype);
+			ptr++;
+			hexToLong(&ptr, &length);
+			ptr++;
+			hexToLong(&ptr, &addr);
+			if (set_hw_break(breakno & 0x3,
+					 breaktype & 0x3,
+					 length & 0x3, addr) == 0) {
+				strcpy(remcomOutBuffer, "OK");
+			} else {
+				strcpy(remcomOutBuffer, "ERROR");
+			}
+			break;
+
+			/* Remove hardware breakpoint */
+		case 'y':
+			ptr = &remcomInBuffer[1];
+			hexToLong(&ptr, &breakno);
+			if (remove_hw_break(breakno & 0x3) == 0) {
+				strcpy(remcomOutBuffer, "OK");
+			} else {
+				strcpy(remcomOutBuffer, "ERROR");
+			}
+			break;
+
+		case 'r':	/* reboot */
+			strcpy(remcomOutBuffer, "OK");
+			putpacket(remcomOutBuffer);
+			/*to_gdb("Rebooting\n"); */
+			/* triplefault	 no return from here */
+			{
+				static long no_idt[2];
+				__asm__ __volatile__("lidt %0"::"m"(no_idt[0]));
+				BREAKPOINT;
+			}
+
+		}		/* switch */
+
+		/* reply to the request */
+		putpacket(remcomOutBuffer);
+	}			/* while(1==1) */
+	/*
+	 *  reached by goto only.
+	 */
+      exit_kgdb:
+	/*
+	 * Here is where we set up to trap a gdb function call.	 NEW_esp
+	 * will be changed if we are trying to do this.	 We handle both
+	 * adding and subtracting, thus allowing gdb to put grung on
+	 * the stack which it removes later.
+	 */
+	if (NEW_esp != OLD_esp) {
+		unsigned long *ptr = END_OF_LOOKASIDE;
+		if (NEW_esp < OLD_esp)
+			ptr -= (OLD_esp - NEW_esp) / sizeof (unsigned long);
+		*--ptr = linux_regs->eflags;
+		*--ptr = linux_regs->cs;
+		*--ptr = linux_regs->rip;
+		*--ptr = linux_regs->rcx;
+		*--ptr = linux_regs->rbx;
+		*--ptr = linux_regs->rax;
+		linux_regs->rcx = NEW_esp - (sizeof (unsigned long) * 6);
+		linux_regs->rbx = (unsigned long) END_OF_LOOKASIDE;
+		if (NEW_esp < OLD_esp) {
+			linux_regs->rip = (unsigned long) fn_call_stub;
+		} else {
+			linux_regs->rip = (unsigned long) fn_rtn_stub;
+			linux_regs->rax = NEW_esp;
+		}
+		linux_regs->eflags &= ~(IF_BIT | TF_BIT);
+	}
+#ifdef CONFIG_SMP
+	/*
+	 * Release gdb wait locks
+	 * Sanity check time.  Must have at least one cpu to run.  Also single
+	 * step must not be done if the current cpu is on hold.
+	 */
+	if (spinlock_count == 1) {
+		int ss_hold = (regs.eflags & 0x100) && kgdb_info.hold_on_sstep;
+		int cpu_avail = 0;
+		int i;
+
+		for (i = 0; i < MAX_NO_CPUS; i++) {
+			if (!cpu_online(i))
+				break;
+			if (!hold_cpu(i)) {
+				cpu_avail = 1;
+			}
+		}
+		/*
+		 * Early in the bring up there will be NO cpus on line...
+		 */
+		if (!cpu_avail && !cpus_empty(cpu_online_map)) {
+			to_gdb("No cpus unblocked, see 'kgdb_info.hold_cpu'\n");
+			goto once_again;
+		}
+		if (hold_cpu(smp_processor_id()) && (regs.eflags & 0x100)) {
+			to_gdb
+			    ("Current cpu must be unblocked to single step\n");
+			goto once_again;
+		}
+		if (!(ss_hold)) {
+			int i;
+			for (i = 0; i < MAX_NO_CPUS; i++) {
+				if (!hold_cpu(i)) {
+					spin_unlock(&waitlocks[i]);
+				}
+			}
+		} else {
+			spin_unlock(&waitlocks[smp_processor_id()]);
+		}
+		/* Release kgdb spinlock */
+		KGDB_SPIN_UNLOCK(&kgdb_spinlock);
+		/*
+		 * If this cpu is on hold, this is where we
+		 * do it.  Note, the NMI will pull us out of here,
+		 * but will return as the above lock is not held.
+		 * We will stay here till another cpu releases the lock for us.
+		 */
+		spin_unlock_wait(waitlocks + smp_processor_id());
+		local_irq_restore(flags);
+		return (1);
+	}
+#if 0
+exit_just_unlock:
+#endif
+#endif
+	/* Release kgdb spinlock */
+	KGDB_SPIN_UNLOCK(&kgdb_spinlock);
+	local_irq_restore(flags);
+	return (1);
+}
+
+#undef regs
+static int kgdb_notify(struct notifier_block *self, unsigned long cmd, void *ptr)
+{
+	struct die_args *d = ptr;
+
+	if (!kgdb_enabled || (cmd == DIE_DEBUG && user_mode(d->regs)))
+		return NOTIFY_DONE;
+	if (cmd == DIE_NMI_IPI) {
+		if (in_kgdb(d->regs))
+			return NOTIFY_BAD;
+	} else if (kgdb_handle_exception(d->trapnr, d->signr, d->err, d->regs))
+		return NOTIFY_BAD; /* skip */
+
+	return NOTIFY_DONE;
+}
+
+static struct notifier_block kgdb_notifier = {
+	.notifier_call = kgdb_notify,
+	.priority = 0,
+};
+
+void set_debug_traps(void)
+{
+	static int initialized = 0;
+
+	if (!initialized) {
+		initialized = 1;
+		notifier_chain_register(&die_chain, &kgdb_notifier);
+	}
+}
+
+/*
+ * Provide the command line "gdb" initial break
+ */
+int __init kgdb_initial_break(char * str)
+{
+	if (*str == '\0'){
+		breakpoint();
+		return 1;
+	}
+	return 0;
+}
+__setup("gdb",kgdb_initial_break);
+
+/* This function will generate a breakpoint exception.	It is used at the
+   beginning of a program to sync up with a debugger and can be used
+   otherwise as a quick means to stop program execution and "break" into
+   the debugger. */
+/* But really, just use the BREAKPOINT macro.  We will handle the int stuff
+ */
+
+void breakpoint(void)
+{
+
+	set_debug_traps();
+	kgdb_enabled = 1;
+#if 0
+	/*
+	 * These calls were not enough to allow breakpoint to be
+	 * called before trap_init().  I moved the argument parsing
+	 * after trap_init() and it seems to work.
+	 */
+	set_intr_usr_gate(3,&int3); /* disable ints on trap */
+	set_intr_gate(1,&debug);
+	set_intr_gate(14,&page_fault);
+#endif
+
+        BREAKPOINT;
+}
+
+#ifdef later
+/*
+ * possibly we should not go thru the traps.c code at all?  Someday.
+ */
+void
+do_kgdb_int3(struct pt_regs *regs, long error_code)
+{
+	kgdb_handle_exception(3, 5, error_code, regs);
+	return;
+}
+#endif
+#undef regs
+#ifdef CONFIG_TRAP_BAD_SYSCALL_EXITS
+asmlinkage void
+bad_sys_call_exit(int stuff)
+{
+	struct pt_regs *regs = (struct pt_regs *) &stuff;
+	printk("Sys call %d return with %x preempt_count\n",
+	       (int) regs->orig_eax, preempt_count());
+}
+#endif
+#ifdef CONFIG_STACK_OVERFLOW_TEST
+#include <asm/kgdb.h>
+asmlinkage void
+stack_overflow(void)
+{
+#ifdef BREAKPOINT
+	BREAKPOINT;
+#else
+	printk("Kernel stack overflow, looping forever\n");
+#endif
+	while (1) {
+	}
+}
+#endif
+
+#if defined(CONFIG_SMP) || defined(CONFIG_KGDB_CONSOLE)
+char gdbconbuf[BUFMAX];
+
+static void
+kgdb_gdb_message(const char *s, unsigned count)
+{
+	int i;
+	int wcount;
+	char *bufptr;
+	/*
+	 * This takes care of NMI while spining out chars to gdb
+	 */
+	IF_SMP(in_kgdb_console = 1);
+	gdbconbuf[0] = 'O';
+	bufptr = gdbconbuf + 1;
+	while (count > 0) {
+		if ((count << 1) > (BUFMAX - 2)) {
+			wcount = (BUFMAX - 2) >> 1;
+		} else {
+			wcount = count;
+		}
+		count -= wcount;
+		for (i = 0; i < wcount; i++) {
+			bufptr = pack_hex_byte(bufptr, s[i]);
+		}
+		*bufptr = '\0';
+		s += wcount;
+
+		putpacket(gdbconbuf);
+
+	}
+	IF_SMP(in_kgdb_console = 0);
+}
+#endif
+#ifdef CONFIG_SMP
+static void
+to_gdb(const char *s)
+{
+	int count = 0;
+	while (s[count] && (count++ < BUFMAX)) ;
+	kgdb_gdb_message(s, count);
+}
+#endif
+#ifdef CONFIG_KGDB_CONSOLE
+#include <linux/console.h>
+#include <linux/init.h>
+#include <linux/fs.h>
+#include <asm/semaphore.h>
+
+void
+kgdb_console_write(struct console *co, const char *s, unsigned count)
+{
+
+	if (gdb_i386vector == -1) {
+		/*
+		 * We have not yet talked to gdb.  What to do...
+		 * lets break, on continue we can do the write.
+		 * But first tell him whats up. Uh, well no can do,
+		 * as this IS the console.  Oh well...
+		 * We do need to wait or the messages will be lost.
+		 * Other option would be to tell the above code to
+		 * ignore this breakpoint and do an auto return,
+		 * but that might confuse gdb.	Also this happens
+		 * early enough in boot up that we don't have the traps
+		 * set up yet, so...
+		 */
+		breakpoint();
+	}
+	kgdb_gdb_message(s, count);
+}
+
+/*
+ * ------------------------------------------------------------
+ * Serial KGDB driver
+ * ------------------------------------------------------------
+ */
+
+static struct console kgdbcons = {
+	name:"kgdb",
+	write:kgdb_console_write,
+#ifdef CONFIG_KGDB_USER_CONSOLE
+	device:kgdb_console_device,
+#endif
+	flags:CON_PRINTBUFFER | CON_ENABLED,
+	index:-1,
+};
+
+/*
+ * The trick here is that this file gets linked before printk.o
+ * That means we get to peer at the console info in the command
+ * line before it does.	 If we are up, we register, otherwise,
+ * do nothing.	By returning 0, we allow printk to look also.
+ */
+static int kgdb_console_enabled;
+
+int __init
+kgdb_console_init(char *str)
+{
+	if ((strncmp(str, "kgdb", 4) == 0) || (strncmp(str, "gdb", 3) == 0)) {
+		register_console(&kgdbcons);
+		kgdb_console_enabled = 1;
+	}
+	return 0;		/* let others look at the string */
+}
+
+__setup("console=", kgdb_console_init);
+
+#ifdef CONFIG_KGDB_USER_CONSOLE
+static kdev_t kgdb_console_device(struct console *c);
+/* This stuff sort of works, but it knocks out telnet devices
+ * we are leaving it here in case we (or you) find time to figure it out
+ * better..
+ */
+
+/*
+ * We need a real char device as well for when the console is opened for user
+ * space activities.
+ */
+
+static int
+kgdb_consdev_open(struct inode *inode, struct file *file)
+{
+	return 0;
+}
+
+static ssize_t
+kgdb_consdev_write(struct file *file, const char *buf,
+		   size_t count, loff_t * ppos)
+{
+	int size, ret = 0;
+	static char kbuf[128];
+	static DECLARE_MUTEX(sem);
+
+	/* We are not reentrant... */
+	if (down_interruptible(&sem))
+		return -ERESTARTSYS;
+
+	while (count > 0) {
+		/* need to copy the data from user space */
+		size = count;
+		if (size > sizeof (kbuf))
+			size = sizeof (kbuf);
+		if (copy_from_user(kbuf, buf, size)) {
+			ret = -EFAULT;
+			break;;
+		}
+		kgdb_console_write(&kgdbcons, kbuf, size);
+		count -= size;
+		ret += size;
+		buf += size;
+	}
+
+	up(&sem);
+
+	return ret;
+}
+
+struct file_operations kgdb_consdev_fops = {
+	open:kgdb_consdev_open,
+	write:kgdb_consdev_write
+};
+static kdev_t
+kgdb_console_device(struct console *c)
+{
+	return MKDEV(TTYAUX_MAJOR, 1);
+}
+
+/*
+ * This routine gets called from the serial stub in the i386/lib
+ * This is so it is done late in bring up (just before the console open).
+ */
+void
+kgdb_console_finit(void)
+{
+	if (kgdb_console_enabled) {
+		char *cptr = cdevname(MKDEV(TTYAUX_MAJOR, 1));
+		char *cp = cptr;
+		while (*cptr && *cptr != '(')
+			cptr++;
+		*cptr = 0;
+		unregister_chrdev(TTYAUX_MAJOR, cp);
+		register_chrdev(TTYAUX_MAJOR, "kgdb", &kgdb_consdev_fops);
+	}
+}
+#endif
+#endif
+#ifdef CONFIG_KGDB_TS
+#include <asm/msr.h>		/* time stamp code */
+#include <asm/hardirq.h>	/* in_interrupt */
+#ifdef CONFIG_KGDB_TS_64
+#define DATA_POINTS 64
+#endif
+#ifdef CONFIG_KGDB_TS_128
+#define DATA_POINTS 128
+#endif
+#ifdef CONFIG_KGDB_TS_256
+#define DATA_POINTS 256
+#endif
+#ifdef CONFIG_KGDB_TS_512
+#define DATA_POINTS 512
+#endif
+#ifdef CONFIG_KGDB_TS_1024
+#define DATA_POINTS 1024
+#endif
+#ifndef DATA_POINTS
+#define DATA_POINTS 128		/* must be a power of two */
+#endif
+#define INDEX_MASK (DATA_POINTS - 1)
+#if (INDEX_MASK & DATA_POINTS)
+#error "CONFIG_KGDB_TS_COUNT must be a power of 2"
+#endif
+struct kgdb_and_then_struct {
+#ifdef CONFIG_SMP
+	int on_cpu;
+#endif
+	struct task_struct *task;
+	long long at_time;
+	int from_ln;
+	char *in_src;
+	void *from;
+	int *with_shpf;
+	int data0;
+	int data1;
+};
+struct kgdb_and_then_struct2 {
+#ifdef CONFIG_SMP
+	int on_cpu;
+#endif
+	struct task_struct *task;
+	long long at_time;
+	int from_ln;
+	char *in_src;
+	void *from;
+	int *with_shpf;
+	struct task_struct *t1;
+	struct task_struct *t2;
+};
+struct kgdb_and_then_struct kgdb_data[DATA_POINTS];
+
+struct kgdb_and_then_struct *kgdb_and_then = &kgdb_data[0];
+int kgdb_and_then_count;
+
+void
+kgdb_tstamp(int line, char *source, int data0, int data1)
+{
+	static spinlock_t ts_spin = SPIN_LOCK_UNLOCKED;
+	int flags;
+	local_irq_save(flags);
+	spin_lock(&ts_spin);
+	rdtscll(kgdb_and_then->at_time);
+#ifdef CONFIG_SMP
+	kgdb_and_then->on_cpu = smp_processor_id();
+#endif
+	kgdb_and_then->task = current;
+	kgdb_and_then->from_ln = line;
+	kgdb_and_then->in_src = source;
+	kgdb_and_then->from = __builtin_return_address(0);
+	kgdb_and_then->with_shpf = (int *) (((flags & IF_BIT) >> 9) |
+					    (preempt_count() << 8));
+	kgdb_and_then->data0 = data0;
+	kgdb_and_then->data1 = data1;
+	kgdb_and_then = &kgdb_data[++kgdb_and_then_count & INDEX_MASK];
+	spin_unlock(&ts_spin);
+	local_irq_restore(flags);
+#ifdef CONFIG_PREEMPT
+
+#endif
+	return;
+}
+#endif
+typedef int gdb_debug_hook(int exceptionVector,
+			   int signo, int err_code, struct pt_regs *linux_regs);
+gdb_debug_hook *linux_debug_hook = &kgdb_handle_exception;	/* histerical reasons... */
+
+static int kgdb_need_breakpoint[NR_CPUS];
+
+void kgdb_schedule_breakpoint(void)
+{
+	kgdb_need_breakpoint[smp_processor_id()] = 1;
+}
+
+void kgdb_process_breakpoint(void)
+{
+	/*
+	 * Handle a breakpoint queued from inside network driver code
+         * to avoid reentrancy issues
+	 */
+	if (kgdb_need_breakpoint[smp_processor_id()]) {
+		kgdb_need_breakpoint[smp_processor_id()] = 0;
+		kgdb_enabled = 1;
+		BREAKPOINT;
+	}
+}
+
--- diff/arch/x86_64/lib/kgdb_serial.c	1970-01-01 01:00:00.000000000 +0100
+++ source/arch/x86_64/lib/kgdb_serial.c	2004-02-23 13:56:39.000000000 +0000
@@ -0,0 +1,490 @@
+/*
+ * Serial interface GDB stub
+ *
+ * Written (hacked together) by David Grothe (dave@gcom.com)
+ * Modified to allow invokation early in boot see also
+ * kgdb.h for instructions by George Anzinger(george@mvista.com)
+ * Modified to handle debugging over ethernet by Robert Walsh
+ * <rjwalsh@durables.org> and wangdi <wangdi@clusterfs.com>, based on
+ * code by San Mehat.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/errno.h>
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/timer.h>
+#include <linux/interrupt.h>
+#include <linux/tty.h>
+#include <linux/tty_flip.h>
+#include <linux/serial.h>
+#include <linux/serial_reg.h>
+#include <linux/config.h>
+#include <linux/major.h>
+#include <linux/string.h>
+#include <linux/fcntl.h>
+#include <linux/ptrace.h>
+#include <linux/ioport.h>
+#include <linux/mm.h>
+#include <linux/init.h>
+#include <linux/highmem.h>
+#include <asm/system.h>
+#include <asm/io.h>
+#include <asm/segment.h>
+#include <asm/bitops.h>
+#include <asm/system.h>
+#include <asm/kgdb_local.h>
+#ifdef CONFIG_KGDB_USER_CONSOLE
+extern void kgdb_console_finit(void);
+#endif
+#define PRNT_off
+#define TEST_EXISTANCE
+#ifdef PRNT
+#define dbprintk(s) printk s
+#else
+#define dbprintk(s)
+#endif
+#define TEST_INTERRUPT_off
+#ifdef TEST_INTERRUPT
+#define intprintk(s) printk s
+#else
+#define intprintk(s)
+#endif
+
+#define IRQ_T(info) ((info->flags & ASYNC_SHARE_IRQ) ? SA_SHIRQ : SA_INTERRUPT)
+
+#define	GDB_BUF_SIZE	512	/* power of 2, please */
+
+static char gdb_buf[GDB_BUF_SIZE];
+static int gdb_buf_in_inx;
+static atomic_t gdb_buf_in_cnt;
+static int gdb_buf_out_inx;
+
+struct async_struct *gdb_async_info;
+static int gdb_async_irq;
+
+#define outb_px(a,b) outb_p(b,a)
+
+static void program_uart(struct async_struct *info);
+static void write_char(struct async_struct *info, int chr);
+/*
+ * Get a byte from the hardware data buffer and return it
+ */
+static int
+read_data_bfr(struct async_struct *info)
+{
+	char it = inb_p(info->port + UART_LSR);
+
+	if (it & UART_LSR_DR)
+		return (inb_p(info->port + UART_RX));
+	/*
+	 * If we have a framing error assume somebody messed with
+	 * our uart.  Reprogram it and send '-' both ways...
+	 */
+	if (it & 0xc) {
+		program_uart(info);
+		write_char(info, '-');
+		return ('-');
+	}
+	return (-1);
+
+}				/* read_data_bfr */
+
+/*
+ * Get a char if available, return -1 if nothing available.
+ * Empty the receive buffer first, then look at the interface hardware.
+
+ * Locking here is a bit of a problem.	We MUST not lock out communication
+ * if we are trying to talk to gdb about a kgdb entry.	ON the other hand
+ * we can loose chars in the console pass thru if we don't lock.  It is also
+ * possible that we could hold the lock or be waiting for it when kgdb
+ * NEEDS to talk.  Since kgdb locks down the world, it does not need locks.
+ * We do, of course have possible issues with interrupting a uart operation,
+ * but we will just depend on the uart status to help keep that straight.
+
+ */
+static spinlock_t uart_interrupt_lock = SPIN_LOCK_UNLOCKED;
+#ifdef CONFIG_SMP
+extern spinlock_t kgdb_spinlock;
+#endif
+
+static int
+read_char(struct async_struct *info)
+{
+	int chr;
+	unsigned long flags;
+	local_irq_save(flags);
+#ifdef CONFIG_SMP
+	if (!spin_is_locked(&kgdb_spinlock)) {
+		spin_lock(&uart_interrupt_lock);
+	}
+#endif
+	if (atomic_read(&gdb_buf_in_cnt) != 0) {	/* intr routine has q'd chars */
+		chr = gdb_buf[gdb_buf_out_inx++];
+		gdb_buf_out_inx &= (GDB_BUF_SIZE - 1);
+		atomic_dec(&gdb_buf_in_cnt);
+	} else {
+		chr = read_data_bfr(info);
+	}
+#ifdef CONFIG_SMP
+	if (!spin_is_locked(&kgdb_spinlock)) {
+		spin_unlock(&uart_interrupt_lock);
+	}
+#endif
+	local_irq_restore(flags);
+	return (chr);
+}
+
+/*
+ * Wait until the interface can accept a char, then write it.
+ */
+static void
+write_char(struct async_struct *info, int chr)
+{
+	while (!(inb_p(info->port + UART_LSR) & UART_LSR_THRE)) ;
+
+	outb_p(chr, info->port + UART_TX);
+
+}				/* write_char */
+
+/*
+ * Mostly we don't need a spinlock, but since the console goes
+ * thru here with interrutps on, well, we need to catch those
+ * chars.
+ */
+/*
+ * This is the receiver interrupt routine for the GDB stub.
+ * It will receive a limited number of characters of input
+ * from the gdb  host machine and save them up in a buffer.
+ *
+ * When the gdb stub routine tty_getDebugChar() is called it
+ * draws characters out of the buffer until it is empty and
+ * then reads directly from the serial port.
+ *
+ * We do not attempt to write chars from the interrupt routine
+ * since the stubs do all of that via tty_putDebugChar() which
+ * writes one byte after waiting for the interface to become
+ * ready.
+ *
+ * The debug stubs like to run with interrupts disabled since,
+ * after all, they run as a consequence of a breakpoint in
+ * the kernel.
+ *
+ * Perhaps someone who knows more about the tty driver than I
+ * care to learn can make this work for any low level serial
+ * driver.
+ */
+static irqreturn_t
+gdb_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+	struct async_struct *info;
+	unsigned long flags;
+
+	info = gdb_async_info;
+	if (!info || !info->tty || irq != gdb_async_irq)
+		return IRQ_NONE;
+
+	local_irq_save(flags);
+	spin_lock(&uart_interrupt_lock);
+	do {
+		int chr = read_data_bfr(info);
+		intprintk(("Debug char on int: %x hex\n", chr));
+		if (chr < 0)
+			continue;
+
+		if (chr == 3) {	/* Ctrl-C means remote interrupt */
+			BREAKPOINT;
+			continue;
+		}
+
+		if (atomic_read(&gdb_buf_in_cnt) >= GDB_BUF_SIZE) {
+			/* buffer overflow tosses early char */
+			read_char(info);
+		}
+		gdb_buf[gdb_buf_in_inx++] = chr;
+		gdb_buf_in_inx &= (GDB_BUF_SIZE - 1);
+	} while (inb_p(info->port + UART_IIR) & UART_IIR_RDI);
+	spin_unlock(&uart_interrupt_lock);
+	local_irq_restore(flags);
+	return IRQ_HANDLED;
+}				/* gdb_interrupt */
+
+/*
+ * Just a NULL routine for testing.
+ */
+void
+gdb_null(void)
+{
+}				/* gdb_null */
+
+/* These structure are filled in with values defined in asm/kgdb_local.h
+ */
+static struct serial_state state = SB_STATE;
+static struct async_struct local_info = SB_INFO;
+static int ok_to_enable_ints = 0;
+static void kgdb_enable_ints_now(void);
+
+extern char *kgdb_version;
+/*
+ * Hook an IRQ for KGDB.
+ *
+ * This routine is called from tty_putDebugChar, below.
+ */
+static int ints_disabled = 1;
+int
+gdb_hook_interrupt(struct async_struct *info, int verb)
+{
+	struct serial_state *state = info->state;
+	unsigned long flags;
+	int port;
+#ifdef TEST_EXISTANCE
+	int scratch, scratch2;
+#endif
+
+	/* The above fails if memory managment is not set up yet.
+	 * Rather than fail the set up, just keep track of the fact
+	 * and pick up the interrupt thing later.
+	 */
+	gdb_async_info = info;
+	port = gdb_async_info->port;
+	gdb_async_irq = state->irq;
+	if (verb) {
+		printk("kgdb %s : port =%x, IRQ=%d, divisor =%d\n",
+		       kgdb_version,
+		       port,
+		       gdb_async_irq, gdb_async_info->state->custom_divisor);
+	}
+	local_irq_save(flags);
+#ifdef TEST_EXISTANCE
+	/* Existance test */
+	/* Should not need all this, but just in case.... */
+
+	scratch = inb_p(port + UART_IER);
+	outb_px(port + UART_IER, 0);
+	outb_px(0xff, 0x080);
+	scratch2 = inb_p(port + UART_IER);
+	outb_px(port + UART_IER, scratch);
+	if (scratch2) {
+		printk
+		    ("gdb_hook_interrupt: Could not clear IER, not a UART!\n");
+		local_irq_restore(flags);
+		return 1;	/* We failed; there's nothing here */
+	}
+	scratch2 = inb_p(port + UART_LCR);
+	outb_px(port + UART_LCR, 0xBF);	/* set up for StarTech test */
+	outb_px(port + UART_EFR, 0);	/* EFR is the same as FCR */
+	outb_px(port + UART_LCR, 0);
+	outb_px(port + UART_FCR, UART_FCR_ENABLE_FIFO);
+	scratch = inb_p(port + UART_IIR) >> 6;
+	if (scratch == 1) {
+		printk("gdb_hook_interrupt: Undefined UART type!"
+		       "  Not a UART! \n");
+		local_irq_restore(flags);
+		return 1;
+	} else {
+		dbprintk(("gdb_hook_interrupt: UART type "
+			  "is %d where 0=16450, 2=16550 3=16550A\n", scratch));
+	}
+	scratch = inb_p(port + UART_MCR);
+	outb_px(port + UART_MCR, UART_MCR_LOOP | scratch);
+	outb_px(port + UART_MCR, UART_MCR_LOOP | 0x0A);
+	scratch2 = inb_p(port + UART_MSR) & 0xF0;
+	outb_px(port + UART_MCR, scratch);
+	if (scratch2 != 0x90) {
+		printk("gdb_hook_interrupt: "
+		       "Loop back test failed! Not a UART!\n");
+		local_irq_restore(flags);
+		return scratch2 + 1000;	/* force 0 to fail */
+	}
+#endif				/* test existance */
+	program_uart(info);
+	local_irq_restore(flags);
+
+	return (0);
+
+}				/* gdb_hook_interrupt */
+
+static void
+program_uart(struct async_struct *info)
+{
+	int port = info->port;
+
+	(void) inb_p(port + UART_RX);
+	outb_px(port + UART_IER, 0);
+
+	(void) inb_p(port + UART_RX);	/* serial driver comments say */
+	(void) inb_p(port + UART_IIR);	/* this clears the interrupt regs */
+	(void) inb_p(port + UART_MSR);
+	outb_px(port + UART_LCR, UART_LCR_WLEN8 | UART_LCR_DLAB);
+	outb_px(port + UART_DLL, info->state->custom_divisor & 0xff);	/* LS */
+	outb_px(port + UART_DLM, info->state->custom_divisor >> 8);	/* MS  */
+	outb_px(port + UART_MCR, info->MCR);
+
+	outb_px(port + UART_FCR, UART_FCR_ENABLE_FIFO | UART_FCR_TRIGGER_1 | UART_FCR_CLEAR_XMIT | UART_FCR_CLEAR_RCVR);	/* set fcr */
+	outb_px(port + UART_LCR, UART_LCR_WLEN8);	/* reset DLAB */
+	outb_px(port + UART_FCR, UART_FCR_ENABLE_FIFO | UART_FCR_TRIGGER_1);	/* set fcr */
+	if (!ints_disabled) {
+		intprintk(("KGDB: Sending %d to port %x offset %d\n",
+			   gdb_async_info->IER,
+			   (int) gdb_async_info->port, UART_IER));
+		outb_px(gdb_async_info->port + UART_IER, gdb_async_info->IER);
+	}
+	return;
+}
+
+/*
+ * tty_getDebugChar
+ *
+ * This is a GDB stub routine.	It waits for a character from the
+ * serial interface and then returns it.  If there is no serial
+ * interface connection then it returns a bogus value which will
+ * almost certainly cause the system to hang.  In the
+ */
+int kgdb_in_isr = 0;
+int kgdb_in_lsr = 0;
+extern spinlock_t kgdb_spinlock;
+
+/* Caller takes needed protections */
+
+int
+tty_getDebugChar(void)
+{
+	volatile int chr, dum, time, end_time;
+
+	dbprintk(("tty_getDebugChar(port %x): ", gdb_async_info->port));
+
+	if (gdb_async_info == NULL) {
+		gdb_hook_interrupt(&local_info, 0);
+	}
+	/*
+	 * This trick says if we wait a very long time and get
+	 * no char, return the -1 and let the upper level deal
+	 * with it.
+	 */
+	rdtsc(dum, time);
+	end_time = time + 2;
+	while (((chr = read_char(gdb_async_info)) == -1) &&
+	       (end_time - time) > 0) {
+		rdtsc(dum, time);
+	};
+	/*
+	 * This covers our butts if some other code messes with
+	 * our uart, hay, it happens :o)
+	 */
+	if (chr == -1)
+		program_uart(gdb_async_info);
+
+	dbprintk(("%c\n", chr > ' ' && chr < 0x7F ? chr : ' '));
+	return (chr);
+
+}				/* tty_getDebugChar */
+
+static int count = 3;
+static spinlock_t one_at_atime = SPIN_LOCK_UNLOCKED;
+
+static int __init
+kgdb_enable_ints(void)
+{
+	set_debug_traps();
+	if (kgdboe) {
+		return 0;
+	}
+	if (gdb_async_info == NULL) {
+		gdb_hook_interrupt(&local_info, 1);
+	}
+	ok_to_enable_ints = 1;
+	kgdb_enable_ints_now();
+#ifdef CONFIG_KGDB_USER_CONSOLE
+	kgdb_console_finit();
+#endif
+	return 0;
+}
+
+#ifdef CONFIG_SERIAL_8250
+void shutdown_for_kgdb(struct async_struct *gdb_async_info);
+#endif
+
+#define kgdb_mem_init_done()    (1)
+
+static void
+kgdb_enable_ints_now(void)
+{
+	if (!spin_trylock(&one_at_atime))
+		return;
+	if (!ints_disabled)
+		goto exit;
+	if (kgdb_mem_init_done() &&
+			ints_disabled) {	/* don't try till mem init */
+#ifdef CONFIG_SERIAL_8250
+		/*
+		 * The ifdef here allows the system to be configured
+		 * without the serial driver.
+		 * Don't make it a module, however, it will steal the port
+		 */
+		shutdown_for_kgdb(gdb_async_info);
+#endif
+		ints_disabled = request_irq(gdb_async_info->state->irq,
+					    gdb_interrupt,
+					    IRQ_T(gdb_async_info),
+					    "KGDB-stub", NULL);
+		intprintk(("KGDB: request_irq returned %d\n", ints_disabled));
+	}
+	if (!ints_disabled) {
+		intprintk(("KGDB: Sending %d to port %x offset %d\n",
+			   gdb_async_info->IER,
+			   (int) gdb_async_info->port, UART_IER));
+		outb_px(gdb_async_info->port + UART_IER, gdb_async_info->IER);
+	}
+      exit:
+	spin_unlock(&one_at_atime);
+}
+
+/*
+ * tty_putDebugChar
+ *
+ * This is a GDB stub routine.	It waits until the interface is ready
+ * to transmit a char and then sends it.  If there is no serial
+ * interface connection then it simply returns to its caller, having
+ * pretended to send the char.	Caller takes needed protections.
+ */
+void
+tty_putDebugChar(int chr)
+{
+	dbprintk(("tty_putDebugChar(port %x): chr=%02x '%c', ints_on=%d\n",
+		  gdb_async_info->port,
+		  chr,
+		  chr > ' ' && chr < 0x7F ? chr : ' ', ints_disabled ? 0 : 1));
+
+	if (gdb_async_info == NULL) {
+		gdb_hook_interrupt(&local_info, 0);
+	}
+
+	write_char(gdb_async_info, chr);	/* this routine will wait */
+	count = (chr == '#') ? 0 : count + 1;
+	if ((count == 2)) {	/* try to enable after */
+		if (ints_disabled & ok_to_enable_ints)
+			kgdb_enable_ints_now();	/* try to enable after */
+
+		/* We do this a lot because, well we really want to get these
+		 * interrupts.	The serial driver will clear these bits when it
+		 * initializes the chip.  Every thing else it does is ok,
+		 * but this.
+		 */
+		if (!ints_disabled) {
+			outb_px(gdb_async_info->port + UART_IER,
+				gdb_async_info->IER);
+		}
+	}
+
+}				/* tty_putDebugChar */
+
+/*
+ * This does nothing for the serial port, since it doesn't buffer.
+ */
+
+void tty_flushDebugChar(void)
+{
+}
+
+module_init(kgdb_enable_ints);
--- diff/drivers/block/cfq-iosched.c	1970-01-01 01:00:00.000000000 +0100
+++ source/drivers/block/cfq-iosched.c	2004-02-23 13:56:40.000000000 +0000
@@ -0,0 +1,707 @@
+/*
+ *  linux/drivers/block/cfq-iosched.c
+ *
+ *  CFQ, or complete fairness queueing, disk scheduler.
+ *
+ *  Based on ideas from a previously unfinished io
+ *  scheduler (round robin per-process disk scheduling) and Andrea Arcangeli.
+ *
+ *  Copyright (C) 2003 Jens Axboe <axboe@suse.de>
+ */
+#include <linux/kernel.h>
+#include <linux/fs.h>
+#include <linux/blkdev.h>
+#include <linux/elevator.h>
+#include <linux/bio.h>
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/init.h>
+#include <linux/compiler.h>
+#include <linux/hash.h>
+#include <linux/rbtree.h>
+#include <linux/mempool.h>
+
+/*
+ * tunables
+ */
+static int cfq_quantum = 4;
+static int cfq_queued = 8;
+
+#define CFQ_QHASH_SHIFT		6
+#define CFQ_QHASH_ENTRIES	(1 << CFQ_QHASH_SHIFT)
+#define list_entry_qhash(entry)	list_entry((entry), struct cfq_queue, cfq_hash)
+
+#define CFQ_MHASH_SHIFT		8
+#define CFQ_MHASH_BLOCK(sec)	((sec) >> 3)
+#define CFQ_MHASH_ENTRIES	(1 << CFQ_MHASH_SHIFT)
+#define CFQ_MHASH_FN(sec)	(hash_long(CFQ_MHASH_BLOCK((sec)),CFQ_MHASH_SHIFT))
+#define ON_MHASH(crq)		!list_empty(&(crq)->hash)
+#define rq_hash_key(rq)		((rq)->sector + (rq)->nr_sectors)
+#define list_entry_hash(ptr)	list_entry((ptr), struct cfq_rq, hash)
+
+#define list_entry_cfqq(ptr)	list_entry((ptr), struct cfq_queue, cfq_list)
+
+#define RQ_DATA(rq)		((struct cfq_rq *) (rq)->elevator_private)
+
+static kmem_cache_t *crq_pool;
+static kmem_cache_t *cfq_pool;
+static mempool_t *cfq_mpool;
+
+struct cfq_data {
+	struct list_head rr_list;
+	struct list_head *dispatch;
+	struct list_head *cfq_hash;
+
+	struct list_head *crq_hash;
+
+	unsigned int busy_queues;
+	unsigned int max_queued;
+
+	mempool_t *crq_pool;
+};
+
+struct cfq_queue {
+	struct list_head cfq_hash;
+	struct list_head cfq_list;
+	struct rb_root sort_list;
+	int pid;
+	int queued[2];
+#if 0
+	/*
+	 * with a simple addition like this, we can do io priorities. almost.
+	 * does need a split request free list, too.
+	 */
+	int io_prio
+#endif
+};
+
+struct cfq_rq {
+	struct rb_node rb_node;
+	sector_t rb_key;
+
+	struct request *request;
+
+	struct cfq_queue *cfq_queue;
+
+	struct list_head hash;
+};
+
+static void cfq_put_queue(struct cfq_data *cfqd, struct cfq_queue *cfqq);
+static struct cfq_queue *cfq_find_cfq_hash(struct cfq_data *cfqd, int pid);
+static void cfq_dispatch_sort(struct list_head *head, struct cfq_rq *crq);
+
+/*
+ * lots of deadline iosched dupes, can be abstracted later...
+ */
+static inline void __cfq_del_crq_hash(struct cfq_rq *crq)
+{
+	list_del_init(&crq->hash);
+}
+
+static inline void cfq_del_crq_hash(struct cfq_rq *crq)
+{
+	if (ON_MHASH(crq))
+		__cfq_del_crq_hash(crq);
+}
+
+static void cfq_remove_merge_hints(request_queue_t *q, struct cfq_rq *crq)
+{
+	cfq_del_crq_hash(crq);
+
+	if (q->last_merge == crq->request)
+		q->last_merge = NULL;
+}
+
+static inline void cfq_add_crq_hash(struct cfq_data *cfqd, struct cfq_rq *crq)
+{
+	struct request *rq = crq->request;
+
+	BUG_ON(ON_MHASH(crq));
+
+	list_add(&crq->hash, &cfqd->crq_hash[CFQ_MHASH_FN(rq_hash_key(rq))]);
+}
+
+static struct request *cfq_find_rq_hash(struct cfq_data *cfqd, sector_t offset)
+{
+	struct list_head *hash_list = &cfqd->crq_hash[CFQ_MHASH_FN(offset)];
+	struct list_head *entry, *next = hash_list->next;
+
+	while ((entry = next) != hash_list) {
+		struct cfq_rq *crq = list_entry_hash(entry);
+		struct request *__rq = crq->request;
+
+		next = entry->next;
+
+		BUG_ON(!ON_MHASH(crq));
+
+		if (!rq_mergeable(__rq)) {
+			__cfq_del_crq_hash(crq);
+			continue;
+		}
+
+		if (rq_hash_key(__rq) == offset)
+			return __rq;
+	}
+
+	return NULL;
+}
+
+/*
+ * rb tree support functions
+ */
+#define RB_NONE		(2)
+#define RB_EMPTY(node)	((node)->rb_node == NULL)
+#define RB_CLEAR(node)	((node)->rb_color = RB_NONE)
+#define RB_CLEAR_ROOT(root)	((root)->rb_node = NULL)
+#define ON_RB(node)	((node)->rb_color != RB_NONE)
+#define rb_entry_crq(node)	rb_entry((node), struct cfq_rq, rb_node)
+#define rq_rb_key(rq)		(rq)->sector
+
+static inline void cfq_del_crq_rb(struct cfq_queue *cfqq, struct cfq_rq *crq)
+{
+	if (ON_RB(&crq->rb_node)) {
+		cfqq->queued[rq_data_dir(crq->request)]--;
+		rb_erase(&crq->rb_node, &cfqq->sort_list);
+		crq->cfq_queue = NULL;
+	}
+}
+
+static struct cfq_rq *
+__cfq_add_crq_rb(struct cfq_queue *cfqq, struct cfq_rq *crq)
+{
+	struct rb_node **p = &cfqq->sort_list.rb_node;
+	struct rb_node *parent = NULL;
+	struct cfq_rq *__crq;
+
+	while (*p) {
+		parent = *p;
+		__crq = rb_entry_crq(parent);
+
+		if (crq->rb_key < __crq->rb_key)
+			p = &(*p)->rb_left;
+		else if (crq->rb_key > __crq->rb_key)
+			p = &(*p)->rb_right;
+		else
+			return __crq;
+	}
+
+	rb_link_node(&crq->rb_node, parent, p);
+	return 0;
+}
+
+static void
+cfq_add_crq_rb(struct cfq_data *cfqd, struct cfq_queue *cfqq,struct cfq_rq *crq)
+{
+	struct request *rq = crq->request;
+	struct cfq_rq *__alias;
+
+	crq->rb_key = rq_rb_key(rq);
+	cfqq->queued[rq_data_dir(rq)]++;
+retry:
+	__alias = __cfq_add_crq_rb(cfqq, crq);
+	if (!__alias) {
+		rb_insert_color(&crq->rb_node, &cfqq->sort_list);
+		crq->cfq_queue = cfqq;
+		return;
+	}
+
+	cfq_del_crq_rb(cfqq, __alias);
+	cfq_dispatch_sort(cfqd->dispatch, __alias);
+	goto retry;
+}
+
+static struct request *
+cfq_find_rq_rb(struct cfq_data *cfqd, sector_t sector)
+{
+	struct cfq_queue *cfqq = cfq_find_cfq_hash(cfqd, current->tgid);
+	struct rb_node *n;
+
+	if (!cfqq)
+		goto out;
+
+	n = cfqq->sort_list.rb_node;
+	while (n) {
+		struct cfq_rq *crq = rb_entry_crq(n);
+
+		if (sector < crq->rb_key)
+			n = n->rb_left;
+		else if (sector > crq->rb_key)
+			n = n->rb_right;
+		else
+			return crq->request;
+	}
+
+out:
+	return NULL;
+}
+
+static void cfq_remove_request(request_queue_t *q, struct request *rq)
+{
+	struct cfq_data *cfqd = q->elevator.elevator_data;
+	struct cfq_rq *crq = RQ_DATA(rq);
+
+	if (crq) {
+		struct cfq_queue *cfqq = crq->cfq_queue;
+
+		cfq_remove_merge_hints(q, crq);
+		list_del_init(&rq->queuelist);
+
+		if (cfqq) {
+			cfq_del_crq_rb(cfqq, crq);
+
+			if (RB_EMPTY(&cfqq->sort_list))
+				cfq_put_queue(cfqd, cfqq);
+		}
+	}
+}
+
+static int
+cfq_merge(request_queue_t *q, struct request **req, struct bio *bio)
+{
+	struct cfq_data *cfqd = q->elevator.elevator_data;
+	struct request *__rq;
+	int ret;
+
+	ret = elv_try_last_merge(q, bio);
+	if (ret != ELEVATOR_NO_MERGE) {
+		__rq = q->last_merge;
+		goto out_insert;
+	}
+
+	__rq = cfq_find_rq_hash(cfqd, bio->bi_sector);
+	if (__rq) {
+		BUG_ON(__rq->sector + __rq->nr_sectors != bio->bi_sector);
+
+		if (elv_rq_merge_ok(__rq, bio)) {
+			ret = ELEVATOR_BACK_MERGE;
+			goto out;
+		}
+	}
+
+	__rq = cfq_find_rq_rb(cfqd, bio->bi_sector + bio_sectors(bio));
+	if (__rq) {
+		if (elv_rq_merge_ok(__rq, bio)) {
+			ret = ELEVATOR_FRONT_MERGE;
+			goto out;
+		}
+	}
+
+	return ELEVATOR_NO_MERGE;
+out:
+	q->last_merge = __rq;
+out_insert:
+	*req = __rq;
+	return ret;
+}
+
+static void cfq_merged_request(request_queue_t *q, struct request *req)
+{
+	struct cfq_data *cfqd = q->elevator.elevator_data;
+	struct cfq_rq *crq = RQ_DATA(req);
+
+	cfq_del_crq_hash(crq);
+	cfq_add_crq_hash(cfqd, crq);
+
+	if (ON_RB(&crq->rb_node) && (rq_rb_key(req) != crq->rb_key)) {
+		struct cfq_queue *cfqq = crq->cfq_queue;
+
+		cfq_del_crq_rb(cfqq, crq);
+		cfq_add_crq_rb(cfqd, cfqq, crq);
+	}
+
+	q->last_merge = req;
+}
+
+static void
+cfq_merged_requests(request_queue_t *q, struct request *req,
+		    struct request *next)
+{
+	cfq_merged_request(q, req);
+	cfq_remove_request(q, next);
+}
+
+static void cfq_dispatch_sort(struct list_head *head, struct cfq_rq *crq)
+{
+	struct list_head *entry = head;
+	struct request *__rq;
+
+	if (!list_empty(head)) {
+		__rq = list_entry_rq(head->next);
+
+		if (crq->request->sector < __rq->sector) {
+			entry = head->prev;
+			goto link;
+		}
+	}
+
+	while ((entry = entry->prev) != head) {
+		__rq = list_entry_rq(entry);
+
+		if (crq->request->sector <= __rq->sector)
+			break;
+	}
+
+link:
+	list_add_tail(&crq->request->queuelist, entry);
+}
+
+static inline void
+__cfq_dispatch_requests(request_queue_t *q, struct cfq_data *cfqd,
+			struct cfq_queue *cfqq)
+{
+	struct cfq_rq *crq = rb_entry_crq(rb_first(&cfqq->sort_list));
+
+	cfq_del_crq_rb(cfqq, crq);
+	cfq_remove_merge_hints(q, crq);
+	cfq_dispatch_sort(cfqd->dispatch, crq);
+}
+
+static int cfq_dispatch_requests(request_queue_t *q, struct cfq_data *cfqd)
+{
+	struct cfq_queue *cfqq;
+	struct list_head *entry, *tmp;
+	int ret, queued, good_queues;
+
+	if (list_empty(&cfqd->rr_list))
+		return 0;
+
+	queued = ret = 0;
+restart:
+	good_queues = 0;
+	list_for_each_safe(entry, tmp, &cfqd->rr_list) {
+		cfqq = list_entry_cfqq(cfqd->rr_list.next);
+
+		BUG_ON(RB_EMPTY(&cfqq->sort_list));
+
+		__cfq_dispatch_requests(q, cfqd, cfqq);
+
+		if (RB_EMPTY(&cfqq->sort_list))
+			cfq_put_queue(cfqd, cfqq);
+		else
+			good_queues++;
+
+		queued++;
+		ret = 1;
+	}
+
+	if ((queued < cfq_quantum) && good_queues)
+		goto restart;
+
+	return ret;
+}
+
+static struct request *cfq_next_request(request_queue_t *q)
+{
+	struct cfq_data *cfqd = q->elevator.elevator_data;
+	struct request *rq;
+
+	if (!list_empty(cfqd->dispatch)) {
+		struct cfq_rq *crq;
+dispatch:
+		rq = list_entry_rq(cfqd->dispatch->next);
+
+		BUG_ON(q->last_merge == rq);
+		crq = RQ_DATA(rq);
+		if (crq)
+			BUG_ON(ON_MHASH(crq));
+
+		return rq;
+	}
+
+	if (cfq_dispatch_requests(q, cfqd))
+		goto dispatch;
+
+	return NULL;
+}
+
+static inline struct cfq_queue *
+__cfq_find_cfq_hash(struct cfq_data *cfqd, int pid, const int hashval)
+{
+	struct list_head *hash_list = &cfqd->cfq_hash[hashval];
+	struct list_head *entry;
+
+	list_for_each(entry, hash_list) {
+		struct cfq_queue *__cfqq = list_entry_qhash(entry);
+
+		if (__cfqq->pid == pid)
+			return __cfqq;
+	}
+
+	return NULL;
+}
+
+static struct cfq_queue *cfq_find_cfq_hash(struct cfq_data *cfqd, int pid)
+{
+	const int hashval = hash_long(current->tgid, CFQ_QHASH_SHIFT);
+
+	return __cfq_find_cfq_hash(cfqd, pid, hashval);
+}
+
+static void cfq_put_queue(struct cfq_data *cfqd, struct cfq_queue *cfqq)
+{
+	cfqd->busy_queues--;
+	list_del(&cfqq->cfq_list);
+	list_del(&cfqq->cfq_hash);
+	mempool_free(cfqq, cfq_mpool);
+}
+
+static struct cfq_queue *cfq_get_queue(struct cfq_data *cfqd, int pid)
+{
+	const int hashval = hash_long(current->tgid, CFQ_QHASH_SHIFT);
+	struct cfq_queue *cfqq = __cfq_find_cfq_hash(cfqd, pid, hashval);
+
+	if (!cfqq) {
+		cfqq = mempool_alloc(cfq_mpool, GFP_NOIO);
+
+		INIT_LIST_HEAD(&cfqq->cfq_hash);
+		INIT_LIST_HEAD(&cfqq->cfq_list);
+		RB_CLEAR_ROOT(&cfqq->sort_list);
+
+		cfqq->pid = pid;
+		cfqq->queued[0] = cfqq->queued[1] = 0;
+		list_add(&cfqq->cfq_hash, &cfqd->cfq_hash[hashval]);
+	}
+
+	return cfqq;
+}
+
+static void cfq_enqueue(struct cfq_data *cfqd, struct cfq_rq *crq)
+{
+	struct cfq_queue *cfqq;
+
+	cfqq = cfq_get_queue(cfqd, current->tgid);
+
+	cfq_add_crq_rb(cfqd, cfqq, crq);
+
+	if (list_empty(&cfqq->cfq_list)) {
+		list_add(&cfqq->cfq_list, &cfqd->rr_list);
+		cfqd->busy_queues++;
+	}
+}
+
+static void
+cfq_insert_request(request_queue_t *q, struct request *rq, int where)
+{
+	struct cfq_data *cfqd = q->elevator.elevator_data;
+	struct cfq_rq *crq = RQ_DATA(rq);
+
+	switch (where) {
+		case ELEVATOR_INSERT_BACK:
+			while (cfq_dispatch_requests(q, cfqd))
+				;
+			list_add_tail(&rq->queuelist, cfqd->dispatch);
+			break;
+		case ELEVATOR_INSERT_FRONT:
+			list_add(&rq->queuelist, cfqd->dispatch);
+			break;
+		case ELEVATOR_INSERT_SORT:
+			BUG_ON(!blk_fs_request(rq));
+			cfq_enqueue(cfqd, crq);
+			break;
+		default:
+			printk("%s: bad insert point %d\n", __FUNCTION__,where);
+			return;
+	}
+
+	if (rq_mergeable(rq)) {
+		cfq_add_crq_hash(cfqd, crq);
+
+		if (!q->last_merge)
+			q->last_merge = rq;
+	}
+}
+
+static int cfq_queue_empty(request_queue_t *q)
+{
+	struct cfq_data *cfqd = q->elevator.elevator_data;
+
+	if (list_empty(cfqd->dispatch) && list_empty(&cfqd->rr_list))
+		return 1;
+
+	return 0;
+}
+
+static struct request *
+cfq_former_request(request_queue_t *q, struct request *rq)
+{
+	struct cfq_rq *crq = RQ_DATA(rq);
+	struct rb_node *rbprev = rb_prev(&crq->rb_node);
+
+	if (rbprev)
+		return rb_entry_crq(rbprev)->request;
+
+	return NULL;
+}
+
+static struct request *
+cfq_latter_request(request_queue_t *q, struct request *rq)
+{
+	struct cfq_rq *crq = RQ_DATA(rq);
+	struct rb_node *rbnext = rb_next(&crq->rb_node);
+
+	if (rbnext)
+		return rb_entry_crq(rbnext)->request;
+
+	return NULL;
+}
+
+static int cfq_may_queue(request_queue_t *q, int rw)
+{
+	struct cfq_data *cfqd = q->elevator.elevator_data;
+	struct cfq_queue *cfqq;
+	int ret = 1;
+
+	if (!cfqd->busy_queues)
+		goto out;
+
+	cfqq = cfq_find_cfq_hash(cfqd, current->tgid);
+	if (cfqq) {
+		int limit = (q->nr_requests - cfq_queued) / cfqd->busy_queues;
+
+		if (limit < 3)
+			limit = 3;
+		else if (limit > cfqd->max_queued)
+			limit = cfqd->max_queued;
+
+		if (cfqq->queued[rw] > limit)
+			ret = 0;
+	}
+out:
+	return ret;
+}
+
+static void cfq_put_request(request_queue_t *q, struct request *rq)
+{
+	struct cfq_data *cfqd = q->elevator.elevator_data;
+	struct cfq_rq *crq = RQ_DATA(rq);
+
+	if (crq) {
+		BUG_ON(q->last_merge == rq);
+		BUG_ON(ON_MHASH(crq));
+
+		mempool_free(crq, cfqd->crq_pool);
+		rq->elevator_private = NULL;
+	}
+}
+
+static int cfq_set_request(request_queue_t *q, struct request *rq, int gfp_mask)
+{
+	struct cfq_data *cfqd = q->elevator.elevator_data;
+	struct cfq_rq *crq = mempool_alloc(cfqd->crq_pool, gfp_mask);
+
+	if (crq) {
+		RB_CLEAR(&crq->rb_node);
+		crq->request = rq;
+		crq->cfq_queue = NULL;
+		INIT_LIST_HEAD(&crq->hash);
+		rq->elevator_private = crq;
+		return 0;
+	}
+
+	return 1;
+}
+
+static void cfq_exit(request_queue_t *q, elevator_t *e)
+{
+	struct cfq_data *cfqd = e->elevator_data;
+
+	e->elevator_data = NULL;
+	mempool_destroy(cfqd->crq_pool);
+	kfree(cfqd->crq_hash);
+	kfree(cfqd->cfq_hash);
+	kfree(cfqd);
+}
+
+static int cfq_init(request_queue_t *q, elevator_t *e)
+{
+	struct cfq_data *cfqd;
+	int i;
+
+	cfqd = kmalloc(sizeof(*cfqd), GFP_KERNEL);
+	if (!cfqd)
+		return -ENOMEM;
+
+	memset(cfqd, 0, sizeof(*cfqd));
+	INIT_LIST_HEAD(&cfqd->rr_list);
+
+	cfqd->crq_hash = kmalloc(sizeof(struct list_head) * CFQ_MHASH_ENTRIES, GFP_KERNEL);
+	if (!cfqd->crq_hash)
+		goto out_crqhash;
+
+	cfqd->cfq_hash = kmalloc(sizeof(struct list_head) * CFQ_QHASH_ENTRIES, GFP_KERNEL);
+	if (!cfqd->cfq_hash)
+		goto out_cfqhash;
+
+	cfqd->crq_pool = mempool_create(BLKDEV_MIN_RQ, mempool_alloc_slab, mempool_free_slab, crq_pool);
+	if (!cfqd->crq_pool)
+		goto out_crqpool;
+
+	for (i = 0; i < CFQ_MHASH_ENTRIES; i++)
+		INIT_LIST_HEAD(&cfqd->crq_hash[i]);
+	for (i = 0; i < CFQ_QHASH_ENTRIES; i++)
+		INIT_LIST_HEAD(&cfqd->cfq_hash[i]);
+
+	cfqd->dispatch = &q->queue_head;
+	e->elevator_data = cfqd;
+
+	/*
+	 * just set it to some high value, we want anyone to be able to queue
+	 * some requests. fairness is handled differently
+	 */
+	cfqd->max_queued = q->nr_requests;
+	q->nr_requests = 8192;
+
+	return 0;
+out_crqpool:
+	kfree(cfqd->cfq_hash);
+out_cfqhash:
+	kfree(cfqd->crq_hash);
+out_crqhash:
+	kfree(cfqd);
+	return -ENOMEM;
+}
+
+static int __init cfq_slab_setup(void)
+{
+	crq_pool = kmem_cache_create("crq_pool", sizeof(struct cfq_rq), 0, 0,
+					NULL, NULL);
+
+	if (!crq_pool)
+		panic("cfq_iosched: can't init crq pool\n");
+
+	cfq_pool = kmem_cache_create("cfq_pool", sizeof(struct cfq_queue), 0, 0,
+					NULL, NULL);
+
+	if (!cfq_pool)
+		panic("cfq_iosched: can't init cfq pool\n");
+
+	cfq_mpool = mempool_create(64, mempool_alloc_slab, mempool_free_slab, cfq_pool);
+
+	if (!cfq_mpool)
+		panic("cfq_iosched: can't init cfq mpool\n");
+
+	return 0;
+}
+
+subsys_initcall(cfq_slab_setup);
+
+elevator_t iosched_cfq = {
+	.elevator_name =		"cfq",
+	.elevator_merge_fn = 		cfq_merge,
+	.elevator_merged_fn =		cfq_merged_request,
+	.elevator_merge_req_fn =	cfq_merged_requests,
+	.elevator_next_req_fn =		cfq_next_request,
+	.elevator_add_req_fn =		cfq_insert_request,
+	.elevator_remove_req_fn =	cfq_remove_request,
+	.elevator_queue_empty_fn =	cfq_queue_empty,
+	.elevator_former_req_fn =	cfq_former_request,
+	.elevator_latter_req_fn =	cfq_latter_request,
+	.elevator_set_req_fn =		cfq_set_request,
+	.elevator_put_req_fn =		cfq_put_request,
+	.elevator_may_queue_fn =	cfq_may_queue,
+	.elevator_init_fn =		cfq_init,
+	.elevator_exit_fn =		cfq_exit,
+};
+
+EXPORT_SYMBOL(iosched_cfq);
--- diff/drivers/char/agp/efficeon-agp.c	1970-01-01 01:00:00.000000000 +0100
+++ source/drivers/char/agp/efficeon-agp.c	2004-02-23 13:56:40.000000000 +0000
@@ -0,0 +1,467 @@
+/*
+ * Transmeta's Efficeon AGPGART driver.
+ * 
+ * Based upon a diff by Linus around November '02.
+ *
+ * Ported to the 2.6 kernel by Carlos Puchol <cpglinux@puchol.com>
+ * and H. Peter Anvin <hpa@transmeta.com>.
+ */
+
+/*
+ * NOTE-cpg-040217:
+ * 
+ *   - when compiled as a module, after loading the module,
+ *     it will refuse to unload, indicating it is in use,
+ *     when it is not.
+ *   - no s3 (suspend to ram) testing.
+ *   - tested on the efficeon integrated nothbridge for tens
+ *     of iterations of starting x and glxgears.
+ *   - tested with radeon 9000 and radeon mobility m9 cards
+ *   - tested with c3/c4 enabled (with the mobility m9 card)
+ */
+
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/agp_backend.h>
+#include <linux/gfp.h>
+#include <linux/page-flags.h>
+#include <linux/mm.h>
+#include "agp.h"
+
+/*
+ * The real differences to the generic AGP code is
+ * in the GART mappings - a two-level setup with the
+ * first level being an on-chip 64-entry table.
+ *
+ * The page array is filled through the ATTPAGE register
+ * (Aperture Translation Table Page Register) at 0xB8. Bits:
+ *  31:20: physical page address
+ *   11:9: Page Attribute Table Index (PATI)
+ *	   must match the PAT index for the
+ *	   mapped pages (the 2nd level page table pages
+ *	   themselves should be just regular WB-cacheable,
+ *	   so this is normally zero.)
+ *      8: Present
+ *    7:6: reserved, write as zero
+ *    5:0: GATT directory index: which 1st-level entry
+ * 
+ * The Efficeon AGP spec requires pages to be WB-cacheable
+ * but to be explicitly CLFLUSH'd after any changes.
+ */
+#define EFFICEON_ATTPAGE	0xb8
+#define EFFICEON_L1_SIZE	64	/* Number of PDE pages */
+
+#define EFFICEON_PATI		(0 << 9)
+#define EFFICEON_PRESENT	(1 << 8)
+
+static struct _efficeon_private {
+	unsigned long l1_table[EFFICEON_L1_SIZE];
+} efficeon_private;
+
+static struct gatt_mask efficeon_generic_masks[] =
+{
+	{.mask = 0x00000001, .type = 0}
+};
+
+static struct aper_size_info_lvl2 efficeon_generic_sizes[4] =
+{
+	{256, 65536, 0},
+	{128, 32768, 32},
+	{64, 16384, 48},
+	{32, 8192, 56}
+};
+
+/*
+ * Control interfaces are largely identical to
+ * the legacy Intel 440BX..
+ */
+
+static int efficeon_fetch_size(void)
+{
+	int i;
+	u16 temp;
+	struct aper_size_info_lvl2 *values;
+
+	pci_read_config_word(agp_bridge->dev, INTEL_APSIZE, &temp);
+	values = A_SIZE_LVL2(agp_bridge->driver->aperture_sizes);
+
+	for (i = 0; i < agp_bridge->driver->num_aperture_sizes; i++) {
+		if (temp == values[i].size_value) {
+			agp_bridge->previous_size =
+			    agp_bridge->current_size = (void *) (values + i);
+			agp_bridge->aperture_size_idx = i;
+			return values[i].size;
+		}
+	}
+
+	return 0;
+}
+
+static void efficeon_tlbflush(struct agp_memory * mem)
+{
+	printk(KERN_DEBUG PFX "efficeon_tlbflush()\n");
+	pci_write_config_dword(agp_bridge->dev, INTEL_AGPCTRL, 0x2200);
+	pci_write_config_dword(agp_bridge->dev, INTEL_AGPCTRL, 0x2280);
+}
+
+static void efficeon_cleanup(void)
+{
+	u16 temp;
+	struct aper_size_info_lvl2 *previous_size;
+
+	printk(KERN_DEBUG PFX "efficeon_cleanup()\n");
+	previous_size = A_SIZE_LVL2(agp_bridge->previous_size);
+	pci_read_config_word(agp_bridge->dev, INTEL_NBXCFG, &temp);
+	pci_write_config_word(agp_bridge->dev, INTEL_NBXCFG, temp & ~(1 << 9));
+	pci_write_config_word(agp_bridge->dev, INTEL_APSIZE,
+			      previous_size->size_value);
+}
+
+static int efficeon_configure(void)
+{
+	u32 temp;
+	u16 temp2;
+	struct aper_size_info_lvl2 *current_size;
+
+	printk(KERN_DEBUG PFX "efficeon_configure()\n");
+	
+	current_size = A_SIZE_LVL2(agp_bridge->current_size);
+
+	/* aperture size */
+	pci_write_config_word(agp_bridge->dev, INTEL_APSIZE,
+			      current_size->size_value);
+
+	/* address to map to */
+	pci_read_config_dword(agp_bridge->dev, AGP_APBASE, &temp);
+	agp_bridge->gart_bus_addr = (temp & PCI_BASE_ADDRESS_MEM_MASK);
+
+	/* agpctrl */
+	pci_write_config_dword(agp_bridge->dev, INTEL_AGPCTRL, 0x2280);
+
+	/* paccfg/nbxcfg */
+	pci_read_config_word(agp_bridge->dev, INTEL_NBXCFG, &temp2);
+	pci_write_config_word(agp_bridge->dev, INTEL_NBXCFG,
+			      (temp2 & ~(1 << 10)) | (1 << 9) | (1 << 11));
+	/* clear any possible error conditions */
+	pci_write_config_byte(agp_bridge->dev, INTEL_ERRSTS + 1, 7);
+	return 0;
+}
+
+static int efficeon_free_gatt_table(void)
+{
+	int index, freed = 0;
+
+	for (index = 0; index < EFFICEON_L1_SIZE; index++) {
+		unsigned long page = efficeon_private.l1_table[index];
+		if (page) {
+			efficeon_private.l1_table[index] = 0;
+			ClearPageReserved(virt_to_page((char *)page));
+			free_page(page);
+			freed++;
+		}
+		printk(KERN_DEBUG PFX "efficeon_free_gatt_table(%p, %02x, %08x)\n",
+			agp_bridge->dev, EFFICEON_ATTPAGE, index);
+		pci_write_config_dword(agp_bridge->dev,
+			EFFICEON_ATTPAGE, index);
+	}
+	printk(KERN_DEBUG PFX "efficeon_free_gatt_table() freed %d pages\n", freed);
+	return 0;
+}
+
+
+/*
+ * Since we don't need contigious memory we just try
+ * to get the gatt table once
+ */
+
+#define GET_PAGE_DIR_OFF(addr) (addr >> 22)
+#define GET_PAGE_DIR_IDX(addr) (GET_PAGE_DIR_OFF(addr) - \
+	GET_PAGE_DIR_OFF(agp_bridge->gart_bus_addr))
+#define GET_GATT_OFF(addr) ((addr & 0x003ff000) >> 12)
+#undef  GET_GATT
+#define GET_GATT(addr) (efficeon_private.gatt_pages[\
+	GET_PAGE_DIR_IDX(addr)]->remapped)
+
+static int efficeon_create_gatt_table(void)
+{
+	int index;
+	const int pati    = EFFICEON_PATI;
+	const int present = EFFICEON_PRESENT;
+	const int clflush_chunk = ((cpuid_ebx(1) >> 8) & 0xff) << 3;
+	int num_entries, l1_pages;
+	
+	num_entries = A_SIZE_LVL2(agp_bridge->current_size)->num_entries;
+
+	printk(KERN_DEBUG PFX "efficeon_create_gatt_table(%d)\n", num_entries);
+
+	/* There are 2^10 PTE pages per PDE page */
+	BUG_ON(num_entries & 0x3ff);
+	l1_pages = num_entries >> 10;
+
+	for (index = 0 ; index < l1_pages ; index++) {
+		int offset;
+		unsigned long page;
+		unsigned long value;
+
+		page = efficeon_private.l1_table[index];
+		BUG_ON(page);
+
+		page = get_zeroed_page(GFP_KERNEL);
+		if (!page) {
+			efficeon_free_gatt_table();
+			return -ENOMEM;
+		}
+		SetPageReserved(virt_to_page((char *)page));
+
+		for (offset = 0; offset < PAGE_SIZE; offset += clflush_chunk)
+			asm volatile("clflush %0" : : "m" (*(char *)(page+offset)));
+
+		efficeon_private.l1_table[index] = page;
+
+		value = __pa(page) | pati | present | index;
+
+		pci_write_config_dword(agp_bridge->dev,
+			EFFICEON_ATTPAGE, value);
+	}
+
+	return 0;
+}
+
+static int efficeon_insert_memory(struct agp_memory * mem, off_t pg_start, int type)
+{
+	int i, count = mem->page_count, num_entries;
+	unsigned int *page, *last_page;
+	const int clflush_chunk = ((cpuid_ebx(1) >> 8) & 0xff) << 3;
+	const unsigned long clflush_mask = ~(clflush_chunk-1);
+
+	printk(KERN_DEBUG PFX "efficeon_insert_memory(%lx, %d)\n", pg_start, count);
+
+	num_entries = A_SIZE_LVL2(agp_bridge->current_size)->num_entries;
+	if ((pg_start + mem->page_count) > num_entries)
+		return -EINVAL;
+	if (type != 0 || mem->type != 0)
+		return -EINVAL;
+
+	if (mem->is_flushed == FALSE) {
+		global_cache_flush();
+		mem->is_flushed = TRUE;
+	}
+
+	last_page = NULL;
+	for (i = 0; i < count; i++) {
+		int index = pg_start + i;
+		unsigned long insert = mem->memory[i];
+
+		page = (unsigned int *) efficeon_private.l1_table[index >> 10];
+
+		if (!page)
+			continue;
+		
+		page += (index & 0x3ff);
+		*page = insert;
+
+		/* clflush is slow, so don't clflush until we have to */
+		if ( last_page && 
+		     ((unsigned long)page^(unsigned long)last_page) & clflush_mask )
+		    asm volatile("clflush %0" : : "m" (*last_page));
+
+		last_page = page;
+	}
+
+	if ( last_page )
+		asm volatile("clflush %0" : : "m" (*last_page));
+
+	agp_bridge->driver->tlb_flush(mem);
+	return 0;
+}
+
+static int efficeon_remove_memory(struct agp_memory * mem, off_t pg_start, int type)
+{
+	int i, count = mem->page_count, num_entries;
+
+	printk(KERN_DEBUG PFX "efficeon_remove_memory(%lx, %d)\n", pg_start, count);
+
+	num_entries = A_SIZE_LVL2(agp_bridge->current_size)->num_entries;
+
+	if ((pg_start + mem->page_count) > num_entries)
+		return -EINVAL;
+	if (type != 0 || mem->type != 0)
+		return -EINVAL;
+
+	for (i = 0; i < count; i++) {
+		int index = pg_start + i;
+		unsigned int *page = (unsigned int *) efficeon_private.l1_table[index >> 10];
+
+		if (!page)
+			continue;
+		page += (index & 0x3ff);
+		*page = 0;
+	}
+	agp_bridge->driver->tlb_flush(mem);
+	return 0;
+}
+
+/* GATT entry: (physical address | 1) */
+static unsigned long efficeon_mask_memory(unsigned long addr, int type)
+{
+	/* Memory type is ignored */
+
+	return addr | agp_bridge->driver->masks[0].mask;
+}
+
+struct agp_bridge_driver efficeon_driver = {
+	.owner			= THIS_MODULE,
+	.aperture_sizes		= efficeon_generic_sizes,
+	.size_type		= LVL2_APER_SIZE,
+	.num_aperture_sizes	= 4,
+	.configure		= efficeon_configure,
+	.fetch_size		= efficeon_fetch_size,
+	.cleanup		= efficeon_cleanup,
+	.tlb_flush		= efficeon_tlbflush,
+	.mask_memory		= efficeon_mask_memory,
+	.masks			= efficeon_generic_masks,
+	.agp_enable		= agp_generic_enable,
+	.cache_flush		= global_cache_flush,
+
+	// Efficeon-specific GATT table setup / populate / teardown
+	.create_gatt_table	= efficeon_create_gatt_table,
+	.free_gatt_table	= efficeon_free_gatt_table,
+	.insert_memory		= efficeon_insert_memory,
+	.remove_memory		= efficeon_remove_memory,
+	.cant_use_aperture	= 0,	// 1 might be faster?
+
+	// Generic
+	.alloc_by_type		= agp_generic_alloc_by_type,
+	.free_by_type		= agp_generic_free_by_type,
+	.agp_alloc_page		= agp_generic_alloc_page,
+	.agp_destroy_page	= agp_generic_destroy_page,
+};
+
+
+static int agp_efficeon_resume(struct pci_dev *pdev)
+{
+	printk(KERN_DEBUG PFX "agp_efficeon_resume()\n");
+	return efficeon_configure();
+}
+
+static int __devinit agp_efficeon_probe(struct pci_dev *pdev,
+				     const struct pci_device_id *ent)
+{
+	struct agp_bridge_data *bridge;
+	u8 cap_ptr;
+	struct resource *r;
+
+	cap_ptr = pci_find_capability(pdev, PCI_CAP_ID_AGP);
+	if (!cap_ptr)
+		return -ENODEV;
+
+	/* Probe for Efficeon controller */
+	if (pdev->device != PCI_DEVICE_ID_EFFICEON) {
+		printk(KERN_ERR PFX "Unsupported Efficeon chipset (device id: %04x)\n",
+		    pdev->device);
+		return -ENODEV;
+	}
+
+	printk(KERN_INFO PFX "Detected Transmeta Efficeon TM8000 series chipset\n");
+
+	bridge = agp_alloc_bridge();
+	if (!bridge)
+		return -ENOMEM;
+
+	bridge->driver = &efficeon_driver;
+	bridge->dev = pdev;
+	bridge->capndx = cap_ptr;
+
+	/*
+	* The following fixes the case where the BIOS has "forgotten" to
+	* provide an address range for the GART.
+	* 20030610 - hamish@zot.org
+	*/
+	r = &pdev->resource[0];
+	if (!r->start && r->end) {
+		if(pci_assign_resource(pdev, 0)) {
+			printk(KERN_ERR PFX "could not assign resource 0\n");
+			return (-ENODEV);
+		}
+	}
+
+	/*
+	* If the device has not been properly setup, the following will catch
+	* the problem and should stop the system from crashing.
+	* 20030610 - hamish@zot.org
+	*/
+	if (pci_enable_device(pdev)) {
+		printk(KERN_ERR PFX "Unable to Enable PCI device\n");
+		return (-ENODEV);
+	}
+
+	/* Fill in the mode register */
+	if (cap_ptr) {
+		pci_read_config_dword(pdev,
+				bridge->capndx+PCI_AGP_STATUS,
+				&bridge->mode);
+	}
+
+	pci_set_drvdata(pdev, bridge);
+	return agp_add_bridge(bridge);
+}
+
+static void __devexit agp_efficeon_remove(struct pci_dev *pdev)
+{
+	struct agp_bridge_data *bridge = pci_get_drvdata(pdev);
+
+	agp_remove_bridge(bridge);
+	agp_put_bridge(bridge);
+}
+
+static int agp_efficeon_suspend(struct pci_dev *dev, u32 state)
+{
+	return 0;
+}
+
+
+static struct pci_device_id agp_efficeon_pci_table[] = {
+	{
+	.class		= (PCI_CLASS_BRIDGE_HOST << 8),
+	.class_mask	= ~0,
+	.vendor		= PCI_VENDOR_ID_TRANSMETA,
+	.device		= PCI_ANY_ID,
+	.subvendor	= PCI_ANY_ID,
+	.subdevice	= PCI_ANY_ID,
+	},
+	{ }
+};
+
+MODULE_DEVICE_TABLE(pci, agp_efficeon_pci_table);
+
+static struct pci_driver agp_efficeon_pci_driver = {
+	.name		= "agpgart-efficeon",
+	.id_table	= agp_efficeon_pci_table,
+	.probe		= agp_efficeon_probe,
+	.remove		= agp_efficeon_remove,
+	.suspend	= agp_efficeon_suspend,
+	.resume		= agp_efficeon_resume,
+};
+
+static int __init agp_efficeon_init(void)
+{
+	static int agp_initialised=0;
+
+	if (agp_initialised == 1)
+		return 0;
+	agp_initialised=1;
+
+	return pci_module_init(&agp_efficeon_pci_driver);
+}
+
+static void __exit agp_efficeon_cleanup(void)
+{
+	pci_unregister_driver(&agp_efficeon_pci_driver);
+}
+
+module_init(agp_efficeon_init);
+module_exit(agp_efficeon_cleanup);
+
+MODULE_AUTHOR("Carlos Puchol <cpglinux@puchol.com>");
+MODULE_LICENSE("GPL and additional rights");
--- diff/drivers/char/drm/drm_irq.h	1970-01-01 01:00:00.000000000 +0100
+++ source/drivers/char/drm/drm_irq.h	2004-02-23 13:56:40.000000000 +0000
@@ -0,0 +1,377 @@
+/**
+ * \file drm_irq.h 
+ * IRQ support
+ *
+ * \author Rickard E. (Rik) Faith <faith@valinux.com>
+ * \author Gareth Hughes <gareth@valinux.com>
+ */
+
+/*
+ * Created: Fri Mar 19 14:30:16 1999 by faith@valinux.com
+ *
+ * Copyright 1999, 2000 Precision Insight, Inc., Cedar Park, Texas.
+ * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include "drmP.h"
+
+#include <linux/interrupt.h>	/* For task queue support */
+
+#ifndef __HAVE_SHARED_IRQ
+#define __HAVE_SHARED_IRQ	0
+#endif
+
+#if __HAVE_SHARED_IRQ
+#define DRM_IRQ_TYPE		SA_SHIRQ
+#else
+#define DRM_IRQ_TYPE		0
+#endif
+
+/**
+ * Get interrupt from bus id.
+ * 
+ * \param inode device inode.
+ * \param filp file pointer.
+ * \param cmd command.
+ * \param arg user argument, pointing to a drm_irq_busid structure.
+ * \return zero on success or a negative number on failure.
+ * 
+ * Finds the PCI device with the specified bus id and gets its IRQ number.
+ * This IOCTL is deprecated, and will now return EINVAL for any busid not equal
+ * to that of the device that this DRM instance attached to.
+ */
+int DRM(irq_by_busid)(struct inode *inode, struct file *filp,
+		   unsigned int cmd, unsigned long arg)
+{
+	drm_file_t *priv = filp->private_data;
+	drm_device_t *dev = priv->dev;
+	drm_irq_busid_t p;
+
+	if (copy_from_user(&p, (drm_irq_busid_t *)arg, sizeof(p)))
+		return -EFAULT;
+
+	if ((p.busnum >> 8) != dev->pci_domain ||
+	    (p.busnum & 0xff) != dev->pci_bus ||
+	    p.devnum != dev->pci_slot ||
+	    p.funcnum != dev->pci_func)
+		return -EINVAL;
+
+	p.irq = dev->irq;
+
+	DRM_DEBUG("%d:%d:%d => IRQ %d\n",
+		  p.busnum, p.devnum, p.funcnum, p.irq);
+	if (copy_to_user((drm_irq_busid_t *)arg, &p, sizeof(p)))
+		return -EFAULT;
+	return 0;
+}
+
+#if __HAVE_IRQ
+
+/**
+ * Install IRQ handler.
+ *
+ * \param dev DRM device.
+ * \param irq IRQ number.
+ *
+ * Initializes the IRQ related data, and setups drm_device::vbl_queue. Installs the handler, calling the driver
+ * \c DRM(driver_irq_preinstall)() and \c DRM(driver_irq_postinstall)() functions
+ * before and after the installation.
+ */
+int DRM(irq_install)( drm_device_t *dev )
+{
+	int ret;
+ 
+	if ( dev->irq == 0 )
+		return -EINVAL;
+
+	down( &dev->struct_sem );
+
+	/* Driver must have been initialized */
+	if ( !dev->dev_private ) {
+		up( &dev->struct_sem );
+		return -EINVAL;
+	}
+
+	if ( dev->irq_enabled ) {
+		up( &dev->struct_sem );
+		return -EBUSY;
+	}
+	dev->irq_enabled = 1;
+	up( &dev->struct_sem );
+
+	DRM_DEBUG( "%s: irq=%d\n", __FUNCTION__, dev->irq );
+
+#if 0 /* this is already done in DRM(setup) - why do it here ?? */
+	dev->context_flag = 0;
+	dev->interrupt_flag = 0;
+	dev->dma_flag = 0;
+#endif
+
+#if __HAVE_DMA
+	dev->dma->next_buffer = NULL;
+	dev->dma->next_queue = NULL;
+	dev->dma->this_buffer = NULL;
+#endif
+
+#if __HAVE_IRQ_BH
+	INIT_WORK(&dev->work, DRM(irq_immediate_bh), dev);
+#endif
+
+#if __HAVE_VBL_IRQ
+	init_waitqueue_head(&dev->vbl_queue);
+
+	spin_lock_init( &dev->vbl_lock );
+
+	INIT_LIST_HEAD( &dev->vbl_sigs.head );
+
+	dev->vbl_pending = 0;
+#endif
+
+				/* Before installing handler */
+	DRM(driver_irq_preinstall)(dev);
+
+				/* Install handler */
+	ret = request_irq( dev->irq, DRM(irq_handler),
+			   DRM_IRQ_TYPE, dev->devname, dev );
+	if ( ret < 0 ) {
+		down( &dev->struct_sem );
+		dev->irq_enabled = 0;
+		up( &dev->struct_sem );
+		return ret;
+	}
+
+				/* After installing handler */
+	DRM(driver_irq_postinstall)(dev);
+
+	return 0;
+}
+
+/**
+ * Uninstall the IRQ handler.
+ *
+ * \param dev DRM device.
+ *
+ * Calls the driver's \c DRM(driver_irq_uninstall)() function, and stops the irq.
+ */
+int DRM(irq_uninstall)( drm_device_t *dev )
+{
+	int irq_enabled;
+
+	down( &dev->struct_sem );
+	irq_enabled = dev->irq_enabled;
+	dev->irq_enabled = 0;
+	up( &dev->struct_sem );
+
+	if ( !irq_enabled )
+		return -EINVAL;
+
+	DRM_DEBUG( "%s: irq=%d\n", __FUNCTION__, dev->irq );
+
+	DRM(driver_irq_uninstall)( dev );
+
+	free_irq( dev->irq, dev );
+
+	return 0;
+}
+
+/**
+ * IRQ control ioctl.
+ *
+ * \param inode device inode.
+ * \param filp file pointer.
+ * \param cmd command.
+ * \param arg user argument, pointing to a drm_control structure.
+ * \return zero on success or a negative number on failure.
+ *
+ * Calls irq_install() or irq_uninstall() according to \p arg.
+ */
+int DRM(control)( struct inode *inode, struct file *filp,
+		  unsigned int cmd, unsigned long arg )
+{
+	drm_file_t *priv = filp->private_data;
+	drm_device_t *dev = priv->dev;
+	drm_control_t ctl;
+
+	if ( copy_from_user( &ctl, (drm_control_t *)arg, sizeof(ctl) ) )
+		return -EFAULT;
+
+	switch ( ctl.func ) {
+	case DRM_INST_HANDLER:
+		if (dev->if_version < DRM_IF_VERSION(1, 2) &&
+		    ctl.irq != dev->irq)
+			return -EINVAL;
+		return DRM(irq_install)( dev );
+	case DRM_UNINST_HANDLER:
+		return DRM(irq_uninstall)( dev );
+	default:
+		return -EINVAL;
+	}
+}
+
+#if __HAVE_VBL_IRQ
+
+/**
+ * Wait for VBLANK.
+ *
+ * \param inode device inode.
+ * \param filp file pointer.
+ * \param cmd command.
+ * \param data user argument, pointing to a drm_wait_vblank structure.
+ * \return zero on success or a negative number on failure.
+ *
+ * Verifies the IRQ is installed. 
+ *
+ * If a signal is requested checks if this task has already scheduled the same signal
+ * for the same vblank sequence number - nothing to be done in
+ * that case. If the number of tasks waiting for the interrupt exceeds 100 the
+ * function fails. Otherwise adds a new entry to drm_device::vbl_sigs for this
+ * task.
+ *
+ * If a signal is not requested, then calls vblank_wait().
+ */
+int DRM(wait_vblank)( DRM_IOCTL_ARGS )
+{
+	drm_file_t *priv = filp->private_data;
+	drm_device_t *dev = priv->dev;
+	drm_wait_vblank_t vblwait;
+	struct timeval now;
+	int ret = 0;
+	unsigned int flags;
+
+	if (!dev->irq)
+		return -EINVAL;
+
+	DRM_COPY_FROM_USER_IOCTL( vblwait, (drm_wait_vblank_t *)data,
+				  sizeof(vblwait) );
+
+	switch ( vblwait.request.type & ~_DRM_VBLANK_FLAGS_MASK ) {
+	case _DRM_VBLANK_RELATIVE:
+		vblwait.request.sequence += atomic_read( &dev->vbl_received );
+		vblwait.request.type &= ~_DRM_VBLANK_RELATIVE;
+	case _DRM_VBLANK_ABSOLUTE:
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	flags = vblwait.request.type & _DRM_VBLANK_FLAGS_MASK;
+	
+	if ( flags & _DRM_VBLANK_SIGNAL ) {
+		unsigned long irqflags;
+		drm_vbl_sig_t *vbl_sig;
+		
+		vblwait.reply.sequence = atomic_read( &dev->vbl_received );
+
+		spin_lock_irqsave( &dev->vbl_lock, irqflags );
+
+		/* Check if this task has already scheduled the same signal
+		 * for the same vblank sequence number; nothing to be done in
+		 * that case
+		 */
+		list_for_each_entry( vbl_sig, &dev->vbl_sigs.head, head ) {
+			if (vbl_sig->sequence == vblwait.request.sequence
+			    && vbl_sig->info.si_signo == vblwait.request.signal
+			    && vbl_sig->task == current)
+			{
+				spin_unlock_irqrestore( &dev->vbl_lock, irqflags );
+				goto done;
+			}
+		}
+
+		if ( dev->vbl_pending >= 100 ) {
+			spin_unlock_irqrestore( &dev->vbl_lock, irqflags );
+			return -EBUSY;
+		}
+
+		dev->vbl_pending++;
+
+		spin_unlock_irqrestore( &dev->vbl_lock, irqflags );
+
+		if ( !( vbl_sig = DRM_MALLOC( sizeof( drm_vbl_sig_t ) ) ) ) {
+			return -ENOMEM;
+		}
+
+		memset( (void *)vbl_sig, 0, sizeof(*vbl_sig) );
+
+		vbl_sig->sequence = vblwait.request.sequence;
+		vbl_sig->info.si_signo = vblwait.request.signal;
+		vbl_sig->task = current;
+
+		spin_lock_irqsave( &dev->vbl_lock, irqflags );
+
+		list_add_tail( (struct list_head *) vbl_sig, &dev->vbl_sigs.head );
+
+		spin_unlock_irqrestore( &dev->vbl_lock, irqflags );
+	} else {
+		ret = DRM(vblank_wait)( dev, &vblwait.request.sequence );
+
+		do_gettimeofday( &now );
+		vblwait.reply.tval_sec = now.tv_sec;
+		vblwait.reply.tval_usec = now.tv_usec;
+	}
+
+done:
+	DRM_COPY_TO_USER_IOCTL( (drm_wait_vblank_t *)data, vblwait,
+				sizeof(vblwait) );
+
+	return ret;
+}
+
+/**
+ * Send the VBLANK signals.
+ *
+ * \param dev DRM device.
+ *
+ * Sends a signal for each task in drm_device::vbl_sigs and empties the list.
+ *
+ * If a signal is not requested, then calls vblank_wait().
+ */
+void DRM(vbl_send_signals)( drm_device_t *dev )
+{
+	struct list_head *list, *tmp;
+	drm_vbl_sig_t *vbl_sig;
+	unsigned int vbl_seq = atomic_read( &dev->vbl_received );
+	unsigned long flags;
+
+	spin_lock_irqsave( &dev->vbl_lock, flags );
+
+	list_for_each_safe( list, tmp, &dev->vbl_sigs.head ) {
+		vbl_sig = list_entry( list, drm_vbl_sig_t, head );
+		if ( ( vbl_seq - vbl_sig->sequence ) <= (1<<23) ) {
+			vbl_sig->info.si_code = vbl_seq;
+			send_sig_info( vbl_sig->info.si_signo, &vbl_sig->info, vbl_sig->task );
+
+			list_del( list );
+
+			DRM_FREE( vbl_sig, sizeof(*vbl_sig) );
+
+			dev->vbl_pending--;
+		}
+	}
+
+	spin_unlock_irqrestore( &dev->vbl_lock, flags );
+}
+
+#endif	/* __HAVE_VBL_IRQ */
+
+#endif /* __HAVE_IRQ */
--- diff/drivers/i2c/busses/i2c-ixp42x.c	1970-01-01 01:00:00.000000000 +0100
+++ source/drivers/i2c/busses/i2c-ixp42x.c	2004-02-23 13:56:41.000000000 +0000
@@ -0,0 +1,180 @@
+/*
+ * drivers/i2c/i2c-adap-ixp42x.c
+ *
+ * Intel's IXP42x XScale NPU chipsets (IXP420, 421, 422, 425) do not have
+ * an on board I2C controller but provide 16 GPIO pins that are often
+ * used to create an I2C bus. This driver provides an i2c_adapter 
+ * interface that plugs in under algo_bit and drives the GPIO pins
+ * as instructed by the alogorithm driver.
+ *
+ * Author: Deepak Saxena <dsaxena@plexity.net>
+ *
+ * Copyright (c) 2003-2004 MontaVista Software Inc.
+ *
+ * This file is licensed under the terms of the GNU General Public 
+ * License version 2. This program is licensed "as is" without any 
+ * warranty of any kind, whether express or implied.
+ *
+ * NOTE: Since different platforms will use different GPIO pins for
+ *       I2C, this driver uses an IXP42x-specific platform_data
+ *       pointer to pass the GPIO numbers to the driver. This 
+ *       allows us to support all the different IXP42x platforms
+ *       w/o having to put #ifdefs in this driver.
+ *
+ *       See arch/arm/mach-ixp42x/ixdp425.c for an example of building a 
+ *       device list and filling in the ixp42x_i2c_pins data structure 
+ *       that is passed as the platform_data to this driver.
+ */
+
+#include <linux/config.h>
+#ifdef CONFIG_I2C_DEBUG_BUS
+#define DEBUG	1
+#endif
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/device.h>
+#include <linux/module.h>
+#include <linux/i2c.h>
+
+#include <asm/hardware.h>	/* Pick up IXP42x-specific bits */
+
+static inline int ixp42x_scl_pin(void *data)
+{
+	return ((struct ixp42x_i2c_pins*)data)->scl_pin;
+}
+
+static inline int ixp42x_sda_pin(void *data)
+{
+	return ((struct ixp42x_i2c_pins*)data)->sda_pin;
+}
+
+static void ixp42x_bit_setscl(void *data, int val)
+{
+	gpio_line_set(ixp42x_scl_pin(data), 0);
+	gpio_line_config(ixp42x_scl_pin(data),
+		val ? IXP425_GPIO_IN : IXP425_GPIO_OUT );
+}
+
+static void ixp42x_bit_setsda(void *data, int val)
+{
+	gpio_line_set(ixp42x_sda_pin(data), 0);
+	gpio_line_config(ixp42x_sda_pin(data),
+		val ? IXP425_GPIO_IN : IXP425_GPIO_OUT );
+}
+
+static int ixp42x_bit_getscl(void *data)
+{
+	int scl;
+
+	gpio_line_config(ixp42x_scl_pin(data), IXP425_GPIO_IN );
+	gpio_line_get(ixp42x_scl_pin(data), &scl);
+
+	return scl;
+}	
+
+static int ixp42x_bit_getsda(void *data)
+{
+	int sda;
+
+	gpio_line_config(ixp42x_sda_pin(data), IXP425_GPIO_IN );
+	gpio_line_get(ixp42x_sda_pin(data), &sda);
+
+	return sda;
+}	
+
+struct ixp42x_i2c_data {
+	struct ixp42x_i2c_pins *gpio_pins;
+	struct i2c_adapter adapter;
+	struct i2c_algo_bit_data algo_data;
+};
+
+static int ixp42x_i2c_remove(struct device *dev)
+{
+	struct platform_device *plat_dev = to_platform_device(dev);
+	struct ixp42x_i2c_data *drv_data = dev_get_drvdata(&plat_dev->dev);
+
+	dev_set_drvdata(&plat_dev->dev, NULL);
+
+	i2c_bit_del_bus(&drv_data->adapter);
+
+	kfree(drv_data);
+
+	return 0;
+}
+
+static int ixp42x_i2c_probe(struct device *dev)
+{
+	int err;
+	struct platform_device *plat_dev = to_platform_device(dev);
+	struct ixp42x_i2c_pins *gpio = plat_dev->dev.platform_data;
+	struct ixp42x_i2c_data *drv_data = 
+		kmalloc(sizeof(struct ixp42x_i2c_data), GFP_KERNEL);
+
+	if(!drv_data)
+		return -ENOMEM;
+
+	memzero(drv_data, sizeof(struct ixp42x_i2c_data));
+	drv_data->gpio_pins = gpio;
+
+	/*
+	 * We could make a lot of these structures static, but
+	 * certain platforms may have multiple GPIO-based I2C
+	 * buses for various device domains, so we need per-device
+	 * algo_data->data. 
+	 */
+	drv_data->algo_data.data = gpio;
+	drv_data->algo_data.setsda = ixp42x_bit_setsda;
+	drv_data->algo_data.setscl = ixp42x_bit_setscl;
+	drv_data->algo_data.getsda = ixp42x_bit_getsda;
+	drv_data->algo_data.getscl = ixp42x_bit_getscl;
+	drv_data->algo_data.udelay = 10;
+	drv_data->algo_data.mdelay = 10;
+	drv_data->algo_data.timeout = 100;
+
+	drv_data->adapter.id = I2C_HW_B_IXP425,
+	drv_data->adapter.algo_data = &drv_data->algo_data,
+
+	drv_data->adapter.dev.parent = &plat_dev->dev;
+
+	gpio_line_config(gpio->scl_pin, IXP425_GPIO_IN);
+	gpio_line_config(gpio->sda_pin, IXP425_GPIO_IN);
+	gpio_line_set(gpio->scl_pin, 0);
+	gpio_line_set(gpio->sda_pin, 0);
+
+	if ((err = i2c_bit_add_bus(&drv_data->adapter) != 0)) {
+		printk(KERN_ERR "ERROR: Could not install %s\n", dev->bus_id);
+
+		kfree(drv_data);
+		return err;
+	}
+
+	dev_set_drvdata(&plat_dev->dev, drv_data);
+
+	return 0;
+}
+
+static struct device_driver ixp42x_i2c_driver = {
+	.name		= "IXP42X-I2C",
+	.bus		= &platform_bus_type,
+	.probe		= ixp42x_i2c_probe,
+	.remove		= ixp42x_i2c_remove,
+};
+
+static int __init ixp42x_i2c_init(void)
+{
+	return driver_register(&ixp42x_i2c_driver);
+}
+
+static void __exit ixp42x_i2c_exit(void)
+{
+	driver_unregister(&ixp42x_i2c_driver);
+}
+
+module_init(ixp42x_i2c_init);
+module_exit(ixp42x_i2c_exit);
+
+MODULE_DESCRIPTION("GPIO-based I2C driver for IXP42x systems");
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Deepak Saxena <dsaxena@plexity.net>");
+
--- diff/drivers/i2c/chips/lm80.c	1970-01-01 01:00:00.000000000 +0100
+++ source/drivers/i2c/chips/lm80.c	2004-02-23 13:56:41.000000000 +0000
@@ -0,0 +1,567 @@
+/*
+ * lm80.c - From lm_sensors, Linux kernel modules for hardware
+ * monitoring
+ * Copyright (C) 1998, 1999  Frodo Looijaard <frodol@dds.nl>
+ * and Philip Edelbrock <phil@netroedge.com>
+ *
+ * Ported to Linux 2.6 by Tiago Sousa <mirage@kaotik.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/config.h>
+#ifdef CONFIG_I2C_DEBUG_CHIP
+#define DEBUG	1
+#endif
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/i2c.h>
+#include <linux/i2c-sensor.h>
+
+/* Addresses to scan */
+static unsigned short normal_i2c[] = { I2C_CLIENT_END };
+static unsigned short normal_i2c_range[] = { 0x28, 0x2f, I2C_CLIENT_END };
+static unsigned int normal_isa[] = { I2C_CLIENT_ISA_END };
+static unsigned int normal_isa_range[] = { I2C_CLIENT_ISA_END };
+
+/* Insmod parameters */
+SENSORS_INSMOD_1(lm80);
+
+/* Many LM80 constants specified below */
+
+/* The LM80 registers */
+#define LM80_REG_IN_MAX(nr)		(0x2a + (nr) * 2)
+#define LM80_REG_IN_MIN(nr)		(0x2b + (nr) * 2)
+#define LM80_REG_IN(nr)			(0x20 + (nr))
+
+#define LM80_REG_FAN1_MIN		0x3c
+#define LM80_REG_FAN2_MIN		0x3d
+#define LM80_REG_FAN1			0x28
+#define LM80_REG_FAN2			0x29
+
+#define LM80_REG_TEMP			0x27
+#define LM80_REG_TEMP_HOT_MAX		0x38
+#define LM80_REG_TEMP_HOT_HYST		0x39
+#define LM80_REG_TEMP_OS_MAX		0x3a
+#define LM80_REG_TEMP_OS_HYST		0x3b
+
+#define LM80_REG_CONFIG			0x00
+#define LM80_REG_ALARM1			0x01
+#define LM80_REG_ALARM2			0x02
+#define LM80_REG_MASK1			0x03
+#define LM80_REG_MASK2			0x04
+#define LM80_REG_FANDIV			0x05
+#define LM80_REG_RES			0x06
+
+
+/* Conversions. Rounding and limit checking is only done on the TO_REG
+   variants. Note that you should be a bit careful with which arguments
+   these macros are called: arguments may be evaluated more than once.
+   Fixing this is just not worth it. */
+
+#define IN_TO_REG(val)		(SENSORS_LIMIT((val)/10,0,255))
+#define IN_FROM_REG(val)	((val)*10)
+
+static inline unsigned char FAN_TO_REG(unsigned rpm, unsigned div)
+{
+	if (rpm == 0)
+		return 255;
+	rpm = SENSORS_LIMIT(rpm, 1, 1000000);
+	return SENSORS_LIMIT((1350000 + rpm*div / 2) / (rpm*div), 1, 254);
+}
+
+#define FAN_FROM_REG(val,div)	((val)==0?-1:\
+				(val)==255?0:1350000/((div)*(val)))
+
+static inline long TEMP_FROM_REG(u16 temp)
+{
+	long res;
+
+	temp >>= 4;
+	if (temp < 0x0800)
+		res = 625 * (long) temp;
+	else
+		res = ((long) temp - 0x01000) * 625;
+
+	return res / 10;
+}
+
+#define TEMP_LIMIT_FROM_REG(val)	(((val)>0x80?(val)-0x100:(val))*1000)
+
+#define TEMP_LIMIT_TO_REG(val)		SENSORS_LIMIT((val)<0?\
+					((val)-500)/1000:((val)+500)/1000,0,255)
+
+#define ALARMS_FROM_REG(val)		(val)
+
+#define DIV_FROM_REG(val)		(1 << (val))
+#define DIV_TO_REG(val)			((val)==8?3:(val)==4?2:(val)==1?0:1)
+
+/*
+ * Client data (each client gets its own)
+ */
+
+struct lm80_data {
+	struct semaphore update_lock;
+	char valid;		/* !=0 if following fields are valid */
+	unsigned long last_updated;	/* In jiffies */
+
+	u8 in[7];		/* Register value */
+	u8 in_max[7];		/* Register value */
+	u8 in_min[7];		/* Register value */
+	u8 fan[2];		/* Register value */
+	u8 fan_min[2];		/* Register value */
+	u8 fan_div[2];		/* Register encoding, shifted right */
+	u16 temp;		/* Register values, shifted right */
+	u8 temp_hot_max;	/* Register value */
+	u8 temp_hot_hyst;	/* Register value */
+	u8 temp_os_max;		/* Register value */
+	u8 temp_os_hyst;	/* Register value */
+	u16 alarms;		/* Register encoding, combined */
+};
+
+/* 
+ * Functions declaration
+ */
+
+static int lm80_attach_adapter(struct i2c_adapter *adapter);
+static int lm80_detect(struct i2c_adapter *adapter, int address, int kind);
+static void lm80_init_client(struct i2c_client *client);
+static int lm80_detach_client(struct i2c_client *client);
+static void lm80_update_client(struct i2c_client *client);
+static int lm80_read_value(struct i2c_client *client, u8 reg);
+static int lm80_write_value(struct i2c_client *client, u8 reg, u8 value);
+
+/*
+ * Internal variables
+ */
+
+static int lm80_id = 0;
+
+/*
+ * Driver data (common to all clients)
+ */
+
+static struct i2c_driver lm80_driver = {
+	.owner		= THIS_MODULE,
+	.name		= "lm80",
+	.id		= I2C_DRIVERID_LM80,
+	.flags		= I2C_DF_NOTIFY,
+	.attach_adapter	= lm80_attach_adapter,
+	.detach_client	= lm80_detach_client,
+};
+
+/*
+ * Sysfs stuff
+ */
+
+#define show_in(suffix, value) \
+static ssize_t show_in_##suffix(struct device *dev, char *buf) \
+{ \
+	struct i2c_client *client = to_i2c_client(dev); \
+	struct lm80_data *data = i2c_get_clientdata(client); \
+	lm80_update_client(client); \
+	return sprintf(buf, "%d\n", IN_FROM_REG(data->value)); \
+}
+show_in(min0, in_min[0]);
+show_in(min1, in_min[1]);
+show_in(min2, in_min[2]);
+show_in(min3, in_min[3]);
+show_in(min4, in_min[4]);
+show_in(min5, in_min[5]);
+show_in(min6, in_min[6]);
+show_in(max0, in_max[0]);
+show_in(max1, in_max[1]);
+show_in(max2, in_max[2]);
+show_in(max3, in_max[3]);
+show_in(max4, in_max[4]);
+show_in(max5, in_max[5]);
+show_in(max6, in_max[6]);
+show_in(input0, in[0]);
+show_in(input1, in[1]);
+show_in(input2, in[2]);
+show_in(input3, in[3]);
+show_in(input4, in[4]);
+show_in(input5, in[5]);
+show_in(input6, in[6]);
+
+#define set_in(suffix, value, reg) \
+static ssize_t set_in_##suffix(struct device *dev, const char *buf, \
+	size_t count) \
+{ \
+	struct i2c_client *client = to_i2c_client(dev); \
+	struct lm80_data *data = i2c_get_clientdata(client); \
+	long val = simple_strtol(buf, NULL, 10); \
+	data->value = IN_TO_REG(val); \
+	lm80_write_value(client, reg, data->value); \
+	return count; \
+}
+set_in(min0, in_min[0], LM80_REG_IN_MIN(0));
+set_in(min1, in_min[1], LM80_REG_IN_MIN(1));
+set_in(min2, in_min[2], LM80_REG_IN_MIN(2));
+set_in(min3, in_min[3], LM80_REG_IN_MIN(3));
+set_in(min4, in_min[4], LM80_REG_IN_MIN(4));
+set_in(min5, in_min[5], LM80_REG_IN_MIN(5));
+set_in(min6, in_min[6], LM80_REG_IN_MIN(6));
+set_in(max0, in_max[0], LM80_REG_IN_MAX(0));
+set_in(max1, in_max[1], LM80_REG_IN_MAX(1));
+set_in(max2, in_max[2], LM80_REG_IN_MAX(2));
+set_in(max3, in_max[3], LM80_REG_IN_MAX(3));
+set_in(max4, in_max[4], LM80_REG_IN_MAX(4));
+set_in(max5, in_max[5], LM80_REG_IN_MAX(5));
+set_in(max6, in_max[6], LM80_REG_IN_MAX(6));
+
+#define show_fan(suffix, value, div) \
+static ssize_t show_fan_##suffix(struct device *dev, char *buf) \
+{ \
+	struct i2c_client *client = to_i2c_client(dev); \
+	struct lm80_data *data = i2c_get_clientdata(client); \
+	lm80_update_client(client); \
+	return sprintf(buf, "%d\n", FAN_FROM_REG(data->value, \
+		       DIV_FROM_REG(data->div))); \
+}
+show_fan(min1, fan_min[0], fan_div[0]);
+show_fan(min2, fan_min[1], fan_div[1]);
+show_fan(input1, fan[0], fan_div[0]);
+show_fan(input2, fan[1], fan_div[1]);
+
+#define show_fan_div(suffix, value) \
+static ssize_t show_fan_div##suffix(struct device *dev, char *buf) \
+{ \
+	struct i2c_client *client = to_i2c_client(dev); \
+	struct lm80_data *data = i2c_get_clientdata(client); \
+	lm80_update_client(client); \
+	return sprintf(buf, "%d\n", DIV_FROM_REG(data->value)); \
+}
+show_fan_div(1, fan_div[0]);
+show_fan_div(2, fan_div[1]);
+
+#define set_fan(suffix, value, reg, div) \
+static ssize_t set_fan_##suffix(struct device *dev, const char *buf, \
+	size_t count) \
+{ \
+	struct i2c_client *client = to_i2c_client(dev); \
+	struct lm80_data *data = i2c_get_clientdata(client); \
+	long val = simple_strtoul(buf, NULL, 10); \
+	data->value = FAN_TO_REG(val, DIV_FROM_REG(data->div)); \
+	lm80_write_value(client, reg, data->value); \
+	return count; \
+}
+set_fan(min1, fan_min[0], LM80_REG_FAN1_MIN, fan_div[0]);
+set_fan(min2, fan_min[1], LM80_REG_FAN2_MIN, fan_div[1]);
+
+static ssize_t show_temp_input1(struct device *dev, char *buf)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct lm80_data *data = i2c_get_clientdata(client);
+	lm80_update_client(client);
+	return sprintf(buf, "%ld\n", TEMP_FROM_REG(data->temp));
+}
+
+#define show_temp(suffix, value) \
+static ssize_t show_temp_##suffix(struct device *dev, char *buf) \
+{ \
+	struct i2c_client *client = to_i2c_client(dev); \
+	struct lm80_data *data = i2c_get_clientdata(client); \
+	lm80_update_client(client); \
+	return sprintf(buf, "%d\n", TEMP_LIMIT_FROM_REG(data->value)); \
+}
+show_temp(hot_max, temp_hot_max);
+show_temp(hot_hyst, temp_hot_hyst);
+show_temp(os_max, temp_os_max);
+show_temp(os_hyst, temp_os_hyst);
+
+#define set_temp(suffix, value, reg) \
+static ssize_t set_temp_##suffix(struct device *dev, const char *buf, \
+	size_t count) \
+{ \
+	struct i2c_client *client = to_i2c_client(dev); \
+	struct lm80_data *data = i2c_get_clientdata(client); \
+	long val = simple_strtoul(buf, NULL, 10); \
+	data->value = TEMP_LIMIT_TO_REG(val); \
+	lm80_write_value(client, reg, data->value); \
+	return count; \
+}
+set_temp(hot_max, temp_hot_max, LM80_REG_TEMP_HOT_MAX);
+set_temp(hot_hyst, temp_hot_hyst, LM80_REG_TEMP_HOT_HYST);
+set_temp(os_max, temp_os_max, LM80_REG_TEMP_OS_MAX);
+set_temp(os_hyst, temp_os_hyst, LM80_REG_TEMP_OS_HYST);
+
+static ssize_t show_alarms(struct device *dev, char *buf)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct lm80_data *data = i2c_get_clientdata(client);
+	lm80_update_client(client);
+	return sprintf(buf, "%d\n", ALARMS_FROM_REG(data->alarms));
+}
+
+static DEVICE_ATTR(in_min0, S_IWUSR | S_IRUGO, show_in_min0, set_in_min0);
+static DEVICE_ATTR(in_min1, S_IWUSR | S_IRUGO, show_in_min1, set_in_min1);
+static DEVICE_ATTR(in_min2, S_IWUSR | S_IRUGO, show_in_min2, set_in_min2);
+static DEVICE_ATTR(in_min3, S_IWUSR | S_IRUGO, show_in_min3, set_in_min3);
+static DEVICE_ATTR(in_min4, S_IWUSR | S_IRUGO, show_in_min4, set_in_min4);
+static DEVICE_ATTR(in_min5, S_IWUSR | S_IRUGO, show_in_min5, set_in_min5);
+static DEVICE_ATTR(in_min6, S_IWUSR | S_IRUGO, show_in_min6, set_in_min6);
+static DEVICE_ATTR(in_max0, S_IWUSR | S_IRUGO, show_in_max0, set_in_max0);
+static DEVICE_ATTR(in_max1, S_IWUSR | S_IRUGO, show_in_max1, set_in_max1);
+static DEVICE_ATTR(in_max2, S_IWUSR | S_IRUGO, show_in_max2, set_in_max2);
+static DEVICE_ATTR(in_max3, S_IWUSR | S_IRUGO, show_in_max3, set_in_max3);
+static DEVICE_ATTR(in_max4, S_IWUSR | S_IRUGO, show_in_max4, set_in_max4);
+static DEVICE_ATTR(in_max5, S_IWUSR | S_IRUGO, show_in_max5, set_in_max5);
+static DEVICE_ATTR(in_max6, S_IWUSR | S_IRUGO, show_in_max6, set_in_max6);
+static DEVICE_ATTR(in_input0, S_IRUGO, show_in_input0, NULL);
+static DEVICE_ATTR(in_input1, S_IRUGO, show_in_input1, NULL);
+static DEVICE_ATTR(in_input2, S_IRUGO, show_in_input2, NULL);
+static DEVICE_ATTR(in_input3, S_IRUGO, show_in_input3, NULL);
+static DEVICE_ATTR(in_input4, S_IRUGO, show_in_input4, NULL);
+static DEVICE_ATTR(in_input5, S_IRUGO, show_in_input5, NULL);
+static DEVICE_ATTR(in_input6, S_IRUGO, show_in_input6, NULL);
+static DEVICE_ATTR(fan_min1, S_IWUSR | S_IRUGO, show_fan_min1,
+    set_fan_min1);
+static DEVICE_ATTR(fan_min2, S_IWUSR | S_IRUGO, show_fan_min2,
+    set_fan_min2);
+static DEVICE_ATTR(fan_input1, S_IRUGO, show_fan_input1, NULL);
+static DEVICE_ATTR(fan_input2, S_IRUGO, show_fan_input2, NULL);
+static DEVICE_ATTR(fan_div1, S_IRUGO, show_fan_div1, NULL);
+static DEVICE_ATTR(fan_div2, S_IRUGO, show_fan_div2, NULL);
+static DEVICE_ATTR(temp_input1, S_IRUGO, show_temp_input1, NULL);
+static DEVICE_ATTR(temp_max1, S_IWUSR | S_IRUGO, show_temp_hot_max,
+    set_temp_hot_max);
+static DEVICE_ATTR(temp_max1_hyst, S_IWUSR | S_IRUGO, show_temp_hot_hyst,
+    set_temp_hot_hyst);
+static DEVICE_ATTR(temp_crit1, S_IWUSR | S_IRUGO, show_temp_os_max,
+    set_temp_os_max);
+static DEVICE_ATTR(temp_crit1_hyst, S_IWUSR | S_IRUGO, show_temp_os_hyst,
+    set_temp_os_hyst);
+static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL);
+
+/*
+ * Real code
+ */
+
+static int lm80_attach_adapter(struct i2c_adapter *adapter)
+{
+	if (!(adapter->class & I2C_ADAP_CLASS_SMBUS))
+		return 0;
+	return i2c_detect(adapter, &addr_data, lm80_detect);
+}
+
+int lm80_detect(struct i2c_adapter *adapter, int address, int kind)
+{
+	int i, cur;
+	struct i2c_client *new_client;
+	struct lm80_data *data;
+	int err = 0;
+	const char *name;
+
+	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
+		goto exit;
+
+	/* OK. For now, we presume we have a valid client. We now create the
+	   client structure, even though we cannot fill it completely yet.
+	   But it allows us to access lm80_{read,write}_value. */
+	if (!(new_client = kmalloc(sizeof(struct i2c_client) +
+	    sizeof(struct lm80_data), GFP_KERNEL))) {
+		err = -ENOMEM;
+		goto exit;
+	}
+	memset(new_client, 0x00, sizeof(struct i2c_client) +
+	       sizeof(struct lm80_data));
+
+	data = (struct lm80_data *) (new_client + 1);
+	i2c_set_clientdata(new_client, data);
+	new_client->addr = address;
+	new_client->adapter = adapter;
+	new_client->driver = &lm80_driver;
+	new_client->flags = 0;
+
+	/* Now, we do the remaining detection. It is lousy. */
+	if (lm80_read_value(new_client, LM80_REG_ALARM2) & 0xc0)
+		goto error_free;
+	for (i = 0x2a; i <= 0x3d; i++) {
+		cur = i2c_smbus_read_byte_data(new_client, i);
+		if ((i2c_smbus_read_byte_data(new_client, i + 0x40) != cur)
+		 || (i2c_smbus_read_byte_data(new_client, i + 0x80) != cur)
+		 || (i2c_smbus_read_byte_data(new_client, i + 0xc0) != cur))
+		    goto error_free;
+	}
+
+	/* Determine the chip type - only one kind supported! */
+	kind = lm80;
+	name = "lm80";
+
+	/* Fill in the remaining client fields and put it into the global list */
+	strlcpy(new_client->name, name, I2C_NAME_SIZE);
+
+	new_client->id = lm80_id++;
+	data->valid = 0;
+	init_MUTEX(&data->update_lock);
+
+	/* Tell the I2C layer a new client has arrived */
+	if ((err = i2c_attach_client(new_client)))
+		goto error_free;
+
+	/* Initialize the LM80 chip */
+	lm80_init_client(new_client);
+
+	/* Register sysfs hooks */
+	device_create_file(&new_client->dev, &dev_attr_in_min0);
+	device_create_file(&new_client->dev, &dev_attr_in_min1);
+	device_create_file(&new_client->dev, &dev_attr_in_min2);
+	device_create_file(&new_client->dev, &dev_attr_in_min3);
+	device_create_file(&new_client->dev, &dev_attr_in_min4);
+	device_create_file(&new_client->dev, &dev_attr_in_min5);
+	device_create_file(&new_client->dev, &dev_attr_in_min6);
+	device_create_file(&new_client->dev, &dev_attr_in_max0);
+	device_create_file(&new_client->dev, &dev_attr_in_max1);
+	device_create_file(&new_client->dev, &dev_attr_in_max2);
+	device_create_file(&new_client->dev, &dev_attr_in_max3);
+	device_create_file(&new_client->dev, &dev_attr_in_max4);
+	device_create_file(&new_client->dev, &dev_attr_in_max5);
+	device_create_file(&new_client->dev, &dev_attr_in_max6);
+	device_create_file(&new_client->dev, &dev_attr_in_input0);
+	device_create_file(&new_client->dev, &dev_attr_in_input1);
+	device_create_file(&new_client->dev, &dev_attr_in_input2);
+	device_create_file(&new_client->dev, &dev_attr_in_input3);
+	device_create_file(&new_client->dev, &dev_attr_in_input4);
+	device_create_file(&new_client->dev, &dev_attr_in_input5);
+	device_create_file(&new_client->dev, &dev_attr_in_input6);
+	device_create_file(&new_client->dev, &dev_attr_fan_min1);
+	device_create_file(&new_client->dev, &dev_attr_fan_min2);
+	device_create_file(&new_client->dev, &dev_attr_fan_input1);
+	device_create_file(&new_client->dev, &dev_attr_fan_input2);
+	device_create_file(&new_client->dev, &dev_attr_fan_div1);
+	device_create_file(&new_client->dev, &dev_attr_fan_div2);
+	device_create_file(&new_client->dev, &dev_attr_temp_input1);
+	device_create_file(&new_client->dev, &dev_attr_temp_max1);
+	device_create_file(&new_client->dev, &dev_attr_temp_max1_hyst);
+	device_create_file(&new_client->dev, &dev_attr_temp_crit1);
+	device_create_file(&new_client->dev, &dev_attr_temp_crit1_hyst);
+	device_create_file(&new_client->dev, &dev_attr_alarms);
+
+	return 0;
+
+error_free:
+	kfree(new_client);
+exit:
+	return err;
+}
+
+static int lm80_detach_client(struct i2c_client *client)
+{
+	int err;
+
+	if ((err = i2c_detach_client(client))) {
+		dev_err(&client->dev, "Client deregistration failed, "
+			"client not detached.\n");
+		return err;
+	}
+
+	kfree(client);
+	return 0;
+}
+
+static int lm80_read_value(struct i2c_client *client, u8 reg)
+{
+	return i2c_smbus_read_byte_data(client, reg);
+}
+
+static int lm80_write_value(struct i2c_client *client, u8 reg, u8 value)
+{
+	return i2c_smbus_write_byte_data(client, reg, value);
+}
+
+/* Called when we have found a new LM80. */
+static void lm80_init_client(struct i2c_client *client)
+{
+	/* Reset all except Watchdog values and last conversion values
+	   This sets fan-divs to 2, among others. This makes most other
+	   initializations unnecessary */
+	lm80_write_value(client, LM80_REG_CONFIG, 0x80);
+	/* Set 11-bit temperature resolution */
+	lm80_write_value(client, LM80_REG_RES, 0x08);
+
+	/* Start monitoring */
+	lm80_write_value(client, LM80_REG_CONFIG, 0x01);
+}
+
+static void lm80_update_client(struct i2c_client *client)
+{
+	struct lm80_data *data = i2c_get_clientdata(client);
+	int i;
+
+	down(&data->update_lock);
+
+	if ((jiffies - data->last_updated > 2 * HZ) ||
+	    (jiffies < data->last_updated) || !data->valid) {
+
+		dev_dbg(&client->dev, "Starting lm80 update\n");
+		for (i = 0; i <= 6; i++) {
+			data->in[i] =
+			    lm80_read_value(client, LM80_REG_IN(i));
+			data->in_min[i] =
+			    lm80_read_value(client, LM80_REG_IN_MIN(i));
+			data->in_max[i] =
+			    lm80_read_value(client, LM80_REG_IN_MAX(i));
+		}
+		data->fan[0] = lm80_read_value(client, LM80_REG_FAN1);
+		data->fan_min[0] =
+		    lm80_read_value(client, LM80_REG_FAN1_MIN);
+		data->fan[1] = lm80_read_value(client, LM80_REG_FAN2);
+		data->fan_min[1] =
+		    lm80_read_value(client, LM80_REG_FAN2_MIN);
+
+		data->temp =
+		    (lm80_read_value(client, LM80_REG_TEMP) << 8) |
+		    (lm80_read_value(client, LM80_REG_RES) & 0xf0);
+		data->temp_os_max =
+		    lm80_read_value(client, LM80_REG_TEMP_OS_MAX);
+		data->temp_os_hyst =
+		    lm80_read_value(client, LM80_REG_TEMP_OS_HYST);
+		data->temp_hot_max =
+		    lm80_read_value(client, LM80_REG_TEMP_HOT_MAX);
+		data->temp_hot_hyst =
+		    lm80_read_value(client, LM80_REG_TEMP_HOT_HYST);
+
+		i = lm80_read_value(client, LM80_REG_FANDIV);
+		data->fan_div[0] = (i >> 2) & 0x03;
+		data->fan_div[1] = (i >> 4) & 0x03;
+		data->alarms = lm80_read_value(client, LM80_REG_ALARM1) +
+		    (lm80_read_value(client, LM80_REG_ALARM2) << 8);
+		data->last_updated = jiffies;
+		data->valid = 1;
+	}
+
+	up(&data->update_lock);
+}
+
+static int __init sensors_lm80_init(void)
+{
+	return i2c_add_driver(&lm80_driver);
+}
+
+static void __exit sensors_lm80_exit(void)
+{
+	i2c_del_driver(&lm80_driver);
+}
+
+MODULE_AUTHOR("Frodo Looijaard <frodol@dds.nl> and "
+	"Philip Edelbrock <phil@netroedge.com>");
+MODULE_DESCRIPTION("LM80 driver");
+MODULE_LICENSE("GPL");
+
+module_init(sensors_lm80_init);
+module_exit(sensors_lm80_exit);
--- diff/drivers/ieee1394/csr1212.c	1970-01-01 01:00:00.000000000 +0100
+++ source/drivers/ieee1394/csr1212.c	2004-02-23 13:56:41.000000000 +0000
@@ -0,0 +1,1566 @@
+/*
+ * csr1212.c -- IEEE 1212 Control and Status Register support for Linux
+ * 
+ * Copyright (C) 2003 Francois Retief <fgretief@sun.ac.za>
+ *                    Steve Kinneberg <kinnebergsteve@acmsystems.com>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *    1. Redistributions of source code must retain the above copyright notice,
+ *       this list of conditions and the following disclaimer.
+ *    2. Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *    3. The name of the author may not be used to endorse or promote products
+ *       derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+/* TODO List:
+ * - Verify interface consistency: i.e., public functions that take a size
+ *   parameter expect size to be in bytes.
+ * - Convenience functions for reading a block of data from a given offset.
+ */
+
+#ifndef __KERNEL__
+#include <string.h>
+#endif
+
+#include "csr1212.h"
+
+
+/* Permitted key type for each key id */
+#define __I (1 << CSR1212_KV_TYPE_IMMEDIATE)
+#define __C (1 << CSR1212_KV_TYPE_CSR_OFFSET)
+#define __D (1 << CSR1212_KV_TYPE_DIRECTORY)
+#define __L (1 << CSR1212_KV_TYPE_LEAF)
+static const u_int8_t csr1212_key_id_type_map[0x30] = {
+	0,			/* Reserved */
+	__D | __L,		/* Descriptor */
+	__I | __D | __L,	/* Bus_Dependent_Info */
+	__I | __D | __L,	/* Vendor */
+	__I,			/* Hardware_Version */
+	0, 0,			/* Reserved */
+	__D | __L,		/* Module */
+	0, 0, 0, 0,		/* Reserved */
+	__I,			/* Node_Capabilities */
+	__L,			/* EUI_64 */
+	0, 0, 0,		/* Reserved */
+	__D,			/* Unit */
+	__I,			/* Specifier_ID */
+	__I,			/* Version */
+	__I | __C | __D | __L,	/* Dependent_Info */
+	__L,			/* Unit_Location */
+	0,			/* Reserved */
+	__I,			/* Model */
+	__D,			/* Instance */
+	__L,			/* Keyword */
+	__D,			/* Feature */
+	__L,			/* Extended_ROM */
+	__I,			/* Extended_Key_Specifier_ID */
+	__I,			/* Extended_Key */
+	__I | __C | __D | __L,	/* Extended_Data */
+	__L,			/* Modifiable_Descriptor */
+	__I,			/* Directory_ID */
+	__I,			/* Revision */
+};
+#undef __I
+#undef __C
+#undef __D
+#undef __L
+
+
+#define quads_to_bytes(_q) ((_q) * sizeof(u_int32_t))
+#define bytes_to_quads(_b) (((_b) + sizeof(u_int32_t) - 1) / sizeof(u_int32_t))
+
+static inline void free_keyval(struct csr1212_keyval *kv)
+{
+	if (kv->key.type == CSR1212_KV_TYPE_LEAF)
+		CSR1212_FREE(kv->value.leaf.data);
+
+	CSR1212_FREE(kv);
+}
+
+static u_int16_t csr1212_crc16(const u_int32_t *buffer, size_t length)
+{
+	int shift;
+	u_int32_t data;
+	u_int16_t sum, crc = 0;
+
+	for (; length; length--) {
+		data = CSR1212_BE32_TO_CPU(*buffer);
+		buffer++;
+		for (shift = 28; shift >= 0; shift -= 4 ) {
+			sum = ((crc >> 12) ^ (data >> shift)) & 0xf;
+			crc = (crc << 4) ^ (sum << 12) ^ (sum << 5) ^ (sum);
+		}
+		crc &= 0xffff;
+	}
+
+	return CSR1212_CPU_TO_BE16(crc);
+}
+
+#if 0
+/* Microsoft computes the CRC with the bytes in reverse order.  Therefore we
+ * have a special version of the CRC algorithm to account for their buggy
+ * software. */
+static u_int16_t csr1212_msft_crc16(const u_int32_t *buffer, size_t length)
+{
+	int shift;
+	u_int32_t data;
+	u_int16_t sum, crc = 0;
+
+	for (; length; length--) {
+		data = CSR1212_LE32_TO_CPU(*buffer);
+		buffer++;
+		for (shift = 28; shift >= 0; shift -= 4 ) {
+			sum = ((crc >> 12) ^ (data >> shift)) & 0xf;
+			crc = (crc << 4) ^ (sum << 12) ^ (sum << 5) ^ (sum);
+		}
+		crc &= 0xffff;
+	}
+
+	return CSR1212_CPU_TO_BE16(crc);
+}
+#endif
+
+static inline struct csr1212_dentry *csr1212_find_keyval(struct csr1212_keyval *dir,
+							 struct csr1212_keyval *kv)
+{
+	struct csr1212_dentry *pos;
+
+	for (pos = dir->value.directory.dentries_head;
+	     pos != NULL; pos = pos->next) {
+		if (pos->kv == kv)
+			return pos;
+	}
+	return NULL;
+}
+
+
+static inline struct csr1212_keyval *csr1212_find_keyval_offset(struct csr1212_keyval *kv_list,
+								u_int32_t offset)
+{
+	struct csr1212_keyval *kv;
+
+	for (kv = kv_list; kv != NULL; kv = kv->next) {
+		if (kv->offset == offset)
+			return kv;
+	}
+	return NULL;
+}
+
+
+/* Creation Routines */
+struct csr1212_csr *csr1212_create_csr(struct csr1212_bus_ops *ops,
+				       size_t bus_info_size, void *private)
+{
+	struct csr1212_csr *csr;
+
+	csr = CSR1212_MALLOC(sizeof(*csr));
+	if (!csr)
+		return NULL;
+
+	csr->cache_head = 
+		csr1212_rom_cache_malloc(CSR1212_CONFIG_ROM_SPACE_OFFSET,
+					 CSR1212_CONFIG_ROM_SPACE_SIZE);
+	if (!csr->cache_head) {
+		CSR1212_FREE(csr);
+		return NULL;
+	}
+
+        /* The keyval key id is not used for the root node, but a valid key id
+         * that can be used for a directory needs to be passed to
+         * csr1212_new_directory(). */
+	csr->root_kv = csr1212_new_directory(CSR1212_KV_ID_VENDOR);
+	if (!csr->root_kv) {
+		CSR1212_FREE(csr->cache_head);
+		CSR1212_FREE(csr);
+		return NULL;
+	}
+
+	csr->bus_info_data = csr->cache_head->data;
+	csr->bus_info_len = bus_info_size;
+	csr->crc_len = bus_info_size;
+	csr->ops = ops;
+	csr->private = private;
+	csr->cache_tail = csr->cache_head;
+
+	return csr;
+}
+
+
+
+void csr1212_init_local_csr(struct csr1212_csr *csr,
+			    const u_int32_t *bus_info_data, int max_rom)
+{
+	csr->max_rom = max_rom;
+	memcpy(csr->bus_info_data, bus_info_data, csr->bus_info_len);
+}
+
+
+static struct csr1212_keyval *csr1212_new_keyval(u_int8_t type, u_int8_t key)
+{
+	struct csr1212_keyval *kv;
+
+	if (key < 0x30 && ((csr1212_key_id_type_map[key] & (1 << type)) == 0))
+		return NULL;
+
+	kv = CSR1212_MALLOC(sizeof(*kv));
+	if (!kv)
+		return NULL;
+
+	kv->key.type = type;
+	kv->key.id = key;
+
+	kv->associate = NULL;
+	kv->refcnt = 1;
+
+	kv->next = NULL;
+	kv->prev = NULL;
+	kv->offset = 0;
+	kv->valid = 0;
+	return kv;
+}
+
+struct csr1212_keyval *csr1212_new_immediate(u_int8_t key, u_int32_t value)
+{
+	struct csr1212_keyval *kv = csr1212_new_keyval(CSR1212_KV_TYPE_IMMEDIATE, key);
+	
+	if (!kv)
+		return NULL;
+
+	kv->value.immediate = value;
+	kv->valid = 1;
+	return kv;
+}
+
+struct csr1212_keyval *csr1212_new_leaf(u_int8_t key, const void *data, size_t data_len)
+{
+	struct csr1212_keyval *kv = csr1212_new_keyval(CSR1212_KV_TYPE_LEAF, key);
+
+	if (!kv)
+		return NULL;
+	
+	if (data_len > 0) {
+		kv->value.leaf.data = CSR1212_MALLOC(data_len);
+		if (!kv->value.leaf.data)
+		{
+			CSR1212_FREE(kv);
+			return NULL;
+		}
+
+		if (data)
+			memcpy(kv->value.leaf.data, data, data_len);
+	} else {
+		kv->value.leaf.data = NULL;
+	}
+
+	kv->value.leaf.len = bytes_to_quads(data_len);
+	kv->offset = 0;
+	kv->valid = 1;
+
+	return kv;
+}
+
+struct csr1212_keyval *csr1212_new_csr_offset(u_int8_t key, u_int32_t csr_offset)
+{
+	struct csr1212_keyval *kv = csr1212_new_keyval(CSR1212_KV_TYPE_CSR_OFFSET, key);
+
+	if (!kv)
+		return NULL;
+
+	kv->value.csr_offset = csr_offset;
+
+	kv->offset = 0;
+	kv->valid = 1;
+	return kv;
+}
+
+struct csr1212_keyval *csr1212_new_directory(u_int8_t key)
+{
+	struct csr1212_keyval *kv = csr1212_new_keyval(CSR1212_KV_TYPE_DIRECTORY, key);
+
+	if (!kv)
+		return NULL;
+
+	kv->value.directory.len = 0;
+	kv->offset = 0;
+	kv->value.directory.dentries_head = NULL;
+	kv->value.directory.dentries_tail = NULL;
+	kv->valid = 1;
+	return kv;
+}
+
+int csr1212_associate_keyval(struct csr1212_keyval *kv,
+			     struct csr1212_keyval *associate)
+{
+	if (!kv || !associate)
+		return CSR1212_EINVAL;
+
+	if (kv->key.id == CSR1212_KV_ID_DESCRIPTOR ||
+	   (associate->key.id != CSR1212_KV_ID_DESCRIPTOR &&
+	    associate->key.id != CSR1212_KV_ID_DEPENDENT_INFO &&
+	    associate->key.id != CSR1212_KV_ID_EXTENDED_KEY &&
+	    associate->key.id != CSR1212_KV_ID_EXTENDED_DATA &&
+	    associate->key.id < 0x30))
+		return CSR1212_EINVAL;
+
+	if (kv->key.id == CSR1212_KV_ID_EXTENDED_KEY_SPECIFIER_ID &&
+	   associate->key.id != CSR1212_KV_ID_EXTENDED_KEY)
+		return CSR1212_EINVAL;
+
+	if (kv->key.id == CSR1212_KV_ID_EXTENDED_KEY &&
+	   associate->key.id != CSR1212_KV_ID_EXTENDED_DATA)
+		return CSR1212_EINVAL;
+
+	if (associate->key.id == CSR1212_KV_ID_EXTENDED_KEY &&
+	   kv->key.id != CSR1212_KV_ID_EXTENDED_KEY_SPECIFIER_ID)
+		return CSR1212_EINVAL;
+
+	if (associate->key.id == CSR1212_KV_ID_EXTENDED_DATA &&
+	   kv->key.id != CSR1212_KV_ID_EXTENDED_KEY)
+		return CSR1212_EINVAL;
+
+	if (kv->associate)
+		csr1212_release_keyval(kv->associate);
+
+	associate->refcnt++;
+	kv->associate = associate;
+
+	return CSR1212_SUCCESS;
+}
+
+int csr1212_attach_keyval_to_directory(struct csr1212_keyval *dir,
+				       struct csr1212_keyval *kv)
+{
+	struct csr1212_dentry *dentry;
+
+	if (!kv || !dir || dir->key.type != CSR1212_KV_TYPE_DIRECTORY)
+		return CSR1212_EINVAL;
+
+	dentry = CSR1212_MALLOC(sizeof(*dentry));
+	if (!dentry)
+		return CSR1212_ENOMEM;
+
+	dentry->kv = kv;
+
+	kv->refcnt++;
+
+	dentry->next = NULL;
+	dentry->prev = dir->value.directory.dentries_tail;
+
+	if (!dir->value.directory.dentries_head)
+		dir->value.directory.dentries_head = dentry;
+
+	if (dir->value.directory.dentries_tail)
+		dir->value.directory.dentries_tail->next = dentry;
+	dir->value.directory.dentries_tail = dentry;
+
+	return CSR1212_SUCCESS;
+}
+
+struct csr1212_keyval *csr1212_new_extended_immediate(u_int32_t spec, u_int32_t key,
+						      u_int32_t value)
+{
+	struct csr1212_keyval *kvs, *kvk, *kvv;
+
+	kvs = csr1212_new_immediate(CSR1212_KV_ID_EXTENDED_KEY_SPECIFIER_ID, spec);
+	kvk = csr1212_new_immediate(CSR1212_KV_ID_EXTENDED_KEY, key);
+	kvv = csr1212_new_immediate(CSR1212_KV_ID_EXTENDED_DATA, value);
+
+	if (!kvs || !kvk || !kvv) {
+		if (kvs)
+			free_keyval(kvs);
+		if (kvk)
+			free_keyval(kvk);
+		if (kvv)
+			free_keyval(kvv);
+		return NULL;
+	}
+
+	/* Don't keep a local reference to the extended key or value. */
+	kvk->refcnt = 0;
+	kvv->refcnt = 0;
+
+	csr1212_associate_keyval(kvk, kvv);
+	csr1212_associate_keyval(kvs, kvk);
+
+	return kvs;
+}
+
+struct csr1212_keyval *csr1212_new_extended_leaf(u_int32_t spec, u_int32_t key,
+						 const void *data, size_t data_len)
+{
+	struct csr1212_keyval *kvs, *kvk, *kvv;
+
+	kvs = csr1212_new_immediate(CSR1212_KV_ID_EXTENDED_KEY_SPECIFIER_ID, spec);
+	kvk = csr1212_new_immediate(CSR1212_KV_ID_EXTENDED_KEY, key);
+	kvv = csr1212_new_leaf(CSR1212_KV_ID_EXTENDED_DATA, data, data_len);
+
+	if (!kvs || !kvk || !kvv) {
+		if (kvs)
+			free_keyval(kvs);
+		if (kvk)
+			free_keyval(kvk);
+		if (kvv)
+			free_keyval(kvv);
+		return NULL;
+	}
+
+	/* Don't keep a local reference to the extended key or value. */
+	kvk->refcnt = 0;
+	kvv->refcnt = 0;
+
+	csr1212_associate_keyval(kvk, kvv);
+	csr1212_associate_keyval(kvs, kvk);
+
+	return kvs;
+}
+
+struct csr1212_keyval *csr1212_new_descriptor_leaf(u_int8_t dtype, u_int32_t specifier_id,
+						   const void *data, size_t data_len)
+{
+	struct csr1212_keyval *kv;
+
+	kv = csr1212_new_leaf(CSR1212_KV_ID_DESCRIPTOR, NULL,
+			      data_len + CSR1212_DESCRIPTOR_LEAF_OVERHEAD);
+	if (!kv)
+		return NULL;
+
+	CSR1212_DESCRIPTOR_LEAF_SET_TYPE(kv, dtype);
+	CSR1212_DESCRIPTOR_LEAF_SET_SPECIFIER_ID(kv, specifier_id);
+
+	if (data) {
+		memcpy(CSR1212_DESCRIPTOR_LEAF_DATA(kv), data, data_len);
+	}
+
+	return kv;
+}
+
+
+struct csr1212_keyval *csr1212_new_textual_descriptor_leaf(u_int8_t cwidth,
+							   u_int16_t cset,
+							   u_int16_t language,
+							   const void *data,
+							   size_t data_len)
+{
+	struct csr1212_keyval *kv;
+	char *lstr;
+
+	kv = csr1212_new_descriptor_leaf(0, 0, NULL, data_len +
+					 CSR1212_TEXTUAL_DESCRIPTOR_LEAF_OVERHEAD);
+	if (!kv)
+		return NULL;
+
+	CSR1212_TEXTUAL_DESCRIPTOR_LEAF_SET_WIDTH(kv, cwidth);
+	CSR1212_TEXTUAL_DESCRIPTOR_LEAF_SET_CHAR_SET(kv, cset);
+	CSR1212_TEXTUAL_DESCRIPTOR_LEAF_SET_LANGUAGE(kv, language);
+
+	lstr = (char*)CSR1212_TEXTUAL_DESCRIPTOR_LEAF_DATA(kv);
+
+	/* make sure last quadlet is zeroed out */
+	*((u_int32_t*)&(lstr[(data_len - 1) & ~0x3])) = 0;
+
+	/* don't copy the NUL terminator */
+	memcpy(lstr, data, data_len);
+
+	return kv;
+}
+
+static int csr1212_check_minimal_ascii(const char *s)
+{
+	static const char minimal_ascii_table[] = {
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07,
+		0x00, 0x00, 0x0a, 0x00, 0x0C, 0x0D, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x20, 0x21, 0x22, 0x00, 0x00, 0x25, 0x26, 0x27,
+		0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
+		0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+		0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
+		0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
+		0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
+		0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
+		0x58, 0x59, 0x5a, 0x00, 0x00, 0x00, 0x00, 0x5f,
+		0x00, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
+		0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
+		0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
+		0x78, 0x79, 0x7a, 0x00, 0x00, 0x00, 0x00, 0x00,
+	};
+	for (; *s; s++) {
+		if (minimal_ascii_table[*s & 0x7F] != *s)
+			return -1; /* failed */
+	}
+	/* String conforms to minimal-ascii, as specified by IEEE 1212,
+	 * par. 7.4 */
+	return 0;
+}
+
+struct csr1212_keyval *csr1212_new_string_descriptor_leaf(const char *s)
+{
+	/* Check if string conform to minimal_ascii format */
+	if (csr1212_check_minimal_ascii(s))
+		return NULL;
+
+	/* IEEE 1212, par. 7.5.4.1  Textual descriptors (minimal ASCII) */
+	return csr1212_new_textual_descriptor_leaf(0, 0, 0, s, strlen(s));
+}
+
+struct csr1212_keyval *csr1212_new_icon_descriptor_leaf(u_int32_t version,
+							u_int8_t palette_depth,
+							u_int8_t color_space,
+							u_int16_t language,
+							u_int16_t hscan,
+							u_int16_t vscan,
+							u_int32_t *palette,
+							u_int32_t *pixels)
+{
+	static const int pd[4] = { 0, 4, 16, 256 };
+	static const int cs[16] = { 4, 2 };
+	struct csr1212_keyval *kv;
+	int palette_size = pd[palette_depth] * cs[color_space];
+	int pixel_size = (hscan * vscan + 3) & ~0x3;
+
+	if ((palette_depth && !palette) || !pixels)
+		return NULL;
+
+	kv = csr1212_new_descriptor_leaf(1, 0, NULL,
+					 palette_size + pixel_size +
+					 CSR1212_ICON_DESCRIPTOR_LEAF_OVERHEAD);
+	if (!kv)
+		return NULL;
+
+	CSR1212_ICON_DESCRIPTOR_LEAF_SET_VERSION(kv, version);
+	CSR1212_ICON_DESCRIPTOR_LEAF_SET_PALETTE_DEPTH(kv, palette_depth);
+	CSR1212_ICON_DESCRIPTOR_LEAF_SET_COLOR_SPACE(kv, color_space);
+	CSR1212_ICON_DESCRIPTOR_LEAF_SET_LANGUAGE(kv, language);
+	CSR1212_ICON_DESCRIPTOR_LEAF_SET_HSCAN(kv, hscan);
+	CSR1212_ICON_DESCRIPTOR_LEAF_SET_VSCAN(kv, vscan);
+
+	if (palette_size)
+		memcpy(CSR1212_ICON_DESCRIPTOR_LEAF_PALETTE(kv), palette,
+		       palette_size);
+
+	memcpy(CSR1212_ICON_DESCRIPTOR_LEAF_PIXELS(kv), pixels, pixel_size);
+
+	return kv;
+}
+
+struct csr1212_keyval *csr1212_new_modifiable_descriptor_leaf(u_int16_t max_size,
+							      u_int64_t address)
+{
+	struct csr1212_keyval *kv;
+
+	/* IEEE 1212, par. 7.5.4.3  Modifiable descriptors */
+	kv = csr1212_new_leaf(CSR1212_KV_ID_MODIFIABLE_DESCRIPTOR, NULL, sizeof(u_int64_t));
+	if(!kv)
+		return NULL;
+
+	CSR1212_MODIFIABLE_DESCRIPTOR_SET_MAX_SIZE(kv, max_size);
+	CSR1212_MODIFIABLE_DESCRIPTOR_SET_ADDRESS_HI(kv, address);
+	CSR1212_MODIFIABLE_DESCRIPTOR_SET_ADDRESS_LO(kv, address);
+        
+	return kv;
+}
+
+static int csr1212_check_keyword(const char *s)
+{
+	for (; *s; s++) {
+
+		if (('A' <= *s) && (*s <= 'Z'))
+			continue;
+		if (('0' <= *s) && (*s <= '9'))
+			continue;
+		if (*s == '-')
+			continue;
+
+		return -1; /* failed */
+	}
+	/* String conforms to keyword, as specified by IEEE 1212,
+	 * par. 7.6.5 */
+	return CSR1212_SUCCESS;
+}
+
+struct csr1212_keyval *csr1212_new_keyword_leaf(int strc, const char *strv[])
+{
+	struct csr1212_keyval *kv;
+	char *buffer;
+	int i, data_len = 0;
+
+	/* Check all keywords to see if they conform to restrictions:
+	 * Only the following characters is allowed ['A'..'Z','0'..'9','-']
+	 * Each word is zero-terminated.
+	 * Also calculate the total length of the keywords.
+	 */
+	for (i = 0; i < strc; i++) {
+		if (!strv[i] || csr1212_check_keyword(strv[i])) {
+			return NULL;
+		}
+		data_len += strlen(strv[i]) + 1; /* Add zero-termination char. */
+	}
+
+	/* IEEE 1212, par. 7.6.5 Keyword leaves */
+	kv = csr1212_new_leaf(CSR1212_KV_ID_KEYWORD, NULL, data_len);
+	if (!kv)
+		return NULL;
+
+	buffer = (char *)kv->value.leaf.data;
+
+	/* make sure last quadlet is zeroed out */
+	*((u_int32_t*)&(buffer[(data_len - 1) & ~0x3])) = 0;
+	
+	/* Copy keyword(s) into leaf data buffer */
+	for (i = 0; i < strc; i++) {
+		int len = strlen(strv[i]) + 1;
+		memcpy(buffer, strv[i], len);
+		buffer += len;
+	}
+	return kv;
+}
+
+
+/* Destruction Routines */
+
+void csr1212_detach_keyval_from_directory(struct csr1212_keyval *dir,
+					  struct csr1212_keyval *kv)
+{
+	struct csr1212_dentry *dentry;
+
+	if (!kv || !dir || dir->key.type != CSR1212_KV_TYPE_DIRECTORY)
+		return;
+
+	dentry = csr1212_find_keyval(dir, kv);
+	
+	if (!dentry)
+		return;
+
+	if (dentry->prev)
+		dentry->prev->next = dentry->next;
+	if (dentry->next)
+		dentry->next->prev = dentry->prev;
+	if (dir->value.directory.dentries_head == dentry)
+		dir->value.directory.dentries_head = dentry->next;
+	if (dir->value.directory.dentries_tail == dentry)
+		dir->value.directory.dentries_tail = dentry->prev;
+
+	CSR1212_FREE(dentry);
+
+	csr1212_release_keyval(kv);
+}
+
+
+void csr1212_disassociate_keyval(struct csr1212_keyval *kv)
+{
+	if (kv->associate) {
+		csr1212_release_keyval(kv->associate);
+	}
+
+	kv->associate = NULL;
+}
+
+
+/* This function is used to free the memory taken by a keyval.  If the given
+ * keyval is a directory type, then any keyvals contained in that directory
+ * will be destroyed as well if their respective refcnts are 0.  By means of
+ * list manipulation, this routine will descend a directory structure in a
+ * non-recursive manner. */
+void _csr1212_destroy_keyval(struct csr1212_keyval *kv)
+{
+	struct csr1212_keyval *k, *a;
+	struct csr1212_dentry dentry;
+	struct csr1212_dentry *head, *tail;
+
+	dentry.kv = kv;
+	dentry.next = NULL;
+	dentry.prev = NULL;
+
+	head = &dentry;
+	tail = head;
+
+	while (head) {
+		k = head->kv;
+
+		while (k) {
+			k->refcnt--;
+
+			if (k->refcnt > 0)
+				break;
+
+			a = k->associate;
+
+			if (k->key.type == CSR1212_KV_TYPE_DIRECTORY) {
+				/* If the current entry is a directory, then move all
+				 * the entries to the destruction list. */
+				tail->next = k->value.directory.dentries_head;
+				if (k->value.directory.dentries_head)
+					k->value.directory.dentries_head->prev = tail;
+				tail = k->value.directory.dentries_tail;
+			}
+			free_keyval(k);
+			k = a;
+		}
+
+		head = head->next;
+		if (head) {
+			if (head->prev && head->prev != &dentry) {
+				CSR1212_FREE(head->prev);
+			}
+			head->prev = NULL;
+		} else if (tail != &dentry)
+			CSR1212_FREE(tail);
+	}
+}
+
+
+void csr1212_destroy_csr(struct csr1212_csr *csr)
+{
+	struct csr1212_csr_rom_cache *c, *oc;
+	struct csr1212_cache_region *cr, *ocr;
+
+	csr1212_release_keyval(csr->root_kv);
+
+	c = csr->cache_head;
+	while (c) {
+		oc = c;
+		cr = c->filled_head;
+		while (cr) {
+			ocr = cr;
+			cr = cr->next;
+			CSR1212_FREE(ocr);
+		}
+		c = c->next;
+		CSR1212_FREE(oc);
+	}
+
+	CSR1212_FREE(csr);
+}
+
+
+
+/* CSR Image Creation */
+
+static int csr1212_append_new_cache(struct csr1212_csr *csr, size_t romsize)
+{
+	struct csr1212_csr_rom_cache *cache;
+	u_int64_t csr_addr;
+
+	if (!csr || !csr->ops->allocate_addr_range ||
+	    !csr->ops->release_addr)
+		return CSR1212_ENOMEM;
+
+	/* ROM size must be a multiple of csr->max_rom */
+	romsize = (romsize + (csr->max_rom - 1)) & ~(csr->max_rom - 1);
+
+	csr_addr = csr->ops->allocate_addr_range(romsize, csr->max_rom, csr->private);
+	if (csr_addr == ~0ULL) {
+		return CSR1212_ENOMEM;
+	}
+	if (csr_addr < CSR1212_REGISTER_SPACE_BASE) {
+		/* Invalid address returned from allocate_addr_range(). */
+		csr->ops->release_addr(csr_addr, csr->private);
+		return CSR1212_ENOMEM;
+	}
+
+	cache = csr1212_rom_cache_malloc(csr_addr - CSR1212_REGISTER_SPACE_BASE, romsize);
+	if (!cache) {
+		csr->ops->release_addr(csr_addr, csr->private);
+		return CSR1212_ENOMEM;
+	}
+
+	cache->ext_rom = csr1212_new_keyval(CSR1212_KV_TYPE_LEAF, CSR1212_KV_ID_EXTENDED_ROM);
+	if (!cache->ext_rom) {
+		csr->ops->release_addr(csr_addr, csr->private);
+		CSR1212_FREE(cache);
+		return CSR1212_ENOMEM;
+	}
+
+	if (csr1212_attach_keyval_to_directory(csr->root_kv, cache->ext_rom) != CSR1212_SUCCESS)
+	{
+		csr1212_release_keyval(cache->ext_rom);
+		csr->ops->release_addr(csr_addr, csr->private);
+		CSR1212_FREE(cache);
+		return CSR1212_ENOMEM;
+	}
+	cache->ext_rom->offset = csr_addr - CSR1212_REGISTER_SPACE_BASE;
+	cache->ext_rom->value.leaf.len = 0;
+
+	/* Add cache to tail of cache list */
+	cache->prev = csr->cache_tail;
+	csr->cache_tail->next = cache;
+	csr->cache_tail = cache;
+	return CSR1212_SUCCESS;
+}
+
+static inline void csr1212_remove_cache(struct csr1212_csr *csr,
+					struct csr1212_csr_rom_cache *cache)
+{
+	if (csr->cache_head == cache)
+		csr->cache_head = cache->next;
+	if (csr->cache_tail == cache)
+		csr->cache_tail = cache->prev;
+
+	if (cache->prev)
+		cache->prev->next = cache->next;
+	if (cache->next)
+		cache->next->prev = cache->prev;
+
+	if (cache->ext_rom) {
+		csr1212_detach_keyval_from_directory(csr->root_kv, cache->ext_rom);
+		csr1212_release_keyval(cache->ext_rom);
+	}
+
+	CSR1212_FREE(cache);
+}
+
+static int csr1212_generate_layout_subdir(struct csr1212_keyval *dir,
+					  struct csr1212_keyval **layout_tail)
+{
+	struct csr1212_dentry *dentry;
+	struct csr1212_keyval *dkv;
+	struct csr1212_keyval *last_extkey_spec = NULL;
+	struct csr1212_keyval *last_extkey = NULL;
+	int num_entries = 0;
+
+	for (dentry = dir->value.directory.dentries_head; dentry;
+	     dentry = dentry->next) {
+		for (dkv = dentry->kv; dkv; dkv = dkv->associate) {
+			/* Special Case: Extended Key Specifier_ID */
+			if (dkv->key.id == CSR1212_KV_ID_EXTENDED_KEY_SPECIFIER_ID) {
+				if (last_extkey_spec == NULL) {
+					last_extkey_spec = dkv;
+				} else if (dkv->value.immediate != last_extkey_spec->value.immediate) {
+					last_extkey_spec = dkv;
+				} else {
+					continue;
+				}
+			/* Special Case: Extended Key */
+			} else if (dkv->key.id == CSR1212_KV_ID_EXTENDED_KEY) {
+				if (last_extkey == NULL) {
+					last_extkey = dkv;
+				} else if (dkv->value.immediate != last_extkey->value.immediate) {
+					last_extkey = dkv;
+				} else {
+					continue;
+				}
+			}
+
+			num_entries += 1;
+
+			switch(dkv->key.type) {
+			default:
+			case CSR1212_KV_TYPE_IMMEDIATE:
+			case CSR1212_KV_TYPE_CSR_OFFSET:
+				continue;
+			case CSR1212_KV_TYPE_LEAF:
+			case CSR1212_KV_TYPE_DIRECTORY:
+				/* Remove from list */
+				if (dkv->prev)
+					dkv->prev->next = dkv->next;
+				if (dkv->next)
+					dkv->next->prev = dkv->prev;
+				if (dkv == *layout_tail)
+					*layout_tail = dkv->prev;
+
+				/* Special case: Extended ROM leafs */
+				if (dkv->key.id == CSR1212_KV_ID_EXTENDED_ROM) {
+					dkv->value.leaf.len = 0; /* initialize to zero */
+					/* Don't add Extended ROM leafs in the layout list,
+					 * they are handled differently. */
+					break;
+				}
+
+				/* Add to tail of list */
+				dkv->next = NULL;
+				dkv->prev = *layout_tail;
+				(*layout_tail)->next = dkv;
+				*layout_tail = dkv;
+				break;
+			}
+		}
+	}
+	return num_entries;
+}
+
+size_t csr1212_generate_layout_order(struct csr1212_keyval *kv)
+{
+	struct csr1212_keyval *ltail = kv;
+	size_t agg_size = 0;
+
+	while(kv) {
+		switch(kv->key.type) {
+		case CSR1212_KV_TYPE_LEAF:
+			/* Add 1 quadlet for crc/len field */
+			agg_size += kv->value.leaf.len + 1;
+			break;
+
+		case CSR1212_KV_TYPE_DIRECTORY:
+			kv->value.directory.len = csr1212_generate_layout_subdir(kv, &ltail);
+			/* Add 1 quadlet for crc/len field */
+			agg_size += kv->value.directory.len + 1;
+			break;
+		}
+		kv = kv->next;
+	}
+	return quads_to_bytes(agg_size);
+}
+
+struct csr1212_keyval *csr1212_generate_positions(struct csr1212_csr_rom_cache *cache,
+                                                  struct csr1212_keyval *start_kv,
+                                                  int start_pos)
+{
+	struct csr1212_keyval *kv = start_kv;
+	struct csr1212_keyval *okv = start_kv;
+	int pos = start_pos;
+	int kv_len = 0, okv_len = 0;
+
+	cache->layout_head = kv;
+
+	while(kv && pos < cache->size) {
+		kv->offset = cache->offset + pos;
+
+		switch(kv->key.type) {
+		case CSR1212_KV_TYPE_LEAF:
+			kv_len = kv->value.leaf.len;
+			break;
+
+		case CSR1212_KV_TYPE_DIRECTORY:
+			kv_len = kv->value.directory.len;
+			break;
+
+		default:
+			/* Should never get here */
+			break;
+		}
+
+		pos += quads_to_bytes(kv_len + 1);
+
+		if (pos <= cache->size) {
+			okv = kv;
+			okv_len = kv_len;
+			kv = kv->next;
+		}
+	}
+
+	cache->layout_tail = okv;
+	cache->len = (okv->offset - cache->offset) + quads_to_bytes(okv_len + 1);
+
+	return kv;
+}
+
+static void csr1212_generate_tree_subdir(struct csr1212_keyval *dir,
+					 u_int32_t *data_buffer)
+{
+	struct csr1212_dentry *dentry;
+	struct csr1212_keyval *last_extkey_spec = NULL;
+	struct csr1212_keyval *last_extkey = NULL;
+	int index = 0;
+
+	for (dentry = dir->value.directory.dentries_head; dentry; dentry = dentry->next) {
+		struct csr1212_keyval *a;
+
+		for (a = dentry->kv; a; a = a->associate) {
+			u_int32_t value = 0;
+
+			/* Special Case: Extended Key Specifier_ID */
+			if (a->key.id == CSR1212_KV_ID_EXTENDED_KEY_SPECIFIER_ID) {
+				if (last_extkey_spec == NULL) {
+					last_extkey_spec = a;
+				} else if (a->value.immediate != last_extkey_spec->value.immediate) {
+					last_extkey_spec = a;
+				} else {
+					continue;
+				}
+			/* Special Case: Extended Key */
+			} else if (a->key.id == CSR1212_KV_ID_EXTENDED_KEY) {
+				if (last_extkey == NULL) {
+					last_extkey = a;
+				} else if (a->value.immediate != last_extkey->value.immediate) {
+					last_extkey = a;
+				} else {
+					continue;
+				}
+			}
+
+			switch(a->key.type) {
+			case CSR1212_KV_TYPE_IMMEDIATE:
+				value = a->value.immediate;
+				break;
+			case CSR1212_KV_TYPE_CSR_OFFSET:
+				value = a->value.csr_offset;
+				break;
+			case CSR1212_KV_TYPE_LEAF:
+				value = a->offset;
+				value -= dir->offset + quads_to_bytes(1+index);
+				value = bytes_to_quads(value);
+				break;
+			case CSR1212_KV_TYPE_DIRECTORY:
+				value = a->offset;
+				value -= dir->offset + quads_to_bytes(1+index);
+				value = bytes_to_quads(value);
+				break;
+			default:
+				/* Should never get here */
+				break; /* GDB breakpoint */
+			}
+
+			value |= (a->key.id & CSR1212_KV_KEY_ID_MASK) << CSR1212_KV_KEY_SHIFT;
+			value |= (a->key.type & CSR1212_KV_KEY_TYPE_MASK) <<
+				(CSR1212_KV_KEY_SHIFT + CSR1212_KV_KEY_TYPE_SHIFT);
+			data_buffer[index] = CSR1212_CPU_TO_BE32(value);
+			index++;
+		}
+	}
+}
+
+void csr1212_fill_cache(struct csr1212_csr_rom_cache *cache)
+{
+	struct csr1212_keyval *kv, *nkv;
+	struct csr1212_keyval_img *kvi;
+
+	for (kv = cache->layout_head; kv != cache->layout_tail->next; kv = nkv) {
+		kvi = (struct csr1212_keyval_img *)
+			(cache->data + bytes_to_quads(kv->offset - cache->offset));
+		switch(kv->key.type) {
+		default:
+		case CSR1212_KV_TYPE_IMMEDIATE:
+		case CSR1212_KV_TYPE_CSR_OFFSET:
+			/* Should never get here */
+			break; /* GDB breakpoint */
+
+		case CSR1212_KV_TYPE_LEAF:
+			/* Don't copy over Extended ROM areas, they are
+			 * already filled out! */
+			if (kv->key.id != CSR1212_KV_ID_EXTENDED_ROM)
+				memcpy(kvi->data, kv->value.leaf.data,
+				       quads_to_bytes(kv->value.leaf.len));
+
+			kvi->length = CSR1212_CPU_TO_BE16(kv->value.leaf.len);
+			kvi->crc = csr1212_crc16(kvi->data, kv->value.leaf.len);
+			break;
+
+		case CSR1212_KV_TYPE_DIRECTORY:
+			csr1212_generate_tree_subdir(kv, kvi->data);
+
+			kvi->length = CSR1212_CPU_TO_BE16(kv->value.directory.len);
+			kvi->crc = csr1212_crc16(kvi->data, kv->value.directory.len);
+			break;
+		}
+
+		nkv = kv->next;
+		kv->prev = NULL;
+		kv->next = NULL;
+	}
+}
+
+int csr1212_generate_csr_image(struct csr1212_csr *csr)
+{
+	struct csr1212_bus_info_block_img *bi;
+	struct csr1212_csr_rom_cache *cache;
+	struct csr1212_keyval *kv;
+	size_t agg_size;
+	int ret;
+	int init_offset;
+
+	if (!csr)
+		return CSR1212_EINVAL;
+
+	cache = csr->cache_head;
+
+	bi = (struct csr1212_bus_info_block_img*)cache->data;
+
+	bi->length = bytes_to_quads(csr->bus_info_len) - 1;
+	bi->crc_length = bi->length;
+	bi->crc = csr1212_crc16(bi->data, bi->crc_length);
+
+	agg_size = csr1212_generate_layout_order(csr->root_kv);
+
+	init_offset = csr->bus_info_len;
+
+	for (kv = csr->root_kv, cache = csr->cache_head; kv; cache = cache->next) {
+		if (!cache) {
+			/* Estimate approximate number of additional cache
+			 * regions needed (it assumes that the cache holding
+			 * the first 1K Config ROM space always exists). */
+			int est_c = agg_size / (CSR1212_EXTENDED_ROM_SIZE -
+						(2 * sizeof(u_int32_t))) + 1;
+
+			/* Add additional cache regions, extras will be
+			 * removed later */
+			for (; est_c; est_c--) {
+				ret = csr1212_append_new_cache(csr, CSR1212_EXTENDED_ROM_SIZE);
+				if (ret != CSR1212_SUCCESS)
+					return ret;
+			}
+			/* Need to re-layout for additional cache regions */
+			agg_size = csr1212_generate_layout_order(csr->root_kv);
+			kv = csr->root_kv;
+			cache = csr->cache_head;
+			init_offset = csr->bus_info_len;
+		}
+		kv = csr1212_generate_positions(cache, kv, init_offset);
+		agg_size -= cache->len;
+		init_offset = sizeof(u_int32_t);
+	}
+
+	/* Remove unused, excess cache regions */
+	while (cache) {
+		struct csr1212_csr_rom_cache *oc = cache;
+		
+		cache = cache->next;
+		csr1212_remove_cache(csr, oc);
+	}
+
+
+	/* Go through the list backward so that when done, the correct CRC
+	 * will be calculated for the Extended ROM areas. */
+	for(cache = csr->cache_tail; cache; cache = cache->prev) {
+		/* Only Extended ROM caches should have this set. */
+		if (cache->ext_rom) {
+			int leaf_size;
+
+			/* Make sure the Extended ROM leaf is a multiple of
+			 * max_rom in size. */
+			leaf_size = (cache->len + (csr->max_rom - 1)) &
+				(csr->max_rom - 1);
+
+			/* Zero out the unused ROM region */
+			memset(cache->data + bytes_to_quads(cache->len), 0x00,
+			       leaf_size - cache->len);
+
+			/* Subtract leaf header */
+			leaf_size -= sizeof(u_int32_t);
+
+			/* Update the Extended ROM leaf length */
+			cache->ext_rom->value.leaf.len =
+				bytes_to_quads(leaf_size);
+		} else {
+			/* Zero out the unused ROM region */
+			memset(cache->data + bytes_to_quads(cache->len), 0x00,
+			       cache->size - cache->len);
+		}
+
+		/* Copy the data into the cache buffer */
+		csr1212_fill_cache(cache);
+	}
+
+	return CSR1212_SUCCESS;
+}
+
+int csr1212_read(struct csr1212_csr *csr, u_int32_t offset, void *buffer, u_int32_t len)
+{
+	struct csr1212_csr_rom_cache *cache;
+
+	for (cache = csr->cache_head; cache; cache = cache->next) {
+		if (offset >= cache->offset &&
+		    (offset + len) <= (cache->offset + cache->size)) {
+			memcpy(buffer,
+			       &cache->data[bytes_to_quads(offset - cache->offset)],
+			       len);
+			return CSR1212_SUCCESS;
+		} else if (((offset < cache->offset) &&
+			    ((offset + len) >= cache->offset)) ||
+			   ((offset >= cache->offset) &&
+			    ((offset + len) > (cache->offset + cache->size)))) {
+			return CSR1212_EINVAL;
+		}
+	}
+	return CSR1212_ENOENT;
+}
+
+
+
+/* Parse a chunk of data as a Config ROM */
+
+static int csr1212_parse_bus_info_block(struct csr1212_csr *csr)
+{
+	struct csr1212_bus_info_block_img *bi;
+	struct csr1212_cache_region *cr;
+	int i;
+	int ret;
+
+	/* IEEE 1212 says that the entire bus info block should be readable in
+	 * a single transaction regardless of the max_rom value.
+	 * Unfortunately, many IEEE 1394 devices do not abide by that, so the
+	 * bus info block will be read 1 quadlet at a time.  The rest of the
+	 * ConfigROM will be read according to the max_rom field. */
+	for (i = 0; i < csr->bus_info_len; i += sizeof(csr1212_quad_t)) {
+		ret = csr->ops->bus_read(csr, CSR1212_CONFIG_ROM_SPACE_BASE + i,
+					 sizeof(csr1212_quad_t),
+					 &csr->cache_head->data[bytes_to_quads(i)],
+					 csr->private);
+		if (ret != CSR1212_SUCCESS)
+			return ret;
+	}
+
+	bi = (struct csr1212_bus_info_block_img*)csr->cache_head->data;
+	csr->crc_len = quads_to_bytes(bi->crc_length);
+
+	/* IEEE 1212 recommends that crc_len be equal to bus_info_len, but that is not
+	 * always the case, so read the rest of the crc area 1 quadlet at a time. */
+	for (i = csr->bus_info_len; i <= csr->crc_len; i += sizeof(csr1212_quad_t)) {
+		ret = csr->ops->bus_read(csr, CSR1212_CONFIG_ROM_SPACE_BASE + i,
+					 sizeof(csr1212_quad_t),
+					 &csr->cache_head->data[bytes_to_quads(i)],
+					 csr->private);
+		if (ret != CSR1212_SUCCESS)
+			return ret;
+	}
+
+	if (bytes_to_quads(csr->bus_info_len - sizeof(csr1212_quad_t)) != bi->length)
+		return CSR1212_EINVAL;
+
+#if 0
+        /* Apparently there are too many differnt wrong implementations of the
+         * CRC algorithm that verifying them is moot. */
+	if ((csr1212_crc16(bi->data, bi->crc_length) != bi->crc) &&
+	    (csr1212_msft_crc16(bi->data, bi->crc_length) != bi->crc))
+		return CSR1212_EINVAL;
+#endif
+
+	cr = CSR1212_MALLOC(sizeof(struct csr1212_cache_region));
+	if (!cr)
+		return CSR1212_ENOMEM;
+
+	cr->next = NULL;
+	cr->prev = NULL;
+	cr->offset_start = 0;
+	cr->offset_end = csr->crc_len + 4;
+
+	csr->cache_head->filled_head = cr;
+	csr->cache_head->filled_tail = cr;
+
+	return CSR1212_SUCCESS;
+}
+
+static inline int csr1212_parse_dir_entry(struct csr1212_keyval *dir,
+					  csr1212_quad_t ki,
+					  u_int32_t kv_pos,
+					  struct csr1212_csr_rom_cache *cache)
+{
+	int ret = CSR1212_SUCCESS;
+	struct csr1212_keyval *k = NULL;
+	u_int32_t offset;
+
+	switch(CSR1212_KV_KEY_TYPE(ki)) {
+	case CSR1212_KV_TYPE_IMMEDIATE:
+		k = csr1212_new_immediate(CSR1212_KV_KEY_ID(ki),
+					  CSR1212_KV_VAL(ki));
+		if (!k) {
+			ret = CSR1212_ENOMEM;
+			goto fail;
+		}
+		
+		k->refcnt = 0;	/* Don't keep local reference when parsing. */
+		break;
+
+	case CSR1212_KV_TYPE_CSR_OFFSET:
+		k = csr1212_new_csr_offset(CSR1212_KV_KEY_ID(ki),
+					   CSR1212_KV_VAL(ki));
+		if (!k) {
+			ret = CSR1212_ENOMEM;
+			goto fail;
+		}
+		k->refcnt = 0;	/* Don't keep local reference when parsing. */
+		break;
+
+	default:
+		/* Compute the offset from 0xffff f000 0000. */
+		offset = quads_to_bytes(CSR1212_KV_VAL(ki)) + kv_pos;
+		if (offset == kv_pos) {
+			/* Uh-oh.  Can't have a relative offset of 0 for Leaves
+			 * or Directories.  The Config ROM image is most likely
+			 * messed up, so we'll just abort here. */
+			ret = CSR1212_EIO;
+			goto fail;
+		}
+
+		k = csr1212_find_keyval_offset(cache->layout_head, offset);
+
+		if (k)
+			break;		/* Found it. */
+
+		if (CSR1212_KV_KEY_TYPE(ki) == CSR1212_KV_TYPE_DIRECTORY) {
+			k = csr1212_new_directory(CSR1212_KV_KEY_ID(ki));
+		} else {
+			k = csr1212_new_leaf(CSR1212_KV_KEY_ID(ki), NULL, 0);
+		}
+		if (!k) {
+			ret = CSR1212_ENOMEM;
+			goto fail;
+		}
+		k->refcnt = 0;	/* Don't keep local reference when parsing. */
+		k->valid = 0;	/* Contents not read yet so it's not valid. */
+		k->offset = offset;
+
+		k->prev = cache->layout_tail;
+		k->next = NULL;
+		if (cache->layout_tail)
+			cache->layout_tail->next = k;
+		cache->layout_tail = k;
+	}
+	ret = csr1212_attach_keyval_to_directory(dir, k);
+
+fail:
+	if (ret != CSR1212_SUCCESS) {
+		if (k)
+			free_keyval(k);
+	}
+	return ret;
+}
+
+int csr1212_parse_keyval(struct csr1212_keyval *kv,
+			 struct csr1212_csr_rom_cache *cache)
+{
+	struct csr1212_keyval_img *kvi;
+	int i;
+	int ret = CSR1212_SUCCESS;
+	int kvi_len;
+
+	kvi = (struct csr1212_keyval_img*)&cache->data[bytes_to_quads(kv->offset -
+								      cache->offset)];
+	kvi_len = CSR1212_BE16_TO_CPU(kvi->length);
+
+#if 0
+        /* Apparently there are too many differnt wrong implementations of the
+         * CRC algorithm that verifying them is moot. */
+	if ((csr1212_crc16(kvi->data, kvi_len) != kvi->crc) &&
+	    (csr1212_msft_crc16(kvi->data, kvi_len) != kvi->crc)) {
+		ret = CSR1212_EINVAL;
+		goto fail;
+	}
+#endif
+
+	switch(kv->key.type) {
+	case CSR1212_KV_TYPE_DIRECTORY:
+		for (i = 0; i < kvi_len; i++) {
+			csr1212_quad_t ki = kvi->data[i];
+			ret = csr1212_parse_dir_entry(kv, ki,
+						      (kv->offset +
+						       quads_to_bytes(i + 1)),
+						      cache);
+		}
+		kv->value.directory.len = kvi_len;
+		break;
+
+	case CSR1212_KV_TYPE_LEAF:
+		if (kv->key.id == CSR1212_KV_ID_EXTENDED_ROM) {
+			kv->value.leaf.data = cache->data;
+		} else {
+			kv->value.leaf.data = CSR1212_MALLOC(quads_to_bytes(kvi_len));
+			if (!kv->value.leaf.data)
+			{
+				ret = CSR1212_ENOMEM;
+				goto fail;
+			}
+
+			kv->value.leaf.len = kvi_len;
+			memcpy(kv->value.leaf.data, kvi->data, quads_to_bytes(kvi_len));
+		}
+		break;
+	}
+
+	kv->valid = 1;
+
+fail:
+	return ret;
+}
+
+
+int _csr1212_read_keyval(struct csr1212_csr *csr, struct csr1212_keyval *kv)
+{
+	struct csr1212_cache_region *cr, *ncr, *newcr = NULL;
+	struct csr1212_keyval_img *kvi = NULL;
+	struct csr1212_csr_rom_cache *cache;
+	int cache_index;
+	u_int64_t addr;
+	u_int32_t *cache_ptr;
+	u_int16_t kv_len = 0;
+
+
+	if (!csr || !kv)
+		return CSR1212_EINVAL;
+
+	/* First find which cache the data should be in (or go in if not read
+	 * yet). */
+	for (cache = csr->cache_head; cache; cache = cache->next) {
+		if (kv->offset >= cache->offset &&
+		    kv->offset < (cache->offset + cache->size))
+			break;
+	}
+
+	if (!cache) {
+		csr1212_quad_t q;
+		struct csr1212_csr_rom_cache *nc;
+
+		/* Only create a new cache for Extended ROM leaves. */
+		if (kv->key.id != CSR1212_KV_ID_EXTENDED_ROM)
+			return CSR1212_EINVAL;
+
+		if (csr->ops->bus_read(csr,
+				       CSR1212_REGISTER_SPACE_BASE + kv->offset,
+				       sizeof(csr1212_quad_t), &q, csr->private)) {
+			return CSR1212_EIO;
+		}
+
+		kv->value.leaf.len = quads_to_bytes(CSR1212_BE32_TO_CPU(q)>>16);
+
+		nc = csr1212_rom_cache_malloc(kv->offset, kv->value.leaf.len);
+		cache->next = nc;
+		nc->prev = cache;
+		csr->cache_tail = nc;
+		cache->filled_head =
+			CSR1212_MALLOC(sizeof(struct csr1212_cache_region));
+		if (!cache->filled_head) {
+			return CSR1212_ENOMEM;
+		}
+
+		cache->filled_head->offset_start = 0;
+		cache->filled_head->offset_end = sizeof(csr1212_quad_t);
+		cache->filled_tail = cache->filled_head;
+		cache->filled_head->next = NULL;
+		cache->filled_head->prev = NULL;
+		cache->data[0] = q;
+	}
+
+	cache_index = kv->offset - cache->offset;
+
+	/* Now seach read portions of the cache to see if it is there. */
+	for (cr = cache->filled_head; cr; cr = cr->next) {
+		if (cache_index < cr->offset_start) {
+			newcr = CSR1212_MALLOC(sizeof(struct csr1212_cache_region));
+			if (!newcr)
+				return CSR1212_ENOMEM;
+			
+			newcr->offset_start = cache_index & ~(csr->max_rom - 1);
+			newcr->offset_end = newcr->offset_start;
+			newcr->next = cr;
+			newcr->prev = cr->prev;
+			cr->prev = newcr;
+			cr = newcr;
+			break;
+		} else if ((cache_index >= cr->offset_start) &&
+			   (cache_index < cr->offset_end)) {
+			kvi = (struct csr1212_keyval_img*)
+				(&cache->data[bytes_to_quads(cache_index)]);
+			kv_len = quads_to_bytes(CSR1212_BE16_TO_CPU(kvi->length) +
+						1);
+			break;
+		} else if (cache_index == cr->offset_end)
+			break;
+	}
+
+	if (!cr) {
+		cr = cache->filled_tail;
+		newcr = CSR1212_MALLOC(sizeof(struct csr1212_cache_region));
+		if (!newcr)
+			return CSR1212_ENOMEM;
+			
+		newcr->offset_start = cache_index & ~(csr->max_rom - 1);
+		newcr->offset_end = newcr->offset_start;
+		newcr->prev = cr;
+		newcr->next = cr->next;
+		cr->next = newcr;
+		cr = newcr;
+		cache->filled_tail = newcr;
+	}
+
+	while(!kvi || cr->offset_end < cache_index + kv_len) {
+		cache_ptr = &cache->data[bytes_to_quads(cr->offset_end &
+							~(csr->max_rom - 1))];
+
+		addr = (CSR1212_CSR_ARCH_REG_SPACE_BASE + cache->offset +
+			cr->offset_end) & ~(csr->max_rom - 1);
+
+		if (csr->ops->bus_read(csr, addr, csr->max_rom, cache_ptr,
+				       csr->private)) {
+			if (csr->max_rom == 4)
+				/* We've got problems! */
+				return CSR1212_EIO;
+
+			/* Apperently the max_rom value was a lie, set it to
+			 * do quadlet reads and try again. */
+			csr->max_rom = 4;
+			continue;
+		}
+
+		cr->offset_end += csr->max_rom - (cr->offset_end &
+						  (csr->max_rom - 1));
+
+		if (!kvi && (cr->offset_end > cache_index)) {
+			kvi = (struct csr1212_keyval_img*)
+				(&cache->data[bytes_to_quads(cache_index)]);
+			kv_len = quads_to_bytes(CSR1212_BE16_TO_CPU(kvi->length) +
+						1);
+		}
+
+		if ((kv_len + (kv->offset - cache->offset)) > cache->size) {
+			/* The Leaf or Directory claims its length extends
+			 * beyond the ConfigROM image region and thus beyond the
+			 * end of our cache region.  Therefore, we abort now
+			 * rather than seg faulting later. */
+			return CSR1212_EIO;
+		}
+
+		ncr = cr->next;
+
+		if (ncr && (cr->offset_end >= ncr->offset_start)) {
+			/* consolidate region entries */
+			ncr->offset_start = cr->offset_start;
+
+			if (cr->prev)
+				cr->prev->next = cr->next;
+			ncr->prev = cr->prev;
+			if (cache->filled_head == cr)
+				cache->filled_head = ncr;
+			CSR1212_FREE(cr);
+			cr = ncr;
+		}
+	}
+
+	return csr1212_parse_keyval(kv, cache);
+}
+
+
+
+int csr1212_parse_csr(struct csr1212_csr *csr)
+{
+	static const int mr_map[] = { 4, 64, 1024, 0 };
+	int ret;
+
+	if (!csr || !csr->ops->bus_read)
+		return CSR1212_EINVAL;
+
+	ret = csr1212_parse_bus_info_block(csr);
+	if (ret != CSR1212_SUCCESS)
+		return ret;
+
+	if (!csr->ops->get_max_rom)
+		csr->max_rom = mr_map[0];	/* default value */
+	else
+		csr->max_rom = mr_map[csr->ops->get_max_rom(csr->bus_info_data,
+							    csr->private)];
+
+	csr->cache_head->layout_head = csr->root_kv;
+	csr->cache_head->layout_tail = csr->root_kv;
+
+	csr->root_kv->offset = (CSR1212_CONFIG_ROM_SPACE_BASE & 0xffff) +
+		csr->bus_info_len;
+
+	csr->root_kv->valid = 0;
+	csr1212_get_keyval(csr, csr->root_kv);
+
+	return CSR1212_SUCCESS;
+}
--- diff/drivers/ieee1394/csr1212.h	1970-01-01 01:00:00.000000000 +0100
+++ source/drivers/ieee1394/csr1212.h	2004-02-23 13:56:41.000000000 +0000
@@ -0,0 +1,724 @@
+/*
+ * csr1212.h -- IEEE 1212 Control and Status Register support for Linux
+ * 
+ * Copyright (C) 2003 Francois Retief <fgretief@sun.ac.za>
+ *                    Steve Kinneberg <kinnebergsteve@acmsystems.com>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *    1. Redistributions of source code must retain the above copyright notice,
+ *       this list of conditions and the following disclaimer.
+ *    2. Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *    3. The name of the author may not be used to endorse or promote products
+ *       derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __CSR1212_H__
+#define __CSR1212_H__
+
+
+/* Compatibility layer */
+#ifdef __KERNEL__
+
+#include <linux/types.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+
+#define CSR1212_MALLOC(size)		kmalloc((size), in_interrupt() ? GFP_ATOMIC : GFP_KERNEL)
+#define CSR1212_FREE(ptr)		kfree(ptr)
+#define CSR1212_BE16_TO_CPU(quad)	be16_to_cpu(quad)
+#define CSR1212_CPU_TO_BE16(quad)	cpu_to_be16(quad)
+#define CSR1212_BE32_TO_CPU(quad)	be32_to_cpu(quad)
+#define CSR1212_CPU_TO_BE32(quad)	cpu_to_be32(quad)
+#define CSR1212_BE64_TO_CPU(quad)	be64_to_cpu(quad)
+#define CSR1212_CPU_TO_BE64(quad)	cpu_to_be64(quad)
+
+#define CSR1212_LE16_TO_CPU(quad)	le16_to_cpu(quad)
+#define CSR1212_CPU_TO_LE16(quad)	cpu_to_le16(quad)
+#define CSR1212_LE32_TO_CPU(quad)	le32_to_cpu(quad)
+#define CSR1212_CPU_TO_LE32(quad)	cpu_to_le32(quad)
+#define CSR1212_LE64_TO_CPU(quad)	le64_to_cpu(quad)
+#define CSR1212_CPU_TO_LE64(quad)	cpu_to_le64(quad)
+
+#include <linux/errno.h>
+#define CSR1212_SUCCESS (0)
+#define CSR1212_EINVAL	(-EINVAL)
+#define CSR1212_ENOMEM	(-ENOMEM)
+#define CSR1212_ENOENT	(-ENOENT)
+#define CSR1212_EIO	(-EIO)
+#define CSR1212_EBUSY	(-EBUSY)
+
+#else	/* Userspace */
+
+#include <sys/types.h>
+#include <malloc.h>
+#define CSR1212_MALLOC(size)		malloc(size)
+#define CSR1212_FREE(ptr)		free(ptr)
+#include <endian.h>
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+#include <byteswap.h>
+#define CSR1212_BE16_TO_CPU(quad)	bswap_16(quad)
+#define CSR1212_CPU_TO_BE16(quad)	bswap_16(quad)
+#define CSR1212_BE32_TO_CPU(quad)	bswap_32(quad)
+#define CSR1212_CPU_TO_BE32(quad)	bswap_32(quad)
+#define CSR1212_BE64_TO_CPU(quad)	bswap_64(quad)
+#define CSR1212_CPU_TO_BE64(quad)	bswap_64(quad)
+
+#define CSR1212_LE16_TO_CPU(quad)	(quad)
+#define CSR1212_CPU_TO_LE16(quad)	(quad)
+#define CSR1212_LE32_TO_CPU(quad)	(quad)
+#define CSR1212_CPU_TO_LE32(quad)	(quad)
+#define CSR1212_LE64_TO_CPU(quad)	(quad)
+#define CSR1212_CPU_TO_LE64(quad)	(quad)
+#else
+#define CSR1212_BE16_TO_CPU(quad)	(quad)
+#define CSR1212_CPU_TO_BE16(quad)	(quad)
+#define CSR1212_BE32_TO_CPU(quad)	(quad)
+#define CSR1212_CPU_TO_BE32(quad)	(quad)
+#define CSR1212_BE64_TO_CPU(quad)	(quad)
+#define CSR1212_CPU_TO_BE64(quad)	(quad)
+
+#define CSR1212_LE16_TO_CPU(quad)	bswap_16(quad)
+#define CSR1212_CPU_TO_LE16(quad)	bswap_16(quad)
+#define CSR1212_LE32_TO_CPU(quad)	bswap_32(quad)
+#define CSR1212_CPU_TO_LE32(quad)	bswap_32(quad)
+#define CSR1212_LE64_TO_CPU(quad)	bswap_64(quad)
+#define CSR1212_CPU_TO_LE64(quad)	bswap_64(quad)
+#endif
+
+#include <errno.h>
+#define CSR1212_SUCCESS (0)
+#define CSR1212_EINVAL	(EINVAL)
+#define CSR1212_ENOMEM	(ENOMEM)
+#define CSR1212_ENOENT	(ENOENT)
+#define CSR1212_EIO	(EIO)
+#define CSR1212_EBUSY	(EBUSY)
+
+#endif
+
+
+#define CSR1212_KV_VAL_MASK			0xffffff
+#define CSR1212_KV_KEY_SHIFT			24
+#define CSR1212_KV_KEY_TYPE_SHIFT		6
+#define CSR1212_KV_KEY_ID_MASK			0x3f
+#define CSR1212_KV_KEY_TYPE_MASK		0x3		/* After shift */
+
+
+/* CSR 1212 key types */
+#define CSR1212_KV_TYPE_IMMEDIATE		0
+#define CSR1212_KV_TYPE_CSR_OFFSET		1
+#define CSR1212_KV_TYPE_LEAF			2
+#define CSR1212_KV_TYPE_DIRECTORY		3
+
+
+/* CSR 1212 key ids */
+#define CSR1212_KV_ID_DESCRIPTOR		0x01
+#define CSR1212_KV_ID_BUS_DEPENDENT_INFO	0x02
+#define CSR1212_KV_ID_VENDOR			0x03
+#define CSR1212_KV_ID_HARDWARE_VERSION		0x04
+#define CSR1212_KV_ID_MODULE			0x07
+#define CSR1212_KV_ID_NODE_CAPABILITIES		0x0C
+#define CSR1212_KV_ID_EUI_64			0x0D
+#define CSR1212_KV_ID_UNIT			0x11
+#define CSR1212_KV_ID_SPECIFIER_ID		0x12
+#define CSR1212_KV_ID_VERSION			0x13
+#define CSR1212_KV_ID_DEPENDENT_INFO		0x14
+#define CSR1212_KV_ID_UNIT_LOCATION		0x15
+#define CSR1212_KV_ID_MODEL			0x17
+#define CSR1212_KV_ID_INSTANCE			0x18
+#define CSR1212_KV_ID_KEYWORD			0x19
+#define CSR1212_KV_ID_FEATURE			0x1A
+#define CSR1212_KV_ID_EXTENDED_ROM		0x1B
+#define CSR1212_KV_ID_EXTENDED_KEY_SPECIFIER_ID	0x1C
+#define CSR1212_KV_ID_EXTENDED_KEY		0x1D
+#define CSR1212_KV_ID_EXTENDED_DATA		0x1E
+#define CSR1212_KV_ID_MODIFIABLE_DESCRIPTOR	0x1F
+#define CSR1212_KV_ID_DIRECTORY_ID		0x20
+#define CSR1212_KV_ID_REVISION			0x21
+
+
+/* IEEE 1212 Address space map */
+#define CSR1212_ALL_SPACE_BASE			(0x000000000000ULL)
+#define CSR1212_ALL_SPACE_SIZE			(1ULL << 48)
+#define CSR1212_ALL_SPACE_END			(CSR1212_ALL_SPACE_BASE + CSR1212_ALL_SPACE_SIZE)
+
+#define  CSR1212_MEMORY_SPACE_BASE		(0x000000000000ULL)
+#define  CSR1212_MEMORY_SPACE_SIZE		((256ULL * (1ULL << 40)) - (512ULL * (1ULL << 20)))
+#define  CSR1212_MEMORY_SPACE_END		(CSR1212_MEMORY_SPACE_BASE + CSR1212_MEMORY_SPACE_SIZE)
+
+#define  CSR1212_PRIVATE_SPACE_BASE		(0xffffe0000000ULL)
+#define  CSR1212_PRIVATE_SPACE_SIZE		(256ULL * (1ULL << 20))
+#define  CSR1212_PRIVATE_SPACE_END		(CSR1212_PRIVATE_SPACE_BASE + CSR1212_PRIVATE_SPACE_SIZE)
+
+#define  CSR1212_REGISTER_SPACE_BASE		(0xfffff0000000ULL)
+#define  CSR1212_REGISTER_SPACE_SIZE		(256ULL * (1ULL << 20))
+#define  CSR1212_REGISTER_SPACE_END		(CSR1212_REGISTER_SPACE_BASE + CSR1212_REGISTER_SPACE_SIZE)
+
+#define  CSR1212_CSR_ARCH_REG_SPACE_BASE	(0xfffff0000000ULL)
+#define  CSR1212_CSR_ARCH_REG_SPACE_SIZE	(512)
+#define  CSR1212_CSR_ARCH_REG_SPACE_END		(CSR1212_CSR_ARCH_REG_SPACE_BASE + CSR1212_CSR_ARCH_REG_SPACE_SIZE)
+#define  CSR1212_CSR_ARCH_REG_SPACE_OFFSET	(CSR1212_CSR_ARCH_REG_SPACE_BASE - CSR1212_REGISTER_SPACE_BASE)
+
+#define  CSR1212_CSR_BUS_DEP_REG_SPACE_BASE	(0xfffff0000200ULL)
+#define  CSR1212_CSR_BUS_DEP_REG_SPACE_SIZE	(512)
+#define  CSR1212_CSR_BUS_DEP_REG_SPACE_END	(CSR1212_CSR_BUS_DEP_REG_SPACE_BASE + CSR1212_CSR_BUS_DEP_REG_SPACE_SIZE)
+#define  CSR1212_CSR_BUS_DEP_REG_SPACE_OFFSET	(CSR1212_CSR_BUS_DEP_REG_SPACE_BASE - CSR1212_REGISTER_SPACE_BASE)
+
+#define  CSR1212_CONFIG_ROM_SPACE_BASE		(0xfffff0000400ULL)
+#define  CSR1212_CONFIG_ROM_SPACE_SIZE		(1024)
+#define  CSR1212_CONFIG_ROM_SPACE_END		(CSR1212_CONFIG_ROM_SPACE_BASE + CSR1212_CONFIG_ROM_SPACE_SIZE)
+#define  CSR1212_CONFIG_ROM_SPACE_OFFSET	(CSR1212_CONFIG_ROM_SPACE_BASE - CSR1212_REGISTER_SPACE_BASE)
+
+#define  CSR1212_UNITS_SPACE_BASE		(0xfffff0000800ULL)
+#define  CSR1212_UNITS_SPACE_SIZE		((256ULL * (1ULL << 20)) - 2048)
+#define  CSR1212_UNITS_SPACE_END		(CSR1212_UNITS_SPACE_BASE + CSR1212_UNITS_SPACE_SIZE)
+#define  CSR1212_UNITS_SPACE_OFFSET		(CSR1212_UNITS_SPACE_BASE - CSR1212_REGISTER_SPACE_BASE)
+
+#define  CSR1212_EXTENDED_ROM_SIZE		(0x10000 * sizeof(u_int32_t))
+
+
+/* Config ROM image structures */
+struct csr1212_bus_info_block_img {
+	u_int8_t length;
+	u_int8_t crc_length;
+	u_int16_t crc;
+
+	/* Must be last */
+	u_int32_t data[0];	/* older gcc can't handle [] which is standard */
+};
+
+#define CSR1212_KV_KEY(quad)		(CSR1212_BE32_TO_CPU(quad) >> CSR1212_KV_KEY_SHIFT)
+#define CSR1212_KV_KEY_TYPE(quad)	(CSR1212_KV_KEY(quad) >> CSR1212_KV_KEY_TYPE_SHIFT)
+#define CSR1212_KV_KEY_ID(quad)		(CSR1212_KV_KEY(quad) & CSR1212_KV_KEY_ID_MASK)
+#define CSR1212_KV_VAL(quad)		(CSR1212_BE32_TO_CPU(quad) & CSR1212_KV_VAL_MASK)
+
+#define CSR1212_SET_KV_KEY(quad, key)	((quad) = \
+	CSR1212_CPU_TO_BE32(CSR1212_KV_VAL(quad) | ((key) << CSR1212_KV_KEY_SHIFT)))
+#define CSR1212_SET_KV_VAL(quad, val)	((quad) = \
+	CSR1212_CPU_TO_BE32((CSR1212_KV_KEY(quad) << CSR1212_KV_KEY_SHIFT) | (val)))
+#define CSR1212_SET_KV_TYPEID(quad, type, id)	((quad) = \
+	CSR1212_CPU_TO_BE32(CSR1212_KV_VAL(quad) | \
+	(((((type) & CSR1212_KV_KEY_TYPE_MASK) << CSR1212_KV_KEY_TYPE_SHIFT) | \
+	  ((id) & CSR1212_KV_KEY_ID_MASK)) << CSR1212_KV_KEY_SHIFT)))
+
+typedef u_int32_t csr1212_quad_t;
+
+
+struct csr1212_keyval_img {
+	u_int16_t length;
+	u_int16_t crc;
+
+	/* Must be last */
+	csr1212_quad_t data[0];	/* older gcc can't handle [] which is standard */
+};
+
+struct csr1212_leaf {
+	int len;
+	u_int32_t *data;
+};
+
+struct csr1212_dentry {
+	struct csr1212_dentry *next, *prev;
+	struct csr1212_keyval *kv;
+};
+
+struct csr1212_directory {
+	int len;
+	struct csr1212_dentry *dentries_head, *dentries_tail;
+};
+
+struct csr1212_keyval {
+	struct {
+		u_int8_t type;
+		u_int8_t id;
+	} key;
+	union {
+		u_int32_t immediate;
+		u_int32_t csr_offset;
+		struct csr1212_leaf leaf;
+		struct csr1212_directory directory;
+	} value;
+	struct csr1212_keyval *associate;
+	int refcnt;
+
+	/* used in generating and/or parsing CSR image */
+	struct csr1212_keyval *next, *prev;	/* flat list of CSR elements */
+	u_int32_t offset;	/* position in CSR from 0xffff f000 0000 */
+	u_int8_t valid;		/* flag indicating keyval has valid data*/
+};
+
+
+struct csr1212_cache_region {
+	struct csr1212_cache_region *next, *prev;
+	u_int32_t offset_start;		/* inclusive */
+	u_int32_t offset_end;		/* exclusive */
+};
+
+struct csr1212_csr_rom_cache {
+	struct csr1212_csr_rom_cache *next, *prev;
+	struct csr1212_cache_region *filled_head, *filled_tail;
+	struct csr1212_keyval *layout_head, *layout_tail;
+	size_t size;
+	u_int32_t offset;
+	struct csr1212_keyval *ext_rom;
+	size_t len;
+
+	/* Must be last */
+	u_int32_t data[0];	/* older gcc can't handle [] which is standard */
+};
+
+struct csr1212_csr {
+	size_t bus_info_len;	/* bus info block length in bytes */
+	size_t crc_len;		/* crc length in bytes */
+	u_int32_t *bus_info_data;	/* bus info data incl bus name and EUI */
+
+	void *private;		/* private, bus specific data */
+	struct csr1212_bus_ops *ops;
+
+	struct csr1212_keyval *root_kv;
+
+	int max_rom;		/* max bytes readable in Config ROM region */
+
+	/* Items below used for image parsing and generation */
+	struct csr1212_csr_rom_cache *cache_head, *cache_tail;
+};
+
+struct csr1212_bus_ops {
+	/* This function is used by csr1212 to read additional information
+	 * from remote nodes when parsing a Config ROM (i.e., read Config ROM
+	 * entries located in the Units Space.  Must return 0 on success
+	 * anything else indicates an error. */
+	int (*bus_read) (struct csr1212_csr *csr, u_int64_t addr,
+			 u_int16_t length, void *buffer, void *private);
+
+	/* This function is used by csr1212 to allocate a region in units space
+	 * in the event that Config ROM entries don't all fit in the predefined
+	 * 1K region.  The void *private parameter is private member of struct
+	 * csr1212_csr. */
+	u_int64_t (*allocate_addr_range) (u_int64_t size, u_int32_t alignment,
+					  void *private);
+
+
+	/* This function is used by csr1212 to release a region in units space
+	 * that is no longer needed. */
+	void (*release_addr) (u_int64_t addr, void *private);
+
+	/* This function is used by csr1212 to determine the max read request
+	 * supported by a remote node when reading the ConfigROM space.  Must
+	 * return 0, 1, or 2 per IEEE 1212.  */
+	int (*get_max_rom) (u_int32_t *bus_info, void *private);
+};
+
+
+
+
+/* Descriptor Leaf manipulation macros */
+#define CSR1212_DESCRIPTOR_LEAF_TYPE_SHIFT 24
+#define CSR1212_DESCRIPTOR_LEAF_SPECIFIER_ID_MASK 0xffffff
+#define CSR1212_DESCRIPTOR_LEAF_OVERHEAD (1 * sizeof(u_int32_t))
+
+#define CSR1212_DESCRIPTOR_LEAF_TYPE(kv) \
+	(CSR1212_BE32_TO_CPU((kv)->value.leaf.data[0]) >> CSR1212_DESCRIPTOR_LEAF_TYPE_SHIFT)
+#define CSR1212_DESCRIPTOR_LEAF_SPECIFIER_ID(kv) \
+	(CSR1212_BE32_TO_CPU((kv)->value.leaf.data[0]) & \
+	 CSR1212_DESCRIPTOR_LEAF_SPECIFIER_ID_MASK)
+#define CSR1212_DESCRIPTOR_LEAF_DATA(kv) \
+	(&((kv)->value.leaf.data[1]))
+
+#define CSR1212_DESCRIPTOR_LEAF_SET_TYPE(kv, type) \
+	((kv)->value.leaf.data[0] = \
+	 CSR1212_CPU_TO_BE32(CSR1212_DESCRIPTOR_LEAF_SPECIFIER_ID(kv) | \
+			     ((type) << CSR1212_DESCRIPTOR_LEAF_TYPE_SHIFT)))
+#define CSR1212_DESCRIPTOR_LEAF_SET_SPECIFIER_ID(kv, spec_id) \
+	((kv)->value.leaf.data[0] = \
+	 CSR1212_CPU_TO_BE32((CSR1212_DESCRIPTOR_LEAF_TYPE(kv) << \
+			      CSR1212_DESCRIPTOR_LEAF_TYPE_SHIFT) | \
+			     ((spec_id) & CSR1212_DESCRIPTOR_LEAF_SPECIFIER_ID_MASK)))
+
+/* Text Descriptor Leaf manipulation macros */
+#define CSR1212_TEXTUAL_DESCRIPTOR_LEAF_WIDTH_SHIFT 28
+#define CSR1212_TEXTUAL_DESCRIPTOR_LEAF_WIDTH_MASK 0xf /* after shift */
+#define CSR1212_TEXTUAL_DESCRIPTOR_LEAF_CHAR_SET_SHIFT 16
+#define CSR1212_TEXTUAL_DESCRIPTOR_LEAF_CHAR_SET_MASK 0xfff  /* after shift */
+#define CSR1212_TEXTUAL_DESCRIPTOR_LEAF_LANGUAGE_MASK 0xffff
+#define CSR1212_TEXTUAL_DESCRIPTOR_LEAF_OVERHEAD (1 * sizeof(u_int32_t))
+
+#define CSR1212_TEXTUAL_DESCRIPTOR_LEAF_WIDTH(kv) \
+	(CSR1212_BE32_TO_CPU((kv)->value.leaf.data[1]) >> \
+	 CSR1212_TEXTUAL_DESCRIPTOR_LEAF_WIDTH_SHIFT)
+#define CSR1212_TEXTUAL_DESCRIPTOR_LEAF_CHAR_SET(kv) \
+	((CSR1212_BE32_TO_CPU((kv)->value.leaf.data[1]) >> \
+			     CSR1212_TEXTUAL_DESCRIPTOR_LEAF_CHAR_SET_SHIFT) & \
+			    CSR1212_TEXTUAL_DESCRIPTOR_LEAF_CHAR_SET_MASK)
+#define CSR1212_TEXTUAL_DESCRIPTOR_LEAF_LANGUAGE(kv) \
+	(CSR1212_BE32_TO_CPU((kv)->value.leaf.data[1]) & \
+	 CSR1212_TEXTUAL_DESCRIPTOR_LEAF_LANGUAGE_MASK)
+#define CSR1212_TEXTUAL_DESCRIPTOR_LEAF_DATA(kv) \
+	(&((kv)->value.leaf.data[2]))
+
+#define CSR1212_TEXTUAL_DESCRIPTOR_LEAF_SET_WIDTH(kv, width) \
+	((kv)->value.leaf.data[1] = \
+	 ((kv)->value.leaf.data[1] & \
+	  CSR1212_CPU_TO_BE32(~(CSR1212_TEXTUAL_DESCRIPTOR_LEAF_WIDTH_MASK << \
+				CSR1212_TEXTUAL_DESCRIPTOR_LEAF_WIDTH_SHIFT))) | \
+	 CSR1212_CPU_TO_BE32(((width) & \
+			      CSR1212_TEXTUAL_DESCRIPTOR_LEAF_WIDTH_MASK) << \
+			     CSR1212_TEXTUAL_DESCRIPTOR_LEAF_WIDTH_SHIFT))
+#define CSR1212_TEXTUAL_DESCRIPTOR_LEAF_SET_CHAR_SET(kv, char_set) \
+	((kv)->value.leaf.data[1] = \
+	 ((kv)->value.leaf.data[1] & \
+	  CSR1212_CPU_TO_BE32(~(CSR1212_TEXTUAL_DESCRIPTOR_LEAF_CHAR_SET_MASK << \
+				CSR1212_TEXTUAL_DESCRIPTOR_LEAF_CHAR_SET_SHIFT))) | \
+	 CSR1212_CPU_TO_BE32(((char_set) & \
+			      CSR1212_TEXTUAL_DESCRIPTOR_LEAF_CHAR_SET_MASK) << \
+			     CSR1212_TEXTUAL_DESCRIPTOR_LEAF_CHAR_SET_SHIFT))
+#define CSR1212_TEXTUAL_DESCRIPTOR_LEAF_SET_LANGUAGE(kv, language) \
+	((kv)->value.leaf.data[1] = \
+	 ((kv)->value.leaf.data[1] & \
+	  CSR1212_CPU_TO_BE32(~(CSR1212_TEXTUAL_DESCRIPTOR_LEAF_LANGUAGE_MASK))) | \
+	 CSR1212_CPU_TO_BE32(((language) & \
+			      CSR1212_TEXTUAL_DESCRIPTOR_LEAF_LANGUAGE_MASK)))
+
+
+/* Icon Descriptor Leaf manipulation macros */
+#define CSR1212_ICON_DESCRIPTOR_LEAF_VERSION_MASK 0xffffff
+#define CSR1212_ICON_DESCRIPTOR_LEAF_PALETTE_DEPTH_SHIFT 30
+#define CSR1212_ICON_DESCRIPTOR_LEAF_PALETTE_DEPTH_MASK 0x3 /* after shift */
+#define CSR1212_ICON_DESCRIPTOR_LEAF_COLOR_SPACE_SHIFT 16
+#define CSR1212_ICON_DESCRIPTOR_LEAF_COLOR_SPACE_MASK 0xf /* after shift */
+#define CSR1212_ICON_DESCRIPTOR_LEAF_LANGUAGE_MASK 0xffff
+#define CSR1212_ICON_DESCRIPTOR_LEAF_HSCAN_SHIFT 16
+#define CSR1212_ICON_DESCRIPTOR_LEAF_HSCAN_MASK 0xffff /* after shift */
+#define CSR1212_ICON_DESCRIPTOR_LEAF_VSCAN_MASK 0xffff
+#define CSR1212_ICON_DESCRIPTOR_LEAF_OVERHEAD (3 * sizeof(u_int32_t))
+
+#define CSR1212_ICON_DESCRIPTOR_LEAF_VERSION(kv) \
+	(CSR1212_BE32_TO_CPU((kv)->value.leaf.data[2]) & \
+	 CSR1212_ICON_DESCRIPTOR_LEAF_VERSION_MASK)
+
+#define CSR1212_ICON_DESCRIPTOR_LEAF_PALETTE_DEPTH(kv) \
+	(CSR1212_BE32_TO_CPU((kv)->value.leaf.data[3]) >> \
+	 CSR1212_ICON_DESCRIPTOR_LEAF_PALETTE_DEPTH_SHIFT)
+
+#define CSR1212_ICON_DESCRIPTOR_LEAF_COLOR_SPACE(kv) \
+	((CSR1212_BE32_TO_CPU((kv)->value.leaf.data[3]) >> \
+	  CSR1212_ICON_DESCRIPTOR_LEAF_COLOR_SPACE_SHIFT) & \
+	 CSR1212_ICON_DESCRIPTOR_LEAF_COLOR_SPACE_MASK)
+
+#define CSR1212_ICON_DESCRIPTOR_LEAF_LANGUAGE(kv) \
+	(CSR1212_BE32_TO_CPU((kv)->value.leaf.data[3]) & \
+	 CSR1212_ICON_DESCRIPTOR_LEAF_LANGUAGE_MASK)
+
+#define CSR1212_ICON_DESCRIPTOR_LEAF_HSCAN(kv) \
+	((CSR1212_BE32_TO_CPU((kv)->value.leaf.data[4]) >> \
+	  CSR1212_ICON_DESCRIPTOR_LEAF_COLOR_HSCAN_SHIFT) & \
+	 CSR1212_ICON_DESCRIPTOR_LEAF_COLOR_HSCAN_MASK)
+
+#define CSR1212_ICON_DESCRIPTOR_LEAF_VSCAN(kv) \
+	(CSR1212_BE32_TO_CPU((kv)->value.leaf.data[4]) & \
+	 CSR1212_ICON_DESCRIPTOR_LEAF_VSCAN_MASK)
+
+#define CSR1212_ICON_DESCRIPTOR_LEAF_PALETTE(kv) \
+	(&((kv)->value.leaf.data[5]))
+
+static inline u_int32_t *CSR1212_ICON_DESCRIPTOR_LEAF_PIXELS(struct csr1212_keyval *kv)
+{
+	static const int pd[4] = { 0, 4, 16, 256 };
+	static const int cs[16] = { 4, 2 };
+	int ps = pd[CSR1212_ICON_DESCRIPTOR_LEAF_PALETTE_DEPTH(kv)];
+	
+	return &kv->value.leaf.data[5 +
+				    (ps * cs[CSR1212_ICON_DESCRIPTOR_LEAF_COLOR_SPACE(kv)]) /
+			   sizeof(u_int32_t)];
+}
+
+#define CSR1212_ICON_DESCRIPTOR_LEAF_SET_VERSION(kv, version) \
+	((kv)->value.leaf.data[2] = \
+	 ((kv)->value.leaf.data[2] & \
+	  CSR1212_CPU_TO_BE32(~(CSR1212_ICON_DESCRIPTOR_LEAF_VERSION_MASK))) | \
+	 CSR1212_CPU_TO_BE32(((version) & \
+			      CSR1212_ICON_DESCRIPTOR_LEAF_VERSION_MASK)))
+
+#define CSR1212_ICON_DESCRIPTOR_LEAF_SET_PALETTE_DEPTH(kv, palette_depth) \
+	((kv)->value.leaf.data[3] = \
+	 ((kv)->value.leaf.data[3] & \
+	  CSR1212_CPU_TO_BE32(~(CSR1212_ICON_DESCRIPTOR_LEAF_PALETTE_DEPTH_MASK << \
+				CSR1212_ICON_DESCRIPTOR_LEAF_PALETTE_DEPTH_SHIFT))) | \
+	 CSR1212_CPU_TO_BE32(((palette_depth) & \
+			      CSR1212_ICON_DESCRIPTOR_LEAF_PALETTE_DEPTH_MASK) << \
+			     CSR1212_ICON_DESCRIPTOR_LEAF_PALETTE_DEPTH_SHIFT))
+
+#define CSR1212_ICON_DESCRIPTOR_LEAF_SET_COLOR_SPACE(kv, color_space) \
+	((kv)->value.leaf.data[3] = \
+	 ((kv)->value.leaf.data[3] & \
+	  CSR1212_CPU_TO_BE32(~(CSR1212_ICON_DESCRIPTOR_LEAF_COLOR_SPACE_MASK << \
+				CSR1212_ICON_DESCRIPTOR_LEAF_COLOR_SPACE_SHIFT))) | \
+	 CSR1212_CPU_TO_BE32(((color_space) & \
+			      CSR1212_ICON_DESCRIPTOR_LEAF_COLOR_SPACE_MASK) << \
+			     CSR1212_ICON_DESCRIPTOR_LEAF_COLOR_SPACE_SHIFT))
+
+#define CSR1212_ICON_DESCRIPTOR_LEAF_SET_LANGUAGE(kv, language) \
+	((kv)->value.leaf.data[3] = \
+	 ((kv)->value.leaf.data[3] & \
+	  CSR1212_CPU_TO_BE32(~(CSR1212_ICON_DESCRIPTOR_LEAF_LANGUAGE_MASK))) | \
+	 CSR1212_CPU_TO_BE32(((language) & \
+			      CSR1212_ICON_DESCRIPTOR_LEAF_LANGUAGE_MASK)))
+
+#define CSR1212_ICON_DESCRIPTOR_LEAF_SET_HSCAN(kv, hscan) \
+	((kv)->value.leaf.data[4] = \
+	 ((kv)->value.leaf.data[4] & \
+	  CSR1212_CPU_TO_BE32(~(CSR1212_ICON_DESCRIPTOR_LEAF_HSCAN_MASK << \
+				CSR1212_ICON_DESCRIPTOR_LEAF_HSCAN_SHIFT))) | \
+	 CSR1212_CPU_TO_BE32(((hscan) & \
+			      CSR1212_ICON_DESCRIPTOR_LEAF_HSCAN_MASK) << \
+			     CSR1212_ICON_DESCRIPTOR_LEAF_HSCAN_SHIFT))
+
+#define CSR1212_ICON_DESCRIPTOR_LEAF_SET_VSCAN(kv, vscan) \
+	((kv)->value.leaf.data[4] = \
+	 (((kv)->value.leaf.data[4] & \
+	  CSR1212_CPU_TO_BE32(~CSR1212_ICON_DESCRIPTOR_LEAF_VSCAN_MASK))) | \
+	 CSR1212_CPU_TO_BE32(((vscan) & \
+			      CSR1212_ICON_DESCRIPTOR_LEAF_VSCAN_MASK)))
+
+
+/* Modifiable Descriptor Leaf manipulation macros */
+#define CSR1212_MODIFIABLE_DESCRIPTOR_LEAF_MAX_SIZE_SHIFT 16
+#define CSR1212_MODIFIABLE_DESCRIPTOR_LEAF_MAX_SIZE_MASK 0xffff
+#define CSR1212_MODIFIABLE_DESCRIPTOR_LEAF_ADDR_HI_SHIFT 32
+#define CSR1212_MODIFIABLE_DESCRIPTOR_LEAF_ADDR_HI_MASK 0xffff
+#define CSR1212_MODIFIABLE_DESCRIPTOR_LEAF_ADDR_LO_MASK 0xffffffffULL
+
+#define CSR1212_MODIFIABLE_DESCRIPTOR_MAX_SIZE(kv) \
+	CSR1212_BE16_TO_CPU((kv)->value.leaf.data[0] >> CSR1212_MODIFIABLE_DESCRIPTOR_MAX_SIZE_SHIFT)
+
+#define CSR1212_MODIFIABLE_DESCRIPTOR_ADDRESS(kv) \
+	(CSR1212_BE16_TO_CPU(((u_int64_t)((kv)->value.leaf.data[0])) << \
+			     CSR1212_MODIFIABLE_DESCRIPTOR_ADDR_HI_SHIFT) | \
+	 CSR1212_BE32_TO_CPU((kv)->value.leaf.data[1]))
+
+#define CSR1212_MODIFIABLE_DESCRIPTOR_SET_MAX_SIZE(kv, size) \
+	((kv)->value.leaf.data[0] = \
+	 ((kv)->value.leaf.data[0] & \
+	  CSR1212_CPU_TO_BE32(~(CSR1212_MODIFIABLE_DESCRIPTOR_LEAF_MAX_SIZE_MASK << \
+				CSR1212_MODIFIABLE_DESCRIPTOR_LEAF_MAX_SIZE_SHIFT))) | \
+	 CSR1212_CPU_TO_BE32(((size) & \
+			      CSR1212_MODIFIABLE_DESCRIPTOR_LEAF_MAX_SIZE_MASK) << \
+			     CSR1212_MODIFIABLE_DESCRIPTOR_LEAF_MAX_SIZE_SHIFT))
+
+#define CSR1212_MODIFIABLE_DESCRIPTOR_SET_ADDRESS_HI(kv, addr) \
+	((kv)->value.leaf.data[0] = \
+	 ((kv)->value.leaf.data[0] & \
+	  CSR1212_CPU_TO_BE32(~(CSR1212_MODIFIABLE_DESCRIPTOR_LEAF_ADDR_HI_MASK))) | \
+	  CSR1212_CPU_TO_BE32(((addr) & \
+			       CSR1212_MODIFIABLE_DESCRIPTOR_LEAF_ADDR_HI_MASK)))
+
+#define CSR1212_MODIFIABLE_DESCRIPTOR_SET_ADDRESS_LO(kv, addr) \
+	((kv)->value.leaf.data[1] = \
+	 CSR1212_CPU_TO_BE32(addr & CSR1212_MODIFIABLE_DESCRIPTOR_LEAF_ADDR_LO_MASK))
+
+
+
+/* The following 2 function are for creating new Configuration ROM trees.  The
+ * first function is used for both creating local trees and parsing remote
+ * trees.  The second function adds pertinent information to local Configuration
+ * ROM trees - namely data for the bus information block. */
+extern struct csr1212_csr *csr1212_create_csr(struct csr1212_bus_ops *ops,
+					      size_t bus_info_size,
+					      void *private);
+extern void csr1212_init_local_csr(struct csr1212_csr *csr,
+				   const u_int32_t *bus_info_data, int max_rom);
+
+
+/* The following function destroys a Configuration ROM tree and release all
+ * memory taken by the tree. */
+extern void csr1212_destroy_csr(struct csr1212_csr *csr);
+
+
+/* The following set of functions are fore creating new keyvals for placement in
+ * a Configuration ROM tree.  Code that creates new keyvals with these functions
+ * must release those keyvals with csr1212_release_keyval() when they are no
+ * longer needed. */
+extern struct csr1212_keyval *csr1212_new_immediate(u_int8_t key, u_int32_t value);
+extern struct csr1212_keyval *csr1212_new_leaf(u_int8_t key, const void *data,
+					       size_t data_len);
+extern struct csr1212_keyval *csr1212_new_csr_offset(u_int8_t key,
+						     u_int32_t csr_offset);
+extern struct csr1212_keyval *csr1212_new_directory(u_int8_t key);
+extern struct csr1212_keyval *csr1212_new_extended_immediate(u_int32_t spec,
+							     u_int32_t key,
+							     u_int32_t value);
+extern struct csr1212_keyval *csr1212_new_extended_leaf(u_int32_t spec,
+							u_int32_t key,
+							const void *data,
+							size_t data_len);
+extern struct csr1212_keyval *csr1212_new_descriptor_leaf(u_int8_t dtype,
+							  u_int32_t specifier_id,
+							  const void *data,
+							  size_t data_len);
+extern struct csr1212_keyval *csr1212_new_textual_descriptor_leaf(u_int8_t cwidth,
+								  u_int16_t cset,
+								  u_int16_t language,
+								  const void *data,
+								  size_t data_len);
+extern struct csr1212_keyval *csr1212_new_string_descriptor_leaf(const char *s);
+extern struct csr1212_keyval *csr1212_new_icon_descriptor_leaf(u_int32_t version,
+							       u_int8_t palette_depth,
+							       u_int8_t color_space,
+							       u_int16_t language,
+							       u_int16_t hscan,
+							       u_int16_t vscan,
+							       u_int32_t *palette,
+							       u_int32_t *pixels);
+extern struct csr1212_keyval *csr1212_new_modifiable_descriptor_leaf(u_int16_t max_size,
+								     u_int64_t address);
+extern struct csr1212_keyval *csr1212_new_keyword_leaf(int strc,
+						       const char *strv[]);
+
+
+/* The following functions manage association between keyvals.  Typically,
+ * Descriptor Leaves and Directories will be associated with another keyval and
+ * it is desirable for the Descriptor keyval to be place immediately after the
+ * keyval that it is associated with.*/
+extern int csr1212_associate_keyval(struct csr1212_keyval *kv,
+				    struct csr1212_keyval *associate);
+extern void csr1212_disassociate_keyval(struct csr1212_keyval *kv);
+
+
+/* The following functions manage the association of a keyval and directories.
+ * A keyval may be attached to more than one directory. */
+extern int csr1212_attach_keyval_to_directory(struct csr1212_keyval *dir,
+					      struct csr1212_keyval *kv);
+extern void csr1212_detach_keyval_from_directory(struct csr1212_keyval *dir,
+						 struct csr1212_keyval *kv);
+
+
+/* The following functions create a Configuration ROM image from the tree of
+ * keyvals provided.  csr1212_generate_csr_image() creates a complete image in
+ * the list of caches available via csr->cache_head.  The other functions are
+ * provided should there be a need to create a flat image without restrictions
+ * placed by IEEE 1212. */
+extern struct csr1212_keyval *csr1212_generate_positions(struct csr1212_csr_rom_cache *cache,
+							 struct csr1212_keyval *start_kv,
+							 int start_pos);
+extern size_t csr1212_generate_layout_order(struct csr1212_keyval *kv);
+extern void csr1212_fill_cache(struct csr1212_csr_rom_cache *cache);
+extern int csr1212_generate_csr_image(struct csr1212_csr *csr);
+
+
+/* This is a convience function for reading a block of data out of one of the
+ * caches in the csr->cache_head list. */
+extern int csr1212_read(struct csr1212_csr *csr, u_int32_t offset, void *buffer,
+			u_int32_t len);
+
+
+/* The following functions are in place for parsing Configuration ROM images.
+ * csr1212_parse_keyval() is used should there be a need to directly parse a
+ * Configuration ROM directly. */
+extern int csr1212_parse_keyval(struct csr1212_keyval *kv,
+				struct csr1212_csr_rom_cache *cache);
+extern int csr1212_parse_csr(struct csr1212_csr *csr);
+
+/* These are internal functions referenced by inline functions below. */
+extern int _csr1212_read_keyval(struct csr1212_csr *csr, struct csr1212_keyval *kv);
+extern void _csr1212_destroy_keyval(struct csr1212_keyval *kv);
+
+
+/* This function allocates a new cache which may be used for either parsing or
+ * generating sub-sets of Configuration ROM images. */
+static inline struct csr1212_csr_rom_cache *csr1212_rom_cache_malloc(u_int32_t offset,
+								     size_t size)
+{
+	struct csr1212_csr_rom_cache *cache;
+
+	cache = CSR1212_MALLOC(sizeof(struct csr1212_csr_rom_cache) + size);
+	if (!cache)
+		return NULL;
+
+	cache->next = NULL;
+	cache->prev = NULL;
+	cache->filled_head = NULL;
+	cache->filled_tail = NULL;
+	cache->layout_head = NULL;
+	cache->layout_tail = NULL;
+	cache->offset = offset;
+	cache->size = size;
+	cache->ext_rom = NULL;
+
+	return cache;
+}
+
+
+/* This function ensures that a keyval contains data when referencing a keyval
+ * created by parsing a Configuration ROM. */
+static inline struct csr1212_keyval *csr1212_get_keyval(struct csr1212_csr *csr,
+							struct csr1212_keyval *kv)
+{
+	if (!kv)
+		return NULL;
+	if (!kv->valid)
+		if (_csr1212_read_keyval(csr, kv) != CSR1212_SUCCESS)
+			return NULL;
+	return kv;
+}
+
+
+/* This function increments the reference count for a keyval should there be a
+ * need for code to retain a keyval that has been parsed. */
+static inline void csr1212_keep_keyval(struct csr1212_keyval *kv)
+{
+	kv->refcnt++;
+}
+
+
+/* This function decrements a keyval's reference count and will destroy the
+ * keyval when there are no more users of the keyval.  This should be called by
+ * any code that calls csr1212_keep_keyval() or any of the keyval creation
+ * routines csr1212_new_*(). */
+static inline void csr1212_release_keyval(struct csr1212_keyval *kv)
+{
+	if (kv->refcnt > 1)
+		kv->refcnt--;
+	else
+		_csr1212_destroy_keyval(kv);
+}
+
+
+/*
+ * This macro allows for looping over the keyval entries in a directory and it
+ * ensures that keyvals from remote ConfigROMs are parsed properly.
+ *
+ * _csr is a struct csr1212_csr * that points to CSR associated with dir.
+ * _kv is a struct csr1212_keyval * that'll point to the current keyval (loop index).
+ * _dir is a struct csr1212_keyval * that points to the directory to be looped.
+ * _pos is a struct csr1212_dentry * that is used internally for indexing.
+ * 
+ * kv will be NULL upon exit of the loop.
+ */
+#define csr1212_for_each_dir_entry(_csr, _kv, _dir, _pos)			\
+	for (csr1212_get_keyval((_csr), (_dir)),				\
+	     _pos = (_dir)->value.directory.dentries_head,			\
+	     _kv = (_pos) ? csr1212_get_keyval((_csr), _pos->kv) : NULL;	\
+	     (_kv) && (_pos);							\
+	     (_kv->associate == NULL) ?						\
+		     ((_pos = _pos->next), 					\
+		      (_kv = (_pos) ? csr1212_get_keyval((_csr), _pos->kv) :	\
+                          NULL)) :						\
+		     (_kv = csr1212_get_keyval((_csr), _kv->associate)))
+
+
+
+#endif /* __CSR1212_H__ */
--- diff/drivers/input/serio/gscps2.c	1970-01-01 01:00:00.000000000 +0100
+++ source/drivers/input/serio/gscps2.c	2004-02-23 13:56:41.000000000 +0000
@@ -0,0 +1,470 @@
+/*
+ * drivers/input/serio/gscps2.c
+ *
+ * Copyright (c) 2004 Helge Deller <deller@gmx.de>
+ * Copyright (c) 2002 Laurent Canet <canetl@esiee.fr>
+ * Copyright (c) 2002 Thibaut Varene <varenet@esiee.fr>
+ *
+ * Pieces of code based on linux-2.4's hp_mouse.c & hp_keyb.c
+ * 	Copyright (c) 1999 Alex deVries <adevries@thepuffingroup.com>
+ *	Copyright (c) 1999-2000 Philipp Rumpf <prumpf@tux.org>
+ *	Copyright (c) 2000 Xavier Debacker <debackex@esiee.fr>
+ *	Copyright (c) 2000-2001 Thomas Marteau <marteaut@esiee.fr>
+ *
+ * HP GSC PS/2 port driver, found in PA/RISC Workstations
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ * 
+ * TODO:
+ * - Dino testing (did HP ever shipped a machine on which this port
+ *                 was usable/enabled ?)
+ */
+
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/serio.h>
+#include <linux/input.h>
+#include <linux/interrupt.h>
+#include <linux/spinlock.h>
+#include <linux/delay.h>
+#include <linux/ioport.h>
+#include <linux/pci_ids.h>
+
+#include <asm/irq.h>
+#include <asm/io.h>
+#include <asm/parisc-device.h>
+
+MODULE_AUTHOR("Laurent Canet <canetl@esiee.fr>, Thibaut Varene <varenet@esiee.fr>, Helge Deller <deller@gmx.de>");
+MODULE_DESCRIPTION("HP GSC PS/2 port driver");
+MODULE_LICENSE("GPL");
+MODULE_DEVICE_TABLE(parisc, gscps2_device_tbl);
+
+#define PFX "gscps2.c: "
+
+/* 
+ * Driver constants
+ */
+
+/* various constants */
+#define ENABLE			1
+#define DISABLE			0
+
+#define GSC_DINO_OFFSET		0x0800	/* offset for DINO controller versus LASI one */
+
+/* PS/2 IO port offsets */
+#define GSC_ID			0x00	/* device ID offset (see: GSC_ID_XXX) */
+#define GSC_RESET		0x00	/* reset port offset */
+#define GSC_RCVDATA		0x04	/* receive port offset */
+#define GSC_XMTDATA		0x04	/* transmit port offset */
+#define GSC_CONTROL		0x08	/* see: Control register bits */
+#define GSC_STATUS		0x0C	/* see: Status register bits */
+
+/* Control register bits */
+#define GSC_CTRL_ENBL		0x01	/* enable interface */
+#define GSC_CTRL_LPBXR		0x02	/* loopback operation */
+#define GSC_CTRL_DIAG		0x20	/* directly control clock/data line */
+#define GSC_CTRL_DATDIR		0x40	/* data line direct control */
+#define GSC_CTRL_CLKDIR		0x80	/* clock line direct control */
+
+/* Status register bits */
+#define GSC_STAT_RBNE		0x01	/* Receive Buffer Not Empty */
+#define GSC_STAT_TBNE		0x02	/* Transmit Buffer Not Empty */
+#define GSC_STAT_TERR		0x04	/* Timeout Error */
+#define GSC_STAT_PERR		0x08	/* Parity Error */
+#define GSC_STAT_CMPINTR	0x10	/* Composite Interrupt = irq on any port */
+#define GSC_STAT_DATSHD		0x40	/* Data Line Shadow */
+#define GSC_STAT_CLKSHD		0x80	/* Clock Line Shadow */
+
+/* IDs returned by GSC_ID port register */
+#define GSC_ID_KEYBOARD		0	/* device ID values */
+#define GSC_ID_MOUSE		1
+
+
+static irqreturn_t gscps2_interrupt(int irq, void *dev, struct pt_regs *regs);
+
+#define BUFFER_SIZE 0x0f
+
+/* GSC PS/2 port device struct */
+struct gscps2port {
+	struct list_head node;
+	struct parisc_device *padev;
+	struct serio port;
+	spinlock_t lock;
+	char *addr;
+	u8 act, append; /* position in buffer[] */
+	struct {
+		u8 data;
+		u8 str;
+	} buffer[BUFFER_SIZE+1];
+	int id;
+	char name[32];
+};
+
+/*
+ * Various HW level routines
+ */
+
+#define gscps2_readb_input(x)		readb((x)+GSC_RCVDATA)
+#define gscps2_readb_control(x)		readb((x)+GSC_CONTROL)
+#define gscps2_readb_status(x)		readb((x)+GSC_STATUS)
+#define gscps2_writeb_control(x, y)	writeb((x), (y)+GSC_CONTROL)
+
+
+/*
+ * wait_TBE() - wait for Transmit Buffer Empty
+ */
+
+static int wait_TBE(char *addr)
+{
+	int timeout = 25000; /* device is expected to react within 250 msec */
+	while (gscps2_readb_status(addr) & GSC_STAT_TBNE) {
+		if (!--timeout)
+			return 0;	/* This should not happen */
+		udelay(10);
+	}
+	return 1;
+}
+
+
+/*
+ * gscps2_flush() - flush the receive buffer
+ */
+
+static void gscps2_flush(struct gscps2port *ps2port)
+{
+	while (gscps2_readb_status(ps2port->addr) & GSC_STAT_RBNE)
+		gscps2_readb_input(ps2port->addr);
+	ps2port->act = ps2port->append = 0;
+}
+
+/*
+ * gscps2_writeb_output() - write a byte to the port
+ *
+ * returns 1 on sucess, 0 on error
+ */
+
+static inline int gscps2_writeb_output(struct gscps2port *ps2port, u8 data)
+{
+	unsigned long flags;
+	char *addr = ps2port->addr;
+
+	if (!wait_TBE(addr)) {
+		printk(KERN_DEBUG PFX "timeout - could not write byte %#x\n", data);
+		return 0;
+	}
+
+	while (gscps2_readb_status(ps2port->addr) & GSC_STAT_RBNE)
+		/* wait */;
+
+	spin_lock_irqsave(&ps2port->lock, flags);
+	writeb(data, addr+GSC_XMTDATA);
+	spin_unlock_irqrestore(&ps2port->lock, flags);
+
+	/* this is ugly, but due to timing of the port it seems to be necessary. */
+	mdelay(6);
+
+	/* make sure any received data is returned as fast as possible */
+	/* this is important e.g. when we set the LEDs on the keyboard */
+	gscps2_interrupt(0, NULL, NULL);
+
+	return 1;
+}
+
+
+/*
+ * gscps2_enable() - enables or disables the port
+ */
+
+static void gscps2_enable(struct gscps2port *ps2port, int enable)
+{
+	unsigned long flags;
+	u8 data;
+
+	/* now enable/disable the port */
+	spin_lock_irqsave(&ps2port->lock, flags);
+	gscps2_flush(ps2port);
+	data = gscps2_readb_control(ps2port->addr);
+	if (enable)
+		data |= GSC_CTRL_ENBL;
+	else
+		data &= ~GSC_CTRL_ENBL;
+	gscps2_writeb_control(data, ps2port->addr);
+	spin_unlock_irqrestore(&ps2port->lock, flags);
+	wait_TBE(ps2port->addr);
+	gscps2_flush(ps2port);
+}
+
+/*
+ * gscps2_reset() - resets the PS/2 port
+ */
+
+static void gscps2_reset(struct gscps2port *ps2port)
+{
+	char *addr = ps2port->addr;
+	unsigned long flags;
+
+	/* reset the interface */
+	spin_lock_irqsave(&ps2port->lock, flags);
+	gscps2_flush(ps2port);
+	writeb(0xff, addr+GSC_RESET);
+	gscps2_flush(ps2port);
+	spin_unlock_irqrestore(&ps2port->lock, flags);
+
+	/* enable it */
+	gscps2_enable(ps2port, ENABLE);
+}
+
+static LIST_HEAD(ps2port_list);
+
+/**
+ * gscps2_interrupt() - Interruption service routine
+ *
+ * This function reads received PS/2 bytes and processes them on 
+ * all interfaces.
+ * The problematic part here is, that the keyboard and mouse PS/2 port
+ * share the same interrupt and it's not possible to send data if any
+ * one of them holds input data. To solve this problem we try to receive
+ * the data as fast as possible and handle the reporting to the upper layer
+ * later.
+ */
+
+static irqreturn_t gscps2_interrupt(int irq, void *dev, struct pt_regs *regs)
+{
+	struct gscps2port *ps2port;
+
+	list_for_each_entry(ps2port, &ps2port_list, node) {
+
+	  unsigned long flags;
+	  spin_lock_irqsave(&ps2port->lock, flags);
+
+	  while ( (ps2port->buffer[ps2port->append].str = 
+		   gscps2_readb_status(ps2port->addr)) & GSC_STAT_RBNE ) {
+		ps2port->buffer[ps2port->append].data = 
+				gscps2_readb_input(ps2port->addr);
+		ps2port->append = ((ps2port->append+1) & BUFFER_SIZE);
+	  }
+
+	  spin_unlock_irqrestore(&ps2port->lock, flags);
+
+	} /* list_for_each_entry */
+
+	/* all data was read from the ports - now report the data to upper layer */
+
+	list_for_each_entry(ps2port, &ps2port_list, node) {
+
+	  while (ps2port->act != ps2port->append) {
+
+	    unsigned int rxflags;
+	    u8 data, status;
+
+	    /* Did new data arrived while we read existing data ?
+	       If yes, exit now and let the new irq handler start over again */
+	    if (gscps2_readb_status(ps2port->addr) & GSC_STAT_CMPINTR)
+		return IRQ_HANDLED;
+
+	    status = ps2port->buffer[ps2port->act].str;
+	    data   = ps2port->buffer[ps2port->act].data;
+
+	    ps2port->act = ((ps2port->act+1) & BUFFER_SIZE);
+	    rxflags =	((status & GSC_STAT_TERR) ? SERIO_TIMEOUT : 0 ) |
+			((status & GSC_STAT_PERR) ? SERIO_PARITY  : 0 );
+
+	    serio_interrupt(&ps2port->port, data, rxflags, regs);
+
+	  } /* while() */
+
+	} /* list_for_each_entry */
+
+	return IRQ_HANDLED;
+}
+
+
+/*
+ * gscps2_write() - send a byte out through the aux interface.
+ */
+
+static int gscps2_write(struct serio *port, unsigned char data)
+{
+	struct gscps2port *ps2port = port->driver;
+
+	if (!gscps2_writeb_output(ps2port, data)) {
+		printk(KERN_DEBUG PFX "sending byte %#x failed.\n", data);
+		return -1;
+	}
+	return 0;
+}
+
+/*
+ * gscps2_open() is called when a port is opened by the higher layer.
+ * It resets and enables the port.
+ */
+
+static int gscps2_open(struct serio *port)
+{
+	struct gscps2port *ps2port = port->driver;
+
+	gscps2_reset(ps2port);
+
+	gscps2_interrupt(0, NULL, NULL);
+
+	return 0;
+}
+
+/*
+ * gscps2_close() disables the port
+ */
+
+static void gscps2_close(struct serio *port)
+{
+	struct gscps2port *ps2port = port->driver;
+	gscps2_enable(ps2port, DISABLE);
+}
+
+static struct serio gscps2_serio_port =
+{
+	.name =		"GSC PS/2",
+	.idbus =	BUS_GSC,
+	.idvendor =	PCI_VENDOR_ID_HP,
+	.idproduct =	0x0001,
+	.idversion =	0x0010,
+	.type =		SERIO_8042,
+	.write =	gscps2_write,
+	.open =		gscps2_open,
+	.close =	gscps2_close,
+};
+
+/**
+ * gscps2_probe() - Probes PS2 devices
+ * @return: success/error report
+ */
+
+static int __init gscps2_probe(struct parisc_device *dev)
+{
+        struct gscps2port *ps2port;
+	unsigned long hpa = dev->hpa;
+	int ret;
+
+	if (!dev->irq)
+		return -ENODEV;
+	
+	/* Offset for DINO PS/2. Works with LASI even */
+	if (dev->id.sversion == 0x96)
+		hpa += GSC_DINO_OFFSET;
+
+	ps2port = kmalloc(sizeof(struct gscps2port), GFP_KERNEL);
+	if (!ps2port)
+		return -ENOMEM;
+
+	dev_set_drvdata(&dev->dev, ps2port);
+
+	memset(ps2port, 0, sizeof(struct gscps2port));
+	ps2port->padev = dev;
+	ps2port->addr = ioremap(hpa, GSC_STATUS + 4);
+	spin_lock_init(&ps2port->lock);
+
+	gscps2_reset(ps2port);
+	ps2port->id = readb(ps2port->addr+GSC_ID) & 0x0f;
+	snprintf(ps2port->name, sizeof(ps2port->name)-1, "%s %s",
+		gscps2_serio_port.name, 
+		(ps2port->id == GSC_ID_KEYBOARD) ? "keyboard" : "mouse" );
+
+	memcpy(&ps2port->port, &gscps2_serio_port, sizeof(gscps2_serio_port));
+	ps2port->port.driver = ps2port;
+	ps2port->port.name = ps2port->name;
+	ps2port->port.phys = dev->dev.bus_id;
+
+	list_add_tail(&ps2port->node, &ps2port_list);
+
+	ret = -EBUSY;
+	if (request_irq(dev->irq, gscps2_interrupt, SA_SHIRQ, ps2port->name, ps2port))
+		goto fail_miserably;
+
+	if ( (ps2port->id != GSC_ID_KEYBOARD) && (ps2port->id != GSC_ID_MOUSE) ) {
+		printk(KERN_WARNING PFX "Unsupported PS/2 port at 0x%08lx (id=%d) ignored\n",
+				hpa, ps2port->id);
+		ret = -ENODEV;
+		goto fail;
+	}
+
+#if 0
+	if (!request_mem_region(hpa, GSC_STATUS + 4, ps2port->port.name))
+		goto fail;
+#endif
+
+	printk(KERN_INFO "serio: %s port at 0x%p irq %d @ %s\n",
+		ps2port->name,
+		ps2port->addr,
+		ps2port->padev->irq,
+		ps2port->port.phys);
+
+	serio_register_port(&ps2port->port);
+	
+	return 0;
+	
+fail:
+	free_irq(dev->irq, ps2port);
+
+fail_miserably:
+	list_del(&ps2port->node);
+	iounmap(ps2port->addr);
+	release_mem_region(dev->hpa, GSC_STATUS + 4);
+	kfree(ps2port);
+	return ret;
+}
+
+/**
+ * gscps2_remove() - Removes PS2 devices
+ * @return: success/error report
+ */
+
+static int __devexit gscps2_remove(struct parisc_device *dev)
+{
+	struct gscps2port *ps2port = dev_get_drvdata(&dev->dev);
+
+	serio_unregister_port(&ps2port->port);
+	free_irq(dev->irq, ps2port);
+	gscps2_flush(ps2port);
+	list_del(&ps2port->node);
+	iounmap(ps2port->addr);
+#if 0
+	release_mem_region(dev->hpa, GSC_STATUS + 4); 
+#endif
+	dev_set_drvdata(&dev->dev, NULL);
+	kfree(ps2port);
+	return 0;
+}
+
+
+static struct parisc_device_id gscps2_device_tbl[] = {
+	{ HPHW_FIO, HVERSION_REV_ANY_ID, HVERSION_ANY_ID, 0x00084 }, /* LASI PS/2 */
+#ifdef DINO_TESTED
+	{ HPHW_FIO, HVERSION_REV_ANY_ID, HVERSION_ANY_ID, 0x00096 }, /* DINO PS/2 */ 
+#endif
+	{ 0, }	/* 0 terminated list */
+};
+
+static struct parisc_driver parisc_ps2_driver = {
+	.name		= "GSC PS/2",
+	.id_table	= gscps2_device_tbl,
+	.probe		= gscps2_probe,
+	.remove		= gscps2_remove,
+};
+
+static int __init gscps2_init(void)
+{
+	register_parisc_driver(&parisc_ps2_driver);
+	return 0;
+}
+
+static void __exit gscps2_exit(void)
+{
+	unregister_parisc_driver(&parisc_ps2_driver);
+}
+
+
+module_init(gscps2_init);
+module_exit(gscps2_exit);
+
--- diff/drivers/isdn/hisax/hfc_usb.c	1970-01-01 01:00:00.000000000 +0100
+++ source/drivers/isdn/hisax/hfc_usb.c	2004-02-23 13:56:42.000000000 +0000
@@ -0,0 +1,1667 @@
+/*
+ * hfc_usb.c
+ *
+ * modular HiSax ISDN driver for Colognechip HFC-USB chip
+ *
+ * Authors : Peter Sprenger  (sprenger@moving-byters.de)
+ *           Martin Bachem   (info@colognechip.com)
+ *           based on the first hfc_usb driver of Werner Cornelius (werner@isdn-development.de)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+*/
+
+
+#include <linux/types.h>
+#include <linux/stddef.h>
+#include <linux/timer.h>
+#include <linux/config.h>
+#include <linux/init.h>
+#include "hisax.h"
+#include <linux/module.h>
+#include <linux/kernel_stat.h>
+#include <linux/usb.h>
+#include <linux/kernel.h>
+#include <linux/smp_lock.h>
+#include <linux/sched.h>
+#include "hisax_if.h"
+
+static const char *hfcusb_revision = "4.0";
+
+/*
+	to enable much mire debug messages in this driver, define
+			VERBOSE_USB_DEBUG and VERBOSE_ISDN_DEBUG
+	below
+*/
+
+#define VERBOSE_USB_DEBUG
+#define VERBOSE_ISDN_DEBUG
+
+#define INCLUDE_INLINE_FUNCS
+
+#define TRUE  1
+#define FALSE 0
+
+
+/***********/
+/* defines */
+/***********/
+#define HFC_CTRL_TIMEOUT	20  //(HZ * USB_CTRL_GET_TIMEOUT)
+/* 5ms timeout writing/reading regs */
+#define HFC_TIMER_T3     8000      /* timeout for l1 activation timer */
+#define HFC_TIMER_T4     500       /* time for state change interval */
+
+#define HFCUSB_L1_STATECHANGE   0  /* L1 state changed */
+#define HFCUSB_L1_DRX           1  /* D-frame received */
+#define HFCUSB_L1_ERX           2  /* E-frame received */
+#define HFCUSB_L1_DTX           4  /* D-frames completed */
+
+#define MAX_BCH_SIZE        2048   /* allowed B-channel packet size */
+
+#define HFCUSB_RX_THRESHOLD 64     /* threshold for fifo report bit rx */
+#define HFCUSB_TX_THRESHOLD 64     /* threshold for fifo report bit tx */
+
+#define HFCUSB_CHIP_ID    0x16     /* Chip ID register index */
+#define HFCUSB_CIRM       0x00     /* cirm register index */
+#define HFCUSB_USB_SIZE   0x07     /* int length register */
+#define HFCUSB_USB_SIZE_I 0x06     /* iso length register */
+#define HFCUSB_F_CROSS    0x0b     /* bit order register */
+#define HFCUSB_CLKDEL     0x37     /* bit delay register */
+#define HFCUSB_CON_HDLC   0xfa     /* channel connect register */
+#define HFCUSB_HDLC_PAR   0xfb
+#define HFCUSB_SCTRL      0x31     /* S-bus control register (tx) */
+#define HFCUSB_SCTRL_E    0x32     /* same for E and special funcs */
+#define HFCUSB_SCTRL_R    0x33     /* S-bus control register (rx) */
+#define HFCUSB_F_THRES    0x0c     /* threshold register */
+#define HFCUSB_FIFO       0x0f     /* fifo select register */
+#define HFCUSB_F_USAGE    0x1a     /* fifo usage register */
+#define HFCUSB_MST_MODE0  0x14
+#define HFCUSB_MST_MODE1  0x15
+#define HFCUSB_P_DATA     0x1f
+#define HFCUSB_INC_RES_F  0x0e
+#define HFCUSB_STATES     0x30
+
+#define HFCUSB_CHIPID 0x40         /* ID value of HFC-USB */
+
+/******************/
+/* fifo registers */
+/******************/
+#define HFCUSB_NUM_FIFOS   8       /* maximum number of fifos */
+#define HFCUSB_B1_TX       0       /* index for B1 transmit bulk/int */
+#define HFCUSB_B1_RX       1       /* index for B1 receive bulk/int */
+#define HFCUSB_B2_TX       2
+#define HFCUSB_B2_RX       3
+#define HFCUSB_D_TX        4
+#define HFCUSB_D_RX        5
+#define HFCUSB_PCM_TX      6
+#define HFCUSB_PCM_RX      7
+
+/*
+* used to switch snd_transfer_mode for different TA modes e.g. the Billion USB TA just
+* supports ISO out, while the Cologne Chip EVAL TA just supports BULK out
+*/
+#define USB_INT		0
+#define USB_BULK	1
+#define USB_ISOC	2
+
+#define ISOC_PACKETS_D	8
+#define ISOC_PACKETS_B	8
+#define ISO_BUFFER_SIZE	128
+
+// ISO send definitions
+#define SINK_MAX	68
+#define SINK_MIN	48
+#define SINK_DMIN	12
+#define SINK_DMAX	18
+#define BITLINE_INF	(-64*8)
+
+
+
+
+/**********/
+/* macros */
+/**********/
+#define write_usb(a,b,c) usb_control_msg((a)->dev,(a)->ctrl_out_pipe,0,0x40,(c),(b),0,0,HFC_CTRL_TIMEOUT)
+#define read_usb(a,b,c) usb_control_msg((a)->dev,(a)->ctrl_in_pipe,1,0xC0,0,(b),(c),1,HFC_CTRL_TIMEOUT)
+
+/*************************************************/
+/* entry and size of output/input control buffer */
+/*************************************************/
+#define HFC_CTRL_BUFSIZE 32
+typedef struct
+{
+	__u8 hfc_reg;		/* register number */
+	__u8 reg_val;		/* value to be written (or read) */
+	int action;         /* data for action handler */
+
+} ctrl_buft;
+
+typedef struct
+{
+	int vendor;         // vendor id
+	int prod_id;	    // product id
+	char *vend_name;    // vendor string
+	__u8 led_scheme;    // led display scheme
+	__u8 led_invert;    // invert led aux port settings
+	__u8 led_bits[8];   // array of 8 possible LED bitmask settings
+
+} vendor_data;
+
+/***************************************************************/
+/* structure defining input+output fifos (interrupt/bulk mode) */
+/***************************************************************/
+
+struct usb_fifo;			/* forward definition */
+typedef struct iso_urb_struct
+{
+	struct urb *purb;
+	__u8 buffer[ISO_BUFFER_SIZE];	/* buffer incoming/outgoing data */
+	struct usb_fifo *owner_fifo;	// pointer to owner fifo
+} iso_urb_struct;
+
+
+struct hfcusb_data;			/* forward definition */
+typedef struct usb_fifo
+{
+	int fifonum;			/* fifo index attached to this structure */
+	int active;			/* fifo is currently active */
+	struct hfcusb_data *hfc;	/* pointer to main structure */
+	int pipe;			/* address of endpoint */
+	__u8 usb_packet_maxlen;		/* maximum length for usb transfer */
+	unsigned int max_size;		/* maximum size of receive/send packet */
+	__u8 intervall;			/* interrupt interval */
+	struct sk_buff *skbuff; 	/* actual used buffer */
+	struct urb *urb;		/* transfer structure for usb routines */
+	__u8 buffer[128];		/* buffer incoming/outgoing data */
+	int bit_line;			/* how much bits are in the fifo? */
+
+	volatile __u8 usb_transfer_mode;/* switched between ISO and INT */
+	iso_urb_struct iso[2];		/* need two urbs to have one always for pending */
+	struct hisax_if *hif;		/* hisax interface */
+	int delete_flg;			/* only delete skbuff once */
+	int last_urblen;		/* remember length of last packet */
+
+} usb_fifo;
+
+
+/*********************************************/
+/* structure holding all data for one device */
+/*********************************************/
+typedef struct hfcusb_data
+{
+	// HiSax Interface for loadable Layer1 drivers
+	struct hisax_d_if d_if;			/* see hisax_if.h */
+	struct hisax_b_if b_if[2];		/* see hisax_if.h */
+	int protocol;
+	
+	struct usb_device *dev;			/* our device */
+	int if_used;				/* used interface number */
+	int alt_used;				/* used alternate config */
+	int ctrl_paksize;			/* control pipe packet size */
+	int ctrl_in_pipe, ctrl_out_pipe;	/* handles for control pipe */
+	int cfg_used;				/* configuration index used */
+	int vend_idx;				// vendor found
+
+	int b_mode[2];				// B-channel mode
+
+	int l1_activated;			// layer 1 activated
+
+	int packet_size,iso_packet_size;	
+
+	/* control pipe background handling */
+	ctrl_buft ctrl_buff[HFC_CTRL_BUFSIZE];	/* buffer holding queued data */
+	volatile int ctrl_in_idx, ctrl_out_idx,
+		ctrl_cnt;			/* input/output pointer + count */
+	struct urb *ctrl_urb;			/* transfer structure for control channel */
+
+	struct usb_ctrlrequest ctrl_write;	/* buffer for control write request */
+	struct usb_ctrlrequest ctrl_read;	/* same for read request */
+
+	__u8 led_state,led_new_data,led_b_active;
+
+	volatile __u8 threshold_mask;		/* threshold actually reported */
+	volatile __u8 bch_enables;		/* or mask for sctrl_r and sctrl register values */
+
+	usb_fifo fifos[HFCUSB_NUM_FIFOS];	/* structure holding all fifo data */
+
+	volatile __u8 l1_state;			/* actual l1 state */
+	struct timer_list t3_timer;		/* timer 3 for activation/deactivation */
+	struct timer_list t4_timer;		/* timer 4 for activation/deactivation */
+	struct timer_list led_timer;		/* timer flashing leds */
+
+} hfcusb_data;
+
+
+static void collect_rx_frame(usb_fifo *fifo,__u8 *data,int len,int finish);
+
+
+
+/******************************************************/
+/* start next background transfer for control channel */
+/******************************************************/
+static void ctrl_start_transfer(hfcusb_data * hfc)
+{
+	int err;
+	if(hfc->ctrl_cnt)
+	{
+		hfc->ctrl_urb->pipe = hfc->ctrl_out_pipe;
+		hfc->ctrl_urb->setup_packet = (u_char *) & hfc->ctrl_write;
+		hfc->ctrl_urb->transfer_buffer = NULL;
+		hfc->ctrl_urb->transfer_buffer_length = 0;
+		hfc->ctrl_write.wIndex = hfc->ctrl_buff[hfc->ctrl_out_idx].hfc_reg;
+		hfc->ctrl_write.wValue = hfc->ctrl_buff[hfc->ctrl_out_idx].reg_val;
+		err = usb_submit_urb(hfc->ctrl_urb, GFP_KERNEL);	/* start transfer */
+		printk(KERN_DEBUG "ctrl_start_transfer: submit %d\n", err);
+	}
+}				/* ctrl_start_transfer */
+
+/************************************/
+/* queue a control transfer request */
+/* return 0 on success.             */
+/************************************/
+static int queue_control_request(hfcusb_data * hfc, __u8 reg, __u8 val,int action)
+{
+	ctrl_buft *buf;
+
+#ifdef VERBOSE_USB_DEBUG
+	printk ("HFC_USB: queue_control_request reg: %x, val: %x\n", reg, val);
+#endif
+
+	if(hfc->ctrl_cnt >= HFC_CTRL_BUFSIZE)  return(1);	   /* no space left */
+	buf = &hfc->ctrl_buff[hfc->ctrl_in_idx];	/* pointer to new index */
+	buf->hfc_reg = reg;
+	buf->reg_val = val;
+	buf->action=action;
+	if (++hfc->ctrl_in_idx >= HFC_CTRL_BUFSIZE)
+		hfc->ctrl_in_idx = 0;	/* pointer wrap */
+	if (++hfc->ctrl_cnt == 1)
+		ctrl_start_transfer(hfc);
+	return(0);
+}		/* queue_control_request */
+
+
+static int control_action_handler(hfcusb_data *hfc,int reg,int val,int action)
+{
+	if(!action) return(1);  // no action defined
+
+	return(0);
+}
+
+
+/***************************************************************/
+/* control completion routine handling background control cmds */
+/***************************************************************/
+static void ctrl_complete(struct urb *urb, struct pt_regs *regs)
+{
+	hfcusb_data *hfc = (hfcusb_data *) urb->context;
+	ctrl_buft *buf;
+
+	printk(KERN_DEBUG "ctrl_complete cnt %d\n", hfc->ctrl_cnt);
+	urb->dev = hfc->dev;
+	if(hfc->ctrl_cnt)
+	{
+		buf=&hfc->ctrl_buff[hfc->ctrl_out_idx];
+		control_action_handler(hfc,buf->hfc_reg,buf->reg_val,buf->action);
+
+		hfc->ctrl_cnt--;	/* decrement actual count */
+		if(++hfc->ctrl_out_idx >= HFC_CTRL_BUFSIZE) hfc->ctrl_out_idx = 0;	/* pointer wrap */
+
+		ctrl_start_transfer(hfc);	/* start next transfer */
+	}
+}				/* ctrl_complete */
+
+
+
+#define LED_OFF      0   // no LED support
+#define LED_SCHEME1  1	 // LED standard scheme
+#define LED_SCHEME2  2	 // not used yet...
+
+#define LED_POWER_ON	1
+#define LED_POWER_OFF	2
+#define LED_S0_ON		3
+#define LED_S0_OFF		4
+#define LED_B1_ON		5
+#define LED_B1_OFF		6
+#define LED_B1_DATA		7
+#define LED_B2_ON		8
+#define LED_B2_OFF		9
+#define LED_B2_DATA	   10
+
+#define LED_NORMAL   0	 // LEDs are normal
+#define LED_INVERTED 1   // LEDs are inverted
+
+// time for LED flashing
+#define LED_TIME      250
+
+vendor_data vdata[]=
+{
+    {0x959, 0x2bd0, "ISDN USB TA (Cologne Chip HFC-S USB based)", LED_OFF,LED_NORMAL,{4,0,2,1}},     /* CologneChip Eval TA */
+	{0x7b0, 0x0007, "Billion tiny USB ISDN TA 128", LED_SCHEME1,  LED_INVERTED, {8,0x40,0x20,0x10}},  /* Billion TA */
+	{0x742, 0x2008, "Stollmann USB TA",             LED_SCHEME1,  LED_NORMAL,   {4,0,2,1}},           /* Stollmann TA */
+	{0x8e3, 0x0301, "Olitec USB RNIS",              LED_SCHEME1,  LED_NORMAL,   {2,0,1,4}},           /* Olitec TA  */
+	{0x675, 0x1688, "DrayTec USB ISDN TA",          LED_SCHEME1,  LED_NORMAL,   {4,0,2,1}},           /* Draytec TA */
+	{0x7fa, 0x0846, "Bewan Modem RNIS USB",         LED_SCHEME1,  LED_INVERTED, {8,0x40,0x20,0x10}},  /* Bewan TA   */
+	{0,0,0}			   // EOL element
+};
+										
+/***************************************************/
+/* write led data to auxport & invert if necessary */
+/***************************************************/
+static void write_led(hfcusb_data * hfc,__u8 led_state)
+{
+	if(led_state!=hfc->led_state)
+	{
+		hfc->led_state=led_state;
+		queue_control_request(hfc, HFCUSB_P_DATA,(vdata[hfc->vend_idx].led_invert) ? ~led_state : led_state,1);
+	}
+}
+
+/******************************************/
+/* invert B-channel LEDs if data is sent  */
+/******************************************/
+static void led_timer(hfcusb_data * hfc)
+{
+   	static int cnt=0;
+	__u8 led_state=hfc->led_state;
+
+	if(cnt)
+	{
+		if(hfc->led_b_active&1) led_state|=vdata[hfc->vend_idx].led_bits[2];
+		if(hfc->led_b_active&2) led_state|=vdata[hfc->vend_idx].led_bits[3];
+	}
+	else
+	{
+		if(!(hfc->led_b_active&1) || hfc->led_new_data&1) led_state&=~vdata[hfc->vend_idx].led_bits[2];
+		if(!(hfc->led_b_active&2) || hfc->led_new_data&2) led_state&=~vdata[hfc->vend_idx].led_bits[3];
+	}
+
+	write_led(hfc,led_state);
+	hfc->led_new_data=0;
+
+	cnt=!cnt;
+	// restart 4 hz timer
+	hfc->led_timer.expires = jiffies + (LED_TIME * HZ) / 1000;
+	if(!timer_pending(&hfc->led_timer)) add_timer(&hfc->led_timer);
+}
+
+/**************************/
+/* handle LED requests    */
+/**************************/
+static void handle_led(hfcusb_data * hfc,int event)
+{
+	__u8 led_state=hfc->led_state;
+
+	// if no scheme -> no LED action
+   	if(vdata[hfc->vend_idx].led_scheme==LED_OFF) return;
+
+	switch(event)
+	{
+		case LED_POWER_ON:
+				   led_state|=vdata[hfc->vend_idx].led_bits[0];
+				break;
+		case LED_POWER_OFF: // no Power off handling
+				break;
+		case LED_S0_ON:
+				   led_state|=vdata[hfc->vend_idx].led_bits[1];
+				break;
+		case LED_S0_OFF:
+				   led_state&=~vdata[hfc->vend_idx].led_bits[1];
+				break;
+		case LED_B1_ON:
+					hfc->led_b_active|=1;
+				break;
+		case LED_B1_OFF:
+					hfc->led_b_active&=~1;
+				break;
+		case LED_B1_DATA:
+				   hfc->led_new_data|=1;
+				break;
+		case LED_B2_ON:
+				   hfc->led_b_active|=2;
+				break;
+		case LED_B2_OFF:
+					hfc->led_b_active&=~2;
+				break;
+		case LED_B2_DATA:
+				   hfc->led_new_data|=2;
+				break;
+	}
+	
+	write_led(hfc,led_state);
+}
+
+/********************************/
+/* called when timer t3 expires */
+/********************************/
+static void l1_timer_expire_t3(hfcusb_data * hfc)
+{
+    //printk (KERN_INFO "HFC-USB: l1_timer_expire_t3\n");
+
+	hfc->d_if.ifc.l1l2(&hfc->d_if.ifc,PH_DEACTIVATE | INDICATION,NULL);
+#ifdef VERBOSE_USB_DEBUG
+	printk(KERN_INFO "PH_DEACTIVATE | INDICATION sent\n");
+#endif
+	hfc->l1_activated=FALSE;
+	handle_led(hfc,LED_S0_OFF);
+}
+
+/********************************/
+/* called when timer t4 expires */
+/********************************/
+static void l1_timer_expire_t4(hfcusb_data * hfc)
+{
+    //printk (KERN_INFO "HFC-USB: l1_timer_expire_t4\n");
+
+	hfc->d_if.ifc.l1l2(&hfc->d_if.ifc,PH_DEACTIVATE | INDICATION,NULL);
+#ifdef VERBOSE_USB_DEBUG
+	printk(KERN_INFO "PH_DEACTIVATE | INDICATION sent\n");
+#endif
+	hfc->l1_activated=FALSE;
+	handle_led(hfc,LED_S0_OFF);
+}
+
+/*****************************/
+/* handle S0 state changes   */
+/*****************************/
+static void state_handler(hfcusb_data * hfc,__u8 state)
+{
+	__u8 old_state;
+
+	old_state=hfc->l1_state;
+
+	// range check
+	if(state==old_state || state<1 || state>8) return;
+
+#ifdef VERBOSE_ISDN_DEBUG
+	printk(KERN_INFO "HFC-USB: new S0 state:%d old_state:%d\n",state,old_state);
+#endif
+
+	if(state<4 || state==7 || state==8)
+	{
+        if(timer_pending(&hfc->t3_timer)) del_timer(&hfc->t3_timer);
+		//printk(KERN_INFO "HFC-USB: T3 deactivated\n");
+	}
+
+	if(state>=7)
+	{
+        if(timer_pending(&hfc->t4_timer)) del_timer(&hfc->t4_timer);
+		//printk(KERN_INFO "HFC-USB: T4 deactivated\n");
+	}
+
+	if(state==7 && !hfc->l1_activated)
+	{
+		hfc->d_if.ifc.l1l2(&hfc->d_if.ifc,PH_ACTIVATE | INDICATION,NULL);
+		//printk(KERN_INFO "HFC-USB: PH_ACTIVATE | INDICATION sent\n");
+		hfc->l1_activated=TRUE;
+		handle_led(hfc,LED_S0_ON);
+	}
+	else
+	if(state<=3 /* && activated*/)
+	{
+		if(old_state==7 || old_state==8)
+		{
+			//printk(KERN_INFO "HFC-USB: T4 activated\n");
+			hfc->t4_timer.expires = jiffies + (HFC_TIMER_T4 * HZ) / 1000;
+			if(!timer_pending(&hfc->t4_timer)) add_timer(&hfc->t4_timer);
+		}
+		else
+		{
+			hfc->d_if.ifc.l1l2(&hfc->d_if.ifc,PH_DEACTIVATE | INDICATION,NULL);
+			//printk(KERN_INFO "HFC-USB: PH_DEACTIVATE | INDICATION sent\n");
+			hfc->l1_activated=FALSE;
+			handle_led(hfc,LED_S0_OFF);
+		}
+	}
+
+	hfc->l1_state=state;
+}
+
+
+/* prepare iso urb */
+static void fill_isoc_urb(struct urb *urb, struct usb_device *dev, unsigned int pipe, void *buf,
+	int num_packets, int packet_size, int interval, usb_complete_t complete, void *context)
+{
+	int k;
+
+	spin_lock_init(&urb->lock);	// do we really need spin_lock_init ?
+	urb->dev = dev;
+	urb->pipe = pipe;
+	urb->complete = complete;
+	urb->number_of_packets = num_packets;
+	urb->transfer_buffer_length = packet_size * num_packets;
+	urb->context = context;
+	urb->transfer_buffer = buf;
+	urb->transfer_flags = 0;
+	urb->transfer_flags = URB_ISO_ASAP;
+	urb->actual_length = 0;
+	urb->interval = interval;
+	for (k = 0; k < num_packets; k++) {
+		urb->iso_frame_desc[k].offset = packet_size * k;
+		urb->iso_frame_desc[k].length = packet_size;
+		urb->iso_frame_desc[k].actual_length = 0;
+	}
+}
+
+/* allocs urbs and start isoc transfer with two pending urbs to avoid gaps in the transfer chain */
+static int start_isoc_chain(usb_fifo * fifo, int num_packets_per_urb,usb_complete_t complete,int packet_size)
+{
+	int i, k, errcode;
+
+#ifdef VERBOSE_USB_DEBUG
+	printk(KERN_INFO "HFC-USB: starting ISO-chain for Fifo %i\n",  fifo->fifonum);
+#endif
+
+
+	// allocate Memory for Iso out Urbs
+	for (i = 0; i < 2; i++) {
+		if (!(fifo->iso[i].purb)) {
+			fifo->iso[i].purb = usb_alloc_urb(num_packets_per_urb, GFP_KERNEL);
+			fifo->iso[i].owner_fifo = (struct usb_fifo *) fifo;
+
+			// Init the first iso
+			if (ISO_BUFFER_SIZE >= (fifo->usb_packet_maxlen * num_packets_per_urb))
+			{
+
+				fill_isoc_urb(fifo->iso[i].purb, fifo->hfc->dev, fifo->pipe, fifo->iso[i].buffer,
+					num_packets_per_urb, fifo->usb_packet_maxlen, fifo->intervall,
+					complete, &fifo->iso[i]);
+
+				memset(fifo->iso[i].buffer, 0, sizeof(fifo->iso[i].buffer));
+
+				// defining packet delimeters in fifo->buffer
+				for(k = 0; k < num_packets_per_urb; k++)
+				{
+					fifo->iso[i].purb->iso_frame_desc[k].offset = k*packet_size;
+					fifo->iso[i].purb->iso_frame_desc[k].length = packet_size;
+				}
+			}
+		}
+
+		fifo->bit_line = BITLINE_INF;
+
+		errcode = usb_submit_urb(fifo->iso[i].purb, GFP_KERNEL);
+		fifo->active = (errcode >= 0) ? 1 : 0;
+		if(errcode < 0)
+		{
+			printk(KERN_INFO "HFC-USB: error submitting ISO URB: %i.%i \n",  errcode, i);
+		};
+
+	}
+
+	// errcode = (usb_submit_urb(fifo->iso[0].purb, GFP_KERNEL));
+	return(fifo->active);
+}
+
+/* stops running iso chain and frees their pending urbs */
+static void stop_isoc_chain(usb_fifo * fifo)
+{
+	int i;
+
+	for(i = 0; i < 2; i++)
+	{
+		if(fifo->iso[i].purb)
+		{
+#ifdef VERBOSE_USB_DEBUG
+			printk(KERN_INFO "HFC-USB: Stopping iso chain for fifo %i.%i\n", fifo->fifonum, i);
+#endif
+			usb_unlink_urb(fifo->iso[i].purb);
+			usb_free_urb(fifo->iso[i].purb);
+			fifo->iso[i].purb = NULL;
+		}
+	}
+	if (fifo->urb) {
+		usb_unlink_urb(fifo->urb);
+		usb_free_urb(fifo->urb);
+		fifo->urb = NULL;
+	}
+	fifo->active = 0;
+}
+
+// defines how much ISO packets are handled in one URB
+static int iso_packets[8]={ISOC_PACKETS_B,ISOC_PACKETS_B,ISOC_PACKETS_B,ISOC_PACKETS_B,
+	                       ISOC_PACKETS_D,ISOC_PACKETS_D,ISOC_PACKETS_D,ISOC_PACKETS_D};
+
+/*****************************************************/
+/* transmit completion routine for all ISO tx fifos */
+/*****************************************************/
+static void tx_iso_complete(struct urb *urb, struct pt_regs *regs)
+{
+	iso_urb_struct *context_iso_urb = (iso_urb_struct *) urb->context;
+	usb_fifo *fifo = context_iso_urb->owner_fifo;
+	hfcusb_data *hfc = fifo->hfc;
+	int k, tx_offset, num_isoc_packets, sink, len, current_len,errcode,frame_complete,transp_mode,fifon;
+	__u8 threshbit;
+	__u8 threshtable[8] = { 1, 2, 4, 8, 0x10, 0x20, 0x40, 0x80};
+
+	fifon=fifo->fifonum;
+	tx_offset=0;
+	// very weird error code when using ohci drivers, for now : ignore this error ...  (MB)
+	if(urb->status == -EOVERFLOW)
+	{
+		urb->status = 0;
+#ifdef VERBOSE_USB_DEBUG
+		printk(KERN_INFO "HFC-USB: ignoring USB DATAOVERRUN  for fifo  %i \n",fifon);
+#endif
+	}
+
+	if(fifo->active && !urb->status)
+	{
+		transp_mode=0;
+		if(fifon<4 && hfc->b_mode[fifon/2]==L1_MODE_TRANS) transp_mode=TRUE;
+
+		threshbit = threshtable[fifon] & hfc->threshold_mask;	// is threshold set for our channel?
+		num_isoc_packets=iso_packets[fifon];
+
+		if(fifon >= HFCUSB_D_TX)
+		{
+			sink = (threshbit) ? SINK_DMIN : SINK_DMAX;	// how much bit go to the sink for D-channel?
+		}
+		else
+		{
+			sink = (threshbit) ? SINK_MIN : SINK_MAX;	// how much bit go to the sink for B-channel?
+		}
+
+		// prepare ISO Urb
+		fill_isoc_urb(urb, fifo->hfc->dev, fifo->pipe,context_iso_urb->buffer, num_isoc_packets,
+			fifo->usb_packet_maxlen, fifo->intervall, tx_iso_complete, urb->context);
+		memset(context_iso_urb->buffer, 0, sizeof(context_iso_urb->buffer));
+
+		frame_complete=FALSE;
+
+		// Generate Iso Packets
+		for(k = 0; k < num_isoc_packets; ++k)
+		{
+			if(fifo->skbuff)
+			{
+				len = fifo->skbuff->len;	// remaining length
+
+				fifo->bit_line -= sink;	// we lower data margin every msec
+				current_len = (0 - fifo->bit_line) / 8;
+				if(current_len > 14) current_len = 14;	// maximum 15 byte for every ISO packet makes our life easier
+				current_len = (len <= current_len) ? len : current_len;
+				fifo->bit_line += current_len * 8;	// how much bit do we put on the line?
+
+				context_iso_urb->buffer[tx_offset] = 0;
+				if(current_len == len)
+				{
+					if(!transp_mode)
+					{
+						context_iso_urb->buffer[tx_offset] = 1;	// here frame completion
+						fifo->bit_line += 32;	// add 2 byte flags and 16bit CRC at end of ISDN frame
+					}
+					frame_complete = TRUE;
+				}
+
+				// copy bytes from buffer into ISO_URB
+				memcpy(context_iso_urb->buffer+tx_offset+1,fifo->skbuff->data,current_len);
+				skb_pull(fifo->skbuff,current_len);
+
+				// define packet delimeters within the URB buffer
+				urb->iso_frame_desc[k].offset = tx_offset;
+				urb->iso_frame_desc[k].length = current_len + 1;
+
+				tx_offset += (current_len + 1);
+				// printk(KERN_INFO "HFC-USB: fifonum:%d,%d bytes to send, %d bytes ISO packet,bitline:%d,sink:%d,threshbit:%d,threshmask:%x\n",fifon,len,current_len,fifo->bit_line,sink,threshbit,hfc->threshold_mask);
+				if(!transp_mode)
+				{
+					if(fifon==HFCUSB_B1_TX) handle_led(hfc,LED_B1_DATA);
+					if(fifon==HFCUSB_B2_TX) handle_led(hfc,LED_B2_DATA);
+				}
+			}
+			else
+			{
+				// we have no more data - generate 1 byte ISO packets
+				urb->iso_frame_desc[k].offset = tx_offset++;
+
+				urb->iso_frame_desc[k].length = 1;
+				fifo->bit_line -= sink;	// we lower data margin every msec
+
+				if(fifo->bit_line < BITLINE_INF)
+				{
+					fifo->bit_line = BITLINE_INF;
+					//printk (KERN_INFO "HFC-USB: BITLINE_INF underrun\n");
+				}
+			}
+
+			if(frame_complete)
+			{
+				// delete the buffer only once, here or in hfc_usb_l2l1() in a PH_DATA|REQUEST
+				fifo->delete_flg=TRUE;
+
+				fifo->hif->l1l2(fifo->hif,PH_DATA|CONFIRM,(void*)fifo->skbuff->truesize);
+
+				if(fifo->skbuff && fifo->delete_flg)
+				{
+					dev_kfree_skb_any(fifo->skbuff);
+					//printk(KERN_INFO "HFC-USB: skbuff=NULL on fifo:%d\n",fifo->fifonum);
+					fifo->skbuff = NULL;
+					fifo->delete_flg=FALSE;
+				}
+
+				frame_complete=FALSE;
+			}
+        }
+
+		errcode = usb_submit_urb(urb, GFP_KERNEL);
+		if(errcode < 0)
+		{
+			printk(KERN_INFO "HFC-USB: error submitting ISO URB: %i \n",  errcode);
+		}
+	}
+	else
+	{
+		if(urb->status)
+		{
+			printk(KERN_INFO "HFC-USB: tx_iso_complete : urb->status %i, fifonum %i\n",  urb->status,fifon);
+		}
+	}
+
+}				/* tx_iso_complete */
+
+/*****************************************************/
+/* receive completion routine for all ISO tx fifos   */
+/*****************************************************/
+static void rx_iso_complete(struct urb *urb, struct pt_regs *regs)
+{
+	iso_urb_struct *context_iso_urb = (iso_urb_struct *) urb->context;
+	usb_fifo *fifo = context_iso_urb->owner_fifo;
+	hfcusb_data *hfc = fifo->hfc;
+	int k, len, errcode, offset, num_isoc_packets,fifon;
+	__u8 *buf;
+
+	fifon=fifo->fifonum;
+	// very weird error code when using ohci drivers, for now : ignore this error ...  (MB)
+	if(urb->status == -EOVERFLOW)
+	{
+		urb->status = 0;
+#ifdef VERBOSE_USB_DEBUG
+		printk(KERN_INFO "HFC-USB: ignoring USB DATAOVERRUN  for fifo  %i \n",fifon);
+#endif
+	}
+
+	if(fifo->active && !urb->status)
+	{
+		num_isoc_packets=iso_packets[fifon];
+
+		// Generate D-Channel Iso Packets
+		for(k = 0; k < num_isoc_packets; ++k)
+		{
+			len=urb->iso_frame_desc[k].actual_length;
+			offset=urb->iso_frame_desc[k].offset;
+			buf=context_iso_urb->buffer+offset;
+
+			if(fifo->last_urblen!=fifo->usb_packet_maxlen)
+			{
+				// the threshold mask is in the 2nd status byte
+				hfc->threshold_mask=buf[1];
+				// the S0 state is in the upper half of the 1st status byte
+				state_handler(hfc,buf[0] >> 4);
+				// if we have more than the 2 status bytes -> collect data
+				if(len>2) collect_rx_frame(fifo,buf+2,len-2,buf[0]&1);
+			}
+			else collect_rx_frame(fifo,buf,len,0);
+
+			fifo->last_urblen=len;
+
+        }
+
+		// prepare ISO Urb
+		fill_isoc_urb(urb, fifo->hfc->dev, fifo->pipe,context_iso_urb->buffer, num_isoc_packets,
+			fifo->usb_packet_maxlen, fifo->intervall, rx_iso_complete, urb->context);
+
+		errcode = usb_submit_urb(urb, GFP_KERNEL);
+		if(errcode < 0)
+		{
+			printk(KERN_INFO "HFC-USB: error submitting ISO URB: %i \n",  errcode);
+		}
+	}
+	else
+	{
+		if(urb->status)
+		{
+			printk(KERN_INFO "HFC-USB: rx_iso_complete : urb->status %i, fifonum %i\n",  urb->status,fifon);
+		}
+	}
+}				/* rx_iso_complete */
+
+
+/*****************************************************/
+/* collect data from interrupt or isochron in        */
+/*****************************************************/
+static void collect_rx_frame(usb_fifo *fifo,__u8 *data,int len,int finish)
+{
+	hfcusb_data *hfc = fifo->hfc;
+	int transp_mode,fifon;
+
+	fifon=fifo->fifonum;
+	transp_mode=0;
+	if(fifon<4 && hfc->b_mode[fifon/2]==L1_MODE_TRANS) transp_mode=TRUE;
+
+	//printk(KERN_INFO "HFC-USB: got %d bytes finish:%d max_size:%d fifo:%d\n",len,finish,fifo->max_size,fifon);
+	if(!fifo->skbuff)
+	{
+		// allocate sk buffer
+		fifo->skbuff=dev_alloc_skb(fifo->max_size + 3);
+		if(!fifo->skbuff)
+		{
+			printk(KERN_INFO "HFC-USB: cannot allocate buffer (dev_alloc_skb) fifo:%d\n",fifon);
+			return;
+		}
+		
+	}
+
+	if(len && fifo->skbuff->len+len<fifo->max_size)
+	{
+		memcpy(skb_put(fifo->skbuff,len),data,len);
+	}
+	else printk(KERN_INFO "HCF-USB: got frame exceeded fifo->max_size:%d\n",fifo->max_size);
+
+	// give transparent data up, when 128 byte are available
+	if(transp_mode && fifo->skbuff->len>=128)
+	{
+		fifo->hif->l1l2(fifo->hif,PH_DATA | INDICATION,fifo->skbuff);
+		fifo->skbuff = NULL;  // buffer was freed from upper layer
+		return;
+	}
+
+	// we have a complete hdlc packet
+	if(finish)
+	{
+		if(!fifo->skbuff->data[fifo->skbuff->len-1])
+		{
+			skb_trim(fifo->skbuff,fifo->skbuff->len-3);  // remove CRC & status
+
+			//printk(KERN_INFO "HFC-USB: got frame %d bytes on fifo:%d\n",fifo->skbuff->len,fifon);
+
+			if(fifon==HFCUSB_PCM_RX) fifo->hif->l1l2(fifo->hif,PH_DATA_E | INDICATION,fifo->skbuff);
+			else fifo->hif->l1l2(fifo->hif,PH_DATA | INDICATION,fifo->skbuff);
+
+			fifo->skbuff = NULL;  // buffer was freed from upper layer
+		}
+		else
+		{
+			printk(KERN_INFO "HFC-USB: got frame %d bytes but CRC ERROR!!!\n",fifo->skbuff->len);
+
+			skb_trim(fifo->skbuff,0);  // clear whole buffer
+		}
+	}
+
+	// LED flashing only in HDLC mode
+	if(!transp_mode)
+	{
+		if(fifon==HFCUSB_B1_RX) handle_led(hfc,LED_B1_DATA);
+		if(fifon==HFCUSB_B2_RX) handle_led(hfc,LED_B2_DATA);
+	}
+}
+
+/***********************************************/
+/* receive completion routine for all rx fifos */
+/***********************************************/
+static void rx_complete(struct urb *urb, struct pt_regs *regs)
+{
+	int len;
+	__u8 *buf;
+	usb_fifo *fifo = (usb_fifo *) urb->context;	/* pointer to our fifo */
+	hfcusb_data *hfc = fifo->hfc;
+
+	urb->dev = hfc->dev;	/* security init */
+
+	if((!fifo->active) || (urb->status)) {
+#ifdef VERBOSE_USB_DEBUG
+		printk(KERN_INFO "HFC-USB: RX-Fifo %i is going down (%i)\n", fifo->fifonum, urb->status);
+#endif
+		fifo->urb->interval = 0;	/* cancel automatic rescheduling */
+		if(fifo->skbuff) {
+			dev_kfree_skb_any(fifo->skbuff);
+			fifo->skbuff = NULL;
+		}
+		return;
+	}
+
+	len=urb->actual_length;
+	buf=fifo->buffer;
+
+	if(fifo->last_urblen!=fifo->usb_packet_maxlen) {
+		// the threshold mask is in the 2nd status byte
+		hfc->threshold_mask=buf[1];
+		// the S0 state is in the upper half of the 1st status byte
+		state_handler(hfc,buf[0] >> 4);
+		// if we have more than the 2 status bytes -> collect data
+		if(len>2) collect_rx_frame(fifo,buf+2,urb->actual_length-2,buf[0]&1);
+	} else
+		collect_rx_frame(fifo,buf,urb->actual_length,0);
+
+	fifo->last_urblen=urb->actual_length;
+
+
+}	/* rx_complete */
+
+
+
+/***************************************************/
+/* start the interrupt transfer for the given fifo */
+/***************************************************/
+static void start_int_fifo(usb_fifo * fifo)
+{
+	int errcode;
+
+#ifdef VERBOSE_USB_DEBUG
+	printk(KERN_INFO "HFC-USB: starting intr IN fifo:%d\n", fifo->fifonum);
+#endif
+	if (!fifo->urb) {
+		fifo->urb = usb_alloc_urb(0, GFP_KERNEL);
+		if (!fifo->urb)
+			return;
+	}
+	usb_fill_int_urb(fifo->urb, fifo->hfc->dev, fifo->pipe, fifo->buffer,
+				 fifo->usb_packet_maxlen, rx_complete, fifo, fifo->intervall);
+	fifo->active = 1;		/* must be marked active */
+	errcode = usb_submit_urb(fifo->urb, GFP_KERNEL);
+
+	if(errcode)
+	{
+		printk(KERN_INFO "HFC-USB: submit URB error(start_int_info): status:%i\n",   errcode);
+		fifo->active = 0;
+		fifo->skbuff = NULL;
+	}
+} /* start_int_fifo */
+
+/*****************************/
+/* set the B-channel mode    */
+/*****************************/
+static void set_hfcmode(hfcusb_data *hfc,int channel,int mode)
+{
+	__u8 val,idx_table[2]={0,2};
+
+#ifdef VERBOSE_ISDN_DEBUG
+  printk (KERN_INFO "HFC-USB: setting channel %d to mode %d\n",channel,mode);
+#endif
+
+	hfc->b_mode[channel]=mode;
+
+	// setup CON_HDLC
+	val=0;
+	if(mode!=L1_MODE_NULL) val=8;    // enable fifo?
+	if(mode==L1_MODE_TRANS) val|=2;  // set transparent bit
+
+	queue_control_request(hfc,HFCUSB_FIFO,idx_table[channel],1); // set FIFO to transmit register
+	queue_control_request(hfc,HFCUSB_CON_HDLC,val,1);
+	queue_control_request(hfc,HFCUSB_INC_RES_F,2,1); // reset fifo
+
+	queue_control_request(hfc,HFCUSB_FIFO,idx_table[channel]+1,1); // set FIFO to receive register
+	queue_control_request(hfc,HFCUSB_CON_HDLC,val,1);
+	queue_control_request(hfc,HFCUSB_INC_RES_F,2,1);  // reset fifo
+
+	val=0x40;
+	if(hfc->b_mode[0]) val|=1;
+	if(hfc->b_mode[1]) val|=2;
+	queue_control_request(hfc,HFCUSB_SCTRL,val,1);
+
+	val=0;
+	if(hfc->b_mode[0]) val|=1;
+	if(hfc->b_mode[1]) val|=2;
+	queue_control_request(hfc,HFCUSB_SCTRL_R,val,1);
+
+	if(mode==L1_MODE_NULL)
+	{
+		if(channel) handle_led(hfc,LED_B2_OFF);
+		else handle_led(hfc,LED_B1_OFF);
+	}
+	else
+	{
+		if(channel) handle_led(hfc,LED_B2_ON);
+		else handle_led(hfc,LED_B1_ON);
+	}
+}
+
+/*
+   --------------------------------------------------------------------------------------
+   from here : hisax_if callback routines :
+     - void hfc_usb_d_l2l1(struct hisax_if *hisax_d_if, int pr, void *arg) {
+
+   l1 to l2 routines :
+     - static void hfc_usb_l1l2(hfcusb_data * hfc)
+
+*/
+
+void hfc_usb_l2l1(struct hisax_if *my_hisax_if, int pr, void *arg)
+{
+    usb_fifo *fifo = my_hisax_if->priv;
+	hfcusb_data *hfc = fifo->hfc;
+
+    switch (pr) {
+		case PH_ACTIVATE | REQUEST:
+				if(fifo->fifonum==HFCUSB_D_TX)
+				{
+#ifdef VERBOSE_ISDN_DEBUG
+					printk (KERN_INFO "HFC_USB: hfc_usb_d_l2l1 D-chan: PH_ACTIVATE | REQUEST\n");
+#endif
+					queue_control_request(hfc, HFCUSB_STATES,0x60,1);	/* make activation */
+					hfc->t3_timer.expires = jiffies + (HFC_TIMER_T3 * HZ) / 1000;
+					if(!timer_pending(&hfc->t3_timer)) add_timer(&hfc->t3_timer);
+				}
+				else
+				{
+#ifdef VERBOSE_ISDN_DEBUG
+					printk (KERN_INFO "HFC_USB: hfc_usb_d_l2l1 Bx-chan: PH_ACTIVATE | REQUEST\n");
+#endif
+					set_hfcmode(hfc,(fifo->fifonum==HFCUSB_B1_TX) ? 0 : 1 ,(int)arg);
+					fifo->hif->l1l2(fifo->hif,PH_ACTIVATE | INDICATION, NULL);
+				}
+                break;
+        case PH_DEACTIVATE | REQUEST:
+				if(fifo->fifonum==HFCUSB_D_TX)
+				{
+#ifdef VERBOSE_ISDN_DEBUG
+					printk (KERN_INFO "HFC_USB: hfc_usb_d_l2l1 D-chan: PH_DEACTIVATE | REQUEST\n");
+#endif
+					printk (KERN_INFO "HFC-USB: ISDN TE device should not deativate...\n");
+				}
+				else
+				{
+#ifdef VERBOSE_ISDN_DEBUG
+					printk (KERN_INFO "HFC_USB: hfc_usb_d_l2l1 Bx-chan: PH_DEACTIVATE | REQUEST\n");
+#endif
+					set_hfcmode(hfc,(fifo->fifonum==HFCUSB_B1_TX) ? 0 : 1 ,(int)L1_MODE_NULL);
+					fifo->hif->l1l2(fifo->hif,PH_DEACTIVATE | INDICATION, NULL);
+				}
+                break;
+		case PH_DATA | REQUEST:
+				if(fifo->skbuff && fifo->delete_flg)
+				{
+					dev_kfree_skb_any(fifo->skbuff);
+					//printk(KERN_INFO "skbuff=NULL on fifo:%d\n",fifo->fifonum);
+					fifo->skbuff = NULL;
+					fifo->delete_flg=FALSE;
+				}
+
+				fifo->skbuff=arg; // we have a new buffer
+
+				//if(fifo->fifonum==HFCUSB_D_TX) printk (KERN_INFO "HFC_USB: hfc_usb_d_l2l1 D-chan: PH_DATA | REQUEST\n");
+				//else printk (KERN_INFO "HFC_USB: hfc_usb_d_l2l1 Bx-chan: PH_DATA | REQUEST\n");
+                break;
+        default:
+                printk (KERN_INFO "HFC_USB: hfc_usb_d_l2l1: unkown state : %#x\n", pr);
+                break;
+    }
+}
+
+// valid configurations
+#define CNF_4INT3ISO  1      // 4 INT IN, 3 ISO OUT
+#define CNF_3INT3ISO  2      // 3 INT IN, 3 ISO OUT
+#define CNF_4ISO3ISO  3      // 4 ISO IN, 3 ISO OUT
+#define CNF_3ISO3ISO  4 	 // 3 ISO IN, 3 ISO OUT
+
+
+/*
+   --------------------------------------------------------------------------------------
+   From here on USB initialization and deactivation related routines are implemented :
+
+   - hfc_usb_init :
+      is the main Entry Point for the USB Subsystem when the device get plugged
+      in. This function calls usb_register with usb_driver as parameter.
+      Here, further entry points for probing (hfc_usb_probe) and disconnecting
+      the device (hfc_usb_disconnect) are published, as the id_table
+
+   - hfc_usb_probe
+      this function is called by the usb subsystem, and steps through the alternate
+      settings of the currently plugged in device to detect all Endpoints needed to
+      run an ISDN TA.
+      Needed EndPoints are
+      3 (+1) IntIn EndPoints   (D-in,  E-in, B1-in, B2-in, (E-in)) or
+      3 (+1) Isochron In Endpoints (D-out, B1-out, B2-out) and 3 IsoOut Endpoints
+      The currently used transfer mode of on the Out-Endpoints will be stored in
+      hfc->usb_transfer_mode and is either USB_INT or USB_ISO
+      When a valid alternate setting could be found, the usb_init (see blow)
+      function is called
+
+   - usb_init
+      Here, the HFC_USB Chip itself gets initialized and the USB framework to send/receive
+      Data to/from the several EndPoints are initialized:
+       The E- and D-Channel Int-In chain gets started
+       The IsoChain for the Iso-Out traffic get started
+
+   - hfc_usb_disconnect
+      this function is called by the usb subsystem and has to free all resources
+      and stop all usb traffic to allow a proper hotplugging disconnect.
+
+*/
+
+/***************************************************************************/
+/* usb_init is called once when a new matching device is detected to setup */
+/* main parameters. It registers the driver at the main hisax module.       */
+/* on success 0 is returned.                                               */
+/***************************************************************************/
+static int usb_init(hfcusb_data * hfc)
+{
+	usb_fifo *fifo;
+	int i, err;
+	u_char b;
+	struct hisax_b_if *p_b_if[2];
+	
+	/* check the chip id */
+	printk(KERN_INFO "HFCUSB_CHIP_ID begin\n");
+	if (read_usb(hfc, HFCUSB_CHIP_ID, &b) != 1) {
+		printk(KERN_INFO "HFC-USB: cannot read chip id\n");
+		return(1); 
+	}
+	printk(KERN_INFO "HFCUSB_CHIP_ID %x\n", b);
+	if (b != HFCUSB_CHIPID) {
+		printk(KERN_INFO "HFC-USB: Invalid chip id 0x%02x\n", b);
+		return(1);
+	}
+
+	/* first set the needed config, interface and alternate */
+	printk(KERN_INFO "usb_init 1\n");
+//	usb_set_configuration(hfc->dev, 1);
+	printk(KERN_INFO "usb_init 2\n");
+	err = usb_set_interface(hfc->dev, hfc->if_used, hfc->alt_used);
+	printk(KERN_INFO "usb_init usb_set_interface return %d\n", err);
+	/* now we initialize the chip */
+	write_usb(hfc, HFCUSB_CIRM, 8);	    // do reset
+	write_usb(hfc, HFCUSB_CIRM, 0x10);	// aux = output, reset off
+
+	// set USB_SIZE to match the the wMaxPacketSize for INT or BULK transfers
+	write_usb(hfc, HFCUSB_USB_SIZE,(hfc->packet_size/8) | ((hfc->packet_size/8) << 4));
+
+	// set USB_SIZE_I to match the the wMaxPacketSize for ISO transfers
+	write_usb(hfc, HFCUSB_USB_SIZE_I, hfc->iso_packet_size);
+
+	/* enable PCM/GCI master mode */
+	write_usb(hfc, HFCUSB_MST_MODE1, 0);	/* set default values */
+	write_usb(hfc, HFCUSB_MST_MODE0, 1);	/* enable master mode */
+
+	/* init the fifos */
+	write_usb(hfc, HFCUSB_F_THRES, (HFCUSB_TX_THRESHOLD/8) |((HFCUSB_RX_THRESHOLD/8) << 4));
+
+	fifo = hfc->fifos;
+	for(i = 0; i < HFCUSB_NUM_FIFOS; i++)
+	{
+		write_usb(hfc, HFCUSB_FIFO, i);	/* select the desired fifo */
+		fifo[i].skbuff = NULL;	/* init buffer pointer */
+		fifo[i].max_size = (i <= HFCUSB_B2_RX) ? MAX_BCH_SIZE : MAX_DFRAME_LEN;
+		fifo[i].last_urblen=0;
+		write_usb(hfc, HFCUSB_HDLC_PAR, ((i <= HFCUSB_B2_RX) ? 0 : 2));	    // set 2 bit for D- & E-channel
+		write_usb(hfc, HFCUSB_CON_HDLC, ((i==HFCUSB_D_TX) ? 0x09 : 0x08));	// rx hdlc, enable IFF for D-channel
+		write_usb(hfc, HFCUSB_INC_RES_F, 2);	/* reset the fifo */
+	}
+
+	write_usb(hfc, HFCUSB_CLKDEL, 0x0f);	 /* clock delay value */
+	write_usb(hfc, HFCUSB_STATES, 3 | 0x10); /* set deactivated mode */
+	write_usb(hfc, HFCUSB_STATES, 3);	     /* enable state machine */
+
+	write_usb(hfc, HFCUSB_SCTRL_R, 0);	     /* disable both B receivers */
+	write_usb(hfc, HFCUSB_SCTRL, 0x40);	     /* disable B transmitters + capacitive mode */
+
+	// set both B-channel to not connected
+	hfc->b_mode[0]=L1_MODE_NULL;
+	hfc->b_mode[1]=L1_MODE_NULL;
+
+	hfc->l1_activated=FALSE;
+	hfc->led_state=0;
+	hfc->led_new_data=0;
+
+	/* init the t3 timer */
+	init_timer(&hfc->t3_timer);
+	hfc->t3_timer.data = (long) hfc;
+	hfc->t3_timer.function = (void *) l1_timer_expire_t3;
+	/* init the t4 timer */
+	init_timer(&hfc->t4_timer);
+	hfc->t4_timer.data = (long) hfc;
+	hfc->t4_timer.function = (void *) l1_timer_expire_t4;
+	/* init the led timer */
+	init_timer(&hfc->led_timer);
+	hfc->led_timer.data = (long) hfc;
+	hfc->led_timer.function = (void *) led_timer;
+	// trigger 4 hz led timer
+	hfc->led_timer.expires = jiffies + (LED_TIME * HZ) / 1000;
+	if(!timer_pending(&hfc->led_timer)) add_timer(&hfc->led_timer);
+
+	// init the background machinery for control requests
+	hfc->ctrl_read.bRequestType = 0xc0;
+	hfc->ctrl_read.bRequest = 1;
+	hfc->ctrl_read.wLength = 1;
+	hfc->ctrl_write.bRequestType = 0x40;
+	hfc->ctrl_write.bRequest = 0;
+	hfc->ctrl_write.wLength = 0;
+	usb_fill_control_urb(hfc->ctrl_urb, hfc->dev, hfc->ctrl_out_pipe,(u_char *) & hfc->ctrl_write, NULL, 0, ctrl_complete, hfc);
+					
+	/* Init All Fifos */
+	for(i = 0; i < HFCUSB_NUM_FIFOS; i++)
+	{
+		hfc->fifos[i].iso[0].purb = NULL;
+		hfc->fifos[i].iso[1].purb = NULL;
+		hfc->fifos[i].active = 0;
+	}
+
+	// register like Germaschewski :
+	hfc->d_if.owner = THIS_MODULE;
+	hfc->d_if.ifc.priv = &hfc->fifos[HFCUSB_D_TX];
+	hfc->d_if.ifc.l2l1 = hfc_usb_l2l1;
+
+	for (i=0; i<2; i++)
+	{
+		hfc->b_if[i].ifc.priv = &hfc->fifos[HFCUSB_B1_TX+i*2];
+		hfc->b_if[i].ifc.l2l1 = hfc_usb_l2l1;
+		p_b_if[i] = &hfc->b_if[i];
+	}
+	
+	hfc->protocol = 2;  /* default EURO ISDN, should be a module_param */
+	hisax_register(&hfc->d_if, p_b_if, "hfc_usb", hfc->protocol);
+	
+	for (i=0; i<4; i++)
+		hfc->fifos[i].hif=&p_b_if[i/2]->ifc;
+	for (i=4; i<8; i++)
+		hfc->fifos[i].hif=&hfc->d_if.ifc;
+
+	// 3 (+1) INT IN + 3 ISO OUT
+	if(hfc->cfg_used == CNF_3INT3ISO || hfc->cfg_used == CNF_4INT3ISO)
+	{
+		start_int_fifo(hfc->fifos + HFCUSB_D_RX);	// Int IN D-fifo
+		if(hfc->fifos[HFCUSB_PCM_RX].pipe) start_int_fifo(hfc->fifos + HFCUSB_PCM_RX);	// E-fifo
+		start_int_fifo(hfc->fifos + HFCUSB_B1_RX);	// Int IN B1-fifo
+		start_int_fifo(hfc->fifos + HFCUSB_B2_RX);	// Int IN B2-fifo
+	}
+
+	// 3 (+1) ISO IN + 3 ISO OUT
+	if(hfc->cfg_used==CNF_3ISO3ISO || hfc->cfg_used==CNF_4ISO3ISO)
+	{
+		start_isoc_chain(hfc->fifos + HFCUSB_D_RX, ISOC_PACKETS_D, rx_iso_complete,16);
+		if(hfc->fifos[HFCUSB_PCM_RX].pipe) start_isoc_chain(hfc->fifos + HFCUSB_PCM_RX, ISOC_PACKETS_D, rx_iso_complete,16);
+		start_isoc_chain(hfc->fifos + HFCUSB_B1_RX, ISOC_PACKETS_B, rx_iso_complete,16);
+		start_isoc_chain(hfc->fifos + HFCUSB_B2_RX, ISOC_PACKETS_B, rx_iso_complete,16);
+	}
+
+	start_isoc_chain(hfc->fifos + HFCUSB_D_TX, ISOC_PACKETS_D, tx_iso_complete,1);
+	start_isoc_chain(hfc->fifos + HFCUSB_B1_TX, ISOC_PACKETS_B, tx_iso_complete,1);
+	start_isoc_chain(hfc->fifos + HFCUSB_B2_TX, ISOC_PACKETS_B, tx_iso_complete,1);
+
+	handle_led(hfc,LED_POWER_ON);
+
+	return(0);
+}	/* usb_init */
+
+
+/****************************************/
+/* data defining the devices to be used */
+/****************************************/
+// static __devinitdata const struct usb_device_id hfc_usb_idtab[3] = {
+static struct usb_device_id hfc_usb_idtab[] = {
+	{USB_DEVICE(0x7b0, 0x0007)},	/* Billion USB TA 2 */
+	{USB_DEVICE(0x742, 0x2008)},	/* Stollmann USB TA */
+	{USB_DEVICE(0x959, 0x2bd0)},	/* Colognechip USB eval TA */
+	{USB_DEVICE(0x8e3, 0x0301)},	/* OliTec ISDN USB */
+	{USB_DEVICE(0x675, 0x1688)},	/* DrayTec ISDN USB */
+	{USB_DEVICE(0x7fa, 0x0846)},    /* Bewan ISDN USB TA */
+	{}				/* end with an all-zeroes entry */
+};
+
+MODULE_AUTHOR("Peter Sprenger (sprenger@moving-byters.de)/Martin Bachem (info@colognechip.com)");
+MODULE_DESCRIPTION("HFC I4L USB driver");
+MODULE_DEVICE_TABLE(usb, hfc_usb_idtab);
+MODULE_LICENSE("GPL");
+
+#define EP_NUL 1    // Endpoint at this position not allowed
+#define EP_NOP 2	// all type of endpoints allowed at this position
+#define EP_ISO 3	// Isochron endpoint mandatory at this position
+#define EP_BLK 4	// Bulk endpoint mandatory at this position
+#define EP_INT 5	// Interrupt endpoint mandatory at this position
+
+// this array represents all endpoints possible in the HCF-USB
+// the last 2 entries are the configuration number and the minimum interval for Interrupt endpoints
+int validconf[][18]=
+{
+	// INT in, ISO out config
+	{EP_NUL,EP_INT,EP_NUL,EP_INT,EP_NUL,EP_INT,EP_NOP,EP_INT,EP_ISO,EP_NUL,EP_ISO,EP_NUL,EP_ISO,EP_NUL,EP_NUL,EP_NUL,CNF_4INT3ISO,2},
+	{EP_NUL,EP_INT,EP_NUL,EP_INT,EP_NUL,EP_INT,EP_NUL,EP_NUL,EP_ISO,EP_NUL,EP_ISO,EP_NUL,EP_ISO,EP_NUL,EP_NUL,EP_NUL,CNF_3INT3ISO,2},
+	// ISO in, ISO out config
+	{EP_NUL,EP_NUL,EP_NUL,EP_NUL,EP_NUL,EP_NUL,EP_NUL,EP_NUL,EP_ISO,EP_ISO,EP_ISO,EP_ISO,EP_ISO,EP_ISO,EP_NOP,EP_ISO,CNF_4ISO3ISO,2},
+	{EP_NUL,EP_NUL,EP_NUL,EP_NUL,EP_NUL,EP_NUL,EP_NUL,EP_NUL,EP_ISO,EP_ISO,EP_ISO,EP_ISO,EP_ISO,EP_ISO,EP_NUL,EP_NUL,CNF_3ISO3ISO,2},
+	{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}       // EOL element
+};
+
+// string description of chosen config
+char *conf_str[]=
+{
+	"4 Interrupt IN + 3 Isochron OUT",
+	"3 Interrupt IN + 3 Isochron OUT",
+	"4 Isochron IN + 3 Isochron OUT",
+	"3 Isochron IN + 3 Isochron OUT"
+};
+
+
+/*************************************************/
+/* function called to probe a new plugged device */
+/*************************************************/
+static int __devinit hfc_usb_probe(struct usb_interface *intf, const struct usb_device_id *id)
+{
+	struct usb_device *dev= interface_to_usbdev(intf);
+	hfcusb_data *context;
+	struct usb_host_interface *iface = intf->altsetting + intf->act_altsetting;
+	struct usb_host_endpoint *ep;
+	int i, idx, probe_alt_setting,vend_idx, cfg_used, *vcf, attr, cfg_found, cidx, ep_addr;
+	int cmptbl[16],small_match,iso_packet_size,packet_size,alt_used=0;
+
+//        usb_show_device(dev);
+//	usb_show_device_descriptor(&dev->descriptor);
+//	usb_show_interface_descriptor(&iface->desc);
+	vend_idx=0xffff;
+	for(i=0;vdata[i].vendor;i++)
+	{
+		if(dev->descriptor.idVendor==vdata[i].vendor && dev->descriptor.idProduct==vdata[i].prod_id) vend_idx=i;
+	}
+	
+
+#ifdef VERBOSE_USB_DEBUG	
+	printk(KERN_INFO "HFC-USB: probing interface(%d) actalt(%d) minor(%d)\n",
+		intf->altsetting->desc.bInterfaceNumber, intf->act_altsetting, intf->minor);
+#endif
+
+	if (vend_idx != 0xffff) {
+#ifdef VERBOSE_USB_DEBUG
+		printk(KERN_INFO "HFC-USB: found vendor idx:%d  name:%s\n",vend_idx,vdata[vend_idx].vend_name);
+#endif
+		/* if vendor and product ID is OK, start probing a matching alternate setting ... */
+		probe_alt_setting = 0;
+		small_match=0xffff;
+		// default settings
+		iso_packet_size=16;
+		packet_size=64;
+
+		while(probe_alt_setting < intf->num_altsetting) {
+			iface = intf->altsetting + probe_alt_setting;
+			cfg_used=0;
+
+#ifdef VERBOSE_USB_DEBUG
+			printk(KERN_INFO "HFC-USB: test alt_setting %d\n", probe_alt_setting);
+#endif
+			// check for config EOL element
+			while (validconf[cfg_used][0]) {
+				cfg_found=TRUE;
+				vcf=validconf[cfg_used];
+				ep = iface->endpoint;	/* first endpoint descriptor */
+
+#ifdef VERBOSE_USB_DEBUG
+				printk(KERN_INFO "HFC-USB: (if=%d alt=%d cfg_used=%d)\n",
+					probe_alt_setting, intf->act_altsetting,cfg_used);
+#endif
+				// copy table
+				memcpy(cmptbl,vcf,16*sizeof(int));
+
+				// check for all endpoints in this alternate setting
+				for (i=0; i < iface->desc.bNumEndpoints; i++) {
+					ep_addr = ep->desc.bEndpointAddress;
+					idx = ((ep_addr & 0x7f)-1)*2;	/* get endpoint base */
+					if (ep_addr & 0x80)
+						idx++;
+					attr = ep->desc.bmAttributes;
+
+					if (cmptbl[idx] == EP_NUL) {
+						printk(KERN_INFO "HFC-USB: cfg_found=FALSE in idx:%d  attr:%d  cmptbl[%d]:%d\n",
+							idx, attr, idx, cmptbl[idx]);
+						cfg_found = FALSE;
+					}
+
+					if (attr == USB_ENDPOINT_XFER_INT && cmptbl[idx] == EP_INT)
+						cmptbl[idx] = EP_NUL;
+					if (attr == USB_ENDPOINT_XFER_BULK && cmptbl[idx] == EP_BLK)
+						cmptbl[idx] = EP_NUL;
+					if (attr == USB_ENDPOINT_XFER_ISOC && cmptbl[idx] == EP_ISO)
+						cmptbl[idx] = EP_NUL;
+
+					// check if all INT endpoints match minimum interval
+					if (attr == USB_ENDPOINT_XFER_INT && ep->desc.bInterval < vcf[17]) {
+#ifdef VERBOSE_USB_DEBUG
+						if (cfg_found)
+							printk(KERN_INFO "HFC-USB: Interrupt Endpoint interval < %d found - skipping config\n",
+								vcf[17]);
+#endif
+						cfg_found = FALSE;
+					}
+
+					ep++;
+				}
+
+				for (i = 0; i < 16; i++) {
+					// printk(KERN_INFO "HFC-USB: cmptbl[%d]:%d\n", i, cmptbl[i]);
+
+					// all entries must be EP_NOP or EP_NUL for a valid config
+					if (cmptbl[i] != EP_NOP && cmptbl[i] != EP_NUL)
+						cfg_found = FALSE;
+				}
+
+				// we check for smallest match, to provide configuration priority
+				// configurations with smaller index have higher priority
+				if (cfg_found) {
+					if (cfg_used < small_match) {
+						small_match = cfg_used;
+						alt_used = probe_alt_setting;
+					}
+#ifdef VERBOSE_USB_DEBUG
+					printk(KERN_INFO "HFC-USB: small_match=%x %x\n", small_match, alt_used);
+#endif
+				}
+
+				cfg_used++;
+			}
+
+			probe_alt_setting++;
+		}		/* (probe_alt_setting < intf->num_altsetting) */
+#ifdef VERBOSE_USB_DEBUG
+		printk(KERN_INFO "HFC-USB: final small_match=%x alt_used=%x\n",small_match, alt_used);
+#endif
+		// yiipiee, we found a valid config
+		if (small_match != 0xffff) {
+			intf->act_altsetting = alt_used;
+			iface = intf->altsetting + intf->act_altsetting;
+
+			if (!(context = kmalloc(sizeof(hfcusb_data), GFP_KERNEL)))
+				return(-ENOMEM);  /* got no mem */
+			memset(context, 0, sizeof(hfcusb_data));	/* clear the structure */
+
+			ep = iface->endpoint;	/* first endpoint descriptor */
+			vcf = validconf[small_match];
+
+			for (i = 0; i < iface->desc.bNumEndpoints; i++) {
+				ep_addr = ep->desc.bEndpointAddress;
+				idx = ((ep_addr & 0x7f)-1)*2;	/* get endpoint base */
+				if (ep_addr & 0x80)
+					idx++;
+				cidx = idx & 7;
+				attr = ep->desc.bmAttributes;
+
+				// only initialize used endpoints
+				if (vcf[idx] != EP_NOP && vcf[idx] != EP_NUL) {
+					switch (attr) {
+						case USB_ENDPOINT_XFER_INT:
+							context->fifos[cidx].pipe = usb_rcvintpipe(dev, ep->desc.bEndpointAddress);
+							context->fifos[cidx].usb_transfer_mode = USB_INT;
+							packet_size = ep->desc.wMaxPacketSize; // remember max packet size
+#ifdef VERBOSE_USB_DEBUG
+							printk (KERN_INFO "HFC-USB: Interrupt-In Endpoint found %d ms(idx:%d cidx:%d)!\n",
+								ep->desc.bInterval, idx, cidx);
+#endif
+							break;
+						case USB_ENDPOINT_XFER_BULK:
+							if (ep_addr & 0x80)
+								context->fifos[cidx].pipe = usb_rcvbulkpipe(dev, ep->desc.bEndpointAddress);
+							else
+								context->fifos[cidx].pipe = usb_sndbulkpipe(dev, ep->desc.bEndpointAddress);
+							context->fifos[cidx].usb_transfer_mode = USB_BULK;
+							packet_size = ep->desc.wMaxPacketSize; // remember max packet size
+#ifdef VERBOSE_USB_DEBUG
+							printk (KERN_INFO "HFC-USB: Bulk Endpoint found (idx:%d cidx:%d)!\n",
+								idx, cidx);
+#endif
+							break;
+						case USB_ENDPOINT_XFER_ISOC:
+							if (ep_addr & 0x80)
+								context->fifos[cidx].pipe = usb_rcvisocpipe(dev, ep->desc.bEndpointAddress);
+							else
+								context->fifos[cidx].pipe = usb_sndisocpipe(dev, ep->desc.bEndpointAddress);
+							context->fifos[cidx].usb_transfer_mode = USB_ISOC;
+							iso_packet_size = ep->desc.wMaxPacketSize; // remember max packet size
+#ifdef VERBOSE_USB_DEBUG
+							printk (KERN_INFO "HFC-USB: ISO Endpoint found (idx:%d cidx:%d)!\n",
+								idx, cidx);
+#endif
+							break;
+						default:
+							context->fifos[cidx].pipe = 0;	/* reset data */
+					}	/* switch attribute */
+
+					if (context->fifos[cidx].pipe) {
+						context->fifos[cidx].fifonum = cidx;
+						context->fifos[cidx].hfc = context;
+						context->fifos[cidx].usb_packet_maxlen = ep->desc.wMaxPacketSize;
+						context->fifos[cidx].intervall = ep->desc.bInterval;
+						context->fifos[cidx].skbuff = NULL;
+#ifdef VERBOSE_USB_DEBUG
+						printk (KERN_INFO "HFC-USB: fifo%d pktlen %d interval %d\n",
+							context->fifos[cidx].fifonum,
+							context->fifos[cidx].usb_packet_maxlen,
+							context->fifos[cidx].intervall);
+#endif
+					}
+				}
+
+				ep++;
+			}
+
+			// now share our luck
+			context->dev = dev;						/* save device */
+			context->if_used = intf->altsetting->desc.bInterfaceNumber;	/* save used interface */
+			context->alt_used = intf->act_altsetting;			/* and alternate config */
+			context->ctrl_paksize = dev->descriptor.bMaxPacketSize0;	/* control size */
+			context->cfg_used=vcf[16];					// store used config
+			context->vend_idx=vend_idx;					// store found vendor
+			context->packet_size=packet_size;
+			context->iso_packet_size=iso_packet_size;
+
+			/* create the control pipes needed for register access */
+			context->ctrl_in_pipe = usb_rcvctrlpipe(context->dev, 0);
+			context->ctrl_out_pipe = usb_sndctrlpipe(context->dev, 0);
+			context->ctrl_urb = usb_alloc_urb(0, GFP_KERNEL);
+
+			printk(KERN_INFO "HFC-USB: detected \"%s\" configuration: %s (if=%d alt=%d)\n",
+				vdata[vend_idx].vend_name, conf_str[small_match], context->if_used, context->alt_used);
+
+			/* init the chip and register the driver */
+			if (usb_init(context))
+			{
+				if (context->ctrl_urb) {
+					usb_unlink_urb(context->ctrl_urb);
+					usb_free_urb(context->ctrl_urb);
+					context->ctrl_urb = NULL;
+				}
+				kfree(context);
+				return(-EIO);
+			}
+			usb_set_intfdata(intf, context);
+			return(0);
+		} 
+	}
+	return(-EIO);
+}
+
+/****************************************************/
+/* function called when an active device is removed */
+/****************************************************/
+static void hfc_usb_disconnect(struct usb_interface *intf)
+{
+	hfcusb_data *context = usb_get_intfdata(intf);
+	int i;
+
+	printk(KERN_INFO "HFC-USB: device disconnect\n");
+	
+	usb_set_intfdata(intf, NULL);
+	if (!context)
+		return;
+	if (timer_pending(&context->t3_timer))
+		del_timer(&context->t3_timer);
+	if (timer_pending(&context->t4_timer))
+		del_timer(&context->t4_timer);
+	if (timer_pending(&context->led_timer))
+		del_timer(&context->led_timer);
+
+	hisax_unregister(&context->d_if);
+
+	/* tell all fifos to terminate */
+	for(i = 0; i < HFCUSB_NUM_FIFOS; i++) {
+		if(context->fifos[i].usb_transfer_mode == USB_ISOC) {
+			if(context->fifos[i].active > 0) {
+	    			stop_isoc_chain(&context->fifos[i]);
+#ifdef VERBOSE_USB_DEBUG
+		    		printk (KERN_INFO "HFC-USB: hfc_usb_disconnect: stopping ISOC chain Fifo no %i\n", i);
+#endif
+ 			}
+		} else {
+			if(context->fifos[i].active > 0) {
+				context->fifos[i].active = 0;
+#ifdef VERBOSE_USB_DEBUG
+				printk (KERN_INFO "HFC-USB: hfc_usb_disconnect: unlinking URB for Fifo no %i\n", i);
+#endif
+			}
+			if (context->fifos[i].urb) {
+				usb_unlink_urb(context->fifos[i].urb);
+				usb_free_urb(context->fifos[i].urb);
+				context->fifos[i].urb = NULL;
+			}
+		}
+		context->fifos[i].active = 0;
+	}
+	if (context->ctrl_urb) {
+		usb_unlink_urb(context->ctrl_urb);
+		usb_free_urb(context->ctrl_urb);
+		context->ctrl_urb = NULL;
+	}
+	kfree(context);		/* free our structure again */
+}				/* hfc_usb_disconnect */
+
+
+/************************************/
+/* our driver information structure */
+/************************************/
+static struct usb_driver hfc_drv = {
+	.owner =	THIS_MODULE,
+	.name =		"hfc_usb",
+	.id_table = 	hfc_usb_idtab,
+	.probe =	hfc_usb_probe,
+	.disconnect =	hfc_usb_disconnect,
+};
+
+static void __exit hfc_usb_exit(void)
+{
+#ifdef VERBOSE_USB_DEBUG
+	printk ("HFC-USB: calling \"hfc_usb_exit\" ...\n");
+#endif
+	usb_deregister(&hfc_drv);	/* release our driver */
+	printk(KERN_INFO "HFC-USB module removed\n");
+}
+
+static int __init hfc_usb_init(void)
+{
+	printk ("HFC-USB: driver module revision %s loaded\n", hfcusb_revision);
+
+	if(usb_register(&hfc_drv))
+	{
+		printk(KERN_INFO "HFC-USB: Unable to register HFC-USB module at usb stack\n");
+		return(-1);		   /* unable to register */
+	}
+	return(0);
+}
+
+module_init(hfc_usb_init);
+module_exit(hfc_usb_exit);
--- diff/drivers/isdn/hisax/hisax_cfg.h	1970-01-01 01:00:00.000000000 +0100
+++ source/drivers/isdn/hisax/hisax_cfg.h	2004-02-23 13:56:42.000000000 +0000
@@ -0,0 +1,64 @@
+/* $Id: hisax_cfg.h,v 1.1.2.1 2004/01/24 20:47:23 keil Exp $
+ * define of the basic HiSax configuration structures
+ * and pcmcia interface
+ *
+ * This software may be used and distributed according to the terms
+ * of the GNU General Public License, incorporated herein by reference.
+ *
+ */
+
+#define ISDN_CTYPE_16_0			1
+#define ISDN_CTYPE_8_0			2
+#define ISDN_CTYPE_16_3			3
+#define ISDN_CTYPE_PNP			4
+#define ISDN_CTYPE_A1			5
+#define ISDN_CTYPE_ELSA			6
+#define ISDN_CTYPE_ELSA_PNP		7
+#define ISDN_CTYPE_TELESPCMCIA		8
+#define ISDN_CTYPE_IX1MICROR2		9
+#define ISDN_CTYPE_ELSA_PCMCIA		10
+#define ISDN_CTYPE_DIEHLDIVA		11
+#define ISDN_CTYPE_ASUSCOM		12
+#define ISDN_CTYPE_TELEINT		13
+#define ISDN_CTYPE_TELES3C		14
+#define ISDN_CTYPE_SEDLBAUER		15
+#define ISDN_CTYPE_SPORTSTER		16
+#define ISDN_CTYPE_MIC			17
+#define ISDN_CTYPE_ELSA_PCI		18
+#define ISDN_CTYPE_COMPAQ_ISA		19
+#define ISDN_CTYPE_NETJET_S		20
+#define ISDN_CTYPE_TELESPCI		21
+#define ISDN_CTYPE_SEDLBAUER_PCMCIA	22
+#define ISDN_CTYPE_AMD7930		23
+#define ISDN_CTYPE_NICCY		24
+#define ISDN_CTYPE_S0BOX		25
+#define ISDN_CTYPE_A1_PCMCIA		26
+#define ISDN_CTYPE_FRITZPCI		27
+#define ISDN_CTYPE_SEDLBAUER_FAX	28
+#define ISDN_CTYPE_ISURF		29
+#define ISDN_CTYPE_ACERP10		30
+#define ISDN_CTYPE_HSTSAPHIR		31
+#define	ISDN_CTYPE_BKM_A4T		32
+#define	ISDN_CTYPE_SCT_QUADRO		33
+#define ISDN_CTYPE_GAZEL		34
+#define ISDN_CTYPE_HFC_PCI		35
+#define ISDN_CTYPE_W6692		36
+#define ISDN_CTYPE_HFC_SX		37
+#define ISDN_CTYPE_NETJET_U		38
+#define ISDN_CTYPE_HFC_SP_PCMCIA	39
+#define ISDN_CTYPE_DYNAMIC		40
+#define ISDN_CTYPE_ENTERNOW		41
+#define ISDN_CTYPE_COUNT		41
+
+typedef struct IsdnCardState	IsdnCardState_t;
+typedef struct IsdnCard		IsdnCard_t;
+
+struct IsdnCard {
+	int		typ;
+	int 		protocol;	/* EDSS1, 1TR6 or NI1 */
+	unsigned long	para[4];
+	IsdnCardState_t	*cs;
+};
+
+extern void	HiSax_closecard(int);
+extern int	hisax_init_pcmcia(void *, int *, IsdnCard_t *);
--- diff/drivers/isdn/hisax/isdnhdlc.c	1970-01-01 01:00:00.000000000 +0100
+++ source/drivers/isdn/hisax/isdnhdlc.c	2004-02-23 13:56:42.000000000 +0000
@@ -0,0 +1,669 @@
+/*
+ * isdnhdlc.c  --  General purpose ISDN HDLC decoder.
+ *
+ *Copyright (C) 2002	Wolfgang Mües      <wolfgang@iksw-muees.de>
+ *		2001 	Frode Isaksen      <fisaksen@bewan.com>
+ *              2001 	Kai Germaschewski  <kai.germaschewski@gmx.de>
+ *
+ *      This program is free software; you can redistribute it and/or modify
+ *      it under the terms of the GNU General Public License as published by
+ *      the Free Software Foundation; either version 2 of the License, or
+ *      (at your option) any later version.
+ *
+ *      This program is distributed in the hope that it will be useful,
+ *      but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *      GNU General Public License for more details.
+ *
+ *      You should have received a copy of the GNU General Public License
+ *      along with this program; if not, write to the Free Software
+ *      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include "isdnhdlc.h"
+
+/*-------------------------------------------------------------------*/
+
+MODULE_AUTHOR("Wolfgang Mües <wolfgang@iksw-muees.de>, "
+	      "Frode Isaksen <fisaksen@bewan.com>, "
+	      "Kai Germaschewski <kai.germaschewski@gmx.de>");
+MODULE_DESCRIPTION("General purpose ISDN HDLC decoder");
+MODULE_LICENSE("GPL");
+
+/*-------------------------------------------------------------------*/
+
+/* bit swap table.
+ * Very handy for devices with different bit order,
+ * and neccessary for each transparent B-channel access for all
+ * devices which works with this HDLC decoder without bit reversal.
+ */
+const unsigned char isdnhdlc_bit_rev_tab[256] = {
+	0x00,0x80,0x40,0xC0,0x20,0xA0,0x60,0xE0,0x10,0x90,0x50,0xD0,0x30,0xB0,0x70,0xF0,
+	0x08,0x88,0x48,0xC8,0x28,0xA8,0x68,0xE8,0x18,0x98,0x58,0xD8,0x38,0xB8,0x78,0xF8,
+	0x04,0x84,0x44,0xC4,0x24,0xA4,0x64,0xE4,0x14,0x94,0x54,0xD4,0x34,0xB4,0x74,0xF4,
+	0x0C,0x8C,0x4C,0xCC,0x2C,0xAC,0x6C,0xEC,0x1C,0x9C,0x5C,0xDC,0x3C,0xBC,0x7C,0xFC,
+	0x02,0x82,0x42,0xC2,0x22,0xA2,0x62,0xE2,0x12,0x92,0x52,0xD2,0x32,0xB2,0x72,0xF2,
+	0x0A,0x8A,0x4A,0xCA,0x2A,0xAA,0x6A,0xEA,0x1A,0x9A,0x5A,0xDA,0x3A,0xBA,0x7A,0xFA,
+	0x06,0x86,0x46,0xC6,0x26,0xA6,0x66,0xE6,0x16,0x96,0x56,0xD6,0x36,0xB6,0x76,0xF6,
+	0x0E,0x8E,0x4E,0xCE,0x2E,0xAE,0x6E,0xEE,0x1E,0x9E,0x5E,0xDE,0x3E,0xBE,0x7E,0xFE,
+	0x01,0x81,0x41,0xC1,0x21,0xA1,0x61,0xE1,0x11,0x91,0x51,0xD1,0x31,0xB1,0x71,0xF1,
+	0x09,0x89,0x49,0xC9,0x29,0xA9,0x69,0xE9,0x19,0x99,0x59,0xD9,0x39,0xB9,0x79,0xF9,
+	0x05,0x85,0x45,0xC5,0x25,0xA5,0x65,0xE5,0x15,0x95,0x55,0xD5,0x35,0xB5,0x75,0xF5,
+	0x0D,0x8D,0x4D,0xCD,0x2D,0xAD,0x6D,0xED,0x1D,0x9D,0x5D,0xDD,0x3D,0xBD,0x7D,0xFD,
+	0x03,0x83,0x43,0xC3,0x23,0xA3,0x63,0xE3,0x13,0x93,0x53,0xD3,0x33,0xB3,0x73,0xF3,
+	0x0B,0x8B,0x4B,0xCB,0x2B,0xAB,0x6B,0xEB,0x1B,0x9B,0x5B,0xDB,0x3B,0xBB,0x7B,0xFB,
+	0x07,0x87,0x47,0xC7,0x27,0xA7,0x67,0xE7,0x17,0x97,0x57,0xD7,0x37,0xB7,0x77,0xF7,
+	0x0F,0x8F,0x4F,0xCF,0x2F,0xAF,0x6F,0xEF,0x1F,0x9F,0x5F,0xDF,0x3F,0xBF,0x7F,0xFF
+};
+
+/* Table for CRC16. Internal used only. */
+static const unsigned short int crc16_tab[] = {
+	0x0000,0x1189,0x2312,0x329b,0x4624,0x57ad,0x6536,0x74bf,
+	0x8c48,0x9dc1,0xaf5a,0xbed3,0xca6c,0xdbe5,0xe97e,0xf8f7,
+	0x1081,0x0108,0x3393,0x221a,0x56a5,0x472c,0x75b7,0x643e,
+	0x9cc9,0x8d40,0xbfdb,0xae52,0xdaed,0xcb64,0xf9ff,0xe876,
+	0x2102,0x308b,0x0210,0x1399,0x6726,0x76af,0x4434,0x55bd,
+	0xad4a,0xbcc3,0x8e58,0x9fd1,0xeb6e,0xfae7,0xc87c,0xd9f5,
+	0x3183,0x200a,0x1291,0x0318,0x77a7,0x662e,0x54b5,0x453c,
+	0xbdcb,0xac42,0x9ed9,0x8f50,0xfbef,0xea66,0xd8fd,0xc974,
+	0x4204,0x538d,0x6116,0x709f,0x0420,0x15a9,0x2732,0x36bb,
+	0xce4c,0xdfc5,0xed5e,0xfcd7,0x8868,0x99e1,0xab7a,0xbaf3,
+	0x5285,0x430c,0x7197,0x601e,0x14a1,0x0528,0x37b3,0x263a,
+	0xdecd,0xcf44,0xfddf,0xec56,0x98e9,0x8960,0xbbfb,0xaa72,
+	0x6306,0x728f,0x4014,0x519d,0x2522,0x34ab,0x0630,0x17b9,
+	0xef4e,0xfec7,0xcc5c,0xddd5,0xa96a,0xb8e3,0x8a78,0x9bf1,
+	0x7387,0x620e,0x5095,0x411c,0x35a3,0x242a,0x16b1,0x0738,
+	0xffcf,0xee46,0xdcdd,0xcd54,0xb9eb,0xa862,0x9af9,0x8b70,
+	0x8408,0x9581,0xa71a,0xb693,0xc22c,0xd3a5,0xe13e,0xf0b7,
+	0x0840,0x19c9,0x2b52,0x3adb,0x4e64,0x5fed,0x6d76,0x7cff,
+	0x9489,0x8500,0xb79b,0xa612,0xd2ad,0xc324,0xf1bf,0xe036,
+	0x18c1,0x0948,0x3bd3,0x2a5a,0x5ee5,0x4f6c,0x7df7,0x6c7e,
+	0xa50a,0xb483,0x8618,0x9791,0xe32e,0xf2a7,0xc03c,0xd1b5,
+	0x2942,0x38cb,0x0a50,0x1bd9,0x6f66,0x7eef,0x4c74,0x5dfd,
+	0xb58b,0xa402,0x9699,0x8710,0xf3af,0xe226,0xd0bd,0xc134,
+	0x39c3,0x284a,0x1ad1,0x0b58,0x7fe7,0x6e6e,0x5cf5,0x4d7c,
+	0xc60c,0xd785,0xe51e,0xf497,0x8028,0x91a1,0xa33a,0xb2b3,
+	0x4a44,0x5bcd,0x6956,0x78df,0x0c60,0x1de9,0x2f72,0x3efb,
+	0xd68d,0xc704,0xf59f,0xe416,0x90a9,0x8120,0xb3bb,0xa232,
+	0x5ac5,0x4b4c,0x79d7,0x685e,0x1ce1,0x0d68,0x3ff3,0x2e7a,
+	0xe70e,0xf687,0xc41c,0xd595,0xa12a,0xb0a3,0x8238,0x93b1,
+	0x6b46,0x7acf,0x4854,0x59dd,0x2d62,0x3ceb,0x0e70,0x1ff9,
+	0xf78f,0xe606,0xd49d,0xc514,0xb1ab,0xa022,0x92b9,0x8330,
+	0x7bc7,0x6a4e,0x58d5,0x495c,0x3de3,0x2c6a,0x1ef1,0x0f78
+};
+
+
+enum {
+	HDLC_FAST_IDLE,HDLC_GET_FLAG_B0,HDLC_GETFLAG_B1A6,HDLC_GETFLAG_B7,
+	HDLC_GET_DATA,HDLC_FAST_FLAG
+};
+
+enum {
+	HDLC_SEND_DATA,HDLC_SEND_CRC1,HDLC_SEND_FAST_FLAG,
+	HDLC_SEND_FIRST_FLAG,HDLC_SEND_CRC2,HDLC_SEND_CLOSING_FLAG,
+	HDLC_SEND_IDLE1,HDLC_SEND_FAST_IDLE,HDLC_SENDFLAG_B0,
+	HDLC_SENDFLAG_B1A6,HDLC_SENDFLAG_B7,STOPPED
+};
+
+void isdnhdlc_rcv_init (struct isdnhdlc_vars *hdlc, int do_adapt56)
+{
+   	hdlc->bit_shift = 0;
+	hdlc->hdlc_bits1 = 0;
+	hdlc->data_bits = 0;
+	hdlc->ffbit_shift = 0;
+	hdlc->data_received = 0;
+	hdlc->state = HDLC_GET_DATA;
+	hdlc->do_adapt56 = do_adapt56;
+	hdlc->dchannel = 0;
+	hdlc->crc = 0;
+	hdlc->cbin = 0;
+	hdlc->shift_reg = 0;
+	hdlc->ffvalue = 0;
+	hdlc->dstpos = 0;
+}
+
+void isdnhdlc_out_init (struct isdnhdlc_vars *hdlc, int is_d_channel, int do_adapt56)
+{
+   	hdlc->bit_shift = 0;
+	hdlc->hdlc_bits1 = 0;
+	hdlc->data_bits = 0;
+	hdlc->ffbit_shift = 0;
+	hdlc->data_received = 0;
+	hdlc->do_closing = 0;
+	hdlc->ffvalue = 0;
+	if (is_d_channel) {
+		hdlc->dchannel = 1;
+		hdlc->state = HDLC_SEND_FIRST_FLAG;
+	} else {
+		hdlc->dchannel = 0;
+		hdlc->state = HDLC_SEND_FAST_FLAG;
+		hdlc->ffvalue = 0x7e;
+	}
+	hdlc->cbin = 0x7e;
+	hdlc->bit_shift = 0;
+	if(do_adapt56){
+		hdlc->do_adapt56 = 1;
+		hdlc->data_bits = 0;
+		hdlc->state = HDLC_SENDFLAG_B0;
+	} else {
+		hdlc->do_adapt56 = 0;
+		hdlc->data_bits = 8;
+	}
+	hdlc->shift_reg = 0;
+}
+
+/*
+  isdnhdlc_decode - decodes HDLC frames from a transparent bit stream.
+
+  The source buffer is scanned for valid HDLC frames looking for
+  flags (01111110) to indicate the start of a frame. If the start of
+  the frame is found, the bit stuffing is removed (0 after 5 1's).
+  When a new flag is found, the complete frame has been received
+  and the CRC is checked.
+  If a valid frame is found, the function returns the frame length
+  excluding the CRC with the bit HDLC_END_OF_FRAME set.
+  If the beginning of a valid frame is found, the function returns
+  the length.
+  If a framing error is found (too many 1s and not a flag) the function
+  returns the length with the bit HDLC_FRAMING_ERROR set.
+  If a CRC error is found the function returns the length with the
+  bit HDLC_CRC_ERROR set.
+  If the frame length exceeds the destination buffer size, the function
+  returns the length with the bit HDLC_LENGTH_ERROR set.
+
+  src - source buffer
+  slen - source buffer length
+  count - number of bytes removed (decoded) from the source buffer
+  dst _ destination buffer
+  dsize - destination buffer size
+  returns - number of decoded bytes in the destination buffer and status
+  flag.
+ */
+int isdnhdlc_decode (struct isdnhdlc_vars *hdlc, const unsigned char *src,
+		     int slen, int *count, unsigned char *dst, int dsize)
+{
+	int status=0;
+
+	static const unsigned char fast_flag[]={
+		0x00,0x00,0x00,0x20,0x30,0x38,0x3c,0x3e,0x3f
+	};
+
+	static const unsigned char fast_flag_value[]={
+		0x00,0x7e,0xfc,0xf9,0xf3,0xe7,0xcf,0x9f,0x3f
+	};
+
+	static const unsigned char fast_abort[]={
+		0x00,0x00,0x80,0xc0,0xe0,0xf0,0xf8,0xfc,0xfe,0xff
+	};
+
+	*count = slen;
+
+	while(slen > 0){
+		if(hdlc->bit_shift==0){
+			hdlc->cbin = *src++;
+			slen--;
+			hdlc->bit_shift = 8;
+			if(hdlc->do_adapt56){
+				hdlc->bit_shift --;
+			}
+		}
+
+		switch(hdlc->state){
+		case STOPPED:
+			return 0;
+		case HDLC_FAST_IDLE:
+			if(hdlc->cbin == 0xff){
+				hdlc->bit_shift = 0;
+				break;
+			}
+			hdlc->state = HDLC_GET_FLAG_B0;
+			hdlc->hdlc_bits1 = 0;
+			hdlc->bit_shift = 8;
+			break;
+		case HDLC_GET_FLAG_B0:
+			if(!(hdlc->cbin & 0x80)) {
+				hdlc->state = HDLC_GETFLAG_B1A6;
+				hdlc->hdlc_bits1 = 0;
+			} else {
+				if(!hdlc->do_adapt56){
+					if(++hdlc->hdlc_bits1 >=8 ) if(hdlc->bit_shift==1)
+						hdlc->state = HDLC_FAST_IDLE;
+				}
+			}
+			hdlc->cbin<<=1;
+			hdlc->bit_shift --;
+			break;
+		case HDLC_GETFLAG_B1A6:
+			if(hdlc->cbin & 0x80){
+				hdlc->hdlc_bits1++;
+				if(hdlc->hdlc_bits1==6){
+					hdlc->state = HDLC_GETFLAG_B7;
+				}
+			} else {
+				hdlc->hdlc_bits1 = 0;
+			}
+			hdlc->cbin<<=1;
+			hdlc->bit_shift --;
+			break;
+		case HDLC_GETFLAG_B7:
+			if(hdlc->cbin & 0x80) {
+				hdlc->state = HDLC_GET_FLAG_B0;
+			} else {
+				hdlc->state = HDLC_GET_DATA;
+				hdlc->crc = 0xffff;
+				hdlc->shift_reg = 0;
+				hdlc->hdlc_bits1 = 0;
+				hdlc->data_bits = 0;
+				hdlc->data_received = 0;
+			}
+			hdlc->cbin<<=1;
+			hdlc->bit_shift --;
+			break;
+		case HDLC_GET_DATA:
+			if(hdlc->cbin & 0x80){
+				hdlc->hdlc_bits1++;
+				switch(hdlc->hdlc_bits1){
+				case 6:
+					break;
+				case 7:
+					if(hdlc->data_received) {
+						// bad frame
+						status = -HDLC_FRAMING_ERROR;
+					}
+					if(!hdlc->do_adapt56){
+						if(hdlc->cbin==fast_abort[hdlc->bit_shift+1]){
+							hdlc->state = HDLC_FAST_IDLE;
+							hdlc->bit_shift=1;
+							break;
+						}
+					} else {
+						hdlc->state = HDLC_GET_FLAG_B0;
+					}
+					break;
+				default:
+					hdlc->shift_reg>>=1;
+					hdlc->shift_reg |= 0x80;
+					hdlc->data_bits++;
+					break;
+				}
+			} else {
+				switch(hdlc->hdlc_bits1){
+				case 5:
+					break;
+				case 6:
+					if(hdlc->data_received){
+						if (hdlc->dstpos < 2) {
+							status = -HDLC_FRAMING_ERROR;
+						} else if (hdlc->crc != 0xf0b8){
+							// crc error
+							status = -HDLC_CRC_ERROR;
+						} else {
+							// remove CRC
+							hdlc->dstpos -= 2;
+							// good frame
+							status = hdlc->dstpos;
+						}
+					}
+					hdlc->crc = 0xffff;
+					hdlc->shift_reg = 0;
+					hdlc->data_bits = 0;
+					if(!hdlc->do_adapt56){
+						if(hdlc->cbin==fast_flag[hdlc->bit_shift]){
+							hdlc->ffvalue = fast_flag_value[hdlc->bit_shift];
+							hdlc->state = HDLC_FAST_FLAG;
+							hdlc->ffbit_shift = hdlc->bit_shift;
+							hdlc->bit_shift = 1;
+						} else {
+							hdlc->state = HDLC_GET_DATA;
+							hdlc->data_received = 0;
+						}
+					} else {
+						hdlc->state = HDLC_GET_DATA;
+						hdlc->data_received = 0;
+					}
+					break;
+				default:
+					hdlc->shift_reg>>=1;
+					hdlc->data_bits++;
+					break;
+				}
+				hdlc->hdlc_bits1 = 0;
+			}
+			if (status) {
+				hdlc->dstpos = 0;
+				*count -= slen;
+				hdlc->cbin <<= 1;
+				hdlc->bit_shift--;
+				return status;
+			}
+			if(hdlc->data_bits==8){
+				unsigned cval;
+
+				hdlc->data_bits = 0;
+				hdlc->data_received = 1;
+				cval = (hdlc->crc^hdlc->shift_reg) & 0xff;
+				hdlc->crc = (hdlc->crc>>8)^crc16_tab[cval];
+				// good byte received
+				if (dsize--) {
+					dst[hdlc->dstpos++] = hdlc->shift_reg;
+				} else {
+					// frame too long
+					status = -HDLC_LENGTH_ERROR;
+					hdlc->dstpos = 0;
+				}
+			}
+			hdlc->cbin <<= 1;
+			hdlc->bit_shift--;
+			break;
+		case HDLC_FAST_FLAG:
+			if(hdlc->cbin==hdlc->ffvalue){
+				hdlc->bit_shift = 0;
+				break;
+			} else {
+				if(hdlc->cbin == 0xff){
+					hdlc->state = HDLC_FAST_IDLE;
+					hdlc->bit_shift=0;
+				} else if(hdlc->ffbit_shift==8){
+					hdlc->state = HDLC_GETFLAG_B7;
+					break;
+				} else {
+					hdlc->shift_reg = fast_abort[hdlc->ffbit_shift-1];
+					hdlc->hdlc_bits1 = hdlc->ffbit_shift-2;
+					if(hdlc->hdlc_bits1<0)hdlc->hdlc_bits1 = 0;
+					hdlc->data_bits = hdlc->ffbit_shift-1;
+					hdlc->state = HDLC_GET_DATA;
+					hdlc->data_received = 0;
+				}
+			}
+			break;
+		default:
+			break;
+		}
+	}
+	*count -= slen;
+	return 0;
+}
+
+/*
+  isdnhdlc_encode - encodes HDLC frames to a transparent bit stream.
+
+  The bit stream starts with a beginning flag (01111110). After
+  that each byte is added to the bit stream with bit stuffing added
+  (0 after 5 1's).
+  When the last byte has been removed from the source buffer, the
+  CRC (2 bytes is added) and the frame terminates with the ending flag.
+  For the dchannel, the idle character (all 1's) is also added at the end.
+  If this function is called with empty source buffer (slen=0), flags or
+  idle character will be generated.
+
+  src - source buffer
+  slen - source buffer length
+  count - number of bytes removed (encoded) from source buffer
+  dst _ destination buffer
+  dsize - destination buffer size
+  returns - number of encoded bytes in the destination buffer
+*/
+int isdnhdlc_encode(struct isdnhdlc_vars *hdlc, const unsigned char *src,
+		unsigned short slen, int *count,
+		unsigned char *dst, int dsize)
+{
+	static const unsigned char xfast_flag_value[] = {
+		0x7e,0x3f,0x9f,0xcf,0xe7,0xf3,0xf9,0xfc,0x7e
+	};
+
+	int len = 0;
+
+	*count = slen;
+
+	while (dsize > 0) {
+		if(hdlc->bit_shift==0){
+			if(slen && !hdlc->do_closing){
+				hdlc->shift_reg = *src++;
+				slen--;
+				if (slen == 0)
+					hdlc->do_closing = 1;  /* closing sequence, CRC + flag(s) */
+				hdlc->bit_shift = 8;
+			} else {
+				if(hdlc->state == HDLC_SEND_DATA){
+					if(hdlc->data_received){
+						hdlc->state = HDLC_SEND_CRC1;
+						hdlc->crc ^= 0xffff;
+						hdlc->bit_shift = 8;
+						hdlc->shift_reg = hdlc->crc & 0xff;
+					} else if(!hdlc->do_adapt56){
+						hdlc->state = HDLC_SEND_FAST_FLAG;
+					} else {
+						hdlc->state = HDLC_SENDFLAG_B0;
+					}
+				}
+
+			}
+		}
+
+		switch(hdlc->state){
+		case STOPPED:
+			while (dsize--)
+				*dst++ = 0xff;
+
+			return dsize;
+		case HDLC_SEND_FAST_FLAG:
+			hdlc->do_closing = 0;
+			if(slen == 0){
+				*dst++ = hdlc->ffvalue;
+				len++;
+				dsize--;
+				break;
+			}
+			if(hdlc->bit_shift==8){
+				hdlc->cbin = hdlc->ffvalue>>(8-hdlc->data_bits);
+				hdlc->state = HDLC_SEND_DATA;
+				hdlc->crc = 0xffff;
+				hdlc->hdlc_bits1 = 0;
+				hdlc->data_received = 1;
+			}
+			break;
+		case HDLC_SENDFLAG_B0:
+			hdlc->do_closing = 0;
+			hdlc->cbin <<= 1;
+			hdlc->data_bits++;
+			hdlc->hdlc_bits1 = 0;
+			hdlc->state = HDLC_SENDFLAG_B1A6;
+			break;
+		case HDLC_SENDFLAG_B1A6:
+			hdlc->cbin <<= 1;
+			hdlc->data_bits++;
+			hdlc->cbin++;
+			if(++hdlc->hdlc_bits1 == 6)
+				hdlc->state = HDLC_SENDFLAG_B7;
+			break;
+		case HDLC_SENDFLAG_B7:
+			hdlc->cbin <<= 1;
+			hdlc->data_bits++;
+			if(slen == 0){
+				hdlc->state = HDLC_SENDFLAG_B0;
+				break;
+			}
+			if(hdlc->bit_shift==8){
+				hdlc->state = HDLC_SEND_DATA;
+				hdlc->crc = 0xffff;
+				hdlc->hdlc_bits1 = 0;
+				hdlc->data_received = 1;
+			}
+			break;
+		case HDLC_SEND_FIRST_FLAG:
+			hdlc->data_received = 1;
+			if(hdlc->data_bits==8){
+				hdlc->state = HDLC_SEND_DATA;
+				hdlc->crc = 0xffff;
+				hdlc->hdlc_bits1 = 0;
+				break;
+			}
+			hdlc->cbin <<= 1;
+			hdlc->data_bits++;
+			if(hdlc->shift_reg & 0x01)
+				hdlc->cbin++;
+			hdlc->shift_reg >>= 1;
+			hdlc->bit_shift--;
+			if(hdlc->bit_shift==0){
+				hdlc->state = HDLC_SEND_DATA;
+				hdlc->crc = 0xffff;
+				hdlc->hdlc_bits1 = 0;
+			}
+			break;
+		case HDLC_SEND_DATA:
+			hdlc->cbin <<= 1;
+			hdlc->data_bits++;
+			if(hdlc->hdlc_bits1 == 5){
+				hdlc->hdlc_bits1 = 0;
+				break;
+			}
+			if(hdlc->bit_shift==8){
+				unsigned cval;
+
+				cval = (hdlc->crc^hdlc->shift_reg) & 0xff;
+				hdlc->crc = (hdlc->crc>>8)^crc16_tab[cval];
+			}
+			if(hdlc->shift_reg & 0x01){
+				hdlc->hdlc_bits1++;
+				hdlc->cbin++;
+				hdlc->shift_reg >>= 1;
+				hdlc->bit_shift--;
+			} else {
+				hdlc->hdlc_bits1 = 0;
+				hdlc->shift_reg >>= 1;
+				hdlc->bit_shift--;
+			}
+			break;
+		case HDLC_SEND_CRC1:
+			hdlc->cbin <<= 1;
+			hdlc->data_bits++;
+			if(hdlc->hdlc_bits1 == 5){
+				hdlc->hdlc_bits1 = 0;
+				break;
+			}
+			if(hdlc->shift_reg & 0x01){
+				hdlc->hdlc_bits1++;
+				hdlc->cbin++;
+				hdlc->shift_reg >>= 1;
+				hdlc->bit_shift--;
+			} else {
+				hdlc->hdlc_bits1 = 0;
+				hdlc->shift_reg >>= 1;
+				hdlc->bit_shift--;
+			}
+			if(hdlc->bit_shift==0){
+				hdlc->shift_reg = (hdlc->crc >> 8);
+				hdlc->state = HDLC_SEND_CRC2;
+				hdlc->bit_shift = 8;
+			}
+			break;
+		case HDLC_SEND_CRC2:
+			hdlc->cbin <<= 1;
+			hdlc->data_bits++;
+			if(hdlc->hdlc_bits1 == 5){
+				hdlc->hdlc_bits1 = 0;
+				break;
+			}
+			if(hdlc->shift_reg & 0x01){
+				hdlc->hdlc_bits1++;
+				hdlc->cbin++;
+				hdlc->shift_reg >>= 1;
+				hdlc->bit_shift--;
+			} else {
+				hdlc->hdlc_bits1 = 0;
+				hdlc->shift_reg >>= 1;
+				hdlc->bit_shift--;
+			}
+			if(hdlc->bit_shift==0){
+				hdlc->shift_reg = 0x7e;
+				hdlc->state = HDLC_SEND_CLOSING_FLAG;
+				hdlc->bit_shift = 8;
+			}
+			break;
+		case HDLC_SEND_CLOSING_FLAG:
+			hdlc->cbin <<= 1;
+			hdlc->data_bits++;
+			if(hdlc->hdlc_bits1 == 5){
+				hdlc->hdlc_bits1 = 0;
+				break;
+			}
+			if(hdlc->shift_reg & 0x01){
+				hdlc->cbin++;
+			}
+			hdlc->shift_reg >>= 1;
+			hdlc->bit_shift--;
+			if(hdlc->bit_shift==0){
+				hdlc->ffvalue = xfast_flag_value[hdlc->data_bits];
+				if(hdlc->dchannel){
+					hdlc->ffvalue = 0x7e;
+					hdlc->state = HDLC_SEND_IDLE1;
+					hdlc->bit_shift = 8-hdlc->data_bits;
+					if(hdlc->bit_shift==0)
+						hdlc->state = HDLC_SEND_FAST_IDLE;
+				} else {
+					if(!hdlc->do_adapt56){
+						hdlc->state = HDLC_SEND_FAST_FLAG;
+						hdlc->data_received = 0;
+					} else {
+						hdlc->state = HDLC_SENDFLAG_B0;
+						hdlc->data_received = 0;
+					}
+					// Finished with this frame, send flags
+					if (dsize > 1) dsize = 1;
+				}
+			}
+			break;
+		case HDLC_SEND_IDLE1:
+			hdlc->do_closing = 0;
+			hdlc->cbin <<= 1;
+			hdlc->cbin++;
+			hdlc->data_bits++;
+			hdlc->bit_shift--;
+			if(hdlc->bit_shift==0){
+				hdlc->state = HDLC_SEND_FAST_IDLE;
+				hdlc->bit_shift = 0;
+			}
+			break;
+		case HDLC_SEND_FAST_IDLE:
+			hdlc->do_closing = 0;
+			hdlc->cbin = 0xff;
+			hdlc->data_bits = 8;
+			if(hdlc->bit_shift == 8){
+				hdlc->cbin = 0x7e;
+				hdlc->state = HDLC_SEND_FIRST_FLAG;
+			} else {
+				*dst++ = hdlc->cbin;
+				hdlc->bit_shift = hdlc->data_bits = 0;
+				len++;
+				dsize = 0;
+			}
+			break;
+		default:
+			break;
+		}
+		if(hdlc->do_adapt56){
+			if(hdlc->data_bits==7){
+				hdlc->cbin <<= 1;
+				hdlc->cbin++;
+				hdlc->data_bits++;
+			}
+		}
+		if(hdlc->data_bits==8){
+			*dst++ = hdlc->cbin;
+			hdlc->data_bits = 0;
+			len++;
+			dsize--;
+		}
+	}
+	*count -= slen;
+
+	return len;
+}
+
+EXPORT_SYMBOL(isdnhdlc_bit_rev_tab);
+EXPORT_SYMBOL(isdnhdlc_rcv_init);
+EXPORT_SYMBOL(isdnhdlc_decode);
+EXPORT_SYMBOL(isdnhdlc_out_init);
+EXPORT_SYMBOL(isdnhdlc_encode);
--- diff/drivers/isdn/hisax/isdnhdlc.h	1970-01-01 01:00:00.000000000 +0100
+++ source/drivers/isdn/hisax/isdnhdlc.h	2004-02-23 13:56:42.000000000 +0000
@@ -0,0 +1,72 @@
+/*
+ * isdnhdlc.h  --  General purpose ISDN HDLC decoder.
+ *
+ * Implementation of a HDLC decoder/encoder in software.
+ * Neccessary because some ISDN devices don't have HDLC
+ * controllers. Also included: a bit reversal table.
+ *
+ *Copyright (C) 2002    Wolfgang Mües      <wolfgang@iksw-muees.de>
+ *		2001 	Frode Isaksen      <fisaksen@bewan.com>
+ *              2001 	Kai Germaschewski  <kai.germaschewski@gmx.de>
+ *
+ *      This program is free software; you can redistribute it and/or modify
+ *      it under the terms of the GNU General Public License as published by
+ *      the Free Software Foundation; either version 2 of the License, or
+ *      (at your option) any later version.
+ *
+ *      This program is distributed in the hope that it will be useful,
+ *      but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *      GNU General Public License for more details.
+ *
+ *      You should have received a copy of the GNU General Public License
+ *      along with this program; if not, write to the Free Software
+ *      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef __ISDNHDLC_H__
+#define __ISDNHDLC_H__
+
+struct isdnhdlc_vars {
+	int bit_shift;
+	int hdlc_bits1;
+	int data_bits;
+	int ffbit_shift; 	// encoding only
+	int state;
+	int dstpos;
+
+	unsigned short crc;
+
+	unsigned char cbin;
+	unsigned char shift_reg;
+	unsigned char ffvalue;
+
+	int data_received:1; 	// set if transferring data
+	int dchannel:1; 	// set if D channel (send idle instead of flags)
+	int do_adapt56:1; 	// set if 56K adaptation
+        int do_closing:1; 	// set if in closing phase (need to send CRC + flag
+};
+
+
+/*
+  The return value from isdnhdlc_decode is
+  the frame length, 0 if no complete frame was decoded,
+  or a negative error number
+*/
+#define HDLC_FRAMING_ERROR     1
+#define HDLC_CRC_ERROR         2
+#define HDLC_LENGTH_ERROR      3
+
+extern const unsigned char isdnhdlc_bit_rev_tab[256];
+
+extern void isdnhdlc_rcv_init (struct isdnhdlc_vars *hdlc, int do_adapt56);
+
+extern int isdnhdlc_decode (struct isdnhdlc_vars *hdlc, const unsigned char *src, int slen,int *count,
+	                    unsigned char *dst, int dsize);
+
+extern void isdnhdlc_out_init (struct isdnhdlc_vars *hdlc,int is_d_channel,int do_adapt56);
+
+extern int isdnhdlc_encode (struct isdnhdlc_vars *hdlc,const unsigned char *src,unsigned short slen,int *count,
+	                    unsigned char *dst,int dsize);
+
+#endif /* __ISDNHDLC_H__ */
--- diff/drivers/isdn/hisax/teles_cs.c	1970-01-01 01:00:00.000000000 +0100
+++ source/drivers/isdn/hisax/teles_cs.c	2004-02-23 13:56:42.000000000 +0000
@@ -0,0 +1,549 @@
+/* $Id: teles_cs.c,v 1.1.2.2 2004/01/25 15:07:06 keil Exp $ */
+/*======================================================================
+
+    A teles S0 PCMCIA client driver
+
+    Based on skeleton by David Hinds, dhinds@allegro.stanford.edu
+    Written by Christof Petig, christof.petig@wtal.de
+    
+    Also inspired by ELSA PCMCIA driver 
+    by Klaus Lichtenwalder <Lichtenwalder@ACM.org>
+    
+    Extentions to new hisax_pcmcia by Karsten Keil
+
+    minor changes to be compatible with kernel 2.4.x
+    by Jan.Schubert@GMX.li
+
+======================================================================*/
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/ptrace.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <linux/timer.h>
+#include <linux/ioport.h>
+#include <asm/io.h>
+#include <asm/system.h>
+
+#include <pcmcia/version.h>
+#include <pcmcia/cs_types.h>
+#include <pcmcia/cs.h>
+#include <pcmcia/cistpl.h>
+#include <pcmcia/cisreg.h>
+#include <pcmcia/ds.h>
+#include "hisax_cfg.h"
+
+MODULE_DESCRIPTION("ISDN4Linux: PCMCIA client driver for Teles PCMCIA cards");
+MODULE_AUTHOR("Christof Petig, christof.petig@wtal.de, Karsten Keil, kkeil@suse.de");
+MODULE_LICENSE("GPL");
+
+/*
+   All the PCMCIA modules use PCMCIA_DEBUG to control debugging.  If
+   you do not define PCMCIA_DEBUG at all, all the debug code will be
+   left out.  If you compile with PCMCIA_DEBUG=0, the debug code will
+   be present but disabled -- but it can then be enabled for specific
+   modules at load time with a 'pc_debug=#' option to insmod.
+*/
+
+#ifdef PCMCIA_DEBUG
+static int pc_debug = PCMCIA_DEBUG;
+MODULE_PARM(pc_debug, "i");
+#define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args);
+static char *version =
+"teles_cs.c 2.10 2002/07/30 22:23:34 kkeil";
+#else
+#define DEBUG(n, args...)
+#endif
+
+/*====================================================================*/
+
+/* Parameters that can be set with 'insmod' */
+
+/* Bit map of interrupts to choose from, the old way */
+/* This means pick from 15, 14, 12, 11, 10, 9, 7, 5, 4, 3 */
+static u_long irq_mask = 0xdeb8;
+
+/* Newer, simpler way of listing specific interrupts */
+static int irq_list[4] = { -1 };
+
+MODULE_PARM(irq_mask, "i");
+MODULE_PARM(irq_list, "1-4i");
+
+static int protocol = 2;        /* EURO-ISDN Default */
+MODULE_PARM(protocol, "i");
+
+/*====================================================================*/
+
+/*
+   The event() function is this driver's Card Services event handler.
+   It will be called by Card Services when an appropriate card status
+   event is received.  The config() and release() entry points are
+   used to configure or release a socket, in response to card insertion
+   and ejection events.  They are invoked from the teles_cs event
+   handler.
+*/
+
+static void teles_cs_config(dev_link_t *link);
+static void teles_cs_release(dev_link_t *link);
+static int teles_cs_event(event_t event, int priority,
+                          event_callback_args_t *args);
+
+/*
+   The attach() and detach() entry points are used to create and destroy
+   "instances" of the driver, where each instance represents everything
+   needed to manage one actual PCMCIA card.
+*/
+
+static dev_link_t *teles_attach(void);
+static void teles_detach(dev_link_t *);
+
+/*
+   The dev_info variable is the "key" that is used to match up this
+   device driver with appropriate cards, through the card configuration
+   database.
+*/
+
+static dev_info_t dev_info = "teles_cs";
+
+/*
+   A linked list of "instances" of the teles_cs device.  Each actual
+   PCMCIA card corresponds to one device instance, and is described
+   by one dev_link_t structure (defined in ds.h).
+
+   You may not want to use a linked list for this -- for example, the
+   memory card driver uses an array of dev_link_t pointers, where minor
+   device numbers are used to derive the corresponding array index.
+*/
+
+static dev_link_t *dev_list = NULL;
+
+/*
+   A dev_link_t structure has fields for most things that are needed
+   to keep track of a socket, but there will usually be some device
+   specific information that also needs to be kept track of.  The
+   'priv' pointer in a dev_link_t structure can be used to point to
+   a device-specific private data structure, like this.
+
+   To simplify the data structure handling, we actually include the
+   dev_link_t structure in the device's private data structure.
+
+   A driver needs to provide a dev_node_t structure for each device
+   on a card.  In some cases, there is only one device per card (for
+   example, ethernet cards, modems).  In other cases, there may be
+   many actual or logical devices (SCSI adapters, memory cards with
+   multiple partitions).  The dev_node_t structures need to be kept
+   in a linked list starting at the 'dev' field of a dev_link_t
+   structure.  We allocate them in the card's private data structure,
+   because they generally shouldn't be allocated dynamically.
+   In this case, we also provide a flag to indicate if a device is
+   "stopped" due to a power management event, or card ejection.  The
+   device IO routines can use a flag like this to throttle IO to a
+   card that is not ready to accept it.
+*/
+
+typedef struct local_info_t {
+    dev_link_t          link;
+    dev_node_t          node;
+    int                 busy;
+    int			cardnr;
+} local_info_t;
+
+/*======================================================================
+
+    teles_attach() creates an "instance" of the driver, allocatingx
+    local data structures for one device.  The device is registered
+    with Card Services.
+
+    The dev_link structure is initialized, but we don't actually
+    configure the card at this point -- we wait until we receive a
+    card insertion event.
+
+======================================================================*/
+
+static dev_link_t *teles_attach(void)
+{
+    client_reg_t client_reg;
+    dev_link_t *link;
+    local_info_t *local;
+    int ret, i;
+
+    DEBUG(0, "teles_attach()\n");
+
+    /* Allocate space for private device-specific data */
+    local = kmalloc(sizeof(local_info_t), GFP_KERNEL);
+    if (!local) return NULL;
+    memset(local, 0, sizeof(local_info_t));
+    local->cardnr = -1;
+    link = &local->link; link->priv = local;
+
+    /* Interrupt setup */
+    link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING|IRQ_FIRST_SHARED;
+    link->irq.IRQInfo1 = IRQ_INFO2_VALID|IRQ_LEVEL_ID|IRQ_SHARE_ID;
+    if (irq_list[0] == -1)
+        link->irq.IRQInfo2 = irq_mask;
+    else
+        for (i = 0; i < 4; i++)
+            link->irq.IRQInfo2 |= 1 << irq_list[i];
+    link->irq.Handler = NULL;
+
+    /*
+      General socket configuration defaults can go here.  In this
+      client, we assume very little, and rely on the CIS for almost
+      everything.  In most clients, many details (i.e., number, sizes,
+      and attributes of IO windows) are fixed by the nature of the
+      device, and can be hard-wired here.
+    */
+    link->io.NumPorts1 = 96;
+    link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
+    link->io.IOAddrLines = 5;
+
+    link->conf.Attributes = CONF_ENABLE_IRQ;
+    link->conf.Vcc = 50;
+    link->conf.IntType = INT_MEMORY_AND_IO;
+
+    /* Register with Card Services */
+    link->next = dev_list;
+    dev_list = link;
+    client_reg.dev_info = &dev_info;
+    client_reg.Attributes = INFO_IO_CLIENT | INFO_CARD_SHARE;
+    client_reg.EventMask =
+        CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL |
+        CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET |
+        CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME;
+    client_reg.event_handler = &teles_cs_event;
+    client_reg.Version = 0x0210;
+    client_reg.event_callback_args.client_data = link;
+    ret = pcmcia_register_client(&link->handle, &client_reg);
+    if (ret != CS_SUCCESS) {
+        cs_error(link->handle, RegisterClient, ret);
+        teles_detach(link);
+        return NULL;
+    }
+
+    return link;
+} /* teles_attach */
+
+/*======================================================================
+
+    This deletes a driver "instance".  The device is de-registered
+    with Card Services.  If it has been released, all local data
+    structures are freed.  Otherwise, the structures will be freed
+    when the device is released.
+
+======================================================================*/
+
+static void teles_detach(dev_link_t *link)
+{
+    dev_link_t **linkp;
+    local_info_t *info = link->priv;
+    int ret;
+
+    DEBUG(0, "teles_detach(0x%p)\n", link);
+
+    /* Locate device structure */
+    for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next)
+        if (*linkp == link) break;
+    if (*linkp == NULL)
+        return;
+
+    if (link->state & DEV_CONFIG)
+        teles_cs_release(link);
+
+    /*
+       If the device is currently configured and active, we won't
+       actually delete it yet.  Instead, it is marked so that when
+       the release() function is called, that will trigger a proper
+       detach().
+    */
+    if (link->state & DEV_CONFIG) {
+      DEBUG(0, "teles_cs: detach postponed, '%s' "
+               "still locked\n", link->dev->dev_name);
+        link->state |= DEV_STALE_LINK;
+        return;
+    }
+
+    /* Break the link with Card Services */
+    if (link->handle) {
+        ret = pcmcia_deregister_client(link->handle);
+	if (ret != CS_SUCCESS)
+	    cs_error(link->handle, DeregisterClient, ret);
+    }
+
+    /* Unlink device structure and free it */
+    *linkp = link->next;
+    kfree(info);
+
+} /* teles_detach */
+
+/*======================================================================
+
+    teles_cs_config() is scheduled to run after a CARD_INSERTION event
+    is received, to configure the PCMCIA socket, and to make the
+    device available to the system.
+
+======================================================================*/
+static int get_tuple(client_handle_t handle, tuple_t *tuple,
+                     cisparse_t *parse)
+{
+    int i = pcmcia_get_tuple_data(handle, tuple);
+    if (i != CS_SUCCESS) return i;
+    return pcmcia_parse_tuple(handle, tuple, parse);
+}
+
+static int first_tuple(client_handle_t handle, tuple_t *tuple,
+                     cisparse_t *parse)
+{
+    int i = pcmcia_get_first_tuple(handle, tuple);
+    if (i != CS_SUCCESS) return i;
+    return get_tuple(handle, tuple, parse);
+}
+
+static int next_tuple(client_handle_t handle, tuple_t *tuple,
+                     cisparse_t *parse)
+{
+    int i = pcmcia_get_next_tuple(handle, tuple);
+    if (i != CS_SUCCESS) return i;
+    return get_tuple(handle, tuple, parse);
+}
+
+static void teles_cs_config(dev_link_t *link)
+{
+    client_handle_t handle;
+    tuple_t tuple;
+    cisparse_t parse;
+    local_info_t *dev;
+    int i, j, last_fn;
+    u_short buf[128];
+    cistpl_cftable_entry_t *cf = &parse.cftable_entry;
+    IsdnCard_t icard;
+
+    DEBUG(0, "teles_config(0x%p)\n", link);
+    handle = link->handle;
+    dev = link->priv;
+
+    /*
+       This reads the card's CONFIG tuple to find its configuration
+       registers.
+    */
+    tuple.DesiredTuple = CISTPL_CONFIG;
+    tuple.TupleData = (cisdata_t *)buf;
+    tuple.TupleDataMax = 255;
+    tuple.TupleOffset = 0;
+    tuple.Attributes = 0;
+    i = first_tuple(handle, &tuple, &parse);
+    if (i != CS_SUCCESS) {
+        last_fn = ParseTuple;
+	goto cs_failed;
+    }
+    link->conf.ConfigBase = parse.config.base;
+    link->conf.Present = parse.config.rmask[0];
+
+    /* Configure card */
+    link->state |= DEV_CONFIG;
+
+    tuple.TupleData = (cisdata_t *)buf;
+    tuple.TupleOffset = 0; tuple.TupleDataMax = 255;
+    tuple.Attributes = 0;
+    tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
+    i = first_tuple(handle, &tuple, &parse);
+    while (i == CS_SUCCESS) {
+        if ( (cf->io.nwin > 0) && cf->io.win[0].base) {
+            printk(KERN_INFO "(teles_cs: looks like the 96 model)\n");
+            link->conf.ConfigIndex = cf->index;
+            link->io.BasePort1 = cf->io.win[0].base;
+            i = pcmcia_request_io(link->handle, &link->io);
+            if (i == CS_SUCCESS) break;
+        } else {
+          printk(KERN_INFO "(teles_cs: looks like the 97 model)\n");
+          link->conf.ConfigIndex = cf->index;
+          for (i = 0, j = 0x2f0; j > 0x100; j -= 0x10) {
+            link->io.BasePort1 = j;
+            i = pcmcia_request_io(link->handle, &link->io);
+            if (i == CS_SUCCESS) break;
+          }
+          break;
+        }
+        i = next_tuple(handle, &tuple, &parse);
+    }
+
+    if (i != CS_SUCCESS) {
+	last_fn = RequestIO;
+	goto cs_failed;
+    }
+
+    i = pcmcia_request_irq(link->handle, &link->irq);
+    if (i != CS_SUCCESS) {
+        link->irq.AssignedIRQ = 0;
+	last_fn = RequestIRQ;
+        goto cs_failed;
+    }
+
+    i = pcmcia_request_configuration(link->handle, &link->conf);
+    if (i != CS_SUCCESS) {
+      last_fn = RequestConfiguration;
+      goto cs_failed;
+    }
+
+    /* At this point, the dev_node_t structure(s) should be
+       initialized and arranged in a linked list at link->dev. *//*  */
+    sprintf(dev->node.dev_name, "teles");
+    dev->node.major = dev->node.minor = 0x0;
+
+    link->dev = &dev->node;
+
+    /* Finally, report what we've done */
+    printk(KERN_INFO "%s: index 0x%02x: Vcc %d.%d",
+           dev->node.dev_name, link->conf.ConfigIndex,
+           link->conf.Vcc/10, link->conf.Vcc%10);
+    if (link->conf.Vpp1)
+        printk(", Vpp %d.%d", link->conf.Vpp1/10, link->conf.Vpp1%10);
+    if (link->conf.Attributes & CONF_ENABLE_IRQ)
+        printk(", irq %d", link->irq.AssignedIRQ);
+    if (link->io.NumPorts1)
+        printk(", io 0x%04x-0x%04x", link->io.BasePort1,
+               link->io.BasePort1+link->io.NumPorts1-1);
+    if (link->io.NumPorts2)
+        printk(" & 0x%04x-0x%04x", link->io.BasePort2,
+               link->io.BasePort2+link->io.NumPorts2-1);
+    printk("\n");
+
+    link->state &= ~DEV_CONFIG_PENDING;
+
+    icard.para[0] = link->irq.AssignedIRQ;
+    icard.para[1] = link->io.BasePort1;
+    icard.protocol = protocol;
+    icard.typ = ISDN_CTYPE_TELESPCMCIA;
+    
+    i = hisax_init_pcmcia(link, &(((local_info_t*)link->priv)->busy), &icard);
+    if (i < 0) {
+    	printk(KERN_ERR "teles_cs: failed to initialize Teles PCMCIA %d at i/o %#x\n",
+    		i, link->io.BasePort1);
+    	teles_cs_release(link);
+    } else
+    	((local_info_t*)link->priv)->cardnr = i;
+
+    return;
+cs_failed:
+    cs_error(link->handle, last_fn, i);
+    teles_cs_release(link);
+} /* teles_cs_config */
+
+/*======================================================================
+
+    After a card is removed, teles_cs_release() will unregister the net
+    device, and release the PCMCIA configuration.  If the device is
+    still open, this will be postponed until it is closed.
+
+======================================================================*/
+
+static void teles_cs_release(dev_link_t *link)
+{
+    local_info_t *local = link->priv;
+
+    DEBUG(0, "teles_cs_release(0x%p)\n", link);
+
+    if (local) {
+    	if (local->cardnr >= 0) {
+    	    /* no unregister function with hisax */
+	    HiSax_closecard(local->cardnr);
+	}
+    }
+    /* Unlink the device chain */
+    link->dev = NULL;
+
+    /* Don't bother checking to see if these succeed or not */
+    if (link->win)
+        pcmcia_release_window(link->win);
+    pcmcia_release_configuration(link->handle);
+    pcmcia_release_io(link->handle, &link->io);
+    pcmcia_release_irq(link->handle, &link->irq);
+    link->state &= ~DEV_CONFIG;
+
+    if (link->state & DEV_STALE_LINK)
+        teles_detach(link);
+
+} /* teles_cs_release */
+
+/*======================================================================
+
+    The card status event handler.  Mostly, this schedules other
+    stuff to run after an event is received.  A CARD_REMOVAL event
+    also sets some flags to discourage the net drivers from trying
+    to talk to the card any more.
+
+    When a CARD_REMOVAL event is received, we immediately set a flag
+    to block future accesses to this device.  All the functions that
+    actually access the device should check this flag to make sure
+    the card is still present.
+
+======================================================================*/
+
+static int teles_cs_event(event_t event, int priority,
+                          event_callback_args_t *args)
+{
+    dev_link_t *link = args->client_data;
+    local_info_t *dev = link->priv;
+
+    DEBUG(1, "teles_cs_event(%d)\n", event);
+
+    switch (event) {
+    case CS_EVENT_CARD_REMOVAL:
+        link->state &= ~DEV_PRESENT;
+        if (link->state & DEV_CONFIG) {
+            ((local_info_t*)link->priv)->busy = 1;
+	    teles_cs_release(link);
+        }
+        break;
+    case CS_EVENT_CARD_INSERTION:
+        link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
+        teles_cs_config(link);
+        break;
+    case CS_EVENT_PM_SUSPEND:
+        link->state |= DEV_SUSPEND;
+        /* Fall through... */
+    case CS_EVENT_RESET_PHYSICAL:
+        /* Mark the device as stopped, to block IO until later */
+        dev->busy = 1;
+        if (link->state & DEV_CONFIG)
+            pcmcia_release_configuration(link->handle);
+        break;
+    case CS_EVENT_PM_RESUME:
+        link->state &= ~DEV_SUSPEND;
+        /* Fall through... */
+    case CS_EVENT_CARD_RESET:
+        if (link->state & DEV_CONFIG)
+            pcmcia_request_configuration(link->handle, &link->conf);
+        dev->busy = 0;
+        break;
+    }
+    return 0;
+} /* teles_cs_event */
+
+static struct pcmcia_driver teles_cs_driver = {
+	.owner		= THIS_MODULE,
+	.drv		= {
+		.name	= "teles_cs",
+	},
+	.attach		= teles_attach,
+	.detach		= teles_detach,
+};
+
+static int __init init_teles_cs(void)
+{
+	return pcmcia_register_driver(&teles_cs_driver);
+}
+
+static void __exit exit_teles_cs(void)
+{
+	pcmcia_unregister_driver(&teles_cs_driver);
+
+	/* XXX: this really needs to move into generic code.. */
+	while (dev_list != NULL)
+		teles_detach(dev_list);
+}
+
+module_init(init_teles_cs);
+module_exit(exit_teles_cs);
--- diff/drivers/md/dm-bio-list.h	1970-01-01 01:00:00.000000000 +0100
+++ source/drivers/md/dm-bio-list.h	2004-02-23 13:56:43.000000000 +0000
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2004 Red Hat UK Ltd.
+ *
+ * This file is released under the GPL.
+ */
+
+#ifndef DM_BIO_LIST_H
+#define DM_BIO_LIST_H
+
+#include <linux/bio.h>
+
+struct bio_list {
+	struct bio *head;
+	struct bio *tail;
+};
+
+static inline void bio_list_init(struct bio_list *bl)
+{
+	bl->head = bl->tail = NULL;
+}
+
+static inline void bio_list_add(struct bio_list *bl, struct bio *bio)
+{
+	bio->bi_next = NULL;
+
+	if (bl->tail)
+		bl->tail->bi_next = bio;
+	else
+		bl->head = bio;
+
+	bl->tail = bio;
+}
+
+static inline void bio_list_merge(struct bio_list *bl, struct bio_list *bl2)
+{
+	if (bl->tail)
+		bl->tail->bi_next = bl2->head;
+	else
+		bl->head = bl2->head;
+
+	bl->tail = bl2->tail;
+}
+
+static inline struct bio *bio_list_pop(struct bio_list *bl)
+{
+	struct bio *bio = bl->head;
+
+	if (bio) {
+		bl->head = bl->head->bi_next;
+		if (!bl->head)
+			bl->tail = NULL;
+
+		bio->bi_next = NULL;
+	}
+
+	return bio;
+}
+
+static inline struct bio *bio_list_get(struct bio_list *bl)
+{
+	struct bio *bio = bl->head;
+
+	bl->head = bl->tail = NULL;
+
+	return bio;
+}
+
+#endif
--- diff/drivers/md/dm-crypt.c	1970-01-01 01:00:00.000000000 +0100
+++ source/drivers/md/dm-crypt.c	2004-02-23 13:56:43.000000000 +0000
@@ -0,0 +1,837 @@
+/*
+ * Copyright (C) 2003 Christophe Saout <christophe@saout.de>
+ *
+ * This file is released under the GPL.
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/bio.h>
+#include <linux/mempool.h>
+#include <linux/slab.h>
+#include <linux/crypto.h>
+#include <linux/spinlock.h>
+#include <linux/workqueue.h>
+#include <asm/scatterlist.h>
+
+#include "dm.h"
+
+/*
+ * per bio private data
+ */
+struct crypt_io {
+	struct dm_target *target;
+	struct bio *bio;
+	struct bio *first_clone;
+	struct work_struct work;
+	atomic_t pending;
+	int error;
+};
+
+/*
+ * context holding the current state of a multi-part conversion
+ */
+struct convert_context {
+	struct bio *bio_in;
+	struct bio *bio_out;
+	unsigned int offset_in;
+	unsigned int offset_out;
+	int idx_in;
+	int idx_out;
+	sector_t sector;
+	int write;
+};
+
+/*
+ * Crypt: maps a linear range of a block device
+ * and encrypts / decrypts at the same time.
+ */
+struct crypt_config {
+	struct dm_dev *dev;
+	sector_t start;
+
+	/*
+	 * pool for per bio private data and
+	 * for encryption buffer pages
+	 */
+	mempool_t *io_pool;
+	mempool_t *page_pool;
+
+	/*
+	 * crypto related data
+	 */
+	struct crypto_tfm *cipher;
+	struct crypto_tfm *digest;
+	sector_t iv_offset;
+	int (*iv_generator)(struct crypt_config *cc, u8 *iv, sector_t sector);
+	int iv_size;
+	int key_size;
+	int digest_size;
+	u8 key[0];
+};
+
+#define MIN_IOS        256
+#define MIN_POOL_PAGES 32
+#define MIN_BIO_PAGES  8
+
+static kmem_cache_t *_crypt_io_pool;
+
+/*
+ * Mempool alloc and free functions for the page
+ */
+static void *mempool_alloc_page(int gfp_mask, void *data)
+{
+	return alloc_page(gfp_mask);
+}
+
+static void mempool_free_page(void *page, void *data)
+{
+	__free_page(page);
+}
+
+
+/*
+ * Different IV generation algorithms
+ */
+static int crypt_iv_plain(struct crypt_config *cc, u8 *iv, sector_t sector)
+{
+	*(u32 *)iv = cpu_to_le32(sector & 0xffffffff);
+	if (cc->iv_size > sizeof(u32) / sizeof(u8))
+		memset(iv + (sizeof(u32) / sizeof(u8)), 0,
+		       cc->iv_size - (sizeof(u32) / sizeof(u8)));
+
+	return 0;
+}
+
+static int crypt_iv_digest(struct crypt_config *cc, u8 *iv, sector_t sector)
+{
+	static DECLARE_MUTEX(tfm_mutex);
+	struct scatterlist sg[2] = {
+		{
+			.page = virt_to_page(iv),
+			.offset = offset_in_page(iv),
+			.length = sizeof(u64) / sizeof(u8)
+		}, {
+			.page = virt_to_page(cc->key),
+			.offset = offset_in_page(cc->key),
+			.length = cc->key_size
+		}
+	};
+	int i;
+
+	*(u64 *)iv = cpu_to_le64((u64)sector);
+
+	/* digests use the context in the tfm, sigh */
+	down(&tfm_mutex);
+	crypto_digest_digest(cc->digest, sg, 2, iv);
+	up(&tfm_mutex);
+
+	for(i = cc->digest_size; i < cc->iv_size; i += cc->digest_size)
+		memcpy(iv + i, iv, min(cc->digest_size, cc->iv_size - i));
+
+	return 0;
+}
+
+static inline int
+crypt_convert_scatterlist(struct crypt_config *cc, struct scatterlist *out,
+                          struct scatterlist *in, unsigned int length,
+                          int write, sector_t sector)
+{
+	u8 iv[cc->iv_size];
+	int r;
+
+	if (cc->iv_generator) {
+		r = cc->iv_generator(cc, iv, sector);
+		if (r < 0)
+			return r;
+
+		if (write)
+			r = crypto_cipher_encrypt_iv(cc->cipher, out, in, length, iv);
+		else
+			r = crypto_cipher_decrypt_iv(cc->cipher, out, in, length, iv);
+	} else {
+		if (write)
+			r = crypto_cipher_encrypt(cc->cipher, out, in, length);
+		else
+			r = crypto_cipher_decrypt(cc->cipher, out, in, length);
+	}
+
+	return r;
+}
+
+static void
+crypt_convert_init(struct crypt_config *cc, struct convert_context *ctx,
+                   struct bio *bio_out, struct bio *bio_in,
+                   sector_t sector, int write)
+{
+	ctx->bio_in = bio_in;
+	ctx->bio_out = bio_out;
+	ctx->offset_in = 0;
+	ctx->offset_out = 0;
+	ctx->idx_in = bio_in ? bio_in->bi_idx : 0;
+	ctx->idx_out = bio_out ? bio_out->bi_idx : 0;
+	ctx->sector = sector + cc->iv_offset;
+	ctx->write = write;
+}
+
+/*
+ * Encrypt / decrypt data from one bio to another one (can be the same one)
+ */
+static int crypt_convert(struct crypt_config *cc,
+                         struct convert_context *ctx)
+{
+	int r = 0;
+
+	while(ctx->idx_in < ctx->bio_in->bi_vcnt &&
+	      ctx->idx_out < ctx->bio_out->bi_vcnt) {
+		struct bio_vec *bv_in = bio_iovec_idx(ctx->bio_in, ctx->idx_in);
+		struct bio_vec *bv_out = bio_iovec_idx(ctx->bio_out, ctx->idx_out);
+		struct scatterlist sg_in = {
+			.page = bv_in->bv_page,
+			.offset = bv_in->bv_offset + ctx->offset_in,
+			.length = 1 << SECTOR_SHIFT
+		};
+		struct scatterlist sg_out = {
+			.page = bv_out->bv_page,
+			.offset = bv_out->bv_offset + ctx->offset_out,
+			.length = 1 << SECTOR_SHIFT
+		};
+
+		ctx->offset_in += sg_in.length;
+		if (ctx->offset_in >= bv_in->bv_len) {
+			ctx->offset_in = 0;
+			ctx->idx_in++;
+		}
+
+		ctx->offset_out += sg_out.length;
+		if (ctx->offset_out >= bv_out->bv_len) {
+			ctx->offset_out = 0;
+			ctx->idx_out++;
+		}
+
+		r = crypt_convert_scatterlist(cc, &sg_out, &sg_in, sg_in.length,
+		                              ctx->write, ctx->sector);
+		if (r < 0)
+			break;
+
+		ctx->sector++;
+	}
+
+	return r;
+}
+
+/*
+ * Generate a new unfragmented bio with the given size
+ * This should never violate the device limitations
+ * May return a smaller bio when running out of pages
+ */
+static struct bio *
+crypt_alloc_buffer(struct crypt_config *cc, unsigned int size,
+                   struct bio *base_bio, int *bio_vec_idx)
+{
+	struct bio *bio;
+	int nr_iovecs = dm_div_up(size, PAGE_SIZE);
+	int gfp_mask = GFP_NOIO | __GFP_HIGHMEM;
+	int flags = current->flags;
+	int i;
+
+	/*
+	 * Tell VM to act less aggressively and fail earlier.
+	 * This is not necessary but increases throughput.
+	 * FIXME: Is this really intelligent?
+	 */
+	current->flags &= ~PF_MEMALLOC;
+
+	if (base_bio)
+		bio = bio_clone(base_bio, GFP_NOIO);
+	else
+		bio = bio_alloc(GFP_NOIO, nr_iovecs);
+	if (!bio) {
+		if (flags & PF_MEMALLOC)
+			current->flags |= PF_MEMALLOC;
+		return NULL;
+	}
+
+	/* if the last bio was not complete, continue where that one ended */
+	bio->bi_idx = *bio_vec_idx;
+	bio->bi_vcnt = *bio_vec_idx;
+	bio->bi_size = 0;
+	bio->bi_flags &= ~(1 << BIO_SEG_VALID);
+
+	/* bio->bi_idx pages have already been allocated */
+	size -= bio->bi_idx * PAGE_SIZE;
+
+	for(i = bio->bi_idx; i < nr_iovecs; i++) {
+		struct bio_vec *bv = bio_iovec_idx(bio, i);
+
+		bv->bv_page = mempool_alloc(cc->page_pool, gfp_mask);
+		if (!bv->bv_page)
+			break;
+
+		/*
+		 * if additional pages cannot be allocated without waiting,
+		 * return a partially allocated bio, the caller will then try
+		 * to allocate additional bios while submitting this partial bio
+		 */
+		if ((i - bio->bi_idx) == (MIN_BIO_PAGES - 1))
+			gfp_mask = (gfp_mask | __GFP_NOWARN) & ~__GFP_WAIT;
+
+		bv->bv_offset = 0;
+		if (size > PAGE_SIZE)
+			bv->bv_len = PAGE_SIZE;
+		else
+			bv->bv_len = size;
+
+		bio->bi_size += bv->bv_len;
+		bio->bi_vcnt++;
+		size -= bv->bv_len;
+	}
+
+	if (flags & PF_MEMALLOC)
+		current->flags |= PF_MEMALLOC;
+
+	if (!bio->bi_size) {
+		bio_put(bio);
+		return NULL;
+	}
+
+	/*
+	 * Remember the last bio_vec allocated to be able
+	 * to correctly continue after the splitting.
+	 */
+	*bio_vec_idx = bio->bi_vcnt;
+
+	return bio;
+}
+
+static void crypt_free_buffer_pages(struct crypt_config *cc,
+                                    struct bio *bio, unsigned int bytes)
+{
+	unsigned int start, end;
+	struct bio_vec *bv;
+	int i;
+
+	/*
+	 * This is ugly, but Jens Axboe thinks that using bi_idx in the
+	 * endio function is too dangerous at the moment, so I calculate the
+	 * correct position using bi_vcnt and bi_size.
+	 * The bv_offset and bv_len fields might already be modified but we
+	 * know that we always allocated whole pages.
+	 * A fix to the bi_idx issue in the kernel is in the works, so
+	 * we will hopefully be able to revert to the cleaner solution soon.
+	 */
+	i = bio->bi_vcnt - 1;
+	bv = bio_iovec_idx(bio, i);
+	end = (i << PAGE_SHIFT) + (bv->bv_offset + bv->bv_len) - bio->bi_size;
+	start = end - bytes;
+
+	start >>= PAGE_SHIFT;
+	if (!bio->bi_size)
+		end = bio->bi_vcnt;
+	else
+		end >>= PAGE_SHIFT;
+
+	for(i = start; i < end; i++) {
+		bv = bio_iovec_idx(bio, i);
+		BUG_ON(!bv->bv_page);
+		mempool_free(bv->bv_page, cc->page_pool);
+		bv->bv_page = NULL;
+	}
+}
+
+/*
+ * One of the bios was finished. Check for completion of
+ * the whole request and correctly clean up the buffer.
+ */
+static void dec_pending(struct crypt_io *io, int error)
+{
+	struct crypt_config *cc = (struct crypt_config *) io->target->private;
+
+	if (error < 0)
+		io->error = error;
+
+	if (!atomic_dec_and_test(&io->pending))
+		return;
+
+	if (io->first_clone)
+		bio_put(io->first_clone);
+
+	bio_endio(io->bio, io->bio->bi_size, io->error);
+
+	mempool_free(io, cc->io_pool);
+}
+
+/*
+ * kcryptd:
+ *
+ * Needed because it would be very unwise to do decryption in an
+ * interrupt context, so bios returning from read requests get
+ * queued here.
+ */
+static struct workqueue_struct *_kcryptd_workqueue;
+
+static void kcryptd_do_work(void *data)
+{
+	struct crypt_io *io = (struct crypt_io *) data;
+	struct crypt_config *cc = (struct crypt_config *) io->target->private;
+	struct convert_context ctx;
+	int r;
+
+	crypt_convert_init(cc, &ctx, io->bio, io->bio,
+	                   io->bio->bi_sector - io->target->begin, 0);
+	r = crypt_convert(cc, &ctx);
+
+	dec_pending(io, r);
+}
+
+static void kcryptd_queue_io(struct crypt_io *io)
+{
+	INIT_WORK(&io->work, kcryptd_do_work, io);
+	queue_work(_kcryptd_workqueue, &io->work);
+}
+
+/*
+ * Decode key from its hex representation
+ */
+static int crypt_decode_key(u8 *key, char *hex, int size)
+{
+	char buffer[3];
+	char *endp;
+	int i;
+
+	buffer[2] = '\0';
+
+	for(i = 0; i < size; i++) {
+		buffer[0] = *hex++;
+		buffer[1] = *hex++;
+
+		key[i] = (u8)simple_strtoul(buffer, &endp, 16);
+
+		if (endp != &buffer[2])
+			return -EINVAL;
+	}
+
+	if (*hex != '\0')
+		return -EINVAL;
+
+	return 0;
+}
+
+/*
+ * Encode key into its hex representation
+ */
+static void crypt_encode_key(char *hex, u8 *key, int size)
+{
+	int i;
+
+	for(i = 0; i < size; i++) {
+		sprintf(hex, "%02x", *key);
+		hex += 2;
+		key++;
+	}
+}
+
+/*
+ * Construct an encryption mapping:
+ * <cipher> <key> <iv_offset> <dev_path> <start>
+ */
+static int crypt_ctr(struct dm_target *ti, unsigned int argc, char **argv)
+{
+	struct crypt_config *cc;
+	struct crypto_tfm *tfm;
+	char *tmp;
+	char *cipher;
+	char *mode;
+	int crypto_flags;
+	int key_size;
+
+	if (argc != 5) {
+		ti->error = "dm-crypt: Not enough arguments";
+		return -EINVAL;
+	}
+
+	tmp = argv[0];
+	cipher = strsep(&tmp, "-");
+	mode = strsep(&tmp, "-");
+
+	if (tmp)
+		DMWARN("dm-crypt: Unexpected additional cipher options");
+
+	key_size = strlen(argv[1]) >> 1;
+
+	cc = kmalloc(sizeof(*cc) + key_size * sizeof(u8), GFP_KERNEL);
+	if (cc == NULL) {
+		ti->error =
+			"dm-crypt: Cannot allocate transparent encryption context";
+		return -ENOMEM;
+	}
+
+	cc->digest_size = 0;
+	cc->digest = NULL;
+	if (!mode || strcmp(mode, "plain") == 0)
+		cc->iv_generator = crypt_iv_plain;
+	else if (strcmp(mode, "ecb") == 0)
+		cc->iv_generator = NULL;
+	else {
+		tfm = crypto_alloc_tfm(mode, 0);
+		if (!tfm) {
+			ti->error = "dm-crypt: Error allocating digest tfm";
+			goto bad1;
+		}
+		if (crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_DIGEST) {
+			ti->error = "dm-crypt: Expected digest algorithm";
+			goto bad1;
+		}
+
+		cc->digest = tfm;
+		cc->digest_size = crypto_tfm_alg_digestsize(tfm);
+		cc->iv_generator = crypt_iv_digest;
+	}
+
+	if (cc->iv_generator)
+		crypto_flags = CRYPTO_TFM_MODE_CBC;
+	else
+		crypto_flags = CRYPTO_TFM_MODE_ECB;
+
+	tfm = crypto_alloc_tfm(cipher, crypto_flags);
+	if (!tfm) {
+		ti->error = "dm-crypt: Error allocating crypto tfm";
+		goto bad1;
+	}
+	if (crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_CIPHER) {
+		ti->error = "dm-crypt: Expected cipher algorithm";
+		goto bad1;
+	}
+
+	if (tfm->crt_u.cipher.cit_decrypt_iv &&
+	    tfm->crt_u.cipher.cit_encrypt_iv) {
+		/* at least a sector number should fit in our buffer */
+		cc->iv_size = max(crypto_tfm_alg_ivsize(tfm),
+		                  (unsigned int)(sizeof(u64) / sizeof(u8)));
+		cc->iv_size = max(cc->iv_size, cc->digest_size);
+	} else {
+		cc->iv_size = 0;
+		if (cc->iv_generator) {
+			DMWARN("dm-crypt: Selected cipher does not support IVs");
+			cc->iv_generator = NULL;
+		}
+	}
+
+	cc->io_pool = mempool_create(MIN_IOS, mempool_alloc_slab,
+				     mempool_free_slab, _crypt_io_pool);
+	if (!cc->io_pool) {
+		ti->error = "dm-crypt: Cannot allocate crypt io mempool";
+		goto bad2;
+	}
+
+	cc->page_pool = mempool_create(MIN_POOL_PAGES, mempool_alloc_page,
+				       mempool_free_page, NULL);
+	if (!cc->page_pool) {
+		ti->error = "dm-crypt: Cannot allocate page mempool";
+		goto bad3;
+	}
+
+	cc->cipher = tfm;
+	cc->key_size = key_size;
+	if ((key_size == 0 && strcmp(argv[1], "-") != 0)
+	    || crypt_decode_key(cc->key, argv[1], key_size) < 0) {
+		ti->error = "dm-crypt: Error decoding key";
+		goto bad4;
+	}
+
+	if (tfm->crt_u.cipher.cit_setkey(tfm, cc->key, key_size) < 0) {
+		ti->error = "dm-crypt: Error setting key";
+		goto bad4;
+	}
+
+	if (sscanf(argv[2], SECTOR_FORMAT, &cc->iv_offset) != 1) {
+		ti->error = "dm-crypt: Invalid iv_offset sector";
+		goto bad4;
+	}
+
+	if (sscanf(argv[4], SECTOR_FORMAT, &cc->start) != 1) {
+		ti->error = "dm-crypt: Invalid device sector";
+		goto bad4;
+	}
+
+	if (dm_get_device(ti, argv[3], cc->start, ti->len,
+	                  dm_table_get_mode(ti->table), &cc->dev)) {
+		ti->error = "dm-crypt: Device lookup failed";
+		goto bad4;
+	}
+
+	ti->private = cc;
+	return 0;
+
+bad4:
+	mempool_destroy(cc->page_pool);
+bad3:
+	mempool_destroy(cc->io_pool);
+bad2:
+	crypto_free_tfm(tfm);
+bad1:
+	if (cc->digest)
+		crypto_free_tfm(cc->digest);
+	kfree(cc);
+	return -EINVAL;
+}
+
+static void crypt_dtr(struct dm_target *ti)
+{
+	struct crypt_config *cc = (struct crypt_config *) ti->private;
+
+	mempool_destroy(cc->page_pool);
+	mempool_destroy(cc->io_pool);
+
+	crypto_free_tfm(cc->cipher);
+	if (cc->digest)
+		crypto_free_tfm(cc->digest);
+
+	dm_put_device(ti, cc->dev);
+	kfree(cc);
+}
+
+static int crypt_endio(struct bio *bio, unsigned int done, int error)
+{
+	struct crypt_io *io = (struct crypt_io *) bio->bi_private;
+	struct crypt_config *cc = (struct crypt_config *) io->target->private;
+
+	if (bio_data_dir(bio) == WRITE) {
+		/*
+		 * free the processed pages, even if
+		 * it's only a partially completed write
+		 */
+		crypt_free_buffer_pages(cc, bio, done);
+	}
+
+	if (bio->bi_size)
+		return 1;
+
+	bio_put(bio);
+
+	/*
+	 * successful reads are decrypted by the worker thread
+	 */
+	if ((bio_data_dir(bio) == READ)
+	    && bio_flagged(bio, BIO_UPTODATE)) {
+		kcryptd_queue_io(io);
+		return 0;
+	}
+
+	dec_pending(io, error);
+	return error;
+}
+
+static inline struct bio *
+crypt_clone(struct crypt_config *cc, struct crypt_io *io, struct bio *bio,
+            sector_t sector, int *bvec_idx, struct convert_context *ctx)
+{
+	struct bio *clone;
+
+	if (bio_data_dir(bio) == WRITE) {
+		clone = crypt_alloc_buffer(cc, bio->bi_size,
+                                 io->first_clone, bvec_idx);
+		if (clone) {
+			ctx->bio_out = clone;
+			if (crypt_convert(cc, ctx) < 0) {
+				crypt_free_buffer_pages(cc, clone,
+				                        clone->bi_size);
+				bio_put(clone);
+				return NULL;
+			}
+		}
+	} else
+		clone = bio_clone(bio, GFP_NOIO);
+
+	if (!clone)
+		return NULL;
+
+	clone->bi_private = io;
+	clone->bi_end_io = crypt_endio;
+	clone->bi_bdev = cc->dev->bdev;
+	clone->bi_sector = cc->start + sector;
+	clone->bi_rw = bio->bi_rw;
+
+	return clone;
+}
+
+static int crypt_map(struct dm_target *ti, struct bio *bio,
+		     union map_info *map_context)
+{
+	struct crypt_config *cc = (struct crypt_config *) ti->private;
+	struct crypt_io *io = mempool_alloc(cc->io_pool, GFP_NOIO);
+	struct convert_context ctx;
+	struct bio *clone;
+	unsigned int remaining = bio->bi_size;
+	sector_t sector = bio->bi_sector - ti->begin;
+	int bvec_idx = 0;
+
+	io->target = ti;
+	io->bio = bio;
+	io->first_clone = NULL;
+	io->error = 0;
+	atomic_set(&io->pending, 1); /* hold a reference */
+
+	if (bio_data_dir(bio) == WRITE)
+		crypt_convert_init(cc, &ctx, NULL, bio, sector, 1);
+
+	/*
+	 * The allocated buffers can be smaller than the whole bio,
+	 * so repeat the whole process until all the data can be handled.
+	 */
+	while (remaining) {
+		clone = crypt_clone(cc, io, bio, sector, &bvec_idx, &ctx);
+		if (!clone)
+			goto cleanup;
+
+		if (!io->first_clone) {
+			/*
+			 * hold a reference to the first clone, because it
+			 * holds the bio_vec array and that can't be freed
+			 * before all other clones are released
+			 */
+			bio_get(clone);
+			io->first_clone = clone;
+		}
+		atomic_inc(&io->pending);
+
+		remaining -= clone->bi_size;
+		sector += bio_sectors(clone);
+
+		generic_make_request(clone);
+
+		/* out of memory -> run queues */
+		if (remaining)
+			blk_run_queues();
+	}
+
+	/* drop reference, clones could have returned before we reach this */
+	dec_pending(io, 0);
+	return 0;
+
+cleanup:
+	if (io->first_clone) {
+		dec_pending(io, -ENOMEM);
+		return 0;
+	}
+
+	/* if no bio has been dispatched yet, we can directly return the error */
+	mempool_free(io, cc->io_pool);
+	return -ENOMEM;
+}
+
+static int crypt_status(struct dm_target *ti, status_type_t type,
+			char *result, unsigned int maxlen)
+{
+	struct crypt_config *cc = (struct crypt_config *) ti->private;
+	char buffer[32];
+	const char *cipher;
+	const char *mode = NULL;
+	int offset;
+
+	switch (type) {
+	case STATUSTYPE_INFO:
+		result[0] = '\0';
+		break;
+
+	case STATUSTYPE_TABLE:
+		cipher = crypto_tfm_alg_name(cc->cipher);
+
+		switch(cc->cipher->crt_u.cipher.cit_mode) {
+		case CRYPTO_TFM_MODE_CBC:
+			if (cc->digest)
+				mode = crypto_tfm_alg_name(cc->digest);
+			else
+				mode = "plain";
+			break;
+		case CRYPTO_TFM_MODE_ECB:
+			mode = "ecb";
+			break;
+		default:
+			BUG();
+		}
+
+		snprintf(result, maxlen, "%s-%s ", cipher, mode);
+		offset = strlen(result);
+
+		if (cc->key_size > 0) {
+			if ((maxlen - offset) < ((cc->key_size << 1) + 1))
+				return -ENOMEM;
+
+			crypt_encode_key(result + offset, cc->key, cc->key_size);
+			offset += cc->key_size << 1;
+		} else {
+			if (offset >= maxlen)
+				return -ENOMEM;
+			result[offset++] = '-';
+		}
+
+		format_dev_t(buffer, cc->dev->bdev->bd_dev);
+		snprintf(result + offset, maxlen - offset, " " SECTOR_FORMAT
+		         " %s " SECTOR_FORMAT, cc->iv_offset,
+		         buffer, cc->start);
+		break;
+	}
+	return 0;
+}
+
+static struct target_type crypt_target = {
+	.name   = "crypt",
+	.version= {1, 0, 0},
+	.module = THIS_MODULE,
+	.ctr    = crypt_ctr,
+	.dtr    = crypt_dtr,
+	.map    = crypt_map,
+	.status = crypt_status,
+};
+
+static int __init dm_crypt_init(void)
+{
+	int r;
+
+	_crypt_io_pool = kmem_cache_create("dm-crypt_io",
+	                                   sizeof(struct crypt_io),
+	                                   0, 0, NULL, NULL);
+	if (!_crypt_io_pool)
+		return -ENOMEM;
+
+	_kcryptd_workqueue = create_workqueue("kcryptd");
+	if (!_kcryptd_workqueue) {
+		r = -ENOMEM;
+		DMERR("couldn't create kcryptd");
+		goto bad1;
+	}
+
+	r = dm_register_target(&crypt_target);
+	if (r < 0) {
+		DMERR("crypt: register failed %d", r);
+		goto bad2;
+	}
+
+	return 0;
+
+bad2:
+	destroy_workqueue(_kcryptd_workqueue);
+bad1:
+	kmem_cache_destroy(_crypt_io_pool);
+	return r;
+}
+
+static void __exit dm_crypt_exit(void)
+{
+	int r = dm_unregister_target(&crypt_target);
+
+	if (r < 0)
+		DMERR("crypt: unregister failed %d", r);
+
+	destroy_workqueue(_kcryptd_workqueue);
+	kmem_cache_destroy(_crypt_io_pool);
+}
+
+module_init(dm_crypt_init);
+module_exit(dm_crypt_exit);
+
+MODULE_AUTHOR("Christophe Saout <christophe@saout.de>");
+MODULE_DESCRIPTION(DM_NAME " target for transparent encryption / decryption");
+MODULE_LICENSE("GPL");
--- diff/drivers/md/dm-mpath.c	1970-01-01 01:00:00.000000000 +0100
+++ source/drivers/md/dm-mpath.c	2004-02-23 13:56:43.000000000 +0000
@@ -0,0 +1,729 @@
+/*
+ * Copyright (C) 2003 Sistina Software Limited.
+ *
+ * This file is released under the GPL.
+ */
+
+#include "dm.h"
+#include "dm-path-selector.h"
+#include "dm-bio-list.h"
+
+#include <linux/ctype.h>
+#include <linux/init.h>
+#include <linux/mempool.h>
+#include <linux/module.h>
+#include <linux/pagemap.h>
+#include <linux/slab.h>
+#include <linux/time.h>
+#include <linux/workqueue.h>
+#include <asm/atomic.h>
+
+/* FIXME: get rid of this */
+#define MPATH_FAIL_COUNT	1
+
+/*
+ * We don't want to call the path selector for every single io
+ * that comes through, so instead we only consider changing paths
+ * every MPATH_MIN_IO ios.  This number should be selected to be
+ * big enough that we can reduce the overhead of the path
+ * selector, but also small enough that we don't take the policy
+ * decision away from the path selector.
+ *
+ * So people should _not_ be tuning this number to try and get
+ * the most performance from some particular type of hardware.
+ * All the smarts should be going into the path selector.
+ */
+#define MPATH_MIN_IO		1000
+
+/* Path properties */
+struct path {
+	struct list_head list;
+
+	struct dm_dev *dev;
+	struct priority_group *pg;
+
+	spinlock_t failed_lock;
+	int has_failed;
+	unsigned fail_count;
+};
+
+struct priority_group {
+	struct list_head list;
+
+	unsigned priority;
+	struct multipath *m;
+	struct path_selector *ps;
+
+	unsigned nr_paths;
+	struct list_head paths;
+};
+
+/* Multipath context */
+struct multipath {
+	struct list_head list;
+	struct dm_target *ti;
+
+	unsigned nr_paths;
+	unsigned nr_priority_groups;
+	struct list_head priority_groups;
+
+	spinlock_t lock;
+	unsigned nr_valid_paths;
+
+	struct path *current_path;
+	unsigned current_count;
+
+	struct work_struct dispatch_failed;
+	struct bio_list failed_ios;
+
+	struct work_struct trigger_event;
+};
+
+static void dispatch_failed_ios(void *data);
+static void trigger_event(void *data);
+
+static struct path *alloc_path(void)
+{
+	struct path *path = kmalloc(sizeof(*path), GFP_KERNEL);
+
+	if (path) {
+		memset(path, 0, sizeof(*path));
+		path->failed_lock = SPIN_LOCK_UNLOCKED;
+		path->fail_count = MPATH_FAIL_COUNT;
+	}
+
+	return path;
+}
+
+static inline void free_path(struct path *p)
+{
+	kfree(p);
+}
+
+static struct priority_group *alloc_priority_group(void)
+{
+	struct priority_group *pg;
+
+	pg = kmalloc(sizeof(*pg), GFP_KERNEL);
+	if (!pg)
+		return NULL;
+
+	pg->ps = kmalloc(sizeof(*pg->ps), GFP_KERNEL);
+	if (!pg->ps) {
+		kfree(pg);
+		return NULL;
+	}
+	memset(pg->ps, 0, sizeof(*pg->ps));
+
+	INIT_LIST_HEAD(&pg->paths);
+
+	return pg;
+}
+
+static void free_paths(struct list_head *paths, struct dm_target *ti)
+{
+	struct path *path, *tmp;
+
+	list_for_each_entry_safe (path, tmp, paths, list) {
+		list_del(&path->list);
+		dm_put_device(ti, path->dev);
+		free_path(path);
+	}
+}
+
+static void free_priority_group(struct priority_group *pg,
+				struct dm_target *ti)
+{
+	struct path_selector *ps = pg->ps;
+
+	if (ps) {
+		if (ps->type) {
+			ps->type->dtr(ps);
+			dm_put_path_selector(ps->type);
+		}
+		kfree(ps);
+	}
+
+	free_paths(&pg->paths, ti);
+	kfree(pg);
+}
+
+static struct multipath *alloc_multipath(void)
+{
+	struct multipath *m;
+
+	m = kmalloc(sizeof(*m), GFP_KERNEL);
+	if (m) {
+		memset(m, 0, sizeof(*m));
+		INIT_LIST_HEAD(&m->priority_groups);
+		m->lock = SPIN_LOCK_UNLOCKED;
+		INIT_WORK(&m->dispatch_failed, dispatch_failed_ios, m);
+		INIT_WORK(&m->trigger_event, trigger_event, m);
+	}
+
+	return m;
+}
+
+static void free_multipath(struct multipath *m)
+{
+	struct priority_group *pg, *tmp;
+
+	list_for_each_entry_safe (pg, tmp, &m->priority_groups, list) {
+		list_del(&pg->list);
+		free_priority_group(pg, m->ti);
+	}
+
+	kfree(m);
+}
+
+/*-----------------------------------------------------------------
+ * The multipath daemon is responsible for resubmitting failed ios.
+ *---------------------------------------------------------------*/
+static struct workqueue_struct *_kmpathd_wq;
+
+static int __choose_path(struct multipath *m)
+{
+	struct priority_group *pg;
+	struct path *path = NULL;
+
+	if (m->nr_valid_paths) {
+		/* loop through the priority groups until we find a valid path. */
+		list_for_each_entry (pg, &m->priority_groups, list) {
+			path = pg->ps->type->select_path(pg->ps);
+			if (path)
+				break;
+		}
+	}
+
+	m->current_path = path;
+	m->current_count = MPATH_MIN_IO;
+
+	return 0;
+}
+
+static struct path *get_current_path(struct multipath *m)
+{
+	struct path *path;
+	unsigned long flags;
+
+	spin_lock_irqsave(&m->lock, flags);
+
+	/* Do we need to select a new path? */
+	if (!m->current_path || --m->current_count == 0)
+		__choose_path(m);
+
+	path = m->current_path;
+
+	spin_unlock_irqrestore(&m->lock, flags);
+
+	return path;
+}
+
+static int map_io(struct multipath *m, struct bio *bio)
+{
+	struct path *path;
+
+	path = get_current_path(m);
+	if (!path)
+		return -EIO;
+
+	bio->bi_bdev = path->dev->bdev;
+	return 0;
+}
+
+static void dispatch_failed_ios(void *data)
+{
+	struct multipath *m = (struct multipath *) data;
+
+	int r;
+	unsigned long flags;
+	struct bio *bio = NULL, *next;
+
+	spin_lock_irqsave(&m->lock, flags);
+	bio = bio_list_get(&m->failed_ios);
+	spin_unlock_irqrestore(&m->lock, flags);
+
+	while (bio) {
+		next = bio->bi_next;
+		bio->bi_next = NULL;
+
+		r = map_io(m, bio);
+		if (r)
+			/*
+			 * This wont loop forever because the
+			 * end_io function will fail the ios if
+			 * we've no valid paths left.
+			 */
+			bio_io_error(bio, bio->bi_size);
+		else
+			generic_make_request(bio);
+
+		bio = next;
+	}
+
+	/*
+	 * FIXME: this now gets called once for each mpath
+	 * target, rather than once per daemon cycle.
+	 */
+ 	blk_run_queues();
+}
+
+static void trigger_event(void *data)
+{
+	struct multipath *m = (struct multipath *) data;
+	dm_table_event(m->ti->table);
+}
+
+/*-----------------------------------------------------------------
+ * Constructor/argument parsing:
+ * <poll interval> <num priority groups> [<priority> <selector>
+ * <num selector args> <num paths> [<path> [<arg>]* ]+ ]+
+ *---------------------------------------------------------------*/
+struct param {
+	unsigned min;
+	unsigned max;
+	char *error;
+};
+
+#define ESTR(s) ("dm-multipath: " s)
+
+static int read_param(struct param *param, char *str, unsigned *v, char **error)
+{
+	if (!str ||
+	    (sscanf(str, "%u", v) != 1) ||
+	    (*v < param->min) ||
+	    (*v > param->max)) {
+		*error = param->error;
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+struct arg_set {
+	unsigned argc;
+	char **argv;
+};
+
+static char *shift(struct arg_set *as)
+{
+	char *r;
+
+	if (as->argc) {
+		as->argc--;
+		r = *as->argv;
+		as->argv++;
+		return r;
+	}
+
+	return NULL;
+}
+
+static void consume(struct arg_set *as, unsigned n)
+{
+	BUG_ON (as->argc < n);
+	as->argc -= n;
+	as->argv += n;
+}
+
+static struct path *parse_path(struct arg_set *as, struct path_selector *ps,
+			       struct dm_target *ti)
+{
+	int r;
+	struct path *p;
+
+	/* we need at least a path arg */
+	if (as->argc < 1) {
+		ti->error = ESTR("no device given");
+		return NULL;
+	}
+
+	p = alloc_path();
+	if (!p)
+		return NULL;
+
+	r = dm_get_device(ti, shift(as), ti->begin, ti->len,
+			  dm_table_get_mode(ti->table), &p->dev);
+	if (r) {
+		ti->error = ESTR("error getting device");
+		goto bad;
+	}
+
+	r = ps->type->add_path(ps, p, as->argc, as->argv, &ti->error);
+	if (r) {
+		dm_put_device(ti, p->dev);
+		goto bad;
+	}
+
+	return p;
+
+ bad:
+	free_path(p);
+	return NULL;
+}
+
+static struct priority_group *parse_priority_group(struct arg_set *as,
+						   struct multipath *m,
+						   struct dm_target *ti)
+{
+	static struct param _params[] = {
+		{0, 1024, ESTR("invalid priority")},
+		{1, 1024, ESTR("invalid number of paths")},
+		{0, 1024, ESTR("invalid number of selector args")}
+	};
+
+	int r;
+	unsigned i, nr_selector_args, nr_params;
+	struct priority_group *pg;
+	struct path_selector_type *pst;
+
+	if (as->argc < 3) {
+		as->argc = 0;
+		ti->error = ESTR("not enough priority group aruments");
+		return NULL;
+	}
+
+	pg = alloc_priority_group();
+	if (!pg) {
+		ti->error = ESTR("couldn't allocate priority group");
+		return NULL;
+	}
+
+	r = read_param(_params, shift(as), &pg->priority, &ti->error);
+	if (r)
+		goto bad;
+
+	pst = dm_get_path_selector(shift(as));
+	if (!pst) {
+		ti->error = ESTR("unknown path selector type");
+		goto bad;
+	}
+
+	r = pst->ctr(pg->ps);
+	if (r) {
+		/* FIXME: need to put the pst ? fix after
+		 * factoring out the register */
+		goto bad;
+	}
+	pg->ps->type = pst;
+
+	/*
+	 * read the paths
+	 */
+	r = read_param(_params + 1, shift(as), &pg->nr_paths, &ti->error);
+	if (r)
+		goto bad;
+
+	r = read_param(_params + 2, shift(as), &nr_selector_args, &ti->error);
+	if (r)
+		goto bad;
+
+	nr_params = 1 + nr_selector_args;
+	for (i = 0; i < pg->nr_paths; i++) {
+		struct path *path;
+		struct arg_set path_args;
+
+		if (as->argc < nr_params)
+			goto bad;
+
+		path_args.argc = nr_params;
+		path_args.argv = as->argv;
+
+		path = parse_path(&path_args, pg->ps, ti);
+		if (!path)
+			goto bad;
+
+		path->pg = pg;
+		list_add_tail(&path->list, &pg->paths);
+		consume(as, nr_params);
+	}
+
+	return pg;
+
+ bad:
+	free_priority_group(pg, ti);
+	return NULL;
+}
+
+static void __insert_priority_group(struct multipath *m,
+				    struct priority_group *pg)
+{
+	struct priority_group *tmp;
+
+	list_for_each_entry (tmp, &m->priority_groups, list)
+		if (tmp->priority > pg->priority)
+			break;
+
+	list_add_tail(&pg->list, &tmp->list);
+	pg->m = m;
+}
+
+static int multipath_ctr(struct dm_target *ti, unsigned int argc,
+			 char **argv)
+{
+	/* target parameters */
+	static struct param _params[] = {
+		{1, 1024, ESTR("invalid number of priority groups")},
+	};
+
+	int r;
+	struct multipath *m;
+	struct arg_set as;
+
+	as.argc = argc;
+	as.argv = argv;
+
+	m = alloc_multipath();
+	if (!m) {
+		ti->error = ESTR("can't allocate multipath");
+		return -EINVAL;
+	}
+
+	r = read_param(_params, shift(&as), &m->nr_priority_groups, &ti->error);
+	if (r)
+		goto bad;
+
+	/* parse the priority groups */
+	while (as.argc) {
+		struct priority_group *pg;
+		pg = parse_priority_group(&as, m, ti);
+		if (pg) {
+			m->nr_paths += pg->nr_paths;
+			__insert_priority_group(m, pg);
+		}
+	}
+	m->nr_valid_paths = m->nr_paths;
+
+	ti->private = m;
+	m->ti = ti;
+
+	return 0;
+
+ bad:
+	free_multipath(m);
+	return -EINVAL;
+}
+
+static void multipath_dtr(struct dm_target *ti)
+{
+	struct multipath *m = (struct multipath *) ti->private;
+	free_multipath(m);
+}
+
+static int multipath_map(struct dm_target *ti, struct bio *bio,
+			 union map_info *map_context)
+{
+	int r;
+	struct multipath *m = (struct multipath *) ti->private;
+
+	bio->bi_rw |= (1 << BIO_RW_FAILFAST);
+	r = map_io(m, bio);
+	if (r)
+		return r;
+
+	return 1;
+}
+
+/*
+ * Only called on the error path.
+ */
+static struct path *find_path(struct multipath *m, struct block_device *bdev)
+{
+	struct path *p;
+	struct priority_group *pg;
+
+	list_for_each_entry (pg, &m->priority_groups, list)
+		list_for_each_entry (p, &pg->paths, list)
+			if (p->dev->bdev == bdev)
+				return p;
+
+	return NULL;
+}
+
+static void fail_path(struct path *path)
+{
+	unsigned long flags;
+	struct multipath *m;
+
+	spin_lock_irqsave(&path->failed_lock, flags);
+
+	/* FIXME: path->fail_count is brain dead */
+	if (!path->has_failed && !--path->fail_count) {
+		m = path->pg->m;
+
+		path->has_failed = 1;
+		path->pg->ps->type->fail_path(path->pg->ps, path);
+		queue_work(_kmpathd_wq, &m->trigger_event);
+
+		spin_lock(&m->lock);
+		m->nr_valid_paths--;
+
+		if (path == m->current_path)
+			m->current_path = NULL;
+
+		spin_unlock(&m->lock);
+	}
+
+	spin_unlock_irqrestore(&path->failed_lock, flags);
+}
+
+static int multipath_end_io(struct dm_target *ti, struct bio *bio,
+			    int error, union map_info *map_context)
+{
+	struct path *path;
+	struct multipath *m = (struct multipath *) ti->private;
+
+	if (error) {
+		spin_lock(&m->lock);
+		if (!m->nr_valid_paths) {
+			spin_unlock(&m->lock);
+			return -EIO;
+		}
+		spin_unlock(&m->lock);
+
+		path = find_path(m, bio->bi_bdev);
+		fail_path(path);
+
+		/* queue for the daemon to resubmit */
+		spin_lock(&m->lock);
+		bio_list_add(&m->failed_ios, bio);
+		spin_unlock(&m->lock);
+
+		queue_work(_kmpathd_wq, &m->dispatch_failed);
+		return 1;	/* io not complete */
+	}
+
+	return 0;
+}
+
+/*
+ * Info string has the following format:
+ * num_groups [num_paths num_selector_args [path_dev A|F fail_count [selector_args]* ]+ ]+
+ *
+ * Table string has the following format (identical to the constructor string):
+ * num_groups [priority selector-name num_paths num_selector_args [path_dev [selector_args]* ]+ ]+
+ */
+static int multipath_status(struct dm_target *ti, status_type_t type,
+			    char *result, unsigned int maxlen)
+{
+	int sz = 0;
+	unsigned long flags;
+	struct multipath *m = (struct multipath *) ti->private;
+	struct priority_group *pg;
+	struct path *p;
+	char buffer[32];
+
+	switch (type) {
+	case STATUSTYPE_INFO:
+		sz += snprintf(result + sz, maxlen - sz, "%u ", m->nr_priority_groups);
+
+		list_for_each_entry(pg, &m->priority_groups, list) {
+			sz += snprintf(result + sz, maxlen - sz, "%u %u ",
+                                       pg->nr_paths,
+				       pg->ps->type->info_args);
+
+			list_for_each_entry(p, &pg->paths, list) {
+				format_dev_t(buffer, p->dev->bdev->bd_dev);
+				spin_lock_irqsave(&p->failed_lock, flags);
+				sz += snprintf(result + sz, maxlen - sz,
+					       "%s %s %u ", buffer,
+					       p->has_failed ? "F" : "A",
+					       p->fail_count);
+				pg->ps->type->status(pg->ps, p, type,
+						     result + sz, maxlen - sz);
+				spin_unlock_irqrestore(&p->failed_lock, flags);
+
+				sz = strlen(result);
+				if (sz >= maxlen)
+					break;
+			}
+		}
+
+		break;
+
+	case STATUSTYPE_TABLE:
+		sz += snprintf(result + sz, maxlen - sz, "%u ", m->nr_priority_groups);
+
+		list_for_each_entry(pg, &m->priority_groups, list) {
+			sz += snprintf(result + sz, maxlen - sz, "%u %s %u %u ",
+				       pg->priority, pg->ps->type->name,
+				       pg->nr_paths, pg->ps->type->table_args);
+
+			list_for_each_entry(p, &pg->paths, list) {
+				format_dev_t(buffer, p->dev->bdev->bd_dev);
+				sz += snprintf(result + sz, maxlen - sz,
+					       "%s ", buffer);
+				pg->ps->type->status(pg->ps, p, type,
+						     result + sz, maxlen - sz);
+
+				sz = strlen(result);
+				if (sz >= maxlen)
+					break;
+			}
+		}
+
+		break;
+	}
+
+	return 0;
+}
+
+/*-----------------------------------------------------------------
+ * Module setup
+ *---------------------------------------------------------------*/
+static struct target_type multipath_target = {
+	.name = "multipath",
+	.version = {1, 0, 2},
+	.module = THIS_MODULE,
+	.ctr = multipath_ctr,
+	.dtr = multipath_dtr,
+	.map = multipath_map,
+	.end_io = multipath_end_io,
+	.status = multipath_status,
+};
+
+int __init dm_multipath_init(void)
+{
+	int r;
+
+	r = dm_register_target(&multipath_target);
+	if (r < 0) {
+		DMERR("%s: register failed %d", multipath_target.name, r);
+		return -EINVAL;
+	}
+
+	r = dm_register_path_selectors();
+	if (r && r != -EEXIST) {
+		dm_unregister_target(&multipath_target);
+		return r;
+	}
+
+	_kmpathd_wq = create_workqueue("dm-mpath");
+	if (!_kmpathd_wq) {
+		/* FIXME: remove this */
+		dm_unregister_path_selectors();
+		dm_unregister_target(&multipath_target);
+	} else
+		DMINFO("dm_multipath v0.2.0");
+
+	return r;
+}
+
+void __exit dm_multipath_exit(void)
+{
+	int r;
+
+	destroy_workqueue(_kmpathd_wq);
+	dm_unregister_path_selectors();
+	r = dm_unregister_target(&multipath_target);
+	if (r < 0)
+		DMERR("%s: target unregister failed %d",
+		      multipath_target.name, r);
+}
+
+module_init(dm_multipath_init);
+module_exit(dm_multipath_exit);
+
+MODULE_DESCRIPTION(DM_NAME " multipath target");
+MODULE_AUTHOR("Sistina software <dm@uk.sistina.com>");
+MODULE_LICENSE("GPL");
--- diff/drivers/md/dm-path-selector.c	1970-01-01 01:00:00.000000000 +0100
+++ source/drivers/md/dm-path-selector.c	2004-02-23 13:56:43.000000000 +0000
@@ -0,0 +1,298 @@
+/*
+ * Copyright (C) 2003 Sistina Software.
+ *
+ * Module Author: Heinz Mauelshagen
+ *
+ * This file is released under the GPL.
+ *
+ * Path selector housekeeping (register/unregister/...)
+ */
+
+#include "dm.h"
+#include "dm-path-selector.h"
+
+#include <linux/slab.h>
+
+struct ps_internal {
+	struct path_selector_type pt;
+
+	struct list_head list;
+	long use;
+};
+
+static LIST_HEAD(_path_selectors);
+static DECLARE_MUTEX(_lock);
+
+struct path_selector_type *__find_path_selector_type(const char *name)
+{
+	struct ps_internal *li;
+
+	list_for_each_entry (li, &_path_selectors, list) {
+		if (!strcmp(name, li->pt.name))
+			return &li->pt;
+	}
+
+	return NULL;
+}
+
+struct path_selector_type *dm_get_path_selector(const char *name)
+{
+	struct path_selector_type *lb;
+
+	if (!name)
+		return NULL;
+
+	down(&_lock);
+	lb = __find_path_selector_type(name);
+	if (lb) {
+		struct ps_internal *li = (struct ps_internal *) lb;
+		li->use++;
+	}
+	up(&_lock);
+
+	return lb;
+}
+
+void dm_put_path_selector(struct path_selector_type *l)
+{
+	struct ps_internal *li = (struct ps_internal *) l;
+
+	down(&_lock);
+	if (--li->use < 0)
+		BUG();
+	up(&_lock);
+
+	return;
+}
+
+static struct ps_internal *_alloc_path_selector(struct path_selector_type *pt)
+{
+	struct ps_internal *psi = kmalloc(sizeof(*psi), GFP_KERNEL);
+
+	if (psi) {
+		memset(psi, 0, sizeof(*psi));
+		memcpy(psi, pt, sizeof(*pt));
+	}
+
+	return psi;
+}
+
+int dm_register_path_selector(struct path_selector_type *pst)
+{
+	int r = 0;
+	struct ps_internal *psi = _alloc_path_selector(pst);
+
+	if (!psi)
+		return -ENOMEM;
+
+	down(&_lock);
+	if (__find_path_selector_type(pst->name)) {
+		kfree(psi);
+		r = -EEXIST;
+	} else
+		list_add(&psi->list, &_path_selectors);
+
+	up(&_lock);
+
+	return r;
+}
+
+int dm_unregister_path_selector(struct path_selector_type *pst)
+{
+	struct ps_internal *psi;
+
+	down(&_lock);
+	psi = (struct ps_internal *) __find_path_selector_type(pst->name);
+	if (!psi) {
+		up(&_lock);
+		return -EINVAL;
+	}
+
+	if (psi->use) {
+		up(&_lock);
+		return -ETXTBSY;
+	}
+
+	list_del(&psi->list);
+	up(&_lock);
+
+	kfree(psi);
+
+	return 0;
+}
+
+/*-----------------------------------------------------------------
+ * Path handling code, paths are held in lists
+ *---------------------------------------------------------------*/
+struct path_info {
+	struct list_head list;
+	struct path *path;
+};
+
+static struct path_info *path_lookup(struct list_head *head, struct path *p)
+{
+	struct path_info *pi;
+
+	list_for_each_entry (pi, head, list)
+		if (pi->path == p)
+			return pi;
+
+	return NULL;
+}
+
+/*-----------------------------------------------------------------
+ * Round robin selector
+ *---------------------------------------------------------------*/
+struct selector {
+	spinlock_t lock;
+
+	struct list_head valid_paths;
+	struct list_head invalid_paths;
+};
+
+static struct selector *alloc_selector(void)
+{
+	struct selector *s = kmalloc(sizeof(*s), GFP_KERNEL);
+
+	if (s) {
+		INIT_LIST_HEAD(&s->valid_paths);
+		INIT_LIST_HEAD(&s->invalid_paths);
+		s->lock = SPIN_LOCK_UNLOCKED;
+	}
+
+	return s;
+}
+
+/* Path selector constructor */
+static int rr_ctr(struct path_selector *ps)
+{
+	struct selector *s;
+
+	s = alloc_selector();
+	if (!s)
+		return -ENOMEM;
+
+	ps->context = s;
+	return 0;
+}
+
+static void free_paths(struct list_head *paths)
+{
+	struct path_info *pi, *next;
+
+	list_for_each_entry_safe (pi, next, paths, list) {
+		list_del(&pi->list);
+		kfree(pi);
+	}
+}
+
+/* Path selector destructor */
+static void rr_dtr(struct path_selector *ps)
+{
+	struct selector *s = (struct selector *) ps->context;
+	free_paths(&s->valid_paths);
+	free_paths(&s->invalid_paths);
+	kfree(s);
+}
+
+/* Path add context */
+static int rr_add_path(struct path_selector *ps, struct path *path,
+		       int argc, char **argv, char **error)
+{
+	struct selector *s = (struct selector *) ps->context;
+	struct path_info *pi;
+
+	/* parse the path arguments */
+	if (argc != 0) {
+		*error = "round-robin ps: incorrect number of arguments";
+		return -EINVAL;
+	}
+
+	/* allocate the path */
+	pi = kmalloc(sizeof(*pi), GFP_KERNEL);
+	if (!pi) {
+		*error = "round-robin ps: Error allocating path context";
+		return -ENOMEM;
+	}
+
+	pi->path = path;
+
+	spin_lock(&s->lock);
+	list_add(&pi->list, &s->valid_paths);
+	spin_unlock(&s->lock);
+
+	return 0;
+}
+
+static void rr_fail_path(struct path_selector *ps, struct path *p)
+{
+	unsigned long flags;
+	struct selector *s = (struct selector *) ps->context;
+	struct path_info *pi;
+
+	/*
+	 * This function will be called infrequently so we don't
+	 * mind the expense of these searches.
+	 */
+	spin_lock_irqsave(&s->lock, flags);
+	pi = path_lookup(&s->valid_paths, p);
+	if (!pi)
+		pi = path_lookup(&s->invalid_paths, p);
+
+	if (!pi)
+		DMWARN("asked to change the state of an unknown path");
+
+	else
+		list_move(&pi->list, &s->invalid_paths);
+
+	spin_unlock_irqrestore(&s->lock, flags);
+}
+
+/* Path selector */
+static struct path *rr_select_path(struct path_selector *ps)
+{
+	unsigned long flags;
+	struct selector *s = (struct selector *) ps->context;
+	struct path_info *pi = NULL;
+
+	spin_lock_irqsave(&s->lock, flags);
+	if (!list_empty(&s->valid_paths)) {
+		pi = list_entry(s->valid_paths.next, struct path_info, list);
+		list_move_tail(&pi->list, &s->valid_paths);
+	}
+	spin_unlock_irqrestore(&s->lock, flags);
+
+	return pi ? pi->path : NULL;
+}
+
+/* Path status */
+static int rr_status(struct path_selector *ps, struct path *path,
+		     status_type_t type, char *result, unsigned int maxlen)
+{
+	return 0;
+}
+
+static struct path_selector_type rr_ps = {
+	.name = "round-robin",
+	.table_args = 0,
+	.info_args = 0,
+	.ctr = rr_ctr,
+	.dtr = rr_dtr,
+	.add_path = rr_add_path,
+	.fail_path = rr_fail_path,
+	.select_path = rr_select_path,
+	.status = rr_status,
+};
+
+/*
+ * (Un)register all path selectors (FIXME: remove this after tests)
+ */
+int dm_register_path_selectors(void)
+{
+	return dm_register_path_selector(&rr_ps);
+}
+
+void dm_unregister_path_selectors(void)
+{
+	dm_unregister_path_selector(&rr_ps);
+}
--- diff/drivers/md/dm-path-selector.h	1970-01-01 01:00:00.000000000 +0100
+++ source/drivers/md/dm-path-selector.h	2004-02-23 13:56:43.000000000 +0000
@@ -0,0 +1,103 @@
+/*
+ * Copyright (C) 2003 Sistina Software.
+ *
+ * Module Author: Heinz Mauelshagen
+ *
+ * This file is released under the GPL.
+ *
+ * Path-Selector interface/registration/unregistration definitions
+ *
+ */
+
+#ifndef	DM_PATH_SELECTOR_H
+#define	DM_PATH_SELECTOR_H
+
+#include <linux/device-mapper.h>
+
+struct path;
+
+/*
+ * We provide an abstraction for the code that chooses which path
+ * to send some io down.
+ */
+struct path_selector_type;
+struct path_selector {
+	struct path_selector_type *type;
+	void *context;
+};
+
+/*
+ * Constructs a path selector object, takes custom arguments
+ */
+typedef int (*ps_ctr_fn) (struct path_selector *ps);
+typedef void (*ps_dtr_fn) (struct path_selector *ps);
+
+/*
+ * Add an opaque path object, along with some selector specific
+ * path args (eg, path priority).
+ */
+typedef	int (*ps_add_path_fn) (struct path_selector *ps,
+			       struct path *path,
+			       int argc, char **argv, char **error);
+
+/*
+ * Chooses a path for this io, if no paths are available then
+ * NULL will be returned. The selector may set the map_info
+ * object if it wishes, this will be fed back into the endio fn.
+ *
+ * Must ensure that _any_ dynamically allocated selection context is
+ * reused or reallocated because an endio call (which needs to free it)
+ * might happen after a couple of select calls.
+ */
+typedef	struct path *(*ps_select_path_fn) (struct path_selector *ps);
+
+/*
+ * Notify the selector that a path has failed.
+ */
+typedef	void (*ps_fail_path_fn) (struct path_selector *ps,
+				 struct path *p);
+
+/*
+ * Table content based on parameters added in ps_add_path_fn
+ * or path selector status
+ */
+typedef	int (*ps_status_fn) (struct path_selector *ps,
+			     struct path *path,
+			     status_type_t type,
+			     char *result, unsigned int maxlen);
+
+/* Information about a path selector type */
+struct path_selector_type {
+	char *name;
+	unsigned int table_args;
+	unsigned int info_args;
+	ps_ctr_fn ctr;
+	ps_dtr_fn dtr;
+
+	ps_add_path_fn add_path;
+	ps_fail_path_fn fail_path;
+	ps_select_path_fn select_path;
+	ps_status_fn status;
+};
+
+/*
+ * FIXME: Factor out registration code.
+ */
+
+/* Register a path selector */
+int dm_register_path_selector(struct path_selector_type *type);
+
+/* Unregister a path selector */
+int dm_unregister_path_selector(struct path_selector_type *type);
+
+/* Returns a registered path selector type */
+struct path_selector_type *dm_get_path_selector(const char *name);
+
+/* Releases a path selector  */
+void dm_put_path_selector(struct path_selector_type *pst);
+
+/* FIXME: remove these */
+int dm_register_path_selectors(void);
+void dm_unregister_path_selectors(void);
+
+#endif
--- diff/drivers/media/radio/radio-sf16fmr2.c	1970-01-01 01:00:00.000000000 +0100
+++ source/drivers/media/radio/radio-sf16fmr2.c	2004-02-23 13:56:43.000000000 +0000
@@ -0,0 +1,447 @@
+/* SF16FMR2 radio driver for Linux radio support
+ * heavily based on fmi driver...
+ * (c) 2000-2002 Ziglio Frediano, freddy77@angelfire.com
+ *
+ * Notes on the hardware
+ *
+ *  Frequency control is done digitally -- ie out(port,encodefreq(95.8));
+ *  No volume control - only mute/unmute - you have to use line volume
+ *
+ *  For read stereo/mono you must wait 0.1 sec after set frequency and
+ *  card unmuted so I set frequency on unmute
+ *  Signal handling seem to work only on autoscanning (not implemented)
+ */
+
+#include <linux/module.h>	/* Modules 			*/
+#include <linux/init.h>		/* Initdata			*/
+#include <linux/ioport.h>	/* check_region, request_region	*/
+#include <linux/delay.h>	/* udelay			*/
+#include <asm/io.h>		/* outb, outb_p			*/
+#include <asm/uaccess.h>	/* copy to/from user		*/
+#include <linux/videodev.h>	/* kernel radio structs		*/
+#include <asm/semaphore.h>
+
+static struct semaphore lock;
+
+#undef DEBUG
+//#define DEBUG 1
+
+#ifdef DEBUG
+# define  debug_print(s) printk s
+#else
+# define  debug_print(s)
+#endif
+
+/* this should be static vars for module size */
+struct fmr2_device
+{
+	int port;
+	int curvol; /* 0-65535, if not volume 0 or 65535 */
+	int mute;
+	int stereo; /* card is producing stereo audio */
+	unsigned long curfreq; /* freq in kHz */
+	int card_type;
+	__u32 flags;
+};
+
+static int io = 0x384;
+static int radio_nr = -1;
+
+/* hw precision is 12.5 kHz
+ * It is only usefull to give freq in intervall of 200 (=0.0125Mhz),
+ * other bits will be truncated
+ */
+#define RSF16_ENCODE(x)	((x)/200+856)
+#define RSF16_MINFREQ 87*16000
+#define RSF16_MAXFREQ 108*16000
+
+/* from radio-aimslab */
+static void sleep_delay(unsigned long n)
+{
+	unsigned d=n/(1000000U/HZ);
+	if (!d)
+		udelay(n);
+	else
+	{
+		set_current_state(TASK_UNINTERRUPTIBLE);
+		schedule_timeout(d);
+	}
+}
+
+static inline void wait(int n,int port)
+{
+	for (;n;--n) inb(port);
+}
+
+static void outbits(int bits, unsigned int data, int nWait, int port)
+{
+	int bit;
+	for(;--bits>=0;) {
+		bit = (data>>bits) & 1;
+		outb(bit,port);
+		wait(nWait,port);
+		outb(bit|2,port);
+		wait(nWait,port);
+		outb(bit,port);
+		wait(nWait,port);
+	}
+}
+
+static inline void fmr2_mute(int port)
+{
+	outb(0x00, port);
+	wait(4,port);
+}
+
+static inline void fmr2_unmute(int port)
+{
+	outb(0x04, port);
+	wait(4,port);
+}
+
+static inline int fmr2_stereo_mode(int port)
+{
+	int n = inb(port);
+	outb(6,port);
+	inb(port);
+	n = ((n>>3)&1)^1;
+	debug_print((KERN_DEBUG "stereo: %d\n", n));
+	return n;
+}
+
+static int fmr2_product_info(struct fmr2_device *dev)
+{
+	int n = inb(dev->port);
+	n &= 0xC1;
+	if (n == 0)
+	{
+		/* this should support volume set */
+		dev->card_type = 12;
+		return 0;
+	}
+	/* not volume (mine is 11) */
+	dev->card_type = (n==128)?11:0;
+	return n;
+}
+
+static inline int fmr2_getsigstr(struct fmr2_device *dev)
+{
+	/* !!! work only if scanning freq */
+	int port = dev->port, res = 0xffff;
+	outb(5,port);
+	wait(4,port);
+	if (!(inb(port)&1)) res = 0;
+	debug_print((KERN_DEBUG "signal: %d\n", res));
+	return res;
+}
+
+/* set frequency and unmute card */
+static int fmr2_setfreq(struct fmr2_device *dev)
+{
+	int port = dev->port;
+	unsigned long freq = dev->curfreq;
+
+	fmr2_mute(port);
+
+	/* 0x42 for mono output
+	 * 0x102 forward scanning
+	 * 0x182 scansione avanti
+	 */
+	outbits(9,0x2,3,port);
+	outbits(16,RSF16_ENCODE(freq),2,port);
+
+	fmr2_unmute(port);
+
+	/* wait 0.11 sec */
+	sleep_delay(110000LU);
+
+	/* NOTE if mute this stop radio
+	   you must set freq on unmute */
+	dev->stereo = fmr2_stereo_mode(port);
+	return 0;
+}
+
+/* !!! not tested, in my card this does't work !!! */
+static int fmr2_setvolume(struct fmr2_device *dev)
+{
+	int i,a,n, port = dev->port;
+
+	if (dev->card_type != 11) return 1;
+
+	switch( (dev->curvol+(1<<11)) >> 12 )
+	{
+	case 0: case 1: n = 0x21; break;
+	case 2: n = 0x84; break;
+	case 3: n = 0x90; break;
+	case 4: n = 0x104; break;
+	case 5: n = 0x110; break;
+	case 6: n = 0x204; break;
+	case 7: n = 0x210; break;
+	case 8: n = 0x402; break;
+	case 9: n = 0x404; break;
+	default:
+	case 10: n = 0x408; break;
+	case 11: n = 0x410; break;
+	case 12: n = 0x801; break;
+	case 13: n = 0x802; break;
+	case 14: n = 0x804; break;
+	case 15: n = 0x808; break;
+	case 16: n = 0x810; break;
+	}
+	for(i=12;--i>=0;)
+	{
+		a = ((n >> i) & 1) << 6; /* if (a=0) a= 0; else a= 0x40; */
+		outb(a|4, port);
+		wait(4,port);
+		outb(a|0x24, port);
+		wait(4,port);
+		outb(a|4, port);
+		wait(4,port);
+	}
+	for(i=6;--i>=0;)
+	{
+		a = ((0x18 >> i) & 1) << 6;
+		outb(a|4, port);
+		wait(4,port);
+		outb(a|0x24, port);
+		wait(4,port);
+		outb(a|4, port);
+		wait(4,port);
+	}
+	wait(4,port);
+	outb(0x14, port);
+
+	return 0;
+}
+
+static int fmr2_do_ioctl(struct inode *inode, struct file *file,
+                      unsigned int cmd, void *arg)
+{
+	struct video_device *dev = video_devdata(file);
+	struct fmr2_device *fmr2 = dev->priv;
+	debug_print((KERN_DEBUG "freq %ld flags %d vol %d mute %d "
+		"stereo %d type %d\n",
+		fmr2->curfreq, fmr2->flags, fmr2->curvol, fmr2->mute,
+		fmr2->stereo, fmr2->card_type));
+
+	switch(cmd)
+	{
+		case VIDIOCGCAP:
+		{
+			struct video_capability *v = arg;
+			memset(v,0,sizeof(*v));
+			strcpy(v->name, "SF16-FMR2 radio");
+			v->type=VID_TYPE_TUNER;
+			v->channels=1;
+			v->audios=1;
+			return 0;
+		}
+		case VIDIOCGTUNER:
+		{
+			struct video_tuner *v = arg;
+			int mult;
+
+			if(v->tuner)     /* Only 1 tuner */
+				return -EINVAL;
+			strcpy(v->name, "FM");
+			mult = (fmr2->flags & VIDEO_TUNER_LOW) ? 1 : 1000;
+			v->rangelow = RSF16_MINFREQ/mult;
+			v->rangehigh = RSF16_MAXFREQ/mult;
+			v->flags = fmr2->flags | VIDEO_AUDIO_MUTABLE;
+			if (fmr2->mute)
+				v->flags |= VIDEO_AUDIO_MUTE;
+			v->mode=VIDEO_MODE_AUTO;
+			down(&lock);
+			v->signal = fmr2_getsigstr(fmr2);
+			up(&lock);
+			return 0;
+		}
+		case VIDIOCSTUNER:
+		{
+			struct video_tuner *v = arg;
+			if (v->tuner!=0)
+				return -EINVAL;
+			fmr2->flags = v->flags & VIDEO_TUNER_LOW;
+			return 0;
+		}
+		case VIDIOCGFREQ:
+		{
+			unsigned long *freq = arg;
+			*freq = fmr2->curfreq;
+			if (!(fmr2->flags & VIDEO_TUNER_LOW))
+				*freq /= 1000;
+			return 0;
+		}
+		case VIDIOCSFREQ:
+		{
+			unsigned long *freq = arg;
+			if (!(fmr2->flags & VIDEO_TUNER_LOW))
+				*freq *= 1000;
+			if ( *freq < RSF16_MINFREQ || *freq > RSF16_MAXFREQ )
+				return -EINVAL;
+			/* rounding in steps of 200 to match th freq
+			 * that will be used
+			 */
+			fmr2->curfreq = (*freq/200)*200;
+
+			/* set card freq (if not muted) */
+			if (fmr2->curvol && !fmr2->mute)
+			{
+				down(&lock);
+				fmr2_setfreq(fmr2);
+				up(&lock);
+			}
+			return 0;
+		}
+		case VIDIOCGAUDIO:
+		{
+			struct video_audio *v = arg;
+			memset(v,0,sizeof(*v));
+			/* !!! do not return VIDEO_AUDIO_MUTE */
+			v->flags = VIDEO_AUDIO_MUTABLE;
+			strcpy(v->name, "Radio");
+			/* get current stereo mode */
+			v->mode = fmr2->stereo ? VIDEO_SOUND_STEREO: VIDEO_SOUND_MONO;
+			/* volume supported ? */
+			if (fmr2->card_type == 11)
+			{
+				v->flags |= VIDEO_AUDIO_VOLUME;
+				v->step = 1 << 12;
+				v->volume = fmr2->curvol;
+			}
+			debug_print((KERN_DEBUG "Get flags %d vol %d\n", v->flags, v->volume));
+			return 0;
+		}
+		case VIDIOCSAUDIO:
+		{
+			struct video_audio *v = arg;
+			if(v->audio)
+				return -EINVAL;
+			debug_print((KERN_DEBUG "Set flags %d vol %d\n", v->flags, v->volume));
+			/* set volume */
+			if (v->flags & VIDEO_AUDIO_VOLUME)
+				fmr2->curvol = v->volume; /* !!! set with precision */
+			if (fmr2->card_type != 11) fmr2->curvol = 65535;
+			fmr2->mute = 0;
+			if (v->flags & VIDEO_AUDIO_MUTE)
+				fmr2->mute = 1;
+#ifdef DEBUG
+			if (fmr2->curvol && !fmr2->mute)
+				printk(KERN_DEBUG "unmute\n");
+			else
+				printk(KERN_DEBUG "mute\n");
+#endif
+			down(&lock);
+			if (fmr2->curvol && !fmr2->mute)
+			{
+				fmr2_setvolume(fmr2);
+				fmr2_setfreq(fmr2);
+			}
+			else fmr2_mute(fmr2->port);
+			up(&lock);
+			return 0;
+		}
+		case VIDIOCGUNIT:
+		{
+			struct video_unit *v = arg;
+			v->video=VIDEO_NO_UNIT;
+			v->vbi=VIDEO_NO_UNIT;
+			v->radio=dev->minor;
+			v->audio=0; /* How do we find out this??? */
+			v->teletext=VIDEO_NO_UNIT;
+			return 0;
+		}
+		default:
+			return -ENOIOCTLCMD;
+	}
+}
+
+static int fmr2_ioctl(struct inode *inode, struct file *file,
+                      unsigned int cmd, unsigned long arg)
+ {
+	return video_usercopy(inode, file, cmd, arg, fmr2_do_ioctl);
+}
+
+static struct fmr2_device fmr2_unit;
+
+static struct file_operations fmr2_fops = {
+	.owner          = THIS_MODULE,
+	.open           = video_exclusive_open,
+	.release        = video_exclusive_release,
+	.ioctl          = fmr2_ioctl,
+	.llseek         = no_llseek,
+};
+
+static struct video_device fmr2_radio=
+{
+	.owner		= THIS_MODULE,
+	.name		= "SF16FMR2 radio",
+	. type		= VID_TYPE_TUNER,
+	.hardware	= VID_HARDWARE_SF16FMR2,
+	.fops		= &fmr2_fops,
+};
+
+static int __init fmr2_init(void)
+{
+	fmr2_unit.port = io;
+	fmr2_unit.curvol = 0;
+	fmr2_unit.mute = 0;
+	fmr2_unit.curfreq = 0;
+	fmr2_unit.stereo = 1;
+	fmr2_unit.flags = VIDEO_TUNER_LOW;
+	fmr2_unit.card_type = 0;
+	fmr2_radio.priv = &fmr2_unit;
+
+	init_MUTEX(&lock);
+
+	if (request_region(io, 2, "sf16fmr2"))
+	{
+		printk(KERN_ERR "fmr2: port 0x%x already in use\n", io);
+		return -EBUSY;
+	}
+
+	if(video_register_device(&fmr2_radio, VFL_TYPE_RADIO, radio_nr)==-1)
+	{
+		release_region(io, 2);
+		return -EINVAL;
+	}
+
+	printk(KERN_INFO "SF16FMR2 radio card driver at 0x%x.\n", io);
+	debug_print((KERN_DEBUG "Mute %d Low %d\n",VIDEO_AUDIO_MUTE,VIDEO_TUNER_LOW));
+	/* mute card - prevents noisy bootups */
+	down(&lock);
+	fmr2_mute(io);
+	fmr2_product_info(&fmr2_unit);
+	up(&lock);
+	debug_print((KERN_DEBUG "card_type %d\n", fmr2_unit.card_type));
+	return 0;
+}
+
+MODULE_AUTHOR("Ziglio Frediano, freddy77@angelfire.com");
+MODULE_DESCRIPTION("A driver for the SF16FMR2 radio.");
+MODULE_LICENSE("GPL");
+
+MODULE_PARM(io, "i");
+MODULE_PARM_DESC(io, "I/O address of the SF16FMR2 card (should be 0x384, if do not work try 0x284)");
+MODULE_PARM(radio_nr, "i");
+
+static void __exit fmr2_cleanup_module(void)
+{
+	video_unregister_device(&fmr2_radio);
+	release_region(io,2);
+}
+
+module_init(fmr2_init);
+module_exit(fmr2_cleanup_module);
+
+#ifndef MODULE
+
+static int __init fmr2_setup_io(char *str)
+{
+	get_option(&str, &io);
+	return 1;
+}
+
+__setup("sf16fmr2=", fmr2_setup_io);
+
+#endif
--- diff/drivers/net/e100.c	1970-01-01 01:00:00.000000000 +0100
+++ source/drivers/net/e100.c	2004-02-23 13:56:43.000000000 +0000
@@ -0,0 +1,2297 @@
+/*******************************************************************************
+
+  
+  Copyright(c) 1999 - 2004 Intel Corporation. All rights reserved.
+  
+  This program is free software; you can redistribute it and/or modify it 
+  under the terms of the GNU General Public License as published by the Free 
+  Software Foundation; either version 2 of the License, or (at your option) 
+  any later version.
+  
+  This program is distributed in the hope that it will be useful, but WITHOUT 
+  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 
+  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for 
+  more details.
+  
+  You should have received a copy of the GNU General Public License along with
+  this program; if not, write to the Free Software Foundation, Inc., 59 
+  Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+  
+  The full GNU General Public License is included in this distribution in the
+  file called LICENSE.
+  
+  Contact Information:
+  Linux NICS <linux.nics@intel.com>
+  Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+
+*******************************************************************************/
+
+/*
+ *	e100.c: Intel(R) PRO/100 ethernet driver
+ *
+ *	(Re)written 2003 by scott.feldman@intel.com.  Based loosely on
+ *	original e100 driver, but better described as a munging of
+ *	e100, e1000, eepro100, tg3, 8139cp, and other drivers.
+ *
+ *	References:
+ *		Intel 8255x 10/100 Mbps Ethernet Controller Family,
+ *		Open Source Software Developers Manual,
+ *		http://sourceforge.net/projects/e1000
+ *
+ *
+ *	                      Theory of Operation
+ *
+ *	I.   General
+ *
+ *	The driver supports Intel(R) 10/100 Mbps PCI Fast Ethernet
+ *	controller family, which includes the 82557, 82558, 82559, 82550,
+ *	82551, and 82562 devices.  82558 and greater controllers
+ *	integrate the Intel 82555 PHY.  The controllers are used in
+ *	server and client network interface cards, as well as in
+ *	LAN-On-Motherboard (LOM), CardBus, MiniPCI, and ICHx
+ *	configurations.  8255x supports a 32-bit linear addressing
+ *	mode and operates at 33Mhz PCI clock rate.
+ *
+ *	II.  Driver Operation
+ *
+ *	Memory-mapped mode is used exclusively to access the device's
+ *	shared-memory structure, the Control/Status Registers (CSR). All
+ *	setup, configuration, and control of the device, including queuing
+ *	of Tx, Rx, and configuration commands is through the CSR.
+ *	cmd_lock serializes accesses to the CSR command register.  cb_lock
+ *	protects the shared Command Block List (CBL).
+ *
+ *	8255x is highly MII-compliant and all access to the PHY go
+ *	through the Management Data Interface (MDI).  Consequently, the
+ *	driver leverages the mii.c library shared with other MII-compliant
+ *	devices.
+ *
+ *	Big- and Little-Endian byte order as well as 32- and 64-bit
+ *	archs are supported.  Weak-ordered memory and non-cache-coherent
+ *	archs are supported.
+ *
+ *	III. Transmit
+ *
+ *	A Tx skb is mapped and hangs off of a TCB.  TCBs are linked
+ *	together in a fixed-size ring (CBL) thus forming the flexible mode
+ *	memory structure.  A TCB marked with the suspend-bit indicates
+ *	the end of the ring.  The last TCB processed suspends the
+ *	controller, and the controller can be restarted by issue a CU
+ *	resume command to continue from the suspend point, or a CU start
+ *	command to start at a given position in the ring.
+ *
+ *	Non-Tx commands (config, multicast setup, etc) are linked
+ *	into the CBL ring along with Tx commands.  The common structure
+ *	used for both Tx and non-Tx commands is the Command Block (CB).
+ *
+ *	cb_to_use is the next CB to use for queuing a command; cb_to_clean
+ *	is the next CB to check for completion; cb_to_send is the first
+ *	CB to start on in case of a previous failure to resume.  CB clean
+ *	up happens in interrupt context in response to a CU interrupt, or
+ *	in dev->poll in the case where NAPI is enabled.  cbs_avail keeps
+ *	track of number of free CB resources available.
+ *
+ * 	Hardware padding of short packets to minimum packet size is
+ * 	enabled.  82557 pads with 7Eh, while the later controllers pad
+ * 	with 00h.
+ *
+ *	IV.  Recieve
+ *
+ *	The Receive Frame Area (RFA) comprises a ring of Receive Frame
+ *	Descriptors (RFD) + data buffer, thus forming the simplified mode
+ *	memory structure.  Rx skbs are allocated to contain both the RFD
+ *	and the data buffer, but the RFD is pulled off before the skb is
+ *	indicated.  The data buffer is aligned such that encapsulated
+ *	protocol headers are u32-aligned.  Since the RFD is part of the
+ *	mapped shared memory, and completion status is contained within
+ *	the RFD, the RFD must be dma_sync'ed to maintain a consistent
+ *	view from software and hardware.
+ *
+ *	Under typical operation, the  receive unit (RU) is start once,
+ *	and the controller happily fills RFDs as frames arrive.  If
+ *	replacement RFDs cannot be allocated, or the RU goes non-active,
+ *	the RU must be restarted.  Frame arrival generates an interrupt,
+ *	and Rx indication and re-allocation happen in the same context,
+ *	therefore no locking is required.  If NAPI is enabled, this work
+ *	happens in dev->poll.  A software-generated interrupt is gen-
+ *	erated from the watchdog to recover from a failed allocation
+ *	senario where all Rx resources have been indicated and none re-
+ *	placed.
+ *
+ *	V.   Miscellaneous
+ *
+ * 	VLAN offloading of tagging, stripping and filtering is not
+ * 	supported, but driver will accommodate the extra 4-byte VLAN tag
+ * 	for processing by upper layers.  Tx/Rx Checksum offloading is not
+ * 	supported.  Tx Scatter/Gather is not supported.  Jumbo Frames is
+ * 	not supported (hardware limitation).
+ *
+ * 	NAPI support is enabled with CONFIG_E100_NAPI.
+ *
+ * 	MagicPacket(tm) WoL support is enabled/disabled via ethtool.
+ *
+ * 	Thanks to JC (jchapman@katalix.com) for helping with
+ * 	testing/troubleshooting the development driver.
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/mii.h>
+#include <linux/if_vlan.h>
+#include <linux/skbuff.h>
+#include <linux/ethtool.h>
+#include <linux/string.h>
+#include <asm/unaligned.h>
+
+
+#define DRV_NAME		"e100"
+#define DRV_VERSION		"3.0.13_dev"
+#define DRV_DESCRIPTION		"Intel(R) PRO/100 Network Driver"
+#define DRV_COPYRIGHT		"Copyright(c) 1999-2004 Intel Corporation"
+#define PFX			DRV_NAME ": "
+
+#define E100_WATCHDOG_PERIOD	2 * HZ
+#define E100_NAPI_WEIGHT	16
+
+MODULE_DESCRIPTION(DRV_DESCRIPTION);
+MODULE_AUTHOR(DRV_COPYRIGHT);
+MODULE_LICENSE("GPL");
+
+static int debug = 3;
+module_param(debug, int, 0);
+MODULE_PARM_DESC(debug, "Debug level (0=none,...,16=all)");
+#define DPRINTK(nlevel, klevel, fmt, args...) \
+	(void)((NETIF_MSG_##nlevel & nic->msg_enable) && \
+	printk(KERN_##klevel PFX "%s: %s: " fmt, nic->netdev->name, \
+		__FUNCTION__ , ## args))
+
+#define INTEL_8255X_ETHERNET_DEVICE(device_id, ich) {\
+	PCI_VENDOR_ID_INTEL, device_id, PCI_ANY_ID, PCI_ANY_ID, \
+	PCI_CLASS_NETWORK_ETHERNET << 8, 0xFFFF00, ich }
+static struct pci_device_id e100_id_table[] = {
+	INTEL_8255X_ETHERNET_DEVICE(0x1029, 0),
+	INTEL_8255X_ETHERNET_DEVICE(0x1030, 0),
+	INTEL_8255X_ETHERNET_DEVICE(0x1031, 3),
+	INTEL_8255X_ETHERNET_DEVICE(0x1032, 3),
+	INTEL_8255X_ETHERNET_DEVICE(0x1033, 3),
+	INTEL_8255X_ETHERNET_DEVICE(0x1034, 3),
+	INTEL_8255X_ETHERNET_DEVICE(0x1038, 3),
+	INTEL_8255X_ETHERNET_DEVICE(0x1039, 4),
+	INTEL_8255X_ETHERNET_DEVICE(0x103A, 4),
+	INTEL_8255X_ETHERNET_DEVICE(0x103B, 4),
+	INTEL_8255X_ETHERNET_DEVICE(0x103C, 4),
+	INTEL_8255X_ETHERNET_DEVICE(0x103D, 4),
+	INTEL_8255X_ETHERNET_DEVICE(0x103E, 4),
+	INTEL_8255X_ETHERNET_DEVICE(0x1050, 5),
+	INTEL_8255X_ETHERNET_DEVICE(0x1051, 5),
+	INTEL_8255X_ETHERNET_DEVICE(0x1052, 5),
+	INTEL_8255X_ETHERNET_DEVICE(0x1053, 5),
+	INTEL_8255X_ETHERNET_DEVICE(0x1054, 5),
+	INTEL_8255X_ETHERNET_DEVICE(0x1055, 5),
+	INTEL_8255X_ETHERNET_DEVICE(0x1064, 6),
+	INTEL_8255X_ETHERNET_DEVICE(0x1065, 6),
+	INTEL_8255X_ETHERNET_DEVICE(0x1066, 6),
+	INTEL_8255X_ETHERNET_DEVICE(0x1067, 6),
+	INTEL_8255X_ETHERNET_DEVICE(0x1068, 6),
+	INTEL_8255X_ETHERNET_DEVICE(0x1069, 6),
+	INTEL_8255X_ETHERNET_DEVICE(0x106A, 6),
+	INTEL_8255X_ETHERNET_DEVICE(0x106B, 6),
+	INTEL_8255X_ETHERNET_DEVICE(0x1059, 0),
+	INTEL_8255X_ETHERNET_DEVICE(0x1209, 0),
+	INTEL_8255X_ETHERNET_DEVICE(0x1229, 0),
+	INTEL_8255X_ETHERNET_DEVICE(0x2449, 2),
+	INTEL_8255X_ETHERNET_DEVICE(0x2459, 2),
+	INTEL_8255X_ETHERNET_DEVICE(0x245D, 2),
+	{ 0, }
+};
+MODULE_DEVICE_TABLE(pci, e100_id_table);
+
+enum mac {
+	mac_82557_D100_A  = 0,
+	mac_82557_D100_B  = 1,
+	mac_82557_D100_C  = 2,
+	mac_82558_D101_A4 = 4,
+	mac_82558_D101_B0 = 5,
+	mac_82559_D101M   = 8,
+	mac_82559_D101S   = 9,
+	mac_82550_D102    = 12,
+	mac_82550_D102_C  = 13,
+	mac_82551_E       = 14,
+	mac_82551_F       = 15,
+	mac_82551_10      = 16,
+	mac_unknown       = 0xFF,
+};
+
+enum phy {
+	phy_100a     = 0x000003E0,
+	phy_100c     = 0x035002A8,
+	phy_82555_tx = 0x015002A8,
+	phy_nsc_tx   = 0x5C002000,
+	phy_82562_et = 0x033002A8,
+	phy_82562_em = 0x032002A8,
+	phy_82562_eh = 0x017002A8,
+	phy_unknown  = 0xFFFFFFFF,
+};
+
+/* CSR (Control/Status Registers) */
+struct csr {
+	struct {
+		u8 status;
+		u8 stat_ack;
+		u8 cmd_lo;
+		u8 cmd_hi;
+		u32 gen_ptr;
+	} scb;
+	u32 port;
+	u16 flash_ctrl;
+	u8 eeprom_ctrl_lo;
+	u8 eeprom_ctrl_hi;
+	u32 mdi_ctrl;
+	u32 rx_dma_count;
+};
+
+enum scb_status {
+	rus_ready        = 0x10,
+	rus_mask         = 0x3C,
+};
+
+enum scb_stat_ack {
+	stat_ack_not_ours    = 0x00,
+	stat_ack_sw_gen      = 0x04,
+	stat_ack_rnr         = 0x10,
+	stat_ack_cu_idle     = 0x20,
+	stat_ack_frame_rx    = 0x40,
+	stat_ack_cu_cmd_done = 0x80,
+	stat_ack_not_present = 0xFF,
+	stat_ack_rx = (stat_ack_sw_gen | stat_ack_rnr | stat_ack_frame_rx),
+	stat_ack_tx = (stat_ack_cu_idle | stat_ack_cu_cmd_done),
+};
+
+enum scb_cmd_hi {
+	irq_mask_none = 0x00,
+	irq_mask_all  = 0x01,
+	irq_sw_gen    = 0x02,
+};
+
+enum scb_cmd_lo {
+	ruc_start      = 0x01,
+	ruc_load_base  = 0x06,
+	cuc_start      = 0x10,
+	cuc_resume     = 0x20,
+	cuc_dump_addr  = 0x40,
+	cuc_dump_stats = 0x50,
+	cuc_load_base  = 0x60,
+	cuc_dump_reset = 0x70,
+};
+
+enum port {
+	software_reset  = 0x0000,
+	selftest        = 0x0001,
+	selective_reset = 0x0002,
+};
+
+enum eeprom_ctrl_lo {
+	eesk = 0x01,
+	eecs = 0x02,
+	eedi = 0x04,
+	eedo = 0x08,
+};
+
+enum mdi_ctrl {
+	mdi_write = 0x04000000,
+	mdi_read  = 0x08000000,
+	mdi_ready = 0x10000000,
+};
+
+enum eeprom_op {
+	op_write = 0x05,
+	op_read  = 0x06,
+	op_ewds  = 0x10,
+	op_ewen  = 0x13,
+};
+
+enum eeprom_offsets {
+	eeprom_id         = 0x0A,
+	eeprom_config_asf = 0x0D,
+	eeprom_smbus_addr = 0x90,
+};
+
+enum eeprom_id {
+	eeprom_id_wol = 0x0020,
+};
+
+enum eeprom_config_asf {
+	eeprom_asf = 0x8000,
+	eeprom_gcl = 0x4000,
+};
+
+enum cb_status {
+	cb_complete = 0x8000,
+	cb_ok       = 0x2000,
+};
+
+enum cb_command {
+	cb_iaaddr = 0x0001,
+	cb_config = 0x0002,
+	cb_multi  = 0x0003,
+	cb_tx     = 0x0004,
+	cb_dump   = 0x0006,
+	cb_tx_sf  = 0x0008,
+	cb_cid    = 0x1f00,
+	cb_i      = 0x2000,
+	cb_s      = 0x4000,
+	cb_el     = 0x8000,
+};
+
+struct rfd {
+	u16 status;
+	u16 command;
+	u32 link;
+	u32 rbd;
+	u16 actual_size;
+	u16 size;
+};
+
+struct rx {
+	struct rx *next, *prev;
+	struct sk_buff *skb;
+	dma_addr_t dma_addr;
+};
+
+#if defined(__BIG_ENDIAN_BITFIELD)
+#define X(a,b)	b,a
+#else
+#define X(a,b)	a,b
+#endif
+struct config {
+/*0*/	u8 X(byte_count:6, pad0:2);
+/*1*/	u8 X(X(rx_fifo_limit:4, tx_fifo_limit:3), pad1:1);
+/*2*/	u8 adaptive_ifs;
+/*3*/	u8 X(X(X(X(mwi_enable:1, type_enable:1), read_align_enable:1),
+	   term_write_cache_line:1), pad3:4);
+/*4*/	u8 X(rx_dma_max_count:7, pad4:1);
+/*5*/	u8 X(tx_dma_max_count:7, dma_max_count_enable:1);
+/*6*/	u8 X(X(X(X(X(X(X(late_scb_update:1, direct_rx_dma:1),
+	   tno_intr:1), cna_intr:1), standard_tcb:1), standard_stat_counter:1),
+	   rx_discard_overruns:1), rx_save_bad_frames:1);
+/*7*/	u8 X(X(X(X(X(rx_discard_short_frames:1, tx_underrun_retry:2),
+	   pad7:2), rx_extended_rfd:1), tx_two_frames_in_fifo:1),
+	   tx_dynamic_tbd:1);
+/*8*/	u8 X(X(mii_mode:1, pad8:6), csma_disabled:1);
+/*9*/	u8 X(X(X(X(X(rx_tcpudp_checksum:1, pad9:3), vlan_arp_tco:1),
+	   link_status_wake:1), arp_wake:1), mcmatch_wake:1);
+/*10*/	u8 X(X(X(pad10:3, no_source_addr_insertion:1), preamble_length:2),
+	   loopback:2);
+/*11*/	u8 X(linear_priority:3, pad11:5);
+/*12*/	u8 X(X(linear_priority_mode:1, pad12:3), ifs:4);
+/*13*/	u8 ip_addr_lo;
+/*14*/	u8 ip_addr_hi;
+/*15*/	u8 X(X(X(X(X(X(X(promiscuous_mode:1, broadcast_disabled:1),
+	   wait_after_win:1), pad15_1:1), ignore_ul_bit:1), crc_16_bit:1),
+	   pad15_2:1), crs_or_cdt:1);
+/*16*/	u8 fc_delay_lo;
+/*17*/	u8 fc_delay_hi;
+/*18*/	u8 X(X(X(X(X(rx_stripping:1, tx_padding:1), rx_crc_transfer:1),
+	   rx_long_ok:1), fc_priority_threshold:3), pad18:1);
+/*19*/	u8 X(X(X(X(X(X(X(addr_wake:1, magic_packet_disable:1),
+	   fc_disable:1), fc_restop:1), fc_restart:1), fc_reject:1),
+	   full_duplex_force:1), full_duplex_pin:1);
+/*20*/	u8 X(X(X(pad20_1:5, fc_priority_location:1), multi_ia:1), pad20_2:1);
+/*21*/	u8 X(X(pad21_1:3, multicast_all:1), pad21_2:4);
+/*22*/	u8 X(X(rx_d102_mode:1, rx_vlan_drop:1), pad22:6);
+	u8 pad_d102[9];
+};
+
+#define E100_MAX_MULTICAST_ADDRS	64
+struct multi {
+	u16 count;
+	u8 addr[E100_MAX_MULTICAST_ADDRS * ETH_ALEN + 2/*pad*/];
+};
+
+/* Important: keep total struct u32-aligned */
+struct cb {
+	u16 status;
+	u16 command;
+	u32 link;
+	union {
+		u8 iaaddr[ETH_ALEN];
+		struct config config;
+		struct multi multi;
+		struct {
+			u32 tbd_array;
+			u16 tcb_byte_count;
+			u8 threshold;
+			u8 tbd_count;
+			struct {
+				u32 buf_addr;
+				u16 size;
+				u16 eol;
+			} tbd;
+		} tcb;
+		u32 dump_buffer_addr;
+	} u;
+	struct cb *next, *prev;
+	dma_addr_t dma_addr;
+	struct sk_buff *skb;
+};
+
+enum loopback {
+	lb_none = 0, lb_mac = 1, lb_phy = 3,
+};
+
+struct stats {
+	u32 tx_good_frames, tx_max_collisions, tx_late_collisions,
+		tx_underruns, tx_lost_crs, tx_deferred, tx_single_collisions,
+		tx_multiple_collisions, tx_total_collisions;
+	u32 rx_good_frames, rx_crc_errors, rx_alignment_errors,
+		rx_resource_errors, rx_overrun_errors, rx_cdt_errors,
+		rx_short_frame_errors;
+	u32 fc_xmt_pause, fc_rcv_pause, fc_rcv_unsupported;
+	u16 xmt_tco_frames, rcv_tco_frames;
+	u32 complete;
+};
+
+struct mem {
+	struct {
+		u32 signature;
+		u32 result;
+	} selftest;
+	struct stats stats;
+	u8 dump_buf[596];
+};
+
+struct param_range {
+	u32 min;
+	u32 max;
+	u32 count;
+};
+
+struct params {
+	struct param_range rfds;
+	struct param_range cbs;
+};
+
+struct nic {
+	/* Begin: frequently used values: keep adjacent for cache effect */
+	u32 msg_enable				____cacheline_aligned;
+	struct net_device *netdev;
+	struct pci_dev *pdev;
+
+	struct rx *rxs				____cacheline_aligned;
+	struct rx *rx_to_use;
+	struct rx *rx_to_clean;
+	struct rfd blank_rfd;
+	int ru_running;
+
+	spinlock_t cb_lock			____cacheline_aligned;
+	spinlock_t cmd_lock;
+	struct csr *csr;
+	enum scb_cmd_lo cuc_cmd;
+	unsigned int cbs_avail;
+	struct cb *cbs;
+	struct cb *cb_to_use;
+	struct cb *cb_to_send;
+	struct cb *cb_to_clean;
+	u16 tx_command;
+	/* End: frequently used values: keep adjacent for cache effect */
+
+	enum {
+		ich           = (1 << 0),
+		promiscuous   = (1 << 1),
+		multicast_all = (1 << 2),
+		wol_magic     = (1 << 3),
+	} flags					____cacheline_aligned;
+
+	enum mac mac;
+	enum phy phy;
+	struct params params;
+	struct net_device_stats net_stats;
+	struct timer_list watchdog;
+	struct timer_list blink_timer;
+	struct mii_if_info mii;
+	enum loopback loopback;
+
+	struct mem *mem;
+	dma_addr_t dma_addr;
+
+	dma_addr_t cbs_dma_addr;
+	u8 adaptive_ifs;
+	u8 tx_threshold;
+	u32 tx_frames;
+	u32 tx_collisions;
+	u32 tx_deferred;
+	u32 tx_single_collisions;
+	u32 tx_multiple_collisions;
+	u32 tx_fc_pause;
+	u32 tx_tco_frames;
+
+	u32 rx_fc_pause;
+	u32 rx_fc_unsupported;
+	u32 rx_tco_frames;
+
+	u8 rev_id;
+	u16 leds;
+	u16 eeprom_wc;
+	u16 eeprom[256];
+	u32 pm_state[16];
+};
+
+static inline void e100_write_flush(struct nic *nic)
+{
+	/* Flush previous PCI writes through intermediate bridges
+	 * by doing a benign read */
+	(void)readb(&nic->csr->scb.status);
+}
+
+static inline void e100_enable_irq(struct nic *nic)
+{
+	writeb(irq_mask_none, &nic->csr->scb.cmd_hi);
+	e100_write_flush(nic);
+}
+
+static inline void e100_disable_irq(struct nic *nic)
+{
+	writeb(irq_mask_all, &nic->csr->scb.cmd_hi);
+	e100_write_flush(nic);
+}
+
+static void e100_hw_reset(struct nic *nic)
+{
+	/* Put CU and RU into idle with a selective reset to get
+	 * device off of PCI bus */
+	writel(selective_reset, &nic->csr->port);
+	e100_write_flush(nic); udelay(20);
+
+	/* Now fully reset device */
+	writel(software_reset, &nic->csr->port);
+	e100_write_flush(nic); udelay(20);
+
+	/* TCO workaround - 82559 and greater */
+	if(nic->mac >= mac_82559_D101M) {
+		/* Issue a redundant CU load base without setting
+		 * general pointer, and without waiting for scb to
+		 * clear.  This gets us into post-driver.  Finally,
+		 * wait 20 msec for reset to take effect. */
+		writeb(cuc_load_base, &nic->csr->scb.cmd_lo);
+		mdelay(20);
+	}
+
+	/* Mask off our interrupt line - it's unmasked after reset */
+	e100_disable_irq(nic);
+}
+
+static int e100_self_test(struct nic *nic)
+{
+	u32 dma_addr = nic->dma_addr + offsetof(struct mem, selftest);
+
+	/* Passing the self-test is a pretty good indication
+	 * that the device can DMA to/from host memory */
+
+	nic->mem->selftest.signature = 0;
+	nic->mem->selftest.result = 0xFFFFFFFF;
+
+	writel(selftest | dma_addr, &nic->csr->port);
+	e100_write_flush(nic);
+	/* Wait 10 msec for self-test to complete */
+	set_current_state(TASK_UNINTERRUPTIBLE);
+	schedule_timeout(HZ / 100 + 1);
+
+	/* Interrupts are enabled after self-test */
+	e100_disable_irq(nic);
+
+	/* Check results of self-test */
+	if(nic->mem->selftest.result != 0) {
+		DPRINTK(HW, ERR, "Self-test failed: result=0x%08X\n",
+			nic->mem->selftest.result);
+		return -ETIMEDOUT;
+	}
+	if(nic->mem->selftest.signature == 0) {
+		DPRINTK(HW, ERR, "Self-test failed: timed out\n");
+		return -ETIMEDOUT;
+	}
+
+	return 0;
+}
+
+static void e100_eeprom_write(struct nic *nic, u16 addr_len, u16 addr, u16 data)
+{
+	u32 cmd_addr_data[3];
+	u8 ctrl;
+	int i, j;
+
+	/* Three cmds: write/erase enable, write data, write/erase disable */
+	cmd_addr_data[0] = op_ewen << (addr_len - 2);
+	cmd_addr_data[1] = (((op_write << addr_len) | addr) << 16) | data;
+	cmd_addr_data[2] = op_ewds << (addr_len - 2);
+
+	/* Bit-bang cmds to write word to eeprom */
+	for(j = 0; j < 3; j++) {
+
+		/* Chip select */
+		writeb(eecs | eesk, &nic->csr->eeprom_ctrl_lo);
+		e100_write_flush(nic); udelay(4);
+
+		for(i = 31; i >= 0; i--) {
+			ctrl = (cmd_addr_data[j] & (1 << i)) ?
+				eecs | eedi : eecs;
+			writeb(ctrl, &nic->csr->eeprom_ctrl_lo);
+			e100_write_flush(nic); udelay(4);
+			writeb(ctrl | eesk, &nic->csr->eeprom_ctrl_lo);
+			e100_write_flush(nic); udelay(4);
+		}
+		/* Wait 10 msec for cmd to complete */
+		set_current_state(TASK_UNINTERRUPTIBLE);
+		schedule_timeout(HZ / 100 + 1);
+
+		/* Chip deselect */
+		writeb(0, &nic->csr->eeprom_ctrl_lo);
+		e100_write_flush(nic); udelay(4);
+	}
+
+};
+
+/* General technique stolen from the eepro100 driver - very clever */
+static u16 e100_eeprom_read(struct nic *nic, u16 *addr_len, u16 addr)
+{
+	u32 cmd_addr_data;
+	u16 data = 0;
+	u8 ctrl;
+	int i;
+
+	cmd_addr_data = ((op_read << *addr_len) | addr) << 16;
+
+	/* Chip select */
+	writeb(eecs | eesk, &nic->csr->eeprom_ctrl_lo);
+	e100_write_flush(nic); udelay(4);
+
+	/* Bit-bang to read word from eeprom */
+	for(i = 31; i >= 0; i--) {
+		ctrl = (cmd_addr_data & (1 << i)) ? eecs | eedi : eecs;
+		writeb(ctrl, &nic->csr->eeprom_ctrl_lo);
+		e100_write_flush(nic); udelay(4);
+		writeb(ctrl | eesk, &nic->csr->eeprom_ctrl_lo);
+		e100_write_flush(nic); udelay(4);
+		/* Eeprom drives a dummy zero to EEDO after receiving
+		 * complete address.  Use this to adjust addr_len. */
+		ctrl = readb(&nic->csr->eeprom_ctrl_lo);
+		if(!(ctrl & eedo) && i > 16) {
+			*addr_len -= (i - 16);
+			i = 17;
+		}
+		data = (data << 1) | (ctrl & eedo ? 1 : 0);
+	}
+
+	/* Chip deselect */
+	writeb(0, &nic->csr->eeprom_ctrl_lo);
+	e100_write_flush(nic); udelay(4);
+
+	return data;
+};
+
+/* Load entire EEPROM image into driver cache and validate checksum */
+static int e100_eeprom_load(struct nic *nic)
+{
+	u16 addr, addr_len = 8, checksum = 0;
+
+	/* Try reading with an 8-bit addr len to discover actual addr len */
+	e100_eeprom_read(nic, &addr_len, 0);
+	nic->eeprom_wc = 1 << addr_len;
+
+	for(addr = 0; addr < nic->eeprom_wc; addr++) {
+		nic->eeprom[addr] = e100_eeprom_read(nic, &addr_len, addr);
+		if(addr < nic->eeprom_wc - 1)
+			checksum += nic->eeprom[addr];
+	}
+
+	/* The checksum, stored in the last word, is calculated such that
+	 * the sum of words should be 0xBABA */
+	checksum = 0xBABA - checksum;
+	if(checksum != nic->eeprom[nic->eeprom_wc - 1]) {
+		DPRINTK(PROBE, ERR, "EEPROM corrupted\n");
+		return -EAGAIN;
+	}
+
+	return 0;
+}
+
+/* Save (portion of) driver EEPROM cache to device and update checksum */
+static int e100_eeprom_save(struct nic *nic, u16 start, u16 count)
+{
+	u16 addr, addr_len = 8, checksum = 0;
+
+	/* Try reading with an 8-bit addr len to discover actual addr len */
+	e100_eeprom_read(nic, &addr_len, 0);
+	nic->eeprom_wc = 1 << addr_len;
+
+	if(start + count >= nic->eeprom_wc)
+		return -EINVAL;
+
+	for(addr = start; addr < start + count; addr++)
+		e100_eeprom_write(nic, addr_len, addr, nic->eeprom[addr]);
+
+	/* The checksum, stored in the last word, is calculated such that
+	 * the sum of words should be 0xBABA */
+	for(addr = 0; addr < nic->eeprom_wc - 1; addr++)
+		checksum += nic->eeprom[addr];
+	nic->eeprom[nic->eeprom_wc - 1] = 0xBABA - checksum;
+	e100_eeprom_write(nic, addr_len, nic->eeprom_wc - 1, 0xBABA - checksum);
+
+	return 0;
+}
+
+#define E100_WAIT_SCB_TIMEOUT 40
+static inline int e100_exec_cmd(struct nic *nic, u8 cmd, dma_addr_t dma_addr)
+{
+	unsigned long flags;
+	unsigned int i;
+	int err = 0;
+
+	spin_lock_irqsave(&nic->cmd_lock, flags);
+
+	/* Previous command is accepted when SCB clears */
+	for(i = 0; i < E100_WAIT_SCB_TIMEOUT; i++) {
+		if(likely(!readb(&nic->csr->scb.cmd_lo)))
+			break;
+		cpu_relax();
+		if(unlikely(i > (E100_WAIT_SCB_TIMEOUT >> 1)))
+			udelay(5);
+	}
+	if(unlikely(i == E100_WAIT_SCB_TIMEOUT)) {
+		err = -EAGAIN;
+		goto err_unlock;
+	}
+
+	if(unlikely(cmd != cuc_resume))
+		writel(dma_addr, &nic->csr->scb.gen_ptr);
+	writeb(cmd, &nic->csr->scb.cmd_lo);
+
+err_unlock:
+	spin_unlock_irqrestore(&nic->cmd_lock, flags);
+
+	return err;
+}
+
+static inline int e100_exec_cb(struct nic *nic, struct sk_buff *skb,
+	void (*cb_prepare)(struct nic *, struct cb *, struct sk_buff *))
+{
+	struct cb *cb;
+	unsigned long flags;
+	int err = 0;
+
+	spin_lock_irqsave(&nic->cb_lock, flags);
+
+	if(unlikely(!nic->cbs_avail)) {
+		err = -ENOMEM;
+		goto err_unlock;
+	}
+
+	cb = nic->cb_to_use;
+	nic->cb_to_use = cb->next;
+	nic->cbs_avail--;
+	cb->skb = skb;
+
+	if(unlikely(!nic->cbs_avail))
+		err = -ENOSPC;
+
+	cb_prepare(nic, cb, skb);
+
+	/* Order is important otherwise we'll be in a race with h/w:
+	 * set S-bit in current first, then clear S-bit in previous. */
+	cb->command |= cpu_to_le16(cb_s);
+	cb->prev->command &= cpu_to_le16(~cb_s);
+
+	while(nic->cb_to_send != nic->cb_to_use) {
+		if(unlikely((err = e100_exec_cmd(nic, nic->cuc_cmd,
+			nic->cb_to_send->dma_addr)))) {
+			/* Ok, here's where things get sticky.  It's
+			 * possible that we can't schedule the command
+			 * because the controller is too busy, so
+			 * let's just queue the command and try again
+			 * when another command is scheduled. */
+			break;
+		} else {
+			nic->cuc_cmd = cuc_resume;
+			nic->cb_to_send = nic->cb_to_send->next;
+		}
+	}
+
+err_unlock:
+	spin_unlock_irqrestore(&nic->cb_lock, flags);
+
+	return err;
+}
+
+static u16 mdio_ctrl(struct nic *nic, u32 addr, u32 dir, u32 reg, u16 data)
+{
+	u32 data_out = 0;
+	unsigned int i;
+
+	writel((reg << 16) | (addr << 21) | dir | data, &nic->csr->mdi_ctrl);
+
+	for(i = 0; i < 100; i++) {
+		udelay(20);
+		if((data_out = readl(&nic->csr->mdi_ctrl)) & mdi_ready)
+			break;
+	}
+
+	DPRINTK(HW, DEBUG,
+		"%s:addr=%d, reg=%d, data_in=0x%04X, data_out=0x%04X\n",
+		dir == mdi_read ? "READ" : "WRITE", addr, reg, data, data_out);
+	return (u16)data_out;
+}
+
+static int mdio_read(struct net_device *netdev, int addr, int reg)
+{
+	return mdio_ctrl(netdev->priv, addr, mdi_read, reg, 0);
+}
+
+static void mdio_write(struct net_device *netdev, int addr, int reg, int data)
+{
+	mdio_ctrl(netdev->priv, addr, mdi_write, reg, data);
+}
+
+static void e100_get_defaults(struct nic *nic)
+{
+	struct param_range rfds = { .min = 64, .max = 256, .count = 64 };
+	struct param_range cbs  = { .min = 64, .max = 256, .count = 64 };
+
+	pci_read_config_byte(nic->pdev, PCI_REVISION_ID, &nic->rev_id);
+	/* MAC type is encoded as rev ID; exception: ICH is treated as 82559 */
+	nic->mac = (nic->flags & ich) ? mac_82559_D101M : nic->rev_id;
+	if(nic->mac == mac_unknown)
+		nic->mac = mac_82557_D100_A;
+
+	nic->params.rfds = rfds;
+	nic->params.cbs = cbs;
+
+	/* Quadwords to DMA into FIFO before starting frame transmit */
+	nic->tx_threshold = 0xE0;
+
+	nic->tx_command = cpu_to_le16(cb_tx | cb_i | cb_tx_sf |
+		((nic->mac >= mac_82558_D101_A4) ? cb_cid : 0));
+
+	/* Template for a freshly allocated RFD */
+	nic->blank_rfd.command = cpu_to_le16(cb_el);
+	nic->blank_rfd.rbd = 0xFFFFFFFF;
+	nic->blank_rfd.size = cpu_to_le16(VLAN_ETH_FRAME_LEN);
+
+	/* MII setup */
+	nic->mii.phy_id_mask = 0x1F;
+	nic->mii.reg_num_mask = 0x1F;
+	nic->mii.dev = nic->netdev;
+	nic->mii.mdio_read = mdio_read;
+	nic->mii.mdio_write = mdio_write;
+}
+
+static void e100_configure(struct nic *nic, struct cb *cb, struct sk_buff *skb)
+{
+	struct config *config = &cb->u.config;
+	u8 *c = (u8 *)config;
+
+	cb->command = cpu_to_le16(cb_config);
+
+	memset(config, 0, sizeof(struct config));
+
+	config->byte_count = 0x16;		/* bytes in this struct */
+	config->rx_fifo_limit = 0x8;		/* bytes in FIFO before DMA */
+	config->direct_rx_dma = 0x1;		/* reserved */
+	config->standard_tcb = 0x1;		/* 1=standard, 0=extended */
+	config->standard_stat_counter = 0x1;	/* 1=standard, 0=extended */
+	config->rx_discard_short_frames = 0x1;	/* 1=discard, 0=pass */
+	config->tx_underrun_retry = 0x3;	/* # of underrun retries */
+	config->mii_mode = 0x1;			/* 1=MII mode, 0=503 mode */
+	config->pad10 = 0x6;
+	config->no_source_addr_insertion = 0x1;	/* 1=no, 0=yes */
+	config->preamble_length = 0x2;		/* 0=1, 1=3, 2=7, 3=15 bytes */
+	config->ifs = 0x6;			/* x16 = inter frame spacing */
+	config->ip_addr_hi = 0xF2;		/* ARP IP filter - not used */
+	config->pad15_1 = 0x1;
+	config->pad15_2 = 0x1;
+	config->crs_or_cdt = 0x0;		/* 0=CRS only, 1=CRS or CDT */
+	config->fc_delay_hi = 0x40;		/* time delay for fc frame */
+	config->tx_padding = 0x1;		/* 1=pad short frames */
+	config->fc_priority_threshold = 0x7;	/* 7=priority fc disabled */
+	config->pad18 = 0x1;
+	config->full_duplex_pin = 0x1;		/* 1=examine FDX# pin */
+	config->pad20_1 = 0x1F;
+	config->fc_priority_location = 0x1;	/* 1=byte#31, 0=byte#19 */
+	config->pad21_1 = 0x5;
+
+	config->adaptive_ifs = nic->adaptive_ifs;
+	config->loopback = nic->loopback;
+
+	if(nic->mii.force_media && nic->mii.full_duplex)
+		config->full_duplex_force = 0x1;	/* 1=force, 0=auto */
+
+	if(nic->flags & promiscuous || nic->loopback) {
+		config->rx_save_bad_frames = 0x1;	/* 1=save, 0=discard */
+		config->rx_discard_short_frames = 0x0;	/* 1=discard, 0=save */
+		config->promiscuous_mode = 0x1;		/* 1=on, 0=off */
+	}
+
+	if(nic->flags & multicast_all)
+		config->multicast_all = 0x1;		/* 1=accept, 0=no */
+
+	if(!(nic->flags & wol_magic))
+		config->magic_packet_disable = 0x1;	/* 1=off, 0=on */
+
+	if(nic->mac >= mac_82558_D101_A4) {
+		config->fc_disable = 0x1;	/* 1=Tx fc off, 0=Tx fc on */
+		config->mwi_enable = 0x1;	/* 1=enable, 0=disable */
+		config->standard_tcb = 0x0;	/* 1=standard, 0=extended */
+		config->rx_long_ok = 0x1;	/* 1=VLANs ok, 0=standard */
+		if(nic->mac >= mac_82559_D101M)
+			config->tno_intr = 0x1;		/* TCO stats enable */
+		else
+			config->standard_stat_counter = 0x0;
+	}
+
+	DPRINTK(HW, DEBUG, "[00-07]=%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X\n",
+		c[0], c[1], c[2], c[3], c[4], c[5], c[6], c[7]);
+	DPRINTK(HW, DEBUG, "[08-15]=%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X\n",
+		c[8], c[9], c[10], c[11], c[12], c[13], c[14], c[15]);
+	DPRINTK(HW, DEBUG, "[16-23]=%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X\n",
+		c[16], c[17], c[18], c[19], c[20], c[21], c[22], c[23]);
+}
+
+static void e100_setup_iaaddr(struct nic *nic, struct cb *cb,
+	struct sk_buff *skb)
+{
+	cb->command = cpu_to_le16(cb_iaaddr);
+	memcpy(cb->u.iaaddr, nic->netdev->dev_addr, ETH_ALEN);
+}
+
+static void e100_dump(struct nic *nic, struct cb *cb, struct sk_buff *skb)
+{
+	cb->command = cpu_to_le16(cb_dump);
+	cb->u.dump_buffer_addr = cpu_to_le32(nic->dma_addr +
+		offsetof(struct mem, dump_buf));
+}
+
+#define NCONFIG_AUTO_SWITCH	0x0080
+#define MII_NSC_CONG		MII_RESV1
+#define NSC_CONG_ENABLE		0x0100
+#define NSC_CONG_TXREADY	0x0400
+#define ADVERTISE_FC_SUPPORTED	0x0400
+static int e100_phy_init(struct nic *nic)
+{
+	struct net_device *netdev = nic->netdev;
+	u32 addr;
+	u16 bmcr, stat, id_lo, id_hi, cong;
+
+	/* Discover phy addr by searching addrs in order {1,0,2,..., 31} */
+	for(addr = 0; addr < 32; addr++) {
+		nic->mii.phy_id = (addr == 0) ? 1 : (addr == 1) ? 0 : addr;
+		bmcr = mdio_read(netdev, nic->mii.phy_id, MII_BMCR);
+		stat = mdio_read(netdev, nic->mii.phy_id, MII_BMSR);
+		stat = mdio_read(netdev, nic->mii.phy_id, MII_BMSR);
+		if(!((bmcr == 0xFFFF) || ((stat == 0) && (bmcr == 0))))
+			break;
+	}
+	DPRINTK(HW, DEBUG, "phy_addr = %d\n", nic->mii.phy_id);
+	if(addr == 32)
+		return -EAGAIN;
+
+	/* Selected the phy and isolate the rest */
+	for(addr = 0; addr < 32; addr++) {
+		if(addr != nic->mii.phy_id) {
+			mdio_write(netdev, addr, MII_BMCR, BMCR_ISOLATE);
+		} else {
+			bmcr = mdio_read(netdev, addr, MII_BMCR);
+			mdio_write(netdev, addr, MII_BMCR,
+				bmcr & ~BMCR_ISOLATE);
+		}
+	}
+
+	/* Get phy ID */
+	id_lo = mdio_read(netdev, nic->mii.phy_id, MII_PHYSID1);
+	id_hi = mdio_read(netdev, nic->mii.phy_id, MII_PHYSID2);
+	nic->phy = (u32)id_hi << 16 | (u32)id_lo;
+	DPRINTK(HW, DEBUG, "phy ID = 0x%08X\n", nic->phy);
+
+	/* Handle National tx phy */
+	if(nic->phy == phy_nsc_tx) {
+		/* Disable congestion control */
+		cong = mdio_read(netdev, nic->mii.phy_id, MII_NSC_CONG);
+		cong |= NSC_CONG_TXREADY;
+		cong &= ~NSC_CONG_ENABLE;
+		mdio_write(netdev, nic->mii.phy_id, MII_NSC_CONG, cong);
+	}
+
+	if(nic->mac >= mac_82550_D102)
+		/* enable/disable MDI/MDI-X auto-switching */
+		mdio_write(netdev, nic->mii.phy_id, MII_NCONFIG,
+			nic->mii.force_media ? 0 : NCONFIG_AUTO_SWITCH);
+
+	return 0;
+}
+
+static int e100_hw_init(struct nic *nic)
+{
+	int err;
+
+	e100_hw_reset(nic);
+
+	DPRINTK(HW, ERR, "e100_hw_init\n");
+	if(!in_interrupt() && (err = e100_self_test(nic)))
+		return err;
+
+	if((err = e100_phy_init(nic)))
+		return err;
+	if((err = e100_exec_cmd(nic, cuc_load_base, 0)))
+		return err;
+	if((err = e100_exec_cmd(nic, ruc_load_base, 0)))
+		return err;
+	if((err = e100_exec_cb(nic, NULL, e100_configure)))
+		return err;
+	if((err = e100_exec_cb(nic, NULL, e100_setup_iaaddr)))
+		return err;
+	if((err = e100_exec_cmd(nic, cuc_dump_addr,
+		nic->dma_addr + offsetof(struct mem, stats))))
+		return err;
+	if((err = e100_exec_cmd(nic, cuc_dump_reset, 0)))
+		return err;
+
+	e100_disable_irq(nic);
+
+	return 0;
+}
+
+static void e100_multi(struct nic *nic, struct cb *cb, struct sk_buff *skb)
+{
+	struct net_device *netdev = nic->netdev;
+	struct dev_mc_list *list = netdev->mc_list;
+	u16 i, count = min(netdev->mc_count, E100_MAX_MULTICAST_ADDRS);
+
+	cb->command = cpu_to_le16(cb_multi);
+	cb->u.multi.count = cpu_to_le16(count * ETH_ALEN);
+	for(i = 0; list && i < count; i++, list = list->next)
+		memcpy(&cb->u.multi.addr[i*ETH_ALEN], &list->dmi_addr,
+			ETH_ALEN);
+}
+
+static void e100_set_multicast_list(struct net_device *netdev)
+{
+	struct nic *nic = netdev->priv;
+
+	DPRINTK(HW, DEBUG, "mc_count=%d, flags=0x%04X\n",
+		netdev->mc_count, netdev->flags);
+
+	if(netdev->flags & IFF_PROMISC)
+		nic->flags |= promiscuous;
+	else
+		nic->flags &= ~promiscuous;
+
+	if(netdev->flags & IFF_ALLMULTI ||
+		netdev->mc_count > E100_MAX_MULTICAST_ADDRS)
+		nic->flags |= multicast_all;
+	else
+		nic->flags &= ~multicast_all;
+
+	e100_exec_cb(nic, NULL, e100_configure);
+	e100_exec_cb(nic, NULL, e100_multi);
+}
+
+static void e100_update_stats(struct nic *nic)
+{
+	struct net_device_stats *ns = &nic->net_stats;
+	struct stats *s = &nic->mem->stats;
+	u32 *complete = (nic->mac < mac_82558_D101_A4) ? &s->fc_xmt_pause :
+		(nic->mac < mac_82559_D101M) ? (u32 *)&s->xmt_tco_frames :
+		&s->complete;
+
+	/* Device's stats reporting may take several microseconds to
+	 * complete, so where always waiting for results of the
+	 * previous command. */
+
+	if(*complete == le32_to_cpu(0x0000A007)) {
+		*complete = 0;
+		nic->tx_frames = le32_to_cpu(s->tx_good_frames);
+		nic->tx_collisions = le32_to_cpu(s->tx_total_collisions);
+		ns->tx_aborted_errors += le32_to_cpu(s->tx_max_collisions);
+		ns->tx_window_errors += le32_to_cpu(s->tx_late_collisions);
+		ns->tx_carrier_errors += le32_to_cpu(s->tx_lost_crs);
+		ns->tx_fifo_errors += le32_to_cpu(s->tx_underruns);
+		ns->collisions += nic->tx_collisions;
+		ns->tx_errors += le32_to_cpu(s->tx_max_collisions) +
+			le32_to_cpu(s->tx_lost_crs);
+		ns->rx_dropped += le32_to_cpu(s->rx_resource_errors);
+		ns->rx_length_errors += le32_to_cpu(s->rx_short_frame_errors);
+		ns->rx_over_errors += le32_to_cpu(s->rx_resource_errors);
+		ns->rx_crc_errors += le32_to_cpu(s->rx_crc_errors);
+		ns->rx_frame_errors += le32_to_cpu(s->rx_alignment_errors);
+		ns->rx_fifo_errors += le32_to_cpu(s->rx_overrun_errors);
+		ns->rx_errors += le32_to_cpu(s->rx_crc_errors) +
+			le32_to_cpu(s->rx_alignment_errors) +
+			le32_to_cpu(s->rx_short_frame_errors) +
+			le32_to_cpu(s->rx_cdt_errors);
+		nic->tx_deferred += le32_to_cpu(s->tx_deferred);
+		nic->tx_single_collisions +=
+			le32_to_cpu(s->tx_single_collisions);
+		nic->tx_multiple_collisions +=
+			le32_to_cpu(s->tx_multiple_collisions);
+		if(nic->mac >= mac_82558_D101_A4) {
+			nic->tx_fc_pause += le32_to_cpu(s->fc_xmt_pause);
+			nic->rx_fc_pause += le32_to_cpu(s->fc_rcv_pause);
+			nic->rx_fc_unsupported +=
+				le32_to_cpu(s->fc_rcv_unsupported);
+			if(nic->mac >= mac_82559_D101M) {
+				nic->tx_tco_frames +=
+					le16_to_cpu(s->xmt_tco_frames);
+				nic->rx_tco_frames +=
+					le16_to_cpu(s->rcv_tco_frames);
+			}
+		}
+	}
+
+	e100_exec_cmd(nic, cuc_dump_reset, 0);
+}
+
+static void e100_adjust_adaptive_ifs(struct nic *nic, int speed, int duplex)
+{
+	/* Adjust inter-frame-spacing (IFS) between two transmits if
+	 * we're getting collisions on a half-duplex connection. */
+
+	if(duplex == DUPLEX_HALF) {
+		u32 prev = nic->adaptive_ifs;
+		u32 min_frames = (speed == SPEED_100) ? 1000 : 100;
+
+		if((nic->tx_frames / 32 < nic->tx_collisions) &&
+		   (nic->tx_frames > min_frames)) {
+			if(nic->adaptive_ifs < 60)
+				nic->adaptive_ifs += 5;
+		} else if (nic->tx_frames < min_frames) {
+			if(nic->adaptive_ifs >= 5)
+				nic->adaptive_ifs -= 5;
+		}
+		if(nic->adaptive_ifs != prev)
+			e100_exec_cb(nic, NULL, e100_configure);
+	}
+}
+
+static void e100_watchdog(unsigned long data)
+{
+	struct nic *nic = (struct nic *)data;
+	struct ethtool_cmd cmd;
+
+	DPRINTK(TIMER, DEBUG, "right now = %ld\n", jiffies);
+
+	/* mii library handles link maintenance tasks */
+
+	mii_ethtool_gset(&nic->mii, &cmd);
+
+	if(mii_link_ok(&nic->mii) && !netif_carrier_ok(nic->netdev)) {
+		DPRINTK(LINK, INFO, "link up, %sMbps, %s-duplex\n",
+			cmd.speed == SPEED_100 ? "100" : "10",
+			cmd.duplex == DUPLEX_FULL ? "full" : "half");
+	} else if(!mii_link_ok(&nic->mii) && netif_carrier_ok(nic->netdev)) {
+		DPRINTK(LINK, INFO, "link down\n");
+	}
+
+	mii_check_link(&nic->mii);
+
+	/* Software generated interrupt to recover from (rare) Rx
+	 * allocation failure */
+	writeb(irq_sw_gen, &nic->csr->scb.cmd_hi);
+	e100_write_flush(nic);
+
+	e100_update_stats(nic);
+	e100_adjust_adaptive_ifs(nic, cmd.speed, cmd.duplex);
+
+	if(nic->mac <= mac_82557_D100_C)
+		/* Issue a multicast command to workaround a 557 lock up */
+		e100_set_multicast_list(nic->netdev);
+
+	mod_timer(&nic->watchdog, jiffies + E100_WATCHDOG_PERIOD);
+}
+
+static inline void e100_xmit_prepare(struct nic *nic, struct cb *cb,
+	struct sk_buff *skb)
+{
+	cb->command = nic->tx_command;
+	cb->u.tcb.tbd_array = cb->dma_addr + offsetof(struct cb, u.tcb.tbd);
+	cb->u.tcb.tcb_byte_count = 0;
+	cb->u.tcb.threshold = nic->tx_threshold;
+	cb->u.tcb.tbd_count = 1;
+	cb->u.tcb.tbd.buf_addr = cpu_to_le32(pci_map_single(nic->pdev,
+		skb->data, skb->len, PCI_DMA_TODEVICE));
+	cb->u.tcb.tbd.size = cpu_to_le16(skb->len);
+}
+
+static int e100_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
+{
+	struct nic *nic = netdev->priv;
+	int err = e100_exec_cb(nic, skb, e100_xmit_prepare);
+
+	switch(err) {
+	case -ENOSPC:
+		/* We queued the skb, but now we're out of space. */
+		netif_stop_queue(netdev);
+		break;
+	case -ENOMEM:
+		/* This is a hard error - log it. */
+		DPRINTK(TX_ERR, DEBUG, "Out of Tx resources, returning skb\n");
+		netif_stop_queue(netdev);
+		return 1;
+	}
+
+	netdev->trans_start = jiffies;
+	return 0;
+}
+
+static inline int e100_tx_clean(struct nic *nic)
+{
+	struct cb *cb;
+	int tx_cleaned = 0;
+
+	spin_lock(&nic->cb_lock);
+
+	DPRINTK(TX_DONE, DEBUG, "cb->status = 0x%04X\n",
+		nic->cb_to_clean->status);
+
+	/* Clean CBs marked complete */
+	for(cb = nic->cb_to_clean;
+	    cb->status & cpu_to_le16(cb_complete);
+	    cb = nic->cb_to_clean = cb->next) {
+		if(likely(cb->skb)) {
+			nic->net_stats.tx_packets++;
+			nic->net_stats.tx_bytes += cb->skb->len;
+
+			pci_unmap_single(nic->pdev,
+				le32_to_cpu(cb->u.tcb.tbd.buf_addr),
+				le16_to_cpu(cb->u.tcb.tbd.size),
+				PCI_DMA_TODEVICE);
+			dev_kfree_skb_any(cb->skb);
+			tx_cleaned = 1;
+		}
+		cb->status = 0;
+		nic->cbs_avail++;
+	}
+
+	spin_unlock(&nic->cb_lock);
+
+	/* Recover from running out of Tx resources in xmit_frame */
+	if(unlikely(tx_cleaned && netif_queue_stopped(nic->netdev)))
+		netif_wake_queue(nic->netdev);
+
+	return tx_cleaned;
+}
+
+static void e100_clean_cbs(struct nic *nic)
+{
+	if(nic->cbs) {
+		while(nic->cb_to_clean != nic->cb_to_use) {
+			struct cb *cb = nic->cb_to_clean;
+			if(cb->skb) {
+				pci_unmap_single(nic->pdev,
+					le32_to_cpu(cb->u.tcb.tbd.buf_addr),
+					le16_to_cpu(cb->u.tcb.tbd.size),
+					PCI_DMA_TODEVICE);
+				dev_kfree_skb(cb->skb);
+			}
+			nic->cb_to_clean = nic->cb_to_clean->next;
+		}
+		nic->cbs_avail = nic->params.cbs.count;
+		pci_free_consistent(nic->pdev,
+			sizeof(struct cb) * nic->params.cbs.count,
+			nic->cbs, nic->cbs_dma_addr);
+		nic->cbs = NULL;
+		nic->cbs_avail = 0;
+	}
+	nic->cuc_cmd = cuc_start;
+	nic->cb_to_use = nic->cb_to_send = nic->cb_to_clean =
+		nic->cbs;
+}
+
+static int e100_alloc_cbs(struct nic *nic)
+{
+	struct cb *cb;
+	unsigned int i, count = nic->params.cbs.count;
+
+	nic->cuc_cmd = cuc_start;
+	nic->cb_to_use = nic->cb_to_send = nic->cb_to_clean = NULL;
+	nic->cbs_avail = 0;
+
+	nic->cbs = pci_alloc_consistent(nic->pdev,
+		sizeof(struct cb) * count, &nic->cbs_dma_addr);
+	if(!nic->cbs)
+		return -ENOMEM;
+
+	for(cb = nic->cbs, i = 0; i < count; cb++, i++) {
+		cb->next = (i + 1 < count) ? cb + 1 : nic->cbs;
+		cb->prev = (i == 0) ? nic->cbs + count - 1 : cb - 1;
+
+		cb->dma_addr = nic->cbs_dma_addr + i * sizeof(struct cb);
+		cb->link = cpu_to_le32(nic->cbs_dma_addr +
+			((i+1) % count) * sizeof(struct cb));
+	}
+
+	nic->cb_to_use = nic->cb_to_send = nic->cb_to_clean = nic->cbs;
+	nic->cbs_avail = count;
+
+	return 0;
+}
+
+static inline void e100_start_receiver(struct nic *nic)
+{
+	/* (Re)start RU if suspended or idle and RFA is non-NULL */
+	if(!nic->ru_running && nic->rx_to_clean->skb) {
+		e100_exec_cmd(nic, ruc_start, nic->rx_to_clean->dma_addr);
+		nic->ru_running = 1;
+	}
+}
+
+#define RFD_BUF_LEN (sizeof(struct rfd) + VLAN_ETH_FRAME_LEN)
+static inline int e100_rx_alloc_skb(struct nic *nic, struct rx *rx)
+{
+	unsigned int rx_offset = 2; /* u32 align protocol headers */
+
+	if(!(rx->skb = dev_alloc_skb(RFD_BUF_LEN + rx_offset)))
+		return -ENOMEM;
+
+	/* Align, init, and map the RFA. */
+	rx->skb->dev = nic->netdev;
+	skb_reserve(rx->skb, rx_offset);
+	memcpy(rx->skb->data, &nic->blank_rfd, sizeof(struct rfd));
+	rx->dma_addr = pci_map_single(nic->pdev, rx->skb->data,
+		RFD_BUF_LEN, PCI_DMA_FROMDEVICE);
+
+	/* Link the RFD to end of RFA by linking previous RFD to
+	 * this one, and clearing EL bit of previous.  */
+	if(rx->prev->skb) {
+		struct rfd *prev_rfd = (struct rfd *)rx->prev->skb->data;
+		put_unaligned(cpu_to_le32(rx->dma_addr),
+			(u32 *)&prev_rfd->link);
+		prev_rfd->command &= ~cpu_to_le16(cb_el);
+		pci_dma_sync_single(nic->pdev, rx->prev->dma_addr,
+			sizeof(struct rfd), PCI_DMA_TODEVICE);
+	}
+
+	return 0;
+}
+
+static inline int e100_rx_indicate(struct nic *nic, struct rx *rx,
+	unsigned int *work_done, unsigned int work_to_do)
+{
+	struct sk_buff *skb = rx->skb;
+	struct rfd *rfd = (struct rfd *)skb->data;
+	u16 rfd_status, actual_size;
+
+	if(unlikely(work_done && *work_done >= work_to_do))
+		return -EAGAIN;
+
+	/* Need to sync before taking a peek at cb_complete bit */
+	pci_dma_sync_single(nic->pdev, rx->dma_addr,
+		sizeof(struct rfd), PCI_DMA_FROMDEVICE);
+	rfd_status = le16_to_cpu(rfd->status);
+
+	DPRINTK(RX_STATUS, DEBUG, "status=0x%04X\n", rfd_status);
+
+	/* If data isn't ready, nothing to indicate */
+	if(unlikely(!(rfd_status & cb_complete)))
+       		return -EAGAIN;
+
+	/* Get actual data size */
+	actual_size = le16_to_cpu(rfd->actual_size) & 0x3FFF;
+	if(unlikely(actual_size > RFD_BUF_LEN - sizeof(struct rfd)))
+		actual_size = RFD_BUF_LEN - sizeof(struct rfd);
+
+	/* Get data */
+	pci_dma_sync_single(nic->pdev, rx->dma_addr,
+		sizeof(struct rfd) + actual_size,
+		PCI_DMA_FROMDEVICE);
+	pci_unmap_single(nic->pdev, rx->dma_addr,
+		RFD_BUF_LEN, PCI_DMA_FROMDEVICE);
+
+	/* Pull off the RFD and put the actual data (minus eth hdr) */
+	skb_reserve(skb, sizeof(struct rfd));
+	skb_put(skb, actual_size);
+	skb->protocol = eth_type_trans(skb, nic->netdev);
+
+	if(unlikely(!(rfd_status & cb_ok)) ||
+	   actual_size > nic->netdev->mtu + VLAN_ETH_HLEN) {
+		/* Don't indicate if errors */
+		dev_kfree_skb_any(skb);
+	} else {
+		nic->net_stats.rx_packets++;
+		nic->net_stats.rx_bytes += actual_size;
+		nic->netdev->last_rx = jiffies;
+#ifdef CONFIG_E100_NAPI
+		netif_receive_skb(skb);
+#else
+		netif_rx(skb);
+#endif
+		if(work_done)
+			(*work_done)++;
+	}
+
+	rx->skb = NULL;
+
+	return 0;
+}
+
+static inline void e100_rx_clean(struct nic *nic, unsigned int *work_done,
+	unsigned int work_to_do)
+{
+	struct rx *rx;
+
+	/* Indicate newly arrived packets */
+	for(rx = nic->rx_to_clean; rx->skb; rx = nic->rx_to_clean = rx->next) {
+		if(e100_rx_indicate(nic, rx, work_done, work_to_do))
+			break; /* No more to clean */
+	}
+
+	/* Alloc new skbs to refill list */
+	for(rx = nic->rx_to_use; !rx->skb; rx = nic->rx_to_use = rx->next) {
+		if(unlikely(e100_rx_alloc_skb(nic, rx)))
+			break; /* Better luck next time (see watchdog) */
+	}
+
+	e100_start_receiver(nic);
+}
+
+static void e100_rx_clean_list(struct nic *nic)
+{
+	struct rx *rx;
+	unsigned int i, count = nic->params.rfds.count;
+
+	if(nic->rxs) {
+		for(rx = nic->rxs, i = 0; i < count; rx++, i++) {
+			if(rx->skb) {
+				pci_unmap_single(nic->pdev, rx->dma_addr,
+					RFD_BUF_LEN, PCI_DMA_FROMDEVICE);
+				dev_kfree_skb(rx->skb);
+			}
+		}
+		kfree(nic->rxs);
+		nic->rxs = NULL;
+	}
+
+	nic->rx_to_use = nic->rx_to_clean = NULL;
+	nic->ru_running = 0;
+}
+
+static int e100_rx_alloc_list(struct nic *nic)
+{
+	struct rx *rx;
+	unsigned int i, count = nic->params.rfds.count;
+
+	nic->rx_to_use = nic->rx_to_clean = NULL;
+
+	if(!(nic->rxs = kmalloc(sizeof(struct rx) * count, GFP_ATOMIC)))
+		return -ENOMEM;
+	memset(nic->rxs, 0, sizeof(struct rx) * count);
+
+	for(rx = nic->rxs, i = 0; i < count; rx++, i++) {
+		rx->next = (i + 1 < count) ? rx + 1 : nic->rxs;
+		rx->prev = (i == 0) ? nic->rxs + count - 1 : rx - 1;
+		if(e100_rx_alloc_skb(nic, rx)) {
+			e100_rx_clean_list(nic);
+			return -ENOMEM;
+		}
+	}
+
+	nic->rx_to_use = nic->rx_to_clean = nic->rxs;
+
+	return 0;
+}
+
+static irqreturn_t e100_intr(int irq, void *dev_id, struct pt_regs *regs)
+{
+	struct net_device *netdev = dev_id;
+	struct nic *nic = netdev->priv;
+	u8 stat_ack = readb(&nic->csr->scb.stat_ack);
+
+	DPRINTK(INTR, DEBUG, "stat_ack = 0x%02X\n", stat_ack);
+
+	if(stat_ack == stat_ack_not_ours ||	/* Not our interrupt */
+	   stat_ack == stat_ack_not_present)	/* Hardware is ejected */
+		return IRQ_NONE;
+
+	/* Ack interrupt(s) */
+	writeb(stat_ack, &nic->csr->scb.stat_ack);
+
+	/* We hit Receive No Resource (RNR); restart RU after cleaning */
+	if(stat_ack & stat_ack_rnr)
+		nic->ru_running = 0;
+
+#ifdef CONFIG_E100_NAPI
+	e100_disable_irq(nic);
+	netif_rx_schedule(netdev);
+#else
+	if(stat_ack & stat_ack_rx)
+		e100_rx_clean(nic, NULL, 0);
+	if(stat_ack & stat_ack_tx)
+		e100_tx_clean(nic);
+#endif
+
+	return IRQ_HANDLED;
+}
+
+#ifdef CONFIG_E100_NAPI
+static int e100_poll(struct net_device *netdev, int *budget)
+{
+	struct nic *nic = netdev->priv;
+	unsigned int work_to_do = min(netdev->quota, *budget);
+	unsigned int work_done = 0;
+	int tx_cleaned;
+
+	e100_rx_clean(nic, &work_done, work_to_do);
+	tx_cleaned = e100_tx_clean(nic);
+
+	/* If no Rx and Tx cleanup work was done, exit polling mode. */
+	if((!tx_cleaned && (work_done == 0)) || !netif_running(netdev)) {
+		netif_rx_complete(netdev);
+		e100_enable_irq(nic);
+		return 0;
+	}
+
+	*budget -= work_done;
+	netdev->quota -= work_done;
+
+	return 1;
+}
+#endif
+
+#ifdef CONFIG_NET_POLL_CONTROLLER
+static void e100_netpoll(struct net_device *netdev)
+{
+	struct nic *nic = netdev->priv;
+	e100_disable_irq(nic);
+	e100_intr(nic->pdev->irq, netdev, NULL);
+	e100_enable_irq(nic);
+}
+#endif
+
+static struct net_device_stats *e100_get_stats(struct net_device *netdev)
+{
+	struct nic *nic = netdev->priv;
+	return &nic->net_stats;
+}
+
+static int e100_set_mac_address(struct net_device *netdev, void *p)
+{
+	struct nic *nic = netdev->priv;
+	struct sockaddr *addr = p;
+
+	if (!is_valid_ether_addr(addr->sa_data))
+		return -EADDRNOTAVAIL;
+
+	memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len);
+	e100_exec_cb(nic, NULL, e100_setup_iaaddr);
+
+	return 0;
+}
+
+static int e100_change_mtu(struct net_device *netdev, int new_mtu)
+{
+	if(new_mtu < ETH_ZLEN || new_mtu > ETH_DATA_LEN)
+		return -EINVAL;
+	netdev->mtu = new_mtu;
+	return 0;
+}
+
+static int e100_asf(struct nic *nic)
+{
+	/* ASF can be enabled from eeprom */
+	return((nic->pdev->device >= 0x1050) && (nic->pdev->device <= 0x1055) &&
+	   (nic->eeprom[eeprom_config_asf] & eeprom_asf) &&
+	   !(nic->eeprom[eeprom_config_asf] & eeprom_gcl) &&
+	   ((nic->eeprom[eeprom_smbus_addr] & 0xFF) != 0xFE));
+}
+
+static int e100_up(struct nic *nic)
+{
+	int err;
+
+	if((err = e100_rx_alloc_list(nic)))
+		return err;
+	if((err = e100_alloc_cbs(nic)))
+		goto err_rx_clean_list;
+	if((err = e100_hw_init(nic)))
+		goto err_clean_cbs;
+	e100_set_multicast_list(nic->netdev);
+	e100_start_receiver(nic);
+	netif_start_queue(nic->netdev);
+	mod_timer(&nic->watchdog, jiffies);
+	if((err = request_irq(nic->pdev->irq, e100_intr, SA_SHIRQ,
+		nic->netdev->name, nic->netdev)))
+		goto err_no_irq;
+	e100_enable_irq(nic);
+	return 0;
+
+err_no_irq:
+	del_timer_sync(&nic->watchdog);
+	netif_stop_queue(nic->netdev);
+err_clean_cbs:
+	e100_clean_cbs(nic);
+err_rx_clean_list:
+	e100_rx_clean_list(nic);
+	return err;
+}
+
+static void e100_down(struct nic *nic)
+{
+	e100_hw_reset(nic);
+	free_irq(nic->pdev->irq, nic->netdev);
+	del_timer_sync(&nic->watchdog);
+	netif_carrier_off(nic->netdev);
+	netif_stop_queue(nic->netdev);
+	e100_clean_cbs(nic);
+	e100_rx_clean_list(nic);
+}
+
+static void e100_tx_timeout(struct net_device *netdev)
+{
+	struct nic *nic = netdev->priv;
+
+	DPRINTK(TX_ERR, DEBUG, "scb.status=0x%02X\n",
+		readb(&nic->csr->scb.status));
+	e100_down(netdev->priv);
+	e100_up(netdev->priv);
+}
+
+static int e100_loopback_test(struct nic *nic, enum loopback loopback_mode)
+{
+	int err;
+	struct sk_buff *skb;
+
+	/* Use driver resources to perform internal MAC or PHY
+	 * loopback test.  A single packet is prepared and transmitted
+	 * in loopback mode, and the test passes if the received
+	 * packet compares byte-for-byte to the transmitted packet. */
+
+	if((err = e100_rx_alloc_list(nic)))
+		return err;
+	if((err = e100_alloc_cbs(nic)))
+		goto err_clean_rx;
+
+	/* ICH PHY loopback is broken so do MAC loopback instead */
+	if(nic->flags & ich && loopback_mode == lb_phy)
+		loopback_mode = lb_mac;
+
+	nic->loopback = loopback_mode;
+	if((err = e100_hw_init(nic)))
+		goto err_loopback_none;
+
+	if(loopback_mode == lb_phy)
+		mdio_write(nic->netdev, nic->mii.phy_id, MII_BMCR,
+			BMCR_LOOPBACK);
+
+	e100_start_receiver(nic);
+
+	if(!(skb = dev_alloc_skb(ETH_DATA_LEN))) {
+		err = -ENOMEM;
+		goto err_loopback_none;
+	}
+	skb_put(skb, ETH_DATA_LEN);
+	memset(skb->data, 0xFF, ETH_DATA_LEN);
+	e100_xmit_frame(skb, nic->netdev);
+
+	set_current_state(TASK_UNINTERRUPTIBLE);
+	schedule_timeout(HZ / 100 + 1);
+
+	if(memcmp(nic->rx_to_clean->skb->data + sizeof(struct rfd),
+	   skb->data, ETH_DATA_LEN))
+       		err = -EAGAIN;
+
+err_loopback_none:
+	mdio_write(nic->netdev, nic->mii.phy_id, MII_BMCR, 0);
+	nic->loopback = lb_none;
+	e100_hw_init(nic);
+	e100_clean_cbs(nic);
+err_clean_rx:
+	e100_rx_clean_list(nic);
+	return err;
+}
+
+#define MII_LED_CONTROL	0x1B
+static void e100_blink_led(unsigned long data)
+{
+	struct nic *nic = (struct nic *)data;
+	enum led_state {
+		led_on     = 0x01,
+		led_off    = 0x04,
+		led_on_559 = 0x05,
+		led_on_557 = 0x07,
+	};
+
+	nic->leds = (nic->leds & led_on) ? led_off :
+		(nic->mac < mac_82559_D101M) ? led_on_557 : led_on_559;
+	mdio_write(nic->netdev, nic->mii.phy_id, MII_LED_CONTROL, nic->leds);
+	mod_timer(&nic->blink_timer, jiffies + HZ / 4);
+}
+
+static int e100_get_settings(struct net_device *netdev, struct ethtool_cmd *cmd)
+{
+	struct nic *nic = netdev->priv;
+	return mii_ethtool_gset(&nic->mii, cmd);
+}
+
+static int e100_set_settings(struct net_device *netdev, struct ethtool_cmd *cmd)
+{
+	struct nic *nic = netdev->priv;
+	int err;
+
+	mdio_write(netdev, nic->mii.phy_id, MII_BMCR, BMCR_RESET);
+	err = mii_ethtool_sset(&nic->mii, cmd);
+	e100_exec_cb(nic, NULL, e100_configure);
+
+	return err;
+}
+
+static void e100_get_drvinfo(struct net_device *netdev,
+	struct ethtool_drvinfo *info)
+{
+	struct nic *nic = netdev->priv;
+	strcpy(info->driver, DRV_NAME);
+	strcpy(info->version, DRV_VERSION);
+	strcpy(info->fw_version, "N/A");
+	strcpy(info->bus_info, pci_name(nic->pdev));
+}
+
+static int e100_get_regs_len(struct net_device *netdev)
+{
+	struct nic *nic = netdev->priv;
+#define E100_PHY_REGS		0x1C
+#define E100_REGS_LEN		1 + E100_PHY_REGS + \
+	sizeof(nic->mem->dump_buf) / sizeof(u32)
+	return E100_REGS_LEN * sizeof(u32);
+}
+
+static void e100_get_regs(struct net_device *netdev,
+	struct ethtool_regs *regs, void *p)
+{
+	struct nic *nic = netdev->priv;
+	u32 *buff = p;
+	int i;
+
+	regs->version = (1 << 24) | nic->rev_id;
+	buff[0] = readb(&nic->csr->scb.cmd_hi) << 24 |
+		readb(&nic->csr->scb.cmd_lo) << 16 |
+		readw(&nic->csr->scb.status);
+	for(i = E100_PHY_REGS; i >= 0; i--)
+		buff[1 + E100_PHY_REGS - i] =
+			mdio_read(netdev, nic->mii.phy_id, i);
+	memset(nic->mem->dump_buf, 0, sizeof(nic->mem->dump_buf));
+	e100_exec_cb(nic, NULL, e100_dump);
+	set_current_state(TASK_UNINTERRUPTIBLE);
+	schedule_timeout(HZ / 100 + 1);
+	memcpy(&buff[2 + E100_PHY_REGS], nic->mem->dump_buf,
+		sizeof(nic->mem->dump_buf));
+}
+
+static void e100_get_wol(struct net_device *netdev, struct ethtool_wolinfo *wol)
+{
+	struct nic *nic = netdev->priv;
+	wol->supported = (nic->mac >= mac_82558_D101_A4) ?  WAKE_MAGIC : 0;
+	wol->wolopts = (nic->flags & wol_magic) ? WAKE_MAGIC : 0;
+}
+
+static int e100_set_wol(struct net_device *netdev, struct ethtool_wolinfo *wol)
+{
+	struct nic *nic = netdev->priv;
+
+	if(wol->wolopts != WAKE_MAGIC && wol->wolopts != 0)
+		return -EOPNOTSUPP;
+
+	if(wol->wolopts)
+		nic->flags |= wol_magic;
+	else
+		nic->flags &= ~wol_magic;
+
+	pci_enable_wake(nic->pdev, 0, nic->flags & (wol_magic | e100_asf(nic)));
+	e100_exec_cb(nic, NULL, e100_configure);
+
+	return 0;
+}
+
+static u32 e100_get_msglevel(struct net_device *netdev)
+{
+	struct nic *nic = netdev->priv;
+	return nic->msg_enable;
+}
+
+static void e100_set_msglevel(struct net_device *netdev, u32 value)
+{
+	struct nic *nic = netdev->priv;
+	nic->msg_enable = value;
+}
+
+static int e100_nway_reset(struct net_device *netdev)
+{
+	struct nic *nic = netdev->priv;
+	return mii_nway_restart(&nic->mii);
+}
+
+static u32 e100_get_link(struct net_device *netdev)
+{
+	struct nic *nic = netdev->priv;
+	return mii_link_ok(&nic->mii);
+}
+
+static int e100_get_eeprom_len(struct net_device *netdev)
+{
+	struct nic *nic = netdev->priv;
+	return nic->eeprom_wc << 1;
+}
+
+#define E100_EEPROM_MAGIC	0x1234
+static int e100_get_eeprom(struct net_device *netdev,
+	struct ethtool_eeprom *eeprom, u8 *bytes)
+{
+	struct nic *nic = netdev->priv;
+
+	eeprom->magic = E100_EEPROM_MAGIC;
+	memcpy(bytes, &((u8 *)nic->eeprom)[eeprom->offset], eeprom->len);
+
+	return 0;
+}
+
+static int e100_set_eeprom(struct net_device *netdev,
+	struct ethtool_eeprom *eeprom, u8 *bytes)
+{
+	struct nic *nic = netdev->priv;
+
+	if(eeprom->magic != E100_EEPROM_MAGIC)
+		return -EINVAL;
+	memcpy(&((u8 *)nic->eeprom)[eeprom->offset], bytes, eeprom->len);
+
+	return e100_eeprom_save(nic, eeprom->offset >> 1,
+		(eeprom->len >> 1) + 1);
+}
+
+static void e100_get_ringparam(struct net_device *netdev,
+	struct ethtool_ringparam *ring)
+{
+	struct nic *nic = netdev->priv;
+	struct param_range *rfds = &nic->params.rfds;
+	struct param_range *cbs = &nic->params.cbs;
+
+	ring->rx_max_pending = rfds->max;
+	ring->tx_max_pending = cbs->max;
+	ring->rx_mini_max_pending = 0;
+	ring->rx_jumbo_max_pending = 0;
+	ring->rx_pending = rfds->count;
+	ring->tx_pending = cbs->count;
+	ring->rx_mini_pending = 0;
+	ring->rx_jumbo_pending = 0;
+}
+
+static int e100_set_ringparam(struct net_device *netdev,
+	struct ethtool_ringparam *ring)
+{
+	struct nic *nic = netdev->priv;
+	struct param_range *rfds = &nic->params.rfds;
+	struct param_range *cbs = &nic->params.cbs;
+
+	if(netif_running(netdev))
+		e100_down(nic);
+	rfds->count = max(ring->rx_pending, rfds->min);
+	rfds->count = min(rfds->count, rfds->max);
+	cbs->count = max(ring->tx_pending, cbs->min);
+	cbs->count = min(cbs->count, cbs->max);
+	if(netif_running(netdev))
+		e100_up(nic);
+
+	return 0;
+}
+
+static const char e100_gstrings_test[][ETH_GSTRING_LEN] = {
+	"Link test     (on/offline)",
+	"Eeprom test   (on/offline)",
+	"Self test        (offline)",
+	"Mac loopback     (offline)",
+	"Phy loopback     (offline)",
+};
+#define E100_TEST_LEN	sizeof(e100_gstrings_test) / ETH_GSTRING_LEN
+
+static int e100_diag_test_count(struct net_device *netdev)
+{
+	return E100_TEST_LEN;
+}
+
+static void e100_diag_test(struct net_device *netdev,
+	struct ethtool_test *test, u64 *data)
+{
+	struct nic *nic = netdev->priv;
+	int i;
+
+	memset(data, 0, E100_TEST_LEN * sizeof(u64));
+	data[0] = !mii_link_ok(&nic->mii);
+	data[1] = e100_eeprom_load(nic);
+	if(test->flags & ETH_TEST_FL_OFFLINE) {
+		if(netif_running(netdev))
+			e100_down(nic);
+		data[2] = e100_self_test(nic);
+		data[3] = e100_loopback_test(nic, lb_mac);
+		data[4] = e100_loopback_test(nic, lb_phy);
+		if(netif_running(netdev))
+			e100_up(nic);
+	}
+	for(i = 0; i < E100_TEST_LEN; i++)
+		test->flags |= data[i] ? ETH_TEST_FL_FAILED : 0;
+}
+
+static int e100_phys_id(struct net_device *netdev, u32 data)
+{
+	struct nic *nic = netdev->priv;
+
+	if(!data || data > (u32)(MAX_SCHEDULE_TIMEOUT / HZ))
+		data = (u32)(MAX_SCHEDULE_TIMEOUT / HZ);
+	mod_timer(&nic->blink_timer, jiffies);
+	set_current_state(TASK_INTERRUPTIBLE);
+	schedule_timeout(data * HZ);
+	del_timer_sync(&nic->blink_timer);
+	mdio_write(netdev, nic->mii.phy_id, MII_LED_CONTROL, 0);
+
+	return 0;
+}
+
+static const char e100_gstrings_stats[][ETH_GSTRING_LEN] = {
+	"rx_packets", "tx_packets", "rx_bytes", "tx_bytes", "rx_errors",
+	"tx_errors", "rx_dropped", "tx_dropped", "multicast", "collisions",
+	"rx_length_errors", "rx_over_errors", "rx_crc_errors",
+	"rx_frame_errors", "rx_fifo_errors", "rx_missed_errors",
+	"tx_aborted_errors", "tx_carrier_errors", "tx_fifo_errors",
+	"tx_heartbeat_errors", "tx_window_errors",
+	/* device-specific stats */
+	"tx_deferred", "tx_single_collisions", "tx_multi_collisions",
+	"tx_flow_control_pause", "rx_flow_control_pause",
+	"rx_flow_control_unsupported", "tx_tco_packets", "rx_tco_packets",
+};
+#define E100_NET_STATS_LEN	21
+#define E100_STATS_LEN	sizeof(e100_gstrings_stats) / ETH_GSTRING_LEN
+
+static int e100_get_stats_count(struct net_device *netdev)
+{
+	return E100_STATS_LEN;
+}
+
+static void e100_get_ethtool_stats(struct net_device *netdev,
+	struct ethtool_stats *stats, u64 *data)
+{
+	struct nic *nic = netdev->priv;
+	int i;
+
+	for(i = 0; i < E100_NET_STATS_LEN; i++)
+		data[i] = ((unsigned long *)&nic->net_stats)[i];
+
+	data[i++] = nic->tx_deferred;
+	data[i++] = nic->tx_single_collisions;
+	data[i++] = nic->tx_multiple_collisions;
+	data[i++] = nic->tx_fc_pause;
+	data[i++] = nic->rx_fc_pause;
+	data[i++] = nic->rx_fc_unsupported;
+	data[i++] = nic->tx_tco_frames;
+	data[i++] = nic->rx_tco_frames;
+}
+
+static void e100_get_strings(struct net_device *netdev, u32 stringset, u8 *data)
+{
+	switch(stringset) {
+	case ETH_SS_TEST:
+		memcpy(data, *e100_gstrings_test, sizeof(e100_gstrings_test));
+		break;
+	case ETH_SS_STATS:
+		memcpy(data, *e100_gstrings_stats, sizeof(e100_gstrings_stats));
+		break;
+	}
+}
+
+static struct ethtool_ops e100_ethtool_ops = {
+	.get_settings		= e100_get_settings,
+	.set_settings		= e100_set_settings,
+	.get_drvinfo		= e100_get_drvinfo,
+	.get_regs_len		= e100_get_regs_len,
+	.get_regs		= e100_get_regs,
+	.get_wol		= e100_get_wol,
+	.set_wol		= e100_set_wol,
+	.get_msglevel		= e100_get_msglevel,
+	.set_msglevel		= e100_set_msglevel,
+	.nway_reset		= e100_nway_reset,
+	.get_link		= e100_get_link,
+	.get_eeprom_len		= e100_get_eeprom_len,
+	.get_eeprom		= e100_get_eeprom,
+	.set_eeprom		= e100_set_eeprom,
+	.get_ringparam		= e100_get_ringparam,
+	.set_ringparam		= e100_set_ringparam,
+	.self_test_count	= e100_diag_test_count,
+	.self_test		= e100_diag_test,
+	.get_strings		= e100_get_strings,
+	.phys_id		= e100_phys_id,
+	.get_stats_count	= e100_get_stats_count,
+	.get_ethtool_stats	= e100_get_ethtool_stats,
+};
+
+static int e100_do_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
+{
+	struct nic *nic = netdev->priv;
+	struct mii_ioctl_data *mii = (struct mii_ioctl_data *)&ifr->ifr_data;
+
+	return generic_mii_ioctl(&nic->mii, mii, cmd, NULL);
+}
+
+static int e100_alloc(struct nic *nic)
+{
+	nic->mem = pci_alloc_consistent(nic->pdev, sizeof(struct mem),
+		&nic->dma_addr);
+	return nic->mem ? 0 : -ENOMEM;
+}
+
+static void e100_free(struct nic *nic)
+{
+	if(nic->mem) {
+		pci_free_consistent(nic->pdev, sizeof(struct mem),
+			nic->mem, nic->dma_addr);
+		nic->mem = NULL;
+	}
+}
+
+static int e100_open(struct net_device *netdev)
+{
+	struct nic *nic = netdev->priv;
+	int err = 0;
+
+	netif_carrier_off(netdev);
+	if((err = e100_up(nic)))
+		DPRINTK(IFUP, ERR, "Cannot open interface, aborting.\n");
+	return err;
+}
+
+static int e100_close(struct net_device *netdev)
+{
+	e100_down(netdev->priv);
+	return 0;
+}
+
+static int __devinit e100_probe(struct pci_dev *pdev,
+	const struct pci_device_id *ent)
+{
+	struct net_device *netdev;
+	struct nic *nic;
+	int err;
+
+	if(!(netdev = alloc_etherdev(sizeof(struct nic)))) {
+		if(((1 << debug) - 1) & NETIF_MSG_PROBE)
+			printk(KERN_ERR PFX "Etherdev alloc failed, abort.\n");
+		return -ENOMEM;
+	}
+
+	netdev->open = e100_open;
+	netdev->stop = e100_close;
+	netdev->hard_start_xmit = e100_xmit_frame;
+	netdev->get_stats = e100_get_stats;
+	netdev->set_multicast_list = e100_set_multicast_list;
+	netdev->set_mac_address = e100_set_mac_address;
+	netdev->change_mtu = e100_change_mtu;
+	netdev->do_ioctl = e100_do_ioctl;
+	SET_ETHTOOL_OPS(netdev, &e100_ethtool_ops);
+	netdev->tx_timeout = e100_tx_timeout;
+	netdev->watchdog_timeo = E100_WATCHDOG_PERIOD;
+#ifdef CONFIG_E100_NAPI
+	netdev->poll = e100_poll;
+	netdev->weight = E100_NAPI_WEIGHT;
+#endif
+#ifdef CONFIG_NET_POLL_CONTROLLER
+	netdev->poll_controller = e100_netpoll;
+#endif
+
+	nic = netdev->priv;
+	nic->netdev = netdev;
+	nic->pdev = pdev;
+	nic->msg_enable = (1 << debug) - 1;
+	pci_set_drvdata(pdev, netdev);
+
+	if((err = pci_enable_device(pdev))) {
+		DPRINTK(PROBE, ERR, "Cannot enable PCI device, aborting.\n");
+		goto err_out_free_dev;
+	}
+
+	if(!(pci_resource_flags(pdev, 0) & IORESOURCE_MEM)) {
+		DPRINTK(PROBE, ERR, "Cannot find proper PCI device "
+			"base address, aborting.\n");
+		err = -ENODEV;
+		goto err_out_disable_pdev;
+	}
+
+	if((err = pci_request_regions(pdev, DRV_NAME))) {
+		DPRINTK(PROBE, ERR, "Cannot obtain PCI resources, aborting.\n");
+		goto err_out_disable_pdev;
+	}
+
+	pci_set_master(pdev);
+
+	if((err = pci_set_dma_mask(pdev, 0xFFFFFFFFULL))) {
+		DPRINTK(PROBE, ERR, "No usable DMA configuration, aborting.\n");
+		goto err_out_free_res;
+	}
+
+	SET_MODULE_OWNER(netdev);
+	SET_NETDEV_DEV(netdev, &pdev->dev);
+
+	nic->csr = ioremap(pci_resource_start(pdev, 0), sizeof(struct csr));
+	if(!nic->csr) {
+		DPRINTK(PROBE, ERR, "Cannot map device registers, aborting.\n");
+		err = -ENOMEM;
+		goto err_out_free_res;
+	}
+
+	if(ent->driver_data)
+		nic->flags |= ich;
+	else
+		nic->flags &= ~ich;
+
+	spin_lock_init(&nic->cb_lock);
+	spin_lock_init(&nic->cmd_lock);
+
+	init_timer(&nic->watchdog);
+	nic->watchdog.function = e100_watchdog;
+	nic->watchdog.data = (unsigned long)nic;
+	init_timer(&nic->blink_timer);
+	nic->blink_timer.function = e100_blink_led;
+	nic->blink_timer.data = (unsigned long)nic;
+
+	if((err = e100_alloc(nic))) {
+		DPRINTK(PROBE, ERR, "Cannot alloc driver memory, aborting.\n");
+		goto err_out_iounmap;
+	}
+
+	e100_get_defaults(nic);
+	e100_hw_reset(nic);
+	e100_phy_init(nic);
+
+	if((err = e100_eeprom_load(nic)))
+		goto err_out_free;
+	((u16 *)netdev->dev_addr)[0] = le16_to_cpu(nic->eeprom[0]);
+	((u16 *)netdev->dev_addr)[1] = le16_to_cpu(nic->eeprom[1]);
+	((u16 *)netdev->dev_addr)[2] = le16_to_cpu(nic->eeprom[2]);
+	if(!is_valid_ether_addr(netdev->dev_addr)) {
+		DPRINTK(PROBE, ERR, "Invalid MAC address from "
+			"EEPROM, aborting.\n");
+		err = -EAGAIN;
+		goto err_out_free;
+	}
+
+	/* Wol magic packet can be enabled from eeprom */
+	if((nic->mac >= mac_82558_D101_A4) &&
+	   (nic->eeprom[eeprom_id] & eeprom_id_wol))
+		nic->flags |= wol_magic;
+
+	pci_enable_wake(pdev, 0, nic->flags & (wol_magic | e100_asf(nic)));
+
+	if((err = register_netdev(netdev))) {
+		DPRINTK(PROBE, ERR, "Cannot register net device, aborting.\n");
+		goto err_out_free;
+	}
+
+	DPRINTK(PROBE, INFO, "addr 0x%lx, irq %d, "
+		"MAC addr %02X:%02X:%02X:%02X:%02X:%02X\n",
+		pci_resource_start(pdev, 0), pdev->irq,
+		netdev->dev_addr[0], netdev->dev_addr[1], netdev->dev_addr[2],
+		netdev->dev_addr[3], netdev->dev_addr[4], netdev->dev_addr[5]);
+
+	return 0;
+
+err_out_free:
+	e100_free(nic);
+err_out_iounmap:
+	iounmap(nic->csr);
+err_out_free_res:
+	pci_release_regions(pdev);
+err_out_disable_pdev:
+	pci_disable_device(pdev);
+err_out_free_dev:
+	pci_set_drvdata(pdev, NULL);
+	free_netdev(netdev);
+	return err;
+}
+
+static void __devexit e100_remove(struct pci_dev *pdev)
+{
+	struct net_device *netdev = pci_get_drvdata(pdev);
+
+	if(netdev) {
+		struct nic *nic = netdev->priv;
+		unregister_netdev(netdev);
+		e100_free(nic);
+		iounmap(nic->csr);
+		free_netdev(netdev);
+		pci_release_regions(pdev);
+		pci_disable_device(pdev);
+		pci_set_drvdata(pdev, NULL);
+	}
+}
+
+#ifdef CONFIG_PM
+static int e100_suspend(struct pci_dev *pdev, u32 state)
+{
+	struct net_device *netdev = pci_get_drvdata(pdev);
+	struct nic *nic = netdev->priv;
+
+	if(netif_running(netdev))
+		e100_down(nic);
+	e100_hw_reset(nic);
+	netif_device_detach(netdev);
+
+	pci_save_state(pdev, nic->pm_state);
+	pci_enable_wake(pdev, state, nic->flags & (wol_magic | e100_asf(nic)));
+	pci_disable_device(pdev);
+	pci_set_power_state(pdev, state);
+
+	return 0;
+}
+
+static int e100_resume(struct pci_dev *pdev)
+{
+	struct net_device *netdev = pci_get_drvdata(pdev);
+	struct nic *nic = netdev->priv;
+
+	pci_set_power_state(pdev, 0);
+	pci_restore_state(pdev, nic->pm_state);
+	e100_hw_init(nic);
+
+	netif_device_attach(netdev);
+	if(netif_running(netdev))
+		e100_up(nic);
+
+	return 0;
+}
+#endif
+
+static struct pci_driver e100_driver = {
+	.name =         DRV_NAME,
+	.id_table =     e100_id_table,
+	.probe =        e100_probe,
+	.remove =       __devexit_p(e100_remove),
+#ifdef CONFIG_PM
+	.suspend =      e100_suspend,
+	.resume =       e100_resume,
+#endif
+};
+
+static int __init e100_init_module(void)
+{
+	if(((1 << debug) - 1) & NETIF_MSG_DRV) {
+		printk(KERN_INFO PFX "%s, %s\n", DRV_DESCRIPTION, DRV_VERSION);
+		printk(KERN_INFO PFX "%s\n", DRV_COPYRIGHT);
+	}
+        return pci_module_init(&e100_driver);
+}
+
+static void __exit e100_cleanup_module(void)
+{
+	pci_unregister_driver(&e100_driver);
+}
+
+module_init(e100_init_module);
+module_exit(e100_cleanup_module);
--- diff/drivers/net/irda/stir4200.c	1970-01-01 01:00:00.000000000 +0100
+++ source/drivers/net/irda/stir4200.c	2004-02-23 13:56:43.000000000 +0000
@@ -0,0 +1,1283 @@
+/*****************************************************************************
+*
+* Filename:      stir4200.c
+* Version:       0.4
+* Description:   Irda SigmaTel USB Dongle
+* Status:        Experimental
+* Author:        Stephen Hemminger <shemminger@osdl.org>
+*
+*  	Based on earlier driver by Paul Stewart <stewart@parc.com>
+*
+*	Copyright (C) 2000, Roman Weissgaerber <weissg@vienna.at>
+*	Copyright (C) 2001, Dag Brattli <dag@brattli.net>
+*	Copyright (C) 2001, Jean Tourrilhes <jt@hpl.hp.com>
+*	Copyright (C) 2004, Stephen Hemminger <shemminger@osdl.org>
+*
+*	This program is free software; you can redistribute it and/or modify
+*	it under the terms of the GNU General Public License as published by
+*	the Free Software Foundation; either version 2 of the License, or
+*	(at your option) any later version.
+*
+*	This program is distributed in the hope that it will be useful,
+*	but WITHOUT ANY WARRANTY; without even the implied warranty of
+*	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+*	GNU General Public License for more details.
+*
+*	You should have received a copy of the GNU General Public License
+*	along with this program; if not, write to the Free Software
+*	Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*
+*****************************************************************************/
+
+/*
+ * This dongle does no framing, and requires polling to receive the
+ * data.  The STIr4200 has bulk in and out endpoints just like
+ * usr-irda devices, but the data it sends and receives is raw; like
+ * irtty, it needs to call the wrap and unwrap functions to add and
+ * remove SOF/BOF and escape characters to/from the frame.
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/time.h>
+#include <linux/skbuff.h>
+#include <linux/netdevice.h>
+#include <linux/suspend.h>
+#include <linux/slab.h>
+#include <linux/usb.h>
+#include <net/irda/irda.h>
+#include <net/irda/irlap.h>
+#include <net/irda/irda_device.h>
+#include <net/irda/wrapper.h>
+#include <net/irda/crc.h>
+#include <linux/crc32.h>
+
+MODULE_AUTHOR("Stephen Hemminger <shemminger@osdl.org>");
+MODULE_DESCRIPTION("IrDA-USB Dongle Driver for SigmaTel STIr4200");
+MODULE_LICENSE("GPL");
+
+static int qos_mtt_bits = 0x07;	/* 1 ms or more */
+module_param(qos_mtt_bits, int, 0);
+MODULE_PARM_DESC(qos_mtt_bits, "Minimum Turn Time");
+
+static int rx_sensitivity = 1;	/* FIR 0..4, SIR 0..6 */
+module_param(rx_sensitivity, int, 0);
+MODULE_PARM_DESC(rx_sensitivity, "Set Receiver sensitivity (0-6, 0 is most sensitive)");
+
+static int tx_power = 0;	/* 0 = highest ... 3 = lowest */
+module_param(tx_power, int, 0);
+MODULE_PARM_DESC(tx_power, "Set Transmitter power (0-3, 0 is highest power)");
+
+static int rx_interval = 5;  /* milliseconds */
+module_param(rx_interval, int, 0);
+MODULE_PARM_DESC(rx_interval, "Receive polling interval (ms)");
+
+#define STIR_IRDA_HEADER  	4
+#define CTRL_TIMEOUT		100	   /* milliseconds */
+#define TRANSMIT_TIMEOUT	200	   /* milliseconds */
+#define STIR_FIFO_SIZE		4096
+#define NUM_RX_URBS		2
+
+enum FirChars {
+	FIR_CE   = 0x7d,
+	FIR_XBOF = 0x7f,
+	FIR_EOF  = 0x7e,
+};
+
+enum StirRequests {
+	REQ_WRITE_REG =		0x00,
+	REQ_READ_REG =		0x01,
+	REQ_READ_ROM =		0x02,
+	REQ_WRITE_SINGLE =	0x03,
+};
+
+/* Register offsets */
+enum StirRegs {
+	REG_RSVD=0,
+	REG_MODE,
+	REG_PDCLK,
+	REG_CTRL1,
+	REG_CTRL2,
+	REG_FIFOCTL,
+	REG_FIFOLSB,
+	REG_FIFOMSB,
+	REG_DPLL,
+	REG_IRDIG,
+	REG_TEST=15,
+};
+
+enum StirModeMask {
+	MODE_FIR = 0x80,
+	MODE_SIR = 0x20,
+	MODE_ASK = 0x10,
+	MODE_FASTRX = 0x08,
+	MODE_FFRSTEN = 0x04,
+	MODE_NRESET = 0x02,
+	MODE_2400 = 0x01,
+};
+
+enum StirPdclkMask {
+	PDCLK_4000000 = 0x02,
+	PDCLK_115200 = 0x09,
+	PDCLK_57600 = 0x13,
+	PDCLK_38400 = 0x1D,
+	PDCLK_19200 = 0x3B,
+	PDCLK_9600 = 0x77,
+	PDCLK_2400 = 0xDF,
+};
+
+enum StirCtrl1Mask {
+	CTRL1_SDMODE = 0x80,
+	CTRL1_RXSLOW = 0x40,
+	CTRL1_TXPWD = 0x10,
+	CTRL1_RXPWD = 0x08,
+	CTRL1_SRESET = 0x01,
+};
+
+enum StirCtrl2Mask {
+	CTRL2_SPWIDTH = 0x08,
+	CTRL2_REVID = 0x03,
+};
+
+enum StirFifoCtlMask {
+	FIFOCTL_EOF = 0x80,
+	FIFOCTL_UNDER = 0x40,
+	FIFOCTL_OVER = 0x20,
+	FIFOCTL_DIR = 0x10,
+	FIFOCTL_CLR = 0x08,
+	FIFOCTL_EMPTY = 0x04,
+	FIFOCTL_RXERR = 0x02,
+	FIFOCTL_TXERR = 0x01,
+};
+
+enum StirDiagMask {
+	IRDIG_RXHIGH = 0x80,
+	IRDIG_RXLOW = 0x40,
+};
+
+enum StirTestMask {
+	TEST_PLLDOWN = 0x80,
+	TEST_LOOPIR = 0x40,
+	TEST_LOOPUSB = 0x20,
+	TEST_TSTENA = 0x10,
+	TEST_TSTOSC = 0x0F,
+};
+
+enum StirState {
+	STIR_STATE_RECEIVING=0,
+	STIR_STATE_TXREADY,
+};
+
+struct stir_cb {
+        struct usb_device *usbdev;      /* init: probe_irda */
+        struct net_device *netdev;      /* network layer */
+        struct irlap_cb   *irlap;       /* The link layer we are binded to */
+        struct net_device_stats stats;	/* network statistics */
+        struct qos_info   qos;
+	unsigned long     state;
+	unsigned 	  speed;	/* Current speed */
+
+	wait_queue_head_t thr_wait;	/* transmit thread wakeup */
+	struct completion thr_exited;
+	pid_t		  thr_pid;
+
+	unsigned int	  tx_bulkpipe;
+	void		 *tx_data;	/* wrapped data out */
+	unsigned	  tx_len;
+	unsigned	  tx_newspeed;
+	unsigned	  tx_mtt;
+
+	unsigned int	  rx_intpipe;
+	iobuff_t  	  rx_buff;	/* receive unwrap state machine */
+	struct timespec	  rx_time;
+
+	struct urb	 *rx_urbs[NUM_RX_URBS];
+	void		 *rx_data[NUM_RX_URBS];
+};
+
+
+/* These are the currently known USB ids */
+static struct usb_device_id dongles[] = {
+    /* SigmaTel, Inc,  STIr4200 IrDA/USB Bridge */
+    { USB_DEVICE(0x066f, 0x4200) },
+    { }
+};
+
+MODULE_DEVICE_TABLE(usb, dongles);
+
+static int fifo_txwait(struct stir_cb *stir, unsigned space);
+static void stir_usb_receive(struct urb *urb, struct pt_regs *regs);
+
+/* Send control message to set dongle register */
+static int write_reg(struct stir_cb *stir, __u16 reg, __u8 value)
+{
+	struct usb_device *dev = stir->usbdev;
+
+	pr_debug("%s: write reg %d = 0x%x\n",
+		 stir->netdev->name, reg, value);
+	return usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
+			       REQ_WRITE_SINGLE,
+			       USB_DIR_OUT|USB_TYPE_VENDOR|USB_RECIP_DEVICE,
+			       value, reg, NULL, 0,
+			       MSECS_TO_JIFFIES(CTRL_TIMEOUT));
+}
+
+/* Send control message to read multiple registers */
+static inline int read_reg(struct stir_cb *stir, __u16 reg,
+		    __u8 *data, __u16 count)
+{
+	struct usb_device *dev = stir->usbdev;
+
+	return usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
+			       REQ_READ_REG,
+			       USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+			       0, reg, data, count,
+			       MSECS_TO_JIFFIES(CTRL_TIMEOUT));
+}
+
+/*
+ * Prepare a FIR IrDA frame for transmission to the USB dongle.  The
+ * FIR transmit frame is documented in the datasheet.  It consists of
+ * a two byte 0x55 0xAA sequence, two little-endian length bytes, a
+ * sequence of exactly 16 XBOF bytes of 0x7E, two BOF bytes of 0x7E,
+ * then the data escaped as follows:
+ *
+ *    0x7D -> 0x7D 0x5D
+ *    0x7E -> 0x7D 0x5E
+ *    0x7F -> 0x7D 0x5F
+ *
+ * Then, 4 bytes of little endian (stuffed) FCS follow, then two
+ * trailing EOF bytes of 0x7E.
+ */
+static inline __u8 *stuff_fir(__u8 *p, __u8 c)
+{
+	switch(c) {
+	case 0x7d:
+	case 0x7e:
+	case 0x7f:
+		*p++ = 0x7d;
+		c ^= IRDA_TRANS;
+		/* fall through */
+	default:
+		*p++ = c;
+	}
+	return p;
+}
+
+/* Take raw data in skb and put it wrapped into buf */
+static unsigned wrap_fir_skb(const struct sk_buff *skb, __u8 *buf)
+{
+	__u8 *ptr = buf;
+	__u32 fcs = ~(crc32_le(~0, skb->data, skb->len));
+	__u16 wraplen;
+	int i;
+
+	/* Header */
+	buf[0] = 0x55;
+	buf[1] = 0xAA;
+
+	ptr = buf + STIR_IRDA_HEADER;
+	memset(ptr, 0x7f, 16);
+	ptr += 16;
+
+	/* BOF */
+	*ptr++  = 0x7e;
+	*ptr++  = 0x7e;
+
+	/* Address / Control / Information */
+	for (i = 0; i < skb->len; i++)
+		ptr = stuff_fir(ptr, skb->data[i]);
+
+	/* FCS */
+	ptr = stuff_fir(ptr, fcs & 0xff);
+	ptr = stuff_fir(ptr, (fcs >> 8) & 0xff);
+	ptr = stuff_fir(ptr, (fcs >> 16) & 0xff);
+	ptr = stuff_fir(ptr, (fcs >> 24) & 0xff);
+
+	/* EOFs */
+	*ptr++ = 0x7e;
+	*ptr++ = 0x7e;
+
+	/* Total length, minus the header */
+	wraplen = (ptr - buf) - STIR_IRDA_HEADER;
+	buf[2] = wraplen & 0xff;
+	buf[3] = (wraplen >> 8) & 0xff;
+
+	return wraplen + STIR_IRDA_HEADER;
+}
+
+static unsigned wrap_sir_skb(struct sk_buff *skb, __u8 *buf)
+{
+	__u16 wraplen;
+
+	wraplen = async_wrap_skb(skb, buf + STIR_IRDA_HEADER,
+				 STIR_FIFO_SIZE - STIR_IRDA_HEADER);
+	buf[0] = 0x55;
+	buf[1] = 0xAA;
+	buf[2] = wraplen & 0xff;
+	buf[3] = (wraplen >> 8) & 0xff;
+
+	return wraplen + STIR_IRDA_HEADER;
+}
+
+/*
+ * Frame is fully formed in the rx_buff so check crc
+ * and pass up to irlap
+ * setup for next receive
+ */
+static void fir_eof(struct stir_cb *stir)
+{
+	iobuff_t *rx_buff = &stir->rx_buff;
+	int len = rx_buff->len - 4;
+	__u32 fcs;
+	struct sk_buff *nskb;
+
+	if (unlikely(len <= 0)) {
+		pr_debug("%s: short frame len %d\n",
+			 stir->netdev->name, len);
+
+		++stir->stats.rx_errors;
+		++stir->stats.rx_length_errors;
+		return;
+	}
+
+	fcs = rx_buff->data[len] |
+		rx_buff->data[len+1] << 8 |
+		rx_buff->data[len+2] << 16 |
+		rx_buff->data[len+3] << 24;
+
+	if (unlikely(fcs != ~(crc32_le(~0, rx_buff->data, len)))) {
+		pr_debug("%s: crc error\n", stir->netdev->name);
+		irda_device_set_media_busy(stir->netdev, TRUE);
+		stir->stats.rx_errors++;
+		stir->stats.rx_crc_errors++;
+		return;
+	}
+
+	/* If can't get new buffer, just drop and reuse */
+	nskb = dev_alloc_skb(IRDA_SKB_MAX_MTU);
+	if (unlikely(!nskb))
+		++stir->stats.rx_dropped;
+	else {
+		struct sk_buff *oskb = rx_buff->skb;
+		skb_reserve(nskb, 1);
+
+		/* Set correct length in socket buffer */
+		skb_put(oskb, len);
+
+		oskb->mac.raw  = oskb->data;
+		oskb->protocol = htons(ETH_P_IRDA);
+		oskb->dev = stir->netdev;
+
+		netif_rx(oskb);
+
+		stir->stats.rx_packets++;
+		stir->stats.rx_bytes += len;
+		rx_buff->skb = nskb;
+		rx_buff->head = nskb->data;
+	}
+
+	rx_buff->data = rx_buff->head;
+	rx_buff->len = 0;
+}
+
+/* Unwrap FIR stuffed data and bump it to IrLAP */
+static void stir_fir_chars(struct stir_cb *stir,
+			    const __u8 *bytes, int len)
+{
+	iobuff_t *rx_buff = &stir->rx_buff;
+	int	i;
+
+	for (i = 0; i < len; i++) {
+		__u8	byte = bytes[i];
+
+		switch(rx_buff->state) {
+		case OUTSIDE_FRAME:
+			/* ignore garbage till start of frame */
+			if (unlikely(byte != FIR_EOF))
+				continue;
+			/* Now receiving frame */
+			rx_buff->state = BEGIN_FRAME;
+			rx_buff->in_frame = TRUE;
+
+			/* Time to initialize receive buffer */
+			rx_buff->data = rx_buff->head;
+			rx_buff->len = 0;
+			continue;
+
+		case LINK_ESCAPE:
+			if (byte == FIR_EOF) {
+				pr_debug("%s: got EOF after escape\n",
+					 stir->netdev->name);
+				goto frame_error;
+			}
+			rx_buff->state = INSIDE_FRAME;
+			byte ^= IRDA_TRANS;
+			break;
+
+		case BEGIN_FRAME:
+			/* ignore multiple BOF/EOF */
+			if (byte == FIR_EOF)
+				continue;
+			rx_buff->state = INSIDE_FRAME;
+
+			/* fall through */
+		case INSIDE_FRAME:
+			switch(byte) {
+			case FIR_CE:
+				rx_buff->state = LINK_ESCAPE;
+				continue;
+			case FIR_XBOF:
+				/* 0x7f is not used in this framing */
+				pr_debug("%s: got XBOF without escape\n",
+					 stir->netdev->name);
+				goto frame_error;
+			case FIR_EOF:
+				rx_buff->state = OUTSIDE_FRAME;
+				rx_buff->in_frame = FALSE;
+				fir_eof(stir);
+				continue;
+			}
+			break;
+		}
+
+		/* add byte to rx buffer */
+		if (unlikely(rx_buff->len >= rx_buff->truesize)) {
+			pr_debug("%s: fir frame exceeds %d\n",
+				 stir->netdev->name, rx_buff->truesize);
+			++stir->stats.rx_over_errors;
+			goto error_recovery;
+		}
+
+		rx_buff->data[rx_buff->len++] = byte;
+		continue;
+
+	frame_error:
+		++stir->stats.rx_frame_errors;
+
+	error_recovery:
+		++stir->stats.rx_errors;
+		irda_device_set_media_busy(stir->netdev, TRUE);
+		rx_buff->state = OUTSIDE_FRAME;
+		rx_buff->in_frame = FALSE;
+	}
+}
+
+/* Unwrap SIR stuffed data and bump it up to IrLAP */
+static void stir_sir_chars(struct stir_cb *stir,
+			    const __u8 *bytes, int len)
+{
+	int i;
+
+	for (i = 0; i < len; i++)
+		async_unwrap_char(stir->netdev, &stir->stats,
+				  &stir->rx_buff, bytes[i]);
+}
+
+static inline int isfir(u32 speed)
+{
+	return (speed == 4000000);
+}
+
+static inline void unwrap_chars(struct stir_cb *stir,
+				const __u8 *bytes, int length)
+{
+	if (isfir(stir->speed))
+		stir_fir_chars(stir, bytes, length);
+	else
+		stir_sir_chars(stir, bytes, length);
+}
+
+/* Mode parameters for each speed */
+static const struct {
+	unsigned speed;
+	__u8 pdclk;
+} stir_modes[] = {
+        { 2400,    PDCLK_2400 },
+        { 9600,    PDCLK_9600 },
+        { 19200,   PDCLK_19200 },
+        { 38400,   PDCLK_38400 },
+        { 57600,   PDCLK_57600 },
+        { 115200,  PDCLK_115200 },
+        { 4000000, PDCLK_4000000 },
+};
+
+
+/*
+ * Setup chip for speed.
+ *  Called at startup to initialize the chip
+ *  and on speed changes.
+ *
+ * Note: Write multiple registers doesn't appear to work
+ */
+static int change_speed(struct stir_cb *stir, unsigned speed)
+{
+	int i, err;
+	__u8 mode;
+
+	pr_debug("%s: change speed %d\n", stir->netdev->name, speed);
+	for (i = 0; i < ARRAY_SIZE(stir_modes); ++i) {
+		if (speed == stir_modes[i].speed)
+			goto found;
+	}
+
+	ERROR("%s: invalid speed %d\n", stir->netdev->name, speed);
+	return -EINVAL;
+
+ found:
+	pr_debug("%s: speed change from %d to %d\n",
+		 stir->netdev->name, stir->speed, speed);
+
+	/* Make sure any previous Tx is really finished. This happens
+	 * when we answer an incomming request ; the ua:rsp and the
+	 * speed change are bundled together, so we need to wait until
+	 * the packet we just submitted has been sent. Jean II */
+	if (fifo_txwait(stir, 0))
+		return -EIO;
+
+	/* Set clock */
+	err = write_reg(stir, REG_PDCLK, stir_modes[i].pdclk);
+	if (err)
+		goto out;
+
+	mode = MODE_NRESET | MODE_FASTRX;
+	if (isfir(speed))
+		mode |= MODE_FIR | MODE_FFRSTEN;
+	else
+		mode |= MODE_SIR;
+
+	if (speed == 2400)
+		mode |= MODE_2400;
+
+	err = write_reg(stir, REG_MODE, mode);
+	if (err)
+		goto out;
+
+	/* This resets TEMIC style transceiver if any. */
+	err = write_reg(stir, REG_CTRL1,
+			CTRL1_SDMODE | (tx_power & 3) << 1);
+	if (err)
+		goto out;
+
+	err = write_reg(stir, REG_CTRL1, (tx_power & 3) << 1);
+
+ out:
+	stir->speed = speed;
+	return err;
+}
+
+static int stir_reset(struct stir_cb *stir)
+{
+	int err;
+
+	/* reset state */
+	stir->rx_buff.in_frame = FALSE;
+	stir->rx_buff.state = OUTSIDE_FRAME;
+	stir->speed = -1;
+
+	/* Undocumented magic to tweak the DPLL */
+	err = write_reg(stir, REG_DPLL, 0x15);
+	if (err)
+		goto out;
+
+	/* Reset sensitivity */
+	err = write_reg(stir, REG_CTRL2, (rx_sensitivity & 7) << 5);
+	if (err)
+		goto out;
+
+	err = change_speed(stir, 9600);
+ out:
+	return err;
+}
+
+/*
+ * Called from net/core when new frame is available.
+ */
+static int stir_hard_xmit(struct sk_buff *skb, struct net_device *netdev)
+{
+	struct stir_cb *stir = netdev->priv;
+
+	netif_stop_queue(netdev);
+
+	/* the IRDA wrapping routines don't deal with non linear skb */
+	SKB_LINEAR_ASSERT(skb);
+
+	if (unlikely(skb->len) == 0) 		/* speed change only */
+		stir->tx_len = 0;
+	else if (isfir(stir->speed))
+		stir->tx_len = wrap_fir_skb(skb, stir->tx_data);
+	else
+		stir->tx_len = wrap_sir_skb(skb, stir->tx_data);
+
+	stir->stats.tx_packets++;
+	stir->stats.tx_bytes += skb->len;
+
+	stir->tx_mtt = irda_get_mtt(skb);
+	stir->tx_newspeed = irda_get_next_speed(skb);
+
+	if (!test_and_set_bit(STIR_STATE_TXREADY, &stir->state))
+		wake_up(&stir->thr_wait);
+
+	dev_kfree_skb(skb);
+	return 0;
+}
+
+/*
+ * Wait for the transmit FIFO to have space for next data
+ */
+static int fifo_txwait(struct stir_cb *stir, unsigned space)
+{
+	int err;
+	unsigned count;
+	__u8 regs[3];
+	unsigned long timeout = jiffies + HZ/10;
+
+	for(;;) {
+		/* Read FIFO status and count */
+		err = read_reg(stir, REG_FIFOCTL, regs, 3);
+		if (unlikely(err != 3)) {
+			WARNING("%s: FIFO register read error: %d\n",
+				stir->netdev->name, err);
+			return err;
+		}
+
+		/* is fifo receiving already, or empty */
+		if (!(regs[0] & FIFOCTL_DIR)
+		    || (regs[0] & FIFOCTL_EMPTY))
+			return 0;
+
+		if (signal_pending(current))
+			return -EINTR;
+
+		/* shutting down? */
+		if (!netif_running(stir->netdev)
+		    || !netif_device_present(stir->netdev))
+			return -ESHUTDOWN;
+
+		count = (unsigned)(regs[2] & 0x1f) << 8 | regs[1];
+
+		pr_debug("%s: fifo status 0x%x count %u\n",
+			 stir->netdev->name, regs[0], count);
+
+		/* only waiting for some space */
+		if (space && STIR_FIFO_SIZE - 4 > space + count)
+			return 0;
+
+		if (time_after(jiffies, timeout)) {
+			WARNING("%s: transmit fifo timeout status=0x%x count=%d\n",
+				stir->netdev->name, regs[0], count);
+			++stir->stats.tx_errors;
+			irda_device_set_media_busy(stir->netdev, TRUE);
+			return -ETIMEDOUT;
+		}
+
+		/* estimate transfer time for remaining chars */
+		wait_ms((count * 8000) / stir->speed);
+	}
+}
+
+
+/* Wait for turnaround delay before starting transmit.  */
+static void turnaround_delay(long us, const struct timespec *last)
+{
+	long ticks;
+	struct timespec now = CURRENT_TIME;
+
+	if (us <= 0)
+		return;
+
+	us -= (now.tv_sec - last->tv_sec) * USEC_PER_SEC;
+	us -= (now.tv_nsec - last->tv_nsec) / NSEC_PER_USEC;
+	if (us < 10)
+		return;
+
+	ticks = us / (1000000 / HZ);
+	if (ticks > 0) {
+		current->state = TASK_INTERRUPTIBLE;
+		schedule_timeout(1 + ticks);
+	} else
+		udelay(us);
+}
+
+/*
+ * Start receiver by submitting a request to the receive pipe.
+ * If nothing is available it will return after rx_interval.
+ */
+static void receive_start(struct stir_cb *stir)
+{
+	int i;
+
+	if (test_and_set_bit(STIR_STATE_RECEIVING, &stir->state))
+		return;
+
+	if (fifo_txwait(stir, 0))
+		return;
+
+	for (i = 0; i < NUM_RX_URBS; i++) {
+		struct urb *urb = stir->rx_urbs[i];
+
+		usb_fill_int_urb(urb, stir->usbdev, stir->rx_intpipe,
+				 stir->rx_data[i], STIR_FIFO_SIZE,
+				 stir_usb_receive, stir, rx_interval);
+
+		if (usb_submit_urb(urb, GFP_KERNEL))
+			urb->status = -EINVAL;
+	}
+
+	if (i == 0) {
+		/* if nothing got queued, then just retry next time */
+		if (net_ratelimit())
+			WARNING("%s: no receive buffers avaiable\n",
+				stir->netdev->name);
+
+		clear_bit(STIR_STATE_RECEIVING, &stir->state);
+	}
+}
+
+/* Stop all pending receive Urb's */
+static void receive_stop(struct stir_cb *stir)
+{
+	int i;
+
+	for (i = 0; i < NUM_RX_URBS; i++) {
+		struct urb *urb = stir->rx_urbs[i];
+		usb_unlink_urb(urb);
+	}
+}
+
+/* Send wrapped data (in tx_data) to device */
+static void stir_send(struct stir_cb *stir)
+{
+	int rc;
+
+	if (test_and_clear_bit(STIR_STATE_RECEIVING, &stir->state)) {
+		receive_stop(stir);
+
+		turnaround_delay(stir->tx_mtt, &stir->rx_time);
+
+		if (stir->rx_buff.in_frame)
+			++stir->stats.collisions;
+	}
+	else if (fifo_txwait(stir, stir->tx_len))
+		return; /* shutdown or major errors */
+
+	stir->netdev->trans_start = jiffies;
+
+	pr_debug("%s: send %d\n", stir->netdev->name, stir->tx_len);
+	rc = usb_bulk_msg(stir->usbdev,
+			  stir->tx_bulkpipe,
+			  stir->tx_data, stir->tx_len,
+			  NULL, MSECS_TO_JIFFIES(TRANSMIT_TIMEOUT));
+
+	if (unlikely(rc)) {
+		WARNING("%s: usb bulk message failed %d\n",
+			stir->netdev->name, rc);
+		stir->stats.tx_errors++;
+	}
+}
+
+/*
+ * Transmit state machine thread
+ */
+static int stir_transmit_thread(void *arg)
+{
+	struct stir_cb *stir = arg;
+	struct net_device *dev = stir->netdev;
+	DECLARE_WAITQUEUE(wait, current);
+
+	daemonize("%s", dev->name);
+	allow_signal(SIGTERM);
+
+	while (netif_running(dev)
+	       && netif_device_present(dev)
+	       && !signal_pending(current))
+	{
+		/* make swsusp happy with our thread */
+		if (current->flags & PF_FREEZE) {
+			receive_stop(stir);
+
+			write_reg(stir, REG_CTRL1, CTRL1_TXPWD|CTRL1_RXPWD);
+
+			refrigerator(PF_IOTHREAD);
+
+			stir_reset(stir);
+		}
+
+		/* if something to send? */
+		if (test_and_clear_bit(STIR_STATE_TXREADY, &stir->state)) {
+			unsigned new_speed = stir->tx_newspeed;
+
+			/* Note that we may both send a packet and
+			 * change speed in some cases. Jean II */
+
+			if (stir->tx_len != 0)
+				stir_send(stir);
+
+			if (stir->speed != new_speed)
+				change_speed(stir, new_speed);
+
+			netif_wake_queue(stir->netdev);
+			continue;
+		}
+
+		if (irda_device_txqueue_empty(dev))
+			receive_start(stir);
+
+		set_task_state(current, TASK_INTERRUPTIBLE);
+		add_wait_queue(&stir->thr_wait, &wait);
+		if (test_bit(STIR_STATE_TXREADY, &stir->state))
+			__set_task_state(current, TASK_RUNNING);
+		else
+			schedule_timeout(HZ/10);
+		remove_wait_queue(&stir->thr_wait, &wait);
+	}
+
+	complete_and_exit (&stir->thr_exited, 0);
+}
+
+
+/*
+ * Receive wrapped data into rx_data buffer.
+ * This chip doesn't block until data is available, we just have
+ * to read the FIFO perodically (ugh).
+ */
+static void stir_usb_receive(struct urb *urb, struct pt_regs *regs)
+{
+	struct stir_cb *stir = urb->context;
+	int err;
+
+	if (!netif_running(stir->netdev))
+		return;
+
+	switch (urb->status) {
+	case 0:
+		if(urb->actual_length > 0) {
+			pr_debug("%s: receive %d\n",
+				 stir->netdev->name, urb->actual_length);
+			unwrap_chars(stir, urb->transfer_buffer,
+				     urb->actual_length);
+
+			stir->netdev->last_rx = jiffies;
+			stir->rx_time = CURRENT_TIME;
+		}
+		break;
+
+	case -ECONNRESET:	/* killed but pending */
+	case -ENOENT:		/* killed but not in use */
+	case -ESHUTDOWN:
+		/* These are normal errors when URB is cancelled */
+		stir->rx_buff.in_frame = FALSE;
+		stir->rx_buff.state = OUTSIDE_FRAME;
+		return;
+
+	default:
+		WARNING("%s: received status %d\n", stir->netdev->name,
+			urb->status);
+		stir->stats.rx_errors++;
+		urb->status = 0;
+	}
+
+	/* kernel thread is stopping receiver don't resubmit */
+	if (!test_bit(STIR_STATE_RECEIVING, &stir->state))
+		return;
+
+	/* resubmit existing urb */
+	err = usb_submit_urb(urb, GFP_ATOMIC);
+
+	/* in case of error, the kernel thread will restart us */
+	if (err) {
+		WARNING("%s: usb receive submit error: %d\n",
+			stir->netdev->name, err);
+		urb->status = -ENOENT;
+		wake_up(&stir->thr_wait);
+	}
+}
+
+
+/*
+ * Function stir_net_open (dev)
+ *
+ *    Network device is taken up. Usually this is done by "ifconfig irda0 up"
+ */
+static int stir_net_open(struct net_device *netdev)
+{
+	struct stir_cb *stir = netdev->priv;
+	int i, err;
+	char	hwname[16];
+
+	err = stir_reset(stir);
+	if (err)
+		goto err_out1;
+
+	err = -ENOMEM;
+
+	/* Note: Max SIR frame possible is 4273 */
+	stir->tx_data = kmalloc(STIR_FIFO_SIZE, GFP_KERNEL);
+	if (!stir->tx_data) {
+		ERROR("%s(), alloc failed for rxbuf!\n", __FUNCTION__);
+		goto err_out1;
+	}
+
+	/* Initialize for SIR/FIR to copy data directly into skb.  */
+	stir->rx_buff.truesize = IRDA_SKB_MAX_MTU;
+	stir->rx_buff.skb = dev_alloc_skb(IRDA_SKB_MAX_MTU);
+	if (!stir->rx_buff.skb) {
+		ERROR("%s(), dev_alloc_skb() failed for rxbuf!\n",
+		      __FUNCTION__);
+		goto err_out2;
+	}
+	skb_reserve(stir->rx_buff.skb, 1);
+	stir->rx_buff.head = stir->rx_buff.skb->data;
+	stir->rx_time = CURRENT_TIME;
+
+	/* Allocate N receive buffer's and urbs */
+	for (i = 0; i < NUM_RX_URBS; i++) {
+		stir->rx_urbs[i] = usb_alloc_urb(0, GFP_KERNEL);
+		if (!stir->rx_urbs[i]){
+			ERROR("%s(), usb_alloc_urb failed\n", __FUNCTION__);
+			goto err_out3;
+		}
+
+		stir->rx_data[i] = kmalloc(STIR_FIFO_SIZE, GFP_KERNEL);
+		if (!stir->rx_data) {
+			usb_free_urb(stir->rx_urbs[i]);
+			ERROR("%s(), alloc failed for rxbuf!\n", __FUNCTION__);
+			goto err_out3;
+		}
+	}
+
+	/*
+	 * Now that everything should be initialized properly,
+	 * Open new IrLAP layer instance to take care of us...
+	 * Note : will send immediately a speed change...
+	 */
+	sprintf(hwname, "usb#%d", stir->usbdev->devnum);
+	stir->irlap = irlap_open(netdev, &stir->qos, hwname);
+	if (!stir->irlap) {
+		ERROR("%s(): irlap_open failed\n", __FUNCTION__);
+		goto err_out3;
+	}
+
+	/** Start kernel thread for transmit.  */
+	stir->thr_pid = kernel_thread(stir_transmit_thread, stir,
+				      CLONE_FS|CLONE_FILES);
+	if (stir->thr_pid < 0) {
+		err = stir->thr_pid;
+		WARNING("%s: unable to start kernel thread\n",
+			stir->netdev->name);
+		goto err_out4;
+	}
+
+	netif_start_queue(netdev);
+
+	return 0;
+
+ err_out4:
+	irlap_close(stir->irlap);
+ err_out3:
+	while(--i >= 0) {
+		usb_free_urb(stir->rx_urbs[i]);
+		kfree(stir->rx_data[i]);
+	}
+	kfree_skb(stir->rx_buff.skb);
+ err_out2:
+	kfree(stir->tx_data);
+ err_out1:
+	return err;
+}
+
+/*
+ * Function stir_net_close (stir)
+ *
+ *    Network device is taken down. Usually this is done by
+ *    "ifconfig irda0 down"
+ */
+static int stir_net_close(struct net_device *netdev)
+{
+	struct stir_cb *stir = netdev->priv;
+	int i;
+
+	/* Stop transmit processing */
+	netif_stop_queue(netdev);
+
+	/* Kill transmit thread */
+	kill_proc(stir->thr_pid, SIGTERM, 1);
+	wait_for_completion(&stir->thr_exited);
+	kfree(stir->tx_data);
+
+	clear_bit(STIR_STATE_RECEIVING, &stir->state);
+	receive_stop(stir);
+
+	for (i = 0; i < NUM_RX_URBS; i++) {
+		usb_free_urb(stir->rx_urbs[i]);
+		kfree(stir->rx_data[i]);
+	}
+	kfree_skb(stir->rx_buff.skb);
+
+	/* Stop and remove instance of IrLAP */
+	if (stir->irlap)
+		irlap_close(stir->irlap);
+
+	stir->irlap = NULL;
+
+	return 0;
+}
+
+/*
+ * IOCTLs : Extra out-of-band network commands...
+ */
+static int stir_net_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
+{
+	struct if_irda_req *irq = (struct if_irda_req *) rq;
+	struct stir_cb *stir = dev->priv;
+	int ret = 0;
+
+	switch (cmd) {
+	case SIOCSBANDWIDTH: /* Set bandwidth */
+		if (!capable(CAP_NET_ADMIN))
+			return -EPERM;
+
+		/* Check if the device is still there */
+		if (netif_device_present(stir->netdev))
+			ret = change_speed(stir, irq->ifr_baudrate);
+		break;
+
+	case SIOCSMEDIABUSY: /* Set media busy */
+		if (!capable(CAP_NET_ADMIN))
+			return -EPERM;
+
+		/* Check if the IrDA stack is still there */
+		if (netif_running(stir->netdev))
+			irda_device_set_media_busy(stir->netdev, TRUE);
+		break;
+
+	case SIOCGRECEIVING:
+		/* Only approximately true */
+		irq->ifr_receiving = test_bit(STIR_STATE_RECEIVING, &stir->state);
+		break;
+
+	default:
+		ret = -EOPNOTSUPP;
+	}
+
+	return ret;
+}
+
+/*
+ * Get device stats (for /proc/net/dev and ifconfig)
+ */
+static struct net_device_stats *stir_net_get_stats(struct net_device *dev)
+{
+	struct stir_cb *stir = dev->priv;
+	return &stir->stats;
+}
+
+/*
+ *    Parse the various endpoints and find the one we need.
+ *
+ * The endpoint are the pipes used to communicate with the USB device.
+ * The spec defines 2 endpoints of type bulk transfer, one in, and one out.
+ * These are used to pass frames back and forth with the dongle.
+ */
+static int stir_setup_usb(struct stir_cb *stir, struct usb_interface *intf)
+{
+	struct usb_device *usbdev = interface_to_usbdev(intf);
+	const struct usb_host_interface *interface
+		= &intf->altsetting[intf->act_altsetting];
+	const struct usb_endpoint_descriptor *ep_in = NULL;
+	const struct usb_endpoint_descriptor *ep_out = NULL;
+	int i;
+
+	if (interface->desc.bNumEndpoints != 2) {
+		WARNING("%s: expected two endpoints\n", __FUNCTION__);
+		return -ENODEV;
+	}
+
+	for(i = 0; i < interface->desc.bNumEndpoints; i++) {
+		const struct usb_endpoint_descriptor *ep
+			= &interface->endpoint[i].desc;
+
+		if ((ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
+		    == USB_ENDPOINT_XFER_BULK) {
+			/* We need to find an IN and an OUT */
+			if ((ep->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_IN)
+				ep_in = ep;
+			else
+				ep_out = ep;
+		} else
+			WARNING("%s: unknown endpoint type 0x%x\n",
+				__FUNCTION__, ep->bmAttributes);
+	}
+
+	if (!ep_in || !ep_out)
+		return -EIO;
+
+	stir->tx_bulkpipe = usb_sndbulkpipe(usbdev,
+			    ep_out->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK);
+	stir->rx_intpipe = usb_rcvintpipe(usbdev,
+			    ep_in->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK);
+	return 0;
+}
+
+/*
+ * This routine is called by the USB subsystem for each new device
+ * in the system. We need to check if the device is ours, and in
+ * this case start handling it.
+ * Note : it might be worth protecting this function by a global
+ * spinlock... Or not, because maybe USB already deal with that...
+ */
+static int stir_probe(struct usb_interface *intf,
+		      const struct usb_device_id *id)
+{
+	struct usb_device *dev = interface_to_usbdev(intf);
+	struct stir_cb *stir = NULL;
+	struct net_device *net;
+	int ret = -ENOMEM;
+
+	/* Allocate network device container. */
+	net = alloc_irdadev(sizeof(*stir));
+	if(!net)
+		goto err_out1;
+
+	SET_MODULE_OWNER(net);
+	SET_NETDEV_DEV(net, &intf->dev);
+	stir = net->priv;
+	stir->netdev = net;
+	stir->usbdev = dev;
+
+	ret = stir_setup_usb(stir, intf);
+	if (ret != 0) {
+		ERROR("%s(), Bogus endpoints...\n", __FUNCTION__);
+		goto err_out2;
+	}
+
+	printk(KERN_INFO "SigmaTel STIr4200 IRDA/USB found at address %d, "
+		"Vendor: %x, Product: %x\n",
+	       dev->devnum, dev->descriptor.idVendor,
+	       dev->descriptor.idProduct);
+
+	/* Initialize QoS for this device */
+	irda_init_max_qos_capabilies(&stir->qos);
+
+	/* That's the Rx capability. */
+	stir->qos.baud_rate.bits       &= IR_2400 | IR_9600 | IR_19200 |
+					 IR_38400 | IR_57600 | IR_115200 |
+					 (IR_4000000 << 8);
+	stir->qos.min_turn_time.bits   &= qos_mtt_bits;
+	irda_qos_bits_to_value(&stir->qos);
+
+	init_completion (&stir->thr_exited);
+	init_waitqueue_head (&stir->thr_wait);
+
+	/* Override the network functions we need to use */
+	net->hard_start_xmit = stir_hard_xmit;
+	net->open            = stir_net_open;
+	net->stop            = stir_net_close;
+	net->get_stats	     = stir_net_get_stats;
+	net->do_ioctl        = stir_net_ioctl;
+
+	ret = stir_reset(stir);
+	if (ret)
+		goto err_out2;
+
+	ret = register_netdev(net);
+	if (ret != 0)
+		goto err_out2;
+
+	MESSAGE("IrDA: Registered SigmaTel device %s\n", net->name);
+
+	usb_set_intfdata(intf, stir);
+
+	return 0;
+
+err_out2:
+	free_netdev(net);
+err_out1:
+	return ret;
+}
+
+/*
+ * The current device is removed, the USB layer tell us to shut it down...
+ */
+static void stir_disconnect(struct usb_interface *intf)
+{
+	struct stir_cb *stir = usb_get_intfdata(intf);
+	struct net_device *net;
+
+	usb_set_intfdata(intf, NULL);
+	if (!stir)
+		return;
+
+	/* Stop transmitter */
+	net = stir->netdev;
+	netif_device_detach(net);
+
+	/* Remove netdevice */
+	unregister_netdev(net);
+
+	/* No longer attached to USB bus */
+	stir->usbdev = NULL;
+
+	free_netdev(net);
+}
+
+
+/* Power management suspend, so power off the transmitter/receiver */
+static int stir_suspend(struct usb_interface *intf, u32 state)
+{
+	struct stir_cb *stir = usb_get_intfdata(intf);
+
+	netif_device_detach(stir->netdev);
+	return 0;
+}
+
+/* Coming out of suspend, so reset hardware */
+static int stir_resume(struct usb_interface *intf)
+{
+	struct stir_cb *stir = usb_get_intfdata(intf);
+
+	netif_device_attach(stir->netdev);
+
+	/* receiver restarted when send thread wakes up */
+	return 0;
+}
+
+/*
+ * USB device callbacks
+ */
+static struct usb_driver irda_driver = {
+	.owner		= THIS_MODULE,
+	.name		= "stir4200",
+	.probe		= stir_probe,
+	.disconnect	= stir_disconnect,
+	.id_table	= dongles,
+	.suspend	= stir_suspend,
+	.resume		= stir_resume,
+};
+
+/*
+ * Module insertion
+ */
+static int __init stir_init(void)
+{
+	if (usb_register(&irda_driver) < 0)
+		return -1;
+
+	MESSAGE("SigmaTel support registered\n");
+	return 0;
+}
+module_init(stir_init);
+
+/*
+ * Module removal
+ */
+static void __exit stir_cleanup(void)
+{
+	/* Deregister the driver and remove all pending instances */
+	usb_deregister(&irda_driver);
+}
+module_exit(stir_cleanup);
--- diff/drivers/net/kgdb_eth.c	1970-01-01 01:00:00.000000000 +0100
+++ source/drivers/net/kgdb_eth.c	2004-02-23 13:56:43.000000000 +0000
@@ -0,0 +1,131 @@
+/*
+ * Network interface GDB stub
+ *
+ * Written by San Mehat (nettwerk@biodome.org)
+ * Based upon 'gdbserial' by David Grothe (dave@gcom.com)
+ * and Scott Foehner (sfoehner@engr.sgi.com)
+ *
+ * Twiddled for 2.6 by Robert Walsh <rjwalsh@durables.org>
+ * and wangdi <wangdi@clusterfs.com>.
+ *
+ * Refactored for netpoll API by Matt Mackall <mpm@selenic.com>
+ *
+ */
+
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <linux/config.h>
+#include <linux/string.h>
+#include <linux/netpoll.h>
+
+#include <asm/system.h>
+#include <asm/kgdb.h>
+#include <asm/io.h>
+#include <asm/bitops.h>
+#include <asm/system.h>
+#include <asm/irq.h>
+#include <asm/atomic.h>
+
+#define IN_BUF_SIZE 512 /* power of 2, please */
+#define OUT_BUF_SIZE 256
+
+static char in_buf[IN_BUF_SIZE], out_buf[OUT_BUF_SIZE];
+static int in_head, in_tail, out_count;
+static atomic_t in_count;
+int kgdboe = 0; /* Default to tty mode */
+
+extern void set_debug_traps(void);
+extern void breakpoint(void);
+static void rx_hook(struct netpoll *np, int port, char *msg, int len);
+
+static struct netpoll np = {
+	.name = "kgdboe",
+	.dev_name = "eth0",
+	.rx_hook = rx_hook,
+	.local_port = 6443,
+	.remote_port = 6442,
+	.remote_mac = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
+};
+
+int eth_getDebugChar(void)
+{
+	int chr;
+
+	while (atomic_read(&in_count) == 0)
+		netpoll_poll(&np);
+
+	chr = in_buf[in_tail++];
+	in_tail &= (IN_BUF_SIZE - 1);
+	atomic_dec(&in_count);
+	return chr;
+}
+
+void eth_flushDebugChar(void)
+{
+	if(out_count && np.dev) {
+		netpoll_send_udp(&np, out_buf, out_count);
+		out_count = 0;
+	}
+}
+
+void eth_putDebugChar(int chr)
+{
+	out_buf[out_count++] = chr;
+	if(out_count == OUT_BUF_SIZE)
+		eth_flushDebugChar();
+}
+
+static void rx_hook(struct netpoll *np, int port, char *msg, int len)
+{
+	int i;
+
+	np->remote_port = port;
+
+	/* Is this gdb trying to attach? */
+	if (!netpoll_trap() && len == 8 && !strncmp(msg, "$Hc-1#09", 8))
+		kgdb_schedule_breakpoint();
+
+	for (i = 0; i < len; i++) {
+		if (msg[i] == 3)
+			kgdb_schedule_breakpoint();
+
+		if (atomic_read(&in_count) >= IN_BUF_SIZE) {
+			/* buffer overflow, clear it */
+			in_head = in_tail = 0;
+			atomic_set(&in_count, 0);
+			break;
+		}
+		in_buf[in_head++] = msg[i];
+		in_head &= (IN_BUF_SIZE - 1);
+		atomic_inc(&in_count);
+	}
+}
+
+static int option_setup(char *opt)
+{
+	return netpoll_parse_options(&np, opt);
+}
+
+__setup("kgdboe=", option_setup);
+
+static int init_kgdboe(void)
+{
+#ifdef CONFIG_SMP
+	if (num_online_cpus() > CONFIG_NO_KGDB_CPUS) {
+		printk("kgdb: too manu cpus. Cannot enable debugger with more than %d cpus\n", CONFIG_NO_KGDB_CPUS);
+		return -1;
+	}
+#endif
+
+	set_debug_traps();
+
+	if(!np.remote_ip || netpoll_setup(&np))
+		return 1;
+
+	kgdboe = 1;
+	printk(KERN_INFO "kgdb: debugging over ethernet enabled\n");
+
+	return 0;
+}
+
+module_init(init_kgdboe);
--- diff/drivers/net/netconsole.c	1970-01-01 01:00:00.000000000 +0100
+++ source/drivers/net/netconsole.c	2004-02-23 13:56:43.000000000 +0000
@@ -0,0 +1,127 @@
+/*
+ *  linux/drivers/net/netconsole.c
+ *
+ *  Copyright (C) 2001  Ingo Molnar <mingo@redhat.com>
+ *
+ *  This file contains the implementation of an IRQ-safe, crash-safe
+ *  kernel console implementation that outputs kernel messages to the
+ *  network.
+ *
+ * Modification history:
+ *
+ * 2001-09-17    started by Ingo Molnar.
+ * 2003-08-11    2.6 port by Matt Mackall
+ *               simplified options
+ *               generic card hooks
+ *               works non-modular
+ * 2003-09-07    rewritten with netpoll api
+ */
+
+/****************************************************************
+ *      This program is free software; you can redistribute it and/or modify
+ *      it under the terms of the GNU General Public License as published by
+ *      the Free Software Foundation; either version 2, or (at your option)
+ *      any later version.
+ *
+ *      This program is distributed in the hope that it will be useful,
+ *      but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *      GNU General Public License for more details.
+ *
+ *      You should have received a copy of the GNU General Public License
+ *      along with this program; if not, write to the Free Software
+ *      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ ****************************************************************/
+
+#include <linux/mm.h>
+#include <linux/tty.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/console.h>
+#include <linux/tty_driver.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/string.h>
+#include <linux/sysrq.h>
+#include <linux/smp.h>
+#include <linux/netpoll.h>
+
+MODULE_AUTHOR("Maintainer: Matt Mackall <mpm@selenic.com>");
+MODULE_DESCRIPTION("Console driver for network interfaces");
+MODULE_LICENSE("GPL");
+
+static char config[256];
+module_param_string(netconsole, config, 256, 0);
+MODULE_PARM_DESC(netconsole, " netconsole=[src-port]@[src-ip]/[dev],[tgt-port]@<tgt-ip>/[tgt-macaddr]\n");
+
+static struct netpoll np = {
+	.name = "netconsole",
+	.dev_name = "eth0",
+	.local_port = 6665,
+	.remote_port = 6666,
+	.remote_mac = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
+};
+static int configured = 0;
+
+#define MAX_PRINT_CHUNK 1000
+
+static void write_msg(struct console *con, const char *msg, unsigned int len)
+{
+	int frag, left;
+	unsigned long flags;
+
+	if (!np.dev)
+		return;
+
+	local_irq_save(flags);
+
+	for(left = len; left; ) {
+		frag = min(left, MAX_PRINT_CHUNK);
+		netpoll_send_udp(&np, msg, frag);
+		msg += frag;
+		left -= frag;
+	}
+
+	local_irq_restore(flags);
+}
+
+static struct console netconsole = {
+	.flags = CON_ENABLED | CON_PRINTBUFFER,
+	.write = write_msg
+};
+
+static int option_setup(char *opt)
+{
+	configured = !netpoll_parse_options(&np, opt);
+	return 0;
+}
+
+__setup("netconsole=", option_setup);
+
+static int init_netconsole(void)
+{
+	if(strlen(config))
+		option_setup(config);
+
+	if(!configured) {
+		printk("netconsole: not configured, aborting\n");
+		return -EINVAL;
+	}
+
+	if(netpoll_setup(&np))
+		return -EINVAL;
+
+	register_console(&netconsole);
+	printk(KERN_INFO "netconsole: network logging started\n");
+	return 0;
+}
+
+static void cleanup_netconsole(void)
+{
+	unregister_console(&netconsole);
+	netpoll_cleanup(&np);
+}
+
+module_init(init_netconsole);
+module_exit(cleanup_netconsole);
--- diff/drivers/pci/hotplug/pciehp.h	1970-01-01 01:00:00.000000000 +0100
+++ source/drivers/pci/hotplug/pciehp.h	2004-02-23 13:56:44.000000000 +0000
@@ -0,0 +1,386 @@
+/*
+ * PCI Express Hot Plug Controller Driver
+ *
+ * Copyright (C) 1995,2001 Compaq Computer Corporation
+ * Copyright (C) 2001 Greg Kroah-Hartman (greg@kroah.com)
+ * Copyright (C) 2001 IBM Corp.
+ * Copyright (C) 2003-2004 Intel Corporation
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Send feedback to <greg@kroah.com>, <dely.l.sy@intel.com>
+ *
+ */
+#ifndef _PCIEHP_H
+#define _PCIEHP_H
+
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <asm/semaphore.h>
+#include <asm/io.h>		
+#include "pci_hotplug.h"
+
+#if !defined(CONFIG_HOTPLUG_PCI_PCIE_MODULE)
+	#define MY_NAME	"pciehp"
+#else
+	#define MY_NAME	THIS_MODULE->name
+#endif
+
+extern int pciehp_poll_mode;
+extern int pciehp_poll_time;
+extern int pciehp_debug;
+
+/*#define dbg(format, arg...) do { if (pciehp_debug) printk(KERN_DEBUG "%s: " format, MY_NAME , ## arg); } while (0)*/
+#define dbg(format, arg...) do { if (pciehp_debug) printk("%s: " format, MY_NAME , ## arg); } while (0)
+#define err(format, arg...) printk(KERN_ERR "%s: " format, MY_NAME , ## arg)
+#define info(format, arg...) printk(KERN_INFO "%s: " format, MY_NAME , ## arg)
+#define warn(format, arg...) printk(KERN_WARNING "%s: " format, MY_NAME , ## arg)
+
+struct pci_func {
+	struct pci_func *next;
+	u8 bus;
+	u8 device;
+	u8 function;
+	u8 is_a_board;
+	u16 status;
+	u8 configured;
+	u8 switch_save;
+	u8 presence_save;
+	u32 base_length[0x06];
+	u8 base_type[0x06];
+	u16 reserved2;
+	u32 config_space[0x20];
+	struct pci_resource *mem_head;
+	struct pci_resource *p_mem_head;
+	struct pci_resource *io_head;
+	struct pci_resource *bus_head;
+	struct pci_dev* pci_dev;
+};
+
+#define SLOT_MAGIC	0x67267321
+struct slot {
+	u32 magic;
+	struct slot *next;
+	u8 bus;
+	u8 device;
+	u32 number;
+	u8 is_a_board;
+	u8 configured;
+	u8 state;
+	u8 switch_save;
+	u8 presence_save;
+	u32 capabilities;
+	u16 reserved2;
+	struct timer_list task_event;
+	u8 hp_slot;
+	struct controller *ctrl;
+	struct hpc_ops *hpc_ops;
+	struct hotplug_slot *hotplug_slot;
+	struct list_head	slot_list;
+};
+
+struct pci_resource {
+	struct pci_resource * next;
+	u32 base;
+	u32 length;
+};
+
+struct event_info {
+	u32 event_type;
+	u8 hp_slot;
+};
+
+struct controller {
+	struct controller *next;
+	struct semaphore crit_sect;	/* critical section semaphore */
+	void * hpc_ctlr_handle;		/* HPC controller handle */
+	int num_slots;			/* Number of slots on ctlr */
+	int slot_num_inc;			/* 1 or -1 */
+	struct pci_resource *mem_head;
+	struct pci_resource *p_mem_head;
+	struct pci_resource *io_head;
+	struct pci_resource *bus_head;
+	struct pci_dev *pci_dev;
+	struct pci_bus *pci_bus;
+	struct event_info event_queue[10];
+	struct slot *slot;
+	struct hpc_ops *hpc_ops;
+	wait_queue_head_t queue;	/* sleep & wake process */
+	u8 next_event;
+	u8 seg;
+	u8 bus;
+	u8 device;
+	u8 function;
+	u8 rev;
+	u8 slot_device_offset;
+	u8 add_support;
+	enum pci_bus_speed speed;
+	u32 first_slot;		/* First physical slot number */  /* PCIE only has 1 slot */
+	u8 slot_bus;		/* Bus where the slots handled by this controller sit */
+	u8 push_flag;
+	u16 ctlrcap;
+	u16 vendor_id;
+};
+
+struct irq_mapping {
+	u8 barber_pole;
+	u8 valid_INT;
+	u8 interrupt[4];
+};
+
+struct resource_lists {
+	struct pci_resource *mem_head;
+	struct pci_resource *p_mem_head;
+	struct pci_resource *io_head;
+	struct pci_resource *bus_head;
+	struct irq_mapping *irqs;
+};
+
+#define INT_BUTTON_IGNORE		0
+#define INT_PRESENCE_ON			1
+#define INT_PRESENCE_OFF		2
+#define INT_SWITCH_CLOSE		3
+#define INT_SWITCH_OPEN			4
+#define INT_POWER_FAULT			5
+#define INT_POWER_FAULT_CLEAR		6
+#define INT_BUTTON_PRESS		7
+#define INT_BUTTON_RELEASE		8
+#define INT_BUTTON_CANCEL		9
+
+#define STATIC_STATE			0
+#define BLINKINGON_STATE		1
+#define BLINKINGOFF_STATE		2
+#define POWERON_STATE			3
+#define POWEROFF_STATE			4
+
+#define PCI_TO_PCI_BRIDGE_CLASS		0x00060400
+
+/* Error messages */
+#define INTERLOCK_OPEN			0x00000002
+#define ADD_NOT_SUPPORTED		0x00000003
+#define CARD_FUNCTIONING		0x00000005
+#define ADAPTER_NOT_SAME		0x00000006
+#define NO_ADAPTER_PRESENT		0x00000009
+#define NOT_ENOUGH_RESOURCES		0x0000000B
+#define DEVICE_TYPE_NOT_SUPPORTED	0x0000000C
+#define WRONG_BUS_FREQUENCY		0x0000000D
+#define POWER_FAILURE			0x0000000E
+
+#define REMOVE_NOT_SUPPORTED		0x00000003
+
+#define DISABLE_CARD			1
+
+/*
+ * error Messages
+ */
+#define msg_initialization_err	"Initialization failure, error=%d\n"
+#define msg_HPC_rev_error	"Unsupported revision of the PCI hot plug controller found.\n"
+#define msg_HPC_non_pcie	"The PCI hot plug controller is not supported by this driver.\n"
+#define msg_HPC_not_supported	"This system is not supported by this version of pciephd mdoule. Upgrade to a newer version of pciehpd\n"
+#define msg_unable_to_save	"Unable to store PCI hot plug add resource information. This system must be rebooted before adding any PCI devices.\n"
+#define msg_button_on		"PCI slot #%d - powering on due to button press.\n"
+#define msg_button_off		"PCI slot #%d - powering off due to button press.\n"
+#define msg_button_cancel	"PCI slot #%d - action canceled due to button press.\n"
+#define msg_button_ignore	"PCI slot #%d - button press ignored.  (action in progress...)\n"
+
+/* sysfs function for the hotplug controller info */
+extern void pciehp_create_ctrl_files	(struct controller *ctrl);
+
+/* controller functions */
+extern void	pciehp_pushbutton_thread		(unsigned long event_pointer);
+extern int	pciehprm_find_available_resources	(struct controller *ctrl);
+extern int	pciehp_event_start_thread	(void);
+extern void	pciehp_event_stop_thread	(void);
+extern struct 	pci_func *pciehp_slot_create	(unsigned char busnumber);
+extern struct 	pci_func *pciehp_slot_find	(unsigned char bus, unsigned char device, unsigned char index);
+extern int	pciehp_enable_slot		(struct slot *slot);
+extern int	pciehp_disable_slot		(struct slot *slot);
+
+extern u8	pciehp_handle_attention_button	(u8 hp_slot, void *inst_id);
+extern u8	pciehp_handle_switch_change	(u8 hp_slot, void *inst_id);
+extern u8	pciehp_handle_presence_change	(u8 hp_slot, void *inst_id);
+extern u8	pciehp_handle_power_fault	(u8 hp_slot, void *inst_id);
+/* extern void	long_delay (int delay); */
+
+/* resource functions */
+extern int	pciehp_resource_sort_and_combine	(struct pci_resource **head);
+
+/* pci functions */
+extern int	pciehp_set_irq			(u8 bus_num, u8 dev_num, u8 int_pin, u8 irq_num);
+/*extern int	pciehp_get_bus_dev		(struct controller *ctrl, u8 *bus_num, u8 *dev_num, struct slot *slot);*/
+extern int	pciehp_save_config	 	(struct controller *ctrl, int busnumber, int num_ctlr_slots, int first_device_num);
+extern int	pciehp_save_used_resources	(struct controller *ctrl, struct pci_func * func, int flag);
+extern int	pciehp_save_slot_config		(struct controller *ctrl, struct pci_func * new_slot);
+extern void	pciehp_destroy_board_resources	(struct pci_func * func);
+extern int	pciehp_return_board_resources	(struct pci_func * func, struct resource_lists * resources);
+extern void	pciehp_destroy_resource_list	(struct resource_lists * resources);
+extern int	pciehp_configure_device		(struct controller* ctrl, struct pci_func* func);
+extern int	pciehp_unconfigure_device	(struct pci_func* func);
+
+
+/* Global variables */
+extern struct controller *pciehp_ctrl_list;
+extern struct pci_func *pciehp_slot_list[256];
+
+/* Inline functions */
+
+
+/* Inline functions to check the sanity of a pointer that is passed to us */
+static inline int slot_paranoia_check (struct slot *slot, const char *function)
+{
+	if (!slot) {
+		dbg("%s - slot == NULL", function);
+		return -1;
+	}
+	if (slot->magic != SLOT_MAGIC) {
+		dbg("%s - bad magic number for slot", function);
+		return -1;
+	}
+	if (!slot->hotplug_slot) {
+		dbg("%s - slot->hotplug_slot == NULL!", function);
+		return -1;
+	}
+	return 0;
+}
+
+static inline struct slot *get_slot (struct hotplug_slot *hotplug_slot, const char *function)
+{ 
+	struct slot *slot;
+
+	if (!hotplug_slot) {
+		dbg("%s - hotplug_slot == NULL\n", function);
+		return NULL;
+	}
+
+	slot = (struct slot *)hotplug_slot->private;
+	if (slot_paranoia_check (slot, function))
+                return NULL;
+	return slot;
+}
+
+static inline struct slot *pciehp_find_slot (struct controller *ctrl, u8 device)
+{
+	struct slot *p_slot, *tmp_slot = NULL;
+
+	if (!ctrl)
+		return NULL;
+
+	p_slot = ctrl->slot;
+
+	dbg("p_slot = %p\n", p_slot);
+
+	while (p_slot && (p_slot->device != device)) {
+		tmp_slot = p_slot;
+		p_slot = p_slot->next;
+		dbg("In while loop, p_slot = %p\n", p_slot);
+	}
+	if (p_slot == NULL) {
+		err("ERROR: pciehp_find_slot device=0x%x\n", device);
+		p_slot = tmp_slot;
+	}
+
+	return (p_slot);
+}
+
+static inline int wait_for_ctrl_irq (struct controller *ctrl)
+{
+	int retval = 0;
+
+	DECLARE_WAITQUEUE(wait, current);
+
+	dbg("%s : start\n", __FUNCTION__);
+	add_wait_queue(&ctrl->queue, &wait);
+	set_current_state(TASK_INTERRUPTIBLE);
+	if (!pciehp_poll_mode) {
+		/* Sleep for up to 1 second */
+		schedule_timeout(1*HZ);
+	} else
+		schedule_timeout(2.5*HZ);
+	
+	set_current_state(TASK_RUNNING);
+	remove_wait_queue(&ctrl->queue, &wait);
+	if (signal_pending(current))
+		retval =  -EINTR;
+
+	dbg("%s : end\n", __FUNCTION__);
+	return retval;
+}
+
+/* Puts node back in the resource list pointed to by head */
+static inline void return_resource(struct pci_resource **head, struct pci_resource *node)
+{
+	if (!node || !head)
+		return;
+	node->next = *head;
+	*head = node;
+}
+
+#define SLOT_NAME_SIZE 10
+
+static inline void make_slot_name(char *buffer, int buffer_size, struct slot *slot)
+{
+	snprintf(buffer, buffer_size, "%d", slot->number);
+}
+
+enum php_ctlr_type {
+	PCI,
+	ISA,
+	ACPI
+};
+
+typedef u8(*php_intr_callback_t) (unsigned int change_id, void *instance_id);
+
+int pcie_init( struct controller *ctrl, struct pci_dev *pdev,
+		php_intr_callback_t attention_button_callback,
+		php_intr_callback_t switch_change_callback,
+		php_intr_callback_t presence_change_callback,
+		php_intr_callback_t power_fault_callback);
+
+
+/* This has no meaning for PCI Express, as there is only 1 slot per port */
+int pcie_get_ctlr_slot_config( struct controller *ctrl,
+		int *num_ctlr_slots,
+		int *first_device_num,
+		int *physical_slot_num,
+		int *updown,
+		int *flags);
+
+struct hpc_ops {
+	int	(*power_on_slot )		(struct slot *slot);
+	int	(*power_off_slot )		(struct slot *slot);
+	int	(*get_power_status)		(struct slot *slot, u8 *status);
+	int	(*get_attention_status)	(struct slot *slot, u8 *status);
+	int	(*set_attention_status)	(struct slot *slot, u8 status);
+	int	(*get_latch_status)		(struct slot *slot, u8 *status);
+	int	(*get_adapter_status)	(struct slot *slot, u8 *status);
+
+	int	(*get_max_bus_speed)	(struct slot *slot, enum pci_bus_speed *speed);
+	int	(*get_cur_bus_speed)	(struct slot *slot, enum pci_bus_speed *speed);
+
+	int	(*get_max_lnk_width)	(struct slot *slot, enum pcie_link_width *value);
+	int	(*get_cur_lnk_width)	(struct slot *slot, enum pcie_link_width *value);
+	
+	int	(*query_power_fault)	(struct slot *slot);
+	void	(*green_led_on)		(struct slot *slot);
+	void	(*green_led_off)	(struct slot *slot);
+	void	(*green_led_blink)	(struct slot *slot);
+	void	(*release_ctlr)		(struct controller *ctrl);
+	int (*check_lnk_status)		(struct controller *ctrl);
+};
+
+#endif				/* _PCIEHP_H */
--- diff/drivers/pci/hotplug/pciehp_core.c	1970-01-01 01:00:00.000000000 +0100
+++ source/drivers/pci/hotplug/pciehp_core.c	2004-02-23 13:56:44.000000000 +0000
@@ -0,0 +1,707 @@
+/*
+ * PCI Express Hot Plug Controller Driver
+ *
+ * Copyright (C) 1995,2001 Compaq Computer Corporation
+ * Copyright (C) 2001 Greg Kroah-Hartman (greg@kroah.com)
+ * Copyright (C) 2001 IBM Corp.
+ * Copyright (C) 2003-2004 Intel Corporation
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Send feedback to <greg@kroah.com>, <dely.l.sy@intel.com>
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/proc_fs.h>
+#include <linux/miscdevice.h>
+#include <linux/slab.h>
+#include <linux/workqueue.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <asm/uaccess.h>
+#include "pciehp.h"
+#include "pciehprm.h"
+
+/* Global variables */
+int pciehp_debug;
+int pciehp_poll_mode;
+int pciehp_poll_time;
+struct controller *pciehp_ctrl_list;	/* = NULL */
+struct pci_func *pciehp_slot_list[256];
+
+#define DRIVER_VERSION	"0.4"
+#define DRIVER_AUTHOR	"Dan Zink <dan.zink@compaq.com>, Greg Kroah-Hartman <greg@kroah.com>, Dely Sy <dely.l.sy@intel.com>"
+#define DRIVER_DESC	"PCI Express Hot Plug Controller Driver"
+
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_LICENSE("GPL");
+
+MODULE_PARM(pciehp_debug, "i");
+MODULE_PARM(pciehp_poll_mode, "i");
+MODULE_PARM(pciehp_poll_time, "i");
+MODULE_PARM_DESC(pciehp_debug, "Debugging mode enabled or not");
+MODULE_PARM_DESC(pciehp_poll_mode, "Using polling mechanism for hot-plug events or not");
+MODULE_PARM_DESC(pciehp_poll_time, "Polling mechanism frequency, in seconds");
+
+#define PCIE_MODULE_NAME "pciehp"
+
+static int pcie_start_thread (void);
+static int set_attention_status (struct hotplug_slot *slot, u8 value);
+static int enable_slot		(struct hotplug_slot *slot);
+static int disable_slot		(struct hotplug_slot *slot);
+static int hardware_test	(struct hotplug_slot *slot, u32 value);
+static int get_power_status	(struct hotplug_slot *slot, u8 *value);
+static int get_attention_status	(struct hotplug_slot *slot, u8 *value);
+static int get_latch_status	(struct hotplug_slot *slot, u8 *value);
+static int get_adapter_status	(struct hotplug_slot *slot, u8 *value);
+static int get_max_bus_speed	(struct hotplug_slot *slot, enum pci_bus_speed *value);
+static int get_cur_bus_speed	(struct hotplug_slot *slot, enum pci_bus_speed *value);
+
+static struct hotplug_slot_ops pciehp_hotplug_slot_ops = {
+	.owner =		THIS_MODULE,
+	.set_attention_status =	set_attention_status,
+	.enable_slot =		enable_slot,
+	.disable_slot =		disable_slot,
+	.hardware_test =	hardware_test,
+	.get_power_status =	get_power_status,
+	.get_attention_status =	get_attention_status,
+	.get_latch_status =	get_latch_status,
+	.get_adapter_status =	get_adapter_status,
+  	.get_max_bus_speed =	get_max_bus_speed,
+  	.get_cur_bus_speed =	get_cur_bus_speed,
+};
+
+static int init_slots(struct controller *ctrl)
+{
+	struct slot *new_slot;
+	u8 number_of_slots;
+	u8 slot_device;
+	u32 slot_number;
+	int result;
+
+	dbg("%s\n",__FUNCTION__);
+
+	number_of_slots = ctrl->num_slots;
+	slot_device = ctrl->slot_device_offset;
+	slot_number = ctrl->first_slot;
+
+	while (number_of_slots) {
+		new_slot = (struct slot *) kmalloc(sizeof(struct slot), GFP_KERNEL);
+		if (!new_slot)
+			return -ENOMEM;
+
+		memset(new_slot, 0, sizeof(struct slot));
+		new_slot->hotplug_slot = kmalloc (sizeof (struct hotplug_slot), GFP_KERNEL);
+		if (!new_slot->hotplug_slot) {
+			kfree (new_slot);
+			return -ENOMEM;
+		}
+		memset(new_slot->hotplug_slot, 0, sizeof (struct hotplug_slot));
+
+		new_slot->hotplug_slot->info = kmalloc (sizeof (struct hotplug_slot_info), GFP_KERNEL);
+		if (!new_slot->hotplug_slot->info) {
+			kfree (new_slot->hotplug_slot);
+			kfree (new_slot);
+			return -ENOMEM;
+		}
+		memset(new_slot->hotplug_slot->info, 0, sizeof (struct hotplug_slot_info));
+		new_slot->hotplug_slot->name = kmalloc (SLOT_NAME_SIZE, GFP_KERNEL);
+		if (!new_slot->hotplug_slot->name) {
+			kfree (new_slot->hotplug_slot->info);
+			kfree (new_slot->hotplug_slot);
+			kfree (new_slot);
+			return -ENOMEM;
+		}
+
+		new_slot->magic = SLOT_MAGIC;
+		new_slot->ctrl = ctrl;
+		new_slot->bus = ctrl->slot_bus;
+		new_slot->device = slot_device;
+		new_slot->hpc_ops = ctrl->hpc_ops;
+
+		new_slot->number = ctrl->first_slot;
+		new_slot->hp_slot = slot_device - ctrl->slot_device_offset;
+
+		/* register this slot with the hotplug pci core */
+		new_slot->hotplug_slot->private = new_slot;
+		make_slot_name (new_slot->hotplug_slot->name, SLOT_NAME_SIZE, new_slot);
+		new_slot->hotplug_slot->ops = &pciehp_hotplug_slot_ops;
+
+		new_slot->hpc_ops->get_power_status(new_slot, &(new_slot->hotplug_slot->info->power_status));
+		new_slot->hpc_ops->get_attention_status(new_slot, &(new_slot->hotplug_slot->info->attention_status));
+		new_slot->hpc_ops->get_latch_status(new_slot, &(new_slot->hotplug_slot->info->latch_status));
+		new_slot->hpc_ops->get_adapter_status(new_slot, &(new_slot->hotplug_slot->info->adapter_status));
+
+		dbg("Registering bus=%x dev=%x hp_slot=%x sun=%x slot_device_offset=%x\n", 
+			new_slot->bus, new_slot->device, new_slot->hp_slot, new_slot->number, ctrl->slot_device_offset);
+		result = pci_hp_register (new_slot->hotplug_slot);
+		if (result) {
+			err ("pci_hp_register failed with error %d\n", result);
+			kfree (new_slot->hotplug_slot->info);
+			kfree (new_slot->hotplug_slot->name);
+			kfree (new_slot->hotplug_slot);
+			kfree (new_slot);
+			return result;
+		}
+
+		new_slot->next = ctrl->slot;
+		ctrl->slot = new_slot;
+
+		number_of_slots--;
+		slot_device++;
+		slot_number += ctrl->slot_num_inc;
+	}
+
+	return(0);
+}
+
+
+static int cleanup_slots (struct controller * ctrl)
+{
+	struct slot *old_slot, *next_slot;
+
+	old_slot = ctrl->slot;
+	ctrl->slot = NULL;
+
+	while (old_slot) {
+		next_slot = old_slot->next;
+		pci_hp_deregister (old_slot->hotplug_slot);
+		kfree(old_slot->hotplug_slot->info);
+		kfree(old_slot->hotplug_slot->name);
+		kfree(old_slot->hotplug_slot);
+		kfree(old_slot);
+		old_slot = next_slot;
+	}
+
+
+	return(0);
+}
+
+static int get_ctlr_slot_config(struct controller *ctrl)
+{
+	int num_ctlr_slots;		/* Not needed; PCI Express has 1 slot per port*/
+	int first_device_num;		/* Not needed */
+	int physical_slot_num;
+	int updown;			/* Not needed */
+	int rc;
+	int flags;			/* Not needed */
+
+	rc = pcie_get_ctlr_slot_config(ctrl, &num_ctlr_slots, &first_device_num, &physical_slot_num, &updown, &flags);
+	if (rc) {
+		err("%s: get_ctlr_slot_config fail for b:d (%x:%x)\n", __FUNCTION__, ctrl->bus, ctrl->device);
+		return (-1);
+	}
+
+	ctrl->num_slots = num_ctlr_slots;	/* PCI Express has 1 slot per port */
+	ctrl->slot_device_offset = first_device_num;
+	ctrl->first_slot = physical_slot_num;
+	ctrl->slot_num_inc = updown; 	/* Not needed */		/* either -1 or 1 */
+
+	dbg("%s: bus(0x%x) num_slot(0x%x) 1st_dev(0x%x) psn(0x%x) updown(%d) for b:d (%x:%x)\n",
+		__FUNCTION__, ctrl->slot_bus, num_ctlr_slots, first_device_num, physical_slot_num, updown, 
+		ctrl->bus, ctrl->device);
+
+	return (0);
+}
+
+
+/*
+ * set_attention_status - Turns the Amber LED for a slot on, off or blink
+ */
+static int set_attention_status (struct hotplug_slot *hotplug_slot, u8 status)
+{
+	struct slot *slot = get_slot (hotplug_slot, __FUNCTION__);
+
+	if (slot == NULL)
+		return -ENODEV;
+	
+	dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
+
+	hotplug_slot->info->attention_status = status;
+	slot->hpc_ops->set_attention_status(slot, status);
+
+	return 0;
+}
+
+
+static int enable_slot (struct hotplug_slot *hotplug_slot)
+{
+	struct slot *slot = get_slot (hotplug_slot, __FUNCTION__);
+	
+	if (slot == NULL)
+		return -ENODEV;
+
+	dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
+
+	return pciehp_enable_slot(slot);
+}
+
+
+static int disable_slot (struct hotplug_slot *hotplug_slot)
+{
+	struct slot *slot = get_slot (hotplug_slot, __FUNCTION__);
+	
+	if (slot == NULL)
+		return -ENODEV;
+
+	dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
+
+	return pciehp_disable_slot(slot);
+}
+
+
+static int hardware_test (struct hotplug_slot *hotplug_slot, u32 value)
+{
+	return 0;
+}
+
+
+static int get_power_status (struct hotplug_slot *hotplug_slot, u8 *value)
+{
+	struct slot *slot = get_slot (hotplug_slot, __FUNCTION__);
+	int retval;
+	
+	if (slot == NULL)
+		return -ENODEV;
+	
+	dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
+
+	retval = slot->hpc_ops->get_power_status(slot, value);
+	if (retval < 0)
+		*value = hotplug_slot->info->power_status;
+
+	return 0;
+}
+
+static int get_attention_status (struct hotplug_slot *hotplug_slot, u8 *value)
+{
+	struct slot *slot = get_slot (hotplug_slot, __FUNCTION__);
+	int retval;
+	
+	if (slot == NULL)
+		return -ENODEV;
+	
+	dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
+
+	retval = slot->hpc_ops->get_attention_status(slot, value);
+	if (retval < 0)
+		*value = hotplug_slot->info->attention_status;
+
+	return 0;
+}
+
+static int get_latch_status (struct hotplug_slot *hotplug_slot, u8 *value)
+{
+	struct slot *slot = get_slot (hotplug_slot, __FUNCTION__);
+	int retval;
+	
+	if (slot == NULL)
+		return -ENODEV;
+	
+	dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
+
+	retval = slot->hpc_ops->get_latch_status(slot, value);
+	if (retval < 0)
+		*value = hotplug_slot->info->latch_status;
+
+	return 0;
+}
+
+static int get_adapter_status (struct hotplug_slot *hotplug_slot, u8 *value)
+{
+	struct slot *slot = get_slot (hotplug_slot, __FUNCTION__);
+	int retval;
+	
+	if (slot == NULL)
+		return -ENODEV;
+
+	dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
+
+	retval = slot->hpc_ops->get_adapter_status(slot, value);
+
+	if (retval < 0)
+		*value = hotplug_slot->info->adapter_status;
+
+	return 0;
+}
+
+static int get_max_bus_speed (struct hotplug_slot *hotplug_slot, enum pci_bus_speed *value)
+{
+	struct slot *slot = get_slot (hotplug_slot, __FUNCTION__);
+	int retval;
+	
+	if (slot == NULL)
+		return -ENODEV;
+
+	dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
+	
+	retval = slot->hpc_ops->get_max_bus_speed(slot, value);
+	if (retval < 0)
+		*value = PCI_SPEED_UNKNOWN;
+
+	return 0;
+}
+
+static int get_cur_bus_speed (struct hotplug_slot *hotplug_slot, enum pci_bus_speed *value)
+{
+	struct slot *slot = get_slot (hotplug_slot, __FUNCTION__);
+	int retval;
+	
+	if (slot == NULL)
+		return -ENODEV;
+
+	dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
+	
+	retval = slot->hpc_ops->get_cur_bus_speed(slot, value);
+	if (retval < 0)
+		*value = PCI_SPEED_UNKNOWN;
+
+	return 0;
+}
+
+static int pcie_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
+{
+	int rc;
+	struct controller *ctrl;
+	struct slot *t_slot;
+	int first_device_num = 0 ;	/* first PCI device number supported by this PCIE */  
+	int num_ctlr_slots;		/* number of slots supported by this HPC */
+	u8 value;
+
+	ctrl = (struct controller *) kmalloc(sizeof(struct controller), GFP_KERNEL);
+	if (!ctrl) {
+		err("%s : out of memory\n", __FUNCTION__);
+		goto err_out_none;
+	}
+	memset(ctrl, 0, sizeof(struct controller));
+
+	dbg("%s: DRV_thread pid = %d\n", __FUNCTION__, current->pid);
+
+	rc = pcie_init(ctrl, pdev,
+		(php_intr_callback_t) pciehp_handle_attention_button,
+		(php_intr_callback_t) pciehp_handle_switch_change,
+		(php_intr_callback_t) pciehp_handle_presence_change,
+		(php_intr_callback_t) pciehp_handle_power_fault);
+	if (rc) {
+		dbg("%s: controller initialization failed\n", PCIE_MODULE_NAME);
+		goto err_out_free_ctrl;
+	}
+
+	ctrl->pci_dev = pdev;
+
+	pci_set_drvdata(pdev, ctrl);
+
+	ctrl->pci_bus = kmalloc (sizeof (*ctrl->pci_bus), GFP_KERNEL);
+	if (!ctrl->pci_bus) {
+		err("%s: out of memory\n", __FUNCTION__);
+		rc = -ENOMEM;
+		goto err_out_unmap_mmio_region;
+	}
+	dbg("%s: ctrl->pci_bus %p\n", __FUNCTION__, ctrl->pci_bus);
+	memcpy (ctrl->pci_bus, pdev->bus, sizeof (*ctrl->pci_bus));
+	ctrl->bus = pdev->bus->number;  /* ctrl bus */
+	ctrl->slot_bus = pdev->subordinate->number;  /* bus controlled by this HPC */
+
+	ctrl->device = PCI_SLOT(pdev->devfn);
+	ctrl->function = PCI_FUNC(pdev->devfn);
+	dbg("%s: ctrl bus=0x%x, device=%x, function=%x, irq=%x\n", __FUNCTION__,
+		ctrl->bus, ctrl->device, ctrl->function, pdev->irq);
+
+	/*
+	 *	Save configuration headers for this and subordinate PCI buses
+	 */
+
+	rc = get_ctlr_slot_config(ctrl);
+	if (rc) {
+		err(msg_initialization_err, rc);
+		goto err_out_free_ctrl_bus;
+	}
+	first_device_num = ctrl->slot_device_offset;
+	num_ctlr_slots = ctrl->num_slots; 
+
+	/* Store PCI Config Space for all devices on this bus */
+	dbg("%s: Before calling pciehp_save_config, ctrl->bus %x,ctrl->slot_bus %x\n", 
+		__FUNCTION__,ctrl->bus, ctrl->slot_bus);
+	rc = pciehp_save_config(ctrl, ctrl->slot_bus, num_ctlr_slots, first_device_num);
+	if (rc) {
+		err("%s: unable to save PCI configuration data, error %d\n", __FUNCTION__, rc);
+		goto err_out_free_ctrl_bus;
+	}
+
+	/* Get IO, memory, and IRQ resources for new devices */
+	rc = pciehprm_find_available_resources(ctrl);
+	ctrl->add_support = !rc;
+	
+	if (rc) {
+		dbg("pciehprm_find_available_resources = %#x\n", rc);
+		err("unable to locate PCI configuration resources for hot plug add.\n");
+		goto err_out_free_ctrl_bus;
+	}
+
+	/* Setup the slot information structures */
+	rc = init_slots(ctrl);
+	if (rc) {
+		err(msg_initialization_err, 6);
+		goto err_out_free_ctrl_slot;
+	}
+
+	t_slot = pciehp_find_slot(ctrl, first_device_num);
+	dbg("%s: t_slot %p\n", __FUNCTION__, t_slot);
+
+	/*	Finish setting up the hot plug ctrl device */
+	ctrl->next_event = 0;
+
+	if (!pciehp_ctrl_list) {
+		pciehp_ctrl_list = ctrl;
+		ctrl->next = NULL;
+	} else {
+		ctrl->next = pciehp_ctrl_list;
+		pciehp_ctrl_list = ctrl;
+	}
+
+	/* Wait for exclusive access to hardware */
+	down(&ctrl->crit_sect);
+
+	t_slot->hpc_ops->get_adapter_status(t_slot, &value); /* Check if slot is occupied */
+	dbg("%s: adpater value %x\n", __FUNCTION__, value);
+	if (!value) {
+		rc = t_slot->hpc_ops->power_off_slot(t_slot); /* Power off slot if not occupied*/
+		if (rc) {
+			/* Done with exclusive hardware access */
+			up(&ctrl->crit_sect);
+			goto err_out_free_ctrl_slot;
+		} else
+			/* Wait for the command to complete */
+			wait_for_ctrl_irq (ctrl);
+	}
+
+	/* Done with exclusive hardware access */
+	up(&ctrl->crit_sect);
+
+	return 0;
+
+err_out_free_ctrl_slot:
+	cleanup_slots(ctrl);
+err_out_free_ctrl_bus:
+	kfree(ctrl->pci_bus);
+err_out_unmap_mmio_region:
+	ctrl->hpc_ops->release_ctlr(ctrl);
+err_out_free_ctrl:
+	kfree(ctrl);
+err_out_none:
+	return -ENODEV;
+}
+
+
+static int pcie_start_thread(void)
+{
+	int loop;
+	int retval = 0;
+	
+	dbg("Initialize + Start the notification/polling mechanism \n");
+
+	retval = pciehp_event_start_thread();
+	if (retval) {
+		dbg("pciehp_event_start_thread() failed\n");
+		return retval;
+	}
+
+	dbg("Initialize slot lists\n");
+	/* One slot list for each bus in the system */
+	for (loop = 0; loop < 256; loop++) {
+		pciehp_slot_list[loop] = NULL;
+	}
+
+	return retval;
+}
+
+
+static void unload_pciehpd(void)
+{
+	struct pci_func *next;
+	struct pci_func *TempSlot;
+	int loop;
+	struct controller *ctrl;
+	struct controller *tctrl;
+	struct pci_resource *res;
+	struct pci_resource *tres;
+
+	ctrl = pciehp_ctrl_list;
+
+	while (ctrl) {
+		cleanup_slots(ctrl);
+
+		res = ctrl->io_head;
+		while (res) {
+			tres = res;
+			res = res->next;
+			kfree(tres);
+		}
+
+		res = ctrl->mem_head;
+		while (res) {
+			tres = res;
+			res = res->next;
+			kfree(tres);
+		}
+
+		res = ctrl->p_mem_head;
+		while (res) {
+			tres = res;
+			res = res->next;
+			kfree(tres);
+		}
+
+		res = ctrl->bus_head;
+		while (res) {
+			tres = res;
+			res = res->next;
+			kfree(tres);
+		}
+
+		kfree (ctrl->pci_bus);
+
+		ctrl->hpc_ops->release_ctlr(ctrl);
+
+		tctrl = ctrl;
+		ctrl = ctrl->next;
+
+		kfree(tctrl);
+	}
+
+	for (loop = 0; loop < 256; loop++) {
+		next = pciehp_slot_list[loop];
+		while (next != NULL) {
+			res = next->io_head;
+			while (res) {
+				tres = res;
+				res = res->next;
+				kfree(tres);
+			}
+
+			res = next->mem_head;
+			while (res) {
+				tres = res;
+				res = res->next;
+				kfree(tres);
+			}
+
+			res = next->p_mem_head;
+			while (res) {
+				tres = res;
+				res = res->next;
+				kfree(tres);
+			}
+
+			res = next->bus_head;
+			while (res) {
+				tres = res;
+				res = res->next;
+				kfree(tres);
+			}
+
+			TempSlot = next;
+			next = next->next;
+			kfree(TempSlot);
+		}
+	}
+
+	/* Stop the notification mechanism */
+	pciehp_event_stop_thread();
+
+}
+
+
+static struct pci_device_id pcied_pci_tbl[] = {
+	{
+	.class =        ((PCI_CLASS_BRIDGE_PCI << 8) | 0x00),
+	.class_mask =	~0,
+	.vendor =       PCI_ANY_ID,
+	.device =       PCI_ANY_ID,
+	.subvendor =    PCI_ANY_ID,
+	.subdevice =    PCI_ANY_ID,
+	},
+	
+	{ /* end: all zeroes */ }
+};
+
+MODULE_DEVICE_TABLE(pci, pcied_pci_tbl);
+
+
+
+static struct pci_driver pcie_driver = {
+	.name		=	PCIE_MODULE_NAME,
+	.id_table	=	pcied_pci_tbl,
+	.probe		=	pcie_probe,
+	/* remove:	pcie_remove_one, */
+};
+
+
+
+static int __init pcied_init(void)
+{
+	int retval = 0;
+
+#ifdef CONFIG_HOTPLUG_PCI_PCIE_POLL_EVENT_MODE
+	pciehp_poll_mode = 1;
+#endif
+
+	retval = pcie_start_thread();
+	if (retval)
+		goto error_hpc_init;
+
+	retval = pciehprm_init(PCI);
+	if (!retval) {
+		retval = pci_module_init(&pcie_driver);
+		dbg("pci_module_init = %d\n", retval);
+		info(DRIVER_DESC " version: " DRIVER_VERSION "\n");
+	}
+
+error_hpc_init:
+	if (retval) {
+		pciehprm_cleanup();
+		pciehp_event_stop_thread();
+	} else
+		pciehprm_print_pirt();
+
+	return retval;
+}
+
+static void __exit pcied_cleanup(void)
+{
+	dbg("unload_pciehpd()\n");
+	unload_pciehpd();
+
+	pciehprm_cleanup();
+
+	dbg("pci_unregister_driver\n");
+	pci_unregister_driver(&pcie_driver);
+
+	info(DRIVER_DESC " version: " DRIVER_VERSION " unloaded\n");
+}
+
+
+module_init(pcied_init);
+module_exit(pcied_cleanup);
+
+
--- diff/drivers/pci/hotplug/pciehp_ctrl.c	1970-01-01 01:00:00.000000000 +0100
+++ source/drivers/pci/hotplug/pciehp_ctrl.c	2004-02-23 13:56:44.000000000 +0000
@@ -0,0 +1,2622 @@
+/*
+ * PCI Express Hot Plug Controller Driver
+ *
+ * Copyright (C) 1995,2001 Compaq Computer Corporation
+ * Copyright (C) 2001 Greg Kroah-Hartman (greg@kroah.com)
+ * Copyright (C) 2001 IBM Corp.
+ * Copyright (C) 2003-2004 Intel Corporation
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Send feedback to <greg@kroah.com>, <dely.l.sy@intel.com>
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/slab.h>
+#include <linux/workqueue.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/wait.h>
+#include <linux/smp_lock.h>
+#include <linux/pci.h>
+#include "pciehp.h"
+#include "pciehprm.h"
+
+static u32 configure_new_device(struct controller *ctrl, struct pci_func *func,
+	u8 behind_bridge, struct resource_lists *resources, u8 bridge_bus, u8 bridge_dev);
+static int configure_new_function( struct controller *ctrl, struct pci_func *func,
+	u8 behind_bridge, struct resource_lists *resources, u8 bridge_bus, u8 bridge_dev);
+static void interrupt_event_handler(struct controller *ctrl);
+
+static struct semaphore event_semaphore;	/* mutex for process loop (up if something to process) */
+static struct semaphore event_exit;		/* guard ensure thread has exited before calling it quits */
+static int event_finished;
+static unsigned long pushbutton_pending;	/* = 0 */
+
+u8 pciehp_handle_attention_button(u8 hp_slot, void *inst_id)
+{
+	struct controller *ctrl = (struct controller *) inst_id;
+	struct slot *p_slot;
+	u8 rc = 0;
+	u8 getstatus;
+	struct pci_func *func;
+	struct event_info *taskInfo;
+
+	/* Attention Button Change */
+	dbg("pciehp:  Attention button interrupt received.\n");
+	
+	func = pciehp_slot_find(ctrl->slot_bus, (hp_slot + ctrl->slot_device_offset), 0);
+
+	/* This is the structure that tells the worker thread what to do */
+	taskInfo = &(ctrl->event_queue[ctrl->next_event]);
+	p_slot = pciehp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset);
+
+	p_slot->hpc_ops->get_adapter_status(p_slot, &(func->presence_save));
+	p_slot->hpc_ops->get_latch_status(p_slot, &getstatus);
+	
+	ctrl->next_event = (ctrl->next_event + 1) % 10;
+	taskInfo->hp_slot = hp_slot;
+
+	rc++;
+
+	/*
+	 *  Button pressed - See if need to TAKE ACTION!!!
+	 */
+	info("Button pressed on Slot(%d)\n", ctrl->first_slot + hp_slot);
+	taskInfo->event_type = INT_BUTTON_PRESS;
+
+	if ((p_slot->state == BLINKINGON_STATE)
+	    || (p_slot->state == BLINKINGOFF_STATE)) {
+		/* Cancel if we are still blinking; this means that we press the
+		 * attention again before the 5 sec. limit expires to cancel hot-add
+		 * or hot-remove
+		 */
+		taskInfo->event_type = INT_BUTTON_CANCEL;
+		info("Button cancel on Slot(%d)\n", ctrl->first_slot + hp_slot);
+	} else if ((p_slot->state == POWERON_STATE)
+		   || (p_slot->state == POWEROFF_STATE)) {
+		/* Ignore if the slot is on power-on or power-off state; this 
+		 * means that the previous attention button action to hot-add or
+		 * hot-remove is undergoing
+		 */
+		taskInfo->event_type = INT_BUTTON_IGNORE;
+		info("Button ignore on Slot(%d)\n", ctrl->first_slot + hp_slot);
+	}
+
+	if (rc)
+		up(&event_semaphore);	/* signal event thread that new event is posted */
+
+	return 0;
+
+}
+
+u8 pciehp_handle_switch_change(u8 hp_slot, void *inst_id)
+{
+	struct controller *ctrl = (struct controller *) inst_id;
+	struct slot *p_slot;
+	u8 rc = 0;
+	u8 getstatus;
+	struct pci_func *func;
+	struct event_info *taskInfo;
+
+	/* Switch Change */
+	dbg("pciehp:  Switch interrupt received.\n");
+
+	func = pciehp_slot_find(ctrl->slot_bus, (hp_slot + ctrl->slot_device_offset), 0);
+
+	/* This is the structure that tells the worker thread
+	 * what to do
+	 */
+	taskInfo = &(ctrl->event_queue[ctrl->next_event]);
+	ctrl->next_event = (ctrl->next_event + 1) % 10;
+	taskInfo->hp_slot = hp_slot;
+
+	rc++;
+	p_slot = pciehp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset);
+	p_slot->hpc_ops->get_adapter_status(p_slot, &(func->presence_save));
+	p_slot->hpc_ops->get_latch_status(p_slot, &getstatus);
+
+	if (!getstatus) {
+		/*
+		 * Switch opened
+		 */
+		info("Latch open on Slot(%d)\n", ctrl->first_slot + hp_slot);
+		func->switch_save = 0;
+		taskInfo->event_type = INT_SWITCH_OPEN;
+	} else {
+		/*
+		 *  Switch closed
+		 */
+		info("Latch close on Slot(%d)\n", ctrl->first_slot + hp_slot);
+		func->switch_save = 0x10;
+		taskInfo->event_type = INT_SWITCH_CLOSE;
+	}
+
+	if (rc)
+		up(&event_semaphore);	/* signal event thread that new event is posted */
+
+	return rc;
+}
+
+u8 pciehp_handle_presence_change(u8 hp_slot, void *inst_id)
+{
+	struct controller *ctrl = (struct controller *) inst_id;
+	struct slot *p_slot;
+	u8 rc = 0;
+	struct pci_func *func;
+	struct event_info *taskInfo;
+
+	/* Presence Change */
+	dbg("pciehp:  Presence/Notify input change.\n");
+
+	func = pciehp_slot_find(ctrl->slot_bus, (hp_slot + ctrl->slot_device_offset), 0);
+
+	/* This is the structure that tells the worker thread
+	 * what to do
+	 */
+	taskInfo = &(ctrl->event_queue[ctrl->next_event]);
+	ctrl->next_event = (ctrl->next_event + 1) % 10;
+	taskInfo->hp_slot = hp_slot;
+
+	rc++;
+	p_slot = pciehp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset);
+
+	/* Switch is open, assume a presence change
+	 * Save the presence state
+	 */
+	p_slot->hpc_ops->get_adapter_status(p_slot, &(func->presence_save));
+	if (func->presence_save) {
+		/*
+		 * Card Present
+		 */
+		taskInfo->event_type = INT_PRESENCE_ON;
+	} else {
+		/*
+		 * Not Present
+		 */
+		taskInfo->event_type = INT_PRESENCE_OFF;
+	}
+
+	if (rc)
+		up(&event_semaphore);	/* signal event thread that new event is posted */
+
+	return rc;
+}
+
+u8 pciehp_handle_power_fault(u8 hp_slot, void *inst_id)
+{
+	struct controller *ctrl = (struct controller *) inst_id;
+	struct slot *p_slot;
+	u8 rc = 0;
+	struct pci_func *func;
+	struct event_info *taskInfo;
+
+	/* power fault */
+	dbg("pciehp:  Power fault interrupt received.\n");
+
+	func = pciehp_slot_find(ctrl->slot_bus, (hp_slot + ctrl->slot_device_offset), 0);
+
+	/* this is the structure that tells the worker thread
+	 * what to do
+	 */
+	taskInfo = &(ctrl->event_queue[ctrl->next_event]);
+	ctrl->next_event = (ctrl->next_event + 1) % 10;
+	taskInfo->hp_slot = hp_slot;
+
+	rc++;
+	p_slot = pciehp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset);
+
+	if ( !(p_slot->hpc_ops->query_power_fault(p_slot))) {
+		/*
+		 * power fault Cleared
+		 */
+		info("Power fault cleared on Slot(%d)\n", ctrl->first_slot + hp_slot);
+		func->status = 0x00;
+		taskInfo->event_type = INT_POWER_FAULT_CLEAR;
+	} else {
+		/*
+		 *   power fault
+		 */
+		info("Power fault on Slot(%d)\n", ctrl->first_slot + hp_slot);
+		taskInfo->event_type = INT_POWER_FAULT;
+		/* set power fault status for this board */
+		func->status = 0xFF;
+		info("power fault bit %x set\n", hp_slot);
+	}
+	if (rc)
+		up(&event_semaphore);	/* signal event thread that new event is posted */
+
+	return rc;
+}
+
+
+/*
+ * sort_by_size
+ *
+ * Sorts nodes on the list by their length.
+ * Smallest first.
+ *
+ */
+static int sort_by_size(struct pci_resource **head)
+{
+	struct pci_resource *current_res;
+	struct pci_resource *next_res;
+	int out_of_order = 1;
+
+	if (!(*head))
+		return(1);
+
+	if (!((*head)->next))
+		return(0);
+
+	while (out_of_order) {
+		out_of_order = 0;
+
+		/* Special case for swapping list head */
+		if (((*head)->next) &&
+		    ((*head)->length > (*head)->next->length)) {
+			out_of_order++;
+			current_res = *head;
+			*head = (*head)->next;
+			current_res->next = (*head)->next;
+			(*head)->next = current_res;
+		}
+
+		current_res = *head;
+
+		while (current_res->next && current_res->next->next) {
+			if (current_res->next->length > current_res->next->next->length) {
+				out_of_order++;
+				next_res = current_res->next;
+				current_res->next = current_res->next->next;
+				current_res = current_res->next;
+				next_res->next = current_res->next;
+				current_res->next = next_res;
+			} else
+				current_res = current_res->next;
+		}
+	}  /* End of out_of_order loop */
+
+	return(0);
+}
+
+
+/*
+ * sort_by_max_size
+ *
+ * Sorts nodes on the list by their length.
+ * Largest first.
+ *
+ */
+static int sort_by_max_size(struct pci_resource **head)
+{
+	struct pci_resource *current_res;
+	struct pci_resource *next_res;
+	int out_of_order = 1;
+
+	if (!(*head))
+		return(1);
+
+	if (!((*head)->next))
+		return(0);
+
+	while (out_of_order) {
+		out_of_order = 0;
+
+		/* Special case for swapping list head */
+		if (((*head)->next) &&
+		    ((*head)->length < (*head)->next->length)) {
+			out_of_order++;
+			current_res = *head;
+			*head = (*head)->next;
+			current_res->next = (*head)->next;
+			(*head)->next = current_res;
+		}
+
+		current_res = *head;
+
+		while (current_res->next && current_res->next->next) {
+			if (current_res->next->length < current_res->next->next->length) {
+				out_of_order++;
+				next_res = current_res->next;
+				current_res->next = current_res->next->next;
+				current_res = current_res->next;
+				next_res->next = current_res->next;
+				current_res->next = next_res;
+			} else
+				current_res = current_res->next;
+		}
+	}  /* End of out_of_order loop */
+
+	return(0);
+}
+
+
+/*
+ * do_pre_bridge_resource_split
+ *
+ *	Returns zero or one node of resources that aren't in use
+ *
+ */
+static struct pci_resource *do_pre_bridge_resource_split (struct pci_resource **head, struct pci_resource **orig_head, u32 alignment)
+{
+	struct pci_resource *prevnode = NULL;
+	struct pci_resource *node;
+	struct pci_resource *split_node;
+	u32 rc;
+	u32 temp_dword;
+	dbg("do_pre_bridge_resource_split\n");
+
+	if (!(*head) || !(*orig_head))
+		return(NULL);
+
+	rc = pciehp_resource_sort_and_combine(head);
+
+	if (rc)
+		return(NULL);
+
+	if ((*head)->base != (*orig_head)->base)
+		return(NULL);
+
+	if ((*head)->length == (*orig_head)->length)
+		return(NULL);
+
+
+	/* If we got here, there the bridge requires some of the resource, but
+	 *  we may be able to split some off of the front
+	 */	
+	node = *head;
+
+	if (node->length & (alignment -1)) {
+		/* this one isn't an aligned length, so we'll make a new entry
+		 * and split it up.
+		 */
+		split_node = (struct pci_resource*) kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
+
+		if (!split_node)
+			return(NULL);
+
+		temp_dword = (node->length | (alignment-1)) + 1 - alignment;
+
+		split_node->base = node->base;
+		split_node->length = temp_dword;
+
+		node->length -= temp_dword;
+		node->base += split_node->length;
+
+		/* Put it in the list */
+		*head = split_node;
+		split_node->next = node;
+	}
+
+	if (node->length < alignment) {
+		return(NULL);
+	}
+
+	/* Now unlink it */
+	if (*head == node) {
+		*head = node->next;
+		node->next = NULL;
+	} else {
+		prevnode = *head;
+		while (prevnode->next != node)
+			prevnode = prevnode->next;
+
+		prevnode->next = node->next;
+		node->next = NULL;
+	}
+
+	return(node);
+}
+
+
+/*
+ * do_bridge_resource_split
+ *
+ *	Returns zero or one node of resources that aren't in use
+ *
+ */
+static struct pci_resource *do_bridge_resource_split (struct pci_resource **head, u32 alignment)
+{
+	struct pci_resource *prevnode = NULL;
+	struct pci_resource *node;
+	u32 rc;
+	u32 temp_dword;
+
+	if (!(*head))
+		return(NULL);
+
+	rc = pciehp_resource_sort_and_combine(head);
+
+	if (rc)
+		return(NULL);
+
+	node = *head;
+
+	while (node->next) {
+		prevnode = node;
+		node = node->next;
+		kfree(prevnode);
+	}
+
+	if (node->length < alignment) {
+		kfree(node);
+		return(NULL);
+	}
+
+	if (node->base & (alignment - 1)) {
+		/* Short circuit if adjusted size is too small */
+		temp_dword = (node->base | (alignment-1)) + 1;
+		if ((node->length - (temp_dword - node->base)) < alignment) {
+			kfree(node);
+			return(NULL);
+		}
+
+		node->length -= (temp_dword - node->base);
+		node->base = temp_dword;
+	}
+
+	if (node->length & (alignment - 1)) {
+		/* There's stuff in use after this node */
+		kfree(node);
+		return(NULL);
+	}
+
+	return(node);
+}
+
+
+/*
+ * get_io_resource
+ *
+ * this function sorts the resource list by size and then
+ * returns the first node of "size" length that is not in the
+ * ISA aliasing window.  If it finds a node larger than "size"
+ * it will split it up.
+ *
+ * size must be a power of two.
+ */
+static struct pci_resource *get_io_resource (struct pci_resource **head, u32 size)
+{
+	struct pci_resource *prevnode;
+	struct pci_resource *node;
+	struct pci_resource *split_node = NULL;
+	u32 temp_dword;
+
+	if (!(*head))
+		return(NULL);
+
+	if ( pciehp_resource_sort_and_combine(head) )
+		return(NULL);
+
+	if ( sort_by_size(head) )
+		return(NULL);
+
+	for (node = *head; node; node = node->next) {
+		if (node->length < size)
+			continue;
+
+		if (node->base & (size - 1)) {
+			/* this one isn't base aligned properly
+			   so we'll make a new entry and split it up */
+			temp_dword = (node->base | (size-1)) + 1;
+
+			/*/ Short circuit if adjusted size is too small */
+			if ((node->length - (temp_dword - node->base)) < size)
+				continue;
+
+			split_node = (struct pci_resource*) kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
+
+			if (!split_node)
+				return(NULL);
+
+			split_node->base = node->base;
+			split_node->length = temp_dword - node->base;
+			node->base = temp_dword;
+			node->length -= split_node->length;
+
+			/* Put it in the list */
+			split_node->next = node->next;
+			node->next = split_node;
+		} /* End of non-aligned base */
+
+		/* Don't need to check if too small since we already did */
+		if (node->length > size) {
+			/* this one is longer than we need
+			   so we'll make a new entry and split it up */
+			split_node = (struct pci_resource*) kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
+
+			if (!split_node)
+				return(NULL);
+
+			split_node->base = node->base + size;
+			split_node->length = node->length - size;
+			node->length = size;
+
+			/* Put it in the list */
+			split_node->next = node->next;
+			node->next = split_node;
+		}  /* End of too big on top end */
+
+		/* For IO make sure it's not in the ISA aliasing space */
+		if (node->base & 0x300L)
+			continue;
+
+		/* If we got here, then it is the right size 
+		   Now take it out of the list */
+		if (*head == node) {
+			*head = node->next;
+		} else {
+			prevnode = *head;
+			while (prevnode->next != node)
+				prevnode = prevnode->next;
+
+			prevnode->next = node->next;
+		}
+		node->next = NULL;
+		/* Stop looping */
+		break;
+	}
+
+	return(node);
+}
+
+
+/*
+ * get_max_resource
+ *
+ * Gets the largest node that is at least "size" big from the
+ * list pointed to by head.  It aligns the node on top and bottom
+ * to "size" alignment before returning it.
+ * J.I. modified to put max size limits of; 64M->32M->16M->8M->4M->1M
+ *  This is needed to avoid allocating entire ACPI _CRS res to one child bridge/slot.
+ */
+static struct pci_resource *get_max_resource (struct pci_resource **head, u32 size)
+{
+	struct pci_resource *max;
+	struct pci_resource *temp;
+	struct pci_resource *split_node;
+	u32 temp_dword;
+	u32 max_size[] = { 0x4000000, 0x2000000, 0x1000000, 0x0800000, 0x0400000, 0x0200000, 0x0100000, 0x00 };
+	int i;
+
+	if (!(*head))
+		return(NULL);
+
+	if (pciehp_resource_sort_and_combine(head))
+		return(NULL);
+
+	if (sort_by_max_size(head))
+		return(NULL);
+
+	for (max = *head;max; max = max->next) {
+
+		/* If not big enough we could probably just bail, 
+		   instead we'll continue to the next. */
+		if (max->length < size)
+			continue;
+
+		if (max->base & (size - 1)) {
+			/* this one isn't base aligned properly
+			   so we'll make a new entry and split it up */
+			temp_dword = (max->base | (size-1)) + 1;
+
+			/* Short circuit if adjusted size is too small */
+			if ((max->length - (temp_dword - max->base)) < size)
+				continue;
+
+			split_node = (struct pci_resource*) kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
+
+			if (!split_node)
+				return(NULL);
+
+			split_node->base = max->base;
+			split_node->length = temp_dword - max->base;
+			max->base = temp_dword;
+			max->length -= split_node->length;
+
+			/* Put it next in the list */
+			split_node->next = max->next;
+			max->next = split_node;
+		}
+
+		if ((max->base + max->length) & (size - 1)) {
+			/* this one isn't end aligned properly at the top
+			   so we'll make a new entry and split it up */
+			split_node = (struct pci_resource*) kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
+
+			if (!split_node)
+				return(NULL);
+			temp_dword = ((max->base + max->length) & ~(size - 1));
+			split_node->base = temp_dword;
+			split_node->length = max->length + max->base
+					     - split_node->base;
+			max->length -= split_node->length;
+
+			/* Put it in the list */
+			split_node->next = max->next;
+			max->next = split_node;
+		}
+
+		/* Make sure it didn't shrink too much when we aligned it */
+		if (max->length < size)
+			continue;
+
+		for ( i = 0; max_size[i] > size; i++) {
+			if (max->length > max_size[i]) {
+				split_node = (struct pci_resource *) kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
+				if (!split_node)
+					break;	/* return (NULL); */
+				split_node->base = max->base + max_size[i];
+				split_node->length = max->length - max_size[i];
+				max->length = max_size[i];
+				/* Put it next in the list */
+				split_node->next = max->next;
+				max->next = split_node;
+				break;
+			}
+		}
+
+		/* Now take it out of the list */
+		temp = (struct pci_resource*) *head;
+		if (temp == max) {
+			*head = max->next;
+		} else {
+			while (temp && temp->next != max) {
+				temp = temp->next;
+			}
+
+			temp->next = max->next;
+		}
+
+		max->next = NULL;
+		return(max);
+	}
+
+	/* If we get here, we couldn't find one */
+	return(NULL);
+}
+
+
+/*
+ * get_resource
+ *
+ * this function sorts the resource list by size and then
+ * returns the first node of "size" length.  If it finds a node
+ * larger than "size" it will split it up.
+ *
+ * size must be a power of two.
+ */
+static struct pci_resource *get_resource (struct pci_resource **head, u32 size)
+{
+	struct pci_resource *prevnode;
+	struct pci_resource *node;
+	struct pci_resource *split_node;
+	u32 temp_dword;
+
+	if (!(*head))
+		return(NULL);
+
+	if ( pciehp_resource_sort_and_combine(head) )
+		return(NULL);
+
+	if ( sort_by_size(head) )
+		return(NULL);
+
+	for (node = *head; node; node = node->next) {
+		dbg("%s: req_size =0x%x node=%p, base=0x%x, length=0x%x\n",
+		    __FUNCTION__, size, node, node->base, node->length);
+		if (node->length < size)
+			continue;
+
+		if (node->base & (size - 1)) {
+			dbg("%s: not aligned\n", __FUNCTION__);
+			/* this one isn't base aligned properly
+			   so we'll make a new entry and split it up */
+			temp_dword = (node->base | (size-1)) + 1;
+
+			/* Short circuit if adjusted size is too small */
+			if ((node->length - (temp_dword - node->base)) < size)
+				continue;
+
+			split_node = (struct pci_resource*) kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
+
+			if (!split_node)
+				return(NULL);
+
+			split_node->base = node->base;
+			split_node->length = temp_dword - node->base;
+			node->base = temp_dword;
+			node->length -= split_node->length;
+
+			/* Put it in the list */
+			split_node->next = node->next;
+			node->next = split_node;
+		} /* End of non-aligned base */
+
+		/* Don't need to check if too small since we already did */
+		if (node->length > size) {
+			dbg("%s: too big\n", __FUNCTION__);
+			/* this one is longer than we need
+			   so we'll make a new entry and split it up */
+			split_node = (struct pci_resource*) kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
+
+			if (!split_node)
+				return(NULL);
+
+			split_node->base = node->base + size;
+			split_node->length = node->length - size;
+			node->length = size;
+
+			/* Put it in the list */
+			split_node->next = node->next;
+			node->next = split_node;
+		}  /* End of too big on top end */
+
+		dbg("%s: got one!!!\n", __FUNCTION__);
+		/* If we got here, then it is the right size
+		   Now take it out of the list */
+		if (*head == node) {
+			*head = node->next;
+		} else {
+			prevnode = *head;
+			while (prevnode->next != node)
+				prevnode = prevnode->next;
+
+			prevnode->next = node->next;
+		}
+		node->next = NULL;
+		/* Stop looping */
+		break;
+	}
+	return(node);
+}
+
+
+/*
+ * pciehp_resource_sort_and_combine
+ *
+ * Sorts all of the nodes in the list in ascending order by
+ * their base addresses.  Also does garbage collection by
+ * combining adjacent nodes.
+ *
+ * returns 0 if success
+ */
+int pciehp_resource_sort_and_combine(struct pci_resource **head)
+{
+	struct pci_resource *node1;
+	struct pci_resource *node2;
+	int out_of_order = 1;
+
+	dbg("%s: head = %p, *head = %p\n", __FUNCTION__, head, *head);
+
+	if (!(*head))
+		return(1);
+
+	dbg("*head->next = %p\n",(*head)->next);
+
+	if (!(*head)->next)
+		return(0);	/* only one item on the list, already sorted! */
+
+	dbg("*head->base = 0x%x\n",(*head)->base);
+	dbg("*head->next->base = 0x%x\n",(*head)->next->base);
+	while (out_of_order) {
+		out_of_order = 0;
+
+		/* Special case for swapping list head */
+		if (((*head)->next) &&
+		    ((*head)->base > (*head)->next->base)) {
+			node1 = *head;
+			(*head) = (*head)->next;
+			node1->next = (*head)->next;
+			(*head)->next = node1;
+			out_of_order++;
+		}
+
+		node1 = (*head);
+
+		while (node1->next && node1->next->next) {
+			if (node1->next->base > node1->next->next->base) {
+				out_of_order++;
+				node2 = node1->next;
+				node1->next = node1->next->next;
+				node1 = node1->next;
+				node2->next = node1->next;
+				node1->next = node2;
+			} else
+				node1 = node1->next;
+		}
+	}  /* End of out_of_order loop */
+
+	node1 = *head;
+
+	while (node1 && node1->next) {
+		if ((node1->base + node1->length) == node1->next->base) {
+			/* Combine */
+			dbg("8..\n");
+			node1->length += node1->next->length;
+			node2 = node1->next;
+			node1->next = node1->next->next;
+			kfree(node2);
+		} else
+			node1 = node1->next;
+	}
+
+	return(0);
+}
+
+
+/**
+ * pciehp_slot_create - Creates a node and adds it to the proper bus.
+ * @busnumber - bus where new node is to be located
+ *
+ * Returns pointer to the new node or NULL if unsuccessful
+ */
+struct pci_func *pciehp_slot_create(u8 busnumber)
+{
+	struct pci_func *new_slot;
+	struct pci_func *next;
+	dbg("%s: busnumber %x\n", __FUNCTION__, busnumber);
+	new_slot = (struct pci_func *) kmalloc(sizeof(struct pci_func), GFP_KERNEL);
+
+	if (new_slot == NULL) {
+		return(new_slot);
+	}
+
+	memset(new_slot, 0, sizeof(struct pci_func));
+
+	new_slot->next = NULL;
+	new_slot->configured = 1;
+
+	if (pciehp_slot_list[busnumber] == NULL) {
+		pciehp_slot_list[busnumber] = new_slot;
+	} else {
+		next = pciehp_slot_list[busnumber];
+		while (next->next != NULL)
+			next = next->next;
+		next->next = new_slot;
+	}
+	return(new_slot);
+}
+
+
+/*
+ * slot_remove - Removes a node from the linked list of slots.
+ * @old_slot: slot to remove
+ *
+ * Returns 0 if successful, !0 otherwise.
+ */
+static int slot_remove(struct pci_func * old_slot)
+{
+	struct pci_func *next;
+
+	if (old_slot == NULL)
+		return(1);
+
+	next = pciehp_slot_list[old_slot->bus];
+
+	if (next == NULL) {
+		return(1);
+	}
+
+	if (next == old_slot) {
+		pciehp_slot_list[old_slot->bus] = old_slot->next;
+		pciehp_destroy_board_resources(old_slot);
+		kfree(old_slot);
+		return(0);
+	}
+
+	while ((next->next != old_slot) && (next->next != NULL)) {
+		next = next->next;
+	}
+
+	if (next->next == old_slot) {
+		next->next = old_slot->next;
+		pciehp_destroy_board_resources(old_slot);
+		kfree(old_slot);
+		return(0);
+	} else
+		return(2);
+}
+
+
+/**
+ * bridge_slot_remove - Removes a node from the linked list of slots.
+ * @bridge: bridge to remove
+ *
+ * Returns 0 if successful, !0 otherwise.
+ */
+static int bridge_slot_remove(struct pci_func *bridge)
+{
+	u8 subordinateBus, secondaryBus;
+	u8 tempBus;
+	struct pci_func *next;
+
+	if (bridge == NULL)
+		return(1);
+
+	secondaryBus = (bridge->config_space[0x06] >> 8) & 0xFF;
+	subordinateBus = (bridge->config_space[0x06] >> 16) & 0xFF;
+
+	for (tempBus = secondaryBus; tempBus <= subordinateBus; tempBus++) {
+		next = pciehp_slot_list[tempBus];
+
+		while (!slot_remove(next)) {
+			next = pciehp_slot_list[tempBus];
+		}
+	}
+
+	next = pciehp_slot_list[bridge->bus];
+
+	if (next == NULL) {
+		return(1);
+	}
+
+	if (next == bridge) {
+		pciehp_slot_list[bridge->bus] = bridge->next;
+		kfree(bridge);
+		return(0);
+	}
+
+	while ((next->next != bridge) && (next->next != NULL)) {
+		next = next->next;
+	}
+
+	if (next->next == bridge) {
+		next->next = bridge->next;
+		kfree(bridge);
+		return(0);
+	} else
+		return(2);
+}
+
+
+/**
+ * pciehp_slot_find - Looks for a node by bus, and device, multiple functions accessed
+ * @bus: bus to find
+ * @device: device to find
+ * @index: is 0 for first function found, 1 for the second...
+ *
+ * Returns pointer to the node if successful, %NULL otherwise.
+ */
+struct pci_func *pciehp_slot_find(u8 bus, u8 device, u8 index)
+{
+	int found = -1;
+	struct pci_func *func;
+
+	func = pciehp_slot_list[bus];
+	dbg("%s: bus %x device %x index %x\n",
+		__FUNCTION__, bus, device, index);
+	if (func != NULL) {
+		dbg("%s: func-> bus %x device %x function %x pci_dev %p\n",
+			__FUNCTION__, func->bus, func->device, func->function,
+			func->pci_dev);
+	} else
+		dbg("%s: func == NULL\n", __FUNCTION__);
+
+	if ((func == NULL) || ((func->device == device) && (index == 0)))
+		return(func);
+
+	if (func->device == device)
+		found++;
+
+	while (func->next != NULL) {
+		func = func->next;
+
+		dbg("%s: In while loop, func-> bus %x device %x function %x pci_dev %p\n",
+			__FUNCTION__, func->bus, func->device, func->function,
+			func->pci_dev);
+		if (func->device == device)
+			found++;
+		dbg("%s: while loop, found %d, index %d\n", __FUNCTION__,
+			found, index);
+
+		if ((found == index) || (func->function == index)) {
+			dbg("%s: Found bus %x dev %x func %x\n", __FUNCTION__,
+					func->bus, func->device, func->function);
+			return(func);
+		}
+	}
+
+	return(NULL);
+}
+
+static int is_bridge(struct pci_func * func)
+{
+	/* Check the header type */
+	if (((func->config_space[0x03] >> 16) & 0xFF) == 0x01)
+		return 1;
+	else
+		return 0;
+}
+
+
+/* The following routines constitute the bulk of the 
+   hotplug controller logic
+ */
+
+
+/**
+ * board_added - Called after a board has been added to the system.
+ *
+ * Turns power on for the board
+ * Configures board
+ *
+ */
+static u32 board_added(struct pci_func * func, struct controller * ctrl)
+{
+	u8 hp_slot;
+	int index;
+	u32 temp_register = 0xFFFFFFFF;
+	u32 retval, rc = 0;
+	struct pci_func *new_func = NULL;
+	struct slot *p_slot;
+	struct resource_lists res_lists;
+
+	p_slot = pciehp_find_slot(ctrl, func->device);
+	hp_slot = func->device - ctrl->slot_device_offset;
+
+	dbg("%s: func->device, slot_offset, hp_slot = %d, %d ,%d\n", __FUNCTION__, func->device, ctrl->slot_device_offset, hp_slot);
+
+	/* Wait for exclusive access to hardware */
+	down(&ctrl->crit_sect);
+
+	/* Power on slot */
+	rc = p_slot->hpc_ops->power_on_slot(p_slot);
+	if (rc)
+		return -1;
+
+	/* Wait for the command to complete */
+	wait_for_ctrl_irq (ctrl);
+	
+	p_slot->hpc_ops->green_led_blink(p_slot);
+			
+	/* Wait for the command to complete */
+	wait_for_ctrl_irq (ctrl);
+
+	/* Done with exclusive hardware access */
+	up(&ctrl->crit_sect);
+
+	/* Wait for ~1 second */
+	dbg("%s: before long_delay\n", __FUNCTION__);
+	wait_for_ctrl_irq (ctrl);
+	dbg("%s: afterlong_delay\n", __FUNCTION__);
+
+	/*  Make this to check for link training status */
+	rc = p_slot->hpc_ops->check_lnk_status(ctrl);  
+	if (rc) {
+		err("%s: Failed to check link status\n", __FUNCTION__);
+		return -1;
+	}
+
+	dbg("%s: func status = %x\n", __FUNCTION__, func->status);
+
+	/* Check for a power fault */
+	if (func->status == 0xFF) {
+		/* power fault occurred, but it was benign */
+		temp_register = 0xFFFFFFFF;
+		dbg("%s: temp register set to %x by power fault\n", __FUNCTION__, temp_register);
+		rc = POWER_FAILURE;
+		func->status = 0;
+	} else {
+		/* Get vendor/device ID u32 */
+		rc = pci_bus_read_config_dword (ctrl->pci_dev->subordinate, PCI_DEVFN(func->device, func->function), 
+			PCI_VENDOR_ID, &temp_register);
+		dbg("%s: pci_bus_read_config_dword returns %d\n", __FUNCTION__, rc);
+		dbg("%s: temp_register is %x\n", __FUNCTION__, temp_register);
+
+		if (rc != 0) {
+			/* Something's wrong here */
+			temp_register = 0xFFFFFFFF;
+			dbg("%s: temp register set to %x by error\n", __FUNCTION__, temp_register);
+		}
+		/* Preset return code.  It will be changed later if things go okay. */
+		rc = NO_ADAPTER_PRESENT;
+	}
+
+	/* All F's is an empty slot or an invalid board */
+	if (temp_register != 0xFFFFFFFF) {	  /* Check for a board in the slot */
+		res_lists.io_head = ctrl->io_head;
+		res_lists.mem_head = ctrl->mem_head;
+		res_lists.p_mem_head = ctrl->p_mem_head;
+		res_lists.bus_head = ctrl->bus_head;
+		res_lists.irqs = NULL;
+
+		rc = configure_new_device(ctrl, func, 0, &res_lists, 0, 0);
+		dbg("%s: back from configure_new_device\n", __FUNCTION__);
+
+		ctrl->io_head = res_lists.io_head;
+		ctrl->mem_head = res_lists.mem_head;
+		ctrl->p_mem_head = res_lists.p_mem_head;
+		ctrl->bus_head = res_lists.bus_head;
+
+		pciehp_resource_sort_and_combine(&(ctrl->mem_head));
+		pciehp_resource_sort_and_combine(&(ctrl->p_mem_head));
+		pciehp_resource_sort_and_combine(&(ctrl->io_head));
+		pciehp_resource_sort_and_combine(&(ctrl->bus_head));
+
+		if (rc) {
+			/* Wait for exclusive access to hardware */
+			down(&ctrl->crit_sect);
+
+			/* turn off slot, turn on Amber LED, turn off Green LED */
+			retval = p_slot->hpc_ops->power_off_slot(p_slot);   
+			/* In PCI Express, just power off slot */
+			if (retval) {
+				err("%s: Issue of Slot Power Off command failed\n", __FUNCTION__);
+				return retval;
+			}
+			/* Wait for the command to complete */
+			wait_for_ctrl_irq (ctrl);
+
+			p_slot->hpc_ops->green_led_off(p_slot);   
+			
+			/* Wait for the command to complete */
+			wait_for_ctrl_irq (ctrl);
+
+			/* turn on Amber LED */
+			retval = p_slot->hpc_ops->set_attention_status(p_slot, 1);   
+			if (retval) {
+				err("%s: Issue of Set Attention Led command failed\n", __FUNCTION__);
+				return retval;
+			}
+			/* Wait for the command to complete */
+			wait_for_ctrl_irq (ctrl);
+
+			/* Done with exclusive hardware access */
+			up(&ctrl->crit_sect);
+
+			return(rc);
+		}
+		pciehp_save_slot_config(ctrl, func);
+
+		func->status = 0;
+		func->switch_save = 0x10;
+		func->is_a_board = 0x01;
+
+		/* next, we will instantiate the linux pci_dev structures 
+		 * (with appropriate driver notification, if already present) 
+		 */
+		index = 0;
+		do {
+			new_func = pciehp_slot_find(ctrl->slot_bus, func->device, index++);
+			if (new_func && !new_func->pci_dev) {
+				dbg("%s:call pci_hp_configure_dev, func %x\n", 
+					__FUNCTION__, index);
+				pciehp_configure_device(ctrl, new_func);
+			}
+		} while (new_func);
+
+		/* Wait for exclusive access to hardware */
+		down(&ctrl->crit_sect);
+
+		p_slot->hpc_ops->green_led_on(p_slot);
+
+		/* Wait for the command to complete */
+		wait_for_ctrl_irq (ctrl);
+
+
+		/* Done with exclusive hardware access */
+		up(&ctrl->crit_sect);
+
+	} else {
+		/* Wait for exclusive access to hardware */
+		down(&ctrl->crit_sect);
+
+		/* turn off slot, turn on Amber LED, turn off Green LED */
+		retval = p_slot->hpc_ops->power_off_slot(p_slot);   
+		/* In PCI Express, just power off slot */
+		if (retval) {
+			err("%s: Issue of Slot Power Off command failed\n", __FUNCTION__);
+			return retval;
+		}
+		/* Wait for the command to complete */
+		wait_for_ctrl_irq (ctrl);
+
+		p_slot->hpc_ops->green_led_off(p_slot);   
+		
+		/* Wait for the command to complete */
+		wait_for_ctrl_irq (ctrl);
+
+		/* turn on Amber LED */
+		retval = p_slot->hpc_ops->set_attention_status(p_slot, 1);   
+		if (retval) {
+			err("%s: Issue of Set Attention Led command failed\n", __FUNCTION__);
+			return retval;
+		}
+		/* Wait for the command to complete */
+		wait_for_ctrl_irq (ctrl);
+
+		/* Done with exclusive hardware access */
+		up(&ctrl->crit_sect);
+
+		return(rc);
+	}
+	return 0;
+}
+
+
+/**
+ * remove_board - Turns off slot and LED's
+ *
+ */
+static u32 remove_board(struct pci_func *func, struct controller *ctrl)
+{
+	int index;
+	u8 skip = 0;
+	u8 device;
+	u8 hp_slot;
+	u32 rc;
+	struct resource_lists res_lists;
+	struct pci_func *temp_func;
+	struct slot *p_slot;
+
+	if (func == NULL)
+		return(1);
+
+	if (pciehp_unconfigure_device(func))
+		return(1);
+
+	device = func->device;
+
+	hp_slot = func->device - ctrl->slot_device_offset;
+	p_slot = pciehp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset);
+
+	dbg("In %s, hp_slot = %d\n", __FUNCTION__, hp_slot);
+
+	if ((ctrl->add_support) &&
+		!(func->bus_head || func->mem_head || func->p_mem_head || func->io_head)) {
+		/* Here we check to see if we've saved any of the board's
+		 * resources already.  If so, we'll skip the attempt to
+		 * determine what's being used.
+		 */
+		index = 0;
+
+		temp_func = func;
+
+		while ((temp_func = pciehp_slot_find(temp_func->bus, temp_func->device, index++))) {
+			if (temp_func->bus_head || temp_func->mem_head
+			    || temp_func->p_mem_head || temp_func->io_head) {
+				skip = 1;
+				break;
+			}
+		}
+
+		if (!skip)
+			rc = pciehp_save_used_resources(ctrl, func, DISABLE_CARD);
+	}
+	/* Change status to shutdown */
+	if (func->is_a_board)
+		func->status = 0x01;
+	func->configured = 0;
+
+	/* Wait for exclusive access to hardware */
+	down(&ctrl->crit_sect);
+
+	/* power off slot */
+	rc = p_slot->hpc_ops->power_off_slot(p_slot);
+	if (rc) {
+		err("%s: Issue of Slot Disable command failed\n", __FUNCTION__);
+		return rc;
+	}
+	/* Wait for the command to complete */
+	wait_for_ctrl_irq (ctrl);
+
+	/* turn off Green LED */
+	p_slot->hpc_ops->green_led_off(p_slot);
+	
+	/* Wait for the command to complete */
+	wait_for_ctrl_irq (ctrl);
+
+	/* Done with exclusive hardware access */
+	up(&ctrl->crit_sect);
+
+	if (ctrl->add_support) {
+		while (func) {
+			res_lists.io_head = ctrl->io_head;
+			res_lists.mem_head = ctrl->mem_head;
+			res_lists.p_mem_head = ctrl->p_mem_head;
+			res_lists.bus_head = ctrl->bus_head;
+
+			dbg("Returning resources to ctlr lists for (B/D/F) = (%#x/%#x/%#x)\n", 
+				func->bus, func->device, func->function);
+
+			pciehp_return_board_resources(func, &res_lists);
+
+			ctrl->io_head = res_lists.io_head;
+			ctrl->mem_head = res_lists.mem_head;
+			ctrl->p_mem_head = res_lists.p_mem_head;
+			ctrl->bus_head = res_lists.bus_head;
+
+			pciehp_resource_sort_and_combine(&(ctrl->mem_head));
+			pciehp_resource_sort_and_combine(&(ctrl->p_mem_head));
+			pciehp_resource_sort_and_combine(&(ctrl->io_head));
+			pciehp_resource_sort_and_combine(&(ctrl->bus_head));
+
+			if (is_bridge(func)) {
+				dbg("PCI Bridge Hot-Remove s:b:d:f(%02x:%02x:%02x:%02x)\n", 
+					ctrl->seg, func->bus, func->device, func->function);
+				bridge_slot_remove(func);
+			} else
+				dbg("PCI Function Hot-Remove s:b:d:f(%02x:%02x:%02x:%02x)\n", 
+					ctrl->seg, func->bus, func->device, func->function);
+				slot_remove(func);
+
+			func = pciehp_slot_find(ctrl->slot_bus, device, 0);
+		}
+
+		/* Setup slot structure with entry for empty slot */
+		func = pciehp_slot_create(ctrl->slot_bus);
+
+		if (func == NULL) {
+			return(1);
+		}
+
+		func->bus = ctrl->slot_bus;
+		func->device = device;
+		func->function = 0;
+		func->configured = 0;
+		func->switch_save = 0x10;
+		func->is_a_board = 0;
+	}
+
+	return 0;
+}
+
+
+static void pushbutton_helper_thread (unsigned long data)
+{
+	pushbutton_pending = data;
+
+	up(&event_semaphore);
+}
+
+
+/* this is the main worker thread */
+static int event_thread(void* data)
+{
+	struct controller *ctrl;
+	lock_kernel();
+	daemonize("pciehpd_event");
+
+	unlock_kernel();
+
+	while (1) {
+		dbg("!!!!event_thread sleeping\n");
+		down_interruptible (&event_semaphore);
+		dbg("event_thread woken finished = %d\n", event_finished);
+		if (event_finished || signal_pending(current))
+			break;
+		/* Do stuff here */
+		if (pushbutton_pending)
+			pciehp_pushbutton_thread(pushbutton_pending);
+		else
+			for (ctrl = pciehp_ctrl_list; ctrl; ctrl=ctrl->next)
+				interrupt_event_handler(ctrl);
+	}
+	dbg("event_thread signals exit\n");
+	up(&event_exit);
+	return 0;
+}
+
+int pciehp_event_start_thread (void)
+{
+	int pid;
+
+	/* initialize our semaphores */
+	init_MUTEX_LOCKED(&event_exit);
+	event_finished=0;
+
+	init_MUTEX_LOCKED(&event_semaphore);
+	pid = kernel_thread(event_thread, 0, 0);
+
+	if (pid < 0) {
+		err ("Can't start up our event thread\n");
+		return -1;
+	}
+	dbg("Our event thread pid = %d\n", pid);
+	return 0;
+}
+
+
+void pciehp_event_stop_thread (void)
+{
+	event_finished = 1;
+	dbg("event_thread finish command given\n");
+	up(&event_semaphore);
+	dbg("wait for event_thread to exit\n");
+	down(&event_exit);
+}
+
+
+static int update_slot_info (struct slot *slot)
+{
+	struct hotplug_slot_info *info;
+	/* char buffer[SLOT_NAME_SIZE]; */
+	int result;
+
+	info = kmalloc (sizeof (struct hotplug_slot_info), GFP_KERNEL);
+	if (!info)
+		return -ENOMEM;
+
+	/* make_slot_name (&buffer[0], SLOT_NAME_SIZE, slot); */
+
+	slot->hpc_ops->get_power_status(slot, &(info->power_status));
+	slot->hpc_ops->get_attention_status(slot, &(info->attention_status));
+	slot->hpc_ops->get_latch_status(slot, &(info->latch_status));
+	slot->hpc_ops->get_adapter_status(slot, &(info->adapter_status));
+
+	/* result = pci_hp_change_slot_info(buffer, info); */
+	result = pci_hp_change_slot_info(slot->hotplug_slot, info);
+	kfree (info);
+	return result;
+}
+
+static void interrupt_event_handler(struct controller *ctrl)
+{
+	int loop = 0;
+	int change = 1;
+	struct pci_func *func;
+	u8 hp_slot;
+	u8 getstatus;
+	struct slot *p_slot;
+
+	while (change) {
+		change = 0;
+
+		for (loop = 0; loop < 10; loop++) {
+			if (ctrl->event_queue[loop].event_type != 0) {
+				hp_slot = ctrl->event_queue[loop].hp_slot;
+
+				func = pciehp_slot_find(ctrl->slot_bus, (hp_slot + ctrl->slot_device_offset), 0);
+
+				p_slot = pciehp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset);
+
+				dbg("hp_slot %d, func %p, p_slot %p\n", hp_slot, func, p_slot);
+
+				if (ctrl->event_queue[loop].event_type == INT_BUTTON_CANCEL) {
+					dbg("button cancel\n");
+					del_timer(&p_slot->task_event);
+
+					switch (p_slot->state) {
+					case BLINKINGOFF_STATE:
+						/* Wait for exclusive access to hardware */
+						down(&ctrl->crit_sect);
+
+						p_slot->hpc_ops->green_led_on(p_slot);
+						/* Wait for the command to complete */
+						wait_for_ctrl_irq (ctrl);
+
+						p_slot->hpc_ops->set_attention_status(p_slot, 0);
+
+						/* Wait for the command to complete */
+						wait_for_ctrl_irq (ctrl);
+
+						/* Done with exclusive hardware access */
+						up(&ctrl->crit_sect);
+						break;
+					case BLINKINGON_STATE:
+						/* Wait for exclusive access to hardware */
+						down(&ctrl->crit_sect);
+
+						p_slot->hpc_ops->green_led_off(p_slot);
+						/* Wait for the command to complete */
+						wait_for_ctrl_irq (ctrl);
+
+						p_slot->hpc_ops->set_attention_status(p_slot, 0);
+						/* Wait for the command to complete */
+						wait_for_ctrl_irq (ctrl);
+
+						/* Done with exclusive hardware access */
+						up(&ctrl->crit_sect);
+
+						break;
+					default:
+						warn("Not a valid state\n");
+						return;
+					}
+					info(msg_button_cancel, p_slot->number);
+					p_slot->state = STATIC_STATE;
+				}
+				/* ***********Button Pressed (No action on 1st press...) */
+				else if (ctrl->event_queue[loop].event_type == INT_BUTTON_PRESS) {
+					dbg("Button pressed\n");
+
+					p_slot->hpc_ops->get_power_status(p_slot, &getstatus);
+					if (getstatus) {
+						/* slot is on */
+						dbg("slot is on\n");
+						p_slot->state = BLINKINGOFF_STATE;
+						info(msg_button_off, p_slot->number);
+					} else {
+						/* slot is off */
+						dbg("slot is off\n");
+						p_slot->state = BLINKINGON_STATE;
+						info(msg_button_on, p_slot->number);
+					}
+
+					/* Wait for exclusive access to hardware */
+					down(&ctrl->crit_sect);
+
+					/* blink green LED and turn off amber */
+					p_slot->hpc_ops->green_led_blink(p_slot);
+					/* Wait for the command to complete */
+					wait_for_ctrl_irq (ctrl);
+					
+					p_slot->hpc_ops->set_attention_status(p_slot, 0);
+
+					/* Wait for the command to complete */
+					wait_for_ctrl_irq (ctrl);
+
+					/* Done with exclusive hardware access */
+					up(&ctrl->crit_sect);
+
+					init_timer(&p_slot->task_event);
+					p_slot->task_event.expires = jiffies + 5 * HZ;   /* 5 second delay */
+					p_slot->task_event.function = (void (*)(unsigned long)) pushbutton_helper_thread;
+					p_slot->task_event.data = (unsigned long) p_slot;
+
+					dbg("add_timer p_slot = %p\n", (void *) p_slot);
+					add_timer(&p_slot->task_event);
+				}
+				/***********POWER FAULT********************/
+				else if (ctrl->event_queue[loop].event_type == INT_POWER_FAULT) {
+					dbg("power fault\n");
+					/* Wait for exclusive access to hardware */
+					down(&ctrl->crit_sect);
+
+					p_slot->hpc_ops->set_attention_status(p_slot, 1);
+					p_slot->hpc_ops->green_led_off(p_slot);
+
+					/* Done with exclusive hardware access */
+					up(&ctrl->crit_sect);
+				} else {
+					/* refresh notification */
+					if (p_slot)
+						update_slot_info(p_slot);
+				}
+
+				ctrl->event_queue[loop].event_type = 0;
+
+				change = 1;
+			}
+		}		/* End of FOR loop */
+	}
+
+	return;
+}
+
+
+/**
+ * pciehp_pushbutton_thread
+ *
+ * Scheduled procedure to handle blocking stuff for the pushbuttons
+ * Handles all pending events and exits.
+ *
+ */
+void pciehp_pushbutton_thread (unsigned long slot)
+{
+	struct slot *p_slot = (struct slot *) slot;
+	u8 getstatus;
+	int rc;
+	
+	pushbutton_pending = 0;
+
+	if (!p_slot) {
+		dbg("%s: Error! slot NULL\n", __FUNCTION__);
+		return;
+	}
+
+	p_slot->hpc_ops->get_power_status(p_slot, &getstatus);
+	if (getstatus) {
+		p_slot->state = POWEROFF_STATE;
+		dbg("In power_down_board, b:d(%x:%x)\n", p_slot->bus, p_slot->device);
+
+		if (pciehp_disable_slot(p_slot)) {
+			/* Wait for exclusive access to hardware */
+			down(&p_slot->ctrl->crit_sect);
+
+			/* Turn on the Attention LED */
+			rc = p_slot->hpc_ops->set_attention_status(p_slot, 1);
+			if (rc) {
+				err("%s: Issue of Set Atten Indicator On command failed\n", __FUNCTION__);
+				return;
+			}
+	
+			/* Wait for the command to complete */
+			wait_for_ctrl_irq (p_slot->ctrl);
+
+			/* Done with exclusive hardware access */
+			up(&p_slot->ctrl->crit_sect);
+		}
+		p_slot->state = STATIC_STATE;
+	} else {
+		p_slot->state = POWERON_STATE;
+		dbg("In add_board, b:d(%x:%x)\n", p_slot->bus, p_slot->device);
+
+		if (pciehp_enable_slot(p_slot)) {
+			/* Wait for exclusive access to hardware */
+			down(&p_slot->ctrl->crit_sect);
+
+			/* Turn off the green LED */
+			rc = p_slot->hpc_ops->set_attention_status(p_slot, 1);
+			if (rc) {
+				err("%s: Issue of Set Atten Indicator On command failed\n", __FUNCTION__);
+				return;
+			}
+			/* Wait for the command to complete */
+			wait_for_ctrl_irq (p_slot->ctrl);
+			
+			p_slot->hpc_ops->green_led_off(p_slot);
+
+			/* Wait for the command to complete */
+			wait_for_ctrl_irq (p_slot->ctrl);
+
+			/* Done with exclusive hardware access */
+			up(&p_slot->ctrl->crit_sect);
+		}
+		p_slot->state = STATIC_STATE;
+	}
+
+	return;
+}
+
+
+int pciehp_enable_slot (struct slot *p_slot)
+{
+	u8 getstatus = 0;
+	int rc;
+	struct pci_func *func;
+
+	func = pciehp_slot_find(p_slot->bus, p_slot->device, 0);
+	if (!func) {
+		dbg("%s: Error! slot NULL\n", __FUNCTION__);
+		return (1);
+	}
+
+	/* Check to see if (latch closed, card present, power off) */
+	down(&p_slot->ctrl->crit_sect);
+	rc = p_slot->hpc_ops->get_adapter_status(p_slot, &getstatus);
+	if (rc || !getstatus) {
+		info("%s: no adapter on slot(%x)\n", __FUNCTION__, p_slot->number);
+		up(&p_slot->ctrl->crit_sect);
+		return (0);
+	}
+	
+	rc = p_slot->hpc_ops->get_latch_status(p_slot, &getstatus);
+	if (rc || !getstatus) {
+		info("%s: latch open on slot(%x)\n", __FUNCTION__, p_slot->number);
+		up(&p_slot->ctrl->crit_sect);
+		return (0);
+	}
+	
+	rc = p_slot->hpc_ops->get_power_status(p_slot, &getstatus);
+	if (rc || getstatus) {
+		info("%s: already enabled on slot(%x)\n", __FUNCTION__, p_slot->number);
+		up(&p_slot->ctrl->crit_sect);
+		return (0);
+	}
+	up(&p_slot->ctrl->crit_sect);
+
+	slot_remove(func);
+
+	func = pciehp_slot_create(p_slot->bus);
+	if (func == NULL)
+		return (1);
+
+	func->bus = p_slot->bus;
+	func->device = p_slot->device;
+	func->function = 0;
+	func->configured = 0;
+	func->is_a_board = 1;
+
+	/* We have to save the presence info for these slots */
+	p_slot->hpc_ops->get_adapter_status(p_slot, &(func->presence_save));
+	p_slot->hpc_ops->get_latch_status(p_slot, &getstatus);
+	func->switch_save = !getstatus? 0x10:0;
+
+	rc = board_added(func, p_slot->ctrl);
+	if (rc) {
+		if (is_bridge(func))
+			bridge_slot_remove(func);
+		else
+			slot_remove(func);
+
+		/* Setup slot structure with entry for empty slot */
+		func = pciehp_slot_create(p_slot->bus);
+		if (func == NULL)
+			return (1);	/* Out of memory */
+
+		func->bus = p_slot->bus;
+		func->device = p_slot->device;
+		func->function = 0;
+		func->configured = 0;
+		func->is_a_board = 1;
+
+		/* We have to save the presence info for these slots */
+		p_slot->hpc_ops->get_adapter_status(p_slot, &(func->presence_save));
+		p_slot->hpc_ops->get_latch_status(p_slot, &getstatus);
+		func->switch_save = !getstatus? 0x10:0;
+	}
+
+	if (p_slot)
+		update_slot_info(p_slot);
+
+	return rc;
+}
+
+
+int pciehp_disable_slot (struct slot *p_slot)
+{
+	u8 class_code, header_type, BCR;
+	u8 index = 0;
+	u8 getstatus = 0;
+	u32 rc = 0;
+	int ret = 0;
+	unsigned int devfn;
+	struct pci_bus *pci_bus = p_slot->ctrl->pci_dev->subordinate;
+	struct pci_func *func;
+
+	if (!p_slot->ctrl)
+		return (1);
+
+	/* Check to see if (latch closed, card present, power on) */
+	down(&p_slot->ctrl->crit_sect);
+
+	ret = p_slot->hpc_ops->get_adapter_status(p_slot, &getstatus);
+	if (ret || !getstatus) {
+		info("%s: no adapter on slot(%x)\n", __FUNCTION__, p_slot->number);
+		up(&p_slot->ctrl->crit_sect);
+		return (0);
+	}
+
+	ret = p_slot->hpc_ops->get_latch_status(p_slot, &getstatus);
+	if (ret || !getstatus) {
+		info("%s: latch open on slot(%x)\n", __FUNCTION__, p_slot->number);
+		up(&p_slot->ctrl->crit_sect);
+		return (0);
+	}
+
+	ret = p_slot->hpc_ops->get_power_status(p_slot, &getstatus);
+	if (ret || !getstatus) {
+		info("%s: already disabled slot(%x)\n", __FUNCTION__, p_slot->number);
+		up(&p_slot->ctrl->crit_sect);
+		return (0);
+	}
+	up(&p_slot->ctrl->crit_sect);
+
+	func = pciehp_slot_find(p_slot->bus, p_slot->device, index++);
+
+	/* Make sure there are no video controllers here
+	 * for all func of p_slot
+	 */
+	while (func && !rc) {
+		pci_bus->number = func->bus;
+		devfn = PCI_DEVFN(func->device, func->function);
+
+		/* Check the Class Code */
+		rc = pci_bus_read_config_byte (pci_bus, devfn, 0x0B, &class_code);
+		if (rc)
+			return rc;
+
+		if (class_code == PCI_BASE_CLASS_DISPLAY) {
+			/* Display/Video adapter (not supported) */
+			rc = REMOVE_NOT_SUPPORTED;
+		} else {
+			/* See if it's a bridge */
+			rc = pci_bus_read_config_byte (pci_bus, devfn, PCI_HEADER_TYPE, &header_type);
+			if (rc)
+				return rc;
+
+			/* If it's a bridge, check the VGA Enable bit */
+			if ((header_type & 0x7F) == PCI_HEADER_TYPE_BRIDGE) {
+				rc = pci_bus_read_config_byte (pci_bus, devfn, PCI_BRIDGE_CONTROL, &BCR);
+				if (rc)
+					return rc;
+
+				/* If the VGA Enable bit is set, remove isn't supported */
+				if (BCR & PCI_BRIDGE_CTL_VGA) {
+					rc = REMOVE_NOT_SUPPORTED;
+				}
+			}
+		}
+
+		func = pciehp_slot_find(p_slot->bus, p_slot->device, index++);
+	}
+
+	func = pciehp_slot_find(p_slot->bus, p_slot->device, 0);
+	if ((func != NULL) && !rc) {
+		rc = remove_board(func, p_slot->ctrl);
+	} else if (!rc)
+		rc = 1;
+
+	if (p_slot)
+		update_slot_info(p_slot);
+
+	return(rc);
+}
+
+
+/**
+ * configure_new_device - Configures the PCI header information of one board.
+ *
+ * @ctrl: pointer to controller structure
+ * @func: pointer to function structure
+ * @behind_bridge: 1 if this is a recursive call, 0 if not
+ * @resources: pointer to set of resource lists
+ *
+ * Returns 0 if success
+ *
+ */
+static u32 configure_new_device (struct controller * ctrl, struct pci_func * func,
+	u8 behind_bridge, struct resource_lists * resources, u8 bridge_bus, u8 bridge_dev)
+{
+	u8 temp_byte, function, max_functions, stop_it;
+	int rc;
+	u32 ID;
+	struct pci_func *new_slot;
+	struct pci_bus lpci_bus, *pci_bus;
+	int index;
+
+	new_slot = func;
+
+	dbg("%s\n", __FUNCTION__);
+	memcpy(&lpci_bus, ctrl->pci_dev->subordinate, sizeof(lpci_bus));
+	pci_bus = &lpci_bus;
+	pci_bus->number = func->bus;
+
+	/* Check for Multi-function device */
+	rc = pci_bus_read_config_byte(pci_bus, PCI_DEVFN(func->device, func->function), 0x0E, &temp_byte);
+	if (rc) {
+		dbg("%s: rc = %d\n", __FUNCTION__, rc);
+		return rc;
+	}
+
+	if (temp_byte & 0x80)	/* Multi-function device */
+		max_functions = 8;
+	else
+		max_functions = 1;
+
+	function = 0;
+
+	do {
+		rc = configure_new_function(ctrl, new_slot, behind_bridge, resources, bridge_bus, bridge_dev);
+
+		if (rc) {
+			dbg("configure_new_function failed %d\n",rc);
+			index = 0;
+
+			while (new_slot) {
+				new_slot = pciehp_slot_find(new_slot->bus, new_slot->device, index++);
+
+				if (new_slot)
+					pciehp_return_board_resources(new_slot, resources);
+			}
+
+			return(rc);
+		}
+
+		function++;
+
+		stop_it = 0;
+
+		/*  The following loop skips to the next present function
+		 *  and creates a board structure
+		 */
+
+		while ((function < max_functions) && (!stop_it)) {
+			pci_bus_read_config_dword(pci_bus, PCI_DEVFN(func->device, function), 0x00, &ID);
+
+			if (ID == 0xFFFFFFFF) {	  /* There's nothing there. */
+				function++;
+			} else {  /* There's something there */
+				/* Setup slot structure. */
+				new_slot = pciehp_slot_create(func->bus);
+
+				if (new_slot == NULL) {
+					/* Out of memory */
+					return(1);
+				}
+
+				new_slot->bus = func->bus;
+				new_slot->device = func->device;
+				new_slot->function = function;
+				new_slot->is_a_board = 1;
+				new_slot->status = 0;
+
+				stop_it++;
+			}
+		}
+
+	} while (function < max_functions);
+	dbg("returning from configure_new_device\n");
+
+	return 0;
+}
+
+
+/*
+ * Configuration logic that involves the hotplug data structures and 
+ * their bookkeeping
+ */
+
+
+/**
+ * configure_new_function - Configures the PCI header information of one device
+ *
+ * @ctrl: pointer to controller structure
+ * @func: pointer to function structure
+ * @behind_bridge: 1 if this is a recursive call, 0 if not
+ * @resources: pointer to set of resource lists
+ *
+ * Calls itself recursively for bridged devices.
+ * Returns 0 if success
+ *
+ */
+static int configure_new_function (struct controller * ctrl, struct pci_func * func,
+	u8 behind_bridge, struct resource_lists *resources, u8 bridge_bus, u8 bridge_dev)
+{
+	int cloop;
+	u8 temp_byte;
+	u8 device;
+	u8 class_code;
+	u16 temp_word;
+	u32 rc;
+	u32 temp_register;
+	u32 base;
+	u32 ID;
+	unsigned int devfn;
+	struct pci_resource *mem_node;
+	struct pci_resource *p_mem_node;
+	struct pci_resource *io_node;
+	struct pci_resource *bus_node;
+	struct pci_resource *hold_mem_node;
+	struct pci_resource *hold_p_mem_node;
+	struct pci_resource *hold_IO_node;
+	struct pci_resource *hold_bus_node;
+	struct irq_mapping irqs;
+	struct pci_func *new_slot;
+	struct pci_bus lpci_bus, *pci_bus;
+	struct resource_lists temp_resources;
+
+	memcpy(&lpci_bus, ctrl->pci_dev->subordinate, sizeof(lpci_bus));
+	pci_bus = &lpci_bus;
+	pci_bus->number = func->bus;
+	devfn = PCI_DEVFN(func->device, func->function);
+
+	/* Check for Bridge */
+	rc = pci_bus_read_config_byte (pci_bus, devfn, PCI_HEADER_TYPE, &temp_byte);
+	if (rc)
+		return rc;
+	dbg("%s: bus %x dev %x func %x temp_byte = %x\n", __FUNCTION__,
+		func->bus, func->device, func->function, temp_byte);
+
+	if ((temp_byte & 0x7F) == PCI_HEADER_TYPE_BRIDGE) { /* PCI-PCI Bridge */
+		/* set Primary bus */
+		dbg("set Primary bus = 0x%x\n", func->bus);
+		rc = pci_bus_write_config_byte(pci_bus, devfn, PCI_PRIMARY_BUS, func->bus);
+		if (rc)
+			return rc;
+
+		/* find range of busses to use */
+		bus_node = get_max_resource(&resources->bus_head, 1L);
+
+		/* If we don't have any busses to allocate, we can't continue */
+		if (!bus_node) {
+			err("Got NO bus resource to use\n");
+			return -ENOMEM;
+		}
+		dbg("Got ranges of buses to use: base:len=0x%x:%x\n", bus_node->base, bus_node->length);
+
+		/* set Secondary bus */
+		dbg("set Secondary bus = 0x%x\n", temp_byte);
+		dbg("func->bus %x\n", func->bus);
+
+		temp_byte = (u8)bus_node->base;
+		dbg("set Secondary bus = 0x%x\n", temp_byte);
+		rc = pci_bus_write_config_byte(pci_bus, devfn, PCI_SECONDARY_BUS, temp_byte);
+		if (rc)
+			return rc;
+
+		/* set subordinate bus */
+		temp_byte = (u8)(bus_node->base + bus_node->length - 1);
+		dbg("set subordinate bus = 0x%x\n", temp_byte);
+		rc = pci_bus_write_config_byte (pci_bus, devfn, PCI_SUBORDINATE_BUS, temp_byte);
+		if (rc)
+			return rc;
+
+		/* Set HP parameters (Cache Line Size, Latency Timer) */
+		rc = pciehprm_set_hpp(ctrl, func, PCI_HEADER_TYPE_BRIDGE);
+		if (rc)
+			return rc;
+
+		/* Setup the IO, memory, and prefetchable windows */
+
+		io_node = get_max_resource(&(resources->io_head), 0x1000L);
+		if (io_node) {
+			dbg("io_node(base, len, next) (%x, %x, %p)\n", io_node->base, io_node->length, io_node->next);
+		}
+
+		mem_node = get_max_resource(&(resources->mem_head), 0x100000L);
+		if (mem_node) {
+			dbg("mem_node(base, len, next) (%x, %x, %p)\n", mem_node->base, mem_node->length, mem_node->next);
+		}
+
+		if (resources->p_mem_head)
+			p_mem_node = get_max_resource(&(resources->p_mem_head), 0x100000L);
+		else {
+			/*
+			 * In some platform implementation, MEM and PMEM are not
+			 *  distinguished, and hence ACPI _CRS has only MEM entries
+			 *  for both MEM and PMEM.
+			 */
+			dbg("using MEM for PMEM\n");
+			p_mem_node = get_max_resource(&(resources->mem_head), 0x100000L);
+		}
+		if (p_mem_node) {
+			dbg("p_mem_node(base, len, next) (%x, %x, %p)\n", p_mem_node->base, p_mem_node->length, p_mem_node->next);
+		}
+
+		/* set up the IRQ info */
+		if (!resources->irqs) {
+			irqs.barber_pole = 0;
+			irqs.interrupt[0] = 0;
+			irqs.interrupt[1] = 0;
+			irqs.interrupt[2] = 0;
+			irqs.interrupt[3] = 0;
+			irqs.valid_INT = 0;
+		} else {
+			irqs.barber_pole = resources->irqs->barber_pole;
+			irqs.interrupt[0] = resources->irqs->interrupt[0];
+			irqs.interrupt[1] = resources->irqs->interrupt[1];
+			irqs.interrupt[2] = resources->irqs->interrupt[2];
+			irqs.interrupt[3] = resources->irqs->interrupt[3];
+			irqs.valid_INT = resources->irqs->valid_INT;
+		}
+
+		/* set up resource lists that are now aligned on top and bottom
+		 * for anything behind the bridge.
+		 */
+		temp_resources.bus_head = bus_node;
+		temp_resources.io_head = io_node;
+		temp_resources.mem_head = mem_node;
+		temp_resources.p_mem_head = p_mem_node;
+		temp_resources.irqs = &irqs;
+
+		/* Make copies of the nodes we are going to pass down so that
+		 * if there is a problem,we can just use these to free resources
+		 */
+		hold_bus_node = (struct pci_resource *) kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
+		hold_IO_node = (struct pci_resource *) kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
+		hold_mem_node = (struct pci_resource *) kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
+		hold_p_mem_node = (struct pci_resource *) kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
+
+		if (!hold_bus_node || !hold_IO_node || !hold_mem_node || !hold_p_mem_node) {
+			if (hold_bus_node)
+				kfree(hold_bus_node);
+			if (hold_IO_node)
+				kfree(hold_IO_node);
+			if (hold_mem_node)
+				kfree(hold_mem_node);
+			if (hold_p_mem_node)
+				kfree(hold_p_mem_node);
+
+			return(1);
+		}
+
+		memcpy(hold_bus_node, bus_node, sizeof(struct pci_resource));
+
+		bus_node->base += 1;
+		bus_node->length -= 1;
+		bus_node->next = NULL;
+
+		/* If we have IO resources copy them and fill in the bridge's
+		 * IO range registers
+		 */
+		if (io_node) {
+			memcpy(hold_IO_node, io_node, sizeof(struct pci_resource));
+			io_node->next = NULL;
+
+			/* set IO base and Limit registers */
+			RES_CHECK(io_node->base, 8);
+			temp_byte = (u8)(io_node->base >> 8);
+			rc = pci_bus_write_config_byte (pci_bus, devfn, PCI_IO_BASE, temp_byte);
+
+			RES_CHECK(io_node->base + io_node->length - 1, 8);
+			temp_byte = (u8)((io_node->base + io_node->length - 1) >> 8);
+			rc = pci_bus_write_config_byte (pci_bus, devfn, PCI_IO_LIMIT, temp_byte);
+		} else {
+			kfree(hold_IO_node);
+			hold_IO_node = NULL;
+		}
+
+		/* If we have memory resources copy them and fill in the bridge's
+		 * memory range registers.  Otherwise, fill in the range
+		 * registers with values that disable them.
+		 */
+		if (mem_node) {
+			memcpy(hold_mem_node, mem_node, sizeof(struct pci_resource));
+			mem_node->next = NULL;
+
+			/* set Mem base and Limit registers */
+			RES_CHECK(mem_node->base, 16);
+			temp_word = (u32)(mem_node->base >> 16);
+			rc = pci_bus_write_config_word (pci_bus, devfn, PCI_MEMORY_BASE, temp_word);
+
+			RES_CHECK(mem_node->base + mem_node->length - 1, 16);
+			temp_word = (u32)((mem_node->base + mem_node->length - 1) >> 16);
+			rc = pci_bus_write_config_word (pci_bus, devfn, PCI_MEMORY_LIMIT, temp_word);
+		} else {
+			temp_word = 0xFFFF;
+			rc = pci_bus_write_config_word (pci_bus, devfn, PCI_MEMORY_BASE, temp_word);
+
+			temp_word = 0x0000;
+			rc = pci_bus_write_config_word (pci_bus, devfn, PCI_MEMORY_LIMIT, temp_word);
+
+			kfree(hold_mem_node);
+			hold_mem_node = NULL;
+		}
+
+		/* If we have prefetchable memory resources copy them and 
+		 * fill in the bridge's memory range registers.  Otherwise,
+		 * fill in the range registers with values that disable them.
+		 */
+		if (p_mem_node) {
+			memcpy(hold_p_mem_node, p_mem_node, sizeof(struct pci_resource));
+			p_mem_node->next = NULL;
+
+			/* set Pre Mem base and Limit registers */
+			RES_CHECK(p_mem_node->base, 16);
+			temp_word = (u32)(p_mem_node->base >> 16);
+			rc = pci_bus_write_config_word (pci_bus, devfn, PCI_PREF_MEMORY_BASE, temp_word);
+
+			RES_CHECK(p_mem_node->base + p_mem_node->length - 1, 16);
+			temp_word = (u32)((p_mem_node->base + p_mem_node->length - 1) >> 16);
+			rc = pci_bus_write_config_word (pci_bus, devfn, PCI_PREF_MEMORY_LIMIT, temp_word);
+		} else {
+			temp_word = 0xFFFF;
+			rc = pci_bus_write_config_word (pci_bus, devfn, PCI_PREF_MEMORY_BASE, temp_word);
+
+			temp_word = 0x0000;
+			rc = pci_bus_write_config_word (pci_bus, devfn, PCI_PREF_MEMORY_LIMIT, temp_word);
+
+			kfree(hold_p_mem_node);
+			hold_p_mem_node = NULL;
+		}
+
+		/* Adjust this to compensate for extra adjustment in first loop */
+		irqs.barber_pole--;
+
+		rc = 0;
+
+		/* Here we actually find the devices and configure them */
+		for (device = 0; (device <= 0x1F) && !rc; device++) {
+			irqs.barber_pole = (irqs.barber_pole + 1) & 0x03;
+
+			ID = 0xFFFFFFFF;
+			pci_bus->number = hold_bus_node->base;
+			pci_bus_read_config_dword (pci_bus, PCI_DEVFN(device, 0), PCI_VENDOR_ID, &ID);
+			pci_bus->number = func->bus;
+
+			if (ID != 0xFFFFFFFF) {	  /*  device Present */
+				/* Setup slot structure. */
+				new_slot = pciehp_slot_create(hold_bus_node->base);
+
+				if (new_slot == NULL) {
+					/* Out of memory */
+					rc = -ENOMEM;
+					continue;
+				}
+
+				new_slot->bus = hold_bus_node->base;
+				new_slot->device = device;
+				new_slot->function = 0;
+				new_slot->is_a_board = 1;
+				new_slot->status = 0;
+
+				rc = configure_new_device(ctrl, new_slot, 1, &temp_resources, func->bus, func->device);
+				dbg("configure_new_device rc=0x%x\n",rc);
+			}	/* End of IF (device in slot?) */
+		}		/* End of FOR loop */
+
+		if (rc) {
+			pciehp_destroy_resource_list(&temp_resources);
+
+			return_resource(&(resources->bus_head), hold_bus_node);
+			return_resource(&(resources->io_head), hold_IO_node);
+			return_resource(&(resources->mem_head), hold_mem_node);
+			return_resource(&(resources->p_mem_head), hold_p_mem_node);
+			return(rc);
+		}
+
+		/* save the interrupt routing information */
+		if (resources->irqs) {
+			resources->irqs->interrupt[0] = irqs.interrupt[0];
+			resources->irqs->interrupt[1] = irqs.interrupt[1];
+			resources->irqs->interrupt[2] = irqs.interrupt[2];
+			resources->irqs->interrupt[3] = irqs.interrupt[3];
+			resources->irqs->valid_INT = irqs.valid_INT;
+		} else if (!behind_bridge) {
+			/* We need to hook up the interrupts here */
+			for (cloop = 0; cloop < 4; cloop++) {
+				if (irqs.valid_INT & (0x01 << cloop)) {
+					rc = pciehp_set_irq(func->bus, func->device,
+							   0x0A + cloop, irqs.interrupt[cloop]);
+					if (rc) {
+						pciehp_destroy_resource_list (&temp_resources);
+						return_resource(&(resources->bus_head), hold_bus_node);
+						return_resource(&(resources->io_head), hold_IO_node);
+						return_resource(&(resources->mem_head), hold_mem_node);
+						return_resource(&(resources->p_mem_head), hold_p_mem_node);
+						return rc;
+					}
+				}
+			}	/* end of for loop */
+		}
+
+		/* Return unused bus resources
+		 * First use the temporary node to store information for the board
+		 */
+		if (hold_bus_node && bus_node && temp_resources.bus_head) {
+			hold_bus_node->length = bus_node->base - hold_bus_node->base;
+
+			hold_bus_node->next = func->bus_head;
+			func->bus_head = hold_bus_node;
+
+			temp_byte = (u8)(temp_resources.bus_head->base - 1);
+
+			/* set subordinate bus */
+			dbg("re-set subordinate bus = 0x%x\n", temp_byte);
+			rc = pci_bus_write_config_byte (pci_bus, devfn, PCI_SUBORDINATE_BUS, temp_byte);
+
+			if (temp_resources.bus_head->length == 0) {
+				kfree(temp_resources.bus_head);
+				temp_resources.bus_head = NULL;
+			} else {
+				dbg("return bus res of b:d(0x%x:%x) base:len(0x%x:%x)\n",
+					func->bus, func->device, temp_resources.bus_head->base, temp_resources.bus_head->length);
+				return_resource(&(resources->bus_head), temp_resources.bus_head);
+			}
+		}
+
+		/* If we have IO space available and there is some left,
+		 * return the unused portion
+		 */
+		if (hold_IO_node && temp_resources.io_head) {
+			io_node = do_pre_bridge_resource_split(&(temp_resources.io_head),
+							       &hold_IO_node, 0x1000);
+
+			/* Check if we were able to split something off */
+			if (io_node) {
+				hold_IO_node->base = io_node->base + io_node->length;
+
+				RES_CHECK(hold_IO_node->base, 8);
+				temp_byte = (u8)((hold_IO_node->base) >> 8);
+				rc = pci_bus_write_config_byte (pci_bus, devfn, PCI_IO_BASE, temp_byte);
+
+				return_resource(&(resources->io_head), io_node);
+			}
+
+			io_node = do_bridge_resource_split(&(temp_resources.io_head), 0x1000);
+
+			/*  Check if we were able to split something off */
+			if (io_node) {
+				/* First use the temporary node to store information for the board */
+				hold_IO_node->length = io_node->base - hold_IO_node->base;
+
+				/* If we used any, add it to the board's list */
+				if (hold_IO_node->length) {
+					hold_IO_node->next = func->io_head;
+					func->io_head = hold_IO_node;
+
+					RES_CHECK(io_node->base - 1, 8);
+					temp_byte = (u8)((io_node->base - 1) >> 8);
+					rc = pci_bus_write_config_byte (pci_bus, devfn, PCI_IO_LIMIT, temp_byte);
+
+					return_resource(&(resources->io_head), io_node);
+				} else {
+					/* it doesn't need any IO */
+					temp_byte = 0x00;
+					rc = pci_bus_write_config_byte(pci_bus, devfn, PCI_IO_LIMIT, temp_byte);
+
+					return_resource(&(resources->io_head), io_node);
+					kfree(hold_IO_node);
+				}
+			} else {
+				/* it used most of the range */
+				hold_IO_node->next = func->io_head;
+				func->io_head = hold_IO_node;
+			}
+		} else if (hold_IO_node) {
+			/* it used the whole range */
+			hold_IO_node->next = func->io_head;
+			func->io_head = hold_IO_node;
+		}
+
+		/* If we have memory space available and there is some left,
+		 * return the unused portion
+		 */
+		if (hold_mem_node && temp_resources.mem_head) {
+			mem_node = do_pre_bridge_resource_split(&(temp_resources.mem_head), &hold_mem_node, 0x100000L);
+
+			/* Check if we were able to split something off */
+			if (mem_node) {
+				hold_mem_node->base = mem_node->base + mem_node->length;
+
+				RES_CHECK(hold_mem_node->base, 16);
+				temp_word = (u32)((hold_mem_node->base) >> 16);
+				rc = pci_bus_write_config_word (pci_bus, devfn, PCI_MEMORY_BASE, temp_word);
+
+				return_resource(&(resources->mem_head), mem_node);
+			}
+
+			mem_node = do_bridge_resource_split(&(temp_resources.mem_head), 0x100000L);
+
+			/* Check if we were able to split something off */
+			if (mem_node) {
+				/* First use the temporary node to store information for the board */
+				hold_mem_node->length = mem_node->base - hold_mem_node->base;
+
+				if (hold_mem_node->length) {
+					hold_mem_node->next = func->mem_head;
+					func->mem_head = hold_mem_node;
+
+					/* configure end address */
+					RES_CHECK(mem_node->base - 1, 16);
+					temp_word = (u32)((mem_node->base - 1) >> 16);
+					rc = pci_bus_write_config_word (pci_bus, devfn, PCI_MEMORY_LIMIT, temp_word);
+
+					/* Return unused resources to the pool */
+					return_resource(&(resources->mem_head), mem_node);
+				} else {
+					/* it doesn't need any Mem */
+					temp_word = 0x0000;
+					rc = pci_bus_write_config_word (pci_bus, devfn, PCI_MEMORY_LIMIT, temp_word);
+
+					return_resource(&(resources->mem_head), mem_node);
+					kfree(hold_mem_node);
+				}
+			} else {
+				/* it used most of the range */
+				hold_mem_node->next = func->mem_head;
+				func->mem_head = hold_mem_node;
+			}
+		} else if (hold_mem_node) {
+			/* it used the whole range */
+			hold_mem_node->next = func->mem_head;
+			func->mem_head = hold_mem_node;
+		}
+
+		/* If we have prefetchable memory space available and there is some 
+		 * left at the end, return the unused portion
+		 */
+		if (hold_p_mem_node && temp_resources.p_mem_head) {
+			p_mem_node = do_pre_bridge_resource_split(&(temp_resources.p_mem_head),
+								  &hold_p_mem_node, 0x100000L);
+
+			/* Check if we were able to split something off */
+			if (p_mem_node) {
+				hold_p_mem_node->base = p_mem_node->base + p_mem_node->length;
+
+				RES_CHECK(hold_p_mem_node->base, 16);
+				temp_word = (u32)((hold_p_mem_node->base) >> 16);
+				rc = pci_bus_write_config_word (pci_bus, devfn, PCI_PREF_MEMORY_BASE, temp_word);
+
+				return_resource(&(resources->p_mem_head), p_mem_node);
+			}
+
+			p_mem_node = do_bridge_resource_split(&(temp_resources.p_mem_head), 0x100000L);
+
+			/* Check if we were able to split something off */
+			if (p_mem_node) {
+				/* First use the temporary node to store information for the board */
+				hold_p_mem_node->length = p_mem_node->base - hold_p_mem_node->base;
+
+				/* If we used any, add it to the board's list */
+				if (hold_p_mem_node->length) {
+					hold_p_mem_node->next = func->p_mem_head;
+					func->p_mem_head = hold_p_mem_node;
+
+					RES_CHECK(p_mem_node->base - 1, 16);
+					temp_word = (u32)((p_mem_node->base - 1) >> 16);
+					rc = pci_bus_write_config_word (pci_bus, devfn, PCI_PREF_MEMORY_LIMIT, temp_word);
+
+					return_resource(&(resources->p_mem_head), p_mem_node);
+				} else {
+					/* it doesn't need any PMem */
+					temp_word = 0x0000;
+					rc = pci_bus_write_config_word (pci_bus, devfn, PCI_PREF_MEMORY_LIMIT, temp_word);
+
+					return_resource(&(resources->p_mem_head), p_mem_node);
+					kfree(hold_p_mem_node);
+				}
+			} else {
+				/* it used the most of the range */
+				hold_p_mem_node->next = func->p_mem_head;
+				func->p_mem_head = hold_p_mem_node;
+			}
+		} else if (hold_p_mem_node) {
+			/* it used the whole range */
+			hold_p_mem_node->next = func->p_mem_head;
+			func->p_mem_head = hold_p_mem_node;
+		}
+
+		/* We should be configuring an IRQ and the bridge's base address
+		 * registers if it needs them.  Although we have never seen such
+		 * a device
+		 */
+
+		pciehprm_enable_card(ctrl, func, PCI_HEADER_TYPE_BRIDGE);
+
+		dbg("PCI Bridge Hot-Added s:b:d:f(%02x:%02x:%02x:%02x)\n", ctrl->seg, func->bus, func->device, func->function);
+	} else if ((temp_byte & 0x7F) == PCI_HEADER_TYPE_NORMAL) {
+		/* Standard device */
+		u64	base64;
+		rc = pci_bus_read_config_byte (pci_bus, devfn, 0x0B, &class_code);
+
+		if (class_code == PCI_BASE_CLASS_DISPLAY)
+			return (DEVICE_TYPE_NOT_SUPPORTED);
+
+		/* Figure out IO and memory needs */
+		for (cloop = PCI_BASE_ADDRESS_0; cloop <= PCI_BASE_ADDRESS_5; cloop += 4) {
+			temp_register = 0xFFFFFFFF;
+
+			rc = pci_bus_write_config_dword (pci_bus, devfn, cloop, temp_register);
+			rc = pci_bus_read_config_dword(pci_bus, devfn, cloop, &temp_register);
+			dbg("Bar[%x]=0x%x on bus:dev:func(0x%x:%x:%x)\n", cloop, temp_register, 
+				func->bus, func->device, func->function);
+
+			if (!temp_register)
+				continue;
+
+			base64 = 0L;
+			if (temp_register & PCI_BASE_ADDRESS_SPACE_IO) {
+				/* Map IO */
+
+				/* set base = amount of IO space */
+				base = temp_register & 0xFFFFFFFC;
+				base = ~base + 1;
+
+				dbg("NEED IO length(0x%x)\n", base);
+				io_node = get_io_resource(&(resources->io_head),(ulong)base);
+
+				/* allocate the resource to the board */
+				if (io_node) {
+					dbg("Got IO base=0x%x(length=0x%x)\n", io_node->base, io_node->length);
+					base = (u32)io_node->base;
+					io_node->next = func->io_head;
+					func->io_head = io_node;
+				} else {
+					err("Got NO IO resource(length=0x%x)\n", base);
+					return -ENOMEM;
+				}
+			} else {	/* map MEM */
+				int prefetchable = 1;
+				struct pci_resource **res_node = &func->p_mem_head;
+				char *res_type_str = "PMEM";
+				u32	temp_register2;
+
+				if (!(temp_register & PCI_BASE_ADDRESS_MEM_PREFETCH)) {
+					prefetchable = 0;
+					res_node = &func->mem_head;
+					res_type_str++;
+				}
+
+				base = temp_register & 0xFFFFFFF0;
+				base = ~base + 1;
+
+				switch (temp_register & PCI_BASE_ADDRESS_MEM_TYPE_MASK) {
+				case PCI_BASE_ADDRESS_MEM_TYPE_32:
+					dbg("NEED 32 %s bar=0x%x(length=0x%x)\n", res_type_str, temp_register, base);
+
+					if (prefetchable && resources->p_mem_head)
+						mem_node=get_resource(&(resources->p_mem_head), (ulong)base);
+					else {
+						if (prefetchable)
+							dbg("using MEM for PMEM\n");
+						mem_node=get_resource(&(resources->mem_head), (ulong)base);
+					}
+
+					/* allocate the resource to the board */
+					if (mem_node) {
+						base = (u32)mem_node->base; 
+						mem_node->next = *res_node;
+						*res_node = mem_node;
+						dbg("Got 32 %s base=0x%x(length=0x%x)\n", res_type_str, mem_node->base, 
+							mem_node->length);
+					} else {
+						err("Got NO 32 %s resource(length=0x%x)\n", res_type_str, base);
+						return -ENOMEM;
+					}
+					break;
+				case PCI_BASE_ADDRESS_MEM_TYPE_64:
+					rc = pci_bus_read_config_dword(pci_bus, devfn, cloop+4, &temp_register2);
+					dbg("NEED 64 %s bar=0x%x:%x(length=0x%x)\n", res_type_str, temp_register2, 
+						temp_register, base);
+
+					if (prefetchable && resources->p_mem_head)
+						mem_node = get_resource(&(resources->p_mem_head), (ulong)base);
+					else {
+						if (prefetchable)
+							dbg("using MEM for PMEM\n");
+						mem_node = get_resource(&(resources->mem_head), (ulong)base);
+					}
+
+					/* allocate the resource to the board */
+					if (mem_node) {
+						base64 = mem_node->base; 
+						mem_node->next = *res_node;
+						*res_node = mem_node;
+						dbg("Got 64 %s base=0x%x:%x(length=%x)\n", res_type_str, (u32)(base64 >> 32), 
+							(u32)base64, mem_node->length);
+					} else {
+						err("Got NO 64 %s resource(length=0x%x)\n", res_type_str, base);
+						return -ENOMEM;
+					}
+					break;
+				default:
+					dbg("reserved BAR type=0x%x\n", temp_register);
+					break;
+				}
+
+			}
+
+			if (base64) {
+				rc = pci_bus_write_config_dword(pci_bus, devfn, cloop, (u32)base64);
+				cloop += 4;
+				base64 >>= 32;
+
+				if (base64) {
+					dbg("%s: high dword of base64(0x%x) set to 0\n", __FUNCTION__, (u32)base64);
+					base64 = 0x0L;
+				}
+
+				rc = pci_bus_write_config_dword(pci_bus, devfn, cloop, (u32)base64);
+			} else {
+				rc = pci_bus_write_config_dword(pci_bus, devfn, cloop, base);
+			}
+		}		/* End of base register loop */
+
+		/* disable ROM base Address */
+		temp_word = 0x00L;
+		rc = pci_bus_write_config_word (pci_bus, devfn, PCI_ROM_ADDRESS, temp_word);
+
+		/* Set HP parameters (Cache Line Size, Latency Timer) */
+		rc = pciehprm_set_hpp(ctrl, func, PCI_HEADER_TYPE_NORMAL);
+		if (rc)
+			return rc;
+
+		pciehprm_enable_card(ctrl, func, PCI_HEADER_TYPE_NORMAL);
+
+		dbg("PCI function Hot-Added s:b:d:f(%02x:%02x:%02x:%02x)\n", ctrl->seg, func->bus, func->device, 
+			func->function);
+	}  /* End of Not-A-Bridge else */
+	else {
+		/* It's some strange type of PCI adapter (Cardbus?) */
+		return(DEVICE_TYPE_NOT_SUPPORTED);
+	}
+
+	func->configured = 1;
+
+	return 0;
+}
+
--- diff/drivers/pci/hotplug/pciehp_hpc.c	1970-01-01 01:00:00.000000000 +0100
+++ source/drivers/pci/hotplug/pciehp_hpc.c	2004-02-23 13:56:44.000000000 +0000
@@ -0,0 +1,1436 @@
+/*
+ * PCI Express PCI Hot Plug Driver
+ *
+ * Copyright (C) 1995,2001 Compaq Computer Corporation
+ * Copyright (C) 2001 Greg Kroah-Hartman (greg@kroah.com)
+ * Copyright (C) 2001 IBM Corp.
+ * Copyright (C) 2003-2004 Intel Corporation
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Send feedback to <greg@kroah.com>,<dely.l.sy@intel.com>
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/slab.h>
+#include <linux/vmalloc.h>
+#include <linux/interrupt.h>
+#include <linux/spinlock.h>
+#include <linux/pci.h>
+#include <asm/system.h>
+#include "pciehp.h"
+
+#ifdef DEBUG
+#define DBG_K_TRACE_ENTRY      ((unsigned int)0x00000001)	/* On function entry */
+#define DBG_K_TRACE_EXIT       ((unsigned int)0x00000002)	/* On function exit */
+#define DBG_K_INFO             ((unsigned int)0x00000004)	/* Info messages */
+#define DBG_K_ERROR            ((unsigned int)0x00000008)	/* Error messages */
+#define DBG_K_TRACE            (DBG_K_TRACE_ENTRY|DBG_K_TRACE_EXIT)
+#define DBG_K_STANDARD         (DBG_K_INFO|DBG_K_ERROR|DBG_K_TRACE)
+/* Redefine this flagword to set debug level */
+#define DEBUG_LEVEL            DBG_K_STANDARD
+
+#define DEFINE_DBG_BUFFER     char __dbg_str_buf[256];
+
+#define DBG_PRINT( dbg_flags, args... )              \
+	do {                                             \
+	  if ( DEBUG_LEVEL & ( dbg_flags ) )             \
+	  {                                              \
+	    int len;                                     \
+	    len = sprintf( __dbg_str_buf, "%s:%d: %s: ", \
+		  __FILE__, __LINE__, __FUNCTION__ );    \
+	    sprintf( __dbg_str_buf + len, args );        \
+	    printk( KERN_NOTICE "%s\n", __dbg_str_buf ); \
+	  }                                              \
+	} while (0)
+
+#define DBG_ENTER_ROUTINE	DBG_PRINT (DBG_K_TRACE_ENTRY, "%s", "[Entry]");
+#define DBG_LEAVE_ROUTINE	DBG_PRINT (DBG_K_TRACE_EXIT, "%s", "[Exit]");
+#else
+#define DEFINE_DBG_BUFFER
+#define DBG_ENTER_ROUTINE
+#define DBG_LEAVE_ROUTINE
+#endif				/* DEBUG */
+
+struct ctrl_reg {
+	u8 cap_id;
+	u8 nxt_ptr;
+	u16 cap_reg;
+	u32 dev_cap;
+	u16 dev_ctrl;
+	u16 dev_status;
+	u32 lnk_cap;
+	u16 lnk_ctrl;
+	u16 lnk_status;
+	u32 slot_cap;
+	u16 slot_ctrl;
+	u16 slot_status;
+	u16 root_ctrl;
+	u16 rsvp;
+	u32 root_status;
+} __attribute__ ((packed));
+
+/* offsets to the controller registers based on the above structure layout */
+enum ctrl_offsets {
+	PCIECAPID	=	offsetof(struct ctrl_reg, cap_id),
+	NXTCAPPTR	=	offsetof(struct ctrl_reg, nxt_ptr),
+	CAPREG		=	offsetof(struct ctrl_reg, cap_reg),
+	DEVCAP		=	offsetof(struct ctrl_reg, dev_cap),
+	DEVCTRL		=	offsetof(struct ctrl_reg, dev_ctrl),
+	DEVSTATUS	=	offsetof(struct ctrl_reg, dev_status),
+	LNKCAP		=	offsetof(struct ctrl_reg, lnk_cap),
+	LNKCTRL		=	offsetof(struct ctrl_reg, lnk_ctrl),
+	LNKSTATUS	=	offsetof(struct ctrl_reg, lnk_status),
+	SLOTCAP		=	offsetof(struct ctrl_reg, slot_cap),
+	SLOTCTRL	=	offsetof(struct ctrl_reg, slot_ctrl),
+	SLOTSTATUS	=	offsetof(struct ctrl_reg, slot_status),
+	ROOTCTRL	=	offsetof(struct ctrl_reg, root_ctrl),
+	ROOTSTATUS	=	offsetof(struct ctrl_reg, root_status),
+};
+static int pcie_cap_base = 0;		/* Base of the PCI Express capability item structure */ 
+
+#define PCIE_CAP_ID	( pcie_cap_base + PCIECAPID )
+#define NXT_CAP_PTR	( pcie_cap_base + NXTCAPPTR )
+#define CAP_REG		( pcie_cap_base + CAPREG )
+#define DEV_CAP		( pcie_cap_base + DEVCAP )
+#define DEV_CTRL	( pcie_cap_base + DEVCTRL )
+#define DEV_STATUS	( pcie_cap_base + DEVSTATUS )
+#define LNK_CAP		( pcie_cap_base + LNKCAP )
+#define LNK_CTRL	( pcie_cap_base + LNKCTRL )
+#define LNK_STATUS	( pcie_cap_base + LNKSTATUS )
+#define SLOT_CAP	( pcie_cap_base + SLOTCAP )
+#define SLOT_CTRL	( pcie_cap_base + SLOTCTRL )
+#define SLOT_STATUS	( pcie_cap_base + SLOTSTATUS )
+#define ROOT_CTRL	( pcie_cap_base + ROOTCTRL )
+#define ROOT_STATUS	( pcie_cap_base + ROOTSTATUS )
+
+#define hp_register_read_word(pdev, reg , value)		\
+	pci_read_config_word(pdev, reg, &value)
+
+#define hp_register_read_dword(pdev, reg , value)		\
+	pci_read_config_dword(pdev, reg, &value)
+ 
+#define hp_register_write_word(pdev, reg , value)		\
+	pci_write_config_word(pdev, reg, value)
+
+#define hp_register_dwrite_word(pdev, reg , value)		\
+	pci_write_config_dword(pdev, reg, value)
+
+/* Field definitions in PCI Express Capabilities Register */
+#define CAP_VER			0x000F
+#define DEV_PORT_TYPE		0x00F0
+#define SLOT_IMPL		0x0100
+#define MSG_NUM			0x3E00
+
+/* Device or Port Type */
+#define NAT_ENDPT		0x00
+#define LEG_ENDPT		0x01
+#define ROOT_PORT		0x04
+#define UP_STREAM		0x05
+#define	DN_STREAM		0x06
+#define PCIE_PCI_BRDG		0x07
+#define PCI_PCIE_BRDG		0x10
+
+/* Field definitions in Device Capabilities Register */
+#define DATTN_BUTTN_PRSN	0x1000
+#define DATTN_LED_PRSN		0x2000
+#define DPWR_LED_PRSN		0x4000
+
+/* Field definitions in Link Capabilities Register */
+#define MAX_LNK_SPEED		0x000F
+#define MAX_LNK_WIDTH		0x03F0
+
+/* Link Width Encoding */
+#define LNK_X1		0x01
+#define LNK_X2		0x02
+#define LNK_X4		0x04	
+#define LNK_X8		0x08
+#define LNK_X12		0x0C
+#define LNK_X16		0x10	
+#define LNK_X32		0x20
+
+/*Field definitions of Link Status Register */
+#define LNK_SPEED	0x000F
+#define NEG_LINK_WD	0x03F0
+#define LNK_TRN_ERR	0x0400
+#define	LNK_TRN		0x0800
+#define SLOT_CLK_CONF	0x1000
+
+/* Field definitions in Slot Capabilities Register */
+#define ATTN_BUTTN_PRSN	0x00000001
+#define	PWR_CTRL_PRSN	0x00000002
+#define MRL_SENS_PRSN	0x00000004
+#define ATTN_LED_PRSN	0x00000008
+#define PWR_LED_PRSN	0x00000010
+#define HP_SUPR_RM	0x00000020
+#define HP_CAP		0x00000040
+#define SLOT_PWR_VALUE	0x000003F8
+#define SLOT_PWR_LIMIT	0x00000C00
+#define PSN		0xFFF80000	/* PSN: Physical Slot Number */
+
+/* Field definitions in Slot Control Register */
+#define ATTN_BUTTN_ENABLE		0x0001
+#define PWR_FAULT_DETECT_ENABLE		0x0002
+#define MRL_DETECT_ENABLE		0x0004
+#define PRSN_DETECT_ENABLE		0x0008
+#define CMD_CMPL_INTR_ENABLE		0x0010
+#define HP_INTR_ENABLE			0x0020
+#define ATTN_LED_CTRL			0x00C0
+#define PWR_LED_CTRL			0x0300
+#define PWR_CTRL			0x0400
+
+/* Attention indicator and Power indicator states */
+#define LED_ON		0x01
+#define LED_BLINK	0x10
+#define LED_OFF		0x11
+
+/* Power Control Command */
+#define POWER_ON	0
+#define POWER_OFF	0x0400
+
+/* Field definitions in Slot Status Register */
+#define ATTN_BUTTN_PRESSED	0x0001
+#define PWR_FAULT_DETECTED	0x0002
+#define MRL_SENS_CHANGED	0x0004
+#define PRSN_DETECT_CHANGED	0x0008
+#define CMD_COMPLETED		0x0010
+#define MRL_STATE		0x0020
+#define PRSN_STATE		0x0040
+
+struct php_ctlr_state_s {
+	struct php_ctlr_state_s *pnext;
+	struct pci_dev *pci_dev;
+	unsigned int irq;
+	unsigned long flags;				/* spinlock's */
+	u32 slot_device_offset;
+	u32 num_slots;
+    	struct timer_list	int_poll_timer;		/* Added for poll event */
+	php_intr_callback_t 	attention_button_callback;
+	php_intr_callback_t 	switch_change_callback;
+	php_intr_callback_t 	presence_change_callback;
+	php_intr_callback_t 	power_fault_callback;
+	void 			*callback_instance_id;
+	struct ctrl_reg 	*creg;				/* Ptr to controller register space */
+};
+
+
+static spinlock_t hpc_event_lock;
+
+DEFINE_DBG_BUFFER		/* Debug string buffer for entire HPC defined here */
+static struct php_ctlr_state_s *php_ctlr_list_head = 0;	/* HPC state linked list */
+static int ctlr_seq_num = 0;	/* Controller sequence # */
+static spinlock_t list_lock;
+
+static irqreturn_t pcie_isr(int IRQ, void *dev_id, struct pt_regs *regs);
+
+static void start_int_poll_timer(struct php_ctlr_state_s *php_ctlr, int seconds);
+
+/* This is the interrupt polling timeout function. */
+static void int_poll_timeout(unsigned long lphp_ctlr)
+{
+	struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *)lphp_ctlr;
+
+	DBG_ENTER_ROUTINE
+
+	if ( !php_ctlr ) {
+		err("%s: Invalid HPC controller handle!\n", __FUNCTION__);
+		return;
+	}
+
+	/* Poll for interrupt events.  regs == NULL => polling */
+	pcie_isr( 0, (void *)php_ctlr, NULL );
+
+	init_timer(&php_ctlr->int_poll_timer);
+
+	if (!pciehp_poll_time)
+		pciehp_poll_time = 2; /* reset timer to poll in 2 secs if user doesn't specify at module installation*/
+
+	start_int_poll_timer(php_ctlr, pciehp_poll_time);  
+	
+	return;
+}
+
+/* This function starts the interrupt polling timer. */
+static void start_int_poll_timer(struct php_ctlr_state_s *php_ctlr, int seconds)
+{
+	if (!php_ctlr) {
+		err("%s: Invalid HPC controller handle!\n", __FUNCTION__);
+		return;
+	}
+
+	if ( ( seconds <= 0 ) || ( seconds > 60 ) )
+        	seconds = 2;            /* Clamp to sane value */
+
+	php_ctlr->int_poll_timer.function = &int_poll_timeout;
+	php_ctlr->int_poll_timer.data = (unsigned long)php_ctlr;    /* Instance data */
+	php_ctlr->int_poll_timer.expires = jiffies + seconds * HZ;
+	add_timer(&php_ctlr->int_poll_timer);
+
+	return;
+}
+
+static int pcie_write_cmd(struct slot *slot, u16 cmd)
+{
+	struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle;
+	int retval = 0;
+	u16 slot_status;
+
+	DBG_ENTER_ROUTINE 
+	
+	dbg("%s : Enter\n", __FUNCTION__);
+	if (!slot->ctrl->hpc_ctlr_handle) {
+		err("%s: Invalid HPC controller handle!\n", __FUNCTION__);
+		return -1;
+	}
+
+	retval = hp_register_read_word(php_ctlr->pci_dev, SLOT_STATUS, slot_status);
+	if (retval) {
+			err("%s : hp_register_read_word SLOT_STATUS failed\n", __FUNCTION__);
+			return retval;
+		}
+	dbg("%s : hp_register_read_word SLOT_STATUS %x\n", __FUNCTION__, slot_status);
+	
+	if ((slot_status & CMD_COMPLETED) == CMD_COMPLETED ) { 
+		/* After 1 sec and CMD_COMPLETED still not set, just proceed forward to issue 
+		   the next command according to spec.  Just print out the error message */
+		dbg("%s : CMD_COMPLETED not clear after 1 sec.\n", __FUNCTION__);
+	}
+
+	retval = hp_register_write_word(php_ctlr->pci_dev, SLOT_CTRL, cmd);
+	if (retval) {
+		err("%s : hp_register_write_word SLOT_CTRL failed\n", __FUNCTION__);
+		return retval;
+	}
+	dbg("%s : hp_register_write_word SLOT_CTRL %x\n", __FUNCTION__, cmd);
+	dbg("%s : Exit\n", __FUNCTION__);
+
+	DBG_LEAVE_ROUTINE 
+	return retval;
+}
+
+static int hpc_check_lnk_status(struct controller *ctrl)
+{
+	struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) ctrl->hpc_ctlr_handle;
+	u16 lnk_status;
+	int retval = 0;
+
+	DBG_ENTER_ROUTINE 
+
+	if (!ctrl->hpc_ctlr_handle) {
+		err("%s: Invalid HPC controller handle!\n", __FUNCTION__);
+		return -1;
+	}
+	
+	retval = hp_register_read_word(php_ctlr->pci_dev, LNK_STATUS, lnk_status);
+
+	if (retval) {
+		err("%s : hp_register_read_word LNK_STATUS failed\n", __FUNCTION__);
+		return retval;
+	}
+
+	if ( (lnk_status & (LNK_TRN | LNK_TRN_ERR)) == 0x0C00) {
+		err("%s : Link Training Error occurs \n", __FUNCTION__);
+		retval = -1;
+		return retval;
+	}
+
+	DBG_LEAVE_ROUTINE 
+	return retval;
+}
+
+
+static int hpc_get_attention_status(struct slot *slot, u8 *status)
+{
+	struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle;
+	u16 slot_ctrl;
+	u8 atten_led_state;
+	int retval = 0;
+	
+	DBG_ENTER_ROUTINE 
+
+	if (!slot->ctrl->hpc_ctlr_handle) {
+		err("%s: Invalid HPC controller handle!\n", __FUNCTION__);
+		return -1;
+	}
+
+	retval = hp_register_read_word(php_ctlr->pci_dev, SLOT_CTRL, slot_ctrl);
+
+	if (retval) {
+		err("%s : hp_register_read_word SLOT_CTRL failed\n", __FUNCTION__);
+		return retval;
+	}
+
+	dbg("%s: SLOT_CTRL %x, value read %x\n", __FUNCTION__,SLOT_CTRL, slot_ctrl);
+
+	atten_led_state = (slot_ctrl & ATTN_LED_CTRL) >> 6;
+
+	switch (atten_led_state) {
+	case 0:
+		*status = 0xFF;	/* Reserved */
+		break;
+	case 1:
+		*status = 1;	/* On */
+		break;
+	case 2:
+		*status = 2;	/* Blink */
+		break;
+	case 3:
+		*status = 0;	/* Off */
+		break;
+	default:
+		*status = 0xFF;
+		break;
+	}
+
+	DBG_LEAVE_ROUTINE 
+	return 0;
+}
+
+static int hpc_get_power_status(struct slot * slot, u8 *status)
+{
+	struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle;
+	u16 slot_ctrl;
+	u8 pwr_state;
+	int	retval = 0;
+	
+	DBG_ENTER_ROUTINE 
+
+	if (!slot->ctrl->hpc_ctlr_handle) {
+		err("%s: Invalid HPC controller handle!\n", __FUNCTION__);
+		return -1;
+	}
+
+	retval = hp_register_read_word(php_ctlr->pci_dev, SLOT_CTRL, slot_ctrl);
+
+	if (retval) {
+		err("%s : hp_register_read_word SLOT_CTRL failed\n", __FUNCTION__);
+		return retval;
+	}
+	dbg("%s: SLOT_CTRL %x value read %x\n", __FUNCTION__, SLOT_CTRL, slot_ctrl);
+
+	pwr_state = (slot_ctrl & PWR_CTRL) >> 10;
+
+	switch (pwr_state) {
+	case 0:
+		*status = 1;
+		break;
+	case 1:
+		*status = 0;	
+		break;
+	default:
+		*status = 0xFF;
+		break;
+	}
+
+	DBG_LEAVE_ROUTINE 
+	return retval;
+}
+
+
+static int hpc_get_latch_status(struct slot *slot, u8 *status)
+{
+	struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle;
+	u16 slot_status;
+	int retval = 0;
+
+	DBG_ENTER_ROUTINE 
+
+	if (!slot->ctrl->hpc_ctlr_handle) {
+		err("%s: Invalid HPC controller handle!\n", __FUNCTION__);
+		return -1;
+	}
+
+	retval = hp_register_read_word(php_ctlr->pci_dev, SLOT_STATUS, slot_status);
+
+	if (retval) {
+		err("%s : hp_register_read_word SLOT_STATUS failed\n", __FUNCTION__);
+		return retval;
+	}
+
+	*status = (((slot_status & MRL_STATE) >> 5) == 0) ? 0 : 1;  
+
+	DBG_LEAVE_ROUTINE 
+	return 0;
+}
+
+static int hpc_get_adapter_status(struct slot *slot, u8 *status)
+{
+	struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle;
+	u16 slot_status;
+	u8 card_state;
+	int retval = 0;
+
+	DBG_ENTER_ROUTINE 
+
+	if (!slot->ctrl->hpc_ctlr_handle) {
+		err("%s: Invalid HPC controller handle!\n", __FUNCTION__);
+		return -1;
+	}
+
+	retval = hp_register_read_word(php_ctlr->pci_dev, SLOT_STATUS, slot_status);
+
+	if (retval) {
+		err("%s : hp_register_read_word SLOT_STATUS failed\n", __FUNCTION__);
+		return retval;
+	}
+	card_state = (u8)((slot_status & PRSN_STATE) >> 6);
+	*status = (card_state == 1) ? 1 : 0;
+
+	DBG_LEAVE_ROUTINE 
+	return 0;
+}
+
+static int hpc_query_power_fault(struct slot * slot)
+{
+	struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle;
+	u16 slot_status;
+	u8 pwr_fault;
+	int retval = 0;
+	u8 status;
+
+	DBG_ENTER_ROUTINE 
+
+	if (!slot->ctrl->hpc_ctlr_handle) {
+		err("%s: Invalid HPC controller handle!\n", __FUNCTION__);
+		return -1;
+	}
+
+	retval = hp_register_read_word(php_ctlr->pci_dev, SLOT_STATUS, slot_status);
+
+	if (retval) {
+		err("%s : hp_register_read_word SLOT_STATUS failed\n", __FUNCTION__);
+		return retval;
+	}
+	pwr_fault = (u8)((slot_status & PWR_FAULT_DETECTED) >> 1);
+	status = (pwr_fault != 1) ? 1 : 0;
+	
+	DBG_LEAVE_ROUTINE
+	/* Note: Logic 0 => fault */
+	return status;
+}
+
+static int hpc_set_attention_status(struct slot *slot, u8 value)
+{
+	struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle;
+	u16 slot_cmd = 0;
+	u16 slot_ctrl;
+	int rc = 0;
+
+	dbg("%s: \n", __FUNCTION__);
+	if (!slot->ctrl->hpc_ctlr_handle) {
+		err("%s: Invalid HPC controller handle!\n", __FUNCTION__);
+		return -1;
+	}
+
+	if (slot->hp_slot >= php_ctlr->num_slots) {
+		err("%s: Invalid HPC slot number!\n", __FUNCTION__);
+		return -1;
+	}
+	rc = hp_register_read_word(php_ctlr->pci_dev, SLOT_CTRL, slot_ctrl);
+
+	if (rc) {
+		err("%s : hp_register_read_word SLOT_CTRL failed\n", __FUNCTION__);
+		return rc;
+	}
+	dbg("%s : hp_register_read_word SLOT_CTRL %x\n", __FUNCTION__, slot_ctrl);
+
+	switch (value) {
+		case 0 :	/* turn off */
+			slot_cmd = (slot_ctrl & ~ATTN_LED_CTRL) | 0x00C0;
+			break;
+		case 1:		/* turn on */
+			slot_cmd = (slot_ctrl & ~ATTN_LED_CTRL) | 0x0040;
+			break;
+		case 2:		/* turn blink */
+			slot_cmd = (slot_ctrl & ~ATTN_LED_CTRL) | 0x0080;
+			break;
+		default:
+			return -1;
+	}
+	if (!pciehp_poll_mode)
+		slot_cmd = slot_cmd | HP_INTR_ENABLE; 
+
+	pcie_write_cmd(slot, slot_cmd);
+	dbg("%s: SLOT_CTRL %x write cmd %x\n", __FUNCTION__, SLOT_CTRL, slot_cmd);
+	
+	return rc;
+}
+
+
+static void hpc_set_green_led_on(struct slot *slot)
+{
+	struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle;
+	u16 slot_cmd;
+	u16 slot_ctrl;
+	int rc = 0;
+       	
+	dbg("%s: \n", __FUNCTION__);	
+	if (!slot->ctrl->hpc_ctlr_handle) {
+		err("%s: Invalid HPC controller handle!\n", __FUNCTION__);
+		return ;
+	}
+
+	if (slot->hp_slot >= php_ctlr->num_slots) {
+		err("%s: Invalid HPC slot number!\n", __FUNCTION__);
+		return ;
+	}
+
+	rc = hp_register_read_word(php_ctlr->pci_dev, SLOT_CTRL, slot_ctrl);
+
+	if (rc) {
+		err("%s : hp_register_read_word SLOT_CTRL failed\n", __FUNCTION__);
+		return;
+	}
+	dbg("%s : hp_register_read_word SLOT_CTRL %x\n", __FUNCTION__, slot_ctrl);
+	slot_cmd = (slot_ctrl & ~PWR_LED_CTRL) | 0x0100;
+	if (!pciehp_poll_mode)
+		slot_cmd = slot_cmd | HP_INTR_ENABLE; 
+
+	pcie_write_cmd(slot, slot_cmd);
+
+	dbg("%s: SLOT_CTRL %x write cmd %x\n",__FUNCTION__, SLOT_CTRL, slot_cmd);
+	return;
+}
+
+static void hpc_set_green_led_off(struct slot *slot)
+{
+	struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle;
+	u16 slot_cmd;
+	u16 slot_ctrl;
+	int rc = 0;
+
+	dbg("%s: \n", __FUNCTION__);	
+	if (!slot->ctrl->hpc_ctlr_handle) {
+		err("%s: Invalid HPC controller handle!\n", __FUNCTION__);
+		return ;
+	}
+
+	if (slot->hp_slot >= php_ctlr->num_slots) {
+		err("%s: Invalid HPC slot number!\n", __FUNCTION__);
+		return ;
+	}
+
+	rc = hp_register_read_word(php_ctlr->pci_dev, SLOT_CTRL, slot_ctrl);
+
+	if (rc) {
+		err("%s : hp_register_read_word SLOT_CTRL failed\n", __FUNCTION__);
+		return;
+	}
+	dbg("%s : hp_register_read_word SLOT_CTRL %x\n", __FUNCTION__, slot_ctrl);
+
+	slot_cmd = (slot_ctrl & ~PWR_LED_CTRL) | 0x0300;
+
+	if (!pciehp_poll_mode)
+		slot_cmd = slot_cmd | HP_INTR_ENABLE; 
+	pcie_write_cmd(slot, slot_cmd);
+	dbg("%s: SLOT_CTRL %x write cmd %x\n", __FUNCTION__, SLOT_CTRL, slot_cmd);
+
+	return;
+}
+
+static void hpc_set_green_led_blink(struct slot *slot)
+{
+	struct php_ctlr_state_s *php_ctlr =(struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle;
+	u16 slot_cmd;
+	u16 slot_ctrl;
+	int rc = 0; 
+	
+	dbg("%s: \n", __FUNCTION__);	
+	if (!slot->ctrl->hpc_ctlr_handle) {
+		err("%s: Invalid HPC controller handle!\n", __FUNCTION__);
+		return ;
+	}
+
+	if (slot->hp_slot >= php_ctlr->num_slots) {
+		err("%s: Invalid HPC slot number!\n", __FUNCTION__);
+		return ;
+	}
+
+	rc = hp_register_read_word(php_ctlr->pci_dev, SLOT_CTRL, slot_ctrl);
+
+	if (rc) {
+		err("%s : hp_register_read_word SLOT_CTRL failed\n", __FUNCTION__);
+		return;
+	}
+	dbg("%s : hp_register_read_word SLOT_CTRL %x\n", __FUNCTION__, slot_ctrl);
+
+	slot_cmd = (slot_ctrl & ~PWR_LED_CTRL) | 0x0200;
+
+	if (!pciehp_poll_mode)
+		slot_cmd = slot_cmd | HP_INTR_ENABLE; 
+	pcie_write_cmd(slot, slot_cmd);
+
+	dbg("%s: SLOT_CTRL %x write cmd %x\n",__FUNCTION__, SLOT_CTRL, slot_cmd);
+	return;
+}
+
+int pcie_get_ctlr_slot_config(struct controller *ctrl,
+	int *num_ctlr_slots,	/* number of slots in this HPC; only 1 in PCIE  */	
+	int *first_device_num,	/* PCI dev num of the first slot in this PCIE	*/
+	int *physical_slot_num,	/* phy slot num of the first slot in this PCIE	*/
+	int *updown,		/* physical_slot_num increament: 1 or -1	*/
+	int *flags)
+{
+	struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) ctrl->hpc_ctlr_handle;
+	u32 slot_cap;
+	int rc = 0;
+	
+	DBG_ENTER_ROUTINE 
+
+	if (!ctrl->hpc_ctlr_handle) {
+		err("%s: Invalid HPC controller handle!\n", __FUNCTION__);
+		return -1;
+	}
+
+	*first_device_num = 0;
+	*num_ctlr_slots = 1; 
+
+	rc = hp_register_read_dword(php_ctlr->pci_dev, SLOT_CAP, slot_cap);
+
+	if (rc) {
+		err("%s : hp_register_read_dword SLOT_CAP failed\n", __FUNCTION__);
+		return -1;
+	}
+	
+	*physical_slot_num = slot_cap >> 19;
+
+	*updown = -1;
+
+	DBG_LEAVE_ROUTINE 
+	return 0;
+}
+
+static void hpc_release_ctlr(struct controller *ctrl)
+{
+	struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) ctrl->hpc_ctlr_handle;
+	struct php_ctlr_state_s *p, *p_prev;
+
+	DBG_ENTER_ROUTINE 
+
+	if (!ctrl->hpc_ctlr_handle) {
+		err("%s: Invalid HPC controller handle!\n", __FUNCTION__);
+		return ;
+	}
+
+	if (pciehp_poll_mode) {
+	    del_timer(&php_ctlr->int_poll_timer);
+	} else {	
+		if (php_ctlr->irq) {
+			free_irq(php_ctlr->irq, ctrl);
+			php_ctlr->irq = 0;
+		}
+	}
+	if (php_ctlr->pci_dev) 
+		php_ctlr->pci_dev = 0;
+
+	spin_lock(&list_lock);
+	p = php_ctlr_list_head;
+	p_prev = NULL;
+	while (p) {
+		if (p == php_ctlr) {
+			if (p_prev)
+				p_prev->pnext = p->pnext;
+			else
+				php_ctlr_list_head = p->pnext;
+			break;
+		} else {
+			p_prev = p;
+			p = p->pnext;
+		}
+	}
+	spin_unlock(&list_lock);
+
+	kfree(php_ctlr);
+
+	DBG_LEAVE_ROUTINE
+			  
+}
+
+static int hpc_power_on_slot(struct slot * slot)
+{
+	struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle;
+	u16 slot_cmd;
+	u16 slot_ctrl;
+
+	int retval = 0;
+
+	DBG_ENTER_ROUTINE 
+	dbg("%s: \n", __FUNCTION__);	
+
+	if (!slot->ctrl->hpc_ctlr_handle) {
+		err("%s: Invalid HPC controller handle!\n", __FUNCTION__);
+		return -1;
+	}
+
+	dbg("%s: slot->hp_slot %x\n", __FUNCTION__, slot->hp_slot);
+	if (slot->hp_slot >= php_ctlr->num_slots) {
+		err("%s: Invalid HPC slot number!\n", __FUNCTION__);
+		return -1;
+	}
+
+	retval = hp_register_read_word(php_ctlr->pci_dev, SLOT_CTRL, slot_ctrl);
+
+	if (retval) {
+		err("%s : hp_register_read_word SLOT_CTRL failed\n", __FUNCTION__);
+		return retval;
+	}
+	dbg("%s: SLOT_CTRL %x, value read %xn", __FUNCTION__, SLOT_CTRL, 
+		slot_ctrl);
+
+	slot_cmd = (slot_ctrl & ~PWR_CTRL) | POWER_ON;
+
+	if (!pciehp_poll_mode)
+		slot_cmd = slot_cmd | HP_INTR_ENABLE; 
+
+	retval = pcie_write_cmd(slot, slot_cmd);
+
+	if (retval) {
+		err("%s: Write %x command failed!\n", __FUNCTION__, slot_cmd);
+		return -1;
+	}
+	dbg("%s: SLOT_CTRL %x write cmd %x\n",__FUNCTION__, SLOT_CTRL, slot_cmd);
+
+	DBG_LEAVE_ROUTINE
+
+	return retval;
+}
+
+static int hpc_power_off_slot(struct slot * slot)
+{
+	struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle;
+	u16 slot_cmd;
+	u16 slot_ctrl;
+
+	int retval = 0;
+
+	DBG_ENTER_ROUTINE 
+	dbg("%s: \n", __FUNCTION__);	
+
+	if (!slot->ctrl->hpc_ctlr_handle) {
+		err("%s: Invalid HPC controller handle!\n", __FUNCTION__);
+		return -1;
+	}
+
+	dbg("%s: slot->hp_slot %x\n", __FUNCTION__, slot->hp_slot);
+	slot->hp_slot = 0;
+	if (slot->hp_slot >= php_ctlr->num_slots) {
+		err("%s: Invalid HPC slot number!\n", __FUNCTION__);
+		return -1;
+	}
+	retval = hp_register_read_word(php_ctlr->pci_dev, SLOT_CTRL, slot_ctrl);
+
+	if (retval) {
+		err("%s : hp_register_read_word SLOT_CTRL failed\n", __FUNCTION__);
+		return retval;
+	}
+	dbg("%s: SLOT_CTRL %x, value read %x\n", __FUNCTION__, SLOT_CTRL, 
+		slot_ctrl);
+
+	slot_cmd = (slot_ctrl & ~PWR_CTRL) | POWER_OFF;
+
+	if (!pciehp_poll_mode)
+		slot_cmd = slot_cmd | HP_INTR_ENABLE; 
+
+	retval = pcie_write_cmd(slot, slot_cmd);
+
+	if (retval) {
+		err("%s: Write command failed!\n", __FUNCTION__);
+		return -1;
+	}
+	dbg("%s: SLOT_CTRL %x write cmd %x\n",__FUNCTION__, SLOT_CTRL, slot_cmd);
+
+	DBG_LEAVE_ROUTINE
+
+	return retval;
+}
+
+static irqreturn_t pcie_isr(int IRQ, void *dev_id, struct pt_regs *regs)
+{
+	struct controller *ctrl = NULL;
+	struct php_ctlr_state_s *php_ctlr;
+	u8 schedule_flag = 0;
+	u16 slot_status, intr_detect, intr_loc;
+	u16 temp_word;
+	int hp_slot = 0;	/* only 1 slot per PCI Express port */
+	int rc = 0;
+
+	if (!dev_id)
+		return IRQ_NONE;
+
+	if (!pciehp_poll_mode) { 
+		ctrl = (struct controller *)dev_id;
+		php_ctlr = ctrl->hpc_ctlr_handle;
+	} else {
+		php_ctlr = (struct php_ctlr_state_s *) dev_id;
+		ctrl = (struct controller *)php_ctlr->callback_instance_id;
+	}
+
+	if (!ctrl) {
+		dbg("%s: dev_id %p ctlr == NULL\n", __FUNCTION__, (void*) dev_id);
+		return IRQ_NONE;
+	}
+	
+	if (!php_ctlr) {
+		dbg("%s: php_ctlr == NULL\n", __FUNCTION__);
+		return IRQ_NONE;
+	}
+
+	rc = hp_register_read_word(php_ctlr->pci_dev, SLOT_STATUS, slot_status);
+	if (rc) {
+		err("%s : hp_register_read_word SLOT_STATUS failed\n", __FUNCTION__);
+		return IRQ_NONE;
+	}
+
+	intr_detect = ( ATTN_BUTTN_PRESSED | PWR_FAULT_DETECTED | MRL_SENS_CHANGED |
+					PRSN_DETECT_CHANGED | CMD_COMPLETED );
+
+	intr_loc = slot_status & intr_detect;
+
+	/* Check to see if it was our interrupt */
+	if ( !intr_loc )
+		return IRQ_NONE;
+
+	dbg("%s: intr_loc %x\n", __FUNCTION__, intr_loc);
+	/* Mask Hot-plug Interrupt Enable */
+	if (!pciehp_poll_mode) {
+		rc = hp_register_read_word(php_ctlr->pci_dev, SLOT_CTRL, temp_word);
+		if (rc) {
+			err("%s : hp_register_read_word SLOT_CTRL failed\n", __FUNCTION__);
+			return IRQ_NONE;;
+		}
+
+		temp_word = (temp_word & ~HP_INTR_ENABLE) | 0x00;
+
+		rc = hp_register_write_word(php_ctlr->pci_dev, SLOT_CTRL, temp_word);
+		if (rc) {
+			err("%s : hp_register_write_word SLOT_CTRL failed\n", __FUNCTION__);
+			return IRQ_NONE;;
+		}
+	}
+	
+	if (intr_loc & CMD_COMPLETED) {
+		/* 
+		 * Command Complete Interrupt Pending 
+		 */
+		dbg("%s: In Command Complete Interrupt Pending\n", __FUNCTION__);
+		wake_up_interruptible(&ctrl->queue);
+	}
+
+	if ((php_ctlr->switch_change_callback) && (intr_loc & MRL_SENS_CHANGED))
+		schedule_flag += php_ctlr->switch_change_callback(
+			hp_slot, php_ctlr->callback_instance_id);
+	if ((php_ctlr->attention_button_callback) && (intr_loc & ATTN_BUTTN_PRESSED))
+		schedule_flag += php_ctlr->attention_button_callback(
+			hp_slot, php_ctlr->callback_instance_id);
+	if ((php_ctlr->presence_change_callback) && (intr_loc & PRSN_DETECT_CHANGED))
+		schedule_flag += php_ctlr->presence_change_callback(
+			hp_slot , php_ctlr->callback_instance_id);
+	if ((php_ctlr->power_fault_callback) && (intr_loc & PWR_FAULT_DETECTED))
+		schedule_flag += php_ctlr->power_fault_callback(
+			hp_slot, php_ctlr->callback_instance_id);
+
+	/* Clear all events after serving them */
+	temp_word = slot_status | 0xff;
+	rc = hp_register_write_word(php_ctlr->pci_dev, SLOT_STATUS, temp_word);
+	if (rc) {
+		err("%s : hp_register_write_word SLOT_STATUS failed\n", __FUNCTION__);
+		return IRQ_NONE;
+	}
+	/* Unmask Hot-plug Interrupt Enable */
+	if (!pciehp_poll_mode) {
+		rc = hp_register_read_word(php_ctlr->pci_dev, SLOT_CTRL, temp_word);
+		if (rc) {
+			err("%s : hp_register_read_word SLOT_CTRL failed\n", __FUNCTION__);
+			return IRQ_NONE;
+		}
+
+		temp_word = (temp_word & ~HP_INTR_ENABLE) | HP_INTR_ENABLE;
+
+		rc = hp_register_write_word(php_ctlr->pci_dev, SLOT_CTRL, temp_word);
+		if (rc) {
+			err("%s : hp_register_write_word SLOT_CTRL failed\n", __FUNCTION__);
+			return IRQ_NONE;
+		}
+	}
+	
+	return IRQ_HANDLED;
+}
+
+static int hpc_get_max_lnk_speed (struct slot *slot, enum pcie_link_speed *value)
+{
+	struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle;
+	enum pcie_link_speed lnk_speed;
+	u32	lnk_cap;
+	int retval = 0;
+
+	DBG_ENTER_ROUTINE 
+
+	if (!slot->ctrl->hpc_ctlr_handle) {
+		err("%s: Invalid HPC controller handle!\n", __FUNCTION__);
+		return -1;
+	}
+
+	if (slot->hp_slot >= php_ctlr->num_slots) {
+		err("%s: Invalid HPC slot number!\n", __FUNCTION__);
+		return -1;
+	}
+
+	retval = hp_register_read_dword(php_ctlr->pci_dev, LNK_CAP, lnk_cap);
+
+	if (retval) {
+		err("%s : hp_register_read_dword  LNK_CAP failed\n", __FUNCTION__);
+		return retval;
+	}
+
+	switch (lnk_cap & 0x000F) {
+	case 1:
+		lnk_speed = PCIE_2PT5GB;
+		break;
+	default:
+		lnk_speed = PCIE_LNK_SPEED_UNKNOWN;
+		break;
+	}
+
+	*value = lnk_speed;
+	dbg("Max link speed = %d\n", lnk_speed);
+	DBG_LEAVE_ROUTINE 
+	return retval;
+}
+
+static int hpc_get_max_lnk_width (struct slot *slot, enum pcie_link_width *value)
+{
+	struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle;
+	enum pcie_link_width lnk_wdth;
+	u32	lnk_cap;
+	int retval = 0;
+
+	DBG_ENTER_ROUTINE 
+
+	if (!slot->ctrl->hpc_ctlr_handle) {
+		err("%s: Invalid HPC controller handle!\n", __FUNCTION__);
+		return -1;
+	}
+
+	if (slot->hp_slot >= php_ctlr->num_slots) {
+		err("%s: Invalid HPC slot number!\n", __FUNCTION__);
+		return -1;
+	}
+
+	retval = hp_register_read_dword(php_ctlr->pci_dev, LNK_CAP, lnk_cap);
+
+	if (retval) {
+		err("%s : hp_register_read_dword  LNK_CAP failed\n", __FUNCTION__);
+		return retval;
+	}
+
+	switch ((lnk_cap & 0x03F0) >> 4){
+	case 0:
+		lnk_wdth = PCIE_LNK_WIDTH_RESRV;
+		break;
+	case 1:
+		lnk_wdth = PCIE_LNK_X1;
+		break;
+	case 2:
+		lnk_wdth = PCIE_LNK_X2;
+		break;
+	case 4:
+		lnk_wdth = PCIE_LNK_X4;
+		break;
+	case 8:
+		lnk_wdth = PCIE_LNK_X8;
+		break;
+	case 12:
+		lnk_wdth = PCIE_LNK_X12;
+		break;
+	case 16:
+		lnk_wdth = PCIE_LNK_X16;
+		break;
+	case 32:
+		lnk_wdth = PCIE_LNK_X32;
+		break;
+	default:
+		lnk_wdth = PCIE_LNK_WIDTH_UNKNOWN;
+		break;
+	}
+
+	*value = lnk_wdth;
+	dbg("Max link width = %d\n", lnk_wdth);
+	DBG_LEAVE_ROUTINE 
+	return retval;
+}
+
+static int hpc_get_cur_lnk_speed (struct slot *slot, enum pcie_link_speed *value)
+{
+	struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle;
+	enum pcie_link_speed lnk_speed = PCI_SPEED_UNKNOWN;
+	int retval = 0;
+	u16 lnk_status;
+
+	DBG_ENTER_ROUTINE 
+
+	if (!slot->ctrl->hpc_ctlr_handle) {
+		err("%s: Invalid HPC controller handle!\n", __FUNCTION__);
+		return -1;
+	}
+
+	if (slot->hp_slot >= php_ctlr->num_slots) {
+		err("%s: Invalid HPC slot number!\n", __FUNCTION__);
+		return -1;
+	}
+
+	retval = hp_register_read_word(php_ctlr->pci_dev, LNK_STATUS, lnk_status);
+
+	if (retval) {
+		err("%s : hp_register_read_word LNK_STATUS failed\n", __FUNCTION__);
+		return retval;
+	}
+
+	switch (lnk_status & 0x0F) {
+	case 1:
+		lnk_speed = PCIE_2PT5GB;
+		break;
+	default:
+		lnk_speed = PCIE_LNK_SPEED_UNKNOWN;
+		break;
+	}
+
+	*value = lnk_speed;
+	dbg("Current link speed = %d\n", lnk_speed);
+	DBG_LEAVE_ROUTINE 
+	return retval;
+}
+
+static int hpc_get_cur_lnk_width (struct slot *slot, enum pcie_link_width *value)
+{
+	struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle;
+	enum pcie_link_width lnk_wdth = PCIE_LNK_WIDTH_UNKNOWN;
+	int retval = 0;
+	u16 lnk_status;
+
+	DBG_ENTER_ROUTINE 
+
+	if (!slot->ctrl->hpc_ctlr_handle) {
+		err("%s: Invalid HPC controller handle!\n", __FUNCTION__);
+		return -1;
+	}
+
+	if (slot->hp_slot >= php_ctlr->num_slots) {
+		err("%s: Invalid HPC slot number!\n", __FUNCTION__);
+		return -1;
+	}
+
+	retval = hp_register_read_word(php_ctlr->pci_dev, LNK_STATUS, lnk_status);
+
+	if (retval) {
+		err("%s : hp_register_read_word LNK_STATUS failed\n", __FUNCTION__);
+		return retval;
+	}
+	
+	switch ((lnk_status & 0x03F0) >> 4){
+	case 0:
+		lnk_wdth = PCIE_LNK_WIDTH_RESRV;
+		break;
+	case 1:
+		lnk_wdth = PCIE_LNK_X1;
+		break;
+	case 2:
+		lnk_wdth = PCIE_LNK_X2;
+		break;
+	case 4:
+		lnk_wdth = PCIE_LNK_X4;
+		break;
+	case 8:
+		lnk_wdth = PCIE_LNK_X8;
+		break;
+	case 12:
+		lnk_wdth = PCIE_LNK_X12;
+		break;
+	case 16:
+		lnk_wdth = PCIE_LNK_X16;
+		break;
+	case 32:
+		lnk_wdth = PCIE_LNK_X32;
+		break;
+	default:
+		lnk_wdth = PCIE_LNK_WIDTH_UNKNOWN;
+		break;
+	}
+
+	*value = lnk_wdth;
+	dbg("Current link width = %d\n", lnk_wdth);
+	DBG_LEAVE_ROUTINE 
+	return retval;
+}
+
+static struct hpc_ops pciehp_hpc_ops = {
+	.power_on_slot			= hpc_power_on_slot,
+	.power_off_slot			= hpc_power_off_slot,
+	.set_attention_status		= hpc_set_attention_status,
+	.get_power_status		= hpc_get_power_status,
+	.get_attention_status		= hpc_get_attention_status,
+	.get_latch_status		= hpc_get_latch_status,
+	.get_adapter_status		= hpc_get_adapter_status,
+
+	.get_max_bus_speed		= hpc_get_max_lnk_speed,
+	.get_cur_bus_speed		= hpc_get_cur_lnk_speed,
+	.get_max_lnk_width		= hpc_get_max_lnk_width,
+	.get_cur_lnk_width		= hpc_get_cur_lnk_width,
+	
+	.query_power_fault		= hpc_query_power_fault,
+	.green_led_on			= hpc_set_green_led_on,
+	.green_led_off			= hpc_set_green_led_off,
+	.green_led_blink		= hpc_set_green_led_blink,
+	
+	.release_ctlr			= hpc_release_ctlr,
+	.check_lnk_status		= hpc_check_lnk_status,
+};
+
+int pcie_init(struct controller * ctrl,
+	struct pci_dev * pdev,
+	php_intr_callback_t attention_button_callback,
+	php_intr_callback_t switch_change_callback,
+	php_intr_callback_t presence_change_callback,
+	php_intr_callback_t power_fault_callback)
+{
+	struct php_ctlr_state_s *php_ctlr, *p;
+	void *instance_id = ctrl;
+	int rc;
+	static int first = 1;
+	u16 temp_word;
+	u16 cap_reg;
+	u16 intr_enable;
+	u32 slot_cap;
+	int cap_base, saved_cap_base;
+	u16 slot_status, slot_ctrl;
+
+	DBG_ENTER_ROUTINE
+	
+	spin_lock_init(&list_lock);	
+	php_ctlr = (struct php_ctlr_state_s *) kmalloc(sizeof(struct php_ctlr_state_s), GFP_KERNEL);
+
+	if (!php_ctlr) {	/* allocate controller state data */
+		err("%s: HPC controller memory allocation error!\n", __FUNCTION__);
+		goto abort;
+	}
+
+	memset(php_ctlr, 0, sizeof(struct php_ctlr_state_s));
+
+	php_ctlr->pci_dev = pdev;	/* save pci_dev in context */
+
+	dbg("%s: pdev->vendor %x pdev->device %x\n", __FUNCTION__,
+		pdev->vendor, pdev->device);
+
+	saved_cap_base = pcie_cap_base;
+
+	if ((cap_base = pci_find_capability(pdev, PCI_CAP_ID_EXP)) == 0) {
+		dbg("%s: Can't find PCI_CAP_ID_EXP (0x10)\n", __FUNCTION__);
+		goto abort_free_ctlr;
+	}
+
+	pcie_cap_base = cap_base;
+
+	dbg("%s: pcie_cap_base %x\n", __FUNCTION__, pcie_cap_base);
+
+	rc = hp_register_read_word(pdev, CAP_REG, cap_reg);
+	if (rc) {
+		err("%s : hp_register_read_word CAP_REG failed\n", __FUNCTION__);
+		goto abort_free_ctlr;
+	}
+	dbg("%s: CAP_REG offset %x cap_reg %x\n", __FUNCTION__, CAP_REG, cap_reg);
+
+	if (((cap_reg & SLOT_IMPL) == 0) || ((cap_reg & DEV_PORT_TYPE) != 0x0040)){
+		dbg("%s : This is not a root port or the port is not connected to a slot\n", __FUNCTION__);
+		goto abort_free_ctlr;
+	}
+
+	rc = hp_register_read_dword(php_ctlr->pci_dev, SLOT_CAP, slot_cap);
+	if (rc) {
+		err("%s : hp_register_read_word CAP_REG failed\n", __FUNCTION__);
+		goto abort_free_ctlr;
+	}
+	dbg("%s: SLOT_CAP offset %x slot_cap %x\n", __FUNCTION__, SLOT_CAP, slot_cap);
+
+	if (!(slot_cap & HP_CAP)) {
+		dbg("%s : This slot is not hot-plug capable\n", __FUNCTION__);
+		goto abort_free_ctlr;
+	}
+	/* For debugging purpose */
+	rc = hp_register_read_word(php_ctlr->pci_dev, SLOT_STATUS, slot_status);
+	if (rc) {
+		err("%s : hp_register_read_word SLOT_STATUS failed\n", __FUNCTION__);
+		goto abort_free_ctlr;
+	}
+	dbg("%s: SLOT_STATUS offset %x slot_status %x\n", __FUNCTION__, SLOT_STATUS, slot_status);
+
+	rc = hp_register_read_word(php_ctlr->pci_dev, SLOT_CTRL, slot_ctrl);
+	if (rc) {
+		err("%s : hp_register_read_word SLOT_CTRL failed\n", __FUNCTION__);
+		goto abort_free_ctlr;
+	}
+	dbg("%s: SLOT_CTRL offset %x slot_ctrl %x\n", __FUNCTION__, SLOT_CTRL, slot_ctrl);
+
+	if (first) {
+		spin_lock_init(&hpc_event_lock);
+		first = 0;
+	}
+
+	dbg("pdev = %p: b:d:f:irq=0x%x:%x:%x:%x\n", pdev, pdev->bus->number, 
+		PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn), pdev->irq);
+	for ( rc = 0; rc < DEVICE_COUNT_RESOURCE; rc++)
+		if (pci_resource_len(pdev, rc) > 0)
+			dbg("pci resource[%d] start=0x%lx(len=0x%lx)\n", rc,
+				pci_resource_start(pdev, rc), pci_resource_len(pdev, rc));
+
+	info("HPC vendor_id %x device_id %x ss_vid %x ss_did %x\n", pdev->vendor, pdev->device, 
+		pdev->subsystem_vendor, pdev->subsystem_device);
+
+	init_MUTEX(&ctrl->crit_sect);
+	/* setup wait queue */
+	init_waitqueue_head(&ctrl->queue);
+
+	/* find the IRQ */
+	php_ctlr->irq = pdev->irq;
+	dbg("HPC interrupt = %d\n", php_ctlr->irq);
+
+	/* Save interrupt callback info */
+	php_ctlr->attention_button_callback = attention_button_callback;
+	php_ctlr->switch_change_callback = switch_change_callback;
+	php_ctlr->presence_change_callback = presence_change_callback;
+	php_ctlr->power_fault_callback = power_fault_callback;
+	php_ctlr->callback_instance_id = instance_id;
+
+	/* return PCI Controller Info */
+	php_ctlr->slot_device_offset = 0;
+	php_ctlr->num_slots = 1;
+
+	/* Mask Hot-plug Interrupt Enable */
+	rc = hp_register_read_word(pdev, SLOT_CTRL, temp_word);
+	if (rc) {
+		err("%s : hp_register_read_word SLOT_CTRL failed\n", __FUNCTION__);
+		goto abort_free_ctlr;
+	}
+
+	dbg("%s: SLOT_CTRL %x value read %x\n", __FUNCTION__, SLOT_CTRL, temp_word);
+	temp_word = (temp_word & ~HP_INTR_ENABLE) | 0x00;
+
+	rc = hp_register_write_word(pdev, SLOT_CTRL, temp_word);
+	if (rc) {
+		err("%s : hp_register_write_word SLOT_CTRL failed\n", __FUNCTION__);
+		goto abort_free_ctlr;
+	}
+	dbg("%s : Mask HPIE hp_register_write_word SLOT_CTRL %x\n", __FUNCTION__, temp_word);
+
+	rc = hp_register_read_word(php_ctlr->pci_dev, SLOT_STATUS, slot_status);
+	if (rc) {
+		err("%s : hp_register_read_word SLOT_STATUS failed\n", __FUNCTION__);
+		goto abort_free_ctlr;
+	}
+	dbg("%s: Mask HPIE SLOT_STATUS offset %x reads slot_status %x\n", __FUNCTION__, SLOT_STATUS, slot_status);
+
+	rc = hp_register_write_word(php_ctlr->pci_dev, SLOT_STATUS, slot_status);
+	if (rc) {
+		err("%s : hp_register_write_word SLOT_STATUS failed\n", __FUNCTION__);
+		goto abort_free_ctlr;
+	}
+	dbg("%s: SLOT_STATUS offset %x writes slot_status %x\n", __FUNCTION__, SLOT_STATUS, slot_status);
+
+	if (pciehp_poll_mode)  {/* Install interrupt polling code */
+		/* Install and start the interrupt polling timer */
+		init_timer(&php_ctlr->int_poll_timer);
+		start_int_poll_timer( php_ctlr, 10 );   /* start with 10 second delay */
+	} else {
+		/* Installs the interrupt handler */
+#ifdef CONFIG_PCI_USE_VECTOR 
+		rc = pci_enable_msi(pdev);
+		if (rc) {
+			err("Can't get msi for the hotplug controller\n");
+			dbg("%s: rc = %x\n", __FUNCTION__, rc);
+			goto abort_free_ctlr;
+		}
+		php_ctlr->irq = pdev->irq;
+#endif		
+		rc = request_irq(php_ctlr->irq, pcie_isr, SA_SHIRQ, MY_NAME, (void *) ctrl);
+		dbg("%s: request_irq %d for hpc%d (returns %d)\n", __FUNCTION__, php_ctlr->irq, ctlr_seq_num, rc);
+		if (rc) {
+			err("Can't get irq %d for the hotplug controller\n", php_ctlr->irq);
+			goto abort_free_ctlr;
+		}
+	}
+
+	rc = hp_register_read_word(pdev, SLOT_CTRL, temp_word);
+	if (rc) {
+		err("%s : hp_register_read_word SLOT_CTRL failed\n", __FUNCTION__);
+		goto abort_free_ctlr;
+	}
+	dbg("%s: SLOT_CTRL %x value read %x\n", __FUNCTION__, SLOT_CTRL, temp_word);
+
+	intr_enable = ATTN_BUTTN_ENABLE | PWR_FAULT_DETECT_ENABLE | MRL_DETECT_ENABLE |
+					PRSN_DETECT_ENABLE | CMD_CMPL_INTR_ENABLE;
+
+	temp_word = (temp_word & ~intr_enable) | intr_enable; 
+
+	if (pciehp_poll_mode) {
+		temp_word = (temp_word & ~HP_INTR_ENABLE) | 0x0;
+	} else {
+		temp_word = (temp_word & ~HP_INTR_ENABLE) | HP_INTR_ENABLE;
+	}
+	dbg("%s: temp_word %x\n", __FUNCTION__, temp_word);
+
+	/* Unmask Hot-plug Interrupt Enable for the interrupt notification mechanism case */
+	rc = hp_register_write_word(pdev, SLOT_CTRL, temp_word);
+	if (rc) {
+		err("%s : hp_register_write_word SLOT_CTRL failed\n", __FUNCTION__);
+		goto abort_free_ctlr;
+	}
+	dbg("%s : Unmask HPIE hp_register_write_word SLOT_CTRL with %x\n", __FUNCTION__, temp_word);
+	
+	/*  Add this HPC instance into the HPC list */
+	spin_lock(&list_lock);
+	if (php_ctlr_list_head == 0) {
+		php_ctlr_list_head = php_ctlr;
+		p = php_ctlr_list_head;
+		p->pnext = 0;
+	} else {
+		p = php_ctlr_list_head;
+
+		while (p->pnext)
+			p = p->pnext;
+
+		p->pnext = php_ctlr;
+	}
+	spin_unlock(&list_lock);
+
+	ctlr_seq_num++;
+	ctrl->hpc_ctlr_handle = php_ctlr;
+	ctrl->hpc_ops = &pciehp_hpc_ops;
+
+	DBG_LEAVE_ROUTINE
+	return 0;
+
+	/* We end up here for the many possible ways to fail this API.  */
+abort_free_ctlr:
+	pcie_cap_base = saved_cap_base;
+	kfree(php_ctlr);
+abort:
+	DBG_LEAVE_ROUTINE
+	return -1;
+}
--- diff/drivers/pci/hotplug/pciehp_pci.c	1970-01-01 01:00:00.000000000 +0100
+++ source/drivers/pci/hotplug/pciehp_pci.c	2004-02-23 13:56:44.000000000 +0000
@@ -0,0 +1,834 @@
+/*
+ * PCI Express Hot Plug Controller Driver
+ *
+ * Copyright (C) 1995,2001 Compaq Computer Corporation
+ * Copyright (C) 2001 Greg Kroah-Hartman (greg@kroah.com)
+ * Copyright (C) 2001 IBM Corp.
+ * Copyright (C) 2003-2004 Intel Corporation
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Send feedback to <greg@kroah.com>, <dely.l.sy@intel.com>
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/slab.h>
+#include <linux/workqueue.h>
+#include <linux/proc_fs.h>
+#include <linux/pci.h>
+#include "../pci.h"
+#include "pciehp.h"
+#ifndef CONFIG_IA64
+#include "../../../arch/i386/pci/pci.h"    /* horrible hack showing how processor dependant we are... */
+#endif
+
+
+int pciehp_configure_device (struct controller* ctrl, struct pci_func* func)  
+{
+	unsigned char bus;
+	struct pci_bus *child;
+	int num;
+
+	if (func->pci_dev == NULL)
+		func->pci_dev = pci_find_slot(func->bus, PCI_DEVFN(func->device, func->function));
+
+	/* Still NULL ? Well then scan for it ! */
+	if (func->pci_dev == NULL) {
+		dbg("%s: pci_dev still null. do pci_scan_slot\n", __FUNCTION__);
+
+		num = pci_scan_slot(ctrl->pci_dev->subordinate, PCI_DEVFN(func->device, func->function));
+
+		if (num)
+			pci_bus_add_devices(ctrl->pci_dev->subordinate);
+		
+		func->pci_dev = pci_find_slot(func->bus, PCI_DEVFN(func->device, func->function));
+		if (func->pci_dev == NULL) {
+			dbg("ERROR: pci_dev still null\n");
+			return 0;
+		}
+	}
+
+	if (func->pci_dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) {
+		pci_read_config_byte(func->pci_dev, PCI_SECONDARY_BUS, &bus);
+		child = (struct pci_bus*) pci_add_new_bus(func->pci_dev->bus, (func->pci_dev), bus);
+		pci_do_scan_bus(child);
+
+	}
+
+	return 0;
+}
+
+
+int pciehp_unconfigure_device(struct pci_func* func) 
+{
+	int rc = 0;
+	int j;
+
+	dbg("%s: bus/dev/func = %x/%x/%x\n", __FUNCTION__, func->bus, func->device, func->function);
+
+	for (j=0; j<8 ; j++) {
+		struct pci_dev* temp = pci_find_slot(func->bus, (func->device << 3) | j);
+		if (temp) {
+			pci_remove_bus_device(temp);
+		}
+	}
+	return rc;
+}
+
+/*
+ * pciehp_set_irq
+ *
+ * @bus_num: bus number of PCI device
+ * @dev_num: device number of PCI device
+ * @slot: pointer to u8 where slot number will be returned
+ */
+int pciehp_set_irq (u8 bus_num, u8 dev_num, u8 int_pin, u8 irq_num)
+{
+#if !defined(CONFIG_X86_IO_APIC) && !defined(CONFIG_X86_64)
+	int rc;
+	u16 temp_word;
+	struct pci_dev fakedev;
+	struct pci_bus fakebus;
+
+	fakedev.devfn = dev_num << 3;
+	fakedev.bus = &fakebus;
+	fakebus.number = bus_num;
+	dbg("%s: dev %d, bus %d, pin %d, num %d\n",
+	    __FUNCTION__, dev_num, bus_num, int_pin, irq_num);
+	rc = pcibios_set_irq_routing(&fakedev, int_pin - 0x0a, irq_num);
+	dbg("%s: rc %d\n", __FUNCTION__, rc);
+	if (!rc)
+		return !rc;
+
+	/* set the Edge Level Control Register (ELCR) */
+	temp_word = inb(0x4d0);
+	temp_word |= inb(0x4d1) << 8;
+
+	temp_word |= 0x01 << irq_num;
+
+	/* This should only be for x86 as it sets the Edge Level Control Register */
+	outb((u8) (temp_word & 0xFF), 0x4d0);
+	outb((u8) ((temp_word & 0xFF00) >> 8), 0x4d1);
+#endif
+	return 0;
+}
+
+/* More PCI configuration routines; this time centered around hotplug controller */
+
+
+/*
+ * pciehp_save_config
+ *
+ * Reads configuration for all slots in a PCI bus and saves info.
+ *
+ * Note:  For non-hot plug busses, the slot # saved is the device #
+ *
+ * returns 0 if success
+ */
+int pciehp_save_config(struct controller *ctrl, int busnumber, int num_ctlr_slots, int first_device_num)
+{
+	int rc;
+	u8 class_code;
+	u8 header_type;
+	u32 ID;
+	u8 secondary_bus;
+	struct pci_func *new_slot;
+	int sub_bus;
+	int max_functions;
+	int function;
+	u8 DevError;
+	int device = 0;
+	int cloop = 0;
+	int stop_it;
+	int index;
+	int is_hot_plug = num_ctlr_slots || first_device_num;
+	struct pci_bus lpci_bus, *pci_bus;
+	int FirstSupported, LastSupported;
+
+	dbg("%s: Enter\n", __FUNCTION__);
+
+	memcpy(&lpci_bus, ctrl->pci_dev->subordinate, sizeof(lpci_bus));
+	pci_bus = &lpci_bus;
+
+	dbg("%s: num_ctlr_slots = %d, first_device_num = %d\n", __FUNCTION__, num_ctlr_slots, first_device_num);
+
+	/*   Decide which slots are supported */
+	if (is_hot_plug) {
+		/*********************************
+		 *  is_hot_plug is the slot mask
+		 *********************************/
+		FirstSupported = first_device_num;
+		LastSupported = FirstSupported + num_ctlr_slots - 1;
+	} else {
+		FirstSupported = 0;
+		LastSupported = 0x1F;
+	}
+
+	dbg("FirstSupported = %d, LastSupported = %d\n", FirstSupported, LastSupported);
+
+	/*   Save PCI configuration space for all devices in supported slots */
+	dbg("%s: pci_bus->number = %x\n", __FUNCTION__, pci_bus->number);
+	pci_bus->number = busnumber;
+	dbg("%s: bus = %x, dev = %x\n", __FUNCTION__, busnumber, device);
+	for (device = FirstSupported; device <= LastSupported; device++) {
+		ID = 0xFFFFFFFF;
+		rc = pci_bus_read_config_dword(pci_bus, PCI_DEVFN(device, 0), PCI_VENDOR_ID, &ID);
+		dbg("%s: ID = %x\n", __FUNCTION__, ID);
+
+		if (ID != 0xFFFFFFFF) {	  /*  device in slot */
+			dbg("%s: ID = %x\n", __FUNCTION__, ID);
+			rc = pci_bus_read_config_byte(pci_bus, PCI_DEVFN(device, 0), 0x0B, &class_code);
+			if (rc)
+				return rc;
+
+			rc = pci_bus_read_config_byte(pci_bus, PCI_DEVFN(device, 0), PCI_HEADER_TYPE, &header_type);
+			if (rc)
+				return rc;
+
+			dbg("class_code = %x, header_type = %x\n", class_code, header_type);
+
+			/* If multi-function device, set max_functions to 8 */
+			if (header_type & 0x80)
+				max_functions = 8;
+			else
+				max_functions = 1;
+
+			function = 0;
+
+			do {
+				DevError = 0;
+				dbg("%s: In do loop\n", __FUNCTION__);
+
+				if ((header_type & 0x7F) == PCI_HEADER_TYPE_BRIDGE) {   /* P-P Bridge */
+					/* Recurse the subordinate bus
+					 * get the subordinate bus number
+					 */
+					rc = pci_bus_read_config_byte(pci_bus, PCI_DEVFN(device, function), 
+						PCI_SECONDARY_BUS, &secondary_bus);
+					if (rc) {
+						return rc;
+					} else {
+						sub_bus = (int) secondary_bus;
+
+						/* Save secondary bus cfg spc with this recursive call. */
+						rc = pciehp_save_config(ctrl, sub_bus, 0, 0);
+						if (rc)
+							return rc;
+					}
+				}
+
+				index = 0;
+				new_slot = pciehp_slot_find(busnumber, device, index++);
+
+				dbg("%s: new_slot = %p bus %x dev %x fun %x\n",
+				__FUNCTION__, new_slot, busnumber, device, index-1);
+
+				while (new_slot && (new_slot->function != (u8) function)) {
+					new_slot = pciehp_slot_find(busnumber, device, index++);
+					dbg("%s: while loop, new_slot = %p bus %x dev %x fun %x\n",
+					__FUNCTION__, new_slot, busnumber, device, index-1);
+				}
+				if (!new_slot) {
+					/* Setup slot structure. */
+					new_slot = pciehp_slot_create(busnumber);
+					dbg("%s: if, new_slot = %p bus %x dev %x fun %x\n",
+					__FUNCTION__, new_slot, busnumber, device, function);
+
+					if (new_slot == NULL)
+						return(1);
+				}
+
+				new_slot->bus = (u8) busnumber;
+				new_slot->device = (u8) device;
+				new_slot->function = (u8) function;
+				new_slot->is_a_board = 1;
+				new_slot->switch_save = 0x10;
+				/* In case of unsupported board */
+				new_slot->status = DevError;
+				new_slot->pci_dev = pci_find_slot(new_slot->bus, (new_slot->device << 3) | new_slot->function);
+				dbg("new_slot->pci_dev = %p\n", new_slot->pci_dev);
+
+				for (cloop = 0; cloop < 0x20; cloop++) {
+					rc = pci_bus_read_config_dword(pci_bus, PCI_DEVFN(device, function), cloop << 2, 
+						(u32 *) & (new_slot->config_space [cloop]));
+					/* dbg("new_slot->config_space[%x] = %x\n", cloop, new_slot->config_space[cloop]); */
+					if (rc)
+						return rc;
+				}
+
+				function++;
+
+				stop_it = 0;
+
+				/*  this loop skips to the next present function
+				 *  reading in Class Code and Header type.
+				 */
+
+				while ((function < max_functions)&&(!stop_it)) {
+					dbg("%s: In while loop \n", __FUNCTION__);
+					rc = pci_bus_read_config_dword(pci_bus, PCI_DEVFN(device, function), PCI_VENDOR_ID, &ID);
+
+					if (ID == 0xFFFFFFFF) {  /* nothing there. */
+						function++;
+						dbg("Nothing there\n");
+					} else {  /* Something there */
+						rc = pci_bus_read_config_byte(pci_bus, PCI_DEVFN(device, function), 0x0B, 
+							&class_code);
+						if (rc)
+							return rc;
+
+						rc = pci_bus_read_config_byte(pci_bus, PCI_DEVFN(device, function), PCI_HEADER_TYPE, 
+							&header_type);
+						if (rc)
+							return rc;
+
+						dbg("class_code = %x, header_type = %x\n", class_code, header_type);
+						stop_it++;
+					}
+				}
+
+			} while (function < max_functions);
+		}		/* End of IF (device in slot?) */
+		else if (is_hot_plug) {
+			/* Setup slot structure with entry for empty slot */
+			new_slot = pciehp_slot_create(busnumber);
+
+			if (new_slot == NULL) {
+				return(1);
+			}
+			dbg("new_slot = %p, bus = %x, dev = %x, fun = %x\n", new_slot,
+				new_slot->bus, new_slot->device, new_slot->function);
+
+			new_slot->bus = (u8) busnumber;
+			new_slot->device = (u8) device;
+			new_slot->function = 0;
+			new_slot->is_a_board = 0;
+			new_slot->presence_save = 0;
+			new_slot->switch_save = 0;
+		}
+		dbg("%s: End of For loop\n", __FUNCTION__);
+	} 			/* End of FOR loop */
+
+	dbg("%s: Exit\n", __FUNCTION__);
+	return(0);
+}
+
+
+/*
+ * pciehp_save_slot_config
+ *
+ * Saves configuration info for all PCI devices in a given slot
+ * including subordinate busses.
+ *
+ * returns 0 if success
+ */
+int pciehp_save_slot_config (struct controller *ctrl, struct pci_func * new_slot)
+{
+	int rc;
+	u8 class_code;
+	u8 header_type;
+	u32 ID;
+	u8 secondary_bus;
+	int sub_bus;
+	int max_functions;
+	int function;
+	int cloop = 0;
+	int stop_it;
+	struct pci_bus lpci_bus, *pci_bus;
+	memcpy(&lpci_bus, ctrl->pci_dev->subordinate, sizeof(lpci_bus));
+	pci_bus = &lpci_bus;
+	pci_bus->number = new_slot->bus;
+
+	ID = 0xFFFFFFFF;
+
+	pci_bus_read_config_dword(pci_bus, PCI_DEVFN(new_slot->device, 0), PCI_VENDOR_ID, &ID);
+
+	if (ID != 0xFFFFFFFF) {	  /*  device in slot */
+		pci_bus_read_config_byte(pci_bus, PCI_DEVFN(new_slot->device, 0), 0x0B, &class_code);
+
+		pci_bus_read_config_byte(pci_bus, PCI_DEVFN(new_slot->device, 0), PCI_HEADER_TYPE, &header_type);
+
+		if (header_type & 0x80)	/* Multi-function device */
+			max_functions = 8;
+		else
+			max_functions = 1;
+
+		function = 0;
+
+		do {
+			if ((header_type & 0x7F) == PCI_HEADER_TYPE_BRIDGE) {	  /* PCI-PCI Bridge */
+				/*  Recurse the subordinate bus */
+				pci_bus_read_config_byte(pci_bus, PCI_DEVFN(new_slot->device, function), 
+					PCI_SECONDARY_BUS, &secondary_bus);
+
+				sub_bus = (int) secondary_bus;
+
+				/* Save the config headers for the secondary bus. */
+				rc = pciehp_save_config(ctrl, sub_bus, 0, 0);
+
+				if (rc)
+					return(rc);
+
+			}	/* End of IF */
+
+			new_slot->status = 0;
+
+			for (cloop = 0; cloop < 0x20; cloop++) {
+				pci_bus_read_config_dword(pci_bus, PCI_DEVFN(new_slot->device, function), 
+					cloop << 2, (u32 *) & (new_slot->config_space [cloop]));
+			}
+
+			function++;
+
+			stop_it = 0;
+
+			/*  this loop skips to the next present function
+			 *  reading in the Class Code and the Header type.
+			 */
+
+			while ((function < max_functions) && (!stop_it)) {
+				pci_bus_read_config_dword(pci_bus, PCI_DEVFN(new_slot->device, function), PCI_VENDOR_ID, &ID);
+
+				if (ID == 0xFFFFFFFF) {	 /* nothing there. */
+					function++;
+				} else {  /* Something there */
+					pci_bus_read_config_byte(pci_bus, PCI_DEVFN(new_slot->device, function), 0x0B, &class_code);
+
+					pci_bus_read_config_byte(pci_bus, PCI_DEVFN(new_slot->device, function), PCI_HEADER_TYPE, 
+						&header_type);
+
+					stop_it++;
+				}
+			}
+
+		} while (function < max_functions);
+	}			/* End of IF (device in slot?) */
+	else {
+		return(2);
+	}
+
+	return(0);
+}
+
+
+/*
+ * pciehp_save_used_resources
+ *
+ * Stores used resource information for existing boards.  this is
+ * for boards that were in the system when this driver was loaded.
+ * this function is for hot plug ADD
+ *
+ * returns 0 if success
+ * if disable  == 1(DISABLE_CARD),
+ *  it loops for all functions of the slot and disables them.
+ * else, it just get resources of the function and return.
+ */
+int pciehp_save_used_resources (struct controller *ctrl, struct pci_func *func, int disable)
+{
+	u8 cloop;
+	u8 header_type;
+	u8 secondary_bus;
+	u8 temp_byte;
+	u16 command;
+	u16 save_command;
+	u16 w_base, w_length;
+	u32 temp_register;
+	u32 save_base;
+	u32 base, length;
+	u64 base64 = 0;
+	int index = 0;
+	unsigned int devfn;
+	struct pci_resource *mem_node = NULL;
+	struct pci_resource *p_mem_node = NULL;
+	struct pci_resource *t_mem_node;
+	struct pci_resource *io_node;
+	struct pci_resource *bus_node;
+	struct pci_bus lpci_bus, *pci_bus;
+	memcpy(&lpci_bus, ctrl->pci_dev->subordinate, sizeof(lpci_bus));
+	pci_bus = &lpci_bus;
+
+	if (disable)
+		func = pciehp_slot_find(func->bus, func->device, index++);
+
+	while ((func != NULL) && func->is_a_board) {
+		pci_bus->number = func->bus;
+		devfn = PCI_DEVFN(func->device, func->function);
+
+		/* Save the command register */
+		pci_bus_read_config_word (pci_bus, devfn, PCI_COMMAND, &save_command);
+
+		if (disable) {
+			/* disable card */
+			command = 0x00;
+			pci_bus_write_config_word(pci_bus, devfn, PCI_COMMAND, command);
+		}
+
+		/* Check for Bridge */
+		pci_bus_read_config_byte (pci_bus, devfn, PCI_HEADER_TYPE, &header_type);
+
+		if ((header_type & 0x7F) == PCI_HEADER_TYPE_BRIDGE) {     /* PCI-PCI Bridge */
+			dbg("Save_used_res of PCI bridge b:d=0x%x:%x, sc=0x%x\n", func->bus, func->device, save_command);
+			if (disable) {
+				/* Clear Bridge Control Register */
+				command = 0x00;
+				pci_bus_write_config_word(pci_bus, devfn, PCI_BRIDGE_CONTROL, command);
+			}
+
+			pci_bus_read_config_byte (pci_bus, devfn, PCI_SECONDARY_BUS, &secondary_bus);
+			pci_bus_read_config_byte (pci_bus, devfn, PCI_SUBORDINATE_BUS, &temp_byte);
+
+			bus_node =(struct pci_resource *) kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
+			if (!bus_node)
+				return -ENOMEM;
+
+			bus_node->base = (ulong)secondary_bus;
+			bus_node->length = (ulong)(temp_byte - secondary_bus + 1);
+
+			bus_node->next = func->bus_head;
+			func->bus_head = bus_node;
+
+			/* Save IO base and Limit registers */
+			pci_bus_read_config_byte (pci_bus, devfn, PCI_IO_BASE, &temp_byte);
+			base = temp_byte;
+			pci_bus_read_config_byte (pci_bus, devfn, PCI_IO_LIMIT, &temp_byte);
+			length = temp_byte;
+
+			if ((base <= length) && (!disable || (save_command & PCI_COMMAND_IO))) {
+				io_node = (struct pci_resource *) kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
+				if (!io_node)
+					return -ENOMEM;
+
+				io_node->base = (ulong)(base & PCI_IO_RANGE_MASK) << 8;
+				io_node->length = (ulong)(length - base + 0x10) << 8;
+
+				io_node->next = func->io_head;
+				func->io_head = io_node;
+			}
+
+			/* Save memory base and Limit registers */
+			pci_bus_read_config_word (pci_bus, devfn, PCI_MEMORY_BASE, &w_base);
+			pci_bus_read_config_word (pci_bus, devfn, PCI_MEMORY_LIMIT, &w_length);
+
+			if ((w_base <= w_length) && (!disable || (save_command & PCI_COMMAND_MEMORY))) {
+				mem_node = (struct pci_resource *) kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
+				if (!mem_node)
+					return -ENOMEM;
+
+				mem_node->base = (ulong)w_base << 16;
+				mem_node->length = (ulong)(w_length - w_base + 0x10) << 16;
+
+				mem_node->next = func->mem_head;
+				func->mem_head = mem_node;
+			}
+			/* Save prefetchable memory base and Limit registers */
+			pci_bus_read_config_word (pci_bus, devfn, PCI_PREF_MEMORY_BASE, &w_base);
+			pci_bus_read_config_word (pci_bus, devfn, PCI_PREF_MEMORY_LIMIT, &w_length);
+
+			if ((w_base <= w_length) && (!disable || (save_command & PCI_COMMAND_MEMORY))) {
+				p_mem_node = (struct pci_resource *) kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
+				if (!p_mem_node)
+					return -ENOMEM;
+
+				p_mem_node->base = (ulong)w_base << 16;
+				p_mem_node->length = (ulong)(w_length - w_base + 0x10) << 16;
+
+				p_mem_node->next = func->p_mem_head;
+				func->p_mem_head = p_mem_node;
+			}
+		} else if ((header_type & 0x7F) == PCI_HEADER_TYPE_NORMAL) {
+			dbg("Save_used_res of PCI adapter b:d=0x%x:%x, sc=0x%x\n", func->bus, func->device, save_command);
+
+			/* Figure out IO and memory base lengths */
+			for (cloop = PCI_BASE_ADDRESS_0; cloop <= PCI_BASE_ADDRESS_5; cloop += 4) {
+				pci_bus_read_config_dword (pci_bus, devfn, cloop, &save_base);
+
+				temp_register = 0xFFFFFFFF;
+				pci_bus_write_config_dword (pci_bus, devfn, cloop, temp_register);
+				pci_bus_read_config_dword (pci_bus, devfn, cloop, &temp_register);
+
+				if (!disable) {
+					pci_bus_write_config_dword (pci_bus, devfn, cloop, save_base);
+				}
+
+				if (!temp_register)
+					continue;
+
+				base = temp_register;
+
+				if ((base & PCI_BASE_ADDRESS_SPACE_IO) && (!disable || (save_command & PCI_COMMAND_IO))) {
+					/* IO base */
+					/* set temp_register = amount of IO space requested */
+					base = base & 0xFFFFFFFCL;
+					base = (~base) + 1;
+
+					io_node = (struct pci_resource *) kmalloc(sizeof (struct pci_resource), GFP_KERNEL);
+					if (!io_node)
+						return -ENOMEM;
+
+					io_node->base = (ulong)save_base & PCI_BASE_ADDRESS_IO_MASK;
+					io_node->length = (ulong)base;
+					dbg("sur adapter: IO bar=0x%x(length=0x%x)\n", io_node->base, io_node->length);
+
+					io_node->next = func->io_head;
+					func->io_head = io_node;
+				} else {  /* map Memory */
+					int prefetchable = 1;
+					/* struct pci_resources **res_node; */
+					char *res_type_str = "PMEM";
+					u32 temp_register2;
+
+					t_mem_node = (struct pci_resource *) kmalloc(sizeof (struct pci_resource), GFP_KERNEL);
+					if (!t_mem_node)
+						return -ENOMEM;
+
+					if (!(base & PCI_BASE_ADDRESS_MEM_PREFETCH) && (!disable || (save_command & PCI_COMMAND_MEMORY))) {
+						prefetchable = 0;
+						mem_node = t_mem_node;
+						res_type_str++;
+					} else
+						p_mem_node = t_mem_node;
+
+					base = base & 0xFFFFFFF0L;
+					base = (~base) + 1;
+
+					switch (temp_register & PCI_BASE_ADDRESS_MEM_TYPE_MASK) {
+					case PCI_BASE_ADDRESS_MEM_TYPE_32:
+						if (prefetchable) {
+							p_mem_node->base = (ulong)save_base & PCI_BASE_ADDRESS_MEM_MASK;
+							p_mem_node->length = (ulong)base;
+							dbg("sur adapter: 32 %s bar=0x%x(length=0x%x)\n", res_type_str, 
+								p_mem_node->base, p_mem_node->length);
+
+							p_mem_node->next = func->p_mem_head;
+							func->p_mem_head = p_mem_node;
+						} else {
+							mem_node->base = (ulong)save_base & PCI_BASE_ADDRESS_MEM_MASK;
+							mem_node->length = (ulong)base;
+							dbg("sur adapter: 32 %s bar=0x%x(length=0x%x)\n", res_type_str, 
+								mem_node->base, mem_node->length);
+
+							mem_node->next = func->mem_head;
+							func->mem_head = mem_node;
+						}
+						break;
+					case PCI_BASE_ADDRESS_MEM_TYPE_64:
+						pci_bus_read_config_dword(pci_bus, devfn, cloop+4, &temp_register2);
+						base64 = temp_register2;
+						base64 = (base64 << 32) | save_base;
+
+						if (temp_register2) {
+							dbg("sur adapter: 64 %s high dword of base64(0x%x:%x) masked to 0\n", 
+								res_type_str, temp_register2, (u32)base64);
+							base64 &= 0x00000000FFFFFFFFL;
+						}
+
+						if (prefetchable) {
+							p_mem_node->base = base64 & PCI_BASE_ADDRESS_MEM_MASK;
+							p_mem_node->length = base;
+							dbg("sur adapter: 64 %s base=0x%x(len=0x%x)\n", res_type_str, 
+								p_mem_node->base, p_mem_node->length);
+
+							p_mem_node->next = func->p_mem_head;
+							func->p_mem_head = p_mem_node;
+						} else {
+							mem_node->base = base64 & PCI_BASE_ADDRESS_MEM_MASK;
+							mem_node->length = base;
+							dbg("sur adapter: 64 %s base=0x%x(len=0x%x)\n", res_type_str, 
+								mem_node->base, mem_node->length);
+
+							mem_node->next = func->mem_head;
+							func->mem_head = mem_node;
+						}
+						cloop += 4;
+						break;
+					default:
+						dbg("asur: reserved BAR type=0x%x\n", temp_register);
+						break;
+					}
+				} 
+			}	/* End of base register loop */
+		} else {	/* Some other unknown header type */
+			dbg("Save_used_res of PCI unknown type b:d=0x%x:%x. skip.\n", func->bus, func->device);
+		}
+
+		/* find the next device in this slot */
+		if (!disable)
+			break;
+		func = pciehp_slot_find(func->bus, func->device, index++);
+	}
+
+	return(0);
+}
+
+
+/*
+ * pciehp_return_board_resources
+ *
+ * this routine returns all resources allocated to a board to
+ * the available pool.
+ *
+ * returns 0 if success
+ */
+int pciehp_return_board_resources(struct pci_func * func, struct resource_lists * resources)
+{
+	int rc = 0;
+	struct pci_resource *node;
+	struct pci_resource *t_node;
+	dbg("%s\n", __FUNCTION__);
+
+	if (!func)
+		return(1);
+
+	node = func->io_head;
+	func->io_head = NULL;
+	while (node) {
+		t_node = node->next;
+		return_resource(&(resources->io_head), node);
+		node = t_node;
+	}
+
+	node = func->mem_head;
+	func->mem_head = NULL;
+	while (node) {
+		t_node = node->next;
+		return_resource(&(resources->mem_head), node);
+		node = t_node;
+	}
+
+	node = func->p_mem_head;
+	func->p_mem_head = NULL;
+	while (node) {
+		t_node = node->next;
+		return_resource(&(resources->p_mem_head), node);
+		node = t_node;
+	}
+
+	node = func->bus_head;
+	func->bus_head = NULL;
+	while (node) {
+		t_node = node->next;
+		return_resource(&(resources->bus_head), node);
+		node = t_node;
+	}
+
+	rc |= pciehp_resource_sort_and_combine(&(resources->mem_head));
+	rc |= pciehp_resource_sort_and_combine(&(resources->p_mem_head));
+	rc |= pciehp_resource_sort_and_combine(&(resources->io_head));
+	rc |= pciehp_resource_sort_and_combine(&(resources->bus_head));
+
+	return(rc);
+}
+
+
+/*
+ * pciehp_destroy_resource_list
+ *
+ * Puts node back in the resource list pointed to by head
+ */
+void pciehp_destroy_resource_list (struct resource_lists * resources)
+{
+	struct pci_resource *res, *tres;
+
+	res = resources->io_head;
+	resources->io_head = NULL;
+
+	while (res) {
+		tres = res;
+		res = res->next;
+		kfree(tres);
+	}
+
+	res = resources->mem_head;
+	resources->mem_head = NULL;
+
+	while (res) {
+		tres = res;
+		res = res->next;
+		kfree(tres);
+	}
+
+	res = resources->p_mem_head;
+	resources->p_mem_head = NULL;
+
+	while (res) {
+		tres = res;
+		res = res->next;
+		kfree(tres);
+	}
+
+	res = resources->bus_head;
+	resources->bus_head = NULL;
+
+	while (res) {
+		tres = res;
+		res = res->next;
+		kfree(tres);
+	}
+}
+
+
+/*
+ * pciehp_destroy_board_resources
+ *
+ * Puts node back in the resource list pointed to by head
+ */
+void pciehp_destroy_board_resources (struct pci_func * func)
+{
+	struct pci_resource *res, *tres;
+
+	res = func->io_head;
+	func->io_head = NULL;
+
+	while (res) {
+		tres = res;
+		res = res->next;
+		kfree(tres);
+	}
+
+	res = func->mem_head;
+	func->mem_head = NULL;
+
+	while (res) {
+		tres = res;
+		res = res->next;
+		kfree(tres);
+	}
+
+	res = func->p_mem_head;
+	func->p_mem_head = NULL;
+
+	while (res) {
+		tres = res;
+		res = res->next;
+		kfree(tres);
+	}
+
+	res = func->bus_head;
+	func->bus_head = NULL;
+
+	while (res) {
+		tres = res;
+		res = res->next;
+		kfree(tres);
+	}
+}
+
--- diff/drivers/pci/hotplug/pciehp_sysfs.c	1970-01-01 01:00:00.000000000 +0100
+++ source/drivers/pci/hotplug/pciehp_sysfs.c	2004-02-23 13:56:44.000000000 +0000
@@ -0,0 +1,143 @@
+/*
+ * PCI Express Hot Plug Controller Driver
+ *
+ * Copyright (C) 1995,2001 Compaq Computer Corporation
+ * Copyright (C) 2001,2003 Greg Kroah-Hartman (greg@kroah.com)
+ * Copyright (C) 2001 IBM Corp.
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Send feedback to <greg@kroah.com>
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/proc_fs.h>
+#include <linux/workqueue.h>
+#include <linux/pci.h>
+#include "pciehp.h"
+
+
+/* A few routines that create sysfs entries for the hot plug controller */
+
+static ssize_t show_ctrl (struct device *dev, char *buf)
+{
+	struct pci_dev *pci_dev;
+	struct controller *ctrl;
+	char * out = buf;
+	int index;
+	struct pci_resource *res;
+
+	pci_dev = container_of (dev, struct pci_dev, dev);
+	ctrl = pci_get_drvdata(pci_dev);
+
+	out += sprintf(buf, "Free resources: memory\n");
+	index = 11;
+	res = ctrl->mem_head;
+	while (res && index--) {
+		out += sprintf(out, "start = %8.8x, length = %8.8x\n", res->base, res->length);
+		res = res->next;
+	}
+	out += sprintf(out, "Free resources: prefetchable memory\n");
+	index = 11;
+	res = ctrl->p_mem_head;
+	while (res && index--) {
+		out += sprintf(out, "start = %8.8x, length = %8.8x\n", res->base, res->length);
+		res = res->next;
+	}
+	out += sprintf(out, "Free resources: IO\n");
+	index = 11;
+	res = ctrl->io_head;
+	while (res && index--) {
+		out += sprintf(out, "start = %8.8x, length = %8.8x\n", res->base, res->length);
+		res = res->next;
+	}
+	out += sprintf(out, "Free resources: bus numbers\n");
+	index = 11;
+	res = ctrl->bus_head;
+	while (res && index--) {
+		out += sprintf(out, "start = %8.8x, length = %8.8x\n", res->base, res->length);
+		res = res->next;
+	}
+
+	return out - buf;
+}
+static DEVICE_ATTR (ctrl, S_IRUGO, show_ctrl, NULL);
+
+static ssize_t show_dev (struct device *dev, char *buf)
+{
+	struct pci_dev *pci_dev;
+	struct controller *ctrl;
+	char * out = buf;
+	int index;
+	struct pci_resource *res;
+	struct pci_func *new_slot;
+	struct slot *slot;
+
+	pci_dev = container_of (dev, struct pci_dev, dev);
+	ctrl = pci_get_drvdata(pci_dev);
+
+	slot=ctrl->slot;
+
+	while (slot) {
+		new_slot = pciehp_slot_find(slot->bus, slot->device, 0);
+		if (!new_slot)
+			break;
+		out += sprintf(out, "assigned resources: memory\n");
+		index = 11;
+		res = new_slot->mem_head;
+		while (res && index--) {
+			out += sprintf(out, "start = %8.8x, length = %8.8x\n", res->base, res->length);
+			res = res->next;
+		}
+		out += sprintf(out, "assigned resources: prefetchable memory\n");
+		index = 11;
+		res = new_slot->p_mem_head;
+		while (res && index--) {
+			out += sprintf(out, "start = %8.8x, length = %8.8x\n", res->base, res->length);
+			res = res->next;
+		}
+		out += sprintf(out, "assigned resources: IO\n");
+		index = 11;
+		res = new_slot->io_head;
+		while (res && index--) {
+			out += sprintf(out, "start = %8.8x, length = %8.8x\n", res->base, res->length);
+			res = res->next;
+		}
+		out += sprintf(out, "assigned resources: bus numbers\n");
+		index = 11;
+		res = new_slot->bus_head;
+		while (res && index--) {
+			out += sprintf(out, "start = %8.8x, length = %8.8x\n", res->base, res->length);
+			res = res->next;
+		}
+		slot=slot->next;
+	}
+
+	return out - buf;
+}
+static DEVICE_ATTR (dev, S_IRUGO, show_dev, NULL);
+
+void pciehp_create_ctrl_files (struct controller *ctrl)
+{
+	device_create_file (&ctrl->pci_dev->dev, &dev_attr_ctrl);
+	device_create_file (&ctrl->pci_dev->dev, &dev_attr_dev);
+}
--- diff/drivers/pci/hotplug/pciehprm.h	1970-01-01 01:00:00.000000000 +0100
+++ source/drivers/pci/hotplug/pciehprm.h	2004-02-23 13:56:44.000000000 +0000
@@ -0,0 +1,53 @@
+/*
+ * PCIEHPRM : PCIEHP Resource Manager for ACPI/non-ACPI platform
+ *
+ * Copyright (C) 1995,2001 Compaq Computer Corporation
+ * Copyright (C) 2001,2003 Greg Kroah-Hartman (greg@kroah.com)
+ * Copyright (C) 2001 IBM Corp.
+ * Copyright (C) 2003-2004 Intel Corporation
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Send feedback to <greg@kroah.com>, <dely.l.sy@intel.com>
+ *
+ */
+
+#ifndef _PCIEHPRM_H_
+#define _PCIEHPRM_H_
+
+#ifdef	CONFIG_HOTPLUG_PCI_PCIE_PHPRM_NONACPI
+#include "pciehprm_nonacpi.h"
+#endif
+
+int pciehprm_init(enum php_ctlr_type ct);
+void pciehprm_cleanup(void);
+int pciehprm_print_pirt(void);
+void *pciehprm_get_slot(struct slot *slot);
+int pciehprm_find_available_resources(struct controller *ctrl);
+int pciehprm_set_hpp(struct controller *ctrl, struct pci_func *func, u8 card_type);
+void pciehprm_enable_card(struct controller *ctrl, struct pci_func *func, u8 card_type);
+
+#ifdef	DEBUG
+#define RES_CHECK(this, bits)	\
+	{ if (((this) & (bits - 1))) \
+		printk("%s:%d ERR: potential res loss!\n", __FUNCTION__, __LINE__); }
+#else
+#define RES_CHECK(this, bits)
+#endif
+
+#endif				/* _PCIEHPRM_H_ */
--- diff/drivers/pci/hotplug/pciehprm_acpi.c	1970-01-01 01:00:00.000000000 +0100
+++ source/drivers/pci/hotplug/pciehprm_acpi.c	2004-02-23 13:56:44.000000000 +0000
@@ -0,0 +1,1689 @@
+/*
+ * PCIEHPRM ACPI: PHP Resource Manager for ACPI platform
+ *
+ * Copyright (C) 2003-2004 Intel Corporation
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Send feedback to <dely.l.sy@intel.com>
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/acpi.h>
+#include <linux/efi.h>
+#include <asm/uaccess.h>
+#include <asm/system.h>
+#ifdef	CONFIG_IA64
+#include <asm/iosapic.h>
+#endif
+#include <acpi/acpi.h>
+#include <acpi/acpi_bus.h>
+#include <acpi/actypes.h>
+#include "pciehp.h"
+#include "pciehprm.h"
+
+#define	PCI_MAX_BUS		0x100
+#define	ACPI_STA_DEVICE_PRESENT	0x01
+
+#define	METHOD_NAME__SUN	"_SUN"
+#define	METHOD_NAME__HPP	"_HPP"
+#define	METHOD_NAME_OSHP	"OSHP"
+
+#define	PHP_RES_BUS		0xA0
+#define	PHP_RES_IO		0xA1
+#define	PHP_RES_MEM		0xA2
+#define	PHP_RES_PMEM		0xA3
+
+#define	BRIDGE_TYPE_P2P		0x00
+#define	BRIDGE_TYPE_HOST	0x01
+
+/* this should go to drivers/acpi/include/ */
+struct acpi__hpp {
+	u8	cache_line_size;
+	u8	latency_timer;
+	u8	enable_serr;
+	u8	enable_perr;
+};
+
+struct acpi_php_slot {
+	struct acpi_php_slot	*next;
+	struct acpi_bridge	*bridge;
+	acpi_handle	handle;
+	int	seg;
+	int	bus;
+	int	dev;
+	int	fun;
+	u32	sun;
+	struct pci_resource *mem_head;
+	struct pci_resource *p_mem_head;
+	struct pci_resource *io_head;
+	struct pci_resource *bus_head;
+	void	*slot_ops;	/* _STA, _EJx, etc */
+	struct slot *slot;
+};		/* per func */
+
+struct acpi_bridge {
+	struct acpi_bridge	*parent;
+	struct acpi_bridge	*next;
+	struct acpi_bridge	*child;
+	acpi_handle	handle;
+	int seg;
+	int pbus;			/* pdev->bus->number		*/
+	int pdevice;			/* PCI_SLOT(pdev->devfn)	*/
+	int pfunction;			/* PCI_DEVFN(pdev->devfn)	*/
+	int bus;			/* pdev->subordinate->number	*/
+	struct acpi__hpp		*_hpp;
+	struct acpi_php_slot	*slots;
+	struct pci_resource 	*tmem_head;	/* total from crs	*/
+	struct pci_resource 	*tp_mem_head;	/* total from crs	*/
+	struct pci_resource 	*tio_head;	/* total from crs	*/
+	struct pci_resource 	*tbus_head;	/* total from crs	*/
+	struct pci_resource 	*mem_head;	/* available	*/
+	struct pci_resource 	*p_mem_head;	/* available	*/
+	struct pci_resource 	*io_head;	/* available	*/
+	struct pci_resource 	*bus_head;	/* available	*/
+	int scanned;
+	int type;
+};
+
+static struct acpi_bridge *acpi_bridges_head;
+
+static u8 * acpi_path_name( acpi_handle	handle)
+{
+	acpi_status		status;
+	static u8		path_name[ACPI_PATHNAME_MAX];
+	struct acpi_buffer	ret_buf = { ACPI_PATHNAME_MAX, path_name };
+
+	memset(path_name, 0, sizeof (path_name));
+	status = acpi_get_name(handle, ACPI_FULL_PATHNAME, &ret_buf);
+
+	if (ACPI_FAILURE(status))
+		return NULL;
+	else
+		return path_name;	
+}
+
+static void acpi_get__hpp ( struct acpi_bridge	*ab);
+static void acpi_run_oshp ( struct acpi_bridge	*ab);
+
+static int acpi_add_slot_to_php_slots(
+	struct acpi_bridge	*ab,
+	int			bus_num,
+	acpi_handle		handle,
+	u32			adr,
+	u32			sun
+	)
+{
+	struct acpi_php_slot	*aps;
+	static long	samesun = -1;
+
+	aps = (struct acpi_php_slot *) kmalloc (sizeof(struct acpi_php_slot), GFP_KERNEL);
+	if (!aps) {
+		err ("acpi_pciehprm: alloc for aps fail\n");
+		return -1;
+	}
+	memset(aps, 0, sizeof(struct acpi_php_slot));
+
+	aps->handle = handle;
+	aps->bus = bus_num;
+	aps->dev = (adr >> 16) & 0xffff;
+	aps->fun = adr & 0xffff;
+	aps->sun = sun;
+
+	aps->next = ab->slots;	/* cling to the bridge */
+	aps->bridge = ab;
+	ab->slots = aps;
+
+	ab->scanned += 1;
+	if (!ab->_hpp)
+		acpi_get__hpp(ab);
+
+	acpi_run_oshp(ab);
+
+	if (sun != samesun) {
+		info("acpi_pciehprm:   Slot sun(%x) at s:b:d:f=0x%02x:%02x:%02x:%02x\n", 
+			aps->sun, ab->seg, aps->bus, aps->dev, aps->fun);
+		samesun = sun;
+	}
+	return 0;
+}
+
+static void acpi_get__hpp ( struct acpi_bridge	*ab)
+{
+	acpi_status		status;
+	u8			nui[4];
+	struct acpi_buffer	ret_buf = { 0, NULL};
+	union acpi_object	*ext_obj, *package;
+	u8			*path_name = acpi_path_name(ab->handle);
+	int			i, len = 0;
+
+	/* get _hpp */
+	status = acpi_evaluate_object(ab->handle, METHOD_NAME__HPP, NULL, &ret_buf);
+	switch (status) {
+	case AE_BUFFER_OVERFLOW:
+		ret_buf.pointer = kmalloc (ret_buf.length, GFP_KERNEL);
+		if (!ret_buf.pointer) {
+			err ("acpi_pciehprm:%s alloc for _HPP fail\n", path_name);
+			return;
+		}
+		status = acpi_evaluate_object(ab->handle, METHOD_NAME__HPP, NULL, &ret_buf);
+		if (ACPI_SUCCESS(status))
+			break;
+	default:
+		if (ACPI_FAILURE(status)) {
+			err("acpi_pciehprm:%s _HPP fail=0x%x\n", path_name, status);
+			return;
+		}
+	}
+
+	ext_obj = (union acpi_object *) ret_buf.pointer;
+	if (ext_obj->type != ACPI_TYPE_PACKAGE) {
+		err ("acpi_pciehprm:%s _HPP obj not a package\n", path_name);
+		goto free_and_return;
+	}
+
+	len = ext_obj->package.count;
+	package = (union acpi_object *) ret_buf.pointer;
+	for ( i = 0; (i < len) || (i < 4); i++) {
+		ext_obj = (union acpi_object *) &package->package.elements[i];
+		switch (ext_obj->type) {
+		case ACPI_TYPE_INTEGER:
+			nui[i] = (u8)ext_obj->integer.value;
+			break;
+		default:
+			err ("acpi_pciehprm:%s _HPP obj type incorrect\n", path_name);
+			goto free_and_return;
+		}
+	}
+
+	ab->_hpp = kmalloc (sizeof (struct acpi__hpp), GFP_KERNEL);
+	memset(ab->_hpp, 0, sizeof(struct acpi__hpp));
+
+	ab->_hpp->cache_line_size	= nui[0];
+	ab->_hpp->latency_timer		= nui[1];
+	ab->_hpp->enable_serr		= nui[2];
+	ab->_hpp->enable_perr		= nui[3];
+
+	dbg("  _HPP: cache_line_size=0x%x\n", ab->_hpp->cache_line_size);
+	dbg("  _HPP: latency timer  =0x%x\n", ab->_hpp->latency_timer);
+	dbg("  _HPP: enable SERR    =0x%x\n", ab->_hpp->enable_serr);
+	dbg("  _HPP: enable PERR    =0x%x\n", ab->_hpp->enable_perr);
+
+free_and_return:
+	kfree(ret_buf.pointer);
+}
+
+static void acpi_run_oshp ( struct acpi_bridge	*ab)
+{
+	acpi_status		status;
+	u8			*path_name = acpi_path_name(ab->handle);
+	struct acpi_buffer	ret_buf = { 0, NULL};
+
+	/* run OSHP */
+	status = acpi_evaluate_object(ab->handle, METHOD_NAME_OSHP, NULL, &ret_buf);
+	if (ACPI_FAILURE(status)) {
+		err("acpi_pciehprm:%s OSHP fails=0x%x\n", path_name, status);
+	} else
+		dbg("acpi_pciehprm:%s OSHP passes =0x%x\n", path_name, status);
+	return;
+}
+
+static acpi_status acpi_evaluate_crs(
+	acpi_handle		handle,
+	struct acpi_resource	**retbuf
+	)
+{
+	acpi_status		status;
+	struct acpi_buffer	crsbuf;
+	u8			*path_name = acpi_path_name(handle);
+
+	crsbuf.length  = 0;
+	crsbuf.pointer = NULL;
+
+	status = acpi_get_current_resources (handle, &crsbuf);
+
+	switch (status) {
+	case AE_BUFFER_OVERFLOW:
+		break;		/* found */
+	case AE_NOT_FOUND:
+		dbg("acpi_pciehprm:%s _CRS not found\n", path_name);
+		return status;
+	default:
+		err ("acpi_pciehprm:%s _CRS fail=0x%x\n", path_name, status);
+		return status;
+	}
+
+	crsbuf.pointer = kmalloc (crsbuf.length, GFP_KERNEL);
+	if (!crsbuf.pointer) {
+		err ("acpi_pciehprm: alloc %ld bytes for %s _CRS fail\n", (ulong)crsbuf.length, path_name);
+		return AE_NO_MEMORY;
+	}
+
+	status = acpi_get_current_resources (handle, &crsbuf);
+	if (ACPI_FAILURE(status)) {
+		err("acpi_pciehprm: %s _CRS fail=0x%x.\n", path_name, status);
+		kfree(crsbuf.pointer);
+		return status;
+	}
+
+	*retbuf = crsbuf.pointer;
+
+	return status;
+}
+
+static void free_pci_resource ( struct pci_resource	*aprh)
+{
+	struct pci_resource	*res, *next;
+
+	for (res = aprh; res; res = next) {
+		next = res->next;
+		kfree(res);
+	}
+}
+
+static void print_pci_resource ( struct pci_resource	*aprh)
+{
+	struct pci_resource	*res;
+
+	for (res = aprh; res; res = res->next)
+		dbg("        base= 0x%x length= 0x%x\n", res->base, res->length);
+}
+
+static void print_slot_resources( struct acpi_php_slot	*aps)
+{
+	if (aps->bus_head) {
+		dbg("    BUS Resources:\n");
+		print_pci_resource (aps->bus_head);
+	}
+
+	if (aps->io_head) {
+		dbg("    IO Resources:\n");
+		print_pci_resource (aps->io_head);
+	}
+
+	if (aps->mem_head) {
+		dbg("    MEM Resources:\n");
+		print_pci_resource (aps->mem_head);
+	}
+
+	if (aps->p_mem_head) {
+		dbg("    PMEM Resources:\n");
+		print_pci_resource (aps->p_mem_head);
+	}
+}
+
+static void print_pci_resources( struct acpi_bridge	*ab)
+{
+	if (ab->tbus_head) {
+		dbg("    Total BUS Resources:\n");
+		print_pci_resource (ab->tbus_head);
+	}
+	if (ab->bus_head) {
+		dbg("    BUS Resources:\n");
+		print_pci_resource (ab->bus_head);
+	}
+
+	if (ab->tio_head) {
+		dbg("    Total IO Resources:\n");
+		print_pci_resource (ab->tio_head);
+	}
+	if (ab->io_head) {
+		dbg("    IO Resources:\n");
+		print_pci_resource (ab->io_head);
+	}
+
+	if (ab->tmem_head) {
+		dbg("    Total MEM Resources:\n");
+		print_pci_resource (ab->tmem_head);
+	}
+	if (ab->mem_head) {
+		dbg("    MEM Resources:\n");
+		print_pci_resource (ab->mem_head);
+	}
+
+	if (ab->tp_mem_head) {
+		dbg("    Total PMEM Resources:\n");
+		print_pci_resource (ab->tp_mem_head);
+	}
+	if (ab->p_mem_head) {
+		dbg("    PMEM Resources:\n");
+		print_pci_resource (ab->p_mem_head);
+	}
+	if (ab->_hpp) {
+		dbg("    _HPP: cache_line_size=0x%x\n", ab->_hpp->cache_line_size);
+		dbg("    _HPP: latency timer  =0x%x\n", ab->_hpp->latency_timer);
+		dbg("    _HPP: enable SERR    =0x%x\n", ab->_hpp->enable_serr);
+		dbg("    _HPP: enable PERR    =0x%x\n", ab->_hpp->enable_perr);
+	}
+}
+
+static int pciehprm_delete_resource(
+	struct pci_resource **aprh,
+	ulong base,
+	ulong size)
+{
+	struct pci_resource *res;
+	struct pci_resource *prevnode;
+	struct pci_resource *split_node;
+	ulong tbase;
+
+	pciehp_resource_sort_and_combine(aprh);
+
+	for (res = *aprh; res; res = res->next) {
+		if (res->base > base)
+			continue;
+
+		if ((res->base + res->length) < (base + size))
+			continue;
+
+		if (res->base < base) {
+			tbase = base;
+
+			if ((res->length - (tbase - res->base)) < size)
+				continue;
+
+			split_node = (struct pci_resource *) kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
+			if (!split_node)
+				return -ENOMEM;
+
+			split_node->base = res->base;
+			split_node->length = tbase - res->base;
+			res->base = tbase;
+			res->length -= split_node->length;
+
+			split_node->next = res->next;
+			res->next = split_node;
+		}
+
+		if (res->length >= size) {
+			split_node = (struct pci_resource*) kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
+			if (!split_node)
+				return -ENOMEM;
+
+			split_node->base = res->base + size;
+			split_node->length = res->length - size;
+			res->length = size;
+
+			split_node->next = res->next;
+			res->next = split_node;
+		}
+
+		if (*aprh == res) {
+			*aprh = res->next;
+		} else {
+			prevnode = *aprh;
+			while (prevnode->next != res)
+				prevnode = prevnode->next;
+
+			prevnode->next = res->next;
+		}
+		res->next = NULL;
+		kfree(res);
+		break;
+	}
+
+	return 0;
+}
+
+static int pciehprm_delete_resources(
+	struct pci_resource **aprh,
+	struct pci_resource *this
+	)
+{
+	struct pci_resource *res;
+
+	for (res = this; res; res = res->next)
+		pciehprm_delete_resource(aprh, res->base, res->length);
+
+	return 0;
+}
+
+static int pciehprm_add_resource(
+	struct pci_resource **aprh,
+	ulong base,
+	ulong size)
+{
+	struct pci_resource *res;
+
+	for (res = *aprh; res; res = res->next) {
+		if ((res->base + res->length) == base) {
+			res->length += size;
+			size = 0L;
+			break;
+		}
+		if (res->next == *aprh)
+			break;
+	}
+
+	if (size) {
+		res = kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
+		if (!res) {
+			err ("acpi_pciehprm: alloc for res fail\n");
+			return -ENOMEM;
+		}
+		memset(res, 0, sizeof (struct pci_resource));
+
+		res->base = base;
+		res->length = size;
+		res->next = *aprh;
+		*aprh = res;
+	}
+
+	return 0;
+}
+
+static int pciehprm_add_resources(
+	struct pci_resource **aprh,
+	struct pci_resource *this
+	)
+{
+	struct pci_resource *res;
+	int	rc = 0;
+
+	for (res = this; res && !rc; res = res->next)
+		rc = pciehprm_add_resource(aprh, res->base, res->length);
+
+	return rc;
+}
+
+static void acpi_parse_io (
+	struct acpi_bridge		*ab,
+	union acpi_resource_data	*data
+	)
+{
+	struct acpi_resource_io	*dataio;
+	dataio = (struct acpi_resource_io *) data;
+
+	dbg("Io Resource\n");
+	dbg("  %d bit decode\n", ACPI_DECODE_16 == dataio->io_decode ? 16:10);
+	dbg("  Range minimum base: %08X\n", dataio->min_base_address);
+	dbg("  Range maximum base: %08X\n", dataio->max_base_address);
+	dbg("  Alignment: %08X\n", dataio->alignment);
+	dbg("  Range Length: %08X\n", dataio->range_length);
+}
+
+static void acpi_parse_fixed_io (
+	struct acpi_bridge	*ab,
+	union acpi_resource_data	*data
+	)
+{
+	struct acpi_resource_fixed_io  *datafio;
+	datafio = (struct acpi_resource_fixed_io *) data;
+
+	dbg("Fixed Io Resource\n");
+	dbg("  Range base address: %08X", datafio->base_address);
+	dbg("  Range length: %08X", datafio->range_length);
+}
+
+static void acpi_parse_address16_32 (
+	struct acpi_bridge	*ab,
+	union acpi_resource_data	*data,
+	acpi_resource_type	id
+	)
+{
+	/* 
+	 * acpi_resource_address16 == acpi_resource_address32
+	 * acpi_resource_address16 *data16 = (acpi_resource_address16 *) data;
+	 */
+	struct acpi_resource_address32 *data32 = (struct acpi_resource_address32 *) data;
+	struct pci_resource **aprh, **tprh;
+
+	if (id == ACPI_RSTYPE_ADDRESS16)
+		dbg("acpi_pciehprm:16-Bit Address Space Resource\n");
+	else
+		dbg("acpi_pciehprm:32-Bit Address Space Resource\n");
+
+	switch (data32->resource_type) {
+	case ACPI_MEMORY_RANGE: 
+		dbg("  Resource Type: Memory Range\n");
+		aprh = &ab->mem_head;
+		tprh = &ab->tmem_head;
+
+		switch (data32->attribute.memory.cache_attribute) {
+		case ACPI_NON_CACHEABLE_MEMORY:
+			dbg("  Type Specific: Noncacheable memory\n");
+			break; 
+		case ACPI_CACHABLE_MEMORY:
+			dbg("  Type Specific: Cacheable memory\n");
+			break; 
+		case ACPI_WRITE_COMBINING_MEMORY:
+			dbg("  Type Specific: Write-combining memory\n");
+			break; 
+		case ACPI_PREFETCHABLE_MEMORY:
+			aprh = &ab->p_mem_head;
+			dbg("  Type Specific: Prefetchable memory\n");
+			break; 
+		default:
+			dbg("  Type Specific: Invalid cache attribute\n");
+			break;
+		}
+
+		dbg("  Type Specific: Read%s\n", ACPI_READ_WRITE_MEMORY == data32->attribute.memory.read_write_attribute ? "/Write":" Only");
+		break;
+
+	case ACPI_IO_RANGE: 
+		dbg("  Resource Type: I/O Range\n");
+		aprh = &ab->io_head;
+		tprh = &ab->tio_head;
+
+		switch (data32->attribute.io.range_attribute) {
+		case ACPI_NON_ISA_ONLY_RANGES:
+			dbg("  Type Specific: Non-ISA Io Addresses\n");
+			break; 
+		case ACPI_ISA_ONLY_RANGES:
+			dbg("  Type Specific: ISA Io Addresses\n");
+			break; 
+		case ACPI_ENTIRE_RANGE:
+			dbg("  Type Specific: ISA and non-ISA Io Addresses\n");
+			break; 
+		default:
+			dbg("  Type Specific: Invalid range attribute\n");
+			break;
+		}
+		break;
+
+	case ACPI_BUS_NUMBER_RANGE: 
+		dbg("  Resource Type: Bus Number Range(fixed)\n");
+		/* fixup to be compatible with the rest of php driver */
+		data32->min_address_range++;
+		data32->address_length--;
+		aprh = &ab->bus_head;
+		tprh = &ab->tbus_head;
+		break; 
+	default: 
+		dbg("  Resource Type: Invalid resource type. Exiting.\n");
+		return;
+	}
+
+	dbg("  Resource %s\n", ACPI_CONSUMER == data32->producer_consumer ? "Consumer":"Producer");
+	dbg("  %s decode\n", ACPI_SUB_DECODE == data32->decode ? "Subtractive":"Positive");
+	dbg("  Min address is %s fixed\n", ACPI_ADDRESS_FIXED == data32->min_address_fixed ? "":"not");
+	dbg("  Max address is %s fixed\n", ACPI_ADDRESS_FIXED == data32->max_address_fixed ? "":"not");
+	dbg("  Granularity: %08X\n", data32->granularity);
+	dbg("  Address range min: %08X\n", data32->min_address_range);
+	dbg("  Address range max: %08X\n", data32->max_address_range);
+	dbg("  Address translation offset: %08X\n", data32->address_translation_offset);
+	dbg("  Address Length: %08X\n", data32->address_length);
+
+	if (0xFF != data32->resource_source.index) {
+		dbg("  Resource Source Index: %X\n", data32->resource_source.index);
+		/* dbg("  Resource Source: %s\n", data32->resource_source.string_ptr); */
+	}
+
+	pciehprm_add_resource(aprh, data32->min_address_range, data32->address_length);
+}
+
+static acpi_status acpi_parse_crs(
+	struct acpi_bridge	*ab,
+	struct acpi_resource	*crsbuf
+	)
+{
+	acpi_status		status = AE_OK;
+	struct acpi_resource	*resource = crsbuf;
+	u8				count = 0;
+	u8				done = 0;
+
+	while (!done) {
+		dbg("acpi_pciehprm: PCI bus 0x%x Resource structure %x.\n", ab->bus, count++);
+		switch (resource->id) {
+		case ACPI_RSTYPE_IRQ:
+			dbg("Irq -------- Resource\n");
+			break; 
+		case ACPI_RSTYPE_DMA:
+			dbg("DMA -------- Resource\n");
+			break; 
+		case ACPI_RSTYPE_START_DPF:
+			dbg("Start DPF -------- Resource\n");
+			break; 
+		case ACPI_RSTYPE_END_DPF:
+			dbg("End DPF -------- Resource\n");
+			break; 
+		case ACPI_RSTYPE_IO:
+			acpi_parse_io (ab, &resource->data);
+			break; 
+		case ACPI_RSTYPE_FIXED_IO:
+			acpi_parse_fixed_io (ab, &resource->data);
+			break; 
+		case ACPI_RSTYPE_VENDOR:
+			dbg("Vendor -------- Resource\n");
+			break; 
+		case ACPI_RSTYPE_END_TAG:
+			dbg("End_tag -------- Resource\n");
+			done = 1;
+			break; 
+		case ACPI_RSTYPE_MEM24:
+			dbg("Mem24 -------- Resource\n");
+			break; 
+		case ACPI_RSTYPE_MEM32:
+			dbg("Mem32 -------- Resource\n");
+			break; 
+		case ACPI_RSTYPE_FIXED_MEM32:
+			dbg("Fixed Mem32 -------- Resource\n");
+			break; 
+		case ACPI_RSTYPE_ADDRESS16:
+			acpi_parse_address16_32(ab, &resource->data, ACPI_RSTYPE_ADDRESS16);
+			break; 
+		case ACPI_RSTYPE_ADDRESS32:
+			acpi_parse_address16_32(ab, &resource->data, ACPI_RSTYPE_ADDRESS32);
+			break; 
+		case ACPI_RSTYPE_ADDRESS64:
+			info("Address64 -------- Resource unparsed\n");
+			break; 
+		case ACPI_RSTYPE_EXT_IRQ:
+			dbg("Ext Irq -------- Resource\n");
+			break; 
+		default:
+			dbg("Invalid -------- resource type 0x%x\n", resource->id);
+			break;
+		}
+
+		resource = (struct acpi_resource *) ((char *)resource + resource->length);
+	}
+
+	return status;
+}
+
+static acpi_status acpi_get_crs( struct acpi_bridge	*ab)
+{
+	acpi_status		status;
+	struct acpi_resource	*crsbuf;
+
+	status = acpi_evaluate_crs(ab->handle, &crsbuf);
+	if (ACPI_SUCCESS(status)) {
+		status = acpi_parse_crs(ab, crsbuf);
+		kfree(crsbuf);
+
+		pciehp_resource_sort_and_combine(&ab->bus_head);
+		pciehp_resource_sort_and_combine(&ab->io_head);
+		pciehp_resource_sort_and_combine(&ab->mem_head);
+		pciehp_resource_sort_and_combine(&ab->p_mem_head);
+
+		pciehprm_add_resources (&ab->tbus_head, ab->bus_head);
+		pciehprm_add_resources (&ab->tio_head, ab->io_head);
+		pciehprm_add_resources (&ab->tmem_head, ab->mem_head);
+		pciehprm_add_resources (&ab->tp_mem_head, ab->p_mem_head);
+	}
+
+	return status;
+}
+
+/* find acpi_bridge downword from ab.  */
+static struct acpi_bridge *
+find_acpi_bridge_by_bus(
+	struct acpi_bridge *ab,
+	int seg,
+	int bus		/* pdev->subordinate->number */
+	)
+{
+	struct acpi_bridge	*lab = NULL;
+
+	if (!ab)
+		return NULL;
+
+	if ((ab->bus == bus) && (ab->seg == seg))
+		return ab;
+
+	if (ab->child)
+		lab = find_acpi_bridge_by_bus(ab->child, seg, bus);
+
+	if (!lab)
+	if (ab->next)
+		lab = find_acpi_bridge_by_bus(ab->next, seg, bus);
+
+	return lab;
+}
+
+/*
+ * Build a device tree of ACPI PCI Bridges
+ */
+static void pciehprm_acpi_register_a_bridge (
+	struct acpi_bridge	**head,
+	struct acpi_bridge	*pab,	/* parent bridge to which child bridge is added */
+	struct acpi_bridge	*cab	/* child bridge to add */
+	)
+{
+	struct acpi_bridge	*lpab;
+	struct acpi_bridge	*lcab;
+
+	lpab = find_acpi_bridge_by_bus(*head, pab->seg, pab->bus);
+	if (!lpab) {
+		if (!(pab->type & BRIDGE_TYPE_HOST))
+			warn("PCI parent bridge s:b(%x:%x) not in list.\n", pab->seg, pab->bus);
+		pab->next = *head;
+		*head = pab;
+		lpab = pab;
+	}
+
+	if ((cab->type & BRIDGE_TYPE_HOST) && (pab == cab))
+		return;
+
+	lcab = find_acpi_bridge_by_bus(*head, cab->seg, cab->bus);
+	if (lcab) {
+		if ((pab->bus != lcab->parent->bus) || (lcab->bus != cab->bus))
+			err("PCI child bridge s:b(%x:%x) in list with diff parent.\n", cab->seg, cab->bus);
+		return;
+	} else
+		lcab = cab;
+
+	lcab->parent = lpab;
+	lcab->next = lpab->child;
+	lpab->child = lcab;
+}
+
+static acpi_status pciehprm_acpi_build_php_slots_callback(
+	acpi_handle		handle,
+	u32			Level,
+	void			*context,
+	void			**retval
+	)
+{
+	ulong		bus_num;
+	ulong		seg_num;
+	ulong		sun, adr;
+	ulong		padr = 0;
+	acpi_handle		phandle = NULL;
+	struct acpi_bridge	*pab = (struct acpi_bridge *)context;
+	struct acpi_bridge	*lab;
+	acpi_status		status;
+	u8			*path_name = acpi_path_name(handle);
+
+	/* get _SUN */
+	status = acpi_evaluate_integer(handle, METHOD_NAME__SUN, NULL, &sun);
+	switch(status) {
+	case AE_NOT_FOUND:
+		return AE_OK;
+	default:
+		if (ACPI_FAILURE(status)) {
+			err("acpi_pciehprm:%s _SUN fail=0x%x\n", path_name, status);
+			return status;
+		}
+	}
+
+	/* get _ADR. _ADR must exist if _SUN exists */
+	status = acpi_evaluate_integer(handle, METHOD_NAME__ADR, NULL, &adr);
+	if (ACPI_FAILURE(status)) {
+		err("acpi_pciehprm:%s _ADR fail=0x%x\n", path_name, status);
+		return status;
+	}
+
+	dbg("acpi_pciehprm:%s sun=0x%08x adr=0x%08x\n", path_name, (u32)sun, (u32)adr);
+
+	status = acpi_get_parent(handle, &phandle);
+	if (ACPI_FAILURE(status)) {
+		err("acpi_pciehprm:%s get_parent fail=0x%x\n", path_name, status);
+		return (status);
+	}
+
+	bus_num = pab->bus;
+	seg_num = pab->seg;
+
+	if (pab->bus == bus_num) {
+		lab = pab;
+	} else {
+		dbg("WARN: pab is not parent\n");
+		lab = find_acpi_bridge_by_bus(pab, seg_num, bus_num);
+		if (!lab) {
+			dbg("acpi_pciehprm: alloc new P2P bridge(%x) for sun(%08x)\n", (u32)bus_num, (u32)sun);
+			lab = (struct acpi_bridge *)kmalloc(sizeof(struct acpi_bridge), GFP_KERNEL);
+			if (!lab) {
+				err("acpi_pciehprm: alloc for ab fail\n");
+				return AE_NO_MEMORY;
+			}
+			memset(lab, 0, sizeof(struct acpi_bridge));
+
+			lab->handle = phandle;
+			lab->pbus = pab->bus;
+			lab->pdevice = (int)(padr >> 16) & 0xffff;
+			lab->pfunction = (int)(padr & 0xffff);
+			lab->bus = (int)bus_num;
+			lab->scanned = 0;
+			lab->type = BRIDGE_TYPE_P2P;
+
+			pciehprm_acpi_register_a_bridge (&acpi_bridges_head, pab, lab);
+		} else
+			dbg("acpi_pciehprm: found P2P bridge(%x) for sun(%08x)\n", (u32)bus_num, (u32)sun);
+	}
+
+	acpi_add_slot_to_php_slots(lab, (int)bus_num, handle, (u32)adr, (u32)sun);
+
+	return (status);
+}
+
+static int pciehprm_acpi_build_php_slots(
+	struct acpi_bridge	*ab,
+	u32			depth
+	)
+{
+	acpi_status	status;
+	u8		*path_name = acpi_path_name(ab->handle);
+
+	/* Walk down this pci bridge to get _SUNs if any behind P2P */
+	status = acpi_walk_namespace ( ACPI_TYPE_DEVICE,
+				ab->handle,
+				depth,
+				pciehprm_acpi_build_php_slots_callback,
+				ab,
+				NULL );
+	if (ACPI_FAILURE(status)) {
+		dbg("acpi_pciehprm:%s walk for _SUN on pci bridge seg:bus(%x:%x) fail=0x%x\n", path_name, ab->seg, ab->bus, status);
+		return -1;
+	}
+
+	return 0;
+}
+
+static void build_a_bridge(
+	struct acpi_bridge	*pab,
+	struct acpi_bridge	*ab
+	)
+{
+	u8		*path_name = acpi_path_name(ab->handle);
+
+	pciehprm_acpi_register_a_bridge (&acpi_bridges_head, pab, ab);
+
+	switch (ab->type) {
+	case BRIDGE_TYPE_HOST:
+		dbg("acpi_pciehprm: Registered PCI HOST Bridge(%02x)    on s:b:d:f(%02x:%02x:%02x:%02x) [%s]\n",
+			ab->bus, ab->seg, ab->pbus, ab->pdevice, ab->pfunction, path_name);
+		break;
+	case BRIDGE_TYPE_P2P:
+		dbg("acpi_pciehprm: Registered PCI  P2P Bridge(%02x-%02x) on s:b:d:f(%02x:%02x:%02x:%02x) [%s]\n",
+			ab->pbus, ab->bus, ab->seg, ab->pbus, ab->pdevice, ab->pfunction, path_name);
+		break;
+	};
+
+	/* build any immediate PHP slots under this pci bridge */
+	pciehprm_acpi_build_php_slots(ab, 1);
+}
+
+static struct acpi_bridge * add_p2p_bridge(
+	acpi_handle handle,
+	struct acpi_bridge	*pab,	/* parent */
+	ulong	adr
+	)
+{
+	struct acpi_bridge	*ab;
+	struct pci_dev	*pdev;
+	ulong		devnum, funcnum;
+	u8			*path_name = acpi_path_name(handle);
+
+	ab = (struct acpi_bridge *) kmalloc (sizeof(struct acpi_bridge), GFP_KERNEL);
+	if (!ab) {
+		err("acpi_pciehprm: alloc for ab fail\n");
+		return NULL;
+	}
+	memset(ab, 0, sizeof(struct acpi_bridge));
+
+	devnum = (adr >> 16) & 0xffff;
+	funcnum = adr & 0xffff;
+
+	pdev = pci_find_slot(pab->bus, PCI_DEVFN(devnum, funcnum));
+	if (!pdev || !pdev->subordinate) {
+		err("acpi_pciehprm:%s is not a P2P Bridge\n", path_name);
+		kfree(ab);
+		return NULL;
+	}
+
+	ab->handle = handle;
+	ab->seg = pab->seg;
+	ab->pbus = pab->bus;		/* or pdev->bus->number */
+	ab->pdevice = devnum;		/* or PCI_SLOT(pdev->devfn) */
+	ab->pfunction = funcnum;	/* or PCI_FUNC(pdev->devfn) */
+	ab->bus = pdev->subordinate->number;
+	ab->scanned = 0;
+	ab->type = BRIDGE_TYPE_P2P;
+
+	dbg("acpi_pciehprm: P2P(%x-%x) on pci=b:d:f(%x:%x:%x) acpi=b:d:f(%x:%x:%x) [%s]\n",
+		pab->bus, ab->bus, pdev->bus->number, PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn),
+		pab->bus, (u32)devnum, (u32)funcnum, path_name);
+
+	build_a_bridge(pab, ab);
+
+	return ab;
+}
+
+static acpi_status scan_p2p_bridge(
+	acpi_handle		handle,
+	u32			Level,
+	void			*context,
+	void			**retval
+	)
+{
+	struct acpi_bridge	*pab = (struct acpi_bridge *)context;
+	struct acpi_bridge	*ab;
+	acpi_status		status;
+	ulong			adr = 0;
+	u8			*path_name = acpi_path_name(handle);
+	ulong			devnum, funcnum;
+	struct pci_dev		*pdev;
+
+	/* get device, function */
+	status = acpi_evaluate_integer(handle, METHOD_NAME__ADR, NULL, &adr);
+	if (ACPI_FAILURE(status)) {
+		if (status != AE_NOT_FOUND)
+			err("acpi_pciehprm:%s _ADR fail=0x%x\n", path_name, status);
+		return AE_OK;
+	}
+
+	devnum = (adr >> 16) & 0xffff;
+	funcnum = adr & 0xffff;
+
+	pdev = pci_find_slot(pab->bus, PCI_DEVFN(devnum, funcnum));
+	if (!pdev)
+		return AE_OK;
+	if (!pdev->subordinate)
+		return AE_OK;
+
+	ab = add_p2p_bridge(handle, pab, adr);
+	if (ab) {
+		status = acpi_walk_namespace ( ACPI_TYPE_DEVICE,
+					handle,
+					(u32)1,
+					scan_p2p_bridge,
+					ab,
+					NULL);
+		if (ACPI_FAILURE(status))
+			dbg("acpi_pciehprm:%s find_p2p fail=0x%x\n", path_name, status);
+	}
+
+	return AE_OK;
+}
+
+static struct acpi_bridge * add_host_bridge(
+	acpi_handle handle,
+	ulong	segnum,
+	ulong	busnum
+	)
+{
+	ulong			adr = 0;
+	acpi_status		status;
+	struct acpi_bridge	*ab;
+	u8			*path_name = acpi_path_name(handle);
+
+	/* get device, function: host br adr is always 0000 though.  */
+	status = acpi_evaluate_integer(handle, METHOD_NAME__ADR, NULL, &adr);
+	if (ACPI_FAILURE(status)) {
+		err("acpi_pciehprm:%s _ADR fail=0x%x\n", path_name, status);
+		return NULL;
+	}
+	dbg("acpi_pciehprm: ROOT PCI seg(0x%x)bus(0x%x)dev(0x%x)func(0x%x) [%s]\n", (u32)segnum, 
+		(u32)busnum, (u32)(adr >> 16) & 0xffff, (u32)adr & 0xffff, path_name);
+
+	ab = (struct acpi_bridge *) kmalloc (sizeof(struct acpi_bridge), GFP_KERNEL);
+	if (!ab) {
+		err("acpi_pciehprm: alloc for ab fail\n");
+		return NULL;
+	}
+	memset(ab, 0, sizeof(struct acpi_bridge));
+
+	ab->handle = handle;
+	ab->seg = (int)segnum;
+	ab->bus = ab->pbus = (int)busnum;
+	ab->pdevice = (int)(adr >> 16) & 0xffff;
+	ab->pfunction = (int)(adr & 0xffff);
+	ab->scanned = 0;
+	ab->type = BRIDGE_TYPE_HOST;
+
+	/* get root pci bridge's current resources */
+	status = acpi_get_crs(ab);
+	if (ACPI_FAILURE(status)) {
+		err("acpi_pciehprm:%s evaluate _CRS fail=0x%x\n", path_name, status);
+		kfree(ab);
+		return NULL;
+	}
+	build_a_bridge(ab, ab);
+
+	return ab;
+}
+
+static acpi_status acpi_scan_from_root_pci_callback (
+	acpi_handle	handle,
+	u32			Level,
+	void		*context,
+	void		**retval
+	)
+{
+	ulong		segnum = 0;
+	ulong		busnum = 0;
+	acpi_status		status;
+	struct acpi_bridge	*ab;
+	u8			*path_name = acpi_path_name(handle);
+
+	/* get bus number of this pci root bridge */
+	status = acpi_evaluate_integer(handle, METHOD_NAME__SEG, NULL, &segnum);
+	if (ACPI_FAILURE(status)) {
+		if (status != AE_NOT_FOUND) {
+			err("acpi_pciehprm:%s evaluate _SEG fail=0x%x\n", path_name, status);
+			return status;
+		}
+		segnum = 0;
+	}
+
+	/* get bus number of this pci root bridge */
+	status = acpi_evaluate_integer(handle, METHOD_NAME__BBN, NULL, &busnum);
+	if (ACPI_FAILURE(status)) {
+		err("acpi_pciehprm:%s evaluate _BBN fail=0x%x\n", path_name, status);
+		return (status);
+	}
+
+	ab = add_host_bridge(handle, segnum, busnum);
+	if (ab) {
+		status = acpi_walk_namespace ( ACPI_TYPE_DEVICE,
+					handle,
+					1,
+					scan_p2p_bridge,
+					ab,
+					NULL);
+		if (ACPI_FAILURE(status))
+			dbg("acpi_pciehprm:%s find_p2p fail=0x%x\n", path_name, status);
+	}
+
+	return AE_OK;
+}
+
+static int pciehprm_acpi_scan_pci (void)
+{
+	acpi_status	status;
+
+	/*
+	 * TBD: traverse LDM device tree with the help of
+	 *  unified ACPI augmented for php device population.
+	 */
+	status = acpi_get_devices ( PCI_ROOT_HID_STRING,
+				acpi_scan_from_root_pci_callback,
+				NULL,
+				NULL );
+	if (ACPI_FAILURE(status)) {
+		err("acpi_pciehprm:get_device PCI ROOT HID fail=0x%x\n", status);
+		return -1;
+	}
+
+	return 0;
+}
+
+int pciehprm_init(enum php_ctlr_type ctlr_type)
+{
+	int	rc;
+
+	if (ctlr_type != PCI)
+		return -ENODEV;
+
+	dbg("pciehprm ACPI init <enter>\n");
+	acpi_bridges_head = NULL;
+
+	/* construct PCI bus:device tree of acpi_handles */
+	rc = pciehprm_acpi_scan_pci();
+	if (rc)
+		return rc;
+
+	dbg("pciehprm ACPI init %s\n", (rc)?"fail":"success");
+	return rc;
+}
+
+static void free_a_slot(struct acpi_php_slot *aps)
+{
+	dbg("        free a php func of slot(0x%02x) on PCI b:d:f=0x%02x:%02x:%02x\n", aps->sun, aps->bus, aps->dev, aps->fun);
+
+	free_pci_resource (aps->io_head);
+	free_pci_resource (aps->bus_head);
+	free_pci_resource (aps->mem_head);
+	free_pci_resource (aps->p_mem_head);
+
+	kfree(aps);
+}
+
+static void free_a_bridge( struct acpi_bridge	*ab)
+{
+	struct acpi_php_slot	*aps, *next;
+
+	switch (ab->type) {
+	case BRIDGE_TYPE_HOST:
+		dbg("Free ACPI PCI HOST Bridge(%x) [%s] on s:b:d:f(%x:%x:%x:%x)\n",
+			ab->bus, acpi_path_name(ab->handle), ab->seg, ab->pbus, ab->pdevice, ab->pfunction);
+		break;
+	case BRIDGE_TYPE_P2P:
+		dbg("Free ACPI PCI P2P Bridge(%x-%x) [%s] on s:b:d:f(%x:%x:%x:%x)\n",
+			ab->pbus, ab->bus, acpi_path_name(ab->handle), ab->seg, ab->pbus, ab->pdevice, ab->pfunction);
+		break;
+	};
+
+	/* free slots first */
+	for (aps = ab->slots; aps; aps = next) {
+		next = aps->next;
+		free_a_slot(aps);
+	}
+
+	free_pci_resource (ab->io_head);
+	free_pci_resource (ab->tio_head);
+	free_pci_resource (ab->bus_head);
+	free_pci_resource (ab->tbus_head);
+	free_pci_resource (ab->mem_head);
+	free_pci_resource (ab->tmem_head);
+	free_pci_resource (ab->p_mem_head);
+	free_pci_resource (ab->tp_mem_head);
+
+	kfree(ab);
+}
+
+static void pciehprm_free_bridges ( struct acpi_bridge	*ab)
+{
+	if (ab->child)
+		pciehprm_free_bridges (ab->child);
+
+	if (ab->next)
+		pciehprm_free_bridges (ab->next);
+
+	free_a_bridge(ab);
+}
+
+void pciehprm_cleanup(void)
+{
+	pciehprm_free_bridges (acpi_bridges_head);
+}
+
+static int get_number_of_slots (
+	struct acpi_bridge	*ab,
+	int				selfonly
+	)
+{
+	struct acpi_php_slot	*aps;
+	int	prev_slot = -1;
+	int	slot_num = 0;
+
+	for ( aps = ab->slots; aps; aps = aps->next)
+		if (aps->dev != prev_slot) {
+			prev_slot = aps->dev;
+			slot_num++;
+		}
+
+	if (ab->child)
+		slot_num += get_number_of_slots (ab->child, 0);
+
+	if (selfonly)
+		return slot_num;
+
+	if (ab->next)
+		slot_num += get_number_of_slots (ab->next, 0);
+
+	return slot_num;
+}
+
+static int print_acpi_resources (struct acpi_bridge	*ab)
+{
+	struct acpi_php_slot		*aps;
+	int	i;
+
+	switch (ab->type) {
+	case BRIDGE_TYPE_HOST:
+		dbg("PCI HOST Bridge (%x) [%s]\n", ab->bus, acpi_path_name(ab->handle));
+		break;
+	case BRIDGE_TYPE_P2P:
+		dbg("PCI P2P Bridge (%x-%x) [%s]\n", ab->pbus, ab->bus, acpi_path_name(ab->handle));
+		break;
+	};
+
+	print_pci_resources (ab);
+
+	for ( i = -1, aps = ab->slots; aps; aps = aps->next) {
+		if (aps->dev == i)
+			continue;
+		dbg("  Slot sun(%x) s:b:d:f(%02x:%02x:%02x:%02x)\n", aps->sun, aps->seg, aps->bus, aps->dev, aps->fun);
+		print_slot_resources(aps);
+		i = aps->dev;
+	}
+
+	if (ab->child)
+		print_acpi_resources (ab->child);
+
+	if (ab->next)
+		print_acpi_resources (ab->next);
+
+	return 0;
+}
+
+int pciehprm_print_pirt(void)
+{
+	dbg("PCIEHPRM ACPI Slots\n");
+	print_acpi_resources (acpi_bridges_head);
+
+	return 0;
+}
+
+static struct acpi_php_slot * get_acpi_slot (
+	struct acpi_bridge *ab,
+	u32 sun
+	)
+{
+	struct acpi_php_slot	*aps = NULL;
+
+	for ( aps = ab->slots; aps; aps = aps->next)
+		if (aps->sun == sun)
+			return aps;
+
+	if (!aps && ab->child) {
+		aps = (struct acpi_php_slot *)get_acpi_slot (ab->child, sun);
+		if (aps)
+			return aps;
+	}
+
+	if (!aps && ab->next) {
+		aps = (struct acpi_php_slot *)get_acpi_slot (ab->next, sun);
+		if (aps)
+			return aps;
+	}
+
+	return aps;
+
+}
+
+void * pciehprm_get_slot(struct slot *slot)
+{
+	struct acpi_bridge	*ab = acpi_bridges_head;
+	struct acpi_php_slot	*aps = get_acpi_slot (ab, slot->number);
+
+	aps->slot = slot;
+
+	dbg("Got acpi slot sun(%x): s:b:d:f(%x:%x:%x:%x)\n", aps->sun, aps->seg, aps->bus, aps->dev, aps->fun);
+
+	return (void *)aps;
+}
+
+static void pciehprm_dump_func_res( struct pci_func *fun)
+{
+	struct pci_func *func = fun;
+
+	if (func->bus_head) {
+		dbg(":    BUS Resources:\n");
+		print_pci_resource (func->bus_head);
+	}
+	if (func->io_head) {
+		dbg(":    IO Resources:\n");
+		print_pci_resource (func->io_head);
+	}
+	if (func->mem_head) {
+		dbg(":    MEM Resources:\n");
+		print_pci_resource (func->mem_head);
+	}
+	if (func->p_mem_head) {
+		dbg(":    PMEM Resources:\n");
+		print_pci_resource (func->p_mem_head);
+	}
+}
+
+static void pciehprm_dump_ctrl_res( struct controller *ctlr)
+{
+	struct controller *ctrl = ctlr;
+
+	if (ctrl->bus_head) {
+		dbg(":    BUS Resources:\n");
+		print_pci_resource (ctrl->bus_head);
+	}
+	if (ctrl->io_head) {
+		dbg(":    IO Resources:\n");
+		print_pci_resource (ctrl->io_head);
+	}
+	if (ctrl->mem_head) {
+		dbg(":    MEM Resources:\n");
+		print_pci_resource (ctrl->mem_head);
+	}
+	if (ctrl->p_mem_head) {
+		dbg(":    PMEM Resources:\n");
+		print_pci_resource (ctrl->p_mem_head);
+	}
+}
+
+static int pciehprm_get_used_resources (
+	struct controller *ctrl,
+	struct pci_func *func
+	)
+{
+	return pciehp_save_used_resources (ctrl, func, !DISABLE_CARD);
+}
+
+static int configure_existing_function(
+	struct controller *ctrl,
+	struct pci_func *func
+	)
+{
+	int rc;
+
+	/* see how much resources the func has used. */
+	rc = pciehprm_get_used_resources (ctrl, func);
+
+	if (!rc) {
+		/* subtract the resources used by the func from ctrl resources */
+		rc  = pciehprm_delete_resources (&ctrl->bus_head, func->bus_head);
+		rc |= pciehprm_delete_resources (&ctrl->io_head, func->io_head);
+		rc |= pciehprm_delete_resources (&ctrl->mem_head, func->mem_head);
+		rc |= pciehprm_delete_resources (&ctrl->p_mem_head, func->p_mem_head);
+		if (rc)
+			warn("aCEF: cannot del used resources\n");
+	} else
+		err("aCEF: cannot get used resources\n");
+
+	return rc;
+}
+
+static int bind_pci_resources_to_slots ( struct controller *ctrl)
+{
+	struct pci_func *func;
+	int busn = ctrl->slot_bus;
+	int devn, funn;
+	u32	vid;
+
+	for (devn = 0; devn < 32; devn++) {
+		for (funn = 0; funn < 8; funn++) {
+			/*
+			if (devn == ctrl->device && funn == ctrl->function)
+				continue;
+			*/
+			/* find out if this entry is for an occupied slot */
+			vid = 0xFFFFFFFF;
+			pci_bus_read_config_dword(ctrl->pci_dev->subordinate, PCI_DEVFN(devn, funn), PCI_VENDOR_ID, &vid);
+
+			if (vid != 0xFFFFFFFF) {
+				dbg("%s: vid = %x\n", __FUNCTION__, vid);
+				func = pciehp_slot_find(busn, devn, funn);
+				if (!func)
+					continue;
+				configure_existing_function(ctrl, func);
+				dbg("aCCF:existing PCI 0x%x Func ResourceDump\n", ctrl->bus);
+				pciehprm_dump_func_res(func);
+			}
+		}
+	}
+
+	return 0;
+}
+
+static int bind_pci_resources(
+	struct controller 	*ctrl,
+	struct acpi_bridge	*ab
+	)
+{
+	int		status = 0;
+
+	if (ab->bus_head) {
+		dbg("bapr:  BUS Resources add on PCI 0x%x\n", ab->bus);
+		status = pciehprm_add_resources (&ctrl->bus_head, ab->bus_head);
+		if (pciehprm_delete_resources (&ab->bus_head, ctrl->bus_head))
+			warn("bapr:  cannot sub BUS Resource on PCI 0x%x\n", ab->bus);
+		if (status) {
+			err("bapr:  BUS Resource add on PCI 0x%x: fail=0x%x\n", ab->bus, status);
+			return status;
+		}
+	} else
+		info("bapr:  No BUS Resource on PCI 0x%x.\n", ab->bus);
+
+	if (ab->io_head) {
+		dbg("bapr:  IO Resources add on PCI 0x%x\n", ab->bus);
+		status = pciehprm_add_resources (&ctrl->io_head, ab->io_head);
+		if (pciehprm_delete_resources (&ab->io_head, ctrl->io_head))
+			warn("bapr:  cannot sub IO Resource on PCI 0x%x\n", ab->bus);
+		if (status) {
+			err("bapr:  IO Resource add on PCI 0x%x: fail=0x%x\n", ab->bus, status);
+			return status;
+		}
+	} else
+		info("bapr:  No  IO Resource on PCI 0x%x.\n", ab->bus);
+
+	if (ab->mem_head) {
+		dbg("bapr:  MEM Resources add on PCI 0x%x\n", ab->bus);
+		status = pciehprm_add_resources (&ctrl->mem_head, ab->mem_head);
+		if (pciehprm_delete_resources (&ab->mem_head, ctrl->mem_head))
+			warn("bapr:  cannot sub MEM Resource on PCI 0x%x\n", ab->bus);
+		if (status) {
+			err("bapr:  MEM Resource add on PCI 0x%x: fail=0x%x\n", ab->bus, status);
+			return status;
+		}
+	} else
+		info("bapr:  No MEM Resource on PCI 0x%x.\n", ab->bus);
+
+	if (ab->p_mem_head) {
+		dbg("bapr:  PMEM Resources add on PCI 0x%x\n", ab->bus);
+		status = pciehprm_add_resources (&ctrl->p_mem_head, ab->p_mem_head);
+		if (pciehprm_delete_resources (&ab->p_mem_head, ctrl->p_mem_head))
+			warn("bapr:  cannot sub PMEM Resource on PCI 0x%x\n", ab->bus);
+		if (status) {
+			err("bapr:  PMEM Resource add on PCI 0x%x: fail=0x%x\n", ab->bus, status);
+			return status;
+		}
+	} else
+		info("bapr:  No PMEM Resource on PCI 0x%x.\n", ab->bus);
+
+	return status;
+}
+
+static int no_pci_resources( struct acpi_bridge *ab)
+{
+	return !(ab->p_mem_head || ab->mem_head || ab->io_head || ab->bus_head);
+}
+
+static int find_pci_bridge_resources (
+	struct controller *ctrl,
+	struct acpi_bridge *ab
+	)
+{
+	int	rc = 0;
+	struct pci_func func;
+
+	memset(&func, 0, sizeof(struct pci_func));
+
+	func.bus = ab->pbus;
+	func.device = ab->pdevice;
+	func.function = ab->pfunction;
+	func.is_a_board = 1;
+
+	/* Get used resources for this PCI bridge */
+	rc = pciehp_save_used_resources (ctrl, &func, !DISABLE_CARD);
+
+	ab->io_head = func.io_head;
+	ab->mem_head = func.mem_head;
+	ab->p_mem_head = func.p_mem_head;
+	ab->bus_head = func.bus_head;
+	if (ab->bus_head)
+		pciehprm_delete_resource(&ab->bus_head, ctrl->pci_dev->subordinate->number, 1);
+
+	return rc;
+}
+
+static int get_pci_resources_from_bridge(
+	struct controller *ctrl,
+	struct acpi_bridge *ab
+	)
+{
+	int	rc = 0;
+
+	dbg("grfb:  Get Resources for PCI 0x%x from actual PCI bridge 0x%x.\n", ctrl->bus, ab->bus);
+
+	rc = find_pci_bridge_resources (ctrl, ab);
+
+	pciehp_resource_sort_and_combine(&ab->bus_head);
+	pciehp_resource_sort_and_combine(&ab->io_head);
+	pciehp_resource_sort_and_combine(&ab->mem_head);
+	pciehp_resource_sort_and_combine(&ab->p_mem_head);
+
+	pciehprm_add_resources (&ab->tbus_head, ab->bus_head);
+	pciehprm_add_resources (&ab->tio_head, ab->io_head);
+	pciehprm_add_resources (&ab->tmem_head, ab->mem_head);
+	pciehprm_add_resources (&ab->tp_mem_head, ab->p_mem_head);
+
+	return rc;
+}
+
+static int get_pci_resources(
+	struct controller	*ctrl,
+	struct acpi_bridge	*ab
+	)
+{
+	int	rc = 0;
+
+	if (no_pci_resources(ab)) {
+		dbg("spbr:PCI 0x%x has no resources. Get parent resources.\n", ab->bus);
+		rc = get_pci_resources_from_bridge(ctrl, ab);
+	}
+
+	return rc;
+}
+
+/*
+ * Get resources for this ctrl.
+ *  1. get total resources from ACPI _CRS or bridge (this ctrl)
+ *  2. find used resources of existing adapters
+ *	3. subtract used resources from total resources
+ */
+int pciehprm_find_available_resources( struct controller *ctrl)
+{
+	int rc = 0;
+	struct acpi_bridge	*ab;
+
+	ab = find_acpi_bridge_by_bus(acpi_bridges_head, ctrl->seg, ctrl->pci_dev->subordinate->number);
+	if (!ab) {
+		err("pfar:cannot locate acpi bridge of PCI 0x%x.\n", ctrl->pci_dev->subordinate->number);
+		return -1;
+	}
+	if (no_pci_resources(ab)) {
+		rc = get_pci_resources(ctrl, ab);
+		if (rc) {
+			err("pfar:cannot get pci resources of PCI 0x%x.\n", ctrl->pci_dev->subordinate->number);
+			return -1;
+		}
+	}
+
+	rc = bind_pci_resources(ctrl, ab);
+	dbg("pfar:pre-Bind PCI 0x%x Ctrl Resource Dump\n", ctrl->pci_dev->subordinate->number);
+	pciehprm_dump_ctrl_res(ctrl);
+
+	bind_pci_resources_to_slots (ctrl);
+
+	dbg("pfar:post-Bind PCI 0x%x Ctrl Resource Dump\n", ctrl->pci_dev->subordinate->number);
+	pciehprm_dump_ctrl_res(ctrl);
+
+	return rc;
+}
+
+int pciehprm_set_hpp(
+	struct controller *ctrl,
+	struct pci_func *func,
+	u8	card_type
+	)
+{
+	struct acpi_bridge	*ab;
+	struct pci_bus lpci_bus, *pci_bus;
+	int				rc = 0;
+	unsigned int	devfn;
+	u8				cls= 0x08;	/* default cache line size	*/
+	u8				lt = 0x40;	/* default latency timer	*/
+	u8				ep = 0;
+	u8				es = 0;
+
+	memcpy(&lpci_bus, ctrl->pci_bus, sizeof(lpci_bus));
+	pci_bus = &lpci_bus;
+	pci_bus->number = func->bus;
+	devfn = PCI_DEVFN(func->device, func->function);
+
+	ab = find_acpi_bridge_by_bus(acpi_bridges_head, ctrl->seg, ctrl->bus);
+
+	if (ab) {
+		if (ab->_hpp) {
+			lt  = (u8)ab->_hpp->latency_timer;
+			cls = (u8)ab->_hpp->cache_line_size;
+			ep  = (u8)ab->_hpp->enable_perr;
+			es  = (u8)ab->_hpp->enable_serr;
+		} else
+			dbg("_hpp: no _hpp for B/D/F=%#x/%#x/%#x. use default value\n", func->bus, func->device, func->function);
+	} else
+		dbg("_hpp: no acpi bridge for B/D/F = %#x/%#x/%#x. use default value\n", func->bus, func->device, func->function);
+
+
+	if (card_type == PCI_HEADER_TYPE_BRIDGE) {
+		/* set subordinate Latency Timer */
+		rc |= pci_bus_write_config_byte(pci_bus, devfn, PCI_SEC_LATENCY_TIMER, lt);
+	}
+
+	/* set base Latency Timer */
+	rc |= pci_bus_write_config_byte(pci_bus, devfn, PCI_LATENCY_TIMER, lt);
+	dbg("  set latency timer  =0x%02x: %x\n", lt, rc);
+
+	rc |= pci_bus_write_config_byte(pci_bus, devfn, PCI_CACHE_LINE_SIZE, cls);
+	dbg("  set cache_line_size=0x%02x: %x\n", cls, rc);
+
+	return rc;
+}
+
+void pciehprm_enable_card(
+	struct controller *ctrl,
+	struct pci_func *func,
+	u8 card_type)
+{
+	u16 command, cmd, bcommand, bcmd;
+	struct pci_bus lpci_bus, *pci_bus;
+	struct acpi_bridge	*ab;
+	unsigned int devfn;
+	int rc;
+
+	memcpy(&lpci_bus, ctrl->pci_bus, sizeof(lpci_bus));
+	pci_bus = &lpci_bus;
+	pci_bus->number = func->bus;
+	devfn = PCI_DEVFN(func->device, func->function);
+
+	rc = pci_bus_read_config_word(pci_bus, devfn, PCI_COMMAND, &command);
+
+	if (card_type == PCI_HEADER_TYPE_BRIDGE) {
+		rc = pci_bus_read_config_word(pci_bus, devfn, PCI_BRIDGE_CONTROL, &bcommand);
+	}
+
+	cmd = command  = command | PCI_COMMAND_MASTER | PCI_COMMAND_INVALIDATE
+		| PCI_COMMAND_IO | PCI_COMMAND_MEMORY;
+	bcmd = bcommand  = bcommand | PCI_BRIDGE_CTL_NO_ISA;
+
+	ab = find_acpi_bridge_by_bus(acpi_bridges_head, ctrl->seg, ctrl->bus);
+	if (ab) {
+		if (ab->_hpp) {
+			if (ab->_hpp->enable_perr) {
+				command |= PCI_COMMAND_PARITY;
+				bcommand |= PCI_BRIDGE_CTL_PARITY;
+			} else {
+				command &= ~PCI_COMMAND_PARITY;
+				bcommand &= ~PCI_BRIDGE_CTL_PARITY;
+			}
+			if (ab->_hpp->enable_serr) {
+				command |= PCI_COMMAND_SERR;
+				bcommand |= PCI_BRIDGE_CTL_SERR;
+			} else {
+				command &= ~PCI_COMMAND_SERR;
+				bcommand &= ~PCI_BRIDGE_CTL_SERR;
+			}
+		} else
+			dbg("no _hpp for B/D/F = %#x/%#x/%#x.\n", func->bus, func->device, func->function);
+	} else
+		dbg("no acpi bridge for B/D/F = %#x/%#x/%#x.\n", func->bus, func->device, func->function);
+
+	if (command != cmd) {
+		rc = pci_bus_write_config_word(pci_bus, devfn, PCI_COMMAND, command);
+	}
+	if ((card_type == PCI_HEADER_TYPE_BRIDGE) && (bcommand != bcmd)) {
+		rc = pci_bus_write_config_word(pci_bus, devfn, PCI_BRIDGE_CONTROL, bcommand);
+	}
+}
--- diff/drivers/pci/hotplug/pciehprm_nonacpi.c	1970-01-01 01:00:00.000000000 +0100
+++ source/drivers/pci/hotplug/pciehprm_nonacpi.c	2004-02-23 13:56:44.000000000 +0000
@@ -0,0 +1,498 @@
+/*
+ * PCIEHPRM NONACPI: PHP Resource Manager for Non-ACPI/Legacy platform
+ *
+ * Copyright (C) 1995,2001 Compaq Computer Corporation
+ * Copyright (C) 2001 Greg Kroah-Hartman (greg@kroah.com)
+ * Copyright (C) 2001 IBM Corp.
+ * Copyright (C) 2003-2004 Intel Corporation
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Send feedback to <greg@kroah.com>, <dely.l.sy@intel.com>
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <asm/uaccess.h>
+#ifdef CONFIG_IA64
+#include <asm/iosapic.h>
+#endif
+#include "pciehp.h"
+#include "pciehprm.h"
+#include "pciehprm_nonacpi.h"
+
+
+void pciehprm_cleanup(void)
+{
+	return;
+}
+
+int pciehprm_print_pirt(void)
+{
+	return 0;
+}
+
+void * pciehprm_get_slot(struct slot *slot)
+{
+	return NULL;
+}
+
+int pciehprm_get_physical_slot_number(struct controller *ctrl, u32 *sun, u8 busnum, u8 devnum)
+{
+
+	*sun = (u8) (ctrl->first_slot);
+	return 0;
+}
+
+
+static void print_pci_resource ( struct pci_resource	*aprh)
+{
+	struct pci_resource	*res;
+
+	for (res = aprh; res; res = res->next)
+		dbg("        base= 0x%x length= 0x%x\n", res->base, res->length);
+}
+
+
+static void phprm_dump_func_res( struct pci_func *fun)
+{
+	struct pci_func *func = fun;
+
+	if (func->bus_head) {
+		dbg(":    BUS Resources:\n");
+		print_pci_resource (func->bus_head);
+	}
+	if (func->io_head) {
+		dbg(":    IO Resources:\n");
+		print_pci_resource (func->io_head);
+	}
+	if (func->mem_head) {
+		dbg(":    MEM Resources:\n");
+		print_pci_resource (func->mem_head);
+	}
+	if (func->p_mem_head) {
+		dbg(":    PMEM Resources:\n");
+		print_pci_resource (func->p_mem_head);
+	}
+}
+
+static int phprm_get_used_resources (
+	struct controller *ctrl,
+	struct pci_func *func
+	)
+{
+	return pciehp_save_used_resources (ctrl, func, !DISABLE_CARD);
+}
+
+static int phprm_delete_resource(
+	struct pci_resource **aprh,
+	ulong base,
+	ulong size)
+{
+	struct pci_resource *res;
+	struct pci_resource *prevnode;
+	struct pci_resource *split_node;
+	ulong tbase;
+
+	pciehp_resource_sort_and_combine(aprh);
+
+	for (res = *aprh; res; res = res->next) {
+		if (res->base > base)
+			continue;
+
+		if ((res->base + res->length) < (base + size))
+			continue;
+
+		if (res->base < base) {
+			tbase = base;
+
+			if ((res->length - (tbase - res->base)) < size)
+				continue;
+
+			split_node = (struct pci_resource *) kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
+			if (!split_node)
+				return -ENOMEM;
+
+			split_node->base = res->base;
+			split_node->length = tbase - res->base;
+			res->base = tbase;
+			res->length -= split_node->length;
+
+			split_node->next = res->next;
+			res->next = split_node;
+		}
+
+		if (res->length >= size) {
+			split_node = (struct pci_resource*) kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
+			if (!split_node)
+				return -ENOMEM;
+
+			split_node->base = res->base + size;
+			split_node->length = res->length - size;
+			res->length = size;
+
+			split_node->next = res->next;
+			res->next = split_node;
+		}
+
+		if (*aprh == res) {
+			*aprh = res->next;
+		} else {
+			prevnode = *aprh;
+			while (prevnode->next != res)
+				prevnode = prevnode->next;
+
+			prevnode->next = res->next;
+		}
+		res->next = NULL;
+		kfree(res);
+		break;
+	}
+
+	return 0;
+}
+
+
+static int phprm_delete_resources(
+	struct pci_resource **aprh,
+	struct pci_resource *this
+	)
+{
+	struct pci_resource *res;
+
+	for (res = this; res; res = res->next)
+		phprm_delete_resource(aprh, res->base, res->length);
+
+	return 0;
+}
+
+
+static int configure_existing_function(
+	struct controller *ctrl,
+	struct pci_func *func
+	)
+{
+	int rc;
+
+	/* see how much resources the func has used. */
+	rc = phprm_get_used_resources (ctrl, func);
+
+	if (!rc) {
+		/* subtract the resources used by the func from ctrl resources */
+		rc  = phprm_delete_resources (&ctrl->bus_head, func->bus_head);
+		rc |= phprm_delete_resources (&ctrl->io_head, func->io_head);
+		rc |= phprm_delete_resources (&ctrl->mem_head, func->mem_head);
+		rc |= phprm_delete_resources (&ctrl->p_mem_head, func->p_mem_head);
+		if (rc)
+			warn("aCEF: cannot del used resources\n");
+	} else
+		err("aCEF: cannot get used resources\n");
+
+	return rc;
+}
+
+static int pciehprm_delete_resource(
+	struct pci_resource **aprh,
+	ulong base,
+	ulong size)
+{
+	struct pci_resource *res;
+	struct pci_resource *prevnode;
+	struct pci_resource *split_node;
+	ulong tbase;
+
+	pciehp_resource_sort_and_combine(aprh);
+
+	for (res = *aprh; res; res = res->next) {
+		if (res->base > base)
+			continue;
+
+		if ((res->base + res->length) < (base + size))
+			continue;
+
+		if (res->base < base) {
+			tbase = base;
+
+			if ((res->length - (tbase - res->base)) < size)
+				continue;
+
+			split_node = (struct pci_resource *) kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
+			if (!split_node)
+				return -ENOMEM;
+
+			split_node->base = res->base;
+			split_node->length = tbase - res->base;
+			res->base = tbase;
+			res->length -= split_node->length;
+
+			split_node->next = res->next;
+			res->next = split_node;
+		}
+
+		if (res->length >= size) {
+			split_node = (struct pci_resource*) kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
+			if (!split_node)
+				return -ENOMEM;
+
+			split_node->base = res->base + size;
+			split_node->length = res->length - size;
+			res->length = size;
+
+			split_node->next = res->next;
+			res->next = split_node;
+		}
+
+		if (*aprh == res) {
+			*aprh = res->next;
+		} else {
+			prevnode = *aprh;
+			while (prevnode->next != res)
+				prevnode = prevnode->next;
+
+			prevnode->next = res->next;
+		}
+		res->next = NULL;
+		kfree(res);
+		break;
+	}
+
+	return 0;
+}
+
+static int bind_pci_resources_to_slots ( struct controller *ctrl)
+{
+	struct pci_func *func;
+	int busn = ctrl->slot_bus;
+	int devn, funn;
+	u32	vid;
+
+	for (devn = 0; devn < 32; devn++) {
+		for (funn = 0; funn < 8; funn++) {
+			/*
+			if (devn == ctrl->device && funn == ctrl->function)
+				continue;
+			*/
+			/* find out if this entry is for an occupied slot */
+			vid = 0xFFFFFFFF;
+
+			pci_bus_read_config_dword(ctrl->pci_dev->subordinate, PCI_DEVFN(devn, funn), PCI_VENDOR_ID, &vid);
+
+			if (vid != 0xFFFFFFFF) {
+				dbg("%s: vid = %x bus %x dev %x fun %x\n", __FUNCTION__,
+				vid, busn, devn, funn);
+				func = pciehp_slot_find(busn, devn, funn);
+				dbg("%s: func = %p\n", __FUNCTION__,func);
+				if (!func)
+					continue;
+				configure_existing_function(ctrl, func);
+				dbg("aCCF:existing PCI 0x%x Func ResourceDump\n", ctrl->bus);
+				phprm_dump_func_res(func);
+			}
+		}
+	}
+
+	return 0;
+}
+
+static void phprm_dump_ctrl_res( struct controller *ctlr)
+{
+	struct controller *ctrl = ctlr;
+
+	if (ctrl->bus_head) {
+		dbg(":    BUS Resources:\n");
+		print_pci_resource (ctrl->bus_head);
+	}
+	if (ctrl->io_head) {
+		dbg(":    IO Resources:\n");
+		print_pci_resource (ctrl->io_head);
+	}
+	if (ctrl->mem_head) {
+		dbg(":    MEM Resources:\n");
+		print_pci_resource (ctrl->mem_head);
+	}
+	if (ctrl->p_mem_head) {
+		dbg(":    PMEM Resources:\n");
+		print_pci_resource (ctrl->p_mem_head);
+	}
+}
+
+/*
+ * phprm_find_available_resources
+ *
+ *  Finds available memory, IO, and IRQ resources for programming
+ *  devices which may be added to the system
+ *  this function is for hot plug ADD!
+ *
+ * returns 0 if success
+ */
+int pciehprm_find_available_resources(struct controller *ctrl)
+{
+	struct pci_func func;
+	u32 rc;
+
+	memset(&func, 0, sizeof(struct pci_func));
+
+	func.bus = ctrl->bus;
+	func.device = ctrl->device;
+	func.function = ctrl->function;
+	func.is_a_board = 1;
+
+	/* Get resources for this PCI bridge */
+	rc = pciehp_save_used_resources (ctrl, &func, !DISABLE_CARD);
+	dbg("%s: pciehp_save_used_resources rc = %d\n", __FUNCTION__, rc);
+
+	if (func.mem_head)
+		func.mem_head->next = ctrl->mem_head;
+	ctrl->mem_head = func.mem_head;
+
+	if (func.p_mem_head)
+		func.p_mem_head->next = ctrl->p_mem_head;
+	ctrl->p_mem_head = func.p_mem_head;
+
+	if (func.io_head)
+		func.io_head->next = ctrl->io_head;
+	ctrl->io_head = func.io_head;
+
+	if(func.bus_head)
+		func.bus_head->next = ctrl->bus_head;
+	ctrl->bus_head = func.bus_head;
+
+	if (ctrl->bus_head)
+		pciehprm_delete_resource(&ctrl->bus_head, ctrl->pci_dev->subordinate->number, 1);
+	
+	dbg("%s:pre-Bind PCI 0x%x Ctrl Resource Dump\n", __FUNCTION__, ctrl->bus);
+	phprm_dump_ctrl_res(ctrl);
+
+	dbg("%s: before bind_pci_resources_to slots\n", __FUNCTION__);
+
+	bind_pci_resources_to_slots (ctrl);
+
+	dbg("%s:post-Bind PCI 0x%x Ctrl Resource Dump\n", __FUNCTION__, ctrl->bus);
+	phprm_dump_ctrl_res(ctrl);
+
+	return (rc);
+}
+
+int pciehprm_set_hpp(
+	struct controller *ctrl,
+	struct pci_func *func,
+	u8	card_type)
+{
+	u32 rc;
+	u8 temp_byte;
+	struct pci_bus lpci_bus, *pci_bus;
+	unsigned int	devfn;
+	memcpy(&lpci_bus, ctrl->pci_bus, sizeof(lpci_bus));
+	pci_bus = &lpci_bus;
+	pci_bus->number = func->bus;
+	devfn = PCI_DEVFN(func->device, func->function);
+
+	temp_byte = 0x40;	/* hard coded value for LT */
+	if (card_type == PCI_HEADER_TYPE_BRIDGE) {
+		/* set subordinate Latency Timer */
+		rc = pci_bus_write_config_byte(pci_bus, devfn, PCI_SEC_LATENCY_TIMER, temp_byte);
+
+		if (rc) {
+			dbg("%s: set secondary LT error. b:d:f(%02x:%02x:%02x)\n", __FUNCTION__, 
+				func->bus, func->device, func->function);
+			return rc;
+		}
+	}
+
+	/* set base Latency Timer */
+	rc = pci_bus_write_config_byte(pci_bus, devfn, PCI_LATENCY_TIMER, temp_byte);
+
+	if (rc) {
+		dbg("%s: set LT error. b:d:f(%02x:%02x:%02x)\n", __FUNCTION__, func->bus, func->device, func->function);
+		return rc;
+	}
+
+	/* set Cache Line size */
+	temp_byte = 0x08;	/* hard coded value for CLS */
+
+	rc = pci_bus_write_config_byte(pci_bus, devfn, PCI_CACHE_LINE_SIZE, temp_byte);
+
+	if (rc) {
+		dbg("%s: set CLS error. b:d:f(%02x:%02x:%02x)\n", __FUNCTION__, func->bus, func->device, func->function);
+	}
+
+	/* set enable_perr */
+	/* set enable_serr */
+
+	return rc;
+}
+
+void pciehprm_enable_card(
+	struct controller *ctrl,
+	struct pci_func *func,
+	u8 card_type)
+{
+	u16 command, bcommand;
+	struct pci_bus lpci_bus, *pci_bus;
+	unsigned int devfn;
+	int rc;
+
+	memcpy(&lpci_bus, ctrl->pci_bus, sizeof(lpci_bus));
+	pci_bus = &lpci_bus;
+	pci_bus->number = func->bus;
+	devfn = PCI_DEVFN(func->device, func->function);
+
+	rc = pci_bus_read_config_word(pci_bus, devfn, PCI_COMMAND, &command);
+
+	command |= PCI_COMMAND_PARITY | PCI_COMMAND_SERR
+		| PCI_COMMAND_MASTER | PCI_COMMAND_INVALIDATE
+		| PCI_COMMAND_IO | PCI_COMMAND_MEMORY;
+
+	rc = pci_bus_write_config_word(pci_bus, devfn, PCI_COMMAND, command);
+
+	if (card_type == PCI_HEADER_TYPE_BRIDGE) {
+
+		rc = pci_bus_read_config_word(pci_bus, devfn, PCI_BRIDGE_CONTROL, &bcommand);
+
+		bcommand |= PCI_BRIDGE_CTL_PARITY | PCI_BRIDGE_CTL_SERR
+			| PCI_BRIDGE_CTL_NO_ISA;
+
+		rc = pci_bus_write_config_word(pci_bus, devfn, PCI_BRIDGE_CONTROL, bcommand);
+	}
+}
+
+static int legacy_pciehprm_init_pci(void)
+{
+	return 0;
+}
+
+int pciehprm_init(enum php_ctlr_type ctrl_type)
+{
+	int retval;
+
+	switch (ctrl_type) {
+	case PCI:
+		retval = legacy_pciehprm_init_pci();
+		break;
+	default:
+		retval = -ENODEV;
+		break;
+	}
+
+	return retval;
+}
--- diff/drivers/pci/hotplug/pciehprm_nonacpi.h	1970-01-01 01:00:00.000000000 +0100
+++ source/drivers/pci/hotplug/pciehprm_nonacpi.h	2004-02-23 13:56:44.000000000 +0000
@@ -0,0 +1,56 @@
+/*
+ * PCIEHPRM NONACPI: PHP Resource Manager for Non-ACPI/Legacy platform
+ *
+ * Copyright (C) 1995,2001 Compaq Computer Corporation
+ * Copyright (C) 2001 Greg Kroah-Hartman (greg@kroah.com)
+ * Copyright (C) 2001 IBM Corp.
+ * Copyright (C) 2003-2004 Intel Corporation
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Send feedback to <greg@kroah.com>, <dely.l.sy@intel.com>
+ *
+ */
+
+#ifndef _PCIEHPRM_NONACPI_H_
+#define _PCIEHPRM_NONACPI_H_
+
+struct irq_info {
+	u8 bus, devfn;		/* bus, device and function */
+	struct {
+		u8 link;	/* IRQ line ID, chipset dependent, 0=not routed */
+		u16 bitmap;	/* Available IRQs */
+	} __attribute__ ((packed)) irq[4];
+	u8 slot;		/* slot number, 0=onboard */
+	u8 rfu;
+} __attribute__ ((packed));
+
+struct irq_routing_table {
+	u32 signature;		/* PIRQ_SIGNATURE should be here */
+	u16 version;		/* PIRQ_VERSION */
+	u16 size;			/* Table size in bytes */
+	u8 rtr_bus, rtr_devfn;	/* Where the interrupt router lies */
+	u16 exclusive_irqs;	/* IRQs devoted exclusively to PCI usage */
+	u16 rtr_vendor, rtr_device;	/* Vendor and device ID of interrupt router */
+	u32 miniport_data;	/* Crap */
+	u8 rfu[11];
+	u8 checksum;		/* Modulo 256 checksum must give zero */
+	struct irq_info slots[0];
+} __attribute__ ((packed));
+
+#endif				/* _PCIEHPRM_NONACPI_H_ */
--- diff/drivers/pci/hotplug/rpadlpar.h	1970-01-01 01:00:00.000000000 +0100
+++ source/drivers/pci/hotplug/rpadlpar.h	2004-02-23 13:56:44.000000000 +0000
@@ -0,0 +1,24 @@
+/*
+ * Interface for Dynamic Logical Partitioning of I/O Slots on
+ * RPA-compliant PPC64 platform.
+ *
+ * John Rose <johnrose@austin.ibm.com>
+ * October 2003
+ *
+ * Copyright (C) 2003 IBM.
+ *
+ *      This program is free software; you can redistribute it and/or
+ *      modify it under the terms of the GNU General Public License
+ *      as published by the Free Software Foundation; either version
+ *      2 of the License, or (at your option) any later version.
+ */
+#ifndef _RPADLPAR_IO_H_
+#define _RPADLPAR_IO_H_
+
+extern int dlpar_sysfs_init(void);
+extern void dlpar_sysfs_exit(void);
+
+extern int dlpar_add_slot(char *drc_name);
+extern int dlpar_remove_slot(char *drc_name);
+
+#endif
--- diff/drivers/pci/hotplug/rpadlpar_core.c	1970-01-01 01:00:00.000000000 +0100
+++ source/drivers/pci/hotplug/rpadlpar_core.c	2004-02-23 13:56:44.000000000 +0000
@@ -0,0 +1,343 @@
+/*
+ * Interface for Dynamic Logical Partitioning of I/O Slots on
+ * RPA-compliant PPC64 platform.
+ *
+ * John Rose <johnrose@austin.ibm.com>
+ * Linda Xie <lxie@us.ibm.com>
+ *
+ * October 2003
+ *
+ * Copyright (C) 2003 IBM.
+ *
+ *      This program is free software; you can redistribute it and/or
+ *      modify it under the terms of the GNU General Public License
+ *      as published by the Free Software Foundation; either version
+ *      2 of the License, or (at your option) any later version.
+ */
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <asm/pci-bridge.h>
+#include <asm/semaphore.h>
+#include "../pci.h"
+#include "rpaphp.h"
+#include "rpadlpar.h"
+
+static DECLARE_MUTEX(rpadlpar_sem);
+
+static inline int is_hotplug_capable(struct device_node *dn)
+{
+	unsigned char *ptr = get_property(dn, "ibm,fw-pci-hot-plug-ctrl", NULL);
+
+	return (int) (ptr != NULL);
+}
+
+static char *get_node_drc_name(struct device_node *dn)
+{
+	char *ptr = NULL;
+	int *drc_names;
+
+	drc_names = (int *) get_property(dn, "ibm,drc-names", NULL);
+	if (drc_names)
+		ptr = (char *) &drc_names[1];
+
+	return ptr;
+}
+
+static struct device_node *find_php_slot_node(char *drc_name)
+{
+	struct device_node *np = NULL;
+	char *name;
+
+	while ((np = of_find_node_by_type(np, "pci")))
+		if (is_hotplug_capable(np)) {
+			name = get_node_drc_name(np);
+			if (name && (!strcmp(drc_name, name)))
+				break;
+		}
+
+	return np;
+}
+
+static inline struct hotplug_slot *find_php_slot(char *drc_name)
+{
+	struct kobject *k;
+
+	k = kset_find_obj(&pci_hotplug_slots_subsys.kset, drc_name);
+	if (!k)
+		return NULL;
+
+	return to_hotplug_slot(k);
+}
+
+static struct slot *find_slot(char *drc_name)
+{
+	struct hotplug_slot *php_slot = find_php_slot(drc_name);
+	
+	if (!php_slot)
+		return NULL;
+
+	return (struct slot *) php_slot->private;
+}
+
+static void rpadlpar_claim_one_bus(struct pci_bus *b)
+{
+	struct list_head *ld;
+	struct pci_bus *child_bus;
+
+	for (ld = b->devices.next; ld != &b->devices; ld = ld->next) {
+		struct pci_dev *dev = pci_dev_b(ld);
+		int i;
+
+		for (i = 0; i < PCI_NUM_RESOURCES; i++) {
+			struct resource *r = &dev->resource[i];
+
+			if (r->parent || !r->start || !r->flags)
+				continue;
+			rpaphp_claim_resource(dev, i);
+		}
+	}
+
+	list_for_each_entry(child_bus, &b->children, node)
+		rpadlpar_claim_one_bus(child_bus);
+}
+
+static int pci_add_secondary_bus(struct device_node *dn,
+		struct pci_dev *bridge_dev)
+{
+	struct pci_controller *hose = dn->phb;
+	struct pci_bus *child;
+	u8 sec_busno;
+
+	/* Get busno of downstream bus */
+	pci_read_config_byte(bridge_dev, PCI_SECONDARY_BUS, &sec_busno);
+
+	/* Allocate and add to children of bridge_dev->bus */
+	child = pci_add_new_bus(bridge_dev->bus, bridge_dev, sec_busno);
+	if (!child) {
+		printk(KERN_ERR "%s: could not add secondary bus\n", __FUNCTION__);
+		return 1;
+	}
+
+	sprintf(child->name, "PCI Bus #%02x", child->number);
+
+	/* Fixup subordinate bridge bases and resources */
+	pcibios_fixup_bus(child);
+
+	/* Claim new bus resources */
+	rpadlpar_claim_one_bus(bridge_dev->bus);
+
+	if (hose->last_busno < child->number)
+	    	hose->last_busno = child->number;
+
+	dn->bussubno = child->number;
+
+	/* ioremap() for child bus */
+	if (remap_bus_range(child)) {
+		printk(KERN_ERR "%s: could not ioremap() child bus\n",
+				__FUNCTION__);
+		return 1;
+	}
+
+	return 0;
+}
+
+static struct pci_dev *dlpar_pci_add_bus(struct device_node *dn)
+{
+	struct pci_controller *hose = dn->phb;
+	struct pci_dev *dev = NULL;
+
+	/* Scan phb bus for EADS device, adding new one to bus->devices */
+	if (!pci_scan_single_device(hose->bus, dn->devfn)) {
+		printk(KERN_ERR "%s: found no device on bus\n", __FUNCTION__);
+		return NULL;
+	}
+
+	/* Add new devices to global lists.  Register in proc, sysfs. */
+	pci_bus_add_devices(hose->bus);
+
+	/* Confirm new bridge dev was created */
+	dev = rpaphp_find_pci_dev(dn);
+	if (!dev) {
+		printk(KERN_ERR "%s: failed to add pci device\n", __FUNCTION__);
+		return NULL;
+	}
+
+	if (dev->hdr_type != PCI_HEADER_TYPE_BRIDGE)  {
+		printk(KERN_ERR "%s: unexpected header type %d\n",
+				__FUNCTION__, dev->hdr_type);
+		return NULL;
+	}
+
+	if (pci_add_secondary_bus(dn, dev))
+		return NULL;
+
+	return dev;
+}
+
+static int dlpar_pci_remove_bus(struct pci_dev *bridge_dev)
+{
+	struct pci_bus *secondary_bus;
+
+	if (!bridge_dev) {
+		printk(KERN_ERR "%s: unexpected null device\n",
+				__FUNCTION__);
+		return 1;
+	}
+
+	secondary_bus = bridge_dev->subordinate;
+
+	if (unmap_bus_range(secondary_bus)) {
+		printk(KERN_ERR "%s: failed to unmap bus range\n",
+				__FUNCTION__);
+		return 1;
+	}
+
+	pci_remove_bus_device(bridge_dev);
+
+	return 0;
+}
+
+/**
+ * dlpar_add_slot - DLPAR add an I/O Slot
+ * @drc_name: drc-name of newly added slot
+ *
+ * Make the hotplug module and the kernel aware
+ * of a newly added I/O Slot.
+ * Return Codes -
+ * 0			Success
+ * -ENODEV		Not a valid drc_name
+ * -EINVAL		Slot already added
+ * -ERESTARTSYS		Signalled before obtaining lock
+ * -EIO			Internal PCI Error
+ */
+int dlpar_add_slot(char *drc_name)
+{
+	struct device_node *dn = find_php_slot_node(drc_name);
+	struct pci_dev *dev;
+	int rc = 0;
+
+	if (down_interruptible(&rpadlpar_sem))
+		return -ERESTARTSYS;
+
+	if (!dn) {
+		rc = -ENODEV;
+		goto exit;
+	}
+
+	/* Check for existing hotplug slot */
+	if (find_slot(drc_name)) {
+		rc = -EINVAL;
+		goto exit;
+	}
+
+	/* Add pci bus */
+	dev = dlpar_pci_add_bus(dn);
+	if (!dev) {
+		printk(KERN_ERR "%s: unable to add bus %s\n", __FUNCTION__,
+				drc_name);
+		rc = -EIO;
+		goto exit;
+	}
+
+	/* Add hotplug slot for new bus */
+	if (rpaphp_add_slot(drc_name)) {
+		printk(KERN_ERR "%s: unable to add hotplug slot %s\n",
+				__FUNCTION__, drc_name);
+		rc = -EIO;
+	}
+exit:
+	up(&rpadlpar_sem);
+	return rc;
+}
+
+/**
+ * dlpar_remove_slot - DLPAR remove an I/O Slot
+ * @drc_name: drc-name of newly added slot
+ *
+ * Remove the kernel and hotplug representations
+ * of an I/O Slot.
+ * Return Codes:
+ * 0			Success
+ * -ENODEV		Not a valid drc_name
+ * -EINVAL		Slot already removed
+ * -ERESTARTSYS		Signalled before obtaining lock
+ * -EIO			Internal PCI Error
+ */
+int dlpar_remove_slot(char *drc_name)
+{
+	struct device_node *dn = find_php_slot_node(drc_name);
+	struct slot *slot;
+	struct pci_dev *bridge_dev;
+	int rc = 0;
+
+	if (down_interruptible(&rpadlpar_sem))
+		return -ERESTARTSYS;
+
+	if (!dn) {
+		rc = -ENODEV;
+		goto exit;
+	}
+
+	slot = find_slot(drc_name);
+	if (!slot) {
+		rc = -EINVAL;
+		goto exit;
+	}
+
+	bridge_dev = slot->bridge;
+	if (!bridge_dev) {
+		printk(KERN_ERR "%s: unexpected null bridge device\n",
+				__FUNCTION__);
+		rc = -EIO;
+		goto exit;
+	}
+
+	/* Remove hotplug slot */
+	if (rpaphp_remove_slot(slot)) {
+		printk(KERN_ERR "%s: unable to remove hotplug slot %s\n",
+				__FUNCTION__, drc_name);
+		rc = -EIO;
+		goto exit;
+	}
+
+	/* Remove pci bus */
+	if (dlpar_pci_remove_bus(bridge_dev)) {
+		printk(KERN_ERR "%s: unable to remove pci bus %s\n",
+				__FUNCTION__, drc_name);
+		rc = -EIO;
+	}
+exit:
+	up(&rpadlpar_sem);
+	return rc;
+}
+
+static inline int is_dlpar_capable(void)
+{
+	int rc = rtas_token("ibm,configure-connector");
+
+	return (int) (rc != RTAS_UNKNOWN_SERVICE);
+}
+
+int __init rpadlpar_io_init(void)
+{
+	int rc = 0;
+
+	if (!is_dlpar_capable()) {
+		printk(KERN_WARNING "%s: partition not DLPAR capable\n",
+				__FUNCTION__);
+		return -EPERM;
+	}
+
+	rc = dlpar_sysfs_init();
+	return rc;
+}
+
+void rpadlpar_io_exit(void)
+{
+	dlpar_sysfs_exit();
+	return;
+}
+
+module_init(rpadlpar_io_init);
+module_exit(rpadlpar_io_exit);
+MODULE_LICENSE("GPL");
--- diff/drivers/pci/hotplug/rpadlpar_sysfs.c	1970-01-01 01:00:00.000000000 +0100
+++ source/drivers/pci/hotplug/rpadlpar_sysfs.c	2004-02-23 13:56:44.000000000 +0000
@@ -0,0 +1,151 @@
+/*
+ * Interface for Dynamic Logical Partitioning of I/O Slots on
+ * RPA-compliant PPC64 platform.
+ *
+ * John Rose <johnrose@austin.ibm.com>
+ * October 2003
+ *
+ * Copyright (C) 2003 IBM.
+ *
+ *      This program is free software; you can redistribute it and/or
+ *      modify it under the terms of the GNU General Public License
+ *      as published by the Free Software Foundation; either version
+ *      2 of the License, or (at your option) any later version.
+ */
+#include <linux/kobject.h>
+#include <linux/string.h>
+#include "pci_hotplug.h"
+#include "rpadlpar.h"
+
+#define DLPAR_KOBJ_NAME       "control"
+#define ADD_SLOT_ATTR_NAME    "add_slot"
+#define REMOVE_SLOT_ATTR_NAME "remove_slot"
+
+#define MAX_DRC_NAME_LEN 64
+
+/* Store return code of dlpar operation in attribute struct */
+struct dlpar_io_attr {
+	int rc;
+	struct attribute attr;
+	ssize_t (*store)(struct dlpar_io_attr *dlpar_attr, const char *buf,
+		size_t nbytes);
+};
+
+/* Common show callback for all attrs, display the return code
+ * of the dlpar op */
+static ssize_t
+dlpar_attr_show(struct kobject * kobj, struct attribute * attr, char * buf)
+{
+	struct dlpar_io_attr *dlpar_attr = container_of(attr,
+						struct dlpar_io_attr, attr);
+	return sprintf(buf, "%d\n", dlpar_attr->rc);
+}
+
+static ssize_t
+dlpar_attr_store(struct kobject * kobj, struct attribute * attr,
+		 const char *buf, size_t nbytes)
+{
+	struct dlpar_io_attr *dlpar_attr = container_of(attr,
+						struct dlpar_io_attr, attr);
+	return dlpar_attr->store ?
+		dlpar_attr->store(dlpar_attr, buf, nbytes) : 0;
+}
+
+static struct sysfs_ops dlpar_attr_sysfs_ops = {
+	.show = dlpar_attr_show,
+	.store = dlpar_attr_store,
+};
+
+static ssize_t add_slot_store(struct dlpar_io_attr *dlpar_attr,
+				const char *buf, size_t nbytes)
+{
+	char drc_name[MAX_DRC_NAME_LEN];
+	char *end;
+
+	if (nbytes > MAX_DRC_NAME_LEN)
+		return 0;
+
+	memcpy(drc_name, buf, nbytes);
+
+	end = strchr(drc_name, '\n');
+	if (!end)
+		end = &drc_name[nbytes];
+	*end = '\0';
+
+	dlpar_attr->rc = dlpar_add_slot(drc_name);
+
+	return nbytes;
+}
+
+static ssize_t remove_slot_store(struct dlpar_io_attr *dlpar_attr,
+		 		const char *buf, size_t nbytes)
+{
+	char drc_name[MAX_DRC_NAME_LEN];
+	char *end;
+
+	if (nbytes > MAX_DRC_NAME_LEN)
+		return 0;
+
+	memcpy(drc_name, buf, nbytes);
+
+	end = strchr(drc_name, '\n');
+	if (!end)
+		end = &drc_name[nbytes];
+	*end = '\0';
+
+	dlpar_attr->rc = dlpar_remove_slot(drc_name);
+
+	return nbytes;
+}
+
+static struct dlpar_io_attr add_slot_attr = {
+	.rc = 0,
+	.attr = { .name = ADD_SLOT_ATTR_NAME, .mode = 0644, },
+	.store = add_slot_store,
+};
+
+static struct dlpar_io_attr remove_slot_attr = {
+	.rc = 0,
+	.attr = { .name = REMOVE_SLOT_ATTR_NAME, .mode = 0644},
+	.store = remove_slot_store,
+};
+
+static struct attribute *default_attrs[] = {
+	&add_slot_attr.attr,
+	&remove_slot_attr.attr,
+	NULL,
+};
+
+static void dlpar_io_release(struct kobject *kobj)
+{
+	/* noop */
+	return;
+}
+
+struct kobj_type ktype_dlpar_io = {
+	.release = dlpar_io_release,
+	.sysfs_ops = &dlpar_attr_sysfs_ops,
+	.default_attrs = default_attrs,
+};
+
+struct kset dlpar_io_kset = {
+	.subsys = &pci_hotplug_slots_subsys,
+	.kobj = {.name = DLPAR_KOBJ_NAME, .ktype=&ktype_dlpar_io,},
+	.ktype = &ktype_dlpar_io,
+};
+
+int dlpar_sysfs_init(void)
+{
+	if (kset_register(&dlpar_io_kset)) {
+		printk(KERN_ERR "rpadlpar_io: cannot register kset for %s\n",
+				dlpar_io_kset.kobj.name);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+void dlpar_sysfs_exit(void)
+{
+	kset_unregister(&dlpar_io_kset);
+}
--- diff/drivers/pci/hotplug/rpaphp.h	1970-01-01 01:00:00.000000000 +0100
+++ source/drivers/pci/hotplug/rpaphp.h	2004-02-23 13:56:44.000000000 +0000
@@ -0,0 +1,101 @@
+/*
+ * PCI Hot Plug Controller Driver for RPA-compliant PPC64 platform.
+ *
+ * Copyright (C) 2003 Linda Xie <lxie@us.ibm.com>
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Send feedback to <lxie@us.ibm.com>,
+ *
+ */
+
+#ifndef _PPC64PHP_H
+#define _PPC64PHP_H
+#include "pci_hotplug.h"
+
+#define DR_INDICATOR 9002
+#define DR_ENTITY_SENSE 9003
+
+#define POWER_ON	100
+#define POWER_OFF	0
+
+#define LED_OFF		0 
+#define LED_ON		1	/* continuous on */ 
+#define LED_ID		2	/* slow blinking */
+#define LED_ACTION	3	/* fast blinking */
+
+#define SLOT_NAME_SIZE 12
+
+/* Error status from rtas_get-sensor */
+#define NEED_POWER    -9000     /* slot must be power up and unisolated to get state */
+#define PWR_ONLY      -9001     /* slot must be powerd up to get state, leave isolated */
+#define ERR_SENSE_USE -9002     /* No DR operation will succeed, slot is unusable  */
+
+/* Sensor values from rtas_get-sensor */
+#define EMPTY	0       /* No card in slot */
+#define PRESENT	1       /* Card in slot */
+
+#define MY_NAME "rpaphp"
+
+#define dbg(format, arg...)					\
+	do {							\
+		if (rpaphp_debug)				\
+			printk(KERN_DEBUG "%s: " format,	\
+				MY_NAME , ## arg); 		\
+	} while (0)
+#define err(format, arg...) printk(KERN_ERR "%s: " format, MY_NAME , ## arg)
+#define info(format, arg...) printk(KERN_INFO "%s: " format, MY_NAME , ## arg)
+#define warn(format, arg...) printk(KERN_WARNING "%s: " format, MY_NAME , ## arg)
+
+#define SLOT_MAGIC	0x67267322
+
+/* slot states */
+
+#define	NOT_VALID	3
+#define	NOT_CONFIGURED	2
+#define	CONFIGURED	1
+#define	EMPTY		0
+
+/*
+ * struct slot - slot information for each *physical* slot
+ */
+struct slot {
+	u32	magic;
+	int     state;
+	u32     index;
+	u32     type;
+	u32     power_domain;
+	char    *name;
+	struct	device_node *dn;/* slot's device_node in OFDT		*/
+				/* dn has phb info			*/
+	struct	pci_dev	*bridge;/* slot's pci_dev in pci_devices	*/
+
+	struct	pci_dev	*dev;	/* pci_dev of device in this slot 	*/
+				/* it will be used for unconfig		*/ 
+				/* NULL if slot is empty		*/
+
+	struct  hotplug_slot    *hotplug_slot;
+	struct list_head	rpaphp_slot_list;
+};
+
+extern struct pci_dev *rpaphp_find_pci_dev(struct device_node *dn);
+extern int rpaphp_add_slot(char *slot_name);
+extern int rpaphp_remove_slot(struct slot *slot);
+extern int rpaphp_claim_resource(struct pci_dev *dev, int resource);
+
+#endif /* _PPC64PHP_H */
--- diff/drivers/pci/hotplug/rpaphp_core.c	1970-01-01 01:00:00.000000000 +0100
+++ source/drivers/pci/hotplug/rpaphp_core.c	2004-02-23 13:56:44.000000000 +0000
@@ -0,0 +1,948 @@
+/*
+ * PCI Hot Plug Controller Driver for RPA-compliant PPC64 platform.
+ * Copyright (C) 2003 Linda Xie <lxie@us.ibm.com>
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Send feedback to <lxie@us.ibm.com>
+ *
+ */
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/pci.h>
+#include <linux/slab.h>
+#include <linux/smp.h>
+#include <linux/smp_lock.h>
+#include <linux/init.h>
+#include <asm/rtas.h>		/* rtas_call */
+#include <asm/pci-bridge.h>	/* for pci_controller */
+#include "../pci.h"		/* for pci_add_new_bus*/
+				/* and pci_do_scan_bus*/
+#include "rpaphp.h"
+#include "pci_hotplug.h"
+
+
+static int debug = 1;
+static struct semaphore rpaphp_sem;
+static LIST_HEAD (rpaphp_slot_head);
+static int num_slots;
+
+#define DRIVER_VERSION	"0.1"
+#define DRIVER_AUTHOR	"Linda Xie <lxie@us.ibm.com>"
+#define DRIVER_DESC	"RPA HOT Plug PCI Controller Driver"
+
+#define MAX_LOC_CODE 128
+
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_LICENSE("GPL");
+
+module_param(debug, int, 0644);
+
+static int enable_slot(struct hotplug_slot *slot);
+static int disable_slot(struct hotplug_slot *slot);
+static int set_attention_status(struct hotplug_slot *slot, u8 value);
+static int get_power_status(struct hotplug_slot *slot, u8 *value);
+static int get_attention_status(struct hotplug_slot *slot, u8 *value);
+static int get_adapter_status(struct hotplug_slot *slot, u8 *value);
+static int get_max_bus_speed(struct hotplug_slot *hotplug_slot, enum pci_bus_speed *value);
+static int get_cur_bus_speed(struct hotplug_slot *hotplug_slot, enum pci_bus_speed *value);
+
+static struct hotplug_slot_ops rpaphp_hotplug_slot_ops = {
+	.owner			= THIS_MODULE,
+	.enable_slot		= enable_slot,
+	.disable_slot		= disable_slot,
+	.set_attention_status	= set_attention_status,
+	.get_power_status	= get_power_status,
+	.get_attention_status	= get_attention_status,
+	.get_adapter_status	= get_adapter_status,
+	.get_max_bus_speed	= get_max_bus_speed,
+	.get_cur_bus_speed	= get_cur_bus_speed,
+};
+
+static int rpaphp_get_sensor_state(int index, int *state)
+{
+	int rc;
+
+	rc = rtas_get_sensor(DR_ENTITY_SENSE, index, state);
+
+	if (rc) {
+		if (rc ==  NEED_POWER || rc == PWR_ONLY) {
+			dbg("%s: slot must be power up to get sensor-state\n",
+				__FUNCTION__);
+		} else if (rc == ERR_SENSE_USE)
+			info("%s: slot is unusable\n", __FUNCTION__);
+		   else err("%s failed to get sensor state\n", __FUNCTION__);
+	}
+	return rc;
+}
+
+static struct pci_dev *rpaphp_find_bridge_pdev(struct slot *slot)
+{
+	return rpaphp_find_pci_dev(slot->dn);
+}
+
+static struct pci_dev *rpaphp_find_adapter_pdev(struct slot *slot)
+{
+	return rpaphp_find_pci_dev(slot->dn->child);
+}
+
+/* Inline functions to check the sanity of a pointer that is passed to us */
+static inline int slot_paranoia_check(struct slot *slot, const char *function)
+{
+	if (!slot) {
+		dbg("%s - slot == NULL\n", function);
+		return -1;
+	}
+
+	if (!slot->hotplug_slot) {
+		dbg("%s - slot->hotplug_slot == NULL!\n", function);
+		return -1;
+	}
+	return 0;
+}
+
+static inline struct slot *get_slot(struct hotplug_slot *hotplug_slot, const char *function)
+{
+	struct slot *slot;
+
+	if (!hotplug_slot) {
+		dbg("%s - hotplug_slot == NULL\n", function);
+		return NULL;
+	}
+
+	slot = (struct slot *)hotplug_slot->private;
+	if (slot_paranoia_check(slot, function))
+		return NULL;
+	return slot;
+}
+
+static inline int rpaphp_set_attention_status(struct slot *slot, u8 status)
+{
+	int	rc;
+
+	/* status: LED_OFF or LED_ON */
+	rc = rtas_set_indicator(DR_INDICATOR, slot->index, status);
+	if (rc)
+		err("slot(%s) set attention-status(%d) failed! rc=0x%x\n",
+			slot->name, status, rc);
+	
+	return rc;
+}
+
+static int rpaphp_get_power_status(struct slot *slot, u8 *value)
+{
+	int	rc;
+
+	rc = rtas_get_power_level(slot->power_domain, (int *)value);
+	if (rc)
+		err("failed to get power-level for slot(%s), rc=0x%x\n",
+			slot->name, rc);
+
+	return rc;
+}
+
+static int rpaphp_get_attention_status(struct slot *slot)
+{
+
+	return slot->hotplug_slot->info->attention_status;
+}
+
+/**
+ * set_attention_status - set attention LED
+ * echo 0 > attention -- set LED OFF
+ * echo 1 > attention -- set LED ON
+ * echo 2 > attention -- set LED ID(identify, light is blinking)
+ *
+ */
+static int set_attention_status (struct hotplug_slot *hotplug_slot, u8 value)
+{
+	int retval = 0;
+	struct slot *slot = get_slot(hotplug_slot, __FUNCTION__);
+
+	if (slot == NULL)
+		return -ENODEV;
+
+	down(&rpaphp_sem);
+	switch (value) {
+		case 0:
+			retval = rpaphp_set_attention_status(slot, LED_OFF);
+			hotplug_slot->info->attention_status = 0;
+			break;
+
+		case 1:
+		default:
+			retval = rpaphp_set_attention_status(slot, LED_ON);
+			hotplug_slot->info->attention_status = 1;
+			break;
+
+		case 2:
+			retval = rpaphp_set_attention_status(slot, LED_ID);
+			hotplug_slot->info->attention_status = 2;
+			break;
+
+	}
+	up(&rpaphp_sem);
+	
+	return retval;
+}
+
+/**
+ * get_power_status - get power status of a slot
+ * @hotplug_slot: slot to get status
+ * @value: pointer to store status
+ *
+ *
+ */
+static int get_power_status (struct hotplug_slot *hotplug_slot, u8 *value)
+{
+	int retval;
+	struct slot *slot = get_slot(hotplug_slot, __FUNCTION__);
+
+	if (slot == NULL)
+		return -ENODEV;
+
+	down(&rpaphp_sem);
+	retval = rpaphp_get_power_status(slot, value);
+	up(&rpaphp_sem);
+
+	return retval;
+}
+
+/**
+ * get_attention_status - get attention LED status
+ *
+ *
+ */
+static int get_attention_status (struct hotplug_slot *hotplug_slot, u8 *value)
+{
+	int retval = 0;
+	struct slot *slot = get_slot(hotplug_slot, __FUNCTION__);
+
+	if (slot == NULL)
+		return -ENODEV;
+
+
+	down(&rpaphp_sem);
+	*value = rpaphp_get_attention_status(slot);
+	up(&rpaphp_sem);
+
+	return retval;
+}
+
+/*
+ * get_adapter_status - get  the status of a slot
+ *
+ * 0-- slot is empty
+ * 1-- adapter is configured
+ * 2-- adapter is not configured
+ * 3-- not valid
+ */
+static int rpaphp_get_adapter_status(struct slot *slot, int is_init, u8 *value)
+{
+	int	state, rc;
+
+	*value 		  = NOT_VALID;
+
+	rc = rpaphp_get_sensor_state(slot->index, &state);
+
+	if (rc)
+		return rc;
+
+	if (state == PRESENT) {
+		dbg("slot is occupied\n");
+
+		if (!is_init) /* at run-time slot->state can be changed by */
+			  /* config/unconfig adapter	 		   */
+			*value = slot->state;
+		else {
+		if (!slot->dn->child)
+			dbg("%s: %s is not valid OFDT node\n",
+				__FUNCTION__, slot->dn->full_name);
+		else
+			if (rpaphp_find_pci_dev(slot->dn->child))
+				*value = CONFIGURED;
+			else {
+				dbg("%s: can't find pdev of adapter in slot[%s]\n",
+					__FUNCTION__, slot->name);
+				*value = NOT_CONFIGURED;
+				}
+		}
+	} else
+		if (state == EMPTY) {
+		dbg("slot is empty\n");
+			*value = state;
+		}
+	
+	return 0;
+}
+
+static int get_adapter_status (struct hotplug_slot *hotplug_slot, u8 *value)
+{
+	struct slot *slot = get_slot(hotplug_slot, __FUNCTION__);
+	int retval = 0;
+
+	if (slot == NULL)
+		return -ENODEV;
+
+	down(&rpaphp_sem);
+
+	/*  have to go through this */
+	retval = rpaphp_get_adapter_status(slot, 0, value);
+
+	up(&rpaphp_sem);
+
+	return retval;
+}
+
+
+static int get_max_bus_speed (struct hotplug_slot *hotplug_slot, enum pci_bus_speed *value)
+{
+	struct slot *slot = get_slot(hotplug_slot, __FUNCTION__);
+
+	if (slot == NULL)
+		return -ENODEV;
+
+	down(&rpaphp_sem);
+
+	switch (slot->type) {
+		case 1:
+		case 2:
+		case 3:
+		case 4:
+		case 5:
+		case 6:
+			*value = PCI_SPEED_33MHz;	/* speed for case 1-6 */
+			break;
+		case 7:
+		case 8:
+			*value = PCI_SPEED_66MHz;
+			break;
+		case 11:
+		case 14:
+			*value = PCI_SPEED_66MHz_PCIX;
+			break;
+		case 12:
+		case 15:
+			*value = PCI_SPEED_100MHz_PCIX;
+			break;
+		case 13:
+		case 16:
+			*value = PCI_SPEED_133MHz_PCIX;
+			break;
+		default:
+			*value = PCI_SPEED_UNKNOWN;
+			break;
+
+	}
+
+	up(&rpaphp_sem);
+
+	return 0;
+}
+
+
+/* return dummy value because not sure if PRA provides any method... */
+static int get_cur_bus_speed (struct hotplug_slot *hotplug_slot, enum pci_bus_speed *value)
+{
+	struct slot *slot = get_slot(hotplug_slot, __FUNCTION__);
+
+	if (slot == NULL)
+		return -ENODEV;
+
+	*value = PCI_SPEED_UNKNOWN;
+
+	return 0;
+}
+
+/*
+ * rpaphp_validate_slot - make sure the name of the slot matches
+ * 				the location code , if the slots is not
+ *				empty.
+ */
+static int rpaphp_validate_slot(const char *slot_name, const int slot_index)
+{
+	struct device_node	*dn;
+
+	for(dn = find_all_nodes(); dn; dn = dn->next) {
+
+		int 		*index;
+		unsigned char	*loc_code;
+
+		index  = (int *)get_property(dn, "ibm,my-drc-index", NULL);
+
+		if (index && *index == slot_index) {
+			char *slash, *tmp_str;
+
+			loc_code = get_property(dn, "ibm,loc-code", NULL);
+			if (!loc_code) { 
+				return -1;
+			}
+
+			tmp_str = kmalloc(MAX_LOC_CODE, GFP_KERNEL); 
+			if (!tmp_str) {
+				err("%s: out of memory\n", __FUNCTION__);
+				return -1;
+			}
+				
+			strcpy(tmp_str, loc_code);
+			slash = strrchr(tmp_str, '/');
+			if (slash) 
+				*slash = '\0';
+			
+			if (strcmp(slot_name, tmp_str)) {
+				kfree(tmp_str);
+				return -1;
+			}
+
+			kfree(tmp_str);
+			break;
+		}
+	}
+	
+	return 0;
+}
+
+/* Must be called before pci_bus_add_devices */
+static void rpaphp_fixup_new_devices(struct pci_bus *bus)
+{
+	struct pci_dev *dev;
+
+	list_for_each_entry(dev, &bus->devices, bus_list) {
+	/*
+	 * Skip already-present devices (which are on the
+	 * global device list.)
+	 */
+		if (list_empty(&dev->global_list)) {
+			int i;
+			pcibios_fixup_device_resources(dev, bus);
+			pci_read_irq_line(dev);
+			for (i = 0; i < PCI_NUM_RESOURCES; i++) {
+				struct resource *r = &dev->resource[i];
+				if (r->parent || !r->start || !r->flags)
+					continue;
+				rpaphp_claim_resource(dev, i);
+			}
+		}
+	}
+}
+
+static struct pci_dev *rpaphp_config_adapter(struct slot *slot)
+{
+	struct pci_bus 		*pci_bus;
+	struct device_node	*dn;
+	int 			num;
+	struct pci_dev		*dev = NULL;
+
+	if (slot->bridge) {
+
+		pci_bus = slot->bridge->subordinate;
+
+		if (!pci_bus) {
+			err("%s: can't find bus structure\n", __FUNCTION__);
+			goto exit;
+		}
+
+		for (dn = slot->dn->child; dn; dn = dn->sibling) {
+			dbg("child dn's devfn=[%x]\n", dn->devfn);
+				num = pci_scan_slot(pci_bus,
+				PCI_DEVFN(PCI_SLOT(dn->devfn),  0));
+
+				dbg("pci_scan_slot return num=%d\n", num);
+
+			if (num) {
+				rpaphp_fixup_new_devices(pci_bus);
+				pci_bus_add_devices(pci_bus);
+			}
+		}
+
+		dev = rpaphp_find_pci_dev(slot->dn->child);
+	} else {
+		/* slot is not enabled */
+		err("slot doesn't have pci_dev structure\n");
+		dev = NULL;
+		goto exit;
+	}
+
+exit:
+	dbg("Exit %s: pci_dev %s\n", __FUNCTION__, dev? "found":"not found");
+
+	return dev;
+}
+
+static int rpaphp_unconfig_adapter(struct slot *slot)
+{
+	if (!slot->dev) {
+		info("%s: no card in slot[%s]\n",
+			__FUNCTION__, slot->name);
+
+		return -EINVAL;
+	}
+
+	/* remove the device from the pci core */
+	pci_remove_bus_device(slot->dev);
+
+	pci_dev_put(slot->dev);
+	slot->state = NOT_CONFIGURED;
+
+	dbg("%s: adapter in slot[%s] unconfigured.\n", __FUNCTION__, slot->name);
+
+	return 0;
+}
+
+/* free up the memory user be a slot */
+
+static void rpaphp_release_slot(struct hotplug_slot *hotplug_slot)
+{
+	struct slot *slot = get_slot(hotplug_slot, __FUNCTION__);
+
+	if (slot == NULL)
+		return;
+
+	kfree(slot->hotplug_slot->info);
+	kfree(slot->hotplug_slot->name);
+	kfree(slot->hotplug_slot);
+	pci_dev_put(slot->bridge);
+	pci_dev_put(slot->dev);
+	kfree(slot);
+}
+
+int rpaphp_remove_slot(struct slot *slot)
+{
+	int retval = 0;
+
+  	sysfs_remove_link(slot->hotplug_slot->kobj.parent,
+			slot->bridge->slot_name);
+
+	list_del(&slot->rpaphp_slot_list);
+	retval = pci_hp_deregister(slot->hotplug_slot);
+	if (retval)
+		err("Problem unregistering a slot %s\n", slot->name);
+	num_slots--;
+
+	return retval;
+}
+
+static int is_php_dn(struct device_node *dn, int **indexes,  int **names, int **types, int **power_domains)
+{
+	*indexes = (int *)get_property(dn, "ibm,drc-indexes", NULL);
+	if (!*indexes)
+		return(0);
+
+	/* &names[1] contains NULL terminated slot names */
+	*names = (int *)get_property(dn, "ibm,drc-names", NULL);
+	if (!*names)
+		return(0);
+
+	/* &types[1] contains NULL terminated slot types */
+	*types = (int *)get_property(dn, "ibm,drc-types", NULL);
+	if (!*types)
+		return(0);
+
+	/* power_domains[1...n] are the slot power domains */
+	*power_domains = (int *)get_property(dn,
+		"ibm,drc-power-domains", NULL);
+	if (!*power_domains)
+		return(0);
+
+	if (!get_property(dn, "ibm,fw-pci-hot-plug-ctrl", NULL))
+		return(0);
+
+	return(1);
+}
+
+static struct slot *alloc_slot_struct(void)
+{
+	struct slot *slot;
+
+	slot = kmalloc(sizeof(struct slot), GFP_KERNEL);
+	if (!slot)
+		return (NULL);
+	memset(slot, 0, sizeof(struct slot));
+	slot->hotplug_slot = kmalloc(sizeof(struct hotplug_slot),
+		GFP_KERNEL);
+	if (!slot->hotplug_slot) {
+		kfree(slot);
+		return (NULL);
+	}
+	memset(slot->hotplug_slot, 0, sizeof(struct hotplug_slot));
+	slot->hotplug_slot->info = kmalloc(sizeof(struct hotplug_slot_info),
+		GFP_KERNEL);
+	if (!slot->hotplug_slot->info) {
+		kfree(slot->hotplug_slot);
+		kfree(slot);
+		return (NULL);
+	}
+	memset(slot->hotplug_slot->info, 0, sizeof(struct hotplug_slot_info));
+	slot->hotplug_slot->name = kmalloc(SLOT_NAME_SIZE, GFP_KERNEL);
+	if (!slot->hotplug_slot->name) {
+		kfree(slot->hotplug_slot->info);
+		kfree(slot->hotplug_slot);
+		kfree(slot);
+		return (NULL);
+	}
+	return (slot);
+}
+
+static int setup_hotplug_slot_info(struct slot *slot)
+{
+	rpaphp_get_power_status(slot,
+		&slot->hotplug_slot->info->power_status);
+
+	rpaphp_get_adapter_status(slot, 1,
+		&slot->hotplug_slot->info->adapter_status);
+
+	if (slot->hotplug_slot->info->adapter_status == NOT_VALID) {
+		dbg("%s: NOT_VALID: skip dn->full_name=%s\n",
+			__FUNCTION__, slot->dn->full_name);
+		    kfree(slot->hotplug_slot->info);
+		    kfree(slot->hotplug_slot->name);
+		    kfree(slot->hotplug_slot);
+		    kfree(slot);
+		return (-1);
+	}
+	return (0);
+}
+
+static int register_slot(struct slot *slot)
+{
+	int retval;
+
+	retval = pci_hp_register(slot->hotplug_slot);
+	if (retval) {
+		err("pci_hp_register failed with error %d\n", retval);
+		rpaphp_release_slot(slot->hotplug_slot);
+		return (retval);
+	}
+	/* create symlink between slot->name and it's bus_id */
+	dbg("%s: sysfs_create_link: %s --> %s\n", __FUNCTION__,
+		slot->bridge->slot_name, slot->name);
+	retval = sysfs_create_link(slot->hotplug_slot->kobj.parent,
+			&slot->hotplug_slot->kobj,
+			slot->bridge->slot_name);
+	if (retval) {
+		err("sysfs_create_link failed with error %d\n", retval);
+		rpaphp_release_slot(slot->hotplug_slot);
+		return (retval);
+	}
+	/* add slot to our internal list */
+	dbg("%s adding slot[%s] to rpaphp_slot_list\n",
+		__FUNCTION__, slot->name);
+
+	list_add(&slot->rpaphp_slot_list, &rpaphp_slot_head);
+
+	info("Slot [%s] (bus_id=%s) registered\n",
+		slot->name, slot->bridge->slot_name);
+	return (0);
+}
+
+/*************************************
+ * Add  Hot Plug slot(s) to sysfs
+ *
+ ************************************/
+int rpaphp_add_slot(char *slot_name)
+{
+	struct slot		*slot;
+	int 			retval = 0;
+	int 			i;
+	struct device_node 	*dn;
+	int 			*indexes, *names, *types, *power_domains;
+	char 			*name, *type;
+
+	for (dn = find_all_nodes(); dn; dn = dn->next) {
+
+		if (dn->name != 0 && strcmp(dn->name, "pci") == 0)	{
+			if (!is_php_dn(dn, &indexes, &names, &types, &power_domains))
+				continue;
+
+			dbg("%s : found device_node in OFDT full_name=%s, name=%s\n",
+				__FUNCTION__, dn->full_name, dn->name);
+
+			name = (char *)&names[1];
+			type = (char *)&types[1];
+
+			for (i = 0; i < indexes[0];
+				i++,
+				name += (strlen(name) + 1),
+				type += (strlen(type) + 1)) {
+
+				dbg("%s: name[%s] index[%x]\n",
+					__FUNCTION__, name, indexes[i+1]);
+
+				if (slot_name && strcmp(slot_name, name))
+					continue;
+
+				if (rpaphp_validate_slot(name, indexes[i + 1])) {
+					dbg("%s: slot(%s, 0x%x) is invalid.\n",
+						__FUNCTION__, name, indexes[i+ 1]);
+					continue;
+				}
+
+				slot = alloc_slot_struct();
+				if (!slot) {
+					retval = -ENOMEM;
+					goto exit;
+				}
+
+				slot->name = slot->hotplug_slot->name;
+				slot->index = indexes[i + 1];
+				strcpy(slot->name, name);
+				slot->type = simple_strtoul(type, NULL, 10);
+				if (slot->type < 1  || slot->type > 16)
+					slot->type = 0;
+
+				slot->power_domain = power_domains[i + 1];
+				slot->magic = SLOT_MAGIC;
+				slot->hotplug_slot->private = slot;
+				slot->hotplug_slot->ops = &rpaphp_hotplug_slot_ops;
+				slot->hotplug_slot->release = &rpaphp_release_slot;
+				slot->dn = dn;
+
+				/*
+			 	* Initilize the slot info structure with some known
+			 	* good values.
+			 	*/
+				if (setup_hotplug_slot_info(slot))
+					continue;
+
+				slot->bridge = rpaphp_find_bridge_pdev(slot);
+				if (!slot->bridge && slot_name) { /* slot being added doesn't have pci_dev yet*/
+					dbg("%s: no pci_dev for bridge dn %s\n",
+							__FUNCTION__, slot_name);
+					kfree(slot->hotplug_slot->info);
+					kfree(slot->hotplug_slot->name);
+					kfree(slot->hotplug_slot);
+					kfree(slot);
+					continue;
+				}
+
+				/* find slot's pci_dev if it's not empty*/
+				if (slot->hotplug_slot->info->adapter_status == EMPTY) {
+					slot->state = EMPTY;  /* slot is empty */
+					slot->dev = NULL;
+				} else {  /* slot is occupied */
+					if(!(slot->dn->child)) { /* non-empty slot has to have child */
+						err("%s: slot[%s]'s device_node doesn't have child for adapter\n",
+						__FUNCTION__, slot->name);
+						kfree(slot->hotplug_slot->info);
+						kfree(slot->hotplug_slot->name);
+						kfree(slot->hotplug_slot);
+						kfree(slot);
+						continue;
+
+					}
+
+					slot->dev = rpaphp_find_adapter_pdev(slot);
+					if(slot->dev) {
+						slot->state = CONFIGURED;
+						pci_dev_get(slot->dev);
+					} else {
+						/* DLPAR add as opposed to
+						 * boot time */
+						slot->state = NOT_CONFIGURED;
+						}
+				}
+				dbg("%s registering slot:path[%s] index[%x], name[%s] pdomain[%x] type[%d]\n",
+					__FUNCTION__, dn->full_name, slot->index, slot->name,
+					slot->power_domain, slot->type);
+
+				retval = register_slot(slot);
+				if (retval)
+					goto exit;
+
+				num_slots++;
+
+				if (slot_name)
+					goto exit;
+
+			}/* for indexes */
+		}/* "pci" */
+	}/* find_all_nodes */
+exit:
+	dbg("%s - Exit: num_slots=%d rc[%d]\n",
+		__FUNCTION__, num_slots, retval);
+	return retval;
+}
+
+/*
+ * init_slots - initialize 'struct slot' structures for each slot
+ *
+ */
+static int init_slots (void)
+{
+	int 			retval = 0;
+
+	retval = rpaphp_add_slot(NULL);
+
+	return retval;
+}
+
+
+static int init_rpa (void)
+{
+	int 			retval = 0;
+
+	init_MUTEX(&rpaphp_sem);
+
+	/* initialize internal data structure etc. */
+	retval = init_slots();
+	if (!num_slots)
+		retval = -ENODEV;
+
+	return retval;
+}
+
+static void cleanup_slots (void)
+{
+	struct list_head *tmp, *n;
+	struct slot *slot;
+
+	/*
+	 * Unregister all of our slots with the pci_hotplug subsystem,
+	 * and free up all memory that we had allocated.
+	 * memory will be freed in release_slot callback.
+	 */
+
+	list_for_each_safe (tmp, n, &rpaphp_slot_head) {
+		slot = list_entry(tmp, struct slot, rpaphp_slot_list);
+		sysfs_remove_link(slot->hotplug_slot->kobj.parent,
+			slot->bridge->slot_name);
+		list_del(&slot->rpaphp_slot_list);
+		pci_hp_deregister(slot->hotplug_slot);
+	}
+
+	return;
+}
+
+
+static int __init rpaphp_init(void)
+{
+	int retval = 0;
+
+	info(DRIVER_DESC " version: " DRIVER_VERSION "\n");
+
+	rpaphp_debug = debug;
+
+	/* read all the PRA info from the system */
+	retval = init_rpa();
+
+	return retval;
+}
+
+
+static void __exit rpaphp_exit(void)
+{
+	cleanup_slots();
+}
+
+
+static int enable_slot(struct hotplug_slot *hotplug_slot)
+{
+	int retval = 0, state;
+
+	struct slot *slot = get_slot(hotplug_slot, __FUNCTION__);
+
+	if (slot == NULL)
+		return -ENODEV;
+
+	if (slot->state == CONFIGURED) {
+		dbg("%s: %s is already enabled\n",
+			__FUNCTION__, slot->name);
+		goto exit;
+	}
+
+	dbg("ENABLING SLOT %s\n", slot->name);
+
+	down(&rpaphp_sem);
+
+	retval = rpaphp_get_sensor_state(slot->index, &state);
+
+	if (retval)
+		goto exit;
+
+	dbg("%s: sensor state[%d]\n", __FUNCTION__, state);
+
+	/* if slot is not empty, enable the adapter */
+	if (state == PRESENT) {
+		dbg("%s : slot[%s] is occupid.\n", __FUNCTION__, slot->name);
+
+		
+		slot->dev = rpaphp_config_adapter(slot);
+		if (slot->dev != NULL) {
+			slot->state = CONFIGURED;
+
+			dbg("%s: adapter %s in slot[%s] has been configured\n",
+				__FUNCTION__, slot->dev->slot_name,
+				slot->name);
+		} else {
+			slot->state = NOT_CONFIGURED;
+
+			dbg("%s: no pci_dev struct for adapter in slot[%s]\n",
+				__FUNCTION__, slot->name);
+		}
+
+	} else if (state == EMPTY) {
+		dbg("%s : slot[%s] is empty\n", __FUNCTION__, slot->name);
+		slot->state = EMPTY;
+	} else {
+		err("%s: slot[%s] is in invalid state\n", __FUNCTION__, slot->name);
+		slot->state = NOT_VALID;
+		retval = -EINVAL;
+	}
+
+exit:
+	if (slot->state != NOT_VALID)
+		rpaphp_set_attention_status(slot, LED_ON);
+	else
+		rpaphp_set_attention_status(slot, LED_ID);
+
+	up(&rpaphp_sem);
+
+	return retval;
+}
+
+static int disable_slot(struct hotplug_slot *hotplug_slot)
+{
+	int	retval;
+	struct slot *slot = get_slot(hotplug_slot, __FUNCTION__);
+
+	if (slot == NULL)
+		return -ENODEV;
+
+	dbg("DISABLING SLOT %s\n", slot->name);
+
+	down(&rpaphp_sem);
+
+	rpaphp_set_attention_status(slot, LED_ID);
+
+	retval = rpaphp_unconfig_adapter(slot);
+
+	rpaphp_set_attention_status(slot, LED_OFF);
+
+	up(&rpaphp_sem);
+
+	return retval;
+}
+
+module_init(rpaphp_init);
+module_exit(rpaphp_exit);
+
+EXPORT_SYMBOL_GPL(rpaphp_add_slot);
+EXPORT_SYMBOL_GPL(rpaphp_remove_slot);
--- diff/drivers/pci/hotplug/rpaphp_pci.c	1970-01-01 01:00:00.000000000 +0100
+++ source/drivers/pci/hotplug/rpaphp_pci.c	2004-02-23 13:56:44.000000000 +0000
@@ -0,0 +1,75 @@
+/*
+ * PCI Hot Plug Controller Driver for RPA-compliant PPC64 platform.
+ * Copyright (C) 2003 Linda Xie <lxie@us.ibm.com>
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Send feedback to <lxie@us.ibm.com>
+ *
+ */
+#include <linux/pci.h>
+#include <asm/pci-bridge.h>	/* for pci_controller */
+#include "rpaphp.h"
+
+
+struct pci_dev *rpaphp_find_pci_dev(struct device_node *dn)
+{
+	struct pci_dev		*retval_dev = NULL, *dev = NULL;
+
+	while ((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) {
+		if(!dev->bus)
+			continue;
+
+		if (dev->devfn != dn->devfn)
+			continue;
+
+		if (dn->phb->global_number == pci_domain_nr(dev->bus) &&
+		    dn->busno == dev->bus->number) {
+			retval_dev = dev;
+			break;
+		}
+	}
+
+	return retval_dev;
+
+}
+
+int rpaphp_claim_resource(struct pci_dev *dev, int resource)
+{
+	struct resource *res = &dev->resource[resource];
+	struct resource *root = pci_find_parent_resource(dev, res);
+	char *dtype = resource < PCI_BRIDGE_RESOURCES ? "device" : "bridge";
+	int err;
+
+	err = -EINVAL;
+	if (root != NULL) {
+		err = request_resource(root, res);
+	}
+
+	if (err) {
+		err("PCI: %s region %d of %s %s [%lx:%lx]\n",
+			root ? "Address space collision on" :
+			"No parent found for",
+			resource, dtype, pci_name(dev), res->start, res->end);
+	}
+
+	return err;
+}
+
+EXPORT_SYMBOL_GPL(rpaphp_find_pci_dev);
+EXPORT_SYMBOL_GPL(rpaphp_claim_resource);
--- diff/drivers/pci/hotplug/shpchp.h	1970-01-01 01:00:00.000000000 +0100
+++ source/drivers/pci/hotplug/shpchp.h	2004-02-23 13:56:44.000000000 +0000
@@ -0,0 +1,467 @@
+/*
+ * Standard Hot Plug Controller Driver
+ *
+ * Copyright (C) 1995,2001 Compaq Computer Corporation
+ * Copyright (C) 2001 Greg Kroah-Hartman (greg@kroah.com)
+ * Copyright (C) 2001 IBM
+ * Copyright (C) 2003-2004 Intel Corporation
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Send feedback to <greg@kroah.com>,<dely.l.sy@intel.com>
+ *
+ */
+#ifndef _SHPCHP_H
+#define _SHPCHP_H
+
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <asm/semaphore.h>
+#include <asm/io.h>		
+#include "pci_hotplug.h"
+
+#if !defined(CONFIG_HOTPLUG_PCI_SHPC_MODULE)
+	#define MY_NAME	"shpchp"
+#else
+	#define MY_NAME	THIS_MODULE->name
+#endif
+
+extern int shpchp_poll_mode;
+extern int shpchp_poll_time;
+extern int shpchp_debug;
+
+/*#define dbg(format, arg...) do { if (shpchp_debug) printk(KERN_DEBUG "%s: " format, MY_NAME , ## arg); } while (0)*/
+#define dbg(format, arg...) do { if (shpchp_debug) printk("%s: " format, MY_NAME , ## arg); } while (0)
+#define err(format, arg...) printk(KERN_ERR "%s: " format, MY_NAME , ## arg)
+#define info(format, arg...) printk(KERN_INFO "%s: " format, MY_NAME , ## arg)
+#define warn(format, arg...) printk(KERN_WARNING "%s: " format, MY_NAME , ## arg)
+
+struct pci_func {
+	struct pci_func *next;
+	u8 bus;
+	u8 device;
+	u8 function;
+	u8 is_a_board;
+	u16 status;
+	u8 configured;
+	u8 switch_save;
+	u8 presence_save;
+	u32 base_length[0x06];
+	u8 base_type[0x06];
+	u16 reserved2;
+	u32 config_space[0x20];
+	struct pci_resource *mem_head;
+	struct pci_resource *p_mem_head;
+	struct pci_resource *io_head;
+	struct pci_resource *bus_head;
+	struct pci_dev* pci_dev;
+};
+
+#define SLOT_MAGIC	0x67267321
+struct slot {
+	u32 magic;
+	struct slot *next;
+	u8 bus;
+	u8 device;
+	u32 number;
+	u8 is_a_board;
+	u8 configured;
+	u8 state;
+	u8 switch_save;
+	u8 presence_save;
+	u32 capabilities;
+	u16 reserved2;
+	struct timer_list task_event;
+	u8 hp_slot;
+	struct controller *ctrl;
+	struct hpc_ops *hpc_ops;
+	struct hotplug_slot *hotplug_slot;
+	struct list_head	slot_list;
+};
+
+struct pci_resource {
+	struct pci_resource * next;
+	u32 base;
+	u32 length;
+};
+
+struct event_info {
+	u32 event_type;
+	u8 hp_slot;
+};
+
+struct controller {
+	struct controller *next;
+	struct semaphore crit_sect;	/* critical section semaphore */
+	void * hpc_ctlr_handle;		/* HPC controller handle */
+	int num_slots;			/* Number of slots on ctlr */
+	int slot_num_inc;		/* 1 or -1 */
+	struct pci_resource *mem_head;
+	struct pci_resource *p_mem_head;
+	struct pci_resource *io_head;
+	struct pci_resource *bus_head;
+	struct pci_dev *pci_dev;
+	struct pci_bus *pci_bus;
+	struct event_info event_queue[10];
+	struct slot *slot;
+	struct hpc_ops *hpc_ops;
+	wait_queue_head_t queue;	/* sleep & wake process */
+	u8 next_event;
+	u8 seg;
+	u8 bus;
+	u8 device;
+	u8 function;
+	u8 rev;
+	u8 slot_device_offset;
+	u8 add_support;
+	enum pci_bus_speed speed;
+	u32 first_slot;		/* First physical slot number */
+	u8 slot_bus;		/* Bus where the slots handled by this controller sit */
+	u8 push_flag;
+	u16 ctlrcap;
+	u16 vendor_id;
+};
+
+struct irq_mapping {
+	u8 barber_pole;
+	u8 valid_INT;
+	u8 interrupt[4];
+};
+
+struct resource_lists {
+	struct pci_resource *mem_head;
+	struct pci_resource *p_mem_head;
+	struct pci_resource *io_head;
+	struct pci_resource *bus_head;
+	struct irq_mapping *irqs;
+};
+
+/* Define AMD SHPC ID  */
+#define PCI_DEVICE_ID_AMD_GOLAM_7450	0x7450 
+
+/* Define SHPC CAP ID - not defined in kernel yet */
+#define PCI_CAP_ID_SHPC			0x0C 
+
+#define INT_BUTTON_IGNORE		0
+#define INT_PRESENCE_ON			1
+#define INT_PRESENCE_OFF		2
+#define INT_SWITCH_CLOSE		3
+#define INT_SWITCH_OPEN			4
+#define INT_POWER_FAULT			5
+#define INT_POWER_FAULT_CLEAR		6
+#define INT_BUTTON_PRESS		7
+#define INT_BUTTON_RELEASE		8
+#define INT_BUTTON_CANCEL		9
+
+#define STATIC_STATE			0
+#define BLINKINGON_STATE		1
+#define BLINKINGOFF_STATE		2
+#define POWERON_STATE			3
+#define POWEROFF_STATE			4
+
+#define PCI_TO_PCI_BRIDGE_CLASS		0x00060400
+
+/* Error messages */
+#define INTERLOCK_OPEN			0x00000002
+#define ADD_NOT_SUPPORTED		0x00000003
+#define CARD_FUNCTIONING		0x00000005
+#define ADAPTER_NOT_SAME		0x00000006
+#define NO_ADAPTER_PRESENT		0x00000009
+#define NOT_ENOUGH_RESOURCES		0x0000000B
+#define DEVICE_TYPE_NOT_SUPPORTED	0x0000000C
+#define WRONG_BUS_FREQUENCY		0x0000000D
+#define POWER_FAILURE			0x0000000E
+
+#define REMOVE_NOT_SUPPORTED		0x00000003
+
+#define DISABLE_CARD			1
+
+/*
+ * error Messages
+ */
+#define msg_initialization_err	"Initialization failure, error=%d\n"
+#define msg_HPC_rev_error	"Unsupported revision of the PCI hot plug controller found.\n"
+#define msg_HPC_non_shpc	"The PCI hot plug controller is not supported by this driver.\n"
+#define msg_HPC_not_supported	"This system is not supported by this version of shpcphd mdoule. Upgrade to a newer version of shpchpd\n"
+#define msg_unable_to_save	"Unable to store PCI hot plug add resource information. This system must be rebooted before adding any PCI devices.\n"
+#define msg_button_on		"PCI slot #%d - powering on due to button press.\n"
+#define msg_button_off		"PCI slot #%d - powering off due to button press.\n"
+#define msg_button_cancel	"PCI slot #%d - action canceled due to button press.\n"
+#define msg_button_ignore	"PCI slot #%d - button press ignored.  (action in progress...)\n"
+
+/* sysfs functions for the hotplug controller info */
+extern void shpchp_create_ctrl_files	(struct controller *ctrl);
+
+/* controller functions */
+extern void	shpchp_pushbutton_thread(unsigned long event_pointer);
+extern int	shpchprm_find_available_resources(struct controller *ctrl);
+extern int	shpchp_event_start_thread(void);
+extern void	shpchp_event_stop_thread(void);
+extern struct 	pci_func *shpchp_slot_create(unsigned char busnumber);
+extern struct 	pci_func *shpchp_slot_find(unsigned char bus, unsigned char device, unsigned char index);
+extern int	shpchp_enable_slot(struct slot *slot);
+extern int	shpchp_disable_slot(struct slot *slot);
+
+extern u8	shpchp_handle_attention_button(u8 hp_slot, void *inst_id);
+extern u8	shpchp_handle_switch_change(u8 hp_slot, void *inst_id);
+extern u8	shpchp_handle_presence_change(u8 hp_slot, void *inst_id);
+extern u8	shpchp_handle_power_fault(u8 hp_slot, void *inst_id);
+
+/* resource functions */
+extern int	shpchp_resource_sort_and_combine(struct pci_resource **head);
+
+/* pci functions */
+extern int	shpchp_set_irq(u8 bus_num, u8 dev_num, u8 int_pin, u8 irq_num);
+/*extern int	shpchp_get_bus_dev(struct controller *ctrl, u8 *bus_num, u8 *dev_num, struct slot *slot);*/
+extern int	shpchp_save_config(struct controller *ctrl, int busnumber, int num_ctlr_slots, int first_device_num);
+extern int	shpchp_save_used_resources(struct controller *ctrl, struct pci_func * func, int flag);
+extern int	shpchp_save_slot_config(struct controller *ctrl, struct pci_func * new_slot);
+extern void	shpchp_destroy_board_resources(struct pci_func * func);
+extern int	shpchp_return_board_resources(struct pci_func * func, struct resource_lists * resources);
+extern void	shpchp_destroy_resource_list(struct resource_lists * resources);
+extern int	shpchp_configure_device(struct controller* ctrl, struct pci_func* func);
+extern int	shpchp_unconfigure_device(struct pci_func* func);
+
+
+/* Global variables */
+extern struct controller *shpchp_ctrl_list;
+extern struct pci_func *shpchp_slot_list[256];
+
+/* These are added to support AMD shpc */
+extern u8 shpchp_nic_irq;
+extern u8 shpchp_disk_irq;
+
+struct ctrl_reg {
+	volatile u32 base_offset;
+	volatile u32 slot_avail1;
+	volatile u32 slot_avail2;
+	volatile u32 slot_config;
+	volatile u16 sec_bus_config;
+	volatile u8  msi_ctrl;
+	volatile u8  prog_interface;
+	volatile u16 cmd;
+	volatile u16 cmd_status;
+	volatile u32 intr_loc;
+	volatile u32 serr_loc;
+	volatile u32 serr_intr_enable;
+	volatile u32 slot1;
+	volatile u32 slot2;
+	volatile u32 slot3;
+	volatile u32 slot4;
+	volatile u32 slot5;
+	volatile u32 slot6;
+	volatile u32 slot7;
+	volatile u32 slot8;
+	volatile u32 slot9;
+	volatile u32 slot10;
+	volatile u32 slot11;
+	volatile u32 slot12;
+} __attribute__ ((packed));
+
+/* offsets to the controller registers based on the above structure layout */
+enum ctrl_offsets {
+	BASE_OFFSET =	offsetof(struct ctrl_reg, base_offset),
+	SLOT_AVAIL1 =	offsetof(struct ctrl_reg, slot_avail1),
+	SLOT_AVAIL2	=	offsetof(struct ctrl_reg, slot_avail2),
+	SLOT_CONFIG =	offsetof(struct ctrl_reg, slot_config),
+	SEC_BUS_CONFIG =	offsetof(struct ctrl_reg, sec_bus_config),
+	MSI_CTRL	=	offsetof(struct ctrl_reg, msi_ctrl),
+	PROG_INTERFACE =	offsetof(struct ctrl_reg, prog_interface),
+	CMD		=	offsetof(struct ctrl_reg, cmd),
+	CMD_STATUS	=	offsetof(struct ctrl_reg, cmd_status),
+	INTR_LOC	= 	offsetof(struct ctrl_reg, intr_loc),
+	SERR_LOC	= 	offsetof(struct ctrl_reg, serr_loc),
+	SERR_INTR_ENABLE =	offsetof(struct ctrl_reg, serr_intr_enable),
+	SLOT1 =		offsetof(struct ctrl_reg, slot1),
+	SLOT2 =		offsetof(struct ctrl_reg, slot2),
+	SLOT3 =		offsetof(struct ctrl_reg, slot3),
+	SLOT4 =		offsetof(struct ctrl_reg, slot4),
+	SLOT5 =		offsetof(struct ctrl_reg, slot5),
+	SLOT6 =		offsetof(struct ctrl_reg, slot6),		
+	SLOT7 =		offsetof(struct ctrl_reg, slot7),
+	SLOT8 =		offsetof(struct ctrl_reg, slot8),
+	SLOT9 =		offsetof(struct ctrl_reg, slot9),
+	SLOT10 =	offsetof(struct ctrl_reg, slot10),
+	SLOT11 =	offsetof(struct ctrl_reg, slot11),
+	SLOT12 =	offsetof(struct ctrl_reg, slot12),
+};
+typedef u8(*php_intr_callback_t) (unsigned int change_id, void *instance_id);
+struct php_ctlr_state_s {
+	struct php_ctlr_state_s *pnext;
+	struct pci_dev *pci_dev;
+	unsigned int irq;
+	unsigned long flags;	/* spinlock's */
+	u32 slot_device_offset;
+	u32 num_slots;
+    	struct timer_list	int_poll_timer;	/* Added for poll event */
+	php_intr_callback_t attention_button_callback;
+	php_intr_callback_t switch_change_callback;
+	php_intr_callback_t presence_change_callback;
+	php_intr_callback_t power_fault_callback;
+	void *callback_instance_id;
+	void *creg;				/* Ptr to controller register space */
+};
+/* Inline functions */
+
+
+/* Inline functions to check the sanity of a pointer that is passed to us */
+static inline int slot_paranoia_check (struct slot *slot, const char *function)
+{
+	if (!slot) {
+		dbg("%s - slot == NULL", function);
+		return -1;
+	}
+	if (slot->magic != SLOT_MAGIC) {
+		dbg("%s - bad magic number for slot", function);
+		return -1;
+	}
+	if (!slot->hotplug_slot) {
+		dbg("%s - slot->hotplug_slot == NULL!", function);
+		return -1;
+	}
+	return 0;
+}
+
+static inline struct slot *get_slot (struct hotplug_slot *hotplug_slot, const char *function)
+{ 
+	struct slot *slot;
+
+	if (!hotplug_slot) {
+		dbg("%s - hotplug_slot == NULL\n", function);
+		return NULL;
+	}
+
+	slot = (struct slot *)hotplug_slot->private;
+	if (slot_paranoia_check (slot, function))
+                return NULL;
+	return slot;
+}
+
+static inline struct slot *shpchp_find_slot (struct controller *ctrl, u8 device)
+{
+	struct slot *p_slot, *tmp_slot = NULL;
+
+	if (!ctrl)
+		return NULL;
+
+	p_slot = ctrl->slot;
+
+	dbg("p_slot = %p\n", p_slot);
+
+	while (p_slot && (p_slot->device != device)) {
+		tmp_slot = p_slot;
+		p_slot = p_slot->next;
+		dbg("In while loop, p_slot = %p\n", p_slot);
+	}
+	if (p_slot == NULL) {
+		err("ERROR: shpchp_find_slot device=0x%x\n", device);
+		p_slot = tmp_slot;
+	}
+
+	return (p_slot);
+}
+
+static inline int wait_for_ctrl_irq (struct controller *ctrl)
+{
+    DECLARE_WAITQUEUE(wait, current);
+	int retval = 0;
+
+	dbg("%s : start\n",__FUNCTION__);
+
+	add_wait_queue(&ctrl->queue, &wait);
+	set_current_state(TASK_INTERRUPTIBLE);
+
+	if (!shpchp_poll_mode) {
+		/* Sleep for up to 1 second */
+		schedule_timeout(1*HZ);
+	} else {
+		/* Sleep for up to 1.5 second */
+		schedule_timeout(1.5*HZ);
+	}
+	set_current_state(TASK_RUNNING);
+	remove_wait_queue(&ctrl->queue, &wait);
+	if (signal_pending(current))
+		retval =  -EINTR;
+
+	dbg("%s : end\n", __FUNCTION__);
+	return retval;
+}
+
+/* Puts node back in the resource list pointed to by head */
+static inline void return_resource(struct pci_resource **head, struct pci_resource *node)
+{
+	if (!node || !head)
+		return;
+	node->next = *head;
+	*head = node;
+}
+
+#define SLOT_NAME_SIZE 10
+
+static inline void make_slot_name(char *buffer, int buffer_size, struct slot *slot)
+{
+	snprintf(buffer, buffer_size, "%d", slot->number);
+}
+
+enum php_ctlr_type {
+	PCI,
+	ISA,
+	ACPI
+};
+
+int shpc_init( struct controller *ctrl, struct pci_dev *pdev,
+		php_intr_callback_t attention_button_callback,
+		php_intr_callback_t switch_change_callback,
+		php_intr_callback_t presence_change_callback,
+		php_intr_callback_t power_fault_callback);
+
+int shpc_get_ctlr_slot_config( struct controller *ctrl,
+		int *num_ctlr_slots,
+		int *first_device_num,
+		int *physical_slot_num,
+		int *updown,
+		int *flags);
+
+struct hpc_ops {
+	int	(*power_on_slot )		(struct slot *slot);
+	int	(*slot_enable )			(struct slot *slot);
+	int	(*slot_disable )		(struct slot *slot);
+	int	(*enable_all_slots)		(struct slot *slot);
+	int	(*pwr_on_all_slots)		(struct slot *slot);
+	int	(*set_bus_speed_mode)	(struct slot *slot, enum pci_bus_speed speed);
+	int	(*get_power_status)		(struct slot *slot, u8 *status);
+	int	(*get_attention_status)	(struct slot *slot, u8 *status);
+	int	(*set_attention_status)	(struct slot *slot, u8 status);
+	int	(*get_latch_status)		(struct slot *slot, u8 *status);
+	int	(*get_adapter_status)	(struct slot *slot, u8 *status);
+
+	int	(*get_max_bus_speed)	(struct slot *slot, enum pci_bus_speed *speed);
+	int	(*get_cur_bus_speed)	(struct slot *slot, enum pci_bus_speed *speed);
+	int	(*get_adapter_speed)	(struct slot *slot, enum pci_bus_speed *speed);
+	int	(*get_mode1_ECC_cap)	(struct slot *slot, u8 *mode);
+	int	(*get_prog_int)			(struct slot *slot, u8 *prog_int);
+
+	int	(*query_power_fault)	(struct slot *slot);
+	void	(*green_led_on)		(struct slot *slot);
+	void	(*green_led_off)	(struct slot *slot);
+	void	(*green_led_blink)	(struct slot *slot);
+	void	(*release_ctlr)		(struct controller *ctrl);
+	int (*check_cmd_status)		(struct controller *ctrl);
+};
+
+#endif				/* _SHPCHP_H */
--- diff/drivers/pci/hotplug/shpchp_core.c	1970-01-01 01:00:00.000000000 +0100
+++ source/drivers/pci/hotplug/shpchp_core.c	2004-02-23 13:56:44.000000000 +0000
@@ -0,0 +1,704 @@
+/*
+ * Standard Hot Plug Controller Driver
+ *
+ * Copyright (C) 1995,2001 Compaq Computer Corporation
+ * Copyright (C) 2001 Greg Kroah-Hartman (greg@kroah.com)
+ * Copyright (C) 2001 IBM Corp.
+ * Copyright (C) 2003-2004 Intel Corporation
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Send feedback to <greg@kroah.com>, <dely.l.sy@intel.com>
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/proc_fs.h>
+#include <linux/miscdevice.h>
+#include <linux/slab.h>
+#include <linux/workqueue.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <asm/uaccess.h>
+#include "shpchp.h"
+#include "shpchprm.h"
+
+/* Global variables */
+int shpchp_debug;
+int shpchp_poll_mode;
+int shpchp_poll_time;
+struct controller *shpchp_ctrl_list;	/* = NULL */
+struct pci_func *shpchp_slot_list[256];
+
+#define DRIVER_VERSION	"0.4"
+#define DRIVER_AUTHOR	"Dan Zink <dan.zink@compaq.com>, Greg Kroah-Hartman <greg@kroah.com>, Dely Sy <dely.l.sy@intel.com>"
+#define DRIVER_DESC	"Standard Hot Plug PCI Controller Driver"
+
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_LICENSE("GPL");
+
+MODULE_PARM(shpchp_debug, "i");
+MODULE_PARM(shpchp_poll_mode, "i");
+MODULE_PARM(shpchp_poll_time, "i");
+MODULE_PARM_DESC(shpchp_debug, "Debugging mode enabled or not");
+MODULE_PARM_DESC(shpchp_poll_mode, "Using polling mechanism for hot-plug events or not");
+MODULE_PARM_DESC(shpchp_poll_time, "Polling mechanism frequency, in seconds");
+
+#define SHPC_MODULE_NAME "shpchp"
+
+static int shpc_start_thread (void);
+static int set_attention_status (struct hotplug_slot *slot, u8 value);
+static int enable_slot		(struct hotplug_slot *slot);
+static int disable_slot		(struct hotplug_slot *slot);
+static int hardware_test	(struct hotplug_slot *slot, u32 value);
+static int get_power_status	(struct hotplug_slot *slot, u8 *value);
+static int get_attention_status	(struct hotplug_slot *slot, u8 *value);
+static int get_latch_status	(struct hotplug_slot *slot, u8 *value);
+static int get_adapter_status	(struct hotplug_slot *slot, u8 *value);
+static int get_max_bus_speed	(struct hotplug_slot *slot, enum pci_bus_speed *value);
+static int get_cur_bus_speed	(struct hotplug_slot *slot, enum pci_bus_speed *value);
+
+static struct hotplug_slot_ops shpchp_hotplug_slot_ops = {
+	.owner =		THIS_MODULE,
+	.set_attention_status =	set_attention_status,
+	.enable_slot =		enable_slot,
+	.disable_slot =		disable_slot,
+	.hardware_test =	hardware_test,
+	.get_power_status =	get_power_status,
+	.get_attention_status =	get_attention_status,
+	.get_latch_status =		get_latch_status,
+	.get_adapter_status =	get_adapter_status,
+  	.get_max_bus_speed =	get_max_bus_speed,
+  	.get_cur_bus_speed =	get_cur_bus_speed,
+};
+
+static int init_slots(struct controller *ctrl)
+{
+	struct slot *new_slot;
+	u8 number_of_slots;
+	u8 slot_device;
+	u32 slot_number, sun;
+	int result;
+
+	dbg("%s\n",__FUNCTION__);
+
+	number_of_slots = ctrl->num_slots;
+	slot_device = ctrl->slot_device_offset;
+	slot_number = ctrl->first_slot;
+
+	while (number_of_slots) {
+		new_slot = (struct slot *) kmalloc(sizeof(struct slot), GFP_KERNEL);
+		if (!new_slot)
+			return -ENOMEM;
+
+		memset(new_slot, 0, sizeof(struct slot));
+		new_slot->hotplug_slot = kmalloc (sizeof (struct hotplug_slot), GFP_KERNEL);
+		if (!new_slot->hotplug_slot) {
+			kfree (new_slot);
+			return -ENOMEM;
+		}
+		memset(new_slot->hotplug_slot, 0, sizeof (struct hotplug_slot));
+
+		new_slot->hotplug_slot->info = kmalloc (sizeof (struct hotplug_slot_info), GFP_KERNEL);
+		if (!new_slot->hotplug_slot->info) {
+			kfree (new_slot->hotplug_slot);
+			kfree (new_slot);
+			return -ENOMEM;
+		}
+		memset(new_slot->hotplug_slot->info, 0, sizeof (struct hotplug_slot_info));
+		new_slot->hotplug_slot->name = kmalloc (SLOT_NAME_SIZE, GFP_KERNEL);
+		if (!new_slot->hotplug_slot->name) {
+			kfree (new_slot->hotplug_slot->info);
+			kfree (new_slot->hotplug_slot);
+			kfree (new_slot);
+			return -ENOMEM;
+		}
+
+		new_slot->magic = SLOT_MAGIC;
+		new_slot->ctrl = ctrl;
+		new_slot->bus = ctrl->slot_bus;
+		new_slot->device = slot_device;
+		new_slot->hpc_ops = ctrl->hpc_ops;
+
+		if (shpchprm_get_physical_slot_number(ctrl, &sun, new_slot->bus, new_slot->device)) {
+			kfree (new_slot->hotplug_slot->info);
+			kfree (new_slot->hotplug_slot);
+			kfree (new_slot);
+			return -ENOMEM;
+		}
+
+		new_slot->number = sun;
+		new_slot->hp_slot = slot_device - ctrl->slot_device_offset;
+
+		/* register this slot with the hotplug pci core */
+		new_slot->hotplug_slot->private = new_slot;
+		make_slot_name (new_slot->hotplug_slot->name, SLOT_NAME_SIZE, new_slot);
+		new_slot->hotplug_slot->ops = &shpchp_hotplug_slot_ops;
+
+		new_slot->hpc_ops->get_power_status(new_slot, &(new_slot->hotplug_slot->info->power_status));
+		new_slot->hpc_ops->get_attention_status(new_slot, &(new_slot->hotplug_slot->info->attention_status));
+		new_slot->hpc_ops->get_latch_status(new_slot, &(new_slot->hotplug_slot->info->latch_status));
+		new_slot->hpc_ops->get_adapter_status(new_slot, &(new_slot->hotplug_slot->info->adapter_status));
+
+		dbg("Registering bus=%x dev=%x hp_slot=%x sun=%x slot_device_offset=%x\n", new_slot->bus, 
+			new_slot->device, new_slot->hp_slot, new_slot->number, ctrl->slot_device_offset);
+		result = pci_hp_register (new_slot->hotplug_slot);
+		if (result) {
+			err ("pci_hp_register failed with error %d\n", result);
+			kfree (new_slot->hotplug_slot->info);
+			kfree (new_slot->hotplug_slot->name);
+			kfree (new_slot->hotplug_slot);
+			kfree (new_slot);
+			return result;
+		}
+
+		new_slot->next = ctrl->slot;
+		ctrl->slot = new_slot;
+
+		number_of_slots--;
+		slot_device++;
+		slot_number += ctrl->slot_num_inc;
+	}
+
+	return(0);
+}
+
+
+static int cleanup_slots (struct controller * ctrl)
+{
+	struct slot *old_slot, *next_slot;
+
+	old_slot = ctrl->slot;
+	ctrl->slot = NULL;
+
+	while (old_slot) {
+		next_slot = old_slot->next;
+		pci_hp_deregister (old_slot->hotplug_slot);
+		kfree(old_slot->hotplug_slot->info);
+		kfree(old_slot->hotplug_slot->name);
+		kfree(old_slot->hotplug_slot);
+		kfree(old_slot);
+		old_slot = next_slot;
+	}
+
+
+	return(0);
+}
+
+static int get_ctlr_slot_config(struct controller *ctrl)
+{
+	int num_ctlr_slots;
+	int first_device_num;
+	int physical_slot_num;
+	int updown;
+	int rc;
+	int flags;
+
+	rc = shpc_get_ctlr_slot_config(ctrl, &num_ctlr_slots, &first_device_num, &physical_slot_num, &updown, &flags);
+	if (rc) {
+		err("%s: get_ctlr_slot_config fail for b:d (%x:%x)\n", __FUNCTION__, ctrl->bus, ctrl->device);
+		return (-1);
+	}
+
+	ctrl->num_slots = num_ctlr_slots;
+	ctrl->slot_device_offset = first_device_num;
+	ctrl->first_slot = physical_slot_num;
+	ctrl->slot_num_inc = updown;		/* either -1 or 1 */
+
+	dbg("%s: num_slot(0x%x) 1st_dev(0x%x) psn(0x%x) updown(%d) for b:d (%x:%x)\n",
+		__FUNCTION__, num_ctlr_slots, first_device_num, physical_slot_num, updown, ctrl->bus, ctrl->device);
+
+	return (0);
+}
+
+
+/*
+ * set_attention_status - Turns the Amber LED for a slot on, off or blink
+ */
+static int set_attention_status (struct hotplug_slot *hotplug_slot, u8 status)
+{
+	struct slot *slot = get_slot (hotplug_slot, __FUNCTION__);
+
+	if (slot == NULL)
+		return -ENODEV;
+	
+	dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
+
+	hotplug_slot->info->attention_status = status;
+	slot->hpc_ops->set_attention_status(slot, status);
+
+
+	return 0;
+}
+
+
+static int enable_slot (struct hotplug_slot *hotplug_slot)
+{
+	struct slot *slot = get_slot (hotplug_slot, __FUNCTION__);
+	
+	if (slot == NULL)
+		return -ENODEV;
+
+	dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
+
+	return shpchp_enable_slot(slot);
+}
+
+
+static int disable_slot (struct hotplug_slot *hotplug_slot)
+{
+	struct slot *slot = get_slot (hotplug_slot, __FUNCTION__);
+	
+	if (slot == NULL)
+		return -ENODEV;
+
+	dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
+
+	return shpchp_disable_slot(slot);
+}
+
+
+static int hardware_test (struct hotplug_slot *hotplug_slot, u32 value)
+{
+	return 0;
+}
+
+
+static int get_power_status (struct hotplug_slot *hotplug_slot, u8 *value)
+{
+	struct slot *slot = get_slot (hotplug_slot, __FUNCTION__);
+	int retval;
+	
+	if (slot == NULL)
+		return -ENODEV;
+	
+	dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
+
+	retval = slot->hpc_ops->get_power_status(slot, value);
+	if (retval < 0)
+		*value = hotplug_slot->info->power_status;
+
+	return 0;
+}
+
+static int get_attention_status (struct hotplug_slot *hotplug_slot, u8 *value)
+{
+	struct slot *slot = get_slot (hotplug_slot, __FUNCTION__);
+	int retval;
+	
+	if (slot == NULL)
+		return -ENODEV;
+	
+	dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
+
+	retval = slot->hpc_ops->get_attention_status(slot, value);
+	if (retval < 0)
+		*value = hotplug_slot->info->attention_status;
+
+	return 0;
+}
+
+static int get_latch_status (struct hotplug_slot *hotplug_slot, u8 *value)
+{
+	struct slot *slot = get_slot (hotplug_slot, __FUNCTION__);
+	int retval;
+	
+	if (slot == NULL)
+		return -ENODEV;
+	
+	dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
+
+	retval = slot->hpc_ops->get_latch_status(slot, value);
+	if (retval < 0)
+		*value = hotplug_slot->info->latch_status;
+
+	return 0;
+}
+
+static int get_adapter_status (struct hotplug_slot *hotplug_slot, u8 *value)
+{
+	struct slot *slot = get_slot (hotplug_slot, __FUNCTION__);
+	int retval;
+	
+	if (slot == NULL)
+		return -ENODEV;
+
+	dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
+
+	retval = slot->hpc_ops->get_adapter_status(slot, value);
+
+	if (retval < 0)
+		*value = hotplug_slot->info->adapter_status;
+
+	return 0;
+}
+
+static int get_max_bus_speed (struct hotplug_slot *hotplug_slot, enum pci_bus_speed *value)
+{
+	struct slot *slot = get_slot (hotplug_slot, __FUNCTION__);
+	int retval;
+	
+	if (slot == NULL)
+		return -ENODEV;
+
+	dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
+	
+	retval = slot->hpc_ops->get_max_bus_speed(slot, value);
+	if (retval < 0)
+		*value = PCI_SPEED_UNKNOWN;
+
+	return 0;
+}
+
+static int get_cur_bus_speed (struct hotplug_slot *hotplug_slot, enum pci_bus_speed *value)
+{
+	struct slot *slot = get_slot (hotplug_slot, __FUNCTION__);
+	int retval;
+	
+	if (slot == NULL)
+		return -ENODEV;
+
+	dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
+	
+	retval = slot->hpc_ops->get_cur_bus_speed(slot, value);
+	if (retval < 0)
+		*value = PCI_SPEED_UNKNOWN;
+
+	return 0;
+}
+
+static int shpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
+{
+	int rc;
+	struct controller *ctrl;
+	struct slot *t_slot;
+	int first_device_num;	/* first PCI device number supported by this SHPC */
+	int num_ctlr_slots;	/* number of slots supported by this SHPC */
+
+	ctrl = (struct controller *) kmalloc(sizeof(struct controller), GFP_KERNEL);
+	if (!ctrl) {
+		err("%s : out of memory\n", __FUNCTION__);
+		goto err_out_none;
+	}
+	memset(ctrl, 0, sizeof(struct controller));
+
+	dbg("DRV_thread pid = %d\n", current->pid);
+
+	rc = shpc_init(ctrl, pdev,
+			(php_intr_callback_t) shpchp_handle_attention_button,
+			(php_intr_callback_t) shpchp_handle_switch_change,
+			(php_intr_callback_t) shpchp_handle_presence_change,
+			(php_intr_callback_t) shpchp_handle_power_fault);
+	if (rc) {
+		dbg("%s: controller initialization failed\n", SHPC_MODULE_NAME);
+		goto err_out_free_ctrl;
+	}
+
+	dbg("%s: controller initialization success\n", __FUNCTION__);
+	ctrl->pci_dev = pdev;  /* pci_dev of the P2P bridge */
+
+	pci_set_drvdata(pdev, ctrl);
+
+	ctrl->pci_bus = kmalloc (sizeof (*ctrl->pci_bus), GFP_KERNEL);
+	if (!ctrl->pci_bus) {
+		err("out of memory\n");
+		rc = -ENOMEM;
+		goto err_out_unmap_mmio_region;
+	}
+	
+	memcpy (ctrl->pci_bus, pdev->bus, sizeof (*ctrl->pci_bus));
+	ctrl->bus = pdev->bus->number;
+	ctrl->slot_bus = pdev->subordinate->number;
+
+	ctrl->device = PCI_SLOT(pdev->devfn);
+	ctrl->function = PCI_FUNC(pdev->devfn);
+	dbg("ctrl bus=0x%x, device=%x, function=%x, irq=%x\n", ctrl->bus, ctrl->device, ctrl->function, pdev->irq);
+
+	/*
+	 *	Save configuration headers for this and subordinate PCI buses
+	 */
+
+	rc = get_ctlr_slot_config(ctrl);
+	if (rc) {
+		err(msg_initialization_err, rc);
+		goto err_out_free_ctrl_bus;
+	}
+	first_device_num = ctrl->slot_device_offset;
+	num_ctlr_slots = ctrl->num_slots;
+
+	/* Store PCI Config Space for all devices on this bus */
+	rc = shpchp_save_config(ctrl, ctrl->slot_bus, num_ctlr_slots, first_device_num);
+	if (rc) {
+		err("%s: unable to save PCI configuration data, error %d\n", __FUNCTION__, rc);
+		goto err_out_free_ctrl_bus;
+	}
+
+	/* Get IO, memory, and IRQ resources for new devices */
+	rc = shpchprm_find_available_resources(ctrl);
+	ctrl->add_support = !rc;
+	
+	if (rc) {
+		dbg("shpchprm_find_available_resources = %#x\n", rc);
+		err("unable to locate PCI configuration resources for hot plug add.\n");
+		goto err_out_free_ctrl_bus;
+	}
+
+	/* Setup the slot information structures */
+	rc = init_slots(ctrl);
+	if (rc) {
+		err(msg_initialization_err, 6);
+		goto err_out_free_ctrl_slot;
+	}
+
+	/* Now hpc_functions (slot->hpc_ops->functions) are ready  */
+	t_slot = shpchp_find_slot(ctrl, first_device_num);
+
+	/* Check for operation bus speed */
+	rc = t_slot->hpc_ops->get_cur_bus_speed(t_slot, &ctrl->speed);
+	dbg("%s: t_slot->hp_slot %x\n", __FUNCTION__,t_slot->hp_slot);
+
+	if (rc || ctrl->speed == PCI_SPEED_UNKNOWN) {
+		err(SHPC_MODULE_NAME ": Can't get current bus speed. Set to 33MHz PCI.\n");
+		ctrl->speed = PCI_SPEED_33MHz;
+	}
+
+	/* Finish setting up the hot plug ctrl device */
+	ctrl->next_event = 0;
+
+	if (!shpchp_ctrl_list) {
+		shpchp_ctrl_list = ctrl;
+		ctrl->next = NULL;
+	} else {
+		ctrl->next = shpchp_ctrl_list;
+		shpchp_ctrl_list = ctrl;
+	}
+
+	shpchp_create_ctrl_files(ctrl);
+
+	return 0;
+
+err_out_free_ctrl_slot:
+	cleanup_slots(ctrl);
+err_out_free_ctrl_bus:
+	kfree(ctrl->pci_bus);
+err_out_unmap_mmio_region:
+	ctrl->hpc_ops->release_ctlr(ctrl);
+err_out_free_ctrl:
+	kfree(ctrl);
+err_out_none:
+	return -ENODEV;
+}
+
+
+static int shpc_start_thread(void)
+{
+	int loop;
+	int retval = 0;
+	
+	dbg("Initialize + Start the notification/polling mechanism \n");
+
+	retval = shpchp_event_start_thread();
+	if (retval) {
+		dbg("shpchp_event_start_thread() failed\n");
+		return retval;
+	}
+
+	dbg("Initialize slot lists\n");
+	/* One slot list for each bus in the system */
+	for (loop = 0; loop < 256; loop++) {
+		shpchp_slot_list[loop] = NULL;
+	}
+
+	return retval;
+}
+
+
+static void unload_shpchpd(void)
+{
+	struct pci_func *next;
+	struct pci_func *TempSlot;
+	int loop;
+	struct controller *ctrl;
+	struct controller *tctrl;
+	struct pci_resource *res;
+	struct pci_resource *tres;
+
+	ctrl = shpchp_ctrl_list;
+
+	while (ctrl) {
+		cleanup_slots(ctrl);
+
+		res = ctrl->io_head;
+		while (res) {
+			tres = res;
+			res = res->next;
+			kfree(tres);
+		}
+
+		res = ctrl->mem_head;
+		while (res) {
+			tres = res;
+			res = res->next;
+			kfree(tres);
+		}
+
+		res = ctrl->p_mem_head;
+		while (res) {
+			tres = res;
+			res = res->next;
+			kfree(tres);
+		}
+
+		res = ctrl->bus_head;
+		while (res) {
+			tres = res;
+			res = res->next;
+			kfree(tres);
+		}
+
+		kfree (ctrl->pci_bus);
+
+		dbg("%s: calling release_ctlr\n", __FUNCTION__);
+		ctrl->hpc_ops->release_ctlr(ctrl);
+
+		tctrl = ctrl;
+		ctrl = ctrl->next;
+
+		kfree(tctrl);
+	}
+
+	for (loop = 0; loop < 256; loop++) {
+		next = shpchp_slot_list[loop];
+		while (next != NULL) {
+			res = next->io_head;
+			while (res) {
+				tres = res;
+				res = res->next;
+				kfree(tres);
+			}
+
+			res = next->mem_head;
+			while (res) {
+				tres = res;
+				res = res->next;
+				kfree(tres);
+			}
+
+			res = next->p_mem_head;
+			while (res) {
+				tres = res;
+				res = res->next;
+				kfree(tres);
+			}
+
+			res = next->bus_head;
+			while (res) {
+				tres = res;
+				res = res->next;
+				kfree(tres);
+			}
+
+			TempSlot = next;
+			next = next->next;
+			kfree(TempSlot);
+		}
+	}
+
+	/* Stop the notification mechanism */
+	shpchp_event_stop_thread();
+
+}
+
+
+static struct pci_device_id shpcd_pci_tbl[] = {
+	{
+	.class =        ((PCI_CLASS_BRIDGE_PCI << 8) | 0x00),
+	.class_mask =	~0,
+	.vendor =       PCI_ANY_ID,
+	.device =       PCI_ANY_ID,
+	.subvendor =    PCI_ANY_ID,
+	.subdevice =    PCI_ANY_ID,
+	},
+	
+	{ /* end: all zeroes */ }
+};
+
+MODULE_DEVICE_TABLE(pci, shpcd_pci_tbl);
+
+
+
+static struct pci_driver shpc_driver = {
+	.name =		SHPC_MODULE_NAME,
+	.id_table =	shpcd_pci_tbl,
+	.probe =	shpc_probe,
+	/* remove:	shpc_remove_one, */
+};
+
+
+
+static int __init shpcd_init(void)
+{
+	int retval = 0;
+
+#ifdef CONFIG_HOTPLUG_PCI_SHPC_POLL_EVENT_MODE
+	shpchp_poll_mode = 1;
+#endif
+
+	retval = shpc_start_thread();
+	if (retval)
+		goto error_hpc_init;
+
+	retval = shpchprm_init(PCI);
+	if (!retval) {
+		retval = pci_module_init(&shpc_driver);
+		dbg("%s: pci_module_init = %d\n", __FUNCTION__, retval);
+		info(DRIVER_DESC " version: " DRIVER_VERSION "\n");
+	}
+
+error_hpc_init:
+	if (retval) {
+		shpchprm_cleanup();
+		shpchp_event_stop_thread();
+	} else
+		shpchprm_print_pirt();
+
+	return retval;
+}
+
+static void __exit shpcd_cleanup(void)
+{
+	dbg("unload_shpchpd()\n");
+	unload_shpchpd();
+
+	shpchprm_cleanup();
+
+	dbg("pci_unregister_driver\n");
+	pci_unregister_driver(&shpc_driver);
+
+	info(DRIVER_DESC " version: " DRIVER_VERSION " unloaded\n");
+}
+
+
+module_init(shpcd_init);
+module_exit(shpcd_cleanup);
+
+
--- diff/drivers/pci/hotplug/shpchp_ctrl.c	1970-01-01 01:00:00.000000000 +0100
+++ source/drivers/pci/hotplug/shpchp_ctrl.c	2004-02-23 13:56:44.000000000 +0000
@@ -0,0 +1,3055 @@
+/*
+ * Standard Hot Plug Controller Driver
+ *
+ * Copyright (C) 1995,2001 Compaq Computer Corporation
+ * Copyright (C) 2001 Greg Kroah-Hartman (greg@kroah.com)
+ * Copyright (C) 2001 IBM Corp.
+ * Copyright (C) 2003-2004 Intel Corporation
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Send feedback to <greg@kroah.com>, <dely.l.sy@intel.com>
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/slab.h>
+#include <linux/workqueue.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/wait.h>
+#include <linux/smp_lock.h>
+#include <linux/pci.h>
+#include "shpchp.h"
+#include "shpchprm.h"
+
+static u32 configure_new_device(struct controller *ctrl, struct pci_func *func,
+	u8 behind_bridge, struct resource_lists *resources, u8 bridge_bus, u8 bridge_dev);
+static int configure_new_function( struct controller *ctrl, struct pci_func *func,
+	u8 behind_bridge, struct resource_lists *resources, u8 bridge_bus, u8 bridge_dev);
+static void interrupt_event_handler(struct controller *ctrl);
+
+static struct semaphore event_semaphore;	/* mutex for process loop (up if something to process) */
+static struct semaphore event_exit;		/* guard ensure thread has exited before calling it quits */
+static int event_finished;
+static unsigned long pushbutton_pending;	/* = 0 */
+
+u8 shpchp_disk_irq;
+u8 shpchp_nic_irq;
+
+u8 shpchp_handle_attention_button(u8 hp_slot, void *inst_id)
+{
+	struct controller *ctrl = (struct controller *) inst_id;
+	struct slot *p_slot;
+	u8 rc = 0;
+	u8 getstatus;
+	struct pci_func *func;
+	struct event_info *taskInfo;
+
+	/* Attention Button Change */
+	dbg("shpchp:  Attention button interrupt received.\n");
+	
+	func = shpchp_slot_find(ctrl->slot_bus, (hp_slot + ctrl->slot_device_offset), 0);
+
+	/* This is the structure that tells the worker thread what to do */
+	taskInfo = &(ctrl->event_queue[ctrl->next_event]);
+	p_slot = shpchp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset);
+
+	p_slot->hpc_ops->get_adapter_status(p_slot, &(func->presence_save));
+	p_slot->hpc_ops->get_latch_status(p_slot, &getstatus);
+	
+	ctrl->next_event = (ctrl->next_event + 1) % 10;
+	taskInfo->hp_slot = hp_slot;
+
+	rc++;
+
+	/*
+	 *  Button pressed - See if need to TAKE ACTION!!!
+	 */
+	info("Button pressed on Slot(%d)\n", ctrl->first_slot + hp_slot);
+	taskInfo->event_type = INT_BUTTON_PRESS;
+
+	if ((p_slot->state == BLINKINGON_STATE)
+	    || (p_slot->state == BLINKINGOFF_STATE)) {
+		/* Cancel if we are still blinking; this means that we press the
+		 * attention again before the 5 sec. limit expires to cancel hot-add
+		 * or hot-remove
+		 */
+		taskInfo->event_type = INT_BUTTON_CANCEL;
+		info("Button cancel on Slot(%d)\n", ctrl->first_slot + hp_slot);
+	} else if ((p_slot->state == POWERON_STATE)
+		   || (p_slot->state == POWEROFF_STATE)) {
+		/* Ignore if the slot is on power-on or power-off state; this 
+		 * means that the previous attention button action to hot-add or
+		 * hot-remove is undergoing
+		 */
+		taskInfo->event_type = INT_BUTTON_IGNORE;
+		info("Button ignore on Slot(%d)\n", ctrl->first_slot + hp_slot);
+	}
+
+	if (rc)
+		up(&event_semaphore);	/* signal event thread that new event is posted */
+
+	return 0;
+
+}
+
+u8 shpchp_handle_switch_change(u8 hp_slot, void *inst_id)
+{
+	struct controller *ctrl = (struct controller *) inst_id;
+	struct slot *p_slot;
+	u8 rc = 0;
+	u8 getstatus;
+	struct pci_func *func;
+	struct event_info *taskInfo;
+
+	/* Switch Change */
+	dbg("shpchp:  Switch interrupt received.\n");
+
+	func = shpchp_slot_find(ctrl->slot_bus, (hp_slot + ctrl->slot_device_offset), 0);
+
+	/* This is the structure that tells the worker thread
+	 * what to do
+	 */
+	taskInfo = &(ctrl->event_queue[ctrl->next_event]);
+	ctrl->next_event = (ctrl->next_event + 1) % 10;
+	taskInfo->hp_slot = hp_slot;
+
+	rc++;
+	p_slot = shpchp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset);
+	p_slot->hpc_ops->get_adapter_status(p_slot, &(func->presence_save));
+	p_slot->hpc_ops->get_latch_status(p_slot, &getstatus);
+
+	if (!getstatus) {
+		/*
+		 * Switch opened
+		 */
+		info("Latch open on Slot(%d)\n", ctrl->first_slot + hp_slot);
+		func->switch_save = 0;
+		taskInfo->event_type = INT_SWITCH_OPEN;
+	} else {
+		/*
+		 *  Switch closed
+		 */
+		info("Latch close on Slot(%d)\n", ctrl->first_slot + hp_slot);
+		func->switch_save = 0x10;
+		taskInfo->event_type = INT_SWITCH_CLOSE;
+	}
+
+	if (rc)
+		up(&event_semaphore);	/* signal event thread that new event is posted */
+
+	return rc;
+}
+
+u8 shpchp_handle_presence_change(u8 hp_slot, void *inst_id)
+{
+	struct controller *ctrl = (struct controller *) inst_id;
+	struct slot *p_slot;
+	u8 rc = 0;
+	/*u8 temp_byte;*/
+	struct pci_func *func;
+	struct event_info *taskInfo;
+
+	/* Presence Change */
+	dbg("shpchp:  Presence/Notify input change.\n");
+
+	func = shpchp_slot_find(ctrl->slot_bus, (hp_slot + ctrl->slot_device_offset), 0);
+
+	/* This is the structure that tells the worker thread
+	 * what to do
+	 */
+	taskInfo = &(ctrl->event_queue[ctrl->next_event]);
+	ctrl->next_event = (ctrl->next_event + 1) % 10;
+	taskInfo->hp_slot = hp_slot;
+
+	rc++;
+	p_slot = shpchp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset);
+
+	/* 
+	 * Save the presence state
+	 */
+	p_slot->hpc_ops->get_adapter_status(p_slot, &(func->presence_save));
+	if (func->presence_save) {
+		/*
+		 * Card Present
+		 */
+		taskInfo->event_type = INT_PRESENCE_ON;
+	} else {
+		/*
+		 * Not Present
+		 */
+		taskInfo->event_type = INT_PRESENCE_OFF;
+	}
+
+	if (rc)
+		up(&event_semaphore);	/* signal event thread that new event is posted */
+
+	return rc;
+}
+
+u8 shpchp_handle_power_fault(u8 hp_slot, void *inst_id)
+{
+	struct controller *ctrl = (struct controller *) inst_id;
+	struct slot *p_slot;
+	u8 rc = 0;
+	struct pci_func *func;
+	struct event_info *taskInfo;
+
+	/* Power fault */
+	dbg("shpchp:  Power fault interrupt received.\n");
+
+	func = shpchp_slot_find(ctrl->slot_bus, (hp_slot + ctrl->slot_device_offset), 0);
+
+	/* This is the structure that tells the worker thread
+	 * what to do
+	 */
+	taskInfo = &(ctrl->event_queue[ctrl->next_event]);
+	ctrl->next_event = (ctrl->next_event + 1) % 10;
+	taskInfo->hp_slot = hp_slot;
+
+	rc++;
+	p_slot = shpchp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset);
+
+	if ( !(p_slot->hpc_ops->query_power_fault(p_slot))) {
+		/*
+		 * Power fault Cleared
+		 */
+		info("Power fault cleared on Slot(%d)\n", ctrl->first_slot + hp_slot);
+		func->status = 0x00;
+		taskInfo->event_type = INT_POWER_FAULT_CLEAR;
+	} else {
+		/*
+		 *   Power fault
+		 */
+		info("Power fault on Slot(%d)\n", ctrl->first_slot + hp_slot);
+		taskInfo->event_type = INT_POWER_FAULT;
+		/* set power fault status for this board */
+		func->status = 0xFF;
+		info("power fault bit %x set\n", hp_slot);
+	}
+	if (rc)
+		up(&event_semaphore);	/* signal event thread that new event is posted */
+
+	return rc;
+}
+
+
+/*
+ * sort_by_size
+ *
+ * Sorts nodes on the list by their length.
+ * Smallest first.
+ *
+ */
+static int sort_by_size(struct pci_resource **head)
+{
+	struct pci_resource *current_res;
+	struct pci_resource *next_res;
+	int out_of_order = 1;
+
+	if (!(*head))
+		return(1);
+
+	if (!((*head)->next))
+		return(0);
+
+	while (out_of_order) {
+		out_of_order = 0;
+
+		/* Special case for swapping list head */
+		if (((*head)->next) &&
+		    ((*head)->length > (*head)->next->length)) {
+			out_of_order++;
+			current_res = *head;
+			*head = (*head)->next;
+			current_res->next = (*head)->next;
+			(*head)->next = current_res;
+		}
+
+		current_res = *head;
+
+		while (current_res->next && current_res->next->next) {
+			if (current_res->next->length > current_res->next->next->length) {
+				out_of_order++;
+				next_res = current_res->next;
+				current_res->next = current_res->next->next;
+				current_res = current_res->next;
+				next_res->next = current_res->next;
+				current_res->next = next_res;
+			} else
+				current_res = current_res->next;
+		}
+	}  /* End of out_of_order loop */
+
+	return(0);
+}
+
+
+/*
+ * sort_by_max_size
+ *
+ * Sorts nodes on the list by their length.
+ * Largest first.
+ *
+ */
+static int sort_by_max_size(struct pci_resource **head)
+{
+	struct pci_resource *current_res;
+	struct pci_resource *next_res;
+	int out_of_order = 1;
+
+	if (!(*head))
+		return(1);
+
+	if (!((*head)->next))
+		return(0);
+
+	while (out_of_order) {
+		out_of_order = 0;
+
+		/* Special case for swapping list head */
+		if (((*head)->next) &&
+		    ((*head)->length < (*head)->next->length)) {
+			out_of_order++;
+			current_res = *head;
+			*head = (*head)->next;
+			current_res->next = (*head)->next;
+			(*head)->next = current_res;
+		}
+
+		current_res = *head;
+
+		while (current_res->next && current_res->next->next) {
+			if (current_res->next->length < current_res->next->next->length) {
+				out_of_order++;
+				next_res = current_res->next;
+				current_res->next = current_res->next->next;
+				current_res = current_res->next;
+				next_res->next = current_res->next;
+				current_res->next = next_res;
+			} else
+				current_res = current_res->next;
+		}
+	}  /* End of out_of_order loop */
+
+	return(0);
+}
+
+
+/*
+ * do_pre_bridge_resource_split
+ *
+ *	Returns zero or one node of resources that aren't in use
+ *
+ */
+static struct pci_resource *do_pre_bridge_resource_split (struct pci_resource **head, struct pci_resource **orig_head, u32 alignment)
+{
+	struct pci_resource *prevnode = NULL;
+	struct pci_resource *node;
+	struct pci_resource *split_node;
+	u32 rc;
+	u32 temp_dword;
+	dbg("do_pre_bridge_resource_split\n");
+
+	if (!(*head) || !(*orig_head))
+		return(NULL);
+
+	rc = shpchp_resource_sort_and_combine(head);
+
+	if (rc)
+		return(NULL);
+
+	if ((*head)->base != (*orig_head)->base)
+		return(NULL);
+
+	if ((*head)->length == (*orig_head)->length)
+		return(NULL);
+
+
+	/* If we got here, there the bridge requires some of the resource, but
+	 *  we may be able to split some off of the front
+	 */	
+	node = *head;
+
+	if (node->length & (alignment -1)) {
+		/* This one isn't an aligned length, so we'll make a new entry
+		 * and split it up.
+		 */
+		split_node = (struct pci_resource*) kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
+
+		if (!split_node)
+			return(NULL);
+
+		temp_dword = (node->length | (alignment-1)) + 1 - alignment;
+
+		split_node->base = node->base;
+		split_node->length = temp_dword;
+
+		node->length -= temp_dword;
+		node->base += split_node->length;
+
+		/* Put it in the list */
+		*head = split_node;
+		split_node->next = node;
+	}
+
+	if (node->length < alignment) {
+		return(NULL);
+	}
+
+	/* Now unlink it */
+	if (*head == node) {
+		*head = node->next;
+		node->next = NULL;
+	} else {
+		prevnode = *head;
+		while (prevnode->next != node)
+			prevnode = prevnode->next;
+
+		prevnode->next = node->next;
+		node->next = NULL;
+	}
+
+	return(node);
+}
+
+
+/*
+ * do_bridge_resource_split
+ *
+ *	Returns zero or one node of resources that aren't in use
+ *
+ */
+static struct pci_resource *do_bridge_resource_split (struct pci_resource **head, u32 alignment)
+{
+	struct pci_resource *prevnode = NULL;
+	struct pci_resource *node;
+	u32 rc;
+	u32 temp_dword;
+
+	if (!(*head))
+		return(NULL);
+
+	rc = shpchp_resource_sort_and_combine(head);
+
+	if (rc)
+		return(NULL);
+
+	node = *head;
+
+	while (node->next) {
+		prevnode = node;
+		node = node->next;
+		kfree(prevnode);
+	}
+
+	if (node->length < alignment) {
+		kfree(node);
+		return(NULL);
+	}
+
+	if (node->base & (alignment - 1)) {
+		/* Short circuit if adjusted size is too small */
+		temp_dword = (node->base | (alignment-1)) + 1;
+		if ((node->length - (temp_dword - node->base)) < alignment) {
+			kfree(node);
+			return(NULL);
+		}
+
+		node->length -= (temp_dword - node->base);
+		node->base = temp_dword;
+	}
+
+	if (node->length & (alignment - 1)) {
+		/* There's stuff in use after this node */
+		kfree(node);
+		return(NULL);
+	}
+
+	return(node);
+}
+
+
+/*
+ * get_io_resource
+ *
+ * this function sorts the resource list by size and then
+ * returns the first node of "size" length that is not in the
+ * ISA aliasing window.  If it finds a node larger than "size"
+ * it will split it up.
+ *
+ * size must be a power of two.
+ */
+static struct pci_resource *get_io_resource (struct pci_resource **head, u32 size)
+{
+	struct pci_resource *prevnode;
+	struct pci_resource *node;
+	struct pci_resource *split_node = NULL;
+	u32 temp_dword;
+
+	if (!(*head))
+		return(NULL);
+
+	if ( shpchp_resource_sort_and_combine(head) )
+		return(NULL);
+
+	if ( sort_by_size(head) )
+		return(NULL);
+
+	for (node = *head; node; node = node->next) {
+		if (node->length < size)
+			continue;
+
+		if (node->base & (size - 1)) {
+			/* This one isn't base aligned properly
+			   so we'll make a new entry and split it up */
+			temp_dword = (node->base | (size-1)) + 1;
+
+			/*/ Short circuit if adjusted size is too small */
+			if ((node->length - (temp_dword - node->base)) < size)
+				continue;
+
+			split_node = (struct pci_resource*) kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
+
+			if (!split_node)
+				return(NULL);
+
+			split_node->base = node->base;
+			split_node->length = temp_dword - node->base;
+			node->base = temp_dword;
+			node->length -= split_node->length;
+
+			/* Put it in the list */
+			split_node->next = node->next;
+			node->next = split_node;
+		} /* End of non-aligned base */
+
+		/* Don't need to check if too small since we already did */
+		if (node->length > size) {
+			/* This one is longer than we need
+			   so we'll make a new entry and split it up */
+			split_node = (struct pci_resource*) kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
+
+			if (!split_node)
+				return(NULL);
+
+			split_node->base = node->base + size;
+			split_node->length = node->length - size;
+			node->length = size;
+
+			/* Put it in the list */
+			split_node->next = node->next;
+			node->next = split_node;
+		}  /* End of too big on top end */
+
+		/* For IO make sure it's not in the ISA aliasing space */
+		if (node->base & 0x300L)
+			continue;
+
+		/* If we got here, then it is the right size 
+		   Now take it out of the list */
+		if (*head == node) {
+			*head = node->next;
+		} else {
+			prevnode = *head;
+			while (prevnode->next != node)
+				prevnode = prevnode->next;
+
+			prevnode->next = node->next;
+		}
+		node->next = NULL;
+		/* Stop looping */
+		break;
+	}
+
+	return(node);
+}
+
+
+/*
+ * get_max_resource
+ *
+ * Gets the largest node that is at least "size" big from the
+ * list pointed to by head.  It aligns the node on top and bottom
+ * to "size" alignment before returning it.
+ * J.I. modified to put max size limits of; 64M->32M->16M->8M->4M->1M
+ *  This is needed to avoid allocating entire ACPI _CRS res to one child bridge/slot.
+ */
+static struct pci_resource *get_max_resource (struct pci_resource **head, u32 size)
+{
+	struct pci_resource *max;
+	struct pci_resource *temp;
+	struct pci_resource *split_node;
+	u32 temp_dword;
+	u32 max_size[] = { 0x4000000, 0x2000000, 0x1000000, 0x0800000, 0x0400000, 0x0200000, 0x0100000, 0x00 };
+	int i;
+
+	if (!(*head))
+		return(NULL);
+
+	if (shpchp_resource_sort_and_combine(head))
+		return(NULL);
+
+	if (sort_by_max_size(head))
+		return(NULL);
+
+	for (max = *head;max; max = max->next) {
+
+		/* If not big enough we could probably just bail, 
+		   instead we'll continue to the next. */
+		if (max->length < size)
+			continue;
+
+		if (max->base & (size - 1)) {
+			/* This one isn't base aligned properly
+			   so we'll make a new entry and split it up */
+			temp_dword = (max->base | (size-1)) + 1;
+
+			/* Short circuit if adjusted size is too small */
+			if ((max->length - (temp_dword - max->base)) < size)
+				continue;
+
+			split_node = (struct pci_resource*) kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
+
+			if (!split_node)
+				return(NULL);
+
+			split_node->base = max->base;
+			split_node->length = temp_dword - max->base;
+			max->base = temp_dword;
+			max->length -= split_node->length;
+
+			/* Put it next in the list */
+			split_node->next = max->next;
+			max->next = split_node;
+		}
+
+		if ((max->base + max->length) & (size - 1)) {
+			/* This one isn't end aligned properly at the top
+			   so we'll make a new entry and split it up */
+			split_node = (struct pci_resource*) kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
+
+			if (!split_node)
+				return(NULL);
+			temp_dword = ((max->base + max->length) & ~(size - 1));
+			split_node->base = temp_dword;
+			split_node->length = max->length + max->base
+					     - split_node->base;
+			max->length -= split_node->length;
+
+			/* Put it in the list */
+			split_node->next = max->next;
+			max->next = split_node;
+		}
+
+		/* Make sure it didn't shrink too much when we aligned it */
+		if (max->length < size)
+			continue;
+
+		for ( i = 0; max_size[i] > size; i++) {
+			if (max->length > max_size[i]) {
+				split_node = (struct pci_resource *) kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
+				if (!split_node)
+					break;	/* return (NULL); */
+				split_node->base = max->base + max_size[i];
+				split_node->length = max->length - max_size[i];
+				max->length = max_size[i];
+				/* Put it next in the list */
+				split_node->next = max->next;
+				max->next = split_node;
+				break;
+			}
+		}
+
+		/* Now take it out of the list */
+		temp = (struct pci_resource*) *head;
+		if (temp == max) {
+			*head = max->next;
+		} else {
+			while (temp && temp->next != max) {
+				temp = temp->next;
+			}
+
+			temp->next = max->next;
+		}
+
+		max->next = NULL;
+		return(max);
+	}
+
+	/* If we get here, we couldn't find one */
+	return(NULL);
+}
+
+
+/*
+ * get_resource
+ *
+ * this function sorts the resource list by size and then
+ * returns the first node of "size" length.  If it finds a node
+ * larger than "size" it will split it up.
+ *
+ * size must be a power of two.
+ */
+static struct pci_resource *get_resource (struct pci_resource **head, u32 size)
+{
+	struct pci_resource *prevnode;
+	struct pci_resource *node;
+	struct pci_resource *split_node;
+	u32 temp_dword;
+
+	if (!(*head))
+		return(NULL);
+
+	if ( shpchp_resource_sort_and_combine(head) )
+		return(NULL);
+
+	if ( sort_by_size(head) )
+		return(NULL);
+
+	for (node = *head; node; node = node->next) {
+		dbg("%s: req_size =0x%x node=%p, base=0x%x, length=0x%x\n",
+		    __FUNCTION__, size, node, node->base, node->length);
+		if (node->length < size)
+			continue;
+
+		if (node->base & (size - 1)) {
+			dbg("%s: not aligned\n", __FUNCTION__);
+			/* this one isn't base aligned properly
+			   so we'll make a new entry and split it up */
+			temp_dword = (node->base | (size-1)) + 1;
+
+			/* Short circuit if adjusted size is too small */
+			if ((node->length - (temp_dword - node->base)) < size)
+				continue;
+
+			split_node = (struct pci_resource*) kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
+
+			if (!split_node)
+				return(NULL);
+
+			split_node->base = node->base;
+			split_node->length = temp_dword - node->base;
+			node->base = temp_dword;
+			node->length -= split_node->length;
+
+			/* Put it in the list */
+			split_node->next = node->next;
+			node->next = split_node;
+		} /* End of non-aligned base */
+
+		/* Don't need to check if too small since we already did */
+		if (node->length > size) {
+			dbg("%s: too big\n", __FUNCTION__);
+			/* this one is longer than we need
+			   so we'll make a new entry and split it up */
+			split_node = (struct pci_resource*) kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
+
+			if (!split_node)
+				return(NULL);
+
+			split_node->base = node->base + size;
+			split_node->length = node->length - size;
+			node->length = size;
+
+			/* Put it in the list */
+			split_node->next = node->next;
+			node->next = split_node;
+		}  /* End of too big on top end */
+
+		dbg("%s: got one!!!\n", __FUNCTION__);
+		/* If we got here, then it is the right size
+		   Now take it out of the list */
+		if (*head == node) {
+			*head = node->next;
+		} else {
+			prevnode = *head;
+			while (prevnode->next != node)
+				prevnode = prevnode->next;
+
+			prevnode->next = node->next;
+		}
+		node->next = NULL;
+		/* Stop looping */
+		break;
+	}
+	return(node);
+}
+
+
+/*
+ * shpchp_resource_sort_and_combine
+ *
+ * Sorts all of the nodes in the list in ascending order by
+ * their base addresses.  Also does garbage collection by
+ * combining adjacent nodes.
+ *
+ * returns 0 if success
+ */
+int shpchp_resource_sort_and_combine(struct pci_resource **head)
+{
+	struct pci_resource *node1;
+	struct pci_resource *node2;
+	int out_of_order = 1;
+
+	dbg("%s: head = %p, *head = %p\n", __FUNCTION__, head, *head);
+
+	if (!(*head))
+		return(1);
+
+	dbg("*head->next = %p\n",(*head)->next);
+
+	if (!(*head)->next)
+		return(0);	/* only one item on the list, already sorted! */
+
+	dbg("*head->base = 0x%x\n",(*head)->base);
+	dbg("*head->next->base = 0x%x\n",(*head)->next->base);
+	while (out_of_order) {
+		out_of_order = 0;
+
+		/* Special case for swapping list head */
+		if (((*head)->next) &&
+		    ((*head)->base > (*head)->next->base)) {
+			node1 = *head;
+			(*head) = (*head)->next;
+			node1->next = (*head)->next;
+			(*head)->next = node1;
+			out_of_order++;
+		}
+
+		node1 = (*head);
+
+		while (node1->next && node1->next->next) {
+			if (node1->next->base > node1->next->next->base) {
+				out_of_order++;
+				node2 = node1->next;
+				node1->next = node1->next->next;
+				node1 = node1->next;
+				node2->next = node1->next;
+				node1->next = node2;
+			} else
+				node1 = node1->next;
+		}
+	}  /* End of out_of_order loop */
+
+	node1 = *head;
+
+	while (node1 && node1->next) {
+		if ((node1->base + node1->length) == node1->next->base) {
+			/* Combine */
+			dbg("8..\n");
+			node1->length += node1->next->length;
+			node2 = node1->next;
+			node1->next = node1->next->next;
+			kfree(node2);
+		} else
+			node1 = node1->next;
+	}
+
+	return(0);
+}
+
+
+/**
+ * shpchp_slot_create - Creates a node and adds it to the proper bus.
+ * @busnumber - bus where new node is to be located
+ *
+ * Returns pointer to the new node or NULL if unsuccessful
+ */
+struct pci_func *shpchp_slot_create(u8 busnumber)
+{
+	struct pci_func *new_slot;
+	struct pci_func *next;
+
+	new_slot = (struct pci_func *) kmalloc(sizeof(struct pci_func), GFP_KERNEL);
+
+	if (new_slot == NULL) {
+		return(new_slot);
+	}
+
+	memset(new_slot, 0, sizeof(struct pci_func));
+
+	new_slot->next = NULL;
+	new_slot->configured = 1;
+
+	if (shpchp_slot_list[busnumber] == NULL) {
+		shpchp_slot_list[busnumber] = new_slot;
+	} else {
+		next = shpchp_slot_list[busnumber];
+		while (next->next != NULL)
+			next = next->next;
+		next->next = new_slot;
+	}
+	return(new_slot);
+}
+
+
+/*
+ * slot_remove - Removes a node from the linked list of slots.
+ * @old_slot: slot to remove
+ *
+ * Returns 0 if successful, !0 otherwise.
+ */
+static int slot_remove(struct pci_func * old_slot)
+{
+	struct pci_func *next;
+
+	if (old_slot == NULL)
+		return(1);
+
+	next = shpchp_slot_list[old_slot->bus];
+
+	if (next == NULL) {
+		return(1);
+	}
+
+	if (next == old_slot) {
+		shpchp_slot_list[old_slot->bus] = old_slot->next;
+		shpchp_destroy_board_resources(old_slot);
+		kfree(old_slot);
+		return(0);
+	}
+
+	while ((next->next != old_slot) && (next->next != NULL)) {
+		next = next->next;
+	}
+
+	if (next->next == old_slot) {
+		next->next = old_slot->next;
+		shpchp_destroy_board_resources(old_slot);
+		kfree(old_slot);
+		return(0);
+	} else
+		return(2);
+}
+
+
+/**
+ * bridge_slot_remove - Removes a node from the linked list of slots.
+ * @bridge: bridge to remove
+ *
+ * Returns 0 if successful, !0 otherwise.
+ */
+static int bridge_slot_remove(struct pci_func *bridge)
+{
+	u8 subordinateBus, secondaryBus;
+	u8 tempBus;
+	struct pci_func *next;
+
+	if (bridge == NULL)
+		return(1);
+
+	secondaryBus = (bridge->config_space[0x06] >> 8) & 0xFF;
+	subordinateBus = (bridge->config_space[0x06] >> 16) & 0xFF;
+
+	for (tempBus = secondaryBus; tempBus <= subordinateBus; tempBus++) {
+		next = shpchp_slot_list[tempBus];
+
+		while (!slot_remove(next)) {
+			next = shpchp_slot_list[tempBus];
+		}
+	}
+
+	next = shpchp_slot_list[bridge->bus];
+
+	if (next == NULL) {
+		return(1);
+	}
+
+	if (next == bridge) {
+		shpchp_slot_list[bridge->bus] = bridge->next;
+		kfree(bridge);
+		return(0);
+	}
+
+	while ((next->next != bridge) && (next->next != NULL)) {
+		next = next->next;
+	}
+
+	if (next->next == bridge) {
+		next->next = bridge->next;
+		kfree(bridge);
+		return(0);
+	} else
+		return(2);
+}
+
+
+/**
+ * shpchp_slot_find - Looks for a node by bus, and device, multiple functions accessed
+ * @bus: bus to find
+ * @device: device to find
+ * @index: is 0 for first function found, 1 for the second...
+ *
+ * Returns pointer to the node if successful, %NULL otherwise.
+ */
+struct pci_func *shpchp_slot_find(u8 bus, u8 device, u8 index)
+{
+	int found = -1;
+	struct pci_func *func;
+
+	func = shpchp_slot_list[bus];
+
+	if ((func == NULL) || ((func->device == device) && (index == 0)))
+		return(func);
+
+	if (func->device == device)
+		found++;
+
+	while (func->next != NULL) {
+		func = func->next;
+
+		if (func->device == device)
+			found++;
+
+		if (found == index)
+			return(func);
+	}
+
+	return(NULL);
+}
+
+static int is_bridge(struct pci_func * func)
+{
+	/* Check the header type */
+	if (((func->config_space[0x03] >> 16) & 0xFF) == 0x01)
+		return 1;
+	else
+		return 0;
+}
+
+
+/* The following routines constitute the bulk of the 
+   hotplug controller logic
+ */
+
+
+/**
+ * board_added - Called after a board has been added to the system.
+ *
+ * Turns power on for the board
+ * Configures board
+ *
+ */
+static u32 board_added(struct pci_func * func, struct controller * ctrl)
+{
+	u8 hp_slot, slot;
+	u8 slots_not_empty = 0;
+	int index;
+	u32 temp_register = 0xFFFFFFFF;
+	u32 retval, rc = 0;
+	struct pci_func *new_func = NULL;
+	struct pci_func *t_func = NULL;
+	struct slot *p_slot, *pslot;
+	struct resource_lists res_lists;
+	enum pci_bus_speed adapter_speed, bus_speed, max_bus_speed;
+	u8 pi, mode;
+
+	p_slot = shpchp_find_slot(ctrl, func->device);
+	hp_slot = func->device - ctrl->slot_device_offset;
+
+	dbg("%s: func->device, slot_offset, hp_slot = %d, %d ,%d\n", __FUNCTION__, func->device, ctrl->slot_device_offset, hp_slot);
+
+	/* Wait for exclusive access to hardware */
+	down(&ctrl->crit_sect);
+
+	/* Power on slot without connecting to bus */
+	rc = p_slot->hpc_ops->power_on_slot(p_slot);
+	if (rc) {
+		err("%s: Failed to power on slot\n", __FUNCTION__);
+		/* Done with exclusive hardware access */
+		up(&ctrl->crit_sect);
+		return -1;
+	}
+			
+	/* Wait for the command to complete */
+	wait_for_ctrl_irq (ctrl);
+	
+	rc = p_slot->hpc_ops->check_cmd_status(ctrl);
+	if (rc) {
+		err("%s: Failed to power on slot, error code(%d)\n", __FUNCTION__, rc);
+		/* Done with exclusive hardware access */
+		up(&ctrl->crit_sect);
+		return -1;
+	}
+
+	rc = p_slot->hpc_ops->get_adapter_speed(p_slot, &adapter_speed);
+	/* 0 = PCI 33Mhz, 1 = PCI 66 Mhz, 2 = PCI-X 66 PA, 4 = PCI-X 66 ECC, */
+	/* 5 = PCI-X 133 PA, 7 = PCI-X 133 ECC,  0xa = PCI-X 133 Mhz 266, */
+	/* 0xd = PCI-X 133 Mhz 533 */
+	/* This encoding is different from the one used in cur_bus_speed & */
+	/* max_bus_speed */
+
+	if (rc  || adapter_speed == PCI_SPEED_UNKNOWN) {
+		err("%s: Can't get adapter speed or bus mode mismatch\n", __FUNCTION__);
+		/* Done with exclusive hardware access */
+		up(&ctrl->crit_sect);
+		return WRONG_BUS_FREQUENCY;
+	}
+
+	rc = p_slot->hpc_ops->get_cur_bus_speed(p_slot, &bus_speed);
+	if (rc || bus_speed == PCI_SPEED_UNKNOWN) {
+		err("%s: Can't get bus operation speed\n", __FUNCTION__);
+		/* Done with exclusive hardware access */
+		up(&ctrl->crit_sect);
+		return WRONG_BUS_FREQUENCY;
+	}
+
+	rc = p_slot->hpc_ops->get_max_bus_speed(p_slot, &max_bus_speed);
+	if (rc || max_bus_speed == PCI_SPEED_UNKNOWN) {
+		err("%s: Can't get max bus operation speed\n", __FUNCTION__);
+		max_bus_speed = bus_speed;
+	}
+
+	/* Done with exclusive hardware access */
+	up(&ctrl->crit_sect);
+
+	rc  = p_slot->hpc_ops->get_prog_int(p_slot, &pi);
+	if (rc) {
+		err("%s: Can't get controller programming interface, set it to 1\n", __FUNCTION__);
+		pi = 1;
+	}
+	if (pi == 2) {
+		for ( slot = 0; slot < ctrl->num_slots; slot++) {
+			if (slot != hp_slot) {
+				pslot = shpchp_find_slot(ctrl, slot + ctrl->slot_device_offset);
+				t_func = shpchp_slot_find(pslot->bus, pslot->device, 0);
+				slots_not_empty |= t_func->is_a_board;
+			}
+		}
+
+		switch (adapter_speed) {
+		case PCI_SPEED_133MHz_PCIX_533:	
+		case PCI_SPEED_133MHz_PCIX_266:
+			if ((( bus_speed < 0xa ) || (bus_speed < 0xd)) && (max_bus_speed > bus_speed) &&
+				((max_bus_speed <= 0xa) || (max_bus_speed <= 0xd)) && (!slots_not_empty)) {
+			
+				/* Wait for exclusive access to hardware */
+				down(&ctrl->crit_sect);
+
+				rc = p_slot->hpc_ops->set_bus_speed_mode(p_slot, max_bus_speed);
+				if (rc) {
+					err("%s: Issue of set bus speed mode command failed\n", __FUNCTION__);
+					/* Done with exclusive hardware access */
+					up(&ctrl->crit_sect);				
+					return WRONG_BUS_FREQUENCY;
+				}
+				
+				/* Wait for the command to complete */
+				wait_for_ctrl_irq (ctrl);
+		
+				rc = p_slot->hpc_ops->check_cmd_status(ctrl);
+				if (rc) {
+					err("%s: Can't set bus speed/mode in the case of adapter & bus mismatch\n",
+							  __FUNCTION__);
+					err("%s: Error code (%d)\n", __FUNCTION__, rc);
+					/* Done with exclusive hardware access */
+					up(&ctrl->crit_sect);				
+					return WRONG_BUS_FREQUENCY;
+				}
+				/* Done with exclusive hardware access */
+				up(&ctrl->crit_sect);
+			}
+			break;
+		case PCI_SPEED_133MHz_PCIX_ECC:
+		case PCI_SPEED_133MHz_PCIX:
+
+			rc = p_slot->hpc_ops->get_mode1_ECC_cap(p_slot, &mode);
+
+			if (rc) {
+				err("%s: PI is 1 \n", __FUNCTION__);
+				return WRONG_BUS_FREQUENCY;
+			}
+
+			if (mode) { /* Bus - Mode 1 ECC */
+
+				if (bus_speed > 0x7)  {
+					err("%s: speed of bus %x and adapter %x mismatch\n", __FUNCTION__, bus_speed, adapter_speed);
+					return WRONG_BUS_FREQUENCY;
+				}
+
+				if ((bus_speed < 0x7) && (max_bus_speed <= 0x7) &&
+					(bus_speed < max_bus_speed) && (!slots_not_empty)) {
+
+					/* Wait for exclusive access to hardware */
+					down(&ctrl->crit_sect);
+
+					rc = p_slot->hpc_ops->set_bus_speed_mode(p_slot, max_bus_speed);
+					if (rc) {
+						err("%s: Issue of set bus speed mode command failed\n", __FUNCTION__);
+						/* Done with exclusive hardware access */
+						up(&ctrl->crit_sect);				
+						return WRONG_BUS_FREQUENCY;
+					}
+				
+					/* Wait for the command to complete */
+					wait_for_ctrl_irq (ctrl);
+		
+					rc = p_slot->hpc_ops->check_cmd_status(ctrl);
+					if (rc) {
+						err("%s: Can't set bus speed/mode in the case of adapter & bus mismatch\n",
+							  __FUNCTION__);
+						err("%s: Error code (%d)\n", __FUNCTION__, rc);
+						/* Done with exclusive hardware access */
+						up(&ctrl->crit_sect);				
+						return WRONG_BUS_FREQUENCY;
+					}
+					/* Done with exclusive hardware access */
+					up(&ctrl->crit_sect);
+				}
+			} else {
+				if ((bus_speed > 0x4) || (max_bus_speed > 0x4))  {
+					err("%s: speed of bus %x and adapter %x mismatch\n", __FUNCTION__, bus_speed, adapter_speed);
+					return WRONG_BUS_FREQUENCY;
+				}
+
+				if ((bus_speed < 0x4) && (max_bus_speed <= 0x4) &&
+					(bus_speed < max_bus_speed) && (!slots_not_empty)) {
+
+					/* Wait for exclusive access to hardware */
+					down(&ctrl->crit_sect);
+
+					rc = p_slot->hpc_ops->set_bus_speed_mode(p_slot, max_bus_speed);
+					if (rc) {
+						err("%s: Issue of set bus speed mode command failed\n", __FUNCTION__);
+						/* Done with exclusive hardware access */
+						up(&ctrl->crit_sect);				
+						return WRONG_BUS_FREQUENCY;
+					}
+				
+					/* Wait for the command to complete */
+					wait_for_ctrl_irq (ctrl);
+		
+					rc = p_slot->hpc_ops->check_cmd_status(ctrl);
+					if (rc) {
+						err("%s: Can't set bus speed/mode in the case of adapter & bus mismatch\n",
+							  __FUNCTION__);
+						err("%s: Error code (%d)\n", __FUNCTION__, rc);
+						/* Done with exclusive hardware access */
+						up(&ctrl->crit_sect);				
+						return WRONG_BUS_FREQUENCY;
+					}
+					/* Done with exclusive hardware access */
+					up(&ctrl->crit_sect);
+				}
+			}
+			break;
+		case PCI_SPEED_66MHz_PCIX_ECC:
+		case PCI_SPEED_66MHz_PCIX:
+
+			rc = p_slot->hpc_ops->get_mode1_ECC_cap(p_slot, &mode);
+
+			if (rc) {
+				err("%s: PI is 1 \n", __FUNCTION__);
+				return WRONG_BUS_FREQUENCY;
+			}
+
+			if (mode) { /* Bus - Mode 1 ECC */
+
+				if (bus_speed > 0x5)  {
+					err("%s: speed of bus %x and adapter %x mismatch\n", __FUNCTION__, bus_speed, adapter_speed);
+					return WRONG_BUS_FREQUENCY;
+				}
+
+				if ((bus_speed < 0x5) && (max_bus_speed <= 0x5) &&
+					(bus_speed < max_bus_speed) && (!slots_not_empty)) {
+
+					/* Wait for exclusive access to hardware */
+					down(&ctrl->crit_sect);
+
+					rc = p_slot->hpc_ops->set_bus_speed_mode(p_slot, max_bus_speed);
+					if (rc) {
+						err("%s: Issue of set bus speed mode command failed\n", __FUNCTION__);
+						/* Done with exclusive hardware access */
+						up(&ctrl->crit_sect);				
+						return WRONG_BUS_FREQUENCY;
+					}
+				
+					/* Wait for the command to complete */
+					wait_for_ctrl_irq (ctrl);
+		
+					rc = p_slot->hpc_ops->check_cmd_status(ctrl);
+					if (rc) {
+						err("%s: Can't set bus speed/mode in the case of adapter & bus mismatch\n",
+							  __FUNCTION__);
+						err("%s: Error code (%d)\n", __FUNCTION__, rc);
+						/* Done with exclusive hardware access */
+						up(&ctrl->crit_sect);				
+						return WRONG_BUS_FREQUENCY;
+					}
+					/* Done with exclusive hardware access */
+					up(&ctrl->crit_sect);
+				}
+			} else {
+				if ((bus_speed > 0x2) || (max_bus_speed > 0x2))  {
+					err("%s: speed of bus %x and adapter %x mismatch\n", __FUNCTION__, bus_speed, adapter_speed);
+					return WRONG_BUS_FREQUENCY;
+				}
+
+				if ((bus_speed < 0x2) && (max_bus_speed <= 0x2) &&
+					(bus_speed < max_bus_speed) && (!slots_not_empty)) {
+
+					/* Wait for exclusive access to hardware */
+					down(&ctrl->crit_sect);
+
+					rc = p_slot->hpc_ops->set_bus_speed_mode(p_slot, max_bus_speed);
+					if (rc) {
+						err("%s: Issue of set bus speed mode command failed\n", __FUNCTION__);
+						/* Done with exclusive hardware access */
+						up(&ctrl->crit_sect);				
+						return WRONG_BUS_FREQUENCY;
+					}
+				
+					/* Wait for the command to complete */
+					wait_for_ctrl_irq (ctrl);
+		
+					rc = p_slot->hpc_ops->check_cmd_status(ctrl);
+					if (rc) {
+						err("%s: Can't set bus speed/mode in the case of adapter & bus mismatch\n",
+							  __FUNCTION__);
+						err("%s: Error code (%d)\n", __FUNCTION__, rc);
+						/* Done with exclusive hardware access */
+						up(&ctrl->crit_sect);				
+						return WRONG_BUS_FREQUENCY;
+					}
+					/* Done with exclusive hardware access */
+					up(&ctrl->crit_sect);
+				}
+			}
+			break;
+		case PCI_SPEED_66MHz:
+			if (bus_speed > 0x1) {
+				err("%s: speed of bus %x and adapter %x mismatch\n", __FUNCTION__, bus_speed, adapter_speed);
+				return WRONG_BUS_FREQUENCY;
+			}
+			if (bus_speed == 0x1)
+				;
+			if ((bus_speed == 0x0) && ( max_bus_speed == 0x1))  {
+				/* Wait for exclusive access to hardware */
+				down(&ctrl->crit_sect);
+
+				rc = p_slot->hpc_ops->set_bus_speed_mode(p_slot, max_bus_speed);
+				if (rc) {
+					err("%s: Issue of set bus speed mode command failed\n", __FUNCTION__);
+					/* Done with exclusive hardware access */
+					up(&ctrl->crit_sect);				
+					return WRONG_BUS_FREQUENCY;
+				}
+				
+				/* Wait for the command to complete */
+				wait_for_ctrl_irq (ctrl);
+		
+				rc = p_slot->hpc_ops->check_cmd_status(ctrl);
+				if (rc) {
+					err("%s: Can't set bus speed/mode in the case of adapter & bus mismatch\n",
+							  __FUNCTION__);
+					err("%s: Error code (%d)\n", __FUNCTION__, rc);
+					/* Done with exclusive hardware access */
+					up(&ctrl->crit_sect);				
+					return WRONG_BUS_FREQUENCY;
+				}
+				/* Done with exclusive hardware access */
+				up(&ctrl->crit_sect);
+			}
+			break;	
+		case PCI_SPEED_33MHz:
+			if (bus_speed > 0x0) {
+				err("%s: speed of bus %x and adapter %x mismatch\n", __FUNCTION__, bus_speed, adapter_speed);
+				return WRONG_BUS_FREQUENCY;
+			}
+			break;
+		default:
+			err("%s: speed of bus %x and adapter %x mismatch\n", __FUNCTION__, bus_speed, adapter_speed);
+			return WRONG_BUS_FREQUENCY;
+		}
+	} else {
+		/* if adpater_speed == bus_speed, nothing to do here */
+		if (adapter_speed != bus_speed) {
+			for ( slot = 0; slot < ctrl->num_slots; slot++) {
+				if (slot != hp_slot) {
+					pslot = shpchp_find_slot(ctrl, slot + ctrl->slot_device_offset);
+					t_func = shpchp_slot_find(pslot->bus, pslot->device, 0);
+					slots_not_empty |= t_func->is_a_board;
+				}
+			}
+
+			if (slots_not_empty != 0) { /* Other slots on the same bus are occupied */
+				if ( adapter_speed < bus_speed ) {
+					err("%s: speed of bus %x and adapter %x mismatch\n", __FUNCTION__, bus_speed, adapter_speed);
+					return WRONG_BUS_FREQUENCY;
+				}
+				/* Do nothing if adapter_speed >= bus_speed */
+			}
+		}
+			
+		if ((adapter_speed != bus_speed) && (slots_not_empty == 0))  {
+			/* Other slots on the same bus are empty */
+			
+			rc = p_slot->hpc_ops->get_max_bus_speed(p_slot, &max_bus_speed);
+			if (rc || max_bus_speed == PCI_SPEED_UNKNOWN) {
+				err("%s: Can't get max bus operation speed\n", __FUNCTION__);
+				max_bus_speed = bus_speed;
+			}
+
+			if (max_bus_speed == bus_speed) {
+				/* if adapter_speed >= bus_speed, do nothing */
+				if (adapter_speed < bus_speed) {
+				/* 
+				 * Try to lower bus speed to accommodate the adapter if other slots 
+				 * on the same controller are empty
+				 */
+					
+					/* Wait for exclusive access to hardware */
+					down(&ctrl->crit_sect);
+
+					rc = p_slot->hpc_ops->set_bus_speed_mode(p_slot, adapter_speed);
+					if (rc) {
+						err("%s: Issue of set bus speed mode command failed\n", __FUNCTION__);
+						return WRONG_BUS_FREQUENCY;
+					}
+				
+					/* Wait for the command to complete */
+					wait_for_ctrl_irq (ctrl);
+		
+					rc = p_slot->hpc_ops->check_cmd_status(ctrl);
+					if (rc) {
+						err("%s: Can't set bus speed/mode in the case of adapter & bus mismatch\n",
+								  __FUNCTION__);
+						err("%s: Error code (%d)\n", __FUNCTION__, rc);
+						return WRONG_BUS_FREQUENCY;
+					}
+					/* Done with exclusive hardware access */
+					up(&ctrl->crit_sect);
+
+				} 
+			} else {
+				/* Wait for exclusive access to hardware */
+				down(&ctrl->crit_sect);
+
+				/* max_bus_speed != bus_speed. Note: max_bus_speed should be > than bus_speed */
+				if (adapter_speed < max_bus_speed) 
+					rc = p_slot->hpc_ops->set_bus_speed_mode(p_slot, adapter_speed);
+				else  
+					rc = p_slot->hpc_ops->set_bus_speed_mode(p_slot, max_bus_speed);
+				
+				if (rc) {
+					err("%s: Issue of set bus speed mode command failed\n", __FUNCTION__);
+					/* Done with exclusive hardware access */
+					up(&ctrl->crit_sect);
+					return WRONG_BUS_FREQUENCY;
+				}
+				
+				/* Wait for the command to complete */
+				wait_for_ctrl_irq (ctrl);
+		
+				rc = p_slot->hpc_ops->check_cmd_status(ctrl);
+				if (rc) {
+					err("%s: Can't set bus speed/mode in the case of adapter & bus mismatch\n", 
+						__FUNCTION__);
+					err("%s: Error code (%d)\n", __FUNCTION__, rc);
+					/* Done with exclusive hardware access */
+					up(&ctrl->crit_sect);
+					return WRONG_BUS_FREQUENCY;
+				}
+				/* Done with exclusive hardware access */
+				up(&ctrl->crit_sect);
+
+			}
+		}
+	}
+
+	/* Wait for exclusive access to hardware */
+	down(&ctrl->crit_sect);
+
+	/* turn on board, blink green LED, turn off Amber LED */
+	rc = p_slot->hpc_ops->slot_enable(p_slot);
+	
+	if (rc) {
+		err("%s: Issue of Slot Enable command failed\n", __FUNCTION__);
+		/* Done with exclusive hardware access */
+		up(&ctrl->crit_sect);
+		return rc;
+	}
+	/* Wait for the command to complete */
+	wait_for_ctrl_irq (ctrl);
+
+	rc = p_slot->hpc_ops->check_cmd_status(ctrl);
+	if (rc) {
+		err("%s: Failed to enable slot, error code(%d)\n", __FUNCTION__, rc);
+		/* Done with exclusive hardware access */
+		up(&ctrl->crit_sect);
+		return rc;  
+	}
+
+	/* Done with exclusive hardware access */
+	up(&ctrl->crit_sect);
+
+	/* Wait for ~1 second */
+	dbg("%s: before long_delay\n", __FUNCTION__);
+	wait_for_ctrl_irq (ctrl);
+	dbg("%s: afterlong_delay\n", __FUNCTION__);
+
+	dbg("%s: func status = %x\n", __FUNCTION__, func->status);
+	/* Check for a power fault */
+	if (func->status == 0xFF) {
+		/* power fault occurred, but it was benign */
+		temp_register = 0xFFFFFFFF;
+		dbg("%s: temp register set to %x by power fault\n", __FUNCTION__, temp_register);
+		rc = POWER_FAILURE;
+		func->status = 0;
+	} else {
+		/* Get vendor/device ID u32 */
+		rc = pci_bus_read_config_dword (ctrl->pci_dev->subordinate, PCI_DEVFN(func->device, func->function), 
+			PCI_VENDOR_ID, &temp_register);
+		dbg("%s: pci_bus_read_config_dword returns %d\n", __FUNCTION__, rc);
+		dbg("%s: temp_register is %x\n", __FUNCTION__, temp_register);
+
+		if (rc != 0) {
+			/* Something's wrong here */
+			temp_register = 0xFFFFFFFF;
+			dbg("%s: temp register set to %x by error\n", __FUNCTION__, temp_register);
+		}
+		/* Preset return code.  It will be changed later if things go okay. */
+		rc = NO_ADAPTER_PRESENT;
+	}
+
+	/* All F's is an empty slot or an invalid board */
+	if (temp_register != 0xFFFFFFFF) {	  /* Check for a board in the slot */
+		res_lists.io_head = ctrl->io_head;
+		res_lists.mem_head = ctrl->mem_head;
+		res_lists.p_mem_head = ctrl->p_mem_head;
+		res_lists.bus_head = ctrl->bus_head;
+		res_lists.irqs = NULL;
+
+		rc = configure_new_device(ctrl, func, 0, &res_lists, 0, 0);
+		dbg("%s: back from configure_new_device\n", __FUNCTION__);
+
+		ctrl->io_head = res_lists.io_head;
+		ctrl->mem_head = res_lists.mem_head;
+		ctrl->p_mem_head = res_lists.p_mem_head;
+		ctrl->bus_head = res_lists.bus_head;
+
+		shpchp_resource_sort_and_combine(&(ctrl->mem_head));
+		shpchp_resource_sort_and_combine(&(ctrl->p_mem_head));
+		shpchp_resource_sort_and_combine(&(ctrl->io_head));
+		shpchp_resource_sort_and_combine(&(ctrl->bus_head));
+
+		if (rc) {
+			/* Wait for exclusive access to hardware */
+			down(&ctrl->crit_sect);
+
+			/* turn off slot, turn on Amber LED, turn off Green LED */
+			retval = p_slot->hpc_ops->slot_disable(p_slot);
+			if (retval) {
+				err("%s: Issue of Slot Enable command failed\n", __FUNCTION__);
+				/* Done with exclusive hardware access */
+				up(&ctrl->crit_sect);
+				return retval;
+			}
+			/* Wait for the command to complete */
+			wait_for_ctrl_irq (ctrl);
+
+			retval = p_slot->hpc_ops->check_cmd_status(ctrl);
+			if (retval) {
+				err("%s: Failed to disable slot, error code(%d)\n", __FUNCTION__, rc);
+				/* Done with exclusive hardware access */
+				up(&ctrl->crit_sect);
+				return retval;  
+			}
+
+			/* Done with exclusive hardware access */
+			up(&ctrl->crit_sect);
+
+			return(rc);
+		}
+		shpchp_save_slot_config(ctrl, func);
+
+		func->status = 0;
+		func->switch_save = 0x10;
+		func->is_a_board = 0x01;
+
+		/* next, we will instantiate the linux pci_dev structures 
+		 * (with appropriate driver notification, if already present) 
+		 */
+		index = 0;
+		do {
+			new_func = shpchp_slot_find(ctrl->slot_bus, func->device, index++);
+			if (new_func && !new_func->pci_dev) {
+				dbg("%s:call pci_hp_configure_dev\n", __FUNCTION__);
+				shpchp_configure_device(ctrl, new_func);
+			}
+		} while (new_func);
+
+		/* Wait for exclusive access to hardware */
+		down(&ctrl->crit_sect);
+
+		p_slot->hpc_ops->green_led_on(p_slot);
+
+		/* Wait for the command to complete */
+		wait_for_ctrl_irq (ctrl);
+
+
+		/* Done with exclusive hardware access */
+		up(&ctrl->crit_sect);
+
+	} else {
+		/* Wait for exclusive access to hardware */
+		down(&ctrl->crit_sect);
+
+		/* turn off slot, turn on Amber LED, turn off Green LED */
+		rc = p_slot->hpc_ops->slot_disable(p_slot);
+		if (rc) {
+			err("%s: Issue of Slot Disable command failed\n", __FUNCTION__);
+			/* Done with exclusive hardware access */
+			up(&ctrl->crit_sect);
+			return rc;
+		}
+		/* Wait for the command to complete */
+		wait_for_ctrl_irq (ctrl);
+
+		rc = p_slot->hpc_ops->check_cmd_status(ctrl);
+		if (rc) {
+			err("%s: Failed to disable slot, error code(%d)\n", __FUNCTION__, rc);
+			/* Done with exclusive hardware access */
+			up(&ctrl->crit_sect);
+			return rc;  
+		}
+
+		/* Done with exclusive hardware access */
+		up(&ctrl->crit_sect);
+
+		return(rc);
+	}
+	return 0;
+}
+
+
+/**
+ * remove_board - Turns off slot and LED's
+ *
+ */
+static u32 remove_board(struct pci_func *func, struct controller *ctrl)
+{
+	int index;
+	u8 skip = 0;
+	u8 device;
+	u8 hp_slot;
+	u32 rc;
+	struct resource_lists res_lists;
+	struct pci_func *temp_func;
+	struct slot *p_slot;
+
+	if (func == NULL)
+		return(1);
+
+	if (shpchp_unconfigure_device(func))
+		return(1);
+
+	device = func->device;
+
+	hp_slot = func->device - ctrl->slot_device_offset;
+	p_slot = shpchp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset);
+
+	dbg("In %s, hp_slot = %d\n", __FUNCTION__, hp_slot);
+
+	if ((ctrl->add_support) &&
+		!(func->bus_head || func->mem_head || func->p_mem_head || func->io_head)) {
+		/* Here we check to see if we've saved any of the board's
+		 * resources already.  If so, we'll skip the attempt to
+		 * determine what's being used.
+		 */
+		index = 0;
+
+		temp_func = func;
+
+		while ((temp_func = shpchp_slot_find(temp_func->bus, temp_func->device, index++))) {
+			if (temp_func->bus_head || temp_func->mem_head
+			    || temp_func->p_mem_head || temp_func->io_head) {
+				skip = 1;
+				break;
+			}
+		}
+
+		if (!skip)
+			rc = shpchp_save_used_resources(ctrl, func, DISABLE_CARD);
+	}
+	/* Change status to shutdown */
+	if (func->is_a_board)
+		func->status = 0x01;
+	func->configured = 0;
+
+	/* Wait for exclusive access to hardware */
+	down(&ctrl->crit_sect);
+
+	/* turn off slot, turn on Amber LED, turn off Green LED */
+	rc = p_slot->hpc_ops->slot_disable(p_slot);
+	if (rc) {
+		err("%s: Issue of Slot Disable command failed\n", __FUNCTION__);
+		/* Done with exclusive hardware access */
+		up(&ctrl->crit_sect);
+		return rc;
+	}
+	/* Wait for the command to complete */
+	wait_for_ctrl_irq (ctrl);
+
+	rc = p_slot->hpc_ops->check_cmd_status(ctrl);
+	if (rc) {
+		err("%s: Failed to disable slot, error code(%d)\n", __FUNCTION__, rc);
+		/* Done with exclusive hardware access */
+		up(&ctrl->crit_sect);
+		return rc;  
+	}
+	
+	rc = p_slot->hpc_ops->set_attention_status(p_slot, 0);
+	if (rc) {
+		err("%s: Issue of Set Attention command failed\n", __FUNCTION__);
+		/* Done with exclusive hardware access */
+		up(&ctrl->crit_sect);
+		return rc;
+	}
+	/* Wait for the command to complete */
+	wait_for_ctrl_irq (ctrl);
+
+	/* Done with exclusive hardware access */
+	up(&ctrl->crit_sect);
+
+	if (ctrl->add_support) {
+		while (func) {
+			res_lists.io_head = ctrl->io_head;
+			res_lists.mem_head = ctrl->mem_head;
+			res_lists.p_mem_head = ctrl->p_mem_head;
+			res_lists.bus_head = ctrl->bus_head;
+
+			dbg("Returning resources to ctlr lists for (B/D/F) = (%#x/%#x/%#x)\n", func->bus, 
+				func->device, func->function);
+
+			shpchp_return_board_resources(func, &res_lists);
+
+			ctrl->io_head = res_lists.io_head;
+			ctrl->mem_head = res_lists.mem_head;
+			ctrl->p_mem_head = res_lists.p_mem_head;
+			ctrl->bus_head = res_lists.bus_head;
+
+			shpchp_resource_sort_and_combine(&(ctrl->mem_head));
+			shpchp_resource_sort_and_combine(&(ctrl->p_mem_head));
+			shpchp_resource_sort_and_combine(&(ctrl->io_head));
+			shpchp_resource_sort_and_combine(&(ctrl->bus_head));
+
+			if (is_bridge(func)) {
+				dbg("PCI Bridge Hot-Remove s:b:d:f(%02x:%02x:%02x:%02x)\n", ctrl->seg, func->bus, 
+					func->device, func->function);
+				bridge_slot_remove(func);
+			} else
+				dbg("PCI Function Hot-Remove s:b:d:f(%02x:%02x:%02x:%02x)\n", ctrl->seg, func->bus, 
+					func->device, func->function);
+				slot_remove(func);
+
+			func = shpchp_slot_find(ctrl->slot_bus, device, 0);
+		}
+
+		/* Setup slot structure with entry for empty slot */
+		func = shpchp_slot_create(ctrl->slot_bus);
+
+		if (func == NULL) {
+			return(1);
+		}
+
+		func->bus = ctrl->slot_bus;
+		func->device = device;
+		func->function = 0;
+		func->configured = 0;
+		func->switch_save = 0x10;
+		func->is_a_board = 0;
+	}
+
+	return 0;
+}
+
+
+static void pushbutton_helper_thread (unsigned long data)
+{
+	pushbutton_pending = data;
+
+	up(&event_semaphore);
+}
+
+
+/* this is the main worker thread */
+static int event_thread(void* data)
+{
+	struct controller *ctrl;
+	lock_kernel();
+	daemonize("shpchpd_event");
+	unlock_kernel();
+
+	while (1) {
+		dbg("!!!!event_thread sleeping\n");
+		down_interruptible (&event_semaphore);
+		dbg("event_thread woken finished = %d\n", event_finished);
+		if (event_finished || signal_pending(current))
+			break;
+		/* Do stuff here */
+		if (pushbutton_pending)
+			shpchp_pushbutton_thread(pushbutton_pending);
+		else
+			for (ctrl = shpchp_ctrl_list; ctrl; ctrl=ctrl->next)
+				interrupt_event_handler(ctrl);
+	}
+	dbg("event_thread signals exit\n");
+	up(&event_exit);
+	return 0;
+}
+
+int shpchp_event_start_thread (void)
+{
+	int pid;
+
+	/* initialize our semaphores */
+	init_MUTEX_LOCKED(&event_exit);
+	event_finished=0;
+
+	init_MUTEX_LOCKED(&event_semaphore);
+	pid = kernel_thread(event_thread, 0, 0);
+
+	if (pid < 0) {
+		err ("Can't start up our event thread\n");
+		return -1;
+	}
+	dbg("Our event thread pid = %d\n", pid);
+	return 0;
+}
+
+
+void shpchp_event_stop_thread (void)
+{
+	event_finished = 1;
+	dbg("event_thread finish command given\n");
+	up(&event_semaphore);
+	dbg("wait for event_thread to exit\n");
+	down(&event_exit);
+}
+
+
+static int update_slot_info (struct slot *slot)
+{
+	struct hotplug_slot_info *info;
+	int result;
+
+	info = kmalloc (sizeof (struct hotplug_slot_info), GFP_KERNEL);
+	if (!info)
+		return -ENOMEM;
+
+	slot->hpc_ops->get_power_status(slot, &(info->power_status));
+	slot->hpc_ops->get_attention_status(slot, &(info->attention_status));
+	slot->hpc_ops->get_latch_status(slot, &(info->latch_status));
+	slot->hpc_ops->get_adapter_status(slot, &(info->adapter_status));
+
+	result = pci_hp_change_slot_info(slot->hotplug_slot, info);
+	kfree (info);
+	return result;
+}
+
+static void interrupt_event_handler(struct controller *ctrl)
+{
+	int loop = 0;
+	int change = 1;
+	struct pci_func *func;
+	u8 hp_slot;
+	u8 getstatus;
+	struct slot *p_slot;
+
+	dbg("%s:\n", __FUNCTION__);
+	while (change) {
+		change = 0;
+
+		for (loop = 0; loop < 10; loop++) {
+			if (ctrl->event_queue[loop].event_type != 0) {
+				dbg("%s:loop %x event_type %x\n", __FUNCTION__, loop, 
+					ctrl->event_queue[loop].event_type);
+				hp_slot = ctrl->event_queue[loop].hp_slot;
+
+				func = shpchp_slot_find(ctrl->slot_bus, (hp_slot + ctrl->slot_device_offset), 0);
+
+				p_slot = shpchp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset);
+
+				dbg("%s: hp_slot %d, func %p, p_slot %p\n", __FUNCTION__, hp_slot, func, p_slot);
+
+				if (ctrl->event_queue[loop].event_type == INT_BUTTON_CANCEL) {
+					dbg("%s: button cancel\n", __FUNCTION__);
+					del_timer(&p_slot->task_event);
+
+					switch (p_slot->state) {
+					case BLINKINGOFF_STATE:
+						/* Wait for exclusive access to hardware */
+						down(&ctrl->crit_sect);
+
+						p_slot->hpc_ops->green_led_on(p_slot);
+						/* Wait for the command to complete */
+						wait_for_ctrl_irq (ctrl);
+
+						p_slot->hpc_ops->set_attention_status(p_slot, 0);
+
+						/* Wait for the command to complete */
+						wait_for_ctrl_irq (ctrl);
+
+						/* Done with exclusive hardware access */
+						up(&ctrl->crit_sect);
+						break;
+					case BLINKINGON_STATE:
+						/* Wait for exclusive access to hardware */
+						down(&ctrl->crit_sect);
+
+						p_slot->hpc_ops->green_led_off(p_slot);
+						/* Wait for the command to complete */
+						wait_for_ctrl_irq (ctrl);
+
+						p_slot->hpc_ops->set_attention_status(p_slot, 0);
+						/* Wait for the command to complete */
+						wait_for_ctrl_irq (ctrl);
+
+						/* Done with exclusive hardware access */
+						up(&ctrl->crit_sect);
+
+						break;
+					default:
+						warn("Not a valid state\n");
+						return;
+					}
+					info(msg_button_cancel, p_slot->number);
+					p_slot->state = STATIC_STATE;
+				} else if (ctrl->event_queue[loop].event_type == INT_BUTTON_PRESS) {
+					/* Button Pressed (No action on 1st press...) */
+					dbg("%s: Button pressed\n", __FUNCTION__);
+
+					p_slot->hpc_ops->get_power_status(p_slot, &getstatus);
+					if (getstatus) {
+						/* slot is on */
+						dbg("%s: slot is on\n", __FUNCTION__);
+						p_slot->state = BLINKINGOFF_STATE;
+						info(msg_button_off, p_slot->number);
+					} else {
+						/* slot is off */
+						dbg("%s: slot is off\n", __FUNCTION__);
+						p_slot->state = BLINKINGON_STATE;
+						info(msg_button_on, p_slot->number);
+					}
+
+					/* Wait for exclusive access to hardware */
+					down(&ctrl->crit_sect);
+
+					/* blink green LED and turn off amber */
+					p_slot->hpc_ops->green_led_blink(p_slot);
+					/* Wait for the command to complete */
+					wait_for_ctrl_irq (ctrl);
+					
+					p_slot->hpc_ops->set_attention_status(p_slot, 0);
+
+					/* Wait for the command to complete */
+					wait_for_ctrl_irq (ctrl);
+
+					/* Done with exclusive hardware access */
+					up(&ctrl->crit_sect);
+
+					init_timer(&p_slot->task_event);
+					p_slot->task_event.expires = jiffies + 5 * HZ;   /* 5 second delay */
+					p_slot->task_event.function = (void (*)(unsigned long)) pushbutton_helper_thread;
+					p_slot->task_event.data = (unsigned long) p_slot;
+
+					dbg("%s: add_timer p_slot = %p\n", __FUNCTION__,(void *) p_slot);
+					add_timer(&p_slot->task_event);
+				} else if (ctrl->event_queue[loop].event_type == INT_POWER_FAULT) {
+					/***********POWER FAULT********************/
+					dbg("%s: power fault\n", __FUNCTION__);
+					/* Wait for exclusive access to hardware */
+					down(&ctrl->crit_sect);
+
+					p_slot->hpc_ops->set_attention_status(p_slot, 1);
+					/* Wait for the command to complete */
+					wait_for_ctrl_irq (ctrl);
+					
+					p_slot->hpc_ops->green_led_off(p_slot);
+					/* Wait for the command to complete */
+					wait_for_ctrl_irq (ctrl);
+
+					/* Done with exclusive hardware access */
+					up(&ctrl->crit_sect);
+				} else {
+					/* refresh notification */
+					if (p_slot)
+						update_slot_info(p_slot);
+				}
+
+				ctrl->event_queue[loop].event_type = 0;
+
+				change = 1;
+			}
+		}		/* End of FOR loop */
+	}
+
+	return;
+}
+
+
+/**
+ * shpchp_pushbutton_thread
+ *
+ * Scheduled procedure to handle blocking stuff for the pushbuttons
+ * Handles all pending events and exits.
+ *
+ */
+void shpchp_pushbutton_thread (unsigned long slot)
+{
+	struct slot *p_slot = (struct slot *) slot;
+	u8 getstatus;
+	int rc;
+	
+	pushbutton_pending = 0;
+
+	if (!p_slot) {
+		dbg("%s: Error! slot NULL\n", __FUNCTION__);
+		return;
+	}
+
+	p_slot->hpc_ops->get_power_status(p_slot, &getstatus);
+	if (getstatus) {
+		p_slot->state = POWEROFF_STATE;
+		dbg("In power_down_board, b:d(%x:%x)\n", p_slot->bus, p_slot->device);
+
+		if (shpchp_disable_slot(p_slot)) {
+			/* Wait for exclusive access to hardware */
+			down(&p_slot->ctrl->crit_sect);
+
+			/* Turn on the Attention LED */
+			rc = p_slot->hpc_ops->set_attention_status(p_slot, 1);
+			if (rc) {
+				err("%s: Issue of Set Atten Indicator On command failed\n", __FUNCTION__);
+				return;
+			}
+	
+			/* Wait for the command to complete */
+			wait_for_ctrl_irq (p_slot->ctrl);
+
+			/* Done with exclusive hardware access */
+			up(&p_slot->ctrl->crit_sect);
+		}
+		p_slot->state = STATIC_STATE;
+	} else {
+		p_slot->state = POWERON_STATE;
+		dbg("In add_board, b:d(%x:%x)\n", p_slot->bus, p_slot->device);
+
+		if (shpchp_enable_slot(p_slot)) {
+			/* Wait for exclusive access to hardware */
+			down(&p_slot->ctrl->crit_sect);
+
+			/* Turn off the green LED */
+			rc = p_slot->hpc_ops->set_attention_status(p_slot, 1);
+			if (rc) {
+				err("%s: Issue of Set Atten Indicator On command failed\n", __FUNCTION__);
+				return;
+			}
+			/* Wait for the command to complete */
+			wait_for_ctrl_irq (p_slot->ctrl);
+			
+			p_slot->hpc_ops->green_led_off(p_slot);
+
+			/* Wait for the command to complete */
+			wait_for_ctrl_irq (p_slot->ctrl);
+
+			/* Done with exclusive hardware access */
+			up(&p_slot->ctrl->crit_sect);
+		}
+		p_slot->state = STATIC_STATE;
+	}
+
+	return;
+}
+
+
+int shpchp_enable_slot (struct slot *p_slot)
+{
+	u8 getstatus = 0;
+	int rc;
+	struct pci_func *func;
+
+	func = shpchp_slot_find(p_slot->bus, p_slot->device, 0);
+	if (!func) {
+		dbg("%s: Error! slot NULL\n", __FUNCTION__);
+		return (1);
+	}
+
+	/* Check to see if (latch closed, card present, power off) */
+	down(&p_slot->ctrl->crit_sect);
+	rc = p_slot->hpc_ops->get_adapter_status(p_slot, &getstatus);
+	if (rc || !getstatus) {
+		info("%s: no adapter on slot(%x)\n", __FUNCTION__, p_slot->number);
+		up(&p_slot->ctrl->crit_sect);
+		return (0);
+	}
+	rc = p_slot->hpc_ops->get_latch_status(p_slot, &getstatus);
+	if (rc || !getstatus) {
+		info("%s: latch open on slot(%x)\n", __FUNCTION__, p_slot->number);
+		up(&p_slot->ctrl->crit_sect);
+		return (0);
+	}
+	rc = p_slot->hpc_ops->get_power_status(p_slot, &getstatus);
+	if (rc || getstatus) {
+		info("%s: already enabled on slot(%x)\n", __FUNCTION__, p_slot->number);
+		up(&p_slot->ctrl->crit_sect);
+		return (0);
+	}
+	up(&p_slot->ctrl->crit_sect);
+
+	slot_remove(func);
+
+	func = shpchp_slot_create(p_slot->bus);
+	if (func == NULL)
+		return (1);
+
+	func->bus = p_slot->bus;
+	func->device = p_slot->device;
+	func->function = 0;
+	func->configured = 0;
+	func->is_a_board = 1;
+
+	/* We have to save the presence info for these slots */
+	p_slot->hpc_ops->get_adapter_status(p_slot, &(func->presence_save));
+	p_slot->hpc_ops->get_latch_status(p_slot, &getstatus);
+	func->switch_save = !getstatus? 0x10:0;
+
+	rc = board_added(func, p_slot->ctrl);
+	if (rc) {
+		if (is_bridge(func))
+			bridge_slot_remove(func);
+		else
+			slot_remove(func);
+
+		/* Setup slot structure with entry for empty slot */
+		func = shpchp_slot_create(p_slot->bus);
+		if (func == NULL)
+			return (1);	/* Out of memory */
+
+		func->bus = p_slot->bus;
+		func->device = p_slot->device;
+		func->function = 0;
+		func->configured = 0;
+		func->is_a_board = 1;
+
+		/* We have to save the presence info for these slots */
+		p_slot->hpc_ops->get_adapter_status(p_slot, &(func->presence_save));
+		p_slot->hpc_ops->get_latch_status(p_slot, &getstatus);
+		func->switch_save = !getstatus? 0x10:0;
+	}
+
+	if (p_slot)
+		update_slot_info(p_slot);
+
+	return rc;
+}
+
+
+int shpchp_disable_slot (struct slot *p_slot)
+{
+	u8 class_code, header_type, BCR;
+	u8 index = 0;
+	u8 getstatus = 0;
+	u32 rc = 0;
+	int ret = 0;
+	unsigned int devfn;
+	struct pci_bus *pci_bus = p_slot->ctrl->pci_dev->subordinate;
+	struct pci_func *func;
+
+	if (!p_slot->ctrl)
+		return (1);
+
+	/* Check to see if (latch closed, card present, power on) */
+	down(&p_slot->ctrl->crit_sect);
+
+	ret = p_slot->hpc_ops->get_adapter_status(p_slot, &getstatus);
+	if (ret || !getstatus) {
+		info("%s: no adapter on slot(%x)\n", __FUNCTION__, p_slot->number);
+		up(&p_slot->ctrl->crit_sect);
+		return (0);
+	}
+	ret = p_slot->hpc_ops->get_latch_status(p_slot, &getstatus);
+	if (ret || !getstatus) {
+		info("%s: latch open on slot(%x)\n", __FUNCTION__, p_slot->number);
+		up(&p_slot->ctrl->crit_sect);
+		return (0);
+	}
+	ret = p_slot->hpc_ops->get_power_status(p_slot, &getstatus);
+	if (ret || !getstatus) {
+		info("%s: already disabled slot(%x)\n", __FUNCTION__, p_slot->number);
+		up(&p_slot->ctrl->crit_sect);
+		return (0);
+	}
+	up(&p_slot->ctrl->crit_sect);
+
+	func = shpchp_slot_find(p_slot->bus, p_slot->device, index++);
+
+	/* Make sure there are no video controllers here
+	 * for all func of p_slot
+	 */
+	while (func && !rc) {
+		pci_bus->number = func->bus;
+		devfn = PCI_DEVFN(func->device, func->function);
+
+		/* Check the Class Code */
+		rc = pci_bus_read_config_byte (pci_bus, devfn, 0x0B, &class_code);
+		if (rc)
+			return rc;
+
+		if (class_code == PCI_BASE_CLASS_DISPLAY) {
+			/* Display/Video adapter (not supported) */
+			rc = REMOVE_NOT_SUPPORTED;
+		} else {
+			/* See if it's a bridge */
+			rc = pci_bus_read_config_byte (pci_bus, devfn, PCI_HEADER_TYPE, &header_type);
+			if (rc)
+				return rc;
+
+			/* If it's a bridge, check the VGA Enable bit */
+			if ((header_type & 0x7F) == PCI_HEADER_TYPE_BRIDGE) {
+				rc = pci_bus_read_config_byte (pci_bus, devfn, PCI_BRIDGE_CONTROL, &BCR);
+				if (rc)
+					return rc;
+
+				/* If the VGA Enable bit is set, remove isn't supported */
+				if (BCR & PCI_BRIDGE_CTL_VGA) {
+					rc = REMOVE_NOT_SUPPORTED;
+				}
+			}
+		}
+
+		func = shpchp_slot_find(p_slot->bus, p_slot->device, index++);
+	}
+
+	func = shpchp_slot_find(p_slot->bus, p_slot->device, 0);
+	if ((func != NULL) && !rc) {
+		rc = remove_board(func, p_slot->ctrl);
+	} else if (!rc)
+		rc = 1;
+
+	if (p_slot)
+		update_slot_info(p_slot);
+
+	return(rc);
+}
+
+
+/**
+ * configure_new_device - Configures the PCI header information of one board.
+ *
+ * @ctrl: pointer to controller structure
+ * @func: pointer to function structure
+ * @behind_bridge: 1 if this is a recursive call, 0 if not
+ * @resources: pointer to set of resource lists
+ *
+ * Returns 0 if success
+ *
+ */
+static u32 configure_new_device (struct controller * ctrl, struct pci_func * func,
+	u8 behind_bridge, struct resource_lists * resources, u8 bridge_bus, u8 bridge_dev)
+{
+	u8 temp_byte, function, max_functions, stop_it;
+	int rc;
+	u32 ID;
+	struct pci_func *new_slot;
+	struct pci_bus lpci_bus, *pci_bus;
+	int index;
+
+	new_slot = func;
+
+	dbg("%s\n", __FUNCTION__);
+	memcpy(&lpci_bus, ctrl->pci_dev->subordinate, sizeof(lpci_bus));
+	pci_bus = &lpci_bus;
+	pci_bus->number = func->bus;
+
+	/* Check for Multi-function device */
+	rc = pci_bus_read_config_byte(pci_bus, PCI_DEVFN(func->device, func->function), 0x0E, &temp_byte);
+	if (rc) {
+		dbg("%s: rc = %d\n", __FUNCTION__, rc);
+		return rc;
+	}
+
+	if (temp_byte & 0x80)	/* Multi-function device */
+		max_functions = 8;
+	else
+		max_functions = 1;
+
+	function = 0;
+
+	do {
+		rc = configure_new_function(ctrl, new_slot, behind_bridge, resources, bridge_bus, bridge_dev);
+
+		if (rc) {
+			dbg("configure_new_function failed %d\n",rc);
+			index = 0;
+
+			while (new_slot) {
+				new_slot = shpchp_slot_find(new_slot->bus, new_slot->device, index++);
+
+				if (new_slot)
+					shpchp_return_board_resources(new_slot, resources);
+			}
+
+			return(rc);
+		}
+
+		function++;
+
+		stop_it = 0;
+
+		/*  The following loop skips to the next present function
+		 *  and creates a board structure
+		 */
+
+		while ((function < max_functions) && (!stop_it)) {
+			pci_bus_read_config_dword(pci_bus, PCI_DEVFN(func->device, function), 0x00, &ID);
+
+			if (ID == 0xFFFFFFFF) {	  /* There's nothing there. */
+				function++;
+			} else {  /* There's something there */
+				/* Setup slot structure. */
+				new_slot = shpchp_slot_create(func->bus);
+
+				if (new_slot == NULL) {
+					/* Out of memory */
+					return(1);
+				}
+
+				new_slot->bus = func->bus;
+				new_slot->device = func->device;
+				new_slot->function = function;
+				new_slot->is_a_board = 1;
+				new_slot->status = 0;
+
+				stop_it++;
+			}
+		}
+
+	} while (function < max_functions);
+	dbg("returning from configure_new_device\n");
+
+	return 0;
+}
+
+
+/*
+ * Configuration logic that involves the hotplug data structures and 
+ * their bookkeeping
+ */
+
+
+/**
+ * configure_new_function - Configures the PCI header information of one device
+ *
+ * @ctrl: pointer to controller structure
+ * @func: pointer to function structure
+ * @behind_bridge: 1 if this is a recursive call, 0 if not
+ * @resources: pointer to set of resource lists
+ *
+ * Calls itself recursively for bridged devices.
+ * Returns 0 if success
+ *
+ */
+static int configure_new_function (struct controller * ctrl, struct pci_func * func,
+	u8 behind_bridge, struct resource_lists *resources, u8 bridge_bus, u8 bridge_dev)
+{
+	int cloop;
+	u8 temp_byte;
+	u8 device;
+	u8 class_code;
+	u16 temp_word;
+	u32 rc;
+	u32 temp_register;
+	u32 base;
+	u32 ID;
+	unsigned int devfn;
+	struct pci_resource *mem_node;
+	struct pci_resource *p_mem_node;
+	struct pci_resource *io_node;
+	struct pci_resource *bus_node;
+	struct pci_resource *hold_mem_node;
+	struct pci_resource *hold_p_mem_node;
+	struct pci_resource *hold_IO_node;
+	struct pci_resource *hold_bus_node;
+	struct irq_mapping irqs;
+	struct pci_func *new_slot;
+	struct pci_bus lpci_bus, *pci_bus;
+	struct resource_lists temp_resources;
+#if defined(CONFIG_X86_64)
+	u8 IRQ=0;
+#endif
+
+	memcpy(&lpci_bus, ctrl->pci_dev->subordinate, sizeof(lpci_bus));
+	pci_bus = &lpci_bus;
+	pci_bus->number = func->bus;
+	devfn = PCI_DEVFN(func->device, func->function);
+
+	/* Check for Bridge */
+	rc = pci_bus_read_config_byte (pci_bus, devfn, PCI_HEADER_TYPE, &temp_byte);
+	if (rc)
+		return rc;
+
+	if ((temp_byte & 0x7F) == PCI_HEADER_TYPE_BRIDGE) { /* PCI-PCI Bridge */
+		/* set Primary bus */
+		dbg("set Primary bus = 0x%x\n", func->bus);
+		rc = pci_bus_write_config_byte(pci_bus, devfn, PCI_PRIMARY_BUS, func->bus);
+		if (rc)
+			return rc;
+
+		/* find range of busses to use */
+		bus_node = get_max_resource(&resources->bus_head, 1L);
+
+		/* If we don't have any busses to allocate, we can't continue */
+		if (!bus_node) {
+			err("Got NO bus resource to use\n");
+			return -ENOMEM;
+		}
+		dbg("Got ranges of buses to use: base:len=0x%x:%x\n", bus_node->base, bus_node->length);
+
+		/* set Secondary bus */
+		temp_byte = (u8)bus_node->base;
+		dbg("set Secondary bus = 0x%x\n", temp_byte);
+		rc = pci_bus_write_config_byte(pci_bus, devfn, PCI_SECONDARY_BUS, temp_byte);
+		if (rc)
+			return rc;
+
+		/* set subordinate bus */
+		temp_byte = (u8)(bus_node->base + bus_node->length - 1);
+		dbg("set subordinate bus = 0x%x\n", temp_byte);
+		rc = pci_bus_write_config_byte (pci_bus, devfn, PCI_SUBORDINATE_BUS, temp_byte);
+		if (rc)
+			return rc;
+
+		/* Set HP parameters (Cache Line Size, Latency Timer) */
+		rc = shpchprm_set_hpp(ctrl, func, PCI_HEADER_TYPE_BRIDGE);
+		if (rc)
+			return rc;
+
+		/* Setup the IO, memory, and prefetchable windows */
+
+		io_node = get_max_resource(&(resources->io_head), 0x1000L);
+		if (io_node) {
+			dbg("io_node(base, len, next) (%x, %x, %p)\n", io_node->base, io_node->length, io_node->next);
+		}
+
+		mem_node = get_max_resource(&(resources->mem_head), 0x100000L);
+		if (mem_node) {
+			dbg("mem_node(base, len, next) (%x, %x, %p)\n", mem_node->base, mem_node->length, mem_node->next);
+		}
+
+		if (resources->p_mem_head)
+			p_mem_node = get_max_resource(&(resources->p_mem_head), 0x100000L);
+		else {
+			/*
+			 * In some platform implementation, MEM and PMEM are not
+			 *  distinguished, and hence ACPI _CRS has only MEM entries
+			 *  for both MEM and PMEM.
+			 */
+			dbg("using MEM for PMEM\n");
+			p_mem_node = get_max_resource(&(resources->mem_head), 0x100000L);
+		}
+		if (p_mem_node) {
+			dbg("p_mem_node(base, len, next) (%x, %x, %p)\n", p_mem_node->base, p_mem_node->length, p_mem_node->next);
+		}
+
+		/* set up the IRQ info */
+		if (!resources->irqs) {
+			irqs.barber_pole = 0;
+			irqs.interrupt[0] = 0;
+			irqs.interrupt[1] = 0;
+			irqs.interrupt[2] = 0;
+			irqs.interrupt[3] = 0;
+			irqs.valid_INT = 0;
+		} else {
+			irqs.barber_pole = resources->irqs->barber_pole;
+			irqs.interrupt[0] = resources->irqs->interrupt[0];
+			irqs.interrupt[1] = resources->irqs->interrupt[1];
+			irqs.interrupt[2] = resources->irqs->interrupt[2];
+			irqs.interrupt[3] = resources->irqs->interrupt[3];
+			irqs.valid_INT = resources->irqs->valid_INT;
+		}
+
+		/* set up resource lists that are now aligned on top and bottom
+		 * for anything behind the bridge.
+		 */
+		temp_resources.bus_head = bus_node;
+		temp_resources.io_head = io_node;
+		temp_resources.mem_head = mem_node;
+		temp_resources.p_mem_head = p_mem_node;
+		temp_resources.irqs = &irqs;
+
+		/* Make copies of the nodes we are going to pass down so that
+		 * if there is a problem,we can just use these to free resources
+		 */
+		hold_bus_node = (struct pci_resource *) kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
+		hold_IO_node = (struct pci_resource *) kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
+		hold_mem_node = (struct pci_resource *) kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
+		hold_p_mem_node = (struct pci_resource *) kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
+
+		if (!hold_bus_node || !hold_IO_node || !hold_mem_node || !hold_p_mem_node) {
+			if (hold_bus_node)
+				kfree(hold_bus_node);
+			if (hold_IO_node)
+				kfree(hold_IO_node);
+			if (hold_mem_node)
+				kfree(hold_mem_node);
+			if (hold_p_mem_node)
+				kfree(hold_p_mem_node);
+
+			return(1);
+		}
+
+		memcpy(hold_bus_node, bus_node, sizeof(struct pci_resource));
+
+		bus_node->base += 1;
+		bus_node->length -= 1;
+		bus_node->next = NULL;
+
+		/* If we have IO resources copy them and fill in the bridge's
+		 * IO range registers
+		 */
+		if (io_node) {
+			memcpy(hold_IO_node, io_node, sizeof(struct pci_resource));
+			io_node->next = NULL;
+
+			/* set IO base and Limit registers */
+			RES_CHECK(io_node->base, 8);
+			temp_byte = (u8)(io_node->base >> 8);
+			rc = pci_bus_write_config_byte (pci_bus, devfn, PCI_IO_BASE, temp_byte);
+
+			RES_CHECK(io_node->base + io_node->length - 1, 8);
+			temp_byte = (u8)((io_node->base + io_node->length - 1) >> 8);
+			rc = pci_bus_write_config_byte (pci_bus, devfn, PCI_IO_LIMIT, temp_byte);
+		} else {
+			kfree(hold_IO_node);
+			hold_IO_node = NULL;
+		}
+
+		/* If we have memory resources copy them and fill in the bridge's
+		 * memory range registers.  Otherwise, fill in the range
+		 * registers with values that disable them.
+		 */
+		if (mem_node) {
+			memcpy(hold_mem_node, mem_node, sizeof(struct pci_resource));
+			mem_node->next = NULL;
+
+			/* set Mem base and Limit registers */
+			RES_CHECK(mem_node->base, 16);
+			temp_word = (u32)(mem_node->base >> 16);
+			rc = pci_bus_write_config_word (pci_bus, devfn, PCI_MEMORY_BASE, temp_word);
+
+			RES_CHECK(mem_node->base + mem_node->length - 1, 16);
+			temp_word = (u32)((mem_node->base + mem_node->length - 1) >> 16);
+			rc = pci_bus_write_config_word (pci_bus, devfn, PCI_MEMORY_LIMIT, temp_word);
+		} else {
+			temp_word = 0xFFFF;
+			rc = pci_bus_write_config_word (pci_bus, devfn, PCI_MEMORY_BASE, temp_word);
+
+			temp_word = 0x0000;
+			rc = pci_bus_write_config_word (pci_bus, devfn, PCI_MEMORY_LIMIT, temp_word);
+
+			kfree(hold_mem_node);
+			hold_mem_node = NULL;
+		}
+
+		/* If we have prefetchable memory resources copy them and 
+		 * fill in the bridge's memory range registers.  Otherwise,
+		 * fill in the range registers with values that disable them.
+		 */
+		if (p_mem_node) {
+			memcpy(hold_p_mem_node, p_mem_node, sizeof(struct pci_resource));
+			p_mem_node->next = NULL;
+
+			/* set Pre Mem base and Limit registers */
+			RES_CHECK(p_mem_node->base, 16);
+			temp_word = (u32)(p_mem_node->base >> 16);
+			rc = pci_bus_write_config_word (pci_bus, devfn, PCI_PREF_MEMORY_BASE, temp_word);
+
+			RES_CHECK(p_mem_node->base + p_mem_node->length - 1, 16);
+			temp_word = (u32)((p_mem_node->base + p_mem_node->length - 1) >> 16);
+			rc = pci_bus_write_config_word (pci_bus, devfn, PCI_PREF_MEMORY_LIMIT, temp_word);
+		} else {
+			temp_word = 0xFFFF;
+			rc = pci_bus_write_config_word (pci_bus, devfn, PCI_PREF_MEMORY_BASE, temp_word);
+
+			temp_word = 0x0000;
+			rc = pci_bus_write_config_word (pci_bus, devfn, PCI_PREF_MEMORY_LIMIT, temp_word);
+
+			kfree(hold_p_mem_node);
+			hold_p_mem_node = NULL;
+		}
+
+		/* Adjust this to compensate for extra adjustment in first loop */
+		irqs.barber_pole--;
+
+		rc = 0;
+
+		/* Here we actually find the devices and configure them */
+		for (device = 0; (device <= 0x1F) && !rc; device++) {
+			irqs.barber_pole = (irqs.barber_pole + 1) & 0x03;
+
+			ID = 0xFFFFFFFF;
+			pci_bus->number = hold_bus_node->base;
+			pci_bus_read_config_dword (pci_bus, PCI_DEVFN(device, 0), PCI_VENDOR_ID, &ID);
+			pci_bus->number = func->bus;
+
+			if (ID != 0xFFFFFFFF) {	  /*  device Present */
+				/* Setup slot structure. */
+				new_slot = shpchp_slot_create(hold_bus_node->base);
+
+				if (new_slot == NULL) {
+					/* Out of memory */
+					rc = -ENOMEM;
+					continue;
+				}
+
+				new_slot->bus = hold_bus_node->base;
+				new_slot->device = device;
+				new_slot->function = 0;
+				new_slot->is_a_board = 1;
+				new_slot->status = 0;
+
+				rc = configure_new_device(ctrl, new_slot, 1, &temp_resources, func->bus, func->device);
+				dbg("configure_new_device rc=0x%x\n",rc);
+			}	/* End of IF (device in slot?) */
+		}		/* End of FOR loop */
+
+		if (rc) {
+			shpchp_destroy_resource_list(&temp_resources);
+
+			return_resource(&(resources->bus_head), hold_bus_node);
+			return_resource(&(resources->io_head), hold_IO_node);
+			return_resource(&(resources->mem_head), hold_mem_node);
+			return_resource(&(resources->p_mem_head), hold_p_mem_node);
+			return(rc);
+		}
+
+		/* save the interrupt routing information */
+		if (resources->irqs) {
+			resources->irqs->interrupt[0] = irqs.interrupt[0];
+			resources->irqs->interrupt[1] = irqs.interrupt[1];
+			resources->irqs->interrupt[2] = irqs.interrupt[2];
+			resources->irqs->interrupt[3] = irqs.interrupt[3];
+			resources->irqs->valid_INT = irqs.valid_INT;
+		} else if (!behind_bridge) {
+			/* We need to hook up the interrupts here */
+			for (cloop = 0; cloop < 4; cloop++) {
+				if (irqs.valid_INT & (0x01 << cloop)) {
+					rc = shpchp_set_irq(func->bus, func->device,
+							   0x0A + cloop, irqs.interrupt[cloop]);
+					if (rc) {
+						shpchp_destroy_resource_list (&temp_resources);
+						return_resource(&(resources->bus_head), hold_bus_node);
+						return_resource(&(resources->io_head), hold_IO_node);
+						return_resource(&(resources->mem_head), hold_mem_node);
+						return_resource(&(resources->p_mem_head), hold_p_mem_node);
+						return rc;
+					}
+				}
+			}	/* end of for loop */
+		}
+
+		/* Return unused bus resources
+		 * First use the temporary node to store information for the board
+		 */
+		if (hold_bus_node && bus_node && temp_resources.bus_head) {
+			hold_bus_node->length = bus_node->base - hold_bus_node->base;
+
+			hold_bus_node->next = func->bus_head;
+			func->bus_head = hold_bus_node;
+
+			temp_byte = (u8)(temp_resources.bus_head->base - 1);
+
+			/* set subordinate bus */
+			dbg("re-set subordinate bus = 0x%x\n", temp_byte);
+			rc = pci_bus_write_config_byte (pci_bus, devfn, PCI_SUBORDINATE_BUS, temp_byte);
+
+			if (temp_resources.bus_head->length == 0) {
+				kfree(temp_resources.bus_head);
+				temp_resources.bus_head = NULL;
+			} else {
+				dbg("return bus res of b:d(0x%x:%x) base:len(0x%x:%x)\n",
+					func->bus, func->device, temp_resources.bus_head->base, temp_resources.bus_head->length);
+				return_resource(&(resources->bus_head), temp_resources.bus_head);
+			}
+		}
+
+		/* If we have IO space available and there is some left,
+		 * return the unused portion
+		 */
+		if (hold_IO_node && temp_resources.io_head) {
+			io_node = do_pre_bridge_resource_split(&(temp_resources.io_head),
+							       &hold_IO_node, 0x1000);
+
+			/* Check if we were able to split something off */
+			if (io_node) {
+				hold_IO_node->base = io_node->base + io_node->length;
+
+				RES_CHECK(hold_IO_node->base, 8);
+				temp_byte = (u8)((hold_IO_node->base) >> 8);
+				rc = pci_bus_write_config_byte (pci_bus, devfn, PCI_IO_BASE, temp_byte);
+
+				return_resource(&(resources->io_head), io_node);
+			}
+
+			io_node = do_bridge_resource_split(&(temp_resources.io_head), 0x1000);
+
+			/*  Check if we were able to split something off */
+			if (io_node) {
+				/* First use the temporary node to store information for the board */
+				hold_IO_node->length = io_node->base - hold_IO_node->base;
+
+				/* If we used any, add it to the board's list */
+				if (hold_IO_node->length) {
+					hold_IO_node->next = func->io_head;
+					func->io_head = hold_IO_node;
+
+					RES_CHECK(io_node->base - 1, 8);
+					temp_byte = (u8)((io_node->base - 1) >> 8);
+					rc = pci_bus_write_config_byte (pci_bus, devfn, PCI_IO_LIMIT, temp_byte);
+
+					return_resource(&(resources->io_head), io_node);
+				} else {
+					/* it doesn't need any IO */
+					temp_byte = 0x00;
+					rc = pci_bus_write_config_byte(pci_bus, devfn, PCI_IO_LIMIT, temp_byte);
+
+					return_resource(&(resources->io_head), io_node);
+					kfree(hold_IO_node);
+				}
+			} else {
+				/* it used most of the range */
+				hold_IO_node->next = func->io_head;
+				func->io_head = hold_IO_node;
+			}
+		} else if (hold_IO_node) {
+			/* it used the whole range */
+			hold_IO_node->next = func->io_head;
+			func->io_head = hold_IO_node;
+		}
+
+		/* If we have memory space available and there is some left,
+		 * return the unused portion
+		 */
+		if (hold_mem_node && temp_resources.mem_head) {
+			mem_node = do_pre_bridge_resource_split(&(temp_resources.mem_head), &hold_mem_node, 0x100000L);
+
+			/* Check if we were able to split something off */
+			if (mem_node) {
+				hold_mem_node->base = mem_node->base + mem_node->length;
+
+				RES_CHECK(hold_mem_node->base, 16);
+				temp_word = (u32)((hold_mem_node->base) >> 16);
+				rc = pci_bus_write_config_word (pci_bus, devfn, PCI_MEMORY_BASE, temp_word);
+
+				return_resource(&(resources->mem_head), mem_node);
+			}
+
+			mem_node = do_bridge_resource_split(&(temp_resources.mem_head), 0x100000L);
+
+			/* Check if we were able to split something off */
+			if (mem_node) {
+				/* First use the temporary node to store information for the board */
+				hold_mem_node->length = mem_node->base - hold_mem_node->base;
+
+				if (hold_mem_node->length) {
+					hold_mem_node->next = func->mem_head;
+					func->mem_head = hold_mem_node;
+
+					/* configure end address */
+					RES_CHECK(mem_node->base - 1, 16);
+					temp_word = (u32)((mem_node->base - 1) >> 16);
+					rc = pci_bus_write_config_word (pci_bus, devfn, PCI_MEMORY_LIMIT, temp_word);
+
+					/* Return unused resources to the pool */
+					return_resource(&(resources->mem_head), mem_node);
+				} else {
+					/* it doesn't need any Mem */
+					temp_word = 0x0000;
+					rc = pci_bus_write_config_word (pci_bus, devfn, PCI_MEMORY_LIMIT, temp_word);
+
+					return_resource(&(resources->mem_head), mem_node);
+					kfree(hold_mem_node);
+				}
+			} else {
+				/* it used most of the range */
+				hold_mem_node->next = func->mem_head;
+				func->mem_head = hold_mem_node;
+			}
+		} else if (hold_mem_node) {
+			/* it used the whole range */
+			hold_mem_node->next = func->mem_head;
+			func->mem_head = hold_mem_node;
+		}
+
+		/* If we have prefetchable memory space available and there is some 
+		 * left at the end, return the unused portion
+		 */
+		if (hold_p_mem_node && temp_resources.p_mem_head) {
+			p_mem_node = do_pre_bridge_resource_split(&(temp_resources.p_mem_head),
+								  &hold_p_mem_node, 0x100000L);
+
+			/* Check if we were able to split something off */
+			if (p_mem_node) {
+				hold_p_mem_node->base = p_mem_node->base + p_mem_node->length;
+
+				RES_CHECK(hold_p_mem_node->base, 16);
+				temp_word = (u32)((hold_p_mem_node->base) >> 16);
+				rc = pci_bus_write_config_word (pci_bus, devfn, PCI_PREF_MEMORY_BASE, temp_word);
+
+				return_resource(&(resources->p_mem_head), p_mem_node);
+			}
+
+			p_mem_node = do_bridge_resource_split(&(temp_resources.p_mem_head), 0x100000L);
+
+			/* Check if we were able to split something off */
+			if (p_mem_node) {
+				/* First use the temporary node to store information for the board */
+				hold_p_mem_node->length = p_mem_node->base - hold_p_mem_node->base;
+
+				/* If we used any, add it to the board's list */
+				if (hold_p_mem_node->length) {
+					hold_p_mem_node->next = func->p_mem_head;
+					func->p_mem_head = hold_p_mem_node;
+
+					RES_CHECK(p_mem_node->base - 1, 16);
+					temp_word = (u32)((p_mem_node->base - 1) >> 16);
+					rc = pci_bus_write_config_word (pci_bus, devfn, PCI_PREF_MEMORY_LIMIT, temp_word);
+
+					return_resource(&(resources->p_mem_head), p_mem_node);
+				} else {
+					/* it doesn't need any PMem */
+					temp_word = 0x0000;
+					rc = pci_bus_write_config_word (pci_bus, devfn, PCI_PREF_MEMORY_LIMIT, temp_word);
+
+					return_resource(&(resources->p_mem_head), p_mem_node);
+					kfree(hold_p_mem_node);
+				}
+			} else {
+				/* it used the most of the range */
+				hold_p_mem_node->next = func->p_mem_head;
+				func->p_mem_head = hold_p_mem_node;
+			}
+		} else if (hold_p_mem_node) {
+			/* it used the whole range */
+			hold_p_mem_node->next = func->p_mem_head;
+			func->p_mem_head = hold_p_mem_node;
+		}
+
+		/* We should be configuring an IRQ and the bridge's base address
+		 * registers if it needs them.  Although we have never seen such
+		 * a device
+		 */
+
+		shpchprm_enable_card(ctrl, func, PCI_HEADER_TYPE_BRIDGE);
+
+		dbg("PCI Bridge Hot-Added s:b:d:f(%02x:%02x:%02x:%02x)\n", ctrl->seg, func->bus, func->device, func->function);
+	} else if ((temp_byte & 0x7F) == PCI_HEADER_TYPE_NORMAL) {
+		/* Standard device */
+		u64	base64;
+		rc = pci_bus_read_config_byte (pci_bus, devfn, 0x0B, &class_code);
+
+		if (class_code == PCI_BASE_CLASS_DISPLAY)
+			return (DEVICE_TYPE_NOT_SUPPORTED);
+
+		/* Figure out IO and memory needs */
+		for (cloop = PCI_BASE_ADDRESS_0; cloop <= PCI_BASE_ADDRESS_5; cloop += 4) {
+			temp_register = 0xFFFFFFFF;
+
+			rc = pci_bus_write_config_dword (pci_bus, devfn, cloop, temp_register);
+			rc = pci_bus_read_config_dword(pci_bus, devfn, cloop, &temp_register);
+			dbg("Bar[%x]=0x%x on bus:dev:func(0x%x:%x:%x)\n", cloop, temp_register, func->bus, func->device, 
+				func->function);
+
+			if (!temp_register)
+				continue;
+
+			base64 = 0L;
+			if (temp_register & PCI_BASE_ADDRESS_SPACE_IO) {
+				/* Map IO */
+
+				/* set base = amount of IO space */
+				base = temp_register & 0xFFFFFFFC;
+				base = ~base + 1;
+
+				dbg("NEED IO length(0x%x)\n", base);
+				io_node = get_io_resource(&(resources->io_head),(ulong)base);
+
+				/* allocate the resource to the board */
+				if (io_node) {
+					dbg("Got IO base=0x%x(length=0x%x)\n", io_node->base, io_node->length);
+					base = (u32)io_node->base;
+					io_node->next = func->io_head;
+					func->io_head = io_node;
+				} else {
+					err("Got NO IO resource(length=0x%x)\n", base);
+					return -ENOMEM;
+				}
+			} else {	/* map MEM */
+				int prefetchable = 1;
+				struct pci_resource **res_node = &func->p_mem_head;
+				char *res_type_str = "PMEM";
+				u32	temp_register2;
+
+				if (!(temp_register & PCI_BASE_ADDRESS_MEM_PREFETCH)) {
+					prefetchable = 0;
+					res_node = &func->mem_head;
+					res_type_str++;
+				}
+
+				base = temp_register & 0xFFFFFFF0;
+				base = ~base + 1;
+
+				switch (temp_register & PCI_BASE_ADDRESS_MEM_TYPE_MASK) {
+				case PCI_BASE_ADDRESS_MEM_TYPE_32:
+					dbg("NEED 32 %s bar=0x%x(length=0x%x)\n", res_type_str, temp_register, base);
+
+					if (prefetchable && resources->p_mem_head)
+						mem_node=get_resource(&(resources->p_mem_head), (ulong)base);
+					else {
+						if (prefetchable)
+							dbg("using MEM for PMEM\n");
+						mem_node=get_resource(&(resources->mem_head), (ulong)base);
+					}
+
+					/* allocate the resource to the board */
+					if (mem_node) {
+						base = (u32)mem_node->base; 
+						mem_node->next = *res_node;
+						*res_node = mem_node;
+						dbg("Got 32 %s base=0x%x(length=0x%x)\n", res_type_str, mem_node->base, 
+							mem_node->length);
+					} else {
+						err("Got NO 32 %s resource(length=0x%x)\n", res_type_str, base);
+						return -ENOMEM;
+					}
+					break;
+				case PCI_BASE_ADDRESS_MEM_TYPE_64:
+					rc = pci_bus_read_config_dword(pci_bus, devfn, cloop+4, &temp_register2);
+					dbg("NEED 64 %s bar=0x%x:%x(length=0x%x)\n", res_type_str, temp_register2, 
+						temp_register, base);
+
+					if (prefetchable && resources->p_mem_head)
+						mem_node = get_resource(&(resources->p_mem_head), (ulong)base);
+					else {
+						if (prefetchable)
+							dbg("using MEM for PMEM\n");
+						mem_node = get_resource(&(resources->mem_head), (ulong)base);
+					}
+
+					/* allocate the resource to the board */
+					if (mem_node) {
+						base64 = mem_node->base; 
+						mem_node->next = *res_node;
+						*res_node = mem_node;
+						dbg("Got 64 %s base=0x%x:%x(length=%x)\n", res_type_str, (u32)(base64 >> 32), 
+							(u32)base64, mem_node->length);
+					} else {
+						err("Got NO 64 %s resource(length=0x%x)\n", res_type_str, base);
+						return -ENOMEM;
+					}
+					break;
+				default:
+					dbg("reserved BAR type=0x%x\n", temp_register);
+					break;
+				}
+
+			}
+
+			if (base64) {
+				rc = pci_bus_write_config_dword(pci_bus, devfn, cloop, (u32)base64);
+				cloop += 4;
+				base64 >>= 32;
+
+				if (base64) {
+					dbg("%s: high dword of base64(0x%x) set to 0\n", __FUNCTION__, (u32)base64);
+					base64 = 0x0L;
+				}
+
+				rc = pci_bus_write_config_dword(pci_bus, devfn, cloop, (u32)base64);
+			} else {
+				rc = pci_bus_write_config_dword(pci_bus, devfn, cloop, base);
+			}
+		}		/* End of base register loop */
+
+#if defined(CONFIG_X86_64)
+		/* Figure out which interrupt pin this function uses */
+		rc = pci_bus_read_config_byte (pci_bus, devfn, PCI_INTERRUPT_PIN, &temp_byte);
+
+		/* If this function needs an interrupt and we are behind a bridge
+		   and the pin is tied to something that's alread mapped,
+		   set this one the same
+		 */
+		if (temp_byte && resources->irqs && 
+		    (resources->irqs->valid_INT & 
+		     (0x01 << ((temp_byte + resources->irqs->barber_pole - 1) & 0x03)))) {
+			/* We have to share with something already set up */
+			IRQ = resources->irqs->interrupt[(temp_byte + resources->irqs->barber_pole - 1) & 0x03];
+		} else {
+			/* Program IRQ based on card type */
+			rc = pci_bus_read_config_byte (pci_bus, devfn, 0x0B, &class_code);
+
+			if (class_code == PCI_BASE_CLASS_STORAGE) {
+				IRQ = shpchp_disk_irq;
+			} else {
+				IRQ = shpchp_nic_irq;
+			}
+		}
+
+		/* IRQ Line */
+		rc = pci_bus_write_config_byte (pci_bus, devfn, PCI_INTERRUPT_LINE, IRQ);
+
+		if (!behind_bridge) {
+			rc = shpchp_set_irq(func->bus, func->device, temp_byte + 0x09, IRQ);
+			if (rc)
+				return(1);
+		} else {
+			/* TBD - this code may also belong in the other clause of this If statement */
+			resources->irqs->interrupt[(temp_byte + resources->irqs->barber_pole - 1) & 0x03] = IRQ;
+			resources->irqs->valid_INT |= 0x01 << (temp_byte + resources->irqs->barber_pole - 1) & 0x03;
+		}
+#endif
+		/* Disable ROM base Address */
+		temp_word = 0x00L;
+		rc = pci_bus_write_config_word (pci_bus, devfn, PCI_ROM_ADDRESS, temp_word);
+
+		/* Set HP parameters (Cache Line Size, Latency Timer) */
+		rc = shpchprm_set_hpp(ctrl, func, PCI_HEADER_TYPE_NORMAL);
+		if (rc)
+			return rc;
+
+		shpchprm_enable_card(ctrl, func, PCI_HEADER_TYPE_NORMAL);
+
+		dbg("PCI function Hot-Added s:b:d:f(%02x:%02x:%02x:%02x)\n", ctrl->seg, func->bus, func->device, func->function);
+	}			/* End of Not-A-Bridge else */
+	else {
+		/* It's some strange type of PCI adapter (Cardbus?) */
+		return(DEVICE_TYPE_NOT_SUPPORTED);
+	}
+
+	func->configured = 1;
+
+	return 0;
+}
+
--- diff/drivers/pci/hotplug/shpchp_hpc.c	1970-01-01 01:00:00.000000000 +0100
+++ source/drivers/pci/hotplug/shpchp_hpc.c	2004-02-23 13:56:44.000000000 +0000
@@ -0,0 +1,1608 @@
+/*
+ * Standard PCI Hot Plug Driver
+ *
+ * Copyright (C) 1995,2001 Compaq Computer Corporation
+ * Copyright (C) 2001 Greg Kroah-Hartman (greg@kroah.com)
+ * Copyright (C) 2001 IBM Corp.
+ * Copyright (C) 2003-2004 Intel Corporation
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Send feedback to <greg@kroah.com>,<dely.l.sy@intel.com>
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/slab.h>
+#include <linux/vmalloc.h>
+#include <linux/interrupt.h>
+#include <linux/spinlock.h>
+#include <linux/pci.h>
+#include <asm/system.h>
+#include "shpchp.h"
+
+#ifdef DEBUG
+#define DBG_K_TRACE_ENTRY      ((unsigned int)0x00000001)	/* On function entry */
+#define DBG_K_TRACE_EXIT       ((unsigned int)0x00000002)	/* On function exit */
+#define DBG_K_INFO             ((unsigned int)0x00000004)	/* Info messages */
+#define DBG_K_ERROR            ((unsigned int)0x00000008)	/* Error messages */
+#define DBG_K_TRACE            (DBG_K_TRACE_ENTRY|DBG_K_TRACE_EXIT)
+#define DBG_K_STANDARD         (DBG_K_INFO|DBG_K_ERROR|DBG_K_TRACE)
+/* Redefine this flagword to set debug level */
+#define DEBUG_LEVEL            DBG_K_STANDARD
+
+#define DEFINE_DBG_BUFFER     char __dbg_str_buf[256];
+
+#define DBG_PRINT( dbg_flags, args... )              \
+	do {                                             \
+	  if ( DEBUG_LEVEL & ( dbg_flags ) )             \
+	  {                                              \
+	    int len;                                     \
+	    len = sprintf( __dbg_str_buf, "%s:%d: %s: ", \
+		  __FILE__, __LINE__, __FUNCTION__ );    \
+	    sprintf( __dbg_str_buf + len, args );        \
+	    printk( KERN_NOTICE "%s\n", __dbg_str_buf ); \
+	  }                                              \
+	} while (0)
+
+#define DBG_ENTER_ROUTINE	DBG_PRINT (DBG_K_TRACE_ENTRY, "%s", "[Entry]");
+#define DBG_LEAVE_ROUTINE	DBG_PRINT (DBG_K_TRACE_EXIT, "%s", "[Exit]");
+#else
+#define DEFINE_DBG_BUFFER
+#define DBG_ENTER_ROUTINE
+#define DBG_LEAVE_ROUTINE
+#endif				/* DEBUG */
+
+/* Slot Available Register I field definition */
+#define SLOT_33MHZ		0x0000001f
+#define SLOT_66MHZ_PCIX		0x00001f00
+#define SLOT_100MHZ_PCIX	0x001f0000
+#define SLOT_133MHZ_PCIX	0x1f000000
+
+/* Slot Available Register II field definition */
+#define SLOT_66MHZ		0x0000001f
+#define SLOT_66MHZ_PCIX_266	0x00000f00
+#define SLOT_100MHZ_PCIX_266	0x0000f000
+#define SLOT_133MHZ_PCIX_266	0x000f0000
+#define SLOT_66MHZ_PCIX_533	0x00f00000
+#define SLOT_100MHZ_PCIX_533	0x0f000000
+#define SLOT_133MHZ_PCIX_533	0xf0000000
+
+
+/* Secondary Bus Configuration Register */
+/* For PI = 1, Bits 0 to 2 have been encoded as follows to show current bus speed/mode */
+#define PCI_33MHZ		0x0
+#define PCI_66MHZ		0x1
+#define PCIX_66MHZ		0x2
+#define PCIX_100MHZ		0x3
+#define PCIX_133MHZ		0x4
+
+/* For PI = 2, Bits 0 to 3 have been encoded as follows to show current bus speed/mode */
+#define PCI_33MHZ		0x0
+#define PCI_66MHZ		0x1
+#define PCIX_66MHZ		0x2
+#define PCIX_100MHZ		0x3
+#define PCIX_133MHZ		0x4
+#define PCIX_66MHZ_ECC		0x5
+#define PCIX_100MHZ_ECC		0x6
+#define PCIX_133MHZ_ECC		0x7
+#define PCIX_66MHZ_266		0x8
+#define PCIX_100MHZ_266		0x9
+#define PCIX_133MHZ_266		0x0a
+#define PCIX_66MHZ_533		0x0b
+#define PCIX_100MHZ_533		0x0c
+#define PCIX_133MHZ_533		0x0d
+
+/* Slot Configuration */
+#define SLOT_NUM		0x0000001F
+#define	FIRST_DEV_NUM		0x00001F00
+#define PSN			0x07FF0000
+#define	UPDOWN			0x20000000
+#define	MRLSENSOR		0x40000000
+#define ATTN_BUTTON		0x80000000
+
+/* Slot Status Field Definitions */
+/* Slot State */
+#define PWR_ONLY		0x0001
+#define ENABLED			0x0002
+#define DISABLED		0x0003
+
+/* Power Indicator State */
+#define PWR_LED_ON		0x0004
+#define PWR_LED_BLINK		0x0008
+#define PWR_LED_OFF		0x000c
+
+/* Attention Indicator State */
+#define ATTEN_LED_ON		0x0010
+#define	ATTEN_LED_BLINK		0x0020
+#define ATTEN_LED_OFF		0x0030
+
+/* Power Fault */
+#define pwr_fault		0x0040
+
+/* Attention Button */
+#define ATTEN_BUTTON		0x0080
+
+/* MRL Sensor */
+#define MRL_SENSOR		0x0100
+
+/* 66 MHz Capable */
+#define IS_66MHZ_CAP		0x0200
+
+/* PRSNT1#/PRSNT2# */
+#define SLOT_EMP		0x0c00
+
+/* PCI-X Capability */
+#define NON_PCIX		0x0000
+#define PCIX_66			0x1000
+#define PCIX_133		0x3000
+#define PCIX_266		0x4000  /* For PI = 2 only */
+#define PCIX_533		0x5000	/* For PI = 2 only */
+
+/* SHPC 'write' operations/commands */
+
+/* Slot operation - 0x00h to 0x3Fh */
+
+#define NO_CHANGE		0x00
+
+/* Slot state - Bits 0 & 1 of controller command register */
+#define SET_SLOT_PWR		0x01	
+#define SET_SLOT_ENABLE		0x02	
+#define SET_SLOT_DISABLE	0x03	
+
+/* Power indicator state - Bits 2 & 3 of controller command register*/
+#define SET_PWR_ON		0x04	
+#define SET_PWR_BLINK		0x08	
+#define SET_PWR_OFF		0x0C	
+
+/* Attention indicator state - Bits 4 & 5 of controller command register*/
+#define SET_ATTN_ON		0x010	
+#define SET_ATTN_BLINK		0x020
+#define SET_ATTN_OFF		0x030	
+
+/* Set bus speed/mode A - 0x40h to 0x47h */
+#define SETA_PCI_33MHZ		0x40
+#define SETA_PCI_66MHZ		0x41
+#define SETA_PCIX_66MHZ		0x42
+#define SETA_PCIX_100MHZ	0x43
+#define SETA_PCIX_133MHZ	0x44
+#define RESERV_1		0x45
+#define RESERV_2		0x46
+#define RESERV_3		0x47
+
+/* Set bus speed/mode B - 0x50h to 0x5fh */
+#define	SETB_PCI_33MHZ		0x50
+#define SETB_PCI_66MHZ		0x51
+#define SETB_PCIX_66MHZ_PM	0x52
+#define SETB_PCIX_100MHZ_PM	0x53
+#define SETB_PCIX_133MHZ_PM	0x54
+#define SETB_PCIX_66MHZ_EM	0x55
+#define SETB_PCIX_100MHZ_EM	0x56
+#define SETB_PCIX_133MHZ_EM	0x57
+#define SETB_PCIX_66MHZ_266	0x58
+#define SETB_PCIX_100MHZ_266	0x59
+#define SETB_PCIX_133MHZ_266	0x5a
+#define SETB_PCIX_66MHZ_533	0x5b
+#define SETB_PCIX_100MHZ_533	0x5c
+#define SETB_PCIX_133MHZ_533	0x5d
+
+
+/* Power-on all slots - 0x48h */
+#define SET_PWR_ON_ALL		0x48
+
+/* Enable all slots	- 0x49h */
+#define SET_ENABLE_ALL		0x49
+
+/*  SHPC controller command error code */
+#define SWITCH_OPEN		0x1
+#define INVALID_CMD		0x2
+#define INVALID_SPEED_MODE	0x4
+
+/* For accessing SHPC Working Register Set */
+#define DWORD_SELECT		0x2
+#define DWORD_DATA		0x4
+#define BASE_OFFSET		0x0
+
+/* Field Offset in Logical Slot Register - byte boundary */
+#define SLOT_EVENT_LATCH	0x2
+#define SLOT_SERR_INT_MASK	0x3
+
+static spinlock_t hpc_event_lock;
+
+DEFINE_DBG_BUFFER		/* Debug string buffer for entire HPC defined here */
+static struct php_ctlr_state_s *php_ctlr_list_head = 0;	/* HPC state linked list */
+static int ctlr_seq_num = 0;	/* Controller sequenc # */
+static spinlock_t list_lock;
+
+static irqreturn_t shpc_isr(int IRQ, void *dev_id, struct pt_regs *regs);
+
+static void start_int_poll_timer(struct php_ctlr_state_s *php_ctlr, int seconds);
+
+/* This is the interrupt polling timeout function. */
+static void int_poll_timeout(unsigned long lphp_ctlr)
+{
+    struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *)lphp_ctlr;
+
+    DBG_ENTER_ROUTINE
+
+    if ( !php_ctlr ) {
+		err("%s: Invalid HPC controller handle!\n", __FUNCTION__);
+		return;
+    }
+
+    /* Poll for interrupt events.  regs == NULL => polling */
+    shpc_isr( 0, (void *)php_ctlr, NULL );
+
+    init_timer(&php_ctlr->int_poll_timer);
+	if (!shpchp_poll_time)
+		shpchp_poll_time = 2; /* reset timer to poll in 2 secs if user doesn't specify at module installation*/
+
+    start_int_poll_timer(php_ctlr, shpchp_poll_time);  
+	
+	return;
+}
+
+/* This function starts the interrupt polling timer. */
+static void start_int_poll_timer(struct php_ctlr_state_s *php_ctlr, int seconds)
+{
+    if (!php_ctlr) {
+		err("%s: Invalid HPC controller handle!\n", __FUNCTION__);
+		return;
+	}
+
+    if ( ( seconds <= 0 ) || ( seconds > 60 ) )
+        seconds = 2;            /* Clamp to sane value */
+
+    php_ctlr->int_poll_timer.function = &int_poll_timeout;
+    php_ctlr->int_poll_timer.data = (unsigned long)php_ctlr;    /* Instance data */
+    php_ctlr->int_poll_timer.expires = jiffies + seconds * HZ;
+    add_timer(&php_ctlr->int_poll_timer);
+
+	return;
+}
+
+static int shpc_write_cmd(struct slot *slot, u8 t_slot, u8 cmd)
+{
+	struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle;
+	u16 cmd_status;
+	int retval = 0;
+	u16 temp_word;
+	int i;
+
+	DBG_ENTER_ROUTINE 
+	
+	if (!php_ctlr) {
+		err("%s: Invalid HPC controller handle!\n", __FUNCTION__);
+		return -1;
+	}
+
+	for (i = 0; i < 10; i++) {
+		cmd_status = readw(php_ctlr->creg + CMD_STATUS);
+		
+		if (!(cmd_status & 0x1))
+			break;
+		/*  Check every 0.1 sec for a total of 1 sec*/
+		set_current_state(TASK_INTERRUPTIBLE);
+		schedule_timeout(HZ/10);
+	}
+
+	cmd_status = readw(php_ctlr->creg + CMD_STATUS);
+	
+	if (cmd_status & 0x1) { 
+		/* After 1 sec and and the controller is still busy */
+		err("%s : Controller is still busy after 1 sec.\n", __FUNCTION__);
+		return -1;
+	}
+
+	++t_slot;
+	temp_word =  (t_slot << 8) | (cmd & 0xFF);
+	dbg("%s: t_slot %x cmd %x\n", __FUNCTION__, t_slot, cmd);
+	
+	/* To make sure the Controller Busy bit is 0 before we send out the
+	 * command. 
+	 */
+	writew(temp_word, php_ctlr->creg + CMD);
+	dbg("%s: temp_word written %x\n", __FUNCTION__, temp_word);
+
+	DBG_LEAVE_ROUTINE 
+	return retval;
+}
+
+static int hpc_check_cmd_status(struct controller *ctrl)
+{
+	struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) ctrl->hpc_ctlr_handle;
+	u16 cmd_status;
+	int retval = 0;
+
+	DBG_ENTER_ROUTINE 
+	
+	if (!ctrl->hpc_ctlr_handle) {
+		err("%s: Invalid HPC controller handle!\n", __FUNCTION__);
+		return -1;
+	}
+
+	cmd_status = readw(php_ctlr->creg + CMD_STATUS) & 0x000F;
+	
+	switch (cmd_status >> 1) {
+	case 0:
+		retval = 0;
+		break;
+	case 1:
+		retval = SWITCH_OPEN;
+		err("%s: Switch opened!\n", __FUNCTION__);
+		break;
+	case 2:
+		retval = INVALID_CMD;
+		err("%s: Invalid HPC command!\n", __FUNCTION__);
+		break;
+	case 4:
+		retval = INVALID_SPEED_MODE;
+		err("%s: Invalid bus speed/mode!\n", __FUNCTION__);
+		break;
+	default:
+		retval = cmd_status;
+	}
+
+	DBG_LEAVE_ROUTINE 
+	return retval;
+}
+
+
+static int hpc_get_attention_status(struct slot *slot, u8 *status)
+{
+	struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle;
+	u32 slot_reg;
+	u16 slot_status;
+	u8 atten_led_state;
+	
+	DBG_ENTER_ROUTINE 
+
+	if (!slot->ctrl->hpc_ctlr_handle) {
+		err("%s: Invalid HPC controller handle!\n", __FUNCTION__);
+		return -1;
+	}
+
+	slot_reg = readl(php_ctlr->creg + SLOT1 + 4*(slot->hp_slot));
+	slot_status = (u16) slot_reg;
+	atten_led_state = (slot_status & 0x0030) >> 4;
+
+	switch (atten_led_state) {
+	case 0:
+		*status = 0xFF;	/* Reserved */
+		break;
+	case 1:
+		*status = 1;	/* On */
+		break;
+	case 2:
+		*status = 2;	/* Blink */
+		break;
+	case 3:
+		*status = 0;	/* Off */
+		break;
+	default:
+		*status = 0xFF;
+		break;
+	}
+
+	DBG_LEAVE_ROUTINE 
+	return 0;
+}
+
+static int hpc_get_power_status(struct slot * slot, u8 *status)
+{
+	struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle;
+	u32 slot_reg;
+	u16 slot_status;
+	u8 slot_state;
+	int	retval = 0;
+	
+	DBG_ENTER_ROUTINE 
+
+	if (!slot->ctrl->hpc_ctlr_handle) {
+		err("%s: Invalid HPC controller handle!\n", __FUNCTION__);
+		return -1;
+	}
+
+	slot_reg = readl(php_ctlr->creg + SLOT1 + 4*(slot->hp_slot));
+	slot_status = (u16) slot_reg;
+	slot_state = (slot_status & 0x0003);
+
+	switch (slot_state) {
+	case 0:
+		*status = 0xFF;
+		break;
+	case 1:
+		*status = 2;	/* Powered only */
+		break;
+	case 2:
+		*status = 1;	/* Enabled */
+		break;
+	case 3:
+		*status = 0;	/* Disabled */
+		break;
+	default:
+		*status = 0xFF;
+		break;
+	}
+
+	DBG_LEAVE_ROUTINE 
+	return retval;
+}
+
+
+static int hpc_get_latch_status(struct slot *slot, u8 *status)
+{
+	struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle;
+	u32 slot_reg;
+	u16 slot_status;
+
+	DBG_ENTER_ROUTINE 
+
+	if (!slot->ctrl->hpc_ctlr_handle) {
+		err("%s: Invalid HPC controller handle!\n", __FUNCTION__);
+		return -1;
+	}
+
+	slot_reg = readl(php_ctlr->creg + SLOT1 + 4*(slot->hp_slot));
+	slot_status = (u16)slot_reg;
+
+	*status = ((slot_status & 0x0100) == 0) ? 1 : 0;
+
+	DBG_LEAVE_ROUTINE 
+	return 0;
+}
+
+static int hpc_get_adapter_status(struct slot *slot, u8 *status)
+{
+	struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle;
+	u32 slot_reg;
+	u16 slot_status;
+	u8 card_state;
+
+	DBG_ENTER_ROUTINE 
+
+	if (!slot->ctrl->hpc_ctlr_handle) {
+		err("%s: Invalid HPC controller handle!\n", __FUNCTION__);
+		return -1;
+	}
+
+	slot_reg = readl(php_ctlr->creg + SLOT1 + 4*(slot->hp_slot));
+	slot_status = (u16)slot_reg;
+	card_state = (u8)((slot_status & 0x0C00) >> 10);
+	*status = (card_state != 0x3) ? 1 : 0;
+
+	DBG_LEAVE_ROUTINE 
+	return 0;
+}
+
+static int hpc_get_prog_int(struct slot *slot, u8 *prog_int)
+{
+	struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle;
+
+	DBG_ENTER_ROUTINE 
+	
+	if (!slot->ctrl->hpc_ctlr_handle) {
+		err("%s: Invalid HPC controller handle!\n", __FUNCTION__);
+		return -1;
+	}
+
+	*prog_int = readb(php_ctlr->creg + PROG_INTERFACE);
+
+	DBG_LEAVE_ROUTINE 
+	return 0;
+}
+
+static int hpc_get_adapter_speed(struct slot *slot, enum pci_bus_speed *value)
+{
+	struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle;
+	u32 slot_reg;
+	u16 slot_status, sec_bus_status;
+	u8 m66_cap, pcix_cap, pi;
+	int retval = 0;
+
+	DBG_ENTER_ROUTINE 
+
+	if (!slot->ctrl->hpc_ctlr_handle) {
+		err("%s: Invalid HPC controller handle!\n", __FUNCTION__);
+		return -1;
+	}
+
+	if (slot->hp_slot >= php_ctlr->num_slots) {
+		err("%s: Invalid HPC slot number!\n", __FUNCTION__);
+		return -1;
+	}
+	
+	pi = readb(php_ctlr->creg + PROG_INTERFACE);
+	slot_reg = readl(php_ctlr->creg + SLOT1 + 4*(slot->hp_slot));
+	dbg("%s: pi = %d, slot_reg = %x\n", __FUNCTION__, pi, slot_reg);
+	slot_status = (u16) slot_reg;
+	dbg("%s: slot_status = %x\n", __FUNCTION__, slot_status);
+	sec_bus_status = readw(php_ctlr->creg + SEC_BUS_CONFIG);
+
+	pcix_cap = (u8) ((slot_status & 0x3000) >> 12);
+	dbg("%s:  pcix_cap = %x\n", __FUNCTION__, pcix_cap);
+	m66_cap = (u8) ((slot_status & 0x0200) >> 9);
+	dbg("%s:  m66_cap = %x\n", __FUNCTION__, m66_cap);
+
+
+	if (pi == 2) {
+		switch (pcix_cap) {
+		case 0:
+			*value = m66_cap ? PCI_SPEED_66MHz : PCI_SPEED_33MHz;
+			break;
+		case 1:
+			*value = PCI_SPEED_66MHz_PCIX;
+			break;
+		case 3:
+			*value = PCI_SPEED_133MHz_PCIX;
+			break;
+		case 4:
+			*value = PCI_SPEED_133MHz_PCIX_266;	
+			break;
+		case 5:
+			*value = PCI_SPEED_133MHz_PCIX_533;	
+			break;
+		case 2:	/* Reserved */
+		default:
+			*value = PCI_SPEED_UNKNOWN;
+			retval = -ENODEV;
+			break;
+		}
+	} else {
+		switch (pcix_cap) {
+		case 0:
+			*value = m66_cap ? PCI_SPEED_66MHz : PCI_SPEED_33MHz;
+			break;
+		case 1:
+			*value = PCI_SPEED_66MHz_PCIX;
+			break;
+		case 3:
+			*value = PCI_SPEED_133MHz_PCIX;	
+			break;
+		case 2:	/* Reserved */
+		default:
+			*value = PCI_SPEED_UNKNOWN;
+			retval = -ENODEV;
+			break;
+		}
+	}
+
+	dbg("Adapter speed = %d\n", *value);
+	
+	DBG_LEAVE_ROUTINE 
+	return retval;
+}
+
+static int hpc_get_mode1_ECC_cap(struct slot *slot, u8 *mode)
+{
+	struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle;
+	u16 sec_bus_status;
+	u8 pi;
+	int retval = 0;
+
+	DBG_ENTER_ROUTINE 
+
+	if (!slot->ctrl->hpc_ctlr_handle) {
+		err("%s: Invalid HPC controller handle!\n", __FUNCTION__);
+		return -1;
+	}
+
+	pi = readb(php_ctlr->creg + PROG_INTERFACE);
+	sec_bus_status = readw(php_ctlr->creg + SEC_BUS_CONFIG);
+
+	if (pi == 2) {
+		*mode = (sec_bus_status & 0x0100) >> 7;
+	} else {
+		retval = -1;
+	}
+
+	dbg("Mode 1 ECC cap = %d\n", *mode);
+	
+	DBG_LEAVE_ROUTINE 
+	return retval;
+}
+
+static int hpc_query_power_fault(struct slot * slot)
+{
+	struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle;
+	u32 slot_reg;
+	u16 slot_status;
+	u8 pwr_fault_state, status;
+
+	DBG_ENTER_ROUTINE 
+
+	if (!slot->ctrl->hpc_ctlr_handle) {
+		err("%s: Invalid HPC controller handle!\n", __FUNCTION__);
+		return -1;
+	}
+
+	slot_reg = readl(php_ctlr->creg + SLOT1 + 4*(slot->hp_slot));
+	slot_status = (u16) slot_reg;
+	pwr_fault_state = (slot_status & 0x0040) >> 7;
+	status = (pwr_fault_state == 1) ? 0 : 1;
+
+	DBG_LEAVE_ROUTINE
+	/* Note: Logic 0 => fault */
+	return status;
+}
+
+static int hpc_set_attention_status(struct slot *slot, u8 value)
+{
+	struct php_ctlr_state_s *php_ctlr =(struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle;
+	u8 slot_cmd = 0;
+	int rc = 0;
+
+	if (!slot->ctrl->hpc_ctlr_handle) {
+		err("%s: Invalid HPC controller handle!\n", __FUNCTION__);
+		return -1;
+	}
+
+	if (slot->hp_slot >= php_ctlr->num_slots) {
+		err("%s: Invalid HPC slot number!\n", __FUNCTION__);
+		return -1;
+	}
+
+	switch (value) {
+		case 0 :	
+			slot_cmd = 0x30;	/* OFF */
+			break;
+		case 1:
+			slot_cmd = 0x10;	/* ON */
+			break;
+		case 2:
+			slot_cmd = 0x20;	/* BLINK */
+			break;
+		default:
+			return -1;
+	}
+
+	shpc_write_cmd(slot, slot->hp_slot, slot_cmd);
+	
+	return rc;
+}
+
+
+static void hpc_set_green_led_on(struct slot *slot)
+{
+	struct php_ctlr_state_s *php_ctlr =(struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle;
+	u8 slot_cmd;
+
+	if (!slot->ctrl->hpc_ctlr_handle) {
+		err("%s: Invalid HPC controller handle!\n", __FUNCTION__);
+		return ;
+	}
+
+	if (slot->hp_slot >= php_ctlr->num_slots) {
+		err("%s: Invalid HPC slot number!\n", __FUNCTION__);
+		return ;
+	}
+
+	slot_cmd = 0x04;
+
+	shpc_write_cmd(slot, slot->hp_slot, slot_cmd);
+
+	return;
+}
+
+static void hpc_set_green_led_off(struct slot *slot)
+{
+	struct php_ctlr_state_s *php_ctlr =(struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle;
+	u8 slot_cmd;
+
+	if (!slot->ctrl->hpc_ctlr_handle) {
+		err("%s: Invalid HPC controller handle!\n", __FUNCTION__);
+		return ;
+	}
+
+	if (slot->hp_slot >= php_ctlr->num_slots) {
+		err("%s: Invalid HPC slot number!\n", __FUNCTION__);
+		return ;
+	}
+
+	slot_cmd = 0x0C;
+
+	shpc_write_cmd(slot, slot->hp_slot, slot_cmd);
+
+	return;
+}
+
+static void hpc_set_green_led_blink(struct slot *slot)
+{
+	struct php_ctlr_state_s *php_ctlr =(struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle;
+	u8 slot_cmd;
+
+	if (!slot->ctrl->hpc_ctlr_handle) {
+		err("%s: Invalid HPC controller handle!\n", __FUNCTION__);
+		return ;
+	}
+
+	if (slot->hp_slot >= php_ctlr->num_slots) {
+		err("%s: Invalid HPC slot number!\n", __FUNCTION__);
+		return ;
+	}
+
+	slot_cmd = 0x08;
+
+	shpc_write_cmd(slot, slot->hp_slot, slot_cmd);
+
+	return;
+}
+
+int shpc_get_ctlr_slot_config(struct controller *ctrl,
+	int *num_ctlr_slots,	/* number of slots in this HPC			*/
+	int *first_device_num,	/* PCI dev num of the first slot in this SHPC	*/
+	int *physical_slot_num,	/* phy slot num of the first slot in this SHPC	*/
+	int *updown,		/* physical_slot_num increament: 1 or -1	*/
+	int *flags)
+{
+	struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) ctrl->hpc_ctlr_handle;
+
+	DBG_ENTER_ROUTINE 
+
+	if (!ctrl->hpc_ctlr_handle) {
+		err("%s: Invalid HPC controller handle!\n", __FUNCTION__);
+		return -1;
+	}
+
+	*first_device_num = php_ctlr->slot_device_offset;	/* Obtained in shpc_init() */
+	*num_ctlr_slots = php_ctlr->num_slots;			/* Obtained in shpc_init() */
+
+	*physical_slot_num = (readl(php_ctlr->creg + SLOT_CONFIG) & PSN) >> 16;
+	dbg("%s: physical_slot_num = %x\n", __FUNCTION__, *physical_slot_num);
+	*updown = ((readl(php_ctlr->creg + SLOT_CONFIG) & UPDOWN ) >> 29) ? 1 : -1;	
+
+	DBG_LEAVE_ROUTINE 
+	return 0;
+}
+
+static void hpc_release_ctlr(struct controller *ctrl)
+{
+	struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) ctrl->hpc_ctlr_handle;
+	struct php_ctlr_state_s *p, *p_prev;
+
+	DBG_ENTER_ROUTINE 
+
+	if (!ctrl->hpc_ctlr_handle) {
+		err("%s: Invalid HPC controller handle!\n", __FUNCTION__);
+		return ;
+	}
+
+	if (shpchp_poll_mode) {
+	    del_timer(&php_ctlr->int_poll_timer);
+	} else {	
+		if (php_ctlr->irq) {
+			free_irq(php_ctlr->irq, ctrl);
+			php_ctlr->irq = 0;
+		}
+	}
+	if (php_ctlr->pci_dev) {
+		dbg("%s: before calling iounmap & release_mem_region\n", __FUNCTION__);
+		iounmap(php_ctlr->creg);
+		release_mem_region(pci_resource_start(php_ctlr->pci_dev, 0), pci_resource_len(php_ctlr->pci_dev, 0));
+		dbg("%s: before calling iounmap & release_mem_region\n", __FUNCTION__);
+		php_ctlr->pci_dev = 0;
+	}
+
+	spin_lock(&list_lock);
+	p = php_ctlr_list_head;
+	p_prev = NULL;
+	while (p) {
+		if (p == php_ctlr) {
+			if (p_prev)
+				p_prev->pnext = p->pnext;
+			else
+				php_ctlr_list_head = p->pnext;
+			break;
+		} else {
+			p_prev = p;
+			p = p->pnext;
+		}
+	}
+	spin_unlock(&list_lock);
+
+	kfree(php_ctlr);
+
+DBG_LEAVE_ROUTINE
+			  
+}
+
+static int hpc_power_on_slot(struct slot * slot)
+{
+	struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle;
+	u8 slot_cmd;
+	int retval = 0;
+
+	DBG_ENTER_ROUTINE 
+
+	if (!slot->ctrl->hpc_ctlr_handle) {
+		err("%s: Invalid HPC controller handle!\n", __FUNCTION__);
+		return -1;
+	}
+
+	if (slot->hp_slot >= php_ctlr->num_slots) {
+		err("%s: Invalid HPC slot number!\n", __FUNCTION__);
+		return -1;
+	}
+	slot_cmd = 0x01;
+
+	retval = shpc_write_cmd(slot, slot->hp_slot, slot_cmd);
+
+	if (retval) {
+		err("%s: Write command failed!\n", __FUNCTION__);
+		return -1;
+	}
+
+	DBG_LEAVE_ROUTINE
+
+	return retval;
+}
+
+static int hpc_slot_enable(struct slot * slot)
+{
+	struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle;
+	u8 slot_cmd;
+	int retval = 0;
+
+	DBG_ENTER_ROUTINE 
+
+	if (!slot->ctrl->hpc_ctlr_handle) {
+		err("%s: Invalid HPC controller handle!\n", __FUNCTION__);
+		return -1;
+	}
+
+	if (slot->hp_slot >= php_ctlr->num_slots) {
+		err("%s: Invalid HPC slot number!\n", __FUNCTION__);
+		return -1;
+	}
+	/* 3A => Slot - Enable, Power Indicator - Blink, Attention Indicator - Off */
+	slot_cmd = 0x3A;  
+
+	retval = shpc_write_cmd(slot, slot->hp_slot, slot_cmd);
+
+	if (retval) {
+		err("%s: Write command failed!\n", __FUNCTION__);
+		return -1;
+	}
+
+	DBG_LEAVE_ROUTINE
+	return retval;
+}
+
+static int hpc_slot_disable(struct slot * slot)
+{
+	struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle;
+	u8 slot_cmd;
+	int retval = 0;
+
+	DBG_ENTER_ROUTINE 
+
+	if (!slot->ctrl->hpc_ctlr_handle) {
+		err("%s: Invalid HPC controller handle!\n", __FUNCTION__);
+		return -1;
+	}
+
+	if (slot->hp_slot >= php_ctlr->num_slots) {
+		err("%s: Invalid HPC slot number!\n", __FUNCTION__);
+		return -1;
+	}
+
+	/* 1F => Slot - Disable, Power Indicator - Off, Attention Indicator - On */
+	slot_cmd = 0x1F;
+
+	retval = shpc_write_cmd(slot, slot->hp_slot, slot_cmd);
+
+	if (retval) {
+		err("%s: Write command failed!\n", __FUNCTION__);
+		return -1;
+	}
+
+	DBG_LEAVE_ROUTINE
+	return retval;
+}
+
+static int hpc_enable_all_slots( struct slot *slot )
+{
+	int retval = 0;
+
+	DBG_ENTER_ROUTINE 
+	
+	if (!slot->ctrl->hpc_ctlr_handle) {
+		err("%s: Invalid HPC controller handle!\n", __FUNCTION__);
+		return -1;
+	}
+
+	retval = shpc_write_cmd(slot, 0, SET_ENABLE_ALL);
+	if (retval) {
+		err("%s: Write command failed!\n", __FUNCTION__);
+		return -1;
+	}
+
+	DBG_LEAVE_ROUTINE
+
+	return retval;
+}
+
+static int hpc_pwr_on_all_slots(struct slot *slot)
+{
+	int retval = 0;
+
+	DBG_ENTER_ROUTINE 
+
+	retval = shpc_write_cmd(slot, 0, SET_PWR_ON_ALL);
+
+	if (retval) {
+		err("%s: Write command failed!\n", __FUNCTION__);
+		return -1;
+	}
+
+	DBG_LEAVE_ROUTINE
+	return retval;
+}
+
+static int hpc_set_bus_speed_mode(struct slot * slot, enum pci_bus_speed value)
+{
+	u8 slot_cmd;
+	u8 pi;
+	int retval = 0;
+	struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle;
+
+	DBG_ENTER_ROUTINE 
+	
+	if (!slot->ctrl->hpc_ctlr_handle) {
+		err("%s: Invalid HPC controller handle!\n", __FUNCTION__);
+		return -1;
+	}
+
+	pi = readb(php_ctlr->creg + PROG_INTERFACE);
+	
+	if (pi == 1) {
+		switch (value) {
+		case 0:
+			slot_cmd = SETA_PCI_33MHZ;
+			break;
+		case 1:
+			slot_cmd = SETA_PCI_66MHZ;
+			break;
+		case 2:
+			slot_cmd = SETA_PCIX_66MHZ;
+			break;
+		case 3:
+			slot_cmd = SETA_PCIX_100MHZ;	
+			break;
+		case 4:
+			slot_cmd = SETA_PCIX_133MHZ;	
+			break;
+		default:
+			slot_cmd = PCI_SPEED_UNKNOWN;
+			retval = -ENODEV;
+			return retval;	
+		}
+	} else {
+		switch (value) {
+		case 0:
+			slot_cmd = SETB_PCI_33MHZ;
+			break;
+		case 1:
+			slot_cmd = SETB_PCI_66MHZ;
+			break;
+		case 2:
+			slot_cmd = SETB_PCIX_66MHZ_PM;
+			break;
+		case 3:
+			slot_cmd = SETB_PCIX_100MHZ_PM;	
+			break;
+		case 4:
+			slot_cmd = SETB_PCIX_133MHZ_PM;	
+			break;
+		case 5:
+			slot_cmd = SETB_PCIX_66MHZ_EM;	
+			break;
+		case 6:
+			slot_cmd = SETB_PCIX_100MHZ_EM;	
+			break;
+		case 7:
+			slot_cmd = SETB_PCIX_133MHZ_EM;	
+			break;
+		case 8:
+			slot_cmd = SETB_PCIX_66MHZ_266;	
+			break;
+		case 0x9:
+			slot_cmd = SETB_PCIX_100MHZ_266;	
+			break;
+		case 0xa:
+			slot_cmd = SETB_PCIX_133MHZ_266;	
+			break;
+		case 0xb:
+			slot_cmd = SETB_PCIX_66MHZ_533;	
+			break;
+		case 0xc:
+			slot_cmd = SETB_PCIX_100MHZ_533;	
+			break;
+		case 0xd:
+			slot_cmd = SETB_PCIX_133MHZ_533;	
+			break;
+		default:
+			slot_cmd = PCI_SPEED_UNKNOWN;
+			retval = -ENODEV;
+			return retval;	
+		}
+
+	}
+	retval = shpc_write_cmd(slot, 0, slot_cmd);
+	if (retval) {
+		err("%s: Write command failed!\n", __FUNCTION__);
+		return -1;
+	}
+
+	DBG_LEAVE_ROUTINE
+	return retval;
+}
+
+static irqreturn_t shpc_isr(int IRQ, void *dev_id, struct pt_regs *regs)
+{
+	struct controller *ctrl = NULL;
+	struct php_ctlr_state_s *php_ctlr;
+	u8 schedule_flag = 0;
+	u8 temp_byte;
+	u32 temp_dword, intr_loc, intr_loc2;
+	int hp_slot;
+
+	if (!dev_id)
+		return IRQ_NONE;
+
+	if (!shpchp_poll_mode) { 
+		ctrl = (struct controller *)dev_id;
+		php_ctlr = ctrl->hpc_ctlr_handle;
+	} else 
+		php_ctlr = (struct php_ctlr_state_s *) dev_id;
+
+	if (!php_ctlr || !php_ctlr->creg)
+		return IRQ_NONE;
+
+	/* Check to see if it was our interrupt */
+	intr_loc = readl(php_ctlr->creg + INTR_LOC);  
+
+	if (!intr_loc)
+		return IRQ_NONE;
+	dbg("%s: shpc_isr proceeds\n", __FUNCTION__);
+	dbg("%s: intr_loc = %x\n",__FUNCTION__, intr_loc); 
+
+	/* Mask Global Interrupt Mask - see implementation note on p. 139 */
+	/* of SHPC spec rev 1.0*/
+	temp_dword = readl(php_ctlr->creg + SERR_INTR_ENABLE);
+	dbg("%s: Before masking global interrupt, temp_dword = %x\n",
+		__FUNCTION__, temp_dword); 
+	temp_dword |= 0x00000001;
+	dbg("%s: After masking global interrupt, temp_dword = %x\n",
+		__FUNCTION__, temp_dword); 
+	writel(temp_dword, php_ctlr->creg + SERR_INTR_ENABLE);
+
+	intr_loc2 = readl(php_ctlr->creg + INTR_LOC);  
+	dbg("%s: intr_loc2 = %x\n",__FUNCTION__, intr_loc2); 
+
+	if (intr_loc & 0x0001) {
+		/* 
+		 * Command Complete Interrupt Pending 
+		 * RO only - clear by writing 0 to the Command Completion
+		 * Detect bit in Controller SERR-INT register
+		 */
+		temp_dword = readl(php_ctlr->creg + SERR_INTR_ENABLE);
+		dbg("%s: Before clearing CCIP, temp_dword = %x\n",
+			__FUNCTION__, temp_dword); 
+		temp_dword &= 0xfffeffff;
+		dbg("%s: After clearing CCIP, temp_dword = %x\n",
+			__FUNCTION__, temp_dword); 
+		writel(temp_dword, php_ctlr->creg + SERR_INTR_ENABLE);
+		wake_up_interruptible(&ctrl->queue);
+	}
+
+	if ((intr_loc = (intr_loc >> 1)) == 0) {
+		/* Unmask Global Interrupt Mask */
+		temp_dword = readl(php_ctlr->creg + SERR_INTR_ENABLE);
+		dbg("%s: 1-Before unmasking global interrupt, temp_dword = %x\n",
+			__FUNCTION__, temp_dword); 
+		temp_dword &= 0xfffffffe;
+		dbg("%s: 1-After unmasking global interrupt, temp_dword = %x\n",
+			__FUNCTION__, temp_dword); 
+		writel(temp_dword, php_ctlr->creg + SERR_INTR_ENABLE);
+
+		return IRQ_NONE;
+	}
+
+	for (hp_slot = 0; hp_slot < ctrl->num_slots; hp_slot++) { 
+	/* To find out which slot has interrupt pending */
+		if ((intr_loc >> hp_slot) & 0x01) {
+			temp_dword = readl(php_ctlr->creg + SLOT1 + (4*hp_slot));
+			dbg("%s: Slot %x with intr, temp_dword = %x\n",
+				__FUNCTION__, hp_slot, temp_dword); 
+			temp_byte = (temp_dword >> 16) & 0xFF;
+			dbg("%s: Slot with intr, temp_byte = %x\n",
+				__FUNCTION__, temp_byte); 
+			if ((php_ctlr->switch_change_callback) && (temp_byte & 0x08))
+				schedule_flag += php_ctlr->switch_change_callback(
+					hp_slot, php_ctlr->callback_instance_id);
+			if ((php_ctlr->attention_button_callback) && (temp_byte & 0x04))
+				schedule_flag += php_ctlr->attention_button_callback(
+					hp_slot, php_ctlr->callback_instance_id);
+			if ((php_ctlr->presence_change_callback) && (temp_byte & 0x01))
+				schedule_flag += php_ctlr->presence_change_callback(
+					hp_slot , php_ctlr->callback_instance_id);
+			if ((php_ctlr->power_fault_callback) && (temp_byte & 0x12))
+				schedule_flag += php_ctlr->power_fault_callback(
+					hp_slot, php_ctlr->callback_instance_id);
+			
+			/* Clear all slot events */
+			temp_dword = 0xe01fffff;
+			dbg("%s: Clearing slot events, temp_dword = %x\n",
+				__FUNCTION__, temp_dword); 
+			writel(temp_dword, php_ctlr->creg + SLOT1 + (4*hp_slot));
+
+			intr_loc2 = readl(php_ctlr->creg + INTR_LOC);  
+			dbg("%s: intr_loc2 = %x\n",__FUNCTION__, intr_loc2); 
+		}
+	}
+	/* Unmask Global Interrupt Mask */
+	temp_dword = readl(php_ctlr->creg + SERR_INTR_ENABLE);
+	dbg("%s: 2-Before unmasking global interrupt, temp_dword = %x\n",
+		__FUNCTION__, temp_dword); 
+	temp_dword &= 0xfffffffe;
+	dbg("%s: 2-After unmasking global interrupt, temp_dword = %x\n",
+		__FUNCTION__, temp_dword); 
+	writel(temp_dword, php_ctlr->creg + SERR_INTR_ENABLE);
+	
+	return IRQ_HANDLED;
+}
+
+static int hpc_get_max_bus_speed (struct slot *slot, enum pci_bus_speed *value)
+{
+	struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle;
+	enum pci_bus_speed bus_speed = PCI_SPEED_UNKNOWN;
+	int retval = 0;
+	u8 pi;
+	u32 slot_avail1, slot_avail2;
+	int slot_num;
+
+	DBG_ENTER_ROUTINE 
+
+	if (!slot->ctrl->hpc_ctlr_handle) {
+		err("%s: Invalid HPC controller handle!\n", __FUNCTION__);
+		return -1;
+	}
+
+	if (slot->hp_slot >= php_ctlr->num_slots) {
+		err("%s: Invalid HPC slot number!\n", __FUNCTION__);
+		return -1;
+	}
+
+	pi = readb(php_ctlr->creg + PROG_INTERFACE);
+	slot_avail1 = readl(php_ctlr->creg + SLOT_AVAIL1);
+	slot_avail2 = readl(php_ctlr->creg + SLOT_AVAIL2);
+
+	if (pi == 2) {
+		if ((slot_num = ((slot_avail2 & SLOT_133MHZ_PCIX_533) >> 27)  ) != 0 )
+			bus_speed = PCIX_133MHZ_533;
+		else if ((slot_num = ((slot_avail2 & SLOT_100MHZ_PCIX_533) >> 23)  ) != 0 )
+			bus_speed = PCIX_100MHZ_533;
+		else if ((slot_num = ((slot_avail2 & SLOT_66MHZ_PCIX_533) >> 19)  ) != 0 )
+			bus_speed = PCIX_66MHZ_533;
+		else if ((slot_num = ((slot_avail2 & SLOT_133MHZ_PCIX_266) >> 15)  ) != 0 )
+			bus_speed = PCIX_133MHZ_266;
+		else if ((slot_num = ((slot_avail2 & SLOT_100MHZ_PCIX_266) >> 11)  ) != 0 )
+			bus_speed = PCIX_100MHZ_266;
+		else if ((slot_num = ((slot_avail2 & SLOT_66MHZ_PCIX_266) >> 7)  ) != 0 )
+			bus_speed = PCIX_66MHZ_266;
+		else if ((slot_num = ((slot_avail1 & SLOT_133MHZ_PCIX) >> 23)  ) != 0 )
+			bus_speed = PCIX_133MHZ;
+		else if ((slot_num = ((slot_avail1 & SLOT_100MHZ_PCIX) >> 15)  ) != 0 )
+			bus_speed = PCIX_100MHZ;
+		else if ((slot_num = ((slot_avail1 & SLOT_66MHZ_PCIX) >> 7)  ) != 0 )
+			bus_speed = PCIX_66MHZ;
+		else if ((slot_num = (slot_avail2 & SLOT_66MHZ)) != 0 )
+			bus_speed = PCI_66MHZ;
+		else if ((slot_num = (slot_avail1 & SLOT_33MHZ)) != 0 )
+			bus_speed = PCI_33MHZ;
+		else bus_speed = PCI_SPEED_UNKNOWN;
+	} else {
+		if ((slot_num = ((slot_avail1 & SLOT_133MHZ_PCIX) >> 23)  ) != 0 )
+			bus_speed = PCIX_133MHZ;
+		else if ((slot_num = ((slot_avail1 & SLOT_100MHZ_PCIX) >> 15)  ) != 0 )
+			bus_speed = PCIX_100MHZ;
+		else if ((slot_num = ((slot_avail1 & SLOT_66MHZ_PCIX) >> 7)  ) != 0 )
+			bus_speed = PCIX_66MHZ;
+		else if ((slot_num = (slot_avail2 & SLOT_66MHZ)) != 0 )
+			bus_speed = PCI_66MHZ;
+		else if ((slot_num = (slot_avail1 & SLOT_33MHZ)) != 0 )
+			bus_speed = PCI_33MHZ;
+		else bus_speed = PCI_SPEED_UNKNOWN;
+	}
+
+	*value = bus_speed;
+	dbg("Max bus speed = %d\n", bus_speed);
+	DBG_LEAVE_ROUTINE 
+	return retval;
+}
+
+static int hpc_get_cur_bus_speed (struct slot *slot, enum pci_bus_speed *value)
+{
+	struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle;
+	enum pci_bus_speed bus_speed = PCI_SPEED_UNKNOWN;
+	u16 sec_bus_status;
+	int retval = 0;
+	u8 pi;
+
+	DBG_ENTER_ROUTINE 
+
+	if (!slot->ctrl->hpc_ctlr_handle) {
+		err("%s: Invalid HPC controller handle!\n", __FUNCTION__);
+		return -1;
+	}
+
+	if (slot->hp_slot >= php_ctlr->num_slots) {
+		err("%s: Invalid HPC slot number!\n", __FUNCTION__);
+		return -1;
+	}
+
+	pi = readb(php_ctlr->creg + PROG_INTERFACE);
+	sec_bus_status = readw(php_ctlr->creg + SEC_BUS_CONFIG);
+
+	if (pi == 2) {
+		switch (sec_bus_status & 0x000f) {
+		case 0:
+			bus_speed = PCI_SPEED_33MHz;
+			break;
+		case 1:
+			bus_speed = PCI_SPEED_66MHz;
+			break;
+		case 2:
+			bus_speed = PCI_SPEED_66MHz_PCIX;
+			break;
+		case 3:
+			bus_speed = PCI_SPEED_100MHz_PCIX;	
+			break;
+		case 4:
+			bus_speed = PCI_SPEED_133MHz_PCIX;	
+			break;
+		case 5:
+			bus_speed = PCI_SPEED_66MHz_PCIX_ECC;
+			break;
+		case 6:
+			bus_speed = PCI_SPEED_100MHz_PCIX_ECC;
+			break;
+		case 7:
+			bus_speed = PCI_SPEED_133MHz_PCIX_ECC;	
+			break;
+		case 8:
+			bus_speed = PCI_SPEED_66MHz_PCIX_266;	
+			break;
+		case 9:
+			bus_speed = PCI_SPEED_100MHz_PCIX_266;	
+			break;
+		case 0xa:
+			bus_speed = PCI_SPEED_133MHz_PCIX_266;	
+			break;
+		case 0xb:
+			bus_speed = PCI_SPEED_66MHz_PCIX_533;	
+			break;
+		case 0xc:
+			bus_speed = PCI_SPEED_100MHz_PCIX_533;	
+			break;
+		case 0xd:
+			bus_speed = PCI_SPEED_133MHz_PCIX_533;	
+			break;
+		case 0xe:
+		case 0xf:
+		default:
+			bus_speed = PCI_SPEED_UNKNOWN;
+			break;
+		}
+	} else {
+		/* In the case where pi is undefined, default it to 1 */ 
+		switch (sec_bus_status & 0x0007) {
+		case 0:
+			bus_speed = PCI_SPEED_33MHz;
+			break;
+		case 1:
+			bus_speed = PCI_SPEED_66MHz;
+			break;
+		case 2:
+			bus_speed = PCI_SPEED_66MHz_PCIX;
+			break;
+		case 3:
+			bus_speed = PCI_SPEED_100MHz_PCIX;	
+			break;
+		case 4:
+			bus_speed = PCI_SPEED_133MHz_PCIX;	
+			break;
+		case 5:
+			bus_speed = PCI_SPEED_UNKNOWN;		/*	Reserved */
+			break;
+		case 6:
+			bus_speed = PCI_SPEED_UNKNOWN;		/*	Reserved */
+			break;
+		case 7:
+			bus_speed = PCI_SPEED_UNKNOWN;		/*	Reserved */	
+			break;
+		default:
+			bus_speed = PCI_SPEED_UNKNOWN;
+			break;
+		}
+	}
+
+	*value = bus_speed;
+	dbg("Current bus speed = %d\n", bus_speed);
+	DBG_LEAVE_ROUTINE 
+	return retval;
+}
+
+static struct hpc_ops shpchp_hpc_ops = {
+	.power_on_slot			= hpc_power_on_slot,
+	.slot_enable			= hpc_slot_enable,
+	.slot_disable			= hpc_slot_disable,
+	.enable_all_slots		= hpc_enable_all_slots,
+	.pwr_on_all_slots		= hpc_pwr_on_all_slots,
+	.set_bus_speed_mode		= hpc_set_bus_speed_mode,	  
+	.set_attention_status	= hpc_set_attention_status,
+	.get_power_status		= hpc_get_power_status,
+	.get_attention_status	= hpc_get_attention_status,
+	.get_latch_status		= hpc_get_latch_status,
+	.get_adapter_status		= hpc_get_adapter_status,
+
+	.get_max_bus_speed		= hpc_get_max_bus_speed,
+	.get_cur_bus_speed		= hpc_get_cur_bus_speed,
+	.get_adapter_speed		= hpc_get_adapter_speed,
+	.get_mode1_ECC_cap		= hpc_get_mode1_ECC_cap,
+	.get_prog_int			= hpc_get_prog_int,
+
+	.query_power_fault		= hpc_query_power_fault,
+	.green_led_on			= hpc_set_green_led_on,
+	.green_led_off			= hpc_set_green_led_off,
+	.green_led_blink		= hpc_set_green_led_blink,
+	
+	.release_ctlr			= hpc_release_ctlr,
+	.check_cmd_status		= hpc_check_cmd_status,
+};
+
+int shpc_init(struct controller * ctrl,
+		struct pci_dev * pdev,
+		php_intr_callback_t attention_button_callback,
+		php_intr_callback_t switch_change_callback,
+		php_intr_callback_t presence_change_callback,
+		php_intr_callback_t power_fault_callback)
+{
+	struct php_ctlr_state_s *php_ctlr, *p;
+	void *instance_id = ctrl;
+	int rc;
+	u8 hp_slot;
+	static int first = 1;
+	u32 shpc_cap_offset, shpc_base_offset;
+	u32 tempdword, slot_reg;
+	u16 vendor_id, device_id;
+	u8 i;
+
+	DBG_ENTER_ROUTINE
+
+	spin_lock_init(&list_lock);
+	php_ctlr = (struct php_ctlr_state_s *) kmalloc(sizeof(struct php_ctlr_state_s), GFP_KERNEL);
+
+	if (!php_ctlr) {	/* allocate controller state data */
+		err("%s: HPC controller memory allocation error!\n", __FUNCTION__);
+		goto abort;
+	}
+
+	memset(php_ctlr, 0, sizeof(struct php_ctlr_state_s));
+
+	php_ctlr->pci_dev = pdev;	/* save pci_dev in context */
+
+	rc = pci_read_config_word(pdev, PCI_VENDOR_ID, &vendor_id);
+	dbg("%s: Vendor ID: %x\n",__FUNCTION__, vendor_id);
+	if (rc) {
+		err("%s: unable to read PCI configuration data\n", __FUNCTION__);
+		goto abort_free_ctlr;
+	}
+
+	rc = pci_read_config_word(pdev, PCI_DEVICE_ID, &device_id);
+	dbg("%s: Device ID: %x\n",__FUNCTION__, device_id);
+	if (rc) {
+		err("%s: unable to read PCI configuration data\n", __FUNCTION__);
+		goto abort_free_ctlr;
+	}
+
+	if ((vendor_id == PCI_VENDOR_ID_AMD) || (device_id == PCI_DEVICE_ID_AMD_GOLAM_7450)) {
+		shpc_base_offset = 0;  /* amd shpc driver doesn't use this; assume 0 */
+	} else {
+		if ((shpc_cap_offset = pci_find_capability(pdev, PCI_CAP_ID_SHPC)) == 0) {
+			err("%s : shpc_cap_offset == 0\n", __FUNCTION__);
+			goto abort_free_ctlr;
+		}
+	
+		rc = pci_write_config_byte(pdev, (u8)shpc_cap_offset + DWORD_SELECT , BASE_OFFSET);
+		if (rc) {
+			err("%s : pci_word_config_byte failed\n", __FUNCTION__);
+			goto abort_free_ctlr;
+		}
+	
+		rc = pci_read_config_dword(pdev, (u8)shpc_cap_offset + DWORD_DATA, &shpc_base_offset);
+		if (rc) {
+			err("%s : pci_read_config_dword failed\n", __FUNCTION__);
+			goto abort_free_ctlr;
+		}
+
+		for (i = 0; i <= 14; i++) {
+			rc = pci_write_config_byte(pdev, (u8)shpc_cap_offset +  DWORD_SELECT , i);
+			if (rc) {
+				err("%s : pci_word_config_byte failed\n", __FUNCTION__);
+				goto abort_free_ctlr;
+			}
+	
+			rc = pci_read_config_dword(pdev, (u8)shpc_cap_offset + DWORD_DATA, &tempdword);
+			if (rc) {
+				err("%s : pci_read_config_dword failed\n", __FUNCTION__);
+				goto abort_free_ctlr;
+			}
+			dbg("%s: offset %d: tempdword %x\n", __FUNCTION__,i, tempdword);
+		}
+	}
+
+	if (first) {
+		spin_lock_init(&hpc_event_lock);
+		first = 0;
+	}
+
+	dbg("pdev = %p: b:d:f:irq=0x%x:%x:%x:%x\n", pdev, pdev->bus->number, PCI_SLOT(pdev->devfn), 
+		PCI_FUNC(pdev->devfn), pdev->irq);
+	for ( rc = 0; rc < DEVICE_COUNT_RESOURCE; rc++)
+		if (pci_resource_len(pdev, rc) > 0)
+			dbg("pci resource[%d] start=0x%lx(len=0x%lx), shpc_base_offset %x\n", rc,
+				pci_resource_start(pdev, rc), pci_resource_len(pdev, rc), shpc_base_offset);
+
+	info("HPC vendor_id %x device_id %x ss_vid %x ss_did %x\n", pdev->vendor, pdev->device, pdev->subsystem_vendor, 
+		pdev->subsystem_device);
+
+	if (!request_mem_region(pci_resource_start(pdev, 0) + shpc_base_offset, pci_resource_len(pdev, 0), MY_NAME)) {
+		err("%s: cannot reserve MMIO region\n", __FUNCTION__);
+		goto abort_free_ctlr;
+	}
+
+	php_ctlr->creg = (struct ctrl_reg *)
+		ioremap(pci_resource_start(pdev, 0) + shpc_base_offset, pci_resource_len(pdev, 0));
+	if (!php_ctlr->creg) {
+		err("%s: cannot remap MMIO region %lx @ %lx\n", __FUNCTION__, pci_resource_len(pdev, 0), 
+			pci_resource_start(pdev, 0) + shpc_base_offset);
+		release_mem_region(pci_resource_start(pdev, 0) + shpc_base_offset, pci_resource_len(pdev, 0));
+		goto abort_free_ctlr;
+	}
+	dbg("%s: php_ctlr->creg %p\n", __FUNCTION__, php_ctlr->creg);
+	dbg("%s: physical addr %p\n", __FUNCTION__, (void*)pci_resource_start(pdev, 0));
+
+	init_MUTEX(&ctrl->crit_sect);
+	/* Setup wait queue */
+	init_waitqueue_head(&ctrl->queue);
+
+	/* Find the IRQ */
+	php_ctlr->irq = pdev->irq;
+	dbg("HPC interrupt = %d\n", php_ctlr->irq);
+
+	/* Save interrupt callback info */
+	php_ctlr->attention_button_callback = attention_button_callback;
+	php_ctlr->switch_change_callback = switch_change_callback;
+	php_ctlr->presence_change_callback = presence_change_callback;
+	php_ctlr->power_fault_callback = power_fault_callback;
+	php_ctlr->callback_instance_id = instance_id;
+
+	/* Return PCI Controller Info */
+	php_ctlr->slot_device_offset = (readl(php_ctlr->creg + SLOT_CONFIG) & FIRST_DEV_NUM ) >> 8;
+	php_ctlr->num_slots = readl(php_ctlr->creg + SLOT_CONFIG) & SLOT_NUM;
+	dbg("%s: slot_device_offset %x\n", __FUNCTION__, php_ctlr->slot_device_offset);
+	dbg("%s: num_slots %x\n", __FUNCTION__, php_ctlr->num_slots);
+
+	/* Mask Global Interrupt Mask & Command Complete Interrupt Mask */
+	tempdword = readl(php_ctlr->creg + SERR_INTR_ENABLE);
+	dbg("%s: SERR_INTR_ENABLE = %x\n", __FUNCTION__, tempdword);
+	tempdword = 0x0003000f;   
+	writel(tempdword, php_ctlr->creg + SERR_INTR_ENABLE);
+	tempdword = readl(php_ctlr->creg + SERR_INTR_ENABLE);
+	dbg("%s: SERR_INTR_ENABLE = %x\n", __FUNCTION__, tempdword);
+
+	/* Mask the MRL sensor SERR Mask of individual slot in
+	 * Slot SERR-INT Mask & clear all the existing event if any
+	 */
+	for (hp_slot = 0; hp_slot < php_ctlr->num_slots; hp_slot++) {
+		slot_reg = readl(php_ctlr->creg + SLOT1 + 4*hp_slot );
+		dbg("%s: Default Logical Slot Register %d value %x\n", __FUNCTION__,
+			hp_slot, slot_reg);
+		tempdword = 0xffffffff;  
+		writel(tempdword, php_ctlr->creg + SLOT1 + (4*hp_slot));
+	}
+	
+	if (shpchp_poll_mode)  {/* Install interrupt polling code */
+		/* Install and start the interrupt polling timer */
+		init_timer(&php_ctlr->int_poll_timer);
+		start_int_poll_timer( php_ctlr, 10 );   /* start with 10 second delay */
+	} else {
+		/* Installs the interrupt handler */
+#ifdef CONFIG_PCI_USE_VECTOR 
+		rc = pci_enable_msi(pdev);
+		if (rc) {
+			err("Can't get msi for the hotplug controller\n");
+			dbg("%s: rc = %x\n", __FUNCTION__, rc);
+			goto abort_free_ctlr;
+		}
+		php_ctlr->irq = pdev->irq;
+#endif
+		
+		rc = request_irq(php_ctlr->irq, shpc_isr, SA_SHIRQ, MY_NAME, (void *) ctrl);
+		dbg("%s: request_irq %d for hpc%d (returns %d)\n", __FUNCTION__, php_ctlr->irq, ctlr_seq_num, rc);
+		if (rc) {
+			err("Can't get irq %d for the hotplug controller\n", php_ctlr->irq);
+			goto abort_free_ctlr;
+		}
+		/* Execute OSHP method here */
+	}
+	dbg("%s: Before adding HPC to HPC list\n", __FUNCTION__);
+
+	/*  Add this HPC instance into the HPC list */
+	spin_lock(&list_lock);
+	if (php_ctlr_list_head == 0) {
+		php_ctlr_list_head = php_ctlr;
+		p = php_ctlr_list_head;
+		p->pnext = 0;
+	} else {
+		p = php_ctlr_list_head;
+
+		while (p->pnext)
+			p = p->pnext;
+
+		p->pnext = php_ctlr;
+	}
+	spin_unlock(&list_lock);
+
+
+	ctlr_seq_num++;
+	ctrl->hpc_ctlr_handle = php_ctlr;
+	ctrl->hpc_ops = &shpchp_hpc_ops;
+
+	for (hp_slot = 0; hp_slot < php_ctlr->num_slots; hp_slot++) {
+		slot_reg = readl(php_ctlr->creg + SLOT1 + 4*hp_slot );
+		dbg("%s: Default Logical Slot Register %d value %x\n", __FUNCTION__,
+			hp_slot, slot_reg);
+		tempdword = 0xe01fffff;  
+		writel(tempdword, php_ctlr->creg + SLOT1 + (4*hp_slot));
+	}
+	if (!shpchp_poll_mode) {
+		/* Unmask all general input interrupts and SERR */
+		tempdword = readl(php_ctlr->creg + SERR_INTR_ENABLE);
+		tempdword = 0x0000000a;
+		writel(tempdword, php_ctlr->creg + SERR_INTR_ENABLE);
+		tempdword = readl(php_ctlr->creg + SERR_INTR_ENABLE);
+		dbg("%s: SERR_INTR_ENABLE = %x\n", __FUNCTION__, tempdword);
+	}
+
+	dbg("%s: Leaving shpc_init\n", __FUNCTION__);
+	DBG_LEAVE_ROUTINE
+	return 0;
+
+	/* We end up here for the many possible ways to fail this API.  */
+abort_free_ctlr:
+	kfree(php_ctlr);
+abort:
+	DBG_LEAVE_ROUTINE
+	return -1;
+}
--- diff/drivers/pci/hotplug/shpchp_pci.c	1970-01-01 01:00:00.000000000 +0100
+++ source/drivers/pci/hotplug/shpchp_pci.c	2004-02-23 13:56:44.000000000 +0000
@@ -0,0 +1,821 @@
+/*
+ * Standard Hot Plug Controller Driver
+ *
+ * Copyright (C) 1995,2001 Compaq Computer Corporation
+ * Copyright (C) 2001 Greg Kroah-Hartman (greg@kroah.com)
+ * Copyright (C) 2001 IBM Corp.
+ * Copyright (C) 2003-2004 Intel Corporation
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Send feedback to <greg@kroah.com>, <dely.l.sy@intel.com>
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/slab.h>
+#include <linux/workqueue.h>
+#include <linux/proc_fs.h>
+#include <linux/pci.h>
+#include "../pci.h"
+#include "shpchp.h"
+#ifndef CONFIG_IA64
+#include "../../../arch/i386/pci/pci.h"    /* horrible hack showing how processor dependant we are... */
+#endif
+
+int shpchp_configure_device (struct controller* ctrl, struct pci_func* func)  
+{
+	unsigned char bus;
+	struct pci_bus *child;
+	int num;
+
+	if (func->pci_dev == NULL)
+		func->pci_dev = pci_find_slot(func->bus, PCI_DEVFN(func->device, func->function));
+
+	/* Still NULL ? Well then scan for it ! */
+	if (func->pci_dev == NULL) {
+		num = pci_scan_slot(ctrl->pci_dev->subordinate, PCI_DEVFN(func->device, func->function));
+		if (num)
+			dbg("%s: subordiante %p number %x\n", __FUNCTION__, ctrl->pci_dev->subordinate,
+				ctrl->pci_dev->subordinate->number);
+			pci_bus_add_devices(ctrl->pci_dev->subordinate);		
+		
+		func->pci_dev = pci_find_slot(func->bus, PCI_DEVFN(func->device, func->function));
+		if (func->pci_dev == NULL) {
+			dbg("ERROR: pci_dev still null\n");
+			return 0;
+		}
+	}
+
+	if (func->pci_dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) {
+		pci_read_config_byte(func->pci_dev, PCI_SECONDARY_BUS, &bus);
+		child = (struct pci_bus*) pci_add_new_bus(func->pci_dev->bus, (func->pci_dev), bus);
+		pci_do_scan_bus(child);
+
+	}
+
+	return 0;
+}
+
+
+int shpchp_unconfigure_device(struct pci_func* func) 
+{
+	int rc = 0;
+	int j;
+	
+	dbg("%s: bus/dev/func = %x/%x/%x\n", __FUNCTION__, func->bus, func->device, func->function);
+
+	for (j=0; j<8 ; j++) {
+		struct pci_dev* temp = pci_find_slot(func->bus, (func->device << 3) | j);
+		if (temp) {
+			pci_remove_bus_device(temp);
+		}
+	}
+	return rc;
+}
+
+/*
+ * shpchp_set_irq
+ *
+ * @bus_num: bus number of PCI device
+ * @dev_num: device number of PCI device
+ * @slot: pointer to u8 where slot number will be returned
+ */
+int shpchp_set_irq (u8 bus_num, u8 dev_num, u8 int_pin, u8 irq_num)
+{
+#if !defined(CONFIG_X86_IO_APIC) && !defined(CONFIG_X86_64)
+	int rc;
+	u16 temp_word;
+	struct pci_dev fakedev;
+	struct pci_bus fakebus;
+
+	fakedev.devfn = dev_num << 3;
+	fakedev.bus = &fakebus;
+	fakebus.number = bus_num;
+	dbg("%s: dev %d, bus %d, pin %d, num %d\n",
+	    __FUNCTION__, dev_num, bus_num, int_pin, irq_num);
+	rc = pcibios_set_irq_routing(&fakedev, int_pin - 0x0a, irq_num);
+	dbg("%s: rc %d\n", __FUNCTION__, rc);
+	if (!rc)
+		return !rc;
+
+	/* set the Edge Level Control Register (ELCR) */
+	temp_word = inb(0x4d0);
+	temp_word |= inb(0x4d1) << 8;
+
+	temp_word |= 0x01 << irq_num;
+
+	/* This should only be for x86 as it sets the Edge Level Control Register */
+	outb((u8) (temp_word & 0xFF), 0x4d0);
+	outb((u8) ((temp_word & 0xFF00) >> 8), 0x4d1);
+#endif
+	return 0;
+}
+
+/* More PCI configuration routines; this time centered around hotplug controller */
+
+
+/*
+ * shpchp_save_config
+ *
+ * Reads configuration for all slots in a PCI bus and saves info.
+ *
+ * Note:  For non-hot plug busses, the slot # saved is the device #
+ *
+ * returns 0 if success
+ */
+int shpchp_save_config(struct controller *ctrl, int busnumber, int num_ctlr_slots, int first_device_num)
+{
+	int rc;
+	u8 class_code;
+	u8 header_type;
+	u32 ID;
+	u8 secondary_bus;
+	struct pci_func *new_slot;
+	int sub_bus;
+	int FirstSupported;
+	int LastSupported;
+	int max_functions;
+	int function;
+	u8 DevError;
+	int device = 0;
+	int cloop = 0;
+	int stop_it;
+	int index;
+	int is_hot_plug = num_ctlr_slots || first_device_num;
+	struct pci_bus lpci_bus, *pci_bus;
+
+	dbg("%s: num_ctlr_slots = %d, first_device_num = %d\n", __FUNCTION__, num_ctlr_slots, first_device_num);
+
+	memcpy(&lpci_bus, ctrl->pci_dev->subordinate, sizeof(lpci_bus));
+	pci_bus = &lpci_bus;
+
+	dbg("%s: num_ctlr_slots = %d, first_device_num = %d\n", __FUNCTION__, num_ctlr_slots, first_device_num);
+
+	/*   Decide which slots are supported */
+	if (is_hot_plug) {
+		/*********************************
+		 *  is_hot_plug is the slot mask
+		 *********************************/
+		FirstSupported = first_device_num;
+		LastSupported = FirstSupported + num_ctlr_slots - 1;
+	} else {
+		FirstSupported = 0;
+		LastSupported = 0x1F;
+	}
+
+	dbg("FirstSupported = %d, LastSupported = %d\n", FirstSupported, LastSupported);
+
+	/*   Save PCI configuration space for all devices in supported slots */
+	pci_bus->number = busnumber;
+	for (device = FirstSupported; device <= LastSupported; device++) {
+		ID = 0xFFFFFFFF;
+		rc = pci_bus_read_config_dword(pci_bus, PCI_DEVFN(device, 0), PCI_VENDOR_ID, &ID);
+
+		if (ID != 0xFFFFFFFF) {	  /*  device in slot */
+			rc = pci_bus_read_config_byte(pci_bus, PCI_DEVFN(device, 0), 0x0B, &class_code);
+			if (rc)
+				return rc;
+
+			rc = pci_bus_read_config_byte(pci_bus, PCI_DEVFN(device, 0), PCI_HEADER_TYPE, &header_type);
+			if (rc)
+				return rc;
+
+			dbg("class_code = %x, header_type = %x\n", class_code, header_type);
+
+			/* If multi-function device, set max_functions to 8 */
+			if (header_type & 0x80)
+				max_functions = 8;
+			else
+				max_functions = 1;
+
+			function = 0;
+
+			do {
+				DevError = 0;
+
+				if ((header_type & 0x7F) == PCI_HEADER_TYPE_BRIDGE) {   /* P-P Bridge */
+					/* Recurse the subordinate bus
+					 * get the subordinate bus number
+					 */
+					rc = pci_bus_read_config_byte(pci_bus, PCI_DEVFN(device, function), 
+						PCI_SECONDARY_BUS, &secondary_bus);
+					if (rc) {
+						return rc;
+					} else {
+						sub_bus = (int) secondary_bus;
+
+						/* Save secondary bus cfg spc with this recursive call. */
+						rc = shpchp_save_config(ctrl, sub_bus, 0, 0);
+						if (rc)
+							return rc;
+					}
+				}
+
+				index = 0;
+				new_slot = shpchp_slot_find(busnumber, device, index++);
+
+				dbg("new_slot = %p\n", new_slot);
+
+				while (new_slot && (new_slot->function != (u8) function)) {
+					new_slot = shpchp_slot_find(busnumber, device, index++);
+					dbg("new_slot = %p\n", new_slot);
+				}
+				if (!new_slot) {
+					/* Setup slot structure. */
+					new_slot = shpchp_slot_create(busnumber);
+					dbg("new_slot = %p\n", new_slot);
+
+					if (new_slot == NULL)
+						return(1);
+				}
+
+				new_slot->bus = (u8) busnumber;
+				new_slot->device = (u8) device;
+				new_slot->function = (u8) function;
+				new_slot->is_a_board = 1;
+				new_slot->switch_save = 0x10;
+				/* In case of unsupported board */
+				new_slot->status = DevError;
+				new_slot->pci_dev = pci_find_slot(new_slot->bus, (new_slot->device << 3) | new_slot->function);
+				dbg("new_slot->pci_dev = %p\n", new_slot->pci_dev);
+
+				for (cloop = 0; cloop < 0x20; cloop++) {
+					rc = pci_bus_read_config_dword(pci_bus, PCI_DEVFN(device, function), 
+						cloop << 2, (u32 *) & (new_slot->config_space [cloop]));
+					/* dbg("new_slot->config_space[%x] = %x\n", cloop, new_slot->config_space[cloop]); */
+					if (rc)
+						return rc;
+				}
+
+				function++;
+
+				stop_it = 0;
+
+				/*  this loop skips to the next present function
+				 *  reading in Class Code and Header type.
+				 */
+
+				while ((function < max_functions)&&(!stop_it)) {
+					rc = pci_bus_read_config_dword(pci_bus, PCI_DEVFN(device, function), PCI_VENDOR_ID, &ID);
+
+					if (ID == 0xFFFFFFFF) {  /* nothing there. */
+						function++;
+						dbg("Nothing there\n");
+					} else {  /* Something there */
+						rc = pci_bus_read_config_byte(pci_bus, PCI_DEVFN(device, function), 
+							0x0B, &class_code);
+						if (rc)
+							return rc;
+
+						rc = pci_bus_read_config_byte(pci_bus, PCI_DEVFN(device, function), 
+							PCI_HEADER_TYPE, &header_type);
+						if (rc)
+							return rc;
+
+						dbg("class_code = %x, header_type = %x\n", class_code, header_type);
+						stop_it++;
+					}
+				}
+
+			} while (function < max_functions);
+			/* End of IF (device in slot?) */
+		} else if (is_hot_plug) {
+			/* Setup slot structure with entry for empty slot */
+			new_slot = shpchp_slot_create(busnumber);
+
+			if (new_slot == NULL) {
+				return(1);
+			}
+			dbg("new_slot = %p\n", new_slot);
+
+			new_slot->bus = (u8) busnumber;
+			new_slot->device = (u8) device;
+			new_slot->function = 0;
+			new_slot->is_a_board = 0;
+			new_slot->presence_save = 0;
+			new_slot->switch_save = 0;
+		}
+	}			/* End of FOR loop */
+
+	return(0);
+}
+
+
+/*
+ * shpchp_save_slot_config
+ *
+ * Saves configuration info for all PCI devices in a given slot
+ * including subordinate busses.
+ *
+ * returns 0 if success
+ */
+int shpchp_save_slot_config (struct controller *ctrl, struct pci_func * new_slot)
+{
+	int rc;
+	u8 class_code;
+	u8 header_type;
+	u32 ID;
+	u8 secondary_bus;
+	int sub_bus;
+	int max_functions;
+	int function;
+	int cloop = 0;
+	int stop_it;
+	struct pci_bus lpci_bus, *pci_bus;
+	memcpy(&lpci_bus, ctrl->pci_dev->subordinate, sizeof(lpci_bus));
+	pci_bus = &lpci_bus;
+	pci_bus->number = new_slot->bus;
+
+	ID = 0xFFFFFFFF;
+
+	pci_bus_read_config_dword(pci_bus, PCI_DEVFN(new_slot->device, 0), PCI_VENDOR_ID, &ID);
+
+	if (ID != 0xFFFFFFFF) {	  /*  device in slot */
+		pci_bus_read_config_byte(pci_bus, PCI_DEVFN(new_slot->device, 0), 0x0B, &class_code);
+
+		pci_bus_read_config_byte(pci_bus, PCI_DEVFN(new_slot->device, 0), PCI_HEADER_TYPE, &header_type);
+
+		if (header_type & 0x80)	/* Multi-function device */
+			max_functions = 8;
+		else
+			max_functions = 1;
+
+		function = 0;
+
+		do {
+			if ((header_type & 0x7F) == PCI_HEADER_TYPE_BRIDGE) {	  /* PCI-PCI Bridge */
+				/*  Recurse the subordinate bus */
+				pci_bus_read_config_byte(pci_bus, PCI_DEVFN(new_slot->device, function), 
+					PCI_SECONDARY_BUS, &secondary_bus);
+
+				sub_bus = (int) secondary_bus;
+
+				/* Save the config headers for the secondary bus. */
+				rc = shpchp_save_config(ctrl, sub_bus, 0, 0);
+
+				if (rc)
+					return(rc);
+
+			}	/* End of IF */
+
+			new_slot->status = 0;
+
+			for (cloop = 0; cloop < 0x20; cloop++) {
+				pci_bus_read_config_dword(pci_bus, PCI_DEVFN(new_slot->device, function), 
+					cloop << 2, (u32 *) & (new_slot->config_space [cloop]));
+			}
+
+			function++;
+
+			stop_it = 0;
+
+			/*  this loop skips to the next present function
+			 *  reading in the Class Code and the Header type.
+			 */
+
+			while ((function < max_functions) && (!stop_it)) {
+				pci_bus_read_config_dword(pci_bus, PCI_DEVFN(new_slot->device, function), PCI_VENDOR_ID, &ID);
+
+				if (ID == 0xFFFFFFFF) {	 /* nothing there. */
+					function++;
+				} else {  /* Something there */
+					pci_bus_read_config_byte(pci_bus, PCI_DEVFN(new_slot->device, function), 0x0B, &class_code);
+
+					pci_bus_read_config_byte(pci_bus, PCI_DEVFN(new_slot->device, function), PCI_HEADER_TYPE, 
+						&header_type);
+
+					stop_it++;
+				}
+			}
+
+		} while (function < max_functions);
+	}			/* End of IF (device in slot?) */
+	else {
+		return(2);
+	}
+
+	return(0);
+}
+
+
+/*
+ * shpchp_save_used_resources
+ *
+ * Stores used resource information for existing boards.  this is
+ * for boards that were in the system when this driver was loaded.
+ * this function is for hot plug ADD
+ *
+ * returns 0 if success
+ * if disable  == 1(DISABLE_CARD),
+ *  it loops for all functions of the slot and disables them.
+ * else, it just get resources of the function and return.
+ */
+int shpchp_save_used_resources (struct controller *ctrl, struct pci_func *func, int disable)
+{
+	u8 cloop;
+	u8 header_type;
+	u8 secondary_bus;
+	u8 temp_byte;
+	u16 command;
+	u16 save_command;
+	u16 w_base, w_length;
+	u32 temp_register;
+	u32 save_base;
+	u32 base, length;
+	u64 base64 = 0;
+	int index = 0;
+	unsigned int devfn;
+	struct pci_resource *mem_node = NULL;
+	struct pci_resource *p_mem_node = NULL;
+	struct pci_resource *t_mem_node;
+	struct pci_resource *io_node;
+	struct pci_resource *bus_node;
+	struct pci_bus lpci_bus, *pci_bus;
+	memcpy(&lpci_bus, ctrl->pci_dev->subordinate, sizeof(lpci_bus));
+	pci_bus = &lpci_bus;
+
+	if (disable)
+		func = shpchp_slot_find(func->bus, func->device, index++);
+
+	while ((func != NULL) && func->is_a_board) {
+		pci_bus->number = func->bus;
+		devfn = PCI_DEVFN(func->device, func->function);
+
+		/* Save the command register */
+		pci_bus_read_config_word (pci_bus, devfn, PCI_COMMAND, &save_command);
+
+		if (disable) {
+			/* disable card */
+			command = 0x00;
+			pci_bus_write_config_word(pci_bus, devfn, PCI_COMMAND, command);
+		}
+
+		/* Check for Bridge */
+		pci_bus_read_config_byte (pci_bus, devfn, PCI_HEADER_TYPE, &header_type);
+
+		if ((header_type & 0x7F) == PCI_HEADER_TYPE_BRIDGE) {     /* PCI-PCI Bridge */
+			dbg("Save_used_res of PCI bridge b:d=0x%x:%x, sc=0x%x\n", func->bus, func->device, save_command);
+			if (disable) {
+				/* Clear Bridge Control Register */
+				command = 0x00;
+				pci_bus_write_config_word(pci_bus, devfn, PCI_BRIDGE_CONTROL, command);
+			}
+
+			pci_bus_read_config_byte (pci_bus, devfn, PCI_SECONDARY_BUS, &secondary_bus);
+			pci_bus_read_config_byte (pci_bus, devfn, PCI_SUBORDINATE_BUS, &temp_byte);
+
+			bus_node =(struct pci_resource *) kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
+			if (!bus_node)
+				return -ENOMEM;
+
+			bus_node->base = (ulong)secondary_bus;
+			bus_node->length = (ulong)(temp_byte - secondary_bus + 1);
+
+			bus_node->next = func->bus_head;
+			func->bus_head = bus_node;
+
+			/* Save IO base and Limit registers */
+			pci_bus_read_config_byte (pci_bus, devfn, PCI_IO_BASE, &temp_byte);
+			base = temp_byte;
+			pci_bus_read_config_byte (pci_bus, devfn, PCI_IO_LIMIT, &temp_byte);
+			length = temp_byte;
+
+			if ((base <= length) && (!disable || (save_command & PCI_COMMAND_IO))) {
+				io_node = (struct pci_resource *) kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
+				if (!io_node)
+					return -ENOMEM;
+
+				io_node->base = (ulong)(base & PCI_IO_RANGE_MASK) << 8;
+				io_node->length = (ulong)(length - base + 0x10) << 8;
+
+				io_node->next = func->io_head;
+				func->io_head = io_node;
+			}
+
+			/* Save memory base and Limit registers */
+			pci_bus_read_config_word (pci_bus, devfn, PCI_MEMORY_BASE, &w_base);
+			pci_bus_read_config_word (pci_bus, devfn, PCI_MEMORY_LIMIT, &w_length);
+
+			if ((w_base <= w_length) && (!disable || (save_command & PCI_COMMAND_MEMORY))) {
+				mem_node = (struct pci_resource *) kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
+				if (!mem_node)
+					return -ENOMEM;
+
+				mem_node->base = (ulong)w_base << 16;
+				mem_node->length = (ulong)(w_length - w_base + 0x10) << 16;
+
+				mem_node->next = func->mem_head;
+				func->mem_head = mem_node;
+			}
+			/* Save prefetchable memory base and Limit registers */
+			pci_bus_read_config_word (pci_bus, devfn, PCI_PREF_MEMORY_BASE, &w_base);
+			pci_bus_read_config_word (pci_bus, devfn, PCI_PREF_MEMORY_LIMIT, &w_length);
+
+			if ((w_base <= w_length) && (!disable || (save_command & PCI_COMMAND_MEMORY))) {
+				p_mem_node = (struct pci_resource *) kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
+				if (!p_mem_node)
+					return -ENOMEM;
+
+				p_mem_node->base = (ulong)w_base << 16;
+				p_mem_node->length = (ulong)(w_length - w_base + 0x10) << 16;
+
+				p_mem_node->next = func->p_mem_head;
+				func->p_mem_head = p_mem_node;
+			}
+		} else if ((header_type & 0x7F) == PCI_HEADER_TYPE_NORMAL) {
+			dbg("Save_used_res of PCI adapter b:d=0x%x:%x, sc=0x%x\n", func->bus, func->device, save_command);
+
+			/* Figure out IO and memory base lengths */
+			for (cloop = PCI_BASE_ADDRESS_0; cloop <= PCI_BASE_ADDRESS_5; cloop += 4) {
+				pci_bus_read_config_dword (pci_bus, devfn, cloop, &save_base);
+
+				temp_register = 0xFFFFFFFF;
+				pci_bus_write_config_dword (pci_bus, devfn, cloop, temp_register);
+				pci_bus_read_config_dword (pci_bus, devfn, cloop, &temp_register);
+
+				if (!disable) {
+					pci_bus_write_config_dword (pci_bus, devfn, cloop, save_base);
+				}
+
+				if (!temp_register)
+					continue;
+
+				base = temp_register;
+
+				if ((base & PCI_BASE_ADDRESS_SPACE_IO) && (!disable || (save_command & PCI_COMMAND_IO))) {
+					/* IO base */
+					/* set temp_register = amount of IO space requested */
+					base = base & 0xFFFFFFFCL;
+					base = (~base) + 1;
+
+					io_node = (struct pci_resource *) kmalloc(sizeof (struct pci_resource), GFP_KERNEL);
+					if (!io_node)
+						return -ENOMEM;
+
+					io_node->base = (ulong)save_base & PCI_BASE_ADDRESS_IO_MASK;
+					io_node->length = (ulong)base;
+					dbg("sur adapter: IO bar=0x%x(length=0x%x)\n", io_node->base, io_node->length);
+
+					io_node->next = func->io_head;
+					func->io_head = io_node;
+				} else {  /* map Memory */
+					int prefetchable = 1;
+					/* struct pci_resources **res_node; */
+					char *res_type_str = "PMEM";
+					u32 temp_register2;
+
+					t_mem_node = (struct pci_resource *) kmalloc(sizeof (struct pci_resource), GFP_KERNEL);
+					if (!t_mem_node)
+						return -ENOMEM;
+
+					if (!(base & PCI_BASE_ADDRESS_MEM_PREFETCH) && (!disable || (save_command & PCI_COMMAND_MEMORY))) {
+						prefetchable = 0;
+						mem_node = t_mem_node;
+						res_type_str++;
+					} else
+						p_mem_node = t_mem_node;
+
+					base = base & 0xFFFFFFF0L;
+					base = (~base) + 1;
+
+					switch (temp_register & PCI_BASE_ADDRESS_MEM_TYPE_MASK) {
+					case PCI_BASE_ADDRESS_MEM_TYPE_32:
+						if (prefetchable) {
+							p_mem_node->base = (ulong)save_base & PCI_BASE_ADDRESS_MEM_MASK;
+							p_mem_node->length = (ulong)base;
+							dbg("sur adapter: 32 %s bar=0x%x(length=0x%x)\n", res_type_str, 
+								p_mem_node->base, p_mem_node->length);
+
+							p_mem_node->next = func->p_mem_head;
+							func->p_mem_head = p_mem_node;
+						} else {
+							mem_node->base = (ulong)save_base & PCI_BASE_ADDRESS_MEM_MASK;
+							mem_node->length = (ulong)base;
+							dbg("sur adapter: 32 %s bar=0x%x(length=0x%x)\n", res_type_str, 
+								mem_node->base, mem_node->length);
+
+							mem_node->next = func->mem_head;
+							func->mem_head = mem_node;
+						}
+						break;
+					case PCI_BASE_ADDRESS_MEM_TYPE_64:
+						pci_bus_read_config_dword(pci_bus, devfn, cloop+4, &temp_register2);
+						base64 = temp_register2;
+						base64 = (base64 << 32) | save_base;
+
+						if (temp_register2) {
+							dbg("sur adapter: 64 %s high dword of base64(0x%x:%x) masked to 0\n", 
+								res_type_str, temp_register2, (u32)base64);
+							base64 &= 0x00000000FFFFFFFFL;
+						}
+
+						if (prefetchable) {
+							p_mem_node->base = base64 & PCI_BASE_ADDRESS_MEM_MASK;
+							p_mem_node->length = base;
+							dbg("sur adapter: 64 %s base=0x%x(len=0x%x)\n", res_type_str, 
+								p_mem_node->base, p_mem_node->length);
+
+							p_mem_node->next = func->p_mem_head;
+							func->p_mem_head = p_mem_node;
+						} else {
+							mem_node->base = base64 & PCI_BASE_ADDRESS_MEM_MASK;
+							mem_node->length = base;
+							dbg("sur adapter: 64 %s base=0x%x(len=0x%x)\n", res_type_str, 
+								mem_node->base, mem_node->length);
+
+							mem_node->next = func->mem_head;
+							func->mem_head = mem_node;
+						}
+						cloop += 4;
+						break;
+					default:
+						dbg("asur: reserved BAR type=0x%x\n", temp_register);
+						break;
+					}
+				} 
+			}	/* End of base register loop */
+		} else {	/* Some other unknown header type */
+			dbg("Save_used_res of PCI unknown type b:d=0x%x:%x. skip.\n", func->bus, func->device);
+		}
+
+		/* find the next device in this slot */
+		if (!disable)
+			break;
+		func = shpchp_slot_find(func->bus, func->device, index++);
+	}
+
+	return(0);
+}
+
+
+/*
+ * shpchp_return_board_resources
+ *
+ * this routine returns all resources allocated to a board to
+ * the available pool.
+ *
+ * returns 0 if success
+ */
+int shpchp_return_board_resources(struct pci_func * func, struct resource_lists * resources)
+{
+	int rc = 0;
+	struct pci_resource *node;
+	struct pci_resource *t_node;
+	dbg("%s\n", __FUNCTION__);
+
+	if (!func)
+		return(1);
+
+	node = func->io_head;
+	func->io_head = NULL;
+	while (node) {
+		t_node = node->next;
+		return_resource(&(resources->io_head), node);
+		node = t_node;
+	}
+
+	node = func->mem_head;
+	func->mem_head = NULL;
+	while (node) {
+		t_node = node->next;
+		return_resource(&(resources->mem_head), node);
+		node = t_node;
+	}
+
+	node = func->p_mem_head;
+	func->p_mem_head = NULL;
+	while (node) {
+		t_node = node->next;
+		return_resource(&(resources->p_mem_head), node);
+		node = t_node;
+	}
+
+	node = func->bus_head;
+	func->bus_head = NULL;
+	while (node) {
+		t_node = node->next;
+		return_resource(&(resources->bus_head), node);
+		node = t_node;
+	}
+
+	rc |= shpchp_resource_sort_and_combine(&(resources->mem_head));
+	rc |= shpchp_resource_sort_and_combine(&(resources->p_mem_head));
+	rc |= shpchp_resource_sort_and_combine(&(resources->io_head));
+	rc |= shpchp_resource_sort_and_combine(&(resources->bus_head));
+
+	return(rc);
+}
+
+
+/*
+ * shpchp_destroy_resource_list
+ *
+ * Puts node back in the resource list pointed to by head
+ */
+void shpchp_destroy_resource_list (struct resource_lists * resources)
+{
+	struct pci_resource *res, *tres;
+
+	res = resources->io_head;
+	resources->io_head = NULL;
+
+	while (res) {
+		tres = res;
+		res = res->next;
+		kfree(tres);
+	}
+
+	res = resources->mem_head;
+	resources->mem_head = NULL;
+
+	while (res) {
+		tres = res;
+		res = res->next;
+		kfree(tres);
+	}
+
+	res = resources->p_mem_head;
+	resources->p_mem_head = NULL;
+
+	while (res) {
+		tres = res;
+		res = res->next;
+		kfree(tres);
+	}
+
+	res = resources->bus_head;
+	resources->bus_head = NULL;
+
+	while (res) {
+		tres = res;
+		res = res->next;
+		kfree(tres);
+	}
+}
+
+
+/*
+ * shpchp_destroy_board_resources
+ *
+ * Puts node back in the resource list pointed to by head
+ */
+void shpchp_destroy_board_resources (struct pci_func * func)
+{
+	struct pci_resource *res, *tres;
+
+	res = func->io_head;
+	func->io_head = NULL;
+
+	while (res) {
+		tres = res;
+		res = res->next;
+		kfree(tres);
+	}
+
+	res = func->mem_head;
+	func->mem_head = NULL;
+
+	while (res) {
+		tres = res;
+		res = res->next;
+		kfree(tres);
+	}
+
+	res = func->p_mem_head;
+	func->p_mem_head = NULL;
+
+	while (res) {
+		tres = res;
+		res = res->next;
+		kfree(tres);
+	}
+
+	res = func->bus_head;
+	func->bus_head = NULL;
+
+	while (res) {
+		tres = res;
+		res = res->next;
+		kfree(tres);
+	}
+}
+
--- diff/drivers/pci/hotplug/shpchp_sysfs.c	1970-01-01 01:00:00.000000000 +0100
+++ source/drivers/pci/hotplug/shpchp_sysfs.c	2004-02-23 13:56:44.000000000 +0000
@@ -0,0 +1,143 @@
+/*
+ * Compaq Hot Plug Controller Driver
+ *
+ * Copyright (c) 1995,2001 Compaq Computer Corporation
+ * Copyright (c) 2001,2003 Greg Kroah-Hartman (greg@kroah.com)
+ * Copyright (c) 2001 IBM Corp.
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Send feedback to <greg@kroah.com>
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/proc_fs.h>
+#include <linux/workqueue.h>
+#include <linux/pci.h>
+#include "shpchp.h"
+
+
+/* A few routines that create sysfs entries for the hot plug controller */
+
+static ssize_t show_ctrl (struct device *dev, char *buf)
+{
+	struct pci_dev *pci_dev;
+	struct controller *ctrl;
+	char * out = buf;
+	int index;
+	struct pci_resource *res;
+
+	pci_dev = container_of (dev, struct pci_dev, dev);
+	ctrl = pci_get_drvdata(pci_dev);
+
+	out += sprintf(buf, "Free resources: memory\n");
+	index = 11;
+	res = ctrl->mem_head;
+	while (res && index--) {
+		out += sprintf(out, "start = %8.8x, length = %8.8x\n", res->base, res->length);
+		res = res->next;
+	}
+	out += sprintf(out, "Free resources: prefetchable memory\n");
+	index = 11;
+	res = ctrl->p_mem_head;
+	while (res && index--) {
+		out += sprintf(out, "start = %8.8x, length = %8.8x\n", res->base, res->length);
+		res = res->next;
+	}
+	out += sprintf(out, "Free resources: IO\n");
+	index = 11;
+	res = ctrl->io_head;
+	while (res && index--) {
+		out += sprintf(out, "start = %8.8x, length = %8.8x\n", res->base, res->length);
+		res = res->next;
+	}
+	out += sprintf(out, "Free resources: bus numbers\n");
+	index = 11;
+	res = ctrl->bus_head;
+	while (res && index--) {
+		out += sprintf(out, "start = %8.8x, length = %8.8x\n", res->base, res->length);
+		res = res->next;
+	}
+
+	return out - buf;
+}
+static DEVICE_ATTR (ctrl, S_IRUGO, show_ctrl, NULL);
+
+static ssize_t show_dev (struct device *dev, char *buf)
+{
+	struct pci_dev *pci_dev;
+	struct controller *ctrl;
+	char * out = buf;
+	int index;
+	struct pci_resource *res;
+	struct pci_func *new_slot;
+	struct slot *slot;
+
+	pci_dev = container_of (dev, struct pci_dev, dev);
+	ctrl = pci_get_drvdata(pci_dev);
+
+	slot=ctrl->slot;
+
+	while (slot) {
+		new_slot = shpchp_slot_find(slot->bus, slot->device, 0);
+		if (!new_slot)
+			break;
+		out += sprintf(out, "assigned resources: memory\n");
+		index = 11;
+		res = new_slot->mem_head;
+		while (res && index--) {
+			out += sprintf(out, "start = %8.8x, length = %8.8x\n", res->base, res->length);
+			res = res->next;
+		}
+		out += sprintf(out, "assigned resources: prefetchable memory\n");
+		index = 11;
+		res = new_slot->p_mem_head;
+		while (res && index--) {
+			out += sprintf(out, "start = %8.8x, length = %8.8x\n", res->base, res->length);
+			res = res->next;
+		}
+		out += sprintf(out, "assigned resources: IO\n");
+		index = 11;
+		res = new_slot->io_head;
+		while (res && index--) {
+			out += sprintf(out, "start = %8.8x, length = %8.8x\n", res->base, res->length);
+			res = res->next;
+		}
+		out += sprintf(out, "assigned resources: bus numbers\n");
+		index = 11;
+		res = new_slot->bus_head;
+		while (res && index--) {
+			out += sprintf(out, "start = %8.8x, length = %8.8x\n", res->base, res->length);
+			res = res->next;
+		}
+		slot=slot->next;
+	}
+
+	return out - buf;
+}
+static DEVICE_ATTR (dev, S_IRUGO, show_dev, NULL);
+
+void shpchp_create_ctrl_files (struct controller *ctrl)
+{
+	device_create_file (&ctrl->pci_dev->dev, &dev_attr_ctrl);
+	device_create_file (&ctrl->pci_dev->dev, &dev_attr_dev);
+}
--- diff/drivers/pci/hotplug/shpchprm.h	1970-01-01 01:00:00.000000000 +0100
+++ source/drivers/pci/hotplug/shpchprm.h	2004-02-23 13:56:44.000000000 +0000
@@ -0,0 +1,56 @@
+/*
+ * SHPCHPRM : SHPCHP Resource Manager for ACPI/non-ACPI platform
+ *
+ * Copyright (C) 1995,2001 Compaq Computer Corporation
+ * Copyright (C) 2001 Greg Kroah-Hartman (greg@kroah.com)
+ * Copyright (C) 2001 IBM Corp.
+ * Copyright (C) 2003-2004 Intel Corporation
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Send feedback to <greg@kroah.com>, <dely.l.sy@intel.com>
+ *
+ */
+
+#ifndef _SHPCHPRM_H_
+#define _SHPCHPRM_H_
+
+#ifdef	CONFIG_HOTPLUG_PCI_SHPC_PHPRM_LEGACY
+#include "shpchprm_legacy.h"
+#else
+#include "shpchprm_nonacpi.h"
+#endif
+
+int shpchprm_init(enum php_ctlr_type ct);
+void shpchprm_cleanup(void);
+int shpchprm_print_pirt(void);
+void *shpchprm_get_slot(struct slot *slot);
+int shpchprm_find_available_resources(struct controller *ctrl);
+int shpchprm_set_hpp(struct controller *ctrl, struct pci_func *func, u8 card_type);
+void shpchprm_enable_card(struct controller *ctrl, struct pci_func *func, u8 card_type);
+int shpchprm_get_physical_slot_number(struct controller *ctrl, u32 *sun, u8 busnum, u8 devnum);
+
+#ifdef	DEBUG
+#define RES_CHECK(this, bits)	\
+	{ if (((this) & (bits - 1))) \
+		printk("%s:%d ERR: potential res loss!\n", __FUNCTION__, __LINE__); }
+#else
+#define RES_CHECK(this, bits)
+#endif
+
+#endif				/* _SHPCHPRM_H_ */
--- diff/drivers/pci/hotplug/shpchprm_acpi.c	1970-01-01 01:00:00.000000000 +0100
+++ source/drivers/pci/hotplug/shpchprm_acpi.c	2004-02-23 13:56:44.000000000 +0000
@@ -0,0 +1,1694 @@
+/*
+ * SHPCHPRM ACPI: PHP Resource Manager for ACPI platform
+ *
+ * Copyright (C) 2003-2004 Intel Corporation
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Send feedback to <dely.l.sy@intel.com>
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/acpi.h>
+#include <linux/efi.h>
+#include <asm/uaccess.h>
+#include <asm/system.h>
+#ifdef	CONFIG_IA64
+#include <asm/iosapic.h>
+#endif
+#include <acpi/acpi.h>
+#include <acpi/acpi_bus.h>
+#include <acpi/actypes.h>
+#include "shpchp.h"
+#include "shpchprm.h"
+
+#define	PCI_MAX_BUS		0x100
+#define	ACPI_STA_DEVICE_PRESENT	0x01
+
+#define	METHOD_NAME__SUN	"_SUN"
+#define	METHOD_NAME__HPP	"_HPP"
+#define	METHOD_NAME_OSHP	"OSHP"
+
+#define	PHP_RES_BUS		0xA0
+#define	PHP_RES_IO		0xA1
+#define	PHP_RES_MEM		0xA2
+#define	PHP_RES_PMEM		0xA3
+
+#define	BRIDGE_TYPE_P2P		0x00
+#define	BRIDGE_TYPE_HOST	0x01
+
+/* this should go to drivers/acpi/include/ */
+struct acpi__hpp {
+	u8	cache_line_size;
+	u8	latency_timer;
+	u8	enable_serr;
+	u8	enable_perr;
+};
+
+struct acpi_php_slot {
+	struct acpi_php_slot	*next;
+	struct acpi_bridge	*bridge;
+	acpi_handle		handle;
+	int	seg;
+	int	bus;
+	int	dev;
+	int	fun;
+	u32	sun;
+	struct pci_resource *mem_head;
+	struct pci_resource *p_mem_head;
+	struct pci_resource *io_head;
+	struct pci_resource *bus_head;
+	void	*slot_ops;	/* _STA, _EJx, etc */
+	struct slot *slot;
+};		/* per func */
+
+struct acpi_bridge {
+	struct acpi_bridge	*parent;
+	struct acpi_bridge	*next;
+	struct acpi_bridge	*child;
+	acpi_handle	handle;
+	int seg;
+	int pbus;				/* pdev->bus->number		*/
+	int pdevice;				/* PCI_SLOT(pdev->devfn)	*/
+	int pfunction;				/* PCI_DEVFN(pdev->devfn)	*/
+	int bus;				/* pdev->subordinate->number	*/
+	struct acpi__hpp		*_hpp;
+	struct acpi_php_slot	*slots;
+	struct pci_resource 	*tmem_head;	/* total from crs	*/
+	struct pci_resource 	*tp_mem_head;	/* total from crs	*/
+	struct pci_resource 	*tio_head;	/* total from crs	*/
+	struct pci_resource 	*tbus_head;	/* total from crs	*/
+	struct pci_resource 	*mem_head;	/* available	*/
+	struct pci_resource 	*p_mem_head;	/* available	*/
+	struct pci_resource 	*io_head;	/* available	*/
+	struct pci_resource 	*bus_head;	/* available	*/
+	int scanned;
+	int type;
+};
+
+static struct acpi_bridge *acpi_bridges_head;
+
+static u8 * acpi_path_name( acpi_handle	handle)
+{
+	acpi_status		status;
+	static u8	path_name[ACPI_PATHNAME_MAX];
+	struct acpi_buffer		ret_buf = { ACPI_PATHNAME_MAX, path_name };
+
+	memset(path_name, 0, sizeof (path_name));
+	status = acpi_get_name(handle, ACPI_FULL_PATHNAME, &ret_buf);
+
+	if (ACPI_FAILURE(status))
+		return NULL;
+	else
+		return path_name;	
+}
+
+static void acpi_get__hpp ( struct acpi_bridge	*ab);
+static void acpi_run_oshp ( struct acpi_bridge	*ab);
+
+static int acpi_add_slot_to_php_slots(
+	struct acpi_bridge	*ab,
+	int				bus_num,
+	acpi_handle		handle,
+	u32				adr,
+	u32				sun
+	)
+{
+	struct acpi_php_slot	*aps;
+	static long	samesun = -1;
+
+	aps = (struct acpi_php_slot *) kmalloc (sizeof(struct acpi_php_slot), GFP_KERNEL);
+	if (!aps) {
+		err ("acpi_shpchprm: alloc for aps fail\n");
+		return -1;
+	}
+	memset(aps, 0, sizeof(struct acpi_php_slot));
+
+	aps->handle = handle;
+	aps->bus = bus_num;
+	aps->dev = (adr >> 16) & 0xffff;
+	aps->fun = adr & 0xffff;
+	aps->sun = sun;
+
+	aps->next = ab->slots;	/* cling to the bridge */
+	aps->bridge = ab;
+	ab->slots = aps;
+
+	ab->scanned += 1;
+	if (!ab->_hpp)
+		acpi_get__hpp(ab);
+
+	acpi_run_oshp(ab);
+
+	if (sun != samesun) {
+		info("acpi_shpchprm:   Slot sun(%x) at s:b:d:f=0x%02x:%02x:%02x:%02x\n", aps->sun, ab->seg, 
+			aps->bus, aps->dev, aps->fun);
+		samesun = sun;
+	}
+	return 0;
+}
+
+static void acpi_get__hpp ( struct acpi_bridge	*ab)
+{
+	acpi_status		status;
+	u8			nui[4];
+	struct acpi_buffer	ret_buf = { 0, NULL};
+	union acpi_object	*ext_obj, *package;
+	u8			*path_name = acpi_path_name(ab->handle);
+	int			i, len = 0;
+
+	/* get _hpp */
+	status = acpi_evaluate_object(ab->handle, METHOD_NAME__HPP, NULL, &ret_buf);
+	switch (status) {
+	case AE_BUFFER_OVERFLOW:
+		ret_buf.pointer = kmalloc (ret_buf.length, GFP_KERNEL);
+		if (!ret_buf.pointer) {
+			err ("acpi_shpchprm:%s alloc for _HPP fail\n", path_name);
+			return;
+		}
+		status = acpi_evaluate_object(ab->handle, METHOD_NAME__HPP, NULL, &ret_buf);
+		if (ACPI_SUCCESS(status))
+			break;
+	default:
+		if (ACPI_FAILURE(status)) {
+			err("acpi_shpchprm:%s _HPP fail=0x%x\n", path_name, status);
+			return;
+		}
+	}
+
+	ext_obj = (union acpi_object *) ret_buf.pointer;
+	if (ext_obj->type != ACPI_TYPE_PACKAGE) {
+		err ("acpi_shpchprm:%s _HPP obj not a package\n", path_name);
+		goto free_and_return;
+	}
+
+	len = ext_obj->package.count;
+	package = (union acpi_object *) ret_buf.pointer;
+	for ( i = 0; (i < len) || (i < 4); i++) {
+		ext_obj = (union acpi_object *) &package->package.elements[i];
+		switch (ext_obj->type) {
+		case ACPI_TYPE_INTEGER:
+			nui[i] = (u8)ext_obj->integer.value;
+			break;
+		default:
+			err ("acpi_shpchprm:%s _HPP obj type incorrect\n", path_name);
+			goto free_and_return;
+		}
+	}
+
+	ab->_hpp = kmalloc (sizeof (struct acpi__hpp), GFP_KERNEL);
+	memset(ab->_hpp, 0, sizeof(struct acpi__hpp));
+
+	ab->_hpp->cache_line_size	= nui[0];
+	ab->_hpp->latency_timer		= nui[1];
+	ab->_hpp->enable_serr		= nui[2];
+	ab->_hpp->enable_perr		= nui[3];
+
+	dbg("  _HPP: cache_line_size=0x%x\n", ab->_hpp->cache_line_size);
+	dbg("  _HPP: latency timer  =0x%x\n", ab->_hpp->latency_timer);
+	dbg("  _HPP: enable SERR    =0x%x\n", ab->_hpp->enable_serr);
+	dbg("  _HPP: enable PERR    =0x%x\n", ab->_hpp->enable_perr);
+
+free_and_return:
+	kfree(ret_buf.pointer);
+}
+
+static void acpi_run_oshp ( struct acpi_bridge	*ab)
+{
+	acpi_status		status;
+	u8			*path_name = acpi_path_name(ab->handle);
+	struct acpi_buffer	ret_buf = { 0, NULL};
+
+	/* run OSHP */
+	status = acpi_evaluate_object(ab->handle, METHOD_NAME_OSHP, NULL, &ret_buf);
+	if (ACPI_FAILURE(status)) {
+		err("acpi_pciehprm:%s OSHP fails=0x%x\n", path_name, status);
+	} else
+		dbg("acpi_pciehprm:%s OSHP passes =0x%x\n", path_name, status);
+	return;
+}
+
+static acpi_status acpi_evaluate_crs(
+	acpi_handle		handle,
+	struct acpi_resource	**retbuf
+	)
+{
+	acpi_status		status;
+	struct acpi_buffer		crsbuf;
+	u8			*path_name = acpi_path_name(handle);
+
+	crsbuf.length  = 0;
+	crsbuf.pointer = NULL;
+
+	status = acpi_get_current_resources (handle, &crsbuf);
+
+	switch (status) {
+	case AE_BUFFER_OVERFLOW:
+		break;		/* found */
+	case AE_NOT_FOUND:
+		dbg("acpi_shpchprm:%s _CRS not found\n", path_name);
+		return status;
+	default:
+		err ("acpi_shpchprm:%s _CRS fail=0x%x\n", path_name, status);
+		return status;
+	}
+
+	crsbuf.pointer = kmalloc (crsbuf.length, GFP_KERNEL);
+	if (!crsbuf.pointer) {
+		err ("acpi_shpchprm: alloc %ld bytes for %s _CRS fail\n", (ulong)crsbuf.length, path_name);
+		return AE_NO_MEMORY;
+	}
+
+	status = acpi_get_current_resources (handle, &crsbuf);
+	if (ACPI_FAILURE(status)) {
+		err("acpi_shpchprm: %s _CRS fail=0x%x.\n", path_name, status);
+		kfree(crsbuf.pointer);
+		return status;
+	}
+
+	*retbuf = crsbuf.pointer;
+
+	return status;
+}
+
+static void free_pci_resource ( struct pci_resource	*aprh)
+{
+	struct pci_resource	*res, *next;
+
+	for (res = aprh; res; res = next) {
+		next = res->next;
+		kfree(res);
+	}
+}
+
+static void print_pci_resource ( struct pci_resource	*aprh)
+{
+	struct pci_resource	*res;
+
+	for (res = aprh; res; res = res->next)
+		dbg("        base= 0x%x length= 0x%x\n", res->base, res->length);
+}
+
+static void print_slot_resources( struct acpi_php_slot	*aps)
+{
+	if (aps->bus_head) {
+		dbg("    BUS Resources:\n");
+		print_pci_resource (aps->bus_head);
+	}
+
+	if (aps->io_head) {
+		dbg("    IO Resources:\n");
+		print_pci_resource (aps->io_head);
+	}
+
+	if (aps->mem_head) {
+		dbg("    MEM Resources:\n");
+		print_pci_resource (aps->mem_head);
+	}
+
+	if (aps->p_mem_head) {
+		dbg("    PMEM Resources:\n");
+		print_pci_resource (aps->p_mem_head);
+	}
+}
+
+static void print_pci_resources( struct acpi_bridge	*ab)
+{
+	if (ab->tbus_head) {
+		dbg("    Total BUS Resources:\n");
+		print_pci_resource (ab->tbus_head);
+	}
+	if (ab->bus_head) {
+		dbg("    BUS Resources:\n");
+		print_pci_resource (ab->bus_head);
+	}
+
+	if (ab->tio_head) {
+		dbg("    Total IO Resources:\n");
+		print_pci_resource (ab->tio_head);
+	}
+	if (ab->io_head) {
+		dbg("    IO Resources:\n");
+		print_pci_resource (ab->io_head);
+	}
+
+	if (ab->tmem_head) {
+		dbg("    Total MEM Resources:\n");
+		print_pci_resource (ab->tmem_head);
+	}
+	if (ab->mem_head) {
+		dbg("    MEM Resources:\n");
+		print_pci_resource (ab->mem_head);
+	}
+
+	if (ab->tp_mem_head) {
+		dbg("    Total PMEM Resources:\n");
+		print_pci_resource (ab->tp_mem_head);
+	}
+	if (ab->p_mem_head) {
+		dbg("    PMEM Resources:\n");
+		print_pci_resource (ab->p_mem_head);
+	}
+	if (ab->_hpp) {
+		dbg("    _HPP: cache_line_size=0x%x\n", ab->_hpp->cache_line_size);
+		dbg("    _HPP: latency timer  =0x%x\n", ab->_hpp->latency_timer);
+		dbg("    _HPP: enable SERR    =0x%x\n", ab->_hpp->enable_serr);
+		dbg("    _HPP: enable PERR    =0x%x\n", ab->_hpp->enable_perr);
+	}
+}
+
+static int shpchprm_delete_resource(
+	struct pci_resource **aprh,
+	ulong base,
+	ulong size)
+{
+	struct pci_resource *res;
+	struct pci_resource *prevnode;
+	struct pci_resource *split_node;
+	ulong tbase;
+
+	shpchp_resource_sort_and_combine(aprh);
+
+	for (res = *aprh; res; res = res->next) {
+		if (res->base > base)
+			continue;
+
+		if ((res->base + res->length) < (base + size))
+			continue;
+
+		if (res->base < base) {
+			tbase = base;
+
+			if ((res->length - (tbase - res->base)) < size)
+				continue;
+
+			split_node = (struct pci_resource *) kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
+			if (!split_node)
+				return -ENOMEM;
+
+			split_node->base = res->base;
+			split_node->length = tbase - res->base;
+			res->base = tbase;
+			res->length -= split_node->length;
+
+			split_node->next = res->next;
+			res->next = split_node;
+		}
+
+		if (res->length >= size) {
+			split_node = (struct pci_resource*) kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
+			if (!split_node)
+				return -ENOMEM;
+
+			split_node->base = res->base + size;
+			split_node->length = res->length - size;
+			res->length = size;
+
+			split_node->next = res->next;
+			res->next = split_node;
+		}
+
+		if (*aprh == res) {
+			*aprh = res->next;
+		} else {
+			prevnode = *aprh;
+			while (prevnode->next != res)
+				prevnode = prevnode->next;
+
+			prevnode->next = res->next;
+		}
+		res->next = NULL;
+		kfree(res);
+		break;
+	}
+
+	return 0;
+}
+
+static int shpchprm_delete_resources(
+	struct pci_resource **aprh,
+	struct pci_resource *this
+	)
+{
+	struct pci_resource *res;
+
+	for (res = this; res; res = res->next)
+		shpchprm_delete_resource(aprh, res->base, res->length);
+
+	return 0;
+}
+
+static int shpchprm_add_resource(
+	struct pci_resource **aprh,
+	ulong base,
+	ulong size)
+{
+	struct pci_resource *res;
+
+	for (res = *aprh; res; res = res->next) {
+		if ((res->base + res->length) == base) {
+			res->length += size;
+			size = 0L;
+			break;
+		}
+		if (res->next == *aprh)
+			break;
+	}
+
+	if (size) {
+		res = kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
+		if (!res) {
+			err ("acpi_shpchprm: alloc for res fail\n");
+			return -ENOMEM;
+		}
+		memset(res, 0, sizeof (struct pci_resource));
+
+		res->base = base;
+		res->length = size;
+		res->next = *aprh;
+		*aprh = res;
+	}
+
+	return 0;
+}
+
+static int shpchprm_add_resources(
+	struct pci_resource **aprh,
+	struct pci_resource *this
+	)
+{
+	struct pci_resource *res;
+	int	rc = 0;
+
+	for (res = this; res && !rc; res = res->next)
+		rc = shpchprm_add_resource(aprh, res->base, res->length);
+
+	return rc;
+}
+
+static void acpi_parse_io (
+	struct acpi_bridge		*ab,
+	union acpi_resource_data	*data
+	)
+{
+	struct acpi_resource_io	*dataio;
+	dataio = (struct acpi_resource_io *) data;
+
+	dbg("Io Resource\n");
+	dbg("  %d bit decode\n", ACPI_DECODE_16 == dataio->io_decode ? 16:10);
+	dbg("  Range minimum base: %08X\n", dataio->min_base_address);
+	dbg("  Range maximum base: %08X\n", dataio->max_base_address);
+	dbg("  Alignment: %08X\n", dataio->alignment);
+	dbg("  Range Length: %08X\n", dataio->range_length);
+}
+
+static void acpi_parse_fixed_io (
+	struct acpi_bridge		*ab,
+	union acpi_resource_data	*data
+	)
+{
+	struct acpi_resource_fixed_io  *datafio;
+	datafio = (struct acpi_resource_fixed_io *) data;
+
+	dbg("Fixed Io Resource\n");
+	dbg("  Range base address: %08X", datafio->base_address);
+	dbg("  Range length: %08X", datafio->range_length);
+}
+
+static void acpi_parse_address16_32 (
+	struct acpi_bridge		*ab,
+	union acpi_resource_data	*data,
+	acpi_resource_type		id
+	)
+{
+	/* 
+	 * acpi_resource_address16 == acpi_resource_address32
+	 * acpi_resource_address16 *data16 = (acpi_resource_address16 *) data;
+	 */
+	struct acpi_resource_address32 *data32 = (struct acpi_resource_address32 *) data;
+	struct pci_resource **aprh, **tprh;
+
+	if (id == ACPI_RSTYPE_ADDRESS16)
+		dbg("acpi_shpchprm:16-Bit Address Space Resource\n");
+	else
+		dbg("acpi_shpchprm:32-Bit Address Space Resource\n");
+
+	switch (data32->resource_type) {
+	case ACPI_MEMORY_RANGE: 
+		dbg("  Resource Type: Memory Range\n");
+		aprh = &ab->mem_head;
+		tprh = &ab->tmem_head;
+
+		switch (data32->attribute.memory.cache_attribute) {
+		case ACPI_NON_CACHEABLE_MEMORY:
+			dbg("  Type Specific: Noncacheable memory\n");
+			break; 
+		case ACPI_CACHABLE_MEMORY:
+			dbg("  Type Specific: Cacheable memory\n");
+			break; 
+		case ACPI_WRITE_COMBINING_MEMORY:
+			dbg("  Type Specific: Write-combining memory\n");
+			break; 
+		case ACPI_PREFETCHABLE_MEMORY:
+			aprh = &ab->p_mem_head;
+			dbg("  Type Specific: Prefetchable memory\n");
+			break; 
+		default:
+			dbg("  Type Specific: Invalid cache attribute\n");
+			break;
+		}
+
+		dbg("  Type Specific: Read%s\n", ACPI_READ_WRITE_MEMORY == data32->attribute.memory.read_write_attribute ? "/Write":" Only");
+		break;
+
+	case ACPI_IO_RANGE: 
+		dbg("  Resource Type: I/O Range\n");
+		aprh = &ab->io_head;
+		tprh = &ab->tio_head;
+
+		switch (data32->attribute.io.range_attribute) {
+		case ACPI_NON_ISA_ONLY_RANGES:
+			dbg("  Type Specific: Non-ISA Io Addresses\n");
+			break; 
+		case ACPI_ISA_ONLY_RANGES:
+			dbg("  Type Specific: ISA Io Addresses\n");
+			break; 
+		case ACPI_ENTIRE_RANGE:
+			dbg("  Type Specific: ISA and non-ISA Io Addresses\n");
+			break; 
+		default:
+			dbg("  Type Specific: Invalid range attribute\n");
+			break;
+		}
+		break;
+
+	case ACPI_BUS_NUMBER_RANGE: 
+		dbg("  Resource Type: Bus Number Range(fixed)\n");
+		/* fixup to be compatible with the rest of php driver */
+		data32->min_address_range++;
+		data32->address_length--;
+		aprh = &ab->bus_head;
+		tprh = &ab->tbus_head;
+		break; 
+	default: 
+		dbg("  Resource Type: Invalid resource type. Exiting.\n");
+		return;
+	}
+
+	dbg("  Resource %s\n", ACPI_CONSUMER == data32->producer_consumer ? "Consumer":"Producer");
+	dbg("  %s decode\n", ACPI_SUB_DECODE == data32->decode ? "Subtractive":"Positive");
+	dbg("  Min address is %s fixed\n", ACPI_ADDRESS_FIXED == data32->min_address_fixed ? "":"not");
+	dbg("  Max address is %s fixed\n", ACPI_ADDRESS_FIXED == data32->max_address_fixed ? "":"not");
+	dbg("  Granularity: %08X\n", data32->granularity);
+	dbg("  Address range min: %08X\n", data32->min_address_range);
+	dbg("  Address range max: %08X\n", data32->max_address_range);
+	dbg("  Address translation offset: %08X\n", data32->address_translation_offset);
+	dbg("  Address Length: %08X\n", data32->address_length);
+
+	if (0xFF != data32->resource_source.index) {
+		dbg("  Resource Source Index: %X\n", data32->resource_source.index);
+		/* dbg("  Resource Source: %s\n", data32->resource_source.string_ptr); */
+	}
+
+	shpchprm_add_resource(aprh, data32->min_address_range, data32->address_length);
+}
+
+static acpi_status acpi_parse_crs(
+	struct acpi_bridge	*ab,
+	struct acpi_resource	*crsbuf
+	)
+{
+	acpi_status		status = AE_OK;
+	struct acpi_resource	*resource = crsbuf;
+	u8			count = 0;
+	u8			done = 0;
+
+	while (!done) {
+		dbg("acpi_shpchprm: PCI bus 0x%x Resource structure %x.\n", ab->bus, count++);
+		switch (resource->id) {
+		case ACPI_RSTYPE_IRQ:
+			dbg("Irq -------- Resource\n");
+			break; 
+		case ACPI_RSTYPE_DMA:
+			dbg("DMA -------- Resource\n");
+			break; 
+		case ACPI_RSTYPE_START_DPF:
+			dbg("Start DPF -------- Resource\n");
+			break; 
+		case ACPI_RSTYPE_END_DPF:
+			dbg("End DPF -------- Resource\n");
+			break; 
+		case ACPI_RSTYPE_IO:
+			acpi_parse_io (ab, &resource->data);
+			break; 
+		case ACPI_RSTYPE_FIXED_IO:
+			acpi_parse_fixed_io (ab, &resource->data);
+			break; 
+		case ACPI_RSTYPE_VENDOR:
+			dbg("Vendor -------- Resource\n");
+			break; 
+		case ACPI_RSTYPE_END_TAG:
+			dbg("End_tag -------- Resource\n");
+			done = 1;
+			break; 
+		case ACPI_RSTYPE_MEM24:
+			dbg("Mem24 -------- Resource\n");
+			break; 
+		case ACPI_RSTYPE_MEM32:
+			dbg("Mem32 -------- Resource\n");
+			break; 
+		case ACPI_RSTYPE_FIXED_MEM32:
+			dbg("Fixed Mem32 -------- Resource\n");
+			break; 
+		case ACPI_RSTYPE_ADDRESS16:
+			acpi_parse_address16_32(ab, &resource->data, ACPI_RSTYPE_ADDRESS16);
+			break; 
+		case ACPI_RSTYPE_ADDRESS32:
+			acpi_parse_address16_32(ab, &resource->data, ACPI_RSTYPE_ADDRESS32);
+			break; 
+		case ACPI_RSTYPE_ADDRESS64:
+			info("Address64 -------- Resource unparsed\n");
+			break; 
+		case ACPI_RSTYPE_EXT_IRQ:
+			dbg("Ext Irq -------- Resource\n");
+			break; 
+		default:
+			dbg("Invalid -------- resource type 0x%x\n", resource->id);
+			break;
+		}
+
+		resource = (struct acpi_resource *) ((char *)resource + resource->length);
+	}
+
+	return status;
+}
+
+static acpi_status acpi_get_crs( struct acpi_bridge	*ab)
+{
+	acpi_status		status;
+	struct acpi_resource	*crsbuf;
+
+	status = acpi_evaluate_crs(ab->handle, &crsbuf);
+	if (ACPI_SUCCESS(status)) {
+		status = acpi_parse_crs(ab, crsbuf);
+		kfree(crsbuf);
+
+		shpchp_resource_sort_and_combine(&ab->bus_head);
+		shpchp_resource_sort_and_combine(&ab->io_head);
+		shpchp_resource_sort_and_combine(&ab->mem_head);
+		shpchp_resource_sort_and_combine(&ab->p_mem_head);
+
+		shpchprm_add_resources (&ab->tbus_head, ab->bus_head);
+		shpchprm_add_resources (&ab->tio_head, ab->io_head);
+		shpchprm_add_resources (&ab->tmem_head, ab->mem_head);
+		shpchprm_add_resources (&ab->tp_mem_head, ab->p_mem_head);
+	}
+
+	return status;
+}
+
+/* find acpi_bridge downword from ab.  */
+static struct acpi_bridge *
+find_acpi_bridge_by_bus(
+	struct acpi_bridge *ab,
+	int seg,
+	int bus		/* pdev->subordinate->number */
+	)
+{
+	struct acpi_bridge	*lab = NULL;
+
+	if (!ab)
+		return NULL;
+
+	if ((ab->bus == bus) && (ab->seg == seg))
+		return ab;
+
+	if (ab->child)
+		lab = find_acpi_bridge_by_bus(ab->child, seg, bus);
+
+	if (!lab)
+	if (ab->next)
+		lab = find_acpi_bridge_by_bus(ab->next, seg, bus);
+
+	return lab;
+}
+
+/*
+ * Build a device tree of ACPI PCI Bridges
+ */
+static void shpchprm_acpi_register_a_bridge (
+	struct acpi_bridge	**head,
+	struct acpi_bridge	*pab,	/* parent bridge to which child bridge is added */
+	struct acpi_bridge	*cab	/* child bridge to add */
+	)
+{
+	struct acpi_bridge	*lpab;
+	struct acpi_bridge	*lcab;
+
+	lpab = find_acpi_bridge_by_bus(*head, pab->seg, pab->bus);
+	if (!lpab) {
+		if (!(pab->type & BRIDGE_TYPE_HOST))
+			warn("PCI parent bridge s:b(%x:%x) not in list.\n", pab->seg, pab->bus);
+		pab->next = *head;
+		*head = pab;
+		lpab = pab;
+	}
+
+	if ((cab->type & BRIDGE_TYPE_HOST) && (pab == cab))
+		return;
+
+	lcab = find_acpi_bridge_by_bus(*head, cab->seg, cab->bus);
+	if (lcab) {
+		if ((pab->bus != lcab->parent->bus) || (lcab->bus != cab->bus))
+			err("PCI child bridge s:b(%x:%x) in list with diff parent.\n", cab->seg, cab->bus);
+		return;
+	} else
+		lcab = cab;
+
+	lcab->parent = lpab;
+	lcab->next = lpab->child;
+	lpab->child = lcab;
+}
+
+static acpi_status shpchprm_acpi_build_php_slots_callback(
+	acpi_handle	handle,
+	u32		Level,
+	void		*context,
+	void		**retval
+	)
+{
+	ulong		bus_num;
+	ulong		seg_num;
+	ulong		sun, adr;
+	ulong		padr = 0;
+	acpi_handle		phandle = NULL;
+	struct acpi_bridge	*pab = (struct acpi_bridge *)context;
+	struct acpi_bridge	*lab;
+	acpi_status		status;
+	u8			*path_name = acpi_path_name(handle);
+
+	/* get _SUN */
+	status = acpi_evaluate_integer(handle, METHOD_NAME__SUN, NULL, &sun);
+	switch(status) {
+	case AE_NOT_FOUND:
+		return AE_OK;
+	default:
+		if (ACPI_FAILURE(status)) {
+			err("acpi_shpchprm:%s _SUN fail=0x%x\n", path_name, status);
+			return status;
+		}
+	}
+
+	/* get _ADR. _ADR must exist if _SUN exists */
+	status = acpi_evaluate_integer(handle, METHOD_NAME__ADR, NULL, &adr);
+	if (ACPI_FAILURE(status)) {
+		err("acpi_shpchprm:%s _ADR fail=0x%x\n", path_name, status);
+		return status;
+	}
+
+	dbg("acpi_shpchprm:%s sun=0x%08x adr=0x%08x\n", path_name, (u32)sun, (u32)adr);
+
+	status = acpi_get_parent(handle, &phandle);
+	if (ACPI_FAILURE(status)) {
+		err("acpi_shpchprm:%s get_parent fail=0x%x\n", path_name, status);
+		return (status);
+	}
+
+	bus_num = pab->bus;
+	seg_num = pab->seg;
+
+	if (pab->bus == bus_num) {
+		lab = pab;
+	} else {
+		dbg("WARN: pab is not parent\n");
+		lab = find_acpi_bridge_by_bus(pab, seg_num, bus_num);
+		if (!lab) {
+			dbg("acpi_shpchprm: alloc new P2P bridge(%x) for sun(%08x)\n", (u32)bus_num, (u32)sun);
+			lab = (struct acpi_bridge *)kmalloc(sizeof(struct acpi_bridge), GFP_KERNEL);
+			if (!lab) {
+				err("acpi_shpchprm: alloc for ab fail\n");
+				return AE_NO_MEMORY;
+			}
+			memset(lab, 0, sizeof(struct acpi_bridge));
+
+			lab->handle = phandle;
+			lab->pbus = pab->bus;
+			lab->pdevice = (int)(padr >> 16) & 0xffff;
+			lab->pfunction = (int)(padr & 0xffff);
+			lab->bus = (int)bus_num;
+			lab->scanned = 0;
+			lab->type = BRIDGE_TYPE_P2P;
+
+			shpchprm_acpi_register_a_bridge (&acpi_bridges_head, pab, lab);
+		} else
+			dbg("acpi_shpchprm: found P2P bridge(%x) for sun(%08x)\n", (u32)bus_num, (u32)sun);
+	}
+
+	acpi_add_slot_to_php_slots(lab, (int)bus_num, handle, (u32)adr, (u32)sun);
+	return (status);
+}
+
+static int shpchprm_acpi_build_php_slots(
+	struct acpi_bridge	*ab,
+	u32			depth
+	)
+{
+	acpi_status	status;
+	u8		*path_name = acpi_path_name(ab->handle);
+
+	/* Walk down this pci bridge to get _SUNs if any behind P2P */
+	status = acpi_walk_namespace ( ACPI_TYPE_DEVICE,
+				ab->handle,
+				depth,
+				shpchprm_acpi_build_php_slots_callback,
+				ab,
+				NULL );
+	if (ACPI_FAILURE(status)) {
+		dbg("acpi_shpchprm:%s walk for _SUN on pci bridge seg:bus(%x:%x) fail=0x%x\n", path_name, ab->seg, ab->bus, status);
+		return -1;
+	}
+
+	return 0;
+}
+
+static void build_a_bridge(
+	struct acpi_bridge	*pab,
+	struct acpi_bridge	*ab
+	)
+{
+	u8		*path_name = acpi_path_name(ab->handle);
+
+	shpchprm_acpi_register_a_bridge (&acpi_bridges_head, pab, ab);
+
+	switch (ab->type) {
+	case BRIDGE_TYPE_HOST:
+		dbg("acpi_shpchprm: Registered PCI HOST Bridge(%02x)    on s:b:d:f(%02x:%02x:%02x:%02x) [%s]\n",
+			ab->bus, ab->seg, ab->pbus, ab->pdevice, ab->pfunction, path_name);
+		break;
+	case BRIDGE_TYPE_P2P:
+		dbg("acpi_shpchprm: Registered PCI  P2P Bridge(%02x-%02x) on s:b:d:f(%02x:%02x:%02x:%02x) [%s]\n",
+			ab->pbus, ab->bus, ab->seg, ab->pbus, ab->pdevice, ab->pfunction, path_name);
+		break;
+	};
+
+	/* build any immediate PHP slots under this pci bridge */
+	shpchprm_acpi_build_php_slots(ab, 1);
+}
+
+static struct acpi_bridge * add_p2p_bridge(
+	acpi_handle handle,
+	struct acpi_bridge	*pab,	/* parent */
+	ulong	adr
+	)
+{
+	struct acpi_bridge	*ab;
+	struct pci_dev	*pdev;
+	ulong		devnum, funcnum;
+	u8			*path_name = acpi_path_name(handle);
+
+	ab = (struct acpi_bridge *) kmalloc (sizeof(struct acpi_bridge), GFP_KERNEL);
+	if (!ab) {
+		err("acpi_shpchprm: alloc for ab fail\n");
+		return NULL;
+	}
+	memset(ab, 0, sizeof(struct acpi_bridge));
+
+	devnum = (adr >> 16) & 0xffff;
+	funcnum = adr & 0xffff;
+
+	pdev = pci_find_slot(pab->bus, PCI_DEVFN(devnum, funcnum));
+	if (!pdev || !pdev->subordinate) {
+		err("acpi_shpchprm:%s is not a P2P Bridge\n", path_name);
+		kfree(ab);
+		return NULL;
+	}
+
+	ab->handle = handle;
+	ab->seg = pab->seg;
+	ab->pbus = pab->bus;		/* or pdev->bus->number */
+	ab->pdevice = devnum;		/* or PCI_SLOT(pdev->devfn) */
+	ab->pfunction = funcnum;	/* or PCI_FUNC(pdev->devfn) */
+	ab->bus = pdev->subordinate->number;
+	ab->scanned = 0;
+	ab->type = BRIDGE_TYPE_P2P;
+
+	dbg("acpi_shpchprm: P2P(%x-%x) on pci=b:d:f(%x:%x:%x) acpi=b:d:f(%x:%x:%x) [%s]\n",
+		pab->bus, ab->bus, pdev->bus->number, PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn),
+		pab->bus, (u32)devnum, (u32)funcnum, path_name);
+
+	build_a_bridge(pab, ab);
+
+	return ab;
+}
+
+static acpi_status scan_p2p_bridge(
+	acpi_handle		handle,
+	u32			Level,
+	void			*context,
+	void			**retval
+	)
+{
+	struct acpi_bridge	*pab = (struct acpi_bridge *)context;
+	struct acpi_bridge	*ab;
+	acpi_status		status;
+	ulong		adr = 0;
+	u8			*path_name = acpi_path_name(handle);
+	ulong		devnum, funcnum;
+	struct pci_dev	*pdev;
+
+	/* get device, function */
+	status = acpi_evaluate_integer(handle, METHOD_NAME__ADR, NULL, &adr);
+	if (ACPI_FAILURE(status)) {
+		if (status != AE_NOT_FOUND)
+			err("acpi_shpchprm:%s _ADR fail=0x%x\n", path_name, status);
+		return AE_OK;
+	}
+
+	devnum = (adr >> 16) & 0xffff;
+	funcnum = adr & 0xffff;
+
+	pdev = pci_find_slot(pab->bus, PCI_DEVFN(devnum, funcnum));
+	if (!pdev)
+		return AE_OK;
+	if (!pdev->subordinate)
+		return AE_OK;
+
+	ab = add_p2p_bridge(handle, pab, adr);
+	if (ab) {
+		status = acpi_walk_namespace ( ACPI_TYPE_DEVICE,
+					handle,
+					(u32)1,
+					scan_p2p_bridge,
+					ab,
+					NULL);
+		if (ACPI_FAILURE(status))
+			dbg("acpi_shpchprm:%s find_p2p fail=0x%x\n", path_name, status);
+	}
+
+	return AE_OK;
+}
+
+static struct acpi_bridge * add_host_bridge(
+	acpi_handle handle,
+	ulong	segnum,
+	ulong	busnum
+	)
+{
+	ulong			adr = 0;
+	acpi_status		status;
+	struct acpi_bridge	*ab;
+	u8			*path_name = acpi_path_name(handle);
+
+	/* get device, function: host br adr is always 0000 though.  */
+	status = acpi_evaluate_integer(handle, METHOD_NAME__ADR, NULL, &adr);
+	if (ACPI_FAILURE(status)) {
+		err("acpi_shpchprm:%s _ADR fail=0x%x\n", path_name, status);
+		return NULL;
+	}
+	dbg("acpi_shpchprm: ROOT PCI seg(0x%x)bus(0x%x)dev(0x%x)func(0x%x) [%s]\n", (u32)segnum, (u32)busnum, 
+		(u32)(adr >> 16) & 0xffff, (u32)adr & 0xffff, path_name);
+
+	ab = (struct acpi_bridge *) kmalloc (sizeof(struct acpi_bridge), GFP_KERNEL);
+	if (!ab) {
+		err("acpi_shpchprm: alloc for ab fail\n");
+		return NULL;
+	}
+	memset(ab, 0, sizeof(struct acpi_bridge));
+
+	ab->handle = handle;
+	ab->seg = (int)segnum;
+	ab->bus = ab->pbus = (int)busnum;
+	ab->pdevice = (int)(adr >> 16) & 0xffff;
+	ab->pfunction = (int)(adr & 0xffff);
+	ab->scanned = 0;
+	ab->type = BRIDGE_TYPE_HOST;
+
+	/* get root pci bridge's current resources */
+	status = acpi_get_crs(ab);
+	if (ACPI_FAILURE(status)) {
+		err("acpi_shpchprm:%s evaluate _CRS fail=0x%x\n", path_name, status);
+		kfree(ab);
+		return NULL;
+	}
+	build_a_bridge(ab, ab);
+
+	return ab;
+}
+
+static acpi_status acpi_scan_from_root_pci_callback (
+	acpi_handle	handle,
+	u32			Level,
+	void		*context,
+	void		**retval
+	)
+{
+	ulong		segnum = 0;
+	ulong		busnum = 0;
+	acpi_status		status;
+	struct acpi_bridge	*ab;
+	u8			*path_name = acpi_path_name(handle);
+
+	/* get bus number of this pci root bridge */
+	status = acpi_evaluate_integer(handle, METHOD_NAME__SEG, NULL, &segnum);
+	if (ACPI_FAILURE(status)) {
+		if (status != AE_NOT_FOUND) {
+			err("acpi_shpchprm:%s evaluate _SEG fail=0x%x\n", path_name, status);
+			return status;
+		}
+		segnum = 0;
+	}
+
+	/* get bus number of this pci root bridge */
+	status = acpi_evaluate_integer(handle, METHOD_NAME__BBN, NULL, &busnum);
+	if (ACPI_FAILURE(status)) {
+		err("acpi_shpchprm:%s evaluate _BBN fail=0x%x\n", path_name, status);
+		return (status);
+	}
+
+	ab = add_host_bridge(handle, segnum, busnum);
+	if (ab) {
+		status = acpi_walk_namespace ( ACPI_TYPE_DEVICE,
+					handle,
+					1,
+					scan_p2p_bridge,
+					ab,
+					NULL);
+		if (ACPI_FAILURE(status))
+			dbg("acpi_shpchprm:%s find_p2p fail=0x%x\n", path_name, status);
+	}
+
+	return AE_OK;
+}
+
+static int shpchprm_acpi_scan_pci (void)
+{
+	acpi_status	status;
+
+	/*
+	 * TBD: traverse LDM device tree with the help of
+	 *  unified ACPI augmented for php device population.
+	 */
+	status = acpi_get_devices ( PCI_ROOT_HID_STRING,
+				acpi_scan_from_root_pci_callback,
+				NULL,
+				NULL );
+	if (ACPI_FAILURE(status)) {
+		err("acpi_shpchprm:get_device PCI ROOT HID fail=0x%x\n", status);
+		return -1;
+	}
+
+	return 0;
+}
+
+int shpchprm_init(enum php_ctlr_type ctlr_type)
+{
+	int	rc;
+
+	if (ctlr_type != PCI)
+		return -ENODEV;
+
+	dbg("shpchprm ACPI init <enter>\n");
+	acpi_bridges_head = NULL;
+
+	/* construct PCI bus:device tree of acpi_handles */
+	rc = shpchprm_acpi_scan_pci();
+	if (rc)
+		return rc;
+
+	dbg("shpchprm ACPI init %s\n", (rc)?"fail":"success");
+	return rc;
+}
+
+static void free_a_slot(struct acpi_php_slot *aps)
+{
+	dbg("        free a php func of slot(0x%02x) on PCI b:d:f=0x%02x:%02x:%02x\n", aps->sun, aps->bus, aps->dev, aps->fun);
+
+	free_pci_resource (aps->io_head);
+	free_pci_resource (aps->bus_head);
+	free_pci_resource (aps->mem_head);
+	free_pci_resource (aps->p_mem_head);
+
+	kfree(aps);
+}
+
+static void free_a_bridge( struct acpi_bridge	*ab)
+{
+	struct acpi_php_slot	*aps, *next;
+
+	switch (ab->type) {
+	case BRIDGE_TYPE_HOST:
+		dbg("Free ACPI PCI HOST Bridge(%x) [%s] on s:b:d:f(%x:%x:%x:%x)\n",
+			ab->bus, acpi_path_name(ab->handle), ab->seg, ab->pbus, ab->pdevice, ab->pfunction);
+		break;
+	case BRIDGE_TYPE_P2P:
+		dbg("Free ACPI PCI P2P Bridge(%x-%x) [%s] on s:b:d:f(%x:%x:%x:%x)\n",
+			ab->pbus, ab->bus, acpi_path_name(ab->handle), ab->seg, ab->pbus, ab->pdevice, ab->pfunction);
+		break;
+	};
+
+	/* free slots first */
+	for (aps = ab->slots; aps; aps = next) {
+		next = aps->next;
+		free_a_slot(aps);
+	}
+
+	free_pci_resource (ab->io_head);
+	free_pci_resource (ab->tio_head);
+	free_pci_resource (ab->bus_head);
+	free_pci_resource (ab->tbus_head);
+	free_pci_resource (ab->mem_head);
+	free_pci_resource (ab->tmem_head);
+	free_pci_resource (ab->p_mem_head);
+	free_pci_resource (ab->tp_mem_head);
+
+	kfree(ab);
+}
+
+static void shpchprm_free_bridges ( struct acpi_bridge	*ab)
+{
+	if (ab->child)
+		shpchprm_free_bridges (ab->child);
+
+	if (ab->next)
+		shpchprm_free_bridges (ab->next);
+
+	free_a_bridge(ab);
+}
+
+void shpchprm_cleanup(void)
+{
+	shpchprm_free_bridges (acpi_bridges_head);
+}
+
+static int get_number_of_slots (
+	struct acpi_bridge	*ab,
+	int				selfonly
+	)
+{
+	struct acpi_php_slot	*aps;
+	int	prev_slot = -1;
+	int	slot_num = 0;
+
+	for ( aps = ab->slots; aps; aps = aps->next)
+		if (aps->dev != prev_slot) {
+			prev_slot = aps->dev;
+			slot_num++;
+		}
+
+	if (ab->child)
+		slot_num += get_number_of_slots (ab->child, 0);
+
+	if (selfonly)
+		return slot_num;
+
+	if (ab->next)
+		slot_num += get_number_of_slots (ab->next, 0);
+
+	return slot_num;
+}
+
+static int print_acpi_resources (struct acpi_bridge	*ab)
+{
+	struct acpi_php_slot	*aps;
+	int	i;
+
+	switch (ab->type) {
+	case BRIDGE_TYPE_HOST:
+		dbg("PCI HOST Bridge (%x) [%s]\n", ab->bus, acpi_path_name(ab->handle));
+		break;
+	case BRIDGE_TYPE_P2P:
+		dbg("PCI P2P Bridge (%x-%x) [%s]\n", ab->pbus, ab->bus, acpi_path_name(ab->handle));
+		break;
+	};
+
+	print_pci_resources (ab);
+
+	for ( i = -1, aps = ab->slots; aps; aps = aps->next) {
+		if (aps->dev == i)
+			continue;
+		dbg("  Slot sun(%x) s:b:d:f(%02x:%02x:%02x:%02x)\n", aps->sun, aps->seg, aps->bus, aps->dev, aps->fun);
+		print_slot_resources(aps);
+		i = aps->dev;
+	}
+
+	if (ab->child)
+		print_acpi_resources (ab->child);
+
+	if (ab->next)
+		print_acpi_resources (ab->next);
+
+	return 0;
+}
+
+int shpchprm_print_pirt(void)
+{
+	dbg("SHPCHPRM ACPI Slots\n");
+	print_acpi_resources (acpi_bridges_head);
+	return 0;
+}
+
+static struct acpi_php_slot * get_acpi_slot (
+	struct acpi_bridge *ab,
+	u32 sun
+	)
+{
+	struct acpi_php_slot	*aps = NULL;
+
+	for ( aps = ab->slots; aps; aps = aps->next)
+		if (aps->sun == sun)
+			return aps;
+
+	if (!aps && ab->child) {
+		aps = (struct acpi_php_slot *)get_acpi_slot (ab->child, sun);
+		if (aps)
+			return aps;
+	}
+
+	if (!aps && ab->next) {
+		aps = (struct acpi_php_slot *)get_acpi_slot (ab->next, sun);
+		if (aps)
+			return aps;
+	}
+
+	return aps;
+
+}
+
+void * shpchprm_get_slot(struct slot *slot)
+{
+	struct acpi_bridge	*ab = acpi_bridges_head;
+	struct acpi_php_slot	*aps = get_acpi_slot (ab, slot->number);
+
+	aps->slot = slot;
+
+	dbg("Got acpi slot sun(%x): s:b:d:f(%x:%x:%x:%x)\n", aps->sun, aps->seg, aps->bus, aps->dev, aps->fun);
+
+	return (void *)aps;
+}
+
+static void shpchprm_dump_func_res( struct pci_func *fun)
+{
+	struct pci_func *func = fun;
+
+	if (func->bus_head) {
+		dbg(":    BUS Resources:\n");
+		print_pci_resource (func->bus_head);
+	}
+	if (func->io_head) {
+		dbg(":    IO Resources:\n");
+		print_pci_resource (func->io_head);
+	}
+	if (func->mem_head) {
+		dbg(":    MEM Resources:\n");
+		print_pci_resource (func->mem_head);
+	}
+	if (func->p_mem_head) {
+		dbg(":    PMEM Resources:\n");
+		print_pci_resource (func->p_mem_head);
+	}
+}
+
+static void shpchprm_dump_ctrl_res( struct controller *ctlr)
+{
+	struct controller *ctrl = ctlr;
+
+	if (ctrl->bus_head) {
+		dbg(":    BUS Resources:\n");
+		print_pci_resource (ctrl->bus_head);
+	}
+	if (ctrl->io_head) {
+		dbg(":    IO Resources:\n");
+		print_pci_resource (ctrl->io_head);
+	}
+	if (ctrl->mem_head) {
+		dbg(":    MEM Resources:\n");
+		print_pci_resource (ctrl->mem_head);
+	}
+	if (ctrl->p_mem_head) {
+		dbg(":    PMEM Resources:\n");
+		print_pci_resource (ctrl->p_mem_head);
+	}
+}
+
+static int shpchprm_get_used_resources (
+	struct controller *ctrl,
+	struct pci_func *func
+	)
+{
+	return shpchp_save_used_resources (ctrl, func, !DISABLE_CARD);
+}
+
+static int configure_existing_function(
+	struct controller *ctrl,
+	struct pci_func *func
+	)
+{
+	int rc;
+
+	/* see how much resources the func has used. */
+	rc = shpchprm_get_used_resources (ctrl, func);
+
+	if (!rc) {
+		/* subtract the resources used by the func from ctrl resources */
+		rc  = shpchprm_delete_resources (&ctrl->bus_head, func->bus_head);
+		rc |= shpchprm_delete_resources (&ctrl->io_head, func->io_head);
+		rc |= shpchprm_delete_resources (&ctrl->mem_head, func->mem_head);
+		rc |= shpchprm_delete_resources (&ctrl->p_mem_head, func->p_mem_head);
+		if (rc)
+			warn("aCEF: cannot del used resources\n");
+	} else
+		err("aCEF: cannot get used resources\n");
+
+	return rc;
+}
+
+static int bind_pci_resources_to_slots ( struct controller *ctrl)
+{
+	struct pci_func *func;
+	int busn = ctrl->bus;
+	int devn, funn;
+	u32	vid;
+
+	for (devn = 0; devn < 32; devn++) {
+		for (funn = 0; funn < 8; funn++) {
+			if (devn == ctrl->device && funn == ctrl->function)
+				continue;
+			/* find out if this entry is for an occupied slot */
+			vid = 0xFFFFFFFF;
+			pci_bus_read_config_dword(ctrl->pci_bus, PCI_DEVFN(devn, funn), PCI_VENDOR_ID, &vid);
+
+			if (vid != 0xFFFFFFFF) {
+				func = shpchp_slot_find(busn, devn, funn);
+				if (!func)
+					continue;
+				configure_existing_function(ctrl, func);
+				dbg("aCCF:existing PCI 0x%x Func ResourceDump\n", ctrl->bus);
+				shpchprm_dump_func_res(func);
+			}
+		}
+	}
+
+	return 0;
+}
+
+static int bind_pci_resources(
+	struct controller 	*ctrl,
+	struct acpi_bridge	*ab
+	)
+{
+	int	status = 0;
+
+	if (ab->bus_head) {
+		dbg("bapr:  BUS Resources add on PCI 0x%x\n", ab->bus);
+		status = shpchprm_add_resources (&ctrl->bus_head, ab->bus_head);
+		if (shpchprm_delete_resources (&ab->bus_head, ctrl->bus_head))
+			warn("bapr:  cannot sub BUS Resource on PCI 0x%x\n", ab->bus);
+		if (status) {
+			err("bapr:  BUS Resource add on PCI 0x%x: fail=0x%x\n", ab->bus, status);
+			return status;
+		}
+	} else
+		info("bapr:  No BUS Resource on PCI 0x%x.\n", ab->bus);
+
+	if (ab->io_head) {
+		dbg("bapr:  IO Resources add on PCI 0x%x\n", ab->bus);
+		status = shpchprm_add_resources (&ctrl->io_head, ab->io_head);
+		if (shpchprm_delete_resources (&ab->io_head, ctrl->io_head))
+			warn("bapr:  cannot sub IO Resource on PCI 0x%x\n", ab->bus);
+		if (status) {
+			err("bapr:  IO Resource add on PCI 0x%x: fail=0x%x\n", ab->bus, status);
+			return status;
+		}
+	} else
+		info("bapr:  No  IO Resource on PCI 0x%x.\n", ab->bus);
+
+	if (ab->mem_head) {
+		dbg("bapr:  MEM Resources add on PCI 0x%x\n", ab->bus);
+		status = shpchprm_add_resources (&ctrl->mem_head, ab->mem_head);
+		if (shpchprm_delete_resources (&ab->mem_head, ctrl->mem_head))
+			warn("bapr:  cannot sub MEM Resource on PCI 0x%x\n", ab->bus);
+		if (status) {
+			err("bapr:  MEM Resource add on PCI 0x%x: fail=0x%x\n", ab->bus, status);
+			return status;
+		}
+	} else
+		info("bapr:  No MEM Resource on PCI 0x%x.\n", ab->bus);
+
+	if (ab->p_mem_head) {
+		dbg("bapr:  PMEM Resources add on PCI 0x%x\n", ab->bus);
+		status = shpchprm_add_resources (&ctrl->p_mem_head, ab->p_mem_head);
+		if (shpchprm_delete_resources (&ab->p_mem_head, ctrl->p_mem_head))
+			warn("bapr:  cannot sub PMEM Resource on PCI 0x%x\n", ab->bus);
+		if (status) {
+			err("bapr:  PMEM Resource add on PCI 0x%x: fail=0x%x\n", ab->bus, status);
+			return status;
+		}
+	} else
+		info("bapr:  No PMEM Resource on PCI 0x%x.\n", ab->bus);
+
+	return status;
+}
+
+static int no_pci_resources( struct acpi_bridge *ab)
+{
+	return !(ab->p_mem_head || ab->mem_head || ab->io_head || ab->bus_head);
+}
+
+static int find_pci_bridge_resources (
+	struct controller *ctrl,
+	struct acpi_bridge *ab
+	)
+{
+	int	rc = 0;
+	struct pci_func func;
+
+	memset(&func, 0, sizeof(struct pci_func));
+
+	func.bus = ab->pbus;
+	func.device = ab->pdevice;
+	func.function = ab->pfunction;
+	func.is_a_board = 1;
+
+	/* Get used resources for this PCI bridge */
+	rc = shpchp_save_used_resources (ctrl, &func, !DISABLE_CARD);
+
+	ab->io_head = func.io_head;
+	ab->mem_head = func.mem_head;
+	ab->p_mem_head = func.p_mem_head;
+	ab->bus_head = func.bus_head;
+	if (ab->bus_head)
+		shpchprm_delete_resource(&ab->bus_head, ctrl->bus, 1);
+
+	return rc;
+}
+
+static int get_pci_resources_from_bridge(
+	struct controller *ctrl,
+	struct acpi_bridge *ab
+	)
+{
+	int	rc = 0;
+
+	dbg("grfb:  Get Resources for PCI 0x%x from actual PCI bridge 0x%x.\n", ctrl->bus, ab->bus);
+
+	rc = find_pci_bridge_resources (ctrl, ab);
+
+	shpchp_resource_sort_and_combine(&ab->bus_head);
+	shpchp_resource_sort_and_combine(&ab->io_head);
+	shpchp_resource_sort_and_combine(&ab->mem_head);
+	shpchp_resource_sort_and_combine(&ab->p_mem_head);
+
+	shpchprm_add_resources (&ab->tbus_head, ab->bus_head);
+	shpchprm_add_resources (&ab->tio_head, ab->io_head);
+	shpchprm_add_resources (&ab->tmem_head, ab->mem_head);
+	shpchprm_add_resources (&ab->tp_mem_head, ab->p_mem_head);
+
+	return rc;
+}
+
+static int get_pci_resources(
+	struct controller	*ctrl,
+	struct acpi_bridge	*ab
+	)
+{
+	int	rc = 0;
+
+	if (no_pci_resources(ab)) {
+		dbg("spbr:PCI 0x%x has no resources. Get parent resources.\n", ab->bus);
+		rc = get_pci_resources_from_bridge(ctrl, ab);
+	}
+
+	return rc;
+}
+
+int shpchprm_get_physical_slot_number(struct controller *ctrl, u32 *sun, u8 busnum, u8 devnum)
+{
+	int offset = devnum - ctrl->slot_device_offset;
+
+	dbg("%s: ctrl->slot_num_inc %d, offset %d\n", __FUNCTION__, ctrl->slot_num_inc, offset);
+	*sun = (u8) (ctrl->first_slot + ctrl->slot_num_inc *offset);
+	return 0;
+}
+
+/*
+ * Get resources for this ctrl.
+ *  1. get total resources from ACPI _CRS or bridge (this ctrl)
+ *  2. find used resources of existing adapters
+ *	3. subtract used resources from total resources
+ */
+int shpchprm_find_available_resources( struct controller *ctrl)
+{
+	int rc = 0;
+	struct acpi_bridge	*ab;
+
+	ab = find_acpi_bridge_by_bus(acpi_bridges_head, ctrl->seg, ctrl->pci_dev->subordinate->number);
+	if (!ab) {
+		err("pfar:cannot locate acpi bridge of PCI 0x%x.\n", ctrl->pci_dev->subordinate->number);
+		return -1;
+	}
+	if (no_pci_resources(ab)) {
+		rc = get_pci_resources(ctrl, ab);
+		if (rc) {
+			err("pfar:cannot get pci resources of PCI 0x%x.\n",ctrl->pci_dev->subordinate->number);
+			return -1;
+		}
+	}
+
+	rc = bind_pci_resources(ctrl, ab);
+	dbg("pfar:pre-Bind PCI 0x%x Ctrl Resource Dump\n", ctrl->pci_dev->subordinate->number);
+	shpchprm_dump_ctrl_res(ctrl);
+
+	bind_pci_resources_to_slots (ctrl);
+
+	dbg("pfar:post-Bind PCI 0x%x Ctrl Resource Dump\n", ctrl->pci_dev->subordinate->number);
+	shpchprm_dump_ctrl_res(ctrl);
+
+	return rc;
+}
+
+int shpchprm_set_hpp(
+	struct controller *ctrl,
+	struct pci_func *func,
+	u8	card_type
+	)
+{
+	struct acpi_bridge	*ab;
+	struct pci_bus lpci_bus, *pci_bus;
+	int				rc = 0;
+	unsigned int	devfn;
+	u8				cls= 0x08;	/* default cache line size	*/
+	u8				lt = 0x40;	/* default latency timer	*/
+	u8				ep = 0;
+	u8				es = 0;
+
+	memcpy(&lpci_bus, ctrl->pci_bus, sizeof(lpci_bus));
+	pci_bus = &lpci_bus;
+	pci_bus->number = func->bus;
+	devfn = PCI_DEVFN(func->device, func->function);
+
+	ab = find_acpi_bridge_by_bus(acpi_bridges_head, ctrl->seg, ctrl->bus);
+
+	if (ab) {
+		if (ab->_hpp) {
+			lt  = (u8)ab->_hpp->latency_timer;
+			cls = (u8)ab->_hpp->cache_line_size;
+			ep  = (u8)ab->_hpp->enable_perr;
+			es  = (u8)ab->_hpp->enable_serr;
+		} else
+			dbg("_hpp: no _hpp for B/D/F=%#x/%#x/%#x. use default value\n", func->bus, func->device, func->function);
+	} else
+		dbg("_hpp: no acpi bridge for B/D/F = %#x/%#x/%#x. use default value\n", func->bus, func->device, func->function);
+
+
+	if (card_type == PCI_HEADER_TYPE_BRIDGE) {
+		/* set subordinate Latency Timer */
+		rc |= pci_bus_write_config_byte(pci_bus, devfn, PCI_SEC_LATENCY_TIMER, lt);
+	}
+
+	/* set base Latency Timer */
+	rc |= pci_bus_write_config_byte(pci_bus, devfn, PCI_LATENCY_TIMER, lt);
+	dbg("  set latency timer  =0x%02x: %x\n", lt, rc);
+
+	rc |= pci_bus_write_config_byte(pci_bus, devfn, PCI_CACHE_LINE_SIZE, cls);
+	dbg("  set cache_line_size=0x%02x: %x\n", cls, rc);
+
+	return rc;
+}
+
+void shpchprm_enable_card(
+	struct controller *ctrl,
+	struct pci_func *func,
+	u8 card_type)
+{
+	u16 command, cmd, bcommand, bcmd;
+	struct pci_bus lpci_bus, *pci_bus;
+	struct acpi_bridge	*ab;
+	unsigned int devfn;
+	int rc;
+
+	memcpy(&lpci_bus, ctrl->pci_bus, sizeof(lpci_bus));
+	pci_bus = &lpci_bus;
+	pci_bus->number = func->bus;
+	devfn = PCI_DEVFN(func->device, func->function);
+
+	rc = pci_bus_read_config_word(pci_bus, devfn, PCI_COMMAND, &command);
+
+	if (card_type == PCI_HEADER_TYPE_BRIDGE) {
+		rc = pci_bus_read_config_word(pci_bus, devfn, PCI_BRIDGE_CONTROL, &bcommand);
+	}
+
+	cmd = command  = command | PCI_COMMAND_MASTER | PCI_COMMAND_INVALIDATE
+		| PCI_COMMAND_IO | PCI_COMMAND_MEMORY;
+	bcmd = bcommand  = bcommand | PCI_BRIDGE_CTL_NO_ISA;
+
+	ab = find_acpi_bridge_by_bus(acpi_bridges_head, ctrl->seg, ctrl->bus);
+	if (ab) {
+		if (ab->_hpp) {
+			if (ab->_hpp->enable_perr) {
+				command |= PCI_COMMAND_PARITY;
+				bcommand |= PCI_BRIDGE_CTL_PARITY;
+			} else {
+				command &= ~PCI_COMMAND_PARITY;
+				bcommand &= ~PCI_BRIDGE_CTL_PARITY;
+			}
+			if (ab->_hpp->enable_serr) {
+				command |= PCI_COMMAND_SERR;
+				bcommand |= PCI_BRIDGE_CTL_SERR;
+			} else {
+				command &= ~PCI_COMMAND_SERR;
+				bcommand &= ~PCI_BRIDGE_CTL_SERR;
+			}
+		} else
+			dbg("no _hpp for B/D/F = %#x/%#x/%#x.\n", func->bus, func->device, func->function);
+	} else
+		dbg("no acpi bridge for B/D/F = %#x/%#x/%#x.\n", func->bus, func->device, func->function);
+
+	if (command != cmd) {
+		rc = pci_bus_write_config_word(pci_bus, devfn, PCI_COMMAND, command);
+	}
+	if ((card_type == PCI_HEADER_TYPE_BRIDGE) && (bcommand != bcmd)) {
+		rc = pci_bus_write_config_word(pci_bus, devfn, PCI_BRIDGE_CONTROL, bcommand);
+	}
+}
+
--- diff/drivers/pci/hotplug/shpchprm_legacy.c	1970-01-01 01:00:00.000000000 +0100
+++ source/drivers/pci/hotplug/shpchprm_legacy.c	2004-02-23 13:56:44.000000000 +0000
@@ -0,0 +1,474 @@
+/*
+ * SHPCHPRM Legacy: PHP Resource Manager for Non-ACPI/Legacy platform
+ *
+ * Copyright (C) 1995,2001 Compaq Computer Corporation
+ * Copyright (C) 2001 Greg Kroah-Hartman (greg@kroah.com)
+ * Copyright (C) 2001 IBM Corp.
+ * Copyright (C) 2003-2004 Intel Corporation
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Send feedback to <greg@kroah.com>,<dely.l.sy@intel.com>
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <asm/uaccess.h>
+#ifdef CONFIG_IA64
+#include <asm/iosapic.h>
+#endif
+#include "shpchp.h"
+#include "shpchprm.h"
+#include "shpchprm_legacy.h"
+
+static void *shpchp_rom_start;
+static u16 unused_IRQ;
+
+void shpchprm_cleanup()
+{
+	if (shpchp_rom_start)
+		iounmap(shpchp_rom_start);
+}
+
+int shpchprm_print_pirt()
+{
+	return 0;
+}
+
+void * shpchprm_get_slot(struct slot *slot)
+{
+	return NULL;
+}
+
+int shpchprm_get_physical_slot_number(struct controller *ctrl, u32 *sun, u8 busnum, u8 devnum)
+{
+	int	offset = devnum - ctrl->slot_device_offset;
+
+	*sun = (u8) (ctrl->first_slot + ctrl->slot_num_inc * offset);
+	return 0;
+}
+
+/* Find the Hot Plug Resource Table in the specified region of memory */
+static void *detect_HRT_floating_pointer(void *begin, void *end)
+{
+	void *fp;
+	void *endp;
+	u8 temp1, temp2, temp3, temp4;
+	int status = 0;
+
+	endp = (end - sizeof(struct hrt) + 1);
+
+	for (fp = begin; fp <= endp; fp += 16) {
+		temp1 = readb(fp + SIG0);
+		temp2 = readb(fp + SIG1);
+		temp3 = readb(fp + SIG2);
+		temp4 = readb(fp + SIG3);
+		if (temp1 == '$' && temp2 == 'H' && temp3 == 'R' && temp4 == 'T') {
+			status = 1;
+			break;
+		}
+	}
+
+	if (!status)
+		fp = NULL;
+
+	dbg("Discovered Hotplug Resource Table at %p\n", fp);
+	return fp;
+}
+
+#if link_available
+/*
+ *  Links available memory, IO, and IRQ resources for programming
+ *  devices which may be added to the system
+ *
+ *  Returns 0 if success
+ */
+static int
+link_available_resources (
+	struct controller *ctrl,
+	struct pci_func *func,
+	int index )
+{
+	return shpchp_save_used_resources (ctrl, func, !DISABLE_CARD);
+}
+#endif
+
+/*
+ * shpchprm_find_available_resources
+ *
+ *  Finds available memory, IO, and IRQ resources for programming
+ *  devices which may be added to the system
+ *  this function is for hot plug ADD!
+ *
+ * returns 0 if success
+ */
+int shpchprm_find_available_resources(struct controller *ctrl)
+{
+	u8 populated_slot;
+	u8 bridged_slot;
+	void *one_slot;
+	struct pci_func *func = NULL;
+	int i = 10, index = 0;
+	u32 temp_dword, rc;
+	ulong temp_ulong;
+	struct pci_resource *mem_node;
+	struct pci_resource *p_mem_node;
+	struct pci_resource *io_node;
+	struct pci_resource *bus_node;
+	void *rom_resource_table;
+	struct pci_bus lpci_bus, *pci_bus;
+	u8 cfgspc_irq, temp;
+
+	memcpy(&lpci_bus, ctrl->pci_bus, sizeof(lpci_bus));
+	pci_bus = &lpci_bus;
+	rom_resource_table = detect_HRT_floating_pointer(shpchp_rom_start, shpchp_rom_start + 0xffff);
+	dbg("rom_resource_table = %p\n", rom_resource_table);
+	if (rom_resource_table == NULL)
+		return -ENODEV;
+
+	/* Sum all resources and setup resource maps */
+	unused_IRQ = readl(rom_resource_table + UNUSED_IRQ);
+	dbg("unused_IRQ = %x\n", unused_IRQ);
+
+	temp = 0;
+	while (unused_IRQ) {
+		if (unused_IRQ & 1) {
+			shpchp_disk_irq = temp;
+			break;
+		}
+		unused_IRQ = unused_IRQ >> 1;
+		temp++;
+	}
+
+	dbg("shpchp_disk_irq= %d\n", shpchp_disk_irq);
+	unused_IRQ = unused_IRQ >> 1;
+	temp++;
+
+	while (unused_IRQ) {
+		if (unused_IRQ & 1) {
+			shpchp_nic_irq = temp;
+			break;
+		}
+		unused_IRQ = unused_IRQ >> 1;
+		temp++;
+	}
+
+	dbg("shpchp_nic_irq= %d\n", shpchp_nic_irq);
+	unused_IRQ = readl(rom_resource_table + PCIIRQ);
+
+	temp = 0;
+
+	pci_read_config_byte(ctrl->pci_dev, PCI_INTERRUPT_LINE, &cfgspc_irq);
+
+	if (!shpchp_nic_irq) {
+		shpchp_nic_irq = cfgspc_irq;
+	}
+
+	if (!shpchp_disk_irq) {
+		shpchp_disk_irq = cfgspc_irq;
+	}
+
+	dbg("shpchp_disk_irq, shpchp_nic_irq= %d, %d\n", shpchp_disk_irq, shpchp_nic_irq);
+
+	one_slot = rom_resource_table + sizeof(struct hrt);
+
+	i = readb(rom_resource_table + NUMBER_OF_ENTRIES);
+	dbg("number_of_entries = %d\n", i);
+
+	if (!readb(one_slot + SECONDARY_BUS))
+		return (1);
+
+	dbg("dev|IO base|length|MEMbase|length|PM base|length|PB SB MB\n");
+
+	while (i && readb(one_slot + SECONDARY_BUS)) {
+		u8 dev_func = readb(one_slot + DEV_FUNC);
+		u8 primary_bus = readb(one_slot + PRIMARY_BUS);
+		u8 secondary_bus = readb(one_slot + SECONDARY_BUS);
+		u8 max_bus = readb(one_slot + MAX_BUS);
+		u16 io_base = readw(one_slot + IO_BASE);
+		u16 io_length = readw(one_slot + IO_LENGTH);
+		u16 mem_base = readw(one_slot + MEM_BASE);
+		u16 mem_length = readw(one_slot + MEM_LENGTH);
+		u16 pre_mem_base = readw(one_slot + PRE_MEM_BASE);
+		u16 pre_mem_length = readw(one_slot + PRE_MEM_LENGTH);
+
+		dbg("%2.2x |  %4.4x | %4.4x |  %4.4x | %4.4x |  %4.4x | %4.4x |%2.2x %2.2x %2.2x\n",
+				dev_func, io_base, io_length, mem_base, mem_length, pre_mem_base, pre_mem_length,
+				primary_bus, secondary_bus, max_bus);
+
+		/* If this entry isn't for our controller's bus, ignore it */
+		if (primary_bus != ctrl->slot_bus) {
+			i--;
+			one_slot += sizeof(struct slot_rt);
+			continue;
+		}
+		/* find out if this entry is for an occupied slot */
+		temp_dword = 0xFFFFFFFF;
+		pci_bus->number = primary_bus;
+		pci_bus_read_config_dword(pci_bus, dev_func, PCI_VENDOR_ID, &temp_dword);
+
+		dbg("temp_D_word = %x\n", temp_dword);
+
+		if (temp_dword != 0xFFFFFFFF) {
+			index = 0;
+			func = shpchp_slot_find(primary_bus, dev_func >> 3, 0);
+
+			while (func && (func->function != (dev_func & 0x07))) {
+				dbg("func = %p b:d:f(%x:%x:%x)\n", func, primary_bus, dev_func >> 3, index);
+				func = shpchp_slot_find(primary_bus, dev_func >> 3, index++);
+			}
+
+			/* If we can't find a match, skip this table entry */
+			if (!func) {
+				i--;
+				one_slot += sizeof(struct slot_rt);
+				continue;
+			}
+			/* this may not work and shouldn't be used */
+			if (secondary_bus != primary_bus)
+				bridged_slot = 1;
+			else
+				bridged_slot = 0;
+
+			populated_slot = 1;
+		} else {
+			populated_slot = 0;
+			bridged_slot = 0;
+		}
+		dbg("slot populated =%s \n", populated_slot?"yes":"no");
+
+		/* If we've got a valid IO base, use it */
+
+		temp_ulong = io_base + io_length;
+
+		if ((io_base) && (temp_ulong <= 0x10000)) {
+			io_node = (struct pci_resource *) kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
+			if (!io_node)
+				return -ENOMEM;
+
+			io_node->base = (ulong)io_base;
+			io_node->length = (ulong)io_length;
+			dbg("found io_node(base, length) = %x, %x\n", io_node->base, io_node->length);
+
+			if (!populated_slot) {
+				io_node->next = ctrl->io_head;
+				ctrl->io_head = io_node;
+			} else {
+				io_node->next = func->io_head;
+				func->io_head = io_node;
+			}
+		}
+
+		/* If we've got a valid memory base, use it */
+		temp_ulong = mem_base + mem_length;
+		if ((mem_base) && (temp_ulong <= 0x10000)) {
+			mem_node = (struct pci_resource *) kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
+			if (!mem_node)
+				return -ENOMEM;
+
+			mem_node->base = (ulong)mem_base << 16;
+			mem_node->length = (ulong)(mem_length << 16);
+			dbg("found mem_node(base, length) = %x, %x\n", mem_node->base, mem_node->length);
+
+			if (!populated_slot) {
+				mem_node->next = ctrl->mem_head;
+				ctrl->mem_head = mem_node;
+			} else {
+				mem_node->next = func->mem_head;
+				func->mem_head = mem_node;
+			}
+		}
+
+		/*
+		 * If we've got a valid prefetchable memory base, and
+		 * the base + length isn't greater than 0xFFFF
+		 */
+		temp_ulong = pre_mem_base + pre_mem_length;
+		if ((pre_mem_base) && (temp_ulong <= 0x10000)) {
+			p_mem_node = (struct pci_resource *) kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
+			if (!p_mem_node)
+				return -ENOMEM;
+
+			p_mem_node->base = (ulong)pre_mem_base << 16;
+			p_mem_node->length = (ulong)pre_mem_length << 16;
+			dbg("found p_mem_node(base, length) = %x, %x\n", p_mem_node->base, p_mem_node->length);
+
+			if (!populated_slot) {
+				p_mem_node->next = ctrl->p_mem_head;
+				ctrl->p_mem_head = p_mem_node;
+			} else {
+				p_mem_node->next = func->p_mem_head;
+				func->p_mem_head = p_mem_node;
+			}
+		}
+
+		/*
+		 * If we've got a valid bus number, use it
+		 * The second condition is to ignore bus numbers on
+		 * populated slots that don't have PCI-PCI bridges
+		 */
+		if (secondary_bus && (secondary_bus != primary_bus)) {
+			bus_node = (struct pci_resource *) kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
+			if (!bus_node)
+				return -ENOMEM;
+
+			bus_node->base = (ulong)secondary_bus;
+			bus_node->length = (ulong)(max_bus - secondary_bus + 1);
+			dbg("found bus_node(base, length) = %x, %x\n", bus_node->base, bus_node->length);
+
+			if (!populated_slot) {
+				bus_node->next = ctrl->bus_head;
+				ctrl->bus_head = bus_node;
+			} else {
+				bus_node->next = func->bus_head;
+				func->bus_head = bus_node;
+			}
+		}
+
+#if link_available
+		++index;
+
+		while (index < 8) {
+			if (((func = shpchp_slot_find(primary_bus, dev_func >> 3, index)) != NULL) && populated_slot)
+				rc = link_available_resources(ctrl, func, index);
+			
+			if (rc)
+				break;
+
+			++index;
+		}
+#endif
+		i--;
+		one_slot += sizeof(struct slot_rt);
+	}
+
+	/* If all of the following fail, we don't have any resources for hot plug add */
+	rc = 1;
+	rc &= shpchp_resource_sort_and_combine(&(ctrl->mem_head));
+	rc &= shpchp_resource_sort_and_combine(&(ctrl->p_mem_head));
+	rc &= shpchp_resource_sort_and_combine(&(ctrl->io_head));
+	rc &= shpchp_resource_sort_and_combine(&(ctrl->bus_head));
+
+	return (rc);
+}
+
+int shpchprm_set_hpp(
+	struct controller *ctrl,
+	struct pci_func *func,
+	u8	card_type)
+{
+	u32 rc;
+	u8 temp_byte;
+	struct pci_bus lpci_bus, *pci_bus;
+	unsigned int	devfn;
+	memcpy(&lpci_bus, ctrl->pci_bus, sizeof(lpci_bus));
+	pci_bus = &lpci_bus;
+	pci_bus->number = func->bus;
+	devfn = PCI_DEVFN(func->device, func->function);
+
+	temp_byte = 0x40;	/* hard coded value for LT */
+	if (card_type == PCI_HEADER_TYPE_BRIDGE) {
+		/* set subordinate Latency Timer */
+		rc = pci_bus_write_config_byte(pci_bus, devfn, PCI_SEC_LATENCY_TIMER, temp_byte);
+		if (rc) {
+			dbg("%s: set secondary LT error. b:d:f(%02x:%02x:%02x)\n", __FUNCTION__, func->bus, 
+				func->device, func->function);
+			return rc;
+		}
+	}
+
+	/* set base Latency Timer */
+	rc = pci_bus_write_config_byte(pci_bus, devfn, PCI_LATENCY_TIMER, temp_byte);
+	if (rc) {
+		dbg("%s: set LT error. b:d:f(%02x:%02x:%02x)\n", __FUNCTION__, func->bus, func->device, func->function);
+		return rc;
+	}
+
+	/* set Cache Line size */
+	temp_byte = 0x08;	/* hard coded value for CLS */
+	rc = pci_bus_write_config_byte(pci_bus, devfn, PCI_CACHE_LINE_SIZE, temp_byte);
+	if (rc) {
+		dbg("%s: set CLS error. b:d:f(%02x:%02x:%02x)\n", __FUNCTION__, func->bus, func->device, func->function);
+	}
+
+	/* set enable_perr */
+	/* set enable_serr */
+
+	return rc;
+}
+
+void shpchprm_enable_card(
+	struct controller *ctrl,
+	struct pci_func *func,
+	u8 card_type)
+{
+	u16 command, bcommand;
+	struct pci_bus lpci_bus, *pci_bus;
+	unsigned int devfn;
+	int rc;
+
+	memcpy(&lpci_bus, ctrl->pci_bus, sizeof(lpci_bus));
+	pci_bus = &lpci_bus;
+	pci_bus->number = func->bus;
+	devfn = PCI_DEVFN(func->device, func->function);
+
+	rc = pci_bus_read_config_word(pci_bus, devfn, PCI_COMMAND, &command);
+	command |= PCI_COMMAND_PARITY | PCI_COMMAND_SERR
+		| PCI_COMMAND_MASTER | PCI_COMMAND_INVALIDATE
+		| PCI_COMMAND_IO | PCI_COMMAND_MEMORY;
+	rc = pci_bus_write_config_word(pci_bus, devfn, PCI_COMMAND, command);
+
+	if (card_type == PCI_HEADER_TYPE_BRIDGE) {
+		rc = pci_bus_read_config_word(pci_bus, devfn, PCI_BRIDGE_CONTROL, &bcommand);
+		bcommand |= PCI_BRIDGE_CTL_PARITY | PCI_BRIDGE_CTL_SERR
+			| PCI_BRIDGE_CTL_NO_ISA;
+		rc = pci_bus_write_config_word(pci_bus, devfn, PCI_BRIDGE_CONTROL, bcommand);
+	}
+}
+
+static int legacy_shpchprm_init_pci(void)
+{
+	shpchp_rom_start = (u8 *) ioremap(ROM_PHY_ADDR, ROM_PHY_LEN);
+	if (!shpchp_rom_start) {
+		err("Could not ioremap memory region for ROM\n");
+		return -EIO;
+	}
+
+	return 0;
+}
+
+int shpchprm_init(enum php_ctlr_type ctrl_type)
+{
+	int retval;
+
+	switch (ctrl_type) {
+	case PCI:
+		retval = legacy_shpchprm_init_pci();
+		break;
+	default:
+		retval = -ENODEV;
+		break;
+	}
+
+	return retval;
+}
--- diff/drivers/pci/hotplug/shpchprm_legacy.h	1970-01-01 01:00:00.000000000 +0100
+++ source/drivers/pci/hotplug/shpchprm_legacy.h	2004-02-23 13:56:44.000000000 +0000
@@ -0,0 +1,113 @@
+/*
+ * SHPCHPRM Legacy: PHP Resource Manager for Non-ACPI/Legacy platform using HRT
+ *
+ * Copyright (C) 1995,2001 Compaq Computer Corporation
+ * Copyright (C) 2001 Greg Kroah-Hartman (greg@kroah.com)
+ * Copyright (C) 2001 IBM Corp.
+ * Copyright (C) 2003-2004 Intel Corporation
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Send feedback to <greg@kroah.com>, <dely.l.sy@intel.com>
+ *
+ */
+
+#ifndef _SHPCHPRM_LEGACY_H_
+#define _SHPCHPRM_LEGACY_H_
+
+#define ROM_PHY_ADDR	0x0F0000
+#define ROM_PHY_LEN	0x00FFFF
+
+struct slot_rt {
+	u8 dev_func;
+	u8 primary_bus;
+	u8 secondary_bus;
+	u8 max_bus;
+	u16 io_base;
+	u16 io_length;
+	u16 mem_base;
+	u16 mem_length;
+	u16 pre_mem_base;
+	u16 pre_mem_length;
+} __attribute__ ((packed));
+
+/* offsets to the hotplug slot resource table registers based on the above structure layout */
+enum slot_rt_offsets {
+	DEV_FUNC = offsetof(struct slot_rt, dev_func),
+	PRIMARY_BUS = offsetof(struct slot_rt, primary_bus),
+	SECONDARY_BUS = offsetof(struct slot_rt, secondary_bus),
+	MAX_BUS = offsetof(struct slot_rt, max_bus),
+	IO_BASE = offsetof(struct slot_rt, io_base),
+	IO_LENGTH = offsetof(struct slot_rt, io_length),
+	MEM_BASE = offsetof(struct slot_rt, mem_base),
+	MEM_LENGTH = offsetof(struct slot_rt, mem_length),
+	PRE_MEM_BASE = offsetof(struct slot_rt, pre_mem_base),
+	PRE_MEM_LENGTH = offsetof(struct slot_rt, pre_mem_length),
+};
+
+struct hrt {
+	char sig0;
+	char sig1;
+	char sig2;
+	char sig3;
+	u16 unused_IRQ;
+	u16 PCIIRQ;
+	u8 number_of_entries;
+	u8 revision;
+	u16 reserved1;
+	u32 reserved2;
+} __attribute__ ((packed));
+
+/* offsets to the hotplug resource table registers based on the above structure layout */
+enum hrt_offsets {
+	SIG0 = offsetof(struct hrt, sig0),
+	SIG1 = offsetof(struct hrt, sig1),
+	SIG2 = offsetof(struct hrt, sig2),
+	SIG3 = offsetof(struct hrt, sig3),
+	UNUSED_IRQ = offsetof(struct hrt, unused_IRQ),
+	PCIIRQ = offsetof(struct hrt, PCIIRQ),
+	NUMBER_OF_ENTRIES = offsetof(struct hrt, number_of_entries),
+	REVISION = offsetof(struct hrt, revision),
+	HRT_RESERVED1 = offsetof(struct hrt, reserved1),
+	HRT_RESERVED2 = offsetof(struct hrt, reserved2),
+};
+
+struct irq_info {
+	u8 bus, devfn;		/* bus, device and function */
+	struct {
+		u8 link;	/* IRQ line ID, chipset dependent, 0=not routed */
+		u16 bitmap;	/* Available IRQs */
+	} __attribute__ ((packed)) irq[4];
+	u8 slot;		/* slot number, 0=onboard */
+	u8 rfu;
+} __attribute__ ((packed));
+
+struct irq_routing_table {
+	u32 signature;		/* PIRQ_SIGNATURE should be here */
+	u16 version;		/* PIRQ_VERSION */
+	u16 size;			/* Table size in bytes */
+	u8 rtr_bus, rtr_devfn;	/* Where the interrupt router lies */
+	u16 exclusive_irqs;	/* IRQs devoted exclusively to PCI usage */
+	u16 rtr_vendor, rtr_device;	/* Vendor and device ID of interrupt router */
+	u32 miniport_data;	/* Crap */
+	u8 rfu[11];
+	u8 checksum;		/* Modulo 256 checksum must give zero */
+	struct irq_info slots[0];
+} __attribute__ ((packed));
+
+#endif				/* _SHPCHPRM_LEGACY_H_ */
--- diff/drivers/pci/hotplug/shpchprm_nonacpi.c	1970-01-01 01:00:00.000000000 +0100
+++ source/drivers/pci/hotplug/shpchprm_nonacpi.c	2004-02-23 13:56:44.000000000 +0000
@@ -0,0 +1,431 @@
+/*
+ * SHPCHPRM NONACPI: PHP Resource Manager for Non-ACPI/Legacy platform
+ *
+ * Copyright (C) 1995,2001 Compaq Computer Corporation
+ * Copyright (C) 2001 Greg Kroah-Hartman (greg@kroah.com)
+ * Copyright (C) 2001 IBM Corp.
+ * Copyright (C) 2003-2004 Intel Corporation
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Send feedback to <greg@kroah.com>, <dely.l.sy@intel.com>
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <asm/uaccess.h>
+#ifdef CONFIG_IA64
+#include <asm/iosapic.h>
+#endif
+#include "shpchp.h"
+#include "shpchprm.h"
+#include "shpchprm_nonacpi.h"
+
+void shpchprm_cleanup(void)
+{
+	return;
+}
+
+int shpchprm_print_pirt(void)
+{
+	return 0;
+}
+
+void * shpchprm_get_slot(struct slot *slot)
+{
+	return NULL;
+}
+
+int shpchprm_get_physical_slot_number(struct controller *ctrl, u32 *sun, u8 busnum, u8 devnum)
+{
+	int	offset = devnum - ctrl->slot_device_offset;
+
+	dbg("%s: ctrl->slot_num_inc %d, offset %d\n", __FUNCTION__, ctrl->slot_num_inc, offset);
+	*sun = (u8) (ctrl->first_slot + ctrl->slot_num_inc * offset);
+	return 0;
+}
+
+static void print_pci_resource ( struct pci_resource	*aprh)
+{
+	struct pci_resource	*res;
+
+	for (res = aprh; res; res = res->next)
+		dbg("        base= 0x%x length= 0x%x\n", res->base, res->length);
+}
+
+
+static void phprm_dump_func_res( struct pci_func *fun)
+{
+	struct pci_func *func = fun;
+
+	if (func->bus_head) {
+		dbg(":    BUS Resources:\n");
+		print_pci_resource (func->bus_head);
+	}
+	if (func->io_head) {
+		dbg(":    IO Resources:\n");
+		print_pci_resource (func->io_head);
+	}
+	if (func->mem_head) {
+		dbg(":    MEM Resources:\n");
+		print_pci_resource (func->mem_head);
+	}
+	if (func->p_mem_head) {
+		dbg(":    PMEM Resources:\n");
+		print_pci_resource (func->p_mem_head);
+	}
+}
+
+static int phprm_get_used_resources (
+	struct controller *ctrl,
+	struct pci_func *func
+	)
+{
+	return shpchp_save_used_resources (ctrl, func, !DISABLE_CARD);
+}
+
+static int phprm_delete_resource(
+	struct pci_resource **aprh,
+	ulong base,
+	ulong size)
+{
+	struct pci_resource *res;
+	struct pci_resource *prevnode;
+	struct pci_resource *split_node;
+	ulong tbase;
+
+	shpchp_resource_sort_and_combine(aprh);
+
+	for (res = *aprh; res; res = res->next) {
+		if (res->base > base)
+			continue;
+
+		if ((res->base + res->length) < (base + size))
+			continue;
+
+		if (res->base < base) {
+			tbase = base;
+
+			if ((res->length - (tbase - res->base)) < size)
+				continue;
+
+			split_node = (struct pci_resource *) kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
+			if (!split_node)
+				return -ENOMEM;
+
+			split_node->base = res->base;
+			split_node->length = tbase - res->base;
+			res->base = tbase;
+			res->length -= split_node->length;
+
+			split_node->next = res->next;
+			res->next = split_node;
+		}
+
+		if (res->length >= size) {
+			split_node = (struct pci_resource*) kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
+			if (!split_node)
+				return -ENOMEM;
+
+			split_node->base = res->base + size;
+			split_node->length = res->length - size;
+			res->length = size;
+
+			split_node->next = res->next;
+			res->next = split_node;
+		}
+
+		if (*aprh == res) {
+			*aprh = res->next;
+		} else {
+			prevnode = *aprh;
+			while (prevnode->next != res)
+				prevnode = prevnode->next;
+
+			prevnode->next = res->next;
+		}
+		res->next = NULL;
+		kfree(res);
+		break;
+	}
+
+	return 0;
+}
+
+
+static int phprm_delete_resources(
+	struct pci_resource **aprh,
+	struct pci_resource *this
+	)
+{
+	struct pci_resource *res;
+
+	for (res = this; res; res = res->next)
+		phprm_delete_resource(aprh, res->base, res->length);
+
+	return 0;
+}
+
+
+static int configure_existing_function(
+	struct controller *ctrl,
+	struct pci_func *func
+	)
+{
+	int rc;
+
+	/* see how much resources the func has used. */
+	rc = phprm_get_used_resources (ctrl, func);
+
+	if (!rc) {
+		/* subtract the resources used by the func from ctrl resources */
+		rc  = phprm_delete_resources (&ctrl->bus_head, func->bus_head);
+		rc |= phprm_delete_resources (&ctrl->io_head, func->io_head);
+		rc |= phprm_delete_resources (&ctrl->mem_head, func->mem_head);
+		rc |= phprm_delete_resources (&ctrl->p_mem_head, func->p_mem_head);
+		if (rc)
+			warn("aCEF: cannot del used resources\n");
+	} else
+		err("aCEF: cannot get used resources\n");
+
+	return rc;
+}
+
+static int bind_pci_resources_to_slots ( struct controller *ctrl)
+{
+	struct pci_func *func;
+	int busn = ctrl->slot_bus;
+	int devn, funn;
+	u32	vid;
+
+	for (devn = 0; devn < 32; devn++) {
+		for (funn = 0; funn < 8; funn++) {
+			/*
+			if (devn == ctrl->device && funn == ctrl->function)
+				continue;
+			 */
+			/* find out if this entry is for an occupied slot */
+			vid = 0xFFFFFFFF;
+
+			pci_bus_read_config_dword(ctrl->pci_dev->subordinate, PCI_DEVFN(devn, funn), PCI_VENDOR_ID, &vid);
+
+			if (vid != 0xFFFFFFFF) {
+				func = shpchp_slot_find(busn, devn, funn);
+				if (!func)
+					continue;
+				configure_existing_function(ctrl, func);
+				dbg("aCCF:existing PCI 0x%x Func ResourceDump\n", ctrl->bus);
+				phprm_dump_func_res(func);
+			}
+		}
+	}
+
+	return 0;
+}
+
+static void phprm_dump_ctrl_res( struct controller *ctlr)
+{
+	struct controller *ctrl = ctlr;
+
+	if (ctrl->bus_head) {
+		dbg(":    BUS Resources:\n");
+		print_pci_resource (ctrl->bus_head);
+	}
+	if (ctrl->io_head) {
+		dbg(":    IO Resources:\n");
+		print_pci_resource (ctrl->io_head);
+	}
+	if (ctrl->mem_head) {
+		dbg(":    MEM Resources:\n");
+		print_pci_resource (ctrl->mem_head);
+	}
+	if (ctrl->p_mem_head) {
+		dbg(":    PMEM Resources:\n");
+		print_pci_resource (ctrl->p_mem_head);
+	}
+}
+
+/*
+ * phprm_find_available_resources
+ *
+ *  Finds available memory, IO, and IRQ resources for programming
+ *  devices which may be added to the system
+ *  this function is for hot plug ADD!
+ *
+ * returns 0 if success
+ */
+int shpchprm_find_available_resources(struct controller *ctrl)
+{
+	struct pci_func func;
+	u32 rc;
+
+	memset(&func, 0, sizeof(struct pci_func));
+
+	func.bus = ctrl->bus;
+	func.device = ctrl->device;
+	func.function = ctrl->function;
+	func.is_a_board = 1;
+
+	/* Get resources for this PCI bridge */
+	rc = shpchp_save_used_resources (ctrl, &func, !DISABLE_CARD);
+	dbg("%s: shpchp_save_used_resources rc = %d\n", __FUNCTION__, rc);
+
+	if (func.mem_head)
+		func.mem_head->next = ctrl->mem_head;
+	ctrl->mem_head = func.mem_head;
+
+	if (func.p_mem_head)
+		func.p_mem_head->next = ctrl->p_mem_head;
+	ctrl->p_mem_head = func.p_mem_head;
+
+	if (func.io_head)
+		func.io_head->next = ctrl->io_head;
+	ctrl->io_head = func.io_head;
+
+	if(func.bus_head)
+		func.bus_head->next = ctrl->bus_head;
+	ctrl->bus_head = func.bus_head;
+	if (ctrl->bus_head)
+		phprm_delete_resource(&ctrl->bus_head, ctrl->pci_dev->subordinate->number, 1);
+
+	dbg("%s:pre-Bind PCI 0x%x Ctrl Resource Dump\n", __FUNCTION__, ctrl->bus);
+	phprm_dump_ctrl_res(ctrl);
+	bind_pci_resources_to_slots (ctrl);
+
+	dbg("%s:post-Bind PCI 0x%x Ctrl Resource Dump\n", __FUNCTION__, ctrl->bus);
+	phprm_dump_ctrl_res(ctrl);
+
+
+	/* If all of the following fail, we don't have any resources for hot plug add */
+	rc = 1;
+	rc &= shpchp_resource_sort_and_combine(&(ctrl->mem_head));
+	rc &= shpchp_resource_sort_and_combine(&(ctrl->p_mem_head));
+	rc &= shpchp_resource_sort_and_combine(&(ctrl->io_head));
+	rc &= shpchp_resource_sort_and_combine(&(ctrl->bus_head));
+
+	return (rc);
+}
+
+int shpchprm_set_hpp(
+	struct controller *ctrl,
+	struct pci_func *func,
+	u8	card_type)
+{
+	u32 rc;
+	u8 temp_byte;
+	struct pci_bus lpci_bus, *pci_bus;
+	unsigned int	devfn;
+	memcpy(&lpci_bus, ctrl->pci_bus, sizeof(lpci_bus));
+	pci_bus = &lpci_bus;
+	pci_bus->number = func->bus;
+	devfn = PCI_DEVFN(func->device, func->function);
+
+	temp_byte = 0x40;	/* hard coded value for LT */
+	if (card_type == PCI_HEADER_TYPE_BRIDGE) {
+		/* set subordinate Latency Timer */
+		rc = pci_bus_write_config_byte(pci_bus, devfn, PCI_SEC_LATENCY_TIMER, temp_byte);
+
+		if (rc) {
+			dbg("%s: set secondary LT error. b:d:f(%02x:%02x:%02x)\n", __FUNCTION__, func->bus, 
+				func->device, func->function);
+			return rc;
+		}
+	}
+
+	/* set base Latency Timer */
+	rc = pci_bus_write_config_byte(pci_bus, devfn, PCI_LATENCY_TIMER, temp_byte);
+
+	if (rc) {
+		dbg("%s: set LT error. b:d:f(%02x:%02x:%02x)\n", __FUNCTION__, func->bus, func->device, func->function);
+		return rc;
+	}
+
+	/* set Cache Line size */
+	temp_byte = 0x08;	/* hard coded value for CLS */
+
+	rc = pci_bus_write_config_byte(pci_bus, devfn, PCI_CACHE_LINE_SIZE, temp_byte);
+
+	if (rc) {
+		dbg("%s: set CLS error. b:d:f(%02x:%02x:%02x)\n", __FUNCTION__, func->bus, func->device, func->function);
+	}
+
+	/* set enable_perr */
+	/* set enable_serr */
+
+	return rc;
+}
+
+void shpchprm_enable_card(
+	struct controller *ctrl,
+	struct pci_func *func,
+	u8 card_type)
+{
+	u16 command, bcommand;
+	struct pci_bus lpci_bus, *pci_bus;
+	unsigned int devfn;
+	int rc;
+
+	memcpy(&lpci_bus, ctrl->pci_bus, sizeof(lpci_bus));
+	pci_bus = &lpci_bus;
+	pci_bus->number = func->bus;
+	devfn = PCI_DEVFN(func->device, func->function);
+
+	rc = pci_bus_read_config_word(pci_bus, devfn, PCI_COMMAND, &command);
+
+	command |= PCI_COMMAND_PARITY | PCI_COMMAND_SERR
+		| PCI_COMMAND_MASTER | PCI_COMMAND_INVALIDATE
+		| PCI_COMMAND_IO | PCI_COMMAND_MEMORY;
+
+	rc = pci_bus_write_config_word(pci_bus, devfn, PCI_COMMAND, command);
+
+	if (card_type == PCI_HEADER_TYPE_BRIDGE) {
+
+		rc = pci_bus_read_config_word(pci_bus, devfn, PCI_BRIDGE_CONTROL, &bcommand);
+
+		bcommand |= PCI_BRIDGE_CTL_PARITY | PCI_BRIDGE_CTL_SERR
+			| PCI_BRIDGE_CTL_NO_ISA;
+
+		rc = pci_bus_write_config_word(pci_bus, devfn, PCI_BRIDGE_CONTROL, bcommand);
+	}
+}
+
+static int legacy_shpchprm_init_pci(void)
+{
+	return 0;
+}
+
+int shpchprm_init(enum php_ctlr_type ctrl_type)
+{
+	int retval;
+
+	switch (ctrl_type) {
+	case PCI:
+		retval = legacy_shpchprm_init_pci();
+		break;
+	default:
+		retval = -ENODEV;
+		break;
+	}
+
+	return retval;
+}
--- diff/drivers/pci/hotplug/shpchprm_nonacpi.h	1970-01-01 01:00:00.000000000 +0100
+++ source/drivers/pci/hotplug/shpchprm_nonacpi.h	2004-02-23 13:56:44.000000000 +0000
@@ -0,0 +1,56 @@
+/*
+ * SHPCHPRM NONACPI: PHP Resource Manager for Non-ACPI/Legacy platform
+ *
+ * Copyright (C) 1995,2001 Compaq Computer Corporation
+ * Copyright (C) 2001 Greg Kroah-Hartman (greg@kroah.com)
+ * Copyright (C) 2001 IBM Corp.
+ * Copyright (C) 2003-2004 Intel Corporation
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Send feedback to <greg@kroah.com>, <dely.l.sy@intel.com>
+ *
+ */
+
+#ifndef _SHPCHPRM_NONACPI_H_
+#define _SHPCHPRM_NONACPI_H_
+
+struct irq_info {
+	u8 bus, devfn;		/* bus, device and function */
+	struct {
+		u8 link;	/* IRQ line ID, chipset dependent, 0=not routed */
+		u16 bitmap;	/* Available IRQs */
+	} __attribute__ ((packed)) irq[4];
+	u8 slot;		/* slot number, 0=onboard */
+	u8 rfu;
+} __attribute__ ((packed));
+
+struct irq_routing_table {
+	u32 signature;		/* PIRQ_SIGNATURE should be here */
+	u16 version;		/* PIRQ_VERSION */
+	u16 size;			/* Table size in bytes */
+	u8 rtr_bus, rtr_devfn;	/* Where the interrupt router lies */
+	u16 exclusive_irqs;	/* IRQs devoted exclusively to PCI usage */
+	u16 rtr_vendor, rtr_device;	/* Vendor and device ID of interrupt router */
+	u32 miniport_data;	/* Crap */
+	u8 rfu[11];
+	u8 checksum;		/* Modulo 256 checksum must give zero */
+	struct irq_info slots[0];
+} __attribute__ ((packed));
+
+#endif				/* _SHPCHPRM_NONACPI_H_ */
--- diff/drivers/s390/block/dasd_cmb.c	1970-01-01 01:00:00.000000000 +0100
+++ source/drivers/s390/block/dasd_cmb.c	2004-02-23 13:56:44.000000000 +0000
@@ -0,0 +1,145 @@
+/*
+ * linux/drivers/s390/block/dasd_cmb.c ($Revision: 1.6 $)
+ *
+ * Linux on zSeries Channel Measurement Facility support
+ *  (dasd device driver interface)
+ *
+ * Copyright 2000,2003 IBM Corporation
+ *
+ * Author: Arnd Bergmann <arndb@de.ibm.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <linux/init.h>
+#include <linux/ioctl32.h>
+#include <linux/module.h>
+#include <asm/ccwdev.h>
+#include <asm/cmb.h>
+
+#include "dasd_int.h"
+
+static int
+dasd_ioctl_cmf_enable(struct block_device *bdev, int no, long args)
+{
+	struct dasd_device *device;
+
+	device = bdev->bd_disk->private_data;
+	if (!device)
+		return -EINVAL;
+
+	return enable_cmf(device->cdev);
+}
+
+static int
+dasd_ioctl_cmf_disable(struct block_device *bdev, int no, long args)
+{
+	struct dasd_device *device;
+
+	device = bdev->bd_disk->private_data;
+	if (!device)
+		return -EINVAL;
+
+	return disable_cmf(device->cdev);
+}
+
+static int
+dasd_ioctl_readall_cmb(struct block_device *bdev, int no, long args)
+{
+	struct dasd_device *device;
+	struct cmbdata * __user udata;
+	struct cmbdata data;
+	size_t size;
+	int ret;
+
+	device = bdev->bd_disk->private_data;
+	if (!device)
+		return -EINVAL;
+	udata = (void *) args;
+	size = _IOC_SIZE(no);
+
+	if (!access_ok(VERIFY_WRITE, udata, size))
+		return -EFAULT;
+	ret = cmf_readall(device->cdev, &data);
+	if (ret)
+		return ret;
+	if (copy_to_user(udata, &data, min(size, sizeof(*udata))))
+		return -EFAULT;
+	return 0;
+}
+
+/* module initialization below here. dasd already provides a mechanism
+ * to dynamically register ioctl functions, so we simply use this. */
+static inline int
+ioctl_reg(unsigned int no, dasd_ioctl_fn_t handler)
+{
+	int ret;
+	ret = dasd_ioctl_no_register(THIS_MODULE, no, handler);
+#ifdef CONFIG_COMPAT
+	if (ret)
+		return ret;
+
+	ret = register_ioctl32_conversion(no, NULL);
+	if (ret)
+		dasd_ioctl_no_unregister(THIS_MODULE, no, handler);
+#endif
+	return ret;
+}
+
+static inline void
+ioctl_unreg(unsigned int no, dasd_ioctl_fn_t handler)
+{
+	dasd_ioctl_no_unregister(THIS_MODULE, no, handler);
+#ifdef CONFIG_COMPAT
+	unregister_ioctl32_conversion(no);
+#endif
+
+}
+
+static void
+dasd_cmf_exit(void)
+{
+	ioctl_unreg(BIODASDCMFENABLE,  dasd_ioctl_cmf_enable);
+	ioctl_unreg(BIODASDCMFDISABLE, dasd_ioctl_cmf_disable);
+	ioctl_unreg(BIODASDREADALLCMB, dasd_ioctl_readall_cmb);
+}
+
+static int __init
+dasd_cmf_init(void)
+{
+	int ret;
+	ret = ioctl_reg (BIODASDCMFENABLE, dasd_ioctl_cmf_enable);
+	if (ret)
+		goto err;
+	ret = ioctl_reg (BIODASDCMFDISABLE, dasd_ioctl_cmf_disable);
+	if (ret)
+		goto err;
+	ret = ioctl_reg (BIODASDREADALLCMB, dasd_ioctl_readall_cmb);
+	if (ret)
+		goto err;
+
+	return 0;
+err:
+	dasd_cmf_exit();
+
+	return ret;
+}
+
+module_init(dasd_cmf_init);
+module_exit(dasd_cmf_exit);
+
+MODULE_AUTHOR("Arnd Bergmann <arndb@de.ibm.com>");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("channel measurement facility interface for dasd\n"
+		   "Copyright 2003 IBM Corporation\n");
--- diff/drivers/s390/block/dcssblk.c	1970-01-01 01:00:00.000000000 +0100
+++ source/drivers/s390/block/dcssblk.c	2004-02-23 13:56:45.000000000 +0000
@@ -0,0 +1,705 @@
+/*
+ * dcssblk.c -- the S/390 block driver for dcss memory
+ *
+ * Authors: Carsten Otte, Stefan Weinhuber, Gerald Schaefer
+ */
+
+#include <linux/module.h>
+#include <linux/ctype.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/blkdev.h>
+#include <asm/extmem.h>
+#include <asm/io.h>
+#include <linux/completion.h>
+#include <linux/interrupt.h>
+#include <asm/ccwdev.h> 	// for s390_root_dev_(un)register()
+
+//#define DCSSBLK_DEBUG		/* Debug messages on/off */
+#define DCSSBLK_NAME "dcssblk"
+#define DCSSBLK_MINORS_PER_DISK 1
+
+#ifdef DCSSBLK_DEBUG
+#define PRINT_DEBUG(x...) printk(KERN_DEBUG DCSSBLK_NAME " debug: " x)
+#else
+#define PRINT_DEBUG(x...) do {} while (0)
+#endif
+#define PRINT_INFO(x...)  printk(KERN_INFO DCSSBLK_NAME " info: " x)
+#define PRINT_WARN(x...)  printk(KERN_WARNING DCSSBLK_NAME " warning: " x)
+#define PRINT_ERR(x...)	  printk(KERN_ERR DCSSBLK_NAME " error: " x)
+
+
+static int dcssblk_open(struct inode *inode, struct file *filp);
+static int dcssblk_release(struct inode *inode, struct file *filp);
+static int dcssblk_make_request(struct request_queue *q, struct bio *bio);
+
+static int dcssblk_major;
+static struct block_device_operations dcssblk_devops = {
+	.owner   = THIS_MODULE,
+	.open    = dcssblk_open,
+	.release = dcssblk_release,
+};
+
+static ssize_t dcssblk_add_store(struct device * dev, const char * buf,
+				  size_t count);
+static ssize_t dcssblk_remove_store(struct device * dev, const char * buf,
+				  size_t count);
+static ssize_t dcssblk_save_store(struct device * dev, const char * buf,
+				  size_t count);
+static ssize_t dcssblk_save_show(struct device *dev, char *buf);
+static ssize_t dcssblk_shared_store(struct device * dev, const char * buf,
+				  size_t count);
+static ssize_t dcssblk_shared_show(struct device *dev, char *buf);
+
+static DEVICE_ATTR(add, S_IWUSR, NULL, dcssblk_add_store);
+static DEVICE_ATTR(remove, S_IWUSR, NULL, dcssblk_remove_store);
+static DEVICE_ATTR(save, S_IWUSR | S_IRUGO, dcssblk_save_show,
+		   dcssblk_save_store);
+static DEVICE_ATTR(shared, S_IWUSR | S_IRUGO, dcssblk_shared_show,
+		   dcssblk_shared_store);
+
+static struct device *dcssblk_root_dev;
+
+struct dcssblk_dev_info {
+	struct list_head lh;
+	struct device dev;
+	char segment_name[BUS_ID_SIZE];
+	atomic_t use_count;
+	struct gendisk *gd;
+	unsigned long start;
+	unsigned long end;
+	int segment_type;
+	unsigned char save_pending;
+	unsigned char is_shared;
+	struct request_queue *dcssblk_queue;
+};
+
+static struct list_head dcssblk_devices = LIST_HEAD_INIT(dcssblk_devices);
+static rwlock_t dcssblk_devices_lock = RW_LOCK_UNLOCKED;
+
+
+/*
+ * release function for segment device.
+ */
+static void
+dcssblk_release_segment(struct device *dev)
+{
+	PRINT_DEBUG("segment release fn called for %s\n", dev->bus_id);
+	kfree(container_of(dev, struct dcssblk_dev_info, dev));
+	module_put(THIS_MODULE);
+}
+
+/*
+ * get a minor number. needs to be called with
+ * write_lock(&dcssblk_devices_lock) and the
+ * device needs to be enqueued before the lock is
+ * freed.
+ */
+static inline int
+dcssblk_assign_free_minor(struct dcssblk_dev_info *dev_info)
+{
+	int minor, found;
+	struct dcssblk_dev_info *entry;
+
+	if (dev_info == NULL)
+		return -EINVAL;
+	for (minor = 0; minor < (1<<MINORBITS); minor++) {
+		found = 0;
+		// test if minor available
+		list_for_each_entry(entry, &dcssblk_devices, lh)
+			if (minor == entry->gd->first_minor)
+				found++;
+		if (!found) break; // got unused minor
+	}
+	if (found)
+		return -EBUSY;
+	dev_info->gd->first_minor = minor;
+	return 0;
+}
+
+/*
+ * get the struct dcssblk_dev_info from dcssblk_devices
+ * for the given name.
+ * read_lock(&dcssblk_devices_lock) must be held.
+ */
+static struct dcssblk_dev_info *
+dcssblk_get_device_by_name(char *name)
+{
+	struct dcssblk_dev_info *entry;
+
+	list_for_each_entry(entry, &dcssblk_devices, lh) {
+		if (!strcmp(name, entry->segment_name)) {
+			return entry;
+		}
+	}
+	return NULL;
+}
+
+/*
+ * register the device that represents a segment in sysfs,
+ * also add the attributes for the device
+ */
+static inline int
+dcssblk_register_segment_device(struct device *dev)
+{
+	int rc;
+
+	rc = device_register(dev);
+	if (rc)
+		return rc;
+	rc = device_create_file(dev, &dev_attr_shared);
+	if (rc)
+		goto unregister_dev;
+	rc = device_create_file(dev, &dev_attr_save);
+	if (rc)
+		goto unregister_dev;
+	return rc;
+
+unregister_dev:
+	device_unregister(dev);
+	return rc;
+}
+
+/*
+ * device attribute for switching shared/nonshared (exclusive)
+ * operation (show + store)
+ */
+static ssize_t
+dcssblk_shared_show(struct device *dev, char *buf)
+{
+	struct dcssblk_dev_info *dev_info;
+
+	dev_info = container_of(dev, struct dcssblk_dev_info, dev);
+	return sprintf(buf, dev_info->is_shared ? "1\n" : "0\n");
+}
+
+static ssize_t
+dcssblk_shared_store(struct device *dev, const char *inbuf, size_t count)
+{
+	struct dcssblk_dev_info *dev_info;
+	int rc;
+
+	if ((count > 1) && (inbuf[1] != '\n') && (inbuf[1] != '\0')) {
+		PRINT_WARN("Invalid value, must be 0 or 1\n");
+		return -EINVAL;
+	}
+	write_lock(&dcssblk_devices_lock);
+	dev_info = container_of(dev, struct dcssblk_dev_info, dev);
+	if (atomic_read(&dev_info->use_count)) {
+		PRINT_ERR("share: segment %s is busy!\n",
+			  dev_info->segment_name);
+		write_unlock(&dcssblk_devices_lock);
+		return -EBUSY;
+	}
+	if ((inbuf[0] == '1') && (dev_info->is_shared == 1)) {
+		PRINT_WARN("Segment %s already loaded in shared mode!\n",
+			   dev_info->segment_name);
+		write_unlock(&dcssblk_devices_lock);
+		return count;
+	}
+	if ((inbuf[0] == '0') && (dev_info->is_shared == 0)) {
+		PRINT_WARN("Segment %s already loaded in exclusive mode!\n",
+			   dev_info->segment_name);
+		write_unlock(&dcssblk_devices_lock);
+		return count;
+	}
+	if (inbuf[0] == '1') {
+		// reload segment in shared mode
+		segment_unload(dev_info->segment_name);
+		rc = segment_load(dev_info->segment_name, SEGMENT_SHARED_RO,
+					&dev_info->start, &dev_info->end);
+		if (rc < 0) {
+			PRINT_ERR("Segment %s not reloaded, rc=%d\n",
+					dev_info->segment_name, rc);
+			goto removeseg;
+		}
+		dev_info->is_shared = 1;
+		PRINT_INFO("Segment %s reloaded, shared mode.\n",
+			   dev_info->segment_name);
+	} else if (inbuf[0] == '0') {
+		// reload segment in exclusive mode
+		segment_unload(dev_info->segment_name);
+		rc = segment_load(dev_info->segment_name, SEGMENT_EXCLUSIVE_RW,
+					&dev_info->start, &dev_info->end);
+		if (rc < 0) {
+			PRINT_ERR("Segment %s not reloaded, rc=%d\n",
+					dev_info->segment_name, rc);
+			goto removeseg;
+		}
+		dev_info->is_shared = 0;
+		PRINT_INFO("Segment %s reloaded, exclusive (read-write) mode.\n",
+			   dev_info->segment_name);
+	} else {
+		write_unlock(&dcssblk_devices_lock);
+		PRINT_WARN("Invalid value, must be 0 or 1\n");
+		return -EINVAL;
+	}
+	dev_info->segment_type = rc;
+	rc = count;
+
+	switch (dev_info->segment_type) {
+		case SEGMENT_SHARED_RO:
+		case SEGMENT_EXCLUSIVE_RO:
+			set_disk_ro(dev_info->gd, 1);
+			break;
+		case SEGMENT_SHARED_RW:
+		case SEGMENT_EXCLUSIVE_RW:
+			set_disk_ro(dev_info->gd, 0);
+			break;
+	}
+	if ((inbuf[0] == '1') &&
+	   ((dev_info->segment_type == SEGMENT_EXCLUSIVE_RO) ||
+	    (dev_info->segment_type == SEGMENT_EXCLUSIVE_RW))) {
+		PRINT_WARN("Could not get shared copy of segment %s\n",
+				dev_info->segment_name);
+		rc = -EPERM;
+	}
+	if ((inbuf[0] == '0') &&
+	   ((dev_info->segment_type == SEGMENT_SHARED_RO) ||
+	    (dev_info->segment_type == SEGMENT_SHARED_RW))) {
+		PRINT_WARN("Could not get exclusive copy of segment %s\n",
+				dev_info->segment_name);
+		rc = -EPERM;
+	}
+	write_unlock(&dcssblk_devices_lock);
+	goto out;
+
+removeseg:
+	PRINT_ERR("Could not reload segment %s, removing it now!\n",
+			dev_info->segment_name);
+	list_del(&dev_info->lh);
+	write_unlock(&dcssblk_devices_lock);
+
+	del_gendisk(dev_info->gd);
+	blk_put_queue(dev_info->dcssblk_queue);
+	dev_info->gd->queue = NULL;
+	put_disk(dev_info->gd);
+	device_unregister(dev);
+	put_device(dev);
+out:
+	return rc;
+}
+
+/*
+ * device attribute for save operation on current copy
+ * of the segment. If the segment is busy, saving will
+ * become pending until it gets released, which can be
+ * undone by storing a non-true value to this entry.
+ * (show + store)
+ */
+static ssize_t
+dcssblk_save_show(struct device *dev, char *buf)
+{
+	struct dcssblk_dev_info *dev_info;
+
+	dev_info = container_of(dev, struct dcssblk_dev_info, dev);
+	return sprintf(buf, dev_info->save_pending ? "1\n" : "0\n");
+}
+
+static ssize_t
+dcssblk_save_store(struct device *dev, const char *inbuf, size_t count)
+{
+	struct dcssblk_dev_info *dev_info;
+
+	if ((count > 1) && (inbuf[1] != '\n') && (inbuf[1] != '\0')) {
+		PRINT_WARN("Invalid value, must be 0 or 1\n");
+		return -EINVAL;
+	}
+	dev_info = container_of(dev, struct dcssblk_dev_info, dev);
+
+	write_lock(&dcssblk_devices_lock);
+	if (inbuf[0] == '1') {
+		if (atomic_read(&dev_info->use_count) == 0) {
+			// device is idle => we save immediately
+			PRINT_INFO("Saving segment %s\n",
+				   dev_info->segment_name);
+			segment_replace(dev_info->segment_name);
+		}  else {
+			// device is busy => we save it when it becomes
+			// idle in dcssblk_release
+			PRINT_INFO("Segment %s is currently busy, it will "
+				   "be saved when it becomes idle...\n",
+				   dev_info->segment_name);
+			dev_info->save_pending = 1;
+		}
+	} else if (inbuf[0] == '0') {
+		if (dev_info->save_pending) {
+			// device is busy & the user wants to undo his save
+			// request
+			dev_info->save_pending = 0;
+			PRINT_INFO("Pending save for segment %s deactivated\n",
+					dev_info->segment_name);
+		}
+	} else {
+		write_unlock(&dcssblk_devices_lock);
+		PRINT_WARN("Invalid value, must be 0 or 1\n");
+		return -EINVAL;
+	}
+	write_unlock(&dcssblk_devices_lock);
+	return count;
+}
+
+/*
+ * device attribute for adding devices
+ */
+static ssize_t
+dcssblk_add_store(struct device *dev, const char *buf, size_t count)
+{
+	int rc, i;
+	struct dcssblk_dev_info *dev_info;
+	char *local_buf;
+	unsigned long seg_byte_size;
+
+	dev_info = NULL;
+	if (dev != dcssblk_root_dev) {
+		rc = -EINVAL;
+		goto out_nobuf;
+	}
+	local_buf = kmalloc(count + 1, GFP_KERNEL);
+	if (local_buf == NULL) {
+		rc = -ENOMEM;
+		goto out_nobuf;
+	}
+	/*
+	 * parse input
+	 */
+	for (i = 0; ((buf[i] != '\0') && (buf[i] != '\n') && i < count); i++) {
+		local_buf[i] = toupper(buf[i]);
+	}
+	local_buf[i] = '\0';
+	if ((i == 0) || (i > 8)) {
+		rc = -ENAMETOOLONG;
+		goto out;
+	}
+	/*
+	 * already loaded?
+	 */
+	read_lock(&dcssblk_devices_lock);
+	dev_info = dcssblk_get_device_by_name(local_buf);
+	read_unlock(&dcssblk_devices_lock);
+	if (dev_info != NULL) {
+		PRINT_WARN("Segment %s already loaded!\n", local_buf);
+		rc = -EEXIST;
+		goto out;
+	}
+	/*
+	 * get a struct dcssblk_dev_info
+	 */
+	dev_info = kmalloc(sizeof(struct dcssblk_dev_info), GFP_KERNEL);
+	if (dev_info == NULL) {
+		rc = -ENOMEM;
+		goto out;
+	}
+	memset(dev_info, 0, sizeof(struct dcssblk_dev_info));
+
+	strcpy(dev_info->segment_name, local_buf);
+	strlcpy(dev_info->dev.bus_id, local_buf, BUS_ID_SIZE);
+	dev_info->dev.release = dcssblk_release_segment;
+	INIT_LIST_HEAD(&dev_info->lh);
+
+	dev_info->gd = alloc_disk(DCSSBLK_MINORS_PER_DISK);
+	if (dev_info->gd == NULL) {
+		rc = -ENOMEM;
+		goto free_dev_info;
+	}
+	dev_info->gd->major = dcssblk_major;
+	dev_info->gd->fops = &dcssblk_devops;
+	dev_info->dcssblk_queue = blk_alloc_queue(GFP_KERNEL);
+	dev_info->gd->queue = dev_info->dcssblk_queue;
+	dev_info->gd->private_data = dev_info;
+	dev_info->gd->driverfs_dev = &dev_info->dev;
+	/*
+	 * load the segment
+	 */
+	rc = segment_load(local_buf, SEGMENT_SHARED_RO,
+				&dev_info->start, &dev_info->end);
+	if (rc < 0) {
+		PRINT_ERR("Segment %s not loaded, rc=%d\n", local_buf, rc);
+		goto dealloc_gendisk;
+	}
+	seg_byte_size = (dev_info->end - dev_info->start + 1);
+	set_capacity(dev_info->gd, seg_byte_size >> 9); // size in sectors
+	PRINT_INFO("Loaded segment %s from %p to %p, size = %lu Byte, "
+		   "capacity = %lu sectors (512 Byte)\n", local_buf,
+		   	(void *) dev_info->start, (void *) dev_info->end,
+			seg_byte_size, seg_byte_size >> 9);
+
+	dev_info->segment_type = rc;
+	dev_info->save_pending = 0;
+	dev_info->is_shared = 1;
+	dev_info->dev.parent = dcssblk_root_dev;
+
+	/*
+	 * get minor, add to list
+	 */
+	write_lock(&dcssblk_devices_lock);
+	rc = dcssblk_assign_free_minor(dev_info);
+	if (rc) {
+		write_unlock(&dcssblk_devices_lock);
+		PRINT_ERR("No free minor number available! "
+			  "Unloading segment...\n");
+		goto unload_seg;
+	}
+	sprintf(dev_info->gd->disk_name, "dcssblk%d",
+		dev_info->gd->first_minor);
+	list_add_tail(&dev_info->lh, &dcssblk_devices);
+	/*
+	 * register the device
+	 */
+	rc = dcssblk_register_segment_device(&dev_info->dev);
+	if (rc) {
+		PRINT_ERR("Segment %s could not be registered RC=%d\n",
+				local_buf, rc);
+		goto list_del;
+	}
+
+	if (!try_module_get(THIS_MODULE)) {
+		rc = -ENODEV;
+		goto list_del;
+	}
+
+	get_device(&dev_info->dev);
+	add_disk(dev_info->gd);
+
+	blk_queue_make_request(dev_info->dcssblk_queue, dcssblk_make_request);
+	blk_queue_hardsect_size(dev_info->dcssblk_queue, 4096);
+
+	switch (dev_info->segment_type) {
+		case SEGMENT_SHARED_RO:
+		case SEGMENT_EXCLUSIVE_RO:
+			set_disk_ro(dev_info->gd,1);
+			break;
+		case SEGMENT_SHARED_RW:
+		case SEGMENT_EXCLUSIVE_RW:
+			set_disk_ro(dev_info->gd,0);
+			break;
+	}
+	PRINT_DEBUG("Segment %s loaded successfully\n", local_buf);
+	write_unlock(&dcssblk_devices_lock);
+	rc = count;
+	goto out;
+
+list_del:
+	list_del(&dev_info->lh);
+	write_unlock(&dcssblk_devices_lock);
+unload_seg:
+	segment_unload(local_buf);
+dealloc_gendisk:
+	blk_put_queue(dev_info->dcssblk_queue);
+	dev_info->gd->queue = NULL;
+	put_disk(dev_info->gd);
+free_dev_info:
+	kfree(dev_info);
+out:
+	kfree(local_buf);
+out_nobuf:
+	return rc;
+}
+
+/*
+ * device attribute for removing devices
+ */
+static ssize_t
+dcssblk_remove_store(struct device *dev, const char *buf, size_t count)
+{
+	struct dcssblk_dev_info *dev_info;
+	int rc, i;
+	char *local_buf;
+
+	if (dev != dcssblk_root_dev) {
+		return -EINVAL;
+	}
+	local_buf = kmalloc(count + 1, GFP_KERNEL);
+	if (local_buf == NULL) {
+		return -ENOMEM;
+	}
+	/*
+	 * parse input
+	 */
+	for (i = 0; ((*(buf+i)!='\0') && (*(buf+i)!='\n') && i < count); i++) {
+		local_buf[i] = toupper(buf[i]);
+	}
+	local_buf[i] = '\0';
+	if ((i == 0) || (i > 8)) {
+		rc = -ENAMETOOLONG;
+		goto out_buf;
+	}
+
+	write_lock(&dcssblk_devices_lock);
+	dev_info = dcssblk_get_device_by_name(local_buf);
+	if (dev_info == NULL) {
+		write_unlock(&dcssblk_devices_lock);
+		PRINT_WARN("Segment %s is not loaded!\n", local_buf);
+		rc = -ENODEV;
+		goto out_buf;
+	}
+	if (atomic_read(&dev_info->use_count) != 0) {
+		write_unlock(&dcssblk_devices_lock);
+		PRINT_WARN("Segment %s is in use!\n", local_buf);
+		rc = -EBUSY;
+		goto out_buf;
+	}
+	list_del(&dev_info->lh);
+	write_unlock(&dcssblk_devices_lock);
+
+	del_gendisk(dev_info->gd);
+	blk_put_queue(dev_info->dcssblk_queue);
+	dev_info->gd->queue = NULL;
+	put_disk(dev_info->gd);
+	device_unregister(&dev_info->dev);
+	put_device(&dev_info->dev);
+	segment_unload(dev_info->segment_name);
+	PRINT_DEBUG("Segment %s unloaded successfully\n",
+			dev_info->segment_name);
+	rc = count;
+out_buf:
+	kfree(local_buf);
+	return rc;
+}
+
+static int
+dcssblk_open(struct inode *inode, struct file *filp)
+{
+	struct dcssblk_dev_info *dev_info;
+	int rc;
+
+	dev_info = inode->i_bdev->bd_disk->private_data;
+	if (NULL == dev_info) {
+		rc = -ENODEV;
+		goto out;
+	}
+	atomic_inc(&dev_info->use_count);
+	inode->i_bdev->bd_block_size = 4096;
+	rc = 0;
+out:
+	return rc;
+}
+
+static int
+dcssblk_release(struct inode *inode, struct file *filp)
+{
+	struct dcssblk_dev_info *dev_info;
+	int rc;
+
+	dev_info = inode->i_bdev->bd_disk->private_data;
+	if (NULL == dev_info) {
+		rc = -ENODEV;
+		goto out;
+	}
+	write_lock(&dcssblk_devices_lock);
+	if (atomic_dec_and_test(&dev_info->use_count)
+	    && (dev_info->save_pending)) {
+		PRINT_INFO("Segment %s became idle and is being saved now\n",
+			    dev_info->segment_name);
+		segment_replace(dev_info->segment_name);
+		dev_info->save_pending = 0;
+	}
+	write_unlock(&dcssblk_devices_lock);
+	rc = 0;
+out:
+	return rc;
+}
+
+static int
+dcssblk_make_request(request_queue_t *q, struct bio *bio)
+{
+	struct dcssblk_dev_info *dev_info;
+	struct bio_vec *bvec;
+	unsigned long index;
+	unsigned long page_addr;
+	unsigned long source_addr;
+	unsigned long bytes_done;
+	int i;
+
+	bytes_done = 0;
+	dev_info = bio->bi_bdev->bd_disk->private_data;
+	if (dev_info == NULL)
+		goto fail;
+	if ((bio->bi_sector & 3) != 0 || (bio->bi_size & 4095) != 0)
+		/* Request is not page-aligned. */
+		goto fail;
+	if (((bio->bi_size >> 9) + bio->bi_sector)
+			> get_capacity(bio->bi_bdev->bd_disk)) {
+		/* Request beyond end of DCSS segment. */
+		goto fail;
+	}
+	index = (bio->bi_sector >> 3);
+	bio_for_each_segment(bvec, bio, i) {
+		page_addr = (unsigned long)
+			page_address(bvec->bv_page) + bvec->bv_offset;
+		source_addr = dev_info->start + (index<<12) + bytes_done;
+		if (unlikely(page_addr & 4095) != 0 || (bvec->bv_len & 4095) != 0)
+			// More paranoia.
+			goto fail;
+		if (bio_data_dir(bio) == READ) {
+			memcpy((void*)page_addr, (void*)source_addr,
+				bvec->bv_len);
+		} else {
+			memcpy((void*)source_addr, (void*)page_addr,
+				bvec->bv_len);
+		}
+		bytes_done += bvec->bv_len;
+	}
+	bio_endio(bio, bytes_done, 0);
+	return 0;
+fail:
+	bio_io_error(bio, bytes_done);
+	return 0;
+}
+
+/*
+ * The init/exit functions.
+ */
+static void __exit
+dcssblk_exit(void)
+{
+	int rc;
+
+	PRINT_DEBUG("DCSSBLOCK EXIT...\n");
+	s390_root_dev_unregister(dcssblk_root_dev);
+	rc = unregister_blkdev(dcssblk_major, DCSSBLK_NAME);
+	if (rc) {
+		PRINT_ERR("unregister_blkdev() failed!\n");
+	}
+	PRINT_DEBUG("...finished!\n");
+}
+
+static int __init
+dcssblk_init(void)
+{
+	int rc;
+
+	PRINT_DEBUG("DCSSBLOCK INIT...\n");
+	dcssblk_root_dev = s390_root_dev_register("dcssblk");
+	if (IS_ERR(dcssblk_root_dev)) {
+		PRINT_ERR("device_register() failed!\n");
+		return PTR_ERR(dcssblk_root_dev);
+	}
+	rc = device_create_file(dcssblk_root_dev, &dev_attr_add);
+	if (rc) {
+		PRINT_ERR("device_create_file(add) failed!\n");
+		s390_root_dev_unregister(dcssblk_root_dev);
+		return rc;
+	}
+	rc = device_create_file(dcssblk_root_dev, &dev_attr_remove);
+	if (rc) {
+		PRINT_ERR("device_create_file(remove) failed!\n");
+		s390_root_dev_unregister(dcssblk_root_dev);
+		return rc;
+	}
+	rc = register_blkdev(0, DCSSBLK_NAME);
+	if (rc < 0) {
+		PRINT_ERR("Can't get dynamic major!\n");
+		s390_root_dev_unregister(dcssblk_root_dev);
+		return rc;
+	}
+	dcssblk_major = rc;
+	PRINT_DEBUG("...finished!\n");
+	return 0;
+}
+
+module_init(dcssblk_init);
+module_exit(dcssblk_exit);
+
+MODULE_LICENSE("GPL");
--- diff/drivers/s390/cio/cmf.c	1970-01-01 01:00:00.000000000 +0100
+++ source/drivers/s390/cio/cmf.c	2004-02-23 13:56:45.000000000 +0000
@@ -0,0 +1,1033 @@
+/*
+ * linux/drivers/s390/cio/cmf.c ($Revision: 1.11 $)
+ *
+ * Linux on zSeries Channel Measurement Facility support
+ *
+ * Copyright 2000,2003 IBM Corporation
+ *
+ * Author: Arnd Bergmann <arndb@de.ibm.com>
+ *
+ * original idea from Natarajan Krishnaswami <nkrishna@us.ibm.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/bootmem.h>
+#include <linux/device.h>
+#include <linux/init.h>
+#include <linux/list.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+
+#include <asm/ccwdev.h>
+#include <asm/cio.h>
+#include <asm/cmb.h>
+
+#include "cio.h"
+#include "css.h"
+#include "device.h"
+#include "ioasm.h"
+
+/* parameter to enable cmf during boot, possible uses are:
+ *  "s390cmf" -- enable cmf and allocate 2 MB of ram so measuring can be
+ *               used on any subchannel
+ *  "s390cmf=<num>" -- enable cmf and allocate enough memory to measure
+ *                     <num> subchannel, where <num> is an integer
+ *                     between 1 and 65535, default is 1024
+ */
+#define ARGSTRING "s390cmf"
+
+/* indices for READCMB */
+enum cmb_index {
+ /* basic and exended format: */
+	cmb_ssch_rsch_count,
+	cmb_sample_count,
+	cmb_device_connect_time,
+	cmb_function_pending_time,
+	cmb_device_disconnect_time,
+	cmb_control_unit_queuing_time,
+	cmb_device_active_only_time,
+ /* extended format only: */
+	cmb_device_busy_time,
+	cmb_initial_command_response_time,
+};
+
+/**
+ * enum cmb_format - types of supported measurement block formats
+ *
+ * @CMF_BASIC:      traditional channel measurement blocks supported
+ * 		    by all machines that we run on
+ * @CMF_EXTENDED:   improved format that was introduced with the z990
+ * 		    machine
+ * @CMF_AUTODETECT: default: use extended format when running on a z990
+ *                  or later machine, otherwise fall back to basic format
+ **/
+enum cmb_format {
+	CMF_BASIC,
+	CMF_EXTENDED,
+	CMF_AUTODETECT = -1,
+};
+/**
+ * format - actual format for all measurement blocks
+ *
+ * The format module parameter can be set to a value of 0 (zero)
+ * or 1, indicating basic or extended format as described for
+ * enum cmb_format.
+ */
+static int format = CMF_AUTODETECT;
+module_param(format, bool, 0444);
+
+/**
+ * struct cmb_operations - functions to use depending on cmb_format
+ *
+ * all these functions operate on a struct cmf_device. There is only
+ * one instance of struct cmb_operations because all cmf_device
+ * objects are guaranteed to be of the same type.
+ *
+ * @alloc:	allocate memory for a channel measurement block,
+ *		either with the help of a special pool or with kmalloc
+ * @free:	free memory allocated with @alloc
+ * @set:	enable or disable measurement
+ * @readall:	read a measurement block in a common format
+ * @reset:	clear the data in the associated measurement block and
+ *		reset its time stamp
+ */
+struct cmb_operations {
+	int (*alloc)  (struct ccw_device*);
+	void(*free)   (struct ccw_device*);
+	int (*set)    (struct ccw_device*, u32);
+	u64 (*read)   (struct ccw_device*, int);
+	int (*readall)(struct ccw_device*, struct cmbdata *);
+	void (*reset) (struct ccw_device*);
+
+	struct attribute_group *attr_group;
+};
+static struct cmb_operations *cmbops;
+
+/* our user interface is designed in terms of nanoseconds,
+ * while the hardware measures total times in its own
+ * unit.*/
+static inline u64 time_to_nsec(u32 value)
+{
+	return ((u64)value) * 128000ull;
+}
+
+/*
+ * Users are usually interested in average times,
+ * not accumulated time.
+ * This also helps us with atomicity problems
+ * when reading sinlge values.
+ */
+static inline u64 time_to_avg_nsec(u32 value, u32 count)
+{
+	u64 ret;
+
+	/* no samples yet, avoid division by 0 */
+	if (count == 0)
+		return 0;
+
+	/* value comes in units of 128 µsec */
+	ret = time_to_nsec(value);
+	do_div(ret, count);
+
+	return ret;
+}
+
+/* activate or deactivate the channel monitor. When area is NULL,
+ * the monitor is deactivated. The channel monitor needs to
+ * be active in order to measure subchannels, which also need
+ * to be enabled. */
+static inline void
+cmf_activate(void *area, unsigned int onoff)
+{
+	register void * __gpr2 asm("2");
+	register long __gpr1 asm("1");
+
+	__gpr2 = area;
+	__gpr1 = onoff ? 2 : 0;
+	/* activate channel measurement */
+	asm("schm" : : "d" (__gpr2), "d" (__gpr1) );
+}
+
+static int
+set_schib(struct ccw_device *cdev, u32 mme, int mbfc, unsigned long address)
+{
+	int ret;
+	int retry;
+	struct subchannel *sch;
+	struct schib *schib;
+
+	sch = to_subchannel(cdev->dev.parent);
+	schib = &sch->schib;
+	/* msch can silently fail, so do it again if necessary */
+	for (retry = 0; retry < 3; retry++) {
+		/* prepare schib */
+		stsch(sch->irq, schib);
+		schib->pmcw.mme  = mme;
+		schib->pmcw.mbfc = mbfc;
+		/* address can be either a block address or a block index */
+		if (mbfc)
+			schib->mba = address;
+		else
+			schib->pmcw.mbi = address;
+
+		/* try to submit it */
+		switch(ret = msch_err(sch->irq, schib)) {
+			case 0:
+				break;
+			case 1:
+			case 2: /* in I/O or status pending */
+				ret = -EBUSY;
+				break;
+			case 3: /* subchannel is no longer valid */
+				ret = -ENODEV;
+				break;
+			default: /* msch caught an exception */
+				ret = -EINVAL;
+				break;
+		}
+		stsch(sch->irq, schib); /* restore the schib */
+
+		if (ret)
+			break;
+
+		/* check if it worked */
+		if (schib->pmcw.mme  == mme &&
+		    schib->pmcw.mbfc == mbfc &&
+		    (mbfc ? (schib->mba == address)
+			  : (schib->pmcw.mbi == address)))
+			return 0;
+
+		ret = -EINVAL;
+	}
+
+	return ret;
+}
+
+struct set_schib_struct {
+	u32 mme;
+	int mbfc;
+	unsigned long address;
+	wait_queue_head_t wait;
+	int ret;
+};
+
+static int set_schib_wait(struct ccw_device *cdev, u32 mme,
+				int mbfc, unsigned long address)
+{
+	struct set_schib_struct s = {
+		.mme = mme,
+		.mbfc = mbfc,
+		.address = address,
+		.wait = __WAIT_QUEUE_HEAD_INITIALIZER(s.wait),
+	};
+
+	spin_lock_irq(cdev->ccwlock);
+	s.ret = set_schib(cdev, mme, mbfc, address);
+	if (s.ret != -EBUSY) {
+		goto out_nowait;
+	}
+
+	if (cdev->private->state != DEV_STATE_ONLINE) {
+		s.ret = -EBUSY;
+		/* if the device is not online, don't even try again */
+		goto out_nowait;
+	}
+	cdev->private->state = DEV_STATE_CMFCHANGE;
+	cdev->private->cmb_wait = &s;
+	s.ret = 1;
+
+	spin_unlock_irq(cdev->ccwlock);
+	if (wait_event_interruptible(s.wait, s.ret != 1)) {
+		spin_lock_irq(cdev->ccwlock);
+		if (s.ret == 1) {
+			s.ret = -ERESTARTSYS;
+			cdev->private->cmb_wait = 0;
+			if (cdev->private->state == DEV_STATE_CMFCHANGE)
+				cdev->private->state = DEV_STATE_ONLINE;
+		}
+		spin_unlock_irq(cdev->ccwlock);
+	}
+	return s.ret;
+
+out_nowait:
+	spin_unlock_irq(cdev->ccwlock);
+	return s.ret;
+}
+
+void retry_set_schib(struct ccw_device *cdev)
+{
+	struct set_schib_struct *s;
+
+	s = cdev->private->cmb_wait;
+	cdev->private->cmb_wait = 0;
+	if (!s) {
+		WARN_ON(1);
+		return;
+	}
+	s->ret = set_schib(cdev, s->mme, s->mbfc, s->address);
+	wake_up(&s->wait);
+}
+
+/**
+ * struct cmb_area - container for global cmb data
+ *
+ * @mem:	pointer to CMBs (only in basic measurement mode)
+ * @list:	contains a linked list of all subchannels
+ * @lock:	protect concurrent access to @mem and @list
+ */
+struct cmb_area {
+	struct cmb *mem;
+	struct list_head list;
+	int num_channels;
+	spinlock_t lock;
+};
+
+static struct cmb_area cmb_area = {
+	.lock = SPIN_LOCK_UNLOCKED,
+	.list = LIST_HEAD_INIT(cmb_area.list),
+	.num_channels  = 1024,
+};
+
+
+/* ****** old style CMB handling ********/
+
+/** int maxchannels
+ *
+ * Basic channel measurement blocks are allocated in one contiguous
+ * block of memory, which can not be moved as long as any channel
+ * is active. Therefore, a maximum number of subchannels needs to
+ * be defined somewhere. This is a module parameter, defaulting to
+ * a resonable value of 1024, or 32 kb of memory.
+ * Current kernels don't allow kmalloc with more than 128kb, so the
+ * maximum is 4096
+ */
+
+module_param_named(maxchannels, cmb_area.num_channels, uint, 0444);
+
+/**
+ * struct cmb - basic channel measurement block
+ *
+ * cmb as used by the hardware the fields are described in z/Architecture
+ * Principles of Operation, chapter 17.
+ * The area to be a contiguous array and may not be reallocated or freed.
+ * Only one cmb area can be present in the system.
+ */
+struct cmb {
+	u16 ssch_rsch_count;
+	u16 sample_count;
+	u32 device_connect_time;
+	u32 function_pending_time;
+	u32 device_disconnect_time;
+	u32 control_unit_queuing_time;
+	u32 device_active_only_time;
+	u32 reserved[2];
+};
+
+/* insert a single device into the cmb_area list
+ * called with cmb_area.lock held from alloc_cmb
+ */
+static inline int
+alloc_cmb_single (struct ccw_device *cdev)
+{
+	struct cmb *cmb;
+	struct ccw_device_private *node;
+	int ret;
+
+	spin_lock_irq(cdev->ccwlock);
+	if (!list_empty(&cdev->private->cmb_list)) {
+		ret = -EBUSY;
+		goto out;
+	}
+
+	/* find first unused cmb in cmb_area.mem.
+	 * this is a little tricky: cmb_area.list
+	 * remains sorted by ->cmb pointers */
+	cmb = cmb_area.mem;
+	list_for_each_entry(node, &cmb_area.list, cmb_list) {
+		if ((struct cmb*)node->cmb > cmb)
+			break;
+		cmb++;
+	}
+	if (cmb - cmb_area.mem >= cmb_area.num_channels) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	/* insert new cmb */
+	list_add_tail(&cdev->private->cmb_list, &node->cmb_list);
+	cdev->private->cmb = cmb;
+	ret = 0;
+out:
+	spin_unlock_irq(cdev->ccwlock);
+	return ret;
+}
+
+static int
+alloc_cmb (struct ccw_device *cdev)
+{
+	int ret;
+	struct cmb *mem;
+	ssize_t size;
+
+	spin_lock(&cmb_area.lock);
+
+	if (!cmb_area.mem) {
+		/* there is no user yet, so we need a new area */
+		size = sizeof(struct cmb) * cmb_area.num_channels;
+		WARN_ON(!list_empty(&cmb_area.list));
+
+		spin_unlock(&cmb_area.lock);
+		mem = kmalloc(size, GFP_KERNEL | GFP_DMA);
+		spin_lock(&cmb_area.lock);
+
+		if (cmb_area.mem) {
+			/* ok, another thread was faster */
+			kfree(mem);
+		} else if (!mem) {
+			/* no luck */
+			ret = -ENOMEM;
+			goto out;
+		} else {
+			/* everything ok */
+			memset(mem, 0, size);
+			cmb_area.mem = mem;
+			cmf_activate(cmb_area.mem, 1);
+		}
+	}
+
+	/* do the actual allocation */
+	ret = alloc_cmb_single(cdev);
+out:
+	spin_unlock(&cmb_area.lock);
+
+	return ret;
+}
+
+static void
+free_cmb(struct ccw_device *cdev)
+{
+	struct ccw_device_private *priv;
+
+	priv = cdev->private;
+
+	spin_lock(&cmb_area.lock);
+	spin_lock_irq(cdev->ccwlock);
+
+	if (list_empty(&priv->cmb_list)) {
+		/* already freed */
+		goto out;
+	}
+
+	priv->cmb = NULL;
+	list_del_init(&priv->cmb_list);
+
+	if (list_empty(&cmb_area.list)) {
+		cmf_activate(NULL, 0);
+		kfree(cmb_area.mem);
+		cmb_area.mem = NULL;
+	}
+out:
+	spin_unlock_irq(cdev->ccwlock);
+	spin_unlock(&cmb_area.lock);
+}
+
+static int
+set_cmb(struct ccw_device *cdev, u32 mme)
+{
+	u16 offset;
+
+	if (!cdev->private->cmb)
+		return -EINVAL;
+
+	offset = mme ? (struct cmb *)cdev->private->cmb - cmb_area.mem : 0;
+
+	return set_schib_wait(cdev, mme, 0, offset);
+}
+
+static u64
+read_cmb (struct ccw_device *cdev, int index)
+{
+	/* yes, we have to put it on the stack
+	 * because the cmb must only be accessed
+	 * atomically, e.g. with mvc */
+	struct cmb cmb;
+	unsigned long flags;
+	u32 val;
+
+	spin_lock_irqsave(cdev->ccwlock, flags);
+	if (!cdev->private->cmb) {
+		spin_unlock_irqrestore(cdev->ccwlock, flags);
+		return 0;
+	}
+
+	cmb = *(struct cmb*)cdev->private->cmb;
+	spin_unlock_irqrestore(cdev->ccwlock, flags);
+
+	switch (index) {
+	case cmb_ssch_rsch_count:
+		return cmb.ssch_rsch_count;
+	case cmb_sample_count:
+		return cmb.sample_count;
+	case cmb_device_connect_time:
+		val = cmb.device_connect_time;
+		break;
+	case cmb_function_pending_time:
+		val = cmb.function_pending_time;
+		break;
+	case cmb_device_disconnect_time:
+		val = cmb.device_disconnect_time;
+		break;
+	case cmb_control_unit_queuing_time:
+		val = cmb.control_unit_queuing_time;
+		break;
+	case cmb_device_active_only_time:
+		val = cmb.device_active_only_time;
+		break;
+	default:
+		return 0;
+	}
+	return time_to_avg_nsec(val, cmb.sample_count);
+}
+
+static int
+readall_cmb (struct ccw_device *cdev, struct cmbdata *data)
+{
+	/* yes, we have to put it on the stack
+	 * because the cmb must only be accessed
+	 * atomically, e.g. with mvc */
+	struct cmb cmb;
+	unsigned long flags;
+	u64 time;
+
+	spin_lock_irqsave(cdev->ccwlock, flags);
+	if (!cdev->private->cmb) {
+		spin_unlock_irqrestore(cdev->ccwlock, flags);
+		return -ENODEV;
+	}
+
+	cmb = *(struct cmb*)cdev->private->cmb;
+	time = get_clock() - cdev->private->cmb_start_time;
+	spin_unlock_irqrestore(cdev->ccwlock, flags);
+
+	*data = (struct cmbdata) {
+		/* we only know values before device_busy_time */
+		.size = offsetof(struct cmbdata, device_busy_time),
+
+		/* conver to nanoseconds */
+		.elapsed_time = (time * 1000) >> 12,
+
+		/* copy data to new structure */
+		.ssch_rsch_count		= cmb.ssch_rsch_count,
+		.sample_count			= cmb.sample_count,
+
+		/* time fields are converted to nanoseconds while copying */
+		.device_connect_time
+			= time_to_nsec(cmb.device_connect_time),
+		.function_pending_time
+			= time_to_nsec(cmb.function_pending_time),
+		.device_disconnect_time
+			= time_to_nsec(cmb.device_disconnect_time),
+		.control_unit_queuing_time
+		 	= time_to_nsec(cmb.control_unit_queuing_time),
+		.device_active_only_time
+			= time_to_nsec(cmb.device_active_only_time),
+	};
+
+	return 0;
+}
+
+static void
+reset_cmb(struct ccw_device *cdev)
+{
+	struct cmb *cmb;
+	spin_lock_irq(cdev->ccwlock);
+	cmb = cdev->private->cmb;
+	if (cmb)
+		memset (cmb, 0, sizeof (*cmb));
+	cdev->private->cmb_start_time = get_clock();
+	spin_unlock_irq(cdev->ccwlock);
+}
+
+static struct attribute_group cmf_attr_group;
+
+static struct cmb_operations cmbops_basic = {
+	.alloc	= alloc_cmb,
+	.free	= free_cmb,
+	.set	= set_cmb,
+	.read	= read_cmb,
+	.readall    = readall_cmb,
+	.reset	    = reset_cmb,
+	.attr_group = &cmf_attr_group,
+};
+
+/* ******** extended cmb handling ********/
+
+/**
+ * struct cmbe - extended channel measurement block
+ *
+ * cmb as used by the hardware, may be in any 64 bit physical location,
+ * the fields are described in z/Architecture Principles of Operation,
+ * third edition, chapter 17.
+ */
+struct cmbe {
+	u32 ssch_rsch_count;
+	u32 sample_count;
+	u32 device_connect_time;
+	u32 function_pending_time;
+	u32 device_disconnect_time;
+	u32 control_unit_queuing_time;
+	u32 device_active_only_time;
+	u32 device_busy_time;
+	u32 initial_command_response_time;
+	u32 reserved[7];
+};
+
+static int
+alloc_cmbe (struct ccw_device *cdev)
+{
+	struct cmbe *cmbe;
+	cmbe = kmalloc (sizeof (*cmbe), GFP_KERNEL /* | GFP_DMA ? */);
+	if (!cmbe)
+		return -ENOMEM;
+
+	spin_lock_irq(cdev->ccwlock);
+	if (cdev->private->cmb) {
+		kfree(cmbe);
+		spin_unlock_irq(cdev->ccwlock);
+		return -EBUSY;
+	}
+
+	cdev->private->cmb = cmbe;
+	spin_unlock_irq(cdev->ccwlock);
+
+	/* activate global measurement if this is the first channel */
+	spin_lock(&cmb_area.lock);
+	if (list_empty(&cmb_area.list))
+		cmf_activate(NULL, 1);
+	list_add_tail(&cdev->private->cmb_list, &cmb_area.list);
+	spin_unlock(&cmb_area.lock);
+
+	return 0;
+}
+
+static void
+free_cmbe (struct ccw_device *cdev)
+{
+	spin_lock_irq(cdev->ccwlock);
+	if (cdev->private->cmb)
+		kfree(cdev->private->cmb);
+	cdev->private->cmb = NULL;
+	spin_unlock_irq(cdev->ccwlock);
+
+	/* deactivate global measurement if this is the last channel */
+	spin_lock(&cmb_area.lock);
+	list_del_init(&cdev->private->cmb_list);
+	if (list_empty(&cmb_area.list))
+		cmf_activate(NULL, 0);
+	spin_unlock(&cmb_area.lock);
+}
+
+static int
+set_cmbe(struct ccw_device *cdev, u32 mme)
+{
+	unsigned long mba;
+
+	if (!cdev->private->cmb)
+		return -EINVAL;
+	mba = mme ? (unsigned long)cdev->private->cmb : 0;
+
+	return set_schib_wait(cdev, mme, 1, mba);
+}
+
+
+u64
+read_cmbe (struct ccw_device *cdev, int index)
+{
+	/* yes, we have to put it on the stack
+	 * because the cmb must only be accessed
+	 * atomically, e.g. with mvc */
+	struct cmbe cmb;
+	unsigned long flags;
+	u32 val;
+
+	spin_lock_irqsave(cdev->ccwlock, flags);
+	if (!cdev->private->cmb) {
+		spin_unlock_irqrestore(cdev->ccwlock, flags);
+		return 0;
+	}
+
+	cmb = *(struct cmbe*)cdev->private->cmb;
+	spin_unlock_irqrestore(cdev->ccwlock, flags);
+
+	switch (index) {
+	case cmb_ssch_rsch_count:
+		return cmb.ssch_rsch_count;
+	case cmb_sample_count:
+		return cmb.sample_count;
+	case cmb_device_connect_time:
+		val = cmb.device_connect_time;
+		break;
+	case cmb_function_pending_time:
+		val = cmb.function_pending_time;
+		break;
+	case cmb_device_disconnect_time:
+		val = cmb.device_disconnect_time;
+		break;
+	case cmb_control_unit_queuing_time:
+		val = cmb.control_unit_queuing_time;
+		break;
+	case cmb_device_active_only_time:
+		val = cmb.device_active_only_time;
+		break;
+	case cmb_device_busy_time:
+		val = cmb.device_busy_time;
+		break;
+	case cmb_initial_command_response_time:
+		val = cmb.initial_command_response_time;
+		break;
+	default:
+		return 0;
+	}
+	return time_to_avg_nsec(val, cmb.sample_count);
+}
+
+static int
+readall_cmbe (struct ccw_device *cdev, struct cmbdata *data)
+{
+	/* yes, we have to put it on the stack
+	 * because the cmb must only be accessed
+	 * atomically, e.g. with mvc */
+	struct cmbe cmb;
+	unsigned long flags;
+	u64 time;
+
+	spin_lock_irqsave(cdev->ccwlock, flags);
+	if (!cdev->private->cmb) {
+		spin_unlock_irqrestore(cdev->ccwlock, flags);
+		return -ENODEV;
+	}
+
+	cmb = *(struct cmbe*)cdev->private->cmb;
+	time = get_clock() - cdev->private->cmb_start_time;
+	spin_unlock_irqrestore(cdev->ccwlock, flags);
+
+	*data = (struct cmbdata) {
+		/* we only know values before device_busy_time */
+		.size = offsetof(struct cmbdata, device_busy_time),
+
+		/* conver to nanoseconds */
+		.elapsed_time = (time * 1000) >> 12,
+
+		/* copy data to new structure */
+		.ssch_rsch_count		= cmb.ssch_rsch_count,
+		.sample_count			= cmb.sample_count,
+
+		/* time fields are converted to nanoseconds while copying */
+		.device_connect_time
+			= time_to_nsec(cmb.device_connect_time),
+		.function_pending_time
+			= time_to_nsec(cmb.function_pending_time),
+		.device_disconnect_time
+			= time_to_nsec(cmb.device_disconnect_time),
+		.control_unit_queuing_time
+		 	= time_to_nsec(cmb.control_unit_queuing_time),
+		.device_active_only_time
+			= time_to_nsec(cmb.device_active_only_time),
+		.device_busy_time
+			= time_to_nsec(cmb.device_busy_time),
+		.initial_command_response_time
+			= time_to_nsec(cmb.initial_command_response_time),
+	};
+
+	return 0;
+}
+
+static void
+reset_cmbe(struct ccw_device *cdev)
+{
+	struct cmbe *cmb;
+	spin_lock_irq(cdev->ccwlock);
+	cmb = cdev->private->cmb;
+	if (cmb)
+		memset (cmb, 0, sizeof (*cmb));
+	cdev->private->cmb_start_time = get_clock();
+	spin_unlock_irq(cdev->ccwlock);
+}
+
+static struct attribute_group cmf_attr_group_ext;
+
+static struct cmb_operations cmbops_extended = {
+	.alloc	    = alloc_cmbe,
+	.free	    = free_cmbe,
+	.set	    = set_cmbe,
+	.read	    = read_cmbe,
+	.readall    = readall_cmbe,
+	.reset	    = reset_cmbe,
+	.attr_group = &cmf_attr_group_ext,
+};
+
+
+static ssize_t
+cmb_show_attr(struct device *dev, char *buf, enum cmb_index idx)
+{
+	return sprintf(buf, "%lld\n",
+		(unsigned long long) cmf_read(to_ccwdev(dev), idx));
+}
+
+static ssize_t
+cmb_show_avg_sample_interval(struct device *dev, char *buf)
+{
+	struct ccw_device *cdev;
+	long interval;
+	unsigned long count;
+
+	cdev = to_ccwdev(dev);
+	interval  = get_clock() - cdev->private->cmb_start_time;
+	count = cmf_read(cdev, cmb_sample_count);
+	if (count)
+		interval /= count;
+	else
+		interval = -1;
+	return sprintf(buf, "%ld\n", interval);
+}
+
+static ssize_t
+cmb_show_avg_utilization(struct device *dev, char *buf)
+{
+	struct cmbdata data;
+	u64 utilization;
+	unsigned long t, u;
+	int ret;
+
+	ret = cmf_readall(to_ccwdev(dev), &data);
+	if (ret)
+		return ret;
+
+	utilization = data.device_connect_time +
+		      data.function_pending_time +
+		      data.device_disconnect_time;
+
+	/* shift to avoid long long division */
+	while (-1ul < (data.elapsed_time | utilization)) {
+		utilization >>= 8;
+		data.elapsed_time >>= 8;
+	}
+
+	/* calculate value in 0.1 percent units */
+	t = (unsigned long) data.elapsed_time / 1000;
+	u = (unsigned long) utilization / t;
+
+	return sprintf(buf, "%02ld.%01ld%%\n", u/ 10, u - (u/ 10) * 10);
+}
+
+#define cmf_attr(name) \
+static ssize_t show_ ## name (struct device * dev, char * buf) \
+{ return cmb_show_attr((dev), buf, cmb_ ## name); } \
+static DEVICE_ATTR(name, 0444, show_ ## name, NULL);
+
+#define cmf_attr_avg(name) \
+static ssize_t show_avg_ ## name (struct device * dev, char * buf) \
+{ return cmb_show_attr((dev), buf, cmb_ ## name); } \
+static DEVICE_ATTR(avg_ ## name, 0444, show_avg_ ## name, NULL);
+
+cmf_attr(ssch_rsch_count);
+cmf_attr(sample_count);
+cmf_attr_avg(device_connect_time);
+cmf_attr_avg(function_pending_time);
+cmf_attr_avg(device_disconnect_time);
+cmf_attr_avg(control_unit_queuing_time);
+cmf_attr_avg(device_active_only_time);
+cmf_attr_avg(device_busy_time);
+cmf_attr_avg(initial_command_response_time);
+
+static DEVICE_ATTR(avg_sample_interval, 0444, cmb_show_avg_sample_interval, NULL);
+static DEVICE_ATTR(avg_utilization, 0444, cmb_show_avg_utilization, NULL);
+
+static struct attribute *cmf_attributes[] = {
+	&dev_attr_avg_sample_interval.attr,
+	&dev_attr_avg_utilization.attr,
+	&dev_attr_ssch_rsch_count.attr,
+	&dev_attr_sample_count.attr,
+	&dev_attr_avg_device_connect_time.attr,
+	&dev_attr_avg_function_pending_time.attr,
+	&dev_attr_avg_device_disconnect_time.attr,
+	&dev_attr_avg_control_unit_queuing_time.attr,
+	&dev_attr_avg_device_active_only_time.attr,
+	0,
+};
+
+static struct attribute_group cmf_attr_group = {
+	.name  = "cmf",
+	.attrs = cmf_attributes,
+};
+
+static struct attribute *cmf_attributes_ext[] = {
+	&dev_attr_avg_sample_interval.attr,
+	&dev_attr_avg_utilization.attr,
+	&dev_attr_ssch_rsch_count.attr,
+	&dev_attr_sample_count.attr,
+	&dev_attr_avg_device_connect_time.attr,
+	&dev_attr_avg_function_pending_time.attr,
+	&dev_attr_avg_device_disconnect_time.attr,
+	&dev_attr_avg_control_unit_queuing_time.attr,
+	&dev_attr_avg_device_active_only_time.attr,
+	&dev_attr_avg_device_busy_time.attr,
+	&dev_attr_avg_initial_command_response_time.attr,
+	0,
+};
+
+static struct attribute_group cmf_attr_group_ext = {
+	.name  = "cmf",
+	.attrs = cmf_attributes_ext,
+};
+
+static ssize_t cmb_enable_show(struct device *dev, char *buf)
+{
+	return sprintf(buf, "%d\n", to_ccwdev(dev)->private->cmb ? 1 : 0);
+}
+
+static ssize_t cmb_enable_store(struct device *dev, const char *buf, size_t c)
+{
+	struct ccw_device *cdev;
+	int ret;
+
+	cdev = to_ccwdev(dev);
+
+	switch (buf[0]) {
+	case '0':
+		ret = disable_cmf(cdev);
+		if (ret)
+			printk(KERN_INFO "disable_cmf failed (%d)\n", ret);
+		break;
+	case '1':
+		ret = enable_cmf(cdev);
+		if (ret && ret != -EBUSY)
+			printk(KERN_INFO "enable_cmf failed (%d)\n", ret);
+		break;
+	}
+
+	return c;
+}
+
+DEVICE_ATTR(cmb_enable, 0644, cmb_enable_show, cmb_enable_store);
+
+/* enable_cmf/disable_cmf: module interface for cmf (de)activation */
+int
+enable_cmf(struct ccw_device *cdev)
+{
+	int ret;
+
+	ret = cmbops->alloc(cdev);
+	cmbops->reset(cdev);
+	if (ret)
+		return ret;
+	ret = cmbops->set(cdev, 2);
+	if (ret) {
+		cmbops->free(cdev);
+		return ret;
+	}
+	ret = sysfs_create_group(&cdev->dev.kobj, cmbops->attr_group);
+	if (!ret)
+		return 0;
+	cmbops->set(cdev, 0);  //FIXME: this can fail
+	cmbops->free(cdev);
+	return ret;
+}
+
+int
+disable_cmf(struct ccw_device *cdev)
+{
+	int ret;
+
+	ret = cmbops->set(cdev, 0);
+	if (ret)
+		return ret;
+	cmbops->free(cdev);
+	sysfs_remove_group(&cdev->dev.kobj, cmbops->attr_group);
+	return ret;
+}
+
+u64
+cmf_read(struct ccw_device *cdev, int index)
+{
+	return cmbops->read(cdev, index);
+}
+
+int
+cmf_readall(struct ccw_device *cdev, struct cmbdata *data)
+{
+	return cmbops->readall(cdev, data);
+}
+
+static int __init
+init_cmf(void)
+{
+	char *format_string;
+	char *detect_string = "parameter";
+
+	/* We cannot really autoprobe this. If the user did not give a parameter,
+	   see if we are running on z990 or up, otherwise fall back to basic mode. */
+
+	if (format == CMF_AUTODETECT) {
+		if (!MACHINE_NEW_STIDP) {
+			format = CMF_BASIC;
+		} else {
+			format = CMF_EXTENDED;
+		}
+		detect_string = "autodetected";
+	} else {
+		detect_string = "parameter";
+	}
+
+	switch (format) {
+	case CMF_BASIC:
+		format_string = "basic";
+		cmbops = &cmbops_basic;
+		if (cmb_area.num_channels > 4096 || cmb_area.num_channels < 1) {
+			printk(KERN_ERR "Basic channel measurement facility"
+					" can only use 1 to 4096 devices\n"
+			       KERN_ERR "when the cmf driver is built"
+					" as a loadable module\n");
+			return 1;
+		}
+		break;
+	case CMF_EXTENDED:
+ 		format_string = "extended";
+		cmbops = &cmbops_extended;
+		break;
+	default:
+		printk(KERN_ERR "Invalid format %d for channel "
+			"measurement facility\n", format);
+		return 1;
+	}
+
+	printk(KERN_INFO "Channel measurement facility using %s format (%s)\n",
+		format_string, detect_string);
+	return 0;
+}
+
+module_init(init_cmf);
+
+
+MODULE_AUTHOR("Arnd Bergmann <arndb@de.ibm.com>");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("channel measurement facility base driver\n"
+		   "Copyright 2003 IBM Corporation\n");
+
+EXPORT_SYMBOL_GPL(enable_cmf);
+EXPORT_SYMBOL_GPL(disable_cmf);
+EXPORT_SYMBOL_GPL(cmf_read);
+EXPORT_SYMBOL_GPL(cmf_readall);
--- diff/drivers/s390/net/smsgiucv.c	1970-01-01 01:00:00.000000000 +0100
+++ source/drivers/s390/net/smsgiucv.c	2004-02-23 13:56:45.000000000 +0000
@@ -0,0 +1,180 @@
+/*
+ * IUCV special message driver
+ *
+ * Copyright (C) 2003 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ * Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/device.h>
+#include <asm/cpcmd.h>
+#include <asm/ebcdic.h>
+
+#include "iucv.h"
+
+struct smsg_callback {
+	struct list_head list;
+	char *prefix;
+	int len;
+	void (*callback)(char *str);
+};
+
+MODULE_AUTHOR
+   ("(C) 2003 IBM Corporation by Martin Schwidefsky (schwidefsky@de.ibm.com)");
+MODULE_DESCRIPTION ("Linux for S/390 IUCV special message driver");
+
+static iucv_handle_t smsg_handle;
+static unsigned short smsg_pathid;
+static spinlock_t smsg_list_lock = SPIN_LOCK_UNLOCKED;
+static struct list_head smsg_list = LIST_HEAD_INIT(smsg_list);
+
+static void
+smsg_connection_complete(iucv_ConnectionComplete *eib, void *pgm_data)
+{
+}
+
+
+static void
+smsg_message_pending(iucv_MessagePending *eib, void *pgm_data)
+{
+	struct smsg_callback *cb;
+	unsigned char *msg;
+	unsigned short len;
+	int rc;
+
+	len = eib->ln1msg2.ipbfln1f;
+	msg = kmalloc(len + 1, GFP_ATOMIC|GFP_DMA);
+	if (!msg) {
+		iucv_reject(eib->ippathid, eib->ipmsgid, eib->iptrgcls);
+		return;
+	}
+	rc = iucv_receive(eib->ippathid, eib->ipmsgid, eib->iptrgcls,
+			  msg, len, 0, 0, 0);
+	if (rc == 0) {
+		msg[len] = 0;
+		EBCASC(msg, len);
+		spin_lock(&smsg_list_lock);
+		list_for_each_entry(cb, &smsg_list, list)
+			if (strncmp(msg + 8, cb->prefix, cb->len) == 0) {
+				cb->callback(msg + 8);
+				break;
+			}
+		spin_unlock(&smsg_list_lock);
+	}
+	kfree(msg);
+}
+
+static iucv_interrupt_ops_t smsg_ops = {
+	.ConnectionComplete = smsg_connection_complete,
+	.MessagePending     = smsg_message_pending,
+};
+
+static struct device_driver smsg_driver = {
+	.name = "SMSGIUCV",
+	.bus  = &iucv_bus,
+};
+
+int
+smsg_register_callback(char *prefix, void (*callback)(char *str))
+{
+	struct smsg_callback *cb;
+
+	cb = kmalloc(sizeof(struct smsg_callback), GFP_KERNEL);
+	if (!cb)
+		return -ENOMEM;
+	cb->prefix = prefix;
+	cb->len = strlen(prefix);
+	cb->callback = callback;
+	spin_lock(&smsg_list_lock);
+	list_add_tail(&cb->list, &smsg_list);
+	spin_unlock(&smsg_list_lock);
+	return 0;
+}
+
+void
+smsg_unregister_callback(char *prefix, void (*callback)(char *str))
+{
+	struct smsg_callback *cb, *tmp;
+
+	spin_lock(&smsg_list_lock);
+	cb = 0;
+	list_for_each_entry(tmp, &smsg_list, list)
+		if (tmp->callback == callback &&
+		    strcmp(tmp->prefix, prefix) == 0) {
+			cb = tmp;
+			list_del(&cb->list);
+			break;
+		}
+	spin_unlock(&smsg_list_lock);
+	kfree(cb);
+}
+
+static void __exit
+smsg_exit(void)
+{
+	if (smsg_handle > 0) {
+		cpcmd("SET SMSG OFF", 0, 0);
+		iucv_sever(smsg_pathid, 0);
+		iucv_unregister_program(smsg_handle);
+		driver_unregister(&smsg_driver);
+	}
+	return;
+}
+
+static int __init
+smsg_init(void)
+{
+	static unsigned char pgmmask[24] = {
+		0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
+	};
+	int rc;
+
+	rc = driver_register(&smsg_driver);
+	if (rc != 0) {
+		printk(KERN_ERR "SMSGIUCV: failed to register driver.\n");
+		return rc;
+	}
+	smsg_handle = iucv_register_program("SMSGIUCV        ", "*MSG    ",
+					    pgmmask, &smsg_ops, 0);
+	if (!smsg_handle) {
+		printk(KERN_ERR "SMSGIUCV: failed to register to iucv");
+		driver_unregister(&smsg_driver);
+		return -EIO;	/* better errno ? */
+	}
+	rc = iucv_connect (&smsg_pathid, 1, 0, "*MSG    ", 0, 0, 0, 0,
+			   smsg_handle, 0);
+	if (rc) {
+		printk(KERN_ERR "SMSGIUCV: failed to connect to *MSG");
+		iucv_unregister_program(smsg_handle);
+		driver_unregister(&smsg_driver);
+		smsg_handle = 0;
+		return -EIO;
+	}
+	cpcmd("SET SMSG IUCV", 0, 0);
+	return 0;
+}
+
+module_init(smsg_init);
+module_exit(smsg_exit);
+MODULE_LICENSE("GPL");
+
+EXPORT_SYMBOL(smsg_register_callback);
+EXPORT_SYMBOL(smsg_unregister_callback);
--- diff/drivers/s390/net/smsgiucv.h	1970-01-01 01:00:00.000000000 +0100
+++ source/drivers/s390/net/smsgiucv.h	2004-02-23 13:56:45.000000000 +0000
@@ -0,0 +1,10 @@
+/*
+ * IUCV special message driver
+ *
+ * Copyright (C) 2003 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ * Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com)
+ */
+
+int  smsg_register_callback(char *, void (*)(char *));
+void smsg_unregister_callback(char *, void (*)(char *));
+
--- diff/drivers/scsi/aacraid/rkt.c	1970-01-01 01:00:00.000000000 +0100
+++ source/drivers/scsi/aacraid/rkt.c	2004-02-23 13:56:45.000000000 +0000
@@ -0,0 +1,448 @@
+/*
+ *	Adaptec AAC series RAID controller driver
+ *	(c) Copyright 2001 Red Hat Inc.	<alan@redhat.com>
+ *
+ * based on the old aacraid driver that is..
+ * Adaptec aacraid device driver for Linux.
+ *
+ * Copyright (c) 2000 Adaptec, Inc. (aacraid@adaptec.com)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING.  If not, write to
+ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Module Name:
+ *  rkt.c
+ *
+ * Abstract: Hardware miniport for Drawbridge specific hardware functions.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/sched.h>
+#include <linux/pci.h>
+#include <linux/spinlock.h>
+#include <linux/slab.h>
+#include <linux/blkdev.h>
+#include <linux/delay.h>
+#include <linux/completion.h>
+#include <linux/interrupt.h>
+#include <asm/semaphore.h>
+
+#include <scsi/scsi_host.h>
+
+#include "aacraid.h"
+
+static irqreturn_t aac_rkt_intr(int irq, void *dev_id, struct pt_regs *regs)
+{
+	struct aac_dev *dev = dev_id;
+	unsigned long bellbits;
+	u8 intstat, mask;
+	intstat = rkt_readb(dev, MUnit.OISR);
+	/*
+	 *	Read mask and invert because drawbridge is reversed.
+	 *	This allows us to only service interrupts that have 
+	 *	been enabled.
+	 */
+	mask = ~(dev->OIMR);
+	/* Check to see if this is our interrupt.  If it isn't just return */
+	if (intstat & mask) 
+	{
+		bellbits = rkt_readl(dev, OutboundDoorbellReg);
+		if (bellbits & DoorBellPrintfReady) {
+			aac_printf(dev, le32_to_cpu(rkt_readl (dev, IndexRegs.Mailbox[5])));
+			rkt_writel(dev, MUnit.ODR,DoorBellPrintfReady);
+			rkt_writel(dev, InboundDoorbellReg,DoorBellPrintfDone);
+		}
+		else if (bellbits & DoorBellAdapterNormCmdReady) {
+			aac_command_normal(&dev->queues->queue[HostNormCmdQueue]);
+			rkt_writel(dev, MUnit.ODR, DoorBellAdapterNormCmdReady);
+		}
+		else if (bellbits & DoorBellAdapterNormRespReady) {
+			aac_response_normal(&dev->queues->queue[HostNormRespQueue]);
+			rkt_writel(dev, MUnit.ODR,DoorBellAdapterNormRespReady);
+		}
+		else if (bellbits & DoorBellAdapterNormCmdNotFull) {
+			rkt_writel(dev, MUnit.ODR, DoorBellAdapterNormCmdNotFull);
+		}
+		else if (bellbits & DoorBellAdapterNormRespNotFull) {
+			rkt_writel(dev, MUnit.ODR, DoorBellAdapterNormCmdNotFull);
+			rkt_writel(dev, MUnit.ODR, DoorBellAdapterNormRespNotFull);
+		}
+		return IRQ_HANDLED;
+	}
+	return IRQ_NONE;
+}
+
+/**
+ *	aac_rkt_enable_interrupt	-	Enable event reporting
+ *	@dev: Adapter
+ *	@event: Event to enable
+ *
+ *	Enable event reporting from the i960 for a given event.
+ */
+ 
+static void aac_rkt_enable_interrupt(struct aac_dev * dev, u32 event)
+{
+	switch (event) {
+
+	case HostNormCmdQue:
+		dev->irq_mask &= ~(OUTBOUNDDOORBELL_1);
+		break;
+
+	case HostNormRespQue:
+		dev->irq_mask &= ~(OUTBOUNDDOORBELL_2);
+		break;
+
+	case AdapNormCmdNotFull:
+		dev->irq_mask &= ~(OUTBOUNDDOORBELL_3);
+		break;
+
+	case AdapNormRespNotFull:
+		dev->irq_mask &= ~(OUTBOUNDDOORBELL_4);
+		break;
+	}
+}
+
+/**
+ *	aac_rkt_disable_interrupt	-	Disable event reporting
+ *	@dev: Adapter
+ *	@event: Event to enable
+ *
+ *	Disable event reporting from the i960 for a given event.
+ */
+
+static void aac_rkt_disable_interrupt(struct aac_dev *dev, u32 event)
+{
+	switch (event) {
+
+	case HostNormCmdQue:
+		dev->irq_mask |= (OUTBOUNDDOORBELL_1);
+		break;
+
+	case HostNormRespQue:
+		dev->irq_mask |= (OUTBOUNDDOORBELL_2);
+		break;
+
+	case AdapNormCmdNotFull:
+		dev->irq_mask |= (OUTBOUNDDOORBELL_3);
+		break;
+
+	case AdapNormRespNotFull:
+		dev->irq_mask |= (OUTBOUNDDOORBELL_4);
+		break;
+	}
+}
+
+/**
+ *	rkt_sync_cmd	-	send a command and wait
+ *	@dev: Adapter
+ *	@command: Command to execute
+ *	@p1: first parameter
+ *	@ret: adapter status
+ *
+ *	This routine will send a synchronous comamnd to the adapter and wait 
+ *	for its	completion.
+ */
+
+static int rkt_sync_cmd(struct aac_dev *dev, u32 command, u32 p1, u32 *status)
+{
+	unsigned long start;
+	int ok;
+	/*
+	 *	Write the command into Mailbox 0
+	 */
+	rkt_writel(dev, InboundMailbox0, cpu_to_le32(command));
+	/*
+	 *	Write the parameters into Mailboxes 1 - 4
+	 */
+	rkt_writel(dev, InboundMailbox1, cpu_to_le32(p1));
+	rkt_writel(dev, InboundMailbox2, 0);
+	rkt_writel(dev, InboundMailbox3, 0);
+	rkt_writel(dev, InboundMailbox4, 0);
+	/*
+	 *	Clear the synch command doorbell to start on a clean slate.
+	 */
+	rkt_writel(dev, OutboundDoorbellReg, OUTBOUNDDOORBELL_0);
+	/*
+	 *	Disable doorbell interrupts
+	 */
+	rkt_writeb(dev, MUnit.OIMR, dev->OIMR |= 0x04);
+	/*
+	 *	Force the completion of the mask register write before issuing
+	 *	the interrupt.
+	 */
+	rkt_readb (dev, MUnit.OIMR);
+	/*
+	 *	Signal that there is a new synch command
+	 */
+	rkt_writel(dev, InboundDoorbellReg, INBOUNDDOORBELL_0);
+
+	ok = 0;
+	start = jiffies;
+
+	/*
+	 *	Wait up to 30 seconds
+	 */
+	while (time_before(jiffies, start+30*HZ)) 
+	{
+		udelay(5);	/* Delay 5 microseconds to let Mon960 get info. */
+		/*
+		 *	Mon960 will set doorbell0 bit when it has completed the command.
+		 */
+		if (rkt_readl(dev, OutboundDoorbellReg) & OUTBOUNDDOORBELL_0) {
+			/*
+			 *	Clear the doorbell.
+			 */
+			rkt_writel(dev, OutboundDoorbellReg, OUTBOUNDDOORBELL_0);
+			ok = 1;
+			break;
+		}
+		/*
+		 *	Yield the processor in case we are slow 
+		 */
+		set_current_state(TASK_UNINTERRUPTIBLE);
+		schedule_timeout(1);
+	}
+	if (ok != 1) {
+		/*
+		 *	Restore interrupt mask even though we timed out
+		 */
+		rkt_writeb(dev, MUnit.OIMR, dev->OIMR &= 0xfb);
+		return -ETIMEDOUT;
+	}
+	/*
+	 *	Pull the synch status from Mailbox 0.
+	 */
+	*status = le32_to_cpu(rkt_readl(dev, IndexRegs.Mailbox[0]));
+	/*
+	 *	Clear the synch command doorbell.
+	 */
+	rkt_writel(dev, OutboundDoorbellReg, OUTBOUNDDOORBELL_0);
+	/*
+	 *	Restore interrupt mask
+	 */
+	rkt_writeb(dev, MUnit.OIMR, dev->OIMR &= 0xfb);
+	return 0;
+
+}
+
+/**
+ *	aac_rkt_interrupt_adapter	-	interrupt adapter
+ *	@dev: Adapter
+ *
+ *	Send an interrupt to the i960 and breakpoint it.
+ */
+
+static void aac_rkt_interrupt_adapter(struct aac_dev *dev)
+{
+	u32 ret;
+	rkt_sync_cmd(dev, BREAKPOINT_REQUEST, 0, &ret);
+}
+
+/**
+ *	aac_rkt_notify_adapter		-	send an event to the adapter
+ *	@dev: Adapter
+ *	@event: Event to send
+ *
+ *	Notify the i960 that something it probably cares about has
+ *	happened.
+ */
+
+static void aac_rkt_notify_adapter(struct aac_dev *dev, u32 event)
+{
+	switch (event) {
+
+	case AdapNormCmdQue:
+		rkt_writel(dev, MUnit.IDR,INBOUNDDOORBELL_1);
+		break;
+	case HostNormRespNotFull:
+		rkt_writel(dev, MUnit.IDR,INBOUNDDOORBELL_4);
+		break;
+	case AdapNormRespQue:
+		rkt_writel(dev, MUnit.IDR,INBOUNDDOORBELL_2);
+		break;
+	case HostNormCmdNotFull:
+		rkt_writel(dev, MUnit.IDR,INBOUNDDOORBELL_3);
+		break;
+	case HostShutdown:
+//		rkt_sync_cmd(dev, HOST_CRASHING, 0, 0, 0, 0, &ret);
+		break;
+	case FastIo:
+		rkt_writel(dev, MUnit.IDR,INBOUNDDOORBELL_6);
+		break;
+	case AdapPrintfDone:
+		rkt_writel(dev, MUnit.IDR,INBOUNDDOORBELL_5);
+		break;
+	default:
+		BUG();
+		break;
+	}
+}
+
+/**
+ *	aac_rkt_start_adapter		-	activate adapter
+ *	@dev:	Adapter
+ *
+ *	Start up processing on an i960 based AAC adapter
+ */
+
+static void aac_rkt_start_adapter(struct aac_dev *dev)
+{
+	u32 status;
+	struct aac_init *init;
+
+	init = dev->init;
+	init->HostElapsedSeconds = cpu_to_le32(jiffies/HZ);
+	/*
+	 *	Tell the adapter we are back and up and running so it will scan
+	 *	its command queues and enable our interrupts
+	 */
+	dev->irq_mask = (DoorBellPrintfReady | OUTBOUNDDOORBELL_1 | OUTBOUNDDOORBELL_2 | OUTBOUNDDOORBELL_3 | OUTBOUNDDOORBELL_4);
+	/*
+	 *	First clear out all interrupts.  Then enable the one's that we
+	 *	can handle.
+	 */
+	rkt_writeb(dev, MUnit.OIMR, 0xff);
+	rkt_writel(dev, MUnit.ODR, 0xffffffff);
+//	rkt_writeb(dev, MUnit.OIMR, ~(u8)OUTBOUND_DOORBELL_INTERRUPT_MASK);
+	rkt_writeb(dev, MUnit.OIMR, dev->OIMR = 0xfb);
+
+	// We can only use a 32 bit address here
+	rkt_sync_cmd(dev, INIT_STRUCT_BASE_ADDRESS, (u32)(ulong)dev->init_pa, &status);
+}
+
+/**
+ *	aac_rkt_check_health
+ *	@dev: device to check if healthy
+ *
+ *	Will attempt to determine if the specified adapter is alive and
+ *	capable of handling requests, returning 0 if alive.
+ */
+static int aac_rkt_check_health(struct aac_dev *dev)
+{
+	long status = rkt_readl(dev, IndexRegs.Mailbox[7]);
+
+	/*
+	 *	Check to see if the board failed any self tests.
+	 */
+	if (status & SELF_TEST_FAILED)
+		return -1;
+	/*
+	 *	Check to see if the board panic'd while booting.
+	 */
+	if (status & KERNEL_PANIC)
+		return -2;
+	/*
+	 *	Wait for the adapter to be up and running. Wait up to 3 minutes
+	 */
+	if (!(status & KERNEL_UP_AND_RUNNING))
+		return -3;
+	/*
+	 *	Everything is OK
+	 */
+	return 0;
+} /* aac_rkt_check_health */
+
+/**
+ *	aac_rkt_init	-	initialize an i960 based AAC card
+ *	@dev: device to configure
+ *	@devnum: adapter number
+ *
+ *	Allocate and set up resources for the i960 based AAC variants. The 
+ *	device_interface in the commregion will be allocated and linked 
+ *	to the comm region.
+ */
+
+int aac_rkt_init(struct aac_dev *dev, unsigned long num)
+{
+	unsigned long start;
+	unsigned long status;
+	int instance;
+	const char * name;
+
+	dev->devnum = num;
+	instance = dev->id;
+	name     = dev->name;
+
+	/*
+	 *	Map in the registers from the adapter.
+	 */
+	if((dev->regs.rkt = (struct rkt_registers *)ioremap((unsigned long)dev->scsi_host_ptr->base, 8192))==NULL)
+	{	
+		printk(KERN_WARNING "aacraid: unable to map i960.\n" );
+		return -1;
+	}
+	/*
+	 *	Check to see if the board failed any self tests.
+	 */
+	if (rkt_readl(dev, IndexRegs.Mailbox[7]) & SELF_TEST_FAILED) {
+		printk(KERN_ERR "%s%d: adapter self-test failed.\n", dev->name, instance);
+		return -1;
+	}
+	/*
+	 *	Check to see if the board panic'd while booting.
+	 */
+	if (rkt_readl(dev, IndexRegs.Mailbox[7]) & KERNEL_PANIC) {
+		printk(KERN_ERR "%s%d: adapter kernel panic'd.\n", dev->name, instance);
+		return -1;
+	}
+	start = jiffies;
+	/*
+	 *	Wait for the adapter to be up and running. Wait up to 3 minutes
+	 */
+	while (!(rkt_readl(dev, IndexRegs.Mailbox[7]) & KERNEL_UP_AND_RUNNING)) 
+	{
+		if(time_after(jiffies, start+180*HZ))
+		{
+			status = rkt_readl(dev, IndexRegs.Mailbox[7]) >> 16;
+			printk(KERN_ERR "%s%d: adapter kernel failed to start, init status = %ld.\n", dev->name, instance, status);
+			return -1;
+		}
+		set_current_state(TASK_UNINTERRUPTIBLE);
+		schedule_timeout(1);
+	}
+	if (request_irq(dev->scsi_host_ptr->irq, aac_rkt_intr, SA_SHIRQ|SA_INTERRUPT, "aacraid", (void *)dev)<0) 
+	{
+		printk(KERN_ERR "%s%d: Interrupt unavailable.\n", name, instance);
+		return -1;
+	}
+	/*
+	 *	Fill in the function dispatch table.
+	 */
+	dev->a_ops.adapter_interrupt = aac_rkt_interrupt_adapter;
+	dev->a_ops.adapter_enable_int = aac_rkt_enable_interrupt;
+	dev->a_ops.adapter_disable_int = aac_rkt_disable_interrupt;
+	dev->a_ops.adapter_notify = aac_rkt_notify_adapter;
+	dev->a_ops.adapter_sync_cmd = rkt_sync_cmd;
+
+	if (aac_init_adapter(dev) == NULL)
+		return -1;
+	/*
+	 *	Start any kernel threads needed
+	 */
+	dev->thread_pid = kernel_thread((int (*)(void *))aac_command_thread, dev, 0);
+	if(dev->thread_pid < 0)
+	{
+		printk(KERN_ERR "aacraid: Unable to create rkt thread.\n");
+		return -1;
+	}	
+	/*
+	 *	Tell the adapter that all is configured, and it can start
+	 *	accepting requests
+	 */
+	aac_rkt_start_adapter(dev);
+	return 0;
+}
--- diff/drivers/serial/au1x00_uart.c	1970-01-01 01:00:00.000000000 +0100
+++ source/drivers/serial/au1x00_uart.c	2004-02-23 13:56:45.000000000 +0000
@@ -0,0 +1,1393 @@
+/*
+ *  Driver for 8250/16550-type serial ports
+ *
+ *  Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o.
+ *
+ *  Copyright (C) 2001 Russell King.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * A note about mapbase / membase
+ *
+ *  mapbase is the physical address of the IO port.  Currently, we don't
+ *  support this very well, and it may well be dropped from this driver
+ *  in future.  As such, mapbase should be NULL.
+ *
+ *  membase is an 'ioremapped' cookie.  This is compatible with the old
+ *  serial.c driver, and is currently the preferred form.
+ */
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/tty.h>
+#include <linux/ioport.h>
+#include <linux/init.h>
+#include <linux/console.h>
+#include <linux/sysrq.h>
+#include <linux/serial.h>
+#include <linux/serialP.h>
+#include <linux/delay.h>
+
+#include <asm/serial.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/mach-au1x00/au1000.h>
+
+#if defined(CONFIG_SERIAL_AU1X00_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
+#define SUPPORT_SYSRQ
+#endif
+
+#include <linux/serial_core.h>
+#include "8250.h"
+
+/*
+ * Debugging.
+ */
+#if 0
+#define DEBUG_AUTOCONF(fmt...)	printk(fmt)
+#else
+#define DEBUG_AUTOCONF(fmt...)	do { } while (0)
+#endif
+
+#if 0
+#define DEBUG_INTR(fmt...)	printk(fmt)
+#else
+#define DEBUG_INTR(fmt...)	do { } while (0)
+#endif
+
+#define PASS_LIMIT	256
+
+/*
+ * We default to IRQ0 for the "no irq" hack.   Some
+ * machine types want others as well - they're free
+ * to redefine this in their header file.
+ */
+#define is_real_interrupt(irq)	((irq) != 0)
+
+static struct old_serial_port old_serial_port[] = {
+	{	.baud_base = 0,
+		.iomem_base = (u8 *)UART0_ADDR,
+		.irq = AU1000_UART0_INT,
+		.flags = STD_COM_FLAGS,
+		.iomem_reg_shift = 2,
+	}, {
+		.baud_base = 0,
+		.iomem_base = (u8 *)UART1_ADDR,
+		.irq = AU1000_UART1_INT,
+		.flags = STD_COM_FLAGS,
+		.iomem_reg_shift = 2
+	}, {
+		.baud_base = 0,
+		.iomem_base = (u8 *)UART2_ADDR,
+		.irq = AU1000_UART2_INT,
+		.flags = STD_COM_FLAGS,
+		.iomem_reg_shift = 2
+	}, {
+		.baud_base = 0,
+		.iomem_base = (u8 *)UART3_ADDR,
+		.irq = AU1000_UART3_INT,
+		.flags = STD_COM_FLAGS,
+		.iomem_reg_shift = 2
+	}
+};
+
+#define UART_NR	ARRAY_SIZE(old_serial_port)
+
+struct uart_8250_port {
+	struct uart_port	port;
+	struct timer_list	timer;		/* "no irq" timer */
+	struct list_head	list;		/* ports on this IRQ */
+	unsigned short		rev;
+	unsigned char		acr;
+	unsigned char		ier;
+	unsigned char		lcr;
+	unsigned char		mcr_mask;	/* mask of user bits */
+	unsigned char		mcr_force;	/* mask of forced bits */
+	unsigned char		lsr_break_flag;
+
+	/*
+	 * We provide a per-port pm hook.
+	 */
+	void			(*pm)(struct uart_port *port,
+				      unsigned int state, unsigned int old);
+};
+
+struct irq_info {
+	spinlock_t		lock;
+	struct list_head	*head;
+};
+
+static struct irq_info irq_lists[NR_IRQS];
+
+/*
+ * Here we define the default xmit fifo size used for each type of UART.
+ */
+static const struct serial_uart_config uart_config[PORT_MAX_8250+1] = {
+	{ "unknown",	1,	0 },
+	{ "8250",	1,	0 },
+	{ "16450",	1,	0 },
+	{ "16550",	1,	0 },
+	/* PORT_16550A */
+	{ "AU1X00_UART",16,	UART_CLEAR_FIFO | UART_USE_FIFO },
+};
+
+static _INLINE_ unsigned int serial_in(struct uart_8250_port *up, int offset)
+{
+	return au_readl((unsigned long)up->port.membase + offset);
+}
+
+static _INLINE_ void
+serial_out(struct uart_8250_port *up, int offset, int value)
+{
+	au_writel(value, (unsigned long)up->port.membase + offset);
+}
+
+#define serial_inp(up, offset)		serial_in(up, offset)
+#define serial_outp(up, offset, value)	serial_out(up, offset, value)
+
+/*
+ * This routine is called by rs_init() to initialize a specific serial
+ * port.  It determines what type of UART chip this serial port is
+ * using: 8250, 16450, 16550, 16550A.  The important question is
+ * whether or not this UART is a 16550A or not, since this will
+ * determine whether or not we can use its FIFO features or not.
+ */
+static void autoconfig(struct uart_8250_port *up, unsigned int probeflags)
+{
+	unsigned char save_lcr, save_mcr;
+	unsigned long flags;
+
+	if (!up->port.iobase && !up->port.mapbase && !up->port.membase)
+		return;
+
+	DEBUG_AUTOCONF("ttyS%d: autoconf (0x%04x, 0x%08lx): ",
+			up->port.line, up->port.iobase, up->port.membase);
+
+	/*
+	 * We really do need global IRQs disabled here - we're going to
+	 * be frobbing the chips IRQ enable register to see if it exists.
+	 */
+	spin_lock_irqsave(&up->port.lock, flags);
+//	save_flags(flags); cli();
+
+	save_mcr = serial_in(up, UART_MCR);
+	save_lcr = serial_in(up, UART_LCR);
+
+	up->port.type = PORT_16550A;
+	serial_outp(up, UART_LCR, save_lcr);
+
+	up->port.fifosize = uart_config[up->port.type].dfl_xmit_fifo_size;
+
+	if (up->port.type == PORT_UNKNOWN)
+		goto out;
+
+	/*
+	 * Reset the UART.
+	 */
+	serial_outp(up, UART_MCR, save_mcr);
+	serial_outp(up, UART_FCR, (UART_FCR_ENABLE_FIFO |
+				     UART_FCR_CLEAR_RCVR |
+				     UART_FCR_CLEAR_XMIT));
+	serial_outp(up, UART_FCR, 0);
+	(void)serial_in(up, UART_RX);
+	serial_outp(up, UART_IER, 0);
+
+ out:	
+	spin_unlock_irqrestore(&up->port.lock, flags);
+//	restore_flags(flags);
+	DEBUG_AUTOCONF("type=%s\n", uart_config[up->port.type].name);
+}
+
+static void serial8250_stop_tx(struct uart_port *port, unsigned int tty_stop)
+{
+	struct uart_8250_port *up = (struct uart_8250_port *)port;
+
+	if (up->ier & UART_IER_THRI) {
+		up->ier &= ~UART_IER_THRI;
+		serial_out(up, UART_IER, up->ier);
+	}
+}
+
+static void serial8250_start_tx(struct uart_port *port, unsigned int tty_start)
+{
+	struct uart_8250_port *up = (struct uart_8250_port *)port;
+
+	if (!(up->ier & UART_IER_THRI)) {
+		up->ier |= UART_IER_THRI;
+		serial_out(up, UART_IER, up->ier);
+	}
+}
+
+static void serial8250_stop_rx(struct uart_port *port)
+{
+	struct uart_8250_port *up = (struct uart_8250_port *)port;
+
+	up->ier &= ~UART_IER_RLSI;
+	up->port.read_status_mask &= ~UART_LSR_DR;
+	serial_out(up, UART_IER, up->ier);
+}
+
+static void serial8250_enable_ms(struct uart_port *port)
+{
+	struct uart_8250_port *up = (struct uart_8250_port *)port;
+
+	up->ier |= UART_IER_MSI;
+	serial_out(up, UART_IER, up->ier);
+}
+
+static _INLINE_ void
+receive_chars(struct uart_8250_port *up, int *status, struct pt_regs *regs)
+{
+	struct tty_struct *tty = up->port.info->tty;
+	unsigned char ch;
+	int max_count = 256;
+
+	do {
+		if (unlikely(tty->flip.count >= TTY_FLIPBUF_SIZE)) {
+			tty->flip.work.func((void *)tty);
+			if (tty->flip.count >= TTY_FLIPBUF_SIZE)
+				return; // if TTY_DONT_FLIP is set
+		}
+		ch = serial_inp(up, UART_RX);
+		*tty->flip.char_buf_ptr = ch;
+		*tty->flip.flag_buf_ptr = TTY_NORMAL;
+		up->port.icount.rx++;
+
+		if (unlikely(*status & (UART_LSR_BI | UART_LSR_PE |
+				       UART_LSR_FE | UART_LSR_OE))) {
+			/*
+			 * For statistics only
+			 */
+			if (*status & UART_LSR_BI) {
+				*status &= ~(UART_LSR_FE | UART_LSR_PE);
+				up->port.icount.brk++;
+				/*
+				 * We do the SysRQ and SAK checking
+				 * here because otherwise the break
+				 * may get masked by ignore_status_mask
+				 * or read_status_mask.
+				 */
+				if (uart_handle_break(&up->port))
+					goto ignore_char;
+			} else if (*status & UART_LSR_PE)
+				up->port.icount.parity++;
+			else if (*status & UART_LSR_FE)
+				up->port.icount.frame++;
+			if (*status & UART_LSR_OE)
+				up->port.icount.overrun++;
+
+			/*
+			 * Mask off conditions which should be ingored.
+			 */
+			*status &= up->port.read_status_mask;
+
+#ifdef CONFIG_SERIAL_AU1X00_CONSOLE
+			if (up->port.line == up->port.cons->index) {
+				/* Recover the break flag from console xmit */
+				*status |= up->lsr_break_flag;
+				up->lsr_break_flag = 0;
+			}
+#endif
+			if (*status & UART_LSR_BI) {
+				DEBUG_INTR("handling break....");
+				*tty->flip.flag_buf_ptr = TTY_BREAK;
+			} else if (*status & UART_LSR_PE)
+				*tty->flip.flag_buf_ptr = TTY_PARITY;
+			else if (*status & UART_LSR_FE)
+				*tty->flip.flag_buf_ptr = TTY_FRAME;
+		}
+		if (uart_handle_sysrq_char(&up->port, ch, regs))
+			goto ignore_char;
+		if ((*status & up->port.ignore_status_mask) == 0) {
+			tty->flip.flag_buf_ptr++;
+			tty->flip.char_buf_ptr++;
+			tty->flip.count++;
+		}
+		if ((*status & UART_LSR_OE) &&
+		    tty->flip.count < TTY_FLIPBUF_SIZE) {
+			/*
+			 * Overrun is special, since it's reported
+			 * immediately, and doesn't affect the current
+			 * character.
+			 */
+			*tty->flip.flag_buf_ptr = TTY_OVERRUN;
+			tty->flip.flag_buf_ptr++;
+			tty->flip.char_buf_ptr++;
+			tty->flip.count++;
+		}
+	ignore_char:
+		*status = serial_inp(up, UART_LSR);
+	} while ((*status & UART_LSR_DR) && (max_count-- > 0));
+	tty_flip_buffer_push(tty);
+}
+
+static _INLINE_ void transmit_chars(struct uart_8250_port *up)
+{
+	struct circ_buf *xmit = &up->port.info->xmit;
+	int count;
+
+	if (up->port.x_char) {
+		serial_outp(up, UART_TX, up->port.x_char);
+		up->port.icount.tx++;
+		up->port.x_char = 0;
+		return;
+	}
+	if (uart_circ_empty(xmit) || uart_tx_stopped(&up->port)) {
+		serial8250_stop_tx(&up->port, 0);
+		return;
+	}
+
+	count = up->port.fifosize;
+	do {
+		serial_out(up, UART_TX, xmit->buf[xmit->tail]);
+		xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
+		up->port.icount.tx++;
+		if (uart_circ_empty(xmit))
+			break;
+	} while (--count > 0);
+
+	if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
+		uart_write_wakeup(&up->port);
+
+	DEBUG_INTR("THRE...");
+
+	if (uart_circ_empty(xmit))
+		serial8250_stop_tx(&up->port, 0);
+}
+
+static _INLINE_ void check_modem_status(struct uart_8250_port *up)
+{
+	int status;
+
+	status = serial_in(up, UART_MSR);
+
+	if ((status & UART_MSR_ANY_DELTA) == 0)
+		return;
+
+	if (status & UART_MSR_TERI)
+		up->port.icount.rng++;
+	if (status & UART_MSR_DDSR)
+		up->port.icount.dsr++;
+	if (status & UART_MSR_DDCD)
+		uart_handle_dcd_change(&up->port, status & UART_MSR_DCD);
+	if (status & UART_MSR_DCTS)
+		uart_handle_cts_change(&up->port, status & UART_MSR_CTS);
+
+	wake_up_interruptible(&up->port.info->delta_msr_wait);
+}
+
+/*
+ * This handles the interrupt from one port.
+ */
+static inline void
+serial8250_handle_port(struct uart_8250_port *up, struct pt_regs *regs)
+{
+	unsigned int status = serial_inp(up, UART_LSR);
+
+	DEBUG_INTR("status = %x...", status);
+
+	if (status & UART_LSR_DR)
+		receive_chars(up, &status, regs);
+	check_modem_status(up);
+	if (status & UART_LSR_THRE)
+		transmit_chars(up);
+}
+
+/*
+ * This is the serial driver's interrupt routine.
+ *
+ * Arjan thinks the old way was overly complex, so it got simplified.
+ * Alan disagrees, saying that need the complexity to handle the weird
+ * nature of ISA shared interrupts.  (This is a special exception.)
+ *
+ * In order to handle ISA shared interrupts properly, we need to check
+ * that all ports have been serviced, and therefore the ISA interrupt
+ * line has been de-asserted.
+ *
+ * This means we need to loop through all ports. checking that they
+ * don't have an interrupt pending.
+ */
+static irqreturn_t serial8250_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+	struct irq_info *i = dev_id;
+	struct list_head *l, *end = NULL;
+	int pass_counter = 0;
+
+	DEBUG_INTR("serial8250_interrupt(%d)...", irq);
+
+	spin_lock(&i->lock);
+
+	l = i->head;
+	do {
+		struct uart_8250_port *up;
+		unsigned int iir;
+
+		up = list_entry(l, struct uart_8250_port, list);
+
+		iir = serial_in(up, UART_IIR);
+		if (!(iir & UART_IIR_NO_INT)) {
+			spin_lock(&up->port.lock);
+			serial8250_handle_port(up, regs);
+			spin_unlock(&up->port.lock);
+
+			end = NULL;
+		} else if (end == NULL)
+			end = l;
+
+		l = l->next;
+
+		if (l == i->head && pass_counter++ > PASS_LIMIT) {
+			/* If we hit this, we're dead. */
+			printk(KERN_ERR "serial8250: too much work for "
+				"irq%d\n", irq);
+			break;
+		}
+	} while (l != end);
+
+	spin_unlock(&i->lock);
+
+	DEBUG_INTR("end.\n");
+	/* FIXME! Was it really ours? */
+	return IRQ_HANDLED;
+}
+
+/*
+ * To support ISA shared interrupts, we need to have one interrupt
+ * handler that ensures that the IRQ line has been deasserted
+ * before returning.  Failing to do this will result in the IRQ
+ * line being stuck active, and, since ISA irqs are edge triggered,
+ * no more IRQs will be seen.
+ */
+static void serial_do_unlink(struct irq_info *i, struct uart_8250_port *up)
+{
+	spin_lock_irq(&i->lock);
+
+	if (!list_empty(i->head)) {
+		if (i->head == &up->list)
+			i->head = i->head->next;
+		list_del(&up->list);
+	} else {
+		BUG_ON(i->head != &up->list);
+		i->head = NULL;
+	}
+
+	spin_unlock_irq(&i->lock);
+}
+
+static int serial_link_irq_chain(struct uart_8250_port *up)
+{
+	struct irq_info *i = irq_lists + up->port.irq;
+	int ret, irq_flags = up->port.flags & UPF_SHARE_IRQ ? SA_SHIRQ : 0;
+
+	spin_lock_irq(&i->lock);
+
+	if (i->head) {
+		list_add(&up->list, i->head);
+		spin_unlock_irq(&i->lock);
+
+		ret = 0;
+	} else {
+		INIT_LIST_HEAD(&up->list);
+		i->head = &up->list;
+		spin_unlock_irq(&i->lock);
+
+		ret = request_irq(up->port.irq, serial8250_interrupt,
+				  irq_flags, "serial", i);
+		if (ret < 0)
+			serial_do_unlink(i, up);
+	}
+
+	return ret;
+}
+
+static void serial_unlink_irq_chain(struct uart_8250_port *up)
+{
+	struct irq_info *i = irq_lists + up->port.irq;
+
+	BUG_ON(i->head == NULL);
+
+	if (list_empty(i->head))
+		free_irq(up->port.irq, i);
+
+	serial_do_unlink(i, up);
+}
+
+/*
+ * This function is used to handle ports that do not have an
+ * interrupt.  This doesn't work very well for 16450's, but gives
+ * barely passable results for a 16550A.  (Although at the expense
+ * of much CPU overhead).
+ */
+static void serial8250_timeout(unsigned long data)
+{
+	struct uart_8250_port *up = (struct uart_8250_port *)data;
+	unsigned int timeout;
+	unsigned int iir;
+
+	iir = serial_in(up, UART_IIR);
+	if (!(iir & UART_IIR_NO_INT)) {
+		spin_lock(&up->port.lock);
+		serial8250_handle_port(up, NULL);
+		spin_unlock(&up->port.lock);
+	}
+
+	timeout = up->port.timeout;
+	timeout = timeout > 6 ? (timeout / 2 - 2) : 1;
+	mod_timer(&up->timer, jiffies + timeout);
+}
+
+static unsigned int serial8250_tx_empty(struct uart_port *port)
+{
+	struct uart_8250_port *up = (struct uart_8250_port *)port;
+	unsigned long flags;
+	unsigned int ret;
+
+	spin_lock_irqsave(&up->port.lock, flags);
+	ret = serial_in(up, UART_LSR) & UART_LSR_TEMT ? TIOCSER_TEMT : 0;
+	spin_unlock_irqrestore(&up->port.lock, flags);
+
+	return ret;
+}
+
+static unsigned int serial8250_get_mctrl(struct uart_port *port)
+{
+	struct uart_8250_port *up = (struct uart_8250_port *)port;
+	unsigned long flags;
+	unsigned char status;
+	unsigned int ret;
+
+	spin_lock_irqsave(&up->port.lock, flags);
+	status = serial_in(up, UART_MSR);
+	spin_unlock_irqrestore(&up->port.lock, flags);
+
+	ret = 0;
+	if (status & UART_MSR_DCD)
+		ret |= TIOCM_CAR;
+	if (status & UART_MSR_RI)
+		ret |= TIOCM_RNG;
+	if (status & UART_MSR_DSR)
+		ret |= TIOCM_DSR;
+	if (status & UART_MSR_CTS)
+		ret |= TIOCM_CTS;
+	return ret;
+}
+
+static void serial8250_set_mctrl(struct uart_port *port, unsigned int mctrl)
+{
+	struct uart_8250_port *up = (struct uart_8250_port *)port;
+	unsigned char mcr = 0;
+
+	if (mctrl & TIOCM_RTS)
+		mcr |= UART_MCR_RTS;
+	if (mctrl & TIOCM_DTR)
+		mcr |= UART_MCR_DTR;
+	if (mctrl & TIOCM_OUT1)
+		mcr |= UART_MCR_OUT1;
+	if (mctrl & TIOCM_OUT2)
+		mcr |= UART_MCR_OUT2;
+	if (mctrl & TIOCM_LOOP)
+		mcr |= UART_MCR_LOOP;
+
+	mcr = (mcr & up->mcr_mask) | up->mcr_force;
+
+	serial_out(up, UART_MCR, mcr);
+}
+
+static void serial8250_break_ctl(struct uart_port *port, int break_state)
+{
+	struct uart_8250_port *up = (struct uart_8250_port *)port;
+	unsigned long flags;
+
+	spin_lock_irqsave(&up->port.lock, flags);
+	if (break_state == -1)
+		up->lcr |= UART_LCR_SBC;
+	else
+		up->lcr &= ~UART_LCR_SBC;
+	serial_out(up, UART_LCR, up->lcr);
+	spin_unlock_irqrestore(&up->port.lock, flags);
+}
+
+static int serial8250_startup(struct uart_port *port)
+{
+	struct uart_8250_port *up = (struct uart_8250_port *)port;
+	unsigned long flags;
+	int retval;
+
+	/*
+	 * Clear the FIFO buffers and disable them.
+	 * (they will be reeanbled in set_termios())
+	 */
+	if (uart_config[up->port.type].flags & UART_CLEAR_FIFO) {
+		serial_outp(up, UART_FCR, UART_FCR_ENABLE_FIFO);
+		serial_outp(up, UART_FCR, UART_FCR_ENABLE_FIFO |
+				UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT);
+		serial_outp(up, UART_FCR, 0);
+	}
+
+	/*
+	 * Clear the interrupt registers.
+	 */
+	(void) serial_inp(up, UART_LSR);
+	(void) serial_inp(up, UART_RX);
+	(void) serial_inp(up, UART_IIR);
+	(void) serial_inp(up, UART_MSR);
+
+	/*
+	 * At this point, there's no way the LSR could still be 0xff;
+	 * if it is, then bail out, because there's likely no UART
+	 * here.
+	 */
+	if (!(up->port.flags & UPF_BUGGY_UART) &&
+	    (serial_inp(up, UART_LSR) == 0xff)) {
+		printk("ttyS%d: LSR safety check engaged!\n", up->port.line);
+		return -ENODEV;
+	}
+
+	retval = serial_link_irq_chain(up);
+		if (retval)
+			return retval;
+
+	/*
+	 * Now, initialize the UART
+	 */
+	serial_outp(up, UART_LCR, UART_LCR_WLEN8);
+
+	spin_lock_irqsave(&up->port.lock, flags);
+	if (up->port.flags & UPF_FOURPORT) {
+		if (!is_real_interrupt(up->port.irq))
+			up->port.mctrl |= TIOCM_OUT1;
+	} else
+		/*
+		 * Most PC uarts need OUT2 raised to enable interrupts.
+		 */
+		if (is_real_interrupt(up->port.irq))
+			up->port.mctrl |= TIOCM_OUT2;
+
+	serial8250_set_mctrl(&up->port, up->port.mctrl);
+	spin_unlock_irqrestore(&up->port.lock, flags);
+
+	/*
+	 * Finally, enable interrupts.  Note: Modem status interrupts
+	 * are set via set_termios(), which will be occurring imminently
+	 * anyway, so we don't enable them here.
+	 */
+	up->ier = UART_IER_RLSI | UART_IER_RDI;
+	serial_outp(up, UART_IER, up->ier);
+
+	if (up->port.flags & UPF_FOURPORT) {
+		unsigned int icp;
+		/*
+		 * Enable interrupts on the AST Fourport board
+		 */
+		icp = (up->port.iobase & 0xfe0) | 0x01f;
+		outb_p(0x80, icp);
+		(void) inb_p(icp);
+	}
+
+	/*
+	 * And clear the interrupt registers again for luck.
+	 */
+	(void) serial_inp(up, UART_LSR);
+	(void) serial_inp(up, UART_RX);
+	(void) serial_inp(up, UART_IIR);
+	(void) serial_inp(up, UART_MSR);
+
+	return 0;
+}
+
+static void serial8250_shutdown(struct uart_port *port)
+{
+	struct uart_8250_port *up = (struct uart_8250_port *)port;
+	unsigned long flags;
+
+	/*
+	 * Disable interrupts from this port
+	 */
+	up->ier = 0;
+	serial_outp(up, UART_IER, 0);
+
+	spin_lock_irqsave(&up->port.lock, flags);
+	if (up->port.flags & UPF_FOURPORT) {
+		/* reset interrupts on the AST Fourport board */
+		inb((up->port.iobase & 0xfe0) | 0x1f);
+		up->port.mctrl |= TIOCM_OUT1;
+	} else
+		up->port.mctrl &= ~TIOCM_OUT2;
+
+	serial8250_set_mctrl(&up->port, up->port.mctrl);
+	spin_unlock_irqrestore(&up->port.lock, flags);
+
+	/*
+	 * Disable break condition and FIFOs
+	 */
+	serial_out(up, UART_LCR, serial_inp(up, UART_LCR) & ~UART_LCR_SBC);
+	serial_outp(up, UART_FCR, UART_FCR_ENABLE_FIFO |
+				  UART_FCR_CLEAR_RCVR |
+				  UART_FCR_CLEAR_XMIT);
+	serial_outp(up, UART_FCR, 0);
+
+	/*
+	 * Read data port to reset things, and then unlink from
+	 * the IRQ chain.
+	 */
+	(void) serial_in(up, UART_RX);
+
+	if (!is_real_interrupt(up->port.irq))
+		del_timer_sync(&up->timer);
+	else
+		serial_unlink_irq_chain(up);
+}
+
+static unsigned int serial8250_get_divisor(struct uart_port *port, unsigned int baud)
+{
+	unsigned int quot;
+
+	/*
+	 * Handle magic divisors for baud rates above baud_base on
+	 * SMSC SuperIO chips.
+	 */
+	if ((port->flags & UPF_MAGIC_MULTIPLIER) &&
+	    baud == (port->uartclk/4))
+		quot = 0x8001;
+	else if ((port->flags & UPF_MAGIC_MULTIPLIER) &&
+		 baud == (port->uartclk/8))
+		quot = 0x8002;
+	else
+		quot = uart_get_divisor(port, baud);
+
+	return quot;
+}
+
+static void
+serial8250_set_termios(struct uart_port *port, struct termios *termios,
+		       struct termios *old)
+{
+	struct uart_8250_port *up = (struct uart_8250_port *)port;
+	unsigned char cval, fcr = 0;
+	unsigned long flags;
+	unsigned int baud, quot;
+
+	switch (termios->c_cflag & CSIZE) {
+	case CS5:
+		cval = 0x00;
+		break;
+	case CS6:
+		cval = 0x01;
+		break;
+	case CS7:
+		cval = 0x02;
+		break;
+	default:
+	case CS8:
+		cval = 0x03;
+		break;
+	}
+
+	if (termios->c_cflag & CSTOPB)
+		cval |= 0x04;
+	if (termios->c_cflag & PARENB)
+		cval |= UART_LCR_PARITY;
+	if (!(termios->c_cflag & PARODD))
+		cval |= UART_LCR_EPAR;
+#ifdef CMSPAR
+	if (termios->c_cflag & CMSPAR)
+		cval |= UART_LCR_SPAR;
+#endif
+
+	/*
+	 * Ask the core to calculate the divisor for us.
+	 */
+	baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/16); 
+	quot = serial8250_get_divisor(port, baud);
+	quot = 0x35; /* FIXME */
+
+	/*
+	 * Work around a bug in the Oxford Semiconductor 952 rev B
+	 * chip which causes it to seriously miscalculate baud rates
+	 * when DLL is 0.
+	 */
+	if ((quot & 0xff) == 0 && up->port.type == PORT_16C950 &&
+	    up->rev == 0x5201)
+		quot ++;
+
+	if (uart_config[up->port.type].flags & UART_USE_FIFO) {
+		if (baud < 2400)
+			fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIGGER_1;
+		else
+			fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIGGER_8;
+	}
+
+	/*
+	 * Ok, we're now changing the port state.  Do it with
+	 * interrupts disabled.
+	 */
+	spin_lock_irqsave(&up->port.lock, flags);
+
+	/*
+	 * Update the per-port timeout.
+	 */
+	uart_update_timeout(port, termios->c_cflag, baud);
+
+	up->port.read_status_mask = UART_LSR_OE | UART_LSR_THRE | UART_LSR_DR;
+	if (termios->c_iflag & INPCK)
+		up->port.read_status_mask |= UART_LSR_FE | UART_LSR_PE;
+	if (termios->c_iflag & (BRKINT | PARMRK))
+		up->port.read_status_mask |= UART_LSR_BI;
+
+	/*
+	 * Characteres to ignore
+	 */
+	up->port.ignore_status_mask = 0;
+	if (termios->c_iflag & IGNPAR)
+		up->port.ignore_status_mask |= UART_LSR_PE | UART_LSR_FE;
+	if (termios->c_iflag & IGNBRK) {
+		up->port.ignore_status_mask |= UART_LSR_BI;
+		/*
+		 * If we're ignoring parity and break indicators,
+		 * ignore overruns too (for real raw support).
+		 */
+		if (termios->c_iflag & IGNPAR)
+			up->port.ignore_status_mask |= UART_LSR_OE;
+	}
+
+	/*
+	 * ignore all characters if CREAD is not set
+	 */
+	if ((termios->c_cflag & CREAD) == 0)
+		up->port.ignore_status_mask |= UART_LSR_DR;
+
+	/*
+	 * CTS flow control flag and modem status interrupts
+	 */
+	up->ier &= ~UART_IER_MSI;
+	if (UART_ENABLE_MS(&up->port, termios->c_cflag))
+		up->ier |= UART_IER_MSI;
+
+	serial_out(up, UART_IER, up->ier);
+	serial_outp(up, 0x28, quot & 0xffff);
+	up->lcr = cval;					/* Save LCR */
+	if (up->port.type != PORT_16750) {
+		if (fcr & UART_FCR_ENABLE_FIFO) {
+			/* emulated UARTs (Lucent Venus 167x) need two steps */
+			serial_outp(up, UART_FCR, UART_FCR_ENABLE_FIFO);
+		}
+		serial_outp(up, UART_FCR, fcr);		/* set fcr */
+	}
+	spin_unlock_irqrestore(&up->port.lock, flags);
+}
+
+static void
+serial8250_pm(struct uart_port *port, unsigned int state,
+	      unsigned int oldstate)
+{
+	struct uart_8250_port *up = (struct uart_8250_port *)port;
+	if (state) {
+		/* sleep */
+		if (up->pm)
+			up->pm(port, state, oldstate);
+	} else {
+		/* wake */
+		if (up->pm)
+			up->pm(port, state, oldstate);
+	}
+}
+
+/*
+ * Resource handling.  This is complicated by the fact that resources
+ * depend on the port type.  Maybe we should be claiming the standard
+ * 8250 ports, and then trying to get other resources as necessary?
+ */
+static int
+serial8250_request_std_resource(struct uart_8250_port *up, struct resource **res)
+{
+	unsigned int size = 8 << up->port.regshift;
+	int ret = 0;
+
+	switch (up->port.iotype) {
+	case SERIAL_IO_MEM:
+		if (up->port.mapbase) {
+			*res = request_mem_region(up->port.mapbase, size, "serial");
+			if (!*res)
+				ret = -EBUSY;
+		}
+		break;
+
+	case SERIAL_IO_HUB6:
+	case SERIAL_IO_PORT:
+		*res = request_region(up->port.iobase, size, "serial");
+		if (!*res)
+			ret = -EBUSY;
+		break;
+	}
+	return ret;
+}
+
+
+static void serial8250_release_port(struct uart_port *port)
+{
+	struct uart_8250_port *up = (struct uart_8250_port *)port;
+	unsigned long start, offset = 0, size = 0;
+
+	size <<= up->port.regshift;
+
+	switch (up->port.iotype) {
+	case SERIAL_IO_MEM:
+		if (up->port.mapbase) {
+			/*
+			 * Unmap the area.
+			 */
+			iounmap(up->port.membase);
+			up->port.membase = NULL;
+
+			start = up->port.mapbase;
+
+			if (size)
+				release_mem_region(start + offset, size);
+			release_mem_region(start, 8 << up->port.regshift);
+		}
+		break;
+
+	case SERIAL_IO_HUB6:
+	case SERIAL_IO_PORT:
+		start = up->port.iobase;
+
+		if (size)
+			release_region(start + offset, size);
+		release_region(start + offset, 8 << up->port.regshift);
+		break;
+
+	default:
+		break;
+	}
+}
+
+static int serial8250_request_port(struct uart_port *port)
+{
+	struct uart_8250_port *up = (struct uart_8250_port *)port;
+	struct resource *res = NULL, *res_rsa = NULL;
+	int ret = 0;
+
+	if (up->port.flags & UPF_RESOURCES) {
+		ret = serial8250_request_std_resource(up, &res);
+	}
+
+	/*
+	 * If we have a mapbase, then request that as well.
+	 */
+	if (ret == 0 && up->port.flags & UPF_IOREMAP) {
+		int size = res->end - res->start + 1;
+
+		up->port.membase = ioremap(up->port.mapbase, size);
+		if (!up->port.membase)
+			ret = -ENOMEM;
+	}
+
+	if (ret < 0) {
+		if (res_rsa)
+			release_resource(res_rsa);
+		if (res)
+			release_resource(res);
+	}
+	return ret;
+}
+
+static void serial8250_config_port(struct uart_port *port, int flags)
+{
+	struct uart_8250_port *up = (struct uart_8250_port *)port;
+	struct resource *res_std = NULL, *res_rsa = NULL;
+	int probeflags = PROBE_ANY;
+
+	probeflags &= ~PROBE_RSA;
+
+	if (flags & UART_CONFIG_TYPE)
+		autoconfig(up, probeflags);
+
+	/*
+	 * If the port wasn't an RSA port, release the resource.
+	 */
+	if (up->port.type != PORT_RSA && res_rsa)
+		release_resource(res_rsa);
+
+	if (up->port.type == PORT_UNKNOWN && res_std)
+		release_resource(res_std);
+}
+
+static int
+serial8250_verify_port(struct uart_port *port, struct serial_struct *ser)
+{
+	if (ser->irq >= NR_IRQS || ser->irq < 0 ||
+	    ser->baud_base < 9600 || ser->type < PORT_UNKNOWN ||
+	    ser->type > PORT_MAX_8250 || ser->type == PORT_CIRRUS ||
+	    ser->type == PORT_STARTECH)
+		return -EINVAL;
+	return 0;
+}
+
+static const char *
+serial8250_type(struct uart_port *port)
+{
+	int type = port->type;
+
+	if (type >= ARRAY_SIZE(uart_config))
+		type = 0;
+	return uart_config[type].name;
+}
+
+static struct uart_ops serial8250_pops = {
+	.tx_empty	= serial8250_tx_empty,
+	.set_mctrl	= serial8250_set_mctrl,
+	.get_mctrl	= serial8250_get_mctrl,
+	.stop_tx	= serial8250_stop_tx,
+	.start_tx	= serial8250_start_tx,
+	.stop_rx	= serial8250_stop_rx,
+	.enable_ms	= serial8250_enable_ms,
+	.break_ctl	= serial8250_break_ctl,
+	.startup	= serial8250_startup,
+	.shutdown	= serial8250_shutdown,
+	.set_termios	= serial8250_set_termios,
+	.pm		= serial8250_pm,
+	.type		= serial8250_type,
+	.release_port	= serial8250_release_port,
+	.request_port	= serial8250_request_port,
+	.config_port	= serial8250_config_port,
+	.verify_port	= serial8250_verify_port,
+};
+
+static struct uart_8250_port serial8250_ports[UART_NR];
+
+static void __init serial8250_isa_init_ports(void)
+{
+	struct uart_8250_port *up;
+	static int first = 1;
+	int i;
+
+	if (!first)
+		return;
+	first = 0;
+
+	for (i = 0, up = serial8250_ports; i < ARRAY_SIZE(old_serial_port);
+	     i++, up++) {
+		up->port.iobase   = old_serial_port[i].port;
+		up->port.irq      = old_serial_port[i].irq;
+		up->port.uartclk  = get_au1x00_uart_baud_base();
+		up->port.flags    = old_serial_port[i].flags |
+				    UPF_RESOURCES;
+		up->port.hub6     = old_serial_port[i].hub6;
+		up->port.membase  = old_serial_port[i].iomem_base;
+		up->port.iotype   = old_serial_port[i].io_type;
+		up->port.regshift = old_serial_port[i].iomem_reg_shift;
+		up->port.ops      = &serial8250_pops;
+	}
+}
+
+static void __init serial8250_register_ports(struct uart_driver *drv)
+{
+	int i;
+
+	serial8250_isa_init_ports();
+
+	for (i = 0; i < UART_NR; i++) {
+		struct uart_8250_port *up = &serial8250_ports[i];
+
+		up->port.line = i;
+		up->port.ops = &serial8250_pops;
+		init_timer(&up->timer);
+		up->timer.function = serial8250_timeout;
+
+		/*
+		 * ALPHA_KLUDGE_MCR needs to be killed.
+		 */
+		up->mcr_mask = ~ALPHA_KLUDGE_MCR;
+		up->mcr_force = ALPHA_KLUDGE_MCR;
+
+		uart_add_one_port(drv, &up->port);
+	}
+}
+
+#ifdef CONFIG_SERIAL_AU1X00_CONSOLE
+
+#define BOTH_EMPTY (UART_LSR_TEMT | UART_LSR_THRE)
+
+/*
+ *	Wait for transmitter & holding register to empty
+ */
+static inline void wait_for_xmitr(struct uart_8250_port *up)
+{
+	unsigned int status, tmout = 10000;
+
+	/* Wait up to 10ms for the character(s) to be sent. */
+	do {
+		status = serial_in(up, UART_LSR);
+
+		if (status & UART_LSR_BI)
+			up->lsr_break_flag = UART_LSR_BI;
+
+		if (--tmout == 0)
+			break;
+		udelay(1);
+	} while ((status & BOTH_EMPTY) != BOTH_EMPTY);
+
+	/* Wait up to 1s for flow control if necessary */
+	if (up->port.flags & UPF_CONS_FLOW) {
+		tmout = 1000000;
+		while (--tmout &&
+		       ((serial_in(up, UART_MSR) & UART_MSR_CTS) == 0))
+			udelay(1);
+	}
+}
+
+/*
+ *	Print a string to the serial port trying not to disturb
+ *	any possible real use of the port...
+ *
+ *	The console_lock must be held when we get here.
+ */
+static void
+serial8250_console_write(struct console *co, const char *s, unsigned int count)
+{
+	struct uart_8250_port *up = &serial8250_ports[co->index];
+	unsigned int ier;
+	int i;
+
+	/*
+	 *	First save the UER then disable the interrupts
+	 */
+	ier = serial_in(up, UART_IER);
+	serial_out(up, UART_IER, 0);
+
+	/*
+	 *	Now, do each character
+	 */
+	for (i = 0; i < count; i++, s++) {
+		wait_for_xmitr(up);
+
+		/*
+		 *	Send the character out.
+		 *	If a LF, also do CR...
+		 */
+		serial_out(up, UART_TX, *s);
+		if (*s == 10) {
+			wait_for_xmitr(up);
+			serial_out(up, UART_TX, 13);
+		}
+	}
+
+	/*
+	 *	Finally, wait for transmitter to become empty
+	 *	and restore the IER
+	 */
+	wait_for_xmitr(up);
+	serial_out(up, UART_IER, ier);
+}
+
+static int __init serial8250_console_setup(struct console *co, char *options)
+{
+	struct uart_port *port;
+	int baud = 9600;
+	int bits = 8;
+	int parity = 'n';
+	int flow = 'n';
+
+	/*
+	 * Check whether an invalid uart number has been specified, and
+	 * if so, search for the first available port that does have
+	 * console support.
+	 */
+	if (co->index >= UART_NR)
+		co->index = 0;
+	port = &serial8250_ports[co->index].port;
+
+	/*
+	 * Temporary fix.
+	 */
+	spin_lock_init(&port->lock);
+
+	if (options)
+		uart_parse_options(options, &baud, &parity, &bits, &flow);
+
+	return uart_set_options(port, co, baud, parity, bits, flow);
+}
+
+extern struct uart_driver serial8250_reg;
+static struct console serial8250_console = {
+	.name		= "ttyS",
+	.write		= serial8250_console_write,
+	.device		= uart_console_device,
+	.setup		= serial8250_console_setup,
+	.flags		= CON_PRINTBUFFER,
+	.index		= -1,
+	.data		= &serial8250_reg,
+};
+
+static int __init serial8250_console_init(void)
+{
+	serial8250_isa_init_ports();
+	register_console(&serial8250_console);
+	return 0;
+}
+console_initcall(serial8250_console_init);
+
+#define SERIAL8250_CONSOLE	&serial8250_console
+#else
+#define SERIAL8250_CONSOLE	NULL
+#endif
+
+static struct uart_driver serial8250_reg = {
+	.owner			= THIS_MODULE,
+	.driver_name		= "serial",
+	.devfs_name		= "tts/",
+	.dev_name		= "ttyS",
+	.major			= TTY_MAJOR,
+	.minor			= 64,
+	.nr			= UART_NR,
+	.cons			= SERIAL8250_CONSOLE,
+};
+
+/*
+ * register_serial and unregister_serial allows for 16x50 serial ports to be
+ * configured at run-time, to support PCMCIA modems.
+ */
+
+static int __register_serial(struct serial_struct *req, int line)
+{
+	struct uart_port port;
+
+	port.iobase   = req->port;
+	port.membase  = req->iomem_base;
+	port.irq      = req->irq;
+	port.uartclk  = req->baud_base * 16;
+	port.fifosize = req->xmit_fifo_size;
+	port.regshift = req->iomem_reg_shift;
+	port.iotype   = req->io_type;
+	port.flags    = req->flags | UPF_BOOT_AUTOCONF;
+	port.mapbase  = req->iomap_base;
+	port.line     = line;
+
+	if (HIGH_BITS_OFFSET)
+		port.iobase |= (long) req->port_high << HIGH_BITS_OFFSET;
+
+	/*
+	 * If a clock rate wasn't specified by the low level
+	 * driver, then default to the standard clock rate.
+	 */
+	if (port.uartclk == 0)
+		port.uartclk = BASE_BAUD * 16;
+
+	return uart_register_port(&serial8250_reg, &port);
+}
+
+/**
+ *	register_serial - configure a 16x50 serial port at runtime
+ *	@req: request structure
+ *
+ *	Configure the serial port specified by the request. If the
+ *	port exists and is in use an error is returned. If the port
+ *	is not currently in the table it is added.
+ *
+ *	The port is then probed and if necessary the IRQ is autodetected
+ *	If this fails an error is returned.
+ *
+ *	On success the port is ready to use and the line number is returned.
+ */
+int register_serial(struct serial_struct *req)
+{
+	return __register_serial(req, -1);
+}
+
+int __init early_serial_setup(struct uart_port *port)
+{
+	serial8250_isa_init_ports();
+	serial8250_ports[port->line].port	= *port;
+	serial8250_ports[port->line].port.ops	= &serial8250_pops;
+	return 0;
+}
+
+/**
+ *	unregister_serial - remove a 16x50 serial port at runtime
+ *	@line: serial line number
+ *
+ *	Remove one serial port.  This may be called from interrupt
+ *	context.
+ */
+void unregister_serial(int line)
+{
+	uart_unregister_port(&serial8250_reg, line);
+}
+
+/*
+ * This is for ISAPNP only.
+ */
+void serial8250_get_irq_map(unsigned int *map)
+{
+	int i;
+
+	for (i = 0; i < UART_NR; i++) {
+		if (serial8250_ports[i].port.type != PORT_UNKNOWN &&
+		    serial8250_ports[i].port.irq < 16)
+			*map |= 1 << serial8250_ports[i].port.irq;
+	}
+}
+
+/**
+ *	serial8250_suspend_port - suspend one serial port
+ *	@line:  serial line number
+ *      @level: the level of port suspension, as per uart_suspend_port
+ *
+ *	Suspend one serial port.
+ */
+void serial8250_suspend_port(int line)
+{
+	uart_suspend_port(&serial8250_reg, &serial8250_ports[line].port);
+}
+
+/**
+ *	serial8250_resume_port - resume one serial port
+ *	@line:  serial line number
+ *      @level: the level of port resumption, as per uart_resume_port
+ *
+ *	Resume one serial port.
+ */
+void serial8250_resume_port(int line)
+{
+	uart_resume_port(&serial8250_reg, &serial8250_ports[line].port);
+}
+
+static int __init serial8250_init(void)
+{
+	int ret, i;
+
+	printk(KERN_INFO "Serial: Au1x00 driver\n");
+
+	for (i = 0; i < NR_IRQS; i++)
+		spin_lock_init(&irq_lists[i].lock);
+
+	ret = uart_register_driver(&serial8250_reg);
+	if (ret >= 0)
+		serial8250_register_ports(&serial8250_reg);
+
+	return ret;
+}
+
+static void __exit serial8250_exit(void)
+{
+	int i;
+
+	for (i = 0; i < UART_NR; i++)
+		uart_remove_one_port(&serial8250_reg, &serial8250_ports[i].port);
+
+	uart_unregister_driver(&serial8250_reg);
+}
+
+module_init(serial8250_init);
+module_exit(serial8250_exit);
+
+EXPORT_SYMBOL(register_serial);
+EXPORT_SYMBOL(unregister_serial);
+EXPORT_SYMBOL(serial8250_get_irq_map);
+EXPORT_SYMBOL(serial8250_suspend_port);
+EXPORT_SYMBOL(serial8250_resume_port);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Au1x00 serial driver\n");
--- diff/drivers/serial/dz.c	1970-01-01 01:00:00.000000000 +0100
+++ source/drivers/serial/dz.c	2004-02-23 13:56:45.000000000 +0000
@@ -0,0 +1,827 @@
+/*
+ * dz.c: Serial port driver for DECStations equiped 
+ *       with the DZ chipset.
+ *
+ * Copyright (C) 1998 Olivier A. D. Lebaillif 
+ *             
+ * Email: olivier.lebaillif@ifrsys.com
+ *
+ * [31-AUG-98] triemer
+ * Changed IRQ to use Harald's dec internals interrupts.h
+ * removed base_addr code - moving address assignment to setup.c
+ * Changed name of dz_init to rs_init to be consistent with tc code
+ * [13-NOV-98] triemer fixed code to receive characters
+ *    after patches by harald to irq code.  
+ * [09-JAN-99] triemer minor fix for schedule - due to removal of timeout
+ *            field from "current" - somewhere between 2.1.121 and 2.1.131
+ Qua Jun 27 15:02:26 BRT 2001
+ * [27-JUN-2001] Arnaldo Carvalho de Melo <acme@conectiva.com.br> - cleanups
+ *  
+ * Parts (C) 1999 David Airlie, airlied@linux.ie 
+ * [07-SEP-99] Bugfixes 
+ *
+ * [06-Jan-2002] Russell King <rmk@arm.linux.org.uk>
+ * Converted to new serial core
+ */
+
+#undef DEBUG_DZ
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/tty.h>
+#include <linux/interrupt.h>
+#include <linux/init.h>
+#include <linux/console.h>
+#include <linux/serial.h>
+#include <linux/serial_core.h>
+
+#include <asm/bootinfo.h>
+#include <asm/dec/interrupts.h>
+#include <asm/dec/kn01.h>
+#include <asm/dec/kn02.h>
+#include <asm/dec/machtype.h>
+#include <asm/dec/prom.h>
+#include <asm/irq.h>
+#include <asm/system.h>
+#include <asm/uaccess.h>
+
+#define CONSOLE_LINE (3)	/* for definition of struct console */
+
+#include "dz.h"
+
+#define DZ_INTR_DEBUG 1
+
+static char *dz_name = "DECstation DZ serial driver version ";
+static char *dz_version = "1.02";
+
+struct dz_port {
+	struct uart_port	port;
+	unsigned int		cflag;
+};
+
+static struct dz_port dz_ports[DZ_NB_PORT];
+
+#ifdef DEBUG_DZ
+/*
+ * debugging code to send out chars via prom 
+ */
+static void debug_console(const char *s, int count)
+{
+	unsigned i;
+
+	for (i = 0; i < count; i++) {
+		if (*s == 10)
+			prom_printf("%c", 13);
+		prom_printf("%c", *s++);
+	}
+}
+#endif
+
+/*
+ * ------------------------------------------------------------
+ * dz_in () and dz_out ()
+ *
+ * These routines are used to access the registers of the DZ 
+ * chip, hiding relocation differences between implementation.
+ * ------------------------------------------------------------
+ */
+
+static inline unsigned short dz_in(struct dz_port *dport, unsigned offset)
+{
+	volatile unsigned short *addr =
+		(volatile unsigned short *) (dport->port.membase + offset);
+	return *addr;
+}
+
+static inline void dz_out(struct dz_port *dport, unsigned offset,
+                          unsigned short value)
+{
+	volatile unsigned short *addr =
+		(volatile unsigned short *) (dport->port.membase + offset);
+	*addr = value;
+}
+
+/*
+ * ------------------------------------------------------------
+ * rs_stop () and rs_start ()
+ *
+ * These routines are called before setting or resetting 
+ * tty->stopped. They enable or disable transmitter interrupts, 
+ * as necessary.
+ * ------------------------------------------------------------
+ */
+
+static void dz_stop_tx(struct uart_port *uport, unsigned int tty_stop)
+{
+	struct dz_port *dport = (struct dz_port *)uport;
+	unsigned short tmp, mask = 1 << dport->port.line;
+	unsigned long flags;
+
+	spin_lock_irqsave(&dport->port.lock, flags);
+	tmp = dz_in(dport, DZ_TCR);	/* read the TX flag */
+	tmp &= ~mask;			/* clear the TX flag */
+	dz_out(dport, DZ_TCR, tmp);
+	spin_unlock_irqrestore(&dport->port.lock, flags);
+}
+
+static void dz_start_tx(struct uart_port *uport, unsigned int tty_start)
+{
+	struct dz_port *dport = (struct dz_port *)uport;
+	unsigned short tmp, mask = 1 << dport->port.line;
+	unsigned long flags;
+
+	spin_lock_irqsave(&dport->port.lock, flags);
+	tmp = dz_in(dport, DZ_TCR);	/* read the TX flag */
+	tmp |= mask;			/* set the TX flag */
+	dz_out(dport, DZ_TCR, tmp);
+	spin_unlock_irqrestore(&dport->port.lock, flags);
+}
+
+static void dz_stop_rx(struct uart_port *uport)
+{
+	struct dz_port *dport = (struct dz_port *)uport;
+	unsigned long flags;
+
+	spin_lock_irqsave(&dport->port.lock, flags);
+	dport->cflag &= ~DZ_CREAD;
+	dz_out(dport, DZ_LPR, dport->cflag);
+	spin_unlock_irqrestore(&dport->port.lock, flags);
+}
+
+static void dz_enable_ms(struct uart_port *port)
+{
+	/* nothing to do */
+}
+
+/*
+ * ------------------------------------------------------------
+ * Here starts the interrupt handling routines.  All of the 
+ * following subroutines are declared as inline and are folded 
+ * into dz_interrupt.  They were separated out for readability's 
+ * sake. 
+ *
+ * Note: rs_interrupt() is a "fast" interrupt, which means that it
+ * runs with interrupts turned off.  People who may want to modify
+ * rs_interrupt() should try to keep the interrupt handler as fast as
+ * possible.  After you are done making modifications, it is not a bad
+ * idea to do:
+ * 
+ *	make drivers/serial/dz.s
+ *
+ * and look at the resulting assemble code in dz.s.
+ *
+ * ------------------------------------------------------------
+ */
+
+/*
+ * ------------------------------------------------------------
+ * receive_char ()
+ *
+ * This routine deals with inputs from any lines.
+ * ------------------------------------------------------------
+ */
+static inline void dz_receive_chars(struct dz_port *dport)
+{
+	struct tty_struct *tty = NULL;
+	struct uart_icount *icount;
+	int ignore = 0;
+	unsigned short status, tmp;
+	unsigned char ch;
+
+	/* this code is going to be a problem...
+	   the call to tty_flip_buffer is going to need
+	   to be rethought...
+	 */
+	do {
+		status = dz_in(dport, DZ_RBUF);
+
+		/* punt so we don't get duplicate characters */
+		if (!(status & DZ_DVAL))
+			goto ignore_char;
+
+
+		ch = UCHAR(status);	/* grab the char */
+
+#if 0
+		if (info->is_console) {
+			if (ch == 0)
+				return;		/* it's a break ... */
+		}
+#endif
+
+		tty = dport->port.info->tty;/* now tty points to the proper dev */
+		icount = &dport->port.icount;
+
+		if (!tty)
+			break;
+		if (tty->flip.count >= TTY_FLIPBUF_SIZE)
+			break;
+
+		*tty->flip.char_buf_ptr = ch;
+		*tty->flip.flag_buf_ptr = 0;
+		icount->rx++;
+
+		/* keep track of the statistics */
+		if (status & (DZ_OERR | DZ_FERR | DZ_PERR)) {
+			if (status & DZ_PERR)	/* parity error */
+				icount->parity++;
+			else if (status & DZ_FERR)	/* frame error */
+				icount->frame++;
+			if (status & DZ_OERR)	/* overrun error */
+				icount->overrun++;
+
+			/*  check to see if we should ignore the character
+			   and mask off conditions that should be ignored
+			 */
+
+			if (status & dport->port.ignore_status_mask) {
+				if (++ignore > 100)
+					break;
+				goto ignore_char;
+			}
+			/* mask off the error conditions we want to ignore */
+			tmp = status & dport->port.read_status_mask;
+
+			if (tmp & DZ_PERR) {
+				*tty->flip.flag_buf_ptr = TTY_PARITY;
+#ifdef DEBUG_DZ
+				debug_console("PERR\n", 5);
+#endif
+			} else if (tmp & DZ_FERR) {
+				*tty->flip.flag_buf_ptr = TTY_FRAME;
+#ifdef DEBUG_DZ
+				debug_console("FERR\n", 5);
+#endif
+			}
+			if (tmp & DZ_OERR) {
+#ifdef DEBUG_DZ
+				debug_console("OERR\n", 5);
+#endif
+				if (tty->flip.count < TTY_FLIPBUF_SIZE) {
+					tty->flip.count++;
+					tty->flip.flag_buf_ptr++;
+					tty->flip.char_buf_ptr++;
+					*tty->flip.flag_buf_ptr = TTY_OVERRUN;
+				}
+			}
+		}
+		tty->flip.flag_buf_ptr++;
+		tty->flip.char_buf_ptr++;
+		tty->flip.count++;
+	      ignore_char:
+	} while (status & DZ_DVAL);
+
+	if (tty)
+		tty_flip_buffer_push(tty);
+}
+
+/*
+ * ------------------------------------------------------------
+ * transmit_char ()
+ *
+ * This routine deals with outputs to any lines.
+ * ------------------------------------------------------------
+ */
+static inline void dz_transmit_chars(struct dz_port *dport)
+{
+	struct circ_buf *xmit = &dport->port.info->xmit;
+	unsigned char tmp;
+
+	if (dport->port.x_char) {	/* XON/XOFF chars */
+		dz_out(dport, DZ_TDR, dport->port.x_char);
+		dport->port.icount.tx++;
+		dport->port.x_char = 0;
+		return;
+	}
+	/* if nothing to do or stopped or hardware stopped */
+	if (uart_circ_empty(xmit) || uart_tx_stopped(&dport->port)) {
+		dz_stop_tx(&dport->port, 0);
+		return;
+	}
+
+	/*
+	 * if something to do ... (rember the dz has no output fifo so we go
+	 * one char at a time :-<
+	 */
+	tmp = xmit->buf[xmit->tail];
+	xmit->tail = (xmit->tail + 1) & (DZ_XMIT_SIZE - 1);
+	dz_out(dport, DZ_TDR, tmp);
+	dport->port.icount.tx++;
+
+	if (uart_circ_chars_pending(xmit) < DZ_WAKEUP_CHARS)
+		uart_write_wakeup(&dport->port);
+
+	/* Are we done */
+	if (uart_circ_empty(xmit))
+		dz_stop_tx(&dport->port, 0);
+}
+
+/*
+ * ------------------------------------------------------------
+ * check_modem_status ()
+ *
+ * Only valid for the MODEM line duh !
+ * ------------------------------------------------------------
+ */
+static inline void check_modem_status(struct dz_port *dport)
+{
+	unsigned short status;
+
+	/* if not ne modem line just return */
+	if (dport->port.line != DZ_MODEM)
+		return;
+
+	status = dz_in(dport, DZ_MSR);
+
+	/* it's easy, since DSR2 is the only bit in the register */
+	if (status)
+		dport->port.icount.dsr++;
+}
+
+/*
+ * ------------------------------------------------------------
+ * dz_interrupt ()
+ *
+ * this is the main interrupt routine for the DZ chip.
+ * It deals with the multiple ports.
+ * ------------------------------------------------------------
+ */
+static irqreturn_t dz_interrupt(int irq, void *dev, struct pt_regs *regs)
+{
+	struct dz_port *dport;
+	unsigned short status;
+
+	/* get the reason why we just got an irq */
+	status = dz_in((struct dz_port *)dev, DZ_CSR);
+	dport = &dz_ports[LINE(status)];
+
+	if (status & DZ_RDONE)
+		dz_receive_chars(dport);
+
+	if (status & DZ_TRDY)
+		dz_transmit_chars(dport);
+
+	/* FIXME: what about check modem status??? --rmk */
+
+	return IRQ_HANDLED;
+}
+
+/*
+ * -------------------------------------------------------------------
+ * Here ends the DZ interrupt routines.
+ * -------------------------------------------------------------------
+ */
+
+static unsigned int dz_get_mctrl(struct uart_port *uport)
+{
+	struct dz_port *dport = (struct dz_port *)uport;
+	unsigned int mctrl = TIOCM_CAR | TIOCM_DSR | TIOCM_CTS;
+
+	if (dport->port.line == DZ_MODEM) {
+		/*
+		 * CHECKME: This is a guess from the other code... --rmk
+		 */
+		if (dz_in(dport, DZ_MSR) & DZ_MODEM_DSR)
+			mctrl &= ~TIOCM_DSR;
+	}
+
+	return mctrl;
+}
+
+static void dz_set_mctrl(struct uart_port *uport, unsigned int mctrl)
+{
+	struct dz_port *dport = (struct dz_port *)uport;
+	unsigned short tmp;
+
+	if (dport->port.line == DZ_MODEM) {
+		tmp = dz_in(dport, DZ_TCR);
+		if (mctrl & TIOCM_DTR)
+			tmp &= ~DZ_MODEM_DTR;
+		else
+			tmp |= DZ_MODEM_DTR;
+		dz_out(dport, DZ_TCR, tmp);
+	}
+}
+
+/*
+ * -------------------------------------------------------------------
+ * startup ()
+ *
+ * various initialization tasks
+ * ------------------------------------------------------------------- 
+ */
+static int dz_startup(struct uart_port *uport)
+{
+	struct dz_port *dport = (struct dz_port *)uport;
+	unsigned long flags;
+	unsigned short tmp;
+
+	/* The dz lines for the mouse/keyboard must be
+	 * opened using their respective drivers.
+	 */
+	if ((dport->port.line == DZ_KEYBOARD) ||
+	    (dport->port.line == DZ_MOUSE))
+		return -ENODEV;
+
+	spin_lock_irqsave(&dport->port.lock, flags);
+
+	/* enable the interrupt and the scanning */
+	tmp = dz_in(dport, DZ_CSR);
+	tmp |= DZ_RIE | DZ_TIE | DZ_MSE;
+	dz_out(dport, DZ_CSR, tmp);
+
+	spin_unlock_irqrestore(&dport->port.lock, flags);
+
+	return 0;
+}
+
+/* 
+ * -------------------------------------------------------------------
+ * shutdown ()
+ *
+ * This routine will shutdown a serial port; interrupts are disabled, and
+ * DTR is dropped if the hangup on close termio flag is on.
+ * ------------------------------------------------------------------- 
+ */
+static void dz_shutdown(struct uart_port *uport)
+{
+	dz_stop_tx(uport, 0);
+}
+
+/*
+ * get_lsr_info - get line status register info
+ *
+ * Purpose: Let user call ioctl() to get info when the UART physically
+ *          is emptied.  On bus types like RS485, the transmitter must
+ *          release the bus after transmitting. This must be done when
+ *          the transmit shift register is empty, not be done when the
+ *          transmit holding register is empty.  This functionality
+ *          allows an RS485 driver to be written in user space. 
+ */
+static unsigned int dz_tx_empty(struct uart_port *uport)
+{
+	struct dz_port *dport = (struct dz_port *)uport;
+	unsigned short status = dz_in(dport, DZ_LPR);
+
+	/* FIXME: this appears to be obviously broken --rmk. */
+	return status ? TIOCSER_TEMT : 0;
+}
+
+static void dz_break_ctl(struct uart_port *uport, int break_state)
+{
+	struct dz_port *dport = (struct dz_port *)uport;
+	unsigned long flags;
+	unsigned short tmp, mask = 1 << uport->line;
+
+	spin_lock_irqsave(&uport->lock, flags);
+	tmp = dz_in(dport, DZ_TCR);
+	if (break_state)
+		tmp |= mask;
+	else
+		tmp &= ~mask;
+	dz_out(dport, DZ_TCR, tmp);
+	spin_unlock_irqrestore(&uport->lock, flags);
+}
+
+static void dz_set_termios(struct uart_port *uport, struct termios *termios,
+			   struct termios *old_termios)
+{
+	struct dz_port *dport = (struct dz_port *)uport;
+	unsigned long flags;
+	unsigned int cflag, baud;
+
+	cflag = dport->port.line;
+
+	switch (termios->c_cflag & CSIZE) {
+	case CS5:
+		cflag |= DZ_CS5;
+		break;
+	case CS6:
+		cflag |= DZ_CS6;
+		break;
+	case CS7:
+		cflag |= DZ_CS7;
+		break;
+	case CS8:
+	default:
+		cflag |= DZ_CS8;
+	}
+
+	if (termios->c_cflag & CSTOPB)
+		cflag |= DZ_CSTOPB;
+	if (termios->c_cflag & PARENB)
+		cflag |= DZ_PARENB;
+	if (termios->c_cflag & PARODD)
+		cflag |= DZ_PARODD;
+
+	baud = uart_get_baud_rate(uport, termios, old_termios, 50, 9600);
+	switch (baud) {
+	case 50:
+		cflag |= DZ_B50;
+		break;
+	case 75:
+		cflag |= DZ_B75;
+		break;
+	case 110:
+		cflag |= DZ_B110;
+		break;
+	case 134:
+		cflag |= DZ_B134;
+		break;
+	case 150:
+		cflag |= DZ_B150;
+		break;
+	case 300:
+		cflag |= DZ_B300;
+		break;
+	case 600:
+		cflag |= DZ_B600;
+		break;
+	case 1200:
+		cflag |= DZ_B1200;
+		break;
+	case 1800:
+		cflag |= DZ_B1800;
+		break;
+	case 2000:
+		cflag |= DZ_B2000;
+		break;
+	case 2400:
+		cflag |= DZ_B2400;
+		break;
+	case 3600:
+		cflag |= DZ_B3600;
+		break;
+	case 4800:
+		cflag |= DZ_B4800;
+		break;
+	case 7200:
+		cflag |= DZ_B7200;
+		break;
+	case 9600:
+	default:
+		cflag |= DZ_B9600;
+	}
+
+	if (termios->c_cflag & CREAD)
+		cflag |= DZ_RXENAB;
+
+	spin_lock_irqsave(&dport->port.lock, flags);
+
+	dz_out(dport, DZ_LPR, cflag);
+	dport->cflag = cflag;
+
+	/* setup accept flag */
+	dport->port.read_status_mask = DZ_OERR;
+	if (termios->c_iflag & INPCK)
+		dport->port.read_status_mask |= DZ_FERR | DZ_PERR;
+
+	/* characters to ignore */
+	uport->ignore_status_mask = 0;
+	if (termios->c_iflag & IGNPAR)
+		dport->port.ignore_status_mask |= DZ_FERR | DZ_PERR;
+
+	spin_unlock_irqrestore(&dport->port.lock, flags);
+}
+
+static const char *dz_type(struct uart_port *port)
+{
+	return "DZ";
+}
+
+static void dz_release_port(struct uart_port *port)
+{
+	/* nothing to do */
+}
+
+static int dz_request_port(struct uart_port *port)
+{
+	return 0;
+}
+
+static void dz_config_port(struct uart_port *port, int flags)
+{
+	if (flags & UART_CONFIG_TYPE)
+		port->type = PORT_DZ;
+}
+
+/*
+ * verify the new serial_struct (for TIOCSSERIAL).
+ */
+static int dz_verify_port(struct uart_port *port, struct serial_struct *ser)
+{
+	int ret = 0;
+	if (ser->type != PORT_UNKNOWN && ser->type != PORT_DZ)
+		ret = -EINVAL;
+	if (ser->irq != port->irq)
+		ret = -EINVAL;
+	return ret;
+}
+
+static struct uart_ops dz_ops = {
+	.tx_empty	= dz_tx_empty,
+	.get_mctrl	= dz_get_mctrl,
+	.set_mctrl	= dz_set_mctrl,
+	.stop_tx	= dz_stop_tx,
+	.start_tx	= dz_start_tx,
+	.stop_rx	= dz_stop_rx,
+	.enable_ms	= dz_enable_ms,
+	.break_ctl	= dz_break_ctl,
+	.startup	= dz_startup,
+	.shutdown	= dz_shutdown,
+	.set_termios	= dz_set_termios,
+	.type		= dz_type,
+	.release_port	= dz_release_port,
+	.request_port	= dz_request_port,
+	.config_port	= dz_config_port,
+	.verify_port	= dz_verify_port,
+};
+
+static void __init dz_init_ports(void)
+{
+	static int first = 1;
+	struct dz_port *dport;
+	unsigned long base;
+	int i;
+
+	if (!first)
+		return;
+	first = 0;
+
+	if (mips_machtype == MACH_DS23100 ||
+	    mips_machtype == MACH_DS5100)
+		base = (unsigned long) KN01_DZ11_BASE;
+	else
+		base = (unsigned long) KN02_DZ11_BASE;
+
+	for (i = 0, dport = dz_ports; i < DZ_NB_PORT; i++, dport++) {
+		spin_lock_init(&dport->port.lock);
+		dport->port.membase	= (char *) base;
+		dport->port.iotype	= SERIAL_IO_PORT;
+		dport->port.irq		= dec_interrupt[DEC_IRQ_DZ11];
+		dport->port.line	= i;
+		dport->port.fifosize	= 1;
+		dport->port.ops		= &dz_ops;
+		dport->port.flags	= UPF_BOOT_AUTOCONF;
+	}
+}
+
+static void dz_reset(struct dz_port *dport)
+{
+	dz_out(dport, DZ_CSR, DZ_CLR);
+
+	while (dz_in(dport, DZ_CSR) & DZ_CLR);
+		/* FIXME: cpu_relax? */
+
+	iob();
+
+	/* enable scanning */
+	dz_out(dport, DZ_CSR, DZ_MSE);
+}
+
+#ifdef CONFIG_SERIAL_DZ_CONSOLE
+static void dz_console_put_char(struct dz_port *dport, unsigned char ch)
+{
+	unsigned long flags;
+	int loops = 2500;
+	unsigned short tmp = ch;
+	/* this code sends stuff out to serial device - spinning its
+	   wheels and waiting. */
+
+	spin_lock_irqsave(&dport->port.lock, flags);
+
+	/* spin our wheels */
+	while (((dz_in(dport, DZ_CSR) & DZ_TRDY) != DZ_TRDY) && loops--)
+		/* FIXME: cpu_relax, udelay? --rmk */
+		;
+
+	/* Actually transmit the character. */
+	dz_out(dport, DZ_TDR, tmp);
+
+	spin_unlock_irqrestore(&dport->port.lock, flags);
+}
+/* 
+ * -------------------------------------------------------------------
+ * dz_console_print ()
+ *
+ * dz_console_print is registered for printk.
+ * The console must be locked when we get here.
+ * ------------------------------------------------------------------- 
+ */
+static void dz_console_print(struct console *cons,
+			     const char *str,
+			     unsigned int count)
+{
+	struct dz_port *dport = &dz_ports[CONSOLE_LINE];
+#ifdef DEBUG_DZ
+	prom_printf((char *) str);
+#endif
+	while (count--) {
+		if (*str == '\n')
+			dz_console_put_char(dport, '\r');
+		dz_console_put_char(dport, *str++);
+	}
+}
+
+static int __init dz_console_setup(struct console *co, char *options)
+{
+	struct dz_port *dport = &dz_ports[CONSOLE_LINE];
+	int baud = 9600;
+	int bits = 8;
+	int parity = 'n';
+	int flow = 'n';
+	int ret;
+	unsigned short mask, tmp;
+
+	if (options)
+		uart_parse_options(options, &baud, &parity, &bits, &flow);
+
+	dz_reset(dport);
+
+	ret = uart_set_options(&dport->port, co, baud, parity, bits, flow);
+	if (ret == 0) {
+		mask = 1 << dport->port.line;
+		tmp = dz_in(dport, DZ_TCR);	/* read the TX flag */
+		if (!(tmp & mask)) {
+			tmp |= mask;		/* set the TX flag */
+			dz_out(dport, DZ_TCR, tmp);
+		}
+	}
+
+	return ret;
+}
+
+static struct console dz_sercons =
+{
+	.name	= "ttyS",
+	.write	= dz_console_print,
+	.device	= uart_console_device,
+	.setup	= dz_console_setup,
+	.flags	= CON_CONSDEV | CON_PRINTBUFFER,
+	.index	= CONSOLE_LINE,
+};
+
+void __init dz_serial_console_init(void)
+{
+	dz_init_ports();
+
+	register_console(&dz_sercons);
+}
+
+#define SERIAL_DZ_CONSOLE	&dz_sercons
+#else
+#define SERIAL_DZ_CONSOLE	NULL
+#endif /* CONFIG_SERIAL_DZ_CONSOLE */
+
+static struct uart_driver dz_reg = {
+	.owner			= THIS_MODULE,
+	.driver_name		= "serial",
+#ifdef CONFIG_DEVFS
+	.dev_name		= "tts/%d",
+#else
+	.dev_name		= "ttyS%d",
+#endif
+	.major			= TTY_MAJOR,
+	.minor			= 64,
+	.nr			= DZ_NB_PORT,
+	.cons			= SERIAL_DZ_CONSOLE,
+};
+
+int __init dz_init(void)
+{
+	unsigned long flags;
+	int ret, i;
+
+	printk("%s%s\n", dz_name, dz_version);
+
+	dz_init_ports();
+
+	save_flags(flags);
+	cli();
+
+#ifndef CONFIG_SERIAL_DZ_CONSOLE
+	/* reset the chip */
+	dz_reset(&dz_ports[0]);
+#endif
+
+	/* order matters here... the trick is that flags
+	   is updated... in request_irq - to immediatedly obliterate
+	   it is unwise. */
+	restore_flags(flags);
+
+	if (request_irq(dz_ports[0].port.irq, dz_interrupt,
+			SA_INTERRUPT, "DZ", &dz_ports[0]))
+		panic("Unable to register DZ interrupt");
+
+	ret = uart_register_driver(&dz_reg);
+	if (ret != 0)
+		return ret;
+
+	for (i = 0; i < DZ_NB_PORT; i++)
+		uart_add_one_port(&dz_reg, &dz_ports[i].port);
+
+	return ret;
+}
+
+MODULE_DESCRIPTION("DECstation DZ serial driver");
+MODULE_LICENSE("GPL");
--- diff/drivers/serial/dz.h	1970-01-01 01:00:00.000000000 +0100
+++ source/drivers/serial/dz.h	2004-02-23 13:56:45.000000000 +0000
@@ -0,0 +1,118 @@
+/*
+ * dz.h: Serial port driver for DECStations equiped 
+ *       with the DZ chipset.
+ *
+ * Copyright (C) 1998 Olivier A. D. Lebaillif 
+ *             
+ * Email: olivier.lebaillif@ifrsys.com
+ *
+ */
+#ifndef DZ_SERIAL_H
+#define DZ_SERIAL_H
+
+/*
+ * Definitions for the Control and Status Received.
+ */
+#define DZ_TRDY        0x8000                 /* Transmitter empty */
+#define DZ_TIE         0x4000                 /* Transmitter Interrupt Enable */
+#define DZ_RDONE       0x0080                 /* Receiver data ready */
+#define DZ_RIE         0x0040                 /* Receive Interrupt Enable */
+#define DZ_MSE         0x0020                 /* Master Scan Enable */
+#define DZ_CLR         0x0010                 /* Master reset */
+#define DZ_MAINT       0x0008                 /* Loop Back Mode */
+
+/*
+ * Definitions for the Received buffer. 
+ */
+#define DZ_RBUF_MASK   0x00FF                 /* Data Mask in the Receive Buffer */
+#define DZ_LINE_MASK   0x0300                 /* Line Mask in the Receive Buffer */
+#define DZ_DVAL        0x8000                 /* Valid Data indicator */
+#define DZ_OERR        0x4000                 /* Overrun error indicator */
+#define DZ_FERR        0x2000                 /* Frame error indicator */
+#define DZ_PERR        0x1000                 /* Parity error indicator */
+
+#define LINE(x) (x & DZ_LINE_MASK) >> 8       /* Get the line number from the input buffer */
+#define UCHAR(x) (unsigned char)(x & DZ_RBUF_MASK)
+
+/*
+ * Definitions for the Transmit Register.
+ */
+#define DZ_LINE_KEYBOARD 0x0001
+#define DZ_LINE_MOUSE    0x0002
+#define DZ_LINE_MODEM    0x0004
+#define DZ_LINE_PRINTER  0x0008
+
+#define DZ_MODEM_DTR     0x0400               /* DTR for the modem line (2) */
+
+/*
+ * Definitions for the Modem Status Register.
+ */
+#define DZ_MODEM_DSR     0x0200               /* DSR for the modem line (2) */
+
+/*
+ * Definitions for the Transmit Data Register.
+ */
+#define DZ_BRK0          0x0100               /* Break assertion for line 0 */
+#define DZ_BRK1          0x0200               /* Break assertion for line 1 */
+#define DZ_BRK2          0x0400               /* Break assertion for line 2 */
+#define DZ_BRK3          0x0800               /* Break assertion for line 3 */
+
+/*
+ * Definitions for the Line Parameter Register.
+ */
+#define DZ_KEYBOARD      0x0000               /* line 0 = keyboard */
+#define DZ_MOUSE         0x0001               /* line 1 = mouse */
+#define DZ_MODEM         0x0002               /* line 2 = modem */
+#define DZ_PRINTER       0x0003               /* line 3 = printer */
+
+#define DZ_CSIZE         0x0018               /* Number of bits per byte (mask) */
+#define DZ_CS5           0x0000               /* 5 bits per byte */
+#define DZ_CS6           0x0008               /* 6 bits per byte */
+#define DZ_CS7           0x0010               /* 7 bits per byte */
+#define DZ_CS8           0x0018               /* 8 bits per byte */
+
+#define DZ_CSTOPB        0x0020               /* 2 stop bits instead of one */ 
+
+#define DZ_PARENB        0x0040               /* Parity enable */
+#define DZ_PARODD        0x0080               /* Odd parity instead of even */
+
+#define DZ_CBAUD         0x0E00               /* Baud Rate (mask) */
+#define DZ_B50           0x0000
+#define DZ_B75           0x0100
+#define DZ_B110          0x0200
+#define DZ_B134          0x0300
+#define DZ_B150          0x0400
+#define DZ_B300          0x0500
+#define DZ_B600          0x0600
+#define DZ_B1200         0x0700 
+#define DZ_B1800         0x0800
+#define DZ_B2000         0x0900
+#define DZ_B2400         0x0A00
+#define DZ_B3600         0x0B00
+#define DZ_B4800         0x0C00
+#define DZ_B7200         0x0D00
+#define DZ_B9600         0x0E00
+
+#define DZ_CREAD         0x1000               /* Enable receiver */
+#define DZ_RXENAB        0x1000               /* enable receive char */
+/*
+ * Addresses for the DZ registers
+ */
+#define DZ_CSR       0x00            /* Control and Status Register */
+#define DZ_RBUF      0x08            /* Receive Buffer */
+#define DZ_LPR       0x08            /* Line Parameters Register */
+#define DZ_TCR       0x10            /* Transmitter Control Register */
+#define DZ_MSR       0x18            /* Modem Status Register */
+#define DZ_TDR       0x18            /* Transmit Data Register */
+
+#define DZ_NB_PORT 4
+
+#define DZ_XMIT_SIZE   4096                 /* buffer size */
+#define DZ_WAKEUP_CHARS   DZ_XMIT_SIZE/4
+
+#ifdef MODULE
+int init_module (void)
+void cleanup_module (void)
+#endif
+
+#endif /* DZ_SERIAL_H */
--- diff/drivers/serial/ip22zilog.c	1970-01-01 01:00:00.000000000 +0100
+++ source/drivers/serial/ip22zilog.c	2004-02-23 13:56:45.000000000 +0000
@@ -0,0 +1,1307 @@
+/*
+ * Driver for Zilog serial chips found on SGI workstations and
+ * servers.  This driver could actually be made more generic.
+ *
+ * This is based on the drivers/serial/sunzilog.c code as of 2.6.0-test7 and the
+ * old drivers/sgi/char/sgiserial.c code which itself is based of the original
+ * drivers/sbus/char/zs.c code.  A lot of code has been simply moved over
+ * directly from there but much has been rewritten.  Credits therefore go out
+ * to David S. Miller, Eddie C. Dost, Pete Zaitcev, Ted Ts'o and Alex Buell
+ * for their work there.
+ *
+ *  Copyright (C) 2002 Ralf Baechle (ralf@linux-mips.org)
+ *  Copyright (C) 2002 David S. Miller (davem@redhat.com)
+ */
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/errno.h>
+#include <linux/delay.h>
+#include <linux/tty.h>
+#include <linux/tty_flip.h>
+#include <linux/major.h>
+#include <linux/string.h>
+#include <linux/ptrace.h>
+#include <linux/ioport.h>
+#include <linux/slab.h>
+#include <linux/circ_buf.h>
+#include <linux/serial.h>
+#include <linux/sysrq.h>
+#include <linux/console.h>
+#include <linux/spinlock.h>
+#include <linux/init.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/sgialib.h>
+#include <asm/sgi/ioc.h>
+#include <asm/sgi/hpc3.h>
+#include <asm/sgi/ip22.h>
+
+#if defined(CONFIG_SERIAL_IP22_ZILOG_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
+#define SUPPORT_SYSRQ
+#endif
+
+#include <linux/serial_core.h>
+
+#include "ip22zilog.h"
+
+int ip22serial_current_minor = 64;
+
+void ip22_do_break(void);
+
+/*
+ * On IP22 we need to delay after register accesses but we do not need to
+ * flush writes.
+ */
+#define ZSDELAY()		udelay(5)
+#define ZSDELAY_LONG()		udelay(20)
+#define ZS_WSYNC(channel)	do { } while (0)
+
+#define NUM_IP22ZILOG	1
+#define NUM_CHANNELS	(NUM_IP22ZILOG * 2)
+
+#define ZS_CLOCK		4915200 /* Zilog input clock rate. */
+#define ZS_CLOCK_DIVISOR	16      /* Divisor this driver uses. */
+
+/*
+ * We wrap our port structure around the generic uart_port.
+ */
+struct uart_ip22zilog_port {
+	struct uart_port		port;
+
+	/* IRQ servicing chain.  */
+	struct uart_ip22zilog_port	*next;
+
+	/* Current values of Zilog write registers.  */
+	unsigned char			curregs[NUM_ZSREGS];
+
+	unsigned int			flags;
+#define IP22ZILOG_FLAG_IS_CONS		0x00000004
+#define IP22ZILOG_FLAG_IS_KGDB		0x00000008
+#define IP22ZILOG_FLAG_MODEM_STATUS	0x00000010
+#define IP22ZILOG_FLAG_IS_CHANNEL_A	0x00000020
+#define IP22ZILOG_FLAG_REGS_HELD	0x00000040
+#define IP22ZILOG_FLAG_TX_STOPPED	0x00000080
+#define IP22ZILOG_FLAG_TX_ACTIVE	0x00000100
+
+	unsigned int cflag;
+
+	/* L1-A keyboard break state.  */
+	int				kbd_id;
+	int				l1_down;
+
+	unsigned char			parity_mask;
+	unsigned char			prev_status;
+};
+
+#define ZILOG_CHANNEL_FROM_PORT(PORT)	((struct zilog_channel *)((PORT)->membase))
+#define UART_ZILOG(PORT)		((struct uart_ip22zilog_port *)(PORT))
+#define IP22ZILOG_GET_CURR_REG(PORT, REGNUM)		\
+	(UART_ZILOG(PORT)->curregs[REGNUM])
+#define IP22ZILOG_SET_CURR_REG(PORT, REGNUM, REGVAL)	\
+	((UART_ZILOG(PORT)->curregs[REGNUM]) = (REGVAL))
+#define ZS_IS_CONS(UP)	((UP)->flags & IP22ZILOG_FLAG_IS_CONS)
+#define ZS_IS_KGDB(UP)	((UP)->flags & IP22ZILOG_FLAG_IS_KGDB)
+#define ZS_WANTS_MODEM_STATUS(UP)	((UP)->flags & IP22ZILOG_FLAG_MODEM_STATUS)
+#define ZS_IS_CHANNEL_A(UP)	((UP)->flags & IP22ZILOG_FLAG_IS_CHANNEL_A)
+#define ZS_REGS_HELD(UP)	((UP)->flags & IP22ZILOG_FLAG_REGS_HELD)
+#define ZS_TX_STOPPED(UP)	((UP)->flags & IP22ZILOG_FLAG_TX_STOPPED)
+#define ZS_TX_ACTIVE(UP)	((UP)->flags & IP22ZILOG_FLAG_TX_ACTIVE)
+
+/* Reading and writing Zilog8530 registers.  The delays are to make this
+ * driver work on the IP22 which needs a settling delay after each chip
+ * register access, other machines handle this in hardware via auxiliary
+ * flip-flops which implement the settle time we do in software.
+ *
+ * The port lock must be held and local IRQs must be disabled
+ * when {read,write}_zsreg is invoked.
+ */
+static unsigned char read_zsreg(struct zilog_channel *channel,
+				unsigned char reg)
+{
+	unsigned char retval;
+
+	writeb(reg, &channel->control);
+	ZSDELAY();
+	retval = readb(&channel->control);
+	ZSDELAY();
+
+	return retval;
+}
+
+static void write_zsreg(struct zilog_channel *channel,
+			unsigned char reg, unsigned char value)
+{
+	writeb(reg, &channel->control);
+	ZSDELAY();
+	writeb(value, &channel->control);
+	ZSDELAY();
+}
+
+static void ip22zilog_clear_fifo(struct zilog_channel *channel)
+{
+	int i;
+
+	for (i = 0; i < 32; i++) {
+		unsigned char regval;
+
+		regval = readb(&channel->control);
+		ZSDELAY();
+		if (regval & Rx_CH_AV)
+			break;
+
+		regval = read_zsreg(channel, R1);
+		readb(&channel->data);
+		ZSDELAY();
+
+		if (regval & (PAR_ERR | Rx_OVR | CRC_ERR)) {
+			writeb(ERR_RES, &channel->control);
+			ZSDELAY();
+			ZS_WSYNC(channel);
+		}
+	}
+}
+
+/* This function must only be called when the TX is not busy.  The UART
+ * port lock must be held and local interrupts disabled.
+ */
+static void __load_zsregs(struct zilog_channel *channel, unsigned char *regs)
+{
+	int i;
+
+	/* Let pending transmits finish.  */
+	for (i = 0; i < 1000; i++) {
+		unsigned char stat = read_zsreg(channel, R1);
+		if (stat & ALL_SNT)
+			break;
+		udelay(100);
+	}
+
+	writeb(ERR_RES, &channel->control);
+	ZSDELAY();
+	ZS_WSYNC(channel);
+
+	ip22zilog_clear_fifo(channel);
+
+	/* Disable all interrupts.  */
+	write_zsreg(channel, R1,
+		    regs[R1] & ~(RxINT_MASK | TxINT_ENAB | EXT_INT_ENAB));
+
+	/* Set parity, sync config, stop bits, and clock divisor.  */
+	write_zsreg(channel, R4, regs[R4]);
+
+	/* Set misc. TX/RX control bits.  */
+	write_zsreg(channel, R10, regs[R10]);
+
+	/* Set TX/RX controls sans the enable bits.  */
+	write_zsreg(channel, R3, regs[R3] & ~RxENAB);
+	write_zsreg(channel, R5, regs[R5] & ~TxENAB);
+
+	/* Synchronous mode config.  */
+	write_zsreg(channel, R6, regs[R6]);
+	write_zsreg(channel, R7, regs[R7]);
+
+	/* Don't mess with the interrupt vector (R2, unused by us) and
+	 * master interrupt control (R9).  We make sure this is setup
+	 * properly at probe time then never touch it again.
+	 */
+
+	/* Disable baud generator.  */
+	write_zsreg(channel, R14, regs[R14] & ~BRENAB);
+
+	/* Clock mode control.  */
+	write_zsreg(channel, R11, regs[R11]);
+
+	/* Lower and upper byte of baud rate generator divisor.  */
+	write_zsreg(channel, R12, regs[R12]);
+	write_zsreg(channel, R13, regs[R13]);
+	
+	/* Now rewrite R14, with BRENAB (if set).  */
+	write_zsreg(channel, R14, regs[R14]);
+
+	/* External status interrupt control.  */
+	write_zsreg(channel, R15, regs[R15]);
+
+	/* Reset external status interrupts.  */
+	write_zsreg(channel, R0, RES_EXT_INT);
+	write_zsreg(channel, R0, RES_EXT_INT);
+
+	/* Rewrite R3/R5, this time without enables masked.  */
+	write_zsreg(channel, R3, regs[R3]);
+	write_zsreg(channel, R5, regs[R5]);
+
+	/* Rewrite R1, this time without IRQ enabled masked.  */
+	write_zsreg(channel, R1, regs[R1]);
+}
+
+/* Reprogram the Zilog channel HW registers with the copies found in the
+ * software state struct.  If the transmitter is busy, we defer this update
+ * until the next TX complete interrupt.  Else, we do it right now.
+ *
+ * The UART port lock must be held and local interrupts disabled.
+ */
+static void ip22zilog_maybe_update_regs(struct uart_ip22zilog_port *up,
+				       struct zilog_channel *channel)
+{
+	if (!ZS_REGS_HELD(up)) {
+		if (ZS_TX_ACTIVE(up)) {
+			up->flags |= IP22ZILOG_FLAG_REGS_HELD;
+		} else {
+			__load_zsregs(channel, up->curregs);
+		}
+	}
+}
+
+static void ip22zilog_receive_chars(struct uart_ip22zilog_port *up,
+				   struct zilog_channel *channel,
+				   struct pt_regs *regs)
+{
+	struct tty_struct *tty = up->port.info->tty;	/* XXX info==NULL? */
+
+	while (1) {
+		unsigned char ch, r1;
+
+		if (unlikely(tty->flip.count >= TTY_FLIPBUF_SIZE)) {
+			tty->flip.work.func((void *)tty);
+			if (tty->flip.count >= TTY_FLIPBUF_SIZE)
+				return;		/* XXX Ignores SysRq when we need it most. Fix. */
+		}
+
+		r1 = read_zsreg(channel, R1);
+		if (r1 & (PAR_ERR | Rx_OVR | CRC_ERR)) {
+			writeb(ERR_RES, &channel->control);
+			ZSDELAY();
+			ZS_WSYNC(channel);
+		}
+
+		ch = readb(&channel->control);
+		ZSDELAY();
+
+		/* This funny hack depends upon BRK_ABRT not interfering
+		 * with the other bits we care about in R1.
+		 */
+		if (ch & BRK_ABRT)
+			r1 |= BRK_ABRT;
+
+		ch = readb(&channel->data);
+		ZSDELAY();
+
+		ch &= up->parity_mask;
+
+		if (ZS_IS_CONS(up) && (r1 & BRK_ABRT)) {
+			/* Wait for BREAK to deassert to avoid potentially
+			 * confusing the PROM.
+			 */
+			while (1) {
+				ch = readb(&channel->control);
+				ZSDELAY();
+				if (!(ch & BRK_ABRT))
+					break;
+			}
+			ip22_do_break();
+			return;
+		}
+
+		/* A real serial line, record the character and status.  */
+		*tty->flip.char_buf_ptr = ch;
+		*tty->flip.flag_buf_ptr = TTY_NORMAL;
+		up->port.icount.rx++;
+		if (r1 & (BRK_ABRT | PAR_ERR | Rx_OVR | CRC_ERR)) {
+			if (r1 & BRK_ABRT) {
+				r1 &= ~(PAR_ERR | CRC_ERR);
+				up->port.icount.brk++;
+				if (uart_handle_break(&up->port))
+					goto next_char;
+			}
+			else if (r1 & PAR_ERR)
+				up->port.icount.parity++;
+			else if (r1 & CRC_ERR)
+				up->port.icount.frame++;
+			if (r1 & Rx_OVR)
+				up->port.icount.overrun++;
+			r1 &= up->port.read_status_mask;
+			if (r1 & BRK_ABRT)
+				*tty->flip.flag_buf_ptr = TTY_BREAK;
+			else if (r1 & PAR_ERR)
+				*tty->flip.flag_buf_ptr = TTY_PARITY;
+			else if (r1 & CRC_ERR)
+				*tty->flip.flag_buf_ptr = TTY_FRAME;
+		}
+		if (uart_handle_sysrq_char(&up->port, ch, regs))
+			goto next_char;
+
+		if (up->port.ignore_status_mask == 0xff ||
+		    (r1 & up->port.ignore_status_mask) == 0) {
+			tty->flip.flag_buf_ptr++;
+			tty->flip.char_buf_ptr++;
+			tty->flip.count++;
+		}
+		if ((r1 & Rx_OVR) &&
+		    tty->flip.count < TTY_FLIPBUF_SIZE) {
+			*tty->flip.flag_buf_ptr = TTY_OVERRUN;
+			tty->flip.flag_buf_ptr++;
+			tty->flip.char_buf_ptr++;
+			tty->flip.count++;
+		}
+	next_char:
+		ch = readb(&channel->control);
+		ZSDELAY();
+		if (!(ch & Rx_CH_AV))
+			break;
+	}
+
+	tty_flip_buffer_push(tty);
+}
+
+static void ip22zilog_status_handle(struct uart_ip22zilog_port *up,
+				   struct zilog_channel *channel,
+				   struct pt_regs *regs)
+{
+	unsigned char status;
+
+	status = readb(&channel->control);
+	ZSDELAY();
+
+	writeb(RES_EXT_INT, &channel->control);
+	ZSDELAY();
+	ZS_WSYNC(channel);
+
+	if (ZS_WANTS_MODEM_STATUS(up)) {
+		if (status & SYNC)
+			up->port.icount.dsr++;
+
+		/* The Zilog just gives us an interrupt when DCD/CTS/etc. change.
+		 * But it does not tell us which bit has changed, we have to keep
+		 * track of this ourselves.
+		 */
+		if ((status & DCD) ^ up->prev_status)
+			uart_handle_dcd_change(&up->port,
+					       (status & DCD));
+		if ((status & CTS) ^ up->prev_status)
+			uart_handle_cts_change(&up->port,
+					       (status & CTS));
+
+		wake_up_interruptible(&up->port.info->delta_msr_wait);
+	}
+
+	up->prev_status = status;
+}
+
+static void ip22zilog_transmit_chars(struct uart_ip22zilog_port *up,
+				    struct zilog_channel *channel)
+{
+	struct circ_buf *xmit;
+
+	if (ZS_IS_CONS(up)) {
+		unsigned char status = readb(&channel->control);
+		ZSDELAY();
+
+		/* TX still busy?  Just wait for the next TX done interrupt.
+		 *
+		 * It can occur because of how we do serial console writes.  It would
+		 * be nice to transmit console writes just like we normally would for
+		 * a TTY line. (ie. buffered and TX interrupt driven).  That is not
+		 * easy because console writes cannot sleep.  One solution might be
+		 * to poll on enough port->xmit space becomming free.  -DaveM
+		 */
+		if (!(status & Tx_BUF_EMP))
+			return;
+	}
+
+	up->flags &= ~IP22ZILOG_FLAG_TX_ACTIVE;
+
+	if (ZS_REGS_HELD(up)) {
+		__load_zsregs(channel, up->curregs);
+		up->flags &= ~IP22ZILOG_FLAG_REGS_HELD;
+	}
+
+	if (ZS_TX_STOPPED(up)) {
+		up->flags &= ~IP22ZILOG_FLAG_TX_STOPPED;
+		goto ack_tx_int;
+	}
+
+	if (up->port.x_char) {
+		up->flags |= IP22ZILOG_FLAG_TX_ACTIVE;
+		writeb(up->port.x_char, &channel->data);
+		ZSDELAY();
+		ZS_WSYNC(channel);
+
+		up->port.icount.tx++;
+		up->port.x_char = 0;
+		return;
+	}
+
+	if (up->port.info == NULL)
+		goto ack_tx_int;
+	xmit = &up->port.info->xmit;
+	if (uart_circ_empty(xmit)) {
+		uart_write_wakeup(&up->port);
+		goto ack_tx_int;
+	}
+	if (uart_tx_stopped(&up->port))
+		goto ack_tx_int;
+
+	up->flags |= IP22ZILOG_FLAG_TX_ACTIVE;
+	writeb(xmit->buf[xmit->tail], &channel->data);
+	ZSDELAY();
+	ZS_WSYNC(channel);
+
+	xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
+	up->port.icount.tx++;
+
+	if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
+		uart_write_wakeup(&up->port);
+
+	return;
+
+ack_tx_int:
+	writeb(RES_Tx_P, &channel->control);
+	ZSDELAY();
+	ZS_WSYNC(channel);
+}
+
+static irqreturn_t ip22zilog_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+	struct uart_ip22zilog_port *up = dev_id;
+
+	while (up) {
+		struct zilog_channel *channel
+			= ZILOG_CHANNEL_FROM_PORT(&up->port);
+		unsigned char r3;
+
+		spin_lock(&up->port.lock);
+		r3 = read_zsreg(channel, R3);
+
+		/* Channel A */
+		if (r3 & (CHAEXT | CHATxIP | CHARxIP)) {
+			writeb(RES_H_IUS, &channel->control);
+			ZSDELAY();
+			ZS_WSYNC(channel);
+
+			if (r3 & CHARxIP)
+				ip22zilog_receive_chars(up, channel, regs);
+			if (r3 & CHAEXT)
+				ip22zilog_status_handle(up, channel, regs);
+			if (r3 & CHATxIP)
+				ip22zilog_transmit_chars(up, channel);
+		}
+		spin_unlock(&up->port.lock);
+
+		/* Channel B */
+		up = up->next;
+		channel = ZILOG_CHANNEL_FROM_PORT(&up->port);
+
+		spin_lock(&up->port.lock);
+		if (r3 & (CHBEXT | CHBTxIP | CHBRxIP)) {
+			writeb(RES_H_IUS, &channel->control);
+			ZSDELAY();
+			ZS_WSYNC(channel);
+
+			if (r3 & CHBRxIP)
+				ip22zilog_receive_chars(up, channel, regs);
+			if (r3 & CHBEXT)
+				ip22zilog_status_handle(up, channel, regs);
+			if (r3 & CHBTxIP)
+				ip22zilog_transmit_chars(up, channel);
+		}
+		spin_unlock(&up->port.lock);
+
+		up = up->next;
+	}
+
+	return IRQ_HANDLED;
+}
+
+/* A convenient way to quickly get R0 status.  The caller must _not_ hold the
+ * port lock, it is acquired here.
+ */
+static __inline__ unsigned char ip22zilog_read_channel_status(struct uart_port *port)
+{
+	struct zilog_channel *channel;
+	unsigned long flags;
+	unsigned char status;
+
+	spin_lock_irqsave(&port->lock, flags);
+
+	channel = ZILOG_CHANNEL_FROM_PORT(port);
+	status = readb(&channel->control);
+	ZSDELAY();
+
+	spin_unlock_irqrestore(&port->lock, flags);
+
+	return status;
+}
+
+/* The port lock is not held.  */
+static unsigned int ip22zilog_tx_empty(struct uart_port *port)
+{
+	unsigned char status;
+	unsigned int ret;
+
+	status = ip22zilog_read_channel_status(port);
+	if (status & Tx_BUF_EMP)
+		ret = TIOCSER_TEMT;
+	else
+		ret = 0;
+
+	return ret;
+}
+
+/* The port lock is not held.  */
+static unsigned int ip22zilog_get_mctrl(struct uart_port *port)
+{
+	unsigned char status;
+	unsigned int ret;
+
+	status = ip22zilog_read_channel_status(port);
+
+	ret = 0;
+	if (status & DCD)
+		ret |= TIOCM_CAR;
+	if (status & SYNC)
+		ret |= TIOCM_DSR;
+	if (status & CTS)
+		ret |= TIOCM_CTS;
+
+	return ret;
+}
+
+/* The port lock is held and interrupts are disabled.  */
+static void ip22zilog_set_mctrl(struct uart_port *port, unsigned int mctrl)
+{
+	struct uart_ip22zilog_port *up = (struct uart_ip22zilog_port *) port;
+	struct zilog_channel *channel = ZILOG_CHANNEL_FROM_PORT(port);
+	unsigned char set_bits, clear_bits;
+
+	set_bits = clear_bits = 0;
+
+	if (mctrl & TIOCM_RTS)
+		set_bits |= RTS;
+	else
+		clear_bits |= RTS;
+	if (mctrl & TIOCM_DTR)
+		set_bits |= DTR;
+	else
+		clear_bits |= DTR;
+
+	/* NOTE: Not subject to 'transmitter active' rule.  */ 
+	up->curregs[R5] |= set_bits;
+	up->curregs[R5] &= ~clear_bits;
+	write_zsreg(channel, R5, up->curregs[R5]);
+}
+
+/* The port lock is held and interrupts are disabled.  */
+static void ip22zilog_stop_tx(struct uart_port *port, unsigned int tty_stop)
+{
+	struct uart_ip22zilog_port *up = (struct uart_ip22zilog_port *) port;
+
+	up->flags |= IP22ZILOG_FLAG_TX_STOPPED;
+}
+
+/* The port lock is held and interrupts are disabled.  */
+static void ip22zilog_start_tx(struct uart_port *port, unsigned int tty_start)
+{
+	struct uart_ip22zilog_port *up = (struct uart_ip22zilog_port *) port;
+	struct zilog_channel *channel = ZILOG_CHANNEL_FROM_PORT(port);
+	unsigned char status;
+
+	up->flags |= IP22ZILOG_FLAG_TX_ACTIVE;
+	up->flags &= ~IP22ZILOG_FLAG_TX_STOPPED;
+
+	status = readb(&channel->control);
+	ZSDELAY();
+
+	/* TX busy?  Just wait for the TX done interrupt.  */
+	if (!(status & Tx_BUF_EMP))
+		return;
+
+	/* Send the first character to jump-start the TX done
+	 * IRQ sending engine.
+	 */
+	if (port->x_char) {
+		writeb(port->x_char, &channel->data);
+		ZSDELAY();
+		ZS_WSYNC(channel);
+
+		port->icount.tx++;
+		port->x_char = 0;
+	} else {
+		struct circ_buf *xmit = &port->info->xmit;
+
+		writeb(xmit->buf[xmit->tail], &channel->data);
+		ZSDELAY();
+		ZS_WSYNC(channel);
+
+		xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
+		port->icount.tx++;
+
+		if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
+			uart_write_wakeup(&up->port);
+	}
+}
+
+/* The port lock is not held.  */
+static void ip22zilog_stop_rx(struct uart_port *port)
+{
+	struct uart_ip22zilog_port *up = UART_ZILOG(port);
+	struct zilog_channel *channel;
+	unsigned long flags;
+
+	if (ZS_IS_CONS(up))
+		return;
+
+	spin_lock_irqsave(&port->lock, flags);
+
+	channel = ZILOG_CHANNEL_FROM_PORT(port);
+
+	/* Disable all RX interrupts.  */
+	up->curregs[R1] &= ~RxINT_MASK;
+	ip22zilog_maybe_update_regs(up, channel);
+
+	spin_unlock_irqrestore(&port->lock, flags);
+}
+
+/* The port lock is not held.  */
+static void ip22zilog_enable_ms(struct uart_port *port)
+{
+	struct uart_ip22zilog_port *up = (struct uart_ip22zilog_port *) port;
+	struct zilog_channel *channel = ZILOG_CHANNEL_FROM_PORT(port);
+	unsigned char new_reg;
+	unsigned long flags;
+
+	spin_lock_irqsave(&port->lock, flags);
+
+	new_reg = up->curregs[R15] | (DCDIE | SYNCIE | CTSIE);
+	if (new_reg != up->curregs[R15]) {
+		up->curregs[R15] = new_reg;
+
+		/* NOTE: Not subject to 'transmitter active' rule.  */ 
+		write_zsreg(channel, R15, up->curregs[R15]);
+	}
+
+	spin_unlock_irqrestore(&port->lock, flags);
+}
+
+/* The port lock is not held.  */
+static void ip22zilog_break_ctl(struct uart_port *port, int break_state)
+{
+	struct uart_ip22zilog_port *up = (struct uart_ip22zilog_port *) port;
+	struct zilog_channel *channel = ZILOG_CHANNEL_FROM_PORT(port);
+	unsigned char set_bits, clear_bits, new_reg;
+	unsigned long flags;
+
+	set_bits = clear_bits = 0;
+
+	if (break_state)
+		set_bits |= SND_BRK;
+	else
+		clear_bits |= SND_BRK;
+
+	spin_lock_irqsave(&port->lock, flags);
+
+	new_reg = (up->curregs[R5] | set_bits) & ~clear_bits;
+	if (new_reg != up->curregs[R5]) {
+		up->curregs[R5] = new_reg;
+
+		/* NOTE: Not subject to 'transmitter active' rule.  */ 
+		write_zsreg(channel, R5, up->curregs[R5]);
+	}
+
+	spin_unlock_irqrestore(&port->lock, flags);
+}
+
+static void __ip22zilog_startup(struct uart_ip22zilog_port *up)
+{
+	struct zilog_channel *channel;
+
+	channel = ZILOG_CHANNEL_FROM_PORT(&up->port);
+	up->prev_status = readb(&channel->control);
+
+	/* Enable receiver and transmitter.  */
+	up->curregs[R3] |= RxENAB;
+	up->curregs[R5] |= TxENAB;
+
+	up->curregs[R1] |= EXT_INT_ENAB | INT_ALL_Rx | TxINT_ENAB;
+	ip22zilog_maybe_update_regs(up, channel);
+}
+
+static int ip22zilog_startup(struct uart_port *port)
+{
+	struct uart_ip22zilog_port *up = UART_ZILOG(port);
+	unsigned long flags;
+
+	if (ZS_IS_CONS(up))
+		return 0;
+
+	spin_lock_irqsave(&port->lock, flags);
+	__ip22zilog_startup(up);
+	spin_unlock_irqrestore(&port->lock, flags);
+	return 0;
+}
+
+/*
+ * The test for ZS_IS_CONS is explained by the following e-mail:
+ *****
+ * From: Russell King <rmk@arm.linux.org.uk>
+ * Date: Sun, 8 Dec 2002 10:18:38 +0000
+ *
+ * On Sun, Dec 08, 2002 at 02:43:36AM -0500, Pete Zaitcev wrote:
+ * > I boot my 2.5 boxes using "console=ttyS0,9600" argument,
+ * > and I noticed that something is not right with reference
+ * > counting in this case. It seems that when the console
+ * > is open by kernel initially, this is not accounted
+ * > as an open, and uart_startup is not called.
+ *
+ * That is correct.  We are unable to call uart_startup when the serial
+ * console is initialised because it may need to allocate memory (as
+ * request_irq does) and the memory allocators may not have been
+ * initialised.
+ *
+ * 1. initialise the port into a state where it can send characters in the
+ *    console write method.
+ *
+ * 2. don't do the actual hardware shutdown in your shutdown() method (but
+ *    do the normal software shutdown - ie, free irqs etc)
+ *****
+ */
+static void ip22zilog_shutdown(struct uart_port *port)
+{
+	struct uart_ip22zilog_port *up = UART_ZILOG(port);
+	struct zilog_channel *channel;
+	unsigned long flags;
+
+	if (ZS_IS_CONS(up))
+		return;
+
+	spin_lock_irqsave(&port->lock, flags);
+
+	channel = ZILOG_CHANNEL_FROM_PORT(port);
+
+	/* Disable receiver and transmitter.  */
+	up->curregs[R3] &= ~RxENAB;
+	up->curregs[R5] &= ~TxENAB;
+
+	/* Disable all interrupts and BRK assertion.  */
+	up->curregs[R1] &= ~(EXT_INT_ENAB | TxINT_ENAB | RxINT_MASK);
+	up->curregs[R5] &= ~SND_BRK;
+	ip22zilog_maybe_update_regs(up, channel);
+
+	spin_unlock_irqrestore(&port->lock, flags);
+}
+
+/* Shared by TTY driver and serial console setup.  The port lock is held
+ * and local interrupts are disabled.
+ */
+static void
+ip22zilog_convert_to_zs(struct uart_ip22zilog_port *up, unsigned int cflag,
+		       unsigned int iflag, int brg)
+{
+
+	up->curregs[R10] = NRZ;
+	up->curregs[R11] = TCBR | RCBR;
+
+	/* Program BAUD and clock source. */
+	up->curregs[R4] &= ~XCLK_MASK;
+	up->curregs[R4] |= X16CLK;
+	up->curregs[R12] = brg & 0xff;
+	up->curregs[R13] = (brg >> 8) & 0xff;
+	up->curregs[R14] = BRSRC | BRENAB;
+
+	/* Character size, stop bits, and parity. */
+	up->curregs[3] &= ~RxN_MASK;
+	up->curregs[5] &= ~TxN_MASK;
+	switch (cflag & CSIZE) {
+	case CS5:
+		up->curregs[3] |= Rx5;
+		up->curregs[5] |= Tx5;
+		up->parity_mask = 0x1f;
+		break;
+	case CS6:
+		up->curregs[3] |= Rx6;
+		up->curregs[5] |= Tx6;
+		up->parity_mask = 0x3f;
+		break;
+	case CS7:
+		up->curregs[3] |= Rx7;
+		up->curregs[5] |= Tx7;
+		up->parity_mask = 0x7f;
+		break;
+	case CS8:
+	default:
+		up->curregs[3] |= Rx8;
+		up->curregs[5] |= Tx8;
+		up->parity_mask = 0xff;
+		break;
+	};
+	up->curregs[4] &= ~0x0c;
+	if (cflag & CSTOPB)
+		up->curregs[4] |= SB2;
+	else
+		up->curregs[4] |= SB1;
+	if (cflag & PARENB)
+		up->curregs[4] |= PAR_ENAB;
+	else
+		up->curregs[4] &= ~PAR_ENAB;
+	if (!(cflag & PARODD))
+		up->curregs[4] |= PAR_EVEN;
+	else
+		up->curregs[4] &= ~PAR_EVEN;
+
+	up->port.read_status_mask = Rx_OVR;
+	if (iflag & INPCK)
+		up->port.read_status_mask |= CRC_ERR | PAR_ERR;
+	if (iflag & (BRKINT | PARMRK))
+		up->port.read_status_mask |= BRK_ABRT;
+
+	up->port.ignore_status_mask = 0;
+	if (iflag & IGNPAR)
+		up->port.ignore_status_mask |= CRC_ERR | PAR_ERR;
+	if (iflag & IGNBRK) {
+		up->port.ignore_status_mask |= BRK_ABRT;
+		if (iflag & IGNPAR)
+			up->port.ignore_status_mask |= Rx_OVR;
+	}
+
+	if ((cflag & CREAD) == 0)
+		up->port.ignore_status_mask = 0xff;
+}
+
+/* The port lock is not held.  */
+static void
+ip22zilog_set_termios(struct uart_port *port, struct termios *termios,
+		      struct termios *old)
+{
+	struct uart_ip22zilog_port *up = (struct uart_ip22zilog_port *) port;
+	unsigned long flags;
+	int baud, brg;
+
+	baud = uart_get_baud_rate(port, termios, old, 1200, 76800);
+
+	spin_lock_irqsave(&up->port.lock, flags);
+
+	brg = BPS_TO_BRG(baud, ZS_CLOCK / ZS_CLOCK_DIVISOR);
+
+	ip22zilog_convert_to_zs(up, termios->c_cflag, termios->c_iflag, brg);
+
+	if (UART_ENABLE_MS(&up->port, termios->c_cflag))
+		up->flags |= IP22ZILOG_FLAG_MODEM_STATUS;
+	else
+		up->flags &= ~IP22ZILOG_FLAG_MODEM_STATUS;
+
+	up->cflag = termios->c_cflag;
+
+	ip22zilog_maybe_update_regs(up, ZILOG_CHANNEL_FROM_PORT(port));
+
+	spin_unlock_irqrestore(&up->port.lock, flags);
+}
+
+static const char *ip22zilog_type(struct uart_port *port)
+{
+	return "IP22-Zilog";
+}
+
+/* We do not request/release mappings of the registers here, this
+ * happens at early serial probe time.
+ */
+static void ip22zilog_release_port(struct uart_port *port)
+{
+}
+
+static int ip22zilog_request_port(struct uart_port *port)
+{
+	return 0;
+}
+
+/* These do not need to do anything interesting either.  */
+static void ip22zilog_config_port(struct uart_port *port, int flags)
+{
+}
+
+/* We do not support letting the user mess with the divisor, IRQ, etc. */
+static int ip22zilog_verify_port(struct uart_port *port, struct serial_struct *ser)
+{
+	return -EINVAL;
+}
+
+static struct uart_ops ip22zilog_pops = {
+	.tx_empty	=	ip22zilog_tx_empty,
+	.set_mctrl	=	ip22zilog_set_mctrl,
+	.get_mctrl	=	ip22zilog_get_mctrl,
+	.stop_tx	=	ip22zilog_stop_tx,
+	.start_tx	=	ip22zilog_start_tx,
+	.stop_rx	=	ip22zilog_stop_rx,
+	.enable_ms	=	ip22zilog_enable_ms,
+	.break_ctl	=	ip22zilog_break_ctl,
+	.startup	=	ip22zilog_startup,
+	.shutdown	=	ip22zilog_shutdown,
+	.set_termios	=	ip22zilog_set_termios,
+	.type		=	ip22zilog_type,
+	.release_port	=	ip22zilog_release_port,
+	.request_port	=	ip22zilog_request_port,
+	.config_port	=	ip22zilog_config_port,
+	.verify_port	=	ip22zilog_verify_port,
+};
+
+static struct uart_ip22zilog_port *ip22zilog_port_table;
+static struct zilog_layout **ip22zilog_chip_regs;
+
+static struct uart_ip22zilog_port *ip22zilog_irq_chain;
+static int zilog_irq = -1;
+
+static struct uart_driver ip22zilog_reg = {
+	.owner		=	THIS_MODULE,
+	.driver_name	=	"ttyS",
+	.devfs_name	=	"tty/",
+	.major		=	TTY_MAJOR,
+};
+
+static void * __init alloc_one_table(unsigned long size)
+{
+	void *ret;
+
+	ret = kmalloc(size, GFP_KERNEL);
+	if (ret != NULL)
+		memset(ret, 0, size);
+
+	return ret;
+}
+
+static void __init ip22zilog_alloc_tables(void)
+{
+	ip22zilog_port_table = (struct uart_ip22zilog_port *)
+		alloc_one_table(NUM_CHANNELS * sizeof(struct uart_ip22zilog_port));
+	ip22zilog_chip_regs = (struct zilog_layout **)
+		alloc_one_table(NUM_IP22ZILOG * sizeof(struct zilog_layout *));
+
+	if (ip22zilog_port_table == NULL || ip22zilog_chip_regs == NULL) {
+		panic("IP22-Zilog: Cannot allocate IP22-Zilog tables.");
+	}
+}
+
+/* Get the address of the registers for IP22-Zilog instance CHIP.  */
+static struct zilog_layout * __init get_zs(int chip)
+{
+	unsigned long base;
+
+	if (chip < 0 || chip >= NUM_IP22ZILOG) {
+		panic("IP22-Zilog: Illegal chip number %d in get_zs.", chip);
+	}
+
+	/* Not probe-able, hard code it. */
+	base = (unsigned long) &sgioc->serport;
+
+	zilog_irq = SGI_SERIAL_IRQ;
+	request_mem_region(base, 8, "IP22-Zilog");
+
+	return (struct zilog_layout *) base;
+}
+
+#define ZS_PUT_CHAR_MAX_DELAY	2000	/* 10 ms */
+
+#ifdef CONFIG_SERIAL_IP22_ZILOG_CONSOLE
+static void ip22zilog_put_char(struct zilog_channel *channel, unsigned char ch)
+{
+	int loops = ZS_PUT_CHAR_MAX_DELAY;
+
+	/* This is a timed polling loop so do not switch the explicit
+	 * udelay with ZSDELAY as that is a NOP on some platforms.  -DaveM
+	 */
+	do {
+		unsigned char val = readb(&channel->control);
+		if (val & Tx_BUF_EMP) {
+			ZSDELAY();
+			break;
+		}
+		udelay(5);
+	} while (--loops);
+
+	writeb(ch, &channel->data);
+	ZSDELAY();
+	ZS_WSYNC(channel);
+}
+
+static void
+ip22zilog_console_write(struct console *con, const char *s, unsigned int count)
+{
+	struct uart_ip22zilog_port *up = &ip22zilog_port_table[con->index];
+	struct zilog_channel *channel = ZILOG_CHANNEL_FROM_PORT(&up->port);
+	unsigned long flags;
+	int i;
+
+	spin_lock_irqsave(&up->port.lock, flags);
+	for (i = 0; i < count; i++, s++) {
+		ip22zilog_put_char(channel, *s);
+		if (*s == 10)
+			ip22zilog_put_char(channel, 13);
+	}
+	udelay(2);
+	spin_unlock_irqrestore(&up->port.lock, flags);
+}
+
+void
+ip22serial_console_termios(struct console *con, char *options)
+{
+	int baud = 9600, bits = 8, cflag;
+	int parity = 'n';
+	int flow = 'n';
+
+	if (!serial_console)
+		return;
+
+	if (options)
+		uart_parse_options(options, &baud, &parity, &bits, &flow);
+
+	cflag = CREAD | HUPCL | CLOCAL;
+
+	switch (baud) {
+		case 150: cflag |= B150; break;
+		case 300: cflag |= B300; break;
+		case 600: cflag |= B600; break;
+		case 1200: cflag |= B1200; break;
+		case 2400: cflag |= B2400; break;
+		case 4800: cflag |= B4800; break;
+		case 9600: cflag |= B9600; break;
+		case 19200: cflag |= B19200; break;
+		case 38400: cflag |= B38400; break;
+		default: baud = 9600; cflag |= B9600; break;
+	}
+
+	con->cflag = cflag | CS8;			/* 8N1 */
+}
+
+static int __init ip22zilog_console_setup(struct console *con, char *options)
+{
+	struct uart_ip22zilog_port *up = &ip22zilog_port_table[con->index];
+	unsigned long flags;
+	int baud, brg;
+
+	printk("Console: ttyS%d (IP22-Zilog)\n",
+	       (ip22zilog_reg.minor - 64) + con->index);
+
+	/* Get firmware console settings.  */
+	ip22serial_console_termios(con, options);
+
+	/* Firmware console speed is limited to 150-->38400 baud so
+	 * this hackish cflag thing is OK.
+	 */
+	switch (con->cflag & CBAUD) {
+	case B150: baud = 150; break;
+	case B300: baud = 300; break;
+	case B600: baud = 600; break;
+	case B1200: baud = 1200; break;
+	case B2400: baud = 2400; break;
+	case B4800: baud = 4800; break;
+	default: case B9600: baud = 9600; break;
+	case B19200: baud = 19200; break;
+	case B38400: baud = 38400; break;
+	};
+
+	brg = BPS_TO_BRG(baud, ZS_CLOCK / ZS_CLOCK_DIVISOR);
+
+	spin_lock_irqsave(&up->port.lock, flags);
+
+	up->curregs[R15] = BRKIE;
+	ip22zilog_convert_to_zs(up, con->cflag, 0, brg);
+
+	__ip22zilog_startup(up);
+
+	spin_unlock_irqrestore(&up->port.lock, flags);
+
+	return 0;
+}
+
+static struct console ip22zilog_console = {
+	.name	=	"ttyS",
+	.write	=	ip22zilog_console_write,
+	.device	=	uart_console_device,
+	.setup	=	ip22zilog_console_setup,
+	.flags	=	CON_PRINTBUFFER,
+	.index	=	-1,
+	.data	=	&ip22zilog_reg,
+};
+#define IP22ZILOG_CONSOLE	(&ip22zilog_console)
+
+static int __init ip22zilog_console_init(void)
+{
+	int i;
+
+	if (con_is_present())
+		return 0;
+
+	for (i = 0; i < NUM_CHANNELS; i++) {
+		int this_minor = ip22zilog_reg.minor + i;
+
+		if ((this_minor - 64) == (serial_console - 1))
+			break;
+	}
+	if (i == NUM_CHANNELS)
+		return 0;
+
+	ip22zilog_console.index = i;
+	register_console(&ip22zilog_console);
+	return 0;
+}
+#else /* CONFIG_SERIAL_IP22_ZILOG_CONSOLE */
+#define IP22ZILOG_CONSOLE		(NULL)
+#define ip22zilog_console_init()	do { } while (0)
+#endif
+
+static void __init ip22zilog_prepare(void)
+{
+	struct uart_ip22zilog_port *up;
+	struct zilog_layout *rp;
+	int channel, chip;
+
+	/*
+	 * Temporary fix.
+	 */
+	for (channel = 0; channel < NUM_CHANNELS; channel++)
+		spin_lock_init(&ip22zilog_port_table[channel].port.lock);
+
+	ip22zilog_irq_chain = up = &ip22zilog_port_table[0];
+	for (channel = 0; channel < NUM_CHANNELS - 1; channel++)
+		up[channel].next = &up[channel + 1];
+	up[channel].next = NULL;
+
+	for (chip = 0; chip < NUM_IP22ZILOG; chip++) {
+		if (!ip22zilog_chip_regs[chip]) {
+			ip22zilog_chip_regs[chip] = rp = get_zs(chip);
+
+			up[(chip * 2) + 0].port.membase = (char *) &rp->channelA;
+			up[(chip * 2) + 1].port.membase = (char *) &rp->channelB;
+		}
+
+		/* Channel A */
+		up[(chip * 2) + 0].port.iotype = UPIO_MEM;
+		up[(chip * 2) + 0].port.irq = zilog_irq;
+		up[(chip * 2) + 0].port.uartclk = ZS_CLOCK;
+		up[(chip * 2) + 0].port.fifosize = 1;
+		up[(chip * 2) + 0].port.ops = &ip22zilog_pops;
+		up[(chip * 2) + 0].port.type = PORT_IP22ZILOG;
+		up[(chip * 2) + 0].port.flags = 0;
+		up[(chip * 2) + 0].port.line = (chip * 2) + 0;
+		up[(chip * 2) + 0].flags |= IP22ZILOG_FLAG_IS_CHANNEL_A;
+
+		/* Channel B */
+		up[(chip * 2) + 1].port.iotype = UPIO_MEM;
+		up[(chip * 2) + 1].port.irq = zilog_irq;
+		up[(chip * 2) + 1].port.uartclk = ZS_CLOCK;
+		up[(chip * 2) + 1].port.fifosize = 1;
+		up[(chip * 2) + 1].port.ops = &ip22zilog_pops;
+		up[(chip * 2) + 1].port.type = PORT_IP22ZILOG;
+		up[(chip * 2) + 1].port.flags = 0;
+		up[(chip * 2) + 1].port.line = (chip * 2) + 1;
+		up[(chip * 2) + 1].flags |= 0;
+	}
+}
+
+static void __init ip22zilog_init_hw(void)
+{
+	int i;
+
+	for (i = 0; i < NUM_CHANNELS; i++) {
+		struct uart_ip22zilog_port *up = &ip22zilog_port_table[i];
+		struct zilog_channel *channel = ZILOG_CHANNEL_FROM_PORT(&up->port);
+		unsigned long flags;
+		int baud, brg;
+
+		spin_lock_irqsave(&up->port.lock, flags);
+
+		if (ZS_IS_CHANNEL_A(up)) {
+			write_zsreg(channel, R9, FHWRES);
+			ZSDELAY_LONG();
+			(void) read_zsreg(channel, R0);
+		}
+
+		/* Normal serial TTY. */
+		up->parity_mask = 0xff;
+		up->curregs[R1] = EXT_INT_ENAB | INT_ALL_Rx | TxINT_ENAB;
+		up->curregs[R4] = PAR_EVEN | X16CLK | SB1;
+		up->curregs[R3] = RxENAB | Rx8;
+		up->curregs[R5] = TxENAB | Tx8;
+		up->curregs[R9] = NV | MIE;
+		up->curregs[R10] = NRZ;
+		up->curregs[R11] = TCBR | RCBR;
+		baud = 9600;
+		brg = BPS_TO_BRG(baud, ZS_CLOCK / ZS_CLOCK_DIVISOR);
+		up->curregs[R12] = (brg & 0xff);
+		up->curregs[R13] = (brg >> 8) & 0xff;
+		up->curregs[R14] = BRSRC | BRENAB;
+		__load_zsregs(channel, up->curregs);
+
+		spin_unlock_irqrestore(&up->port.lock, flags);
+	}
+}
+
+static int __init ip22zilog_ports_init(void)
+{
+	int ret;
+
+	printk(KERN_INFO "Serial: IP22 Zilog driver (%d chips).\n", NUM_IP22ZILOG);
+
+	ip22zilog_prepare();
+
+	if (request_irq(zilog_irq, ip22zilog_interrupt, 0,
+			"IP22-Zilog", ip22zilog_irq_chain)) {
+		panic("IP22-Zilog: Unable to register zs interrupt handler.\n");
+	}
+
+	ip22zilog_init_hw();
+
+	/* We can only init this once we have probed the Zilogs
+	 * in the system.
+	 */
+	ip22zilog_reg.nr = NUM_CHANNELS;
+	ip22zilog_reg.cons = IP22ZILOG_CONSOLE;
+
+	ip22zilog_reg.minor = ip22serial_current_minor;
+	ip22serial_current_minor += NUM_CHANNELS;
+
+	ret = uart_register_driver(&ip22zilog_reg);
+	if (ret == 0) {
+		int i;
+
+		for (i = 0; i < NUM_CHANNELS; i++) {
+			struct uart_ip22zilog_port *up = &ip22zilog_port_table[i];
+
+			uart_add_one_port(&ip22zilog_reg, &up->port);
+		}
+	}
+
+	return ret;
+}
+
+static int __init ip22zilog_init(void)
+{
+	/* IP22 Zilog setup is hard coded, no probing to do.  */
+
+	ip22zilog_alloc_tables();
+
+	ip22zilog_ports_init();
+	ip22zilog_console_init();
+
+	return 0;
+}
+
+static void __exit ip22zilog_exit(void)
+{
+	int i;
+
+	for (i = 0; i < NUM_CHANNELS; i++) {
+		struct uart_ip22zilog_port *up = &ip22zilog_port_table[i];
+
+		uart_remove_one_port(&ip22zilog_reg, &up->port);
+	}
+
+	uart_unregister_driver(&ip22zilog_reg);
+}
+
+module_init(ip22zilog_init);
+module_exit(ip22zilog_exit);
+
+/* David wrote it but I'm to blame for the bugs ...  */
+MODULE_AUTHOR("Ralf Baechle <ralf@linux-mips.org>");
+MODULE_DESCRIPTION("SGI Zilog serial port driver");
+MODULE_LICENSE("GPL");
--- diff/drivers/serial/ip22zilog.h	1970-01-01 01:00:00.000000000 +0100
+++ source/drivers/serial/ip22zilog.h	2004-02-23 13:56:45.000000000 +0000
@@ -0,0 +1,281 @@
+#ifndef _IP22_ZILOG_H
+#define _IP22_ZILOG_H
+
+#include <asm/byteorder.h>
+
+struct zilog_channel {
+#ifdef __BIG_ENDIAN
+	volatile unsigned char unused0[3];
+	volatile unsigned char control;
+	volatile unsigned char unused1[3];
+	volatile unsigned char data;
+#else /* __LITTLE_ENDIAN */
+	volatile unsigned char control;
+	volatile unsigned char unused0[3];
+	volatile unsigned char data;
+	volatile unsigned char unused1[3];
+#endif
+};
+
+struct zilog_layout {
+	struct zilog_channel channelB;
+	struct zilog_channel channelA;
+};
+
+#define NUM_ZSREGS    16
+
+/* Conversion routines to/from brg time constants from/to bits
+ * per second.
+ */
+#define BRG_TO_BPS(brg, freq) ((freq) / 2 / ((brg) + 2))
+#define BPS_TO_BRG(bps, freq) ((((freq) + (bps)) / (2 * (bps))) - 2)
+
+/* The Zilog register set */
+
+#define	FLAG	0x7e
+
+/* Write Register 0 */
+#define	R0	0		/* Register selects */
+#define	R1	1
+#define	R2	2
+#define	R3	3
+#define	R4	4
+#define	R5	5
+#define	R6	6
+#define	R7	7
+#define	R8	8
+#define	R9	9
+#define	R10	10
+#define	R11	11
+#define	R12	12
+#define	R13	13
+#define	R14	14
+#define	R15	15
+
+#define	NULLCODE	0	/* Null Code */
+#define	POINT_HIGH	0x8	/* Select upper half of registers */
+#define	RES_EXT_INT	0x10	/* Reset Ext. Status Interrupts */
+#define	SEND_ABORT	0x18	/* HDLC Abort */
+#define	RES_RxINT_FC	0x20	/* Reset RxINT on First Character */
+#define	RES_Tx_P	0x28	/* Reset TxINT Pending */
+#define	ERR_RES		0x30	/* Error Reset */
+#define	RES_H_IUS	0x38	/* Reset highest IUS */
+
+#define	RES_Rx_CRC	0x40	/* Reset Rx CRC Checker */
+#define	RES_Tx_CRC	0x80	/* Reset Tx CRC Checker */
+#define	RES_EOM_L	0xC0	/* Reset EOM latch */
+
+/* Write Register 1 */
+
+#define	EXT_INT_ENAB	0x1	/* Ext Int Enable */
+#define	TxINT_ENAB	0x2	/* Tx Int Enable */
+#define	PAR_SPEC	0x4	/* Parity is special condition */
+
+#define	RxINT_DISAB	0	/* Rx Int Disable */
+#define	RxINT_FCERR	0x8	/* Rx Int on First Character Only or Error */
+#define	INT_ALL_Rx	0x10	/* Int on all Rx Characters or error */
+#define	INT_ERR_Rx	0x18	/* Int on error only */
+#define RxINT_MASK	0x18
+
+#define	WT_RDY_RT	0x20	/* Wait/Ready on R/T */
+#define	WT_FN_RDYFN	0x40	/* Wait/FN/Ready FN */
+#define	WT_RDY_ENAB	0x80	/* Wait/Ready Enable */
+
+/* Write Register #2 (Interrupt Vector) */
+
+/* Write Register 3 */
+
+#define	RxENAB  	0x1	/* Rx Enable */
+#define	SYNC_L_INH	0x2	/* Sync Character Load Inhibit */
+#define	ADD_SM		0x4	/* Address Search Mode (SDLC) */
+#define	RxCRC_ENAB	0x8	/* Rx CRC Enable */
+#define	ENT_HM		0x10	/* Enter Hunt Mode */
+#define	AUTO_ENAB	0x20	/* Auto Enables */
+#define	Rx5		0x0	/* Rx 5 Bits/Character */
+#define	Rx7		0x40	/* Rx 7 Bits/Character */
+#define	Rx6		0x80	/* Rx 6 Bits/Character */
+#define	Rx8		0xc0	/* Rx 8 Bits/Character */
+#define RxN_MASK	0xc0
+
+/* Write Register 4 */
+
+#define	PAR_ENAB	0x1	/* Parity Enable */
+#define	PAR_EVEN	0x2	/* Parity Even/Odd* */
+
+#define	SYNC_ENAB	0	/* Sync Modes Enable */
+#define	SB1		0x4	/* 1 stop bit/char */
+#define	SB15		0x8	/* 1.5 stop bits/char */
+#define	SB2		0xc	/* 2 stop bits/char */
+
+#define	MONSYNC		0	/* 8 Bit Sync character */
+#define	BISYNC		0x10	/* 16 bit sync character */
+#define	SDLC		0x20	/* SDLC Mode (01111110 Sync Flag) */
+#define	EXTSYNC		0x30	/* External Sync Mode */
+
+#define	X1CLK		0x0	/* x1 clock mode */
+#define	X16CLK		0x40	/* x16 clock mode */
+#define	X32CLK		0x80	/* x32 clock mode */
+#define	X64CLK		0xC0	/* x64 clock mode */
+#define XCLK_MASK	0xC0
+
+/* Write Register 5 */
+
+#define	TxCRC_ENAB	0x1	/* Tx CRC Enable */
+#define	RTS		0x2	/* RTS */
+#define	SDLC_CRC	0x4	/* SDLC/CRC-16 */
+#define	TxENAB		0x8	/* Tx Enable */
+#define	SND_BRK		0x10	/* Send Break */
+#define	Tx5		0x0	/* Tx 5 bits (or less)/character */
+#define	Tx7		0x20	/* Tx 7 bits/character */
+#define	Tx6		0x40	/* Tx 6 bits/character */
+#define	Tx8		0x60	/* Tx 8 bits/character */
+#define TxN_MASK	0x60
+#define	DTR		0x80	/* DTR */
+
+/* Write Register 6 (Sync bits 0-7/SDLC Address Field) */
+
+/* Write Register 7 (Sync bits 8-15/SDLC 01111110) */
+
+/* Write Register 8 (transmit buffer) */
+
+/* Write Register 9 (Master interrupt control) */
+#define	VIS	1	/* Vector Includes Status */
+#define	NV	2	/* No Vector */
+#define	DLC	4	/* Disable Lower Chain */
+#define	MIE	8	/* Master Interrupt Enable */
+#define	STATHI	0x10	/* Status high */
+#define	NORESET	0	/* No reset on write to R9 */
+#define	CHRB	0x40	/* Reset channel B */
+#define	CHRA	0x80	/* Reset channel A */
+#define	FHWRES	0xc0	/* Force hardware reset */
+
+/* Write Register 10 (misc control bits) */
+#define	BIT6	1	/* 6 bit/8bit sync */
+#define	LOOPMODE 2	/* SDLC Loop mode */
+#define	ABUNDER	4	/* Abort/flag on SDLC xmit underrun */
+#define	MARKIDLE 8	/* Mark/flag on idle */
+#define	GAOP	0x10	/* Go active on poll */
+#define	NRZ	0	/* NRZ mode */
+#define	NRZI	0x20	/* NRZI mode */
+#define	FM1	0x40	/* FM1 (transition = 1) */
+#define	FM0	0x60	/* FM0 (transition = 0) */
+#define	CRCPS	0x80	/* CRC Preset I/O */
+
+/* Write Register 11 (Clock Mode control) */
+#define	TRxCXT	0	/* TRxC = Xtal output */
+#define	TRxCTC	1	/* TRxC = Transmit clock */
+#define	TRxCBR	2	/* TRxC = BR Generator Output */
+#define	TRxCDP	3	/* TRxC = DPLL output */
+#define	TRxCOI	4	/* TRxC O/I */
+#define	TCRTxCP	0	/* Transmit clock = RTxC pin */
+#define	TCTRxCP	8	/* Transmit clock = TRxC pin */
+#define	TCBR	0x10	/* Transmit clock = BR Generator output */
+#define	TCDPLL	0x18	/* Transmit clock = DPLL output */
+#define	RCRTxCP	0	/* Receive clock = RTxC pin */
+#define	RCTRxCP	0x20	/* Receive clock = TRxC pin */
+#define	RCBR	0x40	/* Receive clock = BR Generator output */
+#define	RCDPLL	0x60	/* Receive clock = DPLL output */
+#define	RTxCX	0x80	/* RTxC Xtal/No Xtal */
+
+/* Write Register 12 (lower byte of baud rate generator time constant) */
+
+/* Write Register 13 (upper byte of baud rate generator time constant) */
+
+/* Write Register 14 (Misc control bits) */
+#define	BRENAB 	1	/* Baud rate generator enable */
+#define	BRSRC	2	/* Baud rate generator source */
+#define	DTRREQ	4	/* DTR/Request function */
+#define	AUTOECHO 8	/* Auto Echo */
+#define	LOOPBAK	0x10	/* Local loopback */
+#define	SEARCH	0x20	/* Enter search mode */
+#define	RMC	0x40	/* Reset missing clock */
+#define	DISDPLL	0x60	/* Disable DPLL */
+#define	SSBR	0x80	/* Set DPLL source = BR generator */
+#define	SSRTxC	0xa0	/* Set DPLL source = RTxC */
+#define	SFMM	0xc0	/* Set FM mode */
+#define	SNRZI	0xe0	/* Set NRZI mode */
+
+/* Write Register 15 (external/status interrupt control) */
+#define	ZCIE	2	/* Zero count IE */
+#define	DCDIE	8	/* DCD IE */
+#define	SYNCIE	0x10	/* Sync/hunt IE */
+#define	CTSIE	0x20	/* CTS IE */
+#define	TxUIE	0x40	/* Tx Underrun/EOM IE */
+#define	BRKIE	0x80	/* Break/Abort IE */
+
+
+/* Read Register 0 */
+#define	Rx_CH_AV	0x1	/* Rx Character Available */
+#define	ZCOUNT		0x2	/* Zero count */
+#define	Tx_BUF_EMP	0x4	/* Tx Buffer empty */
+#define	DCD		0x8	/* DCD */
+#define	SYNC		0x10	/* Sync/hunt */
+#define	CTS		0x20	/* CTS */
+#define	TxEOM		0x40	/* Tx underrun */
+#define	BRK_ABRT	0x80	/* Break/Abort */
+
+/* Read Register 1 */
+#define	ALL_SNT		0x1	/* All sent */
+/* Residue Data for 8 Rx bits/char programmed */
+#define	RES3		0x8	/* 0/3 */
+#define	RES4		0x4	/* 0/4 */
+#define	RES5		0xc	/* 0/5 */
+#define	RES6		0x2	/* 0/6 */
+#define	RES7		0xa	/* 0/7 */
+#define	RES8		0x6	/* 0/8 */
+#define	RES18		0xe	/* 1/8 */
+#define	RES28		0x0	/* 2/8 */
+/* Special Rx Condition Interrupts */
+#define	PAR_ERR		0x10	/* Parity error */
+#define	Rx_OVR		0x20	/* Rx Overrun Error */
+#define	CRC_ERR		0x40	/* CRC/Framing Error */
+#define	END_FR		0x80	/* End of Frame (SDLC) */
+
+/* Read Register 2 (channel b only) - Interrupt vector */
+#define CHB_Tx_EMPTY	0x00
+#define CHB_EXT_STAT	0x02
+#define CHB_Rx_AVAIL	0x04
+#define CHB_SPECIAL	0x06
+#define CHA_Tx_EMPTY	0x08
+#define CHA_EXT_STAT	0x0a
+#define CHA_Rx_AVAIL	0x0c
+#define CHA_SPECIAL	0x0e
+#define STATUS_MASK	0x0e
+
+/* Read Register 3 (interrupt pending register) ch a only */
+#define	CHBEXT	0x1		/* Channel B Ext/Stat IP */
+#define	CHBTxIP	0x2		/* Channel B Tx IP */
+#define	CHBRxIP	0x4		/* Channel B Rx IP */
+#define	CHAEXT	0x8		/* Channel A Ext/Stat IP */
+#define	CHATxIP	0x10		/* Channel A Tx IP */
+#define	CHARxIP	0x20		/* Channel A Rx IP */
+
+/* Read Register 8 (receive data register) */
+
+/* Read Register 10  (misc status bits) */
+#define	ONLOOP	2		/* On loop */
+#define	LOOPSEND 0x10		/* Loop sending */
+#define	CLK2MIS	0x40		/* Two clocks missing */
+#define	CLK1MIS	0x80		/* One clock missing */
+
+/* Read Register 12 (lower byte of baud rate generator constant) */
+
+/* Read Register 13 (upper byte of baud rate generator constant) */
+
+/* Read Register 15 (value of WR 15) */
+
+/* Misc macros */
+#define ZS_CLEARERR(channel)    do { writeb(ERR_RES, &channel->control); \
+				     udelay(5); } while(0)
+
+#define ZS_CLEARSTAT(channel)   do { writeb(RES_EXT_INT, &channel->control); \
+				     udelay(5); } while(0)
+
+#define ZS_CLEARFIFO(channel)   do { readb(&channel->data); \
+				     udelay(2); \
+				     readb(&channel->data); \
+				     udelay(2); \
+				     readb(&channel->data); \
+				     udelay(2); } while(0)
+
+#endif /* _IP22_ZILOG_H */
--- diff/drivers/serial/pxa.c	1970-01-01 01:00:00.000000000 +0100
+++ source/drivers/serial/pxa.c	2004-02-23 13:56:45.000000000 +0000
@@ -0,0 +1,840 @@
+/*
+ *  linux/drivers/serial/pxa.c
+ *
+ *  Based on drivers/serial/8250.c by Russell King.
+ *
+ *  Author:	Nicolas Pitre
+ *  Created:	Feb 20, 2003
+ *  Copyright:	(C) 2003 Monta Vista Software, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Note 1: This driver is made separate from the already too overloaded
+ * 8250.c because it needs some kirks of its own and that'll make it
+ * easier to add DMA support.
+ *
+ * Note 2: I'm too sick of device allocation policies for serial ports.
+ * If someone else wants to request an "official" allocation of major/minor
+ * for this driver please be my guest.  And don't forget that new hardware
+ * to come from Intel might have more than 3 or 4 of those UARTs.  Let's
+ * hope for a better port registration and dynamic device allocation scheme
+ * with the serial core maintainer satisfaction to appear soon.
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/tty.h>
+#include <linux/ioport.h>
+#include <linux/init.h>
+#include <linux/console.h>
+#include <linux/sysrq.h>
+#include <linux/serial_reg.h>
+#include <linux/circ_buf.h>
+#include <linux/serial.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+
+#include <asm/io.h>
+#include <asm/hardware.h>
+#include <asm/irq.h>
+
+#if defined(CONFIG_SERIAL_PXA_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
+#define SUPPORT_SYSRQ
+#endif
+
+#include <linux/serial_core.h>
+
+
+struct uart_pxa_port {
+	struct uart_port        port;
+	unsigned char           ier;
+	unsigned char           lcr;
+	unsigned char           mcr;
+	unsigned int            lsr_break_flag;
+	unsigned int		cken;
+	char			*name;
+};
+
+static inline unsigned int serial_in(struct uart_pxa_port *up, int offset)
+{
+	offset <<= 2;
+	return readl(up->port.membase + offset);
+}
+
+static inline void serial_out(struct uart_pxa_port *up, int offset, int value)
+{
+	offset <<= 2;
+	writel(value, up->port.membase + offset);
+}
+
+static void serial_pxa_enable_ms(struct uart_port *port)
+{
+	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
+
+	up->ier |= UART_IER_MSI;
+	serial_out(up, UART_IER, up->ier);
+}
+
+static void serial_pxa_stop_tx(struct uart_port *port, unsigned int tty_stop)
+{
+	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
+
+	if (up->ier & UART_IER_THRI) {
+		up->ier &= ~UART_IER_THRI;
+		serial_out(up, UART_IER, up->ier);
+	}
+}
+
+static void serial_pxa_stop_rx(struct uart_port *port)
+{
+	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
+
+	up->ier &= ~UART_IER_RLSI;
+	up->port.read_status_mask &= ~UART_LSR_DR;
+	serial_out(up, UART_IER, up->ier);
+}
+
+static inline void
+receive_chars(struct uart_pxa_port *up, int *status, struct pt_regs *regs)
+{
+	struct tty_struct *tty = up->port.info->tty;
+	unsigned char ch;
+	int max_count = 256;
+
+	do {
+		if (unlikely(tty->flip.count >= TTY_FLIPBUF_SIZE)) {
+			/*
+			 * FIXME: Deadlock can happen here if we're a
+			 * low-latency port.  We're holding the per-port
+			 * spinlock, and we call flush_to_ldisc->
+			 * n_tty_receive_buf->n_tty_receive_char->
+			 * opost->uart_put_char.
+			 */
+			tty->flip.work.func((void *)tty);
+			if (tty->flip.count >= TTY_FLIPBUF_SIZE)
+				return; // if TTY_DONT_FLIP is set
+		}
+		ch = serial_in(up, UART_RX);
+		*tty->flip.char_buf_ptr = ch;
+		*tty->flip.flag_buf_ptr = TTY_NORMAL;
+		up->port.icount.rx++;
+
+		if (unlikely(*status & (UART_LSR_BI | UART_LSR_PE |
+				       UART_LSR_FE | UART_LSR_OE))) {
+			/*
+			 * For statistics only
+			 */
+			if (*status & UART_LSR_BI) {
+				*status &= ~(UART_LSR_FE | UART_LSR_PE);
+				up->port.icount.brk++;
+				/*
+				 * We do the SysRQ and SAK checking
+				 * here because otherwise the break
+				 * may get masked by ignore_status_mask
+				 * or read_status_mask.
+				 */
+				if (uart_handle_break(&up->port))
+					goto ignore_char;
+			} else if (*status & UART_LSR_PE)
+				up->port.icount.parity++;
+			else if (*status & UART_LSR_FE)
+				up->port.icount.frame++;
+			if (*status & UART_LSR_OE)
+				up->port.icount.overrun++;
+
+			/*
+			 * Mask off conditions which should be ignored.
+			 */
+			*status &= up->port.read_status_mask;
+
+#ifdef CONFIG_SERIAL_PXA_CONSOLE
+			if (up->port.line == up->port.cons->index) {
+				/* Recover the break flag from console xmit */
+				*status |= up->lsr_break_flag;
+				up->lsr_break_flag = 0;
+			}
+#endif
+			if (*status & UART_LSR_BI) {
+				*tty->flip.flag_buf_ptr = TTY_BREAK;
+			} else if (*status & UART_LSR_PE)
+				*tty->flip.flag_buf_ptr = TTY_PARITY;
+			else if (*status & UART_LSR_FE)
+				*tty->flip.flag_buf_ptr = TTY_FRAME;
+		}
+		if (uart_handle_sysrq_char(&up->port, ch, regs))
+			goto ignore_char;
+		if ((*status & up->port.ignore_status_mask) == 0) {
+			tty->flip.flag_buf_ptr++;
+			tty->flip.char_buf_ptr++;
+			tty->flip.count++;
+		}
+		if ((*status & UART_LSR_OE) &&
+		    tty->flip.count < TTY_FLIPBUF_SIZE) {
+			/*
+			 * Overrun is special, since it's reported
+			 * immediately, and doesn't affect the current
+			 * character.
+			 */
+			*tty->flip.flag_buf_ptr = TTY_OVERRUN;
+			tty->flip.flag_buf_ptr++;
+			tty->flip.char_buf_ptr++;
+			tty->flip.count++;
+		}
+	ignore_char:
+		*status = serial_in(up, UART_LSR);
+	} while ((*status & UART_LSR_DR) && (max_count-- > 0));
+	tty_flip_buffer_push(tty);
+}
+
+static void transmit_chars(struct uart_pxa_port *up)
+{
+	struct circ_buf *xmit = &up->port.info->xmit;
+	int count;
+
+	if (up->port.x_char) {
+		serial_out(up, UART_TX, up->port.x_char);
+		up->port.icount.tx++;
+		up->port.x_char = 0;
+		return;
+	}
+	if (uart_circ_empty(xmit) || uart_tx_stopped(&up->port)) {
+		serial_pxa_stop_tx(&up->port, 0);
+		return;
+	}
+
+	count = up->port.fifosize / 2;
+	do {
+		serial_out(up, UART_TX, xmit->buf[xmit->tail]);
+		xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
+		up->port.icount.tx++;
+		if (uart_circ_empty(xmit))
+			break;
+	} while (--count > 0);
+
+	if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
+		uart_write_wakeup(&up->port);
+
+
+	if (uart_circ_empty(xmit))
+		serial_pxa_stop_tx(&up->port, 0);
+}
+
+static void serial_pxa_start_tx(struct uart_port *port, unsigned int tty_start)
+{
+	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
+
+	if (!(up->ier & UART_IER_THRI)) {
+		up->ier |= UART_IER_THRI;
+		serial_out(up, UART_IER, up->ier);
+	}
+}
+
+static inline void check_modem_status(struct uart_pxa_port *up)
+{
+	int status;
+
+	status = serial_in(up, UART_MSR);
+
+	if ((status & UART_MSR_ANY_DELTA) == 0)
+		return;
+
+	if (status & UART_MSR_TERI)
+		up->port.icount.rng++;
+	if (status & UART_MSR_DDSR)
+		up->port.icount.dsr++;
+	if (status & UART_MSR_DDCD)
+		uart_handle_dcd_change(&up->port, status & UART_MSR_DCD);
+	if (status & UART_MSR_DCTS)
+		uart_handle_cts_change(&up->port, status & UART_MSR_CTS);
+
+	wake_up_interruptible(&up->port.info->delta_msr_wait);
+}
+
+/*
+ * This handles the interrupt from one port.
+ */
+static inline irqreturn_t
+serial_pxa_irq(int irq, void *dev_id, struct pt_regs *regs)
+{
+	struct uart_pxa_port *up = (struct uart_pxa_port *)dev_id;
+	unsigned int iir, lsr;
+
+	iir = serial_in(up, UART_IIR);
+	if (iir & UART_IIR_NO_INT)
+		return IRQ_NONE;
+	lsr = serial_in(up, UART_LSR);
+	if (lsr & UART_LSR_DR)
+		receive_chars(up, &lsr, regs);
+	check_modem_status(up);
+	if (lsr & UART_LSR_THRE)
+		transmit_chars(up);
+	return IRQ_HANDLED;
+}
+
+static unsigned int serial_pxa_tx_empty(struct uart_port *port)
+{
+	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
+	unsigned long flags;
+	unsigned int ret;
+
+	spin_lock_irqsave(&up->port.lock, flags);
+	ret = serial_in(up, UART_LSR) & UART_LSR_TEMT ? TIOCSER_TEMT : 0;
+	spin_unlock_irqrestore(&up->port.lock, flags);
+
+	return ret;
+}
+
+static unsigned int serial_pxa_get_mctrl(struct uart_port *port)
+{
+	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
+	unsigned long flags;
+	unsigned char status;
+	unsigned int ret;
+
+return TIOCM_CTS | TIOCM_DSR | TIOCM_CAR;
+	spin_lock_irqsave(&up->port.lock, flags);
+	status = serial_in(up, UART_MSR);
+	spin_unlock_irqrestore(&up->port.lock, flags);
+
+	ret = 0;
+	if (status & UART_MSR_DCD)
+		ret |= TIOCM_CAR;
+	if (status & UART_MSR_RI)
+		ret |= TIOCM_RNG;
+	if (status & UART_MSR_DSR)
+		ret |= TIOCM_DSR;
+	if (status & UART_MSR_CTS)
+		ret |= TIOCM_CTS;
+	return ret;
+}
+
+static void serial_pxa_set_mctrl(struct uart_port *port, unsigned int mctrl)
+{
+	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
+	unsigned char mcr = 0;
+
+	if (mctrl & TIOCM_RTS)
+		mcr |= UART_MCR_RTS;
+	if (mctrl & TIOCM_DTR)
+		mcr |= UART_MCR_DTR;
+	if (mctrl & TIOCM_OUT1)
+		mcr |= UART_MCR_OUT1;
+	if (mctrl & TIOCM_OUT2)
+		mcr |= UART_MCR_OUT2;
+	if (mctrl & TIOCM_LOOP)
+		mcr |= UART_MCR_LOOP;
+
+	mcr |= up->mcr;
+
+	serial_out(up, UART_MCR, mcr);
+}
+
+static void serial_pxa_break_ctl(struct uart_port *port, int break_state)
+{
+	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
+	unsigned long flags;
+
+	spin_lock_irqsave(&up->port.lock, flags);
+	if (break_state == -1)
+		up->lcr |= UART_LCR_SBC;
+	else
+		up->lcr &= ~UART_LCR_SBC;
+	serial_out(up, UART_LCR, up->lcr);
+	spin_unlock_irqrestore(&up->port.lock, flags);
+}
+
+#if 0
+static void serial_pxa_dma_init(struct pxa_uart *up)
+{
+	up->rxdma =
+		pxa_request_dma(up->name, DMA_PRIO_LOW, pxa_receive_dma, up);
+	if (up->rxdma < 0)
+		goto out;
+	up->txdma =
+		pxa_request_dma(up->name, DMA_PRIO_LOW, pxa_transmit_dma, up);
+	if (up->txdma < 0)
+		goto err_txdma;
+	up->dmadesc = kmalloc(4 * sizeof(pxa_dma_desc), GFP_KERNEL);
+	if (!up->dmadesc)
+		goto err_alloc;
+
+	/* ... */
+err_alloc:
+	pxa_free_dma(up->txdma);
+err_rxdma:
+	pxa_free_dma(up->rxdma);
+out:
+	return;
+}
+#endif
+
+static int serial_pxa_startup(struct uart_port *port)
+{
+	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
+	unsigned long flags;
+	int retval;
+
+	up->mcr = 0;
+
+	/*
+	 * Allocate the IRQ
+	 */
+	retval = request_irq(up->port.irq, serial_pxa_irq, 0, up->name, up);
+	if (retval)
+		return retval;
+
+	CKEN |= up->cken;
+	udelay(1);
+
+	/*
+	 * Clear the FIFO buffers and disable them.
+	 * (they will be reenabled in set_termios())
+	 */
+	serial_out(up, UART_FCR, UART_FCR_ENABLE_FIFO);
+	serial_out(up, UART_FCR, UART_FCR_ENABLE_FIFO |
+			UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT);
+	serial_out(up, UART_FCR, 0);
+
+	/*
+	 * Clear the interrupt registers.
+	 */
+	(void) serial_in(up, UART_LSR);
+	(void) serial_in(up, UART_RX);
+	(void) serial_in(up, UART_IIR);
+	(void) serial_in(up, UART_MSR);
+
+	/*
+	 * Now, initialize the UART
+	 */
+	serial_out(up, UART_LCR, UART_LCR_WLEN8);
+
+	spin_lock_irqsave(&up->port.lock, flags);
+	up->port.mctrl |= TIOCM_OUT2;
+	serial_pxa_set_mctrl(&up->port, up->port.mctrl);
+	spin_unlock_irqrestore(&up->port.lock, flags);
+
+	/*
+	 * Finally, enable interrupts.  Note: Modem status interrupts
+	 * are set via set_termios(), which will be occuring imminently
+	 * anyway, so we don't enable them here.
+	 */
+	up->ier = UART_IER_RLSI | UART_IER_RDI | UART_IER_RTOIE | UART_IER_UUE;
+	serial_out(up, UART_IER, up->ier);
+
+	/*
+	 * And clear the interrupt registers again for luck.
+	 */
+	(void) serial_in(up, UART_LSR);
+	(void) serial_in(up, UART_RX);
+	(void) serial_in(up, UART_IIR);
+	(void) serial_in(up, UART_MSR);
+
+	return 0;
+}
+
+static void serial_pxa_shutdown(struct uart_port *port)
+{
+	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
+	unsigned long flags;
+
+	free_irq(up->port.irq, up);
+
+	/*
+	 * Disable interrupts from this port
+	 */
+	up->ier = 0;
+	serial_out(up, UART_IER, 0);
+
+	spin_lock_irqsave(&up->port.lock, flags);
+	up->port.mctrl &= ~TIOCM_OUT2;
+	serial_pxa_set_mctrl(&up->port, up->port.mctrl);
+	spin_unlock_irqrestore(&up->port.lock, flags);
+
+	/*
+	 * Disable break condition and FIFOs
+	 */
+	serial_out(up, UART_LCR, serial_in(up, UART_LCR) & ~UART_LCR_SBC);
+	serial_out(up, UART_FCR, UART_FCR_ENABLE_FIFO |
+				  UART_FCR_CLEAR_RCVR |
+				  UART_FCR_CLEAR_XMIT);
+	serial_out(up, UART_FCR, 0);
+
+	CKEN &= ~up->cken;
+}
+
+static void
+serial_pxa_set_termios(struct uart_port *port, struct termios *termios,
+		       struct termios *old)
+{
+	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
+	unsigned char cval, fcr = 0;
+	unsigned long flags;
+	unsigned int baud, quot;
+
+	switch (termios->c_cflag & CSIZE) {
+	case CS5:
+		cval = 0x00;
+		break;
+	case CS6:
+		cval = 0x01;
+		break;
+	case CS7:
+		cval = 0x02;
+		break;
+	default:
+	case CS8:
+		cval = 0x03;
+		break;
+	}
+
+	if (termios->c_cflag & CSTOPB)
+		cval |= 0x04;
+	if (termios->c_cflag & PARENB)
+		cval |= UART_LCR_PARITY;
+	if (!(termios->c_cflag & PARODD))
+		cval |= UART_LCR_EPAR;
+
+	/*
+	 * Ask the core to calculate the divisor for us.
+	 */
+	baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/16);
+	quot = uart_get_divisor(port, baud);
+
+	if ((up->port.uartclk / quot) < (2400 * 16))
+		fcr = UART_FCR_ENABLE_FIFO | UART_FCR_PXAR1;
+	else
+		fcr = UART_FCR_ENABLE_FIFO | UART_FCR_PXAR8;
+
+	/*
+	 * Ok, we're now changing the port state.  Do it with
+	 * interrupts disabled.
+	 */
+	spin_lock_irqsave(&up->port.lock, flags);
+
+	/*
+	 * Ensure the port will be enabled.
+	 * This is required especially for serial console.
+	 */
+	up->ier |= IER_UUE;
+
+	/*
+	 * Update the per-port timeout.
+	 */
+	uart_update_timeout(port, termios->c_cflag, quot);
+
+	up->port.read_status_mask = UART_LSR_OE | UART_LSR_THRE | UART_LSR_DR;
+	if (termios->c_iflag & INPCK)
+		up->port.read_status_mask |= UART_LSR_FE | UART_LSR_PE;
+	if (termios->c_iflag & (BRKINT | PARMRK))
+		up->port.read_status_mask |= UART_LSR_BI;
+
+	/*
+	 * Characters to ignore
+	 */
+	up->port.ignore_status_mask = 0;
+	if (termios->c_iflag & IGNPAR)
+		up->port.ignore_status_mask |= UART_LSR_PE | UART_LSR_FE;
+	if (termios->c_iflag & IGNBRK) {
+		up->port.ignore_status_mask |= UART_LSR_BI;
+		/*
+		 * If we're ignoring parity and break indicators,
+		 * ignore overruns too (for real raw support).
+		 */
+		if (termios->c_iflag & IGNPAR)
+			up->port.ignore_status_mask |= UART_LSR_OE;
+	}
+
+	/*
+	 * ignore all characters if CREAD is not set
+	 */
+	if ((termios->c_cflag & CREAD) == 0)
+		up->port.ignore_status_mask |= UART_LSR_DR;
+
+	/*
+	 * CTS flow control flag and modem status interrupts
+	 */
+	up->ier &= ~UART_IER_MSI;
+	if (UART_ENABLE_MS(&up->port, termios->c_cflag))
+		up->ier |= UART_IER_MSI;
+
+	serial_out(up, UART_IER, up->ier);
+
+	serial_out(up, UART_LCR, cval | UART_LCR_DLAB);/* set DLAB */
+	serial_out(up, UART_DLL, quot & 0xff);		/* LS of divisor */
+	serial_out(up, UART_DLM, quot >> 8);		/* MS of divisor */
+	serial_out(up, UART_LCR, cval);		/* reset DLAB */
+	up->lcr = cval;					/* Save LCR */
+	serial_pxa_set_mctrl(&up->port, up->port.mctrl);
+	serial_out(up, UART_FCR, fcr);
+	spin_unlock_irqrestore(&up->port.lock, flags);
+}
+
+static void
+serial_pxa_pm(struct uart_port *port, unsigned int state,
+	      unsigned int oldstate)
+{
+	if (state) {
+		/* sleep */
+	} else {
+		/* wake */
+	}
+}
+
+static void serial_pxa_release_port(struct uart_port *port)
+{
+}
+
+static int serial_pxa_request_port(struct uart_port *port)
+{
+	return 0;
+}
+
+static void serial_pxa_config_port(struct uart_port *port, int flags)
+{
+	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
+	up->port.type = PORT_PXA;
+}
+
+static int
+serial_pxa_verify_port(struct uart_port *port, struct serial_struct *ser)
+{
+	/* we don't want the core code to modify any port params */
+	return -EINVAL;
+}
+
+static const char *
+serial_pxa_type(struct uart_port *port)
+{
+	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
+	return up->name;
+}
+
+#ifdef CONFIG_SERIAL_PXA_CONSOLE
+
+extern struct uart_pxa_port serial_pxa_ports[];
+extern struct uart_driver serial_pxa_reg;
+
+#define BOTH_EMPTY (UART_LSR_TEMT | UART_LSR_THRE)
+
+/*
+ *	Wait for transmitter & holding register to empty
+ */
+static inline void wait_for_xmitr(struct uart_pxa_port *up)
+{
+	unsigned int status, tmout = 10000;
+
+	/* Wait up to 10ms for the character(s) to be sent. */
+	do {
+		status = serial_in(up, UART_LSR);
+
+		if (status & UART_LSR_BI)
+			up->lsr_break_flag = UART_LSR_BI;
+
+		if (--tmout == 0)
+			break;
+		udelay(1);
+	} while ((status & BOTH_EMPTY) != BOTH_EMPTY);
+
+	/* Wait up to 1s for flow control if necessary */
+	if (up->port.flags & UPF_CONS_FLOW) {
+		tmout = 1000000;
+		while (--tmout &&
+		       ((serial_in(up, UART_MSR) & UART_MSR_CTS) == 0))
+			udelay(1);
+	}
+}
+
+/*
+ * Print a string to the serial port trying not to disturb
+ * any possible real use of the port...
+ *
+ *	The console_lock must be held when we get here.
+ */
+static void
+serial_pxa_console_write(struct console *co, const char *s, unsigned int count)
+{
+	struct uart_pxa_port *up = &serial_pxa_ports[co->index];
+	unsigned int ier;
+	int i;
+
+	/*
+	 *	First save the UER then disable the interrupts
+	 */
+	ier = serial_in(up, UART_IER);
+	serial_out(up, UART_IER, UART_IER_UUE);
+
+	/*
+	 *	Now, do each character
+	 */
+	for (i = 0; i < count; i++, s++) {
+		wait_for_xmitr(up);
+
+		/*
+		 *	Send the character out.
+		 *	If a LF, also do CR...
+		 */
+		serial_out(up, UART_TX, *s);
+		if (*s == 10) {
+			wait_for_xmitr(up);
+			serial_out(up, UART_TX, 13);
+		}
+	}
+
+	/*
+	 *	Finally, wait for transmitter to become empty
+	 *	and restore the IER
+	 */
+	wait_for_xmitr(up);
+	serial_out(up, UART_IER, ier);
+}
+
+static int __init
+serial_pxa_console_setup(struct console *co, char *options)
+{
+	struct uart_pxa_port *up;
+	int baud = 9600;
+	int bits = 8;
+	int parity = 'n';
+	int flow = 'n';
+
+	if (co->index == -1 || co->index >= serial_pxa_reg.nr)
+		co->index = 0;
+       	up = &serial_pxa_ports[co->index];
+
+	if (options)
+		uart_parse_options(options, &baud, &parity, &bits, &flow);
+
+	return uart_set_options(&up->port, co, baud, parity, bits, flow);
+}
+
+static struct console serial_pxa_console = {
+	.name		= "ttyS",
+	.write		= serial_pxa_console_write,
+	.device		= uart_console_device,
+	.setup		= serial_pxa_console_setup,
+	.flags		= CON_PRINTBUFFER,
+	.index		= -1,
+	.data		= &serial_pxa_reg,
+};
+
+static int __init
+serial_pxa_console_init(void)
+{
+	register_console(&serial_pxa_console);
+	return 0;
+}
+
+console_initcall(serial_pxa_console_init);
+
+#define PXA_CONSOLE	&serial_pxa_console
+#else
+#define PXA_CONSOLE	NULL
+#endif
+
+struct uart_ops serial_pxa_pops = {
+	.tx_empty	= serial_pxa_tx_empty,
+	.set_mctrl	= serial_pxa_set_mctrl,
+	.get_mctrl	= serial_pxa_get_mctrl,
+	.stop_tx	= serial_pxa_stop_tx,
+	.start_tx	= serial_pxa_start_tx,
+	.stop_rx	= serial_pxa_stop_rx,
+	.enable_ms	= serial_pxa_enable_ms,
+	.break_ctl	= serial_pxa_break_ctl,
+	.startup	= serial_pxa_startup,
+	.shutdown	= serial_pxa_shutdown,
+	.set_termios	= serial_pxa_set_termios,
+	.pm		= serial_pxa_pm,
+	.type		= serial_pxa_type,
+	.release_port	= serial_pxa_release_port,
+	.request_port	= serial_pxa_request_port,
+	.config_port	= serial_pxa_config_port,
+	.verify_port	= serial_pxa_verify_port,
+};
+
+static struct uart_pxa_port serial_pxa_ports[] = {
+     {	/* FFUART */
+	.name	= "FFUART",
+	.cken	= CKEN6_FFUART,
+	.port	= {
+		.type		= PORT_PXA,
+		.iotype		= SERIAL_IO_MEM,
+		.membase	= (void *)&FFUART,
+		.mapbase	= __PREG(FFUART),
+		.irq		= IRQ_FFUART,
+		.uartclk	= 921600 * 16,
+		.fifosize	= 64,
+		.flags		= ASYNC_SKIP_TEST,
+		.ops		= &serial_pxa_pops,
+		.line		= 0,
+	},
+  }, {	/* BTUART */
+	.name	= "BTUART",
+	.cken	= CKEN7_BTUART,
+	.port	= {
+		.type		= PORT_PXA,
+		.iotype		= SERIAL_IO_MEM,
+		.membase	= (void *)&BTUART,
+		.mapbase	= __PREG(BTUART),
+		.irq		= IRQ_BTUART,
+		.uartclk	= 921600 * 16,
+		.fifosize	= 64,
+		.flags		= ASYNC_SKIP_TEST,
+		.ops		= &serial_pxa_pops,
+		.line		= 1,
+	},
+  }, {	/* STUART */
+	.name	= "STUART",
+	.cken	= CKEN5_STUART,
+	.port	= {
+		.type		= PORT_PXA,
+		.iotype		= SERIAL_IO_MEM,
+		.membase	= (void *)&STUART,
+		.mapbase	= __PREG(STUART),
+		.irq		= IRQ_STUART,
+		.uartclk	= 921600 * 16,
+		.fifosize	= 64,
+		.flags		= ASYNC_SKIP_TEST,
+		.ops		= &serial_pxa_pops,
+		.line		= 2,
+	},
+  }
+};
+
+static struct uart_driver serial_pxa_reg = {
+	.owner		= THIS_MODULE,
+	.driver_name	= "PXA serial",
+	.devfs_name	= "tts/",
+	.dev_name	= "ttyS",
+	.major		= TTY_MAJOR,
+	.minor		= 64,
+	.nr		= ARRAY_SIZE(serial_pxa_ports),
+	.cons		= PXA_CONSOLE,
+};
+
+static int __init serial_pxa_init(void)
+{
+	int i, ret;
+
+	ret = uart_register_driver(&serial_pxa_reg);
+	if (ret)
+		return ret;
+
+	for (i = 0; i < ARRAY_SIZE(serial_pxa_ports); i++)
+		uart_add_one_port(&serial_pxa_reg, &serial_pxa_ports[i].port);
+
+	return 0;
+}
+
+static void __exit serial_pxa_exit(void)
+{
+	uart_unregister_driver(&serial_pxa_reg);
+}
+
+module_init(serial_pxa_init);
+module_exit(serial_pxa_exit);
+
+MODULE_LICENSE("GPL");
+
--- diff/fs/hfs/btree.h	1970-01-01 01:00:00.000000000 +0100
+++ source/fs/hfs/btree.h	2004-02-23 13:56:46.000000000 +0000
@@ -0,0 +1,171 @@
+/*
+ *  linux/fs/hfs/btree.h
+ *
+ * Copyright (C) 2001
+ * Brad Boyer (flar@allandria.com)
+ * (C) 2003 Ardis Technologies <roman@ardistech.com>
+ */
+
+#include "hfs_fs.h"
+
+typedef int (*btree_keycmp)(const btree_key *, const btree_key *);
+
+#define NODE_HASH_SIZE  256
+
+/* A HFS BTree held in memory */
+struct hfs_btree {
+	struct super_block *sb;
+	struct inode *inode;
+	btree_keycmp keycmp;
+
+	u32 cnid;
+	u32 root;
+	u32 leaf_count;
+	u32 leaf_head;
+	u32 leaf_tail;
+	u32 node_count;
+	u32 free_nodes;
+	u32 attributes;
+
+	unsigned int node_size;
+	unsigned int node_size_shift;
+	unsigned int max_key_len;
+	unsigned int depth;
+
+	//unsigned int map1_size, map_size;
+	struct semaphore tree_lock;
+
+	unsigned int pages_per_bnode;
+	spinlock_t hash_lock;
+	struct hfs_bnode *node_hash[NODE_HASH_SIZE];
+	int node_hash_cnt;
+};
+
+/* A HFS BTree node in memory */
+struct hfs_bnode {
+	struct hfs_btree *tree;
+
+	u32 prev;
+	u32 this;
+	u32 next;
+	u32 parent;
+
+	u16 num_recs;
+	u8 type;
+	u8 height;
+
+	struct hfs_bnode *next_hash;
+	unsigned long flags;
+	wait_queue_head_t lock_wq;
+	atomic_t refcnt;
+	unsigned int page_offset;
+	struct page *page[0];
+};
+
+#define HFS_BNODE_ERROR		0
+#define HFS_BNODE_NEW		1
+#define HFS_BNODE_DELETED	2
+
+struct hfs_find_data {
+	btree_key *key;
+	btree_key *search_key;
+	struct hfs_btree *tree;
+	struct hfs_bnode *bnode;
+	int record;
+	int keyoffset, keylength;
+	int entryoffset, entrylength;
+};
+
+
+/* btree.c */
+extern struct hfs_btree *hfs_btree_open(struct super_block *, u32, btree_keycmp);
+extern void hfs_btree_close(struct hfs_btree *);
+extern void hfs_btree_write(struct hfs_btree *);
+extern struct hfs_bnode * hfs_bmap_alloc(struct hfs_btree *);
+extern void hfs_bmap_free(struct hfs_bnode *node);
+
+/* bnode.c */
+extern void hfs_bnode_read(struct hfs_bnode *, void *, int, int);
+extern u16 hfs_bnode_read_u16(struct hfs_bnode *, int);
+extern u8 hfs_bnode_read_u8(struct hfs_bnode *, int);
+extern void hfs_bnode_read_key(struct hfs_bnode *, void *, int);
+extern void hfs_bnode_write(struct hfs_bnode *, void *, int, int);
+extern void hfs_bnode_write_u16(struct hfs_bnode *, int, u16);
+extern void hfs_bnode_write_u8(struct hfs_bnode *, int, u8);
+extern void hfs_bnode_clear(struct hfs_bnode *, int, int);
+extern void hfs_bnode_copy(struct hfs_bnode *, int,
+			   struct hfs_bnode *, int, int);
+extern void hfs_bnode_move(struct hfs_bnode *, int, int, int);
+extern void hfs_bnode_dump(struct hfs_bnode *);
+extern void hfs_bnode_unlink(struct hfs_bnode *);
+extern struct hfs_bnode *hfs_bnode_findhash(struct hfs_btree *, u32);
+extern struct hfs_bnode *hfs_bnode_find(struct hfs_btree *, u32);
+extern void hfs_bnode_unhash(struct hfs_bnode *);
+extern void hfs_bnode_free(struct hfs_bnode *);
+extern struct hfs_bnode *hfs_bnode_create(struct hfs_btree *, u32);
+extern void hfs_bnode_get(struct hfs_bnode *);
+extern void hfs_bnode_put(struct hfs_bnode *);
+
+/* brec.c */
+extern u16 hfs_brec_lenoff(struct hfs_bnode *, u16, u16 *);
+extern u16 hfs_brec_keylen(struct hfs_bnode *, u16);
+extern int hfs_brec_insert(struct hfs_find_data *, void *, int);
+extern int hfs_brec_remove(struct hfs_find_data *);
+extern struct hfs_bnode *hfs_bnode_split(struct hfs_find_data *);
+extern int hfs_brec_update_parent(struct hfs_find_data *);
+extern int hfs_btree_inc_height(struct hfs_btree *);
+
+/* bfind.c */
+extern int hfs_find_init(struct hfs_btree *, struct hfs_find_data *);
+extern void hfs_find_exit(struct hfs_find_data *);
+extern int __hfs_brec_find(struct hfs_bnode *, struct hfs_find_data *);
+extern int hfs_brec_find(struct hfs_find_data *);
+extern int hfs_brec_read(struct hfs_find_data *, void *, int);
+extern int hfs_brec_goto(struct hfs_find_data *, int);
+
+
+struct hfs_bnode_desc {
+	u32 next;		/* (V) Number of the next node at this level */
+	u32 prev;		/* (V) Number of the prev node at this level */
+	u8 type;		/* (F) The type of node */
+	u8 height;		/* (F) The level of this node (leaves=1) */
+	u16 num_recs;		/* (V) The number of records in this node */
+	u16 reserved;
+} __packed;
+
+#define HFS_NODE_INDEX	0x00	/* An internal (index) node */
+#define HFS_NODE_HEADER	0x01	/* The tree header node (node 0) */
+#define HFS_NODE_MAP	0x02	/* Holds part of the bitmap of used nodes */
+#define HFS_NODE_LEAF	0xFF	/* A leaf (ndNHeight==1) node */
+
+struct hfs_btree_header_rec {
+	u16 depth;		/* (V) The number of levels in this B-tree */
+	u32 root;		/* (V) The node number of the root node */
+	u32 leaf_count;		/* (V) The number of leaf records */
+	u32 leaf_head;		/* (V) The number of the first leaf node */
+	u32 leaf_tail;		/* (V) The number of the last leaf node */
+	u16 node_size;		/* (F) The number of bytes in a node (=512) */
+	u16 max_key_len;	/* (F) The length of a key in an index node */
+	u32 node_count;		/* (V) The total number of nodes */
+	u32 free_nodes;		/* (V) The number of unused nodes */
+	u16 reserved1;
+	u32 clump_size;		/* (F) clump size. not usually used. */
+	u8 btree_type;		/* (F) BTree type */
+	u8 reserved2;
+	u32 attributes;		/* (F) attributes */
+	u32 reserved3[16];
+} __packed;
+
+#define HFS_NODE_INDEX	0x00	/* An internal (index) node */
+#define HFS_NODE_HEADER	0x01	/* The tree header node (node 0) */
+#define HFS_NODE_MAP		0x02	/* Holds part of the bitmap of used nodes */
+#define HFS_NODE_LEAF		0xFF	/* A leaf (ndNHeight==1) node */
+
+#define BTREE_ATTR_BADCLOSE	0x00000001	/* b-tree not closed properly. not
+						   used by hfsplus. */
+#define HFS_TREE_BIGKEYS	0x00000002	/* key length is u16 instead of u8.
+						   used by hfsplus. */
+#define HFS_TREE_VARIDXKEYS	0x00000004	/* variable key length instead of
+						   max key length. use din catalog
+						   b-tree but not in extents
+						   b-tree (hfsplus). */
--- diff/fs/hfs/hfs_fs.h	1970-01-01 01:00:00.000000000 +0100
+++ source/fs/hfs/hfs_fs.h	2004-02-23 13:56:46.000000000 +0000
@@ -0,0 +1,291 @@
+/*
+ *  linux/fs/hfs/hfs_fs.h
+ *
+ * Copyright (C) 1995-1997  Paul H. Hargrove
+ * (C) 2003 Ardis Technologies <roman@ardistech.com>
+ * This file may be distributed under the terms of the GNU General Public License.
+ */
+
+#ifndef _LINUX_HFS_FS_H
+#define _LINUX_HFS_FS_H
+
+#include <linux/version.h>
+#include <linux/slab.h>
+#include <linux/types.h>
+#include <linux/buffer_head.h>
+#include <linux/fs.h>
+
+#include <asm/byteorder.h>
+#include <asm/uaccess.h>
+
+#include "hfs.h"
+
+#define DBG_BNODE_REFS	0x00000001
+#define DBG_BNODE_MOD	0x00000002
+#define DBG_CAT_MOD	0x00000004
+#define DBG_INODE	0x00000008
+#define DBG_SUPER	0x00000010
+#define DBG_EXTENT	0x00000020
+#define DBG_BITMAP	0x00000040
+
+//#define DBG_MASK	(DBG_EXTENT|DBG_INODE|DBG_BNODE_MOD|DBG_CAT_MOD|DBG_BITMAP)
+//#define DBG_MASK	(DBG_BNODE_MOD|DBG_CAT_MOD|DBG_INODE)
+//#define DBG_MASK	(DBG_CAT_MOD|DBG_BNODE_REFS|DBG_INODE|DBG_EXTENT)
+#define DBG_MASK	(0)
+
+#define dprint(flg, fmt, args...) \
+	if (flg & DBG_MASK) printk(fmt , ## args)
+
+#define hfs_warn(format, args...) printk(KERN_WARNING format , ## args)
+#define hfs_error(format, args...) printk(KERN_ERR format , ## args)
+
+/*
+ * struct hfs_inode_info
+ *
+ * The HFS-specific part of a Linux (struct inode)
+ */
+struct hfs_inode_info {
+	atomic_t opencnt;
+
+	unsigned int flags;
+
+	/* to deal with localtime ugliness */
+	int tz_secondswest;
+
+	struct hfs_cat_key cat_key;
+
+	struct list_head open_dir_list;
+	struct inode *rsrc_inode;
+
+	struct semaphore extents_lock;
+
+	u16 alloc_blocks, clump_blocks;
+	/* Allocation extents from catlog record or volume header */
+	hfs_extent_rec first_extents;
+	u16 first_blocks;
+	hfs_extent_rec cached_extents;
+	u16 cached_start, cached_blocks;
+
+	loff_t phys_size;
+	struct inode vfs_inode;
+};
+
+#define HFS_FLG_RSRC		0x0001
+#define HFS_FLG_EXT_DIRTY	0x0002
+#define HFS_FLG_EXT_NEW		0x0004
+
+#define HFS_IS_RSRC(inode)	(HFS_I(inode)->flags & HFS_FLG_RSRC)
+
+/*
+ * struct hfs_sb_info
+ *
+ * The HFS-specific part of a Linux (struct super_block)
+ */
+struct hfs_sb_info {
+	struct buffer_head *mdb_bh;		/* The hfs_buffer
+						   holding the real
+						   superblock (aka VIB
+						   or MDB) */
+	struct hfs_mdb *mdb;
+	struct buffer_head *alt_mdb_bh;		/* The hfs_buffer holding
+						   the alternate superblock */
+	struct hfs_mdb *alt_mdb;
+	u32 *bitmap;				/* The page holding the
+						   allocation bitmap */
+	struct hfs_btree *ext_tree;			/* Information about
+						   the extents b-tree */
+	struct hfs_btree *cat_tree;			/* Information about
+						   the catalog b-tree */
+	u32 file_count;				/* The number of
+						   regular files in
+						   the filesystem */
+	u32 folder_count;			/* The number of
+						   directories in the
+						   filesystem */
+	u32 next_id;				/* The next available
+						   file id number */
+	u32 clumpablks;				/* The number of allocation
+						   blocks to try to add when
+						   extending a file */
+	u32 fs_start;				/* The first 512-byte
+						   block represented
+						   in the bitmap */
+	u32 part_start;
+	u16 root_files;				/* The number of
+						   regular
+						   (non-directory)
+						   files in the root
+						   directory */
+	u16 root_dirs;				/* The number of
+						   directories in the
+						   root directory */
+	u16 fs_ablocks;				/* The number of
+						   allocation blocks
+						   in the filesystem */
+	u16 free_ablocks;			/* the number of unused
+						   allocation blocks
+						   in the filesystem */
+	u32 alloc_blksz;			/* The size of an
+						   "allocation block" */
+	int s_quiet;				/* Silent failure when
+						   changing owner or mode? */
+	u32 s_type;				/* Type for new files */
+	u32 s_creator;				/* Creator for new files */
+	umode_t s_file_umask;			/* The umask applied to the
+						   permissions on all files */
+	umode_t s_dir_umask;			/* The umask applied to the
+						   permissions on all dirs */
+	uid_t s_uid;				/* The uid of all files */
+	gid_t s_gid;				/* The gid of all files */
+
+	int session, part;
+
+	struct semaphore bitmap_lock;
+
+	unsigned long flags;
+
+	u16 blockoffset;
+
+	int fs_div;
+
+	struct hlist_head rsrc_inodes;
+};
+
+#define HFS_FLG_BITMAP_DIRTY	0
+#define HFS_FLG_MDB_DIRTY	1
+#define HFS_FLG_ALT_MDB_DIRTY	2
+
+/* bitmap.c */
+extern u32 hfs_vbm_search_free(struct super_block *, u32, u32 *);
+extern int hfs_clear_vbm_bits(struct super_block *, u16, u16);
+
+/* catalog.c */
+extern int hfs_cat_keycmp(const btree_key *, const btree_key *);
+struct hfs_find_data;
+extern int hfs_cat_find_brec(struct super_block *, u32, struct hfs_find_data *);
+extern int hfs_cat_create(u32, struct inode *, struct qstr *, struct inode *);
+extern int hfs_cat_delete(u32, struct inode *, struct qstr *);
+extern int hfs_cat_move(u32, struct inode *, struct qstr *,
+			struct inode *, struct qstr *);
+extern void hfs_cat_build_key(btree_key *, u32, struct qstr *);
+
+/* dir.c */
+extern struct file_operations hfs_dir_operations;
+extern struct inode_operations hfs_dir_inode_operations;
+
+extern int hfs_mkdir(struct inode *, struct dentry *, int);
+extern int hfs_unlink(struct inode *, struct dentry *);
+extern int hfs_rmdir(struct inode *, struct dentry *);
+extern int hfs_rename(struct inode *, struct dentry *,
+		      struct inode *, struct dentry *);
+
+/* extent.c */
+extern int hfs_ext_keycmp(const btree_key *, const btree_key *);
+extern int hfs_free_fork(struct super_block *, struct hfs_cat_file *, int);
+extern void hfs_ext_write_extent(struct inode *);
+extern int hfs_extend_file(struct inode *);
+extern void hfs_file_truncate(struct inode *);
+
+/* file.c */
+extern struct inode_operations hfs_file_inode_operations;
+extern struct file_operations hfs_file_operations;
+
+extern int hfs_get_block(struct inode *, sector_t, struct buffer_head *, int);
+
+/* inode.c */
+extern struct address_space_operations hfs_aops;
+extern struct address_space_operations hfs_btree_aops;
+
+extern struct inode *hfs_new_inode(struct inode *, struct qstr *, int);
+extern void hfs_inode_write_fork(struct inode *, struct hfs_extent *, u32 *, u32 *);
+extern void hfs_write_inode(struct inode *, int);
+extern int hfs_inode_setattr(struct dentry *, struct iattr *);
+extern void hfs_inode_read_fork(struct inode *inode, struct hfs_extent *ext,
+				u32 log_size, u32 phys_size, u32 clump_size);
+extern struct inode *hfs_iget(struct super_block *, struct hfs_cat_key *, hfs_cat_rec *);
+extern void hfs_clear_inode(struct inode *);
+extern void hfs_delete_inode(struct inode *);
+
+/* mdb.c */
+extern int hfs_mdb_get(struct super_block *);
+extern void hfs_mdb_commit(struct super_block *);
+extern void hfs_mdb_close(struct super_block *);
+extern void hfs_mdb_put(struct super_block *);
+
+/* part_tbl.c */
+extern int hfs_part_find(struct super_block *, sector_t *, sector_t *);
+
+/* string.c */
+extern struct dentry_operations hfs_dentry_operations;
+
+extern int hfs_hash_dentry(struct dentry *, struct qstr *);
+extern int hfs_strcmp(const unsigned char *, unsigned int,
+		      const unsigned char *, unsigned int);
+extern int hfs_compare_dentry(struct dentry *, struct qstr *, struct qstr *);
+
+/* super.c */
+extern struct super_block *hfs_read_super(struct super_block *,void *,int);
+
+/* trans.c */
+extern void hfs_triv2mac(struct hfs_name *, struct qstr *);
+extern int hfs_mac2triv(char *, const struct hfs_name *);
+
+extern struct timezone sys_tz;
+
+/*
+ * There are two time systems.  Both are based on seconds since
+ * a particular time/date.
+ *	Unix:	unsigned lil-endian since 00:00 GMT, Jan. 1, 1970
+ *	mac:	unsigned big-endian since 00:00 GMT, Jan. 1, 1904
+ *
+ */
+#define __hfs_u_to_mtime(sec)	cpu_to_be32(sec + 2082844800U - sys_tz.tz_minuteswest * 60)
+#define __hfs_m_to_utime(sec)	(be32_to_cpu(sec) - 2082844800U  + sys_tz.tz_minuteswest * 60)
+
+#define HFS_I(inode)	(list_entry(inode, struct hfs_inode_info, vfs_inode))
+#define HFS_SB(sb)	((struct hfs_sb_info *)(sb)->s_fs_info)
+
+#define hfs_m_to_utime(time)	(struct timespec){ .tv_sec = __hfs_m_to_utime(time) }
+#define hfs_u_to_mtime(time)	__hfs_u_to_mtime((time).tv_sec)
+#define hfs_mtime()		__hfs_u_to_mtime(get_seconds())
+
+static inline const char *hfs_mdb_name(struct super_block *sb)
+{
+	return sb->s_id;
+}
+
+static inline void hfs_bitmap_dirty(struct super_block *sb)
+{
+	set_bit(HFS_FLG_BITMAP_DIRTY, &HFS_SB(sb)->flags);
+	sb->s_dirt = 1;
+}
+
+static inline void hfs_buffer_sync(struct buffer_head *bh)
+{
+	while (buffer_locked(bh)) {
+		wait_on_buffer(bh);
+	}
+	if (buffer_dirty(bh)) {
+		ll_rw_block(WRITE, 1, &bh);
+		wait_on_buffer(bh);
+	}
+}
+
+#define sb_bread512(sb, sec, data) ({			\
+	struct buffer_head *__bh;			\
+	sector_t __block;				\
+	loff_t __start;					\
+	int __offset;					\
+							\
+	__start = (loff_t)(sec) << HFS_SECTOR_SIZE_BITS;\
+	__block = __start >> (sb)->s_blocksize_bits;	\
+	__offset = __start & ((sb)->s_blocksize - 1);	\
+	__bh = sb_bread((sb), __block);			\
+	if (likely(__bh != NULL))			\
+		data = (void *)(__bh->b_data + __offset);\
+	else						\
+		data = NULL;				\
+	__bh;						\
+})
+
+#endif
--- diff/fs/hfsplus/Makefile	1970-01-01 01:00:00.000000000 +0100
+++ source/fs/hfsplus/Makefile	2004-02-23 13:56:46.000000000 +0000
@@ -0,0 +1,9 @@
+#
+## Makefile for the linux hfsplus filesystem routines.
+#
+
+obj-$(CONFIG_HFSPLUS_FS) += hfsplus.o
+
+hfsplus-objs := super.o options.o inode.o ioctl.o extents.o catalog.o dir.o btree.o \
+		bnode.o brec.o bfind.o tables.o unicode.o wrapper.o bitmap.o part_tbl.o
+
--- diff/fs/hfsplus/bfind.c	1970-01-01 01:00:00.000000000 +0100
+++ source/fs/hfsplus/bfind.c	2004-02-23 13:56:46.000000000 +0000
@@ -0,0 +1,209 @@
+/*
+ *  linux/fs/hfsplus/bfind.c
+ *
+ * Copyright (C) 2001
+ * Brad Boyer (flar@allandria.com)
+ * (C) 2003 Ardis Technologies <roman@ardistech.com>
+ *
+ * Search routines for btrees
+ */
+
+#include <linux/slab.h>
+#include "hfsplus_fs.h"
+
+int hfs_find_init(struct hfs_btree *tree, struct hfs_find_data *fd)
+{
+	void *ptr;
+
+	fd->tree = tree;
+	fd->bnode = NULL;
+	ptr = kmalloc(tree->max_key_len * 2 + 4, GFP_KERNEL);
+	if (!ptr)
+		return -ENOMEM;
+	fd->search_key = ptr;
+	fd->key = ptr + tree->max_key_len + 2;
+	dprint(DBG_BNODE_REFS, "find_init: %d (%p)\n", tree->cnid, __builtin_return_address(0));
+	down(&tree->tree_lock);
+	return 0;
+}
+
+void hfs_find_exit(struct hfs_find_data *fd)
+{
+	hfs_bnode_put(fd->bnode);
+	kfree(fd->search_key);
+	dprint(DBG_BNODE_REFS, "find_exit: %d (%p)\n", fd->tree->cnid, __builtin_return_address(0));
+	up(&fd->tree->tree_lock);
+	fd->tree = NULL;
+}
+
+/* Find the record in bnode that best matches key (not greater than...)*/
+int __hfs_brec_find(struct hfs_bnode *bnode, struct hfs_find_data *fd)
+{
+	int cmpval;
+	u16 off, len, keylen;
+	int rec;
+	int b, e;
+	int res;
+
+	b = 0;
+	e = bnode->num_recs - 1;
+	res = -ENOENT;
+	do {
+		rec = (e + b) / 2;
+		len = hfs_brec_lenoff(bnode, rec, &off);
+		keylen = hfs_brec_keylen(bnode, rec);
+		hfs_bnode_read(bnode, fd->key, off, keylen);
+		cmpval = bnode->tree->keycmp(fd->key, fd->search_key);
+		if (!cmpval) {
+			e = rec;
+			res = 0;
+			goto done;
+		}
+		if (cmpval < 0)
+			b = rec + 1;
+		else
+			e = rec - 1;
+	} while (b <= e);
+	//printk("%d: %d,%d,%d\n", bnode->this, b, e, rec);
+	if (rec != e && e >= 0) {
+		len = hfs_brec_lenoff(bnode, e, &off);
+		keylen = hfs_brec_keylen(bnode, e);
+		hfs_bnode_read(bnode, fd->key, off, keylen);
+	}
+done:
+	fd->record = e;
+	fd->keyoffset = off;
+	fd->keylength = keylen;
+	fd->entryoffset = off + keylen;
+	fd->entrylength = len - keylen;
+	return res;
+}
+
+/* Traverse a B*Tree from the root to a leaf finding best fit to key */
+/* Return allocated copy of node found, set recnum to best record */
+int hfs_brec_find(struct hfs_find_data *fd)
+{
+	struct hfs_btree *tree;
+	struct hfs_bnode *bnode;
+	u32 data, nidx, parent;
+	int height, res;
+
+	tree = fd->tree;
+	if (fd->bnode)
+		hfs_bnode_put(fd->bnode);
+	fd->bnode = NULL;
+	nidx = tree->root;
+	if (!nidx)
+		return -ENOENT;
+	height = tree->depth;
+	res = 0;
+	parent = 0;
+	for (;;) {
+		bnode = hfs_bnode_find(tree, nidx);
+		if (IS_ERR(bnode)) {
+			res = PTR_ERR(bnode);
+			bnode = NULL;
+			break;
+		}
+		if (bnode->height != height)
+			goto invalid;
+		if (bnode->type != (--height ? HFS_NODE_INDEX : HFS_NODE_LEAF))
+			goto invalid;
+		bnode->parent = parent;
+
+		res = __hfs_brec_find(bnode, fd);
+		if (!height)
+			break;
+		if (fd->record < 0)
+			goto release;
+
+		parent = nidx;
+		hfs_bnode_read(bnode, &data, fd->entryoffset, 4);
+		nidx = be32_to_cpu(data);
+		hfs_bnode_put(bnode);
+	}
+	fd->bnode = bnode;
+	return res;
+
+invalid:
+	printk("HFS+-fs: inconsistency in B*Tree (%d,%d,%d,%u,%u)\n",
+		height, bnode->height, bnode->type, nidx, parent);
+	res = -EIO;
+release:
+	hfs_bnode_put(bnode);
+	return res;
+}
+
+int hfs_brec_read(struct hfs_find_data *fd, void *rec, int rec_len)
+{
+	int res;
+
+	res = hfs_brec_find(fd);
+	if (res)
+		return res;
+	if (fd->entrylength > rec_len)
+		return -EINVAL;
+	hfs_bnode_read(fd->bnode, rec, fd->entryoffset, fd->entrylength);
+	return 0;
+}
+
+int hfs_brec_goto(struct hfs_find_data *fd, int cnt)
+{
+	struct hfs_btree *tree;
+	struct hfs_bnode *bnode;
+	int idx, res = 0;
+	u16 off, len, keylen;
+
+	bnode = fd->bnode;
+	tree = bnode->tree;
+
+	if (cnt < 0) {
+		cnt = -cnt;
+		while (cnt > fd->record) {
+			cnt -= fd->record + 1;
+			fd->record = bnode->num_recs - 1;
+			idx = bnode->prev;
+			if (!idx) {
+				res = -ENOENT;
+				goto out;
+			}
+			hfs_bnode_put(bnode);
+			bnode = hfs_bnode_find(tree, idx);
+			if (IS_ERR(bnode)) {
+				res = PTR_ERR(bnode);
+				bnode = NULL;
+				goto out;
+			}
+		}
+		fd->record -= cnt;
+	} else {
+		while (cnt >= bnode->num_recs - fd->record) {
+			cnt -= bnode->num_recs - fd->record;
+			fd->record = 0;
+			idx = bnode->next;
+			if (!idx) {
+				res = -ENOENT;
+				goto out;
+			}
+			hfs_bnode_put(bnode);
+			bnode = hfs_bnode_find(tree, idx);
+			if (IS_ERR(bnode)) {
+				res = PTR_ERR(bnode);
+				bnode = NULL;
+				goto out;
+			}
+		}
+		fd->record += cnt;
+	}
+
+	len = hfs_brec_lenoff(bnode, fd->record, &off);
+	keylen = hfs_brec_keylen(bnode, fd->record);
+	fd->keyoffset = off;
+	fd->keylength = keylen;
+	fd->entryoffset = off + keylen;
+	fd->entrylength = len - keylen;
+	hfs_bnode_read(bnode, fd->key, off, keylen);
+out:
+	fd->bnode = bnode;
+	return res;
+}
--- diff/fs/hfsplus/bitmap.c	1970-01-01 01:00:00.000000000 +0100
+++ source/fs/hfsplus/bitmap.c	2004-02-23 13:56:46.000000000 +0000
@@ -0,0 +1,220 @@
+/*
+ *  linux/fs/hfsplus/bitmap.c
+ *
+ * Copyright (C) 2001
+ * Brad Boyer (flar@allandria.com)
+ * (C) 2003 Ardis Technologies <roman@ardistech.com>
+ *
+ * Handling of allocation file
+ */
+
+#include <linux/pagemap.h>
+
+#include "hfsplus_fs.h"
+#include "hfsplus_raw.h"
+
+#define PAGE_CACHE_BITS	(PAGE_CACHE_SIZE * 8)
+
+int hfsplus_block_allocate(struct super_block *sb, u32 size, u32 offset, u32 *max)
+{
+	struct page *page;
+	struct address_space *mapping;
+	u32 *pptr, *curr, *end;
+	u32 val, mask, start, len;
+	int i;
+
+	len = *max;
+	if (!len)
+		return size;
+
+	dprint(DBG_BITMAP, "block_allocate: %u,%u,%u\n", size, offset, len);
+	down(&HFSPLUS_SB(sb).alloc_file->i_sem);
+	mapping = HFSPLUS_SB(sb).alloc_file->i_mapping;
+	page = read_cache_page(mapping, offset / PAGE_CACHE_BITS,
+			       (filler_t *)mapping->a_ops->readpage, NULL);
+	pptr = kmap(page);
+	curr = pptr + (offset & (PAGE_CACHE_BITS - 1)) / 32;
+	i = offset % 32;
+	offset &= ~(PAGE_CACHE_BITS - 1);
+	if ((size ^ offset) / PAGE_CACHE_BITS)
+		end = pptr + PAGE_CACHE_BITS / 32;
+	else
+		end = pptr + ((size + 31) & (PAGE_CACHE_BITS - 1)) / 32;
+
+	/* scan the first partial u32 for zero bits */
+	val = *curr;
+	if (~val) {
+		val = be32_to_cpu(val);
+		mask = (1U << 31) >> i;
+		for (; i < 32; mask >>= 1, i++) {
+			if (!(val & mask))
+				goto found;
+		}
+	}
+	curr++;
+
+	/* scan complete u32s for the first zero bit */
+	while (1) {
+		while (curr < end) {
+			val = *curr;
+			if (~val) {
+				val = be32_to_cpu(val);
+				mask = 1 << 31;
+				for (i = 0; i < 32; mask >>= 1, i++) {
+					if (!(val & mask))
+						goto found;
+				}
+			}
+			curr++;
+		}
+		kunmap(page);
+		offset += PAGE_CACHE_BITS;
+		if (offset >= size)
+			break;
+		page = read_cache_page(mapping, offset / PAGE_CACHE_BITS,
+				       (filler_t *)mapping->a_ops->readpage, NULL);
+		curr = pptr = kmap(page);
+		if ((size ^ offset) / PAGE_CACHE_BITS)
+			end = pptr + PAGE_CACHE_BITS / 32;
+		else
+			end = pptr + ((size + 31) & (PAGE_CACHE_BITS - 1)) / 32;
+	}
+	dprint(DBG_BITMAP, "bitmap full\n");
+	start = size;
+	goto out;
+
+found:
+	start = offset + (curr - pptr) * 32 + i;
+	if (start >= size) {
+		dprint(DBG_BITMAP, "bitmap full\n");
+		goto out;
+	}
+	/* do any partial u32 at the start */
+	len = min(size - start, len);
+	while (1) {
+		val |= mask;
+		if (++i >= 32)
+			break;
+		mask >>= 1;
+		if (!--len || val & mask)
+			goto done;
+	}
+	if (!--len)
+		goto done;
+	*curr++ = cpu_to_be32(val);
+	/* do full u32s */
+	while (1) {
+		while (curr < end) {
+			val = be32_to_cpu(*curr);
+			if (len < 32)
+				goto last;
+			if (val) {
+				len = 32;
+				goto last;
+			}
+			*curr++ = 0xffffffffU;
+			len -= 32;
+		}
+		set_page_dirty(page);
+		kunmap(page);
+		offset += PAGE_CACHE_BITS;
+		page = read_cache_page(mapping, offset / PAGE_CACHE_BITS,
+				       (filler_t *)mapping->a_ops->readpage, NULL);
+		pptr = kmap(page);
+		curr = pptr;
+		end = pptr + PAGE_CACHE_BITS / 32;
+	}
+last:
+	/* do any partial u32 at end */
+	mask = 1U << 31;
+	for (i = 0; i < len; i++) {
+		if (val & mask)
+			break;
+		val |= mask;
+		mask >>= 1;
+	}
+done:
+	*curr = cpu_to_be32(val);
+	set_page_dirty(page);
+	kunmap(page);
+	*max = offset + (curr - pptr) * 32 + i - start;
+	HFSPLUS_SB(sb).free_blocks -= *max;
+	sb->s_dirt = 1;
+	dprint(DBG_BITMAP, "-> %u,%u\n", start, *max);
+out:
+	up(&HFSPLUS_SB(sb).alloc_file->i_sem);
+	return start;
+}
+
+int hfsplus_block_free(struct super_block *sb, u32 offset, u32 count)
+{
+	struct page *page;
+	struct address_space *mapping;
+	u32 *pptr, *curr, *end;
+	u32 mask, len, pnr;
+	int i;
+
+	/* is there any actual work to be done? */
+	if (!count)
+		return 0;
+
+	dprint(DBG_BITMAP, "block_free: %u,%u\n", offset, count);
+	/* are all of the bits in range? */
+	if ((offset + count) > HFSPLUS_SB(sb).total_blocks)
+		return -2;
+
+	down(&HFSPLUS_SB(sb).alloc_file->i_sem);
+	mapping = HFSPLUS_SB(sb).alloc_file->i_mapping;
+	pnr = offset / PAGE_CACHE_BITS;
+	page = read_cache_page(mapping, pnr, (filler_t *)mapping->a_ops->readpage, NULL);
+	pptr = kmap(page);
+	curr = pptr + (offset & (PAGE_CACHE_BITS - 1)) / 32;
+	end = pptr + PAGE_CACHE_BITS / 32;
+	len = count;
+
+	/* do any partial u32 at the start */
+	i = offset % 32;
+	if (i) {
+		int j = 32 - i;
+		mask = 0xffffffffU << j;
+		if (j > count) {
+			mask |= 0xffffffffU >> (i + count);
+			*curr++ &= cpu_to_be32(mask);
+			goto out;
+		}
+		*curr++ &= cpu_to_be32(mask);
+		count -= j;
+	}
+
+	/* do full u32s */
+	while (1) {
+		while (curr < end) {
+			if (count < 32)
+				goto done;
+			*curr++ = 0;
+			count -= 32;
+		}
+		if (!count)
+			break;
+		set_page_dirty(page);
+		kunmap(page);
+		page = read_cache_page(mapping, ++pnr, (filler_t *)mapping->a_ops->readpage, NULL);
+		pptr = kmap(page);
+		curr = pptr;
+		end = pptr + PAGE_CACHE_BITS / 32;
+	}
+done:
+	/* do any partial u32 at end */
+	if (count) {
+		mask = 0xffffffffU >> count;
+		*curr &= cpu_to_be32(mask);
+	}
+out:
+	set_page_dirty(page);
+	kunmap(page);
+	HFSPLUS_SB(sb).free_blocks += len;
+	sb->s_dirt = 1;
+	up(&HFSPLUS_SB(sb).alloc_file->i_sem);
+
+	return 0;
+}
--- diff/fs/hfsplus/bnode.c	1970-01-01 01:00:00.000000000 +0100
+++ source/fs/hfsplus/bnode.c	2004-02-23 13:56:46.000000000 +0000
@@ -0,0 +1,661 @@
+/*
+ *  linux/fs/hfsplus/bnode.c
+ *
+ * Copyright (C) 2001
+ * Brad Boyer (flar@allandria.com)
+ * (C) 2003 Ardis Technologies <roman@ardistech.com>
+ *
+ * Handle basic btree node operations
+ */
+
+#include <linux/string.h>
+#include <linux/slab.h>
+#include <linux/pagemap.h>
+#include <linux/fs.h>
+#include <linux/swap.h>
+#include <linux/version.h>
+
+#include "hfsplus_fs.h"
+#include "hfsplus_raw.h"
+
+#define REF_PAGES	0
+
+/* Copy a specified range of bytes from the raw data of a node */
+void hfs_bnode_read(struct hfs_bnode *node, void *buf, int off, int len)
+{
+	struct page **pagep;
+	int l;
+
+	off += node->page_offset;
+	pagep = node->page + (off >> PAGE_CACHE_SHIFT);
+	off &= ~PAGE_CACHE_MASK;
+
+	l = min(len, (int)PAGE_CACHE_SIZE - off);
+	memcpy(buf, kmap(*pagep) + off, l);
+	kunmap(*pagep);
+
+	while ((len -= l)) {
+		buf += l;
+		l = min(len, (int)PAGE_CACHE_SIZE);
+		memcpy(buf, kmap(*++pagep), l);
+		kunmap(*pagep);
+	}
+}
+
+u16 hfs_bnode_read_u16(struct hfs_bnode *node, int off)
+{
+	u16 data;
+	// optimize later...
+	hfs_bnode_read(node, &data, off, 2);
+	return be16_to_cpu(data);
+}
+
+u8 hfs_bnode_read_u8(struct hfs_bnode *node, int off)
+{
+	u8 data;
+	// optimize later...
+	hfs_bnode_read(node, &data, off, 1);
+	return be16_to_cpu(data);
+}
+
+void hfs_bnode_read_key(struct hfs_bnode *node, void *key, int off)
+{
+	struct hfs_btree *tree;
+	int key_len;
+
+	tree = node->tree;
+	if (node->type == HFS_NODE_LEAF ||
+	    tree->attributes & HFS_TREE_VARIDXKEYS)
+		key_len = hfs_bnode_read_u16(node, off) + 2;
+	else
+		key_len = tree->max_key_len + 2;
+
+	hfs_bnode_read(node, key, off, key_len);
+}
+
+void hfs_bnode_write(struct hfs_bnode *node, void *buf, int off, int len)
+{
+	struct page **pagep;
+	int l;
+
+	off += node->page_offset;
+	pagep = node->page + (off >> PAGE_CACHE_SHIFT);
+	off &= ~PAGE_CACHE_MASK;
+
+	l = min(len, (int)PAGE_CACHE_SIZE - off);
+	memcpy(kmap(*pagep) + off, buf, l);
+	set_page_dirty(*pagep);
+	kunmap(*pagep);
+
+	while ((len -= l)) {
+		buf += l;
+		l = min(len, (int)PAGE_CACHE_SIZE);
+		memcpy(kmap(*++pagep), buf, l);
+		set_page_dirty(*pagep);
+		kunmap(*pagep);
+	}
+}
+
+void hfs_bnode_write_u16(struct hfs_bnode *node, int off, u16 data)
+{
+	data = cpu_to_be16(data);
+	// optimize later...
+	hfs_bnode_write(node, &data, off, 2);
+}
+
+void hfs_bnode_clear(struct hfs_bnode *node, int off, int len)
+{
+	struct page **pagep;
+	int l;
+
+	off += node->page_offset;
+	pagep = node->page + (off >> PAGE_CACHE_SHIFT);
+	off &= ~PAGE_CACHE_MASK;
+
+	l = min(len, (int)PAGE_CACHE_SIZE - off);
+	memset(kmap(*pagep) + off, 0, l);
+	set_page_dirty(*pagep);
+	kunmap(*pagep);
+
+	while ((len -= l)) {
+		l = min(len, (int)PAGE_CACHE_SIZE);
+		memset(kmap(*++pagep), 0, l);
+		set_page_dirty(*pagep);
+		kunmap(*pagep);
+	}
+}
+
+void hfs_bnode_copy(struct hfs_bnode *dst_node, int dst,
+		    struct hfs_bnode *src_node, int src, int len)
+{
+	struct hfs_btree *tree;
+	struct page **src_page, **dst_page;
+	int l;
+
+	dprint(DBG_BNODE_MOD, "copybytes: %u,%u,%u\n", dst, src, len);
+	if (!len)
+		return;
+	tree = src_node->tree;
+	src += src_node->page_offset;
+	dst += dst_node->page_offset;
+	src_page = src_node->page + (src >> PAGE_CACHE_SHIFT);
+	src &= ~PAGE_CACHE_MASK;
+	dst_page = dst_node->page + (dst >> PAGE_CACHE_SHIFT);
+	dst &= ~PAGE_CACHE_MASK;
+
+	if (src == dst) {
+		l = min(len, (int)PAGE_CACHE_SIZE - src);
+		memcpy(kmap(*dst_page) + src, kmap(*src_page) + src, l);
+		kunmap(*src_page);
+		set_page_dirty(*dst_page);
+		kunmap(*dst_page);
+
+		while ((len -= l)) {
+			l = min(len, (int)PAGE_CACHE_SIZE);
+			memcpy(kmap(*++dst_page), kmap(*++src_page), l);
+			kunmap(*src_page);
+			set_page_dirty(*dst_page);
+			kunmap(*dst_page);
+		}
+	} else {
+		void *src_ptr, *dst_ptr;
+
+		do {
+			src_ptr = kmap(*src_page) + src;
+			dst_ptr = kmap(*dst_page) + dst;
+			if (PAGE_CACHE_SIZE - src < PAGE_CACHE_SIZE - dst) {
+				l = PAGE_CACHE_SIZE - src;
+				src = 0;
+				dst += l;
+			} else {
+				l = PAGE_CACHE_SIZE - dst;
+				src += l;
+				dst = 0;
+			}
+			l = min(len, l);
+			memcpy(dst_ptr, src_ptr, l);
+			kunmap(*src_page);
+			set_page_dirty(*dst_page);
+			kunmap(*dst_page);
+			if (!dst)
+				dst_page++;
+			else
+				src_page++;
+		} while ((len -= l));
+	}
+}
+
+void hfs_bnode_move(struct hfs_bnode *node, int dst, int src, int len)
+{
+	struct page **src_page, **dst_page;
+	int l;
+
+	dprint(DBG_BNODE_MOD, "movebytes: %u,%u,%u\n", dst, src, len);
+	if (!len)
+		return;
+	src += node->page_offset;
+	dst += node->page_offset;
+	if (dst > src) {
+		src += len - 1;
+		src_page = node->page + (src >> PAGE_CACHE_SHIFT);
+		src = (src & ~PAGE_CACHE_MASK) + 1;
+		dst += len - 1;
+		dst_page = node->page + (dst >> PAGE_CACHE_SHIFT);
+		dst = (dst & ~PAGE_CACHE_MASK) + 1;
+
+		if (src == dst) {
+			while (src < len) {
+				memmove(kmap(*dst_page), kmap(*src_page), src);
+				kunmap(*src_page);
+				set_page_dirty(*dst_page);
+				kunmap(*dst_page);
+				len -= src;
+				src = PAGE_CACHE_SIZE;
+				src_page--;
+				dst_page--;
+			}
+			src -= len;
+			memmove(kmap(*dst_page) + src, kmap(*src_page) + src, len);
+			kunmap(*src_page);
+			set_page_dirty(*dst_page);
+			kunmap(*dst_page);
+		} else {
+			void *src_ptr, *dst_ptr;
+
+			do {
+				src_ptr = kmap(*src_page) + src;
+				dst_ptr = kmap(*dst_page) + dst;
+				if (src < dst) {
+					l = src;
+					src = PAGE_CACHE_SIZE;
+					dst -= l;
+				} else {
+					l = dst;
+					src -= l;
+					dst = PAGE_CACHE_SIZE;
+				}
+				l = min(len, l);
+				memmove(dst_ptr - l, src_ptr - l, l);
+				kunmap(*src_page);
+				set_page_dirty(*dst_page);
+				kunmap(*dst_page);
+				if (dst == PAGE_CACHE_SIZE)
+					dst_page--;
+				else
+					src_page--;
+			} while ((len -= l));
+		}
+	} else {
+		src_page = node->page + (src >> PAGE_CACHE_SHIFT);
+		src &= ~PAGE_CACHE_MASK;
+		dst_page = node->page + (dst >> PAGE_CACHE_SHIFT);
+		dst &= ~PAGE_CACHE_MASK;
+
+		if (src == dst) {
+			l = min(len, (int)PAGE_CACHE_SIZE - src);
+			memmove(kmap(*dst_page) + src, kmap(*src_page) + src, l);
+			kunmap(*src_page);
+			set_page_dirty(*dst_page);
+			kunmap(*dst_page);
+
+			while ((len -= l)) {
+				l = min(len, (int)PAGE_CACHE_SIZE);
+				memmove(kmap(*++dst_page), kmap(*++src_page), l);
+				kunmap(*src_page);
+				set_page_dirty(*dst_page);
+				kunmap(*dst_page);
+			}
+		} else {
+			void *src_ptr, *dst_ptr;
+
+			do {
+				src_ptr = kmap(*src_page) + src;
+				dst_ptr = kmap(*dst_page) + dst;
+				if (PAGE_CACHE_SIZE - src < PAGE_CACHE_SIZE - dst) {
+					l = PAGE_CACHE_SIZE - src;
+					src = 0;
+					dst += l;
+				} else {
+					l = PAGE_CACHE_SIZE - dst;
+					src += l;
+					dst = 0;
+				}
+				l = min(len, l);
+				memmove(dst_ptr, src_ptr, l);
+				kunmap(*src_page);
+				set_page_dirty(*dst_page);
+				kunmap(*dst_page);
+				if (!dst)
+					dst_page++;
+				else
+					src_page++;
+			} while ((len -= l));
+		}
+	}
+}
+
+void hfs_bnode_dump(struct hfs_bnode *node)
+{
+	struct hfs_bnode_desc desc;
+	u32 cnid;
+	int i, off, key_off;
+
+	dprint(DBG_BNODE_MOD, "bnode: %d\n", node->this);
+	hfs_bnode_read(node, &desc, 0, sizeof(desc));
+	dprint(DBG_BNODE_MOD, "%d, %d, %d, %d, %d\n",
+		be32_to_cpu(desc.next), be32_to_cpu(desc.prev),
+		desc.type, desc.height, be16_to_cpu(desc.num_recs));
+
+	off = node->tree->node_size - 2;
+	for (i = be16_to_cpu(desc.num_recs); i >= 0; off -= 2, i--) {
+		key_off = hfs_bnode_read_u16(node, off);
+		dprint(DBG_BNODE_MOD, " %d", key_off);
+		if (i && node->type == HFS_NODE_INDEX) {
+			int tmp;
+
+			if (node->tree->attributes & HFS_TREE_VARIDXKEYS)
+				tmp = hfs_bnode_read_u16(node, key_off) + 2;
+			else
+				tmp = node->tree->max_key_len + 2;
+			dprint(DBG_BNODE_MOD, " (%d", tmp);
+			hfs_bnode_read(node, &cnid, key_off + tmp, 4);
+			dprint(DBG_BNODE_MOD, ",%d)", be32_to_cpu(cnid));
+		} else if (i && node->type == HFS_NODE_LEAF) {
+			int tmp;
+
+			tmp = hfs_bnode_read_u16(node, key_off);
+			dprint(DBG_BNODE_MOD, " (%d)", tmp);
+		}
+	}
+	dprint(DBG_BNODE_MOD, "\n");
+}
+
+void hfs_bnode_unlink(struct hfs_bnode *node)
+{
+	struct hfs_btree *tree;
+	struct hfs_bnode *tmp;
+	u32 cnid;
+
+	tree = node->tree;
+	if (node->prev) {
+		tmp = hfs_bnode_find(tree, node->prev);
+		if (IS_ERR(tmp))
+			return;
+		tmp->next = node->next;
+		cnid = cpu_to_be32(tmp->next);
+		hfs_bnode_write(tmp, &cnid, offsetof(struct hfs_bnode_desc, next), 4);
+		hfs_bnode_put(tmp);
+	} else if (node->type == HFS_NODE_LEAF)
+		tree->leaf_head = node->next;
+
+	if (node->next) {
+		tmp = hfs_bnode_find(tree, node->next);
+		if (IS_ERR(tmp))
+			return;
+		tmp->prev = node->prev;
+		cnid = cpu_to_be32(tmp->prev);
+		hfs_bnode_write(tmp, &cnid, offsetof(struct hfs_bnode_desc, prev), 4);
+		hfs_bnode_put(tmp);
+	} else if (node->type == HFS_NODE_LEAF)
+		tree->leaf_tail = node->prev;
+
+	// move down?
+	if (!node->prev && !node->next) {
+		printk("hfs_btree_del_level\n");
+	}
+	if (!node->parent) {
+		tree->root = 0;
+		tree->depth = 0;
+	}
+	set_bit(HFS_BNODE_DELETED, &node->flags);
+}
+
+static inline int hfs_bnode_hash(u32 num)
+{
+	num = (num >> 16) + num;
+	num += num >> 8;
+	return num & (NODE_HASH_SIZE - 1);
+}
+
+struct hfs_bnode *hfs_bnode_findhash(struct hfs_btree *tree, u32 cnid)
+{
+	struct hfs_bnode *node;
+
+	if (cnid >= tree->node_count) {
+		printk("HFS+-fs: request for non-existent node %d in B*Tree\n", cnid);
+		return NULL;
+	}
+
+	for (node = tree->node_hash[hfs_bnode_hash(cnid)];
+	     node; node = node->next_hash) {
+		if (node->this == cnid) {
+			return node;
+		}
+	}
+	return NULL;
+}
+
+static struct hfs_bnode *__hfs_bnode_create(struct hfs_btree *tree, u32 cnid)
+{
+	struct super_block *sb;
+	struct hfs_bnode *node, *node2;
+	struct address_space *mapping;
+	struct page *page;
+	int size, block, i, hash;
+	loff_t off;
+
+	if (cnid >= tree->node_count) {
+		printk("HFS+-fs: request for non-existent node %d in B*Tree\n", cnid);
+		return NULL;
+	}
+
+	sb = tree->inode->i_sb;
+	size = sizeof(struct hfs_bnode) + tree->pages_per_bnode *
+		sizeof(struct page *);
+	node = kmalloc(size, GFP_KERNEL);
+	if (!node)
+		return NULL;
+	memset(node, 0, size);
+	node->tree = tree;
+	node->this = cnid;
+	set_bit(HFS_BNODE_NEW, &node->flags);
+	atomic_set(&node->refcnt, 1);
+	dprint(DBG_BNODE_REFS, "new_node(%d:%d): 1\n",
+	       node->tree->cnid, node->this);
+	init_waitqueue_head(&node->lock_wq);
+	spin_lock(&tree->hash_lock);
+	node2 = hfs_bnode_findhash(tree, cnid);
+	if (!node2) {
+		hash = hfs_bnode_hash(cnid);
+		node->next_hash = tree->node_hash[hash];
+		tree->node_hash[hash] = node;
+		tree->node_hash_cnt++;
+	} else {
+		spin_unlock(&tree->hash_lock);
+		kfree(node);
+		wait_event(node2->lock_wq, !test_bit(HFS_BNODE_NEW, &node2->flags));
+		return node2;
+	}
+	spin_unlock(&tree->hash_lock);
+
+	mapping = tree->inode->i_mapping;
+	off = (loff_t)cnid << tree->node_size_shift;
+	block = off >> PAGE_CACHE_SHIFT;
+	node->page_offset = off & ~PAGE_CACHE_MASK;
+	for (i = 0; i < tree->pages_per_bnode; block++, i++) {
+		page = read_cache_page(mapping, block, (filler_t *)mapping->a_ops->readpage, NULL);
+		if (IS_ERR(page))
+			goto fail;
+#if !REF_PAGES
+		page_cache_release(page);
+#endif
+		node->page[i] = page;
+	}
+
+	return node;
+fail:
+	set_bit(HFS_BNODE_ERROR, &node->flags);
+	return node;
+}
+
+void hfs_bnode_unhash(struct hfs_bnode *node)
+{
+	struct hfs_bnode **p;
+
+	dprint(DBG_BNODE_REFS, "remove_node(%d:%d): %d\n",
+		node->tree->cnid, node->this, atomic_read(&node->refcnt));
+	for (p = &node->tree->node_hash[hfs_bnode_hash(node->this)];
+	     *p && *p != node; p = &(*p)->next_hash)
+		;
+	if (!*p)
+		BUG();
+	*p = node->next_hash;
+	node->tree->node_hash_cnt--;
+}
+
+/* Load a particular node out of a tree */
+struct hfs_bnode *hfs_bnode_find(struct hfs_btree *tree, u32 num)
+{
+	struct hfs_bnode *node;
+	struct hfs_bnode_desc *desc;
+	int i, rec_off, off, next_off;
+	int entry_size, key_size;
+
+	spin_lock(&tree->hash_lock);
+	node = hfs_bnode_findhash(tree, num);
+	if (node) {
+		hfs_bnode_get(node);
+		spin_unlock(&tree->hash_lock);
+		wait_event(node->lock_wq, !test_bit(HFS_BNODE_NEW, &node->flags));
+		return node;
+	}
+	spin_unlock(&tree->hash_lock);
+	node = __hfs_bnode_create(tree, num);
+	if (!node)
+		return ERR_PTR(-ENOMEM);
+	if (!test_bit(HFS_BNODE_NEW, &node->flags))
+		return node;
+
+	desc = (struct hfs_bnode_desc *)(kmap(node->page[0]) + node->page_offset);
+	node->prev = be32_to_cpu(desc->prev);
+	node->next = be32_to_cpu(desc->next);
+	node->num_recs = be16_to_cpu(desc->num_recs);
+	node->type = desc->type;
+	node->height = desc->height;
+	kunmap(node->page[0]);
+
+	switch (node->type) {
+	case HFS_NODE_HEADER:
+	case HFS_NODE_MAP:
+		if (node->height != 0)
+			goto node_error;
+		break;
+	case HFS_NODE_LEAF:
+		if (node->height != 1)
+			goto node_error;
+		break;
+	case HFS_NODE_INDEX:
+		if (node->height <= 1 || node->height > tree->depth)
+			goto node_error;
+		break;
+	default:
+		goto node_error;
+	}
+
+	rec_off = tree->node_size - 2;
+	off = hfs_bnode_read_u16(node, rec_off);
+	if (off != sizeof(struct hfs_bnode_desc))
+		goto node_error;
+	for (i = 1; i <= node->num_recs; off = next_off, i++) {
+		rec_off -= 2;
+		next_off = hfs_bnode_read_u16(node, rec_off);
+		if (next_off <= off ||
+		    next_off > tree->node_size ||
+		    next_off & 1)
+			goto node_error;
+		entry_size = next_off - off;
+		if (node->type != HFS_NODE_INDEX &&
+		    node->type != HFS_NODE_LEAF)
+			continue;
+		key_size = hfs_bnode_read_u16(node, off) + 2;
+		if (key_size >= entry_size || key_size & 1)
+			goto node_error;
+	}
+	clear_bit(HFS_BNODE_NEW, &node->flags);
+	wake_up(&node->lock_wq);
+	return node;
+
+node_error:
+	set_bit(HFS_BNODE_ERROR, &node->flags);
+	clear_bit(HFS_BNODE_NEW, &node->flags);
+	wake_up(&node->lock_wq);
+	hfs_bnode_put(node);
+	return ERR_PTR(-EIO);
+}
+
+void hfs_bnode_free(struct hfs_bnode *node)
+{
+	//int i;
+
+	//for (i = 0; i < node->tree->pages_per_bnode; i++)
+	//	if (node->page[i])
+	//		page_cache_release(node->page[i]);
+	kfree(node);
+}
+
+struct hfs_bnode *hfs_bnode_create(struct hfs_btree *tree, u32 num)
+{
+	struct hfs_bnode *node;
+	struct page **pagep;
+	int i;
+
+	spin_lock(&tree->hash_lock);
+	node = hfs_bnode_findhash(tree, num);
+	spin_unlock(&tree->hash_lock);
+	if (node) {
+		printk("new node %u already hashed?\n", num);
+		BUG();
+	}
+	node = __hfs_bnode_create(tree, num);
+	if (!node)
+		return ERR_PTR(-ENOMEM);
+
+	pagep = node->page;
+	memset(kmap(*pagep) + node->page_offset, 0,
+	       min((int)PAGE_CACHE_SIZE, (int)tree->node_size));
+	set_page_dirty(*pagep);
+	kunmap(*pagep);
+	for (i = 1; i < tree->pages_per_bnode; i++) {
+		memset(kmap(*++pagep), 0, PAGE_CACHE_SIZE);
+		set_page_dirty(*pagep);
+		kunmap(*pagep);
+	}
+	clear_bit(HFS_BNODE_NEW, &node->flags);
+	wake_up(&node->lock_wq);
+
+	return node;
+}
+
+void hfs_bnode_get(struct hfs_bnode *node)
+{
+	if (node) {
+		atomic_inc(&node->refcnt);
+#if REF_PAGES
+		{
+		int i;
+		for (i = 0; i < node->tree->pages_per_bnode; i++)
+			get_page(node->page[i]);
+		}
+#endif
+		dprint(DBG_BNODE_REFS, "get_node(%d:%d): %d\n",
+		       node->tree->cnid, node->this, atomic_read(&node->refcnt));
+	}
+}
+
+/* Dispose of resources used by a node */
+void hfs_bnode_put(struct hfs_bnode *node)
+{
+	if (node) {
+		struct hfs_btree *tree = node->tree;
+		int i;
+
+		dprint(DBG_BNODE_REFS, "put_node(%d:%d): %d\n",
+		       node->tree->cnid, node->this, atomic_read(&node->refcnt));
+		if (!atomic_read(&node->refcnt))
+			BUG();
+		if (!atomic_dec_and_lock(&node->refcnt, &tree->hash_lock)) {
+#if REF_PAGES
+			for (i = 0; i < tree->pages_per_bnode; i++)
+				put_page(node->page[i]);
+#endif
+			return;
+		}
+		for (i = 0; i < tree->pages_per_bnode; i++) {
+			mark_page_accessed(node->page[i]);
+#if REF_PAGES
+			put_page(node->page[i]);
+#endif
+		}
+
+		if (test_bit(HFS_BNODE_DELETED, &node->flags)) {
+			hfs_bnode_unhash(node);
+			spin_unlock(&tree->hash_lock);
+			hfs_bmap_free(node);
+			hfs_bnode_free(node);
+			return;
+		}
+		spin_unlock(&tree->hash_lock);
+	}
+}
+
+void hfsplus_lock_bnode(struct hfs_bnode *node)
+{
+	wait_event(node->lock_wq, !test_and_set_bit(HFS_BNODE_LOCK, &node->flags));
+}
+
+void hfsplus_unlock_bnode(struct hfs_bnode *node)
+{
+	clear_bit(HFS_BNODE_LOCK, &node->flags);
+	if (waitqueue_active(&node->lock_wq))
+		wake_up(&node->lock_wq);
+}
--- diff/fs/hfsplus/brec.c	1970-01-01 01:00:00.000000000 +0100
+++ source/fs/hfsplus/brec.c	2004-02-23 13:56:46.000000000 +0000
@@ -0,0 +1,487 @@
+/*
+ *  linux/fs/hfsplus/brec.c
+ *
+ * Copyright (C) 2001
+ * Brad Boyer (flar@allandria.com)
+ * (C) 2003 Ardis Technologies <roman@ardistech.com>
+ *
+ * Handle individual btree records
+ */
+
+#include "hfsplus_fs.h"
+#include "hfsplus_raw.h"
+
+/* Get the length and offset of the given record in the given node */
+u16 hfs_brec_lenoff(struct hfs_bnode *node, u16 rec, u16 *off)
+{
+	u16 retval[2];
+	u16 dataoff;
+
+	dataoff = node->tree->node_size - (rec + 2) * 2;
+	hfs_bnode_read(node, retval, dataoff, 4);
+	*off = be16_to_cpu(retval[1]);
+	return be16_to_cpu(retval[0]) - *off;
+}
+
+/* Get the length of the key from a keyed record */
+u16 hfs_brec_keylen(struct hfs_bnode *node, u16 rec)
+{
+	u16 retval, recoff;
+
+	if (node->type != HFS_NODE_INDEX && node->type != HFS_NODE_LEAF)
+		return 0;
+
+	if ((node->type == HFS_NODE_INDEX) &&
+	   !(node->tree->attributes & HFS_TREE_VARIDXKEYS)) {
+		retval = node->tree->max_key_len;
+	} else {
+		recoff = hfs_bnode_read_u16(node, node->tree->node_size - (rec + 1) * 2);
+		if (!recoff)
+			return 0;
+		if (node->tree->attributes & HFS_TREE_BIGKEYS)
+			retval = hfs_bnode_read_u16(node, recoff) + 2;
+		else
+			retval = (hfs_bnode_read_u8(node, recoff) | 1) + 1;
+	}
+	return retval;
+}
+
+int hfs_brec_insert(struct hfs_find_data *fd, void *entry, int entry_len)
+{
+	struct hfs_btree *tree;
+	struct hfs_bnode *node, *new_node;
+	int size, key_len, rec;
+	int data_off, end_off;
+	int idx_rec_off, data_rec_off, end_rec_off;
+	u32 cnid;
+
+	tree = fd->tree;
+	if (!fd->bnode) {
+		if (!tree->root)
+			hfs_btree_inc_height(tree);
+		fd->bnode = hfs_bnode_find(tree, tree->leaf_head);
+		if (IS_ERR(fd->bnode))
+			return PTR_ERR(fd->bnode);
+		fd->record = -1;
+	}
+	new_node = NULL;
+	key_len = be16_to_cpu(fd->search_key->key_len) + 2;
+again:
+	/* new record idx and complete record size */
+	rec = fd->record + 1;
+	size = key_len + entry_len;
+
+	node = fd->bnode;
+	hfs_bnode_dump(node);
+	/* get last offset */
+	end_rec_off = tree->node_size - (node->num_recs + 1) * 2;
+	end_off = hfs_bnode_read_u16(node, end_rec_off);
+	end_rec_off -= 2;
+	dprint(DBG_BNODE_MOD, "insert_rec: %d, %d, %d, %d\n", rec, size, end_off, end_rec_off);
+	if (size > end_rec_off - end_off) {
+		if (new_node)
+			panic("not enough room!\n");
+		new_node = hfs_bnode_split(fd);
+		if (IS_ERR(new_node))
+			return PTR_ERR(new_node);
+		goto again;
+	}
+	if (node->type == HFS_NODE_LEAF) {
+		tree->leaf_count++;
+		mark_inode_dirty(tree->inode);
+	}
+	node->num_recs++;
+	/* write new last offset */
+	hfs_bnode_write_u16(node, offsetof(struct hfs_bnode_desc, num_recs), node->num_recs);
+	hfs_bnode_write_u16(node, end_rec_off, end_off + size);
+	data_off = end_off;
+	data_rec_off = end_rec_off + 2;
+	idx_rec_off = tree->node_size - (rec + 1) * 2;
+	if (idx_rec_off == data_rec_off)
+		goto skip;
+	/* move all following entries */
+	do {
+		data_off = hfs_bnode_read_u16(node, data_rec_off + 2);
+		hfs_bnode_write_u16(node, data_rec_off, data_off + size);
+		data_rec_off += 2;
+	} while (data_rec_off < idx_rec_off);
+
+	/* move data away */
+	hfs_bnode_move(node, data_off + size, data_off,
+		       end_off - data_off);
+
+skip:
+	hfs_bnode_write(node, fd->search_key, data_off, key_len);
+	hfs_bnode_write(node, entry, data_off + key_len, entry_len);
+	hfs_bnode_dump(node);
+
+	if (new_node) {
+		/* update parent key if we inserted a key
+		 * at the start of the first node
+		 */
+		if (!rec && new_node != node)
+			hfs_brec_update_parent(fd);
+
+		hfs_bnode_put(fd->bnode);
+		if (!new_node->parent) {
+			hfs_btree_inc_height(tree);
+			new_node->parent = tree->root;
+		}
+		fd->bnode = hfs_bnode_find(tree, new_node->parent);
+
+		/* create index data entry */
+		cnid = cpu_to_be32(new_node->this);
+		entry = &cnid;
+		entry_len = sizeof(cnid);
+
+		/* get index key */
+		hfs_bnode_read_key(new_node, fd->search_key, 14);
+		__hfs_brec_find(fd->bnode, fd);
+
+		hfs_bnode_put(new_node);
+		new_node = NULL;
+
+		if (tree->attributes & HFS_TREE_VARIDXKEYS)
+			key_len = be16_to_cpu(fd->search_key->key_len) + 2;
+		else {
+			fd->search_key->key_len = tree->max_key_len;
+			key_len = tree->max_key_len + 2;
+		}
+		goto again;
+	}
+
+	if (!rec)
+		hfs_brec_update_parent(fd);
+
+	return 0;
+}
+
+int hfs_brec_remove(struct hfs_find_data *fd)
+{
+	struct hfs_btree *tree;
+	struct hfs_bnode *node, *parent;
+	int end_off, rec_off, data_off, size;
+
+	tree = fd->tree;
+	node = fd->bnode;
+again:
+	rec_off = tree->node_size - (fd->record + 2) * 2;
+	end_off = tree->node_size - (node->num_recs + 1) * 2;
+
+	if (node->type == HFS_NODE_LEAF) {
+		tree->leaf_count--;
+		mark_inode_dirty(tree->inode);
+	}
+	hfs_bnode_dump(node);
+	dprint(DBG_BNODE_MOD, "remove_rec: %d, %d\n", fd->record, fd->keylength + fd->entrylength);
+	if (!--node->num_recs) {
+		hfs_bnode_unlink(node);
+		if (!node->parent)
+			return 0;
+		parent = hfs_bnode_find(tree, node->parent);
+		if (IS_ERR(parent))
+			return PTR_ERR(parent);
+		hfs_bnode_put(node);
+		node = fd->bnode = parent;
+
+		__hfs_brec_find(node, fd);
+		goto again;
+	}
+	hfs_bnode_write_u16(node, offsetof(struct hfs_bnode_desc, num_recs), node->num_recs);
+
+	if (rec_off == end_off)
+		goto skip;
+	size = fd->keylength + fd->entrylength;
+
+	do {
+		data_off = hfs_bnode_read_u16(node, rec_off);
+		hfs_bnode_write_u16(node, rec_off + 2, data_off - size);
+		rec_off -= 2;
+	} while (rec_off >= end_off);
+
+	/* fill hole */
+	hfs_bnode_move(node, fd->keyoffset, fd->keyoffset + size,
+		       data_off - fd->keyoffset - size);
+skip:
+	hfs_bnode_dump(node);
+	if (!fd->record)
+		hfs_brec_update_parent(fd);
+	return 0;
+}
+
+struct hfs_bnode *hfs_bnode_split(struct hfs_find_data *fd)
+{
+	struct hfs_btree *tree;
+	struct hfs_bnode *node, *new_node;
+	struct hfs_bnode_desc node_desc;
+	int num_recs, new_rec_off, new_off, old_rec_off;
+	int data_start, data_end, size;
+
+	tree = fd->tree;
+	node = fd->bnode;
+	new_node = hfs_bmap_alloc(tree);
+	if (IS_ERR(new_node))
+		return new_node;
+	hfs_bnode_get(node);
+	dprint(DBG_BNODE_MOD, "split_nodes: %d - %d - %d\n",
+		node->this, new_node->this, node->next);
+	new_node->next = node->next;
+	new_node->prev = node->this;
+	new_node->parent = node->parent;
+	new_node->type = node->type;
+	new_node->height = node->height;
+
+	size = tree->node_size / 2 - node->num_recs * 2 - 14;
+	old_rec_off = tree->node_size - 4;
+	num_recs = 1;
+	for (;;) {
+		data_start = hfs_bnode_read_u16(node, old_rec_off);
+		if (data_start > size)
+			break;
+		old_rec_off -= 2;
+		if (++num_recs < node->num_recs)
+			continue;
+		/* panic? */
+		hfs_bnode_put(node);
+		hfs_bnode_put(new_node);
+		return ERR_PTR(-ENOSPC);
+	}
+
+	if (fd->record + 1 < num_recs) {
+		/* new record is in the lower half,
+		 * so leave some more space there
+		 */
+		old_rec_off += 2;
+		num_recs--;
+		data_start = hfs_bnode_read_u16(node, old_rec_off);
+	} else {
+		hfs_bnode_put(node);
+		hfs_bnode_get(new_node);
+		fd->bnode = new_node;
+		fd->record -= num_recs;
+		fd->keyoffset -= data_start - 14;
+		fd->entryoffset -= data_start - 14;
+	}
+	new_node->num_recs = node->num_recs - num_recs;
+	node->num_recs = num_recs;
+
+	new_rec_off = tree->node_size - 2;
+	new_off = 14;
+	size = data_start - new_off;
+	num_recs = new_node->num_recs;
+	data_end = data_start;
+	while (num_recs) {
+		hfs_bnode_write_u16(new_node, new_rec_off, new_off);
+		old_rec_off -= 2;
+		new_rec_off -= 2;
+		data_end = hfs_bnode_read_u16(node, old_rec_off);
+		new_off = data_end - size;
+		num_recs--;
+	}
+	hfs_bnode_write_u16(new_node, new_rec_off, new_off);
+	hfs_bnode_copy(new_node, 14, node, data_start, data_end - data_start);
+
+	/* update new bnode header */
+	node_desc.next = cpu_to_be32(new_node->next);
+	node_desc.prev = cpu_to_be32(new_node->prev);
+	node_desc.type = new_node->type;
+	node_desc.height = new_node->height;
+	node_desc.num_recs = cpu_to_be16(new_node->num_recs);
+	node_desc.reserved = 0;
+	hfs_bnode_write(new_node, &node_desc, 0, sizeof(node_desc));
+
+	/* update previous bnode header */
+	node->next = new_node->this;
+	hfs_bnode_read(node, &node_desc, 0, sizeof(node_desc));
+	node_desc.next = cpu_to_be32(node->next);
+	node_desc.num_recs = cpu_to_be16(node->num_recs);
+	hfs_bnode_write(node, &node_desc, 0, sizeof(node_desc));
+
+	/* update next bnode header */
+	if (new_node->next) {
+		struct hfs_bnode *next_node = hfs_bnode_find(tree, new_node->next);
+		next_node->prev = new_node->this;
+		hfs_bnode_read(next_node, &node_desc, 0, sizeof(node_desc));
+		node_desc.prev = cpu_to_be32(next_node->prev);
+		hfs_bnode_write(next_node, &node_desc, 0, sizeof(node_desc));
+		hfs_bnode_put(next_node);
+	} else if (node->this == tree->leaf_tail) {
+		/* if there is no next node, this might be the new tail */
+		tree->leaf_tail = new_node->this;
+		mark_inode_dirty(tree->inode);
+	}
+
+	hfs_bnode_dump(node);
+	hfs_bnode_dump(new_node);
+	hfs_bnode_put(node);
+
+	return new_node;
+}
+
+int hfs_brec_update_parent(struct hfs_find_data *fd)
+{
+	struct hfs_btree *tree;
+	struct hfs_bnode *node, *new_node, *parent;
+	int newkeylen, diff;
+	int rec, rec_off, end_rec_off;
+	int start_off, end_off;
+
+	tree = fd->tree;
+	node = fd->bnode;
+	new_node = NULL;
+	if (!node->parent)
+		return 0;
+
+again:
+	parent = hfs_bnode_find(tree, node->parent);
+	if (IS_ERR(parent))
+		return PTR_ERR(parent);
+	__hfs_brec_find(parent, fd);
+	hfs_bnode_dump(parent);
+	rec = fd->record;
+
+	/* size difference between old and new key */
+	if (tree->attributes & HFS_TREE_VARIDXKEYS)
+		newkeylen = hfs_bnode_read_u16(node, 14) + 2;
+	else
+		fd->keylength = newkeylen = tree->max_key_len + 2;
+	dprint(DBG_BNODE_MOD, "update_rec: %d, %d, %d\n", rec, fd->keylength, newkeylen);
+
+	rec_off = tree->node_size - (rec + 2) * 2;
+	end_rec_off = tree->node_size - (parent->num_recs + 1) * 2;
+	diff = newkeylen - fd->keylength;
+	if (!diff)
+		goto skip;
+	if (diff > 0) {
+		end_off = hfs_bnode_read_u16(parent, end_rec_off);
+		if (end_rec_off - end_off < diff) {
+
+			printk("splitting index node...\n");
+			fd->bnode = parent;
+			new_node = hfs_bnode_split(fd);
+			if (IS_ERR(new_node))
+				return PTR_ERR(new_node);
+			parent = fd->bnode;
+			rec = fd->record;
+			rec_off = tree->node_size - (rec + 2) * 2;
+			end_rec_off = tree->node_size - (parent->num_recs + 1) * 2;
+		}
+	}
+
+	end_off = start_off = hfs_bnode_read_u16(parent, rec_off);
+	hfs_bnode_write_u16(parent, rec_off, start_off + diff);
+	start_off -= 4;	/* move previous cnid too */
+
+	while (rec_off > end_rec_off) {
+		rec_off -= 2;
+		end_off = hfs_bnode_read_u16(parent, rec_off);
+		hfs_bnode_write_u16(parent, rec_off, end_off + diff);
+	}
+	hfs_bnode_move(parent, start_off + diff, start_off,
+		       end_off - start_off);
+skip:
+	hfs_bnode_copy(parent, fd->keyoffset, node, 14, newkeylen);
+	hfs_bnode_dump(parent);
+
+	hfs_bnode_put(node);
+	node = parent;
+
+	if (new_node) {
+		u32 cnid;
+
+		fd->bnode = hfs_bnode_find(tree, new_node->parent);
+		/* create index key and entry */
+		hfs_bnode_read_key(new_node, fd->search_key, 14);
+		cnid = cpu_to_be32(new_node->this);
+
+		__hfs_brec_find(fd->bnode, fd);
+		hfs_brec_insert(fd, &cnid, sizeof(cnid));
+		hfs_bnode_put(fd->bnode);
+		hfs_bnode_put(new_node);
+
+		if (!rec) {
+			if (new_node == node)
+				goto out;
+			/* restore search_key */
+			hfs_bnode_read_key(node, fd->search_key, 14);
+		}
+	}
+
+	if (!rec && node->parent)
+		goto again;
+out:
+	fd->bnode = node;
+	return 0;
+}
+
+int hfs_btree_inc_height(struct hfs_btree *tree)
+{
+	struct hfs_bnode *node, *new_node;
+	struct hfs_bnode_desc node_desc;
+	int key_size, rec;
+	u32 cnid;
+
+	node = NULL;
+	if (tree->root) {
+		node = hfs_bnode_find(tree, tree->root);
+		if (IS_ERR(node))
+			return PTR_ERR(node);
+	}
+	new_node = hfs_bmap_alloc(tree);
+	if (IS_ERR(new_node)) {
+		hfs_bnode_put(node);
+		return PTR_ERR(new_node);
+	}
+
+	tree->root = new_node->this;
+	if (!tree->depth) {
+		tree->leaf_head = tree->leaf_tail = new_node->this;
+		new_node->type = HFS_NODE_LEAF;
+		new_node->num_recs = 0;
+	} else {
+		new_node->type = HFS_NODE_INDEX;
+		new_node->num_recs = 1;
+	}
+	new_node->parent = 0;
+	new_node->next = 0;
+	new_node->prev = 0;
+	new_node->height = ++tree->depth;
+
+	node_desc.next = cpu_to_be32(new_node->next);
+	node_desc.prev = cpu_to_be32(new_node->prev);
+	node_desc.type = new_node->type;
+	node_desc.height = new_node->height;
+	node_desc.num_recs = cpu_to_be16(new_node->num_recs);
+	node_desc.reserved = 0;
+	hfs_bnode_write(new_node, &node_desc, 0, sizeof(node_desc));
+
+	rec = tree->node_size - 2;
+	hfs_bnode_write_u16(new_node, rec, 14);
+
+	if (node) {
+		/* insert old root idx into new root */
+		node->parent = tree->root;
+		if (node->type == HFS_NODE_LEAF ||
+		    tree->attributes & HFS_TREE_VARIDXKEYS)
+			key_size = hfs_bnode_read_u16(node, 14) + 2;
+		else
+			key_size = tree->max_key_len + 2;
+		hfs_bnode_copy(new_node, 14, node, 14, key_size);
+
+		if (!(tree->attributes & HFS_TREE_VARIDXKEYS)) {
+			key_size = tree->max_key_len + 2;
+			hfs_bnode_write_u16(new_node, 14, tree->max_key_len);
+		}
+		cnid = cpu_to_be32(node->this);
+		hfs_bnode_write(new_node, &cnid, 14 + key_size, 4);
+
+		rec -= 2;
+		hfs_bnode_write_u16(new_node, rec, 14 + key_size + 4);
+
+		hfs_bnode_put(node);
+	}
+	hfs_bnode_put(new_node);
+	mark_inode_dirty(tree->inode);
+
+	return 0;
+}
--- diff/fs/hfsplus/btree.c	1970-01-01 01:00:00.000000000 +0100
+++ source/fs/hfsplus/btree.c	2004-02-23 13:56:46.000000000 +0000
@@ -0,0 +1,319 @@
+/*
+ *  linux/fs/hfsplus/btree.c
+ *
+ * Copyright (C) 2001
+ * Brad Boyer (flar@allandria.com)
+ * (C) 2003 Ardis Technologies <roman@ardistech.com>
+ *
+ * Handle opening/closing btree
+ */
+
+#include <linux/slab.h>
+#include <linux/pagemap.h>
+
+#include "hfsplus_fs.h"
+#include "hfsplus_raw.h"
+
+
+/* Get a reference to a B*Tree and do some initial checks */
+struct hfs_btree *hfs_btree_open(struct super_block *sb, u32 id)
+{
+	struct hfs_btree *tree;
+	struct hfs_btree_header_rec *head;
+	struct address_space *mapping;
+	struct page *page;
+	unsigned int shift, size;
+
+	tree = kmalloc(sizeof(*tree), GFP_KERNEL);
+	if (!tree)
+		return NULL;
+	memset(tree, 0, sizeof(*tree));
+
+	init_MUTEX(&tree->tree_lock);
+	spin_lock_init(&tree->hash_lock);
+	/* Set the correct compare function */
+	tree->sb = sb;
+	tree->cnid = id;
+	if (id == HFSPLUS_EXT_CNID) {
+		tree->keycmp = hfsplus_ext_cmp_key;
+	} else if (id == HFSPLUS_CAT_CNID) {
+		tree->keycmp = hfsplus_cat_cmp_key;
+	} else {
+		printk("HFS+-fs: unknown B*Tree requested\n");
+		goto free_tree;
+	}
+	tree->inode = iget(sb, id);
+	if (!tree->inode)
+		goto free_tree;
+
+	mapping = tree->inode->i_mapping;
+	page = read_cache_page(mapping, 0, (filler_t *)mapping->a_ops->readpage, NULL);
+	if (IS_ERR(page))
+		goto free_tree;
+
+	/* Load the header */
+	head = (struct hfs_btree_header_rec *)(kmap(page) + sizeof(struct hfs_bnode_desc));
+	tree->root = be32_to_cpu(head->root);
+	tree->leaf_count = be32_to_cpu(head->leaf_count);
+	tree->leaf_head = be32_to_cpu(head->leaf_head);
+	tree->leaf_tail = be32_to_cpu(head->leaf_tail);
+	tree->node_count = be32_to_cpu(head->node_count);
+	tree->free_nodes = be32_to_cpu(head->free_nodes);
+	tree->attributes = be32_to_cpu(head->attributes);
+	tree->node_size = be16_to_cpu(head->node_size);
+	tree->max_key_len = be16_to_cpu(head->max_key_len);
+	tree->depth = be16_to_cpu(head->depth);
+
+	size = tree->node_size;
+	if (!size || size & (size - 1))
+		goto fail_page;
+	if (!tree->node_count)
+		goto fail_page;
+	for (shift = 0; size >>= 1; shift += 1)
+		;
+	tree->node_size_shift = shift;
+
+	tree->pages_per_bnode = (tree->node_size + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
+
+	kunmap(page);
+	page_cache_release(page);
+	return tree;
+
+ fail_page:
+	tree->inode->i_mapping->a_ops = &hfsplus_aops;
+	page_cache_release(page);
+ free_tree:
+	iput(tree->inode);
+	kfree(tree);
+	return NULL;
+}
+
+/* Release resources used by a btree */
+void hfs_btree_close(struct hfs_btree *tree)
+{
+	struct hfs_bnode *node;
+	int i;
+
+	if (!tree)
+		return;
+
+	for (i = 0; i < NODE_HASH_SIZE; i++) {
+		while ((node = tree->node_hash[i])) {
+			tree->node_hash[i] = node->next_hash;
+			if (atomic_read(&node->refcnt))
+				printk("HFS+: node %d:%d still has %d user(s)!\n",
+					node->tree->cnid, node->this, atomic_read(&node->refcnt));
+			hfs_bnode_free(node);
+			tree->node_hash_cnt--;
+		}
+	}
+	iput(tree->inode);
+	kfree(tree);
+}
+
+void hfs_btree_write(struct hfs_btree *tree)
+{
+	struct hfs_btree_header_rec *head;
+	struct hfs_bnode *node;
+	struct page *page;
+
+	node = hfs_bnode_find(tree, 0);
+	if (IS_ERR(node))
+		/* panic? */
+		return;
+	/* Load the header */
+	page = node->page[0];
+	head = (struct hfs_btree_header_rec *)(kmap(page) + sizeof(struct hfs_bnode_desc));
+
+	head->root = cpu_to_be32(tree->root);
+	head->leaf_count = cpu_to_be32(tree->leaf_count);
+	head->leaf_head = cpu_to_be32(tree->leaf_head);
+	head->leaf_tail = cpu_to_be32(tree->leaf_tail);
+	head->node_count = cpu_to_be32(tree->node_count);
+	head->free_nodes = cpu_to_be32(tree->free_nodes);
+	head->attributes = cpu_to_be32(tree->attributes);
+	head->depth = cpu_to_be16(tree->depth);
+
+	kunmap(page);
+	set_page_dirty(page);
+	hfs_bnode_put(node);
+}
+
+static struct hfs_bnode *hfs_bmap_new_bmap(struct hfs_bnode *prev, u32 idx)
+{
+	struct hfs_btree *tree = prev->tree;
+	struct hfs_bnode *node;
+	struct hfs_bnode_desc desc;
+	u32 cnid;
+
+	node = hfs_bnode_create(tree, idx);
+	if (IS_ERR(node))
+		return node;
+
+	tree->free_nodes--;
+	prev->next = idx;
+	cnid = cpu_to_be32(idx);
+	hfs_bnode_write(prev, &cnid, offsetof(struct hfs_bnode_desc, next), 4);
+
+	node->type = HFS_NODE_MAP;
+	node->num_recs = 1;
+	hfs_bnode_clear(node, 0, tree->node_size);
+	desc.next = 0;
+	desc.prev = 0;
+	desc.type = HFS_NODE_MAP;
+	desc.height = 0;
+	desc.num_recs = cpu_to_be16(1);
+	desc.reserved = 0;
+	hfs_bnode_write(node, &desc, 0, sizeof(desc));
+	hfs_bnode_write_u16(node, 14, 0x8000);
+	hfs_bnode_write_u16(node, tree->node_size - 2, 14);
+	hfs_bnode_write_u16(node, tree->node_size - 4, tree->node_size - 6);
+
+	return node;
+}
+
+struct hfs_bnode *hfs_bmap_alloc(struct hfs_btree *tree)
+{
+	struct hfs_bnode *node, *next_node;
+	struct page **pagep;
+	u32 nidx, idx;
+	u16 off, len;
+	u8 *data, byte, m;
+	int i;
+
+	while (!tree->free_nodes) {
+		struct inode *inode = tree->inode;
+		u32 count;
+		int res;
+
+		res = hfsplus_file_extend(inode);
+		if (res)
+			return ERR_PTR(res);
+		inode->i_blocks = HFSPLUS_I(inode).alloc_blocks <<
+				  HFSPLUS_SB(tree->sb).fs_shift;
+		HFSPLUS_I(inode).phys_size = inode->i_size =
+			(loff_t)inode->i_blocks << tree->sb->s_blocksize_bits;
+		count = inode->i_size >> tree->node_size_shift;
+		tree->free_nodes = count - tree->node_count;
+		tree->node_count = count;
+	}
+
+	nidx = 0;
+	node = hfs_bnode_find(tree, nidx);
+	if (IS_ERR(node))
+		return node;
+	len = hfs_brec_lenoff(node, 2, &off);
+
+	off += node->page_offset;
+	pagep = node->page + (off >> PAGE_CACHE_SHIFT);
+	data = kmap(*pagep);
+	off &= ~PAGE_CACHE_MASK;
+	idx = 0;
+
+	for (;;) {
+		while (len) {
+			byte = data[off];
+			if (byte != 0xff) {
+				for (m = 0x80, i = 0; i < 8; m >>= 1, i++) {
+					if (!(byte & m)) {
+						idx += i;
+						data[off] |= m;
+						set_page_dirty(*pagep);
+						kunmap(*pagep);
+						tree->free_nodes--;
+						mark_inode_dirty(tree->inode);
+						hfs_bnode_put(node);
+						if (!idx) {
+							printk("unexpected idx %u (%u)\n", idx, node->this);
+							BUG();
+						}
+						return hfs_bnode_create(tree, idx);
+					}
+				}
+			}
+			if (++off >= PAGE_CACHE_SIZE) {
+				kunmap(*pagep);
+				data = kmap(*++pagep);
+				off = 0;
+			}
+			idx += 8;
+			len--;
+		}
+		kunmap(*pagep);
+		nidx = node->next;
+		if (!nidx) {
+			printk("create new bmap node...\n");
+			next_node = hfs_bmap_new_bmap(node, idx);
+		} else
+			next_node = hfs_bnode_find(tree, nidx);
+		hfs_bnode_put(node);
+		if (IS_ERR(next_node))
+			return next_node;
+		node = next_node;
+
+		len = hfs_brec_lenoff(node, 0, &off);
+		off += node->page_offset;
+		pagep = node->page + (off >> PAGE_CACHE_SHIFT);
+		data = kmap(*pagep);
+		off &= ~PAGE_CACHE_MASK;
+	}
+}
+
+void hfs_bmap_free(struct hfs_bnode *node)
+{
+	struct hfs_btree *tree;
+	struct page *page;
+	u16 off, len;
+	u32 nidx;
+	u8 *data, byte, m;
+
+	dprint(DBG_BNODE_MOD, "btree_free_node: %u\n", node->this);
+	if (!node->this)
+		BUG();
+	tree = node->tree;
+	nidx = node->this;
+	node = hfs_bnode_find(tree, 0);
+	if (IS_ERR(node))
+		return;
+	len = hfs_brec_lenoff(node, 2, &off);
+	while (nidx >= len * 8) {
+		u32 i;
+
+		nidx -= len * 8;
+		i = node->next;
+		hfs_bnode_put(node);
+		if (!i) {
+			/* panic */;
+			printk("HFS: unable to free bnode %u. bmap not found!\n", node->this);
+			return;
+		}
+		node = hfs_bnode_find(tree, i);
+		if (IS_ERR(node))
+			return;
+		if (node->type != HFS_NODE_MAP) {
+			/* panic */;
+			printk("HFS: invalid bmap found! (%u,%d)\n", node->this, node->type);
+			hfs_bnode_put(node);
+			return;
+		}
+		len = hfs_brec_lenoff(node, 0, &off);
+	}
+	off += node->page_offset + nidx / 8;
+	page = node->page[off >> PAGE_CACHE_SHIFT];
+	data = kmap(page);
+	off &= ~PAGE_CACHE_MASK;
+	m = 1 << (~nidx & 7);
+	byte = data[off];
+	if (!(byte & m)) {
+		printk("HFS: trying to free free bnode %u(%d)\n", node->this, node->type);
+		kunmap(page);
+		hfs_bnode_put(node);
+		return;
+	}
+	data[off] = byte & ~m;
+	set_page_dirty(page);
+	kunmap(page);
+	hfs_bnode_put(node);
+	tree->free_nodes++;
+	mark_inode_dirty(tree->inode);
+}
--- diff/fs/hfsplus/catalog.c	1970-01-01 01:00:00.000000000 +0100
+++ source/fs/hfsplus/catalog.c	2004-02-23 13:56:46.000000000 +0000
@@ -0,0 +1,344 @@
+/*
+ *  linux/fs/hfsplus/catalog.c
+ *
+ * Copyright (C) 2001
+ * Brad Boyer (flar@allandria.com)
+ * (C) 2003 Ardis Technologies <roman@ardistech.com>
+ *
+ * Handling of catalog records
+ */
+
+#include <linux/sched.h>
+
+#include "hfsplus_fs.h"
+#include "hfsplus_raw.h"
+
+int hfsplus_cat_cmp_key(hfsplus_btree_key *k1, hfsplus_btree_key *k2)
+{
+	u32 k1p, k2p;
+
+	k1p = k1->cat.parent;
+	k2p = k2->cat.parent;
+	if (k1p != k2p)
+		return be32_to_cpu(k1p) < be32_to_cpu(k2p) ? -1 : 1;
+
+	return hfsplus_unistrcmp(&k1->cat.name, &k2->cat.name);
+}
+
+void hfsplus_cat_build_key(hfsplus_btree_key *key, u32 parent,
+			  struct qstr *str)
+{
+	int len;
+
+	key->cat.parent = cpu_to_be32(parent);
+	if (str) {
+		hfsplus_asc2uni(&key->cat.name, str->name, str->len);
+		len = be16_to_cpu(key->cat.name.length);
+	} else
+		len = key->cat.name.length = 0;
+	key->key_len = cpu_to_be16(6 + 2 * len);
+}
+
+static void hfsplus_cat_build_key_uni(hfsplus_btree_key *key, u32 parent,
+				      struct hfsplus_unistr *name)
+{
+	int ustrlen;
+
+	ustrlen = be16_to_cpu(name->length);
+	key->cat.parent = cpu_to_be32(parent);
+	key->cat.name.length = cpu_to_be16(ustrlen);
+	ustrlen *= 2;
+	memcpy(key->cat.name.unicode, name->unicode, ustrlen);
+	key->key_len = cpu_to_be16(6 + ustrlen);
+}
+
+static void hfsplus_set_perms(struct inode *inode, struct hfsplus_perm *perms)
+{
+	if (inode->i_flags & S_IMMUTABLE)
+		perms->rootflags |= HFSPLUS_FLG_IMMUTABLE;
+	else
+		perms->rootflags &= ~HFSPLUS_FLG_IMMUTABLE;
+	if (inode->i_flags & S_APPEND)
+		perms->rootflags |= HFSPLUS_FLG_APPEND;
+	else
+		perms->rootflags &= ~HFSPLUS_FLG_APPEND;
+	HFSPLUS_I(inode).rootflags = perms->rootflags;
+	HFSPLUS_I(inode).userflags = perms->userflags;
+	perms->mode = cpu_to_be16(inode->i_mode);
+	perms->owner = cpu_to_be32(inode->i_uid);
+	perms->group = cpu_to_be32(inode->i_gid);
+}
+
+static int hfsplus_cat_build_record(hfsplus_cat_entry *entry, u32 cnid, struct inode *inode)
+{
+	if (S_ISDIR(inode->i_mode)) {
+		struct hfsplus_cat_folder *folder;
+
+		folder = &entry->folder;
+		memset(folder, 0, sizeof(*folder));
+		folder->type = cpu_to_be16(HFSPLUS_FOLDER);
+		folder->id = cpu_to_be32(inode->i_ino);
+		folder->create_date = folder->content_mod_date =
+			folder->attribute_mod_date = folder->access_date = hfsp_now2mt();
+		hfsplus_set_perms(inode, &folder->permissions);
+		if (inode == HFSPLUS_SB(inode->i_sb).hidden_dir)
+			/* invisible and namelocked */
+			folder->user_info.frFlags = cpu_to_be16(0x5000);
+		return sizeof(*folder);
+	} else {
+		struct hfsplus_cat_file *file;
+
+		file = &entry->file;
+		memset(file, 0, sizeof(*file));
+		file->type = cpu_to_be16(HFSPLUS_FILE);
+		file->flags = cpu_to_be16(HFSPLUS_FILE_THREAD_EXISTS);
+		file->id = cpu_to_be32(cnid);
+		file->create_date = file->content_mod_date =
+			file->attribute_mod_date = file->access_date = hfsp_now2mt();
+		if (cnid == inode->i_ino) {
+			hfsplus_set_perms(inode, &file->permissions);
+			file->user_info.fdType = cpu_to_be32(HFSPLUS_SB(inode->i_sb).type);
+			file->user_info.fdCreator = cpu_to_be32(HFSPLUS_SB(inode->i_sb).creator);
+			if ((file->permissions.rootflags | file->permissions.userflags) & HFSPLUS_FLG_IMMUTABLE)
+				file->flags |= cpu_to_be16(HFSPLUS_FILE_LOCKED);
+		} else {
+			file->user_info.fdType = cpu_to_be32(HFSP_HARDLINK_TYPE);
+			file->user_info.fdCreator = cpu_to_be32(HFSP_HFSPLUS_CREATOR);
+			file->user_info.fdFlags = cpu_to_be16(0x100);
+			file->permissions.dev = cpu_to_be32(HFSPLUS_I(inode).dev);
+		}
+		return sizeof(*file);
+	}
+}
+
+static int hfsplus_fill_cat_thread(hfsplus_cat_entry *entry, int type,
+				   u32 parentid, struct qstr *str)
+{
+	entry->type = cpu_to_be16(type);
+	entry->thread.reserved = 0;
+	entry->thread.parentID = cpu_to_be32(parentid);
+	hfsplus_asc2uni(&entry->thread.nodeName, str->name, str->len);
+	return 10 + be16_to_cpu(entry->thread.nodeName.length) * 2;
+}
+
+/* Try to get a catalog entry for given catalog id */
+int hfsplus_find_cat(struct super_block *sb, u32 cnid,
+		     struct hfs_find_data *fd)
+{
+	hfsplus_cat_entry tmp;
+	int err;
+	u16 type;
+
+	hfsplus_cat_build_key(fd->search_key, cnid, NULL);
+	err = hfs_brec_read(fd, &tmp, sizeof(hfsplus_cat_entry));
+	if (err)
+		return err;
+
+	type = be16_to_cpu(tmp.type);
+	if (type != HFSPLUS_FOLDER_THREAD && type != HFSPLUS_FILE_THREAD) {
+		printk("HFS+-fs: Found bad thread record in catalog\n");
+		return -EIO;
+	}
+
+	hfsplus_cat_build_key_uni(fd->search_key, be32_to_cpu(tmp.thread.parentID),
+				 &tmp.thread.nodeName);
+	return hfs_brec_find(fd);
+}
+
+int hfsplus_create_cat(u32 cnid, struct inode *dir, struct qstr *str, struct inode *inode)
+{
+	struct hfs_find_data fd;
+	struct super_block *sb;
+	hfsplus_cat_entry entry;
+	int entry_size;
+	int err;
+
+	dprint(DBG_CAT_MOD, "create_cat: %s,%u(%d)\n", str->name, cnid, inode->i_nlink);
+	sb = dir->i_sb;
+	hfs_find_init(HFSPLUS_SB(sb).cat_tree, &fd);
+
+	hfsplus_cat_build_key(fd.search_key, cnid, NULL);
+	entry_size = hfsplus_fill_cat_thread(&entry, S_ISDIR(inode->i_mode) ?
+			HFSPLUS_FOLDER_THREAD : HFSPLUS_FILE_THREAD,
+			dir->i_ino, str);
+	err = hfs_brec_find(&fd);
+	if (err != -ENOENT) {
+		if (!err)
+			err = -EEXIST;
+		goto out;
+	}
+	err = hfs_brec_insert(&fd, &entry, entry_size);
+	if (err)
+		goto out;
+
+	hfsplus_cat_build_key(fd.search_key, dir->i_ino, str);
+	entry_size = hfsplus_cat_build_record(&entry, cnid, inode);
+	err = hfs_brec_find(&fd);
+	if (err != -ENOENT) {
+		/* panic? */
+		if (!err)
+			err = -EEXIST;
+		goto out;
+	}
+	err = hfs_brec_insert(&fd, &entry, entry_size);
+	if (!err) {
+		dir->i_size++;
+		mark_inode_dirty(dir);
+	}
+out:
+	hfs_find_exit(&fd);
+
+	return err;
+}
+
+int hfsplus_delete_cat(u32 cnid, struct inode *dir, struct qstr *str)
+{
+	struct super_block *sb;
+	struct hfs_find_data fd;
+	struct hfsplus_fork_raw fork;
+	struct list_head *pos;
+	int err, off;
+	u16 type;
+
+	dprint(DBG_CAT_MOD, "delete_cat: %s,%u\n", str ? str->name : NULL, cnid);
+	sb = dir->i_sb;
+	hfs_find_init(HFSPLUS_SB(sb).cat_tree, &fd);
+
+	if (!str) {
+		int len;
+
+		hfsplus_cat_build_key(fd.search_key, cnid, NULL);
+		err = hfs_brec_find(&fd);
+		if (err)
+			goto out;
+
+		off = fd.entryoffset + offsetof(struct hfsplus_cat_thread, nodeName);
+		fd.search_key->cat.parent = cpu_to_be32(dir->i_ino);
+		hfs_bnode_read(fd.bnode, &fd.search_key->cat.name.length, off, 2);
+		len = be16_to_cpu(fd.search_key->cat.name.length) * 2;
+		hfs_bnode_read(fd.bnode, &fd.search_key->cat.name.unicode, off + 2, len);
+		fd.search_key->key_len = cpu_to_be16(6 + len);
+	} else
+		hfsplus_cat_build_key(fd.search_key, dir->i_ino, str);
+
+	err = hfs_brec_find(&fd);
+	if (err)
+		goto out;
+
+	type = hfs_bnode_read_u16(fd.bnode, fd.entryoffset);
+	if (type == HFSPLUS_FILE) {
+#if 0
+		off = fd.entryoffset + offsetof(hfsplus_cat_file, data_fork);
+		hfs_bnode_read(fd.bnode, &fork, off, sizeof(fork));
+		hfsplus_free_fork(sb, cnid, &fork, HFSPLUS_TYPE_DATA);
+#endif
+
+		off = fd.entryoffset + offsetof(struct hfsplus_cat_file, rsrc_fork);
+		hfs_bnode_read(fd.bnode, &fork, off, sizeof(fork));
+		hfsplus_free_fork(sb, cnid, &fork, HFSPLUS_TYPE_RSRC);
+	}
+
+	list_for_each(pos, &HFSPLUS_I(dir).open_dir_list) {
+		struct hfsplus_readdir_data *rd =
+			list_entry(pos, struct hfsplus_readdir_data, list);
+		if (fd.tree->keycmp(fd.search_key, (void *)&rd->key) < 0)
+			rd->file->f_pos--;
+	}
+
+	err = hfs_brec_remove(&fd);
+	if (err)
+		goto out;
+
+	hfsplus_cat_build_key(fd.search_key, cnid, NULL);
+	err = hfs_brec_find(&fd);
+	if (err)
+		goto out;
+
+	err = hfs_brec_remove(&fd);
+	if (err)
+		goto out;
+
+	dir->i_size--;
+	mark_inode_dirty(dir);
+out:
+	hfs_find_exit(&fd);
+
+	return err;
+}
+
+int hfsplus_rename_cat(u32 cnid,
+		       struct inode *src_dir, struct qstr *src_name,
+		       struct inode *dst_dir, struct qstr *dst_name)
+{
+	struct super_block *sb;
+	struct hfs_find_data src_fd, dst_fd;
+	hfsplus_cat_entry entry;
+	int entry_size, type;
+	int err = 0;
+
+	dprint(DBG_CAT_MOD, "rename_cat: %u - %lu,%s - %lu,%s\n", cnid, src_dir->i_ino, src_name->name,
+		dst_dir->i_ino, dst_name->name);
+	sb = src_dir->i_sb;
+	hfs_find_init(HFSPLUS_SB(sb).cat_tree, &src_fd);
+	dst_fd = src_fd;
+
+	/* find the old dir entry and read the data */
+	hfsplus_cat_build_key(src_fd.search_key, src_dir->i_ino, src_name);
+	err = hfs_brec_find(&src_fd);
+	if (err)
+		goto out;
+
+	hfs_bnode_read(src_fd.bnode, &entry, src_fd.entryoffset,
+				src_fd.entrylength);
+
+	/* create new dir entry with the data from the old entry */
+	hfsplus_cat_build_key(dst_fd.search_key, dst_dir->i_ino, dst_name);
+	err = hfs_brec_find(&dst_fd);
+	if (err != -ENOENT) {
+		if (!err)
+			err = -EEXIST;
+		goto out;
+	}
+
+	err = hfs_brec_insert(&dst_fd, &entry, src_fd.entrylength);
+	if (err)
+		goto out;
+	dst_dir->i_size++;
+	mark_inode_dirty(dst_dir);
+
+	/* finally remove the old entry */
+	hfsplus_cat_build_key(src_fd.search_key, src_dir->i_ino, src_name);
+	err = hfs_brec_find(&src_fd);
+	if (err)
+		goto out;
+	err = hfs_brec_remove(&src_fd);
+	if (err)
+		goto out;
+	src_dir->i_size--;
+	mark_inode_dirty(src_dir);
+
+	/* remove old thread entry */
+	hfsplus_cat_build_key(src_fd.search_key, cnid, NULL);
+	err = hfs_brec_find(&src_fd);
+	if (err)
+		goto out;
+	type = hfs_bnode_read_u16(src_fd.bnode, src_fd.entryoffset);
+	err = hfs_brec_remove(&src_fd);
+	if (err)
+		goto out;
+
+	/* create new thread entry */
+	hfsplus_cat_build_key(dst_fd.search_key, cnid, NULL);
+	entry_size = hfsplus_fill_cat_thread(&entry, type, dst_dir->i_ino, dst_name);
+	err = hfs_brec_find(&dst_fd);
+	if (err != -ENOENT) {
+		if (!err)
+			err = -EEXIST;
+		goto out;
+	}
+	err = hfs_brec_insert(&dst_fd, &entry, entry_size);
+out:
+	hfs_bnode_put(dst_fd.bnode);
+	hfs_find_exit(&src_fd);
+	return err;
+}
--- diff/fs/hfsplus/dir.c	1970-01-01 01:00:00.000000000 +0100
+++ source/fs/hfsplus/dir.c	2004-02-23 13:56:46.000000000 +0000
@@ -0,0 +1,471 @@
+/*
+ *  linux/fs/hfsplus/dir.c
+ *
+ * Copyright (C) 2001
+ * Brad Boyer (flar@allandria.com)
+ * (C) 2003 Ardis Technologies <roman@ardistech.com>
+ *
+ * Handling of directories
+ */
+
+#include <linux/errno.h>
+#include <linux/fs.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/random.h>
+#include <linux/version.h>
+
+#include "hfsplus_fs.h"
+#include "hfsplus_raw.h"
+
+/* Find the entry inside dir named dentry->d_name */
+static struct dentry *hfsplus_lookup(struct inode *dir, struct dentry *dentry,
+				     struct nameidata *nd)
+{
+	struct inode *inode = NULL;
+	struct hfs_find_data fd;
+	struct super_block *sb;
+	hfsplus_cat_entry entry;
+	int err;
+	u32 cnid, linkid = 0;
+	u16 type;
+
+	sb = dir->i_sb;
+	dentry->d_fsdata = NULL;
+	hfs_find_init(HFSPLUS_SB(sb).cat_tree, &fd);
+	hfsplus_cat_build_key(fd.search_key, dir->i_ino, &dentry->d_name);
+again:
+	err = hfs_brec_read(&fd, &entry, sizeof(entry));
+	if (err) {
+		if (err == -ENOENT) {
+			hfs_find_exit(&fd);
+			/* No such entry */
+			inode = NULL;
+			goto out;
+		}
+		goto fail;
+	}
+	type = be16_to_cpu(entry.type);
+	if (type == HFSPLUS_FOLDER) {
+		if (fd.entrylength < sizeof(struct hfsplus_cat_folder)) {
+			err = -EIO;
+			goto fail;
+		}
+		cnid = be32_to_cpu(entry.folder.id);
+	} else if (type == HFSPLUS_FILE) {
+		if (fd.entrylength < sizeof(struct hfsplus_cat_file)) {
+			err = -EIO;
+			goto fail;
+		}
+		cnid = be32_to_cpu(entry.file.id);
+		if (entry.file.user_info.fdType == cpu_to_be32(HFSP_HARDLINK_TYPE) &&
+		    entry.file.user_info.fdCreator == cpu_to_be32(HFSP_HFSPLUS_CREATOR)) {
+			struct qstr str;
+			char name[32];
+
+			if (dentry->d_fsdata) {
+				err = -ENOENT;
+				inode = NULL;
+				goto out;
+			}
+			dentry->d_fsdata = (void *)(unsigned long)cnid;
+			linkid = be32_to_cpu(entry.file.permissions.dev);
+			str.len = sprintf(name, "iNode%d", linkid);
+			str.name = name;
+			hfsplus_cat_build_key(fd.search_key, HFSPLUS_SB(sb).hidden_dir->i_ino, &str);
+			goto again;
+		} else if (!dentry->d_fsdata)
+			dentry->d_fsdata = (void *)(unsigned long)cnid;
+	} else {
+		printk("HFS+-fs: Illegal catalog entry type in lookup\n");
+		err = -EIO;
+		goto fail;
+	}
+	hfs_find_exit(&fd);
+	inode = iget(dir->i_sb, cnid);
+	if (!inode)
+		return ERR_PTR(-EACCES);
+	if (S_ISREG(inode->i_mode))
+		HFSPLUS_I(inode).dev = linkid;
+out:
+	d_add(dentry, inode);
+	return NULL;
+fail:
+	hfs_find_exit(&fd);
+	return ERR_PTR(err);
+}
+
+static int hfsplus_readdir(struct file *filp, void *dirent, filldir_t filldir)
+{
+	struct inode *inode = filp->f_dentry->d_inode;
+	struct super_block *sb = inode->i_sb;
+	int len, err;
+	char strbuf[HFSPLUS_MAX_STRLEN + 1];
+	hfsplus_cat_entry entry;
+	struct hfs_find_data fd;
+	struct hfsplus_readdir_data *rd;
+	u16 type;
+
+	if (filp->f_pos >= inode->i_size)
+		return 0;
+
+	hfs_find_init(HFSPLUS_SB(sb).cat_tree, &fd);
+	hfsplus_cat_build_key(fd.search_key, inode->i_ino, NULL);
+	err = hfs_brec_find(&fd);
+	if (err)
+		goto out;
+
+	switch ((u32)filp->f_pos) {
+	case 0:
+		/* This is completely artificial... */
+		if (filldir(dirent, ".", 1, 0, inode->i_ino, DT_DIR))
+			goto out;
+		filp->f_pos++;
+		/* fall through */
+	case 1:
+		hfs_bnode_read(fd.bnode, &entry, fd.entryoffset, fd.entrylength);
+		if (be16_to_cpu(entry.type) != HFSPLUS_FOLDER_THREAD) {
+			printk("HFS+-fs: bad catalog folder thread\n");
+			err = -EIO;
+			goto out;
+		}
+		if (fd.entrylength < HFSPLUS_MIN_THREAD_SZ) {
+			printk("HFS+-fs: truncated catalog thread\n");
+			err = -EIO;
+			goto out;
+		}
+		if (filldir(dirent, "..", 2, 1,
+			    be32_to_cpu(entry.thread.parentID), DT_DIR))
+			goto out;
+		filp->f_pos++;
+		/* fall through */
+	default:
+		if (filp->f_pos >= inode->i_size)
+			goto out;
+		err = hfs_brec_goto(&fd, filp->f_pos - 1);
+		if (err)
+			goto out;
+	}
+
+	for (;;) {
+		if (be32_to_cpu(fd.key->cat.parent) != inode->i_ino) {
+			printk("HFS+-fs: walked past end of dir\n");
+			err = -EIO;
+			goto out;
+		}
+		hfs_bnode_read(fd.bnode, &entry, fd.entryoffset, fd.entrylength);
+		type = be16_to_cpu(entry.type);
+		len = HFSPLUS_MAX_STRLEN;
+		err = hfsplus_uni2asc(&fd.key->cat.name, strbuf, &len);
+		if (err)
+			goto out;
+		if (type == HFSPLUS_FOLDER) {
+			if (fd.entrylength < sizeof(struct hfsplus_cat_folder)) {
+				printk("HFS+-fs: small dir entry\n");
+				err = -EIO;
+				goto out;
+			}
+			if (HFSPLUS_SB(sb).hidden_dir &&
+			    HFSPLUS_SB(sb).hidden_dir->i_ino == be32_to_cpu(entry.folder.id))
+				goto next;
+			if (filldir(dirent, strbuf, len, filp->f_pos,
+				    be32_to_cpu(entry.folder.id), DT_DIR))
+				break;
+		} else if (type == HFSPLUS_FILE) {
+			if (fd.entrylength < sizeof(struct hfsplus_cat_file)) {
+				printk("HFS+-fs: small file entry\n");
+				err = -EIO;
+				goto out;
+			}
+			if (filldir(dirent, strbuf, len, filp->f_pos,
+				    be32_to_cpu(entry.file.id), DT_REG))
+				break;
+		} else {
+			printk("HFS+-fs: bad catalog entry type\n");
+			err = -EIO;
+			goto out;
+		}
+	next:
+		filp->f_pos++;
+		if (filp->f_pos >= inode->i_size)
+			goto out;
+		err = hfs_brec_goto(&fd, 1);
+		if (err)
+			goto out;
+	}
+	rd = filp->private_data;
+	if (!rd) {
+		rd = kmalloc(sizeof(struct hfsplus_readdir_data), GFP_KERNEL);
+		if (!rd) {
+			err = -ENOMEM;
+			goto out;
+		}
+		filp->private_data = rd;
+		rd->file = filp;
+		list_add(&rd->list, &HFSPLUS_I(inode).open_dir_list);
+	}
+	memcpy(&rd->key, fd.key, sizeof(struct hfsplus_cat_key));
+out:
+	hfs_find_exit(&fd);
+	return err;
+}
+
+static int hfsplus_dir_release(struct inode *inode, struct file *file)
+{
+	struct hfsplus_readdir_data *rd = file->private_data;
+	if (rd) {
+		list_del(&rd->list);
+		kfree(rd);
+	}
+	return 0;
+}
+
+int hfsplus_create(struct inode *dir, struct dentry *dentry, int mode,
+		   struct nameidata *nd)
+{
+	struct inode *inode;
+	int res;
+
+	inode = hfsplus_new_inode(dir->i_sb, mode);
+	if (!inode)
+		return -ENOSPC;
+
+	res = hfsplus_create_cat(inode->i_ino, dir, &dentry->d_name, inode);
+	if (res) {
+		inode->i_nlink = 0;
+		iput(inode);
+		return res;
+	}
+	dentry->d_fsdata = (void *)inode->i_ino;
+	d_instantiate(dentry, inode);
+	mark_inode_dirty(inode);
+	return 0;
+}
+
+int hfsplus_link(struct dentry *src_dentry, struct inode *dst_dir, struct dentry *dst_dentry)
+{
+	struct super_block *sb = dst_dir->i_sb;
+	struct inode *inode = src_dentry->d_inode;
+	struct inode *src_dir = src_dentry->d_parent->d_inode;
+	struct qstr str;
+	char name[32];
+	u32 cnid, id;
+	int res;
+
+	if (HFSPLUS_IS_RSRC(inode))
+		return -EPERM;
+
+	if (inode->i_ino == (u32)(unsigned long)src_dentry->d_fsdata) {
+		for (;;) {
+			get_random_bytes(&id, sizeof(cnid));
+			id &= 0x3fffffff;
+			str.name = name;
+			str.len = sprintf(name, "iNode%d", id);
+			res = hfsplus_rename_cat(inode->i_ino,
+						 src_dir, &src_dentry->d_name,
+						 HFSPLUS_SB(sb).hidden_dir, &str);
+			if (!res)
+				break;
+			if (res != -EEXIST)
+				return res;
+		}
+		HFSPLUS_I(inode).dev = id;
+		cnid = HFSPLUS_SB(sb).next_cnid++;
+		src_dentry->d_fsdata = (void *)(unsigned long)cnid;
+		res = hfsplus_create_cat(cnid, src_dir, &src_dentry->d_name, inode);
+		if (res)
+			/* panic? */
+			return res;
+		HFSPLUS_SB(sb).file_count++;
+	}
+	cnid = HFSPLUS_SB(sb).next_cnid++;
+	res = hfsplus_create_cat(cnid, dst_dir, &dst_dentry->d_name, inode);
+	if (res)
+		return res;
+
+	inode->i_nlink++;
+	dst_dentry->d_fsdata = (void *)(unsigned long)cnid;
+	d_instantiate(dst_dentry, inode);
+	atomic_inc(&inode->i_count);
+	inode->i_ctime = CURRENT_TIME;
+	mark_inode_dirty(inode);
+	HFSPLUS_SB(sb).file_count++;
+	sb->s_dirt = 1;
+
+	return 0;
+}
+
+int hfsplus_unlink(struct inode *dir, struct dentry *dentry)
+{
+	struct super_block *sb = dir->i_sb;
+	struct inode *inode = dentry->d_inode;
+	struct qstr str;
+	char name[32];
+	u32 cnid;
+	int res;
+
+	if (HFSPLUS_IS_RSRC(inode))
+		return -EPERM;
+
+	cnid = (u32)(unsigned long)dentry->d_fsdata;
+	if (inode->i_ino == cnid &&
+	    atomic_read(&HFSPLUS_I(inode).opencnt)) {
+		str.name = name;
+		str.len = sprintf(name, "temp%lu", inode->i_ino);
+		res = hfsplus_rename_cat(inode->i_ino,
+					 dir, &dentry->d_name,
+					 HFSPLUS_SB(sb).hidden_dir, &str);
+		if (!res)
+			inode->i_flags |= S_DEAD;
+		return res;
+	}
+	res = hfsplus_delete_cat(cnid, dir, &dentry->d_name);
+	if (res)
+		return res;
+
+	inode->i_nlink--;
+	hfsplus_delete_inode(inode);
+	if (inode->i_ino != cnid && !inode->i_nlink) {
+		if (!atomic_read(&HFSPLUS_I(inode).opencnt)) {
+			res = hfsplus_delete_cat(inode->i_ino, HFSPLUS_SB(sb).hidden_dir, NULL);
+			if (!res)
+				hfsplus_delete_inode(inode);
+		} else
+			inode->i_flags |= S_DEAD;
+	}
+	inode->i_ctime = CURRENT_TIME;
+	mark_inode_dirty(inode);
+
+	return res;
+}
+
+int hfsplus_mkdir(struct inode *dir, struct dentry *dentry, int mode)
+{
+	struct inode *inode;
+	int res;
+
+	inode = hfsplus_new_inode(dir->i_sb, S_IFDIR | mode);
+	if (!inode)
+		return -ENOSPC;
+
+	res = hfsplus_create_cat(inode->i_ino, dir, &dentry->d_name, inode);
+	if (res) {
+		inode->i_nlink = 0;
+		iput(inode);
+		return res;
+	}
+	d_instantiate(dentry, inode);
+	mark_inode_dirty(inode);
+	return 0;
+}
+
+int hfsplus_rmdir(struct inode *dir, struct dentry *dentry)
+{
+	struct inode *inode;
+	int res;
+
+	inode = dentry->d_inode;
+	if (inode->i_size != 2)
+		return -ENOTEMPTY;
+	res = hfsplus_delete_cat(inode->i_ino, dir, &dentry->d_name);
+	if (res)
+		return res;
+	inode->i_nlink = 0;
+	inode->i_ctime = CURRENT_TIME;
+	hfsplus_delete_inode(inode);
+	mark_inode_dirty(inode);
+	return 0;
+}
+
+int hfsplus_symlink(struct inode *dir, struct dentry *dentry, const char *symname)
+{
+	struct super_block *sb;
+	struct inode *inode;
+	int res;
+
+	sb = dir->i_sb;
+	inode = hfsplus_new_inode(sb, S_IFLNK | S_IRWXUGO);
+	if (!inode)
+		return -ENOSPC;
+
+	res = page_symlink(inode, symname, strlen(symname) + 1);
+	if (res) {
+		inode->i_nlink = 0;
+		iput (inode);
+		return res;
+	}
+
+	mark_inode_dirty(inode);
+	res = hfsplus_create_cat(inode->i_ino, dir, &dentry->d_name, inode);
+
+	if (!res) {
+		d_instantiate(dentry, inode);
+		mark_inode_dirty(inode);
+	}
+
+	return res;
+}
+
+int hfsplus_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t rdev)
+{
+	struct super_block *sb;
+	struct inode *inode;
+	int res;
+
+	sb = dir->i_sb;
+	inode = hfsplus_new_inode(sb, mode);
+	if (!inode)
+		return -ENOSPC;
+
+	res = hfsplus_create_cat(inode->i_ino, dir, &dentry->d_name, inode);
+	if (res) {
+		inode->i_nlink = 0;
+		iput(inode);
+		return res;
+	}
+	init_special_inode(inode, mode, rdev);
+	d_instantiate(dentry, inode);
+	mark_inode_dirty(inode);
+
+	return 0;
+}
+
+int hfsplus_rename(struct inode *old_dir, struct dentry *old_dentry,
+		   struct inode *new_dir, struct dentry *new_dentry)
+{
+	int res;
+
+	/* Unlink destination if it already exists */
+	if (new_dentry->d_inode) {
+		res = hfsplus_unlink(new_dir, new_dentry);
+		if (res)
+			return res;
+	}
+
+	res = hfsplus_rename_cat((u32)(unsigned long)old_dentry->d_fsdata,
+				 old_dir, &old_dentry->d_name,
+				 new_dir, &new_dentry->d_name);
+	if (!res)
+		new_dentry->d_fsdata = old_dentry->d_fsdata;
+	return res;
+}
+
+struct inode_operations hfsplus_dir_inode_operations = {
+	.lookup		= hfsplus_lookup,
+	.create		= hfsplus_create,
+	.link		= hfsplus_link,
+	.unlink		= hfsplus_unlink,
+	.mkdir		= hfsplus_mkdir,
+	.rmdir		= hfsplus_rmdir,
+	.symlink	= hfsplus_symlink,
+	.mknod		= hfsplus_mknod,
+	.rename		= hfsplus_rename,
+};
+
+struct file_operations hfsplus_dir_operations = {
+	.read		= generic_read_dir,
+	.readdir	= hfsplus_readdir,
+	.ioctl          = hfsplus_ioctl,
+	.llseek		= generic_file_llseek,
+	.release	= hfsplus_dir_release,
+};
--- diff/fs/hfsplus/extents.c	1970-01-01 01:00:00.000000000 +0100
+++ source/fs/hfsplus/extents.c	2004-02-23 13:56:46.000000000 +0000
@@ -0,0 +1,502 @@
+/*
+ *  linux/fs/hfsplus/extents.c
+ *
+ * Copyright (C) 2001
+ * Brad Boyer (flar@allandria.com)
+ * (C) 2003 Ardis Technologies <roman@ardistech.com>
+ *
+ * Handling of Extents both in catalog and extents overflow trees
+ */
+
+#include <linux/errno.h>
+#include <linux/fs.h>
+#include <linux/pagemap.h>
+#include <linux/version.h>
+
+#include "hfsplus_fs.h"
+#include "hfsplus_raw.h"
+
+/* Compare two extents keys, returns 0 on same, pos/neg for difference */
+int hfsplus_ext_cmp_key(hfsplus_btree_key *k1, hfsplus_btree_key *k2)
+{
+	u32 k1id, k2id;
+	u32 k1s, k2s;
+
+	k1id = k1->ext.cnid;
+	k2id = k2->ext.cnid;
+	if (k1id != k2id)
+		return be32_to_cpu(k1id) < be32_to_cpu(k2id) ? -1 : 1;
+
+	if (k1->ext.fork_type != k2->ext.fork_type)
+		return k1->ext.fork_type < k2->ext.fork_type ? -1 : 1;
+
+	k1s = k1->ext.start_block;
+	k2s = k2->ext.start_block;
+	if (k1s == k2s)
+		return 0;
+	return be32_to_cpu(k1s) < be32_to_cpu(k2s) ? -1 : 1;
+}
+
+void hfsplus_ext_build_key(hfsplus_btree_key *key, u32 cnid,
+			  u32 block, u8 type)
+{
+	key->key_len = cpu_to_be16(HFSPLUS_EXT_KEYLEN - 2);
+	key->ext.cnid = cpu_to_be32(cnid);
+	key->ext.start_block = cpu_to_be32(block);
+	key->ext.fork_type = type;
+	key->ext.pad = 0;
+}
+
+static u32 hfsplus_ext_find_block(struct hfsplus_extent *ext, u32 off)
+{
+	int i;
+	u32 count;
+
+	for (i = 0; i < 8; ext++, i++) {
+		count = be32_to_cpu(ext->block_count);
+		if (off < count)
+			return be32_to_cpu(ext->start_block) + off;
+		off -= count;
+	}
+	/* panic? */
+	return 0;
+}
+
+static int hfsplus_ext_block_count(struct hfsplus_extent *ext)
+{
+	int i;
+	u32 count = 0;
+
+	for (i = 0; i < 8; ext++, i++)
+		count += be32_to_cpu(ext->block_count);
+	return count;
+}
+
+static u32 hfsplus_ext_lastblock(struct hfsplus_extent *ext)
+{
+	int i;
+
+	ext += 7;
+	for (i = 0; i < 7; ext--, i++)
+		if (ext->block_count)
+			break;
+	return be32_to_cpu(ext->start_block) + be32_to_cpu(ext->block_count);
+}
+
+static void __hfsplus_ext_write_extent(struct inode *inode, struct hfs_find_data *fd)
+{
+	int res;
+
+	hfsplus_ext_build_key(fd->search_key, inode->i_ino, HFSPLUS_I(inode).cached_start,
+			      HFSPLUS_IS_RSRC(inode) ?  HFSPLUS_TYPE_RSRC : HFSPLUS_TYPE_DATA);
+	res = hfs_brec_find(fd);
+	if (HFSPLUS_I(inode).flags & HFSPLUS_FLG_EXT_NEW) {
+		if (res != -ENOENT)
+			return;
+		hfs_brec_insert(fd, HFSPLUS_I(inode).cached_extents, sizeof(hfsplus_extent_rec));
+		HFSPLUS_I(inode).flags &= ~(HFSPLUS_FLG_EXT_DIRTY | HFSPLUS_FLG_EXT_NEW);
+	} else {
+		if (res)
+			return;
+		hfs_bnode_write(fd->bnode, HFSPLUS_I(inode).cached_extents, fd->entryoffset, fd->entrylength);
+		HFSPLUS_I(inode).flags &= ~HFSPLUS_FLG_EXT_DIRTY;
+	}
+}
+
+void hfsplus_ext_write_extent(struct inode *inode)
+{
+	if (HFSPLUS_I(inode).flags & HFSPLUS_FLG_EXT_DIRTY) {
+		struct hfs_find_data fd;
+
+		hfs_find_init(HFSPLUS_SB(inode->i_sb).ext_tree, &fd);
+		__hfsplus_ext_write_extent(inode, &fd);
+		hfs_find_exit(&fd);
+	}
+}
+
+static inline int __hfsplus_ext_read_extent(struct hfs_find_data *fd,
+					    struct hfsplus_extent *extent,
+					    u32 cnid, u32 block, u8 type)
+{
+	int res;
+
+	hfsplus_ext_build_key(fd->search_key, cnid, block, type);
+	fd->key->ext.cnid = 0;
+	res = hfs_brec_find(fd);
+	if (res && res != -ENOENT)
+		return res;
+	if (fd->key->ext.cnid != fd->search_key->ext.cnid ||
+	    fd->key->ext.fork_type != fd->search_key->ext.fork_type)
+		return -ENOENT;
+	if (fd->entrylength != sizeof(hfsplus_extent_rec))
+		return -EIO;
+	hfs_bnode_read(fd->bnode, extent, fd->entryoffset, sizeof(hfsplus_extent_rec));
+	return 0;
+}
+
+static inline int __hfsplus_ext_cache_extent(struct hfs_find_data *fd, struct inode *inode, u32 block)
+{
+	int res;
+
+	if (HFSPLUS_I(inode).flags & HFSPLUS_FLG_EXT_DIRTY)
+		__hfsplus_ext_write_extent(inode, fd);
+
+	res = __hfsplus_ext_read_extent(fd, HFSPLUS_I(inode).cached_extents, inode->i_ino,
+					block, HFSPLUS_IS_RSRC(inode) ? HFSPLUS_TYPE_RSRC : HFSPLUS_TYPE_DATA);
+	if (!res) {
+		HFSPLUS_I(inode).cached_start = be32_to_cpu(fd->key->ext.start_block);
+		HFSPLUS_I(inode).cached_blocks = hfsplus_ext_block_count(HFSPLUS_I(inode).cached_extents);
+	} else {
+		HFSPLUS_I(inode).cached_start = HFSPLUS_I(inode).cached_blocks = 0;
+		HFSPLUS_I(inode).flags &= ~(HFSPLUS_FLG_EXT_DIRTY | HFSPLUS_FLG_EXT_NEW);
+	}
+	return res;
+}
+
+static int hfsplus_ext_read_extent(struct inode *inode, u32 block)
+{
+	struct hfs_find_data fd;
+	int res;
+
+	if (block >= HFSPLUS_I(inode).cached_start &&
+	    block < HFSPLUS_I(inode).cached_start + HFSPLUS_I(inode).cached_blocks)
+		return 0;
+
+	hfs_find_init(HFSPLUS_SB(inode->i_sb).ext_tree, &fd);
+	res = __hfsplus_ext_cache_extent(&fd, inode, block);
+	hfs_find_exit(&fd);
+	return res;
+}
+
+/* Get a block at iblock for inode, possibly allocating if create */
+int hfsplus_get_block(struct inode *inode, sector_t iblock,
+		      struct buffer_head *bh_result, int create)
+{
+	struct super_block *sb;
+	int res = -EIO;
+	u32 ablock, dblock, mask;
+	int shift;
+
+	sb = inode->i_sb;
+
+	/* Convert inode block to disk allocation block */
+	shift = HFSPLUS_SB(sb).alloc_blksz_shift - sb->s_blocksize_bits;
+	ablock = iblock >> HFSPLUS_SB(sb).fs_shift;
+
+	if (iblock >= inode->i_blocks) {
+		if (iblock > inode->i_blocks || !create)
+			return -EIO;
+		if (ablock >= HFSPLUS_I(inode).alloc_blocks) {
+			res = hfsplus_file_extend(inode);
+			if (res)
+				return res;
+		}
+	} else
+		create = 0;
+
+	if (ablock < HFSPLUS_I(inode).first_blocks) {
+		dblock = hfsplus_ext_find_block(HFSPLUS_I(inode).first_extents, ablock);
+		goto done;
+	}
+
+	down(&HFSPLUS_I(inode).extents_lock);
+	res = hfsplus_ext_read_extent(inode, ablock);
+	if (!res) {
+		dblock = hfsplus_ext_find_block(HFSPLUS_I(inode).cached_extents, ablock -
+					     HFSPLUS_I(inode).cached_start);
+	} else {
+		up(&HFSPLUS_I(inode).extents_lock);
+		return -EIO;
+	}
+	up(&HFSPLUS_I(inode).extents_lock);
+
+done:
+	dprint(DBG_EXTENT, "get_block(%lu): %llu - %u\n", inode->i_ino, (long long)iblock, dblock);
+	mask = (1 << HFSPLUS_SB(sb).fs_shift) - 1;
+	map_bh(bh_result, sb, (dblock << HFSPLUS_SB(sb).fs_shift) + HFSPLUS_SB(sb).blockoffset + (iblock & mask));
+	if (create) {
+		set_buffer_new(bh_result);
+		HFSPLUS_I(inode).phys_size += sb->s_blocksize;
+		inode->i_blocks++;
+		mark_inode_dirty(inode);
+	}
+	return 0;
+}
+
+static void hfsplus_dump_extent(struct hfsplus_extent *extent)
+{
+	int i;
+
+	dprint(DBG_EXTENT, "   ");
+	for (i = 0; i < 8; i++)
+		dprint(DBG_EXTENT, " %u:%u", be32_to_cpu(extent[i].start_block),
+				 be32_to_cpu(extent[i].block_count));
+	dprint(DBG_EXTENT, "\n");
+}
+
+static int hfsplus_add_extent(struct hfsplus_extent *extent, u32 offset,
+			      u32 alloc_block, u32 block_count)
+{
+	u32 count, start;
+	int i;
+
+	hfsplus_dump_extent(extent);
+	for (i = 0; i < 8; extent++, i++) {
+		count = be32_to_cpu(extent->block_count);
+		if (offset == count) {
+			start = be32_to_cpu(extent->start_block);
+			if (alloc_block != start + count) {
+				if (++i >= 8)
+					return -ENOSPC;
+				extent++;
+				extent->start_block = cpu_to_be32(alloc_block);
+			} else
+				block_count += count;
+			extent->block_count = cpu_to_be32(block_count);
+			return 0;
+		} else if (offset < count)
+			break;
+		offset -= count;
+	}
+	/* panic? */
+	return -EIO;
+}
+
+int hfsplus_free_extents(struct super_block *sb, struct hfsplus_extent *extent,
+			 u32 offset, u32 block_nr)
+{
+	u32 count, start;
+	int i;
+
+	hfsplus_dump_extent(extent);
+	for (i = 0; i < 8; extent++, i++) {
+		count = be32_to_cpu(extent->block_count);
+		if (offset == count)
+			goto found;
+		else if (offset < count)
+			break;
+		offset -= count;
+	}
+	/* panic? */
+	return -EIO;
+found:
+	for (;;) {
+		start = be32_to_cpu(extent->start_block);
+		if (count <= block_nr) {
+			hfsplus_block_free(sb, start, count);
+			extent->block_count = 0;
+			extent->start_block = 0;
+			block_nr -= count;
+		} else {
+			count -= block_nr;
+			hfsplus_block_free(sb, start + count, block_nr);
+			extent->block_count = cpu_to_be32(count);
+			block_nr = 0;
+		}
+		if (!block_nr || !i)
+			return 0;
+		i--;
+		extent--;
+		count = be32_to_cpu(extent->block_count);
+	}
+}
+
+int hfsplus_free_fork(struct super_block *sb, u32 cnid, struct hfsplus_fork_raw *fork, int type)
+{
+	struct hfs_find_data fd;
+	hfsplus_extent_rec ext_entry;
+	u32 total_blocks, blocks, start;
+	int res, i;
+
+	total_blocks = be32_to_cpu(fork->total_blocks);
+	if (!total_blocks)
+		return 0;
+
+	blocks = 0;
+	for (i = 0; i < 8; i++)
+		blocks += be32_to_cpu(fork->extents[i].block_count);
+
+	res = hfsplus_free_extents(sb, fork->extents, blocks, blocks);
+	if (res)
+		return res;
+	if (total_blocks == blocks)
+		return 0;
+
+	hfs_find_init(HFSPLUS_SB(sb).ext_tree, &fd);
+	do {
+		res = __hfsplus_ext_read_extent(&fd, ext_entry, cnid,
+						total_blocks, type);
+		if (res)
+			break;
+		start = be32_to_cpu(fd.key->ext.start_block);
+		hfsplus_free_extents(sb, ext_entry,
+				     total_blocks - start,
+				     total_blocks);
+		hfs_brec_remove(&fd);
+		total_blocks = start;
+	} while (total_blocks > blocks);
+	hfs_find_exit(&fd);
+
+	return res;
+}
+
+int hfsplus_file_extend(struct inode *inode)
+{
+	struct super_block *sb = inode->i_sb;
+	u32 start, len, goal;
+	int res;
+
+	if (HFSPLUS_SB(sb).alloc_file->i_size * 8 < HFSPLUS_SB(sb).total_blocks - HFSPLUS_SB(sb).free_blocks + 8) {
+		// extend alloc file
+		printk("extend alloc file! (%Lu,%u,%u)\n", HFSPLUS_SB(sb).alloc_file->i_size * 8,
+			HFSPLUS_SB(sb).total_blocks, HFSPLUS_SB(sb).free_blocks);
+		return -ENOSPC;
+		//BUG();
+	}
+
+	down(&HFSPLUS_I(inode).extents_lock);
+	if (HFSPLUS_I(inode).alloc_blocks == HFSPLUS_I(inode).first_blocks)
+		goal = hfsplus_ext_lastblock(HFSPLUS_I(inode).first_extents);
+	else {
+		res = hfsplus_ext_read_extent(inode, HFSPLUS_I(inode).alloc_blocks);
+		if (res)
+			goto out;
+		goal = hfsplus_ext_lastblock(HFSPLUS_I(inode).cached_extents);
+	}
+
+	len = HFSPLUS_I(inode).clump_blocks;
+	start = hfsplus_block_allocate(sb, HFSPLUS_SB(sb).total_blocks, goal, &len);
+	if (start >= HFSPLUS_SB(sb).total_blocks) {
+		start = hfsplus_block_allocate(sb, goal, 0, &len);
+		if (start >= goal) {
+			res = -ENOSPC;
+			goto out;
+		}
+	}
+
+	dprint(DBG_EXTENT, "extend %lu: %u,%u\n", inode->i_ino, start, len);
+	if (HFSPLUS_I(inode).alloc_blocks <= HFSPLUS_I(inode).first_blocks) {
+		if (!HFSPLUS_I(inode).first_blocks) {
+			dprint(DBG_EXTENT, "first extents\n");
+			/* no extents yet */
+			HFSPLUS_I(inode).first_extents[0].start_block = cpu_to_be32(start);
+			HFSPLUS_I(inode).first_extents[0].block_count = cpu_to_be32(len);
+			res = 0;
+		} else {
+			/* try to append to extents in inode */
+			res = hfsplus_add_extent(HFSPLUS_I(inode).first_extents,
+						 HFSPLUS_I(inode).alloc_blocks,
+						 start, len);
+			if (res == -ENOSPC)
+				goto insert_extent;
+		}
+		if (!res) {
+			hfsplus_dump_extent(HFSPLUS_I(inode).first_extents);
+			HFSPLUS_I(inode).first_blocks += len;
+		}
+	} else {
+		res = hfsplus_add_extent(HFSPLUS_I(inode).cached_extents,
+					 HFSPLUS_I(inode).alloc_blocks -
+					 HFSPLUS_I(inode).cached_start,
+					 start, len);
+		if (!res) {
+			hfsplus_dump_extent(HFSPLUS_I(inode).cached_extents);
+			HFSPLUS_I(inode).flags |= HFSPLUS_FLG_EXT_DIRTY;
+			HFSPLUS_I(inode).cached_blocks += len;
+		} else if (res == -ENOSPC)
+			goto insert_extent;
+	}
+out:
+	up(&HFSPLUS_I(inode).extents_lock);
+	if (!res) {
+		HFSPLUS_I(inode).alloc_blocks += len;
+		mark_inode_dirty(inode);
+	}
+	return res;
+
+insert_extent:
+	dprint(DBG_EXTENT, "insert new extent\n");
+	hfsplus_ext_write_extent(inode);
+
+	memset(HFSPLUS_I(inode).cached_extents, 0, sizeof(hfsplus_extent_rec));
+	HFSPLUS_I(inode).cached_extents[0].start_block = cpu_to_be32(start);
+	HFSPLUS_I(inode).cached_extents[0].block_count = cpu_to_be32(len);
+	hfsplus_dump_extent(HFSPLUS_I(inode).cached_extents);
+	HFSPLUS_I(inode).flags |= HFSPLUS_FLG_EXT_DIRTY | HFSPLUS_FLG_EXT_NEW;
+	HFSPLUS_I(inode).cached_start = HFSPLUS_I(inode).alloc_blocks;
+	HFSPLUS_I(inode).cached_blocks = len;
+
+	res = 0;
+	goto out;
+}
+
+void hfsplus_file_truncate(struct inode *inode)
+{
+	struct super_block *sb = inode->i_sb;
+	struct hfs_find_data fd;
+	u32 alloc_cnt, blk_cnt, start;
+	int res;
+
+	dprint(DBG_INODE, "truncate: %lu, %Lu -> %Lu\n", inode->i_ino,
+	       (long long)HFSPLUS_I(inode).phys_size, inode->i_size);
+	if (inode->i_size > HFSPLUS_I(inode).phys_size) {
+		struct address_space *mapping = inode->i_mapping;
+		struct page *page;
+		u32 size = inode->i_size - 1;
+		int res;
+
+		page = grab_cache_page(mapping, size >> PAGE_CACHE_SHIFT);
+		if (!page)
+			return;
+		size &= PAGE_CACHE_SIZE - 1;
+		size++;
+		res = mapping->a_ops->prepare_write(NULL, page, size, size);
+		if (!res)
+			res = mapping->a_ops->commit_write(NULL, page, size, size);
+		if (res)
+			inode->i_size = HFSPLUS_I(inode).phys_size;
+		unlock_page(page);
+		page_cache_release(page);
+		mark_inode_dirty(inode);
+		return;
+	}
+	blk_cnt = (inode->i_size + HFSPLUS_SB(sb).alloc_blksz - 1) >> HFSPLUS_SB(sb).alloc_blksz_shift;
+	alloc_cnt = HFSPLUS_I(inode).alloc_blocks;
+	if (blk_cnt == alloc_cnt)
+		goto out;
+
+	down(&HFSPLUS_I(inode).extents_lock);
+	hfs_find_init(HFSPLUS_SB(sb).ext_tree, &fd);
+	while (1) {
+		if (alloc_cnt == HFSPLUS_I(inode).first_blocks) {
+			hfsplus_free_extents(sb, HFSPLUS_I(inode).first_extents,
+					     alloc_cnt, alloc_cnt - blk_cnt);
+			hfsplus_dump_extent(HFSPLUS_I(inode).first_extents);
+			HFSPLUS_I(inode).first_blocks = blk_cnt;
+			break;
+		}
+		res = __hfsplus_ext_cache_extent(&fd, inode, alloc_cnt);
+		if (res)
+			break;
+		start = HFSPLUS_I(inode).cached_start;
+		hfsplus_free_extents(sb, HFSPLUS_I(inode).cached_extents,
+				     alloc_cnt - start, alloc_cnt - blk_cnt);
+		hfsplus_dump_extent(HFSPLUS_I(inode).cached_extents);
+		if (blk_cnt > start) {
+			HFSPLUS_I(inode).flags |= HFSPLUS_FLG_EXT_DIRTY;
+			break;
+		}
+		alloc_cnt = start;
+		HFSPLUS_I(inode).cached_start = HFSPLUS_I(inode).cached_blocks = 0;
+		HFSPLUS_I(inode).flags &= ~(HFSPLUS_FLG_EXT_DIRTY | HFSPLUS_FLG_EXT_NEW);
+		hfs_brec_remove(&fd);
+	}
+	hfs_find_exit(&fd);
+	up(&HFSPLUS_I(inode).extents_lock);
+
+	HFSPLUS_I(inode).alloc_blocks = blk_cnt;
+out:
+	HFSPLUS_I(inode).phys_size = inode->i_size;
+	mark_inode_dirty(inode);
+	inode->i_blocks = (inode->i_size + sb->s_blocksize - 1) >> sb->s_blocksize_bits;
+}
--- diff/fs/hfsplus/hfsplus_fs.h	1970-01-01 01:00:00.000000000 +0100
+++ source/fs/hfsplus/hfsplus_fs.h	2004-02-23 13:56:46.000000000 +0000
@@ -0,0 +1,412 @@
+/*
+ *  linux/include/linux/hfsplus_fs.h
+ *
+ * Copyright (C) 1999
+ * Brad Boyer (flar@pants.nu)
+ * (C) 2003 Ardis Technologies <roman@ardistech.com>
+ *
+ */
+
+#ifndef _LINUX_HFSPLUS_FS_H
+#define _LINUX_HFSPLUS_FS_H
+
+#include <linux/fs.h>
+#include <linux/version.h>
+#include <linux/buffer_head.h>
+#include "hfsplus_raw.h"
+
+#define DBG_BNODE_REFS	0x00000001
+#define DBG_BNODE_MOD	0x00000002
+#define DBG_CAT_MOD	0x00000004
+#define DBG_INODE	0x00000008
+#define DBG_SUPER	0x00000010
+#define DBG_EXTENT	0x00000020
+#define DBG_BITMAP	0x00000040
+
+//#define DBG_MASK	(DBG_EXTENT|DBG_INODE|DBG_BNODE_MOD)
+//#define DBG_MASK	(DBG_BNODE_MOD|DBG_CAT_MOD|DBG_INODE)
+//#define DBG_MASK	(DBG_CAT_MOD|DBG_BNODE_REFS|DBG_INODE|DBG_EXTENT)
+#define DBG_MASK	(0)
+
+#define dprint(flg, fmt, args...) \
+	if (flg & DBG_MASK) printk(fmt , ## args)
+
+/* Runtime config options */
+#define HFSPLUS_DEF_CR_TYPE    0x3F3F3F3F  /* '????' */
+
+#define HFSPLUS_TYPE_DATA 0x00
+#define HFSPLUS_TYPE_RSRC 0xFF
+
+typedef int (*btree_keycmp)(hfsplus_btree_key *, hfsplus_btree_key *);
+
+#define NODE_HASH_SIZE	256
+
+/* An HFS+ BTree held in memory */
+struct hfs_btree {
+	struct super_block *sb;
+	struct inode *inode;
+	btree_keycmp keycmp;
+
+	u32 cnid;
+	u32 root;
+	u32 leaf_count;
+	u32 leaf_head;
+	u32 leaf_tail;
+	u32 node_count;
+	u32 free_nodes;
+	u32 attributes;
+
+	unsigned int node_size;
+	unsigned int node_size_shift;
+	unsigned int max_key_len;
+	unsigned int depth;
+
+	//unsigned int map1_size, map_size;
+	struct semaphore tree_lock;
+
+	unsigned int pages_per_bnode;
+	spinlock_t hash_lock;
+	struct hfs_bnode *node_hash[NODE_HASH_SIZE];
+	int node_hash_cnt;
+};
+
+struct page;
+
+/* An HFS+ BTree node in memory */
+struct hfs_bnode {
+	struct hfs_btree *tree;
+
+	u32 prev;
+	u32 this;
+	u32 next;
+	u32 parent;
+
+	u16 num_recs;
+	u8 type;
+	u8 height;
+
+	struct hfs_bnode *next_hash;
+	unsigned long flags;
+	wait_queue_head_t lock_wq;
+	atomic_t refcnt;
+	unsigned int page_offset;
+	struct page *page[0];
+};
+
+#define HFS_BNODE_LOCK		0
+#define HFS_BNODE_ERROR		1
+#define HFS_BNODE_NEW		2
+#define HFS_BNODE_DIRTY		3
+#define HFS_BNODE_DELETED	4
+
+/*
+ * HFS+ superblock info (built from Volume Header on disk)
+ */
+
+struct hfsplus_vh;
+struct hfs_btree;
+
+struct hfsplus_sb_info {
+	struct buffer_head *s_vhbh;
+	struct hfsplus_vh *s_vhdr;
+	struct hfs_btree *ext_tree;
+	struct hfs_btree *cat_tree;
+	struct hfs_btree *attr_tree;
+	struct inode *alloc_file;
+	struct inode *hidden_dir;
+
+	/* Runtime variables */
+	u32 blockoffset;
+	u32 sect_count;
+	int fs_shift;
+
+	/* Stuff in host order from Vol Header */
+	u32 alloc_blksz;
+	int alloc_blksz_shift;
+	u32 total_blocks;
+	u32 free_blocks;
+	u32 next_alloc;
+	u32 next_cnid;
+	u32 file_count;
+	u32 folder_count;
+	u32 data_clump_blocks, rsrc_clump_blocks;
+
+	/* Config options */
+	u32 creator;
+	u32 type;
+
+	umode_t umask;
+	uid_t uid;
+	gid_t gid;
+
+	int part, session;
+
+	unsigned long flags;
+
+	atomic_t inode_cnt;
+	u32 last_inode_cnt;
+
+	struct hlist_head rsrc_inodes;
+};
+
+#define HFSPLUS_SB_WRITEBACKUP	0x0001
+
+
+struct hfsplus_inode_info {
+	struct semaphore extents_lock;
+	u32 clump_blocks, alloc_blocks;
+	/* Allocation extents from catalog record or volume header */
+	hfsplus_extent_rec first_extents;
+	u32 first_blocks;
+	hfsplus_extent_rec cached_extents;
+	u32 cached_start, cached_blocks;
+	atomic_t opencnt;
+
+	struct inode *rsrc_inode;
+	unsigned long flags;
+
+	/* Device number in hfsplus_permissions in catalog */
+	u32 dev;
+	/* BSD system and user file flags */
+	u8 rootflags;
+	u8 userflags;
+
+	struct list_head open_dir_list;
+	loff_t phys_size;
+	struct inode vfs_inode;
+};
+
+#define HFSPLUS_FLG_RSRC	0x0001
+#define HFSPLUS_FLG_EXT_DIRTY	0x0002
+#define HFSPLUS_FLG_EXT_NEW	0x0004
+
+#define HFSPLUS_IS_DATA(inode)   (!(HFSPLUS_I(inode).flags & HFSPLUS_FLG_RSRC))
+#define HFSPLUS_IS_RSRC(inode)   (HFSPLUS_I(inode).flags & HFSPLUS_FLG_RSRC)
+
+struct hfs_find_data {
+	/* filled by caller */
+	hfsplus_btree_key *search_key;
+	hfsplus_btree_key *key;
+	/* filled by find */
+	struct hfs_btree *tree;
+	struct hfs_bnode *bnode;
+	/* filled by findrec */
+	int record;
+	int keyoffset, keylength;
+	int entryoffset, entrylength;
+};
+
+struct hfsplus_readdir_data {
+	struct list_head list;
+	struct file *file;
+	struct hfsplus_cat_key key;
+};
+
+#define hfs_btree_open hfsplus_btree_open
+#define hfs_btree_close hfsplus_btree_close
+#define hfs_btree_write hfsplus_btree_write
+#define hfs_bmap_alloc hfsplus_bmap_alloc
+#define hfs_bmap_free hfsplus_bmap_free
+#define hfs_bnode_read hfsplus_bnode_read
+#define hfs_bnode_read_u16 hfsplus_bnode_read_u16
+#define hfs_bnode_read_u8 hfsplus_bnode_read_u8
+#define hfs_bnode_read_key hfsplus_bnode_read_key
+#define hfs_bnode_write hfsplus_bnode_write
+#define hfs_bnode_write_u16 hfsplus_bnode_write_u16
+#define hfs_bnode_clear hfsplus_bnode_clear
+#define hfs_bnode_copy hfsplus_bnode_copy
+#define hfs_bnode_move hfsplus_bnode_move
+#define hfs_bnode_dump hfsplus_bnode_dump
+#define hfs_bnode_unlink hfsplus_bnode_unlink
+#define hfs_bnode_findhash hfsplus_bnode_findhash
+#define hfs_bnode_find hfsplus_bnode_find
+#define hfs_bnode_unhash hfsplus_bnode_unhash
+#define hfs_bnode_free hfsplus_bnode_free
+#define hfs_bnode_create hfsplus_bnode_create
+#define hfs_bnode_get hfsplus_bnode_get
+#define hfs_bnode_put hfsplus_bnode_put
+#define hfs_brec_lenoff hfsplus_brec_lenoff
+#define hfs_brec_keylen hfsplus_brec_keylen
+#define hfs_brec_insert hfsplus_brec_insert
+#define hfs_brec_remove hfsplus_brec_remove
+#define hfs_bnode_split hfsplus_bnode_split
+#define hfs_brec_update_parent hfsplus_brec_update_parent
+#define hfs_btree_inc_height hfsplus_btree_inc_height
+#define hfs_find_init hfsplus_find_init
+#define hfs_find_exit hfsplus_find_exit
+#define __hfs_brec_find __hplusfs_brec_find
+#define hfs_brec_find hfsplus_brec_find
+#define hfs_brec_read hfsplus_brec_read
+#define hfs_brec_goto hfsplus_brec_goto
+#define hfs_part_find hfsplus_part_find
+
+/*
+ * definitions for ext2 flag ioctls (linux really needs a generic
+ * interface for this).
+ */
+
+/* ext2 ioctls (EXT2_IOC_GETFLAGS and EXT2_IOC_SETFLAGS) to support
+ * chattr/lsattr */
+#define HFSPLUS_IOC_EXT2_GETFLAGS	_IOR('f', 1, long)
+#define HFSPLUS_IOC_EXT2_SETFLAGS	_IOW('f', 2, long)
+
+#define EXT2_FLAG_IMMUTABLE		0x00000010 /* Immutable file */
+#define EXT2_FLAG_APPEND		0x00000020 /* writes to file may only append */
+#define EXT2_FLAG_NODUMP		0x00000040 /* do not dump file */
+
+
+/*
+ * Functions in any *.c used in other files
+ */
+
+/* bitmap.c */
+int hfsplus_block_allocate(struct super_block *, u32, u32, u32 *);
+int hfsplus_block_free(struct super_block *, u32, u32);
+
+/* btree.c */
+struct hfs_btree *hfs_btree_open(struct super_block *, u32);
+void hfs_btree_close(struct hfs_btree *);
+void hfs_btree_write(struct hfs_btree *);
+struct hfs_bnode *hfs_bmap_alloc(struct hfs_btree *);
+void hfs_bmap_free(struct hfs_bnode *);
+
+/* bnode.c */
+void hfs_bnode_read(struct hfs_bnode *, void *, int, int);
+u16 hfs_bnode_read_u16(struct hfs_bnode *, int);
+u8 hfs_bnode_read_u8(struct hfs_bnode *, int);
+void hfs_bnode_read_key(struct hfs_bnode *, void *, int);
+void hfs_bnode_write(struct hfs_bnode *, void *, int, int);
+void hfs_bnode_write_u16(struct hfs_bnode *, int, u16);
+void hfs_bnode_clear(struct hfs_bnode *, int, int);
+void hfs_bnode_copy(struct hfs_bnode *, int,
+		    struct hfs_bnode *, int, int);
+void hfs_bnode_move(struct hfs_bnode *, int, int, int);
+void hfs_bnode_dump(struct hfs_bnode *);
+void hfs_bnode_unlink(struct hfs_bnode *);
+struct hfs_bnode *hfs_bnode_findhash(struct hfs_btree *, u32);
+struct hfs_bnode *hfs_bnode_find(struct hfs_btree *, u32);
+void hfs_bnode_unhash(struct hfs_bnode *);
+void hfs_bnode_free(struct hfs_bnode *);
+struct hfs_bnode *hfs_bnode_create(struct hfs_btree *, u32);
+void hfs_bnode_get(struct hfs_bnode *);
+void hfs_bnode_put(struct hfs_bnode *);
+
+/* brec.c */
+u16 hfs_brec_lenoff(struct hfs_bnode *, u16, u16 *);
+u16 hfs_brec_keylen(struct hfs_bnode *, u16);
+int hfs_brec_insert(struct hfs_find_data *, void *, int);
+int hfs_brec_remove(struct hfs_find_data *);
+struct hfs_bnode *hfs_bnode_split(struct hfs_find_data *);
+int hfs_brec_update_parent(struct hfs_find_data *);
+int hfs_btree_inc_height(struct hfs_btree *);
+
+/* bfind.c */
+int hfs_find_init(struct hfs_btree *, struct hfs_find_data *);
+void hfs_find_exit(struct hfs_find_data *);
+int __hfs_brec_find(struct hfs_bnode *, struct hfs_find_data *);
+int hfs_brec_find(struct hfs_find_data *);
+int hfs_brec_read(struct hfs_find_data *, void *, int);
+int hfs_brec_goto(struct hfs_find_data *, int);
+
+/* catalog.c */
+int hfsplus_cat_cmp_key(hfsplus_btree_key *, hfsplus_btree_key *);
+void hfsplus_cat_build_key(hfsplus_btree_key *, u32, struct qstr *);
+int hfsplus_find_cat(struct super_block *, u32, struct hfs_find_data *);
+int hfsplus_create_cat(u32, struct inode *, struct qstr *, struct inode *);
+int hfsplus_delete_cat(u32, struct inode *, struct qstr *);
+int hfsplus_rename_cat(u32, struct inode *, struct qstr *,
+		       struct inode *, struct qstr *);
+
+/* extents.c */
+int hfsplus_ext_cmp_key(hfsplus_btree_key *, hfsplus_btree_key *);
+void hfsplus_ext_build_key(hfsplus_btree_key *, u32, u32, u8);
+void hfsplus_ext_write_extent(struct inode *);
+int hfsplus_get_block(struct inode *, sector_t, struct buffer_head *, int);
+int hfsplus_free_fork(struct super_block *, u32, struct hfsplus_fork_raw *, int);
+int hfsplus_file_extend(struct inode *);
+void hfsplus_file_truncate(struct inode *);
+
+/* inode.c */
+extern struct address_space_operations hfsplus_aops;
+extern struct address_space_operations hfsplus_btree_aops;
+
+void hfsplus_inode_read_fork(struct inode *, struct hfsplus_fork_raw *);
+void hfsplus_inode_write_fork(struct inode *, struct hfsplus_fork_raw *);
+int hfsplus_cat_read_inode(struct inode *, struct hfs_find_data *);
+void hfsplus_cat_write_inode(struct inode *);
+struct inode *hfsplus_new_inode(struct super_block *, int);
+void hfsplus_delete_inode(struct inode *);
+
+/* ioctl.c */
+int hfsplus_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
+		  unsigned long arg);
+
+/* options.c */
+int parse_options(char *, struct hfsplus_sb_info *);
+void fill_defaults(struct hfsplus_sb_info *);
+void fill_current(struct hfsplus_sb_info *, struct hfsplus_sb_info *);
+
+/* tables.c */
+extern u16 case_fold_table[];
+
+/* unicode.c */
+int hfsplus_unistrcmp(const struct hfsplus_unistr *, const struct hfsplus_unistr *);
+int hfsplus_uni2asc(const struct hfsplus_unistr *, char *, int *);
+int hfsplus_asc2uni(struct hfsplus_unistr *, const char *, int);
+
+/* wrapper.c */
+int hfsplus_read_wrapper(struct super_block *);
+
+int hfs_part_find(struct super_block *, sector_t *, sector_t *);
+
+/* access macros */
+/*
+static inline struct hfsplus_sb_info *HFSPLUS_SB(struct super_block *sb)
+{
+	return sb->s_fs_info;
+}
+static inline struct hfsplus_inode_info *HFSPLUS_I(struct inode *inode)
+{
+	return list_entry(inode, struct hfsplus_inode_info, vfs_inode);
+}
+*/
+#define HFSPLUS_SB(super)	(*(struct hfsplus_sb_info *)(super)->s_fs_info)
+#define HFSPLUS_I(inode)	(*list_entry(inode, struct hfsplus_inode_info, vfs_inode))
+
+#if 1
+#define hfsplus_kmap(p)		({ struct page *__p = (p); kmap(__p); })
+#define hfsplus_kunmap(p)	({ struct page *__p = (p); kunmap(__p); __p; })
+#else
+#define hfsplus_kmap(p)		kmap(p)
+#define hfsplus_kunmap(p)	kunmap(p)
+#endif
+
+#define sb_bread512(sb, sec, data) ({			\
+	struct buffer_head *__bh;			\
+	sector_t __block;				\
+	loff_t __start;					\
+	int __offset;					\
+							\
+	__start = (loff_t)(sec) << HFSPLUS_SECTOR_SHIFT;\
+	__block = __start >> (sb)->s_blocksize_bits;	\
+	__offset = __start & ((sb)->s_blocksize - 1);	\
+	__bh = sb_bread((sb), __block);			\
+	if (likely(__bh != NULL))			\
+		data = (void *)(__bh->b_data + __offset);\
+	else						\
+		data = NULL;				\
+	__bh;						\
+})
+
+/* time macros */
+#define __hfsp_mt2ut(t)		(be32_to_cpu(t) - 2082844800U)
+#define __hfsp_ut2mt(t)		(cpu_to_be32(t + 2082844800U))
+
+/* compatibility */
+#define hfsp_mt2ut(t)		(struct timespec){ .tv_sec = __hfsp_mt2ut(t) }
+#define hfsp_ut2mt(t)		__hfsp_ut2mt((t).tv_sec)
+#define hfsp_now2mt()		__hfsp_ut2mt(get_seconds())
+
+#define kdev_t_to_nr(x)		(x)
+
+#endif
--- diff/fs/hfsplus/hfsplus_raw.h	1970-01-01 01:00:00.000000000 +0100
+++ source/fs/hfsplus/hfsplus_raw.h	2004-02-23 13:56:46.000000000 +0000
@@ -0,0 +1,326 @@
+/*
+ *  linux/include/linux/hfsplus_raw.h
+ *
+ * Copyright (C) 1999
+ * Brad Boyer (flar@pants.nu)
+ * (C) 2003 Ardis Technologies <roman@ardistech.com>
+ *
+ * Format of structures on disk
+ * Information taken from Apple Technote #1150 (HFS Plus Volume Format)
+ *
+ */
+
+#ifndef _LINUX_HFSPLUS_RAW_H
+#define _LINUX_HFSPLUS_RAW_H
+
+#include <linux/types.h>
+
+#define __packed __attribute__ ((packed))
+
+/* Some constants */
+#define HFSPLUS_SECTOR_SIZE        512
+#define HFSPLUS_SECTOR_SHIFT         9
+#define HFSPLUS_VOLHEAD_SECTOR       2
+#define HFSPLUS_VOLHEAD_SIG     0x482b
+#define HFSPLUS_SUPER_MAGIC     0x482b
+#define HFSPLUS_CURRENT_VERSION      4
+
+#define HFSP_WRAP_MAGIC         0x4244
+#define HFSP_WRAP_ATTRIB_SLOCK  0x8000
+#define HFSP_WRAP_ATTRIB_SPARED 0x0200
+
+#define HFSP_WRAPOFF_SIG          0x00
+#define HFSP_WRAPOFF_ATTRIB       0x0A
+#define HFSP_WRAPOFF_ABLKSIZE     0x14
+#define HFSP_WRAPOFF_ABLKSTART    0x1C
+#define HFSP_WRAPOFF_EMBEDSIG     0x7C
+#define HFSP_WRAPOFF_EMBEDEXT     0x7E
+
+#define HFSP_HIDDENDIR_NAME	"\xe2\x90\x80\xe2\x90\x80\xe2\x90\x80\xe2\x90\x80HFS+ Private Data"
+
+#define HFSP_HARDLINK_TYPE	0x686c6e6b	/* 'hlnk' */
+#define HFSP_HFSPLUS_CREATOR	0x6866732b	/* 'hfs+' */
+
+#define HFSP_MOUNT_VERSION	0x482b4c78	/* 'H+Lx' */
+
+/* Structures used on disk */
+
+typedef u32 hfsplus_cnid;
+typedef u16 hfsplus_unichr;
+
+/* A "string" as used in filenames, etc. */
+struct hfsplus_unistr {
+	u16 length;
+	hfsplus_unichr unicode[255];
+} __packed;
+
+#define HFSPLUS_MAX_STRLEN 255
+
+/* POSIX permissions */
+struct hfsplus_perm {
+	u32 owner;
+	u32 group;
+	u8  rootflags;
+	u8  userflags;
+	u16 mode;
+	u32 dev;
+} __packed;
+
+#define HFSPLUS_FLG_NODUMP	0x01
+#define HFSPLUS_FLG_IMMUTABLE	0x02
+#define HFSPLUS_FLG_APPEND	0x04
+
+/* A single contiguous area of a file */
+struct hfsplus_extent {
+	u32 start_block;
+	u32 block_count;
+} __packed;
+typedef struct hfsplus_extent hfsplus_extent_rec[8];
+
+/* Information for a "Fork" in a file */
+struct hfsplus_fork_raw {
+	u64 total_size;
+	u32 clump_size;
+	u32 total_blocks;
+	hfsplus_extent_rec extents;
+} __packed;
+
+/* HFS+ Volume Header */
+struct hfsplus_vh {
+	u16 signature;
+	u16 version;
+	u32 attributes;
+	u32 last_mount_vers;
+	u32 reserved;
+
+	u32 create_date;
+	u32 modify_date;
+	u32 backup_date;
+	u32 checked_date;
+
+	u32 file_count;
+	u32 folder_count;
+
+	u32 blocksize;
+	u32 total_blocks;
+	u32 free_blocks;
+
+	u32 next_alloc;
+	u32 rsrc_clump_sz;
+	u32 data_clump_sz;
+	hfsplus_cnid next_cnid;
+
+	u32 write_count;
+	u64 encodings_bmp;
+
+	u8 finder_info[32];
+
+	struct hfsplus_fork_raw alloc_file;
+	struct hfsplus_fork_raw ext_file;
+	struct hfsplus_fork_raw cat_file;
+	struct hfsplus_fork_raw attr_file;
+	struct hfsplus_fork_raw start_file;
+} __packed;
+
+/* HFS+ volume attributes */
+#define HFSPLUS_VOL_UNMNT     (1 << 8)
+#define HFSPLUS_VOL_SPARE_BLK (1 << 9)
+#define HFSPLUS_VOL_NOCACHE   (1 << 10)
+#define HFSPLUS_VOL_INCNSTNT  (1 << 11)
+#define HFSPLUS_VOL_SOFTLOCK  (1 << 15)
+
+/* HFS+ BTree node descriptor */
+struct hfs_bnode_desc {
+	u32 next;
+	u32 prev;
+	s8 type;
+	u8 height;
+	u16 num_recs;
+	u16 reserved;
+} __packed;
+
+/* HFS+ BTree node types */
+#define HFS_NODE_INDEX	0x00
+#define HFS_NODE_HEADER	0x01
+#define HFS_NODE_MAP	0x02
+#define HFS_NODE_LEAF	0xFF
+
+/* HFS+ BTree header */
+struct hfs_btree_header_rec {
+	u16 depth;
+	u32 root;
+	u32 leaf_count;
+	u32 leaf_head;
+	u32 leaf_tail;
+	u16 node_size;
+	u16 max_key_len;
+	u32 node_count;
+	u32 free_nodes;
+	u16 reserved1;
+	u32 clump_size;
+	u8 btree_type;
+	u8 reserved2;
+	u32 attributes;
+	u32 reserved3[16];
+} __packed;
+
+/* BTree attributes */
+#define HFS_TREE_BIGKEYS	2
+#define HFS_TREE_VARIDXKEYS	4
+
+/* HFS+ BTree misc info */
+#define HFSPLUS_TREE_HEAD 0
+#define HFSPLUS_NODE_MXSZ 32768
+
+/* Some special File ID numbers (stolen from hfs.h) */
+#define HFSPLUS_POR_CNID		1	/* Parent Of the Root */
+#define HFSPLUS_ROOT_CNID		2	/* ROOT directory */
+#define HFSPLUS_EXT_CNID		3	/* EXTents B-tree */
+#define HFSPLUS_CAT_CNID		4	/* CATalog B-tree */
+#define HFSPLUS_BAD_CNID		5	/* BAD blocks file */
+#define HFSPLUS_ALLOC_CNID		6	/* ALLOCation file */
+#define HFSPLUS_START_CNID		7	/* STARTup file */
+#define HFSPLUS_ATTR_CNID		8	/* ATTRibutes file */
+#define HFSPLUS_EXCH_CNID		15	/* ExchangeFiles temp id */
+#define HFSPLUS_FIRSTUSER_CNID		16	/* first available user id */
+
+/* HFS+ catalog entry key */
+struct hfsplus_cat_key {
+	u16 key_len;
+	hfsplus_cnid parent;
+	struct hfsplus_unistr name;
+} __packed;
+
+
+/* Structs from hfs.h */
+struct hfsp_point {
+	u16 v;
+	u16 h;
+} __packed;
+
+struct hfsp_rect {
+	u16 top;
+	u16 left;
+	u16 bottom;
+	u16 right;
+} __packed;
+
+
+/* HFS directory info (stolen from hfs.h */
+struct DInfo {
+	struct hfsp_rect frRect;
+	u16 frFlags;
+	struct hfsp_point frLocation;
+	u16 frView;
+} __packed;
+
+struct DXInfo {
+	struct hfsp_point frScroll;
+	u32 frOpenChain;
+	u16 frUnused;
+	u16 frComment;
+	u32 frPutAway;
+} __packed;
+
+/* HFS+ folder data (part of an hfsplus_cat_entry) */
+struct hfsplus_cat_folder {
+	s16 type;
+	u16 flags;
+	u32 valence;
+	hfsplus_cnid id;
+	u32 create_date;
+	u32 content_mod_date;
+	u32 attribute_mod_date;
+	u32 access_date;
+	u32 backup_date;
+	struct hfsplus_perm permissions;
+	struct DInfo user_info;
+	struct DXInfo finder_info;
+	u32 text_encoding;
+	u32 reserved;
+} __packed;
+
+/* HFS file info (stolen from hfs.h) */
+struct FInfo {
+	u32 fdType;
+	u32 fdCreator;
+	u16 fdFlags;
+	struct hfsp_point fdLocation;
+	u16 fdFldr;
+} __packed;
+
+struct FXInfo {
+	u16 fdIconID;
+	u8 fdUnused[8];
+	u16 fdComment;
+	u32 fdPutAway;
+} __packed;
+
+/* HFS+ file data (part of a cat_entry) */
+struct hfsplus_cat_file {
+	s16 type;
+	u16 flags;
+	u32 reserved1;
+	hfsplus_cnid id;
+	u32 create_date;
+	u32 content_mod_date;
+	u32 attribute_mod_date;
+	u32 access_date;
+	u32 backup_date;
+	struct hfsplus_perm permissions;
+	struct FInfo user_info;
+	struct FXInfo finder_info;
+	u32 text_encoding;
+	u32 reserved2;
+
+	struct hfsplus_fork_raw data_fork;
+	struct hfsplus_fork_raw rsrc_fork;
+} __packed;
+
+/* File attribute bits */
+#define HFSPLUS_FILE_LOCKED		0x0001
+#define HFSPLUS_FILE_THREAD_EXISTS	0x0002
+
+/* HFS+ catalog thread (part of a cat_entry) */
+struct hfsplus_cat_thread {
+	s16 type;
+	s16 reserved;
+	hfsplus_cnid parentID;
+	struct hfsplus_unistr nodeName;
+} __packed;
+
+#define HFSPLUS_MIN_THREAD_SZ 10
+
+/* A data record in the catalog tree */
+typedef union {
+	s16 type;
+	struct hfsplus_cat_folder folder;
+	struct hfsplus_cat_file file;
+	struct hfsplus_cat_thread thread;
+} __packed hfsplus_cat_entry;
+
+/* HFS+ catalog entry type */
+#define HFSPLUS_FOLDER         0x0001
+#define HFSPLUS_FILE           0x0002
+#define HFSPLUS_FOLDER_THREAD  0x0003
+#define HFSPLUS_FILE_THREAD    0x0004
+
+/* HFS+ extents tree key */
+struct hfsplus_ext_key {
+	u16 key_len;
+	u8 fork_type;
+	u8 pad;
+	hfsplus_cnid cnid;
+	u32 start_block;
+} __packed;
+
+#define HFSPLUS_EXT_KEYLEN 12
+
+/* HFS+ generic BTree key */
+typedef union {
+	u16 key_len;
+	struct hfsplus_cat_key cat;
+	struct hfsplus_ext_key ext;
+} __packed hfsplus_btree_key;
+
+#endif
--- diff/fs/hfsplus/inode.c	1970-01-01 01:00:00.000000000 +0100
+++ source/fs/hfsplus/inode.c	2004-02-23 13:56:46.000000000 +0000
@@ -0,0 +1,549 @@
+/*
+ *  linux/fs/hfsplus/inode.c
+ *
+ * Copyright (C) 2001
+ * Brad Boyer (flar@allandria.com)
+ * (C) 2003 Ardis Technologies <roman@ardistech.com>
+ *
+ * Inode handling routines
+ */
+
+#include <linux/mm.h>
+#include <linux/fs.h>
+#include <linux/pagemap.h>
+#include <linux/version.h>
+#include <linux/mpage.h>
+
+#include "hfsplus_fs.h"
+#include "hfsplus_raw.h"
+
+static int hfsplus_readpage(struct file *file, struct page *page)
+{
+	//printk("readpage: %lu\n", page->index);
+	return block_read_full_page(page, hfsplus_get_block);
+}
+
+static int hfsplus_writepage(struct page *page, struct writeback_control *wbc)
+{
+	//printk("writepage: %lu\n", page->index);
+	return block_write_full_page(page, hfsplus_get_block, wbc);
+}
+
+static int hfsplus_prepare_write(struct file *file, struct page *page, unsigned from, unsigned to)
+{
+	return cont_prepare_write(page, from, to, hfsplus_get_block,
+		&HFSPLUS_I(page->mapping->host).phys_size);
+}
+
+static sector_t hfsplus_bmap(struct address_space *mapping, sector_t block)
+{
+	return generic_block_bmap(mapping, block, hfsplus_get_block);
+}
+
+int hfsplus_releasepage(struct page *page, int mask)
+{
+	struct inode *inode = page->mapping->host;
+	struct super_block *sb = inode->i_sb;
+	struct hfs_btree *tree;
+	struct hfs_bnode *node;
+	u32 nidx;
+	int i, res = 1;
+
+	switch (inode->i_ino) {
+	case HFSPLUS_EXT_CNID:
+		tree = HFSPLUS_SB(sb).ext_tree;
+		break;
+	case HFSPLUS_CAT_CNID:
+		tree = HFSPLUS_SB(sb).cat_tree;
+		break;
+	case HFSPLUS_ATTR_CNID:
+		tree = HFSPLUS_SB(sb).attr_tree;
+		break;
+	default:
+		BUG();
+		return 0;
+	}
+	if (tree->node_size >= PAGE_CACHE_SIZE) {
+		nidx = page->index >> (tree->node_size_shift - PAGE_CACHE_SHIFT);
+		spin_lock(&tree->hash_lock);
+		node = hfs_bnode_findhash(tree, nidx);
+		if (!node)
+			;
+		else if (atomic_read(&node->refcnt))
+			res = 0;
+		else for (i = 0; i < tree->pages_per_bnode; i++) {
+			if (PageActive(node->page[i])) {
+				res = 0;
+				break;
+			}
+		}
+		if (res && node) {
+			hfs_bnode_unhash(node);
+			hfs_bnode_free(node);
+		}
+		spin_unlock(&tree->hash_lock);
+	} else {
+		nidx = page->index << (PAGE_CACHE_SHIFT - tree->node_size_shift);
+		i = 1 << (PAGE_CACHE_SHIFT - tree->node_size_shift);
+		spin_lock(&tree->hash_lock);
+		do {
+			node = hfs_bnode_findhash(tree, nidx++);
+			if (!node)
+				continue;
+			if (atomic_read(&node->refcnt)) {
+				res = 0;
+				break;
+			}
+			hfs_bnode_unhash(node);
+			hfs_bnode_free(node);
+		} while (--i);
+		spin_unlock(&tree->hash_lock);
+	}
+	//printk("releasepage: %lu,%x = %d\n", page->index, mask, res);
+	return res;
+}
+
+static int hfsplus_get_blocks(struct inode *inode, sector_t iblock, unsigned long max_blocks,
+			      struct buffer_head *bh_result, int create)
+{
+	int ret;
+
+	ret = hfsplus_get_block(inode, iblock, bh_result, create);
+	if (!ret)
+		bh_result->b_size = (1 << inode->i_blkbits);
+	return ret;
+}
+
+static int hfsplus_direct_IO(int rw, struct kiocb *iocb, const struct iovec *iov,
+			  loff_t offset, unsigned long nr_segs)
+{
+	struct file *file = iocb->ki_filp;
+	struct inode *inode = file->f_dentry->d_inode->i_mapping->host;
+
+	return blockdev_direct_IO(rw, iocb, inode, inode->i_sb->s_bdev, iov,
+				  offset, nr_segs, hfsplus_get_blocks, NULL);
+}
+
+static int hfsplus_writepages(struct address_space *mapping,
+			      struct writeback_control *wbc)
+{
+	return mpage_writepages(mapping, wbc, hfsplus_get_block);
+}
+
+struct address_space_operations hfsplus_btree_aops = {
+	.readpage	= hfsplus_readpage,
+	.writepage	= hfsplus_writepage,
+	.sync_page	= block_sync_page,
+	.prepare_write	= hfsplus_prepare_write,
+	.commit_write	= generic_commit_write,
+	.bmap		= hfsplus_bmap,
+	.releasepage	= hfsplus_releasepage,
+};
+
+struct address_space_operations hfsplus_aops = {
+	.readpage	= hfsplus_readpage,
+	.writepage	= hfsplus_writepage,
+	.sync_page	= block_sync_page,
+	.prepare_write	= hfsplus_prepare_write,
+	.commit_write	= generic_commit_write,
+	.bmap		= hfsplus_bmap,
+	.direct_IO	= hfsplus_direct_IO,
+	.writepages	= hfsplus_writepages,
+};
+
+static struct dentry *hfsplus_file_lookup(struct inode *dir, struct dentry *dentry,
+					  struct nameidata *nd)
+{
+	struct hfs_find_data fd;
+	struct super_block *sb = dir->i_sb;
+	struct inode *inode = NULL;
+	int err;
+
+	if (HFSPLUS_IS_RSRC(dir) || strcmp(dentry->d_name.name, "rsrc"))
+		goto out;
+
+	inode = HFSPLUS_I(dir).rsrc_inode;
+	if (inode)
+		goto out;
+
+	inode = new_inode(sb);
+	if (!inode)
+		return ERR_PTR(-ENOMEM);
+
+	inode->i_ino = dir->i_ino;
+	INIT_LIST_HEAD(&HFSPLUS_I(inode).open_dir_list);
+	init_MUTEX(&HFSPLUS_I(inode).extents_lock);
+	HFSPLUS_I(inode).flags = HFSPLUS_FLG_RSRC;
+
+	hfs_find_init(HFSPLUS_SB(sb).cat_tree, &fd);
+	err = hfsplus_find_cat(sb, dir->i_ino, &fd);
+	if (!err)
+		err = hfsplus_cat_read_inode(inode, &fd);
+	hfs_find_exit(&fd);
+	if (err) {
+		iput(inode);
+		return ERR_PTR(err);
+	}
+	HFSPLUS_I(inode).rsrc_inode = dir;
+	HFSPLUS_I(dir).rsrc_inode = inode;
+	igrab(dir);
+	hlist_add_head(&inode->i_hash, &HFSPLUS_SB(sb).rsrc_inodes);
+	mark_inode_dirty(inode);
+	{
+	void hfsplus_inode_check(struct super_block *sb);
+	atomic_inc(&HFSPLUS_SB(sb).inode_cnt);
+	hfsplus_inode_check(sb);
+	}
+out:
+	d_add(dentry, inode);
+	return NULL;
+}
+
+static void hfsplus_get_perms(struct inode *inode, struct hfsplus_perm *perms, int dir)
+{
+	struct super_block *sb = inode->i_sb;
+	u16 mode;
+
+	mode = be16_to_cpu(perms->mode);
+
+	inode->i_uid = be32_to_cpu(perms->owner);
+	if (!inode->i_uid && !mode)
+		inode->i_uid = HFSPLUS_SB(sb).uid;
+
+	inode->i_gid = be32_to_cpu(perms->group);
+	if (!inode->i_gid && !mode)
+		inode->i_gid = HFSPLUS_SB(sb).gid;
+
+	if (dir) {
+		mode = mode ? (mode & S_IALLUGO) :
+			(S_IRWXUGO & ~(HFSPLUS_SB(sb).umask));
+		mode |= S_IFDIR;
+	} else if (!mode)
+		mode = S_IFREG | ((S_IRUGO|S_IWUGO) &
+			~(HFSPLUS_SB(sb).umask));
+	inode->i_mode = mode;
+
+	HFSPLUS_I(inode).rootflags = perms->rootflags;
+	HFSPLUS_I(inode).userflags = perms->userflags;
+	if (perms->rootflags & HFSPLUS_FLG_IMMUTABLE)
+		inode->i_flags |= S_IMMUTABLE;
+	else
+		inode->i_flags &= ~S_IMMUTABLE;
+	if (perms->rootflags & HFSPLUS_FLG_APPEND)
+		inode->i_flags |= S_APPEND;
+	else
+		inode->i_flags &= ~S_APPEND;
+}
+
+static void hfsplus_set_perms(struct inode *inode, struct hfsplus_perm *perms)
+{
+	if (inode->i_flags & S_IMMUTABLE)
+		perms->rootflags |= HFSPLUS_FLG_IMMUTABLE;
+	else
+		perms->rootflags &= ~HFSPLUS_FLG_IMMUTABLE;
+	if (inode->i_flags & S_APPEND)
+		perms->rootflags |= HFSPLUS_FLG_APPEND;
+	else
+		perms->rootflags &= ~HFSPLUS_FLG_APPEND;
+	perms->userflags = HFSPLUS_I(inode).userflags;
+	perms->mode = cpu_to_be16(inode->i_mode);
+	perms->owner = cpu_to_be32(inode->i_uid);
+	perms->group = cpu_to_be32(inode->i_gid);
+	perms->dev = cpu_to_be32(HFSPLUS_I(inode).dev);
+}
+
+static int hfsplus_permission(struct inode *inode, int mask, struct nameidata *nd)
+{
+	/* MAY_EXEC is also used for lookup, if no x bit is set allow lookup,
+	 * open_exec has the same test, so it's still not executable, if a x bit
+	 * is set fall back to standard permission check.
+	 */
+	if (S_ISREG(inode->i_mode) && mask & MAY_EXEC && !(inode->i_mode & 0111))
+		return 0;
+	return vfs_permission(inode, mask);
+}
+
+
+static int hfsplus_file_open(struct inode *inode, struct file *file)
+{
+	if (HFSPLUS_IS_RSRC(inode))
+		inode = HFSPLUS_I(inode).rsrc_inode;
+	if (atomic_read(&file->f_count) != 1)
+		return 0;
+	atomic_inc(&HFSPLUS_I(inode).opencnt);
+	return 0;
+}
+
+static int hfsplus_file_release(struct inode *inode, struct file *file)
+{
+	struct super_block *sb = inode->i_sb;
+
+	if (HFSPLUS_IS_RSRC(inode))
+		inode = HFSPLUS_I(inode).rsrc_inode;
+	if (atomic_read(&file->f_count) != 0)
+		return 0;
+	if (atomic_dec_and_test(&HFSPLUS_I(inode).opencnt)) {
+		down(&inode->i_sem);
+		hfsplus_file_truncate(inode);
+		if (inode->i_flags & S_DEAD) {
+			hfsplus_delete_cat(inode->i_ino, HFSPLUS_SB(sb).hidden_dir, NULL);
+			hfsplus_delete_inode(inode);
+		}
+		up(&inode->i_sem);
+	}
+	return 0;
+}
+
+extern struct inode_operations hfsplus_dir_inode_operations;
+extern struct file_operations hfsplus_dir_operations;
+
+struct inode_operations hfsplus_file_inode_operations = {
+	.lookup		= hfsplus_file_lookup,
+	.truncate	= hfsplus_file_truncate,
+	.permission	= hfsplus_permission,
+};
+
+struct file_operations hfsplus_file_operations = {
+	.llseek 	= generic_file_llseek,
+	.read		= generic_file_read,
+	.write		= generic_file_write,
+	.mmap		= generic_file_mmap,
+	.fsync		= file_fsync,
+	.open		= hfsplus_file_open,
+	.release	= hfsplus_file_release,
+	.ioctl          = hfsplus_ioctl,
+};
+
+struct inode *hfsplus_new_inode(struct super_block *sb, int mode)
+{
+	struct inode *inode = new_inode(sb);
+	if (!inode)
+		return NULL;
+
+	{
+	void hfsplus_inode_check(struct super_block *sb);
+	atomic_inc(&HFSPLUS_SB(sb).inode_cnt);
+	hfsplus_inode_check(sb);
+	}
+	inode->i_ino = HFSPLUS_SB(sb).next_cnid++;
+	inode->i_mode = mode;
+	inode->i_uid = current->fsuid;
+	inode->i_gid = current->fsgid;
+	inode->i_nlink = 1;
+	inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
+	INIT_LIST_HEAD(&HFSPLUS_I(inode).open_dir_list);
+	init_MUTEX(&HFSPLUS_I(inode).extents_lock);
+	atomic_set(&HFSPLUS_I(inode).opencnt, 0);
+	HFSPLUS_I(inode).flags = 0;
+	if (S_ISDIR(inode->i_mode)) {
+		inode->i_size = 2;
+		HFSPLUS_SB(sb).folder_count++;
+		inode->i_op = &hfsplus_dir_inode_operations;
+		inode->i_fop = &hfsplus_dir_operations;
+	} else if (S_ISREG(inode->i_mode)) {
+		HFSPLUS_SB(sb).file_count++;
+		inode->i_op = &hfsplus_file_inode_operations;
+		inode->i_fop = &hfsplus_file_operations;
+		inode->i_mapping->a_ops = &hfsplus_aops;
+		HFSPLUS_I(inode).clump_blocks = HFSPLUS_SB(sb).data_clump_blocks;
+		memset(HFSPLUS_I(inode).first_extents, 0, sizeof(hfsplus_extent_rec));
+		memset(HFSPLUS_I(inode).cached_extents, 0, sizeof(hfsplus_extent_rec));
+		HFSPLUS_I(inode).alloc_blocks = 0;
+		HFSPLUS_I(inode).first_blocks = 0;
+		HFSPLUS_I(inode).cached_start = 0;
+		HFSPLUS_I(inode).cached_blocks = 0;
+		HFSPLUS_I(inode).phys_size = 0;
+		HFSPLUS_I(inode).rsrc_inode = 0;
+	} else if (S_ISLNK(inode->i_mode)) {
+		HFSPLUS_SB(sb).file_count++;
+		inode->i_op = &page_symlink_inode_operations;
+		inode->i_mapping->a_ops = &hfsplus_aops;
+		HFSPLUS_I(inode).clump_blocks = 1;
+	} else
+		HFSPLUS_SB(sb).file_count++;
+	insert_inode_hash(inode);
+	mark_inode_dirty(inode);
+	sb->s_dirt = 1;
+
+	return inode;
+}
+
+void hfsplus_delete_inode(struct inode *inode)
+{
+	struct super_block *sb = inode->i_sb;
+
+	if (S_ISDIR(inode->i_mode)) {
+		HFSPLUS_SB(sb).folder_count--;
+		sb->s_dirt = 1;
+		return;
+	}
+	HFSPLUS_SB(sb).file_count--;
+	if (S_ISREG(inode->i_mode)) {
+		if (!inode->i_nlink) {
+			inode->i_size = 0;
+			hfsplus_file_truncate(inode);
+		}
+	} else if (S_ISLNK(inode->i_mode)) {
+		inode->i_size = 0;
+		hfsplus_file_truncate(inode);
+	}
+	sb->s_dirt = 1;
+}
+
+void hfsplus_inode_read_fork(struct inode *inode, struct hfsplus_fork_raw *fork)
+{
+	struct super_block *sb = inode->i_sb;
+	u32 count;
+	int i;
+
+	memcpy(&HFSPLUS_I(inode).first_extents, &fork->extents,
+	       sizeof(hfsplus_extent_rec));
+	for (count = 0, i = 0; i < 8; i++)
+		count += be32_to_cpu(fork->extents[i].block_count);
+	HFSPLUS_I(inode).first_blocks = count;
+	memset(HFSPLUS_I(inode).cached_extents, 0, sizeof(hfsplus_extent_rec));
+	HFSPLUS_I(inode).cached_start = 0;
+	HFSPLUS_I(inode).cached_blocks = 0;
+
+	HFSPLUS_I(inode).alloc_blocks = be32_to_cpu(fork->total_blocks);
+	inode->i_size = HFSPLUS_I(inode).phys_size = be64_to_cpu(fork->total_size);
+	inode->i_blocks = (inode->i_size + sb->s_blocksize - 1) >> sb->s_blocksize_bits;
+	HFSPLUS_I(inode).clump_blocks = be32_to_cpu(fork->clump_size) >> HFSPLUS_SB(sb).alloc_blksz_shift;
+	if (!HFSPLUS_I(inode).clump_blocks)
+		HFSPLUS_I(inode).clump_blocks = HFSPLUS_IS_RSRC(inode) ? HFSPLUS_SB(sb).rsrc_clump_blocks :
+				HFSPLUS_SB(sb).data_clump_blocks;
+}
+
+void hfsplus_inode_write_fork(struct inode *inode, struct hfsplus_fork_raw *fork)
+{
+	memcpy(&fork->extents, &HFSPLUS_I(inode).first_extents,
+	       sizeof(hfsplus_extent_rec));
+	fork->total_size = cpu_to_be64(inode->i_size);
+	fork->total_blocks = cpu_to_be32(HFSPLUS_I(inode).alloc_blocks);
+}
+
+int hfsplus_cat_read_inode(struct inode *inode, struct hfs_find_data *fd)
+{
+	hfsplus_cat_entry entry;
+	int res = 0;
+	u16 type;
+
+	type = hfs_bnode_read_u16(fd->bnode, fd->entryoffset);
+
+	HFSPLUS_I(inode).dev = 0;
+	inode->i_blksize = PAGE_SIZE; /* Doesn't seem to be useful... */
+	if (type == HFSPLUS_FOLDER) {
+		struct hfsplus_cat_folder *folder = &entry.folder;
+
+		if (fd->entrylength < sizeof(struct hfsplus_cat_folder))
+			/* panic? */;
+		hfs_bnode_read(fd->bnode, &entry, fd->entryoffset,
+					sizeof(struct hfsplus_cat_folder));
+		hfsplus_get_perms(inode, &folder->permissions, 1);
+		inode->i_nlink = 1;
+		inode->i_size = 2 + be32_to_cpu(folder->valence);
+		inode->i_atime = hfsp_mt2ut(folder->access_date);
+		inode->i_mtime = hfsp_mt2ut(folder->content_mod_date);
+		inode->i_ctime = inode->i_mtime;
+		inode->i_blocks = 0;
+		inode->i_op = &hfsplus_dir_inode_operations;
+		inode->i_fop = &hfsplus_dir_operations;
+	} else if (type == HFSPLUS_FILE) {
+		struct hfsplus_cat_file *file = &entry.file;
+
+		if (fd->entrylength < sizeof(struct hfsplus_cat_file))
+			/* panic? */;
+		hfs_bnode_read(fd->bnode, &entry, fd->entryoffset,
+					sizeof(struct hfsplus_cat_file));
+
+		hfsplus_inode_read_fork(inode, HFSPLUS_IS_DATA(inode) ?
+					&file->data_fork : &file->rsrc_fork);
+		hfsplus_get_perms(inode, &file->permissions, 0);
+		inode->i_nlink = 1;
+		if (S_ISREG(inode->i_mode)) {
+			if (file->permissions.dev)
+				inode->i_nlink = be32_to_cpu(file->permissions.dev);
+			inode->i_op = &hfsplus_file_inode_operations;
+			inode->i_fop = &hfsplus_file_operations;
+			inode->i_mapping->a_ops = &hfsplus_aops;
+		} else if (S_ISLNK(inode->i_mode)) {
+			inode->i_op = &page_symlink_inode_operations;
+			inode->i_mapping->a_ops = &hfsplus_aops;
+		} else {
+			init_special_inode(inode, inode->i_mode,
+					   be32_to_cpu(file->permissions.dev));
+		}
+		inode->i_atime = hfsp_mt2ut(file->access_date);
+		inode->i_mtime = hfsp_mt2ut(file->content_mod_date);
+		inode->i_ctime = inode->i_mtime;
+	} else {
+		printk("HFS+-fs: bad catalog entry used to create inode\n");
+		res = -EIO;
+	}
+	return res;
+}
+
+void hfsplus_cat_write_inode(struct inode *inode)
+{
+	struct hfs_find_data fd;
+	hfsplus_cat_entry entry;
+
+	if (HFSPLUS_IS_RSRC(inode)) {
+		mark_inode_dirty(HFSPLUS_I(inode).rsrc_inode);
+		return;
+	}
+
+	if (!inode->i_nlink)
+		return;
+
+	if (hfs_find_init(HFSPLUS_SB(inode->i_sb).cat_tree, &fd))
+		/* panic? */
+		return;
+
+	if (hfsplus_find_cat(inode->i_sb, inode->i_ino, &fd))
+		/* panic? */
+		goto out;
+
+	if (S_ISDIR(inode->i_mode)) {
+		struct hfsplus_cat_folder *folder = &entry.folder;
+
+		if (fd.entrylength < sizeof(struct hfsplus_cat_folder))
+			/* panic? */;
+		hfs_bnode_read(fd.bnode, &entry, fd.entryoffset,
+					sizeof(struct hfsplus_cat_folder));
+		/* simple node checks? */
+		hfsplus_set_perms(inode, &folder->permissions);
+		folder->access_date = hfsp_ut2mt(inode->i_atime);
+		folder->content_mod_date = hfsp_ut2mt(inode->i_mtime);
+		folder->attribute_mod_date = hfsp_ut2mt(inode->i_ctime);
+		folder->valence = cpu_to_be32(inode->i_size - 2);
+		hfs_bnode_write(fd.bnode, &entry, fd.entryoffset,
+					 sizeof(struct hfsplus_cat_folder));
+	} else {
+		struct hfsplus_cat_file *file = &entry.file;
+
+		if (fd.entrylength < sizeof(struct hfsplus_cat_file))
+			/* panic? */;
+		hfs_bnode_read(fd.bnode, &entry, fd.entryoffset,
+					sizeof(struct hfsplus_cat_file));
+		hfsplus_inode_write_fork(inode, &file->data_fork);
+		if (HFSPLUS_I(inode).rsrc_inode)
+			hfsplus_inode_write_fork(HFSPLUS_I(inode).rsrc_inode, &file->rsrc_fork);
+		if (S_ISREG(inode->i_mode))
+			HFSPLUS_I(inode).dev = inode->i_nlink;
+		if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode))
+			HFSPLUS_I(inode).dev = kdev_t_to_nr(inode->i_rdev);
+		hfsplus_set_perms(inode, &file->permissions);
+		if ((file->permissions.rootflags | file->permissions.userflags) & HFSPLUS_FLG_IMMUTABLE)
+			file->flags |= cpu_to_be16(HFSPLUS_FILE_LOCKED);
+		else
+			file->flags &= cpu_to_be16(~HFSPLUS_FILE_LOCKED);
+		file->access_date = hfsp_ut2mt(inode->i_atime);
+		file->content_mod_date = hfsp_ut2mt(inode->i_mtime);
+		file->attribute_mod_date = hfsp_ut2mt(inode->i_ctime);
+		hfs_bnode_write(fd.bnode, &entry, fd.entryoffset,
+					 sizeof(struct hfsplus_cat_file));
+	}
+out:
+	hfs_find_exit(&fd);
+}
--- diff/fs/hfsplus/ioctl.c	1970-01-01 01:00:00.000000000 +0100
+++ source/fs/hfsplus/ioctl.c	2004-02-23 13:56:46.000000000 +0000
@@ -0,0 +1,82 @@
+/*
+ *  linux/fs/hfsplus/ioctl.c
+ *
+ * Copyright (C) 2003
+ * Ethan Benson <erbenson@alaska.net>
+ * partially derived from linux/fs/ext2/ioctl.c
+ * Copyright (C) 1993, 1994, 1995
+ * Remy Card (card@masi.ibp.fr)
+ * Laboratoire MASI - Institut Blaise Pascal
+ * Universite Pierre et Marie Curie (Paris VI)
+ *
+ * hfsplus ioctls
+ */
+
+#include <linux/fs.h>
+#include <linux/sched.h>
+#include <asm/uaccess.h>
+#include "hfsplus_fs.h"
+
+int hfsplus_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
+		  unsigned long arg)
+{
+	unsigned int flags;
+
+	switch (cmd) {
+	case HFSPLUS_IOC_EXT2_GETFLAGS:
+		flags = 0;
+		if (HFSPLUS_I(inode).rootflags & HFSPLUS_FLG_IMMUTABLE)
+			flags |= EXT2_FLAG_IMMUTABLE; /* EXT2_IMMUTABLE_FL */
+		if (HFSPLUS_I(inode).rootflags & HFSPLUS_FLG_APPEND)
+			flags |= EXT2_FLAG_APPEND; /* EXT2_APPEND_FL */
+		if (HFSPLUS_I(inode).userflags & HFSPLUS_FLG_NODUMP)
+			flags |= EXT2_FLAG_NODUMP; /* EXT2_NODUMP_FL */
+		return put_user(flags, (int *)arg);
+	case HFSPLUS_IOC_EXT2_SETFLAGS: {
+		if (IS_RDONLY(inode))
+			return -EROFS;
+
+		if ((current->fsuid != inode->i_uid) && !capable(CAP_FOWNER))
+			return -EACCES;
+
+		if (get_user(flags, (int *)arg))
+			return -EFAULT;
+
+		if (flags & (EXT2_FLAG_IMMUTABLE|EXT2_FLAG_APPEND) ||
+		    HFSPLUS_I(inode).rootflags & (HFSPLUS_FLG_IMMUTABLE|HFSPLUS_FLG_APPEND)) {
+			if (!capable(CAP_LINUX_IMMUTABLE))
+				return -EPERM;
+		}
+
+		/* don't silently ignore unsupported ext2 flags */
+		if (flags & ~(EXT2_FLAG_IMMUTABLE|EXT2_FLAG_APPEND|
+			      EXT2_FLAG_NODUMP))
+			return -EOPNOTSUPP;
+
+		if (flags & EXT2_FLAG_IMMUTABLE) { /* EXT2_IMMUTABLE_FL */
+			inode->i_flags |= S_IMMUTABLE;
+			HFSPLUS_I(inode).rootflags |= HFSPLUS_FLG_IMMUTABLE;
+		} else {
+			inode->i_flags &= ~S_IMMUTABLE;
+			HFSPLUS_I(inode).rootflags &= ~HFSPLUS_FLG_IMMUTABLE;
+		}
+		if (flags & EXT2_FLAG_APPEND) { /* EXT2_APPEND_FL */
+			inode->i_flags |= S_APPEND;
+			HFSPLUS_I(inode).rootflags |= HFSPLUS_FLG_APPEND;
+		} else {
+			inode->i_flags &= ~S_APPEND;
+			HFSPLUS_I(inode).rootflags &= ~HFSPLUS_FLG_APPEND;
+		}
+		if (flags & EXT2_FLAG_NODUMP) /* EXT2_NODUMP_FL */
+			HFSPLUS_I(inode).userflags |= HFSPLUS_FLG_NODUMP;
+		else
+			HFSPLUS_I(inode).userflags &= ~HFSPLUS_FLG_NODUMP;
+
+		inode->i_ctime = CURRENT_TIME;
+		mark_inode_dirty(inode);
+		return 0;
+	}
+	default:
+		return -ENOTTY;
+	}
+}
--- diff/fs/hfsplus/options.c	1970-01-01 01:00:00.000000000 +0100
+++ source/fs/hfsplus/options.c	2004-02-23 13:56:46.000000000 +0000
@@ -0,0 +1,127 @@
+/*
+ *  linux/fs/hfsplus/options.c
+ *
+ * Copyright (C) 2001
+ * Brad Boyer (flar@allandria.com)
+ * (C) 2003 Ardis Technologies <roman@ardistech.com>
+ *
+ * Option parsing
+ */
+
+#include <linux/string.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include "hfsplus_fs.h"
+
+/* Initialize an options object to reasonable defaults */
+void fill_defaults(struct hfsplus_sb_info *opts)
+{
+	if (!opts)
+		return;
+
+	opts->creator = HFSPLUS_DEF_CR_TYPE;
+	opts->type = HFSPLUS_DEF_CR_TYPE;
+	opts->umask = current->fs->umask;
+	opts->uid = current->uid;
+	opts->gid = current->gid;
+	opts->part = -1;
+	opts->session = -1;
+}
+
+/* convert a "four byte character" to a 32 bit int with error checks */
+static int fill_fourchar(u32 *result, char *input)
+{
+	u32 out;
+	int i;
+
+	if (!result || !input || !*input || (strlen(input) != 4))
+		return 0;
+
+	for (out = 0, i = 0; i < 4; i++) {
+		out <<= 8;
+		out |= ((int)(input[i])) & 0xFF;
+	}
+	*result = out;
+	return 1;
+}
+
+/* convert a string to int with error checks */
+static int fill_int(int *result, char *input, int base)
+{
+	char *tmp = input;
+	int intval;
+
+	if (!result || !input || !*input)
+		return 0;
+
+	intval = simple_strtoul(tmp, &tmp, base);
+	if (*tmp)
+		return 0;
+
+	*result = intval;
+	return 1;
+}
+
+/* Parse options from mount. Returns 0 on failure */
+/* input is the options passed to mount() as a string */
+int parse_options(char *input, struct hfsplus_sb_info *results)
+{
+	char *curropt, *value;
+	int tmp;
+
+	if (!input)
+		return 1;
+
+	while ((curropt = strsep(&input,",")) != NULL) {
+		if (!*curropt)
+			continue;
+
+		if ((value = strchr(curropt, '=')) != NULL)
+			*value++ = '\0';
+
+		if (!strcmp(curropt, "creator")) {
+			if (!fill_fourchar(&(results->creator), value)) {
+				printk("HFS+-fs: creator requires a 4 character value\n");
+				return 0;
+			}
+		} else if (!strcmp(curropt, "type")) {
+			if (!fill_fourchar(&(results->type), value)) {
+				printk("HFS+-fs: type requires a 4 character value\n");
+				return 0;
+			}
+		} else if (!strcmp(curropt, "umask")) {
+			if (!fill_int(&tmp, value, 8)) {
+				printk("HFS+-fs: umask requires a value\n");
+				return 0;
+			}
+			results->umask = (umode_t)tmp;
+		} else if (!strcmp(curropt, "uid")) {
+			if (!fill_int(&tmp, value, 0)) {
+				printk("HFS+-fs: uid requires an argument\n");
+				return 0;
+			}
+			results->uid = (uid_t)tmp;
+		} else if (!strcmp(curropt, "gid")) {
+			if (!fill_int(&tmp, value, 0)) {
+				printk("HFS+-fs: gid requires an argument\n");
+				return 0;
+			}
+			results->gid = (gid_t)tmp;
+		} else if (!strcmp(curropt, "part")) {
+			if (!fill_int(&results->part, value, 0)) {
+				printk("HFS+-fs: part requires an argument\n");
+				return 0;
+			}
+		} else if (!strcmp(curropt, "session")) {
+			if (!fill_int(&results->session, value, 0)) {
+				printk("HFS+-fs: session requires an argument\n");
+				return 0;
+			}
+		} else {
+			printk("HFS+-fs: unknown option %s\n", curropt);
+			return 0;
+		}
+	}
+
+	return 1;
+}
--- diff/fs/hfsplus/part_tbl.c	1970-01-01 01:00:00.000000000 +0100
+++ source/fs/hfsplus/part_tbl.c	2004-02-23 13:56:46.000000000 +0000
@@ -0,0 +1,133 @@
+/*
+ * linux/fs/hfs/part_tbl.c
+ *
+ * Copyright (C) 1996-1997  Paul H. Hargrove
+ * This file may be distributed under the terms of the GNU General Public License.
+ *
+ * Original code to handle the new style Mac partition table based on
+ * a patch contributed by Holger Schemel (aeglos@valinor.owl.de).
+ *
+ * In function preconditions the term "valid" applied to a pointer to
+ * a structure means that the pointer is non-NULL and the structure it
+ * points to has all fields initialized to consistent values.
+ *
+ */
+
+#include "hfsplus_fs.h"
+
+/* offsets to various blocks */
+#define HFS_DD_BLK		0 /* Driver Descriptor block */
+#define HFS_PMAP_BLK		1 /* First block of partition map */
+#define HFS_MDB_BLK		2 /* Block (w/i partition) of MDB */
+
+/* magic numbers for various disk blocks */
+#define HFS_DRVR_DESC_MAGIC	0x4552 /* "ER": driver descriptor map */
+#define HFS_OLD_PMAP_MAGIC	0x5453 /* "TS": old-type partition map */
+#define HFS_NEW_PMAP_MAGIC	0x504D /* "PM": new-type partition map */
+#define HFS_SUPER_MAGIC		0x4244 /* "BD": HFS MDB (super block) */
+#define HFS_MFS_SUPER_MAGIC	0xD2D7 /* MFS MDB (super block) */
+
+/*
+ * The new style Mac partition map
+ *
+ * For each partition on the media there is a physical block (512-byte
+ * block) containing one of these structures.  These blocks are
+ * contiguous starting at block 1.
+ */
+struct new_pmap {
+	u16	pmSig;		/* signature */
+	u16	reSigPad;	/* padding */
+	u32	pmMapBlkCnt;	/* partition blocks count */
+	u32	pmPyPartStart;	/* physical block start of partition */
+	u32	pmPartBlkCnt;	/* physical block count of partition */
+	u8	pmPartName[32];	/* (null terminated?) string
+				   giving the name of this
+				   partition */
+	u8	pmPartType[32];	/* (null terminated?) string
+				   giving the type of this
+				   partition */
+	/* a bunch more stuff we don't need */
+} __packed;
+
+/*
+ * The old style Mac partition map
+ *
+ * The partition map consists for a 2-byte signature followed by an
+ * array of these structures.  The map is terminated with an all-zero
+ * one of these.
+ */
+struct old_pmap {
+	u16		pdSig;	/* Signature bytes */
+	struct 	old_pmap_entry {
+		u32	pdStart;
+		u32	pdSize;
+		u32	pdFSID;
+	}	pdEntry[42];
+} __packed;
+
+/*
+ * hfs_part_find()
+ *
+ * Parse the partition map looking for the
+ * start and length of the 'part'th HFS partition.
+ */
+int hfs_part_find(struct super_block *sb,
+		  sector_t *part_start, sector_t *part_size)
+{
+	struct buffer_head *bh;
+	u16 *data;
+	int i, size, res;
+
+	res = -ENOENT;
+	bh = sb_bread512(sb, *part_start + HFS_PMAP_BLK, data);
+	if (!bh)
+		return -EIO;
+
+	switch (be16_to_cpu(*data)) {
+	case HFS_OLD_PMAP_MAGIC:
+	  {
+		struct old_pmap *pm;
+		struct old_pmap_entry *p;
+
+		pm = (struct old_pmap *)bh->b_data;
+		p = pm->pdEntry;
+		size = 42;
+		for (i = 0; i < size; p++, i++) {
+			if (p->pdStart && p->pdSize &&
+			    p->pdFSID == cpu_to_be32(0x54465331)/*"TFS1"*/ &&
+			    (HFSPLUS_SB(sb).part < 0 || HFSPLUS_SB(sb).part == i)) {
+				*part_start += be32_to_cpu(p->pdStart);
+				*part_size = be32_to_cpu(p->pdSize);
+				res = 0;
+			}
+		}
+		break;
+	  }
+	case HFS_NEW_PMAP_MAGIC:
+	  {
+		struct new_pmap *pm;
+
+		pm = (struct new_pmap *)bh->b_data;
+		size = be32_to_cpu(pm->pmMapBlkCnt);
+		for (i = 0; i < size;) {
+			if (!memcmp(pm->pmPartType,"Apple_HFS", 9) &&
+			    (HFSPLUS_SB(sb).part < 0 || HFSPLUS_SB(sb).part == i)) {
+				*part_start += be32_to_cpu(pm->pmPyPartStart);
+				*part_size = be32_to_cpu(pm->pmPartBlkCnt);
+				res = 0;
+				break;
+			}
+			brelse(bh);
+			bh = sb_bread512(sb, *part_start + HFS_PMAP_BLK + ++i, pm);
+			if (!bh)
+				return -EIO;
+			if (pm->pmSig != cpu_to_be16(HFS_NEW_PMAP_MAGIC))
+				break;
+		}
+		break;
+	  }
+	}
+	brelse(bh);
+
+	return res;
+}
--- diff/fs/hfsplus/super.c	1970-01-01 01:00:00.000000000 +0100
+++ source/fs/hfsplus/super.c	2004-02-23 13:56:46.000000000 +0000
@@ -0,0 +1,485 @@
+/*
+ *  linux/fs/hfsplus/super.c
+ *
+ * Copyright (C) 2001
+ * Brad Boyer (flar@allandria.com)
+ * (C) 2003 Ardis Technologies <roman@ardistech.com>
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/pagemap.h>
+#include <linux/fs.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/version.h>
+#include <linux/vfs.h>
+
+static struct inode *hfsplus_alloc_inode(struct super_block *sb);
+static void hfsplus_destroy_inode(struct inode *inode);
+
+#include "hfsplus_fs.h"
+
+void hfsplus_inode_check(struct super_block *sb)
+{
+#if 0
+	u32 cnt = atomic_read(&HFSPLUS_SB(sb).inode_cnt);
+	u32 last_cnt = HFSPLUS_SB(sb).last_inode_cnt;
+
+	if (cnt <= (last_cnt / 2) ||
+	    cnt >= (last_cnt * 2)) {
+		HFSPLUS_SB(sb).last_inode_cnt = cnt;
+		printk("inode_check: %u,%u,%u\n", cnt, last_cnt,
+			HFSPLUS_SB(sb).cat_tree ? HFSPLUS_SB(sb).cat_tree->node_hash_cnt : 0);
+	}
+#endif
+}
+
+static void hfsplus_read_inode(struct inode *inode)
+{
+	struct hfs_find_data fd;
+	struct hfsplus_vh *vhdr;
+	int err;
+
+	atomic_inc(&HFSPLUS_SB(inode->i_sb).inode_cnt);
+	hfsplus_inode_check(inode->i_sb);
+	INIT_LIST_HEAD(&HFSPLUS_I(inode).open_dir_list);
+	init_MUTEX(&HFSPLUS_I(inode).extents_lock);
+	HFSPLUS_I(inode).flags = 0;
+	HFSPLUS_I(inode).rsrc_inode = NULL;
+
+	if (inode->i_ino >= HFSPLUS_FIRSTUSER_CNID) {
+	read_inode:
+		hfs_find_init(HFSPLUS_SB(inode->i_sb).cat_tree, &fd);
+		err = hfsplus_find_cat(inode->i_sb, inode->i_ino, &fd);
+		if (!err)
+			err = hfsplus_cat_read_inode(inode, &fd);
+		hfs_find_exit(&fd);
+		if (err)
+			goto bad_inode;
+		return;
+	}
+	vhdr = HFSPLUS_SB(inode->i_sb).s_vhdr;
+	switch(inode->i_ino) {
+	case HFSPLUS_ROOT_CNID:
+		goto read_inode;
+	case HFSPLUS_EXT_CNID:
+		hfsplus_inode_read_fork(inode, &vhdr->ext_file);
+		inode->i_mapping->a_ops = &hfsplus_btree_aops;
+		break;
+	case HFSPLUS_CAT_CNID:
+		hfsplus_inode_read_fork(inode, &vhdr->cat_file);
+		inode->i_mapping->a_ops = &hfsplus_btree_aops;
+		break;
+	case HFSPLUS_ALLOC_CNID:
+		hfsplus_inode_read_fork(inode, &vhdr->alloc_file);
+		inode->i_mapping->a_ops = &hfsplus_aops;
+		break;
+	case HFSPLUS_START_CNID:
+		hfsplus_inode_read_fork(inode, &vhdr->start_file);
+		break;
+	case HFSPLUS_ATTR_CNID:
+		hfsplus_inode_read_fork(inode, &vhdr->attr_file);
+		inode->i_mapping->a_ops = &hfsplus_btree_aops;
+		break;
+	default:
+		goto bad_inode;
+	}
+
+	return;
+
+ bad_inode:
+	make_bad_inode(inode);
+}
+
+void hfsplus_write_inode(struct inode *inode, int unused)
+{
+	struct hfsplus_vh *vhdr;
+
+	dprint(DBG_INODE, "hfsplus_write_inode: %lu\n", inode->i_ino);
+	hfsplus_ext_write_extent(inode);
+	if (inode->i_ino >= HFSPLUS_FIRSTUSER_CNID) {
+		hfsplus_cat_write_inode(inode);
+		return;
+	}
+	vhdr = HFSPLUS_SB(inode->i_sb).s_vhdr;
+	switch (inode->i_ino) {
+	case HFSPLUS_ROOT_CNID:
+		hfsplus_cat_write_inode(inode);
+		break;
+	case HFSPLUS_EXT_CNID:
+		if (vhdr->ext_file.total_size != cpu_to_be64(inode->i_size)) {
+			HFSPLUS_SB(inode->i_sb).flags |= HFSPLUS_SB_WRITEBACKUP;
+			inode->i_sb->s_dirt = 1;
+		}
+		hfsplus_inode_write_fork(inode, &vhdr->ext_file);
+		hfs_btree_write(HFSPLUS_SB(inode->i_sb).ext_tree);
+		break;
+	case HFSPLUS_CAT_CNID:
+		if (vhdr->cat_file.total_size != cpu_to_be64(inode->i_size)) {
+			HFSPLUS_SB(inode->i_sb).flags |= HFSPLUS_SB_WRITEBACKUP;
+			inode->i_sb->s_dirt = 1;
+		}
+		hfsplus_inode_write_fork(inode, &vhdr->cat_file);
+		hfs_btree_write(HFSPLUS_SB(inode->i_sb).cat_tree);
+		break;
+	case HFSPLUS_ALLOC_CNID:
+		if (vhdr->alloc_file.total_size != cpu_to_be64(inode->i_size)) {
+			HFSPLUS_SB(inode->i_sb).flags |= HFSPLUS_SB_WRITEBACKUP;
+			inode->i_sb->s_dirt = 1;
+		}
+		hfsplus_inode_write_fork(inode, &vhdr->alloc_file);
+		break;
+	case HFSPLUS_START_CNID:
+		if (vhdr->start_file.total_size != cpu_to_be64(inode->i_size)) {
+			HFSPLUS_SB(inode->i_sb).flags |= HFSPLUS_SB_WRITEBACKUP;
+			inode->i_sb->s_dirt = 1;
+		}
+		hfsplus_inode_write_fork(inode, &vhdr->start_file);
+		break;
+	case HFSPLUS_ATTR_CNID:
+		if (vhdr->attr_file.total_size != cpu_to_be64(inode->i_size)) {
+			HFSPLUS_SB(inode->i_sb).flags |= HFSPLUS_SB_WRITEBACKUP;
+			inode->i_sb->s_dirt = 1;
+		}
+		hfsplus_inode_write_fork(inode, &vhdr->attr_file);
+		hfs_btree_write(HFSPLUS_SB(inode->i_sb).attr_tree);
+		break;
+	}
+}
+
+static void hfsplus_clear_inode(struct inode *inode)
+{
+	dprint(DBG_INODE, "hfsplus_clear_inode: %lu\n", inode->i_ino);
+	atomic_dec(&HFSPLUS_SB(inode->i_sb).inode_cnt);
+	if (HFSPLUS_IS_RSRC(inode)) {
+		HFSPLUS_I(HFSPLUS_I(inode).rsrc_inode).rsrc_inode = NULL;
+		iput(HFSPLUS_I(inode).rsrc_inode);
+	}
+	hfsplus_inode_check(inode->i_sb);
+}
+
+static void hfsplus_write_super(struct super_block *sb)
+{
+	struct hfsplus_vh *vhdr = HFSPLUS_SB(sb).s_vhdr;
+
+	dprint(DBG_SUPER, "hfsplus_write_super\n");
+	sb->s_dirt = 0;
+	if (sb->s_flags & MS_RDONLY)
+		/* warn? */
+		return;
+
+	vhdr->free_blocks = cpu_to_be32(HFSPLUS_SB(sb).free_blocks);
+	vhdr->next_alloc = cpu_to_be32(HFSPLUS_SB(sb).next_alloc);
+	vhdr->next_cnid = cpu_to_be32(HFSPLUS_SB(sb).next_cnid);
+	vhdr->folder_count = cpu_to_be32(HFSPLUS_SB(sb).folder_count);
+	vhdr->file_count = cpu_to_be32(HFSPLUS_SB(sb).file_count);
+
+	mark_buffer_dirty(HFSPLUS_SB(sb).s_vhbh);
+	if (HFSPLUS_SB(sb).flags & HFSPLUS_SB_WRITEBACKUP) {
+		if (HFSPLUS_SB(sb).sect_count) {
+			struct buffer_head *bh;
+			u32 block, offset;
+
+			block = HFSPLUS_SB(sb).blockoffset;
+			block += (HFSPLUS_SB(sb).sect_count - 2) >> (sb->s_blocksize_bits - 9);
+			offset = ((HFSPLUS_SB(sb).sect_count - 2) << 9) & (sb->s_blocksize - 1);
+			printk("backup: %u,%u,%u,%u\n", HFSPLUS_SB(sb).blockoffset,
+				HFSPLUS_SB(sb).sect_count, block, offset);
+			bh = sb_bread(sb, block);
+			if (bh) {
+				vhdr = (struct hfsplus_vh *)(bh->b_data + offset);
+				if (be16_to_cpu(vhdr->signature) == HFSPLUS_VOLHEAD_SIG) {
+					memcpy(vhdr, HFSPLUS_SB(sb).s_vhdr, sizeof(*vhdr));
+					mark_buffer_dirty(bh);
+					brelse(bh);
+				} else
+					printk("backup not found!\n");
+			}
+		}
+		HFSPLUS_SB(sb).flags &= ~HFSPLUS_SB_WRITEBACKUP;
+	}
+}
+
+static void hfsplus_put_super(struct super_block *sb)
+{
+	dprint(DBG_SUPER, "hfsplus_put_super\n");
+	if (!(sb->s_flags & MS_RDONLY)) {
+		struct hfsplus_vh *vhdr = HFSPLUS_SB(sb).s_vhdr;
+
+		vhdr->modify_date = hfsp_now2mt();
+		vhdr->attributes |= cpu_to_be32(HFSPLUS_VOL_UNMNT);
+		vhdr->attributes &= cpu_to_be32(~HFSPLUS_VOL_INCNSTNT);
+		mark_buffer_dirty(HFSPLUS_SB(sb).s_vhbh);
+		ll_rw_block(WRITE, 1, &HFSPLUS_SB(sb).s_vhbh);
+		wait_on_buffer(HFSPLUS_SB(sb).s_vhbh);
+	}
+
+	hfs_btree_close(HFSPLUS_SB(sb).cat_tree);
+	hfs_btree_close(HFSPLUS_SB(sb).ext_tree);
+	iput(HFSPLUS_SB(sb).alloc_file);
+	iput(HFSPLUS_SB(sb).hidden_dir);
+	brelse(HFSPLUS_SB(sb).s_vhbh);
+}
+
+static int hfsplus_statfs(struct super_block *sb, struct kstatfs *buf)
+{
+	buf->f_type = HFSPLUS_SUPER_MAGIC;
+	buf->f_bsize = sb->s_blocksize;
+	buf->f_blocks = HFSPLUS_SB(sb).total_blocks << HFSPLUS_SB(sb).fs_shift;
+	buf->f_bfree = HFSPLUS_SB(sb).free_blocks << HFSPLUS_SB(sb).fs_shift;
+	buf->f_bavail = buf->f_bfree;
+	buf->f_files = 0xFFFFFFFF;
+	buf->f_ffree = 0xFFFFFFFF - HFSPLUS_SB(sb).next_cnid;
+	buf->f_namelen = HFSPLUS_MAX_STRLEN;
+
+	return 0;
+}
+
+int hfsplus_remount(struct super_block *sb, int *flags, char *data)
+{
+	if ((*flags & MS_RDONLY) == (sb->s_flags & MS_RDONLY))
+		return 0;
+	if (!(*flags & MS_RDONLY)) {
+		struct hfsplus_vh *vhdr = HFSPLUS_SB(sb).s_vhdr;
+
+		if ((vhdr->attributes & cpu_to_be32(HFSPLUS_VOL_INCNSTNT)) ||
+		    !(vhdr->attributes & cpu_to_be32(HFSPLUS_VOL_UNMNT))) {
+			printk("HFS+-fs warning: Filesystem was not cleanly unmounted, "
+			       "running fsck.hfsplus is recommended.  leaving read-only.\n");
+			sb->s_flags |= MS_RDONLY;
+			*flags |= MS_RDONLY;
+		} else if (vhdr->attributes & cpu_to_be32(HFSPLUS_VOL_SOFTLOCK)) {
+			printk("HFS+-fs: Filesystem is marked locked, leaving read-only.\n");
+			sb->s_flags |= MS_RDONLY;
+			*flags |= MS_RDONLY;
+		}
+	}
+	return 0;
+}
+
+static struct super_operations hfsplus_sops = {
+	.alloc_inode	= hfsplus_alloc_inode,
+	.destroy_inode	= hfsplus_destroy_inode,
+	.read_inode	= hfsplus_read_inode,
+	.write_inode	= hfsplus_write_inode,
+	.clear_inode	= hfsplus_clear_inode,
+	.put_super	= hfsplus_put_super,
+	.write_super	= hfsplus_write_super,
+	.statfs		= hfsplus_statfs,
+	.remount_fs	= hfsplus_remount,
+};
+
+static int hfsplus_fill_super(struct super_block *sb, void *data, int silent)
+{
+	struct hfsplus_vh *vhdr;
+	struct hfsplus_sb_info *sbi;
+	hfsplus_cat_entry entry;
+	struct hfs_find_data fd;
+	struct qstr str;
+	int err = -EINVAL;
+
+	sbi = kmalloc(sizeof(struct hfsplus_sb_info), GFP_KERNEL);
+	if (!sbi) {
+		err = -ENOMEM;
+		goto out2;
+	}
+	memset(sbi, 0, sizeof(HFSPLUS_SB(sb)));
+	sb->s_fs_info = sbi;
+	INIT_HLIST_HEAD(&sbi->rsrc_inodes);
+	fill_defaults(sbi);
+	if (!parse_options(data, sbi)) {
+		if (!silent)
+			printk("HFS+-fs: unable to parse mount options\n");
+		err = -EINVAL;
+		goto out2;
+	}
+
+	/* Grab the volume header */
+	if (hfsplus_read_wrapper(sb)) {
+		if (!silent)
+			printk("HFS+-fs: unable to find HFS+ superblock\n");
+		err = -EINVAL;
+		goto out2;
+	}
+	vhdr = HFSPLUS_SB(sb).s_vhdr;
+
+	/* Copy parts of the volume header into the superblock */
+	sb->s_magic = be16_to_cpu(vhdr->signature);
+	if (be16_to_cpu(vhdr->version) != HFSPLUS_CURRENT_VERSION) {
+		if (!silent)
+			printk("HFS+-fs: wrong filesystem version\n");
+		goto cleanup;
+	}
+	HFSPLUS_SB(sb).total_blocks = be32_to_cpu(vhdr->total_blocks);
+	HFSPLUS_SB(sb).free_blocks = be32_to_cpu(vhdr->free_blocks);
+	HFSPLUS_SB(sb).next_alloc = be32_to_cpu(vhdr->next_alloc);
+	HFSPLUS_SB(sb).next_cnid = be32_to_cpu(vhdr->next_cnid);
+	HFSPLUS_SB(sb).file_count = be32_to_cpu(vhdr->file_count);
+	HFSPLUS_SB(sb).folder_count = be32_to_cpu(vhdr->folder_count);
+	HFSPLUS_SB(sb).data_clump_blocks = be32_to_cpu(vhdr->data_clump_sz) >> HFSPLUS_SB(sb).alloc_blksz_shift;
+	if (!HFSPLUS_SB(sb).data_clump_blocks)
+		HFSPLUS_SB(sb).data_clump_blocks = 1;
+	HFSPLUS_SB(sb).rsrc_clump_blocks = be32_to_cpu(vhdr->rsrc_clump_sz) >> HFSPLUS_SB(sb).alloc_blksz_shift;
+	if (!HFSPLUS_SB(sb).rsrc_clump_blocks)
+		HFSPLUS_SB(sb).rsrc_clump_blocks = 1;
+
+	/* Set up operations so we can load metadata */
+	sb->s_op = &hfsplus_sops;
+	sb->s_maxbytes = MAX_LFS_FILESIZE;
+
+	if ((vhdr->attributes & cpu_to_be32(HFSPLUS_VOL_INCNSTNT)) ||
+	    !(vhdr->attributes & cpu_to_be32(HFSPLUS_VOL_UNMNT))) {
+		if (!silent)
+			printk("HFS+-fs warning: Filesystem was not cleanly unmounted, "
+			       "running fsck.hfsplus is recommended.  mounting read-only.\n");
+		sb->s_flags |= MS_RDONLY;
+	} else if (vhdr->attributes & cpu_to_be32(HFSPLUS_VOL_SOFTLOCK)) {
+		if (!silent)
+			printk("HFS+-fs: Filesystem is marked locked, mounting read-only.\n");
+		sb->s_flags |= MS_RDONLY;
+	}
+
+	/* Load metadata objects (B*Trees) */
+	HFSPLUS_SB(sb).ext_tree = hfs_btree_open(sb, HFSPLUS_EXT_CNID);
+	if (!HFSPLUS_SB(sb).ext_tree) {
+		if (!silent)
+			printk("HFS+-fs: failed to load extents file\n");
+		goto cleanup;
+	}
+	HFSPLUS_SB(sb).cat_tree = hfs_btree_open(sb, HFSPLUS_CAT_CNID);
+	if (!HFSPLUS_SB(sb).cat_tree) {
+		if (!silent)
+			printk("HFS+-fs: failed to load catalog file\n");
+		goto cleanup;
+	}
+
+	HFSPLUS_SB(sb).alloc_file = iget(sb, HFSPLUS_ALLOC_CNID);
+	if (!HFSPLUS_SB(sb).alloc_file) {
+		if (!silent)
+			printk("HFS+-fs: failed to load allocation file\n");
+		goto cleanup;
+	}
+
+	/* Load the root directory */
+	sb->s_root = d_alloc_root(iget(sb, HFSPLUS_ROOT_CNID));
+	if (!sb->s_root) {
+		if (!silent)
+			printk("HFS+-fs: failed to load root directory\n");
+		goto cleanup;
+	}
+
+	str.len = sizeof(HFSP_HIDDENDIR_NAME) - 1;
+	str.name = HFSP_HIDDENDIR_NAME;
+	hfs_find_init(HFSPLUS_SB(sb).cat_tree, &fd);
+	hfsplus_cat_build_key(fd.search_key, HFSPLUS_ROOT_CNID, &str);
+	if (!hfs_brec_read(&fd, &entry, sizeof(entry))) {
+		hfs_find_exit(&fd);
+		if (entry.type != cpu_to_be16(HFSPLUS_FOLDER))
+			goto cleanup;
+		HFSPLUS_SB(sb).hidden_dir = iget(sb, be32_to_cpu(entry.folder.id));
+		if (!HFSPLUS_SB(sb).hidden_dir)
+			goto cleanup;
+	} else
+		hfs_find_exit(&fd);
+
+	if (sb->s_flags & MS_RDONLY)
+		goto out;
+
+	/* H+LX == hfsplusutils, H+Lx == this driver, H+lx is unused
+	 * all three are registered with Apple for our use
+	 */
+	vhdr->last_mount_vers = cpu_to_be32(HFSP_MOUNT_VERSION);
+	vhdr->modify_date = hfsp_now2mt();
+	vhdr->write_count = cpu_to_be32(be32_to_cpu(vhdr->write_count) + 1);
+	vhdr->attributes &= cpu_to_be32(~HFSPLUS_VOL_UNMNT);
+	vhdr->attributes |= cpu_to_be32(HFSPLUS_VOL_INCNSTNT);
+	mark_buffer_dirty(HFSPLUS_SB(sb).s_vhbh);
+	ll_rw_block(WRITE, 1, &HFSPLUS_SB(sb).s_vhbh);
+	wait_on_buffer(HFSPLUS_SB(sb).s_vhbh);
+
+	if (!HFSPLUS_SB(sb).hidden_dir) {
+		printk("HFS+: create hidden dir...\n");
+		HFSPLUS_SB(sb).hidden_dir = hfsplus_new_inode(sb, S_IFDIR);
+		hfsplus_create_cat(HFSPLUS_SB(sb).hidden_dir->i_ino, sb->s_root->d_inode,
+				   &str, HFSPLUS_SB(sb).hidden_dir);
+		mark_inode_dirty(HFSPLUS_SB(sb).hidden_dir);
+	}
+out:
+	return 0;
+
+cleanup:
+	hfsplus_put_super(sb);
+out2:
+	return err;
+}
+
+MODULE_AUTHOR("Brad Boyer");
+MODULE_DESCRIPTION("Extended Macintosh Filesystem");
+MODULE_LICENSE("GPL");
+
+static kmem_cache_t *hfsplus_inode_cachep;
+
+static struct inode *hfsplus_alloc_inode(struct super_block *sb)
+{
+	struct hfsplus_inode_info *i;
+
+	i = kmem_cache_alloc(hfsplus_inode_cachep, SLAB_KERNEL);
+	return i ? &i->vfs_inode : NULL;
+}
+
+static void hfsplus_destroy_inode(struct inode *inode)
+{
+	kmem_cache_free(hfsplus_inode_cachep, &HFSPLUS_I(inode));
+}
+
+#define HFSPLUS_INODE_SIZE	sizeof(struct hfsplus_inode_info)
+
+static struct super_block *hfsplus_get_sb(struct file_system_type *fs_type,
+					  int flags, const char *dev_name, void *data)
+{
+	return get_sb_bdev(fs_type, flags, dev_name, data, hfsplus_fill_super);
+}
+
+static struct file_system_type hfsplus_fs_type = {
+	.owner		= THIS_MODULE,
+	.name		= "hfsplus",
+	.get_sb		= hfsplus_get_sb,
+	.kill_sb	= kill_block_super,
+	.fs_flags	= FS_REQUIRES_DEV,
+};
+
+static void hfsplus_init_once(void *p, kmem_cache_t *cachep, unsigned long flags)
+{
+	struct hfsplus_inode_info *i = p;
+
+	if ((flags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) == SLAB_CTOR_CONSTRUCTOR)
+		inode_init_once(&i->vfs_inode);
+}
+
+static int __init init_hfsplus_fs(void)
+{
+	int err;
+
+	hfsplus_inode_cachep = kmem_cache_create("hfsplus_icache",
+		HFSPLUS_INODE_SIZE, 0, SLAB_HWCACHE_ALIGN,
+		hfsplus_init_once, NULL);
+	if (!hfsplus_inode_cachep)
+		return -ENOMEM;
+	err = register_filesystem(&hfsplus_fs_type);
+	if (err)
+		kmem_cache_destroy(hfsplus_inode_cachep);
+	return err;
+}
+
+static void __exit exit_hfsplus_fs(void)
+{
+	unregister_filesystem(&hfsplus_fs_type);
+	if (kmem_cache_destroy(hfsplus_inode_cachep))
+		printk(KERN_INFO "hfsplus_inode_cache: not all structures were freed\n");
+}
+
+module_init(init_hfsplus_fs)
+module_exit(exit_hfsplus_fs)
--- diff/fs/hfsplus/tables.c	1970-01-01 01:00:00.000000000 +0100
+++ source/fs/hfsplus/tables.c	2004-02-23 13:56:46.000000000 +0000
@@ -0,0 +1,408 @@
+/*
+ * linux/fs/hfsplus/tables.c
+ *
+ * Various data tables
+ */
+
+#include "hfsplus_fs.h"
+
+/*
+ *  Unicode case folding table taken from Apple Technote #1150
+ *  (HFS Plus Volume Format)
+ */
+
+u16 case_fold_table[] = {
+/*
+ *  The lower case table consists of a 256-entry high-byte table followed by
+ *  some number of 256-entry subtables. The high-byte table contains either an
+ *  offset to the subtable for characters with that high byte or zero, which
+ *  means that there are no case mappings or ignored characters in that block.
+ *  Ignored characters are mapped to zero.
+ */
+
+    // High-byte indices ( == 0 iff no case mapping and no ignorables )
+
+
+    /* 0 */ 0x0100, 0x0200, 0x0000, 0x0300, 0x0400, 0x0500, 0x0000, 0x0000,
+            0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+    /* 1 */ 0x0600, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+            0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+    /* 2 */ 0x0700, 0x0800, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+            0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+    /* 3 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+            0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+    /* 4 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+            0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+    /* 5 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+            0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+    /* 6 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+            0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+    /* 7 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+            0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+    /* 8 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+            0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+    /* 9 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+            0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+    /* A */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+            0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+    /* B */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+            0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+    /* C */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+            0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+    /* D */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+            0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+    /* E */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+            0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+    /* F */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+            0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0900, 0x0A00,
+
+    // Table 1 (for high byte 0x00)
+
+    /* 0 */ 0xFFFF, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007,
+            0x0008, 0x0009, 0x000A, 0x000B, 0x000C, 0x000D, 0x000E, 0x000F,
+    /* 1 */ 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017,
+            0x0018, 0x0019, 0x001A, 0x001B, 0x001C, 0x001D, 0x001E, 0x001F,
+    /* 2 */ 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027,
+            0x0028, 0x0029, 0x002A, 0x002B, 0x002C, 0x002D, 0x002E, 0x002F,
+    /* 3 */ 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037,
+            0x0038, 0x0039, 0x003A, 0x003B, 0x003C, 0x003D, 0x003E, 0x003F,
+    /* 4 */ 0x0040, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067,
+            0x0068, 0x0069, 0x006A, 0x006B, 0x006C, 0x006D, 0x006E, 0x006F,
+    /* 5 */ 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077,
+            0x0078, 0x0079, 0x007A, 0x005B, 0x005C, 0x005D, 0x005E, 0x005F,
+    /* 6 */ 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067,
+            0x0068, 0x0069, 0x006A, 0x006B, 0x006C, 0x006D, 0x006E, 0x006F,
+    /* 7 */ 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077,
+            0x0078, 0x0079, 0x007A, 0x007B, 0x007C, 0x007D, 0x007E, 0x007F,
+    /* 8 */ 0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, 0x0087,
+            0x0088, 0x0089, 0x008A, 0x008B, 0x008C, 0x008D, 0x008E, 0x008F,
+    /* 9 */ 0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097,
+            0x0098, 0x0099, 0x009A, 0x009B, 0x009C, 0x009D, 0x009E, 0x009F,
+    /* A */ 0x00A0, 0x00A1, 0x00A2, 0x00A3, 0x00A4, 0x00A5, 0x00A6, 0x00A7,
+            0x00A8, 0x00A9, 0x00AA, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x00AF,
+    /* B */ 0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x00B4, 0x00B5, 0x00B6, 0x00B7,
+            0x00B8, 0x00B9, 0x00BA, 0x00BB, 0x00BC, 0x00BD, 0x00BE, 0x00BF,
+    /* C */ 0x00C0, 0x00C1, 0x00C2, 0x00C3, 0x00C4, 0x00C5, 0x00E6, 0x00C7,
+            0x00C8, 0x00C9, 0x00CA, 0x00CB, 0x00CC, 0x00CD, 0x00CE, 0x00CF,
+    /* D */ 0x00F0, 0x00D1, 0x00D2, 0x00D3, 0x00D4, 0x00D5, 0x00D6, 0x00D7,
+            0x00F8, 0x00D9, 0x00DA, 0x00DB, 0x00DC, 0x00DD, 0x00FE, 0x00DF,
+    /* E */ 0x00E0, 0x00E1, 0x00E2, 0x00E3, 0x00E4, 0x00E5, 0x00E6, 0x00E7,
+            0x00E8, 0x00E9, 0x00EA, 0x00EB, 0x00EC, 0x00ED, 0x00EE, 0x00EF,
+    /* F */ 0x00F0, 0x00F1, 0x00F2, 0x00F3, 0x00F4, 0x00F5, 0x00F6, 0x00F7,
+            0x00F8, 0x00F9, 0x00FA, 0x00FB, 0x00FC, 0x00FD, 0x00FE, 0x00FF,
+
+    // Table 2 (for high byte 0x01)
+
+    /* 0 */ 0x0100, 0x0101, 0x0102, 0x0103, 0x0104, 0x0105, 0x0106, 0x0107,
+            0x0108, 0x0109, 0x010A, 0x010B, 0x010C, 0x010D, 0x010E, 0x010F,
+    /* 1 */ 0x0111, 0x0111, 0x0112, 0x0113, 0x0114, 0x0115, 0x0116, 0x0117,
+            0x0118, 0x0119, 0x011A, 0x011B, 0x011C, 0x011D, 0x011E, 0x011F,
+    /* 2 */ 0x0120, 0x0121, 0x0122, 0x0123, 0x0124, 0x0125, 0x0127, 0x0127,
+            0x0128, 0x0129, 0x012A, 0x012B, 0x012C, 0x012D, 0x012E, 0x012F,
+    /* 3 */ 0x0130, 0x0131, 0x0133, 0x0133, 0x0134, 0x0135, 0x0136, 0x0137,
+            0x0138, 0x0139, 0x013A, 0x013B, 0x013C, 0x013D, 0x013E, 0x0140,
+    /* 4 */ 0x0140, 0x0142, 0x0142, 0x0143, 0x0144, 0x0145, 0x0146, 0x0147,
+            0x0148, 0x0149, 0x014B, 0x014B, 0x014C, 0x014D, 0x014E, 0x014F,
+    /* 5 */ 0x0150, 0x0151, 0x0153, 0x0153, 0x0154, 0x0155, 0x0156, 0x0157,
+            0x0158, 0x0159, 0x015A, 0x015B, 0x015C, 0x015D, 0x015E, 0x015F,
+    /* 6 */ 0x0160, 0x0161, 0x0162, 0x0163, 0x0164, 0x0165, 0x0167, 0x0167,
+            0x0168, 0x0169, 0x016A, 0x016B, 0x016C, 0x016D, 0x016E, 0x016F,
+    /* 7 */ 0x0170, 0x0171, 0x0172, 0x0173, 0x0174, 0x0175, 0x0176, 0x0177,
+            0x0178, 0x0179, 0x017A, 0x017B, 0x017C, 0x017D, 0x017E, 0x017F,
+    /* 8 */ 0x0180, 0x0253, 0x0183, 0x0183, 0x0185, 0x0185, 0x0254, 0x0188,
+            0x0188, 0x0256, 0x0257, 0x018C, 0x018C, 0x018D, 0x01DD, 0x0259,
+    /* 9 */ 0x025B, 0x0192, 0x0192, 0x0260, 0x0263, 0x0195, 0x0269, 0x0268,
+            0x0199, 0x0199, 0x019A, 0x019B, 0x026F, 0x0272, 0x019E, 0x0275,
+    /* A */ 0x01A0, 0x01A1, 0x01A3, 0x01A3, 0x01A5, 0x01A5, 0x01A6, 0x01A8,
+            0x01A8, 0x0283, 0x01AA, 0x01AB, 0x01AD, 0x01AD, 0x0288, 0x01AF,
+    /* B */ 0x01B0, 0x028A, 0x028B, 0x01B4, 0x01B4, 0x01B6, 0x01B6, 0x0292,
+            0x01B9, 0x01B9, 0x01BA, 0x01BB, 0x01BD, 0x01BD, 0x01BE, 0x01BF,
+    /* C */ 0x01C0, 0x01C1, 0x01C2, 0x01C3, 0x01C6, 0x01C6, 0x01C6, 0x01C9,
+            0x01C9, 0x01C9, 0x01CC, 0x01CC, 0x01CC, 0x01CD, 0x01CE, 0x01CF,
+    /* D */ 0x01D0, 0x01D1, 0x01D2, 0x01D3, 0x01D4, 0x01D5, 0x01D6, 0x01D7,
+            0x01D8, 0x01D9, 0x01DA, 0x01DB, 0x01DC, 0x01DD, 0x01DE, 0x01DF,
+    /* E */ 0x01E0, 0x01E1, 0x01E2, 0x01E3, 0x01E5, 0x01E5, 0x01E6, 0x01E7,
+            0x01E8, 0x01E9, 0x01EA, 0x01EB, 0x01EC, 0x01ED, 0x01EE, 0x01EF,
+    /* F */ 0x01F0, 0x01F3, 0x01F3, 0x01F3, 0x01F4, 0x01F5, 0x01F6, 0x01F7,
+            0x01F8, 0x01F9, 0x01FA, 0x01FB, 0x01FC, 0x01FD, 0x01FE, 0x01FF,
+
+    // Table 3 (for high byte 0x03)
+
+    /* 0 */ 0x0300, 0x0301, 0x0302, 0x0303, 0x0304, 0x0305, 0x0306, 0x0307,
+            0x0308, 0x0309, 0x030A, 0x030B, 0x030C, 0x030D, 0x030E, 0x030F,
+    /* 1 */ 0x0310, 0x0311, 0x0312, 0x0313, 0x0314, 0x0315, 0x0316, 0x0317,
+            0x0318, 0x0319, 0x031A, 0x031B, 0x031C, 0x031D, 0x031E, 0x031F,
+    /* 2 */ 0x0320, 0x0321, 0x0322, 0x0323, 0x0324, 0x0325, 0x0326, 0x0327,
+            0x0328, 0x0329, 0x032A, 0x032B, 0x032C, 0x032D, 0x032E, 0x032F,
+    /* 3 */ 0x0330, 0x0331, 0x0332, 0x0333, 0x0334, 0x0335, 0x0336, 0x0337,
+            0x0338, 0x0339, 0x033A, 0x033B, 0x033C, 0x033D, 0x033E, 0x033F,
+    /* 4 */ 0x0340, 0x0341, 0x0342, 0x0343, 0x0344, 0x0345, 0x0346, 0x0347,
+            0x0348, 0x0349, 0x034A, 0x034B, 0x034C, 0x034D, 0x034E, 0x034F,
+    /* 5 */ 0x0350, 0x0351, 0x0352, 0x0353, 0x0354, 0x0355, 0x0356, 0x0357,
+            0x0358, 0x0359, 0x035A, 0x035B, 0x035C, 0x035D, 0x035E, 0x035F,
+    /* 6 */ 0x0360, 0x0361, 0x0362, 0x0363, 0x0364, 0x0365, 0x0366, 0x0367,
+            0x0368, 0x0369, 0x036A, 0x036B, 0x036C, 0x036D, 0x036E, 0x036F,
+    /* 7 */ 0x0370, 0x0371, 0x0372, 0x0373, 0x0374, 0x0375, 0x0376, 0x0377,
+            0x0378, 0x0379, 0x037A, 0x037B, 0x037C, 0x037D, 0x037E, 0x037F,
+    /* 8 */ 0x0380, 0x0381, 0x0382, 0x0383, 0x0384, 0x0385, 0x0386, 0x0387,
+            0x0388, 0x0389, 0x038A, 0x038B, 0x038C, 0x038D, 0x038E, 0x038F,
+    /* 9 */ 0x0390, 0x03B1, 0x03B2, 0x03B3, 0x03B4, 0x03B5, 0x03B6, 0x03B7,
+            0x03B8, 0x03B9, 0x03BA, 0x03BB, 0x03BC, 0x03BD, 0x03BE, 0x03BF,
+    /* A */ 0x03C0, 0x03C1, 0x03A2, 0x03C3, 0x03C4, 0x03C5, 0x03C6, 0x03C7,
+            0x03C8, 0x03C9, 0x03AA, 0x03AB, 0x03AC, 0x03AD, 0x03AE, 0x03AF,
+    /* B */ 0x03B0, 0x03B1, 0x03B2, 0x03B3, 0x03B4, 0x03B5, 0x03B6, 0x03B7,
+            0x03B8, 0x03B9, 0x03BA, 0x03BB, 0x03BC, 0x03BD, 0x03BE, 0x03BF,
+    /* C */ 0x03C0, 0x03C1, 0x03C2, 0x03C3, 0x03C4, 0x03C5, 0x03C6, 0x03C7,
+            0x03C8, 0x03C9, 0x03CA, 0x03CB, 0x03CC, 0x03CD, 0x03CE, 0x03CF,
+    /* D */ 0x03D0, 0x03D1, 0x03D2, 0x03D3, 0x03D4, 0x03D5, 0x03D6, 0x03D7,
+            0x03D8, 0x03D9, 0x03DA, 0x03DB, 0x03DC, 0x03DD, 0x03DE, 0x03DF,
+    /* E */ 0x03E0, 0x03E1, 0x03E3, 0x03E3, 0x03E5, 0x03E5, 0x03E7, 0x03E7,
+            0x03E9, 0x03E9, 0x03EB, 0x03EB, 0x03ED, 0x03ED, 0x03EF, 0x03EF,
+    /* F */ 0x03F0, 0x03F1, 0x03F2, 0x03F3, 0x03F4, 0x03F5, 0x03F6, 0x03F7,
+            0x03F8, 0x03F9, 0x03FA, 0x03FB, 0x03FC, 0x03FD, 0x03FE, 0x03FF,
+
+    // Table 4 (for high byte 0x04)
+
+    /* 0 */ 0x0400, 0x0401, 0x0452, 0x0403, 0x0454, 0x0455, 0x0456, 0x0407,
+            0x0458, 0x0459, 0x045A, 0x045B, 0x040C, 0x040D, 0x040E, 0x045F,
+    /* 1 */ 0x0430, 0x0431, 0x0432, 0x0433, 0x0434, 0x0435, 0x0436, 0x0437,
+            0x0438, 0x0419, 0x043A, 0x043B, 0x043C, 0x043D, 0x043E, 0x043F,
+    /* 2 */ 0x0440, 0x0441, 0x0442, 0x0443, 0x0444, 0x0445, 0x0446, 0x0447,
+            0x0448, 0x0449, 0x044A, 0x044B, 0x044C, 0x044D, 0x044E, 0x044F,
+    /* 3 */ 0x0430, 0x0431, 0x0432, 0x0433, 0x0434, 0x0435, 0x0436, 0x0437,
+            0x0438, 0x0439, 0x043A, 0x043B, 0x043C, 0x043D, 0x043E, 0x043F,
+    /* 4 */ 0x0440, 0x0441, 0x0442, 0x0443, 0x0444, 0x0445, 0x0446, 0x0447,
+            0x0448, 0x0449, 0x044A, 0x044B, 0x044C, 0x044D, 0x044E, 0x044F,
+    /* 5 */ 0x0450, 0x0451, 0x0452, 0x0453, 0x0454, 0x0455, 0x0456, 0x0457,
+            0x0458, 0x0459, 0x045A, 0x045B, 0x045C, 0x045D, 0x045E, 0x045F,
+    /* 6 */ 0x0461, 0x0461, 0x0463, 0x0463, 0x0465, 0x0465, 0x0467, 0x0467,
+            0x0469, 0x0469, 0x046B, 0x046B, 0x046D, 0x046D, 0x046F, 0x046F,
+    /* 7 */ 0x0471, 0x0471, 0x0473, 0x0473, 0x0475, 0x0475, 0x0476, 0x0477,
+            0x0479, 0x0479, 0x047B, 0x047B, 0x047D, 0x047D, 0x047F, 0x047F,
+    /* 8 */ 0x0481, 0x0481, 0x0482, 0x0483, 0x0484, 0x0485, 0x0486, 0x0487,
+            0x0488, 0x0489, 0x048A, 0x048B, 0x048C, 0x048D, 0x048E, 0x048F,
+    /* 9 */ 0x0491, 0x0491, 0x0493, 0x0493, 0x0495, 0x0495, 0x0497, 0x0497,
+            0x0499, 0x0499, 0x049B, 0x049B, 0x049D, 0x049D, 0x049F, 0x049F,
+    /* A */ 0x04A1, 0x04A1, 0x04A3, 0x04A3, 0x04A5, 0x04A5, 0x04A7, 0x04A7,
+            0x04A9, 0x04A9, 0x04AB, 0x04AB, 0x04AD, 0x04AD, 0x04AF, 0x04AF,
+    /* B */ 0x04B1, 0x04B1, 0x04B3, 0x04B3, 0x04B5, 0x04B5, 0x04B7, 0x04B7,
+            0x04B9, 0x04B9, 0x04BB, 0x04BB, 0x04BD, 0x04BD, 0x04BF, 0x04BF,
+    /* C */ 0x04C0, 0x04C1, 0x04C2, 0x04C4, 0x04C4, 0x04C5, 0x04C6, 0x04C8,
+            0x04C8, 0x04C9, 0x04CA, 0x04CC, 0x04CC, 0x04CD, 0x04CE, 0x04CF,
+    /* D */ 0x04D0, 0x04D1, 0x04D2, 0x04D3, 0x04D4, 0x04D5, 0x04D6, 0x04D7,
+            0x04D8, 0x04D9, 0x04DA, 0x04DB, 0x04DC, 0x04DD, 0x04DE, 0x04DF,
+    /* E */ 0x04E0, 0x04E1, 0x04E2, 0x04E3, 0x04E4, 0x04E5, 0x04E6, 0x04E7,
+            0x04E8, 0x04E9, 0x04EA, 0x04EB, 0x04EC, 0x04ED, 0x04EE, 0x04EF,
+    /* F */ 0x04F0, 0x04F1, 0x04F2, 0x04F3, 0x04F4, 0x04F5, 0x04F6, 0x04F7,
+            0x04F8, 0x04F9, 0x04FA, 0x04FB, 0x04FC, 0x04FD, 0x04FE, 0x04FF,
+
+    // Table 5 (for high byte 0x05)
+
+    /* 0 */ 0x0500, 0x0501, 0x0502, 0x0503, 0x0504, 0x0505, 0x0506, 0x0507,
+            0x0508, 0x0509, 0x050A, 0x050B, 0x050C, 0x050D, 0x050E, 0x050F,
+    /* 1 */ 0x0510, 0x0511, 0x0512, 0x0513, 0x0514, 0x0515, 0x0516, 0x0517,
+            0x0518, 0x0519, 0x051A, 0x051B, 0x051C, 0x051D, 0x051E, 0x051F,
+    /* 2 */ 0x0520, 0x0521, 0x0522, 0x0523, 0x0524, 0x0525, 0x0526, 0x0527,
+            0x0528, 0x0529, 0x052A, 0x052B, 0x052C, 0x052D, 0x052E, 0x052F,
+    /* 3 */ 0x0530, 0x0561, 0x0562, 0x0563, 0x0564, 0x0565, 0x0566, 0x0567,
+            0x0568, 0x0569, 0x056A, 0x056B, 0x056C, 0x056D, 0x056E, 0x056F,
+    /* 4 */ 0x0570, 0x0571, 0x0572, 0x0573, 0x0574, 0x0575, 0x0576, 0x0577,
+            0x0578, 0x0579, 0x057A, 0x057B, 0x057C, 0x057D, 0x057E, 0x057F,
+    /* 5 */ 0x0580, 0x0581, 0x0582, 0x0583, 0x0584, 0x0585, 0x0586, 0x0557,
+            0x0558, 0x0559, 0x055A, 0x055B, 0x055C, 0x055D, 0x055E, 0x055F,
+    /* 6 */ 0x0560, 0x0561, 0x0562, 0x0563, 0x0564, 0x0565, 0x0566, 0x0567,
+            0x0568, 0x0569, 0x056A, 0x056B, 0x056C, 0x056D, 0x056E, 0x056F,
+    /* 7 */ 0x0570, 0x0571, 0x0572, 0x0573, 0x0574, 0x0575, 0x0576, 0x0577,
+            0x0578, 0x0579, 0x057A, 0x057B, 0x057C, 0x057D, 0x057E, 0x057F,
+    /* 8 */ 0x0580, 0x0581, 0x0582, 0x0583, 0x0584, 0x0585, 0x0586, 0x0587,
+            0x0588, 0x0589, 0x058A, 0x058B, 0x058C, 0x058D, 0x058E, 0x058F,
+    /* 9 */ 0x0590, 0x0591, 0x0592, 0x0593, 0x0594, 0x0595, 0x0596, 0x0597,
+            0x0598, 0x0599, 0x059A, 0x059B, 0x059C, 0x059D, 0x059E, 0x059F,
+    /* A */ 0x05A0, 0x05A1, 0x05A2, 0x05A3, 0x05A4, 0x05A5, 0x05A6, 0x05A7,
+            0x05A8, 0x05A9, 0x05AA, 0x05AB, 0x05AC, 0x05AD, 0x05AE, 0x05AF,
+    /* B */ 0x05B0, 0x05B1, 0x05B2, 0x05B3, 0x05B4, 0x05B5, 0x05B6, 0x05B7,
+            0x05B8, 0x05B9, 0x05BA, 0x05BB, 0x05BC, 0x05BD, 0x05BE, 0x05BF,
+    /* C */ 0x05C0, 0x05C1, 0x05C2, 0x05C3, 0x05C4, 0x05C5, 0x05C6, 0x05C7,
+            0x05C8, 0x05C9, 0x05CA, 0x05CB, 0x05CC, 0x05CD, 0x05CE, 0x05CF,
+    /* D */ 0x05D0, 0x05D1, 0x05D2, 0x05D3, 0x05D4, 0x05D5, 0x05D6, 0x05D7,
+            0x05D8, 0x05D9, 0x05DA, 0x05DB, 0x05DC, 0x05DD, 0x05DE, 0x05DF,
+    /* E */ 0x05E0, 0x05E1, 0x05E2, 0x05E3, 0x05E4, 0x05E5, 0x05E6, 0x05E7,
+            0x05E8, 0x05E9, 0x05EA, 0x05EB, 0x05EC, 0x05ED, 0x05EE, 0x05EF,
+    /* F */ 0x05F0, 0x05F1, 0x05F2, 0x05F3, 0x05F4, 0x05F5, 0x05F6, 0x05F7,
+            0x05F8, 0x05F9, 0x05FA, 0x05FB, 0x05FC, 0x05FD, 0x05FE, 0x05FF,
+
+    // Table 6 (for high byte 0x10)
+
+    /* 0 */ 0x1000, 0x1001, 0x1002, 0x1003, 0x1004, 0x1005, 0x1006, 0x1007,
+            0x1008, 0x1009, 0x100A, 0x100B, 0x100C, 0x100D, 0x100E, 0x100F,
+    /* 1 */ 0x1010, 0x1011, 0x1012, 0x1013, 0x1014, 0x1015, 0x1016, 0x1017,
+            0x1018, 0x1019, 0x101A, 0x101B, 0x101C, 0x101D, 0x101E, 0x101F,
+    /* 2 */ 0x1020, 0x1021, 0x1022, 0x1023, 0x1024, 0x1025, 0x1026, 0x1027,
+            0x1028, 0x1029, 0x102A, 0x102B, 0x102C, 0x102D, 0x102E, 0x102F,
+    /* 3 */ 0x1030, 0x1031, 0x1032, 0x1033, 0x1034, 0x1035, 0x1036, 0x1037,
+            0x1038, 0x1039, 0x103A, 0x103B, 0x103C, 0x103D, 0x103E, 0x103F,
+    /* 4 */ 0x1040, 0x1041, 0x1042, 0x1043, 0x1044, 0x1045, 0x1046, 0x1047,
+            0x1048, 0x1049, 0x104A, 0x104B, 0x104C, 0x104D, 0x104E, 0x104F,
+    /* 5 */ 0x1050, 0x1051, 0x1052, 0x1053, 0x1054, 0x1055, 0x1056, 0x1057,
+            0x1058, 0x1059, 0x105A, 0x105B, 0x105C, 0x105D, 0x105E, 0x105F,
+    /* 6 */ 0x1060, 0x1061, 0x1062, 0x1063, 0x1064, 0x1065, 0x1066, 0x1067,
+            0x1068, 0x1069, 0x106A, 0x106B, 0x106C, 0x106D, 0x106E, 0x106F,
+    /* 7 */ 0x1070, 0x1071, 0x1072, 0x1073, 0x1074, 0x1075, 0x1076, 0x1077,
+            0x1078, 0x1079, 0x107A, 0x107B, 0x107C, 0x107D, 0x107E, 0x107F,
+    /* 8 */ 0x1080, 0x1081, 0x1082, 0x1083, 0x1084, 0x1085, 0x1086, 0x1087,
+            0x1088, 0x1089, 0x108A, 0x108B, 0x108C, 0x108D, 0x108E, 0x108F,
+    /* 9 */ 0x1090, 0x1091, 0x1092, 0x1093, 0x1094, 0x1095, 0x1096, 0x1097,
+            0x1098, 0x1099, 0x109A, 0x109B, 0x109C, 0x109D, 0x109E, 0x109F,
+    /* A */ 0x10D0, 0x10D1, 0x10D2, 0x10D3, 0x10D4, 0x10D5, 0x10D6, 0x10D7,
+            0x10D8, 0x10D9, 0x10DA, 0x10DB, 0x10DC, 0x10DD, 0x10DE, 0x10DF,
+    /* B */ 0x10E0, 0x10E1, 0x10E2, 0x10E3, 0x10E4, 0x10E5, 0x10E6, 0x10E7,
+            0x10E8, 0x10E9, 0x10EA, 0x10EB, 0x10EC, 0x10ED, 0x10EE, 0x10EF,
+    /* C */ 0x10F0, 0x10F1, 0x10F2, 0x10F3, 0x10F4, 0x10F5, 0x10C6, 0x10C7,
+            0x10C8, 0x10C9, 0x10CA, 0x10CB, 0x10CC, 0x10CD, 0x10CE, 0x10CF,
+    /* D */ 0x10D0, 0x10D1, 0x10D2, 0x10D3, 0x10D4, 0x10D5, 0x10D6, 0x10D7,
+            0x10D8, 0x10D9, 0x10DA, 0x10DB, 0x10DC, 0x10DD, 0x10DE, 0x10DF,
+    /* E */ 0x10E0, 0x10E1, 0x10E2, 0x10E3, 0x10E4, 0x10E5, 0x10E6, 0x10E7,
+            0x10E8, 0x10E9, 0x10EA, 0x10EB, 0x10EC, 0x10ED, 0x10EE, 0x10EF,
+    /* F */ 0x10F0, 0x10F1, 0x10F2, 0x10F3, 0x10F4, 0x10F5, 0x10F6, 0x10F7,
+            0x10F8, 0x10F9, 0x10FA, 0x10FB, 0x10FC, 0x10FD, 0x10FE, 0x10FF,
+
+    // Table 7 (for high byte 0x20)
+
+    /* 0 */ 0x2000, 0x2001, 0x2002, 0x2003, 0x2004, 0x2005, 0x2006, 0x2007,
+            0x2008, 0x2009, 0x200A, 0x200B, 0x0000, 0x0000, 0x0000, 0x0000,
+    /* 1 */ 0x2010, 0x2011, 0x2012, 0x2013, 0x2014, 0x2015, 0x2016, 0x2017,
+            0x2018, 0x2019, 0x201A, 0x201B, 0x201C, 0x201D, 0x201E, 0x201F,
+    /* 2 */ 0x2020, 0x2021, 0x2022, 0x2023, 0x2024, 0x2025, 0x2026, 0x2027,
+            0x2028, 0x2029, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x202F,
+    /* 3 */ 0x2030, 0x2031, 0x2032, 0x2033, 0x2034, 0x2035, 0x2036, 0x2037,
+            0x2038, 0x2039, 0x203A, 0x203B, 0x203C, 0x203D, 0x203E, 0x203F,
+    /* 4 */ 0x2040, 0x2041, 0x2042, 0x2043, 0x2044, 0x2045, 0x2046, 0x2047,
+            0x2048, 0x2049, 0x204A, 0x204B, 0x204C, 0x204D, 0x204E, 0x204F,
+    /* 5 */ 0x2050, 0x2051, 0x2052, 0x2053, 0x2054, 0x2055, 0x2056, 0x2057,
+            0x2058, 0x2059, 0x205A, 0x205B, 0x205C, 0x205D, 0x205E, 0x205F,
+    /* 6 */ 0x2060, 0x2061, 0x2062, 0x2063, 0x2064, 0x2065, 0x2066, 0x2067,
+            0x2068, 0x2069, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+    /* 7 */ 0x2070, 0x2071, 0x2072, 0x2073, 0x2074, 0x2075, 0x2076, 0x2077,
+            0x2078, 0x2079, 0x207A, 0x207B, 0x207C, 0x207D, 0x207E, 0x207F,
+    /* 8 */ 0x2080, 0x2081, 0x2082, 0x2083, 0x2084, 0x2085, 0x2086, 0x2087,
+            0x2088, 0x2089, 0x208A, 0x208B, 0x208C, 0x208D, 0x208E, 0x208F,
+    /* 9 */ 0x2090, 0x2091, 0x2092, 0x2093, 0x2094, 0x2095, 0x2096, 0x2097,
+            0x2098, 0x2099, 0x209A, 0x209B, 0x209C, 0x209D, 0x209E, 0x209F,
+    /* A */ 0x20A0, 0x20A1, 0x20A2, 0x20A3, 0x20A4, 0x20A5, 0x20A6, 0x20A7,
+            0x20A8, 0x20A9, 0x20AA, 0x20AB, 0x20AC, 0x20AD, 0x20AE, 0x20AF,
+    /* B */ 0x20B0, 0x20B1, 0x20B2, 0x20B3, 0x20B4, 0x20B5, 0x20B6, 0x20B7,
+            0x20B8, 0x20B9, 0x20BA, 0x20BB, 0x20BC, 0x20BD, 0x20BE, 0x20BF,
+    /* C */ 0x20C0, 0x20C1, 0x20C2, 0x20C3, 0x20C4, 0x20C5, 0x20C6, 0x20C7,
+            0x20C8, 0x20C9, 0x20CA, 0x20CB, 0x20CC, 0x20CD, 0x20CE, 0x20CF,
+    /* D */ 0x20D0, 0x20D1, 0x20D2, 0x20D3, 0x20D4, 0x20D5, 0x20D6, 0x20D7,
+            0x20D8, 0x20D9, 0x20DA, 0x20DB, 0x20DC, 0x20DD, 0x20DE, 0x20DF,
+    /* E */ 0x20E0, 0x20E1, 0x20E2, 0x20E3, 0x20E4, 0x20E5, 0x20E6, 0x20E7,
+            0x20E8, 0x20E9, 0x20EA, 0x20EB, 0x20EC, 0x20ED, 0x20EE, 0x20EF,
+    /* F */ 0x20F0, 0x20F1, 0x20F2, 0x20F3, 0x20F4, 0x20F5, 0x20F6, 0x20F7,
+            0x20F8, 0x20F9, 0x20FA, 0x20FB, 0x20FC, 0x20FD, 0x20FE, 0x20FF,
+
+    // Table 8 (for high byte 0x21)
+
+    /* 0 */ 0x2100, 0x2101, 0x2102, 0x2103, 0x2104, 0x2105, 0x2106, 0x2107,
+            0x2108, 0x2109, 0x210A, 0x210B, 0x210C, 0x210D, 0x210E, 0x210F,
+    /* 1 */ 0x2110, 0x2111, 0x2112, 0x2113, 0x2114, 0x2115, 0x2116, 0x2117,
+            0x2118, 0x2119, 0x211A, 0x211B, 0x211C, 0x211D, 0x211E, 0x211F,
+    /* 2 */ 0x2120, 0x2121, 0x2122, 0x2123, 0x2124, 0x2125, 0x2126, 0x2127,
+            0x2128, 0x2129, 0x212A, 0x212B, 0x212C, 0x212D, 0x212E, 0x212F,
+    /* 3 */ 0x2130, 0x2131, 0x2132, 0x2133, 0x2134, 0x2135, 0x2136, 0x2137,
+            0x2138, 0x2139, 0x213A, 0x213B, 0x213C, 0x213D, 0x213E, 0x213F,
+    /* 4 */ 0x2140, 0x2141, 0x2142, 0x2143, 0x2144, 0x2145, 0x2146, 0x2147,
+            0x2148, 0x2149, 0x214A, 0x214B, 0x214C, 0x214D, 0x214E, 0x214F,
+    /* 5 */ 0x2150, 0x2151, 0x2152, 0x2153, 0x2154, 0x2155, 0x2156, 0x2157,
+            0x2158, 0x2159, 0x215A, 0x215B, 0x215C, 0x215D, 0x215E, 0x215F,
+    /* 6 */ 0x2170, 0x2171, 0x2172, 0x2173, 0x2174, 0x2175, 0x2176, 0x2177,
+            0x2178, 0x2179, 0x217A, 0x217B, 0x217C, 0x217D, 0x217E, 0x217F,
+    /* 7 */ 0x2170, 0x2171, 0x2172, 0x2173, 0x2174, 0x2175, 0x2176, 0x2177,
+            0x2178, 0x2179, 0x217A, 0x217B, 0x217C, 0x217D, 0x217E, 0x217F,
+    /* 8 */ 0x2180, 0x2181, 0x2182, 0x2183, 0x2184, 0x2185, 0x2186, 0x2187,
+            0x2188, 0x2189, 0x218A, 0x218B, 0x218C, 0x218D, 0x218E, 0x218F,
+    /* 9 */ 0x2190, 0x2191, 0x2192, 0x2193, 0x2194, 0x2195, 0x2196, 0x2197,
+            0x2198, 0x2199, 0x219A, 0x219B, 0x219C, 0x219D, 0x219E, 0x219F,
+    /* A */ 0x21A0, 0x21A1, 0x21A2, 0x21A3, 0x21A4, 0x21A5, 0x21A6, 0x21A7,
+            0x21A8, 0x21A9, 0x21AA, 0x21AB, 0x21AC, 0x21AD, 0x21AE, 0x21AF,
+    /* B */ 0x21B0, 0x21B1, 0x21B2, 0x21B3, 0x21B4, 0x21B5, 0x21B6, 0x21B7,
+            0x21B8, 0x21B9, 0x21BA, 0x21BB, 0x21BC, 0x21BD, 0x21BE, 0x21BF,
+    /* C */ 0x21C0, 0x21C1, 0x21C2, 0x21C3, 0x21C4, 0x21C5, 0x21C6, 0x21C7,
+            0x21C8, 0x21C9, 0x21CA, 0x21CB, 0x21CC, 0x21CD, 0x21CE, 0x21CF,
+    /* D */ 0x21D0, 0x21D1, 0x21D2, 0x21D3, 0x21D4, 0x21D5, 0x21D6, 0x21D7,
+            0x21D8, 0x21D9, 0x21DA, 0x21DB, 0x21DC, 0x21DD, 0x21DE, 0x21DF,
+    /* E */ 0x21E0, 0x21E1, 0x21E2, 0x21E3, 0x21E4, 0x21E5, 0x21E6, 0x21E7,
+            0x21E8, 0x21E9, 0x21EA, 0x21EB, 0x21EC, 0x21ED, 0x21EE, 0x21EF,
+    /* F */ 0x21F0, 0x21F1, 0x21F2, 0x21F3, 0x21F4, 0x21F5, 0x21F6, 0x21F7,
+            0x21F8, 0x21F9, 0x21FA, 0x21FB, 0x21FC, 0x21FD, 0x21FE, 0x21FF,
+
+    // Table 9 (for high byte 0xFE)
+
+    /* 0 */ 0xFE00, 0xFE01, 0xFE02, 0xFE03, 0xFE04, 0xFE05, 0xFE06, 0xFE07,
+            0xFE08, 0xFE09, 0xFE0A, 0xFE0B, 0xFE0C, 0xFE0D, 0xFE0E, 0xFE0F,
+    /* 1 */ 0xFE10, 0xFE11, 0xFE12, 0xFE13, 0xFE14, 0xFE15, 0xFE16, 0xFE17,
+            0xFE18, 0xFE19, 0xFE1A, 0xFE1B, 0xFE1C, 0xFE1D, 0xFE1E, 0xFE1F,
+    /* 2 */ 0xFE20, 0xFE21, 0xFE22, 0xFE23, 0xFE24, 0xFE25, 0xFE26, 0xFE27,
+            0xFE28, 0xFE29, 0xFE2A, 0xFE2B, 0xFE2C, 0xFE2D, 0xFE2E, 0xFE2F,
+    /* 3 */ 0xFE30, 0xFE31, 0xFE32, 0xFE33, 0xFE34, 0xFE35, 0xFE36, 0xFE37,
+            0xFE38, 0xFE39, 0xFE3A, 0xFE3B, 0xFE3C, 0xFE3D, 0xFE3E, 0xFE3F,
+    /* 4 */ 0xFE40, 0xFE41, 0xFE42, 0xFE43, 0xFE44, 0xFE45, 0xFE46, 0xFE47,
+            0xFE48, 0xFE49, 0xFE4A, 0xFE4B, 0xFE4C, 0xFE4D, 0xFE4E, 0xFE4F,
+    /* 5 */ 0xFE50, 0xFE51, 0xFE52, 0xFE53, 0xFE54, 0xFE55, 0xFE56, 0xFE57,
+            0xFE58, 0xFE59, 0xFE5A, 0xFE5B, 0xFE5C, 0xFE5D, 0xFE5E, 0xFE5F,
+    /* 6 */ 0xFE60, 0xFE61, 0xFE62, 0xFE63, 0xFE64, 0xFE65, 0xFE66, 0xFE67,
+            0xFE68, 0xFE69, 0xFE6A, 0xFE6B, 0xFE6C, 0xFE6D, 0xFE6E, 0xFE6F,
+    /* 7 */ 0xFE70, 0xFE71, 0xFE72, 0xFE73, 0xFE74, 0xFE75, 0xFE76, 0xFE77,
+            0xFE78, 0xFE79, 0xFE7A, 0xFE7B, 0xFE7C, 0xFE7D, 0xFE7E, 0xFE7F,
+    /* 8 */ 0xFE80, 0xFE81, 0xFE82, 0xFE83, 0xFE84, 0xFE85, 0xFE86, 0xFE87,
+            0xFE88, 0xFE89, 0xFE8A, 0xFE8B, 0xFE8C, 0xFE8D, 0xFE8E, 0xFE8F,
+    /* 9 */ 0xFE90, 0xFE91, 0xFE92, 0xFE93, 0xFE94, 0xFE95, 0xFE96, 0xFE97,
+            0xFE98, 0xFE99, 0xFE9A, 0xFE9B, 0xFE9C, 0xFE9D, 0xFE9E, 0xFE9F,
+    /* A */ 0xFEA0, 0xFEA1, 0xFEA2, 0xFEA3, 0xFEA4, 0xFEA5, 0xFEA6, 0xFEA7,
+            0xFEA8, 0xFEA9, 0xFEAA, 0xFEAB, 0xFEAC, 0xFEAD, 0xFEAE, 0xFEAF,
+    /* B */ 0xFEB0, 0xFEB1, 0xFEB2, 0xFEB3, 0xFEB4, 0xFEB5, 0xFEB6, 0xFEB7,
+            0xFEB8, 0xFEB9, 0xFEBA, 0xFEBB, 0xFEBC, 0xFEBD, 0xFEBE, 0xFEBF,
+    /* C */ 0xFEC0, 0xFEC1, 0xFEC2, 0xFEC3, 0xFEC4, 0xFEC5, 0xFEC6, 0xFEC7,
+            0xFEC8, 0xFEC9, 0xFECA, 0xFECB, 0xFECC, 0xFECD, 0xFECE, 0xFECF,
+    /* D */ 0xFED0, 0xFED1, 0xFED2, 0xFED3, 0xFED4, 0xFED5, 0xFED6, 0xFED7,
+            0xFED8, 0xFED9, 0xFEDA, 0xFEDB, 0xFEDC, 0xFEDD, 0xFEDE, 0xFEDF,
+    /* E */ 0xFEE0, 0xFEE1, 0xFEE2, 0xFEE3, 0xFEE4, 0xFEE5, 0xFEE6, 0xFEE7,
+            0xFEE8, 0xFEE9, 0xFEEA, 0xFEEB, 0xFEEC, 0xFEED, 0xFEEE, 0xFEEF,
+    /* F */ 0xFEF0, 0xFEF1, 0xFEF2, 0xFEF3, 0xFEF4, 0xFEF5, 0xFEF6, 0xFEF7,
+            0xFEF8, 0xFEF9, 0xFEFA, 0xFEFB, 0xFEFC, 0xFEFD, 0xFEFE, 0x0000,
+
+    // Table 10 (for high byte 0xFF)
+
+    /* 0 */ 0xFF00, 0xFF01, 0xFF02, 0xFF03, 0xFF04, 0xFF05, 0xFF06, 0xFF07,
+            0xFF08, 0xFF09, 0xFF0A, 0xFF0B, 0xFF0C, 0xFF0D, 0xFF0E, 0xFF0F,
+    /* 1 */ 0xFF10, 0xFF11, 0xFF12, 0xFF13, 0xFF14, 0xFF15, 0xFF16, 0xFF17,
+            0xFF18, 0xFF19, 0xFF1A, 0xFF1B, 0xFF1C, 0xFF1D, 0xFF1E, 0xFF1F,
+    /* 2 */ 0xFF20, 0xFF41, 0xFF42, 0xFF43, 0xFF44, 0xFF45, 0xFF46, 0xFF47,
+            0xFF48, 0xFF49, 0xFF4A, 0xFF4B, 0xFF4C, 0xFF4D, 0xFF4E, 0xFF4F,
+    /* 3 */ 0xFF50, 0xFF51, 0xFF52, 0xFF53, 0xFF54, 0xFF55, 0xFF56, 0xFF57,
+            0xFF58, 0xFF59, 0xFF5A, 0xFF3B, 0xFF3C, 0xFF3D, 0xFF3E, 0xFF3F,
+    /* 4 */ 0xFF40, 0xFF41, 0xFF42, 0xFF43, 0xFF44, 0xFF45, 0xFF46, 0xFF47,
+            0xFF48, 0xFF49, 0xFF4A, 0xFF4B, 0xFF4C, 0xFF4D, 0xFF4E, 0xFF4F,
+    /* 5 */ 0xFF50, 0xFF51, 0xFF52, 0xFF53, 0xFF54, 0xFF55, 0xFF56, 0xFF57,
+            0xFF58, 0xFF59, 0xFF5A, 0xFF5B, 0xFF5C, 0xFF5D, 0xFF5E, 0xFF5F,
+    /* 6 */ 0xFF60, 0xFF61, 0xFF62, 0xFF63, 0xFF64, 0xFF65, 0xFF66, 0xFF67,
+            0xFF68, 0xFF69, 0xFF6A, 0xFF6B, 0xFF6C, 0xFF6D, 0xFF6E, 0xFF6F,
+    /* 7 */ 0xFF70, 0xFF71, 0xFF72, 0xFF73, 0xFF74, 0xFF75, 0xFF76, 0xFF77,
+            0xFF78, 0xFF79, 0xFF7A, 0xFF7B, 0xFF7C, 0xFF7D, 0xFF7E, 0xFF7F,
+    /* 8 */ 0xFF80, 0xFF81, 0xFF82, 0xFF83, 0xFF84, 0xFF85, 0xFF86, 0xFF87,
+            0xFF88, 0xFF89, 0xFF8A, 0xFF8B, 0xFF8C, 0xFF8D, 0xFF8E, 0xFF8F,
+    /* 9 */ 0xFF90, 0xFF91, 0xFF92, 0xFF93, 0xFF94, 0xFF95, 0xFF96, 0xFF97,
+            0xFF98, 0xFF99, 0xFF9A, 0xFF9B, 0xFF9C, 0xFF9D, 0xFF9E, 0xFF9F,
+    /* A */ 0xFFA0, 0xFFA1, 0xFFA2, 0xFFA3, 0xFFA4, 0xFFA5, 0xFFA6, 0xFFA7,
+            0xFFA8, 0xFFA9, 0xFFAA, 0xFFAB, 0xFFAC, 0xFFAD, 0xFFAE, 0xFFAF,
+    /* B */ 0xFFB0, 0xFFB1, 0xFFB2, 0xFFB3, 0xFFB4, 0xFFB5, 0xFFB6, 0xFFB7,
+            0xFFB8, 0xFFB9, 0xFFBA, 0xFFBB, 0xFFBC, 0xFFBD, 0xFFBE, 0xFFBF,
+    /* C */ 0xFFC0, 0xFFC1, 0xFFC2, 0xFFC3, 0xFFC4, 0xFFC5, 0xFFC6, 0xFFC7,
+            0xFFC8, 0xFFC9, 0xFFCA, 0xFFCB, 0xFFCC, 0xFFCD, 0xFFCE, 0xFFCF,
+    /* D */ 0xFFD0, 0xFFD1, 0xFFD2, 0xFFD3, 0xFFD4, 0xFFD5, 0xFFD6, 0xFFD7,
+            0xFFD8, 0xFFD9, 0xFFDA, 0xFFDB, 0xFFDC, 0xFFDD, 0xFFDE, 0xFFDF,
+    /* E */ 0xFFE0, 0xFFE1, 0xFFE2, 0xFFE3, 0xFFE4, 0xFFE5, 0xFFE6, 0xFFE7,
+            0xFFE8, 0xFFE9, 0xFFEA, 0xFFEB, 0xFFEC, 0xFFED, 0xFFEE, 0xFFEF,
+    /* F */ 0xFFF0, 0xFFF1, 0xFFF2, 0xFFF3, 0xFFF4, 0xFFF5, 0xFFF6, 0xFFF7,
+            0xFFF8, 0xFFF9, 0xFFFA, 0xFFFB, 0xFFFC, 0xFFFD, 0xFFFE, 0xFFFF,
+};
--- diff/fs/hfsplus/unicode.c	1970-01-01 01:00:00.000000000 +0100
+++ source/fs/hfsplus/unicode.c	2004-02-23 13:56:46.000000000 +0000
@@ -0,0 +1,140 @@
+/*
+ *  linux/fs/hfsplus/unicode.c
+ *
+ * Copyright (C) 2001
+ * Brad Boyer (flar@allandria.com)
+ * (C) 2003 Ardis Technologies <roman@ardistech.com>
+ *
+ * Handler routines for unicode strings
+ */
+
+#include <linux/types.h>
+#include <linux/nls.h>
+#include "hfsplus_fs.h"
+#include "hfsplus_raw.h"
+
+/* Fold the case of a unicode char, given the 16 bit value */
+/* Returns folded char, or 0 if ignorable */
+static inline u16 case_fold(u16 c)
+{
+        u16 tmp;
+
+        tmp = case_fold_table[(c>>8)];
+        if (tmp)
+                tmp = case_fold_table[tmp + (c & 0xFF)];
+        else
+                tmp = c;
+        return tmp;
+}
+
+/* Compare unicode strings, return values like normal strcmp */
+int hfsplus_unistrcmp(const struct hfsplus_unistr *s1, const struct hfsplus_unistr *s2)
+{
+	u16 len1, len2, c1, c2;
+	const hfsplus_unichr *p1, *p2;
+
+	len1 = be16_to_cpu(s1->length);
+	len2 = be16_to_cpu(s2->length);
+	p1 = s1->unicode;
+	p2 = s2->unicode;
+
+	while (1) {
+		c1 = c2 = 0;
+
+		while (len1 && !c1) {
+			c1 = case_fold(be16_to_cpu(*p1));
+			p1++;
+			len1--;
+		}
+		while (len2 && !c2) {
+			c2 = case_fold(be16_to_cpu(*p2));
+			p2++;
+			len2--;
+		}
+
+		if (c1 != c2)
+			return (c1 < c2) ? -1 : 1;
+		if (!c1 && !c2)
+			return 0;
+	}
+}
+
+int hfsplus_uni2asc(const struct hfsplus_unistr *ustr, char *astr, int *len)
+{
+	const hfsplus_unichr *ip;
+	u8 *op;
+	u16 ustrlen, cc;
+	int size, tmp;
+
+	op = astr;
+	ip = ustr->unicode;
+	ustrlen = be16_to_cpu(ustr->length);
+	tmp = *len;
+	while (ustrlen > 0 && tmp > 0) {
+		cc = be16_to_cpu(*ip);
+		switch (cc) {
+		case 0:
+			cc = 0x2400;
+			break;
+		case '/':
+			cc = ':';
+			break;
+		}
+		if (cc > 0x7f) {
+			size = utf8_wctomb(op, cc, tmp);
+			if (size == -1) {
+				/* ignore */
+			} else {
+				op += size;
+				tmp -= size;
+			}
+		} else {
+			*op++ = (u8) cc;
+			tmp--;
+		}
+		ip++;
+		ustrlen--;
+	}
+	*len = (char *)op - astr;
+	if (ustrlen)
+		return -ENAMETOOLONG;
+	return 0;
+}
+
+int hfsplus_asc2uni(struct hfsplus_unistr *ustr, const char *astr, int len)
+{
+	int tmp;
+	wchar_t c;
+	u16 outlen = 0;
+
+	while (outlen <= HFSPLUS_MAX_STRLEN && len > 0) {
+		if (*astr & 0x80) {
+			tmp = utf8_mbtowc(&c, astr, len);
+			if (tmp < 0) {
+				astr++;
+				len--;
+				continue;
+			} else {
+				astr += tmp;
+				len -= tmp;
+			}
+		} else {
+			c = *astr++;
+			len--;
+		}
+		switch (c) {
+		case 0x2400:
+			c = 0;
+			break;
+		case ':':
+			c = '/';
+			break;
+		}
+		ustr->unicode[outlen] = cpu_to_be16(c);
+		outlen++;
+	}
+	ustr->length = cpu_to_be16(outlen);
+	if (len > 0)
+		return -ENAMETOOLONG;
+	return 0;
+}
--- diff/fs/hfsplus/wrapper.c	1970-01-01 01:00:00.000000000 +0100
+++ source/fs/hfsplus/wrapper.c	2004-02-23 13:56:46.000000000 +0000
@@ -0,0 +1,171 @@
+/*
+ *  linux/fs/hfsplus/wrapper.c
+ *
+ * Copyright (C) 2001
+ * Brad Boyer (flar@allandria.com)
+ * (C) 2003 Ardis Technologies <roman@ardistech.com>
+ *
+ * Handling of HFS wrappers around HFS+ volumes
+ */
+
+#include <linux/fs.h>
+#include <linux/blkdev.h>
+#include <linux/cdrom.h>
+#include <linux/genhd.h>
+#include <linux/version.h>
+#include <asm/unaligned.h>
+
+#include "hfsplus_fs.h"
+#include "hfsplus_raw.h"
+
+struct hfsplus_wd {
+	u32 ablk_size;
+	u16 ablk_start;
+	u16 embed_start;
+	u16 embed_count;
+};
+
+static int hfsplus_read_mdb(void *bufptr, struct hfsplus_wd *wd)
+{
+	u32 extent;
+	u16 attrib;
+
+	if (be16_to_cpu(*(u16 *)(bufptr + HFSP_WRAPOFF_EMBEDSIG)) != HFSPLUS_VOLHEAD_SIG)
+		return 0;
+
+	attrib = be16_to_cpu(*(u16 *)(bufptr + HFSP_WRAPOFF_ATTRIB));
+	if (!(attrib & HFSP_WRAP_ATTRIB_SLOCK) ||
+	   !(attrib & HFSP_WRAP_ATTRIB_SPARED))
+		return 0;
+
+	wd->ablk_size = be32_to_cpu(*(u32 *)(bufptr + HFSP_WRAPOFF_ABLKSIZE));
+	if (wd->ablk_size < HFSPLUS_SECTOR_SIZE)
+		return 0;
+	if (wd->ablk_size % HFSPLUS_SECTOR_SIZE)
+		return 0;
+	wd->ablk_start = be16_to_cpu(*(u16 *)(bufptr + HFSP_WRAPOFF_ABLKSTART));
+
+	extent = be32_to_cpu(get_unaligned((u32 *)(bufptr + HFSP_WRAPOFF_EMBEDEXT)));
+	wd->embed_start = (extent >> 16) & 0xFFFF;
+	wd->embed_count = extent & 0xFFFF;
+
+	return 1;
+}
+
+static int hfsplus_get_last_session(struct super_block *sb,
+				    sector_t *start, sector_t *size)
+{
+	struct cdrom_multisession ms_info;
+	struct cdrom_tocentry te;
+	int res;
+
+	/* default values */
+	*start = 0;
+	*size = sb->s_bdev->bd_inode->i_size >> 9;
+
+	if (HFSPLUS_SB(sb).session >= 0) {
+		te.cdte_track = HFSPLUS_SB(sb).session;
+		te.cdte_format = CDROM_LBA;
+		res = ioctl_by_bdev(sb->s_bdev, CDROMREADTOCENTRY, (unsigned long)&te);
+		if (!res && (te.cdte_ctrl & CDROM_DATA_TRACK) == 4) {
+			*start = (sector_t)te.cdte_addr.lba << 2;
+			return 0;
+		}
+		printk(KERN_ERR "HFS: Invalid session number or type of track\n");
+		return -EINVAL;
+	}
+	ms_info.addr_format = CDROM_LBA;
+	res = ioctl_by_bdev(sb->s_bdev, CDROMMULTISESSION, (unsigned long)&ms_info);
+	if (!res && ms_info.xa_flag)
+		*start = (sector_t)ms_info.addr.lba << 2;
+	return 0;
+}
+
+/* Find the volume header and fill in some minimum bits in superblock */
+/* Takes in super block, returns true if good data read */
+int hfsplus_read_wrapper(struct super_block *sb)
+{
+	struct buffer_head *bh;
+	struct hfsplus_vh *vhdr;
+	struct hfsplus_wd wd;
+	sector_t part_start, part_size;
+	u32 blocksize;
+
+	blocksize = sb_min_blocksize(sb, HFSPLUS_SECTOR_SIZE);
+	if (!blocksize)
+		return -EINVAL;
+
+	if (hfsplus_get_last_session(sb, &part_start, &part_size))
+		return -EINVAL;
+	while (1) {
+		bh = sb_bread512(sb, part_start + HFSPLUS_VOLHEAD_SECTOR, vhdr);
+		if (!bh)
+			return -EIO;
+
+		if (vhdr->signature == cpu_to_be16(HFSP_WRAP_MAGIC)) {
+			if (!hfsplus_read_mdb(vhdr, &wd))
+				goto error;
+			wd.ablk_size >>= HFSPLUS_SECTOR_SHIFT;
+			part_start += wd.ablk_start + wd.embed_start * wd.ablk_size;
+			part_size = wd.embed_count * wd.ablk_size;
+			brelse(bh);
+			bh = sb_bread512(sb, part_start + HFSPLUS_VOLHEAD_SECTOR, vhdr);
+			if (!bh)
+				return -EIO;
+		}
+		if (vhdr->signature == cpu_to_be16(HFSPLUS_VOLHEAD_SIG))
+			break;
+		brelse(bh);
+
+		/* check for a partition block
+		 * (should do this only for cdrom/loop though)
+		 */
+		if (hfs_part_find(sb, &part_start, &part_size))
+			return -EINVAL;
+	}
+
+	blocksize = be32_to_cpu(vhdr->blocksize);
+	brelse(bh);
+
+	/* block size must be at least as large as a sector
+	 * and a multiple of 2
+	 */
+	if (blocksize < HFSPLUS_SECTOR_SIZE ||
+	    ((blocksize - 1) & blocksize))
+		return -EINVAL;
+	HFSPLUS_SB(sb).alloc_blksz = blocksize;
+	HFSPLUS_SB(sb).alloc_blksz_shift = 0;
+	while (blocksize >>= 1)
+		HFSPLUS_SB(sb).alloc_blksz_shift++;
+	blocksize = min(HFSPLUS_SB(sb).alloc_blksz, (u32)PAGE_SIZE);
+
+	/* align block size to block offset */
+	while (part_start & ((blocksize >> HFSPLUS_SECTOR_SHIFT) - 1))
+		blocksize >>= 1;
+
+	if (sb_set_blocksize(sb, blocksize) != blocksize) {
+		printk("HFS+: unable to blocksize to %u!\n", blocksize);
+		return -EINVAL;
+	}
+
+	HFSPLUS_SB(sb).blockoffset = part_start >>
+			(sb->s_blocksize_bits - HFSPLUS_SECTOR_SHIFT);
+	HFSPLUS_SB(sb).sect_count = part_size;
+	HFSPLUS_SB(sb).fs_shift = HFSPLUS_SB(sb).alloc_blksz_shift -
+			sb->s_blocksize_bits;
+
+	bh = sb_bread512(sb, part_start + HFSPLUS_VOLHEAD_SECTOR, vhdr);
+	if (!bh)
+		return -EIO;
+
+	/* should still be the same... */
+	if (be16_to_cpu(vhdr->signature) != HFSPLUS_VOLHEAD_SIG)
+		goto error;
+	HFSPLUS_SB(sb).s_vhbh = bh;
+	HFSPLUS_SB(sb).s_vhdr = vhdr;
+
+	return 0;
+ error:
+	brelse(bh);
+	return -EINVAL;
+}
--- diff/include/asm-alpha/lockmeter.h	1970-01-01 01:00:00.000000000 +0100
+++ source/include/asm-alpha/lockmeter.h	2004-02-23 13:56:47.000000000 +0000
@@ -0,0 +1,84 @@
+/*
+ *  Written by John Hawkes (hawkes@sgi.com)
+ *  Based on klstat.h by Jack Steiner (steiner@sgi.com)
+ *
+ *  Modified by Peter Rival (frival@zk3.dec.com)
+ */
+
+#ifndef _ALPHA_LOCKMETER_H
+#define _ALPHA_LOCKMETER_H
+
+#include <asm/hwrpb.h>
+#define CPU_CYCLE_FREQUENCY	hwrpb->cycle_freq
+
+#define get_cycles64()		get_cycles()
+
+#define THIS_CPU_NUMBER		smp_processor_id()
+
+#include <linux/version.h>
+
+#define SPINLOCK_MAGIC_INIT /**/
+
+/*
+ * Macros to cache and retrieve an index value inside of a lock
+ * these macros assume that there are less than 65536 simultaneous
+ * (read mode) holders of a rwlock.
+ * We also assume that the hash table has less than 32767 entries.
+ * the high order bit is used for write locking a rw_lock
+ * Note: although these defines and macros are the same as what is being used
+ *       in include/asm-i386/lockmeter.h, they are present here to easily
+ *	 allow an alternate Alpha implementation.
+ */
+/*
+ * instrumented spinlock structure -- never used to allocate storage
+ * only used in macros below to overlay a spinlock_t
+ */
+typedef struct inst_spinlock_s {
+	/* remember, Alpha is little endian */
+	unsigned short lock;
+	unsigned short index;
+} inst_spinlock_t;
+#define PUT_INDEX(lock_ptr,indexv)	((inst_spinlock_t *)(lock_ptr))->index = indexv
+#define GET_INDEX(lock_ptr)		((inst_spinlock_t *)(lock_ptr))->index
+
+/*
+ * macros to cache and retrieve an index value in a read/write lock
+ * as well as the cpu where a reader busy period started
+ * we use the 2nd word (the debug word) for this, so require the
+ * debug word to be present
+ */
+/*
+ * instrumented rwlock structure -- never used to allocate storage
+ * only used in macros below to overlay a rwlock_t
+ */
+typedef struct inst_rwlock_s {
+	volatile int lock;
+	unsigned short index;
+	unsigned short cpu;
+} inst_rwlock_t;
+#define PUT_RWINDEX(rwlock_ptr,indexv)	((inst_rwlock_t *)(rwlock_ptr))->index = indexv
+#define GET_RWINDEX(rwlock_ptr)		((inst_rwlock_t *)(rwlock_ptr))->index
+#define PUT_RW_CPU(rwlock_ptr,cpuv)	((inst_rwlock_t *)(rwlock_ptr))->cpu = cpuv
+#define GET_RW_CPU(rwlock_ptr)		((inst_rwlock_t *)(rwlock_ptr))->cpu
+
+/*
+ * return true if rwlock is write locked
+ * (note that other lock attempts can cause the lock value to be negative)
+ */
+#define RWLOCK_IS_WRITE_LOCKED(rwlock_ptr) (((inst_rwlock_t *)rwlock_ptr)->lock & 1)
+#define IABS(x) ((x) > 0 ? (x) : -(x))
+
+#define RWLOCK_READERS(rwlock_ptr)	rwlock_readers(rwlock_ptr)
+extern inline int rwlock_readers(rwlock_t *rwlock_ptr)
+{
+	int tmp = (int) ((inst_rwlock_t *)rwlock_ptr)->lock;
+	/* readers subtract 2, so we have to:		*/
+	/* 	- andnot off a possible writer (bit 0)	*/
+	/*	- get the absolute value		*/
+	/*	- divide by 2 (right shift by one)	*/
+	/* to find the number of readers		*/
+	if (tmp == 0) return(0);
+	else return(IABS(tmp & ~1)>>1);
+}
+
+#endif /* _ALPHA_LOCKMETER_H */
--- diff/include/asm-generic/compat_signal.h	1970-01-01 01:00:00.000000000 +0100
+++ source/include/asm-generic/compat_signal.h	2004-02-23 13:56:47.000000000 +0000
@@ -0,0 +1,25 @@
+#ifndef _ASM_GENERIC_COMPAT_SIGNAL_H
+#define _ASM_GENERIC_COMPAT_SIGNAL_H
+
+#ifndef __ASSEMBLY__
+#include <linux/compat.h>
+
+typedef compat_uptr_t compat_sighandler_t;
+
+typedef struct compat_sigaltstack {
+	compat_uptr_t ss_sp;
+	compat_int_t ss_flags;
+	compat_size_t ss_size;
+} compat_stack_t;
+
+/* Most things should be clean enough to redefine this at will, if care
+   is taken to make libc match.  */
+
+struct compat_sigaction {
+	compat_sighandler_t sa_handler;
+	compat_uint_t sa_flags;
+	compat_sigset_t sa_mask;		/* mask last for extensibility */
+};
+
+#endif /* !__ASSEMBLY__ */
+#endif /* !_ASM_GENERIC_COMPAT_SIGNAL_H */
--- diff/include/asm-generic/dma-mapping-broken.h	1970-01-01 01:00:00.000000000 +0100
+++ source/include/asm-generic/dma-mapping-broken.h	2004-02-23 13:56:47.000000000 +0000
@@ -0,0 +1,22 @@
+#ifndef _ASM_GENERIC_DMA_MAPPING_H
+#define _ASM_GENERIC_DMA_MAPPING_H
+
+/* This is used for archs that do not support DMA */
+
+
+static inline void *
+dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_handle,
+		   int flag)
+{
+	BUG();
+	return 0;
+}
+
+static inline void
+dma_free_coherent(struct device *dev, size_t size, void *cpu_addr,
+		    dma_addr_t dma_handle)
+{
+	BUG();
+}
+
+#endif /* _ASM_GENERIC_DMA_MAPPING_H */
--- diff/include/asm-i386/atomic_kmap.h	1970-01-01 01:00:00.000000000 +0100
+++ source/include/asm-i386/atomic_kmap.h	2004-02-23 13:56:47.000000000 +0000
@@ -0,0 +1,95 @@
+/*
+ * atomic_kmap.h: temporary virtual kernel memory mappings
+ *
+ * Copyright (C) 2003 Ingo Molnar <mingo@redhat.com>
+ */
+
+#ifndef _ASM_ATOMIC_KMAP_H
+#define _ASM_ATOMIC_KMAP_H
+
+#ifdef __KERNEL__
+
+#include <linux/config.h>
+#include <asm/tlbflush.h>
+
+#ifdef CONFIG_DEBUG_HIGHMEM
+#define HIGHMEM_DEBUG 1
+#else
+#define HIGHMEM_DEBUG 0
+#endif
+
+extern pte_t *kmap_pte;
+#define kmap_prot PAGE_KERNEL
+
+#define PKMAP_BASE (0xff000000UL)
+#define NR_SHARED_PMDS ((0xffffffff-PKMAP_BASE+1)/PMD_SIZE)
+
+static inline unsigned long __kmap_atomic_vaddr(enum km_type type)
+{
+	enum fixed_addresses idx;
+
+	idx = type + KM_TYPE_NR*smp_processor_id();
+	return __fix_to_virt(FIX_KMAP_BEGIN + idx);
+}
+
+static inline void *__kmap_atomic_noflush(struct page *page, enum km_type type)
+{
+	enum fixed_addresses idx;
+	unsigned long vaddr;
+
+	idx = type + KM_TYPE_NR*smp_processor_id();
+	vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx);
+	/*
+	 * NOTE: entries that rely on some secondary TLB-flush
+	 * effect must not be global:
+	 */
+	set_pte(kmap_pte-idx, mk_pte(page, PAGE_KERNEL));
+
+	return (void*) vaddr;
+}
+
+static inline void *__kmap_atomic(struct page *page, enum km_type type)
+{
+	enum fixed_addresses idx;
+	unsigned long vaddr;
+
+	idx = type + KM_TYPE_NR*smp_processor_id();
+	vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx);
+#if HIGHMEM_DEBUG
+	BUG_ON(!pte_none(*(kmap_pte-idx)));
+#else
+	/*
+	 * Performance optimization - do not flush if the new
+	 * pte is the same as the old one:
+	 */
+	if (pte_val(*(kmap_pte-idx)) == pte_val(mk_pte(page, kmap_prot)))
+		return (void *) vaddr;
+#endif
+	set_pte(kmap_pte-idx, mk_pte(page, kmap_prot));
+	__flush_tlb_one(vaddr);
+
+	return (void*) vaddr;
+}
+
+static inline void __kunmap_atomic(void *kvaddr, enum km_type type)
+{
+#if HIGHMEM_DEBUG
+	unsigned long vaddr = (unsigned long) kvaddr & PAGE_MASK;
+	enum fixed_addresses idx = type + KM_TYPE_NR*smp_processor_id();
+
+	BUG_ON(vaddr != __fix_to_virt(FIX_KMAP_BEGIN+idx));
+	/*
+	 * force other mappings to Oops if they'll try to access
+	 * this pte without first remap it
+	 */
+	pte_clear(kmap_pte-idx);
+	__flush_tlb_one(vaddr);
+#endif
+}
+
+#define __kunmap_atomic_type(type) \
+		__kunmap_atomic((void *)__kmap_atomic_vaddr(type), (type))
+
+#endif /* __KERNEL__ */
+
+#endif /* _ASM_ATOMIC_KMAP_H */
--- diff/include/asm-i386/kgdb.h	1970-01-01 01:00:00.000000000 +0100
+++ source/include/asm-i386/kgdb.h	2004-02-23 13:56:47.000000000 +0000
@@ -0,0 +1,69 @@
+#ifndef __KGDB
+#define __KGDB
+
+/*
+ * This file should not include ANY others.  This makes it usable
+ * most anywhere without the fear of include order or inclusion.
+ * Make it so!
+ *
+ * This file may be included all the time.  It is only active if
+ * CONFIG_KGDB is defined, otherwise it stubs out all the macros
+ * and entry points.
+ */
+#if defined(CONFIG_KGDB) && !defined(__ASSEMBLY__)
+
+extern void breakpoint(void);
+#define INIT_KGDB_INTS kgdb_enable_ints()
+
+#ifndef BREAKPOINT
+#define BREAKPOINT   asm("   int $3")
+#endif
+
+extern void kgdb_schedule_breakpoint(void);
+extern void kgdb_process_breakpoint(void);
+
+extern int kgdb_tty_hook(void);
+extern int kgdb_eth_hook(void);
+extern int kgdboe;
+
+/*
+ * GDB debug stub (or any debug stub) can point the 'linux_debug_hook'
+ * pointer to its routine and it will be entered as the first thing
+ * when a trap occurs.
+ *
+ * Return values are, at present, undefined.
+ *
+ * The debug hook routine does not necessarily return to its caller.
+ * It has the register image and thus may choose to resume execution
+ * anywhere it pleases.
+ */
+struct pt_regs;
+
+extern int kgdb_handle_exception(int trapno,
+				 int signo, int err_code, struct pt_regs *regs);
+extern int in_kgdb(struct pt_regs *regs);
+
+#ifdef CONFIG_KGDB_TS
+void kgdb_tstamp(int line, char *source, int data0, int data1);
+/*
+ * This is the time stamp function.  The macro adds the source info and
+ * does a cast on the data to allow most any 32-bit value.
+ */
+
+#define kgdb_ts(data0,data1) kgdb_tstamp(__LINE__,__FILE__,(int)data0,(int)data1)
+#else
+#define kgdb_ts(data0,data1)
+#endif
+#else				/* CONFIG_KGDB  && ! __ASSEMBLY__ ,stubs follow... */
+#ifndef BREAKPOINT
+#define BREAKPOINT
+#endif
+#define kgdb_ts(data0,data1)
+#define in_kgdb
+#define kgdb_handle_exception
+#define breakpoint
+#define INIT_KGDB_INTS
+#define kgdb_process_breakpoint() do {} while(0)
+
+#endif
+#endif				/* __KGDB */
--- diff/include/asm-i386/kgdb_local.h	1970-01-01 01:00:00.000000000 +0100
+++ source/include/asm-i386/kgdb_local.h	2004-02-23 13:56:47.000000000 +0000
@@ -0,0 +1,102 @@
+#ifndef __KGDB_LOCAL
+#define ___KGDB_LOCAL
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/serial.h>
+#include <linux/serialP.h>
+#include <linux/spinlock.h>
+#include <asm/processor.h>
+#include <asm/msr.h>
+#include <asm/kgdb.h>
+
+#define PORT 0x3f8
+#ifdef CONFIG_KGDB_PORT
+#undef PORT
+#define PORT CONFIG_KGDB_PORT
+#endif
+#define IRQ 4
+#ifdef CONFIG_KGDB_IRQ
+#undef IRQ
+#define IRQ CONFIG_KGDB_IRQ
+#endif
+#define SB_CLOCK 1843200
+#define SB_BASE (SB_CLOCK/16)
+#define SB_BAUD9600 SB_BASE/9600
+#define SB_BAUD192  SB_BASE/19200
+#define SB_BAUD384  SB_BASE/38400
+#define SB_BAUD576  SB_BASE/57600
+#define SB_BAUD1152 SB_BASE/115200
+#ifdef CONFIG_KGDB_9600BAUD
+#define SB_BAUD SB_BAUD9600
+#endif
+#ifdef CONFIG_KGDB_19200BAUD
+#define SB_BAUD SB_BAUD192
+#endif
+#ifdef CONFIG_KGDB_38400BAUD
+#define SB_BAUD SB_BAUD384
+#endif
+#ifdef CONFIG_KGDB_57600BAUD
+#define SB_BAUD SB_BAUD576
+#endif
+#ifdef CONFIG_KGDB_115200BAUD
+#define SB_BAUD SB_BAUD1152
+#endif
+#ifndef SB_BAUD
+#define SB_BAUD SB_BAUD1152	/* Start with this if not given */
+#endif
+
+#ifndef CONFIG_X86_TSC
+#undef rdtsc
+#define rdtsc(a,b) if (a++ > 10000){a = 0; b++;}
+#undef rdtscll
+#define rdtscll(s) s++
+#endif
+
+#ifdef _raw_read_unlock		/* must use a name that is "define"ed, not an inline */
+#undef spin_lock
+#undef spin_trylock
+#undef spin_unlock
+#define spin_lock	 _raw_spin_lock
+#define spin_trylock	 _raw_spin_trylock
+#define spin_unlock	 _raw_spin_unlock
+#else
+#endif
+#undef spin_unlock_wait
+#define spin_unlock_wait(x)  do { cpu_relax(); barrier();} \
+                                     while(spin_is_locked(x))
+
+#define SB_IER 1
+#define SB_MCR UART_MCR_OUT2 | UART_MCR_DTR | UART_MCR_RTS
+
+#define FLAGS 0
+#define SB_STATE { \
+     magic: SSTATE_MAGIC, \
+     baud_base: SB_BASE,  \
+     port:      PORT,     \
+     irq:       IRQ,      \
+     flags:     FLAGS,    \
+     custom_divisor:SB_BAUD}
+#define SB_INFO  { \
+      magic: SERIAL_MAGIC, \
+      port:  PORT,0,FLAGS, \
+      state: &state,       \
+      tty:   (struct tty_struct *)&state, \
+      IER:   SB_IER,       \
+      MCR:   SB_MCR}
+extern void putDebugChar(int);
+/* RTAI support needs us to really stop/start interrupts */
+
+#define kgdb_sti() __asm__ __volatile__("sti": : :"memory")
+#define kgdb_cli() __asm__ __volatile__("cli": : :"memory")
+#define kgdb_local_save_flags(x) __asm__ __volatile__(\
+                                   "pushfl ; popl %0":"=g" (x): /* no input */)
+#define kgdb_local_irq_restore(x) __asm__ __volatile__(\
+                                   "pushl %0 ; popfl": \
+                                     /* no output */ :"g" (x):"memory", "cc")
+#define kgdb_local_irq_save(x) kgdb_local_save_flags(x); kgdb_cli()
+
+#ifdef CONFIG_SERIAL
+extern void shutdown_for_kgdb(struct async_struct *info);
+#endif
+#define INIT_KDEBUG putDebugChar("+");
+#endif				/* __KGDB_LOCAL */
--- diff/include/asm-i386/lockmeter.h	1970-01-01 01:00:00.000000000 +0100
+++ source/include/asm-i386/lockmeter.h	2004-02-23 13:56:47.000000000 +0000
@@ -0,0 +1,115 @@
+/*
+ *  Copyright (C) 1999,2000 Silicon Graphics, Inc.
+ *
+ *  Written by John Hawkes (hawkes@sgi.com)
+ *  Based on klstat.h by Jack Steiner (steiner@sgi.com)
+ *
+ *  Modified by Ray Bryant (raybry@us.ibm.com)
+ *  Changes Copyright (C) 2000 IBM, Inc.
+ *  Added save of index in spinlock_t to improve efficiency
+ *  of "hold" time reporting for spinlocks.
+ *  Added support for hold time statistics for read and write
+ *  locks.
+ *  Moved machine dependent code here from include/lockmeter.h.
+ *
+ */
+
+#ifndef _I386_LOCKMETER_H
+#define _I386_LOCKMETER_H
+
+#include <asm/spinlock.h>
+#include <asm/rwlock.h>
+
+#include <linux/version.h>
+
+#ifdef __KERNEL__
+extern unsigned long cpu_khz;
+#define CPU_CYCLE_FREQUENCY	(cpu_khz * 1000)
+#else
+#define CPU_CYCLE_FREQUENCY	450000000
+#endif
+
+#define THIS_CPU_NUMBER		smp_processor_id()
+
+/*
+ * macros to cache and retrieve an index value inside of a spin lock
+ * these macros assume that there are less than 65536 simultaneous
+ * (read mode) holders of a rwlock.  Not normally a problem!!
+ * we also assume that the hash table has less than 65535 entries.
+ */
+/*
+ * instrumented spinlock structure -- never used to allocate storage
+ * only used in macros below to overlay a spinlock_t
+ */
+typedef struct inst_spinlock_s {
+	/* remember, Intel is little endian */
+	unsigned short lock;
+	unsigned short index;
+} inst_spinlock_t;
+#define PUT_INDEX(lock_ptr,indexv) ((inst_spinlock_t *)(lock_ptr))->index = indexv
+#define GET_INDEX(lock_ptr)        ((inst_spinlock_t *)(lock_ptr))->index
+
+/*
+ * macros to cache and retrieve an index value in a read/write lock
+ * as well as the cpu where a reader busy period started
+ * we use the 2nd word (the debug word) for this, so require the
+ * debug word to be present
+ */
+/*
+ * instrumented rwlock structure -- never used to allocate storage
+ * only used in macros below to overlay a rwlock_t
+ */
+typedef struct inst_rwlock_s {
+	volatile int lock;
+	unsigned short index;
+	unsigned short cpu;
+} inst_rwlock_t;
+#define PUT_RWINDEX(rwlock_ptr,indexv) ((inst_rwlock_t *)(rwlock_ptr))->index = indexv
+#define GET_RWINDEX(rwlock_ptr)        ((inst_rwlock_t *)(rwlock_ptr))->index
+#define PUT_RW_CPU(rwlock_ptr,cpuv)    ((inst_rwlock_t *)(rwlock_ptr))->cpu = cpuv
+#define GET_RW_CPU(rwlock_ptr)         ((inst_rwlock_t *)(rwlock_ptr))->cpu
+
+/*
+ * return the number of readers for a rwlock_t
+ */
+#define RWLOCK_READERS(rwlock_ptr)   rwlock_readers(rwlock_ptr)
+
+extern inline int rwlock_readers(rwlock_t *rwlock_ptr)
+{
+	int tmp = (int) rwlock_ptr->lock;
+	/* read and write lock attempts may cause the lock value to temporarily */
+	/* be negative.  Until it is >= 0 we know nothing (i. e. can't tell if  */
+	/* is -1 because it was write locked and somebody tried to read lock it */
+	/* or if it is -1 because it was read locked and somebody tried to write*/
+	/* lock it. ........................................................... */
+	do {
+		tmp = (int) rwlock_ptr->lock;
+	} while (tmp < 0);
+	if (tmp == 0) return(0);
+	else return(RW_LOCK_BIAS-tmp);
+}
+
+/*
+ * return true if rwlock is write locked
+ * (note that other lock attempts can cause the lock value to be negative)
+ */
+#define RWLOCK_IS_WRITE_LOCKED(rwlock_ptr) ((rwlock_ptr)->lock <= 0)
+#define IABS(x) ((x) > 0 ? (x) : -(x))
+#define RWLOCK_IS_READ_LOCKED(rwlock_ptr)  ((IABS((rwlock_ptr)->lock) % RW_LOCK_BIAS) != 0)
+
+/* this is a lot of typing just to get gcc to emit "rdtsc" */
+static inline long long get_cycles64 (void)
+{
+	union longlong_u {
+		long long intlong;
+		struct intint_s {
+			uint32_t eax;
+			uint32_t edx;
+		} intint;
+	} longlong;
+
+	rdtsc(longlong.intint.eax,longlong.intint.edx);
+	return longlong.intlong;
+}
+
+#endif /* _I386_LOCKMETER_H */
--- diff/include/asm-ia64/cyclone.h	1970-01-01 01:00:00.000000000 +0100
+++ source/include/asm-ia64/cyclone.h	2004-02-23 13:56:47.000000000 +0000
@@ -0,0 +1,15 @@
+#ifndef ASM_IA64_CYCLONE_H
+#define ASM_IA64_CYCLONE_H
+
+#ifdef	CONFIG_IA64_CYCLONE
+extern int use_cyclone;
+extern int __init cyclone_setup(char*);
+#else	/* CONFIG_IA64_CYCLONE */
+#define use_cyclone 0
+static inline void cyclone_setup(char* s)
+{
+	printk(KERN_ERR "Cyclone Counter: System not configured"
+					" w/ CONFIG_IA64_CYCLONE.\n");
+}
+#endif	/* CONFIG_IA64_CYCLONE */
+#endif	/* !ASM_IA64_CYCLONE_H */
--- diff/include/asm-ia64/lockmeter.h	1970-01-01 01:00:00.000000000 +0100
+++ source/include/asm-ia64/lockmeter.h	2004-02-23 13:56:47.000000000 +0000
@@ -0,0 +1,72 @@
+/*
+ *  Copyright (C) 1999,2000 Silicon Graphics, Inc.
+ *
+ *  Written by John Hawkes (hawkes@sgi.com)
+ *  Based on klstat.h by Jack Steiner (steiner@sgi.com)
+ */
+
+#ifndef _IA64_LOCKMETER_H
+#define _IA64_LOCKMETER_H
+
+#ifdef local_cpu_data
+#define CPU_CYCLE_FREQUENCY	local_cpu_data->itc_freq
+#else
+#define CPU_CYCLE_FREQUENCY	my_cpu_data.itc_freq
+#endif
+#define get_cycles64()		get_cycles()
+
+#define THIS_CPU_NUMBER		smp_processor_id()
+
+/*
+ * macros to cache and retrieve an index value inside of a lock
+ * these macros assume that there are less than 65536 simultaneous
+ * (read mode) holders of a rwlock.
+ * we also assume that the hash table has less than 32767 entries.
+ */
+/*
+ * instrumented spinlock structure -- never used to allocate storage
+ * only used in macros below to overlay a spinlock_t
+ */
+typedef struct inst_spinlock_s {
+	/* remember, Intel is little endian */
+	volatile unsigned short lock;
+	volatile unsigned short index;
+} inst_spinlock_t;
+#define PUT_INDEX(lock_ptr,indexv) ((inst_spinlock_t *)(lock_ptr))->index = indexv
+#define GET_INDEX(lock_ptr)        ((inst_spinlock_t *)(lock_ptr))->index
+
+/*
+ * macros to cache and retrieve an index value in a read/write lock
+ * as well as the cpu where a reader busy period started
+ * we use the 2nd word (the debug word) for this, so require the
+ * debug word to be present
+ */
+/*
+ * instrumented rwlock structure -- never used to allocate storage
+ * only used in macros below to overlay a rwlock_t
+ */
+typedef struct inst_rwlock_s {
+	volatile int read_counter:31;
+	volatile int write_lock:1;
+	volatile unsigned short index;
+	volatile unsigned short cpu;
+} inst_rwlock_t;
+#define PUT_RWINDEX(rwlock_ptr,indexv) ((inst_rwlock_t *)(rwlock_ptr))->index = indexv
+#define GET_RWINDEX(rwlock_ptr)        ((inst_rwlock_t *)(rwlock_ptr))->index
+#define PUT_RW_CPU(rwlock_ptr,cpuv)    ((inst_rwlock_t *)(rwlock_ptr))->cpu = cpuv
+#define GET_RW_CPU(rwlock_ptr)         ((inst_rwlock_t *)(rwlock_ptr))->cpu
+
+/*
+ * return the number of readers for a rwlock_t
+ */
+#define RWLOCK_READERS(rwlock_ptr)	((rwlock_ptr)->read_counter)
+
+/*
+ * return true if rwlock is write locked
+ * (note that other lock attempts can cause the lock value to be negative)
+ */
+#define RWLOCK_IS_WRITE_LOCKED(rwlock_ptr) ((rwlock_ptr)->write_lock)
+#define RWLOCK_IS_READ_LOCKED(rwlock_ptr)  ((rwlock_ptr)->read_counter)
+
+#endif /* _IA64_LOCKMETER_H */
+
--- diff/include/asm-mips/cpu-features.h	1970-01-01 01:00:00.000000000 +0100
+++ source/include/asm-mips/cpu-features.h	2004-02-23 13:56:47.000000000 +0000
@@ -0,0 +1,125 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2003 Ralf Baechle
+ */
+#ifndef __ASM_CPU_FEATURES_H
+#define __ASM_CPU_FEATURES_H
+
+#include <cpu-feature-overrides.h>
+
+/*
+ * SMP assumption: Options of CPU 0 are a superset of all processors.
+ * This is true for all known MIPS systems.
+ */
+#ifndef cpu_has_tlb
+#define cpu_has_tlb		(cpu_data[0].options & MIPS_CPU_TLB)
+#endif
+#ifndef cpu_has_4kex
+#define cpu_has_4kex		(cpu_data[0].options & MIPS_CPU_4KEX)
+#endif
+#ifndef cpu_has_4ktlb
+#define cpu_has_4ktlb		(cpu_data[0].options & MIPS_CPU_4KTLB)
+#endif
+#ifndef cpu_has_fpu
+#define cpu_has_fpu		(cpu_data[0].options & MIPS_CPU_FPU)
+#endif
+#ifndef cpu_has_32fpr
+#define cpu_has_32fpr		(cpu_data[0].options & MIPS_CPU_32FPR)
+#endif
+#ifndef cpu_has_counter
+#define cpu_has_counter		(cpu_data[0].options & MIPS_CPU_COUNTER)
+#endif
+#ifndef cpu_has_watch
+#define cpu_has_watch		(cpu_data[0].options & MIPS_CPU_WATCH)
+#endif
+#ifndef cpu_has_mips16
+#define cpu_has_mips16		(cpu_data[0].options & MIPS_CPU_MIPS16)
+#endif
+#ifndef cpu_has_divec
+#define cpu_has_divec		(cpu_data[0].options & MIPS_CPU_DIVEC)
+#endif
+#ifndef cpu_has_vce
+#define cpu_has_vce		(cpu_data[0].options & MIPS_CPU_VCE)
+#endif
+#ifndef cpu_has_cache_cdex_p
+#define cpu_has_cache_cdex_p	(cpu_data[0].options & MIPS_CPU_CACHE_CDEX_P)
+#endif
+#ifndef cpu_has_cache_cdex_s
+#define cpu_has_cache_cdex_s	(cpu_data[0].options & MIPS_CPU_CACHE_CDEX_S)
+#endif
+#ifndef cpu_has_prefetch
+#define cpu_has_prefetch	(cpu_data[0].options & MIPS_CPU_PREFETCH)
+#endif
+#ifndef cpu_has_mcheck
+#define cpu_has_mcheck		(cpu_data[0].options & MIPS_CPU_MCHECK)
+#endif
+#ifndef cpu_has_ejtag
+#define cpu_has_ejtag		(cpu_data[0].options & MIPS_CPU_EJTAG)
+#endif
+#ifndef cpu_has_llsc
+#define cpu_has_llsc		(cpu_data[0].options & MIPS_CPU_LLSC)
+#endif
+#ifndef cpu_has_vtag_icache
+#define cpu_has_vtag_icache	(cpu_data[0].icache.flags & MIPS_CACHE_VTAG)
+#endif
+#ifndef cpu_has_dc_aliases
+#define cpu_has_dc_aliases	(cpu_data[0].dcache.flags & MIPS_CACHE_ALIASES)
+#endif
+#ifndef cpu_has_ic_fills_f_dc
+#define cpu_has_ic_fills_f_dc	(cpu_data[0].dcache.flags & MIPS_CACHE_IC_F_DC)
+#endif
+
+#ifdef CONFIG_MIPS32
+# ifndef cpu_has_nofpuex
+# define cpu_has_nofpuex	(cpu_data[0].options & MIPS_CPU_NOFPUEX)
+# endif
+# ifndef cpu_has_64bits
+# define cpu_has_64bits		(cpu_data[0].isa_level & MIPS_CPU_ISA_64BIT)
+# endif
+# ifndef cpu_has_64bit_zero_reg
+# define cpu_has_64bit_zero_reg	(cpu_data[0].isa_level & MIPS_CPU_ISA_64BIT)
+# endif
+# ifndef cpu_has_64bit_gp_regs
+# define cpu_has_64bit_gp_regs		0
+# endif
+# ifndef cpu_has_64bit_addresses
+# define cpu_has_64bit_addresses	0
+# endif
+#endif
+
+#ifdef CONFIG_MIPS64
+# ifndef cpu_has_nofpuex
+# define cpu_has_nofpuex		0
+# endif
+# ifndef cpu_has_64bits
+# define cpu_has_64bits			1
+# endif
+# ifndef cpu_has_64bit_zero_reg
+# define cpu_has_64bit_zero_reg		1
+# endif
+# ifndef cpu_has_64bit_gp_regs
+# define cpu_has_64bit_gp_regs		1
+# endif
+# ifndef cpu_has_64bit_addresses
+# define cpu_has_64bit_addresses	1
+# endif
+#endif
+
+#ifndef cpu_has_subset_pcaches
+#define cpu_has_subset_pcaches	(cpu_data[0].options & MIPS_CPU_SUBSET_CACHES)
+#endif
+
+#ifndef cpu_dcache_line_size
+#define cpu_dcache_line_size()	current_cpu_data.dcache.linesz
+#endif
+#ifndef cpu_icache_line_size
+#define cpu_icache_line_size()	current_cpu_data.icache.linesz
+#endif
+#ifndef cpu_scache_line_size
+#define cpu_scache_line_size()	current_cpu_data.scache.linesz
+#endif
+
+#endif /* __ASM_CPU_FEATURES_H */
--- diff/include/asm-mips/hazards.h	1970-01-01 01:00:00.000000000 +0100
+++ source/include/asm-mips/hazards.h	2004-02-23 13:56:47.000000000 +0000
@@ -0,0 +1,49 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2003 Ralf Baechle
+ */
+#ifndef _ASM_HAZARDS_H
+#define _ASM_HAZARDS_H
+
+#include <linux/config.h>
+
+#ifdef __ASSEMBLY__
+
+/*
+ * RM9000 hazards.  When the JTLB is updated by tlbwi or tlbwr, a subsequent
+ * use of the JTLB for instructions should not occur for 4 cpu cycles and use
+ * for data translations should not occur for 3 cpu cycles.
+ */
+#ifdef CONFIG_CPU_RM9000
+#define rm9000_tlb_hazard						\
+	.set	push;							\
+	.set	mips32;							\
+	ssnop; ssnop; ssnop; ssnop;					\
+	.set	pop
+#else
+#define rm9000_tlb_hazard
+#endif
+
+#else
+
+/*
+ * RM9000 hazards.  When the JTLB is updated by tlbwi or tlbwr, a subsequent
+ * use of the JTLB for instructions should not occur for 4 cpu cycles and use
+ * for data translations should not occur for 3 cpu cycles.
+ */
+#ifdef CONFIG_CPU_RM9000
+#define rm9000_tlb_hazard()						\
+	__asm__ __volatile__(						\
+		".set\tmips32\n\t"					\
+		"ssnop; ssnop; ssnop; ssnop\n\t"			\
+		".set\tmips0")
+#else
+#define rm9000_tlb_hazard() do { } while (0)
+#endif
+
+#endif
+
+#endif /* _ASM_HAZARDS_H */
--- diff/include/asm-mips/lockmeter.h	1970-01-01 01:00:00.000000000 +0100
+++ source/include/asm-mips/lockmeter.h	2004-02-23 13:56:47.000000000 +0000
@@ -0,0 +1,126 @@
+/*
+ *  Copyright (C) 1999,2000 Silicon Graphics, Inc.
+ *
+ *  Written by John Hawkes (hawkes@sgi.com)
+ *  Based on klstat.h by Jack Steiner (steiner@sgi.com)
+ *  Ported to mips32 for Asita Technologies
+ *   by D.J. Barrow ( dj.barrow@asitatechnologies.com )
+ */
+#ifndef _ASM_LOCKMETER_H
+#define _ASM_LOCKMETER_H
+
+/* do_gettimeoffset is a function pointer on mips */
+/* & it is not included by <linux/time.h> */
+#include <asm/time.h>
+#include <linux/time.h>
+#include <asm/div64.h>
+
+#define SPINLOCK_MAGIC_INIT	/* */
+
+#define CPU_CYCLE_FREQUENCY	get_cpu_cycle_frequency()
+
+#define THIS_CPU_NUMBER		smp_processor_id()
+
+static uint32_t cpu_cycle_frequency = 0;
+
+static uint32_t get_cpu_cycle_frequency(void)
+{
+    /* a total hack, slow and invasive, but ... it works */
+    int sec;
+    uint32_t start_cycles;
+    struct timeval tv;
+
+    if (cpu_cycle_frequency == 0) {	/* uninitialized */
+	do_gettimeofday(&tv);
+	sec = tv.tv_sec;	/* set up to catch the tv_sec rollover */
+	while (sec == tv.tv_sec) { do_gettimeofday(&tv); }
+	sec = tv.tv_sec;	/* rolled over to a new sec value */
+	start_cycles = get_cycles();
+	while (sec == tv.tv_sec) { do_gettimeofday(&tv); }
+	cpu_cycle_frequency = get_cycles() - start_cycles;
+    }
+
+    return cpu_cycle_frequency;
+}
+
+extern struct timeval xtime;
+
+static uint64_t get_cycles64(void)
+{
+    static uint64_t last_get_cycles64 = 0;
+    uint64_t ret;
+    unsigned long sec;
+    unsigned long usec, usec_offset;
+
+again:
+    sec  = xtime.tv_sec;
+    usec = xtime.tv_usec;
+    usec_offset = do_gettimeoffset();
+    if ((xtime.tv_sec != sec)  ||
+	(xtime.tv_usec != usec)||
+	(usec_offset >= 20000))
+	goto again;
+
+    ret = ((uint64_t)(usec + usec_offset) * cpu_cycle_frequency);
+    /* We can't do a normal 64 bit division on mips without libgcc.a */
+    do_div(ret,1000000);
+    ret +=  ((uint64_t)sec * cpu_cycle_frequency);
+
+    /* XXX why does time go backwards?  do_gettimeoffset?  general time adj? */
+    if (ret <= last_get_cycles64)
+	ret  = last_get_cycles64+1;
+    last_get_cycles64 = ret;
+
+    return ret;
+}
+
+/*
+ * macros to cache and retrieve an index value inside of a lock
+ * these macros assume that there are less than 65536 simultaneous
+ * (read mode) holders of a rwlock.
+ * we also assume that the hash table has less than 32767 entries.
+ * the high order bit is used for write locking a rw_lock
+ */
+#define INDEX_MASK   0x7FFF0000
+#define READERS_MASK 0x0000FFFF
+#define INDEX_SHIFT 16
+#define PUT_INDEX(lockp,index)   \
+        lockp->lock = (((lockp->lock) & ~INDEX_MASK) | (index) << INDEX_SHIFT)
+#define GET_INDEX(lockp) \
+        (((lockp->lock) & INDEX_MASK) >> INDEX_SHIFT)
+
+/*
+ * macros to cache and retrieve an index value in a read/write lock
+ * as well as the cpu where a reader busy period started
+ * we use the 2nd word (the debug word) for this, so require the
+ * debug word to be present
+ */
+/*
+ * instrumented rwlock structure -- never used to allocate storage
+ * only used in macros below to overlay a rwlock_t
+ */
+typedef struct inst_rwlock_s {
+	volatile int lock;
+	unsigned short index;
+	unsigned short cpu;
+} inst_rwlock_t;
+#define PUT_RWINDEX(rwlock_ptr,indexv) ((inst_rwlock_t *)(rwlock_ptr))->index = indexv
+#define GET_RWINDEX(rwlock_ptr)        ((inst_rwlock_t *)(rwlock_ptr))->index
+#define PUT_RW_CPU(rwlock_ptr,cpuv)    ((inst_rwlock_t *)(rwlock_ptr))->cpu = cpuv
+#define GET_RW_CPU(rwlock_ptr)         ((inst_rwlock_t *)(rwlock_ptr))->cpu
+
+/*
+ * return the number of readers for a rwlock_t
+ */
+#define RWLOCK_READERS(rwlock_ptr)   rwlock_readers(rwlock_ptr)
+
+extern inline int rwlock_readers(rwlock_t *rwlock_ptr)
+{
+	int tmp = (int) rwlock_ptr->lock;
+	return (tmp >= 0) ? tmp : 0;
+}
+
+#define RWLOCK_IS_WRITE_LOCKED(rwlock_ptr) ((rwlock_ptr)->lock < 0)
+#define RWLOCK_IS_READ_LOCKED(rwlock_ptr)  ((rwlock_ptr)->lock > 0)
+
+#endif /* _ASM_LOCKMETER_H */
--- diff/include/asm-mips/mach-atlas/mc146818rtc.h	1970-01-01 01:00:00.000000000 +0100
+++ source/include/asm-mips/mach-atlas/mc146818rtc.h	2004-02-23 13:56:47.000000000 +0000
@@ -0,0 +1,53 @@
+/*
+ * Carsten Langgaard, carstenl@mips.com
+ * Copyright (C) 1999,2000 MIPS Technologies, Inc.  All rights reserved.
+ * Copyright (C) 2003 by Ralf Baechle
+ *
+ * This program is free software; you can distribute it and/or modify it
+ * under the terms of the GNU General Public License (Version 2) as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ */
+#ifndef __ASM_MACH_ATLAS_MC146818RTC_H
+#define __ASM_MACH_ATLAS_MC146818RTC_H
+
+#include <asm/io.h>
+#include <asm/mips-boards/atlas.h>
+#include <asm/mips-boards/atlasint.h>
+
+
+#define RTC_PORT(x)	(ATLAS_RTC_ADR_REG + (x)*8)
+#define RTC_IOMAPPED	1
+#define RTC_EXTENT	16
+#define RTC_IRQ		ATLASINT_RTC
+
+#if CONFIG_CPU_LITTLE_ENDIAN
+#define ATLAS_RTC_PORT(x) (RTC_PORT(x) + 0)
+#else
+#define ATLAS_RTC_PORT(x) (RTC_PORT(x) + 3)
+#endif
+
+static inline unsigned char CMOS_READ(unsigned long addr)
+{
+	outb(addr, ATLAS_RTC_PORT(0));
+
+	return inb(ATLAS_RTC_PORT(1));
+}
+
+static inline void CMOS_WRITE(unsigned char data, unsigned long addr)
+{
+	outb(addr, ATLAS_RTC_PORT(0));
+	outb(data, ATLAS_RTC_PORT(1));
+}
+
+#define RTC_ALWAYS_BCD	0
+
+#endif /* __ASM_MACH_ATLAS_MC146818RTC_H */
--- diff/include/asm-mips/mach-au1x00/au1000.h	1970-01-01 01:00:00.000000000 +0100
+++ source/include/asm-mips/mach-au1x00/au1000.h	2004-02-23 13:56:47.000000000 +0000
@@ -0,0 +1,1155 @@
+/*
+ *
+ * BRIEF MODULE DESCRIPTION
+ *	Include file for Alchemy Semiconductor's Au1k CPU.
+ *
+ * Copyright 2000,2001 MontaVista Software Inc.
+ * Author: MontaVista Software, Inc.
+ *         	ppopov@mvista.com or source@mvista.com
+ *
+ *  This program is free software; you can redistribute  it and/or modify it
+ *  under  the terms of  the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the  License, or (at your
+ *  option) any later version.
+ *
+ *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
+ *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
+ *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
+ *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
+ *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
+ *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *  You should have received a copy of the  GNU General Public License along
+ *  with this program; if not, write  to the Free Software Foundation, Inc.,
+ *  675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+ /*
+  * some definitions add by takuzo@sm.sony.co.jp and sato@sm.sony.co.jp
+  */
+
+#ifndef _AU1000_H_
+#define _AU1000_H_
+
+#ifndef _LANGUAGE_ASSEMBLY
+
+#include <linux/delay.h>
+#include <asm/io.h>
+
+/* cpu pipeline flush */
+void static inline au_sync(void)
+{
+	__asm__ volatile ("sync");
+}
+
+void static inline au_sync_udelay(int us)
+{
+	__asm__ volatile ("sync");
+	udelay(us);
+}
+
+void static inline au_sync_delay(int ms)
+{
+	__asm__ volatile ("sync");
+	mdelay(ms);
+}
+
+void static inline au_writeb(u8 val, int reg)
+{
+	*(volatile u8 *)(reg) = val;
+}
+
+void static inline au_writew(u16 val, int reg)
+{
+	*(volatile u16 *)(reg) = val;
+}
+
+void static inline au_writel(u32 val, int reg)
+{
+	*(volatile u32 *)(reg) = val;
+}
+
+static inline u8 au_readb(unsigned long port)
+{
+	return (*(volatile u8 *)port);
+}
+
+static inline u16 au_readw(unsigned long port)
+{
+	return (*(volatile u16 *)port);
+}
+
+static inline u32 au_readl(unsigned long port)
+{
+	return (*(volatile u32 *)port);
+}
+
+/* These next three functions should be a generic part of the MIPS
+ * kernel (with the 'au_' removed from the name) and selected for
+ * processors that support the instructions.
+ * Taken from PPC tree.  -- Dan
+ */
+/* Return the bit position of the most significant 1 bit in a word */
+static __inline__ int __ilog2(unsigned int x)
+{
+	int lz;
+
+	asm volatile (
+		".set\tnoreorder\n\t"
+		".set\tnoat\n\t"
+		".set\tmips32\n\t"
+		"clz\t%0,%1\n\t"
+		".set\tmips0\n\t"
+		".set\tat\n\t"
+		".set\treorder"
+		: "=r" (lz)
+		: "r" (x));
+
+	return 31 - lz;
+}
+
+static __inline__ int au_ffz(unsigned int x)
+{
+	if ((x = ~x) == 0)
+		return 32;
+	return __ilog2(x & -x);
+}
+
+/*
+ * ffs: find first bit set. This is defined the same way as
+ * the libc and compiler builtin ffs routines, therefore
+ * differs in spirit from the above ffz (man ffs).
+ */
+static __inline__ int au_ffs(int x)
+{
+	return __ilog2(x & -x) + 1;
+}
+
+/* arch/mips/au1000/common/clocks.c */
+extern void set_au1x00_speed(unsigned int new_freq);
+extern unsigned int get_au1x00_speed(void);
+extern void set_au1x00_uart_baud_base(unsigned long new_baud_base);
+extern unsigned long get_au1x00_uart_baud_base(void);
+extern void set_au1x00_lcd_clock(void);
+extern unsigned int get_au1x00_lcd_clock(void);
+
+/*
+ * Every board describes its IRQ mapping with this table.
+ */
+typedef struct au1xxx_irqmap {
+	int	im_irq;
+	int	im_type;
+	int	im_request;
+} au1xxx_irq_map_t;
+
+/*
+ * init_IRQ looks for a table with this name.
+ */
+extern au1xxx_irq_map_t au1xxx_irq_map[];
+
+#endif /* !defined (_LANGUAGE_ASSEMBLY) */
+
+#ifdef CONFIG_PM
+/* no CP0 timer irq */
+#define ALLINTS (IE_IRQ0 | IE_IRQ1 | IE_IRQ2 | IE_IRQ3 | IE_IRQ4)
+#else
+#define ALLINTS (IE_IRQ0 | IE_IRQ1 | IE_IRQ2 | IE_IRQ3 | IE_IRQ4 | IE_IRQ5)
+#endif
+
+/* SDRAM Controller */
+#define MEM_SDMODE0                0xB4000000
+#define MEM_SDMODE1                0xB4000004
+#define MEM_SDMODE2                0xB4000008
+
+#define MEM_SDADDR0                0xB400000C
+#define MEM_SDADDR1                0xB4000010
+#define MEM_SDADDR2                0xB4000014
+
+#define MEM_SDREFCFG               0xB4000018
+#define MEM_SDPRECMD               0xB400001C
+#define MEM_SDAUTOREF              0xB4000020
+
+#define MEM_SDWRMD0                0xB4000024
+#define MEM_SDWRMD1                0xB4000028
+#define MEM_SDWRMD2                0xB400002C
+
+#define MEM_SDSLEEP                0xB4000030
+#define MEM_SDSMCKE                0xB4000034
+
+/* Static Bus Controller */
+#define MEM_STCFG0                 0xB4001000
+#define MEM_STTIME0                0xB4001004
+#define MEM_STADDR0                0xB4001008
+
+#define MEM_STCFG1                 0xB4001010
+#define MEM_STTIME1                0xB4001014
+#define MEM_STADDR1                0xB4001018
+
+#define MEM_STCFG2                 0xB4001020
+#define MEM_STTIME2                0xB4001024
+#define MEM_STADDR2                0xB4001028
+
+#define MEM_STCFG3                 0xB4001030
+#define MEM_STTIME3                0xB4001034
+#define MEM_STADDR3                0xB4001038
+
+/* Interrupt Controller 0 */
+#define IC0_CFG0RD                 0xB0400040
+#define IC0_CFG0SET                0xB0400040
+#define IC0_CFG0CLR                0xB0400044
+
+#define IC0_CFG1RD                 0xB0400048
+#define IC0_CFG1SET                0xB0400048
+#define IC0_CFG1CLR                0xB040004C
+
+#define IC0_CFG2RD                 0xB0400050
+#define IC0_CFG2SET                0xB0400050
+#define IC0_CFG2CLR                0xB0400054
+
+#define IC0_REQ0INT                0xB0400054
+#define IC0_SRCRD                  0xB0400058
+#define IC0_SRCSET                 0xB0400058
+#define IC0_SRCCLR                 0xB040005C
+#define IC0_REQ1INT                0xB040005C
+
+#define IC0_ASSIGNRD               0xB0400060
+#define IC0_ASSIGNSET              0xB0400060
+#define IC0_ASSIGNCLR              0xB0400064
+
+#define IC0_WAKERD                 0xB0400068
+#define IC0_WAKESET                0xB0400068
+#define IC0_WAKECLR                0xB040006C
+
+#define IC0_MASKRD                 0xB0400070
+#define IC0_MASKSET                0xB0400070
+#define IC0_MASKCLR                0xB0400074
+
+#define IC0_RISINGRD               0xB0400078
+#define IC0_RISINGCLR              0xB0400078
+#define IC0_FALLINGRD              0xB040007C
+#define IC0_FALLINGCLR             0xB040007C
+
+#define IC0_TESTBIT                0xB0400080
+
+/* Interrupt Controller 1 */
+#define IC1_CFG0RD                 0xB1800040
+#define IC1_CFG0SET                0xB1800040
+#define IC1_CFG0CLR                0xB1800044
+
+#define IC1_CFG1RD                 0xB1800048
+#define IC1_CFG1SET                0xB1800048
+#define IC1_CFG1CLR                0xB180004C
+
+#define IC1_CFG2RD                 0xB1800050
+#define IC1_CFG2SET                0xB1800050
+#define IC1_CFG2CLR                0xB1800054
+
+#define IC1_REQ0INT                0xB1800054
+#define IC1_SRCRD                  0xB1800058
+#define IC1_SRCSET                 0xB1800058
+#define IC1_SRCCLR                 0xB180005C
+#define IC1_REQ1INT                0xB180005C
+
+#define IC1_ASSIGNRD               0xB1800060
+#define IC1_ASSIGNSET              0xB1800060
+#define IC1_ASSIGNCLR              0xB1800064
+
+#define IC1_WAKERD                 0xB1800068
+#define IC1_WAKESET                0xB1800068
+#define IC1_WAKECLR                0xB180006C
+
+#define IC1_MASKRD                 0xB1800070
+#define IC1_MASKSET                0xB1800070
+#define IC1_MASKCLR                0xB1800074
+
+#define IC1_RISINGRD               0xB1800078
+#define IC1_RISINGCLR              0xB1800078
+#define IC1_FALLINGRD              0xB180007C
+#define IC1_FALLINGCLR             0xB180007C
+
+#define IC1_TESTBIT                0xB1800080
+
+/* Interrupt Configuration Modes */
+#define INTC_INT_DISABLED                0
+#define INTC_INT_RISE_EDGE             0x1
+#define INTC_INT_FALL_EDGE             0x2
+#define INTC_INT_RISE_AND_FALL_EDGE    0x3
+#define INTC_INT_HIGH_LEVEL            0x5
+#define INTC_INT_LOW_LEVEL             0x6
+#define INTC_INT_HIGH_AND_LOW_LEVEL    0x7
+
+/* Interrupt Numbers */
+#define AU1000_UART0_INT          0
+#define AU1000_UART1_INT          1 /* au1000 */
+#define AU1000_UART2_INT          2 /* au1000 */
+
+#define AU1000_PCI_INTA           1 /* au1500 */
+#define AU1000_PCI_INTB           2 /* au1500 */
+
+#define AU1000_UART3_INT          3
+
+#define AU1000_SSI0_INT           4 /* au1000 */
+#define AU1000_SSI1_INT           5 /* au1000 */
+
+#define AU1000_PCI_INTC           4 /* au1500 */
+#define AU1000_PCI_INTD           5 /* au1500 */
+
+#define AU1000_DMA_INT_BASE       6
+#define AU1000_TOY_INT            14
+#define AU1000_TOY_MATCH0_INT     15
+#define AU1000_TOY_MATCH1_INT     16
+#define AU1000_TOY_MATCH2_INT     17
+#define AU1000_RTC_INT            18
+#define AU1000_RTC_MATCH0_INT     19
+#define AU1000_RTC_MATCH1_INT     20
+#define AU1000_RTC_MATCH2_INT     21
+#define AU1000_IRDA_TX_INT        22 /* au1000 */
+#define AU1000_IRDA_RX_INT        23 /* au1000 */
+#define AU1000_USB_DEV_REQ_INT    24
+#define AU1000_USB_DEV_SUS_INT    25
+#define AU1000_USB_HOST_INT       26
+#define AU1000_ACSYNC_INT         27
+#define AU1000_MAC0_DMA_INT       28
+#define AU1000_MAC1_DMA_INT       29
+#define AU1000_ETH0_IRQ           AU1000_MAC0_DMA_INT
+#define AU1000_ETH1_IRQ           AU1000_MAC1_DMA_INT
+#define AU1000_I2S_UO_INT         30 /* au1000 */
+#define AU1000_AC97C_INT          31
+#define AU1000_LAST_INTC0_INT     AU1000_AC97C_INT
+#define AU1000_GPIO_0             32
+#define AU1000_GPIO_1             33
+#define AU1000_GPIO_2             34
+#define AU1000_GPIO_3             35
+#define AU1000_GPIO_4             36
+#define AU1000_GPIO_5             37
+#define AU1000_GPIO_6             38
+#define AU1000_GPIO_7             39
+#define AU1000_GPIO_8             40
+#define AU1000_GPIO_9             41
+#define AU1000_GPIO_10            42
+#define AU1000_GPIO_11            43
+#define AU1000_GPIO_12            44
+#define AU1000_GPIO_13            45
+#define AU1000_GPIO_14            46
+#define AU1000_GPIO_15            47
+
+/* Au1000 only */
+#define AU1000_GPIO_16            48
+#define AU1000_GPIO_17            49
+#define AU1000_GPIO_18            50
+#define AU1000_GPIO_19            51
+#define AU1000_GPIO_20            52
+#define AU1000_GPIO_21            53
+#define AU1000_GPIO_22            54
+#define AU1000_GPIO_23            55
+#define AU1000_GPIO_24            56
+#define AU1000_GPIO_25            57
+#define AU1000_GPIO_26            58
+#define AU1000_GPIO_27            59
+#define AU1000_GPIO_28            60
+#define AU1000_GPIO_29            61
+#define AU1000_GPIO_30            62
+#define AU1000_GPIO_31            63
+
+/* Au1500 only */
+#define AU1500_GPIO_200           48
+#define AU1500_GPIO_201           49
+#define AU1500_GPIO_202           50
+#define AU1500_GPIO_203           51
+#define AU1500_GPIO_20            52
+#define AU1500_GPIO_204           53
+#define AU1500_GPIO_205           54
+#define AU1500_GPIO_23            55
+#define AU1500_GPIO_24            56
+#define AU1500_GPIO_25            57
+#define AU1500_GPIO_26            58
+#define AU1500_GPIO_27            59
+#define AU1500_GPIO_28            60
+#define AU1500_GPIO_206           61
+#define AU1500_GPIO_207           62
+#define AU1500_GPIO_208_215       63
+
+#define AU1000_MAX_INTR           63
+
+#define AU1100_SD		2
+#define	AU1100_GPIO_208_215	29
+// Seperate defines for AU1550 SOC
+#define AU1550_UART0_INT          AU1000_UART0_INT
+#define AU1550_PCI_INTA           AU1000_PCI_INTA
+#define AU1550_PCI_INTB           AU1000_PCI_INTB
+#define AU1550_DDMA_INT           3
+#define AU1550_CRYPTO_INT         4
+#define AU1550_PCI_INTC           5
+#define AU1550_PCI_INTD           6
+#define AU1550_PCI_RST_INT        7
+#define AU1550_UART1_INT          8
+#define AU1550_UART3_INT          9
+#define AU1550_PSC0_INT           10
+#define AU1550_PSC1_INT           11
+#define AU1550_PSC2_INT           12
+#define AU1550_PSC3_INT           13
+#define AU1550_TOY_INT			  14
+#define AU1550_TOY_MATCH0_INT     15
+#define AU1550_TOY_MATCH1_INT     16
+#define AU1550_TOY_MATCH2_INT     17
+#define AU1550_RTC_INT            18
+#define AU1550_RTC_MATCH0_INT     19
+#define AU1550_RTC_MATCH1_INT     20
+#define AU1550_RTC_MATCH2_INT     21
+#define AU1550_NAND_INT           23
+#define AU1550_USB_DEV_REQ_INT    24
+#define AU1550_USB_DEV_SUS_INT    25
+#define AU1550_USB_HOST_INT       26
+#define AU1550_MAC0_DMA_INT       27
+#define AU1550_MAC1_DMA_INT       28
+#define AU1550_ETH0_IRQ           AU1550_MAC0_DMA_INT
+#define AU1550_ETH1_IRQ           AU1550_MAC1_DMA_INT
+
+#define AU1550_GPIO_200           48
+#define AU1500_GPIO_201_205       49	// Logical or of GPIO201:205
+#define AU1500_GPIO_16            50
+#define AU1500_GPIO_17            51
+#define AU1500_GPIO_20            52
+#define AU1500_GPIO_21            53
+#define AU1500_GPIO_22            54
+#define AU1500_GPIO_23            55
+#define AU1500_GPIO_24            56
+#define AU1500_GPIO_25            57
+#define AU1500_GPIO_26            58
+#define AU1500_GPIO_27            59
+#define AU1500_GPIO_28            60
+#define AU1500_GPIO_206           61
+#define AU1500_GPIO_207           62
+#define AU1500_GPIO_208_218       63	// Logical or of GPIO208:218
+
+// REDEFINE SECONDARY GPIO BLOCK INTO IC1 CONTROLLER HERE
+
+
+/* Programmable Counters 0 and 1 */
+#define SYS_BASE                   0xB1900000
+#define SYS_COUNTER_CNTRL          (SYS_BASE + 0x14)
+  #define SYS_CNTRL_E1S            (1<<23)
+  #define SYS_CNTRL_T1S            (1<<20)
+  #define SYS_CNTRL_M21            (1<<19)
+  #define SYS_CNTRL_M11            (1<<18)
+  #define SYS_CNTRL_M01            (1<<17)
+  #define SYS_CNTRL_C1S            (1<<16)
+  #define SYS_CNTRL_BP             (1<<14)
+  #define SYS_CNTRL_EN1            (1<<13)
+  #define SYS_CNTRL_BT1            (1<<12)
+  #define SYS_CNTRL_EN0            (1<<11)
+  #define SYS_CNTRL_BT0            (1<<10)
+  #define SYS_CNTRL_E0             (1<<8)
+  #define SYS_CNTRL_E0S            (1<<7)
+  #define SYS_CNTRL_32S            (1<<5)
+  #define SYS_CNTRL_T0S            (1<<4)
+  #define SYS_CNTRL_M20            (1<<3)
+  #define SYS_CNTRL_M10            (1<<2)
+  #define SYS_CNTRL_M00            (1<<1)
+  #define SYS_CNTRL_C0S            (1<<0)
+
+/* Programmable Counter 0 Registers */
+#define SYS_TOYTRIM                 (SYS_BASE + 0)
+#define SYS_TOYWRITE                (SYS_BASE + 4)
+#define SYS_TOYMATCH0               (SYS_BASE + 8)
+#define SYS_TOYMATCH1               (SYS_BASE + 0xC)
+#define SYS_TOYMATCH2               (SYS_BASE + 0x10)
+#define SYS_TOYREAD                 (SYS_BASE + 0x40)
+
+/* Programmable Counter 1 Registers */
+#define SYS_RTCTRIM                 (SYS_BASE + 0x44)
+#define SYS_RTCWRITE                (SYS_BASE + 0x48)
+#define SYS_RTCMATCH0               (SYS_BASE + 0x4C)
+#define SYS_RTCMATCH1               (SYS_BASE + 0x50)
+#define SYS_RTCMATCH2               (SYS_BASE + 0x54)
+#define SYS_RTCREAD                 (SYS_BASE + 0x58)
+
+/* I2S Controller */
+#define I2S_DATA                    0xB1000000
+  #define I2S_DATA_MASK        (0xffffff)
+#define I2S_CONFIG                0xB1000004
+  #define I2S_CONFIG_XU        (1<<25)
+  #define I2S_CONFIG_XO        (1<<24)
+  #define I2S_CONFIG_RU        (1<<23)
+  #define I2S_CONFIG_RO        (1<<22)
+  #define I2S_CONFIG_TR        (1<<21)
+  #define I2S_CONFIG_TE        (1<<20)
+  #define I2S_CONFIG_TF        (1<<19)
+  #define I2S_CONFIG_RR        (1<<18)
+  #define I2S_CONFIG_RE        (1<<17)
+  #define I2S_CONFIG_RF        (1<<16)
+  #define I2S_CONFIG_PD        (1<<11)
+  #define I2S_CONFIG_LB        (1<<10)
+  #define I2S_CONFIG_IC        (1<<9)
+  #define I2S_CONFIG_FM_BIT    7
+  #define I2S_CONFIG_FM_MASK     (0x3 << I2S_CONFIG_FM_BIT)
+    #define I2S_CONFIG_FM_I2S    (0x0 << I2S_CONFIG_FM_BIT)
+    #define I2S_CONFIG_FM_LJ     (0x1 << I2S_CONFIG_FM_BIT)
+    #define I2S_CONFIG_FM_RJ     (0x2 << I2S_CONFIG_FM_BIT)
+  #define I2S_CONFIG_TN        (1<<6)
+  #define I2S_CONFIG_RN        (1<<5)
+  #define I2S_CONFIG_SZ_BIT    0
+  #define I2S_CONFIG_SZ_MASK     (0x1F << I2S_CONFIG_SZ_BIT)
+
+#define I2S_CONTROL                0xB1000008
+  #define I2S_CONTROL_D         (1<<1)
+  #define I2S_CONTROL_CE        (1<<0)
+
+/* USB Host Controller */
+// We pass USB_OHCI_BASE to ioremap, so it needs to be a physical address
+#if defined( CONFIG_SOC_AU1550 )
+#define USB_OHCI_BASE             0x14020000
+#define USB_OHCI_LEN              0x00100000
+#define USB_HOST_CONFIG           0xB4027ffc
+#else
+#define USB_OHCI_BASE             0x10100000
+#define USB_OHCI_LEN              0x00100000
+#define USB_HOST_CONFIG           0xB017fffc
+#endif
+
+/* USB Device Controller */
+#define USBD_EP0RD                0xB0200000
+#define USBD_EP0WR                0xB0200004
+#define USBD_EP2WR                0xB0200008
+#define USBD_EP3WR                0xB020000C
+#define USBD_EP4RD                0xB0200010
+#define USBD_EP5RD                0xB0200014
+#define USBD_INTEN                0xB0200018
+#define USBD_INTSTAT              0xB020001C
+  #define USBDEV_INT_SOF       (1<<12)
+  #define USBDEV_INT_HF_BIT    6
+  #define USBDEV_INT_HF_MASK   (0x3f << USBDEV_INT_HF_BIT)
+  #define USBDEV_INT_CMPLT_BIT  0
+  #define USBDEV_INT_CMPLT_MASK (0x3f << USBDEV_INT_CMPLT_BIT)
+#define USBD_CONFIG               0xB0200020
+#define USBD_EP0CS                0xB0200024
+#define USBD_EP2CS                0xB0200028
+#define USBD_EP3CS                0xB020002C
+#define USBD_EP4CS                0xB0200030
+#define USBD_EP5CS                0xB0200034
+  #define USBDEV_CS_SU         (1<<14)
+  #define USBDEV_CS_NAK        (1<<13)
+  #define USBDEV_CS_ACK        (1<<12)
+  #define USBDEV_CS_BUSY       (1<<11)
+  #define USBDEV_CS_TSIZE_BIT  1
+  #define USBDEV_CS_TSIZE_MASK (0x3ff << USBDEV_CS_TSIZE_BIT)
+  #define USBDEV_CS_STALL      (1<<0)
+#define USBD_EP0RDSTAT            0xB0200040
+#define USBD_EP0WRSTAT            0xB0200044
+#define USBD_EP2WRSTAT            0xB0200048
+#define USBD_EP3WRSTAT            0xB020004C
+#define USBD_EP4RDSTAT            0xB0200050
+#define USBD_EP5RDSTAT            0xB0200054
+  #define USBDEV_FSTAT_FLUSH     (1<<6)
+  #define USBDEV_FSTAT_UF        (1<<5)
+  #define USBDEV_FSTAT_OF        (1<<4)
+  #define USBDEV_FSTAT_FCNT_BIT  0
+  #define USBDEV_FSTAT_FCNT_MASK (0x0f << USBDEV_FSTAT_FCNT_BIT)
+#define USBD_ENABLE               0xB0200058
+  #define USBDEV_ENABLE (1<<1)
+  #define USBDEV_CE     (1<<0)
+
+/* Ethernet Controllers  */
+#define AU1000_ETH0_BASE          0xB0500000
+#define AU1000_ETH1_BASE          0xB0510000
+#define AU1500_ETH0_BASE	  0xB1500000
+#define AU1500_ETH1_BASE	  0xB1510000
+#define AU1100_ETH0_BASE	  0xB0500000
+#define AU1550_ETH0_BASE      0xB0500000
+#define AU1550_ETH1_BASE      0xB0510000
+
+/* 4 byte offsets from AU1000_ETH_BASE */
+#define MAC_CONTROL                     0x0
+  #define MAC_RX_ENABLE               (1<<2)
+  #define MAC_TX_ENABLE               (1<<3)
+  #define MAC_DEF_CHECK               (1<<5)
+  #define MAC_SET_BL(X)       (((X)&0x3)<<6)
+  #define MAC_AUTO_PAD                (1<<8)
+  #define MAC_DISABLE_RETRY          (1<<10)
+  #define MAC_DISABLE_BCAST          (1<<11)
+  #define MAC_LATE_COL               (1<<12)
+  #define MAC_HASH_MODE              (1<<13)
+  #define MAC_HASH_ONLY              (1<<15)
+  #define MAC_PASS_ALL               (1<<16)
+  #define MAC_INVERSE_FILTER         (1<<17)
+  #define MAC_PROMISCUOUS            (1<<18)
+  #define MAC_PASS_ALL_MULTI         (1<<19)
+  #define MAC_FULL_DUPLEX            (1<<20)
+  #define MAC_NORMAL_MODE                 0
+  #define MAC_INT_LOOPBACK           (1<<21)
+  #define MAC_EXT_LOOPBACK           (1<<22)
+  #define MAC_DISABLE_RX_OWN         (1<<23)
+  #define MAC_BIG_ENDIAN             (1<<30)
+  #define MAC_RX_ALL                 (1<<31)
+#define MAC_ADDRESS_HIGH                0x4
+#define MAC_ADDRESS_LOW                 0x8
+#define MAC_MCAST_HIGH                  0xC
+#define MAC_MCAST_LOW                  0x10
+#define MAC_MII_CNTRL                  0x14
+  #define MAC_MII_BUSY                (1<<0)
+  #define MAC_MII_READ                     0
+  #define MAC_MII_WRITE               (1<<1)
+  #define MAC_SET_MII_SELECT_REG(X)   (((X)&0x1f)<<6)
+  #define MAC_SET_MII_SELECT_PHY(X)   (((X)&0x1f)<<11)
+#define MAC_MII_DATA                   0x18
+#define MAC_FLOW_CNTRL                 0x1C
+  #define MAC_FLOW_CNTRL_BUSY         (1<<0)
+  #define MAC_FLOW_CNTRL_ENABLE       (1<<1)
+  #define MAC_PASS_CONTROL            (1<<2)
+  #define MAC_SET_PAUSE(X)        (((X)&0xffff)<<16)
+#define MAC_VLAN1_TAG                  0x20
+#define MAC_VLAN2_TAG                  0x24
+
+/* Ethernet Controller Enable */
+#define AU1000_MAC0_ENABLE       0xB0520000
+#define AU1000_MAC1_ENABLE       0xB0520004
+#define AU1500_MAC0_ENABLE       0xB1520000
+#define AU1500_MAC1_ENABLE       0xB1520004
+#define AU1100_MAC0_ENABLE       0xB0520000
+
+  #define MAC_EN_CLOCK_ENABLE         (1<<0)
+  #define MAC_EN_RESET0               (1<<1)
+  #define MAC_EN_TOSS                 (0<<2)
+  #define MAC_EN_CACHEABLE            (1<<3)
+  #define MAC_EN_RESET1               (1<<4)
+  #define MAC_EN_RESET2               (1<<5)
+  #define MAC_DMA_RESET               (1<<6)
+
+/* Ethernet Controller DMA Channels */
+
+#define MAC0_TX_DMA_ADDR         0xB4004000
+#define MAC1_TX_DMA_ADDR         0xB4004200
+/* offsets from MAC_TX_RING_ADDR address */
+#define MAC_TX_BUFF0_STATUS             0x0
+  #define TX_FRAME_ABORTED            (1<<0)
+  #define TX_JAB_TIMEOUT              (1<<1)
+  #define TX_NO_CARRIER               (1<<2)
+  #define TX_LOSS_CARRIER             (1<<3)
+  #define TX_EXC_DEF                  (1<<4)
+  #define TX_LATE_COLL_ABORT          (1<<5)
+  #define TX_EXC_COLL                 (1<<6)
+  #define TX_UNDERRUN                 (1<<7)
+  #define TX_DEFERRED                 (1<<8)
+  #define TX_LATE_COLL                (1<<9)
+  #define TX_COLL_CNT_MASK         (0xF<<10)
+  #define TX_PKT_RETRY               (1<<31)
+#define MAC_TX_BUFF0_ADDR                0x4
+  #define TX_DMA_ENABLE               (1<<0)
+  #define TX_T_DONE                   (1<<1)
+  #define TX_GET_DMA_BUFFER(X)    (((X)>>2)&0x3)
+#define MAC_TX_BUFF0_LEN                 0x8
+#define MAC_TX_BUFF1_STATUS             0x10
+#define MAC_TX_BUFF1_ADDR               0x14
+#define MAC_TX_BUFF1_LEN                0x18
+#define MAC_TX_BUFF2_STATUS             0x20
+#define MAC_TX_BUFF2_ADDR               0x24
+#define MAC_TX_BUFF2_LEN                0x28
+#define MAC_TX_BUFF3_STATUS             0x30
+#define MAC_TX_BUFF3_ADDR               0x34
+#define MAC_TX_BUFF3_LEN                0x38
+
+#define MAC0_RX_DMA_ADDR         0xB4004100
+#define MAC1_RX_DMA_ADDR         0xB4004300
+/* offsets from MAC_RX_RING_ADDR */
+#define MAC_RX_BUFF0_STATUS              0x0
+  #define RX_FRAME_LEN_MASK           0x3fff
+  #define RX_WDOG_TIMER              (1<<14)
+  #define RX_RUNT                    (1<<15)
+  #define RX_OVERLEN                 (1<<16)
+  #define RX_COLL                    (1<<17)
+  #define RX_ETHER                   (1<<18)
+  #define RX_MII_ERROR               (1<<19)
+  #define RX_DRIBBLING               (1<<20)
+  #define RX_CRC_ERROR               (1<<21)
+  #define RX_VLAN1                   (1<<22)
+  #define RX_VLAN2                   (1<<23)
+  #define RX_LEN_ERROR               (1<<24)
+  #define RX_CNTRL_FRAME             (1<<25)
+  #define RX_U_CNTRL_FRAME           (1<<26)
+  #define RX_MCAST_FRAME             (1<<27)
+  #define RX_BCAST_FRAME             (1<<28)
+  #define RX_FILTER_FAIL             (1<<29)
+  #define RX_PACKET_FILTER           (1<<30)
+  #define RX_MISSED_FRAME            (1<<31)
+
+  #define RX_ERROR (RX_WDOG_TIMER | RX_RUNT | RX_OVERLEN |  \
+                    RX_COLL | RX_MII_ERROR | RX_CRC_ERROR | \
+                    RX_LEN_ERROR | RX_U_CNTRL_FRAME | RX_MISSED_FRAME)
+#define MAC_RX_BUFF0_ADDR                0x4
+  #define RX_DMA_ENABLE               (1<<0)
+  #define RX_T_DONE                   (1<<1)
+  #define RX_GET_DMA_BUFFER(X)    (((X)>>2)&0x3)
+  #define RX_SET_BUFF_ADDR(X)     ((X)&0xffffffc0)
+#define MAC_RX_BUFF1_STATUS              0x10
+#define MAC_RX_BUFF1_ADDR                0x14
+#define MAC_RX_BUFF2_STATUS              0x20
+#define MAC_RX_BUFF2_ADDR                0x24
+#define MAC_RX_BUFF3_STATUS              0x30
+#define MAC_RX_BUFF3_ADDR                0x34
+
+
+/* UARTS 0-3 */
+#define UART0_ADDR                0xB1100000
+#define UART1_ADDR                0xB1200000
+#define UART2_ADDR                0xB1300000
+#define UART3_ADDR                0xB1400000
+#define UART_BASE                 UART0_ADDR
+#define UART_DEBUG_BASE           UART3_ADDR
+
+#define UART_RX		0	/* Receive buffer */
+#define UART_TX		4	/* Transmit buffer */
+#define UART_IER	8	/* Interrupt Enable Register */
+#define UART_IIR	0xC	/* Interrupt ID Register */
+#define UART_FCR	0x10	/* FIFO Control Register */
+#define UART_LCR	0x14	/* Line Control Register */
+#define UART_MCR	0x18	/* Modem Control Register */
+#define UART_LSR	0x1C	/* Line Status Register */
+#define UART_MSR	0x20	/* Modem Status Register */
+#define UART_CLK	0x28	/* Baud Rate Clock Divider */
+#define UART_MOD_CNTRL	0x100	/* Module Control */
+
+#define UART_FCR_ENABLE_FIFO	0x01 /* Enable the FIFO */
+#define UART_FCR_CLEAR_RCVR	0x02 /* Clear the RCVR FIFO */
+#define UART_FCR_CLEAR_XMIT	0x04 /* Clear the XMIT FIFO */
+#define UART_FCR_DMA_SELECT	0x08 /* For DMA applications */
+#define UART_FCR_TRIGGER_MASK	0xF0 /* Mask for the FIFO trigger range */
+#define UART_FCR_R_TRIGGER_1	0x00 /* Mask for receive trigger set at 1 */
+#define UART_FCR_R_TRIGGER_4	0x40 /* Mask for receive trigger set at 4 */
+#define UART_FCR_R_TRIGGER_8	0x80 /* Mask for receive trigger set at 8 */
+#define UART_FCR_R_TRIGGER_14   0xA0 /* Mask for receive trigger set at 14 */
+#define UART_FCR_T_TRIGGER_0	0x00 /* Mask for transmit trigger set at 0 */
+#define UART_FCR_T_TRIGGER_4	0x10 /* Mask for transmit trigger set at 4 */
+#define UART_FCR_T_TRIGGER_8    0x20 /* Mask for transmit trigger set at 8 */
+#define UART_FCR_T_TRIGGER_12	0x30 /* Mask for transmit trigger set at 12 */
+
+/*
+ * These are the definitions for the Line Control Register
+ */
+#define UART_LCR_SBC	0x40	/* Set break control */
+#define UART_LCR_SPAR	0x20	/* Stick parity (?) */
+#define UART_LCR_EPAR	0x10	/* Even parity select */
+#define UART_LCR_PARITY	0x08	/* Parity Enable */
+#define UART_LCR_STOP	0x04	/* Stop bits: 0=1 stop bit, 1= 2 stop bits */
+#define UART_LCR_WLEN5  0x00	/* Wordlength: 5 bits */
+#define UART_LCR_WLEN6  0x01	/* Wordlength: 6 bits */
+#define UART_LCR_WLEN7  0x02	/* Wordlength: 7 bits */
+#define UART_LCR_WLEN8  0x03	/* Wordlength: 8 bits */
+
+/*
+ * These are the definitions for the Line Status Register
+ */
+#define UART_LSR_TEMT	0x40	/* Transmitter empty */
+#define UART_LSR_THRE	0x20	/* Transmit-hold-register empty */
+#define UART_LSR_BI	0x10	/* Break interrupt indicator */
+#define UART_LSR_FE	0x08	/* Frame error indicator */
+#define UART_LSR_PE	0x04	/* Parity error indicator */
+#define UART_LSR_OE	0x02	/* Overrun error indicator */
+#define UART_LSR_DR	0x01	/* Receiver data ready */
+
+/*
+ * These are the definitions for the Interrupt Identification Register
+ */
+#define UART_IIR_NO_INT	0x01	/* No interrupts pending */
+#define UART_IIR_ID	0x06	/* Mask for the interrupt ID */
+#define UART_IIR_MSI	0x00	/* Modem status interrupt */
+#define UART_IIR_THRI	0x02	/* Transmitter holding register empty */
+#define UART_IIR_RDI	0x04	/* Receiver data interrupt */
+#define UART_IIR_RLSI	0x06	/* Receiver line status interrupt */
+
+/*
+ * These are the definitions for the Interrupt Enable Register
+ */
+#define UART_IER_MSI	0x08	/* Enable Modem status interrupt */
+#define UART_IER_RLSI	0x04	/* Enable receiver line status interrupt */
+#define UART_IER_THRI	0x02	/* Enable Transmitter holding register int. */
+#define UART_IER_RDI	0x01	/* Enable receiver data interrupt */
+
+/*
+ * These are the definitions for the Modem Control Register
+ */
+#define UART_MCR_LOOP	0x10	/* Enable loopback test mode */
+#define UART_MCR_OUT2	0x08	/* Out2 complement */
+#define UART_MCR_OUT1	0x04	/* Out1 complement */
+#define UART_MCR_RTS	0x02	/* RTS complement */
+#define UART_MCR_DTR	0x01	/* DTR complement */
+
+/*
+ * These are the definitions for the Modem Status Register
+ */
+#define UART_MSR_DCD	0x80	/* Data Carrier Detect */
+#define UART_MSR_RI	0x40	/* Ring Indicator */
+#define UART_MSR_DSR	0x20	/* Data Set Ready */
+#define UART_MSR_CTS	0x10	/* Clear to Send */
+#define UART_MSR_DDCD	0x08	/* Delta DCD */
+#define UART_MSR_TERI	0x04	/* Trailing edge ring indicator */
+#define UART_MSR_DDSR	0x02	/* Delta DSR */
+#define UART_MSR_DCTS	0x01	/* Delta CTS */
+#define UART_MSR_ANY_DELTA 0x0F	/* Any of the delta bits! */
+
+
+
+/* SSIO */
+#define SSI0_STATUS                0xB1600000
+  #define SSI_STATUS_BF              (1<<4)
+  #define SSI_STATUS_OF              (1<<3)
+  #define SSI_STATUS_UF              (1<<2)
+  #define SSI_STATUS_D               (1<<1)
+  #define SSI_STATUS_B               (1<<0)
+#define SSI0_INT                   0xB1600004
+  #define SSI_INT_OI                 (1<<3)
+  #define SSI_INT_UI                 (1<<2)
+  #define SSI_INT_DI                 (1<<1)
+#define SSI0_INT_ENABLE            0xB1600008
+  #define SSI_INTE_OIE               (1<<3)
+  #define SSI_INTE_UIE               (1<<2)
+  #define SSI_INTE_DIE               (1<<1)
+#define SSI0_CONFIG                0xB1600020
+  #define SSI_CONFIG_AO              (1<<24)
+  #define SSI_CONFIG_DO              (1<<23)
+  #define SSI_CONFIG_ALEN_BIT        20
+    #define SSI_CONFIG_ALEN_MASK       (0x7<<20)
+  #define SSI_CONFIG_DLEN_BIT        16
+    #define SSI_CONFIG_DLEN_MASK       (0x7<<16)
+  #define SSI_CONFIG_DD              (1<<11)
+  #define SSI_CONFIG_AD              (1<<10)
+  #define SSI_CONFIG_BM_BIT          8
+    #define SSI_CONFIG_BM_MASK         (0x3<<8)
+  #define SSI_CONFIG_CE              (1<<7)
+  #define SSI_CONFIG_DP              (1<<6)
+  #define SSI_CONFIG_DL              (1<<5)
+  #define SSI_CONFIG_EP              (1<<4)
+#define SSI0_ADATA                 0xB1600024
+  #define SSI_AD_D                   (1<<24)
+  #define SSI_AD_ADDR_BIT            16
+    #define SSI_AD_ADDR_MASK           (0xff<<16)
+  #define SSI_AD_DATA_BIT            0
+    #define SSI_AD_DATA_MASK           (0xfff<<0)
+#define SSI0_CLKDIV                0xB1600028
+#define SSI0_CONTROL               0xB1600100
+  #define SSI_CONTROL_CD             (1<<1)
+  #define SSI_CONTROL_E              (1<<0)
+
+/* SSI1 */
+#define SSI1_STATUS                0xB1680000
+#define SSI1_INT                   0xB1680004
+#define SSI1_INT_ENABLE            0xB1680008
+#define SSI1_CONFIG                0xB1680020
+#define SSI1_ADATA                 0xB1680024
+#define SSI1_CLKDIV                0xB1680028
+#define SSI1_ENABLE                0xB1680100
+
+/*
+ * Register content definitions
+ */
+#define SSI_STATUS_BF				(1<<4)
+#define SSI_STATUS_OF				(1<<3)
+#define SSI_STATUS_UF				(1<<2)
+#define SSI_STATUS_D				(1<<1)
+#define SSI_STATUS_B				(1<<0)
+
+/* SSI_INT */
+#define SSI_INT_OI					(1<<3)
+#define SSI_INT_UI					(1<<2)
+#define SSI_INT_DI					(1<<1)
+
+/* SSI_INTEN */
+#define SSI_INTEN_OIE				(1<<3)
+#define SSI_INTEN_UIE				(1<<2)
+#define SSI_INTEN_DIE				(1<<1)
+
+#define SSI_CONFIG_AO				(1<<24)
+#define SSI_CONFIG_DO				(1<<23)
+#define SSI_CONFIG_ALEN				(7<<20)
+#define SSI_CONFIG_DLEN				(15<<16)
+#define SSI_CONFIG_DD				(1<<11)
+#define SSI_CONFIG_AD				(1<<10)
+#define SSI_CONFIG_BM				(3<<8)
+#define SSI_CONFIG_CE				(1<<7)
+#define SSI_CONFIG_DP				(1<<6)
+#define SSI_CONFIG_DL				(1<<5)
+#define SSI_CONFIG_EP				(1<<4)
+#define SSI_CONFIG_ALEN_N(N)		((N-1)<<20)
+#define SSI_CONFIG_DLEN_N(N)		((N-1)<<16)
+#define SSI_CONFIG_BM_HI			(0<<8)
+#define SSI_CONFIG_BM_LO			(1<<8)
+#define SSI_CONFIG_BM_CY			(2<<8)
+
+#define SSI_ADATA_D					(1<<24)
+#define SSI_ADATA_ADDR				(0xFF<<16)
+#define SSI_ADATA_DATA				(0x0FFF)
+#define SSI_ADATA_ADDR_N(N)			(N<<16)
+
+#define SSI_ENABLE_CD				(1<<1)
+#define SSI_ENABLE_E				(1<<0)
+
+
+/* IrDA Controller */
+#define IRDA_BASE                 0xB0300000
+#define IR_RING_PTR_STATUS        (IRDA_BASE+0x00)
+#define IR_RING_BASE_ADDR_H       (IRDA_BASE+0x04)
+#define IR_RING_BASE_ADDR_L       (IRDA_BASE+0x08)
+#define IR_RING_SIZE              (IRDA_BASE+0x0C)
+#define IR_RING_PROMPT            (IRDA_BASE+0x10)
+#define IR_RING_ADDR_CMPR         (IRDA_BASE+0x14)
+#define IR_INT_CLEAR              (IRDA_BASE+0x18)
+#define IR_CONFIG_1               (IRDA_BASE+0x20)
+  #define IR_RX_INVERT_LED        (1<<0)
+  #define IR_TX_INVERT_LED        (1<<1)
+  #define IR_ST                   (1<<2)
+  #define IR_SF                   (1<<3)
+  #define IR_SIR                  (1<<4)
+  #define IR_MIR                  (1<<5)
+  #define IR_FIR                  (1<<6)
+  #define IR_16CRC                (1<<7)
+  #define IR_TD                   (1<<8)
+  #define IR_RX_ALL               (1<<9)
+  #define IR_DMA_ENABLE           (1<<10)
+  #define IR_RX_ENABLE            (1<<11)
+  #define IR_TX_ENABLE            (1<<12)
+  #define IR_LOOPBACK             (1<<14)
+  #define IR_SIR_MODE	          (IR_SIR | IR_DMA_ENABLE | \
+		                   IR_RX_ALL | IR_RX_ENABLE | IR_SF | IR_16CRC)
+#define IR_SIR_FLAGS              (IRDA_BASE+0x24)
+#define IR_ENABLE                 (IRDA_BASE+0x28)
+  #define IR_RX_STATUS            (1<<9)
+  #define IR_TX_STATUS            (1<<10)
+#define IR_READ_PHY_CONFIG        (IRDA_BASE+0x2C)
+#define IR_WRITE_PHY_CONFIG       (IRDA_BASE+0x30)
+#define IR_MAX_PKT_LEN            (IRDA_BASE+0x34)
+#define IR_RX_BYTE_CNT            (IRDA_BASE+0x38)
+#define IR_CONFIG_2               (IRDA_BASE+0x3C)
+  #define IR_MODE_INV             (1<<0)
+  #define IR_ONE_PIN              (1<<1)
+#define IR_INTERFACE_CONFIG       (IRDA_BASE+0x40)
+
+/* GPIO */
+#define SYS_PINFUNC               0xB190002C
+  #define SYS_PF_USB			(1<<15)	/* 2nd USB device/host */
+  #define SYS_PF_U3			(1<<14)	/* GPIO23/U3TXD */
+  #define SYS_PF_U2			(1<<13) /* GPIO22/U2TXD */
+  #define SYS_PF_U1			(1<<12) /* GPIO21/U1TXD */
+  #define SYS_PF_SRC			(1<<11)	/* GPIO6/SROMCKE */
+  #define SYS_PF_CK5			(1<<10)	/* GPIO3/CLK5 */
+  #define SYS_PF_CK4			(1<<9)	/* GPIO2/CLK4 */
+  #define SYS_PF_IRF			(1<<8)	/* GPIO15/IRFIRSEL */
+  #define SYS_PF_UR3			(1<<7)	/* GPIO[14:9]/UART3 */
+  #define SYS_PF_I2D			(1<<6)	/* GPIO8/I2SDI */
+  #define SYS_PF_I2S			(1<<5)	/* I2S/GPIO[29:31] */
+  #define SYS_PF_NI2			(1<<4)	/* NI2/GPIO[24:28] */
+  #define SYS_PF_U0			(1<<3)	/* U0TXD/GPIO20 */
+  #define SYS_PF_RD			(1<<2)	/* IRTXD/GPIO19 */
+  #define SYS_PF_A97			(1<<1)	/* AC97/SSL1 */
+  #define SYS_PF_S0			(1<<0)	/* SSI_0/GPIO[16:18] */
+
+/* Au1100 Only */
+  #define SYS_PF_PC			(1<<18)	/* PCMCIA/GPIO[207:204] */
+  #define SYS_PF_LCD			(1<<17)	/* extern lcd/GPIO[203:200] */
+  #define SYS_PF_CS			(1<<16)	/* EXTCLK0/32khz to gpio2 */
+  #define SYS_PF_EX0			(1<<9)	/* gpio2/clock */
+
+#define SYS_TRIOUTRD              0xB1900100
+#define SYS_TRIOUTCLR             0xB1900100
+#define SYS_OUTPUTRD              0xB1900108
+#define SYS_OUTPUTSET             0xB1900108
+#define SYS_OUTPUTCLR             0xB190010C
+#define SYS_PINSTATERD            0xB1900110
+#define SYS_PININPUTEN            0xB1900110
+
+/* GPIO2, Au1500 only */
+#define GPIO2_BASE                0xB1700000
+#define GPIO2_DIR                 (GPIO2_BASE + 0)
+#define GPIO2_OUTPUT              (GPIO2_BASE + 8)
+#define GPIO2_PINSTATE            (GPIO2_BASE + 0xC)
+#define GPIO2_INTENABLE           (GPIO2_BASE + 0x10)
+#define GPIO2_ENABLE              (GPIO2_BASE + 0x14)
+
+/* Power Management */
+#define SYS_SCRATCH0              0xB1900018
+#define SYS_SCRATCH1              0xB190001C
+#define SYS_WAKEMSK               0xB1900034
+#define SYS_ENDIAN                0xB1900038
+#define SYS_POWERCTRL             0xB190003C
+#define SYS_WAKESRC               0xB190005C
+#define SYS_SLPPWR                0xB1900078
+#define SYS_SLEEP                 0xB190007C
+
+/* Clock Controller */
+#define SYS_FREQCTRL0             0xB1900020
+  #define SYS_FC_FRDIV2_BIT         22
+  #define SYS_FC_FRDIV2_MASK        (0xff << SYS_FC_FRDIV2_BIT)
+  #define SYS_FC_FE2                (1<<21)
+  #define SYS_FC_FS2                (1<<20)
+  #define SYS_FC_FRDIV1_BIT         12
+  #define SYS_FC_FRDIV1_MASK        (0xff << SYS_FC_FRDIV1_BIT)
+  #define SYS_FC_FE1                (1<<11)
+  #define SYS_FC_FS1                (1<<10)
+  #define SYS_FC_FRDIV0_BIT         2
+  #define SYS_FC_FRDIV0_MASK        (0xff << SYS_FC_FRDIV0_BIT)
+  #define SYS_FC_FE0                (1<<1)
+  #define SYS_FC_FS0                (1<<0)
+#define SYS_FREQCTRL1             0xB1900024
+  #define SYS_FC_FRDIV5_BIT         22
+  #define SYS_FC_FRDIV5_MASK        (0xff << SYS_FC_FRDIV5_BIT)
+  #define SYS_FC_FE5                (1<<21)
+  #define SYS_FC_FS5                (1<<20)
+  #define SYS_FC_FRDIV4_BIT         12
+  #define SYS_FC_FRDIV4_MASK        (0xff << SYS_FC_FRDIV4_BIT)
+  #define SYS_FC_FE4                (1<<11)
+  #define SYS_FC_FS4                (1<<10)
+  #define SYS_FC_FRDIV3_BIT         2
+  #define SYS_FC_FRDIV3_MASK        (0xff << SYS_FC_FRDIV3_BIT)
+  #define SYS_FC_FE3                (1<<1)
+  #define SYS_FC_FS3                (1<<0)
+#define SYS_CLKSRC                0xB1900028
+  #define SYS_CS_ME1_BIT            27
+  #define SYS_CS_ME1_MASK           (0x7<<SYS_CS_ME1_BIT)
+  #define SYS_CS_DE1                (1<<26)
+  #define SYS_CS_CE1                (1<<25)
+  #define SYS_CS_ME0_BIT            22
+  #define SYS_CS_ME0_MASK           (0x7<<SYS_CS_ME0_BIT)
+  #define SYS_CS_DE0                (1<<21)
+  #define SYS_CS_CE0                (1<<20)
+  #define SYS_CS_MI2_BIT            17
+  #define SYS_CS_MI2_MASK           (0x7<<SYS_CS_MI2_BIT)
+  #define SYS_CS_DI2                (1<<16)
+  #define SYS_CS_CI2                (1<<15)
+  #define SYS_CS_MUH_BIT            12
+  #define SYS_CS_MUH_MASK           (0x7<<SYS_CS_MUH_BIT)
+  #define SYS_CS_DUH                (1<<11)
+  #define SYS_CS_CUH                (1<<10)
+  #define SYS_CS_MUD_BIT            7
+  #define SYS_CS_MUD_MASK           (0x7<<SYS_CS_MUD_BIT)
+  #define SYS_CS_DUD                (1<<6)
+  #define SYS_CS_CUD                (1<<5)
+  #define SYS_CS_MIR_BIT            2
+  #define SYS_CS_MIR_MASK           (0x7<<SYS_CS_MIR_BIT)
+  #define SYS_CS_DIR                (1<<1)
+  #define SYS_CS_CIR                (1<<0)
+
+  #define SYS_CS_MUX_AUX            0x1
+  #define SYS_CS_MUX_FQ0            0x2
+  #define SYS_CS_MUX_FQ1            0x3
+  #define SYS_CS_MUX_FQ2            0x4
+  #define SYS_CS_MUX_FQ3            0x5
+  #define SYS_CS_MUX_FQ4            0x6
+  #define SYS_CS_MUX_FQ5            0x7
+#define SYS_CPUPLL                0xB1900060
+#define SYS_AUXPLL                0xB1900064
+
+/* AC97 Controller */
+#define AC97C_CONFIG              0xB0000000
+  #define AC97C_RECV_SLOTS_BIT  13
+  #define AC97C_RECV_SLOTS_MASK (0x3ff << AC97C_RECV_SLOTS_BIT)
+  #define AC97C_XMIT_SLOTS_BIT  3
+  #define AC97C_XMIT_SLOTS_MASK (0x3ff << AC97C_XMIT_SLOTS_BIT)
+  #define AC97C_SG              (1<<2)
+  #define AC97C_SYNC            (1<<1)
+  #define AC97C_RESET           (1<<0)
+#define AC97C_STATUS              0xB0000004
+  #define AC97C_XU              (1<<11)
+  #define AC97C_XO              (1<<10)
+  #define AC97C_RU              (1<<9)
+  #define AC97C_RO              (1<<8)
+  #define AC97C_READY           (1<<7)
+  #define AC97C_CP              (1<<6)
+  #define AC97C_TR              (1<<5)
+  #define AC97C_TE              (1<<4)
+  #define AC97C_TF              (1<<3)
+  #define AC97C_RR              (1<<2)
+  #define AC97C_RE              (1<<1)
+  #define AC97C_RF              (1<<0)
+#define AC97C_DATA                0xB0000008
+#define AC97C_CMD                 0xB000000C
+  #define AC97C_WD_BIT          16
+  #define AC97C_READ            (1<<7)
+  #define AC97C_INDEX_MASK      0x7f
+#define AC97C_CNTRL               0xB0000010
+  #define AC97C_RS              (1<<1)
+  #define AC97C_CE              (1<<0)
+
+#if defined (CONFIG_SOC_AU1500) || defined(CONFIG_SOC_AU1550)
+/* Au1500 PCI Controller */
+#define Au1500_CFG_BASE           0xB4005000 // virtual, kseg0 addr
+#define Au1500_PCI_CMEM           (Au1500_CFG_BASE + 0)
+#define Au1500_PCI_CFG            (Au1500_CFG_BASE + 4)
+  #define PCI_ERROR ((1<<22) | (1<<23) | (1<<24) | (1<<25) | (1<<26) | (1<<27))
+#define Au1500_PCI_B2BMASK_CCH    (Au1500_CFG_BASE + 8)
+#define Au1500_PCI_B2B0_VID       (Au1500_CFG_BASE + 0xC)
+#define Au1500_PCI_B2B1_ID        (Au1500_CFG_BASE + 0x10)
+#define Au1500_PCI_MWMASK_DEV     (Au1500_CFG_BASE + 0x14)
+#define Au1500_PCI_MWBASE_REV_CCL (Au1500_CFG_BASE + 0x18)
+#define Au1500_PCI_ERR_ADDR       (Au1500_CFG_BASE + 0x1C)
+#define Au1500_PCI_SPEC_INTACK    (Au1500_CFG_BASE + 0x20)
+#define Au1500_PCI_ID             (Au1500_CFG_BASE + 0x100)
+#define Au1500_PCI_STATCMD        (Au1500_CFG_BASE + 0x104)
+#define Au1500_PCI_CLASSREV       (Au1500_CFG_BASE + 0x108)
+#define Au1500_PCI_HDRTYPE        (Au1500_CFG_BASE + 0x10C)
+#define Au1500_PCI_MBAR           (Au1500_CFG_BASE + 0x110)
+
+#define Au1500_PCI_HDR            0xB4005100 // virtual, kseg0 addr
+
+/* All of our structures, like pci resource, have 32 bit members.
+ * Drivers are expected to do an ioremap on the PCI MEM resource, but it's
+ * hard to store 0x4 0000 0000 in a 32 bit type.  We require a small patch
+ * to __ioremap to check for addresses between (u32)Au1500_PCI_MEM_START and
+ * (u32)Au1500_PCI_MEM_END and change those to the full 36 bit PCI MEM
+ * addresses.  For PCI IO, it's simpler because we get to do the ioremap
+ * ourselves and then adjust the device's resources.
+ */
+#define Au1500_EXT_CFG            0x600000000
+#define Au1500_EXT_CFG_TYPE1      0x680000000
+#define Au1500_PCI_IO_START       0x500000000
+#define Au1500_PCI_IO_END         0x5000FFFFF
+#define Au1500_PCI_MEM_START      0x440000000
+#define Au1500_PCI_MEM_END        0x44FFFFFFF
+
+#define PCI_IO_START    (Au1500_PCI_IO_START + 0x300)
+#define PCI_IO_END      (Au1500_PCI_IO_END)
+#define PCI_MEM_START   (Au1500_PCI_MEM_START)
+#define PCI_MEM_END     (Au1500_PCI_MEM_END)
+#define PCI_FIRST_DEVFN (0<<3)
+#define PCI_LAST_DEVFN  (19<<3)
+
+#define IOPORT_RESOURCE_START 0x00000000
+#define IOPORT_RESOURCE_END   0xffffffff
+#define IOMEM_RESOURCE_START  0x10000000
+#define IOMEM_RESOURCE_END    0xffffffff
+
+#else /* Au1000 and Au1100 */
+
+/* don't allow any legacy ports probing */
+#define IOPORT_RESOURCE_START 0x10000000;
+#define IOPORT_RESOURCE_END   0xffffffff
+#define IOMEM_RESOURCE_START  0x10000000
+#define IOMEM_RESOURCE_END    0xffffffff
+
+#ifdef CONFIG_MIPS_PB1000
+#define PCI_IO_START      0x10000000
+#define PCI_IO_END        0x1000ffff
+#define PCI_MEM_START     0x18000000
+#define PCI_MEM_END       0x18ffffff
+#define PCI_FIRST_DEVFN   0
+#define PCI_LAST_DEVFN    1
+#else
+/* no PCI bus controller */
+#define PCI_IO_START    0
+#define PCI_IO_END      0
+#define PCI_MEM_START   0
+#define PCI_MEM_END     0 
+#define PCI_FIRST_DEVFN 0
+#define PCI_LAST_DEVFN  0
+#endif
+
+#endif
+
+#if defined(CONFIG_SOC_AU1000) || defined(CONFIG_SOC_AU1500) || defined(CONFIG_SOC_AU1550)
+#define NUM_ETH_INTERFACES 2
+#elif defined(CONFIG_SOC_AU1100)
+#define NUM_ETH_INTERFACES 1
+#endif
+
+#endif
--- diff/include/asm-mips/mach-au1x00/au1000_dma.h	1970-01-01 01:00:00.000000000 +0100
+++ source/include/asm-mips/mach-au1x00/au1000_dma.h	2004-02-23 13:56:47.000000000 +0000
@@ -0,0 +1,432 @@
+/*
+ * BRIEF MODULE DESCRIPTION
+ *	Defines for using and allocating dma channels on the Alchemy
+ *      Au1000 mips processor.
+ *
+ * Copyright 2000 MontaVista Software Inc.
+ * Author: MontaVista Software, Inc.
+ *         	stevel@mvista.com or source@mvista.com
+ *
+ *  This program is free software; you can redistribute  it and/or modify it
+ *  under  the terms of  the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the  License, or (at your
+ *  option) any later version.
+ *
+ *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
+ *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
+ *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
+ *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
+ *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
+ *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *  You should have received a copy of the  GNU General Public License along
+ *  with this program; if not, write  to the Free Software Foundation, Inc.,
+ *  675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+#ifndef __ASM_AU1000_DMA_H
+#define __ASM_AU1000_DMA_H
+
+#include <asm/io.h>		/* need byte IO */
+#include <linux/spinlock.h>	/* And spinlocks */
+#include <linux/delay.h>
+#include <asm/system.h>
+
+#define NUM_AU1000_DMA_CHANNELS	8
+
+/* DMA Channel Base Addresses */
+#define DMA_CHANNEL_BASE	0xB4002000
+#define DMA_CHANNEL_LEN		0x00000100
+
+/* DMA Channel Register Offsets */
+#define DMA_MODE_SET		0x00000000
+#define DMA_MODE_READ		DMA_MODE_SET
+#define DMA_MODE_CLEAR		0x00000004
+/* DMA Mode register bits follow */
+#define DMA_DAH_MASK		(0x0f << 20)
+#define DMA_DID_BIT		16
+#define DMA_DID_MASK		(0x0f << DMA_DID_BIT)
+#define DMA_BE			(1<<13)
+#define DMA_DR			(1<<12)
+#define DMA_TS8			(1<<11)
+#define DMA_DW_BIT		9
+#define DMA_DW_MASK		(0x03 << DMA_DW_BIT)
+#define DMA_DW8			(0 << DMA_DW_BIT)
+#define DMA_DW16		(1 << DMA_DW_BIT)
+#define DMA_DW32		(2 << DMA_DW_BIT)
+#define DMA_NC			(1<<8)
+#define DMA_IE			(1<<7)
+#define DMA_HALT		(1<<6)
+#define DMA_GO			(1<<5)
+#define DMA_AB			(1<<4)
+#define DMA_D1			(1<<3)
+#define DMA_BE1			(1<<2)
+#define DMA_D0			(1<<1)
+#define DMA_BE0			(1<<0)
+
+#define DMA_PERIPHERAL_ADDR       0x00000008
+#define DMA_BUFFER0_START         0x0000000C
+#define DMA_BUFFER1_START         0x00000014
+#define DMA_BUFFER0_COUNT         0x00000010
+#define DMA_BUFFER1_COUNT         0x00000018
+#define DMA_BAH_BIT 16
+#define DMA_BAH_MASK (0x0f << DMA_BAH_BIT)
+#define DMA_COUNT_BIT 0
+#define DMA_COUNT_MASK (0xffff << DMA_COUNT_BIT)
+
+/* DMA Device ID's follow */
+enum {
+	DMA_ID_UART0_TX = 0,
+	DMA_ID_UART0_RX,
+	DMA_ID_GP04,
+	DMA_ID_GP05,
+	DMA_ID_AC97C_TX,
+	DMA_ID_AC97C_RX,
+	DMA_ID_UART3_TX,
+	DMA_ID_UART3_RX,
+	DMA_ID_USBDEV_EP0_RX,
+	DMA_ID_USBDEV_EP0_TX,
+	DMA_ID_USBDEV_EP2_TX,
+	DMA_ID_USBDEV_EP3_TX,
+	DMA_ID_USBDEV_EP4_RX,
+	DMA_ID_USBDEV_EP5_RX,
+	DMA_ID_I2S_TX,
+	DMA_ID_I2S_RX,
+	DMA_NUM_DEV
+};
+
+struct dma_chan {
+	int dev_id;		// this channel is allocated if >=0, free otherwise
+	unsigned int io;
+	const char *dev_str;
+	int irq;
+	void *irq_dev;
+	unsigned int fifo_addr;
+	unsigned int mode;
+};
+
+/* These are in arch/mips/au1000/common/dma.c */
+extern struct dma_chan au1000_dma_table[];
+extern int request_au1000_dma(int dev_id,
+			      const char *dev_str,
+			      irqreturn_t (*irqhandler)(int, void *,
+						 struct pt_regs *),
+			      unsigned long irqflags,
+			      void *irq_dev_id);
+extern void free_au1000_dma(unsigned int dmanr);
+extern int au1000_dma_read_proc(char *buf, char **start, off_t fpos,
+				int length, int *eof, void *data);
+extern void dump_au1000_dma_channel(unsigned int dmanr);
+extern spinlock_t au1000_dma_spin_lock;
+
+
+static __inline__ struct dma_chan *get_dma_chan(unsigned int dmanr)
+{
+	if (dmanr > NUM_AU1000_DMA_CHANNELS
+	    || au1000_dma_table[dmanr].dev_id < 0)
+		return NULL;
+	return &au1000_dma_table[dmanr];
+}
+
+static __inline__ unsigned long claim_dma_lock(void)
+{
+	unsigned long flags;
+	spin_lock_irqsave(&au1000_dma_spin_lock, flags);
+	return flags;
+}
+
+static __inline__ void release_dma_lock(unsigned long flags)
+{
+	spin_unlock_irqrestore(&au1000_dma_spin_lock, flags);
+}
+
+/*
+ * Set the DMA buffer enable bits in the mode register.
+ */
+static __inline__ void enable_dma_buffer0(unsigned int dmanr)
+{
+	struct dma_chan *chan = get_dma_chan(dmanr);
+	if (!chan)
+		return;
+	au_writel(DMA_BE0, chan->io + DMA_MODE_SET);
+}
+static __inline__ void enable_dma_buffer1(unsigned int dmanr)
+{
+	struct dma_chan *chan = get_dma_chan(dmanr);
+	if (!chan)
+		return;
+	au_writel(DMA_BE1, chan->io + DMA_MODE_SET);
+}
+static __inline__ void enable_dma_buffers(unsigned int dmanr)
+{
+	struct dma_chan *chan = get_dma_chan(dmanr);
+	if (!chan)
+		return;
+	au_writel(DMA_BE0 | DMA_BE1, chan->io + DMA_MODE_SET);
+}
+
+static __inline__ void start_dma(unsigned int dmanr)
+{
+	struct dma_chan *chan = get_dma_chan(dmanr);
+	if (!chan)
+		return;
+
+	au_writel(DMA_GO, chan->io + DMA_MODE_SET);
+}
+
+#define DMA_HALT_POLL 0x5000
+
+static __inline__ void halt_dma(unsigned int dmanr)
+{
+	struct dma_chan *chan = get_dma_chan(dmanr);
+	int i;
+	if (!chan)
+		return;
+
+	au_writel(DMA_GO, chan->io + DMA_MODE_CLEAR);
+	// poll the halt bit
+	for (i = 0; i < DMA_HALT_POLL; i++)
+		if (au_readl(chan->io + DMA_MODE_READ) & DMA_HALT)
+			break;
+	if (i == DMA_HALT_POLL)
+		printk(KERN_INFO "halt_dma: HALT poll expired!\n");
+}
+
+
+static __inline__ void disable_dma(unsigned int dmanr)
+{
+	struct dma_chan *chan = get_dma_chan(dmanr);
+	if (!chan)
+		return;
+
+	halt_dma(dmanr);
+
+		// now we can disable the buffers
+		au_writel(~DMA_GO, chan->io + DMA_MODE_CLEAR);
+}
+
+static __inline__ int dma_halted(unsigned int dmanr)
+{
+	struct dma_chan *chan = get_dma_chan(dmanr);
+	if (!chan)
+		return 1;
+	return (au_readl(chan->io + DMA_MODE_READ) & DMA_HALT) ? 1 : 0;
+}
+
+/* initialize a DMA channel */
+static __inline__ void init_dma(unsigned int dmanr)
+{
+	struct dma_chan *chan = get_dma_chan(dmanr);
+	u32 mode;
+	if (!chan)
+		return;
+
+	disable_dma(dmanr);
+
+	// set device FIFO address
+	au_writel(CPHYSADDR(chan->fifo_addr),
+		  chan->io + DMA_PERIPHERAL_ADDR);
+
+	mode = chan->mode | (chan->dev_id << DMA_DID_BIT);
+	if (chan->irq)
+		mode |= DMA_IE;
+
+	au_writel(~mode, chan->io + DMA_MODE_CLEAR);
+	au_writel(mode, chan->io + DMA_MODE_SET);
+}
+
+/*
+ * set mode for a specific DMA channel
+ */
+static __inline__ void set_dma_mode(unsigned int dmanr, unsigned int mode)
+{
+	struct dma_chan *chan = get_dma_chan(dmanr);
+	if (!chan)
+		return;
+	/*
+	 * set_dma_mode is only allowed to change endianess, direction,
+	 * transfer size, device FIFO width, and coherency settings.
+	 * Make sure anything else is masked off.
+	 */
+	mode &= (DMA_BE | DMA_DR | DMA_TS8 | DMA_DW_MASK | DMA_NC);
+	chan->mode &= ~(DMA_BE | DMA_DR | DMA_TS8 | DMA_DW_MASK | DMA_NC);
+	chan->mode |= mode;
+}
+
+static __inline__ unsigned int get_dma_mode(unsigned int dmanr)
+{
+	struct dma_chan *chan = get_dma_chan(dmanr);
+	if (!chan)
+		return 0;
+	return chan->mode;
+}
+
+static __inline__ int get_dma_active_buffer(unsigned int dmanr)
+{
+	struct dma_chan *chan = get_dma_chan(dmanr);
+	if (!chan)
+		return -1;
+	return (au_readl(chan->io + DMA_MODE_READ) & DMA_AB) ? 1 : 0;
+}
+
+
+/*
+ * set the device FIFO address for a specific DMA channel - only
+ * applicable to GPO4 and GPO5. All the other devices have fixed
+ * FIFO addresses.
+ */
+static __inline__ void set_dma_fifo_addr(unsigned int dmanr,
+					 unsigned int a)
+{
+	struct dma_chan *chan = get_dma_chan(dmanr);
+	if (!chan)
+		return;
+
+	if (chan->dev_id != DMA_ID_GP04 && chan->dev_id != DMA_ID_GP05)
+		return;
+
+	au_writel(CPHYSADDR(a), chan->io + DMA_PERIPHERAL_ADDR);
+}
+
+/*
+ * Clear the DMA buffer done bits in the mode register.
+ */
+static __inline__ void clear_dma_done0(unsigned int dmanr)
+{
+	struct dma_chan *chan = get_dma_chan(dmanr);
+	if (!chan)
+		return;
+	au_writel(DMA_D0, chan->io + DMA_MODE_CLEAR);
+}
+static __inline__ void clear_dma_done1(unsigned int dmanr)
+{
+	struct dma_chan *chan = get_dma_chan(dmanr);
+	if (!chan)
+		return;
+	au_writel(DMA_D1, chan->io + DMA_MODE_CLEAR);
+}
+
+/*
+ * This does nothing - not applicable to Au1000 DMA.
+ */
+static __inline__ void set_dma_page(unsigned int dmanr, char pagenr)
+{
+}
+
+/*
+ * Set Buffer 0 transfer address for specific DMA channel.
+ */
+static __inline__ void set_dma_addr0(unsigned int dmanr, unsigned int a)
+{
+	struct dma_chan *chan = get_dma_chan(dmanr);
+	if (!chan)
+		return;
+	au_writel(a, chan->io + DMA_BUFFER0_START);
+}
+
+/*
+ * Set Buffer 1 transfer address for specific DMA channel.
+ */
+static __inline__ void set_dma_addr1(unsigned int dmanr, unsigned int a)
+{
+	struct dma_chan *chan = get_dma_chan(dmanr);
+	if (!chan)
+		return;
+	au_writel(a, chan->io + DMA_BUFFER1_START);
+}
+
+
+/*
+ * Set Buffer 0 transfer size (max 64k) for a specific DMA channel.
+ */
+static __inline__ void set_dma_count0(unsigned int dmanr,
+				      unsigned int count)
+{
+	struct dma_chan *chan = get_dma_chan(dmanr);
+	if (!chan)
+		return;
+	count &= DMA_COUNT_MASK;
+	au_writel(count, chan->io + DMA_BUFFER0_COUNT);
+}
+
+/*
+ * Set Buffer 1 transfer size (max 64k) for a specific DMA channel.
+ */
+static __inline__ void set_dma_count1(unsigned int dmanr,
+				      unsigned int count)
+{
+	struct dma_chan *chan = get_dma_chan(dmanr);
+	if (!chan)
+		return;
+	count &= DMA_COUNT_MASK;
+	au_writel(count, chan->io + DMA_BUFFER1_COUNT);
+}
+
+/*
+ * Set both buffer transfer sizes (max 64k) for a specific DMA channel.
+ */
+static __inline__ void set_dma_count(unsigned int dmanr,
+				     unsigned int count)
+{
+	struct dma_chan *chan = get_dma_chan(dmanr);
+	if (!chan)
+		return;
+	count &= DMA_COUNT_MASK;
+	au_writel(count, chan->io + DMA_BUFFER0_COUNT);
+	au_writel(count, chan->io + DMA_BUFFER1_COUNT);
+}
+
+/*
+ * Returns which buffer has its done bit set in the mode register.
+ * Returns -1 if neither or both done bits set.
+ */
+static __inline__ unsigned int get_dma_buffer_done(unsigned int dmanr)
+{
+	struct dma_chan *chan = get_dma_chan(dmanr);
+	if (!chan)
+		return 0;
+
+    return au_readl(chan->io + DMA_MODE_READ) & (DMA_D0 | DMA_D1);
+}
+
+
+/*
+ * Returns the DMA channel's Buffer Done IRQ number.
+ */
+static __inline__ int get_dma_done_irq(unsigned int dmanr)
+{
+	struct dma_chan *chan = get_dma_chan(dmanr);
+	if (!chan)
+		return -1;
+
+	return chan->irq;
+}
+
+/*
+ * Get DMA residue count. Returns the number of _bytes_ left to transfer.
+ */
+static __inline__ int get_dma_residue(unsigned int dmanr)
+{
+	int curBufCntReg, count;
+	struct dma_chan *chan = get_dma_chan(dmanr);
+	if (!chan)
+		return 0;
+
+	curBufCntReg = (au_readl(chan->io + DMA_MODE_READ) & DMA_AB) ?
+	    DMA_BUFFER1_COUNT : DMA_BUFFER0_COUNT;
+
+	count = au_readl(chan->io + curBufCntReg) & DMA_COUNT_MASK;
+
+	if ((chan->mode & DMA_DW_MASK) == DMA_DW16)
+		count <<= 1;
+	else if ((chan->mode & DMA_DW_MASK) == DMA_DW32)
+		count <<= 2;
+
+	return count;
+}
+
+#endif /* __ASM_AU1000_DMA_H */
--- diff/include/asm-mips/mach-au1x00/au1000_gpio.h	1970-01-01 01:00:00.000000000 +0100
+++ source/include/asm-mips/mach-au1x00/au1000_gpio.h	2004-02-23 13:56:47.000000000 +0000
@@ -0,0 +1,56 @@
+/*
+ * FILE NAME au1000_gpio.h
+ *
+ * BRIEF MODULE DESCRIPTION
+ *	API to Alchemy Au1000 GPIO device.
+ *
+ *  Author: MontaVista Software, Inc.  <source@mvista.com>
+ *          Steve Longerbeam <stevel@mvista.com>
+ *
+ * Copyright 2001 MontaVista Software Inc.
+ *
+ *  This program is free software; you can redistribute  it and/or modify it
+ *  under  the terms of  the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the  License, or (at your
+ *  option) any later version.
+ *
+ *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
+ *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
+ *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
+ *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
+ *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
+ *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *  You should have received a copy of the  GNU General Public License along
+ *  with this program; if not, write  to the Free Software Foundation, Inc.,
+ *  675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef __AU1000_GPIO_H
+#define __AU1000_GPIO_H
+
+#include <linux/ioctl.h>
+
+#define AU1000GPIO_IOC_MAGIC 'A'
+
+#define AU1000GPIO_IN		_IOR (AU1000GPIO_IOC_MAGIC, 0, int)
+#define AU1000GPIO_SET		_IOW (AU1000GPIO_IOC_MAGIC, 1, int)
+#define AU1000GPIO_CLEAR	_IOW (AU1000GPIO_IOC_MAGIC, 2, int)
+#define AU1000GPIO_OUT		_IOW (AU1000GPIO_IOC_MAGIC, 3, int)
+#define AU1000GPIO_TRISTATE	_IOW (AU1000GPIO_IOC_MAGIC, 4, int)
+#define AU1000GPIO_AVAIL_MASK	_IOR (AU1000GPIO_IOC_MAGIC, 5, int)
+
+#ifdef __KERNEL__
+extern u32 get_au1000_avail_gpio_mask(void);
+extern int au1000gpio_tristate(u32 data);
+extern int au1000gpio_in(u32 *data);
+extern int au1000gpio_set(u32 data);
+extern int au1000gpio_clear(u32 data);
+extern int au1000gpio_out(u32 data);
+#endif
+
+#endif
--- diff/include/asm-mips/mach-au1x00/au1000_pcmcia.h	1970-01-01 01:00:00.000000000 +0100
+++ source/include/asm-mips/mach-au1x00/au1000_pcmcia.h	2004-02-23 13:56:47.000000000 +0000
@@ -0,0 +1,107 @@
+/*
+ * Alchemy Semi Au1000 pcmcia driver include file
+ *
+ * Copyright 2001 MontaVista Software Inc.
+ * Author: MontaVista Software, Inc.
+ *         	ppopov@mvista.com or source@mvista.com
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ */
+#ifndef __ASM_AU1000_PCMCIA_H
+#define __ASM_AU1000_PCMCIA_H
+
+#include <linux/config.h>
+
+#define AU1000_PCMCIA_POLL_PERIOD    (2*HZ)
+#define AU1000_PCMCIA_IO_SPEED       (255)
+#define AU1000_PCMCIA_MEM_SPEED      (300)
+
+#define AU1X_SOCK0_IO        0xF00000000
+#define AU1X_SOCK0_PHYS_ATTR 0xF40000000
+#define AU1X_SOCK0_PHYS_MEM  0xF80000000
+
+/* pcmcia socket 1 needs external glue logic so the memory map
+ * differs from board to board.
+ */
+#if defined(CONFIG_MIPS_PB1000) || defined(CONFIG_MIPS_PB1100) || defined(CONFIG_MIPS_PB1500)
+#define AU1X_SOCK1_IO        0xF08000000
+#define AU1X_SOCK1_PHYS_ATTR 0xF48000000
+#define AU1X_SOCK1_PHYS_MEM  0xF88000000
+#elif defined(CONFIG_MIPS_DB1000) || defined(CONFIG_MIPS_DB1100) || defined(CONFIG_MIPS_DB1500)
+#define AU1X_SOCK1_IO        0xF04000000
+#define AU1X_SOCK1_PHYS_ATTR 0xF44000000
+#define AU1X_SOCK1_PHYS_MEM  0xF84000000
+#endif
+
+struct pcmcia_state {
+  unsigned detect: 1,
+            ready: 1,
+           wrprot: 1,
+	     bvd1: 1,
+	     bvd2: 1,
+            vs_3v: 1,
+            vs_Xv: 1;
+};
+
+struct pcmcia_configure {
+  unsigned sock: 8,
+            vcc: 8,
+            vpp: 8,
+         output: 1,
+        speaker: 1,
+          reset: 1;
+};
+
+struct pcmcia_irq_info {
+	unsigned int sock;
+	unsigned int irq;
+};
+
+
+struct au1000_pcmcia_socket {
+	socket_state_t        cs_state;
+	struct pcmcia_state   k_state;
+	unsigned int          irq;
+	void                  (*handler)(void *, unsigned int);
+	void                  *handler_info;
+	pccard_io_map         io_map[MAX_IO_WIN];
+	pccard_mem_map        mem_map[MAX_WIN];
+	u32                   virt_io;
+	ioaddr_t              phys_attr, phys_mem;
+	unsigned short        speed_io, speed_attr, speed_mem;
+};
+
+struct pcmcia_init {
+	void (*handler)(int irq, void *dev, struct pt_regs *regs);
+};
+
+struct pcmcia_low_level {
+	int (*init)(struct pcmcia_init *);
+	int (*shutdown)(void);
+	int (*socket_state)(unsigned sock, struct pcmcia_state *);
+	int (*get_irq_info)(struct pcmcia_irq_info *);
+	int (*configure_socket)(const struct pcmcia_configure *);
+};
+
+#if defined(CONFIG_MIPS_PB1000) || defined(CONFIG_MIPS_PB1100) || defined(CONFIG_MIPS_PB1500)
+extern struct pcmcia_low_level pb1x00_pcmcia_ops;
+#elif defined(CONFIG_MIPS_DB1000) || defined(CONFIG_MIPS_DB1100) || defined(CONFIG_MIPS_DB1500)
+extern struct pcmcia_low_level db1x00_pcmcia_ops;
+#elif defined(CONFIG_MIPS_XXS1500)
+extern struct pcmcia_low_level xxs1500_pcmcia_ops;
+#else
+error unknown Au1000 board
+#endif
+
+#endif /* __ASM_AU1000_PCMCIA_H */
--- diff/include/asm-mips/mach-au1x00/au1000_usbdev.h	1970-01-01 01:00:00.000000000 +0100
+++ source/include/asm-mips/mach-au1x00/au1000_usbdev.h	2004-02-23 13:56:47.000000000 +0000
@@ -0,0 +1,73 @@
+/*
+ * BRIEF MODULE DESCRIPTION
+ *	Au1000 USB Device-Side Driver
+ *
+ * Copyright 2001 MontaVista Software Inc.
+ * Author: MontaVista Software, Inc.
+ *		stevel@mvista.com or source@mvista.com
+ *
+ *  This program is free software; you can redistribute	 it and/or modify it
+ *  under  the terms of	 the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the	License, or (at your
+ *  option) any later version.
+ *
+ *  THIS  SOFTWARE  IS PROVIDED	  ``AS	IS'' AND   ANY	EXPRESS OR IMPLIED
+ *  WARRANTIES,	  INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
+ *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
+ *  NO	EVENT  SHALL   THE AUTHOR  BE	 LIABLE FOR ANY	  DIRECT, INDIRECT,
+ *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ *  NOT LIMITED	  TO, PROCUREMENT OF  SUBSTITUTE GOODS	OR SERVICES; LOSS OF
+ *  USE, DATA,	OR PROFITS; OR	BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ *  ANY THEORY OF LIABILITY, WHETHER IN	 CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *  You should have received a copy of the  GNU General Public License along
+ *  with this program; if not, write  to the Free Software Foundation, Inc.,
+ *  675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#define USBDEV_REV 0x0110 // BCD
+#define USBDEV_EP0_MAX_PACKET_SIZE 64
+
+typedef enum {
+	ATTACHED = 0,
+	POWERED,
+	DEFAULT,
+	ADDRESS,
+	CONFIGURED
+} usbdev_state_t;
+
+typedef enum {
+	CB_NEW_STATE = 0,
+	CB_PKT_COMPLETE
+} usbdev_cb_type_t;
+
+
+typedef struct usbdev_pkt {
+	int                ep_addr;    // ep addr this packet routed to
+	int                size;       // size of payload in bytes
+	unsigned           status;     // packet status
+	struct usbdev_pkt* next;       // function layer can't touch this
+	u8                 payload[0]; // the payload
+} usbdev_pkt_t;
+
+#define PKT_STATUS_ACK  (1<<0)
+#define PKT_STATUS_NAK  (1<<1)
+#define PKT_STATUS_SU   (1<<2)
+
+extern int usbdev_init(struct usb_device_descriptor* dev_desc,
+		       struct usb_config_descriptor* config_desc,
+		       struct usb_interface_descriptor* if_desc,
+		       struct usb_endpoint_descriptor* ep_desc,
+		       struct usb_string_descriptor* str_desc[],
+		       void (*cb)(usbdev_cb_type_t, unsigned long, void *),
+		       void* cb_data);
+
+extern void usbdev_exit(void);
+
+extern int usbdev_alloc_packet  (int ep_addr, int data_size,
+				 usbdev_pkt_t** pkt);
+extern int usbdev_send_packet   (int ep_addr, usbdev_pkt_t* pkt);
+extern int usbdev_receive_packet(int ep_addr, usbdev_pkt_t** pkt);
+extern int usbdev_get_byte_count(int ep_addr);
--- diff/include/asm-mips/mach-au1x00/timex.h	1970-01-01 01:00:00.000000000 +0100
+++ source/include/asm-mips/mach-au1x00/timex.h	2004-02-23 13:56:47.000000000 +0000
@@ -0,0 +1,13 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2003 by Ralf Baechle
+ */
+#ifndef __ASM_MACH_AU1X00_TIMEX_H
+#define __ASM_MACH_AU1X00_TIMEX_H
+
+#define CLOCK_TICK_RATE		((HZ * 100000UL) / 2)
+
+#endif /* __ASM_MACH_AU1X00_TIMEX_H */
--- diff/include/asm-mips/mach-db1x00/db1x00.h	1970-01-01 01:00:00.000000000 +0100
+++ source/include/asm-mips/mach-db1x00/db1x00.h	2004-02-23 13:56:47.000000000 +0000
@@ -0,0 +1,125 @@
+/*
+ * AMD Alchemy DB1x00 Reference Boards
+ *
+ * Copyright 2001 MontaVista Software Inc.
+ * Author: MontaVista Software, Inc.
+ *         	ppopov@mvista.com or source@mvista.com
+ *
+ * ########################################################################
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ *
+ * 
+ */
+#ifndef __ASM_DB1X00_H
+#define __ASM_DB1X00_H
+
+
+/*
+ * Overlay data structure of the Db1x00 board registers.
+ * Registers located at physical 1E0000xx, KSEG1 0xAE0000xx
+ */
+typedef volatile struct
+{
+	/*00*/	unsigned long whoami;
+	/*04*/	unsigned long status;
+	/*08*/	unsigned long switches;
+	/*0C*/	unsigned long resets;
+	/*10*/	unsigned long pcmcia;
+	/*14*/	unsigned long specific;
+	/*18*/	unsigned long leds;
+	/*1C*/	unsigned long swreset;
+
+} BCSR;
+
+
+/*
+ * Register/mask bit definitions for the BCSRs
+ */
+#define BCSR_WHOAMI_DCID		0x000F
+#define BCSR_WHOAMI_CPLD		0x00F0
+#define BCSR_WHOAMI_BOARD		0x0F00
+
+#define BCSR_STATUS_PC0VS		0x0003
+#define BCSR_STATUS_PC1VS		0x000C
+#define BCSR_STATUS_PC0FI		0x0010
+#define BCSR_STATUS_PC1FI		0x0020
+#define BCSR_STATUS_FLASHBUSY		0x0100
+#define BCSR_STATUS_ROMBUSY		0x0400
+#define BCSR_STATUS_SWAPBOOT		0x2000
+#define BCSR_STATUS_FLASHDEN		0xC000
+
+#define BCSR_SWITCHES_DIP		0x00FF
+#define BCSR_SWITCHES_DIP_1		0x0080
+#define BCSR_SWITCHES_DIP_2		0x0040
+#define BCSR_SWITCHES_DIP_3		0x0020
+#define BCSR_SWITCHES_DIP_4		0x0010
+#define BCSR_SWITCHES_DIP_5		0x0008
+#define BCSR_SWITCHES_DIP_6		0x0004
+#define BCSR_SWITCHES_DIP_7		0x0002
+#define BCSR_SWITCHES_DIP_8		0x0001
+#define BCSR_SWITCHES_ROTARY		0x0F00
+
+#define BCSR_RESETS_PHY0		0x0001
+#define BCSR_RESETS_PHY1		0x0002
+#define BCSR_RESETS_DC			0x0004
+#define BCSR_RESETS_FIR_SEL		0x2000
+#define BCSR_RESETS_IRDA_MODE_MASK	0xC000
+#define BCSR_RESETS_IRDA_MODE_FULL	0x0000
+#define BCSR_RESETS_IRDA_MODE_OFF	0x4000
+#define BCSR_RESETS_IRDA_MODE_2_3	0x8000
+#define BCSR_RESETS_IRDA_MODE_1_3	0xC000
+
+#define BCSR_PCMCIA_PC0VPP		0x0003
+#define BCSR_PCMCIA_PC0VCC		0x000C
+#define BCSR_PCMCIA_PC0DRVEN		0x0010
+#define BCSR_PCMCIA_PC0RST		0x0080
+#define BCSR_PCMCIA_PC1VPP		0x0300
+#define BCSR_PCMCIA_PC1VCC		0x0C00
+#define BCSR_PCMCIA_PC1DRVEN		0x1000
+#define BCSR_PCMCIA_PC1RST		0x8000
+
+#define BCSR_BOARD_PCIM66EN		0x0001
+#define BCSR_BOARD_PCIM33		0x0100
+#define BCSR_BOARD_GPIO200RST		0x0400
+#define BCSR_BOARD_PCICFG		0x1000
+
+#define BCSR_LEDS_DECIMALS		0x0003
+#define BCSR_LEDS_LED0			0x0100
+#define BCSR_LEDS_LED1			0x0200
+#define BCSR_LEDS_LED2			0x0400
+#define BCSR_LEDS_LED3			0x0800
+
+#define BCSR_SWRESET_RESET		0x0080
+
+/* PCMCIA Db1x00 specific defines */
+#define PCMCIA_MAX_SOCK 1
+#define PCMCIA_NUM_SOCKS (PCMCIA_MAX_SOCK+1)
+
+/* VPP/VCC */
+#define SET_VCC_VPP(VCC, VPP, SLOT)\
+	((((VCC)<<2) | ((VPP)<<0)) << ((SLOT)*8))
+
+/* MTD CONFIG OPTIONS */
+#if defined(CONFIG_MTD_DB1X00_BOOT) && defined(CONFIG_MTD_DB1X00_USER)
+#define DB1X00_BOTH_BANKS
+#elif defined(CONFIG_MTD_DB1X00_BOOT) && !defined(CONFIG_MTD_DB1X00_USER)
+#define DB1X00_BOOT_ONLY
+#elif !defined(CONFIG_MTD_DB1X00_BOOT) && defined(CONFIG_MTD_DB1X00_USER)
+#define DB1X00_USER_ONLY
+#endif
+
+#endif /* __ASM_DB1X00_H */
--- diff/include/asm-mips/mach-ddb5074/mc146818rtc.h	1970-01-01 01:00:00.000000000 +0100
+++ source/include/asm-mips/mach-ddb5074/mc146818rtc.h	2004-02-23 13:56:47.000000000 +0000
@@ -0,0 +1,31 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 1998, 2001, 03 by Ralf Baechle
+ *
+ * RTC routines for PC style attached Dallas chip.
+ */
+#ifndef __ASM_MACH_DDB5074_MC146818RTC_H
+#define __ASM_MACH_DDB5074_MC146818RTC_H
+
+#include <asm/ddb5xxx/ddb5074.h>
+#include <asm/ddb5xxx/ddb5xxx.h>
+
+#define RTC_PORT(x)	(0x70 + (x))
+#define RTC_IRQ		8
+
+static inline unsigned char CMOS_READ(unsigned long addr)
+{
+	return *(volatile unsigned char *)(KSEG1ADDR(DDB_PCI_MEM_BASE)+addr);
+}
+
+static inline void CMOS_WRITE(unsigned char data, unsigned long addr)
+{
+	*(volatile unsigned char *)(KSEG1ADDR(DDB_PCI_MEM_BASE)+addr) = data;
+}
+
+#define RTC_ALWAYS_BCD	1
+
+#endif /* __ASM_MACH_DDB5074_MC146818RTC_H */
--- diff/include/asm-mips/mach-dec/mc146818rtc.h	1970-01-01 01:00:00.000000000 +0100
+++ source/include/asm-mips/mach-dec/mc146818rtc.h	2004-02-23 13:56:47.000000000 +0000
@@ -0,0 +1,46 @@
+/*
+ * RTC definitions for DECstation style attached Dallas DS1287 chip.
+ *
+ * Copyright (C) 1998, 2001 by Ralf Baechle
+ * Copyright (C) 1998 by Harald Koerfgen
+ * Copyright (C) 2002  Maciej W. Rozycki
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+#ifndef __ASM_MIPS_DEC_RTC_DEC_H
+#define __ASM_MIPS_DEC_RTC_DEC_H
+
+#include <linux/types.h>
+
+#include <asm/addrspace.h>
+
+extern volatile u8 *dec_rtc_base;
+extern unsigned long dec_kn_slot_size;
+
+#define RTC_PORT(x)	CPHYSADDR(dec_rtc_base)
+#define RTC_IO_EXTENT	dec_kn_slot_size
+#define RTC_IOMAPPED	0
+#define RTC_IRQ		0
+
+#define RTC_DEC_YEAR	0x3f	/* Where we store the real year on DECs.  */
+
+#include <linux/mc146818rtc.h>
+#include <linux/module.h>
+#include <linux/types.h>
+
+static inline unsigned char CMOS_READ(unsigned long addr)
+{
+	return dec_rtc_base[addr * 4];
+}
+
+static inline void CMOS_WRITE(unsigned char data, unsigned long addr)
+{
+	dec_rtc_base[addr * 4] = data;
+}
+
+#define RTC_ALWAYS_BCD	0
+
+#endif /* __ASM_MIPS_DEC_RTC_DEC_H */
--- diff/include/asm-mips/mach-dec/param.h	1970-01-01 01:00:00.000000000 +0100
+++ source/include/asm-mips/mach-dec/param.h	2004-02-23 13:56:47.000000000 +0000
@@ -0,0 +1,18 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2003 by Ralf Baechle
+ */
+#ifndef __ASM_MACH_DEC_PARAM_H
+#define __ASM_MACH_DEC_PARAM_H
+
+/*
+ * log2(HZ), change this here if you want another HZ value. This is also
+ * used in dec_time_init.  Minimum is 1, Maximum is 15.
+ */
+#define LOG_2_HZ 7
+#define HZ (1 << LOG_2_HZ)
+
+#endif /* __ASM_MACH_DEC_PARAM_H */
--- diff/include/asm-mips/mach-ev64120/mach-gt64120.h	1970-01-01 01:00:00.000000000 +0100
+++ source/include/asm-mips/mach-ev64120/mach-gt64120.h	2004-02-23 13:56:47.000000000 +0000
@@ -0,0 +1,61 @@
+/*
+ *  This is a direct copy of the ev96100.h file, with a global
+ * search and replace.  The numbers are the same.
+ *
+ *  The reason I'm duplicating this is so that the 64120/96100
+ * defines won't be confusing in the source code.
+ */
+#ifndef __ASM_GALILEO_BOARDS_MIPS_EV64120_H
+#define __ASM_GALILEO_BOARDS_MIPS_EV64120_H
+
+/*
+ *   GT64120 config space base address
+ */
+extern unsigned long gt64120_base;
+
+#define GT64120_BASE	(gt64120_base)
+
+/*
+ *   PCI Bus allocation
+ */
+#define GT_PCI_MEM_BASE    0x12000000UL
+#define GT_PCI_MEM_SIZE    0x02000000UL
+#define GT_PCI_IO_BASE     0x10000000UL
+#define GT_PCI_IO_SIZE     0x02000000UL
+#define GT_ISA_IO_BASE     PCI_IO_BASE
+
+/*
+ *   Duart I/O ports.
+ */
+#define EV64120_COM1_BASE_ADDR  (0x1d000000 + 0x20)
+#define EV64120_COM2_BASE_ADDR  (0x1d000000 + 0x00)
+
+
+/*
+ *   EV64120 interrupt controller register base.
+ */
+#define EV64120_ICTRL_REGS_BASE   (KSEG1ADDR(0x1f000000))
+
+/*
+ *   EV64120 UART register base.
+ */
+#define EV64120_UART0_REGS_BASE    (KSEG1ADDR(EV64120_COM1_BASE_ADDR))
+#define EV64120_UART1_REGS_BASE    (KSEG1ADDR(EV64120_COM2_BASE_ADDR))
+#define EV64120_BASE_BAUD ( 3686400 / 16 )
+
+/*
+ * PCI interrupts will come in on either the INTA or INTD interrups lines,
+ * which are mapped to the #2 and #5 interrupt pins of the MIPS.  On our
+ * boards, they all either come in on IntD or they all come in on IntA, they
+ * aren't mixed. There can be numerous PCI interrupts, so we keep a list of the
+ * "requested" interrupt numbers and go through the list whenever we get an
+ * IntA/D.
+ *
+ * Interrupts < 8 are directly wired to the processor; PCI INTA is 8 and
+ * INTD is 11.
+ */
+#define GT_TIMER	4
+#define GT_INTA		2
+#define GT_INTD		5
+
+#endif /* __ASM_GALILEO_BOARDS_MIPS_EV64120_H */
--- diff/include/asm-mips/mach-ev96100/mach-gt64120.h	1970-01-01 01:00:00.000000000 +0100
+++ source/include/asm-mips/mach-ev96100/mach-gt64120.h	2004-02-23 13:56:47.000000000 +0000
@@ -0,0 +1,46 @@
+/*
+ *  This is a direct copy of the ev96100.h file, with a global
+ * search and replace.  The numbers are the same.
+ *
+ *  The reason I'm duplicating this is so that the 64120/96100
+ * defines won't be confusing in the source code.
+ */
+#ifndef _ASM_GT64120_EV96100_GT64120_DEP_H
+#define _ASM_GT64120_EV96100_GT64120_DEP_H
+
+/*
+ *   GT96100 config space base address
+ */
+#define GT64120_BASE	(KSEG1ADDR(0x14000000))
+
+/*
+ *   PCI Bus allocation
+ *
+ *   (Guessing ...)
+ */
+#define GT_PCI_MEM_BASE    0x12000000UL
+#define GT_PCI_MEM_SIZE    0x02000000UL
+#define GT_PCI_IO_BASE     0x10000000UL
+#define GT_PCI_IO_SIZE     0x02000000UL
+#define GT_ISA_IO_BASE     PCI_IO_BASE
+
+/*
+ *   Duart I/O ports.
+ */
+#define EV96100_COM1_BASE_ADDR  (0xBD000000 + 0x20)
+#define EV96100_COM2_BASE_ADDR  (0xBD000000 + 0x00)
+
+
+/*
+ *   EV96100 interrupt controller register base.
+ */
+#define EV96100_ICTRL_REGS_BASE   (KSEG1ADDR(0x1f000000))
+
+/*
+ *   EV96100 UART register base.
+ */
+#define EV96100_UART0_REGS_BASE    EV96100_COM1_BASE_ADDR
+#define EV96100_UART1_REGS_BASE    EV96100_COM2_BASE_ADDR
+#define EV96100_BASE_BAUD ( 3686400 / 16 )
+
+#endif /* _ASM_GT64120_EV96100_GT64120_DEP_H */
--- diff/include/asm-mips/mach-generic/cpu-feature-overrides.h	1970-01-01 01:00:00.000000000 +0100
+++ source/include/asm-mips/mach-generic/cpu-feature-overrides.h	2004-02-23 13:56:47.000000000 +0000
@@ -0,0 +1,13 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2003 Ralf Baechle
+ */
+#ifndef __ASM_MACH_GENERIC_CPU_FEATURE_OVERRIDES_H
+#define __ASM_MACH_GENERIC_CPU_FEATURE_OVERRIDES_H
+
+/* Intensionally empty file ...  */
+
+#endif /* __ASM_MACH_GENERIC_CPU_FEATURE_OVERRIDES_H */
--- diff/include/asm-mips/mach-generic/floppy.h	1970-01-01 01:00:00.000000000 +0100
+++ source/include/asm-mips/mach-generic/floppy.h	2004-02-23 13:56:47.000000000 +0000
@@ -0,0 +1,140 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 1996, 1997, 1998, 2003 by Ralf Baechle
+ */
+#ifndef __ASM_MACH_GENERIC_FLOPPY_H
+#define __ASM_MACH_GENERIC_FLOPPY_H
+
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/linkage.h>
+#include <linux/types.h>
+#include <linux/mm.h>
+
+#include <asm/bootinfo.h>
+#include <asm/cachectl.h>
+#include <asm/dma.h>
+#include <asm/floppy.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/pgtable.h>
+
+/*
+ * How to access the FDC's registers.
+ */
+static inline unsigned char fd_inb(unsigned int port)
+{
+	return inb_p(port);
+}
+
+static inline void fd_outb(unsigned char value, unsigned int port)
+{
+	outb_p(value, port);
+}
+
+/*
+ * How to access the floppy DMA functions.
+ */
+static inline void fd_enable_dma(void)
+{
+	enable_dma(FLOPPY_DMA);
+}
+
+static inline void fd_disable_dma(void)
+{
+	disable_dma(FLOPPY_DMA);
+}
+
+static inline int fd_request_dma(void)
+{
+	return request_dma(FLOPPY_DMA, "floppy");
+}
+
+static inline void fd_free_dma(void)
+{
+	free_dma(FLOPPY_DMA);
+}
+
+static inline void fd_clear_dma_ff(void)
+{
+	clear_dma_ff(FLOPPY_DMA);
+}
+
+static inline void fd_set_dma_mode(char mode)
+{
+	set_dma_mode(FLOPPY_DMA, mode);
+}
+
+static inline void fd_set_dma_addr(char *addr)
+{
+	set_dma_addr(FLOPPY_DMA, (unsigned long) addr);
+}
+
+static inline void fd_set_dma_count(unsigned int count)
+{
+	set_dma_count(FLOPPY_DMA, count);
+}
+
+static inline int fd_get_dma_residue(void)
+{
+	return get_dma_residue(FLOPPY_DMA);
+}
+
+static inline void fd_enable_irq(void)
+{
+	enable_irq(FLOPPY_IRQ);
+}
+
+static inline void fd_disable_irq(void)
+{
+	disable_irq(FLOPPY_IRQ);
+}
+
+static inline int fd_request_irq(void)
+{
+	return request_irq(FLOPPY_IRQ, floppy_interrupt,
+	                   SA_INTERRUPT | SA_SAMPLE_RANDOM, "floppy", NULL);
+}
+
+static inline void fd_free_irq(void)
+{
+	free_irq(FLOPPY_IRQ, NULL);
+}
+
+#define fd_free_irq()           free_irq(FLOPPY_IRQ, NULL);
+
+
+static inline unsigned long fd_getfdaddr1(void)
+{
+	return 0x3f0;
+}
+
+static inline unsigned long fd_dma_mem_alloc(unsigned long size)
+{
+	unsigned long mem;
+
+	mem = __get_dma_pages(GFP_KERNEL, get_order(size));
+
+	return mem;
+}
+
+static inline void fd_dma_mem_free(unsigned long addr, unsigned long size)
+{
+	free_pages(addr, get_order(size));
+}
+
+static inline unsigned long fd_drive_type(unsigned long n)
+{
+	if (n == 0)
+		return 4;	/* 3,5", 1.44mb */
+
+	return 0;
+}
+
+#endif /* __ASM_MACH_GENERIC_FLOPPY_H */
--- diff/include/asm-mips/mach-generic/ide.h	1970-01-01 01:00:00.000000000 +0100
+++ source/include/asm-mips/mach-generic/ide.h	2004-02-23 13:56:47.000000000 +0000
@@ -0,0 +1,86 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * IDE routines for typical pc-like legacy IDE configurations.
+ *
+ * Copyright (C) 1998, 1999, 2001, 2003 by Ralf Baechle
+ */
+#ifndef __ASM_MACH_GENERIC_IDE_H
+#define __ASM_MACH_GENERIC_IDE_H
+
+#include <linux/config.h>
+
+#ifndef MAX_HWIFS
+# ifdef CONFIG_BLK_DEV_IDEPCI
+#define MAX_HWIFS	10
+# else
+#define MAX_HWIFS	6
+# endif
+#endif
+
+static inline int ide_default_irq(unsigned long base)
+{
+	switch (base) {
+		case 0x1f0: return 14;
+		case 0x170: return 15;
+		case 0x1e8: return 11;
+		case 0x168: return 10;
+		case 0x1e0: return 8;
+		case 0x160: return 12;
+		default:
+			return 0;
+	}
+}
+
+static inline ide_ioreg_t ide_default_io_base(int index)
+{
+	switch (index) {
+		case 0: return 0x1f0;
+		case 1: return 0x170;
+		case 2: return 0x1e8;
+		case 3: return 0x168;
+		case 4: return 0x1e0;
+		case 5: return 0x160;
+		default:
+			return 0;
+	}
+}
+
+static inline void ide_init_hwif_ports(hw_regs_t *hw, unsigned long data_port,
+	 unsigned long ctrl_port, int *irq)
+{
+	unsigned long reg = data_port;
+	int i;
+
+	for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++) {
+		hw->io_ports[i] = reg;
+		reg += 1;
+	}
+	if (ctrl_port) {
+		hw->io_ports[IDE_CONTROL_OFFSET] = ctrl_port;
+	} else {
+		hw->io_ports[IDE_CONTROL_OFFSET] = hw->io_ports[IDE_DATA_OFFSET] + 0x206;
+	}
+	if (irq != NULL)
+		*irq = 0;
+	hw->io_ports[IDE_IRQ_OFFSET] = 0;
+}
+
+static inline void ide_init_default_hwifs(void)
+{
+#ifndef CONFIG_BLK_DEV_IDEPCI
+	hw_regs_t hw;
+	int index;
+
+	for(index = 0; index < MAX_HWIFS; index++) {
+		memset(&hw, 0, sizeof hw);
+		ide_init_hwif_ports(&hw, ide_default_io_base(index), 0, NULL);
+		hw.irq = ide_default_irq(ide_default_io_base(index));
+		ide_register_hw(&hw, NULL);
+	}
+#endif /* CONFIG_BLK_DEV_IDEPCI */
+}
+
+#endif /* __ASM_MACH_GENERIC_IDE_H */
--- diff/include/asm-mips/mach-generic/irq.h	1970-01-01 01:00:00.000000000 +0100
+++ source/include/asm-mips/mach-generic/irq.h	2004-02-23 13:56:47.000000000 +0000
@@ -0,0 +1,13 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2003 by Ralf Baechle
+ */
+#ifndef __ASM_MACH_GENERIC_IRQ_H
+#define __ASM_MACH_GENERIC_IRQ_H
+
+#define NR_IRQS	128
+
+#endif /* __ASM_MACH_GENERIC_IRQ_H */
--- diff/include/asm-mips/mach-generic/mangle-port.h	1970-01-01 01:00:00.000000000 +0100
+++ source/include/asm-mips/mach-generic/mangle-port.h	2004-02-23 13:56:47.000000000 +0000
@@ -0,0 +1,15 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2003 Ralf Baechle
+ */
+#ifndef __ASM_MACH_GENERIC_MANGLE_PORT_H
+#define __ASM_MACH_GENERIC_MANGLE_PORT_H
+
+#define __swizzle_addr_b(port)	(port)
+#define __swizzle_addr_w(port)	(port)
+#define __swizzle_addr_l(port)	(port)
+
+#endif /* __ASM_MACH_GENERIC_MANGLE_PORT_H */
--- diff/include/asm-mips/mach-generic/mc146818rtc.h	1970-01-01 01:00:00.000000000 +0100
+++ source/include/asm-mips/mach-generic/mc146818rtc.h	2004-02-23 13:56:47.000000000 +0000
@@ -0,0 +1,36 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 1998, 2001, 03 by Ralf Baechle
+ *
+ * RTC routines for PC style attached Dallas chip.
+ */
+#ifndef __ASM_MACH_GENERIC_MC146818RTC_H
+#define __ASM_MACH_GENERIC_MC146818RTC_H
+
+#include <asm/io.h>
+
+#define RTC_PORT(x)	(0x70 + (x))
+#define RTC_IRQ		8
+
+static inline unsigned char CMOS_READ(unsigned long addr)
+{
+	outb_p(addr, RTC_PORT(0));
+	return inb_p(RTC_PORT(1));
+}
+
+static inline void CMOS_WRITE(unsigned char data, unsigned long addr)
+{
+	outb_p(addr, RTC_PORT(0));
+	outb_p(data, RTC_PORT(1));
+}
+
+#define RTC_ALWAYS_BCD	1
+
+#ifndef mc146818_decode_year
+#define mc146818_decode_year(year) ((year) < 70 ? (year) + 2000 : (year) + 1970)
+#endif
+
+#endif /* __ASM_MACH_GENERIC_MC146818RTC_H */
--- diff/include/asm-mips/mach-generic/param.h	1970-01-01 01:00:00.000000000 +0100
+++ source/include/asm-mips/mach-generic/param.h	2004-02-23 13:56:47.000000000 +0000
@@ -0,0 +1,13 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2003 by Ralf Baechle
+ */
+#ifndef __ASM_MACH_GENERIC_PARAM_H
+#define __ASM_MACH_GENERIC_PARAM_H
+
+#define HZ		1000		/* Internal kernel timer frequency */
+
+#endif /* __ASM_MACH_GENERIC_PARAM_H */
--- diff/include/asm-mips/mach-generic/spaces.h	1970-01-01 01:00:00.000000000 +0100
+++ source/include/asm-mips/mach-generic/spaces.h	2004-02-23 13:56:47.000000000 +0000
@@ -0,0 +1,41 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 1996, 99 Ralf Baechle
+ * Copyright (C) 2000, 2002  Maciej W. Rozycki
+ * Copyright (C) 1990, 1999 by Silicon Graphics, Inc.
+ */
+#ifndef _ASM_MACH_SPACES_H
+#define _ASM_MACH_SPACES_H
+
+#include <linux/config.h>
+
+#ifdef CONFIG_MIPS32
+
+#define CAC_BASE		0x80000000
+#define IO_BASE			0xa0000000
+#define UNCAC_BASE		0xa0000000
+#define MAP_BASE		0xc0000000
+
+#endif /* CONFIG_MIPS32 */
+
+#ifdef CONFIG_MIPS64
+
+#ifdef CONFIG_DMA_NONCOHERENT
+#define CAC_BASE		0x9800000000000000
+#else
+#define CAC_BASE		0xa800000000000000
+#endif
+#define IO_BASE			0x9000000000000000
+#define UNCAC_BASE		0x9000000000000000
+#define MAP_BASE		0xc000000000000000
+
+#define TO_PHYS(x)		(             ((x) & TO_PHYS_MASK))
+#define TO_CAC(x)		(CAC_BASE   | ((x) & TO_PHYS_MASK))
+#define TO_UNCAC(x)		(UNCAC_BASE | ((x) & TO_PHYS_MASK))
+
+#endif /* CONFIG_MIPS64 */
+
+#endif /* _ASM_MACH_SPACES_H */
--- diff/include/asm-mips/mach-generic/timex.h	1970-01-01 01:00:00.000000000 +0100
+++ source/include/asm-mips/mach-generic/timex.h	2004-02-23 13:56:47.000000000 +0000
@@ -0,0 +1,22 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2003 by Ralf Baechle
+ */
+#ifndef __ASM_MACH_GENERIC_TIMEX_H
+#define __ASM_MACH_GENERIC_TIMEX_H
+
+#include <linux/config.h>
+
+/*
+ * Last remaining user of the i8254 PIC, will be converted, too ...
+ */
+#ifdef CONFIG_SNI_RM200_PCI
+#define CLOCK_TICK_RATE		1193182
+#else
+#define CLOCK_TICK_RATE		500000
+#endif
+
+#endif /* __ASM_MACH_GENERIC_TIMEX_H */
--- diff/include/asm-mips/mach-ip22/cpu-feature-overrides.h	1970-01-01 01:00:00.000000000 +0100
+++ source/include/asm-mips/mach-ip22/cpu-feature-overrides.h	2004-02-23 13:56:47.000000000 +0000
@@ -0,0 +1,29 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2003 Ralf Baechle
+ */
+#ifndef __ASM_MACH_IP22_CPU_FEATURE_OVERRIDES_H
+#define __ASM_MACH_IP22_CPU_FEATURE_OVERRIDES_H
+
+/*
+ * IP22 with a variety of processors so we can't use defaults for everything.
+ */
+#define cpu_has_mips16		0
+#define cpu_has_divec		0
+#define cpu_has_cache_cdex_p	1
+#define cpu_has_prefetch	0
+#define cpu_has_mcheck		0
+#define cpu_has_ejtag		0
+
+#define cpu_has_llsc		1
+#define cpu_has_vtag_icache	0		/* Needs to change for R8000 */
+#define cpu_has_dc_aliases	(PAGE_SIZE < 0x4000)
+#define cpu_has_ic_fills_f_dc	0
+
+#define cpu_has_nofpuex		0
+#define cpu_has_64bits		1
+
+#endif /* __ASM_MACH_IP22_CPU_FEATURE_OVERRIDES_H */
--- diff/include/asm-mips/mach-ip22/ds1286.h	1970-01-01 01:00:00.000000000 +0100
+++ source/include/asm-mips/mach-ip22/ds1286.h	2004-02-23 13:56:47.000000000 +0000
@@ -0,0 +1,18 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 1998, 2001, 03 by Ralf Baechle
+ *
+ * RTC routines for PC style attached Dallas chip.
+ */
+#ifndef __ASM_MACH_IP22_DS1286_H
+#define __ASM_MACH_IP22_DS1286_H
+
+#include <asm/sgi/hpc3.h>
+
+#define rtc_read(reg)		(hpc3c0->rtcregs[(reg)] & 0xff)
+#define rtc_write(data, reg)	do { hpc3c0->rtcregs[(reg)] = (data); } while(0)
+
+#endif /* __ASM_MACH_IP22_DS1286_H */
--- diff/include/asm-mips/mach-ip27/cpu-feature-overrides.h	1970-01-01 01:00:00.000000000 +0100
+++ source/include/asm-mips/mach-ip27/cpu-feature-overrides.h	2004-02-23 13:56:47.000000000 +0000
@@ -0,0 +1,38 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2003 Ralf Baechle
+ */
+#ifndef __ASM_MACH_IP27_CPU_FEATURE_OVERRIDES_H
+#define __ASM_MACH_IP27_CPU_FEATURE_OVERRIDES_H
+
+/*
+ * IP27 only comes with R10000 family processors all using the same config
+ */
+#define cpu_has_watch		1
+#define cpu_has_mips16		0
+#define cpu_has_divec		0
+#define cpu_has_vce		0
+#define cpu_has_cache_cdex_p	0
+#define cpu_has_cache_cdex_s	0
+#define cpu_has_prefetch	1
+#define cpu_has_mcheck		0
+#define cpu_has_ejtag		0
+
+#define cpu_has_llsc		1
+#define cpu_has_vtag_icache	0
+#define cpu_has_dc_aliases	0
+#define cpu_has_ic_fills_f_dc	0
+
+#define cpu_has_nofpuex		0
+#define cpu_has_64bits		1
+
+#define cpu_has_subset_pcaches	1
+
+#define cpu_dcache_line_size()	32
+#define cpu_icache_line_size()	64
+#define cpu_scache_line_size()	128
+
+#endif /* __ASM_MACH_IP27_CPU_FEATURE_OVERRIDES_H */
--- diff/include/asm-mips/mach-ip27/irq.h	1970-01-01 01:00:00.000000000 +0100
+++ source/include/asm-mips/mach-ip27/irq.h	2004-02-23 13:56:47.000000000 +0000
@@ -0,0 +1,22 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 1999, 2000, 01, 02, 03 by Ralf Baechle
+ * Copyright (C) 1999, 2000 Silicon Graphics, Inc.
+ * Copyright (C) 2001 Kanoj Sarcar
+ */
+#ifndef __ASM_MACH_IP27_IRQ_H
+#define __ASM_MACH_IP27_IRQ_H
+
+#include <asm/sn/arch.h>
+
+/*
+ * A hardwired interrupt number is completly stupid for this system - a
+ * large configuration might have thousands if not tenthousands of
+ * interrupts.
+ */
+#define NR_IRQS 256
+
+#endif /* __ASM_MACH_IP27_IRQ_H */
--- diff/include/asm-mips/mach-ip27/mangle-port.h	1970-01-01 01:00:00.000000000 +0100
+++ source/include/asm-mips/mach-ip27/mangle-port.h	2004-02-23 13:56:47.000000000 +0000
@@ -0,0 +1,15 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2003 Ralf Baechle
+ */
+#ifndef __ASM_MACH_IP27_MANGLE_PORT_H
+#define __ASM_MACH_IP27_MANGLE_PORT_H
+
+#define __swizzle_addr_b(port)	(port)
+#define __swizzle_addr_w(port)	((port) ^ 2)
+#define __swizzle_addr_l(port)	(port)
+
+#endif /* __ASM_MACH_IP27_MANGLE_PORT_H */
--- diff/include/asm-mips/mach-ip27/mmzone.h	1970-01-01 01:00:00.000000000 +0100
+++ source/include/asm-mips/mach-ip27/mmzone.h	2004-02-23 13:56:47.000000000 +0000
@@ -0,0 +1,8 @@
+#ifndef _ASM_MACH_MMZONE_H
+#define _ASM_MACH_MMZONE_H
+
+#include <asm/sn/addrs.h>
+
+#define pa_to_nid(addr)		NASID_TO_COMPACT_NODEID(NASID_GET(addr))
+
+#endif /* _ASM_MACH_MMZONE_H */
--- diff/include/asm-mips/mach-ip27/spaces.h	1970-01-01 01:00:00.000000000 +0100
+++ source/include/asm-mips/mach-ip27/spaces.h	2004-02-23 13:56:47.000000000 +0000
@@ -0,0 +1,30 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 1996, 99 Ralf Baechle
+ * Copyright (C) 2000, 2002  Maciej W. Rozycki
+ * Copyright (C) 1990, 1999 by Silicon Graphics, Inc.
+ */
+#ifndef _ASM_MACH_SPACES_H
+#define _ASM_MACH_SPACES_H
+
+/*
+ * IP27 uses the R10000's uncached attribute feature.  Attribute 3 selects
+ * uncached memory addressing.
+ */
+#define CAC_BASE		0xa800000000000000
+
+#define HSPEC_BASE		0x9000000000000000
+#define IO_BASE			0x9200000000000000
+#define MSPEC_BASE		0x9400000000000000
+#define UNCAC_BASE		0x9600000000000000
+
+#define TO_PHYS(x)		(             ((x) & TO_PHYS_MASK))
+#define TO_CAC(x)		(CAC_BASE   | ((x) & TO_PHYS_MASK))
+#define TO_UNCAC(x)		(UNCAC_BASE | ((x) & TO_PHYS_MASK))
+#define TO_MSPEC(x)		(MSPEC_BASE | ((x) & TO_PHYS_MASK))
+#define TO_HSPEC(x)		(HSPEC_BASE | ((x) & TO_PHYS_MASK))
+
+#endif /* _ASM_MACH_SPACES_H */
--- diff/include/asm-mips/mach-ip32/mangle-port.h	1970-01-01 01:00:00.000000000 +0100
+++ source/include/asm-mips/mach-ip32/mangle-port.h	2004-02-23 13:56:47.000000000 +0000
@@ -0,0 +1,15 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2003 Ladislav Michl
+ */
+#ifndef __ASM_MACH_IP32_MANGLE_PORT_H
+#define __ASM_MACH_IP32_MANGLE_PORT_H
+
+#define __swizzle_addr_b(port)	((port) ^ 3)
+#define __swizzle_addr_w(port)	((port) ^ 2)
+#define __swizzle_addr_l(port)	(port)
+
+#endif /* __ASM_MACH_IP32_MANGLE_PORT_H */
--- diff/include/asm-mips/mach-ip32/mc146818rtc.h	1970-01-01 01:00:00.000000000 +0100
+++ source/include/asm-mips/mach-ip32/mc146818rtc.h	2004-02-23 13:56:47.000000000 +0000
@@ -0,0 +1,32 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 1998, 2001, 03 by Ralf Baechle
+ * Copyright (C) 2000 Harald Koerfgen
+ *
+ * RTC routines for IP32 style attached Dallas chip.
+ */
+#ifndef __ASM_MACH_IP32_MC146818RTC_H
+#define __ASM_MACH_IP32_MC146818RTC_H
+
+#include <asm/io.h>
+#include <asm/ip32/mace.h>
+
+#define RTC_PORT(x)	(0x70 + (x))
+#define RTC_IRQ		MACEISA_RTC_IRQ
+
+static unsigned char CMOS_READ(unsigned long addr)
+{
+	return readb(mace->isa.rtc + addr);
+}
+
+static inline void CMOS_WRITE(unsigned char data, unsigned long addr)
+{
+	writeb(data, mace->isa.rtc + addr);
+}
+
+#define RTC_ALWAYS_BCD	0
+
+#endif /* __ASM_MACH_IP32_MC146818RTC_H */
--- diff/include/asm-mips/mach-jazz/floppy.h	1970-01-01 01:00:00.000000000 +0100
+++ source/include/asm-mips/mach-jazz/floppy.h	2004-02-23 13:56:47.000000000 +0000
@@ -0,0 +1,135 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 1998, 2003 by Ralf Baechle
+ */
+#ifndef __ASM_MACH_JAZZ_FLOPPY_H
+#define __ASM_MACH_JAZZ_FLOPPY_H
+
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/linkage.h>
+#include <linux/types.h>
+#include <linux/mm.h>
+#include <asm/addrspace.h>
+#include <asm/jazz.h>
+#include <asm/jazzdma.h>
+#include <asm/pgtable.h>
+
+static inline unsigned char fd_inb(unsigned int port)
+{
+	unsigned char c;
+
+	c = *(volatile unsigned char *) port;
+	udelay(1);
+
+	return c;
+}
+
+static inline void fd_outb(unsigned char value, unsigned int port)
+{
+	*(volatile unsigned char *) port = value;
+}
+
+/*
+ * How to access the floppy DMA functions.
+ */
+static inline void fd_enable_dma(void)
+{
+	vdma_enable(JAZZ_FLOPPY_DMA);
+}
+
+static inline void fd_disable_dma(void)
+{
+	vdma_disable(JAZZ_FLOPPY_DMA);
+}
+
+static inline int fd_request_dma(void)
+{
+	return 0;
+}
+
+static inline void fd_free_dma(void)
+{
+}
+
+static inline void fd_clear_dma_ff(void)
+{
+}
+
+static inline void fd_set_dma_mode(char mode)
+{
+	vdma_set_mode(JAZZ_FLOPPY_DMA, mode);
+}
+
+static inline void fd_set_dma_addr(char *a)
+{
+	vdma_set_addr(JAZZ_FLOPPY_DMA, vdma_phys2log(CPHYSADDR((unsigned long)a)));
+}
+
+static inline void fd_set_dma_count(unsigned int count)
+{
+	vdma_set_count(JAZZ_FLOPPY_DMA, count);
+}
+
+static inline int fd_get_dma_residue(void)
+{
+	return vdma_get_residue(JAZZ_FLOPPY_DMA);
+}
+
+static inline void fd_enable_irq(void)
+{
+}
+
+static inline void fd_disable_irq(void)
+{
+}
+
+static inline int fd_request_irq(void)
+{
+	return request_irq(FLOPPY_IRQ, floppy_interrupt,
+	                   SA_INTERRUPT | SA_SAMPLE_RANDOM, "floppy", NULL);
+}
+                                                                                
+static inline void fd_free_irq(void)
+{
+	free_irq(FLOPPY_IRQ, NULL);
+}
+
+static inline unsigned long fd_getfdaddr1(void)
+{
+	return JAZZ_FDC_BASE;
+}
+
+static inline unsigned long fd_dma_mem_alloc(unsigned long size)
+{
+	unsigned long mem;
+
+	mem = __get_dma_pages(GFP_KERNEL, get_order(size));
+	if(!mem)
+		return 0;
+	vdma_alloc(CPHYSADDR(mem), size);	/* XXX error checking */
+
+	return mem;
+}
+
+static inline void fd_dma_mem_free(unsigned long addr, unsigned long size)
+{
+	vdma_free(vdma_phys2log(CPHYSADDR(addr)));
+	free_pages(addr, get_order(size));
+}
+
+static inline unsigned long fd_drive_type(unsigned long n)
+{
+	/* XXX This is wrong for machines with ED 2.88mb disk drives like the
+	   Olivetti M700.  Anyway, we should suck this from the ARC
+	   firmware.  */
+	if (n == 0)
+		return 4;	/* 3,5", 1.44mb */
+
+	return 0;
+}
+
+#endif /* __ASM_MACH_JAZZ_FLOPPY_H */
--- diff/include/asm-mips/mach-jazz/mc146818rtc.h	1970-01-01 01:00:00.000000000 +0100
+++ source/include/asm-mips/mach-jazz/mc146818rtc.h	2004-02-23 13:56:47.000000000 +0000
@@ -0,0 +1,34 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 1998, 2001, 03 by Ralf Baechle
+ *
+ * RTC routines for Jazz style attached Dallas chip.
+ */
+#ifndef __ASM_MACH_JAZZ_MC146818RTC_H
+#define __ASM_MACH_JAZZ_MC146818RTC_H
+
+#include <asm/io.h>
+#include <asm/jazz.h>
+
+#define RTC_PORT(x)	(0x70 + (x))
+#define RTC_IRQ		8
+
+static inline unsigned char CMOS_READ(unsigned long addr)
+{
+	outb_p(addr, RTC_PORT(0));
+
+	return *(char *)JAZZ_RTC_BASE;
+}
+
+static inline void CMOS_WRITE(unsigned char data, unsigned long addr)
+{
+	outb_p(addr, RTC_PORT(0));
+	*(char *)JAZZ_RTC_BASE = data;
+}
+
+#define RTC_ALWAYS_BCD	0
+
+#endif /* __ASM_MACH_JAZZ_MC146818RTC_H */
--- diff/include/asm-mips/mach-jazz/param.h	1970-01-01 01:00:00.000000000 +0100
+++ source/include/asm-mips/mach-jazz/param.h	2004-02-23 13:56:47.000000000 +0000
@@ -0,0 +1,16 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2003 by Ralf Baechle
+ */
+#ifndef __ASM_MACH_JAZZ_PARAM_H
+#define __ASM_MACH_JAZZ_PARAM_H
+
+/*
+ * Jazz is currently using the internal 100Hz timer of the R4030
+ */
+#define HZ		100		/* Internal kernel timer frequency */
+
+#endif /* __ASM_MACH_JAZZ_PARAM_H */
--- diff/include/asm-mips/mach-jazz/timex.h	1970-01-01 01:00:00.000000000 +0100
+++ source/include/asm-mips/mach-jazz/timex.h	2004-02-23 13:56:47.000000000 +0000
@@ -0,0 +1,16 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2003 by Ralf Baechle
+ */
+#ifndef __ASM_MACH_JAZZ_TIMEX_H
+#define __ASM_MACH_JAZZ_TIMEX_H
+
+/*
+ * Jazz is still using the R4030 100Hz counter
+ */
+#define CLOCK_TICK_RATE		100
+
+#endif /* __ASM_MACH_JAZZ_TIMEX_H */
--- diff/include/asm-mips/mach-jmr3927/asm/ds1742.h	1970-01-01 01:00:00.000000000 +0100
+++ source/include/asm-mips/mach-jmr3927/asm/ds1742.h	2004-02-23 13:56:47.000000000 +0000
@@ -0,0 +1,16 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2003 by Ralf Baechle
+ */
+#ifndef __ASM_MACH_JMR3927_ASM_DS1742_H
+#define __ASM_MACH_JMR3927_ASM_DS1742_H
+
+#include <asm/jmr3927/jmr3927.h>
+
+#define rtc_read(reg)		(jmr3927_nvram_in(addr))
+#define rtc_write(data, reg)	(jmr3927_nvram_out((data),(reg)))
+
+#endif /* __ASM_MACH_JMR3927_ASM_DS1742_H */
--- diff/include/asm-mips/mach-lasat/mach-gt64120.h	1970-01-01 01:00:00.000000000 +0100
+++ source/include/asm-mips/mach-lasat/mach-gt64120.h	2004-02-23 13:56:47.000000000 +0000
@@ -0,0 +1,27 @@
+/*
+ *  This is a direct copy of the ev96100.h file, with a global
+ * search and replace.  The numbers are the same.
+ *
+ *  The reason I'm duplicating this is so that the 64120/96100
+ * defines won't be confusing in the source code.
+ */
+#ifndef _ASM_GT64120_LASAT_GT64120_DEP_H
+#define _ASM_GT64120_LASAT_GT64120_DEP_H
+
+/*
+ *   GT64120 config space base address on Lasat 100
+ */
+#define GT64120_BASE	(KSEG1ADDR(0x14000000))
+
+/*
+ *   PCI Bus allocation
+ *
+ *   (Guessing ...)
+ */
+#define GT_PCI_MEM_BASE    0x12000000UL
+#define GT_PCI_MEM_SIZE    0x02000000UL
+#define GT_PCI_IO_BASE     0x10000000UL
+#define GT_PCI_IO_SIZE     0x02000000UL
+#define GT_ISA_IO_BASE     PCI_IO_BASE
+
+#endif /* _ASM_GT64120_LASAT_GT64120_DEP_H */
--- diff/include/asm-mips/mach-mips/mach-gt64120.h	1970-01-01 01:00:00.000000000 +0100
+++ source/include/asm-mips/mach-mips/mach-gt64120.h	2004-02-23 13:56:47.000000000 +0000
@@ -0,0 +1,28 @@
+/*
+ *  This is a direct copy of the ev96100.h file, with a global
+ * search and replace.  The numbers are the same.
+ *
+ *  The reason I'm duplicating this is so that the 64120/96100
+ * defines won't be confusing in the source code.
+ */
+#ifndef _ASM_MACH_MIPS_MACH_GT64120_DEP_H
+#define _ASM_MACH_MIPS_MACH_GT64120_DEP_H
+
+#define MIPS_GT_BASE    0x1be00000
+
+extern unsigned long _pcictrl_gt64120;
+/*
+ *   GT64120 config space base address
+ */
+#define GT64120_BASE	_pcictrl_gt64120
+
+/*
+ *   PCI Bus allocation
+ */
+#define GT_PCI_MEM_BASE    0x12000000UL
+#define GT_PCI_MEM_SIZE    0x02000000UL
+#define GT_PCI_IO_BASE     0x10000000UL
+#define GT_PCI_IO_SIZE     0x02000000UL
+#define GT_ISA_IO_BASE     PCI_IO_BASE
+
+#endif /* _ASM_MACH_MIPS_MACH_GT64120_DEP_H */
--- diff/include/asm-mips/mach-mips/mc146818rtc.h	1970-01-01 01:00:00.000000000 +0100
+++ source/include/asm-mips/mach-mips/mc146818rtc.h	2004-02-23 13:56:47.000000000 +0000
@@ -0,0 +1,46 @@
+/*
+ * Carsten Langgaard, carstenl@mips.com
+ * Copyright (C) 1999,2000 MIPS Technologies, Inc.  All rights reserved.
+ * Copyright (C) 2003 by Ralf Baechle
+ *
+ * This program is free software; you can distribute it and/or modify it
+ * under the terms of the GNU General Public License (Version 2) as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * RTC routines for Malta style attached PIIX4 device, which contains a
+ * Motorola MC146818A-compatible Real Time Clock.
+ */
+#ifndef __ASM_MACH_MALTA_MC146818RTC_H
+#define __ASM_MACH_MALTA_MC146818RTC_H
+
+#include <asm/io.h>
+#include <asm/mips-boards/generic.h>
+#include <asm/mips-boards/malta.h>
+
+#define RTC_PORT(x)	(0x70 + (x))
+#define RTC_IRQ		8
+
+static inline unsigned char CMOS_READ(unsigned long addr)
+{
+	outb(addr, MALTA_RTC_ADR_REG);
+	return inb(MALTA_RTC_DAT_REG);
+}
+
+static inline void CMOS_WRITE(unsigned char data, unsigned long addr)
+{
+	outb(addr, MALTA_RTC_ADR_REG);
+	outb(data, MALTA_RTC_DAT_REG);
+}
+
+#define RTC_ALWAYS_BCD	0
+
+#endif /* __ASM_MACH_MALTA_MC146818RTC_H */
--- diff/include/asm-mips/mach-ocelot/mach-gt64120.h	1970-01-01 01:00:00.000000000 +0100
+++ source/include/asm-mips/mach-ocelot/mach-gt64120.h	2004-02-23 13:56:47.000000000 +0000
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2001 MontaVista Software Inc.
+ * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+#ifndef _ASM_GT64120_MOMENCO_OCELOT_GT64120_DEP_H
+#define _ASM_GT64120_MOMENCO_OCELOT_GT64120_DEP_H
+
+/*
+ * PCI address allocation
+ */
+#define GT_PCI_MEM_BASE    (0x22000000UL)
+#define GT_PCI_MEM_SIZE    GT_DEF_PCI0_MEM0_SIZE
+#define GT_PCI_IO_BASE     (0x20000000UL)
+#define GT_PCI_IO_SIZE     GT_DEF_PCI0_IO_SIZE
+
+extern unsigned long gt64120_base;
+
+#define GT64120_BASE       (gt64120_base)
+
+/*
+ * GT timer irq
+ */
+#define	GT_TIMER		6
+
+#endif  /* _ASM_GT64120_MOMENCO_OCELOT_GT64120_DEP_H */
--- diff/include/asm-mips/mach-pb1x00/mc146818rtc.h	1970-01-01 01:00:00.000000000 +0100
+++ source/include/asm-mips/mach-pb1x00/mc146818rtc.h	2004-02-23 13:56:47.000000000 +0000
@@ -0,0 +1,34 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 1998, 2001, 03 by Ralf Baechle
+ *
+ * RTC routines for PC style attached Dallas chip.
+ */
+#ifndef __ASM_MACH_AU1XX_MC146818RTC_H
+#define __ASM_MACH_AU1XX_MC146818RTC_H
+
+#include <asm/io.h>
+#include <asm/mach-au1x00/au1000.h>
+
+#define RTC_PORT(x)	(0x0c000000 + (x))
+#define RTC_IRQ		8
+#define PB1500_RTC_ADDR 0x0c000000
+
+static inline unsigned char CMOS_READ(unsigned long offset)
+{
+	offset <<= 2;
+	return (u8)(au_readl(offset + PB1500_RTC_ADDR) & 0xff);
+}
+
+static inline void CMOS_WRITE(unsigned char data, unsigned long offset)
+{
+	offset <<= 2;
+	au_writel(data, offset + PB1500_RTC_ADDR);
+}
+
+#define RTC_ALWAYS_BCD	1
+
+#endif /* __ASM_MACH_AU1XX_MC146818RTC_H */
--- diff/include/asm-mips/mach-pb1x00/pb1000.h	1970-01-01 01:00:00.000000000 +0100
+++ source/include/asm-mips/mach-pb1x00/pb1000.h	2004-02-23 13:56:47.000000000 +0000
@@ -0,0 +1,172 @@
+/*
+ * Alchemy Semi PB1000 Referrence Board
+ *
+ * Copyright 2001 MontaVista Software Inc.
+ * Author: MontaVista Software, Inc.
+ *         	ppopov@mvista.com or source@mvista.com
+ *
+ * ########################################################################
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ *
+ *
+ */
+#ifndef __ASM_PB1000_H
+#define __ASM_PB1000_H
+
+/* PCMCIA PB1000 specific defines */
+#define PCMCIA_MAX_SOCK 1
+#define PCMCIA_NUM_SOCKS (PCMCIA_MAX_SOCK+1)
+
+#define PB1000_PCR     0xBE000000
+  #define PCR_SLOT_0_VPP0  (1<<0)
+  #define PCR_SLOT_0_VPP1  (1<<1)
+  #define PCR_SLOT_0_VCC0  (1<<2)
+  #define PCR_SLOT_0_VCC1  (1<<3)
+  #define PCR_SLOT_0_RST   (1<<4)
+
+  #define PCR_SLOT_1_VPP0  (1<<8)
+  #define PCR_SLOT_1_VPP1  (1<<9)
+  #define PCR_SLOT_1_VCC0  (1<<10)
+  #define PCR_SLOT_1_VCC1  (1<<11)
+  #define PCR_SLOT_1_RST   (1<<12)
+
+#define PB1000_MDR     0xBE000004
+  #define MDR_PI        (1<<5)  /* pcmcia int latch  */
+  #define MDR_EPI      (1<<14)  /* enable pcmcia int */
+  #define MDR_CPI      (1<<15)  /* clear pcmcia int  */
+
+#define PB1000_ACR1    0xBE000008
+  #define ACR1_SLOT_0_CD1    (1<<0)  /* card detect 1     */
+  #define ACR1_SLOT_0_CD2    (1<<1)  /* card detect 2     */
+  #define ACR1_SLOT_0_READY  (1<<2)  /* ready             */
+  #define ACR1_SLOT_0_STATUS (1<<3)  /* status change     */
+  #define ACR1_SLOT_0_VS1    (1<<4)  /* voltage sense 1   */
+  #define ACR1_SLOT_0_VS2    (1<<5)  /* voltage sense 2   */
+  #define ACR1_SLOT_0_INPACK (1<<6)  /* inpack pin status */
+  #define ACR1_SLOT_1_CD1    (1<<8)  /* card detect 1     */
+  #define ACR1_SLOT_1_CD2    (1<<9)  /* card detect 2     */
+  #define ACR1_SLOT_1_READY  (1<<10) /* ready             */
+  #define ACR1_SLOT_1_STATUS (1<<11) /* status change     */
+  #define ACR1_SLOT_1_VS1    (1<<12) /* voltage sense 1   */
+  #define ACR1_SLOT_1_VS2    (1<<13) /* voltage sense 2   */
+  #define ACR1_SLOT_1_INPACK (1<<14) /* inpack pin status */
+
+#define CPLD_AUX0      0xBE00000C
+#define CPLD_AUX1      0xBE000010
+#define CPLD_AUX2      0xBE000014
+
+/* Voltage levels */
+
+/* VPPEN1 - VPPEN0 */
+#define VPP_GND ((0<<1) | (0<<0))
+#define VPP_5V  ((1<<1) | (0<<0))
+#define VPP_3V  ((0<<1) | (1<<0))
+#define VPP_12V ((0<<1) | (1<<0))
+#define VPP_HIZ ((1<<1) | (1<<0))
+
+/* VCCEN1 - VCCEN0 */
+#define VCC_3V  ((0<<1) | (1<<0))
+#define VCC_5V  ((1<<1) | (0<<0))
+#define VCC_HIZ ((0<<1) | (0<<0))
+
+/* VPP/VCC */
+#define SET_VCC_VPP(VCC, VPP, SLOT)\
+	((((VCC)<<2) | ((VPP)<<0)) << ((SLOT)*8))
+
+
+/* PCI PB1000 specific defines */
+/* The reason these defines are here instead of au1000.h is because
+ * the Au1000 does not have a PCI bus controller so the PCI implementation
+ * on the some of the older Pb1000 boards was very board specific.
+ */
+#define PCI_CONFIG_BASE   0xBA020000 /* the only external slot */
+
+#define SDRAM_DEVID       0xBA010000
+#define SDRAM_CMD         0xBA010004
+#define SDRAM_CLASS       0xBA010008
+#define SDRAM_MISC        0xBA01000C
+#define SDRAM_MBAR        0xBA010010
+
+#define PCI_IO_DATA_PORT  0xBA800000
+
+#define PCI_IO_ADDR       0xBE00001C
+#define PCI_INT_ACK       0xBBC00000
+#define PCI_IO_READ       0xBBC00020
+#define PCI_IO_WRITE      0xBBC00030
+
+#define PCI_BRIDGE_CONFIG 0xBE000018
+
+#define PCI_IO_START      0x10000000
+#define PCI_IO_END        0x1000ffff
+#define PCI_MEM_START     0x18000000
+#define PCI_MEM_END       0x18ffffff
+
+#define PCI_FIRST_DEVFN   0
+#define PCI_LAST_DEVFN    1
+
+static inline u8 au_pci_io_readb(u32 addr)
+{
+	writel(addr, PCI_IO_ADDR);
+	writel((readl(PCI_BRIDGE_CONFIG) & 0xffffcfff) | (1<<12), PCI_BRIDGE_CONFIG);
+	return (readl(PCI_IO_DATA_PORT) & 0xff);
+}
+
+static inline u16 au_pci_io_readw(u32 addr)
+{
+	writel(addr, PCI_IO_ADDR);
+	writel((readl(PCI_BRIDGE_CONFIG) & 0xffffcfff) | (1<<13), PCI_BRIDGE_CONFIG);
+	return (readl(PCI_IO_DATA_PORT) & 0xffff);
+}
+
+static inline u32 au_pci_io_readl(u32 addr)
+{
+	writel(addr, PCI_IO_ADDR);
+	writel((readl(PCI_BRIDGE_CONFIG) & 0xffffcfff), PCI_BRIDGE_CONFIG);
+	return readl(PCI_IO_DATA_PORT);
+}
+
+static inline void au_pci_io_writeb(u8 val, u32 addr)
+{
+	writel(addr, PCI_IO_ADDR);
+	writel((readl(PCI_BRIDGE_CONFIG) & 0xffffcfff) | (1<<12), PCI_BRIDGE_CONFIG);
+	writel(val, PCI_IO_DATA_PORT);
+}
+
+static inline void au_pci_io_writew(u16 val, u32 addr)
+{
+	writel(addr, PCI_IO_ADDR);
+	writel((readl(PCI_BRIDGE_CONFIG) & 0xffffcfff) | (1<<13), PCI_BRIDGE_CONFIG);
+	writel(val, PCI_IO_DATA_PORT);
+}
+
+static inline void au_pci_io_writel(u32 val, u32 addr)
+{
+	writel(addr, PCI_IO_ADDR);
+	writel(readl(PCI_BRIDGE_CONFIG) & 0xffffcfff, PCI_BRIDGE_CONFIG);
+	writel(val, PCI_IO_DATA_PORT);
+}
+
+static inline void set_sdram_extbyte(void)
+{
+	writel(readl(PCI_BRIDGE_CONFIG) & 0xffffff00, PCI_BRIDGE_CONFIG);
+}
+
+static inline void set_slot_extbyte(void)
+{
+	writel((readl(PCI_BRIDGE_CONFIG) & 0xffffbf00) | 0x18, PCI_BRIDGE_CONFIG);
+}
+#endif /* __ASM_PB1000_H */
--- diff/include/asm-mips/mach-pb1x00/pb1100.h	1970-01-01 01:00:00.000000000 +0100
+++ source/include/asm-mips/mach-pb1x00/pb1100.h	2004-02-23 13:56:47.000000000 +0000
@@ -0,0 +1,85 @@
+/*
+ * Alchemy Semi PB1100 Referrence Board
+ *
+ * Copyright 2001 MontaVista Software Inc.
+ * Author: MontaVista Software, Inc.
+ *         	ppopov@mvista.com or source@mvista.com
+ *
+ * ########################################################################
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ *
+ *
+ */
+#ifndef __ASM_PB1100_H
+#define __ASM_PB1100_H
+
+#define PB1100_IDENT          0xAE000000
+#define BOARD_STATUS_REG      0xAE000004
+  #define PB1100_ROM_SEL         (1<<15)
+  #define PB1100_ROM_SIZ         (1<<14)
+  #define PB1100_SWAP_BOOT       (1<<13)
+  #define PB1100_FLASH_WP        (1<<12)
+  #define PB1100_ROM_H_STS       (1<<11)
+  #define PB1100_ROM_L_STS       (1<<10)
+  #define PB1100_FLASH_H_STS      (1<<9)
+  #define PB1100_FLASH_L_STS      (1<<8)
+  #define PB1100_SRAM_SIZ         (1<<7)
+  #define PB1100_TSC_BUSY         (1<<6)
+  #define PB1100_PCMCIA_VS_MASK   (3<<4)
+  #define PB1100_RS232_CD         (1<<3)
+  #define PB1100_RS232_CTS        (1<<2)
+  #define PB1100_RS232_DSR        (1<<1)
+  #define PB1100_RS232_RI         (1<<0)
+
+#define PB1100_IRDA_RS232     0xAE00000C
+  #define PB1100_IRDA_FULL       (0<<14) /* full power */
+  #define PB1100_IRDA_SHUTDOWN   (1<<14)
+  #define PB1100_IRDA_TT         (2<<14) /* 2/3 power */
+  #define PB1100_IRDA_OT         (3<<14) /* 1/3 power */
+  #define PB1100_IRDA_FIR        (1<<13)
+
+#define PCMCIA_BOARD_REG     0xAE000010
+  #define PB1100_SD_WP1_RO       (1<<15) /* read only */
+  #define PB1100_SD_WP0_RO       (1<<14) /* read only */
+  #define PB1100_SD_PWR1         (1<<11) /* applies power to SD1 */
+  #define PB1100_SD_PWR0         (1<<10) /* applies power to SD0 */
+  #define PB1100_SEL_SD_CONN1     (1<<9)
+  #define PB1100_SEL_SD_CONN0     (1<<8)
+  #define PC_DEASSERT_RST         (1<<7)
+  #define PC_DRV_EN               (1<<4)
+
+#define PB1100_G_CONTROL      0xAE000014 /* graphics control */
+
+#define PB1100_RST_VDDI       0xAE00001C
+  #define PB1100_SOFT_RESET      (1<<15) /* clear to reset the board */
+  #define PB1100_VDDI_MASK        (0x1F)
+
+#define PB1100_LEDS           0xAE000018
+
+/* 11:8 is 4 discreet LEDs. Clearing a bit illuminates the LED.
+ * 7:0 is the LED Display's decimal points.
+ */
+#define PB1100_HEX_LED        0xAE000018
+
+/* PCMCIA PB1100 specific defines */
+#define PCMCIA_MAX_SOCK 0
+#define PCMCIA_NUM_SOCKS (PCMCIA_MAX_SOCK+1)
+
+/* VPP/VCC */
+#define SET_VCC_VPP(VCC, VPP) (((VCC)<<2) | ((VPP)<<0))
+
+#endif /* __ASM_PB1100_H */
--- diff/include/asm-mips/mach-pb1x00/pb1500.h	1970-01-01 01:00:00.000000000 +0100
+++ source/include/asm-mips/mach-pb1x00/pb1500.h	2004-02-23 13:56:47.000000000 +0000
@@ -0,0 +1,51 @@
+/*
+ * Alchemy Semi PB1500 Referrence Board
+ *
+ * Copyright 2001 MontaVista Software Inc.
+ * Author: MontaVista Software, Inc.
+ *         	ppopov@mvista.com or source@mvista.com
+ *
+ * ########################################################################
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ *
+ *
+ */
+#ifndef __ASM_PB1500_H
+#define __ASM_PB1500_H
+
+
+#define IDENT_BOARD_REG           0xAE000000
+#define BOARD_STATUS_REG          0xAE000004
+#define PCI_BOARD_REG             0xAE000010
+#define PCMCIA_BOARD_REG          0xAE000010
+  #define PC_DEASSERT_RST               0x80
+  #define PC_DRV_EN                     0x10 
+#define PB1500_G_CONTROL          0xAE000014
+#define PB1500_RST_VDDI           0xAE00001C
+#define PB1500_LEDS               0xAE000018
+  
+#define PB1500_HEX_LED            0xAF000004
+#define PB1500_HEX_LED_BLANK      0xAF000008
+
+/* PCMCIA PB1500 specific defines */
+#define PCMCIA_MAX_SOCK 0
+#define PCMCIA_NUM_SOCKS (PCMCIA_MAX_SOCK+1)
+
+/* VPP/VCC */
+#define SET_VCC_VPP(VCC, VPP) (((VCC)<<2) | ((VPP)<<0))
+
+#endif /* __ASM_PB1500_H */
--- diff/include/asm-mips/mach-rm200/cpu-feature-overrides.h	1970-01-01 01:00:00.000000000 +0100
+++ source/include/asm-mips/mach-rm200/cpu-feature-overrides.h	2004-02-23 13:56:47.000000000 +0000
@@ -0,0 +1,42 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2003, 2004 Ralf Baechle
+ *
+ * SNI RM200 C apparently was only shipped with R4600 V2.0 and R5000 processors.
+ */
+#ifndef __ASM_MACH_RM200_CPU_FEATURE_OVERRIDES_H
+#define __ASM_MACH_RM200_CPU_FEATURE_OVERRIDES_H
+
+#include <cpu-feature-overrides.h>
+
+#define cpu_has_tlb		1
+#define cpu_has_4kex		1
+#define cpu_has_4ktlb		1
+#define cpu_has_fpu		1
+#define cpu_has_32fpr		1
+#define cpu_has_counter		1
+#define cpu_has_watch		0
+#define cpu_has_mips16		0
+#define cpu_has_divec		0
+#define cpu_has_vce		0
+#define cpu_has_cache_cdex_p	1
+#define cpu_has_cache_cdex_s	0
+#define cpu_has_prefetch	0
+#define cpu_has_mcheck		0
+#define cpu_has_ejtag		0
+#define cpu_has_llsc		1
+#define cpu_has_vtag_icache	0
+#define cpu_has_dc_aliases	(PAGE_SIZE < 0x4000)
+#define cpu_has_ic_fills_f_dc	0
+#define cpu_has_nofpuex		0
+#define cpu_has_64bits		1
+
+#define cpu_has_subset_pcaches	0	/* No S-cache on R5000 I think ...  */
+#define cpu_dcache_line_size()	32
+#define cpu_icache_line_size()	32
+#define cpu_scache_line_size()	0	/* No S-cache on R5000 I think ...  */
+
+#endif /* __ASM_MACH_RM200_CPU_FEATURE_OVERRIDES_H */
--- diff/include/asm-mips/mach-rm200/mc146818rtc.h	1970-01-01 01:00:00.000000000 +0100
+++ source/include/asm-mips/mach-rm200/mc146818rtc.h	2004-02-23 13:56:47.000000000 +0000
@@ -0,0 +1,17 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2004 by Ralf Baechle
+ *
+ * RTC routines for PC style attached Dallas chip with ARC epoch.
+ */
+#ifndef __ASM_MACH_RM200_MC146818RTC_H
+#define __ASM_MACH_RM200_MC146818RTC_H
+
+#define mc146818_decode_year(year) ((year) + 1980)
+
+#include_next <mc146818rtc.h>
+
+#endif /* __ASM_MACH_RM200_MC146818RTC_H */
--- diff/include/asm-mips/mach-vr41xx/timex.h	1970-01-01 01:00:00.000000000 +0100
+++ source/include/asm-mips/mach-vr41xx/timex.h	2004-02-23 13:56:47.000000000 +0000
@@ -0,0 +1,18 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2003 by Ralf Baechle
+ */
+/*
+ * Changes:
+ *  Yoichi Yuasa <yuasa@hh.iij4u.or.jp>
+ *  - CLOCK_TICK_RATE is changed into 32768 from 6144000.
+ */
+#ifndef __ASM_MACH_VR41XX_TIMEX_H
+#define __ASM_MACH_VR41XX_TIMEX_H
+
+#define CLOCK_TICK_RATE		32768
+
+#endif /* __ASM_MACH_VR41XX_TIMEX_H */
--- diff/include/asm-mips/mc146818-time.h	1970-01-01 01:00:00.000000000 +0100
+++ source/include/asm-mips/mc146818-time.h	2004-02-23 13:56:47.000000000 +0000
@@ -0,0 +1,129 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Machine dependent access functions for RTC registers.
+ */
+#ifndef __ASM_MC146818_TIME_H
+#define __ASM_MC146818_TIME_H
+
+#include <linux/bcd.h>
+#include <linux/mc146818rtc.h>
+#include <linux/time.h>
+
+/*
+ * For check timing call set_rtc_mmss() 500ms; used in timer interrupt.
+ */
+#define USEC_AFTER	500000
+#define USEC_BEFORE	500000
+
+/*
+ * In order to set the CMOS clock precisely, set_rtc_mmss has to be
+ * called 500 ms after the second nowtime has started, because when
+ * nowtime is written into the registers of the CMOS clock, it will
+ * jump to the next second precisely 500 ms later. Check the Motorola
+ * MC146818A or Dallas DS12887 data sheet for details.
+ *
+ * BUG: This routine does not handle hour overflow properly; it just
+ *      sets the minutes. Usually you'll only notice that after reboot!
+ */
+static inline int mc146818_set_rtc_mmss(unsigned long nowtime)
+{
+	int real_seconds, real_minutes, cmos_minutes;
+	unsigned char save_control, save_freq_select;
+	int retval = 0;
+
+	save_control = CMOS_READ(RTC_CONTROL); /* tell the clock it's being set */
+	CMOS_WRITE((save_control|RTC_SET), RTC_CONTROL);
+
+	save_freq_select = CMOS_READ(RTC_FREQ_SELECT); /* stop and reset prescaler */
+	CMOS_WRITE((save_freq_select|RTC_DIV_RESET2), RTC_FREQ_SELECT);
+
+	cmos_minutes = CMOS_READ(RTC_MINUTES);
+	if (!(save_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD)
+		BCD_TO_BIN(cmos_minutes);
+
+	/*
+	 * since we're only adjusting minutes and seconds,
+	 * don't interfere with hour overflow. This avoids
+	 * messing with unknown time zones but requires your
+	 * RTC not to be off by more than 15 minutes
+	 */
+	real_seconds = nowtime % 60;
+	real_minutes = nowtime / 60;
+	if (((abs(real_minutes - cmos_minutes) + 15)/30) & 1)
+		real_minutes += 30;		/* correct for half hour time zone */
+	real_minutes %= 60;
+
+	if (abs(real_minutes - cmos_minutes) < 30) {
+		if (!(save_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD) {
+			BIN_TO_BCD(real_seconds);
+			BIN_TO_BCD(real_minutes);
+		}
+		CMOS_WRITE(real_seconds,RTC_SECONDS);
+		CMOS_WRITE(real_minutes,RTC_MINUTES);
+	} else {
+		printk(KERN_WARNING
+		       "set_rtc_mmss: can't update from %d to %d\n",
+		       cmos_minutes, real_minutes);
+		retval = -1;
+	}
+
+	/* The following flags have to be released exactly in this order,
+	 * otherwise the DS12887 (popular MC146818A clone with integrated
+	 * battery and quartz) will not reset the oscillator and will not
+	 * update precisely 500 ms later. You won't find this mentioned in
+	 * the Dallas Semiconductor data sheets, but who believes data
+	 * sheets anyway ...                           -- Markus Kuhn
+	 */
+	CMOS_WRITE(save_control, RTC_CONTROL);
+	CMOS_WRITE(save_freq_select, RTC_FREQ_SELECT);
+
+	return retval;
+}
+
+static inline unsigned long mc146818_get_cmos_time(void)
+{
+	unsigned int year, mon, day, hour, min, sec;
+	int i;
+
+	/*
+	 * The Linux interpretation of the CMOS clock register contents:
+	 * When the Update-In-Progress (UIP) flag goes from 1 to 0, the
+	 * RTC registers show the second which has precisely just started.
+	 * Let's hope other operating systems interpret the RTC the same way.
+	 */
+
+	/* read RTC exactly on falling edge of update flag */
+	for (i = 0 ; i < 1000000 ; i++)	/* may take up to 1 second... */
+		if (CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP)
+			break;
+	for (i = 0 ; i < 1000000 ; i++)	/* must try at least 2.228 ms */
+		if (!(CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP))
+			break;
+
+	do { /* Isn't this overkill ? UIP above should guarantee consistency */
+		sec = CMOS_READ(RTC_SECONDS);
+		min = CMOS_READ(RTC_MINUTES);
+		hour = CMOS_READ(RTC_HOURS);
+		day = CMOS_READ(RTC_DAY_OF_MONTH);
+		mon = CMOS_READ(RTC_MONTH);
+		year = CMOS_READ(RTC_YEAR);
+	} while (sec != CMOS_READ(RTC_SECONDS));
+
+	if (!(CMOS_READ(RTC_CONTROL) & RTC_DM_BINARY) || RTC_ALWAYS_BCD) {
+		BCD_TO_BIN(sec);
+		BCD_TO_BIN(min);
+		BCD_TO_BIN(hour);
+		BCD_TO_BIN(day);
+		BCD_TO_BIN(mon);
+		BCD_TO_BIN(year);
+	}
+	if ((year += 1900) < 1970)
+		year += 100;
+
+	return mktime(year, mon, day, hour, min, sec);
+}
+
+#endif /* __ASM_MC146818_TIME_H */
--- diff/include/asm-mips/numnodes.h	1970-01-01 01:00:00.000000000 +0100
+++ source/include/asm-mips/numnodes.h	2004-02-23 13:56:47.000000000 +0000
@@ -0,0 +1,7 @@
+#ifndef _ASM_MAX_NUMNODES_H
+#define _ASM_MAX_NUMNODES_H
+
+/* Max 128 Nodes */
+#define NODES_SHIFT	7
+
+#endif /* _ASM_MAX_NUMNODES_H */
--- diff/include/asm-mips/prefetch.h	1970-01-01 01:00:00.000000000 +0100
+++ source/include/asm-mips/prefetch.h	2004-02-23 13:56:47.000000000 +0000
@@ -0,0 +1,43 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2003 by Ralf Baechle
+ */
+#ifndef __ASM_PREFETCH_H
+#define __ASM_PREFETCH_H
+
+/*
+ * R5000 and RM5200 implements pref and prefx instructions but they're nops, so
+ * rather than wasting time we pretend these processors don't support
+ * prefetching at all.
+ *
+ * R5432 implements Load, Store, LoadStreamed, StoreStreamed, LoadRetained,
+ * StoreRetained and WriteBackInvalidate but not Pref_PrepareForStore.
+ *
+ * Hell (and the book on my shelf I can't open ...) know what the R8000 does.
+ *
+ * RM7000 version 1.0 interprets all hints as Pref_Load; version 2.0 implements
+ * Pref_PrepareForStore also.
+ *
+ * RM9000 is MIPS IV but implements prefetching like MIPS32/MIPS64;
+ * it's Pref_WriteBackInvalidate is a nop.
+ *
+ * VR7701 only implements the Load prefetch.
+ *
+ * Finally MIPS32 and MIPS64 implement all of the following hints.
+ */
+
+#define Pref_Load			0
+#define Pref_Store			1
+						/* 2 and 3 are reserved */
+#define Pref_LoadStreamed		4
+#define Pref_StoreStreamed		5
+#define Pref_LoadRetained		6
+#define Pref_StoreRetained		7
+						/* 8 ... 24 are reserved */
+#define Pref_WriteBackInvalidate	25
+#define Pref_PrepareForStore		30
+
+#endif /* __ASM_PREFETCH_H */
--- diff/include/asm-mips/sgi/pi1.h	1970-01-01 01:00:00.000000000 +0100
+++ source/include/asm-mips/sgi/pi1.h	2004-02-23 13:56:47.000000000 +0000
@@ -0,0 +1,71 @@
+/*
+ * pi1.h: Definitions for SGI PI1 parallel port
+ */
+
+#ifndef _SGI_PI1_H
+#define _SGI_PI1_H
+
+struct pi1_regs {
+	u8 _data[3];
+	volatile u8 data;
+	u8 _ctrl[3];
+	volatile u8 ctrl;
+#define PI1_CTRL_STROBE_N	0x01
+#define PI1_CTRL_AFD_N		0x02
+#define PI1_CTRL_INIT_N		0x04
+#define PI1_CTRL_SLIN_N		0x08
+#define PI1_CTRL_IRQ_ENA	0x10
+#define PI1_CTRL_DIR		0x20
+#define PI1_CTRL_SEL		0x40
+	u8 _status[3];
+	volatile u8 status;
+#define PI1_STAT_DEVID		0x03	/* bits 0-1 */
+#define PI1_STAT_NOINK		0x04	/* SGI MODE only */
+#define PI1_STAT_ERROR		0x08
+#define PI1_STAT_ONLINE		0x10
+#define PI1_STAT_PE		0x20
+#define PI1_STAT_ACK		0x40
+#define PI1_STAT_BUSY		0x80
+	u8 _dmactrl[3];
+	volatile u8 dmactrl;
+#define PI1_DMACTRL_FIFO_EMPTY	0x01    /* fifo empty R/O */
+#define PI1_DMACTRL_ABORT	0x02    /* reset DMA and internal fifo W/O */
+#define PI1_DMACTRL_STDMODE	0x00    /* bits 2-3 */
+#define PI1_DMACTRL_SGIMODE	0x04    /* bits 2-3 */
+#define PI1_DMACTRL_RICOHMODE	0x08    /* bits 2-3 */
+#define PI1_DMACTRL_HPMODE	0x0c    /* bits 2-3 */
+#define PI1_DMACTRL_BLKMODE	0x10    /* block mode */
+#define PI1_DMACTRL_FIFO_CLEAR	0x20    /* clear fifo W/O */
+#define PI1_DMACTRL_READ	0x40    /* read */
+#define PI1_DMACTRL_RUN		0x80    /* pedal to the metal */
+	u8 _intstat[3];
+	volatile u8 intstat;
+#define PI1_INTSTAT_ACK		0x04
+#define PI1_INTSTAT_FEMPTY	0x08
+#define PI1_INTSTAT_NOINK	0x10
+#define PI1_INTSTAT_ONLINE	0x20
+#define PI1_INTSTAT_ERR		0x40
+#define PI1_INTSTAT_PE		0x80
+	u8 _intmask[3];
+	volatile u8 intmask;		/* enabled low, reset high*/
+#define PI1_INTMASK_ACK		0x04
+#define PI1_INTMASK_FIFO_EMPTY	0x08
+#define PI1_INTMASK_NOINK	0x10
+#define PI1_INTMASK_ONLINE	0x20
+#define PI1_INTMASK_ERR		0x40
+#define PI1_INTMASK_PE		0x80
+	u8 _timer1[3];
+	volatile u8 timer1;
+#define PI1_TIME1		0x27
+	u8 _timer2[3];
+	volatile u8 timer2;
+#define PI1_TIME2		0x13
+	u8 _timer3[3];
+	volatile u8 timer3;
+#define PI1_TIME3		0x10
+	u8 _timer4[3];
+	volatile u8 timer4;
+#define PI1_TIME4		0x00
+};
+
+#endif
--- diff/include/asm-mips/sn/hub.h	1970-01-01 01:00:00.000000000 +0100
+++ source/include/asm-mips/sn/hub.h	2004-02-23 13:56:47.000000000 +0000
@@ -0,0 +1,15 @@
+#ifndef __ASM_SN_HUB_H
+#define __ASM_SN_HUB_H
+
+#include <asm/sn/types.h>
+#include <asm/sn/io.h>
+#include <asm/sn/klkernvars.h>
+
+struct hub_data {
+	kern_vars_t	kern_vars;
+};
+
+extern struct hub_data *hub_data[];
+#define HUB_DATA(n)		(hub_data[(n)])
+
+#endif /* __ASM_SN_HUB_H */
--- diff/include/asm-mips/titan_dep.h	1970-01-01 01:00:00.000000000 +0100
+++ source/include/asm-mips/titan_dep.h	2004-02-23 13:56:47.000000000 +0000
@@ -0,0 +1,68 @@
+/*
+ * Copyright 2003 PMC-Sierra
+ * Author: Manish Lachwani (lachwani@pmc-sierra.com)
+ *
+ * Board specific definititions for the PMC-Sierra Yosemite
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+
+#ifndef __TITAN_DEP_H__
+#define __TITAN_DEP_H__
+
+#include <asm/addrspace.h>              /* for KSEG1ADDR() */
+#include <asm/byteorder.h>              /* for cpu_to_le32() */
+
+/* Turn on serial */
+#define	CONFIG_TITAN_SERIAL
+
+/* PCI */
+#define	TITAN_PCI_BASE			0xbb000000
+
+#define TITAN_WRITE(ofs, data)  \
+        *(volatile u32 *)(TITAN_PCI_BASE+(ofs)) = cpu_to_le32(data)
+#define TITAN_READ(ofs, data)   \
+        *(data) = le32_to_cpu(*(volatile u32 *)(TITAN_PCI_BASE+(ofs)))
+#define TITAN_READ_DATA(ofs)    \
+        le32_to_cpu(*(volatile u32 *)(TITAN_PCI_BASE+(ofs)))
+
+#define TITAN_WRITE_16(ofs, data)  \
+        *(volatile u16 *)(TITAN_PCI_BASE+(ofs)) = cpu_to_le16(data)
+#define TITAN_READ_16(ofs, data)   \
+        *(data) = le16_to_cpu(*(volatile u16 *)(TITAN_PCI_BASE+(ofs)))
+
+#define TITAN_WRITE_8(ofs, data)  \
+        *(volatile u8 *)(TITAN_PCI_BASE+(ofs)) = data
+#define TITAN_READ_8(ofs, data)   \
+        *(data) = *(volatile u8 *)(TITAN_PCI_BASE+(ofs))
+
+/*
+ * PCI specific defines
+ */
+#define	TITAN_PCI_0_CONFIG_ADDRESS	0x780
+#define	TITAN_PCI_0_CONFIG_DATA		0x784
+
+/*
+ * HT specific defines
+ */
+#define RM9000x2_HTLINK_REG     0xbb000644
+#define RM9000x2_BASE_ADDR      0xbb000000
+#define RM9000x2_OCD_HTCFGA     0x06f8
+#define RM9000x2_OCD_HTCFGD     0x06fc
+
+/*
+ * Hypertransport specific macros
+ */
+#define RM9K_WRITE(ofs, data)   *(volatile u_int32_t *)(RM9000x2_BASE_ADDR+ofs) = data
+#define RM9K_WRITE_8(ofs, data) *(volatile u8 *)(RM9000x2_BASE_ADDR+ofs) = data
+#define RM9K_WRITE_16(ofs, data) *(volatile u16 *)(RM9000x2_BASE_ADDR+ofs) = data
+
+#define RM9K_READ(ofs, val)     *(val) = *(volatile u_int32_t *)(RM9000x2_BASE_ADDR+ofs)
+#define RM9K_READ_8(ofs, val)   *(val) = *(volatile u8 *)(RM9000x2_BASE_ADDR+ofs)
+#define RM9K_READ_16(ofs, val)  *(val) = *(volatile u16 *)(RM9000x2_BASE_ADDR+ofs)
+
+#endif 
+
--- diff/include/asm-mips/vr41xx/vrc4171.h	1970-01-01 01:00:00.000000000 +0100
+++ source/include/asm-mips/vr41xx/vrc4171.h	2004-02-23 13:56:47.000000000 +0000
@@ -0,0 +1,43 @@
+/*
+ *  vrc4171.h, Include file for NEC VRC4171.
+ *
+ *  Copyright (C) 2003  Yoichi Yuasa <yuasa@hh.iij4u.or.jp>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+#ifndef __NEC_VRC4171_H 
+#define __NEC_VRC4171_H 
+
+/*
+ * Configuration 1
+ */
+enum {
+	SLOTB_IS_NONE,       
+	SLOTB_IS_PCCARD,
+	SLOTB_IS_CF,
+	SLOTB_IS_FLASHROM
+};
+
+extern void vrc4171_set_multifunction_pin(int config);
+
+/*
+ * Interrupt Status Mask
+ */
+#define IRQ_A	0x02
+#define IRQ_B	0x04
+
+extern uint16_t vrc4171_get_irq_status(void);
+
+#endif /* __NEC_VRC4171_H */
--- diff/include/asm-mips/xxs1500.h	1970-01-01 01:00:00.000000000 +0100
+++ source/include/asm-mips/xxs1500.h	2004-02-23 13:56:47.000000000 +0000
@@ -0,0 +1,35 @@
+/*
+ * MyCable XXS1500 Referrence Board
+ *
+ * Copyright 2003 MontaVista Software Inc.
+ * Author: Pete Popov, MontaVista Software, Inc.
+ *         	ppopov@mvista.com or source@mvista.com
+ *
+ * ########################################################################
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ *
+ * 
+ */
+#ifndef __ASM_XXS1500_H
+#define __ASM_XXS1500_H
+
+/* PCMCIA XXS1500 specific defines */
+#define PCMCIA_MAX_SOCK 0
+#define PCMCIA_NUM_SOCKS (PCMCIA_MAX_SOCK+1)
+#define PCMCIA_IRQ AU1000_GPIO_4
+
+#endif /* __ASM_XXS1500_ */
--- diff/include/asm-s390/cmb.h	1970-01-01 01:00:00.000000000 +0100
+++ source/include/asm-s390/cmb.h	2004-02-23 13:56:47.000000000 +0000
@@ -0,0 +1,98 @@
+#ifndef S390_CMB_H
+#define S390_CMB_H
+/**
+ * struct cmbdata -- channel measurement block data for user space
+ *
+ * @size:	size of the stored data
+ * @ssch_rsch_count: XXX
+ * @sample_count:
+ * @device_connect_time:
+ * @function_pending_time:
+ * @device_disconnect_time:
+ * @control_unit_queuing_time:
+ * @device_active_only_time:
+ * @device_busy_time:
+ * @initial_command_response_time:
+ *
+ * all values are stored as 64 bit for simplicity, especially
+ * in 32 bit emulation mode. All time values are normalized to
+ * nanoseconds.
+ * Currently, two formats are known, which differ by the size of
+ * this structure, i.e. the last two members are only set when
+ * the extended channel measurement facility (first shipped in
+ * z990 machines) is activated.
+ * Potentially, more fields could be added, which results in a
+ * new ioctl number.
+ **/
+struct cmbdata {
+	__u64 size;
+	__u64 elapsed_time;
+ /* basic and exended format: */
+	__u64 ssch_rsch_count;
+	__u64 sample_count;
+	__u64 device_connect_time;
+	__u64 function_pending_time;
+	__u64 device_disconnect_time;
+	__u64 control_unit_queuing_time;
+	__u64 device_active_only_time;
+ /* extended format only: */
+	__u64 device_busy_time;
+	__u64 initial_command_response_time;
+};
+
+/* enable channel measurement */
+#define BIODASDCMFENABLE	_IO(DASD_IOCTL_LETTER,32)
+/* enable channel measurement */
+#define BIODASDCMFDISABLE	_IO(DASD_IOCTL_LETTER,33)
+/* reset channel measurement block */
+#define BIODASDRESETCMB		_IO(DASD_IOCTL_LETTER,34)
+/* read channel measurement data */
+#define BIODASDREADCMB		_IOWR(DASD_IOCTL_LETTER,32,u64)
+/* read channel measurement data */
+#define BIODASDREADALLCMB	_IOWR(DASD_IOCTL_LETTER,33,struct cmbdata)
+
+#ifdef __KERNEL__
+
+/**
+ * enable_cmf() - switch on the channel measurement for a specific device
+ *  @cdev:	The ccw device to be enabled
+ *  returns 0 for success or a negative error value.
+ *
+ *  Context:
+ *    non-atomic
+ **/
+extern int enable_cmf(struct ccw_device *cdev);
+
+/**
+ * disable_cmf() - switch off the channel measurement for a specific device
+ *  @cdev:	The ccw device to be disabled
+ *  returns 0 for success or a negative error value.
+ *
+ *  Context:
+ *    non-atomic
+ **/
+extern int disable_cmf(struct ccw_device *cdev);
+
+/**
+ * cmf_read() - read one value from the current channel measurement block
+ * @cmf:	the channel to be read
+ * @index:	the name of the value that is read
+ *
+ *  Context:
+ *    any
+ **/
+
+extern u64 cmf_read(struct ccw_device *cdev, int index);
+/**
+ * cmf_readall() - read one value from the current channel measurement block
+ * @cmf:	the channel to be read
+ * @data:	a pointer to a data block that will be filled
+ *
+ *  Context:
+ *    any
+ **/
+extern int cmf_readall(struct ccw_device *cdev, struct cmbdata*data);
+extern void cmf_reset(struct ccw_device *cdev);
+
+#endif /* __KERNEL__ */
+#endif /* S390_CMB_H */
--- diff/include/asm-s390/extmem.h	1970-01-01 01:00:00.000000000 +0100
+++ source/include/asm-s390/extmem.h	2004-02-23 13:56:47.000000000 +0000
@@ -0,0 +1,19 @@
+/*
+ *  include/asm-s390x/extmem.h
+ *
+ *  definitions for external memory segment support
+ *  Copyright (C) 2003 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ */
+
+#ifndef _ASM_S390X_DCSS_H
+#define _ASM_S390X_DCSS_H
+#ifndef __ASSEMBLY__
+#define SEGMENT_SHARED_RW       0
+#define SEGMENT_SHARED_RO       1
+#define SEGMENT_EXCLUSIVE_RW    2
+#define SEGMENT_EXCLUSIVE_RO    3
+extern int segment_load (char *name,int segtype,unsigned long *addr,unsigned long *length);
+extern void segment_unload(char *name);
+extern void segment_replace(char *name);
+#endif
+#endif
--- diff/include/asm-s390/timer.h	1970-01-01 01:00:00.000000000 +0100
+++ source/include/asm-s390/timer.h	2004-02-23 13:56:47.000000000 +0000
@@ -0,0 +1,50 @@
+/*
+ *  include/asm-s390/timer.h
+ *
+ *  (C) Copyright IBM Corp. 2003
+ *  Virtual CPU timer
+ *
+ *  Author: Jan Glauber (jang@de.ibm.com)
+ */
+
+#ifndef _ASM_S390_TIMER_H
+#define _ASM_S390_TIMER_H
+
+#include <linux/timer.h>
+
+#define VTIMER_MAX_SLICE (0x7ffffffffffff000LL)
+
+struct vtimer_list {
+	struct list_head entry;
+
+	int cpu;
+	__u64 expires;
+	__u64 interval;
+
+	spinlock_t lock;
+	unsigned long magic;
+
+	void (*function)(unsigned long, struct pt_regs*);
+	unsigned long data;
+};
+
+/* the offset value will wrap after ca. 71 years */
+struct vtimer_queue {
+	struct list_head list;
+	spinlock_t lock;
+	__u64 to_expire;	  /* current event expire time */
+	__u64 offset;		  /* list offset to zero */
+	__u64 idle;		  /* temp var for idle */
+};
+
+void set_vtimer(__u64 expires);
+
+extern void init_virt_timer(struct vtimer_list *timer);
+extern void add_virt_timer(void *new);
+extern void add_virt_timer_periodic(void *new);
+extern int mod_virt_timer(struct vtimer_list *timer, __u64 expires);
+extern int del_virt_timer(struct vtimer_list *timer);
+
+int stop_timers(void);
+
+#endif
--- diff/include/asm-sparc64/lockmeter.h	1970-01-01 01:00:00.000000000 +0100
+++ source/include/asm-sparc64/lockmeter.h	2004-02-23 13:56:47.000000000 +0000
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2000 Anton Blanchard (anton@linuxcare.com)
+ * Copyright (C) 2003 David S. Miller (davem@redhat.com)
+ */
+
+#ifndef _SPARC64_LOCKMETER_H
+#define _SPARC64_LOCKMETER_H
+
+#include <linux/smp.h>
+#include <asm/spinlock.h>
+#include <asm/timer.h>
+#include <asm/timex.h>
+
+/* Actually, this is not the CPU frequency by the system tick
+ * frequency which is good enough for lock metering.
+ */
+#define CPU_CYCLE_FREQUENCY	(timer_tick_offset * HZ)
+#define THIS_CPU_NUMBER		smp_processor_id()
+
+#define PUT_INDEX(lock_ptr,indexv)	(lock_ptr)->index = (indexv)
+#define GET_INDEX(lock_ptr)		(lock_ptr)->index
+
+#define PUT_RWINDEX(rwlock_ptr,indexv) (rwlock_ptr)->index = (indexv)
+#define GET_RWINDEX(rwlock_ptr)        (rwlock_ptr)->index
+#define PUT_RW_CPU(rwlock_ptr,cpuv)    (rwlock_ptr)->cpu = (cpuv)
+#define GET_RW_CPU(rwlock_ptr)         (rwlock_ptr)->cpu
+
+#define RWLOCK_READERS(rwlock_ptr)	rwlock_readers(rwlock_ptr)
+
+extern inline int rwlock_readers(rwlock_t *rwlock_ptr)
+{
+	signed int tmp = rwlock_ptr->lock;
+
+	if (tmp > 0)
+		return tmp;
+	else
+		return 0;
+}
+
+#define RWLOCK_IS_WRITE_LOCKED(rwlock_ptr)	((signed int)((rwlock_ptr)->lock) < 0)
+#define RWLOCK_IS_READ_LOCKED(rwlock_ptr)	((signed int)((rwlock_ptr)->lock) > 0)
+
+#define get_cycles64()	get_cycles()
+
+#endif /* _SPARC64_LOCKMETER_H */
--- diff/include/asm-x86_64/kgdb.h	1970-01-01 01:00:00.000000000 +0100
+++ source/include/asm-x86_64/kgdb.h	2004-02-23 13:56:47.000000000 +0000
@@ -0,0 +1,71 @@
+#ifndef __KGDB
+#define __KGDB
+
+/*
+ * This file should not include ANY others.  This makes it usable
+ * most anywhere without the fear of include order or inclusion.
+ * Make it so!
+ *
+ * This file may be included all the time.  It is only active if
+ * CONFIG_KGDB is defined, otherwise it stubs out all the macros
+ * and entry points.
+ */
+#if defined(CONFIG_KGDB) && !defined(__ASSEMBLY__)
+
+extern void breakpoint(void);
+#define INIT_KGDB_INTS kgdb_enable_ints()
+
+#ifndef BREAKPOINT
+#define BREAKPOINT   asm("   int $3")
+#endif
+
+extern void kgdb_schedule_breakpoint(void);
+extern void kgdb_process_breakpoint(void);
+
+extern int kgdb_tty_hook(void);
+extern int kgdb_eth_hook(void);
+extern int kgdboe;
+
+/*
+ * GDB debug stub (or any debug stub) can point the 'linux_debug_hook'
+ * pointer to its routine and it will be entered as the first thing
+ * when a trap occurs.
+ *
+ * Return values are, at present, undefined.
+ *
+ * The debug hook routine does not necessarily return to its caller.
+ * It has the register image and thus may choose to resume execution
+ * anywhere it pleases.
+ */
+struct pt_regs;
+
+extern int kgdb_handle_exception(int trapno,
+				 int signo, int err_code, struct pt_regs *regs);
+extern int in_kgdb(struct pt_regs *regs);
+
+extern void set_debug_traps(void);
+
+#ifdef CONFIG_KGDB_TS
+void kgdb_tstamp(int line, char *source, int data0, int data1);
+/*
+ * This is the time stamp function.  The macro adds the source info and
+ * does a cast on the data to allow most any 32-bit value.
+ */
+
+#define kgdb_ts(data0,data1) kgdb_tstamp(__LINE__,__FILE__,(int)data0,(int)data1)
+#else
+#define kgdb_ts(data0,data1)
+#endif
+#else				/* CONFIG_KGDB  && ! __ASSEMBLY__ ,stubs follow... */
+#ifndef BREAKPOINT
+#define BREAKPOINT
+#endif
+#define kgdb_ts(data0,data1)
+#define in_kgdb	(0)
+#define kgdb_handle_exception
+#define breakpoint
+#define INIT_KGDB_INTS
+#define kgdb_process_breakpoint() do {} while(0)
+
+#endif
+#endif				/* __KGDB */
--- diff/include/asm-x86_64/kgdb_local.h	1970-01-01 01:00:00.000000000 +0100
+++ source/include/asm-x86_64/kgdb_local.h	2004-02-23 13:56:47.000000000 +0000
@@ -0,0 +1,102 @@
+#ifndef __KGDB_LOCAL
+#define ___KGDB_LOCAL
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/serial.h>
+#include <linux/serialP.h>
+#include <linux/spinlock.h>
+#include <asm/processor.h>
+#include <asm/msr.h>
+#include <asm/kgdb.h>
+
+#define PORT 0x3f8
+#ifdef CONFIG_KGDB_PORT
+#undef PORT
+#define PORT CONFIG_KGDB_PORT
+#endif
+#define IRQ 4
+#ifdef CONFIG_KGDB_IRQ
+#undef IRQ
+#define IRQ CONFIG_KGDB_IRQ
+#endif
+#define SB_CLOCK 1843200
+#define SB_BASE (SB_CLOCK/16)
+#define SB_BAUD9600 SB_BASE/9600
+#define SB_BAUD192  SB_BASE/19200
+#define SB_BAUD384  SB_BASE/38400
+#define SB_BAUD576  SB_BASE/57600
+#define SB_BAUD1152 SB_BASE/115200
+#ifdef CONFIG_KGDB_9600BAUD
+#define SB_BAUD SB_BAUD9600
+#endif
+#ifdef CONFIG_KGDB_19200BAUD
+#define SB_BAUD SB_BAUD192
+#endif
+#ifdef CONFIG_KGDB_38400BAUD
+#define SB_BAUD SB_BAUD384
+#endif
+#ifdef CONFIG_KGDB_57600BAUD
+#define SB_BAUD SB_BAUD576
+#endif
+#ifdef CONFIG_KGDB_115200BAUD
+#define SB_BAUD SB_BAUD1152
+#endif
+#ifndef SB_BAUD
+#define SB_BAUD SB_BAUD1152	/* Start with this if not given */
+#endif
+
+#ifndef CONFIG_X86_TSC
+#undef rdtsc
+#define rdtsc(a,b) if (a++ > 10000){a = 0; b++;}
+#undef rdtscll
+#define rdtscll(s) s++
+#endif
+
+#ifdef _raw_read_unlock		/* must use a name that is "define"ed, not an inline */
+#undef spin_lock
+#undef spin_trylock
+#undef spin_unlock
+#define spin_lock	 _raw_spin_lock
+#define spin_trylock	 _raw_spin_trylock
+#define spin_unlock	 _raw_spin_unlock
+#else
+#endif
+#undef spin_unlock_wait
+#define spin_unlock_wait(x)  do { cpu_relax(); barrier();} \
+                                     while(spin_is_locked(x))
+
+#define SB_IER 1
+#define SB_MCR UART_MCR_OUT2 | UART_MCR_DTR | UART_MCR_RTS
+
+#define FLAGS 0
+#define SB_STATE { \
+     magic: SSTATE_MAGIC, \
+     baud_base: SB_BASE,  \
+     port:      PORT,     \
+     irq:       IRQ,      \
+     flags:     FLAGS,    \
+     custom_divisor:SB_BAUD}
+#define SB_INFO  { \
+      magic: SERIAL_MAGIC, \
+      port:  PORT,0,FLAGS, \
+      state: &state,       \
+      tty:   (struct tty_struct *)&state, \
+      IER:   SB_IER,       \
+      MCR:   SB_MCR}
+extern void putDebugChar(int);
+/* RTAI support needs us to really stop/start interrupts */
+
+#define kgdb_sti() __asm__ __volatile__("sti": : :"memory")
+#define kgdb_cli() __asm__ __volatile__("cli": : :"memory")
+#define kgdb_local_save_flags(x) __asm__ __volatile__(\
+                                   "pushfl ; popl %0":"=g" (x): /* no input */)
+#define kgdb_local_irq_restore(x) __asm__ __volatile__(\
+                                   "pushl %0 ; popfl": \
+                                     /* no output */ :"g" (x):"memory", "cc")
+#define kgdb_local_irq_save(x) kgdb_local_save_flags(x); kgdb_cli()
+
+#ifdef CONFIG_SERIAL
+extern void shutdown_for_kgdb(struct async_struct *info);
+#endif
+#define INIT_KDEBUG putDebugChar("+");
+#endif				/* __KGDB_LOCAL */
--- diff/include/linux/compat_siginfo.h	1970-01-01 01:00:00.000000000 +0100
+++ source/include/linux/compat_siginfo.h	2004-02-23 13:56:47.000000000 +0000
@@ -0,0 +1,170 @@
+#ifndef _ASM_GENERIC_COMPAT_SIGINFO_H
+#define _ASM_GENERIC_COMPAT_SIGINFO_H
+
+#include <linux/config.h>
+#include <linux/compat.h>
+
+#ifndef CONFIG_COMPAT
+
+/* No compatibility layer required, add empty definitions for the compiler */
+
+typedef struct compat_siginfo{
+} compat_siginfo_t;
+
+static inline int compat_copy_siginfo_to_user(compat_siginfo_t __user *to,
+						struct siginfo *from)
+{
+	return -1;
+}
+
+#else
+
+#include <linux/compiler.h>
+#include <asm/siginfo.h>
+
+/* compat view of sigval_t */
+typedef union compat_sigval {
+	compat_int_t sival_int;
+	compat_uptr_t sival_ptr;
+} compat_sigval_t;
+
+/*
+ * This is the size (including padding) of the part of the
+ * struct siginfo that is before the union.
+ */
+#ifndef __ARCH_SI_COMPAT_PREAMBLE_SIZE
+#define __ARCH_SI_COMPAT_PREAMBLE_SIZE	(3 * sizeof(int))
+#endif
+
+#define SI_COMPAT_MAX_SIZE	128
+#ifndef SI_COMPAT_PAD_SIZE
+#define SI_COMPAT_PAD_SIZE	((SI_COMPAT_MAX_SIZE - __ARCH_SI_COMPAT_PREAMBLE_SIZE) / sizeof(int))
+#endif
+
+/* 32-bit view of si.uid_t */
+#ifndef __ARCH_SI_COMPAT_UID_T
+#define __ARCH_SI_COMPAT_UID_T compat_uid_t
+#endif
+
+/* 32-bit view of si.band_t */
+#ifndef __ARCH_SI_COMPAT_BAND_T
+#define __ARCH_SI_COMPAT_BAND_T compat_int_t
+#endif
+
+#ifndef HAVE_ARCH_COMPAT_SIGINFO_T
+
+/* Compat view of siginfo_t */
+typedef struct compat_siginfo {
+	compat_int_t si_signo;
+	compat_int_t si_errno;
+	compat_int_t si_code;
+
+	union {
+		compat_int_t _pad[SI_COMPAT_PAD_SIZE];
+
+		/* kill() */
+		struct {
+			compat_pid_t _pid;	/* sender's pid */
+			__ARCH_SI_COMPAT_UID_T _uid;	/* sender's uid */
+		} _kill;
+
+		/* POSIX.1b timers */
+		struct {
+			compat_timer_t _tid;	/* timer id */
+			compat_int_t _overrun;		/* overrun count */
+			char _pad[sizeof( __ARCH_SI_UID_T) - sizeof(int)];
+			compat_sigval_t _sigval;	/* same as below */
+			compat_int_t _sys_private;       /* not to be passed to user */
+		} _timer;
+
+		/* POSIX.1b signals */
+		struct {
+			compat_pid_t _pid;		/* sender's pid */
+			__ARCH_SI_COMPAT_UID_T _uid;	/* sender's uid */
+			compat_sigval_t _sigval;
+		} _rt;
+
+		/* SIGCHLD */
+		struct {
+			compat_pid_t _pid;		/* which child */
+			__ARCH_SI_COMPAT_UID_T _uid;	/* sender's uid */
+			compat_int_t _status;		/* exit code */
+			compat_clock_t _utime;
+			compat_clock_t _stime;
+		} _sigchld;
+
+		/* SIGILL, SIGFPE, SIGSEGV, SIGBUS */
+		struct {
+			compat_uptr_t _addr; /* faulting insn/memory ref. */
+#ifdef __ARCH_SI_COMPAT_TRAPNO
+			compat_int_t _trapno;	/* TRAP # which caused the signal */
+#endif
+		} _sigfault;
+
+		/* SIGPOLL */
+		struct {
+			__ARCH_SI_COMPAT_BAND_T _band;	/* POLL_IN, POLL_OUT, POLL_MSG */
+			compat_int_t _fd;
+		} _sigpoll;
+	} _sifields;
+} compat_siginfo_t;
+#endif /* !HAVE_ARCH_COMPAT_SIGINFO_T */
+
+#ifdef __ARCH_SI_COMPAT_TRAPNO
+#define si_trapno	_sifields._sigfault._trapno
+#endif
+
+/*
+ * sigevent definitions
+ *
+ * It seems likely that SIGEV_THREAD will have to be handled from
+ * userspace, libpthread transmuting it to SIGEV_SIGNAL, which the
+ * thread manager then catches and does the appropriate nonsense.
+ * However, everything is written out here so as to not get lost.
+ */
+
+#define SIGEV_COMPAT_MAX_SIZE	64
+#ifndef SIGEV_COMPAT_PAD_SIZE
+#define SIGEV_COMPAT_PAD_SIZE	((SIGEV_COMPAT_MAX_SIZE/sizeof(int)) - 3)
+#endif
+
+#ifndef HAVE_ARCH_COMPAT_SIGEVENT_T
+
+/* 32-bit view of sigevent_t */
+typedef struct compat_sigevent {
+	compat_sigval_t sigev_value;
+	compat_int_t sigev_signo;
+	compat_int_t sigev_notify;
+	union {
+		compat_int_t _pad[SIGEV_COMPAT_PAD_SIZE];
+		compat_int_t _tid;
+
+		struct {
+			compat_uptr_t _function;
+			compat_uptr_t _attribute;	/* really pthread_attr_t */
+		} _sigev_thread;
+	} _sigev_un;
+} compat_sigevent_t;
+
+#endif /* HAVE_ARCH_COMPAT_SIGEVENT_T */
+
+#ifndef HAVE_ARCH_COMPAT_COPY_SIGINFO
+
+#include <linux/string.h>
+
+static inline void compat_copy_siginfo(struct compat_siginfo *to, struct compat_siginfo *from)
+{
+	if (from->si_code < 0)
+		memcpy(to, from, sizeof(*to));
+	else
+		/* _sigchld is currently the largest know union member */
+		memcpy(to, from, __ARCH_SI_COMPAT_PREAMBLE_SIZE + sizeof(from->_sifields._sigchld));
+}
+
+#endif /* !HAVE_ARCH_COMPAT_COPY_SIGINFO */
+
+extern int compat_copy_siginfo_to_user(compat_siginfo_t __user *to, struct siginfo *from);
+
+#endif /* CONFIG_COMPAT */
+#endif /* _ASM_GENERIC_COMPAT_SIGINFO_H */
+
--- diff/include/linux/dwarf2-lang.h	1970-01-01 01:00:00.000000000 +0100
+++ source/include/linux/dwarf2-lang.h	2004-02-23 13:56:47.000000000 +0000
@@ -0,0 +1,132 @@
+#ifndef DWARF2_LANG
+#define DWARF2_LANG
+#include <linux/dwarf2.h>
+
+/*
+ * This is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2, or (at your option) any later
+ * version.
+ */
+/*
+ * This file defines macros that allow generation of DWARF debug records
+ * for asm files.  This file is platform independent.  Register numbers
+ * (which are about the only thing that is platform dependent) are to be
+ * supplied by a platform defined file.
+ */
+#define DWARF_preamble()	.section	.debug_frame,"",@progbits
+/*
+ * This macro starts a debug frame section.  The debug_frame describes
+ * where to find the registers that the enclosing function saved on
+ * entry.
+ *
+ * ORD is use by the label generator and should be the same as what is
+ * passed to CFI_postamble.
+ *
+ * pc,	pc register gdb ordinal.
+ *
+ * code_align this is the factor used to define locations or regions
+ * where the given definitions apply.  If you use labels to define these
+ * this should be 1.
+ *
+ * data_align this is the factor used to define register offsets.  If
+ * you use struct offset, this should be the size of the register in
+ * bytes or the negative of that.  This is how it is used: you will
+ * define a register as the reference register, say the stack pointer,
+ * then you will say where a register is located relative to this
+ * reference registers value, say 40 for register 3 (the gdb register
+ * number).  The <40> will be multiplied by <data_align> to define the
+ * byte offset of the given register (3, in this example).  So if your
+ * <40> is the byte offset and the reference register points at the
+ * begining, you would want 1 for the data_offset.  If <40> was the 40th
+ * 4-byte element in that structure you would want 4.  And if your
+ * reference register points at the end of the structure you would want
+ * a negative data_align value(and you would have to do other math as
+ * well).
+ */
+
+#define CFI_preamble(ORD, pc, code_align, data_align)	\
+.section	.debug_frame,"",@progbits ;		\
+frame/**/_/**/ORD:						\
+	.long end/**/_/**/ORD-start/**/_/**/ORD;			\
+start/**/_/**/ORD:						\
+	.long	DW_CIE_ID;				\
+	.byte	DW_CIE_VERSION;			\
+	.byte 0	 ;				\
+	.uleb128 code_align;				\
+	.sleb128 data_align;				\
+	.byte pc;
+
+/*
+ * After the above macro and prior to the CFI_postamble, you need to
+ * define the initial state.  This starts with defining the reference
+ * register and, usually the pc.  Here are some helper macros:
+ */
+
+#define CFA_define_reference(reg, offset)	\
+	.byte DW_CFA_def_cfa;			\
+	.uleb128 reg;				\
+	.uleb128 (offset);
+
+#define CFA_define_offset(reg, offset)		\
+	.byte (DW_CFA_offset + reg);		\
+	.uleb128 (offset);
+
+#define CFI_postamble(ORD)			\
+	.align 4;				\
+end/**/_/**/ORD:
+/*
+ * So now your code pushs stuff on the stack, you need a new location
+ * and the rules for what to do.  This starts a running description of
+ * the call frame.  You need to describe what changes with respect to
+ * the call registers as the location of the pc moves through the code.
+ * The following builds an FDE (fram descriptor entry?).  Like the
+ * above, it has a preamble and a postamble.  It also is tied to the CFI
+ * above.
+ * The first entry after the preamble must be the location in the code
+ * that the call frame is being described for.
+ */
+#define FDE_preamble(ORD, fde_no, initial_address, length)	\
+	.long FDE_end/**/_/**/fde_no-FDE_start/**/_/**/fde_no;		\
+FDE_start/**/_/**/fde_no:						\
+	.long frame/**/_/**/ORD;					\
+	.long initial_address;					\
+	.long length;
+
+#define FDE_postamble(fde_no)			\
+	.align 4;				\
+FDE_end/**/_/**/fde_no:
+/*
+ * That done, you can now add registers, subtract registers, move the
+ * reference and even change the reference.  You can also define a new
+ * area of code the info applies to.  For discontinuous bits you should
+ * start a new FDE.  You may have as many as you like.
+ */
+
+/*
+ * To advance the address by <bytes>
+ */
+
+#define FDE_advance(bytes)			\
+	.byte DW_CFA_advance_loc4		\
+	.long bytes
+
+
+
+/*
+ * With the above you can define all the register locations.  But
+ * suppose the reference register moves... Takes the new offset NOT an
+ * increment.  This is how esp is tracked if it is not saved.
+ */
+
+#define CFA_define_cfa_offset(offset) \
+	.byte $DW_CFA_def_cfa_offset; \
+	.uleb128 (offset);
+/*
+ * Or suppose you want to use a different reference register...
+ */
+#define CFA_define_cfa_register(reg)		\
+	.byte DW_CFA_def_cfa_register;		\
+	.uleb128 reg;
+
+#endif
--- diff/include/linux/dwarf2.h	1970-01-01 01:00:00.000000000 +0100
+++ source/include/linux/dwarf2.h	2004-02-23 13:56:47.000000000 +0000
@@ -0,0 +1,738 @@
+/* Declarations and definitions of codes relating to the DWARF2 symbolic
+   debugging information format.
+   Copyright (C) 1992, 1993, 1995, 1996, 1997, 1999, 2000, 2001, 2002
+   Free Software Foundation, Inc.
+
+   Written by Gary Funck (gary@intrepid.com) The Ada Joint Program
+   Office (AJPO), Florida State Unviversity and Silicon Graphics Inc.
+   provided support for this effort -- June 21, 1995.
+
+   Derived from the DWARF 1 implementation written by Ron Guilmette
+   (rfg@netcom.com), November 1990.
+
+   This file is part of GCC.
+
+   GCC is free software; you can redistribute it and/or modify it under
+   the terms of the GNU General Public License as published by the Free
+   Software Foundation; either version 2, or (at your option) any later
+   version.
+
+   GCC is distributed in the hope that it will be useful, but WITHOUT
+   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+   or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
+   License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with GCC; see the file COPYING.  If not, write to the Free
+   Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+   02111-1307, USA.  */
+
+/* This file is derived from the DWARF specification (a public document)
+   Revision 2.0.0 (July 27, 1993) developed by the UNIX International
+   Programming Languages Special Interest Group (UI/PLSIG) and distributed
+   by UNIX International.  Copies of this specification are available from
+   UNIX International, 20 Waterview Boulevard, Parsippany, NJ, 07054.
+
+   This file also now contains definitions from the DWARF 3 specification.  */
+
+/* This file is shared between GCC and GDB, and should not contain
+   prototypes.	*/
+
+#ifndef _ELF_DWARF2_H
+#define _ELF_DWARF2_H
+
+/* Structure found in the .debug_line section.	*/
+#ifndef __ASSEMBLY__
+typedef struct
+{
+  unsigned char li_length	   [4];
+  unsigned char li_version	   [2];
+  unsigned char li_prologue_length [4];
+  unsigned char li_min_insn_length [1];
+  unsigned char li_default_is_stmt [1];
+  unsigned char li_line_base	   [1];
+  unsigned char li_line_range	   [1];
+  unsigned char li_opcode_base	   [1];
+}
+DWARF2_External_LineInfo;
+
+typedef struct
+{
+  unsigned long  li_length;
+  unsigned short li_version;
+  unsigned int	 li_prologue_length;
+  unsigned char  li_min_insn_length;
+  unsigned char  li_default_is_stmt;
+  int		 li_line_base;
+  unsigned char  li_line_range;
+  unsigned char  li_opcode_base;
+}
+DWARF2_Internal_LineInfo;
+
+/* Structure found in .debug_pubnames section.	*/
+typedef struct
+{
+  unsigned char pn_length  [4];
+  unsigned char pn_version [2];
+  unsigned char pn_offset  [4];
+  unsigned char pn_size    [4];
+}
+DWARF2_External_PubNames;
+
+typedef struct
+{
+  unsigned long  pn_length;
+  unsigned short pn_version;
+  unsigned long  pn_offset;
+  unsigned long  pn_size;
+}
+DWARF2_Internal_PubNames;
+
+/* Structure found in .debug_info section.  */
+typedef struct
+{
+  unsigned char  cu_length	  [4];
+  unsigned char  cu_version	  [2];
+  unsigned char  cu_abbrev_offset [4];
+  unsigned char  cu_pointer_size  [1];
+}
+DWARF2_External_CompUnit;
+
+typedef struct
+{
+  unsigned long  cu_length;
+  unsigned short cu_version;
+  unsigned long  cu_abbrev_offset;
+  unsigned char  cu_pointer_size;
+}
+DWARF2_Internal_CompUnit;
+
+typedef struct
+{
+  unsigned char  ar_length	 [4];
+  unsigned char  ar_version	 [2];
+  unsigned char  ar_info_offset  [4];
+  unsigned char  ar_pointer_size [1];
+  unsigned char  ar_segment_size [1];
+}
+DWARF2_External_ARange;
+
+typedef struct
+{
+  unsigned long  ar_length;
+  unsigned short ar_version;
+  unsigned long  ar_info_offset;
+  unsigned char  ar_pointer_size;
+  unsigned char  ar_segment_size;
+}
+DWARF2_Internal_ARange;
+
+#define ENUM(name) enum name {
+#define IF_NOT_ASM(a) a
+#define COMMA ,
+#else
+#define ENUM(name)
+#define IF_NOT_ASM(a)
+#define COMMA
+
+#endif
+
+/* Tag names and codes.  */
+ENUM(dwarf_tag)
+
+    DW_TAG_padding = 0x00 COMMA
+    DW_TAG_array_type = 0x01 COMMA
+    DW_TAG_class_type = 0x02 COMMA
+    DW_TAG_entry_point = 0x03 COMMA
+    DW_TAG_enumeration_type = 0x04 COMMA
+    DW_TAG_formal_parameter = 0x05 COMMA
+    DW_TAG_imported_declaration = 0x08 COMMA
+    DW_TAG_label = 0x0a COMMA
+    DW_TAG_lexical_block = 0x0b COMMA
+    DW_TAG_member = 0x0d COMMA
+    DW_TAG_pointer_type = 0x0f COMMA
+    DW_TAG_reference_type = 0x10 COMMA
+    DW_TAG_compile_unit = 0x11 COMMA
+    DW_TAG_string_type = 0x12 COMMA
+    DW_TAG_structure_type = 0x13 COMMA
+    DW_TAG_subroutine_type = 0x15 COMMA
+    DW_TAG_typedef = 0x16 COMMA
+    DW_TAG_union_type = 0x17 COMMA
+    DW_TAG_unspecified_parameters = 0x18 COMMA
+    DW_TAG_variant = 0x19 COMMA
+    DW_TAG_common_block = 0x1a COMMA
+    DW_TAG_common_inclusion = 0x1b COMMA
+    DW_TAG_inheritance = 0x1c COMMA
+    DW_TAG_inlined_subroutine = 0x1d COMMA
+    DW_TAG_module = 0x1e COMMA
+    DW_TAG_ptr_to_member_type = 0x1f COMMA
+    DW_TAG_set_type = 0x20 COMMA
+    DW_TAG_subrange_type = 0x21 COMMA
+    DW_TAG_with_stmt = 0x22 COMMA
+    DW_TAG_access_declaration = 0x23 COMMA
+    DW_TAG_base_type = 0x24 COMMA
+    DW_TAG_catch_block = 0x25 COMMA
+    DW_TAG_const_type = 0x26 COMMA
+    DW_TAG_constant = 0x27 COMMA
+    DW_TAG_enumerator = 0x28 COMMA
+    DW_TAG_file_type = 0x29 COMMA
+    DW_TAG_friend = 0x2a COMMA
+    DW_TAG_namelist = 0x2b COMMA
+    DW_TAG_namelist_item = 0x2c COMMA
+    DW_TAG_packed_type = 0x2d COMMA
+    DW_TAG_subprogram = 0x2e COMMA
+    DW_TAG_template_type_param = 0x2f COMMA
+    DW_TAG_template_value_param = 0x30 COMMA
+    DW_TAG_thrown_type = 0x31 COMMA
+    DW_TAG_try_block = 0x32 COMMA
+    DW_TAG_variant_part = 0x33 COMMA
+    DW_TAG_variable = 0x34 COMMA
+    DW_TAG_volatile_type = 0x35 COMMA
+    /* DWARF 3.  */
+    DW_TAG_dwarf_procedure = 0x36 COMMA
+    DW_TAG_restrict_type = 0x37 COMMA
+    DW_TAG_interface_type = 0x38 COMMA
+    DW_TAG_namespace = 0x39 COMMA
+    DW_TAG_imported_module = 0x3a COMMA
+    DW_TAG_unspecified_type = 0x3b COMMA
+    DW_TAG_partial_unit = 0x3c COMMA
+    DW_TAG_imported_unit = 0x3d COMMA
+    /* SGI/MIPS Extensions.  */
+    DW_TAG_MIPS_loop = 0x4081 COMMA
+    /* GNU extensions.	*/
+    DW_TAG_format_label = 0x4101 COMMA	/* For FORTRAN 77 and Fortran 90.  */
+    DW_TAG_function_template = 0x4102 COMMA	/* For C++.  */
+    DW_TAG_class_template = 0x4103 COMMA	/* For C++.  */
+    DW_TAG_GNU_BINCL = 0x4104 COMMA
+    DW_TAG_GNU_EINCL = 0x4105 COMMA
+    /* Extensions for UPC.  See: http://upc.gwu.edu/~upc.  */
+    DW_TAG_upc_shared_type = 0x8765 COMMA
+    DW_TAG_upc_strict_type = 0x8766 COMMA
+    DW_TAG_upc_relaxed_type = 0x8767
+IF_NOT_ASM(};)
+
+#define DW_TAG_lo_user	0x4080
+#define DW_TAG_hi_user	0xffff
+
+/* Flag that tells whether entry has a child or not.  */
+#define DW_children_no	 0
+#define	DW_children_yes  1
+
+/* Form names and codes.  */
+ENUM(dwarf_form)
+
+    DW_FORM_addr = 0x01 COMMA
+    DW_FORM_block2 = 0x03 COMMA
+    DW_FORM_block4 = 0x04 COMMA
+    DW_FORM_data2 = 0x05 COMMA
+    DW_FORM_data4 = 0x06 COMMA
+    DW_FORM_data8 = 0x07 COMMA
+    DW_FORM_string = 0x08 COMMA
+    DW_FORM_block = 0x09 COMMA
+    DW_FORM_block1 = 0x0a COMMA
+    DW_FORM_data1 = 0x0b COMMA
+    DW_FORM_flag = 0x0c COMMA
+    DW_FORM_sdata = 0x0d COMMA
+    DW_FORM_strp = 0x0e COMMA
+    DW_FORM_udata = 0x0f COMMA
+    DW_FORM_ref_addr = 0x10 COMMA
+    DW_FORM_ref1 = 0x11 COMMA
+    DW_FORM_ref2 = 0x12 COMMA
+    DW_FORM_ref4 = 0x13 COMMA
+    DW_FORM_ref8 = 0x14 COMMA
+    DW_FORM_ref_udata = 0x15 COMMA
+    DW_FORM_indirect = 0x16
+IF_NOT_ASM(};)
+
+/* Attribute names and codes.  */
+
+ENUM(dwarf_attribute)
+
+    DW_AT_sibling = 0x01 COMMA
+    DW_AT_location = 0x02 COMMA
+    DW_AT_name = 0x03 COMMA
+    DW_AT_ordering = 0x09 COMMA
+    DW_AT_subscr_data = 0x0a COMMA
+    DW_AT_byte_size = 0x0b COMMA
+    DW_AT_bit_offset = 0x0c COMMA
+    DW_AT_bit_size = 0x0d COMMA
+    DW_AT_element_list = 0x0f COMMA
+    DW_AT_stmt_list = 0x10 COMMA
+    DW_AT_low_pc = 0x11 COMMA
+    DW_AT_high_pc = 0x12 COMMA
+    DW_AT_language = 0x13 COMMA
+    DW_AT_member = 0x14 COMMA
+    DW_AT_discr = 0x15 COMMA
+    DW_AT_discr_value = 0x16 COMMA
+    DW_AT_visibility = 0x17 COMMA
+    DW_AT_import = 0x18 COMMA
+    DW_AT_string_length = 0x19 COMMA
+    DW_AT_common_reference = 0x1a COMMA
+    DW_AT_comp_dir = 0x1b COMMA
+    DW_AT_const_value = 0x1c COMMA
+    DW_AT_containing_type = 0x1d COMMA
+    DW_AT_default_value = 0x1e COMMA
+    DW_AT_inline = 0x20 COMMA
+    DW_AT_is_optional = 0x21 COMMA
+    DW_AT_lower_bound = 0x22 COMMA
+    DW_AT_producer = 0x25 COMMA
+    DW_AT_prototyped = 0x27 COMMA
+    DW_AT_return_addr = 0x2a COMMA
+    DW_AT_start_scope = 0x2c COMMA
+    DW_AT_stride_size = 0x2e COMMA
+    DW_AT_upper_bound = 0x2f COMMA
+    DW_AT_abstract_origin = 0x31 COMMA
+    DW_AT_accessibility = 0x32 COMMA
+    DW_AT_address_class = 0x33 COMMA
+    DW_AT_artificial = 0x34 COMMA
+    DW_AT_base_types = 0x35 COMMA
+    DW_AT_calling_convention = 0x36 COMMA
+    DW_AT_count = 0x37 COMMA
+    DW_AT_data_member_location = 0x38 COMMA
+    DW_AT_decl_column = 0x39 COMMA
+    DW_AT_decl_file = 0x3a COMMA
+    DW_AT_decl_line = 0x3b COMMA
+    DW_AT_declaration = 0x3c COMMA
+    DW_AT_discr_list = 0x3d COMMA
+    DW_AT_encoding = 0x3e COMMA
+    DW_AT_external = 0x3f COMMA
+    DW_AT_frame_base = 0x40 COMMA
+    DW_AT_friend = 0x41 COMMA
+    DW_AT_identifier_case = 0x42 COMMA
+    DW_AT_macro_info = 0x43 COMMA
+    DW_AT_namelist_items = 0x44 COMMA
+    DW_AT_priority = 0x45 COMMA
+    DW_AT_segment = 0x46 COMMA
+    DW_AT_specification = 0x47 COMMA
+    DW_AT_static_link = 0x48 COMMA
+    DW_AT_type = 0x49 COMMA
+    DW_AT_use_location = 0x4a COMMA
+    DW_AT_variable_parameter = 0x4b COMMA
+    DW_AT_virtuality = 0x4c COMMA
+    DW_AT_vtable_elem_location = 0x4d COMMA
+    /* DWARF 3 values.	*/
+    DW_AT_allocated	= 0x4e COMMA
+    DW_AT_associated	= 0x4f COMMA
+    DW_AT_data_location = 0x50 COMMA
+    DW_AT_stride	= 0x51 COMMA
+    DW_AT_entry_pc	= 0x52 COMMA
+    DW_AT_use_UTF8	= 0x53 COMMA
+    DW_AT_extension	= 0x54 COMMA
+    DW_AT_ranges	= 0x55 COMMA
+    DW_AT_trampoline	= 0x56 COMMA
+    DW_AT_call_column	= 0x57 COMMA
+    DW_AT_call_file	= 0x58 COMMA
+    DW_AT_call_line	= 0x59 COMMA
+    /* SGI/MIPS extensions.  */
+    DW_AT_MIPS_fde = 0x2001 COMMA
+    DW_AT_MIPS_loop_begin = 0x2002 COMMA
+    DW_AT_MIPS_tail_loop_begin = 0x2003 COMMA
+    DW_AT_MIPS_epilog_begin = 0x2004 COMMA
+    DW_AT_MIPS_loop_unroll_factor = 0x2005 COMMA
+    DW_AT_MIPS_software_pipeline_depth = 0x2006 COMMA
+    DW_AT_MIPS_linkage_name = 0x2007 COMMA
+    DW_AT_MIPS_stride = 0x2008 COMMA
+    DW_AT_MIPS_abstract_name = 0x2009 COMMA
+    DW_AT_MIPS_clone_origin = 0x200a COMMA
+    DW_AT_MIPS_has_inlines = 0x200b COMMA
+    /* GNU extensions.	*/
+    DW_AT_sf_names   = 0x2101 COMMA
+    DW_AT_src_info   = 0x2102 COMMA
+    DW_AT_mac_info   = 0x2103 COMMA
+    DW_AT_src_coords = 0x2104 COMMA
+    DW_AT_body_begin = 0x2105 COMMA
+    DW_AT_body_end   = 0x2106 COMMA
+    DW_AT_GNU_vector = 0x2107 COMMA
+    /* VMS extensions.	*/
+    DW_AT_VMS_rtnbeg_pd_address = 0x2201 COMMA
+    /* UPC extension.  */
+    DW_AT_upc_threads_scaled = 0x3210
+IF_NOT_ASM(};)
+
+#define DW_AT_lo_user	0x2000	/* Implementation-defined range start.	*/
+#define DW_AT_hi_user	0x3ff0	/* Implementation-defined range end.  */
+
+/* Location atom names and codes.  */
+ENUM(dwarf_location_atom)
+
+    DW_OP_addr = 0x03 COMMA
+    DW_OP_deref = 0x06 COMMA
+    DW_OP_const1u = 0x08 COMMA
+    DW_OP_const1s = 0x09 COMMA
+    DW_OP_const2u = 0x0a COMMA
+    DW_OP_const2s = 0x0b COMMA
+    DW_OP_const4u = 0x0c COMMA
+    DW_OP_const4s = 0x0d COMMA
+    DW_OP_const8u = 0x0e COMMA
+    DW_OP_const8s = 0x0f COMMA
+    DW_OP_constu = 0x10 COMMA
+    DW_OP_consts = 0x11 COMMA
+    DW_OP_dup = 0x12 COMMA
+    DW_OP_drop = 0x13 COMMA
+    DW_OP_over = 0x14 COMMA
+    DW_OP_pick = 0x15 COMMA
+    DW_OP_swap = 0x16 COMMA
+    DW_OP_rot = 0x17 COMMA
+    DW_OP_xderef = 0x18 COMMA
+    DW_OP_abs = 0x19 COMMA
+    DW_OP_and = 0x1a COMMA
+    DW_OP_div = 0x1b COMMA
+    DW_OP_minus = 0x1c COMMA
+    DW_OP_mod = 0x1d COMMA
+    DW_OP_mul = 0x1e COMMA
+    DW_OP_neg = 0x1f COMMA
+    DW_OP_not = 0x20 COMMA
+    DW_OP_or = 0x21 COMMA
+    DW_OP_plus = 0x22 COMMA
+    DW_OP_plus_uconst = 0x23 COMMA
+    DW_OP_shl = 0x24 COMMA
+    DW_OP_shr = 0x25 COMMA
+    DW_OP_shra = 0x26 COMMA
+    DW_OP_xor = 0x27 COMMA
+    DW_OP_bra = 0x28 COMMA
+    DW_OP_eq = 0x29 COMMA
+    DW_OP_ge = 0x2a COMMA
+    DW_OP_gt = 0x2b COMMA
+    DW_OP_le = 0x2c COMMA
+    DW_OP_lt = 0x2d COMMA
+    DW_OP_ne = 0x2e COMMA
+    DW_OP_skip = 0x2f COMMA
+    DW_OP_lit0 = 0x30 COMMA
+    DW_OP_lit1 = 0x31 COMMA
+    DW_OP_lit2 = 0x32 COMMA
+    DW_OP_lit3 = 0x33 COMMA
+    DW_OP_lit4 = 0x34 COMMA
+    DW_OP_lit5 = 0x35 COMMA
+    DW_OP_lit6 = 0x36 COMMA
+    DW_OP_lit7 = 0x37 COMMA
+    DW_OP_lit8 = 0x38 COMMA
+    DW_OP_lit9 = 0x39 COMMA
+    DW_OP_lit10 = 0x3a COMMA
+    DW_OP_lit11 = 0x3b COMMA
+    DW_OP_lit12 = 0x3c COMMA
+    DW_OP_lit13 = 0x3d COMMA
+    DW_OP_lit14 = 0x3e COMMA
+    DW_OP_lit15 = 0x3f COMMA
+    DW_OP_lit16 = 0x40 COMMA
+    DW_OP_lit17 = 0x41 COMMA
+    DW_OP_lit18 = 0x42 COMMA
+    DW_OP_lit19 = 0x43 COMMA
+    DW_OP_lit20 = 0x44 COMMA
+    DW_OP_lit21 = 0x45 COMMA
+    DW_OP_lit22 = 0x46 COMMA
+    DW_OP_lit23 = 0x47 COMMA
+    DW_OP_lit24 = 0x48 COMMA
+    DW_OP_lit25 = 0x49 COMMA
+    DW_OP_lit26 = 0x4a COMMA
+    DW_OP_lit27 = 0x4b COMMA
+    DW_OP_lit28 = 0x4c COMMA
+    DW_OP_lit29 = 0x4d COMMA
+    DW_OP_lit30 = 0x4e COMMA
+    DW_OP_lit31 = 0x4f COMMA
+    DW_OP_reg0 = 0x50 COMMA
+    DW_OP_reg1 = 0x51 COMMA
+    DW_OP_reg2 = 0x52 COMMA
+    DW_OP_reg3 = 0x53 COMMA
+    DW_OP_reg4 = 0x54 COMMA
+    DW_OP_reg5 = 0x55 COMMA
+    DW_OP_reg6 = 0x56 COMMA
+    DW_OP_reg7 = 0x57 COMMA
+    DW_OP_reg8 = 0x58 COMMA
+    DW_OP_reg9 = 0x59 COMMA
+    DW_OP_reg10 = 0x5a COMMA
+    DW_OP_reg11 = 0x5b COMMA
+    DW_OP_reg12 = 0x5c COMMA
+    DW_OP_reg13 = 0x5d COMMA
+    DW_OP_reg14 = 0x5e COMMA
+    DW_OP_reg15 = 0x5f COMMA
+    DW_OP_reg16 = 0x60 COMMA
+    DW_OP_reg17 = 0x61 COMMA
+    DW_OP_reg18 = 0x62 COMMA
+    DW_OP_reg19 = 0x63 COMMA
+    DW_OP_reg20 = 0x64 COMMA
+    DW_OP_reg21 = 0x65 COMMA
+    DW_OP_reg22 = 0x66 COMMA
+    DW_OP_reg23 = 0x67 COMMA
+    DW_OP_reg24 = 0x68 COMMA
+    DW_OP_reg25 = 0x69 COMMA
+    DW_OP_reg26 = 0x6a COMMA
+    DW_OP_reg27 = 0x6b COMMA
+    DW_OP_reg28 = 0x6c COMMA
+    DW_OP_reg29 = 0x6d COMMA
+    DW_OP_reg30 = 0x6e COMMA
+    DW_OP_reg31 = 0x6f COMMA
+    DW_OP_breg0 = 0x70 COMMA
+    DW_OP_breg1 = 0x71 COMMA
+    DW_OP_breg2 = 0x72 COMMA
+    DW_OP_breg3 = 0x73 COMMA
+    DW_OP_breg4 = 0x74 COMMA
+    DW_OP_breg5 = 0x75 COMMA
+    DW_OP_breg6 = 0x76 COMMA
+    DW_OP_breg7 = 0x77 COMMA
+    DW_OP_breg8 = 0x78 COMMA
+    DW_OP_breg9 = 0x79 COMMA
+    DW_OP_breg10 = 0x7a COMMA
+    DW_OP_breg11 = 0x7b COMMA
+    DW_OP_breg12 = 0x7c COMMA
+    DW_OP_breg13 = 0x7d COMMA
+    DW_OP_breg14 = 0x7e COMMA
+    DW_OP_breg15 = 0x7f COMMA
+    DW_OP_breg16 = 0x80 COMMA
+    DW_OP_breg17 = 0x81 COMMA
+    DW_OP_breg18 = 0x82 COMMA
+    DW_OP_breg19 = 0x83 COMMA
+    DW_OP_breg20 = 0x84 COMMA
+    DW_OP_breg21 = 0x85 COMMA
+    DW_OP_breg22 = 0x86 COMMA
+    DW_OP_breg23 = 0x87 COMMA
+    DW_OP_breg24 = 0x88 COMMA
+    DW_OP_breg25 = 0x89 COMMA
+    DW_OP_breg26 = 0x8a COMMA
+    DW_OP_breg27 = 0x8b COMMA
+    DW_OP_breg28 = 0x8c COMMA
+    DW_OP_breg29 = 0x8d COMMA
+    DW_OP_breg30 = 0x8e COMMA
+    DW_OP_breg31 = 0x8f COMMA
+    DW_OP_regx = 0x90 COMMA
+    DW_OP_fbreg = 0x91 COMMA
+    DW_OP_bregx = 0x92 COMMA
+    DW_OP_piece = 0x93 COMMA
+    DW_OP_deref_size = 0x94 COMMA
+    DW_OP_xderef_size = 0x95 COMMA
+    DW_OP_nop = 0x96 COMMA
+    /* DWARF 3 extensions.  */
+    DW_OP_push_object_address = 0x97 COMMA
+    DW_OP_call2 = 0x98 COMMA
+    DW_OP_call4 = 0x99 COMMA
+    DW_OP_call_ref = 0x9a COMMA
+    /* GNU extensions.	*/
+    DW_OP_GNU_push_tls_address = 0xe0
+IF_NOT_ASM(};)
+
+#define DW_OP_lo_user	0xe0	/* Implementation-defined range start.	*/
+#define DW_OP_hi_user	0xff	/* Implementation-defined range end.  */
+
+/* Type encodings.  */
+ENUM(dwarf_type)
+
+    DW_ATE_void = 0x0 COMMA
+    DW_ATE_address = 0x1 COMMA
+    DW_ATE_boolean = 0x2 COMMA
+    DW_ATE_complex_float = 0x3 COMMA
+    DW_ATE_float = 0x4 COMMA
+    DW_ATE_signed = 0x5 COMMA
+    DW_ATE_signed_char = 0x6 COMMA
+    DW_ATE_unsigned = 0x7 COMMA
+    DW_ATE_unsigned_char = 0x8 COMMA
+    /* DWARF 3.  */
+    DW_ATE_imaginary_float = 0x9
+IF_NOT_ASM(};)
+
+#define	DW_ATE_lo_user 0x80
+#define	DW_ATE_hi_user 0xff
+
+/* Array ordering names and codes.  */
+ENUM(dwarf_array_dim_ordering)
+
+    DW_ORD_row_major = 0 COMMA
+    DW_ORD_col_major = 1
+IF_NOT_ASM(};)
+
+/* Access attribute.  */
+ENUM(dwarf_access_attribute)
+
+    DW_ACCESS_public = 1 COMMA
+    DW_ACCESS_protected = 2 COMMA
+    DW_ACCESS_private = 3
+IF_NOT_ASM(};)
+
+/* Visibility.	*/
+ENUM(dwarf_visibility_attribute)
+
+    DW_VIS_local = 1 COMMA
+    DW_VIS_exported = 2 COMMA
+    DW_VIS_qualified = 3
+IF_NOT_ASM(};)
+
+/* Virtuality.	*/
+ENUM(dwarf_virtuality_attribute)
+
+    DW_VIRTUALITY_none = 0 COMMA
+    DW_VIRTUALITY_virtual = 1 COMMA
+    DW_VIRTUALITY_pure_virtual = 2
+IF_NOT_ASM(};)
+
+/* Case sensitivity.  */
+ENUM(dwarf_id_case)
+
+    DW_ID_case_sensitive = 0 COMMA
+    DW_ID_up_case = 1 COMMA
+    DW_ID_down_case = 2 COMMA
+    DW_ID_case_insensitive = 3
+IF_NOT_ASM(};)
+
+/* Calling convention.	*/
+ENUM(dwarf_calling_convention)
+
+    DW_CC_normal = 0x1 COMMA
+    DW_CC_program = 0x2 COMMA
+    DW_CC_nocall = 0x3
+IF_NOT_ASM(};)
+
+#define DW_CC_lo_user 0x40
+#define DW_CC_hi_user 0xff
+
+/* Inline attribute.  */
+ENUM(dwarf_inline_attribute)
+
+    DW_INL_not_inlined = 0 COMMA
+    DW_INL_inlined = 1 COMMA
+    DW_INL_declared_not_inlined = 2 COMMA
+    DW_INL_declared_inlined = 3
+IF_NOT_ASM(};)
+
+/* Discriminant lists.	*/
+ENUM(dwarf_discrim_list)
+
+    DW_DSC_label = 0 COMMA
+    DW_DSC_range = 1
+IF_NOT_ASM(};)
+
+/* Line number opcodes.  */
+ENUM(dwarf_line_number_ops)
+
+    DW_LNS_extended_op = 0 COMMA
+    DW_LNS_copy = 1 COMMA
+    DW_LNS_advance_pc = 2 COMMA
+    DW_LNS_advance_line = 3 COMMA
+    DW_LNS_set_file = 4 COMMA
+    DW_LNS_set_column = 5 COMMA
+    DW_LNS_negate_stmt = 6 COMMA
+    DW_LNS_set_basic_block = 7 COMMA
+    DW_LNS_const_add_pc = 8 COMMA
+    DW_LNS_fixed_advance_pc = 9 COMMA
+    /* DWARF 3.  */
+    DW_LNS_set_prologue_end = 10 COMMA
+    DW_LNS_set_epilogue_begin = 11 COMMA
+    DW_LNS_set_isa = 12
+IF_NOT_ASM(};)
+
+/* Line number extended opcodes.  */
+ENUM(dwarf_line_number_x_ops)
+
+    DW_LNE_end_sequence = 1 COMMA
+    DW_LNE_set_address = 2 COMMA
+    DW_LNE_define_file = 3
+IF_NOT_ASM(};)
+
+/* Call frame information.  */
+ENUM(dwarf_call_frame_info)
+
+    DW_CFA_advance_loc = 0x40 COMMA
+    DW_CFA_offset = 0x80 COMMA
+    DW_CFA_restore = 0xc0 COMMA
+    DW_CFA_nop = 0x00 COMMA
+    DW_CFA_set_loc = 0x01 COMMA
+    DW_CFA_advance_loc1 = 0x02 COMMA
+    DW_CFA_advance_loc2 = 0x03 COMMA
+    DW_CFA_advance_loc4 = 0x04 COMMA
+    DW_CFA_offset_extended = 0x05 COMMA
+    DW_CFA_restore_extended = 0x06 COMMA
+    DW_CFA_undefined = 0x07 COMMA
+    DW_CFA_same_value = 0x08 COMMA
+    DW_CFA_register = 0x09 COMMA
+    DW_CFA_remember_state = 0x0a COMMA
+    DW_CFA_restore_state = 0x0b COMMA
+    DW_CFA_def_cfa = 0x0c COMMA
+    DW_CFA_def_cfa_register = 0x0d COMMA
+    DW_CFA_def_cfa_offset = 0x0e COMMA
+
+    /* DWARF 3.  */
+    DW_CFA_def_cfa_expression = 0x0f COMMA
+    DW_CFA_expression = 0x10 COMMA
+    DW_CFA_offset_extended_sf = 0x11 COMMA
+    DW_CFA_def_cfa_sf = 0x12 COMMA
+    DW_CFA_def_cfa_offset_sf = 0x13 COMMA
+
+    /* SGI/MIPS specific.  */
+    DW_CFA_MIPS_advance_loc8 = 0x1d COMMA
+
+    /* GNU extensions.	*/
+    DW_CFA_GNU_window_save = 0x2d COMMA
+    DW_CFA_GNU_args_size = 0x2e COMMA
+    DW_CFA_GNU_negative_offset_extended = 0x2f
+IF_NOT_ASM(};)
+
+#define DW_CIE_ID	  0xffffffff
+#define DW_CIE_VERSION	  1
+
+#define DW_CFA_extended   0
+#define DW_CFA_lo_user	  0x1c
+#define DW_CFA_hi_user	  0x3f
+
+#define DW_CHILDREN_no		     0x00
+#define DW_CHILDREN_yes		     0x01
+
+#define DW_ADDR_none		0
+
+/* Source language names and codes.  */
+ENUM(dwarf_source_language)
+
+    DW_LANG_C89 = 0x0001 COMMA
+    DW_LANG_C = 0x0002 COMMA
+    DW_LANG_Ada83 = 0x0003 COMMA
+    DW_LANG_C_plus_plus = 0x0004 COMMA
+    DW_LANG_Cobol74 = 0x0005 COMMA
+    DW_LANG_Cobol85 = 0x0006 COMMA
+    DW_LANG_Fortran77 = 0x0007 COMMA
+    DW_LANG_Fortran90 = 0x0008 COMMA
+    DW_LANG_Pascal83 = 0x0009 COMMA
+    DW_LANG_Modula2 = 0x000a COMMA
+    DW_LANG_Java = 0x000b COMMA
+    /* DWARF 3.  */
+    DW_LANG_C99 = 0x000c COMMA
+    DW_LANG_Ada95 = 0x000d COMMA
+    DW_LANG_Fortran95 = 0x000e COMMA
+    /* MIPS.  */
+    DW_LANG_Mips_Assembler = 0x8001 COMMA
+    /* UPC.  */
+    DW_LANG_Upc = 0x8765
+IF_NOT_ASM(};)
+
+#define DW_LANG_lo_user 0x8000	/* Implementation-defined range start.	*/
+#define DW_LANG_hi_user 0xffff	/* Implementation-defined range start.	*/
+
+/* Names and codes for macro information.  */
+ENUM(dwarf_macinfo_record_type)
+
+    DW_MACINFO_define = 1 COMMA
+    DW_MACINFO_undef = 2 COMMA
+    DW_MACINFO_start_file = 3 COMMA
+    DW_MACINFO_end_file = 4 COMMA
+    DW_MACINFO_vendor_ext = 255
+IF_NOT_ASM(};)
+
+/* @@@ For use with GNU frame unwind information.  */
+
+#define DW_EH_PE_absptr		0x00
+#define DW_EH_PE_omit		0xff
+
+#define DW_EH_PE_uleb128	0x01
+#define DW_EH_PE_udata2		0x02
+#define DW_EH_PE_udata4		0x03
+#define DW_EH_PE_udata8		0x04
+#define DW_EH_PE_sleb128	0x09
+#define DW_EH_PE_sdata2		0x0A
+#define DW_EH_PE_sdata4		0x0B
+#define DW_EH_PE_sdata8		0x0C
+#define DW_EH_PE_signed		0x08
+
+#define DW_EH_PE_pcrel		0x10
+#define DW_EH_PE_textrel	0x20
+#define DW_EH_PE_datarel	0x30
+#define DW_EH_PE_funcrel	0x40
+#define DW_EH_PE_aligned	0x50
+
+#define DW_EH_PE_indirect	0x80
+
+#endif /* _ELF_DWARF2_H */
--- diff/include/linux/kthread.h	1970-01-01 01:00:00.000000000 +0100
+++ source/include/linux/kthread.h	2004-02-23 13:56:47.000000000 +0000
@@ -0,0 +1,81 @@
+#ifndef _LINUX_KTHREAD_H
+#define _LINUX_KTHREAD_H
+/* Simple interface for creating and stopping kernel threads without mess. */
+#include <linux/err.h>
+#include <linux/sched.h>
+
+/**
+ * kthread_create: create a kthread.
+ * @threadfn: the function to run until signal_pending(current).
+ * @data: data ptr for @threadfn.
+ * @namefmt: printf-style name for the thread.
+ *
+ * Description: This helper function creates and names a kernel
+ * thread.  The thread will be stopped: use wake_up_process() to start
+ * it.  See also kthread_run(), kthread_create_on_cpu().
+ *
+ * When woken, the thread will run @threadfn() with @data as its
+ * argument. @threadfn can either call do_exit() directly if it is a
+ * standalone thread for which noone will call kthread_stop(), or
+ * return when 'kthread_should_stop()' is true (which means
+ * kthread_stop() has been called).  The return value should be zero
+ * or a negative error number: it will be passed to kthread_stop().
+ *
+ * Returns a task_struct or ERR_PTR(-ENOMEM).
+ */
+struct task_struct *kthread_create(int (*threadfn)(void *data),
+				   void *data,
+				   const char namefmt[], ...);
+
+/**
+ * kthread_run: create and wake a thread.
+ * @threadfn: the function to run until signal_pending(current).
+ * @data: data ptr for @threadfn.
+ * @namefmt: printf-style name for the thread.
+ *
+ * Description: Convenient wrapper for kthread_create() followed by
+ * wake_up_process().  Returns the kthread, or ERR_PTR(-ENOMEM). */
+#define kthread_run(threadfn, data, namefmt, ...)			   \
+({									   \
+	struct task_struct *__k						   \
+		= kthread_create(threadfn, data, namefmt, ## __VA_ARGS__); \
+	if (!IS_ERR(__k))						   \
+		wake_up_process(__k);					   \
+	__k;								   \
+})
+
+/**
+ * kthread_bind: bind a just-created kthread to a cpu.
+ * @k: thread created by kthread_create().
+ * @cpu: cpu (might not be online, must be possible) for @k to run on.
+ *
+ * Description: This function is equivalent to set_cpus_allowed(),
+ * except that @cpu doesn't need to be online, and the thread must be
+ * stopped (ie. just returned from kthread_create().
+ */
+void kthread_bind(struct task_struct *k, unsigned int cpu);
+
+/**
+ * kthread_stop: stop a thread created by kthread_create().
+ * @k: thread created by kthread_create().
+ *
+ * Sets kthread_should_stop() for @k to return true, wakes it, and
+ * waits for it to exit.  Your threadfn() must not call do_exit()
+ * itself if you use this function!  This can also be called after
+ * kthread_create() instead of calling wake_up_process(): the thread
+ * will exit without calling threadfn().
+ *
+ * Returns the result of threadfn(), or -EINTR if wake_up_process()
+ * was never called. */
+int kthread_stop(struct task_struct *k);
+
+/**
+ * kthread_should_stop: should this kthread return now?
+ *
+ * When someone calls kthread_stop on your kthread, it will be woken
+ * and this will return true.  You should then return, and your return
+ * value will be passed through to kthread_stop().
+ */
+int kthread_should_stop(void);
+
+#endif /* _LINUX_KTHREAD_H */
--- diff/include/linux/lockmeter.h	1970-01-01 01:00:00.000000000 +0100
+++ source/include/linux/lockmeter.h	2004-02-23 13:56:47.000000000 +0000
@@ -0,0 +1,320 @@
+/*
+ *  Copyright (C) 1999-2002 Silicon Graphics, Inc.
+ *
+ *  Written by John Hawkes (hawkes@sgi.com)
+ *  Based on klstat.h by Jack Steiner (steiner@sgi.com)
+ *
+ *  Modified by Ray Bryant (raybry@us.ibm.com) Feb-Apr 2000
+ *  Changes Copyright (C) 2000 IBM, Inc.
+ *  Added save of index in spinlock_t to improve efficiency
+ *  of "hold" time reporting for spinlocks
+ *  Added support for hold time statistics for read and write
+ *  locks.
+ *  Moved machine dependent code to include/asm/lockmeter.h.
+ *
+ */
+
+#ifndef _LINUX_LOCKMETER_H
+#define _LINUX_LOCKMETER_H
+
+
+/*---------------------------------------------------
+ *	architecture-independent lockmeter.h
+ *-------------------------------------------------*/
+
+/*
+ * raybry -- version 2: added efficient hold time statistics
+ *           requires lstat recompile, so flagged as new version
+ * raybry -- version 3: added global reader lock data
+ * hawkes -- version 4: removed some unnecessary fields to simplify mips64 port
+ */
+#define LSTAT_VERSION	5
+
+int	lstat_update(void*, void*, int);
+int	lstat_update_time(void*, void*, int, uint32_t);
+
+/*
+ * Currently, the mips64 and sparc64 kernels talk to a 32-bit lockstat, so we
+ * need to force compatibility in the inter-communication data structure.
+ */
+
+#if defined(CONFIG_MIPS32_COMPAT)
+#define TIME_T		uint32_t
+#elif defined(CONFIG_SPARC) || defined(CONFIG_SPARC64)
+#define TIME_T		uint64_t
+#else
+#define TIME_T		time_t
+#endif
+
+#if defined(__KERNEL__) || (!defined(CONFIG_MIPS32_COMPAT) && !defined(CONFIG_SPARC) && !defined(CONFIG_SPARC64)) || (_MIPS_SZLONG==32)
+#define POINTER		void *
+#else
+#define	POINTER		int64_t
+#endif
+
+/*
+ * Values for the "action" parameter passed to lstat_update.
+ *	ZZZ - do we want a try-success status here???
+ */
+#define LSTAT_ACT_NO_WAIT	0
+#define LSTAT_ACT_SPIN		1
+#define LSTAT_ACT_REJECT	2
+#define LSTAT_ACT_WW_SPIN       3
+#define LSTAT_ACT_SLEPT		4 /* UNUSED */
+
+#define LSTAT_ACT_MAX_VALUES	4 /* NOTE: Increase to 5 if use ACT_SLEPT */
+
+/*
+ * Special values for the low 2 bits of an RA passed to
+ * lstat_update.
+ */
+/* we use these values to figure out what kind of lock data */
+/* is stored in the statistics table entry at index ....... */
+#define LSTAT_RA_SPIN           0  /* spin lock data */
+#define LSTAT_RA_READ           1  /* read lock statistics */
+#define LSTAT_RA_SEMA		2  /* RESERVED */
+#define LSTAT_RA_WRITE          3  /* write lock statistics*/
+
+#define LSTAT_RA(n)	\
+	((void*)( ((unsigned long)__builtin_return_address(0) & ~3) | n) )
+
+/*
+ * Constants used for lock addresses in the lstat_directory
+ * to indicate special values of the lock address.
+ */
+#define	LSTAT_MULTI_LOCK_ADDRESS	NULL
+
+/*
+ * Maximum size of the lockstats tables. Increase this value
+ * if its not big enough. (Nothing bad happens if its not
+ * big enough although some locks will not be monitored.)
+ * We record overflows of this quantity in lstat_control.dir_overflows
+ *
+ * Note:  The max value here must fit into the field set
+ * and obtained by the macro's PUT_INDEX() and GET_INDEX().
+ * This value depends on how many bits are available in the
+ * lock word in the particular machine implementation we are on.
+ */
+#define LSTAT_MAX_STAT_INDEX		2000
+
+/*
+ * Size and mask for the hash table into the directory.
+ */
+#define LSTAT_HASH_TABLE_SIZE		4096		/* must be 2**N */
+#define LSTAT_HASH_TABLE_MASK		(LSTAT_HASH_TABLE_SIZE-1)
+
+#define DIRHASH(ra)      ((unsigned long)(ra)>>2 & LSTAT_HASH_TABLE_MASK)
+
+/*
+ *	This defines an entry in the lockstat directory. It contains
+ *	information about a lock being monitored.
+ *	A directory entry only contains the lock identification -
+ *	counts on usage of the lock are kept elsewhere in a per-cpu
+ *	data structure to minimize cache line pinging.
+ */
+typedef struct {
+	POINTER	caller_ra;		  /* RA of code that set lock */
+	POINTER	lock_ptr;		  /* lock address */
+	ushort	next_stat_index;  /* Used to link multiple locks that have the same hash table value */
+} lstat_directory_entry_t;
+
+/*
+ *	A multi-dimensioned array used to contain counts for lock accesses.
+ *	The array is 3-dimensional:
+ *		- CPU number. Keep from thrashing cache lines between CPUs
+ *		- Directory entry index. Identifies the lock
+ *		- Action. Indicates what kind of contention occurred on an
+ *		  access to the lock.
+ *
+ *	The index of an entry in the directory is the same as the 2nd index
+ *	of the entry in the counts array.
+ */
+/*
+ *  This table contains data for spin_locks, write locks, and read locks
+ *  Not all data is used for all cases.  In particular, the hold time
+ *  information is not stored here for read locks since that is a global
+ *  (e. g. cannot be separated out by return address) quantity.
+ *  See the lstat_read_lock_counts_t structure for the global read lock
+ *  hold time.
+ */
+typedef struct {
+	uint64_t    cum_wait_ticks;	/* sum of wait times               */
+	                                /* for write locks, sum of time a  */
+					/* writer is waiting for a reader  */
+	int64_t	    cum_hold_ticks;	/* cumulative sum of holds         */
+	                                /* not used for read mode locks    */
+					/* must be signed. ............... */
+	uint32_t    max_wait_ticks;	/* max waiting time                */
+	uint32_t    max_hold_ticks;	/* max holding time                */
+	uint64_t    cum_wait_ww_ticks;  /* sum times writer waits on writer*/
+	uint32_t    max_wait_ww_ticks;  /* max wait time writer vs writer  */
+	                                /* prev 2 only used for write locks*/
+	uint32_t    acquire_time;       /* time lock acquired this CPU     */
+	uint32_t    count[LSTAT_ACT_MAX_VALUES];
+} lstat_lock_counts_t;
+
+typedef lstat_lock_counts_t	lstat_cpu_counts_t[LSTAT_MAX_STAT_INDEX];
+
+/*
+ * User request to:
+ *	- turn statistic collection on/off, or to reset
+ */
+#define LSTAT_OFF	 0
+#define LSTAT_ON	 1
+#define LSTAT_RESET      2
+#define LSTAT_RELEASE    3
+
+#define LSTAT_MAX_READ_LOCK_INDEX 1000
+typedef struct {
+	POINTER	    lock_ptr;            /* address of lock for output stats */
+	uint32_t    read_lock_count;
+	int64_t     cum_hold_ticks;       /* sum of read lock hold times over */
+	                                  /* all callers. ....................*/
+	uint32_t    write_index;          /* last write lock hash table index */
+	uint32_t    busy_periods;         /* count of busy periods ended this */
+	uint64_t    start_busy;           /* time this busy period started. ..*/
+	uint64_t    busy_ticks;           /* sum of busy periods this lock. ..*/
+	uint64_t    max_busy;             /* longest busy period for this lock*/
+	uint32_t    max_readers;          /* maximum number of readers ...... */
+#ifdef USER_MODE_TESTING
+	rwlock_t    entry_lock;           /* lock for this read lock entry... */
+	                                  /* avoid having more than one rdr at*/
+	                                  /* needed for user space testing... */
+	                                  /* not needed for kernel 'cause it  */
+					  /* is non-preemptive. ............. */
+#endif
+} lstat_read_lock_counts_t;
+typedef lstat_read_lock_counts_t	lstat_read_lock_cpu_counts_t[LSTAT_MAX_READ_LOCK_INDEX];
+
+#if defined(__KERNEL__) || defined(USER_MODE_TESTING)
+
+#ifndef USER_MODE_TESTING
+#include <asm/lockmeter.h>
+#else
+#include "asm_newlockmeter.h"
+#endif
+
+/*
+ * Size and mask for the hash table into the directory.
+ */
+#define LSTAT_HASH_TABLE_SIZE		4096		/* must be 2**N */
+#define LSTAT_HASH_TABLE_MASK		(LSTAT_HASH_TABLE_SIZE-1)
+
+#define DIRHASH(ra)      ((unsigned long)(ra)>>2 & LSTAT_HASH_TABLE_MASK)
+
+/*
+ * This version eliminates the per processor lock stack.  What we do is to
+ * store the index of the lock hash structure in unused bits in the lock
+ * itself.  Then on unlock we can find the statistics record without doing
+ * any additional hash or lock stack lookup.  This works for spin_locks.
+ * Hold time reporting is now basically as cheap as wait time reporting
+ * so we ignore the difference between LSTAT_ON_HOLD and LSTAT_ON_WAIT
+ * as in version 1.1.* of lockmeter.
+ *
+ * For rw_locks, we store the index of a global reader stats structure in
+ * the lock and the writer index is stored in the latter structure.
+ * For read mode locks we hash at the time of the lock to find an entry
+ * in the directory for reader wait time and the like.
+ * At unlock time for read mode locks, we update just the global structure
+ * so we don't need to know the reader directory index value at unlock time.
+ *
+ */
+
+/*
+ * Protocol to change lstat_control.state
+ *   This is complicated because we don't want the cum_hold_time for
+ * a rw_lock to be decremented in _read_lock_ without making sure it
+ * is incremented in _read_lock_ and vice versa.  So here is the
+ * way we change the state of lstat_control.state:
+ * I.  To Turn Statistics On
+ *     After allocating storage, set lstat_control.state non-zero.
+ * This works because we don't start updating statistics for in use
+ * locks until the reader lock count goes to zero.
+ * II. To Turn Statistics Off:
+ * (0)  Disable interrupts on this CPU
+ * (1)  Seize the lstat_control.directory_lock
+ * (2)  Obtain the current value of lstat_control.next_free_read_lock_index
+ * (3)  Store a zero in lstat_control.state.
+ * (4)  Release the lstat_control.directory_lock
+ * (5)  For each lock in the read lock list up to the saved value
+ *      (well, -1) of the next_free_read_lock_index, do the following:
+ *      (a)  Check validity of the stored lock address
+ *           by making sure that the word at the saved addr
+ *           has an index that matches this entry.  If not
+ *           valid, then skip this entry.
+ *      (b)  If there is a write lock already set on this lock,
+ *           skip to (d) below.
+ *      (c)  Set a non-metered write lock on the lock
+ *      (d)  set the cached INDEX in the lock to zero
+ *      (e)  Release the non-metered write lock.
+ * (6)  Re-enable interrupts
+ *
+ * These rules ensure that a read lock will not have its statistics
+ * partially updated even though the global lock recording state has
+ * changed.  See put_lockmeter_info() for implementation.
+ *
+ * The reason for (b) is that there may be write locks set on the
+ * syscall path to put_lockmeter_info() from user space.  If we do
+ * not do this check, then we can deadlock.  A similar problem would
+ * occur if the lock was read locked by the current CPU.  At the
+ * moment this does not appear to happen.
+ */
+
+/*
+ * Main control structure for lockstat. Used to turn statistics on/off
+ * and to maintain directory info.
+ */
+typedef struct {
+	int				state;
+	spinlock_t		control_lock;		/* used to serialize turning statistics on/off   */
+	spinlock_t		directory_lock;		/* for serialize adding entries to directory     */
+	volatile int	next_free_dir_index;/* next free entry in the directory */
+	/* FIXME not all of these fields are used / needed .............. */
+                /* the following fields represent data since     */
+		/* first "lstat on" or most recent "lstat reset" */
+	TIME_T      first_started_time;     /* time when measurement first enabled */
+	TIME_T      started_time;           /* time when measurement last started  */
+	TIME_T      ending_time;            /* time when measurement last disabled */
+	uint64_t    started_cycles64;       /* cycles when measurement last started          */
+	uint64_t    ending_cycles64;        /* cycles when measurement last disabled         */
+	uint64_t    enabled_cycles64;       /* total cycles with measurement enabled         */
+	int         intervals;              /* number of measurement intervals recorded      */
+	                                    /* i. e. number of times did lstat on;lstat off  */
+	lstat_directory_entry_t	*dir;		/* directory */
+	int         dir_overflow;           /* count of times ran out of space in directory  */
+	int         rwlock_overflow;        /* count of times we couldn't allocate a rw block*/
+	ushort		*hashtab;		 	    /* hash table for quick dir scans */
+	lstat_cpu_counts_t	*counts[NR_CPUS];	 /* Array of pointers to per-cpu stats */
+    int         next_free_read_lock_index;   /* next rwlock reader (global) stats block  */
+    lstat_read_lock_cpu_counts_t *read_lock_counts[NR_CPUS]; /* per cpu read lock stats  */
+} lstat_control_t;
+
+#endif	/* defined(__KERNEL__) || defined(USER_MODE_TESTING) */
+
+typedef struct {
+	short		lstat_version;		/* version of the data */
+	short		state;			/* the current state is returned */
+	int		maxcpus;		/* Number of cpus present */
+	int		next_free_dir_index;	/* index of the next free directory entry */
+	TIME_T          first_started_time;	/* when measurement enabled for first time */
+	TIME_T          started_time;		/* time in secs since 1969 when stats last turned on  */
+	TIME_T		ending_time;		/* time in secs since 1969 when stats last turned off */
+	uint32_t	cycleval;		/* cycles per second */
+#ifdef notyet
+	void		*kernel_magic_addr;	/* address of kernel_magic */
+	void		*kernel_end_addr;	/* contents of kernel magic (points to "end") */
+#endif
+	int              next_free_read_lock_index; /* index of next (global) read lock stats struct */
+	uint64_t         started_cycles64;	/* cycles when measurement last started        */
+	uint64_t         ending_cycles64;	/* cycles when stats last turned off           */
+	uint64_t         enabled_cycles64;	/* total cycles with measurement enabled       */
+	int              intervals;		/* number of measurement intervals recorded      */
+						/* i.e. number of times we did lstat on;lstat off*/
+	int              dir_overflow;		/* number of times we wanted more space in directory */
+	int              rwlock_overflow;	/* # of times we wanted more space in read_locks_count */
+	struct new_utsname   uts;		/* info about machine where stats are measured */
+						/* -T option of lockstat allows data to be     */
+						/* moved to another machine. ................. */
+} lstat_user_request_t;
+
+#endif /* _LINUX_LOCKMETER_H */
--- diff/include/linux/netpoll.h	1970-01-01 01:00:00.000000000 +0100
+++ source/include/linux/netpoll.h	2004-02-23 13:56:47.000000000 +0000
@@ -0,0 +1,38 @@
+/*
+ * Common code for low-level network console, dump, and debugger code
+ *
+ * Derived from netconsole, kgdb-over-ethernet, and netdump patches
+ */
+
+#ifndef _LINUX_NETPOLL_H
+#define _LINUX_NETPOLL_H
+
+#include <linux/netdevice.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/list.h>
+
+struct netpoll;
+
+struct netpoll {
+	struct net_device *dev;
+	char dev_name[16], *name;
+	void (*rx_hook)(struct netpoll *, int, char *, int);
+	u32 local_ip, remote_ip;
+	u16 local_port, remote_port;
+	unsigned char local_mac[6], remote_mac[6];
+	struct list_head rx_list;
+};
+
+void netpoll_poll(struct netpoll *np);
+void netpoll_send_skb(struct netpoll *np, struct sk_buff *skb);
+void netpoll_send_udp(struct netpoll *np, const char *msg, int len);
+int netpoll_parse_options(struct netpoll *np, char *opt);
+int netpoll_setup(struct netpoll *np);
+int netpoll_trap(void);
+void netpoll_set_trap(int trap);
+void netpoll_cleanup(struct netpoll *np);
+int netpoll_rx(struct sk_buff *skb);
+
+
+#endif
--- diff/include/linux/selinux_netlink.h	1970-01-01 01:00:00.000000000 +0100
+++ source/include/linux/selinux_netlink.h	2004-02-23 13:56:48.000000000 +0000
@@ -0,0 +1,37 @@
+/*
+ * Netlink event notifications for SELinux.
+ *
+ * Author: James Morris <jmorris@redhat.com>
+ *
+ * Copyright (C) 2004 Red Hat, Inc., James Morris <jmorris@redhat.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2,
+ * as published by the Free Software Foundation.
+ */
+#ifndef _LINUX_SELINUX_NETLINK_H
+#define _LINUX_SELINUX_NETLINK_H
+
+/* Message types. */
+#define SELNL_MSG_BASE 0x10
+enum {
+	SELNL_MSG_SETENFORCE = SELNL_MSG_BASE,
+	SELNL_MSG_POLICYLOAD,
+	SELNL_MSG_MAX
+};
+
+/* Multicast groups */
+#define SELNL_GRP_NONE		0x00000000
+#define SELNL_GRP_AVC		0x00000001	/* AVC notifications */
+#define SELNL_GRP_ALL		0xffffffff
+
+/* Message structures */
+struct selnl_msg_setenforce {
+	int32_t		val;
+};
+
+struct selnl_msg_policyload {
+	u_int32_t	seqno;
+};
+
+#endif /* _LINUX_SELINUX_NETLINK_H */
--- diff/include/linux/stop_machine.h	1970-01-01 01:00:00.000000000 +0100
+++ source/include/linux/stop_machine.h	2004-02-23 13:56:48.000000000 +0000
@@ -0,0 +1,52 @@
+#ifndef _LINUX_STOP_MACHINE
+#define _LINUX_STOP_MACHINE
+/* "Bogolock": stop the entire machine, disable interrupts.  This is a
+   very heavy lock, which is equivalent to grabbing every spinlock
+   (and more).  So the "read" side to such a lock is anything which
+   diables preeempt. */
+#include <linux/config.h>
+#include <linux/cpu.h>
+#include <asm/system.h>
+
+#ifdef CONFIG_SMP
+/**
+ * stop_machine_run: freeze the machine on all CPUs and run this function
+ * @fn: the function to run
+ * @data: the data ptr for the @fn()
+ * @cpu: the cpu to run @fn() on (or any, if @cpu == NR_CPUS.
+ *
+ * Description: This causes a thread to be scheduled on every other cpu,
+ * each of which disables interrupts, and finally interrupts are disabled
+ * on the current CPU.  The result is that noone is holding a spinlock
+ * or inside any other preempt-disabled region when @fn() runs.
+ *
+ * This can be thought of as a very heavy write lock, equivalent to
+ * grabbing every spinlock in the kernel. */
+int stop_machine_run(int (*fn)(void *), void *data, unsigned int cpu);
+
+/**
+ * __stop_machine_run: freeze the machine on all CPUs and run this function
+ * @fn: the function to run
+ * @data: the data ptr for the @fn
+ * @cpu: the cpu to run @fn on (or any, if @cpu == NR_CPUS.
+ *
+ * Description: This is a special version of the above, which returns the
+ * thread which has run @fn(): kthread_stop will return the return value
+ * of @fn().  Used by hotplug cpu.
+ */
+struct task_struct *__stop_machine_run(int (*fn)(void *), void *data,
+				       unsigned int cpu);
+
+#else
+
+static inline int stop_machine_run(int (*fn)(void *), void *data,
+				   unsigned int cpu)
+{
+	int ret;
+	local_irq_disable();
+	ret = fn(data);
+	local_irq_enable();
+	return ret;
+}
+#endif /* CONFIG_SMP */
+#endif /* _LINUX_STOP_MACHINE */
--- diff/include/linux/syscalls.h	1970-01-01 01:00:00.000000000 +0100
+++ source/include/linux/syscalls.h	2004-02-23 13:56:48.000000000 +0000
@@ -0,0 +1,480 @@
+/*
+ * syscalls.h - Linux syscall interfaces (non-arch-specific)
+ *
+ * Copyright (c) 2004 Randy Dunlap
+ * Copyright (c) 2004 Open Source Development Labs
+ *
+ * This file is released under the GPLv2.
+ * See the file COPYING for more details.
+ */
+
+#ifndef _LINUX_SYSCALLS_H
+#define _LINUX_SYSCALLS_H
+
+struct epoll_event;
+struct iattr;
+struct inode;
+struct iocb;
+struct io_event;
+struct iovec;
+struct itimerspec;
+struct itimerval;
+struct linux_dirent;
+struct linux_dirent64;
+struct list_head;
+struct msgbuf;
+struct msghdr;
+struct msqid_ds;
+struct new_utsname;
+struct nfsctl_arg;
+struct __old_kernel_stat;
+struct pollfd;
+struct rlimit;
+struct rusage;
+struct sched_param;
+struct semaphore;
+struct sembuf;
+struct shmid_ds;
+struct sockaddr;
+struct stat;
+struct stat64;
+struct statfs;
+struct statfs64;
+struct __sysctl_args;
+struct sysinfo;
+struct timespec;
+struct timeval;
+struct timex;
+struct timezone;
+struct tms;
+struct utimbuf;
+
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/aio_abi.h>
+#include <linux/capability.h>
+#include <linux/list.h>
+#include <linux/sem.h>
+#include <asm/semaphore.h>
+#include <asm/siginfo.h>
+#include <asm/signal.h>
+#include <linux/quota.h>
+
+asmlinkage long sys_time(int *tloc);
+asmlinkage long sys_stime(time_t *tptr);
+asmlinkage long sys_gettimeofday(struct timeval __user *tv,
+				struct timezone __user *tz);
+asmlinkage long sys_settimeofday(struct timeval __user *tv,
+				struct timezone __user *tz);
+asmlinkage long sys_adjtimex(struct timex __user *txc_p);
+
+asmlinkage long sys_times(struct tms __user *tbuf);
+
+asmlinkage long sys_gettid(void);
+asmlinkage long sys_nanosleep(struct timespec *rqtp, struct timespec *rmtp);
+asmlinkage unsigned long sys_alarm(unsigned int seconds);
+asmlinkage long sys_getpid(void);
+asmlinkage long sys_getppid(void);
+asmlinkage long sys_getuid(void);
+asmlinkage long sys_geteuid(void);
+asmlinkage long sys_getgid(void);
+asmlinkage long sys_getegid(void);
+asmlinkage long sys_getresuid(uid_t *ruid, uid_t *euid, uid_t *suid);
+asmlinkage long sys_getresgid(gid_t *rgid, gid_t *egid, gid_t *sgid);
+asmlinkage long sys_getpgid(pid_t pid);
+asmlinkage long sys_getpgrp(void);
+asmlinkage long sys_getsid(pid_t pid);
+asmlinkage long sys_getgroups(int gidsetsize, gid_t __user *grouplist);
+
+asmlinkage long sys_setregid(gid_t rgid, gid_t egid);
+asmlinkage long sys_setgid(gid_t gid);
+asmlinkage long sys_setreuid(uid_t ruid, uid_t euid);
+asmlinkage long sys_setuid(uid_t uid);
+asmlinkage long sys_setresuid(uid_t ruid, uid_t euid, uid_t suid);
+asmlinkage long sys_setresgid(gid_t rgid, gid_t egid, gid_t sgid);
+asmlinkage long sys_setfsuid(uid_t uid);
+asmlinkage long sys_setfsgid(gid_t gid);
+asmlinkage long sys_setpgid(pid_t pid, pid_t pgid);
+asmlinkage long sys_setsid(void);
+asmlinkage long sys_setgroups(int gidsetsize, gid_t __user *grouplist);
+
+asmlinkage long sys_acct(const char *name);
+asmlinkage long sys_capget(cap_user_header_t header,
+				cap_user_data_t dataptr);
+asmlinkage long sys_capset(cap_user_header_t header,
+				const cap_user_data_t data);
+asmlinkage long sys_personality(u_long personality);
+
+asmlinkage long sys_sigpending(old_sigset_t __user *set);
+asmlinkage long sys_sigprocmask(int how, old_sigset_t __user *set,
+				old_sigset_t __user *oset);
+asmlinkage long sys_getitimer(int which, struct itimerval __user *value);
+asmlinkage long sys_setitimer(int which,
+				struct itimerval __user *value,
+				struct itimerval __user *ovalue);
+asmlinkage long sys_timer_gettime(timer_t timer_id,
+				struct itimerspec __user *setting);
+asmlinkage long sys_timer_getoverrun(timer_t timer_id);
+asmlinkage long sys_timer_settime(timer_t timer_id, int flags,
+				const struct itimerspec __user *new_setting,
+				struct itimerspec __user *old_setting);
+asmlinkage long sys_timer_delete(timer_t timer_id);
+asmlinkage long sys_clock_settime(clockid_t which_clock,
+				const struct timespec __user *tp);
+asmlinkage long sys_clock_gettime(clockid_t which_clock,
+				struct timespec __user *tp);
+asmlinkage long sys_clock_getres(clockid_t which_clock,
+				struct timespec __user *tp);
+asmlinkage long sys_clock_nanosleep(clockid_t which_clock, int flags,
+				const struct timespec __user *rqtp,
+				struct timespec __user *rmtp);
+
+asmlinkage long sys_nice(int increment);
+asmlinkage long sys_sched_setscheduler(pid_t pid, int policy,
+					struct sched_param __user *param);
+asmlinkage long sys_sched_setparam(pid_t pid,
+					struct sched_param __user *param);
+asmlinkage long sys_sched_getscheduler(pid_t pid);
+asmlinkage long sys_sched_getparam(pid_t pid,
+					struct sched_param __user *param);
+asmlinkage long sys_sched_setaffinity(pid_t pid, unsigned int len,
+					unsigned long __user *user_mask_ptr);
+asmlinkage long sys_sched_getaffinity(pid_t pid, unsigned int len,
+					unsigned long __user *user_mask_ptr);
+asmlinkage long sys_sched_yield(void);
+asmlinkage long sys_sched_get_priority_max(int policy);
+asmlinkage long sys_sched_get_priority_min(int policy);
+asmlinkage long sys_sched_rr_get_interval(pid_t pid,
+					struct timespec __user *interval);
+asmlinkage long sys_setpriority(int which, int who, int niceval);
+asmlinkage long sys_getpriority(int which, int who);
+
+asmlinkage long sys_shutdown(int, int);
+asmlinkage long sys_reboot(int magic1, int magic2, unsigned int cmd,
+				void __user *arg);
+asmlinkage long sys_restart_syscall(void);
+
+asmlinkage long sys_exit(int error_code);
+asmlinkage void sys_exit_group(int error_code);
+asmlinkage long sys_wait4(pid_t pid, unsigned int *stat_addr,
+				int options, struct rusage *ru);
+asmlinkage long sys_waitpid(pid_t pid, unsigned int *stat_addr, int options);
+asmlinkage long sys_set_tid_address(int __user *tidptr);
+asmlinkage long sys_futex(u32 __user *uaddr, int op, int val,
+			struct timespec __user *utime, u32 __user *uaddr2);
+
+asmlinkage long sys_init_module(void __user *umod, unsigned long len,
+				const char __user *uargs);
+asmlinkage long sys_delete_module(const char __user *name_user,
+				unsigned int flags);
+
+asmlinkage long sys_rt_sigprocmask(int how, sigset_t __user *set,
+				sigset_t __user *oset, size_t sigsetsize);
+asmlinkage long sys_rt_sigpending(sigset_t __user *set, size_t sigsetsize);
+asmlinkage long sys_rt_sigtimedwait(const sigset_t __user *uthese,
+				siginfo_t __user *uinfo,
+				const struct timespec __user *uts,
+				size_t sigsetsize);
+asmlinkage long sys_kill(int pid, int sig);
+asmlinkage long sys_tgkill(int tgid, int pid, int sig);
+asmlinkage long sys_tkill(int pid, int sig);
+asmlinkage long sys_rt_sigqueueinfo(int pid, int sig, siginfo_t __user *uinfo);
+asmlinkage long sys_rt_sigaction(int sig,
+				const struct sigaction __user *act,
+				struct sigaction __user *oact,
+				size_t sigsetsize);
+asmlinkage long sys_sgetmask(void);
+asmlinkage long sys_ssetmask(int newmask);
+asmlinkage unsigned long sys_signal(int sig, __sighandler_t handler);
+asmlinkage long sys_pause(void);
+
+asmlinkage long sys_sync(void);
+asmlinkage long sys_fsync(unsigned int fd);
+asmlinkage long sys_fdatasync(unsigned int fd);
+asmlinkage long sys_bdflush(int func, long data);
+asmlinkage long sys_mount(char __user *dev_name, char __user *dir_name,
+				char __user *type, unsigned long flags,
+				void __user *data);
+asmlinkage long sys_umount(char __user *name, int flags);
+asmlinkage long sys_oldumount(char __user *name);
+asmlinkage long sys_truncate(const char __user *path,
+				unsigned long length);
+asmlinkage long sys_ftruncate(unsigned int fd, unsigned long length);
+asmlinkage long sys_stat(char __user *filename,
+			struct __old_kernel_stat __user *statbuf);
+asmlinkage long sys_statfs(const char __user * path,
+				struct statfs __user *buf);
+asmlinkage long sys_statfs64(const char __user *path, size_t sz,
+				struct statfs64 __user *buf);
+asmlinkage long sys_fstatfs(unsigned int fd, struct statfs __user *buf);
+asmlinkage long sys_fstatfs64(unsigned int fd, size_t sz,
+				struct statfs64 __user *buf);
+asmlinkage long sys_lstat(char __user *filename,
+			struct __old_kernel_stat __user *statbuf);
+asmlinkage long sys_fstat(unsigned int fd,
+			struct __old_kernel_stat __user *statbuf);
+asmlinkage long sys_newstat(char __user *filename,
+				struct stat __user *statbuf);
+asmlinkage long sys_newlstat(char __user *filename,
+				struct stat __user *statbuf);
+asmlinkage long sys_newfstat(unsigned int fd, struct stat __user *statbuf);
+asmlinkage long sys_ustat(unsigned dev, struct ustat __user *ubuf);
+#if BITS_PER_LONG == 32
+asmlinkage long sys_stat64(char __user *filename,
+				struct stat64 __user *statbuf);
+asmlinkage long sys_fstat64(unsigned long fd, struct stat64 __user *statbuf);
+asmlinkage long sys_lstat64(char __user *filename,
+				struct stat64 __user *statbuf);
+asmlinkage long sys_truncate64(const char __user *path, loff_t length);
+asmlinkage long sys_ftruncate64(unsigned int fd, loff_t length);
+#endif
+
+asmlinkage long sys_setxattr(char __user *path, char __user *name,
+				void __user *value, size_t size, int flags);
+asmlinkage long sys_lsetxattr(char __user *path, char __user *name,
+				void __user *value, size_t size, int flags);
+asmlinkage long sys_fsetxattr(int fd, char __user *name, void __user *value,
+				size_t size, int flags);
+asmlinkage ssize_t sys_getxattr(char __user *path, char __user *name,
+				void __user *value, size_t size);
+asmlinkage ssize_t sys_lgetxattr(char __user *path, char __user *name,
+				void __user *value, size_t size);
+asmlinkage ssize_t sys_fgetxattr(int fd, char __user *name,
+				void __user *value, size_t size);
+asmlinkage ssize_t sys_listxattr(char __user *path, char __user *list,
+				size_t size);
+asmlinkage ssize_t sys_llistxattr(char __user *path, char __user *list,
+				size_t size);
+asmlinkage ssize_t sys_flistxattr(int fd, char __user *list, size_t size);
+asmlinkage long sys_removexattr(char __user *path, char __user *name);
+asmlinkage long sys_lremovexattr(char __user *path, char __user *name);
+asmlinkage long sys_fremovexattr(int fd, char __user *name);
+
+asmlinkage unsigned long sys_brk(unsigned long brk);
+asmlinkage long sys_mprotect(unsigned long start, size_t len,
+				unsigned long prot);
+asmlinkage unsigned long sys_mremap(unsigned long addr,
+				unsigned long old_len, unsigned long new_len,
+				unsigned long flags, unsigned long new_addr);
+long sys_remap_file_pages(unsigned long start, unsigned long size,
+			unsigned long prot, unsigned long pgoff,
+			unsigned long flags);
+asmlinkage long sys_msync(unsigned long start, size_t len, int flags);
+asmlinkage long sys_fadvise64(int fd, loff_t offset, size_t len, int advice);
+asmlinkage long sys_fadvise64_64(int fd, loff_t offset, loff_t len, int advice);
+asmlinkage long sys_munmap(unsigned long addr, size_t len);
+asmlinkage long sys_mlock(unsigned long start, size_t len);
+asmlinkage long sys_munlock(unsigned long start, size_t len);
+asmlinkage long sys_mlockall(int flags);
+asmlinkage long sys_munlockall(void);
+asmlinkage long sys_madvise(unsigned long start, size_t len, int behavior);
+asmlinkage long sys_mincore(unsigned long start, size_t len,
+				unsigned char __user * vec);
+
+asmlinkage long sys_pivot_root(const char __user *new_root,
+				const char __user *put_old);
+asmlinkage long sys_chroot(const char __user *filename);
+asmlinkage long sys_mknod(const char __user *filename, int mode,
+				unsigned dev);
+asmlinkage long sys_link(const char __user *oldname,
+				const char __user *newname);
+asmlinkage long sys_symlink(const char *old, const char *new);
+asmlinkage long sys_unlink(const char __user *pathname);
+asmlinkage long sys_rename(const char __user *oldname,
+				const char __user *newname);
+asmlinkage long sys_chmod(const char __user *filename, mode_t mode);
+asmlinkage long sys_fchmod(unsigned int fd, mode_t mode);
+
+asmlinkage long sys_fcntl(unsigned int fd, unsigned int cmd, unsigned long arg);
+#if BITS_PER_LONG == 32
+asmlinkage long sys_fcntl64(unsigned int fd,
+				unsigned int cmd, unsigned long arg);
+#endif
+asmlinkage long sys_dup(unsigned int fildes);
+asmlinkage long sys_dup2(unsigned int oldfd, unsigned int newfd);
+asmlinkage long sys_ioperm(unsigned long from, unsigned long num, int on);
+asmlinkage long sys_ioctl(unsigned int fd, unsigned int cmd,
+				unsigned long arg);
+asmlinkage long sys_flock(unsigned int fd, unsigned int cmd);
+asmlinkage long sys_io_setup(unsigned nr_reqs, aio_context_t *ctx);
+asmlinkage long sys_io_destroy(aio_context_t ctx);
+asmlinkage long sys_io_getevents(aio_context_t ctx_id,
+				long min_nr,
+				long nr,
+				struct io_event *events,
+				struct timespec *timeout);
+asmlinkage long sys_io_submit(aio_context_t, long,
+				struct iocb __user **);
+asmlinkage long sys_io_cancel(aio_context_t ctx_id, struct iocb *iocb,
+			      struct io_event *result);
+asmlinkage ssize_t sys_sendfile(int out_fd, int in_fd,
+				off_t __user *offset, size_t count);
+asmlinkage ssize_t sys_sendfile64(int out_fd, int in_fd,
+				loff_t __user *offset, size_t count);
+asmlinkage long sys_readlink(const char __user *path,
+				char __user *buf, int bufsiz);
+asmlinkage long sys_creat(const char __user *pathname, int mode);
+asmlinkage long sys_open(const char __user *filename,
+				int flags, int mode);
+asmlinkage long sys_close(unsigned int fd);
+asmlinkage long sys_access(const char __user *filename, int mode);
+asmlinkage long sys_vhangup(void);
+asmlinkage long sys_chown(const char __user *filename,
+				uid_t user, gid_t group);
+asmlinkage long sys_lchown(const char __user *filename,
+				uid_t user, gid_t group);
+asmlinkage long sys_fchown(unsigned int fd, uid_t user, gid_t group);
+#ifdef CONFIG_UID16
+asmlinkage long sys_chown16(const char *filename,
+				old_uid_t user, old_gid_t group);
+asmlinkage long sys_lchown16(const char *filename,
+				old_uid_t user, old_gid_t group);
+asmlinkage long sys_fchown16(unsigned int fd, old_uid_t user, old_gid_t group);
+asmlinkage long sys_setregid16(old_gid_t rgid, old_gid_t egid);
+asmlinkage long sys_setgid16(old_gid_t gid);
+asmlinkage long sys_setreuid16(old_uid_t ruid, old_uid_t euid);
+asmlinkage long sys_setuid16(old_uid_t uid);
+asmlinkage long sys_setresuid16(old_uid_t ruid, old_uid_t euid, old_uid_t suid);
+asmlinkage long sys_getresuid16(old_uid_t *ruid,
+				old_uid_t *euid, old_uid_t *suid);
+asmlinkage long sys_setresgid16(old_gid_t rgid, old_gid_t egid, old_gid_t sgid);
+asmlinkage long sys_getresgid16(old_gid_t *rgid,
+				old_gid_t *egid, old_gid_t *sgid);
+asmlinkage long sys_setfsuid16(old_uid_t uid);
+asmlinkage long sys_setfsgid16(old_gid_t gid);
+asmlinkage long sys_getgroups16(int gidsetsize, old_gid_t __user *grouplist);
+asmlinkage long sys_setgroups16(int gidsetsize, old_gid_t __user *grouplist);
+asmlinkage long sys_getuid16(void);
+asmlinkage long sys_geteuid16(void);
+asmlinkage long sys_getgid16(void);
+asmlinkage long sys_getegid16(void);
+#endif
+
+asmlinkage long sys_utime(char __user *filename,
+				struct utimbuf __user *times);
+asmlinkage long sys_utimes(char __user *filename,
+				struct timeval __user *utimes);
+asmlinkage off_t sys_lseek(unsigned int fd, off_t offset,
+				unsigned int origin);
+asmlinkage long sys_llseek(unsigned int fd, unsigned long offset_high,
+			unsigned long offset_low, loff_t __user *result,
+			unsigned int origin);
+asmlinkage ssize_t sys_read(unsigned int fd, char __user *buf,
+				size_t count);
+asmlinkage ssize_t sys_readahead(int fd, loff_t offset, size_t count);
+asmlinkage ssize_t sys_readv(unsigned long fd,
+				const struct iovec __user *vec,
+				unsigned long vlen);
+asmlinkage ssize_t sys_write(unsigned int fd, const char __user *buf,
+				size_t count);
+asmlinkage ssize_t sys_writev(unsigned long fd,
+				const struct iovec __user *vec,
+				unsigned long vlen);
+asmlinkage ssize_t sys_pread64(unsigned int fd, char __user *buf,
+				size_t count, loff_t pos);
+asmlinkage ssize_t sys_pwrite64(unsigned int fd, const char __user *buf,
+				size_t count, loff_t pos);
+asmlinkage long sys_getcwd(char __user *buf, unsigned long size);
+asmlinkage long sys_mkdir(const char __user *pathname, int mode);
+asmlinkage long sys_chdir(const char __user *filename);
+asmlinkage long sys_fchdir(unsigned int fd);
+asmlinkage long sys_rmdir(const char __user *pathname);
+asmlinkage long sys_lookup_dcookie(u64 cookie64, char *buf, size_t len);
+asmlinkage long sys_quotactl(unsigned int cmd, const char *special,
+				qid_t id, caddr_t addr);
+asmlinkage long sys_getdents(unsigned int fd,
+				struct linux_dirent __user *dirent,
+				unsigned int count);
+asmlinkage long sys_getdents64(unsigned int fd,
+				struct linux_dirent64 __user *dirent,
+				unsigned int count);
+
+asmlinkage long sys_setsockopt(int fd, int level, int optname,
+				char *optval, int optlen);
+asmlinkage long sys_getsockopt(int fd, int level, int optname,
+				char __user *optval, int __user *optlen);
+asmlinkage long sys_bind(int, struct sockaddr *, int);
+asmlinkage long sys_connect(int, struct sockaddr *, int);
+asmlinkage long sys_accept(int, struct sockaddr *, int *);
+asmlinkage long sys_getsockname(int, struct sockaddr *, int *);
+asmlinkage long sys_getpeername(int, struct sockaddr *, int *);
+asmlinkage long sys_send(int, void *, size_t, unsigned);
+asmlinkage long sys_sendto(int, void *, size_t, unsigned,
+				struct sockaddr *, int);
+asmlinkage long sys_sendmsg(int fd, struct msghdr __user *msg, unsigned flags);
+asmlinkage long sys_recv(int, void *, size_t, unsigned);
+asmlinkage long sys_recvfrom(int, void *, size_t, unsigned,
+				struct sockaddr *, int *);
+asmlinkage long sys_recvmsg(int fd, struct msghdr __user *msg, unsigned flags);
+asmlinkage long sys_socket(int, int, int);
+asmlinkage long sys_socketpair(int, int, int, int [2]);
+asmlinkage long sys_socketcall(int call, unsigned long __user *args);
+asmlinkage long sys_listen(int, int);
+asmlinkage long sys_poll(struct pollfd __user *ufds, unsigned int nfds,
+				long timeout);
+asmlinkage long sys_select(int n, fd_set __user *inp, fd_set __user *outp,
+			fd_set __user *exp, struct timeval __user *tvp);
+asmlinkage long sys_epoll_create(int size);
+asmlinkage long sys_epoll_ctl(int epfd, int op, int fd,
+				struct epoll_event __user *event);
+asmlinkage long sys_epoll_wait(int epfd, struct epoll_event __user *events,
+				int maxevents, int timeout);
+asmlinkage long sys_gethostname(char __user *name, int len);
+asmlinkage long sys_sethostname(char __user *name, int len);
+asmlinkage long sys_setdomainname(char __user *name, int len);
+asmlinkage long sys_newuname(struct new_utsname __user *name);
+
+asmlinkage long sys_getrlimit(unsigned int resource,
+				struct rlimit __user *rlim);
+#if defined(COMPAT_RLIM_OLD_INFINITY) || !(defined(CONFIG_IA64) || defined(CONFIG_V850))
+asmlinkage long sys_old_getrlimit(unsigned int resource, struct rlimit __user *rlim);
+#endif
+asmlinkage long sys_setrlimit(unsigned int resource,
+				struct rlimit __user *rlim);
+asmlinkage long sys_getrusage(int who, struct rusage __user *ru);
+asmlinkage long sys_umask(int mask);
+
+asmlinkage long sys_msgget(key_t key, int msgflg);
+asmlinkage long sys_msgsnd(int msqid, struct msgbuf __user *msgp,
+				size_t msgsz, int msgflg);
+asmlinkage long sys_msgrcv(int msqid, struct msgbuf __user *msgp,
+				size_t msgsz, long msgtyp, int msgflg);
+asmlinkage long sys_msgctl(int msqid, int cmd, struct msqid_ds __user *buf);
+
+asmlinkage long sys_semget(key_t key, int nsems, int semflg);
+asmlinkage long sys_semop(int semid, struct sembuf __user *sops,
+				unsigned nsops);
+asmlinkage long sys_semctl(int semid, int semnum, int cmd, union semun arg);
+asmlinkage long sys_semtimedop(int semid, struct sembuf __user *sops,
+				unsigned nsops,
+				const struct timespec __user *timeout);
+asmlinkage long sys_shmat(int shmid, char __user *shmaddr,
+				int shmflg, unsigned long *addr);
+asmlinkage long sys_shmget(key_t key, size_t size, int flag);
+asmlinkage long sys_shmdt(char __user *shmaddr);
+asmlinkage long sys_shmctl(int shmid, int cmd, struct shmid_ds __user *buf);
+
+asmlinkage long sys_pciconfig_iobase(long which, unsigned long bus, unsigned long devfn);
+asmlinkage long sys_pciconfig_read(unsigned long bus, unsigned long dfn,
+				unsigned long off, unsigned long len,
+				void *buf);
+asmlinkage long sys_pciconfig_write(unsigned long bus, unsigned long dfn,
+				unsigned long off, unsigned long len,
+				void *buf);
+
+asmlinkage long sys_prctl(int option, unsigned long arg2, unsigned long arg3,
+			unsigned long arg4, unsigned long arg5);
+asmlinkage long sys_swapon(const char __user *specialfile, int swap_flags);
+asmlinkage long sys_swapoff(const char __user *specialfile);
+asmlinkage long sys_sysctl(struct __sysctl_args __user *args);
+asmlinkage long sys_sysinfo(struct sysinfo __user *info);
+asmlinkage long sys_sysfs(int option,
+				unsigned long arg1, unsigned long arg2);
+asmlinkage long sys_nfsservctl(int cmd,
+				struct nfsctl_arg __user *arg,
+				void __user *res);
+asmlinkage long sys_syslog(int type, char __user *buf, int len);
+asmlinkage long sys_uselib(const char __user *library);
+asmlinkage long sys_ni_syscall(void);
+
+#endif
--- diff/ipc/compat.c	1970-01-01 01:00:00.000000000 +0100
+++ source/ipc/compat.c	2004-02-23 13:56:48.000000000 +0000
@@ -0,0 +1,734 @@
+/*
+ * 32 bit compatibility code for System V IPC
+ *
+ * Copyright (C) 1997,1998	Jakub Jelinek (jj@sunsite.mff.cuni.cz)
+ * Copyright (C) 1997		David S. Miller (davem@caip.rutgers.edu)
+ * Copyright (C) 1999		Arun Sharma <arun.sharma@intel.com>
+ * Copyright (C) 2000		VA Linux Co
+ * Copyright (C) 2000		Don Dugger <n0ano@valinux.com>
+ * Copyright (C) 2000           Hewlett-Packard Co.
+ * Copyright (C) 2000           David Mosberger-Tang <davidm@hpl.hp.com>
+ * Copyright (C) 2000           Gerhard Tonn (ton@de.ibm.com)
+ * Copyright (C) 2000-2002      Andi Kleen, SuSE Labs (x86-64 port)
+ * Copyright (C) 2000		Silicon Graphics, Inc.
+ * Copyright (C) 2001		IBM
+ * Copyright (C) 2004		IBM Deutschland Entwicklung GmbH, IBM Corporation
+ * Copyright (C) 2004		Arnd Bergmann (arnd@arndb.de)
+ *
+ * This code is collected from the versions for sparc64, mips64, s390x, ia64,
+ * ppc64 and x86_64, all of which are based on the original sparc64 version
+ * by Jakub Jelinek.
+ *
+ */
+#include <linux/compat.h>
+#include <linux/config.h>
+#include <linux/errno.h>
+#include <linux/highuid.h>
+#include <linux/init.h>
+#include <linux/msg.h>
+#include <linux/shm.h>
+#include <linux/slab.h>
+#include <linux/syscalls.h>
+
+#include <asm/semaphore.h>
+#include <asm/uaccess.h>
+
+#include "util.h"
+
+struct compat_msgbuf {
+	compat_long_t mtype;
+	char mtext[1];
+};
+
+struct compat_ipc_perm {
+	key_t key;
+	compat_uid_t uid;
+	compat_gid_t gid;
+	compat_uid_t cuid;
+	compat_gid_t cgid;
+	compat_mode_t mode;
+	unsigned short seq;
+};
+
+struct compat_semid_ds {
+	struct compat_ipc_perm sem_perm;
+	compat_time_t sem_otime;
+	compat_time_t sem_ctime;
+	compat_uptr_t sem_base;
+	compat_uptr_t sem_pending;
+	compat_uptr_t sem_pending_last;
+	compat_uptr_t undo;
+	unsigned short sem_nsems;
+};
+
+struct compat_msqid_ds {
+	struct compat_ipc_perm msg_perm;
+	compat_uptr_t msg_first;
+	compat_uptr_t msg_last;
+	compat_time_t msg_stime;
+	compat_time_t msg_rtime;
+	compat_time_t msg_ctime;
+	compat_ulong_t msg_lcbytes;
+	compat_ulong_t msg_lqbytes;
+	unsigned short msg_cbytes;
+	unsigned short msg_qnum;
+	unsigned short msg_qbytes;
+	compat_ipc_pid_t msg_lspid;
+	compat_ipc_pid_t msg_lrpid;
+};
+
+struct compat_shmid_ds {
+	struct compat_ipc_perm shm_perm;
+	int shm_segsz;
+	compat_time_t shm_atime;
+	compat_time_t shm_dtime;
+	compat_time_t shm_ctime;
+	compat_ipc_pid_t shm_cpid;
+	compat_ipc_pid_t shm_lpid;
+	unsigned short shm_nattch;
+	unsigned short shm_unused;
+	compat_uptr_t shm_unused2;
+	compat_uptr_t shm_unused3;
+};
+
+struct compat_ipc_kludge {
+	compat_uptr_t msgp;
+	compat_long_t msgtyp;
+};
+
+struct compat_shminfo64 {
+	compat_ulong_t shmmax;
+	compat_ulong_t shmmin;
+	compat_ulong_t shmmni;
+	compat_ulong_t shmseg;
+	compat_ulong_t shmall;
+	compat_ulong_t __unused1;
+	compat_ulong_t __unused2;
+	compat_ulong_t __unused3;
+	compat_ulong_t __unused4;
+};
+
+struct compat_shm_info {
+	compat_int_t used_ids;
+	compat_ulong_t shm_tot, shm_rss, shm_swp;
+	compat_ulong_t swap_attempts, swap_successes;
+};
+
+extern int sem_ctls[];
+#define sc_semopm	(sem_ctls[2])
+#define MAXBUF (64*1024)
+
+static inline int compat_ipc_parse_version(int *cmd)
+{
+	int version = *cmd & IPC_64;
+
+	/* this is tricky: architectures that have support for the old
+	 * ipc structures in 64 bit binaries need to have IPC_64 set
+	 * in cmd, the others need to have it cleared */
+#ifndef ipc_parse_version
+	*cmd |= IPC_64;
+#else
+	*cmd &= ~IPC_64;
+#endif
+	return version;
+}
+
+static inline int __get_compat_ipc64_perm(struct ipc64_perm *p64,
+					  struct compat_ipc64_perm *up64)
+{
+	int err;
+
+	err  = __get_user(p64->uid, &up64->uid);
+	err |= __get_user(p64->gid, &up64->gid);
+	err |= __get_user(p64->mode, &up64->mode);
+	return err;
+}
+
+static inline int __get_compat_ipc_perm(struct ipc64_perm *p,
+					struct compat_ipc_perm *up)
+{
+	int err;
+
+	err  = __get_user(p->uid, &up->uid);
+	err |= __get_user(p->gid, &up->gid);
+	err |= __get_user(p->mode, &up->mode);
+	return err;
+}
+
+static inline int __put_compat_ipc64_perm(struct ipc64_perm *p64,
+					  struct compat_ipc64_perm *up64)
+{
+	int err;
+
+	err  = __put_user(p64->key, &up64->key);
+	err |= __put_user(p64->uid, &up64->uid);
+	err |= __put_user(p64->gid, &up64->gid);
+	err |= __put_user(p64->cuid, &up64->cuid);
+	err |= __put_user(p64->cgid, &up64->cgid);
+	err |= __put_user(p64->mode, &up64->mode);
+	err |= __put_user(p64->seq, &up64->seq);
+	return err;
+}
+
+static inline int __put_compat_ipc_perm(struct ipc64_perm *p,
+					struct compat_ipc_perm *up)
+{
+	int err;
+	compat_uid_t u;
+	compat_gid_t g;
+
+	err  = __put_user(p->key, &up->key);
+	SET_UID(u, p->uid);
+	err |= __put_user(u, &up->uid);
+	SET_GID(g, p->gid);
+	err |= __put_user(g, &up->gid);
+	SET_UID(u, p->cuid);
+	err |= __put_user(u, &up->cuid);
+	SET_GID(g, p->cgid);
+	err |= __put_user(g, &up->cgid);
+	err |= __put_user(p->mode, &up->mode);
+	err |= __put_user(p->seq, &up->seq);
+	return err;
+}
+
+static inline int get_compat_semid64_ds(struct semid64_ds *s64,
+					struct compat_semid64_ds *up64)
+{
+	if (!access_ok (VERIFY_READ, up64, sizeof(*up64)))
+		return -EFAULT;
+	return __get_compat_ipc64_perm(&s64->sem_perm, &up64->sem_perm);
+}
+
+static inline int get_compat_semid_ds(struct semid64_ds *s,
+				      struct compat_semid_ds *up)
+{
+	if (!access_ok (VERIFY_READ, up, sizeof(*up)))
+		return -EFAULT;
+	return __get_compat_ipc_perm(&s->sem_perm, &up->sem_perm);
+}
+
+static inline int put_compat_semid64_ds(struct semid64_ds *s64,
+					struct compat_semid64_ds *up64)
+{
+	int err;
+
+	if (!access_ok (VERIFY_WRITE, up64, sizeof(*up64)))
+		return -EFAULT;
+	err  = __put_compat_ipc64_perm(&s64->sem_perm, &up64->sem_perm);
+	err |= __put_user(s64->sem_otime, &up64->sem_otime);
+	err |= __put_user(s64->sem_ctime, &up64->sem_ctime);
+	err |= __put_user(s64->sem_nsems, &up64->sem_nsems);
+	return err;
+}
+
+static inline int put_compat_semid_ds(struct semid64_ds *s,
+				      struct compat_semid_ds *up)
+{
+	int err;
+
+	if (!access_ok (VERIFY_WRITE, up, sizeof(*up)))
+		err = -EFAULT;
+	err  = __put_compat_ipc_perm(&s->sem_perm, &up->sem_perm);
+	err |= __put_user(s->sem_otime, &up->sem_otime);
+	err |= __put_user(s->sem_ctime, &up->sem_ctime);
+	err |= __put_user(s->sem_nsems, &up->sem_nsems);
+	return err;
+}
+
+static inline int do_semctl(int semid, int semnum, int cmd, union semun arg)
+{
+	mm_segment_t old_fs;
+	int err;
+
+	old_fs = get_fs();
+	set_fs(KERNEL_DS);
+	err = sys_semctl(semid, semnum, cmd, arg);
+	set_fs(old_fs);
+
+	return err;
+}
+long compat_sys_semctl(int first, int second, int third, void __user *uptr)
+{
+	union semun fourth;
+	u32 pad;
+	int err, err2;
+	struct semid64_ds s64;
+	int version = compat_ipc_parse_version(&third);
+
+	if (!uptr)
+		return -EINVAL;
+	if (get_user(pad, (u32 __user *) uptr))
+		return -EFAULT;
+	if ((third & (~IPC_64)) == SETVAL)
+		fourth.val = (int) pad;
+	else
+		fourth.__pad = compat_ptr(pad);
+	switch (third & (~IPC_64)) {
+	case IPC_INFO:
+	case IPC_RMID:
+	case SEM_INFO:
+	case GETVAL:
+	case GETPID:
+	case GETNCNT:
+	case GETZCNT:
+	case GETALL:
+	case SETVAL:
+	case SETALL:
+		err = sys_semctl(first, second, third, fourth);
+		break;
+
+	case IPC_STAT:
+	case SEM_STAT:
+		fourth.__pad = &s64;
+		err = do_semctl(first, second, third, fourth);
+		if (err < 0)
+			break;
+
+		if (version == IPC_64) {
+			err2 = put_compat_semid64_ds(&s64, compat_ptr(pad));
+		} else {
+			err2 = put_compat_semid_ds(&s64, compat_ptr(pad));
+		}
+		if (err2)
+			err = -EFAULT;
+		break;
+
+	case IPC_SET:
+		if (version == IPC_64) {
+			err = get_compat_semid64_ds(&s64, compat_ptr(pad));
+		} else {
+			err = get_compat_semid_ds(&s64, compat_ptr(pad));
+		}
+		if (err)
+			break;
+
+		fourth.__pad = &s64;
+		err = do_semctl(first, second, third, fourth);
+		break;
+
+	default:
+		err = -EINVAL;
+		break;
+	}
+	return err;
+}
+
+long compat_sys_msgsnd(int first, int second, int third, void __user *uptr)
+{
+	struct msgbuf *p;
+	struct compat_msgbuf __user *up;
+	mm_segment_t old_fs;
+	int err;
+
+	if (first < 0)
+		return -EINVAL;
+	if (second < 0 || (second >= MAXBUF - sizeof(struct msgbuf)))
+		return -EINVAL;
+
+	p = kmalloc(second + sizeof(struct msgbuf), GFP_USER);
+	if (!p)
+		return -ENOMEM;
+	err = -EFAULT;
+	up = uptr;
+	if (get_user(p->mtype, &up->mtype) ||
+	    copy_from_user(p->mtext, &up->mtext, second))
+		goto out;
+	old_fs = get_fs();
+	set_fs(KERNEL_DS);
+	err = sys_msgsnd(first, p, second, third);
+	set_fs(old_fs);
+out:
+	kfree(p);
+	return err;
+}
+
+long compat_sys_msgrcv(int first, int second, int msgtyp, int third,
+			   int version, void __user *uptr)
+{
+	struct msgbuf *p;
+	struct compat_msgbuf __user *up;
+	mm_segment_t old_fs;
+	int err;
+
+	if (first < 0)
+		return -EINVAL;
+	if (second < 0 || (second >= MAXBUF - sizeof(struct msgbuf)))
+		return -EINVAL;
+
+	if (!version) {
+		struct compat_ipc_kludge __user *uipck = uptr;
+		struct compat_ipc_kludge ipck;
+
+		err = -EINVAL;
+		if (!uptr)
+			goto out;
+		err = -EFAULT;
+		if (copy_from_user (&ipck, uipck, sizeof(ipck)))
+			goto out;
+		uptr = compat_ptr(ipck.msgp);
+		msgtyp = ipck.msgtyp;
+	}
+	err = -ENOMEM;
+	p = kmalloc(second + sizeof(struct msgbuf), GFP_USER);
+	if (!p)
+		goto out;
+	old_fs = get_fs();
+	set_fs(KERNEL_DS);
+	err = sys_msgrcv(first, p, second, msgtyp, third);
+	set_fs(old_fs);
+	if (err < 0)
+		goto free_then_out;
+	up = uptr;
+	if (put_user(p->mtype, &up->mtype) ||
+	    __copy_to_user(&up->mtext, p->mtext, err))
+		err = -EFAULT;
+free_then_out:
+	kfree(p);
+out:
+	return err;
+}
+
+static inline int get_compat_msqid64(struct msqid64_ds *m64,
+				     struct compat_msqid64_ds __user *up64)
+{
+	int err;
+
+	if (!access_ok(VERIFY_READ, up64, sizeof(*up64)))
+		return -EFAULT;
+	err  = __get_compat_ipc64_perm(&m64->msg_perm, &up64->msg_perm);
+	err |= __get_user(m64->msg_qbytes, &up64->msg_qbytes);
+	return err;
+}
+
+static inline int get_compat_msqid(struct msqid64_ds *m,
+				   struct compat_msqid_ds __user *up)
+{
+	int err;
+
+	if (!access_ok(VERIFY_READ, up, sizeof(*up)))
+		return -EFAULT;
+	err  = __get_compat_ipc_perm(&m->msg_perm, &up->msg_perm);
+	err |= __get_user(m->msg_qbytes, &up->msg_qbytes);
+	return err;
+}
+
+static inline int put_compat_msqid64_ds(struct msqid64_ds *m64,
+				 struct compat_msqid64_ds __user __user *up64)
+{
+	int err;
+
+	if (!access_ok(VERIFY_WRITE, up64, sizeof(*up64)))
+		return -EFAULT;
+	err  = __put_compat_ipc64_perm(&m64->msg_perm, &up64->msg_perm);
+	err |= __put_user(m64->msg_stime, &up64->msg_stime);
+	err |= __put_user(m64->msg_rtime, &up64->msg_rtime);
+	err |= __put_user(m64->msg_ctime, &up64->msg_ctime);
+	err |= __put_user(m64->msg_cbytes, &up64->msg_cbytes);
+	err |= __put_user(m64->msg_qnum, &up64->msg_qnum);
+	err |= __put_user(m64->msg_qbytes, &up64->msg_qbytes);
+	err |= __put_user(m64->msg_lspid, &up64->msg_lspid);
+	err |= __put_user(m64->msg_lrpid, &up64->msg_lrpid);
+	return err;
+}
+
+static inline int put_compat_msqid_ds(struct msqid64_ds *m,
+				      struct compat_msqid_ds __user *up)
+{
+	int err;
+
+	if (!access_ok(VERIFY_WRITE, up, sizeof(*up)))
+		return -EFAULT;
+	err  = __put_compat_ipc_perm(&m->msg_perm, &up->msg_perm);
+	err |= __put_user(m->msg_stime, &up->msg_stime);
+	err |= __put_user(m->msg_rtime, &up->msg_rtime);
+	err |= __put_user(m->msg_ctime, &up->msg_ctime);
+	err |= __put_user(m->msg_cbytes, &up->msg_cbytes);
+	err |= __put_user(m->msg_qnum, &up->msg_qnum);
+	err |= __put_user(m->msg_qbytes, &up->msg_qbytes);
+	err |= __put_user(m->msg_lspid, &up->msg_lspid);
+	err |= __put_user(m->msg_lrpid, &up->msg_lrpid);
+	return err;
+}
+
+static inline int do_msgctl(int first, int second, void __user *buf)
+{
+	mm_segment_t old_fs;
+	int err;
+
+	old_fs = get_fs();
+	set_fs(KERNEL_DS);
+	err = sys_msgctl(first, second, buf);
+	set_fs(old_fs);
+
+	return err;
+}
+
+long compat_sys_msgctl(int first, int second, void __user *uptr)
+{
+	int err, err2;
+	struct msqid64_ds m64;
+	int version = compat_ipc_parse_version(&second);
+
+	switch (second & (~IPC_64)) {
+	case IPC_INFO:
+	case IPC_RMID:
+	case MSG_INFO:
+		err = sys_msgctl(first, second, uptr);
+		break;
+
+	case IPC_SET:
+		if (version == IPC_64) {
+			err = get_compat_msqid64(&m64, uptr);
+		} else {
+			err = get_compat_msqid(&m64, uptr);
+		}
+		if (err)
+			break;
+
+		err = do_msgctl(first, second, &m64);
+		break;
+
+	case IPC_STAT:
+	case MSG_STAT:
+		err = do_msgctl(first, second, &m64);
+		if (err < 0)
+			break;
+
+		if (version == IPC_64) {
+			err2 = put_compat_msqid64_ds(&m64, uptr);
+		} else {
+			err2 = put_compat_msqid_ds(&m64, uptr);
+		}
+		if (err2)
+			err = -EFAULT;
+		break;
+
+	default:
+		err = -EINVAL;
+		break;
+	}
+	return err;
+}
+
+long compat_sys_shmat(int first, int second, compat_uptr_t third, int version,
+			void __user *uptr)
+{
+	int err;
+	unsigned long raddr;
+	compat_ulong_t __user *uaddr;
+
+	if (version == 1)
+		return -EINVAL;
+	err = sys_shmat(first, uptr, second, &raddr);
+	if (err < 0)
+		return err;
+	uaddr = compat_ptr(third);
+	return put_user(raddr, uaddr);
+}
+
+static inline int get_compat_shmid64_ds(struct shmid64_ds *s64,
+					struct compat_shmid64_ds __user *up64)
+{
+	if (!access_ok(VERIFY_READ, up64, sizeof(*up64)))
+		return -EFAULT;
+	return __get_compat_ipc64_perm(&s64->shm_perm, &up64->shm_perm);
+}
+
+static inline int get_compat_shmid_ds(struct shmid64_ds *s,
+				      struct compat_shmid_ds __user *up)
+{
+	if (!access_ok(VERIFY_READ, up, sizeof(*up)))
+		return -EFAULT;
+	return __get_compat_ipc_perm(&s->shm_perm, &up->shm_perm);
+}
+
+static inline int put_compat_shmid64_ds(struct shmid64_ds *s64,
+					struct compat_shmid64_ds __user *up64)
+{
+	int err;
+
+	if (!access_ok(VERIFY_WRITE, up64, sizeof(*up64)))
+		return -EFAULT;
+	err  = __put_compat_ipc64_perm(&s64->shm_perm, &up64->shm_perm);
+	err |= __put_user(s64->shm_atime, &up64->shm_atime);
+	err |= __put_user(s64->shm_dtime, &up64->shm_dtime);
+	err |= __put_user(s64->shm_ctime, &up64->shm_ctime);
+	err |= __put_user(s64->shm_segsz, &up64->shm_segsz);
+	err |= __put_user(s64->shm_nattch, &up64->shm_nattch);
+	err |= __put_user(s64->shm_cpid, &up64->shm_cpid);
+	err |= __put_user(s64->shm_lpid, &up64->shm_lpid);
+	return err;
+}
+
+static inline int put_compat_shmid_ds(struct shmid64_ds *s,
+				      struct compat_shmid_ds __user *up)
+{
+	int err;
+
+	if (!access_ok(VERIFY_WRITE, up, sizeof(*up)))
+		return -EFAULT;
+	err  = __put_compat_ipc_perm(&s->shm_perm, &up->shm_perm);
+	err |= __put_user(s->shm_atime, &up->shm_atime);
+	err |= __put_user(s->shm_dtime, &up->shm_dtime);
+	err |= __put_user(s->shm_ctime, &up->shm_ctime);
+	err |= __put_user(s->shm_segsz, &up->shm_segsz);
+	err |= __put_user(s->shm_nattch, &up->shm_nattch);
+	err |= __put_user(s->shm_cpid, &up->shm_cpid);
+	err |= __put_user(s->shm_lpid, &up->shm_lpid);
+	return err;
+}
+
+static inline int put_compat_shminfo64(struct shminfo64 *smi,
+				       struct compat_shminfo64 __user *up64)
+{
+	int err;
+
+	if (!access_ok(VERIFY_WRITE, up64, sizeof(*up64)))
+		return -EFAULT;
+	err  = __put_user(smi->shmmax, &up64->shmmax);
+	err |= __put_user(smi->shmmin, &up64->shmmin);
+	err |= __put_user(smi->shmmni, &up64->shmmni);
+	err |= __put_user(smi->shmseg, &up64->shmseg);
+	err |= __put_user(smi->shmall, &up64->shmall);
+	return err;
+}
+
+static inline int put_compat_shminfo(struct shminfo64 *smi,
+				     struct shminfo __user *up)
+{
+	int err;
+
+	if (!access_ok(VERIFY_WRITE, up, sizeof(*up)))
+		return -EFAULT;
+	err  = __put_user(smi->shmmax, &up->shmmax);
+	err |= __put_user(smi->shmmin, &up->shmmin);
+	err |= __put_user(smi->shmmni, &up->shmmni);
+	err |= __put_user(smi->shmseg, &up->shmseg);
+	err |= __put_user(smi->shmall, &up->shmall);
+}
+
+static inline int put_compat_shm_info(struct shm_info *si,
+				      struct compat_shm_info __user *uip)
+{
+	int err;
+
+	if (!access_ok(VERIFY_WRITE, uip, sizeof(*uip)))
+		return -EFAULT;
+	err  = __put_user(si->used_ids, &uip->used_ids);
+	err |= __put_user(si->shm_tot, &uip->shm_tot);
+	err |= __put_user(si->shm_rss, &uip->shm_rss);
+	err |= __put_user(si->shm_swp, &uip->shm_swp);
+	err |= __put_user(si->swap_attempts, &uip->swap_attempts);
+	err |= __put_user(si->swap_successes, &uip->swap_successes);
+	return err;
+}
+
+static inline int do_shmctl(int shmid, int cmd, void *buf)
+{
+	mm_segment_t old_fs;
+	int err;
+
+	old_fs = get_fs();
+	set_fs(KERNEL_DS);
+	err = sys_shmctl(shmid, cmd, buf);
+	set_fs(old_fs);
+
+	return err;
+}
+
+long compat_sys_shmctl(int first, int second, void __user *uptr)
+{
+	struct shmid64_ds s64;
+	struct shminfo64 smi;
+	struct shm_info si;
+	int err, err2;
+	int version = compat_ipc_parse_version(&second);
+
+	switch (second & (~IPC_64)) {
+	case IPC_RMID:
+	case SHM_LOCK:
+	case SHM_UNLOCK:
+		err = sys_shmctl(first, second, uptr);
+		break;
+
+	case IPC_INFO:
+		err = do_shmctl(first, second, &smi);
+		if (err < 0)
+			break;
+
+		if (version == IPC_64) {
+			err2 = put_compat_shminfo64(&smi, uptr);
+		} else {
+			err2 = put_compat_shminfo(&smi, uptr);
+		}
+		if (err2)
+			err = -EFAULT;
+		break;
+
+
+	case IPC_SET:
+		if (version == IPC_64) {
+			err = get_compat_shmid64_ds(&s64, uptr);
+		} else {
+			err = get_compat_shmid_ds(&s64, uptr);
+		}
+		if (err)
+			break;
+
+		err = do_shmctl(first, second, &s64);
+		break;
+
+	case IPC_STAT:
+	case SHM_STAT:
+		err = do_shmctl(first, second, &s64);
+		if (err < 0)
+			break;
+
+		if (version == IPC_64) {
+			err2 = put_compat_shmid64_ds(&s64, uptr);
+		} else {
+			err2 = put_compat_shmid_ds(&s64, uptr);
+		}
+		if (err2)
+			err = -EFAULT;
+		break;
+
+	case SHM_INFO:
+		err = do_shmctl(first, second, &si);
+		if (err < 0)
+			break;
+		err2 = put_compat_shm_info(&si, uptr);
+		if (err2)
+			err = -EFAULT;
+		break;
+
+	default:
+		err = -EINVAL;
+		break;
+	}
+	return err;
+}
+
+long compat_sys_semtimedop(int semid, struct sembuf __user *tsems,
+		unsigned nsops, const struct compat_timespec __user *timeout)
+{
+	struct timespec ts, __user *ts64;
+
+	/* parameter checking precedence should mirror sys_semtimedop() */
+	if (nsops < 1 || semid < 0)
+		return -EINVAL;
+	if (nsops > sc_semopm)
+		return -E2BIG;
+	if (!access_ok(VERIFY_READ, tsems, nsops * sizeof(struct sembuf)))
+		return -EFAULT;
+	if (!timeout)
+		return sys_semtimedop(semid, tsems, nsops, 0);
+
+	ts64 = compat_alloc_user_space(sizeof(*ts64));
+	if (get_compat_timespec(&ts, timeout))
+		return -EFAULT;
+	if (copy_to_user(ts64, &ts, sizeof(ts)))
+		return -EFAULT;
+
+	return sys_semtimedop(semid, tsems, nsops, ts64);
+}
--- diff/kernel/compat_signal.c	1970-01-01 01:00:00.000000000 +0100
+++ source/kernel/compat_signal.c	2004-02-23 13:56:48.000000000 +0000
@@ -0,0 +1,124 @@
+/*
+ *  Copyright (C) 2003 Carlos O'Donell
+ *
+ *  2003-12-20  Carlos O'Donell
+ *              Copied linux/kernel/compat_signal.c (copy_siginfo_to_user)
+ *              and modified to use compat_siginfo_t for thunking down to
+ *              32-bit userspace from a 64-bit kernel.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#include <linux/compat_siginfo.h>
+#include <asm/errno.h>
+#include <asm/uaccess.h>
+#include <asm/siginfo.h>
+
+#ifndef HAVE_ARCH_COMPAT_COPY_SIGINFO_TO_USER
+
+int compat_copy_siginfo_to_user(compat_siginfo_t __user *to, siginfo_t *from)
+{
+	int err;
+	compat_siginfo_t compat_from;
+
+	if (!access_ok (VERIFY_WRITE, to, sizeof(compat_siginfo_t)))
+		return -EFAULT;
+
+	/*
+	 * If you change compat_siginfo_t structure *or* siginfo_t,
+	 * please be sure this code is fixed accordingly.
+	 * It should never copy any pad contained in the structure
+	 * to avoid security leaks, but must copy the generic
+	 * 3 ints plus the relevant union member.
+	 */
+
+	/* Convert structure, don't leak anything in the copy */
+	memset(&compat_from,'\0',sizeof(compat_siginfo_t));
+	compat_from.si_signo = (compat_int_t)(from->si_signo);
+	compat_from.si_errno = (compat_int_t)(from->si_errno);
+	compat_from.si_code = (compat_int_t)(from->si_code);
+
+	if (from->si_code < 0)
+		return __copy_to_user(to, &compat_from, sizeof(compat_siginfo_t))
+			? -EFAULT : 0;
+
+	err = __put_user(compat_from.si_signo, &to->si_signo);
+	err |= __put_user(compat_from.si_errno, &to->si_errno);
+	err |= __put_user(compat_from.si_code, &to->si_code);
+
+	switch (from->si_code & __SI_MASK) {
+	case __SI_KILL:
+		compat_from.si_pid = (compat_pid_t)(from->si_pid);
+		compat_from.si_uid = (__ARCH_SI_COMPAT_UID_T)(from->si_uid);
+		err |= __put_user(compat_from.si_pid, &to->si_pid);
+		err |= __put_user(compat_from.si_uid, &to->si_uid);
+		break;
+	case __SI_TIMER:
+		compat_from.si_pid = (compat_timer_t)(from->si_tid);
+		compat_from.si_overrun = (compat_int_t)(from->si_overrun);
+		compat_from.si_ptr = (compat_uptr_t)((u64)(from->si_ptr) & 0xffffffffUL);
+		err |= __put_user(compat_from.si_tid, &to->si_tid);
+		err |= __put_user(compat_from.si_overrun, &to->si_overrun);
+		err |= __put_user(compat_from.si_ptr, &to->si_ptr);
+		break;
+	case __SI_POLL:
+		compat_from.si_band = (__ARCH_SI_COMPAT_BAND_T)(from->si_band);
+		compat_from.si_fd = (compat_int_t)(from->si_fd);
+		err |= __put_user(compat_from.si_band, &to->si_band);
+		err |= __put_user(compat_from.si_fd, &to->si_fd);
+		break;
+	case __SI_FAULT:
+		compat_from.si_addr = (compat_uptr_t)((u64)(from->si_addr) & 0xffffffffUL);
+		err |= __put_user(compat_from.si_addr, &to->si_addr);
+#ifdef __ARCH_SI_COMPAT_TRAPNO
+		compat_from.si_trapno = (compat_int_t)(from->si_addr);
+		err |= __put_user(compat_from.si_trapno, &to->si_trapno);
+#endif
+		break;
+	case __SI_CHLD:
+		compat_from.si_pid = (compat_pid_t)(from->si_pid);
+		compat_from.si_uid = (__ARCH_SI_COMPAT_UID_T)(from->si_uid);
+		compat_from.si_status = (compat_int_t)(from->si_status);
+		compat_from.si_utime = (compat_clock_t)(from->si_utime);
+		compat_from.si_stime = (compat_clock_t)(from->si_stime);
+		err |= __put_user(compat_from.si_pid, &to->si_pid);
+		err |= __put_user(compat_from.si_uid, &to->si_uid);
+		err |= __put_user(compat_from.si_status, &to->si_status);
+		err |= __put_user(compat_from.si_utime, &to->si_utime);
+		err |= __put_user(compat_from.si_stime, &to->si_stime);
+		break;
+	case __SI_RT: /* This is not generated by the kernel as of now. */
+		compat_from.si_pid = (compat_pid_t)(from->si_pid);
+		compat_from.si_uid = (__ARCH_SI_COMPAT_UID_T)(from->si_uid);
+		compat_from.si_int = (compat_int_t)(from->si_int);
+		compat_from.si_ptr = (compat_uptr_t)((u64)(from->si_ptr) & 0xffffffffUL);
+		err |= __put_user(compat_from.si_pid, &to->si_pid);
+		err |= __put_user(compat_from.si_uid, &to->si_uid);
+		err |= __put_user(compat_from.si_int, &to->si_int);
+		err |= __put_user(compat_from.si_ptr, &to->si_ptr);
+		break;
+	default: /* this is just in case for now ... */
+		compat_from.si_pid = (compat_pid_t)(from->si_pid);
+		compat_from.si_uid = (__ARCH_SI_COMPAT_UID_T)(from->si_uid);
+		err |= __put_user(compat_from.si_pid, &to->si_pid);
+		err |= __put_user(compat_from.si_uid, &to->si_uid);
+		break;
+	}
+	return err;
+}
+
+#endif
--- diff/kernel/kthread.c	1970-01-01 01:00:00.000000000 +0100
+++ source/kernel/kthread.c	2004-02-23 13:56:48.000000000 +0000
@@ -0,0 +1,163 @@
+/* Kernel thread helper functions.
+ *   Copyright (C) 2004 IBM Corporation, Rusty Russell.
+ *
+ * Creation is done via keventd, so that we get a clean environment
+ * even if we're invoked from userspace (think modprobe, hotplug cpu,
+ * etc.).
+ */
+#include <linux/sched.h>
+#include <linux/kthread.h>
+#include <linux/completion.h>
+#include <linux/err.h>
+#include <linux/unistd.h>
+#include <asm/semaphore.h>
+
+struct kthread_create_info
+{
+	/* Information passed to kthread() from keventd. */
+	int (*threadfn)(void *data);
+	void *data;
+	struct completion started;
+
+	/* Result passed back to kthread_create() from keventd. */
+	struct task_struct *result;
+	struct completion done;
+};
+
+struct kthread_stop_info
+{
+	struct task_struct *k;
+	int err;
+	struct completion done;
+};
+
+/* Thread stopping is done by setthing this var: lock serializes
+ * multiple kthread_stop calls. */
+static DECLARE_MUTEX(kthread_stop_lock);
+static struct kthread_stop_info kthread_stop_info;
+
+int kthread_should_stop(void)
+{
+	return (kthread_stop_info.k == current);
+}
+
+static int kthread(void *_create)
+{
+	struct kthread_create_info *create = _create;
+	int (*threadfn)(void *data);
+	void *data;
+	sigset_t blocked;
+	int ret = -EINTR;
+	cpumask_t mask = CPU_MASK_ALL;
+
+	/* Copy data: it's on keventd's stack */
+	threadfn = create->threadfn;
+	data = create->data;
+
+	/* Block and flush all signals (in case we're not from keventd). */
+	sigfillset(&blocked);
+	sigprocmask(SIG_BLOCK, &blocked, NULL);
+	flush_signals(current);
+
+	/* By default we can run anywhere, unlike keventd. */
+	set_cpus_allowed(current, mask);
+
+	/* OK, tell user we're spawned, wait for stop or wakeup */
+	__set_current_state(TASK_INTERRUPTIBLE);
+	complete(&create->started);
+	schedule();
+
+	if (!kthread_should_stop())
+		ret = threadfn(data);
+
+	/* It might have exited on its own, w/o kthread_stop.  Check. */
+	if (kthread_should_stop()) {
+		kthread_stop_info.err = ret;
+		complete(&kthread_stop_info.done);
+	}
+	return 0;
+}
+
+/* We are keventd: create a thread. */
+static void keventd_create_kthread(void *_create)
+{
+	struct kthread_create_info *create = _create;
+	int pid;
+
+	/* We want our own signal handler (we take no signals by default). */
+	pid = kernel_thread(kthread, create, CLONE_FS | CLONE_FILES | SIGCHLD);
+	if (pid < 0) {
+		create->result = ERR_PTR(pid);
+	} else {
+		wait_for_completion(&create->started);
+		create->result = find_task_by_pid(pid);
+		wait_task_inactive(create->result);
+	}
+	complete(&create->done);
+}
+
+struct task_struct *kthread_create(int (*threadfn)(void *data),
+				   void *data,
+				   const char namefmt[],
+				   ...)
+{
+	struct kthread_create_info create;
+	DECLARE_WORK(work, keventd_create_kthread, &create);
+
+	create.threadfn = threadfn;
+	create.data = data;
+	init_completion(&create.started);
+	init_completion(&create.done);
+
+	/* If we're being called to start the first workqueue, we
+	 * can't use keventd. */
+	if (!keventd_up())
+		work.func(work.data);
+	else {
+		schedule_work(&work);
+		wait_for_completion(&create.done);
+	}
+	if (!IS_ERR(create.result)) {
+		va_list args;
+		va_start(args, namefmt);
+		vsnprintf(create.result->comm, sizeof(create.result->comm),
+			  namefmt, args);
+		va_end(args);
+	}
+
+	return create.result;
+}
+
+void kthread_bind(struct task_struct *k, unsigned int cpu)
+{
+	BUG_ON(k->state != TASK_INTERRUPTIBLE);
+	k->thread_info->cpu = cpu;
+	k->cpus_allowed = cpumask_of_cpu(cpu);
+}
+
+int kthread_stop(struct task_struct *k)
+{
+	int ret;
+
+	down(&kthread_stop_lock);
+
+	/* It could exit after stop_info.k set, but before wake_up_process. */
+	get_task_struct(k);
+
+	/* Must init completion *before* thread sees kthread_stop_info.k */
+	init_completion(&kthread_stop_info.done);
+	wmb();
+
+	/* Now set kthread_should_stop() to true, and wake it up. */
+	kthread_stop_info.k = k;
+	wake_up_process(k);
+	put_task_struct(k);
+
+	/* Once it dies, reset stop ptr, gather result and we're done. */
+	wait_for_completion(&kthread_stop_info.done);
+	kthread_stop_info.k = NULL;
+	ret = kthread_stop_info.err;
+	up(&kthread_stop_lock);
+
+	return ret;
+}
--- diff/kernel/lockmeter.c	1970-01-01 01:00:00.000000000 +0100
+++ source/kernel/lockmeter.c	2004-02-23 13:56:48.000000000 +0000
@@ -0,0 +1,1178 @@
+/*
+ *  Copyright (C) 1999,2000 Silicon Graphics, Inc.
+ *
+ *  Written by John Hawkes (hawkes@sgi.com)
+ *  Based on klstat.c by Jack Steiner (steiner@sgi.com)
+ *
+ *  Modified by Ray Bryant (raybry@us.ibm.com)
+ *  Changes Copyright (C) 2000 IBM, Inc.
+ *  Added save of index in spinlock_t to improve efficiency
+ *  of "hold" time reporting for spinlocks
+ *  Added support for hold time statistics for read and write
+ *  locks.
+ */
+
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/slab.h>
+#include <linux/sched.h>
+#include <linux/smp.h>
+#include <linux/threads.h>
+#include <linux/version.h>
+#include <linux/vmalloc.h>
+#include <linux/spinlock.h>
+#include <linux/utsname.h>
+#include <linux/module.h>
+#include <asm/system.h>
+#include <asm/uaccess.h>
+
+#include <linux/lockmeter.h>
+
+#define ASSERT(cond)
+#define bzero(loc,size)		memset(loc,0,size)
+
+/*<---------------------------------------------------*/
+/*              lockmeter.c                           */
+/*>---------------------------------------------------*/
+
+static lstat_control_t lstat_control __cacheline_aligned =
+	{ LSTAT_OFF, SPIN_LOCK_UNLOCKED, SPIN_LOCK_UNLOCKED,
+	  19 * 0, NR_CPUS * 0, 0, NR_CPUS * 0 };
+
+static ushort lstat_make_dir_entry(void *, void *);
+
+/*
+ * lstat_lookup
+ *
+ * Given a RA, locate the directory entry for the lock.
+ */
+static ushort
+lstat_lookup(void *lock_ptr, void *caller_ra)
+{
+	ushort index;
+	lstat_directory_entry_t *dirp;
+
+	dirp = lstat_control.dir;
+
+	index = lstat_control.hashtab[DIRHASH(caller_ra)];
+	while (dirp[index].caller_ra != caller_ra) {
+		if (index == 0) {
+			return lstat_make_dir_entry(lock_ptr, caller_ra);
+		}
+		index = dirp[index].next_stat_index;
+	}
+
+	if (dirp[index].lock_ptr != NULL && dirp[index].lock_ptr != lock_ptr) {
+		dirp[index].lock_ptr = NULL;
+	}
+
+	return index;
+}
+
+/*
+ * lstat_make_dir_entry
+ * Called to add a new lock to the lock directory.
+ */
+static ushort
+lstat_make_dir_entry(void *lock_ptr, void *caller_ra)
+{
+	lstat_directory_entry_t *dirp;
+	ushort index, hindex;
+	unsigned long flags;
+
+	/* lock the table without recursively reentering this metering code */
+	local_irq_save(flags);
+	_raw_spin_lock(&lstat_control.directory_lock);
+
+	hindex = DIRHASH(caller_ra);
+	index = lstat_control.hashtab[hindex];
+	dirp = lstat_control.dir;
+	while (index && dirp[index].caller_ra != caller_ra)
+		index = dirp[index].next_stat_index;
+
+	if (index == 0) {
+		if (lstat_control.next_free_dir_index < LSTAT_MAX_STAT_INDEX) {
+			index = lstat_control.next_free_dir_index++;
+			lstat_control.dir[index].caller_ra = caller_ra;
+			lstat_control.dir[index].lock_ptr = lock_ptr;
+			lstat_control.dir[index].next_stat_index =
+				lstat_control.hashtab[hindex];
+			lstat_control.hashtab[hindex] = index;
+		} else {
+			lstat_control.dir_overflow++;
+		}
+	}
+	_raw_spin_unlock(&lstat_control.directory_lock);
+	local_irq_restore(flags);
+	return index;
+}
+
+int
+lstat_update(void *lock_ptr, void *caller_ra, int action)
+{
+	int index;
+	int cpu;
+
+	ASSERT(action < LSTAT_ACT_MAX_VALUES);
+
+	if (lstat_control.state == LSTAT_OFF)
+		return 0;
+
+	index = lstat_lookup(lock_ptr, caller_ra);
+	cpu = THIS_CPU_NUMBER;
+	(*lstat_control.counts[cpu])[index].count[action]++;
+	(*lstat_control.counts[cpu])[index].acquire_time = get_cycles();
+
+	return index;
+}
+
+int
+lstat_update_time(void *lock_ptr, void *caller_ra, int action, uint32_t ticks)
+{
+	ushort index;
+	int cpu;
+
+	ASSERT(action < LSTAT_ACT_MAX_VALUES);
+
+	if (lstat_control.state == LSTAT_OFF)
+		return 0;
+
+	index = lstat_lookup(lock_ptr, caller_ra);
+	cpu = THIS_CPU_NUMBER;
+	(*lstat_control.counts[cpu])[index].count[action]++;
+	(*lstat_control.counts[cpu])[index].cum_wait_ticks += (uint64_t) ticks;
+	if ((*lstat_control.counts[cpu])[index].max_wait_ticks < ticks)
+		(*lstat_control.counts[cpu])[index].max_wait_ticks = ticks;
+
+	(*lstat_control.counts[cpu])[index].acquire_time = get_cycles();
+
+	return index;
+}
+
+void
+_metered_spin_lock(spinlock_t * lock_ptr)
+{
+	if (lstat_control.state == LSTAT_OFF) {
+		_raw_spin_lock(lock_ptr);	/* do the real lock */
+		PUT_INDEX(lock_ptr, 0);	/* clean index in case lockmetering  */
+		/* gets turned on before unlock */
+	} else {
+		void *this_pc = LSTAT_RA(LSTAT_RA_SPIN);
+		int index;
+
+		if (_raw_spin_trylock(lock_ptr)) {
+			index = lstat_update(lock_ptr, this_pc,
+						LSTAT_ACT_NO_WAIT);
+		} else {
+			uint32_t start_cycles = get_cycles();
+			_raw_spin_lock(lock_ptr);	/* do the real lock */
+			index = lstat_update_time(lock_ptr, this_pc,
+				LSTAT_ACT_SPIN, get_cycles() - start_cycles);
+		}
+		/* save the index in the lock itself for use in spin unlock */
+		PUT_INDEX(lock_ptr, index);
+	}
+}
+
+int
+_metered_spin_trylock(spinlock_t * lock_ptr)
+{
+	if (lstat_control.state == LSTAT_OFF) {
+		return _raw_spin_trylock(lock_ptr);
+	} else {
+		int retval;
+		void *this_pc = LSTAT_RA(LSTAT_RA_SPIN);
+
+		if ((retval = _raw_spin_trylock(lock_ptr))) {
+			int index = lstat_update(lock_ptr, this_pc,
+						LSTAT_ACT_NO_WAIT);
+			/*
+			 * save the index in the lock itself for use in spin
+			 * unlock
+			 */
+			PUT_INDEX(lock_ptr, index);
+		} else {
+			lstat_update(lock_ptr, this_pc, LSTAT_ACT_REJECT);
+		}
+
+		return retval;
+	}
+}
+
+void
+_metered_spin_unlock(spinlock_t * lock_ptr)
+{
+	int index = -1;
+
+	if (lstat_control.state != LSTAT_OFF) {
+		index = GET_INDEX(lock_ptr);
+		/*
+		 * If statistics were turned off when we set the lock,
+		 * then the index can be zero.  If that is the case,
+		 * then collect no stats on this call.
+		 */
+		if (index > 0) {
+			uint32_t hold_time;
+			int cpu = THIS_CPU_NUMBER;
+			hold_time = get_cycles() -
+			 (*lstat_control.counts[cpu])[index].acquire_time;
+			(*lstat_control.counts[cpu])[index].cum_hold_ticks +=
+				(uint64_t) hold_time;
+			if ((*lstat_control.counts[cpu])[index].max_hold_ticks <
+			    hold_time)
+				(*lstat_control.counts[cpu])[index].
+				    max_hold_ticks = hold_time;
+		}
+	}
+
+	/* make sure we don't have a stale index value saved */
+	PUT_INDEX(lock_ptr, 0);
+	_raw_spin_unlock(lock_ptr);	/* do the real unlock */
+}
+
+/*
+ * allocate the next global read lock structure and store its index
+ * in the rwlock at "lock_ptr".
+ */
+uint32_t
+alloc_rwlock_struct(rwlock_t * rwlock_ptr)
+{
+	int index;
+	unsigned long flags;
+	int cpu = THIS_CPU_NUMBER;
+
+	/* If we've already overflowed, then do a quick exit */
+	if (lstat_control.next_free_read_lock_index >
+			LSTAT_MAX_READ_LOCK_INDEX) {
+		lstat_control.rwlock_overflow++;
+		return 0;
+	}
+
+	local_irq_save(flags);
+	_raw_spin_lock(&lstat_control.directory_lock);
+
+	/* It is possible this changed while we were waiting for the directory_lock */
+	if (lstat_control.state == LSTAT_OFF) {
+		index = 0;
+		goto unlock;
+	}
+
+	/* It is possible someone else got here first and set the index */
+	if ((index = GET_RWINDEX(rwlock_ptr)) == 0) {
+		/*
+		 * we can't turn on read stats for this lock while there are
+		 * readers (this would mess up the running hold time sum at
+		 * unlock time)
+		 */
+		if (RWLOCK_READERS(rwlock_ptr) != 0) {
+			index = 0;
+			goto unlock;
+		}
+
+		/*
+		 * if stats are turned on after being off, we may need to
+		 * return an old index from when the statistics were on last
+		 * time.
+		 */
+		for (index = 1; index < lstat_control.next_free_read_lock_index;
+				index++)
+			if ((*lstat_control.read_lock_counts[cpu])[index].
+					lock_ptr == rwlock_ptr)
+				goto put_index_and_unlock;
+
+		/* allocate the next global read lock structure */
+		if (lstat_control.next_free_read_lock_index >=
+		    LSTAT_MAX_READ_LOCK_INDEX) {
+			lstat_control.rwlock_overflow++;
+			index = 0;
+			goto unlock;
+		}
+		index = lstat_control.next_free_read_lock_index++;
+
+		/*
+		 * initialize the global read stats data structure for each
+		 * cpu
+		 */
+		for (cpu = 0; cpu < num_online_cpus(); cpu++) {
+			(*lstat_control.read_lock_counts[cpu])[index].lock_ptr =
+				rwlock_ptr;
+		}
+put_index_and_unlock:
+		/* store the index for the read lock structure into the lock */
+		PUT_RWINDEX(rwlock_ptr, index);
+	}
+
+unlock:
+	_raw_spin_unlock(&lstat_control.directory_lock);
+	local_irq_restore(flags);
+	return index;
+}
+
+void
+_metered_read_lock(rwlock_t * rwlock_ptr)
+{
+	void *this_pc;
+	uint32_t start_cycles;
+	int index;
+	int cpu;
+	unsigned long flags;
+	int readers_before, readers_after;
+	uint64_t cycles64;
+
+	if (lstat_control.state == LSTAT_OFF) {
+		_raw_read_lock(rwlock_ptr);
+		/* clean index in case lockmetering turns on before an unlock */
+		PUT_RWINDEX(rwlock_ptr, 0);
+		return;
+	}
+
+	this_pc = LSTAT_RA(LSTAT_RA_READ);
+	cpu = THIS_CPU_NUMBER;
+	index = GET_RWINDEX(rwlock_ptr);
+
+	/* allocate the global stats entry for this lock, if needed */
+	if (index == 0)
+		index = alloc_rwlock_struct(rwlock_ptr);
+
+	readers_before = RWLOCK_READERS(rwlock_ptr);
+	if (_raw_read_trylock(rwlock_ptr)) {
+		/*
+		 * We have decremented the lock to count a new reader,
+		 * and have confirmed that no writer has it locked.
+		 */
+		/* update statistics if enabled */
+		if (index > 0) {
+			local_irq_save(flags);
+			lstat_update((void *) rwlock_ptr, this_pc,
+					LSTAT_ACT_NO_WAIT);
+			/* preserve value of TSC so cum_hold_ticks and start_busy use same value */
+			cycles64 = get_cycles64();
+			(*lstat_control.read_lock_counts[cpu])[index].
+				cum_hold_ticks -= cycles64;
+
+			/* record time and cpu of start of busy period */
+			/* this is not perfect (some race conditions are possible) */
+			if (readers_before == 0) {
+				(*lstat_control.read_lock_counts[cpu])[index].
+					start_busy = cycles64;
+				PUT_RW_CPU(rwlock_ptr, cpu);
+			}
+			readers_after = RWLOCK_READERS(rwlock_ptr);
+			if (readers_after >
+				(*lstat_control.read_lock_counts[cpu])[index].
+					max_readers)
+				(*lstat_control.read_lock_counts[cpu])[index].
+					max_readers = readers_after;
+			local_irq_restore(flags);
+		}
+
+		return;
+	}
+	/* If we get here, then we could not quickly grab the read lock */
+
+	start_cycles = get_cycles();	/* start counting the wait time */
+
+	/* Now spin until read_lock is successful */
+	_raw_read_lock(rwlock_ptr);
+
+	lstat_update_time((void *) rwlock_ptr, this_pc, LSTAT_ACT_SPIN,
+			  get_cycles() - start_cycles);
+
+	/* update statistics if they are enabled for this lock */
+	if (index > 0) {
+		local_irq_save(flags);
+		cycles64 = get_cycles64();
+		(*lstat_control.read_lock_counts[cpu])[index].cum_hold_ticks -=
+				cycles64;
+
+		/* this is not perfect (some race conditions are possible) */
+		if (readers_before == 0) {
+			(*lstat_control.read_lock_counts[cpu])[index].
+				start_busy = cycles64;
+			PUT_RW_CPU(rwlock_ptr, cpu);
+		}
+		readers_after = RWLOCK_READERS(rwlock_ptr);
+		if (readers_after >
+		    (*lstat_control.read_lock_counts[cpu])[index].max_readers)
+			(*lstat_control.read_lock_counts[cpu])[index].
+				max_readers = readers_after;
+		local_irq_restore(flags);
+	}
+}
+
+void
+_metered_read_unlock(rwlock_t * rwlock_ptr)
+{
+	int index;
+	int cpu;
+	unsigned long flags;
+	uint64_t busy_length;
+	uint64_t cycles64;
+
+	if (lstat_control.state == LSTAT_OFF) {
+		_raw_read_unlock(rwlock_ptr);
+		return;
+	}
+
+	index = GET_RWINDEX(rwlock_ptr);
+	cpu = THIS_CPU_NUMBER;
+
+	if (index > 0) {
+		local_irq_save(flags);
+		/*
+		 * preserve value of TSC so cum_hold_ticks and busy_ticks are
+		 * consistent.
+		 */
+		cycles64 = get_cycles64();
+		(*lstat_control.read_lock_counts[cpu])[index].cum_hold_ticks +=
+			cycles64;
+		(*lstat_control.read_lock_counts[cpu])[index].read_lock_count++;
+
+		/*
+		 * once again, this is not perfect (some race conditions are
+		 * possible)
+		 */
+		if (RWLOCK_READERS(rwlock_ptr) == 1) {
+			int cpu1 = GET_RW_CPU(rwlock_ptr);
+			uint64_t last_start_busy =
+				(*lstat_control.read_lock_counts[cpu1])[index].
+					start_busy;
+			(*lstat_control.read_lock_counts[cpu])[index].
+				busy_periods++;
+			if (cycles64 > last_start_busy) {
+				busy_length = cycles64 - last_start_busy;
+				(*lstat_control.read_lock_counts[cpu])[index].
+					busy_ticks += busy_length;
+				if (busy_length >
+					(*lstat_control.
+						read_lock_counts[cpu])[index].
+							max_busy)
+					(*lstat_control.
+					 read_lock_counts[cpu])[index].
+						max_busy = busy_length;
+			}
+		}
+		local_irq_restore(flags);
+	}
+	_raw_read_unlock(rwlock_ptr);
+}
+
+void
+_metered_write_lock(rwlock_t * rwlock_ptr)
+{
+	uint32_t start_cycles;
+	void *this_pc;
+	uint32_t spin_ticks = 0; /* in anticipation of a potential wait */
+	int index;
+	int write_index = 0;
+	int cpu;
+	enum {
+		writer_writer_conflict,
+		writer_reader_conflict
+	} why_wait = writer_writer_conflict;
+
+	if (lstat_control.state == LSTAT_OFF) {
+		_raw_write_lock(rwlock_ptr);
+		/* clean index in case lockmetering turns on before an unlock */
+		PUT_RWINDEX(rwlock_ptr, 0);
+		return;
+	}
+
+	this_pc = LSTAT_RA(LSTAT_RA_WRITE);
+	cpu = THIS_CPU_NUMBER;
+	index = GET_RWINDEX(rwlock_ptr);
+
+	/* allocate the global stats entry for this lock, if needed */
+	if (index == 0) {
+		index = alloc_rwlock_struct(rwlock_ptr);
+	}
+
+	if (_raw_write_trylock(rwlock_ptr)) {
+		/* We acquired the lock on the first try */
+		write_index = lstat_update((void *) rwlock_ptr, this_pc,
+					LSTAT_ACT_NO_WAIT);
+		/* save the write_index for use in unlock if stats enabled */
+		if (index > 0)
+			(*lstat_control.read_lock_counts[cpu])[index].
+				write_index = write_index;
+		return;
+	}
+
+	/* If we get here, then we could not quickly grab the write lock */
+	start_cycles = get_cycles();	/* start counting the wait time */
+
+	why_wait = RWLOCK_READERS(rwlock_ptr) ?
+			writer_reader_conflict : writer_writer_conflict;
+
+	/* Now set the lock and wait for conflicts to disappear */
+	_raw_write_lock(rwlock_ptr);
+
+	spin_ticks = get_cycles() - start_cycles;
+
+	/* update stats -- if enabled */
+	if (index > 0 && spin_ticks) {
+		if (why_wait == writer_reader_conflict) {
+			/* waited due to a reader holding the lock */
+			write_index = lstat_update_time((void *)rwlock_ptr,
+					this_pc, LSTAT_ACT_SPIN, spin_ticks);
+		} else {
+			/*
+			 * waited due to another writer holding the lock
+			 */
+			write_index = lstat_update_time((void *)rwlock_ptr,
+				this_pc, LSTAT_ACT_WW_SPIN, spin_ticks);
+			(*lstat_control.counts[cpu])[write_index].
+				cum_wait_ww_ticks += spin_ticks;
+			if (spin_ticks >
+				(*lstat_control.counts[cpu])[write_index].
+					max_wait_ww_ticks) {
+				(*lstat_control.counts[cpu])[write_index].
+					max_wait_ww_ticks = spin_ticks;
+			}
+		}
+
+		/* save the directory index for use on write_unlock */
+		(*lstat_control.read_lock_counts[cpu])[index].
+			write_index = write_index;
+	}
+}
+
+void
+_metered_write_unlock(rwlock_t * rwlock_ptr)
+{
+	int index;
+	int cpu;
+	int write_index;
+	uint32_t hold_time;
+
+	if (lstat_control.state == LSTAT_OFF) {
+		_raw_write_unlock(rwlock_ptr);
+		return;
+	}
+
+	cpu = THIS_CPU_NUMBER;
+	index = GET_RWINDEX(rwlock_ptr);
+
+	/* update statistics if stats enabled for this lock */
+	if (index > 0) {
+		write_index =
+		    (*lstat_control.read_lock_counts[cpu])[index].write_index;
+
+		hold_time = get_cycles() -
+			(*lstat_control.counts[cpu])[write_index].acquire_time;
+		(*lstat_control.counts[cpu])[write_index].cum_hold_ticks +=
+			(uint64_t) hold_time;
+		if ((*lstat_control.counts[cpu])[write_index].max_hold_ticks <
+				hold_time)
+			(*lstat_control.counts[cpu])[write_index].
+				max_hold_ticks = hold_time;
+	}
+	_raw_write_unlock(rwlock_ptr);
+}
+
+int
+_metered_write_trylock(rwlock_t * rwlock_ptr)
+{
+	int retval;
+	void *this_pc = LSTAT_RA(LSTAT_RA_WRITE);
+
+	if ((retval = _raw_write_trylock(rwlock_ptr))) {
+		lstat_update(rwlock_ptr, this_pc, LSTAT_ACT_NO_WAIT);
+	} else {
+		lstat_update(rwlock_ptr, this_pc, LSTAT_ACT_REJECT);
+	}
+
+	return retval;
+}
+
+static void
+init_control_space(void)
+{
+	/* Set all control space pointers to null and indices to "empty" */
+	int cpu;
+
+	/*
+	 * Access CPU_CYCLE_FREQUENCY at the outset, which in some
+	 * architectures may trigger a runtime calculation that uses a
+	 * spinlock.  Let's do this before lockmetering is turned on.
+	 */
+	if (CPU_CYCLE_FREQUENCY == 0)
+		BUG();
+
+	lstat_control.hashtab = NULL;
+	lstat_control.dir = NULL;
+	for (cpu = 0; cpu < NR_CPUS; cpu++) {
+		lstat_control.counts[cpu] = NULL;
+		lstat_control.read_lock_counts[cpu] = NULL;
+	}
+}
+
+static int
+reset_lstat_data(void)
+{
+	int cpu, flags;
+
+	flags = 0;
+	lstat_control.next_free_dir_index = 1;	/* 0 is for overflows */
+	lstat_control.next_free_read_lock_index = 1;
+	lstat_control.dir_overflow = 0;
+	lstat_control.rwlock_overflow = 0;
+
+	lstat_control.started_cycles64 = 0;
+	lstat_control.ending_cycles64 = 0;
+	lstat_control.enabled_cycles64 = 0;
+	lstat_control.first_started_time = 0;
+	lstat_control.started_time = 0;
+	lstat_control.ending_time = 0;
+	lstat_control.intervals = 0;
+
+	/*
+	 * paranoia -- in case someone does a "lockstat reset" before
+	 * "lockstat on"
+	 */
+	if (lstat_control.hashtab) {
+		bzero(lstat_control.hashtab,
+			LSTAT_HASH_TABLE_SIZE * sizeof (short));
+		bzero(lstat_control.dir, LSTAT_MAX_STAT_INDEX *
+				sizeof (lstat_directory_entry_t));
+
+		for (cpu = 0; cpu < num_online_cpus(); cpu++) {
+			bzero(lstat_control.counts[cpu],
+				sizeof (lstat_cpu_counts_t));
+			bzero(lstat_control.read_lock_counts[cpu],
+				sizeof (lstat_read_lock_cpu_counts_t));
+		}
+	}
+#ifdef NOTDEF
+	_raw_spin_unlock(&lstat_control.directory_lock);
+	local_irq_restore(flags);
+#endif
+	return 1;
+}
+
+static void
+release_control_space(void)
+{
+	/*
+	 * Called when either (1) allocation of kmem
+	 * or (2) when user writes LSTAT_RELEASE to /pro/lockmeter.
+	 * Assume that all pointers have been initialized to zero,
+	 * i.e., nonzero pointers are valid addresses.
+	 */
+	int cpu;
+
+	if (lstat_control.hashtab) {
+		kfree(lstat_control.hashtab);
+		lstat_control.hashtab = NULL;
+	}
+
+	if (lstat_control.dir) {
+		vfree(lstat_control.dir);
+		lstat_control.dir = NULL;
+	}
+
+	for (cpu = 0; cpu < NR_CPUS; cpu++) {
+		if (lstat_control.counts[cpu]) {
+			vfree(lstat_control.counts[cpu]);
+			lstat_control.counts[cpu] = NULL;
+		}
+		if (lstat_control.read_lock_counts[cpu]) {
+			kfree(lstat_control.read_lock_counts[cpu]);
+			lstat_control.read_lock_counts[cpu] = NULL;
+		}
+	}
+}
+
+int
+get_lockmeter_info_size(void)
+{
+	return sizeof (lstat_user_request_t)
+		+ num_online_cpus() * sizeof (lstat_cpu_counts_t)
+		+ num_online_cpus() * sizeof (lstat_read_lock_cpu_counts_t)
+		+ (LSTAT_MAX_STAT_INDEX * sizeof (lstat_directory_entry_t));
+}
+
+ssize_t
+get_lockmeter_info(char *buffer, size_t max_len, loff_t * last_index)
+{
+	lstat_user_request_t req;
+	struct timeval tv;
+	ssize_t next_ret_bcount;
+	ssize_t actual_ret_bcount = 0;
+	int cpu;
+
+	*last_index = 0;	/* a one-shot read */
+
+	req.lstat_version = LSTAT_VERSION;
+	req.state = lstat_control.state;
+	req.maxcpus = num_online_cpus();
+	req.cycleval = CPU_CYCLE_FREQUENCY;
+#ifdef notyet
+	req.kernel_magic_addr = (void *) &_etext;
+	req.kernel_end_addr = (void *) &_etext;
+#endif
+	req.uts = system_utsname;
+	req.intervals = lstat_control.intervals;
+
+	req.first_started_time = lstat_control.first_started_time;
+	req.started_time = lstat_control.started_time;
+	req.started_cycles64 = lstat_control.started_cycles64;
+
+	req.next_free_dir_index = lstat_control.next_free_dir_index;
+	req.next_free_read_lock_index = lstat_control.next_free_read_lock_index;
+	req.dir_overflow = lstat_control.dir_overflow;
+	req.rwlock_overflow = lstat_control.rwlock_overflow;
+
+	if (lstat_control.state == LSTAT_OFF) {
+		if (req.intervals == 0) {
+			/* mesasurement is off and no valid data present */
+			next_ret_bcount = sizeof (lstat_user_request_t);
+			req.enabled_cycles64 = 0;
+
+			if ((actual_ret_bcount + next_ret_bcount) > max_len)
+				return actual_ret_bcount;
+
+			copy_to_user(buffer, (void *) &req, next_ret_bcount);
+			actual_ret_bcount += next_ret_bcount;
+			return actual_ret_bcount;
+		} else {
+			/*
+			 * measurement is off but valid data present
+			 * fetch time info from lstat_control
+			 */
+			req.ending_time = lstat_control.ending_time;
+			req.ending_cycles64 = lstat_control.ending_cycles64;
+			req.enabled_cycles64 = lstat_control.enabled_cycles64;
+		}
+	} else {
+		/*
+		 * this must be a read while data active--use current time,
+		 * etc
+		 */
+		do_gettimeofday(&tv);
+		req.ending_time = tv.tv_sec;
+		req.ending_cycles64 = get_cycles64();
+		req.enabled_cycles64 = req.ending_cycles64 -
+			req.started_cycles64 + lstat_control.enabled_cycles64;
+	}
+
+	next_ret_bcount = sizeof (lstat_user_request_t);
+	if ((actual_ret_bcount + next_ret_bcount) > max_len)
+		return actual_ret_bcount;
+
+	copy_to_user(buffer, (void *) &req, next_ret_bcount);
+	actual_ret_bcount += next_ret_bcount;
+
+	if (!lstat_control.counts[0])	/* not initialized? */
+		return actual_ret_bcount;
+
+	next_ret_bcount = sizeof (lstat_cpu_counts_t);
+	for (cpu = 0; cpu < num_online_cpus(); cpu++) {
+		if ((actual_ret_bcount + next_ret_bcount) > max_len)
+			return actual_ret_bcount;	/* leave early */
+		copy_to_user(buffer + actual_ret_bcount,
+				lstat_control.counts[cpu], next_ret_bcount);
+		actual_ret_bcount += next_ret_bcount;
+	}
+
+	next_ret_bcount = LSTAT_MAX_STAT_INDEX *
+			sizeof (lstat_directory_entry_t);
+	if (((actual_ret_bcount + next_ret_bcount) > max_len)
+			|| !lstat_control.dir)
+		return actual_ret_bcount;	/* leave early */
+
+	copy_to_user(buffer + actual_ret_bcount, lstat_control.dir,
+			next_ret_bcount);
+	actual_ret_bcount += next_ret_bcount;
+
+	next_ret_bcount = sizeof (lstat_read_lock_cpu_counts_t);
+	for (cpu = 0; cpu < num_online_cpus(); cpu++) {
+		if (actual_ret_bcount + next_ret_bcount > max_len)
+			return actual_ret_bcount;
+		copy_to_user(buffer + actual_ret_bcount,
+				lstat_control.read_lock_counts[cpu],
+				next_ret_bcount);
+		actual_ret_bcount += next_ret_bcount;
+	}
+
+	return actual_ret_bcount;
+}
+
+/*
+ *  Writing to the /proc lockmeter node enables or disables metering.
+ *  based upon the first byte of the "written" data.
+ *  The following values are defined:
+ *  LSTAT_ON: 1st call: allocates storage, intializes and turns on measurement
+ *            subsequent calls just turn on measurement
+ *  LSTAT_OFF: turns off measurement
+ *  LSTAT_RESET: resets statistics
+ *  LSTAT_RELEASE: releases statistics storage
+ *
+ *  This allows one to accumulate statistics over several lockstat runs:
+ *
+ *  lockstat on
+ *  lockstat off
+ *  ...repeat above as desired...
+ *  lockstat get
+ *  ...now start a new set of measurements...
+ *  lockstat reset
+ *  lockstat on
+ *  ...
+ *
+ */
+ssize_t
+put_lockmeter_info(const char *buffer, size_t len)
+{
+	int error = 0;
+	int dirsize, countsize, read_lock_countsize, hashsize;
+	int cpu;
+	char put_char;
+	int i, read_lock_blocks;
+	unsigned long flags;
+	rwlock_t *lock_ptr;
+	struct timeval tv;
+
+	if (len <= 0)
+		return -EINVAL;
+
+	_raw_spin_lock(&lstat_control.control_lock);
+
+	get_user(put_char, buffer);
+	switch (put_char) {
+
+	case LSTAT_OFF:
+		if (lstat_control.state != LSTAT_OFF) {
+			/*
+			 * To avoid seeing read lock hold times in an
+			 * inconsisent state, we have to follow this protocol
+			 * to turn off statistics
+			 */
+			local_irq_save(flags);
+			/*
+			 * getting this lock will stop any read lock block
+			 * allocations
+			 */
+			_raw_spin_lock(&lstat_control.directory_lock);
+			/*
+			 * keep any more read lock blocks from being
+			 * allocated
+			 */
+			lstat_control.state = LSTAT_OFF;
+			/* record how may read lock blocks there are */
+			read_lock_blocks =
+				lstat_control.next_free_read_lock_index;
+			_raw_spin_unlock(&lstat_control.directory_lock);
+			/* now go through the list of read locks */
+			cpu = THIS_CPU_NUMBER;
+			for (i = 1; i < read_lock_blocks; i++) {
+				lock_ptr =
+				    (*lstat_control.read_lock_counts[cpu])[i].
+				    lock_ptr;
+				/* is this saved lock address still valid? */
+				if (GET_RWINDEX(lock_ptr) == i) {
+					/*
+					 * lock address appears to still be
+					 * valid because we only hold one lock
+					 * at a time, this can't cause a
+					 * deadlock unless this is a lock held
+					 * as part of the current system call
+					 * path. At the moment there
+					 * are no READ mode locks held to get
+					 * here from user space, so we solve
+					 * this by skipping locks held in
+					 * write mode.
+					 */
+					if (RWLOCK_IS_WRITE_LOCKED(lock_ptr)) {
+						PUT_RWINDEX(lock_ptr, 0);
+						continue;
+					}
+					/*
+					 * now we know there are no read
+					 * holders of this lock! stop
+					 * statistics collection for this
+					 * lock
+					 */
+					_raw_write_lock(lock_ptr);
+					PUT_RWINDEX(lock_ptr, 0);
+					_raw_write_unlock(lock_ptr);
+				}
+				/*
+				 * it may still be possible for the hold time
+				 * sum to be negative e.g. if a lock is
+				 * reallocated while "busy" we will have to fix
+				 * this up in the data reduction program.
+				 */
+			}
+			local_irq_restore(flags);
+			lstat_control.intervals++;
+			lstat_control.ending_cycles64 = get_cycles64();
+			lstat_control.enabled_cycles64 +=
+				lstat_control.ending_cycles64 -
+				lstat_control.started_cycles64;
+			do_gettimeofday(&tv);
+			lstat_control.ending_time = tv.tv_sec;
+			/*
+			 * don't deallocate the structures -- we may do a
+			 * lockstat on to add to the data that is already
+			 * there. Use LSTAT_RELEASE to release storage
+			 */
+		} else {
+			error = -EBUSY;	/* already OFF */
+		}
+		break;
+
+	case LSTAT_ON:
+		if (lstat_control.state == LSTAT_OFF) {
+#ifdef DEBUG_LOCKMETER
+			printk("put_lockmeter_info(cpu=%d): LSTAT_ON\n",
+				THIS_CPU_NUMBER);
+#endif
+			lstat_control.next_free_dir_index = 1;	/* 0 is for overflows */
+
+			dirsize = LSTAT_MAX_STAT_INDEX *
+					sizeof (lstat_directory_entry_t);
+			hashsize =
+				(1 + LSTAT_HASH_TABLE_SIZE) * sizeof (ushort);
+			countsize = sizeof (lstat_cpu_counts_t);
+			read_lock_countsize =
+				sizeof (lstat_read_lock_cpu_counts_t);
+#ifdef DEBUG_LOCKMETER
+			printk(" dirsize:%d", dirsize);
+			printk(" hashsize:%d", hashsize);
+			printk(" countsize:%d", countsize);
+			printk(" read_lock_countsize:%d\n",
+				read_lock_countsize);
+#endif
+#ifdef DEBUG_LOCKMETER
+			{
+				int secs;
+				unsigned long cycles;
+				uint64_t cycles64;
+
+				do_gettimeofday(&tv);
+				secs = tv.tv_sec;
+				do {
+					do_gettimeofday(&tv);
+				} while (secs == tv.tv_sec);
+				cycles = get_cycles();
+				cycles64 = get_cycles64();
+				secs = tv.tv_sec;
+				do {
+					do_gettimeofday(&tv);
+				} while (secs == tv.tv_sec);
+				cycles = get_cycles() - cycles;
+				cycles64 = get_cycles64() - cycles;
+				printk("lockmeter: cycleFrequency:%d "
+					"cycles:%d cycles64:%d\n",
+					CPU_CYCLE_FREQUENCY, cycles, cycles64);
+			}
+#endif
+
+			/*
+			 * if this is the first call, allocate storage and
+			 * initialize
+			 */
+			if (!lstat_control.hashtab) {
+
+				spin_lock_init(&lstat_control.directory_lock);
+
+				/* guarantee all pointers at zero */
+				init_control_space();
+
+				lstat_control.hashtab =
+				    kmalloc(hashsize, GFP_KERNEL);
+				if (!lstat_control.hashtab) {
+					error = -ENOSPC;
+#ifdef DEBUG_LOCKMETER
+					printk("!!error kmalloc of hashtab\n");
+#endif
+				}
+				lstat_control.dir = vmalloc(dirsize);
+				if (!lstat_control.dir) {
+					error = -ENOSPC;
+#ifdef DEBUG_LOCKMETER
+					printk("!!error kmalloc of dir\n");
+#endif
+				}
+
+				for (cpu = 0; cpu < num_online_cpus(); cpu++) {
+					lstat_control.counts[cpu] =
+						vmalloc(countsize);
+					if (!lstat_control.counts[cpu]) {
+						error = -ENOSPC;
+#ifdef DEBUG_LOCKMETER
+						printk("!!error vmalloc of "
+							"counts[%d]\n", cpu);
+#endif
+					}
+					lstat_control.read_lock_counts[cpu] =
+						(lstat_read_lock_cpu_counts_t *)
+						kmalloc(read_lock_countsize,
+							GFP_KERNEL);
+					if (!lstat_control.
+							read_lock_counts[cpu]) {
+						error = -ENOSPC;
+#ifdef DEBUG_LOCKMETER
+						printk("!!error kmalloc of "
+						  "read_lock_counts[%d]\n",
+							cpu);
+#endif
+					}
+				}
+			}
+
+			if (error) {
+				/*
+				 * One or more kmalloc failures -- free
+				 * everything
+				 */
+				release_control_space();
+			} else {
+
+				if (!reset_lstat_data()) {
+					error = -EINVAL;
+					break;
+				};
+
+				/*
+				 * record starting and ending times and the
+				 * like
+				 */
+				if (lstat_control.intervals == 0) {
+					do_gettimeofday(&tv);
+					lstat_control.first_started_time =
+						tv.tv_sec;
+				}
+				lstat_control.started_cycles64 = get_cycles64();
+				do_gettimeofday(&tv);
+				lstat_control.started_time = tv.tv_sec;
+
+				lstat_control.state = LSTAT_ON;
+			}
+		} else {
+			error = -EBUSY;	/* already ON */
+		}
+		break;
+
+	case LSTAT_RESET:
+		if (lstat_control.state == LSTAT_OFF) {
+			if (!reset_lstat_data())
+				error = -EINVAL;
+		} else {
+			error = -EBUSY;	/* still on; can't reset */
+		}
+		break;
+
+	case LSTAT_RELEASE:
+		if (lstat_control.state == LSTAT_OFF) {
+			release_control_space();
+			lstat_control.intervals = 0;
+			lstat_control.enabled_cycles64 = 0;
+		} else {
+			error = -EBUSY;
+		}
+		break;
+
+	default:
+		error = -EINVAL;
+	}			/* switch */
+
+	_raw_spin_unlock(&lstat_control.control_lock);
+	return error ? error : len;
+}
+
+#ifdef USER_MODE_TESTING
+/* following used for user mode testing */
+void
+lockmeter_init()
+{
+	int dirsize, hashsize, countsize, read_lock_countsize, cpu;
+
+	printf("lstat_control is at %x size=%d\n", &lstat_control,
+		sizeof (lstat_control));
+	printf("sizeof(spinlock_t)=%d\n", sizeof (spinlock_t));
+	lstat_control.state = LSTAT_ON;
+
+	lstat_control.directory_lock = SPIN_LOCK_UNLOCKED;
+	lstat_control.next_free_dir_index = 1;	/* 0 is for overflows */
+	lstat_control.next_free_read_lock_index = 1;
+
+	dirsize = LSTAT_MAX_STAT_INDEX * sizeof (lstat_directory_entry_t);
+	hashsize = (1 + LSTAT_HASH_TABLE_SIZE) * sizeof (ushort);
+	countsize = sizeof (lstat_cpu_counts_t);
+	read_lock_countsize = sizeof (lstat_read_lock_cpu_counts_t);
+
+	lstat_control.hashtab = (ushort *) malloc(hashsize);
+
+	if (lstat_control.hashtab == 0) {
+		printf("malloc failure for at line %d in lockmeter.c\n",
+			__LINE__);
+		exit(0);
+	}
+
+	lstat_control.dir = (lstat_directory_entry_t *) malloc(dirsize);
+
+	if (lstat_control.dir == 0) {
+		printf("malloc failure for at line %d in lockmeter.c\n", cpu,
+			__LINE__);
+		exit(0);
+	}
+
+	for (cpu = 0; cpu < num_online_cpus(); cpu++) {
+		int j, k;
+		j = (int) (lstat_control.counts[cpu] =
+			   (lstat_cpu_counts_t *) malloc(countsize));
+		k = (int) (lstat_control.read_lock_counts[cpu] =
+			   (lstat_read_lock_cpu_counts_t *)
+			   malloc(read_lock_countsize));
+		if (j * k == 0) {
+			printf("malloc failure for cpu=%d at line %d in "
+				"lockmeter.c\n", cpu, __LINE__);
+			exit(0);
+		}
+	}
+
+	memset(lstat_control.hashtab, 0, hashsize);
+	memset(lstat_control.dir, 0, dirsize);
+
+	for (cpu = 0; cpu < num_online_cpus(); cpu++) {
+		memset(lstat_control.counts[cpu], 0, countsize);
+		memset(lstat_control.read_lock_counts[cpu], 0,
+			read_lock_countsize);
+	}
+}
+
+asm(" \
+.align	4 \
+.globl	__write_lock_failed \
+__write_lock_failed: \
+	" LOCK "addl	$" RW_LOCK_BIAS_STR ",(%eax) \
+1:	cmpl	$" RW_LOCK_BIAS_STR ",(%eax) \
+	jne	1b \
+\
+	" LOCK "subl	$" RW_LOCK_BIAS_STR ",(%eax) \
+	jnz	__write_lock_failed \
+	ret \
+\
+\
+.align	4 \
+.globl	__read_lock_failed \
+__read_lock_failed: \
+	lock ; incl	(%eax) \
+1:	cmpl	$1,(%eax) \
+	js	1b \
+\
+	lock ; decl	(%eax) \
+	js	__read_lock_failed \
+	ret \
+");
+#endif
+
+EXPORT_SYMBOL(_metered_spin_lock);
+EXPORT_SYMBOL(_metered_spin_unlock);
+EXPORT_SYMBOL(_metered_spin_trylock);
+EXPORT_SYMBOL(_metered_read_lock);
+EXPORT_SYMBOL(_metered_read_unlock);
+EXPORT_SYMBOL(_metered_write_lock);
+EXPORT_SYMBOL(_metered_write_unlock);
--- diff/kernel/stop_machine.c	1970-01-01 01:00:00.000000000 +0100
+++ source/kernel/stop_machine.c	2004-02-23 13:56:48.000000000 +0000
@@ -0,0 +1,200 @@
+#include <linux/stop_machine.h>
+#include <linux/kthread.h>
+#include <linux/sched.h>
+#include <linux/cpu.h>
+#include <linux/err.h>
+#include <linux/syscalls.h>
+#include <asm/atomic.h>
+#include <asm/semaphore.h>
+
+/* Since we effect priority and affinity (both of which are visible
+ * to, and settable by outside processes) we do indirection via a
+ * kthread. */
+
+/* Thread to stop each CPU in user context. */
+enum stopmachine_state {
+	STOPMACHINE_WAIT,
+	STOPMACHINE_PREPARE,
+	STOPMACHINE_DISABLE_IRQ,
+	STOPMACHINE_EXIT,
+};
+
+static enum stopmachine_state stopmachine_state;
+static unsigned int stopmachine_num_threads;
+static atomic_t stopmachine_thread_ack;
+static DECLARE_MUTEX(stopmachine_mutex);
+
+static int stopmachine(void *cpu)
+{
+	int irqs_disabled = 0;
+	int prepared = 0;
+
+	set_cpus_allowed(current, cpumask_of_cpu((int)(long)cpu));
+
+	/* Ack: we are alive */
+	mb(); /* Theoretically the ack = 0 might not be on this CPU yet. */
+	atomic_inc(&stopmachine_thread_ack);
+
+	/* Simple state machine */
+	while (stopmachine_state != STOPMACHINE_EXIT) {
+		if (stopmachine_state == STOPMACHINE_DISABLE_IRQ
+		    && !irqs_disabled) {
+			local_irq_disable();
+			irqs_disabled = 1;
+			/* Ack: irqs disabled. */
+			mb(); /* Must read state first. */
+			atomic_inc(&stopmachine_thread_ack);
+		} else if (stopmachine_state == STOPMACHINE_PREPARE
+			   && !prepared) {
+			/* Everyone is in place, hold CPU. */
+			preempt_disable();
+			prepared = 1;
+			mb(); /* Must read state first. */
+			atomic_inc(&stopmachine_thread_ack);
+		}
+		cpu_relax();
+	}
+
+	/* Ack: we are exiting. */
+	mb(); /* Must read state first. */
+	atomic_inc(&stopmachine_thread_ack);
+
+	if (irqs_disabled)
+		local_irq_enable();
+	if (prepared)
+		preempt_enable();
+
+	return 0;
+}
+
+/* Change the thread state */
+static void stopmachine_set_state(enum stopmachine_state state)
+{
+	atomic_set(&stopmachine_thread_ack, 0);
+	wmb();
+	stopmachine_state = state;
+	while (atomic_read(&stopmachine_thread_ack) != stopmachine_num_threads)
+		cpu_relax();
+}
+
+static int stop_machine(void)
+{
+	int i, ret = 0;
+	struct sched_param param = { .sched_priority = MAX_RT_PRIO-1 };
+
+	/* One high-prio thread per cpu.  We'll do this one. */
+	sys_sched_setscheduler(current->pid, SCHED_FIFO, &param);
+
+	atomic_set(&stopmachine_thread_ack, 0);
+	stopmachine_num_threads = 0;
+	stopmachine_state = STOPMACHINE_WAIT;
+
+	for_each_online_cpu(i) {
+		if (i == smp_processor_id())
+			continue;
+		ret = kernel_thread(stopmachine, (void *)(long)i,CLONE_KERNEL);
+		if (ret < 0)
+			break;
+		stopmachine_num_threads++;
+	}
+
+	/* Wait for them all to come to life. */
+	while (atomic_read(&stopmachine_thread_ack) != stopmachine_num_threads)
+		yield();
+
+	/* If some failed, kill them all. */
+	if (ret < 0) {
+		stopmachine_set_state(STOPMACHINE_EXIT);
+		up(&stopmachine_mutex);
+		return ret;
+	}
+
+	/* Don't schedule us away at this point, please. */
+	local_irq_disable();
+
+	/* Now they are all started, make them hold the CPUs, ready. */
+	stopmachine_set_state(STOPMACHINE_PREPARE);
+
+	/* Make them disable irqs. */
+	stopmachine_set_state(STOPMACHINE_DISABLE_IRQ);
+
+	return 0;
+}
+
+static void restart_machine(void)
+{
+	stopmachine_set_state(STOPMACHINE_EXIT);
+	local_irq_enable();
+}
+
+struct stop_machine_data
+{
+	int (*fn)(void *);
+	void *data;
+	struct completion done;
+};
+
+static int do_stop(void *_smdata)
+{
+	struct stop_machine_data *smdata = _smdata;
+	int ret;
+
+	ret = stop_machine();
+	if (ret == 0) {
+		ret = smdata->fn(smdata->data);
+		restart_machine();
+	}
+
+	/* We're done: you can kthread_stop us now */
+	complete(&smdata->done);
+
+	/* Wait for kthread_stop */
+	while (!kthread_should_stop()) {
+		__set_current_state(TASK_INTERRUPTIBLE);
+		schedule();
+	}
+	return ret;
+}
+
+struct task_struct *__stop_machine_run(int (*fn)(void *), void *data,
+				       unsigned int cpu)
+{
+	struct stop_machine_data smdata;
+	struct task_struct *p;
+
+	smdata.fn = fn;
+	smdata.data = data;
+	init_completion(&smdata.done);
+
+	down(&stopmachine_mutex);
+
+	/* If they don't care which CPU fn runs on, bind to any online one. */
+	if (cpu == NR_CPUS)
+		cpu = smp_processor_id();
+
+	p = kthread_create(do_stop, &smdata, "kstopmachine");
+	if (!IS_ERR(p)) {
+		kthread_bind(p, cpu);
+		wake_up_process(p);
+		wait_for_completion(&smdata.done);
+	}
+	up(&stopmachine_mutex);
+	return p;
+}
+
+int stop_machine_run(int (*fn)(void *), void *data, unsigned int cpu)
+{
+	struct task_struct *p;
+	int ret;
+
+	/* No CPUs can come up or down during this. */
+	lock_cpu_hotplug();
+	p = __stop_machine_run(fn, data, cpu);
+	if (!IS_ERR(p))
+		ret = kthread_stop(p);
+	else
+		ret = PTR_ERR(p);
+	unlock_cpu_hotplug();
+
+	return ret;
+}
--- diff/mm/usercopy.c	1970-01-01 01:00:00.000000000 +0100
+++ source/mm/usercopy.c	2004-02-23 13:56:48.000000000 +0000
@@ -0,0 +1,291 @@
+/*
+ * linux/mm/usercopy.c
+ *
+ * (C) Copyright 2003 Ingo Molnar
+ *
+ * Generic implementation of all the user-VM access functions, without
+ * relying on being able to access the VM directly.
+ */
+
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/errno.h>
+#include <linux/mm.h>
+#include <linux/highmem.h>
+#include <linux/pagemap.h>
+#include <linux/smp_lock.h>
+#include <linux/ptrace.h>
+#include <linux/interrupt.h>
+
+#include <asm/pgtable.h>
+#include <asm/uaccess.h>
+#include <asm/atomic_kmap.h>
+
+/*
+ * Get kernel address of the user page and pin it.
+ */
+static inline struct page *pin_page(unsigned long addr, int write)
+{
+	struct mm_struct *mm = current->mm ? : &init_mm;
+	struct page *page = NULL;
+	int ret;
+
+	/*
+	 * Do a quick atomic lookup first - this is the fastpath.
+	 */
+retry:
+	page = follow_page(mm, addr, write);
+	if (likely(page != NULL)) {
+		if (!PageReserved(page))
+			get_page(page);
+		return page;
+	}
+
+	/*
+	 * No luck - bad address or need to fault in the page:
+	 */
+
+	/* Release the lock so get_user_pages can sleep */
+	spin_unlock(&mm->page_table_lock);
+
+	/*
+	 * In the context of filemap_copy_from_user(), we are not allowed
+	 * to sleep.  We must fail this usercopy attempt and allow
+	 * filemap_copy_from_user() to recover: drop its atomic kmap and use
+	 * a sleeping kmap instead.
+	 */
+	if (in_atomic()) {
+		spin_lock(&mm->page_table_lock);
+		return NULL;
+	}
+
+	down_read(&mm->mmap_sem);
+	ret = get_user_pages(current, mm, addr, 1, write, 0, NULL, NULL);
+	up_read(&mm->mmap_sem);
+	spin_lock(&mm->page_table_lock);
+
+	if (ret <= 0)
+		return NULL;
+
+	/*
+	 * Go try the follow_page again.
+	 */
+	goto retry;
+}
+
+static inline void unpin_page(struct page *page)
+{
+	put_page(page);
+}
+
+/*
+ * Access another process' address space.
+ * Source/target buffer must be kernel space,
+ * Do not walk the page table directly, use get_user_pages
+ */
+static int rw_vm(unsigned long addr, void *buf, int len, int write)
+{
+	struct mm_struct *mm = current->mm ? : &init_mm;
+
+	if (!len)
+		return 0;
+
+	spin_lock(&mm->page_table_lock);
+
+	/* ignore errors, just check how much was sucessfully transfered */
+	while (len) {
+		struct page *page = NULL;
+		int bytes, offset;
+		void *maddr;
+
+		page = pin_page(addr, write);
+		if (!page)
+			break;
+
+		bytes = len;
+		offset = addr & (PAGE_SIZE-1);
+		if (bytes > PAGE_SIZE-offset)
+			bytes = PAGE_SIZE-offset;
+
+		maddr = kmap_atomic(page, KM_USER_COPY);
+
+#define HANDLE_TYPE(type) \
+	case sizeof(type): *(type *)(maddr+offset) = *(type *)(buf); break;
+
+		if (write) {
+			switch (bytes) {
+			HANDLE_TYPE(char);
+			HANDLE_TYPE(int);
+			HANDLE_TYPE(long long);
+			default:
+				memcpy(maddr + offset, buf, bytes);
+			}
+		} else {
+#undef HANDLE_TYPE
+#define HANDLE_TYPE(type) \
+	case sizeof(type): *(type *)(buf) = *(type *)(maddr+offset); break;
+			switch (bytes) {
+			HANDLE_TYPE(char);
+			HANDLE_TYPE(int);
+			HANDLE_TYPE(long long);
+			default:
+				memcpy(buf, maddr + offset, bytes);
+			}
+#undef HANDLE_TYPE
+		}
+		kunmap_atomic(maddr, KM_USER_COPY);
+		unpin_page(page);
+		len -= bytes;
+		buf += bytes;
+		addr += bytes;
+	}
+	spin_unlock(&mm->page_table_lock);
+
+	return len;
+}
+
+static int str_vm(unsigned long addr, void *buf0, int len, int copy)
+{
+	struct mm_struct *mm = current->mm ? : &init_mm;
+	struct page *page;
+	void *buf = buf0;
+
+	if (!len)
+		return len;
+
+	spin_lock(&mm->page_table_lock);
+
+	/* ignore errors, just check how much was sucessfully transfered */
+	while (len) {
+		int bytes, offset, left, copied;
+		char *maddr;
+
+		page = pin_page(addr, copy == 2);
+		if (!page) {
+			spin_unlock(&mm->page_table_lock);
+			return -EFAULT;
+		}
+		bytes = len;
+		offset = addr & (PAGE_SIZE-1);
+		if (bytes > PAGE_SIZE-offset)
+			bytes = PAGE_SIZE-offset;
+
+		maddr = kmap_atomic(page, KM_USER_COPY);
+		if (copy == 2) {
+			memset(maddr + offset, 0, bytes);
+			copied = bytes;
+			left = 0;
+		} else if (copy == 1) {
+			left = strncpy_count(buf, maddr + offset, bytes);
+			copied = bytes - left;
+		} else {
+			copied = strnlen(maddr + offset, bytes);
+			left = bytes - copied;
+		}
+		BUG_ON(bytes < 0 || copied < 0);
+		kunmap_atomic(maddr, KM_USER_COPY);
+		unpin_page(page);
+		len -= copied;
+		buf += copied;
+		addr += copied;
+		if (left)
+			break;
+	}
+	spin_unlock(&mm->page_table_lock);
+
+	return len;
+}
+
+/*
+ * Copies memory from userspace (ptr) into kernelspace (val).
+ *
+ * returns # of bytes not copied.
+ */
+int get_user_size(unsigned int size, void *val, const void *ptr)
+{
+	int ret;
+
+	if (unlikely(segment_eq(get_fs(), KERNEL_DS)))
+		ret = __direct_copy_from_user(val, ptr, size);
+	else
+		ret = rw_vm((unsigned long)ptr, val, size, 0);
+	if (ret)
+		/*
+		 * Zero the rest:
+		 */
+		memset(val + size - ret, 0, ret);
+	return ret;
+}
+
+/*
+ * Copies memory from kernelspace (val) into userspace (ptr).
+ *
+ * returns # of bytes not copied.
+ */
+int put_user_size(unsigned int size, const void *val, void *ptr)
+{
+	if (unlikely(segment_eq(get_fs(), KERNEL_DS)))
+		return __direct_copy_to_user(ptr, val, size);
+	else
+		return rw_vm((unsigned long)ptr, (void *)val, size, 1);
+}
+
+int copy_str_fromuser_size(unsigned int size, void *val, const void *ptr)
+{
+	int copied, left;
+
+	if (unlikely(segment_eq(get_fs(), KERNEL_DS))) {
+		left = strncpy_count(val, ptr, size);
+		copied = size - left;
+		BUG_ON(copied < 0);
+
+		return copied;
+	}
+	left = str_vm((unsigned long)ptr, val, size, 1);
+	if (left < 0)
+		return left;
+	copied = size - left;
+	BUG_ON(copied < 0);
+
+	return copied;
+}
+
+int strlen_fromuser_size(unsigned int size, const void *ptr)
+{
+	int copied, left;
+
+	if (unlikely(segment_eq(get_fs(), KERNEL_DS))) {
+		copied = strnlen(ptr, size) + 1;
+		BUG_ON(copied < 0);
+
+		return copied;
+	}
+	left = str_vm((unsigned long)ptr, NULL, size, 0);
+	if (left < 0)
+		return 0;
+	copied = size - left + 1;
+	BUG_ON(copied < 0);
+
+	return copied;
+}
+
+int zero_user_size(unsigned int size, void *ptr)
+{
+	int left;
+
+	if (unlikely(segment_eq(get_fs(), KERNEL_DS))) {
+		memset(ptr, 0, size);
+		return 0;
+	}
+	left = str_vm((unsigned long)ptr, NULL, size, 2);
+	if (left < 0)
+		return size;
+	return left;
+}
+
+EXPORT_SYMBOL(get_user_size);
+EXPORT_SYMBOL(put_user_size);
+EXPORT_SYMBOL(zero_user_size);
+EXPORT_SYMBOL(copy_str_fromuser_size);
+EXPORT_SYMBOL(strlen_fromuser_size);
+
--- diff/net/core/netpoll.c	1970-01-01 01:00:00.000000000 +0100
+++ source/net/core/netpoll.c	2004-02-23 13:56:48.000000000 +0000
@@ -0,0 +1,651 @@
+/*
+ * Common framework for low-level network console, dump, and debugger code
+ *
+ * Sep 8 2003  Matt Mackall <mpm@selenic.com>
+ */
+
+#include <linux/smp_lock.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/string.h>
+#include <linux/inetdevice.h>
+#include <linux/inet.h>
+#include <linux/interrupt.h>
+#include <linux/netpoll.h>
+#include <linux/sched.h>
+#include <net/tcp.h>
+#include <net/udp.h>
+
+/*
+ * We maintain a small pool of fully-sized skbs, to make sure the
+ * message gets out even in extreme OOM situations.
+ */
+
+#define MAX_SKBS 32
+#define MAX_UDP_CHUNK 1460
+
+static spinlock_t skb_list_lock = SPIN_LOCK_UNLOCKED;
+static int nr_skbs;
+static struct sk_buff *skbs;
+
+static spinlock_t rx_list_lock = SPIN_LOCK_UNLOCKED;
+static LIST_HEAD(rx_list);
+
+static int trapped;
+
+#define MAX_SKB_SIZE \
+		(MAX_UDP_CHUNK + sizeof(struct udphdr) + \
+				sizeof(struct iphdr) + sizeof(struct ethhdr))
+
+static void zap_completion_queue(void);
+
+static int checksum_udp(struct sk_buff *skb, struct udphdr *uh,
+			     unsigned short ulen, u32 saddr, u32 daddr)
+{
+	if (uh->check == 0)
+		return 0;
+
+	if (skb->ip_summed == CHECKSUM_HW)
+		return csum_tcpudp_magic(
+			saddr, daddr, ulen, IPPROTO_UDP, skb->csum);
+
+	skb->csum = csum_tcpudp_nofold(saddr, daddr, ulen, IPPROTO_UDP, 0);
+
+	return csum_fold(skb_checksum(skb, 0, skb->len, skb->csum));
+}
+
+void netpoll_poll(struct netpoll *np)
+{
+	int budget = 1;
+
+	if(!np->dev || !netif_running(np->dev) || !np->dev->poll_controller)
+		return;
+
+	/* Process pending work on NIC */
+	np->dev->poll_controller(np->dev);
+
+	/* If scheduling is stopped, tickle NAPI bits */
+	if(trapped && np->dev->poll &&
+	   test_bit(__LINK_STATE_RX_SCHED, &np->dev->state))
+		np->dev->poll(np->dev, &budget);
+	zap_completion_queue();
+}
+
+static void refill_skbs(void)
+{
+	struct sk_buff *skb;
+	unsigned long flags;
+
+	spin_lock_irqsave(&skb_list_lock, flags);
+	while (nr_skbs < MAX_SKBS) {
+		skb = alloc_skb(MAX_SKB_SIZE, GFP_ATOMIC);
+		if (!skb)
+			break;
+
+		skb->next = skbs;
+		skbs = skb;
+		nr_skbs++;
+	}
+	spin_unlock_irqrestore(&skb_list_lock, flags);
+}
+
+static void zap_completion_queue(void)
+{
+	unsigned long flags;
+	struct softnet_data *sd = &get_cpu_var(softnet_data);
+
+	if (sd->completion_queue) {
+		struct sk_buff *clist;
+
+		local_irq_save(flags);
+		clist = sd->completion_queue;
+		sd->completion_queue = NULL;
+		local_irq_restore(flags);
+
+		while (clist != NULL) {
+			struct sk_buff *skb = clist;
+			clist = clist->next;
+			__kfree_skb(skb);
+		}
+	}
+
+	put_cpu_var(softnet_data);
+}
+
+static struct sk_buff * find_skb(struct netpoll *np, int len, int reserve)
+{
+	int once = 1, count = 0;
+	unsigned long flags;
+	struct sk_buff *skb = NULL;
+
+	zap_completion_queue();
+repeat:
+	if (nr_skbs < MAX_SKBS)
+		refill_skbs();
+
+	skb = alloc_skb(len, GFP_ATOMIC);
+
+	if (!skb) {
+		spin_lock_irqsave(&skb_list_lock, flags);
+		skb = skbs;
+		if (skb)
+			skbs = skb->next;
+		skb->next = NULL;
+		nr_skbs--;
+		spin_unlock_irqrestore(&skb_list_lock, flags);
+	}
+
+	if(!skb) {
+		count++;
+		if (once && (count == 1000000)) {
+			printk("out of netpoll skbs!\n");
+			once = 0;
+		}
+		netpoll_poll(np);
+		goto repeat;
+	}
+
+	atomic_set(&skb->users, 1);
+	skb_reserve(skb, reserve);
+	return skb;
+}
+
+void netpoll_send_skb(struct netpoll *np, struct sk_buff *skb)
+{
+	int status;
+
+repeat:
+	if(!np || !np->dev || !netif_running(np->dev)) {
+		__kfree_skb(skb);
+		return;
+	}
+
+	spin_lock(&np->dev->xmit_lock);
+	np->dev->xmit_lock_owner = smp_processor_id();
+
+	if (netif_queue_stopped(np->dev)) {
+		np->dev->xmit_lock_owner = -1;
+		spin_unlock(&np->dev->xmit_lock);
+
+		netpoll_poll(np);
+		goto repeat;
+	}
+
+	status = np->dev->hard_start_xmit(skb, np->dev);
+	np->dev->xmit_lock_owner = -1;
+	spin_unlock(&np->dev->xmit_lock);
+
+	/* transmit busy */
+	if(status)
+		goto repeat;
+}
+
+void netpoll_send_udp(struct netpoll *np, const char *msg, int len)
+{
+	int total_len, eth_len, ip_len, udp_len;
+	struct sk_buff *skb;
+	struct udphdr *udph;
+	struct iphdr *iph;
+	struct ethhdr *eth;
+
+	udp_len = len + sizeof(*udph);
+	ip_len = eth_len = udp_len + sizeof(*iph);
+	total_len = eth_len + ETH_HLEN;
+
+	skb = find_skb(np, total_len, total_len - len);
+	if (!skb)
+		return;
+
+	memcpy(skb->data, msg, len);
+	skb->len += len;
+
+	udph = (struct udphdr *) skb_push(skb, sizeof(*udph));
+	udph->source = htons(np->local_port);
+	udph->dest = htons(np->remote_port);
+	udph->len = htons(udp_len);
+	udph->check = 0;
+
+	iph = (struct iphdr *)skb_push(skb, sizeof(*iph));
+
+	iph->version  = 4;
+	iph->ihl      = 5;
+	iph->tos      = 0;
+	iph->tot_len  = htons(ip_len);
+	iph->id       = 0;
+	iph->frag_off = 0;
+	iph->ttl      = 64;
+	iph->protocol = IPPROTO_UDP;
+	iph->check    = 0;
+	iph->saddr    = htonl(np->local_ip);
+	iph->daddr    = htonl(np->remote_ip);
+	iph->check    = ip_fast_csum((unsigned char *)iph, iph->ihl);
+
+	eth = (struct ethhdr *) skb_push(skb, ETH_HLEN);
+
+	eth->h_proto = htons(ETH_P_IP);
+	memcpy(eth->h_source, np->local_mac, 6);
+	memcpy(eth->h_dest, np->remote_mac, 6);
+
+	netpoll_send_skb(np, skb);
+}
+
+static void arp_reply(struct sk_buff *skb)
+{
+	struct in_device *in_dev = (struct in_device *) skb->dev->ip_ptr;
+	struct arphdr *arp;
+	unsigned char *arp_ptr, *sha, *tha;
+	int size, type = ARPOP_REPLY, ptype = ETH_P_ARP;
+	u32 sip, tip;
+	struct sk_buff *send_skb;
+	unsigned long flags;
+	struct list_head *p;
+	struct netpoll *np = 0;
+
+	spin_lock_irqsave(&rx_list_lock, flags);
+	list_for_each(p, &rx_list) {
+		np = list_entry(p, struct netpoll, rx_list);
+		if ( np->dev == skb->dev )
+			break;
+		np = 0;
+	}
+	spin_unlock_irqrestore(&rx_list_lock, flags);
+
+	if (!np) return;
+
+	/* No arp on this interface */
+	if (!in_dev || skb->dev->flags & IFF_NOARP)
+		return;
+
+	if (!pskb_may_pull(skb, (sizeof(struct arphdr) +
+				 (2 * skb->dev->addr_len) +
+				 (2 * sizeof(u32)))))
+		return;
+
+	skb->h.raw = skb->nh.raw = skb->data;
+	arp = skb->nh.arph;
+
+	if ((arp->ar_hrd != htons(ARPHRD_ETHER) &&
+	     arp->ar_hrd != htons(ARPHRD_IEEE802)) ||
+	    arp->ar_pro != htons(ETH_P_IP) ||
+	    arp->ar_op != htons(ARPOP_REQUEST))
+		return;
+
+	arp_ptr= (unsigned char *)(arp+1);
+	sha = arp_ptr;
+	arp_ptr += skb->dev->addr_len;
+	memcpy(&sip, arp_ptr, 4);
+	arp_ptr += 4;
+	tha = arp_ptr;
+	arp_ptr += skb->dev->addr_len;
+	memcpy(&tip, arp_ptr, 4);
+
+	/* Should we ignore arp? */
+	if (tip != in_dev->ifa_list->ifa_address ||
+	    LOOPBACK(tip) || MULTICAST(tip))
+		return;
+
+
+	size = sizeof(struct arphdr) + 2 * (skb->dev->addr_len + 4);
+	send_skb = find_skb(np, size + LL_RESERVED_SPACE(np->dev),
+			    LL_RESERVED_SPACE(np->dev));
+
+	if (!send_skb)
+		return;
+
+	send_skb->nh.raw = send_skb->data;
+	arp = (struct arphdr *) skb_put(send_skb, size);
+	send_skb->dev = skb->dev;
+	send_skb->protocol = htons(ETH_P_ARP);
+
+	/* Fill the device header for the ARP frame */
+
+	if (np->dev->hard_header &&
+	    np->dev->hard_header(send_skb, skb->dev, ptype,
+				       np->remote_mac, np->local_mac,
+				       send_skb->len) < 0) {
+		kfree_skb(send_skb);
+		return;
+	}
+
+	/*
+	 * Fill out the arp protocol part.
+	 *
+	 * we only support ethernet device type,
+	 * which (according to RFC 1390) should always equal 1 (Ethernet).
+	 */
+
+	arp->ar_hrd = htons(np->dev->type);
+	arp->ar_pro = htons(ETH_P_IP);
+	arp->ar_hln = np->dev->addr_len;
+	arp->ar_pln = 4;
+	arp->ar_op = htons(type);
+
+	arp_ptr=(unsigned char *)(arp + 1);
+	memcpy(arp_ptr, np->dev->dev_addr, np->dev->addr_len);
+	arp_ptr += np->dev->addr_len;
+	memcpy(arp_ptr, &tip, 4);
+	arp_ptr += 4;
+	memcpy(arp_ptr, np->local_mac, np->dev->addr_len);
+	arp_ptr += np->dev->addr_len;
+	memcpy(arp_ptr, &sip, 4);
+
+	netpoll_send_skb(np, send_skb);
+}
+
+int netpoll_rx(struct sk_buff *skb)
+{
+	int proto, len, ulen;
+	struct iphdr *iph;
+	struct udphdr *uh;
+	struct netpoll *np;
+	struct list_head *p;
+	unsigned long flags;
+
+	if (skb->dev->type != ARPHRD_ETHER)
+		goto out;
+
+	/* check if netpoll clients need ARP */
+	if (skb->protocol == __constant_htons(ETH_P_ARP) && trapped) {
+		arp_reply(skb);
+		return 1;
+	}
+
+	proto = ntohs(skb->mac.ethernet->h_proto);
+	if (proto != ETH_P_IP)
+		goto out;
+	if (skb->pkt_type == PACKET_OTHERHOST)
+		goto out;
+	if (skb_shared(skb))
+		goto out;
+
+	iph = (struct iphdr *)skb->data;
+	if (!pskb_may_pull(skb, sizeof(struct iphdr)))
+		goto out;
+	if (iph->ihl < 5 || iph->version != 4)
+		goto out;
+	if (!pskb_may_pull(skb, iph->ihl*4))
+		goto out;
+	if (ip_fast_csum((u8 *)iph, iph->ihl) != 0)
+		goto out;
+
+	len = ntohs(iph->tot_len);
+	if (skb->len < len || len < iph->ihl*4)
+		goto out;
+
+	if (iph->protocol != IPPROTO_UDP)
+		goto out;
+
+	len -= iph->ihl*4;
+	uh = (struct udphdr *)(((char *)iph) + iph->ihl*4);
+	ulen = ntohs(uh->len);
+
+	if (ulen != len)
+		goto out;
+	if (checksum_udp(skb, uh, ulen, iph->saddr, iph->daddr) < 0)
+		goto out;
+
+	spin_lock_irqsave(&rx_list_lock, flags);
+	list_for_each(p, &rx_list) {
+		np = list_entry(p, struct netpoll, rx_list);
+		if (np->dev && np->dev != skb->dev)
+			continue;
+		if (np->local_ip && np->local_ip != ntohl(iph->daddr))
+			continue;
+		if (np->remote_ip && np->remote_ip != ntohl(iph->saddr))
+			continue;
+		if (np->local_port && np->local_port != ntohs(uh->dest))
+			continue;
+
+		spin_unlock_irqrestore(&rx_list_lock, flags);
+
+		if (np->rx_hook)
+			np->rx_hook(np, ntohs(uh->source),
+				    (char *)(uh+1),
+				    ulen - sizeof(struct udphdr));
+
+		return 1;
+	}
+	spin_unlock_irqrestore(&rx_list_lock, flags);
+
+out:
+	return trapped;
+}
+
+int netpoll_parse_options(struct netpoll *np, char *opt)
+{
+	char *cur=opt, *delim;
+
+	if(*cur != '@') {
+		if ((delim = strchr(cur, '@')) == NULL)
+			goto parse_failed;
+		*delim=0;
+		np->local_port=simple_strtol(cur, 0, 10);
+		cur=delim;
+	}
+	cur++;
+	printk(KERN_INFO "%s: local port %d\n", np->name, np->local_port);
+
+	if(*cur != '/') {
+		if ((delim = strchr(cur, '/')) == NULL)
+			goto parse_failed;
+		*delim=0;
+		np->local_ip=ntohl(in_aton(cur));
+		cur=delim;
+
+		printk(KERN_INFO "%s: local IP %d.%d.%d.%d\n",
+		       np->name, HIPQUAD(np->local_ip));
+	}
+	cur++;
+
+	if ( *cur != ',') {
+		/* parse out dev name */
+		if ((delim = strchr(cur, ',')) == NULL)
+			goto parse_failed;
+		*delim=0;
+		strlcpy(np->dev_name, cur, sizeof(np->dev_name));
+		cur=delim;
+	}
+	cur++;
+
+	printk(KERN_INFO "%s: interface %s\n", np->name, np->dev_name);
+
+	if ( *cur != '@' ) {
+		/* dst port */
+		if ((delim = strchr(cur, '@')) == NULL)
+			goto parse_failed;
+		*delim=0;
+		np->remote_port=simple_strtol(cur, 0, 10);
+		cur=delim;
+	}
+	cur++;
+	printk(KERN_INFO "%s: remote port %d\n", np->name, np->remote_port);
+
+	/* dst ip */
+	if ((delim = strchr(cur, '/')) == NULL)
+		goto parse_failed;
+	*delim=0;
+	np->remote_ip=ntohl(in_aton(cur));
+	cur=delim+1;
+
+	printk(KERN_INFO "%s: remote IP %d.%d.%d.%d\n",
+		       np->name, HIPQUAD(np->remote_ip));
+
+	if( *cur != 0 )
+	{
+		/* MAC address */
+		if ((delim = strchr(cur, ':')) == NULL)
+			goto parse_failed;
+		*delim=0;
+		np->remote_mac[0]=simple_strtol(cur, 0, 16);
+		cur=delim+1;
+		if ((delim = strchr(cur, ':')) == NULL)
+			goto parse_failed;
+		*delim=0;
+		np->remote_mac[1]=simple_strtol(cur, 0, 16);
+		cur=delim+1;
+		if ((delim = strchr(cur, ':')) == NULL)
+			goto parse_failed;
+		*delim=0;
+		np->remote_mac[2]=simple_strtol(cur, 0, 16);
+		cur=delim+1;
+		if ((delim = strchr(cur, ':')) == NULL)
+			goto parse_failed;
+		*delim=0;
+		np->remote_mac[3]=simple_strtol(cur, 0, 16);
+		cur=delim+1;
+		if ((delim = strchr(cur, ':')) == NULL)
+			goto parse_failed;
+		*delim=0;
+		np->remote_mac[4]=simple_strtol(cur, 0, 16);
+		cur=delim+1;
+		np->remote_mac[5]=simple_strtol(cur, 0, 16);
+	}
+
+	printk(KERN_INFO "%s: remote ethernet address "
+	       "%02x:%02x:%02x:%02x:%02x:%02x\n",
+	       np->name,
+	       np->remote_mac[0],
+	       np->remote_mac[1],
+	       np->remote_mac[2],
+	       np->remote_mac[3],
+	       np->remote_mac[4],
+	       np->remote_mac[5]);
+
+	return 0;
+
+ parse_failed:
+	printk(KERN_INFO "%s: couldn't parse config at %s!\n",
+	       np->name, cur);
+	return -1;
+}
+
+int netpoll_setup(struct netpoll *np)
+{
+	struct net_device *ndev = NULL;
+	struct in_device *in_dev;
+
+	if (np->dev_name)
+		ndev = dev_get_by_name(np->dev_name);
+	if (!ndev) {
+		printk(KERN_ERR "%s: %s doesn't exist, aborting.\n",
+		       np->name, np->dev_name);
+		return -1;
+	}
+	if (!ndev->poll_controller) {
+		printk(KERN_ERR "%s: %s doesn't support polling, aborting.\n",
+		       np->name, np->dev_name);
+		goto release;
+	}
+
+	if (!(ndev->flags & IFF_UP)) {
+		unsigned short oflags;
+		unsigned long atmost, atleast;
+
+		printk(KERN_INFO "%s: device %s not up yet, forcing it\n",
+		       np->name, np->dev_name);
+
+		oflags = ndev->flags;
+
+		rtnl_shlock();
+		if (dev_change_flags(ndev, oflags | IFF_UP) < 0) {
+			printk(KERN_ERR "%s: failed to open %s\n",
+			       np->name, np->dev_name);
+			rtnl_shunlock();
+			goto release;
+		}
+		rtnl_shunlock();
+
+		atleast = jiffies + HZ/10;
+ 		atmost = jiffies + 10*HZ;
+		while (!netif_carrier_ok(ndev)) {
+			if (time_after(jiffies, atmost)) {
+				printk(KERN_NOTICE
+				       "%s: timeout waiting for carrier\n",
+				       np->name);
+				break;
+			}
+			cond_resched();
+		}
+
+		if (time_before(jiffies, atleast)) {
+			printk(KERN_NOTICE "%s: carrier detect appears flaky,"
+			       " waiting 10 seconds\n",
+			       np->name);
+			while (time_before(jiffies, atmost))
+				cond_resched();
+		}
+	}
+
+	if (!memcmp(np->local_mac, "\0\0\0\0\0\0", 6) && ndev->dev_addr)
+		memcpy(np->local_mac, ndev->dev_addr, 6);
+
+	if (!np->local_ip) {
+		in_dev = in_dev_get(ndev);
+
+		if (!in_dev) {
+			printk(KERN_ERR "%s: no IP address for %s, aborting\n",
+			       np->name, np->dev_name);
+			goto release;
+		}
+
+		np->local_ip = ntohl(in_dev->ifa_list->ifa_local);
+		in_dev_put(in_dev);
+		printk(KERN_INFO "%s: local IP %d.%d.%d.%d\n",
+		       np->name, HIPQUAD(np->local_ip));
+	}
+
+	np->dev = ndev;
+
+	if(np->rx_hook) {
+		unsigned long flags;
+
+#ifdef CONFIG_NETPOLL_RX
+		np->dev->netpoll_rx = 1;
+#endif
+
+		spin_lock_irqsave(&rx_list_lock, flags);
+		list_add(&np->rx_list, &rx_list);
+		spin_unlock_irqrestore(&rx_list_lock, flags);
+	}
+
+	return 0;
+ release:
+	dev_put(ndev);
+	return -1;
+}
+
+void netpoll_cleanup(struct netpoll *np)
+{
+	if(np->rx_hook) {
+		unsigned long flags;
+
+		spin_lock_irqsave(&rx_list_lock, flags);
+		list_del(&np->rx_list);
+#ifdef CONFIG_NETPOLL_RX
+		np->dev->netpoll_rx = 0;
+#endif
+		spin_unlock_irqrestore(&rx_list_lock, flags);
+	}
+
+	dev_put(np->dev);
+	np->dev = 0;
+}
+
+int netpoll_trap()
+{
+	return trapped;
+}
+
+void netpoll_set_trap(int trap)
+{
+	trapped = trap;
+}
+
+EXPORT_SYMBOL(netpoll_set_trap);
+EXPORT_SYMBOL(netpoll_trap);
+EXPORT_SYMBOL(netpoll_parse_options);
+EXPORT_SYMBOL(netpoll_setup);
+EXPORT_SYMBOL(netpoll_cleanup);
+EXPORT_SYMBOL(netpoll_send_skb);
+EXPORT_SYMBOL(netpoll_send_udp);
+EXPORT_SYMBOL(netpoll_poll);
--- diff/scripts/gcc-version.sh	1970-01-01 01:00:00.000000000 +0100
+++ source/scripts/gcc-version.sh	2004-02-23 13:56:48.000000000 +0000
@@ -0,0 +1,14 @@
+#!/bin/sh
+#
+# gcc-version gcc-command
+#
+# Prints the gcc version of `gcc-command' in a canonical 4-digit form
+# such as `0295' for gcc-2.95, `0303' for gcc-3.3, etc.
+#
+
+compiler="$*"
+
+MAJOR=$(echo __GNUC__ | $compiler -E -xc - | tail -n 1)
+MINOR=$(echo __GNUC_MINOR__ | $compiler -E -xc - | tail -n 1)
+printf "%02d%02d\\n" $MAJOR $MINOR
+
--- diff/scripts/sumversion.c	1970-01-01 01:00:00.000000000 +0100
+++ source/scripts/sumversion.c	2004-02-23 13:56:48.000000000 +0000
@@ -0,0 +1,540 @@
+#include <netinet/in.h>
+#include <stdint.h>
+#include <ctype.h>
+#include <errno.h>
+#include <string.h>
+#include "modpost.h"
+
+/* Parse tag=value strings from .modinfo section */
+static char *next_string(char *string, unsigned long *secsize)
+{
+	/* Skip non-zero chars */
+	while (string[0]) {
+		string++;
+		if ((*secsize)-- <= 1)
+			return NULL;
+	}
+
+	/* Skip any zero padding. */
+	while (!string[0]) {
+		string++;
+		if ((*secsize)-- <= 1)
+			return NULL;
+	}
+	return string;
+}
+
+static char *get_modinfo(void *modinfo, unsigned long modinfo_len,
+			 const char *tag)
+{
+	char *p;
+	unsigned int taglen = strlen(tag);
+	unsigned long size = modinfo_len;
+
+	for (p = modinfo; p; p = next_string(p, &size)) {
+		if (strncmp(p, tag, taglen) == 0 && p[taglen] == '=')
+			return p + taglen + 1;
+	}
+	return NULL;
+}
+
+/*
+ * Stolen form Cryptographic API.
+ *
+ * MD4 Message Digest Algorithm (RFC1320).
+ *
+ * Implementation derived from Andrew Tridgell and Steve French's
+ * CIFS MD4 implementation, and the cryptoapi implementation
+ * originally based on the public domain implementation written
+ * by Colin Plumb in 1993.
+ *
+ * Copyright (c) Andrew Tridgell 1997-1998.
+ * Modified by Steve French (sfrench@us.ibm.com) 2002
+ * Copyright (c) Cryptoapi developers.
+ * Copyright (c) 2002 David S. Miller (davem@redhat.com)
+ * Copyright (c) 2002 James Morris <jmorris@intercode.com.au>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ */
+#define MD4_DIGEST_SIZE		16
+#define MD4_HMAC_BLOCK_SIZE	64
+#define MD4_BLOCK_WORDS		16
+#define MD4_HASH_WORDS		4
+
+struct md4_ctx {
+	uint32_t hash[MD4_HASH_WORDS];
+	uint32_t block[MD4_BLOCK_WORDS];
+	uint64_t byte_count;
+};
+
+static inline uint32_t lshift(uint32_t x, unsigned int s)
+{
+	x &= 0xFFFFFFFF;
+	return ((x << s) & 0xFFFFFFFF) | (x >> (32 - s));
+}
+
+static inline uint32_t F(uint32_t x, uint32_t y, uint32_t z)
+{
+	return (x & y) | ((~x) & z);
+}
+
+static inline uint32_t G(uint32_t x, uint32_t y, uint32_t z)
+{
+	return (x & y) | (x & z) | (y & z);
+}
+
+static inline uint32_t H(uint32_t x, uint32_t y, uint32_t z)
+{
+	return x ^ y ^ z;
+}
+
+#define ROUND1(a,b,c,d,k,s) (a = lshift(a + F(b,c,d) + k, s))
+#define ROUND2(a,b,c,d,k,s) (a = lshift(a + G(b,c,d) + k + (uint32_t)0x5A827999,s))
+#define ROUND3(a,b,c,d,k,s) (a = lshift(a + H(b,c,d) + k + (uint32_t)0x6ED9EBA1,s))
+
+/* XXX: this stuff can be optimized */
+static inline void le32_to_cpu_array(uint32_t *buf, unsigned int words)
+{
+	while (words--) {
+		*buf = ntohl(*buf);
+		buf++;
+	}
+}
+
+static inline void cpu_to_le32_array(uint32_t *buf, unsigned int words)
+{
+	while (words--) {
+		*buf = htonl(*buf);
+		buf++;
+	}
+}
+
+static void md4_transform(uint32_t *hash, uint32_t const *in)
+{
+	uint32_t a, b, c, d;
+
+	a = hash[0];
+	b = hash[1];
+	c = hash[2];
+	d = hash[3];
+
+	ROUND1(a, b, c, d, in[0], 3);
+	ROUND1(d, a, b, c, in[1], 7);
+	ROUND1(c, d, a, b, in[2], 11);
+	ROUND1(b, c, d, a, in[3], 19);
+	ROUND1(a, b, c, d, in[4], 3);
+	ROUND1(d, a, b, c, in[5], 7);
+	ROUND1(c, d, a, b, in[6], 11);
+	ROUND1(b, c, d, a, in[7], 19);
+	ROUND1(a, b, c, d, in[8], 3);
+	ROUND1(d, a, b, c, in[9], 7);
+	ROUND1(c, d, a, b, in[10], 11);
+	ROUND1(b, c, d, a, in[11], 19);
+	ROUND1(a, b, c, d, in[12], 3);
+	ROUND1(d, a, b, c, in[13], 7);
+	ROUND1(c, d, a, b, in[14], 11);
+	ROUND1(b, c, d, a, in[15], 19);
+
+	ROUND2(a, b, c, d,in[ 0], 3);
+	ROUND2(d, a, b, c, in[4], 5);
+	ROUND2(c, d, a, b, in[8], 9);
+	ROUND2(b, c, d, a, in[12], 13);
+	ROUND2(a, b, c, d, in[1], 3);
+	ROUND2(d, a, b, c, in[5], 5);
+	ROUND2(c, d, a, b, in[9], 9);
+	ROUND2(b, c, d, a, in[13], 13);
+	ROUND2(a, b, c, d, in[2], 3);
+	ROUND2(d, a, b, c, in[6], 5);
+	ROUND2(c, d, a, b, in[10], 9);
+	ROUND2(b, c, d, a, in[14], 13);
+	ROUND2(a, b, c, d, in[3], 3);
+	ROUND2(d, a, b, c, in[7], 5);
+	ROUND2(c, d, a, b, in[11], 9);
+	ROUND2(b, c, d, a, in[15], 13);
+
+	ROUND3(a, b, c, d,in[ 0], 3);
+	ROUND3(d, a, b, c, in[8], 9);
+	ROUND3(c, d, a, b, in[4], 11);
+	ROUND3(b, c, d, a, in[12], 15);
+	ROUND3(a, b, c, d, in[2], 3);
+	ROUND3(d, a, b, c, in[10], 9);
+	ROUND3(c, d, a, b, in[6], 11);
+	ROUND3(b, c, d, a, in[14], 15);
+	ROUND3(a, b, c, d, in[1], 3);
+	ROUND3(d, a, b, c, in[9], 9);
+	ROUND3(c, d, a, b, in[5], 11);
+	ROUND3(b, c, d, a, in[13], 15);
+	ROUND3(a, b, c, d, in[3], 3);
+	ROUND3(d, a, b, c, in[11], 9);
+	ROUND3(c, d, a, b, in[7], 11);
+	ROUND3(b, c, d, a, in[15], 15);
+
+	hash[0] += a;
+	hash[1] += b;
+	hash[2] += c;
+	hash[3] += d;
+}
+
+static inline void md4_transform_helper(struct md4_ctx *ctx)
+{
+	le32_to_cpu_array(ctx->block, sizeof(ctx->block) / sizeof(uint32_t));
+	md4_transform(ctx->hash, ctx->block);
+}
+
+static void md4_init(struct md4_ctx *mctx)
+{
+	mctx->hash[0] = 0x67452301;
+	mctx->hash[1] = 0xefcdab89;
+	mctx->hash[2] = 0x98badcfe;
+	mctx->hash[3] = 0x10325476;
+	mctx->byte_count = 0;
+}
+
+static void md4_update(struct md4_ctx *mctx,
+		       const unsigned char *data, unsigned int len)
+{
+	const uint32_t avail = sizeof(mctx->block) - (mctx->byte_count & 0x3f);
+
+	mctx->byte_count += len;
+
+	if (avail > len) {
+		memcpy((char *)mctx->block + (sizeof(mctx->block) - avail),
+		       data, len);
+		return;
+	}
+
+	memcpy((char *)mctx->block + (sizeof(mctx->block) - avail),
+	       data, avail);
+
+	md4_transform_helper(mctx);
+	data += avail;
+	len -= avail;
+
+	while (len >= sizeof(mctx->block)) {
+		memcpy(mctx->block, data, sizeof(mctx->block));
+		md4_transform_helper(mctx);
+		data += sizeof(mctx->block);
+		len -= sizeof(mctx->block);
+	}
+
+	memcpy(mctx->block, data, len);
+}
+
+static void md4_final_ascii(struct md4_ctx *mctx, char *out, unsigned int len)
+{
+	const unsigned int offset = mctx->byte_count & 0x3f;
+	char *p = (char *)mctx->block + offset;
+	int padding = 56 - (offset + 1);
+
+	*p++ = 0x80;
+	if (padding < 0) {
+		memset(p, 0x00, padding + sizeof (uint64_t));
+		md4_transform_helper(mctx);
+		p = (char *)mctx->block;
+		padding = 56;
+	}
+
+	memset(p, 0, padding);
+	mctx->block[14] = mctx->byte_count << 3;
+	mctx->block[15] = mctx->byte_count >> 29;
+	le32_to_cpu_array(mctx->block, (sizeof(mctx->block) -
+	                  sizeof(uint64_t)) / sizeof(uint32_t));
+	md4_transform(mctx->hash, mctx->block);
+	cpu_to_le32_array(mctx->hash, sizeof(mctx->hash) / sizeof(uint32_t));
+
+	snprintf(out, len, "%08X%08X%08X%08X",
+		 mctx->hash[0], mctx->hash[1], mctx->hash[2], mctx->hash[3]);
+}
+
+static int parse_file(const char *fname, struct md4_ctx *md);
+
+/* Local include files, if in current dir. */
+static void include_file(const char *line, int maxlen, const char *base,
+			 struct md4_ctx *md)
+{
+	unsigned int i;
+
+	for (i = 0; line[i] != '"'; i++) {
+		if (i == maxlen) {
+			fprintf(stderr,
+				"sumversion: badly formed #include in %s\n",
+				base);
+			return;
+		}
+	}
+
+	{
+		const char *dirend;
+		char fname[i + strlen(base)];
+
+		dirend = strrchr(base, '/');
+		if (!dirend)
+			dirend = base;
+		else
+			dirend++;
+		memcpy(fname, base, dirend - base);
+		memcpy(fname + (dirend - base), line, i);
+		fname[(dirend - base) + i] = '\0';
+
+		parse_file(fname, md);
+	}
+}
+
+static inline void add_char(unsigned char c, struct md4_ctx *md)
+{
+	md4_update(md, &c, 1);
+}
+
+static int parse_string(const char *file, unsigned long len,
+			struct md4_ctx *md)
+{
+	unsigned long i;
+
+	add_char(file[0], md);
+	for (i = 1; i < len; i++) {
+		add_char(file[i], md);
+		if (file[i] == '"' && file[i-1] != '\\')
+			break;
+	}
+	return i;
+}
+
+static int parse_comment(const char *file, unsigned long len)
+{
+	unsigned long i;
+
+	for (i = 2; i < len; i++) {
+		if (file[i-1] == '*' && file[i] == '/')
+			break;
+	}
+	return i;
+}
+
+static int skip_whitespace(const char *file, unsigned long len)
+{
+	unsigned long i;
+
+	for (i = 0; i < len; i++) {
+		if (file[i] != ' ' && file[i] != '\t')
+			break;
+	}
+	return i;
+}
+
+#define strneq(str, literal) (strncmp((str), (literal), strlen(literal)) == 0)
+
+/* Just in case it does a (local) include. */
+static int parse_cpp_line(const char *file, unsigned long len,
+			  const char *base, struct md4_ctx *md)
+{
+	unsigned long i = 0;
+
+	add_char(file[i++], md);
+	i += skip_whitespace(file+i, len - i);
+	if (i + strlen("include") >= len)
+		return i;
+	if (!strneq(file + i, "include"))
+		return i;
+	md4_update(md, (unsigned char *)"include", strlen("include"));
+	i += strlen("include");
+	i += skip_whitespace(file+i, len - i);
+	if (i >= len)
+		return i;
+	if (file[i] != '"')
+		return i-1;
+	include_file(file+i+1, len - i - 1, base, md);
+	return i-1;
+}
+
+static int parse_file(const char *fname, struct md4_ctx *md)
+{
+	char *file;
+	unsigned long i, len;
+	int start_of_line = 1;
+
+	file = grab_file(fname, &len);
+	if (!file)
+		return 0;
+
+	for (i = 0; i < len; i++) {
+		/* Collapse and ignore \ and CR. */
+		if (file[i] == '\\' && (i+1 < len) && file[i+1] == '\n') {
+			i += 2;
+			continue;
+		}
+
+		if (file[i] == '\n')
+			start_of_line = 1;
+
+		/* Ignore whitespace */
+		if (isspace(file[i]))
+			continue;
+
+		/* Handle strings as whole units */
+		if (file[i] == '"') {
+			i += parse_string(file+i, len - i, md);
+			start_of_line = 0;
+			continue;
+		}
+
+		/* Comments: ignore */
+		if (file[i] == '/' && file[i+1] == '*') {
+			i += parse_comment(file+i, len - i);
+			start_of_line = 0;
+			continue;
+		}
+
+		/* Potential #include files */
+		if (file[i] == '#' && start_of_line) {
+			i += parse_cpp_line(file+i, len - i, fname, md);
+			start_of_line = 0;
+			continue;
+		}
+
+		start_of_line = 0;
+		add_char(file[i], md);
+	}
+	return 1;
+}
+
+static void get_version(const char *modname, char sum[])
+{
+	void *file;
+	unsigned long len;
+	struct md4_ctx md;
+	char *sources, *end, *fname;
+	const char *basename;
+	char filelist[sizeof(".tmp_versions/%s.mod") + strlen(modname)];
+
+	/* Source files for module are in .tmp_versions/modname.mod,
+	   after the first line. */
+	if (strrchr(modname, '/'))
+		basename = strrchr(modname, '/') + 1;
+	else
+		basename = modname;
+	sprintf(filelist, ".tmp_versions/%s", basename);
+	/* Truncate .o, add .mod */
+	strcpy(filelist + strlen(filelist)-2, ".mod");
+
+	file = grab_file(filelist, &len);
+	if (!file) {
+		fprintf(stderr, "Warning: could not find versions for %s\n",
+			filelist);
+		return;
+	}
+
+	sources = strchr(file, '\n');
+	if (!sources) {
+		fprintf(stderr, "Warning: malformed versions file for %s\n",
+			modname);
+		goto release;
+	}
+
+	sources++;
+	end = strchr(sources, '\n');
+	if (!end) {
+		fprintf(stderr, "Warning: bad ending versions file for %s\n",
+			modname);
+		goto release;
+	}
+	*end = '\0';
+
+	md4_init(&md);
+	for (fname = strtok(sources, " "); fname; fname = strtok(NULL, " "))
+		if (!parse_file(fname, &md)) {
+			fprintf(stderr, "Warning: could not open %s: %s\n",
+				fname, strerror(errno));
+			goto release;
+		}
+
+	/* sum is of form \0<padding>. */
+	md4_final_ascii(&md, sum, 1 + strlen(sum+1));
+release:
+	release_file(file, len);
+}
+
+static void write_version(const char *filename, const char *sum,
+			  unsigned long offset)
+{
+	int fd;
+
+	fd = open(filename, O_RDWR);
+	if (fd < 0) {
+		fprintf(stderr, "Warning: changing sum in %s failed: %s\n",
+			filename, strerror(errno));
+		return;
+	}
+
+	if (lseek(fd, offset, SEEK_SET) == (off_t)-1) {
+		fprintf(stderr, "Warning: changing sum in %s:%lu failed: %s\n",
+			filename, offset, strerror(errno));
+		goto out;
+	}
+
+	if (write(fd, sum, strlen(sum)+1) != strlen(sum)+1) {
+		fprintf(stderr, "Warning: writing sum in %s failed: %s\n",
+			filename, strerror(errno));
+		goto out;
+	}
+out:
+	close(fd);
+}
+
+void strip_rcs_crap(char *version)
+{
+	unsigned int len, full_len;
+
+	if (strncmp(version, "$Revision", strlen("$Revision")) != 0)
+		return;
+
+	/* Space for version string follows. */
+	full_len = strlen(version) + strlen(version + strlen(version) + 1) + 2;
+
+	/* Move string to start with version number: prefix will be
+	 * $Revision$ or $Revision: */
+	len = strlen("$Revision");
+	if (version[len] == ':' || version[len] == '$')
+		len++;
+	while (isspace(version[len]))
+		len++;
+	memmove(version, version+len, full_len-len);
+	full_len -= len;
+
+	/* Preserve up to next whitespace. */
+	len = 0;
+	while (version[len] && !isspace(version[len]))
+		len++;
+	memmove(version + len, version + strlen(version),
+		full_len - strlen(version));
+}
+
+/* If the modinfo contains a "version" value, then set this. */
+void maybe_frob_version(const char *modfilename,
+			void *modinfo,
+			unsigned long modinfo_len,
+			unsigned long modinfo_offset)
+{
+	char *version, *csum;
+
+	version = get_modinfo(modinfo, modinfo_len, "version");
+	if (!version)
+		return;
+
+	/* RCS $Revision gets stripped out. */
+	strip_rcs_crap(version);
+
+	/* Check against double sumversion */
+	if (strchr(version, ' '))
+		return;
+
+	/* Version contains embedded NUL: second half has space for checksum */
+	csum = version + strlen(version);
+	*(csum++) = ' ';
+	get_version(modfilename, csum);
+	write_version(modfilename, version,
+		      modinfo_offset + (version - (char *)modinfo));
+}
--- diff/security/selinux/netlink.c	1970-01-01 01:00:00.000000000 +0100
+++ source/security/selinux/netlink.c	2004-02-23 13:56:48.000000000 +0000
@@ -0,0 +1,113 @@
+/*
+ * Netlink event notifications for SELinux.
+ *
+ * Author: James Morris <jmorris@redhat.com>
+ *
+ * Copyright (C) 2004 Red Hat, Inc., James Morris <jmorris@redhat.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2,
+ * as published by the Free Software Foundation.
+ */
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/stddef.h>
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/skbuff.h>
+#include <linux/netlink.h>
+#include <linux/selinux_netlink.h>
+
+static struct sock *selnl;
+
+static int selnl_msglen(int msgtype)
+{
+	int ret = 0;
+	
+	switch (msgtype) {
+	case SELNL_MSG_SETENFORCE:
+		ret = sizeof(struct selnl_msg_setenforce);
+		break;
+	
+	case SELNL_MSG_POLICYLOAD:
+		ret = sizeof(struct selnl_msg_policyload);
+		break;
+		
+	default:
+		BUG();
+	}
+	return ret;
+}
+
+static void selnl_add_payload(struct nlmsghdr *nlh, int len, int msgtype, void *data)
+{
+	switch (msgtype) {
+	case SELNL_MSG_SETENFORCE: {
+		struct selnl_msg_setenforce *msg = NLMSG_DATA(nlh);
+		
+		memset(msg, 0, len);
+		msg->val = *((int *)data);
+		break;
+	}
+	
+	case SELNL_MSG_POLICYLOAD: {
+		struct selnl_msg_policyload *msg = NLMSG_DATA(nlh);
+		
+		memset(msg, 0, len);
+		msg->seqno = *((u32 *)data);
+		break;
+	}
+
+	default:
+		BUG();
+	}
+}
+
+static void selnl_notify(int msgtype, void *data)
+{
+	int len;
+	unsigned char *tmp;
+	struct sk_buff *skb;
+	struct nlmsghdr *nlh;
+	
+	len = selnl_msglen(msgtype);
+	
+	skb = alloc_skb(NLMSG_SPACE(len), GFP_USER);
+	if (!skb)
+		goto oom;
+
+	tmp = skb->tail;
+	nlh = NLMSG_PUT(skb, 0, 0, msgtype, len);
+	selnl_add_payload(nlh, len, msgtype, data);
+	nlh->nlmsg_len = skb->tail - tmp;
+	netlink_broadcast(selnl, skb, 0, SELNL_GRP_AVC, GFP_USER);
+out:
+	return;
+	
+nlmsg_failure:
+	kfree_skb(skb);
+oom:
+	printk(KERN_ERR "SELinux:  OOM in %s\n", __FUNCTION__);
+	goto out;
+}
+
+void selnl_notify_setenforce(int val)
+{
+	selnl_notify(SELNL_MSG_SETENFORCE, &val);
+}
+
+void selnl_notify_policyload(u32 seqno)
+{
+	selnl_notify(SELNL_MSG_POLICYLOAD, &seqno);
+}
+
+static int __init selnl_init(void)
+{
+	selnl = netlink_kernel_create(NETLINK_SELINUX, NULL);
+	if (selnl == NULL)
+		panic("SELinux:  Cannot create netlink socket.");
+	netlink_set_nonroot(NETLINK_SELINUX, NL_NONROOT_RECV);	
+	return 0;
+}
+
+__initcall(selnl_init);
--- diff/sound/pci/mixart/Makefile	1970-01-01 01:00:00.000000000 +0100
+++ source/sound/pci/mixart/Makefile	2004-02-23 13:56:48.000000000 +0000
@@ -0,0 +1,8 @@
+#
+# Makefile for ALSA
+# Copyright (c) 2001 by Jaroslav Kysela <perex@suse.cz>
+#
+
+snd-mixart-objs := mixart.o mixart_core.o mixart_hwdep.o mixart_mixer.o
+
+obj-$(CONFIG_SND_MIXART) += snd-mixart.o
--- diff/sound/pci/mixart/mixart.c	1970-01-01 01:00:00.000000000 +0100
+++ source/sound/pci/mixart/mixart.c	2004-02-23 13:56:48.000000000 +0000
@@ -0,0 +1,1448 @@
+/*
+ * Driver for Digigram miXart soundcards
+ *
+ * main file with alsa callbacks
+ *
+ * Copyright (c) 2003 by Digigram <alsa@digigram.com>
+ *
+ *   This program is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License as published by
+ *   the Free Software Foundation; either version 2 of the License, or
+ *   (at your option) any later version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ */
+
+
+#include <sound/driver.h>
+#include <linux/init.h>
+#include <sound/core.h>
+#define SNDRV_GET_ID
+#include <sound/initval.h>
+#include <sound/info.h>
+#include <sound/control.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include "mixart.h"
+#include "mixart_hwdep.h"
+#include "mixart_core.h"
+#include "mixart_mixer.h"
+
+#define CARD_NAME "miXart"
+
+MODULE_AUTHOR("Digigram <alsa@digigram.com>");
+MODULE_DESCRIPTION("Digigram " CARD_NAME);
+MODULE_LICENSE("GPL");
+MODULE_CLASSES("{sound}");
+MODULE_DEVICES("{{Digigram," CARD_NAME "}}");
+
+static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;             /* Index 0-MAX */
+static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;              /* ID for this card */
+static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;     /* Enable this card */
+
+#define chip_t mixart_t
+
+MODULE_PARM(index, "1-" __MODULE_STRING(SNDRV_CARDS) "i");
+MODULE_PARM_DESC(index, "Index value for Digigram " CARD_NAME " soundcard.");
+MODULE_PARM_SYNTAX(index, SNDRV_INDEX_DESC);
+MODULE_PARM(id, "1-" __MODULE_STRING(SNDRV_CARDS) "s");
+MODULE_PARM_DESC(id, "ID string for Digigram " CARD_NAME " soundcard.");
+MODULE_PARM_SYNTAX(id, SNDRV_ID_DESC);
+MODULE_PARM(enable, "1-" __MODULE_STRING(SNDRV_CARDS) "i");
+MODULE_PARM_DESC(enable, "Enable Digigram " CARD_NAME " soundcard.");
+MODULE_PARM_SYNTAX(enable, SNDRV_ENABLE_DESC);
+
+/*
+ */
+
+static struct pci_device_id snd_mixart_ids[] = {
+	{ 0x1057, 0x0003, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* MC8240 */
+	{ 0, }
+};
+
+MODULE_DEVICE_TABLE(pci, snd_mixart_ids);
+
+
+static int mixart_set_pipe_state(mixart_mgr_t *mgr, mixart_pipe_t* pipe, int start)
+{
+	mixart_group_state_req_t group_state;
+	mixart_group_state_resp_t group_state_resp;
+	mixart_msg_t request;
+	int err;
+	u32 system_msg_uid;
+
+	switch(pipe->status) {
+	case PIPE_RUNNING:
+	case PIPE_CLOCK_SET:
+		if(start) return 0; /* already started */
+		break;
+	case PIPE_STOPPED:
+		if(!start) return 0; /* already stopped */
+		break;
+	default:
+		snd_printk(KERN_ERR "error mixart_set_pipe_state called with wrong pipe->status!\n");
+		return -EINVAL;      /* function called with wrong pipe status */
+	}
+
+	system_msg_uid = 0x12345678; /* the event ! (take care: the MSB and two LSB's have to be 0) */
+
+	/* wait on the last MSG_SYSTEM_SEND_SYNCHRO_CMD command to be really finished */
+
+	request.message_id = MSG_SYSTEM_WAIT_SYNCHRO_CMD;
+	request.uid = (mixart_uid_t){0,0};
+	request.data = &system_msg_uid;
+	request.size = sizeof(system_msg_uid);
+
+	err = snd_mixart_send_msg_wait_notif(mgr, &request, system_msg_uid);
+	if(err) {
+		snd_printk(KERN_ERR "error : MSG_SYSTEM_WAIT_SYNCHRO_CMD was not notified !\n");
+		return err;
+	}
+
+	/* start or stop the pipe (1 pipe) */
+
+	memset(&group_state, 0, sizeof(group_state));
+	group_state.pipe_count = 1;
+	group_state.pipe_uid[0] = pipe->group_uid;
+
+	if(start)
+		request.message_id = MSG_STREAM_START_STREAM_GRP_PACKET;
+	else
+		request.message_id = MSG_STREAM_STOP_STREAM_GRP_PACKET;
+
+	request.uid = pipe->group_uid; /*(mixart_uid_t){0,0};*/
+	request.data = &group_state;
+	request.size = sizeof(group_state);
+
+	err = snd_mixart_send_msg(mgr, &request, sizeof(group_state_resp), &group_state_resp);
+	if(err) {
+		snd_printk(KERN_ERR "error MSG_STREAM_ST***_STREAM_GRP_PACKET\n");
+		return err;
+	}
+	if(group_state_resp.txx_status != 0) {
+		snd_printk(KERN_ERR "error status MSG_STREAM_ST***_STREAM_GRP_PACKET (%x)!\n", group_state_resp.txx_status);
+		return -EINVAL;
+	}
+
+	if(start) {
+		u32 stat;
+
+		group_state.pipe_count = 0; /* in case of start same command once again with pipe_count=0 */
+
+		err = snd_mixart_send_msg(mgr, &request, sizeof(group_state_resp), &group_state_resp);
+		if(err)	{
+			snd_printk(KERN_ERR "error MSG_STREAM_START_STREAM_GRP_PACKET !\n");
+			return err;
+		}
+		if(group_state_resp.txx_status != 0) {
+			snd_printk(KERN_ERR "error status MSG_STREAM_START_STREAM_GRP_PACKET (%x)!\n", group_state_resp.txx_status);
+			return -EINVAL;
+		}
+
+		/* in case of start send a synchro top */
+
+		request.message_id = MSG_SYSTEM_SEND_SYNCHRO_CMD;
+		request.uid = (mixart_uid_t){0,0};
+		request.data = NULL;
+		request.size = 0;
+
+		err = snd_mixart_send_msg(mgr, &request, sizeof(stat), &stat);
+		if(err) {
+			snd_printk(KERN_ERR "error MSG_SYSTEM_SEND_SYNCHRO_CMD!\n");
+			return err;
+		}
+		if(stat) {
+			snd_printk(KERN_ERR "error MSG_SYSTEM_SEND_SYNCHRO_CMD stat=%x!\n", stat);
+		}
+
+		pipe->status = PIPE_RUNNING;
+	}
+	else /* !start */
+		pipe->status = PIPE_STOPPED;
+
+	return 0;
+}
+
+
+static int mixart_set_clock(mixart_mgr_t *mgr, mixart_pipe_t *pipe, unsigned int rate)
+{
+	mixart_msg_t request;
+	mixart_clock_properties_t clock_properties;
+
+	switch(pipe->status) {
+	case PIPE_CLOCK_SET:
+		break;
+	case PIPE_RUNNING:
+		if(rate != 0)
+			break;
+	default:
+		if(rate == 0)
+			return 0; /* nothing to do */
+		else {
+			snd_printk(KERN_ERR "error mixart_set_clock(%d) called with wrong pipe->status !\n", rate);
+			return -EINVAL;
+		}
+	}
+
+	memset(&clock_properties, 0, sizeof(clock_properties));
+	clock_properties.clock_generic_type = (rate != 0) ? CGT_INTERNAL_CLOCK : CGT_NO_CLOCK;
+	clock_properties.clock_mode = CM_STANDALONE;
+	clock_properties.frequency = rate;
+	clock_properties.nb_callers = 1; /* only one entry in uid_caller ! */
+	clock_properties.uid_caller[0] = pipe->group_uid;
+
+	snd_printdd("mixart_set_clock to %d kHz\n", rate);
+
+	request.message_id = MSG_CLOCK_SET_PROPERTIES;
+	request.uid = mgr->uid_console_manager;
+	request.data = &clock_properties;
+	request.size = sizeof(clock_properties);
+
+	/* we are not allowed to wait for the response, so simply set rate */
+	/* TODO : error has to be handled later in the tasklet! */
+
+	if(rate)  pipe->status = PIPE_CLOCK_SET;
+	else      pipe->status = PIPE_RUNNING;
+
+	return snd_mixart_send_msg_nonblock(mgr, &request);
+}
+
+
+/*
+ *  Allocate or reference output pipe for analog IOs (pcmp0/1)
+ */
+mixart_pipe_t* snd_mixart_add_ref_pipe( mixart_t *chip, int pcm_number, int capture, int monitoring)
+{
+	int stream_count;
+	mixart_pipe_t *pipe;
+	mixart_msg_t request;
+
+	if(capture) {
+		if (pcm_number == MIXART_PCM_ANALOG) {
+			pipe = &(chip->pipe_in_ana);  /* analog inputs */
+		} else {
+			pipe = &(chip->pipe_in_dig); /* digital inputs */
+		}
+		request.message_id = MSG_STREAM_ADD_OUTPUT_GROUP;
+		stream_count = MIXART_CAPTURE_STREAMS;
+	} else {
+		if (pcm_number == MIXART_PCM_ANALOG) {
+			pipe = &(chip->pipe_out_ana);  /* analog outputs */
+		} else {
+			pipe = &(chip->pipe_out_dig);  /* digital outputs */
+		}
+		request.message_id = MSG_STREAM_ADD_INPUT_GROUP;
+		stream_count = MIXART_PLAYBACK_STREAMS;
+	}
+
+	/* a new stream is opened and there are already all streams in use */
+	if( (monitoring == 0) && (pipe->references >= stream_count) ) {
+		return NULL;
+	}
+
+	/* pipe is not yet defined */
+	if( pipe->status == PIPE_UNDEFINED ) {
+		int err, i;
+		mixart_streaming_group_t streaming_group_resp;
+		mixart_streaming_group_req_t streaming_group_req;
+
+		snd_printdd("add_ref_pipe audio chip(%d) pcm(%d)\n", chip->chip_idx, pcm_number);
+
+		request.uid = (mixart_uid_t){0,0};      /* should be StreamManagerUID, but zero is OK if there is only one ! */
+		request.data = &streaming_group_req;
+		request.size = sizeof(streaming_group_req);
+
+		memset(&streaming_group_req, 0, sizeof(streaming_group_req));
+
+		streaming_group_req.stream_count = stream_count;
+		streaming_group_req.channel_count = 2;
+		streaming_group_req.latency = 256;
+		streaming_group_req.connector = pipe->uid_left_connector;  /* the left connector */
+
+		for (i=0; i<stream_count; i++) {
+			int j;
+			/* we don't yet know the format, so config 16 bit pcm audio for instance */
+			streaming_group_req.stream_info[i].size_max_byte_frame = 1024;
+			streaming_group_req.stream_info[i].size_max_sample_frame = 256;
+			streaming_group_req.stream_info[i].nb_bytes_max_per_sample = MIXART_FLOAT_P__4_0_TO_HEX; /* is 4.0f */
+
+			/* find the right bufferinfo_array */
+			j = (chip->chip_idx * MIXART_MAX_STREAM_PER_CARD) + (pcm_number * (MIXART_PLAYBACK_STREAMS + MIXART_CAPTURE_STREAMS)) + i;
+			if(capture) j += MIXART_PLAYBACK_STREAMS; /* in the array capture is behind playback */
+
+			streaming_group_req.flow_entry[i] = j;
+
+			chip->mgr->flowinfo_array[j].bufferinfo_array_phy_address = (u32)chip->mgr->bufferinfo_physaddr + (j * sizeof(mixart_bufferinfo_t));
+			chip->mgr->flowinfo_array[j].bufferinfo_count = 1;               /* 1 will set the miXart to ring-buffer mode ! */
+
+			chip->mgr->bufferinfo_array[j].buffer_address = 0;               /* buffer is not yet allocated */
+			chip->mgr->bufferinfo_array[j].available_length = 0;             /* buffer is not yet allocated */
+
+			/* construct the identifier of the stream buffer received in the interrupts ! */
+			chip->mgr->bufferinfo_array[j].buffer_id = (chip->chip_idx << MIXART_NOTIFY_CARD_OFFSET) + (pcm_number << MIXART_NOTIFY_PCM_OFFSET ) + i;
+			if(capture) {
+				chip->mgr->bufferinfo_array[j].buffer_id |= MIXART_NOTIFY_CAPT_MASK;
+			}
+		}
+
+		err = snd_mixart_send_msg(chip->mgr, &request, sizeof(streaming_group_resp), &streaming_group_resp);
+		if((err < 0) || (streaming_group_resp.status != 0)) {
+			snd_printk(KERN_ERR "message MSG_STREAM_ADD_**PUT_GROUP return error: err(%x) status(%x)!\n", err, streaming_group_resp.status);
+			return NULL;
+		}
+
+		pipe->group_uid = streaming_group_resp.group;     /* id of the pipe, as returned by embedded */
+		pipe->stream_count = streaming_group_resp.stream_count;
+		/* pipe->stream_uid[i] = streaming_group_resp.stream[i].stream_uid; */
+
+		pipe->status = PIPE_STOPPED;
+	}
+
+	if(monitoring)	pipe->monitoring = 1;
+	else		pipe->references++;
+
+	return pipe;
+}
+
+
+int snd_mixart_kill_ref_pipe( mixart_mgr_t *mgr, mixart_pipe_t *pipe, int monitoring)
+{
+	int err = 0;
+
+	if(pipe->status == PIPE_UNDEFINED)
+		return 0;
+
+	if(monitoring)
+		pipe->monitoring = 0;
+	else
+		pipe->references--;
+
+	if((pipe->references <= 0) && (pipe->monitoring == 0)) {
+
+		mixart_msg_t request;
+		mixart_delete_group_resp_t delete_resp;
+
+		/* release the clock */
+		err = mixart_set_clock( mgr, pipe, 0);
+		if( err < 0 ) {
+			snd_printk(KERN_ERR "mixart_set_clock(0) return error!\n");
+		}
+
+		/* stop the pipe */
+		err = mixart_set_pipe_state(mgr, pipe, 0);
+		if( err < 0 ) {
+			snd_printk(KERN_ERR "error stopping pipe!\n");
+		}
+
+		request.message_id = MSG_STREAM_DELETE_GROUP;
+		request.uid = (mixart_uid_t){0,0};
+		request.data = &pipe->group_uid;            /* the streaming group ! */
+		request.size = sizeof(pipe->group_uid);
+
+		/* delete the pipe */
+		err = snd_mixart_send_msg(mgr, &request, sizeof(delete_resp), &delete_resp);
+		if ((err < 0) || (delete_resp.status != 0)) {
+			snd_printk(KERN_ERR "error MSG_STREAM_DELETE_GROUP err(%x), status(%x)\n", err, delete_resp.status);
+		}
+
+		pipe->group_uid = (mixart_uid_t){0,0};
+		pipe->stream_count = 0;
+		pipe->status = PIPE_UNDEFINED;
+	}
+
+	return err;
+}
+
+static int mixart_set_stream_state(mixart_stream_t *stream, int start)
+{
+	mixart_t *chip;
+	mixart_stream_state_req_t stream_state_req;
+	mixart_msg_t request;
+
+	if(!stream->substream)
+		return -EINVAL;
+
+	memset(&stream_state_req, 0, sizeof(stream_state_req));
+	stream_state_req.stream_count = 1;
+	stream_state_req.stream_info.stream_desc.uid_pipe = stream->pipe->group_uid;
+	stream_state_req.stream_info.stream_desc.stream_idx = stream->substream->number;
+
+	if (stream->substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+		request.message_id = start ? MSG_STREAM_START_INPUT_STAGE_PACKET : MSG_STREAM_STOP_INPUT_STAGE_PACKET;
+	else
+		request.message_id = start ? MSG_STREAM_START_OUTPUT_STAGE_PACKET : MSG_STREAM_STOP_OUTPUT_STAGE_PACKET;
+
+	request.uid = (mixart_uid_t){0,0};
+	request.data = &stream_state_req;
+	request.size = sizeof(stream_state_req);
+
+	stream->abs_period_elapsed = 0;            /* reset stream pos      */
+	stream->buf_periods = 0;
+	stream->buf_period_frag = 0;
+
+	chip = snd_pcm_substream_chip(stream->substream);
+
+	return snd_mixart_send_msg_nonblock(chip->mgr, &request);
+}
+
+/*
+ *  Trigger callback
+ */
+
+static int snd_mixart_trigger(snd_pcm_substream_t *subs, int cmd)
+{
+	mixart_stream_t *stream = (mixart_stream_t*)subs->runtime->private_data;
+
+	switch (cmd) {
+	case SNDRV_PCM_TRIGGER_START:
+
+		snd_printdd("SNDRV_PCM_TRIGGER_START\n");
+
+		// snd_printk(KERN_DEBUG "hw_avail = %d\n", snd_pcm_playback_hw_avail(subs->runtime));
+		/* START_STREAM */
+		if( mixart_set_stream_state(stream, 1) )
+			return -EINVAL;
+
+		stream->status = MIXART_STREAM_STATUS_RUNNING;
+
+		break;
+	case SNDRV_PCM_TRIGGER_STOP:
+
+		/* STOP_STREAM */
+		if( mixart_set_stream_state(stream, 0) )
+			return -EINVAL;
+
+		/* TODO : mixart drains data transefered in advance -> mute stream ? */
+		stream->status = MIXART_STREAM_STATUS_OPEN;
+
+		snd_printdd("SNDRV_PCM_TRIGGER_STOP\n");
+
+		break;
+
+	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+		/* TODO */
+		stream->status = MIXART_STREAM_STATUS_PAUSE;
+		snd_printdd("SNDRV_PCM_PAUSE_PUSH\n");
+		break;
+	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+		/* TODO */
+		stream->status = MIXART_STREAM_STATUS_RUNNING;
+		snd_printdd("SNDRV_PCM_PAUSE_RELEASE\n");
+		break;
+	default:
+		return -EINVAL;
+	}
+	return 0;
+}
+
+/*
+ *  prepare callback for all pcms
+ */
+static int snd_mixart_prepare(snd_pcm_substream_t *subs)
+{
+	mixart_t *chip = snd_pcm_substream_chip(subs);
+	mixart_stream_t *stream = (mixart_stream_t*)subs->runtime->private_data;
+
+	/* TODO de façon non bloquante, réappliquer les hw_params (rate, bits, codec) */
+
+	snd_printdd("snd_mixart_prepare\n");
+
+	/* only the first stream can choose the sample rate */
+	/* the further opened streams will be limited to its frequency (see open) */
+	if(chip->mgr->ref_count_rate == 1)
+		chip->mgr->sample_rate = subs->runtime->rate;
+
+	/* set the clock only once (first stream) on the same pipe */
+	if(stream->pipe->references == 1) {
+		if( mixart_set_clock(chip->mgr, stream->pipe, subs->runtime->rate) )
+			return -EINVAL;
+	}
+
+	return 0;
+}
+
+
+static int mixart_set_format(mixart_stream_t *stream, snd_pcm_format_t format)
+{
+	int err;
+	mixart_t *chip;
+	mixart_msg_t request;
+	mixart_stream_param_desc_t stream_param;
+	mixart_return_uid_t resp;
+
+	chip = snd_pcm_substream_chip(stream->substream);
+
+	memset(&stream_param, 0, sizeof(stream_param));
+
+	stream_param.coding_type = CT_LINEAR;
+	stream_param.number_of_channel = stream->channels;
+
+	stream_param.sampling_freq = chip->mgr->sample_rate;
+	if(stream_param.sampling_freq == 0)
+		stream_param.sampling_freq = 44100; /* if frequency not yet defined, use some default */
+
+	switch(format){
+	case SNDRV_PCM_FORMAT_U8:
+		stream_param.sample_type = ST_INTEGER_8;
+		stream_param.sample_size = 8;
+		break;
+	case SNDRV_PCM_FORMAT_S16_LE:
+		stream_param.sample_type = ST_INTEGER_16LE;
+		stream_param.sample_size = 16;
+		break;
+	case SNDRV_PCM_FORMAT_S16_BE:
+		stream_param.sample_type = ST_INTEGER_16BE;
+		stream_param.sample_size = 16;
+		break;
+	case SNDRV_PCM_FORMAT_S24_3LE:
+		stream_param.sample_type = ST_INTEGER_24LE;
+		stream_param.sample_size = 24;
+		break;
+	case SNDRV_PCM_FORMAT_S24_3BE:
+		stream_param.sample_type = ST_INTEGER_24BE;
+		stream_param.sample_size = 24;
+		break;
+	case SNDRV_PCM_FMTBIT_FLOAT_LE:
+		stream_param.sample_type = ST_FLOATING_POINT_32LE;
+		stream_param.sample_size = 32;
+		break;
+	case  SNDRV_PCM_FMTBIT_FLOAT_BE:
+		stream_param.sample_type = ST_FLOATING_POINT_32BE;
+		stream_param.sample_size = 32;
+		break;
+	default:
+		snd_printk(KERN_DEBUG "error use default SNDRV_PCM_FORMAT_S16_LE\n");
+		stream_param.sample_type = ST_INTEGER_16LE;
+		stream_param.sample_size = 16;
+	}
+
+	snd_printdd("set SNDRV_PCM_FORMAT sample_type(%d) sample_size(%d) freq(%d) channels(%d)\n",
+		   stream_param.sample_type, stream_param.sample_size, stream_param.sampling_freq, stream->channels);
+
+	/* TODO: what else to configure ? */
+	/* stream_param.samples_per_frame = 2; */
+	/* stream_param.bytes_per_frame = 4; */
+	/* stream_param.bytes_per_sample = 2; */
+
+	stream_param.pipe_count = 1;      /* set to 1 */
+	stream_param.stream_count = 1;    /* set to 1 */
+	stream_param.stream_desc[0].uid_pipe = stream->pipe->group_uid;
+	stream_param.stream_desc[0].stream_idx = stream->substream->number;
+
+	request.message_id = MSG_STREAM_SET_INPUT_STAGE_PARAM;
+	request.uid = (mixart_uid_t){0,0};
+	request.data = &stream_param;
+	request.size = sizeof(stream_param);
+
+	err = snd_mixart_send_msg(chip->mgr, &request, sizeof(resp), &resp);
+	if((err < 0) || resp.error_code) {
+		snd_printk(KERN_DEBUG "MSG_STREAM_SET_INPUT_STAGE_PARAM err=%x; resp=%x\n", err, resp.error_code);
+		return -EINVAL;
+	}
+	return 0;
+}
+
+
+/*
+ *  HW_PARAMS callback for all pcms
+ */
+static int snd_mixart_hw_params(snd_pcm_substream_t *subs,
+                                snd_pcm_hw_params_t *hw)
+{
+	mixart_t *chip = snd_pcm_substream_chip(subs);
+	mixart_mgr_t *mgr = chip->mgr;
+	mixart_stream_t *stream = (mixart_stream_t*)subs->runtime->private_data;
+	snd_pcm_format_t format;
+	int err;
+	int channels;
+
+	/* set up channels */
+	channels = params_channels(hw);
+
+	/*  set up format for the stream */
+	format = params_format(hw);
+
+	down(&mgr->setup_mutex);
+
+	/* update the stream levels */
+	if( stream->pcm_number <= MIXART_PCM_DIGITAL ) {
+		int is_aes = stream->pcm_number > MIXART_PCM_ANALOG;
+		if( subs->stream == SNDRV_PCM_STREAM_PLAYBACK )
+			mixart_update_playback_stream_level(chip, is_aes, subs->number);
+		else
+			mixart_update_capture_stream_level( chip, is_aes);
+	}
+
+	stream->channels = channels;
+
+	/* set the format to the board */
+	err = mixart_set_format(stream, format);
+	if(err < 0) {
+		snd_printk(KERN_DEBUG "mixart_set_format() returned error (%x)\n", err);
+		return err;
+	}
+
+	/* allocate buffer */
+	err = snd_pcm_lib_malloc_pages(subs, params_buffer_bytes(hw));
+
+	if (err > 0) {
+		int i = (chip->chip_idx * MIXART_MAX_STREAM_PER_CARD) + (stream->pcm_number * (MIXART_PLAYBACK_STREAMS+MIXART_CAPTURE_STREAMS)) + subs->number;
+		if( subs->stream == SNDRV_PCM_STREAM_CAPTURE ) {
+			i += MIXART_PLAYBACK_STREAMS; /* in array capture is behind playback */
+		}
+		mgr->bufferinfo_array[i].buffer_address = subs->runtime->dma_addr;
+		mgr->bufferinfo_array[i].available_length = subs->runtime->dma_bytes;
+		/* mgr->bufferinfo_array[i].buffer_id  is already defined */
+
+		snd_printdd("snd_mixart_hw_params(pcm %d) : dma_addr(%x) dma_bytes(%x) subs-number(%d)\n", i, subs->runtime->dma_addr, subs->runtime->dma_bytes, subs->number);
+	}
+	up(&mgr->setup_mutex);
+
+	return err;
+}
+
+static int snd_mixart_hw_free(snd_pcm_substream_t *subs)
+{
+	snd_pcm_lib_free_pages(subs);
+	return 0;
+}
+
+
+
+/*
+ *  TODO CONFIGURATION SPACE for all pcms, mono pcm must update channels_max
+ */
+static snd_pcm_hardware_t snd_mixart_analog_caps =
+{
+	.info             = ( SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
+			      SNDRV_PCM_INFO_MMAP_VALID | SNDRV_PCM_INFO_SYNC_START |
+			      SNDRV_PCM_INFO_PAUSE),
+	.formats	  = ( SNDRV_PCM_FMTBIT_U8 |
+			      SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S16_BE |
+			      SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S24_3BE |
+			      SNDRV_PCM_FMTBIT_FLOAT_LE | SNDRV_PCM_FMTBIT_FLOAT_BE ),
+	.rates            = SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_48000,
+	.rate_min         = 8000,
+	.rate_max         = 48000,
+	.channels_min     = 1,
+	.channels_max     = 2,
+	.buffer_bytes_max = (32*1024),
+	.period_bytes_min = 256,                  /* 256 frames U8 mono*/
+	.period_bytes_max = (16*1024),
+	.periods_min      = 2,
+	.periods_max      = (32*1024/256),
+};
+
+static snd_pcm_hardware_t snd_mixart_digital_caps =
+{
+	.info             = ( SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
+			      SNDRV_PCM_INFO_MMAP_VALID | SNDRV_PCM_INFO_SYNC_START |
+			      SNDRV_PCM_INFO_PAUSE),
+	.formats	  = ( SNDRV_PCM_FMTBIT_U8 |
+			      SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S16_BE |
+			      SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S24_3BE |
+			      SNDRV_PCM_FMTBIT_FLOAT_LE | SNDRV_PCM_FMTBIT_FLOAT_BE ),
+	.rates            = SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000,
+	.rate_min         = 32000,
+	.rate_max         = 48000,
+	.channels_min     = 1,
+	.channels_max     = 2,
+	.buffer_bytes_max = (32*1024),
+	.period_bytes_min = 256,                  /* 256 frames U8 mono*/
+	.period_bytes_max = (16*1024),
+	.periods_min      = 2,
+	.periods_max      = (32*1024/256),
+};
+
+
+static int snd_mixart_playback_open(snd_pcm_substream_t *subs)
+{
+	mixart_t            *chip = snd_pcm_substream_chip(subs);
+	mixart_mgr_t        *mgr = chip->mgr;
+	snd_pcm_runtime_t   *runtime = subs->runtime;
+	snd_pcm_t           *pcm = subs->pcm;
+	mixart_stream_t     *stream;
+	mixart_pipe_t       *pipe;
+	int err = 0;
+	int pcm_number;
+
+	down(&mgr->setup_mutex);
+
+	if ( pcm == chip->pcm ) {
+		pcm_number = MIXART_PCM_ANALOG;
+		runtime->hw = snd_mixart_analog_caps;
+	} else {
+		snd_assert ( pcm == chip->pcm_dig ); 
+		pcm_number = MIXART_PCM_DIGITAL;
+		runtime->hw = snd_mixart_digital_caps;
+	}
+	snd_printdd("snd_mixart_playback_open C%d/P%d/Sub%d\n", chip->chip_idx, pcm_number, subs->number);
+
+	/* get stream info */
+	stream = &(chip->playback_stream[pcm_number][subs->number]);
+
+	if (stream->status != MIXART_STREAM_STATUS_FREE){
+		/* streams in use */
+		snd_printk(KERN_ERR "snd_mixart_playback_open C%d/P%d/Sub%d in use\n", chip->chip_idx, pcm_number, subs->number);
+		err = -EBUSY;
+		goto _exit_open;
+	}
+
+	/* get pipe pointer (out pipe) */
+	pipe = snd_mixart_add_ref_pipe(chip, pcm_number, 0, 0);
+
+	if (pipe == NULL) {
+		err = -EINVAL;
+		goto _exit_open;
+	}
+
+	/* start the pipe if necessary */
+	err = mixart_set_pipe_state(chip->mgr, pipe, 1);
+	if( err < 0 ) {
+		snd_printk(KERN_ERR "error starting pipe!\n");
+		snd_mixart_kill_ref_pipe(chip->mgr, pipe, 0);
+		err = -EINVAL;
+		goto _exit_open;
+	}
+
+	stream->pipe        = pipe;
+	stream->pcm_number  = pcm_number;
+	stream->status      = MIXART_STREAM_STATUS_OPEN;
+	stream->substream   = subs;
+	stream->channels    = 0; /* not configured yet */
+
+	runtime->private_data = stream;
+
+	snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 32);
+	snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_SIZE, 64);
+
+	/* if a sample rate is already used, another stream cannot change */
+	if(mgr->ref_count_rate++) {
+		if(mgr->sample_rate) {
+			runtime->hw.rate_min = runtime->hw.rate_max = mgr->sample_rate;
+		}
+	}
+
+ _exit_open:
+	up(&mgr->setup_mutex);
+
+	return err;
+}
+
+
+static int snd_mixart_capture_open(snd_pcm_substream_t *subs)
+{
+	mixart_t            *chip = snd_pcm_substream_chip(subs);
+	mixart_mgr_t        *mgr = chip->mgr;
+	snd_pcm_runtime_t   *runtime = subs->runtime;
+	snd_pcm_t           *pcm = subs->pcm;
+	mixart_stream_t     *stream;
+	mixart_pipe_t       *pipe;
+	int err = 0;
+	int pcm_number;
+
+	down(&mgr->setup_mutex);
+
+	if ( pcm == chip->pcm ) {
+		pcm_number = MIXART_PCM_ANALOG;
+		runtime->hw = snd_mixart_analog_caps;
+	} else {
+		snd_assert ( pcm == chip->pcm_dig ); 
+		pcm_number = MIXART_PCM_DIGITAL;
+		runtime->hw = snd_mixart_digital_caps;
+	}
+
+	runtime->hw.channels_min = 2; /* for instance, no mono */
+
+	snd_printdd("snd_mixart_capture_open C%d/P%d/Sub%d\n", chip->chip_idx, pcm_number, subs->number);
+
+	/* get stream info */
+	stream = &(chip->capture_stream[pcm_number]);
+
+	if (stream->status != MIXART_STREAM_STATUS_FREE){
+		/* streams in use */
+		snd_printk(KERN_ERR "snd_mixart_capture_open C%d/P%d/Sub%d in use\n", chip->chip_idx, pcm_number, subs->number);
+		err = -EBUSY;
+		goto _exit_open;
+	}
+
+	/* get pipe pointer (in pipe) */
+	pipe = snd_mixart_add_ref_pipe(chip, pcm_number, 1, 0);
+
+	if (pipe == NULL) {
+		err = -EINVAL;
+		goto _exit_open;
+	}
+
+	/* start the pipe if necessary */
+	err = mixart_set_pipe_state(chip->mgr, pipe, 1);
+	if( err < 0 ) {
+		snd_printk(KERN_ERR "error starting pipe!\n");
+		snd_mixart_kill_ref_pipe(chip->mgr, pipe, 0);
+		err = -EINVAL;
+		goto _exit_open;
+	}
+
+	stream->pipe        = pipe;
+	stream->pcm_number  = pcm_number;
+	stream->status      = MIXART_STREAM_STATUS_OPEN;
+	stream->substream   = subs;
+	stream->channels    = 0; /* not configured yet */
+
+	runtime->private_data = stream;
+
+	snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 32);
+	snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_SIZE, 64);
+
+	/* if a sample rate is already used, another stream cannot change */
+	if(mgr->ref_count_rate++) {
+		if(mgr->sample_rate) {
+			runtime->hw.rate_min = runtime->hw.rate_max = mgr->sample_rate;
+		}
+	}
+
+ _exit_open:
+	up(&mgr->setup_mutex);
+
+	return err;
+}
+
+
+
+static int snd_mixart_close(snd_pcm_substream_t *subs)
+{
+	mixart_t *chip = snd_pcm_substream_chip(subs);
+	mixart_mgr_t *mgr = chip->mgr;
+	mixart_stream_t *stream = (mixart_stream_t*)subs->runtime->private_data;
+
+	down(&mgr->setup_mutex);
+
+	snd_printdd("snd_mixart_close C%d/P%d/Sub%d\n", chip->chip_idx, stream->pcm_number, subs->number);
+
+	/* sample rate released */
+	if(--mgr->ref_count_rate == 0) {
+		mgr->sample_rate = 0;
+	}
+
+	/* delete pipe */
+	if (snd_mixart_kill_ref_pipe(mgr, stream->pipe, 0 ) < 0) {
+
+		snd_printk(KERN_ERR "error snd_mixart_kill_ref_pipe C%dP%d\n", chip->chip_idx, stream->pcm_number);
+	}
+
+	stream->pipe      = NULL;
+	stream->status    = MIXART_STREAM_STATUS_FREE;
+	stream->substream = NULL;
+
+	up(&mgr->setup_mutex);
+	return 0;
+}
+
+
+static snd_pcm_uframes_t snd_mixart_stream_pointer(snd_pcm_substream_t * subs)
+{
+	snd_pcm_runtime_t *runtime = subs->runtime;
+	mixart_stream_t   *stream  = (mixart_stream_t*)runtime->private_data;
+
+	return (snd_pcm_uframes_t)((stream->buf_periods * runtime->period_size) + stream->buf_period_frag);
+}
+
+
+
+static snd_pcm_ops_t snd_mixart_playback_ops = {
+	.open      = snd_mixart_playback_open,
+	.close     = snd_mixart_close,
+	.ioctl     = snd_pcm_lib_ioctl,
+	.prepare   = snd_mixart_prepare,
+	.hw_params = snd_mixart_hw_params,
+	.hw_free   = snd_mixart_hw_free,
+	.trigger   = snd_mixart_trigger,
+	.pointer   = snd_mixart_stream_pointer,
+};
+
+static snd_pcm_ops_t snd_mixart_capture_ops = {
+	.open      = snd_mixart_capture_open,
+	.close     = snd_mixart_close,
+	.ioctl     = snd_pcm_lib_ioctl,
+	.prepare   = snd_mixart_prepare,
+	.hw_params = snd_mixart_hw_params,
+	.hw_free   = snd_mixart_hw_free,
+	.trigger   = snd_mixart_trigger,
+	.pointer   = snd_mixart_stream_pointer,
+};
+
+static void preallocate_buffers(mixart_t *chip, snd_pcm_t *pcm)
+{
+	snd_pcm_substream_t *subs;
+	int stream;
+
+	for (stream = 0; stream < 2; stream++) {
+		int idx = 0;
+		for (subs = pcm->streams[stream].substream; subs; subs = subs->next, idx++)
+			/* set up the unique device id with the chip index */
+			subs->dma_device.id = subs->pcm->device << 16 |
+				subs->stream << 8 | (subs->number + 1) |
+				(chip->chip_idx + 1) << 24;
+	}
+	snd_pcm_lib_preallocate_pci_pages_for_all(chip->mgr->pci, pcm, 32*1024, 32*1024);
+}
+
+/*
+ */
+static int snd_mixart_pcm_analog(mixart_t *chip)
+{
+	int err;
+	snd_pcm_t *pcm;
+	char name[32];
+
+	sprintf(name, "miXart analog %d", chip->chip_idx);
+	if ((err = snd_pcm_new(chip->card, name, MIXART_PCM_ANALOG,
+			       MIXART_PLAYBACK_STREAMS,
+			       MIXART_CAPTURE_STREAMS, &pcm)) < 0) {
+		snd_printk(KERN_ERR "cannot create the analog pcm %d\n", chip->chip_idx);
+		return err;
+	}
+
+	pcm->private_data = chip;
+
+	snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_mixart_playback_ops);
+	snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_mixart_capture_ops);
+
+	pcm->info_flags = 0;
+	strcpy(pcm->name, name);
+
+	preallocate_buffers(chip, pcm);
+
+	chip->pcm = pcm;
+	return 0;
+}
+
+
+/*
+ */
+static int snd_mixart_pcm_digital(mixart_t *chip)
+{
+	int err;
+	snd_pcm_t *pcm;
+	char name[32];
+
+	sprintf(name, "miXart AES/EBU %d", chip->chip_idx);
+	if ((err = snd_pcm_new(chip->card, name, MIXART_PCM_DIGITAL,
+			       MIXART_PLAYBACK_STREAMS,
+			       MIXART_CAPTURE_STREAMS, &pcm)) < 0) {
+		snd_printk(KERN_ERR "cannot create the digital pcm %d\n", chip->chip_idx);
+		return err;
+	}
+
+	pcm->private_data = chip;
+
+	snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_mixart_playback_ops);
+	snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_mixart_capture_ops);
+
+	pcm->info_flags = 0;
+	strcpy(pcm->name, name);
+
+	preallocate_buffers(chip, pcm);
+
+	chip->pcm_dig = pcm;
+	return 0;
+}
+
+static int snd_mixart_chip_free(mixart_t *chip)
+{
+	snd_magic_kfree(chip);
+	return 0;
+}
+
+static int snd_mixart_chip_dev_free(snd_device_t *device)
+{
+	mixart_t *chip = snd_magic_cast(mixart_t, device->device_data, return -ENXIO);
+	return snd_mixart_chip_free(chip);
+}
+
+
+/*
+ */
+static int __devinit snd_mixart_create(mixart_mgr_t *mgr, snd_card_t *card, int idx)
+{
+	int err;
+	mixart_t *chip;
+	static snd_device_ops_t ops = {
+		.dev_free = snd_mixart_chip_dev_free,
+	};
+
+	mgr->chip[idx] = chip = snd_magic_kcalloc(mixart_t, 0, GFP_KERNEL);
+	if (! chip) {
+		snd_printk(KERN_ERR "cannot allocate chip\n");
+		return -ENOMEM;
+	}
+
+	chip->card = card;
+	chip->chip_idx = idx;
+	chip->mgr = mgr;
+
+	if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops)) < 0) {
+		snd_mixart_chip_free(chip);
+		return err;
+	}
+
+	if (idx == 0) {
+		/* create a DSP loader only on first cardX*/
+		err = snd_mixart_hwdep_new(mgr);
+		if (err < 0)
+			return err;
+	}
+
+	snd_card_set_dev(card, &mgr->pci->dev);
+
+	return 0;
+}
+
+int snd_mixart_create_pcm(mixart_t* chip)
+{
+	int err;
+
+	err = snd_mixart_pcm_analog(chip);
+	if (err < 0)
+		return err;
+
+	if(chip->mgr->board_type == MIXART_DAUGHTER_TYPE_AES) {
+
+		err = snd_mixart_pcm_digital(chip);
+		if (err < 0)
+			return err;
+	}
+	return err;
+}
+
+
+/*
+ * release all the cards assigned to a manager instance
+ */
+static int snd_mixart_free(mixart_mgr_t *mgr)
+{
+	unsigned int i;
+
+	for (i = 0; i < mgr->num_cards; i++) {
+		if (mgr->chip[i])
+			snd_card_free(mgr->chip[i]->card);
+	}
+
+	/* stop mailbox */
+	snd_mixart_exit_mailbox(mgr);
+
+	/* release irq  */
+	if (mgr->irq >= 0)
+		free_irq(mgr->irq, (void *)mgr);
+
+	/* reset board if some firmware was loaded */
+	if(mgr->hwdep->dsp_loaded) {
+		snd_mixart_reset_board(mgr);
+		snd_printdd("reset miXart !\n");
+	}
+
+	/* release the i/o ports */
+	for (i = 0; i < 2; i++) {
+		if (mgr->mem[i].virt)
+			iounmap((void *)mgr->mem[i].virt);
+		if (mgr->mem[i].res) {
+			release_resource(mgr->mem[i].res);
+			kfree_nocheck(mgr->mem[i].res);
+		}
+	}
+
+	/* free flowarray */
+	if(mgr->flowinfo_array) {
+		snd_free_pci_pages(mgr->pci, PAGE_ALIGN(MIXART_MAX_STREAM_PER_CARD * MIXART_MAX_CARDS * sizeof(mixart_flowinfo_t)),
+				   mgr->flowinfo_array, mgr->flowinfo_physaddr);
+	}
+	/* free bufferarray */
+	if(mgr->bufferinfo_array) {
+		snd_free_pci_pages(mgr->pci, PAGE_ALIGN(MIXART_MAX_STREAM_PER_CARD * MIXART_MAX_CARDS * sizeof(mixart_bufferinfo_t)),
+				   mgr->bufferinfo_array, mgr->bufferinfo_physaddr);
+	}
+
+	snd_magic_kfree(mgr);
+	return 0;
+}
+
+/*
+ * proc interface
+ */
+static long long snd_mixart_BA0_llseek(snd_info_entry_t *entry,
+				       void *private_file_data,
+				       struct file *file,
+				       long long offset,
+				       int orig)
+{
+	offset = offset & ~3; /* 4 bytes aligned */
+
+	switch(orig) {
+	case 0:  /* SEEK_SET */
+		file->f_pos = offset;
+		break;
+	case 1:  /* SEEK_CUR */
+		file->f_pos += offset;
+		break;
+	case 2:  /* SEEK_END, offset is negative */
+		file->f_pos = MIXART_BA0_SIZE + offset;
+		break;
+	default:
+		return -EINVAL;
+	}
+	if(file->f_pos > MIXART_BA0_SIZE)
+		file->f_pos = MIXART_BA0_SIZE;
+	return file->f_pos;
+}
+
+static long long snd_mixart_BA1_llseek(snd_info_entry_t *entry,
+				       void *private_file_data,
+				       struct file *file,
+				       long long offset,
+				       int orig)
+{
+	offset = offset & ~3; /* 4 bytes aligned */
+
+	switch(orig) {
+	case 0:  /* SEEK_SET */
+		file->f_pos = offset;
+		break;
+	case 1:  /* SEEK_CUR */
+		file->f_pos += offset;
+		break;
+	case 2: /* SEEK_END, offset is negative */
+		file->f_pos = MIXART_BA1_SIZE + offset;
+		break;
+	default:
+		return -EINVAL;
+	}
+	if(file->f_pos > MIXART_BA1_SIZE)
+		file->f_pos = MIXART_BA1_SIZE;
+	return file->f_pos;
+}
+
+/*
+  mixart_BA0 proc interface for BAR 0 - read callback
+ */
+static long snd_mixart_BA0_read(snd_info_entry_t *entry, void *file_private_data,
+				struct file *file, char *buf, long count)
+{
+	mixart_mgr_t *mgr = snd_magic_cast(mixart_mgr_t, entry->private_data, return -ENXIO);
+
+	count = count & ~3; /* make sure the read size is a multiple of 4 bytes */
+	if(count <= 0)
+		return 0;
+	if(file->f_pos + count > MIXART_BA0_SIZE)
+		count = (long)(MIXART_BA0_SIZE - file->f_pos);
+	if(copy_to_user_fromio(buf, MIXART_MEM( mgr, file->f_pos ), count))
+		return -EFAULT;
+	file->f_pos += count;
+	return count;
+}
+
+/*
+  mixart_BA1 proc interface for BAR 1 - read callback
+ */
+static long snd_mixart_BA1_read(snd_info_entry_t *entry, void *file_private_data,
+				struct file *file, char *buf, long count)
+{
+	mixart_mgr_t *mgr = snd_magic_cast(mixart_mgr_t, entry->private_data, return -ENXIO);
+
+	count = count & ~3; /* make sure the read size is a multiple of 4 bytes */
+	if(count <= 0)
+		return 0;
+	if(file->f_pos + count > MIXART_BA1_SIZE)
+		count = (long)(MIXART_BA1_SIZE - file->f_pos);
+	if(copy_to_user_fromio(buf, MIXART_REG( mgr, file->f_pos ), count))
+		return -EFAULT;
+	file->f_pos += count;
+	return count;
+}
+
+static struct snd_info_entry_ops snd_mixart_proc_ops_BA0 = {
+	.read   = snd_mixart_BA0_read,
+	.llseek = snd_mixart_BA0_llseek
+};
+
+static struct snd_info_entry_ops snd_mixart_proc_ops_BA1 = {
+	.read   = snd_mixart_BA1_read,
+	.llseek = snd_mixart_BA1_llseek
+};
+
+
+static void snd_mixart_proc_read(snd_info_entry_t *entry, 
+                                 snd_info_buffer_t * buffer)
+{
+	mixart_t *chip = snd_magic_cast(mixart_t, entry->private_data, return);        
+	u32 ref; 
+
+	snd_iprintf(buffer, "Digigram miXart (alsa card %d)\n\n", chip->chip_idx);
+
+	/* stats available when embedded OS is running */
+	if (chip->mgr->hwdep->dsp_loaded & ( 1 << MIXART_MOTHERBOARD_ELF_INDEX)) {
+		snd_iprintf(buffer, "- hardware -\n");
+		switch (chip->mgr->board_type ) {
+		case MIXART_DAUGHTER_TYPE_NONE     : snd_iprintf(buffer, "\tmiXart8 (no daughter board)\n\n"); break;
+		case MIXART_DAUGHTER_TYPE_AES      : snd_iprintf(buffer, "\tmiXart8 AES/EBU\n\n"); break;
+		case MIXART_DAUGHTER_TYPE_COBRANET : snd_iprintf(buffer, "\tmiXart8 Cobranet\n\n"); break;
+		default:                             snd_iprintf(buffer, "\tUNKNOWN!\n\n"); break;
+		}
+
+		snd_iprintf(buffer, "- system load -\n");	 
+
+		/* get perf reference */
+
+		ref = readl_be( MIXART_MEM( chip->mgr, MIXART_PSEUDOREG_PERF_SYSTEM_LOAD_OFFSET));
+
+		if (ref) {
+			u32 mailbox   = 100 * readl_be( MIXART_MEM( chip->mgr, MIXART_PSEUDOREG_PERF_MAILBX_LOAD_OFFSET)) / ref;
+			u32 streaming = 100 * readl_be( MIXART_MEM( chip->mgr, MIXART_PSEUDOREG_PERF_STREAM_LOAD_OFFSET)) / ref;
+			u32 interr    = 100 * readl_be( MIXART_MEM( chip->mgr, MIXART_PSEUDOREG_PERF_INTERR_LOAD_OFFSET)) / ref;
+
+			snd_iprintf(buffer, "\tstreaming          : %d\n", streaming);
+			snd_iprintf(buffer, "\tmailbox            : %d\n", mailbox);
+			snd_iprintf(buffer, "\tinterrups handling : %d\n\n", interr);
+		}
+	} /* endif elf loaded */
+}
+
+static void __devinit snd_mixart_proc_init(mixart_t *chip)
+{
+	snd_info_entry_t *entry;
+
+	/* text interface to read perf and temp meters */
+	if (! snd_card_proc_new(chip->card, "board_info", &entry)) {
+		entry->private_data = chip;
+		entry->c.text.read_size = 1024;
+		entry->c.text.read = snd_mixart_proc_read;
+	}
+
+	if (! snd_card_proc_new(chip->card, "mixart_BA0", &entry)) {
+		entry->content = SNDRV_INFO_CONTENT_DATA;
+		entry->private_data = chip->mgr;	
+		entry->c.ops = &snd_mixart_proc_ops_BA0;
+		entry->size = MIXART_BA0_SIZE;
+	}
+	if (! snd_card_proc_new(chip->card, "mixart_BA1", &entry)) {
+		entry->content = SNDRV_INFO_CONTENT_DATA;
+		entry->private_data = chip->mgr;
+		entry->c.ops = &snd_mixart_proc_ops_BA1;
+		entry->size = MIXART_BA1_SIZE;
+	}
+}
+/* end of proc interface */
+
+
+/*
+ *    probe function - creates the card manager
+ */
+static int __devinit snd_mixart_probe(struct pci_dev *pci,
+				      const struct pci_device_id *pci_id)
+{
+	static int dev;
+	mixart_mgr_t *mgr;
+	unsigned int i;
+	int err;
+	size_t size;
+
+	/*
+	 */
+	if (dev >= SNDRV_CARDS)
+		return -ENODEV;
+	if (! enable[dev]) {
+		dev++;
+		return -ENOENT;
+	}
+
+	/* enable PCI device */
+	if ((err = pci_enable_device(pci)) < 0)
+		return err;
+	pci_set_master(pci);
+
+	/* check if we can restrict PCI DMA transfers to 32 bits */
+	if (!pci_dma_supported(pci, 0xffffffff)) {
+		snd_printk(KERN_ERR "architecture does not support 32bit PCI busmaster DMA\n");
+		return -ENXIO;
+	}
+	pci_set_dma_mask(pci, 0xffffffff);
+
+	/*
+	 */
+	mgr = snd_magic_kcalloc(mixart_mgr_t, 0, GFP_KERNEL);
+	if (! mgr)
+		return -ENOMEM;
+
+	mgr->pci = pci;
+	mgr->irq = -1;
+
+	/* resource assignment */
+	for (i = 0; i < 2; i++) {
+		static int memory_sizes[2] = {
+			MIXART_BA0_SIZE, /* 16M */	  
+			MIXART_BA1_SIZE  /* 4 k */
+		};
+		mgr->mem[i].phys = pci_resource_start(pci, i);
+		mgr->mem[i].res = request_mem_region(mgr->mem[i].phys, memory_sizes[i], CARD_NAME);
+		if (! mgr->mem[i].res) {
+			snd_printk(KERN_ERR "unable to grab memory 0x%lx\n", mgr->mem[i].phys);
+			snd_mixart_free(mgr);
+			return -EBUSY;
+		}
+		mgr->mem[i].virt = (unsigned long)ioremap_nocache(mgr->mem[i].phys, memory_sizes[i]);
+	}
+
+	if (request_irq(pci->irq, snd_mixart_interrupt, SA_INTERRUPT|SA_SHIRQ, CARD_NAME, (void *)mgr)) {
+		snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq);
+		snd_mixart_free(mgr);
+		return -EBUSY;
+	}
+	mgr->irq = pci->irq;
+
+	sprintf(mgr->shortname, "Digigram miXart");
+	sprintf(mgr->longname, "%s at 0x%lx & 0x%lx, irq %i", mgr->shortname, mgr->mem[0].phys, mgr->mem[1].phys, mgr->irq);
+
+	/* ISR spinlock  */
+	mgr->lock = SPIN_LOCK_UNLOCKED;
+
+	/* init mailbox  */
+	mgr->msg_fifo_readptr = 0;
+	mgr->msg_fifo_writeptr = 0;
+
+	mgr->msg_lock = SPIN_LOCK_UNLOCKED;
+	init_MUTEX(&mgr->msg_mutex);
+
+	/* init setup mutex*/
+	init_MUTEX(&mgr->setup_mutex);
+
+	/* init message taslket */
+	tasklet_init( &mgr->msg_taskq, snd_mixart_msg_tasklet, (unsigned long) mgr);
+
+	/* card assignment */
+	mgr->num_cards = MIXART_MAX_CARDS; /* 4  FIXME: configurable? */
+	for (i = 0; i < mgr->num_cards; i++) {
+		snd_card_t *card;
+		char tmpid[16];
+		int idx;
+
+		if (index[dev] < 0)
+			idx = index[dev];
+		else
+			idx = index[dev] + i;
+		snprintf(tmpid, sizeof(tmpid), "%s-%d", id[dev], i);
+		card = snd_card_new(idx, tmpid, THIS_MODULE, 0);
+
+		if (! card) {
+			snd_printk(KERN_ERR "cannot allocate the card %d\n", i);
+			snd_mixart_free(mgr);
+			return -ENOMEM;
+		}
+
+		strcpy(card->driver, CARD_NAME);
+		sprintf(card->shortname, "%s [PCM #%d]", mgr->shortname, i);
+		sprintf(card->longname, "%s [PCM #%d]", mgr->longname, i);
+
+		if ((err = snd_mixart_create(mgr, card, i)) < 0) {
+			snd_mixart_free(mgr);
+			return err;
+		}
+
+		if(i==0) {
+			/* init proc interface only for chip0 */
+			snd_mixart_proc_init(mgr->chip[i]);
+		}
+
+		if ((err = snd_card_register(card)) < 0) {
+			snd_mixart_free(mgr);
+			return err;
+		}
+	}
+
+	/* init firmware status (mgr->hwdep->dsp_loaded reset in hwdep_new) */
+	mgr->board_type = MIXART_DAUGHTER_TYPE_NONE;
+
+	/* create array of streaminfo */
+	size = PAGE_ALIGN( (MIXART_MAX_STREAM_PER_CARD * MIXART_MAX_CARDS * sizeof(mixart_flowinfo_t)) );
+	mgr->flowinfo_array = snd_malloc_pci_pages(mgr->pci, size, &mgr->flowinfo_physaddr);
+	if(!mgr->flowinfo_array) {
+		snd_mixart_free(mgr);
+		return -ENOMEM;
+	}
+	/* init streaminfo_array */
+	memset(mgr->flowinfo_array, 0, size);
+
+	/* create array of bufferinfo */
+	size = PAGE_ALIGN( (MIXART_MAX_STREAM_PER_CARD * MIXART_MAX_CARDS * sizeof(mixart_bufferinfo_t)) );
+	mgr->bufferinfo_array = snd_malloc_pci_pages(mgr->pci, size, &mgr->bufferinfo_physaddr);
+	if(!mgr->bufferinfo_array) {
+		snd_mixart_free(mgr);
+		return -ENOMEM;
+	}
+	/* init bufferinfo_array */
+	memset(mgr->bufferinfo_array, 0, size);
+
+	pci_set_drvdata(pci, mgr);
+	dev++;
+	return 0;
+}
+
+static void __devexit snd_mixart_remove(struct pci_dev *pci)
+{
+	snd_mixart_free(pci_get_drvdata(pci));
+	pci_set_drvdata(pci, NULL);
+}
+
+static struct pci_driver driver = {
+	.name = "Digigram miXart",
+	.id_table = snd_mixart_ids,
+	.probe = snd_mixart_probe,
+	.remove = __devexit_p(snd_mixart_remove),
+};
+
+static int __init alsa_card_mixart_init(void)
+{
+	int err;
+
+	if ((err = pci_module_init(&driver)) < 0) {
+#ifdef MODULE
+		snd_printk(KERN_ERR "Digigram miXart soundcard not found or device busy\n");
+#endif
+		return err;
+	}
+	return 0;
+}
+
+static void __exit alsa_card_mixart_exit(void)
+{
+	pci_unregister_driver(&driver);
+}
+
+module_init(alsa_card_mixart_init)
+module_exit(alsa_card_mixart_exit)
+
+#ifndef MODULE
+
+/* format is: snd-mixart=enable,index,id */
+
+static int __init alsa_card_mixart_setup(char *str)
+{
+	static unsigned __initdata nr_dev = 0;
+
+	if (nr_dev >= SNDRV_CARDS)
+		return 0;
+	(void)(get_option(&str,&enable[nr_dev]) == 2 &&
+	       get_option(&str,&index[nr_dev]) == 2 &&
+	       get_id(&str,&id[nr_dev]) == 2);
+	nr_dev++;
+	return 1;
+}
+
+__setup("snd-mixart=", alsa_card_mixart_setup);
+
+#endif /* ifndef MODULE */
--- diff/sound/pci/mixart/mixart.h	1970-01-01 01:00:00.000000000 +0100
+++ source/sound/pci/mixart/mixart.h	2004-02-23 13:56:48.000000000 +0000
@@ -0,0 +1,242 @@
+/*
+ * Driver for Digigram miXart soundcards
+ *
+ * main header file
+ *
+ * Copyright (c) 2003 by Digigram <alsa@digigram.com>
+ *
+ *   This program is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License as published by
+ *   the Free Software Foundation; either version 2 of the License, or
+ *   (at your option) any later version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ */
+
+#ifndef __SOUND_MIXART_H
+#define __SOUND_MIXART_H
+
+#include <sound/pcm.h>
+
+#define MIXART_DRIVER_VERSION	0x000100	/* 0.1.0 */
+
+
+/*
+ */
+
+#define mixart_t_magic		0xa17a3e01
+#define mixart_mgr_t_magic	0xa17a3e02
+
+typedef struct snd_mixart mixart_t;
+typedef struct snd_mixart_mgr mixart_mgr_t;
+
+typedef struct snd_mixart_stream mixart_stream_t;
+typedef struct snd_mixart_pipe mixart_pipe_t;
+
+typedef struct mixart_bufferinfo mixart_bufferinfo_t;
+typedef struct mixart_flowinfo mixart_flowinfo_t;
+typedef struct mixart_uid mixart_uid_t;
+
+struct mixart_uid
+{
+	u32 object_id;
+	u32 desc;
+};
+
+struct mem_area {
+	unsigned long phys;
+	unsigned long virt;
+	struct resource *res;
+};
+
+
+typedef struct mixart_route mixart_route_t;
+struct mixart_route {
+	unsigned char connected;
+	unsigned char phase_inv;
+	int volume;
+};
+
+
+/* firmware status codes  */
+#define MIXART_MOTHERBOARD_XLX_INDEX  0
+#define MIXART_MOTHERBOARD_ELF_INDEX  1
+#define MIXART_AESEBUBOARD_XLX_INDEX  2
+#define MIXART_HARDW_FILES_MAX_INDEX  3  /* xilinx, elf, AESEBU xilinx */
+
+#define MIXART_MAX_CARDS	4
+#define MSG_FIFO_SIZE           16
+
+#define MIXART_MAX_PHYS_CONNECTORS  (MIXART_MAX_CARDS * 2 * 2) /* 4 * stereo * (analog+digital) */
+
+struct snd_mixart_mgr {
+	unsigned int num_cards;
+	mixart_t *chip[MIXART_MAX_CARDS];
+
+	struct pci_dev *pci;
+
+	int irq;
+
+	/* memory-maps */
+	struct mem_area mem[2];
+
+	/* share the name */
+	char shortname[32];         /* short name of this soundcard */
+	char longname[80];          /* name of this soundcard */
+
+	/* message tasklet */
+	struct tasklet_struct msg_taskq;
+
+	/* one and only blocking message or notification may be pending  */
+	u32 pending_event;
+	wait_queue_head_t msg_sleep;
+
+	/* messages stored for tasklet */
+	u32 msg_fifo[MSG_FIFO_SIZE];
+	int msg_fifo_readptr;
+	int msg_fifo_writeptr;
+
+	spinlock_t lock;              /* interrupt spinlock */
+	spinlock_t msg_lock;          /* mailbox spinlock */
+	struct semaphore msg_mutex;   /* mutex for blocking_requests */
+
+	struct semaphore setup_mutex; /* mutex used in hw_params, open and close */
+
+	/* hardware interface */
+	snd_hwdep_t *hwdep;
+	unsigned int board_type;      /* read from embedded once elf file is loaded, 250 = miXart8, 251 = with AES, 252 = with Cobranet */
+
+	mixart_flowinfo_t*   flowinfo_array;
+	dma_addr_t           flowinfo_physaddr;
+	mixart_bufferinfo_t* bufferinfo_array;
+	dma_addr_t           bufferinfo_physaddr;
+
+	mixart_uid_t         uid_console_manager;
+	int sample_rate;
+	int ref_count_rate;
+
+	struct semaphore mixer_mutex; /* mutex for mixer */
+
+};
+
+
+#define MIXART_STREAM_STATUS_FREE	0
+#define MIXART_STREAM_STATUS_OPEN	1
+#define MIXART_STREAM_STATUS_RUNNING	2
+#define MIXART_STREAM_STATUS_DRAINING	3
+#define MIXART_STREAM_STATUS_PAUSE	4
+
+#define MIXART_PLAYBACK_STREAMS		4
+#define MIXART_CAPTURE_STREAMS		1
+
+#define MIXART_PCM_ANALOG		0
+#define MIXART_PCM_DIGITAL		1
+#define MIXART_PCM_TOTAL		2
+
+#define MIXART_MAX_STREAM_PER_CARD  (MIXART_PCM_TOTAL * (MIXART_PLAYBACK_STREAMS + MIXART_CAPTURE_STREAMS) )
+
+
+#define MIXART_NOTIFY_CARD_MASK		0xF000
+#define MIXART_NOTIFY_CARD_OFFSET	12
+#define MIXART_NOTIFY_PCM_MASK		0x0F00
+#define MIXART_NOTIFY_PCM_OFFSET	8
+#define MIXART_NOTIFY_CAPT_MASK		0x0080
+#define MIXART_NOTIFY_SUBS_MASK		0x007F
+
+
+struct snd_mixart_stream {
+	snd_pcm_substream_t *substream;
+	mixart_pipe_t *pipe;
+	int pcm_number;
+
+	int status;      /* nothing, running, draining */
+
+	u64  abs_period_elapsed;  /* last absolute stream position where period_elapsed was called (multiple of runtime->period_size) */
+	u32  buf_periods;         /* periods counter in the buffer (< runtime->periods) */
+	u32  buf_period_frag;     /* defines with buf_period_pos the exact position in the buffer (< runtime->period_size) */
+
+	int channels;
+};
+
+
+enum mixart_pipe_status {
+	PIPE_UNDEFINED,
+	PIPE_STOPPED,
+	PIPE_RUNNING,
+	PIPE_CLOCK_SET
+};
+
+struct snd_mixart_pipe {
+	mixart_uid_t group_uid;			/* id of the pipe, as returned by embedded */
+	int          stream_count;
+	mixart_uid_t uid_left_connector;	/* UID's for the audio connectors */
+	mixart_uid_t uid_right_connector;
+	enum mixart_pipe_status status;
+	int references;             /* number of subs openned */
+	int monitoring;             /* pipe used for monitoring issue */
+};
+
+
+struct snd_mixart {
+	snd_card_t *card;
+	mixart_mgr_t *mgr;
+	int chip_idx;               /* zero based */
+	snd_hwdep_t *hwdep;	    /* DSP loader, only for the first card */
+
+	snd_pcm_t *pcm;             /* PCM analog i/o */
+	snd_pcm_t *pcm_dig;         /* PCM digital i/o */
+
+	/* allocate stereo pipe for instance */
+	mixart_pipe_t pipe_in_ana;
+	mixart_pipe_t pipe_out_ana;
+
+	/* if AES/EBU daughter board is available, additional pipes possible on pcm_dig */
+	mixart_pipe_t pipe_in_dig;
+	mixart_pipe_t pipe_out_dig;
+
+	mixart_stream_t playback_stream[MIXART_PCM_TOTAL][MIXART_PLAYBACK_STREAMS]; /* 0 = pcm, 1 = pcm_dig */
+	mixart_stream_t capture_stream[MIXART_PCM_TOTAL];                           /* 0 = pcm, 1 = pcm_dig */
+
+	/* UID's for the physical io's */
+	mixart_uid_t uid_out_analog_physio;
+	mixart_uid_t uid_in_analog_physio;
+
+	int analog_playback_active[2];		/* Mixer : Master Playback active (!mute) */
+	int analog_playback_volume[2];		/* Mixer : Master Playback Volume */
+	int analog_capture_volume[2];		/* Mixer : Master Capture Volume */
+	int digital_playback_active[2*MIXART_PLAYBACK_STREAMS][2];	/* Mixer : Digital Playback Active [(analog+AES output)*streams][stereo]*/
+	int digital_playback_volume[2*MIXART_PLAYBACK_STREAMS][2];	/* Mixer : Digital Playback Volume [(analog+AES output)*streams][stereo]*/
+	int digital_capture_volume[2][2];	/* Mixer : Digital Capture Volume [analog+AES output][stereo] */
+	int monitoring_active[2];		/* Mixer : Monitoring Active */
+	int monitoring_volume[2];		/* Mixer : Monitoring Volume */
+};
+
+struct mixart_bufferinfo
+{
+	u32 buffer_address;
+	u32 reserved[5];
+	u32 available_length;
+	u32 buffer_id;
+};
+
+struct mixart_flowinfo
+{
+	u32 bufferinfo_array_phy_address;
+	u32 reserved[11];
+	u32 bufferinfo_count;
+	u32 capture;
+};
+
+/* exported */
+int snd_mixart_create_pcm(mixart_t* chip);
+mixart_pipe_t* snd_mixart_add_ref_pipe( mixart_t *chip, int pcm_number, int capture, int monitoring);
+int snd_mixart_kill_ref_pipe( mixart_mgr_t *mgr, mixart_pipe_t *pipe, int monitoring);
+
+#endif /* __SOUND_MIXART_H */
--- diff/sound/pci/mixart/mixart_core.c	1970-01-01 01:00:00.000000000 +0100
+++ source/sound/pci/mixart/mixart_core.c	2004-02-23 13:56:48.000000000 +0000
@@ -0,0 +1,588 @@
+/*
+ * Driver for Digigram miXart soundcards
+ *
+ * low level interface with interrupt handling and mail box implementation
+ *
+ * Copyright (c) 2003 by Digigram <alsa@digigram.com>
+ *
+ *   This program is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License as published by
+ *   the Free Software Foundation; either version 2 of the License, or
+ *   (at your option) any later version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ */
+
+#include <sound/driver.h>
+#include <sound/core.h>
+#include "mixart.h"
+#include "mixart_hwdep.h"
+#include "mixart_core.h"
+
+
+#define MSG_TIMEOUT_JIFFIES         (400 * HZ) / 1000 /* 400 ms */
+
+#define MSG_DESCRIPTOR_SIZE         0x24
+#define MSG_HEADER_SIZE             (MSG_DESCRIPTOR_SIZE + 4)
+
+#define MSG_DEFAULT_SIZE            512
+
+#define MSG_TYPE_MASK               0x00000003    /* mask for following types */
+#define MSG_TYPE_NOTIFY             0             /* embedded -> driver (only notification, do not get_msg() !) */
+#define MSG_TYPE_COMMAND            1             /* driver <-> embedded (a command has no answer) */
+#define MSG_TYPE_REQUEST            2             /* driver -> embedded (request will get an answer back) */
+#define MSG_TYPE_ANSWER             3             /* embedded -> driver */
+#define MSG_CANCEL_NOTIFY_MASK      0x80000000    /* this bit is set for a notification that has been canceled */
+
+
+static int retrieve_msg_frame(mixart_mgr_t *mgr, u32 *msg_frame)
+{
+	/* read the message frame fifo */
+	u32 headptr, tailptr;
+
+	tailptr = readl_be(MIXART_MEM(mgr, MSG_OUTBOUND_POST_TAIL));
+	headptr = readl_be(MIXART_MEM(mgr, MSG_OUTBOUND_POST_HEAD));
+
+	if (tailptr == headptr)
+		return 0; /* no message posted */
+
+	snd_assert( tailptr >= MSG_OUTBOUND_POST_STACK, return 0); /* error */
+	snd_assert( tailptr < (MSG_OUTBOUND_POST_STACK+MSG_BOUND_STACK_SIZE), return 0); /* error */
+
+	*msg_frame = readl_be(MIXART_MEM(mgr, tailptr));
+
+	/* increment the tail index */
+	tailptr += 4;
+	if( tailptr >= (MSG_OUTBOUND_POST_STACK+MSG_BOUND_STACK_SIZE) )
+		tailptr = MSG_OUTBOUND_POST_STACK;
+	writel_be(tailptr, MIXART_MEM(mgr, MSG_OUTBOUND_POST_TAIL));
+
+	return 1;
+}
+
+static int get_msg(mixart_mgr_t *mgr, mixart_msg_t *resp, u32 msg_frame_address )
+{
+	unsigned long flags;
+	u32  headptr, i;
+	u32  size;
+	int  err;
+
+	spin_lock_irqsave(&mgr->msg_lock, flags);
+	err = 0;
+
+	/* copy message descriptor from miXart to driver */
+	size                =  readl_be(MIXART_MEM(mgr, msg_frame_address));       /* size of descriptor + response */
+	resp->message_id    =  readl_be(MIXART_MEM(mgr, msg_frame_address + 4));   /* dwMessageID */
+	resp->uid.object_id =  readl_be(MIXART_MEM(mgr, msg_frame_address + 8));   /* uidDest */
+	resp->uid.desc      =  readl_be(MIXART_MEM(mgr, msg_frame_address + 12));  /* */
+
+	if( (size < MSG_DESCRIPTOR_SIZE) || (resp->size < (size - MSG_DESCRIPTOR_SIZE))) {
+		err = -EINVAL;
+		snd_printk(KERN_ERR "problem with response size = %d\n", size);
+		goto _clean_exit;
+	}
+	size -= MSG_DESCRIPTOR_SIZE;
+
+	memcpy_fromio(resp->data, MIXART_MEM(mgr, msg_frame_address + MSG_HEADER_SIZE ), size);
+	resp->size = size;
+
+	/* swap if necessary */
+#ifndef __BIG_ENDIAN
+	size /= 4; /* u32 size */
+	for(i=0; i < size; i++) {
+		((u32*)resp->data)[i] = be32_to_cpu(((u32*)resp->data)[i]);
+	}
+#endif
+
+	/*
+	 * free message frame address
+	 */
+	headptr = readl_be(MIXART_MEM(mgr, MSG_OUTBOUND_FREE_HEAD));
+
+	if( (headptr < MSG_OUTBOUND_FREE_STACK) || ( headptr >= (MSG_OUTBOUND_FREE_STACK+MSG_BOUND_STACK_SIZE))) {
+		err = -EINVAL;
+		goto _clean_exit;
+	}
+
+	/* give address back to outbound fifo */
+	writel_be(msg_frame_address, MIXART_MEM(mgr, headptr));
+
+	/* increment the outbound free head */
+	headptr += 4;
+	if( headptr >= (MSG_OUTBOUND_FREE_STACK+MSG_BOUND_STACK_SIZE) )
+		headptr = MSG_OUTBOUND_FREE_STACK;
+
+	writel_be(headptr, MIXART_MEM(mgr, MSG_OUTBOUND_FREE_HEAD));
+
+ _clean_exit:
+	spin_unlock_irqrestore(&mgr->msg_lock, flags);
+
+	return err;
+}
+
+
+/*
+ * send a message to miXart. return: the msg_frame used for this message
+ */
+static int send_msg( mixart_mgr_t *mgr,
+		     mixart_msg_t *msg,
+		     int max_answersize,
+		     int mark_pending,
+		     u32 *msg_event)
+{
+	unsigned long flags;
+	u32 headptr, tailptr;
+	u32 msg_frame_address;
+	int err, i;
+
+	snd_assert(msg->size % 4 == 0, return -EINVAL);
+
+	spin_lock_irqsave(&mgr->msg_lock, flags);
+	err = 0;
+
+	/* get message frame address */
+	tailptr = readl_be(MIXART_MEM(mgr, MSG_INBOUND_FREE_TAIL));
+	headptr = readl_be(MIXART_MEM(mgr, MSG_INBOUND_FREE_HEAD));
+
+	if (tailptr == headptr) {
+		snd_printk(KERN_ERR "error: no message frame available\n");
+		err = -EBUSY;
+		goto _clean_exit;
+	}
+
+	if( (tailptr < MSG_INBOUND_FREE_STACK) || (tailptr >= (MSG_INBOUND_FREE_STACK+MSG_BOUND_STACK_SIZE))) {
+		err = -EINVAL;
+		goto _clean_exit;
+	}
+
+	msg_frame_address = readl_be(MIXART_MEM(mgr, tailptr));
+	writel(0, MIXART_MEM(mgr, tailptr)); /* set address to zero on this fifo position */
+
+	/* increment the inbound free tail */
+	tailptr += 4;
+	if( tailptr >= (MSG_INBOUND_FREE_STACK+MSG_BOUND_STACK_SIZE) )
+		tailptr = MSG_INBOUND_FREE_STACK;
+
+	writel_be(tailptr, MIXART_MEM(mgr, MSG_INBOUND_FREE_TAIL));
+
+	/* TODO : use memcpy_toio() with intermediate buffer to copy the message */
+
+	/* copy message descriptor to card memory */
+	writel_be( msg->size + MSG_DESCRIPTOR_SIZE,      MIXART_MEM(mgr, msg_frame_address) );      /* size of descriptor + request */
+	writel_be( msg->message_id ,                     MIXART_MEM(mgr, msg_frame_address + 4) );  /* dwMessageID */
+	writel_be( msg->uid.object_id,                   MIXART_MEM(mgr, msg_frame_address + 8) );  /* uidDest */
+	writel_be( msg->uid.desc,                        MIXART_MEM(mgr, msg_frame_address + 12) ); /* */
+	writel_be( MSG_DESCRIPTOR_SIZE,                  MIXART_MEM(mgr, msg_frame_address + 16) ); /* SizeHeader */
+	writel_be( MSG_DESCRIPTOR_SIZE,                  MIXART_MEM(mgr, msg_frame_address + 20) ); /* OffsetDLL_T16 */
+	writel_be( msg->size,                            MIXART_MEM(mgr, msg_frame_address + 24) ); /* SizeDLL_T16 */
+	writel_be( MSG_DESCRIPTOR_SIZE,                  MIXART_MEM(mgr, msg_frame_address + 28) ); /* OffsetDLL_DRV */
+	writel_be( 0,                                    MIXART_MEM(mgr, msg_frame_address + 32) ); /* SizeDLL_DRV */
+	writel_be( MSG_DESCRIPTOR_SIZE + max_answersize, MIXART_MEM(mgr, msg_frame_address + 36) ); /* dwExpectedAnswerSize */
+
+	/* copy message data to card memory */
+	for( i=0; i < msg->size; i+=4 ) {
+		writel_be( *(u32*)(msg->data + i), MIXART_MEM(mgr, MSG_HEADER_SIZE + msg_frame_address + i)  );
+	}
+
+	if( mark_pending ) {
+		if( *msg_event ) {
+			/* the pending event is the notification we wait for ! */
+			mgr->pending_event = *msg_event;
+		}
+		else {
+			/* the pending event is the answer we wait for (same address than the request)! */
+			mgr->pending_event = msg_frame_address;
+
+			/* copy address back to caller */
+			*msg_event = msg_frame_address;
+		}
+	}
+
+	/* mark the frame as a request (will have an answer) */
+	msg_frame_address |= MSG_TYPE_REQUEST;
+
+	/* post the frame */
+	headptr = readl_be(MIXART_MEM(mgr, MSG_INBOUND_POST_HEAD));
+
+	if( (headptr < MSG_INBOUND_POST_STACK) || (headptr >= (MSG_INBOUND_POST_STACK+MSG_BOUND_STACK_SIZE))) {
+		err = -EINVAL;
+		goto _clean_exit;
+	}
+
+	writel_be(msg_frame_address, MIXART_MEM(mgr, headptr));
+
+	/* increment the inbound post head */
+	headptr += 4;
+	if( headptr >= (MSG_INBOUND_POST_STACK+MSG_BOUND_STACK_SIZE) )
+		headptr = MSG_INBOUND_POST_STACK;
+
+	writel_be(headptr, MIXART_MEM(mgr, MSG_INBOUND_POST_HEAD));
+
+ _clean_exit:
+	spin_unlock_irqrestore(&mgr->msg_lock, flags);
+	return 0;
+}
+
+
+int snd_mixart_send_msg(mixart_mgr_t *mgr, mixart_msg_t *request, int max_resp_size, void *resp_data)
+{
+	mixart_msg_t resp;
+	u32 msg_frame = 0; /* set to 0, so it's no notification to wait for, but the answer */
+	int err;
+	wait_queue_t wait;
+	long timeout;
+
+	down(&mgr->msg_mutex);
+
+	init_waitqueue_head(&mgr->msg_sleep);
+	init_waitqueue_entry(&wait, current);
+
+	current->state = TASK_UNINTERRUPTIBLE;
+	add_wait_queue(&mgr->msg_sleep, &wait);
+
+	/* send the message */
+	err = send_msg(mgr, request, max_resp_size, 1, &msg_frame);  /* send and mark the answer pending */
+	if(err) {
+		current->state = TASK_RUNNING;
+		remove_wait_queue(&mgr->msg_sleep, &wait);
+		up(&mgr->msg_mutex);
+		return err;
+	}
+
+	timeout = schedule_timeout(MSG_TIMEOUT_JIFFIES);
+	current->state = TASK_RUNNING;
+	remove_wait_queue(&mgr->msg_sleep, &wait);
+
+	if (! timeout) {
+		/* error - no ack */
+		up(&mgr->msg_mutex);
+		snd_printk(KERN_ERR "error: no reponse on msg %x\n", msg_frame);
+		return -EIO;
+	}
+
+	/* retrieve the answer into the same mixart_msg_t */
+	resp.message_id = 0;
+	resp.uid = (mixart_uid_t){0,0};
+	resp.data = resp_data;
+	resp.size = max_resp_size;
+
+	err = get_msg(mgr, &resp, msg_frame);
+
+	if( request->message_id != resp.message_id )
+		snd_printk(KERN_ERR "REPONSE ERROR!\n");
+
+	up(&mgr->msg_mutex);
+	return err;
+}
+
+
+int snd_mixart_send_msg_wait_notif(mixart_mgr_t *mgr, mixart_msg_t *request, u32 notif_event)
+{
+	int err;
+	wait_queue_t wait;
+	long timeout;
+
+	snd_assert(notif_event != 0, return -EINVAL);
+	snd_assert((notif_event & MSG_TYPE_MASK) == MSG_TYPE_NOTIFY, return -EINVAL);
+	snd_assert((notif_event & MSG_CANCEL_NOTIFY_MASK) == 0, return -EINVAL);
+
+	down(&mgr->msg_mutex);
+
+	init_waitqueue_head(&mgr->msg_sleep);
+	init_waitqueue_entry(&wait, current);
+
+	current->state = TASK_UNINTERRUPTIBLE;
+	add_wait_queue(&mgr->msg_sleep, &wait);
+
+	/* send the message */
+	err = send_msg(mgr, request, MSG_DEFAULT_SIZE, 1, &notif_event);  /* send and mark the notification event pending */
+	if(err) {
+		current->state = TASK_RUNNING;
+		remove_wait_queue(&mgr->msg_sleep, &wait);
+		up(&mgr->msg_mutex);
+		return err;
+	}
+
+	timeout = schedule_timeout(MSG_TIMEOUT_JIFFIES);
+	current->state = TASK_RUNNING;
+	remove_wait_queue(&mgr->msg_sleep, &wait);
+
+	if (! timeout) {
+		/* error - no ack */
+		up(&mgr->msg_mutex);
+		snd_printk(KERN_ERR "error: notification %x not received\n", notif_event);
+		return -EIO;
+	}
+
+	up(&mgr->msg_mutex);
+	return 0;
+}
+
+
+int snd_mixart_send_msg_nonblock(mixart_mgr_t *mgr, mixart_msg_t *request)
+{
+	u32 message_frame;
+
+	/* just send the message (do not mark it as a pending one) */
+	return send_msg(mgr, request, MSG_DEFAULT_SIZE, 0, &message_frame);
+
+	/* the answer will be handled by snd_mixart_msg_tasklet()  */
+}
+
+
+/* common buffer of tasklet and interrupt to send/receive messages */
+static u32 mixart_msg_data[MSG_DEFAULT_SIZE / 4];
+
+
+void snd_mixart_msg_tasklet( unsigned long arg)
+{
+	mixart_mgr_t *mgr = ( mixart_mgr_t*)(arg);
+	mixart_msg_t resp;
+	u32 msg, addr, type;
+	int err;
+
+	spin_lock(&mgr->lock);
+
+	while (mgr->msg_fifo_readptr != mgr->msg_fifo_writeptr) {
+		msg = mgr->msg_fifo[mgr->msg_fifo_readptr];
+		mgr->msg_fifo_readptr++;
+		mgr->msg_fifo_readptr %= MSG_FIFO_SIZE;
+
+		/* process the message ... */
+		addr = msg & ~MSG_TYPE_MASK;
+		type = msg & MSG_TYPE_MASK;
+
+		switch (type) {
+		case MSG_TYPE_ANSWER:
+			/* answer to a message on that we did not wait for (send_msg_nonblock) */
+			resp.message_id = 0;
+			resp.data = mixart_msg_data;
+			resp.size = sizeof(mixart_msg_data);
+			err = get_msg(mgr, &resp, addr);
+			if( err < 0 ) {
+				snd_printk(KERN_ERR "tasklet: error(%d) reading mf %x\n", err, msg);
+				break;
+			}
+
+			switch(resp.message_id) {
+			case MSG_STREAM_START_INPUT_STAGE_PACKET:
+			case MSG_STREAM_START_OUTPUT_STAGE_PACKET:
+			case MSG_STREAM_STOP_INPUT_STAGE_PACKET:
+			case MSG_STREAM_STOP_OUTPUT_STAGE_PACKET:
+				if(mixart_msg_data[0])
+					snd_printdd("tasklet : MSG_STREAM_ST***_***PUT_STAGE_PACKET txx_status(%x)\n", mixart_msg_data[0]);
+				break;
+			case MSG_CLOCK_CHECK_PROPERTIES:
+			case MSG_CLOCK_SET_PROPERTIES:
+				if(mixart_msg_data[0])
+					snd_printdd("tasklet : MSG_CLOCK_***_PROPERTIES txx_status(%x) clock_mode(%x)\n", mixart_msg_data[0], mixart_msg_data[1]);
+				break;
+			case MSG_SYSTEM_WAIT_SYNCHRO_CMD:
+				if(mixart_msg_data[0])
+					snd_printdd("tasklet : MSG_SYSTEM_WAIT_SYNCHRO_CMD txx_status(%x)\n", mixart_msg_data[0]);
+				break;
+			default:
+				snd_printdd("tasklet received mf(%x) : msg_id(%x) uid(%x, %x) size(%d)\n",
+					   msg, resp.message_id, resp.uid.object_id, resp.uid.desc, resp.size);
+				break;
+			}
+			break;
+		case MSG_TYPE_NOTIFY:
+			/* msg contains no address ! do not get_msg() ! */
+		case MSG_TYPE_COMMAND:
+			/* get_msg() necessary */
+		default:
+			snd_printk(KERN_ERR "tasklet doesn't know what to do with message %x\n", msg);
+		} /* switch type */
+	} /* while there is a msg in fifo */
+
+	spin_unlock(&mgr->lock);
+}
+
+
+irqreturn_t snd_mixart_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+	mixart_mgr_t *mgr = snd_magic_cast(mixart_mgr_t, dev_id, return IRQ_NONE);
+	int err;
+	mixart_msg_t resp;
+
+	u32 msg;
+	u32 it_reg;
+
+	spin_lock(&mgr->lock);
+
+	it_reg = readl_le(MIXART_REG(mgr, MIXART_PCI_OMISR_OFFSET));
+	if( !(it_reg & MIXART_OIDI) ) {
+		/* this device did not cause the interrupt */
+		spin_unlock(&mgr->lock);
+		return IRQ_NONE;
+	}
+
+	/* mask all interrupts */
+	writel_le(MIXART_HOST_ALL_INTERRUPT_MASKED, MIXART_REG(mgr, MIXART_PCI_OMIMR_OFFSET));
+
+	/* outdoorbell register clear */
+	it_reg = readl(MIXART_REG(mgr, MIXART_PCI_ODBR_OFFSET));
+	writel(it_reg, MIXART_REG(mgr, MIXART_PCI_ODBR_OFFSET));
+
+	/* clear interrupt */
+	writel_le( MIXART_OIDI, MIXART_REG(mgr, MIXART_PCI_OMISR_OFFSET) );
+
+	/* process interrupt */
+	while (retrieve_msg_frame(mgr, &msg)) {
+
+		switch (msg & MSG_TYPE_MASK) {
+		case MSG_TYPE_COMMAND:
+			resp.message_id = 0;
+			resp.data = mixart_msg_data;
+			resp.size = sizeof(mixart_msg_data);
+			err = get_msg(mgr, &resp, msg & ~MSG_TYPE_MASK);
+			if( err < 0 ) {
+				snd_printk(KERN_ERR "interrupt: error(%d) reading mf %x\n", err, msg);
+				break;
+			}
+
+			if(resp.message_id == MSG_SERVICES_TIMER_NOTIFY) {
+				int i;
+				mixart_timer_notify_t *notify = (mixart_timer_notify_t*)mixart_msg_data;
+
+				for(i=0; i<notify->stream_count; i++) {
+
+					u32 buffer_id = notify->streams[i].buffer_id;
+					unsigned int chip_number =  (buffer_id & MIXART_NOTIFY_CARD_MASK) >> MIXART_NOTIFY_CARD_OFFSET; /* card0 to 3 */
+					unsigned int pcm_number  =  (buffer_id & MIXART_NOTIFY_PCM_MASK ) >> MIXART_NOTIFY_PCM_OFFSET;  /* pcm0 to 3  */
+					unsigned int sub_number  =   buffer_id & MIXART_NOTIFY_SUBS_MASK;             /* 0 to MIXART_PLAYBACK_STREAMS */
+					unsigned int is_capture  = ((buffer_id & MIXART_NOTIFY_CAPT_MASK) != 0);      /* playback == 0 / capture == 1 */
+
+					mixart_t *chip  = mgr->chip[chip_number];
+					mixart_stream_t *stream;
+
+					if ((chip_number >= mgr->num_cards) || (pcm_number >= MIXART_PCM_TOTAL) || (sub_number >= MIXART_PLAYBACK_STREAMS)) {
+						snd_printk(KERN_DEBUG "ERROR buffer_id (%x) pos(%d)\n", buffer_id, notify->streams[i].sample_pos_low_part);
+						break;
+					}
+
+					if (is_capture)
+						stream = &chip->capture_stream[pcm_number];
+					else
+						stream = &chip->playback_stream[pcm_number][sub_number];
+
+					if (stream->substream && (stream->status == MIXART_STREAM_STATUS_RUNNING)) {
+						snd_pcm_runtime_t *runtime = stream->substream->runtime;
+						int elapsed = 0;
+						u64 sample_count = ((u64)notify->streams[i].sample_pos_high_part) << 32;
+						sample_count |= notify->streams[i].sample_pos_low_part;
+
+						while (1) {
+							u64 new_elapse_pos = stream->abs_period_elapsed +  runtime->period_size;
+
+							if (new_elapse_pos > sample_count) {
+								break; /* while */
+							}
+							else {
+								elapsed = 1;
+								stream->buf_periods++;
+								if (stream->buf_periods >= runtime->periods)
+									stream->buf_periods = 0;
+
+								stream->abs_period_elapsed = new_elapse_pos;
+							}
+						}
+						stream->buf_period_frag = (u32)( sample_count - stream->abs_period_elapsed );
+
+						if(elapsed) {
+							spin_unlock(&mgr->lock);
+							snd_pcm_period_elapsed(stream->substream);
+							spin_lock(&mgr->lock);
+						}
+					}
+				}
+				break;
+			}
+			if(resp.message_id == MSG_SERVICES_REPORT_TRACES) {
+				if(resp.size > 1) {
+#ifndef __BIG_ENDIAN
+					/* Traces are text: the swapped msg_data has to be swapped back ! */
+					int i;
+					for(i=0; i<(resp.size/4); i++) {
+						(mixart_msg_data)[i] = cpu_to_be32((mixart_msg_data)[i]);
+					}
+#endif
+					((char*)mixart_msg_data)[resp.size - 1] = 0;
+					snd_printdd("MIXART TRACE : %s\n", (char*)mixart_msg_data);
+				}
+				break;
+			}
+
+			snd_printdd("command %x not handled\n", resp.message_id);
+			break;
+
+		case MSG_TYPE_NOTIFY:
+			if(msg & MSG_CANCEL_NOTIFY_MASK) {
+				msg &= ~MSG_CANCEL_NOTIFY_MASK;
+				snd_printk(KERN_ERR "canceled notification %x !\n", msg);
+			}
+			/* no break, continue ! */
+		case MSG_TYPE_ANSWER:
+			/* answer or notification to a message we are waiting for*/
+			if( (msg & ~MSG_TYPE_MASK) == mgr->pending_event ) {
+				wake_up(&mgr->msg_sleep);
+				mgr->pending_event = 0;
+			}
+			/* answer to a message we did't want to wait for */
+			else {
+				mgr->msg_fifo[mgr->msg_fifo_writeptr] = msg;
+				mgr->msg_fifo_writeptr++;
+				mgr->msg_fifo_writeptr %= MSG_FIFO_SIZE;
+				tasklet_hi_schedule(&mgr->msg_taskq);
+			}
+			break;
+		case MSG_TYPE_REQUEST:
+		default:
+			snd_printdd("interrupt received request %x\n", msg);
+			/* TODO : are there things to do here ? */
+			break;
+		} /* switch on msg type */
+	} /* while there are msgs */
+
+	/* allow interrupt again */
+	writel_le( MIXART_ALLOW_OUTBOUND_DOORBELL, MIXART_REG( mgr, MIXART_PCI_OMIMR_OFFSET));
+
+	spin_unlock(&mgr->lock);
+
+	return IRQ_HANDLED;
+}
+
+
+void snd_mixart_init_mailbox(mixart_mgr_t *mgr)
+{
+	writel( 0, MIXART_MEM( mgr, MSG_HOST_RSC_PROTECTION ) );
+	writel( 0, MIXART_MEM( mgr, MSG_AGENT_RSC_PROTECTION ) );
+
+	/* allow outbound messagebox to generate interrupts */
+	if(mgr->irq >= 0) {
+		writel_le( MIXART_ALLOW_OUTBOUND_DOORBELL, MIXART_REG( mgr, MIXART_PCI_OMIMR_OFFSET));
+	}
+	return;
+}
+
+void snd_mixart_exit_mailbox(mixart_mgr_t *mgr)
+{
+	/* no more interrupts on outbound messagebox */
+	writel_le( MIXART_HOST_ALL_INTERRUPT_MASKED, MIXART_REG( mgr, MIXART_PCI_OMIMR_OFFSET));
+	return;
+}
+
+void snd_mixart_reset_board(mixart_mgr_t *mgr)
+{
+	/* reset miXart */
+	writel_be( 1, MIXART_REG(mgr, MIXART_BA1_BRUTAL_RESET_OFFSET) );
+	return;
+}
--- diff/sound/pci/mixart/mixart_core.h	1970-01-01 01:00:00.000000000 +0100
+++ source/sound/pci/mixart/mixart_core.h	2004-02-23 13:56:48.000000000 +0000
@@ -0,0 +1,607 @@
+/*
+ * Driver for Digigram miXart soundcards
+ *
+ * low level interface with interrupt handling and mail box implementation
+ *
+ * Copyright (c) 2003 by Digigram <alsa@digigram.com>
+ *
+ *   This program is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License as published by
+ *   the Free Software Foundation; either version 2 of the License, or
+ *   (at your option) any later version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ */
+
+#ifndef __SOUND_MIXART_CORE_H
+#define __SOUND_MIXART_CORE_H
+
+
+enum mixart_message_id {
+	MSG_CONNECTOR_GET_AUDIO_INFO         = 0x050008,
+	MSG_CONNECTOR_GET_OUT_AUDIO_LEVEL    = 0x050009,
+	MSG_CONNECTOR_SET_OUT_AUDIO_LEVEL    = 0x05000A,
+
+	MSG_CONSOLE_MANAGER                  = 0x070000,
+	MSG_CONSOLE_GET_CLOCK_UID            = 0x070003,
+
+	MSG_PHYSICALIO_SET_LEVEL             = 0x0F0008,
+
+	MSG_STREAM_ADD_INPUT_GROUP           = 0x130000,
+	MSG_STREAM_ADD_OUTPUT_GROUP          = 0x130001,
+	MSG_STREAM_DELETE_GROUP              = 0x130004,
+	MSG_STREAM_START_STREAM_GRP_PACKET   = 0x130006,
+	MSG_STREAM_START_INPUT_STAGE_PACKET  = 0x130007,
+	MSG_STREAM_START_OUTPUT_STAGE_PACKET = 0x130008,
+	MSG_STREAM_STOP_STREAM_GRP_PACKET    = 0x130009,
+	MSG_STREAM_STOP_INPUT_STAGE_PACKET   = 0x13000A,
+	MSG_STREAM_STOP_OUTPUT_STAGE_PACKET  = 0x13000B,
+	MSG_STREAM_SET_INPUT_STAGE_PARAM     = 0x13000F,
+	MSG_STREAM_SET_OUTPUT_STAGE_PARAM    = 0x130010,
+	MSG_STREAM_SET_IN_AUDIO_LEVEL        = 0x130015,
+	MSG_STREAM_SET_OUT_STREAM_LEVEL      = 0x130017,
+
+	MSG_SYSTEM_FIRST_ID                  = 0x160000,
+	MSG_SYSTEM_ENUM_PHYSICAL_IO          = 0x16000E,
+	MSG_SYSTEM_ENUM_PLAY_CONNECTOR       = 0x160017,
+	MSG_SYSTEM_ENUM_RECORD_CONNECTOR     = 0x160018,
+	MSG_SYSTEM_WAIT_SYNCHRO_CMD          = 0x16002C,
+	MSG_SYSTEM_SEND_SYNCHRO_CMD          = 0x16002D,
+
+	MSG_SERVICES_TIMER_NOTIFY            = 0x1D0404,
+	MSG_SERVICES_REPORT_TRACES           = 0x1D0700,
+
+	MSG_CLOCK_CHECK_PROPERTIES           = 0x200001,
+	MSG_CLOCK_SET_PROPERTIES             = 0x200002,
+};
+
+
+typedef struct mixart_msg mixart_msg_t;
+struct mixart_msg
+{
+	u32          message_id;
+	mixart_uid_t uid;
+	void*        data;
+	size_t       size;
+};
+
+/* structs used to communicate with miXart */
+
+typedef struct mixart_enum_connector_resp mixart_enum_connector_resp_t;
+struct mixart_enum_connector_resp
+{
+	u32  error_code;
+	u32  first_uid_offset;
+	u32  uid_count;
+	u32  current_uid_index;
+	mixart_uid_t uid[MIXART_MAX_PHYS_CONNECTORS];
+} __attribute__((packed));
+
+
+/* used for following struct */
+#define MIXART_FLOAT_P_22_0_TO_HEX      0x41b00000  /* 22.0f */
+#define MIXART_FLOAT_M_20_0_TO_HEX      0xc1a00000  /* -20.0f */
+#define MIXART_FLOAT____0_0_TO_HEX      0x00000000  /* 0.0f */
+
+typedef struct mixart_audio_info_req mixart_audio_info_req_t;
+struct mixart_audio_info_req
+{
+	u32 line_max_level;    /* float */
+	u32 micro_max_level;   /* float */
+	u32 cd_max_level;      /* float */
+} __attribute__((packed));
+
+typedef struct mixart_analog_hw_info mixart_analog_hw_info_t;
+struct mixart_analog_hw_info
+{
+	u32 is_present;
+	u32 hw_connection_type;
+	u32 max_level;         /* float */
+	u32 min_var_level;     /* float */
+	u32 max_var_level;     /* float */
+	u32 step_var_level;    /* float */
+	u32 fix_gain;          /* float */
+	u32 zero_var;          /* float */
+} __attribute__((packed));
+
+typedef struct mixart_digital_hw_info mixart_digital_hw_info_t;
+struct mixart_digital_hw_info
+{
+	u32   hw_connection_type;
+	u32   presence;
+	u32   clock;
+	u32   reserved;
+} __attribute__((packed));
+
+typedef struct mixart_analog_info mixart_analog_info_t;
+struct mixart_analog_info
+{
+	u32                     type_mask;
+	mixart_analog_hw_info_t micro_info;
+	mixart_analog_hw_info_t line_info;
+	mixart_analog_hw_info_t cd_info;
+	u32                     analog_level_present;
+} __attribute__((packed));
+
+typedef struct mixart_digital_info mixart_digital_info_t;
+struct mixart_digital_info
+{
+	u32 type_mask;
+	mixart_digital_hw_info_t aes_info;
+	mixart_digital_hw_info_t adat_info;
+} __attribute__((packed));
+
+typedef struct mixart_audio_info mixart_audio_info_t;
+struct mixart_audio_info
+{
+	u32                   clock_type_mask;
+	mixart_analog_info_t  analog_info;
+	mixart_digital_info_t digital_info;
+} __attribute__((packed));
+
+typedef struct mixart_audio_info_resp mixart_audio_info_resp_t;
+struct mixart_audio_info_resp
+{
+	u32                 txx_status;
+	mixart_audio_info_t info;
+} __attribute__((packed));
+
+
+/* used for nb_bytes_max_per_sample */
+#define MIXART_FLOAT_P__4_0_TO_HEX      0x40800000  /* +4.0f */
+#define MIXART_FLOAT_P__8_0_TO_HEX      0x41000000  /* +8.0f */
+
+typedef struct mixart_stream_info mixart_stream_info_t;
+struct mixart_stream_info
+{
+	u32 size_max_byte_frame;
+	u32 size_max_sample_frame;
+	u32 nb_bytes_max_per_sample;  /* float */
+} __attribute__((packed));
+
+/*  MSG_STREAM_ADD_INPUT_GROUP */
+/*  MSG_STREAM_ADD_OUTPUT_GROUP */
+
+typedef struct mixart_streaming_group_req mixart_streaming_group_req_t;
+struct mixart_streaming_group_req
+{
+	u32 stream_count;
+	u32 channel_count;
+	u32 user_grp_number;
+	u32 first_phys_audio;
+	u32 latency;
+	mixart_stream_info_t stream_info[32];
+	mixart_uid_t connector;
+	u32 flow_entry[32];
+} __attribute__((packed));
+
+typedef struct mixart_stream_desc mixart_stream_desc_t;
+struct mixart_stream_desc
+{
+	mixart_uid_t stream_uid;
+	u32          stream_desc;
+} __attribute__((packed));
+
+typedef struct mixart_streaming_group mixart_streaming_group_t;
+struct mixart_streaming_group
+{
+	u32                  status;
+	mixart_uid_t         group;
+	u32                  pipe_desc;
+	u32                  stream_count;
+	mixart_stream_desc_t stream[32];
+} __attribute__((packed));
+
+/* MSG_STREAM_DELETE_GROUP */
+
+/* request : mixart_uid_t group */
+
+typedef struct mixart_delete_group_resp mixart_delete_group_resp_t;
+struct mixart_delete_group_resp
+{
+	u32  status;
+	u32  unused[2];
+} __attribute__((packed));
+
+
+/* 	MSG_STREAM_START_INPUT_STAGE_PACKET  = 0x130000 + 7,
+	MSG_STREAM_START_OUTPUT_STAGE_PACKET = 0x130000 + 8,
+	MSG_STREAM_STOP_INPUT_STAGE_PACKET   = 0x130000 + 10,
+	MSG_STREAM_STOP_OUTPUT_STAGE_PACKET  = 0x130000 + 11,
+ */
+
+typedef struct mixart_fx_couple_uid mixart_fx_couple_uid_t;
+struct mixart_fx_couple_uid
+{
+	mixart_uid_t uid_fx_code;
+	mixart_uid_t uid_fx_data;
+} __attribute__((packed));
+
+typedef struct mixart_txx_stream_desc mixart_txx_stream_desc_t;
+struct mixart_txx_stream_desc
+{
+	mixart_uid_t            uid_pipe;
+	u32                     stream_idx;
+	u32                     fx_number;
+	mixart_fx_couple_uid_t  uid_fx[4];
+} __attribute__((packed));
+
+typedef struct mixart_flow_info mixart_flow_info_t;
+struct mixart_flow_info
+{
+	mixart_txx_stream_desc_t  stream_desc;
+	u32                       flow_entry;
+	u32                       flow_phy_addr;
+} __attribute__((packed));
+
+typedef struct mixart_stream_state_req mixart_stream_state_req_t;
+struct mixart_stream_state_req
+{
+	u32                 delayed;
+	u64                 scheduler;
+	u32                 reserved4np[3];
+	u32                 stream_count;  /* set to 1 for instance */
+	mixart_flow_info_t  stream_info;   /* could be an array[stream_count] */
+} __attribute__((packed));
+
+/* 	MSG_STREAM_START_STREAM_GRP_PACKET   = 0x130000 + 6
+	MSG_STREAM_STOP_STREAM_GRP_PACKET    = 0x130000 + 9
+ */
+
+typedef struct mixart_group_state_req mixart_group_state_req_t;
+struct mixart_group_state_req
+{
+	u32           delayed;
+	u64           scheduler;
+	u32           reserved4np[2];
+	u32           pipe_count;    /* set to 1 for instance */
+	mixart_uid_t  pipe_uid[1];   /* could be an array[pipe_count] */
+} __attribute__((packed));
+
+typedef struct mixart_group_state_resp mixart_group_state_resp_t;
+struct mixart_group_state_resp
+{
+	u32           txx_status;
+	u64           scheduler;
+} __attribute__((packed));
+
+
+
+/* Structures used by the MSG_SERVICES_TIMER_NOTIFY command */
+
+typedef struct mixart_sample_pos mixart_sample_pos_t;
+struct mixart_sample_pos
+{
+	u32   buffer_id;
+	u32   validity;
+	u32   sample_pos_high_part;
+	u32   sample_pos_low_part;
+} __attribute__((packed));
+
+typedef struct mixart_timer_notify mixart_timer_notify_t;
+struct mixart_timer_notify
+{
+	u32                  stream_count;
+	mixart_sample_pos_t  streams[MIXART_MAX_STREAM_PER_CARD * MIXART_MAX_CARDS];
+} __attribute__((packed));
+
+
+/*	MSG_CONSOLE_GET_CLOCK_UID            = 0x070003,
+ */
+
+/* request is a uid with desc = MSG_CONSOLE_MANAGER | cardindex */
+
+typedef struct mixart_return_uid mixart_return_uid_t;
+struct mixart_return_uid
+{
+	u32 error_code;
+	mixart_uid_t uid;
+} __attribute__((packed));
+
+/*	MSG_CLOCK_CHECK_PROPERTIES           = 0x200001,
+	MSG_CLOCK_SET_PROPERTIES             = 0x200002,
+*/
+
+enum mixart_clock_generic_type {
+	CGT_NO_CLOCK,
+	CGT_INTERNAL_CLOCK,
+	CGT_PROGRAMMABLE_CLOCK,
+	CGT_INTERNAL_ENSLAVED_CLOCK,
+	CGT_EXTERNAL_CLOCK,
+	CGT_CURRENT_CLOCK
+};
+
+enum mixart_clock_mode {
+	CM_UNDEFINED,
+	CM_MASTER,
+	CM_SLAVE,
+	CM_STANDALONE,
+	CM_NOT_CONCERNED
+};
+
+
+typedef struct mixart_clock_properties mixart_clock_properties_t;
+struct mixart_clock_properties
+{
+	u32 error_code;
+	u32 validation_mask;
+	u32 frequency;
+	u32 reference_frequency;
+	u32 clock_generic_type;
+	u32 clock_mode;
+	mixart_uid_t uid_clock_source;
+	mixart_uid_t uid_event_source;
+	u32 event_mode;
+	u32 synchro_signal_presence;
+	u32 format;
+	u32 board_mask;
+	u32 nb_callers; /* set to 1 (see below) */
+	mixart_uid_t uid_caller[1];
+} __attribute__((packed));
+
+typedef struct mixart_clock_properties_resp mixart_clock_properties_resp_t;
+struct mixart_clock_properties_resp
+{
+	u32 status;
+	u32 clock_mode;
+} __attribute__((packed));
+
+
+/*	MSG_STREAM_SET_INPUT_STAGE_PARAM     = 0x13000F */
+/*	MSG_STREAM_SET_OUTPUT_STAGE_PARAM    = 0x130010 */
+
+enum mixart_coding_type {
+	CT_NOT_DEFINED,
+	CT_LINEAR,
+	CT_MPEG_L1,
+	CT_MPEG_L2,
+	CT_MPEG_L3,
+	CT_MPEG_L3_LSF,
+	CT_GSM
+};
+enum mixart_sample_type {
+	ST_NOT_DEFINED,
+	ST_FLOATING_POINT_32BE,
+	ST_FLOATING_POINT_32LE,
+	ST_FLOATING_POINT_64BE,
+	ST_FLOATING_POINT_64LE,
+	ST_FIXED_POINT_8,
+	ST_FIXED_POINT_16BE,
+	ST_FIXED_POINT_16LE,
+	ST_FIXED_POINT_24BE,
+	ST_FIXED_POINT_24LE,
+	ST_FIXED_POINT_32BE,
+	ST_FIXED_POINT_32LE,
+	ST_INTEGER_8,
+	ST_INTEGER_16BE,
+	ST_INTEGER_16LE,
+	ST_INTEGER_24BE,
+	ST_INTEGER_24LE,
+	ST_INTEGER_32BE,
+	ST_INTEGER_32LE
+};
+
+typedef struct mixart_stream_param_desc mixart_stream_param_desc_t;
+struct mixart_stream_param_desc
+{
+	u32 coding_type;  /* use enum mixart_coding_type */
+	u32 sample_type;  /* use enum mixart_sample_type */
+
+	union {
+		struct {
+			u32 linear_endian_ness;
+			u32 linear_bits;
+			u32 is_signed;
+			u32 is_float;
+		} linear_format_info;
+
+		struct {
+			u32 mpeg_layer;
+			u32 mpeg_mode;
+			u32 mpeg_mode_extension;
+			u32 mpeg_pre_emphasis;
+			u32 mpeg_has_padding_bit;
+			u32 mpeg_has_crc;
+			u32 mpeg_has_extension;
+			u32 mpeg_is_original;
+			u32 mpeg_has_copyright;
+		} mpeg_format_info;
+	} format_info;
+
+	u32 delayed;
+	u64 scheduler;
+	u32 sample_size;
+	u32 has_header;
+	u32 has_suffix;
+	u32 has_bitrate;
+	u32 samples_per_frame;
+	u32 bytes_per_frame;
+	u32 bytes_per_sample;
+	u32 sampling_freq;
+	u32 number_of_channel;
+	u32 stream_number;
+	u32 buffer_size;
+	u32 differed_time;
+	u32 reserved4np[3];
+	u32 pipe_count;                           /* set to 1 (array size !) */
+	u32 stream_count;                         /* set to 1 (array size !) */
+	mixart_txx_stream_desc_t stream_desc[1];  /* only one stream per command, but this could be an array */
+
+} __attribute__((packed));
+
+
+/*	MSG_CONNECTOR_GET_OUT_AUDIO_LEVEL    = 0x050009,
+ */
+
+
+typedef struct mixart_get_out_audio_level mixart_get_out_audio_level_t;
+struct mixart_get_out_audio_level
+{
+	u32 txx_status;
+	u32 digital_level;   /* float */
+	u32 analog_level;    /* float */
+	u32 monitor_level;   /* float */
+	u32 mute;
+	u32 monitor_mute1;
+	u32 monitor_mute2;
+} __attribute__((packed));
+
+
+/*	MSG_CONNECTOR_SET_OUT_AUDIO_LEVEL    = 0x05000A,
+ */
+
+/* used for valid_mask below */
+#define MIXART_AUDIO_LEVEL_ANALOG_MASK	0x01
+#define MIXART_AUDIO_LEVEL_DIGITAL_MASK	0x02
+#define MIXART_AUDIO_LEVEL_MONITOR_MASK	0x04
+#define MIXART_AUDIO_LEVEL_MUTE_MASK	0x08
+#define MIXART_AUDIO_LEVEL_MUTE_M1_MASK	0x10
+#define MIXART_AUDIO_LEVEL_MUTE_M2_MASK	0x20
+
+typedef struct mixart_set_out_audio_level mixart_set_out_audio_level_t;
+struct mixart_set_out_audio_level
+{
+	u32 delayed;
+	u64 scheduler;
+	u32 valid_mask1;
+	u32 valid_mask2;
+	u32 digital_level;   /* float */
+	u32 analog_level;    /* float */
+	u32 monitor_level;   /* float */
+	u32 mute;
+	u32 monitor_mute1;
+	u32 monitor_mute2;
+	u32 reserved4np;
+} __attribute__((packed));
+
+
+/*	MSG_SYSTEM_ENUM_PHYSICAL_IO          = 0x16000E,
+ */
+
+#define MIXART_MAX_PHYS_IO  (MIXART_MAX_CARDS * 2 * 2) /* 4 * (analog+digital) * (playback+capture) */
+
+typedef struct mixart_uid_enumeration mixart_uid_enumeration_t;
+struct mixart_uid_enumeration
+{
+	u32 error_code;
+	u32 first_uid_offset;
+	u32 nb_uid;
+	u32 current_uid_index;
+	mixart_uid_t uid[MIXART_MAX_PHYS_IO];
+} __attribute__((packed));
+
+
+/*	MSG_PHYSICALIO_SET_LEVEL             = 0x0F0008,
+	MSG_PHYSICALIO_GET_LEVEL             = 0x0F000C,
+*/
+
+typedef struct mixart_io_channel_level mixart_io_channel_level_t;
+struct mixart_io_channel_level
+{
+	u32 analog_level;   /* float */
+	u32 unused[2];
+} __attribute__((packed));
+
+typedef struct mixart_io_level mixart_io_level_t;
+struct mixart_io_level
+{
+	s32 channel; /* 0=left, 1=right, -1=both, -2=both same */
+	mixart_io_channel_level_t level[2];
+} __attribute__((packed));
+
+
+/*	MSG_STREAM_SET_IN_AUDIO_LEVEL        = 0x130015,
+ */
+
+typedef struct mixart_in_audio_level_info mixart_in_audio_level_info_t;
+struct mixart_in_audio_level_info
+{
+	mixart_uid_t connector;
+	u32 valid_mask1;
+	u32 valid_mask2;
+	u32 digital_level;
+	u32 analog_level;
+} __attribute__((packed));
+
+typedef struct mixart_set_in_audio_level_req mixart_set_in_audio_level_req_t;
+struct mixart_set_in_audio_level_req
+{
+	u32 delayed;
+	u64 scheduler;
+	u32 audio_count;  /* set to <= 2 */
+	u32 reserved4np;
+	mixart_in_audio_level_info_t level[2];
+} __attribute__((packed));
+
+/* response is a 32 bit status */
+
+
+/*	MSG_STREAM_SET_OUT_STREAM_LEVEL      = 0x130017,
+ */
+
+/* defines used for valid_mask1 */
+#define MIXART_OUT_STREAM_SET_LEVEL_LEFT_AUDIO1		0x01
+#define MIXART_OUT_STREAM_SET_LEVEL_LEFT_AUDIO2		0x02
+#define MIXART_OUT_STREAM_SET_LEVEL_RIGHT_AUDIO1	0x04
+#define MIXART_OUT_STREAM_SET_LEVEL_RIGHT_AUDIO2	0x08
+#define MIXART_OUT_STREAM_SET_LEVEL_STREAM_1		0x10
+#define MIXART_OUT_STREAM_SET_LEVEL_STREAM_2		0x20
+#define MIXART_OUT_STREAM_SET_LEVEL_MUTE_1		0x40
+#define MIXART_OUT_STREAM_SET_LEVEL_MUTE_2		0x80
+
+typedef struct mixart_out_stream_level_info mixart_out_stream_level_info_t;
+struct mixart_out_stream_level_info
+{
+	u32 valid_mask1;
+	u32 valid_mask2;
+	u32 left_to_out1_level;
+	u32 left_to_out2_level;
+	u32 right_to_out1_level;
+	u32 right_to_out2_level;
+	u32 digital_level1;
+	u32 digital_level2;
+	u32 mute1;
+	u32 mute2;
+} __attribute__((packed));
+
+typedef struct mixart_set_out_stream_level mixart_set_out_stream_level_t;
+struct mixart_set_out_stream_level
+{
+	mixart_txx_stream_desc_t desc;
+	mixart_out_stream_level_info_t out_level;
+} __attribute__((packed));
+
+typedef struct mixart_set_out_stream_level_req mixart_set_out_stream_level_req_t;
+struct mixart_set_out_stream_level_req
+{
+	u32 delayed;
+	u64 scheduler;
+	u32 reserved4np[2];
+	u32 nb_of_stream;  /* set to 1 */
+	mixart_set_out_stream_level_t stream_level; /* could be an array */
+} __attribute__((packed));
+
+/* response to this request is a u32 status value */
+
+
+/* exported */
+void snd_mixart_init_mailbox(mixart_mgr_t *mgr);
+void snd_mixart_exit_mailbox(mixart_mgr_t *mgr);
+
+int  snd_mixart_send_msg(mixart_mgr_t *mgr, mixart_msg_t *request, int max_resp_size, void *resp_data);
+int  snd_mixart_send_msg_wait_notif(mixart_mgr_t *mgr, mixart_msg_t *request, u32 notif_event);
+int  snd_mixart_send_msg_nonblock(mixart_mgr_t *mgr, mixart_msg_t *request);
+
+irqreturn_t snd_mixart_interrupt(int irq, void *dev_id, struct pt_regs *regs);
+void snd_mixart_msg_tasklet( unsigned long arg);
+
+void snd_mixart_reset_board(mixart_mgr_t *mgr);
+
+#endif /* __SOUND_MIXART_CORE_H */
--- diff/sound/pci/mixart/mixart_hwdep.c	1970-01-01 01:00:00.000000000 +0100
+++ source/sound/pci/mixart/mixart_hwdep.c	2004-02-23 13:56:48.000000000 +0000
@@ -0,0 +1,570 @@
+/*
+ * Driver for Digigram miXart soundcards
+ *
+ * hwdep device manager
+ *
+ * Copyright (c) 2003 by Digigram <alsa@digigram.com>
+ *
+ *   This program is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License as published by
+ *   the Free Software Foundation; either version 2 of the License, or
+ *   (at your option) any later version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ */
+
+#include <sound/driver.h>
+#include <sound/core.h>
+#include "mixart.h"
+#include "mixart_mixer.h"
+#include "mixart_core.h"
+#include "mixart_hwdep.h"
+
+
+/* miXart hwdep interface id string */
+#define SND_MIXART_HWDEP_ID       "miXart Loader"
+
+static int mixart_hwdep_open(snd_hwdep_t *hw, struct file *file)
+{
+	return 0;
+}
+
+static int mixart_hwdep_release(snd_hwdep_t *hw, struct file *file)
+{
+	return 0;
+}
+
+/**
+ * wait for a value on a peudo register, exit with a timeout
+ *
+ * @param mgr pointer to miXart manager structure
+ * @param offset unsigned pseudo_register base + offset of value
+ * @param value value
+ * @param timeout timeout in centisenconds
+ */
+static int mixart_wait_nice_for_register_value(mixart_mgr_t *mgr, u32 offset, int is_egal, u32 value, unsigned long timeout)
+{
+	unsigned long end_time = jiffies + (timeout * HZ / 100);
+	u32 read;
+
+	do {	/* we may take too long time in this loop.
+		 * so give controls back to kernel if needed.
+		 */
+		cond_resched();
+
+		read = readl_be( MIXART_MEM( mgr, offset ));
+		if(is_egal) {
+			if(read == value) return 0;
+		}
+		else { /* wait for different value */
+			if(read != value) return 0;
+		}
+	} while ( time_after_eq(end_time, jiffies) );
+
+	return -EBUSY;
+}
+
+
+/*
+  structures needed to upload elf code packets 
+ */
+typedef struct snd_mixart_elf32_ehdr snd_mixart_elf32_ehdr_t;
+
+struct snd_mixart_elf32_ehdr {
+	u8      e_ident[16];
+	u16     e_type;
+	u16     e_machine;
+	u32     e_version;
+	u32     e_entry;
+	u32     e_phoff;
+	u32     e_shoff;
+	u32     e_flags;
+	u16     e_ehsize;
+	u16     e_phentsize;
+	u16     e_phnum;
+	u16     e_shentsize;
+	u16     e_shnum;
+	u16     e_shstrndx;
+};
+
+typedef struct snd_mixart_elf32_phdr snd_mixart_elf32_phdr_t;
+
+struct snd_mixart_elf32_phdr {
+	u32     p_type;
+	u32     p_offset;
+	u32     p_vaddr;
+	u32     p_paddr;
+	u32     p_filesz;
+	u32     p_memsz;
+	u32     p_flags;
+	u32     p_align;
+};
+
+static int mixart_load_elf(mixart_mgr_t *mgr, snd_hwdep_dsp_image_t *dsp )
+{
+	char                    elf32_magic_number[4] = {0x7f,'E','L','F'};
+	snd_mixart_elf32_ehdr_t elf_header;
+	int                     i;
+
+	if ( copy_from_user(&elf_header, dsp->image , sizeof(snd_mixart_elf32_ehdr_t)) )
+		return -EFAULT;
+
+	for( i=0; i<4; i++ )
+		if ( elf32_magic_number[i] != elf_header.e_ident[i] )
+			return -EINVAL;
+
+	if( elf_header.e_phoff != 0 ) {
+		snd_mixart_elf32_phdr_t     elf_programheader;
+
+		for( i=0; i < be16_to_cpu(elf_header.e_phnum); i++ ) {
+			u32 pos = be32_to_cpu(elf_header.e_phoff) + (u32)(i * be16_to_cpu(elf_header.e_phentsize));
+
+			if( copy_from_user( &elf_programheader, dsp->image + pos, sizeof(elf_programheader) ) )
+				return -EFAULT;
+
+			if(elf_programheader.p_type != 0) {
+				if( elf_programheader.p_filesz != 0 ) {
+					if(copy_from_user_toio( MIXART_MEM( mgr, be32_to_cpu(elf_programheader.p_vaddr)),
+								dsp->image + be32_to_cpu( elf_programheader.p_offset ),
+								be32_to_cpu( elf_programheader.p_filesz )))
+						return -EFAULT;
+				}
+			}
+		}
+	}
+	return 0;
+}
+
+static int mixart_hwdep_dsp_status(snd_hwdep_t *hw, snd_hwdep_dsp_status_t *info)
+{
+	mixart_mgr_t *mgr = snd_magic_cast(mixart_mgr_t, hw->private_data, return -ENXIO);
+
+	strcpy(info->id, "miXart");
+        info->num_dsps = MIXART_HARDW_FILES_MAX_INDEX;
+
+	if (mgr->hwdep->dsp_loaded & (1 <<  MIXART_MOTHERBOARD_ELF_INDEX))
+		info->chip_ready = 1;
+
+	info->version = MIXART_DRIVER_VERSION;
+	return 0;
+}
+
+/*
+ * get basic information and init miXart
+ */
+
+/* audio IDs for request to the board */
+#define MIXART_FIRST_ANA_AUDIO_ID       0
+#define MIXART_FIRST_DIG_AUDIO_ID       8
+
+static int mixart_enum_connectors(mixart_mgr_t *mgr)
+{
+	u32 k;
+	int err;
+	mixart_msg_t request;
+	mixart_enum_connector_resp_t connector;
+	mixart_audio_info_req_t  audio_info_req;
+	mixart_audio_info_resp_t audio_info;
+
+	audio_info_req.line_max_level = MIXART_FLOAT_P_22_0_TO_HEX;
+	audio_info_req.micro_max_level = MIXART_FLOAT_M_20_0_TO_HEX;
+	audio_info_req.cd_max_level = MIXART_FLOAT____0_0_TO_HEX;
+
+	request.message_id = MSG_SYSTEM_ENUM_PLAY_CONNECTOR;
+	request.uid = (mixart_uid_t){0,0};  /* board num = 0 */
+	request.data = NULL;
+	request.size = 0;
+
+	err = snd_mixart_send_msg(mgr, &request, sizeof(connector), &connector);
+	if((err < 0) || (connector.error_code) || (connector.uid_count > MIXART_MAX_PHYS_CONNECTORS)) {
+		snd_printk(KERN_ERR "error MSG_SYSTEM_ENUM_PLAY_CONNECTOR\n");
+		return -EINVAL;
+	}
+
+	for(k=0; k < connector.uid_count; k++) {
+		mixart_pipe_t* pipe;
+
+		if(k < MIXART_FIRST_DIG_AUDIO_ID) {
+			pipe = &mgr->chip[k/2]->pipe_out_ana;
+		} else {
+			pipe = &mgr->chip[(k-MIXART_FIRST_DIG_AUDIO_ID)/2]->pipe_out_dig;
+		}
+		if(k & 1) {
+			pipe->uid_right_connector = connector.uid[k];   /* odd */
+		} else {
+			pipe->uid_left_connector = connector.uid[k];    /* even */
+		}
+
+		/* snd_printk(KERN_DEBUG "playback connector[%d].object_id = %x\n", k, connector.uid[k].object_id); */
+
+		/* TODO: really need send_msg MSG_CONNECTOR_GET_AUDIO_INFO for each connector ? perhaps for analog level caps ? */
+		request.message_id = MSG_CONNECTOR_GET_AUDIO_INFO;
+		request.uid = connector.uid[k];
+		request.data = &audio_info_req;
+		request.size = sizeof(audio_info_req);
+
+		err = snd_mixart_send_msg(mgr, &request, sizeof(audio_info), &audio_info);
+		if( err < 0 ) {
+			snd_printk(KERN_ERR "error MSG_CONNECTOR_GET_AUDIO_INFO\n");
+			return err;
+		}
+		/*snd_printk(KERN_DEBUG "play  analog_info.analog_level_present = %x\n", audio_info.info.analog_info.analog_level_present);*/
+	}
+
+	request.message_id = MSG_SYSTEM_ENUM_RECORD_CONNECTOR;
+	request.uid = (mixart_uid_t){0,0};  /* board num = 0 */
+	request.data = NULL;
+	request.size = 0;
+
+	err = snd_mixart_send_msg(mgr, &request, sizeof(connector), &connector);
+	if((err < 0) || (connector.error_code) || (connector.uid_count > MIXART_MAX_PHYS_CONNECTORS)) {
+		snd_printk(KERN_ERR "error MSG_SYSTEM_ENUM_RECORD_CONNECTOR\n");
+		return -EINVAL;
+	}
+
+	for(k=0; k < connector.uid_count; k++) {
+		mixart_pipe_t* pipe;
+
+		if(k < MIXART_FIRST_DIG_AUDIO_ID) {
+			pipe = &mgr->chip[k/2]->pipe_in_ana;
+		} else {
+			pipe = &mgr->chip[(k-MIXART_FIRST_DIG_AUDIO_ID)/2]->pipe_in_dig;
+		}
+		if(k & 1) {
+			pipe->uid_right_connector = connector.uid[k];   /* odd */
+		} else {
+			pipe->uid_left_connector = connector.uid[k];    /* even */
+		}
+
+		/* snd_printk(KERN_DEBUG "capture connector[%d].object_id = %x\n", k, connector.uid[k].object_id); */
+
+		/* TODO: really need send_msg MSG_CONNECTOR_GET_AUDIO_INFO for each connector ? perhaps for analog level caps ? */
+		request.message_id = MSG_CONNECTOR_GET_AUDIO_INFO;
+		request.uid = connector.uid[k];
+		request.data = &audio_info_req;
+		request.size = sizeof(audio_info_req);
+
+		err = snd_mixart_send_msg(mgr, &request, sizeof(audio_info), &audio_info);
+		if( err < 0 ) {
+			snd_printk(KERN_ERR "error MSG_CONNECTOR_GET_AUDIO_INFO\n");
+			return err;
+		}
+		/*snd_printk(KERN_DEBUG "rec  analog_info.analog_level_present = %x\n", audio_info.info.analog_info.analog_level_present);*/
+	}
+
+	return 0;
+}
+
+static int mixart_enum_physio(mixart_mgr_t *mgr)
+{
+	u32 k;
+	int err;
+	mixart_msg_t request;
+	mixart_uid_t get_console_mgr;
+	mixart_return_uid_t console_mgr;
+	mixart_uid_enumeration_t phys_io;
+
+	/* get the uid for the console manager */
+	get_console_mgr.object_id = 0;
+	get_console_mgr.desc = MSG_CONSOLE_MANAGER | 0; /* cardindex = 0 */
+
+	request.message_id = MSG_CONSOLE_GET_CLOCK_UID;
+	request.uid = get_console_mgr;
+	request.data = &get_console_mgr;
+	request.size = sizeof(get_console_mgr);
+
+	err = snd_mixart_send_msg(mgr, &request, sizeof(console_mgr), &console_mgr);
+
+	if( (err < 0) || (console_mgr.error_code != 0) ) {
+		snd_printk(KERN_DEBUG "error MSG_CONSOLE_GET_CLOCK_UID : err=%x\n", console_mgr.error_code);
+		return -EINVAL;
+	}
+
+	/* used later for clock issues ! */
+	mgr->uid_console_manager = console_mgr.uid;
+
+	request.message_id = MSG_SYSTEM_ENUM_PHYSICAL_IO;
+	request.uid = (mixart_uid_t){0,0};
+	request.data = &console_mgr.uid;
+	request.size = sizeof(console_mgr.uid);
+
+	err = snd_mixart_send_msg(mgr, &request, sizeof(phys_io), &phys_io);
+	if( (err < 0) || ( phys_io.error_code != 0 ) ) {
+		snd_printk(KERN_ERR "error MSG_SYSTEM_ENUM_PHYSICAL_IO err(%x) error_code(%x)\n", err, phys_io.error_code );
+		return -EINVAL;
+	}
+
+	snd_assert(phys_io.nb_uid >= (MIXART_MAX_CARDS * 2),  return -EINVAL); /* min 2 phys io per card (analog in + analog out) */
+
+	for(k=0; k<mgr->num_cards; k++) {
+		mgr->chip[k]->uid_in_analog_physio = phys_io.uid[k];
+		mgr->chip[k]->uid_out_analog_physio = phys_io.uid[phys_io.nb_uid/2 + k]; 
+	}
+
+	return 0;
+}
+
+
+static int mixart_first_init(mixart_mgr_t *mgr)
+{
+	u32 k;
+	int err;
+	mixart_msg_t request;
+
+	if((err = mixart_enum_connectors(mgr)) < 0) return err;
+
+	if((err = mixart_enum_physio(mgr)) < 0) return err;
+
+	/* send a synchro command to card (necessary to do this before first MSG_STREAM_START_STREAM_GRP_PACKET) */
+	/* though why not here */
+	request.message_id = MSG_SYSTEM_SEND_SYNCHRO_CMD;
+	request.uid = (mixart_uid_t){0,0};
+	request.data = NULL;
+	request.size = 0;
+	/* this command has no data. response is a 32 bit status */
+	err = snd_mixart_send_msg(mgr, &request, sizeof(k), &k);
+	if( (err < 0) || (k != 0) ) {
+		snd_printk(KERN_ERR "error MSG_SYSTEM_SEND_SYNCHRO_CMD\n");
+		return err == 0 ? -EINVAL : err;
+	}
+
+	return 0;
+}
+
+
+/* firmware base addresses (when hard coded) */
+#define MIXART_MOTHERBOARD_XLX_BASE_ADDRESS   0x00600000
+
+static int mixart_hwdep_dsp_load(snd_hwdep_t *hw, snd_hwdep_dsp_image_t *dsp)
+{
+	mixart_mgr_t* mgr = snd_magic_cast(mixart_mgr_t, hw->private_data, return -ENXIO);
+	int           err, card_index;
+	u32           status_xilinx, status_elf, status_daught;
+	u32           val;
+
+	/* read motherboard xilinx status */
+	status_xilinx = readl_be( MIXART_MEM( mgr,MIXART_PSEUDOREG_MXLX_STATUS_OFFSET ));
+	/* read elf status */
+	status_elf = readl_be( MIXART_MEM( mgr,MIXART_PSEUDOREG_ELF_STATUS_OFFSET ));
+	/* read daughterboard xilinx status */
+	status_daught = readl_be( MIXART_MEM( mgr,MIXART_PSEUDOREG_DXLX_STATUS_OFFSET ));
+
+	/* motherboard xilinx status 5 will say that the board is performing a reset */
+	if( status_xilinx == 5 ) {
+		snd_printk( KERN_ERR "miXart is resetting !\n");
+		return -EAGAIN; /* try again later */
+	}
+
+	switch (dsp->index)   {
+	case MIXART_MOTHERBOARD_XLX_INDEX:
+
+		/* xilinx already loaded ? */ 
+		if( status_xilinx == 4 ) {
+			snd_printk( KERN_DEBUG "xilinx is already loaded !\n");
+			return 0;
+		}
+		/* the status should be 0 == "idle" */
+		if( status_xilinx != 0 ) {
+			snd_printk( KERN_ERR "xilinx load error ! status = %d\n", status_xilinx);
+			return -EIO; /* modprob -r may help ? */
+		}
+
+		/* check xilinx validity */
+		snd_assert(((u32*)(dsp->image))[0]==0xFFFFFFFF, return -EINVAL);
+		snd_assert(dsp->length % 4 == 0, return -EINVAL);
+
+		/* set xilinx status to copying */
+		writel_be( 1, MIXART_MEM( mgr, MIXART_PSEUDOREG_MXLX_STATUS_OFFSET ));
+
+		/* setup xilinx base address */
+		writel_be( MIXART_MOTHERBOARD_XLX_BASE_ADDRESS, MIXART_MEM( mgr,MIXART_PSEUDOREG_MXLX_BASE_ADDR_OFFSET ));
+		/* setup code size for xilinx file */
+		writel_be( dsp->length, MIXART_MEM( mgr, MIXART_PSEUDOREG_MXLX_SIZE_OFFSET ));
+
+		/* copy xilinx code */
+		if (copy_from_user_toio(  MIXART_MEM( mgr, MIXART_MOTHERBOARD_XLX_BASE_ADDRESS),  dsp->image,  dsp->length))
+			return -EFAULT;
+    
+		/* set xilinx status to copy finished */
+		writel_be( 2, MIXART_MEM( mgr, MIXART_PSEUDOREG_MXLX_STATUS_OFFSET ));
+
+		/* return, because no further processing needed */
+		return 0;
+
+	case MIXART_MOTHERBOARD_ELF_INDEX:
+
+		if( status_elf == 4 ) {
+			snd_printk( KERN_DEBUG "elf file already loaded !\n");
+			return 0;
+		}
+
+		/* the status should be 0 == "idle" */
+		if( status_elf != 0 ) {
+			snd_printk( KERN_ERR "elf load error ! status = %d\n", status_elf);
+			return -EIO; /* modprob -r may help ? */
+		}
+
+		/* wait for xilinx status == 4 */
+		err = mixart_wait_nice_for_register_value( mgr, MIXART_PSEUDOREG_MXLX_STATUS_OFFSET, 1, 4, 500); /* 5sec */
+		if (err < 0) {
+			snd_printk( KERN_ERR "xilinx was not loaded or could not be started\n");
+			return err;
+		}
+
+		/* init some data on the card */
+		writel_be( 0, MIXART_MEM( mgr, MIXART_PSEUDOREG_BOARDNUMBER ) ); /* set miXart boardnumber to 0 */
+		writel_be( 0, MIXART_MEM( mgr, MIXART_FLOWTABLE_PTR ) );         /* reset pointer to flow table on miXart */
+
+		/* set elf status to copying */
+		writel_be( 1, MIXART_MEM( mgr, MIXART_PSEUDOREG_ELF_STATUS_OFFSET ));
+
+		/* process the copying of the elf packets */
+		err = mixart_load_elf( mgr, dsp);
+		if (err < 0) return err;
+
+		/* set elf status to copy finished */
+		writel_be( 2, MIXART_MEM( mgr, MIXART_PSEUDOREG_ELF_STATUS_OFFSET ));
+
+		/* wait for elf status == 4 */
+		err = mixart_wait_nice_for_register_value( mgr, MIXART_PSEUDOREG_ELF_STATUS_OFFSET, 1, 4, 300); /* 3sec */
+		if (err < 0) {
+			snd_printk( KERN_ERR "elf could not be started\n");
+			return err;
+		}
+
+		/* miXart waits at this point on the pointer to the flow table */
+		writel_be( (u32)mgr->flowinfo_physaddr, MIXART_MEM( mgr, MIXART_FLOWTABLE_PTR ) ); /* give pointer of flow table to miXart */
+
+		return 0;  /* return, another xilinx file has to be loaded before */
+
+	case MIXART_AESEBUBOARD_XLX_INDEX:
+	default:
+
+		/* elf and xilinx should be loaded */
+		if( (status_elf != 4) || (status_xilinx != 4) ) {
+			printk( KERN_ERR "xilinx or elf not successfully loaded\n");
+			return -EIO; /* modprob -r may help ? */
+		}
+
+		/* wait for daughter detection != 0 */
+		err = mixart_wait_nice_for_register_value( mgr, MIXART_PSEUDOREG_DBRD_PRESENCE_OFFSET, 0, 0, 30); /* 300msec */
+		if (err < 0) {
+			snd_printk( KERN_ERR "error starting elf file\n");
+			return err;
+		}
+
+		/* the board type can now be retrieved */
+		mgr->board_type = (DAUGHTER_TYPE_MASK & readl_be( MIXART_MEM( mgr, MIXART_PSEUDOREG_DBRD_TYPE_OFFSET)));
+
+		if (mgr->board_type == MIXART_DAUGHTER_TYPE_NONE)
+			break;  /* no daughter board; the file does not have to be loaded, continue after the switch */
+
+		/* only if aesebu daughter board presence (elf code must run)  */ 
+		if (mgr->board_type != MIXART_DAUGHTER_TYPE_AES )
+			return -EINVAL;
+
+		/* daughter should be idle */
+		if( status_daught != 0 ) {
+			printk( KERN_ERR "daughter load error ! status = %d\n", status_daught);
+			return -EIO; /* modprob -r may help ? */
+		}
+ 
+		/* check daughterboard xilinx validity */
+		snd_assert(((u32*)(dsp->image))[0]==0xFFFFFFFF, return -EINVAL);
+		snd_assert(dsp->length % 4 == 0, return -EINVAL);
+
+		/* inform mixart about the size of the file */
+		writel_be( dsp->length, MIXART_MEM( mgr, MIXART_PSEUDOREG_DXLX_SIZE_OFFSET ));
+
+		/* set daughterboard status to 1 */
+		writel_be( 1, MIXART_MEM( mgr, MIXART_PSEUDOREG_DXLX_STATUS_OFFSET ));
+
+		/* wait for status == 2 */
+		err = mixart_wait_nice_for_register_value( mgr, MIXART_PSEUDOREG_DXLX_STATUS_OFFSET, 1, 2, 30); /* 300msec */
+		if (err < 0) {
+			snd_printk( KERN_ERR "daughter board load error\n");
+			return err;
+		}
+
+		/* get the address where to write the file */
+		val = readl_be( MIXART_MEM( mgr, MIXART_PSEUDOREG_DXLX_BASE_ADDR_OFFSET ));
+		snd_assert(val != 0, return -EINVAL);
+
+		/* copy daughterboard xilinx code */
+		if (copy_from_user_toio(  MIXART_MEM( mgr, val),  dsp->image,  dsp->length))
+			return -EFAULT;
+
+		/* set daughterboard status to 4 */
+		writel_be( 4, MIXART_MEM( mgr, MIXART_PSEUDOREG_DXLX_STATUS_OFFSET ));
+
+		/* continue with init */
+		break;
+	} /* end of switch file index*/
+
+        /* wait for daughter status == 3 */
+        err = mixart_wait_nice_for_register_value( mgr, MIXART_PSEUDOREG_DXLX_STATUS_OFFSET, 1, 3, 300); /* 3sec */
+        if (err < 0) {
+		snd_printk( KERN_ERR "daughter board could not be initialised\n");
+		return err;
+	}
+
+	/* init mailbox (communication with embedded) */
+	snd_mixart_init_mailbox(mgr);
+
+	/* first communication with embedded */
+	err = mixart_first_init(mgr);
+        if (err < 0) {
+		snd_printk( KERN_ERR "miXart could not be set up\n");
+		return err;
+	}
+
+       	/* create devices and mixer in accordance with HW options*/
+        for (card_index = 0; card_index < mgr->num_cards; card_index++) {
+		mixart_t *chip = mgr->chip[card_index];
+
+		if ((err = snd_mixart_create_pcm(chip)) < 0)
+			return err;
+
+		if (card_index == 0) {
+			if ((err = snd_mixart_create_mixer(chip->mgr)) < 0)
+	        		return err;
+		}
+
+		if ((err = snd_card_register(chip->card)) < 0)
+			return err;
+	};
+
+	snd_printdd("miXart firmware downloaded and successfully set up\n");
+
+	return 0;
+}
+
+
+int snd_mixart_hwdep_new(mixart_mgr_t *mgr)
+{
+	int err;
+	snd_hwdep_t *hw;
+
+	/* only create hwdep interface for first cardX (see "index" module parameter)*/
+	if ((err = snd_hwdep_new(mgr->chip[0]->card, SND_MIXART_HWDEP_ID, 0, &hw)) < 0)
+		return err;
+
+	hw->iface = SNDRV_HWDEP_IFACE_MIXART;
+	hw->private_data = mgr;
+	hw->ops.open = mixart_hwdep_open;
+	hw->ops.release = mixart_hwdep_release;
+	hw->ops.dsp_status = mixart_hwdep_dsp_status;
+	hw->ops.dsp_load = mixart_hwdep_dsp_load;
+	hw->exclusive = 1;
+	sprintf(hw->name,  SND_MIXART_HWDEP_ID);
+	mgr->hwdep = hw;
+	mgr->hwdep->dsp_loaded = 0;
+	return 0;
+}
--- diff/sound/pci/mixart/mixart_hwdep.h	1970-01-01 01:00:00.000000000 +0100
+++ source/sound/pci/mixart/mixart_hwdep.h	2004-02-23 13:56:48.000000000 +0000
@@ -0,0 +1,146 @@
+/*
+ * Driver for Digigram miXart soundcards
+ *
+ * definitions and makros for basic card access
+ *
+ * Copyright (c) 2003 by Digigram <alsa@digigram.com>
+ *
+ *   This program is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License as published by
+ *   the Free Software Foundation; either version 2 of the License, or
+ *   (at your option) any later version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ */
+
+#ifndef __SOUND_MIXART_HWDEP_H
+#define __SOUND_MIXART_HWDEP_H
+
+#include <sound/hwdep.h>
+
+#define readl_be(x) be32_to_cpu(__raw_readl(x))
+#define writel_be(data,addr) __raw_writel(cpu_to_be32(data),addr)
+
+#define readl_le(x) le32_to_cpu(__raw_readl(x))
+#define writel_le(data,addr) __raw_writel(cpu_to_le32(data),addr)
+
+#define MIXART_MEM(mgr,x)	((mgr)->mem[0].virt + (x))
+#define MIXART_REG(mgr,x)	((mgr)->mem[1].virt + (x))
+
+
+/* Daughter board Type */
+#define DAUGHTER_TYPE_MASK     0x0F 
+#define DAUGHTER_VER_MASK      0xF0 
+#define DAUGHTER_TYPEVER_MASK  (DAUGHTER_TYPE_MASK|DAUGHTER_VER_MASK)
+ 
+#define MIXART_DAUGHTER_TYPE_NONE     0x00 
+#define MIXART_DAUGHTER_TYPE_COBRANET 0x08 
+#define MIXART_DAUGHTER_TYPE_AES      0x0E
+
+
+
+#define MIXART_BA0_SIZE 	(16 * 1024 * 1024) /* 16M */
+#define MIXART_BA1_SIZE 	(4  * 1024)        /* 4k */
+
+/*
+ * -----------BAR 0 --------------------------------------------------------------------------------------------------------
+ */
+#define  MIXART_PSEUDOREG                          0x2000                    /* base address for pseudoregister */
+
+#define  MIXART_PSEUDOREG_BOARDNUMBER              MIXART_PSEUDOREG+0        /* board number */
+
+/* perfmeter (available when elf loaded)*/
+#define  MIXART_PSEUDOREG_PERF_STREAM_LOAD_OFFSET  MIXART_PSEUDOREG+0x70     /* streaming load */
+#define  MIXART_PSEUDOREG_PERF_SYSTEM_LOAD_OFFSET  MIXART_PSEUDOREG+0x78     /* system load (reference)*/
+#define  MIXART_PSEUDOREG_PERF_MAILBX_LOAD_OFFSET  MIXART_PSEUDOREG+0x7C     /* mailbox load */
+#define  MIXART_PSEUDOREG_PERF_INTERR_LOAD_OFFSET  MIXART_PSEUDOREG+0x74     /* interrupt handling  load */
+
+/* motherboard xilinx loader info */
+#define  MIXART_PSEUDOREG_MXLX_BASE_ADDR_OFFSET    MIXART_PSEUDOREG+0x9C     /* 0x00600000 */ 
+#define  MIXART_PSEUDOREG_MXLX_SIZE_OFFSET         MIXART_PSEUDOREG+0xA0     /* xilinx size in bytes */ 
+#define  MIXART_PSEUDOREG_MXLX_STATUS_OFFSET       MIXART_PSEUDOREG+0xA4     /* status = EMBEBBED_STAT_XXX */ 
+
+/* elf loader info */
+#define  MIXART_PSEUDOREG_ELF_STATUS_OFFSET        MIXART_PSEUDOREG+0xB0     /* status = EMBEBBED_STAT_XXX */ 
+
+/* 
+*  after the elf code is loaded, and the flowtable info was passed to it,
+*  the driver polls on this address, until it shows 1 (presence) or 2 (absence)
+*  once it is non-zero, the daughter board type may be read
+*/
+#define  MIXART_PSEUDOREG_DBRD_PRESENCE_OFFSET     MIXART_PSEUDOREG+0x990   
+
+/* Global info structure */
+#define  MIXART_PSEUDOREG_DBRD_TYPE_OFFSET         MIXART_PSEUDOREG+0x994    /* Type and version of daughterboard  */
+
+
+/* daughterboard xilinx loader info */
+#define  MIXART_PSEUDOREG_DXLX_BASE_ADDR_OFFSET    MIXART_PSEUDOREG+0x998    /* get the address here where to write the file */ 
+#define  MIXART_PSEUDOREG_DXLX_SIZE_OFFSET         MIXART_PSEUDOREG+0x99C    /* xilinx size in bytes */ 
+#define  MIXART_PSEUDOREG_DXLX_STATUS_OFFSET       MIXART_PSEUDOREG+0x9A0    /* status = EMBEBBED_STAT_XXX */ 
+
+/*  */
+#define  MIXART_FLOWTABLE_PTR                      0x3000                    /* pointer to flow table */
+
+/* mailbox addresses  */
+
+/* message DRV -> EMB */
+#define MSG_INBOUND_POST_HEAD       0x010008	/* DRV posts MF + increment4 */
+#define	MSG_INBOUND_POST_TAIL       0x01000C	/* EMB gets MF + increment4 */
+/* message EMB -> DRV */
+#define	MSG_OUTBOUND_POST_TAIL      0x01001C	/* DRV gets MF + increment4 */
+#define	MSG_OUTBOUND_POST_HEAD      0x010018	/* EMB posts MF + increment4 */
+/* Get Free Frames */
+#define MSG_INBOUND_FREE_TAIL       0x010004	/* DRV gets MFA + increment4 */
+#define MSG_OUTBOUND_FREE_TAIL      0x010014	/* EMB gets MFA + increment4 */
+/* Put Free Frames */
+#define MSG_OUTBOUND_FREE_HEAD      0x010010	/* DRV puts MFA + increment4 */
+#define MSG_INBOUND_FREE_HEAD       0x010000    /* EMB puts MFA + increment4 */
+
+/* firmware addresses of the message fifos */
+#define MSG_BOUND_STACK_SIZE        0x004000    /* size of each following stack */
+/* posted messages */
+#define MSG_OUTBOUND_POST_STACK     0x108000    /* stack of messages to the DRV */
+#define MSG_INBOUND_POST_STACK      0x104000    /* stack of messages to the EMB */
+/* available empty messages */
+#define MSG_OUTBOUND_FREE_STACK     0x10C000    /* stack of free enveloped for EMB */
+#define MSG_INBOUND_FREE_STACK      0x100000    /* stack of free enveloped for DRV */
+
+
+/* defines for mailbox message frames */
+#define MSG_FRAME_OFFSET            0x64
+#define MSG_FRAME_SIZE              0x6400
+#define MSG_FRAME_NUMBER            32
+#define MSG_FROM_AGENT_ITMF_OFFSET  (MSG_FRAME_OFFSET + (MSG_FRAME_SIZE * MSG_FRAME_NUMBER))
+#define MSG_TO_AGENT_ITMF_OFFSET    (MSG_FROM_AGENT_ITMF_OFFSET + MSG_FRAME_SIZE)
+#define MSG_HOST_RSC_PROTECTION     (MSG_TO_AGENT_ITMF_OFFSET + MSG_FRAME_SIZE)
+#define MSG_AGENT_RSC_PROTECTION    (MSG_HOST_RSC_PROTECTION + 4)
+
+
+/*
+ * -----------BAR 1 --------------------------------------------------------------------------------------------------------
+ */
+
+/* interrupt addresses and constants */
+#define MIXART_PCI_OMIMR_OFFSET                 0x34    /* outbound message interrupt mask register */
+#define MIXART_PCI_OMISR_OFFSET                 0x30    /* outbound message interrupt status register */
+#define MIXART_PCI_ODBR_OFFSET                  0x60    /* outbound doorbell register */
+
+#define MIXART_BA1_BRUTAL_RESET_OFFSET          0x68    /* write 1 in LSBit to reset board */
+
+#define MIXART_HOST_ALL_INTERRUPT_MASKED        0x02B   /* 0000 0010 1011 */
+#define MIXART_ALLOW_OUTBOUND_DOORBELL          0x023   /* 0000 0010 0011 */
+#define MIXART_OIDI                             0x008   /* 0000 0000 1000 */
+
+
+/* exported */
+int snd_mixart_hwdep_new(mixart_mgr_t *mgr);
+
+#endif /* __SOUND_MIXART_HWDEP_H */
--- diff/sound/pci/mixart/mixart_mixer.c	1970-01-01 01:00:00.000000000 +0100
+++ source/sound/pci/mixart/mixart_mixer.c	2004-02-23 13:56:48.000000000 +0000
@@ -0,0 +1,1137 @@
+/*
+ * Driver for Digigram miXart soundcards
+ *
+ * mixer callbacks
+ *
+ * Copyright (c) 2003 by Digigram <alsa@digigram.com>
+ *
+ *   This program is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License as published by
+ *   the Free Software Foundation; either version 2 of the License, or
+ *   (at your option) any later version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ */
+
+#include <sound/driver.h>
+#include <linux/time.h>
+#include <linux/init.h>
+#include <sound/core.h>
+#include "mixart.h"
+#include "mixart_core.h"
+#include "mixart_hwdep.h"
+#include <sound/control.h>
+#include "mixart_mixer.h"
+
+#define chip_t mixart_t
+
+static u32 mixart_analog_level[256] = {
+	0xc2c00000,		/* [000] -96.0 dB */
+	0xc2bf0000,		/* [001] -95.5 dB */
+	0xc2be0000,		/* [002] -95.0 dB */
+	0xc2bd0000,		/* [003] -94.5 dB */
+	0xc2bc0000,		/* [004] -94.0 dB */
+	0xc2bb0000,		/* [005] -93.5 dB */
+	0xc2ba0000,		/* [006] -93.0 dB */
+	0xc2b90000,		/* [007] -92.5 dB */
+	0xc2b80000,		/* [008] -92.0 dB */
+	0xc2b70000,		/* [009] -91.5 dB */
+	0xc2b60000,		/* [010] -91.0 dB */
+	0xc2b50000,		/* [011] -90.5 dB */
+	0xc2b40000,		/* [012] -90.0 dB */
+	0xc2b30000,		/* [013] -89.5 dB */
+	0xc2b20000,		/* [014] -89.0 dB */
+	0xc2b10000,		/* [015] -88.5 dB */
+	0xc2b00000,		/* [016] -88.0 dB */
+	0xc2af0000,		/* [017] -87.5 dB */
+	0xc2ae0000,		/* [018] -87.0 dB */
+	0xc2ad0000,		/* [019] -86.5 dB */
+	0xc2ac0000,		/* [020] -86.0 dB */
+	0xc2ab0000,		/* [021] -85.5 dB */
+	0xc2aa0000,		/* [022] -85.0 dB */
+	0xc2a90000,		/* [023] -84.5 dB */
+	0xc2a80000,		/* [024] -84.0 dB */
+	0xc2a70000,		/* [025] -83.5 dB */
+	0xc2a60000,		/* [026] -83.0 dB */
+	0xc2a50000,		/* [027] -82.5 dB */
+	0xc2a40000,		/* [028] -82.0 dB */
+	0xc2a30000,		/* [029] -81.5 dB */
+	0xc2a20000,		/* [030] -81.0 dB */
+	0xc2a10000,		/* [031] -80.5 dB */
+	0xc2a00000,		/* [032] -80.0 dB */
+	0xc29f0000,		/* [033] -79.5 dB */
+	0xc29e0000,		/* [034] -79.0 dB */
+	0xc29d0000,		/* [035] -78.5 dB */
+	0xc29c0000,		/* [036] -78.0 dB */
+	0xc29b0000,		/* [037] -77.5 dB */
+	0xc29a0000,		/* [038] -77.0 dB */
+	0xc2990000,		/* [039] -76.5 dB */
+	0xc2980000,		/* [040] -76.0 dB */
+	0xc2970000,		/* [041] -75.5 dB */
+	0xc2960000,		/* [042] -75.0 dB */
+	0xc2950000,		/* [043] -74.5 dB */
+	0xc2940000,		/* [044] -74.0 dB */
+	0xc2930000,		/* [045] -73.5 dB */
+	0xc2920000,		/* [046] -73.0 dB */
+	0xc2910000,		/* [047] -72.5 dB */
+	0xc2900000,		/* [048] -72.0 dB */
+	0xc28f0000,		/* [049] -71.5 dB */
+	0xc28e0000,		/* [050] -71.0 dB */
+	0xc28d0000,		/* [051] -70.5 dB */
+	0xc28c0000,		/* [052] -70.0 dB */
+	0xc28b0000,		/* [053] -69.5 dB */
+	0xc28a0000,		/* [054] -69.0 dB */
+	0xc2890000,		/* [055] -68.5 dB */
+	0xc2880000,		/* [056] -68.0 dB */
+	0xc2870000,		/* [057] -67.5 dB */
+	0xc2860000,		/* [058] -67.0 dB */
+	0xc2850000,		/* [059] -66.5 dB */
+	0xc2840000,		/* [060] -66.0 dB */
+	0xc2830000,		/* [061] -65.5 dB */
+	0xc2820000,		/* [062] -65.0 dB */
+	0xc2810000,		/* [063] -64.5 dB */
+	0xc2800000,		/* [064] -64.0 dB */
+	0xc27e0000,		/* [065] -63.5 dB */
+	0xc27c0000,		/* [066] -63.0 dB */
+	0xc27a0000,		/* [067] -62.5 dB */
+	0xc2780000,		/* [068] -62.0 dB */
+	0xc2760000,		/* [069] -61.5 dB */
+	0xc2740000,		/* [070] -61.0 dB */
+	0xc2720000,		/* [071] -60.5 dB */
+	0xc2700000,		/* [072] -60.0 dB */
+	0xc26e0000,		/* [073] -59.5 dB */
+	0xc26c0000,		/* [074] -59.0 dB */
+	0xc26a0000,		/* [075] -58.5 dB */
+	0xc2680000,		/* [076] -58.0 dB */
+	0xc2660000,		/* [077] -57.5 dB */
+	0xc2640000,		/* [078] -57.0 dB */
+	0xc2620000,		/* [079] -56.5 dB */
+	0xc2600000,		/* [080] -56.0 dB */
+	0xc25e0000,		/* [081] -55.5 dB */
+	0xc25c0000,		/* [082] -55.0 dB */
+	0xc25a0000,		/* [083] -54.5 dB */
+	0xc2580000,		/* [084] -54.0 dB */
+	0xc2560000,		/* [085] -53.5 dB */
+	0xc2540000,		/* [086] -53.0 dB */
+	0xc2520000,		/* [087] -52.5 dB */
+	0xc2500000,		/* [088] -52.0 dB */
+	0xc24e0000,		/* [089] -51.5 dB */
+	0xc24c0000,		/* [090] -51.0 dB */
+	0xc24a0000,		/* [091] -50.5 dB */
+	0xc2480000,		/* [092] -50.0 dB */
+	0xc2460000,		/* [093] -49.5 dB */
+	0xc2440000,		/* [094] -49.0 dB */
+	0xc2420000,		/* [095] -48.5 dB */
+	0xc2400000,		/* [096] -48.0 dB */
+	0xc23e0000,		/* [097] -47.5 dB */
+	0xc23c0000,		/* [098] -47.0 dB */
+	0xc23a0000,		/* [099] -46.5 dB */
+	0xc2380000,		/* [100] -46.0 dB */
+	0xc2360000,		/* [101] -45.5 dB */
+	0xc2340000,		/* [102] -45.0 dB */
+	0xc2320000,		/* [103] -44.5 dB */
+	0xc2300000,		/* [104] -44.0 dB */
+	0xc22e0000,		/* [105] -43.5 dB */
+	0xc22c0000,		/* [106] -43.0 dB */
+	0xc22a0000,		/* [107] -42.5 dB */
+	0xc2280000,		/* [108] -42.0 dB */
+	0xc2260000,		/* [109] -41.5 dB */
+	0xc2240000,		/* [110] -41.0 dB */
+	0xc2220000,		/* [111] -40.5 dB */
+	0xc2200000,		/* [112] -40.0 dB */
+	0xc21e0000,		/* [113] -39.5 dB */
+	0xc21c0000,		/* [114] -39.0 dB */
+	0xc21a0000,		/* [115] -38.5 dB */
+	0xc2180000,		/* [116] -38.0 dB */
+	0xc2160000,		/* [117] -37.5 dB */
+	0xc2140000,		/* [118] -37.0 dB */
+	0xc2120000,		/* [119] -36.5 dB */
+	0xc2100000,		/* [120] -36.0 dB */
+	0xc20e0000,		/* [121] -35.5 dB */
+	0xc20c0000,		/* [122] -35.0 dB */
+	0xc20a0000,		/* [123] -34.5 dB */
+	0xc2080000,		/* [124] -34.0 dB */
+	0xc2060000,		/* [125] -33.5 dB */
+	0xc2040000,		/* [126] -33.0 dB */
+	0xc2020000,		/* [127] -32.5 dB */
+	0xc2000000,		/* [128] -32.0 dB */
+	0xc1fc0000,		/* [129] -31.5 dB */
+	0xc1f80000,		/* [130] -31.0 dB */
+	0xc1f40000,		/* [131] -30.5 dB */
+	0xc1f00000,		/* [132] -30.0 dB */
+	0xc1ec0000,		/* [133] -29.5 dB */
+	0xc1e80000,		/* [134] -29.0 dB */
+	0xc1e40000,		/* [135] -28.5 dB */
+	0xc1e00000,		/* [136] -28.0 dB */
+	0xc1dc0000,		/* [137] -27.5 dB */
+	0xc1d80000,		/* [138] -27.0 dB */
+	0xc1d40000,		/* [139] -26.5 dB */
+	0xc1d00000,		/* [140] -26.0 dB */
+	0xc1cc0000,		/* [141] -25.5 dB */
+	0xc1c80000,		/* [142] -25.0 dB */
+	0xc1c40000,		/* [143] -24.5 dB */
+	0xc1c00000,		/* [144] -24.0 dB */
+	0xc1bc0000,		/* [145] -23.5 dB */
+	0xc1b80000,		/* [146] -23.0 dB */
+	0xc1b40000,		/* [147] -22.5 dB */
+	0xc1b00000,		/* [148] -22.0 dB */
+	0xc1ac0000,		/* [149] -21.5 dB */
+	0xc1a80000,		/* [150] -21.0 dB */
+	0xc1a40000,		/* [151] -20.5 dB */
+	0xc1a00000,		/* [152] -20.0 dB */
+	0xc19c0000,		/* [153] -19.5 dB */
+	0xc1980000,		/* [154] -19.0 dB */
+	0xc1940000,		/* [155] -18.5 dB */
+	0xc1900000,		/* [156] -18.0 dB */
+	0xc18c0000,		/* [157] -17.5 dB */
+	0xc1880000,		/* [158] -17.0 dB */
+	0xc1840000,		/* [159] -16.5 dB */
+	0xc1800000,		/* [160] -16.0 dB */
+	0xc1780000,		/* [161] -15.5 dB */
+	0xc1700000,		/* [162] -15.0 dB */
+	0xc1680000,		/* [163] -14.5 dB */
+	0xc1600000,		/* [164] -14.0 dB */
+	0xc1580000,		/* [165] -13.5 dB */
+	0xc1500000,		/* [166] -13.0 dB */
+	0xc1480000,		/* [167] -12.5 dB */
+	0xc1400000,		/* [168] -12.0 dB */
+	0xc1380000,		/* [169] -11.5 dB */
+	0xc1300000,		/* [170] -11.0 dB */
+	0xc1280000,		/* [171] -10.5 dB */
+	0xc1200000,		/* [172] -10.0 dB */
+	0xc1180000,		/* [173] -9.5 dB */
+	0xc1100000,		/* [174] -9.0 dB */
+	0xc1080000,		/* [175] -8.5 dB */
+	0xc1000000,		/* [176] -8.0 dB */
+	0xc0f00000,		/* [177] -7.5 dB */
+	0xc0e00000,		/* [178] -7.0 dB */
+	0xc0d00000,		/* [179] -6.5 dB */
+	0xc0c00000,		/* [180] -6.0 dB */
+	0xc0b00000,		/* [181] -5.5 dB */
+	0xc0a00000,		/* [182] -5.0 dB */
+	0xc0900000,		/* [183] -4.5 dB */
+	0xc0800000,		/* [184] -4.0 dB */
+	0xc0600000,		/* [185] -3.5 dB */
+	0xc0400000,		/* [186] -3.0 dB */
+	0xc0200000,		/* [187] -2.5 dB */
+	0xc0000000,		/* [188] -2.0 dB */
+	0xbfc00000,		/* [189] -1.5 dB */
+	0xbf800000,		/* [190] -1.0 dB */
+	0xbf000000,		/* [191] -0.5 dB */
+	0x00000000,		/* [192] 0.0 dB */
+	0x3f000000,		/* [193] 0.5 dB */
+	0x3f800000,		/* [194] 1.0 dB */
+	0x3fc00000,		/* [195] 1.5 dB */
+	0x40000000,		/* [196] 2.0 dB */
+	0x40200000,		/* [197] 2.5 dB */
+	0x40400000,		/* [198] 3.0 dB */
+	0x40600000,		/* [199] 3.5 dB */
+	0x40800000,		/* [200] 4.0 dB */
+	0x40900000,		/* [201] 4.5 dB */
+	0x40a00000,		/* [202] 5.0 dB */
+	0x40b00000,		/* [203] 5.5 dB */
+	0x40c00000,		/* [204] 6.0 dB */
+	0x40d00000,		/* [205] 6.5 dB */
+	0x40e00000,		/* [206] 7.0 dB */
+	0x40f00000,		/* [207] 7.5 dB */
+	0x41000000,		/* [208] 8.0 dB */
+	0x41080000,		/* [209] 8.5 dB */
+	0x41100000,		/* [210] 9.0 dB */
+	0x41180000,		/* [211] 9.5 dB */
+	0x41200000,		/* [212] 10.0 dB */
+	0x41280000,		/* [213] 10.5 dB */
+	0x41300000,		/* [214] 11.0 dB */
+	0x41380000,		/* [215] 11.5 dB */
+	0x41400000,		/* [216] 12.0 dB */
+	0x41480000,		/* [217] 12.5 dB */
+	0x41500000,		/* [218] 13.0 dB */
+	0x41580000,		/* [219] 13.5 dB */
+	0x41600000,		/* [220] 14.0 dB */
+	0x41680000,		/* [221] 14.5 dB */
+	0x41700000,		/* [222] 15.0 dB */
+	0x41780000,		/* [223] 15.5 dB */
+	0x41800000,		/* [224] 16.0 dB */
+	0x41840000,		/* [225] 16.5 dB */
+	0x41880000,		/* [226] 17.0 dB */
+	0x418c0000,		/* [227] 17.5 dB */
+	0x41900000,		/* [228] 18.0 dB */
+	0x41940000,		/* [229] 18.5 dB */
+	0x41980000,		/* [230] 19.0 dB */
+	0x419c0000,		/* [231] 19.5 dB */
+	0x41a00000,		/* [232] 20.0 dB */
+	0x41a40000,		/* [233] 20.5 dB */
+	0x41a80000,		/* [234] 21.0 dB */
+	0x41ac0000,		/* [235] 21.5 dB */
+	0x41b00000,		/* [236] 22.0 dB */
+	0x41b40000,		/* [237] 22.5 dB */
+	0x41b80000,		/* [238] 23.0 dB */
+	0x41bc0000,		/* [239] 23.5 dB */
+	0x41c00000,		/* [240] 24.0 dB */
+	0x41c40000,		/* [241] 24.5 dB */
+	0x41c80000,		/* [242] 25.0 dB */
+	0x41cc0000,		/* [243] 25.5 dB */
+	0x41d00000,		/* [244] 26.0 dB */
+	0x41d40000,		/* [245] 26.5 dB */
+	0x41d80000,		/* [246] 27.0 dB */
+	0x41dc0000,		/* [247] 27.5 dB */
+	0x41e00000,		/* [248] 28.0 dB */
+	0x41e40000,		/* [249] 28.5 dB */
+	0x41e80000,		/* [250] 29.0 dB */
+	0x41ec0000,		/* [251] 29.5 dB */
+	0x41f00000,		/* [252] 30.0 dB */
+	0x41f40000,		/* [253] 30.5 dB */
+	0x41f80000,		/* [254] 31.0 dB */
+	0x41fc0000,		/* [255] 31.5 dB */
+};
+
+#define MIXART_ANALOG_CAPTURE_LEVEL_MIN   0      /* -96.0 dB + 8.0 dB = -88.0 dB */
+#define MIXART_ANALOG_CAPTURE_LEVEL_MAX   255    /*  31.5 dB + 8.0 dB =  39.5 dB */
+#define MIXART_ANALOG_CAPTURE_ZERO_LEVEL  176    /*  -8.0 dB + 8.0 dB =  0.0 dB */
+
+#define MIXART_ANALOG_PLAYBACK_LEVEL_MIN  0      /* -96.0 dB + 1.5 dB = -94.5 dB (possible is down to (-114.0+1.5)dB) */
+#define MIXART_ANALOG_PLAYBACK_LEVEL_MAX  192    /*   0.0 dB + 1.5 dB =  1.5 dB */
+#define MIXART_ANALOG_PLAYBACK_ZERO_LEVEL 189    /*  -1.5 dB + 1.5 dB =  0.0 dB */
+
+static int mixart_update_analog_audio_level(mixart_t* chip, int is_capture)
+{
+	int i, err;
+	mixart_msg_t request;
+	mixart_io_level_t io_level;
+	mixart_return_uid_t resp;
+
+	memset(&io_level, 0, sizeof(io_level));
+	io_level.channel = -1; /* left and right */
+
+	for(i=0; i<2; i++) {
+		if(is_capture) {
+			io_level.level[i].analog_level = mixart_analog_level[chip->analog_capture_volume[i]];
+		} else {
+			if(chip->analog_playback_active[i])
+				io_level.level[i].analog_level = mixart_analog_level[chip->analog_playback_volume[i]];
+			else
+				io_level.level[i].analog_level = mixart_analog_level[MIXART_ANALOG_PLAYBACK_LEVEL_MIN];
+		}
+	}
+
+	if(is_capture)	request.uid = chip->uid_in_analog_physio;
+	else		request.uid = chip->uid_out_analog_physio;
+	request.message_id = MSG_PHYSICALIO_SET_LEVEL;
+	request.data = &io_level;
+	request.size = sizeof(io_level);
+
+	err = snd_mixart_send_msg(chip->mgr, &request, sizeof(resp), &resp);
+	if((err<0) || (resp.error_code)) {
+		snd_printk(KERN_DEBUG "error MSG_PHYSICALIO_SET_LEVEL card(%d) is_capture(%d) error_code(%x)\n", chip->chip_idx, is_capture, resp.error_code);
+		return -EINVAL;
+	}
+	return 0;
+}
+
+/*
+ * analog level control
+ */
+static int mixart_analog_vol_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
+{
+	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+	uinfo->count = 2;
+	if(kcontrol->private_value == 0) {	/* playback */
+		uinfo->value.integer.min = MIXART_ANALOG_PLAYBACK_LEVEL_MIN;  /* -96 dB */
+		uinfo->value.integer.max = MIXART_ANALOG_PLAYBACK_LEVEL_MAX;  /* 0 dB */
+	} else {				/* capture */
+		uinfo->value.integer.min = MIXART_ANALOG_CAPTURE_LEVEL_MIN;   /* -96 dB */
+		uinfo->value.integer.max = MIXART_ANALOG_CAPTURE_LEVEL_MAX;   /* 31.5 dB */
+	}
+	return 0;
+}
+
+static int mixart_analog_vol_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+{
+	mixart_t *chip = snd_kcontrol_chip(kcontrol);
+	down(&chip->mgr->mixer_mutex);
+	if(kcontrol->private_value == 0) {	/* playback */
+		ucontrol->value.integer.value[0] = chip->analog_playback_volume[0];
+		ucontrol->value.integer.value[1] = chip->analog_playback_volume[1];
+	} else {				/* capture */
+		ucontrol->value.integer.value[0] = chip->analog_capture_volume[0];
+		ucontrol->value.integer.value[1] = chip->analog_capture_volume[1];
+	}
+	up(&chip->mgr->mixer_mutex);
+	return 0;
+}
+
+static int mixart_analog_vol_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+{
+	mixart_t *chip = snd_kcontrol_chip(kcontrol);
+	int changed = 0;
+	int is_capture, i;
+
+	down(&chip->mgr->mixer_mutex);
+	is_capture = (kcontrol->private_value != 0);
+	for(i=0; i<2; i++) {
+		int  new_volume = ucontrol->value.integer.value[i];
+		int* stored_volume = is_capture ? &chip->analog_capture_volume[i] : &chip->analog_playback_volume[i];
+		if(*stored_volume != new_volume) {
+			*stored_volume = new_volume;
+			changed = 1;
+		}
+	}
+	if(changed)	mixart_update_analog_audio_level(chip, is_capture);
+	up(&chip->mgr->mixer_mutex);
+	return changed;
+}
+
+static snd_kcontrol_new_t mixart_control_analog_level = {
+	.iface =	SNDRV_CTL_ELEM_IFACE_MIXER,
+	/* name will be filled later */
+	.info =		mixart_analog_vol_info,
+	.get =		mixart_analog_vol_get,
+	.put =		mixart_analog_vol_put,
+};
+
+/* shared */
+static int mixart_sw_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
+{
+	uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
+	uinfo->count = 2;
+	uinfo->value.integer.min = 0;
+	uinfo->value.integer.max = 1;
+	return 0;
+}
+
+static int mixart_audio_sw_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+{
+	mixart_t *chip = snd_kcontrol_chip(kcontrol);
+
+	down(&chip->mgr->mixer_mutex);
+	ucontrol->value.integer.value[0] = chip->analog_playback_active[0];
+	ucontrol->value.integer.value[1] = chip->analog_playback_active[1];
+	up(&chip->mgr->mixer_mutex);
+	return 0;
+}
+
+static int mixart_audio_sw_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+{
+	mixart_t *chip = snd_kcontrol_chip(kcontrol);
+	int i, changed = 0;
+	down(&chip->mgr->mixer_mutex);
+	for(i=0; i<2; i++) {
+		if(chip->analog_playback_active[i] != ucontrol->value.integer.value[i]) {
+			chip->analog_playback_active[i] = ucontrol->value.integer.value[i];
+			changed = 1;
+		}
+	}
+	if(changed)	mixart_update_analog_audio_level(chip, 0); /* update playback levels */
+	up(&chip->mgr->mixer_mutex);
+	return changed;
+}
+
+static snd_kcontrol_new_t mixart_control_output_switch = {
+	.iface =	SNDRV_CTL_ELEM_IFACE_MIXER,
+	.name =         "Master Playback Switch",
+	.info =         mixart_sw_info,		/* shared */
+	.get =          mixart_audio_sw_get,
+	.put =          mixart_audio_sw_put
+};
+
+static u32 mixart_digital_level[256] = {
+	0x00000000,		/* [000] = 0.00e+000 = mute if <= -109.5dB */
+	0x366e1c7a,		/* [001] = 3.55e-006 = pow(10.0, 0.05 * -109.0dB) */
+	0x367c3860,		/* [002] = 3.76e-006 = pow(10.0, 0.05 * -108.5dB) */
+	0x36859525,		/* [003] = 3.98e-006 = pow(10.0, 0.05 * -108.0dB) */
+	0x368d7f74,		/* [004] = 4.22e-006 = pow(10.0, 0.05 * -107.5dB) */
+	0x3695e1d4,		/* [005] = 4.47e-006 = pow(10.0, 0.05 * -107.0dB) */
+	0x369ec362,		/* [006] = 4.73e-006 = pow(10.0, 0.05 * -106.5dB) */
+	0x36a82ba8,		/* [007] = 5.01e-006 = pow(10.0, 0.05 * -106.0dB) */
+	0x36b222a0,		/* [008] = 5.31e-006 = pow(10.0, 0.05 * -105.5dB) */
+	0x36bcb0c1,		/* [009] = 5.62e-006 = pow(10.0, 0.05 * -105.0dB) */
+	0x36c7defd,		/* [010] = 5.96e-006 = pow(10.0, 0.05 * -104.5dB) */
+	0x36d3b6d3,		/* [011] = 6.31e-006 = pow(10.0, 0.05 * -104.0dB) */
+	0x36e0424e,		/* [012] = 6.68e-006 = pow(10.0, 0.05 * -103.5dB) */
+	0x36ed8c14,		/* [013] = 7.08e-006 = pow(10.0, 0.05 * -103.0dB) */
+	0x36fb9f6c,		/* [014] = 7.50e-006 = pow(10.0, 0.05 * -102.5dB) */
+	0x37054423,		/* [015] = 7.94e-006 = pow(10.0, 0.05 * -102.0dB) */
+	0x370d29a5,		/* [016] = 8.41e-006 = pow(10.0, 0.05 * -101.5dB) */
+	0x371586f0,		/* [017] = 8.91e-006 = pow(10.0, 0.05 * -101.0dB) */
+	0x371e631b,		/* [018] = 9.44e-006 = pow(10.0, 0.05 * -100.5dB) */
+	0x3727c5ac,		/* [019] = 1.00e-005 = pow(10.0, 0.05 * -100.0dB) */
+	0x3731b69a,		/* [020] = 1.06e-005 = pow(10.0, 0.05 * -99.5dB) */
+	0x373c3e53,		/* [021] = 1.12e-005 = pow(10.0, 0.05 * -99.0dB) */
+	0x374765c8,		/* [022] = 1.19e-005 = pow(10.0, 0.05 * -98.5dB) */
+	0x3753366f,		/* [023] = 1.26e-005 = pow(10.0, 0.05 * -98.0dB) */
+	0x375fba4f,		/* [024] = 1.33e-005 = pow(10.0, 0.05 * -97.5dB) */
+	0x376cfc07,		/* [025] = 1.41e-005 = pow(10.0, 0.05 * -97.0dB) */
+	0x377b06d5,		/* [026] = 1.50e-005 = pow(10.0, 0.05 * -96.5dB) */
+	0x3784f352,		/* [027] = 1.58e-005 = pow(10.0, 0.05 * -96.0dB) */
+	0x378cd40b,		/* [028] = 1.68e-005 = pow(10.0, 0.05 * -95.5dB) */
+	0x37952c42,		/* [029] = 1.78e-005 = pow(10.0, 0.05 * -95.0dB) */
+	0x379e030e,		/* [030] = 1.88e-005 = pow(10.0, 0.05 * -94.5dB) */
+	0x37a75fef,		/* [031] = 2.00e-005 = pow(10.0, 0.05 * -94.0dB) */
+	0x37b14ad5,		/* [032] = 2.11e-005 = pow(10.0, 0.05 * -93.5dB) */
+	0x37bbcc2c,		/* [033] = 2.24e-005 = pow(10.0, 0.05 * -93.0dB) */
+	0x37c6ecdd,		/* [034] = 2.37e-005 = pow(10.0, 0.05 * -92.5dB) */
+	0x37d2b65a,		/* [035] = 2.51e-005 = pow(10.0, 0.05 * -92.0dB) */
+	0x37df32a3,		/* [036] = 2.66e-005 = pow(10.0, 0.05 * -91.5dB) */
+	0x37ec6c50,		/* [037] = 2.82e-005 = pow(10.0, 0.05 * -91.0dB) */
+	0x37fa6e9b,		/* [038] = 2.99e-005 = pow(10.0, 0.05 * -90.5dB) */
+	0x3804a2b3,		/* [039] = 3.16e-005 = pow(10.0, 0.05 * -90.0dB) */
+	0x380c7ea4,		/* [040] = 3.35e-005 = pow(10.0, 0.05 * -89.5dB) */
+	0x3814d1cc,		/* [041] = 3.55e-005 = pow(10.0, 0.05 * -89.0dB) */
+	0x381da33c,		/* [042] = 3.76e-005 = pow(10.0, 0.05 * -88.5dB) */
+	0x3826fa6f,		/* [043] = 3.98e-005 = pow(10.0, 0.05 * -88.0dB) */
+	0x3830df51,		/* [044] = 4.22e-005 = pow(10.0, 0.05 * -87.5dB) */
+	0x383b5a49,		/* [045] = 4.47e-005 = pow(10.0, 0.05 * -87.0dB) */
+	0x3846743b,		/* [046] = 4.73e-005 = pow(10.0, 0.05 * -86.5dB) */
+	0x38523692,		/* [047] = 5.01e-005 = pow(10.0, 0.05 * -86.0dB) */
+	0x385eab48,		/* [048] = 5.31e-005 = pow(10.0, 0.05 * -85.5dB) */
+	0x386bdcf1,		/* [049] = 5.62e-005 = pow(10.0, 0.05 * -85.0dB) */
+	0x3879d6bc,		/* [050] = 5.96e-005 = pow(10.0, 0.05 * -84.5dB) */
+	0x38845244,		/* [051] = 6.31e-005 = pow(10.0, 0.05 * -84.0dB) */
+	0x388c2971,		/* [052] = 6.68e-005 = pow(10.0, 0.05 * -83.5dB) */
+	0x3894778d,		/* [053] = 7.08e-005 = pow(10.0, 0.05 * -83.0dB) */
+	0x389d43a4,		/* [054] = 7.50e-005 = pow(10.0, 0.05 * -82.5dB) */
+	0x38a6952c,		/* [055] = 7.94e-005 = pow(10.0, 0.05 * -82.0dB) */
+	0x38b0740f,		/* [056] = 8.41e-005 = pow(10.0, 0.05 * -81.5dB) */
+	0x38bae8ac,		/* [057] = 8.91e-005 = pow(10.0, 0.05 * -81.0dB) */
+	0x38c5fbe2,		/* [058] = 9.44e-005 = pow(10.0, 0.05 * -80.5dB) */
+	0x38d1b717,		/* [059] = 1.00e-004 = pow(10.0, 0.05 * -80.0dB) */
+	0x38de2440,		/* [060] = 1.06e-004 = pow(10.0, 0.05 * -79.5dB) */
+	0x38eb4de8,		/* [061] = 1.12e-004 = pow(10.0, 0.05 * -79.0dB) */
+	0x38f93f3a,		/* [062] = 1.19e-004 = pow(10.0, 0.05 * -78.5dB) */
+	0x39040206,		/* [063] = 1.26e-004 = pow(10.0, 0.05 * -78.0dB) */
+	0x390bd472,		/* [064] = 1.33e-004 = pow(10.0, 0.05 * -77.5dB) */
+	0x39141d84,		/* [065] = 1.41e-004 = pow(10.0, 0.05 * -77.0dB) */
+	0x391ce445,		/* [066] = 1.50e-004 = pow(10.0, 0.05 * -76.5dB) */
+	0x39263027,		/* [067] = 1.58e-004 = pow(10.0, 0.05 * -76.0dB) */
+	0x3930090d,		/* [068] = 1.68e-004 = pow(10.0, 0.05 * -75.5dB) */
+	0x393a7753,		/* [069] = 1.78e-004 = pow(10.0, 0.05 * -75.0dB) */
+	0x394583d2,		/* [070] = 1.88e-004 = pow(10.0, 0.05 * -74.5dB) */
+	0x395137ea,		/* [071] = 2.00e-004 = pow(10.0, 0.05 * -74.0dB) */
+	0x395d9d8a,		/* [072] = 2.11e-004 = pow(10.0, 0.05 * -73.5dB) */
+	0x396abf37,		/* [073] = 2.24e-004 = pow(10.0, 0.05 * -73.0dB) */
+	0x3978a814,		/* [074] = 2.37e-004 = pow(10.0, 0.05 * -72.5dB) */
+	0x3983b1f8,		/* [075] = 2.51e-004 = pow(10.0, 0.05 * -72.0dB) */
+	0x398b7fa6,		/* [076] = 2.66e-004 = pow(10.0, 0.05 * -71.5dB) */
+	0x3993c3b2,		/* [077] = 2.82e-004 = pow(10.0, 0.05 * -71.0dB) */
+	0x399c8521,		/* [078] = 2.99e-004 = pow(10.0, 0.05 * -70.5dB) */
+	0x39a5cb5f,		/* [079] = 3.16e-004 = pow(10.0, 0.05 * -70.0dB) */
+	0x39af9e4d,		/* [080] = 3.35e-004 = pow(10.0, 0.05 * -69.5dB) */
+	0x39ba063f,		/* [081] = 3.55e-004 = pow(10.0, 0.05 * -69.0dB) */
+	0x39c50c0b,		/* [082] = 3.76e-004 = pow(10.0, 0.05 * -68.5dB) */
+	0x39d0b90a,		/* [083] = 3.98e-004 = pow(10.0, 0.05 * -68.0dB) */
+	0x39dd1726,		/* [084] = 4.22e-004 = pow(10.0, 0.05 * -67.5dB) */
+	0x39ea30db,		/* [085] = 4.47e-004 = pow(10.0, 0.05 * -67.0dB) */
+	0x39f81149,		/* [086] = 4.73e-004 = pow(10.0, 0.05 * -66.5dB) */
+	0x3a03621b,		/* [087] = 5.01e-004 = pow(10.0, 0.05 * -66.0dB) */
+	0x3a0b2b0d,		/* [088] = 5.31e-004 = pow(10.0, 0.05 * -65.5dB) */
+	0x3a136a16,		/* [089] = 5.62e-004 = pow(10.0, 0.05 * -65.0dB) */
+	0x3a1c2636,		/* [090] = 5.96e-004 = pow(10.0, 0.05 * -64.5dB) */
+	0x3a2566d5,		/* [091] = 6.31e-004 = pow(10.0, 0.05 * -64.0dB) */
+	0x3a2f33cd,		/* [092] = 6.68e-004 = pow(10.0, 0.05 * -63.5dB) */
+	0x3a399570,		/* [093] = 7.08e-004 = pow(10.0, 0.05 * -63.0dB) */
+	0x3a44948c,		/* [094] = 7.50e-004 = pow(10.0, 0.05 * -62.5dB) */
+	0x3a503a77,		/* [095] = 7.94e-004 = pow(10.0, 0.05 * -62.0dB) */
+	0x3a5c9112,		/* [096] = 8.41e-004 = pow(10.0, 0.05 * -61.5dB) */
+	0x3a69a2d7,		/* [097] = 8.91e-004 = pow(10.0, 0.05 * -61.0dB) */
+	0x3a777ada,		/* [098] = 9.44e-004 = pow(10.0, 0.05 * -60.5dB) */
+	0x3a83126f,		/* [099] = 1.00e-003 = pow(10.0, 0.05 * -60.0dB) */
+	0x3a8ad6a8,		/* [100] = 1.06e-003 = pow(10.0, 0.05 * -59.5dB) */
+	0x3a9310b1,		/* [101] = 1.12e-003 = pow(10.0, 0.05 * -59.0dB) */
+	0x3a9bc784,		/* [102] = 1.19e-003 = pow(10.0, 0.05 * -58.5dB) */
+	0x3aa50287,		/* [103] = 1.26e-003 = pow(10.0, 0.05 * -58.0dB) */
+	0x3aaec98e,		/* [104] = 1.33e-003 = pow(10.0, 0.05 * -57.5dB) */
+	0x3ab924e5,		/* [105] = 1.41e-003 = pow(10.0, 0.05 * -57.0dB) */
+	0x3ac41d56,		/* [106] = 1.50e-003 = pow(10.0, 0.05 * -56.5dB) */
+	0x3acfbc31,		/* [107] = 1.58e-003 = pow(10.0, 0.05 * -56.0dB) */
+	0x3adc0b51,		/* [108] = 1.68e-003 = pow(10.0, 0.05 * -55.5dB) */
+	0x3ae91528,		/* [109] = 1.78e-003 = pow(10.0, 0.05 * -55.0dB) */
+	0x3af6e4c6,		/* [110] = 1.88e-003 = pow(10.0, 0.05 * -54.5dB) */
+	0x3b02c2f2,		/* [111] = 2.00e-003 = pow(10.0, 0.05 * -54.0dB) */
+	0x3b0a8276,		/* [112] = 2.11e-003 = pow(10.0, 0.05 * -53.5dB) */
+	0x3b12b782,		/* [113] = 2.24e-003 = pow(10.0, 0.05 * -53.0dB) */
+	0x3b1b690d,		/* [114] = 2.37e-003 = pow(10.0, 0.05 * -52.5dB) */
+	0x3b249e76,		/* [115] = 2.51e-003 = pow(10.0, 0.05 * -52.0dB) */
+	0x3b2e5f8f,		/* [116] = 2.66e-003 = pow(10.0, 0.05 * -51.5dB) */
+	0x3b38b49f,		/* [117] = 2.82e-003 = pow(10.0, 0.05 * -51.0dB) */
+	0x3b43a669,		/* [118] = 2.99e-003 = pow(10.0, 0.05 * -50.5dB) */
+	0x3b4f3e37,		/* [119] = 3.16e-003 = pow(10.0, 0.05 * -50.0dB) */
+	0x3b5b85e0,		/* [120] = 3.35e-003 = pow(10.0, 0.05 * -49.5dB) */
+	0x3b6887cf,		/* [121] = 3.55e-003 = pow(10.0, 0.05 * -49.0dB) */
+	0x3b764f0e,		/* [122] = 3.76e-003 = pow(10.0, 0.05 * -48.5dB) */
+	0x3b8273a6,		/* [123] = 3.98e-003 = pow(10.0, 0.05 * -48.0dB) */
+	0x3b8a2e77,		/* [124] = 4.22e-003 = pow(10.0, 0.05 * -47.5dB) */
+	0x3b925e89,		/* [125] = 4.47e-003 = pow(10.0, 0.05 * -47.0dB) */
+	0x3b9b0ace,		/* [126] = 4.73e-003 = pow(10.0, 0.05 * -46.5dB) */
+	0x3ba43aa2,		/* [127] = 5.01e-003 = pow(10.0, 0.05 * -46.0dB) */
+	0x3badf5d1,		/* [128] = 5.31e-003 = pow(10.0, 0.05 * -45.5dB) */
+	0x3bb8449c,		/* [129] = 5.62e-003 = pow(10.0, 0.05 * -45.0dB) */
+	0x3bc32fc3,		/* [130] = 5.96e-003 = pow(10.0, 0.05 * -44.5dB) */
+	0x3bcec08a,		/* [131] = 6.31e-003 = pow(10.0, 0.05 * -44.0dB) */
+	0x3bdb00c0,		/* [132] = 6.68e-003 = pow(10.0, 0.05 * -43.5dB) */
+	0x3be7facc,		/* [133] = 7.08e-003 = pow(10.0, 0.05 * -43.0dB) */
+	0x3bf5b9b0,		/* [134] = 7.50e-003 = pow(10.0, 0.05 * -42.5dB) */
+	0x3c02248a,		/* [135] = 7.94e-003 = pow(10.0, 0.05 * -42.0dB) */
+	0x3c09daac,		/* [136] = 8.41e-003 = pow(10.0, 0.05 * -41.5dB) */
+	0x3c1205c6,		/* [137] = 8.91e-003 = pow(10.0, 0.05 * -41.0dB) */
+	0x3c1aacc8,		/* [138] = 9.44e-003 = pow(10.0, 0.05 * -40.5dB) */
+	0x3c23d70a,		/* [139] = 1.00e-002 = pow(10.0, 0.05 * -40.0dB) */
+	0x3c2d8c52,		/* [140] = 1.06e-002 = pow(10.0, 0.05 * -39.5dB) */
+	0x3c37d4dd,		/* [141] = 1.12e-002 = pow(10.0, 0.05 * -39.0dB) */
+	0x3c42b965,		/* [142] = 1.19e-002 = pow(10.0, 0.05 * -38.5dB) */
+	0x3c4e4329,		/* [143] = 1.26e-002 = pow(10.0, 0.05 * -38.0dB) */
+	0x3c5a7bf1,		/* [144] = 1.33e-002 = pow(10.0, 0.05 * -37.5dB) */
+	0x3c676e1e,		/* [145] = 1.41e-002 = pow(10.0, 0.05 * -37.0dB) */
+	0x3c7524ac,		/* [146] = 1.50e-002 = pow(10.0, 0.05 * -36.5dB) */
+	0x3c81d59f,		/* [147] = 1.58e-002 = pow(10.0, 0.05 * -36.0dB) */
+	0x3c898712,		/* [148] = 1.68e-002 = pow(10.0, 0.05 * -35.5dB) */
+	0x3c91ad39,		/* [149] = 1.78e-002 = pow(10.0, 0.05 * -35.0dB) */
+	0x3c9a4efc,		/* [150] = 1.88e-002 = pow(10.0, 0.05 * -34.5dB) */
+	0x3ca373af,		/* [151] = 2.00e-002 = pow(10.0, 0.05 * -34.0dB) */
+	0x3cad2314,		/* [152] = 2.11e-002 = pow(10.0, 0.05 * -33.5dB) */
+	0x3cb76563,		/* [153] = 2.24e-002 = pow(10.0, 0.05 * -33.0dB) */
+	0x3cc24350,		/* [154] = 2.37e-002 = pow(10.0, 0.05 * -32.5dB) */
+	0x3ccdc614,		/* [155] = 2.51e-002 = pow(10.0, 0.05 * -32.0dB) */
+	0x3cd9f773,		/* [156] = 2.66e-002 = pow(10.0, 0.05 * -31.5dB) */
+	0x3ce6e1c6,		/* [157] = 2.82e-002 = pow(10.0, 0.05 * -31.0dB) */
+	0x3cf49003,		/* [158] = 2.99e-002 = pow(10.0, 0.05 * -30.5dB) */
+	0x3d0186e2,		/* [159] = 3.16e-002 = pow(10.0, 0.05 * -30.0dB) */
+	0x3d0933ac,		/* [160] = 3.35e-002 = pow(10.0, 0.05 * -29.5dB) */
+	0x3d1154e1,		/* [161] = 3.55e-002 = pow(10.0, 0.05 * -29.0dB) */
+	0x3d19f169,		/* [162] = 3.76e-002 = pow(10.0, 0.05 * -28.5dB) */
+	0x3d231090,		/* [163] = 3.98e-002 = pow(10.0, 0.05 * -28.0dB) */
+	0x3d2cba15,		/* [164] = 4.22e-002 = pow(10.0, 0.05 * -27.5dB) */
+	0x3d36f62b,		/* [165] = 4.47e-002 = pow(10.0, 0.05 * -27.0dB) */
+	0x3d41cd81,		/* [166] = 4.73e-002 = pow(10.0, 0.05 * -26.5dB) */
+	0x3d4d494a,		/* [167] = 5.01e-002 = pow(10.0, 0.05 * -26.0dB) */
+	0x3d597345,		/* [168] = 5.31e-002 = pow(10.0, 0.05 * -25.5dB) */
+	0x3d6655c3,		/* [169] = 5.62e-002 = pow(10.0, 0.05 * -25.0dB) */
+	0x3d73fbb4,		/* [170] = 5.96e-002 = pow(10.0, 0.05 * -24.5dB) */
+	0x3d813856,		/* [171] = 6.31e-002 = pow(10.0, 0.05 * -24.0dB) */
+	0x3d88e078,		/* [172] = 6.68e-002 = pow(10.0, 0.05 * -23.5dB) */
+	0x3d90fcbf,		/* [173] = 7.08e-002 = pow(10.0, 0.05 * -23.0dB) */
+	0x3d99940e,		/* [174] = 7.50e-002 = pow(10.0, 0.05 * -22.5dB) */
+	0x3da2adad,		/* [175] = 7.94e-002 = pow(10.0, 0.05 * -22.0dB) */
+	0x3dac5156,		/* [176] = 8.41e-002 = pow(10.0, 0.05 * -21.5dB) */
+	0x3db68738,		/* [177] = 8.91e-002 = pow(10.0, 0.05 * -21.0dB) */
+	0x3dc157fb,		/* [178] = 9.44e-002 = pow(10.0, 0.05 * -20.5dB) */
+	0x3dcccccd,		/* [179] = 1.00e-001 = pow(10.0, 0.05 * -20.0dB) */
+	0x3dd8ef67,		/* [180] = 1.06e-001 = pow(10.0, 0.05 * -19.5dB) */
+	0x3de5ca15,		/* [181] = 1.12e-001 = pow(10.0, 0.05 * -19.0dB) */
+	0x3df367bf,		/* [182] = 1.19e-001 = pow(10.0, 0.05 * -18.5dB) */
+	0x3e00e9f9,		/* [183] = 1.26e-001 = pow(10.0, 0.05 * -18.0dB) */
+	0x3e088d77,		/* [184] = 1.33e-001 = pow(10.0, 0.05 * -17.5dB) */
+	0x3e10a4d3,		/* [185] = 1.41e-001 = pow(10.0, 0.05 * -17.0dB) */
+	0x3e1936ec,		/* [186] = 1.50e-001 = pow(10.0, 0.05 * -16.5dB) */
+	0x3e224b06,		/* [187] = 1.58e-001 = pow(10.0, 0.05 * -16.0dB) */
+	0x3e2be8d7,		/* [188] = 1.68e-001 = pow(10.0, 0.05 * -15.5dB) */
+	0x3e361887,		/* [189] = 1.78e-001 = pow(10.0, 0.05 * -15.0dB) */
+	0x3e40e2bb,		/* [190] = 1.88e-001 = pow(10.0, 0.05 * -14.5dB) */
+	0x3e4c509b,		/* [191] = 2.00e-001 = pow(10.0, 0.05 * -14.0dB) */
+	0x3e586bd9,		/* [192] = 2.11e-001 = pow(10.0, 0.05 * -13.5dB) */
+	0x3e653ebb,		/* [193] = 2.24e-001 = pow(10.0, 0.05 * -13.0dB) */
+	0x3e72d424,		/* [194] = 2.37e-001 = pow(10.0, 0.05 * -12.5dB) */
+	0x3e809bcc,		/* [195] = 2.51e-001 = pow(10.0, 0.05 * -12.0dB) */
+	0x3e883aa8,		/* [196] = 2.66e-001 = pow(10.0, 0.05 * -11.5dB) */
+	0x3e904d1c,		/* [197] = 2.82e-001 = pow(10.0, 0.05 * -11.0dB) */
+	0x3e98da02,		/* [198] = 2.99e-001 = pow(10.0, 0.05 * -10.5dB) */
+	0x3ea1e89b,		/* [199] = 3.16e-001 = pow(10.0, 0.05 * -10.0dB) */
+	0x3eab8097,		/* [200] = 3.35e-001 = pow(10.0, 0.05 * -9.5dB) */
+	0x3eb5aa1a,		/* [201] = 3.55e-001 = pow(10.0, 0.05 * -9.0dB) */
+	0x3ec06dc3,		/* [202] = 3.76e-001 = pow(10.0, 0.05 * -8.5dB) */
+	0x3ecbd4b4,		/* [203] = 3.98e-001 = pow(10.0, 0.05 * -8.0dB) */
+	0x3ed7e89b,		/* [204] = 4.22e-001 = pow(10.0, 0.05 * -7.5dB) */
+	0x3ee4b3b6,		/* [205] = 4.47e-001 = pow(10.0, 0.05 * -7.0dB) */
+	0x3ef240e2,		/* [206] = 4.73e-001 = pow(10.0, 0.05 * -6.5dB) */
+	0x3f004dce,		/* [207] = 5.01e-001 = pow(10.0, 0.05 * -6.0dB) */
+	0x3f07e80b,		/* [208] = 5.31e-001 = pow(10.0, 0.05 * -5.5dB) */
+	0x3f0ff59a,		/* [209] = 5.62e-001 = pow(10.0, 0.05 * -5.0dB) */
+	0x3f187d50,		/* [210] = 5.96e-001 = pow(10.0, 0.05 * -4.5dB) */
+	0x3f21866c,		/* [211] = 6.31e-001 = pow(10.0, 0.05 * -4.0dB) */
+	0x3f2b1896,		/* [212] = 6.68e-001 = pow(10.0, 0.05 * -3.5dB) */
+	0x3f353bef,		/* [213] = 7.08e-001 = pow(10.0, 0.05 * -3.0dB) */
+	0x3f3ff911,		/* [214] = 7.50e-001 = pow(10.0, 0.05 * -2.5dB) */
+	0x3f4b5918,		/* [215] = 7.94e-001 = pow(10.0, 0.05 * -2.0dB) */
+	0x3f5765ac,		/* [216] = 8.41e-001 = pow(10.0, 0.05 * -1.5dB) */
+	0x3f642905,		/* [217] = 8.91e-001 = pow(10.0, 0.05 * -1.0dB) */
+	0x3f71adf9,		/* [218] = 9.44e-001 = pow(10.0, 0.05 * -0.5dB) */
+	0x3f800000,		/* [219] = 1.00e+000 = pow(10.0, 0.05 * 0.0dB) */
+	0x3f8795a0,		/* [220] = 1.06e+000 = pow(10.0, 0.05 * 0.5dB) */
+	0x3f8f9e4d,		/* [221] = 1.12e+000 = pow(10.0, 0.05 * 1.0dB) */
+	0x3f9820d7,		/* [222] = 1.19e+000 = pow(10.0, 0.05 * 1.5dB) */
+	0x3fa12478,		/* [223] = 1.26e+000 = pow(10.0, 0.05 * 2.0dB) */
+	0x3faab0d5,		/* [224] = 1.33e+000 = pow(10.0, 0.05 * 2.5dB) */
+	0x3fb4ce08,		/* [225] = 1.41e+000 = pow(10.0, 0.05 * 3.0dB) */
+	0x3fbf84a6,		/* [226] = 1.50e+000 = pow(10.0, 0.05 * 3.5dB) */
+	0x3fcaddc8,		/* [227] = 1.58e+000 = pow(10.0, 0.05 * 4.0dB) */
+	0x3fd6e30d,		/* [228] = 1.68e+000 = pow(10.0, 0.05 * 4.5dB) */
+	0x3fe39ea9,		/* [229] = 1.78e+000 = pow(10.0, 0.05 * 5.0dB) */
+	0x3ff11b6a,		/* [230] = 1.88e+000 = pow(10.0, 0.05 * 5.5dB) */
+	0x3fff64c1,		/* [231] = 2.00e+000 = pow(10.0, 0.05 * 6.0dB) */
+	0x40074368,		/* [232] = 2.11e+000 = pow(10.0, 0.05 * 6.5dB) */
+	0x400f4735,		/* [233] = 2.24e+000 = pow(10.0, 0.05 * 7.0dB) */
+	0x4017c496,		/* [234] = 2.37e+000 = pow(10.0, 0.05 * 7.5dB) */
+	0x4020c2bf,		/* [235] = 2.51e+000 = pow(10.0, 0.05 * 8.0dB) */
+	0x402a4952,		/* [236] = 2.66e+000 = pow(10.0, 0.05 * 8.5dB) */
+	0x40346063,		/* [237] = 2.82e+000 = pow(10.0, 0.05 * 9.0dB) */
+	0x403f1082,		/* [238] = 2.99e+000 = pow(10.0, 0.05 * 9.5dB) */
+	0x404a62c2,		/* [239] = 3.16e+000 = pow(10.0, 0.05 * 10.0dB) */
+	0x405660bd,		/* [240] = 3.35e+000 = pow(10.0, 0.05 * 10.5dB) */
+	0x406314a0,		/* [241] = 3.55e+000 = pow(10.0, 0.05 * 11.0dB) */
+	0x40708933,		/* [242] = 3.76e+000 = pow(10.0, 0.05 * 11.5dB) */
+	0x407ec9e1,		/* [243] = 3.98e+000 = pow(10.0, 0.05 * 12.0dB) */
+	0x4086f161,		/* [244] = 4.22e+000 = pow(10.0, 0.05 * 12.5dB) */
+	0x408ef052,		/* [245] = 4.47e+000 = pow(10.0, 0.05 * 13.0dB) */
+	0x4097688d,		/* [246] = 4.73e+000 = pow(10.0, 0.05 * 13.5dB) */
+	0x40a06142,		/* [247] = 5.01e+000 = pow(10.0, 0.05 * 14.0dB) */
+	0x40a9e20e,		/* [248] = 5.31e+000 = pow(10.0, 0.05 * 14.5dB) */
+	0x40b3f300,		/* [249] = 5.62e+000 = pow(10.0, 0.05 * 15.0dB) */
+	0x40be9ca5,		/* [250] = 5.96e+000 = pow(10.0, 0.05 * 15.5dB) */
+	0x40c9e807,		/* [251] = 6.31e+000 = pow(10.0, 0.05 * 16.0dB) */
+	0x40d5debc,		/* [252] = 6.68e+000 = pow(10.0, 0.05 * 16.5dB) */
+	0x40e28aeb,		/* [253] = 7.08e+000 = pow(10.0, 0.05 * 17.0dB) */
+	0x40eff755,		/* [254] = 7.50e+000 = pow(10.0, 0.05 * 17.5dB) */
+	0x40fe2f5e,		/* [255] = 7.94e+000 = pow(10.0, 0.05 * 18.0dB) */
+};
+
+#define MIXART_DIGITAL_LEVEL_MIN   0      /* -109.5 dB */
+#define MIXART_DIGITAL_LEVEL_MAX   255    /*  18.0 dB */
+#define MIXART_DIGITAL_ZERO_LEVEL  219    /*  0.0 dB */
+
+
+int mixart_update_playback_stream_level(mixart_t* chip, int is_aes, int idx)
+{
+	int err, i;
+	int volume[2];
+	mixart_msg_t request;
+	mixart_set_out_stream_level_req_t set_level;
+	u32 status;
+	mixart_pipe_t *pipe;
+
+	memset(&set_level, 0, sizeof(set_level));
+	set_level.nb_of_stream = 1;
+	set_level.stream_level.desc.stream_idx = idx;
+
+	if(is_aes) {
+		pipe = &chip->pipe_out_dig;	/* AES playback */
+		idx += MIXART_PLAYBACK_STREAMS;
+	} else {
+		pipe = &chip->pipe_out_ana;	/* analog playback */
+	}
+
+	/* only when pipe exists ! */
+	if(pipe->status == PIPE_UNDEFINED)
+		return 0;
+
+	set_level.stream_level.desc.uid_pipe = pipe->group_uid;
+
+	for(i=0; i<2; i++) {
+		if(chip->digital_playback_active[idx][i])
+			volume[i] = chip->digital_playback_volume[idx][i];
+		else
+			volume[i] = MIXART_DIGITAL_LEVEL_MIN;
+	}
+
+	set_level.stream_level.out_level.valid_mask1 = MIXART_OUT_STREAM_SET_LEVEL_LEFT_AUDIO1 | MIXART_OUT_STREAM_SET_LEVEL_RIGHT_AUDIO2;
+	set_level.stream_level.out_level.left_to_out1_level = mixart_digital_level[volume[0]];
+	set_level.stream_level.out_level.right_to_out2_level = mixart_digital_level[volume[1]];
+
+	request.message_id = MSG_STREAM_SET_OUT_STREAM_LEVEL;
+	request.uid = (mixart_uid_t){0,0};
+	request.data = &set_level;
+	request.size = sizeof(set_level);
+
+	err = snd_mixart_send_msg(chip->mgr, &request, sizeof(status), &status);
+	if((err<0) || status) {
+		snd_printk(KERN_DEBUG "error MSG_STREAM_SET_OUT_STREAM_LEVEL card(%d) status(%x)\n", chip->chip_idx, status);
+		return -EINVAL;
+	}
+	return 0;
+}
+
+int mixart_update_capture_stream_level(mixart_t* chip, int is_aes)
+{
+	int err, i, idx;
+	mixart_pipe_t* pipe;
+	mixart_msg_t request;
+	mixart_set_in_audio_level_req_t set_level;
+	u32 status;
+
+	if(is_aes) {
+		idx = 1;
+		pipe = &chip->pipe_in_dig;
+	} else {
+		idx = 0;
+		pipe = &chip->pipe_in_ana;
+	}
+
+	/* only when pipe exists ! */
+	if(pipe->status == PIPE_UNDEFINED)
+		return 0;
+
+	memset(&set_level, 0, sizeof(set_level));
+	set_level.audio_count = 2;
+	set_level.level[0].connector = pipe->uid_left_connector;
+	set_level.level[1].connector = pipe->uid_right_connector;
+
+	for(i=0; i<2; i++) {
+		set_level.level[i].valid_mask1 = MIXART_AUDIO_LEVEL_DIGITAL_MASK;
+		set_level.level[i].digital_level = mixart_digital_level[chip->digital_capture_volume[idx][i]];
+	}
+
+	request.message_id = MSG_STREAM_SET_IN_AUDIO_LEVEL;
+	request.uid = (mixart_uid_t){0,0};
+	request.data = &set_level;
+	request.size = sizeof(set_level);
+
+	err = snd_mixart_send_msg(chip->mgr, &request, sizeof(status), &status);
+	if((err<0) || status) {
+		snd_printk(KERN_DEBUG "error MSG_STREAM_SET_IN_AUDIO_LEVEL card(%d) status(%x)\n", chip->chip_idx, status);
+		return -EINVAL;
+	}
+	return 0;
+}
+
+
+/* shared */
+static int mixart_digital_vol_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
+{
+	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+	uinfo->count = 2;
+	uinfo->value.integer.min = MIXART_DIGITAL_LEVEL_MIN;   /* -109.5 dB */
+	uinfo->value.integer.max = MIXART_DIGITAL_LEVEL_MAX;   /*   18.0 dB */
+	return 0;
+}
+
+#define MIXART_VOL_REC_MASK	1
+#define MIXART_VOL_AES_MASK	2
+
+static int mixart_pcm_vol_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+{
+	mixart_t *chip = snd_kcontrol_chip(kcontrol);
+	int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); /* index */
+	int *stored_volume;
+	int is_capture = kcontrol->private_value & MIXART_VOL_REC_MASK;
+	int is_aes = kcontrol->private_value & MIXART_VOL_AES_MASK;
+	down(&chip->mgr->mixer_mutex);
+	if(is_capture) {
+		if(is_aes)	stored_volume = chip->digital_capture_volume[1];	/* AES capture */
+		else		stored_volume = chip->digital_capture_volume[0];	/* analog capture */
+	} else {
+		snd_assert ( idx < MIXART_PLAYBACK_STREAMS ); 
+		if(is_aes)	stored_volume = chip->digital_playback_volume[MIXART_PLAYBACK_STREAMS + idx]; /* AES playback */
+		else		stored_volume = chip->digital_playback_volume[idx];	/* analog playback */
+	}
+	ucontrol->value.integer.value[0] = stored_volume[0];
+	ucontrol->value.integer.value[1] = stored_volume[1];
+	up(&chip->mgr->mixer_mutex);
+	return 0;
+}
+
+static int mixart_pcm_vol_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+{
+	mixart_t *chip = snd_kcontrol_chip(kcontrol);
+	int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); /* index */
+	int changed = 0;
+	int is_capture = kcontrol->private_value & MIXART_VOL_REC_MASK;
+	int is_aes = kcontrol->private_value & MIXART_VOL_AES_MASK;
+	int* stored_volume;
+	int i;
+	down(&chip->mgr->mixer_mutex);
+	if(is_capture) {
+		if(is_aes)	stored_volume = chip->digital_capture_volume[1];	/* AES capture */
+		else		stored_volume = chip->digital_capture_volume[0];	/* analog capture */
+	} else {
+		snd_assert ( idx < MIXART_PLAYBACK_STREAMS ); 
+		if(is_aes)	stored_volume = chip->digital_playback_volume[MIXART_PLAYBACK_STREAMS + idx]; /* AES playback */
+		else		stored_volume = chip->digital_playback_volume[idx];	/* analog playback */
+	}
+	for(i=0; i<2; i++) {
+		if(stored_volume[i] != ucontrol->value.integer.value[i]) {
+			stored_volume[i] = ucontrol->value.integer.value[i];
+			changed = 1;
+		}
+	}
+	if(changed) {
+		if(is_capture)	mixart_update_capture_stream_level(chip, is_aes);
+		else		mixart_update_playback_stream_level(chip, is_aes, idx);
+	}
+	up(&chip->mgr->mixer_mutex);
+	return changed;
+}
+
+static snd_kcontrol_new_t snd_mixart_pcm_vol =
+{
+	.iface =        SNDRV_CTL_ELEM_IFACE_MIXER,
+	/* name will be filled later */
+	/* count will be filled later */
+	.info =         mixart_digital_vol_info,		/* shared */
+	.get =          mixart_pcm_vol_get,
+	.put =          mixart_pcm_vol_put,
+};
+
+
+static int mixart_pcm_sw_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+{
+	mixart_t *chip = snd_kcontrol_chip(kcontrol);
+	int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); /* index */
+	snd_assert ( idx < MIXART_PLAYBACK_STREAMS ); 
+	down(&chip->mgr->mixer_mutex);
+	if(kcontrol->private_value & MIXART_VOL_AES_MASK)	/* AES playback */
+		idx += MIXART_PLAYBACK_STREAMS;
+	ucontrol->value.integer.value[0] = chip->digital_playback_active[idx][0];
+	ucontrol->value.integer.value[1] = chip->digital_playback_active[idx][1];
+	up(&chip->mgr->mixer_mutex);
+	return 0;
+}
+
+static int mixart_pcm_sw_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+{
+	mixart_t *chip = snd_kcontrol_chip(kcontrol);
+	int changed = 0;
+	int is_aes = kcontrol->private_value & MIXART_VOL_AES_MASK;
+	int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); /* index */
+	int i, j;
+	snd_assert ( idx < MIXART_PLAYBACK_STREAMS ); 
+	down(&chip->mgr->mixer_mutex);
+	j = idx;
+	if(is_aes)	j += MIXART_PLAYBACK_STREAMS;
+	for(i=0; i<2; i++) {
+		if(chip->digital_playback_active[j][i] != ucontrol->value.integer.value[i]) {
+			chip->digital_playback_active[j][i] = ucontrol->value.integer.value[i];
+			changed = 1;
+		}
+	}
+	if(changed)	mixart_update_playback_stream_level(chip, is_aes, idx);
+	up(&chip->mgr->mixer_mutex);
+	return changed;
+}
+
+static snd_kcontrol_new_t mixart_control_pcm_switch = {
+	.iface =	SNDRV_CTL_ELEM_IFACE_MIXER,
+	/* name will be filled later */
+	.count =        MIXART_PLAYBACK_STREAMS,
+	.info =         mixart_sw_info,		/* shared */
+	.get =          mixart_pcm_sw_get,
+	.put =          mixart_pcm_sw_put
+};
+
+static int mixart_update_monitoring(mixart_t* chip, int channel)
+{
+	int err;
+	mixart_msg_t request;
+	mixart_set_out_audio_level_t audio_level;
+	u32 resp;
+
+	if(chip->pipe_out_ana.status == PIPE_UNDEFINED)
+		return -EINVAL; /* no pipe defined */
+
+	if(!channel)	request.uid = chip->pipe_out_ana.uid_left_connector;
+	else		request.uid = chip->pipe_out_ana.uid_right_connector;
+	request.message_id = MSG_CONNECTOR_SET_OUT_AUDIO_LEVEL;
+	request.data = &audio_level;
+	request.size = sizeof(audio_level);
+
+	memset(&audio_level, 0, sizeof(audio_level));
+	audio_level.valid_mask1 = MIXART_AUDIO_LEVEL_MONITOR_MASK | MIXART_AUDIO_LEVEL_MUTE_M1_MASK;
+	audio_level.monitor_level = mixart_digital_level[chip->monitoring_volume[channel!=0]];
+	audio_level.monitor_mute1 = !chip->monitoring_active[channel!=0];
+
+	err = snd_mixart_send_msg(chip->mgr, &request, sizeof(resp), &resp);
+	if((err<0) || resp) {
+		snd_printk(KERN_DEBUG "error MSG_CONNECTOR_SET_OUT_AUDIO_LEVEL card(%d) resp(%x)\n", chip->chip_idx, resp);
+		return -EINVAL;
+	}
+	return 0;
+}
+
+/*
+ * monitoring level control
+ */
+
+static int mixart_monitor_vol_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+{
+	mixart_t *chip = snd_kcontrol_chip(kcontrol);
+	down(&chip->mgr->mixer_mutex);
+	ucontrol->value.integer.value[0] = chip->monitoring_volume[0];
+	ucontrol->value.integer.value[1] = chip->monitoring_volume[1];
+	up(&chip->mgr->mixer_mutex);
+	return 0;
+}
+
+static int mixart_monitor_vol_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+{
+	mixart_t *chip = snd_kcontrol_chip(kcontrol);
+	int changed = 0;
+	int i;
+	down(&chip->mgr->mixer_mutex);
+	for(i=0; i<2; i++) {
+		if(chip->monitoring_volume[i] != ucontrol->value.integer.value[i]) {
+			chip->monitoring_volume[i] = ucontrol->value.integer.value[i];
+			mixart_update_monitoring(chip, i);
+			changed = 1;
+		}
+	}
+	up(&chip->mgr->mixer_mutex);
+	return changed;
+}
+
+static snd_kcontrol_new_t mixart_control_monitor_vol = {
+	.iface =	SNDRV_CTL_ELEM_IFACE_MIXER,
+	.name =         "Monitoring Volume",
+	.info =		mixart_digital_vol_info,		/* shared */
+	.get =		mixart_monitor_vol_get,
+	.put =		mixart_monitor_vol_put,
+};
+
+/*
+ * monitoring switch control
+ */
+
+static int mixart_monitor_sw_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+{
+	mixart_t *chip = snd_kcontrol_chip(kcontrol);
+	down(&chip->mgr->mixer_mutex);
+	ucontrol->value.integer.value[0] = chip->monitoring_active[0];
+	ucontrol->value.integer.value[1] = chip->monitoring_active[1];
+	up(&chip->mgr->mixer_mutex);
+	return 0;
+}
+
+static int mixart_monitor_sw_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+{
+	mixart_t *chip = snd_kcontrol_chip(kcontrol);
+	int changed = 0;
+	int i;
+	down(&chip->mgr->mixer_mutex);
+	for(i=0; i<2; i++) {
+		if(chip->monitoring_active[i] != ucontrol->value.integer.value[i]) {
+			chip->monitoring_active[i] = ucontrol->value.integer.value[i];
+			changed |= (1<<i); /* mask 0x01 ans 0x02 */
+		}
+	}
+	if(changed) {
+		/* allocate or release resources for monitoring */
+		int allocate = chip->monitoring_active[0] || chip->monitoring_active[1];
+		if(allocate) {
+			snd_mixart_add_ref_pipe( chip, MIXART_PCM_ANALOG, 0, 1);	/* allocate the playback pipe for monitoring */
+			snd_mixart_add_ref_pipe( chip, MIXART_PCM_ANALOG, 1, 1);	/* allocate the capture pipe for monitoring */
+		}
+		if(changed & 0x01)	mixart_update_monitoring(chip, 0);
+		if(changed & 0x02)	mixart_update_monitoring(chip, 1);
+		if(!allocate) {
+			snd_mixart_kill_ref_pipe( chip->mgr, &chip->pipe_in_ana, 1);	/* release the capture pipe for monitoring */
+			snd_mixart_kill_ref_pipe( chip->mgr, &chip->pipe_out_ana, 1);	/* release the playback pipe for monitoring */
+		}
+	}
+
+	up(&chip->mgr->mixer_mutex);
+	return (changed != 0);
+}
+
+static snd_kcontrol_new_t mixart_control_monitor_sw = {
+	.iface =	SNDRV_CTL_ELEM_IFACE_MIXER,
+	.name =         "Monitoring Switch",
+	.info =         mixart_sw_info,		/* shared */
+	.get =          mixart_monitor_sw_get,
+	.put =          mixart_monitor_sw_put
+};
+
+
+static void mixart_reset_audio_levels(mixart_t *chip)
+{
+	/* analog volumes can be set even if there is no pipe */
+	mixart_update_analog_audio_level(chip, 0);
+	/* analog levels for capture only on the first two chips */
+	if(chip->chip_idx < 2) {
+		mixart_update_analog_audio_level(chip, 1);
+	}
+	return;
+}
+
+
+int snd_mixart_create_mixer(mixart_mgr_t *mgr)
+{
+	mixart_t *chip;
+	int err, i;
+
+	init_MUTEX(&mgr->mixer_mutex); /* can be in another place */
+
+	for(i=0; i<mgr->num_cards; i++) {
+		snd_kcontrol_new_t temp;
+		chip = mgr->chip[i];
+
+		/* analog output level control */
+		temp = mixart_control_analog_level;
+		temp.name = "Master Playback Volume";
+		temp.private_value = 0; /* playback */
+		if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&temp, chip))) < 0)
+			return err;
+		/* output mute controls */
+		if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&mixart_control_output_switch, chip))) < 0)
+			return err;
+
+		/* analog input level control only on first two chips !*/
+		if(i<2) {
+			temp = mixart_control_analog_level;
+			temp.name = "Master Capture Volume";
+			temp.private_value = 1; /* capture */
+			if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&temp, chip))) < 0)
+				return err;
+		}
+
+		temp = snd_mixart_pcm_vol;
+		temp.name = "PCM Playback Volume";
+		temp.count = MIXART_PLAYBACK_STREAMS;
+		temp.private_value = 0; /* playback analog */
+		if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&temp, chip))) < 0)
+			return err;
+
+		temp.name = "PCM Capture Volume";
+		temp.count = 1;
+		temp.private_value = MIXART_VOL_REC_MASK; /* capture analog */
+		if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&temp, chip))) < 0)
+			return err;
+
+		if(mgr->board_type == MIXART_DAUGHTER_TYPE_AES) {
+			temp.name = "AES Playback Volume";
+			temp.count = MIXART_PLAYBACK_STREAMS;
+			temp.private_value = MIXART_VOL_AES_MASK; /* playback AES/EBU */
+			if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&temp, chip))) < 0)
+				return err;
+
+			temp.name = "AES Capture Volume";
+			temp.count = 0;
+			temp.private_value = MIXART_VOL_REC_MASK | MIXART_VOL_AES_MASK; /* capture AES/EBU */
+			if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&temp, chip))) < 0)
+				return err;
+		}
+		temp = mixart_control_pcm_switch;
+		temp.name = "PCM Playback Switch";
+		temp.private_value = 0; /* playback analog */
+		if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&temp, chip))) < 0)
+			return err;
+
+		if(mgr->board_type == MIXART_DAUGHTER_TYPE_AES) {
+			temp.name = "AES Playback Switch";
+			temp.private_value = MIXART_VOL_AES_MASK; /* playback AES/EBU */
+			if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&temp, chip))) < 0)
+				return err;
+		}
+
+		/* monitoring */
+		if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&mixart_control_monitor_vol, chip))) < 0)
+			return err;
+		if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&mixart_control_monitor_sw, chip))) < 0)
+			return err;
+
+		/* init all mixer data and program the master volumes/switches */
+		mixart_reset_audio_levels(chip);
+	}
+	return 0;
+}
--- diff/sound/pci/mixart/mixart_mixer.h	1970-01-01 01:00:00.000000000 +0100
+++ source/sound/pci/mixart/mixart_mixer.h	2004-02-23 13:56:48.000000000 +0000
@@ -0,0 +1,31 @@
+/*
+ * Driver for Digigram miXart soundcards
+ *
+ * include file for mixer
+ *
+ * Copyright (c) 2003 by Digigram <alsa@digigram.com>
+ *
+ *   This program is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License as published by
+ *   the Free Software Foundation; either version 2 of the License, or
+ *   (at your option) any later version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ */
+
+#ifndef __SOUND_MIXART_MIXER_H
+#define __SOUND_MIXART_MIXER_H
+
+/* exported */
+int mixart_update_playback_stream_level(mixart_t* chip, int is_aes, int idx);
+int mixart_update_capture_stream_level(mixart_t* chip, int is_aes);
+int snd_mixart_create_mixer(mixart_mgr_t* mgr);
+
+#endif /* __SOUND_MIXART_MIXER_H */
--- diff/arch/cris/arch-v10/output_arch.ld	2003-07-11 09:39:49.000000000 +0100
+++ source/arch/cris/arch-v10/output_arch.ld	1970-01-01 01:00:00.000000000 +0100
@@ -1,2 +0,0 @@
-/* At the time of this writing, there's no equivalent ld option. */
-OUTPUT_ARCH (cris)
--- diff/arch/m68k/kernel/m68k_defs.c	2003-08-20 14:16:08.000000000 +0100
+++ source/arch/m68k/kernel/m68k_defs.c	1970-01-01 01:00:00.000000000 +0100
@@ -1,109 +0,0 @@
-/*
- * This program is used to generate definitions needed by
- * assembly language modules.
- *
- * We use the technique used in the OSF Mach kernel code:
- * generate asm statements containing #defines,
- * compile this file to assembler, and then extract the
- * #defines from the assembly-language output.
- */
-
-#include <linux/stddef.h>
-#include <linux/sched.h>
-#include <linux/kernel_stat.h>
-#include <asm/bootinfo.h>
-#include <asm/irq.h>
-#include <asm/amigahw.h>
-#include <linux/font.h>
-
-#define DEFINE(sym, val) \
-	asm volatile("\n#define " #sym " %c0" : : "i" (val))
-
-int main(void)
-{
-	/* offsets into the task struct */
-	DEFINE(TASK_STATE, offsetof(struct task_struct, state));
-	DEFINE(TASK_FLAGS, offsetof(struct task_struct, flags));
-	DEFINE(TASK_PTRACE, offsetof(struct task_struct, ptrace));
-	DEFINE(TASK_WORK, offsetof(struct task_struct, thread.work));
-	DEFINE(TASK_NEEDRESCHED, offsetof(struct task_struct, thread.work.need_resched));
-	DEFINE(TASK_SYSCALL_TRACE, offsetof(struct task_struct, thread.work.syscall_trace));
-	DEFINE(TASK_SIGPENDING, offsetof(struct task_struct, thread.work.sigpending));
-	DEFINE(TASK_NOTIFY_RESUME, offsetof(struct task_struct, thread.work.notify_resume));
-	DEFINE(TASK_THREAD, offsetof(struct task_struct, thread));
-	DEFINE(TASK_MM, offsetof(struct task_struct, mm));
-	DEFINE(TASK_ACTIVE_MM, offsetof(struct task_struct, active_mm));
-
-	/* offsets into the thread struct */
-	DEFINE(THREAD_KSP, offsetof(struct thread_struct, ksp));
-	DEFINE(THREAD_USP, offsetof(struct thread_struct, usp));
-	DEFINE(THREAD_SR, offsetof(struct thread_struct, sr));
-	DEFINE(THREAD_FS, offsetof(struct thread_struct, fs));
-	DEFINE(THREAD_CRP, offsetof(struct thread_struct, crp));
-	DEFINE(THREAD_ESP0, offsetof(struct thread_struct, esp0));
-	DEFINE(THREAD_FPREG, offsetof(struct thread_struct, fp));
-	DEFINE(THREAD_FPCNTL, offsetof(struct thread_struct, fpcntl));
-	DEFINE(THREAD_FPSTATE, offsetof(struct thread_struct, fpstate));
-
-	/* offsets into the pt_regs */
-	DEFINE(PT_D0, offsetof(struct pt_regs, d0));
-	DEFINE(PT_ORIG_D0, offsetof(struct pt_regs, orig_d0));
-	DEFINE(PT_D1, offsetof(struct pt_regs, d1));
-	DEFINE(PT_D2, offsetof(struct pt_regs, d2));
-	DEFINE(PT_D3, offsetof(struct pt_regs, d3));
-	DEFINE(PT_D4, offsetof(struct pt_regs, d4));
-	DEFINE(PT_D5, offsetof(struct pt_regs, d5));
-	DEFINE(PT_A0, offsetof(struct pt_regs, a0));
-	DEFINE(PT_A1, offsetof(struct pt_regs, a1));
-	DEFINE(PT_A2, offsetof(struct pt_regs, a2));
-	DEFINE(PT_PC, offsetof(struct pt_regs, pc));
-	DEFINE(PT_SR, offsetof(struct pt_regs, sr));
-	/* bitfields are a bit difficult */
-	DEFINE(PT_VECTOR, offsetof(struct pt_regs, pc) + 4);
-
-	/* offsets into the irq_handler struct */
-	DEFINE(IRQ_HANDLER, offsetof(struct irq_node, handler));
-	DEFINE(IRQ_DEVID, offsetof(struct irq_node, dev_id));
-	DEFINE(IRQ_NEXT, offsetof(struct irq_node, next));
-
-	/* offsets into the kernel_stat struct */
-	DEFINE(STAT_IRQ, offsetof(struct kernel_stat, irqs));
-
-	/* offsets into the irq_cpustat_t struct */
-	DEFINE(CPUSTAT_SOFTIRQ_PENDING, offsetof(irq_cpustat_t, __softirq_pending));
-
-	/* offsets into the bi_record struct */
-	DEFINE(BIR_TAG, offsetof(struct bi_record, tag));
-	DEFINE(BIR_SIZE, offsetof(struct bi_record, size));
-	DEFINE(BIR_DATA, offsetof(struct bi_record, data));
-
-	/* offsets into font_desc (drivers/video/console/font.h) */
-	DEFINE(FONT_DESC_IDX, offsetof(struct font_desc, idx));
-	DEFINE(FONT_DESC_NAME, offsetof(struct font_desc, name));
-	DEFINE(FONT_DESC_WIDTH, offsetof(struct font_desc, width));
-	DEFINE(FONT_DESC_HEIGHT, offsetof(struct font_desc, height));
-	DEFINE(FONT_DESC_DATA, offsetof(struct font_desc, data));
-	DEFINE(FONT_DESC_PREF, offsetof(struct font_desc, pref));
-
-	/* signal defines */
-	DEFINE(SIGSEGV, SIGSEGV);
-	DEFINE(SEGV_MAPERR, SEGV_MAPERR);
-	DEFINE(SIGTRAP, SIGTRAP);
-	DEFINE(TRAP_TRACE, TRAP_TRACE);
-
-	/* offsets into the custom struct */
-	DEFINE(CUSTOMBASE, &custom);
-	DEFINE(C_INTENAR, offsetof(struct CUSTOM, intenar));
-	DEFINE(C_INTREQR, offsetof(struct CUSTOM, intreqr));
-	DEFINE(C_INTENA, offsetof(struct CUSTOM, intena));
-	DEFINE(C_INTREQ, offsetof(struct CUSTOM, intreq));
-	DEFINE(C_SERDATR, offsetof(struct CUSTOM, serdatr));
-	DEFINE(C_SERDAT, offsetof(struct CUSTOM, serdat));
-	DEFINE(C_SERPER, offsetof(struct CUSTOM, serper));
-	DEFINE(CIAABASE, &ciaa);
-	DEFINE(CIABBASE, &ciab);
-	DEFINE(C_PRA, offsetof(struct CIA, pra));
-	DEFINE(ZTWOBASE, zTwoBase);
-
-	return 0;
-}
--- diff/arch/m68k/kernel/m68k_defs.head	2002-10-16 04:27:54.000000000 +0100
+++ source/arch/m68k/kernel/m68k_defs.head	1970-01-01 01:00:00.000000000 +0100
@@ -1,5 +0,0 @@
-/*
- * WARNING! This file is automatically generated - DO NOT EDIT!
- */
-
-#define TS_MAGICKEY	0x5a5a5a5a
--- diff/arch/mips/au1000/common/rtc.c	2003-07-08 09:55:17.000000000 +0100
+++ source/arch/mips/au1000/common/rtc.c	1970-01-01 01:00:00.000000000 +0100
@@ -1,37 +0,0 @@
-/*
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * RTC routines for PC style attached Dallas chip.
- *
- * Copyright (C) 1998, 2001 by Ralf Baechle
- */
-#include <linux/mc146818rtc.h>
-#include <asm/io.h>
-#include <asm/au1000.h>
-
-#define PB1500_RTC_ADDR 0xAC000000
-
-unsigned char std_rtc_read_data(unsigned long offset)
-{
-	offset <<= 2;
-	return (u8)(au_readl(offset + PB1500_RTC_ADDR) & 0xff);
-}
-
-static void std_rtc_write_data(unsigned char data, unsigned long offset)
-{
-	offset <<= 2;
-	au_writel(data, offset + PB1500_RTC_ADDR);
-}
-
-static int std_rtc_bcd_mode(void)
-{
-	return 1;
-}
-
-struct rtc_ops pb1500_rtc_ops = {
-	&std_rtc_read_data,
-	&std_rtc_write_data,
-	&std_rtc_bcd_mode
-};
--- diff/arch/mips/au1000/db1x00/setup.c	2003-07-08 09:55:17.000000000 +0100
+++ source/arch/mips/au1000/db1x00/setup.c	1970-01-01 01:00:00.000000000 +0100
@@ -1,230 +0,0 @@
-/*
- *
- * BRIEF MODULE DESCRIPTION
- *	Alchemy Db1000 board setup.
- *
- * Copyright 2000 MontaVista Software Inc.
- * Author: MontaVista Software, Inc.
- *         	ppopov@mvista.com or source@mvista.com
- *
- *  This program is free software; you can redistribute  it and/or modify it
- *  under  the terms of  the GNU General  Public License as published by the
- *  Free Software Foundation;  either version 2 of the  License, or (at your
- *  option) any later version.
- *
- *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
- *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
- *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
- *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
- *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
- *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- *  You should have received a copy of the  GNU General Public License along
- *  with this program; if not, write  to the Free Software Foundation, Inc.,
- *  675 Mass Ave, Cambridge, MA 02139, USA.
- */
-#include <linux/config.h>
-#include <linux/init.h>
-#include <linux/sched.h>
-#include <linux/ioport.h>
-#include <linux/mm.h>
-#include <linux/console.h>
-#include <linux/mc146818rtc.h>
-#include <linux/delay.h>
-
-#include <asm/cpu.h>
-#include <asm/bootinfo.h>
-#include <asm/irq.h>
-#include <asm/keyboard.h>
-#include <asm/mipsregs.h>
-#include <asm/reboot.h>
-#include <asm/pgtable.h>
-#include <asm/au1000.h>
-#include <asm/db1x00.h>
-
-#ifdef CONFIG_BLK_DEV_INITRD
-extern unsigned long initrd_start, initrd_end;
-extern void * __rd_start, * __rd_end;
-#endif
-
-#ifdef CONFIG_BLK_DEV_IDE
-extern struct ide_ops std_ide_ops;
-extern struct ide_ops *ide_ops;
-#endif
-
-extern struct rtc_ops no_rtc_ops;
-extern char * __init prom_getcmdline(void);
-extern void au1000_restart(char *);
-extern void au1000_halt(void);
-extern void au1000_power_off(void);
-extern struct resource ioport_resource;
-extern struct resource iomem_resource;
-#if defined(CONFIG_64BIT_PHYS_ADDR) && defined(CONFIG_SOC_AU1500)
-extern phys_t (*fixup_bigphys_addr)(phys_t phys_addr, phys_t size);
-static phys_t db_fixup_bigphys_addr(phys_t phys_addr, phys_t size);
-#endif
-
-void __init au1x00_setup(void)
-{
-	char *argptr;
-	u32 pin_func, static_cfg0;
-	u32 sys_freqctrl, sys_clksrc;
-	u32 prid = read_c0_prid();
-
-	argptr = prom_getcmdline();
-
-	/* Various early Au1000 Errata corrected by this */
-	set_c0_config(1<<19); /* Config[OD] */
-
-#ifdef CONFIG_AU1X00_SERIAL_CONSOLE
-	if ((argptr = strstr(argptr, "console=")) == NULL) {
-		argptr = prom_getcmdline();
-		strcat(argptr, " console=ttyS0,115200");
-	}
-#endif	  
-
-#ifdef CONFIG_FB_AU1100
-    if ((argptr = strstr(argptr, "video=")) == NULL) {
-        argptr = prom_getcmdline();
-        /* default panel */
-        //strcat(argptr, " video=au1100fb:panel:Sharp_320x240_16");
-        strcat(argptr, " video=au1100fb:panel:s10,nohwcursor");
-    }
-#endif
-
-#if defined(CONFIG_SOUND_AU1X00) && !defined(CONFIG_SOC_AU1000)
-	// au1000 does not support vra, au1500 and au1100 do
-	strcat(argptr, " au1000_audio=vra");
-	argptr = prom_getcmdline();
-#endif
-
-	rtc_ops = &no_rtc_ops;
-	_machine_restart = au1000_restart;
-	_machine_halt = au1000_halt;
-	_machine_power_off = au1000_power_off;
-#if defined(CONFIG_64BIT_PHYS_ADDR) && defined(CONFIG_SOC_AU1500)
-	fixup_bigphys_addr = db_fixup_bigphys_addr;
-#endif
-
-	// IO/MEM resources. 
-	set_io_port_base(0);
-#ifdef CONFIG_SOC_AU1500
-	ioport_resource.start = 0x00000000;
-#else
-	/* don't allow any legacy ports probing */
-	ioport_resource.start = 0x10000000;
-#endif
-	ioport_resource.end = 0xffffffff;
-	iomem_resource.start = 0x10000000;
-	iomem_resource.end = 0xffffffff;
-
-#ifdef CONFIG_BLK_DEV_INITRD
-	ROOT_DEV = MKDEV(RAMDISK_MAJOR, 0);
-	initrd_start = (unsigned long)&__rd_start;
-	initrd_end = (unsigned long)&__rd_end;
-#endif
-
-	//
-	// NOTE:
-	//
-	// YAMON (specifically reset_db1500.s) enables 32khz osc
-	// YAMON (specifically reset_db1x00.s) setups all clocking and GPIOs
-	// YAMON (specifically reset_db1500.s) setups all PCI
-	//
-
-#if defined (CONFIG_USB_OHCI) || defined (CONFIG_AU1X00_USB_DEVICE)
-#ifdef CONFIG_USB_OHCI
-	if ((argptr = strstr(argptr, "usb_ohci=")) == NULL) {
-	        char usb_args[80];
-		argptr = prom_getcmdline();
-		memset(usb_args, 0, sizeof(usb_args));
-		sprintf(usb_args, " usb_ohci=base:0x%x,len:0x%x,irq:%d",
-			USB_OHCI_BASE, USB_OHCI_LEN, AU1000_USB_HOST_INT);
-		strcat(argptr, usb_args);
-	}
-#endif
-
-#ifdef CONFIG_USB_OHCI
-	// enable host controller and wait for reset done
-	au_writel(0x08, USB_HOST_CONFIG);
-	udelay(1000);
-	au_writel(0x0E, USB_HOST_CONFIG);
-	udelay(1000);
-	au_readl(USB_HOST_CONFIG); // throw away first read
-	while (!(au_readl(USB_HOST_CONFIG) & 0x10))
-		au_readl(USB_HOST_CONFIG);
-#endif
-
-#ifdef CONFIG_AU1X00_USB_DEVICE
-	// 2nd USB port is USB device
-	pin_func = au_readl(SYS_PINFUNC) & (u32)(~0x8000);
-	au_writel(pin_func, SYS_PINFUNC);
-#endif
-
-#endif // defined (CONFIG_USB_OHCI) || defined (CONFIG_AU1X00_USB_DEVICE)
-
-#ifdef CONFIG_FB
-	// Needed if PCI video card in use
-	conswitchp = &dummy_con;
-#endif
-
-#ifndef CONFIG_SERIAL_NONSTANDARD
-	/* don't touch the default serial console */
-        au_writel(0, UART_ADDR + UART_CLK);
-#endif
-	//au_writel(0, UART3_ADDR + UART_CLK);
-
-#ifdef CONFIG_BLK_DEV_IDE
-	ide_ops = &std_ide_ops;
-#endif
-
-#if 0
-	//// FIX!!! must be valid for au1000, au1500 and au1100
-	/* Enable Au1000 BCLK switching */
-	switch (prid & 0x000000FF)
-	{
-	case 0x00: /* DA */
-	case 0x01: /* HA */
-	case 0x02: /* HB */
-		break;
-	default:  /* HC and newer */
-		au_writel(0x00000060, 0xb190003c);
-		break;
-	}
-#endif
-
-	au_writel(0, 0xAE000010); /* turn off pcmcia power */
-
-#ifdef CONFIG_MIPS_DB1000
-    printk("AMD Alchemy Au1000/Db1000 Board\n");
-#endif
-#ifdef CONFIG_MIPS_DB1500
-    printk("AMD Alchemy Au1500/Db1500 Board\n");
-#endif
-#ifdef CONFIG_MIPS_DB1100
-    printk("AMD Alchemy Au1100/Db1100 Board\n");
-#endif
-}
-
-#if defined(CONFIG_64BIT_PHYS_ADDR) && defined(CONFIG_SOC_AU1500)
-static phys_t db_fixup_bigphys_addr(phys_t phys_addr, phys_t size)
-{
-	u32 pci_start = (u32)Au1500_PCI_MEM_START;
-	u32 pci_end = (u32)Au1500_PCI_MEM_END;
-
-	/* Don't fixup 36 bit addresses */
-	if ((phys_addr >> 32) != 0) return phys_addr;
-
-	/* check for pci memory window */
-	if ((phys_addr >= pci_start) && ((phys_addr + size) < pci_end)) {
-		return (phys_t)((phys_addr - pci_start) +
-				     Au1500_PCI_MEM_START);
-	}
-	else 
-		return phys_addr;
-}
-#endif
--- diff/arch/mips/au1000/pb1000/setup.c	2003-07-08 09:55:17.000000000 +0100
+++ source/arch/mips/au1000/pb1000/setup.c	1970-01-01 01:00:00.000000000 +0100
@@ -1,301 +0,0 @@
-/*
- *
- * BRIEF MODULE DESCRIPTION
- *	Alchemy Pb1000 board setup.
- *
- * Copyright 2000 MontaVista Software Inc.
- * Author: MontaVista Software, Inc.
- *         	ppopov@mvista.com or source@mvista.com
- *
- *  This program is free software; you can redistribute  it and/or modify it
- *  under  the terms of  the GNU General  Public License as published by the
- *  Free Software Foundation;  either version 2 of the  License, or (at your
- *  option) any later version.
- *
- *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
- *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
- *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
- *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
- *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
- *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- *  You should have received a copy of the  GNU General Public License along
- *  with this program; if not, write  to the Free Software Foundation, Inc.,
- *  675 Mass Ave, Cambridge, MA 02139, USA.
- */
-#include <linux/config.h>
-#include <linux/init.h>
-#include <linux/sched.h>
-#include <linux/ioport.h>
-#include <linux/mm.h>
-#include <linux/console.h>
-#include <linux/mc146818rtc.h>
-#include <linux/major.h>
-#include <linux/kdev_t.h>
-#include <linux/root_dev.h>
-#include <linux/delay.h>
-
-#include <asm/cpu.h>
-#include <asm/bootinfo.h>
-#include <asm/irq.h>
-#include <asm/mipsregs.h>
-#include <asm/reboot.h>
-#include <asm/pgtable.h>
-#include <asm/au1000.h>
-#include <asm/pb1000.h>
-
-#ifdef CONFIG_USB_OHCI
-// Enable the workaround for the OHCI DoneHead
-// register corruption problem.
-#define CONFIG_AU1000_OHCI_FIX
-#endif
-
-#if defined(CONFIG_AU1X00_SERIAL_CONSOLE)
-char serial_console[20];
-#endif
-
-#ifdef CONFIG_BLK_DEV_INITRD
-extern unsigned long initrd_start, initrd_end;
-extern void * __rd_start, * __rd_end;
-#endif
-
-#ifdef CONFIG_BLK_DEV_IDE
-extern struct ide_ops std_ide_ops;
-extern struct ide_ops *ide_ops;
-#endif
-
-extern struct rtc_ops no_rtc_ops;
-extern char * __init prom_getcmdline(void);
-extern void au1000_restart(char *);
-extern void au1000_halt(void);
-extern void au1000_power_off(void);
-extern struct resource ioport_resource;
-extern struct resource iomem_resource;
-
-void __init au1x00_setup(void)
-{
-	char *argptr;
-	u32 pin_func, static_cfg0;
-	u32 sys_freqctrl, sys_clksrc;
-	u32 prid = read_c0_prid();
-
-	argptr = prom_getcmdline();
-
-	/* Various early Au1000 Errata corrected by this */
-	set_c0_config(1<<19); /* Config[OD] */
-
-#ifdef CONFIG_AU1X00_SERIAL_CONSOLE
-	if ((argptr = strstr(argptr, "console=")) == NULL) {
-		argptr = prom_getcmdline();
-		strcat(argptr, " console=ttyS0,115200");
-	}
-#endif
-
-	rtc_ops = &no_rtc_ops;
-	_machine_restart = au1000_restart;
-	_machine_halt = au1000_halt;
-	_machine_power_off = au1000_power_off;
-
-	// IO/MEM resources.
-	set_io_port_base(0);
-	ioport_resource.start = 0x10000000;
-	ioport_resource.end = 0xffffffff;
-	iomem_resource.start = 0x10000000;
-	iomem_resource.end = 0xffffffff;
-
-#ifdef CONFIG_BLK_DEV_INITRD
-	ROOT_DEV = Root_RAM0;
-	initrd_start = (unsigned long)&__rd_start;
-	initrd_end = (unsigned long)&__rd_end;
-#endif
-
-	// set AUX clock to 12MHz * 8 = 96 MHz
-	au_writel(8, SYS_AUXPLL);
-	au_writel(0, SYS_PINSTATERD);
-	udelay(100);
-
-#if defined (CONFIG_USB_OHCI) || defined (CONFIG_AU1X00_USB_DEVICE)
-#ifdef CONFIG_USB_OHCI
-	if ((argptr = strstr(argptr, "usb_ohci=")) == NULL) {
-	        char usb_args[80];
-		argptr = prom_getcmdline();
-		memset(usb_args, 0, sizeof(usb_args));
-		sprintf(usb_args, " usb_ohci=base:0x%x,len:0x%x,irq:%d",
-			USB_OHCI_BASE, USB_OHCI_LEN, AU1000_USB_HOST_INT);
-		strcat(argptr, usb_args);
-	}
-#endif
-
-	/* zero and disable FREQ2 */
-	sys_freqctrl = au_readl(SYS_FREQCTRL0);
-	sys_freqctrl &= ~0xFFF00000;
-	au_writel(sys_freqctrl, SYS_FREQCTRL0);
-
-	/* zero and disable USBH/USBD clocks */
-	sys_clksrc = au_readl(SYS_CLKSRC);
-	sys_clksrc &= ~0x00007FE0;
-	au_writel(sys_clksrc, SYS_CLKSRC);
-
-	sys_freqctrl = au_readl(SYS_FREQCTRL0);
-	sys_freqctrl &= ~0xFFF00000;
-
-	sys_clksrc = au_readl(SYS_CLKSRC);
-	sys_clksrc &= ~0x00007FE0;
-
-	switch (prid & 0x000000FF)
-	{
-	case 0x00: /* DA */
-	case 0x01: /* HA */
-	case 0x02: /* HB */
-	/* CPU core freq to 48MHz to slow it way down... */
-	au_writel(4, SYS_CPUPLL);
-
-	/*
-	 * Setup 48MHz FREQ2 from CPUPLL for USB Host
-	 */
-	/* FRDIV2=3 -> div by 8 of 384MHz -> 48MHz */
-	sys_freqctrl |= ((3<<22) | (1<<21) | (0<<20));
-	au_writel(sys_freqctrl, SYS_FREQCTRL0);
-
-	/* CPU core freq to 384MHz */
-	au_writel(0x20, SYS_CPUPLL);
-
-	printk("Au1000: 48MHz OHCI workaround enabled\n");
-		break;
-
-	default:  /* HC and newer */
-	// FREQ2 = aux/2 = 48 MHz
-	sys_freqctrl |= ((0<<22) | (1<<21) | (1<<20));
-	au_writel(sys_freqctrl, SYS_FREQCTRL0);
-		break;
-	}
-
-	/*
-	 * Route 48MHz FREQ2 into USB Host and/or Device
-	 */
-#ifdef CONFIG_USB_OHCI
-	sys_clksrc |= ((4<<12) | (0<<11) | (0<<10));
-#endif
-#ifdef CONFIG_AU1X00_USB_DEVICE
-	sys_clksrc |= ((4<<7) | (0<<6) | (0<<5));
-#endif
-	au_writel(sys_clksrc, SYS_CLKSRC);
-
-#ifdef CONFIG_USB_OHCI
-	// enable host controller and wait for reset done
-	au_writel(0x08, USB_HOST_CONFIG);
-	udelay(1000);
-	au_writel(0x0E, USB_HOST_CONFIG);
-	udelay(1000);
-	au_readl(USB_HOST_CONFIG); // throw away first read
-	while (!(au_readl(USB_HOST_CONFIG) & 0x10))
-		au_readl(USB_HOST_CONFIG);
-#endif
-
-	// configure pins GPIO[14:9] as GPIO
-	pin_func = au_readl(SYS_PINFUNC) & (u32)(~0x8080);
-
-#ifndef CONFIG_AU1X00_USB_DEVICE
-	// 2nd USB port is USB host
-	pin_func |= 0x8000;
-#endif
-	au_writel(pin_func, SYS_PINFUNC);
-	au_writel(0x2800, SYS_TRIOUTCLR);
-	au_writel(0x0030, SYS_OUTPUTCLR);
-#endif // defined (CONFIG_USB_OHCI) || defined (CONFIG_AU1X00_USB_DEVICE)
-
-	// make gpio 15 an input (for interrupt line)
-	pin_func = au_readl(SYS_PINFUNC) & (u32)(~0x100);
-	// we don't need I2S, so make it available for GPIO[31:29]
-	pin_func |= (1<<5);
-	au_writel(pin_func, SYS_PINFUNC);
-
-	au_writel(0x8000, SYS_TRIOUTCLR);
-
-#ifdef CONFIG_FB
-	conswitchp = &dummy_con;
-#endif
-
-	static_cfg0 = au_readl(MEM_STCFG0) & (u32)(~0xc00);
-	au_writel(static_cfg0, MEM_STCFG0);
-
-	// configure RCE2* for LCD
-	au_writel(0x00000004, MEM_STCFG2);
-
-	// MEM_STTIME2
-	au_writel(0x09000000, MEM_STTIME2);
-
-	// Set 32-bit base address decoding for RCE2*
-	au_writel(0x10003ff0, MEM_STADDR2);
-
-	// PCI CPLD setup
-	// expand CE0 to cover PCI
-	au_writel(0x11803e40, MEM_STADDR1);
-
-	// burst visibility on
-	au_writel(au_readl(MEM_STCFG0) | 0x1000, MEM_STCFG0);
-
-	au_writel(0x83, MEM_STCFG1);         // ewait enabled, flash timing
-	au_writel(0x33030a10, MEM_STTIME1);   // slower timing for FPGA
-
-	/* setup the static bus controller */
-	au_writel(0x00000002, MEM_STCFG3);  /* type = PCMCIA */
-	au_writel(0x280E3D07, MEM_STTIME3); /* 250ns cycle time */
-	au_writel(0x10000000, MEM_STADDR3); /* any PCMCIA select */
-
-#ifdef CONFIG_FB_E1356
-	if ((argptr = strstr(argptr, "video=")) == NULL) {
-		argptr = prom_getcmdline();
-		strcat(argptr, " video=e1356fb:system:pb1000,mmunalign:1");
-	}
-#endif // CONFIG_FB_E1356
-
-
-#ifdef CONFIG_PCI
-	au_writel(0, PCI_BRIDGE_CONFIG); // set extend byte to 0
-	au_writel(0, SDRAM_MBAR);        // set mbar to 0
-	au_writel(0x2, SDRAM_CMD);       // enable memory accesses
-	au_sync_delay(1);
-#endif
-
-#ifndef CONFIG_SERIAL_NONSTANDARD
-	/* don't touch the default serial console */
-	au_writel(0, UART0_ADDR + UART_CLK);
-#endif
-	au_writel(0, UART1_ADDR + UART_CLK);
-	au_writel(0, UART2_ADDR + UART_CLK);
-	au_writel(0, UART3_ADDR + UART_CLK);
-
-#ifdef CONFIG_BLK_DEV_IDE
-	ide_ops = &std_ide_ops;
-#endif
-
-	// setup irda clocks
-	// aux clock, divide by 2, clock from 2/4 divider
-	au_writel(au_readl(SYS_CLKSRC) | 0x7, SYS_CLKSRC);
-	pin_func = au_readl(SYS_PINFUNC) & (u32)(~(1<<2)); // clear IRTXD
-	au_writel(pin_func, SYS_PINFUNC);
-
-	while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_E0S);
-	au_writel(SYS_CNTRL_E0 | SYS_CNTRL_EN0, SYS_COUNTER_CNTRL);
-	au_sync();
-	while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_T0S);
-	au_writel(0, SYS_TOYTRIM);
-
-	/* Enable Au1000 BCLK switching - note: sed1356 must not use
-	 * its BCLK (Au1000 LCLK) for any timings */
-	switch (prid & 0x000000FF)
-	{
-	case 0x00: /* DA */
-	case 0x01: /* HA */
-	case 0x02: /* HB */
-		break;
-	default:  /* HC and newer */
-		au_writel(0x00000060, 0xb190003c);
-		break;
-	}
-}
--- diff/arch/mips/au1000/pb1100/setup.c	2003-07-08 09:55:17.000000000 +0100
+++ source/arch/mips/au1000/pb1100/setup.c	1970-01-01 01:00:00.000000000 +0100
@@ -1,248 +0,0 @@
-/*
- *
- * BRIEF MODULE DESCRIPTION
- *	Alchemy Pb1100 board setup.
- *
- * Copyright 2002 MontaVista Software Inc.
- * Author: MontaVista Software, Inc.
- *         	ppopov@mvista.com or source@mvista.com
- *
- *  This program is free software; you can redistribute  it and/or modify it
- *  under  the terms of  the GNU General  Public License as published by the
- *  Free Software Foundation;  either version 2 of the  License, or (at your
- *  option) any later version.
- *
- *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
- *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
- *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
- *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
- *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
- *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- *  You should have received a copy of the  GNU General Public License along
- *  with this program; if not, write  to the Free Software Foundation, Inc.,
- *  675 Mass Ave, Cambridge, MA 02139, USA.
- */
-#include <linux/config.h>
-#include <linux/init.h>
-#include <linux/sched.h>
-#include <linux/ioport.h>
-#include <linux/mm.h>
-#include <linux/console.h>
-#include <linux/mc146818rtc.h>
-#include <linux/delay.h>
-#include <linux/major.h>
-#include <linux/kdev_t.h>
-#include <linux/root_dev.h>
-
-#include <asm/cpu.h>
-#include <asm/bootinfo.h>
-#include <asm/irq.h>
-#include <asm/mipsregs.h>
-#include <asm/reboot.h>
-#include <asm/pgtable.h>
-#include <asm/au1000.h>
-#include <asm/pb1100.h>
-
-#ifdef CONFIG_USB_OHCI
-// Enable the workaround for the OHCI DoneHead
-// register corruption problem.
-#define CONFIG_AU1000_OHCI_FIX
-#endif
-
-#if defined(CONFIG_AU1X00_SERIAL_CONSOLE)
-extern void console_setup(char *, int *);
-char serial_console[20];
-#endif
-
-#ifdef CONFIG_BLK_DEV_INITRD
-extern unsigned long initrd_start, initrd_end;
-extern void * __rd_start, * __rd_end;
-#endif
-
-#ifdef CONFIG_BLK_DEV_IDE
-extern struct ide_ops std_ide_ops;
-extern struct ide_ops *ide_ops;
-#endif
-
-#ifdef CONFIG_RTC
-extern struct rtc_ops pb1500_rtc_ops;
-#endif
-
-extern char * __init prom_getcmdline(void);
-extern void au1000_restart(char *);
-extern void au1000_halt(void);
-extern void au1000_power_off(void);
-extern struct resource ioport_resource;
-extern struct resource iomem_resource;
-
-
-void __init au1x00_setup(void)
-{
-	char *argptr;
-	u32 pin_func, static_cfg0;
-	u32 sys_freqctrl, sys_clksrc;
-
-	argptr = prom_getcmdline();
-
-	/* NOTE: The memory map is established by YAMON 2.08+ */
-
-	/* Various early Au1000 Errata corrected by this */
-	set_c0_config(1<<19); /* Config[OD] */
-
-#ifdef CONFIG_AU1X00_SERIAL_CONSOLE
-	if ((argptr = strstr(argptr, "console=")) == NULL) {
-		argptr = prom_getcmdline();
-		strcat(argptr, " console=ttyS0,115200");
-	}
-#endif
-
-#ifdef CONFIG_SOUND_AU1X00
-	strcat(argptr, " au1000_audio=vra");
-	argptr = prom_getcmdline();
-#endif
-
-	_machine_restart = au1000_restart;
-	_machine_halt = au1000_halt;
-	_machine_power_off = au1000_power_off;
-
-	// IO/MEM resources.
-	set_io_port_base(0);
-	ioport_resource.start = 0x10000000;
-	ioport_resource.end = 0xffffffff;
-	iomem_resource.start = 0x10000000;
-	iomem_resource.end = 0xffffffff;
-
-#ifdef CONFIG_BLK_DEV_INITRD
-	ROOT_DEV = Root_RAM0;
-	initrd_start = (unsigned long)&__rd_start;
-	initrd_end = (unsigned long)&__rd_end;
-#endif
-
-	// set AUX clock to 12MHz * 8 = 96 MHz
-	au_writel(8, SYS_AUXPLL);
-	au_writel(0, SYS_PININPUTEN);
-	udelay(100);
-
-#if defined (CONFIG_USB_OHCI) || defined (CONFIG_AU1X00_USB_DEVICE)
-#ifdef CONFIG_USB_OHCI
-	if ((argptr = strstr(argptr, "usb_ohci=")) == NULL) {
-	        char usb_args[80];
-		argptr = prom_getcmdline();
-		memset(usb_args, 0, sizeof(usb_args));
-		sprintf(usb_args, " usb_ohci=base:0x%x,len:0x%x,irq:%d",
-			USB_OHCI_BASE, USB_OHCI_LEN, AU1000_USB_HOST_INT);
-		strcat(argptr, usb_args);
-	}
-#endif
-	// configure pins GPIO[14:9] as GPIO
-	pin_func = au_readl(SYS_PINFUNC) & (u32)(~0x80);
-
-	/* zero and disable FREQ2 */
-	sys_freqctrl = au_readl(SYS_FREQCTRL0);
-	sys_freqctrl &= ~0xFFF00000;
-	au_writel(sys_freqctrl, SYS_FREQCTRL0);
-
-	/* zero and disable USBH/USBD/IrDA clock */
-	sys_clksrc = au_readl(SYS_CLKSRC);
-	sys_clksrc &= ~0x0000001F;
-	au_writel(sys_clksrc, SYS_CLKSRC);
-
-	sys_freqctrl = au_readl(SYS_FREQCTRL0);
-	sys_freqctrl &= ~0xFFF00000;
-
-	sys_clksrc = au_readl(SYS_CLKSRC);
-	sys_clksrc &= ~0x0000001F;
-
-	// FREQ2 = aux/2 = 48 MHz
-	sys_freqctrl |= ((0<<22) | (1<<21) | (1<<20));
-	au_writel(sys_freqctrl, SYS_FREQCTRL0);
-
-	/*
-	 * Route 48MHz FREQ2 into USBH/USBD/IrDA
-	 */
-	sys_clksrc |= ((4<<2) | (0<<1) | 0 );
-	au_writel(sys_clksrc, SYS_CLKSRC);
-
-	/* setup the static bus controller */
-	au_writel(0x00000002, MEM_STCFG3);  /* type = PCMCIA */
-	au_writel(0x280E3D07, MEM_STTIME3); /* 250ns cycle time */
-	au_writel(0x10000000, MEM_STADDR3); /* any PCMCIA select */
-
-	// get USB Functionality pin state (device vs host drive pins)
-	pin_func = au_readl(SYS_PINFUNC) & (u32)(~0x8000);
-#ifndef CONFIG_AU1X00_USB_DEVICE
-	// 2nd USB port is USB host
-	pin_func |= 0x8000;
-#endif
-	au_writel(pin_func, SYS_PINFUNC);
-#endif // defined (CONFIG_USB_OHCI) || defined (CONFIG_AU1X00_USB_DEVICE)
-
-#ifdef CONFIG_USB_OHCI
-	// enable host controller and wait for reset done
-	au_writel(0x08, USB_HOST_CONFIG);
-	udelay(1000);
-	au_writel(0x0c, USB_HOST_CONFIG);
-	udelay(1000);
-	au_readl(USB_HOST_CONFIG);
-	while (!(au_readl(USB_HOST_CONFIG) & 0x10))
-	    ;
-	au_readl(USB_HOST_CONFIG);
-#endif
-
-#ifdef CONFIG_FB
-	conswitchp = &dummy_con;
-#endif
-
-#ifdef CONFIG_FB_AU1100
-	if ((argptr = strstr(argptr, "video=")) == NULL) {
-		argptr = prom_getcmdline();
-		/* default panel */
-		strcat(argptr, " video=au1100fb:panel:Sharp_320x240_16");
-	}
-#endif
-
-#ifdef CONFIG_FB_E1356
-	if ((argptr = strstr(argptr, "video=")) == NULL) {
-		argptr = prom_getcmdline();
-		strcat(argptr, " video=e1356fb:system:pb1500");
-	}
-#endif
-
-#ifndef CONFIG_SERIAL_NONSTANDARD
-	/* don't touch the default serial console */
-	au_writel(0, UART0_ADDR + UART_CLK);
-#endif
-	au_writel(0, UART1_ADDR + UART_CLK);
-	au_writel(0, UART3_ADDR + UART_CLK);
-
-#ifdef CONFIG_BLK_DEV_IDE
-	ide_ops = &std_ide_ops;
-#endif
-
-	while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_E0S);
-	au_writel(SYS_CNTRL_E0 | SYS_CNTRL_EN0, SYS_COUNTER_CNTRL);
-	au_sync();
-	while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_T0S);
-	au_writel(0, SYS_TOYTRIM);
-
-	au_writel(0x00000060, 0xb190003c);
-
-#ifdef CONFIG_RTC
-	rtc_ops = &pb1500_rtc_ops;
-	// Enable the RTC if not already enabled
-	if (!(readb(0xac000028) & 0x20)) {
-		writeb(readb(0xac000028) | 0x20, 0xac000028);
-		au_sync();
-	}
-	// Put the clock in BCD mode
-	if (readb(0xac00002C) & 0x4) { /* reg B */
-		writeb(readb(0xac00002c) & ~0x4, 0xac00002c);
-		au_sync();
-	}
-#endif
-}
--- diff/arch/mips/au1000/pb1500/setup.c	2003-07-08 09:55:17.000000000 +0100
+++ source/arch/mips/au1000/pb1500/setup.c	1970-01-01 01:00:00.000000000 +0100
@@ -1,293 +0,0 @@
-/*
- *
- * BRIEF MODULE DESCRIPTION
- *	Alchemy Pb1000 board setup.
- *
- * Copyright 2000 MontaVista Software Inc.
- * Author: MontaVista Software, Inc.
- *         	ppopov@mvista.com or source@mvista.com
- *
- *  This program is free software; you can redistribute  it and/or modify it
- *  under  the terms of  the GNU General  Public License as published by the
- *  Free Software Foundation;  either version 2 of the  License, or (at your
- *  option) any later version.
- *
- *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
- *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
- *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
- *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
- *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
- *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- *  You should have received a copy of the  GNU General Public License along
- *  with this program; if not, write  to the Free Software Foundation, Inc.,
- *  675 Mass Ave, Cambridge, MA 02139, USA.
- */
-#include <linux/config.h>
-#include <linux/init.h>
-#include <linux/sched.h>
-#include <linux/ioport.h>
-#include <linux/mm.h>
-#include <linux/console.h>
-#include <linux/mc146818rtc.h>
-#include <linux/delay.h>
-#include <linux/major.h>
-#include <linux/kdev_t.h>
-#include <linux/root_dev.h>
-
-#include <asm/cpu.h>
-#include <asm/time.h>
-#include <asm/bootinfo.h>
-#include <asm/irq.h>
-#include <asm/mipsregs.h>
-#include <asm/reboot.h>
-#include <asm/pgtable.h>
-#include <asm/au1000.h>
-#include <asm/pb1500.h>
-
-#ifdef CONFIG_USB_OHCI
-// Enable the workaround for the OHCI DoneHead
-// register corruption problem.
-#define CONFIG_AU1000_OHCI_FIX
-#endif
-
-#ifdef CONFIG_BLK_DEV_INITRD
-extern unsigned long initrd_start, initrd_end;
-extern void * __rd_start, * __rd_end;
-#endif
-
-#ifdef CONFIG_BLK_DEV_IDE
-extern struct ide_ops std_ide_ops;
-extern struct ide_ops *ide_ops;
-#endif
-
-#ifdef CONFIG_RTC
-extern struct rtc_ops pb1500_rtc_ops;
-#endif
-
-extern char * __init prom_getcmdline(void);
-extern void __init au1x_time_init(void);
-extern void __init au1x_timer_setup(struct irqaction *irq);
-extern void au1000_restart(char *);
-extern void au1000_halt(void);
-extern void au1000_power_off(void);
-extern struct resource ioport_resource;
-extern struct resource iomem_resource;
-#ifdef CONFIG_64BIT_PHYS_ADDR
-extern phys_t (*fixup_bigphys_addr)(phys_t phys_addr, phys_t size);
-static phys_t pb1500_fixup_bigphys_addr(phys_t phys_addr, phys_t size);
-#endif
-
-
-void __init au1x00_setup(void)
-{
-	char *argptr;
-	u32 pin_func, static_cfg0;
-	u32 sys_freqctrl, sys_clksrc;
-
-	argptr = prom_getcmdline();
-
-	/* NOTE: The memory map is established by YAMON 2.08+ */
-
-	/* Various early Au1500 Errata corrected by this */
-	set_c0_config(1<<19); /* Config[OD] */
-
-	board_time_init = au1x_time_init;
-	board_timer_setup = au1x_timer_setup;
-
-#ifdef CONFIG_SERIAL_AU1X00_CONSOLE
-	if ((argptr = strstr(argptr, "console=")) == NULL) {
-		argptr = prom_getcmdline();
-		strcat(argptr, " console=ttyS0,115200");
-	}
-#endif
-
-#ifdef CONFIG_SOUND_AU1X00
-	strcat(argptr, " au1000_audio=vra");
-	argptr = prom_getcmdline();
-#endif
-
-	_machine_restart = au1000_restart;
-	_machine_halt = au1000_halt;
-	_machine_power_off = au1000_power_off;
-#ifdef CONFIG_64BIT_PHYS_ADDR
-	fixup_bigphys_addr = pb1500_fixup_bigphys_addr;
-#endif
-
-	// IO/MEM resources.
-	set_io_port_base(0);
-	ioport_resource.start = 0x00000000;
-	ioport_resource.end = 0xffffffff;
-	iomem_resource.start = 0x10000000;
-	iomem_resource.end = 0xffffffff;
-
-#ifdef CONFIG_BLK_DEV_INITRD
-	ROOT_DEV = Root_RAM0;
-	initrd_start = (unsigned long)&__rd_start;
-	initrd_end = (unsigned long)&__rd_end;
-#endif
-
-	// set AUX clock to 12MHz * 8 = 96 MHz
-	au_writel(8, SYS_AUXPLL);
-	au_writel(0, SYS_PINSTATERD);
-	udelay(100);
-
-#if defined (CONFIG_USB_OHCI) || defined (CONFIG_AU1X00_USB_DEVICE)
-#ifdef CONFIG_USB_OHCI
-	if ((argptr = strstr(argptr, "usb_ohci=")) == NULL) {
-	        char usb_args[80];
-		argptr = prom_getcmdline();
-		memset(usb_args, 0, sizeof(usb_args));
-		sprintf(usb_args, " usb_ohci=base:0x%x,len:0x%x,irq:%d",
-			USB_OHCI_BASE, USB_OHCI_LEN, AU1000_USB_HOST_INT);
-		strcat(argptr, usb_args);
-	}
-#endif
-
-	/* GPIO201 is input for PCMCIA card detect */
-	/* GPIO203 is input for PCMCIA interrupt request */
-	au_writel(au_readl(GPIO2_DIR) & (u32)(~((1<<1)|(1<<3))), GPIO2_DIR);
-
-	/* zero and disable FREQ2 */
-	sys_freqctrl = au_readl(SYS_FREQCTRL0);
-	sys_freqctrl &= ~0xFFF00000;
-	au_writel(sys_freqctrl, SYS_FREQCTRL0);
-
-	/* zero and disable USBH/USBD clocks */
-	sys_clksrc = au_readl(SYS_CLKSRC);
-	sys_clksrc &= ~0x00007FE0;
-	au_writel(sys_clksrc, SYS_CLKSRC);
-
-	sys_freqctrl = au_readl(SYS_FREQCTRL0);
-	sys_freqctrl &= ~0xFFF00000;
-
-	sys_clksrc = au_readl(SYS_CLKSRC);
-	sys_clksrc &= ~0x00007FE0;
-
-	// FREQ2 = aux/2 = 48 MHz
-	sys_freqctrl |= ((0<<22) | (1<<21) | (1<<20));
-	au_writel(sys_freqctrl, SYS_FREQCTRL0);
-
-	/*
-	 * Route 48MHz FREQ2 into USB Host and/or Device
-	 */
-#ifdef CONFIG_USB_OHCI
-	sys_clksrc |= ((4<<12) | (0<<11) | (0<<10));
-#endif
-#ifdef CONFIG_AU1X00_USB_DEVICE
-	sys_clksrc |= ((4<<7) | (0<<6) | (0<<5));
-#endif
-	au_writel(sys_clksrc, SYS_CLKSRC);
-
-
-	pin_func = au_readl(SYS_PINFUNC) & (u32)(~0x8000);
-#ifndef CONFIG_AU1X00_USB_DEVICE
-	// 2nd USB port is USB host
-	pin_func |= 0x8000;
-#endif
-	au_writel(pin_func, SYS_PINFUNC);
-#endif // defined (CONFIG_USB_OHCI) || defined (CONFIG_AU1X00_USB_DEVICE)
-
-
-#ifdef CONFIG_USB_OHCI
-	// enable host controller and wait for reset done
-	au_writel(0x08, USB_HOST_CONFIG);
-	udelay(1000);
-	au_writel(0x0c, USB_HOST_CONFIG);
-	udelay(1000);
-	au_readl(USB_HOST_CONFIG);
-	while (!(au_readl(USB_HOST_CONFIG) & 0x10))
-	    ;
-	au_readl(USB_HOST_CONFIG);
-#endif
-
-#ifdef CONFIG_FB
-	conswitchp = &dummy_con;
-#endif
-
-#ifdef CONFIG_FB_E1356
-	if ((argptr = strstr(argptr, "video=")) == NULL) {
-		argptr = prom_getcmdline();
-		strcat(argptr, " video=e1356fb:system:pb1500");
-	}
-#elif defined (CONFIG_FB_XPERT98)
-	if ((argptr = strstr(argptr, "video=")) == NULL) {
-		argptr = prom_getcmdline();
-		strcat(argptr, " video=atyfb:1024x768-8@70");
-	}
-#endif // CONFIG_FB_E1356
-
-#ifndef CONFIG_SERIAL_AU1X00_CONSOLE
-	/* don't touch the default serial console */
-	au_writel(0, UART0_ADDR + UART_CLK);
-#endif
-	au_writel(0, UART3_ADDR + UART_CLK);
-
-#ifdef CONFIG_BLK_DEV_IDE
-	ide_ops = &std_ide_ops;
-#endif
-
-#ifdef CONFIG_PCI
-	// Setup PCI bus controller
-	au_writel(0, Au1500_PCI_CMEM);
-	au_writel(0x00003fff, Au1500_CFG_BASE);
-#if defined(__MIPSEB__)
-	au_writel(0xf | (2<<6) | (1<<4), Au1500_PCI_CFG);
-#else
-	au_writel(0xf, Au1500_PCI_CFG);
-#endif
-	au_writel(0xf0000000, Au1500_PCI_MWMASK_DEV);
-	au_writel(0, Au1500_PCI_MWBASE_REV_CCL);
-	au_writel(0x02a00356, Au1500_PCI_STATCMD);
-	au_writel(0x00003c04, Au1500_PCI_HDRTYPE);
-	au_writel(0x00000008, Au1500_PCI_MBAR);
-	au_sync();
-#endif
-
-	while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_E0S);
-	au_writel(SYS_CNTRL_E0 | SYS_CNTRL_EN0, SYS_COUNTER_CNTRL);
-	au_sync();
-	while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_T0S);
-	au_writel(0, SYS_TOYTRIM);
-
-	/* Enable BCLK switching */
-	au_writel(0x00000060, 0xb190003c);
-
-#ifdef CONFIG_RTC
-	rtc_ops = &pb1500_rtc_ops;
-	// Enable the RTC if not already enabled
-	if (!(au_readl(0xac000028) & 0x20)) {
-		printk("enabling clock ...\n");
-		au_writel((au_readl(0xac000028) | 0x20), 0xac000028);
-	}
-	// Put the clock in BCD mode
-	if (readl(0xac00002C) & 0x4) { /* reg B */
-		au_writel(au_readl(0xac00002c) & ~0x4, 0xac00002c);
-		au_sync();
-	}
-#endif
-}
-
-#ifdef CONFIG_64BIT_PHYS_ADDR
-static phys_t pb1500_fixup_bigphys_addr(phys_t phys_addr,
-					phys_t size)
-{
-	u32 pci_start = (u32)Au1500_PCI_MEM_START;
-	u32 pci_end = (u32)Au1500_PCI_MEM_END;
-
-	/* Don't fixup 36 bit addresses */
-	if ((phys_addr >> 32) != 0) return phys_addr;
-
-	/* check for pci memory window */
-	if ((phys_addr >= pci_start) && ((phys_addr + size) < pci_end)) {
-		return (phys_t)((phys_addr - pci_start) +
-				     Au1500_PCI_MEM_START);
-	}
-	else 
-		return phys_addr;
-}
-#endif
--- diff/arch/mips/cobalt/via.c	2003-07-08 09:55:17.000000000 +0100
+++ source/arch/mips/cobalt/via.c	1970-01-01 01:00:00.000000000 +0100
@@ -1,67 +0,0 @@
-/*
- * VIA chipset irq handling
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (C) 1996, 1997 by Ralf Baechle
- * Copyright (C) 2001, 2002, 2003 by Liam Davies (ldavies@agile.tv)
- *
- */
-
-#include <linux/irq.h>
-#include <linux/kernel.h>
-
-#include <asm/gt64120.h>
-#include <asm/ptrace.h>
-#include <asm/io.h>
-
-#include <asm/cobalt/cobalt.h>
-
-asmlinkage void via_irq(struct pt_regs *regs)
-{
-	char mstat, sstat;
-
-	/* Read Master Status */
-	outb(0x0C, 0x20);
-	mstat = inb(0x20);
-
-	if (mstat < 0) {
-		mstat &= 0x7f;
-		if (mstat != 2) {
-			do_IRQ(mstat, regs);
-			outb(mstat | 0x20, 0x20);
-		} else {
-			sstat = inb(0xA0);
-
-			/* Slave interrupt */
-			outb(0x0C, 0xA0);
-			sstat = inb(0xA0);
-
-			if (sstat < 0) {
-				do_IRQ((sstat + 8) & 0x7f, regs);
-				outb(0x22, 0x20);
-				outb((sstat & 0x7f) | 0x20, 0xA0);
-			} else {
-				printk("Spurious slave interrupt...\n");
-			}
-		}
-	} else
-		printk("Spurious master interrupt...");
-}
-
-asmlinkage void galileo_irq(struct pt_regs *regs)
-{
-	unsigned long irq_src;
-
-	irq_src = GALILEO_INL(GT_INTRCAUSE_OFS);
-
-	/* Check for timer irq ... */
-	if (irq_src & GALILEO_T0EXP) {
-		/* Clear the int line */
-		GALILEO_OUTL(0, GT_INTRCAUSE_OFS);
-		do_IRQ(COBALT_TIMER_IRQ, regs);
-	} else
-		printk("Spurious Galileo interrupt...\n");
-}
--- diff/arch/mips/ddb5xxx/ddb5074/time.c	2003-07-08 09:55:17.000000000 +0100
+++ source/arch/mips/ddb5xxx/ddb5074/time.c	1970-01-01 01:00:00.000000000 +0100
@@ -1,33 +0,0 @@
-/*
- *  arch/mips/ddb5074/time.c -- Timer routines
- *
- *  Copyright (C) 2000 Geert Uytterhoeven <geert@sonycom.com>
- *                     Sony Software Development Center Europe (SDCE), Brussels
- *
- */
-#include <linux/init.h>
-#include <asm/mc146818rtc.h>
-#include <asm/ddb5xxx/ddb5074.h>
-#include <asm/ddb5xxx/ddb5xxx.h>
-
-
-static unsigned char ddb_rtc_read_data(unsigned long addr)
-{
-	return *(volatile unsigned char *)(KSEG1ADDR(DDB_PCI_MEM_BASE)+addr);
-}
-
-static void ddb_rtc_write_data(unsigned char data, unsigned long addr)
-{
- 	*(volatile unsigned char *)(KSEG1ADDR(DDB_PCI_MEM_BASE)+addr)=data;
-}
-
-static int ddb_rtc_bcd_mode(void)
-{
-	return 1;
-}
-
-struct rtc_ops ddb_rtc_ops = {
-	ddb_rtc_read_data,
-	ddb_rtc_write_data,
-	ddb_rtc_bcd_mode
-};
--- diff/arch/mips/dec/rtc-dec.c	2003-07-08 09:55:17.000000000 +0100
+++ source/arch/mips/dec/rtc-dec.c	1970-01-01 01:00:00.000000000 +0100
@@ -1,40 +0,0 @@
-/*
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * RTC routines for DECstation style attached Dallas DS1287 chip.
- *
- * Copyright (C) 1998, 2001 by Ralf Baechle
- * Copyright (C) 1998 by Harald Koerfgen
- * Copyright (C) 2002  Maciej W. Rozycki
- */
-
-#include <linux/mc146818rtc.h>
-#include <linux/module.h>
-#include <linux/types.h>
-
-volatile u8 *dec_rtc_base;
-
-static unsigned char dec_rtc_read_data(unsigned long addr)
-{
-	return dec_rtc_base[addr * 4];
-}
-
-static void dec_rtc_write_data(unsigned char data, unsigned long addr)
-{
-	dec_rtc_base[addr * 4] = data;
-}
-
-static int dec_rtc_bcd_mode(void)
-{
-	return 0;
-}
-
-struct rtc_ops dec_rtc_ops = {
-	&dec_rtc_read_data,
-	&dec_rtc_write_data,
-	&dec_rtc_bcd_mode
-};
-
-EXPORT_SYMBOL(dec_rtc_base);
--- diff/arch/mips/defconfig-atlas	2003-08-20 14:16:25.000000000 +0100
+++ source/arch/mips/defconfig-atlas	1970-01-01 01:00:00.000000000 +0100
@@ -1,620 +0,0 @@
-#
-# Automatically generated make config: don't edit
-#
-CONFIG_MIPS=y
-# CONFIG_MIPS64 is not set
-CONFIG_MIPS32=y
-
-#
-# Code maturity level options
-#
-CONFIG_EXPERIMENTAL=y
-
-#
-# General setup
-#
-CONFIG_SWAP=y
-CONFIG_SYSVIPC=y
-# CONFIG_BSD_PROCESS_ACCT is not set
-CONFIG_SYSCTL=y
-CONFIG_LOG_BUF_SHIFT=14
-# CONFIG_EMBEDDED is not set
-CONFIG_KALLSYMS=y
-CONFIG_FUTEX=y
-CONFIG_EPOLL=y
-CONFIG_IOSCHED_AS=y
-CONFIG_IOSCHED_DEADLINE=y
-
-#
-# Loadable module support
-#
-# CONFIG_MODULES is not set
-
-#
-# Machine selection
-#
-# CONFIG_ACER_PICA_61 is not set
-# CONFIG_BAGET_MIPS is not set
-# CONFIG_CASIO_E55 is not set
-# CONFIG_MIPS_COBALT is not set
-# CONFIG_DECSTATION is not set
-# CONFIG_MIPS_EV64120 is not set
-# CONFIG_MIPS_EV96100 is not set
-# CONFIG_MIPS_IVR is not set
-# CONFIG_LASAT is not set
-# CONFIG_HP_LASERJET is not set
-# CONFIG_IBM_WORKPAD is not set
-# CONFIG_MIPS_ITE8172 is not set
-CONFIG_MIPS_ATLAS=y
-# CONFIG_MIPS_MAGNUM_4000 is not set
-# CONFIG_MIPS_MALTA is not set
-# CONFIG_MIPS_SEAD is not set
-# CONFIG_MOMENCO_OCELOT is not set
-# CONFIG_MOMENCO_OCELOT_G is not set
-# CONFIG_MOMENCO_OCELOT_C is not set
-# CONFIG_DDB5074 is not set
-# CONFIG_DDB5476 is not set
-# CONFIG_DDB5477 is not set
-# CONFIG_NEC_OSPREY is not set
-# CONFIG_NEC_EAGLE is not set
-# CONFIG_OLIVETTI_M700 is not set
-# CONFIG_SGI_IP22 is not set
-# CONFIG_SGI_IP32 is not set
-# CONFIG_SOC_AU1X00 is not set
-# CONFIG_SIBYTE_SB1xxx_SOC is not set
-# CONFIG_SNI_RM200_PCI is not set
-# CONFIG_TANBAC_TB0226 is not set
-# CONFIG_TANBAC_TB0229 is not set
-# CONFIG_TOSHIBA_JMR3927 is not set
-# CONFIG_TOSHIBA_RBTX4927 is not set
-# CONFIG_VICTOR_MPC30X is not set
-# CONFIG_ZAO_CAPCELLA is not set
-CONFIG_RWSEM_GENERIC_SPINLOCK=y
-CONFIG_GENERIC_ISA_DMA=y
-CONFIG_NONCOHERENT_IO=y
-# CONFIG_CPU_LITTLE_ENDIAN is not set
-CONFIG_MIPS_BOARDS_GEN=y
-CONFIG_SWAP_IO_SPACE=y
-CONFIG_BOOT_ELF32=y
-CONFIG_L1_CACHE_SHIFT=5
-# CONFIG_FB is not set
-
-#
-# CPU selection
-#
-CONFIG_CPU_MIPS32=y
-# CONFIG_CPU_MIPS64 is not set
-# CONFIG_CPU_R3000 is not set
-# CONFIG_CPU_TX39XX is not set
-# CONFIG_CPU_VR41XX is not set
-# CONFIG_CPU_R4300 is not set
-# CONFIG_CPU_R4X00 is not set
-# CONFIG_CPU_TX49XX is not set
-# CONFIG_CPU_R5000 is not set
-# CONFIG_CPU_R5432 is not set
-# CONFIG_CPU_R6000 is not set
-# CONFIG_CPU_NEVADA is not set
-# CONFIG_CPU_R8000 is not set
-# CONFIG_CPU_R10000 is not set
-# CONFIG_CPU_RM7000 is not set
-# CONFIG_CPU_SB1 is not set
-CONFIG_CPU_HAS_PREFETCH=y
-# CONFIG_VTAG_ICACHE is not set
-# CONFIG_64BIT_PHYS_ADDR is not set
-# CONFIG_CPU_ADVANCED is not set
-CONFIG_CPU_HAS_LLSC=y
-CONFIG_CPU_HAS_SYNC=y
-# CONFIG_PREEMPT is not set
-# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
-
-#
-# Bus options (PCI, PCMCIA, EISA, ISA, TC)
-#
-CONFIG_PCI=y
-CONFIG_PCI_LEGACY_PROC=y
-CONFIG_PCI_NAMES=y
-CONFIG_MMU=y
-# CONFIG_HOTPLUG is not set
-
-#
-# Executable file formats
-#
-CONFIG_KCORE_ELF=y
-CONFIG_BINFMT_ELF=y
-# CONFIG_BINFMT_MISC is not set
-CONFIG_TRAD_SIGNALS=y
-# CONFIG_BINFMT_IRIX is not set
-
-#
-# Memory Technology Devices (MTD)
-#
-# CONFIG_MTD is not set
-
-#
-# Parallel port support
-#
-# CONFIG_PARPORT is not set
-
-#
-# Plug and Play support
-#
-# CONFIG_PNP is not set
-
-#
-# Generic Driver Options
-#
-# CONFIG_FW_LOADER is not set
-
-#
-# Block devices
-#
-# CONFIG_BLK_DEV_FD is not set
-# CONFIG_BLK_CPQ_DA is not set
-# CONFIG_BLK_CPQ_CISS_DA is not set
-# CONFIG_BLK_DEV_DAC960 is not set
-# CONFIG_BLK_DEV_UMEM is not set
-CONFIG_BLK_DEV_LOOP=y
-# CONFIG_BLK_DEV_CRYPTOLOOP is not set
-# CONFIG_BLK_DEV_NBD is not set
-CONFIG_BLK_DEV_RAM=y
-CONFIG_BLK_DEV_RAM_SIZE=4096
-# CONFIG_BLK_DEV_INITRD is not set
-# CONFIG_LBD is not set
-
-#
-# ATA/ATAPI/MFM/RLL support
-#
-# CONFIG_IDE is not set
-
-#
-# SCSI device support
-#
-CONFIG_SCSI=y
-
-#
-# SCSI support type (disk, tape, CD-ROM)
-#
-CONFIG_BLK_DEV_SD=y
-# CONFIG_CHR_DEV_ST is not set
-# CONFIG_CHR_DEV_OSST is not set
-# CONFIG_BLK_DEV_SR is not set
-# CONFIG_CHR_DEV_SG is not set
-
-#
-# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
-#
-# CONFIG_SCSI_MULTI_LUN is not set
-# CONFIG_SCSI_REPORT_LUNS is not set
-# CONFIG_SCSI_CONSTANTS is not set
-# CONFIG_SCSI_LOGGING is not set
-
-#
-# SCSI low-level drivers
-#
-# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
-# CONFIG_SCSI_ACARD is not set
-# CONFIG_SCSI_AACRAID is not set
-# CONFIG_SCSI_AIC7XXX is not set
-# CONFIG_SCSI_AIC7XXX_OLD is not set
-# CONFIG_SCSI_AIC79XX is not set
-# CONFIG_SCSI_DPT_I2O is not set
-# CONFIG_SCSI_ADVANSYS is not set
-# CONFIG_SCSI_MEGARAID is not set
-# CONFIG_SCSI_BUSLOGIC is not set
-# CONFIG_SCSI_CPQFCTS is not set
-# CONFIG_SCSI_DMX3191D is not set
-# CONFIG_SCSI_EATA is not set
-# CONFIG_SCSI_EATA_PIO is not set
-# CONFIG_SCSI_FUTURE_DOMAIN is not set
-# CONFIG_SCSI_GDTH is not set
-# CONFIG_SCSI_INITIO is not set
-# CONFIG_SCSI_INIA100 is not set
-# CONFIG_SCSI_SYM53C8XX_2 is not set
-# CONFIG_SCSI_SYM53C8XX is not set
-# CONFIG_SCSI_PCI2000 is not set
-# CONFIG_SCSI_PCI2220I is not set
-# CONFIG_SCSI_QLOGIC_ISP is not set
-# CONFIG_SCSI_QLOGIC_FC is not set
-# CONFIG_SCSI_QLOGIC_1280 is not set
-# CONFIG_SCSI_DC395x is not set
-# CONFIG_SCSI_DC390T is not set
-# CONFIG_SCSI_NSP32 is not set
-# CONFIG_SCSI_DEBUG is not set
-
-#
-# Multi-device support (RAID and LVM)
-#
-# CONFIG_MD is not set
-
-#
-# Fusion MPT device support
-#
-# CONFIG_FUSION is not set
-
-#
-# IEEE 1394 (FireWire) support (EXPERIMENTAL)
-#
-# CONFIG_IEEE1394 is not set
-
-#
-# I2O device support
-#
-# CONFIG_I2O is not set
-
-#
-# Networking support
-#
-CONFIG_NET=y
-
-#
-# Networking options
-#
-CONFIG_PACKET=y
-# CONFIG_PACKET_MMAP is not set
-CONFIG_NETLINK_DEV=y
-# CONFIG_NETFILTER is not set
-CONFIG_UNIX=y
-CONFIG_NET_KEY=y
-CONFIG_INET=y
-# CONFIG_IP_MULTICAST is not set
-# CONFIG_IP_ADVANCED_ROUTER is not set
-CONFIG_IP_PNP=y
-# CONFIG_IP_PNP_DHCP is not set
-# CONFIG_IP_PNP_BOOTP is not set
-# CONFIG_IP_PNP_RARP is not set
-# CONFIG_NET_IPIP is not set
-# CONFIG_NET_IPGRE is not set
-# CONFIG_ARPD is not set
-# CONFIG_INET_ECN is not set
-# CONFIG_SYN_COOKIES is not set
-# CONFIG_INET_AH is not set
-# CONFIG_INET_ESP is not set
-# CONFIG_INET_IPCOMP is not set
-# CONFIG_IPV6 is not set
-# CONFIG_XFRM_USER is not set
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
-CONFIG_IPV6_SCTP__=y
-# CONFIG_IP_SCTP is not set
-# CONFIG_ATM is not set
-# CONFIG_VLAN_8021Q is not set
-# CONFIG_LLC is not set
-# CONFIG_DECNET is not set
-# CONFIG_BRIDGE is not set
-# CONFIG_X25 is not set
-# CONFIG_LAPB is not set
-# CONFIG_NET_DIVERT is not set
-# CONFIG_ECONET is not set
-# CONFIG_WAN_ROUTER is not set
-# CONFIG_NET_FASTROUTE is not set
-# CONFIG_NET_HW_FLOWCONTROL is not set
-
-#
-# QoS and/or fair queueing
-#
-# CONFIG_NET_SCHED is not set
-
-#
-# Network testing
-#
-# CONFIG_NET_PKTGEN is not set
-CONFIG_NETDEVICES=y
-
-#
-# ARCnet devices
-#
-# CONFIG_ARCNET is not set
-# CONFIG_DUMMY is not set
-# CONFIG_BONDING is not set
-# CONFIG_EQUALIZER is not set
-# CONFIG_TUN is not set
-# CONFIG_ETHERTAP is not set
-
-#
-# Ethernet (10 or 100Mbit)
-#
-CONFIG_NET_ETHERNET=y
-# CONFIG_MII is not set
-# CONFIG_HAPPYMEAL is not set
-# CONFIG_SUNGEM is not set
-# CONFIG_NET_VENDOR_3COM is not set
-
-#
-# Tulip family network device support
-#
-# CONFIG_NET_TULIP is not set
-# CONFIG_HP100 is not set
-# CONFIG_NET_PCI is not set
-
-#
-# Ethernet (1000 Mbit)
-#
-# CONFIG_ACENIC is not set
-# CONFIG_DL2K is not set
-# CONFIG_E1000 is not set
-# CONFIG_NS83820 is not set
-# CONFIG_HAMACHI is not set
-# CONFIG_YELLOWFIN is not set
-# CONFIG_R8169 is not set
-# CONFIG_SK98LIN is not set
-# CONFIG_TIGON3 is not set
-
-#
-# Ethernet (10000 Mbit)
-#
-# CONFIG_IXGB is not set
-# CONFIG_FDDI is not set
-# CONFIG_HIPPI is not set
-# CONFIG_PPP is not set
-# CONFIG_SLIP is not set
-
-#
-# Wireless LAN (non-hamradio)
-#
-# CONFIG_NET_RADIO is not set
-
-#
-# Token Ring devices (depends on LLC=y)
-#
-# CONFIG_NET_FC is not set
-# CONFIG_RCPCI is not set
-# CONFIG_SHAPER is not set
-
-#
-# Wan interfaces
-#
-# CONFIG_WAN is not set
-
-#
-# Amateur Radio support
-#
-# CONFIG_HAMRADIO is not set
-
-#
-# IrDA (infrared) support
-#
-# CONFIG_IRDA is not set
-
-#
-# ISDN subsystem
-#
-# CONFIG_ISDN_BOOL is not set
-
-#
-# Telephony Support
-#
-# CONFIG_PHONE is not set
-
-#
-# Input device support
-#
-CONFIG_INPUT=y
-
-#
-# Userland interfaces
-#
-# CONFIG_INPUT_MOUSEDEV is not set
-# CONFIG_INPUT_JOYDEV is not set
-# CONFIG_INPUT_TSDEV is not set
-# CONFIG_INPUT_EVDEV is not set
-# CONFIG_INPUT_EVBUG is not set
-
-#
-# Input I/O drivers
-#
-# CONFIG_GAMEPORT is not set
-CONFIG_SOUND_GAMEPORT=y
-CONFIG_SERIO=y
-# CONFIG_SERIO_I8042 is not set
-CONFIG_SERIO_SERPORT=y
-# CONFIG_SERIO_CT82C710 is not set
-# CONFIG_SERIO_PCIPS2 is not set
-
-#
-# Input Device Drivers
-#
-# CONFIG_INPUT_KEYBOARD is not set
-# CONFIG_INPUT_MOUSE is not set
-# CONFIG_INPUT_JOYSTICK is not set
-# CONFIG_INPUT_TOUCHSCREEN is not set
-# CONFIG_INPUT_MISC is not set
-
-#
-# Character devices
-#
-# CONFIG_VT is not set
-# CONFIG_SERIAL_NONSTANDARD is not set
-
-#
-# Serial drivers
-#
-CONFIG_SERIAL_8250=y
-CONFIG_SERIAL_8250_CONSOLE=y
-# CONFIG_SERIAL_8250_EXTENDED is not set
-
-#
-# Non-8250 serial port support
-#
-CONFIG_SERIAL_CORE=y
-CONFIG_SERIAL_CORE_CONSOLE=y
-CONFIG_UNIX98_PTYS=y
-CONFIG_UNIX98_PTY_COUNT=256
-
-#
-# I2C support
-#
-# CONFIG_I2C is not set
-
-#
-# I2C Hardware Sensors Mainboard support
-#
-
-#
-# I2C Hardware Sensors Chip support
-#
-# CONFIG_I2C_SENSOR is not set
-
-#
-# Mice
-#
-# CONFIG_BUSMOUSE is not set
-# CONFIG_QIC02_TAPE is not set
-
-#
-# IPMI
-#
-# CONFIG_IPMI_HANDLER is not set
-
-#
-# Watchdog Cards
-#
-# CONFIG_WATCHDOG is not set
-# CONFIG_NVRAM is not set
-# CONFIG_RTC is not set
-# CONFIG_GEN_RTC is not set
-# CONFIG_DTLK is not set
-# CONFIG_R3964 is not set
-# CONFIG_APPLICOM is not set
-
-#
-# Ftape, the floppy tape device driver
-#
-# CONFIG_FTAPE is not set
-# CONFIG_AGP is not set
-# CONFIG_DRM is not set
-# CONFIG_RAW_DRIVER is not set
-# CONFIG_HANGCHECK_TIMER is not set
-
-#
-# Multimedia devices
-#
-# CONFIG_VIDEO_DEV is not set
-
-#
-# Digital Video Broadcasting Devices
-#
-# CONFIG_DVB is not set
-
-#
-# File systems
-#
-CONFIG_EXT2_FS=y
-# CONFIG_EXT2_FS_XATTR is not set
-# CONFIG_EXT3_FS is not set
-# CONFIG_JBD is not set
-# CONFIG_REISERFS_FS is not set
-# CONFIG_JFS_FS is not set
-# CONFIG_XFS_FS is not set
-# CONFIG_MINIX_FS is not set
-# CONFIG_ROMFS_FS is not set
-# CONFIG_QUOTA is not set
-# CONFIG_AUTOFS_FS is not set
-# CONFIG_AUTOFS4_FS is not set
-
-#
-# CD-ROM/DVD Filesystems
-#
-# CONFIG_ISO9660_FS is not set
-# CONFIG_UDF_FS is not set
-
-#
-# DOS/FAT/NT Filesystems
-#
-# CONFIG_FAT_FS is not set
-# CONFIG_NTFS_FS is not set
-
-#
-# Pseudo filesystems
-#
-CONFIG_PROC_FS=y
-# CONFIG_DEVFS_FS is not set
-CONFIG_DEVPTS_FS=y
-CONFIG_DEVPTS_FS_XATTR=y
-CONFIG_DEVPTS_FS_SECURITY=y
-# CONFIG_TMPFS is not set
-CONFIG_RAMFS=y
-
-#
-# Miscellaneous filesystems
-#
-# CONFIG_ADFS_FS is not set
-# CONFIG_AFFS_FS is not set
-# CONFIG_HFS_FS is not set
-# CONFIG_BEFS_FS is not set
-# CONFIG_BFS_FS is not set
-# CONFIG_EFS_FS is not set
-# CONFIG_CRAMFS is not set
-# CONFIG_VXFS_FS is not set
-# CONFIG_HPFS_FS is not set
-# CONFIG_QNX4FS_FS is not set
-# CONFIG_SYSV_FS is not set
-# CONFIG_UFS_FS is not set
-
-#
-# Network File Systems
-#
-CONFIG_NFS_FS=y
-CONFIG_NFS_V3=y
-# CONFIG_NFS_V4 is not set
-# CONFIG_NFSD is not set
-CONFIG_ROOT_NFS=y
-CONFIG_LOCKD=y
-CONFIG_LOCKD_V4=y
-# CONFIG_EXPORTFS is not set
-CONFIG_SUNRPC=y
-# CONFIG_SUNRPC_GSS is not set
-# CONFIG_SMB_FS is not set
-# CONFIG_CIFS is not set
-# CONFIG_NCP_FS is not set
-# CONFIG_CODA_FS is not set
-# CONFIG_INTERMEZZO_FS is not set
-# CONFIG_AFS_FS is not set
-
-#
-# Partition Types
-#
-# CONFIG_PARTITION_ADVANCED is not set
-CONFIG_MSDOS_PARTITION=y
-
-#
-# Graphics support
-#
-
-#
-# Sound
-#
-# CONFIG_SOUND is not set
-
-#
-# USB support
-#
-# CONFIG_USB is not set
-# CONFIG_USB_GADGET is not set
-
-#
-# Bluetooth support
-#
-# CONFIG_BT is not set
-
-#
-# Kernel hacking
-#
-CONFIG_CROSSCOMPILE=y
-# CONFIG_DEBUG_KERNEL is not set
-
-#
-# Security options
-#
-# CONFIG_SECURITY is not set
-
-#
-# Cryptographic options
-#
-# CONFIG_CRYPTO is not set
-
-#
-# Library routines
-#
-# CONFIG_CRC32 is not set
--- diff/arch/mips/defconfig-capcella	2003-08-20 14:16:25.000000000 +0100
+++ source/arch/mips/defconfig-capcella	1970-01-01 01:00:00.000000000 +0100
@@ -1,616 +0,0 @@
-#
-# Automatically generated make config: don't edit
-#
-CONFIG_MIPS=y
-# CONFIG_MIPS64 is not set
-CONFIG_MIPS32=y
-
-#
-# Code maturity level options
-#
-CONFIG_EXPERIMENTAL=y
-
-#
-# General setup
-#
-CONFIG_SWAP=y
-CONFIG_SYSVIPC=y
-# CONFIG_BSD_PROCESS_ACCT is not set
-CONFIG_SYSCTL=y
-CONFIG_LOG_BUF_SHIFT=14
-# CONFIG_EMBEDDED is not set
-CONFIG_KALLSYMS=y
-CONFIG_FUTEX=y
-CONFIG_EPOLL=y
-CONFIG_IOSCHED_AS=y
-CONFIG_IOSCHED_DEADLINE=y
-
-#
-# Loadable module support
-#
-CONFIG_MODULES=y
-CONFIG_MODULE_UNLOAD=y
-# CONFIG_MODULE_FORCE_UNLOAD is not set
-CONFIG_OBSOLETE_MODPARM=y
-CONFIG_MODVERSIONS=y
-CONFIG_KMOD=y
-
-#
-# Machine selection
-#
-# CONFIG_ACER_PICA_61 is not set
-# CONFIG_BAGET_MIPS is not set
-# CONFIG_CASIO_E55 is not set
-# CONFIG_MIPS_COBALT is not set
-# CONFIG_DECSTATION is not set
-# CONFIG_MIPS_EV64120 is not set
-# CONFIG_MIPS_EV96100 is not set
-# CONFIG_MIPS_IVR is not set
-# CONFIG_LASAT is not set
-# CONFIG_HP_LASERJET is not set
-# CONFIG_IBM_WORKPAD is not set
-# CONFIG_MIPS_ITE8172 is not set
-# CONFIG_MIPS_ATLAS is not set
-# CONFIG_MIPS_MAGNUM_4000 is not set
-# CONFIG_MIPS_MALTA is not set
-# CONFIG_MIPS_SEAD is not set
-# CONFIG_MOMENCO_OCELOT is not set
-# CONFIG_MOMENCO_OCELOT_G is not set
-# CONFIG_MOMENCO_OCELOT_C is not set
-# CONFIG_DDB5074 is not set
-# CONFIG_DDB5476 is not set
-# CONFIG_DDB5477 is not set
-# CONFIG_NEC_OSPREY is not set
-# CONFIG_NEC_EAGLE is not set
-# CONFIG_OLIVETTI_M700 is not set
-# CONFIG_SGI_IP22 is not set
-# CONFIG_SGI_IP32 is not set
-# CONFIG_SOC_AU1X00 is not set
-# CONFIG_SIBYTE_SB1xxx_SOC is not set
-# CONFIG_SNI_RM200_PCI is not set
-# CONFIG_TANBAC_TB0226 is not set
-# CONFIG_TANBAC_TB0229 is not set
-# CONFIG_TOSHIBA_JMR3927 is not set
-# CONFIG_TOSHIBA_RBTX4927 is not set
-# CONFIG_VICTOR_MPC30X is not set
-CONFIG_ZAO_CAPCELLA=y
-CONFIG_RWSEM_GENERIC_SPINLOCK=y
-CONFIG_NONCOHERENT_IO=y
-CONFIG_CPU_LITTLE_ENDIAN=y
-CONFIG_IRQ_CPU=y
-CONFIG_VR41XX_TIME_C=y
-CONFIG_DUMMY_KEYB=y
-CONFIG_VR41XX_COMMON=y
-CONFIG_NEW_PCI=y
-# CONFIG_FB is not set
-
-#
-# CPU selection
-#
-# CONFIG_CPU_MIPS32 is not set
-# CONFIG_CPU_MIPS64 is not set
-# CONFIG_CPU_R3000 is not set
-# CONFIG_CPU_TX39XX is not set
-CONFIG_CPU_VR41XX=y
-# CONFIG_CPU_R4300 is not set
-# CONFIG_CPU_R4X00 is not set
-# CONFIG_CPU_TX49XX is not set
-# CONFIG_CPU_R5000 is not set
-# CONFIG_CPU_R5432 is not set
-# CONFIG_CPU_R6000 is not set
-# CONFIG_CPU_NEVADA is not set
-# CONFIG_CPU_R8000 is not set
-# CONFIG_CPU_R10000 is not set
-# CONFIG_CPU_RM7000 is not set
-# CONFIG_CPU_SB1 is not set
-# CONFIG_CPU_ADVANCED is not set
-CONFIG_CPU_HAS_SYNC=y
-# CONFIG_PREEMPT is not set
-# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
-
-#
-# Bus options (PCI, PCMCIA, EISA, ISA, TC)
-#
-CONFIG_PCI=y
-CONFIG_PCI_LEGACY_PROC=y
-CONFIG_PCI_NAMES=y
-CONFIG_MMU=y
-# CONFIG_HOTPLUG is not set
-
-#
-# Executable file formats
-#
-CONFIG_KCORE_ELF=y
-CONFIG_BINFMT_ELF=y
-# CONFIG_BINFMT_MISC is not set
-CONFIG_TRAD_SIGNALS=y
-
-#
-# Memory Technology Devices (MTD)
-#
-# CONFIG_MTD is not set
-
-#
-# Parallel port support
-#
-# CONFIG_PARPORT is not set
-
-#
-# Plug and Play support
-#
-# CONFIG_PNP is not set
-
-#
-# Generic Driver Options
-#
-# CONFIG_FW_LOADER is not set
-
-#
-# Block devices
-#
-# CONFIG_BLK_DEV_FD is not set
-# CONFIG_BLK_CPQ_DA is not set
-# CONFIG_BLK_CPQ_CISS_DA is not set
-# CONFIG_BLK_DEV_DAC960 is not set
-# CONFIG_BLK_DEV_UMEM is not set
-# CONFIG_BLK_DEV_LOOP is not set
-# CONFIG_BLK_DEV_NBD is not set
-# CONFIG_BLK_DEV_RAM is not set
-# CONFIG_BLK_DEV_INITRD is not set
-# CONFIG_LBD is not set
-
-#
-# ATA/ATAPI/MFM/RLL support
-#
-CONFIG_IDE=y
-
-#
-# IDE, ATA and ATAPI Block devices
-#
-CONFIG_BLK_DEV_IDE=y
-
-#
-# Please see Documentation/ide.txt for help/info on IDE drives
-#
-# CONFIG_BLK_DEV_HD is not set
-CONFIG_BLK_DEV_IDEDISK=y
-# CONFIG_IDEDISK_MULTI_MODE is not set
-# CONFIG_IDEDISK_STROKE is not set
-# CONFIG_BLK_DEV_IDECD is not set
-# CONFIG_BLK_DEV_IDEFLOPPY is not set
-# CONFIG_IDE_TASK_IOCTL is not set
-CONFIG_IDE_TASKFILE_IO=y
-
-#
-# IDE chipset support/bugfixes
-#
-# CONFIG_BLK_DEV_IDEPCI is not set
-
-#
-# SCSI device support
-#
-# CONFIG_SCSI is not set
-
-#
-# Multi-device support (RAID and LVM)
-#
-# CONFIG_MD is not set
-
-#
-# Fusion MPT device support
-#
-
-#
-# IEEE 1394 (FireWire) support (EXPERIMENTAL)
-#
-# CONFIG_IEEE1394 is not set
-
-#
-# I2O device support
-#
-# CONFIG_I2O is not set
-
-#
-# Networking support
-#
-CONFIG_NET=y
-
-#
-# Networking options
-#
-CONFIG_PACKET=y
-CONFIG_PACKET_MMAP=y
-CONFIG_NETLINK_DEV=y
-# CONFIG_NETFILTER is not set
-CONFIG_UNIX=y
-CONFIG_NET_KEY=y
-CONFIG_INET=y
-CONFIG_IP_MULTICAST=y
-# CONFIG_IP_ADVANCED_ROUTER is not set
-CONFIG_IP_PNP=y
-# CONFIG_IP_PNP_DHCP is not set
-CONFIG_IP_PNP_BOOTP=y
-# CONFIG_IP_PNP_RARP is not set
-# CONFIG_NET_IPIP is not set
-# CONFIG_NET_IPGRE is not set
-# CONFIG_IP_MROUTE is not set
-# CONFIG_ARPD is not set
-# CONFIG_INET_ECN is not set
-# CONFIG_SYN_COOKIES is not set
-# CONFIG_INET_AH is not set
-# CONFIG_INET_ESP is not set
-# CONFIG_INET_IPCOMP is not set
-# CONFIG_IPV6 is not set
-# CONFIG_XFRM_USER is not set
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
-CONFIG_IPV6_SCTP__=y
-# CONFIG_IP_SCTP is not set
-# CONFIG_ATM is not set
-# CONFIG_VLAN_8021Q is not set
-# CONFIG_LLC is not set
-# CONFIG_DECNET is not set
-# CONFIG_BRIDGE is not set
-# CONFIG_X25 is not set
-# CONFIG_LAPB is not set
-# CONFIG_NET_DIVERT is not set
-# CONFIG_ECONET is not set
-# CONFIG_WAN_ROUTER is not set
-# CONFIG_NET_FASTROUTE is not set
-# CONFIG_NET_HW_FLOWCONTROL is not set
-
-#
-# QoS and/or fair queueing
-#
-# CONFIG_NET_SCHED is not set
-
-#
-# Network testing
-#
-# CONFIG_NET_PKTGEN is not set
-CONFIG_NETDEVICES=y
-
-#
-# ARCnet devices
-#
-# CONFIG_ARCNET is not set
-# CONFIG_DUMMY is not set
-# CONFIG_BONDING is not set
-# CONFIG_EQUALIZER is not set
-# CONFIG_TUN is not set
-# CONFIG_ETHERTAP is not set
-
-#
-# Ethernet (10 or 100Mbit)
-#
-CONFIG_NET_ETHERNET=y
-# CONFIG_MII is not set
-# CONFIG_HAPPYMEAL is not set
-# CONFIG_SUNGEM is not set
-# CONFIG_NET_VENDOR_3COM is not set
-
-#
-# Tulip family network device support
-#
-# CONFIG_NET_TULIP is not set
-# CONFIG_HP100 is not set
-# CONFIG_NET_PCI is not set
-
-#
-# Ethernet (1000 Mbit)
-#
-# CONFIG_ACENIC is not set
-# CONFIG_DL2K is not set
-# CONFIG_E1000 is not set
-# CONFIG_NS83820 is not set
-# CONFIG_HAMACHI is not set
-# CONFIG_YELLOWFIN is not set
-# CONFIG_R8169 is not set
-# CONFIG_SK98LIN is not set
-# CONFIG_TIGON3 is not set
-
-#
-# Ethernet (10000 Mbit)
-#
-# CONFIG_IXGB is not set
-# CONFIG_FDDI is not set
-# CONFIG_HIPPI is not set
-# CONFIG_PPP is not set
-# CONFIG_SLIP is not set
-
-#
-# Wireless LAN (non-hamradio)
-#
-# CONFIG_NET_RADIO is not set
-
-#
-# Token Ring devices (depends on LLC=y)
-#
-# CONFIG_RCPCI is not set
-# CONFIG_SHAPER is not set
-
-#
-# Wan interfaces
-#
-# CONFIG_WAN is not set
-
-#
-# Amateur Radio support
-#
-# CONFIG_HAMRADIO is not set
-
-#
-# IrDA (infrared) support
-#
-# CONFIG_IRDA is not set
-
-#
-# ISDN subsystem
-#
-# CONFIG_ISDN_BOOL is not set
-
-#
-# Telephony Support
-#
-# CONFIG_PHONE is not set
-
-#
-# Input device support
-#
-CONFIG_INPUT=y
-
-#
-# Userland interfaces
-#
-# CONFIG_INPUT_MOUSEDEV is not set
-# CONFIG_INPUT_JOYDEV is not set
-# CONFIG_INPUT_TSDEV is not set
-# CONFIG_INPUT_EVDEV is not set
-# CONFIG_INPUT_EVBUG is not set
-
-#
-# Input I/O drivers
-#
-# CONFIG_GAMEPORT is not set
-CONFIG_SOUND_GAMEPORT=y
-# CONFIG_SERIO is not set
-
-#
-# Input Device Drivers
-#
-# CONFIG_INPUT_KEYBOARD is not set
-# CONFIG_INPUT_MOUSE is not set
-# CONFIG_INPUT_JOYSTICK is not set
-# CONFIG_INPUT_TOUCHSCREEN is not set
-# CONFIG_INPUT_MISC is not set
-
-#
-# Character devices
-#
-CONFIG_VT=y
-# CONFIG_VT_CONSOLE is not set
-CONFIG_HW_CONSOLE=y
-# CONFIG_SERIAL_NONSTANDARD is not set
-
-#
-# Serial drivers
-#
-CONFIG_SERIAL_8250=y
-CONFIG_SERIAL_8250_CONSOLE=y
-# CONFIG_SERIAL_8250_EXTENDED is not set
-
-#
-# Non-8250 serial port support
-#
-CONFIG_SERIAL_CORE=y
-CONFIG_SERIAL_CORE_CONSOLE=y
-CONFIG_UNIX98_PTYS=y
-CONFIG_UNIX98_PTY_COUNT=256
-
-#
-# I2C support
-#
-# CONFIG_I2C is not set
-
-#
-# I2C Hardware Sensors Mainboard support
-#
-
-#
-# I2C Hardware Sensors Chip support
-#
-# CONFIG_I2C_SENSOR is not set
-
-#
-# Mice
-#
-# CONFIG_BUSMOUSE is not set
-# CONFIG_QIC02_TAPE is not set
-
-#
-# IPMI
-#
-# CONFIG_IPMI_HANDLER is not set
-
-#
-# Watchdog Cards
-#
-CONFIG_WATCHDOG=y
-# CONFIG_WATCHDOG_NOWAYOUT is not set
-# CONFIG_SOFT_WATCHDOG is not set
-# CONFIG_WDT is not set
-# CONFIG_WDTPCI is not set
-# CONFIG_PCWATCHDOG is not set
-# CONFIG_ACQUIRE_WDT is not set
-# CONFIG_ADVANTECH_WDT is not set
-# CONFIG_EUROTECH_WDT is not set
-# CONFIG_IB700_WDT is not set
-# CONFIG_I810_TCO is not set
-# CONFIG_MIXCOMWD is not set
-# CONFIG_SCx200_WDT is not set
-# CONFIG_60XX_WDT is not set
-# CONFIG_W83877F_WDT is not set
-# CONFIG_MACHZ_WDT is not set
-# CONFIG_SC520_WDT is not set
-# CONFIG_AMD7XX_TCO is not set
-# CONFIG_ALIM7101_WDT is not set
-# CONFIG_SC1200_WDT is not set
-# CONFIG_WAFER_WDT is not set
-# CONFIG_CPU5_WDT is not set
-# CONFIG_NVRAM is not set
-# CONFIG_RTC is not set
-# CONFIG_GEN_RTC is not set
-# CONFIG_DTLK is not set
-# CONFIG_R3964 is not set
-# CONFIG_APPLICOM is not set
-
-#
-# Ftape, the floppy tape device driver
-#
-# CONFIG_FTAPE is not set
-# CONFIG_AGP is not set
-# CONFIG_DRM is not set
-# CONFIG_RAW_DRIVER is not set
-# CONFIG_HANGCHECK_TIMER is not set
-
-#
-# Multimedia devices
-#
-# CONFIG_VIDEO_DEV is not set
-
-#
-# Digital Video Broadcasting Devices
-#
-# CONFIG_DVB is not set
-
-#
-# File systems
-#
-CONFIG_EXT2_FS=y
-# CONFIG_EXT2_FS_XATTR is not set
-# CONFIG_EXT3_FS is not set
-# CONFIG_JBD is not set
-# CONFIG_REISERFS_FS is not set
-# CONFIG_JFS_FS is not set
-# CONFIG_XFS_FS is not set
-# CONFIG_MINIX_FS is not set
-# CONFIG_ROMFS_FS is not set
-# CONFIG_QUOTA is not set
-CONFIG_AUTOFS_FS=y
-CONFIG_AUTOFS4_FS=y
-
-#
-# CD-ROM/DVD Filesystems
-#
-# CONFIG_ISO9660_FS is not set
-# CONFIG_UDF_FS is not set
-
-#
-# DOS/FAT/NT Filesystems
-#
-# CONFIG_FAT_FS is not set
-# CONFIG_NTFS_FS is not set
-
-#
-# Pseudo filesystems
-#
-CONFIG_PROC_FS=y
-# CONFIG_DEVFS_FS is not set
-CONFIG_DEVPTS_FS=y
-CONFIG_DEVPTS_FS_XATTR=y
-CONFIG_DEVPTS_FS_SECURITY=y
-# CONFIG_TMPFS is not set
-CONFIG_RAMFS=y
-
-#
-# Miscellaneous filesystems
-#
-# CONFIG_ADFS_FS is not set
-# CONFIG_AFFS_FS is not set
-# CONFIG_HFS_FS is not set
-# CONFIG_BEFS_FS is not set
-# CONFIG_BFS_FS is not set
-# CONFIG_EFS_FS is not set
-# CONFIG_CRAMFS is not set
-# CONFIG_VXFS_FS is not set
-# CONFIG_HPFS_FS is not set
-# CONFIG_QNX4FS_FS is not set
-# CONFIG_SYSV_FS is not set
-# CONFIG_UFS_FS is not set
-
-#
-# Network File Systems
-#
-CONFIG_NFS_FS=y
-# CONFIG_NFS_V3 is not set
-# CONFIG_NFS_V4 is not set
-CONFIG_NFSD=y
-# CONFIG_NFSD_V3 is not set
-# CONFIG_NFSD_TCP is not set
-CONFIG_ROOT_NFS=y
-CONFIG_LOCKD=y
-CONFIG_EXPORTFS=y
-CONFIG_SUNRPC=y
-# CONFIG_SUNRPC_GSS is not set
-# CONFIG_SMB_FS is not set
-# CONFIG_CIFS is not set
-# CONFIG_NCP_FS is not set
-# CONFIG_CODA_FS is not set
-# CONFIG_INTERMEZZO_FS is not set
-# CONFIG_AFS_FS is not set
-
-#
-# Partition Types
-#
-# CONFIG_PARTITION_ADVANCED is not set
-CONFIG_MSDOS_PARTITION=y
-
-#
-# Graphics support
-#
-
-#
-# Console display driver support
-#
-# CONFIG_VGA_CONSOLE is not set
-# CONFIG_MDA_CONSOLE is not set
-CONFIG_DUMMY_CONSOLE=y
-
-#
-# Sound
-#
-# CONFIG_SOUND is not set
-
-#
-# USB support
-#
-# CONFIG_USB is not set
-# CONFIG_USB_GADGET is not set
-
-#
-# Bluetooth support
-#
-# CONFIG_BT is not set
-
-#
-# Kernel hacking
-#
-CONFIG_CROSSCOMPILE=y
-# CONFIG_DEBUG_KERNEL is not set
-
-#
-# Security options
-#
-# CONFIG_SECURITY is not set
-
-#
-# Cryptographic options
-#
-# CONFIG_CRYPTO is not set
-
-#
-# Library routines
-#
-# CONFIG_CRC32 is not set
--- diff/arch/mips/defconfig-cobalt	2003-08-20 14:16:25.000000000 +0100
+++ source/arch/mips/defconfig-cobalt	1970-01-01 01:00:00.000000000 +0100
@@ -1,581 +0,0 @@
-#
-# Automatically generated make config: don't edit
-#
-CONFIG_MIPS=y
-# CONFIG_MIPS64 is not set
-CONFIG_MIPS32=y
-
-#
-# Code maturity level options
-#
-CONFIG_EXPERIMENTAL=y
-
-#
-# General setup
-#
-CONFIG_SWAP=y
-CONFIG_SYSVIPC=y
-# CONFIG_BSD_PROCESS_ACCT is not set
-CONFIG_SYSCTL=y
-CONFIG_LOG_BUF_SHIFT=14
-# CONFIG_EMBEDDED is not set
-CONFIG_KALLSYMS=y
-CONFIG_FUTEX=y
-CONFIG_EPOLL=y
-CONFIG_IOSCHED_AS=y
-CONFIG_IOSCHED_DEADLINE=y
-
-#
-# Loadable module support
-#
-# CONFIG_MODULES is not set
-
-#
-# Machine selection
-#
-# CONFIG_ACER_PICA_61 is not set
-# CONFIG_BAGET_MIPS is not set
-# CONFIG_CASIO_E55 is not set
-CONFIG_MIPS_COBALT=y
-# CONFIG_DECSTATION is not set
-# CONFIG_MIPS_EV64120 is not set
-# CONFIG_MIPS_EV96100 is not set
-# CONFIG_MIPS_IVR is not set
-# CONFIG_LASAT is not set
-# CONFIG_HP_LASERJET is not set
-# CONFIG_IBM_WORKPAD is not set
-# CONFIG_MIPS_ITE8172 is not set
-# CONFIG_MIPS_ATLAS is not set
-# CONFIG_MIPS_MAGNUM_4000 is not set
-# CONFIG_MIPS_MALTA is not set
-# CONFIG_MIPS_SEAD is not set
-# CONFIG_MOMENCO_OCELOT is not set
-# CONFIG_MOMENCO_OCELOT_G is not set
-# CONFIG_MOMENCO_OCELOT_C is not set
-# CONFIG_DDB5074 is not set
-# CONFIG_DDB5476 is not set
-# CONFIG_DDB5477 is not set
-# CONFIG_NEC_OSPREY is not set
-# CONFIG_NEC_EAGLE is not set
-# CONFIG_OLIVETTI_M700 is not set
-# CONFIG_SGI_IP22 is not set
-# CONFIG_SGI_IP32 is not set
-# CONFIG_SOC_AU1X00 is not set
-# CONFIG_SIBYTE_SB1xxx_SOC is not set
-# CONFIG_SNI_RM200_PCI is not set
-# CONFIG_TANBAC_TB0226 is not set
-# CONFIG_TANBAC_TB0229 is not set
-# CONFIG_TOSHIBA_JMR3927 is not set
-# CONFIG_TOSHIBA_RBTX4927 is not set
-# CONFIG_VICTOR_MPC30X is not set
-# CONFIG_ZAO_CAPCELLA is not set
-CONFIG_RWSEM_GENERIC_SPINLOCK=y
-CONFIG_I8259=y
-CONFIG_NONCOHERENT_IO=y
-CONFIG_CPU_LITTLE_ENDIAN=y
-CONFIG_COBALT_LCD=y
-# CONFIG_FB is not set
-
-#
-# CPU selection
-#
-# CONFIG_CPU_MIPS32 is not set
-# CONFIG_CPU_MIPS64 is not set
-# CONFIG_CPU_R3000 is not set
-# CONFIG_CPU_TX39XX is not set
-# CONFIG_CPU_VR41XX is not set
-# CONFIG_CPU_R4300 is not set
-# CONFIG_CPU_R4X00 is not set
-# CONFIG_CPU_TX49XX is not set
-# CONFIG_CPU_R5000 is not set
-# CONFIG_CPU_R5432 is not set
-# CONFIG_CPU_R6000 is not set
-CONFIG_CPU_NEVADA=y
-# CONFIG_CPU_R8000 is not set
-# CONFIG_CPU_R10000 is not set
-# CONFIG_CPU_RM7000 is not set
-# CONFIG_CPU_SB1 is not set
-# CONFIG_CPU_ADVANCED is not set
-CONFIG_CPU_HAS_LLSC=y
-CONFIG_CPU_HAS_LLDSCD=y
-CONFIG_CPU_HAS_SYNC=y
-# CONFIG_PREEMPT is not set
-# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
-
-#
-# Bus options (PCI, PCMCIA, EISA, ISA, TC)
-#
-CONFIG_PCI=y
-CONFIG_PCI_LEGACY_PROC=y
-CONFIG_PCI_NAMES=y
-CONFIG_MMU=y
-# CONFIG_HOTPLUG is not set
-
-#
-# Executable file formats
-#
-CONFIG_KCORE_ELF=y
-CONFIG_BINFMT_ELF=y
-# CONFIG_BINFMT_MISC is not set
-CONFIG_TRAD_SIGNALS=y
-
-#
-# Memory Technology Devices (MTD)
-#
-# CONFIG_MTD is not set
-
-#
-# Parallel port support
-#
-# CONFIG_PARPORT is not set
-
-#
-# Plug and Play support
-#
-# CONFIG_PNP is not set
-
-#
-# Generic Driver Options
-#
-# CONFIG_FW_LOADER is not set
-
-#
-# Block devices
-#
-# CONFIG_BLK_DEV_FD is not set
-# CONFIG_BLK_CPQ_DA is not set
-# CONFIG_BLK_CPQ_CISS_DA is not set
-# CONFIG_BLK_DEV_DAC960 is not set
-# CONFIG_BLK_DEV_UMEM is not set
-CONFIG_BLK_DEV_LOOP=y
-# CONFIG_BLK_DEV_CRYPTOLOOP is not set
-# CONFIG_BLK_DEV_NBD is not set
-# CONFIG_BLK_DEV_RAM is not set
-# CONFIG_BLK_DEV_INITRD is not set
-# CONFIG_LBD is not set
-
-#
-# ATA/ATAPI/MFM/RLL support
-#
-CONFIG_IDE=y
-
-#
-# IDE, ATA and ATAPI Block devices
-#
-CONFIG_BLK_DEV_IDE=y
-
-#
-# Please see Documentation/ide.txt for help/info on IDE drives
-#
-# CONFIG_BLK_DEV_HD is not set
-CONFIG_BLK_DEV_IDEDISK=y
-# CONFIG_IDEDISK_MULTI_MODE is not set
-# CONFIG_IDEDISK_STROKE is not set
-# CONFIG_BLK_DEV_IDECD is not set
-# CONFIG_BLK_DEV_IDEFLOPPY is not set
-# CONFIG_IDE_TASK_IOCTL is not set
-CONFIG_IDE_TASKFILE_IO=y
-
-#
-# IDE chipset support/bugfixes
-#
-# CONFIG_BLK_DEV_IDEPCI is not set
-
-#
-# SCSI device support
-#
-# CONFIG_SCSI is not set
-
-#
-# Multi-device support (RAID and LVM)
-#
-# CONFIG_MD is not set
-
-#
-# Fusion MPT device support
-#
-
-#
-# IEEE 1394 (FireWire) support (EXPERIMENTAL)
-#
-# CONFIG_IEEE1394 is not set
-
-#
-# I2O device support
-#
-# CONFIG_I2O is not set
-
-#
-# Networking support
-#
-CONFIG_NET=y
-
-#
-# Networking options
-#
-CONFIG_PACKET=y
-# CONFIG_PACKET_MMAP is not set
-CONFIG_NETLINK_DEV=y
-# CONFIG_NETFILTER is not set
-CONFIG_UNIX=y
-CONFIG_NET_KEY=y
-CONFIG_INET=y
-# CONFIG_IP_MULTICAST is not set
-# CONFIG_IP_ADVANCED_ROUTER is not set
-# CONFIG_IP_PNP is not set
-# CONFIG_NET_IPIP is not set
-# CONFIG_NET_IPGRE is not set
-# CONFIG_ARPD is not set
-# CONFIG_INET_ECN is not set
-# CONFIG_SYN_COOKIES is not set
-# CONFIG_INET_AH is not set
-# CONFIG_INET_ESP is not set
-# CONFIG_INET_IPCOMP is not set
-# CONFIG_IPV6 is not set
-# CONFIG_XFRM_USER is not set
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
-CONFIG_IPV6_SCTP__=y
-# CONFIG_IP_SCTP is not set
-# CONFIG_ATM is not set
-# CONFIG_VLAN_8021Q is not set
-# CONFIG_LLC is not set
-# CONFIG_DECNET is not set
-# CONFIG_BRIDGE is not set
-# CONFIG_X25 is not set
-# CONFIG_LAPB is not set
-# CONFIG_NET_DIVERT is not set
-# CONFIG_ECONET is not set
-# CONFIG_WAN_ROUTER is not set
-# CONFIG_NET_FASTROUTE is not set
-# CONFIG_NET_HW_FLOWCONTROL is not set
-
-#
-# QoS and/or fair queueing
-#
-# CONFIG_NET_SCHED is not set
-
-#
-# Network testing
-#
-# CONFIG_NET_PKTGEN is not set
-CONFIG_NETDEVICES=y
-
-#
-# ARCnet devices
-#
-# CONFIG_ARCNET is not set
-# CONFIG_DUMMY is not set
-# CONFIG_BONDING is not set
-# CONFIG_EQUALIZER is not set
-# CONFIG_TUN is not set
-# CONFIG_ETHERTAP is not set
-
-#
-# Ethernet (10 or 100Mbit)
-#
-CONFIG_NET_ETHERNET=y
-# CONFIG_MII is not set
-# CONFIG_HAPPYMEAL is not set
-# CONFIG_SUNGEM is not set
-# CONFIG_NET_VENDOR_3COM is not set
-
-#
-# Tulip family network device support
-#
-# CONFIG_NET_TULIP is not set
-# CONFIG_HP100 is not set
-# CONFIG_NET_PCI is not set
-
-#
-# Ethernet (1000 Mbit)
-#
-# CONFIG_ACENIC is not set
-# CONFIG_DL2K is not set
-# CONFIG_E1000 is not set
-# CONFIG_NS83820 is not set
-# CONFIG_HAMACHI is not set
-# CONFIG_YELLOWFIN is not set
-# CONFIG_R8169 is not set
-# CONFIG_SK98LIN is not set
-# CONFIG_TIGON3 is not set
-
-#
-# Ethernet (10000 Mbit)
-#
-# CONFIG_IXGB is not set
-# CONFIG_FDDI is not set
-# CONFIG_HIPPI is not set
-# CONFIG_PPP is not set
-# CONFIG_SLIP is not set
-
-#
-# Wireless LAN (non-hamradio)
-#
-# CONFIG_NET_RADIO is not set
-
-#
-# Token Ring devices (depends on LLC=y)
-#
-# CONFIG_RCPCI is not set
-# CONFIG_SHAPER is not set
-
-#
-# Wan interfaces
-#
-# CONFIG_WAN is not set
-
-#
-# Amateur Radio support
-#
-# CONFIG_HAMRADIO is not set
-
-#
-# IrDA (infrared) support
-#
-# CONFIG_IRDA is not set
-
-#
-# ISDN subsystem
-#
-# CONFIG_ISDN_BOOL is not set
-
-#
-# Telephony Support
-#
-# CONFIG_PHONE is not set
-
-#
-# Input device support
-#
-CONFIG_INPUT=y
-
-#
-# Userland interfaces
-#
-# CONFIG_INPUT_MOUSEDEV is not set
-# CONFIG_INPUT_JOYDEV is not set
-# CONFIG_INPUT_TSDEV is not set
-# CONFIG_INPUT_EVDEV is not set
-# CONFIG_INPUT_EVBUG is not set
-
-#
-# Input I/O drivers
-#
-# CONFIG_GAMEPORT is not set
-CONFIG_SOUND_GAMEPORT=y
-CONFIG_SERIO=y
-# CONFIG_SERIO_I8042 is not set
-CONFIG_SERIO_SERPORT=y
-# CONFIG_SERIO_CT82C710 is not set
-# CONFIG_SERIO_PCIPS2 is not set
-
-#
-# Input Device Drivers
-#
-# CONFIG_INPUT_KEYBOARD is not set
-# CONFIG_INPUT_MOUSE is not set
-# CONFIG_INPUT_JOYSTICK is not set
-# CONFIG_INPUT_TOUCHSCREEN is not set
-# CONFIG_INPUT_MISC is not set
-
-#
-# Character devices
-#
-# CONFIG_VT is not set
-# CONFIG_SERIAL_NONSTANDARD is not set
-
-#
-# Serial drivers
-#
-CONFIG_SERIAL_8250=y
-CONFIG_SERIAL_8250_CONSOLE=y
-# CONFIG_SERIAL_8250_EXTENDED is not set
-
-#
-# Non-8250 serial port support
-#
-CONFIG_SERIAL_CORE=y
-CONFIG_SERIAL_CORE_CONSOLE=y
-CONFIG_UNIX98_PTYS=y
-CONFIG_UNIX98_PTY_COUNT=16
-
-#
-# I2C support
-#
-# CONFIG_I2C is not set
-
-#
-# I2C Hardware Sensors Mainboard support
-#
-
-#
-# I2C Hardware Sensors Chip support
-#
-# CONFIG_I2C_SENSOR is not set
-
-#
-# Mice
-#
-# CONFIG_BUSMOUSE is not set
-# CONFIG_QIC02_TAPE is not set
-
-#
-# IPMI
-#
-# CONFIG_IPMI_HANDLER is not set
-
-#
-# Watchdog Cards
-#
-# CONFIG_WATCHDOG is not set
-# CONFIG_NVRAM is not set
-CONFIG_RTC=y
-# CONFIG_DTLK is not set
-# CONFIG_R3964 is not set
-# CONFIG_APPLICOM is not set
-
-#
-# Ftape, the floppy tape device driver
-#
-# CONFIG_FTAPE is not set
-# CONFIG_AGP is not set
-# CONFIG_DRM is not set
-# CONFIG_RAW_DRIVER is not set
-CONFIG_HANGCHECK_TIMER=y
-
-#
-# Multimedia devices
-#
-# CONFIG_VIDEO_DEV is not set
-
-#
-# Digital Video Broadcasting Devices
-#
-# CONFIG_DVB is not set
-
-#
-# File systems
-#
-CONFIG_EXT2_FS=y
-CONFIG_EXT2_FS_XATTR=y
-CONFIG_EXT2_FS_POSIX_ACL=y
-CONFIG_EXT2_FS_SECURITY=y
-# CONFIG_EXT3_FS is not set
-# CONFIG_JBD is not set
-CONFIG_FS_MBCACHE=y
-# CONFIG_REISERFS_FS is not set
-# CONFIG_JFS_FS is not set
-CONFIG_FS_POSIX_ACL=y
-# CONFIG_XFS_FS is not set
-# CONFIG_MINIX_FS is not set
-# CONFIG_ROMFS_FS is not set
-# CONFIG_QUOTA is not set
-# CONFIG_AUTOFS_FS is not set
-# CONFIG_AUTOFS4_FS is not set
-
-#
-# CD-ROM/DVD Filesystems
-#
-# CONFIG_ISO9660_FS is not set
-# CONFIG_UDF_FS is not set
-
-#
-# DOS/FAT/NT Filesystems
-#
-# CONFIG_FAT_FS is not set
-# CONFIG_NTFS_FS is not set
-
-#
-# Pseudo filesystems
-#
-CONFIG_PROC_FS=y
-# CONFIG_DEVFS_FS is not set
-CONFIG_DEVPTS_FS=y
-CONFIG_DEVPTS_FS_XATTR=y
-CONFIG_DEVPTS_FS_SECURITY=y
-# CONFIG_TMPFS is not set
-CONFIG_RAMFS=y
-
-#
-# Miscellaneous filesystems
-#
-# CONFIG_ADFS_FS is not set
-# CONFIG_AFFS_FS is not set
-# CONFIG_HFS_FS is not set
-# CONFIG_BEFS_FS is not set
-# CONFIG_BFS_FS is not set
-# CONFIG_EFS_FS is not set
-# CONFIG_CRAMFS is not set
-# CONFIG_VXFS_FS is not set
-# CONFIG_HPFS_FS is not set
-# CONFIG_QNX4FS_FS is not set
-# CONFIG_SYSV_FS is not set
-# CONFIG_UFS_FS is not set
-
-#
-# Network File Systems
-#
-CONFIG_NFS_FS=y
-# CONFIG_NFS_V3 is not set
-# CONFIG_NFS_V4 is not set
-# CONFIG_NFSD is not set
-CONFIG_LOCKD=y
-# CONFIG_EXPORTFS is not set
-CONFIG_SUNRPC=y
-# CONFIG_SUNRPC_GSS is not set
-# CONFIG_SMB_FS is not set
-# CONFIG_CIFS is not set
-# CONFIG_NCP_FS is not set
-# CONFIG_CODA_FS is not set
-# CONFIG_INTERMEZZO_FS is not set
-# CONFIG_AFS_FS is not set
-
-#
-# Partition Types
-#
-# CONFIG_PARTITION_ADVANCED is not set
-CONFIG_MSDOS_PARTITION=y
-
-#
-# Graphics support
-#
-
-#
-# Sound
-#
-# CONFIG_SOUND is not set
-
-#
-# USB support
-#
-# CONFIG_USB is not set
-# CONFIG_USB_GADGET is not set
-
-#
-# Bluetooth support
-#
-# CONFIG_BT is not set
-
-#
-# Kernel hacking
-#
-CONFIG_CROSSCOMPILE=y
-# CONFIG_DEBUG_KERNEL is not set
-
-#
-# Security options
-#
-# CONFIG_SECURITY is not set
-
-#
-# Cryptographic options
-#
-# CONFIG_CRYPTO is not set
-
-#
-# Library routines
-#
-# CONFIG_CRC32 is not set
--- diff/arch/mips/defconfig-ddb5476	2003-08-20 14:16:25.000000000 +0100
+++ source/arch/mips/defconfig-ddb5476	1970-01-01 01:00:00.000000000 +0100
@@ -1,616 +0,0 @@
-#
-# Automatically generated make config: don't edit
-#
-CONFIG_MIPS=y
-# CONFIG_MIPS64 is not set
-CONFIG_MIPS32=y
-
-#
-# Code maturity level options
-#
-CONFIG_EXPERIMENTAL=y
-
-#
-# General setup
-#
-CONFIG_SWAP=y
-CONFIG_SYSVIPC=y
-# CONFIG_BSD_PROCESS_ACCT is not set
-CONFIG_SYSCTL=y
-CONFIG_LOG_BUF_SHIFT=14
-# CONFIG_EMBEDDED is not set
-CONFIG_KALLSYMS=y
-CONFIG_FUTEX=y
-CONFIG_EPOLL=y
-CONFIG_IOSCHED_AS=y
-CONFIG_IOSCHED_DEADLINE=y
-
-#
-# Loadable module support
-#
-# CONFIG_MODULES is not set
-
-#
-# Machine selection
-#
-# CONFIG_ACER_PICA_61 is not set
-# CONFIG_BAGET_MIPS is not set
-# CONFIG_CASIO_E55 is not set
-# CONFIG_MIPS_COBALT is not set
-# CONFIG_DECSTATION is not set
-# CONFIG_MIPS_EV64120 is not set
-# CONFIG_MIPS_EV96100 is not set
-# CONFIG_MIPS_IVR is not set
-# CONFIG_LASAT is not set
-# CONFIG_HP_LASERJET is not set
-# CONFIG_IBM_WORKPAD is not set
-# CONFIG_MIPS_ITE8172 is not set
-# CONFIG_MIPS_ATLAS is not set
-# CONFIG_MIPS_MAGNUM_4000 is not set
-# CONFIG_MIPS_MALTA is not set
-# CONFIG_MIPS_SEAD is not set
-# CONFIG_MOMENCO_OCELOT is not set
-# CONFIG_MOMENCO_OCELOT_G is not set
-# CONFIG_MOMENCO_OCELOT_C is not set
-# CONFIG_DDB5074 is not set
-CONFIG_DDB5476=y
-# CONFIG_DDB5477 is not set
-# CONFIG_NEC_OSPREY is not set
-# CONFIG_NEC_EAGLE is not set
-# CONFIG_OLIVETTI_M700 is not set
-# CONFIG_SGI_IP22 is not set
-# CONFIG_SGI_IP32 is not set
-# CONFIG_SOC_AU1X00 is not set
-# CONFIG_SIBYTE_SB1xxx_SOC is not set
-# CONFIG_SNI_RM200_PCI is not set
-# CONFIG_TANBAC_TB0226 is not set
-# CONFIG_TANBAC_TB0229 is not set
-# CONFIG_TOSHIBA_JMR3927 is not set
-# CONFIG_TOSHIBA_RBTX4927 is not set
-# CONFIG_VICTOR_MPC30X is not set
-# CONFIG_ZAO_CAPCELLA is not set
-CONFIG_RWSEM_GENERIC_SPINLOCK=y
-CONFIG_I8259=y
-CONFIG_NONCOHERENT_IO=y
-CONFIG_CPU_LITTLE_ENDIAN=y
-CONFIG_IRQ_CPU=y
-CONFIG_DDB5XXX_COMMON=y
-CONFIG_NEW_PCI=y
-CONFIG_FB=y
-CONFIG_HAVE_STD_PC_SERIAL_PORT=y
-
-#
-# CPU selection
-#
-# CONFIG_CPU_MIPS32 is not set
-# CONFIG_CPU_MIPS64 is not set
-# CONFIG_CPU_R3000 is not set
-# CONFIG_CPU_TX39XX is not set
-# CONFIG_CPU_VR41XX is not set
-# CONFIG_CPU_R4300 is not set
-# CONFIG_CPU_R4X00 is not set
-# CONFIG_CPU_TX49XX is not set
-# CONFIG_CPU_R5000 is not set
-CONFIG_CPU_R5432=y
-# CONFIG_CPU_R6000 is not set
-# CONFIG_CPU_NEVADA is not set
-# CONFIG_CPU_R8000 is not set
-# CONFIG_CPU_R10000 is not set
-# CONFIG_CPU_RM7000 is not set
-# CONFIG_CPU_SB1 is not set
-# CONFIG_CPU_ADVANCED is not set
-CONFIG_CPU_HAS_LLSC=y
-CONFIG_CPU_HAS_LLDSCD=y
-CONFIG_CPU_HAS_SYNC=y
-# CONFIG_PREEMPT is not set
-# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
-
-#
-# Bus options (PCI, PCMCIA, EISA, ISA, TC)
-#
-CONFIG_PCI=y
-CONFIG_PCI_LEGACY_PROC=y
-CONFIG_PCI_NAMES=y
-CONFIG_MMU=y
-# CONFIG_HOTPLUG is not set
-
-#
-# Executable file formats
-#
-CONFIG_KCORE_ELF=y
-CONFIG_BINFMT_ELF=y
-# CONFIG_BINFMT_MISC is not set
-CONFIG_TRAD_SIGNALS=y
-
-#
-# Memory Technology Devices (MTD)
-#
-# CONFIG_MTD is not set
-
-#
-# Parallel port support
-#
-# CONFIG_PARPORT is not set
-
-#
-# Plug and Play support
-#
-# CONFIG_PNP is not set
-
-#
-# Generic Driver Options
-#
-# CONFIG_FW_LOADER is not set
-
-#
-# Block devices
-#
-# CONFIG_BLK_DEV_FD is not set
-# CONFIG_BLK_CPQ_DA is not set
-# CONFIG_BLK_CPQ_CISS_DA is not set
-# CONFIG_BLK_DEV_DAC960 is not set
-# CONFIG_BLK_DEV_UMEM is not set
-# CONFIG_BLK_DEV_LOOP is not set
-# CONFIG_BLK_DEV_NBD is not set
-# CONFIG_BLK_DEV_RAM is not set
-# CONFIG_BLK_DEV_INITRD is not set
-# CONFIG_LBD is not set
-
-#
-# ATA/ATAPI/MFM/RLL support
-#
-CONFIG_IDE=y
-
-#
-# IDE, ATA and ATAPI Block devices
-#
-CONFIG_BLK_DEV_IDE=y
-
-#
-# Please see Documentation/ide.txt for help/info on IDE drives
-#
-# CONFIG_BLK_DEV_HD is not set
-CONFIG_BLK_DEV_IDEDISK=y
-# CONFIG_IDEDISK_MULTI_MODE is not set
-# CONFIG_IDEDISK_STROKE is not set
-# CONFIG_BLK_DEV_IDECD is not set
-# CONFIG_BLK_DEV_IDEFLOPPY is not set
-# CONFIG_IDE_TASK_IOCTL is not set
-CONFIG_IDE_TASKFILE_IO=y
-
-#
-# IDE chipset support/bugfixes
-#
-# CONFIG_BLK_DEV_IDEPCI is not set
-
-#
-# SCSI device support
-#
-# CONFIG_SCSI is not set
-
-#
-# Multi-device support (RAID and LVM)
-#
-# CONFIG_MD is not set
-
-#
-# Fusion MPT device support
-#
-
-#
-# IEEE 1394 (FireWire) support (EXPERIMENTAL)
-#
-# CONFIG_IEEE1394 is not set
-
-#
-# I2O device support
-#
-# CONFIG_I2O is not set
-
-#
-# Networking support
-#
-CONFIG_NET=y
-
-#
-# Networking options
-#
-CONFIG_PACKET=y
-# CONFIG_PACKET_MMAP is not set
-CONFIG_NETLINK_DEV=y
-# CONFIG_NETFILTER is not set
-CONFIG_UNIX=y
-CONFIG_NET_KEY=y
-CONFIG_INET=y
-# CONFIG_IP_MULTICAST is not set
-# CONFIG_IP_ADVANCED_ROUTER is not set
-CONFIG_IP_PNP=y
-# CONFIG_IP_PNP_DHCP is not set
-CONFIG_IP_PNP_BOOTP=y
-# CONFIG_IP_PNP_RARP is not set
-# CONFIG_NET_IPIP is not set
-# CONFIG_NET_IPGRE is not set
-# CONFIG_ARPD is not set
-# CONFIG_INET_ECN is not set
-# CONFIG_SYN_COOKIES is not set
-# CONFIG_INET_AH is not set
-# CONFIG_INET_ESP is not set
-# CONFIG_INET_IPCOMP is not set
-# CONFIG_IPV6 is not set
-# CONFIG_XFRM_USER is not set
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
-CONFIG_IPV6_SCTP__=y
-# CONFIG_IP_SCTP is not set
-# CONFIG_ATM is not set
-# CONFIG_VLAN_8021Q is not set
-# CONFIG_LLC is not set
-# CONFIG_DECNET is not set
-# CONFIG_BRIDGE is not set
-# CONFIG_X25 is not set
-# CONFIG_LAPB is not set
-# CONFIG_NET_DIVERT is not set
-# CONFIG_ECONET is not set
-# CONFIG_WAN_ROUTER is not set
-# CONFIG_NET_FASTROUTE is not set
-# CONFIG_NET_HW_FLOWCONTROL is not set
-
-#
-# QoS and/or fair queueing
-#
-# CONFIG_NET_SCHED is not set
-
-#
-# Network testing
-#
-# CONFIG_NET_PKTGEN is not set
-CONFIG_NETDEVICES=y
-
-#
-# ARCnet devices
-#
-# CONFIG_ARCNET is not set
-# CONFIG_DUMMY is not set
-# CONFIG_BONDING is not set
-# CONFIG_EQUALIZER is not set
-# CONFIG_TUN is not set
-# CONFIG_ETHERTAP is not set
-
-#
-# Ethernet (10 or 100Mbit)
-#
-CONFIG_NET_ETHERNET=y
-# CONFIG_MII is not set
-# CONFIG_HAPPYMEAL is not set
-# CONFIG_SUNGEM is not set
-# CONFIG_NET_VENDOR_3COM is not set
-
-#
-# Tulip family network device support
-#
-# CONFIG_NET_TULIP is not set
-# CONFIG_HP100 is not set
-# CONFIG_NET_PCI is not set
-
-#
-# Ethernet (1000 Mbit)
-#
-# CONFIG_ACENIC is not set
-# CONFIG_DL2K is not set
-# CONFIG_E1000 is not set
-# CONFIG_NS83820 is not set
-# CONFIG_HAMACHI is not set
-# CONFIG_YELLOWFIN is not set
-# CONFIG_R8169 is not set
-# CONFIG_SK98LIN is not set
-# CONFIG_TIGON3 is not set
-
-#
-# Ethernet (10000 Mbit)
-#
-# CONFIG_IXGB is not set
-# CONFIG_FDDI is not set
-# CONFIG_HIPPI is not set
-# CONFIG_PPP is not set
-# CONFIG_SLIP is not set
-
-#
-# Wireless LAN (non-hamradio)
-#
-# CONFIG_NET_RADIO is not set
-
-#
-# Token Ring devices (depends on LLC=y)
-#
-# CONFIG_RCPCI is not set
-# CONFIG_SHAPER is not set
-
-#
-# Wan interfaces
-#
-# CONFIG_WAN is not set
-
-#
-# Amateur Radio support
-#
-# CONFIG_HAMRADIO is not set
-
-#
-# IrDA (infrared) support
-#
-# CONFIG_IRDA is not set
-
-#
-# ISDN subsystem
-#
-# CONFIG_ISDN_BOOL is not set
-
-#
-# Telephony Support
-#
-# CONFIG_PHONE is not set
-
-#
-# Input device support
-#
-CONFIG_INPUT=y
-
-#
-# Userland interfaces
-#
-# CONFIG_INPUT_MOUSEDEV is not set
-# CONFIG_INPUT_JOYDEV is not set
-# CONFIG_INPUT_TSDEV is not set
-# CONFIG_INPUT_EVDEV is not set
-# CONFIG_INPUT_EVBUG is not set
-
-#
-# Input I/O drivers
-#
-# CONFIG_GAMEPORT is not set
-CONFIG_SOUND_GAMEPORT=y
-CONFIG_SERIO=y
-# CONFIG_SERIO_I8042 is not set
-CONFIG_SERIO_SERPORT=y
-# CONFIG_SERIO_CT82C710 is not set
-# CONFIG_SERIO_PCIPS2 is not set
-
-#
-# Input Device Drivers
-#
-# CONFIG_INPUT_KEYBOARD is not set
-# CONFIG_INPUT_MOUSE is not set
-# CONFIG_INPUT_JOYSTICK is not set
-# CONFIG_INPUT_TOUCHSCREEN is not set
-# CONFIG_INPUT_MISC is not set
-
-#
-# Character devices
-#
-CONFIG_VT=y
-# CONFIG_VT_CONSOLE is not set
-CONFIG_HW_CONSOLE=y
-# CONFIG_SERIAL_NONSTANDARD is not set
-
-#
-# Serial drivers
-#
-CONFIG_SERIAL_8250=y
-CONFIG_SERIAL_8250_CONSOLE=y
-# CONFIG_SERIAL_8250_EXTENDED is not set
-
-#
-# Non-8250 serial port support
-#
-CONFIG_SERIAL_CORE=y
-CONFIG_SERIAL_CORE_CONSOLE=y
-CONFIG_UNIX98_PTYS=y
-CONFIG_UNIX98_PTY_COUNT=256
-
-#
-# I2C support
-#
-# CONFIG_I2C is not set
-
-#
-# I2C Hardware Sensors Mainboard support
-#
-
-#
-# I2C Hardware Sensors Chip support
-#
-# CONFIG_I2C_SENSOR is not set
-
-#
-# Mice
-#
-# CONFIG_BUSMOUSE is not set
-# CONFIG_QIC02_TAPE is not set
-
-#
-# IPMI
-#
-# CONFIG_IPMI_HANDLER is not set
-
-#
-# Watchdog Cards
-#
-# CONFIG_WATCHDOG is not set
-# CONFIG_NVRAM is not set
-# CONFIG_RTC is not set
-# CONFIG_GEN_RTC is not set
-# CONFIG_DTLK is not set
-# CONFIG_R3964 is not set
-# CONFIG_APPLICOM is not set
-
-#
-# Ftape, the floppy tape device driver
-#
-# CONFIG_FTAPE is not set
-# CONFIG_AGP is not set
-# CONFIG_DRM is not set
-# CONFIG_RAW_DRIVER is not set
-# CONFIG_HANGCHECK_TIMER is not set
-
-#
-# Multimedia devices
-#
-# CONFIG_VIDEO_DEV is not set
-
-#
-# Digital Video Broadcasting Devices
-#
-# CONFIG_DVB is not set
-
-#
-# File systems
-#
-CONFIG_EXT2_FS=y
-# CONFIG_EXT2_FS_XATTR is not set
-# CONFIG_EXT3_FS is not set
-# CONFIG_JBD is not set
-# CONFIG_REISERFS_FS is not set
-# CONFIG_JFS_FS is not set
-# CONFIG_XFS_FS is not set
-# CONFIG_MINIX_FS is not set
-# CONFIG_ROMFS_FS is not set
-# CONFIG_QUOTA is not set
-# CONFIG_AUTOFS_FS is not set
-# CONFIG_AUTOFS4_FS is not set
-
-#
-# CD-ROM/DVD Filesystems
-#
-# CONFIG_ISO9660_FS is not set
-# CONFIG_UDF_FS is not set
-
-#
-# DOS/FAT/NT Filesystems
-#
-# CONFIG_FAT_FS is not set
-# CONFIG_NTFS_FS is not set
-
-#
-# Pseudo filesystems
-#
-CONFIG_PROC_FS=y
-# CONFIG_DEVFS_FS is not set
-CONFIG_DEVPTS_FS=y
-CONFIG_DEVPTS_FS_XATTR=y
-CONFIG_DEVPTS_FS_SECURITY=y
-# CONFIG_TMPFS is not set
-CONFIG_RAMFS=y
-
-#
-# Miscellaneous filesystems
-#
-# CONFIG_ADFS_FS is not set
-# CONFIG_AFFS_FS is not set
-# CONFIG_HFS_FS is not set
-# CONFIG_BEFS_FS is not set
-# CONFIG_BFS_FS is not set
-# CONFIG_EFS_FS is not set
-# CONFIG_CRAMFS is not set
-# CONFIG_VXFS_FS is not set
-# CONFIG_HPFS_FS is not set
-# CONFIG_QNX4FS_FS is not set
-# CONFIG_SYSV_FS is not set
-# CONFIG_UFS_FS is not set
-
-#
-# Network File Systems
-#
-CONFIG_NFS_FS=y
-# CONFIG_NFS_V3 is not set
-# CONFIG_NFS_V4 is not set
-# CONFIG_NFSD is not set
-CONFIG_ROOT_NFS=y
-CONFIG_LOCKD=y
-# CONFIG_EXPORTFS is not set
-CONFIG_SUNRPC=y
-# CONFIG_SUNRPC_GSS is not set
-# CONFIG_SMB_FS is not set
-# CONFIG_CIFS is not set
-# CONFIG_NCP_FS is not set
-# CONFIG_CODA_FS is not set
-# CONFIG_INTERMEZZO_FS is not set
-# CONFIG_AFS_FS is not set
-
-#
-# Partition Types
-#
-# CONFIG_PARTITION_ADVANCED is not set
-CONFIG_MSDOS_PARTITION=y
-
-#
-# Graphics support
-#
-# CONFIG_FB_CIRRUS is not set
-# CONFIG_FB_PM2 is not set
-# CONFIG_FB_CYBER2000 is not set
-# CONFIG_FB_IMSTT is not set
-# CONFIG_FB_RIVA is not set
-# CONFIG_FB_MATROX is not set
-# CONFIG_FB_RADEON is not set
-# CONFIG_FB_ATY128 is not set
-# CONFIG_FB_ATY is not set
-# CONFIG_FB_SIS is not set
-# CONFIG_FB_NEOMAGIC is not set
-# CONFIG_FB_3DFX is not set
-# CONFIG_FB_VOODOO1 is not set
-# CONFIG_FB_TRIDENT is not set
-# CONFIG_FB_PM3 is not set
-# CONFIG_FB_E1356 is not set
-# CONFIG_FB_VIRTUAL is not set
-
-#
-# Console display driver support
-#
-# CONFIG_VGA_CONSOLE is not set
-# CONFIG_MDA_CONSOLE is not set
-CONFIG_DUMMY_CONSOLE=y
-# CONFIG_FRAMEBUFFER_CONSOLE is not set
-
-#
-# Logo configuration
-#
-# CONFIG_LOGO is not set
-
-#
-# Sound
-#
-# CONFIG_SOUND is not set
-
-#
-# USB support
-#
-# CONFIG_USB is not set
-# CONFIG_USB_GADGET is not set
-
-#
-# Bluetooth support
-#
-# CONFIG_BT is not set
-
-#
-# Kernel hacking
-#
-CONFIG_CROSSCOMPILE=y
-# CONFIG_DEBUG_KERNEL is not set
-
-#
-# Security options
-#
-# CONFIG_SECURITY is not set
-
-#
-# Cryptographic options
-#
-# CONFIG_CRYPTO is not set
-
-#
-# Library routines
-#
-# CONFIG_CRC32 is not set
--- diff/arch/mips/defconfig-ddb5477	2003-08-20 14:16:25.000000000 +0100
+++ source/arch/mips/defconfig-ddb5477	1970-01-01 01:00:00.000000000 +0100
@@ -1,597 +0,0 @@
-#
-# Automatically generated make config: don't edit
-#
-CONFIG_MIPS=y
-# CONFIG_MIPS64 is not set
-CONFIG_MIPS32=y
-
-#
-# Code maturity level options
-#
-CONFIG_EXPERIMENTAL=y
-
-#
-# General setup
-#
-CONFIG_SWAP=y
-CONFIG_SYSVIPC=y
-# CONFIG_BSD_PROCESS_ACCT is not set
-CONFIG_SYSCTL=y
-CONFIG_LOG_BUF_SHIFT=14
-# CONFIG_EMBEDDED is not set
-CONFIG_KALLSYMS=y
-CONFIG_FUTEX=y
-CONFIG_EPOLL=y
-CONFIG_IOSCHED_AS=y
-CONFIG_IOSCHED_DEADLINE=y
-
-#
-# Loadable module support
-#
-# CONFIG_MODULES is not set
-
-#
-# Machine selection
-#
-# CONFIG_ACER_PICA_61 is not set
-# CONFIG_BAGET_MIPS is not set
-# CONFIG_CASIO_E55 is not set
-# CONFIG_MIPS_COBALT is not set
-# CONFIG_DECSTATION is not set
-# CONFIG_MIPS_EV64120 is not set
-# CONFIG_MIPS_EV96100 is not set
-# CONFIG_MIPS_IVR is not set
-# CONFIG_LASAT is not set
-# CONFIG_HP_LASERJET is not set
-# CONFIG_IBM_WORKPAD is not set
-# CONFIG_MIPS_ITE8172 is not set
-# CONFIG_MIPS_ATLAS is not set
-# CONFIG_MIPS_MAGNUM_4000 is not set
-# CONFIG_MIPS_MALTA is not set
-# CONFIG_MIPS_SEAD is not set
-# CONFIG_MOMENCO_OCELOT is not set
-# CONFIG_MOMENCO_OCELOT_G is not set
-# CONFIG_MOMENCO_OCELOT_C is not set
-# CONFIG_DDB5074 is not set
-# CONFIG_DDB5476 is not set
-CONFIG_DDB5477=y
-CONFIG_DDB5477_BUS_FREQUENCY=0
-# CONFIG_NEC_OSPREY is not set
-# CONFIG_NEC_EAGLE is not set
-# CONFIG_OLIVETTI_M700 is not set
-# CONFIG_SGI_IP22 is not set
-# CONFIG_SGI_IP32 is not set
-# CONFIG_SOC_AU1X00 is not set
-# CONFIG_SIBYTE_SB1xxx_SOC is not set
-# CONFIG_SNI_RM200_PCI is not set
-# CONFIG_TANBAC_TB0226 is not set
-# CONFIG_TANBAC_TB0229 is not set
-# CONFIG_TOSHIBA_JMR3927 is not set
-# CONFIG_TOSHIBA_RBTX4927 is not set
-# CONFIG_VICTOR_MPC30X is not set
-# CONFIG_ZAO_CAPCELLA is not set
-CONFIG_RWSEM_GENERIC_SPINLOCK=y
-CONFIG_I8259=y
-CONFIG_NONCOHERENT_IO=y
-CONFIG_CPU_LITTLE_ENDIAN=y
-CONFIG_IRQ_CPU=y
-CONFIG_DUMMY_KEYB=y
-CONFIG_DDB5XXX_COMMON=y
-CONFIG_NEW_PCI=y
-# CONFIG_FB is not set
-
-#
-# CPU selection
-#
-# CONFIG_CPU_MIPS32 is not set
-# CONFIG_CPU_MIPS64 is not set
-# CONFIG_CPU_R3000 is not set
-# CONFIG_CPU_TX39XX is not set
-# CONFIG_CPU_VR41XX is not set
-# CONFIG_CPU_R4300 is not set
-# CONFIG_CPU_R4X00 is not set
-# CONFIG_CPU_TX49XX is not set
-# CONFIG_CPU_R5000 is not set
-CONFIG_CPU_R5432=y
-# CONFIG_CPU_R6000 is not set
-# CONFIG_CPU_NEVADA is not set
-# CONFIG_CPU_R8000 is not set
-# CONFIG_CPU_R10000 is not set
-# CONFIG_CPU_RM7000 is not set
-# CONFIG_CPU_SB1 is not set
-# CONFIG_CPU_ADVANCED is not set
-CONFIG_CPU_HAS_LLSC=y
-CONFIG_CPU_HAS_LLDSCD=y
-CONFIG_CPU_HAS_SYNC=y
-# CONFIG_PREEMPT is not set
-# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
-
-#
-# Bus options (PCI, PCMCIA, EISA, ISA, TC)
-#
-CONFIG_PCI=y
-CONFIG_PCI_LEGACY_PROC=y
-CONFIG_PCI_NAMES=y
-CONFIG_MMU=y
-# CONFIG_HOTPLUG is not set
-
-#
-# Executable file formats
-#
-CONFIG_KCORE_ELF=y
-CONFIG_BINFMT_ELF=y
-# CONFIG_BINFMT_MISC is not set
-CONFIG_TRAD_SIGNALS=y
-
-#
-# Memory Technology Devices (MTD)
-#
-# CONFIG_MTD is not set
-
-#
-# Parallel port support
-#
-# CONFIG_PARPORT is not set
-
-#
-# Plug and Play support
-#
-# CONFIG_PNP is not set
-
-#
-# Generic Driver Options
-#
-# CONFIG_FW_LOADER is not set
-
-#
-# Block devices
-#
-# CONFIG_BLK_DEV_FD is not set
-# CONFIG_BLK_CPQ_DA is not set
-# CONFIG_BLK_CPQ_CISS_DA is not set
-# CONFIG_BLK_DEV_DAC960 is not set
-# CONFIG_BLK_DEV_UMEM is not set
-# CONFIG_BLK_DEV_LOOP is not set
-# CONFIG_BLK_DEV_NBD is not set
-# CONFIG_BLK_DEV_RAM is not set
-# CONFIG_BLK_DEV_INITRD is not set
-# CONFIG_LBD is not set
-
-#
-# ATA/ATAPI/MFM/RLL support
-#
-# CONFIG_IDE is not set
-
-#
-# SCSI device support
-#
-# CONFIG_SCSI is not set
-
-#
-# Multi-device support (RAID and LVM)
-#
-# CONFIG_MD is not set
-
-#
-# Fusion MPT device support
-#
-
-#
-# IEEE 1394 (FireWire) support (EXPERIMENTAL)
-#
-# CONFIG_IEEE1394 is not set
-
-#
-# I2O device support
-#
-# CONFIG_I2O is not set
-
-#
-# Networking support
-#
-CONFIG_NET=y
-
-#
-# Networking options
-#
-CONFIG_PACKET=y
-# CONFIG_PACKET_MMAP is not set
-CONFIG_NETLINK_DEV=y
-# CONFIG_NETFILTER is not set
-CONFIG_UNIX=y
-CONFIG_NET_KEY=y
-CONFIG_INET=y
-# CONFIG_IP_MULTICAST is not set
-# CONFIG_IP_ADVANCED_ROUTER is not set
-CONFIG_IP_PNP=y
-# CONFIG_IP_PNP_DHCP is not set
-CONFIG_IP_PNP_BOOTP=y
-# CONFIG_IP_PNP_RARP is not set
-# CONFIG_NET_IPIP is not set
-# CONFIG_NET_IPGRE is not set
-# CONFIG_ARPD is not set
-# CONFIG_INET_ECN is not set
-# CONFIG_SYN_COOKIES is not set
-# CONFIG_INET_AH is not set
-# CONFIG_INET_ESP is not set
-# CONFIG_INET_IPCOMP is not set
-# CONFIG_IPV6 is not set
-# CONFIG_XFRM_USER is not set
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
-CONFIG_IPV6_SCTP__=y
-# CONFIG_IP_SCTP is not set
-# CONFIG_ATM is not set
-# CONFIG_VLAN_8021Q is not set
-# CONFIG_LLC is not set
-# CONFIG_DECNET is not set
-# CONFIG_BRIDGE is not set
-# CONFIG_X25 is not set
-# CONFIG_LAPB is not set
-# CONFIG_NET_DIVERT is not set
-# CONFIG_ECONET is not set
-# CONFIG_WAN_ROUTER is not set
-# CONFIG_NET_FASTROUTE is not set
-# CONFIG_NET_HW_FLOWCONTROL is not set
-
-#
-# QoS and/or fair queueing
-#
-# CONFIG_NET_SCHED is not set
-
-#
-# Network testing
-#
-# CONFIG_NET_PKTGEN is not set
-CONFIG_NETDEVICES=y
-
-#
-# ARCnet devices
-#
-# CONFIG_ARCNET is not set
-# CONFIG_DUMMY is not set
-# CONFIG_BONDING is not set
-# CONFIG_EQUALIZER is not set
-# CONFIG_TUN is not set
-# CONFIG_ETHERTAP is not set
-
-#
-# Ethernet (10 or 100Mbit)
-#
-CONFIG_NET_ETHERNET=y
-# CONFIG_MII is not set
-# CONFIG_HAPPYMEAL is not set
-# CONFIG_SUNGEM is not set
-# CONFIG_NET_VENDOR_3COM is not set
-
-#
-# Tulip family network device support
-#
-# CONFIG_NET_TULIP is not set
-# CONFIG_HP100 is not set
-# CONFIG_NET_PCI is not set
-
-#
-# Ethernet (1000 Mbit)
-#
-# CONFIG_ACENIC is not set
-# CONFIG_DL2K is not set
-# CONFIG_E1000 is not set
-# CONFIG_NS83820 is not set
-# CONFIG_HAMACHI is not set
-# CONFIG_YELLOWFIN is not set
-# CONFIG_R8169 is not set
-# CONFIG_SK98LIN is not set
-# CONFIG_TIGON3 is not set
-
-#
-# Ethernet (10000 Mbit)
-#
-# CONFIG_IXGB is not set
-# CONFIG_FDDI is not set
-# CONFIG_HIPPI is not set
-# CONFIG_PPP is not set
-# CONFIG_SLIP is not set
-
-#
-# Wireless LAN (non-hamradio)
-#
-# CONFIG_NET_RADIO is not set
-
-#
-# Token Ring devices (depends on LLC=y)
-#
-# CONFIG_RCPCI is not set
-# CONFIG_SHAPER is not set
-
-#
-# Wan interfaces
-#
-# CONFIG_WAN is not set
-
-#
-# Amateur Radio support
-#
-# CONFIG_HAMRADIO is not set
-
-#
-# IrDA (infrared) support
-#
-# CONFIG_IRDA is not set
-
-#
-# ISDN subsystem
-#
-# CONFIG_ISDN_BOOL is not set
-
-#
-# Telephony Support
-#
-# CONFIG_PHONE is not set
-
-#
-# Input device support
-#
-CONFIG_INPUT=y
-
-#
-# Userland interfaces
-#
-# CONFIG_INPUT_MOUSEDEV is not set
-# CONFIG_INPUT_JOYDEV is not set
-# CONFIG_INPUT_TSDEV is not set
-# CONFIG_INPUT_EVDEV is not set
-# CONFIG_INPUT_EVBUG is not set
-
-#
-# Input I/O drivers
-#
-# CONFIG_GAMEPORT is not set
-CONFIG_SOUND_GAMEPORT=y
-CONFIG_SERIO=y
-# CONFIG_SERIO_I8042 is not set
-CONFIG_SERIO_SERPORT=y
-# CONFIG_SERIO_CT82C710 is not set
-# CONFIG_SERIO_PCIPS2 is not set
-
-#
-# Input Device Drivers
-#
-# CONFIG_INPUT_KEYBOARD is not set
-# CONFIG_INPUT_MOUSE is not set
-# CONFIG_INPUT_JOYSTICK is not set
-# CONFIG_INPUT_TOUCHSCREEN is not set
-# CONFIG_INPUT_MISC is not set
-
-#
-# Character devices
-#
-# CONFIG_VT is not set
-# CONFIG_SERIAL_NONSTANDARD is not set
-
-#
-# Serial drivers
-#
-CONFIG_SERIAL_8250=y
-CONFIG_SERIAL_8250_CONSOLE=y
-# CONFIG_SERIAL_8250_EXTENDED is not set
-
-#
-# Non-8250 serial port support
-#
-CONFIG_SERIAL_CORE=y
-CONFIG_SERIAL_CORE_CONSOLE=y
-CONFIG_UNIX98_PTYS=y
-CONFIG_UNIX98_PTY_COUNT=256
-
-#
-# I2C support
-#
-# CONFIG_I2C is not set
-
-#
-# I2C Hardware Sensors Mainboard support
-#
-
-#
-# I2C Hardware Sensors Chip support
-#
-# CONFIG_I2C_SENSOR is not set
-
-#
-# Mice
-#
-# CONFIG_BUSMOUSE is not set
-# CONFIG_QIC02_TAPE is not set
-
-#
-# IPMI
-#
-# CONFIG_IPMI_HANDLER is not set
-
-#
-# Watchdog Cards
-#
-# CONFIG_WATCHDOG is not set
-# CONFIG_NVRAM is not set
-# CONFIG_RTC is not set
-# CONFIG_GEN_RTC is not set
-# CONFIG_DTLK is not set
-# CONFIG_R3964 is not set
-# CONFIG_APPLICOM is not set
-
-#
-# Ftape, the floppy tape device driver
-#
-# CONFIG_FTAPE is not set
-# CONFIG_AGP is not set
-# CONFIG_DRM is not set
-# CONFIG_RAW_DRIVER is not set
-# CONFIG_HANGCHECK_TIMER is not set
-
-#
-# Multimedia devices
-#
-# CONFIG_VIDEO_DEV is not set
-
-#
-# Digital Video Broadcasting Devices
-#
-# CONFIG_DVB is not set
-
-#
-# File systems
-#
-CONFIG_EXT2_FS=y
-# CONFIG_EXT2_FS_XATTR is not set
-# CONFIG_EXT3_FS is not set
-# CONFIG_JBD is not set
-# CONFIG_REISERFS_FS is not set
-# CONFIG_JFS_FS is not set
-# CONFIG_XFS_FS is not set
-# CONFIG_MINIX_FS is not set
-# CONFIG_ROMFS_FS is not set
-# CONFIG_QUOTA is not set
-CONFIG_AUTOFS_FS=y
-CONFIG_AUTOFS4_FS=y
-
-#
-# CD-ROM/DVD Filesystems
-#
-# CONFIG_ISO9660_FS is not set
-# CONFIG_UDF_FS is not set
-
-#
-# DOS/FAT/NT Filesystems
-#
-# CONFIG_FAT_FS is not set
-# CONFIG_NTFS_FS is not set
-
-#
-# Pseudo filesystems
-#
-CONFIG_PROC_FS=y
-# CONFIG_DEVFS_FS is not set
-CONFIG_DEVPTS_FS=y
-CONFIG_DEVPTS_FS_XATTR=y
-CONFIG_DEVPTS_FS_SECURITY=y
-# CONFIG_TMPFS is not set
-CONFIG_RAMFS=y
-
-#
-# Miscellaneous filesystems
-#
-# CONFIG_ADFS_FS is not set
-# CONFIG_AFFS_FS is not set
-# CONFIG_HFS_FS is not set
-# CONFIG_BEFS_FS is not set
-# CONFIG_BFS_FS is not set
-# CONFIG_EFS_FS is not set
-# CONFIG_CRAMFS is not set
-# CONFIG_VXFS_FS is not set
-# CONFIG_HPFS_FS is not set
-# CONFIG_QNX4FS_FS is not set
-# CONFIG_SYSV_FS is not set
-# CONFIG_UFS_FS is not set
-
-#
-# Network File Systems
-#
-CONFIG_NFS_FS=y
-# CONFIG_NFS_V3 is not set
-# CONFIG_NFS_V4 is not set
-CONFIG_NFSD=y
-# CONFIG_NFSD_V3 is not set
-# CONFIG_NFSD_TCP is not set
-CONFIG_ROOT_NFS=y
-CONFIG_LOCKD=y
-CONFIG_EXPORTFS=y
-CONFIG_SUNRPC=y
-# CONFIG_SUNRPC_GSS is not set
-# CONFIG_SMB_FS is not set
-# CONFIG_CIFS is not set
-# CONFIG_NCP_FS is not set
-# CONFIG_CODA_FS is not set
-# CONFIG_INTERMEZZO_FS is not set
-# CONFIG_AFS_FS is not set
-
-#
-# Partition Types
-#
-# CONFIG_PARTITION_ADVANCED is not set
-CONFIG_MSDOS_PARTITION=y
-
-#
-# Graphics support
-#
-
-#
-# Sound
-#
-CONFIG_SOUND=y
-
-#
-# Advanced Linux Sound Architecture
-#
-# CONFIG_SND is not set
-
-#
-# Open Sound System
-#
-CONFIG_SOUND_PRIME=y
-# CONFIG_SOUND_BT878 is not set
-# CONFIG_SOUND_CMPCI is not set
-# CONFIG_SOUND_EMU10K1 is not set
-# CONFIG_SOUND_FUSION is not set
-# CONFIG_SOUND_CS4281 is not set
-# CONFIG_SOUND_ES1370 is not set
-# CONFIG_SOUND_ES1371 is not set
-# CONFIG_SOUND_ESSSOLO1 is not set
-# CONFIG_SOUND_MAESTRO is not set
-# CONFIG_SOUND_MAESTRO3 is not set
-# CONFIG_SOUND_ICH is not set
-# CONFIG_SOUND_RME96XX is not set
-# CONFIG_SOUND_SONICVIBES is not set
-CONFIG_SOUND_VRC5477=y
-# CONFIG_SOUND_TRIDENT is not set
-# CONFIG_SOUND_MSNDCLAS is not set
-# CONFIG_SOUND_MSNDPIN is not set
-# CONFIG_SOUND_VIA82CXXX is not set
-# CONFIG_SOUND_OSS is not set
-# CONFIG_SOUND_ALI5455 is not set
-# CONFIG_SOUND_FORTE is not set
-# CONFIG_SOUND_AD1980 is not set
-
-#
-# USB support
-#
-# CONFIG_USB is not set
-# CONFIG_USB_GADGET is not set
-
-#
-# Bluetooth support
-#
-# CONFIG_BT is not set
-
-#
-# Kernel hacking
-#
-CONFIG_CROSSCOMPILE=y
-# CONFIG_DEBUG_KERNEL is not set
-
-#
-# Security options
-#
-# CONFIG_SECURITY is not set
-
-#
-# Cryptographic options
-#
-# CONFIG_CRYPTO is not set
-
-#
-# Library routines
-#
-# CONFIG_CRC32 is not set
--- diff/arch/mips/defconfig-decstation	2003-08-20 14:16:25.000000000 +0100
+++ source/arch/mips/defconfig-decstation	1970-01-01 01:00:00.000000000 +0100
@@ -1,565 +0,0 @@
-#
-# Automatically generated make config: don't edit
-#
-CONFIG_MIPS=y
-# CONFIG_MIPS64 is not set
-CONFIG_MIPS32=y
-
-#
-# Code maturity level options
-#
-CONFIG_EXPERIMENTAL=y
-
-#
-# General setup
-#
-CONFIG_SWAP=y
-CONFIG_SYSVIPC=y
-# CONFIG_BSD_PROCESS_ACCT is not set
-CONFIG_SYSCTL=y
-CONFIG_LOG_BUF_SHIFT=14
-# CONFIG_EMBEDDED is not set
-CONFIG_KALLSYMS=y
-CONFIG_FUTEX=y
-CONFIG_EPOLL=y
-CONFIG_IOSCHED_AS=y
-CONFIG_IOSCHED_DEADLINE=y
-
-#
-# Loadable module support
-#
-CONFIG_MODULES=y
-CONFIG_MODULE_UNLOAD=y
-# CONFIG_MODULE_FORCE_UNLOAD is not set
-CONFIG_OBSOLETE_MODPARM=y
-CONFIG_MODVERSIONS=y
-CONFIG_KMOD=y
-
-#
-# Machine selection
-#
-# CONFIG_ACER_PICA_61 is not set
-# CONFIG_BAGET_MIPS is not set
-# CONFIG_CASIO_E55 is not set
-# CONFIG_MIPS_COBALT is not set
-CONFIG_DECSTATION=y
-# CONFIG_MIPS_EV64120 is not set
-# CONFIG_MIPS_EV96100 is not set
-# CONFIG_MIPS_IVR is not set
-# CONFIG_LASAT is not set
-# CONFIG_HP_LASERJET is not set
-# CONFIG_IBM_WORKPAD is not set
-# CONFIG_MIPS_ITE8172 is not set
-# CONFIG_MIPS_ATLAS is not set
-# CONFIG_MIPS_MAGNUM_4000 is not set
-# CONFIG_MIPS_MALTA is not set
-# CONFIG_MIPS_SEAD is not set
-# CONFIG_MOMENCO_OCELOT is not set
-# CONFIG_MOMENCO_OCELOT_G is not set
-# CONFIG_MOMENCO_OCELOT_C is not set
-# CONFIG_DDB5074 is not set
-# CONFIG_DDB5476 is not set
-# CONFIG_DDB5477 is not set
-# CONFIG_NEC_OSPREY is not set
-# CONFIG_NEC_EAGLE is not set
-# CONFIG_OLIVETTI_M700 is not set
-# CONFIG_SGI_IP22 is not set
-# CONFIG_SGI_IP32 is not set
-# CONFIG_SOC_AU1X00 is not set
-# CONFIG_SIBYTE_SB1xxx_SOC is not set
-# CONFIG_SNI_RM200_PCI is not set
-# CONFIG_TANBAC_TB0226 is not set
-# CONFIG_TANBAC_TB0229 is not set
-# CONFIG_TOSHIBA_JMR3927 is not set
-# CONFIG_TOSHIBA_RBTX4927 is not set
-# CONFIG_VICTOR_MPC30X is not set
-# CONFIG_ZAO_CAPCELLA is not set
-CONFIG_RWSEM_GENERIC_SPINLOCK=y
-CONFIG_GENERIC_ISA_DMA=y
-CONFIG_NONCOHERENT_IO=y
-CONFIG_CPU_LITTLE_ENDIAN=y
-CONFIG_IRQ_CPU=y
-CONFIG_BOOT_ELF32=y
-CONFIG_L1_CACHE_SHIFT=4
-# CONFIG_FB is not set
-
-#
-# CPU selection
-#
-# CONFIG_CPU_MIPS32 is not set
-# CONFIG_CPU_MIPS64 is not set
-CONFIG_CPU_R3000=y
-# CONFIG_CPU_TX39XX is not set
-# CONFIG_CPU_VR41XX is not set
-# CONFIG_CPU_R4300 is not set
-# CONFIG_CPU_R4X00 is not set
-# CONFIG_CPU_TX49XX is not set
-# CONFIG_CPU_R5000 is not set
-# CONFIG_CPU_R5432 is not set
-# CONFIG_CPU_R6000 is not set
-# CONFIG_CPU_NEVADA is not set
-# CONFIG_CPU_R8000 is not set
-# CONFIG_CPU_R10000 is not set
-# CONFIG_CPU_RM7000 is not set
-# CONFIG_CPU_SB1 is not set
-# CONFIG_CPU_ADVANCED is not set
-CONFIG_CPU_HAS_WB=y
-# CONFIG_PREEMPT is not set
-# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
-
-#
-# Bus options (PCI, PCMCIA, EISA, ISA, TC)
-#
-CONFIG_TC=y
-CONFIG_MMU=y
-# CONFIG_HOTPLUG is not set
-
-#
-# Executable file formats
-#
-CONFIG_KCORE_ELF=y
-CONFIG_BINFMT_ELF=y
-# CONFIG_BINFMT_MISC is not set
-CONFIG_TRAD_SIGNALS=y
-
-#
-# Memory Technology Devices (MTD)
-#
-# CONFIG_MTD is not set
-
-#
-# Parallel port support
-#
-# CONFIG_PARPORT is not set
-
-#
-# Plug and Play support
-#
-# CONFIG_PNP is not set
-
-#
-# Generic Driver Options
-#
-# CONFIG_FW_LOADER is not set
-
-#
-# Block devices
-#
-# CONFIG_BLK_DEV_FD is not set
-# CONFIG_BLK_DEV_LOOP is not set
-# CONFIG_BLK_DEV_NBD is not set
-# CONFIG_BLK_DEV_RAM is not set
-# CONFIG_BLK_DEV_INITRD is not set
-# CONFIG_LBD is not set
-
-#
-# ATA/ATAPI/MFM/RLL support
-#
-# CONFIG_IDE is not set
-
-#
-# SCSI device support
-#
-CONFIG_SCSI=y
-
-#
-# SCSI support type (disk, tape, CD-ROM)
-#
-CONFIG_BLK_DEV_SD=y
-# CONFIG_CHR_DEV_ST is not set
-# CONFIG_CHR_DEV_OSST is not set
-# CONFIG_BLK_DEV_SR is not set
-# CONFIG_CHR_DEV_SG is not set
-
-#
-# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
-#
-# CONFIG_SCSI_MULTI_LUN is not set
-# CONFIG_SCSI_REPORT_LUNS is not set
-CONFIG_SCSI_CONSTANTS=y
-# CONFIG_SCSI_LOGGING is not set
-
-#
-# SCSI low-level drivers
-#
-CONFIG_SCSI_DECNCR=y
-# CONFIG_SCSI_DECSII is not set
-# CONFIG_SCSI_AIC7XXX is not set
-# CONFIG_SCSI_AIC7XXX_OLD is not set
-# CONFIG_SCSI_DPT_I2O is not set
-# CONFIG_SCSI_EATA_PIO is not set
-# CONFIG_SCSI_DEBUG is not set
-
-#
-# Multi-device support (RAID and LVM)
-#
-# CONFIG_MD is not set
-
-#
-# Fusion MPT device support
-#
-# CONFIG_FUSION is not set
-
-#
-# I2O device support
-#
-
-#
-# Networking support
-#
-CONFIG_NET=y
-
-#
-# Networking options
-#
-CONFIG_PACKET=y
-# CONFIG_PACKET_MMAP is not set
-CONFIG_NETLINK_DEV=y
-# CONFIG_NETFILTER is not set
-CONFIG_UNIX=y
-CONFIG_NET_KEY=y
-CONFIG_INET=y
-# CONFIG_IP_MULTICAST is not set
-# CONFIG_IP_ADVANCED_ROUTER is not set
-CONFIG_IP_PNP=y
-# CONFIG_IP_PNP_DHCP is not set
-CONFIG_IP_PNP_BOOTP=y
-# CONFIG_IP_PNP_RARP is not set
-# CONFIG_NET_IPIP is not set
-# CONFIG_NET_IPGRE is not set
-# CONFIG_ARPD is not set
-# CONFIG_INET_ECN is not set
-# CONFIG_SYN_COOKIES is not set
-# CONFIG_INET_AH is not set
-# CONFIG_INET_ESP is not set
-# CONFIG_INET_IPCOMP is not set
-# CONFIG_IPV6 is not set
-# CONFIG_XFRM_USER is not set
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
-CONFIG_IPV6_SCTP__=y
-# CONFIG_IP_SCTP is not set
-# CONFIG_ATM is not set
-# CONFIG_VLAN_8021Q is not set
-# CONFIG_LLC is not set
-# CONFIG_DECNET is not set
-# CONFIG_BRIDGE is not set
-# CONFIG_X25 is not set
-# CONFIG_LAPB is not set
-# CONFIG_NET_DIVERT is not set
-# CONFIG_ECONET is not set
-# CONFIG_WAN_ROUTER is not set
-# CONFIG_NET_FASTROUTE is not set
-# CONFIG_NET_HW_FLOWCONTROL is not set
-
-#
-# QoS and/or fair queueing
-#
-# CONFIG_NET_SCHED is not set
-
-#
-# Network testing
-#
-# CONFIG_NET_PKTGEN is not set
-CONFIG_NETDEVICES=y
-# CONFIG_DUMMY is not set
-# CONFIG_BONDING is not set
-# CONFIG_EQUALIZER is not set
-# CONFIG_TUN is not set
-# CONFIG_ETHERTAP is not set
-
-#
-# Ethernet (10 or 100Mbit)
-#
-CONFIG_NET_ETHERNET=y
-# CONFIG_MII is not set
-CONFIG_DECLANCE=y
-
-#
-# Ethernet (1000 Mbit)
-#
-
-#
-# Ethernet (10000 Mbit)
-#
-# CONFIG_PPP is not set
-# CONFIG_SLIP is not set
-
-#
-# Wireless LAN (non-hamradio)
-#
-# CONFIG_NET_RADIO is not set
-
-#
-# Token Ring devices (depends on LLC=y)
-#
-# CONFIG_SHAPER is not set
-
-#
-# Wan interfaces
-#
-# CONFIG_WAN is not set
-
-#
-# Amateur Radio support
-#
-# CONFIG_HAMRADIO is not set
-
-#
-# IrDA (infrared) support
-#
-# CONFIG_IRDA is not set
-
-#
-# ISDN subsystem
-#
-# CONFIG_ISDN_BOOL is not set
-
-#
-# Telephony Support
-#
-# CONFIG_PHONE is not set
-
-#
-# Input device support
-#
-CONFIG_INPUT=y
-
-#
-# Userland interfaces
-#
-# CONFIG_INPUT_MOUSEDEV is not set
-# CONFIG_INPUT_JOYDEV is not set
-# CONFIG_INPUT_TSDEV is not set
-# CONFIG_INPUT_EVDEV is not set
-# CONFIG_INPUT_EVBUG is not set
-
-#
-# Input I/O drivers
-#
-# CONFIG_GAMEPORT is not set
-CONFIG_SOUND_GAMEPORT=y
-CONFIG_SERIO=y
-# CONFIG_SERIO_I8042 is not set
-CONFIG_SERIO_SERPORT=y
-# CONFIG_SERIO_CT82C710 is not set
-
-#
-# Input Device Drivers
-#
-# CONFIG_INPUT_KEYBOARD is not set
-# CONFIG_INPUT_MOUSE is not set
-# CONFIG_INPUT_JOYSTICK is not set
-# CONFIG_INPUT_TOUCHSCREEN is not set
-# CONFIG_INPUT_MISC is not set
-
-#
-# Character devices
-#
-# CONFIG_VT is not set
-# CONFIG_SERIAL_NONSTANDARD is not set
-
-#
-# Serial drivers
-#
-# CONFIG_SERIAL_8250 is not set
-
-#
-# Non-8250 serial port support
-#
-CONFIG_SERIAL_DZ=y
-CONFIG_SERIAL_DZ_CONSOLE=y
-CONFIG_SERIAL_CORE=y
-CONFIG_SERIAL_CORE_CONSOLE=y
-CONFIG_UNIX98_PTYS=y
-CONFIG_UNIX98_PTY_COUNT=256
-
-#
-# I2C support
-#
-# CONFIG_I2C is not set
-
-#
-# I2C Hardware Sensors Mainboard support
-#
-
-#
-# I2C Hardware Sensors Chip support
-#
-# CONFIG_I2C_SENSOR is not set
-
-#
-# Mice
-#
-# CONFIG_BUSMOUSE is not set
-# CONFIG_QIC02_TAPE is not set
-
-#
-# IPMI
-#
-# CONFIG_IPMI_HANDLER is not set
-
-#
-# Watchdog Cards
-#
-# CONFIG_WATCHDOG is not set
-# CONFIG_NVRAM is not set
-# CONFIG_RTC is not set
-# CONFIG_GEN_RTC is not set
-# CONFIG_DTLK is not set
-# CONFIG_R3964 is not set
-# CONFIG_APPLICOM is not set
-
-#
-# Ftape, the floppy tape device driver
-#
-# CONFIG_FTAPE is not set
-# CONFIG_AGP is not set
-# CONFIG_DRM is not set
-# CONFIG_RAW_DRIVER is not set
-# CONFIG_HANGCHECK_TIMER is not set
-
-#
-# Multimedia devices
-#
-# CONFIG_VIDEO_DEV is not set
-
-#
-# Digital Video Broadcasting Devices
-#
-# CONFIG_DVB is not set
-
-#
-# File systems
-#
-CONFIG_EXT2_FS=y
-CONFIG_EXT2_FS_XATTR=y
-CONFIG_EXT2_FS_POSIX_ACL=y
-CONFIG_EXT2_FS_SECURITY=y
-# CONFIG_EXT3_FS is not set
-# CONFIG_JBD is not set
-CONFIG_FS_MBCACHE=y
-# CONFIG_REISERFS_FS is not set
-# CONFIG_JFS_FS is not set
-CONFIG_FS_POSIX_ACL=y
-# CONFIG_XFS_FS is not set
-# CONFIG_MINIX_FS is not set
-# CONFIG_ROMFS_FS is not set
-# CONFIG_QUOTA is not set
-# CONFIG_AUTOFS_FS is not set
-# CONFIG_AUTOFS4_FS is not set
-
-#
-# CD-ROM/DVD Filesystems
-#
-# CONFIG_ISO9660_FS is not set
-# CONFIG_UDF_FS is not set
-
-#
-# DOS/FAT/NT Filesystems
-#
-# CONFIG_FAT_FS is not set
-# CONFIG_NTFS_FS is not set
-
-#
-# Pseudo filesystems
-#
-CONFIG_PROC_FS=y
-# CONFIG_DEVFS_FS is not set
-CONFIG_DEVPTS_FS=y
-CONFIG_DEVPTS_FS_XATTR=y
-CONFIG_DEVPTS_FS_SECURITY=y
-# CONFIG_TMPFS is not set
-CONFIG_RAMFS=y
-
-#
-# Miscellaneous filesystems
-#
-# CONFIG_ADFS_FS is not set
-# CONFIG_AFFS_FS is not set
-# CONFIG_HFS_FS is not set
-# CONFIG_BEFS_FS is not set
-# CONFIG_BFS_FS is not set
-# CONFIG_EFS_FS is not set
-# CONFIG_CRAMFS is not set
-# CONFIG_VXFS_FS is not set
-# CONFIG_HPFS_FS is not set
-# CONFIG_QNX4FS_FS is not set
-# CONFIG_SYSV_FS is not set
-# CONFIG_UFS_FS is not set
-
-#
-# Network File Systems
-#
-# CONFIG_NFS_FS is not set
-# CONFIG_NFSD is not set
-# CONFIG_EXPORTFS is not set
-# CONFIG_SMB_FS is not set
-# CONFIG_CIFS is not set
-# CONFIG_NCP_FS is not set
-# CONFIG_CODA_FS is not set
-# CONFIG_INTERMEZZO_FS is not set
-# CONFIG_AFS_FS is not set
-
-#
-# Partition Types
-#
-CONFIG_PARTITION_ADVANCED=y
-# CONFIG_ACORN_PARTITION is not set
-CONFIG_OSF_PARTITION=y
-# CONFIG_AMIGA_PARTITION is not set
-# CONFIG_ATARI_PARTITION is not set
-# CONFIG_MAC_PARTITION is not set
-CONFIG_MSDOS_PARTITION=y
-# CONFIG_BSD_DISKLABEL is not set
-# CONFIG_MINIX_SUBPARTITION is not set
-# CONFIG_SOLARIS_X86_PARTITION is not set
-# CONFIG_UNIXWARE_DISKLABEL is not set
-# CONFIG_LDM_PARTITION is not set
-# CONFIG_NEC98_PARTITION is not set
-# CONFIG_SGI_PARTITION is not set
-CONFIG_ULTRIX_PARTITION=y
-# CONFIG_SUN_PARTITION is not set
-# CONFIG_EFI_PARTITION is not set
-
-#
-# Graphics support
-#
-
-#
-# Sound
-#
-# CONFIG_SOUND is not set
-
-#
-# USB support
-#
-# CONFIG_USB_GADGET is not set
-
-#
-# Bluetooth support
-#
-# CONFIG_BT is not set
-
-#
-# Kernel hacking
-#
-CONFIG_CROSSCOMPILE=y
-# CONFIG_DEBUG_KERNEL is not set
-
-#
-# Security options
-#
-# CONFIG_SECURITY is not set
-
-#
-# Cryptographic options
-#
-# CONFIG_CRYPTO is not set
-
-#
-# Library routines
-#
-# CONFIG_CRC32 is not set
--- diff/arch/mips/defconfig-e55	2003-08-20 14:16:25.000000000 +0100
+++ source/arch/mips/defconfig-e55	1970-01-01 01:00:00.000000000 +0100
@@ -1,568 +0,0 @@
-#
-# Automatically generated make config: don't edit
-#
-CONFIG_MIPS=y
-# CONFIG_MIPS64 is not set
-CONFIG_MIPS32=y
-
-#
-# Code maturity level options
-#
-CONFIG_EXPERIMENTAL=y
-
-#
-# General setup
-#
-CONFIG_SWAP=y
-CONFIG_SYSVIPC=y
-# CONFIG_BSD_PROCESS_ACCT is not set
-CONFIG_SYSCTL=y
-CONFIG_LOG_BUF_SHIFT=14
-# CONFIG_EMBEDDED is not set
-CONFIG_KALLSYMS=y
-CONFIG_FUTEX=y
-CONFIG_EPOLL=y
-CONFIG_IOSCHED_AS=y
-CONFIG_IOSCHED_DEADLINE=y
-
-#
-# Loadable module support
-#
-CONFIG_MODULES=y
-CONFIG_MODULE_UNLOAD=y
-# CONFIG_MODULE_FORCE_UNLOAD is not set
-CONFIG_OBSOLETE_MODPARM=y
-CONFIG_MODVERSIONS=y
-CONFIG_KMOD=y
-
-#
-# Machine selection
-#
-# CONFIG_ACER_PICA_61 is not set
-# CONFIG_BAGET_MIPS is not set
-CONFIG_CASIO_E55=y
-# CONFIG_MIPS_COBALT is not set
-# CONFIG_DECSTATION is not set
-# CONFIG_MIPS_EV64120 is not set
-# CONFIG_MIPS_EV96100 is not set
-# CONFIG_MIPS_IVR is not set
-# CONFIG_LASAT is not set
-# CONFIG_HP_LASERJET is not set
-# CONFIG_IBM_WORKPAD is not set
-# CONFIG_MIPS_ITE8172 is not set
-# CONFIG_MIPS_ATLAS is not set
-# CONFIG_MIPS_MAGNUM_4000 is not set
-# CONFIG_MIPS_MALTA is not set
-# CONFIG_MIPS_SEAD is not set
-# CONFIG_MOMENCO_OCELOT is not set
-# CONFIG_MOMENCO_OCELOT_G is not set
-# CONFIG_MOMENCO_OCELOT_C is not set
-# CONFIG_DDB5074 is not set
-# CONFIG_DDB5476 is not set
-# CONFIG_DDB5477 is not set
-# CONFIG_NEC_OSPREY is not set
-# CONFIG_NEC_EAGLE is not set
-# CONFIG_OLIVETTI_M700 is not set
-# CONFIG_SGI_IP22 is not set
-# CONFIG_SGI_IP32 is not set
-# CONFIG_SOC_AU1X00 is not set
-# CONFIG_SIBYTE_SB1xxx_SOC is not set
-# CONFIG_SNI_RM200_PCI is not set
-# CONFIG_TANBAC_TB0226 is not set
-# CONFIG_TANBAC_TB0229 is not set
-# CONFIG_TOSHIBA_JMR3927 is not set
-# CONFIG_TOSHIBA_RBTX4927 is not set
-# CONFIG_VICTOR_MPC30X is not set
-# CONFIG_ZAO_CAPCELLA is not set
-CONFIG_RWSEM_GENERIC_SPINLOCK=y
-CONFIG_NONCOHERENT_IO=y
-CONFIG_CPU_LITTLE_ENDIAN=y
-CONFIG_IRQ_CPU=y
-CONFIG_VR41XX_TIME_C=y
-CONFIG_DUMMY_KEYB=y
-CONFIG_VR41XX_COMMON=y
-# CONFIG_FB is not set
-
-#
-# CPU selection
-#
-# CONFIG_CPU_MIPS32 is not set
-# CONFIG_CPU_MIPS64 is not set
-# CONFIG_CPU_R3000 is not set
-# CONFIG_CPU_TX39XX is not set
-CONFIG_CPU_VR41XX=y
-# CONFIG_CPU_R4300 is not set
-# CONFIG_CPU_R4X00 is not set
-# CONFIG_CPU_TX49XX is not set
-# CONFIG_CPU_R5000 is not set
-# CONFIG_CPU_R5432 is not set
-# CONFIG_CPU_R6000 is not set
-# CONFIG_CPU_NEVADA is not set
-# CONFIG_CPU_R8000 is not set
-# CONFIG_CPU_R10000 is not set
-# CONFIG_CPU_RM7000 is not set
-# CONFIG_CPU_SB1 is not set
-# CONFIG_CPU_ADVANCED is not set
-CONFIG_CPU_HAS_SYNC=y
-# CONFIG_PREEMPT is not set
-# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
-
-#
-# Bus options (PCI, PCMCIA, EISA, ISA, TC)
-#
-CONFIG_MMU=y
-# CONFIG_HOTPLUG is not set
-
-#
-# Executable file formats
-#
-CONFIG_KCORE_ELF=y
-CONFIG_BINFMT_ELF=y
-# CONFIG_BINFMT_MISC is not set
-CONFIG_TRAD_SIGNALS=y
-
-#
-# Memory Technology Devices (MTD)
-#
-# CONFIG_MTD is not set
-
-#
-# Parallel port support
-#
-# CONFIG_PARPORT is not set
-
-#
-# Plug and Play support
-#
-# CONFIG_PNP is not set
-
-#
-# Generic Driver Options
-#
-# CONFIG_FW_LOADER is not set
-
-#
-# Block devices
-#
-# CONFIG_BLK_DEV_FD is not set
-# CONFIG_BLK_DEV_LOOP is not set
-# CONFIG_BLK_DEV_NBD is not set
-# CONFIG_BLK_DEV_RAM is not set
-# CONFIG_BLK_DEV_INITRD is not set
-# CONFIG_LBD is not set
-
-#
-# ATA/ATAPI/MFM/RLL support
-#
-CONFIG_IDE=y
-
-#
-# IDE, ATA and ATAPI Block devices
-#
-CONFIG_BLK_DEV_IDE=y
-
-#
-# Please see Documentation/ide.txt for help/info on IDE drives
-#
-# CONFIG_BLK_DEV_HD is not set
-CONFIG_BLK_DEV_IDEDISK=y
-# CONFIG_IDEDISK_MULTI_MODE is not set
-# CONFIG_IDEDISK_STROKE is not set
-# CONFIG_BLK_DEV_IDECD is not set
-# CONFIG_BLK_DEV_IDEFLOPPY is not set
-# CONFIG_IDE_TASK_IOCTL is not set
-CONFIG_IDE_TASKFILE_IO=y
-
-#
-# IDE chipset support/bugfixes
-#
-
-#
-# SCSI device support
-#
-# CONFIG_SCSI is not set
-
-#
-# Multi-device support (RAID and LVM)
-#
-# CONFIG_MD is not set
-
-#
-# Fusion MPT device support
-#
-
-#
-# I2O device support
-#
-
-#
-# Networking support
-#
-CONFIG_NET=y
-
-#
-# Networking options
-#
-CONFIG_PACKET=y
-CONFIG_PACKET_MMAP=y
-CONFIG_NETLINK_DEV=y
-# CONFIG_NETFILTER is not set
-CONFIG_UNIX=y
-CONFIG_NET_KEY=y
-CONFIG_INET=y
-CONFIG_IP_MULTICAST=y
-# CONFIG_IP_ADVANCED_ROUTER is not set
-# CONFIG_IP_PNP is not set
-# CONFIG_NET_IPIP is not set
-# CONFIG_NET_IPGRE is not set
-# CONFIG_IP_MROUTE is not set
-# CONFIG_ARPD is not set
-# CONFIG_INET_ECN is not set
-# CONFIG_SYN_COOKIES is not set
-# CONFIG_INET_AH is not set
-# CONFIG_INET_ESP is not set
-# CONFIG_INET_IPCOMP is not set
-# CONFIG_IPV6 is not set
-# CONFIG_XFRM_USER is not set
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
-CONFIG_IPV6_SCTP__=y
-# CONFIG_IP_SCTP is not set
-# CONFIG_ATM is not set
-# CONFIG_VLAN_8021Q is not set
-# CONFIG_LLC is not set
-# CONFIG_DECNET is not set
-# CONFIG_BRIDGE is not set
-# CONFIG_X25 is not set
-# CONFIG_LAPB is not set
-# CONFIG_NET_DIVERT is not set
-# CONFIG_ECONET is not set
-# CONFIG_WAN_ROUTER is not set
-# CONFIG_NET_FASTROUTE is not set
-# CONFIG_NET_HW_FLOWCONTROL is not set
-
-#
-# QoS and/or fair queueing
-#
-# CONFIG_NET_SCHED is not set
-
-#
-# Network testing
-#
-# CONFIG_NET_PKTGEN is not set
-CONFIG_NETDEVICES=y
-# CONFIG_DUMMY is not set
-# CONFIG_BONDING is not set
-# CONFIG_EQUALIZER is not set
-# CONFIG_TUN is not set
-# CONFIG_ETHERTAP is not set
-
-#
-# Ethernet (10 or 100Mbit)
-#
-CONFIG_NET_ETHERNET=y
-# CONFIG_MII is not set
-
-#
-# Ethernet (1000 Mbit)
-#
-
-#
-# Ethernet (10000 Mbit)
-#
-# CONFIG_PPP is not set
-# CONFIG_SLIP is not set
-
-#
-# Wireless LAN (non-hamradio)
-#
-# CONFIG_NET_RADIO is not set
-
-#
-# Token Ring devices (depends on LLC=y)
-#
-# CONFIG_SHAPER is not set
-
-#
-# Wan interfaces
-#
-# CONFIG_WAN is not set
-
-#
-# Amateur Radio support
-#
-# CONFIG_HAMRADIO is not set
-
-#
-# IrDA (infrared) support
-#
-# CONFIG_IRDA is not set
-
-#
-# ISDN subsystem
-#
-# CONFIG_ISDN_BOOL is not set
-
-#
-# Telephony Support
-#
-# CONFIG_PHONE is not set
-
-#
-# Input device support
-#
-CONFIG_INPUT=y
-
-#
-# Userland interfaces
-#
-# CONFIG_INPUT_MOUSEDEV is not set
-# CONFIG_INPUT_JOYDEV is not set
-# CONFIG_INPUT_TSDEV is not set
-# CONFIG_INPUT_EVDEV is not set
-# CONFIG_INPUT_EVBUG is not set
-
-#
-# Input I/O drivers
-#
-# CONFIG_GAMEPORT is not set
-CONFIG_SOUND_GAMEPORT=y
-# CONFIG_SERIO is not set
-
-#
-# Input Device Drivers
-#
-# CONFIG_INPUT_KEYBOARD is not set
-# CONFIG_INPUT_MOUSE is not set
-# CONFIG_INPUT_JOYSTICK is not set
-# CONFIG_INPUT_TOUCHSCREEN is not set
-# CONFIG_INPUT_MISC is not set
-
-#
-# Character devices
-#
-CONFIG_VT=y
-# CONFIG_VT_CONSOLE is not set
-CONFIG_HW_CONSOLE=y
-# CONFIG_SERIAL_NONSTANDARD is not set
-
-#
-# Serial drivers
-#
-CONFIG_SERIAL_8250=y
-CONFIG_SERIAL_8250_CONSOLE=y
-# CONFIG_SERIAL_8250_EXTENDED is not set
-
-#
-# Non-8250 serial port support
-#
-CONFIG_SERIAL_CORE=y
-CONFIG_SERIAL_CORE_CONSOLE=y
-CONFIG_UNIX98_PTYS=y
-CONFIG_UNIX98_PTY_COUNT=256
-
-#
-# I2C support
-#
-# CONFIG_I2C is not set
-
-#
-# I2C Hardware Sensors Mainboard support
-#
-
-#
-# I2C Hardware Sensors Chip support
-#
-# CONFIG_I2C_SENSOR is not set
-
-#
-# Mice
-#
-# CONFIG_BUSMOUSE is not set
-# CONFIG_QIC02_TAPE is not set
-
-#
-# IPMI
-#
-# CONFIG_IPMI_HANDLER is not set
-
-#
-# Watchdog Cards
-#
-CONFIG_WATCHDOG=y
-# CONFIG_WATCHDOG_NOWAYOUT is not set
-# CONFIG_SOFT_WATCHDOG is not set
-# CONFIG_WDT is not set
-# CONFIG_WDTPCI is not set
-# CONFIG_PCWATCHDOG is not set
-# CONFIG_ACQUIRE_WDT is not set
-# CONFIG_ADVANTECH_WDT is not set
-# CONFIG_EUROTECH_WDT is not set
-# CONFIG_IB700_WDT is not set
-# CONFIG_I810_TCO is not set
-# CONFIG_MIXCOMWD is not set
-# CONFIG_SCx200_WDT is not set
-# CONFIG_60XX_WDT is not set
-# CONFIG_W83877F_WDT is not set
-# CONFIG_MACHZ_WDT is not set
-# CONFIG_SC520_WDT is not set
-# CONFIG_AMD7XX_TCO is not set
-# CONFIG_ALIM7101_WDT is not set
-# CONFIG_SC1200_WDT is not set
-# CONFIG_WAFER_WDT is not set
-# CONFIG_CPU5_WDT is not set
-# CONFIG_NVRAM is not set
-# CONFIG_RTC is not set
-# CONFIG_GEN_RTC is not set
-# CONFIG_DTLK is not set
-# CONFIG_R3964 is not set
-# CONFIG_APPLICOM is not set
-
-#
-# Ftape, the floppy tape device driver
-#
-# CONFIG_FTAPE is not set
-# CONFIG_AGP is not set
-# CONFIG_DRM is not set
-# CONFIG_RAW_DRIVER is not set
-# CONFIG_HANGCHECK_TIMER is not set
-
-#
-# Multimedia devices
-#
-# CONFIG_VIDEO_DEV is not set
-
-#
-# Digital Video Broadcasting Devices
-#
-# CONFIG_DVB is not set
-
-#
-# File systems
-#
-CONFIG_EXT2_FS=y
-# CONFIG_EXT2_FS_XATTR is not set
-# CONFIG_EXT3_FS is not set
-# CONFIG_JBD is not set
-# CONFIG_REISERFS_FS is not set
-# CONFIG_JFS_FS is not set
-# CONFIG_XFS_FS is not set
-# CONFIG_MINIX_FS is not set
-# CONFIG_ROMFS_FS is not set
-# CONFIG_QUOTA is not set
-CONFIG_AUTOFS_FS=y
-CONFIG_AUTOFS4_FS=y
-
-#
-# CD-ROM/DVD Filesystems
-#
-# CONFIG_ISO9660_FS is not set
-# CONFIG_UDF_FS is not set
-
-#
-# DOS/FAT/NT Filesystems
-#
-# CONFIG_FAT_FS is not set
-# CONFIG_NTFS_FS is not set
-
-#
-# Pseudo filesystems
-#
-CONFIG_PROC_FS=y
-# CONFIG_DEVFS_FS is not set
-CONFIG_DEVPTS_FS=y
-CONFIG_DEVPTS_FS_XATTR=y
-CONFIG_DEVPTS_FS_SECURITY=y
-# CONFIG_TMPFS is not set
-CONFIG_RAMFS=y
-
-#
-# Miscellaneous filesystems
-#
-# CONFIG_ADFS_FS is not set
-# CONFIG_AFFS_FS is not set
-# CONFIG_HFS_FS is not set
-# CONFIG_BEFS_FS is not set
-# CONFIG_BFS_FS is not set
-# CONFIG_EFS_FS is not set
-# CONFIG_CRAMFS is not set
-# CONFIG_VXFS_FS is not set
-# CONFIG_HPFS_FS is not set
-# CONFIG_QNX4FS_FS is not set
-# CONFIG_SYSV_FS is not set
-# CONFIG_UFS_FS is not set
-
-#
-# Network File Systems
-#
-CONFIG_NFS_FS=y
-# CONFIG_NFS_V3 is not set
-# CONFIG_NFS_V4 is not set
-CONFIG_NFSD=y
-# CONFIG_NFSD_V3 is not set
-# CONFIG_NFSD_TCP is not set
-CONFIG_LOCKD=y
-CONFIG_EXPORTFS=y
-CONFIG_SUNRPC=y
-# CONFIG_SUNRPC_GSS is not set
-# CONFIG_SMB_FS is not set
-# CONFIG_CIFS is not set
-# CONFIG_NCP_FS is not set
-# CONFIG_CODA_FS is not set
-# CONFIG_INTERMEZZO_FS is not set
-# CONFIG_AFS_FS is not set
-
-#
-# Partition Types
-#
-# CONFIG_PARTITION_ADVANCED is not set
-CONFIG_MSDOS_PARTITION=y
-
-#
-# Graphics support
-#
-
-#
-# Console display driver support
-#
-# CONFIG_VGA_CONSOLE is not set
-# CONFIG_MDA_CONSOLE is not set
-CONFIG_DUMMY_CONSOLE=y
-
-#
-# Sound
-#
-# CONFIG_SOUND is not set
-
-#
-# USB support
-#
-# CONFIG_USB_GADGET is not set
-
-#
-# Bluetooth support
-#
-# CONFIG_BT is not set
-
-#
-# Kernel hacking
-#
-CONFIG_CROSSCOMPILE=y
-# CONFIG_DEBUG_KERNEL is not set
-
-#
-# Security options
-#
-# CONFIG_SECURITY is not set
-
-#
-# Cryptographic options
-#
-# CONFIG_CRYPTO is not set
-
-#
-# Library routines
-#
-# CONFIG_CRC32 is not set
--- diff/arch/mips/defconfig-eagle	2003-08-20 14:16:25.000000000 +0100
+++ source/arch/mips/defconfig-eagle	1970-01-01 01:00:00.000000000 +0100
@@ -1,732 +0,0 @@
-#
-# Automatically generated make config: don't edit
-#
-CONFIG_MIPS=y
-# CONFIG_MIPS64 is not set
-CONFIG_MIPS32=y
-
-#
-# Code maturity level options
-#
-CONFIG_EXPERIMENTAL=y
-
-#
-# General setup
-#
-CONFIG_SWAP=y
-CONFIG_SYSVIPC=y
-# CONFIG_BSD_PROCESS_ACCT is not set
-CONFIG_SYSCTL=y
-CONFIG_LOG_BUF_SHIFT=14
-# CONFIG_EMBEDDED is not set
-CONFIG_KALLSYMS=y
-CONFIG_FUTEX=y
-CONFIG_EPOLL=y
-CONFIG_IOSCHED_AS=y
-CONFIG_IOSCHED_DEADLINE=y
-
-#
-# Loadable module support
-#
-CONFIG_MODULES=y
-CONFIG_MODULE_UNLOAD=y
-# CONFIG_MODULE_FORCE_UNLOAD is not set
-CONFIG_OBSOLETE_MODPARM=y
-CONFIG_MODVERSIONS=y
-CONFIG_KMOD=y
-
-#
-# Machine selection
-#
-# CONFIG_ACER_PICA_61 is not set
-# CONFIG_BAGET_MIPS is not set
-# CONFIG_CASIO_E55 is not set
-# CONFIG_MIPS_COBALT is not set
-# CONFIG_DECSTATION is not set
-# CONFIG_MIPS_EV64120 is not set
-# CONFIG_MIPS_EV96100 is not set
-# CONFIG_MIPS_IVR is not set
-# CONFIG_LASAT is not set
-# CONFIG_HP_LASERJET is not set
-# CONFIG_IBM_WORKPAD is not set
-# CONFIG_MIPS_ITE8172 is not set
-# CONFIG_MIPS_ATLAS is not set
-# CONFIG_MIPS_MAGNUM_4000 is not set
-# CONFIG_MIPS_MALTA is not set
-# CONFIG_MIPS_SEAD is not set
-# CONFIG_MOMENCO_OCELOT is not set
-# CONFIG_MOMENCO_OCELOT_G is not set
-# CONFIG_MOMENCO_OCELOT_C is not set
-# CONFIG_DDB5074 is not set
-# CONFIG_DDB5476 is not set
-# CONFIG_DDB5477 is not set
-# CONFIG_NEC_OSPREY is not set
-CONFIG_NEC_EAGLE=y
-# CONFIG_OLIVETTI_M700 is not set
-# CONFIG_SGI_IP22 is not set
-# CONFIG_SGI_IP32 is not set
-# CONFIG_SOC_AU1X00 is not set
-# CONFIG_SIBYTE_SB1xxx_SOC is not set
-# CONFIG_SNI_RM200_PCI is not set
-# CONFIG_TANBAC_TB0226 is not set
-# CONFIG_TANBAC_TB0229 is not set
-# CONFIG_TOSHIBA_JMR3927 is not set
-# CONFIG_TOSHIBA_RBTX4927 is not set
-# CONFIG_VICTOR_MPC30X is not set
-# CONFIG_ZAO_CAPCELLA is not set
-CONFIG_RWSEM_GENERIC_SPINLOCK=y
-CONFIG_NONCOHERENT_IO=y
-CONFIG_CPU_LITTLE_ENDIAN=y
-CONFIG_IRQ_CPU=y
-CONFIG_VR41XX_TIME_C=y
-CONFIG_DUMMY_KEYB=y
-CONFIG_VR41XX_COMMON=y
-CONFIG_VRC4173=y
-CONFIG_NEW_PCI=y
-# CONFIG_FB is not set
-
-#
-# CPU selection
-#
-# CONFIG_CPU_MIPS32 is not set
-# CONFIG_CPU_MIPS64 is not set
-# CONFIG_CPU_R3000 is not set
-# CONFIG_CPU_TX39XX is not set
-CONFIG_CPU_VR41XX=y
-# CONFIG_CPU_R4300 is not set
-# CONFIG_CPU_R4X00 is not set
-# CONFIG_CPU_TX49XX is not set
-# CONFIG_CPU_R5000 is not set
-# CONFIG_CPU_R5432 is not set
-# CONFIG_CPU_R6000 is not set
-# CONFIG_CPU_NEVADA is not set
-# CONFIG_CPU_R8000 is not set
-# CONFIG_CPU_R10000 is not set
-# CONFIG_CPU_RM7000 is not set
-# CONFIG_CPU_SB1 is not set
-# CONFIG_CPU_ADVANCED is not set
-CONFIG_CPU_HAS_SYNC=y
-# CONFIG_PREEMPT is not set
-# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
-
-#
-# Bus options (PCI, PCMCIA, EISA, ISA, TC)
-#
-CONFIG_PCI=y
-CONFIG_PCI_LEGACY_PROC=y
-CONFIG_PCI_NAMES=y
-CONFIG_MMU=y
-CONFIG_HOTPLUG=y
-
-#
-# PCMCIA/CardBus support
-#
-CONFIG_PCMCIA=y
-# CONFIG_YENTA is not set
-# CONFIG_I82092 is not set
-# CONFIG_TCIC is not set
-# CONFIG_PCMCIA_VRC4173 is not set
-
-#
-# PCI Hotplug Support
-#
-# CONFIG_HOTPLUG_PCI is not set
-
-#
-# Executable file formats
-#
-CONFIG_KCORE_ELF=y
-CONFIG_BINFMT_ELF=y
-# CONFIG_BINFMT_MISC is not set
-CONFIG_TRAD_SIGNALS=y
-
-#
-# Memory Technology Devices (MTD)
-#
-CONFIG_MTD=y
-# CONFIG_MTD_DEBUG is not set
-# CONFIG_MTD_PARTITIONS is not set
-# CONFIG_MTD_CONCAT is not set
-
-#
-# User Modules And Translation Layers
-#
-CONFIG_MTD_CHAR=y
-CONFIG_MTD_BLOCK=y
-# CONFIG_FTL is not set
-# CONFIG_NFTL is not set
-# CONFIG_INFTL is not set
-
-#
-# RAM/ROM/Flash chip drivers
-#
-CONFIG_MTD_CFI=y
-# CONFIG_MTD_JEDECPROBE is not set
-CONFIG_MTD_GEN_PROBE=y
-CONFIG_MTD_CFI_ADV_OPTIONS=y
-CONFIG_MTD_CFI_NOSWAP=y
-# CONFIG_MTD_CFI_BE_BYTE_SWAP is not set
-# CONFIG_MTD_CFI_LE_BYTE_SWAP is not set
-# CONFIG_MTD_CFI_GEOMETRY is not set
-CONFIG_MTD_CFI_INTELEXT=y
-# CONFIG_MTD_CFI_AMDSTD is not set
-# CONFIG_MTD_CFI_STAA is not set
-# CONFIG_MTD_RAM is not set
-# CONFIG_MTD_ROM is not set
-# CONFIG_MTD_ABSENT is not set
-# CONFIG_MTD_OBSOLETE_CHIPS is not set
-
-#
-# Mapping drivers for chip access
-#
-# CONFIG_MTD_COMPLEX_MAPPINGS is not set
-CONFIG_MTD_PHYSMAP=y
-CONFIG_MTD_PHYSMAP_START=0x1c000000
-CONFIG_MTD_PHYSMAP_LEN=0x2000000
-CONFIG_MTD_PHYSMAP_BUSWIDTH=4
-
-#
-# Self-contained MTD device drivers
-#
-# CONFIG_MTD_PMC551 is not set
-# CONFIG_MTD_SLRAM is not set
-# CONFIG_MTD_MTDRAM is not set
-# CONFIG_MTD_BLKMTD is not set
-
-#
-# Disk-On-Chip Device Drivers
-#
-# CONFIG_MTD_DOC2000 is not set
-# CONFIG_MTD_DOC2001 is not set
-# CONFIG_MTD_DOC2001PLUS is not set
-
-#
-# NAND Flash Device Drivers
-#
-# CONFIG_MTD_NAND is not set
-
-#
-# Parallel port support
-#
-# CONFIG_PARPORT is not set
-
-#
-# Plug and Play support
-#
-# CONFIG_PNP is not set
-
-#
-# Generic Driver Options
-#
-# CONFIG_FW_LOADER is not set
-
-#
-# Block devices
-#
-# CONFIG_BLK_DEV_FD is not set
-# CONFIG_BLK_CPQ_DA is not set
-# CONFIG_BLK_CPQ_CISS_DA is not set
-# CONFIG_BLK_DEV_DAC960 is not set
-# CONFIG_BLK_DEV_UMEM is not set
-# CONFIG_BLK_DEV_LOOP is not set
-# CONFIG_BLK_DEV_NBD is not set
-# CONFIG_BLK_DEV_RAM is not set
-# CONFIG_BLK_DEV_INITRD is not set
-# CONFIG_LBD is not set
-
-#
-# ATA/ATAPI/MFM/RLL support
-#
-CONFIG_IDE=y
-
-#
-# IDE, ATA and ATAPI Block devices
-#
-CONFIG_BLK_DEV_IDE=y
-
-#
-# Please see Documentation/ide.txt for help/info on IDE drives
-#
-# CONFIG_BLK_DEV_HD is not set
-CONFIG_BLK_DEV_IDEDISK=y
-CONFIG_IDEDISK_MULTI_MODE=y
-# CONFIG_IDEDISK_STROKE is not set
-CONFIG_BLK_DEV_IDECS=y
-# CONFIG_BLK_DEV_IDECD is not set
-# CONFIG_BLK_DEV_IDEFLOPPY is not set
-# CONFIG_IDE_TASK_IOCTL is not set
-CONFIG_IDE_TASKFILE_IO=y
-
-#
-# IDE chipset support/bugfixes
-#
-# CONFIG_BLK_DEV_IDEPCI is not set
-
-#
-# SCSI device support
-#
-# CONFIG_SCSI is not set
-
-#
-# Multi-device support (RAID and LVM)
-#
-# CONFIG_MD is not set
-
-#
-# Fusion MPT device support
-#
-
-#
-# IEEE 1394 (FireWire) support (EXPERIMENTAL)
-#
-# CONFIG_IEEE1394 is not set
-
-#
-# I2O device support
-#
-# CONFIG_I2O is not set
-
-#
-# Networking support
-#
-CONFIG_NET=y
-
-#
-# Networking options
-#
-CONFIG_PACKET=y
-CONFIG_PACKET_MMAP=y
-CONFIG_NETLINK_DEV=y
-# CONFIG_NETFILTER is not set
-CONFIG_UNIX=y
-CONFIG_NET_KEY=y
-CONFIG_INET=y
-CONFIG_IP_MULTICAST=y
-# CONFIG_IP_ADVANCED_ROUTER is not set
-CONFIG_IP_PNP=y
-# CONFIG_IP_PNP_DHCP is not set
-CONFIG_IP_PNP_BOOTP=y
-# CONFIG_IP_PNP_RARP is not set
-# CONFIG_NET_IPIP is not set
-# CONFIG_NET_IPGRE is not set
-# CONFIG_IP_MROUTE is not set
-# CONFIG_ARPD is not set
-# CONFIG_INET_ECN is not set
-# CONFIG_SYN_COOKIES is not set
-# CONFIG_INET_AH is not set
-# CONFIG_INET_ESP is not set
-# CONFIG_INET_IPCOMP is not set
-# CONFIG_IPV6 is not set
-# CONFIG_XFRM_USER is not set
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
-CONFIG_IPV6_SCTP__=y
-# CONFIG_IP_SCTP is not set
-# CONFIG_ATM is not set
-# CONFIG_VLAN_8021Q is not set
-# CONFIG_LLC is not set
-# CONFIG_DECNET is not set
-# CONFIG_BRIDGE is not set
-# CONFIG_X25 is not set
-# CONFIG_LAPB is not set
-# CONFIG_NET_DIVERT is not set
-# CONFIG_ECONET is not set
-# CONFIG_WAN_ROUTER is not set
-# CONFIG_NET_FASTROUTE is not set
-# CONFIG_NET_HW_FLOWCONTROL is not set
-
-#
-# QoS and/or fair queueing
-#
-# CONFIG_NET_SCHED is not set
-
-#
-# Network testing
-#
-# CONFIG_NET_PKTGEN is not set
-CONFIG_NETDEVICES=y
-
-#
-# ARCnet devices
-#
-# CONFIG_ARCNET is not set
-# CONFIG_DUMMY is not set
-# CONFIG_BONDING is not set
-# CONFIG_EQUALIZER is not set
-# CONFIG_TUN is not set
-# CONFIG_ETHERTAP is not set
-
-#
-# Ethernet (10 or 100Mbit)
-#
-CONFIG_NET_ETHERNET=y
-# CONFIG_MII is not set
-# CONFIG_HAPPYMEAL is not set
-# CONFIG_SUNGEM is not set
-# CONFIG_NET_VENDOR_3COM is not set
-
-#
-# Tulip family network device support
-#
-# CONFIG_NET_TULIP is not set
-# CONFIG_HP100 is not set
-# CONFIG_NET_PCI is not set
-
-#
-# Ethernet (1000 Mbit)
-#
-# CONFIG_ACENIC is not set
-# CONFIG_DL2K is not set
-# CONFIG_E1000 is not set
-# CONFIG_NS83820 is not set
-# CONFIG_HAMACHI is not set
-# CONFIG_YELLOWFIN is not set
-# CONFIG_R8169 is not set
-# CONFIG_SK98LIN is not set
-# CONFIG_TIGON3 is not set
-
-#
-# Ethernet (10000 Mbit)
-#
-# CONFIG_IXGB is not set
-# CONFIG_FDDI is not set
-# CONFIG_HIPPI is not set
-# CONFIG_PPP is not set
-# CONFIG_SLIP is not set
-
-#
-# Wireless LAN (non-hamradio)
-#
-# CONFIG_NET_RADIO is not set
-
-#
-# Token Ring devices (depends on LLC=y)
-#
-# CONFIG_RCPCI is not set
-# CONFIG_SHAPER is not set
-
-#
-# Wan interfaces
-#
-# CONFIG_WAN is not set
-
-#
-# PCMCIA network device support
-#
-CONFIG_NET_PCMCIA=y
-# CONFIG_PCMCIA_3C589 is not set
-# CONFIG_PCMCIA_3C574 is not set
-CONFIG_PCMCIA_FMVJ18X=y
-CONFIG_PCMCIA_PCNET=m
-# CONFIG_PCMCIA_NMCLAN is not set
-# CONFIG_PCMCIA_SMC91C92 is not set
-# CONFIG_PCMCIA_XIRC2PS is not set
-# CONFIG_PCMCIA_AXNET is not set
-
-#
-# Amateur Radio support
-#
-# CONFIG_HAMRADIO is not set
-
-#
-# IrDA (infrared) support
-#
-# CONFIG_IRDA is not set
-
-#
-# ISDN subsystem
-#
-# CONFIG_ISDN_BOOL is not set
-
-#
-# Telephony Support
-#
-# CONFIG_PHONE is not set
-
-#
-# Input device support
-#
-CONFIG_INPUT=y
-
-#
-# Userland interfaces
-#
-# CONFIG_INPUT_MOUSEDEV is not set
-# CONFIG_INPUT_JOYDEV is not set
-# CONFIG_INPUT_TSDEV is not set
-# CONFIG_INPUT_EVDEV is not set
-# CONFIG_INPUT_EVBUG is not set
-
-#
-# Input I/O drivers
-#
-# CONFIG_GAMEPORT is not set
-CONFIG_SOUND_GAMEPORT=y
-# CONFIG_SERIO is not set
-
-#
-# Input Device Drivers
-#
-# CONFIG_INPUT_KEYBOARD is not set
-# CONFIG_INPUT_MOUSE is not set
-# CONFIG_INPUT_JOYSTICK is not set
-# CONFIG_INPUT_TOUCHSCREEN is not set
-# CONFIG_INPUT_MISC is not set
-
-#
-# Character devices
-#
-CONFIG_VT=y
-# CONFIG_VT_CONSOLE is not set
-CONFIG_HW_CONSOLE=y
-# CONFIG_SERIAL_NONSTANDARD is not set
-
-#
-# Serial drivers
-#
-CONFIG_SERIAL_8250=y
-CONFIG_SERIAL_8250_CONSOLE=y
-# CONFIG_SERIAL_8250_CS is not set
-# CONFIG_SERIAL_8250_EXTENDED is not set
-
-#
-# Non-8250 serial port support
-#
-CONFIG_SERIAL_CORE=y
-CONFIG_SERIAL_CORE_CONSOLE=y
-CONFIG_UNIX98_PTYS=y
-CONFIG_UNIX98_PTY_COUNT=256
-
-#
-# I2C support
-#
-# CONFIG_I2C is not set
-
-#
-# I2C Hardware Sensors Mainboard support
-#
-
-#
-# I2C Hardware Sensors Chip support
-#
-# CONFIG_I2C_SENSOR is not set
-
-#
-# Mice
-#
-# CONFIG_BUSMOUSE is not set
-# CONFIG_QIC02_TAPE is not set
-
-#
-# IPMI
-#
-# CONFIG_IPMI_HANDLER is not set
-
-#
-# Watchdog Cards
-#
-CONFIG_WATCHDOG=y
-# CONFIG_WATCHDOG_NOWAYOUT is not set
-# CONFIG_SOFT_WATCHDOG is not set
-# CONFIG_WDT is not set
-# CONFIG_WDTPCI is not set
-# CONFIG_PCWATCHDOG is not set
-# CONFIG_ACQUIRE_WDT is not set
-# CONFIG_ADVANTECH_WDT is not set
-# CONFIG_EUROTECH_WDT is not set
-# CONFIG_IB700_WDT is not set
-# CONFIG_I810_TCO is not set
-# CONFIG_MIXCOMWD is not set
-# CONFIG_SCx200_WDT is not set
-# CONFIG_60XX_WDT is not set
-# CONFIG_W83877F_WDT is not set
-# CONFIG_MACHZ_WDT is not set
-# CONFIG_SC520_WDT is not set
-# CONFIG_AMD7XX_TCO is not set
-# CONFIG_ALIM7101_WDT is not set
-# CONFIG_SC1200_WDT is not set
-# CONFIG_WAFER_WDT is not set
-# CONFIG_CPU5_WDT is not set
-# CONFIG_NVRAM is not set
-# CONFIG_RTC is not set
-# CONFIG_GEN_RTC is not set
-# CONFIG_DTLK is not set
-# CONFIG_R3964 is not set
-# CONFIG_APPLICOM is not set
-
-#
-# Ftape, the floppy tape device driver
-#
-# CONFIG_FTAPE is not set
-# CONFIG_AGP is not set
-# CONFIG_DRM is not set
-
-#
-# PCMCIA character devices
-#
-# CONFIG_SYNCLINK_CS is not set
-# CONFIG_RAW_DRIVER is not set
-# CONFIG_HANGCHECK_TIMER is not set
-
-#
-# Multimedia devices
-#
-# CONFIG_VIDEO_DEV is not set
-
-#
-# Digital Video Broadcasting Devices
-#
-# CONFIG_DVB is not set
-
-#
-# File systems
-#
-CONFIG_EXT2_FS=y
-# CONFIG_EXT2_FS_XATTR is not set
-# CONFIG_EXT3_FS is not set
-# CONFIG_JBD is not set
-# CONFIG_REISERFS_FS is not set
-# CONFIG_JFS_FS is not set
-# CONFIG_XFS_FS is not set
-# CONFIG_MINIX_FS is not set
-# CONFIG_ROMFS_FS is not set
-# CONFIG_QUOTA is not set
-CONFIG_AUTOFS_FS=y
-CONFIG_AUTOFS4_FS=y
-
-#
-# CD-ROM/DVD Filesystems
-#
-# CONFIG_ISO9660_FS is not set
-# CONFIG_UDF_FS is not set
-
-#
-# DOS/FAT/NT Filesystems
-#
-# CONFIG_FAT_FS is not set
-# CONFIG_NTFS_FS is not set
-
-#
-# Pseudo filesystems
-#
-CONFIG_PROC_FS=y
-# CONFIG_DEVFS_FS is not set
-CONFIG_DEVPTS_FS=y
-CONFIG_DEVPTS_FS_XATTR=y
-CONFIG_DEVPTS_FS_SECURITY=y
-# CONFIG_TMPFS is not set
-CONFIG_RAMFS=y
-
-#
-# Miscellaneous filesystems
-#
-# CONFIG_ADFS_FS is not set
-# CONFIG_AFFS_FS is not set
-# CONFIG_HFS_FS is not set
-# CONFIG_BEFS_FS is not set
-# CONFIG_BFS_FS is not set
-# CONFIG_EFS_FS is not set
-CONFIG_JFFS_FS=y
-CONFIG_JFFS_FS_VERBOSE=0
-CONFIG_JFFS2_FS=y
-CONFIG_JFFS2_FS_DEBUG=0
-# CONFIG_JFFS2_FS_NAND is not set
-# CONFIG_CRAMFS is not set
-# CONFIG_VXFS_FS is not set
-# CONFIG_HPFS_FS is not set
-# CONFIG_QNX4FS_FS is not set
-# CONFIG_SYSV_FS is not set
-# CONFIG_UFS_FS is not set
-
-#
-# Network File Systems
-#
-CONFIG_NFS_FS=y
-# CONFIG_NFS_V3 is not set
-# CONFIG_NFS_V4 is not set
-CONFIG_NFSD=y
-# CONFIG_NFSD_V3 is not set
-# CONFIG_NFSD_TCP is not set
-CONFIG_ROOT_NFS=y
-CONFIG_LOCKD=y
-CONFIG_EXPORTFS=y
-CONFIG_SUNRPC=y
-# CONFIG_SUNRPC_GSS is not set
-# CONFIG_SMB_FS is not set
-# CONFIG_CIFS is not set
-# CONFIG_NCP_FS is not set
-# CONFIG_CODA_FS is not set
-# CONFIG_INTERMEZZO_FS is not set
-# CONFIG_AFS_FS is not set
-
-#
-# Partition Types
-#
-# CONFIG_PARTITION_ADVANCED is not set
-CONFIG_MSDOS_PARTITION=y
-
-#
-# Graphics support
-#
-
-#
-# Console display driver support
-#
-# CONFIG_VGA_CONSOLE is not set
-# CONFIG_MDA_CONSOLE is not set
-CONFIG_DUMMY_CONSOLE=y
-
-#
-# Sound
-#
-# CONFIG_SOUND is not set
-
-#
-# USB support
-#
-# CONFIG_USB is not set
-# CONFIG_USB_GADGET is not set
-
-#
-# Bluetooth support
-#
-# CONFIG_BT is not set
-
-#
-# Kernel hacking
-#
-CONFIG_CROSSCOMPILE=y
-# CONFIG_DEBUG_KERNEL is not set
-
-#
-# Security options
-#
-# CONFIG_SECURITY is not set
-
-#
-# Cryptographic options
-#
-CONFIG_CRYPTO=y
-CONFIG_CRYPTO_HMAC=y
-CONFIG_CRYPTO_NULL=y
-# CONFIG_CRYPTO_MD4 is not set
-# CONFIG_CRYPTO_MD5 is not set
-# CONFIG_CRYPTO_SHA1 is not set
-# CONFIG_CRYPTO_SHA256 is not set
-CONFIG_CRYPTO_SHA512=y
-# CONFIG_CRYPTO_DES is not set
-# CONFIG_CRYPTO_BLOWFISH is not set
-CONFIG_CRYPTO_TWOFISH=y
-# CONFIG_CRYPTO_SERPENT is not set
-CONFIG_CRYPTO_AES=y
-CONFIG_CRYPTO_DEFLATE=y
-# CONFIG_CRYPTO_TEST is not set
-
-#
-# Library routines
-#
-# CONFIG_CRC32 is not set
-CONFIG_ZLIB_INFLATE=y
-CONFIG_ZLIB_DEFLATE=y
--- diff/arch/mips/defconfig-ev64120	2003-08-20 14:16:25.000000000 +0100
+++ source/arch/mips/defconfig-ev64120	1970-01-01 01:00:00.000000000 +0100
@@ -1,575 +0,0 @@
-#
-# Automatically generated make config: don't edit
-#
-CONFIG_MIPS=y
-# CONFIG_MIPS64 is not set
-CONFIG_MIPS32=y
-
-#
-# Code maturity level options
-#
-CONFIG_EXPERIMENTAL=y
-
-#
-# General setup
-#
-CONFIG_SWAP=y
-CONFIG_SYSVIPC=y
-# CONFIG_BSD_PROCESS_ACCT is not set
-CONFIG_SYSCTL=y
-CONFIG_LOG_BUF_SHIFT=14
-# CONFIG_EMBEDDED is not set
-CONFIG_KALLSYMS=y
-CONFIG_FUTEX=y
-CONFIG_EPOLL=y
-CONFIG_IOSCHED_AS=y
-CONFIG_IOSCHED_DEADLINE=y
-
-#
-# Loadable module support
-#
-CONFIG_MODULES=y
-CONFIG_MODULE_UNLOAD=y
-# CONFIG_MODULE_FORCE_UNLOAD is not set
-CONFIG_OBSOLETE_MODPARM=y
-CONFIG_MODVERSIONS=y
-# CONFIG_KMOD is not set
-
-#
-# Machine selection
-#
-# CONFIG_ACER_PICA_61 is not set
-# CONFIG_BAGET_MIPS is not set
-# CONFIG_CASIO_E55 is not set
-# CONFIG_MIPS_COBALT is not set
-# CONFIG_DECSTATION is not set
-CONFIG_MIPS_EV64120=y
-# CONFIG_EVB_PCI1 is not set
-CONFIG_SYSCLK_100=y
-# CONFIG_SYSCLK_75 is not set
-# CONFIG_SYSCLK_83 is not set
-# CONFIG_MIPS_EV96100 is not set
-# CONFIG_MIPS_IVR is not set
-# CONFIG_LASAT is not set
-# CONFIG_HP_LASERJET is not set
-# CONFIG_IBM_WORKPAD is not set
-# CONFIG_MIPS_ITE8172 is not set
-# CONFIG_MIPS_ATLAS is not set
-# CONFIG_MIPS_MAGNUM_4000 is not set
-# CONFIG_MIPS_MALTA is not set
-# CONFIG_MIPS_SEAD is not set
-# CONFIG_MOMENCO_OCELOT is not set
-# CONFIG_MOMENCO_OCELOT_G is not set
-# CONFIG_MOMENCO_OCELOT_C is not set
-# CONFIG_DDB5074 is not set
-# CONFIG_DDB5476 is not set
-# CONFIG_DDB5477 is not set
-# CONFIG_NEC_OSPREY is not set
-# CONFIG_NEC_EAGLE is not set
-# CONFIG_OLIVETTI_M700 is not set
-# CONFIG_SGI_IP22 is not set
-# CONFIG_SGI_IP32 is not set
-# CONFIG_SOC_AU1X00 is not set
-# CONFIG_SIBYTE_SB1xxx_SOC is not set
-# CONFIG_SNI_RM200_PCI is not set
-# CONFIG_TANBAC_TB0226 is not set
-# CONFIG_TANBAC_TB0229 is not set
-# CONFIG_TOSHIBA_JMR3927 is not set
-# CONFIG_TOSHIBA_RBTX4927 is not set
-# CONFIG_VICTOR_MPC30X is not set
-# CONFIG_ZAO_CAPCELLA is not set
-CONFIG_RWSEM_GENERIC_SPINLOCK=y
-CONFIG_CONFIG_GT64120=y
-CONFIG_NONCOHERENT_IO=y
-# CONFIG_CPU_LITTLE_ENDIAN is not set
-CONFIG_MIPS_GT64120=y
-# CONFIG_FB is not set
-
-#
-# CPU selection
-#
-# CONFIG_CPU_MIPS32 is not set
-# CONFIG_CPU_MIPS64 is not set
-# CONFIG_CPU_R3000 is not set
-# CONFIG_CPU_TX39XX is not set
-# CONFIG_CPU_VR41XX is not set
-# CONFIG_CPU_R4300 is not set
-# CONFIG_CPU_R4X00 is not set
-# CONFIG_CPU_TX49XX is not set
-CONFIG_CPU_R5000=y
-# CONFIG_CPU_R5432 is not set
-# CONFIG_CPU_R6000 is not set
-# CONFIG_CPU_NEVADA is not set
-# CONFIG_CPU_R8000 is not set
-# CONFIG_CPU_R10000 is not set
-# CONFIG_CPU_RM7000 is not set
-# CONFIG_CPU_SB1 is not set
-# CONFIG_64BIT_PHYS_ADDR is not set
-# CONFIG_CPU_ADVANCED is not set
-CONFIG_CPU_HAS_LLSC=y
-CONFIG_CPU_HAS_LLDSCD=y
-CONFIG_CPU_HAS_SYNC=y
-# CONFIG_PREEMPT is not set
-# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
-
-#
-# Bus options (PCI, PCMCIA, EISA, ISA, TC)
-#
-CONFIG_PCI=y
-CONFIG_PCI_LEGACY_PROC=y
-CONFIG_PCI_NAMES=y
-CONFIG_MMU=y
-# CONFIG_HOTPLUG is not set
-
-#
-# Executable file formats
-#
-CONFIG_KCORE_ELF=y
-CONFIG_BINFMT_ELF=y
-# CONFIG_BINFMT_MISC is not set
-CONFIG_TRAD_SIGNALS=y
-# CONFIG_BINFMT_IRIX is not set
-
-#
-# Memory Technology Devices (MTD)
-#
-# CONFIG_MTD is not set
-
-#
-# Parallel port support
-#
-# CONFIG_PARPORT is not set
-
-#
-# Plug and Play support
-#
-# CONFIG_PNP is not set
-
-#
-# Generic Driver Options
-#
-# CONFIG_FW_LOADER is not set
-
-#
-# Block devices
-#
-# CONFIG_BLK_DEV_FD is not set
-# CONFIG_BLK_CPQ_DA is not set
-# CONFIG_BLK_CPQ_CISS_DA is not set
-# CONFIG_BLK_DEV_DAC960 is not set
-# CONFIG_BLK_DEV_UMEM is not set
-# CONFIG_BLK_DEV_LOOP is not set
-# CONFIG_BLK_DEV_NBD is not set
-# CONFIG_BLK_DEV_RAM is not set
-# CONFIG_BLK_DEV_INITRD is not set
-# CONFIG_LBD is not set
-
-#
-# ATA/ATAPI/MFM/RLL support
-#
-# CONFIG_IDE is not set
-
-#
-# SCSI device support
-#
-# CONFIG_SCSI is not set
-
-#
-# Multi-device support (RAID and LVM)
-#
-# CONFIG_MD is not set
-
-#
-# Fusion MPT device support
-#
-
-#
-# IEEE 1394 (FireWire) support (EXPERIMENTAL)
-#
-# CONFIG_IEEE1394 is not set
-
-#
-# I2O device support
-#
-# CONFIG_I2O is not set
-
-#
-# Networking support
-#
-CONFIG_NET=y
-
-#
-# Networking options
-#
-# CONFIG_PACKET is not set
-CONFIG_NETLINK_DEV=y
-# CONFIG_NETFILTER is not set
-CONFIG_UNIX=y
-CONFIG_NET_KEY=y
-CONFIG_INET=y
-# CONFIG_IP_MULTICAST is not set
-# CONFIG_IP_ADVANCED_ROUTER is not set
-CONFIG_IP_PNP=y
-# CONFIG_IP_PNP_DHCP is not set
-# CONFIG_IP_PNP_BOOTP is not set
-# CONFIG_IP_PNP_RARP is not set
-# CONFIG_NET_IPIP is not set
-# CONFIG_NET_IPGRE is not set
-# CONFIG_ARPD is not set
-# CONFIG_INET_ECN is not set
-# CONFIG_SYN_COOKIES is not set
-# CONFIG_INET_AH is not set
-# CONFIG_INET_ESP is not set
-# CONFIG_INET_IPCOMP is not set
-# CONFIG_IPV6 is not set
-# CONFIG_XFRM_USER is not set
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
-CONFIG_IPV6_SCTP__=y
-# CONFIG_IP_SCTP is not set
-# CONFIG_ATM is not set
-# CONFIG_VLAN_8021Q is not set
-# CONFIG_LLC is not set
-# CONFIG_DECNET is not set
-# CONFIG_BRIDGE is not set
-# CONFIG_X25 is not set
-# CONFIG_LAPB is not set
-# CONFIG_NET_DIVERT is not set
-# CONFIG_ECONET is not set
-# CONFIG_WAN_ROUTER is not set
-# CONFIG_NET_FASTROUTE is not set
-# CONFIG_NET_HW_FLOWCONTROL is not set
-
-#
-# QoS and/or fair queueing
-#
-# CONFIG_NET_SCHED is not set
-
-#
-# Network testing
-#
-# CONFIG_NET_PKTGEN is not set
-CONFIG_NETDEVICES=y
-
-#
-# ARCnet devices
-#
-# CONFIG_ARCNET is not set
-# CONFIG_DUMMY is not set
-# CONFIG_BONDING is not set
-# CONFIG_EQUALIZER is not set
-# CONFIG_TUN is not set
-# CONFIG_ETHERTAP is not set
-
-#
-# Ethernet (10 or 100Mbit)
-#
-CONFIG_NET_ETHERNET=y
-# CONFIG_MII is not set
-# CONFIG_HAPPYMEAL is not set
-# CONFIG_SUNGEM is not set
-# CONFIG_NET_VENDOR_3COM is not set
-
-#
-# Tulip family network device support
-#
-# CONFIG_NET_TULIP is not set
-# CONFIG_HP100 is not set
-# CONFIG_NET_PCI is not set
-
-#
-# Ethernet (1000 Mbit)
-#
-# CONFIG_ACENIC is not set
-# CONFIG_DL2K is not set
-# CONFIG_E1000 is not set
-# CONFIG_NS83820 is not set
-# CONFIG_HAMACHI is not set
-# CONFIG_YELLOWFIN is not set
-# CONFIG_R8169 is not set
-# CONFIG_SK98LIN is not set
-# CONFIG_TIGON3 is not set
-
-#
-# Ethernet (10000 Mbit)
-#
-# CONFIG_IXGB is not set
-# CONFIG_FDDI is not set
-# CONFIG_HIPPI is not set
-CONFIG_PPP=y
-# CONFIG_PPP_MULTILINK is not set
-# CONFIG_PPP_FILTER is not set
-CONFIG_PPP_ASYNC=y
-# CONFIG_PPP_SYNC_TTY is not set
-# CONFIG_PPP_DEFLATE is not set
-# CONFIG_PPP_BSDCOMP is not set
-# CONFIG_PPPOE is not set
-# CONFIG_SLIP is not set
-
-#
-# Wireless LAN (non-hamradio)
-#
-# CONFIG_NET_RADIO is not set
-
-#
-# Token Ring devices (depends on LLC=y)
-#
-# CONFIG_RCPCI is not set
-# CONFIG_SHAPER is not set
-
-#
-# Wan interfaces
-#
-# CONFIG_WAN is not set
-
-#
-# Amateur Radio support
-#
-# CONFIG_HAMRADIO is not set
-
-#
-# IrDA (infrared) support
-#
-# CONFIG_IRDA is not set
-
-#
-# ISDN subsystem
-#
-# CONFIG_ISDN_BOOL is not set
-
-#
-# Telephony Support
-#
-# CONFIG_PHONE is not set
-
-#
-# Input device support
-#
-CONFIG_INPUT=y
-
-#
-# Userland interfaces
-#
-# CONFIG_INPUT_MOUSEDEV is not set
-# CONFIG_INPUT_JOYDEV is not set
-# CONFIG_INPUT_TSDEV is not set
-# CONFIG_INPUT_EVDEV is not set
-# CONFIG_INPUT_EVBUG is not set
-
-#
-# Input I/O drivers
-#
-# CONFIG_GAMEPORT is not set
-CONFIG_SOUND_GAMEPORT=y
-CONFIG_SERIO=y
-# CONFIG_SERIO_I8042 is not set
-CONFIG_SERIO_SERPORT=y
-# CONFIG_SERIO_CT82C710 is not set
-# CONFIG_SERIO_PCIPS2 is not set
-
-#
-# Input Device Drivers
-#
-# CONFIG_INPUT_KEYBOARD is not set
-# CONFIG_INPUT_MOUSE is not set
-# CONFIG_INPUT_JOYSTICK is not set
-# CONFIG_INPUT_TOUCHSCREEN is not set
-# CONFIG_INPUT_MISC is not set
-
-#
-# Character devices
-#
-# CONFIG_VT is not set
-# CONFIG_SERIAL_NONSTANDARD is not set
-
-#
-# Serial drivers
-#
-CONFIG_SERIAL_8250=y
-# CONFIG_SERIAL_8250_CONSOLE is not set
-# CONFIG_SERIAL_8250_EXTENDED is not set
-
-#
-# Non-8250 serial port support
-#
-CONFIG_SERIAL_CORE=y
-CONFIG_UNIX98_PTYS=y
-CONFIG_UNIX98_PTY_COUNT=256
-
-#
-# I2C support
-#
-# CONFIG_I2C is not set
-
-#
-# I2C Hardware Sensors Mainboard support
-#
-
-#
-# I2C Hardware Sensors Chip support
-#
-# CONFIG_I2C_SENSOR is not set
-
-#
-# Mice
-#
-# CONFIG_BUSMOUSE is not set
-# CONFIG_QIC02_TAPE is not set
-
-#
-# IPMI
-#
-# CONFIG_IPMI_HANDLER is not set
-
-#
-# Watchdog Cards
-#
-# CONFIG_WATCHDOG is not set
-# CONFIG_NVRAM is not set
-# CONFIG_RTC is not set
-# CONFIG_GEN_RTC is not set
-# CONFIG_DTLK is not set
-# CONFIG_R3964 is not set
-# CONFIG_APPLICOM is not set
-
-#
-# Ftape, the floppy tape device driver
-#
-# CONFIG_FTAPE is not set
-# CONFIG_AGP is not set
-# CONFIG_DRM is not set
-# CONFIG_RAW_DRIVER is not set
-# CONFIG_HANGCHECK_TIMER is not set
-
-#
-# Multimedia devices
-#
-# CONFIG_VIDEO_DEV is not set
-
-#
-# Digital Video Broadcasting Devices
-#
-# CONFIG_DVB is not set
-
-#
-# File systems
-#
-CONFIG_EXT2_FS=y
-# CONFIG_EXT2_FS_XATTR is not set
-# CONFIG_EXT3_FS is not set
-# CONFIG_JBD is not set
-# CONFIG_REISERFS_FS is not set
-# CONFIG_JFS_FS is not set
-# CONFIG_XFS_FS is not set
-# CONFIG_MINIX_FS is not set
-# CONFIG_ROMFS_FS is not set
-# CONFIG_QUOTA is not set
-# CONFIG_AUTOFS_FS is not set
-# CONFIG_AUTOFS4_FS is not set
-
-#
-# CD-ROM/DVD Filesystems
-#
-# CONFIG_ISO9660_FS is not set
-# CONFIG_UDF_FS is not set
-
-#
-# DOS/FAT/NT Filesystems
-#
-# CONFIG_FAT_FS is not set
-# CONFIG_NTFS_FS is not set
-
-#
-# Pseudo filesystems
-#
-CONFIG_PROC_FS=y
-# CONFIG_DEVFS_FS is not set
-CONFIG_DEVPTS_FS=y
-CONFIG_DEVPTS_FS_XATTR=y
-CONFIG_DEVPTS_FS_SECURITY=y
-# CONFIG_TMPFS is not set
-CONFIG_RAMFS=y
-
-#
-# Miscellaneous filesystems
-#
-# CONFIG_ADFS_FS is not set
-# CONFIG_AFFS_FS is not set
-# CONFIG_HFS_FS is not set
-# CONFIG_BEFS_FS is not set
-# CONFIG_BFS_FS is not set
-# CONFIG_EFS_FS is not set
-# CONFIG_CRAMFS is not set
-# CONFIG_VXFS_FS is not set
-# CONFIG_HPFS_FS is not set
-# CONFIG_QNX4FS_FS is not set
-# CONFIG_SYSV_FS is not set
-# CONFIG_UFS_FS is not set
-
-#
-# Network File Systems
-#
-CONFIG_NFS_FS=y
-# CONFIG_NFS_V3 is not set
-# CONFIG_NFS_V4 is not set
-# CONFIG_NFSD is not set
-CONFIG_ROOT_NFS=y
-CONFIG_LOCKD=y
-# CONFIG_EXPORTFS is not set
-CONFIG_SUNRPC=y
-# CONFIG_SUNRPC_GSS is not set
-# CONFIG_SMB_FS is not set
-# CONFIG_CIFS is not set
-# CONFIG_NCP_FS is not set
-# CONFIG_CODA_FS is not set
-# CONFIG_INTERMEZZO_FS is not set
-# CONFIG_AFS_FS is not set
-
-#
-# Partition Types
-#
-# CONFIG_PARTITION_ADVANCED is not set
-CONFIG_MSDOS_PARTITION=y
-
-#
-# Graphics support
-#
-
-#
-# Sound
-#
-# CONFIG_SOUND is not set
-
-#
-# USB support
-#
-# CONFIG_USB is not set
-# CONFIG_USB_GADGET is not set
-
-#
-# Bluetooth support
-#
-# CONFIG_BT is not set
-
-#
-# Kernel hacking
-#
-CONFIG_CROSSCOMPILE=y
-# CONFIG_DEBUG_KERNEL is not set
-
-#
-# Security options
-#
-# CONFIG_SECURITY is not set
-
-#
-# Cryptographic options
-#
-# CONFIG_CRYPTO is not set
-
-#
-# Library routines
-#
-# CONFIG_CRC32 is not set
--- diff/arch/mips/defconfig-ev96100	2003-08-20 14:16:25.000000000 +0100
+++ source/arch/mips/defconfig-ev96100	1970-01-01 01:00:00.000000000 +0100
@@ -1,527 +0,0 @@
-#
-# Automatically generated make config: don't edit
-#
-CONFIG_MIPS=y
-# CONFIG_MIPS64 is not set
-CONFIG_MIPS32=y
-
-#
-# Code maturity level options
-#
-CONFIG_EXPERIMENTAL=y
-
-#
-# General setup
-#
-CONFIG_SWAP=y
-CONFIG_SYSVIPC=y
-# CONFIG_BSD_PROCESS_ACCT is not set
-CONFIG_SYSCTL=y
-CONFIG_LOG_BUF_SHIFT=14
-# CONFIG_EMBEDDED is not set
-CONFIG_KALLSYMS=y
-CONFIG_FUTEX=y
-CONFIG_EPOLL=y
-CONFIG_IOSCHED_AS=y
-CONFIG_IOSCHED_DEADLINE=y
-
-#
-# Loadable module support
-#
-CONFIG_MODULES=y
-CONFIG_MODULE_UNLOAD=y
-# CONFIG_MODULE_FORCE_UNLOAD is not set
-CONFIG_OBSOLETE_MODPARM=y
-CONFIG_MODVERSIONS=y
-# CONFIG_KMOD is not set
-
-#
-# Machine selection
-#
-# CONFIG_ACER_PICA_61 is not set
-# CONFIG_BAGET_MIPS is not set
-# CONFIG_CASIO_E55 is not set
-# CONFIG_MIPS_COBALT is not set
-# CONFIG_DECSTATION is not set
-# CONFIG_MIPS_EV64120 is not set
-CONFIG_MIPS_EV96100=y
-# CONFIG_MIPS_IVR is not set
-# CONFIG_LASAT is not set
-# CONFIG_HP_LASERJET is not set
-# CONFIG_IBM_WORKPAD is not set
-# CONFIG_MIPS_ITE8172 is not set
-# CONFIG_MIPS_ATLAS is not set
-# CONFIG_MIPS_MAGNUM_4000 is not set
-# CONFIG_MIPS_MALTA is not set
-# CONFIG_MIPS_SEAD is not set
-# CONFIG_MOMENCO_OCELOT is not set
-# CONFIG_MOMENCO_OCELOT_G is not set
-# CONFIG_MOMENCO_OCELOT_C is not set
-# CONFIG_DDB5074 is not set
-# CONFIG_DDB5476 is not set
-# CONFIG_DDB5477 is not set
-# CONFIG_NEC_OSPREY is not set
-# CONFIG_NEC_EAGLE is not set
-# CONFIG_OLIVETTI_M700 is not set
-# CONFIG_SGI_IP22 is not set
-# CONFIG_SGI_IP32 is not set
-# CONFIG_SOC_AU1X00 is not set
-# CONFIG_SIBYTE_SB1xxx_SOC is not set
-# CONFIG_SNI_RM200_PCI is not set
-# CONFIG_TANBAC_TB0226 is not set
-# CONFIG_TANBAC_TB0229 is not set
-# CONFIG_TOSHIBA_JMR3927 is not set
-# CONFIG_TOSHIBA_RBTX4927 is not set
-# CONFIG_VICTOR_MPC30X is not set
-# CONFIG_ZAO_CAPCELLA is not set
-CONFIG_RWSEM_GENERIC_SPINLOCK=y
-CONFIG_NONCOHERENT_IO=y
-# CONFIG_CPU_LITTLE_ENDIAN is not set
-CONFIG_NEW_PCI=y
-CONFIG_SWAP_IO_SPACE=y
-CONFIG_MIPS_GT96100=y
-# CONFIG_FB is not set
-CONFIG_BOARD_SCACHE=y
-
-#
-# CPU selection
-#
-# CONFIG_CPU_MIPS32 is not set
-# CONFIG_CPU_MIPS64 is not set
-# CONFIG_CPU_R3000 is not set
-# CONFIG_CPU_TX39XX is not set
-# CONFIG_CPU_VR41XX is not set
-# CONFIG_CPU_R4300 is not set
-# CONFIG_CPU_R4X00 is not set
-# CONFIG_CPU_TX49XX is not set
-# CONFIG_CPU_R5000 is not set
-# CONFIG_CPU_R5432 is not set
-# CONFIG_CPU_R6000 is not set
-# CONFIG_CPU_NEVADA is not set
-# CONFIG_CPU_R8000 is not set
-# CONFIG_CPU_R10000 is not set
-CONFIG_CPU_RM7000=y
-# CONFIG_CPU_SB1 is not set
-CONFIG_CPU_HAS_PREFETCH=y
-# CONFIG_64BIT_PHYS_ADDR is not set
-# CONFIG_CPU_ADVANCED is not set
-CONFIG_CPU_HAS_LLSC=y
-CONFIG_CPU_HAS_LLDSCD=y
-CONFIG_CPU_HAS_SYNC=y
-# CONFIG_PREEMPT is not set
-# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
-
-#
-# Bus options (PCI, PCMCIA, EISA, ISA, TC)
-#
-# CONFIG_PCI is not set
-CONFIG_MMU=y
-# CONFIG_HOTPLUG is not set
-
-#
-# Executable file formats
-#
-CONFIG_KCORE_ELF=y
-CONFIG_BINFMT_ELF=y
-# CONFIG_BINFMT_MISC is not set
-CONFIG_TRAD_SIGNALS=y
-# CONFIG_BINFMT_IRIX is not set
-
-#
-# Memory Technology Devices (MTD)
-#
-# CONFIG_MTD is not set
-
-#
-# Parallel port support
-#
-# CONFIG_PARPORT is not set
-
-#
-# Plug and Play support
-#
-# CONFIG_PNP is not set
-
-#
-# Generic Driver Options
-#
-# CONFIG_FW_LOADER is not set
-
-#
-# Block devices
-#
-# CONFIG_BLK_DEV_FD is not set
-# CONFIG_BLK_DEV_LOOP is not set
-# CONFIG_BLK_DEV_NBD is not set
-# CONFIG_BLK_DEV_RAM is not set
-# CONFIG_BLK_DEV_INITRD is not set
-# CONFIG_LBD is not set
-
-#
-# ATA/ATAPI/MFM/RLL support
-#
-# CONFIG_IDE is not set
-
-#
-# SCSI device support
-#
-# CONFIG_SCSI is not set
-
-#
-# Multi-device support (RAID and LVM)
-#
-# CONFIG_MD is not set
-
-#
-# Fusion MPT device support
-#
-
-#
-# I2O device support
-#
-
-#
-# Networking support
-#
-CONFIG_NET=y
-
-#
-# Networking options
-#
-# CONFIG_PACKET is not set
-CONFIG_NETLINK_DEV=y
-# CONFIG_NETFILTER is not set
-CONFIG_UNIX=y
-CONFIG_NET_KEY=y
-CONFIG_INET=y
-# CONFIG_IP_MULTICAST is not set
-# CONFIG_IP_ADVANCED_ROUTER is not set
-CONFIG_IP_PNP=y
-# CONFIG_IP_PNP_DHCP is not set
-CONFIG_IP_PNP_BOOTP=y
-# CONFIG_IP_PNP_RARP is not set
-# CONFIG_NET_IPIP is not set
-# CONFIG_NET_IPGRE is not set
-# CONFIG_ARPD is not set
-# CONFIG_INET_ECN is not set
-# CONFIG_SYN_COOKIES is not set
-# CONFIG_INET_AH is not set
-# CONFIG_INET_ESP is not set
-# CONFIG_INET_IPCOMP is not set
-# CONFIG_IPV6 is not set
-# CONFIG_XFRM_USER is not set
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
-CONFIG_IPV6_SCTP__=y
-# CONFIG_IP_SCTP is not set
-# CONFIG_ATM is not set
-# CONFIG_VLAN_8021Q is not set
-# CONFIG_LLC is not set
-# CONFIG_DECNET is not set
-# CONFIG_BRIDGE is not set
-# CONFIG_X25 is not set
-# CONFIG_LAPB is not set
-# CONFIG_NET_DIVERT is not set
-# CONFIG_ECONET is not set
-# CONFIG_WAN_ROUTER is not set
-# CONFIG_NET_FASTROUTE is not set
-# CONFIG_NET_HW_FLOWCONTROL is not set
-
-#
-# QoS and/or fair queueing
-#
-# CONFIG_NET_SCHED is not set
-
-#
-# Network testing
-#
-# CONFIG_NET_PKTGEN is not set
-CONFIG_NETDEVICES=y
-# CONFIG_DUMMY is not set
-# CONFIG_BONDING is not set
-# CONFIG_EQUALIZER is not set
-# CONFIG_TUN is not set
-# CONFIG_ETHERTAP is not set
-
-#
-# Ethernet (10 or 100Mbit)
-#
-CONFIG_NET_ETHERNET=y
-# CONFIG_MII is not set
-CONFIG_MIPS_GT96100ETH=y
-
-#
-# Ethernet (1000 Mbit)
-#
-
-#
-# Ethernet (10000 Mbit)
-#
-# CONFIG_PPP is not set
-# CONFIG_SLIP is not set
-
-#
-# Wireless LAN (non-hamradio)
-#
-# CONFIG_NET_RADIO is not set
-
-#
-# Token Ring devices (depends on LLC=y)
-#
-# CONFIG_SHAPER is not set
-
-#
-# Wan interfaces
-#
-# CONFIG_WAN is not set
-
-#
-# Amateur Radio support
-#
-# CONFIG_HAMRADIO is not set
-
-#
-# IrDA (infrared) support
-#
-# CONFIG_IRDA is not set
-
-#
-# ISDN subsystem
-#
-# CONFIG_ISDN_BOOL is not set
-
-#
-# Telephony Support
-#
-# CONFIG_PHONE is not set
-
-#
-# Input device support
-#
-CONFIG_INPUT=y
-
-#
-# Userland interfaces
-#
-# CONFIG_INPUT_MOUSEDEV is not set
-# CONFIG_INPUT_JOYDEV is not set
-# CONFIG_INPUT_TSDEV is not set
-# CONFIG_INPUT_EVDEV is not set
-# CONFIG_INPUT_EVBUG is not set
-
-#
-# Input I/O drivers
-#
-# CONFIG_GAMEPORT is not set
-CONFIG_SOUND_GAMEPORT=y
-CONFIG_SERIO=y
-# CONFIG_SERIO_I8042 is not set
-CONFIG_SERIO_SERPORT=y
-# CONFIG_SERIO_CT82C710 is not set
-
-#
-# Input Device Drivers
-#
-# CONFIG_INPUT_KEYBOARD is not set
-# CONFIG_INPUT_MOUSE is not set
-# CONFIG_INPUT_JOYSTICK is not set
-# CONFIG_INPUT_TOUCHSCREEN is not set
-# CONFIG_INPUT_MISC is not set
-
-#
-# Character devices
-#
-# CONFIG_VT is not set
-# CONFIG_SERIAL_NONSTANDARD is not set
-
-#
-# Serial drivers
-#
-CONFIG_SERIAL_8250=y
-CONFIG_SERIAL_8250_CONSOLE=y
-# CONFIG_SERIAL_8250_EXTENDED is not set
-
-#
-# Non-8250 serial port support
-#
-CONFIG_SERIAL_CORE=y
-CONFIG_SERIAL_CORE_CONSOLE=y
-CONFIG_UNIX98_PTYS=y
-CONFIG_UNIX98_PTY_COUNT=256
-
-#
-# I2C support
-#
-# CONFIG_I2C is not set
-
-#
-# I2C Hardware Sensors Mainboard support
-#
-
-#
-# I2C Hardware Sensors Chip support
-#
-# CONFIG_I2C_SENSOR is not set
-
-#
-# Mice
-#
-# CONFIG_BUSMOUSE is not set
-# CONFIG_QIC02_TAPE is not set
-
-#
-# IPMI
-#
-# CONFIG_IPMI_HANDLER is not set
-
-#
-# Watchdog Cards
-#
-# CONFIG_WATCHDOG is not set
-# CONFIG_NVRAM is not set
-# CONFIG_RTC is not set
-# CONFIG_GEN_RTC is not set
-# CONFIG_DTLK is not set
-# CONFIG_R3964 is not set
-# CONFIG_APPLICOM is not set
-
-#
-# Ftape, the floppy tape device driver
-#
-# CONFIG_FTAPE is not set
-# CONFIG_AGP is not set
-# CONFIG_DRM is not set
-# CONFIG_RAW_DRIVER is not set
-# CONFIG_HANGCHECK_TIMER is not set
-
-#
-# Multimedia devices
-#
-# CONFIG_VIDEO_DEV is not set
-
-#
-# Digital Video Broadcasting Devices
-#
-# CONFIG_DVB is not set
-
-#
-# File systems
-#
-CONFIG_EXT2_FS=y
-# CONFIG_EXT2_FS_XATTR is not set
-# CONFIG_EXT3_FS is not set
-# CONFIG_JBD is not set
-# CONFIG_REISERFS_FS is not set
-# CONFIG_JFS_FS is not set
-# CONFIG_XFS_FS is not set
-# CONFIG_MINIX_FS is not set
-# CONFIG_ROMFS_FS is not set
-# CONFIG_QUOTA is not set
-# CONFIG_AUTOFS_FS is not set
-# CONFIG_AUTOFS4_FS is not set
-
-#
-# CD-ROM/DVD Filesystems
-#
-# CONFIG_ISO9660_FS is not set
-# CONFIG_UDF_FS is not set
-
-#
-# DOS/FAT/NT Filesystems
-#
-# CONFIG_FAT_FS is not set
-# CONFIG_NTFS_FS is not set
-
-#
-# Pseudo filesystems
-#
-CONFIG_PROC_FS=y
-# CONFIG_DEVFS_FS is not set
-CONFIG_DEVPTS_FS=y
-CONFIG_DEVPTS_FS_XATTR=y
-CONFIG_DEVPTS_FS_SECURITY=y
-# CONFIG_TMPFS is not set
-CONFIG_RAMFS=y
-
-#
-# Miscellaneous filesystems
-#
-# CONFIG_ADFS_FS is not set
-# CONFIG_AFFS_FS is not set
-# CONFIG_HFS_FS is not set
-# CONFIG_BEFS_FS is not set
-# CONFIG_BFS_FS is not set
-# CONFIG_EFS_FS is not set
-# CONFIG_CRAMFS is not set
-# CONFIG_VXFS_FS is not set
-# CONFIG_HPFS_FS is not set
-# CONFIG_QNX4FS_FS is not set
-# CONFIG_SYSV_FS is not set
-# CONFIG_UFS_FS is not set
-
-#
-# Network File Systems
-#
-CONFIG_NFS_FS=y
-# CONFIG_NFS_V3 is not set
-# CONFIG_NFS_V4 is not set
-# CONFIG_NFSD is not set
-CONFIG_ROOT_NFS=y
-CONFIG_LOCKD=y
-# CONFIG_EXPORTFS is not set
-CONFIG_SUNRPC=y
-# CONFIG_SUNRPC_GSS is not set
-# CONFIG_SMB_FS is not set
-# CONFIG_CIFS is not set
-# CONFIG_NCP_FS is not set
-# CONFIG_CODA_FS is not set
-# CONFIG_INTERMEZZO_FS is not set
-# CONFIG_AFS_FS is not set
-
-#
-# Partition Types
-#
-# CONFIG_PARTITION_ADVANCED is not set
-CONFIG_MSDOS_PARTITION=y
-
-#
-# Graphics support
-#
-
-#
-# Sound
-#
-# CONFIG_SOUND is not set
-
-#
-# USB support
-#
-# CONFIG_USB_GADGET is not set
-
-#
-# Bluetooth support
-#
-# CONFIG_BT is not set
-
-#
-# Kernel hacking
-#
-CONFIG_CROSSCOMPILE=y
-# CONFIG_DEBUG_KERNEL is not set
-
-#
-# Security options
-#
-# CONFIG_SECURITY is not set
-
-#
-# Cryptographic options
-#
-# CONFIG_CRYPTO is not set
-
-#
-# Library routines
-#
-# CONFIG_CRC32 is not set
--- diff/arch/mips/defconfig-hp-lj	2003-08-20 14:16:36.000000000 +0100
+++ source/arch/mips/defconfig-hp-lj	1970-01-01 01:00:00.000000000 +0100
@@ -1,613 +0,0 @@
-#
-# Automatically generated make config: don't edit
-#
-CONFIG_MIPS=y
-# CONFIG_MIPS64 is not set
-CONFIG_MIPS32=y
-
-#
-# Code maturity level options
-#
-CONFIG_EXPERIMENTAL=y
-
-#
-# General setup
-#
-CONFIG_SWAP=y
-CONFIG_SYSVIPC=y
-# CONFIG_BSD_PROCESS_ACCT is not set
-CONFIG_SYSCTL=y
-CONFIG_LOG_BUF_SHIFT=14
-# CONFIG_EMBEDDED is not set
-CONFIG_KALLSYMS=y
-CONFIG_FUTEX=y
-CONFIG_EPOLL=y
-CONFIG_IOSCHED_AS=y
-CONFIG_IOSCHED_DEADLINE=y
-
-#
-# Loadable module support
-#
-CONFIG_MODULES=y
-CONFIG_MODULE_UNLOAD=y
-# CONFIG_MODULE_FORCE_UNLOAD is not set
-CONFIG_OBSOLETE_MODPARM=y
-CONFIG_MODVERSIONS=y
-CONFIG_KMOD=y
-
-#
-# Machine selection
-#
-# CONFIG_ACER_PICA_61 is not set
-# CONFIG_BAGET_MIPS is not set
-# CONFIG_CASIO_E55 is not set
-# CONFIG_MIPS_COBALT is not set
-# CONFIG_DECSTATION is not set
-# CONFIG_MIPS_EV64120 is not set
-# CONFIG_MIPS_EV96100 is not set
-# CONFIG_MIPS_IVR is not set
-# CONFIG_LASAT is not set
-CONFIG_HP_LASERJET=y
-# CONFIG_IBM_WORKPAD is not set
-# CONFIG_MIPS_ITE8172 is not set
-# CONFIG_MIPS_ATLAS is not set
-# CONFIG_MIPS_MAGNUM_4000 is not set
-# CONFIG_MIPS_MALTA is not set
-# CONFIG_MIPS_SEAD is not set
-# CONFIG_MOMENCO_OCELOT is not set
-# CONFIG_MOMENCO_OCELOT_G is not set
-# CONFIG_MOMENCO_OCELOT_C is not set
-# CONFIG_DDB5074 is not set
-# CONFIG_DDB5476 is not set
-# CONFIG_DDB5477 is not set
-# CONFIG_NEC_OSPREY is not set
-# CONFIG_NEC_EAGLE is not set
-# CONFIG_OLIVETTI_M700 is not set
-# CONFIG_SGI_IP22 is not set
-# CONFIG_SGI_IP32 is not set
-# CONFIG_SOC_AU1X00 is not set
-# CONFIG_SIBYTE_SB1xxx_SOC is not set
-# CONFIG_SNI_RM200_PCI is not set
-# CONFIG_TANBAC_TB0226 is not set
-# CONFIG_TANBAC_TB0229 is not set
-# CONFIG_TOSHIBA_JMR3927 is not set
-# CONFIG_TOSHIBA_RBTX4927 is not set
-# CONFIG_VICTOR_MPC30X is not set
-# CONFIG_ZAO_CAPCELLA is not set
-CONFIG_RWSEM_GENERIC_SPINLOCK=y
-CONFIG_NONCOHERENT_IO=y
-CONFIG_CPU_LITTLE_ENDIAN=y
-CONFIG_IRQ_CPU=y
-CONFIG_NEW_PCI=y
-# CONFIG_FB is not set
-
-#
-# CPU selection
-#
-# CONFIG_CPU_MIPS32 is not set
-# CONFIG_CPU_MIPS64 is not set
-# CONFIG_CPU_R3000 is not set
-# CONFIG_CPU_TX39XX is not set
-# CONFIG_CPU_VR41XX is not set
-# CONFIG_CPU_R4300 is not set
-# CONFIG_CPU_R4X00 is not set
-# CONFIG_CPU_TX49XX is not set
-CONFIG_CPU_R5000=y
-# CONFIG_CPU_R5432 is not set
-# CONFIG_CPU_R6000 is not set
-# CONFIG_CPU_NEVADA is not set
-# CONFIG_CPU_R8000 is not set
-# CONFIG_CPU_R10000 is not set
-# CONFIG_CPU_RM7000 is not set
-# CONFIG_CPU_SB1 is not set
-# CONFIG_64BIT_PHYS_ADDR is not set
-# CONFIG_CPU_ADVANCED is not set
-CONFIG_CPU_HAS_LLSC=y
-CONFIG_CPU_HAS_LLDSCD=y
-CONFIG_CPU_HAS_SYNC=y
-# CONFIG_PREEMPT is not set
-# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
-
-#
-# Bus options (PCI, PCMCIA, EISA, ISA, TC)
-#
-# CONFIG_PCI is not set
-CONFIG_MMU=y
-# CONFIG_HOTPLUG is not set
-
-#
-# Executable file formats
-#
-CONFIG_KCORE_ELF=y
-CONFIG_BINFMT_ELF=y
-# CONFIG_BINFMT_MISC is not set
-CONFIG_TRAD_SIGNALS=y
-
-#
-# Memory Technology Devices (MTD)
-#
-CONFIG_MTD=y
-CONFIG_MTD_DEBUG=y
-CONFIG_MTD_DEBUG_VERBOSE=3
-CONFIG_MTD_PARTITIONS=y
-# CONFIG_MTD_CONCAT is not set
-# CONFIG_MTD_REDBOOT_PARTS is not set
-# CONFIG_MTD_CMDLINE_PARTS is not set
-
-#
-# User Modules And Translation Layers
-#
-CONFIG_MTD_CHAR=y
-CONFIG_MTD_BLOCK=y
-# CONFIG_FTL is not set
-# CONFIG_NFTL is not set
-# CONFIG_INFTL is not set
-
-#
-# RAM/ROM/Flash chip drivers
-#
-CONFIG_MTD_CFI=y
-CONFIG_MTD_JEDECPROBE=y
-CONFIG_MTD_GEN_PROBE=y
-# CONFIG_MTD_CFI_ADV_OPTIONS is not set
-CONFIG_MTD_CFI_INTELEXT=y
-CONFIG_MTD_CFI_AMDSTD=y
-# CONFIG_MTD_CFI_STAA is not set
-# CONFIG_MTD_RAM is not set
-# CONFIG_MTD_ROM is not set
-# CONFIG_MTD_ABSENT is not set
-# CONFIG_MTD_OBSOLETE_CHIPS is not set
-
-#
-# Mapping drivers for chip access
-#
-# CONFIG_MTD_COMPLEX_MAPPINGS is not set
-CONFIG_MTD_PHYSMAP=y
-CONFIG_MTD_PHYSMAP_START=0x10040000
-CONFIG_MTD_PHYSMAP_LEN=0x00fc0000
-CONFIG_MTD_PHYSMAP_BUSWIDTH=4
-# CONFIG_MTD_CSTM_MIPS_IXX is not set
-
-#
-# Self-contained MTD device drivers
-#
-# CONFIG_MTD_SLRAM is not set
-# CONFIG_MTD_MTDRAM is not set
-# CONFIG_MTD_BLKMTD is not set
-
-#
-# Disk-On-Chip Device Drivers
-#
-# CONFIG_MTD_DOC2000 is not set
-# CONFIG_MTD_DOC2001 is not set
-# CONFIG_MTD_DOC2001PLUS is not set
-
-#
-# NAND Flash Device Drivers
-#
-CONFIG_MTD_NAND=y
-# CONFIG_MTD_NAND_VERIFY_WRITE is not set
-CONFIG_MTD_NAND_IDS=y
-
-#
-# Parallel port support
-#
-# CONFIG_PARPORT is not set
-
-#
-# Plug and Play support
-#
-# CONFIG_PNP is not set
-
-#
-# Generic Driver Options
-#
-# CONFIG_FW_LOADER is not set
-
-#
-# Block devices
-#
-# CONFIG_BLK_DEV_FD is not set
-# CONFIG_BLK_DEV_LOOP is not set
-# CONFIG_BLK_DEV_NBD is not set
-# CONFIG_BLK_DEV_RAM is not set
-# CONFIG_BLK_DEV_INITRD is not set
-# CONFIG_LBD is not set
-
-#
-# ATA/ATAPI/MFM/RLL support
-#
-CONFIG_IDE=y
-
-#
-# IDE, ATA and ATAPI Block devices
-#
-CONFIG_BLK_DEV_IDE=y
-
-#
-# Please see Documentation/ide.txt for help/info on IDE drives
-#
-# CONFIG_BLK_DEV_HD is not set
-CONFIG_BLK_DEV_IDEDISK=y
-# CONFIG_IDEDISK_MULTI_MODE is not set
-# CONFIG_IDEDISK_STROKE is not set
-# CONFIG_BLK_DEV_IDECD is not set
-# CONFIG_BLK_DEV_IDEFLOPPY is not set
-# CONFIG_IDE_TASK_IOCTL is not set
-CONFIG_IDE_TASKFILE_IO=y
-
-#
-# IDE chipset support/bugfixes
-#
-
-#
-# SCSI device support
-#
-# CONFIG_SCSI is not set
-
-#
-# Multi-device support (RAID and LVM)
-#
-# CONFIG_MD is not set
-
-#
-# Fusion MPT device support
-#
-
-#
-# I2O device support
-#
-
-#
-# Networking support
-#
-CONFIG_NET=y
-
-#
-# Networking options
-#
-CONFIG_PACKET=y
-# CONFIG_PACKET_MMAP is not set
-CONFIG_NETLINK_DEV=y
-# CONFIG_NETFILTER is not set
-CONFIG_UNIX=y
-CONFIG_NET_KEY=y
-CONFIG_INET=y
-# CONFIG_IP_MULTICAST is not set
-# CONFIG_IP_ADVANCED_ROUTER is not set
-CONFIG_IP_PNP=y
-CONFIG_IP_PNP_DHCP=y
-# CONFIG_IP_PNP_BOOTP is not set
-# CONFIG_IP_PNP_RARP is not set
-# CONFIG_NET_IPIP is not set
-# CONFIG_NET_IPGRE is not set
-# CONFIG_ARPD is not set
-# CONFIG_INET_ECN is not set
-# CONFIG_SYN_COOKIES is not set
-# CONFIG_INET_AH is not set
-# CONFIG_INET_ESP is not set
-# CONFIG_INET_IPCOMP is not set
-# CONFIG_IPV6 is not set
-# CONFIG_XFRM_USER is not set
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
-CONFIG_IPV6_SCTP__=y
-# CONFIG_IP_SCTP is not set
-# CONFIG_ATM is not set
-# CONFIG_VLAN_8021Q is not set
-# CONFIG_LLC is not set
-# CONFIG_DECNET is not set
-# CONFIG_BRIDGE is not set
-# CONFIG_X25 is not set
-# CONFIG_LAPB is not set
-# CONFIG_NET_DIVERT is not set
-# CONFIG_ECONET is not set
-# CONFIG_WAN_ROUTER is not set
-# CONFIG_NET_FASTROUTE is not set
-# CONFIG_NET_HW_FLOWCONTROL is not set
-
-#
-# QoS and/or fair queueing
-#
-# CONFIG_NET_SCHED is not set
-
-#
-# Network testing
-#
-# CONFIG_NET_PKTGEN is not set
-CONFIG_NETDEVICES=y
-# CONFIG_DUMMY is not set
-# CONFIG_BONDING is not set
-# CONFIG_EQUALIZER is not set
-# CONFIG_TUN is not set
-# CONFIG_ETHERTAP is not set
-
-#
-# Ethernet (10 or 100Mbit)
-#
-CONFIG_NET_ETHERNET=y
-# CONFIG_MII is not set
-
-#
-# Ethernet (1000 Mbit)
-#
-
-#
-# Ethernet (10000 Mbit)
-#
-# CONFIG_PPP is not set
-# CONFIG_SLIP is not set
-
-#
-# Wireless LAN (non-hamradio)
-#
-CONFIG_NET_RADIO=y
-
-#
-# Obsolete Wireless cards support (pre-802.11)
-#
-# CONFIG_STRIP is not set
-
-#
-# Token Ring devices (depends on LLC=y)
-#
-# CONFIG_SHAPER is not set
-
-#
-# Wan interfaces
-#
-# CONFIG_WAN is not set
-
-#
-# Amateur Radio support
-#
-# CONFIG_HAMRADIO is not set
-
-#
-# IrDA (infrared) support
-#
-# CONFIG_IRDA is not set
-
-#
-# ISDN subsystem
-#
-# CONFIG_ISDN_BOOL is not set
-
-#
-# Telephony Support
-#
-# CONFIG_PHONE is not set
-
-#
-# Input device support
-#
-CONFIG_INPUT=y
-
-#
-# Userland interfaces
-#
-# CONFIG_INPUT_MOUSEDEV is not set
-# CONFIG_INPUT_JOYDEV is not set
-# CONFIG_INPUT_TSDEV is not set
-# CONFIG_INPUT_EVDEV is not set
-# CONFIG_INPUT_EVBUG is not set
-
-#
-# Input I/O drivers
-#
-# CONFIG_GAMEPORT is not set
-CONFIG_SOUND_GAMEPORT=y
-CONFIG_SERIO=y
-# CONFIG_SERIO_I8042 is not set
-CONFIG_SERIO_SERPORT=y
-# CONFIG_SERIO_CT82C710 is not set
-
-#
-# Input Device Drivers
-#
-# CONFIG_INPUT_KEYBOARD is not set
-# CONFIG_INPUT_MOUSE is not set
-# CONFIG_INPUT_JOYSTICK is not set
-# CONFIG_INPUT_TOUCHSCREEN is not set
-# CONFIG_INPUT_MISC is not set
-
-#
-# Character devices
-#
-# CONFIG_VT is not set
-# CONFIG_SERIAL_NONSTANDARD is not set
-
-#
-# Serial drivers
-#
-CONFIG_SERIAL_8250=y
-CONFIG_SERIAL_8250_CONSOLE=y
-# CONFIG_SERIAL_8250_EXTENDED is not set
-
-#
-# Non-8250 serial port support
-#
-CONFIG_SERIAL_CORE=y
-CONFIG_SERIAL_CORE_CONSOLE=y
-# CONFIG_UNIX98_PTYS is not set
-
-#
-# I2C support
-#
-# CONFIG_I2C is not set
-
-#
-# I2C Hardware Sensors Mainboard support
-#
-
-#
-# I2C Hardware Sensors Chip support
-#
-# CONFIG_I2C_SENSOR is not set
-
-#
-# Mice
-#
-# CONFIG_BUSMOUSE is not set
-# CONFIG_QIC02_TAPE is not set
-
-#
-# IPMI
-#
-# CONFIG_IPMI_HANDLER is not set
-
-#
-# Watchdog Cards
-#
-# CONFIG_WATCHDOG is not set
-# CONFIG_NVRAM is not set
-# CONFIG_RTC is not set
-# CONFIG_GEN_RTC is not set
-# CONFIG_DTLK is not set
-# CONFIG_R3964 is not set
-# CONFIG_APPLICOM is not set
-
-#
-# Ftape, the floppy tape device driver
-#
-# CONFIG_FTAPE is not set
-# CONFIG_AGP is not set
-# CONFIG_DRM is not set
-# CONFIG_RAW_DRIVER is not set
-# CONFIG_HANGCHECK_TIMER is not set
-
-#
-# Multimedia devices
-#
-# CONFIG_VIDEO_DEV is not set
-
-#
-# Digital Video Broadcasting Devices
-#
-# CONFIG_DVB is not set
-
-#
-# File systems
-#
-CONFIG_EXT2_FS=y
-# CONFIG_EXT2_FS_XATTR is not set
-# CONFIG_EXT3_FS is not set
-# CONFIG_JBD is not set
-# CONFIG_REISERFS_FS is not set
-# CONFIG_JFS_FS is not set
-# CONFIG_XFS_FS is not set
-# CONFIG_MINIX_FS is not set
-# CONFIG_ROMFS_FS is not set
-# CONFIG_QUOTA is not set
-# CONFIG_AUTOFS_FS is not set
-# CONFIG_AUTOFS4_FS is not set
-
-#
-# CD-ROM/DVD Filesystems
-#
-# CONFIG_ISO9660_FS is not set
-# CONFIG_UDF_FS is not set
-
-#
-# DOS/FAT/NT Filesystems
-#
-# CONFIG_FAT_FS is not set
-# CONFIG_NTFS_FS is not set
-
-#
-# Pseudo filesystems
-#
-CONFIG_PROC_FS=y
-# CONFIG_DEVFS_FS is not set
-# CONFIG_TMPFS is not set
-CONFIG_RAMFS=y
-
-#
-# Miscellaneous filesystems
-#
-# CONFIG_ADFS_FS is not set
-# CONFIG_AFFS_FS is not set
-# CONFIG_HFS_FS is not set
-# CONFIG_BEFS_FS is not set
-# CONFIG_BFS_FS is not set
-# CONFIG_EFS_FS is not set
-# CONFIG_JFFS_FS is not set
-CONFIG_JFFS2_FS=y
-CONFIG_JFFS2_FS_DEBUG=3
-# CONFIG_JFFS2_FS_NAND is not set
-# CONFIG_CRAMFS is not set
-# CONFIG_VXFS_FS is not set
-# CONFIG_HPFS_FS is not set
-# CONFIG_QNX4FS_FS is not set
-# CONFIG_SYSV_FS is not set
-# CONFIG_UFS_FS is not set
-
-#
-# Network File Systems
-#
-CONFIG_NFS_FS=y
-CONFIG_NFS_V3=y
-# CONFIG_NFS_V4 is not set
-# CONFIG_NFSD is not set
-CONFIG_ROOT_NFS=y
-CONFIG_LOCKD=y
-CONFIG_LOCKD_V4=y
-# CONFIG_EXPORTFS is not set
-CONFIG_SUNRPC=y
-# CONFIG_SUNRPC_GSS is not set
-# CONFIG_SMB_FS is not set
-# CONFIG_CIFS is not set
-# CONFIG_NCP_FS is not set
-# CONFIG_CODA_FS is not set
-# CONFIG_INTERMEZZO_FS is not set
-# CONFIG_AFS_FS is not set
-
-#
-# Partition Types
-#
-# CONFIG_PARTITION_ADVANCED is not set
-CONFIG_MSDOS_PARTITION=y
-
-#
-# Graphics support
-#
-
-#
-# Sound
-#
-# CONFIG_SOUND is not set
-
-#
-# USB support
-#
-# CONFIG_USB_GADGET is not set
-
-#
-# Bluetooth support
-#
-# CONFIG_BT is not set
-
-#
-# Kernel hacking
-#
-CONFIG_CROSSCOMPILE=y
-# CONFIG_DEBUG_KERNEL is not set
-
-#
-# Security options
-#
-# CONFIG_SECURITY is not set
-
-#
-# Cryptographic options
-#
-# CONFIG_CRYPTO is not set
-
-#
-# Library routines
-#
-# CONFIG_CRC32 is not set
-CONFIG_ZLIB_INFLATE=y
-CONFIG_ZLIB_DEFLATE=y
--- diff/arch/mips/defconfig-ip22	2003-08-20 14:16:25.000000000 +0100
+++ source/arch/mips/defconfig-ip22	1970-01-01 01:00:00.000000000 +0100
@@ -1,650 +0,0 @@
-#
-# Automatically generated make config: don't edit
-#
-CONFIG_MIPS=y
-# CONFIG_MIPS64 is not set
-CONFIG_MIPS32=y
-
-#
-# Code maturity level options
-#
-CONFIG_EXPERIMENTAL=y
-
-#
-# General setup
-#
-CONFIG_SWAP=y
-CONFIG_SYSVIPC=y
-# CONFIG_BSD_PROCESS_ACCT is not set
-CONFIG_SYSCTL=y
-CONFIG_LOG_BUF_SHIFT=14
-# CONFIG_EMBEDDED is not set
-CONFIG_KALLSYMS=y
-CONFIG_FUTEX=y
-CONFIG_EPOLL=y
-CONFIG_IOSCHED_AS=y
-CONFIG_IOSCHED_DEADLINE=y
-
-#
-# Loadable module support
-#
-CONFIG_MODULES=y
-CONFIG_MODULE_UNLOAD=y
-# CONFIG_MODULE_FORCE_UNLOAD is not set
-CONFIG_OBSOLETE_MODPARM=y
-CONFIG_MODVERSIONS=y
-CONFIG_KMOD=y
-
-#
-# Machine selection
-#
-# CONFIG_ACER_PICA_61 is not set
-# CONFIG_BAGET_MIPS is not set
-# CONFIG_CASIO_E55 is not set
-# CONFIG_MIPS_COBALT is not set
-# CONFIG_DECSTATION is not set
-# CONFIG_MIPS_EV64120 is not set
-# CONFIG_MIPS_EV96100 is not set
-# CONFIG_MIPS_IVR is not set
-# CONFIG_LASAT is not set
-# CONFIG_HP_LASERJET is not set
-# CONFIG_IBM_WORKPAD is not set
-# CONFIG_MIPS_ITE8172 is not set
-# CONFIG_MIPS_ATLAS is not set
-# CONFIG_MIPS_MAGNUM_4000 is not set
-# CONFIG_MIPS_MALTA is not set
-# CONFIG_MIPS_SEAD is not set
-# CONFIG_MOMENCO_OCELOT is not set
-# CONFIG_MOMENCO_OCELOT_G is not set
-# CONFIG_MOMENCO_OCELOT_C is not set
-# CONFIG_DDB5074 is not set
-# CONFIG_DDB5476 is not set
-# CONFIG_DDB5477 is not set
-# CONFIG_NEC_OSPREY is not set
-# CONFIG_NEC_EAGLE is not set
-# CONFIG_OLIVETTI_M700 is not set
-CONFIG_SGI_IP22=y
-# CONFIG_SGI_IP32 is not set
-# CONFIG_SOC_AU1X00 is not set
-# CONFIG_SIBYTE_SB1xxx_SOC is not set
-# CONFIG_SNI_RM200_PCI is not set
-# CONFIG_TANBAC_TB0226 is not set
-# CONFIG_TANBAC_TB0229 is not set
-# CONFIG_TOSHIBA_JMR3927 is not set
-# CONFIG_TOSHIBA_RBTX4927 is not set
-# CONFIG_VICTOR_MPC30X is not set
-# CONFIG_ZAO_CAPCELLA is not set
-CONFIG_RWSEM_GENERIC_SPINLOCK=y
-CONFIG_ARC=y
-CONFIG_GENERIC_ISA_DMA=y
-CONFIG_NONCOHERENT_IO=y
-# CONFIG_CPU_LITTLE_ENDIAN is not set
-CONFIG_IRQ_CPU=y
-CONFIG_SWAP_IO_SPACE=y
-CONFIG_BOOT_ELF32=y
-CONFIG_L1_CACHE_SHIFT=5
-CONFIG_ARC32=y
-# CONFIG_FB is not set
-CONFIG_ARC_CONSOLE=y
-CONFIG_ARC_PROMLIB=y
-CONFIG_BOARD_SCACHE=y
-
-#
-# CPU selection
-#
-# CONFIG_CPU_MIPS32 is not set
-# CONFIG_CPU_MIPS64 is not set
-# CONFIG_CPU_R3000 is not set
-# CONFIG_CPU_TX39XX is not set
-# CONFIG_CPU_VR41XX is not set
-# CONFIG_CPU_R4300 is not set
-# CONFIG_CPU_R4X00 is not set
-# CONFIG_CPU_TX49XX is not set
-CONFIG_CPU_R5000=y
-# CONFIG_CPU_R5432 is not set
-# CONFIG_CPU_R6000 is not set
-# CONFIG_CPU_NEVADA is not set
-# CONFIG_CPU_R8000 is not set
-# CONFIG_CPU_R10000 is not set
-# CONFIG_CPU_RM7000 is not set
-# CONFIG_CPU_SB1 is not set
-CONFIG_R5000_CPU_SCACHE=y
-# CONFIG_64BIT_PHYS_ADDR is not set
-# CONFIG_CPU_ADVANCED is not set
-CONFIG_CPU_HAS_LLSC=y
-CONFIG_CPU_HAS_LLDSCD=y
-CONFIG_CPU_HAS_SYNC=y
-# CONFIG_PREEMPT is not set
-# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
-
-#
-# Bus options (PCI, PCMCIA, EISA, ISA, TC)
-#
-# CONFIG_ISA is not set
-CONFIG_MMU=y
-# CONFIG_HOTPLUG is not set
-
-#
-# Executable file formats
-#
-CONFIG_KCORE_ELF=y
-CONFIG_BINFMT_ELF=y
-# CONFIG_BINFMT_MISC is not set
-CONFIG_TRAD_SIGNALS=y
-CONFIG_BINFMT_IRIX=y
-
-#
-# Memory Technology Devices (MTD)
-#
-# CONFIG_MTD is not set
-
-#
-# Parallel port support
-#
-# CONFIG_PARPORT is not set
-
-#
-# Plug and Play support
-#
-# CONFIG_PNP is not set
-
-#
-# Generic Driver Options
-#
-# CONFIG_FW_LOADER is not set
-
-#
-# Block devices
-#
-# CONFIG_BLK_DEV_FD is not set
-# CONFIG_BLK_DEV_LOOP is not set
-# CONFIG_BLK_DEV_NBD is not set
-# CONFIG_BLK_DEV_RAM is not set
-# CONFIG_BLK_DEV_INITRD is not set
-# CONFIG_LBD is not set
-
-#
-# ATA/ATAPI/MFM/RLL support
-#
-# CONFIG_IDE is not set
-
-#
-# SCSI device support
-#
-CONFIG_SCSI=y
-
-#
-# SCSI support type (disk, tape, CD-ROM)
-#
-CONFIG_BLK_DEV_SD=y
-CONFIG_CHR_DEV_ST=y
-# CONFIG_CHR_DEV_OSST is not set
-CONFIG_BLK_DEV_SR=y
-# CONFIG_BLK_DEV_SR_VENDOR is not set
-# CONFIG_CHR_DEV_SG is not set
-
-#
-# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
-#
-# CONFIG_SCSI_MULTI_LUN is not set
-# CONFIG_SCSI_REPORT_LUNS is not set
-CONFIG_SCSI_CONSTANTS=y
-# CONFIG_SCSI_LOGGING is not set
-
-#
-# SCSI low-level drivers
-#
-CONFIG_SGIWD93_SCSI=y
-# CONFIG_SCSI_AIC7XXX is not set
-# CONFIG_SCSI_AIC7XXX_OLD is not set
-# CONFIG_SCSI_DPT_I2O is not set
-# CONFIG_SCSI_EATA_PIO is not set
-# CONFIG_SCSI_DEBUG is not set
-
-#
-# Multi-device support (RAID and LVM)
-#
-# CONFIG_MD is not set
-
-#
-# Fusion MPT device support
-#
-# CONFIG_FUSION is not set
-
-#
-# I2O device support
-#
-
-#
-# Networking support
-#
-CONFIG_NET=y
-
-#
-# Networking options
-#
-CONFIG_PACKET=y
-CONFIG_PACKET_MMAP=y
-CONFIG_NETLINK_DEV=y
-# CONFIG_NETFILTER is not set
-CONFIG_UNIX=y
-CONFIG_NET_KEY=y
-CONFIG_INET=y
-CONFIG_IP_MULTICAST=y
-# CONFIG_IP_ADVANCED_ROUTER is not set
-CONFIG_IP_PNP=y
-# CONFIG_IP_PNP_DHCP is not set
-CONFIG_IP_PNP_BOOTP=y
-# CONFIG_IP_PNP_RARP is not set
-# CONFIG_NET_IPIP is not set
-# CONFIG_NET_IPGRE is not set
-# CONFIG_IP_MROUTE is not set
-# CONFIG_ARPD is not set
-# CONFIG_INET_ECN is not set
-# CONFIG_SYN_COOKIES is not set
-# CONFIG_INET_AH is not set
-# CONFIG_INET_ESP is not set
-# CONFIG_INET_IPCOMP is not set
-# CONFIG_IPV6 is not set
-# CONFIG_XFRM_USER is not set
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
-CONFIG_IPV6_SCTP__=y
-# CONFIG_IP_SCTP is not set
-# CONFIG_ATM is not set
-# CONFIG_VLAN_8021Q is not set
-# CONFIG_LLC is not set
-# CONFIG_DECNET is not set
-# CONFIG_BRIDGE is not set
-# CONFIG_X25 is not set
-# CONFIG_LAPB is not set
-# CONFIG_NET_DIVERT is not set
-# CONFIG_ECONET is not set
-# CONFIG_WAN_ROUTER is not set
-# CONFIG_NET_FASTROUTE is not set
-# CONFIG_NET_HW_FLOWCONTROL is not set
-
-#
-# QoS and/or fair queueing
-#
-# CONFIG_NET_SCHED is not set
-
-#
-# Network testing
-#
-# CONFIG_NET_PKTGEN is not set
-CONFIG_NETDEVICES=y
-# CONFIG_DUMMY is not set
-# CONFIG_BONDING is not set
-# CONFIG_EQUALIZER is not set
-# CONFIG_TUN is not set
-# CONFIG_ETHERTAP is not set
-
-#
-# Ethernet (10 or 100Mbit)
-#
-CONFIG_NET_ETHERNET=y
-# CONFIG_MII is not set
-CONFIG_SGISEEQ=y
-
-#
-# Ethernet (1000 Mbit)
-#
-
-#
-# Ethernet (10000 Mbit)
-#
-# CONFIG_PPP is not set
-# CONFIG_SLIP is not set
-
-#
-# Wireless LAN (non-hamradio)
-#
-# CONFIG_NET_RADIO is not set
-
-#
-# Token Ring devices (depends on LLC=y)
-#
-# CONFIG_SHAPER is not set
-
-#
-# Wan interfaces
-#
-# CONFIG_WAN is not set
-
-#
-# Amateur Radio support
-#
-# CONFIG_HAMRADIO is not set
-
-#
-# IrDA (infrared) support
-#
-# CONFIG_IRDA is not set
-
-#
-# ISDN subsystem
-#
-# CONFIG_ISDN_BOOL is not set
-
-#
-# Telephony Support
-#
-# CONFIG_PHONE is not set
-
-#
-# Input device support
-#
-CONFIG_INPUT=y
-
-#
-# Userland interfaces
-#
-# CONFIG_INPUT_MOUSEDEV is not set
-# CONFIG_INPUT_JOYDEV is not set
-# CONFIG_INPUT_TSDEV is not set
-# CONFIG_INPUT_EVDEV is not set
-# CONFIG_INPUT_EVBUG is not set
-
-#
-# Input I/O drivers
-#
-# CONFIG_GAMEPORT is not set
-CONFIG_SOUND_GAMEPORT=y
-CONFIG_SERIO=y
-CONFIG_SERIO_I8042=y
-CONFIG_SERIO_SERPORT=y
-# CONFIG_SERIO_CT82C710 is not set
-
-#
-# Input Device Drivers
-#
-CONFIG_INPUT_KEYBOARD=y
-CONFIG_KEYBOARD_ATKBD=y
-# CONFIG_KEYBOARD_SUNKBD is not set
-# CONFIG_KEYBOARD_XTKBD is not set
-# CONFIG_KEYBOARD_NEWTON is not set
-# CONFIG_INPUT_MOUSE is not set
-# CONFIG_INPUT_JOYSTICK is not set
-# CONFIG_INPUT_TOUCHSCREEN is not set
-# CONFIG_INPUT_MISC is not set
-
-#
-# Character devices
-#
-CONFIG_VT=y
-CONFIG_VT_CONSOLE=y
-CONFIG_HW_CONSOLE=y
-# CONFIG_SERIAL_NONSTANDARD is not set
-
-#
-# Serial drivers
-#
-# CONFIG_SERIAL_8250 is not set
-
-#
-# Non-8250 serial port support
-#
-CONFIG_SERIAL_IP22_ZILOG=y
-CONFIG_SERIAL_CORE=y
-CONFIG_SERIAL_CORE_CONSOLE=y
-CONFIG_UNIX98_PTYS=y
-CONFIG_UNIX98_PTY_COUNT=256
-
-#
-# I2C support
-#
-# CONFIG_I2C is not set
-
-#
-# I2C Hardware Sensors Mainboard support
-#
-
-#
-# I2C Hardware Sensors Chip support
-#
-# CONFIG_I2C_SENSOR is not set
-
-#
-# Mice
-#
-# CONFIG_BUSMOUSE is not set
-# CONFIG_QIC02_TAPE is not set
-
-#
-# IPMI
-#
-# CONFIG_IPMI_HANDLER is not set
-
-#
-# Watchdog Cards
-#
-CONFIG_WATCHDOG=y
-# CONFIG_WATCHDOG_NOWAYOUT is not set
-# CONFIG_SOFT_WATCHDOG is not set
-# CONFIG_WDT is not set
-# CONFIG_WDTPCI is not set
-# CONFIG_PCWATCHDOG is not set
-# CONFIG_ACQUIRE_WDT is not set
-# CONFIG_ADVANTECH_WDT is not set
-# CONFIG_EUROTECH_WDT is not set
-# CONFIG_IB700_WDT is not set
-# CONFIG_I810_TCO is not set
-# CONFIG_MIXCOMWD is not set
-# CONFIG_SCx200_WDT is not set
-# CONFIG_60XX_WDT is not set
-# CONFIG_W83877F_WDT is not set
-# CONFIG_MACHZ_WDT is not set
-CONFIG_INDYDOG=y
-# CONFIG_SC520_WDT is not set
-# CONFIG_AMD7XX_TCO is not set
-# CONFIG_ALIM7101_WDT is not set
-# CONFIG_SC1200_WDT is not set
-# CONFIG_WAFER_WDT is not set
-# CONFIG_CPU5_WDT is not set
-# CONFIG_NVRAM is not set
-# CONFIG_RTC is not set
-# CONFIG_GEN_RTC is not set
-CONFIG_SGI_DS1286=y
-# CONFIG_DTLK is not set
-# CONFIG_R3964 is not set
-# CONFIG_APPLICOM is not set
-
-#
-# Ftape, the floppy tape device driver
-#
-# CONFIG_FTAPE is not set
-# CONFIG_AGP is not set
-# CONFIG_DRM is not set
-# CONFIG_RAW_DRIVER is not set
-# CONFIG_HANGCHECK_TIMER is not set
-
-#
-# Multimedia devices
-#
-# CONFIG_VIDEO_DEV is not set
-
-#
-# Digital Video Broadcasting Devices
-#
-# CONFIG_DVB is not set
-
-#
-# File systems
-#
-# CONFIG_EXT2_FS is not set
-CONFIG_EXT3_FS=y
-CONFIG_EXT3_FS_XATTR=y
-CONFIG_EXT3_FS_POSIX_ACL=y
-CONFIG_EXT3_FS_SECURITY=y
-CONFIG_JBD=y
-# CONFIG_JBD_DEBUG is not set
-CONFIG_FS_MBCACHE=y
-# CONFIG_REISERFS_FS is not set
-# CONFIG_JFS_FS is not set
-CONFIG_FS_POSIX_ACL=y
-# CONFIG_XFS_FS is not set
-# CONFIG_MINIX_FS is not set
-# CONFIG_ROMFS_FS is not set
-# CONFIG_QUOTA is not set
-CONFIG_AUTOFS_FS=y
-CONFIG_AUTOFS4_FS=y
-
-#
-# CD-ROM/DVD Filesystems
-#
-CONFIG_ISO9660_FS=y
-# CONFIG_JOLIET is not set
-# CONFIG_ZISOFS is not set
-# CONFIG_UDF_FS is not set
-
-#
-# DOS/FAT/NT Filesystems
-#
-# CONFIG_FAT_FS is not set
-# CONFIG_NTFS_FS is not set
-
-#
-# Pseudo filesystems
-#
-CONFIG_PROC_FS=y
-# CONFIG_DEVFS_FS is not set
-CONFIG_DEVPTS_FS=y
-CONFIG_DEVPTS_FS_XATTR=y
-CONFIG_DEVPTS_FS_SECURITY=y
-# CONFIG_TMPFS is not set
-CONFIG_RAMFS=y
-
-#
-# Miscellaneous filesystems
-#
-# CONFIG_ADFS_FS is not set
-# CONFIG_AFFS_FS is not set
-# CONFIG_HFS_FS is not set
-# CONFIG_BEFS_FS is not set
-# CONFIG_BFS_FS is not set
-# CONFIG_EFS_FS is not set
-# CONFIG_CRAMFS is not set
-# CONFIG_VXFS_FS is not set
-# CONFIG_HPFS_FS is not set
-# CONFIG_QNX4FS_FS is not set
-# CONFIG_SYSV_FS is not set
-# CONFIG_UFS_FS is not set
-
-#
-# Network File Systems
-#
-CONFIG_NFS_FS=y
-# CONFIG_NFS_V3 is not set
-# CONFIG_NFS_V4 is not set
-CONFIG_NFSD=y
-# CONFIG_NFSD_V3 is not set
-# CONFIG_NFSD_TCP is not set
-CONFIG_ROOT_NFS=y
-CONFIG_LOCKD=y
-CONFIG_EXPORTFS=y
-CONFIG_SUNRPC=y
-# CONFIG_SUNRPC_GSS is not set
-# CONFIG_SMB_FS is not set
-# CONFIG_CIFS is not set
-# CONFIG_NCP_FS is not set
-# CONFIG_CODA_FS is not set
-# CONFIG_INTERMEZZO_FS is not set
-# CONFIG_AFS_FS is not set
-
-#
-# Partition Types
-#
-CONFIG_PARTITION_ADVANCED=y
-# CONFIG_ACORN_PARTITION is not set
-# CONFIG_OSF_PARTITION is not set
-# CONFIG_AMIGA_PARTITION is not set
-# CONFIG_ATARI_PARTITION is not set
-# CONFIG_MAC_PARTITION is not set
-CONFIG_MSDOS_PARTITION=y
-# CONFIG_BSD_DISKLABEL is not set
-# CONFIG_MINIX_SUBPARTITION is not set
-# CONFIG_SOLARIS_X86_PARTITION is not set
-# CONFIG_UNIXWARE_DISKLABEL is not set
-# CONFIG_LDM_PARTITION is not set
-# CONFIG_NEC98_PARTITION is not set
-CONFIG_SGI_PARTITION=y
-# CONFIG_ULTRIX_PARTITION is not set
-# CONFIG_SUN_PARTITION is not set
-# CONFIG_EFI_PARTITION is not set
-
-#
-# Graphics support
-#
-
-#
-# Console display driver support
-#
-# CONFIG_VGA_CONSOLE is not set
-# CONFIG_MDA_CONSOLE is not set
-CONFIG_SGI_NEWPORT_CONSOLE=y
-CONFIG_DUMMY_CONSOLE=y
-CONFIG_FONT_8x16=y
-
-#
-# Logo configuration
-#
-CONFIG_LOGO=y
-# CONFIG_LOGO_LINUX_MONO is not set
-# CONFIG_LOGO_LINUX_VGA16 is not set
-# CONFIG_LOGO_LINUX_CLUT224 is not set
-CONFIG_LOGO_SGI_CLUT224=y
-
-#
-# Sound
-#
-# CONFIG_SOUND is not set
-
-#
-# USB support
-#
-# CONFIG_USB_GADGET is not set
-
-#
-# Bluetooth support
-#
-# CONFIG_BT is not set
-
-#
-# Kernel hacking
-#
-CONFIG_CROSSCOMPILE=y
-# CONFIG_DEBUG_KERNEL is not set
-
-#
-# Security options
-#
-# CONFIG_SECURITY is not set
-
-#
-# Cryptographic options
-#
-CONFIG_CRYPTO=y
-CONFIG_CRYPTO_HMAC=y
-CONFIG_CRYPTO_NULL=y
-CONFIG_CRYPTO_MD4=y
-CONFIG_CRYPTO_MD5=y
-CONFIG_CRYPTO_SHA1=y
-CONFIG_CRYPTO_SHA256=y
-CONFIG_CRYPTO_SHA512=y
-CONFIG_CRYPTO_DES=y
-CONFIG_CRYPTO_BLOWFISH=y
-CONFIG_CRYPTO_TWOFISH=y
-CONFIG_CRYPTO_SERPENT=y
-CONFIG_CRYPTO_AES=y
-CONFIG_CRYPTO_DEFLATE=y
-# CONFIG_CRYPTO_TEST is not set
-
-#
-# Library routines
-#
-# CONFIG_CRC32 is not set
-CONFIG_ZLIB_INFLATE=y
-CONFIG_ZLIB_DEFLATE=y
--- diff/arch/mips/defconfig-ip27	2003-08-20 14:16:36.000000000 +0100
+++ source/arch/mips/defconfig-ip27	1970-01-01 01:00:00.000000000 +0100
@@ -1,652 +0,0 @@
-#
-# Automatically generated make config: don't edit
-#
-CONFIG_MIPS=y
-CONFIG_MIPS64=y
-
-#
-# Code maturity level options
-#
-CONFIG_EXPERIMENTAL=y
-
-#
-# General setup
-#
-CONFIG_SWAP=y
-CONFIG_SYSVIPC=y
-# CONFIG_BSD_PROCESS_ACCT is not set
-CONFIG_SYSCTL=y
-CONFIG_LOG_BUF_SHIFT=15
-# CONFIG_EMBEDDED is not set
-CONFIG_KALLSYMS=y
-CONFIG_FUTEX=y
-CONFIG_EPOLL=y
-CONFIG_IOSCHED_AS=y
-CONFIG_IOSCHED_DEADLINE=y
-
-#
-# Loadable module support
-#
-# CONFIG_MODULES is not set
-
-#
-# Machine selection
-#
-# CONFIG_ACER_PICA_61 is not set
-# CONFIG_CASIO_E55 is not set
-# CONFIG_MIPS_COBALT is not set
-# CONFIG_DECSTATION is not set
-# CONFIG_MIPS_EV64120 is not set
-# CONFIG_MIPS_EV96100 is not set
-# CONFIG_MIPS_IVR is not set
-# CONFIG_LASAT is not set
-# CONFIG_HP_LASERJET is not set
-# CONFIG_IBM_WORKPAD is not set
-# CONFIG_MIPS_ITE8172 is not set
-# CONFIG_MIPS_ATLAS is not set
-# CONFIG_MIPS_MAGNUM_4000 is not set
-# CONFIG_MIPS_MALTA is not set
-# CONFIG_MIPS_SEAD is not set
-# CONFIG_MOMENCO_OCELOT is not set
-# CONFIG_MOMENCO_OCELOT_G is not set
-# CONFIG_MOMENCO_OCELOT_C is not set
-# CONFIG_DDB5074 is not set
-# CONFIG_DDB5476 is not set
-# CONFIG_DDB5477 is not set
-# CONFIG_NEC_OSPREY is not set
-# CONFIG_NEC_EAGLE is not set
-# CONFIG_OLIVETTI_M700 is not set
-# CONFIG_SGI_IP22 is not set
-CONFIG_SGI_IP27=y
-# CONFIG_SGI_SN0_N_MODE is not set
-# CONFIG_DISCONTIGMEM is not set
-# CONFIG_NUMA is not set
-# CONFIG_MAPPED_KERNEL is not set
-# CONFIG_REPLICATE_KTEXT is not set
-# CONFIG_REPLICATE_EXHANDLERS is not set
-# CONFIG_SGI_IP32 is not set
-# CONFIG_SIBYTE_SB1xxx_SOC is not set
-# CONFIG_SNI_RM200_PCI is not set
-# CONFIG_TANBAC_TB0226 is not set
-# CONFIG_TANBAC_TB0229 is not set
-# CONFIG_VICTOR_MPC30X is not set
-# CONFIG_ZAO_CAPCELLA is not set
-CONFIG_RWSEM_GENERIC_SPINLOCK=y
-CONFIG_ARC=y
-CONFIG_GENERIC_ISA_DMA=y
-# CONFIG_CPU_LITTLE_ENDIAN is not set
-CONFIG_L1_CACHE_SHIFT=7
-# CONFIG_FB is not set
-CONFIG_ARC64=y
-CONFIG_BOOT_ELF64=y
-CONFIG_QL_ISP_A64=y
-
-#
-# CPU selection
-#
-# CONFIG_CPU_MIPS32 is not set
-# CONFIG_CPU_MIPS64 is not set
-# CONFIG_CPU_R3000 is not set
-# CONFIG_CPU_TX39XX is not set
-# CONFIG_CPU_VR41XX is not set
-# CONFIG_CPU_R4300 is not set
-# CONFIG_CPU_R4X00 is not set
-# CONFIG_CPU_TX49XX is not set
-# CONFIG_CPU_R5000 is not set
-# CONFIG_CPU_R5432 is not set
-# CONFIG_CPU_R6000 is not set
-# CONFIG_CPU_NEVADA is not set
-# CONFIG_CPU_R8000 is not set
-CONFIG_CPU_R10000=y
-# CONFIG_CPU_RM7000 is not set
-# CONFIG_CPU_SB1 is not set
-CONFIG_CPU_HAS_LLSC=y
-CONFIG_CPU_HAS_LLDSCD=y
-CONFIG_CPU_HAS_SYNC=y
-CONFIG_SMP=y
-CONFIG_NR_CPUS=4
-# CONFIG_PREEMPT is not set
-# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
-# CONFIG_MIPS_INSANE_LARGE is not set
-
-#
-# Bus options (PCI, PCMCIA, EISA, ISA, TC)
-#
-CONFIG_PCI=y
-CONFIG_PCI_LEGACY_PROC=y
-CONFIG_PCI_NAMES=y
-CONFIG_MMU=y
-# CONFIG_HOTPLUG is not set
-
-#
-# Executable file formats
-#
-CONFIG_KCORE_ELF=y
-CONFIG_BINFMT_ELF=y
-# CONFIG_BINFMT_MISC is not set
-CONFIG_MIPS32_COMPAT=y
-CONFIG_COMPAT=y
-CONFIG_MIPS32_O32=y
-# CONFIG_MIPS32_N32 is not set
-CONFIG_BINFMT_ELF32=y
-
-#
-# Memory Technology Devices (MTD)
-#
-# CONFIG_MTD is not set
-
-#
-# Parallel port support
-#
-# CONFIG_PARPORT is not set
-
-#
-# Plug and Play support
-#
-# CONFIG_PNP is not set
-
-#
-# Generic Driver Options
-#
-# CONFIG_FW_LOADER is not set
-
-#
-# Block devices
-#
-# CONFIG_BLK_DEV_FD is not set
-# CONFIG_BLK_CPQ_DA is not set
-# CONFIG_BLK_CPQ_CISS_DA is not set
-# CONFIG_BLK_DEV_DAC960 is not set
-# CONFIG_BLK_DEV_UMEM is not set
-# CONFIG_BLK_DEV_LOOP is not set
-# CONFIG_BLK_DEV_NBD is not set
-# CONFIG_BLK_DEV_RAM is not set
-# CONFIG_BLK_DEV_INITRD is not set
-
-#
-# ATA/ATAPI/MFM/RLL support
-#
-# CONFIG_IDE is not set
-
-#
-# SCSI device support
-#
-CONFIG_SCSI=y
-
-#
-# SCSI support type (disk, tape, CD-ROM)
-#
-CONFIG_BLK_DEV_SD=y
-CONFIG_CHR_DEV_ST=y
-# CONFIG_CHR_DEV_OSST is not set
-# CONFIG_BLK_DEV_SR is not set
-# CONFIG_CHR_DEV_SG is not set
-
-#
-# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
-#
-# CONFIG_SCSI_MULTI_LUN is not set
-# CONFIG_SCSI_REPORT_LUNS is not set
-CONFIG_SCSI_CONSTANTS=y
-CONFIG_SCSI_LOGGING=y
-
-#
-# SCSI low-level drivers
-#
-# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
-# CONFIG_SCSI_ACARD is not set
-# CONFIG_SCSI_AACRAID is not set
-# CONFIG_SCSI_AIC7XXX is not set
-# CONFIG_SCSI_AIC7XXX_OLD is not set
-# CONFIG_SCSI_AIC79XX is not set
-# CONFIG_SCSI_DPT_I2O is not set
-# CONFIG_SCSI_ADVANSYS is not set
-# CONFIG_SCSI_MEGARAID is not set
-# CONFIG_SCSI_BUSLOGIC is not set
-# CONFIG_SCSI_CPQFCTS is not set
-# CONFIG_SCSI_DMX3191D is not set
-# CONFIG_SCSI_EATA is not set
-# CONFIG_SCSI_EATA_PIO is not set
-# CONFIG_SCSI_FUTURE_DOMAIN is not set
-# CONFIG_SCSI_GDTH is not set
-# CONFIG_SCSI_INITIO is not set
-# CONFIG_SCSI_INIA100 is not set
-# CONFIG_SCSI_SYM53C8XX_2 is not set
-# CONFIG_SCSI_SYM53C8XX is not set
-# CONFIG_SCSI_PCI2000 is not set
-# CONFIG_SCSI_PCI2220I is not set
-# CONFIG_SCSI_QLOGIC_ISP is not set
-# CONFIG_SCSI_QLOGIC_FC is not set
-# CONFIG_SCSI_QLOGIC_1280 is not set
-# CONFIG_SCSI_DC395x is not set
-# CONFIG_SCSI_DC390T is not set
-# CONFIG_SCSI_NSP32 is not set
-# CONFIG_SCSI_DEBUG is not set
-
-#
-# Multi-device support (RAID and LVM)
-#
-# CONFIG_MD is not set
-
-#
-# Fusion MPT device support
-#
-# CONFIG_FUSION is not set
-
-#
-# IEEE 1394 (FireWire) support (EXPERIMENTAL)
-#
-# CONFIG_IEEE1394 is not set
-
-#
-# I2O device support
-#
-# CONFIG_I2O is not set
-
-#
-# Networking support
-#
-CONFIG_NET=y
-
-#
-# Networking options
-#
-CONFIG_PACKET=y
-CONFIG_PACKET_MMAP=y
-CONFIG_NETLINK_DEV=y
-# CONFIG_NETFILTER is not set
-CONFIG_UNIX=y
-CONFIG_NET_KEY=y
-CONFIG_INET=y
-CONFIG_IP_MULTICAST=y
-# CONFIG_IP_ADVANCED_ROUTER is not set
-CONFIG_IP_PNP=y
-# CONFIG_IP_PNP_DHCP is not set
-# CONFIG_IP_PNP_BOOTP is not set
-# CONFIG_IP_PNP_RARP is not set
-# CONFIG_NET_IPIP is not set
-# CONFIG_NET_IPGRE is not set
-# CONFIG_IP_MROUTE is not set
-# CONFIG_ARPD is not set
-# CONFIG_INET_ECN is not set
-# CONFIG_SYN_COOKIES is not set
-# CONFIG_INET_AH is not set
-# CONFIG_INET_ESP is not set
-# CONFIG_INET_IPCOMP is not set
-# CONFIG_IPV6 is not set
-# CONFIG_XFRM_USER is not set
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
-CONFIG_IPV6_SCTP__=y
-# CONFIG_IP_SCTP is not set
-# CONFIG_ATM is not set
-# CONFIG_VLAN_8021Q is not set
-# CONFIG_LLC is not set
-# CONFIG_DECNET is not set
-# CONFIG_BRIDGE is not set
-# CONFIG_X25 is not set
-# CONFIG_LAPB is not set
-# CONFIG_NET_DIVERT is not set
-# CONFIG_ECONET is not set
-# CONFIG_WAN_ROUTER is not set
-# CONFIG_NET_FASTROUTE is not set
-# CONFIG_NET_HW_FLOWCONTROL is not set
-
-#
-# QoS and/or fair queueing
-#
-# CONFIG_NET_SCHED is not set
-
-#
-# Network testing
-#
-# CONFIG_NET_PKTGEN is not set
-CONFIG_NETDEVICES=y
-
-#
-# ARCnet devices
-#
-# CONFIG_ARCNET is not set
-# CONFIG_DUMMY is not set
-# CONFIG_BONDING is not set
-# CONFIG_EQUALIZER is not set
-# CONFIG_TUN is not set
-# CONFIG_ETHERTAP is not set
-
-#
-# Ethernet (10 or 100Mbit)
-#
-CONFIG_NET_ETHERNET=y
-# CONFIG_MII is not set
-CONFIG_SGI_IOC3_ETH=y
-# CONFIG_HAPPYMEAL is not set
-# CONFIG_SUNGEM is not set
-# CONFIG_NET_VENDOR_3COM is not set
-
-#
-# Tulip family network device support
-#
-# CONFIG_NET_TULIP is not set
-# CONFIG_HP100 is not set
-# CONFIG_NET_PCI is not set
-
-#
-# Ethernet (1000 Mbit)
-#
-# CONFIG_ACENIC is not set
-# CONFIG_DL2K is not set
-# CONFIG_E1000 is not set
-# CONFIG_NS83820 is not set
-# CONFIG_HAMACHI is not set
-# CONFIG_YELLOWFIN is not set
-# CONFIG_R8169 is not set
-# CONFIG_SK98LIN is not set
-# CONFIG_TIGON3 is not set
-
-#
-# Ethernet (10000 Mbit)
-#
-# CONFIG_IXGB is not set
-# CONFIG_FDDI is not set
-# CONFIG_HIPPI is not set
-# CONFIG_PPP is not set
-# CONFIG_SLIP is not set
-
-#
-# Wireless LAN (non-hamradio)
-#
-# CONFIG_NET_RADIO is not set
-
-#
-# Token Ring devices (depends on LLC=y)
-#
-# CONFIG_NET_FC is not set
-# CONFIG_RCPCI is not set
-# CONFIG_SHAPER is not set
-
-#
-# Wan interfaces
-#
-# CONFIG_WAN is not set
-
-#
-# Amateur Radio support
-#
-# CONFIG_HAMRADIO is not set
-
-#
-# IrDA (infrared) support
-#
-# CONFIG_IRDA is not set
-
-#
-# ISDN subsystem
-#
-# CONFIG_ISDN_BOOL is not set
-
-#
-# Telephony Support
-#
-# CONFIG_PHONE is not set
-
-#
-# Input device support
-#
-CONFIG_INPUT=y
-
-#
-# Userland interfaces
-#
-# CONFIG_INPUT_MOUSEDEV is not set
-# CONFIG_INPUT_JOYDEV is not set
-# CONFIG_INPUT_TSDEV is not set
-# CONFIG_INPUT_EVDEV is not set
-# CONFIG_INPUT_EVBUG is not set
-
-#
-# Input I/O drivers
-#
-# CONFIG_GAMEPORT is not set
-CONFIG_SOUND_GAMEPORT=y
-CONFIG_SERIO=y
-# CONFIG_SERIO_I8042 is not set
-CONFIG_SERIO_SERPORT=y
-# CONFIG_SERIO_CT82C710 is not set
-# CONFIG_SERIO_PCIPS2 is not set
-
-#
-# Input Device Drivers
-#
-# CONFIG_INPUT_KEYBOARD is not set
-# CONFIG_INPUT_MOUSE is not set
-# CONFIG_INPUT_JOYSTICK is not set
-# CONFIG_INPUT_TOUCHSCREEN is not set
-# CONFIG_INPUT_MISC is not set
-
-#
-# Character devices
-#
-# CONFIG_VT is not set
-# CONFIG_SERIAL_NONSTANDARD is not set
-
-#
-# Serial drivers
-#
-CONFIG_SERIAL_8250=y
-# CONFIG_SERIAL_8250_CONSOLE is not set
-CONFIG_SERIAL_8250_EXTENDED=y
-CONFIG_SERIAL_8250_MANY_PORTS=y
-CONFIG_SERIAL_8250_SHARE_IRQ=y
-# CONFIG_SERIAL_8250_DETECT_IRQ is not set
-# CONFIG_SERIAL_8250_MULTIPORT is not set
-# CONFIG_SERIAL_8250_RSA is not set
-
-#
-# Non-8250 serial port support
-#
-CONFIG_SERIAL_CORE=y
-CONFIG_UNIX98_PTYS=y
-CONFIG_UNIX98_PTY_COUNT=256
-
-#
-# I2C support
-#
-# CONFIG_I2C is not set
-
-#
-# I2C Hardware Sensors Mainboard support
-#
-
-#
-# I2C Hardware Sensors Chip support
-#
-# CONFIG_I2C_SENSOR is not set
-
-#
-# Mice
-#
-# CONFIG_BUSMOUSE is not set
-# CONFIG_QIC02_TAPE is not set
-
-#
-# IPMI
-#
-# CONFIG_IPMI_HANDLER is not set
-
-#
-# Watchdog Cards
-#
-# CONFIG_WATCHDOG is not set
-# CONFIG_NVRAM is not set
-# CONFIG_RTC is not set
-# CONFIG_GEN_RTC is not set
-CONFIG_SGI_IP27_RTC=y
-# CONFIG_DTLK is not set
-# CONFIG_R3964 is not set
-# CONFIG_APPLICOM is not set
-
-#
-# Ftape, the floppy tape device driver
-#
-# CONFIG_FTAPE is not set
-# CONFIG_AGP is not set
-# CONFIG_DRM is not set
-# CONFIG_RAW_DRIVER is not set
-# CONFIG_HANGCHECK_TIMER is not set
-
-#
-# Multimedia devices
-#
-# CONFIG_VIDEO_DEV is not set
-
-#
-# Digital Video Broadcasting Devices
-#
-# CONFIG_DVB is not set
-
-#
-# File systems
-#
-CONFIG_EXT2_FS=y
-CONFIG_EXT2_FS_XATTR=y
-CONFIG_EXT2_FS_POSIX_ACL=y
-CONFIG_EXT2_FS_SECURITY=y
-CONFIG_EXT3_FS=y
-CONFIG_EXT3_FS_XATTR=y
-CONFIG_EXT3_FS_POSIX_ACL=y
-CONFIG_EXT3_FS_SECURITY=y
-CONFIG_JBD=y
-CONFIG_JBD_DEBUG=y
-CONFIG_FS_MBCACHE=y
-# CONFIG_REISERFS_FS is not set
-# CONFIG_JFS_FS is not set
-CONFIG_FS_POSIX_ACL=y
-# CONFIG_XFS_FS is not set
-# CONFIG_MINIX_FS is not set
-# CONFIG_ROMFS_FS is not set
-# CONFIG_QUOTA is not set
-CONFIG_AUTOFS_FS=y
-# CONFIG_AUTOFS4_FS is not set
-
-#
-# CD-ROM/DVD Filesystems
-#
-# CONFIG_ISO9660_FS is not set
-# CONFIG_UDF_FS is not set
-
-#
-# DOS/FAT/NT Filesystems
-#
-# CONFIG_FAT_FS is not set
-# CONFIG_NTFS_FS is not set
-
-#
-# Pseudo filesystems
-#
-CONFIG_PROC_FS=y
-# CONFIG_DEVFS_FS is not set
-CONFIG_DEVPTS_FS=y
-CONFIG_DEVPTS_FS_XATTR=y
-CONFIG_DEVPTS_FS_SECURITY=y
-# CONFIG_TMPFS is not set
-CONFIG_RAMFS=y
-
-#
-# Miscellaneous filesystems
-#
-# CONFIG_ADFS_FS is not set
-# CONFIG_AFFS_FS is not set
-# CONFIG_HFS_FS is not set
-# CONFIG_BEFS_FS is not set
-# CONFIG_BFS_FS is not set
-# CONFIG_EFS_FS is not set
-# CONFIG_CRAMFS is not set
-# CONFIG_VXFS_FS is not set
-# CONFIG_HPFS_FS is not set
-# CONFIG_QNX4FS_FS is not set
-# CONFIG_SYSV_FS is not set
-# CONFIG_UFS_FS is not set
-
-#
-# Network File Systems
-#
-CONFIG_NFS_FS=y
-CONFIG_NFS_V3=y
-# CONFIG_NFS_V4 is not set
-# CONFIG_NFSD is not set
-CONFIG_ROOT_NFS=y
-CONFIG_LOCKD=y
-CONFIG_LOCKD_V4=y
-# CONFIG_EXPORTFS is not set
-CONFIG_SUNRPC=y
-# CONFIG_SUNRPC_GSS is not set
-# CONFIG_SMB_FS is not set
-# CONFIG_CIFS is not set
-# CONFIG_NCP_FS is not set
-# CONFIG_CODA_FS is not set
-# CONFIG_INTERMEZZO_FS is not set
-# CONFIG_AFS_FS is not set
-
-#
-# Partition Types
-#
-CONFIG_PARTITION_ADVANCED=y
-# CONFIG_ACORN_PARTITION is not set
-# CONFIG_OSF_PARTITION is not set
-# CONFIG_AMIGA_PARTITION is not set
-# CONFIG_ATARI_PARTITION is not set
-# CONFIG_MAC_PARTITION is not set
-CONFIG_MSDOS_PARTITION=y
-# CONFIG_BSD_DISKLABEL is not set
-# CONFIG_MINIX_SUBPARTITION is not set
-# CONFIG_SOLARIS_X86_PARTITION is not set
-# CONFIG_UNIXWARE_DISKLABEL is not set
-# CONFIG_LDM_PARTITION is not set
-# CONFIG_NEC98_PARTITION is not set
-CONFIG_SGI_PARTITION=y
-# CONFIG_ULTRIX_PARTITION is not set
-# CONFIG_SUN_PARTITION is not set
-# CONFIG_EFI_PARTITION is not set
-
-#
-# Graphics support
-#
-
-#
-# Sound
-#
-# CONFIG_SOUND is not set
-
-#
-# USB support
-#
-# CONFIG_USB is not set
-# CONFIG_USB_GADGET is not set
-
-#
-# Bluetooth support
-#
-# CONFIG_BT is not set
-
-#
-# Kernel hacking
-#
-CONFIG_CROSSCOMPILE=y
-# CONFIG_DEBUG_KERNEL is not set
-
-#
-# Security options
-#
-# CONFIG_SECURITY is not set
-
-#
-# Cryptographic options
-#
-# CONFIG_CRYPTO is not set
-
-#
-# Library routines
-#
-# CONFIG_CRC32 is not set
--- diff/arch/mips/defconfig-ip32	2003-08-20 14:16:36.000000000 +0100
+++ source/arch/mips/defconfig-ip32	1970-01-01 01:00:00.000000000 +0100
@@ -1,638 +0,0 @@
-#
-# Automatically generated make config: don't edit
-#
-CONFIG_MIPS=y
-CONFIG_MIPS64=y
-
-#
-# Code maturity level options
-#
-CONFIG_EXPERIMENTAL=y
-
-#
-# General setup
-#
-CONFIG_SWAP=y
-CONFIG_SYSVIPC=y
-CONFIG_BSD_PROCESS_ACCT=y
-CONFIG_SYSCTL=y
-CONFIG_LOG_BUF_SHIFT=14
-# CONFIG_EMBEDDED is not set
-CONFIG_KALLSYMS=y
-CONFIG_FUTEX=y
-CONFIG_EPOLL=y
-CONFIG_IOSCHED_AS=y
-CONFIG_IOSCHED_DEADLINE=y
-
-#
-# Loadable module support
-#
-# CONFIG_MODULES is not set
-
-#
-# Machine selection
-#
-# CONFIG_ACER_PICA_61 is not set
-# CONFIG_CASIO_E55 is not set
-# CONFIG_MIPS_COBALT is not set
-# CONFIG_DECSTATION is not set
-# CONFIG_MIPS_EV64120 is not set
-# CONFIG_MIPS_EV96100 is not set
-# CONFIG_MIPS_IVR is not set
-# CONFIG_LASAT is not set
-# CONFIG_HP_LASERJET is not set
-# CONFIG_IBM_WORKPAD is not set
-# CONFIG_MIPS_ITE8172 is not set
-# CONFIG_MIPS_ATLAS is not set
-# CONFIG_MIPS_MAGNUM_4000 is not set
-# CONFIG_MIPS_MALTA is not set
-# CONFIG_MIPS_SEAD is not set
-# CONFIG_MOMENCO_OCELOT is not set
-# CONFIG_MOMENCO_OCELOT_G is not set
-# CONFIG_MOMENCO_OCELOT_C is not set
-# CONFIG_DDB5074 is not set
-# CONFIG_DDB5476 is not set
-# CONFIG_DDB5477 is not set
-# CONFIG_NEC_OSPREY is not set
-# CONFIG_NEC_EAGLE is not set
-# CONFIG_OLIVETTI_M700 is not set
-# CONFIG_SGI_IP22 is not set
-# CONFIG_SGI_IP27 is not set
-CONFIG_SGI_IP32=y
-# CONFIG_SIBYTE_SB1xxx_SOC is not set
-# CONFIG_SNI_RM200_PCI is not set
-# CONFIG_TANBAC_TB0226 is not set
-# CONFIG_TANBAC_TB0229 is not set
-# CONFIG_VICTOR_MPC30X is not set
-# CONFIG_ZAO_CAPCELLA is not set
-CONFIG_RWSEM_GENERIC_SPINLOCK=y
-CONFIG_ARC=y
-CONFIG_GENERIC_ISA_DMA=y
-CONFIG_NONCOHERENT_IO=y
-# CONFIG_CPU_LITTLE_ENDIAN is not set
-CONFIG_BOOT_ELF32=y
-CONFIG_L1_CACHE_SHIFT=5
-CONFIG_ARC32=y
-# CONFIG_FB is not set
-CONFIG_ARC_MEMORY=y
-CONFIG_ARC_PROMLIB=y
-CONFIG_BOARD_SCACHE=y
-
-#
-# CPU selection
-#
-# CONFIG_CPU_MIPS32 is not set
-# CONFIG_CPU_MIPS64 is not set
-# CONFIG_CPU_R3000 is not set
-# CONFIG_CPU_TX39XX is not set
-# CONFIG_CPU_VR41XX is not set
-# CONFIG_CPU_R4300 is not set
-# CONFIG_CPU_R4X00 is not set
-# CONFIG_CPU_TX49XX is not set
-CONFIG_CPU_R5000=y
-# CONFIG_CPU_R5432 is not set
-# CONFIG_CPU_R6000 is not set
-# CONFIG_CPU_NEVADA is not set
-# CONFIG_CPU_R8000 is not set
-# CONFIG_CPU_R10000 is not set
-# CONFIG_CPU_RM7000 is not set
-# CONFIG_CPU_SB1 is not set
-CONFIG_R5000_CPU_SCACHE=y
-CONFIG_CPU_HAS_LLSC=y
-CONFIG_CPU_HAS_LLDSCD=y
-CONFIG_CPU_HAS_SYNC=y
-# CONFIG_PREEMPT is not set
-# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
-
-#
-# Bus options (PCI, PCMCIA, EISA, ISA, TC)
-#
-CONFIG_PCI=y
-CONFIG_PCI_LEGACY_PROC=y
-CONFIG_PCI_NAMES=y
-CONFIG_MMU=y
-# CONFIG_HOTPLUG is not set
-
-#
-# Executable file formats
-#
-CONFIG_KCORE_ELF=y
-CONFIG_BINFMT_ELF=y
-CONFIG_BINFMT_MISC=y
-CONFIG_MIPS32_COMPAT=y
-CONFIG_COMPAT=y
-CONFIG_MIPS32_O32=y
-# CONFIG_MIPS32_N32 is not set
-CONFIG_BINFMT_ELF32=y
-
-#
-# Memory Technology Devices (MTD)
-#
-# CONFIG_MTD is not set
-
-#
-# Parallel port support
-#
-# CONFIG_PARPORT is not set
-
-#
-# Plug and Play support
-#
-# CONFIG_PNP is not set
-
-#
-# Generic Driver Options
-#
-# CONFIG_FW_LOADER is not set
-
-#
-# Block devices
-#
-# CONFIG_BLK_DEV_FD is not set
-# CONFIG_BLK_CPQ_DA is not set
-# CONFIG_BLK_CPQ_CISS_DA is not set
-# CONFIG_BLK_DEV_DAC960 is not set
-# CONFIG_BLK_DEV_UMEM is not set
-CONFIG_BLK_DEV_LOOP=y
-# CONFIG_BLK_DEV_CRYPTOLOOP is not set
-# CONFIG_BLK_DEV_NBD is not set
-# CONFIG_BLK_DEV_RAM is not set
-# CONFIG_BLK_DEV_INITRD is not set
-
-#
-# ATA/ATAPI/MFM/RLL support
-#
-# CONFIG_IDE is not set
-
-#
-# SCSI device support
-#
-CONFIG_SCSI=y
-
-#
-# SCSI support type (disk, tape, CD-ROM)
-#
-CONFIG_BLK_DEV_SD=y
-CONFIG_CHR_DEV_ST=y
-CONFIG_CHR_DEV_OSST=y
-CONFIG_BLK_DEV_SR=y
-CONFIG_BLK_DEV_SR_VENDOR=y
-CONFIG_CHR_DEV_SG=y
-
-#
-# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
-#
-CONFIG_SCSI_MULTI_LUN=y
-# CONFIG_SCSI_REPORT_LUNS is not set
-CONFIG_SCSI_CONSTANTS=y
-CONFIG_SCSI_LOGGING=y
-
-#
-# SCSI low-level drivers
-#
-# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
-# CONFIG_SCSI_ACARD is not set
-# CONFIG_SCSI_AACRAID is not set
-CONFIG_SCSI_AIC7XXX=y
-CONFIG_AIC7XXX_CMDS_PER_DEVICE=8
-CONFIG_AIC7XXX_RESET_DELAY_MS=15000
-# CONFIG_AIC7XXX_PROBE_EISA_VL is not set
-# CONFIG_AIC7XXX_BUILD_FIRMWARE is not set
-CONFIG_AIC7XXX_DEBUG_ENABLE=y
-CONFIG_AIC7XXX_DEBUG_MASK=0
-CONFIG_AIC7XXX_REG_PRETTY_PRINT=y
-# CONFIG_SCSI_AIC7XXX_OLD is not set
-# CONFIG_SCSI_AIC79XX is not set
-# CONFIG_SCSI_DPT_I2O is not set
-# CONFIG_SCSI_ADVANSYS is not set
-# CONFIG_SCSI_MEGARAID is not set
-# CONFIG_SCSI_BUSLOGIC is not set
-# CONFIG_SCSI_CPQFCTS is not set
-# CONFIG_SCSI_DMX3191D is not set
-# CONFIG_SCSI_EATA is not set
-# CONFIG_SCSI_EATA_PIO is not set
-# CONFIG_SCSI_FUTURE_DOMAIN is not set
-# CONFIG_SCSI_GDTH is not set
-# CONFIG_SCSI_INITIO is not set
-# CONFIG_SCSI_INIA100 is not set
-# CONFIG_SCSI_SYM53C8XX_2 is not set
-# CONFIG_SCSI_SYM53C8XX is not set
-# CONFIG_SCSI_PCI2000 is not set
-# CONFIG_SCSI_PCI2220I is not set
-# CONFIG_SCSI_QLOGIC_ISP is not set
-# CONFIG_SCSI_QLOGIC_FC is not set
-# CONFIG_SCSI_QLOGIC_1280 is not set
-# CONFIG_SCSI_DC395x is not set
-# CONFIG_SCSI_DC390T is not set
-# CONFIG_SCSI_NSP32 is not set
-# CONFIG_SCSI_DEBUG is not set
-
-#
-# Multi-device support (RAID and LVM)
-#
-# CONFIG_MD is not set
-
-#
-# Fusion MPT device support
-#
-# CONFIG_FUSION is not set
-
-#
-# IEEE 1394 (FireWire) support (EXPERIMENTAL)
-#
-# CONFIG_IEEE1394 is not set
-
-#
-# I2O device support
-#
-# CONFIG_I2O is not set
-
-#
-# Networking support
-#
-CONFIG_NET=y
-
-#
-# Networking options
-#
-CONFIG_PACKET=y
-CONFIG_PACKET_MMAP=y
-CONFIG_NETLINK_DEV=y
-# CONFIG_NETFILTER is not set
-CONFIG_UNIX=y
-CONFIG_NET_KEY=y
-CONFIG_INET=y
-# CONFIG_IP_MULTICAST is not set
-# CONFIG_IP_ADVANCED_ROUTER is not set
-CONFIG_IP_PNP=y
-# CONFIG_IP_PNP_DHCP is not set
-CONFIG_IP_PNP_BOOTP=y
-# CONFIG_IP_PNP_RARP is not set
-# CONFIG_NET_IPIP is not set
-# CONFIG_NET_IPGRE is not set
-# CONFIG_ARPD is not set
-# CONFIG_INET_ECN is not set
-# CONFIG_SYN_COOKIES is not set
-# CONFIG_INET_AH is not set
-# CONFIG_INET_ESP is not set
-# CONFIG_INET_IPCOMP is not set
-# CONFIG_IPV6 is not set
-# CONFIG_XFRM_USER is not set
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
-CONFIG_IPV6_SCTP__=y
-# CONFIG_IP_SCTP is not set
-# CONFIG_ATM is not set
-# CONFIG_VLAN_8021Q is not set
-# CONFIG_LLC is not set
-# CONFIG_DECNET is not set
-# CONFIG_BRIDGE is not set
-# CONFIG_X25 is not set
-# CONFIG_LAPB is not set
-# CONFIG_NET_DIVERT is not set
-# CONFIG_ECONET is not set
-# CONFIG_WAN_ROUTER is not set
-# CONFIG_NET_FASTROUTE is not set
-# CONFIG_NET_HW_FLOWCONTROL is not set
-
-#
-# QoS and/or fair queueing
-#
-# CONFIG_NET_SCHED is not set
-
-#
-# Network testing
-#
-# CONFIG_NET_PKTGEN is not set
-CONFIG_NETDEVICES=y
-
-#
-# ARCnet devices
-#
-# CONFIG_ARCNET is not set
-# CONFIG_DUMMY is not set
-# CONFIG_BONDING is not set
-# CONFIG_EQUALIZER is not set
-# CONFIG_TUN is not set
-# CONFIG_ETHERTAP is not set
-
-#
-# Ethernet (10 or 100Mbit)
-#
-CONFIG_NET_ETHERNET=y
-# CONFIG_MII is not set
-CONFIG_SGI_O2MACE_ETH=y
-# CONFIG_HAPPYMEAL is not set
-# CONFIG_SUNGEM is not set
-# CONFIG_NET_VENDOR_3COM is not set
-
-#
-# Tulip family network device support
-#
-# CONFIG_NET_TULIP is not set
-# CONFIG_HP100 is not set
-# CONFIG_NET_PCI is not set
-
-#
-# Ethernet (1000 Mbit)
-#
-# CONFIG_ACENIC is not set
-# CONFIG_DL2K is not set
-# CONFIG_E1000 is not set
-# CONFIG_NS83820 is not set
-# CONFIG_HAMACHI is not set
-# CONFIG_YELLOWFIN is not set
-# CONFIG_R8169 is not set
-# CONFIG_SK98LIN is not set
-# CONFIG_TIGON3 is not set
-
-#
-# Ethernet (10000 Mbit)
-#
-# CONFIG_IXGB is not set
-# CONFIG_FDDI is not set
-# CONFIG_HIPPI is not set
-# CONFIG_PPP is not set
-# CONFIG_SLIP is not set
-
-#
-# Wireless LAN (non-hamradio)
-#
-# CONFIG_NET_RADIO is not set
-
-#
-# Token Ring devices (depends on LLC=y)
-#
-# CONFIG_NET_FC is not set
-# CONFIG_RCPCI is not set
-# CONFIG_SHAPER is not set
-
-#
-# Wan interfaces
-#
-# CONFIG_WAN is not set
-
-#
-# Amateur Radio support
-#
-# CONFIG_HAMRADIO is not set
-
-#
-# IrDA (infrared) support
-#
-# CONFIG_IRDA is not set
-
-#
-# ISDN subsystem
-#
-# CONFIG_ISDN_BOOL is not set
-
-#
-# Telephony Support
-#
-# CONFIG_PHONE is not set
-
-#
-# Input device support
-#
-CONFIG_INPUT=y
-
-#
-# Userland interfaces
-#
-# CONFIG_INPUT_MOUSEDEV is not set
-# CONFIG_INPUT_JOYDEV is not set
-# CONFIG_INPUT_TSDEV is not set
-# CONFIG_INPUT_EVDEV is not set
-# CONFIG_INPUT_EVBUG is not set
-
-#
-# Input I/O drivers
-#
-# CONFIG_GAMEPORT is not set
-CONFIG_SOUND_GAMEPORT=y
-CONFIG_SERIO=y
-# CONFIG_SERIO_I8042 is not set
-CONFIG_SERIO_SERPORT=y
-# CONFIG_SERIO_CT82C710 is not set
-# CONFIG_SERIO_PCIPS2 is not set
-
-#
-# Input Device Drivers
-#
-# CONFIG_INPUT_KEYBOARD is not set
-# CONFIG_INPUT_MOUSE is not set
-# CONFIG_INPUT_JOYSTICK is not set
-# CONFIG_INPUT_TOUCHSCREEN is not set
-# CONFIG_INPUT_MISC is not set
-
-#
-# Character devices
-#
-# CONFIG_VT is not set
-# CONFIG_SERIAL_NONSTANDARD is not set
-
-#
-# Serial drivers
-#
-CONFIG_SERIAL_8250=y
-CONFIG_SERIAL_8250_CONSOLE=y
-# CONFIG_SERIAL_8250_EXTENDED is not set
-
-#
-# Non-8250 serial port support
-#
-CONFIG_SERIAL_CORE=y
-CONFIG_SERIAL_CORE_CONSOLE=y
-CONFIG_UNIX98_PTYS=y
-CONFIG_UNIX98_PTY_COUNT=256
-
-#
-# I2C support
-#
-# CONFIG_I2C is not set
-
-#
-# I2C Hardware Sensors Mainboard support
-#
-
-#
-# I2C Hardware Sensors Chip support
-#
-# CONFIG_I2C_SENSOR is not set
-
-#
-# Mice
-#
-# CONFIG_BUSMOUSE is not set
-# CONFIG_QIC02_TAPE is not set
-
-#
-# IPMI
-#
-# CONFIG_IPMI_HANDLER is not set
-
-#
-# Watchdog Cards
-#
-# CONFIG_WATCHDOG is not set
-# CONFIG_NVRAM is not set
-# CONFIG_RTC is not set
-# CONFIG_GEN_RTC is not set
-# CONFIG_DTLK is not set
-# CONFIG_R3964 is not set
-# CONFIG_APPLICOM is not set
-
-#
-# Ftape, the floppy tape device driver
-#
-# CONFIG_FTAPE is not set
-# CONFIG_AGP is not set
-# CONFIG_DRM is not set
-# CONFIG_RAW_DRIVER is not set
-# CONFIG_HANGCHECK_TIMER is not set
-
-#
-# Multimedia devices
-#
-# CONFIG_VIDEO_DEV is not set
-
-#
-# Digital Video Broadcasting Devices
-#
-# CONFIG_DVB is not set
-
-#
-# File systems
-#
-CONFIG_EXT2_FS=y
-# CONFIG_EXT2_FS_XATTR is not set
-# CONFIG_EXT3_FS is not set
-# CONFIG_JBD is not set
-# CONFIG_REISERFS_FS is not set
-# CONFIG_JFS_FS is not set
-# CONFIG_XFS_FS is not set
-# CONFIG_MINIX_FS is not set
-# CONFIG_ROMFS_FS is not set
-# CONFIG_QUOTA is not set
-# CONFIG_AUTOFS_FS is not set
-# CONFIG_AUTOFS4_FS is not set
-
-#
-# CD-ROM/DVD Filesystems
-#
-# CONFIG_ISO9660_FS is not set
-# CONFIG_UDF_FS is not set
-
-#
-# DOS/FAT/NT Filesystems
-#
-# CONFIG_FAT_FS is not set
-# CONFIG_NTFS_FS is not set
-
-#
-# Pseudo filesystems
-#
-CONFIG_PROC_FS=y
-# CONFIG_DEVFS_FS is not set
-CONFIG_DEVPTS_FS=y
-CONFIG_DEVPTS_FS_XATTR=y
-CONFIG_DEVPTS_FS_SECURITY=y
-CONFIG_TMPFS=y
-CONFIG_RAMFS=y
-
-#
-# Miscellaneous filesystems
-#
-# CONFIG_ADFS_FS is not set
-# CONFIG_AFFS_FS is not set
-# CONFIG_HFS_FS is not set
-# CONFIG_BEFS_FS is not set
-# CONFIG_BFS_FS is not set
-# CONFIG_EFS_FS is not set
-# CONFIG_CRAMFS is not set
-# CONFIG_VXFS_FS is not set
-# CONFIG_HPFS_FS is not set
-# CONFIG_QNX4FS_FS is not set
-# CONFIG_SYSV_FS is not set
-# CONFIG_UFS_FS is not set
-
-#
-# Network File Systems
-#
-CONFIG_NFS_FS=y
-CONFIG_NFS_V3=y
-# CONFIG_NFS_V4 is not set
-# CONFIG_NFSD is not set
-CONFIG_ROOT_NFS=y
-CONFIG_LOCKD=y
-CONFIG_LOCKD_V4=y
-# CONFIG_EXPORTFS is not set
-CONFIG_SUNRPC=y
-# CONFIG_SUNRPC_GSS is not set
-# CONFIG_SMB_FS is not set
-# CONFIG_CIFS is not set
-# CONFIG_NCP_FS is not set
-# CONFIG_CODA_FS is not set
-# CONFIG_INTERMEZZO_FS is not set
-# CONFIG_AFS_FS is not set
-
-#
-# Partition Types
-#
-CONFIG_PARTITION_ADVANCED=y
-# CONFIG_ACORN_PARTITION is not set
-# CONFIG_OSF_PARTITION is not set
-# CONFIG_AMIGA_PARTITION is not set
-# CONFIG_ATARI_PARTITION is not set
-# CONFIG_MAC_PARTITION is not set
-# CONFIG_MSDOS_PARTITION is not set
-# CONFIG_LDM_PARTITION is not set
-# CONFIG_NEC98_PARTITION is not set
-CONFIG_SGI_PARTITION=y
-# CONFIG_ULTRIX_PARTITION is not set
-# CONFIG_SUN_PARTITION is not set
-# CONFIG_EFI_PARTITION is not set
-
-#
-# Graphics support
-#
-
-#
-# Sound
-#
-# CONFIG_SOUND is not set
-
-#
-# USB support
-#
-# CONFIG_USB is not set
-# CONFIG_USB_GADGET is not set
-
-#
-# Bluetooth support
-#
-# CONFIG_BT is not set
-
-#
-# Kernel hacking
-#
-CONFIG_CROSSCOMPILE=y
-# CONFIG_DEBUG_KERNEL is not set
-
-#
-# Security options
-#
-# CONFIG_SECURITY is not set
-
-#
-# Cryptographic options
-#
-# CONFIG_CRYPTO is not set
-
-#
-# Library routines
-#
-# CONFIG_CRC32 is not set
--- diff/arch/mips/defconfig-it8172	2003-08-20 14:16:25.000000000 +0100
+++ source/arch/mips/defconfig-it8172	1970-01-01 01:00:00.000000000 +0100
@@ -1,631 +0,0 @@
-#
-# Automatically generated make config: don't edit
-#
-CONFIG_MIPS=y
-# CONFIG_MIPS64 is not set
-CONFIG_MIPS32=y
-
-#
-# Code maturity level options
-#
-CONFIG_EXPERIMENTAL=y
-
-#
-# General setup
-#
-CONFIG_SWAP=y
-CONFIG_SYSVIPC=y
-CONFIG_BSD_PROCESS_ACCT=y
-CONFIG_SYSCTL=y
-CONFIG_LOG_BUF_SHIFT=14
-# CONFIG_EMBEDDED is not set
-CONFIG_KALLSYMS=y
-CONFIG_FUTEX=y
-CONFIG_EPOLL=y
-CONFIG_IOSCHED_AS=y
-CONFIG_IOSCHED_DEADLINE=y
-
-#
-# Loadable module support
-#
-CONFIG_MODULES=y
-CONFIG_MODULE_UNLOAD=y
-# CONFIG_MODULE_FORCE_UNLOAD is not set
-CONFIG_OBSOLETE_MODPARM=y
-CONFIG_MODVERSIONS=y
-CONFIG_KMOD=y
-
-#
-# Machine selection
-#
-# CONFIG_ACER_PICA_61 is not set
-# CONFIG_BAGET_MIPS is not set
-# CONFIG_CASIO_E55 is not set
-# CONFIG_MIPS_COBALT is not set
-# CONFIG_DECSTATION is not set
-# CONFIG_MIPS_EV64120 is not set
-# CONFIG_MIPS_EV96100 is not set
-# CONFIG_MIPS_IVR is not set
-# CONFIG_LASAT is not set
-# CONFIG_HP_LASERJET is not set
-# CONFIG_IBM_WORKPAD is not set
-CONFIG_MIPS_ITE8172=y
-# CONFIG_IT8172_REVC is not set
-# CONFIG_MIPS_ATLAS is not set
-# CONFIG_MIPS_MAGNUM_4000 is not set
-# CONFIG_MIPS_MALTA is not set
-# CONFIG_MIPS_SEAD is not set
-# CONFIG_MOMENCO_OCELOT is not set
-# CONFIG_MOMENCO_OCELOT_G is not set
-# CONFIG_MOMENCO_OCELOT_C is not set
-# CONFIG_DDB5074 is not set
-# CONFIG_DDB5476 is not set
-# CONFIG_DDB5477 is not set
-# CONFIG_NEC_OSPREY is not set
-# CONFIG_NEC_EAGLE is not set
-# CONFIG_OLIVETTI_M700 is not set
-# CONFIG_SGI_IP22 is not set
-# CONFIG_SGI_IP32 is not set
-# CONFIG_SOC_AU1X00 is not set
-# CONFIG_SIBYTE_SB1xxx_SOC is not set
-# CONFIG_SNI_RM200_PCI is not set
-# CONFIG_TANBAC_TB0226 is not set
-# CONFIG_TANBAC_TB0229 is not set
-# CONFIG_TOSHIBA_JMR3927 is not set
-# CONFIG_TOSHIBA_RBTX4927 is not set
-# CONFIG_VICTOR_MPC30X is not set
-# CONFIG_ZAO_CAPCELLA is not set
-CONFIG_RWSEM_GENERIC_SPINLOCK=y
-CONFIG_NONCOHERENT_IO=y
-CONFIG_CPU_LITTLE_ENDIAN=y
-CONFIG_ITE_BOARD_GEN=y
-CONFIG_NEW_PCI=y
-CONFIG_IT8172_CIR=y
-CONFIG_IT8712=y
-# CONFIG_FB is not set
-
-#
-# CPU selection
-#
-# CONFIG_CPU_MIPS32 is not set
-# CONFIG_CPU_MIPS64 is not set
-# CONFIG_CPU_R3000 is not set
-# CONFIG_CPU_TX39XX is not set
-# CONFIG_CPU_VR41XX is not set
-# CONFIG_CPU_R4300 is not set
-# CONFIG_CPU_R4X00 is not set
-# CONFIG_CPU_TX49XX is not set
-# CONFIG_CPU_R5000 is not set
-# CONFIG_CPU_R5432 is not set
-# CONFIG_CPU_R6000 is not set
-CONFIG_CPU_NEVADA=y
-# CONFIG_CPU_R8000 is not set
-# CONFIG_CPU_R10000 is not set
-# CONFIG_CPU_RM7000 is not set
-# CONFIG_CPU_SB1 is not set
-# CONFIG_CPU_ADVANCED is not set
-CONFIG_CPU_HAS_LLSC=y
-CONFIG_CPU_HAS_LLDSCD=y
-CONFIG_CPU_HAS_SYNC=y
-# CONFIG_PREEMPT is not set
-# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
-
-#
-# Bus options (PCI, PCMCIA, EISA, ISA, TC)
-#
-# CONFIG_PCI is not set
-CONFIG_MMU=y
-# CONFIG_HOTPLUG is not set
-
-#
-# Executable file formats
-#
-CONFIG_KCORE_ELF=y
-CONFIG_BINFMT_ELF=y
-# CONFIG_BINFMT_MISC is not set
-CONFIG_TRAD_SIGNALS=y
-
-#
-# Memory Technology Devices (MTD)
-#
-CONFIG_MTD=y
-# CONFIG_MTD_DEBUG is not set
-# CONFIG_MTD_PARTITIONS is not set
-# CONFIG_MTD_CONCAT is not set
-
-#
-# User Modules And Translation Layers
-#
-CONFIG_MTD_CHAR=y
-# CONFIG_MTD_BLOCK is not set
-# CONFIG_MTD_BLOCK_RO is not set
-# CONFIG_FTL is not set
-# CONFIG_NFTL is not set
-# CONFIG_INFTL is not set
-
-#
-# RAM/ROM/Flash chip drivers
-#
-CONFIG_MTD_CFI=y
-# CONFIG_MTD_JEDECPROBE is not set
-CONFIG_MTD_GEN_PROBE=y
-# CONFIG_MTD_CFI_ADV_OPTIONS is not set
-CONFIG_MTD_CFI_INTELEXT=y
-# CONFIG_MTD_CFI_AMDSTD is not set
-# CONFIG_MTD_CFI_STAA is not set
-# CONFIG_MTD_RAM is not set
-# CONFIG_MTD_ROM is not set
-# CONFIG_MTD_ABSENT is not set
-# CONFIG_MTD_OBSOLETE_CHIPS is not set
-
-#
-# Mapping drivers for chip access
-#
-# CONFIG_MTD_COMPLEX_MAPPINGS is not set
-CONFIG_MTD_PHYSMAP=y
-CONFIG_MTD_PHYSMAP_START=0x8000000
-CONFIG_MTD_PHYSMAP_LEN=0x2000000
-CONFIG_MTD_PHYSMAP_BUSWIDTH=4
-
-#
-# Self-contained MTD device drivers
-#
-# CONFIG_MTD_SLRAM is not set
-# CONFIG_MTD_MTDRAM is not set
-# CONFIG_MTD_BLKMTD is not set
-
-#
-# Disk-On-Chip Device Drivers
-#
-# CONFIG_MTD_DOC2000 is not set
-# CONFIG_MTD_DOC2001 is not set
-# CONFIG_MTD_DOC2001PLUS is not set
-
-#
-# NAND Flash Device Drivers
-#
-# CONFIG_MTD_NAND is not set
-
-#
-# Parallel port support
-#
-# CONFIG_PARPORT is not set
-
-#
-# Plug and Play support
-#
-# CONFIG_PNP is not set
-
-#
-# Generic Driver Options
-#
-# CONFIG_FW_LOADER is not set
-
-#
-# Block devices
-#
-# CONFIG_BLK_DEV_FD is not set
-CONFIG_BLK_DEV_LOOP=y
-# CONFIG_BLK_DEV_CRYPTOLOOP is not set
-# CONFIG_BLK_DEV_NBD is not set
-# CONFIG_BLK_DEV_RAM is not set
-# CONFIG_BLK_DEV_INITRD is not set
-# CONFIG_LBD is not set
-
-#
-# ATA/ATAPI/MFM/RLL support
-#
-CONFIG_IDE=y
-
-#
-# IDE, ATA and ATAPI Block devices
-#
-CONFIG_BLK_DEV_IDE=y
-
-#
-# Please see Documentation/ide.txt for help/info on IDE drives
-#
-# CONFIG_BLK_DEV_HD is not set
-CONFIG_BLK_DEV_IDEDISK=y
-# CONFIG_IDEDISK_MULTI_MODE is not set
-# CONFIG_IDEDISK_STROKE is not set
-# CONFIG_BLK_DEV_IDECD is not set
-# CONFIG_BLK_DEV_IDEFLOPPY is not set
-# CONFIG_IDE_TASK_IOCTL is not set
-CONFIG_IDE_TASKFILE_IO=y
-
-#
-# IDE chipset support/bugfixes
-#
-
-#
-# SCSI device support
-#
-# CONFIG_SCSI is not set
-
-#
-# Multi-device support (RAID and LVM)
-#
-# CONFIG_MD is not set
-
-#
-# Fusion MPT device support
-#
-
-#
-# I2O device support
-#
-
-#
-# Networking support
-#
-CONFIG_NET=y
-
-#
-# Networking options
-#
-CONFIG_PACKET=y
-CONFIG_PACKET_MMAP=y
-CONFIG_NETLINK_DEV=y
-# CONFIG_NETFILTER is not set
-CONFIG_UNIX=y
-CONFIG_NET_KEY=y
-CONFIG_INET=y
-# CONFIG_IP_MULTICAST is not set
-# CONFIG_IP_ADVANCED_ROUTER is not set
-CONFIG_IP_PNP=y
-# CONFIG_IP_PNP_DHCP is not set
-CONFIG_IP_PNP_BOOTP=y
-# CONFIG_IP_PNP_RARP is not set
-# CONFIG_NET_IPIP is not set
-# CONFIG_NET_IPGRE is not set
-# CONFIG_ARPD is not set
-# CONFIG_INET_ECN is not set
-# CONFIG_SYN_COOKIES is not set
-# CONFIG_INET_AH is not set
-# CONFIG_INET_ESP is not set
-# CONFIG_INET_IPCOMP is not set
-# CONFIG_IPV6 is not set
-# CONFIG_XFRM_USER is not set
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
-CONFIG_IPV6_SCTP__=y
-# CONFIG_IP_SCTP is not set
-# CONFIG_ATM is not set
-# CONFIG_VLAN_8021Q is not set
-# CONFIG_LLC is not set
-# CONFIG_DECNET is not set
-# CONFIG_BRIDGE is not set
-# CONFIG_X25 is not set
-# CONFIG_LAPB is not set
-# CONFIG_NET_DIVERT is not set
-# CONFIG_ECONET is not set
-# CONFIG_WAN_ROUTER is not set
-# CONFIG_NET_FASTROUTE is not set
-# CONFIG_NET_HW_FLOWCONTROL is not set
-
-#
-# QoS and/or fair queueing
-#
-# CONFIG_NET_SCHED is not set
-
-#
-# Network testing
-#
-# CONFIG_NET_PKTGEN is not set
-CONFIG_NETDEVICES=y
-# CONFIG_DUMMY is not set
-# CONFIG_BONDING is not set
-# CONFIG_EQUALIZER is not set
-# CONFIG_TUN is not set
-# CONFIG_ETHERTAP is not set
-
-#
-# Ethernet (10 or 100Mbit)
-#
-CONFIG_NET_ETHERNET=y
-# CONFIG_MII is not set
-
-#
-# Ethernet (1000 Mbit)
-#
-
-#
-# Ethernet (10000 Mbit)
-#
-# CONFIG_PPP is not set
-# CONFIG_SLIP is not set
-
-#
-# Wireless LAN (non-hamradio)
-#
-# CONFIG_NET_RADIO is not set
-
-#
-# Token Ring devices (depends on LLC=y)
-#
-# CONFIG_SHAPER is not set
-
-#
-# Wan interfaces
-#
-# CONFIG_WAN is not set
-
-#
-# Amateur Radio support
-#
-# CONFIG_HAMRADIO is not set
-
-#
-# IrDA (infrared) support
-#
-# CONFIG_IRDA is not set
-
-#
-# ISDN subsystem
-#
-# CONFIG_ISDN_BOOL is not set
-
-#
-# Telephony Support
-#
-# CONFIG_PHONE is not set
-
-#
-# Input device support
-#
-CONFIG_INPUT=y
-
-#
-# Userland interfaces
-#
-# CONFIG_INPUT_MOUSEDEV is not set
-# CONFIG_INPUT_JOYDEV is not set
-# CONFIG_INPUT_TSDEV is not set
-# CONFIG_INPUT_EVDEV is not set
-# CONFIG_INPUT_EVBUG is not set
-
-#
-# Input I/O drivers
-#
-# CONFIG_GAMEPORT is not set
-CONFIG_SOUND_GAMEPORT=y
-CONFIG_SERIO=y
-# CONFIG_SERIO_I8042 is not set
-CONFIG_SERIO_SERPORT=y
-# CONFIG_SERIO_CT82C710 is not set
-
-#
-# Input Device Drivers
-#
-# CONFIG_INPUT_KEYBOARD is not set
-# CONFIG_INPUT_MOUSE is not set
-# CONFIG_INPUT_JOYSTICK is not set
-# CONFIG_INPUT_TOUCHSCREEN is not set
-# CONFIG_INPUT_MISC is not set
-
-#
-# Character devices
-#
-# CONFIG_VT is not set
-# CONFIG_SERIAL_NONSTANDARD is not set
-# CONFIG_QTRONIX_KEYBOARD is not set
-# CONFIG_IT8172_SCR0 is not set
-# CONFIG_IT8172_SCR1 is not set
-# CONFIG_ITE_GPIO is not set
-
-#
-# Serial drivers
-#
-CONFIG_SERIAL_8250=y
-CONFIG_SERIAL_8250_CONSOLE=y
-# CONFIG_SERIAL_8250_EXTENDED is not set
-
-#
-# Non-8250 serial port support
-#
-CONFIG_SERIAL_CORE=y
-CONFIG_SERIAL_CORE_CONSOLE=y
-CONFIG_UNIX98_PTYS=y
-CONFIG_UNIX98_PTY_COUNT=256
-
-#
-# I2C support
-#
-# CONFIG_I2C is not set
-
-#
-# I2C Hardware Sensors Mainboard support
-#
-
-#
-# I2C Hardware Sensors Chip support
-#
-# CONFIG_I2C_SENSOR is not set
-
-#
-# Mice
-#
-# CONFIG_BUSMOUSE is not set
-# CONFIG_QIC02_TAPE is not set
-
-#
-# IPMI
-#
-# CONFIG_IPMI_HANDLER is not set
-
-#
-# Watchdog Cards
-#
-# CONFIG_WATCHDOG is not set
-# CONFIG_NVRAM is not set
-# CONFIG_RTC is not set
-# CONFIG_GEN_RTC is not set
-# CONFIG_DTLK is not set
-# CONFIG_R3964 is not set
-# CONFIG_APPLICOM is not set
-
-#
-# Ftape, the floppy tape device driver
-#
-# CONFIG_FTAPE is not set
-# CONFIG_AGP is not set
-# CONFIG_DRM is not set
-# CONFIG_RAW_DRIVER is not set
-# CONFIG_HANGCHECK_TIMER is not set
-
-#
-# Multimedia devices
-#
-# CONFIG_VIDEO_DEV is not set
-
-#
-# Digital Video Broadcasting Devices
-#
-# CONFIG_DVB is not set
-
-#
-# File systems
-#
-CONFIG_EXT2_FS=y
-# CONFIG_EXT2_FS_XATTR is not set
-# CONFIG_EXT3_FS is not set
-# CONFIG_JBD is not set
-# CONFIG_REISERFS_FS is not set
-# CONFIG_JFS_FS is not set
-# CONFIG_XFS_FS is not set
-# CONFIG_MINIX_FS is not set
-# CONFIG_ROMFS_FS is not set
-# CONFIG_QUOTA is not set
-# CONFIG_AUTOFS_FS is not set
-# CONFIG_AUTOFS4_FS is not set
-
-#
-# CD-ROM/DVD Filesystems
-#
-# CONFIG_ISO9660_FS is not set
-# CONFIG_UDF_FS is not set
-
-#
-# DOS/FAT/NT Filesystems
-#
-# CONFIG_FAT_FS is not set
-# CONFIG_NTFS_FS is not set
-
-#
-# Pseudo filesystems
-#
-CONFIG_PROC_FS=y
-# CONFIG_DEVFS_FS is not set
-CONFIG_DEVPTS_FS=y
-CONFIG_DEVPTS_FS_XATTR=y
-CONFIG_DEVPTS_FS_SECURITY=y
-# CONFIG_TMPFS is not set
-CONFIG_RAMFS=y
-
-#
-# Miscellaneous filesystems
-#
-# CONFIG_ADFS_FS is not set
-# CONFIG_AFFS_FS is not set
-# CONFIG_HFS_FS is not set
-# CONFIG_BEFS_FS is not set
-# CONFIG_BFS_FS is not set
-# CONFIG_EFS_FS is not set
-# CONFIG_JFFS_FS is not set
-# CONFIG_JFFS2_FS is not set
-# CONFIG_CRAMFS is not set
-# CONFIG_VXFS_FS is not set
-# CONFIG_HPFS_FS is not set
-# CONFIG_QNX4FS_FS is not set
-# CONFIG_SYSV_FS is not set
-# CONFIG_UFS_FS is not set
-
-#
-# Network File Systems
-#
-CONFIG_NFS_FS=y
-# CONFIG_NFS_V3 is not set
-# CONFIG_NFS_V4 is not set
-# CONFIG_NFSD is not set
-CONFIG_ROOT_NFS=y
-CONFIG_LOCKD=y
-# CONFIG_EXPORTFS is not set
-CONFIG_SUNRPC=y
-# CONFIG_SUNRPC_GSS is not set
-# CONFIG_SMB_FS is not set
-# CONFIG_CIFS is not set
-# CONFIG_NCP_FS is not set
-# CONFIG_CODA_FS is not set
-# CONFIG_INTERMEZZO_FS is not set
-# CONFIG_AFS_FS is not set
-
-#
-# Partition Types
-#
-# CONFIG_PARTITION_ADVANCED is not set
-CONFIG_MSDOS_PARTITION=y
-
-#
-# Graphics support
-#
-
-#
-# Sound
-#
-CONFIG_SOUND=y
-
-#
-# Advanced Linux Sound Architecture
-#
-# CONFIG_SND is not set
-
-#
-# Open Sound System
-#
-CONFIG_SOUND_PRIME=y
-# CONFIG_SOUND_BT878 is not set
-# CONFIG_SOUND_FUSION is not set
-# CONFIG_SOUND_CS4281 is not set
-# CONFIG_SOUND_ESSSOLO1 is not set
-# CONFIG_SOUND_MAESTRO is not set
-# CONFIG_SOUND_SONICVIBES is not set
-CONFIG_SOUND_IT8172=y
-# CONFIG_SOUND_TRIDENT is not set
-# CONFIG_SOUND_MSNDCLAS is not set
-# CONFIG_SOUND_MSNDPIN is not set
-# CONFIG_SOUND_OSS is not set
-# CONFIG_SOUND_AD1980 is not set
-
-#
-# USB support
-#
-# CONFIG_USB_GADGET is not set
-
-#
-# Bluetooth support
-#
-# CONFIG_BT is not set
-
-#
-# Kernel hacking
-#
-CONFIG_CROSSCOMPILE=y
-# CONFIG_DEBUG_KERNEL is not set
-
-#
-# Security options
-#
-# CONFIG_SECURITY is not set
-
-#
-# Cryptographic options
-#
-# CONFIG_CRYPTO is not set
-
-#
-# Library routines
-#
-# CONFIG_CRC32 is not set
--- diff/arch/mips/defconfig-ivr	2003-08-20 14:16:36.000000000 +0100
+++ source/arch/mips/defconfig-ivr	1970-01-01 01:00:00.000000000 +0100
@@ -1,600 +0,0 @@
-#
-# Automatically generated make config: don't edit
-#
-CONFIG_MIPS=y
-# CONFIG_MIPS64 is not set
-CONFIG_MIPS32=y
-
-#
-# Code maturity level options
-#
-CONFIG_EXPERIMENTAL=y
-
-#
-# General setup
-#
-CONFIG_SWAP=y
-CONFIG_SYSVIPC=y
-CONFIG_BSD_PROCESS_ACCT=y
-CONFIG_SYSCTL=y
-CONFIG_LOG_BUF_SHIFT=14
-# CONFIG_EMBEDDED is not set
-CONFIG_KALLSYMS=y
-CONFIG_FUTEX=y
-CONFIG_EPOLL=y
-CONFIG_IOSCHED_AS=y
-CONFIG_IOSCHED_DEADLINE=y
-
-#
-# Loadable module support
-#
-CONFIG_MODULES=y
-CONFIG_MODULE_UNLOAD=y
-# CONFIG_MODULE_FORCE_UNLOAD is not set
-CONFIG_OBSOLETE_MODPARM=y
-CONFIG_MODVERSIONS=y
-CONFIG_KMOD=y
-
-#
-# Machine selection
-#
-# CONFIG_ACER_PICA_61 is not set
-# CONFIG_BAGET_MIPS is not set
-# CONFIG_CASIO_E55 is not set
-# CONFIG_MIPS_COBALT is not set
-# CONFIG_DECSTATION is not set
-# CONFIG_MIPS_EV64120 is not set
-# CONFIG_MIPS_EV96100 is not set
-CONFIG_MIPS_IVR=y
-# CONFIG_LASAT is not set
-# CONFIG_HP_LASERJET is not set
-# CONFIG_IBM_WORKPAD is not set
-# CONFIG_MIPS_ITE8172 is not set
-# CONFIG_MIPS_ATLAS is not set
-# CONFIG_MIPS_MAGNUM_4000 is not set
-# CONFIG_MIPS_MALTA is not set
-# CONFIG_MIPS_SEAD is not set
-# CONFIG_MOMENCO_OCELOT is not set
-# CONFIG_MOMENCO_OCELOT_G is not set
-# CONFIG_MOMENCO_OCELOT_C is not set
-# CONFIG_DDB5074 is not set
-# CONFIG_DDB5476 is not set
-# CONFIG_DDB5477 is not set
-# CONFIG_NEC_OSPREY is not set
-# CONFIG_NEC_EAGLE is not set
-# CONFIG_OLIVETTI_M700 is not set
-# CONFIG_SGI_IP22 is not set
-# CONFIG_SGI_IP32 is not set
-# CONFIG_SOC_AU1X00 is not set
-# CONFIG_SIBYTE_SB1xxx_SOC is not set
-# CONFIG_SNI_RM200_PCI is not set
-# CONFIG_TANBAC_TB0226 is not set
-# CONFIG_TANBAC_TB0229 is not set
-# CONFIG_TOSHIBA_JMR3927 is not set
-# CONFIG_TOSHIBA_RBTX4927 is not set
-# CONFIG_VICTOR_MPC30X is not set
-# CONFIG_ZAO_CAPCELLA is not set
-CONFIG_RWSEM_GENERIC_SPINLOCK=y
-CONFIG_NONCOHERENT_IO=y
-CONFIG_CPU_LITTLE_ENDIAN=y
-CONFIG_ITE_BOARD_GEN=y
-CONFIG_NEW_PCI=y
-CONFIG_IT8172_CIR=y
-# CONFIG_FB is not set
-
-#
-# CPU selection
-#
-# CONFIG_CPU_MIPS32 is not set
-# CONFIG_CPU_MIPS64 is not set
-# CONFIG_CPU_R3000 is not set
-# CONFIG_CPU_TX39XX is not set
-# CONFIG_CPU_VR41XX is not set
-# CONFIG_CPU_R4300 is not set
-# CONFIG_CPU_R4X00 is not set
-# CONFIG_CPU_TX49XX is not set
-# CONFIG_CPU_R5000 is not set
-# CONFIG_CPU_R5432 is not set
-# CONFIG_CPU_R6000 is not set
-CONFIG_CPU_NEVADA=y
-# CONFIG_CPU_R8000 is not set
-# CONFIG_CPU_R10000 is not set
-# CONFIG_CPU_RM7000 is not set
-# CONFIG_CPU_SB1 is not set
-# CONFIG_CPU_ADVANCED is not set
-CONFIG_CPU_HAS_LLSC=y
-CONFIG_CPU_HAS_LLDSCD=y
-CONFIG_CPU_HAS_SYNC=y
-# CONFIG_PREEMPT is not set
-# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
-
-#
-# Bus options (PCI, PCMCIA, EISA, ISA, TC)
-#
-CONFIG_PCI=y
-CONFIG_PCI_LEGACY_PROC=y
-CONFIG_PCI_NAMES=y
-CONFIG_MMU=y
-# CONFIG_HOTPLUG is not set
-
-#
-# Executable file formats
-#
-CONFIG_KCORE_ELF=y
-CONFIG_BINFMT_ELF=y
-# CONFIG_BINFMT_MISC is not set
-CONFIG_TRAD_SIGNALS=y
-
-#
-# Memory Technology Devices (MTD)
-#
-# CONFIG_MTD is not set
-
-#
-# Parallel port support
-#
-# CONFIG_PARPORT is not set
-
-#
-# Plug and Play support
-#
-# CONFIG_PNP is not set
-
-#
-# Generic Driver Options
-#
-# CONFIG_FW_LOADER is not set
-
-#
-# Block devices
-#
-# CONFIG_BLK_DEV_FD is not set
-# CONFIG_BLK_CPQ_DA is not set
-# CONFIG_BLK_CPQ_CISS_DA is not set
-# CONFIG_BLK_DEV_DAC960 is not set
-# CONFIG_BLK_DEV_UMEM is not set
-# CONFIG_BLK_DEV_LOOP is not set
-# CONFIG_BLK_DEV_NBD is not set
-# CONFIG_BLK_DEV_RAM is not set
-# CONFIG_BLK_DEV_INITRD is not set
-# CONFIG_LBD is not set
-
-#
-# ATA/ATAPI/MFM/RLL support
-#
-CONFIG_IDE=y
-
-#
-# IDE, ATA and ATAPI Block devices
-#
-CONFIG_BLK_DEV_IDE=y
-
-#
-# Please see Documentation/ide.txt for help/info on IDE drives
-#
-# CONFIG_BLK_DEV_HD is not set
-CONFIG_BLK_DEV_IDEDISK=y
-# CONFIG_IDEDISK_MULTI_MODE is not set
-# CONFIG_IDEDISK_STROKE is not set
-# CONFIG_BLK_DEV_IDECD is not set
-# CONFIG_BLK_DEV_IDEFLOPPY is not set
-# CONFIG_IDE_TASK_IOCTL is not set
-CONFIG_IDE_TASKFILE_IO=y
-
-#
-# IDE chipset support/bugfixes
-#
-# CONFIG_BLK_DEV_IDEPCI is not set
-
-#
-# SCSI device support
-#
-# CONFIG_SCSI is not set
-
-#
-# Multi-device support (RAID and LVM)
-#
-# CONFIG_MD is not set
-
-#
-# Fusion MPT device support
-#
-
-#
-# IEEE 1394 (FireWire) support (EXPERIMENTAL)
-#
-# CONFIG_IEEE1394 is not set
-
-#
-# I2O device support
-#
-# CONFIG_I2O is not set
-
-#
-# Networking support
-#
-CONFIG_NET=y
-
-#
-# Networking options
-#
-CONFIG_PACKET=y
-CONFIG_PACKET_MMAP=y
-CONFIG_NETLINK_DEV=y
-# CONFIG_NETFILTER is not set
-CONFIG_UNIX=y
-CONFIG_NET_KEY=y
-CONFIG_INET=y
-# CONFIG_IP_MULTICAST is not set
-# CONFIG_IP_ADVANCED_ROUTER is not set
-CONFIG_IP_PNP=y
-# CONFIG_IP_PNP_DHCP is not set
-CONFIG_IP_PNP_BOOTP=y
-# CONFIG_IP_PNP_RARP is not set
-# CONFIG_NET_IPIP is not set
-# CONFIG_NET_IPGRE is not set
-# CONFIG_ARPD is not set
-# CONFIG_INET_ECN is not set
-# CONFIG_SYN_COOKIES is not set
-# CONFIG_INET_AH is not set
-# CONFIG_INET_ESP is not set
-# CONFIG_INET_IPCOMP is not set
-# CONFIG_IPV6 is not set
-# CONFIG_XFRM_USER is not set
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
-CONFIG_IPV6_SCTP__=y
-# CONFIG_IP_SCTP is not set
-# CONFIG_ATM is not set
-# CONFIG_VLAN_8021Q is not set
-# CONFIG_LLC is not set
-# CONFIG_DECNET is not set
-# CONFIG_BRIDGE is not set
-# CONFIG_X25 is not set
-# CONFIG_LAPB is not set
-# CONFIG_NET_DIVERT is not set
-# CONFIG_ECONET is not set
-# CONFIG_WAN_ROUTER is not set
-# CONFIG_NET_FASTROUTE is not set
-# CONFIG_NET_HW_FLOWCONTROL is not set
-
-#
-# QoS and/or fair queueing
-#
-# CONFIG_NET_SCHED is not set
-
-#
-# Network testing
-#
-# CONFIG_NET_PKTGEN is not set
-CONFIG_NETDEVICES=y
-
-#
-# ARCnet devices
-#
-# CONFIG_ARCNET is not set
-# CONFIG_DUMMY is not set
-# CONFIG_BONDING is not set
-# CONFIG_EQUALIZER is not set
-# CONFIG_TUN is not set
-# CONFIG_ETHERTAP is not set
-
-#
-# Ethernet (10 or 100Mbit)
-#
-CONFIG_NET_ETHERNET=y
-# CONFIG_MII is not set
-# CONFIG_HAPPYMEAL is not set
-# CONFIG_SUNGEM is not set
-# CONFIG_NET_VENDOR_3COM is not set
-
-#
-# Tulip family network device support
-#
-# CONFIG_NET_TULIP is not set
-# CONFIG_HP100 is not set
-# CONFIG_NET_PCI is not set
-
-#
-# Ethernet (1000 Mbit)
-#
-# CONFIG_ACENIC is not set
-# CONFIG_DL2K is not set
-# CONFIG_E1000 is not set
-# CONFIG_NS83820 is not set
-# CONFIG_HAMACHI is not set
-# CONFIG_YELLOWFIN is not set
-# CONFIG_R8169 is not set
-# CONFIG_SK98LIN is not set
-# CONFIG_TIGON3 is not set
-
-#
-# Ethernet (10000 Mbit)
-#
-# CONFIG_IXGB is not set
-# CONFIG_FDDI is not set
-# CONFIG_HIPPI is not set
-# CONFIG_PPP is not set
-# CONFIG_SLIP is not set
-
-#
-# Wireless LAN (non-hamradio)
-#
-# CONFIG_NET_RADIO is not set
-
-#
-# Token Ring devices (depends on LLC=y)
-#
-# CONFIG_RCPCI is not set
-# CONFIG_SHAPER is not set
-
-#
-# Wan interfaces
-#
-# CONFIG_WAN is not set
-
-#
-# Amateur Radio support
-#
-# CONFIG_HAMRADIO is not set
-
-#
-# IrDA (infrared) support
-#
-# CONFIG_IRDA is not set
-
-#
-# ISDN subsystem
-#
-# CONFIG_ISDN_BOOL is not set
-
-#
-# Telephony Support
-#
-# CONFIG_PHONE is not set
-
-#
-# Input device support
-#
-CONFIG_INPUT=y
-
-#
-# Userland interfaces
-#
-CONFIG_INPUT_MOUSEDEV=y
-# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
-CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
-CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
-# CONFIG_INPUT_JOYDEV is not set
-# CONFIG_INPUT_TSDEV is not set
-# CONFIG_INPUT_EVDEV is not set
-# CONFIG_INPUT_EVBUG is not set
-
-#
-# Input I/O drivers
-#
-# CONFIG_GAMEPORT is not set
-CONFIG_SOUND_GAMEPORT=y
-CONFIG_SERIO=y
-# CONFIG_SERIO_I8042 is not set
-CONFIG_SERIO_SERPORT=y
-# CONFIG_SERIO_CT82C710 is not set
-# CONFIG_SERIO_PCIPS2 is not set
-
-#
-# Input Device Drivers
-#
-# CONFIG_INPUT_KEYBOARD is not set
-# CONFIG_INPUT_MOUSE is not set
-# CONFIG_INPUT_JOYSTICK is not set
-# CONFIG_INPUT_TOUCHSCREEN is not set
-# CONFIG_INPUT_MISC is not set
-
-#
-# Character devices
-#
-CONFIG_VT=y
-CONFIG_VT_CONSOLE=y
-CONFIG_HW_CONSOLE=y
-# CONFIG_SERIAL_NONSTANDARD is not set
-CONFIG_QTRONIX_KEYBOARD=y
-# CONFIG_IT8172_SCR0 is not set
-
-#
-# Serial drivers
-#
-CONFIG_SERIAL_8250=y
-CONFIG_SERIAL_8250_CONSOLE=y
-# CONFIG_SERIAL_8250_EXTENDED is not set
-
-#
-# Non-8250 serial port support
-#
-CONFIG_SERIAL_CORE=y
-CONFIG_SERIAL_CORE_CONSOLE=y
-CONFIG_UNIX98_PTYS=y
-CONFIG_UNIX98_PTY_COUNT=256
-
-#
-# I2C support
-#
-# CONFIG_I2C is not set
-
-#
-# I2C Hardware Sensors Mainboard support
-#
-
-#
-# I2C Hardware Sensors Chip support
-#
-# CONFIG_I2C_SENSOR is not set
-
-#
-# Mice
-#
-# CONFIG_BUSMOUSE is not set
-# CONFIG_QIC02_TAPE is not set
-
-#
-# IPMI
-#
-# CONFIG_IPMI_HANDLER is not set
-
-#
-# Watchdog Cards
-#
-# CONFIG_WATCHDOG is not set
-# CONFIG_NVRAM is not set
-CONFIG_RTC=y
-# CONFIG_DTLK is not set
-# CONFIG_R3964 is not set
-# CONFIG_APPLICOM is not set
-
-#
-# Ftape, the floppy tape device driver
-#
-# CONFIG_FTAPE is not set
-# CONFIG_AGP is not set
-# CONFIG_DRM is not set
-# CONFIG_RAW_DRIVER is not set
-# CONFIG_HANGCHECK_TIMER is not set
-
-#
-# Multimedia devices
-#
-# CONFIG_VIDEO_DEV is not set
-
-#
-# Digital Video Broadcasting Devices
-#
-# CONFIG_DVB is not set
-
-#
-# File systems
-#
-CONFIG_EXT2_FS=y
-# CONFIG_EXT2_FS_XATTR is not set
-# CONFIG_EXT3_FS is not set
-# CONFIG_JBD is not set
-# CONFIG_REISERFS_FS is not set
-# CONFIG_JFS_FS is not set
-# CONFIG_XFS_FS is not set
-# CONFIG_MINIX_FS is not set
-# CONFIG_ROMFS_FS is not set
-# CONFIG_QUOTA is not set
-# CONFIG_AUTOFS_FS is not set
-# CONFIG_AUTOFS4_FS is not set
-
-#
-# CD-ROM/DVD Filesystems
-#
-# CONFIG_ISO9660_FS is not set
-# CONFIG_UDF_FS is not set
-
-#
-# DOS/FAT/NT Filesystems
-#
-# CONFIG_FAT_FS is not set
-# CONFIG_NTFS_FS is not set
-
-#
-# Pseudo filesystems
-#
-CONFIG_PROC_FS=y
-# CONFIG_DEVFS_FS is not set
-CONFIG_DEVPTS_FS=y
-CONFIG_DEVPTS_FS_XATTR=y
-CONFIG_DEVPTS_FS_SECURITY=y
-# CONFIG_TMPFS is not set
-CONFIG_RAMFS=y
-
-#
-# Miscellaneous filesystems
-#
-# CONFIG_ADFS_FS is not set
-# CONFIG_AFFS_FS is not set
-# CONFIG_HFS_FS is not set
-# CONFIG_BEFS_FS is not set
-# CONFIG_BFS_FS is not set
-# CONFIG_EFS_FS is not set
-# CONFIG_CRAMFS is not set
-# CONFIG_VXFS_FS is not set
-# CONFIG_HPFS_FS is not set
-# CONFIG_QNX4FS_FS is not set
-# CONFIG_SYSV_FS is not set
-# CONFIG_UFS_FS is not set
-
-#
-# Network File Systems
-#
-CONFIG_NFS_FS=y
-# CONFIG_NFS_V3 is not set
-# CONFIG_NFS_V4 is not set
-# CONFIG_NFSD is not set
-CONFIG_ROOT_NFS=y
-CONFIG_LOCKD=y
-# CONFIG_EXPORTFS is not set
-CONFIG_SUNRPC=y
-# CONFIG_SUNRPC_GSS is not set
-# CONFIG_SMB_FS is not set
-# CONFIG_CIFS is not set
-# CONFIG_NCP_FS is not set
-# CONFIG_CODA_FS is not set
-# CONFIG_INTERMEZZO_FS is not set
-# CONFIG_AFS_FS is not set
-
-#
-# Partition Types
-#
-# CONFIG_PARTITION_ADVANCED is not set
-CONFIG_MSDOS_PARTITION=y
-
-#
-# Graphics support
-#
-
-#
-# Console display driver support
-#
-# CONFIG_VGA_CONSOLE is not set
-# CONFIG_MDA_CONSOLE is not set
-CONFIG_DUMMY_CONSOLE=y
-
-#
-# Sound
-#
-# CONFIG_SOUND is not set
-
-#
-# USB support
-#
-# CONFIG_USB is not set
-# CONFIG_USB_GADGET is not set
-
-#
-# Bluetooth support
-#
-# CONFIG_BT is not set
-
-#
-# Kernel hacking
-#
-CONFIG_CROSSCOMPILE=y
-# CONFIG_DEBUG_KERNEL is not set
-
-#
-# Security options
-#
-# CONFIG_SECURITY is not set
-
-#
-# Cryptographic options
-#
-# CONFIG_CRYPTO is not set
-
-#
-# Library routines
-#
-# CONFIG_CRC32 is not set
--- diff/arch/mips/defconfig-jmr3927	2003-08-20 14:16:25.000000000 +0100
+++ source/arch/mips/defconfig-jmr3927	1970-01-01 01:00:00.000000000 +0100
@@ -1,602 +0,0 @@
-#
-# Automatically generated make config: don't edit
-#
-CONFIG_MIPS=y
-# CONFIG_MIPS64 is not set
-CONFIG_MIPS32=y
-
-#
-# Code maturity level options
-#
-CONFIG_EXPERIMENTAL=y
-
-#
-# General setup
-#
-CONFIG_SWAP=y
-CONFIG_SYSVIPC=y
-# CONFIG_BSD_PROCESS_ACCT is not set
-CONFIG_SYSCTL=y
-CONFIG_LOG_BUF_SHIFT=14
-# CONFIG_EMBEDDED is not set
-CONFIG_KALLSYMS=y
-CONFIG_FUTEX=y
-CONFIG_EPOLL=y
-CONFIG_IOSCHED_AS=y
-CONFIG_IOSCHED_DEADLINE=y
-
-#
-# Loadable module support
-#
-# CONFIG_MODULES is not set
-
-#
-# Machine selection
-#
-# CONFIG_ACER_PICA_61 is not set
-# CONFIG_BAGET_MIPS is not set
-# CONFIG_CASIO_E55 is not set
-# CONFIG_MIPS_COBALT is not set
-# CONFIG_DECSTATION is not set
-# CONFIG_MIPS_EV64120 is not set
-# CONFIG_MIPS_EV96100 is not set
-# CONFIG_MIPS_IVR is not set
-# CONFIG_LASAT is not set
-# CONFIG_HP_LASERJET is not set
-# CONFIG_IBM_WORKPAD is not set
-# CONFIG_MIPS_ITE8172 is not set
-# CONFIG_MIPS_ATLAS is not set
-# CONFIG_MIPS_MAGNUM_4000 is not set
-# CONFIG_MIPS_MALTA is not set
-# CONFIG_MIPS_SEAD is not set
-# CONFIG_MOMENCO_OCELOT is not set
-# CONFIG_MOMENCO_OCELOT_G is not set
-# CONFIG_MOMENCO_OCELOT_C is not set
-# CONFIG_DDB5074 is not set
-# CONFIG_DDB5476 is not set
-# CONFIG_DDB5477 is not set
-# CONFIG_NEC_OSPREY is not set
-# CONFIG_NEC_EAGLE is not set
-# CONFIG_OLIVETTI_M700 is not set
-# CONFIG_SGI_IP22 is not set
-# CONFIG_SGI_IP32 is not set
-# CONFIG_SOC_AU1X00 is not set
-# CONFIG_SIBYTE_SB1xxx_SOC is not set
-# CONFIG_SNI_RM200_PCI is not set
-# CONFIG_TANBAC_TB0226 is not set
-# CONFIG_TANBAC_TB0229 is not set
-CONFIG_TOSHIBA_JMR3927=y
-# CONFIG_TOSHIBA_RBTX4927 is not set
-# CONFIG_VICTOR_MPC30X is not set
-# CONFIG_ZAO_CAPCELLA is not set
-CONFIG_RWSEM_GENERIC_SPINLOCK=y
-CONFIG_NONCOHERENT_IO=y
-# CONFIG_CPU_LITTLE_ENDIAN is not set
-CONFIG_NEW_PCI=y
-CONFIG_SWAP_IO_SPACE=y
-CONFIG_FB=y
-CONFIG_TOSHIBA_BOARDS=y
-
-#
-# CPU selection
-#
-# CONFIG_CPU_MIPS32 is not set
-# CONFIG_CPU_MIPS64 is not set
-# CONFIG_CPU_R3000 is not set
-CONFIG_CPU_TX39XX=y
-# CONFIG_CPU_VR41XX is not set
-# CONFIG_CPU_R4300 is not set
-# CONFIG_CPU_R4X00 is not set
-# CONFIG_CPU_TX49XX is not set
-# CONFIG_CPU_R5000 is not set
-# CONFIG_CPU_R5432 is not set
-# CONFIG_CPU_R6000 is not set
-# CONFIG_CPU_NEVADA is not set
-# CONFIG_CPU_R8000 is not set
-# CONFIG_CPU_R10000 is not set
-# CONFIG_CPU_RM7000 is not set
-# CONFIG_CPU_SB1 is not set
-# CONFIG_CPU_ADVANCED is not set
-CONFIG_CPU_HAS_SYNC=y
-# CONFIG_PREEMPT is not set
-# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
-CONFIG_RTC_DS1742=y
-
-#
-# Bus options (PCI, PCMCIA, EISA, ISA, TC)
-#
-CONFIG_PCI=y
-CONFIG_PCI_LEGACY_PROC=y
-CONFIG_PCI_NAMES=y
-CONFIG_MMU=y
-# CONFIG_HOTPLUG is not set
-
-#
-# Executable file formats
-#
-CONFIG_KCORE_ELF=y
-CONFIG_BINFMT_ELF=y
-# CONFIG_BINFMT_MISC is not set
-CONFIG_TRAD_SIGNALS=y
-# CONFIG_BINFMT_IRIX is not set
-
-#
-# Memory Technology Devices (MTD)
-#
-# CONFIG_MTD is not set
-
-#
-# Parallel port support
-#
-# CONFIG_PARPORT is not set
-
-#
-# Plug and Play support
-#
-# CONFIG_PNP is not set
-
-#
-# Generic Driver Options
-#
-# CONFIG_FW_LOADER is not set
-
-#
-# Block devices
-#
-# CONFIG_BLK_DEV_FD is not set
-# CONFIG_BLK_CPQ_DA is not set
-# CONFIG_BLK_CPQ_CISS_DA is not set
-# CONFIG_BLK_DEV_DAC960 is not set
-# CONFIG_BLK_DEV_UMEM is not set
-# CONFIG_BLK_DEV_LOOP is not set
-# CONFIG_BLK_DEV_NBD is not set
-# CONFIG_BLK_DEV_RAM is not set
-# CONFIG_BLK_DEV_INITRD is not set
-# CONFIG_LBD is not set
-
-#
-# ATA/ATAPI/MFM/RLL support
-#
-# CONFIG_IDE is not set
-
-#
-# SCSI device support
-#
-# CONFIG_SCSI is not set
-
-#
-# Multi-device support (RAID and LVM)
-#
-# CONFIG_MD is not set
-
-#
-# Fusion MPT device support
-#
-
-#
-# IEEE 1394 (FireWire) support (EXPERIMENTAL)
-#
-# CONFIG_IEEE1394 is not set
-
-#
-# I2O device support
-#
-# CONFIG_I2O is not set
-
-#
-# Networking support
-#
-CONFIG_NET=y
-
-#
-# Networking options
-#
-CONFIG_PACKET=y
-# CONFIG_PACKET_MMAP is not set
-CONFIG_NETLINK_DEV=y
-# CONFIG_NETFILTER is not set
-CONFIG_UNIX=y
-CONFIG_NET_KEY=y
-CONFIG_INET=y
-# CONFIG_IP_MULTICAST is not set
-# CONFIG_IP_ADVANCED_ROUTER is not set
-CONFIG_IP_PNP=y
-# CONFIG_IP_PNP_DHCP is not set
-CONFIG_IP_PNP_BOOTP=y
-# CONFIG_IP_PNP_RARP is not set
-# CONFIG_NET_IPIP is not set
-# CONFIG_NET_IPGRE is not set
-# CONFIG_ARPD is not set
-# CONFIG_INET_ECN is not set
-# CONFIG_SYN_COOKIES is not set
-# CONFIG_INET_AH is not set
-# CONFIG_INET_ESP is not set
-# CONFIG_INET_IPCOMP is not set
-# CONFIG_IPV6 is not set
-# CONFIG_XFRM_USER is not set
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
-CONFIG_IPV6_SCTP__=y
-# CONFIG_IP_SCTP is not set
-# CONFIG_ATM is not set
-# CONFIG_VLAN_8021Q is not set
-# CONFIG_LLC is not set
-# CONFIG_DECNET is not set
-# CONFIG_BRIDGE is not set
-# CONFIG_X25 is not set
-# CONFIG_LAPB is not set
-# CONFIG_NET_DIVERT is not set
-# CONFIG_ECONET is not set
-# CONFIG_WAN_ROUTER is not set
-# CONFIG_NET_FASTROUTE is not set
-# CONFIG_NET_HW_FLOWCONTROL is not set
-
-#
-# QoS and/or fair queueing
-#
-# CONFIG_NET_SCHED is not set
-
-#
-# Network testing
-#
-# CONFIG_NET_PKTGEN is not set
-CONFIG_NETDEVICES=y
-
-#
-# ARCnet devices
-#
-# CONFIG_ARCNET is not set
-# CONFIG_DUMMY is not set
-# CONFIG_BONDING is not set
-# CONFIG_EQUALIZER is not set
-# CONFIG_TUN is not set
-# CONFIG_ETHERTAP is not set
-
-#
-# Ethernet (10 or 100Mbit)
-#
-CONFIG_NET_ETHERNET=y
-# CONFIG_MII is not set
-# CONFIG_HAPPYMEAL is not set
-# CONFIG_SUNGEM is not set
-# CONFIG_NET_VENDOR_3COM is not set
-
-#
-# Tulip family network device support
-#
-# CONFIG_NET_TULIP is not set
-# CONFIG_HP100 is not set
-# CONFIG_NET_PCI is not set
-
-#
-# Ethernet (1000 Mbit)
-#
-# CONFIG_ACENIC is not set
-# CONFIG_DL2K is not set
-# CONFIG_E1000 is not set
-# CONFIG_NS83820 is not set
-# CONFIG_HAMACHI is not set
-# CONFIG_YELLOWFIN is not set
-# CONFIG_R8169 is not set
-# CONFIG_SK98LIN is not set
-# CONFIG_TIGON3 is not set
-
-#
-# Ethernet (10000 Mbit)
-#
-# CONFIG_IXGB is not set
-# CONFIG_FDDI is not set
-# CONFIG_HIPPI is not set
-# CONFIG_PPP is not set
-# CONFIG_SLIP is not set
-
-#
-# Wireless LAN (non-hamradio)
-#
-# CONFIG_NET_RADIO is not set
-
-#
-# Token Ring devices (depends on LLC=y)
-#
-# CONFIG_RCPCI is not set
-# CONFIG_SHAPER is not set
-
-#
-# Wan interfaces
-#
-# CONFIG_WAN is not set
-
-#
-# Amateur Radio support
-#
-# CONFIG_HAMRADIO is not set
-
-#
-# IrDA (infrared) support
-#
-# CONFIG_IRDA is not set
-
-#
-# ISDN subsystem
-#
-# CONFIG_ISDN_BOOL is not set
-
-#
-# Telephony Support
-#
-# CONFIG_PHONE is not set
-
-#
-# Input device support
-#
-CONFIG_INPUT=y
-
-#
-# Userland interfaces
-#
-# CONFIG_INPUT_MOUSEDEV is not set
-# CONFIG_INPUT_JOYDEV is not set
-# CONFIG_INPUT_TSDEV is not set
-# CONFIG_INPUT_EVDEV is not set
-# CONFIG_INPUT_EVBUG is not set
-
-#
-# Input I/O drivers
-#
-# CONFIG_GAMEPORT is not set
-CONFIG_SOUND_GAMEPORT=y
-CONFIG_SERIO=y
-# CONFIG_SERIO_I8042 is not set
-CONFIG_SERIO_SERPORT=y
-# CONFIG_SERIO_CT82C710 is not set
-# CONFIG_SERIO_PCIPS2 is not set
-
-#
-# Input Device Drivers
-#
-# CONFIG_INPUT_KEYBOARD is not set
-# CONFIG_INPUT_MOUSE is not set
-# CONFIG_INPUT_JOYSTICK is not set
-# CONFIG_INPUT_TOUCHSCREEN is not set
-# CONFIG_INPUT_MISC is not set
-
-#
-# Character devices
-#
-CONFIG_VT=y
-# CONFIG_VT_CONSOLE is not set
-CONFIG_HW_CONSOLE=y
-CONFIG_SERIAL_NONSTANDARD=y
-# CONFIG_COMPUTONE is not set
-# CONFIG_ROCKETPORT is not set
-# CONFIG_CYCLADES is not set
-# CONFIG_DIGIEPCA is not set
-# CONFIG_DIGI is not set
-# CONFIG_MOXA_INTELLIO is not set
-# CONFIG_MOXA_SMARTIO is not set
-# CONFIG_SYNCLINK is not set
-# CONFIG_SYNCLINKMP is not set
-# CONFIG_N_HDLC is not set
-# CONFIG_RISCOM8 is not set
-# CONFIG_SPECIALIX is not set
-# CONFIG_SX is not set
-# CONFIG_RIO is not set
-# CONFIG_STALDRV is not set
-# CONFIG_SERIAL_TX3912 is not set
-CONFIG_TXX927_SERIAL=y
-CONFIG_TXX927_SERIAL_CONSOLE=y
-# CONFIG_SERIAL_TXX9 is not set
-
-#
-# Serial drivers
-#
-# CONFIG_SERIAL_8250 is not set
-
-#
-# Non-8250 serial port support
-#
-# CONFIG_UNIX98_PTYS is not set
-
-#
-# I2C support
-#
-# CONFIG_I2C is not set
-
-#
-# I2C Hardware Sensors Mainboard support
-#
-
-#
-# I2C Hardware Sensors Chip support
-#
-# CONFIG_I2C_SENSOR is not set
-
-#
-# Mice
-#
-# CONFIG_BUSMOUSE is not set
-# CONFIG_QIC02_TAPE is not set
-
-#
-# IPMI
-#
-# CONFIG_IPMI_HANDLER is not set
-
-#
-# Watchdog Cards
-#
-# CONFIG_WATCHDOG is not set
-# CONFIG_NVRAM is not set
-# CONFIG_RTC is not set
-# CONFIG_GEN_RTC is not set
-# CONFIG_DTLK is not set
-# CONFIG_R3964 is not set
-# CONFIG_APPLICOM is not set
-
-#
-# Ftape, the floppy tape device driver
-#
-# CONFIG_FTAPE is not set
-# CONFIG_AGP is not set
-# CONFIG_DRM is not set
-# CONFIG_RAW_DRIVER is not set
-# CONFIG_HANGCHECK_TIMER is not set
-
-#
-# Multimedia devices
-#
-# CONFIG_VIDEO_DEV is not set
-
-#
-# Digital Video Broadcasting Devices
-#
-# CONFIG_DVB is not set
-
-#
-# File systems
-#
-# CONFIG_EXT2_FS is not set
-# CONFIG_EXT3_FS is not set
-# CONFIG_JBD is not set
-# CONFIG_REISERFS_FS is not set
-# CONFIG_JFS_FS is not set
-# CONFIG_XFS_FS is not set
-# CONFIG_MINIX_FS is not set
-# CONFIG_ROMFS_FS is not set
-# CONFIG_QUOTA is not set
-# CONFIG_AUTOFS_FS is not set
-# CONFIG_AUTOFS4_FS is not set
-
-#
-# CD-ROM/DVD Filesystems
-#
-# CONFIG_ISO9660_FS is not set
-# CONFIG_UDF_FS is not set
-
-#
-# DOS/FAT/NT Filesystems
-#
-# CONFIG_FAT_FS is not set
-# CONFIG_NTFS_FS is not set
-
-#
-# Pseudo filesystems
-#
-CONFIG_PROC_FS=y
-# CONFIG_DEVFS_FS is not set
-# CONFIG_TMPFS is not set
-CONFIG_RAMFS=y
-
-#
-# Miscellaneous filesystems
-#
-# CONFIG_ADFS_FS is not set
-# CONFIG_AFFS_FS is not set
-# CONFIG_HFS_FS is not set
-# CONFIG_BEFS_FS is not set
-# CONFIG_BFS_FS is not set
-# CONFIG_EFS_FS is not set
-# CONFIG_CRAMFS is not set
-# CONFIG_VXFS_FS is not set
-# CONFIG_HPFS_FS is not set
-# CONFIG_QNX4FS_FS is not set
-# CONFIG_SYSV_FS is not set
-# CONFIG_UFS_FS is not set
-
-#
-# Network File Systems
-#
-CONFIG_NFS_FS=y
-# CONFIG_NFS_V3 is not set
-# CONFIG_NFS_V4 is not set
-# CONFIG_NFSD is not set
-CONFIG_ROOT_NFS=y
-CONFIG_LOCKD=y
-# CONFIG_EXPORTFS is not set
-CONFIG_SUNRPC=y
-# CONFIG_SUNRPC_GSS is not set
-# CONFIG_SMB_FS is not set
-# CONFIG_CIFS is not set
-# CONFIG_NCP_FS is not set
-# CONFIG_CODA_FS is not set
-# CONFIG_INTERMEZZO_FS is not set
-# CONFIG_AFS_FS is not set
-
-#
-# Partition Types
-#
-# CONFIG_PARTITION_ADVANCED is not set
-CONFIG_MSDOS_PARTITION=y
-
-#
-# Graphics support
-#
-# CONFIG_FB_CIRRUS is not set
-# CONFIG_FB_PM2 is not set
-# CONFIG_FB_CYBER2000 is not set
-# CONFIG_FB_IMSTT is not set
-# CONFIG_FB_RIVA is not set
-# CONFIG_FB_MATROX is not set
-# CONFIG_FB_RADEON is not set
-# CONFIG_FB_ATY128 is not set
-# CONFIG_FB_ATY is not set
-# CONFIG_FB_SIS is not set
-# CONFIG_FB_NEOMAGIC is not set
-# CONFIG_FB_3DFX is not set
-# CONFIG_FB_VOODOO1 is not set
-# CONFIG_FB_TRIDENT is not set
-# CONFIG_FB_PM3 is not set
-# CONFIG_FB_E1356 is not set
-# CONFIG_FB_VIRTUAL is not set
-
-#
-# Console display driver support
-#
-# CONFIG_VGA_CONSOLE is not set
-# CONFIG_MDA_CONSOLE is not set
-CONFIG_DUMMY_CONSOLE=y
-# CONFIG_FRAMEBUFFER_CONSOLE is not set
-
-#
-# Logo configuration
-#
-# CONFIG_LOGO is not set
-
-#
-# Sound
-#
-# CONFIG_SOUND is not set
-
-#
-# USB support
-#
-# CONFIG_USB is not set
-# CONFIG_USB_GADGET is not set
-
-#
-# Bluetooth support
-#
-# CONFIG_BT is not set
-
-#
-# Kernel hacking
-#
-CONFIG_CROSSCOMPILE=y
-# CONFIG_DEBUG_KERNEL is not set
-
-#
-# Security options
-#
-# CONFIG_SECURITY is not set
-
-#
-# Cryptographic options
-#
-# CONFIG_CRYPTO is not set
-
-#
-# Library routines
-#
-# CONFIG_CRC32 is not set
--- diff/arch/mips/defconfig-lasat200	2004-02-18 08:54:07.000000000 +0000
+++ source/arch/mips/defconfig-lasat200	1970-01-01 01:00:00.000000000 +0100
@@ -1,678 +0,0 @@
-#
-# Automatically generated make config: don't edit
-#
-CONFIG_MIPS=y
-# CONFIG_MIPS64 is not set
-CONFIG_MIPS32=y
-
-#
-# Code maturity level options
-#
-CONFIG_EXPERIMENTAL=y
-
-#
-# General setup
-#
-CONFIG_SWAP=y
-CONFIG_SYSVIPC=y
-# CONFIG_BSD_PROCESS_ACCT is not set
-CONFIG_SYSCTL=y
-CONFIG_LOG_BUF_SHIFT=14
-# CONFIG_EMBEDDED is not set
-CONFIG_KALLSYMS=y
-CONFIG_FUTEX=y
-CONFIG_EPOLL=y
-CONFIG_IOSCHED_AS=y
-CONFIG_IOSCHED_DEADLINE=y
-
-#
-# Loadable module support
-#
-CONFIG_MODULES=y
-CONFIG_MODULE_UNLOAD=y
-# CONFIG_MODULE_FORCE_UNLOAD is not set
-CONFIG_OBSOLETE_MODPARM=y
-CONFIG_MODVERSIONS=y
-CONFIG_KMOD=y
-
-#
-# Machine selection
-#
-# CONFIG_ACER_PICA_61 is not set
-# CONFIG_BAGET_MIPS is not set
-# CONFIG_CASIO_E55 is not set
-# CONFIG_MIPS_COBALT is not set
-# CONFIG_DECSTATION is not set
-# CONFIG_MIPS_EV64120 is not set
-# CONFIG_MIPS_EV96100 is not set
-# CONFIG_MIPS_IVR is not set
-CONFIG_LASAT=y
-CONFIG_PICVUE=y
-CONFIG_PICVUE_PROC=y
-CONFIG_DS1603=y
-CONFIG_LASAT_SYSCTL=y
-# CONFIG_HP_LASERJET is not set
-# CONFIG_IBM_WORKPAD is not set
-# CONFIG_MIPS_ITE8172 is not set
-# CONFIG_MIPS_ATLAS is not set
-# CONFIG_MIPS_MAGNUM_4000 is not set
-# CONFIG_MIPS_MALTA is not set
-# CONFIG_MIPS_SEAD is not set
-# CONFIG_MOMENCO_OCELOT is not set
-# CONFIG_MOMENCO_OCELOT_G is not set
-# CONFIG_MOMENCO_OCELOT_C is not set
-# CONFIG_DDB5074 is not set
-# CONFIG_DDB5476 is not set
-# CONFIG_DDB5477 is not set
-# CONFIG_NEC_OSPREY is not set
-# CONFIG_NEC_EAGLE is not set
-# CONFIG_OLIVETTI_M700 is not set
-# CONFIG_SGI_IP22 is not set
-# CONFIG_SGI_IP32 is not set
-# CONFIG_SOC_AU1X00 is not set
-# CONFIG_SIBYTE_SB1xxx_SOC is not set
-# CONFIG_SNI_RM200_PCI is not set
-# CONFIG_TANBAC_TB0226 is not set
-# CONFIG_TANBAC_TB0229 is not set
-# CONFIG_TOSHIBA_JMR3927 is not set
-# CONFIG_TOSHIBA_RBTX4927 is not set
-# CONFIG_VICTOR_MPC30X is not set
-# CONFIG_ZAO_CAPCELLA is not set
-CONFIG_RWSEM_GENERIC_SPINLOCK=y
-CONFIG_NONCOHERENT_IO=y
-CONFIG_CPU_LITTLE_ENDIAN=y
-# CONFIG_FB is not set
-CONFIG_BOARD_SCACHE=y
-
-#
-# CPU selection
-#
-# CONFIG_CPU_MIPS32 is not set
-# CONFIG_CPU_MIPS64 is not set
-# CONFIG_CPU_R3000 is not set
-# CONFIG_CPU_TX39XX is not set
-# CONFIG_CPU_VR41XX is not set
-# CONFIG_CPU_R4300 is not set
-# CONFIG_CPU_R4X00 is not set
-# CONFIG_CPU_TX49XX is not set
-CONFIG_CPU_R5000=y
-# CONFIG_CPU_R5432 is not set
-# CONFIG_CPU_R6000 is not set
-# CONFIG_CPU_NEVADA is not set
-# CONFIG_CPU_R8000 is not set
-# CONFIG_CPU_R10000 is not set
-# CONFIG_CPU_RM7000 is not set
-# CONFIG_CPU_SB1 is not set
-CONFIG_R5000_CPU_SCACHE=y
-# CONFIG_64BIT_PHYS_ADDR is not set
-# CONFIG_CPU_ADVANCED is not set
-CONFIG_CPU_HAS_LLSC=y
-CONFIG_CPU_HAS_LLDSCD=y
-CONFIG_CPU_HAS_SYNC=y
-# CONFIG_PREEMPT is not set
-# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
-
-#
-# Bus options (PCI, PCMCIA, EISA, ISA, TC)
-#
-CONFIG_PCI=y
-CONFIG_PCI_LEGACY_PROC=y
-# CONFIG_PCI_NAMES is not set
-CONFIG_MMU=y
-# CONFIG_HOTPLUG is not set
-
-#
-# Executable file formats
-#
-CONFIG_KCORE_ELF=y
-CONFIG_BINFMT_ELF=y
-# CONFIG_BINFMT_MISC is not set
-CONFIG_TRAD_SIGNALS=y
-
-#
-# Memory Technology Devices (MTD)
-#
-CONFIG_MTD=y
-# CONFIG_MTD_DEBUG is not set
-CONFIG_MTD_PARTITIONS=y
-# CONFIG_MTD_CONCAT is not set
-# CONFIG_MTD_REDBOOT_PARTS is not set
-# CONFIG_MTD_CMDLINE_PARTS is not set
-
-#
-# User Modules And Translation Layers
-#
-CONFIG_MTD_CHAR=y
-CONFIG_MTD_BLOCK=y
-# CONFIG_FTL is not set
-# CONFIG_NFTL is not set
-# CONFIG_INFTL is not set
-
-#
-# RAM/ROM/Flash chip drivers
-#
-CONFIG_MTD_CFI=y
-# CONFIG_MTD_JEDECPROBE is not set
-CONFIG_MTD_GEN_PROBE=y
-# CONFIG_MTD_CFI_ADV_OPTIONS is not set
-# CONFIG_MTD_CFI_INTELEXT is not set
-CONFIG_MTD_CFI_AMDSTD=y
-# CONFIG_MTD_CFI_STAA is not set
-# CONFIG_MTD_RAM is not set
-# CONFIG_MTD_ROM is not set
-# CONFIG_MTD_ABSENT is not set
-# CONFIG_MTD_OBSOLETE_CHIPS is not set
-
-#
-# Mapping drivers for chip access
-#
-# CONFIG_MTD_COMPLEX_MAPPINGS is not set
-# CONFIG_MTD_PHYSMAP is not set
-CONFIG_MTD_LASAT=y
-
-#
-# Self-contained MTD device drivers
-#
-# CONFIG_MTD_PMC551 is not set
-# CONFIG_MTD_SLRAM is not set
-# CONFIG_MTD_MTDRAM is not set
-# CONFIG_MTD_BLKMTD is not set
-
-#
-# Disk-On-Chip Device Drivers
-#
-# CONFIG_MTD_DOC2000 is not set
-# CONFIG_MTD_DOC2001 is not set
-# CONFIG_MTD_DOC2001PLUS is not set
-
-#
-# NAND Flash Device Drivers
-#
-# CONFIG_MTD_NAND is not set
-
-#
-# Parallel port support
-#
-# CONFIG_PARPORT is not set
-
-#
-# Plug and Play support
-#
-# CONFIG_PNP is not set
-
-#
-# Generic Driver Options
-#
-# CONFIG_FW_LOADER is not set
-
-#
-# Block devices
-#
-# CONFIG_BLK_DEV_FD is not set
-# CONFIG_BLK_CPQ_DA is not set
-# CONFIG_BLK_CPQ_CISS_DA is not set
-# CONFIG_BLK_DEV_DAC960 is not set
-# CONFIG_BLK_DEV_UMEM is not set
-# CONFIG_BLK_DEV_LOOP is not set
-# CONFIG_BLK_DEV_NBD is not set
-# CONFIG_BLK_DEV_RAM is not set
-# CONFIG_BLK_DEV_INITRD is not set
-# CONFIG_LBD is not set
-
-#
-# ATA/ATAPI/MFM/RLL support
-#
-CONFIG_IDE=y
-
-#
-# IDE, ATA and ATAPI Block devices
-#
-CONFIG_BLK_DEV_IDE=y
-
-#
-# Please see Documentation/ide.txt for help/info on IDE drives
-#
-# CONFIG_BLK_DEV_HD is not set
-CONFIG_BLK_DEV_IDEDISK=y
-CONFIG_IDEDISK_MULTI_MODE=y
-# CONFIG_IDEDISK_STROKE is not set
-# CONFIG_BLK_DEV_IDECD is not set
-# CONFIG_BLK_DEV_IDEFLOPPY is not set
-# CONFIG_IDE_TASK_IOCTL is not set
-CONFIG_IDE_TASKFILE_IO=y
-
-#
-# IDE chipset support/bugfixes
-#
-CONFIG_BLK_DEV_IDEPCI=y
-CONFIG_BLK_DEV_GENERIC=y
-# CONFIG_IDEPCI_SHARE_IRQ is not set
-CONFIG_BLK_DEV_IDEDMA_PCI=y
-# CONFIG_BLK_DEV_IDE_TCQ is not set
-# CONFIG_BLK_DEV_OFFBOARD is not set
-# CONFIG_BLK_DEV_IDEDMA_FORCED is not set
-CONFIG_IDEDMA_PCI_AUTO=y
-# CONFIG_IDEDMA_ONLYDISK is not set
-CONFIG_BLK_DEV_IDEDMA=y
-CONFIG_BLK_DEV_ADMA=y
-# CONFIG_BLK_DEV_AEC62XX is not set
-# CONFIG_BLK_DEV_ALI15X3 is not set
-# CONFIG_BLK_DEV_AMD74XX is not set
-CONFIG_BLK_DEV_CMD64X=y
-# CONFIG_BLK_DEV_TRIFLEX is not set
-# CONFIG_BLK_DEV_CY82C693 is not set
-# CONFIG_BLK_DEV_CS5520 is not set
-# CONFIG_BLK_DEV_HPT34X is not set
-# CONFIG_BLK_DEV_HPT366 is not set
-# CONFIG_BLK_DEV_SC1200 is not set
-# CONFIG_BLK_DEV_PIIX is not set
-# CONFIG_BLK_DEV_NS87415 is not set
-# CONFIG_BLK_DEV_OPTI621 is not set
-# CONFIG_BLK_DEV_PDC202XX_OLD is not set
-# CONFIG_BLK_DEV_PDC202XX_NEW is not set
-# CONFIG_BLK_DEV_SVWKS is not set
-# CONFIG_BLK_DEV_SIIMAGE is not set
-# CONFIG_BLK_DEV_SLC90E66 is not set
-# CONFIG_BLK_DEV_TRM290 is not set
-# CONFIG_BLK_DEV_VIA82CXXX is not set
-CONFIG_IDEDMA_AUTO=y
-# CONFIG_IDEDMA_IVB is not set
-
-#
-# SCSI device support
-#
-# CONFIG_SCSI is not set
-
-#
-# Multi-device support (RAID and LVM)
-#
-# CONFIG_MD is not set
-
-#
-# Fusion MPT device support
-#
-
-#
-# IEEE 1394 (FireWire) support (EXPERIMENTAL)
-#
-# CONFIG_IEEE1394 is not set
-
-#
-# I2O device support
-#
-# CONFIG_I2O is not set
-
-#
-# Networking support
-#
-CONFIG_NET=y
-
-#
-# Networking options
-#
-# CONFIG_PACKET is not set
-# CONFIG_NETLINK_DEV is not set
-# CONFIG_NETFILTER is not set
-CONFIG_UNIX=y
-CONFIG_NET_KEY=y
-CONFIG_INET=y
-# CONFIG_IP_MULTICAST is not set
-# CONFIG_IP_ADVANCED_ROUTER is not set
-# CONFIG_IP_PNP is not set
-# CONFIG_NET_IPIP is not set
-# CONFIG_NET_IPGRE is not set
-# CONFIG_ARPD is not set
-# CONFIG_INET_ECN is not set
-# CONFIG_SYN_COOKIES is not set
-# CONFIG_INET_AH is not set
-# CONFIG_INET_ESP is not set
-# CONFIG_INET_IPCOMP is not set
-# CONFIG_IPV6 is not set
-# CONFIG_XFRM_USER is not set
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
-CONFIG_IPV6_SCTP__=y
-# CONFIG_IP_SCTP is not set
-# CONFIG_ATM is not set
-# CONFIG_VLAN_8021Q is not set
-# CONFIG_LLC is not set
-# CONFIG_DECNET is not set
-# CONFIG_BRIDGE is not set
-# CONFIG_X25 is not set
-# CONFIG_LAPB is not set
-# CONFIG_NET_DIVERT is not set
-# CONFIG_ECONET is not set
-# CONFIG_WAN_ROUTER is not set
-# CONFIG_NET_FASTROUTE is not set
-# CONFIG_NET_HW_FLOWCONTROL is not set
-
-#
-# QoS and/or fair queueing
-#
-# CONFIG_NET_SCHED is not set
-
-#
-# Network testing
-#
-# CONFIG_NET_PKTGEN is not set
-CONFIG_NETDEVICES=y
-
-#
-# ARCnet devices
-#
-# CONFIG_ARCNET is not set
-# CONFIG_DUMMY is not set
-# CONFIG_BONDING is not set
-# CONFIG_EQUALIZER is not set
-# CONFIG_TUN is not set
-# CONFIG_ETHERTAP is not set
-
-#
-# Ethernet (10 or 100Mbit)
-#
-CONFIG_NET_ETHERNET=y
-# CONFIG_MII is not set
-# CONFIG_HAPPYMEAL is not set
-# CONFIG_SUNGEM is not set
-# CONFIG_NET_VENDOR_3COM is not set
-
-#
-# Tulip family network device support
-#
-# CONFIG_NET_TULIP is not set
-# CONFIG_HP100 is not set
-# CONFIG_NET_PCI is not set
-
-#
-# Ethernet (1000 Mbit)
-#
-# CONFIG_ACENIC is not set
-# CONFIG_DL2K is not set
-# CONFIG_E1000 is not set
-# CONFIG_NS83820 is not set
-# CONFIG_HAMACHI is not set
-# CONFIG_YELLOWFIN is not set
-# CONFIG_R8169 is not set
-# CONFIG_SK98LIN is not set
-# CONFIG_TIGON3 is not set
-
-#
-# Ethernet (10000 Mbit)
-#
-# CONFIG_IXGB is not set
-# CONFIG_FDDI is not set
-# CONFIG_HIPPI is not set
-# CONFIG_PPP is not set
-# CONFIG_SLIP is not set
-
-#
-# Wireless LAN (non-hamradio)
-#
-# CONFIG_NET_RADIO is not set
-
-#
-# Token Ring devices (depends on LLC=y)
-#
-# CONFIG_RCPCI is not set
-# CONFIG_SHAPER is not set
-
-#
-# Wan interfaces
-#
-# CONFIG_WAN is not set
-
-#
-# Amateur Radio support
-#
-# CONFIG_HAMRADIO is not set
-
-#
-# IrDA (infrared) support
-#
-# CONFIG_IRDA is not set
-
-#
-# ISDN subsystem
-#
-# CONFIG_ISDN_BOOL is not set
-
-#
-# Telephony Support
-#
-# CONFIG_PHONE is not set
-
-#
-# Input device support
-#
-CONFIG_INPUT=y
-
-#
-# Userland interfaces
-#
-# CONFIG_INPUT_MOUSEDEV is not set
-# CONFIG_INPUT_JOYDEV is not set
-# CONFIG_INPUT_TSDEV is not set
-# CONFIG_INPUT_EVDEV is not set
-# CONFIG_INPUT_EVBUG is not set
-
-#
-# Input I/O drivers
-#
-# CONFIG_GAMEPORT is not set
-CONFIG_SOUND_GAMEPORT=y
-# CONFIG_SERIO is not set
-
-#
-# Input Device Drivers
-#
-# CONFIG_INPUT_KEYBOARD is not set
-# CONFIG_INPUT_MOUSE is not set
-# CONFIG_INPUT_JOYSTICK is not set
-# CONFIG_INPUT_TOUCHSCREEN is not set
-# CONFIG_INPUT_MISC is not set
-
-#
-# Character devices
-#
-# CONFIG_VT is not set
-# CONFIG_SERIAL_NONSTANDARD is not set
-
-#
-# Serial drivers
-#
-CONFIG_SERIAL_8250=y
-CONFIG_SERIAL_8250_CONSOLE=y
-# CONFIG_SERIAL_8250_EXTENDED is not set
-
-#
-# Non-8250 serial port support
-#
-CONFIG_SERIAL_CORE=y
-CONFIG_SERIAL_CORE_CONSOLE=y
-CONFIG_UNIX98_PTYS=y
-CONFIG_UNIX98_PTY_COUNT=256
-
-#
-# I2C support
-#
-# CONFIG_I2C is not set
-
-#
-# I2C Hardware Sensors Mainboard support
-#
-
-#
-# I2C Hardware Sensors Chip support
-#
-# CONFIG_I2C_SENSOR is not set
-
-#
-# Mice
-#
-# CONFIG_BUSMOUSE is not set
-# CONFIG_QIC02_TAPE is not set
-
-#
-# IPMI
-#
-# CONFIG_IPMI_HANDLER is not set
-
-#
-# Watchdog Cards
-#
-# CONFIG_WATCHDOG is not set
-# CONFIG_NVRAM is not set
-# CONFIG_RTC is not set
-# CONFIG_GEN_RTC is not set
-# CONFIG_DTLK is not set
-# CONFIG_R3964 is not set
-# CONFIG_APPLICOM is not set
-
-#
-# Ftape, the floppy tape device driver
-#
-# CONFIG_FTAPE is not set
-# CONFIG_AGP is not set
-# CONFIG_DRM is not set
-# CONFIG_RAW_DRIVER is not set
-# CONFIG_HANGCHECK_TIMER is not set
-
-#
-# Multimedia devices
-#
-# CONFIG_VIDEO_DEV is not set
-
-#
-# Digital Video Broadcasting Devices
-#
-# CONFIG_DVB is not set
-
-#
-# File systems
-#
-CONFIG_EXT2_FS=y
-# CONFIG_EXT2_FS_XATTR is not set
-CONFIG_EXT3_FS=y
-CONFIG_EXT3_FS_XATTR=y
-# CONFIG_EXT3_FS_POSIX_ACL is not set
-CONFIG_EXT3_FS_SECURITY=y
-CONFIG_JBD=y
-# CONFIG_JBD_DEBUG is not set
-CONFIG_FS_MBCACHE=y
-# CONFIG_REISERFS_FS is not set
-# CONFIG_JFS_FS is not set
-# CONFIG_XFS_FS is not set
-# CONFIG_MINIX_FS is not set
-# CONFIG_ROMFS_FS is not set
-# CONFIG_QUOTA is not set
-# CONFIG_AUTOFS_FS is not set
-# CONFIG_AUTOFS4_FS is not set
-
-#
-# CD-ROM/DVD Filesystems
-#
-# CONFIG_ISO9660_FS is not set
-# CONFIG_UDF_FS is not set
-
-#
-# DOS/FAT/NT Filesystems
-#
-# CONFIG_FAT_FS is not set
-# CONFIG_NTFS_FS is not set
-
-#
-# Pseudo filesystems
-#
-CONFIG_PROC_FS=y
-# CONFIG_DEVFS_FS is not set
-CONFIG_DEVPTS_FS=y
-CONFIG_DEVPTS_FS_XATTR=y
-CONFIG_DEVPTS_FS_SECURITY=y
-# CONFIG_TMPFS is not set
-CONFIG_RAMFS=y
-
-#
-# Miscellaneous filesystems
-#
-# CONFIG_ADFS_FS is not set
-# CONFIG_AFFS_FS is not set
-# CONFIG_HFS_FS is not set
-# CONFIG_BEFS_FS is not set
-# CONFIG_BFS_FS is not set
-# CONFIG_EFS_FS is not set
-# CONFIG_JFFS_FS is not set
-# CONFIG_JFFS2_FS is not set
-# CONFIG_CRAMFS is not set
-# CONFIG_VXFS_FS is not set
-# CONFIG_HPFS_FS is not set
-# CONFIG_QNX4FS_FS is not set
-# CONFIG_SYSV_FS is not set
-# CONFIG_UFS_FS is not set
-
-#
-# Network File Systems
-#
-CONFIG_NFS_FS=y
-CONFIG_NFS_V3=y
-# CONFIG_NFS_V4 is not set
-# CONFIG_NFSD is not set
-CONFIG_LOCKD=y
-CONFIG_LOCKD_V4=y
-# CONFIG_EXPORTFS is not set
-CONFIG_SUNRPC=y
-# CONFIG_SUNRPC_GSS is not set
-# CONFIG_SMB_FS is not set
-# CONFIG_CIFS is not set
-# CONFIG_NCP_FS is not set
-# CONFIG_CODA_FS is not set
-# CONFIG_INTERMEZZO_FS is not set
-# CONFIG_AFS_FS is not set
-
-#
-# Partition Types
-#
-# CONFIG_PARTITION_ADVANCED is not set
-CONFIG_MSDOS_PARTITION=y
-
-#
-# Graphics support
-#
-
-#
-# Sound
-#
-# CONFIG_SOUND is not set
-
-#
-# USB support
-#
-# CONFIG_USB is not set
-# CONFIG_USB_GADGET is not set
-
-#
-# Bluetooth support
-#
-# CONFIG_BT is not set
-
-#
-# Kernel hacking
-#
-CONFIG_CROSSCOMPILE=y
-# CONFIG_DEBUG_KERNEL is not set
-
-#
-# Security options
-#
-# CONFIG_SECURITY is not set
-
-#
-# Cryptographic options
-#
-# CONFIG_CRYPTO is not set
-
-#
-# Library routines
-#
-CONFIG_CRC32=y
--- diff/arch/mips/defconfig-malta	2003-08-20 14:16:25.000000000 +0100
+++ source/arch/mips/defconfig-malta	1970-01-01 01:00:00.000000000 +0100
@@ -1,626 +0,0 @@
-#
-# Automatically generated make config: don't edit
-#
-CONFIG_MIPS=y
-# CONFIG_MIPS64 is not set
-CONFIG_MIPS32=y
-
-#
-# Code maturity level options
-#
-CONFIG_EXPERIMENTAL=y
-
-#
-# General setup
-#
-CONFIG_SWAP=y
-CONFIG_SYSVIPC=y
-# CONFIG_BSD_PROCESS_ACCT is not set
-CONFIG_SYSCTL=y
-CONFIG_LOG_BUF_SHIFT=14
-# CONFIG_EMBEDDED is not set
-CONFIG_KALLSYMS=y
-CONFIG_FUTEX=y
-CONFIG_EPOLL=y
-CONFIG_IOSCHED_AS=y
-CONFIG_IOSCHED_DEADLINE=y
-
-#
-# Loadable module support
-#
-CONFIG_MODULES=y
-CONFIG_MODULE_UNLOAD=y
-# CONFIG_MODULE_FORCE_UNLOAD is not set
-CONFIG_OBSOLETE_MODPARM=y
-CONFIG_MODVERSIONS=y
-CONFIG_KMOD=y
-
-#
-# Machine selection
-#
-# CONFIG_ACER_PICA_61 is not set
-# CONFIG_BAGET_MIPS is not set
-# CONFIG_CASIO_E55 is not set
-# CONFIG_MIPS_COBALT is not set
-# CONFIG_DECSTATION is not set
-# CONFIG_MIPS_EV64120 is not set
-# CONFIG_MIPS_EV96100 is not set
-# CONFIG_MIPS_IVR is not set
-# CONFIG_LASAT is not set
-# CONFIG_HP_LASERJET is not set
-# CONFIG_IBM_WORKPAD is not set
-# CONFIG_MIPS_ITE8172 is not set
-# CONFIG_MIPS_ATLAS is not set
-# CONFIG_MIPS_MAGNUM_4000 is not set
-CONFIG_MIPS_MALTA=y
-# CONFIG_MIPS_SEAD is not set
-# CONFIG_MOMENCO_OCELOT is not set
-# CONFIG_MOMENCO_OCELOT_G is not set
-# CONFIG_MOMENCO_OCELOT_C is not set
-# CONFIG_DDB5074 is not set
-# CONFIG_DDB5476 is not set
-# CONFIG_DDB5477 is not set
-# CONFIG_NEC_OSPREY is not set
-# CONFIG_NEC_EAGLE is not set
-# CONFIG_OLIVETTI_M700 is not set
-# CONFIG_SGI_IP22 is not set
-# CONFIG_SGI_IP32 is not set
-# CONFIG_SOC_AU1X00 is not set
-# CONFIG_SIBYTE_SB1xxx_SOC is not set
-# CONFIG_SNI_RM200_PCI is not set
-# CONFIG_TANBAC_TB0226 is not set
-# CONFIG_TANBAC_TB0229 is not set
-# CONFIG_TOSHIBA_JMR3927 is not set
-# CONFIG_TOSHIBA_RBTX4927 is not set
-# CONFIG_VICTOR_MPC30X is not set
-# CONFIG_ZAO_CAPCELLA is not set
-CONFIG_RWSEM_GENERIC_SPINLOCK=y
-CONFIG_GENERIC_ISA_DMA=y
-CONFIG_I8259=y
-CONFIG_NONCOHERENT_IO=y
-CONFIG_CPU_LITTLE_ENDIAN=y
-CONFIG_MIPS_BOARDS_GEN=y
-CONFIG_SWAP_IO_SPACE=y
-CONFIG_BOOT_ELF32=y
-CONFIG_L1_CACHE_SHIFT=5
-# CONFIG_FB is not set
-CONFIG_HAVE_STD_PC_SERIAL_PORT=y
-
-#
-# CPU selection
-#
-CONFIG_CPU_MIPS32=y
-# CONFIG_CPU_MIPS64 is not set
-# CONFIG_CPU_R3000 is not set
-# CONFIG_CPU_TX39XX is not set
-# CONFIG_CPU_VR41XX is not set
-# CONFIG_CPU_R4300 is not set
-# CONFIG_CPU_R4X00 is not set
-# CONFIG_CPU_TX49XX is not set
-# CONFIG_CPU_R5000 is not set
-# CONFIG_CPU_R5432 is not set
-# CONFIG_CPU_R6000 is not set
-# CONFIG_CPU_NEVADA is not set
-# CONFIG_CPU_R8000 is not set
-# CONFIG_CPU_R10000 is not set
-# CONFIG_CPU_RM7000 is not set
-# CONFIG_CPU_SB1 is not set
-CONFIG_CPU_HAS_PREFETCH=y
-# CONFIG_VTAG_ICACHE is not set
-# CONFIG_64BIT_PHYS_ADDR is not set
-# CONFIG_CPU_ADVANCED is not set
-CONFIG_CPU_HAS_LLSC=y
-CONFIG_CPU_HAS_SYNC=y
-# CONFIG_PREEMPT is not set
-# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
-
-#
-# Bus options (PCI, PCMCIA, EISA, ISA, TC)
-#
-CONFIG_PCI=y
-CONFIG_PCI_LEGACY_PROC=y
-CONFIG_PCI_NAMES=y
-CONFIG_MMU=y
-# CONFIG_HOTPLUG is not set
-
-#
-# Executable file formats
-#
-CONFIG_KCORE_ELF=y
-CONFIG_BINFMT_ELF=y
-# CONFIG_BINFMT_MISC is not set
-CONFIG_TRAD_SIGNALS=y
-
-#
-# Memory Technology Devices (MTD)
-#
-# CONFIG_MTD is not set
-
-#
-# Parallel port support
-#
-# CONFIG_PARPORT is not set
-
-#
-# Plug and Play support
-#
-# CONFIG_PNP is not set
-
-#
-# Generic Driver Options
-#
-# CONFIG_FW_LOADER is not set
-
-#
-# Block devices
-#
-CONFIG_BLK_DEV_FD=y
-# CONFIG_BLK_CPQ_DA is not set
-# CONFIG_BLK_CPQ_CISS_DA is not set
-# CONFIG_BLK_DEV_DAC960 is not set
-# CONFIG_BLK_DEV_UMEM is not set
-# CONFIG_BLK_DEV_LOOP is not set
-# CONFIG_BLK_DEV_NBD is not set
-CONFIG_BLK_DEV_RAM=y
-CONFIG_BLK_DEV_RAM_SIZE=4096
-# CONFIG_BLK_DEV_INITRD is not set
-# CONFIG_LBD is not set
-
-#
-# ATA/ATAPI/MFM/RLL support
-#
-# CONFIG_IDE is not set
-
-#
-# SCSI device support
-#
-CONFIG_SCSI=y
-
-#
-# SCSI support type (disk, tape, CD-ROM)
-#
-CONFIG_BLK_DEV_SD=y
-# CONFIG_CHR_DEV_ST is not set
-# CONFIG_CHR_DEV_OSST is not set
-# CONFIG_BLK_DEV_SR is not set
-# CONFIG_CHR_DEV_SG is not set
-
-#
-# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
-#
-# CONFIG_SCSI_MULTI_LUN is not set
-# CONFIG_SCSI_REPORT_LUNS is not set
-# CONFIG_SCSI_CONSTANTS is not set
-# CONFIG_SCSI_LOGGING is not set
-
-#
-# SCSI low-level drivers
-#
-# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
-# CONFIG_SCSI_ACARD is not set
-# CONFIG_SCSI_AACRAID is not set
-# CONFIG_SCSI_AIC7XXX is not set
-# CONFIG_SCSI_AIC7XXX_OLD is not set
-# CONFIG_SCSI_AIC79XX is not set
-# CONFIG_SCSI_DPT_I2O is not set
-# CONFIG_SCSI_ADVANSYS is not set
-# CONFIG_SCSI_MEGARAID is not set
-# CONFIG_SCSI_BUSLOGIC is not set
-# CONFIG_SCSI_CPQFCTS is not set
-# CONFIG_SCSI_DMX3191D is not set
-# CONFIG_SCSI_EATA is not set
-# CONFIG_SCSI_EATA_PIO is not set
-# CONFIG_SCSI_FUTURE_DOMAIN is not set
-# CONFIG_SCSI_GDTH is not set
-# CONFIG_SCSI_INITIO is not set
-# CONFIG_SCSI_INIA100 is not set
-# CONFIG_SCSI_SYM53C8XX_2 is not set
-# CONFIG_SCSI_SYM53C8XX is not set
-# CONFIG_SCSI_PCI2000 is not set
-# CONFIG_SCSI_PCI2220I is not set
-# CONFIG_SCSI_QLOGIC_ISP is not set
-# CONFIG_SCSI_QLOGIC_FC is not set
-# CONFIG_SCSI_QLOGIC_1280 is not set
-# CONFIG_SCSI_DC395x is not set
-# CONFIG_SCSI_DC390T is not set
-# CONFIG_SCSI_NSP32 is not set
-# CONFIG_SCSI_DEBUG is not set
-
-#
-# Multi-device support (RAID and LVM)
-#
-# CONFIG_MD is not set
-
-#
-# Fusion MPT device support
-#
-# CONFIG_FUSION is not set
-
-#
-# IEEE 1394 (FireWire) support (EXPERIMENTAL)
-#
-# CONFIG_IEEE1394 is not set
-
-#
-# I2O device support
-#
-# CONFIG_I2O is not set
-
-#
-# Networking support
-#
-CONFIG_NET=y
-
-#
-# Networking options
-#
-# CONFIG_PACKET is not set
-CONFIG_NETLINK_DEV=y
-# CONFIG_NETFILTER is not set
-CONFIG_UNIX=y
-CONFIG_NET_KEY=y
-CONFIG_INET=y
-# CONFIG_IP_MULTICAST is not set
-# CONFIG_IP_ADVANCED_ROUTER is not set
-CONFIG_IP_PNP=y
-CONFIG_IP_PNP_DHCP=y
-CONFIG_IP_PNP_BOOTP=y
-# CONFIG_IP_PNP_RARP is not set
-# CONFIG_NET_IPIP is not set
-# CONFIG_NET_IPGRE is not set
-# CONFIG_ARPD is not set
-# CONFIG_INET_ECN is not set
-# CONFIG_SYN_COOKIES is not set
-# CONFIG_INET_AH is not set
-# CONFIG_INET_ESP is not set
-# CONFIG_INET_IPCOMP is not set
-# CONFIG_IPV6 is not set
-# CONFIG_XFRM_USER is not set
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
-CONFIG_IPV6_SCTP__=y
-# CONFIG_IP_SCTP is not set
-# CONFIG_ATM is not set
-# CONFIG_VLAN_8021Q is not set
-# CONFIG_LLC is not set
-# CONFIG_DECNET is not set
-# CONFIG_BRIDGE is not set
-# CONFIG_X25 is not set
-# CONFIG_LAPB is not set
-# CONFIG_NET_DIVERT is not set
-# CONFIG_ECONET is not set
-# CONFIG_WAN_ROUTER is not set
-# CONFIG_NET_FASTROUTE is not set
-# CONFIG_NET_HW_FLOWCONTROL is not set
-
-#
-# QoS and/or fair queueing
-#
-# CONFIG_NET_SCHED is not set
-
-#
-# Network testing
-#
-# CONFIG_NET_PKTGEN is not set
-CONFIG_NETDEVICES=y
-
-#
-# ARCnet devices
-#
-# CONFIG_ARCNET is not set
-# CONFIG_DUMMY is not set
-# CONFIG_BONDING is not set
-# CONFIG_EQUALIZER is not set
-# CONFIG_TUN is not set
-# CONFIG_ETHERTAP is not set
-
-#
-# Ethernet (10 or 100Mbit)
-#
-CONFIG_NET_ETHERNET=y
-# CONFIG_MII is not set
-# CONFIG_HAPPYMEAL is not set
-# CONFIG_SUNGEM is not set
-# CONFIG_NET_VENDOR_3COM is not set
-
-#
-# Tulip family network device support
-#
-# CONFIG_NET_TULIP is not set
-# CONFIG_HP100 is not set
-# CONFIG_NET_PCI is not set
-
-#
-# Ethernet (1000 Mbit)
-#
-# CONFIG_ACENIC is not set
-# CONFIG_DL2K is not set
-# CONFIG_E1000 is not set
-# CONFIG_NS83820 is not set
-# CONFIG_HAMACHI is not set
-# CONFIG_YELLOWFIN is not set
-# CONFIG_R8169 is not set
-# CONFIG_SK98LIN is not set
-# CONFIG_TIGON3 is not set
-
-#
-# Ethernet (10000 Mbit)
-#
-# CONFIG_IXGB is not set
-# CONFIG_FDDI is not set
-# CONFIG_HIPPI is not set
-# CONFIG_PPP is not set
-# CONFIG_SLIP is not set
-
-#
-# Wireless LAN (non-hamradio)
-#
-# CONFIG_NET_RADIO is not set
-
-#
-# Token Ring devices (depends on LLC=y)
-#
-# CONFIG_NET_FC is not set
-# CONFIG_RCPCI is not set
-# CONFIG_SHAPER is not set
-
-#
-# Wan interfaces
-#
-# CONFIG_WAN is not set
-
-#
-# Amateur Radio support
-#
-# CONFIG_HAMRADIO is not set
-
-#
-# IrDA (infrared) support
-#
-# CONFIG_IRDA is not set
-
-#
-# ISDN subsystem
-#
-# CONFIG_ISDN_BOOL is not set
-
-#
-# Telephony Support
-#
-# CONFIG_PHONE is not set
-
-#
-# Input device support
-#
-CONFIG_INPUT=y
-
-#
-# Userland interfaces
-#
-# CONFIG_INPUT_MOUSEDEV is not set
-# CONFIG_INPUT_JOYDEV is not set
-# CONFIG_INPUT_TSDEV is not set
-# CONFIG_INPUT_EVDEV is not set
-# CONFIG_INPUT_EVBUG is not set
-
-#
-# Input I/O drivers
-#
-# CONFIG_GAMEPORT is not set
-CONFIG_SOUND_GAMEPORT=y
-CONFIG_SERIO=y
-# CONFIG_SERIO_I8042 is not set
-CONFIG_SERIO_SERPORT=y
-# CONFIG_SERIO_CT82C710 is not set
-# CONFIG_SERIO_PCIPS2 is not set
-
-#
-# Input Device Drivers
-#
-# CONFIG_INPUT_KEYBOARD is not set
-# CONFIG_INPUT_MOUSE is not set
-# CONFIG_INPUT_JOYSTICK is not set
-# CONFIG_INPUT_TOUCHSCREEN is not set
-# CONFIG_INPUT_MISC is not set
-
-#
-# Character devices
-#
-# CONFIG_VT is not set
-# CONFIG_SERIAL_NONSTANDARD is not set
-
-#
-# Serial drivers
-#
-CONFIG_SERIAL_8250=y
-CONFIG_SERIAL_8250_CONSOLE=y
-# CONFIG_SERIAL_8250_EXTENDED is not set
-
-#
-# Non-8250 serial port support
-#
-CONFIG_SERIAL_CORE=y
-CONFIG_SERIAL_CORE_CONSOLE=y
-CONFIG_UNIX98_PTYS=y
-CONFIG_UNIX98_PTY_COUNT=256
-
-#
-# I2C support
-#
-# CONFIG_I2C is not set
-
-#
-# I2C Hardware Sensors Mainboard support
-#
-
-#
-# I2C Hardware Sensors Chip support
-#
-# CONFIG_I2C_SENSOR is not set
-
-#
-# Mice
-#
-# CONFIG_BUSMOUSE is not set
-# CONFIG_QIC02_TAPE is not set
-
-#
-# IPMI
-#
-# CONFIG_IPMI_HANDLER is not set
-
-#
-# Watchdog Cards
-#
-# CONFIG_WATCHDOG is not set
-# CONFIG_NVRAM is not set
-CONFIG_RTC=y
-# CONFIG_DTLK is not set
-# CONFIG_R3964 is not set
-# CONFIG_APPLICOM is not set
-
-#
-# Ftape, the floppy tape device driver
-#
-# CONFIG_FTAPE is not set
-# CONFIG_AGP is not set
-# CONFIG_DRM is not set
-# CONFIG_RAW_DRIVER is not set
-# CONFIG_HANGCHECK_TIMER is not set
-
-#
-# Multimedia devices
-#
-# CONFIG_VIDEO_DEV is not set
-
-#
-# Digital Video Broadcasting Devices
-#
-# CONFIG_DVB is not set
-
-#
-# File systems
-#
-CONFIG_EXT2_FS=y
-# CONFIG_EXT2_FS_XATTR is not set
-# CONFIG_EXT3_FS is not set
-# CONFIG_JBD is not set
-# CONFIG_REISERFS_FS is not set
-# CONFIG_JFS_FS is not set
-# CONFIG_XFS_FS is not set
-# CONFIG_MINIX_FS is not set
-# CONFIG_ROMFS_FS is not set
-# CONFIG_QUOTA is not set
-CONFIG_AUTOFS_FS=y
-# CONFIG_AUTOFS4_FS is not set
-
-#
-# CD-ROM/DVD Filesystems
-#
-# CONFIG_ISO9660_FS is not set
-# CONFIG_UDF_FS is not set
-
-#
-# DOS/FAT/NT Filesystems
-#
-# CONFIG_FAT_FS is not set
-# CONFIG_NTFS_FS is not set
-
-#
-# Pseudo filesystems
-#
-CONFIG_PROC_FS=y
-# CONFIG_DEVFS_FS is not set
-CONFIG_DEVPTS_FS=y
-CONFIG_DEVPTS_FS_XATTR=y
-CONFIG_DEVPTS_FS_SECURITY=y
-# CONFIG_TMPFS is not set
-CONFIG_RAMFS=y
-
-#
-# Miscellaneous filesystems
-#
-# CONFIG_ADFS_FS is not set
-# CONFIG_AFFS_FS is not set
-# CONFIG_HFS_FS is not set
-# CONFIG_BEFS_FS is not set
-# CONFIG_BFS_FS is not set
-CONFIG_EFS_FS=y
-# CONFIG_CRAMFS is not set
-# CONFIG_VXFS_FS is not set
-# CONFIG_HPFS_FS is not set
-# CONFIG_QNX4FS_FS is not set
-# CONFIG_SYSV_FS is not set
-# CONFIG_UFS_FS is not set
-
-#
-# Network File Systems
-#
-CONFIG_NFS_FS=y
-CONFIG_NFS_V3=y
-# CONFIG_NFS_V4 is not set
-CONFIG_NFSD=y
-CONFIG_NFSD_V3=y
-# CONFIG_NFSD_V4 is not set
-# CONFIG_NFSD_TCP is not set
-CONFIG_ROOT_NFS=y
-CONFIG_LOCKD=y
-CONFIG_LOCKD_V4=y
-CONFIG_EXPORTFS=y
-CONFIG_SUNRPC=y
-# CONFIG_SUNRPC_GSS is not set
-# CONFIG_SMB_FS is not set
-# CONFIG_CIFS is not set
-# CONFIG_NCP_FS is not set
-# CONFIG_CODA_FS is not set
-# CONFIG_INTERMEZZO_FS is not set
-# CONFIG_AFS_FS is not set
-
-#
-# Partition Types
-#
-# CONFIG_PARTITION_ADVANCED is not set
-CONFIG_MSDOS_PARTITION=y
-
-#
-# Graphics support
-#
-
-#
-# Sound
-#
-# CONFIG_SOUND is not set
-
-#
-# USB support
-#
-# CONFIG_USB is not set
-# CONFIG_USB_GADGET is not set
-
-#
-# Bluetooth support
-#
-# CONFIG_BT is not set
-
-#
-# Kernel hacking
-#
-CONFIG_CROSSCOMPILE=y
-# CONFIG_DEBUG_KERNEL is not set
-
-#
-# Security options
-#
-# CONFIG_SECURITY is not set
-
-#
-# Cryptographic options
-#
-# CONFIG_CRYPTO is not set
-
-#
-# Library routines
-#
-# CONFIG_CRC32 is not set
--- diff/arch/mips/defconfig-mpc30x	2003-08-20 14:16:25.000000000 +0100
+++ source/arch/mips/defconfig-mpc30x	1970-01-01 01:00:00.000000000 +0100
@@ -1,547 +0,0 @@
-#
-# Automatically generated make config: don't edit
-#
-CONFIG_MIPS=y
-# CONFIG_MIPS64 is not set
-CONFIG_MIPS32=y
-
-#
-# Code maturity level options
-#
-CONFIG_EXPERIMENTAL=y
-
-#
-# General setup
-#
-CONFIG_SWAP=y
-CONFIG_SYSVIPC=y
-# CONFIG_BSD_PROCESS_ACCT is not set
-CONFIG_SYSCTL=y
-CONFIG_LOG_BUF_SHIFT=14
-# CONFIG_EMBEDDED is not set
-CONFIG_KALLSYMS=y
-CONFIG_FUTEX=y
-CONFIG_EPOLL=y
-CONFIG_IOSCHED_AS=y
-CONFIG_IOSCHED_DEADLINE=y
-
-#
-# Loadable module support
-#
-CONFIG_MODULES=y
-CONFIG_MODULE_UNLOAD=y
-# CONFIG_MODULE_FORCE_UNLOAD is not set
-CONFIG_OBSOLETE_MODPARM=y
-CONFIG_MODVERSIONS=y
-CONFIG_KMOD=y
-
-#
-# Machine selection
-#
-# CONFIG_ACER_PICA_61 is not set
-# CONFIG_BAGET_MIPS is not set
-# CONFIG_CASIO_E55 is not set
-# CONFIG_MIPS_COBALT is not set
-# CONFIG_DECSTATION is not set
-# CONFIG_MIPS_EV64120 is not set
-# CONFIG_MIPS_EV96100 is not set
-# CONFIG_MIPS_IVR is not set
-# CONFIG_LASAT is not set
-# CONFIG_HP_LASERJET is not set
-# CONFIG_IBM_WORKPAD is not set
-# CONFIG_MIPS_ITE8172 is not set
-# CONFIG_MIPS_ATLAS is not set
-# CONFIG_MIPS_MAGNUM_4000 is not set
-# CONFIG_MIPS_MALTA is not set
-# CONFIG_MIPS_SEAD is not set
-# CONFIG_MOMENCO_OCELOT is not set
-# CONFIG_MOMENCO_OCELOT_G is not set
-# CONFIG_MOMENCO_OCELOT_C is not set
-# CONFIG_DDB5074 is not set
-# CONFIG_DDB5476 is not set
-# CONFIG_DDB5477 is not set
-# CONFIG_NEC_OSPREY is not set
-# CONFIG_NEC_EAGLE is not set
-# CONFIG_OLIVETTI_M700 is not set
-# CONFIG_SGI_IP22 is not set
-# CONFIG_SGI_IP32 is not set
-# CONFIG_SOC_AU1X00 is not set
-# CONFIG_SIBYTE_SB1xxx_SOC is not set
-# CONFIG_SNI_RM200_PCI is not set
-# CONFIG_TANBAC_TB0226 is not set
-# CONFIG_TANBAC_TB0229 is not set
-# CONFIG_TOSHIBA_JMR3927 is not set
-# CONFIG_TOSHIBA_RBTX4927 is not set
-CONFIG_VICTOR_MPC30X=y
-# CONFIG_ZAO_CAPCELLA is not set
-CONFIG_RWSEM_GENERIC_SPINLOCK=y
-CONFIG_NONCOHERENT_IO=y
-CONFIG_CPU_LITTLE_ENDIAN=y
-CONFIG_IRQ_CPU=y
-CONFIG_VR41XX_TIME_C=y
-CONFIG_DUMMY_KEYB=y
-CONFIG_VR41XX_COMMON=y
-CONFIG_VRC4173=y
-CONFIG_NEW_PCI=y
-# CONFIG_FB is not set
-
-#
-# CPU selection
-#
-# CONFIG_CPU_MIPS32 is not set
-# CONFIG_CPU_MIPS64 is not set
-# CONFIG_CPU_R3000 is not set
-# CONFIG_CPU_TX39XX is not set
-CONFIG_CPU_VR41XX=y
-# CONFIG_CPU_R4300 is not set
-# CONFIG_CPU_R4X00 is not set
-# CONFIG_CPU_TX49XX is not set
-# CONFIG_CPU_R5000 is not set
-# CONFIG_CPU_R5432 is not set
-# CONFIG_CPU_R6000 is not set
-# CONFIG_CPU_NEVADA is not set
-# CONFIG_CPU_R8000 is not set
-# CONFIG_CPU_R10000 is not set
-# CONFIG_CPU_RM7000 is not set
-# CONFIG_CPU_SB1 is not set
-# CONFIG_CPU_ADVANCED is not set
-CONFIG_CPU_HAS_SYNC=y
-# CONFIG_PREEMPT is not set
-# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
-
-#
-# Bus options (PCI, PCMCIA, EISA, ISA, TC)
-#
-# CONFIG_PCI is not set
-CONFIG_MMU=y
-# CONFIG_HOTPLUG is not set
-
-#
-# Executable file formats
-#
-CONFIG_KCORE_ELF=y
-CONFIG_BINFMT_ELF=y
-# CONFIG_BINFMT_MISC is not set
-CONFIG_TRAD_SIGNALS=y
-
-#
-# Memory Technology Devices (MTD)
-#
-# CONFIG_MTD is not set
-
-#
-# Parallel port support
-#
-# CONFIG_PARPORT is not set
-
-#
-# Plug and Play support
-#
-# CONFIG_PNP is not set
-
-#
-# Generic Driver Options
-#
-# CONFIG_FW_LOADER is not set
-
-#
-# Block devices
-#
-# CONFIG_BLK_DEV_FD is not set
-# CONFIG_BLK_DEV_LOOP is not set
-# CONFIG_BLK_DEV_NBD is not set
-# CONFIG_BLK_DEV_RAM is not set
-# CONFIG_BLK_DEV_INITRD is not set
-# CONFIG_LBD is not set
-
-#
-# ATA/ATAPI/MFM/RLL support
-#
-# CONFIG_IDE is not set
-
-#
-# SCSI device support
-#
-# CONFIG_SCSI is not set
-
-#
-# Multi-device support (RAID and LVM)
-#
-# CONFIG_MD is not set
-
-#
-# Fusion MPT device support
-#
-
-#
-# I2O device support
-#
-
-#
-# Networking support
-#
-CONFIG_NET=y
-
-#
-# Networking options
-#
-CONFIG_PACKET=y
-CONFIG_PACKET_MMAP=y
-CONFIG_NETLINK_DEV=y
-# CONFIG_NETFILTER is not set
-CONFIG_UNIX=y
-CONFIG_NET_KEY=y
-CONFIG_INET=y
-CONFIG_IP_MULTICAST=y
-# CONFIG_IP_ADVANCED_ROUTER is not set
-CONFIG_IP_PNP=y
-# CONFIG_IP_PNP_DHCP is not set
-CONFIG_IP_PNP_BOOTP=y
-# CONFIG_IP_PNP_RARP is not set
-# CONFIG_NET_IPIP is not set
-# CONFIG_NET_IPGRE is not set
-# CONFIG_IP_MROUTE is not set
-# CONFIG_ARPD is not set
-# CONFIG_INET_ECN is not set
-# CONFIG_SYN_COOKIES is not set
-# CONFIG_INET_AH is not set
-# CONFIG_INET_ESP is not set
-# CONFIG_INET_IPCOMP is not set
-# CONFIG_IPV6 is not set
-# CONFIG_XFRM_USER is not set
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
-CONFIG_IPV6_SCTP__=y
-# CONFIG_IP_SCTP is not set
-# CONFIG_ATM is not set
-# CONFIG_VLAN_8021Q is not set
-# CONFIG_LLC is not set
-# CONFIG_DECNET is not set
-# CONFIG_BRIDGE is not set
-# CONFIG_X25 is not set
-# CONFIG_LAPB is not set
-# CONFIG_NET_DIVERT is not set
-# CONFIG_ECONET is not set
-# CONFIG_WAN_ROUTER is not set
-# CONFIG_NET_FASTROUTE is not set
-# CONFIG_NET_HW_FLOWCONTROL is not set
-
-#
-# QoS and/or fair queueing
-#
-# CONFIG_NET_SCHED is not set
-
-#
-# Network testing
-#
-# CONFIG_NET_PKTGEN is not set
-CONFIG_NETDEVICES=y
-# CONFIG_DUMMY is not set
-# CONFIG_BONDING is not set
-# CONFIG_EQUALIZER is not set
-# CONFIG_TUN is not set
-# CONFIG_ETHERTAP is not set
-
-#
-# Ethernet (10 or 100Mbit)
-#
-CONFIG_NET_ETHERNET=y
-# CONFIG_MII is not set
-
-#
-# Ethernet (1000 Mbit)
-#
-
-#
-# Ethernet (10000 Mbit)
-#
-# CONFIG_PPP is not set
-# CONFIG_SLIP is not set
-
-#
-# Wireless LAN (non-hamradio)
-#
-# CONFIG_NET_RADIO is not set
-
-#
-# Token Ring devices (depends on LLC=y)
-#
-# CONFIG_SHAPER is not set
-
-#
-# Wan interfaces
-#
-# CONFIG_WAN is not set
-
-#
-# Amateur Radio support
-#
-# CONFIG_HAMRADIO is not set
-
-#
-# IrDA (infrared) support
-#
-# CONFIG_IRDA is not set
-
-#
-# ISDN subsystem
-#
-# CONFIG_ISDN_BOOL is not set
-
-#
-# Telephony Support
-#
-# CONFIG_PHONE is not set
-
-#
-# Input device support
-#
-CONFIG_INPUT=y
-
-#
-# Userland interfaces
-#
-# CONFIG_INPUT_MOUSEDEV is not set
-# CONFIG_INPUT_JOYDEV is not set
-# CONFIG_INPUT_TSDEV is not set
-# CONFIG_INPUT_EVDEV is not set
-# CONFIG_INPUT_EVBUG is not set
-
-#
-# Input I/O drivers
-#
-# CONFIG_GAMEPORT is not set
-CONFIG_SOUND_GAMEPORT=y
-# CONFIG_SERIO is not set
-
-#
-# Input Device Drivers
-#
-# CONFIG_INPUT_KEYBOARD is not set
-# CONFIG_INPUT_MOUSE is not set
-# CONFIG_INPUT_JOYSTICK is not set
-# CONFIG_INPUT_TOUCHSCREEN is not set
-# CONFIG_INPUT_MISC is not set
-
-#
-# Character devices
-#
-CONFIG_VT=y
-# CONFIG_VT_CONSOLE is not set
-CONFIG_HW_CONSOLE=y
-# CONFIG_SERIAL_NONSTANDARD is not set
-
-#
-# Serial drivers
-#
-CONFIG_SERIAL_8250=y
-CONFIG_SERIAL_8250_CONSOLE=y
-# CONFIG_SERIAL_8250_EXTENDED is not set
-
-#
-# Non-8250 serial port support
-#
-CONFIG_SERIAL_CORE=y
-CONFIG_SERIAL_CORE_CONSOLE=y
-CONFIG_UNIX98_PTYS=y
-CONFIG_UNIX98_PTY_COUNT=256
-
-#
-# I2C support
-#
-# CONFIG_I2C is not set
-
-#
-# I2C Hardware Sensors Mainboard support
-#
-
-#
-# I2C Hardware Sensors Chip support
-#
-# CONFIG_I2C_SENSOR is not set
-
-#
-# Mice
-#
-# CONFIG_BUSMOUSE is not set
-# CONFIG_QIC02_TAPE is not set
-
-#
-# IPMI
-#
-# CONFIG_IPMI_HANDLER is not set
-
-#
-# Watchdog Cards
-#
-# CONFIG_WATCHDOG is not set
-# CONFIG_NVRAM is not set
-# CONFIG_RTC is not set
-# CONFIG_GEN_RTC is not set
-# CONFIG_DTLK is not set
-# CONFIG_R3964 is not set
-# CONFIG_APPLICOM is not set
-
-#
-# Ftape, the floppy tape device driver
-#
-# CONFIG_FTAPE is not set
-# CONFIG_AGP is not set
-# CONFIG_DRM is not set
-# CONFIG_RAW_DRIVER is not set
-# CONFIG_HANGCHECK_TIMER is not set
-
-#
-# Multimedia devices
-#
-# CONFIG_VIDEO_DEV is not set
-
-#
-# Digital Video Broadcasting Devices
-#
-# CONFIG_DVB is not set
-
-#
-# File systems
-#
-CONFIG_EXT2_FS=y
-# CONFIG_EXT2_FS_XATTR is not set
-# CONFIG_EXT3_FS is not set
-# CONFIG_JBD is not set
-# CONFIG_REISERFS_FS is not set
-# CONFIG_JFS_FS is not set
-# CONFIG_XFS_FS is not set
-# CONFIG_MINIX_FS is not set
-# CONFIG_ROMFS_FS is not set
-# CONFIG_QUOTA is not set
-CONFIG_AUTOFS_FS=y
-CONFIG_AUTOFS4_FS=y
-
-#
-# CD-ROM/DVD Filesystems
-#
-# CONFIG_ISO9660_FS is not set
-# CONFIG_UDF_FS is not set
-
-#
-# DOS/FAT/NT Filesystems
-#
-# CONFIG_FAT_FS is not set
-# CONFIG_NTFS_FS is not set
-
-#
-# Pseudo filesystems
-#
-CONFIG_PROC_FS=y
-# CONFIG_DEVFS_FS is not set
-CONFIG_DEVPTS_FS=y
-CONFIG_DEVPTS_FS_XATTR=y
-CONFIG_DEVPTS_FS_SECURITY=y
-# CONFIG_TMPFS is not set
-CONFIG_RAMFS=y
-
-#
-# Miscellaneous filesystems
-#
-# CONFIG_ADFS_FS is not set
-# CONFIG_AFFS_FS is not set
-# CONFIG_HFS_FS is not set
-# CONFIG_BEFS_FS is not set
-# CONFIG_BFS_FS is not set
-# CONFIG_EFS_FS is not set
-# CONFIG_CRAMFS is not set
-# CONFIG_VXFS_FS is not set
-# CONFIG_HPFS_FS is not set
-# CONFIG_QNX4FS_FS is not set
-# CONFIG_SYSV_FS is not set
-# CONFIG_UFS_FS is not set
-
-#
-# Network File Systems
-#
-CONFIG_NFS_FS=y
-# CONFIG_NFS_V3 is not set
-# CONFIG_NFS_V4 is not set
-# CONFIG_NFSD is not set
-CONFIG_ROOT_NFS=y
-CONFIG_LOCKD=y
-# CONFIG_EXPORTFS is not set
-CONFIG_SUNRPC=y
-# CONFIG_SUNRPC_GSS is not set
-# CONFIG_SMB_FS is not set
-# CONFIG_CIFS is not set
-# CONFIG_NCP_FS is not set
-# CONFIG_CODA_FS is not set
-# CONFIG_INTERMEZZO_FS is not set
-# CONFIG_AFS_FS is not set
-
-#
-# Partition Types
-#
-# CONFIG_PARTITION_ADVANCED is not set
-CONFIG_MSDOS_PARTITION=y
-
-#
-# Graphics support
-#
-
-#
-# Console display driver support
-#
-# CONFIG_VGA_CONSOLE is not set
-# CONFIG_MDA_CONSOLE is not set
-CONFIG_DUMMY_CONSOLE=y
-
-#
-# Sound
-#
-# CONFIG_SOUND is not set
-
-#
-# USB support
-#
-# CONFIG_USB_GADGET is not set
-
-#
-# Bluetooth support
-#
-# CONFIG_BT is not set
-
-#
-# Kernel hacking
-#
-CONFIG_CROSSCOMPILE=y
-# CONFIG_DEBUG_KERNEL is not set
-
-#
-# Security options
-#
-# CONFIG_SECURITY is not set
-
-#
-# Cryptographic options
-#
-CONFIG_CRYPTO=y
-CONFIG_CRYPTO_HMAC=y
-CONFIG_CRYPTO_NULL=y
-# CONFIG_CRYPTO_MD4 is not set
-# CONFIG_CRYPTO_MD5 is not set
-# CONFIG_CRYPTO_SHA1 is not set
-# CONFIG_CRYPTO_SHA256 is not set
-CONFIG_CRYPTO_SHA512=y
-# CONFIG_CRYPTO_DES is not set
-# CONFIG_CRYPTO_BLOWFISH is not set
-CONFIG_CRYPTO_TWOFISH=y
-# CONFIG_CRYPTO_SERPENT is not set
-CONFIG_CRYPTO_AES=y
-CONFIG_CRYPTO_DEFLATE=y
-# CONFIG_CRYPTO_TEST is not set
-
-#
-# Library routines
-#
-# CONFIG_CRC32 is not set
-CONFIG_ZLIB_INFLATE=y
-CONFIG_ZLIB_DEFLATE=y
--- diff/arch/mips/defconfig-ocelot	2003-08-20 14:16:25.000000000 +0100
+++ source/arch/mips/defconfig-ocelot	1970-01-01 01:00:00.000000000 +0100
@@ -1,523 +0,0 @@
-#
-# Automatically generated make config: don't edit
-#
-CONFIG_MIPS=y
-# CONFIG_MIPS64 is not set
-CONFIG_MIPS32=y
-
-#
-# Code maturity level options
-#
-CONFIG_EXPERIMENTAL=y
-
-#
-# General setup
-#
-CONFIG_SWAP=y
-CONFIG_SYSVIPC=y
-# CONFIG_BSD_PROCESS_ACCT is not set
-CONFIG_SYSCTL=y
-CONFIG_LOG_BUF_SHIFT=14
-# CONFIG_EMBEDDED is not set
-CONFIG_KALLSYMS=y
-CONFIG_FUTEX=y
-CONFIG_EPOLL=y
-CONFIG_IOSCHED_AS=y
-CONFIG_IOSCHED_DEADLINE=y
-
-#
-# Loadable module support
-#
-# CONFIG_MODULES is not set
-
-#
-# Machine selection
-#
-# CONFIG_ACER_PICA_61 is not set
-# CONFIG_BAGET_MIPS is not set
-# CONFIG_CASIO_E55 is not set
-# CONFIG_MIPS_COBALT is not set
-# CONFIG_DECSTATION is not set
-# CONFIG_MIPS_EV64120 is not set
-CONFIG_SYSCLK_100=y
-# CONFIG_MIPS_EV96100 is not set
-# CONFIG_MIPS_IVR is not set
-# CONFIG_LASAT is not set
-# CONFIG_HP_LASERJET is not set
-# CONFIG_IBM_WORKPAD is not set
-# CONFIG_MIPS_ITE8172 is not set
-# CONFIG_MIPS_ATLAS is not set
-# CONFIG_MIPS_MAGNUM_4000 is not set
-# CONFIG_MIPS_MALTA is not set
-# CONFIG_MIPS_SEAD is not set
-CONFIG_MOMENCO_OCELOT=y
-# CONFIG_MOMENCO_OCELOT_G is not set
-# CONFIG_MOMENCO_OCELOT_C is not set
-# CONFIG_DDB5074 is not set
-# CONFIG_DDB5476 is not set
-# CONFIG_DDB5477 is not set
-# CONFIG_NEC_OSPREY is not set
-# CONFIG_NEC_EAGLE is not set
-# CONFIG_OLIVETTI_M700 is not set
-# CONFIG_SGI_IP22 is not set
-# CONFIG_SGI_IP32 is not set
-# CONFIG_SOC_AU1X00 is not set
-# CONFIG_SIBYTE_SB1xxx_SOC is not set
-# CONFIG_SNI_RM200_PCI is not set
-# CONFIG_TANBAC_TB0226 is not set
-# CONFIG_TANBAC_TB0229 is not set
-# CONFIG_TOSHIBA_JMR3927 is not set
-# CONFIG_TOSHIBA_RBTX4927 is not set
-# CONFIG_VICTOR_MPC30X is not set
-# CONFIG_ZAO_CAPCELLA is not set
-CONFIG_RWSEM_GENERIC_SPINLOCK=y
-CONFIG_CONFIG_GT64120=y
-CONFIG_NONCOHERENT_IO=y
-# CONFIG_CPU_LITTLE_ENDIAN is not set
-CONFIG_SWAP_IO_SPACE=y
-# CONFIG_FB is not set
-CONFIG_BOARD_SCACHE=y
-
-#
-# CPU selection
-#
-# CONFIG_CPU_MIPS32 is not set
-# CONFIG_CPU_MIPS64 is not set
-# CONFIG_CPU_R3000 is not set
-# CONFIG_CPU_TX39XX is not set
-# CONFIG_CPU_VR41XX is not set
-# CONFIG_CPU_R4300 is not set
-# CONFIG_CPU_R4X00 is not set
-# CONFIG_CPU_TX49XX is not set
-# CONFIG_CPU_R5000 is not set
-# CONFIG_CPU_R5432 is not set
-# CONFIG_CPU_R6000 is not set
-# CONFIG_CPU_NEVADA is not set
-# CONFIG_CPU_R8000 is not set
-# CONFIG_CPU_R10000 is not set
-CONFIG_CPU_RM7000=y
-# CONFIG_CPU_SB1 is not set
-CONFIG_CPU_HAS_PREFETCH=y
-# CONFIG_64BIT_PHYS_ADDR is not set
-# CONFIG_CPU_ADVANCED is not set
-CONFIG_CPU_HAS_LLSC=y
-CONFIG_CPU_HAS_LLDSCD=y
-CONFIG_CPU_HAS_SYNC=y
-# CONFIG_PREEMPT is not set
-# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
-
-#
-# Bus options (PCI, PCMCIA, EISA, ISA, TC)
-#
-# CONFIG_PCI is not set
-CONFIG_MMU=y
-# CONFIG_HOTPLUG is not set
-
-#
-# Executable file formats
-#
-CONFIG_KCORE_ELF=y
-CONFIG_BINFMT_ELF=y
-# CONFIG_BINFMT_MISC is not set
-CONFIG_TRAD_SIGNALS=y
-# CONFIG_BINFMT_IRIX is not set
-
-#
-# Memory Technology Devices (MTD)
-#
-# CONFIG_MTD is not set
-
-#
-# Parallel port support
-#
-# CONFIG_PARPORT is not set
-
-#
-# Plug and Play support
-#
-# CONFIG_PNP is not set
-
-#
-# Generic Driver Options
-#
-# CONFIG_FW_LOADER is not set
-
-#
-# Block devices
-#
-# CONFIG_BLK_DEV_FD is not set
-# CONFIG_BLK_DEV_LOOP is not set
-# CONFIG_BLK_DEV_NBD is not set
-# CONFIG_BLK_DEV_RAM is not set
-# CONFIG_BLK_DEV_INITRD is not set
-# CONFIG_LBD is not set
-
-#
-# ATA/ATAPI/MFM/RLL support
-#
-# CONFIG_IDE is not set
-
-#
-# SCSI device support
-#
-# CONFIG_SCSI is not set
-
-#
-# Multi-device support (RAID and LVM)
-#
-# CONFIG_MD is not set
-
-#
-# Fusion MPT device support
-#
-
-#
-# I2O device support
-#
-
-#
-# Networking support
-#
-CONFIG_NET=y
-
-#
-# Networking options
-#
-# CONFIG_PACKET is not set
-CONFIG_NETLINK_DEV=y
-# CONFIG_NETFILTER is not set
-CONFIG_UNIX=y
-CONFIG_NET_KEY=y
-CONFIG_INET=y
-# CONFIG_IP_MULTICAST is not set
-# CONFIG_IP_ADVANCED_ROUTER is not set
-CONFIG_IP_PNP=y
-# CONFIG_IP_PNP_DHCP is not set
-CONFIG_IP_PNP_BOOTP=y
-# CONFIG_IP_PNP_RARP is not set
-# CONFIG_NET_IPIP is not set
-# CONFIG_NET_IPGRE is not set
-# CONFIG_ARPD is not set
-# CONFIG_INET_ECN is not set
-# CONFIG_SYN_COOKIES is not set
-# CONFIG_INET_AH is not set
-# CONFIG_INET_ESP is not set
-# CONFIG_INET_IPCOMP is not set
-# CONFIG_IPV6 is not set
-# CONFIG_XFRM_USER is not set
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
-CONFIG_IPV6_SCTP__=y
-# CONFIG_IP_SCTP is not set
-# CONFIG_ATM is not set
-# CONFIG_VLAN_8021Q is not set
-# CONFIG_LLC is not set
-# CONFIG_DECNET is not set
-# CONFIG_BRIDGE is not set
-# CONFIG_X25 is not set
-# CONFIG_LAPB is not set
-# CONFIG_NET_DIVERT is not set
-# CONFIG_ECONET is not set
-# CONFIG_WAN_ROUTER is not set
-# CONFIG_NET_FASTROUTE is not set
-# CONFIG_NET_HW_FLOWCONTROL is not set
-
-#
-# QoS and/or fair queueing
-#
-# CONFIG_NET_SCHED is not set
-
-#
-# Network testing
-#
-# CONFIG_NET_PKTGEN is not set
-CONFIG_NETDEVICES=y
-# CONFIG_DUMMY is not set
-# CONFIG_BONDING is not set
-# CONFIG_EQUALIZER is not set
-# CONFIG_TUN is not set
-# CONFIG_ETHERTAP is not set
-
-#
-# Ethernet (10 or 100Mbit)
-#
-CONFIG_NET_ETHERNET=y
-# CONFIG_MII is not set
-
-#
-# Ethernet (1000 Mbit)
-#
-
-#
-# Ethernet (10000 Mbit)
-#
-# CONFIG_PPP is not set
-# CONFIG_SLIP is not set
-
-#
-# Wireless LAN (non-hamradio)
-#
-# CONFIG_NET_RADIO is not set
-
-#
-# Token Ring devices (depends on LLC=y)
-#
-# CONFIG_SHAPER is not set
-
-#
-# Wan interfaces
-#
-# CONFIG_WAN is not set
-
-#
-# Amateur Radio support
-#
-# CONFIG_HAMRADIO is not set
-
-#
-# IrDA (infrared) support
-#
-# CONFIG_IRDA is not set
-
-#
-# ISDN subsystem
-#
-# CONFIG_ISDN_BOOL is not set
-
-#
-# Telephony Support
-#
-# CONFIG_PHONE is not set
-
-#
-# Input device support
-#
-CONFIG_INPUT=y
-
-#
-# Userland interfaces
-#
-# CONFIG_INPUT_MOUSEDEV is not set
-# CONFIG_INPUT_JOYDEV is not set
-# CONFIG_INPUT_TSDEV is not set
-# CONFIG_INPUT_EVDEV is not set
-# CONFIG_INPUT_EVBUG is not set
-
-#
-# Input I/O drivers
-#
-# CONFIG_GAMEPORT is not set
-CONFIG_SOUND_GAMEPORT=y
-CONFIG_SERIO=y
-# CONFIG_SERIO_I8042 is not set
-CONFIG_SERIO_SERPORT=y
-# CONFIG_SERIO_CT82C710 is not set
-
-#
-# Input Device Drivers
-#
-# CONFIG_INPUT_KEYBOARD is not set
-# CONFIG_INPUT_MOUSE is not set
-# CONFIG_INPUT_JOYSTICK is not set
-# CONFIG_INPUT_TOUCHSCREEN is not set
-# CONFIG_INPUT_MISC is not set
-
-#
-# Character devices
-#
-# CONFIG_VT is not set
-# CONFIG_SERIAL_NONSTANDARD is not set
-
-#
-# Serial drivers
-#
-CONFIG_SERIAL_8250=y
-CONFIG_SERIAL_8250_CONSOLE=y
-# CONFIG_SERIAL_8250_EXTENDED is not set
-
-#
-# Non-8250 serial port support
-#
-CONFIG_SERIAL_CORE=y
-CONFIG_SERIAL_CORE_CONSOLE=y
-CONFIG_UNIX98_PTYS=y
-CONFIG_UNIX98_PTY_COUNT=256
-
-#
-# I2C support
-#
-# CONFIG_I2C is not set
-
-#
-# I2C Hardware Sensors Mainboard support
-#
-
-#
-# I2C Hardware Sensors Chip support
-#
-# CONFIG_I2C_SENSOR is not set
-
-#
-# Mice
-#
-# CONFIG_BUSMOUSE is not set
-# CONFIG_QIC02_TAPE is not set
-
-#
-# IPMI
-#
-# CONFIG_IPMI_HANDLER is not set
-
-#
-# Watchdog Cards
-#
-# CONFIG_WATCHDOG is not set
-# CONFIG_NVRAM is not set
-# CONFIG_RTC is not set
-# CONFIG_GEN_RTC is not set
-# CONFIG_DTLK is not set
-# CONFIG_R3964 is not set
-# CONFIG_APPLICOM is not set
-
-#
-# Ftape, the floppy tape device driver
-#
-# CONFIG_FTAPE is not set
-# CONFIG_AGP is not set
-# CONFIG_DRM is not set
-# CONFIG_RAW_DRIVER is not set
-# CONFIG_HANGCHECK_TIMER is not set
-
-#
-# Multimedia devices
-#
-# CONFIG_VIDEO_DEV is not set
-
-#
-# Digital Video Broadcasting Devices
-#
-# CONFIG_DVB is not set
-
-#
-# File systems
-#
-CONFIG_EXT2_FS=y
-# CONFIG_EXT2_FS_XATTR is not set
-# CONFIG_EXT3_FS is not set
-# CONFIG_JBD is not set
-# CONFIG_REISERFS_FS is not set
-# CONFIG_JFS_FS is not set
-# CONFIG_XFS_FS is not set
-# CONFIG_MINIX_FS is not set
-# CONFIG_ROMFS_FS is not set
-# CONFIG_QUOTA is not set
-# CONFIG_AUTOFS_FS is not set
-# CONFIG_AUTOFS4_FS is not set
-
-#
-# CD-ROM/DVD Filesystems
-#
-# CONFIG_ISO9660_FS is not set
-# CONFIG_UDF_FS is not set
-
-#
-# DOS/FAT/NT Filesystems
-#
-# CONFIG_FAT_FS is not set
-# CONFIG_NTFS_FS is not set
-
-#
-# Pseudo filesystems
-#
-CONFIG_PROC_FS=y
-# CONFIG_DEVFS_FS is not set
-CONFIG_DEVPTS_FS=y
-CONFIG_DEVPTS_FS_XATTR=y
-CONFIG_DEVPTS_FS_SECURITY=y
-# CONFIG_TMPFS is not set
-CONFIG_RAMFS=y
-
-#
-# Miscellaneous filesystems
-#
-# CONFIG_ADFS_FS is not set
-# CONFIG_AFFS_FS is not set
-# CONFIG_HFS_FS is not set
-# CONFIG_BEFS_FS is not set
-# CONFIG_BFS_FS is not set
-# CONFIG_EFS_FS is not set
-# CONFIG_CRAMFS is not set
-# CONFIG_VXFS_FS is not set
-# CONFIG_HPFS_FS is not set
-# CONFIG_QNX4FS_FS is not set
-# CONFIG_SYSV_FS is not set
-# CONFIG_UFS_FS is not set
-
-#
-# Network File Systems
-#
-CONFIG_NFS_FS=y
-# CONFIG_NFS_V3 is not set
-# CONFIG_NFS_V4 is not set
-CONFIG_NFSD=y
-# CONFIG_NFSD_V3 is not set
-# CONFIG_NFSD_TCP is not set
-CONFIG_ROOT_NFS=y
-CONFIG_LOCKD=y
-CONFIG_EXPORTFS=y
-CONFIG_SUNRPC=y
-# CONFIG_SUNRPC_GSS is not set
-# CONFIG_SMB_FS is not set
-# CONFIG_CIFS is not set
-# CONFIG_NCP_FS is not set
-# CONFIG_CODA_FS is not set
-# CONFIG_INTERMEZZO_FS is not set
-# CONFIG_AFS_FS is not set
-
-#
-# Partition Types
-#
-# CONFIG_PARTITION_ADVANCED is not set
-CONFIG_MSDOS_PARTITION=y
-
-#
-# Graphics support
-#
-
-#
-# Sound
-#
-# CONFIG_SOUND is not set
-
-#
-# USB support
-#
-# CONFIG_USB_GADGET is not set
-
-#
-# Bluetooth support
-#
-# CONFIG_BT is not set
-
-#
-# Kernel hacking
-#
-CONFIG_CROSSCOMPILE=y
-# CONFIG_DEBUG_KERNEL is not set
-
-#
-# Security options
-#
-# CONFIG_SECURITY is not set
-
-#
-# Cryptographic options
-#
-# CONFIG_CRYPTO is not set
-
-#
-# Library routines
-#
-# CONFIG_CRC32 is not set
--- diff/arch/mips/defconfig-osprey	2003-08-20 14:16:36.000000000 +0100
+++ source/arch/mips/defconfig-osprey	1970-01-01 01:00:00.000000000 +0100
@@ -1,531 +0,0 @@
-#
-# Automatically generated make config: don't edit
-#
-CONFIG_MIPS=y
-# CONFIG_MIPS64 is not set
-CONFIG_MIPS32=y
-
-#
-# Code maturity level options
-#
-CONFIG_EXPERIMENTAL=y
-
-#
-# General setup
-#
-CONFIG_SWAP=y
-CONFIG_SYSVIPC=y
-# CONFIG_BSD_PROCESS_ACCT is not set
-CONFIG_SYSCTL=y
-CONFIG_LOG_BUF_SHIFT=14
-# CONFIG_EMBEDDED is not set
-CONFIG_KALLSYMS=y
-CONFIG_FUTEX=y
-CONFIG_EPOLL=y
-CONFIG_IOSCHED_AS=y
-CONFIG_IOSCHED_DEADLINE=y
-
-#
-# Loadable module support
-#
-CONFIG_MODULES=y
-CONFIG_MODULE_UNLOAD=y
-# CONFIG_MODULE_FORCE_UNLOAD is not set
-CONFIG_OBSOLETE_MODPARM=y
-CONFIG_MODVERSIONS=y
-CONFIG_KMOD=y
-
-#
-# Machine selection
-#
-# CONFIG_ACER_PICA_61 is not set
-# CONFIG_BAGET_MIPS is not set
-# CONFIG_CASIO_E55 is not set
-# CONFIG_MIPS_COBALT is not set
-# CONFIG_DECSTATION is not set
-# CONFIG_MIPS_EV64120 is not set
-# CONFIG_MIPS_EV96100 is not set
-# CONFIG_MIPS_IVR is not set
-# CONFIG_LASAT is not set
-# CONFIG_HP_LASERJET is not set
-# CONFIG_IBM_WORKPAD is not set
-# CONFIG_MIPS_ITE8172 is not set
-# CONFIG_MIPS_ATLAS is not set
-# CONFIG_MIPS_MAGNUM_4000 is not set
-# CONFIG_MIPS_MALTA is not set
-# CONFIG_MIPS_SEAD is not set
-# CONFIG_MOMENCO_OCELOT is not set
-# CONFIG_MOMENCO_OCELOT_G is not set
-# CONFIG_MOMENCO_OCELOT_C is not set
-# CONFIG_DDB5074 is not set
-# CONFIG_DDB5476 is not set
-# CONFIG_DDB5477 is not set
-CONFIG_NEC_OSPREY=y
-# CONFIG_NEC_EAGLE is not set
-# CONFIG_OLIVETTI_M700 is not set
-# CONFIG_SGI_IP22 is not set
-# CONFIG_SGI_IP32 is not set
-# CONFIG_SOC_AU1X00 is not set
-# CONFIG_SIBYTE_SB1xxx_SOC is not set
-# CONFIG_SNI_RM200_PCI is not set
-# CONFIG_TANBAC_TB0226 is not set
-# CONFIG_TANBAC_TB0229 is not set
-# CONFIG_TOSHIBA_JMR3927 is not set
-# CONFIG_TOSHIBA_RBTX4927 is not set
-# CONFIG_VICTOR_MPC30X is not set
-# CONFIG_ZAO_CAPCELLA is not set
-CONFIG_RWSEM_GENERIC_SPINLOCK=y
-CONFIG_NONCOHERENT_IO=y
-CONFIG_CPU_LITTLE_ENDIAN=y
-CONFIG_IRQ_CPU=y
-CONFIG_DUMMY_KEYB=y
-# CONFIG_FB is not set
-CONFIG_VR4181=y
-
-#
-# CPU selection
-#
-# CONFIG_CPU_MIPS32 is not set
-# CONFIG_CPU_MIPS64 is not set
-# CONFIG_CPU_R3000 is not set
-# CONFIG_CPU_TX39XX is not set
-CONFIG_CPU_VR41XX=y
-# CONFIG_CPU_R4300 is not set
-# CONFIG_CPU_R4X00 is not set
-# CONFIG_CPU_TX49XX is not set
-# CONFIG_CPU_R5000 is not set
-# CONFIG_CPU_R5432 is not set
-# CONFIG_CPU_R6000 is not set
-# CONFIG_CPU_NEVADA is not set
-# CONFIG_CPU_R8000 is not set
-# CONFIG_CPU_R10000 is not set
-# CONFIG_CPU_RM7000 is not set
-# CONFIG_CPU_SB1 is not set
-# CONFIG_CPU_ADVANCED is not set
-CONFIG_CPU_HAS_SYNC=y
-# CONFIG_PREEMPT is not set
-# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
-
-#
-# Bus options (PCI, PCMCIA, EISA, ISA, TC)
-#
-CONFIG_MMU=y
-# CONFIG_HOTPLUG is not set
-
-#
-# Executable file formats
-#
-CONFIG_KCORE_ELF=y
-CONFIG_BINFMT_ELF=y
-# CONFIG_BINFMT_MISC is not set
-CONFIG_TRAD_SIGNALS=y
-
-#
-# Memory Technology Devices (MTD)
-#
-# CONFIG_MTD is not set
-
-#
-# Parallel port support
-#
-# CONFIG_PARPORT is not set
-
-#
-# Plug and Play support
-#
-# CONFIG_PNP is not set
-
-#
-# Generic Driver Options
-#
-# CONFIG_FW_LOADER is not set
-
-#
-# Block devices
-#
-# CONFIG_BLK_DEV_FD is not set
-# CONFIG_BLK_DEV_LOOP is not set
-# CONFIG_BLK_DEV_NBD is not set
-# CONFIG_BLK_DEV_RAM is not set
-# CONFIG_BLK_DEV_INITRD is not set
-# CONFIG_LBD is not set
-
-#
-# ATA/ATAPI/MFM/RLL support
-#
-# CONFIG_IDE is not set
-
-#
-# SCSI device support
-#
-# CONFIG_SCSI is not set
-
-#
-# Multi-device support (RAID and LVM)
-#
-# CONFIG_MD is not set
-
-#
-# Fusion MPT device support
-#
-
-#
-# I2O device support
-#
-
-#
-# Networking support
-#
-CONFIG_NET=y
-
-#
-# Networking options
-#
-CONFIG_PACKET=y
-# CONFIG_PACKET_MMAP is not set
-CONFIG_NETLINK_DEV=y
-# CONFIG_NETFILTER is not set
-CONFIG_UNIX=y
-CONFIG_NET_KEY=y
-CONFIG_INET=y
-# CONFIG_IP_MULTICAST is not set
-# CONFIG_IP_ADVANCED_ROUTER is not set
-CONFIG_IP_PNP=y
-# CONFIG_IP_PNP_DHCP is not set
-CONFIG_IP_PNP_BOOTP=y
-# CONFIG_IP_PNP_RARP is not set
-# CONFIG_NET_IPIP is not set
-# CONFIG_NET_IPGRE is not set
-# CONFIG_ARPD is not set
-# CONFIG_INET_ECN is not set
-# CONFIG_SYN_COOKIES is not set
-# CONFIG_INET_AH is not set
-# CONFIG_INET_ESP is not set
-# CONFIG_INET_IPCOMP is not set
-# CONFIG_IPV6 is not set
-# CONFIG_XFRM_USER is not set
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
-CONFIG_IPV6_SCTP__=y
-# CONFIG_IP_SCTP is not set
-# CONFIG_ATM is not set
-# CONFIG_VLAN_8021Q is not set
-# CONFIG_LLC is not set
-# CONFIG_DECNET is not set
-# CONFIG_BRIDGE is not set
-# CONFIG_X25 is not set
-# CONFIG_LAPB is not set
-# CONFIG_NET_DIVERT is not set
-# CONFIG_ECONET is not set
-# CONFIG_WAN_ROUTER is not set
-# CONFIG_NET_FASTROUTE is not set
-# CONFIG_NET_HW_FLOWCONTROL is not set
-
-#
-# QoS and/or fair queueing
-#
-# CONFIG_NET_SCHED is not set
-
-#
-# Network testing
-#
-# CONFIG_NET_PKTGEN is not set
-CONFIG_NETDEVICES=y
-# CONFIG_DUMMY is not set
-# CONFIG_BONDING is not set
-# CONFIG_EQUALIZER is not set
-# CONFIG_TUN is not set
-# CONFIG_ETHERTAP is not set
-
-#
-# Ethernet (10 or 100Mbit)
-#
-CONFIG_NET_ETHERNET=y
-# CONFIG_MII is not set
-
-#
-# Ethernet (1000 Mbit)
-#
-
-#
-# Ethernet (10000 Mbit)
-#
-# CONFIG_PPP is not set
-# CONFIG_SLIP is not set
-
-#
-# Wireless LAN (non-hamradio)
-#
-# CONFIG_NET_RADIO is not set
-
-#
-# Token Ring devices (depends on LLC=y)
-#
-# CONFIG_SHAPER is not set
-
-#
-# Wan interfaces
-#
-# CONFIG_WAN is not set
-
-#
-# Amateur Radio support
-#
-# CONFIG_HAMRADIO is not set
-
-#
-# IrDA (infrared) support
-#
-# CONFIG_IRDA is not set
-
-#
-# ISDN subsystem
-#
-# CONFIG_ISDN_BOOL is not set
-
-#
-# Telephony Support
-#
-# CONFIG_PHONE is not set
-
-#
-# Input device support
-#
-CONFIG_INPUT=y
-
-#
-# Userland interfaces
-#
-# CONFIG_INPUT_MOUSEDEV is not set
-# CONFIG_INPUT_JOYDEV is not set
-# CONFIG_INPUT_TSDEV is not set
-# CONFIG_INPUT_EVDEV is not set
-# CONFIG_INPUT_EVBUG is not set
-
-#
-# Input I/O drivers
-#
-# CONFIG_GAMEPORT is not set
-CONFIG_SOUND_GAMEPORT=y
-CONFIG_SERIO=y
-# CONFIG_SERIO_I8042 is not set
-CONFIG_SERIO_SERPORT=y
-# CONFIG_SERIO_CT82C710 is not set
-
-#
-# Input Device Drivers
-#
-# CONFIG_INPUT_KEYBOARD is not set
-# CONFIG_INPUT_MOUSE is not set
-# CONFIG_INPUT_JOYSTICK is not set
-# CONFIG_INPUT_TOUCHSCREEN is not set
-# CONFIG_INPUT_MISC is not set
-
-#
-# Character devices
-#
-CONFIG_VT=y
-# CONFIG_VT_CONSOLE is not set
-CONFIG_HW_CONSOLE=y
-# CONFIG_SERIAL_NONSTANDARD is not set
-
-#
-# Serial drivers
-#
-CONFIG_SERIAL_8250=y
-CONFIG_SERIAL_8250_CONSOLE=y
-# CONFIG_SERIAL_8250_EXTENDED is not set
-
-#
-# Non-8250 serial port support
-#
-CONFIG_SERIAL_CORE=y
-CONFIG_SERIAL_CORE_CONSOLE=y
-CONFIG_UNIX98_PTYS=y
-CONFIG_UNIX98_PTY_COUNT=256
-
-#
-# I2C support
-#
-# CONFIG_I2C is not set
-
-#
-# I2C Hardware Sensors Mainboard support
-#
-
-#
-# I2C Hardware Sensors Chip support
-#
-# CONFIG_I2C_SENSOR is not set
-
-#
-# Mice
-#
-# CONFIG_BUSMOUSE is not set
-# CONFIG_QIC02_TAPE is not set
-
-#
-# IPMI
-#
-# CONFIG_IPMI_HANDLER is not set
-
-#
-# Watchdog Cards
-#
-# CONFIG_WATCHDOG is not set
-# CONFIG_NVRAM is not set
-# CONFIG_RTC is not set
-# CONFIG_GEN_RTC is not set
-# CONFIG_DTLK is not set
-# CONFIG_R3964 is not set
-# CONFIG_APPLICOM is not set
-
-#
-# Ftape, the floppy tape device driver
-#
-# CONFIG_FTAPE is not set
-# CONFIG_AGP is not set
-# CONFIG_DRM is not set
-# CONFIG_RAW_DRIVER is not set
-# CONFIG_HANGCHECK_TIMER is not set
-
-#
-# Multimedia devices
-#
-# CONFIG_VIDEO_DEV is not set
-
-#
-# Digital Video Broadcasting Devices
-#
-# CONFIG_DVB is not set
-
-#
-# File systems
-#
-CONFIG_EXT2_FS=y
-# CONFIG_EXT2_FS_XATTR is not set
-# CONFIG_EXT3_FS is not set
-# CONFIG_JBD is not set
-# CONFIG_REISERFS_FS is not set
-# CONFIG_JFS_FS is not set
-# CONFIG_XFS_FS is not set
-# CONFIG_MINIX_FS is not set
-# CONFIG_ROMFS_FS is not set
-# CONFIG_QUOTA is not set
-# CONFIG_AUTOFS_FS is not set
-# CONFIG_AUTOFS4_FS is not set
-
-#
-# CD-ROM/DVD Filesystems
-#
-# CONFIG_ISO9660_FS is not set
-# CONFIG_UDF_FS is not set
-
-#
-# DOS/FAT/NT Filesystems
-#
-# CONFIG_FAT_FS is not set
-# CONFIG_NTFS_FS is not set
-
-#
-# Pseudo filesystems
-#
-CONFIG_PROC_FS=y
-# CONFIG_DEVFS_FS is not set
-CONFIG_DEVPTS_FS=y
-CONFIG_DEVPTS_FS_XATTR=y
-CONFIG_DEVPTS_FS_SECURITY=y
-# CONFIG_TMPFS is not set
-CONFIG_RAMFS=y
-
-#
-# Miscellaneous filesystems
-#
-# CONFIG_ADFS_FS is not set
-# CONFIG_AFFS_FS is not set
-# CONFIG_HFS_FS is not set
-# CONFIG_BEFS_FS is not set
-# CONFIG_BFS_FS is not set
-# CONFIG_EFS_FS is not set
-# CONFIG_CRAMFS is not set
-# CONFIG_VXFS_FS is not set
-# CONFIG_HPFS_FS is not set
-# CONFIG_QNX4FS_FS is not set
-# CONFIG_SYSV_FS is not set
-# CONFIG_UFS_FS is not set
-
-#
-# Network File Systems
-#
-CONFIG_NFS_FS=y
-# CONFIG_NFS_V3 is not set
-# CONFIG_NFS_V4 is not set
-CONFIG_NFSD=y
-# CONFIG_NFSD_V3 is not set
-# CONFIG_NFSD_TCP is not set
-CONFIG_ROOT_NFS=y
-CONFIG_LOCKD=y
-CONFIG_EXPORTFS=y
-CONFIG_SUNRPC=y
-# CONFIG_SUNRPC_GSS is not set
-# CONFIG_SMB_FS is not set
-# CONFIG_CIFS is not set
-# CONFIG_NCP_FS is not set
-# CONFIG_CODA_FS is not set
-# CONFIG_INTERMEZZO_FS is not set
-# CONFIG_AFS_FS is not set
-
-#
-# Partition Types
-#
-# CONFIG_PARTITION_ADVANCED is not set
-CONFIG_MSDOS_PARTITION=y
-
-#
-# Graphics support
-#
-
-#
-# Console display driver support
-#
-# CONFIG_VGA_CONSOLE is not set
-# CONFIG_MDA_CONSOLE is not set
-CONFIG_DUMMY_CONSOLE=y
-
-#
-# Sound
-#
-# CONFIG_SOUND is not set
-
-#
-# USB support
-#
-# CONFIG_USB_GADGET is not set
-
-#
-# Bluetooth support
-#
-# CONFIG_BT is not set
-
-#
-# Kernel hacking
-#
-CONFIG_CROSSCOMPILE=y
-# CONFIG_DEBUG_KERNEL is not set
-
-#
-# Security options
-#
-# CONFIG_SECURITY is not set
-
-#
-# Cryptographic options
-#
-# CONFIG_CRYPTO is not set
-
-#
-# Library routines
-#
-# CONFIG_CRC32 is not set
--- diff/arch/mips/defconfig-pb1000	2003-08-20 14:16:25.000000000 +0100
+++ source/arch/mips/defconfig-pb1000	1970-01-01 01:00:00.000000000 +0100
@@ -1,711 +0,0 @@
-#
-# Automatically generated make config: don't edit
-#
-CONFIG_MIPS=y
-# CONFIG_MIPS64 is not set
-CONFIG_MIPS32=y
-
-#
-# Code maturity level options
-#
-CONFIG_EXPERIMENTAL=y
-
-#
-# General setup
-#
-CONFIG_SWAP=y
-CONFIG_SYSVIPC=y
-# CONFIG_BSD_PROCESS_ACCT is not set
-CONFIG_SYSCTL=y
-CONFIG_LOG_BUF_SHIFT=14
-# CONFIG_EMBEDDED is not set
-CONFIG_KALLSYMS=y
-CONFIG_FUTEX=y
-CONFIG_EPOLL=y
-CONFIG_IOSCHED_AS=y
-CONFIG_IOSCHED_DEADLINE=y
-
-#
-# Loadable module support
-#
-CONFIG_MODULES=y
-CONFIG_MODULE_UNLOAD=y
-# CONFIG_MODULE_FORCE_UNLOAD is not set
-CONFIG_OBSOLETE_MODPARM=y
-CONFIG_MODVERSIONS=y
-CONFIG_KMOD=y
-
-#
-# Machine selection
-#
-# CONFIG_ACER_PICA_61 is not set
-# CONFIG_BAGET_MIPS is not set
-# CONFIG_CASIO_E55 is not set
-# CONFIG_MIPS_COBALT is not set
-# CONFIG_DECSTATION is not set
-# CONFIG_MIPS_EV64120 is not set
-# CONFIG_MIPS_EV96100 is not set
-# CONFIG_MIPS_IVR is not set
-# CONFIG_LASAT is not set
-# CONFIG_HP_LASERJET is not set
-# CONFIG_IBM_WORKPAD is not set
-# CONFIG_MIPS_ITE8172 is not set
-# CONFIG_MIPS_ATLAS is not set
-# CONFIG_MIPS_MAGNUM_4000 is not set
-# CONFIG_MIPS_MALTA is not set
-# CONFIG_MIPS_SEAD is not set
-# CONFIG_MOMENCO_OCELOT is not set
-# CONFIG_MOMENCO_OCELOT_G is not set
-# CONFIG_MOMENCO_OCELOT_C is not set
-# CONFIG_DDB5074 is not set
-# CONFIG_DDB5476 is not set
-# CONFIG_DDB5477 is not set
-# CONFIG_NEC_OSPREY is not set
-# CONFIG_NEC_EAGLE is not set
-# CONFIG_OLIVETTI_M700 is not set
-# CONFIG_SGI_IP22 is not set
-# CONFIG_SGI_IP32 is not set
-# CONFIG_SOC_AU1X00 is not set
-# CONFIG_SIBYTE_SB1xxx_SOC is not set
-# CONFIG_SNI_RM200_PCI is not set
-# CONFIG_TANBAC_TB0226 is not set
-# CONFIG_TANBAC_TB0229 is not set
-# CONFIG_TOSHIBA_JMR3927 is not set
-# CONFIG_TOSHIBA_RBTX4927 is not set
-# CONFIG_VICTOR_MPC30X is not set
-# CONFIG_ZAO_CAPCELLA is not set
-CONFIG_RWSEM_GENERIC_SPINLOCK=y
-CONFIG_CPU_LITTLE_ENDIAN=y
-CONFIG_FB=y
-
-#
-# CPU selection
-#
-CONFIG_CPU_MIPS32=y
-# CONFIG_CPU_MIPS64 is not set
-# CONFIG_CPU_R3000 is not set
-# CONFIG_CPU_TX39XX is not set
-# CONFIG_CPU_VR41XX is not set
-# CONFIG_CPU_R4300 is not set
-# CONFIG_CPU_R4X00 is not set
-# CONFIG_CPU_TX49XX is not set
-# CONFIG_CPU_R5000 is not set
-# CONFIG_CPU_R5432 is not set
-# CONFIG_CPU_R6000 is not set
-# CONFIG_CPU_NEVADA is not set
-# CONFIG_CPU_R8000 is not set
-# CONFIG_CPU_R10000 is not set
-# CONFIG_CPU_RM7000 is not set
-# CONFIG_CPU_SB1 is not set
-CONFIG_CPU_HAS_PREFETCH=y
-# CONFIG_VTAG_ICACHE is not set
-CONFIG_64BIT_PHYS_ADDR=y
-CONFIG_CPU_ADVANCED=y
-CONFIG_CPU_HAS_LLSC=y
-# CONFIG_CPU_HAS_LLDSCD is not set
-CONFIG_CPU_HAS_WB=y
-CONFIG_CPU_HAS_SYNC=y
-# CONFIG_PREEMPT is not set
-# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
-
-#
-# Bus options (PCI, PCMCIA, EISA, ISA, TC)
-#
-CONFIG_MMU=y
-CONFIG_HOTPLUG=y
-
-#
-# PCMCIA/CardBus support
-#
-CONFIG_PCMCIA=m
-# CONFIG_TCIC is not set
-
-#
-# PCI Hotplug Support
-#
-
-#
-# Executable file formats
-#
-CONFIG_KCORE_ELF=y
-CONFIG_BINFMT_ELF=y
-# CONFIG_BINFMT_MISC is not set
-CONFIG_TRAD_SIGNALS=y
-
-#
-# Memory Technology Devices (MTD)
-#
-CONFIG_MTD=y
-# CONFIG_MTD_DEBUG is not set
-CONFIG_MTD_PARTITIONS=y
-# CONFIG_MTD_CONCAT is not set
-# CONFIG_MTD_REDBOOT_PARTS is not set
-# CONFIG_MTD_CMDLINE_PARTS is not set
-
-#
-# User Modules And Translation Layers
-#
-CONFIG_MTD_CHAR=y
-CONFIG_MTD_BLOCK=y
-# CONFIG_FTL is not set
-# CONFIG_NFTL is not set
-# CONFIG_INFTL is not set
-
-#
-# RAM/ROM/Flash chip drivers
-#
-CONFIG_MTD_CFI=y
-# CONFIG_MTD_JEDECPROBE is not set
-CONFIG_MTD_GEN_PROBE=y
-# CONFIG_MTD_CFI_ADV_OPTIONS is not set
-# CONFIG_MTD_CFI_INTELEXT is not set
-CONFIG_MTD_CFI_AMDSTD=y
-# CONFIG_MTD_CFI_STAA is not set
-# CONFIG_MTD_RAM is not set
-# CONFIG_MTD_ROM is not set
-# CONFIG_MTD_ABSENT is not set
-# CONFIG_MTD_OBSOLETE_CHIPS is not set
-
-#
-# Mapping drivers for chip access
-#
-# CONFIG_MTD_COMPLEX_MAPPINGS is not set
-# CONFIG_MTD_PHYSMAP is not set
-
-#
-# Self-contained MTD device drivers
-#
-# CONFIG_MTD_SLRAM is not set
-# CONFIG_MTD_MTDRAM is not set
-# CONFIG_MTD_BLKMTD is not set
-
-#
-# Disk-On-Chip Device Drivers
-#
-# CONFIG_MTD_DOC2000 is not set
-# CONFIG_MTD_DOC2001 is not set
-# CONFIG_MTD_DOC2001PLUS is not set
-
-#
-# NAND Flash Device Drivers
-#
-# CONFIG_MTD_NAND is not set
-
-#
-# Parallel port support
-#
-# CONFIG_PARPORT is not set
-
-#
-# Plug and Play support
-#
-# CONFIG_PNP is not set
-
-#
-# Generic Driver Options
-#
-# CONFIG_FW_LOADER is not set
-
-#
-# Block devices
-#
-# CONFIG_BLK_DEV_FD is not set
-# CONFIG_BLK_DEV_LOOP is not set
-# CONFIG_BLK_DEV_NBD is not set
-# CONFIG_BLK_DEV_RAM is not set
-# CONFIG_BLK_DEV_INITRD is not set
-# CONFIG_LBD is not set
-
-#
-# ATA/ATAPI/MFM/RLL support
-#
-CONFIG_IDE=y
-
-#
-# IDE, ATA and ATAPI Block devices
-#
-CONFIG_BLK_DEV_IDE=y
-
-#
-# Please see Documentation/ide.txt for help/info on IDE drives
-#
-# CONFIG_BLK_DEV_HD is not set
-CONFIG_BLK_DEV_IDEDISK=y
-# CONFIG_IDEDISK_MULTI_MODE is not set
-# CONFIG_IDEDISK_STROKE is not set
-CONFIG_BLK_DEV_IDECS=m
-# CONFIG_BLK_DEV_IDECD is not set
-# CONFIG_BLK_DEV_IDEFLOPPY is not set
-# CONFIG_IDE_TASK_IOCTL is not set
-CONFIG_IDE_TASKFILE_IO=y
-
-#
-# IDE chipset support/bugfixes
-#
-
-#
-# SCSI device support
-#
-# CONFIG_SCSI is not set
-
-#
-# Multi-device support (RAID and LVM)
-#
-# CONFIG_MD is not set
-
-#
-# Fusion MPT device support
-#
-
-#
-# I2O device support
-#
-
-#
-# Networking support
-#
-CONFIG_NET=y
-
-#
-# Networking options
-#
-CONFIG_PACKET=y
-# CONFIG_PACKET_MMAP is not set
-# CONFIG_NETLINK_DEV is not set
-# CONFIG_NETFILTER is not set
-CONFIG_UNIX=y
-CONFIG_NET_KEY=y
-CONFIG_INET=y
-# CONFIG_IP_MULTICAST is not set
-# CONFIG_IP_ADVANCED_ROUTER is not set
-CONFIG_IP_PNP=y
-# CONFIG_IP_PNP_DHCP is not set
-CONFIG_IP_PNP_BOOTP=y
-# CONFIG_IP_PNP_RARP is not set
-# CONFIG_NET_IPIP is not set
-# CONFIG_NET_IPGRE is not set
-# CONFIG_ARPD is not set
-# CONFIG_INET_ECN is not set
-# CONFIG_SYN_COOKIES is not set
-# CONFIG_INET_AH is not set
-# CONFIG_INET_ESP is not set
-# CONFIG_INET_IPCOMP is not set
-# CONFIG_IPV6 is not set
-# CONFIG_XFRM_USER is not set
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
-CONFIG_IPV6_SCTP__=y
-# CONFIG_IP_SCTP is not set
-# CONFIG_ATM is not set
-# CONFIG_VLAN_8021Q is not set
-# CONFIG_LLC is not set
-# CONFIG_DECNET is not set
-# CONFIG_BRIDGE is not set
-# CONFIG_X25 is not set
-# CONFIG_LAPB is not set
-# CONFIG_NET_DIVERT is not set
-# CONFIG_ECONET is not set
-# CONFIG_WAN_ROUTER is not set
-# CONFIG_NET_FASTROUTE is not set
-# CONFIG_NET_HW_FLOWCONTROL is not set
-
-#
-# QoS and/or fair queueing
-#
-# CONFIG_NET_SCHED is not set
-
-#
-# Network testing
-#
-# CONFIG_NET_PKTGEN is not set
-CONFIG_NETDEVICES=y
-# CONFIG_DUMMY is not set
-# CONFIG_BONDING is not set
-# CONFIG_EQUALIZER is not set
-# CONFIG_TUN is not set
-# CONFIG_ETHERTAP is not set
-
-#
-# Ethernet (10 or 100Mbit)
-#
-CONFIG_NET_ETHERNET=y
-# CONFIG_MII is not set
-
-#
-# Ethernet (1000 Mbit)
-#
-
-#
-# Ethernet (10000 Mbit)
-#
-# CONFIG_PPP is not set
-# CONFIG_SLIP is not set
-
-#
-# Wireless LAN (non-hamradio)
-#
-# CONFIG_NET_RADIO is not set
-
-#
-# Token Ring devices (depends on LLC=y)
-#
-# CONFIG_SHAPER is not set
-
-#
-# Wan interfaces
-#
-# CONFIG_WAN is not set
-
-#
-# PCMCIA network device support
-#
-CONFIG_NET_PCMCIA=y
-CONFIG_PCMCIA_3C589=m
-# CONFIG_PCMCIA_3C574 is not set
-# CONFIG_PCMCIA_FMVJ18X is not set
-# CONFIG_PCMCIA_PCNET is not set
-# CONFIG_PCMCIA_NMCLAN is not set
-# CONFIG_PCMCIA_SMC91C92 is not set
-# CONFIG_PCMCIA_XIRC2PS is not set
-# CONFIG_PCMCIA_AXNET is not set
-
-#
-# Amateur Radio support
-#
-# CONFIG_HAMRADIO is not set
-
-#
-# IrDA (infrared) support
-#
-CONFIG_IRDA=y
-
-#
-# IrDA protocols
-#
-CONFIG_IRLAN=m
-CONFIG_IRCOMM=m
-# CONFIG_IRDA_ULTRA is not set
-
-#
-# IrDA options
-#
-CONFIG_IRDA_CACHE_LAST_LSAP=y
-CONFIG_IRDA_FAST_RR=y
-# CONFIG_IRDA_DEBUG is not set
-
-#
-# Infrared-port device drivers
-#
-
-#
-# SIR device drivers
-#
-# CONFIG_IRTTY_SIR is not set
-
-#
-# Dongle support
-#
-
-#
-# Old SIR device drivers
-#
-# CONFIG_IRTTY_OLD is not set
-# CONFIG_IRPORT_SIR is not set
-
-#
-# Old Serial dongle support
-#
-
-#
-# FIR device drivers
-#
-# CONFIG_TOSHIBA_OLD is not set
-# CONFIG_TOSHIBA_FIR is not set
-# CONFIG_VLSI_FIR is not set
-
-#
-# ISDN subsystem
-#
-# CONFIG_ISDN_BOOL is not set
-
-#
-# Telephony Support
-#
-# CONFIG_PHONE is not set
-
-#
-# Input device support
-#
-CONFIG_INPUT=y
-
-#
-# Userland interfaces
-#
-# CONFIG_INPUT_MOUSEDEV is not set
-# CONFIG_INPUT_JOYDEV is not set
-# CONFIG_INPUT_TSDEV is not set
-# CONFIG_INPUT_EVDEV is not set
-# CONFIG_INPUT_EVBUG is not set
-
-#
-# Input I/O drivers
-#
-# CONFIG_GAMEPORT is not set
-CONFIG_SOUND_GAMEPORT=y
-# CONFIG_SERIO is not set
-
-#
-# Input Device Drivers
-#
-# CONFIG_INPUT_KEYBOARD is not set
-# CONFIG_INPUT_MOUSE is not set
-# CONFIG_INPUT_JOYSTICK is not set
-# CONFIG_INPUT_TOUCHSCREEN is not set
-# CONFIG_INPUT_MISC is not set
-
-#
-# Character devices
-#
-CONFIG_VT=y
-CONFIG_VT_CONSOLE=y
-CONFIG_HW_CONSOLE=y
-CONFIG_SERIAL_NONSTANDARD=y
-# CONFIG_COMPUTONE is not set
-# CONFIG_ROCKETPORT is not set
-# CONFIG_CYCLADES is not set
-# CONFIG_DIGIEPCA is not set
-# CONFIG_DIGI is not set
-# CONFIG_MOXA_INTELLIO is not set
-# CONFIG_MOXA_SMARTIO is not set
-# CONFIG_ISI is not set
-# CONFIG_SYNCLINK is not set
-# CONFIG_SYNCLINKMP is not set
-# CONFIG_N_HDLC is not set
-# CONFIG_RISCOM8 is not set
-# CONFIG_SPECIALIX is not set
-# CONFIG_SX is not set
-# CONFIG_RIO is not set
-# CONFIG_STALDRV is not set
-
-#
-# Serial drivers
-#
-# CONFIG_SERIAL_8250 is not set
-
-#
-# Non-8250 serial port support
-#
-CONFIG_UNIX98_PTYS=y
-CONFIG_UNIX98_PTY_COUNT=256
-
-#
-# I2C support
-#
-# CONFIG_I2C is not set
-
-#
-# I2C Hardware Sensors Mainboard support
-#
-
-#
-# I2C Hardware Sensors Chip support
-#
-# CONFIG_I2C_SENSOR is not set
-
-#
-# Mice
-#
-# CONFIG_BUSMOUSE is not set
-# CONFIG_QIC02_TAPE is not set
-
-#
-# IPMI
-#
-# CONFIG_IPMI_HANDLER is not set
-
-#
-# Watchdog Cards
-#
-# CONFIG_WATCHDOG is not set
-# CONFIG_NVRAM is not set
-# CONFIG_RTC is not set
-# CONFIG_GEN_RTC is not set
-# CONFIG_DTLK is not set
-# CONFIG_R3964 is not set
-# CONFIG_APPLICOM is not set
-
-#
-# Ftape, the floppy tape device driver
-#
-# CONFIG_FTAPE is not set
-# CONFIG_AGP is not set
-# CONFIG_DRM is not set
-
-#
-# PCMCIA character devices
-#
-# CONFIG_SYNCLINK_CS is not set
-# CONFIG_RAW_DRIVER is not set
-# CONFIG_HANGCHECK_TIMER is not set
-
-#
-# Multimedia devices
-#
-# CONFIG_VIDEO_DEV is not set
-
-#
-# Digital Video Broadcasting Devices
-#
-# CONFIG_DVB is not set
-
-#
-# File systems
-#
-CONFIG_EXT2_FS=y
-# CONFIG_EXT2_FS_XATTR is not set
-# CONFIG_EXT3_FS is not set
-# CONFIG_JBD is not set
-# CONFIG_REISERFS_FS is not set
-# CONFIG_JFS_FS is not set
-# CONFIG_XFS_FS is not set
-# CONFIG_MINIX_FS is not set
-# CONFIG_ROMFS_FS is not set
-# CONFIG_QUOTA is not set
-CONFIG_AUTOFS_FS=y
-CONFIG_AUTOFS4_FS=y
-
-#
-# CD-ROM/DVD Filesystems
-#
-# CONFIG_ISO9660_FS is not set
-# CONFIG_UDF_FS is not set
-
-#
-# DOS/FAT/NT Filesystems
-#
-# CONFIG_FAT_FS is not set
-# CONFIG_NTFS_FS is not set
-
-#
-# Pseudo filesystems
-#
-CONFIG_PROC_FS=y
-# CONFIG_DEVFS_FS is not set
-CONFIG_DEVPTS_FS=y
-CONFIG_DEVPTS_FS_XATTR=y
-CONFIG_DEVPTS_FS_SECURITY=y
-# CONFIG_TMPFS is not set
-CONFIG_RAMFS=y
-
-#
-# Miscellaneous filesystems
-#
-# CONFIG_ADFS_FS is not set
-# CONFIG_AFFS_FS is not set
-# CONFIG_HFS_FS is not set
-# CONFIG_BEFS_FS is not set
-# CONFIG_BFS_FS is not set
-# CONFIG_EFS_FS is not set
-# CONFIG_JFFS_FS is not set
-CONFIG_JFFS2_FS=y
-CONFIG_JFFS2_FS_DEBUG=0
-# CONFIG_JFFS2_FS_NAND is not set
-# CONFIG_CRAMFS is not set
-# CONFIG_VXFS_FS is not set
-# CONFIG_HPFS_FS is not set
-# CONFIG_QNX4FS_FS is not set
-# CONFIG_SYSV_FS is not set
-# CONFIG_UFS_FS is not set
-
-#
-# Network File Systems
-#
-CONFIG_NFS_FS=y
-# CONFIG_NFS_V3 is not set
-# CONFIG_NFS_V4 is not set
-# CONFIG_NFSD is not set
-CONFIG_ROOT_NFS=y
-CONFIG_LOCKD=y
-# CONFIG_EXPORTFS is not set
-CONFIG_SUNRPC=y
-# CONFIG_SUNRPC_GSS is not set
-# CONFIG_SMB_FS is not set
-# CONFIG_CIFS is not set
-# CONFIG_NCP_FS is not set
-# CONFIG_CODA_FS is not set
-# CONFIG_INTERMEZZO_FS is not set
-# CONFIG_AFS_FS is not set
-
-#
-# Partition Types
-#
-# CONFIG_PARTITION_ADVANCED is not set
-CONFIG_MSDOS_PARTITION=y
-
-#
-# Graphics support
-#
-# CONFIG_FB_VIRTUAL is not set
-
-#
-# Console display driver support
-#
-# CONFIG_VGA_CONSOLE is not set
-# CONFIG_MDA_CONSOLE is not set
-CONFIG_DUMMY_CONSOLE=y
-# CONFIG_FRAMEBUFFER_CONSOLE is not set
-
-#
-# Logo configuration
-#
-# CONFIG_LOGO is not set
-
-#
-# Sound
-#
-CONFIG_SOUND=y
-
-#
-# Advanced Linux Sound Architecture
-#
-# CONFIG_SND is not set
-
-#
-# Open Sound System
-#
-# CONFIG_SOUND_PRIME is not set
-
-#
-# USB support
-#
-# CONFIG_USB_GADGET is not set
-
-#
-# Bluetooth support
-#
-# CONFIG_BT is not set
-
-#
-# Kernel hacking
-#
-CONFIG_CROSSCOMPILE=y
-# CONFIG_DEBUG_KERNEL is not set
-
-#
-# Security options
-#
-# CONFIG_SECURITY is not set
-
-#
-# Cryptographic options
-#
-# CONFIG_CRYPTO is not set
-
-#
-# Library routines
-#
-# CONFIG_CRC32 is not set
-CONFIG_ZLIB_INFLATE=y
-CONFIG_ZLIB_DEFLATE=y
--- diff/arch/mips/defconfig-pb1100	2003-08-20 14:16:25.000000000 +0100
+++ source/arch/mips/defconfig-pb1100	1970-01-01 01:00:00.000000000 +0100
@@ -1,791 +0,0 @@
-#
-# Automatically generated make config: don't edit
-#
-CONFIG_MIPS=y
-# CONFIG_MIPS64 is not set
-CONFIG_MIPS32=y
-
-#
-# Code maturity level options
-#
-CONFIG_EXPERIMENTAL=y
-
-#
-# General setup
-#
-CONFIG_SWAP=y
-CONFIG_SYSVIPC=y
-# CONFIG_BSD_PROCESS_ACCT is not set
-CONFIG_SYSCTL=y
-CONFIG_LOG_BUF_SHIFT=14
-# CONFIG_EMBEDDED is not set
-CONFIG_KALLSYMS=y
-CONFIG_FUTEX=y
-CONFIG_EPOLL=y
-CONFIG_IOSCHED_AS=y
-CONFIG_IOSCHED_DEADLINE=y
-
-#
-# Loadable module support
-#
-CONFIG_MODULES=y
-CONFIG_MODULE_UNLOAD=y
-# CONFIG_MODULE_FORCE_UNLOAD is not set
-CONFIG_OBSOLETE_MODPARM=y
-CONFIG_MODVERSIONS=y
-CONFIG_KMOD=y
-
-#
-# Machine selection
-#
-# CONFIG_ACER_PICA_61 is not set
-# CONFIG_BAGET_MIPS is not set
-# CONFIG_CASIO_E55 is not set
-# CONFIG_MIPS_COBALT is not set
-# CONFIG_DECSTATION is not set
-# CONFIG_MIPS_EV64120 is not set
-# CONFIG_MIPS_EV96100 is not set
-# CONFIG_MIPS_IVR is not set
-# CONFIG_LASAT is not set
-# CONFIG_HP_LASERJET is not set
-# CONFIG_IBM_WORKPAD is not set
-# CONFIG_MIPS_ITE8172 is not set
-# CONFIG_MIPS_ATLAS is not set
-# CONFIG_MIPS_MAGNUM_4000 is not set
-# CONFIG_MIPS_MALTA is not set
-# CONFIG_MIPS_SEAD is not set
-# CONFIG_MOMENCO_OCELOT is not set
-# CONFIG_MOMENCO_OCELOT_G is not set
-# CONFIG_MOMENCO_OCELOT_C is not set
-# CONFIG_DDB5074 is not set
-# CONFIG_DDB5476 is not set
-# CONFIG_DDB5477 is not set
-# CONFIG_NEC_OSPREY is not set
-# CONFIG_NEC_EAGLE is not set
-# CONFIG_OLIVETTI_M700 is not set
-# CONFIG_SGI_IP22 is not set
-# CONFIG_SGI_IP32 is not set
-# CONFIG_SOC_AU1X00 is not set
-# CONFIG_SIBYTE_SB1xxx_SOC is not set
-# CONFIG_SNI_RM200_PCI is not set
-# CONFIG_TANBAC_TB0226 is not set
-# CONFIG_TANBAC_TB0229 is not set
-# CONFIG_TOSHIBA_JMR3927 is not set
-# CONFIG_TOSHIBA_RBTX4927 is not set
-# CONFIG_VICTOR_MPC30X is not set
-# CONFIG_ZAO_CAPCELLA is not set
-CONFIG_RWSEM_GENERIC_SPINLOCK=y
-CONFIG_CPU_LITTLE_ENDIAN=y
-CONFIG_FB=y
-
-#
-# CPU selection
-#
-CONFIG_CPU_MIPS32=y
-# CONFIG_CPU_MIPS64 is not set
-# CONFIG_CPU_R3000 is not set
-# CONFIG_CPU_TX39XX is not set
-# CONFIG_CPU_VR41XX is not set
-# CONFIG_CPU_R4300 is not set
-# CONFIG_CPU_R4X00 is not set
-# CONFIG_CPU_TX49XX is not set
-# CONFIG_CPU_R5000 is not set
-# CONFIG_CPU_R5432 is not set
-# CONFIG_CPU_R6000 is not set
-# CONFIG_CPU_NEVADA is not set
-# CONFIG_CPU_R8000 is not set
-# CONFIG_CPU_R10000 is not set
-# CONFIG_CPU_RM7000 is not set
-# CONFIG_CPU_SB1 is not set
-CONFIG_CPU_HAS_PREFETCH=y
-# CONFIG_VTAG_ICACHE is not set
-CONFIG_64BIT_PHYS_ADDR=y
-CONFIG_CPU_ADVANCED=y
-CONFIG_CPU_HAS_LLSC=y
-# CONFIG_CPU_HAS_LLDSCD is not set
-CONFIG_CPU_HAS_WB=y
-CONFIG_CPU_HAS_SYNC=y
-# CONFIG_PREEMPT is not set
-# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
-
-#
-# Bus options (PCI, PCMCIA, EISA, ISA, TC)
-#
-CONFIG_MMU=y
-CONFIG_HOTPLUG=y
-
-#
-# PCMCIA/CardBus support
-#
-CONFIG_PCMCIA=m
-# CONFIG_TCIC is not set
-
-#
-# PCI Hotplug Support
-#
-
-#
-# Executable file formats
-#
-CONFIG_KCORE_ELF=y
-CONFIG_BINFMT_ELF=y
-# CONFIG_BINFMT_MISC is not set
-CONFIG_TRAD_SIGNALS=y
-
-#
-# Memory Technology Devices (MTD)
-#
-CONFIG_MTD=y
-# CONFIG_MTD_DEBUG is not set
-CONFIG_MTD_PARTITIONS=y
-# CONFIG_MTD_CONCAT is not set
-# CONFIG_MTD_REDBOOT_PARTS is not set
-# CONFIG_MTD_CMDLINE_PARTS is not set
-
-#
-# User Modules And Translation Layers
-#
-CONFIG_MTD_CHAR=y
-CONFIG_MTD_BLOCK=y
-# CONFIG_FTL is not set
-# CONFIG_NFTL is not set
-# CONFIG_INFTL is not set
-
-#
-# RAM/ROM/Flash chip drivers
-#
-CONFIG_MTD_CFI=y
-# CONFIG_MTD_JEDECPROBE is not set
-CONFIG_MTD_GEN_PROBE=y
-# CONFIG_MTD_CFI_ADV_OPTIONS is not set
-CONFIG_MTD_CFI_INTELEXT=y
-# CONFIG_MTD_CFI_AMDSTD is not set
-# CONFIG_MTD_CFI_STAA is not set
-# CONFIG_MTD_RAM is not set
-# CONFIG_MTD_ROM is not set
-# CONFIG_MTD_ABSENT is not set
-# CONFIG_MTD_OBSOLETE_CHIPS is not set
-
-#
-# Mapping drivers for chip access
-#
-# CONFIG_MTD_COMPLEX_MAPPINGS is not set
-# CONFIG_MTD_PHYSMAP is not set
-
-#
-# Self-contained MTD device drivers
-#
-# CONFIG_MTD_SLRAM is not set
-# CONFIG_MTD_MTDRAM is not set
-# CONFIG_MTD_BLKMTD is not set
-
-#
-# Disk-On-Chip Device Drivers
-#
-# CONFIG_MTD_DOC2000 is not set
-# CONFIG_MTD_DOC2001 is not set
-# CONFIG_MTD_DOC2001PLUS is not set
-
-#
-# NAND Flash Device Drivers
-#
-# CONFIG_MTD_NAND is not set
-
-#
-# Parallel port support
-#
-# CONFIG_PARPORT is not set
-
-#
-# Plug and Play support
-#
-# CONFIG_PNP is not set
-
-#
-# Generic Driver Options
-#
-# CONFIG_FW_LOADER is not set
-
-#
-# Block devices
-#
-# CONFIG_BLK_DEV_FD is not set
-CONFIG_BLK_DEV_LOOP=y
-# CONFIG_BLK_DEV_CRYPTOLOOP is not set
-# CONFIG_BLK_DEV_NBD is not set
-# CONFIG_BLK_DEV_RAM is not set
-# CONFIG_BLK_DEV_INITRD is not set
-# CONFIG_LBD is not set
-
-#
-# ATA/ATAPI/MFM/RLL support
-#
-CONFIG_IDE=y
-
-#
-# IDE, ATA and ATAPI Block devices
-#
-CONFIG_BLK_DEV_IDE=y
-
-#
-# Please see Documentation/ide.txt for help/info on IDE drives
-#
-# CONFIG_BLK_DEV_HD is not set
-CONFIG_BLK_DEV_IDEDISK=y
-# CONFIG_IDEDISK_MULTI_MODE is not set
-# CONFIG_IDEDISK_STROKE is not set
-CONFIG_BLK_DEV_IDECS=m
-# CONFIG_BLK_DEV_IDECD is not set
-# CONFIG_BLK_DEV_IDEFLOPPY is not set
-# CONFIG_IDE_TASK_IOCTL is not set
-CONFIG_IDE_TASKFILE_IO=y
-
-#
-# IDE chipset support/bugfixes
-#
-
-#
-# SCSI device support
-#
-# CONFIG_SCSI is not set
-
-#
-# Multi-device support (RAID and LVM)
-#
-# CONFIG_MD is not set
-
-#
-# Fusion MPT device support
-#
-
-#
-# I2O device support
-#
-
-#
-# Networking support
-#
-CONFIG_NET=y
-
-#
-# Networking options
-#
-CONFIG_PACKET=y
-# CONFIG_PACKET_MMAP is not set
-# CONFIG_NETLINK_DEV is not set
-CONFIG_NETFILTER=y
-# CONFIG_NETFILTER_DEBUG is not set
-CONFIG_UNIX=y
-CONFIG_NET_KEY=y
-CONFIG_INET=y
-CONFIG_IP_MULTICAST=y
-# CONFIG_IP_ADVANCED_ROUTER is not set
-CONFIG_IP_PNP=y
-# CONFIG_IP_PNP_DHCP is not set
-CONFIG_IP_PNP_BOOTP=y
-# CONFIG_IP_PNP_RARP is not set
-# CONFIG_NET_IPIP is not set
-# CONFIG_NET_IPGRE is not set
-# CONFIG_IP_MROUTE is not set
-# CONFIG_ARPD is not set
-# CONFIG_INET_ECN is not set
-# CONFIG_SYN_COOKIES is not set
-# CONFIG_INET_AH is not set
-# CONFIG_INET_ESP is not set
-# CONFIG_INET_IPCOMP is not set
-
-#
-# IP: Netfilter Configuration
-#
-# CONFIG_IP_NF_CONNTRACK is not set
-# CONFIG_IP_NF_QUEUE is not set
-# CONFIG_IP_NF_IPTABLES is not set
-# CONFIG_IP_NF_ARPTABLES is not set
-# CONFIG_IP_NF_COMPAT_IPCHAINS is not set
-# CONFIG_IP_NF_COMPAT_IPFWADM is not set
-
-#
-# IP: Virtual Server Configuration
-#
-# CONFIG_IP_VS is not set
-# CONFIG_IPV6 is not set
-# CONFIG_XFRM_USER is not set
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
-CONFIG_IPV6_SCTP__=y
-# CONFIG_IP_SCTP is not set
-# CONFIG_ATM is not set
-# CONFIG_VLAN_8021Q is not set
-# CONFIG_LLC is not set
-# CONFIG_DECNET is not set
-# CONFIG_BRIDGE is not set
-# CONFIG_X25 is not set
-# CONFIG_LAPB is not set
-# CONFIG_NET_DIVERT is not set
-# CONFIG_ECONET is not set
-# CONFIG_WAN_ROUTER is not set
-# CONFIG_NET_FASTROUTE is not set
-# CONFIG_NET_HW_FLOWCONTROL is not set
-
-#
-# QoS and/or fair queueing
-#
-# CONFIG_NET_SCHED is not set
-
-#
-# Network testing
-#
-# CONFIG_NET_PKTGEN is not set
-CONFIG_NETDEVICES=y
-# CONFIG_DUMMY is not set
-# CONFIG_BONDING is not set
-# CONFIG_EQUALIZER is not set
-# CONFIG_TUN is not set
-# CONFIG_ETHERTAP is not set
-
-#
-# Ethernet (10 or 100Mbit)
-#
-CONFIG_NET_ETHERNET=y
-# CONFIG_MII is not set
-
-#
-# Ethernet (1000 Mbit)
-#
-
-#
-# Ethernet (10000 Mbit)
-#
-CONFIG_PPP=m
-CONFIG_PPP_MULTILINK=y
-# CONFIG_PPP_FILTER is not set
-CONFIG_PPP_ASYNC=m
-# CONFIG_PPP_SYNC_TTY is not set
-CONFIG_PPP_DEFLATE=m
-# CONFIG_PPP_BSDCOMP is not set
-CONFIG_PPPOE=m
-# CONFIG_SLIP is not set
-
-#
-# Wireless LAN (non-hamradio)
-#
-# CONFIG_NET_RADIO is not set
-
-#
-# Token Ring devices (depends on LLC=y)
-#
-# CONFIG_SHAPER is not set
-
-#
-# Wan interfaces
-#
-# CONFIG_WAN is not set
-
-#
-# PCMCIA network device support
-#
-CONFIG_NET_PCMCIA=y
-CONFIG_PCMCIA_3C589=m
-# CONFIG_PCMCIA_3C574 is not set
-# CONFIG_PCMCIA_FMVJ18X is not set
-# CONFIG_PCMCIA_PCNET is not set
-# CONFIG_PCMCIA_NMCLAN is not set
-# CONFIG_PCMCIA_SMC91C92 is not set
-# CONFIG_PCMCIA_XIRC2PS is not set
-# CONFIG_PCMCIA_AXNET is not set
-
-#
-# Amateur Radio support
-#
-# CONFIG_HAMRADIO is not set
-
-#
-# IrDA (infrared) support
-#
-CONFIG_IRDA=y
-
-#
-# IrDA protocols
-#
-CONFIG_IRLAN=m
-# CONFIG_IRNET is not set
-CONFIG_IRCOMM=m
-# CONFIG_IRDA_ULTRA is not set
-
-#
-# IrDA options
-#
-CONFIG_IRDA_CACHE_LAST_LSAP=y
-CONFIG_IRDA_FAST_RR=y
-# CONFIG_IRDA_DEBUG is not set
-
-#
-# Infrared-port device drivers
-#
-
-#
-# SIR device drivers
-#
-# CONFIG_IRTTY_SIR is not set
-
-#
-# Dongle support
-#
-
-#
-# Old SIR device drivers
-#
-# CONFIG_IRTTY_OLD is not set
-# CONFIG_IRPORT_SIR is not set
-
-#
-# Old Serial dongle support
-#
-
-#
-# FIR device drivers
-#
-# CONFIG_TOSHIBA_OLD is not set
-# CONFIG_TOSHIBA_FIR is not set
-# CONFIG_VLSI_FIR is not set
-
-#
-# ISDN subsystem
-#
-# CONFIG_ISDN_BOOL is not set
-
-#
-# Telephony Support
-#
-# CONFIG_PHONE is not set
-
-#
-# Input device support
-#
-CONFIG_INPUT=y
-
-#
-# Userland interfaces
-#
-# CONFIG_INPUT_MOUSEDEV is not set
-# CONFIG_INPUT_JOYDEV is not set
-# CONFIG_INPUT_TSDEV is not set
-# CONFIG_INPUT_EVDEV is not set
-# CONFIG_INPUT_EVBUG is not set
-
-#
-# Input I/O drivers
-#
-# CONFIG_GAMEPORT is not set
-CONFIG_SOUND_GAMEPORT=y
-# CONFIG_SERIO is not set
-
-#
-# Input Device Drivers
-#
-# CONFIG_INPUT_KEYBOARD is not set
-# CONFIG_INPUT_MOUSE is not set
-# CONFIG_INPUT_JOYSTICK is not set
-# CONFIG_INPUT_TOUCHSCREEN is not set
-# CONFIG_INPUT_MISC is not set
-
-#
-# Character devices
-#
-CONFIG_VT=y
-CONFIG_VT_CONSOLE=y
-CONFIG_HW_CONSOLE=y
-CONFIG_SERIAL_NONSTANDARD=y
-# CONFIG_COMPUTONE is not set
-# CONFIG_ROCKETPORT is not set
-# CONFIG_CYCLADES is not set
-# CONFIG_DIGIEPCA is not set
-# CONFIG_DIGI is not set
-# CONFIG_MOXA_INTELLIO is not set
-# CONFIG_MOXA_SMARTIO is not set
-# CONFIG_ISI is not set
-# CONFIG_SYNCLINK is not set
-# CONFIG_SYNCLINKMP is not set
-# CONFIG_N_HDLC is not set
-# CONFIG_RISCOM8 is not set
-# CONFIG_SPECIALIX is not set
-# CONFIG_SX is not set
-# CONFIG_RIO is not set
-# CONFIG_STALDRV is not set
-
-#
-# Serial drivers
-#
-# CONFIG_SERIAL_8250 is not set
-
-#
-# Non-8250 serial port support
-#
-CONFIG_UNIX98_PTYS=y
-CONFIG_UNIX98_PTY_COUNT=256
-
-#
-# I2C support
-#
-# CONFIG_I2C is not set
-
-#
-# I2C Hardware Sensors Mainboard support
-#
-
-#
-# I2C Hardware Sensors Chip support
-#
-# CONFIG_I2C_SENSOR is not set
-
-#
-# Mice
-#
-# CONFIG_BUSMOUSE is not set
-# CONFIG_QIC02_TAPE is not set
-
-#
-# IPMI
-#
-# CONFIG_IPMI_HANDLER is not set
-
-#
-# Watchdog Cards
-#
-# CONFIG_WATCHDOG is not set
-# CONFIG_NVRAM is not set
-CONFIG_RTC=y
-# CONFIG_DTLK is not set
-# CONFIG_R3964 is not set
-# CONFIG_APPLICOM is not set
-
-#
-# Ftape, the floppy tape device driver
-#
-# CONFIG_FTAPE is not set
-# CONFIG_AGP is not set
-# CONFIG_DRM is not set
-
-#
-# PCMCIA character devices
-#
-# CONFIG_SYNCLINK_CS is not set
-# CONFIG_RAW_DRIVER is not set
-# CONFIG_HANGCHECK_TIMER is not set
-
-#
-# Multimedia devices
-#
-# CONFIG_VIDEO_DEV is not set
-
-#
-# Digital Video Broadcasting Devices
-#
-# CONFIG_DVB is not set
-
-#
-# File systems
-#
-CONFIG_EXT2_FS=y
-# CONFIG_EXT2_FS_XATTR is not set
-CONFIG_EXT3_FS=y
-CONFIG_EXT3_FS_XATTR=y
-# CONFIG_EXT3_FS_POSIX_ACL is not set
-CONFIG_EXT3_FS_SECURITY=y
-CONFIG_JBD=y
-# CONFIG_JBD_DEBUG is not set
-CONFIG_FS_MBCACHE=y
-CONFIG_REISERFS_FS=m
-# CONFIG_REISERFS_CHECK is not set
-# CONFIG_REISERFS_PROC_INFO is not set
-# CONFIG_JFS_FS is not set
-# CONFIG_XFS_FS is not set
-# CONFIG_MINIX_FS is not set
-# CONFIG_ROMFS_FS is not set
-# CONFIG_QUOTA is not set
-CONFIG_AUTOFS_FS=m
-CONFIG_AUTOFS4_FS=m
-
-#
-# CD-ROM/DVD Filesystems
-#
-# CONFIG_ISO9660_FS is not set
-# CONFIG_UDF_FS is not set
-
-#
-# DOS/FAT/NT Filesystems
-#
-# CONFIG_FAT_FS is not set
-# CONFIG_NTFS_FS is not set
-
-#
-# Pseudo filesystems
-#
-CONFIG_PROC_FS=y
-# CONFIG_DEVFS_FS is not set
-CONFIG_DEVPTS_FS=y
-CONFIG_DEVPTS_FS_XATTR=y
-CONFIG_DEVPTS_FS_SECURITY=y
-CONFIG_TMPFS=y
-CONFIG_RAMFS=y
-
-#
-# Miscellaneous filesystems
-#
-# CONFIG_ADFS_FS is not set
-# CONFIG_AFFS_FS is not set
-# CONFIG_HFS_FS is not set
-# CONFIG_BEFS_FS is not set
-# CONFIG_BFS_FS is not set
-# CONFIG_EFS_FS is not set
-CONFIG_JFFS_FS=m
-CONFIG_JFFS_FS_VERBOSE=0
-CONFIG_JFFS2_FS=m
-CONFIG_JFFS2_FS_DEBUG=0
-# CONFIG_JFFS2_FS_NAND is not set
-CONFIG_CRAMFS=m
-# CONFIG_VXFS_FS is not set
-# CONFIG_HPFS_FS is not set
-# CONFIG_QNX4FS_FS is not set
-# CONFIG_SYSV_FS is not set
-# CONFIG_UFS_FS is not set
-
-#
-# Network File Systems
-#
-CONFIG_NFS_FS=y
-# CONFIG_NFS_V3 is not set
-# CONFIG_NFS_V4 is not set
-CONFIG_NFSD=m
-# CONFIG_NFSD_V3 is not set
-# CONFIG_NFSD_TCP is not set
-CONFIG_ROOT_NFS=y
-CONFIG_LOCKD=y
-CONFIG_EXPORTFS=m
-CONFIG_SUNRPC=y
-# CONFIG_SUNRPC_GSS is not set
-CONFIG_SMB_FS=m
-# CONFIG_SMB_NLS_DEFAULT is not set
-# CONFIG_CIFS is not set
-# CONFIG_NCP_FS is not set
-# CONFIG_CODA_FS is not set
-# CONFIG_INTERMEZZO_FS is not set
-# CONFIG_AFS_FS is not set
-
-#
-# Partition Types
-#
-# CONFIG_PARTITION_ADVANCED is not set
-CONFIG_MSDOS_PARTITION=y
-CONFIG_SMB_NLS=y
-CONFIG_NLS=y
-
-#
-# Native Language Support
-#
-CONFIG_NLS_DEFAULT="iso8859-1"
-# CONFIG_NLS_CODEPAGE_437 is not set
-# CONFIG_NLS_CODEPAGE_737 is not set
-# CONFIG_NLS_CODEPAGE_775 is not set
-# CONFIG_NLS_CODEPAGE_850 is not set
-# CONFIG_NLS_CODEPAGE_852 is not set
-# CONFIG_NLS_CODEPAGE_855 is not set
-# CONFIG_NLS_CODEPAGE_857 is not set
-# CONFIG_NLS_CODEPAGE_860 is not set
-# CONFIG_NLS_CODEPAGE_861 is not set
-# CONFIG_NLS_CODEPAGE_862 is not set
-# CONFIG_NLS_CODEPAGE_863 is not set
-# CONFIG_NLS_CODEPAGE_864 is not set
-# CONFIG_NLS_CODEPAGE_865 is not set
-# CONFIG_NLS_CODEPAGE_866 is not set
-# CONFIG_NLS_CODEPAGE_869 is not set
-# CONFIG_NLS_CODEPAGE_936 is not set
-# CONFIG_NLS_CODEPAGE_950 is not set
-# CONFIG_NLS_CODEPAGE_932 is not set
-# CONFIG_NLS_CODEPAGE_949 is not set
-# CONFIG_NLS_CODEPAGE_874 is not set
-# CONFIG_NLS_ISO8859_8 is not set
-# CONFIG_NLS_CODEPAGE_1250 is not set
-# CONFIG_NLS_CODEPAGE_1251 is not set
-# CONFIG_NLS_ISO8859_1 is not set
-# CONFIG_NLS_ISO8859_2 is not set
-# CONFIG_NLS_ISO8859_3 is not set
-# CONFIG_NLS_ISO8859_4 is not set
-# CONFIG_NLS_ISO8859_5 is not set
-# CONFIG_NLS_ISO8859_6 is not set
-# CONFIG_NLS_ISO8859_7 is not set
-# CONFIG_NLS_ISO8859_9 is not set
-# CONFIG_NLS_ISO8859_13 is not set
-# CONFIG_NLS_ISO8859_14 is not set
-# CONFIG_NLS_ISO8859_15 is not set
-# CONFIG_NLS_KOI8_R is not set
-# CONFIG_NLS_KOI8_U is not set
-# CONFIG_NLS_UTF8 is not set
-
-#
-# Graphics support
-#
-# CONFIG_FB_VIRTUAL is not set
-
-#
-# Console display driver support
-#
-# CONFIG_VGA_CONSOLE is not set
-# CONFIG_MDA_CONSOLE is not set
-CONFIG_DUMMY_CONSOLE=y
-# CONFIG_FRAMEBUFFER_CONSOLE is not set
-
-#
-# Logo configuration
-#
-# CONFIG_LOGO is not set
-
-#
-# Sound
-#
-CONFIG_SOUND=y
-
-#
-# Advanced Linux Sound Architecture
-#
-# CONFIG_SND is not set
-
-#
-# Open Sound System
-#
-# CONFIG_SOUND_PRIME is not set
-
-#
-# USB support
-#
-# CONFIG_USB_GADGET is not set
-
-#
-# Bluetooth support
-#
-# CONFIG_BT is not set
-
-#
-# Kernel hacking
-#
-CONFIG_CROSSCOMPILE=y
-# CONFIG_DEBUG_KERNEL is not set
-
-#
-# Security options
-#
-# CONFIG_SECURITY is not set
-
-#
-# Cryptographic options
-#
-# CONFIG_CRYPTO is not set
-
-#
-# Library routines
-#
-# CONFIG_CRC32 is not set
-CONFIG_ZLIB_INFLATE=m
-CONFIG_ZLIB_DEFLATE=m
--- diff/arch/mips/defconfig-pb1500	2003-08-20 14:16:25.000000000 +0100
+++ source/arch/mips/defconfig-pb1500	1970-01-01 01:00:00.000000000 +0100
@@ -1,674 +0,0 @@
-#
-# Automatically generated make config: don't edit
-#
-CONFIG_MIPS=y
-# CONFIG_MIPS64 is not set
-CONFIG_MIPS32=y
-
-#
-# Code maturity level options
-#
-CONFIG_EXPERIMENTAL=y
-
-#
-# General setup
-#
-CONFIG_SWAP=y
-CONFIG_SYSVIPC=y
-# CONFIG_BSD_PROCESS_ACCT is not set
-CONFIG_SYSCTL=y
-CONFIG_LOG_BUF_SHIFT=14
-# CONFIG_EMBEDDED is not set
-CONFIG_KALLSYMS=y
-CONFIG_FUTEX=y
-CONFIG_EPOLL=y
-CONFIG_IOSCHED_AS=y
-CONFIG_IOSCHED_DEADLINE=y
-
-#
-# Loadable module support
-#
-CONFIG_MODULES=y
-CONFIG_MODULE_UNLOAD=y
-# CONFIG_MODULE_FORCE_UNLOAD is not set
-CONFIG_OBSOLETE_MODPARM=y
-CONFIG_MODVERSIONS=y
-CONFIG_KMOD=y
-
-#
-# Machine selection
-#
-# CONFIG_ACER_PICA_61 is not set
-# CONFIG_BAGET_MIPS is not set
-# CONFIG_CASIO_E55 is not set
-# CONFIG_MIPS_COBALT is not set
-# CONFIG_DECSTATION is not set
-# CONFIG_MIPS_EV64120 is not set
-# CONFIG_MIPS_EV96100 is not set
-# CONFIG_MIPS_IVR is not set
-# CONFIG_LASAT is not set
-# CONFIG_HP_LASERJET is not set
-# CONFIG_IBM_WORKPAD is not set
-# CONFIG_MIPS_ITE8172 is not set
-# CONFIG_MIPS_ATLAS is not set
-# CONFIG_MIPS_MAGNUM_4000 is not set
-# CONFIG_MIPS_MALTA is not set
-# CONFIG_MIPS_SEAD is not set
-# CONFIG_MOMENCO_OCELOT is not set
-# CONFIG_MOMENCO_OCELOT_G is not set
-# CONFIG_MOMENCO_OCELOT_C is not set
-# CONFIG_DDB5074 is not set
-# CONFIG_DDB5476 is not set
-# CONFIG_DDB5477 is not set
-# CONFIG_NEC_OSPREY is not set
-# CONFIG_NEC_EAGLE is not set
-# CONFIG_OLIVETTI_M700 is not set
-# CONFIG_SGI_IP22 is not set
-# CONFIG_SGI_IP32 is not set
-CONFIG_SOC_AU1X00=y
-# CONFIG_SOC_AU1000 is not set
-# CONFIG_SOC_AU1100 is not set
-CONFIG_SOC_AU1500=y
-# CONFIG_MIPS_PB1000 is not set
-# CONFIG_MIPS_PB1100 is not set
-CONFIG_MIPS_PB1500=y
-# CONFIG_MIPS_DB1000 is not set
-# CONFIG_MIPS_DB1100 is not set
-# CONFIG_MIPS_DB1500 is not set
-# CONFIG_SIBYTE_SB1xxx_SOC is not set
-# CONFIG_SNI_RM200_PCI is not set
-# CONFIG_TANBAC_TB0226 is not set
-# CONFIG_TANBAC_TB0229 is not set
-# CONFIG_TOSHIBA_JMR3927 is not set
-# CONFIG_TOSHIBA_RBTX4927 is not set
-# CONFIG_VICTOR_MPC30X is not set
-# CONFIG_ZAO_CAPCELLA is not set
-CONFIG_RWSEM_GENERIC_SPINLOCK=y
-CONFIG_NONCOHERENT_IO=y
-CONFIG_CPU_LITTLE_ENDIAN=y
-CONFIG_NEW_PCI=y
-# CONFIG_AU1000_USB_DEVICE is not set
-# CONFIG_FB is not set
-
-#
-# CPU selection
-#
-CONFIG_CPU_MIPS32=y
-# CONFIG_CPU_MIPS64 is not set
-# CONFIG_CPU_R3000 is not set
-# CONFIG_CPU_TX39XX is not set
-# CONFIG_CPU_VR41XX is not set
-# CONFIG_CPU_R4300 is not set
-# CONFIG_CPU_R4X00 is not set
-# CONFIG_CPU_TX49XX is not set
-# CONFIG_CPU_R5000 is not set
-# CONFIG_CPU_R5432 is not set
-# CONFIG_CPU_R6000 is not set
-# CONFIG_CPU_NEVADA is not set
-# CONFIG_CPU_R8000 is not set
-# CONFIG_CPU_R10000 is not set
-# CONFIG_CPU_RM7000 is not set
-# CONFIG_CPU_SB1 is not set
-CONFIG_CPU_HAS_PREFETCH=y
-# CONFIG_VTAG_ICACHE is not set
-# CONFIG_64BIT_PHYS_ADDR is not set
-# CONFIG_CPU_ADVANCED is not set
-CONFIG_CPU_HAS_LLSC=y
-CONFIG_CPU_HAS_SYNC=y
-# CONFIG_PREEMPT is not set
-# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
-
-#
-# Bus options (PCI, PCMCIA, EISA, ISA, TC)
-#
-# CONFIG_PCI is not set
-CONFIG_MMU=y
-CONFIG_HOTPLUG=y
-
-#
-# PCMCIA/CardBus support
-#
-CONFIG_PCMCIA=m
-# CONFIG_TCIC is not set
-
-#
-# PCI Hotplug Support
-#
-
-#
-# Executable file formats
-#
-CONFIG_KCORE_ELF=y
-CONFIG_BINFMT_ELF=y
-# CONFIG_BINFMT_MISC is not set
-CONFIG_TRAD_SIGNALS=y
-# CONFIG_PM is not set
-
-#
-# Memory Technology Devices (MTD)
-#
-# CONFIG_MTD is not set
-
-#
-# Parallel port support
-#
-# CONFIG_PARPORT is not set
-
-#
-# Plug and Play support
-#
-# CONFIG_PNP is not set
-
-#
-# Generic Driver Options
-#
-# CONFIG_FW_LOADER is not set
-
-#
-# Block devices
-#
-# CONFIG_BLK_DEV_FD is not set
-CONFIG_BLK_DEV_LOOP=y
-# CONFIG_BLK_DEV_CRYPTOLOOP is not set
-# CONFIG_BLK_DEV_NBD is not set
-# CONFIG_BLK_DEV_RAM is not set
-# CONFIG_BLK_DEV_INITRD is not set
-# CONFIG_LBD is not set
-
-#
-# ATA/ATAPI/MFM/RLL support
-#
-# CONFIG_IDE is not set
-
-#
-# SCSI device support
-#
-# CONFIG_SCSI is not set
-
-#
-# Multi-device support (RAID and LVM)
-#
-# CONFIG_MD is not set
-
-#
-# Fusion MPT device support
-#
-
-#
-# I2O device support
-#
-
-#
-# Networking support
-#
-CONFIG_NET=y
-
-#
-# Networking options
-#
-CONFIG_PACKET=y
-# CONFIG_PACKET_MMAP is not set
-CONFIG_NETLINK_DEV=y
-CONFIG_NETFILTER=y
-# CONFIG_NETFILTER_DEBUG is not set
-CONFIG_UNIX=y
-CONFIG_NET_KEY=y
-CONFIG_INET=y
-CONFIG_IP_MULTICAST=y
-# CONFIG_IP_ADVANCED_ROUTER is not set
-CONFIG_IP_PNP=y
-# CONFIG_IP_PNP_DHCP is not set
-CONFIG_IP_PNP_BOOTP=y
-# CONFIG_IP_PNP_RARP is not set
-# CONFIG_NET_IPIP is not set
-# CONFIG_NET_IPGRE is not set
-# CONFIG_IP_MROUTE is not set
-# CONFIG_ARPD is not set
-# CONFIG_INET_ECN is not set
-# CONFIG_SYN_COOKIES is not set
-# CONFIG_INET_AH is not set
-# CONFIG_INET_ESP is not set
-# CONFIG_INET_IPCOMP is not set
-
-#
-# IP: Netfilter Configuration
-#
-# CONFIG_IP_NF_CONNTRACK is not set
-# CONFIG_IP_NF_QUEUE is not set
-# CONFIG_IP_NF_IPTABLES is not set
-# CONFIG_IP_NF_ARPTABLES is not set
-# CONFIG_IP_NF_COMPAT_IPCHAINS is not set
-# CONFIG_IP_NF_COMPAT_IPFWADM is not set
-
-#
-# IP: Virtual Server Configuration
-#
-# CONFIG_IP_VS is not set
-# CONFIG_IPV6 is not set
-# CONFIG_XFRM_USER is not set
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
-CONFIG_IPV6_SCTP__=y
-# CONFIG_IP_SCTP is not set
-# CONFIG_ATM is not set
-# CONFIG_VLAN_8021Q is not set
-# CONFIG_LLC is not set
-# CONFIG_DECNET is not set
-# CONFIG_BRIDGE is not set
-# CONFIG_X25 is not set
-# CONFIG_LAPB is not set
-# CONFIG_NET_DIVERT is not set
-# CONFIG_ECONET is not set
-# CONFIG_WAN_ROUTER is not set
-# CONFIG_NET_FASTROUTE is not set
-# CONFIG_NET_HW_FLOWCONTROL is not set
-
-#
-# QoS and/or fair queueing
-#
-# CONFIG_NET_SCHED is not set
-
-#
-# Network testing
-#
-# CONFIG_NET_PKTGEN is not set
-CONFIG_NETDEVICES=y
-# CONFIG_DUMMY is not set
-# CONFIG_BONDING is not set
-# CONFIG_EQUALIZER is not set
-# CONFIG_TUN is not set
-# CONFIG_ETHERTAP is not set
-
-#
-# Ethernet (10 or 100Mbit)
-#
-CONFIG_NET_ETHERNET=y
-# CONFIG_MII is not set
-CONFIG_MIPS_AU1X00_ENET=y
-
-#
-# Ethernet (1000 Mbit)
-#
-
-#
-# Ethernet (10000 Mbit)
-#
-CONFIG_PPP=m
-CONFIG_PPP_MULTILINK=y
-# CONFIG_PPP_FILTER is not set
-CONFIG_PPP_ASYNC=m
-# CONFIG_PPP_SYNC_TTY is not set
-CONFIG_PPP_DEFLATE=m
-# CONFIG_PPP_BSDCOMP is not set
-CONFIG_PPPOE=m
-# CONFIG_SLIP is not set
-
-#
-# Wireless LAN (non-hamradio)
-#
-# CONFIG_NET_RADIO is not set
-
-#
-# Token Ring devices (depends on LLC=y)
-#
-# CONFIG_SHAPER is not set
-
-#
-# Wan interfaces
-#
-# CONFIG_WAN is not set
-
-#
-# PCMCIA network device support
-#
-CONFIG_NET_PCMCIA=y
-CONFIG_PCMCIA_3C589=m
-# CONFIG_PCMCIA_3C574 is not set
-# CONFIG_PCMCIA_FMVJ18X is not set
-# CONFIG_PCMCIA_PCNET is not set
-# CONFIG_PCMCIA_NMCLAN is not set
-# CONFIG_PCMCIA_SMC91C92 is not set
-# CONFIG_PCMCIA_XIRC2PS is not set
-# CONFIG_PCMCIA_AXNET is not set
-
-#
-# Amateur Radio support
-#
-# CONFIG_HAMRADIO is not set
-
-#
-# IrDA (infrared) support
-#
-# CONFIG_IRDA is not set
-
-#
-# ISDN subsystem
-#
-# CONFIG_ISDN_BOOL is not set
-
-#
-# Telephony Support
-#
-# CONFIG_PHONE is not set
-
-#
-# Input device support
-#
-CONFIG_INPUT=y
-
-#
-# Userland interfaces
-#
-CONFIG_INPUT_MOUSEDEV=y
-# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
-CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
-CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
-# CONFIG_INPUT_JOYDEV is not set
-# CONFIG_INPUT_TSDEV is not set
-CONFIG_INPUT_EVDEV=y
-# CONFIG_INPUT_EVBUG is not set
-
-#
-# Input I/O drivers
-#
-# CONFIG_GAMEPORT is not set
-CONFIG_SOUND_GAMEPORT=y
-CONFIG_SERIO=y
-# CONFIG_SERIO_I8042 is not set
-CONFIG_SERIO_SERPORT=y
-# CONFIG_SERIO_CT82C710 is not set
-
-#
-# Input Device Drivers
-#
-# CONFIG_INPUT_KEYBOARD is not set
-# CONFIG_INPUT_MOUSE is not set
-# CONFIG_INPUT_JOYSTICK is not set
-# CONFIG_INPUT_TOUCHSCREEN is not set
-# CONFIG_INPUT_MISC is not set
-
-#
-# Character devices
-#
-CONFIG_VT=y
-CONFIG_VT_CONSOLE=y
-CONFIG_HW_CONSOLE=y
-# CONFIG_SERIAL_NONSTANDARD is not set
-# CONFIG_AU1X00_GPIO is not set
-# CONFIG_TS_AU1X00_ADS7846 is not set
-
-#
-# Serial drivers
-#
-# CONFIG_SERIAL_8250 is not set
-
-#
-# Non-8250 serial port support
-#
-CONFIG_SERIAL_AU1X00=y
-CONFIG_SERIAL_AU1X00_CONSOLE=y
-CONFIG_SERIAL_CORE=y
-CONFIG_SERIAL_CORE_CONSOLE=y
-CONFIG_UNIX98_PTYS=y
-CONFIG_UNIX98_PTY_COUNT=256
-
-#
-# I2C support
-#
-# CONFIG_I2C is not set
-
-#
-# I2C Hardware Sensors Mainboard support
-#
-
-#
-# I2C Hardware Sensors Chip support
-#
-# CONFIG_I2C_SENSOR is not set
-
-#
-# Mice
-#
-# CONFIG_BUSMOUSE is not set
-# CONFIG_QIC02_TAPE is not set
-
-#
-# IPMI
-#
-# CONFIG_IPMI_HANDLER is not set
-
-#
-# Watchdog Cards
-#
-# CONFIG_WATCHDOG is not set
-# CONFIG_NVRAM is not set
-CONFIG_RTC=y
-# CONFIG_DTLK is not set
-# CONFIG_R3964 is not set
-# CONFIG_APPLICOM is not set
-
-#
-# Ftape, the floppy tape device driver
-#
-# CONFIG_FTAPE is not set
-# CONFIG_AGP is not set
-# CONFIG_DRM is not set
-
-#
-# PCMCIA character devices
-#
-# CONFIG_SYNCLINK_CS is not set
-# CONFIG_RAW_DRIVER is not set
-# CONFIG_HANGCHECK_TIMER is not set
-
-#
-# Multimedia devices
-#
-# CONFIG_VIDEO_DEV is not set
-
-#
-# Digital Video Broadcasting Devices
-#
-# CONFIG_DVB is not set
-
-#
-# File systems
-#
-CONFIG_EXT2_FS=y
-CONFIG_EXT2_FS_XATTR=y
-CONFIG_EXT2_FS_POSIX_ACL=y
-# CONFIG_EXT2_FS_SECURITY is not set
-CONFIG_EXT3_FS=y
-CONFIG_EXT3_FS_XATTR=y
-CONFIG_EXT3_FS_POSIX_ACL=y
-CONFIG_EXT3_FS_SECURITY=y
-CONFIG_JBD=y
-# CONFIG_JBD_DEBUG is not set
-CONFIG_FS_MBCACHE=y
-CONFIG_REISERFS_FS=m
-# CONFIG_REISERFS_CHECK is not set
-# CONFIG_REISERFS_PROC_INFO is not set
-# CONFIG_JFS_FS is not set
-CONFIG_FS_POSIX_ACL=y
-# CONFIG_XFS_FS is not set
-# CONFIG_MINIX_FS is not set
-# CONFIG_ROMFS_FS is not set
-# CONFIG_QUOTA is not set
-CONFIG_AUTOFS_FS=m
-CONFIG_AUTOFS4_FS=m
-
-#
-# CD-ROM/DVD Filesystems
-#
-# CONFIG_ISO9660_FS is not set
-# CONFIG_UDF_FS is not set
-
-#
-# DOS/FAT/NT Filesystems
-#
-# CONFIG_FAT_FS is not set
-# CONFIG_NTFS_FS is not set
-
-#
-# Pseudo filesystems
-#
-CONFIG_PROC_FS=y
-# CONFIG_DEVFS_FS is not set
-CONFIG_DEVPTS_FS=y
-CONFIG_DEVPTS_FS_XATTR=y
-CONFIG_DEVPTS_FS_SECURITY=y
-CONFIG_TMPFS=y
-CONFIG_RAMFS=y
-
-#
-# Miscellaneous filesystems
-#
-# CONFIG_ADFS_FS is not set
-# CONFIG_AFFS_FS is not set
-# CONFIG_HFS_FS is not set
-# CONFIG_BEFS_FS is not set
-# CONFIG_BFS_FS is not set
-# CONFIG_EFS_FS is not set
-CONFIG_CRAMFS=m
-# CONFIG_VXFS_FS is not set
-# CONFIG_HPFS_FS is not set
-# CONFIG_QNX4FS_FS is not set
-# CONFIG_SYSV_FS is not set
-# CONFIG_UFS_FS is not set
-
-#
-# Network File Systems
-#
-CONFIG_NFS_FS=y
-# CONFIG_NFS_V3 is not set
-# CONFIG_NFS_V4 is not set
-CONFIG_NFSD=m
-# CONFIG_NFSD_V3 is not set
-# CONFIG_NFSD_TCP is not set
-CONFIG_ROOT_NFS=y
-CONFIG_LOCKD=y
-CONFIG_EXPORTFS=m
-CONFIG_SUNRPC=y
-# CONFIG_SUNRPC_GSS is not set
-CONFIG_SMB_FS=m
-# CONFIG_SMB_NLS_DEFAULT is not set
-# CONFIG_CIFS is not set
-# CONFIG_NCP_FS is not set
-# CONFIG_CODA_FS is not set
-# CONFIG_INTERMEZZO_FS is not set
-# CONFIG_AFS_FS is not set
-
-#
-# Partition Types
-#
-# CONFIG_PARTITION_ADVANCED is not set
-CONFIG_MSDOS_PARTITION=y
-CONFIG_SMB_NLS=y
-CONFIG_NLS=y
-
-#
-# Native Language Support
-#
-CONFIG_NLS_DEFAULT="iso8859-1"
-# CONFIG_NLS_CODEPAGE_437 is not set
-# CONFIG_NLS_CODEPAGE_737 is not set
-# CONFIG_NLS_CODEPAGE_775 is not set
-# CONFIG_NLS_CODEPAGE_850 is not set
-# CONFIG_NLS_CODEPAGE_852 is not set
-# CONFIG_NLS_CODEPAGE_855 is not set
-# CONFIG_NLS_CODEPAGE_857 is not set
-# CONFIG_NLS_CODEPAGE_860 is not set
-# CONFIG_NLS_CODEPAGE_861 is not set
-# CONFIG_NLS_CODEPAGE_862 is not set
-# CONFIG_NLS_CODEPAGE_863 is not set
-# CONFIG_NLS_CODEPAGE_864 is not set
-# CONFIG_NLS_CODEPAGE_865 is not set
-# CONFIG_NLS_CODEPAGE_866 is not set
-# CONFIG_NLS_CODEPAGE_869 is not set
-# CONFIG_NLS_CODEPAGE_936 is not set
-# CONFIG_NLS_CODEPAGE_950 is not set
-# CONFIG_NLS_CODEPAGE_932 is not set
-# CONFIG_NLS_CODEPAGE_949 is not set
-# CONFIG_NLS_CODEPAGE_874 is not set
-# CONFIG_NLS_ISO8859_8 is not set
-# CONFIG_NLS_CODEPAGE_1250 is not set
-# CONFIG_NLS_CODEPAGE_1251 is not set
-# CONFIG_NLS_ISO8859_1 is not set
-# CONFIG_NLS_ISO8859_2 is not set
-# CONFIG_NLS_ISO8859_3 is not set
-# CONFIG_NLS_ISO8859_4 is not set
-# CONFIG_NLS_ISO8859_5 is not set
-# CONFIG_NLS_ISO8859_6 is not set
-# CONFIG_NLS_ISO8859_7 is not set
-# CONFIG_NLS_ISO8859_9 is not set
-# CONFIG_NLS_ISO8859_13 is not set
-# CONFIG_NLS_ISO8859_14 is not set
-# CONFIG_NLS_ISO8859_15 is not set
-# CONFIG_NLS_KOI8_R is not set
-# CONFIG_NLS_KOI8_U is not set
-# CONFIG_NLS_UTF8 is not set
-
-#
-# Graphics support
-#
-
-#
-# Console display driver support
-#
-# CONFIG_VGA_CONSOLE is not set
-# CONFIG_MDA_CONSOLE is not set
-CONFIG_DUMMY_CONSOLE=y
-
-#
-# Sound
-#
-# CONFIG_SOUND is not set
-
-#
-# USB support
-#
-# CONFIG_USB_GADGET is not set
-
-#
-# Bluetooth support
-#
-# CONFIG_BT is not set
-
-#
-# Kernel hacking
-#
-CONFIG_CROSSCOMPILE=y
-# CONFIG_DEBUG_KERNEL is not set
-
-#
-# Security options
-#
-# CONFIG_SECURITY is not set
-
-#
-# Cryptographic options
-#
-CONFIG_CRYPTO=y
-CONFIG_CRYPTO_HMAC=y
-CONFIG_CRYPTO_NULL=y
-# CONFIG_CRYPTO_MD4 is not set
-# CONFIG_CRYPTO_MD5 is not set
-# CONFIG_CRYPTO_SHA1 is not set
-# CONFIG_CRYPTO_SHA256 is not set
-CONFIG_CRYPTO_SHA512=y
-# CONFIG_CRYPTO_DES is not set
-# CONFIG_CRYPTO_BLOWFISH is not set
-CONFIG_CRYPTO_TWOFISH=y
-# CONFIG_CRYPTO_SERPENT is not set
-CONFIG_CRYPTO_AES=y
-CONFIG_CRYPTO_DEFLATE=y
-# CONFIG_CRYPTO_TEST is not set
-
-#
-# Library routines
-#
-CONFIG_CRC32=y
-CONFIG_ZLIB_INFLATE=y
-CONFIG_ZLIB_DEFLATE=y
--- diff/arch/mips/defconfig-rm200	2003-08-20 14:16:25.000000000 +0100
+++ source/arch/mips/defconfig-rm200	1970-01-01 01:00:00.000000000 +0100
@@ -1,700 +0,0 @@
-#
-# Automatically generated make config: don't edit
-#
-CONFIG_MIPS=y
-# CONFIG_MIPS64 is not set
-CONFIG_MIPS32=y
-
-#
-# Code maturity level options
-#
-CONFIG_EXPERIMENTAL=y
-
-#
-# General setup
-#
-CONFIG_SWAP=y
-# CONFIG_SYSVIPC is not set
-# CONFIG_BSD_PROCESS_ACCT is not set
-CONFIG_SYSCTL=y
-CONFIG_LOG_BUF_SHIFT=14
-# CONFIG_EMBEDDED is not set
-CONFIG_KALLSYMS=y
-CONFIG_FUTEX=y
-CONFIG_EPOLL=y
-CONFIG_IOSCHED_AS=y
-CONFIG_IOSCHED_DEADLINE=y
-
-#
-# Loadable module support
-#
-CONFIG_MODULES=y
-CONFIG_MODULE_UNLOAD=y
-# CONFIG_MODULE_FORCE_UNLOAD is not set
-CONFIG_OBSOLETE_MODPARM=y
-CONFIG_MODVERSIONS=y
-CONFIG_KMOD=y
-
-#
-# Machine selection
-#
-# CONFIG_ACER_PICA_61 is not set
-# CONFIG_BAGET_MIPS is not set
-# CONFIG_CASIO_E55 is not set
-# CONFIG_MIPS_COBALT is not set
-# CONFIG_DECSTATION is not set
-# CONFIG_MIPS_EV64120 is not set
-# CONFIG_MIPS_EV96100 is not set
-# CONFIG_MIPS_IVR is not set
-# CONFIG_LASAT is not set
-# CONFIG_HP_LASERJET is not set
-# CONFIG_IBM_WORKPAD is not set
-# CONFIG_MIPS_ITE8172 is not set
-# CONFIG_MIPS_ATLAS is not set
-# CONFIG_MIPS_MAGNUM_4000 is not set
-# CONFIG_MIPS_MALTA is not set
-# CONFIG_MIPS_SEAD is not set
-# CONFIG_MOMENCO_OCELOT is not set
-# CONFIG_MOMENCO_OCELOT_G is not set
-# CONFIG_MOMENCO_OCELOT_C is not set
-# CONFIG_DDB5074 is not set
-# CONFIG_DDB5476 is not set
-# CONFIG_DDB5477 is not set
-# CONFIG_NEC_OSPREY is not set
-# CONFIG_NEC_EAGLE is not set
-# CONFIG_OLIVETTI_M700 is not set
-# CONFIG_SGI_IP22 is not set
-# CONFIG_SGI_IP32 is not set
-# CONFIG_SOC_AU1X00 is not set
-# CONFIG_SIBYTE_SB1xxx_SOC is not set
-CONFIG_SNI_RM200_PCI=y
-# CONFIG_TANBAC_TB0226 is not set
-# CONFIG_TANBAC_TB0229 is not set
-# CONFIG_TOSHIBA_JMR3927 is not set
-# CONFIG_TOSHIBA_RBTX4927 is not set
-# CONFIG_VICTOR_MPC30X is not set
-# CONFIG_ZAO_CAPCELLA is not set
-CONFIG_RWSEM_GENERIC_SPINLOCK=y
-CONFIG_ARC=y
-CONFIG_GENERIC_ISA_DMA=y
-CONFIG_I8259=y
-CONFIG_NONCOHERENT_IO=y
-CONFIG_CPU_LITTLE_ENDIAN=y
-CONFIG_BOOT_ELF32=y
-CONFIG_ARC32=y
-# CONFIG_FB is not set
-CONFIG_ARC_CONSOLE=y
-CONFIG_ARC_MEMORY=y
-CONFIG_ARC_PROMLIB=y
-
-#
-# CPU selection
-#
-# CONFIG_CPU_MIPS32 is not set
-# CONFIG_CPU_MIPS64 is not set
-# CONFIG_CPU_R3000 is not set
-# CONFIG_CPU_TX39XX is not set
-# CONFIG_CPU_VR41XX is not set
-# CONFIG_CPU_R4300 is not set
-CONFIG_CPU_R4X00=y
-# CONFIG_CPU_TX49XX is not set
-# CONFIG_CPU_R5000 is not set
-# CONFIG_CPU_R5432 is not set
-# CONFIG_CPU_R6000 is not set
-# CONFIG_CPU_NEVADA is not set
-# CONFIG_CPU_R8000 is not set
-# CONFIG_CPU_R10000 is not set
-# CONFIG_CPU_RM7000 is not set
-# CONFIG_CPU_SB1 is not set
-# CONFIG_64BIT_PHYS_ADDR is not set
-# CONFIG_CPU_ADVANCED is not set
-CONFIG_CPU_HAS_LLSC=y
-CONFIG_CPU_HAS_LLDSCD=y
-CONFIG_CPU_HAS_SYNC=y
-# CONFIG_PREEMPT is not set
-# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
-
-#
-# Bus options (PCI, PCMCIA, EISA, ISA, TC)
-#
-CONFIG_PCI=y
-CONFIG_PCI_LEGACY_PROC=y
-# CONFIG_PCI_NAMES is not set
-CONFIG_ISA=y
-# CONFIG_EISA is not set
-CONFIG_MMU=y
-# CONFIG_HOTPLUG is not set
-
-#
-# Executable file formats
-#
-CONFIG_KCORE_ELF=y
-CONFIG_BINFMT_ELF=y
-# CONFIG_BINFMT_MISC is not set
-CONFIG_TRAD_SIGNALS=y
-
-#
-# Memory Technology Devices (MTD)
-#
-# CONFIG_MTD is not set
-
-#
-# Parallel port support
-#
-# CONFIG_PARPORT is not set
-
-#
-# Plug and Play support
-#
-# CONFIG_PNP is not set
-
-#
-# Generic Driver Options
-#
-# CONFIG_FW_LOADER is not set
-
-#
-# Block devices
-#
-CONFIG_BLK_DEV_FD=y
-# CONFIG_BLK_DEV_XD is not set
-# CONFIG_BLK_CPQ_DA is not set
-# CONFIG_BLK_CPQ_CISS_DA is not set
-# CONFIG_BLK_DEV_DAC960 is not set
-# CONFIG_BLK_DEV_UMEM is not set
-# CONFIG_BLK_DEV_LOOP is not set
-# CONFIG_BLK_DEV_NBD is not set
-# CONFIG_BLK_DEV_RAM is not set
-# CONFIG_BLK_DEV_INITRD is not set
-# CONFIG_LBD is not set
-
-#
-# ATA/ATAPI/MFM/RLL support
-#
-# CONFIG_IDE is not set
-
-#
-# SCSI device support
-#
-CONFIG_SCSI=y
-
-#
-# SCSI support type (disk, tape, CD-ROM)
-#
-CONFIG_BLK_DEV_SD=y
-CONFIG_CHR_DEV_ST=y
-# CONFIG_CHR_DEV_OSST is not set
-CONFIG_BLK_DEV_SR=y
-# CONFIG_BLK_DEV_SR_VENDOR is not set
-# CONFIG_CHR_DEV_SG is not set
-
-#
-# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
-#
-# CONFIG_SCSI_MULTI_LUN is not set
-# CONFIG_SCSI_REPORT_LUNS is not set
-CONFIG_SCSI_CONSTANTS=y
-# CONFIG_SCSI_LOGGING is not set
-
-#
-# SCSI low-level drivers
-#
-# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
-# CONFIG_SCSI_7000FASST is not set
-# CONFIG_SCSI_ACARD is not set
-# CONFIG_SCSI_AHA152X is not set
-# CONFIG_SCSI_AHA1542 is not set
-# CONFIG_SCSI_AACRAID is not set
-# CONFIG_SCSI_AIC7XXX is not set
-# CONFIG_SCSI_AIC7XXX_OLD is not set
-# CONFIG_SCSI_AIC79XX is not set
-# CONFIG_SCSI_DPT_I2O is not set
-# CONFIG_SCSI_ADVANSYS is not set
-# CONFIG_SCSI_IN2000 is not set
-# CONFIG_SCSI_MEGARAID is not set
-# CONFIG_SCSI_BUSLOGIC is not set
-# CONFIG_SCSI_CPQFCTS is not set
-# CONFIG_SCSI_DMX3191D is not set
-# CONFIG_SCSI_DTC3280 is not set
-# CONFIG_SCSI_EATA is not set
-# CONFIG_SCSI_EATA_PIO is not set
-# CONFIG_SCSI_FUTURE_DOMAIN is not set
-# CONFIG_SCSI_GDTH is not set
-# CONFIG_SCSI_GENERIC_NCR5380 is not set
-# CONFIG_SCSI_GENERIC_NCR5380_MMIO is not set
-# CONFIG_SCSI_INITIO is not set
-# CONFIG_SCSI_INIA100 is not set
-# CONFIG_SCSI_NCR53C406A is not set
-CONFIG_SCSI_SYM53C8XX_2=y
-CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=1
-CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=16
-CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64
-# CONFIG_SCSI_SYM53C8XX_IOMAPPED is not set
-# CONFIG_SCSI_PAS16 is not set
-# CONFIG_SCSI_PCI2000 is not set
-# CONFIG_SCSI_PCI2220I is not set
-# CONFIG_SCSI_PSI240I is not set
-# CONFIG_SCSI_QLOGIC_FAS is not set
-# CONFIG_SCSI_QLOGIC_ISP is not set
-# CONFIG_SCSI_QLOGIC_FC is not set
-# CONFIG_SCSI_QLOGIC_1280 is not set
-# CONFIG_SCSI_SYM53C416 is not set
-# CONFIG_SCSI_DC395x is not set
-# CONFIG_SCSI_DC390T is not set
-# CONFIG_SCSI_T128 is not set
-# CONFIG_SCSI_U14_34F is not set
-# CONFIG_SCSI_NSP32 is not set
-# CONFIG_SCSI_DEBUG is not set
-
-#
-# Old CD-ROM drivers (not SCSI, not IDE)
-#
-# CONFIG_CD_NO_IDESCSI is not set
-
-#
-# Multi-device support (RAID and LVM)
-#
-# CONFIG_MD is not set
-
-#
-# Fusion MPT device support
-#
-# CONFIG_FUSION is not set
-
-#
-# IEEE 1394 (FireWire) support (EXPERIMENTAL)
-#
-# CONFIG_IEEE1394 is not set
-
-#
-# I2O device support
-#
-# CONFIG_I2O is not set
-
-#
-# Networking support
-#
-CONFIG_NET=y
-
-#
-# Networking options
-#
-CONFIG_PACKET=y
-# CONFIG_PACKET_MMAP is not set
-CONFIG_NETLINK_DEV=y
-# CONFIG_NETFILTER is not set
-CONFIG_UNIX=y
-CONFIG_NET_KEY=y
-CONFIG_INET=y
-CONFIG_IP_MULTICAST=y
-# CONFIG_IP_ADVANCED_ROUTER is not set
-# CONFIG_IP_PNP is not set
-# CONFIG_NET_IPIP is not set
-# CONFIG_NET_IPGRE is not set
-# CONFIG_IP_MROUTE is not set
-# CONFIG_ARPD is not set
-CONFIG_INET_ECN=y
-# CONFIG_SYN_COOKIES is not set
-# CONFIG_INET_AH is not set
-# CONFIG_INET_ESP is not set
-# CONFIG_INET_IPCOMP is not set
-# CONFIG_IPV6 is not set
-# CONFIG_XFRM_USER is not set
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
-CONFIG_IPV6_SCTP__=y
-# CONFIG_IP_SCTP is not set
-# CONFIG_ATM is not set
-# CONFIG_VLAN_8021Q is not set
-# CONFIG_LLC is not set
-# CONFIG_DECNET is not set
-# CONFIG_BRIDGE is not set
-# CONFIG_X25 is not set
-# CONFIG_LAPB is not set
-# CONFIG_NET_DIVERT is not set
-# CONFIG_ECONET is not set
-# CONFIG_WAN_ROUTER is not set
-# CONFIG_NET_FASTROUTE is not set
-# CONFIG_NET_HW_FLOWCONTROL is not set
-
-#
-# QoS and/or fair queueing
-#
-# CONFIG_NET_SCHED is not set
-
-#
-# Network testing
-#
-# CONFIG_NET_PKTGEN is not set
-CONFIG_NETDEVICES=y
-
-#
-# ARCnet devices
-#
-# CONFIG_ARCNET is not set
-# CONFIG_DUMMY is not set
-# CONFIG_BONDING is not set
-# CONFIG_EQUALIZER is not set
-# CONFIG_TUN is not set
-# CONFIG_ETHERTAP is not set
-
-#
-# Ethernet (10 or 100Mbit)
-#
-CONFIG_NET_ETHERNET=y
-# CONFIG_MII is not set
-# CONFIG_HAPPYMEAL is not set
-# CONFIG_SUNGEM is not set
-# CONFIG_NET_VENDOR_3COM is not set
-# CONFIG_LANCE is not set
-# CONFIG_NET_VENDOR_SMC is not set
-# CONFIG_NET_VENDOR_RACAL is not set
-
-#
-# Tulip family network device support
-#
-# CONFIG_NET_TULIP is not set
-# CONFIG_AT1700 is not set
-# CONFIG_DEPCA is not set
-# CONFIG_HP100 is not set
-# CONFIG_NET_ISA is not set
-CONFIG_NET_PCI=y
-CONFIG_PCNET32=y
-# CONFIG_AMD8111_ETH is not set
-# CONFIG_ADAPTEC_STARFIRE is not set
-# CONFIG_AC3200 is not set
-# CONFIG_APRICOT is not set
-# CONFIG_B44 is not set
-# CONFIG_CS89x0 is not set
-# CONFIG_DGRS is not set
-# CONFIG_EEPRO100 is not set
-# CONFIG_E100 is not set
-# CONFIG_FEALNX is not set
-# CONFIG_NATSEMI is not set
-# CONFIG_NE2K_PCI is not set
-# CONFIG_8139CP is not set
-# CONFIG_8139TOO is not set
-# CONFIG_SIS900 is not set
-# CONFIG_EPIC100 is not set
-# CONFIG_SUNDANCE is not set
-# CONFIG_TLAN is not set
-# CONFIG_VIA_RHINE is not set
-# CONFIG_LAN_SAA9730 is not set
-# CONFIG_NET_POCKET is not set
-
-#
-# Ethernet (1000 Mbit)
-#
-# CONFIG_ACENIC is not set
-# CONFIG_DL2K is not set
-# CONFIG_E1000 is not set
-# CONFIG_NS83820 is not set
-# CONFIG_HAMACHI is not set
-# CONFIG_YELLOWFIN is not set
-# CONFIG_R8169 is not set
-# CONFIG_SK98LIN is not set
-# CONFIG_TIGON3 is not set
-
-#
-# Ethernet (10000 Mbit)
-#
-# CONFIG_IXGB is not set
-# CONFIG_FDDI is not set
-# CONFIG_HIPPI is not set
-# CONFIG_PPP is not set
-# CONFIG_SLIP is not set
-
-#
-# Wireless LAN (non-hamradio)
-#
-# CONFIG_NET_RADIO is not set
-
-#
-# Token Ring devices (depends on LLC=y)
-#
-# CONFIG_NET_FC is not set
-# CONFIG_RCPCI is not set
-# CONFIG_SHAPER is not set
-
-#
-# Wan interfaces
-#
-# CONFIG_WAN is not set
-
-#
-# Amateur Radio support
-#
-# CONFIG_HAMRADIO is not set
-
-#
-# IrDA (infrared) support
-#
-# CONFIG_IRDA is not set
-
-#
-# ISDN subsystem
-#
-# CONFIG_ISDN_BOOL is not set
-
-#
-# Telephony Support
-#
-# CONFIG_PHONE is not set
-
-#
-# Input device support
-#
-CONFIG_INPUT=y
-
-#
-# Userland interfaces
-#
-# CONFIG_INPUT_MOUSEDEV is not set
-# CONFIG_INPUT_JOYDEV is not set
-# CONFIG_INPUT_TSDEV is not set
-# CONFIG_INPUT_EVDEV is not set
-# CONFIG_INPUT_EVBUG is not set
-
-#
-# Input I/O drivers
-#
-# CONFIG_GAMEPORT is not set
-CONFIG_SOUND_GAMEPORT=y
-CONFIG_SERIO=y
-CONFIG_SERIO_I8042=y
-CONFIG_SERIO_SERPORT=y
-# CONFIG_SERIO_CT82C710 is not set
-# CONFIG_SERIO_PCIPS2 is not set
-
-#
-# Input Device Drivers
-#
-CONFIG_INPUT_KEYBOARD=y
-CONFIG_KEYBOARD_ATKBD=y
-# CONFIG_KEYBOARD_SUNKBD is not set
-# CONFIG_KEYBOARD_XTKBD is not set
-# CONFIG_KEYBOARD_NEWTON is not set
-# CONFIG_INPUT_MOUSE is not set
-# CONFIG_INPUT_JOYSTICK is not set
-# CONFIG_INPUT_TOUCHSCREEN is not set
-# CONFIG_INPUT_MISC is not set
-
-#
-# Character devices
-#
-CONFIG_VT=y
-CONFIG_VT_CONSOLE=y
-CONFIG_HW_CONSOLE=y
-# CONFIG_SERIAL_NONSTANDARD is not set
-
-#
-# Serial drivers
-#
-CONFIG_SERIAL_8250=y
-# CONFIG_SERIAL_8250_CONSOLE is not set
-# CONFIG_SERIAL_8250_EXTENDED is not set
-
-#
-# Non-8250 serial port support
-#
-CONFIG_SERIAL_CORE=y
-CONFIG_UNIX98_PTYS=y
-CONFIG_UNIX98_PTY_COUNT=256
-
-#
-# I2C support
-#
-# CONFIG_I2C is not set
-
-#
-# I2C Hardware Sensors Mainboard support
-#
-
-#
-# I2C Hardware Sensors Chip support
-#
-# CONFIG_I2C_SENSOR is not set
-
-#
-# Mice
-#
-# CONFIG_BUSMOUSE is not set
-# CONFIG_QIC02_TAPE is not set
-
-#
-# IPMI
-#
-# CONFIG_IPMI_HANDLER is not set
-
-#
-# Watchdog Cards
-#
-# CONFIG_WATCHDOG is not set
-# CONFIG_NVRAM is not set
-CONFIG_RTC=y
-# CONFIG_DTLK is not set
-# CONFIG_R3964 is not set
-# CONFIG_APPLICOM is not set
-
-#
-# Ftape, the floppy tape device driver
-#
-# CONFIG_FTAPE is not set
-# CONFIG_AGP is not set
-# CONFIG_DRM is not set
-# CONFIG_RAW_DRIVER is not set
-# CONFIG_HANGCHECK_TIMER is not set
-
-#
-# Multimedia devices
-#
-# CONFIG_VIDEO_DEV is not set
-
-#
-# Digital Video Broadcasting Devices
-#
-# CONFIG_DVB is not set
-
-#
-# File systems
-#
-# CONFIG_EXT2_FS is not set
-CONFIG_EXT3_FS=y
-CONFIG_EXT3_FS_XATTR=y
-CONFIG_EXT3_FS_POSIX_ACL=y
-CONFIG_EXT3_FS_SECURITY=y
-CONFIG_JBD=y
-# CONFIG_JBD_DEBUG is not set
-CONFIG_FS_MBCACHE=y
-# CONFIG_REISERFS_FS is not set
-# CONFIG_JFS_FS is not set
-CONFIG_FS_POSIX_ACL=y
-# CONFIG_XFS_FS is not set
-# CONFIG_MINIX_FS is not set
-# CONFIG_ROMFS_FS is not set
-# CONFIG_QUOTA is not set
-# CONFIG_AUTOFS_FS is not set
-# CONFIG_AUTOFS4_FS is not set
-
-#
-# CD-ROM/DVD Filesystems
-#
-# CONFIG_ISO9660_FS is not set
-# CONFIG_UDF_FS is not set
-
-#
-# DOS/FAT/NT Filesystems
-#
-# CONFIG_FAT_FS is not set
-# CONFIG_NTFS_FS is not set
-
-#
-# Pseudo filesystems
-#
-CONFIG_PROC_FS=y
-# CONFIG_DEVFS_FS is not set
-CONFIG_DEVPTS_FS=y
-CONFIG_DEVPTS_FS_XATTR=y
-CONFIG_DEVPTS_FS_SECURITY=y
-# CONFIG_TMPFS is not set
-CONFIG_RAMFS=y
-
-#
-# Miscellaneous filesystems
-#
-# CONFIG_ADFS_FS is not set
-# CONFIG_AFFS_FS is not set
-# CONFIG_HFS_FS is not set
-# CONFIG_BEFS_FS is not set
-# CONFIG_BFS_FS is not set
-# CONFIG_EFS_FS is not set
-# CONFIG_CRAMFS is not set
-# CONFIG_VXFS_FS is not set
-# CONFIG_HPFS_FS is not set
-# CONFIG_QNX4FS_FS is not set
-# CONFIG_SYSV_FS is not set
-# CONFIG_UFS_FS is not set
-
-#
-# Network File Systems
-#
-# CONFIG_NFS_FS is not set
-# CONFIG_NFSD is not set
-# CONFIG_EXPORTFS is not set
-# CONFIG_SMB_FS is not set
-# CONFIG_CIFS is not set
-# CONFIG_NCP_FS is not set
-# CONFIG_CODA_FS is not set
-# CONFIG_INTERMEZZO_FS is not set
-# CONFIG_AFS_FS is not set
-
-#
-# Partition Types
-#
-CONFIG_PARTITION_ADVANCED=y
-# CONFIG_ACORN_PARTITION is not set
-# CONFIG_OSF_PARTITION is not set
-# CONFIG_AMIGA_PARTITION is not set
-# CONFIG_ATARI_PARTITION is not set
-# CONFIG_MAC_PARTITION is not set
-CONFIG_MSDOS_PARTITION=y
-# CONFIG_BSD_DISKLABEL is not set
-# CONFIG_MINIX_SUBPARTITION is not set
-# CONFIG_SOLARIS_X86_PARTITION is not set
-# CONFIG_UNIXWARE_DISKLABEL is not set
-# CONFIG_LDM_PARTITION is not set
-# CONFIG_NEC98_PARTITION is not set
-CONFIG_SGI_PARTITION=y
-# CONFIG_ULTRIX_PARTITION is not set
-# CONFIG_SUN_PARTITION is not set
-# CONFIG_EFI_PARTITION is not set
-
-#
-# Graphics support
-#
-
-#
-# Console display driver support
-#
-CONFIG_VGA_CONSOLE=y
-# CONFIG_MDA_CONSOLE is not set
-CONFIG_DUMMY_CONSOLE=y
-
-#
-# Sound
-#
-# CONFIG_SOUND is not set
-
-#
-# USB support
-#
-# CONFIG_USB is not set
-# CONFIG_USB_GADGET is not set
-
-#
-# Bluetooth support
-#
-# CONFIG_BT is not set
-
-#
-# Kernel hacking
-#
-CONFIG_CROSSCOMPILE=y
-# CONFIG_DEBUG_KERNEL is not set
-
-#
-# Security options
-#
-# CONFIG_SECURITY is not set
-
-#
-# Cryptographic options
-#
-# CONFIG_CRYPTO is not set
-
-#
-# Library routines
-#
-# CONFIG_CRC32 is not set
--- diff/arch/mips/defconfig-sb1250-swarm	2003-08-20 14:16:25.000000000 +0100
+++ source/arch/mips/defconfig-sb1250-swarm	1970-01-01 01:00:00.000000000 +0100
@@ -1,619 +0,0 @@
-#
-# Automatically generated make config: don't edit
-#
-CONFIG_MIPS=y
-# CONFIG_MIPS64 is not set
-CONFIG_MIPS32=y
-
-#
-# Code maturity level options
-#
-CONFIG_EXPERIMENTAL=y
-
-#
-# General setup
-#
-CONFIG_SWAP=y
-CONFIG_SYSVIPC=y
-# CONFIG_BSD_PROCESS_ACCT is not set
-CONFIG_SYSCTL=y
-CONFIG_LOG_BUF_SHIFT=15
-# CONFIG_EMBEDDED is not set
-CONFIG_KALLSYMS=y
-CONFIG_FUTEX=y
-CONFIG_EPOLL=y
-CONFIG_IOSCHED_AS=y
-CONFIG_IOSCHED_DEADLINE=y
-
-#
-# Loadable module support
-#
-CONFIG_MODULES=y
-CONFIG_MODULE_UNLOAD=y
-# CONFIG_MODULE_FORCE_UNLOAD is not set
-CONFIG_OBSOLETE_MODPARM=y
-CONFIG_MODVERSIONS=y
-CONFIG_KMOD=y
-
-#
-# Machine selection
-#
-# CONFIG_ACER_PICA_61 is not set
-# CONFIG_BAGET_MIPS is not set
-# CONFIG_CASIO_E55 is not set
-# CONFIG_MIPS_COBALT is not set
-# CONFIG_DECSTATION is not set
-# CONFIG_MIPS_EV64120 is not set
-# CONFIG_MIPS_EV96100 is not set
-# CONFIG_MIPS_IVR is not set
-# CONFIG_LASAT is not set
-# CONFIG_HP_LASERJET is not set
-# CONFIG_IBM_WORKPAD is not set
-# CONFIG_MIPS_ITE8172 is not set
-# CONFIG_MIPS_ATLAS is not set
-# CONFIG_MIPS_MAGNUM_4000 is not set
-# CONFIG_MIPS_MALTA is not set
-# CONFIG_MIPS_SEAD is not set
-# CONFIG_MOMENCO_OCELOT is not set
-# CONFIG_MOMENCO_OCELOT_G is not set
-# CONFIG_MOMENCO_OCELOT_C is not set
-# CONFIG_DDB5074 is not set
-# CONFIG_DDB5476 is not set
-# CONFIG_DDB5477 is not set
-# CONFIG_NEC_OSPREY is not set
-# CONFIG_NEC_EAGLE is not set
-# CONFIG_OLIVETTI_M700 is not set
-# CONFIG_SGI_IP22 is not set
-# CONFIG_SGI_IP32 is not set
-# CONFIG_SOC_AU1X00 is not set
-CONFIG_SIBYTE_SB1xxx_SOC=y
-CONFIG_SIBYTE_SB1250=y
-# CONFIG_SIMULATION is not set
-CONFIG_SIBYTE_CFE=y
-# CONFIG_SIBYTE_CFE_CONSOLE is not set
-# CONFIG_SIBYTE_BUS_WATCHER is not set
-# CONFIG_SIBYTE_SB1250_PROF is not set
-# CONFIG_SIBYTE_TBPROF is not set
-CONFIG_SIBYTE_SWARM=y
-CONFIG_SIBYTE_BOARD=y
-# CONFIG_SNI_RM200_PCI is not set
-# CONFIG_TANBAC_TB0226 is not set
-# CONFIG_TANBAC_TB0229 is not set
-# CONFIG_TOSHIBA_JMR3927 is not set
-# CONFIG_TOSHIBA_RBTX4927 is not set
-# CONFIG_VICTOR_MPC30X is not set
-# CONFIG_ZAO_CAPCELLA is not set
-CONFIG_RWSEM_GENERIC_SPINLOCK=y
-# CONFIG_CPU_LITTLE_ENDIAN is not set
-CONFIG_DUMMY_KEYB=y
-CONFIG_SWAP_IO_SPACE=y
-CONFIG_SIBYTE_HAS_LDT=y
-CONFIG_BOOT_ELF32=y
-# CONFIG_FB is not set
-
-#
-# CPU selection
-#
-# CONFIG_CPU_MIPS32 is not set
-# CONFIG_CPU_MIPS64 is not set
-# CONFIG_CPU_R3000 is not set
-# CONFIG_CPU_TX39XX is not set
-# CONFIG_CPU_VR41XX is not set
-# CONFIG_CPU_R4300 is not set
-# CONFIG_CPU_R4X00 is not set
-# CONFIG_CPU_TX49XX is not set
-# CONFIG_CPU_R5000 is not set
-# CONFIG_CPU_R5432 is not set
-# CONFIG_CPU_R6000 is not set
-# CONFIG_CPU_NEVADA is not set
-# CONFIG_CPU_R8000 is not set
-# CONFIG_CPU_R10000 is not set
-# CONFIG_CPU_RM7000 is not set
-CONFIG_CPU_SB1=y
-# CONFIG_SIBYTE_DMA_PAGEOPS is not set
-CONFIG_CPU_HAS_PREFETCH=y
-CONFIG_VTAG_ICACHE=y
-CONFIG_CPU_SB1_PASS_1=y
-# CONFIG_CPU_SB1_PASS_2 is not set
-# CONFIG_CPU_SB1_PASS_2_2 is not set
-CONFIG_SB1_PASS_1_WORKAROUNDS=y
-CONFIG_SB1_CACHE_ERROR=y
-CONFIG_SB1_CERR_IGNORE_RECOVERABLE=y
-# CONFIG_SB1_CERR_SPIN is not set
-# CONFIG_64BIT_PHYS_ADDR is not set
-# CONFIG_CPU_ADVANCED is not set
-CONFIG_CPU_HAS_LLSC=y
-CONFIG_CPU_HAS_LLDSCD=y
-CONFIG_CPU_HAS_SYNC=y
-# CONFIG_HIGHMEM is not set
-CONFIG_SMP=y
-CONFIG_NR_CPUS=2
-# CONFIG_PREEMPT is not set
-# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
-
-#
-# Bus options (PCI, PCMCIA, EISA, ISA, TC)
-#
-CONFIG_PCI=y
-CONFIG_PCI_LEGACY_PROC=y
-CONFIG_PCI_NAMES=y
-CONFIG_MMU=y
-# CONFIG_HOTPLUG is not set
-
-#
-# Executable file formats
-#
-CONFIG_KCORE_ELF=y
-CONFIG_BINFMT_ELF=y
-# CONFIG_BINFMT_MISC is not set
-CONFIG_TRAD_SIGNALS=y
-# CONFIG_BINFMT_IRIX is not set
-
-#
-# Memory Technology Devices (MTD)
-#
-# CONFIG_MTD is not set
-
-#
-# Parallel port support
-#
-# CONFIG_PARPORT is not set
-
-#
-# Plug and Play support
-#
-# CONFIG_PNP is not set
-
-#
-# Generic Driver Options
-#
-# CONFIG_FW_LOADER is not set
-
-#
-# Block devices
-#
-# CONFIG_BLK_DEV_FD is not set
-# CONFIG_BLK_CPQ_DA is not set
-# CONFIG_BLK_CPQ_CISS_DA is not set
-# CONFIG_BLK_DEV_DAC960 is not set
-# CONFIG_BLK_DEV_UMEM is not set
-# CONFIG_BLK_DEV_LOOP is not set
-# CONFIG_BLK_DEV_NBD is not set
-CONFIG_BLK_DEV_RAM=y
-CONFIG_BLK_DEV_RAM_SIZE=9220
-# CONFIG_BLK_DEV_INITRD is not set
-# CONFIG_LBD is not set
-
-#
-# ATA/ATAPI/MFM/RLL support
-#
-# CONFIG_IDE is not set
-
-#
-# SCSI device support
-#
-# CONFIG_SCSI is not set
-
-#
-# Multi-device support (RAID and LVM)
-#
-# CONFIG_MD is not set
-
-#
-# Fusion MPT device support
-#
-
-#
-# IEEE 1394 (FireWire) support (EXPERIMENTAL)
-#
-# CONFIG_IEEE1394 is not set
-
-#
-# I2O device support
-#
-# CONFIG_I2O is not set
-
-#
-# Networking support
-#
-CONFIG_NET=y
-
-#
-# Networking options
-#
-CONFIG_PACKET=y
-CONFIG_PACKET_MMAP=y
-CONFIG_NETLINK_DEV=y
-# CONFIG_NETFILTER is not set
-CONFIG_UNIX=y
-CONFIG_NET_KEY=y
-CONFIG_INET=y
-# CONFIG_IP_MULTICAST is not set
-# CONFIG_IP_ADVANCED_ROUTER is not set
-# CONFIG_IP_PNP is not set
-# CONFIG_NET_IPIP is not set
-# CONFIG_NET_IPGRE is not set
-# CONFIG_ARPD is not set
-# CONFIG_INET_ECN is not set
-# CONFIG_SYN_COOKIES is not set
-# CONFIG_INET_AH is not set
-# CONFIG_INET_ESP is not set
-# CONFIG_INET_IPCOMP is not set
-# CONFIG_IPV6 is not set
-# CONFIG_XFRM_USER is not set
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
-CONFIG_IPV6_SCTP__=y
-# CONFIG_IP_SCTP is not set
-# CONFIG_ATM is not set
-# CONFIG_VLAN_8021Q is not set
-# CONFIG_LLC is not set
-# CONFIG_DECNET is not set
-# CONFIG_BRIDGE is not set
-# CONFIG_X25 is not set
-# CONFIG_LAPB is not set
-# CONFIG_NET_DIVERT is not set
-# CONFIG_ECONET is not set
-# CONFIG_WAN_ROUTER is not set
-# CONFIG_NET_FASTROUTE is not set
-# CONFIG_NET_HW_FLOWCONTROL is not set
-
-#
-# QoS and/or fair queueing
-#
-# CONFIG_NET_SCHED is not set
-
-#
-# Network testing
-#
-# CONFIG_NET_PKTGEN is not set
-CONFIG_NETDEVICES=y
-
-#
-# ARCnet devices
-#
-# CONFIG_ARCNET is not set
-# CONFIG_DUMMY is not set
-# CONFIG_BONDING is not set
-# CONFIG_EQUALIZER is not set
-# CONFIG_TUN is not set
-# CONFIG_ETHERTAP is not set
-
-#
-# Ethernet (10 or 100Mbit)
-#
-CONFIG_NET_ETHERNET=y
-# CONFIG_MII is not set
-CONFIG_NET_SB1250_MAC=y
-# CONFIG_HAPPYMEAL is not set
-# CONFIG_SUNGEM is not set
-# CONFIG_NET_VENDOR_3COM is not set
-
-#
-# Tulip family network device support
-#
-# CONFIG_NET_TULIP is not set
-# CONFIG_HP100 is not set
-# CONFIG_NET_PCI is not set
-
-#
-# Ethernet (1000 Mbit)
-#
-# CONFIG_ACENIC is not set
-# CONFIG_DL2K is not set
-# CONFIG_E1000 is not set
-# CONFIG_NS83820 is not set
-# CONFIG_HAMACHI is not set
-# CONFIG_YELLOWFIN is not set
-# CONFIG_R8169 is not set
-# CONFIG_SK98LIN is not set
-# CONFIG_TIGON3 is not set
-
-#
-# Ethernet (10000 Mbit)
-#
-# CONFIG_IXGB is not set
-# CONFIG_FDDI is not set
-# CONFIG_HIPPI is not set
-# CONFIG_PPP is not set
-# CONFIG_SLIP is not set
-
-#
-# Wireless LAN (non-hamradio)
-#
-# CONFIG_NET_RADIO is not set
-
-#
-# Token Ring devices (depends on LLC=y)
-#
-# CONFIG_RCPCI is not set
-# CONFIG_SHAPER is not set
-
-#
-# Wan interfaces
-#
-# CONFIG_WAN is not set
-
-#
-# Amateur Radio support
-#
-# CONFIG_HAMRADIO is not set
-
-#
-# IrDA (infrared) support
-#
-# CONFIG_IRDA is not set
-
-#
-# ISDN subsystem
-#
-# CONFIG_ISDN_BOOL is not set
-
-#
-# Telephony Support
-#
-# CONFIG_PHONE is not set
-
-#
-# Input device support
-#
-CONFIG_INPUT=y
-
-#
-# Userland interfaces
-#
-# CONFIG_INPUT_MOUSEDEV is not set
-# CONFIG_INPUT_JOYDEV is not set
-# CONFIG_INPUT_TSDEV is not set
-# CONFIG_INPUT_EVDEV is not set
-# CONFIG_INPUT_EVBUG is not set
-
-#
-# Input I/O drivers
-#
-# CONFIG_GAMEPORT is not set
-CONFIG_SOUND_GAMEPORT=y
-CONFIG_SERIO=y
-# CONFIG_SERIO_I8042 is not set
-CONFIG_SERIO_SERPORT=y
-# CONFIG_SERIO_CT82C710 is not set
-# CONFIG_SERIO_PCIPS2 is not set
-
-#
-# Input Device Drivers
-#
-# CONFIG_INPUT_KEYBOARD is not set
-# CONFIG_INPUT_MOUSE is not set
-# CONFIG_INPUT_JOYSTICK is not set
-# CONFIG_INPUT_TOUCHSCREEN is not set
-# CONFIG_INPUT_MISC is not set
-
-#
-# Character devices
-#
-# CONFIG_VT is not set
-CONFIG_SERIAL_NONSTANDARD=y
-# CONFIG_COMPUTONE is not set
-# CONFIG_ROCKETPORT is not set
-# CONFIG_CYCLADES is not set
-# CONFIG_DIGIEPCA is not set
-# CONFIG_DIGI is not set
-# CONFIG_MOXA_INTELLIO is not set
-# CONFIG_MOXA_SMARTIO is not set
-# CONFIG_ISI is not set
-# CONFIG_SYNCLINK is not set
-# CONFIG_SYNCLINKMP is not set
-# CONFIG_N_HDLC is not set
-# CONFIG_RISCOM8 is not set
-# CONFIG_SPECIALIX is not set
-# CONFIG_SX is not set
-# CONFIG_RIO is not set
-# CONFIG_STALDRV is not set
-CONFIG_SIBYTE_SB1250_DUART=y
-CONFIG_SIBYTE_SB1250_DUART_CONSOLE=y
-CONFIG_SERIAL_CONSOLE=y
-
-#
-# Serial drivers
-#
-# CONFIG_SERIAL_8250 is not set
-
-#
-# Non-8250 serial port support
-#
-# CONFIG_UNIX98_PTYS is not set
-
-#
-# I2C support
-#
-# CONFIG_I2C is not set
-
-#
-# I2C Hardware Sensors Mainboard support
-#
-
-#
-# I2C Hardware Sensors Chip support
-#
-# CONFIG_I2C_SENSOR is not set
-
-#
-# Mice
-#
-# CONFIG_BUSMOUSE is not set
-# CONFIG_QIC02_TAPE is not set
-
-#
-# IPMI
-#
-# CONFIG_IPMI_HANDLER is not set
-
-#
-# Watchdog Cards
-#
-# CONFIG_WATCHDOG is not set
-# CONFIG_NVRAM is not set
-# CONFIG_RTC is not set
-# CONFIG_GEN_RTC is not set
-# CONFIG_DTLK is not set
-# CONFIG_R3964 is not set
-# CONFIG_APPLICOM is not set
-
-#
-# Ftape, the floppy tape device driver
-#
-# CONFIG_FTAPE is not set
-# CONFIG_AGP is not set
-# CONFIG_DRM is not set
-# CONFIG_RAW_DRIVER is not set
-# CONFIG_HANGCHECK_TIMER is not set
-
-#
-# Multimedia devices
-#
-# CONFIG_VIDEO_DEV is not set
-
-#
-# Digital Video Broadcasting Devices
-#
-# CONFIG_DVB is not set
-
-#
-# File systems
-#
-CONFIG_EXT2_FS=y
-CONFIG_EXT2_FS_XATTR=y
-CONFIG_EXT2_FS_POSIX_ACL=y
-CONFIG_EXT2_FS_SECURITY=y
-# CONFIG_EXT3_FS is not set
-# CONFIG_JBD is not set
-CONFIG_FS_MBCACHE=y
-# CONFIG_REISERFS_FS is not set
-# CONFIG_JFS_FS is not set
-CONFIG_FS_POSIX_ACL=y
-# CONFIG_XFS_FS is not set
-# CONFIG_MINIX_FS is not set
-# CONFIG_ROMFS_FS is not set
-# CONFIG_QUOTA is not set
-# CONFIG_AUTOFS_FS is not set
-# CONFIG_AUTOFS4_FS is not set
-
-#
-# CD-ROM/DVD Filesystems
-#
-# CONFIG_ISO9660_FS is not set
-# CONFIG_UDF_FS is not set
-
-#
-# DOS/FAT/NT Filesystems
-#
-# CONFIG_FAT_FS is not set
-# CONFIG_NTFS_FS is not set
-
-#
-# Pseudo filesystems
-#
-CONFIG_PROC_FS=y
-# CONFIG_DEVFS_FS is not set
-# CONFIG_TMPFS is not set
-CONFIG_RAMFS=y
-
-#
-# Miscellaneous filesystems
-#
-# CONFIG_ADFS_FS is not set
-# CONFIG_AFFS_FS is not set
-# CONFIG_HFS_FS is not set
-# CONFIG_BEFS_FS is not set
-# CONFIG_BFS_FS is not set
-# CONFIG_EFS_FS is not set
-# CONFIG_CRAMFS is not set
-# CONFIG_VXFS_FS is not set
-# CONFIG_HPFS_FS is not set
-# CONFIG_QNX4FS_FS is not set
-# CONFIG_SYSV_FS is not set
-# CONFIG_UFS_FS is not set
-
-#
-# Network File Systems
-#
-CONFIG_NFS_FS=y
-CONFIG_NFS_V3=y
-# CONFIG_NFS_V4 is not set
-# CONFIG_NFSD is not set
-CONFIG_LOCKD=y
-CONFIG_LOCKD_V4=y
-# CONFIG_EXPORTFS is not set
-CONFIG_SUNRPC=y
-# CONFIG_SUNRPC_GSS is not set
-# CONFIG_SMB_FS is not set
-# CONFIG_CIFS is not set
-# CONFIG_NCP_FS is not set
-# CONFIG_CODA_FS is not set
-# CONFIG_INTERMEZZO_FS is not set
-# CONFIG_AFS_FS is not set
-
-#
-# Partition Types
-#
-# CONFIG_PARTITION_ADVANCED is not set
-CONFIG_MSDOS_PARTITION=y
-
-#
-# Graphics support
-#
-
-#
-# Sound
-#
-# CONFIG_SOUND is not set
-
-#
-# USB support
-#
-# CONFIG_USB is not set
-# CONFIG_USB_GADGET is not set
-
-#
-# Bluetooth support
-#
-# CONFIG_BT is not set
-
-#
-# Kernel hacking
-#
-CONFIG_CROSSCOMPILE=y
-# CONFIG_DEBUG_KERNEL is not set
-
-#
-# Security options
-#
-# CONFIG_SECURITY is not set
-
-#
-# Cryptographic options
-#
-CONFIG_CRYPTO=y
-CONFIG_CRYPTO_HMAC=y
-CONFIG_CRYPTO_NULL=y
-CONFIG_CRYPTO_MD4=y
-CONFIG_CRYPTO_MD5=y
-CONFIG_CRYPTO_SHA1=y
-CONFIG_CRYPTO_SHA256=y
-CONFIG_CRYPTO_SHA512=y
-CONFIG_CRYPTO_DES=y
-CONFIG_CRYPTO_BLOWFISH=y
-CONFIG_CRYPTO_TWOFISH=y
-CONFIG_CRYPTO_SERPENT=y
-CONFIG_CRYPTO_AES=y
-CONFIG_CRYPTO_DEFLATE=y
-# CONFIG_CRYPTO_TEST is not set
-
-#
-# Library routines
-#
-# CONFIG_CRC32 is not set
-CONFIG_ZLIB_INFLATE=y
-CONFIG_ZLIB_DEFLATE=y
--- diff/arch/mips/defconfig-sead	2003-08-20 14:16:25.000000000 +0100
+++ source/arch/mips/defconfig-sead	1970-01-01 01:00:00.000000000 +0100
@@ -1,398 +0,0 @@
-#
-# Automatically generated make config: don't edit
-#
-CONFIG_MIPS=y
-# CONFIG_MIPS64 is not set
-CONFIG_MIPS32=y
-
-#
-# Code maturity level options
-#
-CONFIG_EXPERIMENTAL=y
-
-#
-# General setup
-#
-CONFIG_SWAP=y
-# CONFIG_SYSVIPC is not set
-# CONFIG_BSD_PROCESS_ACCT is not set
-CONFIG_SYSCTL=y
-CONFIG_LOG_BUF_SHIFT=14
-# CONFIG_EMBEDDED is not set
-CONFIG_KALLSYMS=y
-CONFIG_FUTEX=y
-CONFIG_EPOLL=y
-CONFIG_IOSCHED_AS=y
-CONFIG_IOSCHED_DEADLINE=y
-
-#
-# Loadable module support
-#
-# CONFIG_MODULES is not set
-
-#
-# Machine selection
-#
-# CONFIG_ACER_PICA_61 is not set
-# CONFIG_BAGET_MIPS is not set
-# CONFIG_CASIO_E55 is not set
-# CONFIG_MIPS_COBALT is not set
-# CONFIG_DECSTATION is not set
-# CONFIG_MIPS_EV64120 is not set
-# CONFIG_MIPS_EV96100 is not set
-# CONFIG_MIPS_IVR is not set
-# CONFIG_LASAT is not set
-# CONFIG_HP_LASERJET is not set
-# CONFIG_IBM_WORKPAD is not set
-# CONFIG_MIPS_ITE8172 is not set
-# CONFIG_MIPS_ATLAS is not set
-# CONFIG_MIPS_MAGNUM_4000 is not set
-# CONFIG_MIPS_MALTA is not set
-CONFIG_MIPS_SEAD=y
-# CONFIG_MOMENCO_OCELOT is not set
-# CONFIG_MOMENCO_OCELOT_G is not set
-# CONFIG_MOMENCO_OCELOT_C is not set
-# CONFIG_DDB5074 is not set
-# CONFIG_DDB5476 is not set
-# CONFIG_DDB5477 is not set
-# CONFIG_NEC_OSPREY is not set
-# CONFIG_NEC_EAGLE is not set
-# CONFIG_OLIVETTI_M700 is not set
-# CONFIG_SGI_IP22 is not set
-# CONFIG_SGI_IP32 is not set
-# CONFIG_SOC_AU1X00 is not set
-# CONFIG_SIBYTE_SB1xxx_SOC is not set
-# CONFIG_SNI_RM200_PCI is not set
-# CONFIG_TANBAC_TB0226 is not set
-# CONFIG_TANBAC_TB0229 is not set
-# CONFIG_TOSHIBA_JMR3927 is not set
-# CONFIG_TOSHIBA_RBTX4927 is not set
-# CONFIG_VICTOR_MPC30X is not set
-# CONFIG_ZAO_CAPCELLA is not set
-CONFIG_RWSEM_GENERIC_SPINLOCK=y
-CONFIG_NONCOHERENT_IO=y
-CONFIG_CPU_LITTLE_ENDIAN=y
-CONFIG_MIPS_BOARDS_GEN=y
-CONFIG_L1_CACHE_SHIFT=5
-# CONFIG_FB is not set
-
-#
-# CPU selection
-#
-CONFIG_CPU_MIPS32=y
-# CONFIG_CPU_MIPS64 is not set
-# CONFIG_CPU_R3000 is not set
-# CONFIG_CPU_TX39XX is not set
-# CONFIG_CPU_VR41XX is not set
-# CONFIG_CPU_R4300 is not set
-# CONFIG_CPU_R4X00 is not set
-# CONFIG_CPU_TX49XX is not set
-# CONFIG_CPU_R5000 is not set
-# CONFIG_CPU_R5432 is not set
-# CONFIG_CPU_R6000 is not set
-# CONFIG_CPU_NEVADA is not set
-# CONFIG_CPU_R8000 is not set
-# CONFIG_CPU_R10000 is not set
-# CONFIG_CPU_RM7000 is not set
-# CONFIG_CPU_SB1 is not set
-CONFIG_CPU_HAS_PREFETCH=y
-# CONFIG_VTAG_ICACHE is not set
-# CONFIG_64BIT_PHYS_ADDR is not set
-# CONFIG_CPU_ADVANCED is not set
-CONFIG_CPU_HAS_LLSC=y
-CONFIG_CPU_HAS_SYNC=y
-# CONFIG_PREEMPT is not set
-# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
-
-#
-# Bus options (PCI, PCMCIA, EISA, ISA, TC)
-#
-CONFIG_MMU=y
-# CONFIG_HOTPLUG is not set
-
-#
-# Executable file formats
-#
-CONFIG_KCORE_ELF=y
-CONFIG_BINFMT_ELF=y
-# CONFIG_BINFMT_MISC is not set
-CONFIG_TRAD_SIGNALS=y
-
-#
-# Memory Technology Devices (MTD)
-#
-# CONFIG_MTD is not set
-
-#
-# Parallel port support
-#
-# CONFIG_PARPORT is not set
-
-#
-# Plug and Play support
-#
-# CONFIG_PNP is not set
-
-#
-# Generic Driver Options
-#
-# CONFIG_FW_LOADER is not set
-
-#
-# Block devices
-#
-# CONFIG_BLK_DEV_FD is not set
-CONFIG_BLK_DEV_LOOP=y
-# CONFIG_BLK_DEV_CRYPTOLOOP is not set
-CONFIG_BLK_DEV_RAM=y
-CONFIG_BLK_DEV_RAM_SIZE=18432
-CONFIG_BLK_DEV_INITRD=y
-# CONFIG_LBD is not set
-
-#
-# MIPS initrd options
-#
-CONFIG_EMBEDDED_RAMDISK=y
-CONFIG_EMBEDDED_RAMDISK_IMAGE="ramdisk.gz"
-
-#
-# ATA/ATAPI/MFM/RLL support
-#
-# CONFIG_IDE is not set
-
-#
-# SCSI device support
-#
-# CONFIG_SCSI is not set
-
-#
-# Multi-device support (RAID and LVM)
-#
-# CONFIG_MD is not set
-
-#
-# Fusion MPT device support
-#
-
-#
-# I2O device support
-#
-
-#
-# Networking support
-#
-# CONFIG_NET is not set
-
-#
-# Amateur Radio support
-#
-# CONFIG_HAMRADIO is not set
-
-#
-# ISDN subsystem
-#
-
-#
-# Telephony Support
-#
-# CONFIG_PHONE is not set
-
-#
-# Input device support
-#
-CONFIG_INPUT=y
-
-#
-# Userland interfaces
-#
-# CONFIG_INPUT_MOUSEDEV is not set
-# CONFIG_INPUT_JOYDEV is not set
-# CONFIG_INPUT_TSDEV is not set
-# CONFIG_INPUT_EVDEV is not set
-# CONFIG_INPUT_EVBUG is not set
-
-#
-# Input I/O drivers
-#
-# CONFIG_GAMEPORT is not set
-CONFIG_SOUND_GAMEPORT=y
-CONFIG_SERIO=y
-# CONFIG_SERIO_I8042 is not set
-CONFIG_SERIO_SERPORT=y
-# CONFIG_SERIO_CT82C710 is not set
-
-#
-# Input Device Drivers
-#
-# CONFIG_INPUT_KEYBOARD is not set
-# CONFIG_INPUT_MOUSE is not set
-# CONFIG_INPUT_JOYSTICK is not set
-# CONFIG_INPUT_TOUCHSCREEN is not set
-# CONFIG_INPUT_MISC is not set
-
-#
-# Character devices
-#
-# CONFIG_VT is not set
-# CONFIG_SERIAL_NONSTANDARD is not set
-
-#
-# Serial drivers
-#
-CONFIG_SERIAL_8250=y
-CONFIG_SERIAL_8250_CONSOLE=y
-# CONFIG_SERIAL_8250_EXTENDED is not set
-
-#
-# Non-8250 serial port support
-#
-CONFIG_SERIAL_CORE=y
-CONFIG_SERIAL_CORE_CONSOLE=y
-# CONFIG_UNIX98_PTYS is not set
-
-#
-# I2C support
-#
-# CONFIG_I2C is not set
-
-#
-# I2C Hardware Sensors Mainboard support
-#
-
-#
-# I2C Hardware Sensors Chip support
-#
-# CONFIG_I2C_SENSOR is not set
-
-#
-# Mice
-#
-# CONFIG_BUSMOUSE is not set
-# CONFIG_QIC02_TAPE is not set
-
-#
-# IPMI
-#
-# CONFIG_IPMI_HANDLER is not set
-
-#
-# Watchdog Cards
-#
-# CONFIG_WATCHDOG is not set
-# CONFIG_NVRAM is not set
-# CONFIG_RTC is not set
-# CONFIG_GEN_RTC is not set
-# CONFIG_DTLK is not set
-# CONFIG_R3964 is not set
-# CONFIG_APPLICOM is not set
-
-#
-# Ftape, the floppy tape device driver
-#
-# CONFIG_FTAPE is not set
-# CONFIG_AGP is not set
-# CONFIG_DRM is not set
-# CONFIG_RAW_DRIVER is not set
-# CONFIG_HANGCHECK_TIMER is not set
-
-#
-# Multimedia devices
-#
-# CONFIG_VIDEO_DEV is not set
-
-#
-# File systems
-#
-CONFIG_EXT2_FS=y
-CONFIG_EXT2_FS_XATTR=y
-CONFIG_EXT2_FS_POSIX_ACL=y
-CONFIG_EXT2_FS_SECURITY=y
-# CONFIG_EXT3_FS is not set
-# CONFIG_JBD is not set
-CONFIG_FS_MBCACHE=y
-# CONFIG_REISERFS_FS is not set
-# CONFIG_JFS_FS is not set
-CONFIG_FS_POSIX_ACL=y
-# CONFIG_XFS_FS is not set
-# CONFIG_MINIX_FS is not set
-# CONFIG_ROMFS_FS is not set
-# CONFIG_QUOTA is not set
-# CONFIG_AUTOFS_FS is not set
-# CONFIG_AUTOFS4_FS is not set
-
-#
-# CD-ROM/DVD Filesystems
-#
-# CONFIG_ISO9660_FS is not set
-# CONFIG_UDF_FS is not set
-
-#
-# DOS/FAT/NT Filesystems
-#
-# CONFIG_FAT_FS is not set
-# CONFIG_NTFS_FS is not set
-
-#
-# Pseudo filesystems
-#
-CONFIG_PROC_FS=y
-# CONFIG_DEVFS_FS is not set
-# CONFIG_TMPFS is not set
-CONFIG_RAMFS=y
-
-#
-# Miscellaneous filesystems
-#
-# CONFIG_ADFS_FS is not set
-# CONFIG_AFFS_FS is not set
-# CONFIG_HFS_FS is not set
-# CONFIG_BEFS_FS is not set
-# CONFIG_BFS_FS is not set
-# CONFIG_EFS_FS is not set
-# CONFIG_CRAMFS is not set
-# CONFIG_VXFS_FS is not set
-# CONFIG_HPFS_FS is not set
-# CONFIG_QNX4FS_FS is not set
-# CONFIG_SYSV_FS is not set
-# CONFIG_UFS_FS is not set
-
-#
-# Partition Types
-#
-# CONFIG_PARTITION_ADVANCED is not set
-CONFIG_MSDOS_PARTITION=y
-
-#
-# Graphics support
-#
-
-#
-# Sound
-#
-# CONFIG_SOUND is not set
-
-#
-# USB support
-#
-# CONFIG_USB_GADGET is not set
-
-#
-# Kernel hacking
-#
-CONFIG_CROSSCOMPILE=y
-# CONFIG_DEBUG_KERNEL is not set
-
-#
-# Security options
-#
-# CONFIG_SECURITY is not set
-
-#
-# Cryptographic options
-#
-# CONFIG_CRYPTO is not set
-
-#
-# Library routines
-#
-# CONFIG_CRC32 is not set
--- diff/arch/mips/defconfig-tb0226	2003-08-20 14:16:25.000000000 +0100
+++ source/arch/mips/defconfig-tb0226	1970-01-01 01:00:00.000000000 +0100
@@ -1,672 +0,0 @@
-#
-# Automatically generated make config: don't edit
-#
-CONFIG_MIPS=y
-# CONFIG_MIPS64 is not set
-CONFIG_MIPS32=y
-
-#
-# Code maturity level options
-#
-CONFIG_EXPERIMENTAL=y
-
-#
-# General setup
-#
-CONFIG_SWAP=y
-CONFIG_SYSVIPC=y
-# CONFIG_BSD_PROCESS_ACCT is not set
-CONFIG_SYSCTL=y
-CONFIG_LOG_BUF_SHIFT=14
-# CONFIG_EMBEDDED is not set
-CONFIG_KALLSYMS=y
-CONFIG_FUTEX=y
-CONFIG_EPOLL=y
-CONFIG_IOSCHED_AS=y
-CONFIG_IOSCHED_DEADLINE=y
-
-#
-# Loadable module support
-#
-CONFIG_MODULES=y
-CONFIG_MODULE_UNLOAD=y
-# CONFIG_MODULE_FORCE_UNLOAD is not set
-CONFIG_OBSOLETE_MODPARM=y
-CONFIG_MODVERSIONS=y
-CONFIG_KMOD=y
-
-#
-# Machine selection
-#
-# CONFIG_ACER_PICA_61 is not set
-# CONFIG_BAGET_MIPS is not set
-# CONFIG_CASIO_E55 is not set
-# CONFIG_MIPS_COBALT is not set
-# CONFIG_DECSTATION is not set
-# CONFIG_MIPS_EV64120 is not set
-# CONFIG_MIPS_EV96100 is not set
-# CONFIG_MIPS_IVR is not set
-# CONFIG_LASAT is not set
-# CONFIG_HP_LASERJET is not set
-# CONFIG_IBM_WORKPAD is not set
-# CONFIG_MIPS_ITE8172 is not set
-# CONFIG_MIPS_ATLAS is not set
-# CONFIG_MIPS_MAGNUM_4000 is not set
-# CONFIG_MIPS_MALTA is not set
-# CONFIG_MIPS_SEAD is not set
-# CONFIG_MOMENCO_OCELOT is not set
-# CONFIG_MOMENCO_OCELOT_G is not set
-# CONFIG_MOMENCO_OCELOT_C is not set
-# CONFIG_DDB5074 is not set
-# CONFIG_DDB5476 is not set
-# CONFIG_DDB5477 is not set
-# CONFIG_NEC_OSPREY is not set
-# CONFIG_NEC_EAGLE is not set
-# CONFIG_OLIVETTI_M700 is not set
-# CONFIG_SGI_IP22 is not set
-# CONFIG_SGI_IP32 is not set
-# CONFIG_SOC_AU1X00 is not set
-# CONFIG_SIBYTE_SB1xxx_SOC is not set
-# CONFIG_SNI_RM200_PCI is not set
-CONFIG_TANBAC_TB0226=y
-# CONFIG_TANBAC_TB0229 is not set
-# CONFIG_TOSHIBA_JMR3927 is not set
-# CONFIG_TOSHIBA_RBTX4927 is not set
-# CONFIG_VICTOR_MPC30X is not set
-# CONFIG_ZAO_CAPCELLA is not set
-CONFIG_RWSEM_GENERIC_SPINLOCK=y
-CONFIG_GENERIC_ISA_DMA=y
-CONFIG_NONCOHERENT_IO=y
-CONFIG_CPU_LITTLE_ENDIAN=y
-CONFIG_IRQ_CPU=y
-CONFIG_VR41XX_TIME_C=y
-CONFIG_DUMMY_KEYB=y
-CONFIG_VR41XX_COMMON=y
-CONFIG_NEW_PCI=y
-CONFIG_FB=y
-
-#
-# CPU selection
-#
-# CONFIG_CPU_MIPS32 is not set
-# CONFIG_CPU_MIPS64 is not set
-# CONFIG_CPU_R3000 is not set
-# CONFIG_CPU_TX39XX is not set
-CONFIG_CPU_VR41XX=y
-# CONFIG_CPU_R4300 is not set
-# CONFIG_CPU_R4X00 is not set
-# CONFIG_CPU_TX49XX is not set
-# CONFIG_CPU_R5000 is not set
-# CONFIG_CPU_R5432 is not set
-# CONFIG_CPU_R6000 is not set
-# CONFIG_CPU_NEVADA is not set
-# CONFIG_CPU_R8000 is not set
-# CONFIG_CPU_R10000 is not set
-# CONFIG_CPU_RM7000 is not set
-# CONFIG_CPU_SB1 is not set
-# CONFIG_CPU_ADVANCED is not set
-CONFIG_CPU_HAS_SYNC=y
-# CONFIG_PREEMPT is not set
-# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
-
-#
-# Bus options (PCI, PCMCIA, EISA, ISA, TC)
-#
-# CONFIG_PCI is not set
-CONFIG_MMU=y
-# CONFIG_HOTPLUG is not set
-
-#
-# Executable file formats
-#
-CONFIG_KCORE_ELF=y
-CONFIG_BINFMT_ELF=y
-# CONFIG_BINFMT_MISC is not set
-CONFIG_TRAD_SIGNALS=y
-
-#
-# Memory Technology Devices (MTD)
-#
-# CONFIG_MTD is not set
-
-#
-# Parallel port support
-#
-# CONFIG_PARPORT is not set
-
-#
-# Plug and Play support
-#
-# CONFIG_PNP is not set
-
-#
-# Generic Driver Options
-#
-# CONFIG_FW_LOADER is not set
-
-#
-# Block devices
-#
-CONFIG_BLK_DEV_FD=y
-CONFIG_BLK_DEV_LOOP=m
-# CONFIG_BLK_DEV_CRYPTOLOOP is not set
-CONFIG_BLK_DEV_NBD=m
-CONFIG_BLK_DEV_RAM=m
-CONFIG_BLK_DEV_RAM_SIZE=4096
-# CONFIG_BLK_DEV_INITRD is not set
-# CONFIG_LBD is not set
-
-#
-# ATA/ATAPI/MFM/RLL support
-#
-CONFIG_IDE=y
-
-#
-# IDE, ATA and ATAPI Block devices
-#
-CONFIG_BLK_DEV_IDE=y
-
-#
-# Please see Documentation/ide.txt for help/info on IDE drives
-#
-# CONFIG_BLK_DEV_HD is not set
-CONFIG_BLK_DEV_IDEDISK=y
-CONFIG_IDEDISK_MULTI_MODE=y
-# CONFIG_IDEDISK_STROKE is not set
-# CONFIG_BLK_DEV_IDECD is not set
-# CONFIG_BLK_DEV_IDEFLOPPY is not set
-CONFIG_BLK_DEV_IDESCSI=y
-# CONFIG_IDE_TASK_IOCTL is not set
-CONFIG_IDE_TASKFILE_IO=y
-
-#
-# IDE chipset support/bugfixes
-#
-
-#
-# SCSI device support
-#
-CONFIG_SCSI=y
-
-#
-# SCSI support type (disk, tape, CD-ROM)
-#
-CONFIG_BLK_DEV_SD=y
-# CONFIG_CHR_DEV_ST is not set
-# CONFIG_CHR_DEV_OSST is not set
-CONFIG_BLK_DEV_SR=y
-# CONFIG_BLK_DEV_SR_VENDOR is not set
-CONFIG_CHR_DEV_SG=y
-
-#
-# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
-#
-CONFIG_SCSI_MULTI_LUN=y
-# CONFIG_SCSI_REPORT_LUNS is not set
-CONFIG_SCSI_CONSTANTS=y
-# CONFIG_SCSI_LOGGING is not set
-
-#
-# SCSI low-level drivers
-#
-# CONFIG_SCSI_AIC7XXX is not set
-# CONFIG_SCSI_AIC7XXX_OLD is not set
-# CONFIG_SCSI_DPT_I2O is not set
-# CONFIG_SCSI_EATA_PIO is not set
-# CONFIG_SCSI_DEBUG is not set
-
-#
-# Multi-device support (RAID and LVM)
-#
-# CONFIG_MD is not set
-
-#
-# Fusion MPT device support
-#
-# CONFIG_FUSION is not set
-
-#
-# I2O device support
-#
-
-#
-# Networking support
-#
-CONFIG_NET=y
-
-#
-# Networking options
-#
-CONFIG_PACKET=y
-# CONFIG_PACKET_MMAP is not set
-CONFIG_NETLINK_DEV=m
-# CONFIG_NETFILTER is not set
-CONFIG_UNIX=y
-# CONFIG_NET_KEY is not set
-CONFIG_INET=y
-CONFIG_IP_MULTICAST=y
-CONFIG_IP_ADVANCED_ROUTER=y
-CONFIG_IP_MULTIPLE_TABLES=y
-CONFIG_IP_ROUTE_NAT=y
-CONFIG_IP_ROUTE_MULTIPATH=y
-CONFIG_IP_ROUTE_TOS=y
-CONFIG_IP_ROUTE_VERBOSE=y
-CONFIG_IP_PNP=y
-# CONFIG_IP_PNP_DHCP is not set
-CONFIG_IP_PNP_BOOTP=y
-# CONFIG_IP_PNP_RARP is not set
-# CONFIG_NET_IPIP is not set
-# CONFIG_NET_IPGRE is not set
-# CONFIG_IP_MROUTE is not set
-# CONFIG_ARPD is not set
-# CONFIG_INET_ECN is not set
-CONFIG_SYN_COOKIES=y
-# CONFIG_INET_AH is not set
-# CONFIG_INET_ESP is not set
-# CONFIG_INET_IPCOMP is not set
-# CONFIG_IPV6 is not set
-# CONFIG_XFRM_USER is not set
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
-CONFIG_IPV6_SCTP__=y
-# CONFIG_IP_SCTP is not set
-# CONFIG_ATM is not set
-# CONFIG_VLAN_8021Q is not set
-# CONFIG_LLC is not set
-# CONFIG_DECNET is not set
-# CONFIG_BRIDGE is not set
-# CONFIG_X25 is not set
-# CONFIG_LAPB is not set
-# CONFIG_NET_DIVERT is not set
-# CONFIG_ECONET is not set
-# CONFIG_WAN_ROUTER is not set
-# CONFIG_NET_FASTROUTE is not set
-# CONFIG_NET_HW_FLOWCONTROL is not set
-
-#
-# QoS and/or fair queueing
-#
-# CONFIG_NET_SCHED is not set
-
-#
-# Network testing
-#
-# CONFIG_NET_PKTGEN is not set
-CONFIG_NETDEVICES=y
-# CONFIG_DUMMY is not set
-# CONFIG_BONDING is not set
-# CONFIG_EQUALIZER is not set
-# CONFIG_TUN is not set
-# CONFIG_ETHERTAP is not set
-
-#
-# Ethernet (10 or 100Mbit)
-#
-CONFIG_NET_ETHERNET=y
-# CONFIG_MII is not set
-
-#
-# Ethernet (1000 Mbit)
-#
-
-#
-# Ethernet (10000 Mbit)
-#
-CONFIG_PPP=m
-CONFIG_PPP_MULTILINK=y
-# CONFIG_PPP_FILTER is not set
-CONFIG_PPP_ASYNC=m
-CONFIG_PPP_SYNC_TTY=m
-CONFIG_PPP_DEFLATE=m
-CONFIG_PPP_BSDCOMP=m
-CONFIG_PPPOE=m
-# CONFIG_SLIP is not set
-
-#
-# Wireless LAN (non-hamradio)
-#
-# CONFIG_NET_RADIO is not set
-
-#
-# Token Ring devices (depends on LLC=y)
-#
-# CONFIG_SHAPER is not set
-
-#
-# Wan interfaces
-#
-# CONFIG_WAN is not set
-
-#
-# Amateur Radio support
-#
-# CONFIG_HAMRADIO is not set
-
-#
-# IrDA (infrared) support
-#
-# CONFIG_IRDA is not set
-
-#
-# ISDN subsystem
-#
-# CONFIG_ISDN_BOOL is not set
-
-#
-# Telephony Support
-#
-# CONFIG_PHONE is not set
-
-#
-# Input device support
-#
-CONFIG_INPUT=y
-
-#
-# Userland interfaces
-#
-CONFIG_INPUT_MOUSEDEV=m
-# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
-CONFIG_INPUT_MOUSEDEV_SCREEN_X=1280
-CONFIG_INPUT_MOUSEDEV_SCREEN_Y=1024
-# CONFIG_INPUT_JOYDEV is not set
-# CONFIG_INPUT_TSDEV is not set
-# CONFIG_INPUT_EVDEV is not set
-# CONFIG_INPUT_EVBUG is not set
-
-#
-# Input I/O drivers
-#
-# CONFIG_GAMEPORT is not set
-CONFIG_SOUND_GAMEPORT=y
-# CONFIG_SERIO is not set
-
-#
-# Input Device Drivers
-#
-# CONFIG_INPUT_KEYBOARD is not set
-# CONFIG_INPUT_MOUSE is not set
-# CONFIG_INPUT_JOYSTICK is not set
-# CONFIG_INPUT_TOUCHSCREEN is not set
-# CONFIG_INPUT_MISC is not set
-
-#
-# Character devices
-#
-CONFIG_VT=y
-# CONFIG_VT_CONSOLE is not set
-CONFIG_HW_CONSOLE=y
-# CONFIG_SERIAL_NONSTANDARD is not set
-
-#
-# Serial drivers
-#
-CONFIG_SERIAL_8250=y
-CONFIG_SERIAL_8250_CONSOLE=y
-# CONFIG_SERIAL_8250_EXTENDED is not set
-
-#
-# Non-8250 serial port support
-#
-CONFIG_SERIAL_CORE=y
-CONFIG_SERIAL_CORE_CONSOLE=y
-CONFIG_UNIX98_PTYS=y
-CONFIG_UNIX98_PTY_COUNT=256
-
-#
-# I2C support
-#
-# CONFIG_I2C is not set
-
-#
-# I2C Hardware Sensors Mainboard support
-#
-
-#
-# I2C Hardware Sensors Chip support
-#
-# CONFIG_I2C_SENSOR is not set
-
-#
-# Mice
-#
-# CONFIG_BUSMOUSE is not set
-# CONFIG_QIC02_TAPE is not set
-
-#
-# IPMI
-#
-# CONFIG_IPMI_HANDLER is not set
-
-#
-# Watchdog Cards
-#
-# CONFIG_WATCHDOG is not set
-# CONFIG_NVRAM is not set
-# CONFIG_RTC is not set
-# CONFIG_GEN_RTC is not set
-# CONFIG_DTLK is not set
-# CONFIG_R3964 is not set
-# CONFIG_APPLICOM is not set
-
-#
-# Ftape, the floppy tape device driver
-#
-# CONFIG_FTAPE is not set
-# CONFIG_AGP is not set
-# CONFIG_DRM is not set
-# CONFIG_RAW_DRIVER is not set
-# CONFIG_HANGCHECK_TIMER is not set
-
-#
-# Multimedia devices
-#
-# CONFIG_VIDEO_DEV is not set
-
-#
-# Digital Video Broadcasting Devices
-#
-# CONFIG_DVB is not set
-
-#
-# File systems
-#
-CONFIG_EXT2_FS=y
-# CONFIG_EXT2_FS_XATTR is not set
-# CONFIG_EXT3_FS is not set
-# CONFIG_JBD is not set
-# CONFIG_REISERFS_FS is not set
-# CONFIG_JFS_FS is not set
-# CONFIG_XFS_FS is not set
-# CONFIG_MINIX_FS is not set
-CONFIG_ROMFS_FS=m
-# CONFIG_QUOTA is not set
-# CONFIG_AUTOFS_FS is not set
-CONFIG_AUTOFS4_FS=y
-
-#
-# CD-ROM/DVD Filesystems
-#
-CONFIG_ISO9660_FS=y
-CONFIG_JOLIET=y
-CONFIG_ZISOFS=y
-CONFIG_ZISOFS_FS=y
-# CONFIG_UDF_FS is not set
-
-#
-# DOS/FAT/NT Filesystems
-#
-CONFIG_FAT_FS=m
-CONFIG_MSDOS_FS=m
-CONFIG_VFAT_FS=m
-# CONFIG_NTFS_FS is not set
-
-#
-# Pseudo filesystems
-#
-CONFIG_PROC_FS=y
-# CONFIG_DEVFS_FS is not set
-CONFIG_DEVPTS_FS=y
-CONFIG_DEVPTS_FS_XATTR=y
-CONFIG_DEVPTS_FS_SECURITY=y
-CONFIG_TMPFS=y
-CONFIG_RAMFS=y
-
-#
-# Miscellaneous filesystems
-#
-# CONFIG_ADFS_FS is not set
-# CONFIG_AFFS_FS is not set
-# CONFIG_HFS_FS is not set
-# CONFIG_BEFS_FS is not set
-# CONFIG_BFS_FS is not set
-# CONFIG_EFS_FS is not set
-CONFIG_CRAMFS=m
-# CONFIG_VXFS_FS is not set
-# CONFIG_HPFS_FS is not set
-# CONFIG_QNX4FS_FS is not set
-# CONFIG_SYSV_FS is not set
-# CONFIG_UFS_FS is not set
-
-#
-# Network File Systems
-#
-CONFIG_NFS_FS=y
-CONFIG_NFS_V3=y
-# CONFIG_NFS_V4 is not set
-CONFIG_NFSD=m
-CONFIG_NFSD_V3=y
-# CONFIG_NFSD_V4 is not set
-# CONFIG_NFSD_TCP is not set
-CONFIG_ROOT_NFS=y
-CONFIG_LOCKD=y
-CONFIG_LOCKD_V4=y
-CONFIG_EXPORTFS=m
-CONFIG_SUNRPC=y
-# CONFIG_SUNRPC_GSS is not set
-CONFIG_SMB_FS=m
-CONFIG_SMB_NLS_DEFAULT=y
-CONFIG_SMB_NLS_REMOTE="cp932"
-# CONFIG_CIFS is not set
-# CONFIG_NCP_FS is not set
-# CONFIG_CODA_FS is not set
-# CONFIG_INTERMEZZO_FS is not set
-# CONFIG_AFS_FS is not set
-
-#
-# Partition Types
-#
-# CONFIG_PARTITION_ADVANCED is not set
-CONFIG_MSDOS_PARTITION=y
-CONFIG_SMB_NLS=y
-CONFIG_NLS=y
-
-#
-# Native Language Support
-#
-CONFIG_NLS_DEFAULT="iso8859-1"
-CONFIG_NLS_CODEPAGE_437=m
-# CONFIG_NLS_CODEPAGE_737 is not set
-# CONFIG_NLS_CODEPAGE_775 is not set
-# CONFIG_NLS_CODEPAGE_850 is not set
-# CONFIG_NLS_CODEPAGE_852 is not set
-# CONFIG_NLS_CODEPAGE_855 is not set
-# CONFIG_NLS_CODEPAGE_857 is not set
-# CONFIG_NLS_CODEPAGE_860 is not set
-# CONFIG_NLS_CODEPAGE_861 is not set
-# CONFIG_NLS_CODEPAGE_862 is not set
-# CONFIG_NLS_CODEPAGE_863 is not set
-# CONFIG_NLS_CODEPAGE_864 is not set
-# CONFIG_NLS_CODEPAGE_865 is not set
-# CONFIG_NLS_CODEPAGE_866 is not set
-# CONFIG_NLS_CODEPAGE_869 is not set
-# CONFIG_NLS_CODEPAGE_936 is not set
-# CONFIG_NLS_CODEPAGE_950 is not set
-CONFIG_NLS_CODEPAGE_932=m
-# CONFIG_NLS_CODEPAGE_949 is not set
-# CONFIG_NLS_CODEPAGE_874 is not set
-# CONFIG_NLS_ISO8859_8 is not set
-# CONFIG_NLS_CODEPAGE_1250 is not set
-# CONFIG_NLS_CODEPAGE_1251 is not set
-CONFIG_NLS_ISO8859_1=m
-# CONFIG_NLS_ISO8859_2 is not set
-# CONFIG_NLS_ISO8859_3 is not set
-# CONFIG_NLS_ISO8859_4 is not set
-# CONFIG_NLS_ISO8859_5 is not set
-# CONFIG_NLS_ISO8859_6 is not set
-# CONFIG_NLS_ISO8859_7 is not set
-# CONFIG_NLS_ISO8859_9 is not set
-# CONFIG_NLS_ISO8859_13 is not set
-# CONFIG_NLS_ISO8859_14 is not set
-# CONFIG_NLS_ISO8859_15 is not set
-# CONFIG_NLS_KOI8_R is not set
-# CONFIG_NLS_KOI8_U is not set
-# CONFIG_NLS_UTF8 is not set
-
-#
-# Graphics support
-#
-# CONFIG_FB_VIRTUAL is not set
-
-#
-# Console display driver support
-#
-# CONFIG_VGA_CONSOLE is not set
-# CONFIG_MDA_CONSOLE is not set
-CONFIG_DUMMY_CONSOLE=y
-# CONFIG_FRAMEBUFFER_CONSOLE is not set
-
-#
-# Logo configuration
-#
-# CONFIG_LOGO is not set
-
-#
-# Sound
-#
-CONFIG_SOUND=y
-
-#
-# Advanced Linux Sound Architecture
-#
-# CONFIG_SND is not set
-
-#
-# Open Sound System
-#
-# CONFIG_SOUND_PRIME is not set
-
-#
-# USB support
-#
-# CONFIG_USB_GADGET is not set
-
-#
-# Bluetooth support
-#
-# CONFIG_BT is not set
-
-#
-# Kernel hacking
-#
-CONFIG_CROSSCOMPILE=y
-# CONFIG_DEBUG_KERNEL is not set
-
-#
-# Security options
-#
-# CONFIG_SECURITY is not set
-
-#
-# Cryptographic options
-#
-# CONFIG_CRYPTO is not set
-
-#
-# Library routines
-#
-# CONFIG_CRC32 is not set
-CONFIG_ZLIB_INFLATE=y
-CONFIG_ZLIB_DEFLATE=m
--- diff/arch/mips/defconfig-tb0229	2003-08-20 14:16:25.000000000 +0100
+++ source/arch/mips/defconfig-tb0229	1970-01-01 01:00:00.000000000 +0100
@@ -1,662 +0,0 @@
-#
-# Automatically generated make config: don't edit
-#
-CONFIG_MIPS=y
-# CONFIG_MIPS64 is not set
-CONFIG_MIPS32=y
-
-#
-# Code maturity level options
-#
-CONFIG_EXPERIMENTAL=y
-
-#
-# General setup
-#
-CONFIG_SWAP=y
-CONFIG_SYSVIPC=y
-# CONFIG_BSD_PROCESS_ACCT is not set
-CONFIG_SYSCTL=y
-CONFIG_LOG_BUF_SHIFT=14
-# CONFIG_EMBEDDED is not set
-CONFIG_KALLSYMS=y
-CONFIG_FUTEX=y
-CONFIG_EPOLL=y
-CONFIG_IOSCHED_AS=y
-CONFIG_IOSCHED_DEADLINE=y
-
-#
-# Loadable module support
-#
-CONFIG_MODULES=y
-CONFIG_MODULE_UNLOAD=y
-# CONFIG_MODULE_FORCE_UNLOAD is not set
-CONFIG_OBSOLETE_MODPARM=y
-CONFIG_MODVERSIONS=y
-CONFIG_KMOD=y
-
-#
-# Machine selection
-#
-# CONFIG_ACER_PICA_61 is not set
-# CONFIG_BAGET_MIPS is not set
-# CONFIG_CASIO_E55 is not set
-# CONFIG_MIPS_COBALT is not set
-# CONFIG_DECSTATION is not set
-# CONFIG_MIPS_EV64120 is not set
-# CONFIG_MIPS_EV96100 is not set
-# CONFIG_MIPS_IVR is not set
-# CONFIG_LASAT is not set
-# CONFIG_HP_LASERJET is not set
-# CONFIG_IBM_WORKPAD is not set
-# CONFIG_MIPS_ITE8172 is not set
-# CONFIG_MIPS_ATLAS is not set
-# CONFIG_MIPS_MAGNUM_4000 is not set
-# CONFIG_MIPS_MALTA is not set
-# CONFIG_MIPS_SEAD is not set
-# CONFIG_MOMENCO_OCELOT is not set
-# CONFIG_MOMENCO_OCELOT_G is not set
-# CONFIG_MOMENCO_OCELOT_C is not set
-# CONFIG_DDB5074 is not set
-# CONFIG_DDB5476 is not set
-# CONFIG_DDB5477 is not set
-# CONFIG_NEC_OSPREY is not set
-# CONFIG_NEC_EAGLE is not set
-# CONFIG_OLIVETTI_M700 is not set
-# CONFIG_SGI_IP22 is not set
-# CONFIG_SGI_IP32 is not set
-# CONFIG_SOC_AU1X00 is not set
-# CONFIG_SIBYTE_SB1xxx_SOC is not set
-# CONFIG_SNI_RM200_PCI is not set
-# CONFIG_TANBAC_TB0226 is not set
-CONFIG_TANBAC_TB0229=y
-# CONFIG_TOSHIBA_JMR3927 is not set
-# CONFIG_TOSHIBA_RBTX4927 is not set
-# CONFIG_VICTOR_MPC30X is not set
-# CONFIG_ZAO_CAPCELLA is not set
-CONFIG_RWSEM_GENERIC_SPINLOCK=y
-CONFIG_NONCOHERENT_IO=y
-CONFIG_CPU_LITTLE_ENDIAN=y
-CONFIG_IRQ_CPU=y
-CONFIG_VR41XX_TIME_C=y
-CONFIG_DUMMY_KEYB=y
-CONFIG_VR41XX_COMMON=y
-CONFIG_NEW_PCI=y
-# CONFIG_FB is not set
-CONFIG_TANBAC_TB0219=y
-
-#
-# CPU selection
-#
-# CONFIG_CPU_MIPS32 is not set
-# CONFIG_CPU_MIPS64 is not set
-# CONFIG_CPU_R3000 is not set
-# CONFIG_CPU_TX39XX is not set
-CONFIG_CPU_VR41XX=y
-# CONFIG_CPU_R4300 is not set
-# CONFIG_CPU_R4X00 is not set
-# CONFIG_CPU_TX49XX is not set
-# CONFIG_CPU_R5000 is not set
-# CONFIG_CPU_R5432 is not set
-# CONFIG_CPU_R6000 is not set
-# CONFIG_CPU_NEVADA is not set
-# CONFIG_CPU_R8000 is not set
-# CONFIG_CPU_R10000 is not set
-# CONFIG_CPU_RM7000 is not set
-# CONFIG_CPU_SB1 is not set
-# CONFIG_CPU_ADVANCED is not set
-CONFIG_CPU_HAS_SYNC=y
-# CONFIG_PREEMPT is not set
-# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
-
-#
-# Bus options (PCI, PCMCIA, EISA, ISA, TC)
-#
-CONFIG_PCI=y
-CONFIG_PCI_LEGACY_PROC=y
-CONFIG_PCI_NAMES=y
-CONFIG_MMU=y
-# CONFIG_HOTPLUG is not set
-
-#
-# Executable file formats
-#
-CONFIG_KCORE_ELF=y
-CONFIG_BINFMT_ELF=y
-# CONFIG_BINFMT_MISC is not set
-CONFIG_TRAD_SIGNALS=y
-
-#
-# Memory Technology Devices (MTD)
-#
-# CONFIG_MTD is not set
-
-#
-# Parallel port support
-#
-# CONFIG_PARPORT is not set
-
-#
-# Plug and Play support
-#
-# CONFIG_PNP is not set
-
-#
-# Generic Driver Options
-#
-# CONFIG_FW_LOADER is not set
-
-#
-# Block devices
-#
-# CONFIG_BLK_DEV_FD is not set
-# CONFIG_BLK_CPQ_DA is not set
-# CONFIG_BLK_CPQ_CISS_DA is not set
-# CONFIG_BLK_DEV_DAC960 is not set
-# CONFIG_BLK_DEV_UMEM is not set
-CONFIG_BLK_DEV_LOOP=m
-# CONFIG_BLK_DEV_CRYPTOLOOP is not set
-CONFIG_BLK_DEV_NBD=m
-CONFIG_BLK_DEV_RAM=y
-CONFIG_BLK_DEV_RAM_SIZE=4096
-# CONFIG_BLK_DEV_INITRD is not set
-# CONFIG_LBD is not set
-
-#
-# ATA/ATAPI/MFM/RLL support
-#
-# CONFIG_IDE is not set
-
-#
-# SCSI device support
-#
-# CONFIG_SCSI is not set
-
-#
-# Multi-device support (RAID and LVM)
-#
-# CONFIG_MD is not set
-
-#
-# Fusion MPT device support
-#
-
-#
-# IEEE 1394 (FireWire) support (EXPERIMENTAL)
-#
-# CONFIG_IEEE1394 is not set
-
-#
-# I2O device support
-#
-# CONFIG_I2O is not set
-
-#
-# Networking support
-#
-CONFIG_NET=y
-
-#
-# Networking options
-#
-CONFIG_PACKET=y
-# CONFIG_PACKET_MMAP is not set
-CONFIG_NETLINK_DEV=m
-# CONFIG_NETFILTER is not set
-CONFIG_UNIX=y
-# CONFIG_NET_KEY is not set
-CONFIG_INET=y
-CONFIG_IP_MULTICAST=y
-CONFIG_IP_ADVANCED_ROUTER=y
-CONFIG_IP_MULTIPLE_TABLES=y
-CONFIG_IP_ROUTE_NAT=y
-CONFIG_IP_ROUTE_MULTIPATH=y
-CONFIG_IP_ROUTE_TOS=y
-CONFIG_IP_ROUTE_VERBOSE=y
-CONFIG_IP_PNP=y
-# CONFIG_IP_PNP_DHCP is not set
-CONFIG_IP_PNP_BOOTP=y
-# CONFIG_IP_PNP_RARP is not set
-CONFIG_NET_IPIP=m
-CONFIG_NET_IPGRE=m
-# CONFIG_NET_IPGRE_BROADCAST is not set
-# CONFIG_IP_MROUTE is not set
-# CONFIG_ARPD is not set
-# CONFIG_INET_ECN is not set
-CONFIG_SYN_COOKIES=y
-# CONFIG_INET_AH is not set
-# CONFIG_INET_ESP is not set
-# CONFIG_INET_IPCOMP is not set
-# CONFIG_IPV6 is not set
-# CONFIG_XFRM_USER is not set
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
-CONFIG_IPV6_SCTP__=y
-# CONFIG_IP_SCTP is not set
-# CONFIG_ATM is not set
-# CONFIG_VLAN_8021Q is not set
-# CONFIG_LLC is not set
-# CONFIG_DECNET is not set
-# CONFIG_BRIDGE is not set
-# CONFIG_X25 is not set
-# CONFIG_LAPB is not set
-# CONFIG_NET_DIVERT is not set
-# CONFIG_ECONET is not set
-# CONFIG_WAN_ROUTER is not set
-# CONFIG_NET_FASTROUTE is not set
-# CONFIG_NET_HW_FLOWCONTROL is not set
-
-#
-# QoS and/or fair queueing
-#
-# CONFIG_NET_SCHED is not set
-
-#
-# Network testing
-#
-# CONFIG_NET_PKTGEN is not set
-CONFIG_NETDEVICES=y
-
-#
-# ARCnet devices
-#
-# CONFIG_ARCNET is not set
-CONFIG_DUMMY=m
-# CONFIG_BONDING is not set
-# CONFIG_EQUALIZER is not set
-# CONFIG_TUN is not set
-# CONFIG_ETHERTAP is not set
-
-#
-# Ethernet (10 or 100Mbit)
-#
-CONFIG_NET_ETHERNET=y
-# CONFIG_MII is not set
-# CONFIG_HAPPYMEAL is not set
-# CONFIG_SUNGEM is not set
-# CONFIG_NET_VENDOR_3COM is not set
-
-#
-# Tulip family network device support
-#
-# CONFIG_NET_TULIP is not set
-# CONFIG_HP100 is not set
-# CONFIG_NET_PCI is not set
-
-#
-# Ethernet (1000 Mbit)
-#
-# CONFIG_ACENIC is not set
-# CONFIG_DL2K is not set
-# CONFIG_E1000 is not set
-# CONFIG_NS83820 is not set
-# CONFIG_HAMACHI is not set
-# CONFIG_YELLOWFIN is not set
-# CONFIG_R8169 is not set
-# CONFIG_SK98LIN is not set
-# CONFIG_TIGON3 is not set
-
-#
-# Ethernet (10000 Mbit)
-#
-# CONFIG_IXGB is not set
-# CONFIG_FDDI is not set
-# CONFIG_HIPPI is not set
-CONFIG_PPP=m
-CONFIG_PPP_MULTILINK=y
-CONFIG_PPP_FILTER=y
-CONFIG_PPP_ASYNC=m
-CONFIG_PPP_SYNC_TTY=m
-CONFIG_PPP_DEFLATE=m
-CONFIG_PPP_BSDCOMP=m
-CONFIG_PPPOE=m
-CONFIG_SLIP=m
-CONFIG_SLIP_COMPRESSED=y
-CONFIG_SLIP_SMART=y
-CONFIG_SLIP_MODE_SLIP6=y
-
-#
-# Wireless LAN (non-hamradio)
-#
-# CONFIG_NET_RADIO is not set
-
-#
-# Token Ring devices (depends on LLC=y)
-#
-# CONFIG_RCPCI is not set
-# CONFIG_SHAPER is not set
-
-#
-# Wan interfaces
-#
-# CONFIG_WAN is not set
-
-#
-# Amateur Radio support
-#
-# CONFIG_HAMRADIO is not set
-
-#
-# IrDA (infrared) support
-#
-# CONFIG_IRDA is not set
-
-#
-# ISDN subsystem
-#
-# CONFIG_ISDN_BOOL is not set
-
-#
-# Telephony Support
-#
-# CONFIG_PHONE is not set
-
-#
-# Input device support
-#
-CONFIG_INPUT=y
-
-#
-# Userland interfaces
-#
-CONFIG_INPUT_MOUSEDEV=m
-# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
-CONFIG_INPUT_MOUSEDEV_SCREEN_X=1280
-CONFIG_INPUT_MOUSEDEV_SCREEN_Y=1024
-# CONFIG_INPUT_JOYDEV is not set
-# CONFIG_INPUT_TSDEV is not set
-# CONFIG_INPUT_EVDEV is not set
-# CONFIG_INPUT_EVBUG is not set
-
-#
-# Input I/O drivers
-#
-# CONFIG_GAMEPORT is not set
-CONFIG_SOUND_GAMEPORT=y
-# CONFIG_SERIO is not set
-
-#
-# Input Device Drivers
-#
-# CONFIG_INPUT_KEYBOARD is not set
-# CONFIG_INPUT_MOUSE is not set
-# CONFIG_INPUT_JOYSTICK is not set
-# CONFIG_INPUT_TOUCHSCREEN is not set
-# CONFIG_INPUT_MISC is not set
-
-#
-# Character devices
-#
-CONFIG_VT=y
-# CONFIG_VT_CONSOLE is not set
-CONFIG_HW_CONSOLE=y
-# CONFIG_SERIAL_NONSTANDARD is not set
-
-#
-# Serial drivers
-#
-CONFIG_SERIAL_8250=y
-CONFIG_SERIAL_8250_CONSOLE=y
-# CONFIG_SERIAL_8250_EXTENDED is not set
-
-#
-# Non-8250 serial port support
-#
-CONFIG_SERIAL_CORE=y
-CONFIG_SERIAL_CORE_CONSOLE=y
-CONFIG_UNIX98_PTYS=y
-CONFIG_UNIX98_PTY_COUNT=256
-
-#
-# I2C support
-#
-# CONFIG_I2C is not set
-
-#
-# I2C Hardware Sensors Mainboard support
-#
-
-#
-# I2C Hardware Sensors Chip support
-#
-# CONFIG_I2C_SENSOR is not set
-
-#
-# Mice
-#
-# CONFIG_BUSMOUSE is not set
-# CONFIG_QIC02_TAPE is not set
-
-#
-# IPMI
-#
-# CONFIG_IPMI_HANDLER is not set
-
-#
-# Watchdog Cards
-#
-# CONFIG_WATCHDOG is not set
-# CONFIG_NVRAM is not set
-# CONFIG_RTC is not set
-# CONFIG_GEN_RTC is not set
-# CONFIG_DTLK is not set
-# CONFIG_R3964 is not set
-# CONFIG_APPLICOM is not set
-
-#
-# Ftape, the floppy tape device driver
-#
-# CONFIG_FTAPE is not set
-# CONFIG_AGP is not set
-# CONFIG_DRM is not set
-# CONFIG_RAW_DRIVER is not set
-# CONFIG_HANGCHECK_TIMER is not set
-
-#
-# Multimedia devices
-#
-# CONFIG_VIDEO_DEV is not set
-
-#
-# Digital Video Broadcasting Devices
-#
-# CONFIG_DVB is not set
-
-#
-# File systems
-#
-CONFIG_EXT2_FS=y
-# CONFIG_EXT2_FS_XATTR is not set
-CONFIG_EXT3_FS=m
-CONFIG_EXT3_FS_XATTR=y
-# CONFIG_EXT3_FS_POSIX_ACL is not set
-CONFIG_EXT3_FS_SECURITY=y
-CONFIG_JBD=m
-# CONFIG_JBD_DEBUG is not set
-CONFIG_FS_MBCACHE=y
-# CONFIG_REISERFS_FS is not set
-CONFIG_JFS_FS=m
-# CONFIG_JFS_POSIX_ACL is not set
-# CONFIG_JFS_DEBUG is not set
-# CONFIG_JFS_STATISTICS is not set
-CONFIG_XFS_FS=y
-# CONFIG_XFS_RT is not set
-CONFIG_XFS_QUOTA=y
-CONFIG_XFS_POSIX_ACL=y
-# CONFIG_MINIX_FS is not set
-CONFIG_ROMFS_FS=m
-# CONFIG_QUOTA is not set
-CONFIG_QUOTACTL=y
-# CONFIG_AUTOFS_FS is not set
-CONFIG_AUTOFS4_FS=y
-
-#
-# CD-ROM/DVD Filesystems
-#
-CONFIG_ISO9660_FS=y
-CONFIG_JOLIET=y
-CONFIG_ZISOFS=y
-CONFIG_ZISOFS_FS=y
-# CONFIG_UDF_FS is not set
-
-#
-# DOS/FAT/NT Filesystems
-#
-CONFIG_FAT_FS=m
-CONFIG_MSDOS_FS=m
-CONFIG_VFAT_FS=m
-# CONFIG_NTFS_FS is not set
-
-#
-# Pseudo filesystems
-#
-CONFIG_PROC_FS=y
-# CONFIG_DEVFS_FS is not set
-CONFIG_DEVPTS_FS=y
-CONFIG_DEVPTS_FS_XATTR=y
-CONFIG_DEVPTS_FS_SECURITY=y
-CONFIG_TMPFS=y
-CONFIG_RAMFS=y
-
-#
-# Miscellaneous filesystems
-#
-# CONFIG_ADFS_FS is not set
-# CONFIG_AFFS_FS is not set
-# CONFIG_HFS_FS is not set
-# CONFIG_BEFS_FS is not set
-# CONFIG_BFS_FS is not set
-# CONFIG_EFS_FS is not set
-CONFIG_CRAMFS=m
-# CONFIG_VXFS_FS is not set
-# CONFIG_HPFS_FS is not set
-# CONFIG_QNX4FS_FS is not set
-# CONFIG_SYSV_FS is not set
-# CONFIG_UFS_FS is not set
-
-#
-# Network File Systems
-#
-CONFIG_NFS_FS=y
-CONFIG_NFS_V3=y
-# CONFIG_NFS_V4 is not set
-CONFIG_NFSD=y
-CONFIG_NFSD_V3=y
-# CONFIG_NFSD_V4 is not set
-CONFIG_NFSD_TCP=y
-CONFIG_ROOT_NFS=y
-CONFIG_LOCKD=y
-CONFIG_LOCKD_V4=y
-CONFIG_EXPORTFS=y
-CONFIG_SUNRPC=y
-# CONFIG_SUNRPC_GSS is not set
-CONFIG_SMB_FS=m
-CONFIG_SMB_NLS_DEFAULT=y
-CONFIG_SMB_NLS_REMOTE="cp932"
-# CONFIG_CIFS is not set
-# CONFIG_NCP_FS is not set
-# CONFIG_CODA_FS is not set
-# CONFIG_INTERMEZZO_FS is not set
-# CONFIG_AFS_FS is not set
-
-#
-# Partition Types
-#
-# CONFIG_PARTITION_ADVANCED is not set
-CONFIG_MSDOS_PARTITION=y
-CONFIG_SMB_NLS=y
-CONFIG_NLS=y
-
-#
-# Native Language Support
-#
-CONFIG_NLS_DEFAULT="iso8859-1"
-CONFIG_NLS_CODEPAGE_437=m
-# CONFIG_NLS_CODEPAGE_737 is not set
-# CONFIG_NLS_CODEPAGE_775 is not set
-# CONFIG_NLS_CODEPAGE_850 is not set
-# CONFIG_NLS_CODEPAGE_852 is not set
-# CONFIG_NLS_CODEPAGE_855 is not set
-# CONFIG_NLS_CODEPAGE_857 is not set
-# CONFIG_NLS_CODEPAGE_860 is not set
-# CONFIG_NLS_CODEPAGE_861 is not set
-# CONFIG_NLS_CODEPAGE_862 is not set
-# CONFIG_NLS_CODEPAGE_863 is not set
-# CONFIG_NLS_CODEPAGE_864 is not set
-# CONFIG_NLS_CODEPAGE_865 is not set
-# CONFIG_NLS_CODEPAGE_866 is not set
-# CONFIG_NLS_CODEPAGE_869 is not set
-# CONFIG_NLS_CODEPAGE_936 is not set
-# CONFIG_NLS_CODEPAGE_950 is not set
-CONFIG_NLS_CODEPAGE_932=m
-# CONFIG_NLS_CODEPAGE_949 is not set
-# CONFIG_NLS_CODEPAGE_874 is not set
-# CONFIG_NLS_ISO8859_8 is not set
-# CONFIG_NLS_CODEPAGE_1250 is not set
-# CONFIG_NLS_CODEPAGE_1251 is not set
-CONFIG_NLS_ISO8859_1=m
-# CONFIG_NLS_ISO8859_2 is not set
-# CONFIG_NLS_ISO8859_3 is not set
-# CONFIG_NLS_ISO8859_4 is not set
-# CONFIG_NLS_ISO8859_5 is not set
-# CONFIG_NLS_ISO8859_6 is not set
-# CONFIG_NLS_ISO8859_7 is not set
-# CONFIG_NLS_ISO8859_9 is not set
-# CONFIG_NLS_ISO8859_13 is not set
-# CONFIG_NLS_ISO8859_14 is not set
-# CONFIG_NLS_ISO8859_15 is not set
-# CONFIG_NLS_KOI8_R is not set
-# CONFIG_NLS_KOI8_U is not set
-# CONFIG_NLS_UTF8 is not set
-
-#
-# Graphics support
-#
-
-#
-# Console display driver support
-#
-# CONFIG_VGA_CONSOLE is not set
-# CONFIG_MDA_CONSOLE is not set
-CONFIG_DUMMY_CONSOLE=y
-
-#
-# Sound
-#
-# CONFIG_SOUND is not set
-
-#
-# USB support
-#
-# CONFIG_USB is not set
-# CONFIG_USB_GADGET is not set
-
-#
-# Bluetooth support
-#
-# CONFIG_BT is not set
-
-#
-# Kernel hacking
-#
-CONFIG_CROSSCOMPILE=y
-# CONFIG_DEBUG_KERNEL is not set
-
-#
-# Security options
-#
-# CONFIG_SECURITY is not set
-
-#
-# Cryptographic options
-#
-# CONFIG_CRYPTO is not set
-
-#
-# Library routines
-#
-# CONFIG_CRC32 is not set
-CONFIG_ZLIB_INFLATE=y
-CONFIG_ZLIB_DEFLATE=m
--- diff/arch/mips/defconfig-workpad	2003-08-20 14:16:25.000000000 +0100
+++ source/arch/mips/defconfig-workpad	1970-01-01 01:00:00.000000000 +0100
@@ -1,572 +0,0 @@
-#
-# Automatically generated make config: don't edit
-#
-CONFIG_MIPS=y
-# CONFIG_MIPS64 is not set
-CONFIG_MIPS32=y
-
-#
-# Code maturity level options
-#
-CONFIG_EXPERIMENTAL=y
-
-#
-# General setup
-#
-CONFIG_SWAP=y
-CONFIG_SYSVIPC=y
-# CONFIG_BSD_PROCESS_ACCT is not set
-CONFIG_SYSCTL=y
-CONFIG_LOG_BUF_SHIFT=14
-# CONFIG_EMBEDDED is not set
-CONFIG_KALLSYMS=y
-CONFIG_FUTEX=y
-CONFIG_EPOLL=y
-CONFIG_IOSCHED_AS=y
-CONFIG_IOSCHED_DEADLINE=y
-
-#
-# Loadable module support
-#
-CONFIG_MODULES=y
-CONFIG_MODULE_UNLOAD=y
-# CONFIG_MODULE_FORCE_UNLOAD is not set
-CONFIG_OBSOLETE_MODPARM=y
-CONFIG_MODVERSIONS=y
-CONFIG_KMOD=y
-
-#
-# Machine selection
-#
-# CONFIG_ACER_PICA_61 is not set
-# CONFIG_BAGET_MIPS is not set
-# CONFIG_CASIO_E55 is not set
-# CONFIG_MIPS_COBALT is not set
-# CONFIG_DECSTATION is not set
-# CONFIG_MIPS_EV64120 is not set
-# CONFIG_MIPS_EV96100 is not set
-# CONFIG_MIPS_IVR is not set
-# CONFIG_LASAT is not set
-# CONFIG_HP_LASERJET is not set
-CONFIG_IBM_WORKPAD=y
-# CONFIG_MIPS_ITE8172 is not set
-# CONFIG_MIPS_ATLAS is not set
-# CONFIG_MIPS_MAGNUM_4000 is not set
-# CONFIG_MIPS_MALTA is not set
-# CONFIG_MIPS_SEAD is not set
-# CONFIG_MOMENCO_OCELOT is not set
-# CONFIG_MOMENCO_OCELOT_G is not set
-# CONFIG_MOMENCO_OCELOT_C is not set
-# CONFIG_DDB5074 is not set
-# CONFIG_DDB5476 is not set
-# CONFIG_DDB5477 is not set
-# CONFIG_NEC_OSPREY is not set
-# CONFIG_NEC_EAGLE is not set
-# CONFIG_OLIVETTI_M700 is not set
-# CONFIG_SGI_IP22 is not set
-# CONFIG_SGI_IP32 is not set
-# CONFIG_SOC_AU1X00 is not set
-# CONFIG_SIBYTE_SB1xxx_SOC is not set
-# CONFIG_SNI_RM200_PCI is not set
-# CONFIG_TANBAC_TB0226 is not set
-# CONFIG_TANBAC_TB0229 is not set
-# CONFIG_TOSHIBA_JMR3927 is not set
-# CONFIG_TOSHIBA_RBTX4927 is not set
-# CONFIG_VICTOR_MPC30X is not set
-# CONFIG_ZAO_CAPCELLA is not set
-CONFIG_RWSEM_GENERIC_SPINLOCK=y
-CONFIG_NONCOHERENT_IO=y
-CONFIG_CPU_LITTLE_ENDIAN=y
-CONFIG_IRQ_CPU=y
-CONFIG_VR41XX_TIME_C=y
-CONFIG_DUMMY_KEYB=y
-CONFIG_VR41XX_COMMON=y
-# CONFIG_FB is not set
-
-#
-# CPU selection
-#
-# CONFIG_CPU_MIPS32 is not set
-# CONFIG_CPU_MIPS64 is not set
-# CONFIG_CPU_R3000 is not set
-# CONFIG_CPU_TX39XX is not set
-CONFIG_CPU_VR41XX=y
-# CONFIG_CPU_R4300 is not set
-# CONFIG_CPU_R4X00 is not set
-# CONFIG_CPU_TX49XX is not set
-# CONFIG_CPU_R5000 is not set
-# CONFIG_CPU_R5432 is not set
-# CONFIG_CPU_R6000 is not set
-# CONFIG_CPU_NEVADA is not set
-# CONFIG_CPU_R8000 is not set
-# CONFIG_CPU_R10000 is not set
-# CONFIG_CPU_RM7000 is not set
-# CONFIG_CPU_SB1 is not set
-# CONFIG_CPU_ADVANCED is not set
-CONFIG_CPU_HAS_SYNC=y
-# CONFIG_PREEMPT is not set
-# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
-
-#
-# Bus options (PCI, PCMCIA, EISA, ISA, TC)
-#
-CONFIG_MMU=y
-# CONFIG_HOTPLUG is not set
-
-#
-# Executable file formats
-#
-CONFIG_KCORE_ELF=y
-CONFIG_BINFMT_ELF=y
-# CONFIG_BINFMT_MISC is not set
-CONFIG_TRAD_SIGNALS=y
-
-#
-# Memory Technology Devices (MTD)
-#
-# CONFIG_MTD is not set
-
-#
-# Parallel port support
-#
-# CONFIG_PARPORT is not set
-
-#
-# Plug and Play support
-#
-# CONFIG_PNP is not set
-
-#
-# Generic Driver Options
-#
-# CONFIG_FW_LOADER is not set
-
-#
-# Block devices
-#
-# CONFIG_BLK_DEV_FD is not set
-# CONFIG_BLK_DEV_LOOP is not set
-# CONFIG_BLK_DEV_NBD is not set
-# CONFIG_BLK_DEV_RAM is not set
-# CONFIG_BLK_DEV_INITRD is not set
-# CONFIG_LBD is not set
-
-#
-# ATA/ATAPI/MFM/RLL support
-#
-CONFIG_IDE=y
-
-#
-# IDE, ATA and ATAPI Block devices
-#
-CONFIG_BLK_DEV_IDE=y
-
-#
-# Please see Documentation/ide.txt for help/info on IDE drives
-#
-# CONFIG_BLK_DEV_HD is not set
-CONFIG_BLK_DEV_IDEDISK=y
-# CONFIG_IDEDISK_MULTI_MODE is not set
-# CONFIG_IDEDISK_STROKE is not set
-# CONFIG_BLK_DEV_IDECD is not set
-# CONFIG_BLK_DEV_IDEFLOPPY is not set
-# CONFIG_IDE_TASK_IOCTL is not set
-CONFIG_IDE_TASKFILE_IO=y
-
-#
-# IDE chipset support/bugfixes
-#
-
-#
-# SCSI device support
-#
-# CONFIG_SCSI is not set
-
-#
-# Multi-device support (RAID and LVM)
-#
-# CONFIG_MD is not set
-
-#
-# Fusion MPT device support
-#
-
-#
-# I2O device support
-#
-
-#
-# Networking support
-#
-CONFIG_NET=y
-
-#
-# Networking options
-#
-CONFIG_PACKET=y
-CONFIG_PACKET_MMAP=y
-CONFIG_NETLINK_DEV=y
-# CONFIG_NETFILTER is not set
-CONFIG_UNIX=y
-CONFIG_NET_KEY=y
-CONFIG_INET=y
-CONFIG_IP_MULTICAST=y
-# CONFIG_IP_ADVANCED_ROUTER is not set
-# CONFIG_IP_PNP is not set
-# CONFIG_NET_IPIP is not set
-# CONFIG_NET_IPGRE is not set
-# CONFIG_IP_MROUTE is not set
-# CONFIG_ARPD is not set
-# CONFIG_INET_ECN is not set
-# CONFIG_SYN_COOKIES is not set
-# CONFIG_INET_AH is not set
-# CONFIG_INET_ESP is not set
-# CONFIG_INET_IPCOMP is not set
-# CONFIG_IPV6 is not set
-# CONFIG_XFRM_USER is not set
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
-CONFIG_IPV6_SCTP__=y
-# CONFIG_IP_SCTP is not set
-# CONFIG_ATM is not set
-# CONFIG_VLAN_8021Q is not set
-# CONFIG_LLC is not set
-# CONFIG_DECNET is not set
-# CONFIG_BRIDGE is not set
-# CONFIG_X25 is not set
-# CONFIG_LAPB is not set
-# CONFIG_NET_DIVERT is not set
-# CONFIG_ECONET is not set
-# CONFIG_WAN_ROUTER is not set
-# CONFIG_NET_FASTROUTE is not set
-# CONFIG_NET_HW_FLOWCONTROL is not set
-
-#
-# QoS and/or fair queueing
-#
-# CONFIG_NET_SCHED is not set
-
-#
-# Network testing
-#
-# CONFIG_NET_PKTGEN is not set
-CONFIG_NETDEVICES=y
-# CONFIG_DUMMY is not set
-# CONFIG_BONDING is not set
-# CONFIG_EQUALIZER is not set
-# CONFIG_TUN is not set
-# CONFIG_ETHERTAP is not set
-
-#
-# Ethernet (10 or 100Mbit)
-#
-CONFIG_NET_ETHERNET=y
-# CONFIG_MII is not set
-
-#
-# Ethernet (1000 Mbit)
-#
-
-#
-# Ethernet (10000 Mbit)
-#
-# CONFIG_PPP is not set
-# CONFIG_SLIP is not set
-
-#
-# Wireless LAN (non-hamradio)
-#
-# CONFIG_NET_RADIO is not set
-
-#
-# Token Ring devices (depends on LLC=y)
-#
-# CONFIG_SHAPER is not set
-
-#
-# Wan interfaces
-#
-# CONFIG_WAN is not set
-
-#
-# Amateur Radio support
-#
-# CONFIG_HAMRADIO is not set
-
-#
-# IrDA (infrared) support
-#
-# CONFIG_IRDA is not set
-
-#
-# ISDN subsystem
-#
-# CONFIG_ISDN_BOOL is not set
-
-#
-# Telephony Support
-#
-# CONFIG_PHONE is not set
-
-#
-# Input device support
-#
-CONFIG_INPUT=y
-
-#
-# Userland interfaces
-#
-# CONFIG_INPUT_MOUSEDEV is not set
-# CONFIG_INPUT_JOYDEV is not set
-# CONFIG_INPUT_TSDEV is not set
-# CONFIG_INPUT_EVDEV is not set
-# CONFIG_INPUT_EVBUG is not set
-
-#
-# Input I/O drivers
-#
-# CONFIG_GAMEPORT is not set
-CONFIG_SOUND_GAMEPORT=y
-# CONFIG_SERIO is not set
-
-#
-# Input Device Drivers
-#
-# CONFIG_INPUT_KEYBOARD is not set
-# CONFIG_INPUT_MOUSE is not set
-# CONFIG_INPUT_JOYSTICK is not set
-# CONFIG_INPUT_TOUCHSCREEN is not set
-# CONFIG_INPUT_MISC is not set
-
-#
-# Character devices
-#
-CONFIG_VT=y
-# CONFIG_VT_CONSOLE is not set
-CONFIG_HW_CONSOLE=y
-# CONFIG_SERIAL_NONSTANDARD is not set
-
-#
-# Serial drivers
-#
-CONFIG_SERIAL_8250=y
-CONFIG_SERIAL_8250_CONSOLE=y
-# CONFIG_SERIAL_8250_EXTENDED is not set
-
-#
-# Non-8250 serial port support
-#
-CONFIG_SERIAL_CORE=y
-CONFIG_SERIAL_CORE_CONSOLE=y
-CONFIG_UNIX98_PTYS=y
-CONFIG_UNIX98_PTY_COUNT=256
-
-#
-# I2C support
-#
-# CONFIG_I2C is not set
-
-#
-# I2C Hardware Sensors Mainboard support
-#
-
-#
-# I2C Hardware Sensors Chip support
-#
-# CONFIG_I2C_SENSOR is not set
-
-#
-# Mice
-#
-# CONFIG_BUSMOUSE is not set
-# CONFIG_QIC02_TAPE is not set
-
-#
-# IPMI
-#
-# CONFIG_IPMI_HANDLER is not set
-
-#
-# Watchdog Cards
-#
-CONFIG_WATCHDOG=y
-# CONFIG_WATCHDOG_NOWAYOUT is not set
-# CONFIG_SOFT_WATCHDOG is not set
-# CONFIG_WDT is not set
-# CONFIG_WDTPCI is not set
-# CONFIG_PCWATCHDOG is not set
-# CONFIG_ACQUIRE_WDT is not set
-# CONFIG_ADVANTECH_WDT is not set
-# CONFIG_EUROTECH_WDT is not set
-# CONFIG_IB700_WDT is not set
-# CONFIG_I810_TCO is not set
-# CONFIG_MIXCOMWD is not set
-# CONFIG_SCx200_WDT is not set
-# CONFIG_60XX_WDT is not set
-# CONFIG_W83877F_WDT is not set
-# CONFIG_MACHZ_WDT is not set
-# CONFIG_SC520_WDT is not set
-# CONFIG_AMD7XX_TCO is not set
-# CONFIG_ALIM7101_WDT is not set
-# CONFIG_SC1200_WDT is not set
-# CONFIG_WAFER_WDT is not set
-# CONFIG_CPU5_WDT is not set
-# CONFIG_NVRAM is not set
-# CONFIG_RTC is not set
-# CONFIG_GEN_RTC is not set
-# CONFIG_DTLK is not set
-# CONFIG_R3964 is not set
-# CONFIG_APPLICOM is not set
-
-#
-# Ftape, the floppy tape device driver
-#
-# CONFIG_FTAPE is not set
-# CONFIG_AGP is not set
-# CONFIG_DRM is not set
-# CONFIG_RAW_DRIVER is not set
-# CONFIG_HANGCHECK_TIMER is not set
-
-#
-# Multimedia devices
-#
-# CONFIG_VIDEO_DEV is not set
-
-#
-# Digital Video Broadcasting Devices
-#
-# CONFIG_DVB is not set
-
-#
-# File systems
-#
-CONFIG_EXT2_FS=y
-CONFIG_EXT2_FS_XATTR=y
-CONFIG_EXT2_FS_POSIX_ACL=y
-CONFIG_EXT2_FS_SECURITY=y
-# CONFIG_EXT3_FS is not set
-# CONFIG_JBD is not set
-CONFIG_FS_MBCACHE=y
-# CONFIG_REISERFS_FS is not set
-# CONFIG_JFS_FS is not set
-CONFIG_FS_POSIX_ACL=y
-# CONFIG_XFS_FS is not set
-# CONFIG_MINIX_FS is not set
-# CONFIG_ROMFS_FS is not set
-# CONFIG_QUOTA is not set
-CONFIG_AUTOFS_FS=y
-CONFIG_AUTOFS4_FS=y
-
-#
-# CD-ROM/DVD Filesystems
-#
-# CONFIG_ISO9660_FS is not set
-# CONFIG_UDF_FS is not set
-
-#
-# DOS/FAT/NT Filesystems
-#
-# CONFIG_FAT_FS is not set
-# CONFIG_NTFS_FS is not set
-
-#
-# Pseudo filesystems
-#
-CONFIG_PROC_FS=y
-# CONFIG_DEVFS_FS is not set
-CONFIG_DEVPTS_FS=y
-CONFIG_DEVPTS_FS_XATTR=y
-CONFIG_DEVPTS_FS_SECURITY=y
-# CONFIG_TMPFS is not set
-CONFIG_RAMFS=y
-
-#
-# Miscellaneous filesystems
-#
-# CONFIG_ADFS_FS is not set
-# CONFIG_AFFS_FS is not set
-# CONFIG_HFS_FS is not set
-# CONFIG_BEFS_FS is not set
-# CONFIG_BFS_FS is not set
-# CONFIG_EFS_FS is not set
-# CONFIG_CRAMFS is not set
-# CONFIG_VXFS_FS is not set
-# CONFIG_HPFS_FS is not set
-# CONFIG_QNX4FS_FS is not set
-# CONFIG_SYSV_FS is not set
-# CONFIG_UFS_FS is not set
-
-#
-# Network File Systems
-#
-CONFIG_NFS_FS=y
-# CONFIG_NFS_V3 is not set
-# CONFIG_NFS_V4 is not set
-CONFIG_NFSD=y
-# CONFIG_NFSD_V3 is not set
-# CONFIG_NFSD_TCP is not set
-CONFIG_LOCKD=y
-CONFIG_EXPORTFS=y
-CONFIG_SUNRPC=y
-# CONFIG_SUNRPC_GSS is not set
-# CONFIG_SMB_FS is not set
-# CONFIG_CIFS is not set
-# CONFIG_NCP_FS is not set
-# CONFIG_CODA_FS is not set
-# CONFIG_INTERMEZZO_FS is not set
-# CONFIG_AFS_FS is not set
-
-#
-# Partition Types
-#
-# CONFIG_PARTITION_ADVANCED is not set
-CONFIG_MSDOS_PARTITION=y
-
-#
-# Graphics support
-#
-
-#
-# Console display driver support
-#
-# CONFIG_VGA_CONSOLE is not set
-# CONFIG_MDA_CONSOLE is not set
-CONFIG_DUMMY_CONSOLE=y
-
-#
-# Sound
-#
-# CONFIG_SOUND is not set
-
-#
-# USB support
-#
-# CONFIG_USB_GADGET is not set
-
-#
-# Bluetooth support
-#
-# CONFIG_BT is not set
-
-#
-# Kernel hacking
-#
-CONFIG_CROSSCOMPILE=y
-# CONFIG_DEBUG_KERNEL is not set
-
-#
-# Security options
-#
-# CONFIG_SECURITY is not set
-
-#
-# Cryptographic options
-#
-# CONFIG_CRYPTO is not set
-
-#
-# Library routines
-#
-# CONFIG_CRC32 is not set
--- diff/arch/mips/galileo-boards/ev64120/Makefile	2003-07-08 09:55:17.000000000 +0100
+++ source/arch/mips/galileo-boards/ev64120/Makefile	1970-01-01 01:00:00.000000000 +0100
@@ -1,12 +0,0 @@
-#
-#  Copyright 2000 RidgeRun, Inc.
-#  Author: RidgeRun, Inc.
-#     	glonnon@ridgerun.com, skranz@ridgerun.com, stevej@ridgerun.com
-#
-# Makefile for the Galileo EV64120 board.
-#
-
-obj-y		:= serialGT.o int-handler.o promcon.o reset.o setup.o irq.o \
-		   irq-handler.o
-
-EXTRA_AFLAGS := $(CFLAGS)
--- diff/arch/mips/galileo-boards/ev64120/README	2003-07-08 09:55:17.000000000 +0100
+++ source/arch/mips/galileo-boards/ev64120/README	1970-01-01 01:00:00.000000000 +0100
@@ -1,2 +0,0 @@
-The compressed boot code was such a mess I deleted it.  Feel free to
-reimplement it -- Ralf
--- diff/arch/mips/galileo-boards/ev64120/dma.c	2003-07-08 09:55:17.000000000 +0100
+++ source/arch/mips/galileo-boards/ev64120/dma.c	1970-01-01 01:00:00.000000000 +0100
@@ -1,168 +0,0 @@
-/* DMA.C - DMA functions and definitions */
-
-/* Copyright Galileo Technology. */
-
-/*
-DESCRIPTION
-This file gives the user a complete interface to the powerful DMA engines,
-including functions for controling the priority mechanism.
-To fully understand the capabilities of the DMA engines please spare some
-time to go trough the spec.
-*/
-
-/* includes */
-
-#ifdef __linux__
-#include <asm/galileo/evb64120A/core.h>
-#include <asm/galileo/evb64120A/dma.h>
-#else
-#include "Core.h"
-#include "DMA.h"
-#endif
-/********************************************************************
-* dmaCommand - Write a command to a DMA channel
-*
-* Inputs: DMA_ENGINE channel - choosing one of the four engine.
-*         unsigned int command - The command to be written to the control register.
-* Returns: false if one of the parameters is erroneous else returns true.
-*********************************************************************/
-
-bool dmaCommand(DMA_ENGINE channel, unsigned int command)
-{
-	if (channel > LAST_DMA_ENGINE)
-		return false;
-	GT_REG_WRITE(CHANNEL0CONTROL + channel * 4, command);
-	return true;
-}
-
-/********************************************************************
-* dmaTransfer - transfer data from sourceAddr to destAddr on DMA channel
-* Inputs:
-*   DMA_RECORED *nextRecoredPointer: If we are using chain mode DMA transfer,
-*   then this pointer should point to the next recored,otherwise it should be
-*   NULL.
-*   VERY IMPORTANT !!! When using chain mode, the records must be 16 Bytes
-*   aligned, the function will take care of that for you, but you need to
-*   allocate one more record for that, meaning: if you are having 3 records ,
-*   declare 4 (see the example bellow) and start using the second one.
-*   Example:
-*   Performing a chain mode DMA transfer(Copy a 1/4 mega of data using
-*   chain mode DMA):
-*    DMA_RECORED dmaRecoredArray[4];
-*    dmaRecoredArray[1].ByteCnt = _64KB;
-*    dmaRecoredArray[1].DestAdd = destAddress + _64KB;
-*    dmaRecoredArray[1].SrcAdd  = sourceAddress + _64KB;
-*    dmaRecoredArray[1].NextRecPtr = &dmaRecoredArray[2];
-*    dmaRecoredArray[2].ByteCnt = _64KB;
-*    dmaRecoredArray[2].DestAdd = destAddress + 2*_64KB;
-*    dmaRecoredArray[2].SrcAdd  = sourceAddress + 2*_64KB;
-*    dmaRecoredArray[2].NextRecPtr = &dmaRecoredArray[3];
-*    dmaRecoredArray[3].ByteCnt = _64KB;
-*    dmaRecoredArray[3].DestAdd = destAddress + 3*_64KB;
-*    dmaRecoredArray[3].SrcAdd  = sourceAddress + 3*_64KB;
-*    dmaRecoredArray[3].NextRecPtr = NULL;
-*    performCmDma(0,sourceAddress,destAddress,_64KB,PLAIN,WAIT_TO_END,
-*                            &dmaRecoredArray[1]);
-* Returns: NO_SUCH_CHANNEL if channel does not exist, CHANNEL_BUSY if channel
-*          is active and true if the transfer ended successfully
-*********************************************************************/
-
-DMA_STATUS dmaTransfer(DMA_ENGINE channel, unsigned int sourceAddr,
-		       unsigned int destAddr, unsigned int numOfBytes,
-		       unsigned int command,
-		       DMA_RECORED * nextRecoredPointer)
-{
-	unsigned int tempData, checkBits, alignmentOffset = 0;
-	DMA_RECORED *next = nextRecoredPointer;
-
-	if (channel > LAST_DMA_ENGINE)
-		return NO_SUCH_CHANNEL;
-	if (numOfBytes > 0xffff)
-		return GENERAL_ERROR;
-	if (isDmaChannelActive(channel))
-		return CHANNEL_BUSY;
-	if (next != NULL) {	/* case of chain Mode */
-		alignmentOffset = ((unsigned int) next % 16);
-	}
-	checkBits = command & 0x6000000;
-	if (checkBits == 0) {
-		while (next != NULL) {
-			WRITE_WORD((unsigned int) next - alignmentOffset,
-				   next->ByteCnt);
-			tempData = (unsigned int) next->SrcAdd;
-			WRITE_WORD((unsigned int) next + 4 -
-				   alignmentOffset, tempData & 0x5fffffff);
-			tempData = (unsigned int) next->DestAdd;
-			WRITE_WORD((unsigned int) next + 8 -
-				   alignmentOffset, tempData & 0x5fffffff);
-			tempData = (unsigned int) next->NextRecPtr;
-			WRITE_WORD((unsigned int) next + 12 -
-				   alignmentOffset,
-				   tempData & 0x5fffffff -
-				   alignmentOffset);
-			next = (DMA_RECORED *) tempData;
-			if (next == nextRecoredPointer)
-				next = NULL;
-		}
-	}
-	GT_REG_WRITE(CHANNEL0_DMA_BYTE_COUNT + channel * 4, numOfBytes);
-	tempData = sourceAddr;
-	GT_REG_WRITE(CHANNEL0_DMA_SOURCE_ADDRESS + channel * 4,
-		     tempData & 0x5fffffff);
-	tempData = destAddr;
-	GT_REG_WRITE(CHANNEL0_DMA_DESTINATION_ADDRESS + channel * 4,
-		     tempData & 0x5fffffff);
-	if (nextRecoredPointer != NULL) {
-		tempData =
-		    (unsigned int) nextRecoredPointer - alignmentOffset;
-		GT_REG_WRITE(CHANNEL0NEXT_RECORD_POINTER + 4 * channel,
-			     tempData & 0x5fffffff);
-		command = command | CHANNEL_ENABLE;
-	} else {
-		command = command | CHANNEL_ENABLE | NON_CHAIN_MOD;
-	}
-	/* Activate DMA engine By writting to dmaControlRegister */
-	GT_REG_WRITE(CHANNEL0CONTROL + channel * 4, command);
-
-	return DMA_OK;
-}
-
-/********************************************************************
-* isDmaChannelActive - check if channel is busy
-*
-* Inputs: channel number
-* RETURNS: True if the channel is busy, false otherwise.
-*********************************************************************/
-
-bool isDmaChannelActive(DMA_ENGINE channel)
-{
-	unsigned int data;
-
-	if (channel > LAST_DMA_ENGINE)
-		return false;
-	GT_REG_READ(CHANNEL0CONTROL + 4 * channel, &data);
-	if (data & DMA_ACTIVITY_STATUS)
-		return true;
-	else
-		return false;
-}
-
-
-/********************************************************************
-* changeDmaPriority - update the arbiter`s priority for channels 0-3
-*
-* Inputs: priority  for channels 0-1, priority  for channels 2-3,
-          priority for groups and other priority options
-* RETURNS: false if one of the parameters is erroneous and true else
-*********************************************************************/
-
-bool changeDmaPriority(PRIO_CHAN_0_1 prio_01, PRIO_CHAN_2_3 prio_23,
-		       PRIO_GROUP prioGrp, PRIO_OPT prioOpt)
-{
-	unsigned int prioReg = 0;
-
-	prioReg = (prio_01 & 0x3) + ((prio_23 & 0x3) << 2) +
-	    ((prioGrp & 0x3) << 4) + (prioOpt << 6);
-	GT_REG_WRITE(ARBITER_CONTROL, prioReg);
-	return true;
-}
--- diff/arch/mips/galileo-boards/ev64120/i2o.c	2003-07-08 09:55:17.000000000 +0100
+++ source/arch/mips/galileo-boards/ev64120/i2o.c	1970-01-01 01:00:00.000000000 +0100
@@ -1,689 +0,0 @@
-/* i2o.c - Drivers for the I2O */
-
-/* Copyright - Galileo technology. */
-
-/*includes*/
-
-#include <linux/module.h>
-
-#ifdef __linux__
-#include <asm/galileo-boards/evb64120A/core.h>
-#include <asm/galileo-boards/evb64120A/i2o.h>
-#else
-#include "Core.h"
-#include "i2o.h"
-#endif
-
-/********************************************************************
-* getInBoundMessage - When the GT is configured for I2O support
-*                     it can receive a message from an agent on the pci bus.
-*                     This message is a 32 bit wide and can be read by
-*                     the CPU.
-*                     The messaging unit contains two sets of registers
-*                     so, actually it can receive a 64 bit message.
-*
-* INPUTS: I2O_MESSAGE_REG messageRegNum - Selected set (0 or 1) register.
-* OUTPUT: N/A.
-* RETURNS: Data received from the remote agent.
-*********************************************************************/
-unsigned int getInBoundMessage(I2O_MESSAGE_REG messageRegNum)
-{
-	unsigned int regValue;
-
-	GT_REG_READ(INBOUND_MESSAGE_REGISTER0_CPU_SIDE + 4 * messageRegNum,
-		    &regValue);
-	return (regValue);
-}
-
-
-/********************************************************************
-* checkInboundIntAndClear - When a message is received an interrupt is
-*                           generated, to enable polling instead the use of
-*                           an interrupt handler the user can use this fuction.
-*                           You will need to mask the incomming interrupt for
-*                           proper use.
-*
-* INPUTS: I2O_MESSAGE_REG messageRegNum - Selected set (0 or 1) register.
-* OUTPUT: N/A.
-* RETURNS: true if the corresponding bit in the cause register is set otherwise
-*          false.
-*********************************************************************/
-bool checkInBoundIntAndClear(I2O_MESSAGE_REG messageRegNum)
-{
-	unsigned int regValue;
-
-	GT_REG_READ(INBOUND_INTERRUPT_CAUSE_REGISTER_CPU_SIDE, &regValue);
-	/* clears bit 0 for message register 0 or bit 1 for message register 1 */
-	GT_REG_WRITE(INBOUND_INTERRUPT_CAUSE_REGISTER_CPU_SIDE,
-		     BIT1 * messageRegNum);
-	switch (messageRegNum) {
-	case MESSAGE_REG_0:
-		if (regValue & BIT0)
-			return true;
-		break;
-	case MESSAGE_REG_1:
-		if (regValue & BIT1)
-			return true;
-		break;
-	}
-	return false;
-}
-
-/********************************************************************
-* sendOutBoundMessage - When the GT is configured for I2O support
-*                     it can send a message to an agent on the pci bus.
-*                     This message is a 32 bit wide and can be read by
-*                     the PCI agent.
-*                     The messaging unit contains two sets of registers
-*                     so, actually it can send a 64 bit message.
-*
-* INPUTS: I2O_MESSAGE_REG messageRegNum - Selected set (0 or 1) register.
-*         unsigned int message - Message to be sent.
-* OUTPUT: N/A.
-* RETURNS: true.
-*********************************************************************/
-bool sendOutBoundMessage(I2O_MESSAGE_REG messageRegNum,
-			 unsigned int message)
-{
-	GT_REG_WRITE(OUTBOUND_MESSAGE_REGISTER0_CPU_SIDE +
-		     4 * messageRegNum, message);
-	return true;
-}
-
-/********************************************************************
-* checkOutboundInt - When the CPU sends a message to the Outbound
-*                    register it generates an interrupt which is refelcted on
-*                    the Outbound Interrupt cause register, the interrupt can
-*                    be cleard only by the PCI agent which read the message.
-*                    After sending the message you can acknowledge it by
-*                    monitoring the corresponding bit in the cause register.
-*
-* INPUTS: I2O_MESSAGE_REG messageRegNum - Selected set (0 or 1) register.
-* OUTPUT: N/A.
-* RETURNS: true if the corresponding bit in the cause register is set otherwise
-*          false.
-*********************************************************************/
-bool outBoundMessageAcknowledge(I2O_MESSAGE_REG messageRegNum)
-{
-	unsigned int regValue;
-
-	GT_REG_READ(OUTBOUND_INTERRUPT_CAUSE_REGISTER_CPU_SIDE, &regValue);
-	switch (messageRegNum) {
-	case MESSAGE_REG_0:
-		if (regValue & BIT0)
-			return true;
-		break;
-	case MESSAGE_REG_1:
-		if (regValue & BIT1)
-			return true;
-		break;
-	}
-	return false;
-}
-
-/********************************************************************
-* maskInBoundMessageInterrupt - Mask the inbound interrupt, when masking
-*                               the interrupt you can work in polling mode
-*                               using the checkInboundIntAndClear function.
-*
-* INPUTS: I2O_MESSAGE_REG messageRegNum - Selected set (0 or 1) register.
-* OUTPUT: N/A.
-* RETURNS: true.
-*********************************************************************/
-bool maskInBoundMessageInterrupt(I2O_MESSAGE_REG messageRegNum)
-{
-	switch (messageRegNum) {
-	case MESSAGE_REG_0:
-		SET_REG_BITS(INBOUND_INTERRUPT_MASK_REGISTER_CPU_SIDE,
-			     BIT0);
-		break;
-	case MESSAGE_REG_1:
-		SET_REG_BITS(INBOUND_INTERRUPT_MASK_REGISTER_CPU_SIDE,
-			     BIT1);
-		break;
-	}
-	return true;
-}
-
-/********************************************************************
-* enableInBoundMessageInterrupt - unMask the inbound interrupt.
-*
-* INPUTS: I2O_MESSAGE_REG messageRegNum - Selected set (0 or 1) register.
-* OUTPUT: N/A.
-* RETURNS: true.
-*********************************************************************/
-bool enableInBoundMessageInterrupt(I2O_MESSAGE_REG messageRegNum)
-{
-	switch (messageRegNum) {
-	case MESSAGE_REG_0:
-		RESET_REG_BITS(INBOUND_INTERRUPT_MASK_REGISTER_CPU_SIDE,
-			       BIT0);
-		break;
-	case MESSAGE_REG_1:
-		RESET_REG_BITS(INBOUND_INTERRUPT_MASK_REGISTER_CPU_SIDE,
-			       BIT1);
-		break;
-	}
-	return true;
-}
-
-/********************************************************************
-* maskOutboundMessageInterrupt - Mask the out bound interrupt, when doing so
-*                           the PCI agent needs to poll on the interrupt
-*                           cause register to monitor an incoming message.
-*
-* INPUTS: I2O_MESSAGE_REG messageRegNum - Selected set (0 or 1) register.
-* OUTPUT: N/A.
-* RETURNS: true.
-*********************************************************************/
-bool maskOutBoundMessageInterrupt(I2O_MESSAGE_REG messageRegNum)
-{
-	switch (messageRegNum) {
-	case MESSAGE_REG_0:
-		SET_REG_BITS(OUTBOUND_INTERRUPT_MASK_REGISTER_CPU_SIDE,
-			     BIT0);
-		break;
-	case MESSAGE_REG_1:
-		SET_REG_BITS(OUTBOUND_INTERRUPT_MASK_REGISTER_CPU_SIDE,
-			     BIT1);
-		break;
-	}
-	return true;
-}
-
-/********************************************************************
-* enableOutboundMessageInterrupt - Mask the out bound interrupt, when doing so
-*                           the PCI agent needs to poll on the interrupt
-*                           cause register to monitor an incoming message.
-*
-* INPUTS: I2O_MESSAGE_REG messageRegNum - Selected set (0 or 1) register.
-* OUTPUT: N/A.
-* RETURNS: true.
-*********************************************************************/
-bool enableOutBoundMessageInterrupt(I2O_MESSAGE_REG messageRegNum)
-{
-	switch (messageRegNum) {
-	case MESSAGE_REG_0:
-		RESET_REG_BITS(OUTBOUND_INTERRUPT_MASK_REGISTER_CPU_SIDE,
-			       BIT0);
-		break;
-	case MESSAGE_REG_1:
-		RESET_REG_BITS(OUTBOUND_INTERRUPT_MASK_REGISTER_CPU_SIDE,
-			       BIT1);
-		break;
-	}
-	return true;
-}
-
-/********************************************************************
-* initiateOutBoundDoorBellInt - Setting a bit in this register to '1' by the
-*                       CPU generates a PCI interrupt (if it is not masked by
-*                       the Outbound interrupt Mask register)
-*                       Only the PCI agent which recieved the interrupt can
-*                       clear it, only after clearing all the bits the
-*                       interrupt will be de-asserted.
-*
-* INPUTS: unsigned int data - Requested interrupt bits.
-* OUTPUT: N/A.
-* RETURNS: true.
-*********************************************************************/
-bool initiateOutBoundDoorBellInt(unsigned int data)
-{
-	GT_REG_WRITE(OUTBOUND_DOORBELL_REGISTER_CPU_SIDE, data);
-	return true;
-}
-
-/********************************************************************
-* readInBoundDoorBellInt - Read the in bound door bell interrupt cause
-*                          register.
-*
-* OUTPUT:  N/A.
-* RETURNS: The 32 bit interrupt cause register.
-*********************************************************************/
-unsigned int readInBoundDoorBellInt()
-{
-	unsigned int regData;
-	GT_REG_READ(INBOUND_DOORBELL_REGISTER_CPU_SIDE, &regData);
-	return regData;
-}
-
-/********************************************************************
-* clearInBoundDoorBellInt - An interrupt generated by a PCI agent through
-*                           the in bound door bell mechanisem can be cleared
-*                           only by the CPU. The interrupt will be de-asserted
-*                           only if all the bits which where set by the PCI
-*                           agent are cleared.
-*
-* INPUTS:  unsigned int data - Bits to be cleared.
-* OUTPUT:  N/A.
-* RETURNS: true.
-*********************************************************************/
-bool clearInBoundDoorBellInt(unsigned int data)
-{
-	GT_REG_WRITE(INBOUND_DOORBELL_REGISTER_CPU_SIDE, data);
-	return true;
-}
-
-/********************************************************************
-* isInBoundDoorBellInterruptSet - Check if Inbound Doorbell Interrupt is set,
-*                                 can be used for polling mode.
-*
-* INPUTS:  N/A.
-* OUTPUT:  N/A.
-* RETURNS: true if the corresponding bit in the cause register is set otherwise
-*          false.
-*********************************************************************/
-bool isInBoundDoorBellInterruptSet()
-{
-	unsigned int regData;
-
-	GT_REG_READ(INBOUND_INTERRUPT_CAUSE_REGISTER_CPU_SIDE, &regData);
-	return (regData & BIT2);
-}
-
-/********************************************************************
-* isOutBoundDoorBellInterruptSet - Check if out bound Doorbell Interrupt is
-*                                  set, can be used for acknowledging interrupt
-*                                  handling by the agent who recieived the
-*                                  interrupt.
-*
-* INPUTS:  N/A.
-* OUTPUT:  N/A.
-* RETURNS: true if the corresponding bit in the cause register is set otherwise
-*          false.
-*********************************************************************/
-bool isOutBoundDoorBellInterruptSet()
-{
-	unsigned int regData;
-
-	GT_REG_READ(OUTBOUND_INTERRUPT_CAUSE_REGISTER_CPU_SIDE, &regData);
-	return (regData & BIT2);
-}
-
-/********************************************************************
-* maskInboundDoorBellInterrupt - Mask the Inbound Doorbell Interrupt.
-*
-* INPUTS:  N/A.
-* OUTPUT:  N/A.
-* RETURNS: true.
-*********************************************************************/
-bool maskInBoundDoorBellInterrupt()
-{
-	SET_REG_BITS(INBOUND_INTERRUPT_MASK_REGISTER_CPU_SIDE, BIT2);
-	return true;
-}
-
-/********************************************************************
-* enableInboundDoorBellInterrupt - unMask the Inbound Doorbell Interrupt.
-*
-* INPUTS:  N/A.
-* OUTPUT:  N/A.
-* RETURNS: true.
-*********************************************************************/
-bool enableInBoundDoorBellInterrupt()
-{
-	RESET_REG_BITS(INBOUND_INTERRUPT_MASK_REGISTER_CPU_SIDE, BIT2);
-	return true;
-}
-
-/********************************************************************
-* maskOutboundDoorBellInterrupt - Mask the Outbound Doorbell Interrupt.
-*
-* INPUTS:  N/A.
-* OUTPUT:  N/A.
-* RETURNS: true.
-*********************************************************************/
-bool maskOutBoundDoorBellInterrupt()
-{
-	SET_REG_BITS(OUTBOUND_INTERRUPT_MASK_REGISTER_CPU_SIDE, BIT2);
-	return true;
-}
-
-/********************************************************************
-* enableOutboundDoorBellInterrupt - unMask the Outbound Doorbell Interrupt.
-*
-* INPUTS:  N/A.
-* OUTPUT:  N/A.
-* RETURNS: true.
-*********************************************************************/
-bool enableOutBoundDoorBellInterrupt()
-{
-	RESET_REG_BITS(OUTBOUND_INTERRUPT_MASK_REGISTER_CPU_SIDE, BIT2);
-	return true;
-}
-
-/********************************************************************
-* circularQueueEnable - Initialize the I2O messaging mechanism.
-*
-* INPUTS:   CIRCULE_QUEUE_SIZE cirQueSize - Bits 5:1 in the:
-*           Queue Control Register, Offset 0x50 (0x1c50).
-*           Defines the queues size (refer to the data sheet
-*           for more information)
-*          unsigned int queueBaseAddr - The base address for the first queue.
-*           The other queues base Address will be determined as follows:
-*           Inbound Free = queueBaseAddr
-*           Inbound Post = queueBaseAddr + cirQueSize
-*           Outbound Post = queueBaseAddr + cirQueSize
-*
-* OUTPUT:  N/A.
-* RETURNS: true.
-*
-*  The Circular Queue Starting Addresses as written in the spec:
-*  ----------------------------------------
-*  |    Queue       |  Starting Address   |
-*  |----------------|---------------------|
-*  | Inbound Free   |       QBAR          |
-*  | Inbound Post   | QBAR + Queue Size   |
-*  | Outbound Post  | QBAR + 2*Queue Size |
-*  | Outbound Free  | QBAR + 3*Queue Size |
-*  ----------------------------------------
-*********************************************************************/
-bool circularQueueEnable(CIRCULAR_QUEUE_SIZE cirQueSize,
-			 unsigned int queueBaseAddr)
-{
-	unsigned int regData;
-
-	regData = BIT0 | (cirQueSize << 1);
-	/* Enable Queue Operation */
-	GT_REG_WRITE(QUEUE_CONTROL_REGISTER_CPU_SIDE, regData);
-	/* Writing The base Address for the 4 Queues */
-	GT_REG_WRITE(QUEUE_BASE_ADDRESS_REGISTER_CPU_SIDE, queueBaseAddr);
-	/* Update The Inbound Free Queue Base Address, offset=0 */
-	GT_REG_WRITE(INBOUND_FREE_HEAD_POINTER_REGISTER_CPU_SIDE, 0);
-	GT_REG_WRITE(INBOUND_FREE_TAIL_POINTER_REGISTER_CPU_SIDE, 0);
-	/* Update The Inbound Post Queue Base Address, offset=_16K*cirQueSize */
-	GT_REG_WRITE(INBOUND_POST_HEAD_POINTER_REGISTER_CPU_SIDE,
-		     _16K * cirQueSize);
-	GT_REG_WRITE(INBOUND_POST_TAIL_POINTER_REGISTER_CPU_SIDE,
-		     _16K * cirQueSize);
-	/* Update The Outbound Post Queue Base Address, offset=2*_16K*cirQueSize */
-	GT_REG_WRITE(OUTBOUND_POST_HEAD_POINTER_REGISTER_CPU_SIDE,
-		     2 * _16K * cirQueSize);
-	GT_REG_WRITE(OUTBOUND_POST_TAIL_POINTER_REGISTER_CPU_SIDE,
-		     2 * _16K * cirQueSize);
-	/* Update The Outbound Free Queue Base Address, offset=3*_16K*cirQueSize */
-	GT_REG_WRITE(OUTBOUND_FREE_HEAD_POINTER_REGISTER_CPU_SIDE,
-		     3 * _16K * cirQueSize);
-	GT_REG_WRITE(OUTBOUND_FREE_TAIL_POINTER_REGISTER_CPU_SIDE,
-		     3 * _16K * cirQueSize);
-	return true;
-}
-
-/********************************************************************
-* inBoundPostQueuePop - Two actions are being taken upon pop:
-*           1) Getting out the data from the Queue`s head.
-*           2) Increment the tail pointer in a cyclic way (The HEAD is
-*              incremented automaticaly by the GT)
-*
-* INPUTS:  N/A.
-* OUTPUT:  N/A.
-* RETURNS: Data pointed by tail.
-*********************************************************************/
-unsigned int inBoundPostQueuePop()
-{
-	unsigned int tailAddrPointer;
-	unsigned int data;
-	unsigned int cirQueSize;
-	unsigned int qBar;
-	unsigned int inBoundPostQbase;
-
-	/* Gets the Inbound Post TAIL pointer */
-	GT_REG_READ(INBOUND_POST_TAIL_POINTER_REGISTER_CPU_SIDE,
-		    &tailAddrPointer);
-	/* Gets the Data From the pointer Address */
-	READ_WORD(tailAddrPointer, &data);
-	/* incrementing head process: */
-	/* Gets the fifo's base Address */
-	GT_REG_READ(QUEUE_BASE_ADDRESS_REGISTER_CPU_SIDE, &qBar);
-	qBar = qBar & 0xfff00000;
-	/* Gets the fifo's size */
-	GT_REG_READ(QUEUE_CONTROL_REGISTER_CPU_SIDE, &cirQueSize);
-	cirQueSize = 0x1f && (cirQueSize >> 1);
-	/* calculating The Inbound Post Queue Base Address */
-	inBoundPostQbase = qBar + 1 * cirQueSize * _16K;
-	/* incrementing Inbound Post queue TAIL in a cyclic loop */
-	tailAddrPointer = inBoundPostQbase + ((tailAddrPointer + 4) %
-					      (_16K * cirQueSize));
-	/* updating the pointer back to INBOUND_POST_TAIL_POINTER_REGISTER */
-	GT_REG_WRITE(INBOUND_POST_TAIL_POINTER_REGISTER_CPU_SIDE,
-		     tailAddrPointer);
-	return data;
-}
-
-/********************************************************************
-* isInBoundPostQueueInterruptSet - Check if in bound interrupt is set.
-*                                  can be used for polling mode.
-*
-* INPUTS:  N/A.
-* OUTPUT:  N/A.
-* RETURNS: true if the corresponding bit in the cause register is set otherwise
-*          false.
-*********************************************************************/
-bool isInBoundPostQueueInterruptSet()
-{
-	unsigned int regData;
-
-	GT_REG_READ(INBOUND_INTERRUPT_CAUSE_REGISTER_CPU_SIDE, &regData);
-	return (regData & BIT4);	/* if set return '1' (true), else '0' (false) */
-}
-
-/********************************************************************
-* clearInBoundPostQueueInterrupt - Clears the Post queue interrupt.
-*
-* INPUTS:  N/A.
-* OUTPUT:  N/A.
-* RETURNS: true.
-*********************************************************************/
-bool clearInBoundPostQueueInterrupt()
-{
-	GT_REG_WRITE(INBOUND_INTERRUPT_CAUSE_REGISTER_CPU_SIDE, BIT4);
-	return true;
-}
-
-/********************************************************************
-* maskInBoundPostQueueInterrupt - Mask the inbound interrupt, when masking
-*                                 the interrupt you can work in polling mode.
-*
-* INPUTS:  N/A.
-* OUTPUT:  N/A.
-* RETURNS:
-*********************************************************************/
-void maskInBoundPostQueueInterrupt()
-{
-	unsigned int regData;
-
-	GT_REG_READ(INBOUND_INTERRUPT_MASK_REGISTER_CPU_SIDE, &regData);
-	GT_REG_WRITE(INBOUND_INTERRUPT_MASK_REGISTER_CPU_SIDE,
-		     regData | BIT4);
-
-}
-
-/********************************************************************
-* enableInBoundPostQueueInterrupt - Enable interrupt when ever there is a new
-*                                   message from the PCI agent.
-*
-* INPUTS:  N/A.
-* OUTPUT:  N/A.
-* RETURNS:
-*********************************************************************/
-void enableInBoundPostQueueInterrupt()
-{
-	unsigned int regData;
-
-	GT_REG_READ(INBOUND_INTERRUPT_MASK_REGISTER_CPU_SIDE, &regData);
-	GT_REG_WRITE(INBOUND_INTERRUPT_MASK_REGISTER_CPU_SIDE,
-		     regData & 0xfffffffb);
-}
-
-/********************************************************************
-* inBoundFreeQueuePush - Two actions are being taken upon push:
-*           1) Place the user`s data on the Queue`s head.
-*           2) Increment the haed pointer in a cyclic way (The tail is
-*              decremented automaticaly by the GT)
-*
-* INPUTS:  unsigned int data - Data to be placed in the queue.
-* OUTPUT:  N/A.
-* RETURNS: true.
-*********************************************************************/
-bool inBoundFreeQueuePush(unsigned int data)
-{
-	unsigned int headPointer;
-	unsigned int cirQueSize;
-	unsigned int qBar;
-	unsigned int inBoundFreeQbase;
-
-	GT_REG_READ(INBOUND_FREE_HEAD_POINTER_REGISTER_CPU_SIDE,
-		    &headPointer);
-	/* placing the data in the queue */
-	WRITE_WORD(headPointer, data);
-	/* incrementing head process: */
-	/* Gets the fifo's base Address */
-	GT_REG_READ(QUEUE_BASE_ADDRESS_REGISTER_CPU_SIDE, &qBar);
-	qBar = qBar & 0xfff00000;
-	/* Gets the fifo's size */
-	GT_REG_READ(QUEUE_CONTROL_REGISTER_CPU_SIDE, &cirQueSize);
-	cirQueSize = 0x1f && (cirQueSize >> 1);
-	/* calculating The Inbound Free Queue Base Address */
-	inBoundFreeQbase = qBar;
-	/* incrementing Inbound Free queue HEAD in a cyclic loop */
-	headPointer =
-	    inBoundFreeQbase + ((headPointer + 4) % (_16K * cirQueSize));
-	/* updating the pointer back to OUTBOUND_POST_HEAD_POINTER_REGISTER */
-	GT_REG_WRITE(INBOUND_FREE_HEAD_POINTER_REGISTER_CPU_SIDE,
-		     headPointer);
-	return true;
-}
-
-/********************************************************************
-* isInBoundFreeQueueEmpty - Check if Inbound Free Queue Empty.
-*                           Can be used for acknowledging the messages
-*                           being sent by us to the PCI agent.
-*
-* INPUTS:  N/A.
-* OUTPUT:  N/A.
-* RETURNS: true if the queue is empty , otherwise false.
-*********************************************************************/
-bool isInBoundFreeQueueEmpty()
-{
-	unsigned int inBoundFreeQueHead;
-	unsigned int inBoundFreeQueTail;
-
-	GT_REG_READ(INBOUND_FREE_HEAD_POINTER_REGISTER_CPU_SIDE,
-		    &inBoundFreeQueHead);
-	GT_REG_READ(INBOUND_FREE_TAIL_POINTER_REGISTER_CPU_SIDE,
-		    &inBoundFreeQueTail);
-	if (inBoundFreeQueHead == inBoundFreeQueTail) {
-		return true;
-	} else
-		return false;
-}
-
-/********************************************************************
-* outBoundPostQueuePush  - Two actions are being taken upon push:
-*           1) Place the user`s data on the Queue`s head.
-*           2) Increment the haed pointer in a cyclic way (The tail is
-*              decremented automaticaly by the GT when the Agent on the
-*              PCI have read data from the Outbound Port).
-*
-* INPUTS:  unsigned int data - Data to be placed in the queue`s head.
-* OUTPUT:  N/A.
-* RETURNS: true.
-*********************************************************************/
-bool outBoundPostQueuePush(unsigned int data)
-{
-	unsigned int headPointer;
-	unsigned int cirQueSize;
-	unsigned int qBar;
-	unsigned int outBoundPostQbase;
-
-	GT_REG_READ(OUTBOUND_POST_HEAD_POINTER_REGISTER_CPU_SIDE,
-		    &headPointer);
-	/* placing the data in the queue (where the head point to..) */
-	WRITE_WORD(headPointer, data);
-	/* incrementing head process: */
-	/* Gets the fifo's base Address */
-	GT_REG_READ(QUEUE_BASE_ADDRESS_REGISTER_CPU_SIDE, &qBar);
-	qBar = qBar & 0xfff00000;
-	/* Gets the fifo's size */
-	GT_REG_READ(QUEUE_CONTROL_REGISTER_CPU_SIDE, &cirQueSize);
-	cirQueSize = 0x1f && (cirQueSize >> 1);
-	/* calculating The Outbound Post Queue Base Address */
-	outBoundPostQbase = qBar + 2 * cirQueSize * _16K;
-	/* incrementing Outbound Post queue in a cyclic loop */
-	headPointer =
-	    outBoundPostQbase + ((headPointer + 4) % (_16K * cirQueSize));
-	/* updating the pointer back to OUTBOUND_POST_HEAD_POINTER_REGISTER */
-	GT_REG_WRITE(OUTBOUND_POST_HEAD_POINTER_REGISTER_CPU_SIDE,
-		     headPointer);
-	return true;
-}
-
-/********************************************************************
-* isOutBoundPostQueueEmpty - Check if Outbound Post Queue Empty.
-*                            Can be used for acknowledging the messages
-*                            being sent by us to the PCI agent.
-*
-* INPUTS:  N/A.
-* OUTPUT:  N/A.
-* RETURNS: true if the queue is empty , otherwise false.
-*********************************************************************/
-bool isOutBoundPostQueueEmpty()
-{
-	unsigned int outBoundPostQueHead;
-	unsigned int outBoundPostQueTail;
-
-	GT_REG_READ(INBOUND_FREE_HEAD_POINTER_REGISTER_CPU_SIDE,
-		    &outBoundPostQueHead);
-	GT_REG_READ(INBOUND_FREE_TAIL_POINTER_REGISTER_CPU_SIDE,
-		    &outBoundPostQueTail);
-	if (outBoundPostQueHead == outBoundPostQueTail) {
-		return true;
-	} else
-		return false;
-}
-
-/********************************************************************
-* outBoundFreeQueuePop - Two actions are being taken upon pop:
-*           1) Getting out the data from the Queue`s head.
-*           2) Increment the tail pointer in a cyclic way (The HEAD is
-*              incremented automaticaly by the GT)
-*
-* INPUTS:  N/A.
-* OUTPUT:  N/A.
-* RETURNS: Data pointed by tail.
-*********************************************************************/
-unsigned int outBoundFreeQueuePop()
-{
-	unsigned int tailAddrPointer;
-	unsigned int data;
-	unsigned int cirQueSize;
-	unsigned int qBar;
-	unsigned int outBoundFreeQbase;
-
-	/* Gets the Inbound Post TAIL pointer */
-	GT_REG_READ(OUTBOUND_FREE_TAIL_POINTER_REGISTER_CPU_SIDE,
-		    &tailAddrPointer);
-	/* Gets the Data From the pointer Address */
-	READ_WORD(tailAddrPointer, &data);
-	/* incrementing head process: */
-	/* Gets the fifo's base Address */
-	GT_REG_READ(QUEUE_BASE_ADDRESS_REGISTER_CPU_SIDE, &qBar);
-	qBar = qBar & 0xfff00000;
-	/* Gets the fifo's size */
-	GT_REG_READ(QUEUE_CONTROL_REGISTER_CPU_SIDE, &cirQueSize);
-	cirQueSize = 0x1f && (cirQueSize >> 1);
-	/* calculating The Inbound Post Queue Base Address */
-	outBoundFreeQbase = qBar + 3 * cirQueSize * _16K;
-	/* incrementing Outbound Free queue TAlL in a cyclic loop */
-	tailAddrPointer = outBoundFreeQbase + ((tailAddrPointer + 4) %
-					       (_16K * cirQueSize));
-	/* updating the pointer back to OUTBOUND_FREE_TAIL_POINTER_REGISTER */
-	GT_REG_WRITE(OUTBOUND_FREE_TAIL_POINTER_REGISTER_CPU_SIDE,
-		     tailAddrPointer);
-	return data;
-}
-
-
-EXPORT_SYMBOL(isInBoundDoorBellInterruptSet);
-EXPORT_SYMBOL(initiateOutBoundDoorBellInt);
-EXPORT_SYMBOL(clearInBoundDoorBellInt);
--- diff/arch/mips/galileo-boards/ev64120/int-handler.S	2003-07-08 09:55:17.000000000 +0100
+++ source/arch/mips/galileo-boards/ev64120/int-handler.S	1970-01-01 01:00:00.000000000 +0100
@@ -1,85 +0,0 @@
-/*
- * int-handler.S
- *
- * Based on the cobalt handler.
- */
-#include <asm/asm.h>
-#include <asm/mipsregs.h>
-#include <asm/addrspace.h>
-#include <asm/regdef.h>
-#include <asm/stackframe.h>
-
-/*
- * We check for the timer first, then check PCI ints A and D.
- * Then check for serial IRQ and fall through.
- */
-		.align	5
-		.set	reorder
-		.set	noat
-		NESTED(galileo_handle_int, PT_SIZE, sp)
-		SAVE_ALL
-		CLI
-		.set	at
-
-		mfc0	t0, CP0_CAUSE
-		mfc0	t2, CP0_STATUS
-
-		and	t0, t2
-
-		.set	noreorder
-		andi	t1, t0, STATUSF_IP4 /* int2 hardware line (timer) */
-		andi	t2, t0, STATUSF_IP2 /* int0 hardware line */
-		bnez	t1, ll_galileo_irq
-		 andi	t1, t0, STATUSF_IP5 /* int3 hardware line */
-		bnez	t2, ll_pci_intA
-		 andi	t2, t0, STATUSF_IP6 /* int4 hardware line */
-		bnez	t1, ll_pci_intD
-		 andi	t1, t0, STATUSF_IP7 /* compare int */
-		bnez	t2, ll_serial_irq
-		 nop
-		bnez	t1, ll_compare_irq
-		 nop
-		.set	reorder
-
-		j	spurious_interrupt
-		END(galileo_handle_int)
-
-		.align	5
-ll_galileo_irq:	li	a0, 4
-		move	a1, sp
-		jal	do_IRQ
-		j	ret_from_irq
-
-		.align	5
-ll_compare_irq:	li 	a0, 7
-		move	a1, sp
-		jal	do_IRQ
-		j	ret_from_irq
-
-		.align	5
-ll_pci_intA:	move	a0, sp
-		jal	pci_intA
-		j	ret_from_irq
-
-#if 0
-		.align	5
-ll_pci_intB:	move 	a0, sp
-		jal	pci_intB
-		j	ret_from_irq
-
-		.align	5
-ll_pci_intC:	move 	a0, sp
-		jal	pci_intC
-		j	ret_from_irq
-#endif
-
-		.align	5
-ll_pci_intD:	move 	a0, sp
-		jal	pci_intD
-		j	ret_from_irq
-
-		.align	5
-ll_serial_irq:	li	a0, 6
-		move	a1, sp
-		jal	do_IRQ
-		j	ret_from_irq
--- diff/arch/mips/galileo-boards/ev64120/irq-handler.c	2003-07-08 09:55:17.000000000 +0100
+++ source/arch/mips/galileo-boards/ev64120/irq-handler.c	1970-01-01 01:00:00.000000000 +0100
@@ -1,270 +0,0 @@
-/*
- * Galileo Technology chip interrupt handler
- *
- *  Modified by RidgeRun, Inc.
- */
-#include <linux/module.h>
-#include <linux/interrupt.h>
-#include <linux/kernel.h>
-#include <asm/ptrace.h>
-#include <linux/config.h>
-#include <linux/sched.h>
-#include <linux/kernel_stat.h>
-#include <asm/io.h>
-#include <asm/gt64120.h>
-#include <asm/galileo-boards/ev64120.h>
-#include <asm/galileo-boards/ev64120int.h>
-
-/*
- * These are interrupt handlers for the GT on-chip interrupts.  They all come
- * in to the MIPS on a single interrupt line, and have to be handled and ack'ed
- * differently than other MIPS interrupts.
- */
-
-#if CURRENTLY_UNUSED
-
-struct tq_struct irq_handlers[MAX_CAUSE_REGS][MAX_CAUSE_REG_WIDTH];
-void hook_irq_handler(int int_cause, int bit_num, void *isr_ptr);
-
-/*
- * hook_irq_handler
- *
- * Hooks IRQ handler to the system. When the system is interrupted
- * the interrupt service routine is called.
- *
- * Inputs :
- * int_cause - The interrupt cause number. In EVB64120 two parameters
- *             are declared, INT_CAUSE_MAIN and INT_CAUSE_HIGH.
- * bit_num   - Indicates which bit number in the cause register
- * isr_ptr   - Pointer to the interrupt service routine
- *
- * Outputs :
- */
-void hook_irq_handler(int int_cause, int bit_num, void *isr_ptr)
-{
-	irq_handlers[int_cause][bit_num].routine = isr_ptr;
-}
-
-
-/*
- * enable_galileo_irq
- *
- * Enables the IRQ on Galileo Chip
- *
- * Inputs :
- * int_cause -  The interrupt cause number. In EVB64120 two parameters
- *            are declared, INT_CAUSE_MAIN and INT_CAUSE_HIGH.
- * bit_num   - Indicates which bit number in the cause register
- *
- * Outputs :
- * 1 if succesful, 0 if failure
- */
-int enable_galileo_irq(int int_cause, int bit_num)
-{
-	if (int_cause == INT_CAUSE_MAIN)
-		SET_REG_BITS(CPU_INTERRUPT_MASK_REGISTER, (1 << bit_num));
-	else if (int_cause == INT_CAUSE_HIGH)
-		SET_REG_BITS(CPU_HIGH_INTERRUPT_MASK_REGISTER,
-			     (1 << bit_num));
-	else
-		return 0;
-	return 1;
-}
-
-/*
- * disable_galileo_irq
- *
- * Disables the IRQ on Galileo Chip
- *
- * Inputs :
- * int_cause -  The interrupt cause number. In EVB64120 two parameters
- *            are declared, INT_CAUSE_MAIN and INT_CAUSE_HIGH.
- * bit_num   - Indicates which bit number in the cause register
- *
- * Outputs :
- * 1 if succesful, 0 if failure
- */
-int disable_galileo_irq(int int_cause, int bit_num)
-{
-	if (int_cause == INT_CAUSE_MAIN)
-		RESET_REG_BITS(CPU_INTERRUPT_MASK_REGISTER,
-			       (1 << bit_num));
-	else if (int_cause == INT_CAUSE_HIGH)
-		RESET_REG_BITS(CPU_HIGH_INTERRUPT_MASK_REGISTER,
-			       (1 << bit_num));
-	else
-		return 0;
-	return 1;
-}
-
-#endif				/*  UNUSED  */
-
-/*
- * galileo_irq -
- *
- * Interrupt handler for interrupts coming from the Galileo chip.
- * It could be timer interrupt, built in ethernet ports etc...
- *
- * Inputs :
- *
- * Outputs :
- *
- */
-static void galileo_irq(int irq, void *dev_id, struct pt_regs *regs)
-{
-	unsigned int irq_src, int_high_src, irq_src_mask,
-	    int_high_src_mask;
-	int handled;
-	unsigned int count;
-	static int counter = 0;
-
-	GT_READ(GT_INTRCAUSE_OFS, &irq_src);
-	GT_READ(GT_INTRMASK_OFS, &irq_src_mask);
-	GT_READ(GT_HINTRCAUSE_OFS, &int_high_src);
-	GT_READ(GT_HINTRMASK_OFS, &int_high_src_mask);
-	irq_src = irq_src & irq_src_mask;
-	int_high_src = int_high_src & int_high_src_mask;
-
-	handled = 0;
-
-	/* Execute all interrupt handlers */
-	/* Check for timer interrupt */
-	if (irq_src & 0x00000800) {
-		handled = 1;
-		irq_src &= ~0x00000800;
-		//    RESET_REG_BITS (INTERRUPT_CAUSE_REGISTER,BIT8);
-		do_timer(regs);
-	}
-
-	if (irq_src) {
-		printk(KERN_INFO
-		       "Other Galileo interrupt received irq_src %x\n",
-		       irq_src);
-#if CURRENTLY_UNUSED
-		for (count = 0; count < MAX_CAUSE_REG_WIDTH; count++) {
-			if (irq_src & (1 << count)) {
-				if (irq_handlers[INT_CAUSE_MAIN][count].
-				    routine) {
-					queue_task(&irq_handlers
-						   [INT_CAUSE_MAIN][count],
-						   &tq_immediate);
-					mark_bh(IMMEDIATE_BH);
-					handled = 1;
-				}
-			}
-		}
-#endif				/*  UNUSED  */
-	}
-	GT_WRITE(GT_INTRCAUSE_OFS, 0);
-	GT_WRITE(GT_HINTRCAUSE_OFS, 0);
-
-#undef GALILEO_I2O
-#ifdef GALILEO_I2O
-	/*
-	   Future I2O support.  We currently attach I2O interrupt handlers to the
-	   Galileo interrupt (int 4) and handle them in do_IRQ.
-	 */
-	if (isInBoundDoorBellInterruptSet()) {
-		printk(KERN_INFO "I2O doorbell interrupt received.\n");
-		handled = 1;
-	}
-
-	if (isInBoundPostQueueInterruptSet()) {
-		printk(KERN_INFO "I2O Queue interrupt received.\n");
-		handled = 1;
-	}
-
-	/*
-	   This normally would be outside of the ifdef, but since
-	   we're handling I2O outside of this handler, this
-	   printk shows up every time we get a valid I2O
-	   interrupt.  So turn this off for now.
-	 */
-	if (handled == 0) {
-		if (counter < 50) {
-			printk("Spurious Galileo interrupt...\n");
-			counter++;
-		}
-	}
-#endif
-}
-
-/*
- * galileo_time_init -
- *
- * Initializes timer using galileo's built in timer.
- *
- *
- * Inputs :
- * irq - number of irq to be used by the timer
- *
- * Outpus :
- *
- */
-#ifdef CONFIG_SYSCLK_100
-#define Sys_clock (100 * 1000000)	// 100 MHz
-#endif
-#ifdef CONFIG_SYSCLK_83
-#define Sys_clock (83.333 * 1000000)	// 83.333 MHz
-#endif
-#ifdef CONFIG_SYSCLK_75
-#define Sys_clock (75 * 1000000)	// 75 MHz
-#endif
-
-/*
- * This will ignore the standard MIPS timer interrupt handler that is passed
- * in as *irq (=irq0 in ../kernel/time.c).  We will do our own timer interrupt
- * handling.
- */
-void galileo_time_init(struct irqaction *irq)
-{
-	extern irq_desc_t irq_desc[NR_IRQS];
-	static struct irqaction timer;
-
-	/* Disable timer first */
-	GT_WRITE(GT_TC_CONTROL_OFS, 0);
-	/* Load timer value for 100 Hz */
-	GT_WRITE(GT_TC3_OFS, Sys_clock / 100);
-
-	/*
-	 * Create the IRQ structure entry for the timer.  Since we're too early
-	 * in the boot process to use the "request_irq()" call, we'll hard-code
-	 * the values to the correct interrupt line.
-	 */
-	timer.handler = &galileo_irq;
-	timer.flags = SA_SHIRQ;
-	timer.name = "timer";
-	timer.dev_id = NULL;
-	timer.next = NULL;
-	timer.mask = 0;
-	irq_desc[TIMER].action = &timer;
-
-	/* Enable timer ints */
-	GT_WRITE(GT_TC_CONTROL_OFS, 0xc0);
-	/* clear Cause register first */
-	GT_WRITE(GT_INTRCAUSE_OFS, 0x0);
-	/* Unmask timer int */
-	GT_WRITE(GT_INTRMASK_OFS, 0x800);
-	/* Clear High int register */
-	GT_WRITE(GT_HINTRCAUSE_OFS, 0x0);
-	/* Mask All interrupts at High cause interrupt */
-	GT_WRITE(GT_HINTRMASK_OFS, 0x0);
-
-}
-
-void galileo_irq_init(void)
-{
-#if CURRENTLY_UNUSED
-	int i, j;
-
-	/* Reset irq handlers pointers to NULL */
-	for (i = 0; i < MAX_CAUSE_REGS; i++) {
-		for (j = 0; j < MAX_CAUSE_REG_WIDTH; j++) {
-			irq_handlers[i][j].next = NULL;
-			irq_handlers[i][j].sync = 0;
-			irq_handlers[i][j].routine = NULL;
-			irq_handlers[i][j].data = NULL;
-		}
-	}
-#endif
-}
--- diff/arch/mips/galileo-boards/ev64120/irq.c	2003-07-08 09:55:17.000000000 +0100
+++ source/arch/mips/galileo-boards/ev64120/irq.c	1970-01-01 01:00:00.000000000 +0100
@@ -1,184 +0,0 @@
-/*
- * BRIEF MODULE DESCRIPTION
- * Code to handle irqs on GT64120A boards
- *  Derived from mips/orion and Cort <cort@fsmlabs.com>
- *
- * Copyright (C) 2000 RidgeRun, Inc.
- * Author: RidgeRun, Inc.
- *   glonnon@ridgerun.com, skranz@ridgerun.com, stevej@ridgerun.com
- *
- *  This program is free software; you can redistribute  it and/or modify it
- *  under  the terms of  the GNU General  Public License as published by the
- *  Free Software Foundation;  either version 2 of the  License, or (at your
- *  option) any later version.
- *
- *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
- *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
- *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
- *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
- *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
- *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- *  You should have received a copy of the  GNU General Public License along
- *  with this program; if not, write  to the Free Software Foundation, Inc.,
- *  675 Mass Ave, Cambridge, MA 02139, USA.
- *
- */
-#include <linux/errno.h>
-#include <linux/init.h>
-#include <linux/kernel_stat.h>
-#include <linux/module.h>
-#include <linux/signal.h>
-#include <linux/sched.h>
-#include <linux/types.h>
-#include <linux/interrupt.h>
-#include <linux/ioport.h>
-#include <linux/timex.h>
-#include <linux/slab.h>
-#include <linux/random.h>
-#include <asm/bitops.h>
-#include <asm/bootinfo.h>
-#include <asm/io.h>
-#include <asm/irq.h>
-#include <asm/mipsregs.h>
-#include <asm/system.h>
-#include <asm/galileo-boards/ev64120int.h>
-
-#define MAX_AGENTS_PER_INT 21	/*  Random number  */
-unsigned char pci_int_irq[MAX_AGENTS_PER_INT];
-static int max_interrupts = 0;
-
-asmlinkage void pci_intA(struct pt_regs *regs)
-{
-	unsigned int count = 0;
-
-	/* This must be a joke - Ralf  */
-	for (count = 0; count < max_interrupts; count++)
-		do_IRQ(pci_int_irq[count], regs);
-}
-
-asmlinkage void pci_intD(struct pt_regs *regs)
-{
-	unsigned int count = 0;
-
-	/* Encore une fois - This must be a joke - Ralf  */
-	for (count = 0; count < max_interrupts; count++)
-		do_IRQ(pci_int_irq[count], regs);
-}
-
-/*
- * Now this is scarry.  A disable_irq(2) or disable_irq(5) would just
- * accidently disable a pci irq.  It shouldn't happen but may just leaving
- * these always enabled or use some reference counting wouldn't be such a
- * bad thing.
- */
-static void disable_ev64120_irq(unsigned int irq_nr)
-{
-	unsigned long flags;
-
-	local_irq_save(flags);
-	if (irq_nr >= 8) {
-		/* All PCI interrupts are on line 5 or 2  */
-		clear_c0_status(IE_IRQ0 | IE_IRQ3);
-	} else {
-		clear_c0_status(0x100 << irq_nr);
-	}
-	local_irq_restore(flags);
-}
-
-#define mask_and_ack_ev64120_irq disable_ev64120_irq
-
-static inline void enable_ev64120_irq(unsigned int irq_nr)
-{
-	unsigned long flags;
-
-	local_irq_save(flags);
-	if (irq_nr >= 8) {
-		/* All PCI interrupts are on line 5 or 2  */
-		set_c0_status(IE_IRQ0 | IE_IRQ3);
-	} else {
-		set_c0_status(IE_SW0 << irq_nr);
-	}
-	local_irq_restore(flags);
-}
-
-static unsigned int startup_ev64120_irq(unsigned int irq)
-{
-	if (irq >= 8) {
-		// NOTE:  Add error-handling if > max
-		pci_int_irq[max_interrupts++] = irq;
-	}
-	enable_ev64120_irq(irq);
-
-	return 0;
-}
-
-static void shutdown_ev64120_irq(unsigned int irq)
-{
-	int count, tmp;
-
-	/*
-	 * Remove PCI interrupts from the pci_int_irq list.  Make sure
-	 * that some handler was removed before decrementing max_interrupts.
-	 */
-	if (irq >= 8) {
-		for (count = 0; count < max_interrupts; count++) {
-			if (pci_int_irq[count] == irq) {
-				for (tmp = count; tmp < max_interrupts; tmp++) {
-					pci_int_irq[tmp] =
-					    pci_int_irq[tmp + 1];
-				}
-			}
-		}
-		max_interrupts--;
-	}
-}
-
-static void end_ev64120_irq(unsigned int irq)
-{
-	if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
-		enable_ev64120_irq(irq);
-}
-
-static struct hw_interrupt_type ev64120_irq_type = {
-	"EV64120",
-	startup_ev64120_irq,
-	shutdown_ev64120_irq,
-	enable_ev64120_irq,
-	disable_ev64120_irq,
-	mask_and_ack_ev64120_irq,
-	end_ev64120_irq
-};
-
-/*
- * galileo_irq_setup - Initializes CPU interrupts
- */
-void __init init_IRQ(void)
-{
-	extern asmlinkage void galileo_handle_int(void);
-	int i;
-
-	init_generic_irq();
-
-	/* Yes, how many interrupts does this beast actually have?  -- Ralf */
-	for (i = 0; i < NR_IRQS; i++) {
-		irq_desc[i].status      = IRQ_DISABLED;
-		irq_desc[i].action      = 0;
-		irq_desc[i].depth       = 1;
-		irq_desc[i].handler     = &ev64120_irq_type;
-	}
-
-	/*
-	 * Clear all of the interrupts while we change the able around a bit.
-	 * Enable timer.  Other interrupts will be enabled as they are
-	 * registered.
-	 */
-	change_c0_status(ST0_IM | IE_IRQ2, IE_IRQ2);
-
-	/* Sets the exception_handler array. */
-	set_except_vector(0, galileo_handle_int);
-}
--- diff/arch/mips/galileo-boards/ev64120/promcon.c	2003-07-08 09:55:17.000000000 +0100
+++ source/arch/mips/galileo-boards/ev64120/promcon.c	1970-01-01 01:00:00.000000000 +0100
@@ -1,70 +0,0 @@
-/*
- * Wrap-around code for a console using the
- * SGI PROM io-routines.
- *
- * Copyright (c) 1999 Ulf Carlsson
- *
- * Derived from DECstation promcon.c
- * Copyright (c) 1998 Harald Koerfgen
- * Copyright (c) 2002 Ralf Baechle
- */
-
-#include <linux/tty.h>
-#include <linux/major.h>
-#include <linux/ptrace.h>
-#include <linux/init.h>
-#include <linux/console.h>
-#include <linux/fs.h>
-/*
-#include <asm/sgialib.h>
-*/
-
-static void prom_console_write(struct console *co, const char *s,
-			       unsigned count)
-{
-	extern int CONSOLE_CHANNEL;	// The default serial port
-	unsigned i;
-	/*
-	 *    Now, do each character
-	 */
-	for (i = 0; i < count; i++) {
-		if (*s == 10)
-			serial_putc(CONSOLE_CHANNEL, 13);
-		serial_putc(CONSOLE_CHANNEL, *s++);
-	}
-}
-int prom_getchar(void)
-{
-	return 0;
-}
-static int __init prom_console_setup(struct console *co, char *options)
-{
-	return 0;
-}
-
-static kdev_t prom_console_device(struct console *c)
-{
-	return mk_kdev(TTY_MAJOR, 64 + c->index);
-}
-
-static struct console sercons = {
-	.name	= "ttyS",
-	.write	= prom_console_write,
-	.device	= prom_console_device,
-	.setup	= prom_console_setup,
-	.flags	= CON_PRINTBUFFER,
-	.index	= -1,
-};
-
-
-/*
- *    Register console.
- */
-
-void gal_serial_console_init(void)
-{
-	//  serial_init();
-	//serial_set(115200);
-
-	register_console(&sercons);
-}
--- diff/arch/mips/galileo-boards/ev64120/reset.c	2003-07-08 09:55:17.000000000 +0100
+++ source/arch/mips/galileo-boards/ev64120/reset.c	1970-01-01 01:00:00.000000000 +0100
@@ -1,45 +0,0 @@
-/*
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (C) 1997, 2002 Ralf Baechle
- */
-#include <linux/sched.h>
-#include <linux/mm.h>
-#include <asm/io.h>
-#include <asm/cacheflush.h>
-#include <asm/processor.h>
-#include <asm/reboot.h>
-#include <asm/system.h>
-
-void galileo_machine_restart(char *command)
-{
-	*(volatile char *) 0xbc000000 = 0x0f;
-	/*
-	 * Ouch, we're still alive ... This time we take the silver bullet ...
-	 * ... and find that we leave the hardware in a state in which the
-	 * kernel in the flush locks up somewhen during of after the PCI
-	 * detection stuff.
-	 */
-	set_c0_status(ST0_BEV | ST0_ERL);
-	change_c0_config(CONF_CM_CMASK, CONF_CM_UNCACHED);
-	flush_cache_all();
-	write_c0_wired(0);
-	__asm__ __volatile__("jr\t%0"::"r"(0xbfc00000));
-}
-
-void galileo_machine_halt(void)
-{
-	printk(KERN_NOTICE "You can safely turn off the power\n");
-	while (1)
-		__asm__(".set\tmips3\n\t"
-	                "wait\n\t"
-			".set\tmips0");
-
-}
-
-void galileo_machine_power_off(void)
-{
-	galileo_machine_halt();
-}
--- diff/arch/mips/galileo-boards/ev64120/serialGT.c	2003-07-08 09:55:17.000000000 +0100
+++ source/arch/mips/galileo-boards/ev64120/serialGT.c	1970-01-01 01:00:00.000000000 +0100
@@ -1,212 +0,0 @@
-/*
- * serialGT.c
- *
- * BRIEF MODULE DESCRIPTION
- *  Low Level Serial Port control for use
- *  with the Galileo EVB64120A MIPS eval board and
- *  its on board two channel 16552 Uart.
- *
- * Copyright (C) 2000 RidgeRun, Inc.
- * Author: RidgeRun, Inc.
- *   glonnon@ridgerun.com, skranz@ridgerun.com, stevej@ridgerun.com
- *
- *  This program is free software; you can redistribute  it and/or modify it
- *  under  the terms of  the GNU General  Public License as published by the
- *  Free Software Foundation;  either version 2 of the  License, or (at your
- *  option) any later version.
- *
- *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
- *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
- *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
- *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
- *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
- *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- *  You should have received a copy of the  GNU General Public License along
- *  with this program; if not, write  to the Free Software Foundation, Inc.,
- *  675 Mass Ave, Cambridge, MA 02139, USA.
- *
- */
-
-// Note:
-//   Serial CHANNELS - 0 is the bottom connector of evb64120A.
-//                       (The one that maps to the "B" channel of the
-//                       board's uart)
-//                     1 is the top connector of evb64120A.
-//                       (The one that maps to the "A" channel of the
-//                       board's uart)
-int DEBUG_CHANNEL = 0;		// See Note Above
-int CONSOLE_CHANNEL = 1;	// See Note Above
-
-#define DUART 0xBD000000	/* Base address of Uart. */
-#define CHANNELOFFSET 0x20	/* DUART+CHANNELOFFSET gets you to the ChanA
-				   register set of the 16552 Uart device.
-				   DUART+0 gets you to the ChanB register set.
-				 */
-#define DUART_DELTA 0x4
-#define FIFO_ENABLE 0x07
-#define INT_ENABLE  0x04	/* default interrupt mask */
-
-#define RBR 0x00
-#define THR 0x00
-#define DLL 0x00
-#define IER 0x01
-#define DLM 0x01
-#define IIR 0x02
-#define FCR 0x02
-#define LCR 0x03
-#define MCR 0x04
-#define LSR 0x05
-#define MSR 0x06
-#define SCR 0x07
-
-#define LCR_DLAB 0x80
-#define XTAL 1843200
-#define LSR_THRE 0x20
-#define LSR_BI   0x10
-#define LSR_DR   0x01
-#define MCR_LOOP 0x10
-#define ACCESS_DELAY 0x10000
-
-/******************************
- Routine:
- Description:
- ******************************/
-int inreg(int channel, int reg)
-{
-	int val;
-	val =
-	    *((volatile unsigned char *) DUART +
-	      (channel * CHANNELOFFSET) + (reg * DUART_DELTA));
-	return val;
-}
-
-/******************************
- Routine:
- Description:
- ******************************/
-void outreg(int channel, int reg, unsigned char val)
-{
-	*((volatile unsigned char *) DUART + (channel * CHANNELOFFSET)
-	  + (reg * DUART_DELTA)) = val;
-}
-
-/******************************
- Routine:
- Description:
-   Initialize the device driver.
- ******************************/
-void serial_init(int channel)
-{
-	/*
-	 * Configure active port, (CHANNELOFFSET already set.)
-	 *
-	 * Set 8 bits, 1 stop bit, no parity.
-	 *
-	 * LCR<7>       0       divisor latch access bit
-	 * LCR<6>       0       break control (1=send break)
-	 * LCR<5>       0       stick parity (0=space, 1=mark)
-	 * LCR<4>       0       parity even (0=odd, 1=even)
-	 * LCR<3>       0       parity enable (1=enabled)
-	 * LCR<2>       0       # stop bits (0=1, 1=1.5)
-	 * LCR<1:0>     11      bits per character(00=5, 01=6, 10=7, 11=8)
-	 */
-	outreg(channel, LCR, 0x3);
-
-	outreg(channel, FCR, FIFO_ENABLE);	/* Enable the FIFO */
-
-	outreg(channel, IER, INT_ENABLE);	/* Enable appropriate interrupts */
-}
-
-/******************************
- Routine:
- Description:
-   Set the baud rate.
- ******************************/
-void serial_set(int channel, unsigned long baud)
-{
-	unsigned char sav_lcr;
-
-	/*
-	 * Enable access to the divisor latches by setting DLAB in LCR.
-	 *
-	 */
-	sav_lcr = inreg(channel, LCR);
-
-#if 0
-	/*
-	 * Set baud rate
-	 */
-	outreg(channel, LCR, LCR_DLAB | sav_lcr);
-	//  outreg(DLL,(XTAL/(16*2*(baud))-2));
-	outreg(channel, DLL, XTAL / (16 * baud));
-	//  outreg(DLM,(XTAL/(16*2*(baud))-2)>>8);
-	outreg(channel, DLM, (XTAL / (16 * baud)) >> 8);
-#else
-	/*
-	 * Note: Set baud rate, hardcoded here for rate of 115200
-	 * since became unsure of above "buad rate" algorithm (??).
-	 */
-	outreg(channel, LCR, 0x83);
-	outreg(channel, DLM, 0x00);	// See note above
-	outreg(channel, DLL, 0x02);	// See note above.
-	outreg(channel, LCR, 0x03);
-#endif
-
-	/*
-	 * Restore line control register
-	 */
-	outreg(channel, LCR, sav_lcr);
-}
-
-
-/******************************
- Routine:
- Description:
-   Transmit a character.
- ******************************/
-void serial_putc(int channel, int c)
-{
-	while ((inreg(channel, LSR) & LSR_THRE) == 0);
-	outreg(channel, THR, c);
-}
-
-/******************************
- Routine:
- Description:
-    Read a received character if one is
-    available.  Return -1 otherwise.
- ******************************/
-int serial_getc(int channel)
-{
-	if (inreg(channel, LSR) & LSR_DR) {
-		return inreg(channel, RBR);
-	}
-	return -1;
-}
-
-/******************************
- Routine:
- Description:
-   Used by embedded gdb client. (example; gdb-stub.c)
- ******************************/
-char getDebugChar()
-{
-	int val;
-	while ((val = serial_getc(DEBUG_CHANNEL)) == -1);	// loop until we get a character in.
-	return (char) val;
-}
-
-/******************************
- Routine:
- Description:
-   Used by embedded gdb target. (example; gdb-stub.c)
- ******************************/
-void putDebugChar(char c)
-{
-	serial_putc(DEBUG_CHANNEL, (int) c);
-}
--- diff/arch/mips/galileo-boards/ev64120/setup.c	2003-07-08 09:55:17.000000000 +0100
+++ source/arch/mips/galileo-boards/ev64120/setup.c	1970-01-01 01:00:00.000000000 +0100
@@ -1,176 +0,0 @@
-/*
- * BRIEF MODULE DESCRIPTION
- * Galileo Evaluation Boards - board dependent boot routines
- *
- * Copyright (C) 2000 RidgeRun, Inc.
- * Author: RidgeRun, Inc.
- *   glonnon@ridgerun.com, skranz@ridgerun.com, stevej@ridgerun.com
- *
- *  This program is free software; you can redistribute  it and/or modify it
- *  under  the terms of  the GNU General  Public License as published by the
- *  Free Software Foundation;  either version 2 of the  License, or (at your
- *  option) any later version.
- *
- *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
- *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
- *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
- *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
- *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
- *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- *  You should have received a copy of the  GNU General Public License along
- *  with this program; if not, write  to the Free Software Foundation, Inc.,
- *  675 Mass Ave, Cambridge, MA 02139, USA.
- *
- */
-#include <linux/config.h>
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/mm.h>
-#include <linux/bootmem.h>
-#include <linux/swap.h>
-#include <linux/ioport.h>
-#include <linux/sched.h>
-#include <linux/interrupt.h>
-#include <linux/pci.h>
-#include <linux/timex.h>
-#include <linux/version.h>
-
-#include <asm/bootinfo.h>
-#include <asm/page.h>
-#include <asm/bootinfo.h>
-#include <asm/io.h>
-#include <asm/irq.h>
-#include <asm/pci.h>
-#include <asm/processor.h>
-#include <asm/ptrace.h>
-#include <asm/reboot.h>
-#include <asm/mc146818rtc.h>
-#include <asm/traps.h>
-
-extern struct rtc_ops no_rtc_ops;
-
-/* These functions are used for rebooting or halting the machine*/
-extern void galileo_machine_restart(char *command);
-extern void galileo_machine_halt(void);
-extern void galileo_machine_power_off(void);
-/*
- *This structure holds pointers to the pci configuration space accesses
- *and interrupts allocating routine for device over the PCI
- */
-extern struct pci_ops galileo_pci_ops;
-
-extern unsigned long mips_machgroup;
-
-char arcs_cmdline[CL_SIZE] = { "console=ttyS0,115200 "
-	    "root=/dev/nfs rw nfsroot=192.168.1.1:/mnt/disk2/fs.gal "
-	    "ip=192.168.1.211:192.168.1.1:::gt::"
-};
-
-//struct eeprom_parameters eeprom_param;
-
-/*
- * This function is added because arch/mips/mm/init.c needs it
- * basically it does nothing
- */
-void prom_free_prom_memory(void)
-{
-}
-
-extern void (*board_time_init) (struct irqaction * irq);
-
-static unsigned char galileo_rtc_read_data(unsigned long addr)
-{
-	return 0;
-}
-
-static void galileo_rtc_write_data(unsigned char data, unsigned long addr)
-{
-}
-
-static int galileo_rtc_bcd_mode(void)
-{
-	return 0;
-}
-
-struct rtc_ops galileo_rtc_ops = {
-	&galileo_rtc_read_data,
-	&galileo_rtc_write_data,
-	&galileo_rtc_bcd_mode
-};
-
-/********************************************************************
- *ev64120_setup -
- *
- *Initializes basic routines and structures pointers, memory size (as
- *given by the bios and saves the command line.
- *
- *
- *Inputs :
- *
- *Outpus :
- *
- *********************************************************************/
-extern void galileo_time_init();
-
-void __init ev64120_setup(void)
-{
-	_machine_restart = galileo_machine_restart;
-	_machine_halt = galileo_machine_halt;
-	_machine_power_off = galileo_machine_power_off;
-
-	rtc_ops = &galileo_rtc_ops;
-
-	board_time_init = galileo_time_init;
-	set_io_port_base(KSEG1);
-
-#ifdef CONFIG_L2_L3_CACHE
-#error "external cache not implemented yet"
-	config_register = read_c0_config();
-	printk("\n\n\nchecking second level cache cp0_config = %08lx\n",
-	       config_register);
-	if (config_register & CONF_SC) {	// second/third level cache available
-		config_register = config_register & (1 << 12);
-		write_c0_config(config_register);
-		printk
-		    ("\n\n\nchecking second level cache c0_config = %08lx\n",
-		     config_register);
-	}
-#endif
-}
-
-const char *get_system_type(void)
-{
-	return "Galileo EV64120A";
-}
-
-/*
- * SetUpBootInfo -
- *
- * This function is called at very first stages of kernel startup.
- * It specifies for the kernel the evaluation board that the linux
- * is running on. Then it saves the eprom parameters that holds the
- * command line, memory size etc...
- *
- * Inputs :
- * argc - nothing
- * argv - holds a pointer to the eprom parameters
- * envp - nothing
- */
-
-void SetUpBootInfo(int argc, char **argv, char **envp)
-{
-	mips_machgroup = MACH_GROUP_GALILEO;
-	mips_machtype = MACH_EV64120A;
-}
-
-void __init prom_init(int a, char **b, char **c, int *d)
-{
-	mips_machgroup = MACH_GROUP_GALILEO;
-	add_memory_region(0, 32 << 20, BOOT_MEM_RAM);
-}
--- diff/arch/mips/galileo-boards/generic/Makefile	2003-07-08 09:55:17.000000000 +0100
+++ source/arch/mips/galileo-boards/generic/Makefile	1970-01-01 01:00:00.000000000 +0100
@@ -1,25 +0,0 @@
-#
-# Carsten Langgaard, carstenl@mips.com
-# Copyright (C) 1999,2000 MIPS Technologies, Inc.  All rights reserved.
-#
-# ########################################################################
-#
-# This program is free software; you can distribute it and/or modify it
-# under the terms of the GNU General Public License (Version 2) as
-# published by the Free Software Foundation.
-#
-# This program is distributed in the hope it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
-# for more details.
-#
-# You should have received a copy of the GNU General Public License along
-# with this program; if not, write to the Free Software Foundation, Inc.,
-# 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
-#
-# #######################################################################
-#
-# Makefile for the MIPS boards generic routines under Linux.
-#
-
-obj-y := reset.o
--- diff/arch/mips/galileo-boards/generic/reset.c	2003-07-08 09:55:17.000000000 +0100
+++ source/arch/mips/galileo-boards/generic/reset.c	1970-01-01 01:00:00.000000000 +0100
@@ -1,72 +0,0 @@
-/*
- * BRIEF MODULE DESCRIPTION
- *	Galileo EV96100 reset routines.
- *
- * Copyright 2000 MontaVista Software Inc.
- * Author: MontaVista Software, Inc.
- *         	ppopov@mvista.com or source@mvista.com
- *
- * This file was derived from Carsten Langgaard's
- * arch/mips/mips-boards/generic/reset.c
- *
- * Carsten Langgaard, carstenl@mips.com
- * Copyright (C) 1999,2000 MIPS Technologies, Inc.  All rights reserved.
- *
- *  This program is free software; you can redistribute  it and/or modify it
- *  under  the terms of  the GNU General  Public License as published by the
- *  Free Software Foundation;  either version 2 of the  License, or (at your
- *  option) any later version.
- *
- *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
- *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
- *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
- *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
- *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
- *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- *  You should have received a copy of the  GNU General Public License along
- *  with this program; if not, write  to the Free Software Foundation, Inc.,
- *  675 Mass Ave, Cambridge, MA 02139, USA.
- */
-#include <linux/sched.h>
-#include <linux/mm.h>
-#include <asm/cacheflush.h>
-#include <asm/io.h>
-#include <asm/processor.h>
-#include <asm/reboot.h>
-#include <asm/system.h>
-
-#include <asm/reboot.h>
-#include <asm/galileo-boards/ev96100.h>
-
-static void mips_machine_restart(char *command);
-static void mips_machine_halt(void);
-
-static void mips_machine_restart(char *command)
-{
-	set_c0_status(ST0_BEV | ST0_ERL);
-	change_c0_config(CONF_CM_CMASK, CONF_CM_UNCACHED);
-	flush_cache_all();
-	write_c0_wired(0);
-	__asm__ __volatile__("jr\t%0"::"r"(0xbfc00000));
-	while (1);
-}
-
-static void mips_machine_halt(void)
-{
-	printk(KERN_NOTICE "You can safely turn off the power\n");
-	while (1)
-		__asm__(".set\tmips3\n\t"
-	                "wait\n\t"
-			".set\tmips0");
-}
-
-void mips_reboot_setup(void)
-{
-	_machine_restart = mips_machine_restart;
-	_machine_halt = mips_machine_halt;
-}
--- diff/arch/mips/gt64120/common/gt_irq.c	2003-08-20 14:16:25.000000000 +0100
+++ source/arch/mips/gt64120/common/gt_irq.c	1970-01-01 01:00:00.000000000 +0100
@@ -1,250 +0,0 @@
-/*
- *
- * Copyright 2001 MontaVista Software Inc.
- * Author: jsun@mvista.com or jsun@junsun.net
- *
- * arch/mips/gt64120/common/gt_irq.c
- *     Interrupt routines for gt64120.  Currently it only handles timer irq.
- *
- * This program is free software; you can redistribute  it and/or modify it
- * under  the terms of  the GNU General  Public License as published by the
- * Free Software Foundation;  either version 2 of the  License, or (at your
- * option) any later version.
- */
-#include <linux/module.h>
-#include <linux/interrupt.h>
-#include <linux/kernel.h>
-#include <asm/ptrace.h>
-#include <linux/config.h>
-#include <linux/sched.h>
-#include <linux/kernel_stat.h>
-#include <asm/io.h>
-#include <asm/gt64120/gt64120.h>
-
-/*
- * These are interrupt handlers for the GT on-chip interrupts.  They
- * all come in to the MIPS on a single interrupt line, and have to
- * be handled and ack'ed differently than other MIPS interrupts.
- */
-
-#if CURRENTLY_UNUSED
-
-struct tq_struct irq_handlers[MAX_CAUSE_REGS][MAX_CAUSE_REG_WIDTH];
-void hook_irq_handler(int int_cause, int bit_num, void *isr_ptr);
-
-/*
- * Hooks IRQ handler to the system. When the system is interrupted
- * the interrupt service routine is called.
- *
- * Inputs :
- * int_cause - The interrupt cause number. In EVB64120 two parameters
- *             are declared, INT_CAUSE_MAIN and INT_CAUSE_HIGH.
- * bit_num   - Indicates which bit number in the cause register
- * isr_ptr   - Pointer to the interrupt service routine
- */
-void hook_irq_handler(int int_cause, int bit_num, void *isr_ptr)
-{
-	irq_handlers[int_cause][bit_num].routine = isr_ptr;
-}
-
-
-/*
- * Enables the IRQ on Galileo Chip
- *
- * Inputs :
- * int_cause - The interrupt cause number. In EVB64120 two parameters
- *             are declared, INT_CAUSE_MAIN and INT_CAUSE_HIGH.
- * bit_num   - Indicates which bit number in the cause register
- *
- * Outputs :
- * 1 if succesful, 0 if failure
- */
-int enable_galileo_irq(int int_cause, int bit_num)
-{
-	if (int_cause == INT_CAUSE_MAIN)
-		SET_REG_BITS(CPU_INTERRUPT_MASK_REGISTER, (1 << bit_num));
-	else if (int_cause == INT_CAUSE_HIGH)
-		SET_REG_BITS(CPU_HIGH_INTERRUPT_MASK_REGISTER,
-			     (1 << bit_num));
-	else
-		return 0;
-
-	return 1;
-}
-
-/*
- * Disables the IRQ on Galileo Chip
- *
- * Inputs :
- * int_cause - The interrupt cause number. In EVB64120 two parameters
- *             are declared, INT_CAUSE_MAIN and INT_CAUSE_HIGH.
- * bit_num   - Indicates which bit number in the cause register
- *
- * Outputs :
- * 1 if succesful, 0 if failure
- */
-int disable_galileo_irq(int int_cause, int bit_num)
-{
-	if (int_cause == INT_CAUSE_MAIN)
-		RESET_REG_BITS(CPU_INTERRUPT_MASK_REGISTER,
-			       (1 << bit_num));
-	else if (int_cause == INT_CAUSE_HIGH)
-		RESET_REG_BITS(CPU_HIGH_INTERRUPT_MASK_REGISTER,
-			       (1 << bit_num));
-	else
-		return 0;
-	return 1;
-}
-#endif				/*  UNUSED  */
-
-/*
- * Interrupt handler for interrupts coming from the Galileo chip.
- * It could be timer interrupt, built in ethernet ports etc...
- */
-static void gt64120_irq(int irq, void *dev_id, struct pt_regs *regs)
-{
-	unsigned int irq_src, int_high_src, irq_src_mask,
-	    int_high_src_mask;
-	int handled;
-
-	GT_READ(GT_INTRCAUSE_OFS, &irq_src);
-	GT_READ(GT_INTRMASK_OFS, &irq_src_mask);
-	GT_READ(GT_HINTRCAUSE_OFS, &int_high_src);
-	GT_READ(GT_HINTRMASK_OFS, &int_high_src_mask);
-	irq_src = irq_src & irq_src_mask;
-	int_high_src = int_high_src & int_high_src_mask;
-
-	handled = 0;
-
-	/* Execute all interrupt handlers */
-	/* Check for timer interrupt */
-	if (irq_src & 0x00000800) {
-		handled = 1;
-		irq_src &= ~0x00000800;
-		//    RESET_REG_BITS (INTERRUPT_CAUSE_REGISTER,BIT8);
-		do_timer(regs);
-	}
-
-	if (irq_src) {
-		printk(KERN_INFO
-		       "Other Galileo interrupt received irq_src %x\n",
-		       irq_src);
-#if CURRENTLY_UNUSED
-		for (count = 0; count < MAX_CAUSE_REG_WIDTH; count++) {
-			if (irq_src & (1 << count)) {
-				if (irq_handlers[INT_CAUSE_MAIN][count].
-				    routine) {
-					queue_task(&irq_handlers
-						   [INT_CAUSE_MAIN][count],
-						   &tq_immediate);
-					mark_bh(IMMEDIATE_BH);
-					handled = 1;
-				}
-			}
-		}
-#endif				/*  UNUSED  */
-	}
-	GT_WRITE(GT_INTRCAUSE_OFS, 0);
-	GT_WRITE(GT_HINTRCAUSE_OFS, 0);
-
-#undef GALILEO_I2O
-#ifdef GALILEO_I2O
-	/*
-	 * Future I2O support.  We currently attach I2O interrupt handlers to
-	 * the Galileo interrupt (int 4) and handle them in do_IRQ.
-	 */
-	if (isInBoundDoorBellInterruptSet()) {
-		printk(KERN_INFO "I2O doorbell interrupt received.\n");
-		handled = 1;
-	}
-
-	if (isInBoundPostQueueInterruptSet()) {
-		printk(KERN_INFO "I2O Queue interrupt received.\n");
-		handled = 1;
-	}
-
-	/*
-	 * This normally would be outside of the ifdef, but since we're
-	 * handling I2O outside of this handler, this printk shows up every
-	 * time we get a valid I2O interrupt.  So turn this off for now.
-	 */
-	if (handled == 0) {
-		if (counter < 50) {
-			printk("Spurious Galileo interrupt...\n");
-			counter++;
-		}
-	}
-#endif
-}
-
-/*
- * Initializes timer using galileo's built in timer.
- */
-#ifdef CONFIG_SYSCLK_100
-#define Sys_clock (100 * 1000000)	// 100 MHz
-#endif
-#ifdef CONFIG_SYSCLK_83
-#define Sys_clock (83.333 * 1000000)	// 83.333 MHz
-#endif
-#ifdef CONFIG_SYSCLK_75
-#define Sys_clock (75 * 1000000)	// 75 MHz
-#endif
-
-/*
- * This will ignore the standard MIPS timer interrupt handler
- * that is passed in as *irq (=irq0 in ../kernel/time.c).
- * We will do our own timer interrupt handling.
- */
-void gt64120_time_init(void)
-{
-	extern irq_desc_t irq_desc[NR_IRQS];
-	static struct irqaction timer;
-
-	/* Disable timer first */
-	GT_WRITE(GT_TC_CONTROL_OFS, 0);
-	/* Load timer value for 100 Hz */
-	GT_WRITE(GT_TC3_OFS, Sys_clock / 100);
-
-	/*
-	 * Create the IRQ structure entry for the timer.  Since we're too early
-	 * in the boot process to use the "request_irq()" call, we'll hard-code
-	 * the values to the correct interrupt line.
-	 */
-	timer.handler = &gt64120_irq;
-	timer.flags = SA_SHIRQ | SA_INTERRUPT;
-	timer.name = "timer";
-	timer.dev_id = NULL;
-	timer.next = NULL;
-	timer.mask = 0;
-	irq_desc[TIMER].action = &timer;
-
-	enable_irq(TIMER);
-
-	/* Enable timer ints */
-	GT_WRITE(GT_TC_CONTROL_OFS, 0xc0);
-	/* clear Cause register first */
-	GT_WRITE(GT_INTRCAUSE_OFS, 0x0);
-	/* Unmask timer int */
-	GT_WRITE(GT_INTRMASK_OFS, 0x800);
-	/* Clear High int register */
-	GT_WRITE(GT_HINTRCAUSE_OFS, 0x0);
-	/* Mask All interrupts at High cause interrupt */
-	GT_WRITE(GT_HINTRMASK_OFS, 0x0);
-}
-
-void gt64120_irq_init(void)
-{
-#if CURRENTLY_UNUSED
-	int i, j;
-
-	/* Reset irq handlers pointers to NULL */
-	for (i = 0; i < MAX_CAUSE_REGS; i++) {
-		for (j = 0; j < MAX_CAUSE_REG_WIDTH; j++) {
-			irq_handlers[i][j].next = NULL;
-			irq_handlers[i][j].sync = 0;
-			irq_handlers[i][j].routine = NULL;
-			irq_handlers[i][j].data = NULL;
-		}
-	}
-#endif
-}
--- diff/arch/mips/jazz/floppy-jazz.c	2003-08-20 14:16:25.000000000 +0100
+++ source/arch/mips/jazz/floppy-jazz.c	1970-01-01 01:00:00.000000000 +0100
@@ -1,149 +0,0 @@
-/*
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Low-level floppy stuff for Jazz family machines.
- *
- * Copyright (C) 1998 by Ralf Baechle
- */
-#include <linux/delay.h>
-#include <linux/init.h>
-#include <linux/linkage.h>
-#include <linux/types.h>
-#include <linux/mm.h>
-#include <asm/addrspace.h>
-#include <asm/jazz.h>
-#include <asm/jazzdma.h>
-#include <asm/pgtable.h>
-#include <asm/floppy.h>
-
-static unsigned char jazz_fd_inb(unsigned int port)
-{
-	unsigned char c;
-
-	c = *(volatile unsigned char *) port;
-	udelay(1);
-
-	return c;
-}
-
-static void jazz_fd_outb(unsigned char value, unsigned int port)
-{
-	*(volatile unsigned char *) port = value;
-}
-
-/*
- * How to access the floppy DMA functions.
- */
-static void jazz_fd_enable_dma(int channel)
-{
-	vdma_enable(JAZZ_FLOPPY_DMA);
-}
-
-static void jazz_fd_disable_dma(int channel)
-{
-	vdma_disable(JAZZ_FLOPPY_DMA);
-}
-
-static int jazz_fd_request_dma(int channel)
-{
-	return 0;
-}
-
-static void jazz_fd_free_dma(int channel)
-{
-}
-
-static void jazz_fd_clear_dma_ff(int channel)
-{
-}
-
-static void jazz_fd_set_dma_mode(int channel, char mode)
-{
-	vdma_set_mode(JAZZ_FLOPPY_DMA, mode);
-}
-
-static void jazz_fd_set_dma_addr(int channel, unsigned int a)
-{
-	vdma_set_addr(JAZZ_FLOPPY_DMA, vdma_phys2log(PHYSADDR(a)));
-}
-
-static void jazz_fd_set_dma_count(int channel, unsigned int count)
-{
-	vdma_set_count(JAZZ_FLOPPY_DMA, count);
-}
-
-static int jazz_fd_get_dma_residue(int channel)
-{
-	return vdma_get_residue(JAZZ_FLOPPY_DMA);
-}
-
-static void jazz_fd_enable_irq(int irq)
-{
-}
-
-static void jazz_fd_disable_irq(int irq)
-{
-}
-
-static unsigned long jazz_fd_getfdaddr1(void)
-{
-	return JAZZ_FDC_BASE;
-}
-
-static unsigned long jazz_fd_dma_mem_alloc(unsigned long size)
-{
-	unsigned long mem;
-
-	mem = __get_dma_pages(GFP_KERNEL, get_order(size));
-	if(!mem)
-		return 0;
-	vdma_alloc(PHYSADDR(mem), size);	/* XXX error checking */
-
-	return mem;
-}
-
-static void jazz_fd_dma_mem_free(unsigned long addr,
-                                        unsigned long size)
-{
-	vdma_free(vdma_phys2log(PHYSADDR(addr)));
-	free_pages(addr, get_order(size));
-}
-
-static unsigned long jazz_fd_drive_type(unsigned long n)
-{
-	/* XXX This is wrong for machines with ED 2.88mb disk drives like the
-	   Olivetti M700.  Anyway, we should suck this from the ARC
-	   firmware.  */
-	if (n == 0)
-		return 4;	/* 3,5", 1.44mb */
-
-	return 0;
-}
-
-struct fd_ops jazz_fd_ops = {
-	/*
-	 * How to access the floppy controller's ports
-	 */
-	jazz_fd_inb,
-	jazz_fd_outb,
-	/*
-	 * How to access the floppy DMA functions.
-	 */
-	jazz_fd_enable_dma,
-	jazz_fd_disable_dma,
-	jazz_fd_request_dma,
-	jazz_fd_free_dma,
-	jazz_fd_clear_dma_ff,
-	jazz_fd_set_dma_mode,
-	jazz_fd_set_dma_addr,
-	jazz_fd_set_dma_count,
-	jazz_fd_get_dma_residue,
-	jazz_fd_enable_irq,
-	jazz_fd_disable_irq,
-	jazz_fd_getfdaddr1,
-	jazz_fd_dma_mem_alloc,
-	jazz_fd_dma_mem_free,
-	jazz_fd_drive_type
-};
--- diff/arch/mips/jazz/jazz-ksyms.c	2003-08-20 14:16:36.000000000 +0100
+++ source/arch/mips/jazz/jazz-ksyms.c	1970-01-01 01:00:00.000000000 +0100
@@ -1,16 +0,0 @@
-/*
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (C) 1996, 1997, 1998, 2000, 2001, 2003 by Ralf Baechle
- */
-#include <linux/module.h>
-
-#include <asm/dma.h>
-#include <asm/io.h>
-#include <asm/jazzdma.h>
-
-EXPORT_SYMBOL(vdma_alloc);
-EXPORT_SYMBOL(vdma_free);
-EXPORT_SYMBOL(vdma_log2phys);
--- diff/arch/mips/jazz/kbd-jazz.c	2003-08-20 14:16:25.000000000 +0100
+++ source/arch/mips/jazz/kbd-jazz.c	1970-01-01 01:00:00.000000000 +0100
@@ -1,99 +0,0 @@
-/*
- * Low-level hardware access stuff for Jazz family machines.
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (C) 1995, 1996, 1997, 1998 by Ralf Baechle
- */
-#include <linux/sched.h>
-#include <asm/jazz.h>
-
-#define jazz_kh ((keyboard_hardware *) JAZZ_KEYBOARD_ADDRESS)
-
-static void jazz_request_region(void)
-{
-	/* No I/O ports are being used on Jazz.  */
-}
-
-static int jazz_request_irq(void (*handler)(int, void *, struct pt_regs *))
-{
-	int res;
-
-	res = request_irq(JAZZ_KEYBOARD_IRQ, handler, 0, "keyboard", NULL);
-	if (res != 0)
-		return res;
-
-	/* jazz_request_irq() should do this ...  */
-	r4030_write_reg16(JAZZ_IO_IRQ_ENABLE,
-	                  r4030_read_reg16(JAZZ_IO_IRQ_ENABLE)
-	                  | JAZZ_IE_KEYBOARD);
-
-	return 0;
-}
-
-static int jazz_aux_request_irq(void (*handler)(int, void *, struct pt_regs *))
-{
-	int ret;
-
-	ret = request_irq(JAZZ_MOUSE_IRQ, handler, 0, "PS/2 Mouse", NULL);
-	if (ret != 0)
-		return ret;
-
-		r4030_write_reg16(JAZZ_IO_IRQ_ENABLE,
-				  r4030_read_reg16(JAZZ_IO_IRQ_ENABLE) |
-				  JAZZ_IE_MOUSE);
-	return 0;
-}
-
-static void jazz_aux_free_irq(void)
-{
-	r4030_write_reg16(JAZZ_IO_IRQ_ENABLE,
-	                  r4030_read_reg16(JAZZ_IO_IRQ_ENABLE)
-	                  | JAZZ_IE_MOUSE);
-	free_irq(JAZZ_MOUSE_IRQ, NULL);
-}
-
-static unsigned char jazz_read_input(void)
-{
-	return jazz_kh->data;
-}
-
-static void jazz_write_output(unsigned char val)
-{
-	int status;
-
-	do {
-		status = jazz_kh->command;
-	} while (status & KBD_STAT_IBF);
-	jazz_kh->data = val;
-}
-
-static void jazz_write_command(unsigned char val)
-{
-	int status;
-
-	do {
-		status = jazz_kh->command;
-	} while (status & KBD_STAT_IBF);
-	jazz_kh->command = val;
-}
-
-static unsigned char jazz_read_status(void)
-{
-	return jazz_kh->command;
-}
-
-struct kbd_ops jazz_kbd_ops = {
-	jazz_request_region,
-	jazz_request_irq,
-
-	jazz_aux_request_irq,
-	jazz_aux_free_irq,
-
-	jazz_read_input,
-	jazz_write_output,
-	jazz_write_command,
-	jazz_read_status
-};
--- diff/arch/mips/jazz/rtc-jazz.c	2002-10-16 04:26:42.000000000 +0100
+++ source/arch/mips/jazz/rtc-jazz.c	1970-01-01 01:00:00.000000000 +0100
@@ -1,35 +0,0 @@
-/*
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * RTC routines for Jazz style attached Dallas chip.
- *
- * Copyright (C) 1998, 2001 by Ralf Baechle
- */
-#include <linux/mc146818rtc.h>
-#include <asm/io.h>
-#include <asm/jazz.h>
-
-static unsigned char jazz_rtc_read_data(unsigned long addr)
-{
-	outb_p(addr, RTC_PORT(0));
-	return *(char *)JAZZ_RTC_BASE;
-}
-
-static void jazz_rtc_write_data(unsigned char data, unsigned long addr)
-{
-	outb_p(addr, RTC_PORT(0));
-	*(char *)JAZZ_RTC_BASE = data;
-}
-
-static int jazz_rtc_bcd_mode(void)
-{
-	return 0;
-}
-
-struct rtc_ops jazz_rtc_ops = {
-	&jazz_rtc_read_data,
-	&jazz_rtc_write_data,
-	&jazz_rtc_bcd_mode
-};
--- diff/arch/mips/jmr3927/rbhma3100/rtc.c	2003-07-08 09:55:17.000000000 +0100
+++ source/arch/mips/jmr3927/rbhma3100/rtc.c	1970-01-01 01:00:00.000000000 +0100
@@ -1,56 +0,0 @@
-/*
- * Copyright 2001 MontaVista Software Inc.
- * Author: MontaVista Software, Inc.
- *              ahennessy@mvista.com
- *
- * RTC routines for Dallas chip.
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (C) 200-2001 Toshiba Corporation
- *
- *  This program is free software; you can redistribute  it and/or modify it
- *  under  the terms of  the GNU General  Public License as published by the
- *  Free Software Foundation;  either version 2 of the  License, or (at your
- *  option) any later version.
- *
- *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
- *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
- *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
- *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
- *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
- *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- *  You should have received a copy of the  GNU General Public License along
- *  with this program; if not, write  to the Free Software Foundation, Inc.,
- *  675 Mass Ave, Cambridge, MA 02139, USA.
- */
-#include <asm/mc146818rtc.h>	/* bad name... */
-#include <asm/jmr3927/jmr3927.h>
-
-static unsigned char jmr3927_rtc_read_data(unsigned long addr)
-{
-	return jmr3927_nvram_in(addr);
-}
-
-static void jmr3927_rtc_write_data(unsigned char data, unsigned long addr)
-{
-	jmr3927_nvram_out(data, addr);
-}
-
-static int jmr3927_rtc_bcd_mode(void)
-{
-	return 1;
-}
-
-struct rtc_ops jmr3927_rtc_ops = {
-	&jmr3927_rtc_read_data,
-	&jmr3927_rtc_write_data,
-	&jmr3927_rtc_bcd_mode
-};
--- diff/arch/mips/kernel/pci-dma.c	2003-08-20 14:16:25.000000000 +0100
+++ source/arch/mips/kernel/pci-dma.c	1970-01-01 01:00:00.000000000 +0100
@@ -1,64 +0,0 @@
-/*
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (C) 2000  Ani Joshi <ajoshi@unixbox.com>
- * Copyright (C) 2000, 2001  Ralf Baechle <ralf@gnu.org>
- * swiped from i386, and cloned for MIPS by Geert, polished by Ralf.
- */
-#include <linux/config.h>
-#include <linux/types.h>
-#include <linux/mm.h>
-#include <linux/module.h>
-#include <linux/string.h>
-#include <linux/pci.h>
-
-#include <asm/io.h>
-
-#ifndef UNCAC_BASE	/* Hack ... */
-#define UNCAC_BASE	0x9000000000000000UL
-#endif
-
-void *dma_alloc_coherent(struct device *dev, size_t size,
-			 dma_addr_t * dma_handle, int gfp)
-{
-	void *ret;
-	/* ignore region specifiers */
-	gfp &= ~(__GFP_DMA | __GFP_HIGHMEM);
-
-	if (dev == NULL || (*dev->dma_mask < 0xffffffff))
-		gfp |= GFP_DMA;
-	ret = (void *) __get_free_pages(gfp, get_order(size));
-
-	if (ret != NULL) {
-		memset(ret, 0, size);
-#if 0	/* Broken support for some platforms ...  */
-		if (hwdev)
-			bus = hwdev->bus;
-		*dma_handle = bus_to_baddr(bus, __pa(ret));
-#else
-		*dma_handle = virt_to_phys(ret);
-#endif
-#ifdef CONFIG_NONCOHERENT_IO
-		dma_cache_wback_inv((unsigned long) ret, size);
-		ret = UNCAC_ADDR(ret);
-#endif
-	}
-
-	return ret;
-}
-
-void dma_free_coherent(struct device *dev, size_t size,
-                       void *vaddr, dma_addr_t dma_handle)
-{
-	unsigned long addr = (unsigned long) vaddr;
-
-#ifdef CONFIG_NONCOHERENT_IO
-	addr = CAC_ADDR(addr);
-#endif
-	free_pages(addr, get_order(size));
-}
-
-EXPORT_SYMBOL(pci_alloc_consistent);
-EXPORT_SYMBOL(pci_free_consistent);
--- diff/arch/mips/lib-32/strlen_user.S	2003-08-20 14:16:36.000000000 +0100
+++ source/arch/mips/lib-32/strlen_user.S	1970-01-01 01:00:00.000000000 +0100
@@ -1,40 +0,0 @@
-/*
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (c) 1996, 1998, 1999 by Ralf Baechle
- * Copyright (c) 1999 Silicon Graphics, Inc.
- */
-#include <asm/asm.h>
-#include <asm/offset.h>
-#include <asm/regdef.h>
-#include <asm/sgidefs.h>
-
-#define EX(insn,reg,addr,handler)			\
-9:	insn	reg, addr;				\
-	.section __ex_table,"a";			\
-	PTR	9b, handler;				\
-	.previous
-
-/*
- * Return the size of a string (including the ending 0)
- *
- * Return 0 for error
- */
-LEAF(__strlen_user_asm)
-	LONG_L		v0, TI_ADDR_LIMIT($28)	# pointer ok?
-	and		v0, a0
-	bltz		v0, fault
-
-FEXPORT(__strlen_user_nocheck_asm)
-	move		v0, a0
-1:	EX(lb, t0, (v0), fault)
-	PTR_ADDIU	v0, 1
-	bnez		t0, 1b
-	PTR_SUBU	v0, a0
-	jr		ra
-	END(__strlen_user_asm)
-
-fault:	move	v0, zero
-	jr	ra
--- diff/arch/mips/lib-32/strncpy_user.S	2003-08-20 14:16:36.000000000 +0100
+++ source/arch/mips/lib-32/strncpy_user.S	1970-01-01 01:00:00.000000000 +0100
@@ -1,58 +0,0 @@
-/*
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (c) 1996, 1999 by Ralf Baechle
- */
-#include <linux/errno.h>
-#include <asm/asm.h>
-#include <asm/offset.h>
-#include <asm/regdef.h>
-
-#define EX(insn,reg,addr,handler)			\
-9:	insn	reg, addr;				\
-	.section __ex_table,"a";			\
-	PTR	9b, handler;				\
-	.previous
-
-/*
- * Returns: -EFAULT if exception before terminator, N if the entire
- * buffer filled, else strlen.
- */
-
-/*
- * Ugly special case have to check: we might get passed a user space
- * pointer which wraps into the kernel space.  We don't deal with that.  If
- * it happens at most some bytes of the exceptions handlers will be copied.
- */
-
-LEAF(__strncpy_from_user_asm)
-	LONG_L		v0, TI_ADDR_LIMIT($28)	# pointer ok?
-	and		v0, a1
-	bltz		v0, fault
-
-FEXPORT(__strncpy_from_user_nocheck_asm)
-	move		v0, zero
-	move		v1, a1
-	.set		noreorder
-1:	EX(lbu, t0, (v1), fault)
-	PTR_ADDIU	v1, 1
-	beqz		t0, 2f
-	 sb		t0, (a0)
-	PTR_ADDIU	v0, 1
-	bne		v0, a2, 1b
-	 PTR_ADDIU	a0, 1
-	.set		reorder
-2:	PTR_ADDU	t0, a1, v0
-	xor		t0, a1
-	bltz		t0, fault
-	jr		ra			# return n
-	END(__strncpy_from_user_asm)
-
-fault:	li		v0, -EFAULT
-	jr		ra
-
-	.section	__ex_table,"a"
-	PTR		1b, fault
-	.previous
--- diff/arch/mips/lib-32/strnlen_user.S	2003-08-20 14:16:36.000000000 +0100
+++ source/arch/mips/lib-32/strnlen_user.S	1970-01-01 01:00:00.000000000 +0100
@@ -1,46 +0,0 @@
-/*
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (c) 1996, 1998, 1999 by Ralf Baechle
- * Copyright (c) 1999 Silicon Graphics, Inc.
- */
-#include <asm/asm.h>
-#include <asm/offset.h>
-#include <asm/regdef.h>
-#include <asm/sgidefs.h>
-
-#define EX(insn,reg,addr,handler)			\
-9:	insn	reg, addr;				\
-	.section __ex_table,"a";			\
-	PTR	9b, handler;				\
-	.previous
-
-/*
- * Return the size of a string including the ending NUL character upto a
- * maximum of a1 or 0 in case of error.
- *
- * Note: for performance reasons we deliberately accept that a user may
- *       make strlen_user and strnlen_user access the first few KSEG0
- *       bytes.  There's nothing secret there.  On 64-bit accessing beyond
- *       the maximum is a tad hairier ...
- */
-LEAF(__strnlen_user_asm)
-	LONG_L		v0, TI_ADDR_LIMIT($28)	# pointer ok?
-	and		v0, a0
-	bltz		v0, fault
-
-FEXPORT(__strnlen_user_nocheck_asm)
-	move		v0, a0
-	PTR_ADDU	a1, a0			# stop pointer
-1:	beq		v0, a1, 1f		# limit reached?
-	EX(lb, t0, (v0), fault)
-	PTR_ADDU	v0, 1
-	bnez		t0, 1b
-1:	PTR_SUBU	v0, a0
-	jr		ra
-	END(__strnlen_user_asm)
-
-fault:	move		v0, zero
-	jr		ra
--- diff/arch/mips/lib-64/strlen_user.S	2003-08-20 14:16:36.000000000 +0100
+++ source/arch/mips/lib-64/strlen_user.S	1970-01-01 01:00:00.000000000 +0100
@@ -1,40 +0,0 @@
-/*
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (c) 1996, 1998, 1999 by Ralf Baechle
- * Copyright (c) 1999 Silicon Graphics, Inc.
- */
-#include <asm/asm.h>
-#include <asm/offset.h>
-#include <asm/regdef.h>
-#include <asm/sgidefs.h>
-
-#define EX(insn,reg,addr,handler)			\
-9:	insn	reg, addr;				\
-	.section __ex_table,"a";			\
-	PTR	9b, handler;				\
-	.previous
-
-/*
- * Return the size of a string (including the ending 0)
- *
- * Return 0 for error
- */
-LEAF(__strlen_user_asm)
-	LONG_L		v0, TI_ADDR_LIMIT($28)	# pointer ok?
-	and		v0, a0
-	bnez		v0, fault
-
-FEXPORT(__strlen_user_nocheck_asm)
-	move		v0, a0
-1:	EX(lb, t0, (v0), fault)
-	PTR_ADDIU	v0, 1
-	bnez		t0, 1b
-	PTR_SUBU	v0, a0
-	jr		ra
-	END(__strlen_user_asm)
-
-fault:	move		v0, zero
-	jr		ra
--- diff/arch/mips/lib-64/strncpy_user.S	2003-08-20 14:16:36.000000000 +0100
+++ source/arch/mips/lib-64/strncpy_user.S	1970-01-01 01:00:00.000000000 +0100
@@ -1,58 +0,0 @@
-/*
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (c) 1996, 1999 by Ralf Baechle
- */
-#include <linux/errno.h>
-#include <asm/asm.h>
-#include <asm/offset.h>
-#include <asm/regdef.h>
-
-#define EX(insn,reg,addr,handler)			\
-9:	insn	reg, addr;				\
-	.section __ex_table,"a";			\
-	PTR	9b, handler;				\
-	.previous
-
-/*
- * Returns: -EFAULT if exception before terminator, N if the entire
- * buffer filled, else strlen.
- */
-
-/*
- * Ugly special case have to check: we might get passed a user space
- * pointer which wraps into the kernel space.  We don't deal with that.  If
- * it happens at most some bytes of the exceptions handlers will be copied.
- */
-
-LEAF(__strncpy_from_user_asm)
-	LONG_L		v0, TI_ADDR_LIMIT($28)	# pointer ok?
-	and		v0, a1
-	bnez		v0, fault
-
-FEXPORT(__strncpy_from_user_nocheck_asm)
-	move		v0, zero
-	move		v1, a1
-	.set		noreorder
-1:	EX(lbu, t0, (v1), fault)
-	PTR_ADDIU	v1, 1
-	beqz		t0, 2f
-	 sb		t0, (a0)
-	PTR_ADDIU	v0, 1
-	bne		v0, a2, 1b
-	 PTR_ADDIU	a0, 1
-	.set		reorder
-2:	PTR_ADDU	t0, a1, v0
-	xor		t0, a1
-	bltz		t0, fault
-	jr		ra			# return n
-	END(__strncpy_from_user_asm)
-
-fault:	li		v0, -EFAULT
-	jr		ra
-
-	.section	__ex_table,"a"
-	PTR		1b, fault
-	.previous
--- diff/arch/mips/lib-64/strnlen_user.S	2003-08-20 14:16:36.000000000 +0100
+++ source/arch/mips/lib-64/strnlen_user.S	1970-01-01 01:00:00.000000000 +0100
@@ -1,46 +0,0 @@
-/*
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (c) 1996, 1998, 1999 by Ralf Baechle
- * Copyright (c) 1999 Silicon Graphics, Inc.
- */
-#include <asm/asm.h>
-#include <asm/offset.h>
-#include <asm/regdef.h>
-#include <asm/sgidefs.h>
-
-#define EX(insn,reg,addr,handler)			\
-9:	insn	reg, addr;				\
-	.section __ex_table,"a";			\
-	PTR	9b, handler;				\
-	.previous
-
-/*
- * Return the size of a string including the ending NUL character upto a
- * maximum of a1 or 0 in case of error.
- *
- * Note: for performance reasons we deliberately accept that a user may
- *       make strlen_user and strnlen_user access the first few KSEG0
- *       bytes.  There's nothing secret there.  On 64-bit accessing beyond
- *       the maximum is a tad hairier ...
- */
-LEAF(__strnlen_user_asm)
-	LONG_L		v0, TI_ADDR_LIMIT($28)	# pointer ok?
-	and		v0, a0
-	bnez		v0, fault
-
-FEXPORT(__strnlen_user_nocheck_asm)
-	move		v0, a0
-	PTR_ADDU	a1, a0			# stop pointer
-1:	beq		v0, a1, 1f		# limit reached?
-	EX(lb, t0, (v0), fault)
-	PTR_ADDU	v0, 1
-	bnez		t0, 1b
-1:	PTR_SUBU	v0, a0
-	jr		ra
-	END(__strnlen_user_asm)
-
-fault:	move		v0, zero
-	jr		ra
--- diff/arch/mips/lib/floppy-no.c	2003-07-08 09:55:17.000000000 +0100
+++ source/arch/mips/lib/floppy-no.c	1970-01-01 01:00:00.000000000 +0100
@@ -1,57 +0,0 @@
-/*
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Dummy file for machines without standard floppy drives.
- *
- * Copyright (C) 1998 by Ralf Baechle
- */
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/mm.h>
-#include <asm/floppy.h>
-
-/*
- * How to access the FDC's registers.
- */
-static void no_fd_dummy(void)
-{
-	panic("no_fd_dummy called - shouldn't happen");
-}
-
-static unsigned long no_fd_getfdaddr1(void)
-{
-	return (unsigned long)-1;	/* No FDC nowhere ... */
-}
-
-static unsigned long no_fd_drive_type(unsigned long n)
-{
-	return 0;
-}
-
-struct fd_ops no_fd_ops = {
-	/*
-	 * How to access the floppy controller's ports
-	 */
-	(void *) no_fd_dummy,
-	(void *) no_fd_dummy,
-	/*
-	 * How to access the floppy DMA functions.
-	 */
-	(void *) no_fd_dummy,
-	(void *) no_fd_dummy,
-	(void *) no_fd_dummy,
-	(void *) no_fd_dummy,
-	(void *) no_fd_dummy,
-	(void *) no_fd_dummy,
-	(void *) no_fd_dummy,
-	(void *) no_fd_dummy,
-	(void *) no_fd_dummy,
-	(void *) no_fd_dummy,
-	(void *) no_fd_dummy,
-	no_fd_getfdaddr1,
-	(void *) no_fd_dummy,
-	(void *) no_fd_dummy,
-	no_fd_drive_type
-};
--- diff/arch/mips/lib/floppy-std.c	2003-08-20 14:16:25.000000000 +0100
+++ source/arch/mips/lib/floppy-std.c	1970-01-01 01:00:00.000000000 +0100
@@ -1,149 +0,0 @@
-/*
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Access the floppy hardware on PC style hardware
- *
- * Copyright (C) 1996, 1997, 1998, 2003 by Ralf Baechle
- */
-#include <linux/delay.h>
-#include <linux/init.h>
-#include <linux/ioport.h>
-#include <linux/sched.h>
-#include <linux/kernel.h>
-#include <linux/linkage.h>
-#include <linux/types.h>
-#include <linux/mm.h>
-
-#include <asm/bootinfo.h>
-#include <asm/cachectl.h>
-#include <asm/dma.h>
-#include <asm/floppy.h>
-#include <asm/io.h>
-#include <asm/irq.h>
-#include <asm/pgtable.h>
-
-/*
- * How to access the FDC's registers.
- */
-static unsigned char std_fd_inb(unsigned int port)
-{
-	return inb_p(port);
-}
-
-static void std_fd_outb(unsigned char value, unsigned int port)
-{
-	outb_p(value, port);
-}
-
-/*
- * How to access the floppy DMA functions.
- */
-static void std_fd_enable_dma(int channel)
-{
-	enable_dma(channel);
-}
-
-static void std_fd_disable_dma(int channel)
-{
-	disable_dma(channel);
-}
-
-static int std_fd_request_dma(int channel)
-{
-	return request_dma(channel, "floppy");
-}
-
-static void std_fd_free_dma(int channel)
-{
-	free_dma(channel);
-}
-
-static void std_fd_clear_dma_ff(int channel)
-{
-	clear_dma_ff(channel);
-}
-
-static void std_fd_set_dma_mode(int channel, char mode)
-{
-	set_dma_mode(channel, mode);
-}
-
-static void std_fd_set_dma_addr(int channel, unsigned int addr)
-{
-	set_dma_addr(channel, addr);
-}
-
-static void std_fd_set_dma_count(int channel, unsigned int count)
-{
-	set_dma_count(channel, count);
-}
-
-static int std_fd_get_dma_residue(int channel)
-{
-	return get_dma_residue(channel);
-}
-
-static void std_fd_enable_irq(int irq)
-{
-	enable_irq(irq);
-}
-
-static void std_fd_disable_irq(int irq)
-{
-	disable_irq(irq);
-}
-
-static unsigned long std_fd_getfdaddr1(void)
-{
-	return 0x3f0;
-}
-
-static unsigned long std_fd_dma_mem_alloc(unsigned long size)
-{
-	unsigned long mem;
-
-	mem = __get_dma_pages(GFP_KERNEL, get_order(size));
-
-	return mem;
-}
-
-static void std_fd_dma_mem_free(unsigned long addr, unsigned long size)
-{
-	free_pages(addr, get_order(size));
-}
-
-static unsigned long std_fd_drive_type(unsigned long n)
-{
-	if (n == 0)
-		return 4;	/* 3,5", 1.44mb */
-
-	return 0;
-}
-
-struct fd_ops std_fd_ops = {
-	/*
-	 * How to access the floppy controller's ports
-	 */
-	std_fd_inb,
-	std_fd_outb,
-	/*
-	 * How to access the floppy DMA functions.
-	 */
-	std_fd_enable_dma,
-	std_fd_disable_dma,
-	std_fd_request_dma,
-	std_fd_free_dma,
-	std_fd_clear_dma_ff,
-	std_fd_set_dma_mode,
-	std_fd_set_dma_addr,
-	std_fd_set_dma_count,
-	std_fd_get_dma_residue,
-	std_fd_enable_irq,
-	std_fd_disable_irq,
-        std_fd_getfdaddr1,
-        std_fd_dma_mem_alloc,
-        std_fd_dma_mem_free,
-	std_fd_drive_type
-};
--- diff/arch/mips/lib/ide-no.c	2003-07-08 09:55:17.000000000 +0100
+++ source/arch/mips/lib/ide-no.c	1970-01-01 01:00:00.000000000 +0100
@@ -1,35 +0,0 @@
-/*
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Stub IDE routines to keep Linux from crashing on machine which don't
- * have IDE like the Indy.
- *
- * Copyright (C) 1998, 1999 by Ralf Baechle
- */
-#include <linux/hdreg.h>
-#include <linux/kernel.h>
-#include <linux/ide.h>
-#include <asm/hdreg.h>
-
-static int no_ide_default_irq(ide_ioreg_t base)
-{
-	return 0;
-}
-
-static ide_ioreg_t no_ide_default_io_base(int index)
-{
-	return 0;
-}
-
-static void no_ide_init_hwif_ports (hw_regs_t *hw, ide_ioreg_t data_port,
-                                    ide_ioreg_t ctrl_port, int *irq)
-{
-}
-
-struct ide_ops no_ide_ops = {
-	&no_ide_default_irq,
-	&no_ide_default_io_base,
-	&no_ide_init_hwif_ports
-};
--- diff/arch/mips/lib/ide-std.c	2003-07-08 09:55:17.000000000 +0100
+++ source/arch/mips/lib/ide-std.c	1970-01-01 01:00:00.000000000 +0100
@@ -1,63 +0,0 @@
-/*
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * IDE routines for typical pc-like standard configurations.
- *
- * Copyright (C) 1998, 1999, 2001 by Ralf Baechle
- */
-#include <linux/sched.h>
-#include <linux/ide.h>
-#include <linux/ioport.h>
-#include <linux/hdreg.h>
-#include <asm/hdreg.h>
-
-static int std_ide_default_irq(ide_ioreg_t base)
-{
-	switch (base) {
-		case 0x1f0: return 14;
-		case 0x170: return 15;
-		case 0x1e8: return 11;
-		case 0x168: return 10;
-		case 0x1e0: return 8;
-		case 0x160: return 12;
-		default:
-			return 0;
-	}
-}
-
-static ide_ioreg_t std_ide_default_io_base(int index)
-{
-	static unsigned long ata_io_base[MAX_HWIFS] = {
-		0x1f0, 0x170, 0x1e8, 0x168, 0x1e0, 0x160
-	};
-
-	return ata_io_base[index];
-}
-
-static void std_ide_init_hwif_ports (hw_regs_t *hw, ide_ioreg_t data_port,
-                                     ide_ioreg_t ctrl_port, int *irq)
-{
-	ide_ioreg_t reg = data_port;
-	int i;
-
-	for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++) {
-		hw->io_ports[i] = reg;
-		reg += 1;
-	}
-	if (ctrl_port) {
-		hw->io_ports[IDE_CONTROL_OFFSET] = ctrl_port;
-	} else {
-		hw->io_ports[IDE_CONTROL_OFFSET] = hw->io_ports[IDE_DATA_OFFSET] + 0x206;
-	}
-	if (irq != NULL)
-		*irq = 0;
-	hw->io_ports[IDE_IRQ_OFFSET] = 0;
-}
-
-struct ide_ops std_ide_ops = {
-	&std_ide_default_irq,
-	&std_ide_default_io_base,
-	&std_ide_init_hwif_ports
-};
--- diff/arch/mips/lib/rtc-no.c	2003-08-20 14:16:25.000000000 +0100
+++ source/arch/mips/lib/rtc-no.c	1970-01-01 01:00:00.000000000 +0100
@@ -1,30 +0,0 @@
-/*
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Stub RTC routines to keep Linux from crashing on machine which don't
- * have a RTC chip.
- *
- * Copyright (C) 1998, 2001, 2003 by Ralf Baechle
- */
-#include <linux/kernel.h>
-#include <linux/mc146818rtc.h>
-
-static unsigned int shouldnt_happen(void)
-{
-	static int called;
-
-	if (called) {
-		called = 1;
-		printk(KERN_DEBUG "RTC functions called - shouldn't happen\n");
-	}
-
-	return 0;
-}
-
-struct rtc_ops no_rtc_ops = {
-	.rtc_read_data  = (void *) &shouldnt_happen,
-	.rtc_write_data = (void *) &shouldnt_happen,
-	.rtc_bcd_mode   = (void *) &shouldnt_happen
-};
--- diff/arch/mips/lib/rtc-std.c	2002-10-16 04:28:33.000000000 +0100
+++ source/arch/mips/lib/rtc-std.c	1970-01-01 01:00:00.000000000 +0100
@@ -1,34 +0,0 @@
-/*
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * RTC routines for PC style attached Dallas chip.
- *
- * Copyright (C) 1998, 2001 by Ralf Baechle
- */
-#include <linux/mc146818rtc.h>
-#include <asm/io.h>
-
-static unsigned char std_rtc_read_data(unsigned long addr)
-{
-	outb_p(addr, RTC_PORT(0));
-	return inb_p(RTC_PORT(1));
-}
-
-static void std_rtc_write_data(unsigned char data, unsigned long addr)
-{
-	outb_p(addr, RTC_PORT(0));
-	outb_p(data, RTC_PORT(1));
-}
-
-static int std_rtc_bcd_mode(void)
-{
-	return 1;
-}
-
-struct rtc_ops std_rtc_ops = {
-	&std_rtc_read_data,
-	&std_rtc_write_data,
-	&std_rtc_bcd_mode
-};
--- diff/arch/mips/mips-boards/atlas/atlas_rtc.c	2002-10-16 04:27:53.000000000 +0100
+++ source/arch/mips/mips-boards/atlas/atlas_rtc.c	1970-01-01 01:00:00.000000000 +0100
@@ -1,57 +0,0 @@
-/*
- * Carsten Langgaard, carstenl@mips.com
- * Copyright (C) 1999,2000 MIPS Technologies, Inc.  All rights reserved.
- *
- * ########################################################################
- *
- *  This program is free software; you can distribute it and/or modify it
- *  under the terms of the GNU General Public License (Version 2) as
- *  published by the Free Software Foundation.
- *
- *  This program is distributed in the hope it will be useful, but WITHOUT
- *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- *  for more details.
- *
- *  You should have received a copy of the GNU General Public License along
- *  with this program; if not, write to the Free Software Foundation, Inc.,
- *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
- *
- * ########################################################################
- *
- * RTC routines for Atlas style attached Dallas chip.
- *
- */
-#include <linux/mc146818rtc.h>
-#include <asm/mips-boards/atlas.h>
-
-
-static unsigned char atlas_rtc_read_data(unsigned long addr)
-{
-	volatile unsigned int *rtc_adr_reg = (void *)ATLAS_RTC_ADR_REG;
-	volatile unsigned int *rtc_dat_reg = (void *)ATLAS_RTC_DAT_REG;
-
-	*rtc_adr_reg = addr;
-
-	return *rtc_dat_reg;
-}
-
-static void atlas_rtc_write_data(unsigned char data, unsigned long addr)
-{
-	volatile unsigned int *rtc_adr_reg = (void *)ATLAS_RTC_ADR_REG;
-	volatile unsigned int *rtc_dat_reg = (void *)ATLAS_RTC_DAT_REG;
-
-	*rtc_adr_reg = addr;
-	*rtc_dat_reg = data;
-}
-
-static int atlas_rtc_bcd_mode(void)
-{
-	return 0;
-}
-
-struct rtc_ops atlas_rtc_ops = {
-	&atlas_rtc_read_data,
-	&atlas_rtc_write_data,
-	&atlas_rtc_bcd_mode
-};
--- diff/arch/mips/mips-boards/malta/malta_rtc.c	2002-10-16 04:28:24.000000000 +0100
+++ source/arch/mips/mips-boards/malta/malta_rtc.c	1970-01-01 01:00:00.000000000 +0100
@@ -1,50 +0,0 @@
-/*
- * Carsten Langgaard, carstenl@mips.com
- * Copyright (C) 2000 MIPS Technologies, Inc.  All rights reserved.
- *
- * ########################################################################
- *
- *  This program is free software; you can distribute it and/or modify it
- *  under the terms of the GNU General Public License (Version 2) as
- *  published by the Free Software Foundation.
- *
- *  This program is distributed in the hope it will be useful, but WITHOUT
- *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- *  for more details.
- *
- *  You should have received a copy of the GNU General Public License along
- *  with this program; if not, write to the Free Software Foundation, Inc.,
- *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
- *
- * ########################################################################
- *
- * RTC routines for Malta style attached PIIX4 device, which contains a
- * Motorola MC146818A-compatible Real Time Clock.
- *
- */
-#include <linux/mc146818rtc.h>
-#include <asm/mips-boards/malta.h>
-
-static unsigned char malta_rtc_read_data(unsigned long addr)
-{
-	outb(addr, MALTA_RTC_ADR_REG);
-	return inb(MALTA_RTC_DAT_REG);
-}
-
-static void malta_rtc_write_data(unsigned char data, unsigned long addr)
-{
-	outb(addr, MALTA_RTC_ADR_REG);
-	outb(data, MALTA_RTC_DAT_REG);
-}
-
-static int malta_rtc_bcd_mode(void)
-{
-	return 0;
-}
-
-struct rtc_ops malta_rtc_ops = {
-	&malta_rtc_read_data,
-	&malta_rtc_write_data,
-	&malta_rtc_bcd_mode
-};
--- diff/arch/mips/mips-boards/sead/sead_time.c	2003-08-20 14:16:25.000000000 +0100
+++ source/arch/mips/mips-boards/sead/sead_time.c	1970-01-01 01:00:00.000000000 +0100
@@ -1,140 +0,0 @@
-/*
- * Carsten Langgaard, carstenl@mips.com
- * Copyright (C) 2002 MIPS Technologies, Inc.  All rights reserved.
- *
- *  This program is free software; you can distribute it and/or modify it
- *  under the terms of the GNU General Public License (Version 2) as
- *  published by the Free Software Foundation.
- *
- *  This program is distributed in the hope it will be useful, but WITHOUT
- *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- *  for more details.
- *
- *  You should have received a copy of the GNU General Public License along
- *  with this program; if not, write to the Free Software Foundation, Inc.,
- *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
- *
- * Setting up the clock on the MIPS boards.
- */
-#include <linux/config.h>
-#include <linux/init.h>
-#include <linux/kernel_stat.h>
-#include <linux/sched.h>
-#include <linux/spinlock.h>
-
-#include <asm/mipsregs.h>
-#include <asm/ptrace.h>
-#include <asm/hardirq.h>
-#include <asm/cpu.h>
-
-#include <linux/interrupt.h>
-#include <linux/timex.h>
-
-#include <asm/mips-boards/generic.h>
-#include <asm/mips-boards/prom.h>
-
-extern volatile unsigned long wall_jiffies;
-
-static unsigned long r4k_offset; /* Amount to increment compare reg each time */
-static unsigned long r4k_cur;    /* What counter should be at next timer irq */
-
-#define ALLINTS (IE_IRQ0 | IE_IRQ1 | IE_IRQ5)
-
-static char display_string[] = "        LINUX ON SEAD       ";
-
-static unsigned int display_count = 0;
-#define MAX_DISPLAY_COUNT (sizeof(display_string) - 8)
-
-#define MIPS_CPU_TIMER_IRQ 7
-
-static unsigned int timer_tick_count=0;
-
-static inline void ack_r4ktimer(unsigned long newval)
-{
-	write_c0_compare(newval);
-}
-
-/*
- * There are a lot of conceptually broken versions of the MIPS timer interrupt
- * handler floating around.  This one is rather different, but the algorithm
- * is provably more robust.
- */
-void mips_timer_interrupt(struct pt_regs *regs)
-{
-	int cpu = smp_processor_id();
-	int irq = MIPS_CPU_TIMER_IRQ;
-
-	irq_enter();
-
-	do {
-		kstat_this_cpu.irqs[irq]++;
-		do_timer(regs);
-
-		if ((timer_tick_count++ % HZ) == 0) {
-		    mips_display_message(&display_string[display_count++]);
-		    if (display_count == MAX_DISPLAY_COUNT)
-		        display_count = 0;
-		}
-
-		r4k_cur += r4k_offset;
-		ack_r4ktimer(r4k_cur);
-
-	} while (((unsigned long)read_c0_count()
-	         - r4k_cur) < 0x7fffffff);
-
-	irq_exit();
-}
-
-/*
- * Figure out the r4k offset, the amount to increment the compare
- * register for each time tick.
- */
-static unsigned long __init cal_r4koff(void)
-{
-	/*
-	 * The SEAD board doesn't have a real time clock, so we can't
-	 * really calculate the timer offset.
-	 * For now we hardwire the SEAD board frequency to 12MHz.
-	 */
-	return(6000000/HZ);
-}
-
-void __init mips_time_init(void)
-{
-        unsigned int est_freq, flags;
-
-	local_irq_save(flags);
-
-        /* Start r4k counter. */
-        write_c0_count(0);
-
-	printk("calculating r4koff... ");
-	r4k_offset = cal_r4koff();
-	printk("%08lx(%d)\n", r4k_offset, (int) r4k_offset);
-
-        if ((read_c0_prid() & 0xffff00) ==
-	    (PRID_COMP_MIPS | PRID_IMP_20KC))
-		est_freq = r4k_offset*HZ;
-	else
-		est_freq = 2*r4k_offset*HZ;
-
-	est_freq += 5000;    /* round */
-	est_freq -= est_freq%10000;
-	printk("CPU frequency %d.%02d MHz\n", est_freq/1000000,
-	       (est_freq%1000000)*100/1000000);
-
-	local_irq_restore(flags);
-}
-
-void __init mips_timer_setup(struct irqaction *irq)
-{
-	/* we are using the cpu counter for timer interrupts */
-	irq->handler = no_action;     /* we use our own handler */
-	setup_irq(MIPS_CPU_TIMER_IRQ, irq);
-
-        /* to generate the first timer interrupt */
-	r4k_cur = (read_c0_count() + r4k_offset);
-	write_c0_compare(r4k_cur);
-	set_c0_status(ALLINTS);
-}
--- diff/arch/mips/mm-32/init.c	2003-10-09 09:47:33.000000000 +0100
+++ source/arch/mips/mm-32/init.c	1970-01-01 01:00:00.000000000 +0100
@@ -1,292 +0,0 @@
-/*
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (C) 1994 - 2000 Ralf Baechle
- * Copyright (C) 1999, 2000 Silicon Graphics, Inc.
- * Kevin D. Kissell, kevink@mips.com and Carsten Langgaard, carstenl@mips.com
- * Copyright (C) 2000 MIPS Technologies, Inc.  All rights reserved.
- */
-#include <linux/config.h>
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/signal.h>
-#include <linux/sched.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/types.h>
-#include <linux/pagemap.h>
-#include <linux/ptrace.h>
-#include <linux/mman.h>
-#include <linux/mm.h>
-#include <linux/bootmem.h>
-#include <linux/highmem.h>
-#include <linux/swap.h>
-
-#include <asm/bootinfo.h>
-#include <asm/cachectl.h>
-#include <asm/cpu.h>
-#include <asm/dma.h>
-#include <asm/pgalloc.h>
-#include <asm/mmu_context.h>
-#include <asm/sections.h>
-#include <asm/tlb.h>
-
-DEFINE_PER_CPU(struct mmu_gather, mmu_gathers);
-
-unsigned long highstart_pfn, highend_pfn;
-
-/*
- * We have up to 8 empty zeroed pages so we can map one of the right colour
- * when needed.  This is necessary only on R4000 / R4400 SC and MC versions
- * where we have to avoid VCED / VECI exceptions for good performance at
- * any price.  Since page is never written to after the initialization we
- * don't have to care about aliases on other CPUs.
- */
-unsigned long empty_zero_page, zero_page_mask;
-
-/*
- * Not static inline because used by IP27 special magic initialization code
- */
-unsigned long setup_zero_pages(void)
-{
-	unsigned long order, size;
-	struct page *page;
-
-	if (cpu_has_vce)
-		order = 3;
-	else
-		order = 0;
-
-	empty_zero_page = __get_free_pages(GFP_KERNEL, order);
-	if (!empty_zero_page)
-		panic("Oh boy, that early out of memory?");
-
-	page = virt_to_page(empty_zero_page);
-	while (page < virt_to_page(empty_zero_page + (PAGE_SIZE << order))) {
-		set_bit(PG_reserved, &page->flags);
-		set_page_count(page, 0);
-		page++;
-	}
-
-	size = PAGE_SIZE << order;
-	zero_page_mask = (size - 1) & PAGE_MASK;
-	memset((void *)empty_zero_page, 0, size);
-
-	return 1UL << order;
-}
-
-#ifdef CONFIG_HIGHMEM
-pte_t *kmap_pte;
-pgprot_t kmap_prot;
-
-EXPORT_SYMBOL(kmap_prot);
-EXPORT_SYMBOL(kmap_pte);
-
-#define kmap_get_fixmap_pte(vaddr)					\
-	pte_offset_kernel(pmd_offset(pgd_offset_k(vaddr), (vaddr)), (vaddr))
-
-static void __init kmap_init(void)
-{
-	unsigned long kmap_vstart;
-
-	/* cache the first kmap pte */
-	kmap_vstart = __fix_to_virt(FIX_KMAP_BEGIN);
-	kmap_pte = kmap_get_fixmap_pte(kmap_vstart);
-
-	kmap_prot = PAGE_KERNEL;
-}
-
-#endif /* CONFIG_HIGHMEM */
-
-#ifdef CONFIG_HIGHMEM
-static void __init fixrange_init (unsigned long start, unsigned long end,
-	pgd_t *pgd_base)
-{
-	pgd_t *pgd;
-	pmd_t *pmd;
-	pte_t *pte;
-	int i, j;
-	unsigned long vaddr;
-
-	vaddr = start;
-	i = __pgd_offset(vaddr);
-	j = __pmd_offset(vaddr);
-	pgd = pgd_base + i;
-
-	for ( ; (i < PTRS_PER_PGD) && (vaddr != end); pgd++, i++) {
-		pmd = (pmd_t *)pgd;
-		for (; (j < PTRS_PER_PMD) && (vaddr != end); pmd++, j++) {
-			if (pmd_none(*pmd)) {
-				pte = (pte_t *) alloc_bootmem_low_pages(PAGE_SIZE);
-				set_pmd(pmd, __pmd(pte));
-				if (pte != pte_offset_kernel(pmd, 0))
-					BUG();
-			}
-			vaddr += PMD_SIZE;
-		}
-		j = 0;
-	}
-}
-#endif
-
-#ifndef CONFIG_DISCONTIGMEM
-
-extern void pagetable_init(void);
-
-void __init paging_init(void)
-{
-	unsigned long zones_size[MAX_NR_ZONES] = {0, 0, 0};
-	unsigned long max_dma, high, low;
-
-	pagetable_init();
-
-#ifdef CONFIG_HIGHMEM
-	kmap_init();
-#endif
-
-	max_dma = virt_to_phys((char *)MAX_DMA_ADDRESS) >> PAGE_SHIFT;
-	low = max_low_pfn;
-	high = highend_pfn;
-
-#ifdef CONFIG_ISA
-	if (low < max_dma)
-		zones_size[ZONE_DMA] = low;
-	else {
-		zones_size[ZONE_DMA] = max_dma;
-		zones_size[ZONE_NORMAL] = low - max_dma;
-	}
-#else
-	zones_size[ZONE_DMA] = low;
-#endif
-#ifdef CONFIG_HIGHMEM
-	zones_size[ZONE_HIGHMEM] = high - low;
-#endif
-
-	free_area_init(zones_size);
-}
-
-#define PFN_UP(x)	(((x) + PAGE_SIZE - 1) >> PAGE_SHIFT)
-#define PFN_DOWN(x)	((x) >> PAGE_SHIFT)
-
-static inline int page_is_ram(unsigned long pagenr)
-{
-	int i;
-
-	for (i = 0; i < boot_mem_map.nr_map; i++) {
-		unsigned long addr, end;
-
-		if (boot_mem_map.map[i].type != BOOT_MEM_RAM)
-			/* not usable memory */
-			continue;
-
-		addr = PFN_UP(boot_mem_map.map[i].addr);
-		end = PFN_DOWN(boot_mem_map.map[i].addr +
-			       boot_mem_map.map[i].size);
-
-		if (pagenr >= addr && pagenr < end)
-			return 1;
-	}
-
-	return 0;
-}
-
-void __init mem_init(void)
-{
-	unsigned long codesize, reservedpages, datasize, initsize;
-	unsigned long tmp, ram;
-
-#ifdef CONFIG_HIGHMEM
-	highstart_pfn = (KSEG1 - KSEG0) >> PAGE_SHIFT;
-	highmem_start_page = mem_map + highstart_pfn;
-#ifdef CONFIG_DISCONTIGMEM
-#error "CONFIG_HIGHMEM and CONFIG_DISCONTIGMEM dont work together yet"
-#endif
-	max_mapnr = num_physpages = highend_pfn;
-#else
-	max_mapnr = num_physpages = max_low_pfn;
-#endif
-	high_memory = (void *) __va(max_low_pfn << PAGE_SHIFT);
-
-	totalram_pages += free_all_bootmem();
-	totalram_pages -= setup_zero_pages();	/* Setup zeroed pages.  */
-
-	reservedpages = ram = 0;
-	for (tmp = 0; tmp < max_low_pfn; tmp++)
-		if (page_is_ram(tmp)) {
-			ram++;
-			if (PageReserved(mem_map+tmp))
-				reservedpages++;
-		}
-
-#ifdef CONFIG_HIGHMEM
-	for (tmp = highstart_pfn; tmp < highend_pfn; tmp++) {
-		struct page *page = mem_map + tmp;
-
-		if (!page_is_ram(tmp)) {
-			SetPageReserved(page);
-			continue;
-		}
-		ClearPageReserved(page);
-		set_bit(PG_highmem, &page->flags);
-		atomic_set(&page->count, 1);
-		__free_page(page);
-		totalhigh_pages++;
-	}
-	totalram_pages += totalhigh_pages;
-#endif
-
-	codesize =  (unsigned long) &_etext - (unsigned long) &_text;
-	datasize =  (unsigned long) &_edata - (unsigned long) &_etext;
-	initsize =  (unsigned long) &__init_end - (unsigned long) &__init_begin;
-
-	printk(KERN_INFO "Memory: %luk/%luk available (%ldk kernel code, "
-	       "%ldk reserved, %ldk data, %ldk init, %ldk highmem)\n",
-	       (unsigned long) nr_free_pages() << (PAGE_SHIFT-10),
-	       ram << (PAGE_SHIFT-10),
-	       codesize >> 10,
-	       reservedpages << (PAGE_SHIFT-10),
-	       datasize >> 10,
-	       initsize >> 10,
-	       (unsigned long) (totalhigh_pages << (PAGE_SHIFT-10)));
-}
-#endif /* !CONFIG_DISCONTIGMEM */
-
-#ifdef CONFIG_BLK_DEV_INITRD
-void free_initrd_mem(unsigned long start, unsigned long end)
-{
-	if (start < end)
-		printk(KERN_INFO "Freeing initrd memory: %ldk freed\n",
-		       (end - start) >> 10);
-
-	for (; start < end; start += PAGE_SIZE) {
-		ClearPageReserved(virt_to_page(start));
-		set_page_count(virt_to_page(start), 1);
-		free_page(start);
-		totalram_pages++;
-	}
-}
-#endif
-
-extern void prom_free_prom_memory(void);
-
-void free_initmem(void)
-{
-	unsigned long addr, page;
-
-	prom_free_prom_memory();
-
-	addr = (unsigned long) &__init_begin;
-	while (addr < (unsigned long) &__init_end) {
-		page = addr;
-		ClearPageReserved(virt_to_page(page));
-		set_page_count(virt_to_page(page), 1);
-		free_page(page);
-		totalram_pages++;
-		addr += PAGE_SIZE;
-	}
-	printk(KERN_INFO "Freeing unused kernel memory: %ldk freed\n",
-	       (unsigned long) (__init_end - __init_begin) >> 10);
-}
--- diff/arch/mips/mm-32/pg-r4k.S	2003-08-20 14:16:36.000000000 +0100
+++ source/arch/mips/mm-32/pg-r4k.S	1970-01-01 01:00:00.000000000 +0100
@@ -1,785 +0,0 @@
-/*
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * r4xx0.c: R4000 processor variant specific MMU/Cache routines.
- *
- * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
- * Copyright (C) 1997,  1998,  1999,  2000 Ralf Baechle ralf@gnu.org
- */
-#include <linux/config.h>
-#include <asm/addrspace.h>
-#include <asm/asm.h>
-#include <asm/regdef.h>
-#include <asm/cacheops.h>
-#include <asm/mipsregs.h>
-#include <asm/offset.h>
-
-#ifdef CONFIG_64BIT_PHYS_ADDR
-#define PGD_SIZE	0x2000
-#else
-#define PGD_SIZE	0x1000
-#endif
-
-	.text
-	.set	noat
-
-/*
- * Zero an entire page.  Basically a simple unrolled loop should do the
- * job but we want more performance by saving memory bus bandwidth.  We
- * have five flavours of the routine available for:
- *
- * - 16byte cachelines and no second level cache
- * - 32byte cachelines second level cache
- * - a version which handles the buggy R4600 v1.x
- * - a version which handles the buggy R4600 v2.0
- * - Finally a last version without fancy cache games for the SC and MC
- *   versions of R4000 and R4400.
- */
-
-LEAF(r4k_clear_page32_d16)
-	.set	mips3
-	addiu	AT, a0, _PAGE_SIZE
-1:	cache	Create_Dirty_Excl_D, (a0)
-	sw	zero, (a0)
-	sw	zero, 4(a0)
-	sw	zero, 8(a0)
-	sw	zero, 12(a0)
-	addiu	a0, 32
-	cache	Create_Dirty_Excl_D, -16(a0)
-	sw	zero, -16(a0)
-	sw	zero, -12(a0)
-	sw	zero, -8(a0)
-	sw	zero, -4(a0)
-	bne	AT, a0, 1b
-	jr	ra
-	END(r4k_clear_page32_d16)
-
-LEAF(r4k_clear_page32_d32)
-	.set	mips3
-	addiu	AT, a0, _PAGE_SIZE
-1:	cache	Create_Dirty_Excl_D, (a0)
-	sw	zero, (a0)
-	sw	zero, 4(a0)
-	sw	zero, 8(a0)
-	sw	zero, 12(a0)
-	addiu	a0, 32
-	sw	zero, -16(a0)
-	sw	zero, -12(a0)
-	sw	zero, -8(a0)
-	sw	zero, -4(a0)
-	bne	AT, a0, 1b
-	jr	ra
-	END(r4k_clear_page32_d32)
-
-LEAF(r4k_clear_page_d16)
-	.set	mips3
-	addiu	AT, a0, _PAGE_SIZE
-1:	cache	Create_Dirty_Excl_D, (a0)
-	sd	zero, (a0)
-	sd	zero, 8(a0)
-	cache	Create_Dirty_Excl_D, 16(a0)
-	sd	zero, 16(a0)
-	sd	zero, 24(a0)
-	addiu	a0, 64
-	cache	Create_Dirty_Excl_D, -32(a0)
-	sd	zero, -32(a0)
-	sd	zero, -24(a0)
-	cache	Create_Dirty_Excl_D, -16(a0)
-	sd	zero, -16(a0)
-	sd	zero, -8(a0)
-	bne	AT, a0, 1b
-	jr	ra
-	END(r4k_clear_page_d16)
-
-LEAF(r4k_clear_page_d32)
-	.set	mips3
-	addiu	AT, a0, _PAGE_SIZE
-1:	cache	Create_Dirty_Excl_D, (a0)
-	sd	zero, (a0)
-	sd	zero, 8(a0)
-	sd	zero, 16(a0)
-	sd	zero, 24(a0)
-	addiu	a0, 64
-	cache	Create_Dirty_Excl_D, -32(a0)
-	sd	zero, -32(a0)
-	sd	zero, -24(a0)
-	sd	zero, -16(a0)
-	sd	zero, -8(a0)
-	bne	AT, a0, 1b
-	jr	ra
-	END(r4k_clear_page_d32)
-
-/*
- * This flavour of r4k_clear_page is for the R4600 V1.x.  Cite from the
- * IDT R4600 V1.7 errata:
- *
- *  18. The CACHE instructions Hit_Writeback_Invalidate_D, Hit_Writeback_D,
- *      Hit_Invalidate_D and Create_Dirty_Excl_D should only be
- *      executed if there is no other dcache activity. If the dcache is
- *      accessed for another instruction immeidately preceding when these
- *      cache instructions are executing, it is possible that the dcache
- *      tag match outputs used by these cache instructions will be
- *      incorrect. These cache instructions should be preceded by at least
- *      four instructions that are not any kind of load or store
- *      instruction.
- *
- *      This is not allowed:    lw
- *                              nop
- *                              nop
- *                              nop
- *                              cache       Hit_Writeback_Invalidate_D
- *
- *      This is allowed:        lw
- *                              nop
- *                              nop
- *                              nop
- *                              nop
- *                              cache       Hit_Writeback_Invalidate_D
- */
-
-LEAF(r4k_clear_page_r4600_v1)
-	.set	mips3
-	addiu	AT, a0, _PAGE_SIZE
-1:	nop
-	nop
-	nop
-	nop
-	cache	Create_Dirty_Excl_D, (a0)
-	sd	zero, (a0)
-	sd	zero, 8(a0)
-	sd	zero, 16(a0)
-	sd	zero, 24(a0)
-	addiu	a0, 64
-	nop
-	nop
-	nop
-	cache	Create_Dirty_Excl_D, -32(a0)
-	sd	zero, -32(a0)
-	sd	zero, -24(a0)
-	sd	zero, -16(a0)
-	sd	zero, -8(a0)
-	bne	AT, a0, 1b
-	jr	ra
-	END(r4k_clear_page_r4600_v1)
-
-LEAF(r4k_clear_page_r4600_v2)
-	.set	mips3
-	mfc0	a1, CP0_STATUS
-	ori	AT, a1, 1
-	xori	AT, 1
-	mtc0	AT, CP0_STATUS
-	nop
-	nop
-	nop
-
-	.set	volatile
-	la	AT, KSEG1
-	lw	zero, (AT)
-	.set	novolatile
-
-	addiu	AT, a0, _PAGE_SIZE
-1:	cache	Create_Dirty_Excl_D, (a0)
-	sd	zero, (a0)
-	sd	zero, 8(a0)
-	sd	zero, 16(a0)
-	sd	zero, 24(a0)
-	addiu	a0, 64
-	cache	Create_Dirty_Excl_D, -32(a0)
-	sd	zero, -32(a0)
-	sd	zero, -24(a0)
-	sd	zero, -16(a0)
-	sd	zero, -8(a0)
-	bne	AT, a0, 1b
-
-	mfc0	AT, CP0_STATUS			# local_irq_restore
-	andi	a1, 1
-	ori	AT, 1
-	xori	AT, 1
-	or	a1, AT
-	mtc0	a1, CP0_STATUS
-	nop
-	nop
-	nop
-
-	jr	ra
-	END(r4k_clear_page_r4600_v2)
-
-/*
- * The next 4 versions are optimized for all possible scache configurations
- * of the SC / MC versions of R4000 and R4400 ...
- *
- * Todo: For even better performance we should have a routine optimized for
- * every legal combination of dcache / scache linesize.  When I (Ralf) tried
- * this the kernel crashed shortly after mounting the root filesystem.  CPU
- * bug?  Weirdo cache instruction semantics?
- */
-
-LEAF(r4k_clear_page_s16)
-	.set	mips3
-	addiu	AT, a0, _PAGE_SIZE
-1:	cache	Create_Dirty_Excl_SD, (a0)
-	sd	zero, (a0)
-	sd	zero, 8(a0)
-	cache	Create_Dirty_Excl_SD, 16(a0)
-	sd	zero, 16(a0)
-	sd	zero, 24(a0)
-	addiu	a0, 64
-	cache	Create_Dirty_Excl_SD, -32(a0)
-	sd	zero, -32(a0)
-	sd	zero, -24(a0)
-	cache	Create_Dirty_Excl_SD, -16(a0)
-	sd	zero, -16(a0)
-	sd	zero, -8(a0)
-	bne	AT, a0, 1b
-	jr	ra
-	END(r4k_clear_page_s16)
-
-LEAF(r4k_clear_page_s32)
-	.set	mips3
-	addiu	AT, a0, _PAGE_SIZE
-1:	cache	Create_Dirty_Excl_SD, (a0)
-	sd	zero, (a0)
-	sd	zero, 8(a0)
-	sd	zero, 16(a0)
-	sd	zero, 24(a0)
-	addiu	a0, 64
-	cache	Create_Dirty_Excl_SD, -32(a0)
-	sd	zero, -32(a0)
-	sd	zero, -24(a0)
-	sd	zero, -16(a0)
-	sd	zero, -8(a0)
-	bne	AT, a0, 1b
-	jr	ra
-	END(r4k_clear_page_s32)
-
-LEAF(r4k_clear_page_s64)
-	.set	mips3
-	addiu	AT, a0, _PAGE_SIZE
-1:	cache	Create_Dirty_Excl_SD, (a0)
-	sd	zero, (a0)
-	sd	zero, 8(a0)
-	sd	zero, 16(a0)
-	sd	zero, 24(a0)
-	addiu	a0, 64
-	sd	zero, -32(a0)
-	sd	zero, -24(a0)
-	sd	zero, -16(a0)
-	sd	zero, -8(a0)
-	bne	AT, a0, 1b
-	jr	ra
-	END(r4k_clear_page_s64)
-
-LEAF(r4k_clear_page_s128)
-	.set	mips3
-	addiu	AT, a0, _PAGE_SIZE
-1:	cache	Create_Dirty_Excl_SD, (a0)
-	sd	zero, (a0)
-	sd	zero, 8(a0)
-	sd	zero, 16(a0)
-	sd	zero, 24(a0)
-	sd	zero, 32(a0)
-	sd	zero, 40(a0)
-	sd	zero, 48(a0)
-	sd	zero, 56(a0)
-	addiu	a0, 128
-	sd	zero, -64(a0)
-	sd	zero, -56(a0)
-	sd	zero, -48(a0)
-	sd	zero, -40(a0)
-	sd	zero, -32(a0)
-	sd	zero, -24(a0)
-	sd	zero, -16(a0)
-	sd	zero, -8(a0)
-	bne	AT, a0, 1b
-	jr	ra
-	END(r4k_clear_page_s128)
-
-/*
- * This is suboptimal for 32-bit kernels; we assume that R10000 is only used
- * with 64-bit kernels.  The prefetch offsets have been experimentally tuned
- * an Origin 200.
- */
-LEAF(andes_clear_page)
-	.set		mips4
-	LONG_ADDIU	AT, a0, _PAGE_SIZE
-1:	pref		7, 512(a0)
-	sd		zero, 0*SZREG(a0)
-	sd		zero, 1*SZREG(a0)
-	sd		zero, 2*SZREG(a0)
-	sd		zero, 3*SZREG(a0)
-	LONG_ADDIU	a0, a0, 8*SZREG
-	sd		zero, -4*SZREG(a0)
-	sd		zero, -3*SZREG(a0)
-	sd		zero, -2*SZREG(a0)
-	sd		zero, -1*SZREG(a0)
-	bne		AT, a0, 1b
-	j		ra
-	END(andes_clear_page)
-	.set		mips0
-
-/*
- * This is still inefficient.  We only can do better if we know the
- * virtual address where the copy will be accessed.
- */
-
-LEAF(r4k_copy_page_d16)
-	.set	mips3
-	addiu	AT, a0, _PAGE_SIZE
-1:	cache	Create_Dirty_Excl_D, (a0)
-	lw	a3, (a1)
-	lw	a2, 4(a1)
-	lw	v1, 8(a1)
-	lw	v0, 12(a1)
-	sw	a3, (a0)
-	sw	a2, 4(a0)
-	sw	v1, 8(a0)
-	sw	v0, 12(a0)
-	cache	Create_Dirty_Excl_D, 16(a0)
-	lw	a3, 16(a1)
-	lw	a2, 20(a1)
-	lw	v1, 24(a1)
-	lw	v0, 28(a1)
-	sw	a3, 16(a0)
-	sw	a2, 20(a0)
-	sw	v1, 24(a0)
-	sw	v0, 28(a0)
-	cache	Create_Dirty_Excl_D, 32(a0)
-	addiu	a0, 64
-	addiu	a1, 64
-	lw	a3, -32(a1)
-	lw	a2, -28(a1)
-	lw	v1, -24(a1)
-	lw	v0, -20(a1)
-	sw	a3, -32(a0)
-	sw	a2, -28(a0)
-	sw	v1, -24(a0)
-	sw	v0, -20(a0)
-	cache	Create_Dirty_Excl_D, -16(a0)
-	lw	a3, -16(a1)
-	lw	a2, -12(a1)
-	lw	v1, -8(a1)
-	lw	v0, -4(a1)
-	sw	a3, -16(a0)
-	sw	a2, -12(a0)
-	sw	v1, -8(a0)
-	sw	v0, -4(a0)
-	bne	AT, a0, 1b
-	jr	ra
-	END(r4k_copy_page_d16)
-
-LEAF(r4k_copy_page_d32)
-	.set	mips3
-	addiu	AT, a0, _PAGE_SIZE
-1:	cache	Create_Dirty_Excl_D, (a0)
-	lw	a3, (a1)
-	lw	a2, 4(a1)
-	lw	v1, 8(a1)
-	lw	v0, 12(a1)
-	sw	a3, (a0)
-	sw	a2, 4(a0)
-	sw	v1, 8(a0)
-	sw	v0, 12(a0)
-	lw	a3, 16(a1)
-	lw	a2, 20(a1)
-	lw	v1, 24(a1)
-	lw	v0, 28(a1)
-	sw	a3, 16(a0)
-	sw	a2, 20(a0)
-	sw	v1, 24(a0)
-	sw	v0, 28(a0)
-	cache	Create_Dirty_Excl_D, 32(a0)
-	addiu	a0, 64
-	addiu	a1, 64
-	lw	a3, -32(a1)
-	lw	a2, -28(a1)
-	lw	v1, -24(a1)
-	lw	v0, -20(a1)
-	sw	a3, -32(a0)
-	sw	a2, -28(a0)
-	sw	v1, -24(a0)
-	sw	v0, -20(a0)
-	lw	a3, -16(a1)
-	lw	a2, -12(a1)
-	lw	v1, -8(a1)
-	lw	v0, -4(a1)
-	sw	a3, -16(a0)
-	sw	a2, -12(a0)
-	sw	v1, -8(a0)
-	sw	v0, -4(a0)
-	bne	AT, a0, 1b
-	jr	ra
-	END(r4k_copy_page_d32)
-
-/*
- * Again a special version for the R4600 V1.x
- */
-
-LEAF(r4k_copy_page_r4600_v1)
-	.set	mips3
-	addiu	AT, a0, _PAGE_SIZE
-1:	nop
-	nop
-	nop
-	nop
-	cache	Create_Dirty_Excl_D, (a0)
-	lw	a3, (a1)
-	lw	a2, 4(a1)
-	lw	v1, 8(a1)
-	lw	v0, 12(a1)
-	sw	a3, (a0)
-	sw	a2, 4(a0)
-	sw	v1, 8(a0)
-	sw	v0, 12(a0)
-	lw	a3, 16(a1)
-	lw	a2, 20(a1)
-	lw	v1, 24(a1)
-	lw	v0, 28(a1)
-	sw	a3, 16(a0)
-	sw	a2, 20(a0)
-	sw	v1, 24(a0)
-	sw	v0, 28(a0)
-	nop
-	nop
-	nop
-	nop
-	cache	Create_Dirty_Excl_D, 32(a0)
-	addiu	a0, 64
-	addiu	a1, 64
-	lw	a3, -32(a1)
-	lw	a2, -28(a1)
-	lw	v1, -24(a1)
-	lw	v0, -20(a1)
-	sw	a3, -32(a0)
-	sw	a2, -28(a0)
-	sw	v1, -24(a0)
-	sw	v0, -20(a0)
-	lw	a3, -16(a1)
-	lw	a2, -12(a1)
-	lw	v1, -8(a1)
-	lw	v0, -4(a1)
-	sw	a3, -16(a0)
-	sw	a2, -12(a0)
-	sw	v1, -8(a0)
-	sw	v0, -4(a0)
-	bne	AT, a0, 1b
-	jr	ra
-	END(r4k_copy_page_r4600_v1)
-
-LEAF(r4k_copy_page_r4600_v2)
-	.set	mips3
-	mfc0	v1, CP0_STATUS
-	ori	AT, v1, 1
-	xori	AT, 1
-
-	mtc0	AT, CP0_STATUS
-	nop
-	nop
-	nop
-
-	addiu	AT, a0, _PAGE_SIZE
-1:	nop
-	nop
-	nop
-	nop
-	cache	Create_Dirty_Excl_D, (a0)
-	lw	t1, (a1)
-	lw	t0, 4(a1)
-	lw	a3, 8(a1)
-	lw	a2, 12(a1)
-	sw	t1, (a0)
-	sw	t0, 4(a0)
-	sw	a3, 8(a0)
-	sw	a2, 12(a0)
-	lw	t1, 16(a1)
-	lw	t0, 20(a1)
-	lw	a3, 24(a1)
-	lw	a2, 28(a1)
-	sw	t1, 16(a0)
-	sw	t0, 20(a0)
-	sw	a3, 24(a0)
-	sw	a2, 28(a0)
-	nop
-	nop
-	nop
-	nop
-	cache	Create_Dirty_Excl_D, 32(a0)
-	addiu	a0, 64
-	addiu	a1, 64
-	lw	t1, -32(a1)
-	lw	t0, -28(a1)
-	lw	a3, -24(a1)
-	lw	a2, -20(a1)
-	sw	t1, -32(a0)
-	sw	t0, -28(a0)
-	sw	a3, -24(a0)
-	sw	a2, -20(a0)
-	lw	t1, -16(a1)
-	lw	t0, -12(a1)
-	lw	a3, -8(a1)
-	lw	a2, -4(a1)
-	sw	t1, -16(a0)
-	sw	t0, -12(a0)
-	sw	a3, -8(a0)
-	sw	a2, -4(a0)
-	bne	AT, a0, 1b
-
-	mfc0	AT, CP0_STATUS			# local_irq_restore
-	andi	v1, 1
-	ori	AT, 1
-	xori	AT, 1
-	or	v1, AT
-	mtc0	v1, CP0_STATUS
-	nop
-	nop
-	nop
-	jr	ra
-	END(r4k_copy_page_r4600_v2)
-
-/*
- * These are for R4000SC / R4400MC
- */
-
-LEAF(r4k_copy_page_s16)
-	.set	mips3
-	addiu	AT, a0, _PAGE_SIZE
-1:	cache	Create_Dirty_Excl_SD, (a0)
-	lw	a3, (a1)
-	lw	a2, 4(a1)
-	lw	v1, 8(a1)
-	lw	v0, 12(a1)
-	sw	a3, (a0)
-	sw	a2, 4(a0)
-	sw	v1, 8(a0)
-	sw	v0, 12(a0)
-	cache	Create_Dirty_Excl_SD, 16(a0)
-	lw	a3, 16(a1)
-	lw	a2, 20(a1)
-	lw	v1, 24(a1)
-	lw	v0, 28(a1)
-	sw	a3, 16(a0)
-	sw	a2, 20(a0)
-	sw	v1, 24(a0)
-	sw	v0, 28(a0)
-	cache	Create_Dirty_Excl_SD, 32(a0)
-	addiu	a0, 64
-	addiu	a1, 64
-	lw	a3, -32(a1)
-	lw	a2, -28(a1)
-	lw	v1, -24(a1)
-	lw	v0, -20(a1)
-	sw	a3, -32(a0)
-	sw	a2, -28(a0)
-	sw	v1, -24(a0)
-	sw	v0, -20(a0)
-	cache	Create_Dirty_Excl_SD, -16(a0)
-	lw	a3, -16(a1)
-	lw	a2, -12(a1)
-	lw	v1, -8(a1)
-	lw	v0, -4(a1)
-	sw	a3, -16(a0)
-	sw	a2, -12(a0)
-	sw	v1, -8(a0)
-	sw	v0, -4(a0)
-	bne	AT, a0, 1b
-	jr	ra
-	END(r4k_copy_page_s16)
-
-LEAF(r4k_copy_page_s32)
-	.set	mips3
-	addiu	AT, a0, _PAGE_SIZE
-1:	cache	Create_Dirty_Excl_SD, (a0)
-	lw	a3, (a1)
-	lw	a2, 4(a1)
-	lw	v1, 8(a1)
-	lw	v0, 12(a1)
-	sw	a3, (a0)
-	sw	a2, 4(a0)
-	sw	v1, 8(a0)
-	sw	v0, 12(a0)
-	lw	a3, 16(a1)
-	lw	a2, 20(a1)
-	lw	v1, 24(a1)
-	lw	v0, 28(a1)
-	sw	a3, 16(a0)
-	sw	a2, 20(a0)
-	sw	v1, 24(a0)
-	sw	v0, 28(a0)
-	cache	Create_Dirty_Excl_SD, 32(a0)
-	addiu	a0, 64
-	addiu	a1, 64
-	lw	a3, -32(a1)
-	lw	a2, -28(a1)
-	lw	v1, -24(a1)
-	lw	v0, -20(a1)
-	sw	a3, -32(a0)
-	sw	a2, -28(a0)
-	sw	v1, -24(a0)
-	sw	v0, -20(a0)
-	lw	a3, -16(a1)
-	lw	a2, -12(a1)
-	lw	v1, -8(a1)
-	lw	v0, -4(a1)
-	sw	a3, -16(a0)
-	sw	a2, -12(a0)
-	sw	v1, -8(a0)
-	sw	v0, -4(a0)
-	bne	AT, a0, 1b
-	jr	ra
-	END(r4k_copy_page_s32)
-
-LEAF(r4k_copy_page_s64)
-	.set	mips3
-	addiu	AT, a0, _PAGE_SIZE
-1:	cache	Create_Dirty_Excl_SD, (a0)
-	lw	a3, (a1)
-	lw	a2, 4(a1)
-	lw	v1, 8(a1)
-	lw	v0, 12(a1)
-	sw	a3, (a0)
-	sw	a2, 4(a0)
-	sw	v1, 8(a0)
-	sw	v0, 12(a0)
-	lw	a3, 16(a1)
-	lw	a2, 20(a1)
-	lw	v1, 24(a1)
-	lw	v0, 28(a1)
-	sw	a3, 16(a0)
-	sw	a2, 20(a0)
-	sw	v1, 24(a0)
-	sw	v0, 28(a0)
-	addiu	a0, 64
-	addiu	a1, 64
-	lw	a3, -32(a1)
-	lw	a2, -28(a1)
-	lw	v1, -24(a1)
-	lw	v0, -20(a1)
-	sw	a3, -32(a0)
-	sw	a2, -28(a0)
-	sw	v1, -24(a0)
-	sw	v0, -20(a0)
-	lw	a3, -16(a1)
-	lw	a2, -12(a1)
-	lw	v1, -8(a1)
-	lw	v0, -4(a1)
-	sw	a3, -16(a0)
-	sw	a2, -12(a0)
-	sw	v1, -8(a0)
-	sw	v0, -4(a0)
-	bne	AT, a0, 1b
-	jr	ra
-	END(r4k_copy_page_s64)
-
-LEAF(r4k_copy_page_s128)
-	.set	mips3
-	addiu	AT, a0, _PAGE_SIZE
-1:	cache	Create_Dirty_Excl_SD, (a0)
-	lw	a3, (a1)
-	lw	a2, 4(a1)
-	lw	v1, 8(a1)
-	lw	v0, 12(a1)
-	sw	a3, (a0)
-	sw	a2, 4(a0)
-	sw	v1, 8(a0)
-	sw	v0, 12(a0)
-	lw	a3, 16(a1)
-	lw	a2, 20(a1)
-	lw	v1, 24(a1)
-	lw	v0, 28(a1)
-	sw	a3, 16(a0)
-	sw	a2, 20(a0)
-	sw	v1, 24(a0)
-	sw	v0, 28(a0)
-	lw	a3, 32(a1)
-	lw	a2, 36(a1)
-	lw	v1, 40(a1)
-	lw	v0, 44(a1)
-	sw	a3, 32(a0)
-	sw	a2, 36(a0)
-	sw	v1, 40(a0)
-	sw	v0, 44(a0)
-	lw	a3, 48(a1)
-	lw	a2, 52(a1)
-	lw	v1, 56(a1)
-	lw	v0, 60(a1)
-	sw	a3, 48(a0)
-	sw	a2, 52(a0)
-	sw	v1, 56(a0)
-	sw	v0, 60(a0)
-	addiu	a0, 128
-	addiu	a1, 128
-	lw	a3, -64(a1)
-	lw	a2, -60(a1)
-	lw	v1, -56(a1)
-	lw	v0, -52(a1)
-	sw	a3, -64(a0)
-	sw	a2, -60(a0)
-	sw	v1, -56(a0)
-	sw	v0, -52(a0)
-	lw	a3, -48(a1)
-	lw	a2, -44(a1)
-	lw	v1, -40(a1)
-	lw	v0, -36(a1)
-	sw	a3, -48(a0)
-	sw	a2, -44(a0)
-	sw	v1, -40(a0)
-	sw	v0, -36(a0)
-	lw	a3, -32(a1)
-	lw	a2, -28(a1)
-	lw	v1, -24(a1)
-	lw	v0, -20(a1)
-	sw	a3, -32(a0)
-	sw	a2, -28(a0)
-	sw	v1, -24(a0)
-	sw	v0, -20(a0)
-	lw	a3, -16(a1)
-	lw	a2, -12(a1)
-	lw	v1, -8(a1)
-	lw	v0, -4(a1)
-	sw	a3, -16(a0)
-	sw	a2, -12(a0)
-	sw	v1, -8(a0)
-	sw	v0, -4(a0)
-	bne	AT, a0, 1b
-	jr	ra
-	END(r4k_copy_page_s128)
-
-
-	.text
-	.set	mips4
-	.set	noat
-
-
-/*
- * This is suboptimal for 32-bit kernels; we assume that R10000 is only used
- * with 64-bit kernels.  The prefetch offsets have been experimentally tuned
- * an Origin 200.
- */
-LEAF(andes_copy_page)
-	.set		mips4
-	LONG_ADDIU	AT, a0, _PAGE_SIZE
-1:	pref		0, 2*128(a1)
-	pref		1, 2*128(a0)
-	LONG_L		a3, 0*SZREG(a1)
-	LONG_L		a2, 1*SZREG(a1)
-	LONG_L		v1, 2*SZREG(a1)
-	LONG_L		v0, 3*SZREG(a1)
-	LONG_S		a3, 0*SZREG(a0)
-	LONG_S		a2, 1*SZREG(a0)
-	LONG_S		v1, 2*SZREG(a0)
-	LONG_S		v0, 3*SZREG(a0)
-	LONG_ADDIU	a0, a0, 8*SZREG
-	LONG_ADDIU	a1, a1, 8*SZREG
-	LONG_L		a3, -4*SZREG(a1)
-	LONG_L		a2, -3*SZREG(a1)
-	LONG_L		v1, -2*SZREG(a1)
-	LONG_L		v0, -1*SZREG(a1)
-	LONG_S		a3, -4*SZREG(a0)
-	LONG_S		a2, -3*SZREG(a0)
-	LONG_S		v1, -2*SZREG(a0)
-	LONG_S		v0, -1*SZREG(a0)
-	bne		AT, a0,1b
-	j		ra
-	END(andes_copy_page)
-	.set		mips0
--- diff/arch/mips/mm-64/init.c	2003-10-09 09:47:33.000000000 +0100
+++ source/arch/mips/mm-64/init.c	1970-01-01 01:00:00.000000000 +0100
@@ -1,296 +0,0 @@
-/*
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (C) 1994 - 2000 Ralf Baechle
- * Copyright (C) 1999, 2000 Silicon Graphics, Inc.
- * Kevin D. Kissell, kevink@mips.com and Carsten Langgaard, carstenl@mips.com
- * Copyright (C) 2000 MIPS Technologies, Inc.  All rights reserved.
- */
-#include <linux/config.h>
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/signal.h>
-#include <linux/sched.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/types.h>
-#include <linux/pagemap.h>
-#include <linux/ptrace.h>
-#include <linux/mman.h>
-#include <linux/mm.h>
-#include <linux/bootmem.h>
-#include <linux/highmem.h>
-#include <linux/swap.h>
-
-#include <asm/bootinfo.h>
-#include <asm/cachectl.h>
-#include <asm/cpu.h>
-#include <asm/dma.h>
-#include <asm/pgalloc.h>
-#include <asm/mmu_context.h>
-#include <asm/sections.h>
-#include <asm/tlb.h>
-
-DEFINE_PER_CPU(struct mmu_gather, mmu_gathers);
-
-unsigned long highstart_pfn, highend_pfn;
-
-/*
- * We have up to 8 empty zeroed pages so we can map one of the right colour
- * when needed.  This is necessary only on R4000 / R4400 SC and MC versions
- * where we have to avoid VCED / VECI exceptions for good performance at
- * any price.  Since page is never written to after the initialization we
- * don't have to care about aliases on other CPUs.
- */
-unsigned long empty_zero_page, zero_page_mask;
-
-/*
- * Not static inline because used by IP27 special magic initialization code
- */
-unsigned long setup_zero_pages(void)
-{
-	unsigned long order, size;
-	struct page *page;
-
-	if (cpu_has_vce)
-		order = 3;
-	else
-		order = 0;
-
-	empty_zero_page = __get_free_pages(GFP_KERNEL, order);
-	if (!empty_zero_page)
-		panic("Oh boy, that early out of memory?");
-
-	page = virt_to_page(empty_zero_page);
-	while (page < virt_to_page(empty_zero_page + (PAGE_SIZE << order))) {
-		set_bit(PG_reserved, &page->flags);
-		set_page_count(page, 0);
-		page++;
-	}
-
-	size = PAGE_SIZE << order;
-	zero_page_mask = (size - 1) & PAGE_MASK;
-	memset((void *)empty_zero_page, 0, size);
-
-	return 1UL << order;
-}
-
-#ifdef CONFIG_HIGHMEM
-pte_t *kmap_pte;
-pgprot_t kmap_prot;
-
-EXPORT_SYMBOL(kmap_prot);
-EXPORT_SYMBOL(kmap_pte);
-
-#define kmap_get_fixmap_pte(vaddr)					\
-	pte_offset_kernel(pmd_offset(pgd_offset_k(vaddr), (vaddr)), (vaddr))
-
-static void __init kmap_init(void)
-{
-	unsigned long kmap_vstart;
-
-	/* cache the first kmap pte */
-	kmap_vstart = __fix_to_virt(FIX_KMAP_BEGIN);
-	kmap_pte = kmap_get_fixmap_pte(kmap_vstart);
-
-	kmap_prot = PAGE_KERNEL;
-}
-
-#endif /* CONFIG_HIGHMEM */
-
-#ifdef CONFIG_HIGHMEM
-static void __init fixrange_init (unsigned long start, unsigned long end,
-	pgd_t *pgd_base)
-{
-	pgd_t *pgd;
-	pmd_t *pmd;
-	pte_t *pte;
-	int i, j;
-	unsigned long vaddr;
-
-	vaddr = start;
-	i = __pgd_offset(vaddr);
-	j = __pmd_offset(vaddr);
-	pgd = pgd_base + i;
-
-	for ( ; (i < PTRS_PER_PGD) && (vaddr != end); pgd++, i++) {
-		pmd = (pmd_t *)pgd;
-		for (; (j < PTRS_PER_PMD) && (vaddr != end); pmd++, j++) {
-			if (pmd_none(*pmd)) {
-				pte = (pte_t *) alloc_bootmem_low_pages(PAGE_SIZE);
-				set_pmd(pmd, __pmd(pte));
-				if (pte != pte_offset_kernel(pmd, 0))
-					BUG();
-			}
-			vaddr += PMD_SIZE;
-		}
-		j = 0;
-	}
-}
-#endif
-
-#ifndef CONFIG_DISCONTIGMEM
-
-extern void pagetable_init(void);
-
-void __init paging_init(void)
-{
-	unsigned long zones_size[MAX_NR_ZONES] = {0, 0, 0};
-	unsigned long max_dma, high, low;
-
-	pagetable_init();
-
-#ifdef CONFIG_HIGHMEM
-	kmap_init();
-#endif
-
-	max_dma = virt_to_phys((char *)MAX_DMA_ADDRESS) >> PAGE_SHIFT;
-	low = max_low_pfn;
-	high = highend_pfn;
-
-#ifdef CONFIG_ISA
-	if (low < max_dma)
-		zones_size[ZONE_DMA] = low;
-	else {
-		zones_size[ZONE_DMA] = max_dma;
-		zones_size[ZONE_NORMAL] = low - max_dma;
-	}
-#else
-	zones_size[ZONE_DMA] = low;
-#endif
-#ifdef CONFIG_HIGHMEM
-	zones_size[ZONE_HIGHMEM] = high - low;
-#endif
-
-	free_area_init(zones_size);
-}
-
-#define PFN_UP(x)	(((x) + PAGE_SIZE - 1) >> PAGE_SHIFT)
-#define PFN_DOWN(x)	((x) >> PAGE_SHIFT)
-
-static inline int page_is_ram(unsigned long pagenr)
-{
-	int i;
-
-	for (i = 0; i < boot_mem_map.nr_map; i++) {
-		unsigned long addr, end;
-
-		if (boot_mem_map.map[i].type != BOOT_MEM_RAM)
-			/* not usable memory */
-			continue;
-
-		addr = PFN_UP(boot_mem_map.map[i].addr);
-		end = PFN_DOWN(boot_mem_map.map[i].addr +
-			       boot_mem_map.map[i].size);
-
-		if (pagenr >= addr && pagenr < end)
-			return 1;
-	}
-
-	return 0;
-}
-
-void __init mem_init(void)
-{
-	unsigned long codesize, reservedpages, datasize, initsize;
-	unsigned long tmp, ram;
-
-#ifdef CONFIG_HIGHMEM
-	highstart_pfn = (KSEG1 - KSEG0) >> PAGE_SHIFT;
-	highmem_start_page = mem_map + highstart_pfn;
-#ifdef CONFIG_DISCONTIGMEM
-#error "CONFIG_HIGHMEM and CONFIG_DISCONTIGMEM dont work together yet"
-#endif
-	max_mapnr = num_physpages = highend_pfn;
-#else
-	max_mapnr = num_physpages = max_low_pfn;
-#endif
-	high_memory = (void *) __va(max_low_pfn << PAGE_SHIFT);
-
-	totalram_pages += free_all_bootmem();
-	totalram_pages -= setup_zero_pages();	/* Setup zeroed pages.  */
-
-	reservedpages = ram = 0;
-	for (tmp = 0; tmp < max_low_pfn; tmp++)
-		if (page_is_ram(tmp)) {
-			ram++;
-			if (PageReserved(mem_map+tmp))
-				reservedpages++;
-		}
-
-#ifdef CONFIG_HIGHMEM
-	for (tmp = highstart_pfn; tmp < highend_pfn; tmp++) {
-		struct page *page = mem_map + tmp;
-
-		if (!page_is_ram(tmp)) {
-			SetPageReserved(page);
-			continue;
-		}
-		ClearPageReserved(page);
-		set_bit(PG_highmem, &page->flags);
-		atomic_set(&page->count, 1);
-		__free_page(page);
-		totalhigh_pages++;
-	}
-	totalram_pages += totalhigh_pages;
-#endif
-
-	codesize =  (unsigned long) &_etext - (unsigned long) &_text;
-	datasize =  (unsigned long) &_edata - (unsigned long) &_etext;
-	initsize =  (unsigned long) &__init_end - (unsigned long) &__init_begin;
-
-	printk(KERN_INFO "Memory: %luk/%luk available (%ldk kernel code, "
-	       "%ldk reserved, %ldk data, %ldk init, %ldk highmem)\n",
-	       (unsigned long) nr_free_pages() << (PAGE_SHIFT-10),
-	       ram << (PAGE_SHIFT-10),
-	       codesize >> 10,
-	       reservedpages << (PAGE_SHIFT-10),
-	       datasize >> 10,
-	       initsize >> 10,
-	       (unsigned long) (totalhigh_pages << (PAGE_SHIFT-10)));
-}
-#endif /* !CONFIG_DISCONTIGMEM */
-
-#ifdef CONFIG_BLK_DEV_INITRD
-void free_initrd_mem(unsigned long start, unsigned long end)
-{
-	/* Switch from KSEG0 to XKPHYS addresses */
-	start = (unsigned long)phys_to_virt(CPHYSADDR(start));
-	end = (unsigned long)phys_to_virt(CPHYSADDR(end));
-
-	if (start < end)
-		printk(KERN_INFO "Freeing initrd memory: %ldk freed\n",
-		       (end - start) >> 10);
-
-	for (; start < end; start += PAGE_SIZE) {
-		ClearPageReserved(virt_to_page(start));
-		set_page_count(virt_to_page(start), 1);
-		free_page(start);
-		totalram_pages++;
-	}
-}
-#endif
-
-extern void prom_free_prom_memory(void);
-
-void free_initmem(void)
-{
-	unsigned long addr, page;
-
-	prom_free_prom_memory();
-
-	addr = (unsigned long) &__init_begin;
-	while (addr < (unsigned long) &__init_end) {
-		page = PAGE_OFFSET | CPHYSADDR(addr);
-		ClearPageReserved(virt_to_page(page));
-		set_page_count(virt_to_page(page), 1);
-		free_page(page);
-		totalram_pages++;
-		addr += PAGE_SIZE;
-	}
-	printk(KERN_INFO "Freeing unused kernel memory: %ldk freed\n",
-	       (unsigned long) (__init_end - __init_begin) >> 10);
-}
--- diff/arch/mips/mm-64/pg-r4k.c	2003-08-20 14:16:36.000000000 +0100
+++ source/arch/mips/mm-64/pg-r4k.c	1970-01-01 01:00:00.000000000 +0100
@@ -1,708 +0,0 @@
-/*
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
- * Copyright (C) 1997, 98, 99, 2000, 01, 02, 03 Ralf Baechle (ralf@gnu.org)
- * Copyright (C) 1999, 2000 Silicon Graphics, Inc.
- * Copyright (C) 2000 Kanoj Sarcar (kanoj@sgi.com)
- */
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/mm.h>
-
-#include <asm/cacheops.h>
-#include <asm/io.h>
-#include <asm/page.h>
-#include <asm/pgtable.h>
-#include <asm/system.h>
-#include <asm/bootinfo.h>
-#include <asm/mmu_context.h>
-#include <asm/cpu.h>
-
-/*
- * Zero an entire page.  Basically a simple unrolled loop should do the
- * job but we want more performance by saving memory bus bandwidth.  We
- * have five flavours of the routine available for:
- *
- * - 16byte cachelines and no second level cache
- * - 32byte cachelines second level cache
- * - a version which handles the buggy R4600 v1.x
- * - a version which handles the buggy R4600 v2.0
- * - Finally a last version without fancy cache games for the SC and MC
- *   versions of R4000 and R4400.
- */
-
-void r4k_clear_page_d16(void * page)
-{
-	__asm__ __volatile__(
-		".set\tnoreorder\n\t"
-		".set\tnoat\n\t"
-		"daddiu\t$1,%0,%2\n"
-		"1:\tcache\t%3,(%0)\n\t"
-		"sd\t$0,(%0)\n\t"
-		"sd\t$0,8(%0)\n\t"
-		"cache\t%3,16(%0)\n\t"
-		"sd\t$0,16(%0)\n\t"
-		"sd\t$0,24(%0)\n\t"
-		"daddiu\t%0,64\n\t"
-		"cache\t%3,-32(%0)\n\t"
-		"sd\t$0,-32(%0)\n\t"
-		"sd\t$0,-24(%0)\n\t"
-		"cache\t%3,-16(%0)\n\t"
-		"sd\t$0,-16(%0)\n\t"
-		"bne\t$1,%0,1b\n\t"
-		"sd\t$0,-8(%0)\n\t"
-		".set\tat\n\t"
-		".set\treorder"
-		: "=r" (page)
-		: "0" (page), "I" (PAGE_SIZE), "i" (Create_Dirty_Excl_D)
-		: "memory");
-}
-
-void r4k_clear_page_d32(void * page)
-{
-	__asm__ __volatile__(
-		".set\tnoreorder\n\t"
-		".set\tnoat\n\t"
-		"daddiu\t$1,%0,%2\n"
-		"1:\tcache\t%3,(%0)\n\t"
-		"sd\t$0,(%0)\n\t"
-		"sd\t$0,8(%0)\n\t"
-		"sd\t$0,16(%0)\n\t"
-		"sd\t$0,24(%0)\n\t"
-		"daddiu\t%0,64\n\t"
-		"cache\t%3,-32(%0)\n\t"
-		"sd\t$0,-32(%0)\n\t"
-		"sd\t$0,-24(%0)\n\t"
-		"sd\t$0,-16(%0)\n\t"
-		"bne\t$1,%0,1b\n\t"
-		"sd\t$0,-8(%0)\n\t"
-		".set\tat\n\t"
-		".set\treorder"
-		: "=r" (page)
-		: "0" (page), "I" (PAGE_SIZE), "i" (Create_Dirty_Excl_D)
-		: "memory");
-}
-
-
-/*
- * This flavour of r4k_clear_page is for the R4600 V1.x.  Cite from the
- * IDT R4600 V1.7 errata:
- *
- *  18. The CACHE instructions Hit_Writeback_Invalidate_D, Hit_Writeback_D,
- *      Hit_Invalidate_D and Create_Dirty_Excl_D should only be
- *      executed if there is no other dcache activity. If the dcache is
- *      accessed for another instruction immeidately preceding when these
- *      cache instructions are executing, it is possible that the dcache
- *      tag match outputs used by these cache instructions will be
- *      incorrect. These cache instructions should be preceded by at least
- *      four instructions that are not any kind of load or store
- *      instruction.
- *
- *      This is not allowed:    lw
- *                              nop
- *                              nop
- *                              nop
- *                              cache       Hit_Writeback_Invalidate_D
- *
- *      This is allowed:        lw
- *                              nop
- *                              nop
- *                              nop
- *                              nop
- *                              cache       Hit_Writeback_Invalidate_D
- */
-void r4k_clear_page_r4600_v1(void * page)
-{
-	__asm__ __volatile__(
-		".set\tnoreorder\n\t"
-		".set\tnoat\n\t"
-		"daddiu\t$1,%0,%2\n"
-		"1:\tnop\n\t"
-		"nop\n\t"
-		"nop\n\t"
-		"nop\n\t"
-		"cache\t%3,(%0)\n\t"
-		"sd\t$0,(%0)\n\t"
-		"sd\t$0,8(%0)\n\t"
-		"sd\t$0,16(%0)\n\t"
-		"sd\t$0,24(%0)\n\t"
-		"daddiu\t%0,64\n\t"
-		"nop\n\t"
-		"nop\n\t"
-		"nop\n\t"
-		"cache\t%3,-32(%0)\n\t"
-		"sd\t$0,-32(%0)\n\t"
-		"sd\t$0,-24(%0)\n\t"
-		"sd\t$0,-16(%0)\n\t"
-		"bne\t$1,%0,1b\n\t"
-		"sd\t$0,-8(%0)\n\t"
-		".set\tat\n\t"
-		".set\treorder"
-		: "=r" (page)
-		: "0" (page), "I" (PAGE_SIZE), "i" (Create_Dirty_Excl_D)
-		: "memory");
-}
-
-/*
- * And this one is for the R4600 V2.0
- */
-void r4k_clear_page_r4600_v2(void * page)
-{
-	unsigned int flags;
-
-	local_irq_save(flags);
-	*(volatile unsigned int *)KSEG1;
-	__asm__ __volatile__(
-		".set\tnoreorder\n\t"
-		".set\tnoat\n\t"
-		"daddiu\t$1,%0,%2\n"
-		"1:\tcache\t%3,(%0)\n\t"
-		"sd\t$0,(%0)\n\t"
-		"sd\t$0,8(%0)\n\t"
-		"sd\t$0,16(%0)\n\t"
-		"sd\t$0,24(%0)\n\t"
-		"daddiu\t%0,64\n\t"
-		"cache\t%3,-32(%0)\n\t"
-		"sd\t$0,-32(%0)\n\t"
-		"sd\t$0,-24(%0)\n\t"
-		"sd\t$0,-16(%0)\n\t"
-		"bne\t$1,%0,1b\n\t"
-		"sd\t$0,-8(%0)\n\t"
-		".set\tat\n\t"
-		".set\treorder"
-		: "=r" (page)
-		: "0" (page), "I" (PAGE_SIZE), "i" (Create_Dirty_Excl_D)
-		: "memory");
-	local_irq_restore(flags);
-}
-
-/*
- * The next 4 versions are optimized for all possible scache configurations
- * of the SC / MC versions of R4000 and R4400 ...
- *
- * Todo: For even better performance we should have a routine optimized for
- * every legal combination of dcache / scache linesize.  When I (Ralf) tried
- * this the kernel crashed shortly after mounting the root filesystem.  CPU
- * bug?  Weirdo cache instruction semantics?
- */
-void r4k_clear_page_s16(void * page)
-{
-	__asm__ __volatile__(
-		".set\tnoreorder\n\t"
-		".set\tnoat\n\t"
-		"daddiu\t$1,%0,%2\n"
-		"1:\tcache\t%3,(%0)\n\t"
-		"sd\t$0,(%0)\n\t"
-		"sd\t$0,8(%0)\n\t"
-		"cache\t%3,16(%0)\n\t"
-		"sd\t$0,16(%0)\n\t"
-		"sd\t$0,24(%0)\n\t"
-		"daddiu\t%0,64\n\t"
-		"cache\t%3,-32(%0)\n\t"
-		"sd\t$0,-32(%0)\n\t"
-		"sd\t$0,-24(%0)\n\t"
-		"cache\t%3,-16(%0)\n\t"
-		"sd\t$0,-16(%0)\n\t"
-		"bne\t$1,%0,1b\n\t"
-		"sd\t$0,-8(%0)\n\t"
-		".set\tat\n\t"
-		".set\treorder"
-		: "=r" (page)
-		: "0" (page), "I" (PAGE_SIZE), "i" (Create_Dirty_Excl_SD)
-		: "memory");
-}
-
-void r4k_clear_page_s32(void * page)
-{
-	__asm__ __volatile__(
-		".set\tnoreorder\n\t"
-		".set\tnoat\n\t"
-		"daddiu\t$1,%0,%2\n"
-		"1:\tcache\t%3,(%0)\n\t"
-		"sd\t$0,(%0)\n\t"
-		"sd\t$0,8(%0)\n\t"
-		"sd\t$0,16(%0)\n\t"
-		"sd\t$0,24(%0)\n\t"
-		"daddiu\t%0,64\n\t"
-		"cache\t%3,-32(%0)\n\t"
-		"sd\t$0,-32(%0)\n\t"
-		"sd\t$0,-24(%0)\n\t"
-		"sd\t$0,-16(%0)\n\t"
-		"bne\t$1,%0,1b\n\t"
-		"sd\t$0,-8(%0)\n\t"
-		".set\tat\n\t"
-		".set\treorder"
-		: "=r" (page)
-		: "0" (page), "I" (PAGE_SIZE), "i" (Create_Dirty_Excl_SD)
-		: "memory");
-}
-
-void r4k_clear_page_s64(void * page)
-{
-	__asm__ __volatile__(
-		".set\tnoreorder\n\t"
-		".set\tnoat\n\t"
-		"daddiu\t$1,%0,%2\n"
-		"1:\tcache\t%3,(%0)\n\t"
-		"sd\t$0,(%0)\n\t"
-		"sd\t$0,8(%0)\n\t"
-		"sd\t$0,16(%0)\n\t"
-		"sd\t$0,24(%0)\n\t"
-		"daddiu\t%0,64\n\t"
-		"sd\t$0,-32(%0)\n\t"
-		"sd\t$0,-24(%0)\n\t"
-		"sd\t$0,-16(%0)\n\t"
-		"bne\t$1,%0,1b\n\t"
-		"sd\t$0,-8(%0)\n\t"
-		".set\tat\n\t"
-		".set\treorder"
-		: "=r" (page)
-		: "0" (page), "I" (PAGE_SIZE), "i" (Create_Dirty_Excl_SD)
-		: "memory");
-}
-
-void r4k_clear_page_s128(void * page)
-{
-	__asm__ __volatile__(
-		".set\tnoreorder\n\t"
-		".set\tnoat\n\t"
-		"daddiu\t$1,%0,%2\n"
-		"1:\tcache\t%3,(%0)\n\t"
-		"sd\t$0,(%0)\n\t"
-		"sd\t$0,8(%0)\n\t"
-		"sd\t$0,16(%0)\n\t"
-		"sd\t$0,24(%0)\n\t"
-		"sd\t$0,32(%0)\n\t"
-		"sd\t$0,40(%0)\n\t"
-		"sd\t$0,48(%0)\n\t"
-		"sd\t$0,56(%0)\n\t"
-		"daddiu\t%0,128\n\t"
-		"sd\t$0,-64(%0)\n\t"
-		"sd\t$0,-56(%0)\n\t"
-		"sd\t$0,-48(%0)\n\t"
-		"sd\t$0,-40(%0)\n\t"
-		"sd\t$0,-32(%0)\n\t"
-		"sd\t$0,-24(%0)\n\t"
-		"sd\t$0,-16(%0)\n\t"
-		"bne\t$1,%0,1b\n\t"
-		"sd\t$0,-8(%0)\n\t"
-		".set\tat\n\t"
-		".set\treorder"
-		: "=r" (page)
-		: "0" (page), "I" (PAGE_SIZE), "i" (Create_Dirty_Excl_SD)
-		: "memory");
-}
-
-/*
- * This version has been tuned on an Origin.  For other machines the arguments
- * of the pref instructin may have to be tuned differently.
- */
-void andes_clear_page(void * page)
-{
-	__asm__ __volatile__(
-		".set\tpush\n\t"
-		".set\tmips4\n\t"
-		".set\tnoreorder\n\t"
-		".set\tnoat\n\t"
-		"daddiu\t$1,%0,%2\n"
-		"1:\tpref 7,512(%0)\n\t"
-		"sd\t$0,(%0)\n\t"
-		"sd\t$0,8(%0)\n\t"
-		"sd\t$0,16(%0)\n\t"
-		"sd\t$0,24(%0)\n\t"
-		"daddiu\t%0,64\n\t"
-		"sd\t$0,-32(%0)\n\t"
-		"sd\t$0,-24(%0)\n\t"
-		"sd\t$0,-16(%0)\n\t"
-		"bne\t$1,%0,1b\n\t"
-		"sd\t$0,-8(%0)\n\t"
-		".set\tpop"
-		: "=r" (page)
-		: "0" (page), "I" (PAGE_SIZE)
-		: "memory");
-}
-
-
-/*
- * This is still inefficient.  We only can do better if we know the
- * virtual address where the copy will be accessed.
- */
-
-void r4k_copy_page_d16(void * to, void * from)
-{
-	unsigned long dummy1, dummy2, reg1, reg2;
-
-	__asm__ __volatile__(
-		".set\tnoreorder\n\t"
-		".set\tnoat\n\t"
-		"daddiu\t$1,%0,%6\n"
-		"1:\tcache\t%7,(%0)\n\t"
-		"ld\t%2,(%1)\n\t"
-		"ld\t%3,8(%1)\n\t"
-		"sd\t%2,(%0)\n\t"
-		"sd\t%3,8(%0)\n\t"
-		"cache\t%7,16(%0)\n\t"
-		"ld\t%2,16(%1)\n\t"
-		"ld\t%3,24(%1)\n\t"
-		"sd\t%2,16(%0)\n\t"
-		"sd\t%3,24(%0)\n\t"
-		"cache\t%7,32(%0)\n\t"
-		"daddiu\t%0,64\n\t"
-		"daddiu\t%1,64\n\t"
-		"ld\t%2,-32(%1)\n\t"
-		"ld\t%3,-24(%1)\n\t"
-		"sd\t%2,-32(%0)\n\t"
-		"sd\t%3,-24(%0)\n\t"
-		"cache\t%7,-16(%0)\n\t"
-		"ld\t%2,-16(%1)\n\t"
-		"ld\t%3,-8(%1)\n\t"
-		"sd\t%2,-16(%0)\n\t"
-		"bne\t$1,%0,1b\n\t"
-		" sd\t%3,-8(%0)\n\t"
-		".set\tat\n\t"
-		".set\treorder"
-		:"=r" (dummy1), "=r" (dummy2), "=&r" (reg1), "=&r" (reg2)
-		:"0" (to), "1" (from), "I" (PAGE_SIZE),
-		 "i" (Create_Dirty_Excl_D));
-}
-
-void r4k_copy_page_d32(void * to, void * from)
-{
-	unsigned long dummy1, dummy2, reg1, reg2;
-
-	__asm__ __volatile__(
-		".set\tnoreorder\n\t"
-		".set\tnoat\n\t"
-		"daddiu\t$1,%0,%6\n"
-		"1:\tcache\t%7,(%0)\n\t"
-		"ld\t%2,(%1)\n\t"
-		"ld\t%3,8(%1)\n\t"
-		"sd\t%2,(%0)\n\t"
-		"sd\t%3,8(%0)\n\t"
-		"ld\t%2,16(%1)\n\t"
-		"ld\t%3,24(%1)\n\t"
-		"sd\t%2,16(%0)\n\t"
-		"sd\t%3,24(%0)\n\t"
-		"cache\t%7,32(%0)\n\t"
-		"daddiu\t%0,64\n\t"
-		"daddiu\t%1,64\n\t"
-		"ld\t%2,-32(%1)\n\t"
-		"ld\t%3,-24(%1)\n\t"
-		"sd\t%2,-32(%0)\n\t"
-		"sd\t%3,-24(%0)\n\t"
-		"ld\t%2,-16(%1)\n\t"
-		"ld\t%3,-8(%1)\n\t"
-		"sd\t%2,-16(%0)\n\t"
-		"bne\t$1,%0,1b\n\t"
-		" sd\t%3,-8(%0)\n\t"
-		".set\tat\n\t"
-		".set\treorder"
-		:"=r" (dummy1), "=r" (dummy2), "=&r" (reg1), "=&r" (reg2)
-		:"0" (to), "1" (from), "I" (PAGE_SIZE),
-		 "i" (Create_Dirty_Excl_D));
-}
-
-/*
- * Again a special version for the R4600 V1.x
- */
-void r4k_copy_page_r4600_v1(void * to, void * from)
-{
-	unsigned long dummy1, dummy2, reg1, reg2;
-
-	__asm__ __volatile__(
-		".set\tnoreorder\n\t"
-		".set\tnoat\n\t"
-		"daddiu\t$1,%0,%6\n"
-		"1:\tnop\n\t"
-		"nop\n\t"
-		"nop\n\t"
-		"nop\n\t"
-		"\tcache\t%7,(%0)\n\t"
-		"ld\t%2,(%1)\n\t"
-		"ld\t%3,8(%1)\n\t"
-		"sd\t%2,(%0)\n\t"
-		"sd\t%3,8(%0)\n\t"
-		"ld\t%2,16(%1)\n\t"
-		"ld\t%3,24(%1)\n\t"
-		"sd\t%2,16(%0)\n\t"
-		"sd\t%3,24(%0)\n\t"
-		"nop\n\t"
-		"nop\n\t"
-		"nop\n\t"
-		"nop\n\t"
-		"cache\t%7,32(%0)\n\t"
-		"daddiu\t%0,64\n\t"
-		"daddiu\t%1,64\n\t"
-		"ld\t%2,-32(%1)\n\t"
-		"ld\t%3,-24(%1)\n\t"
-		"sd\t%2,-32(%0)\n\t"
-		"sd\t%3,-24(%0)\n\t"
-		"ld\t%2,-16(%1)\n\t"
-		"ld\t%3,-8(%1)\n\t"
-		"sd\t%2,-16(%0)\n\t"
-		"bne\t$1,%0,1b\n\t"
-		" sd\t%3,-8(%0)\n\t"
-		".set\tat\n\t"
-		".set\treorder"
-		:"=r" (dummy1), "=r" (dummy2), "=&r" (reg1), "=&r" (reg2)
-		:"0" (to), "1" (from), "I" (PAGE_SIZE),
-		 "i" (Create_Dirty_Excl_D));
-}
-
-void r4k_copy_page_r4600_v2(void * to, void * from)
-{
-	unsigned long dummy1, dummy2, reg1, reg2;
-	unsigned int flags;
-
-	local_irq_save(flags);
-	__asm__ __volatile__(
-		".set\tnoreorder\n\t"
-		".set\tnoat\n\t"
-		"daddiu\t$1,%0,%6\n"
-		"1:\tnop\n\t"
-		"nop\n\t"
-		"nop\n\t"
-		"nop\n\t"
-		"\tcache\t%7,(%0)\n\t"
-		"ld\t%2,(%1)\n\t"
-		"ld\t%3,8(%1)\n\t"
-		"sd\t%2,(%0)\n\t"
-		"sd\t%3,8(%0)\n\t"
-		"ld\t%2,16(%1)\n\t"
-		"ld\t%3,24(%1)\n\t"
-		"sd\t%2,16(%0)\n\t"
-		"sd\t%3,24(%0)\n\t"
-		"nop\n\t"
-		"nop\n\t"
-		"nop\n\t"
-		"nop\n\t"
-		"cache\t%7,32(%0)\n\t"
-		"daddiu\t%0,64\n\t"
-		"daddiu\t%1,64\n\t"
-		"ld\t%2,-32(%1)\n\t"
-		"ld\t%3,-24(%1)\n\t"
-		"sd\t%2,-32(%0)\n\t"
-		"sd\t%3,-24(%0)\n\t"
-		"ld\t%2,-16(%1)\n\t"
-		"ld\t%3,-8(%1)\n\t"
-		"sd\t%2,-16(%0)\n\t"
-		"bne\t$1,%0,1b\n\t"
-		" sd\t%3,-8(%0)\n\t"
-		".set\tat\n\t"
-		".set\treorder"
-		:"=r" (dummy1), "=r" (dummy2), "=&r" (reg1), "=&r" (reg2)
-		:"0" (to), "1" (from), "I" (PAGE_SIZE),
-		 "i" (Create_Dirty_Excl_D));
-	local_irq_restore(flags);
-}
-
-/*
- * These are for R4000SC / R4400MC
- */
-void r4k_copy_page_s16(void * to, void * from)
-{
-	unsigned long dummy1, dummy2, reg1, reg2;
-
-	__asm__ __volatile__(
-		".set\tnoreorder\n\t"
-		".set\tnoat\n\t"
-		"daddiu\t$1,%0,%6\n"
-		"1:\tcache\t%7,(%0)\n\t"
-		"ld\t%2,(%1)\n\t"
-		"ld\t%3,8(%1)\n\t"
-		"sd\t%2,(%0)\n\t"
-		"sd\t%3,8(%0)\n\t"
-		"cache\t%7,16(%0)\n\t"
-		"ld\t%2,16(%1)\n\t"
-		"ld\t%3,24(%1)\n\t"
-		"sd\t%2,16(%0)\n\t"
-		"sd\t%3,24(%0)\n\t"
-		"cache\t%7,32(%0)\n\t"
-		"daddiu\t%0,64\n\t"
-		"daddiu\t%1,64\n\t"
-		"ld\t%2,-32(%1)\n\t"
-		"ld\t%3,-24(%1)\n\t"
-		"sd\t%2,-32(%0)\n\t"
-		"sd\t%3,-24(%0)\n\t"
-		"cache\t%7,-16(%0)\n\t"
-		"ld\t%2,-16(%1)\n\t"
-		"ld\t%3,-8(%1)\n\t"
-		"sd\t%2,-16(%0)\n\t"
-		"bne\t$1,%0,1b\n\t"
-		" sd\t%3,-8(%0)\n\t"
-		".set\tat\n\t"
-		".set\treorder"
-		:"=r" (dummy1), "=r" (dummy2), "=&r" (reg1), "=&r" (reg2)
-		:"0" (to), "1" (from), "I" (PAGE_SIZE),
-		 "i" (Create_Dirty_Excl_SD));
-}
-
-void r4k_copy_page_s32(void * to, void * from)
-{
-	unsigned long dummy1, dummy2, reg1, reg2;
-
-	__asm__ __volatile__(
-		".set\tnoreorder\n\t"
-		".set\tnoat\n\t"
-		"daddiu\t$1,%0,%6\n"
-		"1:\tcache\t%7,(%0)\n\t"
-		"ld\t%2,(%1)\n\t"
-		"ld\t%3,8(%1)\n\t"
-		"sd\t%2,(%0)\n\t"
-		"sd\t%3,8(%0)\n\t"
-		"ld\t%2,16(%1)\n\t"
-		"ld\t%3,24(%1)\n\t"
-		"sd\t%2,16(%0)\n\t"
-		"sd\t%3,24(%0)\n\t"
-		"cache\t%7,32(%0)\n\t"
-		"daddiu\t%0,64\n\t"
-		"daddiu\t%1,64\n\t"
-		"ld\t%2,-32(%1)\n\t"
-		"ld\t%3,-24(%1)\n\t"
-		"sd\t%2,-32(%0)\n\t"
-		"sd\t%3,-24(%0)\n\t"
-		"ld\t%2,-16(%1)\n\t"
-		"ld\t%3,-8(%1)\n\t"
-		"sd\t%2,-16(%0)\n\t"
-		"bne\t$1,%0,1b\n\t"
-		" sd\t%3,-8(%0)\n\t"
-		".set\tat\n\t"
-		".set\treorder"
-		:"=r" (dummy1), "=r" (dummy2), "=&r" (reg1), "=&r" (reg2)
-		:"0" (to), "1" (from), "I" (PAGE_SIZE),
-		 "i" (Create_Dirty_Excl_SD));
-}
-
-void r4k_copy_page_s64(void * to, void * from)
-{
-	unsigned long dummy1, dummy2, reg1, reg2;
-
-	__asm__ __volatile__(
-		".set\tnoreorder\n\t"
-		".set\tnoat\n\t"
-		"daddiu\t$1,%0,%6\n"
-		"1:\tcache\t%7,(%0)\n\t"
-		"ld\t%2,(%1)\n\t"
-		"ld\t%3,8(%1)\n\t"
-		"sd\t%2,(%0)\n\t"
-		"sd\t%3,8(%0)\n\t"
-		"ld\t%2,16(%1)\n\t"
-		"ld\t%3,24(%1)\n\t"
-		"sd\t%2,16(%0)\n\t"
-		"sd\t%3,24(%0)\n\t"
-		"daddiu\t%0,64\n\t"
-		"daddiu\t%1,64\n\t"
-		"ld\t%2,-32(%1)\n\t"
-		"ld\t%3,-24(%1)\n\t"
-		"sd\t%2,-32(%0)\n\t"
-		"sd\t%3,-24(%0)\n\t"
-		"ld\t%2,-16(%1)\n\t"
-		"ld\t%3,-8(%1)\n\t"
-		"sd\t%2,-16(%0)\n\t"
-		"bne\t$1,%0,1b\n\t"
-		" sd\t%3,-8(%0)\n\t"
-		".set\tat\n\t"
-		".set\treorder"
-		:"=r" (dummy1), "=r" (dummy2), "=&r" (reg1), "=&r" (reg2)
-		:"0" (to), "1" (from), "I" (PAGE_SIZE),
-		 "i" (Create_Dirty_Excl_SD));
-}
-
-void r4k_copy_page_s128(void * to, void * from)
-{
-	unsigned long dummy1, dummy2;
-	unsigned long reg1, reg2, reg3, reg4;
-
-	__asm__ __volatile__(
-		".set\tnoreorder\n\t"
-		".set\tnoat\n\t"
-		"daddiu\t$1,%0,%8\n"
-		"1:\tcache\t%9,(%0)\n\t"
-		"ld\t%2,(%1)\n\t"
-		"ld\t%3,8(%1)\n\t"
-		"ld\t%4,16(%1)\n\t"
-		"ld\t%5,24(%1)\n\t"
-		"sd\t%2,(%0)\n\t"
-		"sd\t%3,8(%0)\n\t"
-		"sd\t%4,16(%0)\n\t"
-		"sd\t%5,24(%0)\n\t"
-		"ld\t%2,32(%1)\n\t"
-		"ld\t%3,40(%1)\n\t"
-		"ld\t%4,48(%1)\n\t"
-		"ld\t%5,56(%1)\n\t"
-		"sd\t%2,32(%0)\n\t"
-		"sd\t%3,40(%0)\n\t"
-		"sd\t%4,48(%0)\n\t"
-		"sd\t%5,56(%0)\n\t"
-		"daddiu\t%0,128\n\t"
-		"daddiu\t%1,128\n\t"
-		"ld\t%2,-64(%1)\n\t"
-		"ld\t%3,-56(%1)\n\t"
-		"ld\t%4,-48(%1)\n\t"
-		"ld\t%5,-40(%1)\n\t"
-		"sd\t%2,-64(%0)\n\t"
-		"sd\t%3,-56(%0)\n\t"
-		"sd\t%4,-48(%0)\n\t"
-		"sd\t%5,-40(%0)\n\t"
-		"ld\t%2,-32(%1)\n\t"
-		"ld\t%3,-24(%1)\n\t"
-		"ld\t%4,-16(%1)\n\t"
-		"ld\t%5,-8(%1)\n\t"
-		"sd\t%2,-32(%0)\n\t"
-		"sd\t%3,-24(%0)\n\t"
-		"sd\t%4,-16(%0)\n\t"
-		"bne\t$1,%0,1b\n\t"
-		" sd\t%5,-8(%0)\n\t"
-		".set\tat\n\t"
-		".set\treorder"
-		:"=r" (dummy1), "=r" (dummy2),
-		 "=&r" (reg1), "=&r" (reg2), "=&r" (reg3), "=&r" (reg4)
-		:"0" (to), "1" (from),
-		 "I" (PAGE_SIZE),
-		 "i" (Create_Dirty_Excl_SD));
-}
-
-/*
- * This version has been tuned on an Origin.  For other machines the arguments
- * of the pref instructin may have to be tuned differently.
- */
-void andes_copy_page(void * to, void * from)
-{
-	unsigned long dummy1, dummy2, reg1, reg2, reg3, reg4;
-
-	__asm__ __volatile__(
-		".set\tpush\n\t"
-		".set\tmips4\n\t"
-		".set\tnoreorder\n\t"
-		".set\tnoat\n\t"
-		"daddiu\t$1,%0,%8\n"
-		"1:\tpref\t0,2*128(%1)\n\t"
-		"pref\t1,2*128(%0)\n\t"
-		"ld\t%2,(%1)\n\t"
-		"ld\t%3,8(%1)\n\t"
-		"ld\t%4,16(%1)\n\t"
-		"ld\t%5,24(%1)\n\t"
-		"sd\t%2,(%0)\n\t"
-		"sd\t%3,8(%0)\n\t"
-		"sd\t%4,16(%0)\n\t"
-		"sd\t%5,24(%0)\n\t"
-		"daddiu\t%0,64\n\t"
-		"daddiu\t%1,64\n\t"
-		"ld\t%2,-32(%1)\n\t"
-		"ld\t%3,-24(%1)\n\t"
-		"ld\t%4,-16(%1)\n\t"
-		"ld\t%5,-8(%1)\n\t"
-		"sd\t%2,-32(%0)\n\t"
-		"sd\t%3,-24(%0)\n\t"
-		"sd\t%4,-16(%0)\n\t"
-		"bne\t$1,%0,1b\n\t"
-		" sd\t%5,-8(%0)\n\t"
-		".set\tpop\n\t"
-		:"=r" (dummy1), "=r" (dummy2), "=&r" (reg1), "=&r" (reg2),
-		 "=&r" (reg3), "=&r" (reg4)
-		:"0" (to), "1" (from), "I" (PAGE_SIZE));
-}
--- diff/arch/mips/mm/loadmmu.c	2003-07-08 09:55:17.000000000 +0100
+++ source/arch/mips/mm/loadmmu.c	1970-01-01 01:00:00.000000000 +0100
@@ -1,120 +0,0 @@
-/*
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
- * Copyright (C) 1997, 1999, 2000, 2001, 2002, 2003 Ralf Baechle (ralf@gnu.org)
- * Copyright (C) 1999 Silicon Graphics, Inc.
- * Kevin D. Kissell, kevink@mips.com and Carsten Langgaard, carstenl@mips.com
- * Copyright (C) 2000 MIPS Technologies, Inc.  All rights reserved.
- */
-#include <linux/config.h>
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/mm.h>
-#include <linux/module.h>
-
-#include <asm/bootinfo.h>
-#include <asm/cpu.h>
-#include <asm/page.h>
-#include <asm/pgtable.h>
-#include <asm/system.h>
-
-/* memory functions */
-void (*_clear_page)(void * page);
-void (*_copy_page)(void * to, void * from);
-
-/* Cache operations. */
-void (*flush_cache_all)(void);
-void (*__flush_cache_all)(void);
-void (*flush_cache_mm)(struct mm_struct *mm);
-void (*flush_cache_range)(struct vm_area_struct *vma, unsigned long start,
-	unsigned long end);
-void (*flush_cache_page)(struct vm_area_struct *vma, unsigned long page);
-void (*flush_icache_range)(unsigned long start, unsigned long end);
-void (*flush_icache_page)(struct vm_area_struct *vma, struct page *page);
-
-/* MIPS specific cache operations */
-void (*flush_cache_sigtramp)(unsigned long addr);
-void (*flush_data_cache_page)(unsigned long addr);
-void (*flush_icache_all)(void);
-
-#ifdef CONFIG_NONCOHERENT_IO
-
-/* DMA cache operations. */
-void (*_dma_cache_wback_inv)(unsigned long start, unsigned long size);
-void (*_dma_cache_wback)(unsigned long start, unsigned long size);
-void (*_dma_cache_inv)(unsigned long start, unsigned long size);
-
-EXPORT_SYMBOL(_dma_cache_wback_inv);
-EXPORT_SYMBOL(_dma_cache_wback);
-EXPORT_SYMBOL(_dma_cache_inv);
-
-#endif /* CONFIG_NONCOHERENT_IO */
-
-extern void ld_mmu_r23000(void);
-extern void ld_mmu_r4xx0(void);
-extern void ld_mmu_tx39(void);
-extern void ld_mmu_r6000(void);
-extern void ld_mmu_tfp(void);
-extern void ld_mmu_andes(void);
-extern void ld_mmu_sb1(void);
-extern void sb1_tlb_init(void);
-extern void r3k_tlb_init(void);
-extern void r4k_tlb_init(void);
-extern void sb1_tlb_init(void);
-
-void __init load_mmu(void)
-{
-	if (cpu_has_4ktlb) {
-#if defined(CONFIG_CPU_R4X00)  || defined(CONFIG_CPU_VR41XX) || \
-    defined(CONFIG_CPU_R4300)  || defined(CONFIG_CPU_R5000)  || \
-    defined(CONFIG_CPU_NEVADA) || defined(CONFIG_CPU_R5432)  || \
-    defined(CONFIG_CPU_R5500)  || defined(CONFIG_CPU_MIPS32) || \
-    defined(CONFIG_CPU_MIPS64) || defined(CONFIG_CPU_TX49XX) || \
-    defined(CONFIG_CPU_RM7000)
-		ld_mmu_r4xx0();
-		r4k_tlb_init();
-#endif
-	} else switch (current_cpu_data.cputype) {
-#ifdef CONFIG_CPU_R3000
-	case CPU_R2000:
-	case CPU_R3000:
-	case CPU_R3000A:
-	case CPU_R3081E:
-		ld_mmu_r23000();
-		r3k_tlb_init();
-		break;
-#endif
-#ifdef CONFIG_CPU_TX39XX
-	case CPU_TX3912:
-	case CPU_TX3922:
-	case CPU_TX3927:
-		ld_mmu_tx39();
-		r3k_tlb_init();
-		break;
-#endif
-#ifdef CONFIG_CPU_R10000
-	case CPU_R10000:
-	case CPU_R12000:
-		ld_mmu_r4xx0();
-		andes_tlb_init();
-		break;
-#endif
-#ifdef CONFIG_CPU_SB1
-	case CPU_SB1:
-		ld_mmu_sb1();
-		sb1_tlb_init();
-		break;
-#endif
-
-	case CPU_R8000:
-		panic("R8000 is unsupported");
-		break;
-
-	default:
-		panic("Yeee, unsupported mmu/cache architecture.");
-	}
-}
--- diff/arch/mips/mm/pg-r3k.c	2003-08-20 14:16:25.000000000 +0100
+++ source/arch/mips/mm/pg-r3k.c	1970-01-01 01:00:00.000000000 +0100
@@ -1,81 +0,0 @@
-/*
- * Copyright (C) 2001 Ralf Baechle (ralf@gnu.org)
- */
-#include <linux/sched.h>
-#include <linux/mm.h>
-
-/* page functions */
-void r3k_clear_page(void * page)
-{
-	__asm__ __volatile__(
-		".set\tnoreorder\n\t"
-		".set\tnoat\n\t"
-		"addiu\t$1,%0,%2\n"
-		"1:\tsw\t$0,(%0)\n\t"
-		"sw\t$0,4(%0)\n\t"
-		"sw\t$0,8(%0)\n\t"
-		"sw\t$0,12(%0)\n\t"
-		"addiu\t%0,32\n\t"
-		"sw\t$0,-16(%0)\n\t"
-		"sw\t$0,-12(%0)\n\t"
-		"sw\t$0,-8(%0)\n\t"
-		"bne\t$1,%0,1b\n\t"
-		"sw\t$0,-4(%0)\n\t"
-		".set\tat\n\t"
-		".set\treorder"
-		: "=r" (page)
-		: "0" (page), "I" (PAGE_SIZE)
-		: "memory");
-}
-
-void r3k_copy_page(void * to, void * from)
-{
-	unsigned long dummy1, dummy2;
-	unsigned long reg1, reg2, reg3, reg4;
-
-	__asm__ __volatile__(
-		".set\tnoreorder\n\t"
-		".set\tnoat\n\t"
-		"addiu\t$1,%0,%8\n"
-		"1:\tlw\t%2,(%1)\n\t"
-		"lw\t%3,4(%1)\n\t"
-		"lw\t%4,8(%1)\n\t"
-		"lw\t%5,12(%1)\n\t"
-		"sw\t%2,(%0)\n\t"
-		"sw\t%3,4(%0)\n\t"
-		"sw\t%4,8(%0)\n\t"
-		"sw\t%5,12(%0)\n\t"
-		"lw\t%2,16(%1)\n\t"
-		"lw\t%3,20(%1)\n\t"
-		"lw\t%4,24(%1)\n\t"
-		"lw\t%5,28(%1)\n\t"
-		"sw\t%2,16(%0)\n\t"
-		"sw\t%3,20(%0)\n\t"
-		"sw\t%4,24(%0)\n\t"
-		"sw\t%5,28(%0)\n\t"
-		"addiu\t%0,64\n\t"
-		"addiu\t%1,64\n\t"
-		"lw\t%2,-32(%1)\n\t"
-		"lw\t%3,-28(%1)\n\t"
-		"lw\t%4,-24(%1)\n\t"
-		"lw\t%5,-20(%1)\n\t"
-		"sw\t%2,-32(%0)\n\t"
-		"sw\t%3,-28(%0)\n\t"
-		"sw\t%4,-24(%0)\n\t"
-		"sw\t%5,-20(%0)\n\t"
-		"lw\t%2,-16(%1)\n\t"
-		"lw\t%3,-12(%1)\n\t"
-		"lw\t%4,-8(%1)\n\t"
-		"lw\t%5,-4(%1)\n\t"
-		"sw\t%2,-16(%0)\n\t"
-		"sw\t%3,-12(%0)\n\t"
-		"sw\t%4,-8(%0)\n\t"
-		"bne\t$1,%0,1b\n\t"
-		"sw\t%5,-4(%0)\n\t"
-		".set\tat\n\t"
-		".set\treorder"
-		: "=r" (dummy1), "=r" (dummy2),
-		  "=&r" (reg1), "=&r" (reg2), "=&r" (reg3), "=&r" (reg4)
-		: "0" (to), "1" (from),
-		  "I" (PAGE_SIZE));
-}
--- diff/arch/mips/pci/common.c	2003-08-20 14:16:25.000000000 +0100
+++ source/arch/mips/pci/common.c	1970-01-01 01:00:00.000000000 +0100
@@ -1,72 +0,0 @@
-#include <linux/config.h>
-#include <linux/init.h>
-#include <linux/pci.h>
-
-void __init pcibios_fixup_bus(struct pci_bus *b)
-{
-}
-
-static int pcibios_enable_resources(struct pci_dev *dev, int mask)
-{
-	u16 cmd, old_cmd;
-	int idx;
-	struct resource *r;
-
-	pci_read_config_word(dev, PCI_COMMAND, &cmd);
-	old_cmd = cmd;
-	for (idx = 0; idx < 6; idx++) {
-		/* Only set up the requested stuff */
-		if (!(mask & (1 << idx)))
-			continue;
-
-		r = &dev->resource[idx];
-		if (!r->start && r->end) {
-			printk(KERN_ERR
-			       "PCI: Device %s not available because of resource collisions\n",
-			       pci_name(dev));
-			return -EINVAL;
-		}
-		if (r->flags & IORESOURCE_IO)
-			cmd |= PCI_COMMAND_IO;
-		if (r->flags & IORESOURCE_MEM)
-			cmd |= PCI_COMMAND_MEMORY;
-	}
-	if (dev->resource[PCI_ROM_RESOURCE].start)
-		cmd |= PCI_COMMAND_MEMORY;
-	if (cmd != old_cmd) {
-		printk("PCI: Enabling device %s (%04x -> %04x)\n",
-		       pci_name(dev), old_cmd, cmd);
-		pci_write_config_word(dev, PCI_COMMAND, cmd);
-	}
-	return 0;
-}
-
-int pcibios_enable_device(struct pci_dev *dev, int mask)
-{
-	int err;
-
-	if ((err = pcibios_enable_resources(dev, mask)) < 0)
-		return err;
-
-	return 0;
-}
-
-void __init pcibios_align_resource(void *data, struct resource *res,
-				   unsigned long size, unsigned long align)
-{
-	panic("Uhhoh called pcibios_align_resource");
-}
-
-unsigned __init int pcibios_assign_all_busses(void)
-{
-	return 1;
-}
-
-char *pcibios_setup(char *str)
-{
-	return str;
-}
-
-struct pci_fixup pcibios_fixups[] = {
-	{0}
-};
--- diff/arch/mips/pci/fixups-ev96100.c	2003-07-08 09:55:17.000000000 +0100
+++ source/arch/mips/pci/fixups-ev96100.c	1970-01-01 01:00:00.000000000 +0100
@@ -1,91 +0,0 @@
-/*
- *
- * BRIEF MODULE DESCRIPTION
- *	EV96100 Board specific pci fixups.
- *
- * Copyright 2001 MontaVista Software Inc.
- * Author: MontaVista Software, Inc.
- *         	ppopov@mvista.com or source@mvista.com
- *
- *  This program is free software; you can redistribute  it and/or modify it
- *  under  the terms of  the GNU General  Public License as published by the
- *  Free Software Foundation;  either version 2 of the  License, or (at your
- *  option) any later version.
- *
- *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
- *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
- *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
- *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
- *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
- *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- *  You should have received a copy of the  GNU General Public License along
- *  with this program; if not, write  to the Free Software Foundation, Inc.,
- *  675 Mass Ave, Cambridge, MA 02139, USA.
- */
-#include <linux/types.h>
-#include <linux/pci.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/pci_ids.h>
-
-#include <asm/gt64120.h>
-#include <asm/galileo-boards/ev96100.h>
-
-extern unsigned short get_gt_devid(void);
-
-void __init pcibios_fixup_resources(struct pci_dev *dev)
-{
-}
-
-void __init pcibios_fixup(void)
-{
-}
-
-void __init pcibios_fixup_irqs(void)
-{
-	struct pci_dev *dev = NULL;
-	unsigned int slot;
-	u32 vendor;
-	unsigned short gt_devid = get_gt_devid();
-
-	/*
-	 ** EV96100/A interrupt routing for pci bus 0
-	 **
-	 ** Note: EV96100A board with irq jumper set on 'VxWorks'
-	 ** for EV96100 compatibility.
-	 */
-
-	while ((dev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) {
-		if (dev->bus->number != 0)
-			return;
-
-		slot = PCI_SLOT(dev->devfn);
-		pci_read_config_dword(dev, PCI_SUBSYSTEM_VENDOR_ID,
-				      &vendor);
-
-#ifdef DEBUG
-		printk("devfn %x, slot %d devid %x\n",
-		       dev->devfn, slot, gt_devid);
-#endif
-
-		/* fixup irq line based on slot # */
-		if (slot == 8) {
-			dev->irq = 5;
-			pci_write_config_byte(dev, PCI_INTERRUPT_LINE,
-					      dev->irq);
-		} else if (slot == 9) {
-			dev->irq = 2;
-			pci_write_config_byte(dev, PCI_INTERRUPT_LINE,
-					      dev->irq);
-		}
-	}
-}
-unsigned int pcibios_assign_all_busses(void)
-{
-	return 0;
-}
--- diff/arch/mips/pci/ops-ev64120.c	2003-08-20 14:16:25.000000000 +0100
+++ source/arch/mips/pci/ops-ev64120.c	1970-01-01 01:00:00.000000000 +0100
@@ -1,1201 +0,0 @@
-/*
- * BRIEF MODULE DESCRIPTION
- * Galileo Evaluation Boards PCI support.
- *
- * The general-purpose functions to read/write and configure the GT64120A's
- * PCI registers (function names start with pci0 or pci1) are either direct
- * copies of functions written by Galileo Technology, or are modifications
- * of their functions to work with Linux 2.4 vs Linux 2.2.  These functions
- * are Copyright - Galileo Technology.
- *
- * Other functions are derived from other MIPS PCI implementations, or were
- * written by RidgeRun, Inc,  Copyright (C) 2000 RidgeRun, Inc.
- *   glonnon@ridgerun.com, skranz@ridgerun.com, stevej@ridgerun.com
- *
- *  This program is free software; you can redistribute  it and/or modify it
- *  under  the terms of  the GNU General  Public License as published by the
- *  Free Software Foundation;  either version 2 of the  License, or (at your
- *  option) any later version.
- *
- *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
- *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
- *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
- *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
- *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
- *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- *  You should have received a copy of the  GNU General Public License along
- *  with this program; if not, write  to the Free Software Foundation, Inc.,
- *  675 Mass Ave, Cambridge, MA 02139, USA.
- */
-#include <linux/types.h>
-#include <linux/pci.h>
-#include <linux/kernel.h>
-#include <linux/slab.h>
-#include <linux/version.h>
-#include <asm/pci.h>
-#include <asm/io.h>
-#include <asm/galileo-boards/ev64120.h>
-#include <asm/gt64120.h>
-
-#include <linux/init.h>
-
-#undef PCI_DEBUG
-
-#ifdef PCI_DEBUG
-#define DBG(x...) printk(x)
-#else
-#define DBG(x...)
-#endif
-
-#define SELF 0
-
-/*
- * These functions and structures provide the BIOS scan and mapping of the PCI
- * devices.
- */
-
-#define MAX_PCI_DEVS 10
-
-struct pci_device {
-	u32 slot;
-	u32 BARtype[6];
-	u32 BARsize[6];
-};
-
-static void __init scan_and_initialize_pci(void);
-static u32 __init scan_pci_bus(struct pci_device *pci_devices);
-static void __init allocate_pci_space(struct pci_device *pci_devices);
-
-static void __devinit galileo_pcibios_fixup_bus(struct pci_bus *bus);
-
-/*
- * The functions that actually read and write to the controller.
- * Copied from or modified from Galileo Technology code.
- */
-static unsigned int pci0ReadConfigReg(int offset, struct pci_dev *device);
-static void pci0WriteConfigReg(unsigned int offset,
-			       struct pci_dev *device, unsigned int data);
-static unsigned int pci1ReadConfigReg(int offset, struct pci_dev *device);
-static void pci1WriteConfigReg(unsigned int offset,
-			       struct pci_dev *device, unsigned int data);
-
-static void pci0MapIOspace(unsigned int pci0IoBase,
-			   unsigned int pci0IoLength);
-static void pci1MapIOspace(unsigned int pci1IoBase,
-			   unsigned int pci1IoLength);
-static void pci0MapMemory0space(unsigned int pci0Mem0Base,
-				unsigned int pci0Mem0Length);
-static void pci1MapMemory0space(unsigned int pci1Mem0Base,
-				unsigned int pci1Mem0Length);
-static void pci0MapMemory1space(unsigned int pci0Mem1Base,
-				unsigned int pci0Mem1Length);
-static void pci1MapMemory1space(unsigned int pci1Mem1Base,
-				unsigned int pci1Mem1Length);
-static unsigned int pci0GetIOspaceBase(void);
-static unsigned int pci0GetIOspaceSize(void);
-static unsigned int pci0GetMemory0Base(void);
-static unsigned int pci0GetMemory0Size(void);
-static unsigned int pci0GetMemory1Base(void);
-static unsigned int pci0GetMemory1Size(void);
-static unsigned int pci1GetIOspaceBase(void);
-static unsigned int pci1GetIOspaceSize(void);
-static unsigned int pci1GetMemory0Base(void);
-static unsigned int pci1GetMemory0Size(void);
-static unsigned int pci1GetMemory1Base(void);
-static unsigned int pci1GetMemory1Size(void);
-
-
-/*  Functions to implement "pci ops"  */
-static int galileo_pcibios_read_config_word(struct pci_dev *dev,
-					    int offset, u16 * val);
-static int galileo_pcibios_read_config_byte(struct pci_dev *dev,
-					    int offset, u8 * val);
-static int galileo_pcibios_read_config_dword(struct pci_dev *dev,
-					     int offset, u32 * val);
-static int galileo_pcibios_write_config_byte(struct pci_dev *dev,
-					     int offset, u8 val);
-static int galileo_pcibios_write_config_word(struct pci_dev *dev,
-					     int offset, u16 val);
-static int galileo_pcibios_write_config_dword(struct pci_dev *dev,
-					      int offset, u32 val);
-static void galileo_pcibios_set_master(struct pci_dev *dev);
-
-/*
- * General-purpose PCI functions.
- */
-
-/*
- * pci0MapIOspace - Maps PCI0 IO space for the master.
- * Inputs: base and length of pci0Io
- */
-static void pci0MapIOspace(unsigned int pci0IoBase,
-			   unsigned int pci0IoLength)
-{
-	unsigned int pci0IoTop =
-	    (unsigned int) (pci0IoBase + pci0IoLength);
-
-	if (pci0IoLength == 0)
-		pci0IoTop++;
-
-	pci0IoBase = (unsigned int) (pci0IoBase >> 21);
-	pci0IoTop = (unsigned int) (((pci0IoTop - 1) & 0x0fffffff) >> 21);
-	GT_WRITE(GT_PCI0IOLD_OFS, pci0IoBase);
-	GT_WRITE(GT_PCI0IOHD_OFS, pci0IoTop);
-}
-
-/*
- * pci1MapIOspace - Maps PCI1 IO space for the master.
- * Inputs: base and length of pci1Io
- */
-
-static void pci1MapIOspace(unsigned int pci1IoBase,
-			   unsigned int pci1IoLength)
-{
-	unsigned int pci1IoTop =
-	    (unsigned int) (pci1IoBase + pci1IoLength);
-
-	if (pci1IoLength == 0)
-		pci1IoTop++;
-
-	pci1IoBase = (unsigned int) (pci1IoBase >> 21);
-	pci1IoTop = (unsigned int) (((pci1IoTop - 1) & 0x0fffffff) >> 21);
-	GT_WRITE(GT_PCI1IOLD_OFS, pci1IoBase);
-	GT_WRITE(GT_PCI1IOHD_OFS, pci1IoTop);
-}
-
-/*
- * pci0MapMemory0space - Maps PCI0 memory0 space for the master.
- * Inputs: base and length of pci0Mem0
- */
-
-static void pci0MapMemory0space(unsigned int pci0Mem0Base,
-				unsigned int pci0Mem0Length)
-{
-	unsigned int pci0Mem0Top = pci0Mem0Base + pci0Mem0Length;
-
-	if (pci0Mem0Length == 0)
-		pci0Mem0Top++;
-
-	pci0Mem0Base = pci0Mem0Base >> 21;
-	pci0Mem0Top = ((pci0Mem0Top - 1) & 0x0fffffff) >> 21;
-	GT_WRITE(GT_PCI0M0LD_OFS, pci0Mem0Base);
-	GT_WRITE(GT_PCI0M0HD_OFS, pci0Mem0Top);
-}
-
-/*
- * pci1MapMemory0space - Maps PCI1 memory0 space for the master.
- * Inputs: base and length of pci1Mem0
- */
-
-static void pci1MapMemory0space(unsigned int pci1Mem0Base,
-				unsigned int pci1Mem0Length)
-{
-	unsigned int pci1Mem0Top = pci1Mem0Base + pci1Mem0Length;
-
-	if (pci1Mem0Length == 0)
-		pci1Mem0Top++;
-
-	pci1Mem0Base = pci1Mem0Base >> 21;
-	pci1Mem0Top = ((pci1Mem0Top - 1) & 0x0fffffff) >> 21;
-	GT_WRITE(GT_PCI1M0LD_OFS, pci1Mem0Base);
-	GT_WRITE(GT_PCI1M0HD_OFS, pci1Mem0Top);
-}
-
-/*
- * pci0MapMemory1space - Maps PCI0 memory1 space for the master.
- * Inputs: base and length of pci0Mem1
- */
-
-static void pci0MapMemory1space(unsigned int pci0Mem1Base,
-				unsigned int pci0Mem1Length)
-{
-	unsigned int pci0Mem1Top = pci0Mem1Base + pci0Mem1Length;
-
-	if (pci0Mem1Length == 0)
-		pci0Mem1Top++;
-
-	pci0Mem1Base = pci0Mem1Base >> 21;
-	pci0Mem1Top = ((pci0Mem1Top - 1) & 0x0fffffff) >> 21;
-	GT_WRITE(GT_PCI0M1LD_OFS, pci0Mem1Base);
-	GT_WRITE(GT_PCI0M1HD_OFS, pci0Mem1Top);
-
-}
-
-/*
- * pci1MapMemory1space - Maps PCI1 memory1 space for the master.
- * Inputs: base and length of pci1Mem1
- */
-
-static void pci1MapMemory1space(unsigned int pci1Mem1Base,
-				unsigned int pci1Mem1Length)
-{
-	unsigned int pci1Mem1Top = pci1Mem1Base + pci1Mem1Length;
-
-	if (pci1Mem1Length == 0)
-		pci1Mem1Top++;
-
-	pci1Mem1Base = pci1Mem1Base >> 21;
-	pci1Mem1Top = ((pci1Mem1Top - 1) & 0x0fffffff) >> 21;
-	GT_WRITE(GT_PCI1M1LD_OFS, pci1Mem1Base);
-	GT_WRITE(GT_PCI1M1HD_OFS, pci1Mem1Top);
-}
-
-/*
- * pci0GetIOspaceBase - Return PCI0 IO Base Address.
- * Inputs: N/A
- * Returns: PCI0 IO Base Address.
- */
-
-static unsigned int pci0GetIOspaceBase(void)
-{
-	unsigned int base;
-	GT_READ(GT_PCI0IOLD_OFS, &base);
-	base = base << 21;
-	return base;
-}
-
-/*
- * pci0GetIOspaceSize - Return PCI0 IO Bar Size.
- * Inputs: N/A
- * Returns: PCI0 IO Bar Size.
- */
-static unsigned int pci0GetIOspaceSize(void)
-{
-	unsigned int top, base, size;
-	GT_READ(GT_PCI0IOLD_OFS, &base);
-	base = base << 21;
-	GT_READ(GT_PCI0IOHD_OFS, &top);
-	top = (top << 21);
-	size = ((top - base) & 0xfffffff);
-	size = size | 0x1fffff;
-	return (size + 1);
-}
-
-/*
- * pci0GetMemory0Base - Return PCI0 Memory 0 Base Address.
- * Inputs: N/A
- * Returns: PCI0 Memory 0 Base Address.
- */
-static unsigned int pci0GetMemory0Base(void)
-{
-	unsigned int base;
-	GT_READ(GT_PCI0M0LD_OFS, &base);
-	base = base << 21;
-	return base;
-}
-
-/*
- * pci0GetMemory0Size - Return PCI0 Memory 0 Bar Size.
- * Inputs: N/A
- * Returns: PCI0 Memory 0 Bar Size.
- */
-static unsigned int pci0GetMemory0Size(void)
-{
-	unsigned int top, base, size;
-	GT_READ(GT_PCI0M0LD_OFS, &base);
-	base = base << 21;
-	GT_READ(GT_PCI0M0HD_OFS, &top);
-	top = (top << 21);
-	size = ((top - base) & 0xfffffff);
-	size = size | 0x1fffff;
-	return (size + 1);
-}
-
-/*
- * pci0GetMemory1Base - Return PCI0 Memory 1 Base Address.
- * Inputs: N/A
- * Returns: PCI0 Memory 1 Base Address.
- */
-static unsigned int pci0GetMemory1Base(void)
-{
-	unsigned int base;
-	GT_READ(GT_PCI0M1LD_OFS, &base);
-	base = base << 21;
-	return base;
-}
-
-/*
- * pci0GetMemory1Size - Return PCI0 Memory 1 Bar Size.
- * Inputs: N/A
- * Returns: PCI0 Memory 1 Bar Size.
- */
-
-static unsigned int pci0GetMemory1Size(void)
-{
-	unsigned int top, base, size;
-	GT_READ(GT_PCI0M1LD_OFS, &base);
-	base = base << 21;
-	GT_READ(GT_PCI0M1HD_OFS, &top);
-	top = (top << 21);
-	size = ((top - base) & 0xfffffff);
-	size = size | 0x1fffff;
-	return (size + 1);
-}
-
-/*
- * pci1GetIOspaceBase - Return PCI1 IO Base Address.
- * Inputs: N/A
- * Returns: PCI1 IO Base Address.
- */
-
-static unsigned int pci1GetIOspaceBase(void)
-{
-	unsigned int base;
-	GT_READ(GT_PCI1IOLD_OFS, &base);
-	base = base << 21;
-	return base;
-}
-
-/*
- * pci1GetIOspaceSize - Return PCI1 IO Bar Size.
- * Inputs: N/A
- * Returns: PCI1 IO Bar Size.
- */
-
-static unsigned int pci1GetIOspaceSize(void)
-{
-	unsigned int top, base, size;
-	GT_READ(GT_PCI1IOLD_OFS, &base);
-	base = base << 21;
-	GT_READ(GT_PCI1IOHD_OFS, &top);
-	top = (top << 21);
-	size = ((top - base) & 0xfffffff);
-	size = size | 0x1fffff;
-	return (size + 1);
-}
-
-/*
- * pci1GetMemory0Base - Return PCI1 Memory 0 Base Address.
- * Inputs: N/A
- * Returns: PCI1 Memory 0 Base Address.
- */
-
-static unsigned int pci1GetMemory0Base(void)
-{
-	unsigned int base;
-	GT_READ(GT_PCI1M0LD_OFS, &base);
-	base = base << 21;
-	return base;
-}
-
-/*
- * pci1GetMemory0Size - Return PCI1 Memory 0 Bar Size.
- * Inputs: N/A
- * Returns: PCI1 Memory 0 Bar Size.
- */
-
-static unsigned int pci1GetMemory0Size(void)
-{
-	unsigned int top, base, size;
-	GT_READ(GT_PCI1M1LD_OFS, &base);
-	base = base << 21;
-	GT_READ(GT_PCI1M1HD_OFS, &top);
-	top = (top << 21);
-	size = ((top - base) & 0xfffffff);
-	size = size | 0x1fffff;
-	return (size + 1);
-}
-
-/*
- * pci1GetMemory1Base - Return PCI1 Memory 1 Base Address.
- * Inputs: N/A
- * Returns: PCI1 Memory 1 Base Address.
- */
-
-static unsigned int pci1GetMemory1Base(void)
-{
-	unsigned int base;
-	GT_READ(GT_PCI1M1LD_OFS, &base);
-	base = base << 21;
-	return base;
-}
-
-/*
- * pci1GetMemory1Size - Return PCI1 Memory 1 Bar Size.
- * Inputs: N/A
- * Returns: PCI1 Memory 1 Bar Size.
- */
-
-static unsigned int pci1GetMemory1Size(void)
-{
-	unsigned int top, base, size;
-	GT_READ(GT_PCI1M1LD_OFS, &base);
-	base = base << 21;
-	GT_READ(GT_PCI1M1HD_OFS, &top);
-	top = (top << 21);
-	size = ((top - base) & 0xfffffff);
-	size = size | 0x1fffff;
-	return (size + 1);
-}
-
-
-
-/*
- * pci_range_ck -
- *
- * Check if the pci device that are trying to access does really exists
- * on the evaluation board.
- *
- * Inputs :
- * bus - bus number (0 for PCI 0 ; 1 for PCI 1)
- * dev - number of device on the specific pci bus
- *
- * Outpus :
- * 0 - if OK , 1 - if failure
- */
-static __inline__ int pci_range_ck(unsigned char bus, unsigned char dev)
-{
-	//DBG(KERN_INFO "p_r_c %d %d\n",bus,dev);
-	if (((bus == 0) || (bus == 1)) && (dev >= 6) && (dev <= 8))
-		return 0;	// Bus/Device Number OK
-	return -1;		// Bus/Device Number not OK
-}
-
-/*
- * pciXReadConfigReg  - Read from a PCI configuration register
- *                    - Make sure the GT is configured as a master before
- *                      reading from another device on the PCI.
- *                   - The function takes care of Big/Little endian conversion.
- * INPUTS:   regOffset: The register offset as it apears in the GT spec (or PCI
- *                        spec)
- *           pciDevNum: The device number needs to be addressed.
- * RETURNS: data , if the data == 0xffffffff check the master abort bit in the
- *                 cause register to make sure the data is valid
- *
- *  Configuration Address 0xCF8:
- *
- *       31 30    24 23  16 15  11 10     8 7      2  0     <=bit Number
- *  |congif|Reserved|  Bus |Device|Function|Register|00|
- *  |Enable|        |Number|Number| Number | Number |  |    <=field Name
- *
- */
-static unsigned int pci0ReadConfigReg(int offset, struct pci_dev *device)
-{
-	unsigned int DataForRegCf8;
-	unsigned int data;
-
-	DataForRegCf8 = ((PCI_SLOT(device->devfn) << 11) |
-			 (PCI_FUNC(device->devfn) << 8) |
-			 (offset & ~0x3)) | 0x80000000;
-	GT_WRITE(GT_PCI0_CFGADDR_OFS, DataForRegCf8);
-
-	/*  The casual observer might wonder why the READ is duplicated here,
-	   rather than immediately following the WRITE, and just have the
-	   swap in the "if".  That's because there is a latency problem
-	   with trying to read immediately after setting up the address
-	   register.  The "if" check gives enough time for the address
-	   to stabilize, so the READ can work.
-	 */
-	if (PCI_SLOT(device->devfn) == SELF) {	/* This board */
-		GT_READ(GT_PCI0_CFGDATA_OFS, &data);
-		return data;
-	} else {		/* The PCI is working in LE Mode so swap the Data. */
-		GT_READ(GT_PCI0_CFGDATA_OFS, &data);
-		return cpu_to_le32(data);
-	}
-}
-
-static unsigned int pci1ReadConfigReg(int offset, struct pci_dev *device)
-{
-	unsigned int DataForRegCf8;
-	unsigned int data;
-
-	DataForRegCf8 = ((PCI_SLOT(device->devfn) << 11) |
-			 (PCI_FUNC(device->devfn) << 8) |
-			 (offset & ~0x3)) | 0x80000000;
-	/*  The casual observer might wonder why the READ is duplicated here,
-	   rather than immediately following the WRITE, and just have the
-	   swap in the "if".  That's because there is a latency problem
-	   with trying to read immediately after setting up the address
-	   register.  The "if" check gives enough time for the address
-	   to stabilize, so the READ can work.
-	 */
-	if (PCI_SLOT(device->devfn) == SELF) {	/* This board */
-		/* when configurating our own PCI 1 L-unit the access is through
-		   the PCI 0 interface with reg number = reg number + 0x80 */
-		DataForRegCf8 |= 0x80;
-		GT_WRITE(GT_PCI0_CFGADDR_OFS, DataForRegCf8);
-	} else {		/* The PCI is working in LE Mode so swap the Data. */
-		GT_WRITE(GT_PCI1_CFGADDR_OFS, DataForRegCf8);
-	}
-	if (PCI_SLOT(device->devfn) == SELF) {	/* This board */
-		GT_READ(GT_PCI0_CFGDATA_OFS, &data);
-		return data;
-	} else {
-		GT_READ(GT_PCI1_CFGDATA_OFS, &data);
-		return cpu_to_le32(data);
-	}
-}
-
-
-
-/*
- * pciXWriteConfigReg - Write to a PCI configuration register
- *                    - Make sure the GT is configured as a master before
- *                      writingto another device on the PCI.
- *                    - The function takes care of Big/Little endian conversion.
- * Inputs:   unsigned int regOffset: The register offset as it apears in the
- *           GT spec
- *                   (or any other PCI device spec)
- *           pciDevNum: The device number needs to be addressed.
- *
- *  Configuration Address 0xCF8:
- *
- *       31 30    24 23  16 15  11 10     8 7      2  0     <=bit Number
- *  |congif|Reserved|  Bus |Device|Function|Register|00|
- *  |Enable|        |Number|Number| Number | Number |  |    <=field Name
- *
- */
-static void pci0WriteConfigReg(unsigned int offset,
-			       struct pci_dev *device, unsigned int data)
-{
-	unsigned int DataForRegCf8;
-
-	DataForRegCf8 = ((PCI_SLOT(device->devfn) << 11) |
-			 (PCI_FUNC(device->devfn) << 8) |
-			 (offset & ~0x3)) | 0x80000000;
-	GT_WRITE(GT_PCI0_CFGADDR_OFS, DataForRegCf8);
-	if (PCI_SLOT(device->devfn) == SELF) {	/* This board */
-		GT_WRITE(GT_PCI0_CFGDATA_OFS, data);
-	} else {		/* configuration Transaction over the pci. */
-		/* The PCI is working in LE Mode so swap the Data. */
-		GT_WRITE(GT_PCI0_CFGDATA_OFS, le32_to_cpu(data));
-	}
-}
-
-static void pci1WriteConfigReg(unsigned int offset,
-			       struct pci_dev *device, unsigned int data)
-{
-	unsigned int DataForRegCf8;
-
-	DataForRegCf8 = ((PCI_SLOT(device->devfn) << 11) |
-			 (PCI_FUNC(device->devfn) << 8) |
-			 (offset & ~0x3)) | 0x80000000;
-	/*  There is a latency problem
-	   with trying to read immediately after setting up the address
-	   register.  The "if" check gives enough time for the address
-	   to stabilize, so the WRITE can work.
-	 */
-	if (PCI_SLOT(device->devfn) == SELF) {	/* This board */
-		/* when configurating our own PCI 1 L-unit the access is through
-		   the PCI 0 interface with reg number = reg number + 0x80 */
-		DataForRegCf8 |= 0x80;
-		GT_WRITE(GT_PCI0_CFGADDR_OFS, DataForRegCf8);
-	} else {		/* configuration Transaction over the pci. */
-		/* The PCI is working in LE Mode so swap the Data. */
-		GT_WRITE(GT_PCI1_CFGADDR_OFS, DataForRegCf8);
-	}
-	if (PCI_SLOT(device->devfn) == SELF) {	/* This board */
-		GT_WRITE(GT_PCI0_CFGDATA_OFS, data);
-	} else {		/* configuration Transaction over the pci. */
-		GT_WRITE(GT_PCI1_CFGADDR_OFS, le32_to_cpu(data));
-	}
-}
-
-
-/*
- * galileo_pcibios_(read/write)_config_(dword/word/byte) -
- *
- * reads/write a dword/word/byte register from the configuration space
- * of a device.
- *
- * Inputs :
- * bus - bus number
- * dev - device number
- * offset - register offset in the configuration space
- * val - value to be written / read
- *
- * Outputs :
- * PCIBIOS_SUCCESSFUL when operation was succesfull
- * PCIBIOS_DEVICE_NOT_FOUND when the bus or dev is errorneous
- * PCIBIOS_BAD_REGISTER_NUMBER when accessing non aligned
- */
-
-static int galileo_pcibios_read_config_dword(struct pci_dev *device,
-					     int offset, u32 * val)
-{
-	int dev, bus;
-	//DBG(KERN_INFO "rcd entry \n",offset,val);
-	bus = device->bus->number;
-	dev = PCI_SLOT(device->devfn);
-
-	if (pci_range_ck(bus, dev)) {
-		*val = 0xffffffff;
-		return PCIBIOS_DEVICE_NOT_FOUND;
-	}
-	if (offset & 0x3)
-		return PCIBIOS_BAD_REGISTER_NUMBER;
-	if (bus == 0)
-		*val = pci0ReadConfigReg(offset, device);
-//  if (bus == 1) *val = pci1ReadConfigReg (offset,device);
-	DBG(KERN_INFO "rr: rcd dev %d offset %x %x\n", dev, offset, *val);
-
-	/*
-	 * This is so that the upper PCI layer will get the correct return
-	 * value if we're not attached to anything.
-	 */
-	if ((offset == 0) && (*val == 0xffffffff)) {
-		return PCIBIOS_DEVICE_NOT_FOUND;
-	}
-
-	return PCIBIOS_SUCCESSFUL;
-}
-
-static int galileo_pcibios_read_config_word(struct pci_dev *device,
-					    int offset, u16 * val)
-{
-	int dev, bus;
-
-	bus = device->bus->number;
-	dev = PCI_SLOT(device->devfn);
-
-	if (pci_range_ck(bus, dev)) {
-		*val = 0xffff;
-		return PCIBIOS_DEVICE_NOT_FOUND;
-	}
-	if (offset & 0x1)
-		return PCIBIOS_BAD_REGISTER_NUMBER;
-
-	if (bus == 0)
-		*val =
-		    (unsigned short) (pci0ReadConfigReg(offset, device) >>
-				      ((offset & ~0x3) * 8));
-//  if (bus == 1) *val = (unsigned short) (pci1ReadConfigReg(offset,device) >> ((offset & ~0x3) * 8));
-
-	DBG(KERN_INFO "rr: rcw dev %d offset %x %x\n", dev, offset, *val);
-
-	return PCIBIOS_SUCCESSFUL;
-}
-
-static int galileo_pcibios_read_config_byte(struct pci_dev *device,
-					    int offset, u8 * val)
-{
-	int dev, bus;
-
-	bus = device->bus->number;
-	dev = PCI_SLOT(device->devfn);
-
-	if (pci_range_ck(bus, dev)) {
-		*val = 0xff;
-		return PCIBIOS_DEVICE_NOT_FOUND;
-	}
-
-	if (bus == 0)
-		*val =
-		    (unsigned char) (pci0ReadConfigReg(offset, device) >>
-				     ((offset & ~0x3) * 8));
-//  if (bus == 1) *val = (unsigned char) (pci1ReadConfigReg(offset,device) >> ((offset & ~0x3) * 8));
-
-	DBG(KERN_INFO "rr: rcb dev %d offset %x %x\n", dev, offset, *val);
-
-	/*  This is so that the upper PCI layer will get the correct return value if
-	   we're not attached to anything.  */
-	if ((offset == 0xe) && (*val == 0xff)) {
-		u32 MasterAbort;
-		GT_READ(GT_INTRCAUSE_OFS, &MasterAbort);
-		if (MasterAbort & 0x40000) {
-			DBG(KERN_INFO "PCI Master Abort, ICR %x\n",
-			    MasterAbort);
-			GT_WRITE(GT_INTRCAUSE_OFS,
-				 (MasterAbort & 0xfffbffff));
-			return PCIBIOS_DEVICE_NOT_FOUND;
-		}
-	}
-
-	return PCIBIOS_SUCCESSFUL;
-}
-
-static int galileo_pcibios_write_config_dword(struct pci_dev *device,
-					      int offset, u32 val)
-{
-	int dev, bus;
-
-	bus = device->bus->number;
-	dev = PCI_SLOT(device->devfn);
-
-	if (pci_range_ck(bus, dev))
-		return PCIBIOS_DEVICE_NOT_FOUND;
-	if (offset & 0x3)
-		return PCIBIOS_BAD_REGISTER_NUMBER;
-	if (bus == 0)
-		pci0WriteConfigReg(offset, device, val);
-//  if (bus == 1) pci1WriteConfigReg (offset,device,val);
-
-	DBG(KERN_INFO "rr: wcd dev %d, offset %x, val %x\n", dev, offset,
-	    val);
-	return PCIBIOS_SUCCESSFUL;
-}
-
-
-static int galileo_pcibios_write_config_word(struct pci_dev *device,
-					     int offset, u16 val)
-{
-	int dev, bus;
-	unsigned long tmp;
-
-	bus = device->bus->number;
-	dev = PCI_SLOT(device->devfn);
-
-	if (pci_range_ck(bus, dev))
-		return PCIBIOS_DEVICE_NOT_FOUND;
-	if (offset & 0x1)
-		return PCIBIOS_BAD_REGISTER_NUMBER;
-	if (bus == 0)
-		tmp = pci0ReadConfigReg(offset, device);
-//  if (bus == 1) tmp = pci1ReadConfigReg (offset,device);
-
-	if ((offset % 4) == 0)
-		tmp = (tmp & 0xffff0000) | (val & 0xffff);
-	if ((offset % 4) == 2)
-		tmp = (tmp & 0x0000ffff) | ((val & 0xffff) << 16);
-
-	if (bus == 0)
-		pci0WriteConfigReg(offset, device, tmp);
-//  if (bus == 1) pci1WriteConfigReg (offset,device,tmp);
-	DBG(KERN_INFO "rr: wcw dev %d, offset %x, val %x\n", dev, offset,
-	    val);
-	return PCIBIOS_SUCCESSFUL;
-}
-
-static int galileo_pcibios_write_config_byte(struct pci_dev *device,
-					     int offset, u8 val)
-{
-	int dev, bus;
-	unsigned long tmp;
-
-	bus = device->bus->number;
-	dev = PCI_SLOT(device->devfn);
-
-	if (pci_range_ck(bus, dev))
-		return PCIBIOS_DEVICE_NOT_FOUND;
-	if (bus == 0)
-		tmp = pci0ReadConfigReg(offset, device);
-//  if (bus == 1) tmp = pci1ReadConfigReg (offset,device);
-
-	if ((offset % 4) == 0)
-		tmp = (tmp & 0xffffff00) | (val & 0xff);
-	if ((offset % 4) == 1)
-		tmp = (tmp & 0xffff00ff) | ((val & 0xff) << 8);
-	if ((offset % 4) == 2)
-		tmp = (tmp & 0xff00ffff) | ((val & 0xff) << 16);
-	if ((offset % 4) == 3)
-		tmp = (tmp & 0x00ffffff) | ((val & 0xff) << 24);
-
-	if (bus == 0)
-		pci0WriteConfigReg(offset, device, tmp);
-//  if (bus == 1) pci1WriteConfigReg (offset,device,tmp);
-	DBG(KERN_INFO "rr: wcb dev %d, offset %x, val %x\n", dev, offset,
-	    val);
-
-	return PCIBIOS_SUCCESSFUL;
-}
-
-static void galileo_pcibios_set_master(struct pci_dev *dev)
-{
-	u16 cmd;
-
-	DBG(KERN_INFO "rr: galileo_pcibios_set_master\n");
-
-	galileo_pcibios_read_config_word(dev, PCI_COMMAND, &cmd);
-	cmd |= PCI_COMMAND_MASTER;
-	galileo_pcibios_write_config_word(dev, PCI_COMMAND, cmd);
-	DBG("PCI: Enabling device %s (%04x)\n", pci_name(dev), cmd);
-}
-
-/*  Externally-expected functions.  Do not change function names  */
-
-int pcibios_enable_resources(struct pci_dev *dev)
-{
-	u16 cmd, old_cmd;
-	u16 tmp;
-	u8 tmp1;
-	int idx;
-	struct resource *r;
-
-	DBG(KERN_INFO "rr: pcibios_enable_resources\n");
-
-	galileo_pcibios_read_config_word(dev, PCI_COMMAND, &cmd);
-	old_cmd = cmd;
-	for (idx = 0; idx < 6; idx++) {
-		r = &dev->resource[idx];
-		DBG(KERN_INFO
-		    "rr: BAR %d, start %lx, end %lx, flags %lx\n", idx,
-		    r->start, r->end, r->flags);
-		if (!r->start && r->end) {
-			printk(KERN_ERR
-			       "PCI: Device %s not available because of resource collisions\n",
-			       pci_name(dev));
-			return -EINVAL;
-		}
-		if (r->flags & IORESOURCE_IO)
-			cmd |= PCI_COMMAND_IO;
-		if (r->flags & IORESOURCE_MEM)
-			cmd |= PCI_COMMAND_MEMORY;
-	}
-	if (cmd != old_cmd) {
-		DBG(KERN_INFO "PCI: Enabling device %s (%04x -> %04x)\n",
-		    pci_name(dev), old_cmd, cmd);
-		galileo_pcibios_write_config_word(dev, PCI_COMMAND, cmd);
-	}
-
-	/*
-	   Let's fix up the latency timer and cache line size here.  Cache line size =
-	   32 bytes / sizeof dword (4) = 8.
-	   Latency timer must be > 8.  32 is random but appears to work.
-	 */
-	galileo_pcibios_read_config_byte(dev, PCI_CACHE_LINE_SIZE, &tmp1);
-	if (tmp1 != 8) {
-		DBG(KERN_INFO
-		    "rr: PCI setting cache line size to 8 from %d\n",
-		    tmp1);
-		galileo_pcibios_write_config_byte(dev, PCI_CACHE_LINE_SIZE,
-						  8);
-	}
-	galileo_pcibios_read_config_byte(dev, PCI_LATENCY_TIMER, &tmp1);
-	if (tmp1 < 32) {
-		DBG(KERN_INFO
-		    "rr: PCI setting latency timer to 32 from %d\n", tmp1);
-		galileo_pcibios_write_config_byte(dev, PCI_LATENCY_TIMER,
-						  32);
-	}
-
-	return 0;
-}
-
-int pcibios_enable_device(struct pci_dev *dev, int mask)
-{
-	DBG(KERN_INFO "rr: pcibios_enable_device\n");
-	return pcibios_enable_resources(dev);
-}
-
-void pcibios_align_resource(void *data, struct resource *res,
-			    unsigned long size, unsigned long align)
-{
-	if (res->flags & IORESOURCE_IO) {
-		unsigned long start = res->start;
-
-		/* We need to avoid collisions with `mirrored' VGA ports
-		   and other strange ISA hardware, so we always want the
-		   addresses kilobyte aligned.  */
-		if (size > 0x100) {
-			DBG(KERN_ERR "PCI: I/O Region %s/%d too large"
-			    " (%ld bytes)\n", pci_name(dev),
-			    dev->resource - res, size);
-		}
-
-		start = (start + 1024 - 1) & ~(1024 - 1);
-		res->start = start;
-	}
-}
-
-/*
- * structure galileo_pci_ops
- *
- * This structure holds the pointers for the PCI configuration space
- * access, and the fixup for the interrupts.
- * This structure is registered to the operating system in boot time
- */
-struct pci_ops galileo_pci_ops = {
-	galileo_pcibios_read_config_byte,
-	galileo_pcibios_read_config_word,
-	galileo_pcibios_read_config_dword,
-	galileo_pcibios_write_config_byte,
-	galileo_pcibios_write_config_word,
-	galileo_pcibios_write_config_dword
-};
-
-/*
- * galileo_pcibios_fixup_bus -
- *
- * After detecting all agents over the PCI , this function is called
- * in order to give an interrupt number for each PCI device starting
- * from IRQ 20. It does also enables master for each device.
- *
- * Inputs :
- * mem_start , mem_end are not relevant in MIPS architecture.
- *
- * Outpus :
- * return always mem_start
- */
-static void __devinit galileo_pcibios_fixup_bus(struct pci_bus *bus)
-{
-	unsigned int Current_IRQ = 20;
-	struct pci_bus *current_bus = bus;
-	struct pci_dev *devices;
-	struct list_head *devices_link;
-
-	list_for_each(devices_link, &(current_bus->devices)) {
-		devices = pci_dev_b(devices_link);
-		if (devices != NULL) {
-			devices->irq = Current_IRQ++;
-
-			/* Assign an interrupt number for the device */
-			galileo_pcibios_write_config_byte(devices,
-							  PCI_INTERRUPT_LINE,
-							  Current_IRQ);
-			galileo_pcibios_set_master(devices);
-
-		}
-	}
-
-}
-
-struct pci_fixup pcibios_fixups[] = {
-//    { PCI_FIXUP_HEADER, 0x4620, 0x11ab, galileo_pcibios_fixup },
-	{0}
-};
-
-void __devinit pcibios_fixup_bus(struct pci_bus *c)
-{
-	DBG(KERN_INFO "rr: pcibios_fixup_bus\n");
-	galileo_pcibios_fixup_bus(c);
-}
-
-/*
- * This code was derived from Galileo Technology's example
- * and significantly reworked.
- *
- * This is very simple.  It does not scan multiple function devices.  It does
- * not scan behind bridges.  Those would be simple to implement, but we don't
- * currently need this.
- */
-static void __init scan_and_initialize_pci(void)
-{
-	struct pci_device pci_devices[MAX_PCI_DEVS];
-
-	if (scan_pci_bus(pci_devices)) {
-		allocate_pci_space(pci_devices);
-	}
-}
-
-/*
- * This is your basic PCI scan.  It goes through each slot and checks to
- * see if there's something that responds.  If so, then get the size and
- * type of each of the responding BARs.  Save them for later.
- */
-
-static u32 __init scan_pci_bus(struct pci_device *pci_devices)
-{
-	u32 arrayCounter = 0;
-	u32 memType;
-	u32 memSize;
-	u32 pci_slot, bar;
-	u32 id;
-	u32 c18RegValue;
-	struct pci_dev device;
-
-	DBG(KERN_INFO "rr: scan_pci_bus\n");
-
-	/*
-	   According to PCI REV 2.1 MAX agents on the bus are 21.
-	   We don't bother scanning ourselves (slot 0).
-	 */
-	for (pci_slot = 1; pci_slot < 22; pci_slot++) {
-
-		device.devfn = PCI_DEVFN(pci_slot, 0);
-		id = pci0ReadConfigReg(PCI_VENDOR_ID, &device);
-
-		/*  Check for a PCI Master Abort (nothing responds in the slot) */
-		GT_READ(GT_INTRCAUSE_OFS, &c18RegValue);
-		/* Clearing bit 18 of in the Cause Register 0xc18 by writting 0. */
-		GT_WRITE(GT_INTRCAUSE_OFS, (c18RegValue & 0xfffbffff));
-		if ((id != 0xffffffff) && !(c18RegValue & 0x40000)) {
-			DBG(KERN_INFO "rr: found device %x, slot %d\n", id,
-			    pci_slot);
-			pci_devices[arrayCounter].slot = pci_slot;
-			for (bar = 0; bar < 6; bar++) {
-				memType =
-				    pci0ReadConfigReg(PCI_BASE_ADDRESS_0 +
-						      (bar * 4), &device);
-				pci_devices[arrayCounter].BARtype[bar] =
-				    memType & 1;
-				pci0WriteConfigReg(PCI_BASE_ADDRESS_0 +
-						   (bar * 4), &device,
-						   0xffffffff);
-				memSize =
-				    pci0ReadConfigReg(PCI_BASE_ADDRESS_0 +
-						      (bar * 4), &device);
-				if (memType & 1) {	/*  IO space  */
-					pci_devices[arrayCounter].
-					    BARsize[bar] =
-					    ~(memSize & 0xfffffffc) + 1;
-				} else {	/*  memory space */
-					pci_devices[arrayCounter].
-					    BARsize[bar] =
-					    ~(memSize & 0xfffffff0) + 1;
-				}
-				DBG(KERN_INFO
-				    "rr: BAR %d, type %d, size %x\n", bar,
-				    (memType & 1),
-				    pci_devices[arrayCounter].
-				    BARsize[bar]);
-			}	/*  BAR counter  */
-
-			arrayCounter++;
-		}
-		/*  found a device  */
-	}			/*  slot counter  */
-
-	DBG(KERN_INFO "rr: found %d devices\n", arrayCounter);
-	if (arrayCounter < MAX_PCI_DEVS) {
-		pci_devices[arrayCounter].slot = -1;
-	}
-	return (arrayCounter);
-}
-
-#define ALIGN(val,align)        (((val) + ((align) - 1)) & ~((align) - 1))
-#define MAX(val1, val2) ((val1) > (val2) ? (val1) : (val2))
-
-/*
- * This function goes through the list of devices and allocates the BARs in
- * either IO or MEM space.  It does it in order of size, which will limit the
- * amount of fragmentation we have in the IO and MEM spaces.
- */
-
-static void __init allocate_pci_space(struct pci_device *pci_devices)
-{
-	u32 count, maxcount, bar;
-	u32 maxSize, maxDevice, maxBAR;
-	u32 alignto;
-	u32 base;
-	u32 pci0_mem_base = pci0GetMemory0Base();
-	u32 pci0_io_base = pci0GetIOspaceBase();
-	struct pci_dev device;
-
-	DBG(KERN_INFO "rr: allocate_pci_space\n");
-
-	DBG(KERN_INFO "pci0_io_base %x\n", pci0_io_base);
-	DBG(KERN_INFO "pci0_mem_base %x\n", pci0_mem_base);
-
-	/*  How many PCI devices do we have?  */
-	maxcount = MAX_PCI_DEVS;
-	for (count = 0; count < MAX_PCI_DEVS; count++) {
-		if (pci_devices[count].slot == -1) {
-			maxcount = count;
-			break;
-		}
-	}
-
-//    DBG(KERN_INFO "Found %d devices\n", maxcount);
-
-	do {
-		/*  Find the largest size BAR we need to allocate  */
-		maxSize = 0;
-		for (count = 0; count < maxcount; count++) {
-			for (bar = 0; bar < 6; bar++) {
-				if (pci_devices[count].BARsize[bar] >
-				    maxSize) {
-					maxSize =
-					    pci_devices[count].
-					    BARsize[bar];
-					maxDevice = count;
-					maxBAR = bar;
-				}
-			}
-		}
-
-		/*
-		   We've found the largest BAR.  Allocate it into IO or
-		   mem space.  We don't idiot check the bases to make
-		   sure they haven't overflowed the current size for that aperture.
-
-		   Don't bother to enable the device's IO or MEM space here.  That will
-		   be done in pci_enable_resources if the device is activated by a driver.
-		 */
-		if (maxSize) {
-			device.devfn =
-			    PCI_DEVFN(pci_devices[maxDevice].slot, 0);
-			if (pci_devices[maxDevice].BARtype[maxBAR] == 1) {
-				alignto = MAX(0x1000, maxSize);
-				base = ALIGN(pci0_io_base, alignto);
-				pci0WriteConfigReg(PCI_BASE_ADDRESS_0 +
-						   (maxBAR * 4), &device,
-						   base | 0x1);
-				pci0_io_base = base + alignto;
-				DBG(KERN_INFO
-				    "Device %d BAR %d address %x\n",
-				    pci_devices[maxDevice].slot, maxBAR,
-				    base);
-				DBG(KERN_INFO "New IO base %x\n",
-				    pci0_io_base);
-			} else {
-				alignto = MAX(0x1000, maxSize);
-				base = ALIGN(pci0_mem_base, alignto);
-				pci0WriteConfigReg(PCI_BASE_ADDRESS_0 +
-						   (maxBAR * 4), &device,
-						   base);
-				pci0_mem_base = base + alignto;
-				DBG(KERN_INFO
-				    "Device %d BAR %d address %x\n",
-				    pci_devices[maxDevice].slot, maxBAR,
-				    base);
-				DBG(KERN_INFO "New mem base %x\n",
-				    pci0_mem_base);
-			}
-			/*
-			   This entry is finished.  Remove it from the list we'll scan.
-			 */
-			pci_devices[maxDevice].BARsize[maxBAR] = 0;
-		}
-	} while (maxSize);
-}
-
-unsigned __init int pcibios_assign_all_busses(void)
-{
-	return 1;
-}
-
-static int __init pcibios_init(void)
-{
-
-	u32 tmp;
-	struct pci_dev controller;
-
-	controller.devfn = SELF;
-
-	DBG(KERN_INFO "rr: pcibios_init\n");
-	GT_READ(GT_PCI0_CMD_OFS, &tmp);
-	DBG(KERN_INFO "rr: PCI0 command - %x\n", tmp);
-	GT_READ(GT_PCI0_BARE_OFS, &tmp);
-	DBG(KERN_INFO "rr: BAR0 - %x\n", tmp);
-
-	/*
-	 * You have to enable bus mastering to configure any other
-	 * card on the bus.
-	 */
-	tmp = pci0ReadConfigReg(PCI_COMMAND, &controller);
-	DBG(KERN_INFO "rr: command/status - %x\n", tmp);
-	tmp |= PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER | PCI_COMMAND_SERR;
-	DBG(KERN_INFO "rr: new command/status - %x\n", tmp);
-	pci0WriteConfigReg(PCI_COMMAND, &controller, tmp);
-
-	/*  This scans the PCI bus and sets up initial values.  */
-	scan_and_initialize_pci();
-
-	/*
-	 * Reset PCI I/O and PCI MEM values to ones supported by EVM.
-	 */
-	ioport_resource.start = 0x10000000;
-	ioport_resource.end = 0x11ffffff;	/*  32 MB */
-	iomem_resource.start = 0x12000000;
-	iomem_resource.end = 0x13ffffff;	/* 32 MB */
-
-	pci_scan_bus(0, &galileo_pci_ops, NULL);
-
-	return 0;
-}
-
-subsys_initcall(pcibios_init);
-
-char *pcibios_setup(char *str)
-{
-	printk(KERN_INFO "rr: pcibios_setup\n");
-	/* Nothing to do for now.  */
-
-	return str;
-}
--- diff/arch/mips/pci/ops-ev96100.c	2003-07-08 09:55:17.000000000 +0100
+++ source/arch/mips/pci/ops-ev96100.c	1970-01-01 01:00:00.000000000 +0100
@@ -1,264 +0,0 @@
-/*
- *
- * BRIEF MODULE DESCRIPTION
- *	Galileo EV96100 board specific pci support.
- *
- * Copyright 2000 MontaVista Software Inc.
- * Author: MontaVista Software, Inc.
- *         	ppopov@mvista.com or source@mvista.com
- *
- * This file was derived from Carsten Langgaard's
- * arch/mips/mips-boards/generic/pci.c
- *
- * Carsten Langgaard, carstenl@mips.com
- * Copyright (C) 1999,2000 MIPS Technologies, Inc.  All rights reserved.
- *
- *  This program is free software; you can redistribute  it and/or modify it
- *  under  the terms of  the GNU General  Public License as published by the
- *  Free Software Foundation;  either version 2 of the  License, or (at your
- *  option) any later version.
- *
- *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
- *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
- *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
- *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
- *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
- *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- *  You should have received a copy of the  GNU General Public License along
- *  with this program; if not, write  to the Free Software Foundation, Inc.,
- *  675 Mass Ave, Cambridge, MA 02139, USA.
- */
-#include <linux/types.h>
-#include <linux/pci.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
-
-#include <asm/delay.h>
-#include <asm			//gt64120.h>
-#include <asm/galileo-boards/ev96100.h>
-#include <asm/pci_channel.h>
-
-#define PCI_ACCESS_READ  0
-#define PCI_ACCESS_WRITE 1
-
-#undef DEBUG
-
-#ifdef DEBUG
-#define DBG(x...) printk(x)
-#else
-#define DBG(x...)
-#endif
-
-#define GT_PCI_MEM_BASE    0x12000000
-#define GT_PCI_MEM_SIZE    0x02000000
-#define GT_PCI_IO_BASE     0x10000000
-#define GT_PCI_IO_SIZE     0x02000000
-static struct resource pci_io_resource = {
-	"io pci IO space",
-	0x10000000,
-	0x10000000 + 0x02000000,
-	IORESOURCE_IO
-};
-
-static struct resource pci_mem_resource = {
-	"ext pci memory space",
-	0x12000000,
-	0x12000000 + 0x02000000,
-	IORESOURCE_MEM
-};
-
-extern struct pci_ops gt96100_pci_ops;
-
-struct pci_channel mips_pci_channels[] = {
-	{&gt96100_pci_ops, &pci_io_resource, &pci_mem_resource, 1, 0xff},
-	{NULL, NULL, NULL, NULL, NULL}
-};
-
-int
-static gt96100_config_access(unsigned char access_type,
-			     struct pci_dev *dev, unsigned char where,
-			     u32 * data)
-{
-	unsigned char bus = dev->bus->number;
-	unsigned char dev_fn = dev->devfn;
-	u32 intr;
-
-
-	if ((bus == 0) && (dev_fn >= PCI_DEVFN(31, 0))) {
-		return -1;	/* Because of a bug in the galileo (for slot 31). */
-	}
-
-	/* Clear cause register bits */
-	GT_WRITE(GT_INTRCAUSE_OFS, ~(GT_INTRCAUSE_MASABORT0_BIT |
-				     GT_INTRCAUSE_TARABORT0_BIT));
-
-	/* Setup address */
-	GT_WRITE(GT_PCI0_CFGADDR_OFS,
-		 (bus << GT_PCI0_CFGADDR_BUSNUM_SHF) |
-		 (dev_fn << GT_PCI0_CFGADDR_FUNCTNUM_SHF) |
-		 ((where / 4) << GT_PCI0_CFGADDR_REGNUM_SHF) |
-		 GT_PCI0_CFGADDR_CONFIGEN_BIT);
-	udelay(2);
-
-
-	if (access_type == PCI_ACCESS_WRITE) {
-		if (dev_fn != 0) {
-			*data = le32_to_cpu(*data);
-		}
-		GT_WRITE(GT_PCI0_CFGDATA_OFS, *data);
-	} else {
-		GT_READ(GT_PCI0_CFGDATA_OFS, *data);
-		if (dev_fn != 0) {
-			*data = le32_to_cpu(*data);
-		}
-	}
-
-	udelay(2);
-
-	/* Check for master or target abort */
-	GT_READ(GT_INTRCAUSE_OFS, intr);
-
-	if (intr &
-	    (GT_INTRCAUSE_MASABORT0_BIT | GT_INTRCAUSE_TARABORT0_BIT)) {
-		//printk("config access error:  %x:%x\n", dev_fn,where);
-		/* Error occured */
-
-		/* Clear bits */
-		GT_WRITE(GT_INTRCAUSE_OFS, ~(GT_INTRCAUSE_MASABORT0_BIT |
-					     GT_INTRCAUSE_TARABORT0_BIT));
-
-		if (access_type == PCI_ACCESS_READ) {
-			*data = 0xffffffff;
-		}
-		return -1;
-	}
-	return 0;
-}
-
-
-/*
- * We can't address 8 and 16 bit words directly.  Instead we have to
- * read/write a 32bit word and mask/modify the data we actually want.
- */
-static int read_config_byte(struct pci_dev *dev, int where, u8 * val)
-{
-	u32 data = 0;
-
-	if (gt96100_config_access(PCI_ACCESS_READ, dev, where, &data)) {
-		*val = 0xff;
-		return -1;
-	}
-
-	*val = (data >> ((where & 3) << 3)) & 0xff;
-	DBG("cfg read byte: bus %d dev_fn %x where %x: val %x\n",
-	    dev->bus->number, dev->devfn, where, *val);
-
-	return PCIBIOS_SUCCESSFUL;
-}
-
-
-static int read_config_word(struct pci_dev *dev, int where, u16 * val)
-{
-	u32 data = 0;
-
-	if (where & 1)
-		return PCIBIOS_BAD_REGISTER_NUMBER;
-
-	if (gt96100_config_access(PCI_ACCESS_READ, dev, where, &data)) {
-		*val = 0xffff;
-		return -1;
-	}
-
-	*val = (data >> ((where & 3) << 3)) & 0xffff;
-	DBG("cfg read word: bus %d dev_fn %x where %x: val %x\n",
-	    dev->bus->number, dev->devfn, where, *val);
-
-	return PCIBIOS_SUCCESSFUL;
-}
-
-static int read_config_dword(struct pci_dev *dev, int where, u32 * val)
-{
-	u32 data = 0;
-
-	if (where & 3)
-		return PCIBIOS_BAD_REGISTER_NUMBER;
-
-	if (gt96100_config_access(PCI_ACCESS_READ, dev, where, &data)) {
-		*val = 0xffffffff;
-		return -1;
-	}
-
-	*val = data;
-	DBG("cfg read dword: bus %d dev_fn %x where %x: val %x\n",
-	    dev->bus->number, dev->devfn, where, *val);
-
-	return PCIBIOS_SUCCESSFUL;
-}
-
-
-static int write_config_byte(struct pci_dev *dev, int where, u8 val)
-{
-	u32 data = 0;
-
-	if (gt96100_config_access(PCI_ACCESS_READ, dev, where, &data))
-		return -1;
-
-	data = (data & ~(0xff << ((where & 3) << 3))) |
-	    (val << ((where & 3) << 3));
-	DBG("cfg write byte: bus %d dev_fn %x where %x: val %x\n",
-	    dev->bus->number, dev->devfn, where, val);
-
-	if (gt96100_config_access(PCI_ACCESS_WRITE, dev, where, &data))
-		return -1;
-
-	return PCIBIOS_SUCCESSFUL;
-}
-
-static int write_config_word(struct pci_dev *dev, int where, u16 val)
-{
-	u32 data = 0;
-
-	if (where & 1)
-		return PCIBIOS_BAD_REGISTER_NUMBER;
-
-	if (gt96100_config_access(PCI_ACCESS_READ, dev, where, &data))
-		return -1;
-
-	data = (data & ~(0xffff << ((where & 3) << 3))) |
-	    (val << ((where & 3) << 3));
-	DBG("cfg write word: bus %d dev_fn %x where %x: val %x\n",
-	    dev->bus->number, dev->devfn, where, val);
-
-	if (gt96100_config_access(PCI_ACCESS_WRITE, dev, where, &data))
-		return -1;
-
-
-	return PCIBIOS_SUCCESSFUL;
-}
-
-static int write_config_dword(struct pci_dev *dev, int where, u32 val)
-{
-	if (where & 3)
-		return PCIBIOS_BAD_REGISTER_NUMBER;
-
-	if (gt96100_config_access(PCI_ACCESS_WRITE, dev, where, &val))
-		return -1;
-	DBG("cfg write dword: bus %d dev_fn %x where %x: val %x\n",
-	    dev->bus->number, dev->devfn, where, val);
-
-	return PCIBIOS_SUCCESSFUL;
-}
-
-struct pci_ops gt96100_pci_ops = {
-	read_config_byte,
-	read_config_word,
-	read_config_dword,
-	write_config_byte,
-	write_config_word,
-	write_config_dword
-};
--- diff/arch/mips/pci/ops-jmr3927.c	2003-07-08 09:55:17.000000000 +0100
+++ source/arch/mips/pci/ops-jmr3927.c	1970-01-01 01:00:00.000000000 +0100
@@ -1,491 +0,0 @@
-/***********************************************************************
- * Copyright 2001 MontaVista Software Inc.
- * Author: MontaVista Software, Inc.
- *              ahennessy@mvista.com
- *
- * Copyright (C) 2000-2001 Toshiba Corporation
- *
- * Based on arch/mips/ddb5xxx/ddb5477/pci_ops.c
- *
- *     Define the pci_ops for JMR3927.
- *
- * Much of the code is derived from the original DDB5074 port by
- * Geert Uytterhoeven <geert@sonycom.com>
- *
- *  This program is free software; you can redistribute  it and/or modify it
- *  under  the terms of  the GNU General  Public License as published by the
- *  Free Software Foundation;  either version 2 of the  License, or (at your
- *  option) any later version.
- *
- *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
- *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
- *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
- *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
- *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
- *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- *  You should have received a copy of the  GNU General Public License along
- *  with this program; if not, write  to the Free Software Foundation, Inc.,
- *  675 Mass Ave, Cambridge, MA 02139, USA.
- */
-#include <linux/types.h>
-#include <linux/pci.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
-
-#include <asm/addrspace.h>
-#include <asm/pci_channel.h>
-#include <asm/jmr3927/jmr3927.h>
-#include <asm/debug.h>
-
-struct resource pci_io_resource = {
-	"pci IO space",
-	0x1000,			/* reserve regacy I/O space */
-	0x1000 + JMR3927_PCIIO_SIZE - 1,
-	IORESOURCE_IO
-};
-
-struct resource pci_mem_resource = {
-	"pci memory space",
-	JMR3927_PCIMEM,
-	JMR3927_PCIMEM + JMR3927_PCIMEM_SIZE - 1,
-	IORESOURCE_MEM
-};
-
-extern struct pci_ops jmr3927_pci_ops;
-
-struct pci_channel mips_pci_channels[] = {
-	{&jmr3927_pci_ops, &pci_io_resource, &pci_mem_resource, 0, 0xff},
-	{NULL, NULL, NULL, NULL, NULL}
-};
-
-unsigned int pcibios_assign_all_busses(void)
-{
-	return 1;
-}
-
-static int
-mkaddr(unsigned char bus, unsigned char dev_fn, unsigned char where,
-       int *flagsp)
-{
-	if (bus == 0 && dev_fn >= PCI_DEVFN(TX3927_PCIC_MAX_DEVNU, 0))
-		return -1;
-
-	tx3927_pcicptr->ica = ((bus & 0xff) << 0x10) |
-	    ((dev_fn & 0xff) << 0x08) | (where & 0xfc);
-	/* clear M_ABORT and Disable M_ABORT Int. */
-	tx3927_pcicptr->pcistat |= PCI_STATUS_REC_MASTER_ABORT;
-	tx3927_pcicptr->pcistatim &= ~PCI_STATUS_REC_MASTER_ABORT;
-	return 0;
-}
-
-static int check_abort(int flags)
-{
-	int code = PCIBIOS_SUCCESSFUL;
-	if (tx3927_pcicptr->pcistat & PCI_STATUS_REC_MASTER_ABORT) {
-		tx3927_pcicptr->pcistat |= PCI_STATUS_REC_MASTER_ABORT;
-		tx3927_pcicptr->pcistatim |= PCI_STATUS_REC_MASTER_ABORT;
-		code = PCIBIOS_DEVICE_NOT_FOUND;
-	}
-	return code;
-}
-
-/*
- * We can't address 8 and 16 bit words directly.  Instead we have to
- * read/write a 32bit word and mask/modify the data we actually want.
- */
-static int jmr3927_pcibios_read_config_byte(struct pci_dev *dev,
-					    int where, unsigned char *val)
-{
-	int flags;
-	unsigned char bus, func_num;
-
-	db_assert((where & 3) == 0);
-	db_assert(where < (1 << 8));
-
-	/* check if the bus is top-level */
-	if (dev->bus->parent != NULL) {
-		bus = dev->bus->number;
-		db_assert(bus != 0);
-	} else {
-		bus = 0;
-	}
-
-	func_num = PCI_FUNC(dev->devfn);
-	if (mkaddr(bus, dev->devfn, where, &flags))
-		return -1;
-	*val =
-	    *(volatile u8 *) ((ulong) & tx3927_pcicptr->icd | (where & 3));
-	return check_abort(flags);
-}
-
-static int jmr3927_pcibios_read_config_word(struct pci_dev *dev,
-					    int where, unsigned short *val)
-{
-	int flags;
-	unsigned char bus, func_num;
-
-	if (where & 1)
-		return PCIBIOS_BAD_REGISTER_NUMBER;
-
-	db_assert((where & 3) == 0);
-	db_assert(where < (1 << 8));
-
-	/* check if the bus is top-level */
-	if (dev->bus->parent != NULL) {
-		bus = dev->bus->number;
-		db_assert(bus != 0);
-	} else {
-		bus = 0;
-	}
-
-	func_num = PCI_FUNC(dev->devfn);
-	if (mkaddr(bus, dev->devfn, where, &flags))
-		return -1;
-	*val =
-	    le16_to_cpu(*(volatile u16 *)
-			((ulong) & tx3927_pcicptr->icd | (where & 3)));
-	return check_abort(flags);
-}
-
-static int jmr3927_pcibios_read_config_dword(struct pci_dev *dev,
-					     int where, unsigned int *val)
-{
-	int flags;
-	unsigned char bus, func_num;
-
-	if (where & 3)
-		return PCIBIOS_BAD_REGISTER_NUMBER;
-
-	db_assert((where & 3) == 0);
-	db_assert(where < (1 << 8));
-
-	/* check if the bus is top-level */
-	if (dev->bus->parent != NULL) {
-		bus = dev->bus->number;
-		db_assert(bus != 0);
-	} else {
-		bus = 0;
-	}
-
-	func_num = PCI_FUNC(dev->devfn);
-	if (mkaddr(bus, dev->devfn, where, &flags))
-		return -1;
-	*val = le32_to_cpu(tx3927_pcicptr->icd);
-	return check_abort(flags);
-}
-
-static int jmr3927_pcibios_write_config_byte(struct pci_dev *dev,
-					     int where, unsigned char val)
-{
-	int flags;
-	unsigned char bus, func_num;
-
-	/* check if the bus is top-level */
-	if (dev->bus->parent != NULL) {
-		bus = dev->bus->number;
-		db_assert(bus != 0);
-	} else {
-		bus = 0;
-	}
-
-	func_num = PCI_FUNC(dev->devfn);
-	if (mkaddr(bus, dev->devfn, where, &flags))
-		return -1;
-	*(volatile u8 *) ((ulong) & tx3927_pcicptr->icd | (where & 3)) =
-	    val;
-	return check_abort(flags);
-}
-
-static int jmr3927_pcibios_write_config_word(struct pci_dev *dev,
-					     int where, unsigned short val)
-{
-	int flags;
-	unsigned char bus, func_num;
-
-	if (where & 1)
-		return PCIBIOS_BAD_REGISTER_NUMBER;
-
-	/* check if the bus is top-level */
-	if (dev->bus->parent != NULL) {
-		bus = dev->bus->number;
-		db_assert(bus != 0);
-	} else {
-		bus = 0;
-	}
-
-	func_num = PCI_FUNC(dev->devfn);
-	if (mkaddr(bus, dev->devfn, where, &flags))
-		return -1;
-	*(volatile u16 *) ((ulong) & tx3927_pcicptr->icd | (where & 3)) =
-	    cpu_to_le16(val);
-	return check_abort(flags);
-}
-
-static int jmr3927_pcibios_write_config_dword(struct pci_dev *dev,
-					      int where, unsigned int val)
-{
-	int flags;
-	unsigned char bus, func_num;
-
-	if (where & 3)
-		return PCIBIOS_BAD_REGISTER_NUMBER;
-
-	/* check if the bus is top-level */
-	if (dev->bus->parent != NULL) {
-		bus = dev->bus->number;
-		db_assert(bus != 0);
-	} else {
-		bus = 0;
-	}
-
-	func_num = PCI_FUNC(dev->devfn);
-	if (mkaddr(bus, dev->devfn, where, &flags))
-		return -1;
-	tx3927_pcicptr->icd = cpu_to_le32(val);
-	return check_abort(flags);
-}
-struct pci_ops jmr3927_pci_ops = {
-	jmr3927_pcibios_read_config_byte,
-	jmr3927_pcibios_read_config_word,
-	jmr3927_pcibios_read_config_dword,
-	jmr3927_pcibios_write_config_byte,
-	jmr3927_pcibios_write_config_word,
-	jmr3927_pcibios_write_config_dword
-};
-
-#ifndef JMR3927_INIT_INDIRECT_PCI
-inline unsigned long tc_readl(volatile __u32 * addr)
-{
-	return readl(addr);
-}
-inline void tc_writel(unsigned long data, volatile __u32 * addr)
-{
-	writel(data, addr);
-}
-#else
-unsigned long tc_readl(volatile __u32 * addr)
-{
-	unsigned long val;
-
-	addr = PHYSADDR(addr);
-	*(volatile u32 *) (ulong) & tx3927_pcicptr->ipciaddr =
-	    (unsigned long) addr;
-	*(volatile u32 *) (ulong) & tx3927_pcicptr->ipcibe =
-	    (PCI_IPCIBE_ICMD_MEMREAD << PCI_IPCIBE_ICMD_SHIFT) |
-	    PCI_IPCIBE_IBE_LONG;
-	while (!(tx3927_pcicptr->istat & PCI_ISTAT_IDICC));
-	val =
-	    le32_to_cpu(*(volatile u32 *) (ulong) & tx3927_pcicptr->
-			ipcidata);
-	/* clear by setting */
-	tx3927_pcicptr->istat |= PCI_ISTAT_IDICC;
-	return val;
-}
-void tc_writel(unsigned long data, volatile __u32 * addr)
-{
-	addr = PHYSADDR(addr);
-	*(volatile u32 *) (ulong) & tx3927_pcicptr->ipcidata =
-	    cpu_to_le32(data);
-	*(volatile u32 *) (ulong) & tx3927_pcicptr->ipciaddr =
-	    (unsigned long) addr;
-	*(volatile u32 *) (ulong) & tx3927_pcicptr->ipcibe =
-	    (PCI_IPCIBE_ICMD_MEMWRITE << PCI_IPCIBE_ICMD_SHIFT) |
-	    PCI_IPCIBE_IBE_LONG;
-	while (!(tx3927_pcicptr->istat & PCI_ISTAT_IDICC));
-	/* clear by setting */
-	tx3927_pcicptr->istat |= PCI_ISTAT_IDICC;
-}
-unsigned char tx_ioinb(unsigned char *addr)
-{
-	unsigned long val;
-	__u32 ioaddr;
-	int offset;
-	int byte;
-
-	ioaddr = (unsigned long) addr;
-	offset = ioaddr & 0x3;
-	if (offset == 0)
-		byte = 0x7;
-	else if (offset == 1)
-		byte = 0xb;
-	else if (offset == 2)
-		byte = 0xd;
-	else if (offset == 3)
-		byte = 0xe;
-	*(volatile u32 *) (ulong) & tx3927_pcicptr->ipciaddr =
-	    (unsigned long) ioaddr;
-	*(volatile u32 *) (ulong) & tx3927_pcicptr->ipcibe =
-	    (PCI_IPCIBE_ICMD_IOREAD << PCI_IPCIBE_ICMD_SHIFT) | byte;
-	while (!(tx3927_pcicptr->istat & PCI_ISTAT_IDICC));
-	val =
-	    le32_to_cpu(*(volatile u32 *) (ulong) & tx3927_pcicptr->
-			ipcidata);
-	val = val & 0xff;
-	/* clear by setting */
-	tx3927_pcicptr->istat |= PCI_ISTAT_IDICC;
-	return val;
-}
-void tx_iooutb(unsigned long data, unsigned char *addr)
-{
-	__u32 ioaddr;
-	int offset;
-	int byte;
-
-	data = data | (data << 8) | (data << 16) | (data << 24);
-	ioaddr = (unsigned long) addr;
-	offset = ioaddr & 0x3;
-	if (offset == 0)
-		byte = 0x7;
-	else if (offset == 1)
-		byte = 0xb;
-	else if (offset == 2)
-		byte = 0xd;
-	else if (offset == 3)
-		byte = 0xe;
-	*(volatile u32 *) (ulong) & tx3927_pcicptr->ipcidata = data;
-	*(volatile u32 *) (ulong) & tx3927_pcicptr->ipciaddr =
-	    (unsigned long) ioaddr;
-	*(volatile u32 *) (ulong) & tx3927_pcicptr->ipcibe =
-	    (PCI_IPCIBE_ICMD_IOWRITE << PCI_IPCIBE_ICMD_SHIFT) | byte;
-	while (!(tx3927_pcicptr->istat & PCI_ISTAT_IDICC));
-	/* clear by setting */
-	tx3927_pcicptr->istat |= PCI_ISTAT_IDICC;
-}
-unsigned short tx_ioinw(unsigned short *addr)
-{
-	unsigned long val;
-	__u32 ioaddr;
-	int offset;
-	int byte;
-
-	ioaddr = (unsigned long) addr;
-	offset = ioaddr & 0x3;
-	if (offset == 0)
-		byte = 0x3;
-	else if (offset == 2)
-		byte = 0xc;
-	*(volatile u32 *) (ulong) & tx3927_pcicptr->ipciaddr =
-	    (unsigned long) ioaddr;
-	*(volatile u32 *) (ulong) & tx3927_pcicptr->ipcibe =
-	    (PCI_IPCIBE_ICMD_IOREAD << PCI_IPCIBE_ICMD_SHIFT) | byte;
-	while (!(tx3927_pcicptr->istat & PCI_ISTAT_IDICC));
-	val =
-	    le32_to_cpu(*(volatile u32 *) (ulong) & tx3927_pcicptr->
-			ipcidata);
-	val = val & 0xffff;
-	/* clear by setting */
-	tx3927_pcicptr->istat |= PCI_ISTAT_IDICC;
-	return val;
-
-}
-void tx_iooutw(unsigned long data, unsigned short *addr)
-{
-	__u32 ioaddr;
-	int offset;
-	int byte;
-
-	data = data | (data << 16);
-	ioaddr = (unsigned long) addr;
-	offset = ioaddr & 0x3;
-	if (offset == 0)
-		byte = 0x3;
-	else if (offset == 2)
-		byte = 0xc;
-	*(volatile u32 *) (ulong) & tx3927_pcicptr->ipcidata = data;
-	*(volatile u32 *) (ulong) & tx3927_pcicptr->ipciaddr =
-	    (unsigned long) ioaddr;
-	*(volatile u32 *) (ulong) & tx3927_pcicptr->ipcibe =
-	    (PCI_IPCIBE_ICMD_IOWRITE << PCI_IPCIBE_ICMD_SHIFT) | byte;
-	while (!(tx3927_pcicptr->istat & PCI_ISTAT_IDICC));
-	/* clear by setting */
-	tx3927_pcicptr->istat |= PCI_ISTAT_IDICC;
-}
-unsigned long tx_ioinl(unsigned int *addr)
-{
-	unsigned long val;
-	__u32 ioaddr;
-
-	ioaddr = (unsigned long) addr;
-	*(volatile u32 *) (ulong) & tx3927_pcicptr->ipciaddr =
-	    (unsigned long) ioaddr;
-	*(volatile u32 *) (ulong) & tx3927_pcicptr->ipcibe =
-	    (PCI_IPCIBE_ICMD_IOREAD << PCI_IPCIBE_ICMD_SHIFT) |
-	    PCI_IPCIBE_IBE_LONG;
-	while (!(tx3927_pcicptr->istat & PCI_ISTAT_IDICC));
-	val =
-	    le32_to_cpu(*(volatile u32 *) (ulong) & tx3927_pcicptr->
-			ipcidata);
-	/* clear by setting */
-	tx3927_pcicptr->istat |= PCI_ISTAT_IDICC;
-	return val;
-}
-void tx_iooutl(unsigned long data, unsigned int *addr)
-{
-	__u32 ioaddr;
-
-	ioaddr = (unsigned long) addr;
-	*(volatile u32 *) (ulong) & tx3927_pcicptr->ipcidata =
-	    cpu_to_le32(data);
-	*(volatile u32 *) (ulong) & tx3927_pcicptr->ipciaddr =
-	    (unsigned long) ioaddr;
-	*(volatile u32 *) (ulong) & tx3927_pcicptr->ipcibe =
-	    (PCI_IPCIBE_ICMD_IOWRITE << PCI_IPCIBE_ICMD_SHIFT) |
-	    PCI_IPCIBE_IBE_LONG;
-	while (!(tx3927_pcicptr->istat & PCI_ISTAT_IDICC));
-	/* clear by setting */
-	tx3927_pcicptr->istat |= PCI_ISTAT_IDICC;
-}
-void tx_insbyte(unsigned char *addr, void *buffer, unsigned int count)
-{
-	unsigned char *ptr = (unsigned char *) buffer;
-
-	while (count--) {
-		*ptr++ = tx_ioinb(addr);
-	}
-}
-void tx_insword(unsigned short *addr, void *buffer, unsigned int count)
-{
-	unsigned short *ptr = (unsigned short *) buffer;
-
-	while (count--) {
-		*ptr++ = tx_ioinw(addr);
-	}
-}
-void tx_inslong(unsigned int *addr, void *buffer, unsigned int count)
-{
-	unsigned long *ptr = (unsigned long *) buffer;
-
-	while (count--) {
-		*ptr++ = tx_ioinl(addr);
-	}
-}
-void tx_outsbyte(unsigned char *addr, void *buffer, unsigned int count)
-{
-	unsigned char *ptr = (unsigned char *) buffer;
-
-	while (count--) {
-		tx_iooutb(*ptr++, addr);
-	}
-}
-void tx_outsword(unsigned short *addr, void *buffer, unsigned int count)
-{
-	unsigned short *ptr = (unsigned short *) buffer;
-
-	while (count--) {
-		tx_iooutw(*ptr++, addr);
-	}
-}
-void tx_outslong(unsigned int *addr, void *buffer, unsigned int count)
-{
-	unsigned long *ptr = (unsigned long *) buffer;
-
-	while (count--) {
-		tx_iooutl(*ptr++, addr);
-	}
-}
-#endif
--- diff/arch/mips/pci/ops-ocelot.c	2003-08-20 14:16:25.000000000 +0100
+++ source/arch/mips/pci/ops-ocelot.c	1970-01-01 01:00:00.000000000 +0100
@@ -1,1056 +0,0 @@
-/*
- * BRIEF MODULE DESCRIPTION
- * Galileo Evaluation Boards PCI support.
- *
- * The general-purpose functions to read/write and configure the GT64120A's
- * PCI registers (function names start with pci0 or pci1) are either direct
- * copies of functions written by Galileo Technology, or are modifications
- * of their functions to work with Linux 2.4 vs Linux 2.2.  These functions
- * are Copyright - Galileo Technology.
- *
- * Other functions are derived from other MIPS PCI implementations, or were
- * written by RidgeRun, Inc,  Copyright (C) 2000 RidgeRun, Inc.
- *   glonnon@ridgerun.com, skranz@ridgerun.com, stevej@ridgerun.com
- *
- * Copyright 2001 MontaVista Software Inc.
- * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net
- *
- *  This program is free software; you can redistribute  it and/or modify it
- *  under  the terms of  the GNU General  Public License as published by the
- *  Free Software Foundation;  either version 2 of the  License, or (at your
- *  option) any later version.
- *
- *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
- *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
- *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
- *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
- *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
- *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- *  You should have received a copy of the  GNU General Public License along
- *  with this program; if not, write  to the Free Software Foundation, Inc.,
- *  675 Mass Ave, Cambridge, MA 02139, USA.
- */
-#include <linux/types.h>
-#include <linux/pci.h>
-#include <linux/kernel.h>
-#include <linux/slab.h>
-#include <linux/version.h>
-#include <linux/cache.h>
-#include <asm/pci.h>
-#include <asm/io.h>
-#include <asm/gt64120/gt64120.h>
-
-#include <linux/init.h>
-
-#define SELF 0
-
-/*
- * These functions and structures provide the BIOS scan and mapping of the PCI
- * devices.
- */
-
-#define MAX_PCI_DEVS 10
-
-struct pci_device {
-	u32 slot;
-	u32 BARtype[6];
-	u32 BARsize[6];
-};
-
-static void __init scan_and_initialize_pci(void);
-static u32 __init scan_pci_bus(struct pci_device *pci_devices);
-static void __init allocate_pci_space(struct pci_device *pci_devices);
-
-/*
- * The functions that actually read and write to the controller.
- *
- *  Copied from or modified from Galileo Technology code.
- */
-static unsigned int pci0ReadConfigReg(int offset, struct pci_dev *device);
-static void pci0WriteConfigReg(unsigned int offset,
-			       struct pci_dev *device, unsigned int data);
-static unsigned int pci1ReadConfigReg(int offset, struct pci_dev *device);
-static void pci1WriteConfigReg(unsigned int offset,
-			       struct pci_dev *device, unsigned int data);
-
-static void pci0MapIOspace(unsigned int pci0IoBase,
-			   unsigned int pci0IoLength);
-static void pci1MapIOspace(unsigned int pci1IoBase,
-			   unsigned int pci1IoLength);
-static void pci0MapMemory0space(unsigned int pci0Mem0Base,
-				unsigned int pci0Mem0Length);
-static void pci1MapMemory0space(unsigned int pci1Mem0Base,
-				unsigned int pci1Mem0Length);
-static void pci0MapMemory1space(unsigned int pci0Mem1Base,
-				unsigned int pci0Mem1Length);
-static void pci1MapMemory1space(unsigned int pci1Mem1Base,
-				unsigned int pci1Mem1Length);
-static unsigned int pci0GetIOspaceBase(void);
-static unsigned int pci0GetIOspaceSize(void);
-static unsigned int pci0GetMemory0Base(void);
-static unsigned int pci0GetMemory0Size(void);
-static unsigned int pci0GetMemory1Base(void);
-static unsigned int pci0GetMemory1Size(void);
-static unsigned int pci1GetIOspaceBase(void);
-static unsigned int pci1GetIOspaceSize(void);
-static unsigned int pci1GetMemory0Base(void);
-static unsigned int pci1GetMemory0Size(void);
-static unsigned int pci1GetMemory1Base(void);
-static unsigned int pci1GetMemory1Size(void);
-
-
-/*  Functions to implement "pci ops"  */
-static int galileo_pcibios_read(struct pci_bus *bus, unsigned int devfn,
-				int offset, int size, u32 * val);
-static int galileo_pcibios_write(struct pci_bus *bus, unsigned int devfn,
-				 int offset, int size, u32 val);
-static void galileo_pcibios_set_master(struct pci_dev *dev);
-
-/*
- *  General-purpose PCI functions.
- */
-
-/*
- * pci0MapIOspace - Maps PCI0 IO space for the master.
- * Inputs: base and length of pci0Io
- */
-
-static void pci0MapIOspace(unsigned int pci0IoBase,
-			   unsigned int pci0IoLength)
-{
-	unsigned int pci0IoTop =
-	    (unsigned int) (pci0IoBase + pci0IoLength);
-
-	if (pci0IoLength == 0)
-		pci0IoTop++;
-
-	pci0IoBase = (unsigned int) (pci0IoBase >> 21);
-	pci0IoTop = (unsigned int) (((pci0IoTop - 1) & 0x0fffffff) >> 21);
-	GT_WRITE(GT_PCI0IOLD_OFS, pci0IoBase);
-	GT_WRITE(GT_PCI0IOHD_OFS, pci0IoTop);
-}
-
-/*
- * pci1MapIOspace - Maps PCI1 IO space for the master.
- * Inputs: base and length of pci1Io
- */
-
-static void pci1MapIOspace(unsigned int pci1IoBase,
-			   unsigned int pci1IoLength)
-{
-	unsigned int pci1IoTop =
-	    (unsigned int) (pci1IoBase + pci1IoLength);
-
-	if (pci1IoLength == 0)
-		pci1IoTop++;
-
-	pci1IoBase = (unsigned int) (pci1IoBase >> 21);
-	pci1IoTop = (unsigned int) (((pci1IoTop - 1) & 0x0fffffff) >> 21);
-	GT_WRITE(GT_PCI1IOLD_OFS, pci1IoBase);
-	GT_WRITE(GT_PCI1IOHD_OFS, pci1IoTop);
-}
-
-/*
- * pci0MapMemory0space - Maps PCI0 memory0 space for the master.
- * Inputs: base and length of pci0Mem0
- */
-
-static void pci0MapMemory0space(unsigned int pci0Mem0Base,
-				unsigned int pci0Mem0Length)
-{
-	unsigned int pci0Mem0Top = pci0Mem0Base + pci0Mem0Length;
-
-	if (pci0Mem0Length == 0)
-		pci0Mem0Top++;
-
-	pci0Mem0Base = pci0Mem0Base >> 21;
-	pci0Mem0Top = ((pci0Mem0Top - 1) & 0x0fffffff) >> 21;
-	GT_WRITE(GT_PCI0M0LD_OFS, pci0Mem0Base);
-	GT_WRITE(GT_PCI0M0HD_OFS, pci0Mem0Top);
-}
-
-/*
- * pci1MapMemory0space - Maps PCI1 memory0 space for the master.
- * Inputs: base and length of pci1Mem0
- */
-
-static void pci1MapMemory0space(unsigned int pci1Mem0Base,
-				unsigned int pci1Mem0Length)
-{
-	unsigned int pci1Mem0Top = pci1Mem0Base + pci1Mem0Length;
-
-	if (pci1Mem0Length == 0)
-		pci1Mem0Top++;
-
-	pci1Mem0Base = pci1Mem0Base >> 21;
-	pci1Mem0Top = ((pci1Mem0Top - 1) & 0x0fffffff) >> 21;
-	GT_WRITE(GT_PCI1M0LD_OFS, pci1Mem0Base);
-	GT_WRITE(GT_PCI1M0HD_OFS, pci1Mem0Top);
-}
-
-/*
- * pci0MapMemory1space - Maps PCI0 memory1 space for the master.
- * Inputs: base and length of pci0Mem1
- */
-
-static void pci0MapMemory1space(unsigned int pci0Mem1Base,
-				unsigned int pci0Mem1Length)
-{
-	unsigned int pci0Mem1Top = pci0Mem1Base + pci0Mem1Length;
-
-	if (pci0Mem1Length == 0)
-		pci0Mem1Top++;
-
-	pci0Mem1Base = pci0Mem1Base >> 21;
-	pci0Mem1Top = ((pci0Mem1Top - 1) & 0x0fffffff) >> 21;
-	GT_WRITE(GT_PCI0M1LD_OFS, pci0Mem1Base);
-	GT_WRITE(GT_PCI0M1HD_OFS, pci0Mem1Top);
-
-}
-
-/*
- * pci1MapMemory1space - Maps PCI1 memory1 space for the master.
- * Inputs: base and length of pci1Mem1
- */
-
-static void pci1MapMemory1space(unsigned int pci1Mem1Base,
-				unsigned int pci1Mem1Length)
-{
-	unsigned int pci1Mem1Top = pci1Mem1Base + pci1Mem1Length;
-
-	if (pci1Mem1Length == 0)
-		pci1Mem1Top++;
-
-	pci1Mem1Base = pci1Mem1Base >> 21;
-	pci1Mem1Top = ((pci1Mem1Top - 1) & 0x0fffffff) >> 21;
-	GT_WRITE(GT_PCI1M1LD_OFS, pci1Mem1Base);
-	GT_WRITE(GT_PCI1M1HD_OFS, pci1Mem1Top);
-}
-
-/*
- * pci0GetIOspaceBase - Return PCI0 IO Base Address.
- * Inputs: N/A
- * Returns: PCI0 IO Base Address.
- */
-
-static unsigned int pci0GetIOspaceBase(void)
-{
-	unsigned int base;
-	GT_READ(GT_PCI0IOLD_OFS, &base);
-	base = base << 21;
-	return base;
-}
-
-/*
- * pci0GetIOspaceSize - Return PCI0 IO Bar Size.
- * Inputs: N/A
- * Returns: PCI0 IO Bar Size.
- */
-
-static unsigned int pci0GetIOspaceSize(void)
-{
-	unsigned int top, base, size;
-	GT_READ(GT_PCI0IOLD_OFS, &base);
-	base = base << 21;
-	GT_READ(GT_PCI0IOHD_OFS, &top);
-	top = (top << 21);
-	size = ((top - base) & 0xfffffff);
-	size = size | 0x1fffff;
-	return (size + 1);
-}
-
-/*
- * pci0GetMemory0Base - Return PCI0 Memory 0 Base Address.
- * Inputs: N/A
- * Returns: PCI0 Memory 0 Base Address.
- */
-
-static unsigned int pci0GetMemory0Base(void)
-{
-	unsigned int base;
-	GT_READ(GT_PCI0M0LD_OFS, &base);
-	base = base << 21;
-	return base;
-}
-
-/*
- * pci0GetMemory0Size - Return PCI0 Memory 0 Bar Size.
- * Inputs: N/A
- * Returns: PCI0 Memory 0 Bar Size.
- */
-
-static unsigned int pci0GetMemory0Size(void)
-{
-	unsigned int top, base, size;
-	GT_READ(GT_PCI0M0LD_OFS, &base);
-	base = base << 21;
-	GT_READ(GT_PCI0M0HD_OFS, &top);
-	top = (top << 21);
-	size = ((top - base) & 0xfffffff);
-	size = size | 0x1fffff;
-	return (size + 1);
-}
-
-/*
- * pci0GetMemory1Base - Return PCI0 Memory 1 Base Address.
- * Inputs: N/A
- * Returns: PCI0 Memory 1 Base Address.
- */
-
-static unsigned int pci0GetMemory1Base(void)
-{
-	unsigned int base;
-	GT_READ(GT_PCI0M1LD_OFS, &base);
-	base = base << 21;
-	return base;
-}
-
-/*
- * pci0GetMemory1Size - Return PCI0 Memory 1 Bar Size.
- * Inputs: N/A
- * Returns: PCI0 Memory 1 Bar Size.
- */
-
-static unsigned int pci0GetMemory1Size(void)
-{
-	unsigned int top, base, size;
-	GT_READ(GT_PCI0M1LD_OFS, &base);
-	base = base << 21;
-	GT_READ(GT_PCI0M1HD_OFS, &top);
-	top = (top << 21);
-	size = ((top - base) & 0xfffffff);
-	size = size | 0x1fffff;
-	return (size + 1);
-}
-
-/*
- * pci1GetIOspaceBase - Return PCI1 IO Base Address.
- * Inputs: N/A
- * Returns: PCI1 IO Base Address.
- */
-
-static unsigned int pci1GetIOspaceBase(void)
-{
-	unsigned int base;
-	GT_READ(GT_PCI1IOLD_OFS, &base);
-	base = base << 21;
-	return base;
-}
-
-/*
- * pci1GetIOspaceSize - Return PCI1 IO Bar Size.
- * Inputs: N/A
- * Returns: PCI1 IO Bar Size.
- */
-
-static unsigned int pci1GetIOspaceSize(void)
-{
-	unsigned int top, base, size;
-	GT_READ(GT_PCI1IOLD_OFS, &base);
-	base = base << 21;
-	GT_READ(GT_PCI1IOHD_OFS, &top);
-	top = (top << 21);
-	size = ((top - base) & 0xfffffff);
-	size = size | 0x1fffff;
-	return (size + 1);
-}
-
-/*
- * pci1GetMemory0Base - Return PCI1 Memory 0 Base Address.
- * Inputs: N/A
- * Returns: PCI1 Memory 0 Base Address.
- */
-
-static unsigned int pci1GetMemory0Base(void)
-{
-	unsigned int base;
-	GT_READ(GT_PCI1M0LD_OFS, &base);
-	base = base << 21;
-	return base;
-}
-
-/*
- * pci1GetMemory0Size - Return PCI1 Memory 0 Bar Size.
- * Inputs: N/A
- * Returns: PCI1 Memory 0 Bar Size.
- */
-
-static unsigned int pci1GetMemory0Size(void)
-{
-	unsigned int top, base, size;
-	GT_READ(GT_PCI1M1LD_OFS, &base);
-	base = base << 21;
-	GT_READ(GT_PCI1M1HD_OFS, &top);
-	top = (top << 21);
-	size = ((top - base) & 0xfffffff);
-	size = size | 0x1fffff;
-	return (size + 1);
-}
-
-/*
- * pci1GetMemory1Base - Return PCI1 Memory 1 Base Address.
- * Inputs: N/A
- * Returns: PCI1 Memory 1 Base Address.
- */
-
-static unsigned int pci1GetMemory1Base(void)
-{
-	unsigned int base;
-	GT_READ(GT_PCI1M1LD_OFS, &base);
-	base = base << 21;
-	return base;
-}
-
-/*
- * pci1GetMemory1Size - Return PCI1 Memory 1 Bar Size.
- * Inputs: N/A
- * Returns: PCI1 Memory 1 Bar Size.
- */
-
-static unsigned int pci1GetMemory1Size(void)
-{
-	unsigned int top, base, size;
-	GT_READ(GT_PCI1M1LD_OFS, &base);
-	base = base << 21;
-	GT_READ(GT_PCI1M1HD_OFS, &top);
-	top = (top << 21);
-	size = ((top - base) & 0xfffffff);
-	size = size | 0x1fffff;
-	return (size + 1);
-}
-
-
-
-/*
- * pci_range_ck -
- *
- * Check if the pci device that are trying to access does really exists
- * on the evaluation board.
- *
- * Inputs :
- * bus - bus number (0 for PCI 0 ; 1 for PCI 1)
- * dev - number of device on the specific pci bus
- *
- * Outpus :
- * 0 - if OK , 1 - if failure
- */
-static __inline__ int pci_range_ck(unsigned char bus, unsigned char dev)
-{
-	/*
-	 * We don't even pretend to handle other busses than bus 0 correctly.
-	 * Accessing device 31 crashes the CP7000 for some reason.
-	 */
-	if ((bus == 0) && (dev != 31))
-		return 0;
-	return -1;
-}
-
-/*
- * pciXReadConfigReg  - Read from a PCI configuration register
- *                    - Make sure the GT is configured as a master before
- *                      reading from another device on the PCI.
- *                   - The function takes care of Big/Little endian conversion.
- * INPUTS:   regOffset: The register offset as it apears in the GT spec (or PCI
- *                        spec)
- *           pciDevNum: The device number needs to be addressed.
- * RETURNS: data , if the data == 0xffffffff check the master abort bit in the
- *                 cause register to make sure the data is valid
- *
- *  Configuration Address 0xCF8:
- *
- *       31 30    24 23  16 15  11 10     8 7      2  0     <=bit Number
- *  |congif|Reserved|  Bus |Device|Function|Register|00|
- *  |Enable|        |Number|Number| Number | Number |  |    <=field Name
- *
- */
-static unsigned int pci0ReadConfigReg(int offset, struct pci_dev *device)
-{
-	unsigned int DataForRegCf8;
-	unsigned int data;
-
-	DataForRegCf8 = ((PCI_SLOT(device->devfn) << 11) |
-			 (PCI_FUNC(device->devfn) << 8) |
-			 (offset & ~0x3)) | 0x80000000;
-	GT_WRITE(GT_PCI0_CFGADDR_OFS, DataForRegCf8);
-
-	/*
-	 * The casual observer might wonder why the READ is duplicated here,
-	 * rather than immediately following the WRITE, and just have the swap
-	 * in the "if".  That's because there is a latency problem with trying
-	 * to read immediately after setting up the address register.  The "if"
-	 * check gives enough time for the address to stabilize, so the READ
-	 * can work.
-	 */
-	if (PCI_SLOT(device->devfn) == SELF) {	/* This board */
-		GT_READ(GT_PCI0_CFGDATA_OFS, &data);
-		return data;
-	} else {		/* The PCI is working in LE Mode so swap the Data. */
-		GT_READ(GT_PCI0_CFGDATA_OFS, &data);
-		return cpu_to_le32(data);
-	}
-}
-
-static unsigned int pci1ReadConfigReg(int offset, struct pci_dev *device)
-{
-	unsigned int DataForRegCf8;
-	unsigned int data;
-
-	DataForRegCf8 = ((PCI_SLOT(device->devfn) << 11) |
-			 (PCI_FUNC(device->devfn) << 8) |
-			 (offset & ~0x3)) | 0x80000000;
-	/*
-	 * The casual observer might wonder why the READ is duplicated here,
-	 * rather than immediately following the WRITE, and just have the
-	 * swap in the "if".  That's because there is a latency problem
-	 * with trying to read immediately after setting up the address
-	 * register.  The "if" check gives enough time for the address
-	 * to stabilize, so the READ can work.
-	 */
-	if (PCI_SLOT(device->devfn) == SELF) {	/* This board */
-		/* when configurating our own PCI 1 L-unit the access is through
-		   the PCI 0 interface with reg number = reg number + 0x80 */
-		DataForRegCf8 |= 0x80;
-		GT_WRITE(GT_PCI0_CFGADDR_OFS, DataForRegCf8);
-	} else {		/* The PCI is working in LE Mode so swap the Data. */
-		GT_WRITE(GT_PCI1_CFGADDR_OFS, DataForRegCf8);
-	}
-	if (PCI_SLOT(device->devfn) == SELF) {	/* This board */
-		GT_READ(GT_PCI0_CFGDATA_OFS, &data);
-		return data;
-	} else {
-		GT_READ(GT_PCI1_CFGDATA_OFS, &data);
-		return cpu_to_le32(data);
-	}
-}
-
-
-
-/*
- * pciXWriteConfigReg - Write to a PCI configuration register
- *                    - Make sure the GT is configured as a master before
- *                      writingto another device on the PCI.
- *                    - The function takes care of Big/Little endian conversion.
- * Inputs:   unsigned int regOffset: The register offset as it apears in the
- *           GT spec
- *                   (or any other PCI device spec)
- *           pciDevNum: The device number needs to be addressed.
- *
- *  Configuration Address 0xCF8:
- *
- *       31 30    24 23  16 15  11 10     8 7      2  0     <=bit Number
- *  |congif|Reserved|  Bus |Device|Function|Register|00|
- *  |Enable|        |Number|Number| Number | Number |  |    <=field Name
- *
- */
-static void pci0WriteConfigReg(unsigned int offset,
-			       struct pci_dev *device, unsigned int data)
-{
-	unsigned int DataForRegCf8;
-
-	DataForRegCf8 = ((PCI_SLOT(device->devfn) << 11) |
-			 (PCI_FUNC(device->devfn) << 8) |
-			 (offset & ~0x3)) | 0x80000000;
-	GT_WRITE(GT_PCI0_CFGADDR_OFS, DataForRegCf8);
-	if (PCI_SLOT(device->devfn) == SELF) {	/* This board */
-		GT_WRITE(GT_PCI0_CFGDATA_OFS, data);
-	} else {		/* configuration Transaction over the pci. */
-		/* The PCI is working in LE Mode so swap the Data. */
-		GT_WRITE(GT_PCI0_CFGDATA_OFS, le32_to_cpu(data));
-	}
-}
-
-static void pci1WriteConfigReg(unsigned int offset,
-			       struct pci_dev *device, unsigned int data)
-{
-	unsigned int DataForRegCf8;
-
-	DataForRegCf8 = ((PCI_SLOT(device->devfn) << 11) |
-			 (PCI_FUNC(device->devfn) << 8) |
-			 (offset & ~0x3)) | 0x80000000;
-	/*
-	 * There is a latency problem
-	 * with trying to read immediately after setting up the address
-	 * register.  The "if" check gives enough time for the address
-	 * to stabilize, so the WRITE can work.
-	 */
-	if (PCI_SLOT(device->devfn) == SELF) {	/* This board */
-		/*
-		 * when configurating our own PCI 1 L-unit the access is through
-		 * the PCI 0 interface with reg number = reg number + 0x80
-		 */
-		DataForRegCf8 |= 0x80;
-		GT_WRITE(GT_PCI0_CFGADDR_OFS, DataForRegCf8);
-	} else {		/* configuration Transaction over the pci. */
-		/* The PCI is working in LE Mode so swap the Data. */
-		GT_WRITE(GT_PCI1_CFGADDR_OFS, DataForRegCf8);
-	}
-	if (PCI_SLOT(device->devfn) == SELF) {	/* This board */
-		GT_WRITE(GT_PCI0_CFGDATA_OFS, data);
-	} else {		/* configuration Transaction over the pci. */
-		GT_WRITE(GT_PCI1_CFGADDR_OFS, le32_to_cpu(data));
-	}
-}
-
-
-/*
- * galileo_pcibios_(read/write) -
- *
- * reads/write a dword/word/byte register from the configuration space
- * of a device.
- *
- * Inputs :
- * bus - bus number
- * devfn - device function index
- * offset - register offset in the configuration space
- * size - size of value (1=byte,2=word,4-dword)
- * val - value to be written / read
- *
- * Outputs :
- * PCIBIOS_SUCCESSFUL when operation was succesfull
- * PCIBIOS_DEVICE_NOT_FOUND when the bus or dev is errorneous
- * PCIBIOS_BAD_REGISTER_NUMBER when accessing non aligned
- */
-
-static int galileo_pcibios_read(struct pci_bus *bus, unsigned int devfn,
-				int offset, int size, u32 * val)
-{
-	int dev, busnum;
-
-	busnum = bus->number;
-	dev = PCI_SLOT(devfn);
-
-	if (pci_range_ck(busnum, dev)) {
-		if (size == 1)
-			*val = (u8) 0xff;
-		else if (size == 2)
-			*val = (u16) 0xffff;
-		else if (size == 4)
-			*val = 0xffffffff;
-		return PCIBIOS_DEVICE_NOT_FOUND;
-	}
-	if ((size == 2) && (offset & 0x1))
-		return PCIBIOS_BAD_REGISTER_NUMBER;
-	else if ((size == 4) && (offset & 0x3))
-		return PCIBIOS_BAD_REGISTER_NUMBER;
-
-	if (busnum == 0) {
-		if (size == 1) {
-			*val = (u8) (pci0ReadConfigReg(offset, bus->dev) >>
-				     ((offset & ~0x3) * 8));
-		} else if (size == 2) {
-			*val =
-			    (u16) (pci0ReadConfigReg(offset, bus->dev) >>
-				   ((offset & ~0x3) * 8));
-		} else if (size == 4) {
-			*val = pci0ReadConfigReg(offset, bus->dev);
-		}
-	}
-
-	/*
-	 *  This is so that the upper PCI layer will get the correct return
-	 * value if we're not attached to anything.
-	 */
-	switch (size) {
-	case 1:
-		if ((offset == 0xe) && (*val == (u8) 0xff)) {
-			u32 MasterAbort;
-			GT_READ(GT_INTRCAUSE_OFS, &MasterAbort);
-			if (MasterAbort & 0x40000) {
-				GT_WRITE(GT_INTRCAUSE_OFS,
-					 (MasterAbort & 0xfffbffff));
-				return PCIBIOS_DEVICE_NOT_FOUND;
-			}
-		}
-		break;
-	case 4:
-		if ((offset == 0) && (*val == 0xffffffff)) {
-			return PCIBIOS_DEVICE_NOT_FOUND;
-		}
-	break}
-	return PCIBIOS_SUCCESSFUL;
-}
-
-static int galileo_pcibios_write(struct pci_bus *bus, unsigned int devfn,
-				 int offset, int size, u32 val)
-{
-	int dev, busnum;
-	unsigned long tmp;
-
-	busnum = bus->number;
-	dev = PCI_SLOT(devfn);
-
-	if (pci_range_ck(busnum, dev))
-		return PCIBIOS_DEVICE_NOT_FOUND;
-	if (size == 4) {
-		if (offset & 0x3)
-			return PCIBIOS_BAD_REGISTER_NUMBER;
-		if (busnum == 0)
-			pci0WriteConfigReg(offset, bus->dev, val);
-		//if (busnum == 1) pci1WriteConfigReg (offset,bus->dev,val);
-		return PCIBIOS_SUCCESSFUL;
-	}
-	if ((size == 2) && (offset & 0x1))
-		return PCIBIOS_BAD_REGISTER_NUMBER;
-	if (busnum == 0) {
-		tmp = pci0ReadConfigReg(offset, bus->dev);
-		//if (busnum == 1) tmp = pci1ReadConfigReg (offset,bus->dev);
-		if (size == 1) {
-			if ((offset % 4) == 0)
-				tmp =
-				    (tmp & 0xffffff00) | (val & (u8) 0xff);
-			if ((offset % 4) == 1)
-				tmp =
-				    (tmp & 0xffff00ff) | ((val & (u8) 0xff)
-							  << 8);
-			if ((offset % 4) == 2)
-				tmp =
-				    (tmp & 0xff00ffff) | ((val & (u8) 0xff)
-							  << 16);
-			if ((offset % 4) == 3)
-				tmp =
-				    (tmp & 0x00ffffff) | ((val & (u8) 0xff)
-							  << 24);
-		} else if (size == 2) {
-			if ((offset % 4) == 0)
-				tmp =
-				    (tmp & 0xffff0000) | (val & (u16)
-							  0xffff);
-			if ((offset % 4) == 2)
-				tmp =
-				    (tmp & 0x0000ffff) |
-				    ((val & (u16) 0xffff) << 16);
-		}
-		if (busnum == 0)
-			pci0WriteConfigReg(offset, bus->dev, tmp);
-		//if (busnum == 1) pci1WriteConfigReg (offset,bus->dev,tmp);
-	}
-	return PCIBIOS_SUCCESSFUL;
-}
-
-static void galileo_pcibios_set_master(struct pci_dev *dev)
-{
-	u16 cmd;
-
-	galileo_pcibios_read(dev->bus, dev->devfn, PCI_COMMAND, 2, &cmd);
-	cmd |= PCI_COMMAND_MASTER;
-	galileo_pcibios_write(dev->bus, dev->devfn, PCI_COMMAND, 2, cmd);
-}
-
-/*  Externally-expected functions.  Do not change function names  */
-
-int pcibios_enable_resources(struct pci_dev *dev)
-{
-	u16 cmd, old_cmd;
-	u8 tmp1;
-	int idx;
-	struct resource *r;
-
-	galileo_pcibios_read(dev->bus, dev->devfn, PCI_COMMAND, 2, &cmd);
-	old_cmd = cmd;
-	for (idx = 0; idx < 6; idx++) {
-		r = &dev->resource[idx];
-		if (!r->start && r->end) {
-			printk(KERN_ERR
-			       "PCI: Device %s not available because of "
-			       "resource collisions\n", pci_name(dev));
-			return -EINVAL;
-		}
-		if (r->flags & IORESOURCE_IO)
-			cmd |= PCI_COMMAND_IO;
-		if (r->flags & IORESOURCE_MEM)
-			cmd |= PCI_COMMAND_MEMORY;
-	}
-	if (cmd != old_cmd) {
-		galileo_pcibios_write(dev->bus, dev->devfn, PCI_COMMAND, 2,
-				      cmd);
-	}
-
-	/*
-	 * Let's fix up the latency timer and cache line size here.  Cache
-	 * line size = 32 bytes / sizeof dword (4) = 8.
-	 * Latency timer must be > 8.  32 is random but appears to work.
-	 */
-	galileo_pcibios_read(dev->bus, dev->devfn, PCI_CACHE_LINE_SIZE, 1,
-			     &tmp1);
-	if (tmp1 != 8) {
-		printk(KERN_WARNING
-		       "PCI setting cache line size to 8 from " "%d\n",
-		       tmp1);
-		galileo_pcibios_write(dev->bus, dev->devfn,
-				      PCI_CACHE_LINE_SIZE, 1, 8);
-	}
-	galileo_pcibios_read(dev->bus, dev->devfn, PCI_LATENCY_TIMER, 1,
-			     &tmp1);
-	if (tmp1 < 32) {
-		printk(KERN_WARNING
-		       "PCI setting latency timer to 32 from %d\n", tmp1);
-		galileo_pcibios_write(dev->bus, dev->devfn,
-				      PCI_LATENCY_TIMER, 1, 32);
-	}
-
-	return 0;
-}
-
-int pcibios_enable_device(struct pci_dev *dev, int mask)
-{
-	return pcibios_enable_resources(dev);
-}
-
-void pcibios_align_resource(void *data, struct resource *res,
-			    unsigned long size, unsigned long align)
-{
-	struct pci_dev *dev = data;
-
-	if (res->flags & IORESOURCE_IO) {
-		unsigned long start = res->start;
-
-		/* We need to avoid collisions with `mirrored' VGA ports
-		   and other strange ISA hardware, so we always want the
-		   addresses kilobyte aligned.  */
-		if (size > 0x100) {
-			printk(KERN_ERR "PCI: I/O Region %s/%d too large"
-			       " (%ld bytes)\n", pci_name(dev),
-			       dev->resource - res, size);
-		}
-
-		start = (start + 1024 - 1) & ~(1024 - 1);
-		res->start = start;
-	}
-}
-
-struct pci_ops galileo_pci_ops = {
-	.read = galileo_pcibios_read,
-	.write = galileo_pcibios_write,
-};
-
-struct pci_fixup pcibios_fixups[] = {
-	{0}
-};
-
-void __devinit pcibios_fixup_bus(struct pci_bus *c)
-{
-	gt64120_board_pcibios_fixup_bus(c);
-}
-
-/*
- * This code was derived from Galileo Technology's example
- * and significantly reworked.
- *
- * This is very simple.  It does not scan multiple function devices.  It does
- * not scan behind bridges.  Those would be simple to implement, but we don't
- * currently need this.
- */
-
-static void __init scan_and_initialize_pci(void)
-{
-	struct pci_device pci_devices[MAX_PCI_DEVS];
-
-	if (scan_pci_bus(pci_devices)) {
-		allocate_pci_space(pci_devices);
-	}
-}
-
-/*
- * This is your basic PCI scan.  It goes through each slot and checks to
- * see if there's something that responds.  If so, then get the size and
- * type of each of the responding BARs.  Save them for later.
- */
-
-static u32 __init scan_pci_bus(struct pci_device *pci_devices)
-{
-	u32 arrayCounter = 0;
-	u32 memType;
-	u32 memSize;
-	u32 pci_slot, bar;
-	u32 id;
-	u32 c18RegValue;
-	struct pci_dev device;
-
-	/*
-	 * According to PCI REV 2.1 MAX agents on the bus are 21.
-	 * We don't bother scanning ourselves (slot 0).
-	 */
-	for (pci_slot = 1; pci_slot < 22; pci_slot++) {
-
-		device.devfn = PCI_DEVFN(pci_slot, 0);
-		id = pci0ReadConfigReg(PCI_VENDOR_ID, &device);
-
-		/*
-		 *  Check for a PCI Master Abort (nothing responds in the
-		 * slot)
-		 */
-		GT_READ(GT_INTRCAUSE_OFS, &c18RegValue);
-		/*
-		 * Clearing bit 18 of in the Cause Register 0xc18 by
-		 * writting 0.
-		 */
-		GT_WRITE(GT_INTRCAUSE_OFS, (c18RegValue & 0xfffbffff));
-		if ((id != 0xffffffff) && !(c18RegValue & 0x40000)) {
-			pci_devices[arrayCounter].slot = pci_slot;
-			for (bar = 0; bar < 6; bar++) {
-				memType =
-				    pci0ReadConfigReg(PCI_BASE_ADDRESS_0 +
-						      (bar * 4), &device);
-				pci_devices[arrayCounter].BARtype[bar] =
-				    memType & 1;
-				pci0WriteConfigReg(PCI_BASE_ADDRESS_0 +
-						   (bar * 4), &device,
-						   0xffffffff);
-				memSize =
-				    pci0ReadConfigReg(PCI_BASE_ADDRESS_0 +
-						      (bar * 4), &device);
-				if (memType & 1) {	/*  IO space  */
-					pci_devices[arrayCounter].
-					    BARsize[bar] =
-					    ~(memSize & 0xfffffffc) + 1;
-				} else {	/*  memory space */
-					pci_devices[arrayCounter].
-					    BARsize[bar] =
-					    ~(memSize & 0xfffffff0) + 1;
-				}
-			}	/*  BAR counter  */
-
-			arrayCounter++;
-		}
-		/*  found a device  */
-	}			/*  slot counter  */
-
-	if (arrayCounter < MAX_PCI_DEVS)
-		pci_devices[arrayCounter].slot = -1;
-
-	return arrayCounter;
-}
-
-/*
- * This function goes through the list of devices and allocates the BARs in
- * either IO or MEM space.  It does it in order of size, which will limit the
- * amount of fragmentation we have in the IO and MEM spaces.
- */
-
-static void __init allocate_pci_space(struct pci_device *pci_devices)
-{
-	u32 count, maxcount, bar;
-	u32 maxSize, maxDevice, maxBAR;
-	u32 alignto;
-	u32 base;
-	u32 pci0_mem_base = pci0GetMemory0Base();
-	u32 pci0_io_base = pci0GetIOspaceBase();
-	struct pci_dev device;
-
-	/*  How many PCI devices do we have?  */
-	maxcount = MAX_PCI_DEVS;
-	for (count = 0; count < MAX_PCI_DEVS; count++) {
-		if (pci_devices[count].slot == -1) {
-			maxcount = count;
-			break;
-		}
-	}
-
-	do {
-		/*  Find the largest size BAR we need to allocate  */
-		maxSize = 0;
-		for (count = 0; count < maxcount; count++) {
-			for (bar = 0; bar < 6; bar++) {
-				if (pci_devices[count].BARsize[bar] >
-				    maxSize) {
-					maxSize =
-					    pci_devices[count].
-					    BARsize[bar];
-					maxDevice = count;
-					maxBAR = bar;
-				}
-			}
-		}
-
-		/*
-		 * We've found the largest BAR.  Allocate it into IO or
-		 * mem space.  We don't idiot check the bases to make
-		 * sure they haven't overflowed the current size for that
-		 * aperture.
-		 * Don't bother to enable the device's IO or MEM space here.
-		 * That will be done in pci_enable_resources if the device is
-		 * activated by a driver.
-		 */
-		if (maxSize) {
-			device.devfn =
-			    PCI_DEVFN(pci_devices[maxDevice].slot, 0);
-			if (pci_devices[maxDevice].BARtype[maxBAR] == 1) {
-				alignto = max(0x1000U, maxSize);
-				base = ALIGN(pci0_io_base, alignto);
-				pci0WriteConfigReg(PCI_BASE_ADDRESS_0 +
-						   (maxBAR * 4), &device,
-						   base | 0x1);
-				pci0_io_base = base + alignto;
-			} else {
-				alignto = max(0x1000U, maxSize);
-				base = ALIGN(pci0_mem_base, alignto);
-				pci0WriteConfigReg(PCI_BASE_ADDRESS_0 +
-						   (maxBAR * 4), &device,
-						   base);
-				pci0_mem_base = base + alignto;
-			}
-			/*
-			 * This entry is finished.  Remove it from the list
-			 * we'll scan.
-			 */
-			pci_devices[maxDevice].BARsize[maxBAR] = 0;
-		}
-	} while (maxSize);
-}
-
-static int __init pcibios_init(void)
-{
-	u32 tmp;
-	struct pci_dev controller;
-
-	controller.devfn = SELF;
-
-	GT_READ(GT_PCI0_CMD_OFS, &tmp);
-	GT_READ(GT_PCI0_BARE_OFS, &tmp);
-
-	/*
-	 * You have to enable bus mastering to configure any other
-	 * card on the bus.
-	 */
-	tmp = pci0ReadConfigReg(PCI_COMMAND, &controller);
-	tmp |= PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER | PCI_COMMAND_SERR;
-	pci0WriteConfigReg(PCI_COMMAND, &controller, tmp);
-
-	/*  This scans the PCI bus and sets up initial values.  */
-	scan_and_initialize_pci();
-
-	/*
-	 *  Reset PCI I/O and PCI MEM values to ones supported by EVM.
-	 */
-	ioport_resource.start = GT_PCI_IO_BASE;
-	ioport_resource.end = GT_PCI_IO_BASE + GT_PCI_IO_SIZE - 1;
-	iomem_resource.start = GT_PCI_MEM_BASE;
-	iomem_resource.end = GT_PCI_MEM_BASE + GT_PCI_MEM_BASE - 1;
-
-	pci_scan_bus(0, &galileo_pci_ops, NULL);
-
-	return 0;
-}
-
-subsys_initcall(pcibios_init);
-
-/*
- * for parsing "pci=" kernel boot arguments.
- */
-char *pcibios_setup(char *str)
-{
-	printk(KERN_INFO "rr: pcibios_setup\n");
-	/* Nothing to do for now.  */
-
-	return str;
-}
-
-unsigned __init int pcibios_assign_all_busses(void)
-{
-	return 1;
-}
--- diff/arch/mips/pci/pci-auto.c	2003-07-08 09:55:17.000000000 +0100
+++ source/arch/mips/pci/pci-auto.c	1970-01-01 01:00:00.000000000 +0100
@@ -1,518 +0,0 @@
-/*
- * PCI autoconfiguration library
- *
- * Author: Matt Porter <mporter@mvista.com>
- *
- * Copyright 2000, 2001, 2002, 2003 MontaVista Software Inc.
- * Copyright 2001 Bradley D. LaRonde <brad@ltc.com>
- *
- * This program is free software; you can redistribute  it and/or modify it
- * under  the terms of  the GNU General  Public License as published by the
- * Free Software Foundation;  either version 2 of the  License, or (at your
- * option) any later version.
- */
-
-/*
- * Modified for MIPS by Jun Sun, jsun@mvista.com
- *
- * . Simplify the interface between pci_auto and the rest: a single function.
- * . Assign resources from low address to upper address.
- * . change most int to u32.
- *
- * Further modified to include it as mips generic code, ppopov@mvista.com.
- *
- * 2001-10-26  Bradley D. LaRonde <brad@ltc.com>
- * - Add a top_bus argument to the "early config" functions so that
- *   they can set a fake parent bus pointer to convince the underlying
- *   pci ops to use type 1 configuration for sub busses.
- * - Set bridge base and limit registers correctly.
- * - Align io and memory base properly before and after bridge setup.
- * - Don't fall through to pci_setup_bars for bridge.
- * - Reformat the debug output to look more like lspci's output.
- *
- * 2003-04-09 Yoichi Yuasa, Alice Hennessy, Jun Sun
- * - Add cardbus bridge support, mostly copied from PPC
- */
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/types.h>
-#include <linux/pci.h>
-
-#include <asm/pci_channel.h>
-
-#define	DEBUG
-#ifdef 	DEBUG
-#define	DBG(x...)	printk(x)
-#else
-#define	DBG(x...)
-#endif
-
-/*
- * These functions are used early on before PCI scanning is done
- * and all of the pci_dev and pci_bus structures have been created.
- */
-static struct pci_dev *fake_pci_dev(struct pci_channel *hose,
-				    int top_bus, int busnr, int devfn)
-{
-	static struct pci_dev dev;
-	static struct pci_bus bus;
-
-	dev.bus = &bus;
-	dev.sysdata = hose;
-	dev.devfn = devfn;
-	bus.number = busnr;
-	bus.ops = hose->pci_ops;
-
-	if (busnr != top_bus)
-		/* Fake a parent bus structure. */
-		bus.parent = &bus;
-	else
-		bus.parent = NULL;
-
-	return &dev;
-}
-
-#define EARLY_PCI_OP(rw, size, type)					\
-int early_##rw##_config_##size(struct pci_channel *hose,		\
-	int top_bus, int bus, int devfn, int offset, type value)	\
-{									\
-	return pci_##rw##_config_##size(				\
-		fake_pci_dev(hose, top_bus, bus, devfn),		\
-		offset, value);						\
-}
-
-EARLY_PCI_OP(read, byte, u8 *)
-    EARLY_PCI_OP(read, word, u16 *)
-    EARLY_PCI_OP(read, dword, u32 *)
-    EARLY_PCI_OP(write, byte, u8)
-    EARLY_PCI_OP(write, word, u16)
-    EARLY_PCI_OP(write, dword, u32)
-
-static struct resource *io_resource_inuse;
-static struct resource *mem_resource_inuse;
-
-static u32 pciauto_lower_iospc;
-static u32 pciauto_upper_iospc;
-
-static u32 pciauto_lower_memspc;
-static u32 pciauto_upper_memspc;
-
-void __init
-pciauto_setup_bars(struct pci_channel *hose,
-		   int top_bus,
-		   int current_bus, int pci_devfn, int bar_limit)
-{
-	u32 bar_response, bar_size, bar_value;
-	u32 bar, addr_mask, bar_nr = 0;
-	u32 *upper_limit;
-	u32 *lower_limit;
-	int found_mem64 = 0;
-
-	for (bar = PCI_BASE_ADDRESS_0; bar <= bar_limit; bar += 4) {
-		/* Tickle the BAR and get the response */
-		early_write_config_dword(hose, top_bus,
-					 current_bus,
-					 pci_devfn, bar, 0xffffffff);
-		early_read_config_dword(hose, top_bus,
-					current_bus,
-					pci_devfn, bar, &bar_response);
-
-		/* If BAR is not implemented go to the next BAR */
-		if (!bar_response)
-			continue;
-
-		/*
-		 * Workaround for a BAR that doesn't use its upper word,
-		 * like the ALi 1535D+ PCI DC-97 Controller Modem (M5457).
-		 * bdl <brad@ltc.com>
-		 */
-		if (!(bar_response & 0xffff0000))
-			bar_response |= 0xffff0000;
-
-	      retry:
-		/* Check the BAR type and set our address mask */
-		if (bar_response & PCI_BASE_ADDRESS_SPACE) {
-			addr_mask = PCI_BASE_ADDRESS_IO_MASK;
-			upper_limit = &pciauto_upper_iospc;
-			lower_limit = &pciauto_lower_iospc;
-			DBG("        I/O");
-		} else {
-			if ((bar_response & PCI_BASE_ADDRESS_MEM_TYPE_MASK)
-			    == PCI_BASE_ADDRESS_MEM_TYPE_64)
-				found_mem64 = 1;
-
-			addr_mask = PCI_BASE_ADDRESS_MEM_MASK;
-			upper_limit = &pciauto_upper_memspc;
-			lower_limit = &pciauto_lower_memspc;
-			DBG("        Mem");
-		}
-
-
-		/* Calculate requested size */
-		bar_size = ~(bar_response & addr_mask) + 1;
-
-		/* Allocate a base address */
-		bar_value =
-		    ((*lower_limit - 1) & ~(bar_size - 1)) + bar_size;
-
-		if ((bar_value + bar_size) > *upper_limit) {
-			if (bar_response & PCI_BASE_ADDRESS_SPACE) {
-				if (io_resource_inuse->child) {
-					io_resource_inuse =
-					    io_resource_inuse->child;
-					pciauto_lower_iospc =
-					    io_resource_inuse->start;
-					pciauto_upper_iospc =
-					    io_resource_inuse->end + 1;
-					goto retry;
-				}
-
-			} else {
-				if (mem_resource_inuse->child) {
-					mem_resource_inuse =
-					    mem_resource_inuse->child;
-					pciauto_lower_memspc =
-					    mem_resource_inuse->start;
-					pciauto_upper_memspc =
-					    mem_resource_inuse->end + 1;
-					goto retry;
-				}
-			}
-			DBG(" unavailable -- skipping\n");
-			continue;
-		}
-
-		/* Write it out and update our limit */
-		early_write_config_dword(hose, top_bus, current_bus,
-					 pci_devfn, bar, bar_value);
-
-		*lower_limit = bar_value + bar_size;
-
-		/*
-		 * If we are a 64-bit decoder then increment to the
-		 * upper 32 bits of the bar and force it to locate
-		 * in the lower 4GB of memory.
-		 */
-		if (found_mem64) {
-			bar += 4;
-			early_write_config_dword(hose, top_bus,
-						 current_bus,
-						 pci_devfn,
-						 bar, 0x00000000);
-		}
-
-		DBG(" at 0x%.8x [size=0x%x]\n", bar_value, bar_size);
-
-		bar_nr++;
-	}
-
-}
-
-void __init
-pciauto_prescan_setup_bridge(struct pci_channel *hose,
-			     int top_bus,
-			     int current_bus, int pci_devfn, int sub_bus)
-{
-	/* Configure bus number registers */
-	early_write_config_byte(hose, top_bus, current_bus, pci_devfn,
-				PCI_PRIMARY_BUS, current_bus);
-	early_write_config_byte(hose, top_bus, current_bus, pci_devfn,
-				PCI_SECONDARY_BUS, sub_bus + 1);
-	early_write_config_byte(hose, top_bus, current_bus, pci_devfn,
-				PCI_SUBORDINATE_BUS, 0xff);
-
-	/* Align memory and I/O to 1MB and 4KB boundaries. */
-	pciauto_lower_memspc = (pciauto_lower_memspc + (0x100000 - 1))
-	    & ~(0x100000 - 1);
-	pciauto_lower_iospc = (pciauto_lower_iospc + (0x1000 - 1))
-	    & ~(0x1000 - 1);
-
-	/* Set base (lower limit) of address range behind bridge. */
-	early_write_config_word(hose, top_bus, current_bus, pci_devfn,
-				PCI_MEMORY_BASE,
-				pciauto_lower_memspc >> 16);
-	early_write_config_byte(hose, top_bus, current_bus, pci_devfn,
-				PCI_IO_BASE,
-				(pciauto_lower_iospc & 0x0000f000) >> 8);
-	early_write_config_word(hose, top_bus, current_bus, pci_devfn,
-				PCI_IO_BASE_UPPER16,
-				pciauto_lower_iospc >> 16);
-
-	/* We don't support prefetchable memory for now, so disable */
-	early_write_config_word(hose, top_bus, current_bus, pci_devfn,
-				PCI_PREF_MEMORY_BASE, 0);
-	early_write_config_word(hose, top_bus, current_bus, pci_devfn,
-				PCI_PREF_MEMORY_LIMIT, 0);
-}
-
-void __init
-pciauto_postscan_setup_bridge(struct pci_channel *hose,
-			      int top_bus,
-			      int current_bus, int pci_devfn, int sub_bus)
-{
-	u32 temp;
-
-	/* 
-	 * [jsun] we always bump up baselines a little, so that if there
-	 * nothing behind P2P bridge, we don't wind up overlapping IO/MEM
-	 * spaces.
-	 */
-	pciauto_lower_memspc += 1;
-	pciauto_lower_iospc += 1;
-
-	/* Configure bus number registers */
-	early_write_config_byte(hose, top_bus, current_bus, pci_devfn,
-				PCI_SUBORDINATE_BUS, sub_bus);
-
-	/* Set upper limit of address range behind bridge. */
-	early_write_config_word(hose, top_bus, current_bus, pci_devfn,
-				PCI_MEMORY_LIMIT,
-				pciauto_lower_memspc >> 16);
-	early_write_config_byte(hose, top_bus, current_bus, pci_devfn,
-				PCI_IO_LIMIT,
-				(pciauto_lower_iospc & 0x0000f000) >> 8);
-	early_write_config_word(hose, top_bus, current_bus, pci_devfn,
-				PCI_IO_LIMIT_UPPER16,
-				pciauto_lower_iospc >> 16);
-
-	/* Align memory and I/O to 1MB and 4KB boundaries. */
-	pciauto_lower_memspc = (pciauto_lower_memspc + (0x100000 - 1))
-	    & ~(0x100000 - 1);
-	pciauto_lower_iospc = (pciauto_lower_iospc + (0x1000 - 1))
-	    & ~(0x1000 - 1);
-
-	/* Enable memory and I/O accesses, enable bus master */
-	early_read_config_dword(hose, top_bus, current_bus, pci_devfn,
-				PCI_COMMAND, &temp);
-	early_write_config_dword(hose, top_bus, current_bus, pci_devfn,
-				 PCI_COMMAND,
-				 temp | PCI_COMMAND_IO | PCI_COMMAND_MEMORY
-				 | PCI_COMMAND_MASTER);
-}
-
-void __init
-pciauto_prescan_setup_cardbus_bridge(struct pci_channel *hose,
-				     int top_bus,
-				     int current_bus,
-				     int pci_devfn, int sub_bus)
-{
-	/* Configure bus number registers */
-	early_write_config_byte(hose, top_bus, current_bus, pci_devfn,
-				PCI_PRIMARY_BUS, current_bus);
-	early_write_config_byte(hose, top_bus, current_bus, pci_devfn,
-				PCI_SECONDARY_BUS, sub_bus + 1);
-	early_write_config_byte(hose, top_bus, current_bus, pci_devfn,
-				PCI_SUBORDINATE_BUS, 0xff);
-
-	/* Align memory and I/O to 4KB and 4 byte boundaries. */
-	pciauto_lower_memspc = (pciauto_lower_memspc + (0x1000 - 1))
-	    & ~(0x1000 - 1);
-	pciauto_lower_iospc = (pciauto_lower_iospc + (0x4 - 1))
-	    & ~(0x4 - 1);
-
-	early_write_config_dword(hose, top_bus, current_bus, pci_devfn,
-				 PCI_CB_MEMORY_BASE_0,
-				 pciauto_lower_memspc);
-	early_write_config_dword(hose, top_bus, current_bus, pci_devfn,
-				 PCI_CB_IO_BASE_0, pciauto_lower_iospc);
-}
-
-void __init
-pciauto_postscan_setup_cardbus_bridge(struct pci_channel *hose,
-				      int top_bus,
-				      int current_bus,
-				      int pci_devfn, int sub_bus)
-{
-	u32 temp;
-
-	/*
-	 * Configure subordinate bus number.  The PCI subsystem
-	 * bus scan will renumber buses (reserving three additional
-	 * for this PCI<->CardBus bridge for the case where a CardBus
-	 * adapter contains a P2P or CB2CB bridge.
-	 */
-
-	early_write_config_byte(hose, top_bus, current_bus, pci_devfn,
-				PCI_SUBORDINATE_BUS, sub_bus);
-
-	/*
-	 * Reserve an additional 4MB for mem space and 16KB for
-	 * I/O space.  This should cover any additional space
-	 * requirement of unusual CardBus devices with 
-	 * additional bridges that can consume more address space.
-	 * 
-	 * Although pcmcia-cs currently will reprogram bridge
-	 * windows, the goal is to add an option to leave them
-	 * alone and use the bridge window ranges as the regions
-	 * that are searched for free resources upon hot-insertion
-	 * of a device.  This will allow a PCI<->CardBus bridge
-	 * configured by this routine to happily live behind a
-	 * P2P bridge in a system.
-	 */
-	pciauto_lower_memspc += 0x00400000;
-	pciauto_lower_iospc += 0x00004000;
-
-	/* Align memory and I/O to 4KB and 4 byte boundaries. */
-	pciauto_lower_memspc = (pciauto_lower_memspc + (0x1000 - 1))
-	    & ~(0x1000 - 1);
-	pciauto_lower_iospc = (pciauto_lower_iospc + (0x4 - 1))
-	    & ~(0x4 - 1);
-	/* Set up memory and I/O filter limits, assume 32-bit I/O space */
-	early_write_config_dword(hose, top_bus, current_bus, pci_devfn,
-				 PCI_CB_MEMORY_LIMIT_0,
-				 pciauto_lower_memspc - 1);
-	early_write_config_dword(hose, top_bus, current_bus, pci_devfn,
-				 PCI_CB_IO_LIMIT_0,
-				 pciauto_lower_iospc - 1);
-
-	/* Enable memory and I/O accesses, enable bus master */
-	early_read_config_dword(hose, top_bus, current_bus, pci_devfn,
-				PCI_COMMAND, &temp);
-	early_write_config_dword(hose, top_bus, current_bus, pci_devfn,
-				 PCI_COMMAND,
-				 temp | PCI_COMMAND_IO | PCI_COMMAND_MEMORY
-				 | PCI_COMMAND_MASTER);
-}
-
-#define      PCIAUTO_IDE_MODE_MASK           0x05
-
-int __init
-pciauto_bus_scan(struct pci_channel *hose, int top_bus, int current_bus)
-{
-	int sub_bus;
-	u32 pci_devfn, pci_class, cmdstat, found_multi = 0;
-	unsigned short vid, did;
-	unsigned char header_type;
-	int devfn_start = 0;
-	int devfn_stop = 0xff;
-
-	sub_bus = current_bus;
-
-	if (hose->first_devfn)
-		devfn_start = hose->first_devfn;
-	if (hose->last_devfn)
-		devfn_stop = hose->last_devfn;
-
-	for (pci_devfn = devfn_start; pci_devfn < devfn_stop; pci_devfn++) {
-
-		if (PCI_FUNC(pci_devfn) && !found_multi)
-			continue;
-
-		early_read_config_word(hose, top_bus, current_bus,
-				       pci_devfn, PCI_VENDOR_ID, &vid);
-
-		if (vid == 0xffff)
-			continue;
-
-		early_read_config_byte(hose, top_bus, current_bus,
-				       pci_devfn, PCI_HEADER_TYPE,
-				       &header_type);
-
-		if (!PCI_FUNC(pci_devfn))
-			found_multi = header_type & 0x80;
-
-		early_read_config_word(hose, top_bus, current_bus,
-				       pci_devfn, PCI_DEVICE_ID, &did);
-
-		early_read_config_dword(hose, top_bus, current_bus,
-					pci_devfn, PCI_CLASS_REVISION,
-					&pci_class);
-
-		DBG("%.2x:%.2x.%x Class %.4x: %.4x:%.4x",
-		    current_bus, PCI_SLOT(pci_devfn), PCI_FUNC(pci_devfn),
-		    pci_class >> 16, vid, did);
-		if (pci_class & 0xff)
-			DBG(" (rev %.2x)", pci_class & 0xff);
-		DBG("\n");
-
-		if ((pci_class >> 16) == PCI_CLASS_BRIDGE_PCI) {
-			DBG("        Bridge: primary=%.2x, secondary=%.2x\n", current_bus, sub_bus + 1);
-			pciauto_setup_bars(hose, top_bus, current_bus,
-					   pci_devfn, PCI_BASE_ADDRESS_1);
-			pciauto_prescan_setup_bridge(hose, top_bus,
-						     current_bus,
-						     pci_devfn, sub_bus);
-			DBG("Scanning sub bus %.2x, I/O 0x%.8x, Mem 0x%.8x\n", sub_bus + 1, pciauto_lower_iospc, pciauto_lower_memspc);
-			sub_bus =
-			    pciauto_bus_scan(hose, top_bus, sub_bus + 1);
-			DBG("Back to bus %.2x\n", current_bus);
-			pciauto_postscan_setup_bridge(hose, top_bus,
-						      current_bus,
-						      pci_devfn, sub_bus);
-			continue;
-		} else if ((pci_class >> 16) == PCI_CLASS_BRIDGE_CARDBUS) {
-			DBG("  CARDBUS  Bridge: primary=%.2x, secondary=%.2x\n", current_bus, sub_bus + 1);
-			DBG("PCI Autoconfig: Found CardBus bridge, device %d function %d\n", PCI_SLOT(pci_devfn), PCI_FUNC(pci_devfn));
-			/* Place CardBus Socket/ExCA registers */
-			pciauto_setup_bars(hose, top_bus, current_bus,
-					   pci_devfn, PCI_BASE_ADDRESS_0);
-
-			pciauto_prescan_setup_cardbus_bridge(hose, top_bus,
-							     current_bus,
-							     pci_devfn,
-							     sub_bus);
-
-			DBG("Scanning sub bus %.2x, I/O 0x%.8x, Mem 0x%.8x\n", sub_bus + 1, pciauto_lower_iospc, pciauto_lower_memspc);
-			sub_bus =
-			    pciauto_bus_scan(hose, top_bus, sub_bus + 1);
-			DBG("Back to bus %.2x, sub_bus is %x\n",
-			    current_bus, sub_bus);
-			pciauto_postscan_setup_cardbus_bridge(hose,
-							      top_bus,
-							      current_bus,
-							      pci_devfn,
-							      sub_bus);
-			continue;
-		} else if ((pci_class >> 16) == PCI_CLASS_STORAGE_IDE) {
-
-			unsigned char prg_iface;
-
-			early_read_config_byte(hose, top_bus, current_bus,
-					       pci_devfn, PCI_CLASS_PROG,
-					       &prg_iface);
-			if (!(prg_iface & PCIAUTO_IDE_MODE_MASK)) {
-				DBG("Skipping legacy mode IDE controller\n");
-				continue;
-			}
-		}
-
-		/*
-		 * Found a peripheral, enable some standard
-		 * settings
-		 */
-		early_read_config_dword(hose, top_bus, current_bus,
-					pci_devfn, PCI_COMMAND, &cmdstat);
-		early_write_config_dword(hose, top_bus, current_bus,
-					 pci_devfn, PCI_COMMAND,
-					 cmdstat | PCI_COMMAND_IO |
-					 PCI_COMMAND_MEMORY |
-					 PCI_COMMAND_MASTER);
-		early_write_config_byte(hose, top_bus, current_bus,
-					pci_devfn, PCI_LATENCY_TIMER,
-					0x80);
-
-		/* Allocate PCI I/O and/or memory space */
-		pciauto_setup_bars(hose, top_bus, current_bus, pci_devfn,
-				   PCI_BASE_ADDRESS_5);
-	}
-	return sub_bus;
-}
-
-int __init pciauto_assign_resources(int busno, struct pci_channel *hose)
-{
-	/* setup resource limits */
-	io_resource_inuse = hose->io_resource;
-	mem_resource_inuse = hose->mem_resource;
-
-	pciauto_lower_iospc = io_resource_inuse->start;
-	pciauto_upper_iospc = io_resource_inuse->end + 1;
-	pciauto_lower_memspc = mem_resource_inuse->start;
-	pciauto_upper_memspc = mem_resource_inuse->end + 1;
-	DBG("Autoconfig PCI channel 0x%p\n", hose);
-	DBG("Scanning bus %.2x, I/O 0x%.8x:0x%.8x, Mem 0x%.8x:0x%.8x\n",
-	    busno, pciauto_lower_iospc, pciauto_upper_iospc,
-	    pciauto_lower_memspc, pciauto_upper_memspc);
-
-	return pciauto_bus_scan(hose, busno, busno);
-}
--- diff/arch/mips/pci/pci-cobalt.c	2003-08-20 14:16:25.000000000 +0100
+++ source/arch/mips/pci/pci-cobalt.c	1970-01-01 01:00:00.000000000 +0100
@@ -1,433 +0,0 @@
-/*
- * Cobalt Qube/Raq PCI support
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (C) 1995, 1996, 1997, 2002 by Ralf Baechle
- * Copyright (C) 2001, 2002, 2003 by Liam Davies (ldavies@agile.tv)
- */
-#include <linux/types.h>
-#include <linux/pci.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
-
-#include <asm/pci.h>
-#include <asm/io.h>
-#include <asm/gt64120.h>
-
-#include <asm/cobalt/cobalt.h>
-
-int cobalt_board_id;
-
-static void qube_expansion_slot_bist(struct pci_dev *dev)
-{
-	unsigned char ctrl;
-	int timeout = 100000;
-
-	pci_read_config_byte(dev, PCI_BIST, &ctrl);
-	if (!(ctrl & PCI_BIST_CAPABLE))
-		return;
-
-	pci_write_config_byte(dev, PCI_BIST, ctrl | PCI_BIST_START);
-	do {
-		pci_read_config_byte(dev, PCI_BIST, &ctrl);
-		if (!(ctrl & PCI_BIST_START))
-			break;
-	} while (--timeout > 0);
-	if ((timeout <= 0) || (ctrl & PCI_BIST_CODE_MASK))
-		printk
-		    ("PCI: Expansion slot card failed BIST with code %x\n",
-		     (ctrl & PCI_BIST_CODE_MASK));
-}
-
-static void qube_expansion_slot_fixup(struct pci_dev *dev)
-{
-	unsigned short pci_cmd;
-	unsigned long ioaddr_base = 0x10108000;	/* It's magic, ask Doug. */
-	unsigned long memaddr_base = 0x12001000;
-	int i;
-
-	/* Enable bits in COMMAND so driver can talk to it. */
-	pci_read_config_word(dev, PCI_COMMAND, &pci_cmd);
-	pci_cmd |=
-	    (PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER);
-	pci_write_config_word(dev, PCI_COMMAND, pci_cmd);
-
-	/* Give it a working IRQ. */
-	pci_write_config_byte(dev, PCI_INTERRUPT_LINE,
-			      COBALT_QUBE_SLOT_IRQ);
-	dev->irq = COBALT_QUBE_SLOT_IRQ;
-
-	ioaddr_base += 0x2000 * PCI_FUNC(dev->devfn);
-	memaddr_base += 0x2000 * PCI_FUNC(dev->devfn);
-
-	/* Fixup base addresses, we only support I/O at the moment. */
-	for (i = 0; i <= 5; i++) {
-		unsigned int regaddr = (PCI_BASE_ADDRESS_0 + (i * 4));
-		unsigned int rval, mask, size, alignme, aspace;
-		unsigned long *basep = &ioaddr_base;
-
-		/* Check type first, punt if non-IO. */
-		pci_read_config_dword(dev, regaddr, &rval);
-		aspace = (rval & PCI_BASE_ADDRESS_SPACE);
-		if (aspace != PCI_BASE_ADDRESS_SPACE_IO)
-			basep = &memaddr_base;
-
-		/* Figure out how much it wants, if anything. */
-		pci_write_config_dword(dev, regaddr, 0xffffffff);
-		pci_read_config_dword(dev, regaddr, &rval);
-
-		/* Unused? */
-		if (rval == 0)
-			continue;
-
-		rval &= PCI_BASE_ADDRESS_IO_MASK;
-		mask = (~rval << 1) | 0x1;
-		size = (mask & rval) & 0xffffffff;
-		alignme = size;
-		if (alignme < 0x400)
-			alignme = 0x400;
-		rval = ((*basep + (alignme - 1)) & ~(alignme - 1));
-		*basep = (rval + size);
-		pci_write_config_dword(dev, regaddr, rval | aspace);
-		dev->resource[i].start = rval;
-		dev->resource[i].end = *basep - 1;
-		if (aspace == PCI_BASE_ADDRESS_SPACE_IO) {
-			dev->resource[i].start -= 0x10000000;
-			dev->resource[i].end -= 0x10000000;
-		}
-	}
-	qube_expansion_slot_bist(dev);
-}
-
-static void qube_raq_via_bmIDE_fixup(struct pci_dev *dev)
-{
-	unsigned short cfgword;
-	unsigned char lt;
-
-	/* Enable Bus Mastering and fast back to back. */
-	pci_read_config_word(dev, PCI_COMMAND, &cfgword);
-	cfgword |= (PCI_COMMAND_FAST_BACK | PCI_COMMAND_MASTER);
-	pci_write_config_word(dev, PCI_COMMAND, cfgword);
-
-	/* Enable both ide interfaces. ROM only enables primary one.  */
-	pci_write_config_byte(dev, 0x40, 0xb);
-
-	/* Set latency timer to reasonable value. */
-	pci_read_config_byte(dev, PCI_LATENCY_TIMER, &lt);
-	if (lt < 64)
-		pci_write_config_byte(dev, PCI_LATENCY_TIMER, 64);
-	pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, 7);
-}
-
-static void qube_raq_tulip_fixup(struct pci_dev *dev)
-{
-	unsigned short pci_cmd;
-
-	/* Fixup the first tulip located at device PCICONF_ETH0 */
-	if (PCI_SLOT(dev->devfn) == COBALT_PCICONF_ETH0) {
-		/* Setup the first Tulip */
-		pci_write_config_byte(dev, PCI_INTERRUPT_LINE,
-				      COBALT_ETH0_IRQ);
-		dev->irq = COBALT_ETH0_IRQ;
-
-		dev->resource[0].start = 0x100000;
-		dev->resource[0].end = 0x10007f;
-
-		dev->resource[1].start = 0x12000000;
-		dev->resource[1].end = dev->resource[1].start + 0x3ff;
-		pci_write_config_dword(dev, PCI_BASE_ADDRESS_1,
-				       dev->resource[1].start);
-
-		/* Fixup the second tulip located at device PCICONF_ETH1 */
-	} else if (PCI_SLOT(dev->devfn) == COBALT_PCICONF_ETH1) {
-
-		/* Enable the second Tulip device. */
-		pci_read_config_word(dev, PCI_COMMAND, &pci_cmd);
-		pci_cmd |= (PCI_COMMAND_IO | PCI_COMMAND_MASTER);
-		pci_write_config_word(dev, PCI_COMMAND, pci_cmd);
-
-		/* Give it it's IRQ. */
-		pci_write_config_byte(dev, PCI_INTERRUPT_LINE,
-				      COBALT_ETH1_IRQ);
-		dev->irq = COBALT_ETH1_IRQ;
-
-		/* And finally, a usable I/O space allocation, right after what
-		 * the first Tulip uses.
-		 */
-		dev->resource[0].start = 0x101000;
-		dev->resource[0].end = 0x10107f;
-
-		dev->resource[1].start = 0x12000400;
-		dev->resource[1].end = dev->resource[1].start + 0x3ff;
-		pci_write_config_dword(dev, PCI_BASE_ADDRESS_1,
-				       dev->resource[1].start);
-	}
-}
-
-static void qube_raq_scsi_fixup(struct pci_dev *dev)
-{
-	unsigned short pci_cmd;
-
-	/*
-	 * Tell the SCSI device that we expect an interrupt at
-	 * IRQ 7 and not the default 0.
-	 */
-	pci_write_config_byte(dev, PCI_INTERRUPT_LINE, COBALT_SCSI_IRQ);
-	dev->irq = COBALT_SCSI_IRQ;
-
-	if (cobalt_board_id == COBALT_BRD_ID_RAQ2) {
-
-		/* Enable the device. */
-		pci_read_config_word(dev, PCI_COMMAND, &pci_cmd);
-
-		pci_cmd |=
-		    (PCI_COMMAND_IO | PCI_COMMAND_MASTER |
-		     PCI_COMMAND_MEMORY | PCI_COMMAND_INVALIDATE);
-		pci_write_config_word(dev, PCI_COMMAND, pci_cmd);
-
-		/* Give it it's RAQ IRQ. */
-		pci_write_config_byte(dev, PCI_INTERRUPT_LINE,
-				      COBALT_RAQ_SCSI_IRQ);
-		dev->irq = COBALT_RAQ_SCSI_IRQ;
-
-		/* And finally, a usable I/O space allocation, right after what
-		 * the second Tulip uses.
-		 */
-		dev->resource[0].start = 0x102000;
-		dev->resource[0].end = dev->resource[0].start + 0xff;
-		pci_write_config_dword(dev, PCI_BASE_ADDRESS_0,
-				       0x10102000);
-
-		pci_write_config_dword(dev, PCI_BASE_ADDRESS_1,
-				       0x00002000);
-		pci_write_config_dword(dev, PCI_BASE_ADDRESS_2,
-				       0x00100000);
-	}
-}
-
-static void qube_raq_galileo_fixup(struct pci_dev *dev)
-{
-	unsigned short galileo_id;
-
-	/* Fix PCI latency-timer and cache-line-size values in Galileo
-	 * host bridge.
-	 */
-	pci_write_config_byte(dev, PCI_LATENCY_TIMER, 64);
-	pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, 7);
-
-	/* On all machines prior to Q2, we had the STOP line disconnected
-	 * from Galileo to VIA on PCI.  The new Galileo does not function
-	 * correctly unless we have it connected.
-	 *
-	 * Therefore we must set the disconnect/retry cycle values to
-	 * something sensible when using the new Galileo.
-	 */
-	pci_read_config_word(dev, PCI_REVISION_ID, &galileo_id);
-	galileo_id &= 0xff;	/* mask off class info */
-	if (galileo_id >= 0x10) {
-		/* New Galileo, assumes PCI stop line to VIA is connected. */
-		GALILEO_OUTL(0x4020, GT_PCI0_TOR_OFS);
-	} else if (galileo_id == 0x1 || galileo_id == 0x2) {
-		signed int timeo;
-		/* XXX WE MUST DO THIS ELSE GALILEO LOCKS UP! -DaveM */
-		timeo = GALILEO_INL(GT_PCI0_TOR_OFS);
-		/* Old Galileo, assumes PCI STOP line to VIA is disconnected. */
-		GALILEO_OUTL(0xffff, GT_PCI0_TOR_OFS);
-	}
-}
-
-static void qube_pcibios_fixup(struct pci_dev *dev)
-{
-	if (PCI_SLOT(dev->devfn) == COBALT_PCICONF_PCISLOT) {
-		unsigned int tmp;
-
-		/* See if there is a device in the expansion slot, if so
-		 * discover its resources and fixup whatever we need to
-		 */
-		pci_read_config_dword(dev, PCI_VENDOR_ID, &tmp);
-		if (tmp != 0xffffffff && tmp != 0x00000000)
-			qube_expansion_slot_fixup(dev);
-	}
-}
-
-struct pci_fixup pcibios_fixups[] = {
-	{PCI_FIXUP_HEADER, PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_1,
-	 qube_raq_via_bmIDE_fixup},
-	{PCI_FIXUP_HEADER, PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_21142,
-	 qube_raq_tulip_fixup},
-	{PCI_FIXUP_HEADER, PCI_VENDOR_ID_GALILEO, PCI_ANY_ID,
-	 qube_raq_galileo_fixup},
-	{PCI_FIXUP_HEADER, PCI_VENDOR_ID_NCR, PCI_DEVICE_ID_NCR_53C860,
-	 qube_raq_scsi_fixup},
-	{PCI_FIXUP_HEADER, PCI_ANY_ID, PCI_ANY_ID, qube_pcibios_fixup}
-};
-
-
-static inline int pci_range_ck(struct pci_bus *bus, unsigned int devfn)
-{
-	if ((bus->number == 0)
-	    && ((PCI_SLOT(devfn) == 0)
-		|| ((PCI_SLOT(devfn) > 6)
-		    && (PCI_SLOT(devfn) <= 12))))
-		return 0;	/* OK device number  */
-
-	return -1;		/* NOT ok device number */
-}
-
-#define PCI_CFG_SET(devfn,where) \
-       GALILEO_OUTL((0x80000000 | (PCI_SLOT (devfn) << 11) | \
-                           (PCI_FUNC (devfn) << 8) | (where)), \
-                           GT_PCI0_CFGADDR_OFS)
-
-
-static int qube_pci_read_config(struct pci_bus *bus, unsigned int devfn,
-				int where, int size, u32 * val)
-{
-	switch (size) {
-	case 4:
-		if (where & 0x3)
-			return PCIBIOS_BAD_REGISTER_NUMBER;
-		if (pci_range_ck(bus, devfn)) {
-			*val = 0xFFFFFFFF;
-			return PCIBIOS_DEVICE_NOT_FOUND;
-		}
-		PCI_CFG_SET(devfn, where);
-		*val = GALILEO_INL(GT_PCI0_CFGDATA_OFS);
-		return PCIBIOS_SUCCESSFUL;
-
-	case 2:
-		if (where & 0x1)
-			return PCIBIOS_BAD_REGISTER_NUMBER;
-		if (pci_range_ck(bus, devfn)) {
-			*val = 0xffff;
-			return PCIBIOS_DEVICE_NOT_FOUND;
-		}
-		PCI_CFG_SET(devfn, (where & ~0x3));
-		*val = GALILEO_INL(GT_PCI0_CFGDATA_OFS)
-		    >> ((where & 3) * 8);
-		return PCIBIOS_SUCCESSFUL;
-
-	case 1:
-		if (pci_range_ck(bus, devfn)) {
-			*val = 0xff;
-			return PCIBIOS_DEVICE_NOT_FOUND;
-		}
-		PCI_CFG_SET(devfn, (where & ~0x3));
-		*val = GALILEO_INL(GT_PCI0_CFGDATA_OFS)
-		    >> ((where & 3) * 8);
-		return PCIBIOS_SUCCESSFUL;
-	}
-}
-
-static int qube_pci_write_config(struct pci_bus *bus, unsigned int devfn,
-				 int where, int size, u32 val)
-{
-	u32 tmp;
-
-	switch (size) {
-	case 4:
-		if (where & 0x3)
-			return PCIBIOS_BAD_REGISTER_NUMBER;
-		if (pci_range_ck(bus, devfn))
-			return PCIBIOS_DEVICE_NOT_FOUND;
-		PCI_CFG_SET(devfn, where);
-		GALILEO_OUTL(val, GT_PCI0_CFGDATA_OFS);
-
-		return PCIBIOS_SUCCESSFUL;
-
-	case 2:
-		if (where & 0x1)
-			return PCIBIOS_BAD_REGISTER_NUMBER;
-		if (pci_range_ck(bus, devfn))
-			return PCIBIOS_DEVICE_NOT_FOUND;
-		PCI_CFG_SET(devfn, (where & ~0x3));
-		tmp = GALILEO_INL(GT_PCI0_CFGDATA_OFS);
-		tmp &= ~(0xffff << ((where & 0x3) * 8));
-		tmp |= (val << ((where & 0x3) * 8));
-		GALILEO_OUTL(tmp, GT_PCI0_CFGDATA_OFS);
-
-		return PCIBIOS_SUCCESSFUL;
-
-	case 1:
-
-		if (pci_range_ck(bus, devfn))
-			return PCIBIOS_DEVICE_NOT_FOUND;
-		PCI_CFG_SET(devfn, (where & ~0x3));
-		tmp = GALILEO_INL(GT_PCI0_CFGDATA_OFS);
-		tmp &= ~(0xff << ((where & 0x3) * 8));
-		tmp |= (val << ((where & 0x3) * 8));
-		GALILEO_OUTL(tmp, GT_PCI0_CFGDATA_OFS);
-
-		return PCIBIOS_SUCCESSFUL;
-	}
-}
-
-struct pci_ops qube_pci_ops = {
-	.read = qube_pci_read_config,
-	.write = qube_pci_write_config,
-};
-
-static int __init pcibios_init(void)
-{
-	unsigned int devfn = PCI_DEVFN(COBALT_PCICONF_VIA, 0);
-
-	printk("PCI: Probing PCI hardware\n");
-
-	/* Read the cobalt id register out of the PCI config space */
-	PCI_CFG_SET(devfn, (VIA_COBALT_BRD_ID_REG & ~0x3));
-	cobalt_board_id = GALILEO_INL(GT_PCI0_CFGDATA_OFS)
-	    >> ((VIA_COBALT_BRD_ID_REG & 3) * 8);
-	cobalt_board_id = VIA_COBALT_BRD_REG_to_ID(cobalt_board_id);
-
-	printk("Cobalt Board ID: %d\n", cobalt_board_id);
-
-	ioport_resource.start = 0x00000000;
-	ioport_resource.end = 0x0fffffff;
-
-	iomem_resource.start = 0x01000000;
-	iomem_resource.end = 0xffffffff;
-
-	pci_scan_bus(0, &qube_pci_ops, NULL);
-
-	return 0;
-}
-
-subsys_initcall(pcibios_init);
-
-char *pcibios_setup(char *str)
-{
-	return str;
-}
-
-int pcibios_enable_device(struct pci_dev *dev, int mask)
-{
-	u16 cmd, status;
-
-	pci_read_config_word(dev, PCI_COMMAND, &cmd);
-	pci_read_config_word(dev, PCI_STATUS, &status);
-	printk("PCI: Enabling device %s (%04x  %04x)\n", pci_name(dev),
-	       cmd, status);
-	/* We'll sort this out when we know it isn't enabled ;) */
-
-	return 0;
-}
-
-void pcibios_align_resource(void *data, struct resource *res,
-			    unsigned long size, unsigned long align)
-{
-
-	panic("Uhhoh called pcibios_align_resource\n");
-}
-
-void __devinit pcibios_fixup_bus(struct pci_bus *bus)
-{
-	/* We don't have sub-busses to fixup here */
-}
-
-unsigned int __init pcibios_assign_all_busses(void)
-{
-	return 1;
-}
--- diff/arch/mips/pci/pci-lasat.c	2003-08-20 14:16:25.000000000 +0100
+++ source/arch/mips/pci/pci-lasat.c	1970-01-01 01:00:00.000000000 +0100
@@ -1,242 +0,0 @@
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/pci.h>
-#include <asm/bootinfo.h>
-
-#include <asm/lasat/lasat.h>
-#include <asm/gt64120.h>
-#include <asm/nile4.h>
-
-#define PCI_ACCESS_READ  0
-#define PCI_ACCESS_WRITE 1
-
-#undef DEBUG_PCI
-#ifdef DEBUG_PCI
-#define Dprintk(fmt...) printk(fmt)
-#else
-#define Dprintk(fmt...)
-#endif
-
-static int (*lasat_pcibios_config_access) (unsigned char access_type,
-					   struct pci_bus * bus,
-					   unsigned int devfn, int where,
-					   u32 * val);
-
-/*
- * Because of an error/peculiarity in the Galileo chip, we need to swap the 
- * bytes when running bigendian.
- */
-#define GT_WRITE(ofs, data)  \
-             *(volatile u32 *)(LASAT_GT_BASE+ofs) = cpu_to_le32(data)
-#define GT_READ(ofs, data)   \
-             data = le32_to_cpu(*(volatile u32 *)(LASAT_GT_BASE+ofs))
-
-
-static int lasat_pcibios_config_access_100(unsigned char access_type,
-					   struct pci_bus *bus,
-					   unsigned int devfn, int where,
-					   u32 * val)
-{
-	unsigned char busnum = bus->number;
-	u32 intr;
-
-	if ((busnum == 0) && (devfn >= PCI_DEVFN(31, 0)))
-		return -1;	/* Because of a bug in the Galileo (for slot 31). */
-
-	/* Clear cause register bits */
-	GT_WRITE(GT_INTRCAUSE_OFS, ~(GT_INTRCAUSE_MASABORT0_BIT |
-				     GT_INTRCAUSE_TARABORT0_BIT));
-
-	/* Setup address */
-	GT_WRITE(GT_PCI0_CFGADDR_OFS,
-		 (busnum << GT_PCI0_CFGADDR_BUSNUM_SHF) |
-		 (devfn << GT_PCI0_CFGADDR_FUNCTNUM_SHF) |
-		 ((where / 4) << GT_PCI0_CFGADDR_REGNUM_SHF) |
-		 GT_PCI0_CFGADDR_CONFIGEN_BIT);
-
-	if (access_type == PCI_ACCESS_WRITE) {
-		GT_WRITE(GT_PCI0_CFGDATA_OFS, *val);
-	} else {
-		GT_READ(GT_PCI0_CFGDATA_OFS, *val);
-	}
-
-	/* Check for master or target abort */
-	GT_READ(GT_INTRCAUSE_OFS, intr);
-
-	if (intr &
-	    (GT_INTRCAUSE_MASABORT0_BIT | GT_INTRCAUSE_TARABORT0_BIT)) {
-		/* Error occurred */
-
-		/* Clear bits */
-		GT_WRITE(GT_INTRCAUSE_OFS, ~(GT_INTRCAUSE_MASABORT0_BIT |
-					     GT_INTRCAUSE_TARABORT0_BIT));
-
-		return -1;
-	}
-
-	return 0;
-}
-
-#define LO(reg) (reg / 4)
-#define HI(reg) (reg / 4 + 1)
-
-volatile unsigned long *const vrc_pciregs = (void *) Vrc5074_BASE;
-
-static int lasat_pcibios_config_access_200(unsigned char access_type,
-					   struct pci_bus *bus,
-					   unsigned int devfn, int where,
-					   u32 * val)
-{
-	unsigned char busnum = bus->number;
-	u32 adr, mask, err;
-
-	if ((busnum == 0) && (PCI_SLOT(devfn) > 8))
-		/* The addressing scheme chosen leaves room for just
-		 * 8 devices on the first busnum (besides the PCI
-		 * controller itself) */
-		return -1;
-
-	if ((busnum == 0) && (devfn == PCI_DEVFN(0, 0))) {
-		/* Access controller registers directly */
-		if (access_type == PCI_ACCESS_WRITE) {
-			vrc_pciregs[(0x200 + where) >> 2] = *val;
-		} else {
-			*val = vrc_pciregs[(0x200 + where) >> 2];
-		}
-		return 0;
-	}
-
-	/* Temporarily map PCI Window 1 to config space */
-	mask = vrc_pciregs[LO(NILE4_PCIINIT1)];
-	vrc_pciregs[LO(NILE4_PCIINIT1)] =
-	    0x0000001a | (busnum ? 0x200 : 0);
-
-	/* Clear PCI Error register. This also clears the Error Type
-	 * bits in the Control register */
-	vrc_pciregs[LO(NILE4_PCIERR)] = 0;
-	vrc_pciregs[HI(NILE4_PCIERR)] = 0;
-
-	/* Setup address */
-	if (busnum == 0)
-		adr =
-		    KSEG1ADDR(PCI_WINDOW1) +
-		    ((1 << (PCI_SLOT(devfn) + 15)) | (PCI_FUNC(devfn) << 8)
-		     | (where & ~3));
-	else
-		adr =
-		    KSEG1ADDR(PCI_WINDOW1) | (busnum << 16) | (devfn << 8)
-		    | (where & ~3);
-
-#ifdef DEBUG_PCI
-	printk("PCI config %s: adr %x",
-	       access_type == PCI_ACCESS_WRITE ? "write" : "read", adr);
-#endif
-
-	if (access_type == PCI_ACCESS_WRITE) {
-		*(u32 *) adr = *val;
-	} else {
-		*val = *(u32 *) adr;
-	}
-
-#ifdef DEBUG_PCI
-	printk(" value = %x\n", *val);
-#endif
-
-	/* Check for master or target abort */
-	err = (vrc_pciregs[HI(NILE4_PCICTRL)] >> 5) & 0x7;
-
-	/* Restore PCI Window 1 */
-	vrc_pciregs[LO(NILE4_PCIINIT1)] = mask;
-
-	if (err) {
-		/* Error occured */
-#ifdef DEBUG_PCI
-		printk("\terror %x at adr %x\n", err,
-		       vrc_pciregs[LO(NILE4_PCIERR)]);
-#endif
-		return -1;
-	}
-
-	return 0;
-}
-
-static int lasat_pcibios_read(struct pci_bus *bus, unsigned int devfn,
-			      int where, int size, u32 * val)
-{
-	u32 data = 0;
-
-	if ((size == 2) && (where & 1))
-		return PCIBIOS_BAD_REGISTER_NUMBER;
-	else if ((size == 4) && (where & 3))
-		return PCIBIOS_BAD_REGISTER_NUMBER;
-
-	if (lasat_pcibios_config_access(PCI_ACCESS_READ, bus, devfn, where,
-					&data))
-		return -1;
-
-	if (size == 1)
-		*val = (data >> ((where & 3) << 3)) & 0xff;
-	else if (size == 2)
-		*val = (data >> ((where & 3) << 3)) & 0xffff;
-	else
-		*val = data;
-
-	return PCIBIOS_SUCCESSFUL;
-}
-
-static int lasat_pcibios_write(struct pci_bus *bus, unsigned int devfn,
-			       int where, int size, u32 val)
-{
-	u32 data = 0;
-
-	if ((size == 2) && (where & 1))
-		return PCIBIOS_BAD_REGISTER_NUMBER;
-	else if ((size == 4) && (where & 3))
-		return PCIBIOS_BAD_REGISTER_NUMBER;
-
-	if (lasat_pcibios_config_access(PCI_ACCESS_READ, bus, devfn, where,
-					&data))
-		return -1;
-
-	if (size == 1)
-		data = (data & ~(0xff << ((where & 3) << 3))) |
-		    (val << ((where & 3) << 3));
-	else if (size == 2)
-		data = (data & ~(0xffff << ((where & 3) << 3))) |
-		    (val << ((where & 3) << 3));
-	else
-		data = val;
-
-	if (lasat_pcibios_config_access
-	    (PCI_ACCESS_WRITE, bus, devfn, where, &data))
-		return -1;
-
-	return PCIBIOS_SUCCESSFUL;
-}
-
-struct pci_ops lasat_pci_ops = {
-	.read = lasat_pcibios_read,
-	.write = lasat_pcibios_write,
-};
-
-static int __init pcibios_init(void)
-{
-	switch (mips_machtype) {
-	case MACH_LASAT_100:
-		lasat_pcibios_config_access =
-		    &lasat_pcibios_config_access_100;
-		break;
-	case MACH_LASAT_200:
-		lasat_pcibios_config_access =
-		    &lasat_pcibios_config_access_200;
-		break;
-	default:
-		panic("pcibios_init: mips_machtype incorrect");
-	}
-
-	Dprintk("pcibios_init()\n");
-	pci_scan_bus(0, &lasat_pci_ops, NULL);
-	return 0;
-}
-
-subsys_initcall(pcibios_init);
--- diff/arch/mips/pci/pci-mips.c	2003-08-20 14:16:25.000000000 +0100
+++ source/arch/mips/pci/pci-mips.c	1970-01-01 01:00:00.000000000 +0100
@@ -1,483 +0,0 @@
-/*
- * Carsten Langgaard, carstenl@mips.com
- * Copyright (C) 1999, 2000 MIPS Technologies, Inc.  All rights reserved.
- *
- *  This program is free software; you can distribute it and/or modify it
- *  under the terms of the GNU General Public License (Version 2) as
- *  published by the Free Software Foundation.
- *
- *  This program is distributed in the hope it will be useful, but WITHOUT
- *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- *  for more details.
- *
- *  You should have received a copy of the GNU General Public License along
- *  with this program; if not, write to the Free Software Foundation, Inc.,
- *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
- *
- * MIPS boards specific PCI support.
- *
- */
-#include <linux/config.h>
-#include <linux/types.h>
-#include <linux/pci.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
-
-#include <asm/mips-boards/generic.h>
-#include <asm/gt64120.h>
-#include <asm/mips-boards/bonito64.h>
-#ifdef CONFIG_MIPS_MALTA
-#include <asm/mips-boards/malta.h>
-#endif
-#include <asm/mips-boards/msc01_pci.h>
-
-#define PCI_ACCESS_READ  0
-#define PCI_ACCESS_WRITE 1
-
-/*
- *  PCI configuration cycle AD bus definition
- */
-/* Type 0 */
-#define PCI_CFG_TYPE0_REG_SHF           0
-#define PCI_CFG_TYPE0_FUNC_SHF          8
-
-/* Type 1 */
-#define PCI_CFG_TYPE1_REG_SHF           0
-#define PCI_CFG_TYPE1_FUNC_SHF          8
-#define PCI_CFG_TYPE1_DEV_SHF           11
-#define PCI_CFG_TYPE1_BUS_SHF           16
-
-static int mips_pcibios_config_access(unsigned char access_type,
-				      struct pci_bus *bus,
-				      unsigned int devfn, int where,
-				      u32 * data)
-{
-	unsigned char busnum = bus->number;
-	unsigned char type;
-	u32 intr, dummy;
-	u64 pci_addr;
-
-	switch (mips_revision_corid) {
-	case MIPS_REVISION_CORID_QED_RM5261:
-	case MIPS_REVISION_CORID_CORE_LV:
-	case MIPS_REVISION_CORID_CORE_FPGA:
-		/* Galileo GT64120 system controller. */
-
-		if ((busnum == 0) && (devfn >= PCI_DEVFN(31, 0)))
-			return -1;	/* Because of a bug in the galileo (for slot 31). */
-
-		/* Clear cause register bits */
-		GT_READ(GT_INTRCAUSE_OFS, intr);
-		GT_WRITE(GT_INTRCAUSE_OFS, intr &
-			 ~(GT_INTRCAUSE_MASABORT0_BIT |
-			   GT_INTRCAUSE_TARABORT0_BIT));
-
-		/* Setup address */
-		GT_WRITE(GT_PCI0_CFGADDR_OFS,
-			 (busnum << GT_PCI0_CFGADDR_BUSNUM_SHF) |
-			 (devfn << GT_PCI0_CFGADDR_FUNCTNUM_SHF) |
-			 ((where / 4) << GT_PCI0_CFGADDR_REGNUM_SHF) |
-			 GT_PCI0_CFGADDR_CONFIGEN_BIT);
-
-		if (access_type == PCI_ACCESS_WRITE) {
-			if (busnum == 0 && devfn == 0) {
-				/*
-				 * The Galileo system controller is acting
-				 * differently than other devices.
-				 */
-				GT_WRITE(GT_PCI0_CFGDATA_OFS, *data);
-			} else {
-				GT_PCI_WRITE(GT_PCI0_CFGDATA_OFS, *data);
-			}
-		} else {
-			if (busnum == 0 && devfn == 0) {
-				/*
-				 * The Galileo system controller is acting
-				 * differently than other devices.
-				 */
-				GT_READ(GT_PCI0_CFGDATA_OFS, *data);
-			} else {
-				GT_PCI_READ(GT_PCI0_CFGDATA_OFS, *data);
-			}
-		}
-
-		/* Check for master or target abort */
-		GT_READ(GT_INTRCAUSE_OFS, intr);
-
-		if (intr & (GT_INTRCAUSE_MASABORT0_BIT |
-			    GT_INTRCAUSE_TARABORT0_BIT)) {
-			/* Error occurred */
-
-			/* Clear bits */
-			GT_READ(GT_INTRCAUSE_OFS, intr);
-			GT_WRITE(GT_INTRCAUSE_OFS, intr &
-				 ~(GT_INTRCAUSE_MASABORT0_BIT |
-				   GT_INTRCAUSE_TARABORT0_BIT));
-
-			return -1;
-		}
-
-		break;
-
-	case MIPS_REVISION_CORID_BONITO64:
-	case MIPS_REVISION_CORID_CORE_20K:
-		/* Algorithmics Bonito64 system controller. */
-
-		if ((busnum == 0) && (PCI_SLOT(devfn) == 0)) {
-			return -1;
-		}
-
-		/* Clear cause register bits */
-		BONITO_PCICMD |= (BONITO_PCICMD_MABORT_CLR |
-				  BONITO_PCICMD_MTABORT_CLR);
-
-		/*
-		 * Setup pattern to be used as PCI "address" for
-		 * Type 0 cycle
-		 */
-		if (busnum == 0) {
-			/* IDSEL */
-			pci_addr = (u64) 1 << (PCI_SLOT(devfn) + 10);
-		} else {
-			/* Bus number */
-			pci_addr = busnum << PCI_CFG_TYPE1_BUS_SHF;
-
-			/* Device number */
-			pci_addr |=
-			    PCI_SLOT(devfn) << PCI_CFG_TYPE1_DEV_SHF;
-		}
-
-		/* Function (same for Type 0/1) */
-		pci_addr |= PCI_FUNC(devfn) << PCI_CFG_TYPE0_FUNC_SHF;
-
-		/* Register number (same for Type 0/1) */
-		pci_addr |= (where & ~0x3) << PCI_CFG_TYPE0_REG_SHF;
-
-		if (busnum == 0) {
-			/* Type 0 */
-			BONITO_PCIMAP_CFG = pci_addr >> 16;
-		} else {
-			/* Type 1 */
-			BONITO_PCIMAP_CFG = (pci_addr >> 16) | 0x10000;
-		}
-
-		/* Flush Bonito register block */
-		dummy = BONITO_PCIMAP_CFG;
-		iob();		/* sync */
-
-		/* Perform access */
-		if (access_type == PCI_ACCESS_WRITE) {
-			*(volatile u32 *) (KSEG1ADDR(BONITO_PCICFG_BASE +
-						     (pci_addr & 0xffff)))
-			    = *(u32 *) data;
-
-			/* Wait till done */
-			while (BONITO_PCIMSTAT & 0xF);
-		} else {
-			*(u32 *) data =
-			    *(volatile u32
-			      *) (KSEG1ADDR(BONITO_PCICFG_BASE +
-					    (pci_addr & 0xffff)));
-		}
-
-		/* Detect Master/Target abort */
-		if (BONITO_PCICMD & (BONITO_PCICMD_MABORT_CLR |
-				     BONITO_PCICMD_MTABORT_CLR)) {
-			/* Error occurred */
-
-			/* Clear bits */
-			BONITO_PCICMD |= (BONITO_PCICMD_MABORT_CLR |
-					  BONITO_PCICMD_MTABORT_CLR);
-
-			return -1;
-		}
-		break;
-
-	case MIPS_REVISION_CORID_CORE_MSC:
-		/* MIPS system controller. */
-
-		if ((busnum == 0) && (PCI_SLOT(devfn) == 0)) {
-			return -1;
-		}
-
-		/* Clear status register bits. */
-		MSC_WRITE(MSC01_PCI_INTSTAT,
-			  (MSC01_PCI_INTCFG_MA_BIT |
-			   MSC01_PCI_INTCFG_TA_BIT));
-
-		/* Setup address */
-		if (busnum == 0)
-			type = 0;	/* Type 0 */
-		else
-			type = 1;	/* Type 1 */
-
-		MSC_WRITE(MSC01_PCI_CFGADDR,
-			  ((busnum << MSC01_PCI_CFGADDR_BNUM_SHF) |
-			   (PCI_SLOT(devfn) << MSC01_PCI_CFGADDR_DNUM_SHF)
-			   | (PCI_FUNC(devfn) <<
-			      MSC01_PCI_CFGADDR_FNUM_SHF) | ((where /
-							      4) <<
-							     MSC01_PCI_CFGADDR_RNUM_SHF)
-			   | (type)));
-
-		/* Perform access */
-		if (access_type == PCI_ACCESS_WRITE) {
-			MSC_WRITE(MSC01_PCI_CFGDATA, *data);
-		} else {
-			MSC_READ(MSC01_PCI_CFGDATA, *data);
-		}
-
-		/* Detect Master/Target abort */
-		MSC_READ(MSC01_PCI_INTSTAT, intr);
-		if (intr & (MSC01_PCI_INTCFG_MA_BIT |
-			    MSC01_PCI_INTCFG_TA_BIT)) {
-			/* Error occurred */
-
-			/* Clear bits */
-			MSC_READ(MSC01_PCI_INTSTAT, intr);
-			MSC_WRITE(MSC01_PCI_INTSTAT,
-				  (MSC01_PCI_INTCFG_MA_BIT |
-				   MSC01_PCI_INTCFG_TA_BIT));
-
-			return -1;
-		}
-		break;
-	default:
-		printk
-		    ("Unknown Core card, don't know the system controller.\n");
-		return -1;
-	}
-
-	return 0;
-}
-
-
-/*
- * We can't address 8 and 16 bit words directly.  Instead we have to
- * read/write a 32bit word and mask/modify the data we actually want.
- */
-static int mips_pcibios_read(struct pci_bus *bus, unsigned int devfn,
-			     int where, int size, u32 * val)
-{
-	u32 data = 0;
-
-	if ((size == 2) && (where & 1))
-		return PCIBIOS_BAD_REGISTER_NUMBER;
-	else if ((size == 4) && (where & 3))
-		return PCIBIOS_BAD_REGISTER_NUMBER;
-
-	if (mips_pcibios_config_access(PCI_ACCESS_READ, bus, devfn, where,
-				       &data))
-		return -1;
-
-	if (size == 1)
-		*val = (data >> ((where & 3) << 3)) & 0xff;
-	else if (size == 2)
-		*val = (data >> ((where & 3) << 3)) & 0xffff;
-	else
-		*val = data;
-
-	return PCIBIOS_SUCCESSFUL;
-}
-
-static int mips_pcibios_write(struct pci_bus *bus, unsigned int devfn,
-			      int where, int size, u32 val)
-{
-	u32 data = 0;
-
-	if ((size == 2) && (where & 1))
-		return PCIBIOS_BAD_REGISTER_NUMBER;
-	else if ((size == 4) && (where & 3))
-		return PCIBIOS_BAD_REGISTER_NUMBER;
-
-	if (size == 4)
-		data = val;
-	else {
-		if (mips_pcibios_config_access(PCI_ACCESS_READ, bus, devfn,
-		                               where, &data))
-			return -1;
-
-		if (size == 1)
-			data = (data & ~(0xff << ((where & 3) << 3))) |
-				(val << ((where & 3) << 3));
-		else if (size == 2)
-			data = (data & ~(0xffff << ((where & 3) << 3))) |
-				(val << ((where & 3) << 3));
-	}
-
-	if (mips_pcibios_config_access(PCI_ACCESS_WRITE, bus, devfn, where,
-				       &data))
-		return -1;
-
-	return PCIBIOS_SUCCESSFUL;
-}
-
-struct pci_ops mips_pci_ops = {
-	.read = mips_pcibios_read,
-	.write = mips_pcibios_write
-};
-
-int mips_pcibios_iack(void)
-{
-	int irq;
-	u32 dummy;
-
-	/*
-	 * Determine highest priority pending interrupt by performing
-	 * a PCI Interrupt Acknowledge cycle.
-	 */
-	switch (mips_revision_corid) {
-	case MIPS_REVISION_CORID_QED_RM5261:
-	case MIPS_REVISION_CORID_CORE_LV:
-	case MIPS_REVISION_CORID_CORE_FPGA:
-	case MIPS_REVISION_CORID_CORE_MSC:
-		if (mips_revision_corid == MIPS_REVISION_CORID_CORE_MSC)
-			MSC_READ(MSC01_PCI_IACK, irq);
-		else
-			GT_READ(GT_PCI0_IACK_OFS, irq);
-		irq &= 0xff;
-		break;
-	case MIPS_REVISION_CORID_BONITO64:
-	case MIPS_REVISION_CORID_CORE_20K:
-		/* The following will generate a PCI IACK cycle on the
-		 * Bonito controller. It's a little bit kludgy, but it
-		 * was the easiest way to implement it in hardware at
-		 * the given time.
-		 */
-		BONITO_PCIMAP_CFG = 0x20000;
-
-		/* Flush Bonito register block */
-		dummy = BONITO_PCIMAP_CFG;
-		iob();		/* sync */
-
-		irq = *(volatile u32 *) (KSEG1ADDR(BONITO_PCICFG_BASE));
-		iob();		/* sync */
-		irq &= 0xff;
-		BONITO_PCIMAP_CFG = 0;
-		break;
-	default:
-		printk
-		    ("Unknown Core card, don't know the system controller.\n");
-		return -1;
-	}
-	return irq;
-}
-
-static int __init pcibios_init(void)
-{
-#ifdef CONFIG_MIPS_MALTA
-	struct pci_dev *pdev = NULL;
-	unsigned char reg_val;
-#endif
-
-	printk("PCI: Probing PCI hardware on host bus 0.\n");
-	pci_scan_bus(0, &mips_pci_ops, NULL);
-
-	switch (mips_revision_corid) {
-	case MIPS_REVISION_CORID_QED_RM5261:
-	case MIPS_REVISION_CORID_CORE_LV:
-	case MIPS_REVISION_CORID_CORE_FPGA:
-		/*
-		 * Due to a bug in the Galileo system controller, we need
-		 * to setup the PCI BAR for the Galileo internal registers.
-		 * This should be done in the bios/bootprom and will be
-		 * fixed in a later revision of YAMON (the MIPS boards
-		 * boot prom).
-		 */
-		GT_WRITE(GT_PCI0_CFGADDR_OFS, (0 << GT_PCI0_CFGADDR_BUSNUM_SHF) |	/* Local bus */
-			 (0 << GT_PCI0_CFGADDR_DEVNUM_SHF) |	/* GT64120 dev */
-			 (0 << GT_PCI0_CFGADDR_FUNCTNUM_SHF) |	/* Function 0 */
-			 ((0x20 / 4) << GT_PCI0_CFGADDR_REGNUM_SHF) |	/* BAR 4 */
-			 GT_PCI0_CFGADDR_CONFIGEN_BIT);
-
-		/* Perform the write */
-		GT_WRITE(GT_PCI0_CFGDATA_OFS, PHYSADDR(MIPS_GT_BASE));
-		break;
-	}
-
-#ifdef CONFIG_MIPS_MALTA
-	while ((pdev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, pdev)) != NULL) {
-		if ((pdev->vendor == PCI_VENDOR_ID_INTEL)
-		    && (pdev->device == PCI_DEVICE_ID_INTEL_82371AB)
-		    && (PCI_SLOT(pdev->devfn) == 0x0a)) {
-			/*
-			 * IDE Decode enable.
-			 */
-			pci_read_config_byte(pdev, 0x41, &reg_val);
-			pci_write_config_byte(pdev, 0x41, reg_val | 0x80);
-			pci_read_config_byte(pdev, 0x43, &reg_val);
-			pci_write_config_byte(pdev, 0x43, reg_val | 0x80);
-		}
-
-		if ((pdev->vendor == PCI_VENDOR_ID_INTEL)
-		    && (pdev->device == PCI_DEVICE_ID_INTEL_82371AB_0)
-		    && (PCI_SLOT(pdev->devfn) == 0x0a)) {
-			/*
-			 * Set top of main memory accessible by ISA or DMA
-			 * devices to 16 Mb.
-			 */
-			pci_read_config_byte(pdev, 0x69, &reg_val);
-			pci_write_config_byte(pdev, 0x69, reg_val | 0xf0);
-		}
-	}
-
-	/*
-	 * Activate Floppy Controller in the SMSC FDC37M817 Super I/O
-	 * Controller.
-	 * This should be done in the bios/bootprom and will be fixed in
-	 * a later revision of YAMON (the MIPS boards boot prom).
-	 */
-	/* Entering config state. */
-	SMSC_WRITE(SMSC_CONFIG_ENTER, SMSC_CONFIG_REG);
-
-	/* Activate floppy controller. */
-	SMSC_WRITE(SMSC_CONFIG_DEVNUM, SMSC_CONFIG_REG);
-	SMSC_WRITE(SMSC_CONFIG_DEVNUM_FLOPPY, SMSC_DATA_REG);
-	SMSC_WRITE(SMSC_CONFIG_ACTIVATE, SMSC_CONFIG_REG);
-	SMSC_WRITE(SMSC_CONFIG_ACTIVATE_ENABLE, SMSC_DATA_REG);
-
-	/* Exit config state. */
-	SMSC_WRITE(SMSC_CONFIG_EXIT, SMSC_CONFIG_REG);
-#endif
-
-	return 0;
-}
-
-subsys_initcall(pcibios_init);
-
-int pcibios_enable_device(struct pci_dev *dev, int mask)
-{
-	/* Not needed, since we enable all devices at startup.  */
-	return 0;
-}
-
-void pcibios_align_resource(void *data, struct resource *res,
-			    unsigned long size, unsigned long align)
-{
-}
-
-char *__init pcibios_setup(char *str)
-{
-	/* Nothing to do for now.  */
-
-	return str;
-}
-
-struct pci_fixup pcibios_fixups[] = {
-	{0}
-};
-
-/*
- *  Called after each bus is probed, but before its children
- *  are examined.
- */
-void __devinit pcibios_fixup_bus(struct pci_bus *b)
-{
-	pci_read_bridge_bases(b);
-}
-
-unsigned int pcibios_assign_all_busses(void)
-{
-	return 1;
-}
--- diff/arch/mips/pci/pci-sni.c	2003-07-08 09:55:17.000000000 +0100
+++ source/arch/mips/pci/pci-sni.c	1970-01-01 01:00:00.000000000 +0100
@@ -1,175 +0,0 @@
-/*
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * SNI specific PCI support for RM200/RM300.
- *
- * Copyright (C) 1997 - 2000 Ralf Baechle
- */
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/pci.h>
-#include <linux/types.h>
-#include <asm/byteorder.h>
-#include <asm/sni.h>
-
-#define mkaddr(bus, devfn, where)                                                   \
-do {                                                                         \
-	if (bus->number == 0)                                         \
-		return -1;                                                   \
-	*(volatile u32 *)PCIMT_CONFIG_ADDRESS =                              \
-		 ((bus->number    & 0xff) << 0x10) |                    \
-	         ((devfn & 0xff) << 0x08) |                             \
-	         (where  & 0xfc);                                            \
-} while(0)
-
-#if 0
-/* To do:  Bring this uptodate ...  */
-static void pcimt_pcibios_fixup(void)
-{
-	struct pci_dev *dev = NULL;
-
-	while ((dev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) {
-		/*
-		 * TODO: Take care of RM300 revision D boards for where the
-		 * network slot became an ordinary PCI slot.
-		 */
-		if (dev->devfn == PCI_DEVFN(1, 0)) {
-			/* Evil hack ...  */
-			set_cp0_config(CONF_CM_CMASK,
-				       CONF_CM_CACHABLE_NO_WA);
-			dev->irq = PCIMT_IRQ_SCSI;
-			continue;
-		}
-		if (dev->devfn == PCI_DEVFN(2, 0)) {
-			dev->irq = PCIMT_IRQ_ETHERNET;
-			continue;
-		}
-
-		switch (dev->irq) {
-		case 1...4:
-			dev->irq += PCIMT_IRQ_INTA - 1;
-			break;
-		case 0:
-			break;
-		default:
-			printk("PCI device on bus %d, dev %d, function %d "
-			       "impossible interrupt configured.\n",
-			       dev->bus->number, PCI_SLOT(dev->devfn),
-			       PCI_SLOT(dev->devfn));
-		}
-	}
-}
-#endif
-
-/*
- * We can't address 8 and 16 bit words directly.  Instead we have to
- * read/write a 32bit word and mask/modify the data we actually want.
- */
-static int pcimt_read(struct pci_bus *bus, unsigned int devfn, int where,
-		      int size, u32 * val)
-{
-	u32 res;
-
-	switch (size) {
-	case 1:
-		mkaddr(bus, devfn, where);
-		res = *(volatile u32 *) PCIMT_CONFIG_DATA;
-		res = (le32_to_cpu(res) >> ((where & 3) << 3)) & 0xff;
-		*val = (u8) res;
-		break;
-	case 2:
-		if (where & 1)
-			return PCIBIOS_BAD_REGISTER_NUMBER;
-		mkaddr(bus, devfn, where);
-		res = *(volatile u32 *) PCIMT_CONFIG_DATA;
-		res = (le32_to_cpu(res) >> ((where & 3) << 3)) & 0xffff;
-		*val = (u16) res;
-		break;
-	case 4:
-		if (where & 3)
-			return PCIBIOS_BAD_REGISTER_NUMBER;
-		mkaddr(bus, devfn, where);
-		res = *(volatile u32 *) PCIMT_CONFIG_DATA;
-		res = le32_to_cpu(res);
-		*val = res;
-		break;
-	}
-
-	return PCIBIOS_SUCCESSFUL;
-}
-
-static int pcimt_write(struct pci_bus *bus, unsigned int devfn, int where,
-		       int size, u32 val)
-{
-	switch (size) {
-	case 1:
-		mkaddr(bus, devfn, where);
-		*(volatile u8 *) (PCIMT_CONFIG_DATA + (where & 3)) =
-		    (u8) le32_to_cpu(val);
-		break;
-	case 2:
-		if (where & 1)
-			return PCIBIOS_BAD_REGISTER_NUMBER;
-		mkaddr(bus, devfn, where);
-		*(volatile u16 *) (PCIMT_CONFIG_DATA + (where & 3)) =
-		    (u16) le32_to_cpu(val);
-		break;
-	case 4:
-		if (where & 3)
-			return PCIBIOS_BAD_REGISTER_NUMBER;
-		mkaddr(bus, devfn, where);
-		*(volatile u32 *) PCIMT_CONFIG_DATA = le32_to_cpu(val);
-		break;
-	}
-
-	return PCIBIOS_SUCCESSFUL;
-}
-
-struct pci_ops sni_pci_ops = {
-	.read = pcimt_read,
-	.write = pcimt_write,
-};
-
-void __devinit pcibios_fixup_bus(struct pci_bus *b)
-{
-}
-
-static int __init pcibios_init(void)
-{
-	struct pci_ops *ops = &sni_pci_ops;
-
-	pci_scan_bus(0, ops, NULL);
-
-	return 0;
-}
-
-subsys_initcall(pcibios_init);
-
-int __init pcibios_enable_device(struct pci_dev *dev, int mask)
-{
-	/* Not needed, since we enable all devices at startup.  */
-	return 0;
-}
-
-void pcibios_align_resource(void *data, struct resource *res,
-			    unsigned long size, unsigned long align)
-{
-}
-
-unsigned __init int pcibios_assign_all_busses(void)
-{
-	return 0;
-}
-
-char *__init pcibios_setup(char *str)
-{
-	/* Nothing to do for now.  */
-
-	return str;
-}
-
-struct pci_fixup pcibios_fixups[] = {
-	{0}
-};
--- diff/arch/mips/sgi-ip22/ip22-ksyms.c	2003-07-08 09:55:17.000000000 +0100
+++ source/arch/mips/sgi-ip22/ip22-ksyms.c	1970-01-01 01:00:00.000000000 +0100
@@ -1,21 +0,0 @@
-/*
- * ip22-ksyms.c: IP22 specific exports
- */
-
-#include <linux/module.h>
-
-#include <asm/sgi/mc.h>
-#include <asm/sgi/hpc3.h>
-#include <asm/sgi/ioc.h>
-#include <asm/sgi/ip22.h>
-
-EXPORT_SYMBOL(sgimc);
-EXPORT_SYMBOL(hpc3c0);
-EXPORT_SYMBOL(hpc3c1);
-EXPORT_SYMBOL(sgioc);
-
-extern void (*indy_volume_button)(int);
-EXPORT_SYMBOL(indy_volume_button);
-
-EXPORT_SYMBOL(ip22_eeprom_read);
-EXPORT_SYMBOL(ip22_nvram_read);
--- diff/arch/mips/sgi-ip22/ip22-rtc.c	2003-07-08 09:55:17.000000000 +0100
+++ source/arch/mips/sgi-ip22/ip22-rtc.c	1970-01-01 01:00:00.000000000 +0100
@@ -1,32 +0,0 @@
-/*
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * RTC routines for Indy style attached Dallas chip.
- *
- * Copyright (C) 1998, 2001 by Ralf Baechle
- */
-#include <asm/ds1286.h>
-#include <asm/sgi/hpc3.h>
-
-static unsigned char ip22_rtc_read_data(unsigned long addr)
-{
-	return hpc3c0->rtcregs[addr];
-}
-
-static void ip22_rtc_write_data(unsigned char data, unsigned long addr)
-{
-	hpc3c0->rtcregs[addr] = data;
-}
-
-static int ip22_rtc_bcd_mode(void)
-{
-	return 0;
-}
-
-struct rtc_ops ip22_rtc_ops = {
-	&ip22_rtc_read_data,
-	&ip22_rtc_write_data,
-	&ip22_rtc_bcd_mode
-};
--- diff/arch/mips/sgi-ip32/ip32-rtc.c	2003-07-08 09:55:17.000000000 +0100
+++ source/arch/mips/sgi-ip32/ip32-rtc.c	1970-01-01 01:00:00.000000000 +0100
@@ -1,32 +0,0 @@
-/*
- * RTC routines for IP32 style attached Dallas chip.
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (C) 2000 Harald Koerfgen
- */
-#include <linux/mc146818rtc.h>
-#include <asm/ip32/mace.h>
-
-static unsigned char ip32_rtc_read_data(unsigned long addr)
-{
-	return (unsigned char) mace_read_8 (MACEISA_RTC_BASE + (addr << 8));
-}
-
-static void ip32_rtc_write_data(unsigned char data, unsigned long addr)
-{
-	mace_write_8 (MACEISA_RTC_BASE + (addr << 8), data);
-}
-
-static int ip32_rtc_bcd_mode(void)
-{
-	return 0;
-}
-
-struct rtc_ops ip32_rtc_ops = {
-	&ip32_rtc_read_data,
-	&ip32_rtc_write_data,
-	&ip32_rtc_bcd_mode
-};
--- diff/arch/mips/sibyte/swarm/cmdline.c	2003-07-08 09:55:17.000000000 +0100
+++ source/arch/mips/sibyte/swarm/cmdline.c	1970-01-01 01:00:00.000000000 +0100
@@ -1,26 +0,0 @@
-/*
- * Copyright (C) 2000, 2001 Broadcom Corporation
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
- */
-#include <asm/bootinfo.h>
-
-/*
- * The naming of this variable is a remnant of the initial mips port to
- * ARC-firmware based SGI consoles.  We don't really need to do anything for
- * the variable other than provide an instantiation.  Everything about
- * arcs_cmdline seems more than a little bit hackish...
- */
-char arcs_cmdline[CL_SIZE];
--- diff/arch/mips/sibyte/swarm/rtc.c	2003-07-08 09:55:17.000000000 +0100
+++ source/arch/mips/sibyte/swarm/rtc.c	1970-01-01 01:00:00.000000000 +0100
@@ -1,44 +0,0 @@
-/*
- * Copyright (C) 2000, 2001 Broadcom Corporation
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
- */
-
-/*
- *  Not really sure what is supposed to be here, yet
- */
-
-#include <linux/spinlock.h>
-#include <linux/mc146818rtc.h>
-
-static unsigned char swarm_rtc_read_data(unsigned long addr)
-{
-	return 0;
-}
-
-static void swarm_rtc_write_data(unsigned char data, unsigned long addr)
-{
-}
-
-static int swarm_rtc_bcd_mode(void)
-{
-	return 0;
-}
-
-struct rtc_ops swarm_rtc_ops = {
-	&swarm_rtc_read_data,
-	&swarm_rtc_write_data,
-	&swarm_rtc_bcd_mode
-};
--- diff/arch/mips/sni/io.c	2003-08-20 14:16:25.000000000 +0100
+++ source/arch/mips/sni/io.c	1970-01-01 01:00:00.000000000 +0100
@@ -1,178 +0,0 @@
-/*
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Low level I/O functions for SNI.
- */
-#include <linux/string.h>
-#include <linux/spinlock.h>
-#include <asm/addrspace.h>
-#include <asm/system.h>
-#include <asm/sni.h>
-
-/*
- * Urgs...  We only can see a 16mb window of the 4gb EISA address space
- * at PCIMT_EISA_BASE.  Maladia segmentitis ...
- *
- * To avoid locking and all the related headacke we implement this such
- * that accessing the bus address space nests, so we're treating this
- * correctly even for interrupts.  This is going to suck seriously for
- * the SMP members of the RM family.
- *
- * Making things worse the PCIMT_CSMAPISA register resides on the X bus with
- * it's unbeatable 1.4 mb/s transfer rate.
- */
-
-static inline void eisa_map(unsigned long address)
-{
-	unsigned char upper;
-
-	upper = address >> 24;
-	*(volatile unsigned char *)PCIMT_CSMAPISA = ~upper;
-}
-
-#define save_eisa_map()							\
-	(*(volatile unsigned char *)PCIMT_CSMAPISA)
-#define restore_eisa_map(val)						\
-	do { (*(volatile unsigned char *)PCIMT_CSMAPISA) = val; } while(0)
-
-static unsigned char sni_readb(unsigned long addr)
-{
-	unsigned char res;
-	unsigned int save_map;
-
-	save_map = save_eisa_map();
-	eisa_map(addr);
-	addr &= 0xffffff;
-	res = *(volatile unsigned char *) (PCIMT_EISA_BASE + addr);
-	restore_eisa_map(save_map);
-
-	return res;
-}
-
-static unsigned short sni_readw(unsigned long addr)
-{
-	unsigned short res;
-	unsigned int save_map;
-
-	save_map = save_eisa_map();
-	eisa_map(addr);
-	addr &= 0xffffff;
-	res = *(volatile unsigned char *) (PCIMT_EISA_BASE + addr);
-	restore_eisa_map(save_map);
-
-	return res;
-}
-
-static unsigned int sni_readl(unsigned long addr)
-{
-	unsigned int res;
-	unsigned int save_map;
-
-	save_map = save_eisa_map();
-	eisa_map(addr);
-	addr &= 0xffffff;
-	res = *(volatile unsigned char *) (PCIMT_EISA_BASE + addr);
-	restore_eisa_map(save_map);
-
-	return res;
-}
-
-static void sni_writeb(unsigned char val, unsigned long addr)
-{
-	unsigned int save_map;
-
-	save_map = save_eisa_map();
-	eisa_map(addr);
-	addr &= 0xffffff;
-	*(volatile unsigned char *) (PCIMT_EISA_BASE + addr) = val;
-	restore_eisa_map(save_map);
-}
-
-static void sni_writew(unsigned short val, unsigned long addr)
-{
-	unsigned int save_map;
-
-	save_map = save_eisa_map();
-	eisa_map(addr);
-	addr &= 0xffffff;
-	*(volatile unsigned char *) (PCIMT_EISA_BASE + addr) = val;
-	restore_eisa_map(save_map);
-}
-
-static void sni_writel(unsigned int val, unsigned long addr)
-{
-	unsigned int save_map;
-
-	save_map = save_eisa_map();
-	eisa_map(addr);
-	addr &= 0xffffff;
-	*(volatile unsigned char *) (PCIMT_EISA_BASE + addr) = val;
-	restore_eisa_map(save_map);
-}
-
-static void sni_memset_io(unsigned long addr, int val, unsigned long len)
-{
-	unsigned long waddr;
-	unsigned int save_map;
-
-	save_map = save_eisa_map();
-	waddr = PCIMT_EISA_BASE | (addr & 0xffffff);
-	while(len) {
-		unsigned long fraglen;
-
-		fraglen = (~addr + 1) & 0xffffff;
-		fraglen = (fraglen < len) ? fraglen : len;
-		eisa_map(addr);
-		memset((char *)waddr, val, fraglen);
-		addr += fraglen;
-		waddr = waddr + fraglen - 0x1000000;
-		len -= fraglen;
-	}
-	restore_eisa_map(save_map);
-}
-
-static void sni_memcpy_fromio(unsigned long to, unsigned long from, unsigned long len)
-{
-	unsigned long waddr;
-	unsigned int save_map;
-
-	save_map = save_eisa_map();
-	waddr = PCIMT_EISA_BASE | (from & 0xffffff);
-	while(len) {
-		unsigned long fraglen;
-
-		fraglen = (~from + 1) & 0xffffff;
-		fraglen = (fraglen < len) ? fraglen : len;
-		eisa_map(from);
-		memcpy((void *)to, (void *)waddr, fraglen);
-		to += fraglen;
-		from += fraglen;
-		waddr = waddr + fraglen - 0x1000000;
-		len -= fraglen;
-	}
-	restore_eisa_map(save_map);
-}
-
-static void sni_memcpy_toio(unsigned long to, unsigned long from, unsigned long len)
-{
-	unsigned long waddr;
-	unsigned int save_map;
-
-	save_map = save_eisa_map();
-	waddr = PCIMT_EISA_BASE | (to & 0xffffff);
-	while(len) {
-		unsigned long fraglen;
-
-		fraglen = (~to + 1) & 0xffffff;
-		fraglen = (fraglen < len) ? fraglen : len;
-		eisa_map(to);
-		memcpy((char *)to + PCIMT_EISA_BASE, (void *)from, fraglen);
-		to += fraglen;
-		from += fraglen;
-		waddr = waddr + fraglen - 0x1000000;
-		len -= fraglen;
-	}
-	restore_eisa_map(save_map);
-}
--- diff/arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_pci_fixup.c	2003-07-08 09:55:17.000000000 +0100
+++ source/arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_pci_fixup.c	1970-01-01 01:00:00.000000000 +0100
@@ -1,329 +0,0 @@
-/*
- *
- * BRIEF MODULE DESCRIPTION
- *      Board specific pci fixups for the Toshiba rbtx4927
- *
- * Copyright 2001 MontaVista Software Inc.
- * Author: MontaVista Software, Inc.
- *              ppopov@mvista.com or source@mvista.com
- *
- * Copyright (C) 2000-2001 Toshiba Corporation 
- *
- *  This program is free software; you can redistribute  it and/or modify it
- *  under  the terms of  the GNU General  Public License as published by the
- *  Free Software Foundation;  either version 2 of the  License, or (at your
- *  option) any later version.
- *
- *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
- *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
- *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
- *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
- *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
- *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- *  You should have received a copy of the  GNU General Public License along
- *  with this program; if not, write  to the Free Software Foundation, Inc.,
- *  675 Mass Ave, Cambridge, MA 02139, USA.
- */
-#include <linux/types.h>
-#include <linux/pci.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
-
-#include <asm/tx4927/tx4927.h>
-#include <asm/tx4927/tx4927_pci.h>
-
-#undef  DEBUG
-#ifdef  DEBUG
-#define DBG(x...)       printk(x)
-#else
-#define DBG(x...)
-#endif
-
-void __init pcibios_fixup_resources(struct pci_dev *dev)
-{
-	/* will need to fixup IO resources */
-}
-
-void __init pcibios_fixup(void)
-{
-	/* nothing to do here */
-}
-
-/* look up table for backplane pci irq for slots 17-20 by pin # */
-static unsigned char backplane_pci_irq[4][4] = {
-	/* PJ6 SLOT:  17, PIN: 1 */ {TX4927_IRQ_IOC_PCIA,
-				     /* PJ6 SLOT:  17, PIN: 2 */
-				     TX4927_IRQ_IOC_PCIB,
-				     /* PJ6 SLOT:  17, PIN: 3 */
-				     TX4927_IRQ_IOC_PCIC,
-				     /* PJ6 SLOT:  17, PIN: 4 */
-				     TX4927_IRQ_IOC_PCID},
-	/* SB  SLOT:  18, PIN: 1 */ {TX4927_IRQ_IOC_PCIB,
-				     /* SB  SLOT:  18, PIN: 2 */
-				     TX4927_IRQ_IOC_PCIC,
-				     /* SB  SLOT:  18, PIN: 3 */
-				     TX4927_IRQ_IOC_PCID,
-				     /* SB  SLOT:  18, PIN: 4 */
-				     TX4927_IRQ_IOC_PCIA},
-	/* PJ5 SLOT:  19, PIN: 1 */ {TX4927_IRQ_IOC_PCIC,
-				     /* PJ5 SLOT:  19, PIN: 2 */
-				     TX4927_IRQ_IOC_PCID,
-				     /* PJ5 SLOT:  19, PIN: 3 */
-				     TX4927_IRQ_IOC_PCIA,
-				     /* PJ5 SLOT:  19, PIN: 4 */
-				     TX4927_IRQ_IOC_PCIB},
-	/* PJ4 SLOT:  20, PIN: 1 */ {TX4927_IRQ_IOC_PCID,
-				     /* PJ4 SLOT:  20, PIN: 2 */
-				     TX4927_IRQ_IOC_PCIA,
-				     /* PJ4 SLOT:  20, PIN: 3 */
-				     TX4927_IRQ_IOC_PCIB,
-				     /* PJ4 SLOT:  20, PIN: 4 */
-				     TX4927_IRQ_IOC_PCIC}
-};
-
-int pci_get_irq(struct pci_dev *dev, int pin)
-{
-	unsigned char irq = pin;
-
-	DBG("pci_get_irq: pin is %d\n", pin);
-	/* IRQ rotation */
-	irq--;			/* 0-3 */
-	if (dev->bus->parent == NULL &&
-	    PCI_SLOT(dev->devfn) == TX4927_PCIC_IDSEL_AD_TO_SLOT(23)) {
-		printk("Onboard PCI_SLOT(dev->devfn) is %d\n",
-		       PCI_SLOT(dev->devfn));
-		/* IDSEL=A23 is tx4927 onboard pci slot */
-		irq = (irq + PCI_SLOT(dev->devfn)) % 4;
-		irq++;		/* 1-4 */
-		DBG("irq is now %d\n", irq);
-
-		switch (irq) {
-		case 1:
-			irq = TX4927_IRQ_IOC_PCIA;
-			break;
-		case 2:
-			irq = TX4927_IRQ_IOC_PCIB;
-			break;
-		case 3:
-			irq = TX4927_IRQ_IOC_PCIC;
-			break;
-		case 4:
-			irq = TX4927_IRQ_IOC_PCID;
-			break;
-		}
-	} else {
-		/* PCI Backplane */
-		DBG("PCI Backplane PCI_SLOT(dev->devfn) is %d\n",
-		    PCI_SLOT(dev->devfn));
-		irq = backplane_pci_irq[PCI_SLOT(dev->devfn) - 17][irq];
-	}
-	DBG("assigned irq %d\n", irq);
-	return irq;
-}
-
-
-#ifdef  TX4927_SUPPORT_PCI_66
-extern int tx4927_pci66;
-extern void tx4927_pci66_setup(void);
-#endif
-extern void tx4927_pci_setup(void);
-
-#ifdef  TX4927_SUPPORT_PCI_66
-int tx4927_pci66_check(void)
-{
-	struct pci_dev *dev;
-	unsigned short stat;
-	int cap66 = 1;
-
-	if (tx4927_pci66 < 0)
-		return 0;
-
-	/* check 66MHz capability */
-	pci_for_each_dev(dev) {
-		if (cap66) {
-			pci_read_config_word(dev, PCI_STATUS, &stat);
-			if (!(stat & PCI_STATUS_66MHZ)) {
-				printk(KERN_INFO
-				       "PCI: %02x:%02x not 66MHz capable.\n",
-				       dev->bus->number, dev->devfn);
-				cap66 = 0;
-			}
-		}
-	}
-	return cap66;
-}
-#endif
-
-#ifdef DEBUG
-void do_it(u32 offset, u32 reg)
-{
-	volatile u32 a1;
-	volatile u32 a2;
-	volatile u32 v1;
-	volatile u32 v2;
-
-	a1 = 0xff1f0000 + offset + reg;
-	a2 = a1 + 4;
-
-	v1 = *(volatile u32 *) a1;
-	v2 = *(volatile u32 *) a2;
-
-	if (v1)
-		printk("TX4927 0x%08x 0x%08x\n", a1, v1);
-	if (v2)
-		printk("TX4927 0x%08x 0x%08x\n", a2, v2);
-}
-
-void do_it1(u32 base, u32 r)
-{
-	do_it(base, r);
-}
-
-void do_it2(u32 base, u32 start, u32 stop)
-{
-	u32 r;
-
-	for (r = start; r <= stop; r += 8) {
-		do_it(base, r);
-	}
-}
-void dump_config(void)
-{
-	unsigned long id;
-	unsigned long j;
-	struct pci_dev *dev;
-
-	printk("----------------------pci\n");
-	pci_for_each_dev(dev) {
-		for (j = 0; j < 64; j++) {
-			pci_read_config_dword(dev, j * 4, &id);
-			if (id == 0)
-				continue;
-			printk
-			    ("dev 0x%02x 0x%02x:0x%02x -- 0x%02x-0x%02x 0x%08x\n",
-			     dev->devfn, PCI_SLOT(dev->devfn),
-			     PCI_FUNC(dev->devfn), (j * 4) + 3, (j * 4),
-			     id);
-		}
-		printk("dev 0x%02x \n", dev->devfn);
-	}
-	printk("----------------------sdram\n");
-	do_it2(0x8000, 0x00, 0x18);
-	do_it1(0x8000, 0x40);
-	do_it1(0x8000, 0x58);
-	printk("----------------------ebus\n");
-	do_it2(0x9000, 0x00, 0x38);
-	printk("----------------------ecc\n");
-	do_it2(0xa000, 0x00, 0x08);
-	printk("----------------------dmac\n");
-	do_it2(0xb000, 0x00, 0xf8);
-	/* b1xx */
-	printk("----------------------pci\n");
-	/* d */
-	printk("----------------------cfg\n");
-	do_it2(0xe000, 0x00, 0x20);
-	do_it1(0xe000, 0x30);
-	do_it1(0xe000, 0x48);
-	printk("----------------------timers\n");
-	do_it2(0xf000, 0x00, 0xf0);
-	do_it2(0xf100, 0x00, 0xf0);
-	do_it2(0xf200, 0x00, 0xf0);
-	printk("----------------------serial\n");
-	do_it2(0xf300, 0x00, 0x20);
-	do_it2(0xf400, 0x00, 0x20);
-	printk("----------------------parallel\n");
-	do_it2(0xf500, 0x00, 0x0c);
-	printk("----------------------pic\n");
-	do_it2(0xf500, 0x10, 0x24);
-	do_it2(0xf600, 0x00, 0x2c);
-	do_it1(0xf600, 0x40);
-	do_it1(0xf600, 0x60);
-	do_it1(0xf600, 0x80);
-	do_it1(0xf600, 0xa0);
-	printk("----------------------aclink\n");
-	do_it2(0xf700, 0x00, 0xfc);
-	printk("----------------------done\n");
-}
-#endif
-
-
-void __init pcibios_fixup_irqs(void)
-{
-	unsigned char pin;
-	unsigned char irq;
-	struct pci_dev *dev;
-	unsigned int id;
-
-#ifdef  TX4927_SUPPORT_PCI_66
-	{
-		if (tx4927_pci66_check()) {
-			tx4927_pci66_setup();
-			tx4927_pci_setup();	/* Reinitialize PCIC */
-		}
-	}
-#endif
-
-	pci_for_each_dev(dev) {
-		DBG("FIXUP:\n");
-		DBG(" devfn=0x%02x (0x%02x:0x%02x)\n",
-		    dev->devfn, PCI_SLOT(dev->devfn),
-		    PCI_FUNC(dev->devfn));
-
-		pci_read_config_dword(dev, PCI_VENDOR_ID, &id);
-		DBG(" id=0x%08x\n", id);
-
-		pci_read_config_byte(dev, PCI_INTERRUPT_LINE, &irq);
-		DBG(" line=0x%02x/%d\n", irq, irq);
-
-		pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin);
-		DBG(" pin=%d\n", pin);
-
-#ifdef DEBUG
-		{
-			unsigned int tmp;
-			pci_read_config_dword(dev, 0x10, &tmp);
-			DBG(" bar0:0x10=0x%08x\n", tmp);
-			pci_read_config_dword(dev, 0x14, &tmp);
-			DBG(" bar1:0x14=0x%08x\n", tmp);
-			pci_read_config_dword(dev, 0x1c, &tmp);
-			DBG(" bar2:0x1c=0x%08x\n", tmp);
-			pci_read_config_dword(dev, 0x20, &tmp);
-			DBG(" bar3:0x20=0x%08x\n", tmp);
-			pci_read_config_dword(dev, 0x24, &tmp);
-			DBG(" bar4:0x24=0x%08x\n", tmp);
-		}
-#endif
-
-		irq = 0;
-
-		if (id == 0x91301055) {	/* ide */
-			irq = 14;
-		}
-
-		if (pin == 0) {
-			DBG(" auto irq (now=%d) -- skipping pin=0\n", irq);
-		} else if (irq) {
-			DBG(" auto irq (now=%d) -- skipping hardcoded irq\n", irq);
-		} else {
-			DBG(" auto irq (was=%d)\n", irq);
-			irq = pci_get_irq(dev, pin);
-			pci_write_config_byte(dev, PCI_INTERRUPT_LINE,
-					      irq);
-			dev->irq = irq;
-			DBG(" auto irq (now=%d)\n", irq);
-		}
-
-		pci_read_config_byte(dev, PCI_INTERRUPT_LINE, &irq);
-		printk(KERN_INFO
-		       "PCI: 0x%02x:0x%02x(0x%02x,0x%02x) IRQ=%d\n",
-		       dev->bus->number, dev->devfn, PCI_SLOT(dev->devfn),
-		       PCI_FUNC(dev->devfn), irq);
-
-	}
-
-}
--- diff/arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_pci_ops.c	2003-07-08 09:55:17.000000000 +0100
+++ source/arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_pci_ops.c	1970-01-01 01:00:00.000000000 +0100
@@ -1,317 +0,0 @@
-/*
- * Copyright 2001 MontaVista Software Inc.
- * Author: MontaVista Software, Inc.
- *              ahennessy@mvista.com       
- *
- * Copyright (C) 2000-2001 Toshiba Corporation 
- *
- * Based on arch/mips/ddb5xxx/ddb5477/pci_ops.c
- *
- *     Define the pci_ops for the Toshiba rbtx4927
- *
- * Much of the code is derived from the original DDB5074 port by 
- * Geert Uytterhoeven <geert@sonycom.com>
- *
- *  This program is free software; you can redistribute  it and/or modify it
- *  under  the terms of  the GNU General  Public License as published by the
- *  Free Software Foundation;  either version 2 of the  License, or (at your
- *  option) any later version.
- *
- *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
- *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
- *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
- *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
- *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
- *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- *  You should have received a copy of the  GNU General Public License along
- *  with this program; if not, write  to the Free Software Foundation, Inc.,
- *  675 Mass Ave, Cambridge, MA 02139, USA.
- */
-#include <linux/types.h>
-#include <linux/pci.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
-
-#include <asm/addrspace.h>
-#include <asm/pci_channel.h>
-#include <asm/tx4927/tx4927_pci.h>
-#include <asm/debug.h>
-
-/* initialize in setup */
-struct resource pci_io_resource = {
-	"pci IO space",
-	(PCIBIOS_MIN_IO),
-	((PCIBIOS_MIN_IO) + (TX4927_PCIIO_SIZE)) - 1,
-	IORESOURCE_IO
-};
-
-/* initialize in setup */
-struct resource pci_mem_resource = {
-	"pci memory space",
-	TX4927_PCIMEM,
-	TX4927_PCIMEM + TX4927_PCIMEM_SIZE - 1,
-	IORESOURCE_MEM
-};
-
-extern struct pci_ops tx4927_pci_ops;
-
-struct pci_channel mips_pci_channels[] = {
-	/* h/w only supports devices 0x00 to 0x14 */
-	{&tx4927_pci_ops, &pci_io_resource, &pci_mem_resource,
-	 PCI_DEVFN(0x00, 0), PCI_DEVFN(0x14, 7)},
-	{NULL, NULL, NULL, 0, 0}
-};
-
-unsigned int pcibios_assign_all_busses(void)
-{
-	return 1;
-}
-
-static int
-mkaddr(unsigned char bus, unsigned char dev_fn, unsigned char where,
-       int *flagsp)
-{
-	if (bus > 0) {
-		/* Type 1 configuration */
-		tx4927_pcicptr->g2pcfgadrs = ((bus & 0xff) << 0x10) |
-		    ((dev_fn & 0xff) << 0x08) | (where & 0xfc) | 1;
-	} else {
-		if (dev_fn >= PCI_DEVFN(TX4927_PCIC_MAX_DEVNU, 0))
-			return -1;
-
-		/* Type 0 configuration */
-		tx4927_pcicptr->g2pcfgadrs = ((bus & 0xff) << 0x10) |
-		    ((dev_fn & 0xff) << 0x08) | (where & 0xfc);
-	}
-	/* clear M_ABORT and Disable M_ABORT Int. */
-	tx4927_pcicptr->pcistatus =
-	    (tx4927_pcicptr->pcistatus & 0x0000ffff) |
-	    (PCI_STATUS_REC_MASTER_ABORT << 16);
-	tx4927_pcicptr->pcimask &= ~PCI_STATUS_REC_MASTER_ABORT;
-	return 0;
-}
-
-static int check_abort(int flags)
-{
-	int code = PCIBIOS_SUCCESSFUL;
-	if (tx4927_pcicptr->
-	    pcistatus & (PCI_STATUS_REC_MASTER_ABORT << 16)) {
-		tx4927_pcicptr->pcistatus =
-		    (tx4927_pcicptr->
-		     pcistatus & 0x0000ffff) | (PCI_STATUS_REC_MASTER_ABORT
-						<< 16);
-		tx4927_pcicptr->pcimask |= PCI_STATUS_REC_MASTER_ABORT;
-		code = PCIBIOS_DEVICE_NOT_FOUND;
-		//      printk("returning PCIBIOS_DEVICE_NOT_FOUND\n");
-	}
-	return code;
-}
-
-/*
- * We can't address 8 and 16 bit words directly.  Instead we have to
- * read/write a 32bit word and mask/modify the data we actually want.
- */
-static int tx4927_pcibios_read_config_byte(struct pci_dev *dev,
-					   int where, unsigned char *val)
-{
-	int flags, retval;
-	unsigned char bus, func_num;
-
-	db_assert((where & 3) == 0);
-	db_assert(where < (1 << 8));
-
-	/* check if the bus is top-level */
-	if (dev->bus->parent != NULL) {
-		bus = dev->bus->number;
-		db_assert(bus != 0);
-	} else {
-		bus = 0;
-	}
-
-	func_num = PCI_FUNC(dev->devfn);
-	if (mkaddr(bus, dev->devfn, where, &flags))
-		return -1;
-#ifdef __BIG_ENDIAN
-	*val =
-	    *(volatile u8 *) ((ulong) & tx4927_pcicptr->
-			      g2pcfgdata | ((where & 3) ^ 3));
-#else
-	*val =
-	    *(volatile u8 *) ((ulong) & tx4927_pcicptr->
-			      g2pcfgdata | (where & 3));
-#endif
-	retval = check_abort(flags);
-	if (retval == PCIBIOS_DEVICE_NOT_FOUND)
-		*val = 0xff;
-//printk("CFG R1 0x%02x 0x%02x 0x%08x\n", dev->devfn, where, *val );
-	return retval;
-}
-
-static int tx4927_pcibios_read_config_word(struct pci_dev *dev,
-					   int where, unsigned short *val)
-{
-	int flags, retval;
-	unsigned char bus, func_num;
-
-	if (where & 1)
-		return PCIBIOS_BAD_REGISTER_NUMBER;
-
-	db_assert((where & 3) == 0);
-	db_assert(where < (1 << 8));
-
-	/* check if the bus is top-level */
-	if (dev->bus->parent != NULL) {
-		bus = dev->bus->number;
-		db_assert(bus != 0);
-	} else {
-		bus = 0;
-	}
-
-	func_num = PCI_FUNC(dev->devfn);
-	if (mkaddr(bus, dev->devfn, where, &flags))
-		return -1;
-#ifdef __BIG_ENDIAN
-	*val =
-	    *(volatile u16 *) ((ulong) & tx4927_pcicptr->
-			       g2pcfgdata | ((where & 3) ^ 2));
-#else
-	*val =
-	    *(volatile u16 *) ((ulong) & tx4927_pcicptr->
-			       g2pcfgdata | (where & 3));
-#endif
-	retval = check_abort(flags);
-	if (retval == PCIBIOS_DEVICE_NOT_FOUND)
-		*val = 0xffff;
-//printk("CFG R2 0x%02x 0x%02x 0x%08x\n", dev->devfn, where, *val );
-	return retval;
-}
-
-static int tx4927_pcibios_read_config_dword(struct pci_dev *dev,
-					    int where, unsigned int *val)
-{
-	int flags, retval;
-	unsigned char bus, func_num;
-
-	if (where & 3)
-		return PCIBIOS_BAD_REGISTER_NUMBER;
-
-	db_assert((where & 3) == 0);
-	db_assert(where < (1 << 8));
-
-	/* check if the bus is top-level */
-	if (dev->bus->parent != NULL) {
-		bus = dev->bus->number;
-		db_assert(bus != 0);
-	} else {
-		bus = 0;
-	}
-
-	func_num = PCI_FUNC(dev->devfn);
-	if (mkaddr(bus, dev->devfn, where, &flags))
-		return -1;
-	*val = tx4927_pcicptr->g2pcfgdata;
-	retval = check_abort(flags);
-	if (retval == PCIBIOS_DEVICE_NOT_FOUND)
-		*val = 0xffffffff;
-
-//printk("CFG R4 0x%02x 0x%02x 0x%08x\n", dev->devfn, where, *val );
-	return retval;
-}
-
-static int tx4927_pcibios_write_config_byte(struct pci_dev *dev,
-					    int where, unsigned char val)
-{
-	int flags;
-	unsigned char bus, func_num;
-
-	/* check if the bus is top-level */
-	if (dev->bus->parent != NULL) {
-		bus = dev->bus->number;
-		db_assert(bus != 0);
-	} else {
-		bus = 0;
-	}
-
-	func_num = PCI_FUNC(dev->devfn);
-	if (mkaddr(bus, dev->devfn, where, &flags))
-		return -1;
-#ifdef __BIG_ENDIAN
-	*(volatile u8 *) ((ulong) & tx4927_pcicptr->
-			  g2pcfgdata | ((where & 3) ^ 3)) = val;
-#else
-	*(volatile u8 *) ((ulong) & tx4927_pcicptr->
-			  g2pcfgdata | (where & 3)) = val;
-#endif
-//printk("CFG W1 0x%02x 0x%02x 0x%08x\n", dev->devfn, where, val );
-	return check_abort(flags);
-}
-
-static int tx4927_pcibios_write_config_word(struct pci_dev *dev,
-					    int where, unsigned short val)
-{
-	int flags;
-	unsigned char bus, func_num;
-
-	if (where & 1)
-		return PCIBIOS_BAD_REGISTER_NUMBER;
-
-	/* check if the bus is top-level */
-	if (dev->bus->parent != NULL) {
-		bus = dev->bus->number;
-		db_assert(bus != 0);
-	} else {
-		bus = 0;
-	}
-
-	func_num = PCI_FUNC(dev->devfn);
-	if (mkaddr(bus, dev->devfn, where, &flags))
-		return -1;
-#ifdef __BIG_ENDIAN
-	*(volatile u16 *) ((ulong) & tx4927_pcicptr->
-			   g2pcfgdata | ((where & 3) ^ 2)) = val;
-#else
-	*(volatile u16 *) ((ulong) & tx4927_pcicptr->
-			   g2pcfgdata | (where & 3)) = val;
-#endif
-//printk("CFG W2 0x%02x 0x%02x 0x%08x\n", dev->devfn, where, val );
-	return check_abort(flags);
-}
-
-static int tx4927_pcibios_write_config_dword(struct pci_dev *dev,
-					     int where, unsigned int val)
-{
-	int flags;
-	unsigned char bus, func_num;
-
-	if (where & 3)
-		return PCIBIOS_BAD_REGISTER_NUMBER;
-
-	/* check if the bus is top-level */
-	if (dev->bus->parent != NULL) {
-		bus = dev->bus->number;
-		db_assert(bus != 0);
-	} else {
-		bus = 0;
-	}
-
-	func_num = PCI_FUNC(dev->devfn);
-	if (mkaddr(bus, dev->devfn, where, &flags))
-		return -1;
-	tx4927_pcicptr->g2pcfgdata = val;
-//printk("CFG W4 0x%02x 0x%02x 0x%08x\n", dev->devfn, where, val );
-	return check_abort(flags);
-}
-
-struct pci_ops tx4927_pci_ops = {
-	tx4927_pcibios_read_config_byte,
-	tx4927_pcibios_read_config_word,
-	tx4927_pcibios_read_config_dword,
-	tx4927_pcibios_write_config_byte,
-	tx4927_pcibios_write_config_word,
-	tx4927_pcibios_write_config_dword
-};
--- diff/arch/mips/vr41xx/casio-e55/ide-e55.c	2003-07-08 09:55:17.000000000 +0100
+++ source/arch/mips/vr41xx/casio-e55/ide-e55.c	1970-01-01 01:00:00.000000000 +0100
@@ -1,99 +0,0 @@
-/*
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * IDE routines for typical pc-like standard configurations
- * for the CASIO CASSIOPEIA E-55/65.
- *
- * Copyright (C) 1998, 1999, 2001 by Ralf Baechle
- */
-/*
- * Changes:
- *  Yoichi Yuasa <yuasa@hh.iij4u.or.jp>  Sun, 24 Feb 2002
- *  - Added CASIO CASSIOPEIA E-55/65 support.
- */
-#include <linux/sched.h>
-#include <linux/ide.h>
-#include <linux/ioport.h>
-#include <linux/hdreg.h>
-#include <asm/ptrace.h>
-#include <asm/hdreg.h>
-
-static int e55_ide_default_irq(ide_ioreg_t base)
-{
-	return 40;
-}
-
-static ide_ioreg_t e55_ide_default_io_base(int index)
-{
-	switch (index) {
-		case 0: return 0xc1f0;
-		case 1: return 0xc170;
-		case 2: return 0xc1e8;
-		case 3: return 0xc168;
-		case 4: return 0xc1e0;
-		case 5: return 0xc160;
-	}
-	return 0;
-}
-
-static void e55_ide_init_hwif_ports(hw_regs_t *hw, ide_ioreg_t data_port,
-                                    ide_ioreg_t ctrl_port, int *irq)
-{
-	ide_ioreg_t reg = data_port;
-	int i;
-
-	for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++) {
-		hw->io_ports[i] = reg;
-		reg += 1;
-	}
-	if (ctrl_port) {
-		hw->io_ports[IDE_CONTROL_OFFSET] = ctrl_port;
-	} else {
-		hw->io_ports[IDE_CONTROL_OFFSET] = hw->io_ports[IDE_DATA_OFFSET] + 0x206;
-	}
-	if (irq != NULL)
-		*irq = 0;
-	hw->io_ports[IDE_IRQ_OFFSET] = 0;
-}
-
-static int e55_ide_request_irq(unsigned int irq,
-                               void (*handler)(int,void *, struct pt_regs *),
-                               unsigned long flags, const char *device,
-                               void *dev_id)
-{
-	return request_irq(irq, handler, flags, device, dev_id);
-}			
-
-static void e55_ide_free_irq(unsigned int irq, void *dev_id)
-{
-	free_irq(irq, dev_id);
-}
-
-static int e55_ide_check_region(ide_ioreg_t from, unsigned int extent)
-{
-	return check_region(from, extent);
-}
-
-static void e55_ide_request_region(ide_ioreg_t from, unsigned int extent,
-                                   const char *name)
-{
-	request_region(from, extent, name);
-}
-
-static void e55_ide_release_region(ide_ioreg_t from, unsigned int extent)
-{
-	release_region(from, extent);
-}
-
-struct ide_ops e55_ide_ops = {
-	&e55_ide_default_irq,
-	&e55_ide_default_io_base,
-	&e55_ide_init_hwif_ports,
-	&e55_ide_request_irq,
-	&e55_ide_free_irq,
-	&e55_ide_check_region,
-	&e55_ide_request_region,
-	&e55_ide_release_region
-};
--- diff/arch/mips/vr41xx/common/reset.c	2003-07-08 09:55:17.000000000 +0100
+++ source/arch/mips/vr41xx/common/reset.c	1970-01-01 01:00:00.000000000 +0100
@@ -1,37 +0,0 @@
-/*
- * This program is free software; you can redistribute  it and/or modify it
- * under  the terms of  the GNU General  Public License as published by the
- * Free Software Foundation;  either version 2 of the  License, or (at your
- * option) any later version.
- *
- * Copyright (C) 1997, 2001 Ralf Baechle
- * Copyright 2001 MontaVista Software Inc.
- * Author: jsun@mvista.com or jsun@junsun.net
- */
-#include <linux/sched.h>
-#include <linux/mm.h>
-#include <asm/io.h>
-#include <asm/cacheflush.h>
-#include <asm/processor.h>
-#include <asm/reboot.h>
-#include <asm/system.h>
-
-void vr41xx_restart(char *command)
-{
-	change_c0_status((ST0_BEV | ST0_ERL), (ST0_BEV | ST0_ERL));
-	change_c0_config(CONF_CM_CMASK, CONF_CM_UNCACHED);
-	flush_cache_all();
-	write_c0_wired(0);
-	__asm__ __volatile__("jr\t%0"::"r"(0xbfc00000));
-}
-
-void vr41xx_halt(void)
-{
-	printk(KERN_NOTICE "\n** You can safely turn off the power\n");
-	while (1);
-}
-
-void vr41xx_power_off(void)
-{
-	vr41xx_halt();
-}
--- diff/arch/mips/vr41xx/common/time.c	2003-07-08 09:55:17.000000000 +0100
+++ source/arch/mips/vr41xx/common/time.c	1970-01-01 01:00:00.000000000 +0100
@@ -1,93 +0,0 @@
-/*
- * FILE NAME
- *	arch/mips/vr41xx/common/time.c
- *
- * BRIEF MODULE DESCRIPTION
- *	Timer routines for the NEC VR4100 series.
- *
- * Author: Yoichi Yuasa
- *         yyuasa@mvista.com or source@mvista.com
- *
- * Copyright 2001,2002 MontaVista Software Inc.
- *
- *  This program is free software; you can redistribute it and/or modify it
- *  under the terms of the GNU General Public License as published by the
- *  Free Software Foundation; either version 2 of the License, or (at your
- *  option) any later version.
- *
- *  THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
- *  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- *  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
- *  OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- *  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
- *  TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
- *  USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- *  You should have received a copy of the GNU General Public License along
- *  with this program; if not, write to the Free Software Foundation, Inc.,
- *  675 Mass Ave, Cambridge, MA 02139, USA.
- */
-/*
- * Changes:
- *  MontaVista Software Inc. <yyuasa@mvista.com> or <source@mvista.com>
- *  - Added support for NEC VR4100 series RTC Unit.
- *
- *  MontaVista Software Inc. <yyuasa@mvista.com> or <source@mvista.com>
- *  - New creation, NEC VR4100 series are supported.
- */
-#include <linux/config.h>
-#include <linux/interrupt.h>
-#include <linux/irq.h>
-#include <linux/types.h>
-
-#include <asm/cpu.h>
-#include <asm/io.h>
-#include <asm/mipsregs.h>
-#include <asm/param.h>
-#include <asm/time.h>
-#include <asm/vr41xx/vr41xx.h>
-
-#define VR4111_ETIMELREG	KSEG1ADDR(0x0b0000c0)
-#define VR4122_ETIMELREG	KSEG1ADDR(0x0f000100)
-
-u32 vr41xx_rtc_base = 0;
-
-#ifdef CONFIG_VR41XX_RTC
-extern unsigned long vr41xx_rtc_get_time(void);
-extern int vr41xx_rtc_set_time(unsigned long sec);
-#endif
-
-void vr41xx_time_init(void)
-{
-	switch (current_cpu_data.cputype) {
-	case CPU_VR4111:
-	case CPU_VR4121:
-		vr41xx_rtc_base = VR4111_ETIMELREG;
-		break;
-	case CPU_VR4122:
-	case CPU_VR4131:
-                vr41xx_rtc_base = VR4122_ETIMELREG;
-                break;
-        default:
-                panic("Unexpected CPU of NEC VR4100 series");
-                break;
-        }
-
-#ifdef CONFIG_VR41XX_RTC
-        rtc_get_time = vr41xx_rtc_get_time;
-        rtc_set_time = vr41xx_rtc_set_time;
-#endif
-}
-
-void vr41xx_timer_setup(struct irqaction *irq)
-{
-	u32 count;
-
-	setup_irq(MIPS_COUNTER_IRQ, irq);
-
-	count = read_c0_count();
-	write_c0_compare(count + (mips_counter_frequency / HZ));
-}
--- diff/arch/mips/vr41xx/ibm-workpad/ide-workpad.c	2003-07-08 09:55:17.000000000 +0100
+++ source/arch/mips/vr41xx/ibm-workpad/ide-workpad.c	1970-01-01 01:00:00.000000000 +0100
@@ -1,98 +0,0 @@
-/*
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * IDE routines for typical pc-like standard configurations for the IBM WorkPad z50.
- *
- * Copyright (C) 1998, 1999, 2001 by Ralf Baechle
- */
-/*
- * Changes:
- *  Yoichi Yuasa <yuasa@hh.iij4u.or.jp>  Sun, 24 Feb 2002
- *  - Added IBM WorkPad z50 support.
- */
-#include <linux/sched.h>
-#include <linux/ide.h>
-#include <linux/ioport.h>
-#include <linux/hdreg.h>
-#include <asm/ptrace.h>
-#include <asm/hdreg.h>
-
-static int workpad_ide_default_irq(ide_ioreg_t base)
-{
-	return 49;
-}
-
-static ide_ioreg_t workpad_ide_default_io_base(int index)
-{
-	switch (index) {
-		case 0: return 0x1f0;
-		case 1: return 0x170;
-		case 2: return 0x1e8;
-		case 3: return 0x168;
-		case 4: return 0x1e0;
-		case 5: return 0x160;
-	}
-	return 0;
-}
-
-static void workpad_ide_init_hwif_ports(hw_regs_t *hw, ide_ioreg_t data_port,
-                                        ide_ioreg_t ctrl_port, int *irq)
-{
-	ide_ioreg_t reg = data_port;
-	int i;
-
-	for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++) {
-		hw->io_ports[i] = reg;
-		reg += 1;
-	}
-	if (ctrl_port) {
-		hw->io_ports[IDE_CONTROL_OFFSET] = ctrl_port;
-	} else {
-		hw->io_ports[IDE_CONTROL_OFFSET] = hw->io_ports[IDE_DATA_OFFSET] + 0x206;
-	}
-	if (irq != NULL)
-		*irq = 0;
-	hw->io_ports[IDE_IRQ_OFFSET] = 0;
-}
-
-static int workpad_ide_request_irq(unsigned int irq,
-                                   void (*handler)(int,void *, struct pt_regs *),
-                                   unsigned long flags, const char *device,
-                                   void *dev_id)
-{
-	return request_irq(irq, handler, SA_SHIRQ, device, dev_id);
-}			
-
-static void workpad_ide_free_irq(unsigned int irq, void *dev_id)
-{
-	free_irq(irq, dev_id);
-}
-
-static int workpad_ide_check_region(ide_ioreg_t from, unsigned int extent)
-{
-	return check_region(from, extent);
-}
-
-static void workpad_ide_request_region(ide_ioreg_t from, unsigned int extent,
-                                       const char *name)
-{
-	request_region(from, extent, name);
-}
-
-static void workpad_ide_release_region(ide_ioreg_t from, unsigned int extent)
-{
-	release_region(from, extent);
-}
-
-struct ide_ops workpad_ide_ops = {
-	&workpad_ide_default_irq,
-	&workpad_ide_default_io_base,
-	&workpad_ide_init_hwif_ports,
-	&workpad_ide_request_irq,
-	&workpad_ide_free_irq,
-	&workpad_ide_check_region,
-	&workpad_ide_request_region,
-	&workpad_ide_release_region
-};
--- diff/arch/mips/vr41xx/nec-eagle/ide-eagle.c	2003-07-08 09:55:17.000000000 +0100
+++ source/arch/mips/vr41xx/nec-eagle/ide-eagle.c	1970-01-01 01:00:00.000000000 +0100
@@ -1,96 +0,0 @@
-/*
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * IDE routines for typical pc-like standard configurations
- * for the NEC Eagle/Hawk board.
- *
- * Copyright (C) 1998, 1999, 2001 by Ralf Baechle
- */
-/*
- * Changes:
- *  MontaVista Software Inc. <yyuasa@mvista.com> or <source@mvista.com>
- *  Fri,  5 Apr 2002
- *  - Added support for NEC Hawk.
- *
- *  MontaVista Software Inc. <yyuasa@mvista.com> or <source@mvista.com>
- *  Fri,  1 Mar 2002
- *  - Added support for NEC Eagle.
- */
-#include <linux/sched.h>
-#include <linux/ide.h>
-#include <linux/ioport.h>
-#include <linux/hdreg.h>
-#include <asm/ptrace.h>
-#include <asm/hdreg.h>
-
-static int eagle_ide_default_irq(ide_ioreg_t base)
-{
-	return 0;
-}
-
-static ide_ioreg_t eagle_ide_default_io_base(int index)
-{
-	return 0;
-}
-
-static void eagle_ide_init_hwif_ports(hw_regs_t *hw, ide_ioreg_t data_port,
-                                      ide_ioreg_t ctrl_port, int *irq)
-{
-	ide_ioreg_t reg = data_port;
-	int i;
-
-	for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++) {
-		hw->io_ports[i] = reg;
-		reg += 1;
-	}
-	if (ctrl_port) {
-		hw->io_ports[IDE_CONTROL_OFFSET] = ctrl_port;
-	} else {
-		hw->io_ports[IDE_CONTROL_OFFSET] = hw->io_ports[IDE_DATA_OFFSET] + 0x206;
-	}
-	if (irq != NULL)
-		*irq = 0;
-	hw->io_ports[IDE_IRQ_OFFSET] = 0;
-}
-
-static int eagle_ide_request_irq(unsigned int irq,
-                                 void (*handler)(int,void *, struct pt_regs *),
-                                 unsigned long flags, const char *device,
-                                 void *dev_id)
-{
-	return request_irq(irq, handler, SA_SHIRQ, device, dev_id);
-}
-
-static void eagle_ide_free_irq(unsigned int irq, void *dev_id)
-{
-	free_irq(irq, dev_id);
-}
-
-static int eagle_ide_check_region(ide_ioreg_t from, unsigned int extent)
-{
-	return check_region(from, extent);
-}
-
-static void eagle_ide_request_region(ide_ioreg_t from, unsigned int extent,
-                                     const char *name)
-{
-	request_region(from, extent, name);
-}
-
-static void eagle_ide_release_region(ide_ioreg_t from, unsigned int extent)
-{
-	release_region(from, extent);
-}
-
-struct ide_ops eagle_ide_ops = {
-	&eagle_ide_default_irq,
-	&eagle_ide_default_io_base,
-	&eagle_ide_init_hwif_ports,
-	&eagle_ide_request_irq,
-	&eagle_ide_free_irq,
-	&eagle_ide_check_region,
-	&eagle_ide_request_region,
-	&eagle_ide_release_region
-};
--- diff/arch/mips/vr41xx/victor-mpc30x/ide-mpc30x.c	2003-07-08 09:55:17.000000000 +0100
+++ source/arch/mips/vr41xx/victor-mpc30x/ide-mpc30x.c	1970-01-01 01:00:00.000000000 +0100
@@ -1,91 +0,0 @@
-/*
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * IDE routines for typical pc-like standard configurations
- * for the ZAO Networks Capcella.
- *
- * Copyright (C) 1998, 1999, 2001 by Ralf Baechle
- */
-/*
- * Changes:
- *  Yoichi Yuasa <yuasa@hh.iij4u.or.jp>  Fri, 23 Aug 2002
- *  - Added Victor MP-C303/304 support.
- */
-#include <linux/sched.h>
-#include <linux/ide.h>
-#include <linux/ioport.h>
-#include <linux/hdreg.h>
-#include <asm/ptrace.h>
-#include <asm/hdreg.h>
-
-static int mpc30x_ide_default_irq(ide_ioreg_t base)
-{
-	return 0;
-}
-
-static ide_ioreg_t mpc30x_ide_default_io_base(int index)
-{
-	return 0;
-}
-
-static void mpc30x_ide_init_hwif_ports(hw_regs_t *hw, ide_ioreg_t data_port,
-                                       ide_ioreg_t ctrl_port, int *irq)
-{
-	ide_ioreg_t reg = data_port;
-	int i;
-
-	for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++) {
-		hw->io_ports[i] = reg;
-		reg += 1;
-	}
-	if (ctrl_port) {
-		hw->io_ports[IDE_CONTROL_OFFSET] = ctrl_port;
-	} else {
-		hw->io_ports[IDE_CONTROL_OFFSET] = hw->io_ports[IDE_DATA_OFFSET] + 0x206;
-	}
-	if (irq != NULL)
-		*irq = 0;
-	hw->io_ports[IDE_IRQ_OFFSET] = 0;
-}
-
-static int mpc30x_ide_request_irq(unsigned int irq,
-                                  void (*handler)(int,void *, struct pt_regs *),
-                                  unsigned long flags, const char *device,
-                                  void *dev_id)
-{
-	return request_irq(irq, handler, flags, device, dev_id);
-}
-
-static void mpc30x_ide_free_irq(unsigned int irq, void *dev_id)
-{
-	free_irq(irq, dev_id);
-}
-
-static int mpc30x_ide_check_region(ide_ioreg_t from, unsigned int extent)
-{
-	return check_region(from, extent);
-}
-
-static void mpc30x_ide_request_region(ide_ioreg_t from, unsigned int extent,
-                                      const char *name)
-{
-	request_region(from, extent, name);
-}
-
-static void mpc30x_ide_release_region(ide_ioreg_t from, unsigned int extent)
-{
-	release_region(from, extent);
-}
-
-struct ide_ops mpc30x_ide_ops = {
-	&mpc30x_ide_default_irq,
-	&mpc30x_ide_default_io_base,
-	&mpc30x_ide_init_hwif_ports,
-	&mpc30x_ide_request_irq,
-	&mpc30x_ide_free_irq,
-	&mpc30x_ide_check_region,
-	&mpc30x_ide_request_region,
-	&mpc30x_ide_release_region
-};
--- diff/arch/mips/vr41xx/zao-capcella/ide-capcella.c	2003-07-08 09:55:17.000000000 +0100
+++ source/arch/mips/vr41xx/zao-capcella/ide-capcella.c	1970-01-01 01:00:00.000000000 +0100
@@ -1,99 +0,0 @@
-/*
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * IDE routines for typical pc-like standard configurations
- * for the ZAO Networks Capcella.
- *
- * Copyright (C) 1998, 1999, 2001 by Ralf Baechle
- */
-/*
- * Changes:
- *  Yoichi Yuasa <yuasa@hh.iij4u.or.jp>  Sun, 24 Feb 2002
- *  - Added ZAO Networks Capcella support.
- */
-#include <linux/sched.h>
-#include <linux/ide.h>
-#include <linux/ioport.h>
-#include <linux/hdreg.h>
-#include <asm/ptrace.h>
-#include <asm/hdreg.h>
-
-static int capcella_ide_default_irq(ide_ioreg_t base)
-{
-	switch (base) {
-	case 0x8300: return 42;
-	}
-
-	return 0;
-}
-
-static ide_ioreg_t capcella_ide_default_io_base(int index)
-{
-	switch (index) {
-	case 0: return 0x8300;
-	}
-
-	return 0;
-}
-
-static void capcella_ide_init_hwif_ports(hw_regs_t *hw, ide_ioreg_t data_port,
-                                         ide_ioreg_t ctrl_port, int *irq)
-{
-	ide_ioreg_t reg = data_port;
-	int i;
-
-	for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++) {
-		hw->io_ports[i] = reg;
-		reg += 1;
-	}
-	if (ctrl_port) {
-		hw->io_ports[IDE_CONTROL_OFFSET] = ctrl_port;
-	} else {
-		hw->io_ports[IDE_CONTROL_OFFSET] = hw->io_ports[IDE_DATA_OFFSET] + 0x206;
-	}
-	if (irq != NULL)
-		*irq = 0;
-	hw->io_ports[IDE_IRQ_OFFSET] = 0;
-}
-
-static int capcella_ide_request_irq(unsigned int irq,
-                                    void (*handler)(int,void *, struct pt_regs *),
-                                    unsigned long flags, const char *device,
-                                    void *dev_id)
-{
-	return request_irq(irq, handler, flags, device, dev_id);
-}
-
-static void capcella_ide_free_irq(unsigned int irq, void *dev_id)
-{
-	free_irq(irq, dev_id);
-}
-
-static int capcella_ide_check_region(ide_ioreg_t from, unsigned int extent)
-{
-	return check_region(from, extent);
-}
-
-static void capcella_ide_request_region(ide_ioreg_t from, unsigned int extent,
-                                        const char *name)
-{
-	request_region(from, extent, name);
-}
-
-static void capcella_ide_release_region(ide_ioreg_t from, unsigned int extent)
-{
-	release_region(from, extent);
-}
-
-struct ide_ops capcella_ide_ops = {
-	&capcella_ide_default_irq,
-	&capcella_ide_default_io_base,
-	&capcella_ide_init_hwif_ports,
-	&capcella_ide_request_irq,
-	&capcella_ide_free_irq,
-	&capcella_ide_check_region,
-	&capcella_ide_request_region,
-	&capcella_ide_release_region
-};
--- diff/drivers/input/misc/gsc_ps2.c	2003-07-22 18:54:27.000000000 +0100
+++ source/drivers/input/misc/gsc_ps2.c	1970-01-01 01:00:00.000000000 +0100
@@ -1,712 +0,0 @@
-/*
- * drivers/input/misc/gsc_ps2.c
- *
- * Copyright (c) 2002 Laurent Canet <canetl@esiee.fr>
- * Copyright (c) 2002 Thibaut Varene <varenet@esiee.fr>
- *
- * Pieces of code based on linux-2.4's hp_mouse.c & hp_keyb.c
- * 	Copyright (c) 1999 Alex deVries <adevries@thepuffingroup.com>
- *	Copyright (c) 1999-2000 Philipp Rumpf <prumpf@tux.org>
- *	Copyright (c) 2000 Xavier Debacker <debackex@esiee.fr>
- *	Copyright (c) 2000-2001 Thomas Marteau <marteaut@esiee.fr>
- *
- * HP PS/2 Keyboard, found in PA/RISC Workstations
- * very similar to AT keyboards, but without i8042
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- * 
- * STATUS:
- * 11/09: lc: Only basic keyboard is supported, mouse still needs to be done.
- * 11/12: tv: switching iomapping; cleaning code; improving module stuff.
- * 11/13: lc & tv: leds aren't working. auto_repeat/meta are. Generaly good behavior.
- * 11/15: tv: 2AM: leds ARE working !
- * 11/16: tv: 3AM: escaped keycodes emulation *handled*, some keycodes are
- *	  still deliberately ignored (18), what are they used for ?
- * 11/21: lc: mouse is now working
- * 11/29: tv: first try for error handling in init sequence
- *
- * TODO:
- * Error handling in init sequence
- * SysRq handling
- * Pause key handling
- * Intellimouse & other rodents handling (at least send an error when
- * such a mouse is plugged : it will totally fault)
- * Mouse: set scaling / Dino testing
- * Bug chasing...
- *
- */
-
-#include <linux/input.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/ptrace.h>       /* interrupt.h wants struct pt_regs defined */
-#include <linux/interrupt.h>
-#include <linux/sched.h>        /* for request_irq/free_irq */        
-#include <linux/spinlock.h>
-#include <linux/delay.h>
-#include <linux/ioport.h>
-#include <linux/kd.h>
-#include <linux/pci_ids.h>
-
-#include <asm/irq.h>
-#include <asm/io.h>
-#include <asm/parisc-device.h>
-
-/* Debugging stuff */
-#undef KBD_DEBUG
-#ifdef KBD_DEBUG
-	#define DPRINTK(fmt,args...) printk(KERN_DEBUG __FILE__ ":" fmt, ##args)
-#else 
-	#define DPRINTK(x,...)
-#endif
-
-
-/* 
- * Driver constants
- */
-
-/* PS/2 keyboard and mouse constants */
-#define AUX_RECONNECT		0xAA	/* PS/2 Mouse end of test successful */
-#define AUX_REPLY_ACK		0xFA
-#define AUX_ENABLE_DEV		0xF4	/* Enables aux device */
-
-/* Order of the mouse bytes coming to the host */
-#define PACKET_X		1
-#define PACKET_Y		2
-#define PACKET_CTRL		0
-
-#define GSC_MOUSE_OFFSET	0x0100	/* offset from keyboard to mouse port */
-#define GSC_DINO_OFFSET		0x800	/* offset for DINO controller versus LASI one */
-
-#define GSC_ID			0x00	/* ID and reset port offsets */
-#define GSC_RESET		0x00
-#define GSC_RCVDATA		0x04	/* receive and transmit port offsets */
-#define GSC_XMTDATA		0x04
-#define GSC_CONTROL		0x08	/* see: control register bits */
-#define GSC_STATUS		0x0C	/* see: status register bits */
-
-/* Control register bits */
-#define GSC_CTRL_ENBL		0x01	/* enable interface */
-#define GSC_CTRL_LPBXR		0x02	/* loopback operation */
-#define GSC_CTRL_DIAG		0x20	/* directly control clock/data line */
-#define GSC_CTRL_DATDIR		0x40	/* data line direct control */
-#define GSC_CTRL_CLKDIR		0x80	/* clock line direct control */
-
-/* Status register bits */
-#define GSC_STAT_RBNE		0x01	/* Receive Buffer Not Empty */
-#define GSC_STAT_TBNE		0x02	/* Transmit Buffer Not Empty */
-#define GSC_STAT_TERR		0x04	/* Timeout Error */
-#define GSC_STAT_PERR		0x08	/* Parity Error */
-#define GSC_STAT_CMPINTR	0x10	/* Composite Interrupt */
-#define GSC_STAT_DATSHD		0x40	/* Data Line Shadow */
-#define GSC_STAT_CLKSHD		0x80	/* Clock Line Shadow */
-
-/* Keycode map */
-#define KBD_ESCAPE0		0xe0
-#define KBD_ESCAPE1		0xe1
-#define KBD_RELEASE		0xf0
-#define KBD_ACK			0xfa
-#define KBD_RESEND		0xfe
-#define KBD_UNKNOWN		0
-
-#define KBD_TBLSIZE		512
-
-/* Mouse */
-#define MOUSE_LEFTBTN		0x1
-#define MOUSE_MIDBTN		0x4
-#define MOUSE_RIGHTBTN		0x2
-#define MOUSE_ALWAYS1		0x8
-#define MOUSE_XSIGN		0x10
-#define MOUSE_YSIGN		0x20
-#define MOUSE_XOVFLOW		0x40
-#define MOUSE_YOVFLOW		0x80
-
-/* Remnant of pc_keyb.h */
-#define KBD_CMD_SET_LEDS	0xED	/* Sets keyboard leds */
-#define KBD_CMD_SET_RATE	0xF3	/* Sets typematic rate */
-#define KBD_CMD_ENABLE		0xF4	/* Enables scanning */
-#define KBD_CMD_DISABLE		0xF5
-#define KBD_CMD_RESET		0xFF
-
-static unsigned char hpkeyb_keycode[KBD_TBLSIZE] =
-{
-	/* 00 */  KBD_UNKNOWN,  KEY_F9,        KBD_UNKNOWN,   KEY_F5,        KEY_F3,        KEY_F1,       KEY_F2,        KEY_F12,
-	/* 08 */  KBD_UNKNOWN,  KEY_F10,       KEY_F8,        KEY_F6,        KEY_F4,        KEY_TAB,      KEY_GRAVE,     KBD_UNKNOWN,
-	/* 10 */  KBD_UNKNOWN,  KEY_LEFTALT,   KEY_LEFTSHIFT, KBD_UNKNOWN,   KEY_LEFTCTRL,  KEY_Q,        KEY_1,         KBD_UNKNOWN,
-	/* 18 */  KBD_UNKNOWN,  KBD_UNKNOWN,   KEY_Z,         KEY_S,         KEY_A,         KEY_W,        KEY_2,         KBD_UNKNOWN,
-	/* 20 */  KBD_UNKNOWN,  KEY_C,         KEY_X,         KEY_D,         KEY_E,         KEY_4,        KEY_3,         KBD_UNKNOWN,
-	/* 28 */  KBD_UNKNOWN,  KEY_SPACE,     KEY_V,         KEY_F,         KEY_T,         KEY_R,        KEY_5,         KBD_UNKNOWN,
-	/* 30 */  KBD_UNKNOWN,  KEY_N,         KEY_B,         KEY_H,         KEY_G,         KEY_Y,        KEY_6,         KBD_UNKNOWN,
-	/* 38 */  KBD_UNKNOWN,  KBD_UNKNOWN,   KEY_M,         KEY_J,         KEY_U,         KEY_7,        KEY_8,         KBD_UNKNOWN,
-	/* 40 */  KBD_UNKNOWN,  KEY_COMMA,     KEY_K,         KEY_I,         KEY_O,         KEY_0,        KEY_9,         KBD_UNKNOWN,
-	/* 48 */  KBD_UNKNOWN,  KEY_DOT,       KEY_SLASH,     KEY_L,         KEY_SEMICOLON, KEY_P,        KEY_MINUS,     KBD_UNKNOWN,
-	/* 50 */  KBD_UNKNOWN,  KBD_UNKNOWN,   KEY_APOSTROPHE,KBD_UNKNOWN,   KEY_LEFTBRACE, KEY_EQUAL,    KBD_UNKNOWN,   KBD_UNKNOWN,
-	/* 58 */  KEY_CAPSLOCK, KEY_RIGHTSHIFT,KEY_ENTER,     KEY_RIGHTBRACE,KBD_UNKNOWN,   KEY_BACKSLASH,KBD_UNKNOWN,   KBD_UNKNOWN,
-	/* 60 */  KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,  KEY_BACKSPACE, KBD_UNKNOWN,
-	/* 68 */  KBD_UNKNOWN,  KEY_KP1,       KBD_UNKNOWN,   KEY_KP4,       KEY_KP7,       KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,
-	/* 70 */  KEY_KP0,      KEY_KPDOT,     KEY_KP2,       KEY_KP5,       KEY_KP6,       KEY_KP8,      KEY_ESC,       KEY_NUMLOCK,
-	/* 78 */  KEY_F11,      KEY_KPPLUS,    KEY_KP3,       KEY_KPMINUS,   KEY_KPASTERISK,KEY_KP9,      KEY_SCROLLLOCK,KEY_103RD,
-	/* 80 */  KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,   KEY_F7,        KBD_UNKNOWN,   KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,
-	/* 88 */  KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,
-	/* 90 */  KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,
-	/* 98 */  KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,
-	/* a0 */  KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,
-	/* a8 */  KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,
-	/* b0 */  KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,
-	/* b8 */  KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,
-	/* c0 */  KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,
-	/* c8 */  KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,
-	/* d0 */  KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,
-	/* d8 */  KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,
-	/* e0 */  KBD_ESCAPE0,  KBD_ESCAPE1,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,
-	/* e8 */  KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,
-	/* f0 */  KBD_RELEASE,  KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,
-	/* f8 */  KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_ACK,       KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,  KBD_RESEND,    KBD_UNKNOWN,
-/* These are offset for escaped keycodes */
-	/* 00 */  KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,
-	/* 08 */  KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,
-	/* 10 */  KBD_UNKNOWN,  KEY_RIGHTALT,  KBD_UNKNOWN,   KBD_UNKNOWN,   KEY_RIGHTCTRL, KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,
-	/* 18 */  KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,
-	/* 20 */  KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,
-	/* 28 */  KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,
-	/* 30 */  KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,
-	/* 38 */  KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,
-	/* 40 */  KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,
-	/* 48 */  KBD_UNKNOWN,  KBD_UNKNOWN,   KEY_KPSLASH,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,
-	/* 50 */  KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,
-	/* 58 */  KBD_UNKNOWN,  KBD_UNKNOWN,   KEY_KPENTER,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,
-	/* 60 */  KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,
-	/* 68 */  KBD_UNKNOWN,  KEY_END,       KBD_UNKNOWN,   KEY_LEFT,      KEY_HOME,      KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,
-	/* 70 */  KEY_INSERT,   KEY_DELETE,    KEY_DOWN,      KBD_UNKNOWN,   KEY_RIGHT,     KEY_UP,       KBD_UNKNOWN,   KBD_UNKNOWN,
-	/* 78 */  KBD_UNKNOWN,  KBD_UNKNOWN,   KEY_PAGEDOWN,  KBD_UNKNOWN,   KEY_SYSRQ,     KEY_PAGEUP,   KBD_UNKNOWN,   KBD_UNKNOWN,
-	/* 80 */  KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,
-	/* 88 */  KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,
-	/* 90 */  KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,
-	/* 98 */  KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,
-	/* a0 */  KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,
-	/* a8 */  KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,
-	/* b0 */  KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,
-	/* b8 */  KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,
-	/* c0 */  KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,
-	/* c8 */  KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,
-	/* d0 */  KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,
-	/* d8 */  KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,
-	/* e0 */  KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,
-	/* e8 */  KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,
-	/* f0 */  KBD_RELEASE,  KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,
-	/* f8 */  KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN
-};
-
-
-/* Keyboard struct */
-static struct {
-	struct input_dev dev;
-	char * addr;
-	unsigned int irq;
-	unsigned int scancode;
-	unsigned int escaped;
-	unsigned int released;
-	unsigned int initialized;
-}
-hpkeyb = {
-	.escaped = 0,
-	.released = 0,
-	.initialized = 0
-};
-
-/* Mouse struct */
-static struct {
-   	struct input_dev dev;
-	char * addr;
-	unsigned long irq;
-	unsigned long initialized;
-	int nbread;
-	unsigned char bytes[3];
-	unsigned long last;
-}
-hpmouse = {
-	.initialized = 0,
-	.nbread = 0
-};
-
-static spinlock_t gscps2_lock = SPIN_LOCK_UNLOCKED;
-
-
-/*
- * Various HW level routines
- */
-
-#define gscps2_readb_input(x)		readb(x+GSC_RCVDATA)
-#define gscps2_readb_control(x)		readb(x+GSC_CONTROL)
-#define gscps2_readb_status(x)		readb(x+GSC_STATUS)
-#define gscps2_writeb_control(x, y)	writeb(x, y+GSC_CONTROL)
-
-static inline void gscps2_writeb_output(u8 val, char * addr)
-{
-	int wait = 250;			/* Keyboard is expected to react within 250ms */
-
-	while (gscps2_readb_status(addr) & GSC_STAT_TBNE) {
-		if (!--wait)
-			return;		/* This should not happen */
-		mdelay(1);
-	}
-	writeb(val, addr+GSC_XMTDATA);
-}
-
-static inline unsigned char gscps2_wait_input(char * addr)
-{
-	int wait = 250;			/* Keyboard is expected to react within 250ms */
-
-	while (!(gscps2_readb_status(addr) & GSC_STAT_RBNE)) {
-		if (!--wait)
-			return 0;	/* This should not happen */
-		mdelay(1);
-	}
-	return gscps2_readb_input(addr);
-}
-
-static int gscps2_writeb_safe_output(u8 val)
-{
-	/* This function waits for keyboard's ACK */
-	u8 scanread = KBD_UNKNOWN;
-	int loop = 5;
-	
-	while (hpkeyb_keycode[scanread]!=KBD_ACK && --loop > 0) {	
-		gscps2_writeb_output(val, hpkeyb.addr);
-		mdelay(5);
-		scanread = gscps2_wait_input(hpkeyb.addr);
-	}
-	
-	if (loop <= 0)
-		return -1;
-	
-	return 0;
-}
-
-/* Reset the PS2 port */
-static void __init gscps2_reset(char * addr)
-{
-	/* reset the interface */
-	writeb(0xff, addr+GSC_RESET);
-	writeb(0x0 , addr+GSC_RESET);
-
-	/* enable it */
-	gscps2_writeb_control(gscps2_readb_control(addr) | GSC_CTRL_ENBL, addr);
-}
-
-
-/**
- * gscps2_kbd_docode() - PS2 Keyboard basic handler
- *
- * Receives a keyboard scancode, analyses it and sends it to the input layer.
- */
-
-static void gscps2_kbd_docode(struct pt_regs *regs)
-{
-	int scancode = gscps2_readb_input(hpkeyb.addr);
-	DPRINTK("rel=%d scancode=%d, esc=%d ", hpkeyb.released, scancode, hpkeyb.escaped);
-
-	/* Handle previously escaped scancodes */
-	if (hpkeyb.escaped == KBD_ESCAPE0)
-		scancode |= 0x100;	/* jump to the next 256 chars of the table */
-		
-	switch (hpkeyb_keycode[scancode]) {
-		case KBD_RELEASE:
-			DPRINTK("release\n");
-			hpkeyb.released = 1;
-			break;
-		case KBD_RESEND:
-			DPRINTK("resend request\n");
-			break;
-		case KBD_ACK:
-			DPRINTK("ACK\n");
-			break;
-		case KBD_ESCAPE0:
-		case KBD_ESCAPE1:
-			DPRINTK("escape code %d\n", hpkeyb_keycode[scancode]);
-			hpkeyb.escaped = hpkeyb_keycode[scancode];
-			break;
-		case KBD_UNKNOWN:
-			DPRINTK("received unknown scancode %d, escape %d.\n",
-				scancode, hpkeyb.escaped);	/* This is a DPRINTK atm since we do not handle escaped scancodes cleanly */
-			if (hpkeyb.escaped)
-			hpkeyb.escaped = 0;
-			if (hpkeyb.released)
-				hpkeyb.released = 0;
-			return;
-		default:
-			hpkeyb.scancode = scancode;
-			DPRINTK("sent=%d, rel=%d\n",hpkeyb.scancode, hpkeyb.released);
-			/*input_regs(regs);*/
-			input_report_key(&hpkeyb.dev, hpkeyb_keycode[hpkeyb.scancode], !hpkeyb.released);
-			input_sync(&hpkeyb.dev);
-			if (hpkeyb.escaped)
-				hpkeyb.escaped = 0;
-			if (hpkeyb.released) 
-				hpkeyb.released = 0;
-			break;	
-	}
-}
-
-
-/**
- * gscps2_mouse_docode() - PS2 Mouse basic handler
- *
- * Receives mouse codes, processes them by packets of three, and sends
- * correct events to the input layer.
- */
-
-static void gscps2_mouse_docode(struct pt_regs *regs)
-{
-	int xrel, yrel;
-
-	/* process BAT (end of basic tests) command */
-	if ((hpmouse.nbread == 1) && (hpmouse.bytes[0] == AUX_RECONNECT))
-		hpmouse.nbread--;
-
-	/* stolen from psmouse.c */
-	if (hpmouse.nbread && time_after(jiffies, hpmouse.last + HZ/2)) {
-		printk(KERN_DEBUG "%s:%d : Lost mouse synchronization, throwing %d bytes away.\n", __FILE__, __LINE__,
-				hpmouse.nbread);
-		hpmouse.nbread = 0;
-	}
-
-	hpmouse.last = jiffies;
-	hpmouse.bytes[hpmouse.nbread++] = gscps2_readb_input(hpmouse.addr);
-	
-	/* process packet */
-	if (hpmouse.nbread == 3) {
-		
-		if (!(hpmouse.bytes[PACKET_CTRL] & MOUSE_ALWAYS1))
-			DPRINTK("Mouse: error on packet always1 bit checking\n");
-			/* XXX should exit now, bad data on the line! */
-		
-		if ((hpmouse.bytes[PACKET_CTRL] & (MOUSE_XOVFLOW | MOUSE_YOVFLOW)))
-			DPRINTK("Mouse: position overflow\n");
-		
-		/*input_regs(regs);*/
-
-		input_report_key(&hpmouse.dev, BTN_LEFT, hpmouse.bytes[PACKET_CTRL] & MOUSE_LEFTBTN);
-		input_report_key(&hpmouse.dev, BTN_MIDDLE, hpmouse.bytes[PACKET_CTRL] & MOUSE_MIDBTN);
-		input_report_key(&hpmouse.dev, BTN_RIGHT, hpmouse.bytes[PACKET_CTRL] & MOUSE_RIGHTBTN);
-		
-		xrel = hpmouse.bytes[PACKET_X];
-		yrel = hpmouse.bytes[PACKET_Y];
-		
-		/* Data sent by mouse are 9-bit signed, the sign bit is in the control packet */
-		if (xrel && (hpmouse.bytes[PACKET_CTRL] & MOUSE_XSIGN))
-			xrel = xrel - 0x100;
-		if (yrel && (hpmouse.bytes[PACKET_CTRL] & MOUSE_YSIGN))
-			yrel = yrel - 0x100;
-		
-		input_report_rel(&hpmouse.dev, REL_X, xrel);
-		input_report_rel(&hpmouse.dev, REL_Y, -yrel);	/* Y axis is received upside-down */
-		
-		input_sync(&hpmouse.dev);
-		
-		hpmouse.nbread = 0;
-	}
-}
-
-
-/**
- * gscps2_interrupt() - Interruption service routine
- *
- * This processes the list of scancodes queued and sends appropriate
- * key value to the system.
- */
-
-static irqreturn_t gscps2_interrupt(int irq, void *dev, struct pt_regs *reg)
-{
-	/* process mouse actions */
-	while (gscps2_readb_status(hpmouse.addr) & GSC_STAT_RBNE)
-		gscps2_mouse_docode(reg);
-	
-	/* process keyboard scancode */
-	while (gscps2_readb_status(hpkeyb.addr) & GSC_STAT_RBNE)
-		gscps2_kbd_docode(reg);
-
-	return IRQ_HANDLED;
-}
-
-
-/**
- * gscps2_hpkeyb_event() - Event handler
- * @return: success/error report
- *
- * Currently only updates leds on keyboard
- */
-
-int gscps2_hpkeyb_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)
-{
-	DPRINTK("Calling %s, type=%d, code=%d, value=%d\n",
-			__FUNCTION__, type, code, value);
-
-	if (!hpkeyb.initialized)
-		return -1;
-
-	if (type == EV_LED) {
-		u8 leds[2];
-
-		if (gscps2_writeb_safe_output(KBD_CMD_SET_LEDS)) {
-			printk(KERN_ERR "gsckbd_leds: timeout\n");
-			return -1;
-		}
-		DPRINTK("KBD_CMD_SET_LEDS\n");
-
-		*leds = (test_bit(LED_SCROLLL, dev->led) ? LED_SCR : 0)
-			| (test_bit(LED_NUML,    dev->led) ? LED_NUM : 0)
-			| (test_bit(LED_CAPSL,   dev->led) ? LED_CAP : 0);
-		DPRINTK("Sending leds=%x\n", *leds);
-		
-		if (gscps2_writeb_safe_output(*leds)) {
-			printk(KERN_ERR "gsckbd_leds: timeout\n");
-			return -1;
-		}
-		DPRINTK("leds sent\n");
-		
-		if (gscps2_writeb_safe_output(KBD_CMD_ENABLE)) {
-			printk(KERN_ERR "gsckbd_leds: timeout\n");
-			return -1;
-		}
-		DPRINTK("End\n");
-
-		return 0;
-
-	}
-	return -1;
-}
-
-
-/**
- * gscps2_kbd_probe() - Probes keyboard device and init input_dev structure
- * @return: number of device initialized (1, 0 on error)
- */
-
-static int __init gscps2_kbd_probe(void)
-{
-	int i, res = 0;
-	unsigned long flags;
-
-	if (hpkeyb.initialized) {
-		printk(KERN_ERR "GSC PS/2 keyboard driver already registered\n");
-		return 0;
-	}
-	
-	spin_lock_irqsave(&gscps2_lock, flags);
- 
-	if (!gscps2_writeb_safe_output(KBD_CMD_SET_LEDS)	&&
-	    !gscps2_writeb_safe_output(0)			&&
-	    !gscps2_writeb_safe_output(KBD_CMD_ENABLE))
-		res = 1;
- 
-	spin_unlock_irqrestore(&gscps2_lock, flags);
-
-	if (!res)
-		printk(KERN_ERR "Keyboard initialization sequence failled\n");
-	
-	init_input_dev(&hpkeyb.dev);
-	
-	for (i = 0; i < KBD_TBLSIZE; i++)
-		if (hpkeyb_keycode[i] != KBD_UNKNOWN)
-			set_bit(hpkeyb_keycode[i], hpkeyb.dev.keybit);
-		
-	hpkeyb.dev.evbit[0]	= BIT(EV_KEY) | BIT(EV_LED) | BIT(EV_REP);
-	hpkeyb.dev.ledbit[0]	= BIT(LED_NUML) | BIT(LED_CAPSL) | BIT(LED_SCROLLL);
-	hpkeyb.dev.keycode	= hpkeyb_keycode;
-	hpkeyb.dev.keycodesize	= sizeof(unsigned char);
-	hpkeyb.dev.keycodemax	= KBD_TBLSIZE;
-	hpkeyb.dev.name		= "GSC Keyboard";
-	hpkeyb.dev.phys		= "hpkbd/input0";
-
-	hpkeyb.dev.event	= gscps2_hpkeyb_event;
-	
-	/* TODO These need some adjustement, are they really useful ? */
-	hpkeyb.dev.id.bustype	= BUS_GSC;
-	hpkeyb.dev.id.vendor	= PCI_VENDOR_ID_HP;
-	hpkeyb.dev.id.product	= 0x0001;
-	hpkeyb.dev.id.version	= 0x0010;
-	hpkeyb.initialized	= 1;
-
-	return 1;
-}
-
-
-/**
- * gscps2_mouse_probe() - Probes mouse device and init input_dev structure
- * @return: number of device initialized (1, 0 on error)
- *
- * Currently no check on initialization is performed
- */
-
-static int __init gscps2_mouse_probe(void)
-{
-	if (hpmouse.initialized) {
-		printk(KERN_ERR "GSC PS/2 Mouse driver already registered\n");
-		return 0;
-	}
-	
-	init_input_dev(&hpmouse.dev);
-	
-	hpmouse.dev.name	= "GSC Mouse";
-	hpmouse.dev.phys	= "hpmouse/input0";
-   	hpmouse.dev.evbit[0] 	= BIT(EV_KEY) | BIT(EV_REL);
-	hpmouse.dev.keybit[LONG(BTN_MOUSE)] = BIT(BTN_LEFT) | BIT(BTN_MIDDLE) | BIT(BTN_RIGHT);
-	hpmouse.dev.relbit[0] 	= BIT(REL_X) | BIT(REL_Y);
-	hpmouse.last 		= 0;
-
-	gscps2_writeb_output(AUX_ENABLE_DEV, hpmouse.addr);
-	/* Try it a second time, this will give status if the device is available */
-	gscps2_writeb_output(AUX_ENABLE_DEV, hpmouse.addr);
-	
-	/* TODO These need some adjustement, are they really useful ? */
-	hpmouse.dev.id.bustype	= BUS_GSC;
-	hpmouse.dev.id.vendor	= 0x0001;
-	hpmouse.dev.id.product	= 0x0001;
-	hpmouse.dev.id.version	= 0x0010;
-	hpmouse.initialized = 1;
-	return 1;	/* XXX: we don't check if initialization failed */
-}
-
-
-/**
- * gscps2_probe() - Probes PS2 devices
- * @return: success/error report
- */
-
-static int __init gscps2_probe(struct parisc_device *dev)
-{
-	u8 id;
-	char *addr, *name;
-	int ret = 0, device_found = 0;
-	unsigned long hpa = dev->hpa;
-
-	if (!dev->irq)
-		goto fail_pitifully;
-	
-	/* Offset for DINO PS/2. Works with LASI even */
-	if (dev->id.sversion == 0x96)
-		hpa += GSC_DINO_OFFSET;
-
-	addr = ioremap(hpa, 256);
-	
-	if (!hpmouse.initialized || !hpkeyb.initialized)
-		gscps2_reset(addr);
-
-	ret = -EINVAL;
-	id = readb(addr+GSC_ID) & 0x0f;
-	switch (id) {
-		case 0:				/* keyboard */
-			hpkeyb.addr = addr;
-			name = "keyboard";
-			device_found = gscps2_kbd_probe();
-			break;
-		case 1:				/* mouse */
-			hpmouse.addr = addr;
-			name = "mouse";
-			device_found = gscps2_mouse_probe();
-			break;
-		default:
-			printk(KERN_WARNING "%s: Unsupported PS/2 port (id=%d) ignored\n",
-		    		__FUNCTION__, id);
-			goto fail_miserably;
-	}
-
-	/* No valid device found */
-	ret = -ENODEV;
-	if (!device_found)
-		goto fail_miserably;
-
-	/* Here we claim only if we have a device attached */
-	/* Allocate the irq and memory region for that device */
-	ret = -EBUSY;
-	if (request_irq(dev->irq, gscps2_interrupt, 0, name, NULL))
-		goto fail_miserably;
-
-	if (!request_mem_region(hpa, GSC_STATUS + 4, name))
-		goto fail_request_mem;
-	
-	/* Finalize input struct and register it */
-	switch (id) {
-		case 0:				/* keyboard */
-			hpkeyb.irq = dev->irq;
-			input_register_device(&hpkeyb.dev);	
-			break;
-		case 1:				/* mouse */
-			hpmouse.irq = dev->irq;
-			input_register_device(&hpmouse.dev);
-			break;
-		default:
-			break;
-	}
-
-	printk(KERN_INFO "input: PS/2 %s port at 0x%08lx (irq %d) found and attached\n",
-			name, hpa, dev->irq);
-
-	return 0;
-	
-fail_request_mem: free_irq(dev->irq, NULL);
-fail_miserably: iounmap(addr);
-fail_pitifully:	return ret;
-}
-
-
-
-static struct parisc_device_id gscps2_device_tbl[] = {
-	{ HPHW_FIO, HVERSION_REV_ANY_ID, HVERSION_ANY_ID, 0x00084 }, /* LASI PS/2 */
-/*	{ HPHW_FIO, HVERSION_REV_ANY_ID, HVERSION_ANY_ID, 0x00096 },  DINO PS/2 (XXX Not yet tested) */
-	{ 0, }	/* 0 terminated list */
-};
-
-static struct parisc_driver gscps2_driver = {
-	.name		= "GSC PS2",
-	.id_table	= gscps2_device_tbl,
-	.probe		= gscps2_probe,
-};
-
-static int __init gscps2_init(void)
-{
-	if (register_parisc_driver(&gscps2_driver))
-		return -EBUSY;
-	return 0;
-}
-
-static void __exit gscps2_exit(void)
-{
-	/* TODO this is probably not very good and needs to be checked */
-	if (hpkeyb.initialized) {
-		free_irq(hpkeyb.irq, gscps2_interrupt);
-		iounmap(hpkeyb.addr);
-		hpkeyb.initialized = 0;
-		input_unregister_device(&hpkeyb.dev);
-	}
-	if (hpmouse.initialized) {
-		free_irq(hpmouse.irq, gscps2_interrupt);
-		iounmap(hpmouse.addr);
-		hpmouse.initialized = 0;
-		input_unregister_device(&hpmouse.dev);
-	}
-	unregister_parisc_driver(&gscps2_driver);
-}
-
-
-MODULE_AUTHOR("Laurent Canet <canetl@esiee.fr>, Thibaut Varene <varenet@esiee.fr>");
-MODULE_DESCRIPTION("GSC PS/2 keyboard/mouse driver");
-MODULE_LICENSE("GPL");
-MODULE_DEVICE_TABLE(parisc, gscps2_device_tbl);
-
-
-module_init(gscps2_init);
-module_exit(gscps2_exit);
--- diff/drivers/isdn/hisax/cert.c	2002-10-16 04:28:32.000000000 +0100
+++ source/drivers/isdn/hisax/cert.c	1970-01-01 01:00:00.000000000 +0100
@@ -1,50 +0,0 @@
-/* $Id: cert.c,v 2.3.6.3 2001/09/23 22:24:47 kai Exp $
- *
- * Author       Karsten Keil
- * Copyright    by Karsten Keil      <keil@isdn4linux.de>
- * 
- * This software may be used and distributed according to the terms
- * of the GNU General Public License, incorporated herein by reference.
- *
- * For changes and modifications please read
- * ../../../Documentation/isdn/HiSax.cert
- *
- */
- 
-#include <linux/kernel.h>
-
-int
-certification_check(int output) {
-
-#ifdef CERTIFICATION
-#if CERTIFICATION == 0
-	if (output) {
-		printk(KERN_INFO "HiSax: Approval certification valid\n");
-		printk(KERN_INFO "HiSax: Approved with ELSA Microlink PCI cards\n");
-		printk(KERN_INFO "HiSax: Approved with Eicon Technology Diva 2.01 PCI cards\n");
-		printk(KERN_INFO "HiSax: Approved with Sedlbauer Speedfax + cards\n");
-		printk(KERN_INFO "HiSax: Approved with HFC-S PCI A based cards\n");
-	}
-	return(0);
-#endif
-#if CERTIFICATION == 1
-	if (output) {
-		printk(KERN_INFO "HiSax: Approval certification failed because of\n");
-		printk(KERN_INFO "HiSax: unauthorized source code changes\n");
-	}
-	return(1);
-#endif
-#if CERTIFICATION == 127
-	if (output) {
-		printk(KERN_INFO "HiSax: Approval certification not possible\n");
-		printk(KERN_INFO "HiSax: because \"md5sum\" is not available\n");
-	}
-	return(2);
-#endif
-#else
-	if (output) {
-		printk(KERN_INFO "HiSax: Certification not verified\n");
-	}
-	return(3);
-#endif
-}
--- diff/drivers/isdn/hisax/hisax_fcclassic.c	2003-06-09 14:18:18.000000000 +0100
+++ source/drivers/isdn/hisax/hisax_fcclassic.c	1970-01-01 01:00:00.000000000 +0100
@@ -1,385 +0,0 @@
-/*
- * Driver for AVM Fritz!classic (ISA) ISDN card
- *
- * Author       Kai Germaschewski
- * Copyright    2001 by Kai Germaschewski  <kai.germaschewski@gmx.de>
- *              2001 by Karsten Keil       <keil@isdn4linux.de>
- * 
- * based upon Karsten Keil's original avm_a1.c driver
- *
- * This software may be used and distributed according to the terms
- * of the GNU General Public License, incorporated herein by reference.
- *
- */
-
-
-#include <linux/version.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/pci.h>
-#include <linux/isapnp.h>
-#include <linux/kmod.h>
-#include <linux/slab.h>
-#include <linux/skbuff.h>
-#include <linux/netdevice.h>
-#include "hisax_fcclassic.h"
-
-// debugging cruft
-#define __debug_variable debug
-#include "hisax_debug.h"
-
-#ifdef CONFIG_HISAX_DEBUG
-static int debug = 0;
-MODULE_PARM(debug, "i");
-#endif
-
-MODULE_AUTHOR("Kai Germaschewski <kai.germaschewski@gmx.de>/Karsten Keil <kkeil@suse.de>");
-MODULE_DESCRIPTION("AVM Fritz!Card classic ISDN driver");
-
-static int protocol = 2;       /* EURO-ISDN Default */
-MODULE_PARM(protocol, "i");
-
-// ----------------------------------------------------------------------
-
-#define	 AVM_A1_STAT_ISAC	0x01
-#define	 AVM_A1_STAT_HSCX	0x02
-#define	 AVM_A1_STAT_TIMER	0x04
-
-// ----------------------------------------------------------------------
-
-static unsigned char
-fcclassic_read_isac(struct isac *isac, unsigned char offset)
-{
-	struct fritz_adapter *adapter = isac->priv;
-	unsigned char val;
-
-	val = inb(adapter->isac_base + offset);
-	DBG(0x1000, " port %#x, value %#x",
-	    offset, val);
-	return val;
-}
-
-static void
-fcclassic_write_isac(struct isac *isac, unsigned char offset,
-		     unsigned char value)
-{
-	struct fritz_adapter *adapter = isac->priv;
-
-	DBG(0x1000, " port %#x, value %#x",
-	    offset, value);
-	outb(value, adapter->isac_base + offset);
-}
-
-static void
-fcclassic_read_isac_fifo(struct isac *isac, unsigned char * data, int size)
-{
-	struct fritz_adapter *adapter = isac->priv;
-
-	insb(adapter->isac_fifo, data, size);
-}
-
-static void
-fcclassic_write_isac_fifo(struct isac *isac, unsigned char * data, int size)
-{
-	struct fritz_adapter *adapter = isac->priv;
-
-	outsb(adapter->isac_fifo, data, size);
-}
-
-static u8
-fcclassic_read_hscx(struct hscx *hscx, u8 offset)
-{
-	struct fritz_adapter *adapter = hscx->priv;
-
-	return inb(adapter->hscx_base[hscx->channel] + offset);
-}
-
-static void
-fcclassic_write_hscx(struct hscx *hscx, u8 offset, u8 value)
-{
-	struct fritz_adapter *adapter = hscx->priv;
-
-	outb(value, adapter->hscx_base[hscx->channel] + offset);
-}
-
-static void
-fcclassic_read_hscx_fifo(struct hscx *hscx, unsigned char * data, int size)
-{
-	struct fritz_adapter *adapter = hscx->priv;
-
-	insb(adapter->hscx_fifo[hscx->channel], data, size);
-}
-
-static void
-fcclassic_write_hscx_fifo(struct hscx *hscx, unsigned char * data, int size)
-{
-	struct fritz_adapter *adapter = hscx->priv;
-
-	outsb(adapter->hscx_fifo[hscx->channel], data, size);
-}
-
-// ----------------------------------------------------------------------
-
-static irqreturn_t
-fcclassic_irq(int intno, void *dev, struct pt_regs *regs)
-{
-	struct fritz_adapter *adapter = dev;
-	unsigned char sval;
-
-	DBG(2, "");
-	while ((sval = inb(adapter->cfg_reg) & 0xf) != 0x7) {
-		DBG(2, "sval %#x", sval);
-		if (!(sval & AVM_A1_STAT_TIMER)) {
-			outb(0x1e, adapter->cfg_reg);
-		}
-		if (!(sval & AVM_A1_STAT_HSCX)) {
-			hscx_irq(adapter->hscx);
-		}
-		if (!(sval & AVM_A1_STAT_ISAC)) {
-			isac_irq(&adapter->isac);
-		}
-	}
-	return IRQ_HANDLED;
-}
-
-// ----------------------------------------------------------------------
-
-static int __init
-fcclassic_setup(struct fritz_adapter *adapter)
-{
-	u32 val = 0;
-	int i;
-	int retval;
-
-	DBG(1,"");
-
-	isac_init(&adapter->isac); // FIXME is this okay now
-
-	adapter->cfg_reg      = adapter->io + 0x1800;
-	adapter->isac_base    = adapter->io + 0x1400 - 0x20;
-	adapter->isac_fifo    = adapter->io + 0x1000;
-	adapter->hscx_base[0] = adapter->io + 0x0400 - 0x20;
-	adapter->hscx_fifo[0] = adapter->io;
-	adapter->hscx_base[1] = adapter->io + 0x0c00 - 0x20;
-	adapter->hscx_fifo[1] = adapter->io + 0x0800;
-
-	retval = -EBUSY;
-	if (!request_region(adapter->cfg_reg            ,  8,
-			    "fcclassic cfg"))
-		goto err;
-	if (!request_region(adapter->isac_base + 0x20   , 32,
-			    "fcclassic isac"))
-		goto err_cfg_reg;
-	if (!request_region(adapter->isac_fifo          ,  1,
-			    "fcclassic isac fifo"))
-		goto err_isac_base;
-	if (!request_region(adapter->hscx_base[0] + 0x20, 32,
-			    "fcclassic hscx"))
-		goto err_isac_fifo;
-	if (!request_region(adapter->hscx_fifo[0]       ,  1,
-			    "fcclassic hscx fifo"))
-		goto err_hscx_base_0;
-	if (!request_region(adapter->hscx_base[1] + 0x20, 32,
-			    "fcclassic hscx"))
-		goto err_hscx_fifo_0;
-	if (!request_region(adapter->hscx_fifo[1]       ,  1,
-			    "fcclassic hscx fifo"))
-		goto err_hscx_base_1;
-	retval = request_irq(adapter->irq, fcclassic_irq,  0,
-			     "fcclassic", adapter);
-	if (retval)
-		goto err_hscx_fifo_1;
-
-	// Reset
-	outb(0x00, adapter->cfg_reg);
-	set_current_state(TASK_UNINTERRUPTIBLE);
-	schedule_timeout(200 * HZ / 1000); // 200 msec
-	outb(0x01, adapter->cfg_reg);
-	set_current_state(TASK_UNINTERRUPTIBLE);
-	schedule_timeout(200 * HZ / 1000); // 200 msec
-	outb(0x00, adapter->cfg_reg);
-	set_current_state(TASK_UNINTERRUPTIBLE);
-	schedule_timeout(200 * HZ / 1000); // 200 msec
-
-	val = adapter->irq;
-	if (val == 9)
-		val = 2;
-	outb(val, adapter->cfg_reg + 1);
-	set_current_state(TASK_UNINTERRUPTIBLE);
-	schedule_timeout(200 * HZ / 1000); // 200 msec
-	outb(0x00, adapter->cfg_reg);
-	set_current_state(TASK_UNINTERRUPTIBLE);
-	schedule_timeout(200 * HZ / 1000); // 200 msec
-
-	val = inb(adapter->cfg_reg);
-	printk(KERN_INFO "AVM A1: Byte at %x is %x\n",
-	       adapter->cfg_reg, val);
-	val = inb(adapter->cfg_reg + 3);
-	printk(KERN_INFO "AVM A1: Byte at %x is %x\n",
-	       adapter->cfg_reg + 3, val);
-	val = inb(adapter->cfg_reg + 2);
-	printk(KERN_INFO "AVM A1: Byte at %x is %x\n",
-	       adapter->cfg_reg + 2, val);
-	val = inb(adapter->cfg_reg);
-	printk(KERN_INFO "AVM A1: Byte at %x is %x\n",
-	       adapter->cfg_reg, val);
-
-	outb(0x16, adapter->cfg_reg);
-	outb(0x1e, adapter->cfg_reg);
-
-	adapter->isac.priv            = adapter;
-	adapter->isac.read_isac       = &fcclassic_read_isac;
-	adapter->isac.write_isac      = &fcclassic_write_isac;
-	adapter->isac.read_isac_fifo  = &fcclassic_read_isac_fifo;
-	adapter->isac.write_isac_fifo = &fcclassic_write_isac_fifo;
-	hisax_isac_setup(&adapter->isac);
-	for (i = 0; i < 2; i++) {
-		hscx_init(&adapter->hscx[i]);
-		adapter->hscx[i].priv            = adapter;
-		adapter->hscx[i].read_hscx       = &fcclassic_read_hscx;
-		adapter->hscx[i].write_hscx      = &fcclassic_write_hscx;
-		adapter->hscx[i].read_hscx_fifo  = &fcclassic_read_hscx_fifo;
-		adapter->hscx[i].write_hscx_fifo = &fcclassic_write_hscx_fifo;
-		hscx_setup(&adapter->hscx[i]);
-	}
-
-	return 0;
-
- err_hscx_fifo_1:
-	release_region(adapter->hscx_fifo[1]       ,  1);
- err_hscx_base_1:
-	release_region(adapter->hscx_base[1] + 0x20, 32);
- err_hscx_fifo_0:
-	release_region(adapter->hscx_fifo[0]       ,  1);
- err_hscx_base_0:
-	release_region(adapter->hscx_base[0] + 0x20, 32);
- err_isac_fifo:
-	release_region(adapter->isac_fifo          ,  1);
- err_isac_base:
-	release_region(adapter->isac_base    + 0x20, 32);
- err_cfg_reg:
-	release_region(adapter->cfg_reg            ,  8);
- err:
-	return retval;
-}
-
-static void __exit fcclassic_release(struct fritz_adapter *adapter)
-{
-	DBG(1,"");
-
-//	outb(0, adapter->io + AVM_STATUS0);
-	free_irq(adapter->irq, adapter);
-	release_region(adapter->hscx_fifo[1]       ,  1);
-	release_region(adapter->hscx_base[1] + 0x20, 32);
-	release_region(adapter->hscx_fifo[0]       ,  1);
-	release_region(adapter->hscx_base[0] + 0x20, 32);
-	release_region(adapter->isac_fifo          ,  1);
-	release_region(adapter->isac_base    + 0x20, 32);
-	release_region(adapter->cfg_reg            ,  8);
-}
-
-// ----------------------------------------------------------------------
-
-static struct fritz_adapter * __init 
-new_adapter(struct pci_dev *pdev)
-{
-	struct fritz_adapter *adapter;
-	struct hisax_b_if *b_if[2];
-	int i;
-
-	adapter = kmalloc(sizeof(struct fritz_adapter), GFP_KERNEL);
-	if (!adapter)
-		return NULL;
-
-	memset(adapter, 0, sizeof(struct fritz_adapter));
-
-	adapter->isac.hisax_d_if.owner = THIS_MODULE;
-	adapter->isac.hisax_d_if.ifc.priv = &adapter->isac;
-	adapter->isac.hisax_d_if.ifc.l2l1 = isac_d_l2l1;
-
-	for (i = 0; i < 2; i++) {
-	  //		adapter->hscx[i].adapter = adapter;
-		adapter->hscx[i].channel = i;
-		adapter->hscx[i].b_if.ifc.priv = &adapter->hscx[i];
-		adapter->hscx[i].b_if.ifc.l2l1 = hscx_b_l2l1;
-	}
-	pci_set_drvdata(pdev, adapter);
-
-	for (i = 0; i < 2; i++)
-		b_if[i] = &adapter->hscx[i].b_if;
-
-	hisax_register(&adapter->isac.hisax_d_if, b_if, "fcclassic", protocol);
-
-	return adapter;
-}
-
-static void
-delete_adapter(struct fritz_adapter *adapter)
-{
-	hisax_unregister(&adapter->isac.hisax_d_if);
-	kfree(adapter);
-}
-
-static int __init
-fcclassic_probe(struct pci_dev *pdev, const struct isapnp_device_id *ent)
-{
-	struct fritz_adapter *adapter;
-	int retval;
-
-	retval = -ENOMEM;
-	adapter = new_adapter(pdev);
-	if (!adapter)
-		goto err;
-
-	adapter->io = pdev->resource[0].start;
-	adapter->irq = pdev->irq_resource[0].start;
-
-	printk(KERN_INFO "hisax_fcclassic: found Fritz!Card classic at IO %#x irq %d\n",
-	       adapter->io, adapter->irq);
-
-	retval = fcclassic_setup(adapter);
-	if (retval)
-		goto err_free;
-
-	return 0;
-	
- err_free:
-	delete_adapter(adapter);
- err:
-	return retval;
-}
-
-static int __exit 
-fcclassic_remove(struct pci_dev *pdev)
-{
-	struct fritz_adapter *adapter = pci_get_drvdata(pdev);
-
-	fcclassic_release(adapter);
-	delete_adapter(adapter);
-
-	return 0;
-}
-
-static struct pci_dev isa_dev[4];
-
-static int __init
-hisax_fcclassic_init(void)
-{
-	printk(KERN_INFO "hisax_fcclassic: Fritz!Card classic ISDN driver v0.0.1\n");
-
-	isa_dev[0].resource[0].start = 0x300;
-	isa_dev[0].irq_resource[0].start = 7;
-
-	fcclassic_probe(isa_dev, NULL);
-
-	return 0;
-}
-
-static void __exit
-hisax_fcclassic_exit(void)
-{
-	fcclassic_remove(isa_dev);
-}
-
-module_init(hisax_fcclassic_init);
-module_exit(hisax_fcclassic_exit);
--- diff/drivers/isdn/hisax/hisax_fcclassic.h	2002-10-16 04:28:30.000000000 +0100
+++ source/drivers/isdn/hisax/hisax_fcclassic.h	1970-01-01 01:00:00.000000000 +0100
@@ -1,18 +0,0 @@
-#include "hisax_if.h"
-#include "hisax_isac.h"
-#include "hisax_hscx.h"
-
-#include <linux/pci.h>
-
-struct fritz_adapter {
-	unsigned int io;
-	unsigned int irq;
-	unsigned int cfg_reg;
-	unsigned int isac_base;
-	unsigned int isac_fifo;
-	unsigned int hscx_base[2];
-	unsigned int hscx_fifo[2];
-	struct isac isac;
-
-	struct hscx hscx[2];
-};
--- diff/drivers/isdn/hisax/hisax_hfcpci.c	2004-02-18 08:54:09.000000000 +0000
+++ source/drivers/isdn/hisax/hisax_hfcpci.c	1970-01-01 01:00:00.000000000 +0100
@@ -1,1645 +0,0 @@
-/*
- * Driver for HFC PCI based cards
- *
- * Author       Kai Germaschewski
- * Copyright    2002 by Kai Germaschewski  <kai.germaschewski@gmx.de>
- *              2000 by Karsten Keil       <keil@isdn4linux.de>
- *              2000 by Werner Cornelius   <werner@isdn4linux.de>
- * 
- * based upon Werner Cornelius's original hfc_pci.c driver
- *
- * This software may be used and distributed according to the terms
- * of the GNU General Public License, incorporated herein by reference.
- *
- */
-
-// XXX timer3
-
-#include <linux/version.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/pci.h>
-#include <linux/kmod.h>
-#include <linux/slab.h>
-#include <linux/skbuff.h>
-#include <linux/netdevice.h>
-#include <linux/delay.h>
-#include "hisax_hfcpci.h"
-
-// debugging cruft
-#define __debug_variable debug
-#include "hisax_debug.h"
-
-#ifdef CONFIG_HISAX_DEBUG
-static int debug = 0;
-MODULE_PARM(debug, "i");
-#endif
-
-MODULE_AUTHOR("Kai Germaschewski <kai.germaschewski@gmx.de>/Werner Cornelius <werner@isdn4linux.de>");
-MODULE_DESCRIPTION("HFC PCI ISDN driver");
-
-#define ID(ven, dev, name)                     \
-        { .vendor      = PCI_VENDOR_ID_##ven,    \
-	  .device      = PCI_DEVICE_ID_##dev,    \
-	  .subvendor   = PCI_ANY_ID,             \
-	  .subdevice   = PCI_ANY_ID,             \
-	  .class       = 0,                      \
-          .class_mask  = 0,                      \
-	  .driver_data = (unsigned long) name }
-
-static struct pci_device_id hfcpci_ids[] = {
-	ID(CCD,     CCD_2BD0,         "CCD/Billion/Asuscom 2BD0"),
-	ID(CCD,     CCD_B000,         "Billion B000"),
-	ID(CCD,     CCD_B006,         "Billion B006"),
-	ID(CCD,     CCD_B007,         "Billion B007"),
-	ID(CCD,     CCD_B008,         "Billion B008"),
-	ID(CCD,     CCD_B009,         "Billion B009"),
-	ID(CCD,     CCD_B00A,         "Billion B00A"),
-	ID(CCD,     CCD_B00B,         "Billion B00B"),
-	ID(CCD,     CCD_B00C,         "Billion B00C"),
-	ID(CCD,     CCD_B100,         "Seyeon"),
-	ID(ABOCOM,  ABOCOM_2BD1,      "Abocom/Magitek"),
-	ID(ASUSTEK, ASUSTEK_0675,     "Asuscom/Askey"),
-	ID(BERKOM,  BERKOM_T_CONCEPT, "German Telekom T-Concept"),
-	ID(BERKOM,  BERKOM_A1T,       "German Telekom A1T"),
-	ID(ANIGMA,  ANIGMA_MC145575,  "Motorola MC145575"),
-	ID(ZOLTRIX, ZOLTRIX_2BD0,     "Zoltrix 2BD0"),
-	ID(DIGI,    DIGI_DF_M_IOM2_E, "Digi DataFire Micro V IOM2 (Europe)"),
-	ID(DIGI,    DIGI_DF_M_E,      "Digi DataFire Micro V (Europe)"),
-	ID(DIGI,    DIGI_DF_M_IOM2_A, "Digi DataFire Micro V IOM2 (America)"),
-	ID(DIGI,    DIGI_DF_M_A,      "Digi DataFire Micro V (America)"),
-	{ } 
-};
-MODULE_DEVICE_TABLE(pci, hfcpci_ids);
-
-#undef ID
-
-static int protocol = 2;       /* EURO-ISDN Default */
-MODULE_PARM(protocol, "i");
-
-// ----------------------------------------------------------------------
-//
-
-#define DBG_WARN      0x0001
-#define DBG_INFO      0x0002
-#define DBG_IRQ       0x0010
-#define DBG_L1M       0x0020
-#define DBG_PR        0x0040
-#define DBG_D_XMIT    0x0100
-#define DBG_D_RECV    0x0200
-#define DBG_B_XMIT    0x1000
-#define DBG_B_RECV    0x2000
-
-/* memory window base address offset (in config space) */
-
-#define HFCPCI_MWBA      0x80
-
-/* GCI/IOM bus monitor registers */
-
-#define HCFPCI_C_I       0x08
-#define HFCPCI_TRxR      0x0C
-#define HFCPCI_MON1_D    0x28
-#define HFCPCI_MON2_D    0x2C
-
-
-/* GCI/IOM bus timeslot registers */
-
-#define HFCPCI_B1_SSL    0x80
-#define HFCPCI_B2_SSL    0x84
-#define HFCPCI_AUX1_SSL  0x88
-#define HFCPCI_AUX2_SSL  0x8C
-#define HFCPCI_B1_RSL    0x90
-#define HFCPCI_B2_RSL    0x94
-#define HFCPCI_AUX1_RSL  0x98
-#define HFCPCI_AUX2_RSL  0x9C
-
-/* GCI/IOM bus data registers */
-
-#define HFCPCI_B1_D      0xA0
-#define HFCPCI_B2_D      0xA4
-#define HFCPCI_AUX1_D    0xA8
-#define HFCPCI_AUX2_D    0xAC
-
-/* GCI/IOM bus configuration registers */
-
-#define HFCPCI_MST_EMOD  0xB4
-#define HFCPCI_MST_MODE	 0xB8
-#define HFCPCI_CONNECT 	 0xBC
-
-
-/* Interrupt and status registers */
-
-#define HFCPCI_FIFO_EN   0x44
-#define HFCPCI_TRM       0x48
-#define HFCPCI_B_MODE    0x4C
-#define HFCPCI_CHIP_ID   0x58
-#define HFCPCI_CIRM  	 0x60
-#define HFCPCI_CTMT	 0x64
-#define HFCPCI_INT_M1  	 0x68
-#define HFCPCI_INT_M2  	 0x6C
-#define HFCPCI_INT_S1  	 0x78
-#define HFCPCI_INT_S2  	 0x7C
-#define HFCPCI_STATUS  	 0x70
-
-/* S/T section registers */
-
-#define HFCPCI_STATES  	 0xC0
-#define HFCPCI_SCTRL  	 0xC4
-#define HFCPCI_SCTRL_E   0xC8
-#define HFCPCI_SCTRL_R   0xCC
-#define HFCPCI_SQ  	 0xD0
-#define HFCPCI_CLKDEL  	 0xDC
-#define HFCPCI_B1_REC    0xF0
-#define HFCPCI_B1_SEND   0xF0
-#define HFCPCI_B2_REC    0xF4
-#define HFCPCI_B2_SEND   0xF4
-#define HFCPCI_D_REC     0xF8
-#define HFCPCI_D_SEND    0xF8
-#define HFCPCI_E_REC     0xFC
-
-
-/* bits in status register (READ) */
-#define HFCPCI_PCI_PROC   0x02
-#define HFCPCI_NBUSY	  0x04 
-#define HFCPCI_TIMER_ELAP 0x10
-#define HFCPCI_STATINT	  0x20
-#define HFCPCI_FRAMEINT	  0x40
-#define HFCPCI_ANYINT	  0x80
-
-/* bits in CTMT (Write) */
-#define HFCPCI_CLTIMER    0x80
-#define HFCPCI_TIM3_125   0x04
-#define HFCPCI_TIM25      0x10
-#define HFCPCI_TIM50      0x14
-#define HFCPCI_TIM400     0x18
-#define HFCPCI_TIM800     0x1C
-#define HFCPCI_AUTO_TIMER 0x20
-#define HFCPCI_TRANSB2    0x02
-#define HFCPCI_TRANSB1    0x01
-
-/* bits in CIRM (Write) */
-#define HFCPCI_AUX_MSK    0x07
-#define HFCPCI_RESET  	  0x08
-#define HFCPCI_B1_REV     0x40
-#define HFCPCI_B2_REV     0x80
-
-/* bits in INT_M1 and INT_S1 */
-#define HFCPCI_INTS_B1TRANS  0x01
-#define HFCPCI_INTS_B2TRANS  0x02
-#define HFCPCI_INTS_DTRANS   0x04
-#define HFCPCI_INTS_B1REC    0x08
-#define HFCPCI_INTS_B2REC    0x10
-#define HFCPCI_INTS_DREC     0x20
-#define HFCPCI_INTS_L1STATE  0x40
-#define HFCPCI_INTS_TIMER    0x80
-
-/* bits in INT_M2 */
-#define HFCPCI_PROC_TRANS    0x01
-#define HFCPCI_GCI_I_CHG     0x02
-#define HFCPCI_GCI_MON_REC   0x04
-#define HFCPCI_IRQ_ENABLE    0x08
-#define HFCPCI_PMESEL        0x80
-
-/* bits in STATES */
-#define HFCPCI_STATE_MSK     0x0F
-#define HFCPCI_LOAD_STATE    0x10
-#define HFCPCI_ACTIVATE	     0x20
-#define HFCPCI_DO_ACTION     0x40
-#define HFCPCI_NT_G2_G3      0x80
-
-/* bits in HFCD_MST_MODE */
-#define HFCPCI_MASTER	     0x01
-#define HFCPCI_SLAVE         0x00
-/* remaining bits are for codecs control */
-
-/* bits in HFCD_SCTRL */
-#define SCTRL_B1_ENA	     0x01
-#define SCTRL_B2_ENA	     0x02
-#define SCTRL_MODE_TE        0x00
-#define SCTRL_MODE_NT        0x04
-#define SCTRL_LOW_PRIO	     0x08
-#define SCTRL_SQ_ENA	     0x10
-#define SCTRL_TEST	     0x20
-#define SCTRL_NONE_CAP	     0x40
-#define SCTRL_PWR_DOWN	     0x80
-
-/* bits in SCTRL_E  */
-#define HFCPCI_AUTO_AWAKE    0x01
-#define HFCPCI_DBIT_1        0x04
-#define HFCPCI_IGNORE_COL    0x08
-#define HFCPCI_CHG_B1_B2     0x80
-
-/* bits in FIFO_EN register */
-#define HFCPCI_FIFOEN_B1     0x03
-#define HFCPCI_FIFOEN_B2     0x0C
-#define HFCPCI_FIFOEN_DTX    0x10
-#define HFCPCI_FIFOEN_DRX    0x20
-#define HFCPCI_FIFOEN_B1TX   0x01
-#define HFCPCI_FIFOEN_B1RX   0x02
-#define HFCPCI_FIFOEN_B2TX   0x04
-#define HFCPCI_FIFOEN_B2RX   0x08
-
-/*
- * thresholds for transparent B-channel mode
- * change mask and threshold simultaneously
- */
-#define HFCPCI_BTRANS_THRESHOLD 128
-#define HFCPCI_BTRANS_THRESMASK 0x00
-
-#define CLKDEL_TE	0x0e	/* CLKDEL in TE mode */
-#define CLKDEL_NT	0x6c	/* CLKDEL in NT mode */
-
-#define MAX_D_FRAMES 0x10
-#define MAX_B_FRAMES 0x20
-#define B_FIFO_START 0x0200
-#define B_FIFO_END   0x2000
-#define B_FIFO_SIZE  (B_FIFO_END - B_FIFO_START)
-#define D_FIFO_START 0x0000
-#define D_FIFO_END   0x0200
-#define D_FIFO_SIZE  (D_FIFO_END - D_FIFO_START)
-
-// ----------------------------------------------------------------------
-// push messages to the upper layers
-
-static inline void D_L1L2(struct hfcpci_adapter *adapter, int pr, void *arg)
-{
-	struct hisax_if *ifc = (struct hisax_if *) &adapter->d_if;
-
-	DBG(DBG_PR, "pr %#x", pr);
-	ifc->l1l2(ifc, pr, arg);
-}
-
-static inline void B_L1L2(struct hfcpci_bcs *bcs, int pr, void *arg)
-{
-	struct hisax_if *ifc = (struct hisax_if *) &bcs->b_if;
-
-	DBG(DBG_PR, "pr %#x", pr);
-	ifc->l1l2(ifc, pr, arg);
-}
-
-// ----------------------------------------------------------------------
-// MMIO
-
-static inline void
-hfcpci_writeb(struct hfcpci_adapter *adapter, u8 b, unsigned char offset)
-{
-	writeb(b, adapter->mmio + offset);
-}
-
-static inline u8
-hfcpci_readb(struct hfcpci_adapter *adapter, unsigned char offset)
-{
-	return readb(adapter->mmio + offset);
-}
-
-// ----------------------------------------------------------------------
-// magic to define the various F/Z counter accesses
-
-#define DECL_B_F(r, f)                                                      \
-static inline u8                                                            \
-get_b_##r##_##f (struct hfcpci_bcs *bcs)                                    \
-{                                                                           \
-	u16 off = bcs->channel ? OFF_B2_##r##_##f : OFF_B1_##r##_##f;       \
-                                                                            \
-	return *(bcs->adapter->fifo + off);                                 \
-}                                                                           \
-                                                                            \
-static inline void                                                          \
-set_b_##r##_##f (struct hfcpci_bcs *bcs, u8 f)                              \
-{                                                                           \
-	u16 off = bcs->channel ? OFF_B2_##r##_##f : OFF_B1_##r##_##f;       \
-                                                                            \
-	*(bcs->adapter->fifo + off) = f;                                    \
-}
-
-#define OFF_B1_rx_f1 0x6080
-#define OFF_B2_rx_f1 0x6180
-#define OFF_B1_rx_f2 0x6081
-#define OFF_B2_rx_f2 0x6181
-
-#define OFF_B1_tx_f1 0x2080
-#define OFF_B2_tx_f1 0x2180
-#define OFF_B1_tx_f2 0x2081
-#define OFF_B2_tx_f2 0x2181
-
-DECL_B_F(rx, f1)
-DECL_B_F(rx, f2)
-DECL_B_F(tx, f1)
-DECL_B_F(tx, f2)
-
-#undef DECL_B_F
-
-#define DECL_B_Z(r, z)                                                      \
-static inline u16                                                           \
-get_b_##r##_##z (struct hfcpci_bcs *bcs, u8 f)                              \
-{                                                                           \
-	u16 off = bcs->channel ? OFF_B2_##r##_##z : OFF_B1_##r##_##z;       \
-                                                                            \
-	return le16_to_cpu(*((u16 *) (bcs->adapter->fifo + off + f * 4)));  \
-}                                                                           \
-                                                                            \
-static inline void                                                          \
-set_b_##r##_##z(struct hfcpci_bcs *bcs, u8 f, u16 z)                        \
-{                                                                           \
-	u16 off = bcs->channel ? OFF_B2_##r##_##z : OFF_B1_##r##_##z;       \
-                                                                            \
-	*((u16 *) (bcs->adapter->fifo + off + f * 4)) = cpu_to_le16(z);     \
-}
-
-#define OFF_B1_rx_z1 0x6000
-#define OFF_B2_rx_z1 0x6100
-#define OFF_B1_rx_z2 0x6002
-#define OFF_B2_rx_z2 0x6102
-
-#define OFF_B1_tx_z1 0x2000
-#define OFF_B2_tx_z1 0x2100
-#define OFF_B1_tx_z2 0x2002
-#define OFF_B2_tx_z2 0x2102
-
-DECL_B_Z(rx, z1)
-DECL_B_Z(rx, z2)
-DECL_B_Z(tx, z1)
-DECL_B_Z(tx, z2)
-
-#undef DECL_B_Z
-
-#define DECL_D_F(r, f)                                                      \
-static inline u8                                                            \
-get_d_##r##_##f (struct hfcpci_adapter *adapter)                            \
-{                                                                           \
-	u16 off = OFF_D_##r##_##f;                                          \
-                                                                            \
-	return *(adapter->fifo + off) & 0xf;                                \
-}                                                                           \
-                                                                            \
-static inline void                                                          \
-set_d_##r##_##f (struct hfcpci_adapter *adapter, u8 f)                      \
-{                                                                           \
-	u16 off = OFF_D_##r##_##f;                                          \
-                                                                            \
-	*(adapter->fifo + off) = f | 0x10;                                  \
-}
-
-#define OFF_D_rx_f1 0x60a0
-#define OFF_D_rx_f2 0x60a1
-
-#define OFF_D_tx_f1 0x20a0
-#define OFF_D_tx_f2 0x20a1
-
-DECL_D_F(rx, f1)
-DECL_D_F(rx, f2)
-DECL_D_F(tx, f1)
-DECL_D_F(tx, f2)
-
-#undef DECL_D_F
-
-#define DECL_D_Z(r, z)                                                      \
-static inline u16                                                           \
-get_d_##r##_##z (struct hfcpci_adapter *adapter, u8 f)                      \
-{                                                                           \
-	u16 off = OFF_D_##r##_##z;                                          \
-                                                                            \
-	return le16_to_cpu(*((u16 *) (adapter->fifo + off + (f | 0x10) * 4)));\
-}                                                                           \
-                                                                            \
-static inline void                                                          \
-set_d_##r##_##z(struct hfcpci_adapter *adapter, u8 f, u16 z)                \
-{                                                                           \
-	u16 off = OFF_D_##r##_##z;                                          \
-                                                                            \
-	*((u16 *) (adapter->fifo + off + (f | 0x10) * 4)) = cpu_to_le16(z); \
-}
-
-#define OFF_D_rx_z1 0x6080
-#define OFF_D_rx_z2 0x6082
-
-#define OFF_D_tx_z1 0x2080
-#define OFF_D_tx_z2 0x2082
-
-DECL_D_Z(rx, z1)
-DECL_D_Z(rx, z2)
-DECL_D_Z(tx, z1)
-DECL_D_Z(tx, z2)
-
-#undef DECL_B_Z
-
-// ----------------------------------------------------------------------
-// fill b / d fifos
-
-static inline void
-hfcpci_fill_d_fifo(struct hfcpci_adapter *adapter)
-{
-	u8 f1, f2;
-	u16 z1, z2;
-	int cnt, fcnt;
-	char *fifo_adr = adapter->fifo;
-	struct sk_buff *tx_skb = adapter->tx_skb;
-	
-	f1 = get_d_tx_f1(adapter);
-	f2 = get_d_tx_f2(adapter);
-	DBG(DBG_D_XMIT, "f1 %#x f2 %#x", f1, f2);
-
-	fcnt = f1 - f2;
-	if (fcnt < 0)
-		fcnt += MAX_D_FRAMES;
-	
-	if (fcnt) {
-		printk("BUG\n");
-		return;
-	}
-
-	z1 = get_d_tx_z1(adapter, f1);
-	z2 = get_d_tx_z2(adapter, f1); //XXX
-	DBG(DBG_D_XMIT, "z1 %#x z2 %#x", z1, z2);
-
-	cnt = z2 - z1;
-	if (cnt <= 0)
-		cnt += D_FIFO_SIZE;
-
-	if (tx_skb->len > cnt) {
-		printk("BUG\n");
-		return;
-	}
-
-	cnt = tx_skb->len;
-	if (z1 + cnt <= D_FIFO_END) {
-		memcpy(fifo_adr + z1, tx_skb->data, cnt);
-	} else {
-		memcpy(fifo_adr + z1, tx_skb->data, D_FIFO_END - z1);
-		memcpy(fifo_adr + D_FIFO_START, 
-		       tx_skb->data + (D_FIFO_END - z1), 
-		       cnt - (D_FIFO_END - z1));
-	}
-	z1 += cnt;
-	if (z1 >= D_FIFO_END)
-		z1 -= D_FIFO_SIZE;
-
-	f1 = (f1 + 1) & (MAX_D_FRAMES - 1);
-	mb();
-	set_d_tx_z1(adapter, f1, z1);
-	mb();
-	set_d_tx_f1(adapter, f1);
-}
-
-static inline void
-hfcpci_fill_b_fifo_hdlc(struct hfcpci_bcs *bcs)
-{
-	u8 f1, f2;
-	u16 z1, z2;
-	int cnt, fcnt;
-	char *fifo_adr = bcs->adapter->fifo + (bcs->channel ? 0x2000 : 0x0000);
-	struct sk_buff *tx_skb = bcs->tx_skb;
-	
-	f1 = get_b_tx_f1(bcs);
-	f2 = get_b_tx_f2(bcs);
-	DBG(DBG_B_XMIT, "f1 %#x f2 %#x", f1, f2);
-
-	fcnt = f1 - f2;
-	if (fcnt < 0)
-		fcnt += MAX_B_FRAMES;
-	
-	if (fcnt) {
-		printk("BUG\n");
-		return;
-	}
-
-	z1 = get_b_tx_z1(bcs, f1);
-	z2 = get_b_tx_z2(bcs, f1); //XXX
-	DBG(DBG_B_XMIT, "z1 %#x z2 %#x", z1, z2);
-
-	cnt = z2 - z1;
-	if (cnt <= 0)
-		cnt += B_FIFO_SIZE;
-
-	if (tx_skb->len > cnt) {
-		printk("BUG\n");
-		return;
-	}
-
-	cnt = tx_skb->len;
-	if (z1 + cnt <= B_FIFO_END) {
-		memcpy(fifo_adr + z1, tx_skb->data, cnt);
-	} else {
-		memcpy(fifo_adr + z1, tx_skb->data, B_FIFO_END - z1);
-		memcpy(fifo_adr + B_FIFO_START,
-		       tx_skb->data + (B_FIFO_END - z1), 
-		       cnt - (B_FIFO_END - z1));
-	}
-	z1 += cnt;
-	if (z1 >= B_FIFO_END)
-		z1 -= B_FIFO_SIZE;
-
-	f1 = (f1 + 1) & (MAX_B_FRAMES - 1);
-	mb();
-	set_b_tx_z1(bcs, f1, z1);
-	mb();
-	set_b_tx_f1(bcs, f1);
-}
-
-static inline void
-hfcpci_fill_b_fifo_trans(struct hfcpci_bcs *bcs)
-{
-	int cnt;
-	char *fifo_adr = bcs->adapter->fifo + (bcs->channel ? 0x2000 : 0x0000);
-	struct sk_buff *tx_skb = bcs->tx_skb;
-	u8 f1, f2;
-	u16 z1, z2;
-
-	f1 = get_b_tx_f1(bcs);
-	f2 = get_b_tx_f2(bcs);
-
-	if (f1 != f2)
-		BUG();
-
-	z1 = get_b_tx_z1(bcs, f1);
-	z2 = get_b_tx_z2(bcs, f1);
-
-	cnt = z2 - z1;
-	if (cnt <= 0)
-		cnt += B_FIFO_SIZE;
-
-	if (tx_skb->len > cnt)
-		BUG();
-
-	if (z1 + cnt <= B_FIFO_END) {
-		memcpy(fifo_adr + z1, tx_skb->data, cnt);
-	} else {
-		memcpy(fifo_adr + z1, tx_skb->data, B_FIFO_END - z1);
-		memcpy(fifo_adr + B_FIFO_START,
-		       tx_skb->data + (B_FIFO_END - z1), 
-		       cnt - (B_FIFO_END - z1));
-	}
-	z1 += cnt;
-	if (z1 >= B_FIFO_END)
-		z1 -= B_FIFO_SIZE;
-
-	mb();
-	set_b_tx_z1(bcs, f1, z1);
-}
-
-static inline void
-hfcpci_fill_b_fifo(struct hfcpci_bcs *bcs)
-{
-	if (!bcs->tx_skb) {
-		DBG(DBG_WARN, "?");
-		return;
-	}
-	
-	switch (bcs->mode) {
-	case L1_MODE_TRANS:
-		hfcpci_fill_b_fifo_trans(bcs);
-		break;
-	case L1_MODE_HDLC:
-		hfcpci_fill_b_fifo_hdlc(bcs);
-		break;
-	default:
-		DBG(DBG_WARN, "?");
-	}
-}
-
-static void hfcpci_clear_b_rx_fifo(struct hfcpci_bcs *bcs);
-static void hfcpci_clear_b_tx_fifo(struct hfcpci_bcs *bcs);
-
-static void
-hfcpci_b_mode(struct hfcpci_bcs *bcs, int mode)
-{
-	struct hfcpci_adapter *adapter = bcs->adapter;
-	
-	DBG(DBG_B_XMIT, "B%d mode %d --> %d",
-	    bcs->channel + 1, bcs->mode, mode);
-
-	if (bcs->mode == mode)
-		return;
-
-	switch (mode) {
-	case L1_MODE_NULL:
-		if (bcs->channel == 0) {
-			adapter->sctrl &= ~SCTRL_B1_ENA;
-			adapter->sctrl_r &= ~SCTRL_B1_ENA;
-			adapter->fifo_en &= ~HFCPCI_FIFOEN_B1;
-			adapter->int_m1 &= ~(HFCPCI_INTS_B1TRANS + HFCPCI_INTS_B1REC);
-		} else {
-			adapter->sctrl &= ~SCTRL_B2_ENA;
-			adapter->sctrl_r &= ~SCTRL_B2_ENA;
-			adapter->fifo_en &= ~HFCPCI_FIFOEN_B2;
-			adapter->int_m1 &= ~(HFCPCI_INTS_B2TRANS + HFCPCI_INTS_B2REC);
-		}
-		break;
-	case L1_MODE_TRANS:
-	case L1_MODE_HDLC:
-		hfcpci_clear_b_rx_fifo(bcs);
-		hfcpci_clear_b_tx_fifo(bcs);
-		if (bcs->channel == 0) {
-			adapter->sctrl |= SCTRL_B1_ENA;
-			adapter->sctrl_r |= SCTRL_B1_ENA;
-			adapter->fifo_en |= HFCPCI_FIFOEN_B1;
-			adapter->int_m1 |= (HFCPCI_INTS_B1TRANS + HFCPCI_INTS_B1REC);
-
-			if (mode == L1_MODE_TRANS)
-				adapter->ctmt |= 1;
-			else
-				adapter->ctmt &= ~1;
-
-		} else {
-			adapter->sctrl |= SCTRL_B2_ENA;
-			adapter->sctrl_r |= SCTRL_B2_ENA;
-			adapter->fifo_en |= HFCPCI_FIFOEN_B2;
-			adapter->int_m1 |= (HFCPCI_INTS_B2TRANS + HFCPCI_INTS_B2REC);
-
-			if (mode == L1_MODE_TRANS)
-				adapter->ctmt |= 2;
-			else
-				adapter->ctmt &= ~2;
-
-		}
-		break;
-	}
-	hfcpci_writeb(adapter, adapter->int_m1,  HFCPCI_INT_M1);
-	hfcpci_writeb(adapter, adapter->fifo_en, HFCPCI_FIFO_EN);
-	hfcpci_writeb(adapter, adapter->sctrl,   HFCPCI_SCTRL);
-	hfcpci_writeb(adapter, adapter->sctrl_r, HFCPCI_SCTRL_R);
-	hfcpci_writeb(adapter, adapter->ctmt,    HFCPCI_CTMT);
-	hfcpci_writeb(adapter, adapter->conn,    HFCPCI_CONNECT);
-
-	bcs->mode = mode;
-}
-
-// ----------------------------------------------------------------------
-// Layer 1 state machine
-
-static struct Fsm l1fsm;
-
-enum {
-	ST_L1_F0,
-	ST_L1_F2,
-	ST_L1_F3,
-	ST_L1_F4,
-	ST_L1_F5,
-	ST_L1_F6,
-	ST_L1_F7,
-	ST_L1_F8,
-};
-
-#define L1_STATE_COUNT (ST_L1_F8+1)
-
-static char *strL1State[] =
-{
-	"ST_L1_F0",
-	"ST_L1_F2",
-	"ST_L1_F3",
-	"ST_L1_F4",
-	"ST_L1_F5",
-	"ST_L1_F6",
-	"ST_L1_F7",
-	"ST_L1_F8",
-};
-
-enum {
-	EV_PH_F0,
-	EV_PH_1,
-	EV_PH_F2,
-	EV_PH_F3,
-	EV_PH_F4,
-	EV_PH_F5,
-	EV_PH_F6,
-	EV_PH_F7,
-	EV_PH_F8,
-	EV_PH_ACTIVATE_REQ,
-	EV_PH_DEACTIVATE_REQ,
-	EV_TIMER3,
-};
-
-#define L1_EVENT_COUNT (EV_TIMER3 + 1)
-
-static char *strL1Event[] =
-{
-	"EV_PH_F0",
-	"EV_PH_1",
-	"EV_PH_F2",
-	"EV_PH_F3",
-	"EV_PH_F4",
-	"EV_PH_F5",
-	"EV_PH_F6",
-	"EV_PH_F7",
-	"EV_PH_F8",
-	"EV_PH_ACTIVATE_REQ",
-	"EV_PH_DEACTIVATE_REQ",
-	"EV_TIMER3",
-};
-
-static void l1_ignore(struct FsmInst *fi, int event, void *arg)
-{
-}
-
-static void l1_go_f3(struct FsmInst *fi, int event, void *arg)
-{
-	FsmChangeState(fi, ST_L1_F3);
-}
-
-static void l1_go_f3_deact_ind(struct FsmInst *fi, int event, void *arg)
-{
-	struct hfcpci_adapter *adapter = fi->userdata;
-
-	FsmChangeState(fi, ST_L1_F3);
-	D_L1L2(adapter, PH_DEACTIVATE | INDICATION, NULL);
-}
-
-static void l1_go_f4(struct FsmInst *fi, int event, void *arg)
-{
-	FsmChangeState(fi, ST_L1_F3);
-}
-
-static void l1_go_f5(struct FsmInst *fi, int event, void *arg)
-{
-	FsmChangeState(fi, ST_L1_F3);
-}
-
-static void l1_go_f6(struct FsmInst *fi, int event, void *arg)
-{
-	FsmChangeState(fi, ST_L1_F6);
-}
-
-static void l1_go_f6_deact_ind(struct FsmInst *fi, int event, void *arg)
-{
-	struct hfcpci_adapter *adapter = fi->userdata;
-
-	FsmChangeState(fi, ST_L1_F6);
-	D_L1L2(adapter, PH_DEACTIVATE | INDICATION, NULL);
-}
-
-static void l1_go_f7(struct FsmInst *fi, int event, void *arg)
-{
-	FsmChangeState(fi, ST_L1_F7);
-}
-
-static void l1_go_f7_act_ind(struct FsmInst *fi, int event, void *arg)
-{
-	struct hfcpci_adapter *adapter = fi->userdata;
-
-	FsmChangeState(fi, ST_L1_F7);
-	D_L1L2(adapter, PH_ACTIVATE | INDICATION, NULL);
-}
-
-static void l1_go_f8(struct FsmInst *fi, int event, void *arg)
-{
-	FsmChangeState(fi, ST_L1_F8);
-}
-
-static void l1_go_f8_deact_ind(struct FsmInst *fi, int event, void *arg)
-{
-	struct hfcpci_adapter *adapter = fi->userdata;
-
-	FsmChangeState(fi, ST_L1_F8);
-	D_L1L2(adapter, PH_DEACTIVATE | INDICATION, NULL);
-}
-
-static void l1_act_req(struct FsmInst *fi, int event, void *arg)
-{
-	struct hfcpci_adapter *adapter = fi->userdata;
-
-	hfcpci_writeb(adapter, HFCPCI_ACTIVATE | HFCPCI_DO_ACTION, HFCPCI_STATES);
-}
-
-static struct FsmNode L1FnList[] __initdata =
-{
-	{ST_L1_F2,            EV_PH_F3,             l1_go_f3},
-	{ST_L1_F2,            EV_PH_F6,             l1_go_f6},
-	{ST_L1_F2,            EV_PH_F7,             l1_go_f7_act_ind},
-
-	{ST_L1_F3,            EV_PH_F3,             l1_ignore},
-	{ST_L1_F3,            EV_PH_F4,             l1_go_f4},
-	{ST_L1_F3,            EV_PH_F5,             l1_go_f5},
-	{ST_L1_F3,            EV_PH_F6,             l1_go_f6},
-	{ST_L1_F3,            EV_PH_F7,             l1_go_f7_act_ind},
-	{ST_L1_F3,            EV_PH_ACTIVATE_REQ,   l1_act_req},
-
-	{ST_L1_F4,            EV_PH_F7,             l1_ignore},
-	{ST_L1_F4,            EV_PH_F3,             l1_go_f3},
-	{ST_L1_F4,            EV_PH_F5,             l1_go_f5},
-	{ST_L1_F4,            EV_PH_F6,             l1_go_f6},
-	{ST_L1_F4,            EV_PH_F7,             l1_go_f7},
-
-	{ST_L1_F5,            EV_PH_F7,             l1_ignore},
-	{ST_L1_F5,            EV_PH_F3,             l1_go_f3},
-	{ST_L1_F5,            EV_PH_F6,             l1_go_f6},
-	{ST_L1_F5,            EV_PH_F7,             l1_go_f7},
-
-	{ST_L1_F6,            EV_PH_F7,             l1_ignore},
-	{ST_L1_F6,            EV_PH_F3,             l1_go_f3},
-	{ST_L1_F6,            EV_PH_F7,             l1_go_f7_act_ind},
-	{ST_L1_F6,            EV_PH_F8,             l1_go_f8},
-
-	{ST_L1_F7,            EV_PH_F7,             l1_ignore},
-	{ST_L1_F7,            EV_PH_F3,             l1_go_f3_deact_ind},
-	{ST_L1_F7,            EV_PH_F6,             l1_go_f6_deact_ind},
-	{ST_L1_F7,            EV_PH_F8,             l1_go_f8_deact_ind},
-
-	{ST_L1_F8,            EV_PH_F7,             l1_ignore},
-	{ST_L1_F8,            EV_PH_F3,             l1_go_f3},
-	{ST_L1_F8,            EV_PH_F6,             l1_go_f6},
-	{ST_L1_F8,            EV_PH_F7,             l1_go_f7_act_ind},
-
-};
-
-static void l1m_debug(struct FsmInst *fi, char *fmt, ...)
-{
-	va_list args;
-	char buf[256];
-	
-	va_start(args, fmt);
-	vsprintf(buf, fmt, args);
-	DBG(DBG_L1M, "%s", buf);
-	va_end(args);
-}
-
-// ----------------------------------------------------------------------
-// clear FIFOs
-
-static void
-hfcpci_clear_d_rx_fifo(struct hfcpci_adapter *adapter)
-{
-	u8 fifo_state;
-
-	DBG(DBG_D_RECV, "");
-
-	fifo_state = adapter->fifo_en & HFCPCI_FIFOEN_DRX;
-
-	if (fifo_state) { // enabled
-		// XXX locking
-	        adapter->fifo_en &= ~fifo_state;
-		hfcpci_writeb(adapter, adapter->fifo_en, HFCPCI_FIFO_EN);
-	}
-	
-	adapter->last_fcnt = 0;
-
-	set_d_rx_z1(adapter, MAX_D_FRAMES - 1, D_FIFO_END - 1);
-	set_d_rx_z2(adapter, MAX_D_FRAMES - 1, D_FIFO_END - 1);
-	mb();
-	set_d_rx_f1(adapter, MAX_D_FRAMES - 1);
-	set_d_rx_f2(adapter, MAX_D_FRAMES - 1);
-	mb();
-	
-	if (fifo_state) {
-	        adapter->fifo_en |= fifo_state;
-		hfcpci_writeb(adapter, adapter->fifo_en, HFCPCI_FIFO_EN);
-	}
-}   
-
-static void
-hfcpci_clear_b_rx_fifo(struct hfcpci_bcs *bcs)
-{
-	struct hfcpci_adapter *adapter = bcs->adapter;
-	int nr = bcs->channel;
-	u8 fifo_state;
-
-	DBG(DBG_B_RECV, "");
-
-	fifo_state = adapter->fifo_en & 
-		(nr ? HFCPCI_FIFOEN_B2RX : HFCPCI_FIFOEN_B1RX);
-
-	if (fifo_state) { // enabled
-	        adapter->fifo_en &= ~fifo_state;
-		hfcpci_writeb(adapter, adapter->fifo_en, HFCPCI_FIFO_EN);
-	}
-	
-	bcs->last_fcnt = 0;
-
-	set_b_rx_z1(bcs, MAX_B_FRAMES - 1, B_FIFO_END - 1);
-	set_b_rx_z2(bcs, MAX_B_FRAMES - 1, B_FIFO_END - 1);
-	mb();
-	set_b_rx_f1(bcs, MAX_B_FRAMES - 1);
-	set_b_rx_f2(bcs, MAX_B_FRAMES - 1);
-	mb();
-	
-	if (fifo_state) {
-	        adapter->fifo_en |= fifo_state;
-		hfcpci_writeb(adapter, adapter->fifo_en, HFCPCI_FIFO_EN);
-	}
-}   
-
-// XXX clear d_tx_fifo?
-
-static void
-hfcpci_clear_b_tx_fifo(struct hfcpci_bcs *bcs)
-{
-	struct hfcpci_adapter *adapter = bcs->adapter;
-	int nr = bcs->channel;
-	u8 fifo_state;
-
-	fifo_state = adapter->fifo_en & 
-		(nr ? HFCPCI_FIFOEN_B2TX : HFCPCI_FIFOEN_B1TX);
-
-	if (fifo_state) { // enabled
-	        adapter->fifo_en &= ~fifo_state;
-		hfcpci_writeb(adapter, adapter->fifo_en, HFCPCI_FIFO_EN);
-	}
-	
-	bcs->last_fcnt = 0;
-
-	set_b_rx_z1(bcs, MAX_B_FRAMES - 1, B_FIFO_END - 1);
-	set_b_rx_z2(bcs, MAX_B_FRAMES - 1, B_FIFO_END - 1);
-	mb();
-	set_b_rx_f1(bcs, MAX_B_FRAMES - 1);
-	set_b_rx_f2(bcs, MAX_B_FRAMES - 1);
-	mb();
-	
-	if (fifo_state) {
-	        adapter->fifo_en |= fifo_state;
-		hfcpci_writeb(adapter, adapter->fifo_en, HFCPCI_FIFO_EN);
-	}
-}   
-
-// ----------------------------------------------------------------------
-// receive messages from upper layers
-
-static void
-hfcpci_d_l2l1(struct hisax_if *ifc, int pr, void *arg)
-{
-	struct hfcpci_adapter *adapter = ifc->priv;
-	struct sk_buff *skb = arg;
-
-	DBG(DBG_PR, "pr %#x", pr);
-
-	switch (pr) {
-	case PH_ACTIVATE | REQUEST:
-		FsmEvent(&adapter->l1m, EV_PH_ACTIVATE_REQ, NULL);
-		break;
-	case PH_DEACTIVATE | REQUEST:
-		FsmEvent(&adapter->l1m, EV_PH_DEACTIVATE_REQ, NULL);
-		break;
-	case PH_DATA | REQUEST:
-		DBG(DBG_PR, "PH_DATA REQUEST len %d", skb->len);
-		DBG_SKB(DBG_D_XMIT, skb);
-		if (adapter->l1m.state != ST_L1_F7) {
-			DBG(DBG_WARN, "L1 wrong state %d", adapter->l1m.state);
-			break;
-		}
-		if (adapter->tx_skb)
-			BUG();
-
-		adapter->tx_skb = skb;
-		hfcpci_fill_d_fifo(adapter);
-		break;
-	}
-}
-
-static void
-hfcpci_b_l2l1(struct hisax_if *ifc, int pr, void *arg)
-{
-	struct hfcpci_bcs *bcs = ifc->priv;
-	struct sk_buff *skb = arg;
-	int mode;
-
-	DBG(DBG_PR, "pr %#x", pr);
-
-	switch (pr) {
-	case PH_DATA | REQUEST:
-		if (bcs->tx_skb)
-			BUG();
-		
-		bcs->tx_skb = skb;
-		DBG_SKB(DBG_B_XMIT, skb);
-		hfcpci_fill_b_fifo(bcs);
-		break;
-	case PH_ACTIVATE | REQUEST:
-		mode = (int) arg;
-		DBG(DBG_PR,"B%d,PH_ACTIVATE_REQUEST %d", bcs->channel + 1, mode);
-		hfcpci_b_mode(bcs, mode);
-		B_L1L2(bcs, PH_ACTIVATE | INDICATION, NULL);
-		break;
-	case PH_DEACTIVATE | REQUEST:
-		DBG(DBG_PR,"B%d,PH_DEACTIVATE_REQUEST", bcs->channel + 1);
-		hfcpci_b_mode(bcs, L1_MODE_NULL);
-		B_L1L2(bcs, PH_DEACTIVATE | INDICATION, NULL);
-		break;
-	}
-}
-
-// ----------------------------------------------------------------------
-// receive IRQ
-
-static inline void
-hfcpci_d_recv_irq(struct hfcpci_adapter *adapter)
-{
-	struct sk_buff *skb;
-	char *fifo_adr = adapter->fifo + 0x4000;
-	char *p;
-	int cnt, fcnt;
-	int loop = 5;
-	u8 f1, f2;
-	u16 z1, z2;
-
-	while (loop-- > 0) {
-		f1 = get_d_rx_f1(adapter);
-		f2 = get_d_rx_f2(adapter);
-		DBG(DBG_D_RECV, "f1 %#x f2 %#x", f1, f2);
-		
-		fcnt = f1 - f2;
-		if (fcnt < 0)
-			fcnt += 16;
-
-		if (!fcnt)
-			return;
-		
-		if (fcnt < adapter->last_fcnt)
-			/* overrun */
-			hfcpci_clear_d_rx_fifo(adapter);
-			// XXX init last_fcnt
-
-		z1 = get_d_rx_z1(adapter, f2);
-		z2 = get_d_rx_z2(adapter, f2);
-		DBG(DBG_D_RECV, "z1 %#x z2 %#x", z1, z2);
-
-		cnt = z1 - z2;
-		if (cnt < 0)
-			cnt += D_FIFO_SIZE;
-		cnt++;
-		
-		if (cnt < 4) {
-			DBG(DBG_WARN, "frame too short");
-			goto next;
-		}
-		if (fifo_adr[z1] != 0) {
-			DBG(DBG_WARN, "CRC error");
-			goto next;
-		}
-		cnt -= 3;
-		skb = dev_alloc_skb(cnt);
-		if (!skb) {
-			DBG(DBG_WARN, "no mem");
-			goto next;
-		}
-		p = skb_put(skb, cnt);
-		if (z2 + cnt <= D_FIFO_END) {
-			memcpy(p, fifo_adr + z2, cnt);
-		} else {
-			memcpy(p, fifo_adr + z2, D_FIFO_END - z2);
-			memcpy(p + (D_FIFO_END - z2), fifo_adr + D_FIFO_START,
-			       cnt - (D_FIFO_END - z2));
-		}
-
-		DBG_SKB(DBG_D_RECV, skb);
-		D_L1L2(adapter, PH_DATA | INDICATION, skb);
-	
-	next:
-		if (++z1 >= D_FIFO_END)
-			z1 -= D_FIFO_START;
-
-		f2 = (f2 + 1) & (MAX_D_FRAMES - 1);
-		mb();
-		set_d_rx_z2(adapter, f2, z1);
-		mb();
-		set_d_rx_f2(adapter, f2);
-		
-		adapter->last_fcnt = fcnt - 1;
-	}
-}
-
-static inline void
-hfcpci_b_recv_hdlc_irq(struct hfcpci_adapter *adapter, int nr)
-{
-	struct hfcpci_bcs *bcs = &adapter->bcs[nr];
-	struct sk_buff *skb;
-	char *fifo_adr = adapter->fifo + (nr ? 0x6000 : 0x4000);
-	char *p;
-	int cnt, fcnt;
-	int loop = 5;
-	u8 f1, f2;
-	u16 z1, z2;
-
-	while (loop-- > 0) {
-		f1 = get_b_rx_f1(bcs);
-		f2 = get_b_rx_f2(bcs);
-		DBG(DBG_B_RECV, "f1 %d f2 %d", f1, f2);
-		
-		fcnt = f1 - f2;
-		if (fcnt < 0)
-			fcnt += 32;
-
-		if (!fcnt)
-			return;
-		
-		if (fcnt < bcs->last_fcnt)
-			/* overrun */
-			hfcpci_clear_b_rx_fifo(bcs);
-			// XXX init last_fcnt
-		
-		z1 = get_b_rx_z1(bcs, f2);
-		z2 = get_b_rx_z2(bcs, f2);
-		DBG(DBG_B_RECV, "z1 %d z2 %d", z1, z2);
-
-		cnt = z1 - z2;
-		if (cnt < 0)
-			cnt += B_FIFO_SIZE;
-		cnt++;
-		
-		if (cnt < 4) {
-			DBG(DBG_WARN, "frame too short");
-			goto next;
-		}
-		if (fifo_adr[z1] != 0) {
-			DBG(DBG_WARN, "CRC error");
-			goto next;
-		}
-		cnt -= 3;
-		skb = dev_alloc_skb(cnt);
-		if (!skb) {
-			DBG(DBG_WARN, "no mem");
-			goto next;
-		}
-		p = skb_put(skb, cnt);
-		if (z2 + cnt <= B_FIFO_END) {
-			memcpy(p, fifo_adr + z2, cnt);
-		} else {
-			memcpy(p, fifo_adr + z2, B_FIFO_END - z2);
-			memcpy(p + (B_FIFO_END - z2), fifo_adr + B_FIFO_START,
-			       cnt - (B_FIFO_END - z2));
-		}
-
-		DBG_SKB(DBG_B_RECV, skb);
-		B_L1L2(bcs, PH_DATA | INDICATION, skb);
-	
-	next:
-		if (++z1 >= B_FIFO_END)
-			z1 -= B_FIFO_SIZE;
-
-		f2 = (f2 + 1) & (MAX_B_FRAMES - 1);
-		mb();
-		set_b_rx_z2(bcs, f2, z1);
-		mb();
-		set_b_rx_f2(bcs, f2);
-		
-		bcs->last_fcnt = fcnt - 1;
-	}
-}
-
-static inline void
-hfcpci_b_recv_trans_irq(struct hfcpci_adapter *adapter, int nr)
-{
-	struct hfcpci_bcs *bcs = &adapter->bcs[nr];
-	struct sk_buff *skb;
-	char *fifo_adr = adapter->fifo + (nr ? 0x6000 : 0x4000);
-	char *p;
-	int cnt;
-	int loop = 5;
-	u8 f1, f2;
-	u16 z1, z2;
-
-	f1 = get_b_rx_f1(bcs);
-	f2 = get_b_rx_f2(bcs);
-
-	if (f1 != f2)
-		BUG();
-
-	while (loop-- > 0) {
-		z1 = get_b_rx_z1(bcs, f2);
-		z2 = get_b_rx_z2(bcs, f2);
-		
-		cnt = z1 - z2;
-		if (!cnt)
-			/* no data available */
-			return;
-		
-		if (cnt < 0)
-			cnt += B_FIFO_SIZE;
-		
-		if (cnt > HFCPCI_BTRANS_THRESHOLD)
-			cnt = HFCPCI_BTRANS_THRESHOLD;
-		
-		skb = dev_alloc_skb(cnt);
-		if (!skb) {
-			DBG(DBG_WARN, "no mem");
-			goto next;
-		}
-		
-		p = skb_put(skb, cnt);
-		if (z2 + cnt <= 0x2000) {
-			memcpy(p, fifo_adr + z2, cnt);
-		} else {
-			memcpy(p, fifo_adr + z2, 0x2000 - z2);
-			p += 0x2000 - z2;
-			memcpy(p, fifo_adr + 0x200, cnt - (0x2000 - z2));
-		}
-		
-		DBG_SKB(DBG_B_RECV, skb);
-		B_L1L2(bcs, PH_DATA | INDICATION, skb);
-		
-	next:
-		z2 += cnt;
-		if (z2 >= 0x2000)
-			z2 -= B_FIFO_SIZE;
-		
-		mb();
-		set_b_rx_z2(bcs, f2, z2);
-		// XXX always receive buffers of a given size
-	}
-}
-
-static inline void
-hfcpci_b_recv_irq(struct hfcpci_adapter *adapter, int nr)
-{
-	DBG(DBG_B_RECV, "");
-
-	switch (adapter->bcs[nr].mode) {
-	case L1_MODE_NULL:
-		DBG(DBG_WARN, "?");
-		break;
-		
-	case L1_MODE_HDLC:
-		hfcpci_b_recv_hdlc_irq(adapter, nr);
-		break;
-
-	case L1_MODE_TRANS:
-		hfcpci_b_recv_trans_irq(adapter, nr);
-		break;
-	}
-}
-
-// ----------------------------------------------------------------------
-// transmit IRQ
-
-// XXX make xmit FIFO deeper than 1 
-
-static inline void
-hfcpci_d_xmit_irq(struct hfcpci_adapter *adapter)
-{
-	struct sk_buff *skb;
-
-	DBG(DBG_D_XMIT, "");
-
-	skb = adapter->tx_skb;
-	if (!skb) {
-		DBG(DBG_WARN, "?");
-		return;
-	}
-
-	adapter->tx_skb = NULL;
-	D_L1L2(adapter, PH_DATA | CONFIRM, (void *) skb->truesize);
-	dev_kfree_skb_irq(skb);
-}
-
-static inline void
-hfcpci_b_xmit_irq(struct hfcpci_adapter *adapter, int nr)
-{
-	struct hfcpci_bcs *bcs = &adapter->bcs[nr];
-	struct sk_buff *skb;
-
-	DBG(DBG_B_XMIT, "");
-
-	skb = bcs->tx_skb;
-	if (!skb) {
-		DBG(DBG_WARN, "?");
-		return;
-	}
-
-	bcs->tx_skb = NULL;
-	B_L1L2(bcs, PH_DATA | CONFIRM, skb);
-}
-
-// ----------------------------------------------------------------------
-// Layer 1 state change IRQ
-
-static inline void
-hfcpci_state_irq(struct hfcpci_adapter *adapter)
-{
-	u8 val;
-
-	val = hfcpci_readb(adapter, HFCPCI_STATES);
-	DBG(DBG_L1M, "STATES %#x", val);
-	FsmEvent(&adapter->l1m, val & 0xf, NULL);
-}
-
-// ----------------------------------------------------------------------
-// Timer IRQ
-
-static inline void
-hfcpci_timer_irq(struct hfcpci_adapter *adapter)
-{
-	hfcpci_writeb(adapter, adapter->ctmt | HFCPCI_CLTIMER, HFCPCI_CTMT);
-}
-
-// ----------------------------------------------------------------------
-// IRQ handler
-
-static irqreturn_t
-hfcpci_irq(int intno, void *dev, struct pt_regs *regs)
-{
-	struct hfcpci_adapter *adapter = dev;
-	int loop = 15;
-	u8 val, stat;
-
-	if (!(adapter->int_m2 & 0x08))
-		return IRQ_NONE;		/* not initialised */ // XX
-
-	stat = hfcpci_readb(adapter, HFCPCI_STATUS);
-	if (!(stat & HFCPCI_ANYINT))
-		return IRQ_NONE;
-
-	spin_lock(&adapter->hw_lock);
-	while (loop-- > 0) {
-		val = hfcpci_readb(adapter, HFCPCI_INT_S1);
-		DBG(DBG_IRQ, "stat %02x s1 %02x", stat, val);
-		val &= adapter->int_m1;
-
-		if (!val)
-			break;
-
-		if (val & 0x08)
-			hfcpci_b_recv_irq(adapter, 0);
-			
-		if (val & 0x10)
-			hfcpci_b_recv_irq(adapter, 1);
-
-		if (val & 0x01)
-			hfcpci_b_xmit_irq(adapter, 0);
-
-		if (val & 0x02)
-			hfcpci_b_xmit_irq(adapter, 1);
-
-		if (val & 0x20)
-			hfcpci_d_recv_irq(adapter);
-
-		if (val & 0x04)
-			hfcpci_d_xmit_irq(adapter);
-
-		if (val & 0x40)
-			hfcpci_state_irq(adapter);
-
-		if (val & 0x80)
-			hfcpci_timer_irq(adapter);
-	}
-	spin_unlock(&adapter->hw_lock);
-	return IRQ_HANDLED;
-}
-
-// ----------------------------------------------------------------------
-// reset hardware
-
-static void
-hfcpci_reset(struct hfcpci_adapter *adapter)
-{
-	/* disable all interrupts */
-	adapter->int_m1 = 0;
-	adapter->int_m2 = 0;
-	hfcpci_writeb(adapter, adapter->int_m1, HFCPCI_INT_M1);
-	hfcpci_writeb(adapter, adapter->int_m2, HFCPCI_INT_M2);
-
-	/* reset */
-	hfcpci_writeb(adapter, HFCPCI_RESET, HFCPCI_CIRM);
-	set_current_state(TASK_UNINTERRUPTIBLE);
-	schedule_timeout((30 * HZ) / 1000);
-	hfcpci_writeb(adapter, 0, HFCPCI_CIRM);
-	set_current_state(TASK_UNINTERRUPTIBLE);
-	schedule_timeout((20 * HZ) / 1000);
-	if (hfcpci_readb(adapter, HFCPCI_STATUS) & 2) // XX
-		printk(KERN_WARNING "HFC-PCI init bit busy\n");
-}
-
-// ----------------------------------------------------------------------
-// init hardware
-
-static void
-hfcpci_hw_init(struct hfcpci_adapter *adapter)
-{
-	adapter->fifo_en = 0x30;	/* only D fifos enabled */ // XX
-	hfcpci_writeb(adapter, adapter->fifo_en, HFCPCI_FIFO_EN);
-
-	/* no echo connect , threshold */
-	adapter->trm = HFCPCI_BTRANS_THRESMASK;
-	hfcpci_writeb(adapter, adapter->trm, HFCPCI_TRM);
-
-	/* ST-Bit delay for TE-Mode */
-	hfcpci_writeb(adapter, CLKDEL_TE, HFCPCI_CLKDEL);
-
-	/* S/T Auto awake */
-	adapter->sctrl_e = HFCPCI_AUTO_AWAKE;
-	hfcpci_writeb(adapter, adapter->sctrl_e, HFCPCI_SCTRL_E);
-
-	/* no exchange */
-	adapter->bswapped = 0;
-	/* we are in TE mode */
-	adapter->nt_mode = 0;
-
-	adapter->ctmt = HFCPCI_TIM3_125 | HFCPCI_AUTO_TIMER;
-	hfcpci_writeb(adapter, adapter->ctmt, HFCPCI_CTMT);
-
-	adapter->int_m1 = HFCPCI_INTS_DTRANS | HFCPCI_INTS_DREC |
-		HFCPCI_INTS_L1STATE;
-	hfcpci_writeb(adapter, adapter->int_m1, HFCPCI_INT_M1);
-
-	/* clear already pending ints */
-	hfcpci_readb(adapter, HFCPCI_INT_S1);
-
-	adapter->l1m.state = 2;
-	hfcpci_writeb(adapter, HFCPCI_LOAD_STATE | 2, HFCPCI_STATES);	// XX /* HFC ST 2 */
-	udelay(10);
-	hfcpci_writeb(adapter, 2, HFCPCI_STATES);	/* HFC ST 2 */
-
-	/* HFC Master Mode */
-	adapter->mst_m = HFCPCI_MASTER;
-	hfcpci_writeb(adapter, adapter->mst_m, HFCPCI_MST_MODE);
-
-	/* set tx_lo mode, error in datasheet ! */
-	adapter->sctrl = 0x40;
-	hfcpci_writeb(adapter, adapter->sctrl, HFCPCI_SCTRL);
-
-	adapter->sctrl_r = 0;
-	hfcpci_writeb(adapter, adapter->sctrl_r, HFCPCI_SCTRL_R);
-
-	// XXX
-	/* Init GCI/IOM2 in master mode */
-	/* Slots 0 and 1 are set for B-chan 1 and 2 */
-	/* D- and monitor/CI channel are not enabled */
-	/* STIO1 is used as output for data, B1+B2 from ST->IOM+HFC */
-	/* STIO2 is used as data input, B1+B2 from IOM->ST */
-	/* ST B-channel send disabled -> continous 1s */
-	/* The IOM slots are always enabled */
-	adapter->conn = 0;	/* set data flow directions */
-	hfcpci_writeb(adapter, adapter->conn, HFCPCI_CONNECT);
-	hfcpci_writeb(adapter, 0x80, HFCPCI_B1_SSL);	/* B1-Slot 0 STIO1 out enabled */
-	hfcpci_writeb(adapter, 0x81, HFCPCI_B2_SSL);	/* B2-Slot 1 STIO1 out enabled */
-	hfcpci_writeb(adapter, 0x80, HFCPCI_B1_RSL);	/* B1-Slot 0 STIO2 in enabled */
-	hfcpci_writeb(adapter, 0x81, HFCPCI_B2_RSL);	/* B2-Slot 1 STIO2 in enabled */
-
-	/* Finally enable IRQ output */
-	adapter->int_m2 = HFCPCI_IRQ_ENABLE;
-	hfcpci_writeb(adapter, adapter->int_m2, HFCPCI_INT_M2);
-
-	hfcpci_readb(adapter, HFCPCI_INT_S2);
-}
-
-// ----------------------------------------------------------------------
-// probe / remove
-
-static struct hfcpci_adapter * __devinit 
-new_adapter(struct pci_dev *pdev)
-{
-	struct hfcpci_adapter *adapter;
-	struct hisax_b_if *b_if[2];
-	int i;
-
-	adapter = kmalloc(sizeof(struct hfcpci_adapter), GFP_KERNEL);
-	if (!adapter)
-		return NULL;
-
-	memset(adapter, 0, sizeof(struct hfcpci_adapter));
-
-	adapter->d_if.owner = THIS_MODULE;
-	adapter->d_if.ifc.priv = adapter;
-	adapter->d_if.ifc.l2l1 = hfcpci_d_l2l1;
-	
-	for (i = 0; i < 2; i++) {
-		adapter->bcs[i].adapter = adapter;
-		adapter->bcs[i].channel = i;
-		adapter->bcs[i].b_if.ifc.priv = &adapter->bcs[i];
-		adapter->bcs[i].b_if.ifc.l2l1 = hfcpci_b_l2l1;
-	}
-
-	pci_set_drvdata(pdev, adapter);
-
-	for (i = 0; i < 2; i++)
-		b_if[i] = &adapter->bcs[i].b_if;
-
-	hisax_register(&adapter->d_if, b_if, "hfcpci", protocol);
-
-	return adapter;
-}
-
-static void delete_adapter(struct hfcpci_adapter *adapter)
-{
-	hisax_unregister(&adapter->d_if);
-	kfree(adapter);
-}
-
-static int __devinit hfcpci_probe(struct pci_dev *pdev,
-				 const struct pci_device_id *ent)
-{
-	struct hfcpci_adapter *adapter;
-	int retval;
-
-	DBG(DBG_INFO, "");
-	retval = -ENOMEM;
-	adapter = new_adapter(pdev);
-	if (!adapter)
-		goto err;
-
-	retval = pci_enable_device(pdev);
-	if (retval)
-		goto err_free;
-
-	adapter->irq = pdev->irq;
-	retval = request_irq(adapter->irq, hfcpci_irq, SA_SHIRQ, 
-			     "hfcpci", adapter);
-	if (retval)
-		goto err_free;
-
-	retval = -EBUSY;
-	if (!request_mem_region(pci_resource_start(pdev, 1), 256, "hfcpci"))
-		goto err_free_irq;
-
-	adapter->mmio = ioremap(pci_resource_start(pdev, 1), 256); // XX pci_io
-	if (!adapter->mmio)
-		goto err_release_region;
-
-	/* Allocate 32K for FIFOs */
-	if (pci_set_dma_mask(pdev, 0xffffffff))
-		goto err_unmap;
-	
-	adapter->fifo = pci_alloc_consistent(pdev, 32768, &adapter->fifo_dma); 
-	if (!adapter->fifo)
-		goto err_unmap;
-	
-	pci_write_config_dword(pdev, HFCPCI_MWBA, (u32) adapter->fifo_dma);
-	pci_set_master(pdev);
-
-	adapter->l1m.fsm = &l1fsm;
-	adapter->l1m.state = ST_L1_F0;
-#ifdef CONFIG_HISAX_DEBUG
-	adapter->l1m.debug = 1;
-#else
-	adapter->l1m.debug = 0;
-#endif
-	adapter->l1m.userdata = adapter;
-	adapter->l1m.printdebug = l1m_debug;
-	FsmInitTimer(&adapter->l1m, &adapter->timer);
-
-	hfcpci_reset(adapter);
-	hfcpci_hw_init(adapter);
-
-	printk(KERN_INFO "hisax_hfcpci: found adapter %s at %s\n",
-	       (char *) ent->driver_data, pci_name(pdev));
-
-	return 0;
-
- err_unmap:
-	iounmap(adapter->mmio);
- err_release_region:
-	release_mem_region(pci_resource_start(pdev, 1), 256);
- err_free_irq:
-	free_irq(adapter->irq, adapter);
- err_free:
-	delete_adapter(adapter);
- err:
-	return retval;
-}
-
-static void __devexit hfcpci_remove(struct pci_dev *pdev)
-{
-	struct hfcpci_adapter *adapter = pci_get_drvdata(pdev);
-
-	hfcpci_reset(adapter);
-
-//	del_timer(&cs->hw.hfcpci.timer); XX
-
-	/* disable DMA */
-	pci_disable_device(pdev);
-	pci_write_config_dword(pdev, HFCPCI_MWBA, 0);
-	pci_free_consistent(pdev, 32768, adapter->fifo, adapter->fifo_dma);
-
-	iounmap(adapter->mmio);
-	release_mem_region(pci_resource_start(pdev, 1), 256);
-	free_irq(adapter->irq, adapter);
-	delete_adapter(adapter);
-}
-
-static struct pci_driver hfcpci_driver = {
-	.name     = "hfcpci",
-	.probe    = hfcpci_probe,
-	.remove   = __devexit_p(hfcpci_remove),
-	.id_table = hfcpci_ids,
-};
-
-static int __init hisax_hfcpci_init(void)
-{
-	int retval;
-
-	printk(KERN_INFO "hisax_hfcpcipnp: HFC PCI ISDN driver v0.0.1\n");
-
-	l1fsm.state_count = L1_STATE_COUNT;
-	l1fsm.event_count = L1_EVENT_COUNT;
-	l1fsm.strState = strL1State;
-	l1fsm.strEvent = strL1Event;
-	retval = FsmNew(&l1fsm, L1FnList, ARRAY_SIZE(L1FnList));
-	if (retval)
-		goto err;
-
-	retval = pci_module_init(&hfcpci_driver);
-	if (retval)
-		goto err_fsm;
-	
-	return 0;
-
- err_fsm:
-	FsmFree(&l1fsm);
- err:
-	return retval;
-}
-
-static void __exit hisax_hfcpci_exit(void)
-{
-	FsmFree(&l1fsm);
-	pci_unregister_driver(&hfcpci_driver);
-}
-
-module_init(hisax_hfcpci_init);
-module_exit(hisax_hfcpci_exit);
--- diff/drivers/isdn/hisax/hisax_hfcpci.h	2002-10-16 04:27:55.000000000 +0100
+++ source/drivers/isdn/hisax/hisax_hfcpci.h	1970-01-01 01:00:00.000000000 +0100
@@ -1,40 +0,0 @@
-#include "hisax_if.h"
-#include "hisax_isac.h"
-#include <linux/pci.h>
-
-struct hfcpci_bcs {
-	struct hisax_b_if b_if;
-	struct hfcpci_adapter *adapter;
-	int mode;
-	int channel;
-	int last_fcnt;
-
-	struct sk_buff *tx_skb;
-};
-
-struct hfcpci_adapter {
-	struct hisax_d_if d_if;
-	spinlock_t hw_lock;
-	unsigned int irq;
-	void *mmio;
-	u8 *fifo;
-	dma_addr_t fifo_dma;
-
-	struct FsmInst l1m;
-	struct FsmTimer timer;
-	struct sk_buff *tx_skb;
-	int last_fcnt;
-
-	u8 int_m1, int_m2;
-	u8 fifo_en;
-	u8 trm;
-	u8 sctrl, sctrl_r, sctrl_e;
-	u8 nt_mode;
-	u8 ctmt;
-	u8 mst_m;
-	u8 conn;
-	u8 bswapped;
-
-	struct hfcpci_bcs bcs[2];
-};
-
--- diff/drivers/isdn/hisax/hisax_hscx.c	2003-01-13 14:18:15.000000000 +0000
+++ source/drivers/isdn/hisax/hisax_hscx.c	1970-01-01 01:00:00.000000000 +0100
@@ -1,420 +0,0 @@
-/*
- * Driver for HSCX
- * High-Level Serial Communcation Controller Extended
- *
- * Author       Kai Germaschewski
- * Copyright    2001 by Kai Germaschewski  <kai.germaschewski@gmx.de>
- *              2001 by Karsten Keil       <keil@isdn4linux.de>
- * 
- * based upon Karsten Keil's original isac.c driver
- *
- * This software may be used and distributed according to the terms
- * of the GNU General Public License, incorporated herein by reference.
- */
-
-/* TODO:
- * comments in .h
- */
-
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/netdevice.h>
-#include "hisax_hscx.h"
-
-// debugging cruft
-
-#define __debug_variable debug
-#include "hisax_debug.h"
-
-#ifdef CONFIG_HISAX_DEBUG
-static int debug = 1;
-MODULE_PARM(debug, "i");
-
-static char *HSCXVer[] =
-{"A1", "?1", "A2", "?3", "A3", "V2.1", "?6", "?7",
- "?8", "?9", "?10", "?11", "?12", "?13", "?14", "???"};
-#endif
-
-MODULE_AUTHOR("Kai Germaschewski <kai.germaschewski@gmx.de>/Karsten Keil <kkeil@suse.de>");
-MODULE_DESCRIPTION("HSCX driver");
-
-#define DBG_WARN      0x0001
-#define DBG_IRQ       0x0002
-#define DBG_L1M       0x0004
-#define DBG_PR        0x0008
-#define DBG_RFIFO     0x0100
-#define DBG_RPACKET   0x0200
-#define DBG_XFIFO     0x1000
-#define DBG_XPACKET   0x2000
-
-#define HSCX_ISTA      0x20
-#define HSCX_ISTA_EXB  0x01
-#define HSCX_ISTA_EXA  0x02
-#define HSCX_ISTA_ICA  0x04
-#define HSCX_ISTA_TIN  0x08
-#define HSCX_ISTA_XPR  0x10
-#define HSCX_ISTA_RSC  0x20
-#define HSCX_ISTA_RPF  0x40
-#define HSCX_ISTA_RME  0x80
-
-#define HSCX_CMDR      0x21
-#define HSCX_CMDR_RMC  0x80
-#define HSCX_CMDR_RHR  0x40
-#define HSCX_CMDR_RNR  0x20
-#define HSCX_CMDR_STI  0x10
-#define HSCX_CMDR_XTF  0x08
-#define HSCX_CMDR_XIF  0x04
-#define HSCX_CMDR_XME  0x02
-#define HSCX_CMDR_XRES 0x01
-
-#define HSCX_EXIR      0x24
-#define HSCX_EXIR_XDU  0x40
-
-#define HSCX_RSTA      0x27
-#define HSCX_RSTA_VFR  0x80
-#define HSCX_RSTA_RDO  0x40
-#define HSCX_RSTA_CRC  0x20
-#define HSCX_RSTA_RAB  0x10
-
-#define HSCX_CCR1 0x2f
-#define HSCX_CCR2 0x2c
-#define HSCX_TSAR 0x31
-#define HSCX_TSAX 0x30
-#define HSCX_XCCR 0x32
-#define HSCX_RCCR 0x33
-#define HSCX_MODE 0x22
-
-#define HSCX_XAD1 0x24
-#define HSCX_XAD2 0x25
-#define HSCX_RAH2 0x27
-#define HSCX_TIMR 0x23
-#define HSCX_STAR 0x21
-#define HSCX_RBCL 0x25
-#define HSCX_XBCH 0x2d
-#define HSCX_VSTR 0x2e
-#define HSCX_RLCR 0x2e
-#define HSCX_MASK 0x20
-
-static inline void B_L1L2(struct hscx *hscx, int pr, void *arg)
-{
-	struct hisax_if *ifc = (struct hisax_if *) &hscx->b_if;
-
-	DBG(0x10, "pr %#x", pr);
-	ifc->l1l2(ifc, pr, arg);
-}
-
-static void hscx_version(struct hscx *hscx)
-{
-	int val;
-
-	val = hscx->read_hscx(hscx, HSCX_VSTR) & 0xf;
-	DBG(1, "HSCX version (%x): %s", val, HSCXVer[val]);
-}
-
-static void hscx_empty_fifo(struct hscx *hscx, int count)
-{
-	u8 *ptr;
-
-	DBG(DBG_IRQ, "count %d", count);
-
-	if ((hscx->rcvidx + count) >= HSCX_BUFMAX) {
-		DBG(DBG_WARN, "overrun %d", hscx->rcvidx + count);
-		hscx->write_hscx(hscx, HSCX_CMDR, HSCX_CMDR_RMC);
-		hscx->rcvidx = 0;
-		return;
-	}
-	ptr = hscx->rcvbuf + hscx->rcvidx;
-	hscx->rcvidx += count;
-	hscx->read_hscx_fifo(hscx, ptr, count);
-	hscx->write_hscx(hscx, HSCX_CMDR, HSCX_CMDR_RMC);
-	DBG_PACKET(DBG_RFIFO, ptr, count);
-}
-
-static void hscx_fill_fifo(struct hscx *hscx)
-{
-	int count;
-	unsigned char cmd;
-	int fifo_size = test_bit(HSCX_IPAC, &hscx->flags)? 64: 32;
-	unsigned char *ptr;
-
-	if (!hscx->tx_skb)
-		BUG();
-
-	count = hscx->tx_skb->len;
-	if (count <= 0)
-		BUG();
-
-	DBG(DBG_IRQ, "count %d", count);
-
-	if (count > fifo_size || hscx->mode == L1_MODE_TRANS) {
-		count = fifo_size;
-		cmd = 0x8;
-	} else {
-		cmd = 0xa;
-	}
-
-	ptr = hscx->tx_skb->data;
-	skb_pull(hscx->tx_skb, count);
-	hscx->tx_cnt += count;
-	DBG_PACKET(DBG_XFIFO, ptr, count);
-	hscx->write_hscx_fifo(hscx, ptr, count);
-	hscx->write_hscx(hscx, HSCX_CMDR, cmd);
-}
-
-static void hscx_retransmit(struct hscx *hscx)
-{
-	if (!hscx->tx_skb) {
-		DBG(DBG_WARN, "no skb");
-		return;
-	}
-	skb_push(hscx->tx_skb, hscx->tx_cnt);
-	hscx->tx_cnt = 0;
-	hscx->write_hscx(hscx, HSCX_CMDR, 0x01);
-}
-
-static inline void hscx_rme_interrupt(struct hscx *hscx)
-{
-	unsigned char val;
-	int count;
-	struct sk_buff *skb;
-	int fifo_size = test_bit(HSCX_IPAC, &hscx->flags)? 64: 32;
-	
-	val = hscx->read_hscx(hscx, HSCX_RSTA);
-	if ((val & (HSCX_RSTA_VFR | HSCX_RSTA_RDO | HSCX_RSTA_CRC | HSCX_RSTA_RAB) )
-	     != (HSCX_RSTA_VFR | HSCX_RSTA_CRC)) {
-		DBG(DBG_WARN, "RSTA %#x, dropped", val);
-		hscx->write_hscx(hscx, HSCX_CMDR, HSCX_CMDR_RMC);
-		goto out;
-	}
-	
-	count = hscx->read_hscx(hscx, HSCX_RBCL) & (fifo_size-1);
-	DBG(DBG_IRQ, "RBCL %#x", count);
-	if (count == 0)
-		count = fifo_size;
-
-	hscx_empty_fifo(hscx, count);
-
-	count = hscx->rcvidx;
-	if (count < 1) {
-		DBG(DBG_WARN, "count %d < 1", count);
-		goto out;
-	}
-
-	skb = alloc_skb(count, GFP_ATOMIC);
-	if (!skb) {
-		DBG(DBG_WARN, "no memory, dropping\n");
-		goto out;
-	}
-	memcpy(skb_put(skb, count), hscx->rcvbuf, count);
-	DBG_SKB(DBG_RPACKET, skb);
-	B_L1L2(hscx, PH_DATA | INDICATION, skb);
- out:
-	hscx->rcvidx = 0;
-}
-
-static inline void hscx_xpr_interrupt(struct hscx *hscx)
-{
-	struct sk_buff *skb;
-
-	skb = hscx->tx_skb;
-	if (!skb)
-		return;
-
-	if (skb->len > 0) {
-		hscx_fill_fifo(hscx);
-		return;
-	}
-	hscx->tx_cnt = 0;
-	hscx->tx_skb = NULL;
-	B_L1L2(hscx, PH_DATA | CONFIRM, skb);
-}
-
-static inline void hscx_exi_interrupt(struct hscx *hscx)
-{
-	unsigned char val;
-
-	val = hscx->read_hscx(hscx, HSCX_EXIR);
-	DBG(2, "EXIR %#x", val);
-
-	if (val & HSCX_EXIR_XDU) {
-		DBG(DBG_WARN, "HSCX XDU");
-		if (hscx->mode == L1_MODE_TRANS) {
-			hscx_fill_fifo(hscx);
-		} else {
-			hscx_retransmit(hscx);
-		}
-	}
-}
-
-static void hscx_reg_interrupt(struct hscx *hscx, unsigned char val)
-{
-	struct sk_buff *skb;
-
-	if (val & HSCX_ISTA_XPR) {
-		DBG(DBG_IRQ, "XPR");
-		hscx_xpr_interrupt(hscx);
-	}
-	if (val & HSCX_ISTA_RME) {
-		DBG(DBG_IRQ, "RME");
-		hscx_rme_interrupt(hscx);
-	}
-	if (val & HSCX_ISTA_RPF) {
-		int fifo_size = test_bit(HSCX_IPAC, &hscx->flags)? 64: 32;
-
-		DBG(DBG_IRQ, "RPF");
-		hscx_empty_fifo(hscx, fifo_size);
-		if (hscx->mode == L1_MODE_TRANS) {
-			skb = dev_alloc_skb(fifo_size);
-			if (!skb) {
-				DBG(DBG_WARN, "no memory, dropping\n");
-				goto out;
-			}
-			memcpy(skb_put(skb, fifo_size), hscx->rcvbuf, fifo_size);
-			DBG_SKB(DBG_RPACKET, skb);
-			B_L1L2(hscx, PH_DATA | INDICATION, skb);
-		out:
-			hscx->rcvidx = 0;
-		}
-	}
-}
-
-void hscx_irq(struct hscx *hscx_a)
-{
-	struct hscx *hscx_b = hscx_a + 1;
-	unsigned char val;
-
-	val = hscx_b->read_hscx(hscx_b, HSCX_ISTA);
-	DBG(DBG_IRQ, "ISTA B %#x", val);
-
-	if (val & HSCX_ISTA_EXB) {
-		DBG(DBG_IRQ, "EXI B");
-		hscx_exi_interrupt(hscx_b);
-	}
-	if (val & HSCX_ISTA_EXA) {
-		DBG(DBG_IRQ, "EXI A");
-		hscx_exi_interrupt(hscx_a);
-	}
-	if (val & 0xf8) {
-		hscx_reg_interrupt(hscx_b, val);
-	}
-	if (val & HSCX_ISTA_ICA) {
-		val = hscx_a->read_hscx(hscx_a, HSCX_ISTA);
-		DBG(DBG_IRQ, "ISTA A %#x", val);
-		hscx_reg_interrupt(hscx_a, val);
-		hscx_a->write_hscx(hscx_a, HSCX_MASK, 0xff);
-		hscx_a->write_hscx(hscx_a, HSCX_MASK, 0x00);
-	}
-	hscx_b->write_hscx(hscx_b, HSCX_MASK, 0xff);
-	hscx_b->write_hscx(hscx_b, HSCX_MASK, 0x00);
-}
-
-static void modehscx(struct hscx *hscx, int mode)
-{
-	int bc = hscx->channel;
-
-	DBG(0x40, "hscx %c mode %d --> %d",
-	    'A' + hscx->channel, hscx->mode, mode);
-
-	hscx->mode = mode;
-	hscx->write_hscx(hscx, HSCX_XAD1, 0xFF);
-	hscx->write_hscx(hscx, HSCX_XAD2, 0xFF);
-	hscx->write_hscx(hscx, HSCX_RAH2, 0xFF);
-	hscx->write_hscx(hscx, HSCX_XBCH, 0x0);
-	hscx->write_hscx(hscx, HSCX_RLCR, 0x0);
-	hscx->write_hscx(hscx, HSCX_CCR1, 
-			 test_bit(HSCX_IPAC, &hscx->flags) ? 0x82 : 0x85);
-	hscx->write_hscx(hscx, HSCX_CCR2, 0x30);
-	hscx->write_hscx(hscx, HSCX_XCCR, 7);
-	hscx->write_hscx(hscx, HSCX_RCCR, 7);
-
-	/* Switch IOM 1 SSI */
-	if (test_bit(HSCX_IOM1, &hscx->flags))
-		bc = 1;
-
-	hscx->write_hscx(hscx, HSCX_TSAX, hscx->tsaxr);
-	hscx->write_hscx(hscx, HSCX_TSAR, hscx->tsaxr);
-
-	switch (mode) {
-		case (L1_MODE_NULL):
-			hscx->write_hscx(hscx, HSCX_TSAX, 0x1f);
-			hscx->write_hscx(hscx, HSCX_TSAR, 0x1f);
-			hscx->write_hscx(hscx, HSCX_MODE, 0x84);
-			break;
-		case (L1_MODE_TRANS):
-			hscx->write_hscx(hscx, HSCX_MODE, 0xe4);
-			break;
-		case (L1_MODE_HDLC):
-			hscx->write_hscx(hscx, HSCX_CCR1, test_bit(HSCX_IPAC, &hscx->flags) ? 0x8a : 0x8d);
-			hscx->write_hscx(hscx, HSCX_MODE, 0x8c);
-			break;
-	}
-	if (mode)
-		hscx->write_hscx(hscx, HSCX_CMDR, 0x41);
-
-	hscx->write_hscx(hscx, HSCX_ISTA, 0x00);
-}
-
-void hscx_init(struct hscx *hscx)
-{
-	if (hscx->channel)
-		hscx->tsaxr = 0x03;
-	else
-		hscx->tsaxr = 0x2f;
-}
-
-void hscx_setup(struct hscx *hscx)
-{
-	hscx_version(hscx);
-	hscx->mode = -1;
-	modehscx(hscx, L1_MODE_NULL);
-}
-
-void hscx_b_l2l1(struct hisax_if *ifc, int pr, void *arg)
-{
-	struct hscx *hscx = ifc->priv;
-	struct sk_buff *skb = arg;
-	int mode;
-
-	DBG(0x10, "pr %#x", pr);
-
-	switch (pr) {
-	case PH_DATA | REQUEST:
-		if (hscx->tx_skb)
-			BUG();
-		
-		hscx->tx_skb = skb;
-		DBG_SKB(1, skb);
-		hscx_fill_fifo(hscx);
-		break;
-	case PH_ACTIVATE | REQUEST:
-		mode = (int) arg;
-		DBG(4,"B%d,PH_ACTIVATE_REQUEST %d", hscx->channel + 1, mode);
-		modehscx(hscx, mode);
-		B_L1L2(hscx, PH_ACTIVATE | INDICATION, NULL);
-		break;
-	case PH_DEACTIVATE | REQUEST:
-		DBG(4,"B%d,PH_DEACTIVATE_REQUEST", hscx->channel + 1);
-		modehscx(hscx, L1_MODE_NULL);
-		B_L1L2(hscx, PH_DEACTIVATE | INDICATION, NULL);
-		break;
-	}
-}
-
-static int __init hisax_hscx_init(void)
-{
-	printk(KERN_INFO "hisax_hscx: HSCX ISDN driver v0.1.0\n");
-	return 0;
-}
-
-static void __exit hisax_hscx_exit(void)
-{
-}
-
-EXPORT_SYMBOL(hscx_init);
-EXPORT_SYMBOL(hscx_b_l2l1);
-
-EXPORT_SYMBOL(hscx_setup);
-EXPORT_SYMBOL(hscx_irq);
-
-module_init(hisax_hscx_init);
-module_exit(hisax_hscx_exit);
--- diff/drivers/isdn/hisax/hisax_hscx.h	2003-01-13 14:18:15.000000000 +0000
+++ source/drivers/isdn/hisax/hisax_hscx.h	1970-01-01 01:00:00.000000000 +0100
@@ -1,37 +0,0 @@
-#ifndef __HISAX_HSCX_H__
-#define __HISAX_HSCX_H__
-
-#include <linux/kernel.h>
-#include "fsm.h"
-#include "hisax_if.h"
-
-#define HSCX_BUFMAX	4096
-
-#define HSCX_IOM1 0
-#define HSCX_IPAC 1
-
-struct hscx {
-	void *priv;
-	u_long flags;
-	struct hisax_b_if b_if;
-	int mode;
-	int channel;
-	u8 tsaxr;
-	struct sk_buff *tx_skb;
-	int tx_cnt;
-	u8 rcvbuf[HSCX_BUFMAX];
-	int rcvidx;
-
-	u8 (*read_hscx)      (struct hscx *, u8);
-	void   (*write_hscx)     (struct hscx *, u8, u8);
-	void   (*read_hscx_fifo) (struct hscx *, u8 *, int);
-	void   (*write_hscx_fifo)(struct hscx *, u8 *, int);
-};
-
-void hscx_init(struct hscx *hscx);
-void hscx_b_l2l1(struct hisax_if *hisax_b_if, int pr, void *arg);
-
-void hscx_setup(struct hscx *hscx);
-void hscx_irq(struct hscx *hscx);
-
-#endif
--- diff/drivers/isdn/hisax/ipac.c	2003-05-21 11:50:15.000000000 +0100
+++ source/drivers/isdn/hisax/ipac.c	1970-01-01 01:00:00.000000000 +0100
@@ -1,107 +0,0 @@
-#include "hisax.h"
-#include "isdnl1.h"
-#include "ipac.h"
-#include "hscx.h"
-#include "isac.h"
-
-static inline u8
-ipac_dc_read(struct IsdnCardState *cs, u8 addr)
-{
-	return cs->dc_hw_ops->read_reg(cs, addr);
-}
-
-static inline void
-ipac_dc_write(struct IsdnCardState *cs, u8 addr, u8 val)
-{
-	cs->dc_hw_ops->write_reg(cs, addr, val);
-}
-
-static inline u8
-ipac_bc_read(struct IsdnCardState *cs, int hscx, u8 addr)
-{
-	return cs->bc_hw_ops->read_reg(cs, hscx, addr);
-}
-
-static inline void
-ipac_bc_write(struct IsdnCardState *cs, int hscx, u8 addr, u8 val)
-{
-	cs->bc_hw_ops->write_reg(cs, hscx, addr, val);
-}
-
-static inline u8
-ipac_read(struct IsdnCardState *cs, u8 offset)
-{
-	return ipac_dc_read(cs, offset - 0x80);
-}
-
-static inline void
-ipac_write(struct IsdnCardState *cs, u8 offset, u8 value)
-{
-	ipac_dc_write(cs, offset - 0x80, value);
-}
-
-void
-ipac_init(struct IsdnCardState *cs)
-{
-	set_bit(HW_IPAC, &cs->HW_Flags);
-	inithscxisac(cs);
-}
-
-irqreturn_t
-ipac_irq(int intno, void *dev_id, struct pt_regs *regs)
-{
-	struct IsdnCardState *cs = dev_id;
-	u8 ista, val, icnt = 5;
-
-	spin_lock(&cs->lock);
-	ista = ipac_read(cs, IPAC_ISTA);
-Start_IPAC:
-	if (cs->debug & L1_DEB_IPAC)
-		debugl1(cs, "IPAC ISTA %02X", ista);
-	if (ista & 0x0f) {
-		val = ipac_bc_read(cs, 1, HSCX_ISTA);
-		if (ista & 0x01)
-			val |= 0x01;
-		if (ista & 0x04)
-			val |= 0x02;
-		if (ista & 0x08)
-			val |= 0x04;
-		if (val)
-			hscx_int_main(cs, val);
-	}
-	if (ista & 0x20) {
-		val = ipac_dc_read(cs, ISAC_ISTA) & 0xfe;
-		if (val) {
-			isac_interrupt(cs, val);
-		}
-	}
-	if (ista & 0x10) {
-		val = 0x01;
-		isac_interrupt(cs, val);
-	}
-	ista  = ipac_read(cs, IPAC_ISTA);
-	if ((ista & 0x3f) && icnt) {
-		icnt--;
-		goto Start_IPAC;
-	}
-	if (!icnt)
-		printk(KERN_WARNING "IRQ LOOP\n");
-
-	ipac_write(cs, IPAC_MASK, 0xFF);
-	ipac_write(cs, IPAC_MASK, 0xC0);
-	spin_unlock(&cs->lock);
-	return IRQ_HANDLED;
-}
-
-int
-ipac_setup(struct IsdnCardState *cs, struct dc_hw_ops *ipac_dc_ops,
-	   struct bc_hw_ops *ipac_bc_ops)
-{
-	u8 val;
-
-	cs->dc_hw_ops = ipac_dc_ops;
-	cs->bc_hw_ops = ipac_bc_ops;
-	val = ipac_read(cs, IPAC_ID);
-	printk(KERN_INFO "HiSax: IPAC version %#x\n", val);
-	return 0;
-}
--- diff/drivers/isdn/hisax/md5sums.asc	2002-10-16 04:27:53.000000000 +0100
+++ source/drivers/isdn/hisax/md5sums.asc	1970-01-01 01:00:00.000000000 +0100
@@ -1,22 +0,0 @@
-# This are valid md5sums for certificated HiSax driver.
-# The certification is valid only if the md5sums of all files match.
-# The certification is valid only for ELSA Microlink PCI,
-# Eicon Technology Diva 2.01 PCI, Sedlbauer SpeedFax+, 
-# HFC-S PCI A based cards and HFC-S USB based isdn tas 
-# in the moment.
-# Read ../../../Documentation/isdn/HiSax.cert for more informations.
-# 
-d08b59f56fb9ed1fbd17713342c75081  isac.c
-e81e6e96f307e55f8b9777aca2b356d9  isdnl1.c
-cfd2527d9fb01885484cba74bfc67121  isdnl2.c
-8c6829f11459f9d044b5768803fb646d  isdnl3.c
-d40f88dff4191d2660240749cbdcb688  tei.c
-3bd3bd05ee4cb25ffe046200b569a83a  callc.c
-d518f52402ebc3f1be84e09af375313c  cert.c
-c425de1f8be86e84006de63c9bb3cc5f  l3dss1.c
-4c411e29d4103ba60e9af4e3e1234a99  l3_1tr6.c
-68c6cc2784f208e3247a5a555918d014  elsa.c
-8d63a85d7222cf7b40e663e543191d8f  diva.c
-8c8cb4ce621fb84d8e337a696e75b0df  sedlbauer.c
-ebe5613d535748409407568435b2be97  hfc_pci.c
-# end of md5sums
--- diff/drivers/isdn/hisax/rawhdlc.c	2003-05-21 11:49:45.000000000 +0100
+++ source/drivers/isdn/hisax/rawhdlc.c	1970-01-01 01:00:00.000000000 +0100
@@ -1,543 +0,0 @@
-/* $Id: rawhdlc.c,v 1.5.6.2 2001/09/23 22:24:51 kai Exp $
- *
- * support routines for cards that don't support HDLC
- *
- * Author     Brent Baccala
- * Copyright  by Karsten Keil <keil@isdn4linux.de>
- *            by Brent Baccala <baccala@FreeSoft.org>
- *
- * This software may be used and distributed according to the terms
- * of the GNU General Public License, incorporated herein by reference.
- *
- *
- * Some passive ISDN cards, such as the Traverse NETJet and the AMD 7930,
- * don't perform HDLC encapsulation over the B channel.  Drivers for
- * such cards use support routines in this file to perform B channel HDLC.
- *
- * Bit-synchronous HDLC encapsulation is a means of encapsulating packets
- * over a continuously transmitting serial communications link.
- * It looks like this:
- *
- *      11111111101111110...........0111111011111111111
- *      iiiiiiiiiffffffffdddddddddddffffffffiiiiiiiiiii
- *
- *      i = idle     f = flag     d = data
- *
- * When idle, the channel sends a continuous string of ones (mark
- * idle; illustrated), or a continuous string of flag characters (flag
- * idle).  The beginning of a data frame is marked by a flag character
- * (01111110), then comes the actual data, followed by another flag
- * character, after which another frame may be sent immediately (a
- * single flag may serve as both the end of one frame and the start of
- * the next), or the link may return to idle.  Obviously, the flag
- * character can not appear anywhere in the data (or a false
- * end-of-frame would occur), so the transmitter performs
- * "bit-stuffing" - inserting a zero bit after every five one bits,
- * irregardless of the original bit after the five ones.  Byte
- * ordering is irrelevant at this point - the data is treated as a
- * string of bits, not bytes.  Since no more than 5 ones may now occur
- * in a row, the flag sequence, with its 6 ones, is unique.
- *
- * Upon reception, a zero bit that occur after 5 one bits is simply
- * discarded.  A series of 6 one bits is end-of-frame, and a series of
- * 7 one bits is an abort.  Once bit-stuffing has been corrected for,
- * an integer number of bytes should now be present.  The last two
- * of these bytes form the Frame Check Sequence, a CRC that is verified
- * and then discarded.  Note that bit-stuffing is performed on the FCS
- * just as if it were regular data.
- *
- *
- *
- * int make_raw_hdlc_data(u8 *src, u_int slen,
- *                        u8 *dst, u_int dsize)
- *
- *   Used for transmission.  Copies slen bytes from src to dst, performing
- *   HDLC encapsulation (flag bytes, bit-stuffing, CRC) in the process.
- *   dsize is size of destination buffer, and should be at least
- *   ((6*slen)/5)+5 bytes to ensure adequate space will be available.
- *   Function returns length (in bytes) of valid destination buffer, or
- *   0 upon destination overflow.
- *
- * void init_hdlc_state(struct hdlc_state *stateptr, int mode)
- *
- *   Initializes hdlc_state structure before first call to read_raw_hdlc_data
- *
- *   mode = 0: Sane mode
- *   mode = 1/2: 
- *             Insane mode; NETJet use a shared unsigned int memory block (
- * 	       with busmaster DMA), the bit pattern of every word is 
- *  	       <8 B1> <8 B2> <8 Mon> <2 D> <4 C/I> <MX> <MR>
- *	       according to Siemens IOM-2 interface, so we have to handle
- *             the src buffer as unsigned int and have to shift/mask the
- *             B-channel bytes.
- *             mode 1 -> B1  mode 2  -> B2 data is used
- *
- * int read_raw_hdlc_data(struct hdlc_state *saved_state,
- *                        u8 *src, u_int slen,
- *                        u8 *dst, u_int dsize)
- *
- *   Used for reception.  Scans source buffer bit-by-bit looking for
- *   valid HDLC frames, which are copied to destination buffer.  HDLC
- *   state information is stored in a structure, which allows this
- *   function to process frames spread across several blocks of raw
- *   HDLC data.  Part of the state information is bit offsets into
- *   the source and destination buffers.
- *
- *   A return value >0 indicates the length of a valid frame, now
- *   stored in the destination buffer.  In this case, the source
- *   buffer might not be completely processed, so this function should
- *   be called again with the same source buffer, possibly with a
- *   different destination buffer.
- *
- *   A return value of zero indicates that the source buffer was
- *   completely processed without finding a valid end-of-packet;
- *   however, we might be in the middle of packet reception, so
- *   the function should be called again with the next block of
- *   raw HDLC data and the same destination buffer.  It is NOT
- *   permitted to change the destination buffer in this case,
- *   since data may already have begun to be stored there.
- *
- *   A return value of -1 indicates some kind of error - destination
- *   buffer overflow, CRC check failed, frame not a multiple of 8
- *   bits.  Destination buffer probably contains invalid data, which
- *   should be discarded.  Call function again with same source buffer
- *   and a new (or same) destination buffer.
- *
- *   Suggested calling sequence:
- *
- *      init_hdlc_state(...);
- *      for (EACH_RAW_DATA_BLOCK) {
- *         while (len = read_raw_hdlc_data(...)) {
- *             if (len == -1) DISCARD_FRAME;
- *             else PROCESS_FRAME;
- *         }
- *      }
- *
- *
- * Test the code in this file as follows:
- *    gcc -DDEBUGME -o rawhdlctest rawhdlc.c
- *    ./rawhdlctest < rawdata
- *
- * The file "rawdata" can be easily generated from a HISAX B-channel
- * hex dump (CF CF CF 02 ...) using the following perl script:
- *
- * while(<>) {
- *     @hexlist = split ' ';
- *     while ($hexstr = shift(@hexlist)) {
- *         printf "%c", hex($hexstr);
- *     }
- * }
- *
- */
-
-#ifdef DEBUGME
-#include <stdio.h>
-#endif
-
-#include <linux/types.h>
-#include <linux/ppp_defs.h>
-#include "rawhdlc.h"
-
-/* There's actually an identical copy of this table in the PPP code
- * (ppp_crc16_table), but I don't want this code dependent on PPP
- */
-
-// static 
-__u16 fcstab[256] =
-{
-	0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf,
-	0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7,
-	0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e,
-	0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876,
-	0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd,
-	0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5,
-	0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c,
-	0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974,
-	0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb,
-	0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3,
-	0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a,
-	0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72,
-	0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9,
-	0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1,
-	0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738,
-	0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70,
-	0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7,
-	0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff,
-	0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036,
-	0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e,
-	0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5,
-	0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd,
-	0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134,
-	0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c,
-	0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3,
-	0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb,
-	0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232,
-	0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a,
-	0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1,
-	0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9,
-	0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330,
-	0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78
-};
-
-#define HDLC_ZERO_SEARCH 0
-#define HDLC_FLAG_SEARCH 1
-#define HDLC_FLAG_FOUND  2
-#define HDLC_FRAME_FOUND 3
-#define HDLC_NULL 4
-#define HDLC_PART 5
-#define HDLC_FULL 6
-
-#define HDLC_FLAG_VALUE	0x7e
-
-
-#define MAKE_RAW_BYTE for (j=0; j<8; j++) { \
-			bitcnt++;\
-			out_val >>= 1;\
-			if (val & 1) {\
-				s_one++;\
-				out_val |= 0x80;\
-			} else {\
-				s_one = 0;\
-				out_val &= 0x7f;\
-			}\
-			if (bitcnt==8) {\
-				if (d_cnt == dsize) return 0;\
-				dst[d_cnt++] = out_val;\
-				bitcnt = 0;\
-			}\
-			if (s_one == 5) {\
-				out_val >>= 1;\
-				out_val &= 0x7f;\
-				bitcnt++;\
-				s_one = 0;\
-			}\
-			if (bitcnt==8) {\
-				if (d_cnt == dsize) return 0;\
-				dst[d_cnt++] = out_val;\
-				bitcnt = 0;\
-			}\
-			val >>= 1;\
-		}
-
-/* Optimization suggestion: If needed, this function could be
- * dramatically sped up using a state machine.  Each state would
- * correspond to having seen N one bits, and being offset M bits into
- * the current output byte.  N ranges from 0 to 4, M from 0 to 7, so
- * we need 5*8 = 35 states.  Each state would have a table with 256
- * entries, one for each input character.  Each entry would contain
- * three output characters, an output state, an a byte increment
- * that's either 1 or 2.  All this could fit in four bytes; so we need
- * 4 bytes * 256 characters = 1 KB for each state (35 KB total).  Zero
- * the output buffer before you start.  For each character in your
- * input, you look it up in the current state's table and get three
- * bytes to be or'ed into the output at the current byte offset, and
- * an byte increment to move your pointer forward.  A simple Perl
- * script could generate the tables.  Given HDLC semantics, probably
- * would be better to set output to all 1s, then use ands instead of ors.
- * A smaller state machine could operate on nibbles instead of bytes.
- * A state machine for 32-bit architectures could use word offsets
- * instead of byte offsets, requiring 5*32 = 160 states; probably
- * best to work on nibbles in such a case.
- */
-
-
-int make_raw_hdlc_data(u8 *src, u_int slen, u8 *dst, u_int dsize)
-{
-	register u_int i,d_cnt=0;
-	register u8 j;
-	register u8 val;
-	register u8 s_one = 0;
-	register u8 out_val = 0;
-	register u8 bitcnt = 0;
-	u_int fcs;
-	
-	
-	dst[d_cnt++] = HDLC_FLAG_VALUE;
-	fcs = PPP_INITFCS;
-	for (i=0; i<slen; i++) {
-		val = src[i];
-		fcs = PPP_FCS (fcs, val);
-		MAKE_RAW_BYTE;
-	}
-	fcs ^= 0xffff;
-	val = fcs & 0xff;
-	MAKE_RAW_BYTE;
-	val = (fcs>>8) & 0xff;
-	MAKE_RAW_BYTE;
-	val = HDLC_FLAG_VALUE;
-	for (j=0; j<8; j++) { 
-		bitcnt++;
-		out_val >>= 1;
-		if (val & 1)
-			out_val |= 0x80;
-		else
-			out_val &= 0x7f;
-		if (bitcnt==8) {
-			if (d_cnt == dsize) return 0;
-			dst[d_cnt++] = out_val;
-			bitcnt = 0;
-		}
-		val >>= 1;
-	}
-	if (bitcnt) {
-		while (8>bitcnt++) {
-			out_val >>= 1;
-			out_val |= 0x80;
-		}
-		if (d_cnt == dsize) return 0;
-		dst[d_cnt++] = out_val;
-	}
-
-	return d_cnt;
-}
-
-void init_hdlc_state(struct hdlc_state *stateptr, int mode)
-{
-	stateptr->state = HDLC_ZERO_SEARCH;
-	stateptr->r_one = 0;
-	stateptr->r_val = 0;
-	stateptr->o_bitcnt = 0;
-	stateptr->i_bitcnt = 0;
-	stateptr->insane_mode = mode;
-}
-
-/* Optimization suggestion: A similar state machine could surely
- * be developed for this function as well.
- */
-
-int read_raw_hdlc_data(struct hdlc_state *saved_state,
-                       u8 *src, u_int slen, u8 *dst, u_int dsize)
-{
-	int retval=0;
-	register u8 val;
-	register u8 state = saved_state->state;
-	register u8 r_one = saved_state->r_one;
-	register u8 r_val = saved_state->r_val;
-	register u_int o_bitcnt = saved_state->o_bitcnt;
-	register u_int i_bitcnt = saved_state->i_bitcnt;
-	register u_int fcs    = saved_state->fcs;
-	register u_int *isrc = (u_int *) src;
-        
-	/* Use i_bitcnt (bit offset into source buffer) to reload "val"
-	 * in case we're starting up again partway through a source buffer
-	 */
-
-	if ((i_bitcnt >> 3) < slen) {
-		if (saved_state->insane_mode==1) {
-			val = isrc[(i_bitcnt >> 3)] & 0xff;
-		} else if (saved_state->insane_mode==2) {
-			val = (isrc[i_bitcnt >> 3] >>8) & 0xff;
-		} else {
-			val = src[i_bitcnt >> 3];
-		}
-		val >>= i_bitcnt & 7;
-	}
-
-	/* One bit per loop.  Keep going until we've got something to
-	 * report (retval != 0), or we exhaust the source buffer
-	 */
-
-	while ((retval == 0) && ((i_bitcnt >> 3) < slen)) {
-		if ((i_bitcnt & 7) == 0) {
-			if (saved_state->insane_mode==1) {
-				val = isrc[(i_bitcnt >> 3)] & 0xff;
-			} else if (saved_state->insane_mode==2) {
-				val = (isrc[i_bitcnt >> 3] >>8) & 0xff;
-			} else {
-				val = src[i_bitcnt >> 3];
-			}
-#ifdef DEBUGME
-			printf("Input byte %d: 0x%2x\n", i_bitcnt>>3, val);
-#endif
-			if (val == 0xff) {
-				state = HDLC_ZERO_SEARCH;
-				o_bitcnt = 0;
-				r_one = 0;
-				i_bitcnt += 8;
-				continue;
-			}
-		}
-
-#ifdef DEBUGME
-		/* printf("Data bit=%d (%d/%d)\n", val&1, i_bitcnt>>3, i_bitcnt&7);*/
-#endif
-
-		if (state == HDLC_ZERO_SEARCH) {
-			if (val & 1) {
-				r_one++;
-			} else {
-				r_one=0;
-				state= HDLC_FLAG_SEARCH;
-			}
-		} else if (state == HDLC_FLAG_SEARCH) { 
-			if (val & 1) {
-				r_one++;
-				if (r_one>6) {
-					state=HDLC_ZERO_SEARCH;
-				}
-			} else {
-				if (r_one==6) {
-					o_bitcnt=0;
-					r_val=0;
-					state=HDLC_FLAG_FOUND;
-				}
-				r_one=0;
-			}
-		} else if (state ==  HDLC_FLAG_FOUND) {
-			if (val & 1) {
-				r_one++;
-				if (r_one>6) {
-					state=HDLC_ZERO_SEARCH;
-				} else {
-					r_val >>= 1;
-					r_val |= 0x80;
-					o_bitcnt++;
-				}
-			} else {
-				if (r_one==6) {
-					o_bitcnt=0;
-					r_val=0;
-					r_one=0;
-					i_bitcnt++;
-					val >>= 1;
-					continue;
-				} else if (r_one!=5) {
-					r_val >>= 1;
-					r_val &= 0x7f;
-					o_bitcnt++;
-				}
-				r_one=0;	
-			}
-			if ((state != HDLC_ZERO_SEARCH) &&
-				!(o_bitcnt & 7)) {
-#ifdef DEBUGME
-				printf("HDLC_FRAME_FOUND at i_bitcnt:%d\n",i_bitcnt);
-#endif
-				state=HDLC_FRAME_FOUND;
-				fcs = PPP_INITFCS;
-				dst[0] = r_val;
-				fcs = PPP_FCS (fcs, r_val);
-			}
-		} else if (state ==  HDLC_FRAME_FOUND) {
-			if (val & 1) {
-				r_one++;
-				if (r_one>6) {
-					state=HDLC_ZERO_SEARCH;
-					o_bitcnt=0;
-				} else {
-					r_val >>= 1;
-					r_val |= 0x80;
-					o_bitcnt++;
-				}
-			} else {
-				if (r_one==6) {
-					r_val=0; 
-					r_one=0;
-					o_bitcnt++;
-					if (o_bitcnt & 7) {
-						/* Alignment error */
-#ifdef DEBUGME
-						printf("Alignment error\n");
-#endif
-						state=HDLC_FLAG_SEARCH;
-						retval = -1;
-					} else if (fcs==PPP_GOODFCS) {
-						/* Valid frame */
-						state=HDLC_FLAG_FOUND;
-						retval = (o_bitcnt>>3)-3;
-					} else {
-						/* CRC error */
-#ifdef DEBUGME
-						printf("CRC error; fcs was 0x%x, should have been 0x%x\n", fcs, PPP_GOODFCS);
-#endif
-						state=HDLC_FLAG_FOUND;
-						retval = -1;
-					}
-				} else if (r_one==5) {
-					r_one=0;
-					i_bitcnt++;
-					val >>= 1;
-					continue;
-				} else {
-					r_val >>= 1;
-					r_val &= 0x7f;
-					o_bitcnt++;
-				}
-				r_one=0;	
-			}
-			if ((state == HDLC_FRAME_FOUND) &&
-				!(o_bitcnt & 7)) {
-				if ((o_bitcnt>>3)>=dsize) {
-					/* Buffer overflow error */
-#ifdef DEBUGME
-					printf("Buffer overflow error\n");
-#endif
-					r_val=0; 
-					state=HDLC_FLAG_SEARCH;
-					retval = -1;
-				} else {
-					dst[(o_bitcnt>>3)-1] = r_val;
-					fcs = PPP_FCS (fcs, r_val);
-#ifdef DEBUGME
-					printf("Output byte %d: 0x%02x; FCS 0x%04x\n", (o_bitcnt>>3)-1, r_val, fcs);
-#endif
-				}
-			}
-		}
-		i_bitcnt ++;
-		val >>= 1;
-	}
-
-	/* We exhausted the source buffer before anything else happened
-	 * (retval==0).  Reset i_bitcnt in expectation of a new source
-	 * buffer.  Other, we either had an error or a valid frame, so
-	 * reset o_bitcnt in expectation of a new destination buffer.
-	 */
-
-	if (retval == 0) {
-		i_bitcnt = 0;
-	} else {
-		o_bitcnt = 0;
-	}
-
-	saved_state->state = state;
-	saved_state->r_one = r_one;
-	saved_state->r_val = r_val;
-	saved_state->fcs = fcs;
-	saved_state->o_bitcnt = o_bitcnt;
-	saved_state->i_bitcnt = i_bitcnt;
-
-	return (retval);
-}
-
-
-
-#ifdef DEBUGME
-
-char buffer[1024];
-char obuffer[1024];
-
-main()
-{
-  int buflen=0;
-  int len;
-  struct hdlc_state hdlc_state;
-
-  while((buffer[buflen] = getc(stdin)) != EOF && buflen<1024) buflen++;
-
-  printf("buflen = %d\n", buflen);
-
-  init_hdlc_state(&hdlc_state, 0);
-
-  while (len = read_raw_hdlc_data(&hdlc_state,buffer,buflen,obuffer,1024)) {
-    if (len == -1) printf("Error @ byte %d/bit %d\n",
-			  hdlc_state.i_bitcnt>>3, hdlc_state.i_bitcnt & 7);
-    else {
-      printf("Frame received: len %d\n", len);
-    }
-  }
-
-  printf("Done\n");
-}
-
-#endif
--- diff/drivers/isdn/hisax/rawhdlc.h	2003-01-13 14:18:15.000000000 +0000
+++ source/drivers/isdn/hisax/rawhdlc.h	1970-01-01 01:00:00.000000000 +0100
@@ -1,28 +0,0 @@
-/* $Id: rawhdlc.h,v 1.3.6.2 2001/09/23 22:24:51 kai Exp $
- *
- * Author     Brent Baccala
- * Copyright  by Brent Baccala <baccala@FreeSoft.org>
- *
- * This software may be used and distributed according to the terms
- * of the GNU General Public License, incorporated herein by reference.
- *
- */
-
-#ifndef RAWHDLC_H
-struct hdlc_state {
-	char insane_mode;
-	u8 state;
-	u8 r_one;
-	u8 r_val;
-	u_int o_bitcnt;
-	u_int i_bitcnt;
-	u_int fcs;
-};
-
-
-int make_raw_hdlc_data(u8 *src, u_int slen, u8 *dst, u_int dsize);
-void init_hdlc_state(struct hdlc_state *stateptr, int mode);
-int read_raw_hdlc_data(struct hdlc_state *saved_state,
-                       u8 *src, u_int slen, u8 *dst, u_int dsize);
-#define RAWHDLC_H
-#endif
--- diff/drivers/isdn/i4l/isdn_ciscohdlck.c	2002-11-11 11:09:36.000000000 +0000
+++ source/drivers/isdn/i4l/isdn_ciscohdlck.c	1970-01-01 01:00:00.000000000 +0100
@@ -1,452 +0,0 @@
-/* Linux ISDN subsystem, CISCO HDLC network interfaces
- *
- * Copyright 1994-1998  by Fritz Elfert (fritz@isdn4linux.de)
- *           1995,96    by Thinking Objects Software GmbH Wuerzburg
- *           1995,96    by Michael Hipp (Michael.Hipp@student.uni-tuebingen.de)
- *           1999-2002  by Kai Germaschewski <kai@germaschewski.name>
- *           2001       by Bjoern A. Zeeb <i4l@zabbadoz.net>
- *
- * This software may be used and distributed according to the terms
- * of the GNU General Public License, incorporated herein by reference.
- *
- * For info on the protocol, see http://i4l.zabbadoz.net/i4l/cisco-hdlc.txt
- */
-
-#include "isdn_common.h"
-#include "isdn_net_lib.h"
-#include "isdn_ciscohdlck.h"
-
-#include <linux/if_arp.h>
-#include <linux/inetdevice.h>
-
-/*
- * Definitions for Cisco-HDLC header.
- */
-
-#define CISCO_ADDR_UNICAST    0x0f
-#define CISCO_ADDR_BROADCAST  0x8f
-#define CISCO_CTRL            0x00
-#define CISCO_TYPE_CDP        0x2000
-#define CISCO_TYPE_SLARP      0x8035
-#define CISCO_SLARP_REQUEST   0
-#define CISCO_SLARP_REPLY     1
-#define CISCO_SLARP_KEEPALIVE 2
-
-/* 
- * CISCO HDLC keepalive specific stuff
- */
-static struct sk_buff*
-isdn_net_ciscohdlck_alloc_skb(isdn_net_dev *idev, int len)
-{
-	unsigned short hl = isdn_slot_hdrlen(idev->isdn_slot);
-	struct sk_buff *skb;
-
-	skb = alloc_skb(hl + len, GFP_ATOMIC);
-	if (!skb) {
-		printk("isdn out of mem at %s:%d!\n", __FILE__, __LINE__);
-		return NULL;
-	}
-	skb_reserve(skb, hl);
-	return skb;
-}
-
-/* cisco hdlck device private ioctls */
-static int
-isdn_ciscohdlck_dev_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
-{
-	isdn_net_local *mlp = dev->priv;
-	struct inl_cisco *cisco = mlp->inl_priv;
-	unsigned long len = 0;
-	int period;
-	char debserint;
-	int rc = 0;
-
-	if (mlp->p_encap != ISDN_NET_ENCAP_CISCOHDLCK)
-		return -EINVAL;
-
-	switch (cmd) {
-		/* get/set keepalive period */
-		case SIOCGKEEPPERIOD:
-			len = sizeof(cisco->keepalive_period);
-			if (copy_to_user((char *)ifr->ifr_ifru.ifru_data,
-					 (char *)&cisco->keepalive_period, len))
-				rc = -EFAULT;
-			break;
-		case SIOCSKEEPPERIOD:
-			len = sizeof(cisco->keepalive_period);
-			if (copy_from_user((char *)&period,
-					   (char *)ifr->ifr_ifru.ifru_data, len)) {
-				rc = -EFAULT;
-				break;
-			}
-			if (period <= 0 || period > 32767) {
-				rc = -EINVAL;
-				break;
-			}
-			mod_timer(&cisco->timer, jiffies + period * HZ);
-			printk(KERN_INFO "%s: Keepalive period set "
-			       "to %d seconds.\n", dev->name, period);
-			cisco->keepalive_period = period;
-			break;
-
-		/* get/set debugging */
-		case SIOCGDEBSERINT:
-			len = sizeof(cisco->debserint);
-			if (copy_to_user((char *)ifr->ifr_ifru.ifru_data,
-					 (char *)&cisco->debserint, len))
-				rc = -EFAULT;
-			break;
-		case SIOCSDEBSERINT:
-			len = sizeof(cisco->debserint);
-			if (copy_from_user((char *)&debserint,
-					   (char *)ifr->ifr_ifru.ifru_data, len)) {
-				rc = -EFAULT;
-				break;
-			}
-			if (debserint < 0 || debserint > 64) {
-				rc = -EINVAL;
-				break;
-			}
-			cisco->debserint = debserint;
-			break;
-
-		default:
-			rc = -EINVAL;
-			break;
-	}
-	return (rc);
-}
-
-/* called via cisco_timer.function */
-static void
-isdn_net_ciscohdlck_slarp_send_keepalive(unsigned long data)
-{
-	isdn_net_local *mlp = (isdn_net_local *) data;
- 	isdn_net_dev *idev;
-	struct inl_cisco *cisco = mlp->inl_priv;
-	struct sk_buff *skb;
-	unsigned char *p;
-	unsigned long last_cisco_myseq = cisco->myseq;
-	int myseq_diff = 0;
-
-	if (list_empty(&mlp->online)) {
-		isdn_BUG();
-		return;
-	}
-	idev = list_entry(mlp->online.next, isdn_net_dev, online);
-	cisco->myseq++;
-
-	myseq_diff = cisco->myseq - cisco->mineseen;
-	if (cisco->line_state && (myseq_diff >= 3 || myseq_diff <= -3)) {
-		/* line up -> down */
-		cisco->line_state = 0;
-		printk (KERN_WARNING
-				"UPDOWN: Line protocol on Interface %s,"
-				" changed state to down\n", idev->name);
-		/* should stop routing higher-level data accross */
-	} else if (!cisco->line_state &&
-		myseq_diff >= 0 && myseq_diff <= 2) {
-		/* line down -> up */
-		cisco->line_state = 1;
-		printk (KERN_WARNING
-				"UPDOWN: Line protocol on Interface %s,"
-				" changed state to up\n", idev->name);
-		/* restart routing higher-level data accross */
-	}
-
-	if (cisco->debserint)
-		printk (KERN_DEBUG "%s: HDLC "
-			"myseq %u, mineseen %u%c, yourseen %u, %s\n",
-			idev->name, cisco->myseq, cisco->mineseen,
-			(last_cisco_myseq == cisco->mineseen) ? '*' : 040,
-			cisco->yourseq,
-			(cisco->line_state) ? "line up" : "line down");
-
-	skb = isdn_net_ciscohdlck_alloc_skb(idev, 4 + 14);
-	if (!skb)
-		return;
-
-	p = skb_put(skb, 4 + 14);
-
-	/* cisco header */
-	p += put_u8 (p, CISCO_ADDR_UNICAST);
-	p += put_u8 (p, CISCO_CTRL);
-	p += put_u16(p, CISCO_TYPE_SLARP);
-
-	/* slarp keepalive */
-	p += put_u32(p, CISCO_SLARP_KEEPALIVE);
-	p += put_u32(p, cisco->myseq);
-	p += put_u32(p, cisco->yourseq);
-	p += put_u16(p, 0xffff); // reliablity, always 0xffff
-
-	isdn_net_write_super(idev, skb);
-
-	mod_timer(&cisco->timer, jiffies + cisco->keepalive_period * HZ);
-}
-
-static void
-isdn_net_ciscohdlck_slarp_send_request(isdn_net_local *mlp)
-{
-	isdn_net_dev *idev;
-	struct sk_buff *skb;
-	unsigned char *p;
-
-	if (list_empty(&mlp->online)) {
-		isdn_BUG();
-		return;
-	}
-	idev = list_entry(mlp->online.next, isdn_net_dev, online);
-
-	skb = isdn_net_ciscohdlck_alloc_skb(idev, 4 + 14);
-	if (!skb)
-		return;
-
-	p = skb_put(skb, 4 + 14);
-
-	/* cisco header */
-	p += put_u8 (p, CISCO_ADDR_UNICAST);
-	p += put_u8 (p, CISCO_CTRL);
-	p += put_u16(p, CISCO_TYPE_SLARP);
-
-	/* slarp request */
-	p += put_u32(p, CISCO_SLARP_REQUEST);
-	p += put_u32(p, 0); // address
-	p += put_u32(p, 0); // netmask
-	p += put_u16(p, 0); // unused
-
-	isdn_net_write_super(idev, skb);
-}
-
-static void 
-isdn_ciscohdlck_connected(isdn_net_dev *idev)
-{
-	isdn_net_local *lp = idev->mlp;
-	struct inl_cisco *cisco = lp->inl_priv;
-
-	cisco->myseq = 0;
-	cisco->mineseen = 0;
-	cisco->yourseq = 0;
-	cisco->keepalive_period = 10;
-	cisco->last_slarp_in = 0;
-	cisco->line_state = 0;
-	cisco->debserint = 0;
-
-	if (lp->p_encap == ISDN_NET_ENCAP_CISCOHDLCK) {
-		/* send slarp request because interface/seq.no.s reset */
-		isdn_net_ciscohdlck_slarp_send_request(lp);
-
-		init_timer(&cisco->timer);
-		cisco->timer.data = (unsigned long) lp;
-		cisco->timer.function = isdn_net_ciscohdlck_slarp_send_keepalive;
-		cisco->timer.expires = jiffies + cisco->keepalive_period * HZ;
-		add_timer(&cisco->timer);
-	}
-	netif_wake_queue(&lp->dev);
-}
-
-static void 
-isdn_ciscohdlck_disconnected(isdn_net_dev *idev)
-{
-	isdn_net_local *lp = idev->mlp;
-	struct inl_cisco *cisco = lp->inl_priv;
-
-	if (lp->p_encap == ISDN_NET_ENCAP_CISCOHDLCK) {
-		del_timer(&cisco->timer);
-	}
-}
-
-static void
-isdn_net_ciscohdlck_slarp_send_reply(isdn_net_dev *idev)
-{
-	isdn_net_local *mlp = idev->mlp;
-	struct sk_buff *skb;
-	unsigned char *p;
-	struct in_device *in_dev = NULL;
-	u32 addr = 0;		/* local ipv4 address */
-	u32 mask = 0;		/* local netmask */
-
-	if ((in_dev = mlp->dev.ip_ptr) != NULL) {
-		/* take primary(first) address of interface */
-		struct in_ifaddr *ifa = in_dev->ifa_list;
-		if (ifa != NULL) {
-			addr = ifa->ifa_local;
-			mask = ifa->ifa_mask;
-		}
-	}
-
-	skb = isdn_net_ciscohdlck_alloc_skb(idev, 4 + 14);
-	if (!skb)
-		return;
-
-	p = skb_put(skb, 4 + 14);
-
-	/* cisco header */
-	p += put_u8 (p, CISCO_ADDR_UNICAST);
-	p += put_u8 (p, CISCO_CTRL);
-	p += put_u16(p, CISCO_TYPE_SLARP);
-
-	/* slarp reply, send own ip/netmask; if values are nonsense remote
-	 * should think we are unable to provide it with an address via SLARP */
-	p += put_u32(p, CISCO_SLARP_REPLY);
-	p += put_u32(p, addr);	// address
-	p += put_u32(p, mask);	// netmask
-	p += put_u16(p, 0);	// unused
-
-	isdn_net_write_super(idev, skb);
-}
-
-static void
-isdn_net_ciscohdlck_slarp_in(isdn_net_dev *idev, struct sk_buff *skb)
-{
-	isdn_net_local *mlp = idev->mlp;
-	struct inl_cisco *cisco = mlp->inl_priv;
-	unsigned char *p;
-	int period;
-	u32 code;
-	u32 my_seq, addr;
-	u32 your_seq, mask;
-	u32 local;
-	u16 unused;
-
-	if (skb->len < 14)
-		return;
-
-	p = skb->data;
-	p += get_u32(p, &code);
-	
-	switch (code) {
-	case CISCO_SLARP_REQUEST:
-		cisco->yourseq = 0;
-		isdn_net_ciscohdlck_slarp_send_reply(idev);
-		break;
-	case CISCO_SLARP_REPLY:
-		addr = ntohl(*(u32 *)p);
-		mask = ntohl(*(u32 *)(p+4));
-		if (mask != 0xfffffffc)
-			goto slarp_reply_out;
-		if ((addr & 3) == 0 || (addr & 3) == 3)
-			goto slarp_reply_out;
-		local = addr ^ 3;
-		printk(KERN_INFO "%s: got slarp reply: "
-			"remote ip: %d.%d.%d.%d, "
-			"local ip: %d.%d.%d.%d "
-			"mask: %d.%d.%d.%d\n",
-		       idev->name,
-		       HIPQUAD(addr),
-		       HIPQUAD(local),
-		       HIPQUAD(mask));
-		break;
-  slarp_reply_out:
-		 printk(KERN_INFO "%s: got invalid slarp "
-				 "reply (%d.%d.%d.%d/%d.%d.%d.%d) "
-				 "- ignored\n", idev->name,
-				 HIPQUAD(addr), HIPQUAD(mask));
-		break;
-	case CISCO_SLARP_KEEPALIVE:
-		period = (jiffies - cisco->last_slarp_in + HZ/2 - 1) / HZ;
-		if (cisco->debserint &&
-				(period != cisco->keepalive_period) &&
-				cisco->last_slarp_in) {
-			printk(KERN_DEBUG "%s: Keepalive period mismatch - "
-				"is %d but should be %d.\n",
-				idev->name, period, cisco->keepalive_period);
-		}
-		cisco->last_slarp_in = jiffies;
-		p += get_u32(p, &my_seq);
-		p += get_u32(p, &your_seq);
-		p += get_u16(p, &unused);
-		cisco->yourseq = my_seq;
-		cisco->mineseen = your_seq;
-		break;
-	}
-}
-
-static void 
-isdn_ciscohdlck_receive(isdn_net_local *lp, isdn_net_dev *idev,
-			struct sk_buff *skb)
-{
-	struct inl_cisco *cisco = lp->inl_priv;
-	unsigned char *p;
- 	u8 addr;
- 	u8 ctrl;
- 	u16 type;
-	
-	if (skb->len < 4)
-		goto out_free;
-
-	p = skb->data;
-	p += get_u8 (p, &addr);
-	p += get_u8 (p, &ctrl);
-	p += get_u16(p, &type);
-	skb_pull(skb, 4);
-	
-	if ((addr != CISCO_ADDR_UNICAST && addr != CISCO_ADDR_BROADCAST) ||
-	    ctrl != CISCO_CTRL) {
-		printk(KERN_DEBUG "%s: Unknown Cisco header %#02x %#02x\n",
-		       idev->name, addr, ctrl);
-		goto out_free;
-	}
-
-	switch (type) {
-	case CISCO_TYPE_SLARP:
-		isdn_net_ciscohdlck_slarp_in(idev, skb);
-		goto out_free;
-	case CISCO_TYPE_CDP:
-		if (cisco->debserint)
-			printk(KERN_DEBUG "%s: Received CDP packet. use "
-				"\"no cdp enable\" on cisco.\n", idev->name);
-		goto out_free;
-	default:
-		/* no special cisco protocol */
-		idev->huptimer = 0;
-		skb->protocol = htons(type);
-		netif_rx(skb);
-		return;
-	}
-
- out_free:
-	kfree_skb(skb);
-}
-
-static int
-isdn_ciscohdlck_header(struct sk_buff *skb, struct net_device *dev, 
-		      unsigned short type,
-		      void *daddr, void *saddr, unsigned plen)
-{
-	unsigned char *p = skb_push(skb, 4);
-
-	p += put_u8 (p, CISCO_ADDR_UNICAST);
-	p += put_u8 (p, CISCO_CTRL);
-	p += put_u16(p, type);
-	
-	return 4;
-}
-
-static int
-isdn_ciscohdlck_open(isdn_net_local *lp)
-{
-	lp->inl_priv = kmalloc(sizeof(struct inl_cisco), GFP_KERNEL);
-	if (!lp->inl_priv)
-		return -ENOMEM;
-
-	return 0;
-}
-
-static void
-isdn_ciscohdlck_close(isdn_net_local *lp)
-{
-	kfree(lp->inl_priv);
-}
-
-struct isdn_netif_ops isdn_ciscohdlck_ops = {
-	.hard_start_xmit     = isdn_net_start_xmit,
-	.hard_header         = isdn_ciscohdlck_header,
-	.do_ioctl            = isdn_ciscohdlck_dev_ioctl,
-	.flags               = IFF_NOARP | IFF_POINTOPOINT,
-	.type                = ARPHRD_CISCO,
-	.receive             = isdn_ciscohdlck_receive,
-	.connected           = isdn_ciscohdlck_connected,
-	.disconnected        = isdn_ciscohdlck_disconnected,
-	.open                = isdn_ciscohdlck_open,
-	.close               = isdn_ciscohdlck_close,
-};
--- diff/drivers/isdn/i4l/isdn_ciscohdlck.h	2002-11-11 11:09:36.000000000 +0000
+++ source/drivers/isdn/i4l/isdn_ciscohdlck.h	1970-01-01 01:00:00.000000000 +0100
@@ -1,26 +0,0 @@
-/* Linux ISDN subsystem, CISCO HDLC network interfaces
- *
- * Copyright 1999-2002  by Kai Germaschewski <kai@germaschewski.name>
- *           2001       by Bjoern A. Zeeb <i4l@zabbadoz.net>
- *
- * This software may be used and distributed according to the terms
- * of the GNU General Public License, incorporated herein by reference.
- */
-
-#ifndef ISDN_CISCOHDLCK_H
-#define ISDN_CISCOHDLCK_H
-
-extern struct isdn_netif_ops isdn_ciscohdlck_ops;
-
-struct inl_cisco {
-	u32 myseq;             /* local keepalive seq. for Cisco */
-	u32 mineseen;          /* returned keepalive seq. from remote */
-	u32 yourseq;           /* remote keepalive seq. for Cisco  */
-	int keepalive_period;  /* keepalive period */
-	int last_slarp_in;     /* jiffie of last recvd keepalive pkt */
-	char line_state;       /* state of line */
-	char debserint;	       /* debugging flags */
-	struct timer_list timer;
-};
-
-#endif
--- diff/drivers/isdn/i4l/isdn_fsm.c	2002-11-11 11:09:36.000000000 +0000
+++ source/drivers/isdn/i4l/isdn_fsm.c	1970-01-01 01:00:00.000000000 +0100
@@ -1,166 +0,0 @@
-/* Linux ISDN subsystem, finite state machine
- *
- * Author       Karsten Keil
- * Copyright              by Karsten Keil      <keil@isdn4linux.de>
- *              2001-2002 by Kai Germaschewski <kai@germaschewski.name>
- * 
- * This software may be used and distributed according to the terms
- * of the GNU General Public License, incorporated herein by reference.
- *
- * Thanks to    Jan den Ouden
- *              Fritz Elfert
- */
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/slab.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/isdn/fsm.h>
-
-int
-fsm_new(struct fsm *fsm)
-{
-	int i;
-	int size = sizeof(fsm_fn) * fsm->st_cnt * fsm->ev_cnt;
-
-	fsm->jumpmatrix = kmalloc(size, GFP_KERNEL);
-	if (!fsm->jumpmatrix)
-		return -ENOMEM;
-
-	memset(fsm->jumpmatrix, 0, size);
-
-	for (i = 0; i < fsm->fn_cnt; i++) {
-		if (fsm->fn_tbl[i].st >= fsm->st_cnt || 
-		    fsm->fn_tbl[i].ev >= fsm->ev_cnt) {
-			printk(KERN_ERR "FsmNew Error line %d st(%d/%d) ev(%d/%d)\n", i,
-			       fsm->fn_tbl[i].st, fsm->st_cnt, 
-			       fsm->fn_tbl[i].ev, fsm->ev_cnt);
-			continue;
-		}
-		fsm->jumpmatrix[fsm->st_cnt * fsm->fn_tbl[i].ev + fsm->fn_tbl[i].st] = fsm->fn_tbl[i].fn;
-	}
-	return 0;
-}
-
-void
-fsm_free(struct fsm *fsm)
-{
-	kfree(fsm->jumpmatrix);
-}
-
-int
-fsm_event(struct fsm_inst *fi, int event, void *arg)
-{
-	fsm_fn fn;
-
-	if (fi->state >= fi->fsm->st_cnt || 
-	    event >= fi->fsm->ev_cnt) {
-		printk(KERN_ERR "FsmEvent Error st(%d/%d) ev(%d/%d)\n",
-		       fi->state, fi->fsm->st_cnt,event, 
-		       fi->fsm->ev_cnt);
-		return -EINVAL;
-	}
-	fn = fi->fsm->jumpmatrix[fi->fsm->st_cnt * event + fi->state];
-	if (!fn) {
-		if (fi->debug)
-			fi->printdebug(fi, "State %s Event %s no routine",
-				       fi->fsm->st_str[fi->state],
-				       fi->fsm->ev_str[event]);
-		return -ESRCH;
-	}
-	if (fi->debug)
-		fi->printdebug(fi, "State %s Event %s",
-			       fi->fsm->st_str[fi->state],
-			       fi->fsm->ev_str[event]);
-
-	return fn(fi, event, arg);
-}
-
-void
-fsm_change_state(struct fsm_inst *fi, int newstate)
-{
-	fi->state = newstate;
-	if (fi->debug)
-		fi->printdebug(fi, "ChangeState %s",
-			       fi->fsm->st_str[newstate]);
-}
-
-#if 0
-static void
-FsmExpireTimer(struct FsmTimer *ft)
-{
-#if FSM_TIMER_DEBUG
-	if (ft->fi->debug)
-		ft->fi->printdebug(ft->fi, "FsmExpireTimer %lx", (long) ft);
-#endif
-	FsmEvent(ft->fi, ft->event, ft->arg);
-}
-
-void
-FsmInitTimer(struct FsmInst *fi, struct FsmTimer *ft)
-{
-	ft->fi = fi;
-	ft->tl.function = (void *) FsmExpireTimer;
-	ft->tl.data = (long) ft;
-#if FSM_TIMER_DEBUG
-	if (ft->fi->debug)
-		ft->fi->printdebug(ft->fi, "FsmInitTimer %lx", (long) ft);
-#endif
-	init_timer(&ft->tl);
-}
-
-void
-FsmDelTimer(struct FsmTimer *ft, int where)
-{
-#if FSM_TIMER_DEBUG
-	if (ft->fi->debug)
-		ft->fi->printdebug(ft->fi, "FsmDelTimer %lx %d", (long) ft, where);
-#endif
-	del_timer(&ft->tl);
-}
-
-int
-FsmAddTimer(struct FsmTimer *ft,
-	    int millisec, int event, void *arg, int where)
-{
-
-#if FSM_TIMER_DEBUG
-	if (ft->fi->debug)
-		ft->fi->printdebug(ft->fi, "FsmAddTimer %lx %d %d",
-			(long) ft, millisec, where);
-#endif
-
-	if (timer_pending(&ft->tl)) {
-		printk(KERN_WARNING "FsmAddTimer: timer already active!\n");
-		ft->fi->printdebug(ft->fi, "FsmAddTimer already active!");
-		return -1;
-	}
-	init_timer(&ft->tl);
-	ft->event = event;
-	ft->arg = arg;
-	ft->tl.expires = jiffies + (millisec * HZ) / 1000;
-	add_timer(&ft->tl);
-	return 0;
-}
-
-void
-FsmRestartTimer(struct FsmTimer *ft,
-	    int millisec, int event, void *arg, int where)
-{
-
-#if FSM_TIMER_DEBUG
-	if (ft->fi->debug)
-		ft->fi->printdebug(ft->fi, "FsmRestartTimer %lx %d %d",
-			(long) ft, millisec, where);
-#endif
-
-	if (timer_pending(&ft->tl))
-		del_timer(&ft->tl);
-	init_timer(&ft->tl);
-	ft->event = event;
-	ft->arg = arg;
-	ft->tl.expires = jiffies + (millisec * HZ) / 1000;
-	add_timer(&ft->tl);
-}
-#endif
--- diff/drivers/isdn/i4l/isdn_net_lib.c	2003-09-17 12:28:06.000000000 +0100
+++ source/drivers/isdn/i4l/isdn_net_lib.c	1970-01-01 01:00:00.000000000 +0100
@@ -1,2342 +0,0 @@
-/* Linux ISDN subsystem, network interface support code
- *
- * Copyright 1994-1998  by Fritz Elfert (fritz@isdn4linux.de)
- *           1995,96    by Thinking Objects Software GmbH Wuerzburg
- *           1995,96    by Michael Hipp (Michael.Hipp@student.uni-tuebingen.de)
- *           1999-2002  by Kai Germaschewski <kai@germaschewski.name>
- *
- * This software may be used and distributed according to the terms
- * of the GNU General Public License, incorporated herein by reference.
- */
-
-/*
- * Data Over Voice (DOV) support added - Guy Ellis 23-Mar-02 
- *                                       guy@traverse.com.au
- * Outgoing calls - looks for a 'V' in first char of dialed number
- * Incoming calls - checks first character of eaz as follows:
- *   Numeric - accept DATA only - original functionality
- *   'V'     - accept VOICE (DOV) only
- *   'B'     - accept BOTH DATA and DOV types
- *
- */
-
-/* Locking works as follows: 
- *
- * The configuration of isdn_net_devs works via ioctl on
- * /dev/isdnctrl (for legacy reasons).
- * All configuration accesses are globally serialized by means of
- * the global semaphore &sem.
- * 
- * All other uses of isdn_net_dev will only happen when the corresponding
- * struct net_device has been opened. So in the non-config code we can
- * rely on the config data not changing under us.
- *
- * To achieve this, in the "writing" ioctls, that is those which may change
- * data, additionally grep the rtnl semaphore and check to make sure
- * that the net_device has not been openend ("netif_running()")
- *
- * isdn_net_dev's are added to the global list "isdn_net_devs" in the
- * configuration ioctls, so accesses to that list are protected by
- * &sem as well.
- *
- * Incoming calls are signalled in IRQ context, so we cannot take &sem
- * while walking the list of devices. To handle this, we put devices
- * onto a "running" list, which is protected by a spin lock and can thus
- * be traversed in IRQ context. If a matching isdn_net_dev is found,
- * it's ref count shall be incremented, to make sure no racing
- * net_device::close() can take it away under us. 
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/skbuff.h>
-#include <linux/socket.h>
-#include <linux/capability.h>
-#include <linux/rtnetlink.h>
-#include "isdn_common.h"
-#include "isdn_net_lib.h"
-#include "isdn_net.h"
-#include "isdn_ppp.h"
-#include "isdn_ciscohdlck.h"
-#include "isdn_concap.h"
-
-#define ISDN_NET_TX_TIMEOUT (20*HZ) 
-
-/* All of this configuration code is globally serialized */
-
-static DECLARE_MUTEX(sem);
-LIST_HEAD(isdn_net_devs); /* Linked list of isdn_net_dev's */ // FIXME static
-
-/* Reference counting for net devices (they work on isdn_net_local *,
- * but count references to the related isdn_net_dev's as well.
- * Basic rule: When state of isdn_net_dev changes from ST_NULL -> sth,
- * get a reference, when it changes back to ST_NULL, put it
- */ 
-
-static inline void
-lp_get(isdn_net_local *lp)
-{
-	if (atomic_read(&lp->refcnt) < 1)
-		isdn_BUG();
-
-	atomic_inc(&lp->refcnt);
-}
-
-static inline void
-lp_put(isdn_net_local *lp)
-{
-	atomic_dec(&lp->refcnt);
-
-	/* the last reference, the list should always remain */
-	if (atomic_read(&lp->refcnt) < 1)
-		isdn_BUG();
-}
-
-static int isdn_net_handle_event(isdn_net_dev *idev, int pr, void *arg);
-static void isdn_net_tasklet(unsigned long data);
-static void isdn_net_dial_timer(unsigned long data);
-static int isdn_init_netif(struct net_device *ndev);
-static void isdn_net_dev_debug(struct fsm_inst *fi, char *fmt, ...);
-static int isdn_net_dial(isdn_net_dev *idev);
-static int isdn_net_bsent(isdn_net_dev *idev, isdn_ctrl *c);
-
-static struct fsm isdn_net_fsm;
-
-enum {
-	ST_NULL,
-	ST_OUT_BOUND,
-	ST_OUT_WAIT_DCONN,
-	ST_OUT_WAIT_BCONN,
-	ST_IN_WAIT_DCONN,
-	ST_IN_WAIT_BCONN,
-	ST_ACTIVE,
-	ST_WAIT_DHUP,
-	ST_WAIT_BEFORE_CB,
-	ST_OUT_DIAL_WAIT,
-};
-
-static char *isdn_net_st_str[] = {
-	"ST_NULL",
-	"ST_OUT_BOUND",
-	"ST_OUT_WAIT_DCONN",
-	"ST_OUT_WAIT_BCONN",
-	"ST_IN_WAIT_DCONN",
-	"ST_IN_WAIT_BCONN",
-	"ST_ACTIVE",
-	"ST_WAIT_DHUP",
-	"ST_WAIT_BEFORE_CB",
-	"ST_OUT_DIAL_WAIT",
-};
-
-enum {
-	EV_NET_TIMER_INCOMING,
-	EV_NET_TIMER_DIAL,
-	EV_NET_TIMER_DIAL_WAIT,
-	EV_NET_TIMER_CB_OUT,
-	EV_NET_TIMER_CB_IN,
-	EV_NET_TIMER_HUP,
-	EV_NET_STAT_DCONN,
-	EV_NET_STAT_BCONN,
-	EV_NET_STAT_DHUP,
-	EV_NET_STAT_BHUP,
-	EV_NET_STAT_CINF,
-	EV_NET_STAT_BSENT,
-	EV_NET_DO_DIAL,
-	EV_NET_DO_CALLBACK,
-	EV_NET_DO_ACCEPT,
-};
-
-static char *isdn_net_ev_str[] = {
-	"EV_NET_TIMER_INCOMING",
-	"EV_NET_TIMER_DIAL",
-	"EV_NET_TIMER_DIAL_WAIT",
-	"EV_NET_TIMER_CB_OUT",
-	"EV_NET_TIMER_CB_IN",
-	"EV_NET_TIMER_HUP",
-	"EV_NET_STAT_DCONN",
-	"EV_NET_STAT_BCONN",
-	"EV_NET_STAT_DHUP",
-	"EV_NET_STAT_BHUP",
-	"EV_NET_STAT_CINF",
-	"EV_NET_STAT_BSENT",
-	"EV_NET_DO_DIAL",
-	"EV_NET_DO_CALLBACK",
-	"EV_NET_DO_ACCEPT",
-};
-
-/* Definitions for hupflags: */
-
-#define ISDN_CHARGEHUP   4      /* We want to use the charge mechanism      */
-#define ISDN_INHUP       8      /* Even if incoming, close after huptimeout */
-#define ISDN_MANCHARGE  16      /* Charge Interval manually set             */
-
-enum {
-	ST_CHARGE_NULL,
-	ST_CHARGE_GOT_CINF,  /* got a first charge info */
-	ST_CHARGE_HAVE_CINT, /* got a second chare info and thus the timing */
-};
-
-/* ====================================================================== */
-/* Registration of ISDN network interface types                           */
-/* ====================================================================== */
-
-static struct isdn_netif_ops *isdn_netif_ops[ISDN_NET_ENCAP_NR];
-
-int
-register_isdn_netif(int encap, struct isdn_netif_ops *ops)
-{
-	if (encap < 0 || encap >= ISDN_NET_ENCAP_NR)
-		return -EINVAL;
-
-	if (isdn_netif_ops[encap])
-		return -EBUSY;
-
-	isdn_netif_ops[encap] = ops;
-
-	return 0;
-}
-
-/* ====================================================================== */
-/* Helpers                                                                */
-/* ====================================================================== */
-
-/* Search list of net-interfaces for an interface with given name. */
-
-static isdn_net_dev *
-isdn_net_findif(char *name)
-{
-	isdn_net_dev *idev;
-
-	list_for_each_entry(idev, &isdn_net_devs, global_list) {
-		if (!strcmp(idev->name, name))
-			return idev;
-	}
-	return NULL;
-}
-
-/* Set up a certain encapsulation */
-
-static int
-isdn_net_set_encap(isdn_net_local *lp, int encap)
-{
-	int retval = 0;
-
-	if (lp->p_encap == encap){
-		/* nothing to do */
-		retval = 0;
-		goto out;
-	}
-	if (netif_running(&lp->dev)) {
-		retval = -EBUSY;
-		goto out;
-	}
-	if (lp->ops && lp->ops->cleanup)
-		lp->ops->cleanup(lp);
-
-	if (encap < 0 || encap >= ISDN_NET_ENCAP_NR ||
-	    !isdn_netif_ops[encap]) {
-		lp->p_encap = -1;
-		lp->ops = NULL;
-		retval = -EINVAL;
-		goto out;
-	}
-
-	lp->p_encap = encap;
-	lp->ops = isdn_netif_ops[encap];
-
-	lp->dev.hard_start_xmit     = lp->ops->hard_start_xmit;
-	lp->dev.hard_header         = lp->ops->hard_header;
-	lp->dev.do_ioctl            = lp->ops->do_ioctl;
-	lp->dev.flags               = lp->ops->flags;
-	lp->dev.type                = lp->ops->type;
-	lp->dev.addr_len            = lp->ops->addr_len;
-	if (lp->ops->init)
-		retval = lp->ops->init(lp);
-
-	if (retval != 0) {
-		lp->p_encap = -1;
-		lp->ops = NULL;
-	}
- out:
-	return retval;
-}
-
-static int
-isdn_net_bind(isdn_net_dev *idev, isdn_net_ioctl_cfg *cfg)
-{
-	isdn_net_local *mlp = idev->mlp;
-	int retval;
-	int drvidx = -1;
-	int chidx = -1;
-	char drvid[25];
-
-	strlcpy(drvid, cfg->drvid, sizeof(drvid));
-
-	if (cfg->exclusive && !strlen(drvid)) {
-		/* If we want to bind exclusively, need to specify drv/chan */
-		retval = -ENODEV;
-		goto out;
-	}
-	if (strlen(drvid)) {
-		/* A bind has been requested ... */
-		char *c = strchr(drvid, ',');
-		if (!c) {
-			retval = -ENODEV;
-			goto out;
-		}
-		/* The channel-number is appended to the driver-Id with a comma */
-		*c = 0;
-		chidx = simple_strtol(c + 1, NULL, 10);
-		drvidx = isdn_drv_lookup(drvid);
-		if (drvidx == -1 || chidx == -1) {
-			/* Either driver-Id or channel-number invalid */
-			retval = -ENODEV;
-			goto out;
-		}
-	}
-	if (cfg->exclusive == !!idev->exclusive &&
-	    drvidx == idev->pre_device && chidx == idev->pre_channel) {
-		/* no change */
-		retval = 0;
-		goto out;
-	}
-	if (idev->exclusive) {
-		isdn_slot_free(idev->exclusive);
-		idev->exclusive = NULL;
-	}
-	if (cfg->exclusive) {
-		/* If binding is exclusive, try to grab the channel */
-		idev->exclusive = isdn_get_free_slot(ISDN_USAGE_NET | ISDN_USAGE_EXCLUSIVE, 
-						     mlp->l2_proto, mlp->l3_proto, drvidx, chidx, cfg->eaz);
-		if (!idev->exclusive) {
-			/* Grab failed, because desired channel is in use */
-			retval = -EBUSY;
-			goto out;
-		}
-	}
-	idev->pre_device = drvidx;
-	idev->pre_channel = chidx;
-	retval = 0;
- out:
-	return retval;
-}
-
-/*
- * Delete all phone-numbers of an interface.
- */
-static void
-isdn_net_rmallphone(isdn_net_dev *idev)
-{
-	isdn_net_local *mlp = idev->mlp;
-	struct isdn_net_phone *n;
-	int i;
-
-	for (i = 0; i < 2; i++) {
-		while (!list_empty(&mlp->phone[i])) {
-			n = list_entry(mlp->phone[i].next, struct isdn_net_phone, list);
-			list_del(&n->list);
-			kfree(n);
-		}
-	}
-}
-
-/* ====================================================================== */
-/* /dev/isdnctrl net ioctl interface                                      */
-/* ====================================================================== */
-
-/*
- * Allocate a new network-interface and initialize its data structures
- */
-static int
-isdn_net_addif(char *name, isdn_net_local *mlp)
-{
-	int retval;
-	struct net_device *dev = NULL;
-	isdn_net_dev *idev;
-
-	/* Avoid creating an existing interface */
-	if (isdn_net_findif(name))
-		return -EEXIST;
-
-	idev = kmalloc(sizeof(*idev), GFP_KERNEL);
-	if (!idev)
-		return -ENOMEM;
-
-	memset(idev, 0, sizeof(*idev));
-	strcpy(idev->name, name);
-
-	tasklet_init(&idev->tlet, isdn_net_tasklet, (unsigned long) idev);
-	skb_queue_head_init(&idev->super_tx_queue);
-
-	idev->isdn_slot = NULL;
-	idev->pre_device = -1;
-	idev->pre_channel = -1;
-	idev->exclusive = NULL;
-
-	idev->pppbind = -1;
-
-	init_timer(&idev->dial_timer);
-	idev->dial_timer.data = (unsigned long) idev;
-	idev->dial_timer.function = isdn_net_dial_timer;
-
-	idev->fi.fsm = &isdn_net_fsm;
-	idev->fi.state = ST_NULL;
-	idev->fi.debug = 1;
-	idev->fi.userdata = idev;
-	idev->fi.printdebug = isdn_net_dev_debug;
-
-	if (!mlp) {
-		/* Device shall be a master */
-		mlp = kmalloc(sizeof(*mlp), GFP_KERNEL);
-		if (!mlp)
-			return -ENOMEM;
-		
-		memset(mlp, 0, sizeof(*mlp));
-
-		mlp->magic = ISDN_NET_MAGIC;
-		INIT_LIST_HEAD(&mlp->slaves);
-		INIT_LIST_HEAD(&mlp->online);
-		spin_lock_init(&mlp->xmit_lock);
-
-		mlp->p_encap = -1;
-		isdn_net_set_encap(mlp, ISDN_NET_ENCAP_RAWIP);
-
-		mlp->l2_proto = ISDN_PROTO_L2_X75I;
-		mlp->l3_proto = ISDN_PROTO_L3_TRANS;
-		mlp->triggercps = 6000;
-		mlp->slavedelay = 10 * HZ;
-		mlp->hupflags = ISDN_INHUP;
-		mlp->onhtime = 10;
-		mlp->dialmax = 1;
-		mlp->flags = ISDN_NET_CBHUP | ISDN_NET_DM_MANUAL | ISDN_NET_SECURE;
-		mlp->cbdelay = 5 * HZ;	   /* Wait 5 secs before call-back  */
-		mlp->dialtimeout = 60 * HZ;/* Wait 1 min for connection     */
-		mlp->dialwait = 5 * HZ;    /* Wait 5 sec. after failed dial */
-		INIT_LIST_HEAD(&mlp->phone[0]);
-		INIT_LIST_HEAD(&mlp->phone[1]);
-		dev = &mlp->dev;
-	}
-	idev->mlp = mlp;
-	list_add_tail(&idev->slaves, &mlp->slaves);
-
-	if (dev) {
-		strcpy(dev->name, name);
-		dev->priv = mlp;
-		dev->init = isdn_init_netif;
-		SET_MODULE_OWNER(dev);
-		retval = register_netdev(dev);
-		if (retval) {
-			kfree(mlp);
-			kfree(idev);
-			return retval;
-		}
-	}
-	list_add(&idev->global_list, &isdn_net_devs);
-
-	return 0;
-}
-
-/*
- * Add a new slave interface to an existing one
- */
-static int
-isdn_net_addslave(char *parm)
-{
-	char *p = strchr(parm, ',');
-	isdn_net_dev *idev;
-	isdn_net_local *mlp;
-	int retval;
-
-	/* get slave name */
-	if (!p || !p[1])
-		return -EINVAL;
-
-	*p++ = 0;
-
-	/* find master */
-	idev = isdn_net_findif(parm);
-	if (!idev)
-		return -ESRCH;
-
-	mlp = idev->mlp;
-
-	rtnl_lock();
-
-	if (netif_running(&mlp->dev)) {
-		retval = -EBUSY;
-		goto out;
-	}
-	retval = isdn_net_addif(p, mlp);
- out:	
-	rtnl_unlock();
-	return retval;
-}
-
-/*
- * Delete a single network-interface
- */
-static int
-isdn_net_dev_delete(isdn_net_dev *idev)
-{
-	isdn_net_local *mlp = idev->mlp;
-	int retval;
-
-	rtnl_lock();
-	
-	if (netif_running(&mlp->dev)) {
-		retval = -EBUSY;
-		goto unlock;
-	}
-	isdn_net_set_encap(mlp, -1);
-	isdn_net_rmallphone(idev);
-
-	if (idev->exclusive)
-		isdn_slot_free(idev->exclusive);
-
-	list_del(&idev->slaves);
-	
-	rtnl_unlock();
-
-	if (list_empty(&mlp->slaves)) {
-		unregister_netdev(&mlp->dev);
-		kfree(mlp);
-	}
-
-	list_del(&idev->global_list);
-	kfree(idev);
-	return 0;
-
- unlock:
-	rtnl_unlock();
-	return retval;
-}
-
-/*
- * Delete a single network-interface
- */
-static int
-isdn_net_delif(char *name)
-{
-	/* FIXME: For compatibility, if a master isdn_net_dev is rm'ed,
-	 * kill all slaves, too */
-
-	isdn_net_dev *idev = isdn_net_findif(name);
-
-	if (!idev)
-		return -ENODEV;
-
-	return isdn_net_dev_delete(idev);
-}
-
-/*
- * Set interface-parameters.
- * Always set all parameters, so the user-level application is responsible
- * for not overwriting existing setups. It has to get the current
- * setup first, if only selected parameters are to be changed.
- */
-static int
-isdn_net_setcfg(isdn_net_ioctl_cfg *cfg)
-{
-	isdn_net_dev *idev = isdn_net_findif(cfg->name);
-	isdn_net_local *mlp;
-	int retval;
-
-	if (!idev)
-		return -ENODEV;
-
-	mlp = idev->mlp;
-
-	rtnl_lock();
-
-	if (netif_running(&mlp->dev)) {
-		retval = -EBUSY;
-		goto out;
-	}
-
-	retval = isdn_net_set_encap(mlp, cfg->p_encap);
-	if (retval)
-		goto out;
-
-	retval = isdn_net_bind(idev, cfg);
-	if (retval)
-		goto out;
-
-	strlcpy(mlp->msn, cfg->eaz, sizeof(mlp->msn));
-	mlp->onhtime = cfg->onhtime;
-	idev->charge = cfg->charge;
-	mlp->l2_proto = cfg->l2_proto;
-	mlp->l3_proto = cfg->l3_proto;
-	mlp->cbdelay = cfg->cbdelay * HZ / 5;
-	mlp->dialmax = cfg->dialmax;
-	mlp->triggercps = cfg->triggercps;
-	mlp->slavedelay = cfg->slavedelay * HZ;
-	idev->pppbind = cfg->pppbind;
-	mlp->dialtimeout = cfg->dialtimeout >= 0 ? cfg->dialtimeout * HZ : -1;
-	mlp->dialwait = cfg->dialwait * HZ;
-	if (cfg->secure)
-		mlp->flags |= ISDN_NET_SECURE;
-	else
-		mlp->flags &= ~ISDN_NET_SECURE;
-	if (cfg->cbhup)
-		mlp->flags |= ISDN_NET_CBHUP;
-	else
-		mlp->flags &= ~ISDN_NET_CBHUP;
-	switch (cfg->callback) {
-	case 0:
-		mlp->flags &= ~(ISDN_NET_CALLBACK | ISDN_NET_CBOUT);
-		break;
-	case 1:
-		mlp->flags |= ISDN_NET_CALLBACK;
-		mlp->flags &= ~ISDN_NET_CBOUT;
-		break;
-	case 2:
-		mlp->flags |= ISDN_NET_CBOUT;
-		mlp->flags &= ~ISDN_NET_CALLBACK;
-		break;
-	}
-	mlp->flags &= ~ISDN_NET_DIALMODE_MASK;	/* first all bits off */
-	if (cfg->dialmode && !(cfg->dialmode & ISDN_NET_DIALMODE_MASK)) {
-		retval = -EINVAL;
-		goto out;
-	}
-
-	mlp->flags |= cfg->dialmode;  /* turn on selected bits */
-	if (mlp->flags & ISDN_NET_DM_OFF)
-		isdn_net_hangup(idev);
-
-	if (cfg->chargehup)
-		mlp->hupflags |= ISDN_CHARGEHUP;
-	else
-		mlp->hupflags &= ~ISDN_CHARGEHUP;
-
-	if (cfg->ihup)
-		mlp->hupflags |= ISDN_INHUP;
-	else
-		mlp->hupflags &= ~ISDN_INHUP;
-
-	if (cfg->chargeint > 10) {
-		idev->chargeint = cfg->chargeint * HZ;
-		idev->charge_state = ST_CHARGE_HAVE_CINT;
-		mlp->hupflags |= ISDN_MANCHARGE;
-	}
-	retval = 0;
-
- out:
-	rtnl_unlock();
-	
-	return retval;
-}
-
-/*
- * Perform get-interface-parameters.ioctl
- */
-static int
-isdn_net_getcfg(isdn_net_ioctl_cfg *cfg)
-{
-	isdn_net_dev *idev = isdn_net_findif(cfg->name);
-	isdn_net_local *mlp;
-		
-	if (!idev)
-		return -ENODEV;
-
-	mlp = idev->mlp;
-
-	strcpy(cfg->eaz, mlp->msn);
-	cfg->exclusive = !!idev->exclusive;
-	if (idev->pre_device >= 0) {
-		sprintf(cfg->drvid, "%s,%d", isdn_drv_drvid(idev->pre_device),
-			idev->pre_channel);
-	} else {
-		cfg->drvid[0] = '\0';
-	}
-	cfg->onhtime = mlp->onhtime;
-	cfg->charge = idev->charge;
-	cfg->l2_proto = mlp->l2_proto;
-	cfg->l3_proto = mlp->l3_proto;
-	cfg->p_encap = mlp->p_encap;
-	cfg->secure = (mlp->flags & ISDN_NET_SECURE) ? 1 : 0;
-	cfg->callback = 0;
-	if (mlp->flags & ISDN_NET_CALLBACK)
-		cfg->callback = 1;
-	if (mlp->flags & ISDN_NET_CBOUT)
-		cfg->callback = 2;
-	cfg->cbhup = (mlp->flags & ISDN_NET_CBHUP) ? 1 : 0;
-	cfg->dialmode = mlp->flags & ISDN_NET_DIALMODE_MASK;
-	cfg->chargehup = (mlp->hupflags & ISDN_CHARGEHUP) ? 1 : 0;
-	cfg->ihup = (mlp->hupflags & ISDN_INHUP) ? 1 : 0;
-	cfg->cbdelay = mlp->cbdelay * 5 / HZ;
-	cfg->dialmax = mlp->dialmax;
-	cfg->triggercps = mlp->triggercps;
-	cfg->slavedelay = mlp->slavedelay / HZ;
-	cfg->chargeint = (mlp->hupflags & ISDN_CHARGEHUP) ?
-		(idev->chargeint / HZ) : 0;
-	cfg->pppbind = idev->pppbind;
-	cfg->dialtimeout = mlp->dialtimeout >= 0 ? mlp->dialtimeout / HZ : -1;
-	cfg->dialwait = mlp->dialwait / HZ;
-
-	if (idev->slaves.next != &mlp->slaves)
-		strcpy(cfg->slave, list_entry(idev->slaves.next, isdn_net_dev, slaves)->name);
-	else
-		cfg->slave[0] = '\0';
-	if (strcmp(mlp->dev.name, idev->name))
-		strcpy(cfg->master, mlp->dev.name);
-	else
-		cfg->master[0] = '\0';
-
-	return 0;
-}
-
-/*
- * Add a phone-number to an interface.
- */
-static int
-isdn_net_addphone(isdn_net_ioctl_phone *phone)
-{
-	isdn_net_dev *idev = isdn_net_findif(phone->name);
-	struct isdn_net_phone *n;
-	int retval = 0;
-
-	if (!idev)
-		return -ENODEV;
-
-	rtnl_lock();
-
-	if (netif_running(&idev->mlp->dev)) {
-		retval = -EBUSY;
-		goto out;
-	}
-	n = kmalloc(sizeof(*n), GFP_KERNEL);
-	if (!n) {
-		retval = -ENOMEM;
-		goto out;
-	}
-	strcpy(n->num, phone->phone);
-	list_add_tail(&n->list, &idev->mlp->phone[phone->outgoing & 1]);
-
- out:
-	rtnl_unlock();
-	return retval;
-}
-
-/*
- * Delete a phone-number from an interface.
- */
-static int
-isdn_net_delphone(isdn_net_ioctl_phone *phone)
-{
-	isdn_net_dev *idev = isdn_net_findif(phone->name);
-	struct isdn_net_phone *n;
-	int retval;
-
-	if (!idev)
-		return -ENODEV;
-
-	rtnl_lock();
-
-	if (netif_running(&idev->mlp->dev)) {
-		retval = -EBUSY;
-		goto out;
-	}
-	retval = -EINVAL;
-	list_for_each_entry(n, &idev->mlp->phone[phone->outgoing & 1], list) {
-		if (!strcmp(n->num, phone->phone)) {
-			list_del(&n->list);
-			kfree(n);
-			retval = 0;
-			break;
-		}
-	}
- out:
-	rtnl_unlock();
-	return retval;
-}
-
-/*
- * Copy a string of all phone-numbers of an interface to user space.
- */
-static int
-isdn_net_getphone(isdn_net_ioctl_phone * phone, char *phones)
-{
-	isdn_net_dev *idev = isdn_net_findif(phone->name);
-	u_int count = 0;
-	char *buf = (char *)__get_free_page(GFP_KERNEL);
-	struct isdn_net_phone *n;
-
-	if (!buf)
-		return -ENOMEM;
-
-	if (!idev) {
-		count = -ENODEV;
-		goto free;
-	}
-	list_for_each_entry(n, &idev->mlp->phone[phone->outgoing & 1], list) {
-		strcpy(&buf[count], n->num);
-		count += strlen(n->num);
-		buf[count++] = ' ';
-		if (count > PAGE_SIZE - ISDN_MSNLEN - 1)
-			break;
-	}
-	if (!count) /* list was empty? */
-		count++;
-
-	buf[count-1] = 0;
-
-	if (copy_to_user(phones, buf, count))
-		count = -EFAULT;
-
- free:
-	free_page((unsigned long)buf);
-	return count;
-}
-
-/*
- * Force a net-interface to dial out.
- */
-static int
-isdn_net_dial_out(char *name)
-{
-	isdn_net_dev *idev = isdn_net_findif(name);
-
-	if (!idev)
-		return -ENODEV;
-
-	return isdn_net_dial(idev);
-}
-
-static int
-__isdn_net_dial_slave(isdn_net_local *mlp)
-{
-	isdn_net_dev *idev;
-
-	list_for_each_entry(idev, &mlp->slaves, slaves) {
-		if (isdn_net_dial(idev) == 0)
-			return 0;
-	}
-	return -EBUSY;
-}
-
-static int
-isdn_net_dial_slave(char *name)
-{
-	isdn_net_dev *idev = isdn_net_findif(name);
-
-	if (!idev)
-		return -ENODEV;
-
-	return __isdn_net_dial_slave(idev->mlp);
-}
-
-/*
- * Force a hangup of a network-interface.
- */
-static int
-isdn_net_force_hangup(char *name) // FIXME rename?
-{
-	isdn_net_dev *idev = isdn_net_findif(name);
-
-	if (!idev)
-		return -ENODEV;
-
-	if (idev->isdn_slot == NULL)
-		return -ENOTCONN;
-
-	isdn_net_hangup(idev);
-	return 0;
-}
-
-/*
- * Copy a string containing the peer's phone number of a connected interface
- * to user space.
- */
-static int
-isdn_net_getpeer(isdn_net_ioctl_phone *phone, isdn_net_ioctl_phone *peer)
-{
-	isdn_net_dev *idev = isdn_net_findif(phone->name);
-	struct isdn_slot *slot;
-
-	if (!idev)
-		return -ENODEV;
-
-	if (idev->fi.state != ST_ACTIVE)
-		return -ENOTCONN;
-
-	slot = idev->isdn_slot;
-
-	strlcpy(phone->phone, slot->num, sizeof(phone->phone));
-	phone->outgoing = USG_OUTGOING(slot->usage);
-
-	if (copy_to_user(peer, phone, sizeof(*peer)))
-		return -EFAULT;
-
-	return 0;
-}
-
-/*
- * ioctl on /dev/isdnctrl, used to configure ISDN net interfaces 
- */
-int
-isdn_net_ioctl(struct inode *ino, struct file *file, uint cmd, ulong arg)
-{
-	/* Save stack space */
-	union {
-		char name[10];
-		char bname[20];
-		isdn_net_ioctl_phone phone;
-		isdn_net_ioctl_cfg cfg;
-	} iocpar;
-	int retval;
-
-#define name  iocpar.name
-#define bname iocpar.bname
-#define phone iocpar.phone
-#define cfg   iocpar.cfg
-
-	name[sizeof(name)-1] = 0;
-	bname[sizeof(bname)-1] = 0;
-
-	down(&sem);
-	
-	switch (cmd) {
-	case IIOCNETAIF: /* add an interface */
-		if (copy_from_user(name, (char *) arg, sizeof(name) - 1)) {
-			retval = -EFAULT;
-			break;
-		}
-		retval = isdn_net_addif(name, NULL);
-		break;
-	case IIOCNETASL: /* add slave to an interface */
-		if (copy_from_user(bname, (char *) arg, sizeof(bname) - 1)) {
-			retval = -EFAULT;
-			break;
-		}
-		retval = isdn_net_addslave(bname);
-		break;
-	case IIOCNETDIF: /* delete an interface */
-		if (copy_from_user(name, (char *) arg, sizeof(name) - 1)) {
-			retval = -EFAULT;
-			break;
-		}
-		retval = isdn_net_delif(name);
-		break;
-	case IIOCNETSCF: /* set config */
-		if (copy_from_user((char *) &cfg, (char *) arg, sizeof(cfg))) {
-			retval = -EFAULT;
-			break;
-		}
-		retval = isdn_net_setcfg(&cfg);
-		break;
-	case IIOCNETGCF: /* get config */
-		if (copy_from_user((char *) &cfg, (char *) arg, sizeof(cfg))) {
-			retval = -EFAULT;
-			break;
-		}
-		retval = isdn_net_getcfg(&cfg);
-		if (retval)
-			break;
-		if (copy_to_user((char *) arg, (char *) &cfg, sizeof(cfg)))
-			retval = -EFAULT;
-		break;
-	case IIOCNETANM: /* add a phone number */
-		if (copy_from_user((char *) &phone, (char *) arg, sizeof(phone))) {
-			retval = -EFAULT;
-			break;
-		}
-		retval = isdn_net_addphone(&phone);
-		break;
-	case IIOCNETGNM: /* get list of phone numbers */
-		if (copy_from_user((char *) &phone, (char *) arg, sizeof(phone))) {
-			retval = -EFAULT;
-			break;
-		}
-		retval = isdn_net_getphone(&phone, (char *) arg);
-		break;
-	case IIOCNETDNM: /* delete a phone number */
-		if (copy_from_user((char *) &phone, (char *) arg, sizeof(phone))) {
-			retval = -EFAULT;
-			break;
-		}
-		retval = isdn_net_delphone(&phone);
-		break;
-	case IIOCNETDIL: /* trigger dial-out */
-		if (copy_from_user(name, (char *) arg, sizeof(name))) {
-			retval = -EFAULT;
-			break;
-		}
-		retval = isdn_net_dial_out(name);
-		break;
-	case IIOCNETHUP: /* hangup */
-		if (copy_from_user(name, (char *) arg, sizeof(name))) {
-			retval = -EFAULT;
-			break;
-		}
-		retval = isdn_net_force_hangup(name);
-		break;
-	case IIOCNETGPN: /* Get peer phone number of a connected interface */
-		if (copy_from_user((char *) &phone, (char *) arg, sizeof(phone))) {
-			retval = -EFAULT;
-		}
-		retval = isdn_net_getpeer(&phone, (isdn_net_ioctl_phone *) arg);
-		break;
-	case IIOCNETALN: /* Add link */
-		if (copy_from_user(name, (char *) arg, sizeof(name))) {
-			retval = -EFAULT;
-			break;
-		}
-		retval = isdn_net_dial_slave(name);
-		break;
-	case IIOCNETDLN: /* Delete link */
-		if (copy_from_user(name, (char *) arg, sizeof(name))) {
-			retval = -EFAULT;
-			break;
-		}
-		retval = isdn_net_force_hangup(name);
-		break;
-	default:
-		retval = -ENOTTY;
-	}
-	up(&sem);
-	return retval;
-
-#undef name
-#undef bname
-#undef iocts
-#undef phone
-#undef cfg
-}
-
-/*
- * Hang up all network-interfaces
- */
-void
-isdn_net_hangup_all(void)
-{
-	isdn_net_dev *idev;
-
-	down(&sem);
-
-	list_for_each_entry(idev, &isdn_net_devs, global_list)
-		isdn_net_hangup(idev);
-
-	up(&sem);
-}
-
-/*
- * Remove all network-interfaces
- */
-void
-isdn_net_cleanup(void)
-{
-	isdn_net_dev *idev;
-	int retval;
-
-	down(&sem);
-
-	while (!list_empty(&isdn_net_devs)) {
-		idev = list_entry(isdn_net_devs.next, isdn_net_dev, global_list);
-		retval = isdn_net_dev_delete(idev);
-		/* can only fail if an interface is still running.
-		 * In this case, an elevated module use count should
-		 * have prevented this function from being called in
-		 * the first place */
-		if (retval)
-			isdn_BUG();
-	}
-	up(&sem);
-}
-
-/* ====================================================================== */
-/* interface to network layer                                             */
-/* ====================================================================== */
-
-static spinlock_t running_devs_lock = SPIN_LOCK_UNLOCKED;
-static LIST_HEAD(running_devs);
-
-/* 
- * Open/initialize the board.
- */
-static int
-isdn_net_open(struct net_device *dev)
-{
-	isdn_net_local *lp = dev->priv;
-	unsigned long flags;
-	int retval = 0;
-
-	if (!lp->ops)
-		return -ENODEV;
-
-	if (lp->ops->open)
-		retval = lp->ops->open(lp);
-
-	if (retval)
-		return retval;
-	
-	netif_start_queue(dev);
-
-	atomic_set(&lp->refcnt, 1);
-	spin_lock_irqsave(&running_devs_lock, flags);
-	list_add(&lp->running_devs, &running_devs);
-	spin_unlock_irqrestore(&running_devs_lock, flags);
-
-	return 0;
-}
-
-/*
- * Shutdown a net-interface.
- */
-static int
-isdn_net_close(struct net_device *dev)
-{
-	isdn_net_local *lp = dev->priv;
-	isdn_net_dev *sdev;
-	struct list_head *l, *n;
-	unsigned long flags;
-
-	if (lp->ops->close)
-		lp->ops->close(lp);
-
-	netif_stop_queue(dev);
-
-	list_for_each_safe(l, n, &lp->slaves) {
-		sdev = list_entry(l, isdn_net_dev, slaves);
-		isdn_net_hangup(sdev);
-	}
-	/* The hangup will make the refcnt drop back to
-	 * 1 (referenced by list only) soon. */
-	spin_lock_irqsave(&running_devs_lock, flags);
-	while (atomic_read(&lp->refcnt) != 1) {
-		spin_unlock_irqrestore(&running_devs_lock, flags);
-		set_current_state(TASK_UNINTERRUPTIBLE);
-		schedule_timeout(HZ/10);
-		spin_lock_irqsave(&running_devs_lock, flags);
-	}
-	/* We have the only reference and list lock, so
-	 * nobody can get another reference. */
-	list_del(&lp->running_devs);
-	spin_unlock_irqrestore(&running_devs_lock, flags);
-
-	return 0;
-}
-
-/*
- * Get statistics
- */
-static struct net_device_stats *
-isdn_net_get_stats(struct net_device *dev)
-{
-	isdn_net_local *lp = dev->priv;
-
-	return &lp->stats;
-}
-
-/*
- * Transmit timeout
- */
-static void
-isdn_net_tx_timeout(struct net_device *dev)
-{
-	printk(KERN_WARNING "isdn_tx_timeout dev %s\n", dev->name);
-
-	netif_wake_queue(dev);
-}
-
-/*
- * Interface-setup. (just after registering a new interface)
- */
-static int
-isdn_init_netif(struct net_device *ndev)
-{
-	/* Setup the generic properties */
-
-	ndev->mtu = 1500;
-	ndev->tx_queue_len = 10;
-	ndev->open = &isdn_net_open;
-	ndev->hard_header_len = ETH_HLEN + isdn_hard_header_len();
-	ndev->stop = &isdn_net_close;
-	ndev->get_stats = &isdn_net_get_stats;
-	ndev->tx_timeout = isdn_net_tx_timeout;
-	ndev->watchdog_timeo = ISDN_NET_TX_TIMEOUT;
-
-	return 0;
-}
-
-/* ====================================================================== */
-/* call control state machine                                             */
-/* ====================================================================== */
-
-// FIXME
-static int
-isdn_net_is_connected(isdn_net_dev *idev)
-{
-	return idev->fi.state == ST_ACTIVE;
-}
-
-static void
-isdn_net_dial_timer(unsigned long data)
-{
-	isdn_net_dev *idev = (isdn_net_dev *) data;
-
-	isdn_net_handle_event(idev, idev->dial_event, NULL);
-}
-
-/*
- * Unbind a net-interface
- */
-static void
-isdn_net_unbind_channel(isdn_net_dev *idev)
-{
-	isdn_net_local *mlp = idev->mlp;
-
-	if (idev->isdn_slot == NULL) {
-		isdn_BUG();
-		return;
-	}
-
-	if (mlp->ops->unbind)
-		mlp->ops->unbind(idev);
-
-	idev->isdn_slot->priv = NULL;
-	idev->isdn_slot->event_cb = NULL;
-
-	skb_queue_purge(&idev->super_tx_queue);
-
-	if (idev->isdn_slot != idev->exclusive)
-		isdn_slot_free(idev->isdn_slot);
-
-	idev->isdn_slot = NULL;
-
-	if (idev->fi.state != ST_NULL) {
-		lp_put(mlp);
-		fsm_change_state(&idev->fi, ST_NULL);
-	}
-}
-
-static int isdn_net_event_callback(struct isdn_slot *slot, int pr, void *arg);
-
-/*
- * Assign an ISDN-channel to a net-interface
- */
-static int
-isdn_net_bind_channel(isdn_net_dev *idev, struct isdn_slot *slot)
-{
-	isdn_net_local *mlp = idev->mlp;
-	int retval = 0;
-
-	if (mlp->ops->bind)
-		retval = mlp->ops->bind(idev);
-
-	if (retval < 0)
-		goto out;
-
-	idev->isdn_slot = slot;
-	slot->priv = idev;
-	slot->event_cb = isdn_net_event_callback;
-	slot->usage |= ISDN_USAGE_NET;
-
- out:
-	return retval;
-}
-
-static int
-isdn_net_dial(isdn_net_dev *idev)
-{
-	int retval;
-
-	lp_get(idev->mlp);
-	retval = fsm_event(&idev->fi, EV_NET_DO_DIAL, NULL);
-	if (retval == -ESRCH) /* event not handled in this state */
-		retval = -EBUSY;
-
-	if (retval)
-		lp_put(idev->mlp);
-
-	return retval;
-}
-
-static void
-isdn_net_unreachable(struct net_device *dev, struct sk_buff *skb, char *reason)
-{
-	u_short proto = ntohs(skb->protocol);
-	
-	printk(KERN_DEBUG "isdn_net: %s: %s, signalling dst_link_failure %s\n",
-	       dev->name,
-	       (reason != NULL) ? reason : "unknown",
-	       (proto != ETH_P_IP) ? "Protocol != ETH_P_IP" : "");
-	
-	dst_link_failure(skb);
-}
-
-/*
- * This is called from certain upper protocol layers (multilink ppp
- * and x25iface encapsulation module) that want to initiate dialing
- * themselves.
- */
-int
-isdn_net_dial_req(isdn_net_dev *idev)
-{
-	isdn_net_local *mlp = idev->mlp;
-	/* is there a better error code? */
-	if (ISDN_NET_DIALMODE(*mlp) != ISDN_NET_DM_AUTO)
-		return -EBUSY;
-
-	return isdn_net_dial(idev);
-}
-
-static void
-isdn_net_log_skb(struct sk_buff *skb, isdn_net_dev *idev)
-{
-	unsigned char *p = skb->nh.raw; /* hopefully, this was set correctly */
-	unsigned short proto = ntohs(skb->protocol);
-	int data_ofs;
-	struct ip_ports {
-		unsigned short source;
-		unsigned short dest;
-	} *ipp;
-	char addinfo[100];
-
-	data_ofs = ((p[0] & 15) * 4);
-	switch (proto) {
-	case ETH_P_IP:
-		switch (p[9]) {
-		case IPPROTO_ICMP:
-			strcpy(addinfo, "ICMP");
-			break;
-		case IPPROTO_TCP:
-		case IPPROTO_UDP:
-			ipp = (struct ip_ports *) (&p[data_ofs]);
-			sprintf(addinfo, "%s, port: %d -> %d",
-				p[9] == IPPROTO_TCP ? "TCP" : "UDP",
-				ntohs(ipp->source), ntohs(ipp->dest));
-			break;
-		default:
-			sprintf(addinfo, "type %d", p[9]);
-		}
-		printk(KERN_INFO
-		       "OPEN: %u.%u.%u.%u -> %u.%u.%u.%u %s\n",
-		       
-		       NIPQUAD(*(u32 *)(p + 12)), NIPQUAD(*(u32 *)(p + 16)),
-		       addinfo);
-		break;
-	case ETH_P_ARP:
-		printk(KERN_INFO
-		       "OPEN: ARP %d.%d.%d.%d -> *.*.*.* ?%d.%d.%d.%d\n",
-		       NIPQUAD(*(u32 *)(p + 14)), NIPQUAD(*(u32 *)(p + 24)));
-		break;
-	default:
-		printk(KERN_INFO "OPEN: unknown proto %#x\n", proto);
-	}
-}
-
-int
-isdn_net_autodial(struct sk_buff *skb, struct net_device *ndev)
-{
-	isdn_net_local *mlp = ndev->priv;
-	isdn_net_dev *idev = list_entry(mlp->slaves.next, isdn_net_dev, slaves);
-	int retval;
-
-	if (ISDN_NET_DIALMODE(*mlp) != ISDN_NET_DM_AUTO)
-		goto discard;
-
-	retval = isdn_net_dial(idev);
-	if (retval == -ESRCH)
-		goto stop_queue;
-
-	if (retval < 0)
-		goto discard;
-
-	/* Log packet, which triggered dialing */
-	if ((get_isdn_dev())->net_verbose)
-		isdn_net_log_skb(skb, idev);
-
- stop_queue:
-	netif_stop_queue(ndev);
-	return 1;
-
- discard:
-	isdn_net_unreachable(ndev, skb, "dial rejected");
-	dev_kfree_skb(skb);
-	return 0;
-}
-
-static int
-accept_icall(struct fsm_inst *fi, int pr, void *arg)
-{
-	isdn_net_dev *idev = fi->userdata;
-	isdn_net_local *mlp = idev->mlp;
-	isdn_ctrl cmd;
-	struct isdn_slot *slot = arg;
-
-	isdn_net_bind_channel(idev, slot);
-	
-	idev->outgoing = 0;
-	idev->charge_state = ST_CHARGE_NULL;
-	/* Got incoming call, setup L2 and L3 protocols,
-	 * then wait for D-Channel-connect
-	 */
-	cmd.arg = mlp->l2_proto << 8;
-	isdn_slot_command(idev->isdn_slot, ISDN_CMD_SETL2, &cmd);
-	cmd.arg = mlp->l3_proto << 8;
-	isdn_slot_command(idev->isdn_slot, ISDN_CMD_SETL3, &cmd);
-	isdn_slot_command(idev->isdn_slot, ISDN_CMD_ACCEPTD, &cmd);
-	
-	idev->dial_timer.expires = jiffies + mlp->dialtimeout;
-	idev->dial_event = EV_NET_TIMER_INCOMING;
-	add_timer(&idev->dial_timer);
-	fsm_change_state(&idev->fi, ST_IN_WAIT_DCONN);
-	return 0;
-}
-
-static int
-do_callback(struct fsm_inst *fi, int pr, void *arg)
-{
-	isdn_net_dev *idev = fi->userdata;
-	isdn_net_local *mlp = idev->mlp;
-
-	printk(KERN_DEBUG "%s: start callback\n", idev->name);
-
-	idev->dial_timer.expires = jiffies + mlp->cbdelay;
-	idev->dial_event = EV_NET_TIMER_CB_IN;
-	add_timer(&idev->dial_timer);
-	fsm_change_state(&idev->fi, ST_WAIT_BEFORE_CB);
-
-	return 0;
-}
-
-static int
-isdn_net_dev_icall(isdn_net_dev *idev, struct isdn_slot *slot,
-		   int si1, char *eaz, char *nr)
-{
-	isdn_net_local *mlp = idev->mlp;
-	struct isdn_net_phone *ph;
-	char *my_eaz;
-	
-	/* check acceptable call types for DOV */
-	dbg_net_icall("n_fi: if='%s', l.msn=%s, l.flags=%#x, l.dstate=%d\n",
-		      idev->name, mlp->msn, mlp->flags, idev->fi.state);
-	
-	my_eaz = isdn_slot_map_eaz2msn(slot, mlp->msn);
-	if (si1 == 1) { /* it's a DOV call, check if we allow it */
-		if (*my_eaz == 'v' || *my_eaz == 'V' ||
-		    *my_eaz == 'b' || *my_eaz == 'B')
-			my_eaz++; /* skip to allow a match */
-		else
-			return 0; /* no match */
-	} else { /* it's a DATA call, check if we allow it */
-		if (*my_eaz == 'b' || *my_eaz == 'B')
-			my_eaz++; /* skip to allow a match */
-	}
-	/* check called number */
-	switch (isdn_msncmp(eaz, my_eaz)) {
-	case 1: /* no match */
-		return 0;
-	case 2: /* matches so far */
-		return 5;
-	}
-
-	dbg_net_icall("%s: pdev=%d di=%d pch=%d ch = %d\n", idev->name,
-		      idev->pre_device, slot->di, idev->pre_channel, slot->ch);
-	
-	/* check if exclusive */
-	if ((slot->usage & ISDN_USAGE_EXCLUSIVE) &&
-	    (idev->pre_channel != slot->ch || idev->pre_device != slot->di)) {
-		dbg_net_icall("%s: excl check failed\n", idev->name);
-		return 0;
-	}
-	
-	/* check calling number */
-	dbg_net_icall("%s: secure\n", idev->name);
-	if (mlp->flags & ISDN_NET_SECURE) {
-		list_for_each_entry(ph, &mlp->phone[0], list) {
-			if (isdn_msncmp(nr, ph->num) == 0)
-					goto found;
-		}
-		return 0;
-	}
- found:
-	/* check dial mode */
-	if (ISDN_NET_DIALMODE(*mlp) == ISDN_NET_DM_OFF) {
-		printk(KERN_INFO "%s: incoming call, stopped -> rejected\n",
-		       idev->name);
-		return 3;
-	}
-	lp_get(mlp);
-	/* check callback */
-	if (mlp->flags & ISDN_NET_CALLBACK) {
-		if (fsm_event(&idev->fi, EV_NET_DO_CALLBACK, NULL)) {
-			lp_put(mlp);
-			return 0;
-		}
-		/* Initiate dialing by returning 2 or 4 */
-		return (mlp->flags & ISDN_NET_CBHUP) ? 2 : 4;
-	}
-	printk(KERN_INFO "%s: call from %s -> %s accepted\n",
-	       idev->name, nr, eaz);
-
-	if (fsm_event(&idev->fi, EV_NET_DO_ACCEPT, slot)) {
-		lp_put(mlp);
-		return 0;
-	}
-	return 1; // accepted
-}
-
-/*
- * An incoming call-request has arrived.
- * Search the interface-chain for an appropriate interface.
- * If found, connect the interface to the ISDN-channel and initiate
- * D- and B-Channel-setup. If secure-flag is set, accept only
- * configured phone-numbers. If callback-flag is set, initiate
- * callback-dialing.
- *
- * Return-Value: 0 = No appropriate interface for this call.
- *               1 = Call accepted
- *               2 = Reject call, wait cbdelay, then call back
- *               3 = Reject call
- *               4 = Wait cbdelay, then call back
- *               5 = No appropriate interface for this call,
- *                   would eventually match if CID was longer.
- */
-int
-isdn_net_find_icall(struct isdn_slot *slot, setup_parm *setup)
-{
-	isdn_net_local	*lp;
-	isdn_net_dev	*idev;
-	char		*nr, *eaz;
-	unsigned char	si1, si2;
-	int		retval;
-	int		verbose = (get_isdn_dev())->net_verbose;
-	unsigned long	flags;
-
-	/* fix up calling number */
-	if (!setup->phone[0]) {
-		printk(KERN_INFO
-		       "isdn_net: Incoming call without OAD, assuming '0'\n");
-		nr = "0";
-	} else {
-		nr = setup->phone;
-	}
-	/* fix up called number */
-	if (!setup->eazmsn[0]) {
-		printk(KERN_INFO
-		       "isdn_net: Incoming call without CPN, assuming '0'\n");
-		eaz = "0";
-	} else {
-		eaz = setup->eazmsn;
-	}
-	si1 = setup->si1;
-	si2 = setup->si2;
-	if (verbose > 1)
-		printk(KERN_INFO "isdn_net: call from %s,%d,%d -> %s\n", 
-		       nr, si1, si2, eaz);
-	/* check service indicator */
-        /* Accept DATA and VOICE calls at this stage
-	   local eaz is checked later for allowed call types */
-        if ((si1 != 7) && (si1 != 1)) {
-                if (verbose > 1)
-                        printk(KERN_INFO "isdn_net: "
-			       "Service-Indicator not 1 or 7, ignored\n");
-                return 0;
-        }
-
-	dbg_net_icall("n_fi: di=%d ch=%d usg=%#x\n", slot->di, slot->ch,
-		      slot->usage);
-
-	retval = 0;
-	spin_lock_irqsave(&running_devs_lock, flags);
-	list_for_each_entry(lp, &running_devs, running_devs) {
-		lp_get(lp);
-		spin_unlock_irqrestore(&running_devs_lock, flags);
-
-		list_for_each_entry(idev, &lp->slaves, slaves) {
-			retval = isdn_net_dev_icall(idev, slot, si1, eaz, nr);
-			if (retval > 0)
-				break;
-		}
-
-		spin_lock_irqsave(&running_devs_lock, flags);
-		lp_put(lp);
-		if (retval > 0)
-			break;
-		
-	}
-	spin_unlock_irqrestore(&running_devs_lock, flags);
-	if (!retval) {
-		if (verbose)
-			printk(KERN_INFO "isdn_net: call "
-			       "from %s -> %s ignored\n", nr, eaz);
-	}
-	return retval;
-}
-
-/* ---------------------------------------------------------------------- */
-/* callbacks in the state machine                                         */
-/* ---------------------------------------------------------------------- */
-
-/* Find the idev->dial'th outgoing number. */
-
-static struct isdn_net_phone *
-get_outgoing_phone(isdn_net_dev *idev)
-{
-	isdn_net_local *mlp = idev->mlp;
-	struct isdn_net_phone *phone;
-	int i = 0;
-
-	list_for_each_entry(phone, &mlp->phone[1], list) {
-		if (i++ == idev->dial)
-			return phone;
-	}
-	return NULL;
-}
-
-static int dialout_next(struct fsm_inst *fi, int pr, void *arg);
-
-/* Initiate dialout. */
-
-static int
-do_dial(struct fsm_inst *fi, int pr, void *arg)
-{
-	isdn_net_dev *idev = fi->userdata;
-	isdn_net_local *mlp = idev->mlp;
-	struct isdn_slot *slot;
-
-	if (ISDN_NET_DIALMODE(*mlp) == ISDN_NET_DM_OFF)
-		return -EPERM;
-
-	if (list_empty(&mlp->phone[1])) /* no number to dial ? */
-		return -EINVAL;
-
-	if (idev->exclusive)
-		slot = idev->exclusive;
-	else
-		slot = isdn_get_free_slot(ISDN_USAGE_NET, mlp->l2_proto,
-					  mlp->l3_proto, idev->pre_device, 
-					  idev->pre_channel, mlp->msn);
-	if (!slot)
-		return -EAGAIN;
-
-	if (isdn_net_bind_channel(idev, slot) < 0) {
-		/* has freed the slot as well */
-		return -EAGAIN;
-	}
-
-	fsm_change_state(fi, ST_OUT_BOUND);
-
-	idev->dial = 0;
-	idev->dialretry = 0;
-
-	dialout_next(fi, pr, arg);
-	return 0;
-}
-
-/* Try dialing the next number. */
-
-static int
-dialout_next(struct fsm_inst *fi, int pr, void *arg)
-{
-	isdn_net_dev *idev = fi->userdata;
-	isdn_net_local *mlp = idev->mlp;
-	struct dial_info dial = {
-		.l2_proto = mlp->l2_proto,
-		.l3_proto = mlp->l3_proto,
-		.si1      = 7,
-		.si2      = 0,
-		.msn      = mlp->msn,
-		.phone    = get_outgoing_phone(idev)->num,
-	};
-
-	/* next time, try next number */
-	idev->dial++;
-
-	idev->outgoing = 1;
-	if (idev->chargeint)
-		idev->charge_state = ST_CHARGE_HAVE_CINT;
-	else
-		idev->charge_state = ST_CHARGE_NULL;
-
-	/* For outgoing callback, use cbdelay instead of dialtimeout */
-	if (mlp->cbdelay && (mlp->flags & ISDN_NET_CBOUT)) {
-		idev->dial_timer.expires = jiffies + mlp->cbdelay;
-		idev->dial_event = EV_NET_TIMER_CB_OUT;
-	} else {
-		idev->dial_timer.expires = jiffies + mlp->dialtimeout;
-		idev->dial_event = EV_NET_TIMER_DIAL;
-	}
-	fsm_change_state(&idev->fi, ST_OUT_WAIT_DCONN);
-	add_timer(&idev->dial_timer);
-
-	/* Dial */
-	isdn_slot_dial(idev->isdn_slot, &dial);
-	return 0;
-}
-
-/* If we didn't connect within dialtimeout, we give up for now
- * and wait for dialwait jiffies before trying again.
- */
-static int
-dial_timeout(struct fsm_inst *fi, int pr, void *arg)
-{
-	isdn_net_dev *idev = fi->userdata;
-	isdn_net_local *mlp = idev->mlp;
-	isdn_ctrl cmd;
-
-	fsm_change_state(&idev->fi, ST_OUT_DIAL_WAIT);
-	isdn_slot_command(idev->isdn_slot, ISDN_CMD_HANGUP, &cmd);
-	
-	/* get next phone number */
-	if (!get_outgoing_phone(idev)) {
-		/* otherwise start over at first entry */
-		idev->dial = 0;
-		idev->dialretry++;
-	}
-	if (idev->dialretry >= mlp->dialmax) {
-		isdn_net_hangup(idev);
-		return 0;
-	}
-	idev->dial_event = EV_NET_TIMER_DIAL_WAIT;
-	mod_timer(&idev->dial_timer, jiffies + mlp->dialwait);
-	return 0;
-}
-
-static int
-connect_fail(struct fsm_inst *fi, int pr, void *arg)
-{
-	isdn_net_dev *idev = fi->userdata;
-
-	del_timer(&idev->dial_timer);
-	printk(KERN_INFO "%s: connection failed\n", idev->name);
-	isdn_net_unbind_channel(idev);
-	return 0;
-}
-
-static int
-out_dconn(struct fsm_inst *fi, int pr, void *arg)
-{
-	isdn_net_dev *idev = fi->userdata;
-	isdn_ctrl cmd;
-
-	fsm_change_state(&idev->fi, ST_OUT_WAIT_BCONN);
-	isdn_slot_command(idev->isdn_slot, ISDN_CMD_ACCEPTB, &cmd);
-	return 0;
-}
-
-static int
-in_dconn(struct fsm_inst *fi, int pr, void *arg)
-{
-	isdn_net_dev *idev = fi->userdata;
-	isdn_ctrl cmd;
-
-	fsm_change_state(&idev->fi, ST_IN_WAIT_BCONN);
-	isdn_slot_command(idev->isdn_slot, ISDN_CMD_ACCEPTB, &cmd);
-	return 0;
-}
-
-static int
-bconn(struct fsm_inst *fi, int pr, void *arg)
-{
-	isdn_net_dev *idev = fi->userdata;
-	isdn_net_local *mlp = idev->mlp;
-
-	fsm_change_state(&idev->fi, ST_ACTIVE);
-
-	if (mlp->onhtime) {
-		idev->huptimer = 0;
-		idev->dial_event = EV_NET_TIMER_HUP;
-		mod_timer(&idev->dial_timer, jiffies + HZ);
-	} else {
-		del_timer(&idev->dial_timer);
-	}
-
-	printk(KERN_INFO "%s connected\n", idev->name);
-	/* If first Chargeinfo comes before B-Channel connect,
-	 * we correct the timestamp here.
-	 */
-	idev->chargetime = jiffies;
-	idev->frame_cnt = 0;
-	idev->transcount = 0;
-	idev->cps = 0;
-	idev->last_jiffies = jiffies;
-
-	if (mlp->ops->connected)
-		mlp->ops->connected(idev);
-	else
-		isdn_net_online(idev);
-       
-	return 0;
-}
-
-static int
-bhup(struct fsm_inst *fi, int pr, void *arg)
-{
-	isdn_net_dev *idev = fi->userdata;
-	isdn_net_local *mlp = idev->mlp;
-
-	del_timer(&idev->dial_timer);
-	if (mlp->ops->disconnected)
-		mlp->ops->disconnected(idev);
-	else 
-		isdn_net_offline(idev);
-
-	printk(KERN_INFO "%s: disconnected\n", idev->name);
-	fsm_change_state(fi, ST_WAIT_DHUP);
-	return 0;
-}
-
-static int
-dhup(struct fsm_inst *fi, int pr, void *arg)
-{
-	isdn_net_dev *idev = fi->userdata;
-
-	printk(KERN_INFO "%s: Chargesum is %d\n", idev->name, idev->charge);
-	isdn_net_unbind_channel(idev);
-	return 0;
-}
-
-/* Check if it's time for idle hang-up */
-
-static int
-check_hup(struct fsm_inst *fi, int pr, void *arg)
-{
-	isdn_net_dev *idev = fi->userdata;
-	isdn_net_local *mlp = idev->mlp;
-
-	dbg_net_dial("%s: huptimer %d onhtime %d chargetime %ld chargeint %d\n",
-		     idev->name, idev->huptimer, mlp->onhtime, idev->chargetime, idev->chargeint);
-
-	if (idev->huptimer++ <= mlp->onhtime)
-		goto mod_timer;
-
-	if (mlp->hupflags & ISDN_CHARGEHUP &&
-	    idev->charge_state == ST_CHARGE_HAVE_CINT) {
-		if (!time_after(jiffies, idev->chargetime 
-				+ idev->chargeint - 2 * HZ))
-			goto mod_timer;
-	}
-	if (idev->outgoing || mlp->hupflags & ISDN_INHUP) {
-		isdn_net_hangup(idev);
-		return 0;
-	}
- mod_timer:
-	mod_timer(&idev->dial_timer, idev->dial_timer.expires + HZ);
-	return 0;
-}
-
-/* Charge-info from TelCo. */
-
-static int
-got_cinf(struct fsm_inst *fi, int pr, void *arg)
-{
-	isdn_net_dev *idev = fi->userdata;
-
-	idev->charge++;
-	switch (idev->charge_state) {
-	case ST_CHARGE_NULL:
-		idev->charge_state = ST_CHARGE_GOT_CINF;
-		break;
-	case ST_CHARGE_GOT_CINF:
-		idev->charge_state = ST_CHARGE_HAVE_CINT;
-		/* fall through */
-	case ST_CHARGE_HAVE_CINT:
-		idev->chargeint = jiffies - idev->chargetime;
-		break;
-	}
-	idev->chargetime = jiffies;
-	dbg_net_dial("%s: got CINF\n", idev->name);
-	return 0;
-}
-
-/* Perform hangup for a net-interface. */
-
-int
-isdn_net_hangup(isdn_net_dev *idev)
-{
-	isdn_ctrl cmd;
-
-	del_timer(&idev->dial_timer);
-
-	printk(KERN_INFO "%s: local hangup\n", idev->name);
-	// FIXME via state machine
-	if (idev->isdn_slot)
-		isdn_slot_command(idev->isdn_slot, ISDN_CMD_HANGUP, &cmd);
-	return 1;
-}
-
-static int isdn_net_rcv_skb(struct isdn_slot *slot, struct sk_buff *skb);
-
-/*
- * Handle status-messages from ISDN-interfacecard.
- * This function is called from within the main-status-dispatcher
- * isdn_status_callback, which itself is called from the low-level driver.
- */
-static int
-isdn_net_event_callback(struct isdn_slot *slot, int pr, void *arg)
-{
-	isdn_net_dev *idev = slot->priv;
-
-	if (!idev) {
-		isdn_BUG();
-		return 0;
-	}
-	switch (pr) {
-	case EV_DATA_IND:
-		return isdn_net_rcv_skb(slot, arg);
-	case EV_STAT_DCONN:
-		return fsm_event(&idev->fi, EV_NET_STAT_DCONN, arg);
-	case EV_STAT_BCONN:
-		return fsm_event(&idev->fi, EV_NET_STAT_BCONN, arg);
-	case EV_STAT_BHUP:
-		return fsm_event(&idev->fi, EV_NET_STAT_BHUP, arg);
-	case EV_STAT_DHUP:
-		return fsm_event(&idev->fi, EV_NET_STAT_DHUP, arg);
-	case EV_STAT_CINF:
-		return fsm_event(&idev->fi, EV_NET_STAT_CINF, arg);
-	case EV_STAT_BSENT:
-		return fsm_event(&idev->fi, EV_NET_STAT_BSENT, arg);
-	default:
-		printk("unknown pr %d\n", pr);
-		return 0;
-	}
-}
-
-static int
-isdn_net_handle_event(isdn_net_dev *idev, int pr, void *arg)
-{
-	return fsm_event(&idev->fi, pr, arg);
-}
-
-static int
-hang_up(struct fsm_inst *fi, int pr, void *arg)
-{
-	isdn_net_dev *idev = fi->userdata;
-
-	isdn_net_hangup(idev);
-	return 0;
-}
-
-static int
-got_bsent(struct fsm_inst *fi, int pr, void *arg)
-{
-	isdn_net_dev *idev = fi->userdata;
-	isdn_ctrl *c = arg;
-	
-	isdn_net_bsent(idev, c);
-	return 0;
-}
-
-static struct fsm_node isdn_net_fn_tbl[] = {
-	{ ST_NULL,           EV_NET_DO_DIAL,         do_dial       },
-	{ ST_NULL,           EV_NET_DO_ACCEPT,       accept_icall  },
-	{ ST_NULL,           EV_NET_DO_CALLBACK,     do_callback   },
-
-	{ ST_OUT_WAIT_DCONN, EV_NET_TIMER_DIAL,      dial_timeout  },
-	{ ST_OUT_WAIT_DCONN, EV_NET_STAT_DCONN,      out_dconn     },
-	{ ST_OUT_WAIT_DCONN, EV_NET_STAT_DHUP,       connect_fail  },
-	{ ST_OUT_WAIT_DCONN, EV_NET_TIMER_CB_OUT,    hang_up       },
-
-	{ ST_OUT_WAIT_BCONN, EV_NET_TIMER_DIAL,      dial_timeout  },
-	{ ST_OUT_WAIT_BCONN, EV_NET_STAT_BCONN,      bconn         },
-	{ ST_OUT_WAIT_BCONN, EV_NET_STAT_DHUP,       connect_fail  },
-
-	{ ST_IN_WAIT_DCONN,  EV_NET_TIMER_INCOMING,  hang_up       },
-	{ ST_IN_WAIT_DCONN,  EV_NET_STAT_DCONN,      in_dconn      },
-	{ ST_IN_WAIT_DCONN,  EV_NET_STAT_DHUP,       connect_fail  },
-
-	{ ST_IN_WAIT_BCONN,  EV_NET_TIMER_INCOMING,  hang_up       },
-	{ ST_IN_WAIT_BCONN,  EV_NET_STAT_BCONN,      bconn         },
-	{ ST_IN_WAIT_BCONN,  EV_NET_STAT_DHUP,       connect_fail  },
-
-	{ ST_ACTIVE,         EV_NET_TIMER_HUP,       check_hup     },
-	{ ST_ACTIVE,         EV_NET_STAT_BHUP,       bhup          },
-	{ ST_ACTIVE,         EV_NET_STAT_CINF,       got_cinf      },
-	{ ST_ACTIVE,         EV_NET_STAT_BSENT,      got_bsent     },
-
-	{ ST_WAIT_DHUP,      EV_NET_STAT_DHUP,       dhup          },
-
-	{ ST_WAIT_BEFORE_CB, EV_NET_TIMER_CB_IN,     do_dial       },
-
-	{ ST_OUT_DIAL_WAIT,  EV_NET_TIMER_DIAL_WAIT, dialout_next  },
-};
-
-static struct fsm isdn_net_fsm = {
-	.st_cnt = ARRAY_SIZE(isdn_net_st_str),
-	.st_str = isdn_net_st_str,
-	.ev_cnt = ARRAY_SIZE(isdn_net_ev_str),
-	.ev_str = isdn_net_ev_str,
-	.fn_cnt = ARRAY_SIZE(isdn_net_fn_tbl),
-	.fn_tbl = isdn_net_fn_tbl,
-};
-
-static void isdn_net_dev_debug(struct fsm_inst *fi, char *fmt, ...)
-{
-	va_list args;
-	isdn_net_dev *idev = fi->userdata;
-	char buf[128];
-	char *p = buf;
-
-	va_start(args, fmt);
-	p += sprintf(p, "%s: ", idev->name);
-	p += vsprintf(p, fmt, args);
-	va_end(args);
-	printk(KERN_DEBUG "%s\n", buf);
-}
-
-/* ====================================================================== */
-/* xmit path                                                              */
-/* ====================================================================== */
-
-#define ISDN_NET_MAX_QUEUE_LENGTH 2
-
-/*
- * is this particular channel busy?
- */
-static inline int
-isdn_net_dev_busy(isdn_net_dev *idev)
-{
-	return idev->frame_cnt >= ISDN_NET_MAX_QUEUE_LENGTH;
-}
-
-/*
- * find out if the net_device which this mlp is belongs to is busy.
- * It's busy iff all channels are busy.
- * must hold mlp->xmit_lock
- * FIXME: Use a mlp->frame_cnt instead of loop?
- */
-static inline int
-isdn_net_local_busy(isdn_net_local *mlp)
-{
-	isdn_net_dev *idev;
-
-	list_for_each_entry(idev, &mlp->online, online) {
-		if (!isdn_net_dev_busy(idev))
-			return 0;
-	}
-	return 1;
-}
-
-/*
- * For the given net device, this will get a non-busy channel out of the
- * corresponding bundle.
- * must hold mlp->xmit_lock
- */
-isdn_net_dev *
-isdn_net_get_xmit_dev(isdn_net_local *mlp)
-{
-	isdn_net_dev *idev;
-
-	list_for_each_entry(idev, &mlp->online, online) {
-		if (!isdn_net_dev_busy(idev)) {
-			/* point the head to next online channel */
-			list_del(&mlp->online);
-			list_add(&mlp->online, &idev->online);
-			return idev;
-		}
-	}
-	return NULL;
-}
-
-/* mlp->xmit_lock must be held */
-static inline void
-isdn_net_inc_frame_cnt(isdn_net_dev *idev)
-{
-	isdn_net_local *mlp = idev->mlp;
-
-	if (isdn_net_dev_busy(idev))
-		isdn_BUG();
-		
-	idev->frame_cnt++;
-	if (isdn_net_local_busy(mlp))
-		netif_stop_queue(&mlp->dev);
-}
-
-/* mlp->xmit_lock must be held */
-static inline void
-isdn_net_dec_frame_cnt(isdn_net_dev *idev)
-{
-	isdn_net_local *mlp = idev->mlp;
-
-	idev->frame_cnt--;
-
-	if (isdn_net_dev_busy(idev))
-		isdn_BUG();
-
-	if (!skb_queue_empty(&idev->super_tx_queue))
-		tasklet_schedule(&idev->tlet);
-	else
-		netif_wake_queue(&mlp->dev);
-}
-
-static void
-isdn_net_tasklet(unsigned long data)
-{
-	isdn_net_dev *idev = (isdn_net_dev *) data;
-	isdn_net_local *mlp = idev->mlp;
-	struct sk_buff *skb;
-	unsigned long flags;
-
-	spin_lock_irqsave(&mlp->xmit_lock, flags);
-	while (!isdn_net_dev_busy(idev) &&
-	       (skb = skb_dequeue(&idev->super_tx_queue))) {
-		isdn_net_writebuf_skb(idev, skb);
-	}
-	spin_unlock_irqrestore(&mlp->xmit_lock, flags);
-}
-
-/* We're good to accept (IP/whatever) traffic now */
-
-void
-isdn_net_online(isdn_net_dev *idev)
-{
-	// FIXME check we're connected
-	isdn_net_local *mlp = idev->mlp;
-	unsigned long flags;
-
-	spin_lock_irqsave(&mlp->xmit_lock, flags);
-	list_add(&idev->online, &mlp->online);
-	spin_unlock_irqrestore(&mlp->xmit_lock, flags);
-
-	netif_wake_queue(&mlp->dev);
-}
-
-/* No more (IP/whatever) traffic over the net interface */
-
-void
-isdn_net_offline(isdn_net_dev *idev)
-{
-	isdn_net_local *mlp = idev->mlp;
-	unsigned long flags;
-
-	spin_lock_irqsave(&mlp->xmit_lock, flags);
-	list_del(&idev->online);
-	spin_unlock_irqrestore(&mlp->xmit_lock, flags);
-	
-	skb_queue_purge(&idev->super_tx_queue);
-}
-
-/* 
- * all frames sent from the (net) LL to a HL driver should go via this function
- * must hold mlp->xmit_lock
- */
-void
-isdn_net_writebuf_skb(isdn_net_dev *idev, struct sk_buff *skb)
-{
-	isdn_net_local *mlp = idev->mlp;
-	int ret;
-	int len = skb->len;     /* save len */
-
-	/* before obtaining the lock the caller should have checked that
-	   the lp isn't busy */
-	if (isdn_net_dev_busy(idev)) {
-		isdn_BUG();
-		goto error;
-	}
-
-	if (!isdn_net_is_connected(idev)) {
-		isdn_BUG();
-		goto error;
-	}
-	ret = isdn_slot_write(idev->isdn_slot, skb);
-	if (ret != len) {
-		/* we should never get here */
-		printk(KERN_WARNING "%s: HL driver queue full\n", idev->name);
-		goto error;
-	}
-	
-	idev->transcount += len;
-	isdn_net_inc_frame_cnt(idev);
-	return;
-
- error:
-	dev_kfree_skb(skb);
-	mlp->stats.tx_errors++;
-}
-
-/* A packet has successfully been sent out. */
-
-static int
-isdn_net_bsent(isdn_net_dev *idev, isdn_ctrl *c)
-{
-	isdn_net_local *mlp = idev->mlp;
-	unsigned long flags;
-
-	spin_lock_irqsave(&mlp->xmit_lock, flags);
-	isdn_net_dec_frame_cnt(idev);
-	spin_unlock_irqrestore(&mlp->xmit_lock, flags);
-	mlp->stats.tx_packets++;
-	mlp->stats.tx_bytes += c->parm.length;
-	return 1;
-}
-
-/*
- *  Based on cps-calculation, check if device is overloaded.
- *  If so, and if a slave exists, trigger dialing for it.
- *  If any slave is online, deliver packets using a simple round robin
- *  scheme.
- *
- *  Return: 0 on success, !0 on failure.
- */
-
-int
-isdn_net_start_xmit(struct sk_buff *skb, struct net_device *ndev)
-{
-	isdn_net_dev	*idev;
-	isdn_net_local	*mlp = ndev->priv;
-	unsigned long	flags;
-	int		retval;
-
-	ndev->trans_start = jiffies;
-
-	spin_lock_irqsave(&mlp->xmit_lock, flags);
-
-	if (list_empty(&mlp->online)) {
-		retval = isdn_net_autodial(skb, ndev);
-		goto out;
-	}
-
-	idev = isdn_net_get_xmit_dev(mlp);
-	if (!idev) {
-		printk(KERN_INFO "%s: all channels busy - requeuing!\n", ndev->name);
-		netif_stop_queue(ndev);
-		retval = 1;
-		goto out;
-	}
-
-	isdn_net_writebuf_skb(idev, skb);
-
-	/* the following stuff is here for backwards compatibility.
-	 * in future, start-up and hangup of slaves (based on current load)
-	 * should move to userspace and get based on an overall cps
-	 * calculation
-	 */
-	if (jiffies != idev->last_jiffies) {
-		idev->cps = idev->transcount * HZ / (jiffies - idev->last_jiffies);
-		idev->last_jiffies = jiffies;
-		idev->transcount = 0;
-	}
-	if ((get_isdn_dev())->net_verbose > 3)
-		printk(KERN_DEBUG "%s: %d bogocps\n", idev->name, idev->cps);
-
-	if (idev->cps > mlp->triggercps) {
-		if (!idev->sqfull) {
-			/* First time overload: set timestamp only */
-			idev->sqfull = 1;
-			idev->sqfull_stamp = jiffies;
-		} else {
-			/* subsequent overload: if slavedelay exceeded, start dialing */
-			if (time_after(jiffies, idev->sqfull_stamp + mlp->slavedelay)) {
-				if (ISDN_NET_DIALMODE(*mlp) == ISDN_NET_DM_AUTO)
-					__isdn_net_dial_slave(mlp);
-			}
-		}
-	} else {
-		if (idev->sqfull && time_after(jiffies, idev->sqfull_stamp + mlp->slavedelay + 10 * HZ)) {
-			idev->sqfull = 0;
-		}
-		/* this is a hack to allow auto-hangup for slaves on moderate loads */
-		list_del(&mlp->online);
-		list_add_tail(&mlp->online, &idev->online);
-	}
-
-	retval = 0;
- out:
-	spin_unlock_irqrestore(&mlp->xmit_lock, flags);
-	return retval;
-}
-
-/*
- * this function is used to send supervisory data, i.e. data which was
- * not received from the network layer, but e.g. frames from ipppd, CCP
- * reset frames etc.
- * must hold mlp->xmit_lock
- */
-void
-isdn_net_write_super(isdn_net_dev *idev, struct sk_buff *skb)
-{
-	if (!isdn_net_dev_busy(idev)) {
-		isdn_net_writebuf_skb(idev, skb);
-	} else {
-		skb_queue_tail(&idev->super_tx_queue, skb);
-	}
-}
-
-/* ====================================================================== */
-/* receive path                                                           */
-/* ====================================================================== */
-
-/*
- * A packet arrived via ISDN. Search interface-chain for a corresponding
- * interface. If found, deliver packet to receiver-function and return 1,
- * else return 0.
- */
-static int
-isdn_net_rcv_skb(struct isdn_slot *slot, struct sk_buff *skb)
-{
-	isdn_net_dev *idev = slot->priv;
-	isdn_net_local *mlp;
-
-	if (!idev) {
-		isdn_BUG();
-		return 0;
-	}
-	if (!isdn_net_is_connected(idev)) {
-		isdn_BUG();
-		return 0;
-	}
-
-	mlp = idev->mlp;
-
-	idev->transcount += skb->len;
-
-	mlp->stats.rx_packets++;
-	mlp->stats.rx_bytes += skb->len;
-	skb->dev = &mlp->dev;
-	skb->pkt_type = PACKET_HOST;
-	isdn_dumppkt("R:", skb->data, skb->len, 40);
-
-	mlp->ops->receive(mlp, idev, skb);
-
-	return 1;
-}
-
-/*
- * After handling connection-type specific stuff, the receiver function
- * can use this function to pass the skb on to the network layer.
- */
-void
-isdn_netif_rx(isdn_net_dev *idev, struct sk_buff *skb, u16 protocol)
-{
-	idev->huptimer = 0;
-
-	skb->protocol = protocol;
-	skb->dev = &idev->mlp->dev;
-	netif_rx(skb);
-}
-
-/* ====================================================================== */
-/* init / exit                                                            */
-/* ====================================================================== */
-
-void
-isdn_net_lib_init(void)
-{
-	fsm_new(&isdn_net_fsm);
-
-#ifdef CONFIG_ISDN_NET_SIMPLE
-	register_isdn_netif(ISDN_NET_ENCAP_ETHER,      &isdn_ether_ops);
-	register_isdn_netif(ISDN_NET_ENCAP_RAWIP,      &isdn_rawip_ops);
-	register_isdn_netif(ISDN_NET_ENCAP_IPTYP,      &isdn_iptyp_ops);
-	register_isdn_netif(ISDN_NET_ENCAP_UIHDLC,     &isdn_uihdlc_ops);
-#endif
-#ifdef CONFIG_ISDN_NET_CISCO
-	register_isdn_netif(ISDN_NET_ENCAP_CISCOHDLC,  &isdn_ciscohdlck_ops);
-	register_isdn_netif(ISDN_NET_ENCAP_CISCOHDLCK, &isdn_ciscohdlck_ops);
-#endif
-#ifdef CONFIG_ISDN_X25
-	register_isdn_netif(ISDN_NET_ENCAP_X25IFACE,   &isdn_x25_ops);
-#endif
-#ifdef CONFIG_ISDN_PPP
-	register_isdn_netif(ISDN_NET_ENCAP_SYNCPPP,    &isdn_ppp_ops);
-#endif
-}
-
-void
-isdn_net_lib_exit(void)
-{
-	fsm_free(&isdn_net_fsm);
-}
--- diff/drivers/isdn/i4l/isdn_net_lib.h	2003-09-17 12:28:06.000000000 +0100
+++ source/drivers/isdn/i4l/isdn_net_lib.h	1970-01-01 01:00:00.000000000 +0100
@@ -1,224 +0,0 @@
-/* Linux ISDN subsystem, network interface support code
- *
- * Copyright 1994-1998  by Fritz Elfert (fritz@isdn4linux.de)
- *           1995,96    by Thinking Objects Software GmbH Wuerzburg
- *           1995,96    by Michael Hipp (Michael.Hipp@student.uni-tuebingen.de)
- *           1999-2002  by Kai Germaschewski <kai@germaschewski.name>
- *
- * This software may be used and distributed according to the terms
- * of the GNU General Public License, incorporated herein by reference.
- */
-
-#ifndef __ISDN_NET_LIB_H__
-#define __ISDN_NET_LIB_H__
-
-#include <linux/isdn.h>
-
-typedef struct isdn_net_local_s isdn_net_local;
-typedef struct isdn_net_dev_s isdn_net_dev;
-
-struct isdn_netif_ops {
-	int			(*hard_start_xmit) (struct sk_buff *skb,
-						    struct net_device *dev);
-	int			(*hard_header) (struct sk_buff *skb,
-						struct net_device *dev,
-						unsigned short type,
-						void *daddr,
-						void *saddr,
-						unsigned len);
-	int			(*do_ioctl)(struct net_device *dev,
-					    struct ifreq *ifr, int cmd);
-
-	unsigned short		flags;	/* interface flags (a la BSD)	*/
-	unsigned short		type;	/* interface hardware type	*/
-	unsigned char		addr_len;/* hardware address length	*/
-	void                    (*receive)(struct isdn_net_local_s *,
-					   struct isdn_net_dev_s *,
-					   struct sk_buff *);
-	void                    (*connected)(struct isdn_net_dev_s *);
-	void                    (*disconnected)(struct isdn_net_dev_s *);
-	int                     (*bind)(struct isdn_net_dev_s *);
-	void                    (*unbind)(struct isdn_net_dev_s *);
-	int                     (*init)(struct isdn_net_local_s *);
-	void                    (*cleanup)(struct isdn_net_local_s *);
-	int                     (*open)(struct isdn_net_local_s *);
-	void                    (*close)(struct isdn_net_local_s *);
-};
-
-/* our interface to isdn_common.c */
-void isdn_net_lib_init(void);
-void isdn_net_lib_exit(void);
-void isdn_net_hangup_all(void);
-int  isdn_net_ioctl(struct inode *, struct file *, uint, ulong);
-int  isdn_net_find_icall(struct isdn_slot *slot, setup_parm *setup);
-
-/* provided for interface types to use */
-void isdn_net_writebuf_skb(isdn_net_dev *, struct sk_buff *skb);
-void isdn_net_write_super(isdn_net_dev *, struct sk_buff *skb);
-void isdn_net_online(isdn_net_dev *idev);
-void isdn_net_offline(isdn_net_dev *idev);
-int  isdn_net_start_xmit(struct sk_buff *skb, struct net_device *ndev);
-void isdn_netif_rx(isdn_net_dev *idev, struct sk_buff *skb, u16 protocol);
-isdn_net_dev *isdn_net_get_xmit_dev(isdn_net_local *mlp);
-int  isdn_net_hangup(isdn_net_dev *);
-int  isdn_net_autodial(struct sk_buff *skb, struct net_device *ndev);
-int  isdn_net_dial_req(isdn_net_dev *);
-int  register_isdn_netif(int encap, struct isdn_netif_ops *ops);
-
-/* ====================================================================== */
-
-/* Feature- and status-flags for a net-interface */
-#define ISDN_NET_SECURE     0x02       /* Accept calls from phonelist only  */
-#define ISDN_NET_CALLBACK   0x04       /* activate callback                 */
-#define ISDN_NET_CBHUP      0x08       /* hangup before callback            */
-#define ISDN_NET_CBOUT      0x10       /* remote machine does callback      */
-
-#define ISDN_NET_MAGIC      0x49344C02 /* for paranoia-checking             */
-
-/* Phone-list-element */
-struct isdn_net_phone {
-	struct list_head list;
-	char num[ISDN_MSNLEN];
-};
-
-/* per network interface data (dev->priv) */
-
-struct isdn_net_local_s {
-  ulong                  magic;
-  struct net_device      dev;          /* interface to upper levels        */
-  struct net_device_stats stats;       /* Ethernet Statistics              */
-  struct isdn_netif_ops *ops;
-  void                  *inl_priv;     /* interface types can put their
-					  private data here                */
-  int                    flags;        /* Connection-flags                 */
-  int                    dialmax;      /* Max. Number of Dial-retries      */
-  int	        	 dialtimeout;  /* How long shall we try on dialing */
-  int			 dialwait;     /* wait after failed attempt        */
-
-  int                    cbdelay;      /* Delay before Callback starts     */
-  char                   msn[ISDN_MSNLEN]; /* MSNs/EAZs for this interface */
-
-  u_char                 cbhup;        /* Flag: Reject Call before Callback*/
-  int                    hupflags;     /* Flags for charge-unit-hangup:    */
-  int                    onhtime;      /* Time to keep link up             */
-
-  u_char                 p_encap;      /* Packet encapsulation             */
-  u_char                 l2_proto;     /* Layer-2-protocol                 */
-  u_char                 l3_proto;     /* Layer-3-protocol                 */
-
-  ulong                  slavedelay;   /* Dynamic bundling delaytime       */
-  int                    triggercps;   /* BogoCPS needed for trigger slave */
-  struct list_head       phone[2];     /* List of remote-phonenumbers      */
-				       /* phone[0] = Incoming Numbers      */
-				       /* phone[1] = Outgoing Numbers      */
-
-  struct list_head       slaves;       /* list of all bundled channels    
-					  protected by serializing config
-					  ioctls / no change allowed when
-					  interface is running             */
-  struct list_head       online;       /* list of all bundled channels 
-					  which can be used for actual
-					  data (IP) transfer              
-					  protected by xmit_lock           */
-
-  spinlock_t             xmit_lock;    /* used to protect the xmit path of 
-					  a net_device, including all
-					  associated channels's frame_cnt  */
-  struct list_head       running_devs; /* member of global running_devs    */
-  atomic_t               refcnt;       /* references held by ISDN code     */
-
-};
-
-
-/* per ISDN channel (ISDN interface) data */
-
-struct isdn_net_dev_s {
-  struct isdn_slot	*isdn_slot;	/* Index to isdn device/channel     */
-  struct isdn_slot	*exclusive;	/* NULL if non excl                 */
-  int			pre_device;	/* Preselected isdn-device          */
-  int			pre_channel;	/* Preselected isdn-channel         */
-
-  struct timer_list	dial_timer;	/* dial events timer                */
-  struct fsm_inst	fi;		/* call control state machine       */
-  int			dial_event;	/* event in case of timer expiry    */
-  int			dial;		/* # of phone number just dialed    */
-  int			outgoing;	/* Flag: outgoing call              */
-  int			dialretry;	/* Counter for Dialout-retries      */
-
-  int			cps;		/* current speed of this interface  */
-  int			transcount;	/* byte-counter for cps-calculation */
-  u_long		last_jiffies;	/* when transcount was reset        */
-  int			sqfull;		/* Flag: netdev-queue overloaded    */
-  u_long		sqfull_stamp;	/* Start-Time of overload           */
-
-  int			huptimer;	/* Timeout-counter for auto-hangup  */
-  int			charge;		/* Counter for charging units       */
-  int			charge_state;	/* ChargeInfo state machine         */
-  u_long		chargetime;	/* Timer for Charging info          */
-  int			chargeint;	/* Interval between charge-infos    */
-
-  int			pppbind;	/* ippp device for bindings         */
-
-  struct sk_buff_head	super_tx_queue;	/* List of supervisory frames to  */
-					/* be transmitted asap              */
-  int			frame_cnt;	/* number of frames currently       */
-					/* queued in HL driver              */
-  struct tasklet_struct	tlet;
-
-  isdn_net_local	*mlp;		/* Ptr to master device for all devs*/
-
-  struct list_head	slaves;		/* member of local->slaves          */
-  struct list_head	online;		/* member of local->online          */
-
-  char			name[10];	/* Name of device                   */
-  struct list_head	global_list;	/* global list of all isdn_net_devs */
-  void			*ind_priv;	/* interface types can put their
-					   private data here                */
-};
-
-/* ====================================================================== */
-
-static inline int
-put_u8(unsigned char *p, u8 x)
-{
-	*p = x;
-	return 1;
-}
-
-static inline int
-put_u16(unsigned char *p, u16 x)
-{
-	*((u16 *)p) = htons(x);
-	return 2;
-}
-
-static inline int
-put_u32(unsigned char *p, u32 x)
-{
-	*((u32 *)p) = htonl(x);
-	return 4;
-}
-
-static inline int
-get_u8(unsigned char *p, u8 *x)
-{
-	*x = *p;
-	return 1;
-}
-
-static inline int
-get_u16(unsigned char *p, u16 *x)
-{
-	*x = ntohs(*((u16 *)p));
-	return 2;
-}
-
-static inline int
-get_u32(unsigned char *p, u32 *x)
-{
-	*x = ntohl(*((u32 *)p));
-	return 4;
-}
-
-
-#endif
--- diff/drivers/isdn/i4l/isdn_ppp_ccp.c	2004-01-19 10:22:56.000000000 +0000
+++ source/drivers/isdn/i4l/isdn_ppp_ccp.c	1970-01-01 01:00:00.000000000 +0100
@@ -1,657 +0,0 @@
-/* Linux ISDN subsystem, PPP CCP support
- *
- * Copyright 1994-1998  by Fritz Elfert (fritz@isdn4linux.de)
- *           1995,96    by Thinking Objects Software GmbH Wuerzburg
- *           1995,96    by Michael Hipp (Michael.Hipp@student.uni-tuebingen.de)
- *           1999-2002  by Kai Germaschewski <kai@germaschewski.name>
- *
- * This software may be used and distributed according to the terms
- * of the GNU General Public License, incorporated herein by reference.
- */
-
-#include "isdn_ppp_ccp.h"
-#include "isdn_common.h"
-#include "isdn_net_lib.h"
-#include "isdn_ppp.h"
-#include <linux/ppp-comp.h>
-
-/* ====================================================================== */                                                                       
-enum ippp_ccp_reset_states {
-	CCPResetIdle,
-	CCPResetSentReq,
-	CCPResetRcvdReq,
-	CCPResetSentAck,
-	CCPResetRcvdAck
-};
-
-struct ippp_ccp_reset_state {
-	enum ippp_ccp_reset_states state;/* State of this transaction */
-	struct ippp_ccp *ccp;            /* Backlink */
-	unsigned char id;		 /* id index */
-	unsigned char ta:1;		 /* The timer is active (flag) */
-	unsigned char expra:1;		 /* We expect a ResetAck at all */
-	int dlen;			 /* Databytes stored in data */
-	struct timer_list timer;	 /* For timeouts/retries */
-	/* This is a hack but seems sufficient for the moment. We do not want
-	   to have this be yet another allocation for some bytes, it is more
-	   memory management overhead than the whole mess is worth. */
-	unsigned char data[IPPP_RESET_MAXDATABYTES];
-};
-
-/* The data structure keeping track of the currently outstanding CCP Reset
-   transactions. */
-struct ippp_ccp_reset {
-	struct ippp_ccp_reset_state *rs[256];	/* One per possible id */
-	unsigned char lastid;			/* Last id allocated */
-};
-
-/* In-kernel handling of CCP Reset-Request and Reset-Ack is necessary,
-   but absolutely nontrivial. The most abstruse problem we are facing is
-   that the generation, reception and all the handling of timeouts and
-   resends including proper request id management should be entirely left
-   to the (de)compressor, but indeed is not covered by the current API to
-   the (de)compressor. The API is a prototype version from PPP where only
-   some (de)compressors have yet been implemented and all of them are
-   rather simple in their reset handling. Especially, their is only one
-   outstanding ResetAck at a time with all of them and ResetReq/-Acks do
-   not have parameters. For this very special case it was sufficient to
-   just return an error code from the decompressor and have a single
-   reset() entry to communicate all the necessary information between
-   the framework and the (de)compressor. Bad enough, LZS is different
-   (and any other compressor may be different, too). It has multiple
-   histories (eventually) and needs to Reset each of them independently
-   and thus uses multiple outstanding Acks and history numbers as an
-   additional parameter to Reqs/Acks.
-   All that makes it harder to port the reset state engine into the
-   kernel because it is not just the same simple one as in (i)pppd but
-   it must be able to pass additional parameters and have multiple out-
-   standing Acks. We are trying to achieve the impossible by handling
-   reset transactions independent by their id. The id MUST change when
-   the data portion changes, thus any (de)compressor who uses more than
-   one resettable state must provide and recognize individual ids for
-   each individual reset transaction. The framework itself does _only_
-   differentiate them by id, because it has no other semantics like the
-   (de)compressor might.
-   This looks like a major redesign of the interface would be nice,
-   but I don't have an idea how to do it better. */
-
-/* ====================================================================== */
-
-/* Free a given state and clear everything up for later reallocation */
-static void
-ippp_ccp_reset_free_state(struct ippp_ccp *ccp, unsigned char id)
-{
-	struct ippp_ccp_reset_state *rs	= ccp->reset->rs[id];
-
-	if (!rs)
-		return;
-	
-	if (rs->ta) // FIXME?
-		del_timer_sync(&rs->timer);
-
-	kfree(rs);
-	ccp->reset->rs[id] = NULL;
-}
-
-static void
-do_xmit_reset(struct ippp_ccp *ccp, unsigned char code, unsigned char id,
-	      unsigned char *data, int len)
-{
-	struct sk_buff *skb;
-	unsigned char *p;
-	u16 proto = ccp->proto == PPP_COMP ? PPP_CCP : PPP_CCPFRAG;
-
-	skb = ccp->alloc_skb(ccp->priv, 4 + len, GFP_ATOMIC);
-
-	p = skb_put(skb, 4);
-	p += put_u8 (p, code);
-	p += put_u8 (p, id);
-	p += put_u16(p, len + 4);
-
-	if (len)
-		memcpy(skb_put(skb, len), data, len);
-
-	isdn_ppp_frame_log("ccp-xmit", skb->data, skb->len, 32, -1, -1);
-
-	ccp->xmit(ccp->priv, skb, proto);
-}
-
-/* The timer callback function which is called when a ResetReq has timed out,
-   aka has never been answered by a ResetAck */
-static void
-isdn_ppp_ccp_timer_callback(unsigned long data)
-{
-	struct ippp_ccp_reset_state *rs = (struct ippp_ccp_reset_state *) data;
-
-	if (!rs->ta) {
-		isdn_BUG();
-		return;
-	}
-	if (rs->state != CCPResetSentReq) {
-		printk(KERN_WARNING "ippp_ccp: timer cb in wrong state %d\n",
-		       rs->state);
-		rs->ta = 0;
-		return;
-	}
-	/* We are correct here */
-	if (!rs->expra) {
-		/* Hmm, there is no Ack really expected. We can clean
-		   up the state now, it will be reallocated if the
-		   decompressor insists on another reset */
-		rs->ta = 0;
-		ippp_ccp_reset_free_state(rs->ccp, rs->id);
-		return;
-	}
-	printk(KERN_DEBUG "ippp_ccp: CCP Reset timed out for id %d\n",
-	       rs->id);
-	/* Push it again */
-	do_xmit_reset(rs->ccp, CCP_RESETREQ, rs->id, rs->data, rs->dlen);
-
-	mod_timer(&rs->timer, jiffies + 5 * HZ);
-}
-
-/* Allocate a new reset transaction state */
-static struct ippp_ccp_reset_state *
-ippp_ccp_reset_alloc_state(struct ippp_ccp *ccp, unsigned char id)
-{
-	struct ippp_ccp_reset_state *rs;
-
-	rs = kmalloc(sizeof(struct ippp_ccp_reset_state), GFP_KERNEL);
-	if(!rs)
-		return NULL;
-	memset(rs, 0, sizeof(struct ippp_ccp_reset_state));
-	rs->state = CCPResetIdle;
-	rs->ccp = ccp;
-	rs->id = id;
-	init_timer(&rs->timer);
-	rs->timer.data = (unsigned long)rs;
-	rs->timer.function = isdn_ppp_ccp_timer_callback;
-
-	ccp->reset->rs[id] = rs;
-	return rs;
-}
-
-/* A decompressor wants a reset with a set of parameters - do what is
-   necessary to fulfill it */
-static void
-ippp_ccp_reset_xmit(struct ippp_ccp *ccp,
-		    struct isdn_ppp_resetparams *rp)
-{
-	struct ippp_ccp_reset_state *rs;
-	int id;
-
-	if (rp->valid) {
-		/* The decompressor defines parameters by itself */
-		if (!rp->rsend)
-			return;
-
-		/* And it wants us to send a request */
-		if (!rp->idval) {
-			isdn_BUG();
-			return;
-		}
-		id = rp->id;
-	} else {
-		/* The reset params are invalid. The decompressor does not
-		   care about them, so we just send the minimal requests
-		   and increase ids only when an Ack is received for a
-		   given id */
-		id = ccp->reset->lastid++;
-		/* We always expect an Ack if the decompressor doesn't
-		   know	better */
-		rp->expra = 1;
-		rp->dtval = 0;
-	}
-	rs = ccp->reset->rs[id];
-	if (rs) {
-		printk(KERN_INFO "ippp_ccp: reset xmit in wrong state %d "
-		       "for id %d (%d)\n", rs->state, id, rs->ta);
-		return;
-	}
-	/* Ok, this is a new transaction */
-	printk(KERN_DEBUG "ippp_ccp: new xmit for id %d\n", id);
-	rs = ippp_ccp_reset_alloc_state(ccp, id);
-	if(!rs) {
-		printk(KERN_INFO "ippp_ccp: out of mem allocing ccp trans\n");
-		return;
-	}
-	rs->expra = rp->expra;
-	rs->id = id;
-	if (rp->dtval) {
-		rs->dlen = rp->dlen;
-		memcpy(rs->data, rp->data, rp->dlen);
-	} else {
-		rs->dlen = 0;
-	}
-
-	rs->state = CCPResetSentReq;
-	do_xmit_reset(rs->ccp, CCP_RESETREQ, rs->id, rs->data, rs->dlen);
-
-	/* Start the timer */
-	rs->timer.expires = jiffies + 5*HZ;
-	add_timer(&rs->timer);
-	rs->ta = 1;
-}
-
-/* ====================================================================== */
-
-struct ippp_ccp *
-ippp_ccp_alloc(void)
-{
-	struct ippp_ccp *ccp;
-
-	ccp = kmalloc(sizeof(*ccp), GFP_ATOMIC); // FIXME
-	if (!ccp)
-		return NULL;
-	memset(ccp, 0, sizeof(*ccp));
-	ccp->mru = 1524;      /* MRU, default 1524 */
-	ccp->reset = kmalloc(sizeof(*ccp->reset), GFP_ATOMIC); // FIXME alloc together?
-	if (!ccp->reset) {
-		kfree(ccp);
-		return NULL;
-	}
-	memset(ccp->reset, 0, sizeof(*ccp->reset));
-	return ccp;
-}
-
-void
-ippp_ccp_free(struct ippp_ccp *ccp)
-{
-	int id;
-
-	if (ccp->comp_stat) {
-		ccp->compressor->free(ccp->comp_stat);
-		module_put(ccp->compressor->owner);
-	}
-	if (ccp->decomp_stat) {
-		ccp->decompressor->free(ccp->decomp_stat);
-		module_put(ccp->decompressor->owner);
-	}
-	for (id = 0; id < 256; id++) {
-		if (ccp->reset->rs[id])
-			ippp_ccp_reset_free_state(ccp, id);
-	}
-	kfree(ccp->reset);
-	kfree(ccp);
-}
-
-int
-ippp_ccp_set_mru(struct ippp_ccp *ccp, unsigned int mru)
-{
-	ccp->mru = mru;
-	return 0;
-}
-
-unsigned int
-ippp_ccp_get_flags(struct ippp_ccp *ccp)
-{
-	return ccp->compflags & (SC_DC_ERROR|SC_DC_FERROR);
-}
-
-/*
- * compress a frame 
- * returns original skb if we did not compress the frame
- * and a new skb otherwise
- */
-struct sk_buff *
-ippp_ccp_compress(struct ippp_ccp *ccp, struct sk_buff *skb_in, u16 *proto)
-{
-	struct sk_buff *skb;
-
-	if (!(ccp->compflags & (SC_COMP_ON|SC_DECOMP_ON))) {
-		/* We send compressed only if both down- und upstream
-		   compression is negotiated, that means, CCP is up */
-		return skb_in;
-	}
-	/* we do not compress control protocols */
-	if (*proto > 0x3fff) {
-		return skb_in;
-	}
-	if (!ccp->compressor || !ccp->comp_stat) {
-		isdn_BUG();
-		return skb_in;
-	}
-	/* Allow for at least 150 % expansion (for now) */
-	skb = alloc_skb(skb_in->len*2 + skb_headroom(skb_in), GFP_ATOMIC);
-	if (!skb)
-		return skb_in;
-
-	skb_reserve(skb, skb_headroom(skb_in));
-	if (!ccp->compressor->compress(ccp->comp_stat, skb_in, skb, *proto)) {
-		dev_kfree_skb(skb);
-		return skb_in;
-	}
-	isdn_ppp_frame_log("comp  in:", skb_in->data, skb_in->len, 20, -1, -1);
-	isdn_ppp_frame_log("comp out:", skb->data, skb->len, 20, -1, -1);
-	dev_kfree_skb(skb_in);
-	*proto = ccp->proto;
-	return skb;
-}
-
-/* 
- * decompress packet
- *
- * proto is updated to protocol field of uncompressed packet.
- * retval: decompressed packet,
- *         same packet if uncompressed,
- *	   NULL if decompression error
- */
-
-struct sk_buff *
-ippp_ccp_decompress(struct ippp_ccp *ccp, struct sk_buff *skb_in, u16 *proto)
-{
-	struct sk_buff *skb;
-	struct isdn_ppp_resetparams rsparm;
-	unsigned char rsdata[IPPP_RESET_MAXDATABYTES];
-	int len;
-
-	if (!(ccp->compflags & SC_DECOMP_ON)) {
-		return skb_in;
-	}
-	if (!ccp->decompressor || !ccp->decomp_stat) {
-		isdn_BUG();
-		return skb_in;
-	}
-	if (*proto != ccp->proto) {
-		/* uncompressed packets are fed through the decompressor to
-		 * update the decompressor state */
-		ccp->decompressor->incomp(ccp->decomp_stat, skb_in, *proto);
-		return skb_in;
-	}
-	skb = dev_alloc_skb(ccp->mru + PPP_HDRLEN); // FIXME oom?
-
-	// Set up reset params for the decompressor
-	memset(&rsparm, 0, sizeof(rsparm));
-	rsparm.data = rsdata;
-	rsparm.maxdlen = IPPP_RESET_MAXDATABYTES;
-
-	len = ccp->decompressor->decompress(ccp->decomp_stat, skb_in, skb,
-					    &rsparm);
-	isdn_ppp_frame_log("deco  in:", skb_in->data, skb_in->len, 20, -1, -1);
-	isdn_ppp_frame_log("deco out:", skb->data, skb->len, 20, -1, -1);
-	kfree_skb(skb_in);
-
-	if (len <= 0) {
-		switch(len) {
-		case DECOMP_ERROR:
-			printk(KERN_INFO "ippp: decomp wants reset with%s params\n",
-			       rsparm.valid ? "" : "out");
-			
-			ippp_ccp_reset_xmit(ccp, &rsparm);
-			break;
-		case DECOMP_FATALERROR:
-			ccp->compflags |= SC_DC_FERROR;
-			/* Kick ipppd to recognize the error */
-			ccp->kick_up(ccp->priv);
-			break;
-		}
-		kfree_skb(skb);
-		return NULL;
-	}
-	if (isdn_ppp_strip_proto(skb, proto)) {
-		kfree_skb(skb);
-		return NULL;
-	}
-	return skb;
-}
-
-/* An Ack was received for this id. This means we stop the timer and clean
-   up the state prior to calling the decompressors reset routine. */
-static void
-isdn_ppp_ccp_reset_ack_rcvd(struct ippp_ccp *ccp, unsigned char id)
-{
-	struct ippp_ccp_reset_state *rs = ccp->reset->rs[id];
-
-	if (!rs) {
-		printk(KERN_INFO "ippp_ccp: ResetAck received for unknown id"
-		       " %d\n", id);
-		return;
-	}
-
-	if (rs->ta && rs->state == CCPResetSentReq) {
-		/* Great, we are correct */
-		if(!rs->expra)
-			printk(KERN_DEBUG "ippp_ccp: ResetAck received"
-			       " for id %d but not expected\n", id);
-	} else {
-		printk(KERN_INFO "ippp_ccp: ResetAck received out of"
-		       "sync for id %d\n", id);
-	}
-	if(rs->ta) {
-		rs->ta = 0;
-		del_timer(&rs->timer);
-	}
-	ippp_ccp_reset_free_state(ccp, id);
-}
-
-void
-ippp_ccp_receive_ccp(struct ippp_ccp *ccp, struct sk_buff *skb)
-{
-	int len;
-	struct isdn_ppp_resetparams rsparm;
-	unsigned char rsdata[IPPP_RESET_MAXDATABYTES];	
-
-	isdn_ppp_frame_log("ccp-recv", skb->data, skb->len, 32, -1, -1);
-
-	switch(skb->data[0]) {
-	case CCP_CONFREQ:
-		if (ccp->debug & 0x10)
-			printk(KERN_DEBUG "Disable compression here!\n");
-
-		ccp->compflags &= ~SC_COMP_ON;		
-		break;
-	case CCP_TERMREQ:
-	case CCP_TERMACK:
-		if (ccp->debug & 0x10)
-			printk(KERN_DEBUG "Disable (de)compression here!\n");
-
-		ccp->compflags &= ~(SC_DECOMP_ON|SC_COMP_ON);		
-		break;
-	case CCP_CONFACK:
-		/* if we RECEIVE an ackowledge we enable the decompressor */
-		if (ccp->debug & 0x10)
-			printk(KERN_DEBUG "Enable decompression here!\n");
-
-		if (!ccp->decomp_stat)
-			break;
-		ccp->compflags |= SC_DECOMP_ON;
-		break;
-	case CCP_RESETACK:
-		printk(KERN_DEBUG "Received ResetAck from peer\n");
-		len = (skb->data[2] << 8) | skb->data[3];
-		len -= 4;
-
-		/* If a reset Ack was outstanding for this id, then
-		   clean up the state engine */
-		isdn_ppp_ccp_reset_ack_rcvd(ccp, skb->data[1]);
-		if (ccp->decomp_stat)
-			ccp->decompressor->reset(ccp->decomp_stat,
-						 skb->data[0], skb->data[1],
-						 len ? &skb->data[4] : NULL,
-						 len, NULL);
-		/* TODO: This is not easy to decide here */
-		ccp->compflags &= ~SC_DECOMP_DISCARD;
-		break;
-	case CCP_RESETREQ:
-		printk(KERN_DEBUG "Received ResetReq from peer\n");
-		/* Receiving a ResetReq means we must reset our compressor */
-		/* Set up reset params for the reset entry */
-		memset(&rsparm, 0, sizeof(rsparm));
-		rsparm.data = rsdata;
-		rsparm.maxdlen = IPPP_RESET_MAXDATABYTES; 
-		/* Isolate data length */
-		len = (skb->data[2] << 8) | skb->data[3];
-		len -= 4;
-		if (ccp->comp_stat)
-			ccp->compressor->reset(ccp->comp_stat,
-					       skb->data[0], skb->data[1],
-					       len ? &skb->data[4] : NULL,
-					       len, &rsparm);
-		/* Ack the Req as specified by rsparm */
-		if (rsparm.valid) {
-			/* Compressor reset handler decided how to answer */
-			if (!rsparm.rsend) {
-				printk(KERN_DEBUG "ResetAck suppressed\n");
-				return;
-			}
-			/* We should send a Frame */
-			do_xmit_reset(ccp, CCP_RESETACK,
-				      rsparm.idval ? rsparm.id : skb->data[1],
-				      rsparm.data,
-				      rsparm.dtval ? rsparm.dlen : 0);
-			return;
-		}
-		/* We answer with a straight reflected Ack */
-		do_xmit_reset(ccp, CCP_RESETACK, skb->data[1], 
-			      skb->data + 4, len);
-	}
-}
-
-void
-ippp_ccp_send_ccp(struct ippp_ccp *ccp, struct sk_buff *skb)
-{
-	isdn_ppp_frame_log("ccp-xmit", skb->data, skb->len, 32, -1, -1);
-
-        switch (skb->data[2]) {
-	case CCP_CONFREQ:
-		if (ccp->debug & 0x10)
-			printk(KERN_DEBUG "Disable decompression here!\n");
-
-		ccp->compflags &= ~SC_DECOMP_ON;
-		break;
-	case CCP_TERMREQ:
-	case CCP_TERMACK:
-		if (ccp->debug & 0x10)
-			printk(KERN_DEBUG "Disable (de)compression here!\n");
-
-		ccp->compflags &= ~(SC_DECOMP_ON|SC_COMP_ON);
-		break;
-	case CCP_CONFACK:
-		/* if we SEND an ackowledge we can/must enable the compressor */
-		if (ccp->debug & 0x10)
-			printk(KERN_DEBUG "Enable compression here!\n");
-
-		if (!ccp->compressor)
-			break;
-
-		ccp->compflags |= SC_COMP_ON;
-		break;
-	case CCP_RESETACK:
-		/* If we send a ACK we should reset our compressor */
-		if (ccp->debug & 0x10)
-			printk(KERN_DEBUG "Reset decompression state here!\n");
-
-		printk(KERN_DEBUG "ResetAck from daemon passed by\n");
-
-		if (!ccp->comp_stat)
-			break;
-
-		ccp->compressor->reset(ccp->comp_stat, 0, 0, NULL, 0, NULL);
-		ccp->compflags &= ~SC_COMP_DISCARD;	
-		break;
-	case CCP_RESETREQ:
-		/* Just let it pass by */
-		printk(KERN_DEBUG "ResetReq from daemon passed by\n");
-		break;
-	}
-}
-
-static LIST_HEAD(ipc_head);
-static spinlock_t ipc_head_lock = SPIN_LOCK_UNLOCKED;
-
-int
-ippp_ccp_set_compressor(struct ippp_ccp *ccp, int unit,
-			struct isdn_ppp_comp_data *data)
-{
-	struct isdn_ppp_compressor *ipc;
-	int ret;
-	void *stat;
-	int num = data->num;
-
-	if (ccp->debug & 0x10)
-		printk(KERN_DEBUG "[%d] Set %scompressor type %d\n", unit,
-		       data->flags & IPPP_COMP_FLAG_XMIT ? "" : "de", num);
-
-	spin_lock(&ipc_head_lock);
-	list_for_each_entry(ipc, &ipc_head, list) {
-		if (ipc->num == num &&
-		    try_module_get(ipc->owner))
-			goto found;
-	}
-	spin_unlock(&ipc_head_lock);
-	return -EINVAL;
-
- found:
-	spin_unlock(&ipc_head_lock);
-
-	stat = ipc->alloc(data);
-	if (!stat) {
-		printk(KERN_ERR "Can't alloc (de)compression!\n");
-		goto err;
-	}
-	ret = ipc->init(stat, data, unit, 0);
-	if(!ret) {
-		printk(KERN_ERR "Can't init (de)compression!\n");
-		ipc->free(stat);
-		goto err;
-	}
-	if (data->flags & IPPP_COMP_FLAG_XMIT) {
-		if (ccp->comp_stat) {
-			ccp->compressor->free(ccp->comp_stat);
-			module_put(ccp->compressor->owner);
-		}
-			ccp->comp_stat = stat;
-			ccp->compressor = ipc;
-	} else {
-		if (ccp->decomp_stat) {
-			ccp->decompressor->free(ccp->decomp_stat);
-			module_put(ccp->decompressor->owner);
-		}
-		ccp->decomp_stat = stat;
-		ccp->decompressor = ipc;
-	}
-	return 0;
-
- err:
-	module_put(ipc->owner);
-	return -EINVAL;
-}
-
-void
-ippp_ccp_get_compressors(unsigned long protos[8])
-{
-	struct isdn_ppp_compressor *ipc;
-	int i, j;
-
-	memset(protos, 0, sizeof(unsigned long) * 8);
-
-	spin_lock(&ipc_head_lock);
-	list_for_each_entry(ipc, &ipc_head, list) {
-		j = ipc->num / (sizeof(long)*8);
-		i = ipc->num % (sizeof(long)*8);
-		if (j < 8)
-			protos[j] |= 1 << i;
-	}
-	spin_unlock(&ipc_head_lock);
-}
-
-int
-isdn_ppp_register_compressor(struct isdn_ppp_compressor *ipc)
-{
-	spin_lock(&ipc_head_lock);
-	list_add_tail(&ipc->list, &ipc_head);
-	spin_unlock(&ipc_head_lock);
-
-	return 0;
-}
-
-int
-isdn_ppp_unregister_compressor(struct isdn_ppp_compressor *ipc)
-{
-	spin_lock(&ipc_head_lock);
-	list_del(&ipc->list);
-	spin_unlock(&ipc_head_lock);
-
-	return 0;
-}
-
--- diff/drivers/isdn/i4l/isdn_ppp_ccp.h	2002-11-11 11:09:36.000000000 +0000
+++ source/drivers/isdn/i4l/isdn_ppp_ccp.h	1970-01-01 01:00:00.000000000 +0100
@@ -1,75 +0,0 @@
-/* Linux ISDN subsystem, PPP CCP support
- *
- * Copyright 1994-1998  by Fritz Elfert (fritz@isdn4linux.de)
- *           1995,96    by Thinking Objects Software GmbH Wuerzburg
- *           1995,96    by Michael Hipp (Michael.Hipp@student.uni-tuebingen.de)
- *           1999-2002  by Kai Germaschewski <kai@germaschewski.name>
- *
- * This software may be used and distributed according to the terms
- * of the GNU General Public License, incorporated herein by reference.
- */
-
-#include <linux/kernel.h>
-#include <linux/isdn_ppp.h>
-
-/* for ippp_ccp::flags */
-
-#define SC_DECOMP_ON		0x01
-#define SC_COMP_ON		0x02
-#define SC_DECOMP_DISCARD	0x04
-#define SC_COMP_DISCARD		0x08
-
-/* SC_DC_ERROR/FERROR go in here as well, but are defined elsewhere
-
-   #define SC_DC_FERROR	0x00800000
-   #define SC_DC_ERROR	0x00400000
-*/
-
-struct ippp_ccp {
-	u16                         proto;
-	struct isdn_ppp_compressor *compressor;
-	struct isdn_ppp_compressor *decompressor;
-	void                       *comp_stat;
-	void                       *decomp_stat;
-	unsigned long               compflags;
-	struct ippp_ccp_reset      *reset;
-	int                         mru;
-	int                         debug;
-	void                       *priv;
-	void            (*xmit)(void *priv, struct sk_buff *skb, u16 proto);
-	void            (*kick_up)(void *priv);
-	struct sk_buff *(*alloc_skb)(void *priv, int len, int gfp_mask);
-};
-
-struct ippp_ccp *
-ippp_ccp_alloc(void);
-
-void
-ippp_ccp_free(struct ippp_ccp *ccp);
-
-int
-ippp_ccp_set_mru(struct ippp_ccp *ccp, unsigned int mru);
-
-unsigned int
-ippp_ccp_get_flags(struct ippp_ccp *ccp);
-
-struct sk_buff *
-ippp_ccp_compress(struct ippp_ccp *ccp, struct sk_buff *skb, u16 *proto);
-
-struct sk_buff *
-ippp_ccp_decompress(struct ippp_ccp *ccp, struct sk_buff *skb, u16 *proto);
-
-void
-ippp_ccp_send_ccp(struct ippp_ccp *ccp, struct sk_buff *skb);
-
-void
-ippp_ccp_receive_ccp(struct ippp_ccp *ccp, struct sk_buff *skb);
-
-void
-ippp_ccp_get_compressors(unsigned long protos[8]);
-
-int
-ippp_ccp_set_compressor(struct ippp_ccp *ccp, int unit,
-			struct isdn_ppp_comp_data *data);
-
-
--- diff/drivers/isdn/i4l/isdn_ppp_mp.c	2003-05-21 11:49:50.000000000 +0100
+++ source/drivers/isdn/i4l/isdn_ppp_mp.c	1970-01-01 01:00:00.000000000 +0100
@@ -1,353 +0,0 @@
-/* Linux ISDN subsystem, PPP CCP support
- *
- * Copyright 1994-1998  by Fritz Elfert (fritz@isdn4linux.de)
- *           1995,96    by Thinking Objects Software GmbH Wuerzburg
- *           1995,96    by Michael Hipp (Michael.Hipp@student.uni-tuebingen.de)
- *           1999-2002  by Kai Germaschewski <kai@germaschewski.name>
- *
- * This software may be used and distributed according to the terms
- * of the GNU General Public License, incorporated herein by reference.
- */
-
-#include "isdn_ppp_mp.h"
-#include "isdn_ppp_ccp.h"
-#include "isdn_common.h"
-#include "isdn_net_lib.h"
-#include "isdn_ppp.h"
-
-/* ====================================================================== */
-
-#define MP_END_FRAG             0x40
-#define MP_BEGIN_FRAG           0x80
-
-#define MP_MAX_QUEUE_LEN	16
-
-/* ====================================================================== */
-
-int
-ippp_mp_bind(isdn_net_dev *idev)
-{
-	struct ind_ppp *ind_ppp = idev->ind_priv;
-	struct inl_ppp *inl_ppp = idev->mlp->inl_priv;
-
-	/* seq no last seen, maybe set to bundle min, when joining? */
-	ind_ppp->mp_rxseq = 0;
-
-	if (!list_empty(&idev->mlp->online))
-		return 0;
-
-	/* first channel for this link, do some setup */
-
-	inl_ppp->mp_cfg   = 0;        /* MPPP configuration */
-	inl_ppp->mp_txseq = 0;        /* MPPP tx sequence number */
-	inl_ppp->mp_rxseq = (u32) -1;
-	skb_queue_head_init(&inl_ppp->mp_frags);
-
-	return 0;
-}
-
-int
-ippp_mp_bundle(isdn_net_dev *idev, int unit)
-{
-	isdn_net_local *lp = idev->mlp;
-	char ifn[IFNAMSIZ + 1];
-	isdn_net_dev *n_idev;
-	struct ind_ppp *ind_ppp;
-
-	printk(KERN_DEBUG "%s: %s: slave unit: %d\n",
-	       __FUNCTION__, idev->name, unit);
-
-	sprintf(ifn, "ippp%d", unit);
-	list_for_each_entry(n_idev, &lp->slaves, slaves) {
-		if (strcmp(n_idev->name, ifn) == 0)
-			goto found;
-	}
-	
-	printk(KERN_INFO "%s: cannot find %s\n", __FUNCTION__, ifn);
-	return -ENODEV;
-
- found:
-	ind_ppp = n_idev->ind_priv;
-	if (!ind_ppp->ipppd) {
-		printk(KERN_INFO "%s: no ipppd?\n", __FUNCTION__);
-		return -ENXIO;
-	}
-	ind_ppp->pppcfg |= SC_ENABLE_IP;
-	isdn_net_online(n_idev);
-
-	return 0;
-}
-  
-void
-ippp_mp_disconnected(isdn_net_dev *idev)
-{
-	struct inl_ppp *inl_ppp = idev->mlp->inl_priv;
-
-	if (!list_empty(&idev->mlp->online))
-		return;
-
-	/* we're the last link going down */
-	skb_queue_purge(&inl_ppp->mp_frags);
-}
-
-void
-ippp_mp_xmit(isdn_net_dev *idev, struct sk_buff *skb)
-{
-	struct ind_ppp *ind_ppp = idev->ind_priv;
-	struct inl_ppp *inl_ppp = idev->mlp->inl_priv;
-	unsigned char *p;
-	u32 txseq;
-	u16 proto;
-
-	if (!(inl_ppp->mp_cfg & SC_MP_PROT)) {
-		return ippp_xmit(idev, skb);
-	}
-
-	/* we could do something smarter than just sending
-	 * the complete packet as fragment... */
-
-	txseq = inl_ppp->mp_txseq++;
-	
-	if (inl_ppp->mp_cfg & SC_OUT_SHORT_SEQ) {
-		/* sequence number: 12bit */
-		p = skb_push(skb, 2);
-		p[0] = MP_BEGIN_FRAG | MP_END_FRAG | ((txseq >> 8) & 0xf);
-		p[1] = txseq & 0xff;
-	} else {
-		/* sequence number: 24bit */
-		p = skb_push(skb, 4);
-		p[0] = MP_BEGIN_FRAG | MP_END_FRAG;
-		p[1] = (txseq >> 16) & 0xff;
-		p[2] = (txseq >>  8) & 0xff;
-		p[3] = (txseq >>  0) & 0xff;
-	}
-	proto = PPP_MP;
-	skb = ippp_ccp_compress(ind_ppp->ccp, skb, &proto);
-	ippp_push_proto(ind_ppp, skb, proto);
-	ippp_xmit(idev, skb);
-}
-
-static void mp_receive(isdn_net_dev *idev, struct sk_buff *skb);
-
-void
-ippp_mp_receive(isdn_net_dev *idev, struct sk_buff *skb, u16 proto)
-{
-	struct ind_ppp *ind_ppp = idev->ind_priv;
-	struct inl_ppp *inl_ppp = idev->mlp->inl_priv;
-
- 	if (inl_ppp->mp_cfg & SC_REJ_MP_PROT)
-		goto out;
-
-	skb = ippp_ccp_decompress(ind_ppp->ccp, skb, &proto);
-	if (!skb)
-		goto drop;
-
-	if (proto == PPP_MP)
-		return mp_receive(idev, skb);
-
- out:
-	return ippp_receive(idev, skb, proto);
-
- drop:
-	idev->mlp->stats.rx_errors++;
-	kfree_skb(skb);
-}
-
-#define MP_LONGSEQ_MASK		0x00ffffff
-#define MP_SHORTSEQ_MASK	0x00000fff
-#define MP_LONGSEQ_MAX		MP_LONGSEQ_MASK
-#define MP_SHORTSEQ_MAX		MP_SHORTSEQ_MASK
-#define MP_LONGSEQ_MAXBIT	((MP_LONGSEQ_MASK+1)>>1)
-#define MP_SHORTSEQ_MAXBIT	((MP_SHORTSEQ_MASK+1)>>1)
-
-/* sequence-wrap safe comparisions (for long sequence)*/ 
-#define MP_LT(a,b)	((a-b)&MP_LONGSEQ_MAXBIT)
-#define MP_LE(a,b) 	!((b-a)&MP_LONGSEQ_MAXBIT)
-#define MP_GT(a,b) 	((b-a)&MP_LONGSEQ_MAXBIT)
-#define MP_GE(a,b)	!((a-b)&MP_LONGSEQ_MAXBIT)
-
-#define MP_SEQUENCE(skb) (skb)->priority
-#define MP_FLAGS(skb)    (skb)->cb[0]
-
-static u32
-get_seq(struct sk_buff *skb, u32 last_seq, int short_seq)
-{
-	u32 seq;
-	u16 shseq;
-	u8  flags;
-	int delta;
-   
-	get_u8(skb->data, &flags);
-   	if (short_seq) {
-		/* convert 12-bit short seq number to 24-bit long one */
-		get_u16(skb->data, &shseq);
-		delta = (shseq & MP_SHORTSEQ_MASK) - 
-			(last_seq & MP_SHORTSEQ_MASK);
-		/* check for seqence wrap */
-		if (delta < 0)
-			delta += MP_SHORTSEQ_MAX + 1;
-
-		seq = last_seq + delta;
-		skb_pull(skb, 2);
-	} else {
-		get_u32(skb->data, &seq);
-		skb_pull(skb, 4);
-	}
-	seq &= MP_LONGSEQ_MASK;
-	MP_SEQUENCE(skb) = seq;
-	MP_FLAGS(skb) = flags;
-	return seq;
-}
-
-static int
-mp_insert_frag(struct sk_buff_head *frags, struct sk_buff *skb)
-{
-	struct sk_buff *p;
-
-	/* If our queue of not yet reassembled fragments grows too
-	   large, throw away the oldest fragment */
-	if (skb_queue_len(frags) > MP_MAX_QUEUE_LEN)
-		kfree_skb(skb_dequeue(frags));
-	
-	for (p = frags->next; p != (struct sk_buff *) frags; p = p->next) {
-		if (MP_LE(MP_SEQUENCE(skb), MP_SEQUENCE(p)))
-			break;
-	}
-	/* duplicate ? */
-	if (MP_SEQUENCE(skb) == MP_SEQUENCE(p))
-		return -EBUSY;
-
-	__skb_insert(skb, p->prev, p, frags);
-	return 0;
-}
-
-struct sk_buff *
-mp_complete_seq(isdn_net_local *lp, struct sk_buff *b, struct sk_buff *e)
-{
-	struct sk_buff *p, *n, *skb;
-	int len = 0;
-
-	if (b->next == e) {
-		/* sequence with only one frag */
-		skb_unlink(b);
-		return b;
-	}
-	for (p = b, n = p->next; p != e; p = n, n = p->next ) {
-		len += p->len;
-	}
-	// FIXME check against mrru?
-	skb = dev_alloc_skb(len);
-	if (!skb)
-		lp->stats.rx_errors++;
-
-	for (p = b, n = p->next; p != e; p = n, n = p->next ) {
-		if (skb)
-			memcpy(skb_put(skb, p->len), p->data, p->len);
-		
-		skb_unlink(p);
-		kfree_skb(p);
-	}
-	return skb;
-}
-
-struct sk_buff *
-mp_reassemble(isdn_net_local *lp)
-{
-	struct inl_ppp *inl_ppp = lp->inl_priv;
-	struct sk_buff_head *frags = &inl_ppp->mp_frags;
-	struct sk_buff *p, *n, *pp, *start;
-	u32 min_seq = inl_ppp->mp_rxseq;
-	u32 next_seq = 0;
-
- again:
-	start = NULL;
-	for (p = frags->next, n = p->next; p != (struct sk_buff *) frags; p = n, n = p->next ) {
-		if (!start) {
-			if (MP_FLAGS(p) & MP_BEGIN_FRAG) {
-				start = p;
-				next_seq = MP_SEQUENCE(p);
-			} else {
-				/* start frag is missing */
-				goto frag_missing;
-			}
-		}
-		/* we've seen the first fragment of this series */
-		if (MP_SEQUENCE(p) != next_seq) {
-			/* previous frag is missing */
-			goto frag_missing;
-		}
-		if (MP_FLAGS(p) & MP_END_FRAG) {
-			/* we got a full sequence */
-			return mp_complete_seq(lp, start, p->next);
-		}
-		next_seq = MP_SEQUENCE(p) + 1;
-	}
-	return NULL;
-	
- frag_missing:
-	if (MP_SEQUENCE(p) - 1 > min_seq)
-		/* may come later */
-		return NULL;
-
-	/* for all fragments up to p */
-	p = p->next;
-	for (pp = frags->next, n = pp->next; pp != p; pp = n, n = pp->next ) {
-		skb_unlink(pp);
-		kfree_skb(pp);
-		lp->stats.rx_errors++;
-	}
-	goto again;
-
-}
-
-static void
-mp_receive(isdn_net_dev *idev, struct sk_buff *skb)
-{
-	isdn_net_local *lp = idev->mlp;
-	struct inl_ppp *inl_ppp = lp->inl_priv;
-	struct ind_ppp *ind_ppp = idev->ind_priv;
-	isdn_net_dev *qdev;
-	struct sk_buff_head *frags = &inl_ppp->mp_frags;
-	u32 seq;
-	u16 proto;
-
-	if (skb->len < (inl_ppp->mp_cfg & SC_IN_SHORT_SEQ ? 2 : 4))
-		goto drop;
-
-	seq = get_seq(skb, ind_ppp->mp_rxseq, inl_ppp->mp_cfg & SC_IN_SHORT_SEQ);
-	ind_ppp->mp_rxseq = seq;
-
-	if (inl_ppp->mp_rxseq == (u32) -1) { 
-		/* first packet */
-		inl_ppp->mp_rxseq = seq;
-	}
-	if (MP_LT(seq, inl_ppp->mp_rxseq)) {
-		goto drop;
-	}
-	/* Find the minimum sequence number received over all channels.
-	 * No fragments with numbers lower than this will arrive later. */
-	inl_ppp->mp_rxseq = seq;
-	list_for_each_entry(qdev, &lp->online, online) {
-		struct ind_ppp *ind_ppp = qdev->ind_priv;
-		if (MP_LT(ind_ppp->mp_rxseq, inl_ppp->mp_rxseq))
-			inl_ppp->mp_rxseq = ind_ppp->mp_rxseq;
-	}
-
-	/* Insert the skb into the list of received fragments, ordered by
-	 * sequence number */
-	if (mp_insert_frag(frags, skb))
-		goto drop;
-
-	while ((skb = mp_reassemble(lp))) {
-		if (isdn_ppp_strip_proto(skb, &proto)) {
-			kfree_skb(skb);
-			continue;
-		}
-		ippp_receive(idev, skb, proto);
-	}
-	return;
-	
- drop:
-	lp->stats.rx_errors++;
-	kfree_skb(skb);
-}
--- diff/drivers/isdn/i4l/isdn_ppp_mp.h	2003-05-21 11:49:50.000000000 +0100
+++ source/drivers/isdn/i4l/isdn_ppp_mp.h	1970-01-01 01:00:00.000000000 +0100
@@ -1,58 +0,0 @@
-/* Linux ISDN subsystem, PPP CCP support
- *
- * Copyright 1994-1998  by Fritz Elfert (fritz@isdn4linux.de)
- *           1995,96    by Thinking Objects Software GmbH Wuerzburg
- *           1995,96    by Michael Hipp (Michael.Hipp@student.uni-tuebingen.de)
- *           1999-2002  by Kai Germaschewski <kai@germaschewski.name>
- *
- * This software may be used and distributed according to the terms
- * of the GNU General Public License, incorporated herein by reference.
- */
-
-#ifndef __ISDN_PPP_MP_H__
-#define __ISDN_PPP_MP_H__
-
-#include "isdn_net_lib.h"
-
-#ifdef CONFIG_ISDN_MPP
-
-int  ippp_mp_bind(isdn_net_dev *idev);
-void ippp_mp_disconnected(isdn_net_dev *idev);
-int  ippp_mp_bundle(isdn_net_dev *idev, int val);
-void ippp_mp_xmit(isdn_net_dev *idev, struct sk_buff *skb);
-void ippp_mp_receive(isdn_net_dev *idev, struct sk_buff *skb, u16 proto);
-
-#else
-
-static inline int
-ippp_mp_bind(isdn_net_dev *idev)
-{
-	return 0;
-}
-
-static void
-ippp_mp_disconnected(isdn_net_dev *idev)
-{
-}
-
-static inline int
-ippp_mp_bundle(isdn_net_dev *idev, int val)
-{
-	return -EINVAL;
-}
-
-static inline void
-ippp_mp_xmit(isdn_net_dev *idev, struct sk_buff *skb)
-{
-	ippp_xmit(idev, skb);
-}
-
-static inline void 
-ippp_mp_receive(isdn_net_dev *idev, struct sk_buff *skb, u16 proto)
-{
-	ippp_receive(idev, skb, proto);
-}
-
-#endif
-
-#endif
--- diff/drivers/isdn/i4l/isdn_ppp_vj.c	2002-11-11 11:09:36.000000000 +0000
+++ source/drivers/isdn/i4l/isdn_ppp_vj.c	1970-01-01 01:00:00.000000000 +0100
@@ -1,128 +0,0 @@
-/* Linux ISDN subsystem, PPP VJ header compression
- *
- * Copyright 1995,96    by Michael Hipp (Michael.Hipp@student.uni-tuebingen.de)
- *           1999-2002  by Kai Germaschewski <kai@germaschewski.name>
- *
- * This software may be used and distributed according to the terms
- * of the GNU General Public License, incorporated herein by reference.
- */
-
-#include "isdn_ppp_vj.h"
-#include "isdn_common.h"
-#include "isdn_net_lib.h"
-#include "isdn_ppp.h"
-
-struct slcompress *
-ippp_vj_alloc(void)
-{
-	return slhc_init(16, 16);
-}
-
-void
-ippp_vj_free(struct slcompress *slcomp)
-{
-	slhc_free(slcomp);
-}
-
-int
-ippp_vj_set_maxcid(isdn_net_dev *idev, int val)
-{
-	struct inl_ppp *inl_ppp = idev->mlp->inl_priv;
-	struct slcompress *sltmp;
-
-	sltmp = slhc_init(16, val + 1);
-	if (!sltmp)
-		return -ENOMEM;
-
-	if (inl_ppp->slcomp)
-		slhc_free(inl_ppp->slcomp);
-
-	inl_ppp->slcomp = sltmp;
-	return 0;
-}
-
-void
-ippp_vj_decompress(isdn_net_dev *idev, struct sk_buff *skb_old, u16 proto)
-{
-	struct inl_ppp *inl_ppp = idev->mlp->inl_priv;
-	struct slcompress *slcomp = inl_ppp->slcomp;
-	struct sk_buff *skb;
-	int len;
-
-	switch (proto) {
-	case PPP_VJC_UNCOMP:
-		if (slhc_remember(slcomp, skb_old->data, skb_old->len) <= 0)
-			goto drop;
-		
-		skb = skb_old;
-		break;
-	case PPP_VJC_COMP:
-		skb = dev_alloc_skb(skb_old->len + 128);
-		if (!skb)
-			goto drop;
-
-		memcpy(skb->data, skb_old->data, skb_old->len);
-		len = slhc_uncompress(slcomp, skb->data, skb_old->len);
-		if (len < 0)
-			goto drop_both;
-
-		skb_put(skb, len);
-		kfree_skb(skb_old);
-		break;
-	default:
-		isdn_BUG();
-		goto drop;
-	}
-	isdn_netif_rx(idev, skb, htons(ETH_P_IP));
-	return;
-
- drop_both:
-	kfree_skb(skb);
- drop:
-	kfree_skb(skb_old);
-	idev->mlp->stats.rx_dropped++;
-}
-
-struct sk_buff *
-ippp_vj_compress(isdn_net_dev *idev, struct sk_buff *skb_old, u16 *proto)
-{
-	struct inl_ppp *inl_ppp = idev->mlp->inl_priv;
-	struct ind_ppp *ind_ppp = idev->ind_priv;
-	struct slcompress *slcomp = inl_ppp->slcomp;
-	struct sk_buff *skb;
-	unsigned char *buf;
-	int len;
-
-	if (!(ind_ppp->pppcfg & SC_COMP_TCP) || *proto != PPP_IP)
-		return skb_old;
-
-	skb = isdn_ppp_dev_alloc_skb(idev, skb_old->len, GFP_ATOMIC);
-	if (!skb)
-		return skb_old;
-
-	skb_put(skb, skb_old->len);
-	buf = skb_old->data;
-	// FIXME flag should be per bundle
-	len = slhc_compress(slcomp, skb_old->data, skb_old->len, skb->data,
-			    &buf, !(ind_ppp->pppcfg & SC_NO_TCP_CCID)); 
-
-	if (buf == skb_old->data) {
-		kfree_skb(skb);
-		skb = skb_old;
-	} else {
-		kfree_skb(skb_old);
-	}
-	skb_trim(skb, len);
-			
-	/* cslip style -> PPP */
-	if ((skb->data[0] & SL_TYPE_COMPRESSED_TCP) == SL_TYPE_COMPRESSED_TCP) {
-		skb->data[0] &= ~SL_TYPE_COMPRESSED_TCP;
-		*proto = PPP_VJC_COMP;
-	} else if ((skb->data[0] & SL_TYPE_UNCOMPRESSED_TCP) == SL_TYPE_UNCOMPRESSED_TCP) {
-		skb->data[0] &= ~SL_TYPE_UNCOMPRESSED_TCP;
-		skb->data[0] |= SL_TYPE_IP;
-		*proto = PPP_VJC_UNCOMP;
-	}
-	return skb;
-}
-
--- diff/drivers/isdn/i4l/isdn_ppp_vj.h	2002-11-11 11:09:36.000000000 +0000
+++ source/drivers/isdn/i4l/isdn_ppp_vj.h	1970-01-01 01:00:00.000000000 +0100
@@ -1,61 +0,0 @@
-/* Linux ISDN subsystem, PPP VJ header compression
- *
- * Copyright 1995,96    by Michael Hipp (Michael.Hipp@student.uni-tuebingen.de)
- *           1999-2002  by Kai Germaschewski <kai@germaschewski.name>
- *
- * This software may be used and distributed according to the terms
- * of the GNU General Public License, incorporated herein by reference.
- */
-
-#ifndef __ISDN_PPP_VJ_H__
-#define __ISDN_PPP_VJ_H__
-
-#include "isdn_net_lib.h"
-
-#ifdef CONFIG_ISDN_PPP_VJ
-
-
-struct slcompress *
-ippp_vj_alloc(void);
-
-void
-ippp_vj_free(struct slcompress *slcomp);
-
-int
-ippp_vj_set_maxcid(isdn_net_dev *idev, int val);
-
-void
-ippp_vj_decompress(isdn_net_dev *idev, struct sk_buff *skb_old, u16 proto);
-
-struct sk_buff *
-ippp_vj_compress(isdn_net_dev *idev, struct sk_buff *skb_old, u16 *proto);
-
-
-#else
-
-
-static inline struct slcompress *
-ippp_vj_alloc(void)
-{ return (struct slcompress *) !NULL; }
-
-static inline void
-ippp_vj_free(struct slcompress *slcomp) 
-{ }
-
-static inline int
-ippp_vj_set_maxcid(isdn_net_dev *idev, int val)
-{ return -EINVAL; }
-
-static inline struct sk_buff *
-ippp_vj_decompress(struct slcompress *slcomp, struct sk_buff *skb_old, 
-		   u16 proto)
-{ return skb_old; }
-
-static inline struct sk_buff *
-ippp_vj_compress(isdn_net_dev *idev, struct sk_buff *skb_old, u16 *proto)
-{ return skb_old; }
-
-
-#endif
-
-#endif
--- diff/drivers/md/dm-ioctl-v1.c	2004-01-19 10:22:56.000000000 +0000
+++ source/drivers/md/dm-ioctl-v1.c	1970-01-01 01:00:00.000000000 +0100
@@ -1,1159 +0,0 @@
-/*
- * Copyright (C) 2001, 2002 Sistina Software (UK) Limited.
- *
- * This file is released under the GPL.
- */
-
-#include "dm.h"
-
-#include <linux/module.h>
-#include <linux/vmalloc.h>
-#include <linux/miscdevice.h>
-#include <linux/dm-ioctl.h>
-#include <linux/init.h>
-#include <linux/wait.h>
-#include <linux/slab.h>
-#include <linux/devfs_fs_kernel.h>
-
-#include <asm/uaccess.h>
-
-#define DM_DRIVER_EMAIL "dm@uk.sistina.com"
-
-/*-----------------------------------------------------------------
- * The ioctl interface needs to be able to look up devices by
- * name or uuid.
- *---------------------------------------------------------------*/
-struct hash_cell {
-	struct list_head name_list;
-	struct list_head uuid_list;
-
-	char *name;
-	char *uuid;
-	struct mapped_device *md;
-};
-
-#define NUM_BUCKETS 64
-#define MASK_BUCKETS (NUM_BUCKETS - 1)
-static struct list_head _name_buckets[NUM_BUCKETS];
-static struct list_head _uuid_buckets[NUM_BUCKETS];
-
-void dm_hash_remove_all(void);
-
-/*
- * Guards access to all three tables.
- */
-static DECLARE_RWSEM(_hash_lock);
-
-static void init_buckets(struct list_head *buckets)
-{
-	unsigned int i;
-
-	for (i = 0; i < NUM_BUCKETS; i++)
-		INIT_LIST_HEAD(buckets + i);
-}
-
-int dm_hash_init(void)
-{
-	init_buckets(_name_buckets);
-	init_buckets(_uuid_buckets);
-	devfs_mk_dir(DM_DIR);
-	return 0;
-}
-
-void dm_hash_exit(void)
-{
-	dm_hash_remove_all();
-	devfs_remove(DM_DIR);
-}
-
-/*-----------------------------------------------------------------
- * Hash function:
- * We're not really concerned with the str hash function being
- * fast since it's only used by the ioctl interface.
- *---------------------------------------------------------------*/
-static unsigned int hash_str(const char *str)
-{
-	const unsigned int hash_mult = 2654435387U;
-	unsigned int h = 0;
-
-	while (*str)
-		h = (h + (unsigned int) *str++) * hash_mult;
-
-	return h & MASK_BUCKETS;
-}
-
-/*-----------------------------------------------------------------
- * Code for looking up a device by name
- *---------------------------------------------------------------*/
-static struct hash_cell *__get_name_cell(const char *str)
-{
-	struct list_head *tmp;
-	struct hash_cell *hc;
-	unsigned int h = hash_str(str);
-
-	list_for_each (tmp, _name_buckets + h) {
-		hc = list_entry(tmp, struct hash_cell, name_list);
-		if (!strcmp(hc->name, str))
-			return hc;
-	}
-
-	return NULL;
-}
-
-static struct hash_cell *__get_uuid_cell(const char *str)
-{
-	struct list_head *tmp;
-	struct hash_cell *hc;
-	unsigned int h = hash_str(str);
-
-	list_for_each (tmp, _uuid_buckets + h) {
-		hc = list_entry(tmp, struct hash_cell, uuid_list);
-		if (!strcmp(hc->uuid, str))
-			return hc;
-	}
-
-	return NULL;
-}
-
-/*-----------------------------------------------------------------
- * Inserting, removing and renaming a device.
- *---------------------------------------------------------------*/
-static inline char *kstrdup(const char *str)
-{
-	char *r = kmalloc(strlen(str) + 1, GFP_KERNEL);
-	if (r)
-		strcpy(r, str);
-	return r;
-}
-
-static struct hash_cell *alloc_cell(const char *name, const char *uuid,
-				    struct mapped_device *md)
-{
-	struct hash_cell *hc;
-
-	hc = kmalloc(sizeof(*hc), GFP_KERNEL);
-	if (!hc)
-		return NULL;
-
-	hc->name = kstrdup(name);
-	if (!hc->name) {
-		kfree(hc);
-		return NULL;
-	}
-
-	if (!uuid)
-		hc->uuid = NULL;
-
-	else {
-		hc->uuid = kstrdup(uuid);
-		if (!hc->uuid) {
-			kfree(hc->name);
-			kfree(hc);
-			return NULL;
-		}
-	}
-
-	INIT_LIST_HEAD(&hc->name_list);
-	INIT_LIST_HEAD(&hc->uuid_list);
-	hc->md = md;
-	return hc;
-}
-
-static void free_cell(struct hash_cell *hc)
-{
-	if (hc) {
-		kfree(hc->name);
-		kfree(hc->uuid);
-		kfree(hc);
-	}
-}
-
-/*
- * devfs stuff.
- */
-static int register_with_devfs(struct hash_cell *hc)
-{
-	struct gendisk *disk = dm_disk(hc->md);
-
-	devfs_mk_bdev(MKDEV(disk->major, disk->first_minor),
-		       S_IFBLK | S_IRUSR | S_IWUSR | S_IRGRP,
-		       DM_DIR "/%s", hc->name);
-	return 0;
-}
-
-static int unregister_with_devfs(struct hash_cell *hc)
-{
-	devfs_remove(DM_DIR"/%s", hc->name);
-	return 0;
-}
-
-/*
- * The kdev_t and uuid of a device can never change once it is
- * initially inserted.
- */
-int dm_hash_insert(const char *name, const char *uuid, struct mapped_device *md)
-{
-	struct hash_cell *cell;
-
-	/*
-	 * Allocate the new cells.
-	 */
-	cell = alloc_cell(name, uuid, md);
-	if (!cell)
-		return -ENOMEM;
-
-	/*
-	 * Insert the cell into all three hash tables.
-	 */
-	down_write(&_hash_lock);
-	if (__get_name_cell(name))
-		goto bad;
-
-	list_add(&cell->name_list, _name_buckets + hash_str(name));
-
-	if (uuid) {
-		if (__get_uuid_cell(uuid)) {
-			list_del(&cell->name_list);
-			goto bad;
-		}
-		list_add(&cell->uuid_list, _uuid_buckets + hash_str(uuid));
-	}
-	register_with_devfs(cell);
-	dm_get(md);
-	up_write(&_hash_lock);
-
-	return 0;
-
- bad:
-	up_write(&_hash_lock);
-	free_cell(cell);
-	return -EBUSY;
-}
-
-void __hash_remove(struct hash_cell *hc)
-{
-	/* remove from the dev hash */
-	list_del(&hc->uuid_list);
-	list_del(&hc->name_list);
-	unregister_with_devfs(hc);
-	dm_put(hc->md);
-	free_cell(hc);
-}
-
-void dm_hash_remove_all(void)
-{
-	int i;
-	struct hash_cell *hc;
-	struct list_head *tmp, *n;
-
-	down_write(&_hash_lock);
-	for (i = 0; i < NUM_BUCKETS; i++) {
-		list_for_each_safe (tmp, n, _name_buckets + i) {
-			hc = list_entry(tmp, struct hash_cell, name_list);
-			__hash_remove(hc);
-		}
-	}
-	up_write(&_hash_lock);
-}
-
-int dm_hash_rename(const char *old, const char *new)
-{
-	char *new_name, *old_name;
-	struct hash_cell *hc;
-
-	/*
-	 * duplicate new.
-	 */
-	new_name = kstrdup(new);
-	if (!new_name)
-		return -ENOMEM;
-
-	down_write(&_hash_lock);
-
-	/*
-	 * Is new free ?
-	 */
-	hc = __get_name_cell(new);
-	if (hc) {
-		DMWARN("asked to rename to an already existing name %s -> %s",
-		       old, new);
-		up_write(&_hash_lock);
-		kfree(new_name);
-		return -EBUSY;
-	}
-
-	/*
-	 * Is there such a device as 'old' ?
-	 */
-	hc = __get_name_cell(old);
-	if (!hc) {
-		DMWARN("asked to rename a non existent device %s -> %s",
-		       old, new);
-		up_write(&_hash_lock);
-		kfree(new_name);
-		return -ENXIO;
-	}
-
-	/*
-	 * rename and move the name cell.
-	 */
-	unregister_with_devfs(hc);
-
-	list_del(&hc->name_list);
-	old_name = hc->name;
-	hc->name = new_name;
-	list_add(&hc->name_list, _name_buckets + hash_str(new_name));
-
-	/* rename the device node in devfs */
-	register_with_devfs(hc);
-
-	up_write(&_hash_lock);
-	kfree(old_name);
-	return 0;
-}
-
-
-/*-----------------------------------------------------------------
- * Implementation of the ioctl commands
- *---------------------------------------------------------------*/
-
-/*
- * All the ioctl commands get dispatched to functions with this
- * prototype.
- */
-typedef int (*ioctl_fn)(struct dm_ioctl *param, struct dm_ioctl *user);
-
-/*
- * Check a string doesn't overrun the chunk of
- * memory we copied from userland.
- */
-static int valid_str(char *str, void *begin, void *end)
-{
-	while (((void *) str >= begin) && ((void *) str < end))
-		if (!*str++)
-			return 0;
-
-	return -EINVAL;
-}
-
-static int next_target(struct dm_target_spec *last, uint32_t next,
-		       void *begin, void *end,
-		       struct dm_target_spec **spec, char **params)
-{
-	*spec = (struct dm_target_spec *)
-	    ((unsigned char *) last + next);
-	*params = (char *) (*spec + 1);
-
-	if (*spec < (last + 1) || ((void *) *spec > end))
-		return -EINVAL;
-
-	return valid_str(*params, begin, end);
-}
-
-static int populate_table(struct dm_table *table, struct dm_ioctl *args)
-{
-	int r, first = 1;
-	unsigned int i = 0;
-	struct dm_target_spec *spec;
-	char *params;
-	void *begin, *end;
-
-	if (!args->target_count) {
-		DMWARN("populate_table: no targets specified");
-		return -EINVAL;
-	}
-
-	begin = (void *) args;
-	end = begin + args->data_size;
-
-	for (i = 0; i < args->target_count; i++) {
-
-		if (first)
-			r = next_target((struct dm_target_spec *) args,
-					args->data_start,
-					begin, end, &spec, &params);
-		else
-			r = next_target(spec, spec->next, begin, end,
-					&spec, &params);
-
-		if (r) {
-			DMWARN("unable to find target");
-			return -EINVAL;
-		}
-
-		r = dm_table_add_target(table, spec->target_type,
-					(sector_t) spec->sector_start,
-					(sector_t) spec->length,
-					params);
-		if (r) {
-			DMWARN("internal error adding target to table");
-			return -EINVAL;
-		}
-
-		first = 0;
-	}
-
-	return dm_table_complete(table);
-}
-
-/*
- * Round up the ptr to the next 'align' boundary.  Obviously
- * 'align' must be a power of 2.
- */
-static inline void *align_ptr(void *ptr, unsigned int align)
-{
-	align--;
-	return (void *) (((unsigned long) (ptr + align)) & ~align);
-}
-
-/*
- * Copies a dm_ioctl and an optional additional payload to
- * userland.
- */
-static int results_to_user(struct dm_ioctl *user, struct dm_ioctl *param,
-			   void *data, uint32_t len)
-{
-	int r;
-	void *ptr = NULL;
-
-	if (data) {
-		ptr = align_ptr(user + 1, sizeof(unsigned long));
-		param->data_start = ptr - (void *) user;
-	}
-
-	/*
-	 * The version number has already been filled in, so we
-	 * just copy later fields.
-	 */
-	r = copy_to_user(&user->data_size, &param->data_size,
-			 sizeof(*param) - sizeof(param->version));
-	if (r)
-		return -EFAULT;
-
-	if (data) {
-		if (param->data_start + len > param->data_size)
-			return -ENOSPC;
-
-		if (copy_to_user(ptr, data, len))
-			r = -EFAULT;
-	}
-
-	return r;
-}
-
-/*
- * Fills in a dm_ioctl structure, ready for sending back to
- * userland.
- */
-static int __info(struct mapped_device *md, struct dm_ioctl *param)
-{
-	struct dm_table *table;
-	struct block_device *bdev;
-	struct gendisk *disk = dm_disk(md);
-
-	param->flags = DM_EXISTS_FLAG;
-	if (dm_suspended(md))
-		param->flags |= DM_SUSPEND_FLAG;
-
-	bdev = bdget_disk(disk, 0);
-	if (!bdev)
-		return -ENXIO;
-
-	param->dev = old_encode_dev(bdev->bd_dev);
-	param->open_count = bdev->bd_openers;
-	bdput(bdev);
-
-	if (disk->policy)
-		param->flags |= DM_READONLY_FLAG;
-
-	table = dm_get_table(md);
-	param->target_count = dm_table_get_num_targets(table);
-	dm_table_put(table);
-
-	return 0;
-}
-
-/*
- * Always use UUID for lookups if it's present, otherwise use name.
- */
-static inline struct mapped_device *find_device(struct dm_ioctl *param)
-{
-	struct hash_cell *hc;
-	struct mapped_device *md = NULL;
-
-	down_read(&_hash_lock);
-	hc = *param->uuid ? __get_uuid_cell(param->uuid) :
-		__get_name_cell(param->name);
-	if (hc) {
-		md = hc->md;
-
-		/*
-		 * Sneakily write in both the name and the uuid
-		 * while we have the cell.
-		 */
-		strlcpy(param->name, hc->name, sizeof(param->name));
-		if (hc->uuid)
-			strlcpy(param->uuid, hc->uuid, sizeof(param->uuid));
-		else
-			param->uuid[0] = '\0';
-
-		dm_get(md);
-	}
-	up_read(&_hash_lock);
-
-	return md;
-}
-
-#define ALIGNMENT sizeof(int)
-static void *_align(void *ptr, unsigned int a)
-{
-	register unsigned long align = --a;
-
-	return (void *) (((unsigned long) ptr + align) & ~align);
-}
-
-/*
- * Copies device info back to user space, used by
- * the create and info ioctls.
- */
-static int info(struct dm_ioctl *param, struct dm_ioctl *user)
-{
-	struct mapped_device *md;
-
-	param->flags = 0;
-
-	md = find_device(param);
-	if (!md)
-		/*
-		 * Device not found - returns cleared exists flag.
-		 */
-		goto out;
-
-	__info(md, param);
-	dm_put(md);
-
-      out:
-	return results_to_user(user, param, NULL, 0);
-}
-
-static inline int get_mode(struct dm_ioctl *param)
-{
-	int mode = FMODE_READ | FMODE_WRITE;
-
-	if (param->flags & DM_READONLY_FLAG)
-		mode = FMODE_READ;
-
-	return mode;
-}
-
-static int check_name(const char *name)
-{
-	if (name[0] == '/') {
-		DMWARN("invalid device name");
-		return -EINVAL;
-	}
-
-	return 0;
-}
-
-static int create(struct dm_ioctl *param, struct dm_ioctl *user)
-{
-	int r;
-	struct dm_table *t;
-	struct mapped_device *md;
-
-	r = check_name(param->name);
-	if (r)
-		return r;
-
-	r = dm_table_create(&t, get_mode(param), param->target_count);
-	if (r)
-		return r;
-
-	r = populate_table(t, param);
-	if (r) {
-		dm_table_put(t);
-		return r;
-	}
-
-	if (param->flags & DM_PERSISTENT_DEV_FLAG)
-		r = dm_create_with_minor(MINOR(old_decode_dev(param->dev)), &md);
-	else
-		r = dm_create(&md);
-
-	if (r) {
-		dm_table_put(t);
-		return r;
-	}
-
-	/* suspend the device */
-	r = dm_suspend(md);
-	if (r) {
-		DMWARN("suspend failed");
-		dm_table_put(t);
-		dm_put(md);
-		return r;
-	}
-	/* swap in the table */
-	r = dm_swap_table(md, t);
-	if (r) {
-		DMWARN("table swap failed");
-		dm_table_put(t);
-		dm_put(md);
-		return r;
-	}
-
-	/* resume the device */
-	r = dm_resume(md);
-	if (r) {
-		DMWARN("resume failed");
-		dm_table_put(t);
-		dm_put(md);
-		return r;
-	}
-
-	dm_table_put(t);	/* md will have grabbed its own reference */
-
-	set_disk_ro(dm_disk(md), (param->flags & DM_READONLY_FLAG) ? 1 : 0);
-	r = dm_hash_insert(param->name, *param->uuid ? param->uuid : NULL, md);
-	dm_put(md);
-
-	return r ? r : info(param, user);
-}
-
-/*
- * Build up the status struct for each target
- */
-static int __status(struct mapped_device *md, struct dm_ioctl *param,
-		    char *outbuf, size_t *len)
-{
-	unsigned int i, num_targets;
-	struct dm_target_spec *spec;
-	char *outptr;
-	status_type_t type;
-	struct dm_table *table = dm_get_table(md);
-
-	if (param->flags & DM_STATUS_TABLE_FLAG)
-		type = STATUSTYPE_TABLE;
-	else
-		type = STATUSTYPE_INFO;
-
-	outptr = outbuf;
-
-	/* Get all the target info */
-	num_targets = dm_table_get_num_targets(table);
-	for (i = 0; i < num_targets; i++) {
-		struct dm_target *ti = dm_table_get_target(table, i);
-
-		if (outptr - outbuf +
-		    sizeof(struct dm_target_spec) > param->data_size) {
-			dm_table_put(table);
-			return -ENOMEM;
-		}
-
-		spec = (struct dm_target_spec *) outptr;
-
-		spec->status = 0;
-		spec->sector_start = ti->begin;
-		spec->length = ti->len;
-		strlcpy(spec->target_type, ti->type->name,
-			sizeof(spec->target_type));
-
-		outptr += sizeof(struct dm_target_spec);
-
-		/* Get the status/table string from the target driver */
-		if (ti->type->status)
-			ti->type->status(ti, type, outptr,
-					 outbuf + param->data_size - outptr);
-		else
-			outptr[0] = '\0';
-
-		outptr += strlen(outptr) + 1;
-		_align(outptr, ALIGNMENT);
-		spec->next = outptr - outbuf;
-	}
-
-	param->target_count = num_targets;
-	*len = outptr - outbuf;
-	dm_table_put(table);
-
-	return 0;
-}
-
-/*
- * Return the status of a device as a text string for each
- * target.
- */
-static int get_status(struct dm_ioctl *param, struct dm_ioctl *user)
-{
-	struct mapped_device *md;
-	size_t len = 0;
-	int ret;
-	char *outbuf = NULL;
-
-	md = find_device(param);
-	if (!md)
-		/*
-		 * Device not found - returns cleared exists flag.
-		 */
-		goto out;
-
-	/* We haven't a clue how long the resultant data will be so
-	   just allocate as much as userland has allowed us and make sure
-	   we don't overun it */
-	outbuf = kmalloc(param->data_size, GFP_KERNEL);
-	if (!outbuf)
-		goto out;
-	/*
-	 * Get the status of all targets
-	 */
-	__status(md, param, outbuf, &len);
-
-	/*
-	 * Setup the basic dm_ioctl structure.
-	 */
-	__info(md, param);
-
-      out:
-	if (md)
-		dm_put(md);
-
-	ret = results_to_user(user, param, outbuf, len);
-
-	if (outbuf)
-		kfree(outbuf);
-
-	return ret;
-}
-
-/*
- * Wait for a device to report an event
- */
-static int wait_device_event(struct dm_ioctl *param, struct dm_ioctl *user)
-{
-	struct mapped_device *md;
-	DECLARE_WAITQUEUE(wq, current);
-
-	md = find_device(param);
-	if (!md)
-		/*
-		 * Device not found - returns cleared exists flag.
-		 */
-		goto out;
-
-	/*
-	 * Setup the basic dm_ioctl structure.
-	 */
-	__info(md, param);
-
-	/*
-	 * Wait for a notification event
-	 */
-	set_current_state(TASK_INTERRUPTIBLE);
- 	if (!dm_add_wait_queue(md, &wq, dm_get_event_nr(md))) {
- 		schedule();
- 		dm_remove_wait_queue(md, &wq);
- 	}
-  	set_current_state(TASK_RUNNING);
- 	dm_put(md);
-
-      out:
-	return results_to_user(user, param, NULL, 0);
-}
-
-/*
- * Retrieves a list of devices used by a particular dm device.
- */
-static int dep(struct dm_ioctl *param, struct dm_ioctl *user)
-{
-	int r;
-	unsigned int count;
-	struct mapped_device *md;
-	struct list_head *tmp;
-	size_t len = 0;
-	struct dm_target_deps *deps = NULL;
-	struct dm_table *table;
-
-	md = find_device(param);
-	if (!md)
-		goto out;
-	table = dm_get_table(md);
-
-	/*
-	 * Setup the basic dm_ioctl structure.
-	 */
-	__info(md, param);
-
-	/*
-	 * Count the devices.
-	 */
-	count = 0;
-	list_for_each(tmp, dm_table_get_devices(table))
-	    count++;
-
-	/*
-	 * Allocate a kernel space version of the dm_target_status
-	 * struct.
-	 */
-	if (array_too_big(sizeof(*deps), sizeof(*deps->dev), count)) {
-		dm_table_put(table);
-		dm_put(md);
-		return -ENOMEM;
-	}
-
-	len = sizeof(*deps) + (sizeof(*deps->dev) * count);
-	deps = kmalloc(len, GFP_KERNEL);
-	if (!deps) {
-		dm_table_put(table);
-		dm_put(md);
-		return -ENOMEM;
-	}
-
-	/*
-	 * Fill in the devices.
-	 */
-	deps->count = count;
-	count = 0;
-	list_for_each(tmp, dm_table_get_devices(table)) {
-		struct dm_dev *dd = list_entry(tmp, struct dm_dev, list);
-		deps->dev[count++] = old_encode_dev(dd->bdev->bd_dev);
-	}
-	dm_table_put(table);
-	dm_put(md);
-
-      out:
-	r = results_to_user(user, param, deps, len);
-
-	kfree(deps);
-	return r;
-}
-
-static int remove(struct dm_ioctl *param, struct dm_ioctl *user)
-{
-	struct hash_cell *hc;
-
-	down_write(&_hash_lock);
-	hc = *param->uuid ? __get_uuid_cell(param->uuid) :
-		__get_name_cell(param->name);
-	if (!hc) {
-		DMWARN("device doesn't appear to be in the dev hash table.");
-		up_write(&_hash_lock);
-		return -EINVAL;
-	}
-
-	/*
-	 * You may ask the interface to drop its reference to an
-	 * in use device.  This is no different to unlinking a
-	 * file that someone still has open.  The device will not
-	 * actually be destroyed until the last opener closes it.
-	 * The name and uuid of the device (both are interface
-	 * properties) will be available for reuse immediately.
-	 *
-	 * You don't want to drop a _suspended_ device from the
-	 * interface, since that will leave you with no way of
-	 * resuming it.
-	 */
-	if (dm_suspended(hc->md)) {
-		DMWARN("refusing to remove a suspended device.");
-		up_write(&_hash_lock);
-		return -EPERM;
-	}
-
-	__hash_remove(hc);
-	up_write(&_hash_lock);
-	return 0;
-}
-
-static int remove_all(struct dm_ioctl *param, struct dm_ioctl *user)
-{
-	dm_hash_remove_all();
-	return 0;
-}
-
-static int suspend(struct dm_ioctl *param, struct dm_ioctl *user)
-{
-	int r;
-	struct mapped_device *md;
-
-	md = find_device(param);
-	if (!md)
-		return -ENXIO;
-
-	if (param->flags & DM_SUSPEND_FLAG)
-		r = dm_suspend(md);
-	else
-		r = dm_resume(md);
-
-	dm_put(md);
-	return r;
-}
-
-static int reload(struct dm_ioctl *param, struct dm_ioctl *user)
-{
-	int r;
-	struct mapped_device *md;
-	struct dm_table *t;
-
-	r = dm_table_create(&t, get_mode(param), param->target_count);
-	if (r)
-		return r;
-
-	r = populate_table(t, param);
-	if (r) {
-		dm_table_put(t);
-		return r;
-	}
-
-	md = find_device(param);
-	if (!md) {
-		dm_table_put(t);
-		return -ENXIO;
-	}
-
-	r = dm_swap_table(md, t);
-	if (r) {
-		dm_put(md);
-		dm_table_put(t);
-		return r;
-	}
-	dm_table_put(t);	/* md will have taken its own reference */
-
-	set_disk_ro(dm_disk(md), (param->flags & DM_READONLY_FLAG) ? 1 : 0);
-	dm_put(md);
-
-	r = info(param, user);
-	return r;
-}
-
-static int rename(struct dm_ioctl *param, struct dm_ioctl *user)
-{
-	int r;
-	char *new_name = (char *) param + param->data_start;
-
-	if (valid_str(new_name, (void *) param,
-		      (void *) param + param->data_size)) {
-		DMWARN("Invalid new logical volume name supplied.");
-		return -EINVAL;
-	}
-
-	r = check_name(new_name);
-	if (r)
-		return r;
-
-	return dm_hash_rename(param->name, new_name);
-}
-
-
-/*-----------------------------------------------------------------
- * Implementation of open/close/ioctl on the special char
- * device.
- *---------------------------------------------------------------*/
-static ioctl_fn lookup_ioctl(unsigned int cmd)
-{
-	static struct {
-		int cmd;
-		ioctl_fn fn;
-	} _ioctls[] = {
-		{DM_VERSION_CMD, NULL},	/* version is dealt with elsewhere */
-		{DM_REMOVE_ALL_CMD, remove_all},
-		{DM_DEV_CREATE_CMD, create},
-		{DM_DEV_REMOVE_CMD, remove},
-		{DM_DEV_RELOAD_CMD, reload},
-		{DM_DEV_RENAME_CMD, rename},
-		{DM_DEV_SUSPEND_CMD, suspend},
-		{DM_DEV_DEPS_CMD, dep},
-		{DM_DEV_STATUS_CMD, info},
-		{DM_TARGET_STATUS_CMD, get_status},
-		{DM_TARGET_WAIT_CMD, wait_device_event},
-	};
-
-	return (cmd >= ARRAY_SIZE(_ioctls)) ? NULL : _ioctls[cmd].fn;
-}
-
-/*
- * As well as checking the version compatibility this always
- * copies the kernel interface version out.
- */
-static int check_version(unsigned int cmd, struct dm_ioctl *user)
-{
-	uint32_t version[3];
-	int r = 0;
-
-	if (copy_from_user(version, user->version, sizeof(version)))
-		return -EFAULT;
-
-	if ((DM_VERSION_MAJOR != version[0]) ||
-	    (DM_VERSION_MINOR < version[1])) {
-		DMWARN("ioctl interface mismatch: "
-		       "kernel(%u.%u.%u), user(%u.%u.%u), cmd(%d)",
-		       DM_VERSION_MAJOR, DM_VERSION_MINOR,
-		       DM_VERSION_PATCHLEVEL,
-		       version[0], version[1], version[2], cmd);
-		r = -EINVAL;
-	}
-
-	/*
-	 * Fill in the kernel version.
-	 */
-	version[0] = DM_VERSION_MAJOR;
-	version[1] = DM_VERSION_MINOR;
-	version[2] = DM_VERSION_PATCHLEVEL;
-	if (copy_to_user(user->version, version, sizeof(version)))
-		return -EFAULT;
-
-	return r;
-}
-
-static void free_params(struct dm_ioctl *param)
-{
-	vfree(param);
-}
-
-static int copy_params(struct dm_ioctl *user, struct dm_ioctl **param)
-{
-	struct dm_ioctl tmp, *dmi;
-
-	if (copy_from_user(&tmp, user, sizeof(tmp)))
-		return -EFAULT;
-
-	if (tmp.data_size < sizeof(tmp))
-		return -EINVAL;
-
-	dmi = (struct dm_ioctl *) vmalloc(tmp.data_size);
-	if (!dmi)
-		return -ENOMEM;
-
-	if (copy_from_user(dmi, user, tmp.data_size)) {
-		vfree(dmi);
-		return -EFAULT;
-	}
-
-	*param = dmi;
-	return 0;
-}
-
-static int validate_params(uint cmd, struct dm_ioctl *param)
-{
-	/* Ignores parameters */
-	if (cmd == DM_REMOVE_ALL_CMD)
-		return 0;
-
-	/* Unless creating, either name of uuid but not both */
-	if (cmd != DM_DEV_CREATE_CMD) {
-		if ((!*param->uuid && !*param->name) ||
-		    (*param->uuid && *param->name)) {
-			DMWARN("one of name or uuid must be supplied");
-			return -EINVAL;
-		}
-	}
-
-	/* Ensure strings are terminated */
-	param->name[DM_NAME_LEN - 1] = '\0';
-	param->uuid[DM_UUID_LEN - 1] = '\0';
-
-	return 0;
-}
-
-static int ctl_ioctl(struct inode *inode, struct file *file,
-		     uint command, ulong u)
-{
-	int r = 0;
-	unsigned int cmd;
-	struct dm_ioctl *param;
-	struct dm_ioctl *user = (struct dm_ioctl *) u;
-	ioctl_fn fn = NULL;
-
-	/* only root can play with this */
-	if (!capable(CAP_SYS_ADMIN))
-		return -EACCES;
-
-	if (_IOC_TYPE(command) != DM_IOCTL)
-		return -ENOTTY;
-
-	cmd = _IOC_NR(command);
-
-	/*
-	 * Check the interface version passed in.  This also
-	 * writes out the kernels interface version.
-	 */
-	r = check_version(cmd, user);
-	if (r)
-		return r;
-
-	/*
-	 * Nothing more to do for the version command.
-	 */
-	if (cmd == DM_VERSION_CMD)
-		return 0;
-
-	fn = lookup_ioctl(cmd);
-	if (!fn) {
-		DMWARN("dm_ctl_ioctl: unknown command 0x%x", command);
-		return -ENOTTY;
-	}
-
-	/*
-	 * Copy the parameters into kernel space.
-	 */
-	r = copy_params(user, &param);
-	if (r)
-		return r;
-
-	r = validate_params(cmd, param);
-	if (r) {
-		free_params(param);
-		return r;
-	}
-
-	r = fn(param, user);
-	free_params(param);
-	return r;
-}
-
-static struct file_operations _ctl_fops = {
-	.ioctl	 = ctl_ioctl,
-	.owner	 = THIS_MODULE,
-};
-
-static struct miscdevice _dm_misc = {
-	.minor		= MISC_DYNAMIC_MINOR,
-	.name		= DM_NAME,
-	.devfs_name	= "mapper/control",
-	.fops		= &_ctl_fops
-};
-
-/*
- * Create misc character device and link to DM_DIR/control.
- */
-int __init dm_interface_init(void)
-{
-	int r;
-
-	r = dm_hash_init();
-	if (r)
-		return r;
-
-	r = misc_register(&_dm_misc);
-	if (r) {
-		DMERR("misc_register failed for control device");
-		dm_hash_exit();
-		return r;
-	}
-
-	DMINFO("%d.%d.%d%s initialised: %s", DM_VERSION_MAJOR,
-	       DM_VERSION_MINOR, DM_VERSION_PATCHLEVEL, DM_VERSION_EXTRA,
-	       DM_DRIVER_EMAIL);
-	return 0;
-
-	if (misc_deregister(&_dm_misc) < 0)
-		DMERR("misc_deregister failed for control device");
-	dm_hash_exit();
-	return r;
-}
-
-void dm_interface_exit(void)
-{
-	if (misc_deregister(&_dm_misc) < 0)
-		DMERR("misc_deregister failed for control device");
-	dm_hash_exit();
-}
--- diff/drivers/md/dm-ioctl-v4.c	2004-01-19 10:22:56.000000000 +0000
+++ source/drivers/md/dm-ioctl-v4.c	1970-01-01 01:00:00.000000000 +0100
@@ -1,1264 +0,0 @@
-/*
- * Copyright (C) 2001, 2002 Sistina Software (UK) Limited.
- *
- * This file is released under the GPL.
- */
-
-#include "dm.h"
-
-#include <linux/module.h>
-#include <linux/vmalloc.h>
-#include <linux/miscdevice.h>
-#include <linux/init.h>
-#include <linux/wait.h>
-#include <linux/slab.h>
-#include <linux/devfs_fs_kernel.h>
-#include <linux/dm-ioctl.h>
-
-#include <asm/uaccess.h>
-
-#define DM_DRIVER_EMAIL "dm@uk.sistina.com"
-
-/*-----------------------------------------------------------------
- * The ioctl interface needs to be able to look up devices by
- * name or uuid.
- *---------------------------------------------------------------*/
-struct hash_cell {
-	struct list_head name_list;
-	struct list_head uuid_list;
-
-	char *name;
-	char *uuid;
-	struct mapped_device *md;
-	struct dm_table *new_map;
-};
-
-#define NUM_BUCKETS 64
-#define MASK_BUCKETS (NUM_BUCKETS - 1)
-static struct list_head _name_buckets[NUM_BUCKETS];
-static struct list_head _uuid_buckets[NUM_BUCKETS];
-
-void dm_hash_remove_all(void);
-
-/*
- * Guards access to both hash tables.
- */
-static DECLARE_RWSEM(_hash_lock);
-
-static void init_buckets(struct list_head *buckets)
-{
-	unsigned int i;
-
-	for (i = 0; i < NUM_BUCKETS; i++)
-		INIT_LIST_HEAD(buckets + i);
-}
-
-int dm_hash_init(void)
-{
-	init_buckets(_name_buckets);
-	init_buckets(_uuid_buckets);
-	devfs_mk_dir(DM_DIR);
-	return 0;
-}
-
-void dm_hash_exit(void)
-{
-	dm_hash_remove_all();
-	devfs_remove(DM_DIR);
-}
-
-/*-----------------------------------------------------------------
- * Hash function:
- * We're not really concerned with the str hash function being
- * fast since it's only used by the ioctl interface.
- *---------------------------------------------------------------*/
-static unsigned int hash_str(const char *str)
-{
-	const unsigned int hash_mult = 2654435387U;
-	unsigned int h = 0;
-
-	while (*str)
-		h = (h + (unsigned int) *str++) * hash_mult;
-
-	return h & MASK_BUCKETS;
-}
-
-/*-----------------------------------------------------------------
- * Code for looking up a device by name
- *---------------------------------------------------------------*/
-static struct hash_cell *__get_name_cell(const char *str)
-{
-	struct list_head *tmp;
-	struct hash_cell *hc;
-	unsigned int h = hash_str(str);
-
-	list_for_each (tmp, _name_buckets + h) {
-		hc = list_entry(tmp, struct hash_cell, name_list);
-		if (!strcmp(hc->name, str))
-			return hc;
-	}
-
-	return NULL;
-}
-
-static struct hash_cell *__get_uuid_cell(const char *str)
-{
-	struct list_head *tmp;
-	struct hash_cell *hc;
-	unsigned int h = hash_str(str);
-
-	list_for_each (tmp, _uuid_buckets + h) {
-		hc = list_entry(tmp, struct hash_cell, uuid_list);
-		if (!strcmp(hc->uuid, str))
-			return hc;
-	}
-
-	return NULL;
-}
-
-/*-----------------------------------------------------------------
- * Inserting, removing and renaming a device.
- *---------------------------------------------------------------*/
-static inline char *kstrdup(const char *str)
-{
-	char *r = kmalloc(strlen(str) + 1, GFP_KERNEL);
-	if (r)
-		strcpy(r, str);
-	return r;
-}
-
-static struct hash_cell *alloc_cell(const char *name, const char *uuid,
-				    struct mapped_device *md)
-{
-	struct hash_cell *hc;
-
-	hc = kmalloc(sizeof(*hc), GFP_KERNEL);
-	if (!hc)
-		return NULL;
-
-	hc->name = kstrdup(name);
-	if (!hc->name) {
-		kfree(hc);
-		return NULL;
-	}
-
-	if (!uuid)
-		hc->uuid = NULL;
-
-	else {
-		hc->uuid = kstrdup(uuid);
-		if (!hc->uuid) {
-			kfree(hc->name);
-			kfree(hc);
-			return NULL;
-		}
-	}
-
-	INIT_LIST_HEAD(&hc->name_list);
-	INIT_LIST_HEAD(&hc->uuid_list);
-	hc->md = md;
-	hc->new_map = NULL;
-	return hc;
-}
-
-static void free_cell(struct hash_cell *hc)
-{
-	if (hc) {
-		kfree(hc->name);
-		kfree(hc->uuid);
-		kfree(hc);
-	}
-}
-
-/*
- * devfs stuff.
- */
-static int register_with_devfs(struct hash_cell *hc)
-{
-	struct gendisk *disk = dm_disk(hc->md);
-
-	devfs_mk_bdev(MKDEV(disk->major, disk->first_minor),
-		      S_IFBLK | S_IRUSR | S_IWUSR | S_IRGRP,
-		      DM_DIR "/%s", hc->name);
-	return 0;
-}
-
-static int unregister_with_devfs(struct hash_cell *hc)
-{
-	devfs_remove(DM_DIR"/%s", hc->name);
-	return 0;
-}
-
-/*
- * The kdev_t and uuid of a device can never change once it is
- * initially inserted.
- */
-int dm_hash_insert(const char *name, const char *uuid, struct mapped_device *md)
-{
-	struct hash_cell *cell;
-
-	/*
-	 * Allocate the new cells.
-	 */
-	cell = alloc_cell(name, uuid, md);
-	if (!cell)
-		return -ENOMEM;
-
-	/*
-	 * Insert the cell into both hash tables.
-	 */
-	down_write(&_hash_lock);
-	if (__get_name_cell(name))
-		goto bad;
-
-	list_add(&cell->name_list, _name_buckets + hash_str(name));
-
-	if (uuid) {
-		if (__get_uuid_cell(uuid)) {
-			list_del(&cell->name_list);
-			goto bad;
-		}
-		list_add(&cell->uuid_list, _uuid_buckets + hash_str(uuid));
-	}
-	register_with_devfs(cell);
-	dm_get(md);
-	up_write(&_hash_lock);
-
-	return 0;
-
- bad:
-	up_write(&_hash_lock);
-	free_cell(cell);
-	return -EBUSY;
-}
-
-void __hash_remove(struct hash_cell *hc)
-{
-	/* remove from the dev hash */
-	list_del(&hc->uuid_list);
-	list_del(&hc->name_list);
-	unregister_with_devfs(hc);
-	dm_put(hc->md);
-	if (hc->new_map)
-		dm_table_put(hc->new_map);
-	free_cell(hc);
-}
-
-void dm_hash_remove_all(void)
-{
-	int i;
-	struct hash_cell *hc;
-	struct list_head *tmp, *n;
-
-	down_write(&_hash_lock);
-	for (i = 0; i < NUM_BUCKETS; i++) {
-		list_for_each_safe (tmp, n, _name_buckets + i) {
-			hc = list_entry(tmp, struct hash_cell, name_list);
-			__hash_remove(hc);
-		}
-	}
-	up_write(&_hash_lock);
-}
-
-int dm_hash_rename(const char *old, const char *new)
-{
-	char *new_name, *old_name;
-	struct hash_cell *hc;
-
-	/*
-	 * duplicate new.
-	 */
-	new_name = kstrdup(new);
-	if (!new_name)
-		return -ENOMEM;
-
-	down_write(&_hash_lock);
-
-	/*
-	 * Is new free ?
-	 */
-	hc = __get_name_cell(new);
-	if (hc) {
-		DMWARN("asked to rename to an already existing name %s -> %s",
-		       old, new);
-		up_write(&_hash_lock);
-		kfree(new_name);
-		return -EBUSY;
-	}
-
-	/*
-	 * Is there such a device as 'old' ?
-	 */
-	hc = __get_name_cell(old);
-	if (!hc) {
-		DMWARN("asked to rename a non existent device %s -> %s",
-		       old, new);
-		up_write(&_hash_lock);
-		kfree(new_name);
-		return -ENXIO;
-	}
-
-	/*
-	 * rename and move the name cell.
-	 */
-	unregister_with_devfs(hc);
-
-	list_del(&hc->name_list);
-	old_name = hc->name;
-	hc->name = new_name;
-	list_add(&hc->name_list, _name_buckets + hash_str(new_name));
-
-	/* rename the device node in devfs */
-	register_with_devfs(hc);
-
-	up_write(&_hash_lock);
-	kfree(old_name);
-	return 0;
-}
-
-/*-----------------------------------------------------------------
- * Implementation of the ioctl commands
- *---------------------------------------------------------------*/
-/*
- * All the ioctl commands get dispatched to functions with this
- * prototype.
- */
-typedef int (*ioctl_fn)(struct dm_ioctl *param, size_t param_size);
-
-static int remove_all(struct dm_ioctl *param, size_t param_size)
-{
-	dm_hash_remove_all();
-	param->data_size = 0;
-	return 0;
-}
-
-/*
- * Round up the ptr to an 8-byte boundary.
- */
-#define ALIGN_MASK 7
-static inline void *align_ptr(void *ptr)
-{
-	return (void *) (((size_t) (ptr + ALIGN_MASK)) & ~ALIGN_MASK);
-}
-
-/*
- * Retrieves the data payload buffer from an already allocated
- * struct dm_ioctl.
- */
-static void *get_result_buffer(struct dm_ioctl *param, size_t param_size,
-			       size_t *len)
-{
-	param->data_start = align_ptr(param + 1) - (void *) param;
-
-	if (param->data_start < param_size)
-		*len = param_size - param->data_start;
-	else
-		*len = 0;
-
-	return ((void *) param) + param->data_start;
-}
-
-static int list_devices(struct dm_ioctl *param, size_t param_size)
-{
-	unsigned int i;
-	struct hash_cell *hc;
-	size_t len, needed = 0;
-	struct gendisk *disk;
-	struct dm_name_list *nl, *old_nl = NULL;
-
-	down_write(&_hash_lock);
-
-	/*
-	 * Loop through all the devices working out how much
-	 * space we need.
-	 */
-	for (i = 0; i < NUM_BUCKETS; i++) {
-		list_for_each_entry (hc, _name_buckets + i, name_list) {
-			needed += sizeof(struct dm_name_list);
-			needed += strlen(hc->name);
-			needed += ALIGN_MASK;
-		}
-	}
-
-	/*
-	 * Grab our output buffer.
-	 */
-	nl = get_result_buffer(param, param_size, &len);
-	if (len < needed) {
-		param->flags |= DM_BUFFER_FULL_FLAG;
-		goto out;
-	}
-	param->data_size = param->data_start + needed;
-
-	nl->dev = 0;	/* Flags no data */
-
-	/*
-	 * Now loop through filling out the names.
-	 */
-	for (i = 0; i < NUM_BUCKETS; i++) {
-		list_for_each_entry (hc, _name_buckets + i, name_list) {
-			if (old_nl)
-				old_nl->next = (uint32_t) ((void *) nl -
-							   (void *) old_nl);
-			disk = dm_disk(hc->md);
-			nl->dev = huge_encode_dev(MKDEV(disk->major, disk->first_minor));
-			nl->next = 0;
-			strcpy(nl->name, hc->name);
-
-			old_nl = nl;
-			nl = align_ptr(((void *) ++nl) + strlen(hc->name) + 1);
-		}
-	}
-
- out:
-	up_write(&_hash_lock);
-	return 0;
-}
-
-static int check_name(const char *name)
-{
-	if (strchr(name, '/')) {
-		DMWARN("invalid device name");
-		return -EINVAL;
-	}
-
-	return 0;
-}
-
-/*
- * Fills in a dm_ioctl structure, ready for sending back to
- * userland.
- */
-static int __dev_status(struct mapped_device *md, struct dm_ioctl *param)
-{
-	struct gendisk *disk = dm_disk(md);
-	struct dm_table *table;
-	struct block_device *bdev;
-
-	param->flags &= ~(DM_SUSPEND_FLAG | DM_READONLY_FLAG |
-			  DM_ACTIVE_PRESENT_FLAG);
-
-	if (dm_suspended(md))
-		param->flags |= DM_SUSPEND_FLAG;
-
-	bdev = bdget_disk(disk, 0);
-	if (!bdev)
-		return -ENXIO;
-
-	param->dev = huge_encode_dev(MKDEV(disk->major, disk->first_minor));
-
-	/*
-	 * Yes, this will be out of date by the time it gets back
-	 * to userland, but it is still very useful ofr
-	 * debugging.
-	 */
-	param->open_count = bdev->bd_openers;
-	bdput(bdev);
-
-	if (disk->policy)
-		param->flags |= DM_READONLY_FLAG;
-
-	param->event_nr = dm_get_event_nr(md);
-
-	table = dm_get_table(md);
-	if (table) {
-		param->flags |= DM_ACTIVE_PRESENT_FLAG;
-		param->target_count = dm_table_get_num_targets(table);
-		dm_table_put(table);
-	} else
-		param->target_count = 0;
-
-	return 0;
-}
-
-static int dev_create(struct dm_ioctl *param, size_t param_size)
-{
-	int r;
-	struct mapped_device *md;
-
-	r = check_name(param->name);
-	if (r)
-		return r;
-
-	if (param->flags & DM_PERSISTENT_DEV_FLAG)
-		r = dm_create_with_minor(MINOR(huge_decode_dev(param->dev)), &md);
-	else
-		r = dm_create(&md);
-
-	if (r)
-		return r;
-
-	r = dm_hash_insert(param->name, *param->uuid ? param->uuid : NULL, md);
-	if (r) {
-		dm_put(md);
-		return r;
-	}
-
-	param->flags &= ~DM_INACTIVE_PRESENT_FLAG;
-
-	r = __dev_status(md, param);
-	dm_put(md);
-
-	return r;
-}
-
-/*
- * Always use UUID for lookups if it's present, otherwise use name.
- */
-static inline struct hash_cell *__find_device_hash_cell(struct dm_ioctl *param)
-{
-	return *param->uuid ?
-	    __get_uuid_cell(param->uuid) : __get_name_cell(param->name);
-}
-
-static inline struct mapped_device *find_device(struct dm_ioctl *param)
-{
-	struct hash_cell *hc;
-	struct mapped_device *md = NULL;
-
-	down_read(&_hash_lock);
-	hc = __find_device_hash_cell(param);
-	if (hc) {
-		md = hc->md;
-
-		/*
-		 * Sneakily write in both the name and the uuid
-		 * while we have the cell.
-		 */
-		strncpy(param->name, hc->name, sizeof(param->name));
-		if (hc->uuid)
-			strncpy(param->uuid, hc->uuid, sizeof(param->uuid)-1);
-		else
-			param->uuid[0] = '\0';
-
-		if (hc->new_map)
-			param->flags |= DM_INACTIVE_PRESENT_FLAG;
-		else
-			param->flags &= ~DM_INACTIVE_PRESENT_FLAG;
-
-		dm_get(md);
-	}
-	up_read(&_hash_lock);
-
-	return md;
-}
-
-static int dev_remove(struct dm_ioctl *param, size_t param_size)
-{
-	struct hash_cell *hc;
-
-	down_write(&_hash_lock);
-	hc = __find_device_hash_cell(param);
-
-	if (!hc) {
-		DMWARN("device doesn't appear to be in the dev hash table.");
-		up_write(&_hash_lock);
-		return -ENXIO;
-	}
-
-	__hash_remove(hc);
-	up_write(&_hash_lock);
-	param->data_size = 0;
-	return 0;
-}
-
-/*
- * Check a string doesn't overrun the chunk of
- * memory we copied from userland.
- */
-static int invalid_str(char *str, void *end)
-{
-	while ((void *) str < end)
-		if (!*str++)
-			return 0;
-
-	return -EINVAL;
-}
-
-static int dev_rename(struct dm_ioctl *param, size_t param_size)
-{
-	int r;
-	char *new_name = (char *) param + param->data_start;
-
-	if (new_name < (char *) (param + 1) ||
-	    invalid_str(new_name, (void *) param + param_size)) {
-		DMWARN("Invalid new logical volume name supplied.");
-		return -EINVAL;
-	}
-
-	r = check_name(new_name);
-	if (r)
-		return r;
-
-	param->data_size = 0;
-	return dm_hash_rename(param->name, new_name);
-}
-
-static int do_suspend(struct dm_ioctl *param)
-{
-	int r = 0;
-	struct mapped_device *md;
-
-	md = find_device(param);
-	if (!md)
-		return -ENXIO;
-
-	if (!dm_suspended(md))
-		r = dm_suspend(md);
-
-	if (!r)
-		r = __dev_status(md, param);
-
-	dm_put(md);
-	return r;
-}
-
-static int do_resume(struct dm_ioctl *param)
-{
-	int r = 0;
-	struct hash_cell *hc;
-	struct mapped_device *md;
-	struct dm_table *new_map;
-
-	down_write(&_hash_lock);
-
-	hc = __find_device_hash_cell(param);
-	if (!hc) {
-		DMWARN("device doesn't appear to be in the dev hash table.");
-		up_write(&_hash_lock);
-		return -ENXIO;
-	}
-
-	md = hc->md;
-	dm_get(md);
-
-	new_map = hc->new_map;
-	hc->new_map = NULL;
-	param->flags &= ~DM_INACTIVE_PRESENT_FLAG;
-
-	up_write(&_hash_lock);
-
-	/* Do we need to load a new map ? */
-	if (new_map) {
-		/* Suspend if it isn't already suspended */
-		if (!dm_suspended(md))
-			dm_suspend(md);
-
-		r = dm_swap_table(md, new_map);
-		if (r) {
-			dm_put(md);
-			dm_table_put(new_map);
-			return r;
-		}
-
-		if (dm_table_get_mode(new_map) & FMODE_WRITE)
-			set_disk_ro(dm_disk(md), 0);
-		else
-			set_disk_ro(dm_disk(md), 1);
-
-		dm_table_put(new_map);
-	}
-
-	if (dm_suspended(md))
-		r = dm_resume(md);
-
-	if (!r)
-		r = __dev_status(md, param);
-
-	dm_put(md);
-	return r;
-}
-
-/*
- * Set or unset the suspension state of a device.
- * If the device already is in the requested state we just return its status.
- */
-static int dev_suspend(struct dm_ioctl *param, size_t param_size)
-{
-	if (param->flags & DM_SUSPEND_FLAG)
-		return do_suspend(param);
-
-	return do_resume(param);
-}
-
-/*
- * Copies device info back to user space, used by
- * the create and info ioctls.
- */
-static int dev_status(struct dm_ioctl *param, size_t param_size)
-{
-	int r;
-	struct mapped_device *md;
-
-	md = find_device(param);
-	if (!md)
-		return -ENXIO;
-
-	r = __dev_status(md, param);
-	dm_put(md);
-	return r;
-}
-
-/*
- * Build up the status struct for each target
- */
-static void retrieve_status(struct dm_table *table,
-			    struct dm_ioctl *param, size_t param_size)
-{
-	unsigned int i, num_targets;
-	struct dm_target_spec *spec;
-	char *outbuf, *outptr;
-	status_type_t type;
-	size_t remaining, len, used = 0;
-
-	outptr = outbuf = get_result_buffer(param, param_size, &len);
-
-	if (param->flags & DM_STATUS_TABLE_FLAG)
-		type = STATUSTYPE_TABLE;
-	else
-		type = STATUSTYPE_INFO;
-
-	/* Get all the target info */
-	num_targets = dm_table_get_num_targets(table);
-	for (i = 0; i < num_targets; i++) {
-		struct dm_target *ti = dm_table_get_target(table, i);
-
-		remaining = len - (outptr - outbuf);
-		if (remaining < sizeof(struct dm_target_spec)) {
-			param->flags |= DM_BUFFER_FULL_FLAG;
-			break;
-		}
-
-		spec = (struct dm_target_spec *) outptr;
-
-		spec->status = 0;
-		spec->sector_start = ti->begin;
-		spec->length = ti->len;
-		strncpy(spec->target_type, ti->type->name,
-			sizeof(spec->target_type));
-
-		outptr += sizeof(struct dm_target_spec);
-		remaining = len - (outptr - outbuf);
-
-		/* Get the status/table string from the target driver */
-		if (ti->type->status) {
-			if (ti->type->status(ti, type, outptr, remaining)) {
-				param->flags |= DM_BUFFER_FULL_FLAG;
-				break;
-			}
-		} else
-			outptr[0] = '\0';
-
-		outptr += strlen(outptr) + 1;
-		used = param->data_start + (outptr - outbuf);
-
-		align_ptr(outptr);
-		spec->next = outptr - outbuf;
-	}
-
-	if (used)
-		param->data_size = used;
-
-	param->target_count = num_targets;
-}
-
-/*
- * Wait for a device to report an event
- */
-static int dev_wait(struct dm_ioctl *param, size_t param_size)
-{
-	int r;
-	struct mapped_device *md;
-	struct dm_table *table;
-	DECLARE_WAITQUEUE(wq, current);
-
-	md = find_device(param);
-	if (!md)
-		return -ENXIO;
-
-	/*
-	 * Wait for a notification event
-	 */
-	set_current_state(TASK_INTERRUPTIBLE);
-	if (!dm_add_wait_queue(md, &wq, param->event_nr)) {
-		schedule();
-		dm_remove_wait_queue(md, &wq);
-	}
- 	set_current_state(TASK_RUNNING);
-
-	/*
-	 * The userland program is going to want to know what
-	 * changed to trigger the event, so we may as well tell
-	 * him and save an ioctl.
-	 */
-	r = __dev_status(md, param);
-	if (r)
-		goto out;
-
-	table = dm_get_table(md);
-	if (table) {
-		retrieve_status(table, param, param_size);
-		dm_table_put(table);
-	}
-
- out:
-	dm_put(md);
-	return r;
-}
-
-static inline int get_mode(struct dm_ioctl *param)
-{
-	int mode = FMODE_READ | FMODE_WRITE;
-
-	if (param->flags & DM_READONLY_FLAG)
-		mode = FMODE_READ;
-
-	return mode;
-}
-
-static int next_target(struct dm_target_spec *last, uint32_t next, void *end,
-		       struct dm_target_spec **spec, char **target_params)
-{
-	*spec = (struct dm_target_spec *) ((unsigned char *) last + next);
-	*target_params = (char *) (*spec + 1);
-
-	if (*spec < (last + 1))
-		return -EINVAL;
-
-	return invalid_str(*target_params, end);
-}
-
-static int populate_table(struct dm_table *table,
-			  struct dm_ioctl *param, size_t param_size)
-{
-	int r;
-	unsigned int i = 0;
-	struct dm_target_spec *spec = (struct dm_target_spec *) param;
-	uint32_t next = param->data_start;
-	void *end = (void *) param + param_size;
-	char *target_params;
-
-	if (!param->target_count) {
-		DMWARN("populate_table: no targets specified");
-		return -EINVAL;
-	}
-
-	for (i = 0; i < param->target_count; i++) {
-
-		r = next_target(spec, next, end, &spec, &target_params);
-		if (r) {
-			DMWARN("unable to find target");
-			return r;
-		}
-
-		r = dm_table_add_target(table, spec->target_type,
-					(sector_t) spec->sector_start,
-					(sector_t) spec->length,
-					target_params);
-		if (r) {
-			DMWARN("error adding target to table");
-			return r;
-		}
-
-		next = spec->next;
-	}
-
-	return dm_table_complete(table);
-}
-
-static int table_load(struct dm_ioctl *param, size_t param_size)
-{
-	int r;
-	struct hash_cell *hc;
-	struct dm_table *t;
-
-	r = dm_table_create(&t, get_mode(param), param->target_count);
-	if (r)
-		return r;
-
-	r = populate_table(t, param, param_size);
-	if (r) {
-		dm_table_put(t);
-		return r;
-	}
-
-	down_write(&_hash_lock);
-	hc = __find_device_hash_cell(param);
-	if (!hc) {
-		DMWARN("device doesn't appear to be in the dev hash table.");
-		up_write(&_hash_lock);
-		return -ENXIO;
-	}
-
-	if (hc->new_map)
-		dm_table_put(hc->new_map);
-	hc->new_map = t;
-	param->flags |= DM_INACTIVE_PRESENT_FLAG;
-
-	r = __dev_status(hc->md, param);
-	up_write(&_hash_lock);
-	return r;
-}
-
-static int table_clear(struct dm_ioctl *param, size_t param_size)
-{
-	int r;
-	struct hash_cell *hc;
-
-	down_write(&_hash_lock);
-
-	hc = __find_device_hash_cell(param);
-	if (!hc) {
-		DMWARN("device doesn't appear to be in the dev hash table.");
-		up_write(&_hash_lock);
-		return -ENXIO;
-	}
-
-	if (hc->new_map) {
-		dm_table_put(hc->new_map);
-		hc->new_map = NULL;
-	}
-
-	param->flags &= ~DM_INACTIVE_PRESENT_FLAG;
-
-	r = __dev_status(hc->md, param);
-	up_write(&_hash_lock);
-	return r;
-}
-
-/*
- * Retrieves a list of devices used by a particular dm device.
- */
-static void retrieve_deps(struct dm_table *table,
-			  struct dm_ioctl *param, size_t param_size)
-{
-	unsigned int count = 0;
-	struct list_head *tmp;
-	size_t len, needed;
-	struct dm_target_deps *deps;
-
-	deps = get_result_buffer(param, param_size, &len);
-
-	/*
-	 * Count the devices.
-	 */
-	list_for_each(tmp, dm_table_get_devices(table))
-		count++;
-
-	/*
-	 * Check we have enough space.
-	 */
-	needed = sizeof(*deps) + (sizeof(*deps->dev) * count);
-	if (len < needed) {
-		param->flags |= DM_BUFFER_FULL_FLAG;
-		return;
-	}
-
-	/*
-	 * Fill in the devices.
-	 */
-	deps->count = count;
-	count = 0;
-	list_for_each(tmp, dm_table_get_devices(table)) {
-		struct dm_dev *dd = list_entry(tmp, struct dm_dev, list);
-		deps->dev[count++] = huge_encode_dev(dd->bdev->bd_dev);
-	}
-
-	param->data_size = param->data_start + needed;
-}
-
-static int table_deps(struct dm_ioctl *param, size_t param_size)
-{
-	int r = 0;
-	struct mapped_device *md;
-	struct dm_table *table;
-
-	md = find_device(param);
-	if (!md)
-		return -ENXIO;
-
-	r = __dev_status(md, param);
-	if (r)
-		goto out;
-
-	table = dm_get_table(md);
-	if (table) {
-		retrieve_deps(table, param, param_size);
-		dm_table_put(table);
-	}
-
- out:
-	dm_put(md);
-	return r;
-}
-
-/*
- * Return the status of a device as a text string for each
- * target.
- */
-static int table_status(struct dm_ioctl *param, size_t param_size)
-{
-	int r;
-	struct mapped_device *md;
-	struct dm_table *table;
-
-	md = find_device(param);
-	if (!md)
-		return -ENXIO;
-
-	r = __dev_status(md, param);
-	if (r)
-		goto out;
-
-	table = dm_get_table(md);
-	if (table) {
-		retrieve_status(table, param, param_size);
-		dm_table_put(table);
-	}
-
- out:
-	dm_put(md);
-	return r;
-}
-
-/*-----------------------------------------------------------------
- * Implementation of open/close/ioctl on the special char
- * device.
- *---------------------------------------------------------------*/
-static ioctl_fn lookup_ioctl(unsigned int cmd)
-{
-	static struct {
-		int cmd;
-		ioctl_fn fn;
-	} _ioctls[] = {
-		{DM_VERSION_CMD, NULL},	/* version is dealt with elsewhere */
-		{DM_REMOVE_ALL_CMD, remove_all},
-		{DM_LIST_DEVICES_CMD, list_devices},
-
-		{DM_DEV_CREATE_CMD, dev_create},
-		{DM_DEV_REMOVE_CMD, dev_remove},
-		{DM_DEV_RENAME_CMD, dev_rename},
-		{DM_DEV_SUSPEND_CMD, dev_suspend},
-		{DM_DEV_STATUS_CMD, dev_status},
-		{DM_DEV_WAIT_CMD, dev_wait},
-
-		{DM_TABLE_LOAD_CMD, table_load},
-		{DM_TABLE_CLEAR_CMD, table_clear},
-		{DM_TABLE_DEPS_CMD, table_deps},
-		{DM_TABLE_STATUS_CMD, table_status}
-	};
-
-	return (cmd >= ARRAY_SIZE(_ioctls)) ? NULL : _ioctls[cmd].fn;
-}
-
-/*
- * As well as checking the version compatibility this always
- * copies the kernel interface version out.
- */
-static int check_version(unsigned int cmd, struct dm_ioctl *user)
-{
-	uint32_t version[3];
-	int r = 0;
-
-	if (copy_from_user(version, user->version, sizeof(version)))
-		return -EFAULT;
-
-	if ((DM_VERSION_MAJOR != version[0]) ||
-	    (DM_VERSION_MINOR < version[1])) {
-		DMWARN("ioctl interface mismatch: "
-		       "kernel(%u.%u.%u), user(%u.%u.%u), cmd(%d)",
-		       DM_VERSION_MAJOR, DM_VERSION_MINOR,
-		       DM_VERSION_PATCHLEVEL,
-		       version[0], version[1], version[2], cmd);
-		r = -EINVAL;
-	}
-
-	/*
-	 * Fill in the kernel version.
-	 */
-	version[0] = DM_VERSION_MAJOR;
-	version[1] = DM_VERSION_MINOR;
-	version[2] = DM_VERSION_PATCHLEVEL;
-	if (copy_to_user(user->version, version, sizeof(version)))
-		return -EFAULT;
-
-	return r;
-}
-
-static void free_params(struct dm_ioctl *param)
-{
-	vfree(param);
-}
-
-static int copy_params(struct dm_ioctl *user, struct dm_ioctl **param)
-{
-	struct dm_ioctl tmp, *dmi;
-
-	if (copy_from_user(&tmp, user, sizeof(tmp)))
-		return -EFAULT;
-
-	if (tmp.data_size < sizeof(tmp))
-		return -EINVAL;
-
-	dmi = (struct dm_ioctl *) vmalloc(tmp.data_size);
-	if (!dmi)
-		return -ENOMEM;
-
-	if (copy_from_user(dmi, user, tmp.data_size)) {
-		vfree(dmi);
-		return -EFAULT;
-	}
-
-	*param = dmi;
-	return 0;
-}
-
-static int validate_params(uint cmd, struct dm_ioctl *param)
-{
-	/* Always clear this flag */
-	param->flags &= ~DM_BUFFER_FULL_FLAG;
-
-	/* Ignores parameters */
-	if (cmd == DM_REMOVE_ALL_CMD || cmd == DM_LIST_DEVICES_CMD)
-		return 0;
-
-	/* Unless creating, either name or uuid but not both */
-	if (cmd != DM_DEV_CREATE_CMD) {
-		if ((!*param->uuid && !*param->name) ||
-		    (*param->uuid && *param->name)) {
-			DMWARN("one of name or uuid must be supplied, cmd(%u)",
-			       cmd);
-			return -EINVAL;
-		}
-	}
-
-	/* Ensure strings are terminated */
-	param->name[DM_NAME_LEN - 1] = '\0';
-	param->uuid[DM_UUID_LEN - 1] = '\0';
-
-	return 0;
-}
-
-static int ctl_ioctl(struct inode *inode, struct file *file,
-		     uint command, ulong u)
-{
-	int r = 0;
-	unsigned int cmd;
-	struct dm_ioctl *param;
-	struct dm_ioctl *user = (struct dm_ioctl *) u;
-	ioctl_fn fn = NULL;
-	size_t param_size;
-
-	/* only root can play with this */
-	if (!capable(CAP_SYS_ADMIN))
-		return -EACCES;
-
-	if (_IOC_TYPE(command) != DM_IOCTL)
-		return -ENOTTY;
-
-	cmd = _IOC_NR(command);
-
-	/*
-	 * Check the interface version passed in.  This also
-	 * writes out the kernel's interface version.
-	 */
-	r = check_version(cmd, user);
-	if (r)
-		return r;
-
-	/*
-	 * Nothing more to do for the version command.
-	 */
-	if (cmd == DM_VERSION_CMD)
-		return 0;
-
-	fn = lookup_ioctl(cmd);
-	if (!fn) {
-		DMWARN("dm_ctl_ioctl: unknown command 0x%x", command);
-		return -ENOTTY;
-	}
-
-	/*
-	 * Trying to avoid low memory issues when a device is
-	 * suspended.
-	 */
-	current->flags |= PF_MEMALLOC;
-
-	/*
-	 * Copy the parameters into kernel space.
-	 */
-	r = copy_params(user, &param);
-	if (r) {
-		current->flags &= ~PF_MEMALLOC;
-		return r;
-	}
-
-	/*
-	 * FIXME: eventually we will remove the PF_MEMALLOC flag
-	 * here.  However the tools still do nasty things like
-	 * 'load' while a device is suspended.
-	 */
-
-	r = validate_params(cmd, param);
-	if (r)
-		goto out;
-
-	param_size = param->data_size;
-	param->data_size = sizeof(*param);
-	r = fn(param, param_size);
-
-	/*
-	 * Copy the results back to userland.
-	 */
-	if (!r && copy_to_user(user, param, param->data_size))
-		r = -EFAULT;
-
- out:
-	free_params(param);
-	current->flags &= ~PF_MEMALLOC;
-	return r;
-}
-
-static struct file_operations _ctl_fops = {
-	.ioctl	 = ctl_ioctl,
-	.owner	 = THIS_MODULE,
-};
-
-static struct miscdevice _dm_misc = {
-	.minor 		= MISC_DYNAMIC_MINOR,
-	.name  		= DM_NAME,
-	.devfs_name 	= "mapper/control",
-	.fops  		= &_ctl_fops
-};
-
-/*
- * Create misc character device and link to DM_DIR/control.
- */
-int __init dm_interface_init(void)
-{
-	int r;
-
-	r = dm_hash_init();
-	if (r)
-		return r;
-
-	r = misc_register(&_dm_misc);
-	if (r) {
-		DMERR("misc_register failed for control device");
-		dm_hash_exit();
-		return r;
-	}
-
-	DMINFO("%d.%d.%d%s initialised: %s", DM_VERSION_MAJOR,
-	       DM_VERSION_MINOR, DM_VERSION_PATCHLEVEL, DM_VERSION_EXTRA,
-	       DM_DRIVER_EMAIL);
-	return 0;
-}
-
-void dm_interface_exit(void)
-{
-	if (misc_deregister(&_dm_misc) < 0)
-		DMERR("misc_deregister failed for control device");
-
-	dm_hash_exit();
-}
--- diff/drivers/net/e100/LICENSE	2002-10-16 04:28:27.000000000 +0100
+++ source/drivers/net/e100/LICENSE	1970-01-01 01:00:00.000000000 +0100
@@ -1,339 +0,0 @@
-
-"This software program is licensed subject to the GNU General Public License 
-(GPL). Version 2, June 1991, available at 
-<http://www.fsf.org/copyleft/gpl.html>"
-
-GNU General Public License 
-
-Version 2, June 1991
-
-Copyright (C) 1989, 1991 Free Software Foundation, Inc.  
-59 Temple Place - Suite 330, Boston, MA  02111-1307, USA
-
-Everyone is permitted to copy and distribute verbatim copies of this license
-document, but changing it is not allowed.
-
-Preamble
-
-The licenses for most software are designed to take away your freedom to 
-share and change it. By contrast, the GNU General Public License is intended
-to guarantee your freedom to share and change free software--to make sure 
-the software is free for all its users. This General Public License applies 
-to most of the Free Software Foundation's software and to any other program 
-whose authors commit to using it. (Some other Free Software Foundation 
-software is covered by the GNU Library General Public License instead.) You 
-can apply it to your programs, too.
-
-When we speak of free software, we are referring to freedom, not price. Our
-General Public Licenses are designed to make sure that you have the freedom 
-to distribute copies of free software (and charge for this service if you 
-wish), that you receive source code or can get it if you want it, that you 
-can change the software or use pieces of it in new free programs; and that 
-you know you can do these things.
-
-To protect your rights, we need to make restrictions that forbid anyone to 
-deny you these rights or to ask you to surrender the rights. These 
-restrictions translate to certain responsibilities for you if you distribute
-copies of the software, or if you modify it.
-
-For example, if you distribute copies of such a program, whether gratis or 
-for a fee, you must give the recipients all the rights that you have. You 
-must make sure that they, too, receive or can get the source code. And you 
-must show them these terms so they know their rights.
- 
-We protect your rights with two steps: (1) copyright the software, and (2) 
-offer you this license which gives you legal permission to copy, distribute 
-and/or modify the software. 
-
-Also, for each author's protection and ours, we want to make certain that 
-everyone understands that there is no warranty for this free software. If 
-the software is modified by someone else and passed on, we want its 
-recipients to know that what they have is not the original, so that any 
-problems introduced by others will not reflect on the original authors' 
-reputations. 
-
-Finally, any free program is threatened constantly by software patents. We 
-wish to avoid the danger that redistributors of a free program will 
-individually obtain patent licenses, in effect making the program 
-proprietary. To prevent this, we have made it clear that any patent must be 
-licensed for everyone's free use or not licensed at all. 
-
-The precise terms and conditions for copying, distribution and modification 
-follow. 
-
-TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
-
-0. This License applies to any program or other work which contains a notice
-   placed by the copyright holder saying it may be distributed under the 
-   terms of this General Public License. The "Program", below, refers to any
-   such program or work, and a "work based on the Program" means either the 
-   Program or any derivative work under copyright law: that is to say, a 
-   work containing the Program or a portion of it, either verbatim or with 
-   modifications and/or translated into another language. (Hereinafter, 
-   translation is included without limitation in the term "modification".) 
-   Each licensee is addressed as "you". 
-
-   Activities other than copying, distribution and modification are not 
-   covered by this License; they are outside its scope. The act of running 
-   the Program is not restricted, and the output from the Program is covered 
-   only if its contents constitute a work based on the Program (independent 
-   of having been made by running the Program). Whether that is true depends
-   on what the Program does. 
-
-1. You may copy and distribute verbatim copies of the Program's source code 
-   as you receive it, in any medium, provided that you conspicuously and 
-   appropriately publish on each copy an appropriate copyright notice and 
-   disclaimer of warranty; keep intact all the notices that refer to this 
-   License and to the absence of any warranty; and give any other recipients 
-   of the Program a copy of this License along with the Program. 
-
-   You may charge a fee for the physical act of transferring a copy, and you 
-   may at your option offer warranty protection in exchange for a fee. 
-
-2. You may modify your copy or copies of the Program or any portion of it, 
-   thus forming a work based on the Program, and copy and distribute such 
-   modifications or work under the terms of Section 1 above, provided that 
-   you also meet all of these conditions: 
-
-   * a) You must cause the modified files to carry prominent notices stating 
-        that you changed the files and the date of any change. 
-
-   * b) You must cause any work that you distribute or publish, that in 
-        whole or in part contains or is derived from the Program or any part 
-        thereof, to be licensed as a whole at no charge to all third parties
-        under the terms of this License. 
-
-   * c) If the modified program normally reads commands interactively when 
-        run, you must cause it, when started running for such interactive 
-        use in the most ordinary way, to print or display an announcement 
-        including an appropriate copyright notice and a notice that there is
-        no warranty (or else, saying that you provide a warranty) and that 
-        users may redistribute the program under these conditions, and 
-        telling the user how to view a copy of this License. (Exception: if 
-        the Program itself is interactive but does not normally print such 
-        an announcement, your work based on the Program is not required to 
-        print an announcement.) 
-
-   These requirements apply to the modified work as a whole. If identifiable 
-   sections of that work are not derived from the Program, and can be 
-   reasonably considered independent and separate works in themselves, then 
-   this License, and its terms, do not apply to those sections when you 
-   distribute them as separate works. But when you distribute the same 
-   sections as part of a whole which is a work based on the Program, the 
-   distribution of the whole must be on the terms of this License, whose 
-   permissions for other licensees extend to the entire whole, and thus to 
-   each and every part regardless of who wrote it. 
-
-   Thus, it is not the intent of this section to claim rights or contest 
-   your rights to work written entirely by you; rather, the intent is to 
-   exercise the right to control the distribution of derivative or 
-   collective works based on the Program. 
-
-   In addition, mere aggregation of another work not based on the Program 
-   with the Program (or with a work based on the Program) on a volume of a 
-   storage or distribution medium does not bring the other work under the 
-   scope of this License. 
-
-3. You may copy and distribute the Program (or a work based on it, under 
-   Section 2) in object code or executable form under the terms of Sections 
-   1 and 2 above provided that you also do one of the following: 
-
-   * a) Accompany it with the complete corresponding machine-readable source 
-        code, which must be distributed under the terms of Sections 1 and 2 
-        above on a medium customarily used for software interchange; or, 
-
-   * b) Accompany it with a written offer, valid for at least three years, 
-        to give any third party, for a charge no more than your cost of 
-        physically performing source distribution, a complete machine-
-        readable copy of the corresponding source code, to be distributed 
-        under the terms of Sections 1 and 2 above on a medium customarily 
-        used for software interchange; or, 
-
-   * c) Accompany it with the information you received as to the offer to 
-        distribute corresponding source code. (This alternative is allowed 
-        only for noncommercial distribution and only if you received the 
-        program in object code or executable form with such an offer, in 
-        accord with Subsection b above.) 
-
-   The source code for a work means the preferred form of the work for 
-   making modifications to it. For an executable work, complete source code 
-   means all the source code for all modules it contains, plus any 
-   associated interface definition files, plus the scripts used to control 
-   compilation and installation of the executable. However, as a special 
-   exception, the source code distributed need not include anything that is 
-   normally distributed (in either source or binary form) with the major 
-   components (compiler, kernel, and so on) of the operating system on which
-   the executable runs, unless that component itself accompanies the 
-   executable. 
-
-   If distribution of executable or object code is made by offering access 
-   to copy from a designated place, then offering equivalent access to copy 
-   the source code from the same place counts as distribution of the source 
-   code, even though third parties are not compelled to copy the source 
-   along with the object code. 
-
-4. You may not copy, modify, sublicense, or distribute the Program except as
-   expressly provided under this License. Any attempt otherwise to copy, 
-   modify, sublicense or distribute the Program is void, and will 
-   automatically terminate your rights under this License. However, parties 
-   who have received copies, or rights, from you under this License will not
-   have their licenses terminated so long as such parties remain in full 
-   compliance. 
-
-5. You are not required to accept this License, since you have not signed 
-   it. However, nothing else grants you permission to modify or distribute 
-   the Program or its derivative works. These actions are prohibited by law 
-   if you do not accept this License. Therefore, by modifying or 
-   distributing the Program (or any work based on the Program), you 
-   indicate your acceptance of this License to do so, and all its terms and
-   conditions for copying, distributing or modifying the Program or works 
-   based on it. 
-
-6. Each time you redistribute the Program (or any work based on the 
-   Program), the recipient automatically receives a license from the 
-   original licensor to copy, distribute or modify the Program subject to 
-   these terms and conditions. You may not impose any further restrictions 
-   on the recipients' exercise of the rights granted herein. You are not 
-   responsible for enforcing compliance by third parties to this License. 
-
-7. If, as a consequence of a court judgment or allegation of patent 
-   infringement or for any other reason (not limited to patent issues), 
-   conditions are imposed on you (whether by court order, agreement or 
-   otherwise) that contradict the conditions of this License, they do not 
-   excuse you from the conditions of this License. If you cannot distribute 
-   so as to satisfy simultaneously your obligations under this License and 
-   any other pertinent obligations, then as a consequence you may not 
-   distribute the Program at all. For example, if a patent license would 
-   not permit royalty-free redistribution of the Program by all those who 
-   receive copies directly or indirectly through you, then the only way you 
-   could satisfy both it and this License would be to refrain entirely from 
-   distribution of the Program. 
-
-   If any portion of this section is held invalid or unenforceable under any
-   particular circumstance, the balance of the section is intended to apply
-   and the section as a whole is intended to apply in other circumstances. 
-
-   It is not the purpose of this section to induce you to infringe any 
-   patents or other property right claims or to contest validity of any 
-   such claims; this section has the sole purpose of protecting the 
-   integrity of the free software distribution system, which is implemented 
-   by public license practices. Many people have made generous contributions
-   to the wide range of software distributed through that system in 
-   reliance on consistent application of that system; it is up to the 
-   author/donor to decide if he or she is willing to distribute software 
-   through any other system and a licensee cannot impose that choice. 
-
-   This section is intended to make thoroughly clear what is believed to be 
-   a consequence of the rest of this License. 
-
-8. If the distribution and/or use of the Program is restricted in certain 
-   countries either by patents or by copyrighted interfaces, the original 
-   copyright holder who places the Program under this License may add an 
-   explicit geographical distribution limitation excluding those countries, 
-   so that distribution is permitted only in or among countries not thus 
-   excluded. In such case, this License incorporates the limitation as if 
-   written in the body of this License. 
-
-9. The Free Software Foundation may publish revised and/or new versions of 
-   the General Public License from time to time. Such new versions will be 
-   similar in spirit to the present version, but may differ in detail to 
-   address new problems or concerns. 
-
-   Each version is given a distinguishing version number. If the Program 
-   specifies a version number of this License which applies to it and "any 
-   later version", you have the option of following the terms and 
-   conditions either of that version or of any later version published by 
-   the Free Software Foundation. If the Program does not specify a version 
-   number of this License, you may choose any version ever published by the 
-   Free Software Foundation. 
-
-10. If you wish to incorporate parts of the Program into other free programs
-    whose distribution conditions are different, write to the author to ask 
-    for permission. For software which is copyrighted by the Free Software 
-    Foundation, write to the Free Software Foundation; we sometimes make 
-    exceptions for this. Our decision will be guided by the two goals of 
-    preserving the free status of all derivatives of our free software and 
-    of promoting the sharing and reuse of software generally. 
-
-   NO WARRANTY
-
-11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY 
-    FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN 
-    OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES 
-    PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER 
-    EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
-    WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE 
-    ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH 
-    YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL 
-    NECESSARY SERVICING, REPAIR OR CORRECTION. 
-
-12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 
-    WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR 
-    REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR 
-    DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL 
-    DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM 
-    (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED 
-    INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF 
-    THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR 
-    OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 
-
-END OF TERMS AND CONDITIONS
-
-How to Apply These Terms to Your New Programs
-
-If you develop a new program, and you want it to be of the greatest 
-possible use to the public, the best way to achieve this is to make it free 
-software which everyone can redistribute and change under these terms. 
-
-To do so, attach the following notices to the program. It is safest to 
-attach them to the start of each source file to most effectively convey the
-exclusion of warranty; and each file should have at least the "copyright" 
-line and a pointer to where the full notice is found. 
-
-one line to give the program's name and an idea of what it does.
-Copyright (C) yyyy  name of author
-
-This program is free software; you can redistribute it and/or modify it 
-under the terms of the GNU General Public License as published by the Free 
-Software Foundation; either version 2 of the License, or (at your option) 
-any later version.
-
-This program is distributed in the hope that it will be useful, but WITHOUT 
-ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 
-FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for 
-more details.
-
-You should have received a copy of the GNU General Public License along with
-this program; if not, write to the Free Software Foundation, Inc., 59 
-Temple Place - Suite 330, Boston, MA  02111-1307, USA.
-
-Also add information on how to contact you by electronic and paper mail. 
-
-If the program is interactive, make it output a short notice like this when 
-it starts in an interactive mode: 
-
-Gnomovision version 69, Copyright (C) year name of author Gnomovision comes 
-with ABSOLUTELY NO WARRANTY; for details type 'show w'.  This is free 
-software, and you are welcome to redistribute it under certain conditions; 
-type 'show c' for details.
-
-The hypothetical commands 'show w' and 'show c' should show the appropriate 
-parts of the General Public License. Of course, the commands you use may be 
-called something other than 'show w' and 'show c'; they could even be 
-mouse-clicks or menu items--whatever suits your program. 
-
-You should also get your employer (if you work as a programmer) or your 
-school, if any, to sign a "copyright disclaimer" for the program, if 
-necessary. Here is a sample; alter the names: 
-
-Yoyodyne, Inc., hereby disclaims all copyright interest in the program 
-'Gnomovision' (which makes passes at compilers) written by James Hacker.
-
-signature of Ty Coon, 1 April 1989
-Ty Coon, President of Vice
-
-This General Public License does not permit incorporating your program into 
-proprietary programs. If your program is a subroutine library, you may 
-consider it more useful to permit linking proprietary applications with the 
-library. If this is what you want to do, use the GNU Library General Public 
-License instead of this License.
--- diff/drivers/net/e100/Makefile	2003-02-13 11:46:52.000000000 +0000
+++ source/drivers/net/e100/Makefile	1970-01-01 01:00:00.000000000 +0100
@@ -1,8 +0,0 @@
-#
-# Makefile for the Intel's E100 ethernet driver
-#
-
-obj-$(CONFIG_E100) += e100.o
-
-e100-objs := e100_main.o e100_config.o e100_phy.o \
-	     e100_eeprom.o e100_test.o
--- diff/drivers/net/e100/e100.h	2003-09-30 15:46:15.000000000 +0100
+++ source/drivers/net/e100/e100.h	1970-01-01 01:00:00.000000000 +0100
@@ -1,999 +0,0 @@
-/*******************************************************************************
-
-  
-  Copyright(c) 1999 - 2003 Intel Corporation. All rights reserved.
-  
-  This program is free software; you can redistribute it and/or modify it 
-  under the terms of the GNU General Public License as published by the Free 
-  Software Foundation; either version 2 of the License, or (at your option) 
-  any later version.
-  
-  This program is distributed in the hope that it will be useful, but WITHOUT 
-  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 
-  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for 
-  more details.
-  
-  You should have received a copy of the GNU General Public License along with
-  this program; if not, write to the Free Software Foundation, Inc., 59 
-  Temple Place - Suite 330, Boston, MA  02111-1307, USA.
-  
-  The full GNU General Public License is included in this distribution in the
-  file called LICENSE.
-  
-  Contact Information:
-  Linux NICS <linux.nics@intel.com>
-  Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
-*******************************************************************************/
-
-#ifndef _E100_INC_
-#define _E100_INC_
-
-#include <linux/module.h>
-#include <linux/types.h>
-#include <linux/init.h>
-#include <linux/mm.h>
-#include <linux/errno.h>
-#include <linux/ioport.h>
-#include <linux/pci.h>
-#include <linux/kernel.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/skbuff.h>
-#include <linux/delay.h>
-#include <linux/timer.h>
-#include <linux/slab.h>
-#include <linux/interrupt.h>
-#include <linux/string.h>
-#include <linux/wait.h>
-#include <linux/reboot.h>
-#include <asm/io.h>
-#include <asm/unaligned.h>
-#include <asm/processor.h>
-#include <linux/ethtool.h>
-#include <linux/inetdevice.h>
-#include <linux/bitops.h>
-
-#include <linux/if.h>
-#include <asm/uaccess.h>
-#include <linux/ip.h>
-#include <linux/if_vlan.h>
-#include <linux/mii.h>
-
-#define E100_CABLE_UNKNOWN	0
-#define E100_CABLE_OK		1		
-#define E100_CABLE_OPEN_NEAR	2	/* Open Circuit Near End  */
-#define E100_CABLE_OPEN_FAR	3	/* Open Circuit Far End   */
-#define E100_CABLE_SHORT_NEAR	4	/* Short Circuit Near End */
-#define E100_CABLE_SHORT_FAR	5	/* Short Circuit Far End  */
-
-#define E100_REGS_LEN 2
-/*
- *  Configure parameters for buffers per controller.
- *  If the machine this is being used on is a faster machine (i.e. > 150MHz)
- *  and running on a 10MBS network then more queueing of data occurs. This
- *  may indicate the some of the numbers below should be adjusted.  Here are
- *  some typical numbers:
- *                             MAX_TCB 64
- *                             MAX_RFD 64
- *  The default numbers give work well on most systems tests so no real
- *  adjustments really need to take place.  Also, if the machine is connected
- *  to a 100MBS network the numbers described above can be lowered from the
- *  defaults as considerably less data will be queued.
- */
-
-#define TX_FRAME_CNT   8	/* consecutive transmit frames per interrupt */
-/* TX_FRAME_CNT must be less than MAX_TCB    */
-
-#define E100_DEFAULT_TCB   64
-#define E100_MIN_TCB       2*TX_FRAME_CNT + 3	/* make room for at least 2 interrupts */
-#define E100_MAX_TCB       1024
-
-#define E100_DEFAULT_RFD   64
-#define E100_MIN_RFD       8
-#define E100_MAX_RFD       1024
-
-#define E100_DEFAULT_XSUM         true
-#define E100_DEFAULT_BER          ZLOCK_MAX_ERRORS
-#define E100_DEFAULT_SPEED_DUPLEX 0
-#define E100_DEFAULT_FC           0
-#define E100_DEFAULT_IFS          true
-#define E100_DEFAULT_UCODE        true
-
-#define TX_THRSHLD     8
-
-/* IFS parameters */
-#define MIN_NUMBER_OF_TRANSMITS_100 1000
-#define MIN_NUMBER_OF_TRANSMITS_10  100
-
-#define E100_MAX_NIC 16
-
-#define E100_MAX_SCB_WAIT	100	/* Max udelays in wait_scb */
-#define E100_MAX_CU_IDLE_WAIT	50	/* Max udelays in wait_cus_idle */
-
-/* HWI feature related constant */
-#define HWI_REGISTER_GRANULARITY        80	/* register granularity = 80 Cm */
-#define HWI_NEAR_END_BOUNDARY           1000	/* Near end is defined as < 10 meters */
-
-/* CPUSAVER_BUNDLE_MAX: Sets the maximum number of frames that will be bundled.
- * In some situations, such as the TCP windowing algorithm, it may be
- * better to limit the growth of the bundle size than let it go as
- * high as it can, because that could cause too much added latency.
- * The default is six, because this is the number of packets in the
- * default TCP window size.  A value of 1 would make CPUSaver indicate
- * an interrupt for every frame received.  If you do not want to put
- * a limit on the bundle size, set this value to xFFFF.
- */
-#define E100_DEFAULT_CPUSAVER_BUNDLE_MAX	6
-#define E100_DEFAULT_CPUSAVER_INTERRUPT_DELAY	0x600
-#define E100_DEFAULT_BUNDLE_SMALL_FR		false
-
-/* end of configurables */
-
-/* ====================================================================== */
-/*                                hw                                      */
-/* ====================================================================== */
-
-/* timeout for command completion */
-#define E100_CMD_WAIT   100	/* iterations */
-
-struct driver_stats {
-	struct net_device_stats net_stats;
-
-	unsigned long tx_late_col;
-	unsigned long tx_ok_defrd;
-	unsigned long tx_one_retry;
-	unsigned long tx_mt_one_retry;
-	unsigned long rcv_cdt_frames;
-	unsigned long xmt_fc_pkts;
-	unsigned long rcv_fc_pkts;
-	unsigned long rcv_fc_unsupported;
-	unsigned long xmt_tco_pkts;
-	unsigned long rcv_tco_pkts;
-	unsigned long rx_intr_pkts;
-};
-
-/* TODO: kill me when we can do C99 */
-#define false		(0)
-#define true		(1)
-
-/* Changed for 82558 and 82559 enhancements */
-/* defines for 82558/9 flow control CSR values */
-#define DFLT_FC_THLD       0x00	/* Rx FIFO threshold of 0.5KB free  */
-#define DFLT_FC_CMD        0x00	/* FC Command in CSR */
-
-/* ====================================================================== */
-/*                              equates                                   */
-/* ====================================================================== */
-
-/*
- * These are general purpose defines 
- */
-
-/* Bit Mask definitions */
-#define BIT_0       0x0001
-#define BIT_1       0x0002
-#define BIT_2       0x0004
-#define BIT_3       0x0008
-#define BIT_4       0x0010
-#define BIT_5       0x0020
-#define BIT_6       0x0040
-#define BIT_7       0x0080
-#define BIT_8       0x0100
-#define BIT_9       0x0200
-#define BIT_10      0x0400
-#define BIT_11      0x0800
-#define BIT_12      0x1000
-#define BIT_13      0x2000
-#define BIT_14      0x4000
-#define BIT_15      0x8000
-#define BIT_28      0x10000000
-
-#define BIT_0_2     0x0007
-#define BIT_0_3     0x000F
-#define BIT_0_4     0x001F
-#define BIT_0_5     0x003F
-#define BIT_0_6     0x007F
-#define BIT_0_7     0x00FF
-#define BIT_0_8     0x01FF
-#define BIT_0_13    0x3FFF
-#define BIT_0_15    0xFFFF
-#define BIT_1_2     0x0006
-#define BIT_1_3     0x000E
-#define BIT_2_5     0x003C
-#define BIT_3_4     0x0018
-#define BIT_4_5     0x0030
-#define BIT_4_6     0x0070
-#define BIT_4_7     0x00F0
-#define BIT_5_7     0x00E0
-#define BIT_5_12    0x1FE0
-#define BIT_5_15    0xFFE0
-#define BIT_6_7     0x00c0
-#define BIT_7_11    0x0F80
-#define BIT_8_10    0x0700
-#define BIT_9_13    0x3E00
-#define BIT_12_15   0xF000
-#define BIT_8_15    0xFF00
-
-#define BIT_16_20   0x001F0000
-#define BIT_21_25   0x03E00000
-#define BIT_26_27   0x0C000000
-
-/* Transmit Threshold related constants */
-#define DEFAULT_TX_PER_UNDERRUN         20000
-
-#define MAX_MULTICAST_ADDRS             64
-#define MAX_FILTER                      16
-
-#define FULL_DUPLEX      2
-#define HALF_DUPLEX      1
-
-/*
- * These defines are specific to the 82557 
- */
-
-/* E100 PORT functions -- lower 4 bits */
-#define PORT_SOFTWARE_RESET         0
-#define PORT_SELFTEST               1
-#define PORT_SELECTIVE_RESET        2
-#define PORT_DUMP                   3
-
-/* SCB Status Word bit definitions */
-/* Interrupt status/ack fields */
-/* ER and FCP interrupts for 82558 masks  */
-#define SCB_STATUS_ACK_MASK        BIT_8_15	/* Status Mask */
-#define SCB_STATUS_ACK_CX          BIT_15	/* CU Completed Action Cmd */
-#define SCB_STATUS_ACK_FR          BIT_14	/* RU Received A Frame */
-#define SCB_STATUS_ACK_CNA         BIT_13	/* CU Became Inactive (IDLE) */
-#define SCB_STATUS_ACK_RNR         BIT_12	/* RU Became Not Ready */
-#define SCB_STATUS_ACK_MDI         BIT_11	/* MDI read or write done */
-#define SCB_STATUS_ACK_SWI         BIT_10	/* S/W generated interrupt */
-#define SCB_STATUS_ACK_ER          BIT_9	/* Early Receive */
-#define SCB_STATUS_ACK_FCP         BIT_8	/* Flow Control Pause */
-
-/*- CUS Fields */
-#define SCB_CUS_MASK            (BIT_6 | BIT_7)	/* CUS 2-bit Mask */
-#define SCB_CUS_IDLE            0	/* CU Idle */
-#define SCB_CUS_SUSPEND         BIT_6	/* CU Suspended */
-#define SCB_CUS_ACTIVE          BIT_7	/* CU Active */
-
-/*- RUS Fields */
-#define SCB_RUS_IDLE            0	/* RU Idle */
-#define SCB_RUS_MASK            BIT_2_5	/* RUS 3-bit Mask */
-#define SCB_RUS_SUSPEND         BIT_2	/* RU Suspended */
-#define SCB_RUS_NO_RESOURCES    BIT_3	/* RU Out Of Resources */
-#define SCB_RUS_READY           BIT_4	/* RU Ready */
-#define SCB_RUS_SUSP_NO_RBDS    (BIT_2 | BIT_5)	/* RU No More RBDs */
-#define SCB_RUS_NO_RBDS         (BIT_3 | BIT_5)	/* RU No More RBDs */
-#define SCB_RUS_READY_NO_RBDS   (BIT_4 | BIT_5)	/* RU Ready, No RBDs */
-
-/* SCB Command Word bit definitions */
-/*- CUC fields */
-/* Changing mask to 4 bits */
-#define SCB_CUC_MASK            BIT_4_7	/* CUC 4-bit Mask */
-#define SCB_CUC_NOOP            0
-#define SCB_CUC_START           BIT_4	/* CU Start */
-#define SCB_CUC_RESUME          BIT_5	/* CU Resume */
-#define SCB_CUC_UNKNOWN         BIT_7	/* CU unknown command */
-/* Changed for 82558 enhancements */
-#define SCB_CUC_STATIC_RESUME   (BIT_5 | BIT_7)	/* 82558/9 Static Resume */
-#define SCB_CUC_DUMP_ADDR       BIT_6	/* CU Dump Counters Address */
-#define SCB_CUC_DUMP_STAT       (BIT_4 | BIT_6)	/* CU Dump stat. counters */
-#define SCB_CUC_LOAD_BASE       (BIT_5 | BIT_6)	/* Load the CU base */
-/* Below was defined as BIT_4_7 */
-#define SCB_CUC_DUMP_RST_STAT   BIT_4_6	/* CU Dump & reset statistics cntrs */
-
-/*- RUC fields */
-#define SCB_RUC_MASK            BIT_0_2	/* RUC 3-bit Mask */
-#define SCB_RUC_START           BIT_0	/* RU Start */
-#define SCB_RUC_RESUME          BIT_1	/* RU Resume */
-#define SCB_RUC_ABORT           BIT_2	/* RU Abort */
-#define SCB_RUC_LOAD_HDS        (BIT_0 | BIT_2)	/* Load RFD Header Data Size */
-#define SCB_RUC_LOAD_BASE       (BIT_1 | BIT_2)	/* Load the RU base */
-#define SCB_RUC_RBD_RESUME      BIT_0_2	/* RBD resume */
-
-/* Interrupt fields (assuming byte addressing) */
-#define SCB_INT_MASK            BIT_0	/* Mask interrupts */
-#define SCB_SOFT_INT            BIT_1	/* Generate a S/W interrupt */
-/*  Specific Interrupt Mask Bits (upper byte of SCB Command word) */
-#define SCB_FCP_INT_MASK        BIT_2	/* Flow Control Pause */
-#define SCB_ER_INT_MASK         BIT_3	/* Early Receive */
-#define SCB_RNR_INT_MASK        BIT_4	/* RU Not Ready */
-#define SCB_CNA_INT_MASK        BIT_5	/* CU Not Active */
-#define SCB_FR_INT_MASK         BIT_6	/* Frame Received */
-#define SCB_CX_INT_MASK         BIT_7	/* CU eXecution w/ I-bit done */
-#define SCB_BACHELOR_INT_MASK   BIT_2_7	/* 82558 interrupt mask bits */
-
-#define SCB_GCR2_EEPROM_ACCESS_SEMAPHORE BIT_7
-
-/* EEPROM bit definitions */
-/*- EEPROM control register bits */
-#define EEPROM_FLAG_ASF  0x8000
-#define EEPROM_FLAG_GCL  0x4000
-
-#define EN_TRNF          0x10	/* Enable turnoff */
-#define EEDO             0x08	/* EEPROM data out */
-#define EEDI             0x04	/* EEPROM data in (set for writing data) */
-#define EECS             0x02	/* EEPROM chip select (1=hi, 0=lo) */
-#define EESK             0x01	/* EEPROM shift clock (1=hi, 0=lo) */
-
-/*- EEPROM opcodes */
-#define EEPROM_READ_OPCODE          06
-#define EEPROM_WRITE_OPCODE         05
-#define EEPROM_ERASE_OPCODE         07
-#define EEPROM_EWEN_OPCODE          19	/* Erase/write enable */
-#define EEPROM_EWDS_OPCODE          16	/* Erase/write disable */
-
-/*- EEPROM data locations */
-#define EEPROM_NODE_ADDRESS_BYTE_0      0
-#define EEPROM_COMPATIBILITY_WORD       3
-#define EEPROM_PWA_NO                   8
-#define EEPROM_ID_WORD			0x0A
-#define EEPROM_CONFIG_ASF		0x0D
-#define EEPROM_SMBUS_ADDR		0x90
-
-#define EEPROM_SUM                      0xbaba
-
-// Zero Locking Algorithm definitions:
-#define ZLOCK_ZERO_MASK		0x00F0
-#define ZLOCK_MAX_READS		50	
-#define ZLOCK_SET_ZERO		0x2010
-#define ZLOCK_MAX_SLEEP		300 * HZ	
-#define ZLOCK_MAX_ERRORS	300
-
-/* E100 Action Commands */
-#define CB_IA_ADDRESS           1
-#define CB_CONFIGURE            2
-#define CB_MULTICAST            3
-#define CB_TRANSMIT             4
-#define CB_LOAD_MICROCODE       5
-#define CB_LOAD_FILTER		8
-#define CB_MAX_NONTX_CMD        9
-#define CB_IPCB_TRANSMIT        9
-
-/* Pre-defined Filter Bits */
-#define CB_FILTER_EL            0x80000000
-#define CB_FILTER_FIX           0x40000000
-#define CB_FILTER_ARP           0x08000000
-#define CB_FILTER_IA_MATCH      0x02000000
-
-/* Command Block (CB) Field Definitions */
-/*- CB Command Word */
-#define CB_EL_BIT           BIT_15	/* CB EL Bit */
-#define CB_S_BIT            BIT_14	/* CB Suspend Bit */
-#define CB_I_BIT            BIT_13	/* CB Interrupt Bit */
-#define CB_TX_SF_BIT        BIT_3	/* TX CB Flexible Mode */
-#define CB_CMD_MASK         BIT_0_3	/* CB 4-bit CMD Mask */
-#define CB_CID_DEFAULT      (0x1f << 8)	/* CB 5-bit CID (max value) */
-
-/*- CB Status Word */
-#define CB_STATUS_MASK          BIT_12_15	/* CB Status Mask (4-bits) */
-#define CB_STATUS_COMPLETE      BIT_15	/* CB Complete Bit */
-#define CB_STATUS_OK            BIT_13	/* CB OK Bit */
-#define CB_STATUS_VLAN          BIT_12 /* CB Valn detected Bit */
-#define CB_STATUS_FAIL          BIT_11	/* CB Fail (F) Bit */
-
-/*misc command bits */
-#define CB_TX_EOF_BIT           BIT_15	/* TX CB/TBD EOF Bit */
-
-/* Config params */
-#define CB_CFIG_BYTE_COUNT          22	/* 22 config bytes */
-#define CB_CFIG_D102_BYTE_COUNT    10
-
-/* Receive Frame Descriptor Fields */
-
-/*- RFD Status Bits */
-#define RFD_RECEIVE_COLLISION   BIT_0	/* Collision detected on Receive */
-#define RFD_IA_MATCH            BIT_1	/* Indv Address Match Bit */
-#define RFD_RX_ERR              BIT_4	/* RX_ERR pin on Phy was set */
-#define RFD_FRAME_TOO_SHORT     BIT_7	/* Receive Frame Short */
-#define RFD_DMA_OVERRUN         BIT_8	/* Receive DMA Overrun */
-#define RFD_NO_RESOURCES        BIT_9	/* No Buffer Space */
-#define RFD_ALIGNMENT_ERROR     BIT_10	/* Alignment Error */
-#define RFD_CRC_ERROR           BIT_11	/* CRC Error */
-#define RFD_STATUS_OK           BIT_13	/* RFD OK Bit */
-#define RFD_STATUS_COMPLETE     BIT_15	/* RFD Complete Bit */
-
-/*- RFD Command Bits*/
-#define RFD_EL_BIT      BIT_15	/* RFD EL Bit */
-#define RFD_S_BIT       BIT_14	/* RFD Suspend Bit */
-#define RFD_H_BIT       BIT_4	/* Header RFD Bit */
-#define RFD_SF_BIT      BIT_3	/* RFD Flexible Mode */
-
-/*- RFD misc bits*/
-#define RFD_EOF_BIT         BIT_15	/* RFD End-Of-Frame Bit */
-#define RFD_F_BIT           BIT_14	/* RFD Buffer Fetch Bit */
-#define RFD_ACT_COUNT_MASK  BIT_0_13	/* RFD Actual Count Mask */
-
-/* Receive Buffer Descriptor Fields*/
-#define RBD_EOF_BIT             BIT_15	/* RBD End-Of-Frame Bit */
-#define RBD_F_BIT               BIT_14	/* RBD Buffer Fetch Bit */
-#define RBD_ACT_COUNT_MASK      BIT_0_13	/* RBD Actual Count Mask */
-
-#define SIZE_FIELD_MASK     BIT_0_13	/* Size of the associated buffer */
-#define RBD_EL_BIT          BIT_15	/* RBD EL Bit */
-
-/* Self Test Results*/
-#define CB_SELFTEST_FAIL_BIT        BIT_12
-#define CB_SELFTEST_DIAG_BIT        BIT_5
-#define CB_SELFTEST_REGISTER_BIT    BIT_3
-#define CB_SELFTEST_ROM_BIT         BIT_2
-
-#define CB_SELFTEST_ERROR_MASK ( \
-                CB_SELFTEST_FAIL_BIT | CB_SELFTEST_DIAG_BIT | \
-                CB_SELFTEST_REGISTER_BIT | CB_SELFTEST_ROM_BIT)
-
-/* adapter vendor & device ids */
-#define PCI_OHIO_BOARD   0x10f0	/* subdevice ID, Ohio dual port nic */
-
-/* Values for PCI_REV_ID_REGISTER values */
-#define D101A4_REV_ID      4	/* 82558 A4 stepping */
-#define D101B0_REV_ID      5	/* 82558 B0 stepping */
-#define D101MA_REV_ID      8	/* 82559 A0 stepping */
-#define D101S_REV_ID      9	/* 82559S A-step */
-#define D102_REV_ID      12
-#define D102C_REV_ID     13	/* 82550 step C */
-#define D102E_REV_ID     15
-
-/* ############Start of 82555 specific defines################## */
-
-#define PHY_82555_LED_SWITCH_CONTROL    	0x1b	/* 82555 led switch control register */
-
-/* 82555 led switch control reg. opcodes */
-#define PHY_82555_LED_NORMAL_CONTROL    0	// control back to the 8255X
-#define PHY_82555_LED_DRIVER_CONTROL    BIT_2	// the driver is in control
-#define PHY_82555_LED_OFF               BIT_2	// activity LED is off
-#define PHY_82555_LED_ON_559           (BIT_0 | BIT_2)	// activity LED is on for 559 and later
-#define PHY_82555_LED_ON_PRE_559       (BIT_0 | BIT_1 | BIT_2)	// activity LED is on for 558 and before
-
-// Describe the state of the phy led.
-// needed for the function : 'e100_blink_timer'
-enum led_state_e {
-	LED_OFF = 0,
-	LED_ON,
-};
-
-/* ############End of 82555 specific defines##################### */
-
-#define RFD_PARSE_BIT			BIT_3
-#define RFD_TCP_PACKET			0x00
-#define RFD_UDP_PACKET			0x01
-#define TCPUDP_CHECKSUM_BIT_VALID	BIT_4
-#define TCPUDP_CHECKSUM_VALID		BIT_5
-#define CHECKSUM_PROTOCOL_MASK		0x03
-
-#define VLAN_SIZE   4
-#define CHKSUM_SIZE 2
-#define RFD_DATA_SIZE (ETH_FRAME_LEN + CHKSUM_SIZE + VLAN_SIZE)
-
-/* Bits for bdp->flags */
-#define DF_LINK_FC_CAP     0x00000001	/* Link is flow control capable */
-#define DF_CSUM_OFFLOAD    0x00000002
-#define DF_UCODE_LOADED    0x00000004
-#define USE_IPCB           0x00000008	/* set if using ipcb for transmits */
-#define IS_BACHELOR        0x00000010	/* set if 82558 or newer board */
-#define IS_ICH             0x00000020
-#define DF_SPEED_FORCED    0x00000040	/* set if speed is forced */
-#define LED_IS_ON	   0x00000080	/* LED is turned ON by the driver */
-#define DF_LINK_FC_TX_ONLY 0x00000100	/* Received PAUSE frames are honored*/
-
-typedef struct net_device_stats net_dev_stats_t;
-
-/* needed macros */
-/* These macros use the bdp pointer. If you use them it better be defined */
-#define PREV_TCB_USED(X)  ((X).tail ? (X).tail - 1 : bdp->params.TxDescriptors - 1)
-#define NEXT_TCB_TOUSE(X) ((((X) + 1) >= bdp->params.TxDescriptors) ? 0 : (X) + 1)
-#define TCB_TO_USE(X)     ((X).tail)
-#define TCBS_AVAIL(X)     (NEXT_TCB_TOUSE( NEXT_TCB_TOUSE((X).tail)) != (X).head)
-
-#define RFD_POINTER(skb,bdp)      ((rfd_t *) (((unsigned char *)((skb)->data))-((bdp)->rfd_size)))
-#define SKB_RFD_STATUS(skb,bdp)   ((RFD_POINTER((skb),(bdp)))->rfd_header.cb_status)
-
-/* ====================================================================== */
-/*                              82557                                     */
-/* ====================================================================== */
-
-/* Changed for 82558 enhancement */
-typedef struct _d101_scb_ext_t {
-	u32 scb_rx_dma_cnt;	/* Rx DMA byte count */
-	u8 scb_early_rx_int;	/* Early Rx DMA byte count */
-	u8 scb_fc_thld;	/* Flow Control threshold */
-	u8 scb_fc_xon_xoff;	/* Flow Control XON/XOFF values */
-	u8 scb_pmdr;	/* Power Mgmt. Driver Reg */
-} d101_scb_ext __attribute__ ((__packed__));
-
-/* Changed for 82559 enhancement */
-typedef struct _d101m_scb_ext_t {
-	u32 scb_rx_dma_cnt;	/* Rx DMA byte count */
-	u8 scb_early_rx_int;	/* Early Rx DMA byte count */
-	u8 scb_fc_thld;	/* Flow Control threshold */
-	u8 scb_fc_xon_xoff;	/* Flow Control XON/XOFF values */
-	u8 scb_pmdr;	/* Power Mgmt. Driver Reg */
-	u8 scb_gen_ctrl;	/* General Control */
-	u8 scb_gen_stat;	/* General Status */
-	u16 scb_reserved;	/* Reserved */
-	u32 scb_function_event;	/* Cardbus Function Event */
-	u32 scb_function_event_mask;	/* Cardbus Function Mask */
-	u32 scb_function_present_state;	/* Cardbus Function state */
-	u32 scb_force_event;	/* Cardbus Force Event */
-} d101m_scb_ext __attribute__ ((__packed__));
-
-/* Changed for 82550 enhancement */
-typedef struct _d102_scb_ext_t {
-	u32 scb_rx_dma_cnt;	/* Rx DMA byte count */
-	u8 scb_early_rx_int;	/* Early Rx DMA byte count */
-	u8 scb_fc_thld;	/* Flow Control threshold */
-	u8 scb_fc_xon_xoff;	/* Flow Control XON/XOFF values */
-	u8 scb_pmdr;	/* Power Mgmt. Driver Reg */
-	u8 scb_gen_ctrl;	/* General Control */
-	u8 scb_gen_stat;	/* General Status */
-	u8 scb_gen_ctrl2;
-	u8 scb_reserved;	/* Reserved */
-	u32 scb_scheduling_reg;
-	u32 scb_reserved2;
-	u32 scb_function_event;	/* Cardbus Function Event */
-	u32 scb_function_event_mask;	/* Cardbus Function Mask */
-	u32 scb_function_present_state;	/* Cardbus Function state */
-	u32 scb_force_event;	/* Cardbus Force Event */
-} d102_scb_ext __attribute__ ((__packed__));
-
-/*
- * 82557 status control block. this will be memory mapped & will hang of the
- * the bdp, which hangs of the bdp. This is the brain of it.
- */
-typedef struct _scb_t {
-	u16 scb_status;	/* SCB Status register */
-	u8 scb_cmd_low;	/* SCB Command register (low byte) */
-	u8 scb_cmd_hi;	/* SCB Command register (high byte) */
-	u32 scb_gen_ptr;	/* SCB General pointer */
-	u32 scb_port;	/* PORT register */
-	u16 scb_flsh_cntrl;	/* Flash Control register */
-	u16 scb_eprm_cntrl;	/* EEPROM control register */
-	u32 scb_mdi_cntrl;	/* MDI Control Register */
-	/* Changed for 82558 enhancement */
-	union {
-		u32 scb_rx_dma_cnt;	/* Rx DMA byte count */
-		d101_scb_ext d101_scb;	/* 82558/9 specific fields */
-		d101m_scb_ext d101m_scb;	/* 82559 specific fields */
-		d102_scb_ext d102_scb;
-	} scb_ext;
-} scb_t __attribute__ ((__packed__));
-
-/* Self test
- * This is used to dump results of the self test 
- */
-typedef struct _self_test_t {
-	u32 st_sign;	/* Self Test Signature */
-	u32 st_result;	/* Self Test Results */
-} self_test_t __attribute__ ((__packed__));
-
-/* 
- *  Statistical Counters 
- */
-/* 82557 counters */
-typedef struct _basic_cntr_t {
-	u32 xmt_gd_frames;	/* Good frames transmitted */
-	u32 xmt_max_coll;	/* Fatal frames -- had max collisions */
-	u32 xmt_late_coll;	/* Fatal frames -- had a late coll. */
-	u32 xmt_uruns;	/* Xmit underruns (fatal or re-transmit) */
-	u32 xmt_lost_crs;	/* Frames transmitted without CRS */
-	u32 xmt_deferred;	/* Deferred transmits */
-	u32 xmt_sngl_coll;	/* Transmits that had 1 and only 1 coll. */
-	u32 xmt_mlt_coll;	/* Transmits that had multiple coll. */
-	u32 xmt_ttl_coll;	/* Transmits that had 1+ collisions. */
-	u32 rcv_gd_frames;	/* Good frames received */
-	u32 rcv_crc_errs;	/* Aligned frames that had a CRC error */
-	u32 rcv_algn_errs;	/* Receives that had alignment errors */
-	u32 rcv_rsrc_err;	/* Good frame dropped cuz no resources */
-	u32 rcv_oruns;	/* Overrun errors - bus was busy */
-	u32 rcv_err_coll;	/* Received frms. that encountered coll. */
-	u32 rcv_shrt_frames;	/* Received frames that were to short */
-} basic_cntr_t;
-
-/* 82558 extended statistic counters */
-typedef struct _ext_cntr_t {
-	u32 xmt_fc_frames;
-	u32 rcv_fc_frames;
-	u32 rcv_fc_unsupported;
-} ext_cntr_t;
-
-/* 82559 TCO statistic counters */
-typedef struct _tco_cntr_t {
-	u16 xmt_tco_frames;
-	u16 rcv_tco_frames;
-} tco_cntr_t;
-
-/* Structures to access thet physical dump area */
-/* Use one of these types, according to the statisitcal counters mode,
-   to cast the pointer to the physical dump area and access the cmd_complete
-   DWORD. */
-
-/* 557-mode : only basic counters + cmd_complete */
-typedef struct _err_cntr_557_t {
-	basic_cntr_t basic_stats;
-	u32 cmd_complete;
-} err_cntr_557_t;
-
-/* 558-mode : basic + extended counters + cmd_complete */
-typedef struct _err_cntr_558_t {
-	basic_cntr_t basic_stats;
-	ext_cntr_t extended_stats;
-	u32 cmd_complete;
-} err_cntr_558_t;
-
-/* 559-mode : basic + extended + TCO counters + cmd_complete */
-typedef struct _err_cntr_559_t {
-	basic_cntr_t basic_stats;
-	ext_cntr_t extended_stats;
-	tco_cntr_t tco_stats;
-	u32 cmd_complete;
-} err_cntr_559_t;
-
-/* This typedef defines the struct needed to hold the largest number of counters */
-typedef err_cntr_559_t max_counters_t;
-
-/* Different statistical-counters mode the controller may be in */
-typedef enum _stat_mode_t {
-	E100_BASIC_STATS = 0,	/* 82557 stats : 16 counters / 16 dw */
-	E100_EXTENDED_STATS,	/* 82558 stats : 19 counters / 19 dw */
-	E100_TCO_STATS		/* 82559 stats : 21 counters / 20 dw */
-} stat_mode_t;
-
-/* dump statistical counters complete codes */
-#define DUMP_STAT_COMPLETED	0xA005
-#define DUMP_RST_STAT_COMPLETED	0xA007
-
-/* Command Block (CB) Generic Header Structure*/
-typedef struct _cb_header_t {
-	u16 cb_status;	/* Command Block Status */
-	u16 cb_cmd;	/* Command Block Command */
-	u32 cb_lnk_ptr;	/* Link To Next CB */
-} cb_header_t __attribute__ ((__packed__));
-
-//* Individual Address Command Block (IA_CB)*/
-typedef struct _ia_cb_t {
-	cb_header_t ia_cb_hdr;
-	u8 ia_addr[ETH_ALEN];
-} ia_cb_t __attribute__ ((__packed__));
-
-/* Configure Command Block (CONFIG_CB)*/
-typedef struct _config_cb_t {
-	cb_header_t cfg_cbhdr;
-	u8 cfg_byte[CB_CFIG_BYTE_COUNT + CB_CFIG_D102_BYTE_COUNT];
-} config_cb_t __attribute__ ((__packed__));
-
-/* MultiCast Command Block (MULTICAST_CB)*/
-typedef struct _multicast_cb_t {
-	cb_header_t mc_cbhdr;
-	u16 mc_count;	/* Number of multicast addresses */
-	u8 mc_addr[(ETH_ALEN * MAX_MULTICAST_ADDRS)];
-} mltcst_cb_t __attribute__ ((__packed__));
-
-#define UCODE_MAX_DWORDS	134
-/* Load Microcode Command Block (LOAD_UCODE_CB)*/
-typedef struct _load_ucode_cb_t {
-	cb_header_t load_ucode_cbhdr;
-	u32 ucode_dword[UCODE_MAX_DWORDS];
-} load_ucode_cb_t __attribute__ ((__packed__));
-
-/* Load Programmable Filter Data*/
-typedef struct _filter_cb_t {
-	cb_header_t filter_cb_hdr;
-	u32 filter_data[MAX_FILTER];
-} filter_cb_t __attribute__ ((__packed__));
-
-/* NON_TRANSMIT_CB -- Generic Non-Transmit Command Block 
- */
-typedef struct _nxmit_cb_t {
-	union {
-		config_cb_t config;
-		ia_cb_t setup;
-		load_ucode_cb_t load_ucode;
-		mltcst_cb_t multicast;
-		filter_cb_t filter;
-	} ntcb;
-} nxmit_cb_t __attribute__ ((__packed__));
-
-/*Block for queuing for postponed execution of the non-transmit commands*/
-typedef struct _nxmit_cb_entry_t {
-	struct list_head list_elem;
-	nxmit_cb_t *non_tx_cmd;
-	dma_addr_t dma_addr;
-	unsigned long expiration_time;
-} nxmit_cb_entry_t;
-
-/* States for postponed non tx commands execution */
-typedef enum _non_tx_cmd_state_t {
-	E100_NON_TX_IDLE = 0,	/* No queued NON-TX commands */
-	E100_WAIT_TX_FINISH,	/* Wait for completion of the TX activities */
-	E100_WAIT_NON_TX_FINISH	/* Wait for completion of the non TX command */
-} non_tx_cmd_state_t;
-
-/* some defines for the ipcb */
-#define IPCB_IP_CHECKSUM_ENABLE 	BIT_4
-#define IPCB_TCPUDP_CHECKSUM_ENABLE	BIT_5
-#define IPCB_TCP_PACKET 		BIT_6
-#define IPCB_LARGESEND_ENABLE 		BIT_7
-#define IPCB_HARDWAREPARSING_ENABLE	BIT_0
-#define IPCB_INSERTVLAN_ENABLE 		BIT_1
-#define IPCB_IP_ACTIVATION_DEFAULT      IPCB_HARDWAREPARSING_ENABLE
-
-/* Transmit Buffer Descriptor (TBD)*/
-typedef struct _tbd_t {
-	u32 tbd_buf_addr;	/* Physical Transmit Buffer Address */
-	u16 tbd_buf_cnt;	/* Actual Count Of Bytes */
-	u16 padd;
-} tbd_t __attribute__ ((__packed__));
-
-/* d102 specific fields */
-typedef struct _tcb_ipcb_t {
-	u16 schedule_low;
-	u8 ip_schedule;
-	u8 ip_activation_high;
-	u16 vlan;
-	u8 ip_header_offset;
-	u8 tcp_header_offset;
-	union {
-		u32 sec_rec_phys_addr;
-		u32 tbd_zero_address;
-	} tbd_sec_addr;
-	union {
-		u16 sec_rec_size;
-		u16 tbd_zero_size;
-	} tbd_sec_size;
-	u16 total_tcp_payload;
-} tcb_ipcb_t __attribute__ ((__packed__));
-
-#define E100_TBD_ARRAY_SIZE (2+MAX_SKB_FRAGS)
-
-/* Transmit Command Block (TCB)*/
-struct _tcb_t {
-	cb_header_t tcb_hdr;
-	u32 tcb_tbd_ptr;	/* TBD address */
-	u16 tcb_cnt;	/* Data Bytes In TCB past header */
-	u8 tcb_thrshld;	/* TX Threshold for FIFO Extender */
-	u8 tcb_tbd_num;
-
-	union {
-		tcb_ipcb_t ipcb;	/* d102 ipcb fields */
-		tbd_t tbd_array[E100_TBD_ARRAY_SIZE];
-	} tcbu;
-
-	/* From here onward we can dump anything we want as long as the
-	 * size of the total structure is a multiple of a paragraph
-	 * boundary ( i.e. -16 bit aligned ).
-	 */
-	tbd_t *tbd_ptr;
-
-	u32 tcb_tbd_dflt_ptr;	/* TBD address for non-segmented packet */
-	u32 tcb_tbd_expand_ptr;	/* TBD address for segmented packet */
-
-	struct sk_buff *tcb_skb;	/* the associated socket buffer */
-	dma_addr_t tcb_phys;	/* phys addr of the TCB */
-} __attribute__ ((__packed__));
-
-#define _TCB_T_
-typedef struct _tcb_t tcb_t;
-
-/* Receive Frame Descriptor (RFD) - will be using the simple model*/
-struct _rfd_t {
-	/* 8255x */
-	cb_header_t rfd_header;
-	u32 rfd_rbd_ptr;	/* Receive Buffer Descriptor Addr */
-	u16 rfd_act_cnt;	/* Number Of Bytes Received */
-	u16 rfd_sz;	/* Number Of Bytes In RFD */
-	/* D102 aka Gamla */
-	u16 vlanid;
-	u8 rcvparserstatus;
-	u8 reserved;
-	u16 securitystatus;
-	u8 checksumstatus;
-	u8 zerocopystatus;
-	u8 pad[8];	/* data should be 16 byte aligned */
-	u8 data[RFD_DATA_SIZE];
-
-} __attribute__ ((__packed__));
-
-#define _RFD_T_
-typedef struct _rfd_t rfd_t;
-
-/* Receive Buffer Descriptor (RBD)*/
-typedef struct _rbd_t {
-	u16 rbd_act_cnt;	/* Number Of Bytes Received */
-	u16 rbd_filler;
-	u32 rbd_lnk_addr;	/* Link To Next RBD */
-	u32 rbd_rcb_addr;	/* Receive Buffer Address */
-	u16 rbd_sz;	/* Receive Buffer Size */
-	u16 rbd_filler1;
-} rbd_t __attribute__ ((__packed__));
-
-/*
- * This structure is used to maintain a FIFO access to a resource that is 
- * maintained as a circular queue. The resource to be maintained is pointed
- * to by the "data" field in the structure below. In this driver the TCBs', 
- * TBDs' & RFDs' are maintained  as a circular queue & are managed thru this
- * structure.
- */
-typedef struct _buf_pool_t {
-	unsigned int head;	/* index to first used resource */
-	unsigned int tail;	/* index to last used resource */
-	void *data;		/* points to resource pool */
-} buf_pool_t;
-
-/*Rx skb holding structure*/
-struct rx_list_elem {
-	struct list_head list_elem;
-	dma_addr_t dma_addr;
-	struct sk_buff *skb;
-};
-
-enum next_cu_cmd_e { RESUME_NO_WAIT = 0, RESUME_WAIT, START_WAIT };
-enum zlock_state_e { ZLOCK_INITIAL, ZLOCK_READING, ZLOCK_SLEEPING };
-enum tx_queue_stop_type { LONG_STOP = 0, SHORT_STOP };
-
-/* 64 bit aligned size */
-#define E100_SIZE_64A(X) ((sizeof(X) + 7) & ~0x7)
-
-typedef struct _bd_dma_able_t {
-	char selftest[E100_SIZE_64A(self_test_t)];
-	char stats_counters[E100_SIZE_64A(max_counters_t)];
-} bd_dma_able_t;
-
-/* bit masks for bool parameters */
-#define PRM_XSUMRX       0x00000001
-#define PRM_UCODE        0x00000002
-#define PRM_FC           0x00000004
-#define PRM_IFS          0x00000008
-#define PRM_BUNDLE_SMALL 0x00000010
-
-struct cfg_params {
-	int e100_speed_duplex;
-	int RxDescriptors;
-	int TxDescriptors;
-	int IntDelay;
-	int BundleMax;
-	int ber;
-	u32 b_params;
-};
-struct ethtool_lpbk_data{
-        dma_addr_t dma_handle;
-        tcb_t *tcb;
-        rfd_t *rfd;
-
-};
-
-struct e100_private {
-	struct vlan_group *vlgrp;
-	u32 flags;		/* board management flags */
-	u32 tx_per_underrun;	/* number of good tx frames per underrun */
-	unsigned int tx_count;	/* count of tx frames, so we can request an interrupt */
-	u8 tx_thld;		/* stores transmit threshold */
-	u16 eeprom_size;
-	u32 pwa_no;		/* PWA: xxxxxx-0xx */
-	u8 perm_node_address[ETH_ALEN];
-	struct list_head active_rx_list;	/* list of rx buffers */
-	struct list_head rx_struct_pool;	/* pool of rx buffer struct headers */
-	u16 rfd_size;			/* size of the adapter's RFD struct */
-	int skb_req;			/* number of skbs neede by the adapter */
-	u8 intr_mask;			/* mask for interrupt status */
-
-	void *dma_able;			/* dma allocated structs */
-	dma_addr_t dma_able_phys;
-	self_test_t *selftest;		/* pointer to self test area */
-	dma_addr_t selftest_phys;	/* phys addr of selftest */
-	max_counters_t *stats_counters;	/* pointer to stats table */
-	dma_addr_t stat_cnt_phys;	/* phys addr of stat counter area */
-
-	stat_mode_t stat_mode;	/* statistics mode: extended, TCO, basic */
-	scb_t *scb;		/* memory mapped ptr to 82557 scb */
-
-	tcb_t *last_tcb;	/* pointer to last tcb sent */
-	buf_pool_t tcb_pool;	/* adapter's TCB array */
-	dma_addr_t tcb_phys;	/* phys addr of start of TCBs */
-
-	u16 cur_line_speed;
-	u16 cur_dplx_mode;
-
-	struct net_device *device;
-	struct pci_dev *pdev;
-	struct driver_stats drv_stats;
-
-	u8 rev_id;		/* adapter PCI revision ID */
-
-	unsigned int phy_addr;	/* address of PHY component */
-	unsigned int PhyId;	/* ID of PHY component */
-	unsigned int PhyState;	/* state for the fix squelch algorithm */
-	unsigned int PhyDelay;	/* delay for the fix squelch algorithm */
-
-	/* Lock defintions for the driver */
-	spinlock_t bd_lock;		/* board lock */
-	spinlock_t bd_non_tx_lock;	/* Non transmit command lock  */
-	spinlock_t config_lock;		/* config block lock */
-	spinlock_t mdi_access_lock;	/* mdi lock */
-
-	struct timer_list watchdog_timer;	/* watchdog timer id */
-
-	/* non-tx commands parameters */
-	struct timer_list nontx_timer_id;	/* non-tx timer id */
-	struct list_head non_tx_cmd_list;
-	non_tx_cmd_state_t non_tx_command_state;
-	nxmit_cb_entry_t *same_cmd_entry[CB_MAX_NONTX_CMD];
-
-	enum next_cu_cmd_e next_cu_cmd;
-
-	/* Zero Locking Algorithm data members */
-	enum zlock_state_e zlock_state;
-	u8 zlock_read_data[16];	/* number of times each value 0-15 was read */
-	u16 zlock_read_cnt;	/* counts number of reads */
-	ulong zlock_sleep_cnt;	/* keeps track of "sleep" time */
-
-	u8 config[CB_CFIG_BYTE_COUNT + CB_CFIG_D102_BYTE_COUNT];
-
-	/* IFS params */
-	u8 ifs_state;
-	u8 ifs_value;
-
-	struct cfg_params params;	/* adapter's command line parameters */
-
-	u32 speed_duplex_caps;	/* adapter's speed/duplex capabilities */
-
-	/* WOL params for ethtool */
-	u32 wolsupported;
-	u32 wolopts;
-	u16 ip_lbytes;
-	struct ethtool_lpbk_data loopback;
-	struct timer_list blink_timer;	/* led blink timer id */
-
-#ifdef CONFIG_PM
-	u32 pci_state[16];
-#endif
-#ifdef E100_CU_DEBUG	
-	u8 last_cmd;
-	u8 last_sub_cmd;
-#endif	
-};
-
-#define E100_AUTONEG        0
-#define E100_SPEED_10_HALF  1
-#define E100_SPEED_10_FULL  2
-#define E100_SPEED_100_HALF 3
-#define E100_SPEED_100_FULL 4
-
-/********* function prototypes *************/
-extern int e100_open(struct net_device *);
-extern int e100_close(struct net_device *);
-extern void e100_isolate_driver(struct e100_private *bdp);
-extern unsigned char e100_hw_init(struct e100_private *);
-extern void e100_sw_reset(struct e100_private *bdp, u32 reset_cmd);
-extern u8 e100_start_cu(struct e100_private *bdp, tcb_t *tcb);
-extern void e100_free_non_tx_cmd(struct e100_private *bdp,
-				 nxmit_cb_entry_t *non_tx_cmd);
-extern nxmit_cb_entry_t *e100_alloc_non_tx_cmd(struct e100_private *bdp);
-extern unsigned char e100_exec_non_cu_cmd(struct e100_private *bdp,
-					  nxmit_cb_entry_t *cmd);
-extern unsigned char e100_selftest(struct e100_private *bdp, u32 *st_timeout,
-				   u32 *st_result);
-extern unsigned char e100_get_link_state(struct e100_private *bdp);
-extern unsigned char e100_wait_scb(struct e100_private *bdp);
-
-extern void e100_deisolate_driver(struct e100_private *bdp, u8 full_reset);
-extern unsigned char e100_configure_device(struct e100_private *bdp);
-#ifdef E100_CU_DEBUG
-extern unsigned char e100_cu_unknown_state(struct e100_private *bdp);
-#endif
-
-#define ROM_TEST_FAIL		0x01
-#define REGISTER_TEST_FAIL	0x02
-#define SELF_TEST_FAIL		0x04
-#define TEST_TIMEOUT		0x08
-
-enum test_offsets {
-	test_link,
-	test_eeprom,
-	test_self_test,
-	test_loopback_mac,
-	test_loopback_phy,
-	cable_diag,
-	max_test_res,  /* must be last */
-};
-
-#endif
--- diff/drivers/net/e100/e100_config.c	2004-01-19 10:22:57.000000000 +0000
+++ source/drivers/net/e100/e100_config.c	1970-01-01 01:00:00.000000000 +0100
@@ -1,639 +0,0 @@
-/*******************************************************************************
-
-  
-  Copyright(c) 1999 - 2003 Intel Corporation. All rights reserved.
-  
-  This program is free software; you can redistribute it and/or modify it 
-  under the terms of the GNU General Public License as published by the Free 
-  Software Foundation; either version 2 of the License, or (at your option) 
-  any later version.
-  
-  This program is distributed in the hope that it will be useful, but WITHOUT 
-  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 
-  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for 
-  more details.
-  
-  You should have received a copy of the GNU General Public License along with
-  this program; if not, write to the Free Software Foundation, Inc., 59 
-  Temple Place - Suite 330, Boston, MA  02111-1307, USA.
-  
-  The full GNU General Public License is included in this distribution in the
-  file called LICENSE.
-  
-  Contact Information:
-  Linux NICS <linux.nics@intel.com>
-  Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
-*******************************************************************************/
-
-/**********************************************************************
-*                                                                     *
-* INTEL CORPORATION                                                   *
-*                                                                     *
-* This software is supplied under the terms of the license included   *
-* above.  All use of this driver must be in accordance with the terms *
-* of that license.                                                    *
-*                                                                     *
-* Module Name:  e100_config.c                                         *
-*                                                                     *
-* Abstract:     Functions for configuring the network adapter.        *
-*                                                                     *
-* Environment:  This file is intended to be specific to the Linux     *
-*               operating system.                                     *
-*                                                                     *
-**********************************************************************/
-#include "e100_config.h"
-
-static void e100_config_long_rx(struct e100_private *bdp, unsigned char enable);
-
-static const u8 def_config[] = {
-	CB_CFIG_BYTE_COUNT,
-	0x08, 0x00, 0x00, 0x00, 0x00, 0x32, 0x07, 0x01,
-	0x00, 0x2e, 0x00, 0x60, 0x00, 0xf2, 0xc8, 0x00,
-	0x40, 0xf2, 0x80, 0x3f, 0x05
-};
-
-/**
- * e100_config_init_82557 - config the 82557 adapter
- * @bdp: atapter's private data struct
- *
- * This routine will initialize the 82557 configure block.
- * All other init functions will only set values that are
- * different from the 82557 default.
- */
-void
-e100_config_init_82557(struct e100_private *bdp)
-{
-	/* initialize config block */
-	memcpy(bdp->config, def_config, sizeof (def_config));
-	bdp->config[0] = CB_CFIG_BYTE_COUNT;	/* just in case */
-
-	e100_config_ifs(bdp);
-
-	/*
-	 * Enable extended statistical counters (82558 and up) and TCO counters
-	 * (82559 and up) and set the statistical counters' mode in bdp 
-	 *  
-	 *  stat. mode      |    TCO stat. bit (2)  |  Extended stat. bit (5)
-	 * ------------------------------------------------------------------
-	 *  Basic (557)     |       0               |         1
-	 * ------------------------------------------------------------------
-	 *  Extended (558)  |       0               |         0
-	 * ------------------------------------------------------------------
-	 *  TCO (559)       |       1               |         1
-	 * ------------------------------------------------------------------
-	 *  Reserved        |       1               |         0
-	 * ------------------------------------------------------------------
-	 */
-	bdp->config[6] &= ~CB_CFIG_TCO_STAT;
-	bdp->config[6] |= CB_CFIG_EXT_STAT_DIS;
-	bdp->stat_mode = E100_BASIC_STATS;
-
-	/* Setup for MII or 503 operation.  The CRS+CDT bit should only be set */
-	/* when operating in 503 mode. */
-	if (bdp->phy_addr == 32) {
-		bdp->config[8] &= ~CB_CFIG_503_MII;
-		bdp->config[15] |= CB_CFIG_CRS_OR_CDT;
-	} else {
-		bdp->config[8] |= CB_CFIG_503_MII;
-		bdp->config[15] &= ~CB_CFIG_CRS_OR_CDT;
-	}
-
-	e100_config_fc(bdp);
-	e100_config_force_dplx(bdp);
-	e100_config_promisc(bdp, false);
-	e100_config_mulcast_enbl(bdp, false);
-}
-
-static void
-e100_config_init_82558(struct e100_private *bdp)
-{
-	/* MWI enable. This should be turned on only if the adapter is a 82558/9
-	 * and if the PCI command reg. has enabled the MWI bit. */
-	bdp->config[3] |= CB_CFIG_MWI_EN;
-
-	bdp->config[6] &= ~CB_CFIG_EXT_TCB_DIS;
-
-	if (bdp->rev_id >= D101MA_REV_ID) {
-		/* this is 82559 and up - enable TCO counters */
-		bdp->config[6] |= CB_CFIG_TCO_STAT;
-		bdp->config[6] |= CB_CFIG_EXT_STAT_DIS;
-		bdp->stat_mode = E100_TCO_STATS;
-
-		if ((bdp->rev_id < D102_REV_ID) &&
-		    (bdp->params.b_params & PRM_XSUMRX) &&
-		    (bdp->pdev->device != 0x1209)) {
-
-			bdp->flags |= DF_CSUM_OFFLOAD;
-			bdp->config[9] |= 1;
-		}
-	} else {
-		/* this is 82558 */
-		bdp->config[6] &= ~CB_CFIG_TCO_STAT;
-		bdp->config[6] &= ~CB_CFIG_EXT_STAT_DIS;
-		bdp->stat_mode = E100_EXTENDED_STATS;
-	}
-
-	e100_config_long_rx(bdp, true);
-}
-
-static void
-e100_config_init_82550(struct e100_private *bdp)
-{
-	/* The D102 chip allows for 32 config bytes.  This value is
-	 * supposed to be in Byte 0.  Just add the extra bytes to
-	 * what was already setup in the block. */
-	bdp->config[0] += CB_CFIG_D102_BYTE_COUNT;
-
-	/* now we need to enable the extended RFD.  When this is
-	 * enabled, the immediated receive data buffer starts at offset
-	 * 32 from the RFD base address, instead of at offset 16. */
-	bdp->config[7] |= CB_CFIG_EXTENDED_RFD;
-
-	/* put the chip into D102 receive mode.  This is necessary
-	 * for any parsing and offloading features. */
-	bdp->config[22] = CB_CFIG_RECEIVE_GAMLA_MODE;
-
-	/* set the flag if checksum offloading was enabled */
-	if (bdp->params.b_params & PRM_XSUMRX) {
-		bdp->flags |= DF_CSUM_OFFLOAD;
-	}
-}
-
-/* Initialize the adapter's configure block */
-void
-e100_config_init(struct e100_private *bdp)
-{
-	e100_config_init_82557(bdp);
-
-	if (bdp->flags & IS_BACHELOR)
-		e100_config_init_82558(bdp);
-
-	if (bdp->rev_id >= D102_REV_ID)
-		e100_config_init_82550(bdp);
-}
-
-/**
- * e100_force_config - force a configure command
- * @bdp: atapter's private data struct
- *
- * This routine will force a configure command to the adapter.
- * The command will be executed in polled mode as interrupts
- * are _disabled_ at this time.
- *
- * Returns:
- *      true: if the configure command was successfully issued and completed
- *      false: otherwise
- */
-unsigned char
-e100_force_config(struct e100_private *bdp)
-{
-	spin_lock_bh(&(bdp->config_lock));
-
-	bdp->config[0] = CB_CFIG_BYTE_COUNT;
-	if (bdp->rev_id >= D102_REV_ID) {
-		/* The D102 chip allows for 32 config bytes.  This value is
-		   supposed to be in Byte 0.  Just add the extra bytes to
-		   what was already setup in the block. */
-		bdp->config[0] += CB_CFIG_D102_BYTE_COUNT;
-	}
-
-	spin_unlock_bh(&(bdp->config_lock));
-
-	// although we call config outside the lock, there is no
-	// race condition because config byte count has maximum value
-	return e100_config(bdp);
-}
-
-/**
- * e100_config - issue a configure command
- * @bdp: atapter's private data struct
- *
- * This routine will issue a configure command to the 82557.
- * This command will be executed in polled mode as interrupts
- * are _disabled_ at this time.
- *
- * Returns:
- *      true: if the configure command was successfully issued and completed
- *      false: otherwise
- */
-unsigned char
-e100_config(struct e100_private *bdp)
-{
-	cb_header_t *pntcb_hdr;
-	unsigned char res = true;
-	nxmit_cb_entry_t *cmd;
-
-	if (bdp->config[0] == 0) {
-		goto exit;
-	}
-
-	if ((cmd = e100_alloc_non_tx_cmd(bdp)) == NULL) {
-		res = false;
-		goto exit;
-	}
-
-	pntcb_hdr = (cb_header_t *) cmd->non_tx_cmd;
-	pntcb_hdr->cb_cmd = __constant_cpu_to_le16(CB_CONFIGURE);
-
-	spin_lock_bh(&bdp->config_lock);
-
-	if (bdp->config[0] < CB_CFIG_MIN_PARAMS) {
-		bdp->config[0] = CB_CFIG_MIN_PARAMS;
-	}
-
-	/* Copy the device's config block to the device's memory */
-	memcpy(cmd->non_tx_cmd->ntcb.config.cfg_byte, bdp->config,
-	       bdp->config[0]);
-	/* reset number of bytes to config next time */
-	bdp->config[0] = 0;
-
-	spin_unlock_bh(&bdp->config_lock);
-
-	res = e100_exec_non_cu_cmd(bdp, cmd);
-
-exit:
-	if (netif_running(bdp->device))
-		netif_wake_queue(bdp->device);
-	return res;
-}
-
-/**
- * e100_config_fc - config flow-control state
- * @bdp: adapter's private data struct
- *
- * This routine will enable or disable flow control support in the adapter's
- * config block. Flow control will be enable only if requested using the command
- * line option, and if the link is flow-contorl capable (both us and the link
- * partner). But, if link partner is capable of autoneg, but not capable of
- * flow control, received PAUSE	frames are still honored.
- */
-void
-e100_config_fc(struct e100_private *bdp)
-{
-	unsigned char enable = false;
-	/* 82557 doesn't support fc. Don't touch this option */
-	if (!(bdp->flags & IS_BACHELOR))
-		return;
-
-	/* Enable fc if requested and if the link supports it */
-	if ((bdp->params.b_params & PRM_FC) && (bdp->flags & 
-		(DF_LINK_FC_CAP | DF_LINK_FC_TX_ONLY))) {
-		enable = true;
-	}
-
-	spin_lock_bh(&(bdp->config_lock));
-
-	if (enable) {
-		if (bdp->flags & DF_LINK_FC_TX_ONLY) {
-			/* If link partner is capable of autoneg, but  */
-			/* not capable of flow control, Received PAUSE */
-			/* frames are still honored, i.e.,             */
-			/* transmitted frames would be paused by       */
-			/* incoming PAUSE frames                       */
-			bdp->config[16] = DFLT_NO_FC_DELAY_LSB;
-			bdp->config[17] = DFLT_NO_FC_DELAY_MSB;
-			bdp->config[19] &= ~(CB_CFIG_FC_RESTOP | CB_CFIG_FC_RESTART);
-			bdp->config[19] |= CB_CFIG_FC_REJECT;
-			bdp->config[19] &= ~CB_CFIG_TX_FC_DIS;
-		} else {
-			bdp->config[16] = DFLT_FC_DELAY_LSB;
-			bdp->config[17] = DFLT_FC_DELAY_MSB;
-			bdp->config[19] |= CB_CFIG_FC_OPTS;
-			bdp->config[19] &= ~CB_CFIG_TX_FC_DIS;
-		}
-	} else {
-		bdp->config[16] = DFLT_NO_FC_DELAY_LSB;
-		bdp->config[17] = DFLT_NO_FC_DELAY_MSB;
-		bdp->config[19] &= ~CB_CFIG_FC_OPTS;
-		bdp->config[19] |= CB_CFIG_TX_FC_DIS;
-	}
-	E100_CONFIG(bdp, 19);
-	spin_unlock_bh(&(bdp->config_lock));
-
-	return;
-}
-
-/**
- * e100_config_promisc - configure promiscuous mode
- * @bdp: atapter's private data struct
- * @enable: should we enable this option or not
- *
- * This routine will enable or disable promiscuous mode
- * in the adapter's config block.
- */
-void
-e100_config_promisc(struct e100_private *bdp, unsigned char enable)
-{
-	spin_lock_bh(&(bdp->config_lock));
-
-	/* if in promiscuous mode, save bad frames */
-	if (enable) {
-
-		if (!(bdp->config[6] & CB_CFIG_SAVE_BAD_FRAMES)) {
-			bdp->config[6] |= CB_CFIG_SAVE_BAD_FRAMES;
-			E100_CONFIG(bdp, 6);
-		}
-
-		if (bdp->config[7] & (u8) BIT_0) {
-			bdp->config[7] &= (u8) (~BIT_0);
-			E100_CONFIG(bdp, 7);
-		}
-
-		if (!(bdp->config[15] & CB_CFIG_PROMISCUOUS)) {
-			bdp->config[15] |= CB_CFIG_PROMISCUOUS;
-			E100_CONFIG(bdp, 15);
-		}
-
-	} else {		/* not in promiscuous mode */
-
-		if (bdp->config[6] & CB_CFIG_SAVE_BAD_FRAMES) {
-			bdp->config[6] &= ~CB_CFIG_SAVE_BAD_FRAMES;
-			E100_CONFIG(bdp, 6);
-		}
-
-		if (!(bdp->config[7] & (u8) BIT_0)) {
-			bdp->config[7] |= (u8) (BIT_0);
-			E100_CONFIG(bdp, 7);
-		}
-
-		if (bdp->config[15] & CB_CFIG_PROMISCUOUS) {
-			bdp->config[15] &= ~CB_CFIG_PROMISCUOUS;
-			E100_CONFIG(bdp, 15);
-		}
-	}
-
-	spin_unlock_bh(&(bdp->config_lock));
-}
-
-/**
- * e100_config_mulcast_enbl - configure allmulti mode
- * @bdp: atapter's private data struct
- * @enable: should we enable this option or not
- *
- * This routine will enable or disable reception of all multicast packets
- * in the adapter's config block.
- */
-void
-e100_config_mulcast_enbl(struct e100_private *bdp, unsigned char enable)
-{
-	spin_lock_bh(&(bdp->config_lock));
-
-	/* this flag is used to enable receiving all multicast packet */
-	if (enable) {
-		if (!(bdp->config[21] & CB_CFIG_MULTICAST_ALL)) {
-			bdp->config[21] |= CB_CFIG_MULTICAST_ALL;
-			E100_CONFIG(bdp, 21);
-		}
-
-	} else {
-		if (bdp->config[21] & CB_CFIG_MULTICAST_ALL) {
-			bdp->config[21] &= ~CB_CFIG_MULTICAST_ALL;
-			E100_CONFIG(bdp, 21);
-		}
-	}
-
-	spin_unlock_bh(&(bdp->config_lock));
-}
-
-/**
- * e100_config_ifs - configure the IFS parameter
- * @bdp: atapter's private data struct
- *
- * This routine will configure the adaptive IFS value
- * in the adapter's config block. IFS values are only
- * relevant in half duplex, so set to 0 in full duplex.
- */
-void
-e100_config_ifs(struct e100_private *bdp)
-{
-	u8 value = 0;
-
-	spin_lock_bh(&(bdp->config_lock));
-
-	/* IFS value is only needed to be specified at half-duplex mode */
-	if (bdp->cur_dplx_mode == HALF_DUPLEX) {
-		value = (u8) bdp->ifs_value;
-	}
-
-	if (bdp->config[2] != value) {
-		bdp->config[2] = value;
-		E100_CONFIG(bdp, 2);
-	}
-
-	spin_unlock_bh(&(bdp->config_lock));
-}
-
-/**
- * e100_config_force_dplx - configure the forced full duplex mode
- * @bdp: atapter's private data struct
- *
- * This routine will enable or disable force full duplex
- * in the adapter's config block. If the PHY is 503, and
- * the duplex is full, consider the adapter forced.
- */
-void
-e100_config_force_dplx(struct e100_private *bdp)
-{
-	spin_lock_bh(&(bdp->config_lock));
-
-	/* We must force full duplex on if we are using PHY 0, and we are */
-	/* supposed to run in FDX mode. We do this because the e100 has only */
-	/* one FDX# input pin, and that pin will be connected to PHY 1. */
-	/* Changed the 'if' condition below to fix performance problem * at 10
-	 * full. The Phy was getting forced to full duplex while the MAC * was
-	 * not, because the cur_dplx_mode was not being set to 2 by SetupPhy. *
-	 * This is how the condition was, initially. * This has been changed so
-	 * that the MAC gets forced to full duplex * simply if the user has
-	 * forced full duplex. * * if (( bdp->phy_addr == 0 ) && (
-	 * bdp->cur_dplx_mode == 2 )) */
-	/* The rest of the fix is in the PhyDetect code. */
-	if ((bdp->params.e100_speed_duplex == E100_SPEED_10_FULL) ||
-	    (bdp->params.e100_speed_duplex == E100_SPEED_100_FULL) ||
-	    ((bdp->phy_addr == 32) && (bdp->cur_dplx_mode == FULL_DUPLEX))) {
-		if (!(bdp->config[19] & (u8) CB_CFIG_FORCE_FDX)) {
-			bdp->config[19] |= (u8) CB_CFIG_FORCE_FDX;
-			E100_CONFIG(bdp, 19);
-		}
-
-	} else {
-		if (bdp->config[19] & (u8) CB_CFIG_FORCE_FDX) {
-			bdp->config[19] &= (u8) (~CB_CFIG_FORCE_FDX);
-			E100_CONFIG(bdp, 19);
-		}
-	}
-
-	spin_unlock_bh(&(bdp->config_lock));
-}
-
-/**
- * e100_config_long_rx
- * @bdp: atapter's private data struct
- * @enable: should we enable this option or not
- *
- * This routine will enable or disable reception of larger packets.
- * This is needed by VLAN implementations.
- */
-static void
-e100_config_long_rx(struct e100_private *bdp, unsigned char enable)
-{
-	if (enable) {
-		if (!(bdp->config[18] & CB_CFIG_LONG_RX_OK)) {
-			bdp->config[18] |= CB_CFIG_LONG_RX_OK;
-			E100_CONFIG(bdp, 18);
-		}
-
-	} else {
-		if ((bdp->config[18] & CB_CFIG_LONG_RX_OK)) {
-			bdp->config[18] &= ~CB_CFIG_LONG_RX_OK;
-			E100_CONFIG(bdp, 18);
-		}
-	}
-}
-
-/**
- * e100_config_wol
- * @bdp: atapter's private data struct
- *
- * This sets configuration options for PHY and Magic Packet WoL 
- */
-void
-e100_config_wol(struct e100_private *bdp)
-{
-	spin_lock_bh(&(bdp->config_lock));
-
-	if (bdp->wolopts & WAKE_PHY) {
-		bdp->config[9] |= CB_LINK_STATUS_WOL;
-	}
-	else {
-		/* Disable PHY WoL */
-		bdp->config[9] &= ~CB_LINK_STATUS_WOL;
-	}
-
-	if (bdp->wolopts & WAKE_MAGIC) {
-		bdp->config[19] &= ~CB_DISABLE_MAGPAK_WAKE;
-	}
-	else {
-		/* Disable Magic Packet WoL */
-		bdp->config[19] |= CB_DISABLE_MAGPAK_WAKE;
-	}
-
-	E100_CONFIG(bdp, 19);
-	spin_unlock_bh(&(bdp->config_lock));
-}
-
-void
-e100_config_vlan_drop(struct e100_private *bdp, unsigned char enable)
-{
-	spin_lock_bh(&(bdp->config_lock));
-	if (enable) {
-		if (!(bdp->config[22] & CB_CFIG_VLAN_DROP_ENABLE)) {
-			bdp->config[22] |= CB_CFIG_VLAN_DROP_ENABLE;
-			E100_CONFIG(bdp, 22);
-		}
-
-	} else {
-		if ((bdp->config[22] & CB_CFIG_VLAN_DROP_ENABLE)) {
-			bdp->config[22] &= ~CB_CFIG_VLAN_DROP_ENABLE;
-			E100_CONFIG(bdp, 22);
-		}
-	}
-	spin_unlock_bh(&(bdp->config_lock));
-}
-
-/**
- * e100_config_loopback_mode
- * @bdp: atapter's private data struct
- * @mode: loopback mode(phy/mac/none)
- *
- */
-unsigned char
-e100_config_loopback_mode(struct e100_private *bdp, u8 mode)
-{
-	unsigned char bc_changed = false;
-	u8 config_byte;
-
-	spin_lock_bh(&(bdp->config_lock));
-
-	switch (mode) {
-	case NO_LOOPBACK:
-		config_byte = CB_CFIG_LOOPBACK_NORMAL;
-		break;
-	case MAC_LOOPBACK:
-		config_byte = CB_CFIG_LOOPBACK_INTERNAL;
-		break;
-	case PHY_LOOPBACK:
-		config_byte = CB_CFIG_LOOPBACK_EXTERNAL;
-		break;
-	default:
-		printk(KERN_NOTICE "e100: e100_config_loopback_mode: "
-		       "Invalid argument 'mode': %d\n", mode);
-		goto exit;
-	}
-
-	if ((bdp->config[10] & CB_CFIG_LOOPBACK_MODE) != config_byte) {
-
-		bdp->config[10] &= (~CB_CFIG_LOOPBACK_MODE);
-		bdp->config[10] |= config_byte;
-		E100_CONFIG(bdp, 10);
-		bc_changed = true;
-	}
-
-exit:
-	spin_unlock_bh(&(bdp->config_lock));
-	return bc_changed;
-}
-unsigned char
-e100_config_tcb_ext_enable(struct e100_private *bdp, unsigned char enable)
-{
-        unsigned char bc_changed = false;
- 
-        spin_lock_bh(&(bdp->config_lock));
- 
-        if (enable) {
-                if (bdp->config[6] & CB_CFIG_EXT_TCB_DIS) {
- 
-                        bdp->config[6] &= (~CB_CFIG_EXT_TCB_DIS);
-                        E100_CONFIG(bdp, 6);
-                        bc_changed = true;
-                }
- 
-        } else {
-                if (!(bdp->config[6] & CB_CFIG_EXT_TCB_DIS)) {
- 
-                        bdp->config[6] |= CB_CFIG_EXT_TCB_DIS;
-                        E100_CONFIG(bdp, 6);
-                        bc_changed = true;
-                }
-        }
-        spin_unlock_bh(&(bdp->config_lock));
- 
-        return bc_changed;
-}
-unsigned char
-e100_config_dynamic_tbd(struct e100_private *bdp, unsigned char enable)
-{
-        unsigned char bc_changed = false;
- 
-        spin_lock_bh(&(bdp->config_lock));
- 
-        if (enable) {
-                if (!(bdp->config[7] & CB_CFIG_DYNTBD_EN)) {
- 
-                        bdp->config[7] |= CB_CFIG_DYNTBD_EN;
-                        E100_CONFIG(bdp, 7);
-                        bc_changed = true;
-                }
- 
-        } else {
-                if (bdp->config[7] & CB_CFIG_DYNTBD_EN) {
- 
-                        bdp->config[7] &= (~CB_CFIG_DYNTBD_EN);
-                        E100_CONFIG(bdp, 7);
-                        bc_changed = true;
-                }
-        }
-        spin_unlock_bh(&(bdp->config_lock));
- 
-        return bc_changed;
-}
-
--- diff/drivers/net/e100/e100_config.h	2003-09-30 15:46:15.000000000 +0100
+++ source/drivers/net/e100/e100_config.h	1970-01-01 01:00:00.000000000 +0100
@@ -1,168 +0,0 @@
-/*******************************************************************************
-
-  
-  Copyright(c) 1999 - 2003 Intel Corporation. All rights reserved.
-  
-  This program is free software; you can redistribute it and/or modify it 
-  under the terms of the GNU General Public License as published by the Free 
-  Software Foundation; either version 2 of the License, or (at your option) 
-  any later version.
-  
-  This program is distributed in the hope that it will be useful, but WITHOUT 
-  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 
-  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for 
-  more details.
-  
-  You should have received a copy of the GNU General Public License along with
-  this program; if not, write to the Free Software Foundation, Inc., 59 
-  Temple Place - Suite 330, Boston, MA  02111-1307, USA.
-  
-  The full GNU General Public License is included in this distribution in the
-  file called LICENSE.
-  
-  Contact Information:
-  Linux NICS <linux.nics@intel.com>
-  Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
-*******************************************************************************/
-
-#ifndef _E100_CONFIG_INC_
-#define _E100_CONFIG_INC_
-
-#include "e100.h"
-
-#define E100_CONFIG(bdp, X) ((bdp)->config[0] = max_t(u8, (bdp)->config[0], (X)+1))
-
-#define CB_CFIG_MIN_PARAMS         8
-
-/* byte 0 bit definitions*/
-#define CB_CFIG_BYTE_COUNT_MASK     BIT_0_5	/* Byte count occupies bit 5-0 */
-
-/* byte 1 bit definitions*/
-#define CB_CFIG_RXFIFO_LIMIT_MASK   BIT_0_4	/* RxFifo limit mask */
-#define CB_CFIG_TXFIFO_LIMIT_MASK   BIT_4_7	/* TxFifo limit mask */
-
-/* byte 2 bit definitions -- ADAPTIVE_IFS*/
-
-/* word 3 bit definitions -- RESERVED*/
-/* Changed for 82558 enhancements */
-/* byte 3 bit definitions */
-#define CB_CFIG_MWI_EN      BIT_0	/* Enable MWI on PCI bus */
-#define CB_CFIG_TYPE_EN     BIT_1	/* Type Enable */
-#define CB_CFIG_READAL_EN   BIT_2	/* Enable Read Align */
-#define CB_CFIG_TERMCL_EN   BIT_3	/* Cache line write  */
-
-/* byte 4 bit definitions*/
-#define CB_CFIG_RX_MIN_DMA_MASK     BIT_0_6	/* Rx minimum DMA count mask */
-
-/* byte 5 bit definitions*/
-#define CB_CFIG_TX_MIN_DMA_MASK BIT_0_6	/* Tx minimum DMA count mask */
-#define CB_CFIG_DMBC_EN         BIT_7	/* Enable Tx/Rx min. DMA counts */
-
-/* Changed for 82558 enhancements */
-/* byte 6 bit definitions*/
-#define CB_CFIG_LATE_SCB           BIT_0	/* Update SCB After New Tx Start */
-#define CB_CFIG_DIRECT_DMA_DIS     BIT_1	/* Direct DMA mode */
-#define CB_CFIG_TNO_INT            BIT_2	/* Tx Not OK Interrupt */
-#define CB_CFIG_TCO_STAT           BIT_2	/* TCO statistics in 559 and above */
-#define CB_CFIG_CI_INT             BIT_3	/* Command Complete Interrupt */
-#define CB_CFIG_EXT_TCB_DIS        BIT_4	/* Extended TCB */
-#define CB_CFIG_EXT_STAT_DIS       BIT_5	/* Extended Stats */
-#define CB_CFIG_SAVE_BAD_FRAMES    BIT_7	/* Save Bad Frames Enabled */
-
-/* byte 7 bit definitions*/
-#define CB_CFIG_DISC_SHORT_FRAMES   BIT_0	/* Discard Short Frames */
-#define CB_CFIG_DYNTBD_EN           BIT_7	/* Enable dynamic TBD */
-/* Enable extended RFD's on D102 */
-#define CB_CFIG_EXTENDED_RFD        BIT_5
-
-/* byte 8 bit definitions*/
-#define CB_CFIG_503_MII             BIT_0	/* 503 vs. MII mode */
-
-/* byte 9 bit definitions -- pre-defined all zeros*/
-#define CB_LINK_STATUS_WOL	BIT_5
-
-/* byte 10 bit definitions*/
-#define CB_CFIG_NO_SRCADR       BIT_3	/* No Source Address Insertion */
-#define CB_CFIG_PREAMBLE_LEN    BIT_4_5	/* Preamble Length */
-#define CB_CFIG_LOOPBACK_MODE   BIT_6_7	/* Loopback Mode */
-#define CB_CFIG_LOOPBACK_NORMAL 0
-#define CB_CFIG_LOOPBACK_INTERNAL BIT_6
-#define CB_CFIG_LOOPBACK_EXTERNAL BIT_6_7
-
-/* byte 11 bit definitions*/
-#define CB_CFIG_LINEAR_PRIORITY     BIT_0_2	/* Linear Priority */
-
-/* byte 12 bit definitions*/
-#define CB_CFIG_LINEAR_PRI_MODE     BIT_0	/* Linear Priority mode */
-#define CB_CFIG_IFS_MASK            BIT_4_7	/* Interframe Spacing mask */
-
-/* byte 13 bit definitions -- pre-defined all zeros*/
-
-/* byte 14 bit definitions -- pre-defined 0xf2*/
-
-/* byte 15 bit definitions*/
-#define CB_CFIG_PROMISCUOUS         BIT_0	/* Promiscuous Mode Enable */
-#define CB_CFIG_BROADCAST_DIS       BIT_1	/* Broadcast Mode Disable */
-#define CB_CFIG_CRS_OR_CDT          BIT_7	/* CRS Or CDT */
-
-/* byte 16 bit definitions -- pre-defined all zeros*/
-#define DFLT_FC_DELAY_LSB  0x1f	/* Delay for outgoing Pause frames */
-#define DFLT_NO_FC_DELAY_LSB  0x00	/* no flow control default value */
-
-/* byte 17 bit definitions -- pre-defined 0x40*/
-#define DFLT_FC_DELAY_MSB  0x01	/* Delay for outgoing Pause frames */
-#define DFLT_NO_FC_DELAY_MSB  0x40	/* no flow control default value */
-
-/* byte 18 bit definitions*/
-#define CB_CFIG_STRIPPING           BIT_0	/* Padding Disabled */
-#define CB_CFIG_PADDING             BIT_1	/* Padding Disabled */
-#define CB_CFIG_CRC_IN_MEM          BIT_2	/* Transfer CRC To Memory */
-
-/* byte 19 bit definitions*/
-#define CB_CFIG_TX_ADDR_WAKE        BIT_0	/* Address Wakeup */
-#define CB_DISABLE_MAGPAK_WAKE      BIT_1	/* Magic Packet Wakeup disable */
-/* Changed TX_FC_EN to TX_FC_DIS because 0 enables, 1 disables. Jul 8, 1999 */
-#define CB_CFIG_TX_FC_DIS           BIT_2	/* Tx Flow Control Disable */
-#define CB_CFIG_FC_RESTOP           BIT_3	/* Rx Flow Control Restop */
-#define CB_CFIG_FC_RESTART          BIT_4	/* Rx Flow Control Restart */
-#define CB_CFIG_FC_REJECT           BIT_5	/* Rx Flow Control Restart */
-#define CB_CFIG_FC_OPTS (CB_CFIG_FC_RESTOP | CB_CFIG_FC_RESTART | CB_CFIG_FC_REJECT)
-
-/* end 82558/9 specifics */
-
-#define CB_CFIG_FORCE_FDX           BIT_6	/* Force Full Duplex */
-#define CB_CFIG_FDX_ENABLE          BIT_7	/* Full Duplex Enabled */
-
-/* byte 20 bit definitions*/
-#define CB_CFIG_MULTI_IA            BIT_6	/* Multiple IA Addr */
-
-/* byte 21 bit definitions*/
-#define CB_CFIG_MULTICAST_ALL       BIT_3	/* Multicast All */
-
-/* byte 22 bit defines */
-#define CB_CFIG_RECEIVE_GAMLA_MODE  BIT_0	/* D102 receive mode */
-#define CB_CFIG_VLAN_DROP_ENABLE    BIT_1	/* vlan stripping */
-
-#define CB_CFIG_LONG_RX_OK	    BIT_3
-
-#define NO_LOOPBACK	0	
-#define MAC_LOOPBACK	0x01
-#define PHY_LOOPBACK	0x02
-
-/* function prototypes */
-extern void e100_config_init(struct e100_private *bdp);
-extern void e100_config_init_82557(struct e100_private *bdp);
-extern unsigned char e100_force_config(struct e100_private *bdp);
-extern unsigned char e100_config(struct e100_private *bdp);
-extern void e100_config_fc(struct e100_private *bdp);
-extern void e100_config_promisc(struct e100_private *bdp, unsigned char enable);
-extern void e100_config_brdcast_dsbl(struct e100_private *bdp);
-extern void e100_config_mulcast_enbl(struct e100_private *bdp,
-				     unsigned char enable);
-extern void e100_config_ifs(struct e100_private *bdp);
-extern void e100_config_force_dplx(struct e100_private *bdp);
-extern u8 e100_config_loopback_mode(struct e100_private *bdp, u8 mode);
-extern u8 e100_config_dynamic_tbd(struct e100_private *bdp, u8 enable);
-extern u8 e100_config_tcb_ext_enable(struct e100_private *bdp, u8 enable);
-extern void e100_config_vlan_drop(struct e100_private *bdp, unsigned char enable);
-#endif /* _E100_CONFIG_INC_ */
--- diff/drivers/net/e100/e100_eeprom.c	2003-05-21 11:49:55.000000000 +0100
+++ source/drivers/net/e100/e100_eeprom.c	1970-01-01 01:00:00.000000000 +0100
@@ -1,565 +0,0 @@
-/*******************************************************************************
-
-  
-  Copyright(c) 1999 - 2003 Intel Corporation. All rights reserved.
-  
-  This program is free software; you can redistribute it and/or modify it 
-  under the terms of the GNU General Public License as published by the Free 
-  Software Foundation; either version 2 of the License, or (at your option) 
-  any later version.
-  
-  This program is distributed in the hope that it will be useful, but WITHOUT 
-  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 
-  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for 
-  more details.
-  
-  You should have received a copy of the GNU General Public License along with
-  this program; if not, write to the Free Software Foundation, Inc., 59 
-  Temple Place - Suite 330, Boston, MA  02111-1307, USA.
-  
-  The full GNU General Public License is included in this distribution in the
-  file called LICENSE.
-  
-  Contact Information:
-  Linux NICS <linux.nics@intel.com>
-  Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
-*******************************************************************************/
-
-/**********************************************************************
-*                                                                     *
-* INTEL CORPORATION                                                   *
-*                                                                     *
-* This software is supplied under the terms of the license included   *
-* above.  All use of this driver must be in accordance with the terms *
-* of that license.                                                    *
-*                                                                     *
-* Module Name:  e100_eeprom.c                                         *
-*                                                                     *
-* Abstract:     This module contains routines to read and write to a  *
-*               serial EEPROM                                         *
-*                                                                     *
-* Environment:  This file is intended to be specific to the Linux     *
-*               operating system.                                     *
-*                                                                     *
-**********************************************************************/
-#include "e100.h"
-
-#define CSR_EEPROM_CONTROL_FIELD(bdp) ((bdp)->scb->scb_eprm_cntrl)
-
-#define CSR_GENERAL_CONTROL2_FIELD(bdp) \
-	           ((bdp)->scb->scb_ext.d102_scb.scb_gen_ctrl2)
-
-#define EEPROM_STALL_TIME	4
-#define EEPROM_CHECKSUM		((u16) 0xBABA)
-#define EEPROM_MAX_WORD_SIZE	256
-
-void e100_eeprom_cleanup(struct e100_private *adapter);
-u16 e100_eeprom_calculate_chksum(struct e100_private *adapter);
-static void e100_eeprom_write_word(struct e100_private *adapter, u16 reg,
-				   u16 data);
-void e100_eeprom_write_block(struct e100_private *adapter, u16 start, u16 *data,
-			     u16 size);
-u16 e100_eeprom_size(struct e100_private *adapter);
-u16 e100_eeprom_read(struct e100_private *adapter, u16 reg);
-
-static void shift_out_bits(struct e100_private *adapter, u16 data, u16 count);
-static u16 shift_in_bits(struct e100_private *adapter);
-static void raise_clock(struct e100_private *adapter, u16 *x);
-static void lower_clock(struct e100_private *adapter, u16 *x);
-static u16 eeprom_wait_cmd_done(struct e100_private *adapter);
-static void eeprom_stand_by(struct e100_private *adapter);
-
-//----------------------------------------------------------------------------------------
-// Procedure:   eeprom_set_semaphore
-//
-// Description: This function set (write 1) Gamla EEPROM semaphore bit (bit 23 word 0x1C in the CSR).
-//
-// Arguments:
-//      Adapter                 - Adapter context
-//
-// Returns:  true if success
-//           else return false 
-//
-//----------------------------------------------------------------------------------------
-
-inline u8
-eeprom_set_semaphore(struct e100_private *adapter)
-{
-	u16 data = 0;
-	unsigned long expiration_time = jiffies + HZ / 100 + 1;
-
-	do {
-		// Get current value of General Control 2
-		data = readb(&CSR_GENERAL_CONTROL2_FIELD(adapter));
-
-		// Set bit 23 word 0x1C in the CSR.
-		data |= SCB_GCR2_EEPROM_ACCESS_SEMAPHORE;
-		writeb(data, &CSR_GENERAL_CONTROL2_FIELD(adapter));
-
-		// Check to see if this bit set or not.
-		data = readb(&CSR_GENERAL_CONTROL2_FIELD(adapter));
-
-		if (data & SCB_GCR2_EEPROM_ACCESS_SEMAPHORE) {
-			return true;
-		}
-
-		if (time_before(jiffies, expiration_time))
-			yield();
-		else
-			return false;
-
-	} while (true);
-}
-
-//----------------------------------------------------------------------------------------
-// Procedure:   eeprom_reset_semaphore
-//
-// Description: This function reset (write 0) Gamla EEPROM semaphore bit 
-//              (bit 23 word 0x1C in the CSR).
-//
-// Arguments:  struct e100_private * adapter - Adapter context
-//----------------------------------------------------------------------------------------
-
-inline void
-eeprom_reset_semaphore(struct e100_private *adapter)
-{
-	u16 data = 0;
-
-	data = readb(&CSR_GENERAL_CONTROL2_FIELD(adapter));
-	data &= ~(SCB_GCR2_EEPROM_ACCESS_SEMAPHORE);
-	writeb(data, &CSR_GENERAL_CONTROL2_FIELD(adapter));
-}
-
-//----------------------------------------------------------------------------------------
-// Procedure:   e100_eeprom_size
-//
-// Description: This routine determines the size of the EEPROM.  This value should be
-//              checked for validity - ie. is it too big or too small.  The size returned
-//              is then passed to the read/write functions.
-//
-// Returns:
-//      Size of the eeprom, or zero if an error occurred
-//----------------------------------------------------------------------------------------
-u16
-e100_eeprom_size(struct e100_private *adapter)
-{
-	u16 x, size = 1;	// must be one to accumulate a product
-
-	// if we've already stored this data, read from memory
-	if (adapter->eeprom_size) {
-		return adapter->eeprom_size;
-	}
-	// otherwise, read from the eeprom
-	// Set EEPROM semaphore.
-	if (adapter->rev_id >= D102_REV_ID) {
-		if (!eeprom_set_semaphore(adapter))
-			return 0;
-	}
-	// enable the eeprom by setting EECS.
-	x = readw(&CSR_EEPROM_CONTROL_FIELD(adapter));
-	x &= ~(EEDI | EEDO | EESK);
-	x |= EECS;
-	writew(x, &CSR_EEPROM_CONTROL_FIELD(adapter));
-
-	// write the read opcode
-	shift_out_bits(adapter, EEPROM_READ_OPCODE, 3);
-
-	// experiment to discover the size of the eeprom.  request register zero
-	// and wait for the eeprom to tell us it has accepted the entire address.
-	x = readw(&CSR_EEPROM_CONTROL_FIELD(adapter));
-	do {
-		size *= 2;	// each bit of address doubles eeprom size
-		x |= EEDO;	// set bit to detect "dummy zero"
-		x &= ~EEDI;	// address consists of all zeros
-
-		writew(x, &CSR_EEPROM_CONTROL_FIELD(adapter));
-		readw(&(adapter->scb->scb_status));
-		udelay(EEPROM_STALL_TIME);
-		raise_clock(adapter, &x);
-		lower_clock(adapter, &x);
-
-		// check for "dummy zero"
-		x = readw(&CSR_EEPROM_CONTROL_FIELD(adapter));
-		if (size > EEPROM_MAX_WORD_SIZE) {
-			size = 0;
-			break;
-		}
-	} while (x & EEDO);
-
-	// read in the value requested
-	(void) shift_in_bits(adapter);
-	e100_eeprom_cleanup(adapter);
-
-	// Clear EEPROM Semaphore.
-	if (adapter->rev_id >= D102_REV_ID) {
-		eeprom_reset_semaphore(adapter);
-	}
-
-	return size;
-}
-
-//----------------------------------------------------------------------------------------
-// Procedure:   eeprom_address_size
-//
-// Description: determines the number of bits in an address for the eeprom acceptable
-//              values are 64, 128, and 256
-// Arguments: size of the eeprom
-// Returns: bits in an address for that size eeprom
-//----------------------------------------------------------------------------------------
-
-static inline int
-eeprom_address_size(u16 size)
-{
-	int isize = size;
-	
-	return (ffs(isize) - 1);
-}
-
-//----------------------------------------------------------------------------------------
-// Procedure:   e100_eeprom_read
-//
-// Description: This routine serially reads one word out of the EEPROM.
-//
-// Arguments:
-//      adapter - our adapter context
-//      reg - EEPROM word to read.
-//
-// Returns:
-//      Contents of EEPROM word (reg).
-//----------------------------------------------------------------------------------------
-
-u16
-e100_eeprom_read(struct e100_private *adapter, u16 reg)
-{
-	u16 x, data, bits;
-
-	// Set EEPROM semaphore.
-	if (adapter->rev_id >= D102_REV_ID) {
-		if (!eeprom_set_semaphore(adapter))
-			return 0;
-	}
-	// eeprom size is initialized to zero
-	if (!adapter->eeprom_size)
-		adapter->eeprom_size = e100_eeprom_size(adapter);
-
-	bits = eeprom_address_size(adapter->eeprom_size);
-
-	// select EEPROM, reset bits, set EECS
-	x = readw(&CSR_EEPROM_CONTROL_FIELD(adapter));
-
-	x &= ~(EEDI | EEDO | EESK);
-	x |= EECS;
-	writew(x, &CSR_EEPROM_CONTROL_FIELD(adapter));
-
-	// write the read opcode and register number in that order
-	// The opcode is 3bits in length, reg is 'bits' bits long
-	shift_out_bits(adapter, EEPROM_READ_OPCODE, 3);
-	shift_out_bits(adapter, reg, bits);
-
-	// Now read the data (16 bits) in from the selected EEPROM word
-	data = shift_in_bits(adapter);
-
-	e100_eeprom_cleanup(adapter);
-
-	// Clear EEPROM Semaphore.
-	if (adapter->rev_id >= D102_REV_ID) {
-		eeprom_reset_semaphore(adapter);
-	}
-
-	return data;
-}
-
-//----------------------------------------------------------------------------------------
-// Procedure:   shift_out_bits
-//
-// Description: This routine shifts data bits out to the EEPROM.
-//
-// Arguments:
-//      data - data to send to the EEPROM.
-//      count - number of data bits to shift out.
-//
-// Returns: (none)
-//----------------------------------------------------------------------------------------
-
-static void
-shift_out_bits(struct e100_private *adapter, u16 data, u16 count)
-{
-	u16 x, mask;
-
-	mask = 1 << (count - 1);
-	x = readw(&CSR_EEPROM_CONTROL_FIELD(adapter));
-	x &= ~(EEDO | EEDI);
-
-	do {
-		x &= ~EEDI;
-		if (data & mask)
-			x |= EEDI;
-
-		writew(x, &CSR_EEPROM_CONTROL_FIELD(adapter));
-		readw(&(adapter->scb->scb_status)); /* flush command to card */
-		udelay(EEPROM_STALL_TIME);
-		raise_clock(adapter, &x);
-		lower_clock(adapter, &x);
-		mask = mask >> 1;
-	} while (mask);
-
-	x &= ~EEDI;
-	writew(x, &CSR_EEPROM_CONTROL_FIELD(adapter));
-}
-
-//----------------------------------------------------------------------------------------
-// Procedure:   raise_clock
-//
-// Description: This routine raises the EEPROM's clock input (EESK)
-//
-// Arguments:
-//      x - Ptr to the EEPROM control register's current value
-//
-// Returns: (none)
-//----------------------------------------------------------------------------------------
-
-void
-raise_clock(struct e100_private *adapter, u16 *x)
-{
-	*x = *x | EESK;
-	writew(*x, &CSR_EEPROM_CONTROL_FIELD(adapter));
-	readw(&(adapter->scb->scb_status)); /* flush command to card */
-	udelay(EEPROM_STALL_TIME);
-}
-
-//----------------------------------------------------------------------------------------
-// Procedure:   lower_clock
-//
-// Description: This routine lower's the EEPROM's clock input (EESK)
-//
-// Arguments:
-//      x - Ptr to the EEPROM control register's current value
-//
-// Returns: (none)
-//----------------------------------------------------------------------------------------
-
-void
-lower_clock(struct e100_private *adapter, u16 *x)
-{
-	*x = *x & ~EESK;
-	writew(*x, &CSR_EEPROM_CONTROL_FIELD(adapter));
-	readw(&(adapter->scb->scb_status)); /* flush command to card */
-	udelay(EEPROM_STALL_TIME);
-}
-
-//----------------------------------------------------------------------------------------
-// Procedure:   shift_in_bits
-//
-// Description: This routine shifts data bits in from the EEPROM.
-//
-// Arguments:
-//
-// Returns:
-//      The contents of that particular EEPROM word
-//----------------------------------------------------------------------------------------
-
-static u16
-shift_in_bits(struct e100_private *adapter)
-{
-	u16 x, d, i;
-
-	x = readw(&CSR_EEPROM_CONTROL_FIELD(adapter));
-	x &= ~(EEDO | EEDI);
-	d = 0;
-
-	for (i = 0; i < 16; i++) {
-		d <<= 1;
-		raise_clock(adapter, &x);
-
-		x = readw(&CSR_EEPROM_CONTROL_FIELD(adapter));
-
-		x &= ~EEDI;
-		if (x & EEDO)
-			d |= 1;
-
-		lower_clock(adapter, &x);
-	}
-
-	return d;
-}
-
-//----------------------------------------------------------------------------------------
-// Procedure:   e100_eeprom_cleanup
-//
-// Description: This routine returns the EEPROM to an idle state
-//----------------------------------------------------------------------------------------
-
-void
-e100_eeprom_cleanup(struct e100_private *adapter)
-{
-	u16 x;
-
-	x = readw(&CSR_EEPROM_CONTROL_FIELD(adapter));
-
-	x &= ~(EECS | EEDI);
-	writew(x, &CSR_EEPROM_CONTROL_FIELD(adapter));
-
-	raise_clock(adapter, &x);
-	lower_clock(adapter, &x);
-}
-
-//**********************************************************************************
-// Procedure:   e100_eeprom_update_chksum
-//
-// Description: Calculates the checksum and writes it to the EEProm. 
-//              It calculates the checksum accroding to the formula: 
-//                              Checksum = 0xBABA - (sum of first 63 words).
-//
-//-----------------------------------------------------------------------------------
-u16
-e100_eeprom_calculate_chksum(struct e100_private *adapter)
-{
-	u16 idx, xsum_index, checksum = 0;
-
-	// eeprom size is initialized to zero
-	if (!adapter->eeprom_size)
-		adapter->eeprom_size = e100_eeprom_size(adapter);
-
-	xsum_index = adapter->eeprom_size - 1;
-	for (idx = 0; idx < xsum_index; idx++)
-		checksum += e100_eeprom_read(adapter, idx);
-
-	checksum = EEPROM_CHECKSUM - checksum;
-	return checksum;
-}
-
-//----------------------------------------------------------------------------------------
-// Procedure:   e100_eeprom_write_word
-//
-// Description: This routine writes a word to a specific EEPROM location without.
-//              taking EEPROM semaphore and updating checksum. 
-//              Use e100_eeprom_write_block for the EEPROM update
-// Arguments: reg - The EEPROM word that we are going to write to.
-//            data - The data (word) that we are going to write to the EEPROM.
-//----------------------------------------------------------------------------------------
-static void
-e100_eeprom_write_word(struct e100_private *adapter, u16 reg, u16 data)
-{
-	u16 x;
-	u16 bits;
-
-	bits = eeprom_address_size(adapter->eeprom_size);
-
-	/* select EEPROM, mask off ASIC and reset bits, set EECS */
-	x = readw(&CSR_EEPROM_CONTROL_FIELD(adapter));
-	x &= ~(EEDI | EEDO | EESK);
-	writew(x, &CSR_EEPROM_CONTROL_FIELD(adapter));
-	readw(&(adapter->scb->scb_status)); /* flush command to card */
-	udelay(EEPROM_STALL_TIME);
-	x |= EECS;
-	writew(x, &CSR_EEPROM_CONTROL_FIELD(adapter));
-
-	shift_out_bits(adapter, EEPROM_EWEN_OPCODE, 5);
-	shift_out_bits(adapter, reg, (u16) (bits - 2));
-	if (!eeprom_wait_cmd_done(adapter))
-		return;
-
-	/* write the new word to the EEPROM & send the write opcode the EEPORM */
-	shift_out_bits(adapter, EEPROM_WRITE_OPCODE, 3);
-
-	/* select which word in the EEPROM that we are writing to */
-	shift_out_bits(adapter, reg, bits);
-
-	/* write the data to the selected EEPROM word */
-	shift_out_bits(adapter, data, 16);
-	if (!eeprom_wait_cmd_done(adapter))
-		return;
-
-	shift_out_bits(adapter, EEPROM_EWDS_OPCODE, 5);
-	shift_out_bits(adapter, reg, (u16) (bits - 2));
-	if (!eeprom_wait_cmd_done(adapter))
-		return;
-
-	e100_eeprom_cleanup(adapter);
-}
-
-//----------------------------------------------------------------------------------------
-// Procedure:   e100_eeprom_write_block
-//
-// Description: This routine writes a block of words starting from specified EEPROM 
-//              location and updates checksum
-// Arguments: reg - The EEPROM word that we are going to write to.
-//            data - The data (word) that we are going to write to the EEPROM.
-//----------------------------------------------------------------------------------------
-void
-e100_eeprom_write_block(struct e100_private *adapter, u16 start, u16 *data,
-			u16 size)
-{
-	u16 checksum;
-	u16 i;
-
-	if (!adapter->eeprom_size)
-		adapter->eeprom_size = e100_eeprom_size(adapter);
-
-	// Set EEPROM semaphore.
-	if (adapter->rev_id >= D102_REV_ID) {
-		if (!eeprom_set_semaphore(adapter))
-			return;
-	}
-
-	for (i = 0; i < size; i++) {
-		e100_eeprom_write_word(adapter, start + i, data[i]);
-	}
-	//Update checksum
-	checksum = e100_eeprom_calculate_chksum(adapter);
-	e100_eeprom_write_word(adapter, (adapter->eeprom_size - 1), checksum);
-
-	// Clear EEPROM Semaphore.
-	if (adapter->rev_id >= D102_REV_ID) {
-		eeprom_reset_semaphore(adapter);
-	}
-}
-
-//----------------------------------------------------------------------------------------
-// Procedure:   eeprom_wait_cmd_done
-//
-// Description: This routine waits for the the EEPROM to finish its command.  
-//                              Specifically, it waits for EEDO (data out) to go high.
-// Returns:     true - If the command finished
-//              false - If the command never finished (EEDO stayed low)
-//----------------------------------------------------------------------------------------
-static u16
-eeprom_wait_cmd_done(struct e100_private *adapter)
-{
-	u16 x;
-	unsigned long expiration_time = jiffies + HZ / 100 + 1;
-
-	eeprom_stand_by(adapter);
-
-	do {
-		rmb();
-		x = readw(&CSR_EEPROM_CONTROL_FIELD(adapter));
-		if (x & EEDO)
-			return true;
-		if (time_before(jiffies, expiration_time))
-			yield();
-		else
-			return false;
-	} while (true);
-}
-
-//----------------------------------------------------------------------------------------
-// Procedure:   eeprom_stand_by
-//
-// Description: This routine lowers the EEPROM chip select (EECS) for a few microseconds.
-//----------------------------------------------------------------------------------------
-static void
-eeprom_stand_by(struct e100_private *adapter)
-{
-	u16 x;
-
-	x = readw(&CSR_EEPROM_CONTROL_FIELD(adapter));
-	x &= ~(EECS | EESK);
-	writew(x, &CSR_EEPROM_CONTROL_FIELD(adapter));
-	readw(&(adapter->scb->scb_status)); /* flush command to card */
-	udelay(EEPROM_STALL_TIME);
-	x |= EECS;
-	writew(x, &CSR_EEPROM_CONTROL_FIELD(adapter));
-	readw(&(adapter->scb->scb_status)); /* flush command to card */
-	udelay(EEPROM_STALL_TIME);
-}
--- diff/drivers/net/e100/e100_main.c	2004-02-18 08:54:10.000000000 +0000
+++ source/drivers/net/e100/e100_main.c	1970-01-01 01:00:00.000000000 +0100
@@ -1,4341 +0,0 @@
-/*******************************************************************************
-
-  
-  Copyright(c) 1999 - 2003 Intel Corporation. All rights reserved.
-  
-  This program is free software; you can redistribute it and/or modify it 
-  under the terms of the GNU General Public License as published by the Free 
-  Software Foundation; either version 2 of the License, or (at your option) 
-  any later version.
-  
-  This program is distributed in the hope that it will be useful, but WITHOUT 
-  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 
-  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for 
-  more details.
-  
-  You should have received a copy of the GNU General Public License along with
-  this program; if not, write to the Free Software Foundation, Inc., 59 
-  Temple Place - Suite 330, Boston, MA  02111-1307, USA.
-  
-  The full GNU General Public License is included in this distribution in the
-  file called LICENSE.
-  
-  Contact Information:
-  Linux NICS <linux.nics@intel.com>
-  Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
-*******************************************************************************/
-
-/**********************************************************************
-*                                                                     *
-* INTEL CORPORATION                                                   *
-*                                                                     *
-* This software is supplied under the terms of the license included   *
-* above.  All use of this driver must be in accordance with the terms *
-* of that license.                                                    *
-*                                                                     *
-* Module Name:  e100_main.c                                           *
-*                                                                     *
-* Abstract:     Functions for the driver entry points like load,      *
-*               unload, open and close. All board specific calls made *
-*               by the network interface section of the driver.       *
-*                                                                     *
-* Environment:  This file is intended to be specific to the Linux     *
-*               operating system.                                     *
-*                                                                     *
-**********************************************************************/
-
-/* Change Log
- * 
- * 2.3.36       11/13/03
- * o Moved to 2.6 APIs: pci_name() and free_netdev().
- * o Removed some __devinit from some functions that shouldn't be marked
- *   as such (Anton Blanchard [anton@samba.org]).
- * 
- * 2.3.33       10/21/03
- * o Bug fix (Bugzilla 97908): Loading e100 was causing crash on Itanium2
- *   with HP chipset
- * o Bug fix (Bugzilla 101583): e100 can't pass traffic with ipv6
- * o Bug fix (Bugzilla 101360): PRO/10+ can't pass traffic
- * 
- * 2.3.27       08/08/03
- */
- 
-#include <linux/config.h>
-#include <net/checksum.h>
-#include <linux/tcp.h>
-#include <linux/udp.h>
-#include "e100.h"
-#include "e100_ucode.h"
-#include "e100_config.h"
-#include "e100_phy.h"
-
-extern void e100_force_speed_duplex_to_phy(struct e100_private *bdp);
-
-static char e100_gstrings_stats[][ETH_GSTRING_LEN] = {
-	"rx_packets", "tx_packets", "rx_bytes", "tx_bytes", "rx_errors",
-	"tx_errors", "rx_dropped", "tx_dropped", "multicast", "collisions",
-	"rx_length_errors", "rx_over_errors", "rx_crc_errors",
-	"rx_frame_errors", "rx_fifo_errors", "rx_missed_errors",
-	"tx_aborted_errors", "tx_carrier_errors", "tx_fifo_errors",
-	"tx_heartbeat_errors", "tx_window_errors",
-};
-#define E100_STATS_LEN	sizeof(e100_gstrings_stats) / ETH_GSTRING_LEN
-
-static int e100_do_ethtool_ioctl(struct net_device *, struct ifreq *);
-static void e100_get_speed_duplex_caps(struct e100_private *);
-static int e100_ethtool_get_settings(struct net_device *, struct ifreq *);
-static int e100_ethtool_set_settings(struct net_device *, struct ifreq *);
-
-static int e100_ethtool_get_drvinfo(struct net_device *, struct ifreq *);
-static int e100_ethtool_eeprom(struct net_device *, struct ifreq *);
-
-#define E100_EEPROM_MAGIC 0x1234
-static int e100_ethtool_glink(struct net_device *, struct ifreq *);
-static int e100_ethtool_gregs(struct net_device *, struct ifreq *);
-static int e100_ethtool_nway_rst(struct net_device *, struct ifreq *);
-static int e100_ethtool_wol(struct net_device *, struct ifreq *);
-#ifdef CONFIG_PM
-static unsigned char e100_setup_filter(struct e100_private *bdp);
-static void e100_do_wol(struct pci_dev *pcid, struct e100_private *bdp);
-#endif
-static u16 e100_get_ip_lbytes(struct net_device *dev);
-extern void e100_config_wol(struct e100_private *bdp);
-extern u32 e100_run_diag(struct net_device *dev, u64 *test_info, u32 flags);
-static int e100_ethtool_test(struct net_device *, struct ifreq *);
-static int e100_ethtool_gstrings(struct net_device *, struct ifreq *);
-static char test_strings[][ETH_GSTRING_LEN] = {
-	"Link test     (on/offline)",
-	"Eeprom test   (on/offline)",
-	"Self test        (offline)",
-	"Mac loopback     (offline)",
-	"Phy loopback     (offline)",
-	"Cable diagnostic (offline)"
-};
-
-static int e100_ethtool_led_blink(struct net_device *, struct ifreq *);
-
-static int e100_mii_ioctl(struct net_device *, struct ifreq *, int);
-
-static unsigned char e100_delayed_exec_non_cu_cmd(struct e100_private *,
-						  nxmit_cb_entry_t *);
-static void e100_free_nontx_list(struct e100_private *);
-static void e100_non_tx_background(unsigned long);
-static inline void e100_tx_skb_free(struct e100_private *bdp, tcb_t *tcb);
-/* Global Data structures and variables */
-char e100_copyright[] = "Copyright (c) 2003 Intel Corporation";
-char e100_driver_version[]="2.3.36-k1";
-const char *e100_full_driver_name = "Intel(R) PRO/100 Network Driver";
-char e100_short_driver_name[] = "e100";
-static int e100nics = 0;
-static void e100_vlan_rx_register(struct net_device *netdev, struct vlan_group
-		*grp);
-static void e100_vlan_rx_add_vid(struct net_device *netdev, u16 vid);
-static void e100_vlan_rx_kill_vid(struct net_device *netdev, u16 vid);
-
-#ifdef CONFIG_PM
-static int e100_notify_reboot(struct notifier_block *, unsigned long event, void *ptr);
-static int e100_suspend(struct pci_dev *pcid, u32 state);
-static int e100_resume(struct pci_dev *pcid);
-static unsigned char e100_asf_enabled(struct e100_private *bdp);
-struct notifier_block e100_notifier_reboot = {
-        .notifier_call  = e100_notify_reboot,
-        .next           = NULL,
-        .priority       = 0
-};
-#endif
-
-/*********************************************************************/
-/*! This is a GCC extension to ANSI C.
- *  See the item "Labeled Elements in Initializers" in the section
- *  "Extensions to the C Language Family" of the GCC documentation.
- *********************************************************************/
-#define E100_PARAM_INIT { [0 ... E100_MAX_NIC] = -1 }
-
-/* All parameters are treated the same, as an integer array of values.
- * This macro just reduces the need to repeat the same declaration code
- * over and over (plus this helps to avoid typo bugs).
- */
-#define E100_PARAM(X, S)                                        \
-        static const int X[E100_MAX_NIC + 1] = E100_PARAM_INIT; \
-        MODULE_PARM(X, "1-" __MODULE_STRING(E100_MAX_NIC) "i"); \
-        MODULE_PARM_DESC(X, S);
-
-/* ====================================================================== */
-static u8 e100_D101M_checksum(struct e100_private *, struct sk_buff *);
-static u8 e100_D102_check_checksum(rfd_t *);
-static int e100_ioctl(struct net_device *, struct ifreq *, int);
-static int e100_change_mtu(struct net_device *, int);
-static int e100_xmit_frame(struct sk_buff *, struct net_device *);
-static unsigned char e100_init(struct e100_private *);
-static int e100_set_mac(struct net_device *, void *);
-struct net_device_stats *e100_get_stats(struct net_device *);
-
-static irqreturn_t e100intr(int, void *, struct pt_regs *);
-static void e100_print_brd_conf(struct e100_private *);
-static void e100_set_multi(struct net_device *);
-
-static u8 e100_pci_setup(struct pci_dev *, struct e100_private *);
-static u8 e100_sw_init(struct e100_private *);
-static void e100_tco_workaround(struct e100_private *);
-static unsigned char e100_alloc_space(struct e100_private *);
-static void e100_dealloc_space(struct e100_private *);
-static int e100_alloc_tcb_pool(struct e100_private *);
-static void e100_setup_tcb_pool(tcb_t *, unsigned int, struct e100_private *);
-static void e100_free_tcb_pool(struct e100_private *);
-static int e100_alloc_rfd_pool(struct e100_private *);
-static void e100_free_rfd_pool(struct e100_private *);
-
-static void e100_rd_eaddr(struct e100_private *);
-static void e100_rd_pwa_no(struct e100_private *);
-extern u16 e100_eeprom_read(struct e100_private *, u16);
-extern void e100_eeprom_write_block(struct e100_private *, u16, u16 *, u16);
-extern u16 e100_eeprom_size(struct e100_private *);
-u16 e100_eeprom_calculate_chksum(struct e100_private *adapter);
-
-static unsigned char e100_clr_cntrs(struct e100_private *);
-static unsigned char e100_load_microcode(struct e100_private *);
-static unsigned char e100_setup_iaaddr(struct e100_private *, u8 *);
-static unsigned char e100_update_stats(struct e100_private *bdp);
-
-static void e100_start_ru(struct e100_private *);
-static void e100_dump_stats_cntrs(struct e100_private *);
-
-static void e100_check_options(int board, struct e100_private *bdp);
-static void e100_set_int_option(int *, int, int, int, int, char *);
-static void e100_set_bool_option(struct e100_private *bdp, int, u32, int,
-				 char *);
-unsigned char e100_wait_exec_cmplx(struct e100_private *, u32, u8, u8);
-void e100_exec_cmplx(struct e100_private *, u32, u8);
-
-/**
- * e100_get_rx_struct - retrieve cell to hold skb buff from the pool
- * @bdp: atapter's private data struct
- *
- * Returns the new cell to hold sk_buff or %NULL.
- */
-static inline struct rx_list_elem *
-e100_get_rx_struct(struct e100_private *bdp)
-{
-	struct rx_list_elem *rx_struct = NULL;
-
-	if (!list_empty(&(bdp->rx_struct_pool))) {
-		rx_struct = list_entry(bdp->rx_struct_pool.next,
-				       struct rx_list_elem, list_elem);
-		list_del(&(rx_struct->list_elem));
-	}
-
-	return rx_struct;
-}
-
-/**
- * e100_alloc_skb - allocate an skb for the adapter
- * @bdp: atapter's private data struct
- *
- * Allocates skb with enough room for rfd, and data, and reserve non-data space.
- * Returns the new cell with sk_buff or %NULL.
- */
-static inline struct rx_list_elem *
-e100_alloc_skb(struct e100_private *bdp)
-{
-	struct sk_buff *new_skb;
-	u32 skb_size = sizeof (rfd_t);
-	struct rx_list_elem *rx_struct;
-
-	new_skb = (struct sk_buff *) dev_alloc_skb(skb_size);
-	if (new_skb) {
-		/* The IP data should be 
-		   DWORD aligned. since the ethernet header is 14 bytes long, 
-		   we need to reserve 2 extra bytes so that the TCP/IP headers
-		   will be DWORD aligned. */
-		skb_reserve(new_skb, 2);
-		if ((rx_struct = e100_get_rx_struct(bdp)) == NULL)
-			goto err;
-		rx_struct->skb = new_skb;
-		rx_struct->dma_addr = pci_map_single(bdp->pdev, new_skb->data,
-						     sizeof (rfd_t),
-						     PCI_DMA_FROMDEVICE);
-		if (!rx_struct->dma_addr)
-			goto err;
-		skb_reserve(new_skb, bdp->rfd_size);
-		return rx_struct;
-	} else {
-		return NULL;
-	}
-
-err:
-	dev_kfree_skb_irq(new_skb);
-	return NULL;
-}
-
-/**
- * e100_add_skb_to_end - add an skb to the end of our rfd list
- * @bdp: atapter's private data struct
- * @rx_struct: rx_list_elem with the new skb
- *
- * Adds a newly allocated skb to the end of our rfd list.
- */
-inline void
-e100_add_skb_to_end(struct e100_private *bdp, struct rx_list_elem *rx_struct)
-{
-	rfd_t *rfdn;		/* The new rfd */
-	rfd_t *rfd;		/* The old rfd */
-	struct rx_list_elem *rx_struct_last;
-
-	(rx_struct->skb)->dev = bdp->device;
-	rfdn = RFD_POINTER(rx_struct->skb, bdp);
-	rfdn->rfd_header.cb_status = 0;
-	rfdn->rfd_header.cb_cmd = __constant_cpu_to_le16(RFD_EL_BIT);
-	rfdn->rfd_act_cnt = 0;
-	rfdn->rfd_sz = __constant_cpu_to_le16(RFD_DATA_SIZE);
-
-	pci_dma_sync_single(bdp->pdev, rx_struct->dma_addr, bdp->rfd_size,
-			    PCI_DMA_TODEVICE);
-
-	if (!list_empty(&(bdp->active_rx_list))) {
-		rx_struct_last = list_entry(bdp->active_rx_list.prev,
-					    struct rx_list_elem, list_elem);
-		rfd = RFD_POINTER(rx_struct_last->skb, bdp);
-		pci_dma_sync_single(bdp->pdev, rx_struct_last->dma_addr,
-				    4, PCI_DMA_FROMDEVICE);
-		put_unaligned(cpu_to_le32(rx_struct->dma_addr),
-			      ((u32 *) (&(rfd->rfd_header.cb_lnk_ptr))));
-
-		pci_dma_sync_single(bdp->pdev, rx_struct_last->dma_addr,
-				    8, PCI_DMA_TODEVICE);
-		rfd->rfd_header.cb_cmd &=
-			__constant_cpu_to_le16((u16) ~RFD_EL_BIT);
-
-		pci_dma_sync_single(bdp->pdev, rx_struct_last->dma_addr,
-				    4, PCI_DMA_TODEVICE);
-	}
-
-	list_add_tail(&(rx_struct->list_elem), &(bdp->active_rx_list));
-}
-
-static inline void
-e100_alloc_skbs(struct e100_private *bdp)
-{
-	for (; bdp->skb_req > 0; bdp->skb_req--) {
-		struct rx_list_elem *rx_struct;
-
-		if ((rx_struct = e100_alloc_skb(bdp)) == NULL)
-			return;
-
-		e100_add_skb_to_end(bdp, rx_struct);
-	}
-}
-
-void e100_tx_srv(struct e100_private *);
-u32 e100_rx_srv(struct e100_private *);
-
-void e100_watchdog(struct net_device *);
-void e100_refresh_txthld(struct e100_private *);
-void e100_manage_adaptive_ifs(struct e100_private *);
-void e100_clear_pools(struct e100_private *);
-static void e100_clear_structs(struct net_device *);
-static inline tcb_t *e100_prepare_xmit_buff(struct e100_private *,
-					    struct sk_buff *);
-static void e100_set_multi_exec(struct net_device *dev);
-
-MODULE_AUTHOR("Intel Corporation, <linux.nics@intel.com>");
-MODULE_DESCRIPTION("Intel(R) PRO/100 Network Driver");
-MODULE_LICENSE("GPL");
-
-E100_PARAM(TxDescriptors, "Number of transmit descriptors");
-E100_PARAM(RxDescriptors, "Number of receive descriptors");
-E100_PARAM(XsumRX, "Disable or enable Receive Checksum offload");
-E100_PARAM(e100_speed_duplex, "Speed and Duplex settings");
-E100_PARAM(ucode, "Disable or enable microcode loading");
-E100_PARAM(ber, "Value for the BER correction algorithm");
-E100_PARAM(flow_control, "Disable or enable Ethernet PAUSE frames processing");
-E100_PARAM(IntDelay, "Value for CPU saver's interrupt delay");
-E100_PARAM(BundleSmallFr, "Disable or enable interrupt bundling of small frames");
-E100_PARAM(BundleMax, "Maximum number for CPU saver's packet bundling");
-E100_PARAM(IFS, "Disable or enable the adaptive IFS algorithm");
-
-/**
- * e100_exec_cmd - issue a comand
- * @bdp: atapter's private data struct
- * @scb_cmd_low: the command that is to be issued
- *
- * This general routine will issue a command to the e100.
- */
-static inline void
-e100_exec_cmd(struct e100_private *bdp, u8 cmd_low)
-{
-	writeb(cmd_low, &(bdp->scb->scb_cmd_low));
-	readw(&(bdp->scb->scb_status));	/* flushes last write, read-safe */
-}
-
-/**
- * e100_wait_scb - wait for SCB to clear
- * @bdp: atapter's private data struct
- *
- * This routine checks to see if the e100 has accepted a command.
- * It does so by checking the command field in the SCB, which will
- * be zeroed by the e100 upon accepting a command.  The loop waits
- * for up to 1 millisecond for command acceptance.
- *
- * Returns:
- *      true if the SCB cleared within 1 millisecond.
- *      false if it didn't clear within 1 millisecond
- */
-unsigned char
-e100_wait_scb(struct e100_private *bdp)
-{
-	int i;
-
-	/* loop on the scb for a few times */
-	for (i = 0; i < 100; i++) {
-		if (!readb(&bdp->scb->scb_cmd_low))
-			return true;
-		cpu_relax();
-	}
-
-	/* it didn't work. do it the slow way using udelay()s */
-	for (i = 0; i < E100_MAX_SCB_WAIT; i++) {
-		if (!readb(&bdp->scb->scb_cmd_low))
-			return true;
-		cpu_relax();
-		udelay(1);
-	}
-
-	return false;
-}
-
-/**
- * e100_wait_exec_simple - issue a command
- * @bdp: atapter's private data struct
- * @scb_cmd_low: the command that is to be issued
- *
- * This general routine will issue a command to the e100 after waiting for
- * the previous command to finish.
- *
- * Returns:
- *      true if the command was issued to the chip successfully
- *      false if the command was not issued to the chip
- */
-inline unsigned char
-e100_wait_exec_simple(struct e100_private *bdp, u8 scb_cmd_low)
-{
-	if (!e100_wait_scb(bdp)) {
-		printk(KERN_DEBUG "e100: %s: e100_wait_exec_simple: failed\n",
-		       bdp->device->name);
-#ifdef E100_CU_DEBUG		
-		printk(KERN_ERR "e100: %s: Last command (%x/%x) "
-			"timeout\n", bdp->device->name, 
-			bdp->last_cmd, bdp->last_sub_cmd);
-		printk(KERN_ERR "e100: %s: Current simple command (%x) "
-			"can't be executed\n", 
-			bdp->device->name, scb_cmd_low);
-#endif		
-		return false;
-	}
-	e100_exec_cmd(bdp, scb_cmd_low);
-#ifdef E100_CU_DEBUG	
-	bdp->last_cmd = scb_cmd_low;
-	bdp->last_sub_cmd = 0;
-#endif	
-	return true;
-}
-
-void
-e100_exec_cmplx(struct e100_private *bdp, u32 phys_addr, u8 cmd)
-{
-	writel(phys_addr, &(bdp->scb->scb_gen_ptr));
-	readw(&(bdp->scb->scb_status));	/* flushes last write, read-safe */
-	e100_exec_cmd(bdp, cmd);
-}
-
-unsigned char
-e100_wait_exec_cmplx(struct e100_private *bdp, u32 phys_addr, u8 cmd, u8 sub_cmd)
-{
-	if (!e100_wait_scb(bdp)) {
-#ifdef E100_CU_DEBUG		
-		printk(KERN_ERR "e100: %s: Last command (%x/%x) "
-			"timeout\n", bdp->device->name, 
-			bdp->last_cmd, bdp->last_sub_cmd);
-		printk(KERN_ERR "e100: %s: Current complex command "
-			"(%x/%x) can't be executed\n", 
-			bdp->device->name, cmd, sub_cmd);
-#endif		
-		return false;
-	}
-	e100_exec_cmplx(bdp, phys_addr, cmd);
-#ifdef E100_CU_DEBUG	
-	bdp->last_cmd = cmd;
-	bdp->last_sub_cmd = sub_cmd;
-#endif	
-	return true;
-}
-
-inline u8
-e100_wait_cus_idle(struct e100_private *bdp)
-{
-	int i;
-
-	/* loop on the scb for a few times */
-	for (i = 0; i < 100; i++) {
-		if (((readw(&(bdp->scb->scb_status)) & SCB_CUS_MASK) !=
-		     SCB_CUS_ACTIVE)) {
-			return true;
-		}
-		cpu_relax();
-	}
-
-	for (i = 0; i < E100_MAX_CU_IDLE_WAIT; i++) {
-		if (((readw(&(bdp->scb->scb_status)) & SCB_CUS_MASK) !=
-		     SCB_CUS_ACTIVE)) {
-			return true;
-		}
-		cpu_relax();
-		udelay(1);
-	}
-
-	return false;
-}
-
-/**
- * e100_disable_clear_intr - disable and clear/ack interrupts
- * @bdp: atapter's private data struct
- *
- * This routine disables interrupts at the hardware, by setting
- * the M (mask) bit in the adapter's CSR SCB command word.
- * It also clear/ack interrupts.
- */
-static inline void
-e100_disable_clear_intr(struct e100_private *bdp)
-{
-	u16 intr_status;
-	/* Disable interrupts on our PCI board by setting the mask bit */
-	writeb(SCB_INT_MASK, &bdp->scb->scb_cmd_hi);
-	intr_status = readw(&bdp->scb->scb_status);
-	/* ack and clear intrs */
-	writew(intr_status, &bdp->scb->scb_status);
-	readw(&bdp->scb->scb_status);
-}
-
-/**
- * e100_set_intr_mask - set interrupts
- * @bdp: atapter's private data struct
- *
- * This routine sets interrupts at the hardware, by resetting
- * the M (mask) bit in the adapter's CSR SCB command word
- */
-static inline void
-e100_set_intr_mask(struct e100_private *bdp)
-{
-	writeb(bdp->intr_mask, &bdp->scb->scb_cmd_hi);
-	readw(&(bdp->scb->scb_status)); /* flushes last write, read-safe */
-}
-
-static inline void
-e100_trigger_SWI(struct e100_private *bdp)
-{
-	/* Trigger interrupt on our PCI board by asserting SWI bit */
-	writeb(SCB_SOFT_INT, &bdp->scb->scb_cmd_hi);
-	readw(&(bdp->scb->scb_status));	/* flushes last write, read-safe */
-}
-
-static int
-e100_found1(struct pci_dev *pcid, const struct pci_device_id *ent)
-{
-	static int first_time = true;
-	struct net_device *dev = NULL;
-	struct e100_private *bdp = NULL;
-	int rc = 0;
-	u16 cal_checksum, read_checksum;
-
-	dev = alloc_etherdev(sizeof (struct e100_private));
-	if (dev == NULL) {
-		printk(KERN_ERR "e100: Not able to alloc etherdev struct\n");
-		rc = -ENODEV;
-		goto out;
-	}
-
-	SET_MODULE_OWNER(dev);
-
-	if (first_time) {
-		first_time = false;
-        	printk(KERN_NOTICE "%s - version %s\n",
-	               e100_full_driver_name, e100_driver_version);
-		printk(KERN_NOTICE "%s\n", e100_copyright);
-		printk(KERN_NOTICE "\n");
-	}
-
-	bdp = dev->priv;
-	bdp->pdev = pcid;
-	bdp->device = dev;
-
-	pci_set_drvdata(pcid, dev);
-	SET_NETDEV_DEV(dev, &pcid->dev);
-
-	bdp->flags = 0;
-	bdp->ifs_state = 0;
-	bdp->ifs_value = 0;
-	bdp->scb = 0;
-
-	init_timer(&bdp->nontx_timer_id);
-	bdp->nontx_timer_id.data = (unsigned long) bdp;
-	bdp->nontx_timer_id.function = (void *) &e100_non_tx_background;
-	INIT_LIST_HEAD(&(bdp->non_tx_cmd_list));
-	bdp->non_tx_command_state = E100_NON_TX_IDLE;
-
-	init_timer(&bdp->watchdog_timer);
-	bdp->watchdog_timer.data = (unsigned long) dev;
-	bdp->watchdog_timer.function = (void *) &e100_watchdog;
-
-	if ((rc = e100_pci_setup(pcid, bdp)) != 0) {
-		goto err_dev;
-	}
-
-	if ((rc = e100_alloc_space(bdp)) != 0) {
-		goto err_pci;
-	}
-
-	if (((bdp->pdev->device > 0x1030)
-	       && (bdp->pdev->device < 0x103F))
-	    || ((bdp->pdev->device >= 0x1050)
-	       && (bdp->pdev->device <= 0x1057))
-	    || (bdp->pdev->device == 0x2449)
-	    || (bdp->pdev->device == 0x2459)
-	    || (bdp->pdev->device == 0x245D)) {
-		bdp->rev_id = D101MA_REV_ID;	/* workaround for ICH3 */
-		bdp->flags |= IS_ICH;
-	}
-
-	if (bdp->rev_id == 0xff)
-		bdp->rev_id = 1;
-
-	if ((u8) bdp->rev_id >= D101A4_REV_ID)
-		bdp->flags |= IS_BACHELOR;
-
-	if ((u8) bdp->rev_id >= D102_REV_ID) {
-		bdp->flags |= USE_IPCB;
-		bdp->rfd_size = 32;
-	} else {
-		bdp->rfd_size = 16;
-	}
-
-	dev->vlan_rx_register = e100_vlan_rx_register;
-	dev->vlan_rx_add_vid = e100_vlan_rx_add_vid;
-	dev->vlan_rx_kill_vid = e100_vlan_rx_kill_vid;
-	dev->irq = pcid->irq;
-	dev->open = &e100_open;
-	dev->hard_start_xmit = &e100_xmit_frame;
-	dev->stop = &e100_close;
-	dev->change_mtu = &e100_change_mtu;
-	dev->get_stats = &e100_get_stats;
-	dev->set_multicast_list = &e100_set_multi;
-	dev->set_mac_address = &e100_set_mac;
-	dev->do_ioctl = &e100_ioctl;
-
-	if (bdp->flags & USE_IPCB)
-	dev->features = NETIF_F_SG | NETIF_F_IP_CSUM |
-			NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX;
-		
-	if ((rc = register_netdev(dev)) != 0) {
-		goto err_dealloc;
-	}
-
-	e100_check_options(e100nics, bdp);
-
-	if (!e100_init(bdp)) {
-		printk(KERN_ERR "e100: Failed to initialize, instance #%d\n",
-		       e100nics);
-		rc = -ENODEV;
-		goto err_unregister_netdev;
-	}
-
-	/* Check if checksum is valid */
-	cal_checksum = e100_eeprom_calculate_chksum(bdp);
-	read_checksum = e100_eeprom_read(bdp, (bdp->eeprom_size - 1));
-	if (cal_checksum != read_checksum) {
-                printk(KERN_ERR "e100: Corrupted EEPROM on instance #%d\n",
-		       e100nics);
-                rc = -ENODEV;
-                goto err_unregister_netdev;
-	}
-	
-	e100nics++;
-
-	e100_get_speed_duplex_caps(bdp);
-
-	printk(KERN_NOTICE
-	       "e100: %s: %s\n", 
-	       bdp->device->name, "Intel(R) PRO/100 Network Connection");
-	e100_print_brd_conf(bdp);
-
-	bdp->wolsupported = 0;
-	bdp->wolopts = 0;
-	if (bdp->rev_id >= D101A4_REV_ID)
-		bdp->wolsupported = WAKE_PHY | WAKE_MAGIC;
-	if (bdp->rev_id >= D101MA_REV_ID)
-		bdp->wolsupported |= WAKE_UCAST | WAKE_ARP;
-	
-	/* Check if WoL is enabled on EEPROM */
-	if (e100_eeprom_read(bdp, EEPROM_ID_WORD) & BIT_5) {
-		/* Magic Packet WoL is enabled on device by default */
-		/* if EEPROM WoL bit is TRUE                        */
-		bdp->wolopts = WAKE_MAGIC;
-	}
-
-	printk(KERN_NOTICE "\n");
-
-	goto out;
-
-err_unregister_netdev:
-	unregister_netdev(dev);
-err_dealloc:
-	e100_dealloc_space(bdp);
-err_pci:
-	iounmap(bdp->scb);
-	pci_release_regions(pcid);
-	pci_disable_device(pcid);
-err_dev:
-	pci_set_drvdata(pcid, NULL);
-	free_netdev(dev);
-out:
-	return rc;
-}
-
-/**
- * e100_clear_structs - free resources
- * @dev: adapter's net_device struct
- *
- * Free all device specific structs, unmap i/o address, etc.
- */
-static void __devexit
-e100_clear_structs(struct net_device *dev)
-{
-	struct e100_private *bdp = dev->priv;
-
-	iounmap(bdp->scb);
-	pci_release_regions(bdp->pdev);
-	pci_disable_device(bdp->pdev);
-
-	e100_dealloc_space(bdp);
-	pci_set_drvdata(bdp->pdev, NULL);
-	free_netdev(dev);
-}
-
-static void __devexit
-e100_remove1(struct pci_dev *pcid)
-{
-	struct net_device *dev;
-	struct e100_private *bdp;
-
-	if (!(dev = (struct net_device *) pci_get_drvdata(pcid)))
-		return;
-
-	bdp = dev->priv;
-
-	unregister_netdev(dev);
-
-	e100_sw_reset(bdp, PORT_SELECTIVE_RESET);
-
-	if (bdp->non_tx_command_state != E100_NON_TX_IDLE) {
-		del_timer_sync(&bdp->nontx_timer_id);
-		e100_free_nontx_list(bdp);
-		bdp->non_tx_command_state = E100_NON_TX_IDLE;
-	}
-
-	e100_clear_structs(dev);
-
-	--e100nics;
-}
-
-static struct pci_device_id e100_id_table[] = {
-	{0x8086, 0x1229, PCI_ANY_ID, PCI_ANY_ID, 0, 0, },
-	{0x8086, 0x2449, PCI_ANY_ID, PCI_ANY_ID, 0, 0, },
-	{0x8086, 0x1059, PCI_ANY_ID, PCI_ANY_ID, 0, 0, },
-	{0x8086, 0x1209, PCI_ANY_ID, PCI_ANY_ID, 0, 0, },
-  	{0x8086, 0x1029, PCI_ANY_ID, PCI_ANY_ID, 0, 0, },
-	{0x8086, 0x1030, PCI_ANY_ID, PCI_ANY_ID, 0, 0, },	
-	{0x8086, 0x1031, PCI_ANY_ID, PCI_ANY_ID, 0, 0, }, 
-	{0x8086, 0x1032, PCI_ANY_ID, PCI_ANY_ID, 0, 0, },
-	{0x8086, 0x1033, PCI_ANY_ID, PCI_ANY_ID, 0, 0, }, 
-	{0x8086, 0x1034, PCI_ANY_ID, PCI_ANY_ID, 0, 0, }, 
-	{0x8086, 0x1038, PCI_ANY_ID, PCI_ANY_ID, 0, 0, },
-	{0x8086, 0x1039, PCI_ANY_ID, PCI_ANY_ID, 0, 0, },
-	{0x8086, 0x103A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, },
-	{0x8086, 0x103B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, },
-	{0x8086, 0x103C, PCI_ANY_ID, PCI_ANY_ID, 0, 0, },
-	{0x8086, 0x103D, PCI_ANY_ID, PCI_ANY_ID, 0, 0, },
-	{0x8086, 0x103E, PCI_ANY_ID, PCI_ANY_ID, 0, 0, },
-	{0x8086, 0x1050, PCI_ANY_ID, PCI_ANY_ID, 0, 0, },
-	{0x8086, 0x1051, PCI_ANY_ID, PCI_ANY_ID, 0, 0, },
-	{0x8086, 0x1052, PCI_ANY_ID, PCI_ANY_ID, 0, 0, },
-	{0x8086, 0x1053, PCI_ANY_ID, PCI_ANY_ID, 0, 0, },
-	{0x8086, 0x1054, PCI_ANY_ID, PCI_ANY_ID, 0, 0, },
-	{0x8086, 0x1055, PCI_ANY_ID, PCI_ANY_ID, 0, 0, },
-	{0x8086, 0x2459, PCI_ANY_ID, PCI_ANY_ID, 0, 0, },
-	{0x8086, 0x245D, PCI_ANY_ID, PCI_ANY_ID, 0, 0, },
-	{0,} /* This has to be the last entry*/
-};
-MODULE_DEVICE_TABLE(pci, e100_id_table);
-
-static struct pci_driver e100_driver = {
-	.name         = "e100",
-	.id_table     = e100_id_table,
-	.probe        = e100_found1,
-	.remove       = __devexit_p(e100_remove1),
-#ifdef CONFIG_PM
-	.suspend      = e100_suspend,
-	.resume       = e100_resume,
-#endif
-};
-
-static int __init
-e100_init_module(void)
-{
-	int ret;
-        ret = pci_module_init(&e100_driver);
-
-	if(ret >= 0) {
-#ifdef CONFIG_PM
-		register_reboot_notifier(&e100_notifier_reboot);
-#endif 
-	}
-
-	return ret;
-}
-
-static void __exit
-e100_cleanup_module(void)
-{
-#ifdef CONFIG_PM	
-	unregister_reboot_notifier(&e100_notifier_reboot);
-#endif 
-
-	pci_unregister_driver(&e100_driver);
-}
-
-module_init(e100_init_module);
-module_exit(e100_cleanup_module);
-
-/**
- * e100_check_options - check command line options
- * @board: board number
- * @bdp: atapter's private data struct
- *
- * This routine does range checking on command-line options
- */
-void
-e100_check_options(int board, struct e100_private *bdp)
-{
-	if (board >= E100_MAX_NIC) {
-		printk(KERN_NOTICE 
-		       "e100: No configuration available for board #%d\n",
-		       board);
-		printk(KERN_NOTICE "e100: Using defaults for all values\n");
-		board = E100_MAX_NIC;
-	}
-
-	e100_set_int_option(&(bdp->params.TxDescriptors), TxDescriptors[board],
-			    E100_MIN_TCB, E100_MAX_TCB, E100_DEFAULT_TCB,
-			    "TxDescriptor count");
-
-	e100_set_int_option(&(bdp->params.RxDescriptors), RxDescriptors[board],
-			    E100_MIN_RFD, E100_MAX_RFD, E100_DEFAULT_RFD,
-			    "RxDescriptor count");
-
-	e100_set_int_option(&(bdp->params.e100_speed_duplex),
-			    e100_speed_duplex[board], 0, 4,
-			    E100_DEFAULT_SPEED_DUPLEX, "speed/duplex mode");
-
-	e100_set_int_option(&(bdp->params.ber), ber[board], 0, ZLOCK_MAX_ERRORS,
-			    E100_DEFAULT_BER, "Bit Error Rate count");
-
-	e100_set_bool_option(bdp, XsumRX[board], PRM_XSUMRX, E100_DEFAULT_XSUM,
-			     "XsumRX value");
-
-	/* Default ucode value depended on controller revision */
-	if (bdp->rev_id >= D101MA_REV_ID) {
-		e100_set_bool_option(bdp, ucode[board], PRM_UCODE,
-				     E100_DEFAULT_UCODE, "ucode value");
-	} else {
-		e100_set_bool_option(bdp, ucode[board], PRM_UCODE, false,
-				     "ucode value");
-	}
-
-	e100_set_bool_option(bdp, flow_control[board], PRM_FC, E100_DEFAULT_FC,
-			     "flow control value");
-
-	e100_set_bool_option(bdp, IFS[board], PRM_IFS, E100_DEFAULT_IFS,
-			     "IFS value");
-
-	e100_set_bool_option(bdp, BundleSmallFr[board], PRM_BUNDLE_SMALL,
-			     E100_DEFAULT_BUNDLE_SMALL_FR,
-			     "CPU saver bundle small frames value");
-
-	e100_set_int_option(&(bdp->params.IntDelay), IntDelay[board], 0x0,
-			    0xFFFF, E100_DEFAULT_CPUSAVER_INTERRUPT_DELAY,
-			    "CPU saver interrupt delay value");
-
-	e100_set_int_option(&(bdp->params.BundleMax), BundleMax[board], 0x1,
-			    0xFFFF, E100_DEFAULT_CPUSAVER_BUNDLE_MAX,
-			    "CPU saver bundle max value");
-
-}
-
-/**
- * e100_set_int_option - check and set an integer option
- * @option: a pointer to the relevant option field
- * @val: the value specified
- * @min: the minimum valid value
- * @max: the maximum valid value
- * @default_val: the default value
- * @name: the name of the option
- *
- * This routine does range checking on a command-line option.
- * If the option's value is '-1' use the specified default.
- * Otherwise, if the value is invalid, change it to the default.
- */
-void
-e100_set_int_option(int *option, int val, int min, int max, int default_val,
-		    char *name)
-{
-	if (val == -1) {	/* no value specified. use default */
-		*option = default_val;
-
-	} else if ((val < min) || (val > max)) {
-		printk(KERN_NOTICE
-		       "e100: Invalid %s specified (%i). "
-		       "Valid range is %i-%i\n",
-		       name, val, min, max);
-		printk(KERN_NOTICE "e100: Using default %s of %i\n", name,
-		       default_val);
-		*option = default_val;
-	} else {
-		printk(KERN_INFO "e100: Using specified %s of %i\n", name, val);
-		*option = val;
-	}
-}
-
-/**
- * e100_set_bool_option - check and set a boolean option
- * @bdp: atapter's private data struct
- * @val: the value specified
- * @mask: the mask for the relevant option
- * @default_val: the default value
- * @name: the name of the option
- *
- * This routine checks a boolean command-line option.
- * If the option's value is '-1' use the specified default.
- * Otherwise, if the value is invalid (not 0 or 1), 
- * change it to the default.
- */
-void
-e100_set_bool_option(struct e100_private *bdp, int val, u32 mask,
-		     int default_val, char *name)
-{
-	if (val == -1) {
-		if (default_val)
-			bdp->params.b_params |= mask;
-
-	} else if ((val != true) && (val != false)) {
-		printk(KERN_NOTICE
-		       "e100: Invalid %s specified (%i). "
-		       "Valid values are %i/%i\n",
-		       name, val, false, true);
-		printk(KERN_NOTICE "e100: Using default %s of %i\n", name,
-		       default_val);
-
-		if (default_val)
-			bdp->params.b_params |= mask;
-	} else {
-		printk(KERN_INFO "e100: Using specified %s of %i\n", name, val);
-		if (val)
-			bdp->params.b_params |= mask;
-	}
-}
-
-int
-e100_open(struct net_device *dev)
-{
-	struct e100_private *bdp;
-	int rc = 0;
-
-	bdp = dev->priv;
-
-	/* setup the tcb pool */
-	if (!e100_alloc_tcb_pool(bdp)) {
-		rc = -ENOMEM;
-		goto err_exit;
-	}
-	bdp->last_tcb = NULL;
-
-	bdp->tcb_pool.head = 0;
-	bdp->tcb_pool.tail = 1;	
-
-	e100_setup_tcb_pool((tcb_t *) bdp->tcb_pool.data,
-			    bdp->params.TxDescriptors, bdp);
-
-	if (!e100_alloc_rfd_pool(bdp)) {
-		rc = -ENOMEM;
-		goto err_exit;
-	}
-
-	if (!e100_wait_exec_cmplx(bdp, 0, SCB_CUC_LOAD_BASE, 0)) {
-		rc = -EAGAIN;
-		goto err_exit;
-	}
-
-	if (!e100_wait_exec_cmplx(bdp, 0, SCB_RUC_LOAD_BASE, 0)) {
-		rc = -EAGAIN;
-		goto err_exit;
-	}
-
-	mod_timer(&(bdp->watchdog_timer), jiffies + (2 * HZ));
-
-	if (dev->flags & IFF_UP)
-		/* Otherwise process may sleep forever */
-		netif_wake_queue(dev);
-	else
-		netif_start_queue(dev);
-
-	e100_start_ru(bdp);
-	if ((rc = request_irq(dev->irq, &e100intr, SA_SHIRQ,
-			      dev->name, dev)) != 0) {
-		del_timer_sync(&bdp->watchdog_timer);
-		goto err_exit;
-	}
-	bdp->intr_mask = 0;
-	e100_set_intr_mask(bdp);
-
-	e100_force_config(bdp);
-
-	goto exit;
-
-err_exit:
-	e100_clear_pools(bdp);
-exit:
-	return rc;
-}
-
-int
-e100_close(struct net_device *dev)
-{
-	struct e100_private *bdp = dev->priv;
-
-	e100_disable_clear_intr(bdp);
-	free_irq(dev->irq, dev);
-	bdp->intr_mask = SCB_INT_MASK;
-	e100_isolate_driver(bdp);
-
-	netif_carrier_off(bdp->device);
-	bdp->cur_line_speed = 0;
-	bdp->cur_dplx_mode = 0;
-	e100_clear_pools(bdp);
-
-	return 0;
-}
-
-static int
-e100_change_mtu(struct net_device *dev, int new_mtu)
-{
-	if ((new_mtu < 68) || (new_mtu > (ETH_DATA_LEN + VLAN_SIZE)))
-		return -EINVAL;
-
-	dev->mtu = new_mtu;
-	return 0;
-}
-
-static int
-e100_xmit_frame(struct sk_buff *skb, struct net_device *dev)
-{
-	int rc = 0;
-	int notify_stop = false;
-	struct e100_private *bdp = dev->priv;
-
-	if (!spin_trylock(&bdp->bd_non_tx_lock)) {
-		notify_stop = true;
-		rc = 1;
-		goto exit2;
-	}
-
-	/* tcb list may be empty temporarily during releasing resources */
-	if (!TCBS_AVAIL(bdp->tcb_pool) || (bdp->tcb_phys == 0) ||
-	    (bdp->non_tx_command_state != E100_NON_TX_IDLE)) {
-		notify_stop = true;
-		rc = 1;
-		goto exit1;
-	}
-
-	bdp->drv_stats.net_stats.tx_bytes += skb->len;
-
-	e100_prepare_xmit_buff(bdp, skb);
-
-	dev->trans_start = jiffies;
-
-exit1:
-	spin_unlock(&bdp->bd_non_tx_lock);
-exit2:
-	if (notify_stop) {
-		netif_stop_queue(dev);
-	}
-
-	return rc;
-}
-
-/**
- * e100_get_stats - get driver statistics
- * @dev: adapter's net_device struct
- *
- * This routine is called when the OS wants the adapter's stats returned.
- * It returns the address of the net_device_stats stucture for the device.
- * If the statistics are currently being updated, then they might be incorrect
- * for a short while. However, since this cannot actually cause damage, no
- * locking is used.
- */
-struct net_device_stats *
-e100_get_stats(struct net_device *dev)
-{
-	struct e100_private *bdp = dev->priv;
-
-	bdp->drv_stats.net_stats.tx_errors =
-		bdp->drv_stats.net_stats.tx_carrier_errors +
-		bdp->drv_stats.net_stats.tx_aborted_errors;
-
-	bdp->drv_stats.net_stats.rx_errors =
-		bdp->drv_stats.net_stats.rx_crc_errors +
-		bdp->drv_stats.net_stats.rx_frame_errors +
-		bdp->drv_stats.net_stats.rx_length_errors +
-		bdp->drv_stats.rcv_cdt_frames;
-
-	return &(bdp->drv_stats.net_stats);
-}
-
-/**
- * e100_set_mac - set the MAC address
- * @dev: adapter's net_device struct
- * @addr: the new address
- *
- * This routine sets the ethernet address of the board
- * Returns:
- * 0  - if successful
- * -1 - otherwise
- */
-static int
-e100_set_mac(struct net_device *dev, void *addr)
-{
-	struct e100_private *bdp;
-	int rc = -1;
-	struct sockaddr *p_sockaddr = (struct sockaddr *) addr;
-
-	if (!is_valid_ether_addr(p_sockaddr->sa_data))
-		return -EADDRNOTAVAIL;
-	bdp = dev->priv;
-
-	if (e100_setup_iaaddr(bdp, (u8 *) (p_sockaddr->sa_data))) {
-		memcpy(&(dev->dev_addr[0]), p_sockaddr->sa_data, ETH_ALEN);
-		rc = 0;
-	}
-
-	return rc;
-}
-
-static void
-e100_set_multi_exec(struct net_device *dev)
-{
-	struct e100_private *bdp = dev->priv;
-	mltcst_cb_t *mcast_buff;
-	cb_header_t *cb_hdr;
-	struct dev_mc_list *mc_list;
-	unsigned int i;
-	nxmit_cb_entry_t *cmd = e100_alloc_non_tx_cmd(bdp);
-
-	if (cmd != NULL) {
-		mcast_buff = &((cmd->non_tx_cmd)->ntcb.multicast);
-		cb_hdr = &((cmd->non_tx_cmd)->ntcb.multicast.mc_cbhdr);
-	} else {
-		return;
-	}
-
-	/* initialize the multi cast command */
-	cb_hdr->cb_cmd = __constant_cpu_to_le16(CB_MULTICAST);
-
-	/* now fill in the rest of the multicast command */
-	*(u16 *) (&(mcast_buff->mc_count)) = cpu_to_le16(dev->mc_count * 6);
-	for (i = 0, mc_list = dev->mc_list;
-	     (i < dev->mc_count) && (i < MAX_MULTICAST_ADDRS);
-	     i++, mc_list = mc_list->next) {
-		/* copy into the command */
-		memcpy(&(mcast_buff->mc_addr[i * ETH_ALEN]),
-		       (u8 *) &(mc_list->dmi_addr), ETH_ALEN);
-	}
-
-	if (!e100_exec_non_cu_cmd(bdp, cmd)) {
-		printk(KERN_WARNING "e100: %s: Multicast setup failed\n", 
-		       dev->name);
-	}
-}
-
-/**
- * e100_set_multi - set multicast status
- * @dev: adapter's net_device struct
- *
- * This routine is called to add or remove multicast addresses, and/or to
- * change the adapter's promiscuous state.
- */
-static void
-e100_set_multi(struct net_device *dev)
-{
-	struct e100_private *bdp = dev->priv;
-	unsigned char promisc_enbl;
-	unsigned char mulcast_enbl;
-
-	promisc_enbl = ((dev->flags & IFF_PROMISC) == IFF_PROMISC);
-	mulcast_enbl = ((dev->flags & IFF_ALLMULTI) ||
-			(dev->mc_count > MAX_MULTICAST_ADDRS));
-
-	e100_config_promisc(bdp, promisc_enbl);
-	e100_config_mulcast_enbl(bdp, mulcast_enbl);
-
-	/* reconfigure the chip if something has changed in its config space */
-	e100_config(bdp);
-
-	if (promisc_enbl || mulcast_enbl) {
-		return;	/* no need for Multicast Cmd */
-	}
-
-	/* get the multicast CB */
-	e100_set_multi_exec(dev);
-}
-
-static int
-e100_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
-{
-
-	switch (cmd) {
-
-	case SIOCETHTOOL:
-		return e100_do_ethtool_ioctl(dev, ifr);
-		break;
-
-	case SIOCGMIIPHY:	/* Get address of MII PHY in use. */
-	case SIOCGMIIREG:	/* Read MII PHY register. */
-	case SIOCSMIIREG:	/* Write to MII PHY register. */
-		return e100_mii_ioctl(dev, ifr, cmd);
-		break;
-
-	default:
-		return -EOPNOTSUPP;
-	}
-	return 0;
-
-}
-
-/**
- * e100init - initialize the adapter
- * @bdp: atapter's private data struct
- *
- * This routine is called when this driver is loaded. This is the initialization
- * routine which allocates memory, configures the adapter and determines the
- * system resources.
- *
- * Returns:
- *      true: if successful
- *      false: otherwise
- */
-static unsigned char
-e100_init(struct e100_private *bdp)
-{
-	u32 st_timeout = 0;
-	u32 st_result = 0;
-	e100_sw_init(bdp);
-
-	if (!e100_selftest(bdp, &st_timeout, &st_result)) {
-        	if (st_timeout) {
-			printk(KERN_ERR "e100: selftest timeout\n");
-		} else {
-			printk(KERN_ERR "e100: selftest failed. Results: %x\n",
-					st_result);
-		}
-		return false;
-	}
-	else
-		printk(KERN_DEBUG "e100: selftest OK.\n");
-
-	/* read the MAC address from the eprom */
-	e100_rd_eaddr(bdp);
-	if (!is_valid_ether_addr(bdp->device->dev_addr)) {
-		printk(KERN_ERR "e100: Invalid Ethernet address\n");
-		return false;
-	}
-	/* read NIC's part number */
-	e100_rd_pwa_no(bdp);
-
-	if (!e100_hw_init(bdp))
-		return false;
-	/* Interrupts are enabled after device reset */
-	e100_disable_clear_intr(bdp);
-
-	return true;
-}
-
-/**
- * e100_sw_init - initialize software structs
- * @bdp: atapter's private data struct
- * 
- * This routine initializes all software structures. Sets up the
- * circular structures for the RFD's & TCB's. Allocates the per board
- * structure for storing adapter information. The CSR is also memory 
- * mapped in this routine.
- *
- * Returns :
- *      true: if S/W was successfully initialized
- *      false: otherwise
- */
-static unsigned char
-e100_sw_init(struct e100_private *bdp)
-{
-	bdp->next_cu_cmd = START_WAIT;	// init the next cu state
-
-	/* 
-	 * Set the value for # of good xmits per underrun. the value assigned
-	 * here is an intelligent  suggested default. Nothing magical about it.
-	 */
-	bdp->tx_per_underrun = DEFAULT_TX_PER_UNDERRUN;
-
-	/* get the default transmit threshold value */
-	bdp->tx_thld = TX_THRSHLD;
-
-	/* get the EPROM size */
-	bdp->eeprom_size = e100_eeprom_size(bdp);
-
-	/* Initialize our spinlocks */
-	spin_lock_init(&(bdp->bd_lock));
-	spin_lock_init(&(bdp->bd_non_tx_lock));
-	spin_lock_init(&(bdp->config_lock));
-	spin_lock_init(&(bdp->mdi_access_lock));
-	/* Initialize configuration data */
-	e100_config_init(bdp);
-
-	return 1;
-}
-
-static void
-e100_tco_workaround(struct e100_private *bdp)
-{
-	int i;
-
-	/* Do software reset */
-	e100_sw_reset(bdp, PORT_SOFTWARE_RESET);
-
-	/* Do a dummy LOAD CU BASE command. */
-	/* This gets us out of pre-driver to post-driver. */
-	e100_exec_cmplx(bdp, 0, SCB_CUC_LOAD_BASE);
-
-	/* Wait 20 msec for reset to take effect */
-	set_current_state(TASK_UNINTERRUPTIBLE);
-	schedule_timeout(HZ / 50 + 1);
-
-	/* disable interrupts since they are enabled */
-	/* after device reset                        */
-	e100_disable_clear_intr(bdp);
-
-	/* Wait for command to be cleared up to 1 sec */
-	for (i=0; i<100; i++) {
-		if (!readb(&bdp->scb->scb_cmd_low))
-			break;
-		set_current_state(TASK_UNINTERRUPTIBLE);
-		schedule_timeout(HZ / 100 + 1);
-	}
-
-	/* Wait for TCO request bit in PMDR register to be clear */
-	for (i=0; i<50; i++) {
-		if (!(readb(&bdp->scb->scb_ext.d101m_scb.scb_pmdr) & BIT_1))
-			break;
-		set_current_state(TASK_UNINTERRUPTIBLE);
-		schedule_timeout(HZ / 100 + 1);
-	}
-}
-
-/**
- * e100_hw_init - initialized tthe hardware
- * @bdp: atapter's private data struct
- *
- * This routine performs a reset on the adapter, and configures the adapter.
- * This includes configuring the 82557 LAN controller, validating and setting
- * the node address, detecting and configuring the Phy chip on the adapter,
- * and initializing all of the on chip counters.
- *
- * Returns:
- *      true - If the adapter was initialized
- *      false - If the adapter failed initialization
- */
-unsigned char
-e100_hw_init(struct e100_private *bdp)
-{
-	if (!e100_phy_init(bdp))
-		goto err;
-
-	e100_sw_reset(bdp, PORT_SELECTIVE_RESET);
-
-	/* Only 82559 or above needs TCO workaround */
-	if (bdp->rev_id >= D101MA_REV_ID)
-		e100_tco_workaround(bdp);
-
-	/* Load the CU BASE (set to 0, because we use linear mode) */
-	if (!e100_wait_exec_cmplx(bdp, 0, SCB_CUC_LOAD_BASE, 0))
-		goto err;
-
-	if (!e100_wait_exec_cmplx(bdp, 0, SCB_RUC_LOAD_BASE, 0))
-		goto err;
-
-	/* Load interrupt microcode  */
-	if (e100_load_microcode(bdp)) {
-		bdp->flags |= DF_UCODE_LOADED;
-	}
-
-	if ((u8) bdp->rev_id < D101A4_REV_ID)
-		e100_config_init_82557(bdp);
-		
-	if (!e100_config(bdp))
-		goto err;
-
-	if (!e100_setup_iaaddr(bdp, bdp->device->dev_addr))
-		goto err;
-
-	/* Clear the internal counters */
-	if (!e100_clr_cntrs(bdp))
-		goto err;
-
-	/* Change for 82558 enhancement */
-	/* If 82558/9 and if the user has enabled flow control, set up the
-	 * Flow Control Reg. in the CSR */
-	if ((bdp->flags & IS_BACHELOR)
-	    && (bdp->params.b_params & PRM_FC)) {
-		writeb(DFLT_FC_THLD, &bdp->scb->scb_ext.d101_scb.scb_fc_thld);
-		writeb(DFLT_FC_CMD,
-		       &bdp->scb->scb_ext.d101_scb.scb_fc_xon_xoff);
-	}
-
-	return true;
-err:
-	printk(KERN_ERR "e100: hw init failed\n");
-	return false;
-}
-
-/**
- * e100_setup_tcb_pool - setup TCB circular list
- * @head: Pointer to head of the allocated TCBs
- * @qlen: Number of elements in the queue
- * @bdp: atapter's private data struct
- * 
- * This routine arranges the contigiously allocated TCB's in a circular list.
- * Also does the one time initialization of the TCBs.
- */
-static void
-e100_setup_tcb_pool(tcb_t *head, unsigned int qlen, struct e100_private *bdp)
-{
-	int ele_no;
-	tcb_t *pcurr_tcb;	/* point to current tcb */
-	u32 next_phys;		/* the next phys addr */
-	u16 txcommand = CB_S_BIT | CB_TX_SF_BIT;
-
-	bdp->tx_count = 0;
-	if (bdp->flags & USE_IPCB) {
-		txcommand |= CB_IPCB_TRANSMIT | CB_CID_DEFAULT;
-	} else if (bdp->flags & IS_BACHELOR) {
-		txcommand |= CB_TRANSMIT | CB_CID_DEFAULT;
-	} else {
-		txcommand |= CB_TRANSMIT;
-	}
-
-	for (ele_no = 0, next_phys = bdp->tcb_phys, pcurr_tcb = head;
-	     ele_no < qlen; ele_no++, pcurr_tcb++) {
-
-		/* set the phys addr for this TCB, next_phys has not incr. yet */
-		pcurr_tcb->tcb_phys = next_phys;
-		next_phys += sizeof (tcb_t);
-
-		/* set the link to next tcb */
-		if (ele_no == (qlen - 1))
-			pcurr_tcb->tcb_hdr.cb_lnk_ptr =
-				cpu_to_le32(bdp->tcb_phys);
-		else
-			pcurr_tcb->tcb_hdr.cb_lnk_ptr = cpu_to_le32(next_phys);
-
-		pcurr_tcb->tcb_hdr.cb_status = 0;
-		pcurr_tcb->tcb_hdr.cb_cmd = cpu_to_le16(txcommand);
-		pcurr_tcb->tcb_cnt = 0;	
-		pcurr_tcb->tcb_thrshld = bdp->tx_thld;	
-		if (ele_no < 2) {
-			pcurr_tcb->tcb_hdr.cb_status =
-				cpu_to_le16(CB_STATUS_COMPLETE);
-		}
-		pcurr_tcb->tcb_tbd_num = 1;
-
-		if (bdp->flags & IS_BACHELOR) {
-			pcurr_tcb->tcb_tbd_ptr =
-				__constant_cpu_to_le32(0xFFFFFFFF);
-		} else {
-			pcurr_tcb->tcb_tbd_ptr =
-				cpu_to_le32(pcurr_tcb->tcb_phys + 0x10);
-		}
-
-		if (bdp->flags & IS_BACHELOR) {
-			pcurr_tcb->tcb_tbd_expand_ptr =
-				cpu_to_le32(pcurr_tcb->tcb_phys + 0x20);
-		} else {
-			pcurr_tcb->tcb_tbd_expand_ptr =
-				cpu_to_le32(pcurr_tcb->tcb_phys + 0x10);
-		}
-		pcurr_tcb->tcb_tbd_dflt_ptr = pcurr_tcb->tcb_tbd_ptr;
-
-		if (bdp->flags & USE_IPCB) {
-			pcurr_tcb->tbd_ptr = &(pcurr_tcb->tcbu.tbd_array[1]);
-			pcurr_tcb->tcbu.ipcb.ip_activation_high =
-				IPCB_IP_ACTIVATION_DEFAULT;
-			pcurr_tcb->tcbu.ipcb.vlan = 0;
-		} else {
-			pcurr_tcb->tbd_ptr = &(pcurr_tcb->tcbu.tbd_array[0]);
-		}
-
-		pcurr_tcb->tcb_skb = NULL;
-	}
-
-	wmb();
-}
-
-/***************************************************************************/
-/***************************************************************************/
-/*       Memory Management Routines                                        */
-/***************************************************************************/
-
-/**
- * e100_alloc_space - allocate private driver data
- * @bdp: atapter's private data struct
- *
- * This routine allocates memory for the driver. Memory allocated is for the
- * selftest and statistics structures.
- *
- * Returns:
- *      0: if the operation was successful
- *      %-ENOMEM: if memory allocation failed
- */
-unsigned char
-e100_alloc_space(struct e100_private *bdp)
-{
-	unsigned long off;
-
-	/* allocate all the dma-able structures in one call:
-	 * selftest results, adapter stats, and non-tx cb commands */
-	if (!(bdp->dma_able =
-	      pci_alloc_consistent(bdp->pdev, sizeof (bd_dma_able_t),
-				   &(bdp->dma_able_phys)))) {
-		goto err;
-	}
-
-	/* now assign the various pointers into the struct we've just allocated */
-	off = offsetof(bd_dma_able_t, selftest);
-
-	bdp->selftest = (self_test_t *) (bdp->dma_able + off);
-	bdp->selftest_phys = bdp->dma_able_phys + off;
-
-	off = offsetof(bd_dma_able_t, stats_counters);
-
-	bdp->stats_counters = (max_counters_t *) (bdp->dma_able + off);
-	bdp->stat_cnt_phys = bdp->dma_able_phys + off;
-
-	return 0;
-
-err:
-	printk(KERN_ERR
-	       "e100: Failed to allocate memory\n");
-	return -ENOMEM;
-}
-
-/**
- * e100_alloc_tcb_pool - allocate TCB circular list
- * @bdp: atapter's private data struct
- *
- * This routine allocates memory for the circular list of transmit descriptors.
- *
- * Returns:
- *       0: if allocation has failed.
- *       1: Otherwise. 
- */
-int
-e100_alloc_tcb_pool(struct e100_private *bdp)
-{
-	int stcb = sizeof (tcb_t) * bdp->params.TxDescriptors;
-
-	/* allocate space for the TCBs */
-	if (!(bdp->tcb_pool.data =
-	      pci_alloc_consistent(bdp->pdev, stcb, &bdp->tcb_phys)))
-		return 0;
-
-	memset(bdp->tcb_pool.data, 0x00, stcb);
-
-	return 1;
-}
-
-void
-e100_free_tcb_pool(struct e100_private *bdp)
-{
-	tcb_t *tcb;
-	int i;
-	/* Return tx skbs */ 
-	for (i = 0; i < bdp->params.TxDescriptors; i++) {
-	  	tcb = bdp->tcb_pool.data;
-		tcb += bdp->tcb_pool.head;
-  		e100_tx_skb_free(bdp, tcb);
-		if (NEXT_TCB_TOUSE(bdp->tcb_pool.head) == bdp->tcb_pool.tail)
-		  	break;
-		bdp->tcb_pool.head = NEXT_TCB_TOUSE(bdp->tcb_pool.head);
-	}
-	pci_free_consistent(bdp->pdev,
-			    sizeof (tcb_t) * bdp->params.TxDescriptors,
-			    bdp->tcb_pool.data, bdp->tcb_phys);
-	bdp->tcb_pool.head = 0;
-	bdp->tcb_pool.tail = 1;	
-	bdp->tcb_phys = 0;
-}
-
-static void
-e100_dealloc_space(struct e100_private *bdp)
-{
-	if (bdp->dma_able) {
-		pci_free_consistent(bdp->pdev, sizeof (bd_dma_able_t),
-				    bdp->dma_able, bdp->dma_able_phys);
-	}
-
-	bdp->selftest_phys = 0;
-	bdp->stat_cnt_phys = 0;
-	bdp->dma_able_phys = 0;
-	bdp->dma_able = 0;
-}
-
-static void
-e100_free_rfd_pool(struct e100_private *bdp)
-{
-	struct rx_list_elem *rx_struct;
-
-	while (!list_empty(&(bdp->active_rx_list))) {
-
-		rx_struct = list_entry(bdp->active_rx_list.next,
-				       struct rx_list_elem, list_elem);
-		list_del(&(rx_struct->list_elem));
-		pci_unmap_single(bdp->pdev, rx_struct->dma_addr,
-				 sizeof (rfd_t), PCI_DMA_TODEVICE);
-		dev_kfree_skb(rx_struct->skb);
-		kfree(rx_struct);
-	}
-
-	while (!list_empty(&(bdp->rx_struct_pool))) {
-		rx_struct = list_entry(bdp->rx_struct_pool.next,
-				       struct rx_list_elem, list_elem);
-		list_del(&(rx_struct->list_elem));
-		kfree(rx_struct);
-	}
-}
-
-/**
- * e100_alloc_rfd_pool - allocate RFDs
- * @bdp: atapter's private data struct
- *
- * Allocates initial pool of skb which holds both rfd and data,
- * and return a pointer to the head of the list
- */
-static int
-e100_alloc_rfd_pool(struct e100_private *bdp)
-{
-	struct rx_list_elem *rx_struct;
-	int i;
-
-	INIT_LIST_HEAD(&(bdp->active_rx_list));
-	INIT_LIST_HEAD(&(bdp->rx_struct_pool));
-	bdp->skb_req = bdp->params.RxDescriptors;
-	for (i = 0; i < bdp->skb_req; i++) {
-		rx_struct = kmalloc(sizeof (struct rx_list_elem), GFP_ATOMIC);
-		list_add(&(rx_struct->list_elem), &(bdp->rx_struct_pool));
-	}
-	e100_alloc_skbs(bdp);
-	return !list_empty(&(bdp->active_rx_list));
-
-}
-
-void
-e100_clear_pools(struct e100_private *bdp)
-{
-	bdp->last_tcb = NULL;
-	e100_free_rfd_pool(bdp);
-	e100_free_tcb_pool(bdp);
-}
-
-/*****************************************************************************/
-/*****************************************************************************/
-/*      Run Time Functions                                                   */
-/*****************************************************************************/
-
-/**
- * e100_watchdog
- * @dev: adapter's net_device struct
- *
- * This routine runs every 2 seconds and updates our statitics and link state,
- * and refreshs txthld value.
- */
-void
-e100_watchdog(struct net_device *dev)
-{
-	struct e100_private *bdp = dev->priv;
-
-#ifdef E100_CU_DEBUG
-	if (e100_cu_unknown_state(bdp)) {
-		printk(KERN_ERR "e100: %s: CU unknown state in e100_watchdog\n",
-			dev->name);
-	}
-#endif	
-	if (!netif_running(dev)) {
-		return;
-	}
-
-	/* check if link state has changed */
-	if (e100_phy_check(bdp)) {
-		if (netif_carrier_ok(dev)) {
-			printk(KERN_ERR
-			       "e100: %s NIC Link is Up %d Mbps %s duplex\n",
-			       bdp->device->name, bdp->cur_line_speed,
-			       (bdp->cur_dplx_mode == HALF_DUPLEX) ?
-			       "Half" : "Full");
-
-			e100_config_fc(bdp);
-			e100_config(bdp);  
-
-		} else {
-			printk(KERN_ERR "e100: %s NIC Link is Down\n",
-			       bdp->device->name);
-		}
-	}
-
-	// toggle the tx queue according to link status
-	// this also resolves a race condition between tx & non-cu cmd flows
-	if (netif_carrier_ok(dev)) {
-		if (netif_running(dev))
-			netif_wake_queue(dev);
-	} else {
-		if (netif_running(dev))
-			netif_stop_queue(dev);
-		/* When changing to non-autoneg, device may lose  */
-		/* link with some switches. e100 will try to      */
-		/* revover link by sending command to PHY layer   */
-		if (bdp->params.e100_speed_duplex != E100_AUTONEG)
-			e100_force_speed_duplex_to_phy(bdp);
-	}
-
-	rmb();
-
-	if (e100_update_stats(bdp)) {
-
-		/* Check if a change in the IFS parameter is needed,
-		   and configure the device accordingly */
-		if (bdp->params.b_params & PRM_IFS)
-			e100_manage_adaptive_ifs(bdp);
-
-		/* Now adjust our dynamic tx threshold value */
-		e100_refresh_txthld(bdp);
-
-		/* Now if we are on a 557 and we havn't received any frames then we
-		 * should issue a multicast command to reset the RU */
-		if (bdp->rev_id < D101A4_REV_ID) {
-			if (!(bdp->stats_counters->basic_stats.rcv_gd_frames)) {
-				e100_set_multi(dev);
-			}
-		}
-	}
-	/* Issue command to dump statistics from device.        */
-	/* Check for command completion on next watchdog timer. */
-	e100_dump_stats_cntrs(bdp);
-
-	wmb();
-
-	/* relaunch watchdog timer in 2 sec */
-	mod_timer(&(bdp->watchdog_timer), jiffies + (2 * HZ));
-
-	if (list_empty(&bdp->active_rx_list))
-		e100_trigger_SWI(bdp);
-}
-
-/**
- * e100_manage_adaptive_ifs
- * @bdp: atapter's private data struct
- *
- * This routine manages the adaptive Inter-Frame Spacing algorithm
- * using a state machine.
- */
-void
-e100_manage_adaptive_ifs(struct e100_private *bdp)
-{
-	static u16 state_table[9][4] = {	// rows are states
-		{2, 0, 0, 0},	// state0   // column0: next state if increasing
-		{2, 0, 5, 30},	// state1   // column1: next state if decreasing
-		{5, 1, 5, 30},	// state2   // column2: IFS value for 100 mbit
-		{5, 3, 0, 0},	// state3   // column3: IFS value for 10 mbit
-		{5, 3, 10, 60},	// state4
-		{8, 4, 10, 60},	// state5
-		{8, 6, 0, 0},	// state6
-		{8, 6, 20, 60},	// state7
-		{8, 7, 20, 60}	// state8
-	};
-
-	u32 transmits =
-		le32_to_cpu(bdp->stats_counters->basic_stats.xmt_gd_frames);
-	u32 collisions =
-		le32_to_cpu(bdp->stats_counters->basic_stats.xmt_ttl_coll);
-	u32 state = bdp->ifs_state;
-	u32 old_value = bdp->ifs_value;
-	int next_col;
-	u32 min_transmits;
-
-	if (bdp->cur_dplx_mode == FULL_DUPLEX) {
-		bdp->ifs_state = 0;
-		bdp->ifs_value = 0;
-
-	} else {		/* Half Duplex */
-		/* Set speed specific parameters */
-		if (bdp->cur_line_speed == 100) {
-			next_col = 2;
-			min_transmits = MIN_NUMBER_OF_TRANSMITS_100;
-
-		} else {	/* 10 Mbps */
-			next_col = 3;
-			min_transmits = MIN_NUMBER_OF_TRANSMITS_10;
-		}
-
-		if ((transmits / 32 < collisions)
-		    && (transmits > min_transmits)) {
-			state = state_table[state][0];	/* increment */
-
-		} else if (transmits < min_transmits) {
-			state = state_table[state][1];	/* decrement */
-		}
-
-		bdp->ifs_value = state_table[state][next_col];
-		bdp->ifs_state = state;
-	}
-
-	/* If the IFS value has changed, configure the device */
-	if (bdp->ifs_value != old_value) {
-		e100_config_ifs(bdp);
-		e100_config(bdp);
-	}
-}
-
-/**
- * e100intr - interrupt handler
- * @irq: the IRQ number
- * @dev_inst: the net_device struct
- * @regs: registers (unused)
- *
- * This routine is the ISR for the e100 board. It services
- * the RX & TX queues & starts the RU if it has stopped due
- * to no resources.
- */
-irqreturn_t
-e100intr(int irq, void *dev_inst, struct pt_regs *regs)
-{
-	struct net_device *dev;
-	struct e100_private *bdp;
-	u16 intr_status;
-
-	dev = dev_inst;
-	bdp = dev->priv;
-
-	intr_status = readw(&bdp->scb->scb_status);
-	/* If not my interrupt, just return */
-	if (!(intr_status & SCB_STATUS_ACK_MASK) || (intr_status == 0xffff)) {
-		return IRQ_NONE;
-	}
-
-	/* disable and ack intr */
-	e100_disable_clear_intr(bdp);
-
-	/* the device is closed, don't continue or else bad things may happen. */
-	if (!netif_running(dev)) {
-		e100_set_intr_mask(bdp);
-		return IRQ_NONE;
-	}
-
-	/* SWI intr (triggered by watchdog) is signal to allocate new skb buffers */
-	if (intr_status & SCB_STATUS_ACK_SWI) {
-		e100_alloc_skbs(bdp);
-	}
-
-	/* do recv work if any */
-	if (intr_status &
-	    (SCB_STATUS_ACK_FR | SCB_STATUS_ACK_RNR | SCB_STATUS_ACK_SWI)) 
-		bdp->drv_stats.rx_intr_pkts += e100_rx_srv(bdp);
-
-	/* clean up after tx'ed packets */
-	if (intr_status & (SCB_STATUS_ACK_CNA | SCB_STATUS_ACK_CX))
-		e100_tx_srv(bdp);
-
-	e100_set_intr_mask(bdp);
-	return IRQ_HANDLED;
-}
-
-/**
- * e100_tx_skb_free - free TX skbs resources
- * @bdp: atapter's private data struct
- * @tcb: associated tcb of the freed skb
- *
- * This routine frees resources of TX skbs.
- */
-static inline void
-e100_tx_skb_free(struct e100_private *bdp, tcb_t *tcb)
-{
-	if (tcb->tcb_skb) {
-		int i;
-		tbd_t *tbd_arr = tcb->tbd_ptr;
-		int frags = skb_shinfo(tcb->tcb_skb)->nr_frags;
-
-		for (i = 0; i <= frags; i++, tbd_arr++) {
-			pci_unmap_single(bdp->pdev,
-					 le32_to_cpu(tbd_arr->tbd_buf_addr),
-					 le16_to_cpu(tbd_arr->tbd_buf_cnt),
-					 PCI_DMA_TODEVICE);
-		}
-		dev_kfree_skb_irq(tcb->tcb_skb);
-		tcb->tcb_skb = NULL;
-	}
-}
-
-/**
- * e100_tx_srv - service TX queues
- * @bdp: atapter's private data struct
- *
- * This routine services the TX queues. It reclaims the TCB's & TBD's & other
- * resources used during the transmit of this buffer. It is called from the ISR.
- * We don't need a tx_lock since we always access buffers which were already
- * prepared.
- */
-void
-e100_tx_srv(struct e100_private *bdp)
-{
-	tcb_t *tcb;
-	int i;
-
-	/* go over at most TxDescriptors buffers */
-	for (i = 0; i < bdp->params.TxDescriptors; i++) {
-		tcb = bdp->tcb_pool.data;
-		tcb += bdp->tcb_pool.head;
-
-		rmb();
-
-		/* if the buffer at 'head' is not complete, break */
-		if (!(tcb->tcb_hdr.cb_status &
-		      __constant_cpu_to_le16(CB_STATUS_COMPLETE)))
-			break;
-
-		/* service next buffer, clear the out of resource condition */
-		e100_tx_skb_free(bdp, tcb);
-
-		if (netif_running(bdp->device))
-			netif_wake_queue(bdp->device);
-
-		/* if we've caught up with 'tail', break */
-		if (NEXT_TCB_TOUSE(bdp->tcb_pool.head) == bdp->tcb_pool.tail) {
-			break;
-		}
-
-		bdp->tcb_pool.head = NEXT_TCB_TOUSE(bdp->tcb_pool.head);
-	}
-}
-
-/**
- * e100_rx_srv - service RX queue
- * @bdp: atapter's private data struct
- * @max_number_of_rfds: max number of RFDs to process
- * @rx_congestion: flag pointer, to inform the calling function of congestion.
- *
- * This routine processes the RX interrupt & services the RX queues.
- * For each successful RFD, it allocates a new msg block, links that
- * into the RFD list, and sends the old msg upstream.
- * The new RFD is then put at the end of the free list of RFD's.
- * It returns the number of serviced RFDs.
- */
-u32
-e100_rx_srv(struct e100_private *bdp)
-{
-	rfd_t *rfd;		/* new rfd, received rfd */
-	int i;
-	u16 rfd_status;
-	struct sk_buff *skb;
-	struct net_device *dev;
-	unsigned int data_sz;
-	struct rx_list_elem *rx_struct;
-	u32 rfd_cnt = 0;
-
-	dev = bdp->device;
-
-	/* current design of rx is as following:
-	 * 1. socket buffer (skb) used to pass network packet to upper layer
-	 * 2. all HW host memory structures (like RFDs, RBDs and data buffers)
-	 *    are placed in a skb's data room
-	 * 3. when rx process is complete, we change skb internal pointers to exclude
-	 *    from data area all unrelated things (RFD, RDB) and to leave
-	 *    just rx'ed packet netto
-	 * 4. for each skb passed to upper layer, new one is allocated instead.
-	 * 5. if no skb left, in 2 sec another atempt to allocate skbs will be made
-	 *    (watchdog trigger SWI intr and isr should allocate new skbs)
-	 */
-	for (i = 0; i < bdp->params.RxDescriptors; i++) {
-		if (list_empty(&(bdp->active_rx_list))) {
-			break;
-		}
-
-		rx_struct = list_entry(bdp->active_rx_list.next,
-				       struct rx_list_elem, list_elem);
-		skb = rx_struct->skb;
-
-		rfd = RFD_POINTER(skb, bdp);	/* locate RFD within skb */
-
-		// sync only the RFD header
-		pci_dma_sync_single(bdp->pdev, rx_struct->dma_addr,
-				    bdp->rfd_size, PCI_DMA_FROMDEVICE);
-		rfd_status = le16_to_cpu(rfd->rfd_header.cb_status);	/* get RFD's status */
-		if (!(rfd_status & RFD_STATUS_COMPLETE))	/* does not contains data yet - exit */
-			break;
-
-		/* to allow manipulation with current skb we need to unlink it */
-		list_del(&(rx_struct->list_elem));
-
-		/* do not free & unmap badly received packet.
-		 * move it to the end of skb list for reuse */
-		if (!(rfd_status & RFD_STATUS_OK)) {
-			e100_add_skb_to_end(bdp, rx_struct);
-			continue;
-		}
-
-		data_sz = min_t(u16, (le16_to_cpu(rfd->rfd_act_cnt) & 0x3fff),
-				(sizeof (rfd_t) - bdp->rfd_size));
-
-		/* now sync all the data */
-		pci_dma_sync_single(bdp->pdev, rx_struct->dma_addr,
-				    (data_sz + bdp->rfd_size),
-				    PCI_DMA_FROMDEVICE);
-
-		pci_unmap_single(bdp->pdev, rx_struct->dma_addr,
-				 sizeof (rfd_t), PCI_DMA_FROMDEVICE);
-
-		list_add(&(rx_struct->list_elem), &(bdp->rx_struct_pool));
-
-		/* end of dma access to rfd */
-		bdp->skb_req++;	/* incr number of requested skbs */
-		e100_alloc_skbs(bdp);	/* and get them */
-
-		/* set packet size, excluding checksum (2 last bytes) if it is present */
-		if ((bdp->flags & DF_CSUM_OFFLOAD)
-		    && (bdp->rev_id < D102_REV_ID))
-			skb_put(skb, (int) data_sz - 2);
-		else
-			skb_put(skb, (int) data_sz);
-
-		/* set the protocol */
-		skb->protocol = eth_type_trans(skb, dev);
-
-		/* set the checksum info */
-		if (bdp->flags & DF_CSUM_OFFLOAD) {
-			if (bdp->rev_id >= D102_REV_ID) {
-				skb->ip_summed = e100_D102_check_checksum(rfd);
-			} else {
-				skb->ip_summed = e100_D101M_checksum(bdp, skb);
-			}
-		} else {
-			skb->ip_summed = CHECKSUM_NONE;
-		}
-
-		bdp->drv_stats.net_stats.rx_bytes += skb->len;
-
-		if(bdp->vlgrp && (rfd_status & CB_STATUS_VLAN)) {
-			vlan_hwaccel_rx(skb, bdp->vlgrp, be16_to_cpu(rfd->vlanid));
-		} else {
-			netif_rx(skb);
-		}
-		dev->last_rx = jiffies;
-		
-		rfd_cnt++;
-	}			/* end of rfd loop */
-
-	/* restart the RU if it has stopped */
-	if ((readw(&bdp->scb->scb_status) & SCB_RUS_MASK) != SCB_RUS_READY) {
-		e100_start_ru(bdp);
-	}
-
-	return rfd_cnt;
-}
-
-void
-e100_refresh_txthld(struct e100_private *bdp)
-{
-	basic_cntr_t *pstat = &(bdp->stats_counters->basic_stats);
-
-	/* as long as tx_per_underrun is not 0, we can go about dynamically *
-	 * adjusting the xmit threshold. we stop doing that & resort to defaults
-	 * * once the adjustments become meaningless. the value is adjusted by *
-	 * dumping the error counters & checking the # of xmit underrun errors *
-	 * we've had. */
-	if (bdp->tx_per_underrun) {
-		/* We are going to last values dumped from the dump statistics
-		 * command */
-		if (le32_to_cpu(pstat->xmt_gd_frames)) {
-			if (le32_to_cpu(pstat->xmt_uruns)) {
-				/* 
-				 * if we have had more than one underrun per "DEFAULT #
-				 * OF XMITS ALLOWED PER UNDERRUN" good xmits, raise the
-				 * THRESHOLD.
-				 */
-				if ((le32_to_cpu(pstat->xmt_gd_frames) /
-				     le32_to_cpu(pstat->xmt_uruns)) <
-				    bdp->tx_per_underrun) {
-					bdp->tx_thld += 3;
-				}
-			}
-
-			/* 
-			 * if we've had less than one underrun per the DEFAULT number of
-			 * of good xmits allowed, lower the THOLD but not less than 0 
-			 */
-			if (le32_to_cpu(pstat->xmt_gd_frames) >
-			    bdp->tx_per_underrun) {
-				bdp->tx_thld--;
-
-				if (bdp->tx_thld < 6)
-					bdp->tx_thld = 6;
-
-			}
-		}
-
-		/* end good xmits */
-		/* 
-		 * * if our adjustments are becoming unresonable, stop adjusting &
-		 * resort * to defaults & pray. A THOLD value > 190 means that the
-		 * adapter will * wait for 190*8=1520 bytes in TX FIFO before it
-		 * starts xmit. Since * MTU is 1514, it doesn't make any sense for
-		 * further increase. */
-		if (bdp->tx_thld >= 190) {
-			bdp->tx_per_underrun = 0;
-			bdp->tx_thld = 189;
-		}
-	}			/* end underrun check */
-}
-
-/**
- * e100_prepare_xmit_buff - prepare a buffer for transmission
- * @bdp: atapter's private data struct
- * @skb: skb to send
- *
- * This routine prepare a buffer for transmission. It checks
- * the message length for the appropiate size. It picks up a
- * free tcb from the TCB pool and sets up the corresponding
- * TBD's. If the number of fragments are more than the number
- * of TBD/TCB it copies all the fragments in a coalesce buffer.
- * It returns a pointer to the prepared TCB.
- */
-static inline tcb_t *
-e100_prepare_xmit_buff(struct e100_private *bdp, struct sk_buff *skb)
-{
-	tcb_t *tcb, *prev_tcb;
-
-	tcb = bdp->tcb_pool.data;
-	tcb += TCB_TO_USE(bdp->tcb_pool);
-
-	if (bdp->flags & USE_IPCB) {
-		tcb->tcbu.ipcb.ip_activation_high = IPCB_IP_ACTIVATION_DEFAULT;
-		tcb->tcbu.ipcb.ip_schedule &= ~IPCB_TCP_PACKET;
-		tcb->tcbu.ipcb.ip_schedule &= ~IPCB_TCPUDP_CHECKSUM_ENABLE;
-	}
-
-	if(bdp->vlgrp && vlan_tx_tag_present(skb)) {
-		(tcb->tcbu).ipcb.ip_activation_high |= IPCB_INSERTVLAN_ENABLE;
-		(tcb->tcbu).ipcb.vlan = cpu_to_be16(vlan_tx_tag_get(skb));
-	}
-	
-	tcb->tcb_hdr.cb_status = 0;
-	tcb->tcb_thrshld = bdp->tx_thld;
-	tcb->tcb_hdr.cb_cmd |= __constant_cpu_to_le16(CB_S_BIT);
-
-	/* Set I (Interrupt) bit on every (TX_FRAME_CNT)th packet */
-	if (!(++bdp->tx_count % TX_FRAME_CNT))
-		tcb->tcb_hdr.cb_cmd |= __constant_cpu_to_le16(CB_I_BIT);
-	else
-		/* Clear I bit on other packets */
-		tcb->tcb_hdr.cb_cmd &= ~__constant_cpu_to_le16(CB_I_BIT);
-
-	tcb->tcb_skb = skb;
-
-	if (skb->ip_summed == CHECKSUM_HW) {
-		const struct iphdr *ip = skb->nh.iph;
-
-		if ((ip->protocol == IPPROTO_TCP) ||
-		    (ip->protocol == IPPROTO_UDP)) {
-
-			tcb->tcbu.ipcb.ip_activation_high |=
-				IPCB_HARDWAREPARSING_ENABLE;
-			tcb->tcbu.ipcb.ip_schedule |=
-				IPCB_TCPUDP_CHECKSUM_ENABLE;
-
-			if (ip->protocol == IPPROTO_TCP)
-				tcb->tcbu.ipcb.ip_schedule |= IPCB_TCP_PACKET;
-		}
-	}
-
-	if (!skb_shinfo(skb)->nr_frags) {
-		(tcb->tbd_ptr)->tbd_buf_addr =
-			cpu_to_le32(pci_map_single(bdp->pdev, skb->data,
-						   skb->len, PCI_DMA_TODEVICE));
-		(tcb->tbd_ptr)->tbd_buf_cnt = cpu_to_le16(skb->len);
-		tcb->tcb_tbd_num = 1;
-		tcb->tcb_tbd_ptr = tcb->tcb_tbd_dflt_ptr;
-	} else {
-		int i;
-		void *addr;
-		tbd_t *tbd_arr_ptr = &(tcb->tbd_ptr[1]);
-		skb_frag_t *frag = &skb_shinfo(skb)->frags[0];
-
-		(tcb->tbd_ptr)->tbd_buf_addr =
-			cpu_to_le32(pci_map_single(bdp->pdev, skb->data,
-						   skb_headlen(skb),
-						   PCI_DMA_TODEVICE));
-		(tcb->tbd_ptr)->tbd_buf_cnt =
-			cpu_to_le16(skb_headlen(skb));
-
-		for (i = 0; i < skb_shinfo(skb)->nr_frags;
-		     i++, tbd_arr_ptr++, frag++) {
-
-			addr = ((void *) page_address(frag->page) +
-				frag->page_offset);
-
-			tbd_arr_ptr->tbd_buf_addr =
-				cpu_to_le32(pci_map_single(bdp->pdev,
-							   addr, frag->size,
-							   PCI_DMA_TODEVICE));
-			tbd_arr_ptr->tbd_buf_cnt = cpu_to_le16(frag->size);
-		}
-		tcb->tcb_tbd_num = skb_shinfo(skb)->nr_frags + 1;
-		tcb->tcb_tbd_ptr = tcb->tcb_tbd_expand_ptr;
-	}
-
-	/* clear the S-BIT on the previous tcb */
-	prev_tcb = bdp->tcb_pool.data;
-	prev_tcb += PREV_TCB_USED(bdp->tcb_pool);
-	prev_tcb->tcb_hdr.cb_cmd &= __constant_cpu_to_le16((u16) ~CB_S_BIT);
-
-	bdp->tcb_pool.tail = NEXT_TCB_TOUSE(bdp->tcb_pool.tail);
-
-	wmb();
-
-	e100_start_cu(bdp, tcb);
-
-	return tcb;
-}
-
-/* Changed for 82558 enhancement */
-/**
- * e100_start_cu - start the adapter's CU
- * @bdp: atapter's private data struct
- * @tcb: TCB to be transmitted
- *
- * This routine issues a CU Start or CU Resume command to the 82558/9.
- * This routine was added because the prepare_ext_xmit_buff takes advantage
- * of the 82558/9's Dynamic TBD chaining feature and has to start the CU as
- * soon as the first TBD is ready. 
- *
- * e100_start_cu must be called while holding the tx_lock ! 
- */
-u8
-e100_start_cu(struct e100_private *bdp, tcb_t *tcb)
-{
-	unsigned long lock_flag;
-	u8 ret = true;
-
-	spin_lock_irqsave(&(bdp->bd_lock), lock_flag);
-	switch (bdp->next_cu_cmd) {
-	case RESUME_NO_WAIT:
-		/*last cu command was a CU_RESMUE if this is a 558 or newer we don't need to
-		 * wait for command word to clear, we reach here only if we are bachlor
-		 */
-		e100_exec_cmd(bdp, SCB_CUC_RESUME);
-		break;
-
-	case RESUME_WAIT:
-		if ((bdp->flags & IS_ICH) &&
-		    (bdp->cur_line_speed == 10) &&
-		    (bdp->cur_dplx_mode == HALF_DUPLEX)) {
-			e100_wait_exec_simple(bdp, SCB_CUC_NOOP);
-			udelay(1);
-		}
-		if ((e100_wait_exec_simple(bdp, SCB_CUC_RESUME)) &&
-		    (bdp->flags & IS_BACHELOR) && (!(bdp->flags & IS_ICH))) {
-			bdp->next_cu_cmd = RESUME_NO_WAIT;
-		}
-		break;
-
-	case START_WAIT:
-		// The last command was a non_tx CU command
-		if (!e100_wait_cus_idle(bdp))
-			printk(KERN_DEBUG
-			       "e100: %s: cu_start: timeout waiting for cu\n",
-			       bdp->device->name);
-		if (!e100_wait_exec_cmplx(bdp, (u32) (tcb->tcb_phys),
-					  SCB_CUC_START, CB_TRANSMIT)) {
-			printk(KERN_DEBUG
-			       "e100: %s: cu_start: timeout waiting for scb\n",
-			       bdp->device->name);
-			e100_exec_cmplx(bdp, (u32) (tcb->tcb_phys),
-					SCB_CUC_START);
-			ret = false;
-		}
-
-		bdp->next_cu_cmd = RESUME_WAIT;
-
-		break;
-	}
-
-	/* save the last tcb */
-	bdp->last_tcb = tcb;
-
-	spin_unlock_irqrestore(&(bdp->bd_lock), lock_flag);
-	return ret;
-}
-
-/* ====================================================================== */
-/* hw                                                                     */
-/* ====================================================================== */
-
-/**
- * e100_selftest - perform H/W self test
- * @bdp: atapter's private data struct
- * @st_timeout: address to return timeout value, if fails
- * @st_result: address to return selftest result, if fails
- *
- * This routine will issue PORT Self-test command to test the e100.
- * The self-test will fail if the adapter's master-enable bit is not
- * set in the PCI Command Register, or if the adapter is not seated
- * in a PCI master-enabled slot. we also disable interrupts when the
- * command is completed.
- *
- * Returns:
- *      true: if adapter passes self_test
- *      false: otherwise
- */
-unsigned char
-e100_selftest(struct e100_private *bdp, u32 *st_timeout, u32 *st_result)
-{
-	u32 selftest_cmd;
-
-	/* initialize the nic state before running test */
-	e100_sw_reset(bdp, PORT_SOFTWARE_RESET);
-	/* Setup the address of the self_test area */
-	selftest_cmd = bdp->selftest_phys;
-
-	/* Setup SELF TEST Command Code in D3 - D0 */
-	selftest_cmd |= PORT_SELFTEST;
-
-	/* Initialize the self-test signature and results DWORDS */
-	bdp->selftest->st_sign = 0;
-	bdp->selftest->st_result = 0xffffffff;
-
-	/* Do the port command */
-	writel(selftest_cmd, &bdp->scb->scb_port);
-	readw(&(bdp->scb->scb_status));	/* flushes last write, read-safe */
-
-	/* Wait at least 10 milliseconds for the self-test to complete */
-	set_current_state(TASK_UNINTERRUPTIBLE);
-	schedule_timeout(HZ / 100 + 1);
-
-	/* disable interrupts since they are enabled */
-	/* after device reset during selftest        */
-	e100_disable_clear_intr(bdp);
-
-	/* if The First Self Test DWORD Still Zero, We've timed out. If the
-	 * second DWORD is not zero then we have an error. */
-	if ((bdp->selftest->st_sign == 0) || (bdp->selftest->st_result != 0)) {
-
-		if (st_timeout)
-			*st_timeout = !(le32_to_cpu(bdp->selftest->st_sign));
-
-		if (st_result)
-			*st_result = le32_to_cpu(bdp->selftest->st_result);
-
-		return false;
-	}
-
-	return true;
-}
-
-/**
- * e100_setup_iaaddr - issue IA setup sommand
- * @bdp: atapter's private data struct
- * @eaddr: new ethernet address
- *
- * This routine will issue the IA setup command. This command
- * will notify the 82557 (e100) of what its individual (node)
- * address is. This command will be executed in polled mode.
- *
- * Returns:
- *      true: if the IA setup command was successfully issued and completed
- *      false: otherwise
- */
-unsigned char
-e100_setup_iaaddr(struct e100_private *bdp, u8 *eaddr)
-{
-	unsigned int i;
-	cb_header_t *ntcb_hdr;
-	unsigned char res;
-	nxmit_cb_entry_t *cmd;
-
-	if ((cmd = e100_alloc_non_tx_cmd(bdp)) == NULL) {
-		res = false;
-		goto exit;
-	}
-
-	ntcb_hdr = (cb_header_t *) cmd->non_tx_cmd;
-	ntcb_hdr->cb_cmd = __constant_cpu_to_le16(CB_IA_ADDRESS);
-
-	for (i = 0; i < ETH_ALEN; i++) {
-		(cmd->non_tx_cmd)->ntcb.setup.ia_addr[i] = eaddr[i];
-	}
-
-	res = e100_exec_non_cu_cmd(bdp, cmd);
-	if (!res)
-		printk(KERN_WARNING "e100: %s: IA setup failed\n", 
-		       bdp->device->name);
-
-exit:
-	return res;
-}
-
-/**
- * e100_start_ru - start the RU if needed
- * @bdp: atapter's private data struct
- *
- * This routine checks the status of the 82557's receive unit(RU),
- * and starts the RU if it was not already active.  However,
- * before restarting the RU, the driver gives the RU the buffers
- * it freed up during the servicing of the ISR. If there are
- * no free buffers to give to the RU, (i.e. we have reached a
- * no resource condition) the RU will not be started till the
- * next ISR.
- */
-void
-e100_start_ru(struct e100_private *bdp)
-{
-	struct rx_list_elem *rx_struct = NULL;
-	int buffer_found = 0;
-	struct list_head *entry_ptr;
-
-	list_for_each(entry_ptr, &(bdp->active_rx_list)) {
-		rx_struct =
-			list_entry(entry_ptr, struct rx_list_elem, list_elem);
-		pci_dma_sync_single(bdp->pdev, rx_struct->dma_addr,
-				    bdp->rfd_size, PCI_DMA_FROMDEVICE);
-		if (!((SKB_RFD_STATUS(rx_struct->skb, bdp) &
-		       __constant_cpu_to_le16(RFD_STATUS_COMPLETE)))) {
-			buffer_found = 1;
-			break;
-		}
-	}
-
-	/* No available buffers */
-	if (!buffer_found) {
-		return;
-	}
-
-	spin_lock(&bdp->bd_lock);
-
-	if (!e100_wait_exec_cmplx(bdp, rx_struct->dma_addr, SCB_RUC_START, 0)) {
-		printk(KERN_DEBUG
-		       "e100: %s: start_ru: wait_scb failed\n", 
-		       bdp->device->name);
-		e100_exec_cmplx(bdp, rx_struct->dma_addr, SCB_RUC_START);
-	}
-	if (bdp->next_cu_cmd == RESUME_NO_WAIT) {
-		bdp->next_cu_cmd = RESUME_WAIT;
-	}
-	spin_unlock(&bdp->bd_lock);
-}
-
-/**
- * e100_cmd_complete_location
- * @bdp: atapter's private data struct
- *
- * This routine returns a pointer to the location of the command-complete
- * DWord in the dump statistical counters area, according to the statistical
- * counters mode (557 - basic, 558 - extended, or 559 - TCO mode).
- * See e100_config_init() for the setting of the statistical counters mode.
- */
-static u32 *
-e100_cmd_complete_location(struct e100_private *bdp)
-{
-	u32 *cmd_complete;
-	max_counters_t *stats = bdp->stats_counters;
-
-	switch (bdp->stat_mode) {
-	case E100_EXTENDED_STATS:
-		cmd_complete =
-			(u32 *) &(((err_cntr_558_t *) (stats))->cmd_complete);
-		break;
-
-	case E100_TCO_STATS:
-		cmd_complete =
-			(u32 *) &(((err_cntr_559_t *) (stats))->cmd_complete);
-		break;
-
-	case E100_BASIC_STATS:
-	default:		
-		cmd_complete =
-			(u32 *) &(((err_cntr_557_t *) (stats))->cmd_complete);
-		break;
-	}
-
-	return cmd_complete;
-}
-
-/**
- * e100_clr_cntrs - clear statistics counters
- * @bdp: atapter's private data struct
- *
- * This routine will clear the adapter error statistic counters.
- *
- * Returns:
- *      true: if successfully cleared stat counters
- *      false: otherwise
- */
-static unsigned char
-e100_clr_cntrs(struct e100_private *bdp)
-{
-	volatile u32 *pcmd_complete;
-
-	/* clear the dump counter complete word */
-	pcmd_complete = e100_cmd_complete_location(bdp);
-	*pcmd_complete = 0;
-	wmb();
-
-	if (!e100_wait_exec_cmplx(bdp, bdp->stat_cnt_phys, SCB_CUC_DUMP_ADDR, 0))
-		return false;
-
-	/* wait 10 microseconds for the command to complete */
-	udelay(10);
-
-	if (!e100_wait_exec_simple(bdp, SCB_CUC_DUMP_RST_STAT))
-		return false;
-
-	if (bdp->next_cu_cmd == RESUME_NO_WAIT) {
-		bdp->next_cu_cmd = RESUME_WAIT;
-	}
-
-	return true;
-}
-
-static unsigned char
-e100_update_stats(struct e100_private *bdp)
-{
-	u32 *pcmd_complete;
-	basic_cntr_t *pstat = &(bdp->stats_counters->basic_stats);
-
-	// check if last dump command completed
-	pcmd_complete = e100_cmd_complete_location(bdp);
-	if (*pcmd_complete != le32_to_cpu(DUMP_RST_STAT_COMPLETED) &&
-	    *pcmd_complete != le32_to_cpu(DUMP_STAT_COMPLETED)) {
-		*pcmd_complete = 0;
-		return false;
-	}
-
-	/* increment the statistics */
-	bdp->drv_stats.net_stats.rx_packets +=
-		le32_to_cpu(pstat->rcv_gd_frames);
-	bdp->drv_stats.net_stats.tx_packets +=
-		le32_to_cpu(pstat->xmt_gd_frames);
-	bdp->drv_stats.net_stats.rx_dropped += le32_to_cpu(pstat->rcv_rsrc_err);
-	bdp->drv_stats.net_stats.collisions += le32_to_cpu(pstat->xmt_ttl_coll);
-	bdp->drv_stats.net_stats.rx_length_errors +=
-		le32_to_cpu(pstat->rcv_shrt_frames);
-	bdp->drv_stats.net_stats.rx_over_errors +=
-		le32_to_cpu(pstat->rcv_rsrc_err);
-	bdp->drv_stats.net_stats.rx_crc_errors +=
-		le32_to_cpu(pstat->rcv_crc_errs);
-	bdp->drv_stats.net_stats.rx_frame_errors +=
-		le32_to_cpu(pstat->rcv_algn_errs);
-	bdp->drv_stats.net_stats.rx_fifo_errors +=
-		le32_to_cpu(pstat->rcv_oruns);
-	bdp->drv_stats.net_stats.tx_aborted_errors +=
-		le32_to_cpu(pstat->xmt_max_coll);
-	bdp->drv_stats.net_stats.tx_carrier_errors +=
-		le32_to_cpu(pstat->xmt_lost_crs);
-	bdp->drv_stats.net_stats.tx_fifo_errors +=
-		le32_to_cpu(pstat->xmt_uruns);
-
-	bdp->drv_stats.tx_late_col += le32_to_cpu(pstat->xmt_late_coll);
-	bdp->drv_stats.tx_ok_defrd += le32_to_cpu(pstat->xmt_deferred);
-	bdp->drv_stats.tx_one_retry += le32_to_cpu(pstat->xmt_sngl_coll);
-	bdp->drv_stats.tx_mt_one_retry += le32_to_cpu(pstat->xmt_mlt_coll);
-	bdp->drv_stats.rcv_cdt_frames += le32_to_cpu(pstat->rcv_err_coll);
-
-	if (bdp->stat_mode != E100_BASIC_STATS) {
-		ext_cntr_t *pex_stat = &bdp->stats_counters->extended_stats;
-
-		bdp->drv_stats.xmt_fc_pkts +=
-			le32_to_cpu(pex_stat->xmt_fc_frames);
-		bdp->drv_stats.rcv_fc_pkts +=
-			le32_to_cpu(pex_stat->rcv_fc_frames);
-		bdp->drv_stats.rcv_fc_unsupported +=
-			le32_to_cpu(pex_stat->rcv_fc_unsupported);
-	}
-
-	if (bdp->stat_mode == E100_TCO_STATS) {
-		tco_cntr_t *ptco_stat = &bdp->stats_counters->tco_stats;
-
-		bdp->drv_stats.xmt_tco_pkts +=
-			le16_to_cpu(ptco_stat->xmt_tco_frames);
-		bdp->drv_stats.rcv_tco_pkts +=
-			le16_to_cpu(ptco_stat->rcv_tco_frames);
-	}
-
-	*pcmd_complete = 0;
-	return true;
-}
-
-/**
- * e100_dump_stat_cntrs
- * @bdp: atapter's private data struct
- *
- * This routine will dump the board statistical counters without waiting
- * for stat_dump to complete. Any access to this stats should verify the completion
- * of the command
- */
-void
-e100_dump_stats_cntrs(struct e100_private *bdp)
-{
-	unsigned long lock_flag_bd;
-
-	spin_lock_irqsave(&(bdp->bd_lock), lock_flag_bd);
-
-	/* dump h/w stats counters */
-	if (e100_wait_exec_simple(bdp, SCB_CUC_DUMP_RST_STAT)) {
-		if (bdp->next_cu_cmd == RESUME_NO_WAIT) {
-			bdp->next_cu_cmd = RESUME_WAIT;
-		}
-	}
-
-	spin_unlock_irqrestore(&(bdp->bd_lock), lock_flag_bd);
-}
-
-/**
- * e100_exec_non_cu_cmd
- * @bdp: atapter's private data struct
- * @command: the non-cu command to execute
- *
- * This routine will submit a command block to be executed,
- */
-unsigned char
-e100_exec_non_cu_cmd(struct e100_private *bdp, nxmit_cb_entry_t *command)
-{
-	cb_header_t *ntcb_hdr;
-	unsigned long lock_flag;
-	unsigned long expiration_time;
-	unsigned char rc = true;
-	u8 sub_cmd;
-
-	ntcb_hdr = (cb_header_t *) command->non_tx_cmd;	/* get hdr of non tcb cmd */
-	sub_cmd = cpu_to_le16(ntcb_hdr->cb_cmd);
-
-	/* Set the Command Block to be the last command block */
-	ntcb_hdr->cb_cmd |= __constant_cpu_to_le16(CB_EL_BIT);
-	ntcb_hdr->cb_status = 0;
-	ntcb_hdr->cb_lnk_ptr = 0;
-
-	wmb();
-	if (in_interrupt())
-		return e100_delayed_exec_non_cu_cmd(bdp, command);
-
-	if (netif_running(bdp->device) && netif_carrier_ok(bdp->device))
-		return e100_delayed_exec_non_cu_cmd(bdp, command);
-
-	spin_lock_bh(&(bdp->bd_non_tx_lock));
-
-	if (bdp->non_tx_command_state != E100_NON_TX_IDLE) {
-		goto delayed_exec;
-	}
-
-	if (bdp->last_tcb) {
-		rmb();
-		if ((bdp->last_tcb->tcb_hdr.cb_status &
-		     __constant_cpu_to_le16(CB_STATUS_COMPLETE)) == 0)
-			goto delayed_exec;
-	}
-
-	if ((readw(&bdp->scb->scb_status) & SCB_CUS_MASK) == SCB_CUS_ACTIVE) {
-		goto delayed_exec;
-	}
-
-	spin_lock_irqsave(&bdp->bd_lock, lock_flag);
-
-	if (!e100_wait_exec_cmplx(bdp, command->dma_addr, SCB_CUC_START, sub_cmd)) {
-		spin_unlock_irqrestore(&(bdp->bd_lock), lock_flag);
-		rc = false;
-		goto exit;
-	}
-
-	bdp->next_cu_cmd = START_WAIT;
-	spin_unlock_irqrestore(&(bdp->bd_lock), lock_flag);
-
-	/* now wait for completion of non-cu CB up to 20 msec */
-	expiration_time = jiffies + HZ / 50 + 1;
-	rmb();
-	while (!(ntcb_hdr->cb_status &
-		     __constant_cpu_to_le16(CB_STATUS_COMPLETE))) {
-
-		if (time_before(jiffies, expiration_time)) {
-			spin_unlock_bh(&(bdp->bd_non_tx_lock));
-			yield();
-			spin_lock_bh(&(bdp->bd_non_tx_lock));
-		} else {
-#ifdef E100_CU_DEBUG			
-			printk(KERN_ERR "e100: %s: non-TX command (%x) "
-				"timeout\n", bdp->device->name, sub_cmd);
-#endif			
-			rc = false;
-			goto exit;
-		}
-		rmb();
-	}
-
-exit:
-	e100_free_non_tx_cmd(bdp, command);
-
-	if (netif_running(bdp->device))
-		netif_wake_queue(bdp->device);
-
-	spin_unlock_bh(&(bdp->bd_non_tx_lock));
-	return rc;
-
-delayed_exec:
-	spin_unlock_bh(&(bdp->bd_non_tx_lock));
-	return e100_delayed_exec_non_cu_cmd(bdp, command);
-}
-
-/**
- * e100_sw_reset
- * @bdp: atapter's private data struct
- * @reset_cmd: s/w reset or selective reset
- *
- * This routine will issue a software reset to the adapter. It 
- * will also disable interrupts, as the are enabled after reset.
- */
-void
-e100_sw_reset(struct e100_private *bdp, u32 reset_cmd)
-{
-	/* Do  a selective reset first to avoid a potential PCI hang */
-	writel(PORT_SELECTIVE_RESET, &bdp->scb->scb_port);
-	readw(&(bdp->scb->scb_status));	/* flushes last write, read-safe */
-
-	/* wait for the reset to take effect */
-	udelay(20);
-	if (reset_cmd == PORT_SOFTWARE_RESET) {
-		writel(PORT_SOFTWARE_RESET, &bdp->scb->scb_port);
-
-		/* wait 20 micro seconds for the reset to take effect */
-		udelay(20);
-	}
-
-	/* Mask off our interrupt line -- it is unmasked after reset */
-	e100_disable_clear_intr(bdp);
-#ifdef E100_CU_DEBUG	
-	bdp->last_cmd = 0;
-	bdp->last_sub_cmd = 0;
-#endif	
-}
-
-/**
- * e100_load_microcode - Download microsocde to controller.
- * @bdp: atapter's private data struct
- *
- * This routine downloads microcode on to the controller. This
- * microcode is available for the 82558/9, 82550. Currently the
- * microcode handles interrupt bundling and TCO workaround.
- *
- * Returns:
- *      true: if successfull
- *      false: otherwise
- */
-static unsigned char
-e100_load_microcode(struct e100_private *bdp)
-{
-	static struct {
-		u8 rev_id;
-		u32 ucode[UCODE_MAX_DWORDS + 1];
-		int timer_dword;
-		int bundle_dword;
-		int min_size_dword;
-	} ucode_opts[] = {
-		{ D101A4_REV_ID,
-		  D101_A_RCVBUNDLE_UCODE,
-		  D101_CPUSAVER_TIMER_DWORD,
-		  D101_CPUSAVER_BUNDLE_DWORD,
-		  D101_CPUSAVER_MIN_SIZE_DWORD },
-		{ D101B0_REV_ID,
-		  D101_B0_RCVBUNDLE_UCODE,
-		  D101_CPUSAVER_TIMER_DWORD,
-		  D101_CPUSAVER_BUNDLE_DWORD,
-		  D101_CPUSAVER_MIN_SIZE_DWORD },
-		{ D101MA_REV_ID,
-		  D101M_B_RCVBUNDLE_UCODE,
-		  D101M_CPUSAVER_TIMER_DWORD,
-		  D101M_CPUSAVER_BUNDLE_DWORD,
-		  D101M_CPUSAVER_MIN_SIZE_DWORD },
-		{ D101S_REV_ID,
-		  D101S_RCVBUNDLE_UCODE,
-		  D101S_CPUSAVER_TIMER_DWORD,
-		  D101S_CPUSAVER_BUNDLE_DWORD,
-		  D101S_CPUSAVER_MIN_SIZE_DWORD },
-		{ D102_REV_ID,
-		  D102_B_RCVBUNDLE_UCODE,
-		  D102_B_CPUSAVER_TIMER_DWORD,
-		  D102_B_CPUSAVER_BUNDLE_DWORD,
-		  D102_B_CPUSAVER_MIN_SIZE_DWORD },
-		{ D102C_REV_ID,
-		  D102_C_RCVBUNDLE_UCODE,
-		  D102_C_CPUSAVER_TIMER_DWORD,
-		  D102_C_CPUSAVER_BUNDLE_DWORD,
-		  D102_C_CPUSAVER_MIN_SIZE_DWORD },
-		{ D102E_REV_ID,
-		  D102_E_RCVBUNDLE_UCODE,
-		  D102_E_CPUSAVER_TIMER_DWORD,
-		  D102_E_CPUSAVER_BUNDLE_DWORD,
-		  D102_E_CPUSAVER_MIN_SIZE_DWORD },
-		{ 0, {0}, 0, 0, 0}
-	}, *opts;
-
-	opts = ucode_opts;
-
-	/* User turned ucode loading off */
-	if (!(bdp->params.b_params & PRM_UCODE))
-		return false;
-
-	/* These controllers do not need ucode */
-	if (bdp->flags & IS_ICH)
-		return false;
-
-	/* Search for ucode match against h/w rev_id */
-	while (opts->rev_id) {
-		if (bdp->rev_id == opts->rev_id) {
-			int i;
-			u32 *ucode_dword;
-			load_ucode_cb_t *ucode_cmd_ptr;
-			nxmit_cb_entry_t *cmd = e100_alloc_non_tx_cmd(bdp);
-
-			if (cmd != NULL) {
-				ucode_cmd_ptr =
-					(load_ucode_cb_t *) cmd->non_tx_cmd;
-				ucode_dword = ucode_cmd_ptr->ucode_dword;
-			} else {
-				return false;
-			}
-
-			memcpy(ucode_dword, opts->ucode, sizeof (opts->ucode));
-
-			/* Insert user-tunable settings */
-			ucode_dword[opts->timer_dword] &= 0xFFFF0000;
-			ucode_dword[opts->timer_dword] |=
-				(u16) bdp->params.IntDelay;
-			ucode_dword[opts->bundle_dword] &= 0xFFFF0000;
-			ucode_dword[opts->bundle_dword] |=
-				(u16) bdp->params.BundleMax;
-			ucode_dword[opts->min_size_dword] &= 0xFFFF0000;
-			ucode_dword[opts->min_size_dword] |=
-				(bdp->params.b_params & PRM_BUNDLE_SMALL) ?
-				0xFFFF : 0xFF80;
-
-			for (i = 0; i < UCODE_MAX_DWORDS; i++)
-				cpu_to_le32s(&(ucode_dword[i]));
-
-			ucode_cmd_ptr->load_ucode_cbhdr.cb_cmd =
-				__constant_cpu_to_le16(CB_LOAD_MICROCODE);
-
-			return e100_exec_non_cu_cmd(bdp, cmd);
-		}
-		opts++;
-	}
-
-	return false;
-}
-
-/***************************************************************************/
-/***************************************************************************/
-/*       EEPROM  Functions                                                 */
-/***************************************************************************/
-
-/* Read PWA (printed wired assembly) number */
-void
-e100_rd_pwa_no(struct e100_private *bdp)
-{
-	bdp->pwa_no = e100_eeprom_read(bdp, EEPROM_PWA_NO);
-	bdp->pwa_no <<= 16;
-	bdp->pwa_no |= e100_eeprom_read(bdp, EEPROM_PWA_NO + 1);
-}
-
-/* Read the permanent ethernet address from the eprom. */
-void
-e100_rd_eaddr(struct e100_private *bdp)
-{
-	int i;
-	u16 eeprom_word;
-
-	for (i = 0; i < 6; i += 2) {
-		eeprom_word =
-			e100_eeprom_read(bdp,
-					 EEPROM_NODE_ADDRESS_BYTE_0 + (i / 2));
-
-		bdp->device->dev_addr[i] =
-			bdp->perm_node_address[i] = (u8) eeprom_word;
-		bdp->device->dev_addr[i + 1] =
-			bdp->perm_node_address[i + 1] = (u8) (eeprom_word >> 8);
-	}
-}
-
-/* Check the D102 RFD flags to see if the checksum passed */
-static unsigned char
-e100_D102_check_checksum(rfd_t *rfd)
-{
-	if (((le16_to_cpu(rfd->rfd_header.cb_status)) & RFD_PARSE_BIT)
-	    && (((rfd->rcvparserstatus & CHECKSUM_PROTOCOL_MASK) ==
-		 RFD_TCP_PACKET)
-		|| ((rfd->rcvparserstatus & CHECKSUM_PROTOCOL_MASK) ==
-		    RFD_UDP_PACKET))
-	    && (rfd->checksumstatus & TCPUDP_CHECKSUM_BIT_VALID)
-	    && (rfd->checksumstatus & TCPUDP_CHECKSUM_VALID)) {
-		return CHECKSUM_UNNECESSARY;
-	}
-	return CHECKSUM_NONE;
-}
-
-/**
- * e100_D101M_checksum
- * @bdp: atapter's private data struct
- * @skb: skb received
- *
- * Sets the skb->csum value from D101 csum found at the end of the Rx frame. The
- * D101M sums all words in frame excluding the ethernet II header (14 bytes) so
- * in case the packet is ethernet II and the protocol is IP, all is need is to
- * assign this value to skb->csum.
- */
-static unsigned char
-e100_D101M_checksum(struct e100_private *bdp, struct sk_buff *skb)
-{
-	unsigned short proto = (skb->protocol);
-
-	if (proto == __constant_htons(ETH_P_IP)) {
-
-		skb->csum = get_unaligned((u16 *) (skb->tail));
-		return CHECKSUM_HW;
-	}
-	return CHECKSUM_NONE;
-}
-
-/***************************************************************************/
-/***************************************************************************/
-/***************************************************************************/
-/***************************************************************************/
-/*       Auxilary Functions                                                */
-/***************************************************************************/
-
-/* Print the board's configuration */
-void
-e100_print_brd_conf(struct e100_private *bdp)
-{
-	/* Print the string if checksum Offloading was enabled */
-	if (bdp->flags & DF_CSUM_OFFLOAD)
-		printk(KERN_NOTICE "  Hardware receive checksums enabled\n");
-	else {
-		if (bdp->rev_id >= D101MA_REV_ID) 
-			printk(KERN_NOTICE "  Hardware receive checksums disabled\n");
-	}
-
-	if ((bdp->flags & DF_UCODE_LOADED))
-		printk(KERN_NOTICE "  cpu cycle saver enabled\n");
-}
-
-/**
- * e100_pci_setup - setup the adapter's PCI information
- * @pcid: adapter's pci_dev struct
- * @bdp: atapter's private data struct
- *
- * This routine sets up all PCI information for the adapter. It enables the bus
- * master bit (some BIOS don't do this), requests memory ans I/O regions, and
- * calls ioremap() on the adapter's memory region.
- *
- * Returns:
- *      true: if successfull
- *      false: otherwise
- */
-static unsigned char
-e100_pci_setup(struct pci_dev *pcid, struct e100_private *bdp)
-{
-	struct net_device *dev = bdp->device;
-	int rc = 0;
-
-	if ((rc = pci_enable_device(pcid)) != 0) {
-		goto err;
-	}
-
-	/* dev and ven ID have already been checked so it is our device */
-	pci_read_config_byte(pcid, PCI_REVISION_ID, (u8 *) &(bdp->rev_id));
-
-	/* address #0 is a memory region */
-	dev->mem_start = pci_resource_start(pcid, 0);
-	dev->mem_end = dev->mem_start + sizeof (scb_t);
-
-	/* address #1 is a IO region */
-	dev->base_addr = pci_resource_start(pcid, 1);
-
-	if ((rc = pci_request_regions(pcid, e100_short_driver_name)) != 0) {
-		goto err_disable;
-	}
-
-	pci_enable_wake(pcid, 0, 0);
-
-	/* if Bus Mastering is off, turn it on! */
-	pci_set_master(pcid);
-
-	/* address #0 is a memory mapping */
-	bdp->scb = (scb_t *) ioremap_nocache(dev->mem_start, sizeof (scb_t));
-
-	if (!bdp->scb) {
-		printk(KERN_ERR "e100: %s: Failed to map PCI address 0x%lX\n",
-		       dev->name, pci_resource_start(pcid, 0));
-		rc = -ENOMEM;
-		goto err_region;
-	}
-
-	return 0;
-
-err_region:
-	pci_release_regions(pcid);
-err_disable:
-	pci_disable_device(pcid);
-err:
-	return rc;
-}
-
-void
-e100_isolate_driver(struct e100_private *bdp)
-{
-
-	/* Check if interface is up                              */
-	/* NOTE: Can't use netif_running(bdp->device) because    */
-	/* dev_close clears __LINK_STATE_START before calling    */
-	/* e100_close (aka dev->stop)                            */
-	if (bdp->device->flags & IFF_UP) {
-		e100_disable_clear_intr(bdp);
-		del_timer_sync(&bdp->watchdog_timer);
-		netif_carrier_off(bdp->device);
-		netif_stop_queue(bdp->device); 
-		bdp->last_tcb = NULL;
-	} 
-	e100_sw_reset(bdp, PORT_SELECTIVE_RESET);
-}
-
-static void
-e100_tcb_add_C_bit(struct e100_private *bdp)
-{
-	tcb_t *tcb = (tcb_t *) bdp->tcb_pool.data;
-	int i;
-
-	for (i = 0; i < bdp->params.TxDescriptors; i++, tcb++) {
-		tcb->tcb_hdr.cb_status |= cpu_to_le16(CB_STATUS_COMPLETE);
-	}
-}
-
-/* 
- * Procedure:   e100_configure_device
- *
- * Description: This routine will configure device
- *
- * Arguments:
- *      bdp - Ptr to this card's e100_bdconfig structure
- *
- * Returns:
- *        true upon success
- *        false upon failure
- */
-unsigned char
-e100_configure_device(struct e100_private *bdp)
-{
-	/*load CU & RU base */
-	if (!e100_wait_exec_cmplx(bdp, 0, SCB_CUC_LOAD_BASE, 0))
-		return false;
-
-	if (e100_load_microcode(bdp))
-		bdp->flags |= DF_UCODE_LOADED;
-
-	if (!e100_wait_exec_cmplx(bdp, 0, SCB_RUC_LOAD_BASE, 0))
-		return false;
-
-	/* Issue the load dump counters address command */
-	if (!e100_wait_exec_cmplx(bdp, bdp->stat_cnt_phys, SCB_CUC_DUMP_ADDR, 0))
-		return false;
-
-	if (!e100_setup_iaaddr(bdp, bdp->device->dev_addr)) {
-		printk(KERN_ERR "e100: e100_configure_device: "
-			"setup iaaddr failed\n");
-		return false;
-	}
-
-	e100_set_multi_exec(bdp->device);
-
-	/* Change for 82558 enhancement                                */
-	/* If 82558/9 and if the user has enabled flow control, set up */
-	/* flow Control Reg. in the CSR                                */
-	if ((bdp->flags & IS_BACHELOR)
-	    && (bdp->params.b_params & PRM_FC)) {
-		writeb(DFLT_FC_THLD,
-			&bdp->scb->scb_ext.d101_scb.scb_fc_thld);
-		writeb(DFLT_FC_CMD,
-			&bdp->scb->scb_ext.d101_scb.scb_fc_xon_xoff);
-	}
-
-	e100_force_config(bdp);
-
-	return true;
-}
-
-void
-e100_deisolate_driver(struct e100_private *bdp, u8 full_reset)
-{
-	u32 cmd = full_reset ? PORT_SOFTWARE_RESET : PORT_SELECTIVE_RESET;
-	e100_sw_reset(bdp, cmd);
-	if (cmd == PORT_SOFTWARE_RESET) {
-		if (!e100_configure_device(bdp))
-			printk(KERN_ERR "e100: e100_deisolate_driver:" 
-		       		" device configuration failed\n");
-	} 
-
-	if (netif_running(bdp->device)) {
-
-		bdp->next_cu_cmd = START_WAIT;
-		bdp->last_tcb = NULL;
-
-		e100_start_ru(bdp);
-
-		/* relaunch watchdog timer in 2 sec */
-		mod_timer(&(bdp->watchdog_timer), jiffies + (2 * HZ));
-
-		// we must clear tcbs since we may have lost Tx intrrupt
-		// or have unsent frames on the tcb chain
-		e100_tcb_add_C_bit(bdp);
-		e100_tx_srv(bdp);
-		netif_wake_queue(bdp->device);
-		e100_set_intr_mask(bdp);
-	}
-}
-
-static int
-e100_do_ethtool_ioctl(struct net_device *dev, struct ifreq *ifr)
-{
-	struct ethtool_cmd ecmd;
-	int rc = -EOPNOTSUPP;
-
-	if (copy_from_user(&ecmd, ifr->ifr_data, sizeof (ecmd.cmd)))
-		return -EFAULT;
-
-	switch (ecmd.cmd) {
-	case ETHTOOL_GSET:
-		rc = e100_ethtool_get_settings(dev, ifr);
-		break;
-	case ETHTOOL_SSET:
-		rc = e100_ethtool_set_settings(dev, ifr);
-		break;
-	case ETHTOOL_GDRVINFO:
-		rc = e100_ethtool_get_drvinfo(dev, ifr);
-		break;
-	case ETHTOOL_GREGS:
-		rc = e100_ethtool_gregs(dev, ifr);
-		break;
-	case ETHTOOL_NWAY_RST:
-		rc = e100_ethtool_nway_rst(dev, ifr);
-		break;
-	case ETHTOOL_GLINK:
-		rc = e100_ethtool_glink(dev, ifr);
-		break;
-	case ETHTOOL_GEEPROM:
-	case ETHTOOL_SEEPROM:
-		rc = e100_ethtool_eeprom(dev, ifr);
-		break;
-	case ETHTOOL_GSTATS: {
-		struct {
-			struct ethtool_stats cmd;
-			uint64_t data[E100_STATS_LEN];
-		} stats = { {ETHTOOL_GSTATS, E100_STATS_LEN} };
-		struct e100_private *bdp = dev->priv;
-		void *addr = ifr->ifr_data;
-		int i;
-
-		for(i = 0; i < E100_STATS_LEN; i++)
-			stats.data[i] =
-				((unsigned long *)&bdp->drv_stats.net_stats)[i];
-		if(copy_to_user(addr, &stats, sizeof(stats)))
-			return -EFAULT;
-		return 0;
-	}
-	case ETHTOOL_GWOL:
-	case ETHTOOL_SWOL:
-		rc = e100_ethtool_wol(dev, ifr);
-		break;
-	case ETHTOOL_TEST:
-		rc = e100_ethtool_test(dev, ifr);
-		break;
-	case ETHTOOL_GSTRINGS:
-		rc = e100_ethtool_gstrings(dev,ifr);
-		break;
-	case ETHTOOL_PHYS_ID:
-		rc = e100_ethtool_led_blink(dev,ifr);
-		break;
-#ifdef	ETHTOOL_GRINGPARAM
-	case ETHTOOL_GRINGPARAM: {
-		struct ethtool_ringparam ering;
-		struct e100_private *bdp = dev->priv;
-		memset((void *) &ering, 0, sizeof(ering));
-		ering.rx_max_pending = E100_MAX_RFD;
-		ering.tx_max_pending = E100_MAX_TCB;
-		ering.rx_pending = bdp->params.RxDescriptors;
-		ering.tx_pending = bdp->params.TxDescriptors;
-		rc = copy_to_user(ifr->ifr_data, &ering, sizeof(ering))
-			? -EFAULT : 0;
-		return rc;
-	}
-#endif
-#ifdef	ETHTOOL_SRINGPARAM
-	case ETHTOOL_SRINGPARAM: {
-		struct ethtool_ringparam ering;
-		struct e100_private *bdp = dev->priv;
-		if (copy_from_user(&ering, ifr->ifr_data, sizeof(ering)))
-			return -EFAULT;
-		if (ering.rx_pending > E100_MAX_RFD 
-		    || ering.rx_pending < E100_MIN_RFD)
-			return -EINVAL;
-		if (ering.tx_pending > E100_MAX_TCB 
-		    || ering.tx_pending < E100_MIN_TCB)
-			return -EINVAL;
-		if (netif_running(dev)) {
-			spin_lock_bh(&dev->xmit_lock);
-			e100_close(dev);
-			spin_unlock_bh(&dev->xmit_lock);
-			/* Use new values to open interface */
-			bdp->params.RxDescriptors = ering.rx_pending;
-			bdp->params.TxDescriptors = ering.tx_pending;
-			e100_hw_init(bdp);
-			e100_open(dev);
-		}
-		else {
-			bdp->params.RxDescriptors = ering.rx_pending;
-			bdp->params.TxDescriptors = ering.tx_pending;
-		}
-		return 0;
-	}
-#endif
-#ifdef	ETHTOOL_GPAUSEPARAM
-	case ETHTOOL_GPAUSEPARAM: {
-		struct ethtool_pauseparam epause;
-		struct e100_private *bdp = dev->priv;
-		memset((void *) &epause, 0, sizeof(epause));
-		if ((bdp->flags & IS_BACHELOR)
-		    && (bdp->params.b_params & PRM_FC)) {
-			epause.autoneg = 1;
-			if (bdp->flags && DF_LINK_FC_CAP) {
-				epause.rx_pause = 1;
-				epause.tx_pause = 1;
-			}
-			if (bdp->flags && DF_LINK_FC_TX_ONLY)
-				epause.tx_pause = 1;
-		}
-		rc = copy_to_user(ifr->ifr_data, &epause, sizeof(epause))
-			? -EFAULT : 0;
-		return rc;
-	}
-#endif
-#ifdef	ETHTOOL_SPAUSEPARAM
-	case ETHTOOL_SPAUSEPARAM: {
-		struct ethtool_pauseparam epause;
-		struct e100_private *bdp = dev->priv;
-		if (!(bdp->flags & IS_BACHELOR))
-			return -EINVAL;
-		if (copy_from_user(&epause, ifr->ifr_data, sizeof(epause)))
-			return -EFAULT;
-		if (epause.autoneg == 1)
-			bdp->params.b_params |= PRM_FC;
-		else
-			bdp->params.b_params &= ~PRM_FC;
-		if (netif_running(dev)) {
-			spin_lock_bh(&dev->xmit_lock);
-			e100_close(dev);
-			spin_unlock_bh(&dev->xmit_lock);
-			e100_hw_init(bdp);
-			e100_open(dev);
-		}
-		return 0;
-	}
-#endif
-#ifdef	ETHTOOL_GRXCSUM
-	case ETHTOOL_GRXCSUM:
-	case ETHTOOL_GTXCSUM:
-	case ETHTOOL_GSG:
-	{	struct ethtool_value eval;
-		struct e100_private *bdp = dev->priv;
-		memset((void *) &eval, 0, sizeof(eval));
-		if ((ecmd.cmd == ETHTOOL_GRXCSUM) 
-		    && (bdp->params.b_params & PRM_XSUMRX))
-			eval.data = 1;
-		else
-			eval.data = 0;
-		rc = copy_to_user(ifr->ifr_data, &eval, sizeof(eval))
-			? -EFAULT : 0;
-		return rc;
-	}
-#endif
-#ifdef	ETHTOOL_SRXCSUM
-	case ETHTOOL_SRXCSUM:
-	case ETHTOOL_STXCSUM:
-	case ETHTOOL_SSG:
-	{	struct ethtool_value eval;
-		struct e100_private *bdp = dev->priv;
-		if (copy_from_user(&eval, ifr->ifr_data, sizeof(eval)))
-			return -EFAULT;
-		if (ecmd.cmd == ETHTOOL_SRXCSUM) {
-			if (eval.data == 1) { 
-				if (bdp->rev_id >= D101MA_REV_ID)
-					bdp->params.b_params |= PRM_XSUMRX;
-				else
-					return -EINVAL;
-			} else {
-				if (bdp->rev_id >= D101MA_REV_ID)
-					bdp->params.b_params &= ~PRM_XSUMRX;
-				else
-					return 0;
-			}
-		} else {
-			if (eval.data == 1)
-				return -EINVAL;
-			else
-				return 0;
-		}
-		if (netif_running(dev)) {
-			spin_lock_bh(&dev->xmit_lock);
-			e100_close(dev);
-			spin_unlock_bh(&dev->xmit_lock);
-			e100_hw_init(bdp);
-			e100_open(dev);
-		}
-		return 0;
-	}
-#endif
-	default:
-		break;
-	}			//switch
-	return rc;
-}
-
-static int
-e100_ethtool_get_settings(struct net_device *dev, struct ifreq *ifr)
-{
-	struct e100_private *bdp;
-	struct ethtool_cmd ecmd;
-	u16 advert = 0;
-
-	memset((void *) &ecmd, 0, sizeof (ecmd));
-
-	bdp = dev->priv;
-
-	ecmd.supported = bdp->speed_duplex_caps;
-
-	ecmd.port =
-		(bdp->speed_duplex_caps & SUPPORTED_TP) ? PORT_TP : PORT_FIBRE;
-	ecmd.transceiver = XCVR_INTERNAL;
-	ecmd.phy_address = bdp->phy_addr;
-
-	if (netif_carrier_ok(bdp->device)) {
-		ecmd.speed = bdp->cur_line_speed;
-		ecmd.duplex =
-			(bdp->cur_dplx_mode == HALF_DUPLEX) ? DUPLEX_HALF : DUPLEX_FULL;
-	}
-	else {
-		ecmd.speed = -1;
-		ecmd.duplex = -1;
-	}
-
-	ecmd.advertising = ADVERTISED_TP;
-
-	if (bdp->params.e100_speed_duplex == E100_AUTONEG) {
-		ecmd.autoneg = AUTONEG_ENABLE;
-		ecmd.advertising |= ADVERTISED_Autoneg;
-	} else {
-		ecmd.autoneg = AUTONEG_DISABLE;
-	}
-
-	if (bdp->speed_duplex_caps & SUPPORTED_MII) {
-		e100_mdi_read(bdp, MII_ADVERTISE, bdp->phy_addr, &advert);
-
-		if (advert & ADVERTISE_10HALF)
-			ecmd.advertising |= ADVERTISED_10baseT_Half;
-		if (advert & ADVERTISE_10FULL)
-			ecmd.advertising |= ADVERTISED_10baseT_Full;
-		if (advert & ADVERTISE_100HALF)
-			ecmd.advertising |= ADVERTISED_100baseT_Half;
-		if (advert & ADVERTISE_100FULL)
-			ecmd.advertising |= ADVERTISED_100baseT_Full;
-	} else {
-		ecmd.autoneg = AUTONEG_DISABLE;
-		ecmd.advertising &= ~ADVERTISED_Autoneg;
-	}
-
-	if (copy_to_user(ifr->ifr_data, &ecmd, sizeof (ecmd)))
-		return -EFAULT;
-
-	return 0;
-}
-
-static int
-e100_ethtool_set_settings(struct net_device *dev, struct ifreq *ifr)
-{
-	struct e100_private *bdp;
-	int e100_new_speed_duplex;
-	int ethtool_new_speed_duplex;
-	struct ethtool_cmd ecmd;
-
-	bdp = dev->priv;
-	if (copy_from_user(&ecmd, ifr->ifr_data, sizeof (ecmd))) {
-		return -EFAULT;
-	}
-
-	if ((ecmd.autoneg == AUTONEG_ENABLE)
-	    && (bdp->speed_duplex_caps & SUPPORTED_Autoneg)) {
-		bdp->params.e100_speed_duplex = E100_AUTONEG;
-		if (netif_running(dev)) {
-			spin_lock_bh(&dev->xmit_lock);
-			e100_close(dev);
-			spin_unlock_bh(&dev->xmit_lock);
-			e100_hw_init(bdp);
-			e100_open(dev);
-		}
-	} else {
-		if (ecmd.speed == SPEED_10) {
-			if (ecmd.duplex == DUPLEX_HALF) {
-				e100_new_speed_duplex =
-					E100_SPEED_10_HALF;
-				ethtool_new_speed_duplex =
-					SUPPORTED_10baseT_Half;
-			} else { 
-				e100_new_speed_duplex =
-					E100_SPEED_10_FULL;
-				ethtool_new_speed_duplex =
-					SUPPORTED_10baseT_Full;
-			} 
-		} else { 
-			if (ecmd.duplex == DUPLEX_HALF) {
-				e100_new_speed_duplex =
-					E100_SPEED_100_HALF;
-				ethtool_new_speed_duplex =
-					SUPPORTED_100baseT_Half;
-			} else { 
-				e100_new_speed_duplex =
-					E100_SPEED_100_FULL;
-				ethtool_new_speed_duplex =
-					SUPPORTED_100baseT_Full;
-			} 
-		}
-
-		if (bdp->speed_duplex_caps & ethtool_new_speed_duplex) {
-			bdp->params.e100_speed_duplex =
-				e100_new_speed_duplex;
-			if (netif_running(dev)) {
-				spin_lock_bh(&dev->xmit_lock);
-				e100_close(dev);
-				spin_unlock_bh(&dev->xmit_lock);
-				e100_hw_init(bdp);
-				e100_open(dev);
-			}
-		} else {
-			return -EOPNOTSUPP;
-		} 
-	}
-
-	return 0;
-}
-
-static int
-e100_ethtool_glink(struct net_device *dev, struct ifreq *ifr)
-{
-	struct e100_private *bdp;
-	struct ethtool_value info;
-
-	memset((void *) &info, 0, sizeof (info));
-
-	bdp = dev->priv;
-	info.cmd = ETHTOOL_GLINK;
-
-	/* Consider both PHY link and netif_running */
-	info.data = e100_update_link_state(bdp);
-
-	if (copy_to_user(ifr->ifr_data, &info, sizeof (info)))
-		return -EFAULT;
-
-	return 0;
-}
-
-static int
-e100_ethtool_test(struct net_device *dev, struct ifreq *ifr)
-{
-	struct ethtool_test *info;
-	int rc = -EFAULT;
-
-	info = kmalloc(sizeof(*info) + max_test_res * sizeof(u64),
-		       GFP_ATOMIC);
-
-	if (!info)
-		return -ENOMEM;
-
-	memset((void *) info, 0, sizeof(*info) +
-				 max_test_res * sizeof(u64));
-
-	if (copy_from_user(info, ifr->ifr_data, sizeof(*info)))
-		goto exit;
-
-	info->flags = e100_run_diag(dev, info->data, info->flags);
-
-	if (!copy_to_user(ifr->ifr_data, info,
-			 sizeof(*info) + max_test_res * sizeof(u64)))
-		rc = 0;
-exit:
-	kfree(info);
-	return rc;
-}
-
-static int
-e100_ethtool_gregs(struct net_device *dev, struct ifreq *ifr)
-{
-	struct e100_private *bdp;
-	u32 regs_buff[E100_REGS_LEN];
-	struct ethtool_regs regs = {ETHTOOL_GREGS};
-	void *addr = ifr->ifr_data;
-	u16 mdi_reg;
-
-	bdp = dev->priv;
-
-	if(copy_from_user(&regs, addr, sizeof(regs)))
-		return -EFAULT;
-
-	regs.version = (1 << 24) | bdp->rev_id;
-	regs_buff[0] = readb(&(bdp->scb->scb_cmd_hi)) << 24 |
-		readb(&(bdp->scb->scb_cmd_low)) << 16 |
-		readw(&(bdp->scb->scb_status));
-	e100_mdi_read(bdp, MII_NCONFIG, bdp->phy_addr, &mdi_reg);
-	regs_buff[1] = mdi_reg;
-
-	if(copy_to_user(addr, &regs, sizeof(regs)))
-		return -EFAULT;
-
-	addr += offsetof(struct ethtool_regs, data);
-	if(copy_to_user(addr, regs_buff, regs.len))
-		return -EFAULT;
-
-	return 0;
-}
-
-static int
-e100_ethtool_nway_rst(struct net_device *dev, struct ifreq *ifr)
-{
-	struct e100_private *bdp;
-
-	bdp = dev->priv;
-
-	if ((bdp->speed_duplex_caps & SUPPORTED_Autoneg) &&
-	    (bdp->params.e100_speed_duplex == E100_AUTONEG)) {
-		if (netif_running(dev)) {
-			spin_lock_bh(&dev->xmit_lock);
-			e100_close(dev);
-			spin_unlock_bh(&dev->xmit_lock);
-			e100_hw_init(bdp);
-			e100_open(dev);
-		}
-	} else {
-		return -EFAULT;
-	}
-	return 0;
-}
-
-static int
-e100_ethtool_get_drvinfo(struct net_device *dev, struct ifreq *ifr)
-{
-	struct e100_private *bdp;
-	struct ethtool_drvinfo info;
-
-	memset((void *) &info, 0, sizeof (info));
-
-	bdp = dev->priv;
-
-	strncpy(info.driver, e100_short_driver_name, sizeof (info.driver) - 1);
-	strncpy(info.version, e100_driver_version, sizeof (info.version) - 1);
-	strncpy(info.fw_version, "N/A",
-		sizeof (info.fw_version) - 1);
-	strncpy(info.bus_info, pci_name(bdp->pdev),
-		sizeof (info.bus_info) - 1);
-	info.n_stats = E100_STATS_LEN;
-	info.regdump_len  = E100_REGS_LEN * sizeof(u32);
-	info.eedump_len = (bdp->eeprom_size << 1);	
-	info.testinfo_len = max_test_res;
-	if (copy_to_user(ifr->ifr_data, &info, sizeof (info)))
-		return -EFAULT;
-
-	return 0;
-}
-
-static int
-e100_ethtool_eeprom(struct net_device *dev, struct ifreq *ifr)
-{
-	struct e100_private *bdp;
-	struct ethtool_eeprom ecmd;
-	u16 eeprom_data[256];
-	u16 *usr_eeprom_ptr;
-	u16 first_word, last_word;
-	int i, max_len;
-	void *ptr;
-	u8 *eeprom_data_bytes = (u8 *)eeprom_data;
-
-	bdp = dev->priv;
-
-	if (copy_from_user(&ecmd, ifr->ifr_data, sizeof (ecmd)))
-		return -EFAULT;
-
-	usr_eeprom_ptr =
-		(u16 *) (ifr->ifr_data + offsetof(struct ethtool_eeprom, data));
-
-        max_len = bdp->eeprom_size * 2;
-        
-        if (ecmd.offset > ecmd.offset + ecmd.len)
-        	return -EINVAL;
-        	
-	if ((ecmd.offset + ecmd.len) > max_len)
-		ecmd.len = (max_len - ecmd.offset);
-
-	first_word = ecmd.offset >> 1;
-	last_word = (ecmd.offset + ecmd.len - 1) >> 1;
-		
-	if (first_word >= bdp->eeprom_size)
-		return -EFAULT;
-
-	if (ecmd.cmd == ETHTOOL_GEEPROM) {
-        	for(i = 0; i <= (last_word - first_word); i++)
-			eeprom_data[i] = e100_eeprom_read(bdp, first_word + i);
-
-		ecmd.magic = E100_EEPROM_MAGIC;
-
-		if (copy_to_user(ifr->ifr_data, &ecmd, sizeof (ecmd)))
-			return -EFAULT;
-
-		if(ecmd.offset & 1)
-			eeprom_data_bytes++;
-		if (copy_to_user(usr_eeprom_ptr, eeprom_data_bytes, ecmd.len))
-			return -EFAULT;
-	} else {
-		if (ecmd.magic != E100_EEPROM_MAGIC)
-			return -EFAULT;
-
-		ptr = (void *)eeprom_data;
-        	if(ecmd.offset & 1) {
-                	/* need modification of first changed EEPROM word */
-                	/* only the second byte of the word is being modified */
-			eeprom_data[0] = e100_eeprom_read(bdp, first_word);
-                	ptr++;
-        	}
-        	if((ecmd.offset + ecmd.len) & 1) {
-	                /* need modification of last changed EEPROM word */
-	                /* only the first byte of the word is being modified */
-			eeprom_data[last_word - first_word] = 
-				e100_eeprom_read(bdp, last_word);
-		}
-        	if(copy_from_user(ptr, usr_eeprom_ptr, ecmd.len))
-	                return -EFAULT;
-
-		e100_eeprom_write_block(bdp, first_word, eeprom_data,
-					last_word - first_word + 1);
-
-		if (copy_to_user(ifr->ifr_data, &ecmd, sizeof (ecmd)))
-			return -EFAULT;
-	}
-	return 0;
-}
-
-#define E100_BLINK_INTERVAL	(HZ/4)
-/**
- * e100_led_control
- * @bdp: atapter's private data struct
- * @led_mdi_op: led operation
- *
- * Software control over adapter's led. The possible operations are:
- * TURN LED OFF, TURN LED ON and RETURN LED CONTROL TO HARDWARE.
- */
-static void
-e100_led_control(struct e100_private *bdp, u16 led_mdi_op)
-{
-	e100_mdi_write(bdp, PHY_82555_LED_SWITCH_CONTROL,
-		       bdp->phy_addr, led_mdi_op);
-
-}
-/**
- * e100_led_blink_callback
- * @data: pointer to atapter's private data struct
- *
- * Blink timer callback function. Toggles ON/OFF led status bit and calls
- * led hardware access function. 
- */
-static void
-e100_led_blink_callback(unsigned long data)
-{
-	struct e100_private *bdp = (struct e100_private *) data;
-
-	if(bdp->flags & LED_IS_ON) {
-		bdp->flags &= ~LED_IS_ON;
-		e100_led_control(bdp, PHY_82555_LED_OFF);
-	} else {
-		bdp->flags |= LED_IS_ON;
-		if (bdp->rev_id >= D101MA_REV_ID)
-			e100_led_control(bdp, PHY_82555_LED_ON_559);
-		else
-			e100_led_control(bdp, PHY_82555_LED_ON_PRE_559);
-	}
-
-	mod_timer(&bdp->blink_timer, jiffies + E100_BLINK_INTERVAL);
-}
-/**
- * e100_ethtool_led_blink
- * @dev: pointer to atapter's net_device struct
- * @ifr: pointer to ioctl request structure
- *
- * Blink led ioctl handler. Initialtes blink timer and sleeps until
- * blink period expires. Than it kills timer and returns. The led control
- * is returned back to hardware when blink timer is killed.
- */
-static int
-e100_ethtool_led_blink(struct net_device *dev, struct ifreq *ifr)
-{
-	struct e100_private *bdp;
-	struct ethtool_value ecmd;
-
-	bdp = dev->priv;
-
-	if (copy_from_user(&ecmd, ifr->ifr_data, sizeof (ecmd)))
-		return -EFAULT;
-
-	if(!bdp->blink_timer.function) {
-		init_timer(&bdp->blink_timer);
-		bdp->blink_timer.function = e100_led_blink_callback;
-		bdp->blink_timer.data = (unsigned long) bdp;
-	}
-
-	mod_timer(&bdp->blink_timer, jiffies);
-
-	set_current_state(TASK_INTERRUPTIBLE);
-
-	if ((!ecmd.data) || (ecmd.data > (u32)(MAX_SCHEDULE_TIMEOUT / HZ)))
-		ecmd.data = (u32)(MAX_SCHEDULE_TIMEOUT / HZ);
-
-	schedule_timeout(ecmd.data * HZ);
-
-	del_timer_sync(&bdp->blink_timer);
-
-	e100_led_control(bdp, PHY_82555_LED_NORMAL_CONTROL);
-
-	return 0;
-}
-
-static inline int
-e100_10BaseT_adapter(struct e100_private *bdp)
-{
-	return ((bdp->pdev->device == 0x1229) &&
-		(bdp->pdev->subsystem_vendor == 0x8086) &&
-		(bdp->pdev->subsystem_device == 0x0003));
-}
-
-static void
-e100_get_speed_duplex_caps(struct e100_private *bdp)
-{
-	u16 status;
-
-	e100_mdi_read(bdp, MII_BMSR, bdp->phy_addr, &status);
-
-	bdp->speed_duplex_caps = 0;
-
-	bdp->speed_duplex_caps |=
-		(status & BMSR_ANEGCAPABLE) ? SUPPORTED_Autoneg : 0;
-
-	bdp->speed_duplex_caps |=
-		(status & BMSR_10HALF) ? SUPPORTED_10baseT_Half : 0;
-
-	bdp->speed_duplex_caps |=
-		(status & BMSR_10FULL) ? SUPPORTED_10baseT_Full : 0;
-
-	bdp->speed_duplex_caps |=
-		(status & BMSR_100HALF) ? SUPPORTED_100baseT_Half : 0;
-
-	bdp->speed_duplex_caps |=
-		(status & BMSR_100FULL) ? SUPPORTED_100baseT_Full : 0;
-
-	if (IS_NC3133(bdp))
-		bdp->speed_duplex_caps =
-			(SUPPORTED_FIBRE | SUPPORTED_100baseT_Full);
-	else
-		bdp->speed_duplex_caps |= SUPPORTED_TP;
-
-	if ((status == 0xFFFF) && e100_10BaseT_adapter(bdp)) {
-		bdp->speed_duplex_caps =
-			(SUPPORTED_10baseT_Half | SUPPORTED_TP);
-	} else {
-		bdp->speed_duplex_caps |= SUPPORTED_MII;
-	}
-
-}
-
-#ifdef CONFIG_PM
-static unsigned char
-e100_setup_filter(struct e100_private *bdp)
-{
-	cb_header_t *ntcb_hdr;
-	unsigned char res = false;
-	nxmit_cb_entry_t *cmd;
-
-	if ((cmd = e100_alloc_non_tx_cmd(bdp)) == NULL) {
-		goto exit;
-	}
-
-	ntcb_hdr = (cb_header_t *) cmd->non_tx_cmd;
-	ntcb_hdr->cb_cmd = __constant_cpu_to_le16(CB_LOAD_FILTER);
-
-	/* Set EL and FIX bit */
-	(cmd->non_tx_cmd)->ntcb.filter.filter_data[0] =
-		__constant_cpu_to_le32(CB_FILTER_EL | CB_FILTER_FIX);
-
-	if (bdp->wolopts & WAKE_UCAST) {
-		(cmd->non_tx_cmd)->ntcb.filter.filter_data[0] |=
-			__constant_cpu_to_le32(CB_FILTER_IA_MATCH);
-	}
-
-	if (bdp->wolopts & WAKE_ARP) {
-		/* Setup ARP bit and lower IP parts */
-		/* bdp->ip_lbytes contains 2 lower bytes of IP address in network byte order */
-		(cmd->non_tx_cmd)->ntcb.filter.filter_data[0] |=
-			cpu_to_le32(CB_FILTER_ARP | bdp->ip_lbytes);
-	}
-
-	res = e100_exec_non_cu_cmd(bdp, cmd);
-	if (!res)
-		printk(KERN_WARNING "e100: %s: Filter setup failed\n",
-		       bdp->device->name);
-
-exit:
-	return res;
-
-}
-
-static void
-e100_do_wol(struct pci_dev *pcid, struct e100_private *bdp)
-{
-	e100_config_wol(bdp);
-
-	if (e100_config(bdp)) {
-		if (bdp->wolopts & (WAKE_UCAST | WAKE_ARP))
-			if (!e100_setup_filter(bdp))
-				printk(KERN_ERR
-				       "e100: WOL options failed\n");
-	} else {
-		printk(KERN_ERR "e100: config WOL failed\n");
-	}
-}
-#endif
-
-static u16
-e100_get_ip_lbytes(struct net_device *dev)
-{
-	struct in_ifaddr *ifa;
-	struct in_device *in_dev;
-	u32 res = 0;
-
-	in_dev = (struct in_device *) dev->ip_ptr;
-	/* Check if any in_device bound to interface */
-	if (in_dev) {
-		/* Check if any IP address is bound to interface */
-		if ((ifa = in_dev->ifa_list) != NULL) {
-			res = __constant_ntohl(ifa->ifa_address);
-			res = __constant_htons(res & 0x0000ffff);
-		}
-	}
-	return res;
-}
-
-static int
-e100_ethtool_wol(struct net_device *dev, struct ifreq *ifr)
-{
-	struct e100_private *bdp;
-	struct ethtool_wolinfo wolinfo;
-	int res = 0;
-
-	bdp = dev->priv;
-
-	if (copy_from_user(&wolinfo, ifr->ifr_data, sizeof (wolinfo))) {
-		return -EFAULT;
-	}
-
-	switch (wolinfo.cmd) {
-	case ETHTOOL_GWOL:
-		wolinfo.supported = bdp->wolsupported;
-		wolinfo.wolopts = bdp->wolopts;
-		if (copy_to_user(ifr->ifr_data, &wolinfo, sizeof (wolinfo)))
-			res = -EFAULT;
-		break;
-	case ETHTOOL_SWOL:
-		/* If ALL requests are supported or request is DISABLE wol */
-		if (((wolinfo.wolopts & bdp->wolsupported) == wolinfo.wolopts)
-		    || (wolinfo.wolopts == 0)) {
-			bdp->wolopts = wolinfo.wolopts;
-		} else {
-			res = -EOPNOTSUPP;
-		}
-		if (wolinfo.wolopts & WAKE_ARP)
-			bdp->ip_lbytes = e100_get_ip_lbytes(dev);
-		break;
-	default:
-		break;
-	}
-	return res;
-}
-
-static int e100_ethtool_gstrings(struct net_device *dev, struct ifreq *ifr)
-{
-	struct ethtool_gstrings info;
-	char *strings = NULL;
-	char *usr_strings;
-	int i;
-
-	memset((void *) &info, 0, sizeof(info));
-
-	usr_strings = (u8 *) (ifr->ifr_data + 
-			      offsetof(struct ethtool_gstrings, data));
-
-	if (copy_from_user(&info, ifr->ifr_data, sizeof (info)))
-		return -EFAULT;
-
-	switch (info.string_set) {
-	case ETH_SS_TEST: {
-		int ret = 0;
-		if (info.len > max_test_res)
-			info.len = max_test_res;
-		strings = kmalloc(info.len * ETH_GSTRING_LEN, GFP_ATOMIC);
-		if (!strings)
-			return -ENOMEM;
-		memset(strings, 0, info.len * ETH_GSTRING_LEN);
-
-		for (i = 0; i < info.len; i++) {
-			sprintf(strings + i * ETH_GSTRING_LEN, "%s",
-				test_strings[i]);
-		}
-		if (copy_to_user(ifr->ifr_data, &info, sizeof (info)))
-			ret = -EFAULT;
-		if (copy_to_user(usr_strings, strings, info.len * ETH_GSTRING_LEN))
-			ret = -EFAULT;
-		kfree(strings);
-		return ret;
-	}
-	case ETH_SS_STATS: {
-		char *strings = NULL;
-		void *addr = ifr->ifr_data;
-		info.len = E100_STATS_LEN;
-		strings = *e100_gstrings_stats;
-		if(copy_to_user(ifr->ifr_data, &info, sizeof(info)))
-			return -EFAULT;
-		addr += offsetof(struct ethtool_gstrings, data);
-		if(copy_to_user(addr, strings,
-		   info.len * ETH_GSTRING_LEN))
-			return -EFAULT;
-		return 0;
-	}
-	default:
-		return -EOPNOTSUPP;
-	}
-}
-
-static int
-e100_mii_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
-{
-	struct e100_private *bdp;
-	struct mii_ioctl_data *data_ptr =
-		(struct mii_ioctl_data *) &(ifr->ifr_data);
-
-	bdp = dev->priv;
-
-	switch (cmd) {
-	case SIOCGMIIPHY:
-		data_ptr->phy_id = bdp->phy_addr & 0x1f;
-		break;
-
-	case SIOCGMIIREG:
-		if (!capable(CAP_NET_ADMIN))
-			return -EPERM;
-		e100_mdi_read(bdp, data_ptr->reg_num & 0x1f, bdp->phy_addr,
-			      &(data_ptr->val_out));
-		break;
-
-	case SIOCSMIIREG:
-		if (!capable(CAP_NET_ADMIN))
-			return -EPERM;
-		/* If reg = 0 && change speed/duplex */
-		if (data_ptr->reg_num == 0 && 
-			(data_ptr->val_in == (BMCR_ANENABLE | BMCR_ANRESTART) /* restart cmd */
-			|| data_ptr->val_in == (BMCR_RESET) /* reset cmd */ 
-			|| data_ptr->val_in & (BMCR_SPEED100 | BMCR_FULLDPLX) 
-			|| data_ptr->val_in == 0)) {
-				if (data_ptr->val_in == (BMCR_ANENABLE | BMCR_ANRESTART)
-					|| data_ptr->val_in == (BMCR_RESET))
-					bdp->params.e100_speed_duplex = E100_AUTONEG;
-				else if (data_ptr->val_in == (BMCR_SPEED100 | BMCR_FULLDPLX))
-					bdp->params.e100_speed_duplex = E100_SPEED_100_FULL;
-				else if (data_ptr->val_in == (BMCR_SPEED100))
-					bdp->params.e100_speed_duplex = E100_SPEED_100_HALF;
-				else if (data_ptr->val_in == (BMCR_FULLDPLX))
-					bdp->params.e100_speed_duplex = E100_SPEED_10_FULL;
-				else
-					bdp->params.e100_speed_duplex = E100_SPEED_10_HALF;
-				if (netif_running(dev)) {
-					spin_lock_bh(&dev->xmit_lock);
-					e100_close(dev);
-					spin_unlock_bh(&dev->xmit_lock);
-					e100_hw_init(bdp);
-					e100_open(dev);
-				}
-		}
-		else 
-			/* Only allows changing speed/duplex */
-			return -EINVAL;
-		
-		break;
-
-	default:
-		return -EOPNOTSUPP;
-	}
-	return 0;
-}
-
-nxmit_cb_entry_t *
-e100_alloc_non_tx_cmd(struct e100_private *bdp)
-{
-	nxmit_cb_entry_t *non_tx_cmd_elem;
-
-	if (!(non_tx_cmd_elem = (nxmit_cb_entry_t *)
-	      kmalloc(sizeof (nxmit_cb_entry_t), GFP_ATOMIC))) {
-		return NULL;
-	}
-	non_tx_cmd_elem->non_tx_cmd =
-		pci_alloc_consistent(bdp->pdev, sizeof (nxmit_cb_t),
-				     &(non_tx_cmd_elem->dma_addr));
-	if (non_tx_cmd_elem->non_tx_cmd == NULL) {
-		kfree(non_tx_cmd_elem);
-		return NULL;
-	}
-	return non_tx_cmd_elem;
-}
-
-void
-e100_free_non_tx_cmd(struct e100_private *bdp,
-		     nxmit_cb_entry_t *non_tx_cmd_elem)
-{
-	pci_free_consistent(bdp->pdev, sizeof (nxmit_cb_t),
-			    non_tx_cmd_elem->non_tx_cmd,
-			    non_tx_cmd_elem->dma_addr);
-	kfree(non_tx_cmd_elem);
-}
-
-static void
-e100_free_nontx_list(struct e100_private *bdp)
-{
-	nxmit_cb_entry_t *command;
-	int i;
-
-	while (!list_empty(&bdp->non_tx_cmd_list)) {
-		command = list_entry(bdp->non_tx_cmd_list.next,
-				     nxmit_cb_entry_t, list_elem);
-		list_del(&(command->list_elem));
-		e100_free_non_tx_cmd(bdp, command);
-	}
-
-	for (i = 0; i < CB_MAX_NONTX_CMD; i++) {
-		bdp->same_cmd_entry[i] = NULL;
-	}
-}
-
-static unsigned char
-e100_delayed_exec_non_cu_cmd(struct e100_private *bdp,
-			     nxmit_cb_entry_t *command)
-{
-	nxmit_cb_entry_t *same_command;
-	cb_header_t *ntcb_hdr;
-	u16 cmd;
-
-	ntcb_hdr = (cb_header_t *) command->non_tx_cmd;
-
-	cmd = CB_CMD_MASK & le16_to_cpu(ntcb_hdr->cb_cmd);
-
-	spin_lock_bh(&(bdp->bd_non_tx_lock));
-
-	same_command = bdp->same_cmd_entry[cmd];
-
-	if (same_command != NULL) {
-		memcpy((void *) (same_command->non_tx_cmd),
-		       (void *) (command->non_tx_cmd), sizeof (nxmit_cb_t));
-		e100_free_non_tx_cmd(bdp, command);
-	} else {
-		list_add_tail(&(command->list_elem), &(bdp->non_tx_cmd_list));
-		bdp->same_cmd_entry[cmd] = command;
-	}
-
-	if (bdp->non_tx_command_state == E100_NON_TX_IDLE) {
-		bdp->non_tx_command_state = E100_WAIT_TX_FINISH;
-		mod_timer(&(bdp->nontx_timer_id), jiffies + 1);
-	}
-
-	spin_unlock_bh(&(bdp->bd_non_tx_lock));
-	return true;
-}
-
-static void
-e100_non_tx_background(unsigned long ptr)
-{
-	struct e100_private *bdp = (struct e100_private *) ptr;
-	nxmit_cb_entry_t *active_command;
-	int restart = true;
-	cb_header_t *non_tx_cmd;
-	u8 sub_cmd;
-
-	spin_lock_bh(&(bdp->bd_non_tx_lock));
-
-	switch (bdp->non_tx_command_state) {
-	case E100_WAIT_TX_FINISH:
-		if (bdp->last_tcb != NULL) {
-			rmb();
-			if ((bdp->last_tcb->tcb_hdr.cb_status &
-			     __constant_cpu_to_le16(CB_STATUS_COMPLETE)) == 0)
-				goto exit;
-		}
-		if ((readw(&bdp->scb->scb_status) & SCB_CUS_MASK) ==
-		    SCB_CUS_ACTIVE) {
-			goto exit;
-		}
-		break;
-
-	case E100_WAIT_NON_TX_FINISH:
-		active_command = list_entry(bdp->non_tx_cmd_list.next,
-					    nxmit_cb_entry_t, list_elem);
-		rmb();
-
-		if (((((cb_header_t *) (active_command->non_tx_cmd))->cb_status
-		      & __constant_cpu_to_le16(CB_STATUS_COMPLETE)) == 0)
-		    && time_before(jiffies, active_command->expiration_time)) {
-			goto exit;
-		} else {
-			non_tx_cmd = (cb_header_t *) active_command->non_tx_cmd;
-			sub_cmd = CB_CMD_MASK & le16_to_cpu(non_tx_cmd->cb_cmd);
-#ifdef E100_CU_DEBUG			
-			if (!(non_tx_cmd->cb_status 
-			    & __constant_cpu_to_le16(CB_STATUS_COMPLETE)))
-				printk(KERN_ERR "e100: %s: Queued "
-					"command (%x) timeout\n", 
-					bdp->device->name, sub_cmd);
-#endif			
-			list_del(&(active_command->list_elem));
-			e100_free_non_tx_cmd(bdp, active_command);
-		}
-		break;
-
-	default:
-		break;
-	}			//switch
-
-	if (list_empty(&bdp->non_tx_cmd_list)) {
-		bdp->non_tx_command_state = E100_NON_TX_IDLE;
-		spin_lock_irq(&(bdp->bd_lock));
-		bdp->next_cu_cmd = START_WAIT;
-		spin_unlock_irq(&(bdp->bd_lock));
-		restart = false;
-		goto exit;
-	} else {
-		u16 cmd_type;
-
-		bdp->non_tx_command_state = E100_WAIT_NON_TX_FINISH;
-		active_command = list_entry(bdp->non_tx_cmd_list.next,
-					    nxmit_cb_entry_t, list_elem);
-		sub_cmd = ((cb_header_t *) active_command->non_tx_cmd)->cb_cmd;
-		spin_lock_irq(&(bdp->bd_lock));
-		e100_wait_exec_cmplx(bdp, active_command->dma_addr,
-				     SCB_CUC_START, sub_cmd);
-		spin_unlock_irq(&(bdp->bd_lock));
-		active_command->expiration_time = jiffies + HZ;
-		cmd_type = CB_CMD_MASK &
-			le16_to_cpu(((cb_header_t *)
-				     (active_command->non_tx_cmd))->cb_cmd);
-		bdp->same_cmd_entry[cmd_type] = NULL;
-	}
-
-exit:
-	if (restart) {
-		mod_timer(&(bdp->nontx_timer_id), jiffies + 1);
-	} else {
-		if (netif_running(bdp->device))
-			netif_wake_queue(bdp->device);
-	}
-	spin_unlock_bh(&(bdp->bd_non_tx_lock));
-}
-
-static void
-e100_vlan_rx_register(struct net_device *netdev, struct vlan_group *grp)
-{
-	struct e100_private *bdp = netdev->priv;
-
-	e100_disable_clear_intr(bdp);
-	bdp->vlgrp = grp;
-
-	if(grp) {
-		/* enable VLAN tag insert/strip */
-		e100_config_vlan_drop(bdp, true);
-
-	} else {
-		/* disable VLAN tag insert/strip */
-		e100_config_vlan_drop(bdp, false);
-	}
-
-	e100_config(bdp);
-	e100_set_intr_mask(bdp);
-}
-
-static void
-e100_vlan_rx_add_vid(struct net_device *netdev, u16 vid)
-{
-	/* We don't do Vlan filtering */
-	return;
-}
-
-static void
-e100_vlan_rx_kill_vid(struct net_device *netdev, u16 vid)
-{
-	struct e100_private *bdp = netdev->priv;
-
-	if(bdp->vlgrp)
-		bdp->vlgrp->vlan_devices[vid] = NULL;
-	/* We don't do Vlan filtering */
-	return;
-}
-
-#ifdef CONFIG_PM
-static int
-e100_notify_reboot(struct notifier_block *nb, unsigned long event, void *p)
-{
-        struct pci_dev *pdev = NULL;
-	
-        switch(event) {
-        case SYS_DOWN:
-        case SYS_HALT:
-        case SYS_POWER_OFF:
-		while ((pdev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, pdev)) != NULL) {
-                        if(pci_dev_driver(pdev) == &e100_driver) {
-				/* If net_device struct is allocated? */
-                                if (pci_get_drvdata(pdev))
-					e100_suspend(pdev, 3);
-
-			}
-		}
-        }
-        return NOTIFY_DONE;
-}
-
-static int
-e100_suspend(struct pci_dev *pcid, u32 state)
-{
-	struct net_device *netdev = pci_get_drvdata(pcid);
-	struct e100_private *bdp = netdev->priv;
-
-	e100_isolate_driver(bdp);
-	pci_save_state(pcid, bdp->pci_state);
-
-	/* Enable or disable WoL */
-	e100_do_wol(pcid, bdp);
-	
-	/* If wol is enabled */
-	if (bdp->wolopts || e100_asf_enabled(bdp)) {
-		pci_enable_wake(pcid, 3, 1);	/* Enable PME for power state D3 */
-		pci_set_power_state(pcid, 3);	/* Set power state to D3.        */
-	} else {
-		/* Disable bus mastering */
-		pci_disable_device(pcid);
-		pci_set_power_state(pcid, state);
-	}
-	return 0;
-}
-
-static int
-e100_resume(struct pci_dev *pcid)
-{
-	struct net_device *netdev = pci_get_drvdata(pcid);
-	struct e100_private *bdp = netdev->priv;
-
-	pci_set_power_state(pcid, 0);
-	pci_enable_wake(pcid, 0, 0);	/* Clear PME status and disable PME */
-	pci_restore_state(pcid, bdp->pci_state);
-
-	/* Also do device full reset because device was in D3 state */
-	e100_deisolate_driver(bdp, true);
-
-	return 0;
-}
-
-/**
- * e100_asf_enabled - checks if ASF is configured on the current adaper
- *                    by reading registers 0xD and 0x90 in the EEPROM 
- * @bdp: atapter's private data struct
- *
- * Returns: true if ASF is enabled
- */
-static unsigned char
-e100_asf_enabled(struct e100_private *bdp)
-{
-	u16 asf_reg;
-	u16 smbus_addr_reg;
-	if ((bdp->pdev->device >= 0x1050) && (bdp->pdev->device <= 0x1055)) {
-		asf_reg = e100_eeprom_read(bdp, EEPROM_CONFIG_ASF);
-		if ((asf_reg & EEPROM_FLAG_ASF)
-		    && !(asf_reg & EEPROM_FLAG_GCL)) {
-			smbus_addr_reg = 
-				e100_eeprom_read(bdp, EEPROM_SMBUS_ADDR);
-			if ((smbus_addr_reg & 0xFF) != 0xFE) 
-				return true;
-		}
-	}
-	return false;
-}
-#endif /* CONFIG_PM */
-
-#ifdef E100_CU_DEBUG
-unsigned char
-e100_cu_unknown_state(struct e100_private *bdp)
-{
-	u8 scb_cmd_low;
-	u16 scb_status;
-	scb_cmd_low = bdp->scb->scb_cmd_low;
-	scb_status = le16_to_cpu(bdp->scb->scb_status);
-	/* If CU is active and executing unknown cmd */
-	if (scb_status & SCB_CUS_ACTIVE && scb_cmd_low & SCB_CUC_UNKNOWN)
-		return true;
-	else
-		return false;
-}
-#endif
-
--- diff/drivers/net/e100/e100_phy.c	2004-01-19 10:22:57.000000000 +0000
+++ source/drivers/net/e100/e100_phy.c	1970-01-01 01:00:00.000000000 +0100
@@ -1,1163 +0,0 @@
-/*******************************************************************************
-
-  
-  Copyright(c) 1999 - 2003 Intel Corporation. All rights reserved.
-  
-  This program is free software; you can redistribute it and/or modify it 
-  under the terms of the GNU General Public License as published by the Free 
-  Software Foundation; either version 2 of the License, or (at your option) 
-  any later version.
-  
-  This program is distributed in the hope that it will be useful, but WITHOUT 
-  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 
-  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for 
-  more details.
-  
-  You should have received a copy of the GNU General Public License along with
-  this program; if not, write to the Free Software Foundation, Inc., 59 
-  Temple Place - Suite 330, Boston, MA  02111-1307, USA.
-  
-  The full GNU General Public License is included in this distribution in the
-  file called LICENSE.
-  
-  Contact Information:
-  Linux NICS <linux.nics@intel.com>
-  Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
-*******************************************************************************/
-
-#include "e100_phy.h"
-
-void e100_handle_zlock(struct e100_private *bdp);
-
-/* 
- * Procedure:	e100_mdi_write
- *
- * Description: This routine will write a value to the specified MII register
- *		of an external MDI compliant device (e.g. PHY 100).  The
- *		command will execute in polled mode.
- *
- * Arguments:
- *	bdp - Ptr to this card's e100_bdconfig structure
- *	reg_addr - The MII register that we are writing to
- *	phy_addr - The MDI address of the Phy component.
- *	data - The value that we are writing to the MII register.
- *
- * Returns:
- *	NOTHING
- */
-int
-e100_mdi_write(struct e100_private *bdp, u32 reg_addr, u32 phy_addr, u16 data)
-{
-	int e100_retry;
-	u32 temp_val;
-	unsigned int mdi_cntrl;
-
-	spin_lock_bh(&bdp->mdi_access_lock);
-	temp_val = (((u32) data) | (reg_addr << 16) |
-		    (phy_addr << 21) | (MDI_WRITE << 26));
-	writel(temp_val, &bdp->scb->scb_mdi_cntrl);
-	readw(&bdp->scb->scb_status);
-
-	/* wait 20usec before checking status */
-	udelay(20);
-
-	/* poll for the mdi write to complete */
-	e100_retry = E100_CMD_WAIT;
-	while ((!((mdi_cntrl = readl(&bdp->scb->scb_mdi_cntrl)) & MDI_PHY_READY)) && (e100_retry)) {
-
-		udelay(20);
-		e100_retry--;
-	}
-	spin_unlock_bh(&bdp->mdi_access_lock);
-	if (mdi_cntrl & MDI_PHY_READY) 
-		return 0;
-	else {
-		printk(KERN_ERR "e100: MDI write timeout\n");
-		return 1;
-	}
-}
-
-/* 
- * Procedure:	e100_mdi_read
- *
- * Description: This routine will read a value from the specified MII register
- *		of an external MDI compliant device (e.g. PHY 100), and return
- *		it to the calling routine.  The command will execute in polled
- *		mode.
- *
- * Arguments:
- *	bdp - Ptr to this card's e100_bdconfig structure
- *	reg_addr - The MII register that we are reading from
- *	phy_addr - The MDI address of the Phy component.
- *
- * Results:
- *	data - The value that we read from the MII register.
- *
- * Returns:
- *	NOTHING
- */
-int
-e100_mdi_read(struct e100_private *bdp, u32 reg_addr, u32 phy_addr, u16 *data)
-{
-	int e100_retry;
-	u32 temp_val;
-	unsigned int mdi_cntrl;
-
-	spin_lock_bh(&bdp->mdi_access_lock);
-	/* Issue the read command to the MDI control register. */
-	temp_val = ((reg_addr << 16) | (phy_addr << 21) | (MDI_READ << 26));
-	writel(temp_val, &bdp->scb->scb_mdi_cntrl);
-	readw(&bdp->scb->scb_status);
-
-	/* wait 20usec before checking status */
-	udelay(20);
-
-	/* poll for the mdi read to complete */
-	e100_retry = E100_CMD_WAIT;
-	while ((!((mdi_cntrl = readl(&bdp->scb->scb_mdi_cntrl)) & MDI_PHY_READY)) && (e100_retry)) {
-
-		udelay(20);
-		e100_retry--;
-	}
-
-	spin_unlock_bh(&bdp->mdi_access_lock);
-	if (mdi_cntrl & MDI_PHY_READY) {
-		/* return the lower word */
-		*data = (u16) mdi_cntrl;
-		return 0;
-	}
-	else {
-		printk(KERN_ERR "e100: MDI read timeout\n");
-		return 1;
-	}
-}
-
-static unsigned char
-e100_phy_valid(struct e100_private *bdp, unsigned int phy_address)
-{
-	u16 ctrl_reg, stat_reg;
-
-	/* Read the MDI control register */
-	e100_mdi_read(bdp, MII_BMCR, phy_address, &ctrl_reg);
-
-	/* Read the status register twice, bacause of sticky bits */
-	e100_mdi_read(bdp, MII_BMSR, phy_address, &stat_reg);
-	e100_mdi_read(bdp, MII_BMSR, phy_address, &stat_reg);
-
-	if ((ctrl_reg == 0xffff) || ((stat_reg == 0) && (ctrl_reg == 0)))
-		return false;
-
-	return true;
-}
-
-static void
-e100_phy_address_detect(struct e100_private *bdp)
-{
-	unsigned int addr;
-	unsigned char valid_phy_found = false;
-
-	if (IS_NC3133(bdp)) {
-		bdp->phy_addr = 0;
-		return;
-	}
-
-	if (e100_phy_valid(bdp, PHY_DEFAULT_ADDRESS)) {
-		bdp->phy_addr = PHY_DEFAULT_ADDRESS;
-		valid_phy_found = true;
-
-	} else {
-		for (addr = MIN_PHY_ADDR; addr <= MAX_PHY_ADDR; addr++) {
-			if (e100_phy_valid(bdp, addr)) {
-				bdp->phy_addr = addr;
-				valid_phy_found = true;
-				break;
-			}
-		}
-	}
-
-	if (!valid_phy_found) {
-		bdp->phy_addr = PHY_ADDRESS_503;
-	}
-}
-
-static void
-e100_phy_id_detect(struct e100_private *bdp)
-{
-	u16 low_id_reg, high_id_reg;
-
-	if (bdp->phy_addr == PHY_ADDRESS_503) {
-		bdp->PhyId = PHY_503;
-		return;
-	}
-	if (!(bdp->flags & IS_ICH)) {
-		if (bdp->rev_id >= D102_REV_ID) {
-			bdp->PhyId = PHY_82562ET;
-			return;
-		}
-	}
-
-	/* Read phy id from the MII register */
-	e100_mdi_read(bdp, MII_PHYSID1, bdp->phy_addr, &low_id_reg);
-	e100_mdi_read(bdp, MII_PHYSID2, bdp->phy_addr, &high_id_reg);
-
-	bdp->PhyId = ((unsigned int) low_id_reg |
-		      ((unsigned int) high_id_reg << 16));
-}
-
-static void
-e100_phy_isolate(struct e100_private *bdp)
-{
-	unsigned int phy_address;
-	u16 ctrl_reg;
-
-	/* Go over all phy addresses. Deisolate the selected one, and isolate
-	 * all the rest */
-	for (phy_address = 0; phy_address <= MAX_PHY_ADDR; phy_address++) {
-		if (phy_address != bdp->phy_addr) {
-			e100_mdi_write(bdp, MII_BMCR, phy_address,
-				       BMCR_ISOLATE);
-
-		} else {
-			e100_mdi_read(bdp, MII_BMCR, bdp->phy_addr, &ctrl_reg);
-			ctrl_reg &= ~BMCR_ISOLATE;
-			e100_mdi_write(bdp, MII_BMCR, bdp->phy_addr, ctrl_reg);
-		}
-
-		udelay(100);
-	}
-}
-
-static unsigned char
-e100_phy_specific_setup(struct e100_private *bdp)
-{
-	u16 misc_reg;
-
-	if (bdp->phy_addr == PHY_ADDRESS_503) {
-		switch (bdp->params.e100_speed_duplex) {
-		case E100_AUTONEG:
-			/* The adapter can't autoneg. so set to 10/HALF */
-			printk(KERN_INFO
-			       "e100: 503 serial component detected which "
-			       "cannot autonegotiate\n");
-			printk(KERN_INFO
-			       "e100: speed/duplex forced to "
-			       "10Mbps / Half duplex\n");
-			bdp->params.e100_speed_duplex = E100_SPEED_10_HALF;
-			break;
-
-		case E100_SPEED_100_HALF:
-		case E100_SPEED_100_FULL:
-			printk(KERN_ERR
-			       "e100: 503 serial component detected "
-			       "which does not support 100Mbps\n");
-			printk(KERN_ERR
-			       "e100: Change the forced speed/duplex "
-			       "to a supported setting\n");
-			return false;
-		}
-
-		return true;
-	}
-
-	if (IS_NC3133(bdp)) {
-		u16 int_reg;
-
-		/* enable 100BASE fiber interface */
-		e100_mdi_write(bdp, MDI_NC3133_CONFIG_REG, bdp->phy_addr,
-			       MDI_NC3133_100FX_ENABLE);
-
-		if ((bdp->params.e100_speed_duplex != E100_AUTONEG) &&
-		    (bdp->params.e100_speed_duplex != E100_SPEED_100_FULL)) {
-			/* just inform user about 100 full */
-			printk(KERN_ERR "e100: NC3133 NIC can only run "
-			       "at 100Mbps full duplex\n");
-		}
-
-		bdp->params.e100_speed_duplex = E100_SPEED_100_FULL;
-
-		/* enable interrupts */
-		e100_mdi_read(bdp, MDI_NC3133_INT_ENABLE_REG,
-			      bdp->phy_addr, &int_reg);
-		int_reg |= MDI_NC3133_INT_ENABLE;
-		e100_mdi_write(bdp, MDI_NC3133_INT_ENABLE_REG,
-			       bdp->phy_addr, int_reg);
-	}
-
-	/* Handle the National TX */
-	if ((bdp->PhyId & PHY_MODEL_REV_ID_MASK) == PHY_NSC_TX) {
-		e100_mdi_read(bdp, NSC_CONG_CONTROL_REG,
-			      bdp->phy_addr, &misc_reg);
-
-		misc_reg |= NSC_TX_CONG_TXREADY;
-
-		/* disable the congestion control bit in the National Phy */
-		misc_reg &= ~NSC_TX_CONG_ENABLE;
-
-		e100_mdi_write(bdp, NSC_CONG_CONTROL_REG,
-			       bdp->phy_addr, misc_reg);
-	}
-
-	return true;
-}
-
-/* 
- * Procedure:	e100_phy_fix_squelch
- *
- * Description:
- *	Help find link on certain rare scenarios.
- *	NOTE: This routine must be called once per watchdog,
- *	      and *after* setting the current link state.
- *
- * Arguments:
- *	bdp - Ptr to this card's e100_bdconfig structure
- *
- * Returns:
- *	NOTHING
- */
-static void
-e100_phy_fix_squelch(struct e100_private *bdp)
-{
-	if ((bdp->PhyId != PHY_82555_TX) || (bdp->flags & DF_SPEED_FORCED))
-		return;
-
-	if (netif_carrier_ok(bdp->device)) {
-		switch (bdp->PhyState) {
-		case 0:
-			break;
-		case 1:
-			e100_mdi_write(bdp, PHY_82555_SPECIAL_CONTROL,
-				       bdp->phy_addr, 0x0000);
-			break;
-		case 2:
-			e100_mdi_write(bdp, PHY_82555_MDI_EQUALIZER_CSR,
-				       bdp->phy_addr, 0x3000);
-			break;
-		}
-		bdp->PhyState = 0;
-		bdp->PhyDelay = 0;
-
-	} else if (!bdp->PhyDelay--) {
-		switch (bdp->PhyState) {
-		case 0:
-			e100_mdi_write(bdp, PHY_82555_SPECIAL_CONTROL,
-				       bdp->phy_addr, EXTENDED_SQUELCH_BIT);
-			bdp->PhyState = 1;
-			break;
-		case 1:
-			e100_mdi_write(bdp, PHY_82555_SPECIAL_CONTROL,
-				       bdp->phy_addr, 0x0000);
-			e100_mdi_write(bdp, PHY_82555_MDI_EQUALIZER_CSR,
-				       bdp->phy_addr, 0x2010);
-			bdp->PhyState = 2;
-			break;
-		case 2:
-			e100_mdi_write(bdp, PHY_82555_MDI_EQUALIZER_CSR,
-				       bdp->phy_addr, 0x3000);
-			bdp->PhyState = 0;
-			break;
-		}
-
-		e100_mdi_write(bdp, MII_BMCR, bdp->phy_addr,
-			       BMCR_ANENABLE | BMCR_ANRESTART);
-		bdp->PhyDelay = 3;
-	}
-}
-
-/* 
- * Procedure:	e100_fix_polarity
- *
- * Description:
- *	Fix for 82555 auto-polarity toggle problem. With a short cable 
- *	connecting an 82555 with an 840A link partner, if the medium is noisy,
- *	the 82555 sometime thinks that the polarity might be wrong and so 
- *	toggles polarity. This happens repeatedly and results in a high bit 
- *	error rate.
- *	NOTE: This happens only at 10 Mbps
- *
- * Arguments:
- *	bdp - Ptr to this card's e100_bdconfig structure
- *
- * Returns:
- *	NOTHING
- */
-static void
-e100_fix_polarity(struct e100_private *bdp)
-{
-	u16 status;
-	u16 errors;
-	u16 misc_reg;
-	int speed;
-
-	if ((bdp->PhyId != PHY_82555_TX) && (bdp->PhyId != PHY_82562ET) &&
-	    (bdp->PhyId != PHY_82562EM))
-		return;
-
-	/* If the user wants auto-polarity disabled, do only that and nothing *
-	 * else. * e100_autopolarity == 0 means disable --- we do just the
-	 * disabling * e100_autopolarity == 1 means enable  --- we do nothing at
-	 * all * e100_autopolarity >= 2 means we do the workaround code. */
-	/* Change for 82558 enhancement */
-	switch (E100_AUTOPOLARITY) {
-	case 0:
-		e100_mdi_read(bdp, PHY_82555_SPECIAL_CONTROL,
-			      bdp->phy_addr, &misc_reg);
-		e100_mdi_write(bdp, PHY_82555_SPECIAL_CONTROL, bdp->phy_addr,
-			       (u16) (misc_reg | DISABLE_AUTO_POLARITY));
-		break;
-
-	case 1:
-		e100_mdi_read(bdp, PHY_82555_SPECIAL_CONTROL,
-			      bdp->phy_addr, &misc_reg);
-		e100_mdi_write(bdp, PHY_82555_SPECIAL_CONTROL, bdp->phy_addr,
-			       (u16) (misc_reg & ~DISABLE_AUTO_POLARITY));
-		break;
-
-	case 2:
-		/* we do this only if link is up */
-		if (!netif_carrier_ok(bdp->device)) {
-			break;
-		}
-
-		e100_mdi_read(bdp, PHY_82555_CSR, bdp->phy_addr, &status);
-		speed = (status & PHY_82555_SPEED_BIT) ? 100 : 10;
-
-		/* we need to do this only if speed is 10 */
-		if (speed != 10) {
-			break;
-		}
-
-		/* see if we have any end of frame errors */
-		e100_mdi_read(bdp, PHY_82555_EOF_COUNTER,
-			      bdp->phy_addr, &errors);
-
-		/* if non-zero, wait for 100 ms before reading again */
-		if (errors) {
-			udelay(200);
-			e100_mdi_read(bdp, PHY_82555_EOF_COUNTER,
-				      bdp->phy_addr, &errors);
-
-			/* if non-zero again, we disable polarity */
-			if (errors) {
-				e100_mdi_read(bdp, PHY_82555_SPECIAL_CONTROL,
-					      bdp->phy_addr, &misc_reg);
-				e100_mdi_write(bdp, PHY_82555_SPECIAL_CONTROL,
-					       bdp->phy_addr,
-					       (u16) (misc_reg |
-						      DISABLE_AUTO_POLARITY));
-			}
-		}
-
-		if (!errors) {
-			/* it is safe to read the polarity now */
-			e100_mdi_read(bdp, PHY_82555_CSR,
-				      bdp->phy_addr, &status);
-
-			/* if polarity is normal, disable polarity */
-			if (!(status & PHY_82555_POLARITY_BIT)) {
-				e100_mdi_read(bdp, PHY_82555_SPECIAL_CONTROL,
-					      bdp->phy_addr, &misc_reg);
-				e100_mdi_write(bdp, PHY_82555_SPECIAL_CONTROL,
-					       bdp->phy_addr,
-					       (u16) (misc_reg |
-						      DISABLE_AUTO_POLARITY));
-			}
-		}
-		break;
-
-	default:
-		break;
-	}
-}
-
-/* 
- * Procedure:	e100_find_speed_duplex
- *
- * Description: This routine will figure out what line speed and duplex mode
- *		the PHY is currently using.
- *
- * Arguments:
- *	bdp - Ptr to this card's e100_bdconfig structure
- *
- * Returns:
- *	NOTHING
- */
-static void
-e100_find_speed_duplex(struct e100_private *bdp)
-{
-	unsigned int PhyId;
-	u16 stat_reg, misc_reg;
-	u16 ad_reg, lp_ad_reg;
-
-	PhyId = bdp->PhyId & PHY_MODEL_REV_ID_MASK;
-
-	/* First we should check to see if we have link */
-	/* If we don't have a link no reason to print a speed and duplex */
-	if (!e100_update_link_state(bdp)) {
-		bdp->cur_line_speed = 0;
-		bdp->cur_dplx_mode = 0;
-		return;
-	}
-
-	/* On the 82559 and later controllers, speed/duplex is part of the *
-	 * SCB. So, we save an mdi_read and get these from the SCB. * */
-	if (bdp->rev_id >= D101MA_REV_ID) {
-		/* Read speed */
-		if (readb(&bdp->scb->scb_ext.d101m_scb.scb_gen_stat) & BIT_1)
-			bdp->cur_line_speed = 100;
-		else
-			bdp->cur_line_speed = 10;
-
-		/* Read duplex */
-		if (readb(&bdp->scb->scb_ext.d101m_scb.scb_gen_stat) & BIT_2)
-			bdp->cur_dplx_mode = FULL_DUPLEX;
-		else
-			bdp->cur_dplx_mode = HALF_DUPLEX;
-
-		return;
-	}
-
-	/* If this is a Phy 100, then read bits 1 and 0 of extended register 0,
-	 * to get the current speed and duplex settings. */
-	if ((PhyId == PHY_100_A) || (PhyId == PHY_100_C) ||
-	    (PhyId == PHY_82555_TX)) {
-
-		/* Read Phy 100 extended register 0 */
-		e100_mdi_read(bdp, EXTENDED_REG_0, bdp->phy_addr, &misc_reg);
-
-		/* Get current speed setting */
-		if (misc_reg & PHY_100_ER0_SPEED_INDIC)
-			bdp->cur_line_speed = 100;
-		else
-			bdp->cur_line_speed = 10;
-
-		/* Get current duplex setting -- FDX enabled if bit is set */
-		if (misc_reg & PHY_100_ER0_FDX_INDIC)
-			bdp->cur_dplx_mode = FULL_DUPLEX;
-		else
-			bdp->cur_dplx_mode = HALF_DUPLEX;
-
-		return;
-	}
-
-	/* See if link partner is capable of Auto-Negotiation (bit 0, reg 6) */
-	e100_mdi_read(bdp, MII_EXPANSION, bdp->phy_addr, &misc_reg);
-
-	/* See if Auto-Negotiation was complete (bit 5, reg 1) */
-	e100_mdi_read(bdp, MII_BMSR, bdp->phy_addr, &stat_reg);
-
-	/* If a True NWAY connection was made, then we can detect speed/dplx
-	 * by ANDing our adapter's advertised abilities with our link partner's
-	 * advertised ablilities, and then assuming that the highest common
-	 * denominator was chosed by NWAY. */
-	if ((misc_reg & EXPANSION_NWAY) && (stat_reg & BMSR_ANEGCOMPLETE)) {
-
-		/* Read our advertisement register */
-		e100_mdi_read(bdp, MII_ADVERTISE, bdp->phy_addr, &ad_reg);
-
-		/* Read our link partner's advertisement register */
-		e100_mdi_read(bdp, MII_LPA, bdp->phy_addr, &lp_ad_reg);
-
-		/* AND the two advertisement registers together, and get rid
-		 * of any extraneous bits. */
-		ad_reg &= (lp_ad_reg & NWAY_LP_ABILITY);
-
-		/* Get speed setting */
-		if (ad_reg &
-		    (ADVERTISE_100HALF | ADVERTISE_100FULL |
-		     ADVERTISE_100BASE4))
-
-			bdp->cur_line_speed = 100;
-		else
-			bdp->cur_line_speed = 10;
-
-		/* Get duplex setting -- use priority resolution algorithm */
-		if (ad_reg & ADVERTISE_100BASE4) {
-			bdp->cur_dplx_mode = HALF_DUPLEX;
-		} else if (ad_reg & ADVERTISE_100FULL) {
-			bdp->cur_dplx_mode = FULL_DUPLEX;
-		} else if (ad_reg & ADVERTISE_100HALF) {
-			bdp->cur_dplx_mode = HALF_DUPLEX;
-		} else if (ad_reg & ADVERTISE_10FULL) {
-			bdp->cur_dplx_mode = FULL_DUPLEX;
-		} else {
-			bdp->cur_dplx_mode = HALF_DUPLEX;
-		}
-
-		return;
-	}
-
-	/* If we are connected to a dumb (non-NWAY) repeater or hub, and the
-	 * line speed was determined automatically by parallel detection, then
-	 * we have no way of knowing exactly what speed the PHY is set to
-	 * unless that PHY has a propietary register which indicates speed in
-	 * this situation. The NSC TX PHY does have such a register. Also,
-	 * since NWAY didn't establish the connection, the duplex setting
-	 * should HALF duplex. */
-	bdp->cur_dplx_mode = HALF_DUPLEX;
-
-	if (PhyId == PHY_NSC_TX) {
-		/* Read register 25 to get the SPEED_10 bit */
-		e100_mdi_read(bdp, NSC_SPEED_IND_REG, bdp->phy_addr, &misc_reg);
-
-		/* If bit 6 was set then we're at 10Mbps */
-		if (misc_reg & NSC_TX_SPD_INDC_SPEED)
-			bdp->cur_line_speed = 10;
-		else
-			bdp->cur_line_speed = 100;
-
-	} else {
-		/* If we don't know the line speed, default to 10Mbps */
-		bdp->cur_line_speed = 10;
-	}
-}
-
-/* 
- * Procedure: e100_force_speed_duplex
- *
- * Description: This routine forces line speed and duplex mode of the
- * adapter based on the values the user has set in e100.c.
- *
- * Arguments:  bdp - Pointer to the e100_private structure for the board
- *
- * Returns: void
- *
- */
-void
-e100_force_speed_duplex(struct e100_private *bdp)
-{
-	u16 control;
-	unsigned long expires;
-
-	bdp->flags |= DF_SPEED_FORCED;
-
-	e100_mdi_read(bdp, MII_BMCR, bdp->phy_addr, &control);
-	control &= ~BMCR_ANENABLE;
-	control &= ~BMCR_LOOPBACK;
-
-	switch (bdp->params.e100_speed_duplex) {
-	case E100_SPEED_10_HALF:
-		control &= ~BMCR_SPEED100;
-		control &= ~BMCR_FULLDPLX;
-		bdp->cur_line_speed = 10;
-		bdp->cur_dplx_mode = HALF_DUPLEX;
-		break;
-
-	case E100_SPEED_10_FULL:
-		control &= ~BMCR_SPEED100;
-		control |= BMCR_FULLDPLX;
-		bdp->cur_line_speed = 10;
-		bdp->cur_dplx_mode = FULL_DUPLEX;
-		break;
-
-	case E100_SPEED_100_HALF:
-		control |= BMCR_SPEED100;
-		control &= ~BMCR_FULLDPLX;
-		bdp->cur_line_speed = 100;
-		bdp->cur_dplx_mode = HALF_DUPLEX;
-		break;
-
-	case E100_SPEED_100_FULL:
-		control |= BMCR_SPEED100;
-		control |= BMCR_FULLDPLX;
-		bdp->cur_line_speed = 100;
-		bdp->cur_dplx_mode = FULL_DUPLEX;
-		break;
-	}
-
-	e100_mdi_write(bdp, MII_BMCR, bdp->phy_addr, control);
-
-	/* loop must run at least once */
-	expires = jiffies + 2 * HZ;
-	do {
-		if (e100_update_link_state(bdp) || 
-		    time_after(jiffies, expires)) {
-			break;
-		} else {
-			yield();
-		}
-
-	} while (true);
-}
-
-void
-e100_force_speed_duplex_to_phy(struct e100_private *bdp)
-{
-	u16 control;
-
-	e100_mdi_read(bdp, MII_BMCR, bdp->phy_addr, &control);
-	control &= ~BMCR_ANENABLE;
-	control &= ~BMCR_LOOPBACK;
-
-	switch (bdp->params.e100_speed_duplex) {
-	case E100_SPEED_10_HALF:
-		control &= ~BMCR_SPEED100;
-		control &= ~BMCR_FULLDPLX;
-		break;
-
-	case E100_SPEED_10_FULL:
-		control &= ~BMCR_SPEED100;
-		control |= BMCR_FULLDPLX;
-		break;
-
-	case E100_SPEED_100_HALF:
-		control |= BMCR_SPEED100;
-		control &= ~BMCR_FULLDPLX;
-		break;
-
-	case E100_SPEED_100_FULL:
-		control |= BMCR_SPEED100;
-		control |= BMCR_FULLDPLX;
-		break;
-	}
-
-	/* Send speed/duplex command to PHY layer. */
-	e100_mdi_write(bdp, MII_BMCR, bdp->phy_addr, control);
-}
-
-/* 
- * Procedure: e100_set_fc
- *
- * Description: Checks the link's capability for flow control.
- * 
- * Arguments:  bdp - Pointer to the e100_private structure for the board
- *		    
- * Returns: void
- *
- */
-static void
-e100_set_fc(struct e100_private *bdp)
-{
-	u16 ad_reg;
-	u16 lp_ad_reg;
-	u16 exp_reg;
-
-	/* no flow control for 82557, forced links or half duplex */
-	if (!netif_carrier_ok(bdp->device) || (bdp->flags & DF_SPEED_FORCED) ||
-	    (bdp->cur_dplx_mode == HALF_DUPLEX) ||
-	    !(bdp->flags & IS_BACHELOR)) {
-
-		bdp->flags &= ~DF_LINK_FC_CAP;
-		return;
-	}
-
-	/* See if link partner is capable of Auto-Negotiation (bit 0, reg 6) */
-	e100_mdi_read(bdp, MII_EXPANSION, bdp->phy_addr, &exp_reg);
-
-	if (exp_reg & EXPANSION_NWAY) {
-		/* Read our advertisement register */
-		e100_mdi_read(bdp, MII_ADVERTISE, bdp->phy_addr, &ad_reg);
-
-		/* Read our link partner's advertisement register */
-		e100_mdi_read(bdp, MII_LPA, bdp->phy_addr, &lp_ad_reg);
-
-		ad_reg &= lp_ad_reg;	/* AND the 2 ad registers */
-
-		if (ad_reg & NWAY_AD_FC_SUPPORTED)
-			bdp->flags |= DF_LINK_FC_CAP;
-		else
-			/* If link partner is capable of autoneg, but  */
-			/* not capable of flow control, Received PAUSE */
-			/* frames are still honored, i.e.,             */
-		        /* transmitted frames would be paused */
-			/* by incoming PAUSE frames           */
-			bdp->flags |= DF_LINK_FC_TX_ONLY;
-
-	} else {
-		bdp->flags &= ~DF_LINK_FC_CAP;
-	}
-}
-
-/* 
- * Procedure: e100_phy_check
- * 
- * Arguments:  bdp - Pointer to the e100_private structure for the board
- *
- * Returns: true if link state was changed
- *	   false otherwise
- *
- */
-unsigned char
-e100_phy_check(struct e100_private *bdp)
-{
-	unsigned char old_link;
-	unsigned char changed = false;
-
-	old_link = netif_carrier_ok(bdp->device) ? 1 : 0;
-	e100_find_speed_duplex(bdp);
-
-	if (!old_link && netif_carrier_ok(bdp->device)) {
-		e100_set_fc(bdp);
-		changed = true;
-	}
-
-	if (old_link && !netif_carrier_ok(bdp->device)) {
-		/* reset the zero lock state */
-		bdp->zlock_state = ZLOCK_INITIAL;
-
-		// set auto lock for phy auto-negotiation on link up
-		if ((bdp->PhyId & PHY_MODEL_REV_ID_MASK) == PHY_82555_TX)
-			e100_mdi_write(bdp, PHY_82555_MDI_EQUALIZER_CSR,
-				       bdp->phy_addr, 0);
-		changed = true;
-	}
-
-	e100_phy_fix_squelch(bdp);
-	e100_handle_zlock(bdp);
-
-	return changed;
-}
-
-/* 
- * Procedure:	e100_auto_neg
- *
- * Description: This routine will start autonegotiation and wait
- *		     for it to complete
- *
- * Arguments:
- *	bdp		- pointer to this card's e100_bdconfig structure
- *	force_restart	- defines if autoneg should be restarted even if it
- *			has been completed before
- * Returns:
- *	NOTHING
- */
-static void
-e100_auto_neg(struct e100_private *bdp, unsigned char force_restart)
-{
-	u16 stat_reg;
-	unsigned long expires;
-
-	bdp->flags &= ~DF_SPEED_FORCED;
-
-	e100_mdi_read(bdp, MII_BMSR, bdp->phy_addr, &stat_reg);
-	e100_mdi_read(bdp, MII_BMSR, bdp->phy_addr, &stat_reg);
-
-	/* if we are capable of performing autoneg then we restart if needed */
-	if ((stat_reg != 0xFFFF) && (stat_reg & BMSR_ANEGCAPABLE)) {
-
-		if ((!force_restart) &&
-		    (stat_reg & BMSR_ANEGCOMPLETE)) {
-			goto exit;
-		}
-
-		e100_mdi_write(bdp, MII_BMCR, bdp->phy_addr,
-			       BMCR_ANENABLE | BMCR_ANRESTART);
-
-		/* wait for autoneg to complete (up to 3 seconds) */
-		expires = jiffies + HZ * 3;
-		do {
-			/* now re-read the value. Sticky so read twice */
-			e100_mdi_read(bdp, MII_BMSR, bdp->phy_addr, &stat_reg);
-			e100_mdi_read(bdp, MII_BMSR, bdp->phy_addr, &stat_reg);
-
-			if ((stat_reg & BMSR_ANEGCOMPLETE) ||
-			    time_after(jiffies, expires) ) {
-				goto exit;
-			} else {
-				yield();
-			}
-		} while (true);
-	}
-
-exit:
-	e100_find_speed_duplex(bdp);
-}
-
-void
-e100_phy_set_speed_duplex(struct e100_private *bdp, unsigned char force_restart)
-{
-	if (bdp->params.e100_speed_duplex == E100_AUTONEG) {
-        	if (bdp->rev_id >= D102_REV_ID) 
-			/* Enable MDI/MDI-X auto switching */
-                	e100_mdi_write(bdp, MII_NCONFIG, bdp->phy_addr,
-		                       MDI_MDIX_AUTO_SWITCH_ENABLE);
-		e100_auto_neg(bdp, force_restart);
-
-	} else {
-        	if (bdp->rev_id >= D102_REV_ID) 
-			/* Disable MDI/MDI-X auto switching */
-                	e100_mdi_write(bdp, MII_NCONFIG, bdp->phy_addr,
-		                       MDI_MDIX_RESET_ALL_MASK);
-		e100_force_speed_duplex(bdp);
-	}
-
-	e100_set_fc(bdp);
-}
-
-void
-e100_phy_autoneg(struct e100_private *bdp)
-{
-	u16 ctrl_reg;
-
-	ctrl_reg = BMCR_ANENABLE | BMCR_ANRESTART | BMCR_RESET;
-
-	e100_mdi_write(bdp, MII_BMCR, bdp->phy_addr, ctrl_reg);
-
-	udelay(100);
-}
-
-void
-e100_phy_set_loopback(struct e100_private *bdp)
-{
-	u16 ctrl_reg;
-	ctrl_reg = BMCR_LOOPBACK;
-	e100_mdi_write(bdp, MII_BMCR, bdp->phy_addr, ctrl_reg);
-		udelay(100);
-}
-	
-void
-e100_phy_reset(struct e100_private *bdp)
-{
-	u16 ctrl_reg;
-	ctrl_reg = BMCR_RESET;
-	e100_mdi_write(bdp, MII_BMCR, bdp->phy_addr, ctrl_reg);
-	/* ieee 802.3 : The reset process shall be completed       */
-	/* within 0.5 seconds from the settting of PHY reset bit.  */
-	set_current_state(TASK_UNINTERRUPTIBLE);
-	schedule_timeout(HZ / 2);
-}
-
-unsigned char
-e100_phy_init(struct e100_private *bdp)
-{
-	e100_phy_reset(bdp);
-	e100_phy_address_detect(bdp);
-	e100_phy_isolate(bdp);
-	e100_phy_id_detect(bdp);
-
-	if (!e100_phy_specific_setup(bdp))
-		return false;
-
-	bdp->PhyState = 0;
-	bdp->PhyDelay = 0;
-	bdp->zlock_state = ZLOCK_INITIAL;
-
-	e100_phy_set_speed_duplex(bdp, false);
-	e100_fix_polarity(bdp);
-
-	return true;
-}
-
-/* 
- * Procedure: e100_get_link_state
- * 
- * Description: This routine checks the link status of the adapter
- *
- * Arguments:  bdp - Pointer to the e100_private structure for the board
- *		    
- *
- * Returns: true - If a link is found
- *		false - If there is no link
- *
- */
-unsigned char
-e100_get_link_state(struct e100_private *bdp)
-{
-	unsigned char link = false;
-	u16 status;
-
-	/* Check link status */
-	/* If the controller is a 82559 or later one, link status is available
-	 * from the CSR. This avoids the mdi_read. */
-	if (bdp->rev_id >= D101MA_REV_ID) {
-		if (readb(&bdp->scb->scb_ext.d101m_scb.scb_gen_stat) & BIT_0) {
-			link = true;
-		} else {
-			link = false;
-		}
-
-	} else {
-		/* Read the status register twice because of sticky bits */
-		e100_mdi_read(bdp, MII_BMSR, bdp->phy_addr, &status);
-		e100_mdi_read(bdp, MII_BMSR, bdp->phy_addr, &status);
-
-		if (status & BMSR_LSTATUS) {
-			link = true;
-		} else {
-			link = false;
-		}
-	}
-
-	return link;
-}
-
-/* 
- * Procedure: e100_update_link_state
- * 
- * Description: This routine updates the link status of the adapter,
- * 		also considering netif_running
- *
- * Arguments:  bdp - Pointer to the e100_private structure for the board
- *		    
- *
- * Returns: true - If a link is found
- *		false - If there is no link
- *
- */
-unsigned char
-e100_update_link_state(struct e100_private *bdp)
-{
-	unsigned char link;
-
-	/* Logical AND PHY link & netif_running */
-	link = e100_get_link_state(bdp) && netif_running(bdp->device);
-
-	if (link) {
-		if (!netif_carrier_ok(bdp->device))
-			netif_carrier_on(bdp->device);
-	} else {
-		if (netif_carrier_ok(bdp->device))
-			netif_carrier_off(bdp->device);
-	}
-
-	return link;
-}
-
-/**************************************************************************\
- **
- ** PROC NAME:     e100_handle_zlock
- **    This function manages a state machine that controls
- **    the driver's zero locking algorithm.
- **    This function is called by e100_watchdog() every ~2 second.
- ** States:
- **    The current link handling state is stored in 
- **    bdp->zlock_state, and is one of:
- **    ZLOCK_INITIAL, ZLOCK_READING, ZLOCK_SLEEPING
- **    Detailed description of the states and the transitions
- **    between states is found below.
- **    Note that any time the link is down / there is a reset
- **    state will be changed outside this function to ZLOCK_INITIAL
- ** Algorithm:
- **    1. If link is up & 100 Mbps continue else stay in #1:
- **    2. Set 'auto lock'
- **    3. Read & Store 100 times 'Zero' locked in 1 sec interval
- **    4. If max zero read >= 0xB continue else goto 1
- **    5. Set most popular 'Zero' read in #3
- **    6. Sleep 5 minutes
- **    7. Read number of errors, if it is > 300 goto 2 else goto 6
- ** Data Structures (in DRIVER_DATA):
- **    zlock_state           - current state of the algorithm
- **    zlock_read_cnt        - counts number of reads (up to 100)
- **    zlock_read_data[i]    - counts number of times 'Zero' read was i, 0 <= i <= 15
- **    zlock_sleep_cnt       - keeps track of "sleep" time (up to 300 secs = 5 minutes)
- **                                
- ** Parameters:    DRIVER_DATA    *bdp
- **
- **                bdp  - Pointer to HSM's adapter data space
- **
- ** Return Value:  NONE
- **
- ** See Also:      e100_watchdog()
- **
- \**************************************************************************/
-void
-e100_handle_zlock(struct e100_private *bdp)
-{
-	u16 pos;
-	u16 eq_reg;
-	u16 err_cnt;
-	u8 mpz;			/* Most Popular Zero */
-
-	switch (bdp->zlock_state) {
-	case ZLOCK_INITIAL:
-
-		if (((u8) bdp->rev_id <= D102_REV_ID) ||
-		    !(bdp->cur_line_speed == 100) ||
-		    !netif_carrier_ok(bdp->device)) {
-			break;
-		}
-
-		/* initialize hw and sw and start reading */
-		e100_mdi_write(bdp, PHY_82555_MDI_EQUALIZER_CSR,
-			       bdp->phy_addr, 0);
-		/* reset read counters: */
-		bdp->zlock_read_cnt = 0;
-		for (pos = 0; pos < 16; pos++)
-			bdp->zlock_read_data[pos] = 0;
-		/* start reading in the next call back: */
-		bdp->zlock_state = ZLOCK_READING;
-
-		/* FALL THROUGH !! */
-
-	case ZLOCK_READING:
-		/* state: reading (100 times) zero locked in 1 sec interval
-		 * prev states: ZLOCK_INITIAL
-		 * next states: ZLOCK_INITIAL, ZLOCK_SLEEPING */
-
-		e100_mdi_read(bdp, PHY_82555_MDI_EQUALIZER_CSR,
-			      bdp->phy_addr, &eq_reg);
-		pos = (eq_reg & ZLOCK_ZERO_MASK) >> 4;
-		bdp->zlock_read_data[pos]++;
-		bdp->zlock_read_cnt++;
-
-		if (bdp->zlock_read_cnt == ZLOCK_MAX_READS) {
-			/* check if we read a 'Zero' value of 0xB or greater */
-			if ((bdp->zlock_read_data[0xB]) ||
-			    (bdp->zlock_read_data[0xC]) ||
-			    (bdp->zlock_read_data[0xD]) ||
-			    (bdp->zlock_read_data[0xE]) ||
-			    (bdp->zlock_read_data[0xF])) {
-
-				/* we've read 'Zero' value of 0xB or greater,
-				 * find most popular 'Zero' value and lock it */
-				mpz = 0;
-				/* this loop finds the most popular 'Zero': */
-				for (pos = 1; pos < 16; pos++) {
-					if (bdp->zlock_read_data[pos] >
-					    bdp->zlock_read_data[mpz])
-
-						mpz = pos;
-				}
-				/* now lock the most popular 'Zero': */
-				eq_reg = (ZLOCK_SET_ZERO | mpz);
-				e100_mdi_write(bdp,
-					       PHY_82555_MDI_EQUALIZER_CSR,
-					       bdp->phy_addr, eq_reg);
-
-				/* sleep for 5 minutes: */
-				bdp->zlock_sleep_cnt = jiffies;
-				bdp->zlock_state = ZLOCK_SLEEPING;
-				/* we will be reading the # of errors after 5
-				 * minutes, so we need to reset the error
-				 * counters - these registers are self clearing
-				 * on read, so read them */
-				e100_mdi_read(bdp, PHY_82555_SYMBOL_ERR,
-					      bdp->phy_addr, &err_cnt);
-
-			} else {
-				/* we did not read a 'Zero' value of 0xB or
-				 * above. go back to the start */
-				bdp->zlock_state = ZLOCK_INITIAL;
-			}
-
-		}
-		break;
-
-	case ZLOCK_SLEEPING:
-		/* state: sleeping for 5 minutes
-		 * prev states: ZLOCK_READING
-		 * next states: ZLOCK_READING, ZLOCK_SLEEPING */
-
-		/* if 5 minutes have passed: */
-		if ((jiffies - bdp->zlock_sleep_cnt) >= ZLOCK_MAX_SLEEP) {
-			/* read and sum up the number of errors:  */
-			e100_mdi_read(bdp, PHY_82555_SYMBOL_ERR,
-				      bdp->phy_addr, &err_cnt);
-			/* if we've more than 300 errors (this number was
-			 * calculated according to the spec max allowed errors
-			 * (80 errors per 1 million frames) for 5 minutes in
-			 * 100 Mbps (or the user specified max BER number) */
-			if (err_cnt > bdp->params.ber) {
-				/* start again in the next callback: */
-				bdp->zlock_state = ZLOCK_INITIAL;
-			} else {
-				/* we don't have more errors than allowed,
-				 * sleep for 5 minutes */
-				bdp->zlock_sleep_cnt = jiffies;
-			}
-		}
-		break;
-
-	default:
-		break;
-	}
-}
--- diff/drivers/net/e100/e100_phy.h	2003-05-21 11:49:55.000000000 +0100
+++ source/drivers/net/e100/e100_phy.h	1970-01-01 01:00:00.000000000 +0100
@@ -1,158 +0,0 @@
-/*******************************************************************************
-
-  
-  Copyright(c) 1999 - 2003 Intel Corporation. All rights reserved.
-  
-  This program is free software; you can redistribute it and/or modify it 
-  under the terms of the GNU General Public License as published by the Free 
-  Software Foundation; either version 2 of the License, or (at your option) 
-  any later version.
-  
-  This program is distributed in the hope that it will be useful, but WITHOUT 
-  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 
-  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for 
-  more details.
-  
-  You should have received a copy of the GNU General Public License along with
-  this program; if not, write to the Free Software Foundation, Inc., 59 
-  Temple Place - Suite 330, Boston, MA  02111-1307, USA.
-  
-  The full GNU General Public License is included in this distribution in the
-  file called LICENSE.
-  
-  Contact Information:
-  Linux NICS <linux.nics@intel.com>
-  Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
-*******************************************************************************/
-
-#ifndef _E100_PHY_INC_
-#define _E100_PHY_INC_
-
-#include "e100.h"
-
-/*
- * Auto-polarity enable/disable
- * e100_autopolarity = 0 => disable auto-polarity
- * e100_autopolarity = 1 => enable auto-polarity
- * e100_autopolarity = 2 => let software determine
- */
-#define E100_AUTOPOLARITY 2
-
-#define IS_NC3133(bdp) (((bdp)->pdev->subsystem_vendor == 0x0E11) && \
-                        ((bdp)->pdev->subsystem_device == 0xB0E1))
-
-#define PHY_503                 0
-#define PHY_100_A               0x000003E0
-#define PHY_100_C               0x035002A8
-#define PHY_NSC_TX              0x5c002000
-#define PHY_82562ET             0x033002A8
-#define PHY_82562EM             0x032002A8
-#define PHY_82562EH             0x017002A8
-#define PHY_82555_TX            0x015002a8	/* added this for 82555 */
-#define PHY_OTHER               0xFFFF
-#define MAX_PHY_ADDR            31
-#define MIN_PHY_ADDR            0
-
-#define PHY_MODEL_REV_ID_MASK   0xFFF0FFFF
-
-#define PHY_DEFAULT_ADDRESS 1
-#define PHY_ADDRESS_503 32
-
-/* MDI Control register bit definitions */
-#define MDI_PHY_READY	    BIT_28	/* PHY is ready for next MDI cycle */
-
-#define MDI_NC3133_CONFIG_REG           0x19
-#define MDI_NC3133_100FX_ENABLE         BIT_2
-#define MDI_NC3133_INT_ENABLE_REG       0x17
-#define MDI_NC3133_INT_ENABLE           BIT_1
-
-/* MDI Control register opcode definitions */
-#define MDI_WRITE 1		/* Phy Write */
-#define MDI_READ  2		/* Phy read */
-
-/* MDI register set*/
-#define AUTO_NEG_NEXT_PAGE_REG	    0x07	/* Auto-negotiation next page xmit */
-#define EXTENDED_REG_0		    0x10	/* Extended reg 0 (Phy 100 modes) */
-#define EXTENDED_REG_1		    0x14	/* Extended reg 1 (Phy 100 error indications) */
-#define NSC_CONG_CONTROL_REG	    0x17	/* National (TX) congestion control */
-#define NSC_SPEED_IND_REG	    0x19	/* National (TX) speed indication */
-
-#define HWI_CONTROL_REG             0x1D	/* HWI Control register */
-/* MDI/MDI-X Control Register bit definitions */
-#define MDI_MDIX_RES_TIMER          BIT_0_3	/* minimum slot time for resolution timer */
-#define MDI_MDIX_CONFIG_IS_OK       BIT_4	/* 1 = resolution algorithm completes OK */
-#define MDI_MDIX_STATUS             BIT_5	/* 1 = MDIX (croos over), 0 = MDI (straight through) */
-#define MDI_MDIX_SWITCH             BIT_6	/* 1 = Forces to MDIX, 0 = Forces to MDI */
-#define MDI_MDIX_AUTO_SWITCH_ENABLE BIT_7	/* 1 = MDI/MDI-X feature enabled */
-#define MDI_MDIX_CONCT_CONFIG       BIT_8	/* Sets the MDI/MDI-X connectivity configuration (test prupose only) */
-#define MDI_MDIX_CONCT_TEST_ENABLE  BIT_9	/* 1 = Enables connectivity testing */
-#define MDI_MDIX_RESET_ALL_MASK     0x0000
-
-/* HWI Control Register bit definitions */
-#define HWI_TEST_DISTANCE           BIT_0_8	/* distance to cable problem */
-#define HWI_TEST_HIGHZ_PROBLEM      BIT_9	/* 1 = Open Circuit */
-#define HWI_TEST_LOWZ_PROBLEM       BIT_10	/* 1 = Short Circuit */
-#define HWI_TEST_RESERVED           (BIT_11 | BIT_12)	/* reserved */
-#define HWI_TEST_EXECUTE            BIT_13	/* 1 = Execute the HWI test on the PHY */
-#define HWI_TEST_ABILITY            BIT_14	/* 1 = test passed */
-#define HWI_TEST_ENABLE             BIT_15	/* 1 = Enables the HWI feature */
-#define HWI_RESET_ALL_MASK          0x0000
-
-/* ############Start of 82555 specific defines################## */
-
-/* Intel 82555 specific registers */
-#define PHY_82555_CSR		    0x10	/* 82555 CSR */
-#define PHY_82555_SPECIAL_CONTROL   0x11	/* 82555 special control register */
-
-#define PHY_82555_RCV_ERR	    0x15	/* 82555 100BaseTx Receive Error
-						 * Frame Counter */
-#define PHY_82555_SYMBOL_ERR	    0x16	/* 82555 RCV Symbol Error Counter */
-#define PHY_82555_PREM_EOF_ERR	    0x17	/* 82555 100BaseTx RCV Premature End
-						 * of Frame Error Counter */
-#define PHY_82555_EOF_COUNTER	    0x18	/* 82555 end of frame error counter */
-#define PHY_82555_MDI_EQUALIZER_CSR 0x1a	/* 82555 specific equalizer reg. */
-
-/* 82555 CSR bits */
-#define PHY_82555_SPEED_BIT    BIT_1
-#define PHY_82555_POLARITY_BIT BIT_8
-
-/* 82555 equalizer reg. opcodes */
-#define ENABLE_ZERO_FORCING  0x2010	/* write to ASD conf. reg. 0 */
-#define DISABLE_ZERO_FORCING 0x2000	/* write to ASD conf. reg. 0 */
-
-/* 82555 special control reg. opcodes */
-#define DISABLE_AUTO_POLARITY 0x0010
-#define EXTENDED_SQUELCH_BIT  BIT_2
-
-/* ############End of 82555 specific defines##################### */
-
-/* Auto-Negotiation advertisement register bit definitions*/
-#define NWAY_AD_FC_SUPPORTED    0x0400	/* Flow Control supported */
-
-/* Auto-Negotiation link partner ability register bit definitions*/
-#define NWAY_LP_ABILITY	        0x07e0	/* technologies supported */
-
-/* PHY 100 Extended Register 0 bit definitions*/
-#define PHY_100_ER0_FDX_INDIC	BIT_0	/* 1 = FDX, 0 = half duplex */
-#define PHY_100_ER0_SPEED_INDIC BIT_1	/* 1 = 100Mbps, 0= 10Mbps */
-
-/* National Semiconductor TX phy congestion control register bit definitions*/
-#define NSC_TX_CONG_TXREADY  BIT_10	/* Makes TxReady an input */
-#define NSC_TX_CONG_ENABLE   BIT_8	/* Enables congestion control */
-
-/* National Semiconductor TX phy speed indication register bit definitions*/
-#define NSC_TX_SPD_INDC_SPEED BIT_6	/* 0 = 100Mbps, 1=10Mbps */
-
-/************* function prototypes ************/
-extern unsigned char e100_phy_init(struct e100_private *bdp);
-extern unsigned char e100_update_link_state(struct e100_private *bdp);
-extern unsigned char e100_phy_check(struct e100_private *bdp);
-extern void e100_phy_set_speed_duplex(struct e100_private *bdp,
-				      unsigned char force_restart);
-extern void e100_phy_autoneg(struct e100_private *bdp);
-extern void e100_phy_reset(struct e100_private *bdp);
-extern void e100_phy_set_loopback(struct e100_private *bdp);
-extern int e100_mdi_write(struct e100_private *, u32, u32, u16);
-extern int e100_mdi_read(struct e100_private *, u32, u32, u16 *);
-
-#endif
--- diff/drivers/net/e100/e100_test.c	2003-06-09 14:18:19.000000000 +0100
+++ source/drivers/net/e100/e100_test.c	1970-01-01 01:00:00.000000000 +0100
@@ -1,500 +0,0 @@
-/*******************************************************************************
-
-  
-  Copyright(c) 1999 - 2003 Intel Corporation. All rights reserved.
-  
-  This program is free software; you can redistribute it and/or modify it 
-  under the terms of the GNU General Public License as published by the Free 
-  Software Foundation; either version 2 of the License, or (at your option) 
-  any later version.
-  
-  This program is distributed in the hope that it will be useful, but WITHOUT 
-  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 
-  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for 
-  more details.
-  
-  You should have received a copy of the GNU General Public License along with
-  this program; if not, write to the Free Software Foundation, Inc., 59 
-  Temple Place - Suite 330, Boston, MA  02111-1307, USA.
-  
-  The full GNU General Public License is included in this distribution in the
-  file called LICENSE.
-  
-  Contact Information:
-  Linux NICS <linux.nics@intel.com>
-  Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
-*******************************************************************************/
-
-#include "e100_phy.h"
-#include "e100_config.h"
-
-extern u16 e100_eeprom_read(struct e100_private *, u16);
-extern int e100_wait_exec_cmplx(struct e100_private *, u32,u8, u8);
-extern void e100_phy_reset(struct e100_private *bdp);
-extern void e100_phy_autoneg(struct e100_private *bdp);
-extern void e100_phy_set_loopback(struct e100_private *bdp);
-extern void e100_force_speed_duplex(struct e100_private *bdp);
-
-static u8 e100_diag_selftest(struct net_device *);
-static u8 e100_diag_eeprom(struct net_device *);
-static u8 e100_diag_loopback(struct net_device *);
-
-static u8 e100_diag_one_loopback (struct net_device *, u8);
-static u8 e100_diag_rcv_loopback_pkt(struct e100_private *);
-static void e100_diag_config_loopback(struct e100_private *, u8, u8, u8 *,u8 *);
-static u8 e100_diag_loopback_alloc(struct e100_private *);
-static void e100_diag_loopback_cu_ru_exec(struct e100_private *);
-static u8 e100_diag_check_pkt(u8 *);
-static void e100_diag_loopback_free(struct e100_private *);
-static int e100_cable_diag(struct e100_private *bdp);
-
-#define LB_PACKET_SIZE 1500
-
-/**
- * e100_run_diag - main test execution handler - checks mask of requests and calls the diag routines  
- * @dev: atapter's net device data struct
- * @test_info: array with test request mask also used to store test results
- *
- * RETURNS: updated flags field of struct ethtool_test
- */
-u32
-e100_run_diag(struct net_device *dev, u64 *test_info, u32 flags)
-{
-	struct e100_private* bdp = dev->priv;
-	u8 test_result = 0;
-
-	if (!e100_get_link_state(bdp)) {
-		test_result = ETH_TEST_FL_FAILED;
-		test_info[test_link] = true;
-	}
-	if (!e100_diag_eeprom(dev)) {
-		test_result = ETH_TEST_FL_FAILED;
-		test_info[test_eeprom] = true;
-	}
-	if (flags & ETH_TEST_FL_OFFLINE) {
-		u8 fail_mask;
-		if (netif_running(dev)) {
-			spin_lock_bh(&dev->xmit_lock);
-			e100_close(dev);
-			spin_unlock_bh(&dev->xmit_lock);
-		}
-		if (e100_diag_selftest(dev)) {
-			test_result = ETH_TEST_FL_FAILED;
-			test_info[test_self_test] = true;
-		}
-
-		fail_mask = e100_diag_loopback(dev);
-		if (fail_mask) {
-			test_result = ETH_TEST_FL_FAILED;
-			if (fail_mask & PHY_LOOPBACK)
-				test_info[test_loopback_phy] = true;
-			if (fail_mask & MAC_LOOPBACK)
-				test_info[test_loopback_mac] = true;
-		}
-
-		test_info[cable_diag] = e100_cable_diag(bdp);
-		/* Need hw init regardless of netif_running */
-		e100_hw_init(bdp);
-		if (netif_running(dev)) {
-			e100_open(dev);
-		}
-	}
-	else {
-		test_info[test_self_test] = false;
-		test_info[test_loopback_phy] = false;
-		test_info[test_loopback_mac] = false;
-		test_info[cable_diag] = false;
-	}
-
-	return flags | test_result;
-}
-
-/**
- * e100_diag_selftest - run hardware selftest 
- * @dev: atapter's net device data struct
- */
-static u8
-e100_diag_selftest(struct net_device *dev)
-{
-	struct e100_private *bdp = dev->priv;
-	u32 st_timeout, st_result;
-	u8 retval = 0;
-
-	if (!e100_selftest(bdp, &st_timeout, &st_result)) {
-		if (!st_timeout) {
-			if (st_result & CB_SELFTEST_REGISTER_BIT)
-				retval |= REGISTER_TEST_FAIL;
-			if (st_result & CB_SELFTEST_DIAG_BIT)
-				retval |= SELF_TEST_FAIL;
-			if (st_result & CB_SELFTEST_ROM_BIT)
-				retval |= ROM_TEST_FAIL;
-		} else {
-            		retval = TEST_TIMEOUT;
-		}
-	}
-
-	return retval;
-}
-
-/**
- * e100_diag_eeprom - validate eeprom checksum correctness
- * @dev: atapter's net device data struct
- *
- */
-static u8
-e100_diag_eeprom (struct net_device *dev)
-{
-	struct e100_private *bdp = dev->priv;
-	u16 i, eeprom_sum, eeprom_actual_csm;
-
-	for (i = 0, eeprom_sum = 0; i < (bdp->eeprom_size - 1); i++) {
-		eeprom_sum += e100_eeprom_read(bdp, i);
-	}
-
-	eeprom_actual_csm = e100_eeprom_read(bdp, bdp->eeprom_size - 1);
-
-	if (eeprom_actual_csm == (u16)(EEPROM_SUM - eeprom_sum)) {
-		return true;
-	}
-
-	return false;
-}
-
-/**
- * e100_diag_loopback - performs loopback test  
- * @dev: atapter's net device data struct
- */
-static u8
-e100_diag_loopback (struct net_device *dev)
-{
-	u8 rc = 0;
-
-	printk(KERN_DEBUG "%s: PHY loopback test starts\n", dev->name);
-	e100_hw_init(dev->priv);
-	if (!e100_diag_one_loopback(dev, PHY_LOOPBACK)) {
-		rc |= PHY_LOOPBACK;
-	}
-	printk(KERN_DEBUG "%s: PHY loopback test ends\n", dev->name);
-
-	printk(KERN_DEBUG "%s: MAC loopback test starts\n", dev->name);
-	e100_hw_init(dev->priv);
-	if (!e100_diag_one_loopback(dev, MAC_LOOPBACK)) {
-		rc |= MAC_LOOPBACK;
-	}
-	printk(KERN_DEBUG "%s: MAC loopback test ends\n", dev->name);
-
-	return rc;
-}
-
-/**
- * e100_diag_loopback - performs loopback test  
- * @dev: atapter's net device data struct
- * @mode: lopback test type
- */
-static u8
-e100_diag_one_loopback (struct net_device *dev, u8 mode)
-{
-        struct e100_private *bdp = dev->priv;
-        u8 res = false;
-   	u8 saved_dynamic_tbd = false;
-   	u8 saved_extended_tcb = false;
-
-	if (!e100_diag_loopback_alloc(bdp))
-		return false;
-
-	/* change the config block to standard tcb and the correct loopback */
-        e100_diag_config_loopback(bdp, true, mode,
-				  &saved_extended_tcb, &saved_dynamic_tbd);
-
-	e100_diag_loopback_cu_ru_exec(bdp);
-
-        if (e100_diag_rcv_loopback_pkt(bdp)) {
-		res = true;
-	}
-
-        e100_diag_loopback_free(bdp);
-
-        /* change the config block to previous tcb mode and the no loopback */
-        e100_diag_config_loopback(bdp, false, mode,
-				  &saved_extended_tcb, &saved_dynamic_tbd);
-	return res;
-}
-
-/**
- * e100_diag_config_loopback - setup/clear loopback before/after lpbk test
- * @bdp: atapter's private data struct
- * @set_loopback: true if the function is called to set lb
- * @loopback_mode: the loopback mode(MAC or PHY)
- * @tcb_extended: true if need to set extended tcb mode after clean loopback
- * @dynamic_tbd: true if needed to set dynamic tbd mode after clean loopback
- *
- */
-void
-e100_diag_config_loopback(struct e100_private* bdp,
-			  u8 set_loopback,
-			  u8 loopback_mode,
-			  u8* tcb_extended,
-			  u8* dynamic_tbd)
-{
-	/* if set_loopback == true - we want to clear tcb_extended/dynamic_tbd.
-	 * the previous values are saved in the params tcb_extended/dynamic_tbd
-	 * if set_loopback == false - we want to restore previous value.
-	 */
-	if (set_loopback || (*tcb_extended))
-		  *tcb_extended = e100_config_tcb_ext_enable(bdp,*tcb_extended);
-
-	if (set_loopback || (*dynamic_tbd))
-		 *dynamic_tbd = e100_config_dynamic_tbd(bdp,*dynamic_tbd);
-
-	if (set_loopback) {
-		/* ICH PHY loopback is broken */
-		if (bdp->flags & IS_ICH && loopback_mode == PHY_LOOPBACK)
-			loopback_mode = MAC_LOOPBACK;
-		/* Configure loopback on MAC */
-		e100_config_loopback_mode(bdp,loopback_mode);
-	} else {
-		e100_config_loopback_mode(bdp,NO_LOOPBACK);
-	}
-
-	e100_config(bdp);
-
-	if (loopback_mode == PHY_LOOPBACK) {
-		if (set_loopback)
-                        /* Set PHY loopback mode */
-                        e100_phy_set_loopback(bdp);
-		else
-			/* Reset PHY loopback mode */
-			e100_phy_reset(bdp);	
-		/* Wait for PHY state change */
-		set_current_state(TASK_UNINTERRUPTIBLE);
-                schedule_timeout(HZ);
-	} else { /* For MAC loopback wait 500 msec to take effect */
-		set_current_state(TASK_UNINTERRUPTIBLE);
-		schedule_timeout(HZ / 2);
-	}
-}
-  
-/**
- * e100_diag_loopback_alloc - alloc & initate tcb and rfd for the loopback
- * @bdp: atapter's private data struct
- *
- */
-static u8
-e100_diag_loopback_alloc(struct e100_private *bdp)
-{
-	dma_addr_t dma_handle;
-	tcb_t *tcb;
-	rfd_t *rfd;
-	tbd_t *tbd;
-
-	/* tcb, tbd and transmit buffer are allocated */
-	tcb = pci_alloc_consistent(bdp->pdev,
-				   (sizeof (tcb_t) + sizeof (tbd_t) +
-				    LB_PACKET_SIZE),
-				   &dma_handle);
-        if (tcb == NULL)
-		return false;
-
-	memset(tcb, 0x00, sizeof (tcb_t) + sizeof (tbd_t) + LB_PACKET_SIZE);
-	tcb->tcb_phys = dma_handle;
-	tcb->tcb_hdr.cb_status = 0;
-	tcb->tcb_hdr.cb_cmd =
-		cpu_to_le16(CB_EL_BIT | CB_TRANSMIT | CB_TX_SF_BIT);
-	/* Next command is null */
-	tcb->tcb_hdr.cb_lnk_ptr = cpu_to_le32(0xffffffff);
-	tcb->tcb_cnt = 0;
-	tcb->tcb_thrshld = bdp->tx_thld;
-	tcb->tcb_tbd_num = 1;
-	/* Set up tcb tbd pointer */
-	tcb->tcb_tbd_ptr = cpu_to_le32(tcb->tcb_phys + sizeof (tcb_t));
-	tbd = (tbd_t *) ((u8 *) tcb + sizeof (tcb_t));
-	/* Set up tbd transmit buffer */
-	tbd->tbd_buf_addr =
-		cpu_to_le32(le32_to_cpu(tcb->tcb_tbd_ptr) + sizeof (tbd_t));
-	tbd->tbd_buf_cnt = __constant_cpu_to_le16(1024);
-	/* The value of first 512 bytes is FF */
-	memset((void *) ((u8 *) tbd + sizeof (tbd_t)), 0xFF, 512);
-	/* The value of second 512 bytes is BA */
-	memset((void *) ((u8 *) tbd + sizeof (tbd_t) + 512), 0xBA, 512);
-	wmb();
-	rfd = pci_alloc_consistent(bdp->pdev, sizeof (rfd_t), &dma_handle);
-
-	if (rfd == NULL) {
-		pci_free_consistent(bdp->pdev,
-				    sizeof (tcb_t) + sizeof (tbd_t) +
-				    LB_PACKET_SIZE, tcb, tcb->tcb_phys);
-		return false;
-	}
-
-	memset(rfd, 0x00, sizeof (rfd_t));
-
-	/* init all fields in rfd */
-	rfd->rfd_header.cb_cmd = cpu_to_le16(RFD_EL_BIT);
-	rfd->rfd_sz = cpu_to_le16(ETH_FRAME_LEN + CHKSUM_SIZE);
-	/* dma_handle is physical address of rfd */
-	bdp->loopback.dma_handle = dma_handle;
-	bdp->loopback.tcb = tcb;
-	bdp->loopback.rfd = rfd;
-	wmb();
-	return true;
-}
-
-/**
- * e100_diag_loopback_cu_ru_exec - activates cu and ru to send & receive the pkt
- * @bdp: atapter's private data struct
- *
- */
-static void
-e100_diag_loopback_cu_ru_exec(struct e100_private *bdp)
-{
-	/*load CU & RU base */ 
-	if(!e100_wait_exec_cmplx(bdp, bdp->loopback.dma_handle, SCB_RUC_START, 0))
-		printk(KERN_ERR "e100: SCB_RUC_START failed!\n");
-
-	bdp->next_cu_cmd = START_WAIT;
-	e100_start_cu(bdp, bdp->loopback.tcb);
-	bdp->last_tcb = NULL;
-	rmb();
-}
-/**
- * e100_diag_check_pkt - checks if a given packet is a loopback packet
- * @bdp: atapter's private data struct
- *
- * Returns true if OK false otherwise.
- */
-static u8
-e100_diag_check_pkt(u8 *datap)
-{
-	int i;
-	for (i = 0; i<512; i++) {
-		if( !((*datap)==0xFF && (*(datap + 512) == 0xBA)) ) {
-			printk (KERN_ERR "e100: check loopback packet failed at: %x\n", i);
-			return false;
-			}
-	}
-	printk (KERN_DEBUG "e100: Check received loopback packet OK\n");
-	return true;
-}
-
-/**
- * e100_diag_rcv_loopback_pkt - waits for receive and checks lpbk packet
- * @bdp: atapter's private data struct
- *
- * Returns true if OK false otherwise.
- */
-static u8
-e100_diag_rcv_loopback_pkt(struct e100_private* bdp) 
-{    
-	rfd_t *rfdp;
-	u16 rfd_status;
-	unsigned long expires = jiffies + HZ * 2;
-
-        rfdp =bdp->loopback.rfd;
-
-        rfd_status = le16_to_cpu(rfdp->rfd_header.cb_status);
-
-        while (!(rfd_status & RFD_STATUS_COMPLETE)) { 
-		if (time_before(jiffies, expires)) {
-			yield();
-			rmb();
-			rfd_status = le16_to_cpu(rfdp->rfd_header.cb_status);
-		} else {
-			break;
-		}
-        }
-
-        if (rfd_status & RFD_STATUS_COMPLETE) {
-		printk(KERN_DEBUG "e100: Loopback packet received\n");
-                return e100_diag_check_pkt(((u8 *)rfdp+bdp->rfd_size));
-	}
-	else {
-		printk(KERN_ERR "e100: Loopback packet not received\n");
-		return false;
-	}
-}
-
-/**
- * e100_diag_loopback_free - free data allocated for loopback pkt send/receive
- * @bdp: atapter's private data struct
- *
- */
-static void
-e100_diag_loopback_free (struct e100_private *bdp)
-{
-        pci_free_consistent(bdp->pdev,
-			    sizeof(tcb_t) + sizeof(tbd_t) + LB_PACKET_SIZE,
-			    bdp->loopback.tcb, bdp->loopback.tcb->tcb_phys);
-
-        pci_free_consistent(bdp->pdev, sizeof(rfd_t), bdp->loopback.rfd,
-			    bdp->loopback.dma_handle);
-}
-
-static int
-e100_cable_diag(struct e100_private *bdp)
-{	
-	int saved_open_circut = 0xffff;
-	int saved_short_circut = 0xffff;
-	int saved_distance = 0xffff;
-	int saved_same = 0;
-	int cable_status = E100_CABLE_UNKNOWN;
-	int i;
-	
-	/* If we have link, */	
-	if (e100_get_link_state(bdp))
-		return E100_CABLE_OK;
-	
-	if (bdp->rev_id < D102_REV_ID)
-		return E100_CABLE_UNKNOWN;
-
-	/* Disable MDI/MDI-X auto switching */
-        e100_mdi_write(bdp, MII_NCONFIG, bdp->phy_addr,
-		MDI_MDIX_RESET_ALL_MASK);
-	/* Set to 100 Full as required by cable test */
-	e100_mdi_write(bdp, MII_BMCR, bdp->phy_addr,
-		BMCR_SPEED100 | BMCR_FULLDPLX);
-
-	/* Test up to 100 times */
-	for (i = 0; i < 100; i++) {
-		u16 ctrl_reg;
-		int distance, open_circut, short_circut, near_end;
-
-		/* Enable and execute cable test */
-		e100_mdi_write(bdp, HWI_CONTROL_REG, bdp->phy_addr,
-			(HWI_TEST_ENABLE | HWI_TEST_EXECUTE));
-		/* Wait for cable test finished */
-		set_current_state(TASK_UNINTERRUPTIBLE);
-		schedule_timeout(HZ/100 + 1);
-		/* Read results */
-		e100_mdi_read(bdp, HWI_CONTROL_REG, bdp->phy_addr, &ctrl_reg);
-		distance = ctrl_reg & HWI_TEST_DISTANCE;
-		open_circut = ctrl_reg & HWI_TEST_HIGHZ_PROBLEM;
-		short_circut = ctrl_reg & HWI_TEST_LOWZ_PROBLEM;
-
-		if ((distance == saved_distance) &&
-	    	    (open_circut == saved_open_circut) &&
-	    	    (short_circut == saved_short_circut)) 
-			saved_same++;
-		else {
-			saved_same = 0;
-			saved_distance = distance;
-			saved_open_circut = open_circut;
-			saved_short_circut = short_circut;
-		}
-		/* If results are the same 3 times */
-		if (saved_same == 3) {
-			near_end = ((distance * HWI_REGISTER_GRANULARITY) <
-			       HWI_NEAR_END_BOUNDARY);
-			if (open_circut)
-				cable_status = (near_end) ? 
-					E100_CABLE_OPEN_NEAR : E100_CABLE_OPEN_FAR;
-			if (short_circut)
-				cable_status = (near_end) ?
-					E100_CABLE_SHORT_NEAR : E100_CABLE_SHORT_FAR;
-			break;
-		}
-	}
-	/* Reset cable test */
-        e100_mdi_write(bdp, HWI_CONTROL_REG, bdp->phy_addr,					       HWI_RESET_ALL_MASK);
-	return cable_status;
-}
-
--- diff/drivers/net/e100/e100_ucode.h	2003-05-21 11:49:55.000000000 +0100
+++ source/drivers/net/e100/e100_ucode.h	1970-01-01 01:00:00.000000000 +0100
@@ -1,365 +0,0 @@
-/*******************************************************************************
-
-  
-  Copyright(c) 1999 - 2003 Intel Corporation. All rights reserved.
-  
-  This program is free software; you can redistribute it and/or modify it 
-  under the terms of the GNU General Public License as published by the Free 
-  Software Foundation; either version 2 of the License, or (at your option) 
-  any later version.
-  
-  This program is distributed in the hope that it will be useful, but WITHOUT 
-  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 
-  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for 
-  more details.
-  
-  You should have received a copy of the GNU General Public License along with
-  this program; if not, write to the Free Software Foundation, Inc., 59 
-  Temple Place - Suite 330, Boston, MA  02111-1307, USA.
-  
-  The full GNU General Public License is included in this distribution in the
-  file called LICENSE.
-  
-  Contact Information:
-  Linux NICS <linux.nics@intel.com>
-  Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
-*******************************************************************************/
-
-#ifndef _E100_UCODE_H_
-#define _E100_UCODE_H_
-
-/*
-e100_ucode.h
-
-This file contains the loadable micro code arrays to implement receive 
-bundling on the D101 A-step, D101 B-step, D101M (B-step only), D101S, 
-D102 B-step, D102 B-step with TCO work around and D102 C-step.
-
-Each controller has its own specific micro code array.  The array for one 
-controller is totally incompatible with any other controller, and if used 
-will most likely cause the controller to lock up and stop responding to 
-the driver.  Each micro code array has its own parameter offsets (described 
-below), and they each have their own version number.
-*/
-
-/*************************************************************************
-*  CPUSaver parameters
-*
-*  All CPUSaver parameters are 16-bit literals that are part of a
-*  "move immediate value" instruction.  By changing the value of
-*  the literal in the instruction before the code is loaded, the
-*  driver can change algorithm.
-*
-*  CPUSAVER_DWORD - This is the location of the instruction that loads
-*    the dead-man timer with its inital value.  By writing a 16-bit
-*    value to the low word of this instruction, the driver can change
-*    the timer value.  The current default is either x600 or x800;
-*    experiments show that the value probably should stay within the
-*    range of x200 - x1000.
-*
-*  CPUSAVER_BUNDLE_MAX_DWORD - This is the location of the instruction
-*    that sets the maximum number of frames that will be bundled.  In
-*    some situations, such as the TCP windowing algorithm, it may be
-*    better to limit the growth of the bundle size than let it go as
-*    high as it can, because that could cause too much added latency.
-*    The default is six, because this is the number of packets in the
-*    default TCP window size.  A value of 1 would make CPUSaver indicate
-*    an interrupt for every frame received.  If you do not want to put
-*    a limit on the bundle size, set this value to xFFFF.
-*
-*  CPUSAVER_MIN_SIZE_DWORD - This is the location of the instruction
-*    that contains a bit-mask describing the minimum size frame that
-*    will be bundled.  The default masks the lower 7 bits, which means
-*    that any frame less than 128 bytes in length will not be bundled,
-*    but will instead immediately generate an interrupt.  This does
-*    not affect the current bundle in any way.  Any frame that is 128
-*    bytes or large will be bundled normally.  This feature is meant
-*    to provide immediate indication of ACK frames in a TCP environment.
-*    Customers were seeing poor performance when a machine with CPUSaver
-*    enabled was sending but not receiving.  The delay introduced when
-*    the ACKs were received was enough to reduce total throughput, because
-*    the sender would sit idle until the ACK was finally seen.
-*
-*    The current default is 0xFF80, which masks out the lower 7 bits.
-*    This means that any frame which is x7F (127) bytes or smaller
-*    will cause an immediate interrupt.  Because this value must be a 
-*    bit mask, there are only a few valid values that can be used.  To
-*    turn this feature off, the driver can write the value xFFFF to the
-*    lower word of this instruction (in the same way that the other
-*    parameters are used).  Likewise, a value of 0xF800 (2047) would
-*    cause an interrupt to be generated for every frame, because all
-*    standard Ethernet frames are <= 2047 bytes in length.
-*************************************************************************/
-
-#ifndef UCODE_MAX_DWORDS
-#define UCODE_MAX_DWORDS	134
-#endif
-
-/********************************************************/
-/*  CPUSaver micro code for the D101A                   */
-/********************************************************/
-
-/*  Version 2.0  */
-
-/*  This value is the same for both A and B step of 558.  */
-
-#define D101_CPUSAVER_TIMER_DWORD		72
-#define D101_CPUSAVER_BUNDLE_DWORD		UCODE_MAX_DWORDS
-#define D101_CPUSAVER_MIN_SIZE_DWORD		UCODE_MAX_DWORDS
-
-#define     D101_A_RCVBUNDLE_UCODE \
-{\
-0x03B301BB, 0x0046FFFF, 0xFFFFFFFF, 0x051DFFFF, 0xFFFFFFFF, 0xFFFFFFFF, \
-0x000C0001, 0x00101212, 0x000C0008, 0x003801BC, \
-0x00000000, 0x00124818, 0x000C1000, 0x00220809, \
-0x00010200, 0x00124818, 0x000CFFFC, 0x003803B5, \
-0x00000000, 0x00000000, 0x00000000, 0x00000000, \
-0x0010009C, 0x0024B81D, 0x00130836, 0x000C0001, \
-0x0026081C, 0x0020C81B, 0x00130824, 0x00222819, \
-0x00101213, 0x00041000, 0x003A03B3, 0x00010200, \
-0x00101B13, 0x00238081, 0x00213049, 0x0038003B, \
-0x00000000, 0x00000000, 0x00000000, 0x00000000, \
-0x00000000, 0x00000000, 0x00000000, 0x00000000, \
-0x00000000, 0x00000000, 0x00000000, 0x00000000, \
-0x00000000, 0x00000000, 0x00000000, 0x00000000, \
-0x0010009C, 0x0024B83E, 0x00130826, 0x000C0001, \
-0x0026083B, 0x00010200, 0x00134824, 0x000C0001, \
-0x00101213, 0x00041000, 0x0038051E, 0x00101313, \
-0x00010400, 0x00380521, 0x00050600, 0x00100824, \
-0x00101310, 0x00041000, 0x00080600, 0x00101B10, \
-0x0038051E, 0x00000000, 0x00000000, 0x00000000  \
-}
-
-/********************************************************/
-/*  CPUSaver micro code for the D101B                   */
-/********************************************************/
-
-/*  Version 2.0  */
-
-#define     D101_B0_RCVBUNDLE_UCODE \
-{\
-0x03B401BC, 0x0047FFFF, 0xFFFFFFFF, 0x051EFFFF, 0xFFFFFFFF, 0xFFFFFFFF, \
-0x000C0001, 0x00101B92, 0x000C0008, 0x003801BD, \
-0x00000000, 0x00124818, 0x000C1000, 0x00220809, \
-0x00010200, 0x00124818, 0x000CFFFC, 0x003803B6, \
-0x00000000, 0x00000000, 0x00000000, 0x00000000, \
-0x0010009C, 0x0024B81D, 0x0013082F, 0x000C0001, \
-0x0026081C, 0x0020C81B, 0x00130837, 0x00222819, \
-0x00101B93, 0x00041000, 0x003A03B4, 0x00010200, \
-0x00101793, 0x00238082, 0x0021304A, 0x0038003C, \
-0x00000000, 0x00000000, 0x00000000, 0x00000000, \
-0x00000000, 0x00000000, 0x00000000, 0x00000000, \
-0x00000000, 0x00000000, 0x00000000, 0x00000000, \
-0x00000000, 0x00000000, 0x00000000, 0x00000000, \
-0x0010009C, 0x0024B83E, 0x00130826, 0x000C0001, \
-0x0026083B, 0x00010200, 0x00134837, 0x000C0001, \
-0x00101B93, 0x00041000, 0x0038051F, 0x00101313, \
-0x00010400, 0x00380522, 0x00050600, 0x00100837, \
-0x00101310, 0x00041000, 0x00080600, 0x00101790, \
-0x0038051F, 0x00000000, 0x00000000, 0x00000000  \
-}
-
-/********************************************************/
-/*  CPUSaver micro code for the D101M (B-step only)     */
-/********************************************************/
-
-/*  Version 2.10.1  */
-
-/*  Parameter values for the D101M B-step  */
-#define D101M_CPUSAVER_TIMER_DWORD		78
-#define D101M_CPUSAVER_BUNDLE_DWORD		65
-#define D101M_CPUSAVER_MIN_SIZE_DWORD		126
-
-#define D101M_B_RCVBUNDLE_UCODE \
-{\
-0x00550215, 0xFFFF0437, 0xFFFFFFFF, 0x06A70789, 0xFFFFFFFF, 0x0558FFFF, \
-0x000C0001, 0x00101312, 0x000C0008, 0x00380216, \
-0x0010009C, 0x00204056, 0x002380CC, 0x00380056, \
-0x0010009C, 0x00244C0B, 0x00000800, 0x00124818, \
-0x00380438, 0x00000000, 0x00140000, 0x00380555, \
-0x00308000, 0x00100662, 0x00100561, 0x000E0408, \
-0x00134861, 0x000C0002, 0x00103093, 0x00308000, \
-0x00100624, 0x00100561, 0x000E0408, 0x00100861, \
-0x000C007E, 0x00222C21, 0x000C0002, 0x00103093, \
-0x00380C7A, 0x00080000, 0x00103090, 0x00380C7A, \
-0x00000000, 0x00000000, 0x00000000, 0x00000000, \
-0x0010009C, 0x00244C2D, 0x00010004, 0x00041000, \
-0x003A0437, 0x00044010, 0x0038078A, 0x00000000, \
-0x00100099, 0x00206C7A, 0x0010009C, 0x00244C48, \
-0x00130824, 0x000C0001, 0x00101213, 0x00260C75, \
-0x00041000, 0x00010004, 0x00130826, 0x000C0006, \
-0x002206A8, 0x0013C926, 0x00101313, 0x003806A8, \
-0x00000000, 0x00000000, 0x00000000, 0x00000000, \
-0x00000000, 0x00000000, 0x00000000, 0x00000000, \
-0x00080600, 0x00101B10, 0x00050004, 0x00100826, \
-0x00101210, 0x00380C34, 0x00000000, 0x00000000, \
-0x0021155B, 0x00100099, 0x00206559, 0x0010009C, \
-0x00244559, 0x00130836, 0x000C0000, 0x00220C62, \
-0x000C0001, 0x00101B13, 0x00229C0E, 0x00210C0E, \
-0x00226C0E, 0x00216C0E, 0x0022FC0E, 0x00215C0E, \
-0x00214C0E, 0x00380555, 0x00010004, 0x00041000, \
-0x00278C67, 0x00040800, 0x00018100, 0x003A0437, \
-0x00130826, 0x000C0001, 0x00220559, 0x00101313, \
-0x00380559, 0x00000000, 0x00000000, 0x00000000, \
-0x00000000, 0x00000000, 0x00000000, 0x00000000, \
-0x00000000, 0x00130831, 0x0010090B, 0x00124813, \
-0x000CFF80, 0x002606AB, 0x00041000, 0x00010004, \
-0x003806A8, 0x00000000, 0x00000000, 0x00000000, \
-}
-
-/********************************************************/
-/*  CPUSaver micro code for the D101S                   */
-/********************************************************/
-
-/*  Version 1.20.1  */
-
-/*  Parameter values for the D101S  */
-#define D101S_CPUSAVER_TIMER_DWORD		78
-#define D101S_CPUSAVER_BUNDLE_DWORD		67
-#define D101S_CPUSAVER_MIN_SIZE_DWORD		128
-
-#define D101S_RCVBUNDLE_UCODE \
-{\
-0x00550242, 0xFFFF047E, 0xFFFFFFFF, 0x06FF0818, 0xFFFFFFFF, 0x05A6FFFF, \
-0x000C0001, 0x00101312, 0x000C0008, 0x00380243, \
-0x0010009C, 0x00204056, 0x002380D0, 0x00380056, \
-0x0010009C, 0x00244F8B, 0x00000800, 0x00124818, \
-0x0038047F, 0x00000000, 0x00140000, 0x003805A3, \
-0x00308000, 0x00100610, 0x00100561, 0x000E0408, \
-0x00134861, 0x000C0002, 0x00103093, 0x00308000, \
-0x00100624, 0x00100561, 0x000E0408, 0x00100861, \
-0x000C007E, 0x00222FA1, 0x000C0002, 0x00103093, \
-0x00380F90, 0x00080000, 0x00103090, 0x00380F90, \
-0x00000000, 0x00000000, 0x00000000, 0x00000000, \
-0x0010009C, 0x00244FAD, 0x00010004, 0x00041000, \
-0x003A047E, 0x00044010, 0x00380819, 0x00000000, \
-0x00100099, 0x00206FFD, 0x0010009A, 0x0020AFFD, \
-0x0010009C, 0x00244FC8, 0x00130824, 0x000C0001, \
-0x00101213, 0x00260FF7, 0x00041000, 0x00010004, \
-0x00130826, 0x000C0006, 0x00220700, 0x0013C926, \
-0x00101313, 0x00380700, 0x00000000, 0x00000000, \
-0x00000000, 0x00000000, 0x00000000, 0x00000000, \
-0x00080600, 0x00101B10, 0x00050004, 0x00100826, \
-0x00101210, 0x00380FB6, 0x00000000, 0x00000000, \
-0x002115A9, 0x00100099, 0x002065A7, 0x0010009A, \
-0x0020A5A7, 0x0010009C, 0x002445A7, 0x00130836, \
-0x000C0000, 0x00220FE4, 0x000C0001, 0x00101B13, \
-0x00229F8E, 0x00210F8E, 0x00226F8E, 0x00216F8E, \
-0x0022FF8E, 0x00215F8E, 0x00214F8E, 0x003805A3, \
-0x00010004, 0x00041000, 0x00278FE9, 0x00040800, \
-0x00018100, 0x003A047E, 0x00130826, 0x000C0001, \
-0x002205A7, 0x00101313, 0x003805A7, 0x00000000, \
-0x00000000, 0x00000000, 0x00000000, 0x00000000, \
-0x00000000, 0x00000000, 0x00000000, 0x00130831, \
-0x0010090B, 0x00124813, 0x000CFF80, 0x00260703, \
-0x00041000, 0x00010004, 0x00380700  \
-}
-
-/********************************************************/
-/*  CPUSaver micro code for the D102 B-step             */
-/********************************************************/
-
-/*  Version 2.0  */
-/*  Parameter values for the D102 B-step  */
-#define D102_B_CPUSAVER_TIMER_DWORD		82
-#define D102_B_CPUSAVER_BUNDLE_DWORD		106
-#define D102_B_CPUSAVER_MIN_SIZE_DWORD		70
-
-#define     D102_B_RCVBUNDLE_UCODE \
-{\
-0x006F0276, 0x0EF71FFF, 0x0ED30F86, 0x0D250ED9, 0x1FFF1FFF, 0x1FFF04D2, \
-0x00300001, 0x0140D871, 0x00300008, 0x00E00277, \
-0x01406C57, 0x00816073, 0x008700FA, 0x00E00070, \
-0x00000000, 0x00000000, 0x00000000, 0x00000000, \
-0x00000000, 0x00000000, 0x00000000, 0x00000000, \
-0x01406CBA, 0x00807F9A, 0x00901F9A, 0x0024FFFF, \
-0x014B6F6F, 0x0030FFFE, 0x01407172, 0x01496FBA, \
-0x014B6F72, 0x00308000, 0x01406C52, 0x00912EFC, \
-0x00E00EF8, 0x00000000, 0x00000000, 0x00000000, \
-0x00906F8C, 0x00900F8C, 0x00E00F87, 0x00000000, \
-0x00906ED8, 0x01406C55, 0x00E00ED4, 0x00000000, \
-0x01406C51, 0x0080DFC2, 0x01406C52, 0x00815FC2, \
-0x01406C57, 0x00917FCC, 0x00E01FDD, 0x00000000, \
-0x00822D30, 0x01406C51, 0x0080CD26, 0x01406C52, \
-0x00814D26, 0x01406C57, 0x00916D26, 0x014C6FD7, \
-0x00300000, 0x00841FD2, 0x00300001, 0x0140D772, \
-0x00E012B3, 0x014C6F91, 0x0150710B, 0x01496F72, \
-0x0030FF80, 0x00940EDD, 0x00102000, 0x00038400, \
-0x00E00EDA, 0x00000000, 0x00000000, 0x00000000, \
-0x01406C57, 0x00917FE9, 0x00001000, 0x00E01FE9, \
-0x00200600, 0x0140D76F, 0x00138400, 0x01406FD8, \
-0x0140D96F, 0x00E01FDD, 0x00038400, 0x00102000, \
-0x00971FD7, 0x00101000, 0x00050200, 0x00E804D2, \
-0x014C6FD8, 0x00300001, 0x00840D26, 0x0140D872, \
-0x00E00D26, 0x014C6FD9, 0x00300001, 0x0140D972, \
-0x00941FBD, 0x00102000, 0x00038400, 0x014C6FD8, \
-0x00300006, 0x00840EDA, 0x014F71D8, 0x0140D872, \
-0x00E00EDA, 0x01496F50, 0x00E004D3, 0x00000000, \
-}
-
-/********************************************************/
-/*  Micro code for the D102 C-step                      */
-/********************************************************/
-
-/*  Parameter values for the D102 C-step  */
-#define D102_C_CPUSAVER_TIMER_DWORD		46
-#define D102_C_CPUSAVER_BUNDLE_DWORD		74
-#define D102_C_CPUSAVER_MIN_SIZE_DWORD		54
-
-#define     D102_C_RCVBUNDLE_UCODE \
-{ \
-0x00700279, 0x0E6604E2, 0x02BF0CAE, 0x1508150C, 0x15190E5B, 0x0E840F13, \
-0x00E014D8, 0x00000000, 0x00000000, 0x00000000, \
-0x00E014DC, 0x00000000, 0x00000000, 0x00000000, \
-0x00E014F4, 0x00000000, 0x00000000, 0x00000000, \
-0x00000000, 0x00000000, 0x00000000, 0x00000000, \
-0x00E014E0, 0x00000000, 0x00000000, 0x00000000, \
-0x00000000, 0x00000000, 0x00000000, 0x00000000, \
-0x00000000, 0x00000000, 0x00000000, 0x00000000, \
-0x00000000, 0x00000000, 0x00000000, 0x00000000, \
-0x00E014E7, 0x00000000, 0x00000000, 0x00000000, \
-0x00141000, 0x015D6F0D, 0x00E002C0, 0x00000000, \
-0x00200600, 0x00E0150D, 0x00000000, 0x00000000, \
-0x00000000, 0x00000000, 0x00000000, 0x00000000, \
-0x0030FF80, 0x00940E6A, 0x00038200, 0x00102000, \
-0x00E00E67, 0x00000000, 0x00000000, 0x00000000, \
-0x00000000, 0x00000000, 0x00000000, 0x00000000, \
-0x00000000, 0x00000000, 0x00000000, 0x00000000, \
-0x00906E65, 0x00800E60, 0x00E00E5D, 0x00000000, \
-0x00300006, 0x00E0151A, 0x00000000, 0x00000000, \
-0x00906F19, 0x00900F19, 0x00E00F14, 0x00000000, \
-0x00000000, 0x00000000, 0x00000000, 0x00000000, \
-0x01406CBA, 0x00807FDA, 0x00901FDA, 0x0024FFFF, \
-0x014B6F6F, 0x0030FFFE, 0x01407172, 0x01496FBA, \
-0x014B6F72, 0x00308000, 0x01406C52, 0x00912E89, \
-0x00E00E85, 0x00000000, 0x00000000, 0x00000000  \
-}
-
-/********************************************************/
-/*  Micro code for the D102 E-step                      */
-/********************************************************/
-
-/*  Parameter values for the D102 E-step  */
-#define D102_E_CPUSAVER_TIMER_DWORD		42
-#define D102_E_CPUSAVER_BUNDLE_DWORD		54
-#define D102_E_CPUSAVER_MIN_SIZE_DWORD		46
-
-#define     D102_E_RCVBUNDLE_UCODE \
-{\
-0x007D028F, 0x0E4204F9, 0x14ED0C85, 0x14FA14E9, 0x1FFF1FFF, 0x1FFF1FFF, \
-0x00E014B9, 0x00000000, 0x00000000, 0x00000000, \
-0x00E014BD, 0x00000000, 0x00000000, 0x00000000, \
-0x00E014D5, 0x00000000, 0x00000000, 0x00000000, \
-0x00000000, 0x00000000, 0x00000000, 0x00000000, \
-0x00E014C1, 0x00000000, 0x00000000, 0x00000000, \
-0x00000000, 0x00000000, 0x00000000, 0x00000000, \
-0x00000000, 0x00000000, 0x00000000, 0x00000000, \
-0x00000000, 0x00000000, 0x00000000, 0x00000000, \
-0x00E014C8, 0x00000000, 0x00000000, 0x00000000, \
-0x00200600, 0x00E014EE, 0x00000000, 0x00000000, \
-0x0030FF80, 0x00940E46, 0x00038200, 0x00102000, \
-0x00E00E43, 0x00000000, 0x00000000, 0x00000000, \
-0x00300006, 0x00E014FB, 0x00000000, 0x00000000  \
-}
-
-#endif /* _E100_UCODE_H_ */
--- diff/drivers/parport/init.c	2003-05-21 11:49:55.000000000 +0100
+++ source/drivers/parport/init.c	1970-01-01 01:00:00.000000000 +0100
@@ -1,229 +0,0 @@
-/* Parallel-port initialisation code.
- * 
- * Authors: David Campbell <campbell@torque.net>
- *          Tim Waugh <tim@cyberelk.demon.co.uk>
- *	    Jose Renau <renau@acm.org>
- *
- * based on work by Grant Guenther <grant@torque.net>
- *              and Philip Blundell <Philip.Blundell@pobox.com>
- */
-
-#include <linux/config.h>
-#include <linux/module.h>
-#include <linux/threads.h>
-#include <linux/string.h>
-#include <linux/parport.h>
-#include <linux/errno.h>
-#include <linux/kernel.h>
-#include <linux/slab.h>
-#include <linux/init.h>
-
-#ifndef MODULE
-static int io[PARPORT_MAX+1] __initdata = { [0 ... PARPORT_MAX] = 0 };
-#ifdef CONFIG_PARPORT_PC
-static int io_hi[PARPORT_MAX+1] __initdata =
-	{ [0 ... PARPORT_MAX] = PARPORT_IOHI_AUTO };
-#endif
-static int irq[PARPORT_MAX] __initdata = { [0 ... PARPORT_MAX-1] = PARPORT_IRQ_PROBEONLY };
-static int dma[PARPORT_MAX] __initdata = { [0 ... PARPORT_MAX-1] = PARPORT_DMA_NONE };
-
-extern int parport_pc_init(int *io, int *io_hi, int *irq, int *dma);
-extern int parport_sunbpp_init(void);
-extern int parport_amiga_init(void);
-extern int parport_mfc3_init(void);
-extern int parport_atari_init(void);
-
-static int parport_setup_ptr __initdata = 0;
-
-/*
- * Acceptable parameters:
- *
- * parport=0
- * parport=auto
- * parport=0xBASE[,IRQ[,DMA]]
- *
- * IRQ/DMA may be numeric or 'auto' or 'none'
- */
-static int __init parport_setup (char *str)
-{
-	char *endptr;
-	char *sep;
-	int val;
-
-	if (!str || !*str || (*str == '0' && !*(str+1))) {
-		/* Disable parport if "parport=0" in cmdline */
-		io[0] = PARPORT_DISABLE;
-		return 1;
-	}
-
-	if (!strncmp (str, "auto", 4)) {
-		irq[0] = PARPORT_IRQ_AUTO;
-		dma[0] = PARPORT_DMA_AUTO;
-		return 1;
-	}
-
-	val = simple_strtoul (str, &endptr, 0);
-	if (endptr == str) {
-		printk (KERN_WARNING "parport=%s not understood\n", str);
-		return 1;
-	}
-
-	if (parport_setup_ptr == PARPORT_MAX) {
-		printk(KERN_ERR "parport=%s ignored, too many ports\n", str);
-		return 1;
-	}
-	
-	io[parport_setup_ptr] = val;
-	irq[parport_setup_ptr] = PARPORT_IRQ_NONE;
-	dma[parport_setup_ptr] = PARPORT_DMA_NONE;
-
-	sep = strchr (str, ',');
-	if (sep++) {
-		if (!strncmp (sep, "auto", 4))
-			irq[parport_setup_ptr] = PARPORT_IRQ_AUTO;
-		else if (strncmp (sep, "none", 4)) {
-			val = simple_strtoul (sep, &endptr, 0);
-			if (endptr == sep) {
-				printk (KERN_WARNING
-					"parport=%s: irq not understood\n",
-					str);
-				return 1;
-			}
-			irq[parport_setup_ptr] = val;
-		}
-	}
-
-	sep = strchr (sep, ',');
-	if (sep++) {
-		if (!strncmp (sep, "auto", 4))
-			dma[parport_setup_ptr] = PARPORT_DMA_AUTO;
-		else if (!strncmp (sep, "nofifo", 6))
-			dma[parport_setup_ptr] = PARPORT_DMA_NOFIFO;
-		else if (strncmp (sep, "none", 4)) {
-			val = simple_strtoul (sep, &endptr, 0);
-			if (endptr == sep) {
-				printk (KERN_WARNING
-					"parport=%s: dma not understood\n",
-					str);
-				return 1;
-			}
-			dma[parport_setup_ptr] = val;
-		}
-	}
-
-	parport_setup_ptr++;
-	return 1;
-}
-
-__setup ("parport=", parport_setup);
-
-#endif
-
-#ifdef MODULE
-int init_module(void)
-{
-#ifdef CONFIG_SYSCTL
-	parport_default_proc_register ();
-#endif
-	return 0;
-}
-
-void cleanup_module(void)
-{
-#ifdef CONFIG_SYSCTL
-	parport_default_proc_unregister ();
-#endif
-}
-
-#else
-
-int __init parport_init (void)
-{
-	if (io[0] == PARPORT_DISABLE) 
-		return 1;
-
-#ifdef CONFIG_SYSCTL
-	parport_default_proc_register ();
-#endif
-
-#ifdef CONFIG_PARPORT_PC
-	parport_pc_init(io, io_hi, irq, dma);
-#endif
-#ifdef CONFIG_PARPORT_AMIGA
-	parport_amiga_init();
-#endif
-#ifdef CONFIG_PARPORT_MFC3
-	parport_mfc3_init();
-#endif
-#ifdef CONFIG_PARPORT_ATARI
-	parport_atari_init();
-#endif
-#ifdef CONFIG_PARPORT_ARC
-	parport_arc_init();
-#endif
-#ifdef CONFIG_PARPORT_SUNBPP
-	parport_sunbpp_init();
-#endif
-	return 0;
-}
-
-__initcall(parport_init);
-
-#endif
-
-/* Exported symbols for modules. */
-
-EXPORT_SYMBOL(parport_claim);
-EXPORT_SYMBOL(parport_claim_or_block);
-EXPORT_SYMBOL(parport_release);
-EXPORT_SYMBOL(parport_register_port);
-EXPORT_SYMBOL(parport_announce_port);
-EXPORT_SYMBOL(parport_unregister_port);
-EXPORT_SYMBOL(parport_register_driver);
-EXPORT_SYMBOL(parport_unregister_driver);
-EXPORT_SYMBOL(parport_register_device);
-EXPORT_SYMBOL(parport_unregister_device);
-EXPORT_SYMBOL(parport_enumerate);
-EXPORT_SYMBOL(parport_get_port);
-EXPORT_SYMBOL(parport_put_port);
-EXPORT_SYMBOL(parport_find_number);
-EXPORT_SYMBOL(parport_find_base);
-EXPORT_SYMBOL(parport_negotiate);
-EXPORT_SYMBOL(parport_write);
-EXPORT_SYMBOL(parport_read);
-EXPORT_SYMBOL(parport_ieee1284_wakeup);
-EXPORT_SYMBOL(parport_wait_peripheral);
-EXPORT_SYMBOL(parport_poll_peripheral);
-EXPORT_SYMBOL(parport_wait_event);
-EXPORT_SYMBOL(parport_set_timeout);
-EXPORT_SYMBOL(parport_ieee1284_interrupt);
-EXPORT_SYMBOL(parport_ieee1284_ecp_write_data);
-EXPORT_SYMBOL(parport_ieee1284_ecp_read_data);
-EXPORT_SYMBOL(parport_ieee1284_ecp_write_addr);
-EXPORT_SYMBOL(parport_ieee1284_write_compat);
-EXPORT_SYMBOL(parport_ieee1284_read_nibble);
-EXPORT_SYMBOL(parport_ieee1284_read_byte);
-EXPORT_SYMBOL(parport_ieee1284_epp_write_data);
-EXPORT_SYMBOL(parport_ieee1284_epp_read_data);
-EXPORT_SYMBOL(parport_ieee1284_epp_write_addr);
-EXPORT_SYMBOL(parport_ieee1284_epp_read_addr);
-EXPORT_SYMBOL(parport_proc_register);
-EXPORT_SYMBOL(parport_proc_unregister);
-EXPORT_SYMBOL(parport_device_proc_register);
-EXPORT_SYMBOL(parport_device_proc_unregister);
-EXPORT_SYMBOL(parport_default_proc_register);
-EXPORT_SYMBOL(parport_default_proc_unregister);
-EXPORT_SYMBOL(parport_parse_irqs);
-EXPORT_SYMBOL(parport_parse_dmas);
-#ifdef CONFIG_PARPORT_1284
-EXPORT_SYMBOL(parport_open);
-EXPORT_SYMBOL(parport_close);
-EXPORT_SYMBOL(parport_device_id);
-EXPORT_SYMBOL(parport_device_num);
-EXPORT_SYMBOL(parport_device_coords);
-EXPORT_SYMBOL(parport_daisy_deselect_all);
-EXPORT_SYMBOL(parport_daisy_select);
-EXPORT_SYMBOL(parport_daisy_init);
-EXPORT_SYMBOL(parport_find_device);
-EXPORT_SYMBOL(parport_find_class);
-#endif
--- diff/fs/devfs/internal.h	2003-02-13 11:46:39.000000000 +0000
+++ source/fs/devfs/internal.h	1970-01-01 01:00:00.000000000 +0100
@@ -1,3 +0,0 @@
-
-extern dev_t devfs_alloc_devnum(umode_t mode);
-extern void devfs_dealloc_devnum(umode_t mode, dev_t devnum);
--- diff/fs/hfs/ChangeLog	2002-10-16 04:27:53.000000000 +0100
+++ source/fs/hfs/ChangeLog	1970-01-01 01:00:00.000000000 +0100
@@ -1,2506 +0,0 @@
-2000-01-02  a sun  <asun@asun.cobalt.com>
-
-	* file.c (hfs_get_block): added hfs_get_block for regular files. 
-
-1999-04-12  a sun  <asun@hecate.darksunrising.blah>
-
-	* file_hdr.c (hdr_read): added rootinfo behaviour for DID header.
-
-1999-04-11  a sun  <asun@hecate.darksunrising.blah>
-
-	* super.c (parse_options): added s_version so that we can select
-	between different versions of the same layout.
-
-1999-04-05  a sun  <asun@hecate.darksunrising.blah>
-
-	* linux/hfs_fs.h: unified netatalk and appledouble header format. 
-	added in all of the AFP attribute bits.
-
-	* file_hdr.c: added netatalk appledouble v2 compatible headers. 
-
-1999-01-30  a sun  <asun@hecate.darksunrising.blah>
-
-	* catalog.c (hfs_cat_move): fixed corruption problem with
-	renames.
-
-1999-01-27  a sun  <asun@hecate.darksunrising.blah>
-
-	* file_hdr.c (get/set_dates): got rid of broken afpd times. NOTE:
-	you must use netatalk-1.4b2+asun2.1.2 or newer for this.
-
-1998-12-20  a sun  <asun@hecate.darksunrising.blah>
-
-	* bdelete.c (del_root): assign bthLNode and bthFNode only if the
-	root node becomes a leaf node. Disk First Aid no longer
-	complains. Norton Utilities, of course, has decided that it
-	doesn't like the root node number. bleah. i think that it might be
-	due to Norton Utilities not expecting the root node to have moved.
-
-1998-12-16  a sun  <asun@hecate.darksunrising.blah>
-
-	* sysdep.c (hfs_revalidate_dentry): fix inode dates when there's a
-	timezone change.
-
-1998-12-15  root  <root@hecate.darksunrising.blah>
-
-	* extent.c (new_extent): expand block size variables to handle
-	u32. 
-
-	* mdb.c (hfs_mdb_get): AlBlkSiz shouldn't be capped at 65535. we
-	should be able to handle much larger volumes now.
-
-1998-11-21  a sun  <asun@hecate.darksunrising.blah>
-
-	* hfs_sysdep.h, hfs_fs.h: added hfs_from_utc/to_utc to deal with
-	date differences on hfs formatted media. 
-
-	NOTE: hfs extended keeps everything in utc, so we'll need to deal
-	with that when appropriate.
-
-1998-11-12  a sun  <asun@hecate.darksunrising.blah>
-
-	* extent.c (shrink_fork): added some lock_bitmap/unlock_bitmap's
-	to protect hfs_clear_vbm_bits. we should no longer have problems
-	with free_ablocks wrapping around.
-
-1998-11-02  a sun  <asun@hecate.darksunrising.blah>
-
-	* mdb.c (hfs_mdb_get): plugged up an mdb failed initialization
-	leak.
-
-1998-10-31  a sun  <asun@hecate.darksunrising.blah>
-
-	* version.c (hfs_version): bumped to version 0.96.
-
-	* mdb.c (hfs_mdb_commit): you only write out the alternate MDB
-	when the catalog or extents overflow files grow. that just leaves
-	the btree corruption problems. bleah (whilst deleting a bunch of
-	files, more of the btree can get pruned away than desired).
-
-1998-10-30  a sun  <asun@hecate.darksunrising.blah>
-
-	* dir.c: fixed a bunch of silliness with deletions. make sure to
-	zero out stuff and set mark_inode_dirty().
-	
-1998-10-29  a sun  <asun@hecate.darksunrising.blah>
-
-	* string.c (hfs_strcmp, hfs_streq, hfs_strhash): converted them to
-	take name/len arguments instead of hfs_name to reduce copying.
-
-	* dir.c, dir_nat.c, dir_cap.c, dir_dbl.c, sysdep.c: modified
-	relevant areas to reflect string.c changes.
-	
-1998-10-28  a sun  <asun@hecate.darksunrising.blah>
-
-	* hfs.h (hfs_lookup_dentry): oh my. more silliness. make sure to
-	have the d_lookup use the same hash value as the one generated by
-	hfs_hash_dentry. i also changed the argument order.
-	(hfs_drop_special): change the argument order to be more in line
-	with what the dcache stuff looks like.
-
-	* sysdep.c (hfs_compare_dentry): the compare was returning the
-	wrong value for correct matches and causing all sorts of
-	mischief. this fixes both directory counts and mounting on top of
-	hfs volumes.
-
-	* file.c, file_cap.c, file_hdr.c: added mark_inode_dirty()'s in
-	the relevant places.
-
-1998-10-11  root  <asun@hecate.darksunrising.blah>
-
-	* mdb.c (hfs_mdb_get): moved initialization of mdb->entry_dirty
-	list to here to deal with trying to read a bad hfs volume.
-
-1998-10-10  a sun  <asun@zoology.washington.edu>
-
-	* inode.c, catalog.c, dir_*.c, sysdep.c: parts of the dcache
-	conversion didn't get done properly. specifically, i forgot to
-	move the hfs_cat_puts into the right place. that's fixed now.
-
-1998-09-11  a sun  <asun@purgatorius.zoology.washington.edu>
-
-	* mdb.c: altered mdb struct to reflect hfs plus usage.
-
-1998-08-27  a sun  <asun@purgatorius.zoology.washington.edu>
-
-	* file.c, file_hdr.c, file_cap.c: dealt with the remaining
-	copy_to/from_user() error cases.
-
-1998-08-26  a sun  <asun@purgatorius.zoology.washington.edu>
-
-	* super.c (hfs_read_super): fixed to deal with cdroms. why doesn't
-	the cdrom layer call the partition table code?
-
-Wed Jan 21 14:04:26 1998  a sun  <asun@zoology.washington.edu>
-
-	* inode.c, sysdep.c
-	use d_iput to uncache dentry from catalog entry instead of relying
-	on put_inode. no more NULL pointer dereferences!
-
-	* catalog.c
-	cleaned up hfs_cat_put a little.
-	
-	ISSUES (non-fatal): mv dir dir2 while creating files in dir screws
-	                    up directory counts.
-		
-			    deletion using netatalk screws up directory
- 			    counts.
-
-Thu Jan 15 19:14:28 1998  a sun  <asun@zoology.washington.edu>
-
-	* catalog.c
-	make deletion happen when requested instead of waiting until
-	an hfs_cat_put as the dcache can hold onto entries for quite
-	some time.
-
-Wed Jan 14 14:43:16 1998  a sun  <asun@zoology.washington.edu>
-	
-	* catalog.c
-	the current catalog allocation scheme allocates
-	PAGE_SIZE/sizeof(struct hfs_cat_entry) entries at a time and keeps
-	a pool of free entries up to this allocation unit * 8.
-
-	* inode.c
-	make sure to always hfs_cat_put if hfs_iget is going to return
-	NULL.
-
-	* string.c, catalog.c
-	use linux' hashing method to generate hashes. the old hashing was
- 	getting collisions. catalog.c also has a larger hash table to
- 	prevent collisions.
-	
-Tue Jan 13 13:06:01 1998  a sun  <asun@zoology.washington.edu>
-
-	* version.c
-	bumped to 0.95+asun3
-
-	* catalog.c
-	re-wrote to dynamically allocate/delete catalog entries. on a 486,
-	entries fit into the size-256 slab.
-
-Wed Jan  7 19:33:33 1998  a sun  <asun@zoology.washington.edu>
-
-	* inode.c 
-	don't hfs_cat_put gratuitously in hfs_iget. that's a bad
- 	idea and results in screwed up entry counts.
-
-Tue Jan  6 14:38:24 1998  a sun  <asun@zoology.washington.edu>
-
-	* version.c
-	changed it to 0.95+asun2
-
-	* sysdep.c
-	altered catalog entry pruning to make sure that an iput
-	gets done. for some reason, shrink_dcache_parent wasn't
-	doing it.
-
-	* catalog.c
-	added a global dirty list to check for pruning.
-	
-Tue Jan  6 12:29:52 1998  a sun  <asun@zoology.washington.edu>
-
-	* catalog.c
-	re-wrote it to be similar to 2.1.x inode.c. this should
- 	at least make catalog.c SMP safe. 
-
-	* hfs.h, linux/hfs_fs.h
-	moved dentry operations into hfs.h. these probably should
-	be moved somewhere else.
-
-	* super.c, dir_cap.c, dir_nat.c, dir_dbl.c, sysdep.c
-	added dentry ops to hash everything to lowercase.
-
-Sun Dec 28 22:48:53 1997  a sun  <asun@zoology.washington.edu>
-
-	* sysdep.c, catalog.c, hfs.h
-	as a temporary workaround until catalog.c gets re-written, 
-	i flush the dcache if we need more entries. 
-	
-Fri Dec 19 15:11:21 1997  a sun  <asun@zoology.washington.edu>
-
-	* dir_dbl.c
-	statically allocate tmp_name instead of doing it dynamically.
-
-	NOTE: well, those pesky hfs_cat_put messages still aren't gone. in
-	addition, catalog.c needs to be modified to free up some entries
-	when the cache gets filled up. 
-
-Sun Dec 14 11:51:11 1997  a sun  <asun@zoology.washington.edu>
-
-	* linux/hfs_fs.h
-	moved the dentry stuff into within the #ifdef __KERNEL__ 
-	part of hfs_fs.h and cleaned up a little.
-
-Sun Dec 14 11:24:54 1997  a sun  <asun@zoology.washington.edu>
-
-	* dir.c
-	changed hfs_rename to delete all old dentries. hfs_cat_put
-	messages on umount should be a thing of the past now.
-
-Sun Dec 14 01:12:58 1997  a sun  <asun@zoology.washington.edu>
-
-	* dir.c
-	changed mark_inodes_deleted to dget/d_delete/dput the dentry
-	instead of just dropping it. the bytes available should now
-	be updated properly upon deletion.
-
-Wed Dec 10 00:01:25 1997  a sun  <asun@zoology.washington.edu>
-
-	* dir.c
-	changed mark_inodes_deleted to drop the dentry instead of 
-	just deleting it. 
-
-	TODO: bytes available aren't being properly updated when a
-	resource fork gets deleted.
-
-Mon Dec  8 23:22:40 1997  a sun  <asun@zoology.washington.edu>
-
-	* dir_cap.c, dir_nat.c, dir_dbl.c, dir.c
-	* hfs.h, linux/hfs_sysdep.h, linux/hfs_fs_i.h
-	Added code to drop ({dbl,cap,nat}_drop_dentry) invalid
-	dentries when creating or moving a file.
-
-	* inode.c
-	Added code to delete cached dentries when a file gets deleted.
-
-	* current yuckiness: there's an extra hfs_cat_put somewhere. it's
-	harmless but bothersome.
-	
-Thu Dec  4 00:14:03 1997  a sun  <asun@zoology.washington.edu>
-
-	* dir.c, dir_cap.c, dir_nat.c, file.c, file_hdr.c, inode.c,
-	* linux/{hfs_sysdep.h, hfs_fs.h}, version.c:
-	Completed first code dentrification sweep. It mounts! It copies!
-	It dcaches! 
-
-Mon Apr 28 06:58:44 1997  Paul H. Hargrove  <hargrove@sccm.stanford.edu>
-
-	* version.c, INSTALL.sgml, HFS.sgml:
-	Bump version to 0.95 (Woohoo! We're beta!)
-
-	* linux/hfs_fs.h:
-	Modify HFS_SB() and HFS_I() when compiled into the kernel.
-
-	* FAQ.sgml:
-	Add a new question (and its answer):
-	Why does my Macintosh show generic application and document icons?
-
-	* HFS.sgml:
-	Add some URLs and remove the (now empty) FAQ section.
-
-Sun Apr 27 22:17:01 1997  Paul H. Hargrove  <hargrove@sccm.stanford.edu>
-
-	* HFS.sgml:
-	Don't call the version 1 headers "slightly modified".
-
-	* file_hdr.c, dir_nat.c:
-	Comment some AFPD compatibility stuff.
-
-	* FAQ.sgml:
-	Update for version 0.95.
-
-	* BUG_INFO:
-	Remove the BIG_INFO script since we no longer mention it.
-
-	* README.sgml, INSTALL.sgml, HFS.sgml, Makefile:
-	Split README.sgml into HFS.sgml and INSTALL.sgml.
-	Stop including the document sources in snapshots.
-
-	* file_hdr.c:
-	Fix hdr_truncate() not to truncate the data fork.
-
-Wed Apr 16 23:56:25 1997  Paul H. Hargrove  <hargrove@sccm.stanford.edu>
-
-	* FAQ.sgml:
-	Bump version to 0.8.4 and add two answers:
-		How to fsck an HFS filesystem.
-		How to generate linux/version.h.
-
-	* version.c, README.sgml:
-	Bump version to 0.8.4.
-
-	* README.sgml, FAQ.sgml, Makefile:
-	Separate the FAQ from the README.
-
-	* linux/hfs_fs.h:
-	Add (struct hfs_fork) to the forward declarations.
-
-Thu Apr 10 05:47:16 1997  Paul H. Hargrove  <hargrove@sccm.stanford.edu>
-
-	* linux/hfs_sysdep.h:
-	Work around the non-const declaration of test_bit()'s second argument.
-
-	* Makefile:
-	Use .config from the kernel source to check for MODVERSIONS.
-
-Wed Apr  9 07:57:17 1997  Paul H. Hargrove  <hargrove@sccm.stanford.edu>
-
-	* bnode.c:
-	Check the record table in each bnode as we read it from disk.
-
-	* super.c, mdb.c, hfs.h:
-	Deal with the ATTRIB_CLEAN bit of the MDB properly (in mdb.c).
-
-	* super.c, hfs.h, mdb.c:
-	Search for the alt-MDB rather than using the device size to find it.
-
-Wed Apr  9 03:39:05 1997  Paul H. Hargrove  <hargrove@sccm.stanford.edu>
-
-	* version.c, README.sgml:
-	Bump version to 0.8.3.
-
-Mon Apr  7 20:09:56 1997  Paul H. Hargrove  <hargrove@sccm.stanford.edu>
-
-	* part_tbl.c:
-	Fix to allow bootable CDROMs (which have blocksize != 512) to mount.
-
-	* super.c:
-	Check that blk_size[MAJOR(dev)] is non-NULL before dereferencing.
-
-Sat Apr  5 10:44:42 1997  Paul H. Hargrove  <hargrove@sccm.stanford.edu>
-
-	* hfs_btree.h, binsert.c, brec.c, bfind.c, bins_del.c, bdelete.c:
-	Make btree operations less likely to do
-	nasty things if the tree is corrupted.
-
-	* part_tbl.c, README.sgml:
-	Count partitions from 0 rather than from 1.
-
-Wed Apr  2 23:26:51 1997  Paul H. Hargrove  <hargrove@sccm.stanford.edu>
-
-	* bdelete.c:
-	Don't bother checking for oversized keys in hfs_bdelete().
-
-	* bdelete.c, bfind.c, binsert.c:
-	Verify key lengths against the maximum given for the tree.
-
-	* Makefile:
-	Check that /usr/include/linux/modversions.h exists before including it.
-	This allows compilation without CONFIG_MODVERSIONS enabled.
-
-Sat Mar 29 13:17:53 1997  Paul H. Hargrove  <hargrove@sccm.stanford.edu>
-
-	* linux/hfs_fs.h, super.c, file_hdr.c, hfs.h, extent.c, file_cap.c,
-	  dir_dbl.c, dir_nat.c, dir.c, dir_cap.c, binsert.c, catalog.c,
-	  bfind.c:
-	Make (struct hfs_bkey) and (struct hfs_brec) more "abstract".
-
-	* binsert.c:
-	Remove redundant test in hfs_binsert().
-
-Sat Mar 29 05:24:23 1997  Paul H. Hargrove  <hargrove@sccm.stanford.edu>
-
-	* version.c, README.sgml:
-	Fix formatting problems in README.sgml and bump version to 0.8.2.
-
-	* extent.c:
-	Fix bug that caused serious headaches with fragmented files.
-
-Fri Mar 28 00:23:18 1997  Paul H. Hargrove  <hargrove@sccm.stanford.edu>
-
-	* version.c, README.sgml:
-	Bump version to 0.8.1.
-
-	* btree.c, balloc.c:
-	Commit map nodes to buffers when new map nodes are added.
-
-Thu Mar 27 22:41:07 1997  Paul H. Hargrove  <hargrove@sccm.stanford.edu>
-
-	* Makefile:
-	Include linux/modversions.h from the gcc command line.
-
-	* mdb.c:
-	Was updating modified date twice in hfs_mdb_commit().
-
-	* linux/hfs_sysdep.h, linux/hfs_fs.h, linux/hfs_fs_i.h,
-	  linux/hfs_fs_sb.h, sysdep.c, trans.c, super.c, hfs_sysdep.h, inode.c,
-	  hfs_fs_i.h, hfs_fs_sb.h, hfs_fs.h, hfs.h, file_cap.c, file_hdr.c,
-	  file.c, dir_nat.c, dir_cap.c, dir_dbl.c, Makefile, dir.c:
-	Rearrange headers in preparation for inclusion in the kernel.
-
-	* hfs_fs_sb.h, hfs_fs.h:
-	Add forward declarations so other code can include these headers.
-
-	* hfs_sysdep.h:
-	Include __constant_hton[ls]() for little-endian machines.
-
-	* hfs_fs.h, hfs_sysdep.h, hfs.h:
-	Move typedefs of hfs_{byte,word,lword}_t from hfs.h to hfs_sysdep.h.
-	Include hfs_sysdep.h from hfs_fs.h.
-
-	* trans.c, super.c, part_tbl.c, string.c, inode.c, mdb.c, hfs_fs_sb.h,
-	  hfs_sysdep.h, hfs_fs.h, hfs.h, hfs_btree.h, file_cap.c, file_hdr.c,
-	  file.c, dir_nat.c, extent.c, dir_dbl.c, dir.c, dir_cap.c, catalog.c,
-	  btree.c, bnode.c, brec.c, bitmap.c, bitops.c, bins_del.c, binsert.c,
-	  bdelete.c, bfind.c, balloc.c:
-	Big type system changes in preparation for kernel inclusion:
-	'[US](8|16|32)' -> 'hfs_[us](8|16|32)' (avoids name space pollution)
-	'hfs_name_t' -> 'struct hfs_name' (allows forward declaration)
-
-	* super.c, hfs_fs.h:
-	Add init_hfs_fs() to super.c for non-module compilation.
-
-Wed Mar 26 07:53:59 1997  Paul H. Hargrove  <hargrove@sccm.stanford.edu>
-
-	* version.c, README.sgml:
-	Bump version to 0.8.
-
-	* README.sgml:
-	Special compilation note for DEC Alpha.
-
-	* README.sgml:
-	Note status on non-Intel processors.
-
-	* hfs_fs.h:
-	Use long's for read() and write() on the Alpha.
-
-	* README.sgml:
-	Document the afpd mount option.
-
-	* inode.c:
-	Make files always writable for owner in afpd mode.
-
-Tue Mar 25 23:21:39 1997  Paul H. Hargrove  <hargrove@sccm.stanford.edu>
-
-	* part_tbl.c:
-	Clean up the error checking code a bit.
-
-Sat Mar 22 19:43:40 1997  Paul H. Hargrove  <hargrove@sccm.stanford.edu>
-
-	* part_tbl.c:
-	Fixed uninitialized variable in old-style partition code.
-
-	* bins_del.c, bdelete.c:
-	Fix extraneous "bad argument to shift_{left,right}" messages.
-
-	* bitops.c:
-	Note that these routines are now tested on Intel, PPC and Alpha.
-
-	* Makefile:
-	Add -fno-builtin to the CFLAGS.
-
-Fri Feb 14 10:50:14 1997  Paul H. Hargrove  <hargrove@sccm.stanford.edu>
-
-	* hfs_sysdep.h:
-	Don't include <asm/*.h> until after <linux/types.h>.
-
-	* catalog.c:
-	Use volume create date in hashfn() rather than casting pointer to int.
-
-	* hfs.h, mdb.c:
-	Maintaing volume create, modify and backup dates in struct hfs_mdb.
-
-	* hfs_fs.h:
-	Include the header for put_user BEFORE using it!
-
-	* string.c, hfs.h:
-	Make hfs_strhash() return an unsigned int.
-
-	* trans.c, version.c, super.c, mdb.c, part_tbl.c, string.c, inode.c,
-	  hfs_sysdep.h, hfs_fs.h, hfs_fs_sb.h, hfs_btree.h, hfs.h, file_cap.c,
-	  file_hdr.c, extent.c, dir_dbl.c, dir_nat.c, dir_cap.c, dir.c,
-	  catalog.c, btree.c, bnode.c, brec.c, bitmap.c, binsert.c,
-	  bins_del.c, bdelete.c, balloc.c, README.sgml, Makefile:
-	Updated copyright notices.
-
-	* trans.c, part_tbl.c, string.c, super.c, inode.c, mdb.c, hfs_fs.h,
-	  hfs_fs_sb.h, hfs_sysdep.h, hfs_btree.h, hfs.h, file_cap.c,
-	  file_hdr.c, dir_nat.c, extent.c, dir_cap.c, dir_dbl.c, catalog.c,
-	  dir.c, brec.c, btree.c, bitmap.c, bnode.c, bdelete.c, bins_del.c,
-	  binsert.c, Makefile, TODO, balloc.c:
-	First shot at portability to the DEC Alpha and non-gcc compilers.
-	This involved a significant overhaul of the type system.
-
-Tue Feb  4 04:26:54 1997  Paul H. Hargrove  <hargrove@sccm.stanford.edu>
-
-	* version.c, README.sgml:
-	Bump version to "pre-0.8-4".
-
-	* dir_nat.c:
-	Allow creat() in Netatalk .AppleDouble directories.
-
-	* dir_dbl.c:
-	Make local functions static.
-
-	* dir_dbl.c:
-	Removed unnecessary 'extern' qualifiers from forward declarations.
-
-	* file_hdr.c, TODO:
-	Fixed the 30-year time warp with afpd.
-
-	* TODO, trans.c:
-	Don't mangle the name .AppleDesktop under fork=netatalk.
-
-Mon Feb  3 23:18:45 1997  Paul H. Hargrove  <hargrove@sccm.stanford.edu>
-
-	* inode.c:
-	Make header files always writable when the afpd mount option is given.
-	Otherwise it is impossible to unlock a locked file.
-
-	* TODO, inode.c:
-	Let afpd think chmod() always succeeds, so "New Folder" works right.
-
-	* super.c:
-	The 'afpd' mount option now makes 'fork=n,names=n' the default.
-
-	* TODO:
-	List the current known afpd-compatibility problems as bugs.
-
-	* file_hdr.c:
-	Make certain date changes through header files get written to disk.
-
-Sat Feb  1 02:24:12 1997  Paul H. Hargrove  <hargrove@sccm.stanford.edu>
-
-	* mdb.c:
-	Work around for Linux rounding device sizes to 1k increments.
-
-	* README.sgml:
-	Fixed a typo: "the a".
-
-Sat Dec 28 20:41:01 1996  Paul H. Hargrove  <hargrove@sccm.stanford.edu>
-
-	* TODO:
-	Add ioctl() interface as a "missing feature."
-
-	* dir_nat.c:
-	Finish implementing the afpd-compatibility
-	mode using the new 'afpd' mount option.
-
-	* hfs_fs_sb.h, super.c:
-	Add new 'afpd' mount option.
-
-	* file_cap.c:
-	Spelling fix.
-
-Wed Dec 11 23:16:08 1996  Paul H. Hargrove  <hargrove@sccm.stanford.edu>
-
-	* TODO, README.sgml:
-	Optimistically document the hybrid CD problem as fixed.
-
-	* part_tbl.c:
-	Fix the partition code so at least some of the hybrid
-	CDROMs that were previously rejected are now accepted.
-
-	* hfs.h:
-	Make fs_start a 32-bit integer rather than 16-bits.
-	The 16-bit value would overflow if a partition started
-	beyond the 32M mark (e.g. the Executor 2 Beta 1 CDROM).
-
-	* extent.c:
-	Fixed a typo in an error message.
-
-Tue Dec 10 14:43:46 1996  Paul H. Hargrove  <hargrove@sccm.stanford.edu>
-
-	* dir_nat.c:
-	Merge in the (still dormant) afpd-compatibility changes.
-
-	* inode.c:
-	Make the .AppleDouble directory writable (again).
-
-	* version.c, README.sgml:
-	Bump version up to "pre-0.8-3".
-
-	* hfs_fs.h, file_cap.c, file_hdr.c:
-	Move AFP constants to hfs_fs.h and prefix them with "HFS_".
-
-	* dir_nat.c, inode.c:
-	Back-out changes that allowed writing to the .AppleDouble directory.
-
-	* Makefile:
-	Update rules for linuxdoc-sgml v1.5.
-
-	* extent.c:
-	Fixed serious bug in decode_extent() with handling of empty extents.
-
-	* file.c:
-	Rewrote hfs_getblk().
-	It will no longer hang if hfs_extent_map() is buggy.
-	Also halves the worst-case number of calls to hfs_extent_map().
-
-	* extent.c:
-	Fixed serious bug in decode_extent() with handling of empty extents.
-
-	* hfs_fs.h:
-	Small change so the PPC (and maybe other architectures?)
-	pick up the prototypes for the user-space access functions.
-
-	* super.c, file_cap.c, file_hdr.c, hfs_fs.h, file.c:
-	Updated for new user-space memory interface.
-
-Sun Dec  8 11:49:36 1996  Paul H. Hargrove  <hargrove@sccm.stanford.edu>
-
-	* dir_nat.c:
-	Add special code for unlink(), and rename() in the .AppleDouble
-	directory and rmdir() of the .AppleDouble directory.
-
-	* inode.c:
-	Make the .AppleDouble directory writable.
-
-	* file_hdr.c:
-	Use AFP flags in version 1 headers (for Netatalk compatibility).
-
-	* trans.c:
-	Fixed bug with long names causing kernel Oops.
-
-Mon Oct  7 06:05:01 1996  Paul H. Hargrove  <hargrove@sccm.stanford.edu>
-
-	* hfs_fs.h, file_cap.c, file_hdr.c, hfs.h, extent.c, file.c, dir.c:
-	Fix types for various read/write/truncate computations.
-	Also allows compilation with 2.1.x kernels.
-
-Thu Sep 19 10:28:43 1996  Paul H. Hargrove  <hargrove@sccm.stanford.edu>
-
-	* README.sgml, version.c:
-	Bump version up to "pre-0.8-2".
-
-	* TODO:
-	Reformat the To Do list introducing prioritized categories.
-
-	* file_hdr.c, file.c:
-	Move comments about mmap() for headers from file.c to file_hdr.c.
-	Also revise the reasoning for not yet having it implemented.
-
-	* dir_nat.c, dir_cap.c, dir_dbl.c:
-	Remove 'hfs_' prefix from names of some purely local functions.
-
-	* dir_dbl.c, TODO:
-	Under AppleDouble make create(), mkdir(), mknod(), unlink(), rename()
-	and rename() check against header files when arguments start with '%'.
-
-	* super.c, hfs_fs_sb.h, hfs_fs.h, dir_dbl.c, dir_nat.c, dir_cap.c,
-	  dir.c, README.sgml:
-	Fix problem that prevented creating %RootInfo or .rootinfo in all
-	directories in addition to preventing deletion from the root directory.
-
-	* TODO:
-	Remove writable header files from the To Do list.
-
-	* README.sgml:
-	Add extensive discussion of writing to HFS filesystems and
-	the format of the special files.
-
-	* file_hdr.c:
-	Generate the 'homefs' field for version 1 header files.
-
-Wed Sep 18 23:07:45 1996  Paul H. Hargrove  <hargrove@sccm.stanford.edu>
-
-	* hfs_fs.h, file_cap.c:
-	Comment the definition of (struct hfs_cap_info).
-
-	* version.c, README.sgml:
-	Bump version up to "pre-0.8-1" and update the "How can I write?" FAQ.
-
-	* file_hdr.c:
-	Implement hdr_write() and hdr_truncate()!!
-
-	* hfs_fs_i.h, inode.c:
-	Make hdr_layout per-inode (not per-file) so hdr_truncate() will work.
-
-	* file.c, hfs.h, catalog.c, extent.c, balloc.c:
-	hfs_extent_adj() now uses fork->lsize to determine the target file size.
-
-Sun Sep 15 07:55:24 1996  Paul H. Hargrove  <hargrove@sccm.stanford.edu>
-
-	* README.sgml, trans.c:
-	Prevent creation of files & directories with '\0' or ':' in their names.
-
-	* string.c, hfs_fs.h, hfs.h, dir_dbl.c, dir_nat.c, dir_cap.c:
-	With case=lower could have run off end of string.
-
-Tue Sep 10 12:05:47 1996  Paul H. Hargrove  <hargrove@sccm.stanford.edu>
-
-	* inode.c:
-	Small clean up of HFS_FIL_LOCK handling.
-
-	* inode.c:
-	Fix notify_change() not to accidentally make metadata executable.
-
-	* hfs_fs.h:
-	AppleSingle files should have HFS_ITYPE_NORM.
-
-	* inode.c:
-	Return to old behavior where MdDat = i_mtime.
-
-	* dir_dbl.c:
-	Fix serious bug in hfs_dbl_readdir() that would lock-up access to a
-	directory if one tried to write to a directory they had previously read.
-
-	* file.c:
-	Fix hfs_do_write() to adjust the fork's 'lsize' if it changed.
-
-	* inode.c, file_cap.c:
-	Allow truncate() to be called even on metadata.
-	Any size changes will last only until the next iput() of the inode.
-	Truncating a header file doesn't yet truncate the resource fork.
-
-	* inode.c:
-	Allow chmod() on a directory if it doesn't actually change i_mode.
-
-	* hfs_fs.h, trans.c, super.c:
-	Rename hfs_cap2mac() to hfs_colon2mac().
-	Rename hfs_apl2mac() to hfs_prcnt2mac().
-
-	* file_hdr.c:
-	Move header construction out of hdr_read() to create hdr_build_meta().
-
-	* hfs.h:
-	Add byte-order independent conversions: U32->U16, U32->U8 and U16->U8.
-
-	* file.c, file_cap.c, hfs_fs.h:
-	Rename fix_perms() to hfs_file_fix_mode() and
-	move it from file_cap.c to file.c.
-
-	* README.sgml, super.c:
-	Make the default for the names mount option vary with the fork option.
-
-	* file_cap.c:
-	The umask was applied incorrectly in fix_perms().
-
-Mon Sep  9 13:11:28 1996  Paul H. Hargrove  <hargrove@sccm.stanford.edu>
-
-	* README.sgml:
-	Note that it compiles on m68k machines, but needs more testing.
-
-	* hfs_sysdep.h, Makefile:
-	Changes to compile unmodified on m68k (and possibly other machines).
-
-	* dir_cap.c:
-	hfs_cap_readdir() was mistakenly producing .rootinfo entries for
-	the .finderinfo and .resource subdirectories of the root directory.
-
-	* inode.c:
-	A directory's i_size was too small by 1 under CAP, so hfs_cap_readdir()
-	would omit the last directory entry.  i_nlink was also too large by 1.
-
-Sun Sep  8 12:56:06 1996  Paul H. Hargrove  <hargrove@sccm.stanford.edu>
-
-	* file_hdr.c:
-	Rewrite hdr_read() to be more efficient and to deal correctly with
-	descriptors having lengths that differ from the actual size of the data.
-
-	* file_cap.c:
-	Add write support for CAP finderinfo files!!
-
-	* super.c, inode.c, hfs_fs.h, hfs_fs_i.h, hfs_fs_sb.h, file_dbl.c,
-	  file_nat.c, file_hdr.c, file.c, file_cap.c, Makefile, dir.c:
-	Generate metadata (header files and CAP finderinfo files) on-the-fly.
-	The files file_{dbl,nat}.c are merged into file_hdr.c as a result.
-
-Sat Sep  7 08:09:24 1996  Paul H. Hargrove  <hargrove@sccm.stanford.edu>
-
-	* README.sgml:
-	Fix silly grammatical error.
-
-Fri Sep  6 09:17:12 1996  Paul H. Hargrove  <hargrove@sccm.stanford.edu>
-
-	* hfs_fs_sb.h, super.c:
-	No need to cast type of s_reserved.
-
-	* file_dbl.c, file_nat.c, dir_dbl.c, dir_nat.c, file_cap.c, dir_cap.c:
-	Add the missing NULL readpage and writepage entries to the inode_ops.
-
-	* file_dbl.c, file_nat.c, file.c, file_cap.c:
-	Cleanup error checking for read() and write().
-
-Thu Sep  5 05:29:53 1996  Paul H. Hargrove  <hargrove@sccm.stanford.edu>
-
-	* version.c, README.sgml:
-	Bump version up to "0.7.2".
-	User-visible changes from 0.7.0:
-	+ Corrected CAP finderinfo file format.
-	+ Support for more features of CAP finderinfo files.
-	+ No longer requires gcc 2.7.0 or newer.
-	+ Now implements mknod() system call.
-
-	* hfs_fs.h, dir_nat.c, file_cap.c, file_nat.c, README.sgml, dir_cap.c:
-	Include the CAP and Netatalk copyright notices.
-
-	* hfs_fs.h, file_cap.c:
-	Repair and improve CAP support.
-
-	* catalog.c:
-	Oops! The BkDat for new files and directories was in 1972 when
-	it should have been in 1904 (not that it matters that much).
-
-	* inode.c:
-	The HFS MdDat should be the larger of the i_mtime and i_ctime.
-
-	* README.sgml:
-	Change 'm_time' to 'i_mtime'.
-
-Wed Sep  4 13:27:35 1996  Paul H. Hargrove  <hargrove@sccm.stanford.edu>
-
-	* version.c, README.sgml:
-	Bump version up to "0.7.1".
-	User-visible changes from 0.7.0:
-	+ Minor bug in CAP finderinfo file format fixed.
-	+ No longer requires gcc 2.7.0 or newer.
-	+ Now implements mknod() system call.
-
-	* README.sgml:
-	Removed note about needing gcc 2.7.0 or newer.
-
-	* file.c:
-	Optimize hfs_do_read() based on the fact that HFS has no holes in files.
-	Minor code formatting changes.
-
-	* hfs.h, hfs_sysdep.h, mdb.c, extent.c, file.c, btree.c, catalog.c,
-	  balloc.c, bnode.c:
-	Reorganize memory management routines.
-	hfs_malloc() and hfs_free() are the main routines.
-	The macros FREE() and MALLOC() are gone.
-	HFS_NEW() and HFS_DELETE() are new 'shorthand' macros.
-
-	* btree.c:
-	Fix broken debugging code.
-
-	* super.c, hfs.h, mdb.c, part_tbl.c, Makefile:
-	Separate partition table handling into its own file.
-
-	* dir.c:
-	Spelling fixes.
-
-	* sysdep.c:
-	Oops!  Error check got sense reversed while editing.
-
-	* mdb.c, sysdep.c, hfs.h, hfs_btree.h, hfs_sysdep.h, btree.c, extent.c,
-	  bfind.c, bnode.c, balloc.c:
-	Make hfs_buffer a pointer to a buffer_head, rather than a buffer_head.
-
-	* hfs_fs.h, dir_cap.c, dir_dbl.c, dir_nat.c, dir.c:
-	Add a mknod() entry to the inode_operations for normal directories.
-	All it is good for is letting root create regular files.
-
-	* file_dbl.c, file_nat.c, file.c, file_cap.c, dir_cap.c, dir_dbl.c,
-	  dir_nat.c:
-	Add the missing NULL entries to the end of the file_operations.
-
-	* super.c, hfs_btree.h, hfs_fs.h, mdb.c, extent.c, hfs.h, catalog.c:
-	Make the remainder of the (untested) changes
-	to allow compilation with gcc 2.6.3.
-
-	* hfs_fs.h:
-	Fix hfs_fs.h to work with gcc 2.6.3.
-
-	* hfs_fs.h:
-	(struct hfs_cap_info) should never have been 'packed'.
-
-	* BUG_INFO:
-	Use -V for getting version of module utilities.
-
-	* super.c, sysdep.c, trans.c, hfs_fs_sb.h, inode.c, hfs_fs.h,
-	  hfs_fs_i.h, file_cap.c, file_dbl.c, file_nat.c, dir_dbl.c,
-	  dir_nat.c, file.c, dir.c, dir_cap.c:
-	Fix up hfs_fs{,_i,_sb}.h in preparation for inclusion in kernel.
-
-Tue Sep  3 23:58:03 1996  Paul H. Hargrove  <hargrove@sccm.stanford.edu>
-
-	* hfs.h:
-	Change eventual destination to linux/fs/hfs rather than include/linux.
-
-	* super.c, inode.c, mdb.c, hfs_btree.h, hfs_fs.h, hfs_sysdep.h,
-	  file_dbl.c, file_nat.c, hfs.h, dir_nat.c, extent.c, dir_dbl.c,
-	  catalog.c, dir_cap.c, brec.c, btree.c, binsert.c, bnode.c, bdelete.c,
-	  bfind.c, bins_del.c, balloc.c:
-	Replace all the swap{16,32}() stuff w/ ntohl() and friends.
-
-Fri Aug 30 09:51:23 1996  Paul H. Hargrove  <hargrove@sccm.stanford.edu>
-
-	* version.c, README.sgml:
-	Rewrite installation instructions and bump version up to "0.7.0".
-
-	* Makefile:
-	Remove the INCDIR variable; we now rely on the
-	user to have the correct links in /usr/include.
-
-Mon Aug 26 12:25:41 1996  Paul H. Hargrove  <hargrove@sccm.stanford.edu>
-
-	* version.c, README.sgml:
-	Reformat the documentation and bump version up to "pre-0.7-9".
-	Hopefully this will become version 0.7 in a few days.
-
-Thu Aug 22 08:00:44 1996  Paul H. Hargrove  <hargrove@sccm.stanford.edu>
-
-	* README.sgml, version.c:
-	Bump version up to "pre-0.7-8".
-
-	* file_nat.c, file_dbl.c:
-	AppleDouble headers had resource fork size in wrong byte order.
-
-Wed Aug 21 05:22:28 1996  Paul H. Hargrove  <hargrove@sccm.stanford.edu>
-
-	* version.c, README.sgml:
-	Bump version up to "pre-0.7-7".
-
-	* bnode.c:
-	Fixed a long-standing bug in hfs_bnode_lock().
-	This bug occasionally caused lock-up under heavy load.
-
-Tue Aug 20 09:15:10 1996  Paul H. Hargrove  <hargrove@sccm.stanford.edu>
-
-	* README.sgml, version.c:
-	Bump version up to "pre-0.7-6".
-
-	* catalog.c:
-	Fix a deadlock problem in catalog readers/writers locking.
-
-	* bins_del.c:
-	hfs_bnode_update_key() was still corrupting the header node sometimes.
-
-	* catalog.c, dir.c:
-	Fix problem with extending the catalog B-tree hanging hfs_cat_commit().
-	Fix a race that could delete a non-empty directory.
-
-Sun Aug 18 23:16:43 1996  Paul H. Hargrove  <hargrove@sccm.stanford.edu>
-
-	* version.c, README.sgml:
-	Bump version to "pre-0.7-5" for test release.
-
-	* dir_cap.c, README.sgml:
-	Change ".:rootinfo:" to ".rootinfo".
-
-	* hfs_fs.h, dir_cap.c, dir_dbl.c, dir_nat.c:
-	Mangle the names as first step in hfs_{cap,dbl,nat}_lookup().
-	Use the new hfs_streq() to catch mixed case matches to the special
-	files and directories in hfs_{cap,dbl,nat}_lookup().
-	Store reserved names only once.
-
-	* dir.c, hfs.h, string.c:
-	Implement hfs_streq() which tests for string equality more
-	rapidly than hfs_strcmp() by checking for equal length first,
-	and use it when checking for reserved names.
-
-	* inode.c, TODO, dir_cap.c, dir_dbl.c, README.sgml:
-	Provide the metadata for the root directory for the CAP and AppleDouble
-	schemes in the files ".:rootinfo:" and "%RootInfo", respectively.
-
-	* TODO, super.c:
-	Add (untested) support for the old Mac Plus style of partition map.
-
-	* bdelete.c, TODO:
-	Note the possibility of bdelete() to hanging on a corrupted B-tree.
-
-	* TODO:
-	Add items corresponding to some of the 'XXX' comments in the sources.
-
-	* dir_dbl.c, dir_cap.c:
-	Update comments, removing ref. to a comment that once existed in inode.c
-
-	* catalog.c:
-	Remove some redundant locking and error checks
-	that had been previously marked as questionable.
-
-Sat Aug 17 08:06:56 1996  Paul H. Hargrove  <hargrove@sccm.stanford.edu>
-
-	* binsert.c, bfind.c, bins_del.c, balloc.c, bdelete.c:
-	Edited some comments for correctness.
-
-	* README.sgml, version.c:
-	Bump version up to "pre-0.7-4" in preparation for snapshot release.
-
-	* Makefile:
-	Have 'make dep' delete the *.o and *.s files.
-
-	* catalog.c, hfs.h, TODO, bfind.c:
-	Move looping from hfs_cat_next() into hfs_bsucc(),
-	where it can be done an entire node at a time.
-
-Fri Aug 16 05:02:59 1996  Paul H. Hargrove  <hargrove@sccm.stanford.edu>
-
-	* TODO:
-	Add AppleShare support to the list of goals.
-
-	* trans.c, super.c, hfs_fs.h, README.sgml:
-	Add a "names=netatalk" mount option, since
-	Netatalk quotes initial periods and CAP doesn't.
-
-	* Makefile:
-	Oops! Had removed the 'include .depend' from Makefile.
-
-	* inode.c, hfs_fs.h, file_nat.c, file_dbl.c, file.c, dir_nat.c,
-	  dir_dbl.c, dir_cap.c, dir.c, README.sgml:
-	Update for 2.0.1 and newer kernels.
-
-	* Makefile:
-	Get rid of ifeq stuff and use a .tmpdepend file to make sure
-	a failed 'make depend' doesn't allow a 'make hfs.o'.
-
-Wed Aug 14 01:03:01 1996  Paul H. Hargrove  <hargrove@sccm.stanford.edu>
-
-	* version.c, README.sgml:
-	Bump version up to "pre-0.7-3" in preparation for snapshot release.
-
-	* btree.c, extent.c, bnode.c:
-	Fix up some debugging code.
-
-Tue Aug 13 12:42:12 1996  Paul H. Hargrove  <hargrove@sccm.stanford.edu>
-
-	* version.c, README.sgml:
-	Bump revision to "pre-0.7-2".
-
-	* super.c, sysdep.c, mdb.c, file_nat.c, inode.c, file_cap.c,
-	  file_dbl.c, file.c, extent.c, dir.c, catalog.c, btree.c, bnode.c,
-	  balloc.c:
-	Added the remaining missing function comments.
-
-	* Makefile, README.sgml:
-	Simplify the default make rule to build the dependency file AND hfs.o.
-	Change the installation instructions to reflect the change.
-
-	* hfs.h:
-	Added missing structure comments.
-
-	* bdelete.c:
-	Merge bdelete_brec() back into hfs_bdelete().
-	Add missing function comments.
-
-
-	* extent.c:
-	Insignificant code change removing an unneeded indirection.
-
-	* btree.c, hfs_btree.h, balloc.c, bnode.c:
-	Add a 'sys_mdb' field to (struct hfs_btree).
-
-	* extent.c, hfs_sysdep.h, sysdep.c, bnode.c, balloc.c, bfind.c,
-	  Makefile:
-	Move hfs_buffer_read() from hfs_sysdep.h to sysdep.c so it can use
-	the symbol HFS_SECTOR_SIZE rather than the manifest constant 512.
-	Have hfs_buffer_read() print an error message,
-	and remove redundant errors from the callers.
-
-	* hfs_sysdep.h, mdb.c, super.c, file.c, hfs.h, hfs_btree.h, catalog.c,
-	  extent.c, btree.c, balloc.c, bfind.c, bnode.c:
-	Get rid of the type hfs_device and the fields of that type,
-	using the type hfs_sysmdb and the 'sys_mdb' field in its place.
-
-	* Makefile:
-	Fix definition of HDRS variable.
-
-	* README.sgml, version.c:
-	Bump version up to "pre-0.7-1".
-
-	* Makefile:
-	Separate sources and headers into three groups:
-	B-tree code, HFS code and Linux code.
-
-	* bitmap.c, bitops.c, hfs.h, hfs_sysdep.h, balloc.c:
-	Implemented portable set of bit operations in hfs_sysdep.h
-
-	* mdb.c, hfs_sysdep.h, hfs_btree.h, extent.c, btree.c, bitmap.c,
-	  bnode.c, balloc.c:
-	Implement a portable set of buffer operations in hfs_sysdep.h
-
-	* TODO:
-	Remove note about separating header files into two parts.
-
-	* catalog.c:
-	Remove call to hfs_mdb_dirty(), since the hfs_brec_relse() does it.
-
-	* hfs.h, extent.c, file.c:
-	Move hfs_getblk() from extent.c to file.c, since that is now the
-	only file that actually uses it.
-
-	* balloc.c:
-	Replace use of hfs_getblk() in balloc.c with a local function
-	(get_new_node()) that doesn't retry, since B-trees can't shrink.
-
-	* hfs.h, hfs_btree.h, hfs_sysdep.h, mdb.c, extent.c:
-	Make hfs_buffer a typedef.
-
-	* inode.c, hfs.h, hfs_sysdep.h, dir.c:
-	Change hfs_sysentry to a typedef.
-	Rename 'sysentry' field of (struct hfs_cat_entry) to 'sys_entry'.
-
-	* super.c, mdb.c, catalog.c:
-	Rename hfs_cat_sync() to hfs_cat_commit() and call it
-	from hfs_mdb_commit() rather than from hfs_write_super().
-
-	* catalog.c, file.c:
-	Minimize the calls to hfs_mdb_dirty().   Now called when:
-	1) A buffer holding a volume bitmap block is dirtied.
-	2) A dirty B-tree node is written back to the buffers.
-	3) A dirty catalog entry is written back to the buffers.
-
-	* hfs_sysdep.h, hfs.h:
-	Make hfs_sysmdb a typedef.
-
-Sun Aug 11 08:46:10 1996  Paul H. Hargrove  <hargrove@sccm.stanford.edu>
-
-	* hfs_sysdep.h, extent.c, hfs.h:
-	Replace hfs_mdb_{lock,unlock} with more portable
-	scheme using a wait queue in the MDB.
-
-	* hfs.h, hfs_btree.h, hfs_sysdep.h, bnode.c, catalog.c, binsert.c:
-	Make hfs_wait_queue a typedef'd pointer to a (struct wait_queue).
-	Rename hfs_wait_on() to hfs_sleep_on().
-
-	* catalog.c, hfs_sysdep.h, super.c, bfind.c, bnode.c, balloc.c:
-	Implemented hfs_dev_name() in hfs_sysdep.h
-	as a portable call to produce a device name.
-
-	* super.c, hfs.h, mdb.c:
-	Rename hfs_mdb_read() to hfs_mdb_get(), and don't take a
-	'sys_mdb' argument.  That's the callers responsibility.
-
-	* sysdep.c, Makefile:
-	Remove the pointless file sysdep.c
-
-	* README.sgml:
-	Clean up the "System Requirements" section.
-
-Sat Aug 10 22:41:24 1996  Paul H. Hargrove  <hargrove@sccm.stanford.edu>
-
-	* sysdep.h, sysdep.c, super.c, hfs_sysdep.h, mdb.c, string.c,
-	  hfs_fs.h, hfs_fs_i.h, hfs_fs_sb.h, hfs_btree_private.h, hfs_btree.h,
-	  file_cap.c, file_dbl.c, file_nat.c, hfs.h, file.c, dir_nat.c,
-	  extent.c, dir.c, dir_cap.c, dir_dbl.c, catalog.c, bnode.c, brec.c,
-	  btree.c, binsert.c, bitmap.c, bitops.c, bfind.c, bins_del.c,
-	  Makefile, balloc.c, bdelete.c:
-	Includes the hfs.h that was missing from the previous check in.
-	MAJOR include-file cleanup:
-		hfs_btree.h merged into hfs.h
-		hfs_btree_private.h renamed hfs_btree.h
-		sysdep.h renamed hfs_sysdep.h
-	Fixed some minor portability fixes shown up by the header split.
-
-	* README.sgml:
-	Add instructions for a dealing with a missing linux/version.h
-
-	* hfs_fs.h, mdb.c, string.c, catalog.c, extent.c, btree.c, bitmap.c,
-	  bitops.c, bnode.c, brec.c, bins_del.c, binsert.c, bdelete.c, bfind.c,
-	  balloc.c:
-	Major split of hfs_fs.h into Linux-specific
-	part (hfs_fs.h) and HFS-specific part (hfs.h).
-
-	* file.c, extent.c:
-	Move hfs_getblk() from file.c to extent.c
-
-	* sysdep.h, super.c, mdb.c, hfs_fs_sb.h, hfs_fs.h, file.c, extent.c,
-	  catalog.c, bnode.c, bitmap.c:
-	Make the field 's_mdb' in (struct hfs_sb_info) a pointer to
-	the MDB, rather than the actual MDB.  This allowed the definition
-	of (struct hfs_mdb) to be moved from hfs_fs_sb.h to hfs_fs.h.
-
-	* ccache.c, hfs_fs.h, Makefile, catalog.c:
-	Merged ccache.c and catalog.c into the latter.
-	Moved definition of (struct hfs_cat_rec) into catalog.c
-
-	* extent.c:
-	Oops!  Last set of changes didn't compile but they're OK now.
-
-	* hfs_btree.h, hfs_fs.h, mdb.c, ccache.c, extent.c, btree.c:
-	Move the definition of (struct hfs_raw_extent) inside
-	extent.c and treat it as simple array of U16's elsewhere.
-
-	* hfs_fs.h, dir_dbl.c, dir_nat.c, ccache.c, catalog.c, dir_cap.c:
-	Make hfs_cat_next() return the CNID and cdrType of the entry.
-	Now catalog.c and ccache.c are the only files which
-	depend on the structure of a catalog record on disk.
-
-	* dir.c, hfs_fs.h, catalog.c:
-	Replace hfs_cat_new_{file,dir}() with hfs_cat_{create,mkdir}()
-	which are wrappers for what used to be hfs_cat_create().
-
-	* hfs_fs.h, mdb.c, super.c, Makefile:
-	Split super.c into super.c (Linux stuff) and mdb.c (MDB stuff).
-
-	* super.c, hfs_fs_sb.h:
-	Add the MDB field 'drAtrb' to (struct hfs_mdb) as the field 'attrib'.
-
-	* hfs_fs_sb.h, super.c:
-	Split hfs_read_super() into hfs_read_super() and hfs_mdb_read().
-
-	* super.c, hfs_fs_sb.h:
-	Remove the unneeded 'hs' field from (struct hfs_mdb).
-
-	* TODO:
-	Remove item about hfs_notify_change() needing to update metadata.
-
-	* inode.c, hfs_fs.h, hfs_fs_sb.h, file_cap.c, file_dbl.c, file_nat.c,
-	  file.c, dir.c:
-	Add a flags argument to hfs_{cap,dbl,nat}_buildmeta() so that
-	it only builds the parts that are currently out-of-date.
-	Call hfs_{cap,dbl,nat}_buildmeta() through hfs_update_meta()
-	in hfs_notify_change() and hfs_rename() to update the metadata.
-
-	* dir.c:
-	Make test for normal dir in update_dirs_{plus,minus}() more explicit.
-
-	* inode.c, file_cap.c, file_dbl.c, file_nat.c, dir_dbl.c, dir_nat.c,
-	  file.c, README.sgml, dir_cap.c:
-	Resolve the "meta-data" vs. "metadata" rivalry in favor of the latter.
-
-	* btree.c:
-	Simplify some debugging code.
-
-	* hfs_btree_private.h, bnode.c, btree.c, balloc.c:
-	Put the in-core copy of the header node IN the
-	B-tree structure rather than just a pointer to it.
-
-	* hfs_btree_private.h, btree.c, bnode.c:
-	Have hfs_btree_commit() call hfs_bnode_commit()
-	to commit the header and root nodes.
-
-	* hfs_fs.h, super.c, hfs_btree_private.h, btree.c, hfs_btree.h,
-	  balloc.c:
-	Change hfs_commit_mdb() to hfs_mdb_commit().
-	Make hfs_mdb_commit() call hfs_btree_commit().
-	Move code to update B-tree size and extent
-	from hfs_btree_extend() to hfs_btree_commit().
-	Make hfs_btree_extend() call hfs_mdb_commit().
-
-	* super.c:
-	Change hfs_commit_super() to hfs_commit_mdb().
-
-	* btree.c, bnode.c, bfind.c:
-	Fixed up broken debugging code and error messages.
-
-	* super.c, hfs_btree_private.h, btree.c, hfs_btree.h, bdelete.c,
-	  binsert.c, balloc.c:
-	Now use write-back caching of B-tree header fields.
-
-	* hfs_fs.h:
-	Get rid of the add{16,32}() inlines as they are no longer used.
-
-	* hfs_btree_private.h, binsert.c, btree.c, bdelete.c, bfind.c, balloc.c:
-	All the needed fields of the B-tree header are
-	now cached for reading, but not yet writing.
-
-	* TODO:
-	Remove "Implement write count" from TODO list.
-
-	* file.c, super.c, bnode.c:
-	Implement write count.
-
-	* catalog.c:
-	Fix directory entry counting in hfs_cat_move().
-
-	* balloc.c:
-	Simplify hfs_btree_extend(), since the allocation
-	request will get rounded up to the clumpsize.
-
-	* extent.c:
-	Honor clumpsize when allocating blocks to files.
-
-	* file_cap.c, file_dbl.c, file_nat.c, super.c, dir.c, file.c,
-	  ccache.c, catalog.c, balloc.c:
-	Mark 44 functions in need of commenting.
-
-	* hfs_fs_sb.h, super.c, extent.c, hfs_fs.h, ccache.c, btree.c, balloc.c:
-	Record clumpsize in allocation blocks rather than 512-byte blocks.
-
-	* sysdep.h, super.c, TODO, balloc.c, hfs_fs_sb.h:
-	Now updates the backup MDB when a B-tree grows.
-
-	* extent.c:
-	hfs_extent_free() had test against NULL backward.
-	The result is that access to a file with extents in the extents
-	B-tree would result in an infinite loop in hfs_cat_put().
-
-	* hfs_fs_sb.h, super.c, hfs_fs.h:
-	Reorganize partition map code to get size of partition
-	in preparation for dealing with the alternate MDB.
-
-Fri Aug  9 03:25:13 1996  Paul H. Hargrove  <hargrove@sccm.stanford.edu>
-
-	* Makefile:
-	Add make rules for README.{ps,info}
-
-	* README, README.sgml, DOC, FAQ, Makefile, .cvsignore, 
-	Merge CHANGES into ChangeLog.
-	Merge DOC, FAQ and README into README.sgml.
-	Add make rules for building README.{txt,dvi}
-
-	* BUG_INFO, Makefile:
-	Added a BUG_INFO script which attempts to collect some useful
-	information which I'd like to see in every bug report I receive.
-
-	* Makefile, version.c:
-	Added version.c which contains a version string.
-
-Thu Aug  8 21:48:24 1996  Paul H. Hargrove  <hargrove@sccm.stanford.edu>
-
-	* trans.c:
-	Fix Latin-1 -> Macintosh filename mapping to change colons to pipes.
-
-	* trans.c:
-	Fixed Mac->Latin-1 translation to behave as documented for the
-	extended 8-bit characters without corresponding Latin-1 characters.
-
-	* inode.c, super.c, file.c, hfs_fs_i.h, hfs_fs_sb.h, DOC:
-	Added a conv={binary,text,auto} mount option similar to that of the
-	msdos, hpfs and iso9660 filesystems, but applying only to data forks.
-	As compared to those filesystems, HFS has the advantage that only a
-	single CR need be converted to a NL, rather than a CR/NL sequence, so
-	it is quite safe to seek in the file.
-	Additionally the 'Type' field is far more reliable indicator of text
-	files than a file extension.
-
-	* super.c:
-	Simplified parsing of mount options.
-
-	* super.c:
-	Oops!  The part=<n> mount option was being parsed in octal!
-
-	* TODO:
-	Remove "case=lower" from the list of goals.
-
-	* super.c, hfs_fs.h, hfs_fs_sb.h, string.c, dir_dbl.c, dir_nat.c,
-	  dir_cap.c, DOC:
-	Resurrect the case={asis,lower} mount option.
-
-	* dir.c:
-	Simpler test for "normal" directory in update_dirs_{plus,minus}().
-
-	* hfs_fs_sb.h, super.c, dir.c, hfs_fs.h, catalog.c, DOC:
-	Add mount options to specify what Type and Creator will be used for
-	new files and change the default from NULLs to "????".
-
-Wed Aug  7 11:32:22 1996  Paul H. Hargrove  <hargrove@sccm.stanford.edu>
-
-	* catalog.c:
-	In hfs_cat_next() use entry->cnid rather than the key of the initial
-	brec to identify the end of the directory.
-
-	* README:
-	Update for pre-0.7 version.
-
-	* hfs_fs.h:
-	Create versioned module if CONFIG_MODVERSIONS is set in linux/config.h
-
-	* TODO:
-	Note need for special steps for unaligned accesses on some machines.
-
-	* FAQ:
-	Added Q0: What is HFS?
-	Added Q7: Does hfs_fs work w/ 400k and 800k diskettes?
-	Brought Q6 (about writability) up to date.
-	Made a few other answers more verbose.
-
-Tue Aug  6 00:58:46 1996  Paul H. Hargrove  <hargrove@sccm.stanford.edu>
-
-	* Makefile:
-	Changed 'snapshot' rule to include cvs tag command.
-
-	* hfs_fs.h, dir_cap.c, dir_dbl.c, dir_nat.c, catalog.c, ccache.c:
-	Implemented readers half of dir locking scheme so readdir() should
-	produce consistent results and count_dir_entries() is not race prone.
-
-	* catalog.c:
-	hfs_cat_move() was calling hfs_cat_decache() after changing
-	the key rather than before, corrupting the hash lists.
-
-Mon Aug  5 14:03:46 1996  Paul H. Hargrove  <hargrove@sccm.stanford.edu>
-
-	* hfs_fs.h, catalog.c:
-	Implemented the writers half of a locking scheme for directories.
-
-	* inode.c:
-	Fixed a serious bug in hfs_notify_change() that would allow a chmod()
-	on directory meta-data and would cause the directory inode (if it was
-	in memory at the time) to change into a file inode.
-
-	* inode.c:
-	Fixed a problem with write permissions on directory meta-data.
-
-	* dir_dbl.c, dir_nat.c, dir_cap.c:
-	hfs_{cap,dbl,nat}_readdir() now return the correct value in the 'd_ino'
-	field of the dirent for all cases, something I think has always been
-	done incorrectly until now.
-
-	* dir_nat.c, inode.c, dir_cap.c:
-	In hfs_{cap,nat}_lookup() take advantage of the
-	'file_type' field of (struct hfs_inode_info).
-
-	* TODO:
-	Removed two accomplished goals (rename() and improved readdir()).
-
-	* inode.c, dir_dbl.c, dir_nat.c, hfs_fs_i.h, dir.c, dir_cap.c:
-	Rewrite hfs_{cap,dbl,nat}_readdir() to take advantage of hfs_cat_next().
-	They now use a uniform 'i_size' for all inodes for a given directory.
-	This simplifies update_dirs_{plus,minus}() and eliminates the need for
-	the 'file_size' and 'dir_link' fields of (struct hfs_inode_info).
-	For the CAP and Netatalk schemes the meta-data directories are now the
-	last entries rather than coming just after '.' and '..'.  This is in
-	preparation for the day when we can write to the files in those
-	directories, and ensures that when using 'tar' to copy HFS filesystems
-	the file or directory will be created before the meta-data is written.
-	Otherwise we could be stuck writing meta-data and not knowing if it is
-	for a file or a directory!
-
-	* ccache.c:
-	Updated count_dir_entries() for new hfs_cat_next().
-
-	* hfs_fs.h, catalog.c:
-	hfs_cat{nth,next}() no longer take a 'types' argument,
-	so they now return all entries.
-	hfs_cat_next() now uses the ParID of the key to detect
-	the end of the directory.
-	hfs_cat_nth() now accepts n=0 as a valid input, requesting the thread.
-
-	* trans.c, string.c, super.c, dir_nat.c, hfs_fs.h, dir.c, dir_cap.c,
-	  dir_dbl.c, catalog.c:
-	Rename (struct hfs_cname) to the more appropriate (struct hfs_pstr).
-
-	* hfs_fs.h, hfs_btree.h:
-	Move some constants from hfs_fs.h to hfs_btree.h
-
-	* bdelete.c, hfs_btree.h:
-	Remove hfs_bdelete_brec() from public B-tree interface.
-
-	* hfs_btree_private.h, hfs_fs.h, btree.c, hfs_btree.h, bnode.c, brec.c,
-	  bfind.c, bins_del.c, binsert.c, balloc.c, bdelete.c, Makefile:
-	Split B-tree stuff into public and private parts:
-		brec.c split into bfind.c and brec.c
-		hfs_btree.h split into hfs_btree.h and hfs_btree_private.c
-
-	* inode.c:
-	The tests and sets of the HFS_FIL_LOCK bit where all reversed!
-
-	* hfs_fs.h, ccache.c:
-	Redo some ccache stuff, removing the 'error' field from
-	(struct hfs_cat_entry) and ensuring that hfs_cat_put()
-	will not sleep on an uninitialized entry.
-
-Sun Aug  4 23:43:28 1996  Paul H. Hargrove  <hargrove@sccm.stanford.edu>
-
-	* sysdep.h:
-	Change swap{16,32}() back to macros since hton[ls]() are functions.
-
-	* hfs_fs.h, ccache.c:
-	Use only lowest order byte of parent CNID in hashing a catalog key.
-
-	* bdelete.c:
-	The "improved" bdelete() was TOO paranoid looking for missing parents.
-
-	* ccache.c:
-	Get rid of pointless swap16const(0).
-
-	* hfs_fs.h, inode.c, extent.c, ccache.c, dir_cap.c, dir_nat.c,
-	  binsert.c, catalog.c:
-	Store cnid and associated constants in big-endian byte order.
-	This reduces the number of byte-order swaps required.
-
-	* sysdep.h:
-	Make swap32() and swap16() inline functions.
-
-	* dir_nat.c, dir_cap.c, dir_dbl.c:
-	Added hfs_rename() to the inode_operations for normal directories.
-
-	* dir.c, hfs_fs.h:
-	Added hfs_rename() and cleaned up hfs_{create,mkdir,unlink,rmdir}().
-
-	* catalog.c:
-	Added the missing check for moving a directory into itself.
-
-	* catalog.c, ccache.c, hfs_fs.h:
-	Implement a nearly ideal hfs_cat_move().
-	It still needs to prevent moving a directory into itself.
-	The functions hfs_cat_{create,delete,move}() still need work with
-	respect to their atomicity (especially vs. readdir).
-
-	* bdelete.c:
-	Fixed a serious bug in hfs_bdelete_brec() that would yield a corrupted
-	b-tree when the first record in a bnode was deleted.
-	Made bdelete() more aggressive when checking for missing parents.
-
-Sat Aug  3 06:11:50 1996  Paul H. Hargrove  <hargrove@sccm.stanford.edu>
-
-	* btree.c, super.c:
-	Fixed a problem that caused a kernel oops when no HFS filesystem
-	is found.
-
-Wed Jul 24 13:06:12 1996  Paul H. Hargrove  <hargrove@sccm.stanford.edu>
-
-	* catalog.c:
-	Remove race in hfs_cat_create() that could overflow directory valence.
-
-	* catalog.c:
-	Fix hfs_cat_create() so the parent directory doesn't get deleted
-	out from under it.  Otherwise we could have created files and
-	directories in deleted directories.
-
-	* hfs_fs.h, dir_cap.c, dir_dbl.c, dir_nat.c, catalog.c, ccache.c:
-	Redo hfs_cat_{next,nth}() in terms of which entry types to
-	allow, rather than which to skip.
-
-	* catalog.c:
-	The function hfs_cat_create() would fail to hfs_cat_put(entry) if
-	the 'record' argument was invalid or if the 'result' argument was NULL.
-
-	* dir.c:
-	The functions hfs_{create,mkdir,unlink,rmdir} all failed to
-	call iput() when their arguments conflicted with a reserved name.
-
-	* catalog.c, hfs_fs_sb.h:
-	Start over on rename().  Still unfinished.
-	Fix silly bug in hfs_cat_create() that made it always fail.
-
-	* ccache.c:
-	Fix byte-order bug in write_entry().
-
-Tue Jul 23 12:12:58 1996  Paul H. Hargrove  <hargrove@sccm.stanford.edu>
-
-	* dir_dbl.c, dir_nat.c, hfs_fs.h, dir.c, dir_cap.c:
-	Remove the macros KEY() and PARENT() since the key is now easy
-	to access through the catalog entry.
-	Replace the macros NAME{IN,OUT}() with inline functions
-	hfs_name{in,out}() to gain type checking of arguments.
-
-	* catalog.c:
-	Remove the macro TYPE().
-
-	* inode.c, file_dbl.c, file_nat.c, file.c, file_cap.c:
-	Remove the #define's of the unused macro KEY().
-
-	* hfs_fs.h, dir_cap.c, dir_dbl.c, dir_nat.c, catalog.c, dir.c:
-	Replace hfs_lookup_parent() in dir.c with hfs_cat_parent() in catalog.c.
-	This new function performs locking to protect against rename() changing
-		the parent during I/O.
-	It is also intended for use with files as well as directories.
-	Change hfs_{cap,dbl,nat}_lookup() to use the new function.
-
-	* dir.c, hfs_fs.h, catalog.c:
-	Remerge hfs_cat_{create,mkdir}() into hfs_cat_create() and resurrect
-		hfs_cat_new_{file,dir}().
-	Fix hfs_cat_{create,delete} to use the improved catalog cache for
-		locking in place of directory-level create/delete locks.
-	Fix hfs_{create,mkdir}() to use the new hfs_cat_create().
-
-	* hfs_fs.h, ccache.c:
-	Rewrite parts to remove need for specialized create/delete locking.
-	Use new case-independent hash function.
-	Fix bug in hfs_cat_get() that would read an entry w/o locking it.
-	Call hfs_relinquish() before retrying a deleted entry in hfs_cat_get.
-	If there is a read error, then don't retry in hfs_cat_get().
-	Remove unused 'version' field from (struct hfs_cat_entry).
-
-	* sysdep.h:
-	Add hfs_relinquish(), a system-independent alias for schedule().
-
-	* hfs_fs.h, string.c:
-	Add hfs_strhash(), a simplistic case-independent hash function.
-
-	* hfs_fs.h, inode.c:
-	Make hfs_iget() an inline function.
-
-	* TODO:
-	Add a few goals and removed those that have been achieved.
-
-	* Makefile:
-	Add ccache.c to list of source files.
-	Add rule for *.s files and include them in the 'clean' rule.
-
-Wed Jul 17 17:22:45 1996  Paul H. Hargrove  <hargrove@sccm.stanford.edu>
-
-	* sysdep.h, trans.c, string.c, super.c, hfs_fs_i.h, hfs_fs_sb.h,
-	  inode.c, hfs_btree.h, hfs_fs.h, file_dbl.c, file_nat.c, extent.c,
-	  file.c, file_cap.c, dir_dbl.c, dir_nat.c, ccache.c, dir.c,
-	  dir_cap.c, btree.c, catalog.c, bnode.c, brec.c, balloc.c:
-	Total rewrite of the inode-handling stuff to be centered around
-	a catalog entry cache (ccache.c).  This results not only in a far
-	more sensible way of doing things, but also removed many race
-	conditions. (The source and object code both got smaller too!)
-	Many small "undocumented features" were also fixed.
-	Replace HFS_CNAME with (struct hfs_cname).
-	rename() has been temporarily abandoned.
-
-Thu Jul 11 01:14:38 1996  Paul H. Hargrove  <hargrove@sccm.stanford.edu>
-
-	* dir.c:
-	As written hfs_lookup_parent() had two overlapping read requests
-	in the catalog tree.  This could have led to deadlock.
-
-Wed Jul 10 09:27:00 1996  Paul H. Hargrove  <hargrove@sccm.stanford.edu>
-
-	* catalog.c, hfs_fs.h, bdelete.c:
-	More work on getting rename() fleshed out.  Still not done.
-	Before I can finish it looks like I'll need to build a
-	mechanism for exclusive access to the catalog tree.  There
-	just doesn't seem to be any other way to get proper POSIX
-	semantics without a bunch of race conditions elsewhere.
-
-	* hfs_fs.h, inode.c, dir_cap.c, dir_dbl.c, dir_nat.c, catalog.c:
-	More work on the still incomplete rename() code.
-	Merge hfs_cat_add_{dir,file}() into hfs_cat_create().
-	Add file-thread support to hfs_cat_{create,delete,rename}.
-
-Tue Jul  9 09:43:15 1996  Paul H. Hargrove  <hargrove@sccm.stanford.edu>
-
-	* inode.c, dir_dbl.c, dir_nat.c, extent.c, dir_cap.c:
-	The indirect (struct hfs_file) was causing blocks not to be freed
-	when files where deleted, and an omission in hfs_put_inode() was
-	preventing the inode from getting freed.  Both are now fixed.
-
-	* hfs_fs.h, dir_dbl.c, dir_nat.c, hfs_btree.h, catalog.c, dir_cap.c,
-	  bdelete.c:
-	Made unlink() and rmdir() more race resistant and did some more
-	work on the still incomplete code for rename().
-
-	* btree.c, bnode.c:
-	There was a serious race condition in the bnode cache, so
-	hfs_bnode_find() is now modeled after Linus's inode cache.
-
-Mon Jul  8 10:33:38 1996  Paul H. Hargrove  <hargrove@sccm.stanford.edu>
-
-	* hfs_fs_i.h, inode.c, file_cap.c, file_dbl.c, file_nat.c, dir_dbl.c,
-	  dir_nat.c, file.c, dir.c, dir_cap.c:
-	More changes to layout of (struct hfs_inode_info).
-
-	* super.c, inode_cap.c, inode_dbl.c, inode_nat.c, inode.c, hfs_fs_i.h,
-	  hfs_fs_sb.h, file_nat.c, hfs_fs.h, file.c, file_cap.c, file_dbl.c,
-	  Makefile, catalog.c:
-	Implemented new layout for (struct hfs_inode_info) resulting in the
-	elimination of lots of duplicated code for hfs_*_write_inode(),
-	hfs_*_put_inode() and *_open() functions.
-	Merged inode_*.c files back into inode.c.
-	Not fully tested.
-
-	* TODO:
-	Add a few more of my goals to the list.
-
-	* README:
-	Documentation updates.
-
-	* inode_nat.c, inode_cap.c, inode_dbl.c, inode.c, hfs_fs.h, hfs_fs_i.h,
-	  file.c, file_cap.c, file_dbl.c, file_nat.c, catalog.c:
-	(struct hfs_file) and metadata are read when file is opened or
-	truncated and are released by iput().
-
-Sun Jul  7 23:55:43 1996  Paul H. Hargrove  <hargrove@sccm.stanford.edu>
-
-	* inode_nat.c, inode_cap.c, inode_dbl.c, inode.c, dir_nat.c, hfs_fs.h,
-	  hfs_fs_i.h, dir_cap.c, dir_dbl.c, catalog.c, dir.c:
-	(struct hfs_dir) is now inside (struct hfs_inode_info) once again.
-
-	* inode_nat.c, super.c, inode_cap.c, inode_dbl.c, inode.c, file_nat.c,
-	  hfs_btree.h, hfs_fs.h, extent.c, file_cap.c, file_dbl.c, dir_nat.c,
-	  dir_cap.c, dir_dbl.c, btree.c, catalog.c, dir.c, bpath.c, brec.c,
-	  bins_del.c, binsert.c, bnode.c, bfind.c, balloc.c, bdelete.c,
-	  Makefile:
-	Remerged (struct hfs_bpath) and (struct hfs_brec), merging the
-	files bfind.c and bpath.c as a resurrected brec.c.
-
-Sat Jul  6 21:47:05 1996  Paul H. Hargrove  <hargrove@sccm.stanford.edu>
-
-	* inode_cap.c, inode_dbl.c, inode_nat.c, inode.c, hfs_fs.h, hfs_fs_i.h,
-	  file_cap.c, file_dbl.c, file_nat.c, hfs_btree.h, dir_nat.c, extent.c,
-	  dir.c, dir_cap.c, dir_dbl.c, btree.c, catalog.c, bfind.c, bpath.c,
-	  binsert.c, bdelete.c:
-	Renamed (struct hfs_brec_key) to (struct hfs_bkey).
-
-Tue May 28 07:53:24 1996  Paul H. Hargrove  <hargrove@sccm.stanford.edu>
-
-	* inode_cap.c, catalog.c:
-	Spelling fixes.
-
-	* inode_nat.c, super.c, inode_cap.c, inode_dbl.c, inode.c, hfs_fs.h,
-	  hfs_fs_i.h, hfs_fs_sb.h, file.c, file_dbl.c, file_nat.c, dir_dbl.c,
-	  dir_nat.c, extent.c, dir.c, dir_cap.c, catalog.c:
-	Structures got too big, so I had to add a layer of indirection
-	to (struct hfs_inode_info).
-	This means we must clear_inode() in inode_put().
-
-Mon May 27 01:32:42 1996  Paul H. Hargrove  <hargrove@sccm.stanford.edu>
-
-	* catalog.c, file_cap.c:
-	Some sizeof() stuff now uses variable not type.
-
-	* hfs_fs.h:
-	Make HFS_I() and HFS_SB() inline to gain type checking.
-
-Sun May 26 13:34:17 1996  Paul H. Hargrove  <hargrove@sccm.stanford.edu>
-
-	* dir_nat.c:
-	Oops.  Had left some debugging printk()s in place.
-
-	* file_dbl.c, file_nat.c, file_cap.c:
-	Cleaned up variable names for consistency.
-
-	* hfs_fs_sb.h:
-	Add a couple 'const's to function typedefs.
-
-	* hfs_fs.h:
-	Add and update function prototypes.
-	Cleaned up type names.
-	Fix debugging malloc code.
-	Add hfs_iget_by_name() as an inline function.
-
-	* sysdep.h:
-	Remove extra semicolon from macro definitions.
-
-	* super.c:
-	Use new hfs_iget_by_name() to get root inode.
-
-	* extent.c:
-	Cleaned up some variable naming for consistency.
-
-	* catalog.c:
-	Added (untested) code for hfs_cat_move_file().
-
-	* catalog.c:
-	Fix one missed call to hfs_cat_build_key().
-	Make hfs_cat_add_{file,dir}() take a cat_entry as an argument.
-	Add hfs_cat_new_{file,dir}() to generate new cat_entry's.
-
-	* dir_dbl.c, dir_nat.c, dir.c, dir_cap.c:
-	Cleaned up type and variable names.
-	Updated calls to hfs_cat_build_key() and NAMEOUT()
-	Use new hfs_iget_by_*() calls.
-
-	* inode_cap.c, inode_dbl.c, inode_nat.c:
-	Cleaned up type and variable names.
-
-	* inode.c:
-	Update calls to hfs_cat_build_key().
-	Cleaned up type and variable names.
-	Implemented a hierarchy of hfs_iget_by*() calls.
-
-	* catalog.c:
-	Change hfs_cat_build_key() to take a HFS_CNAME as input.
-
-	* btree.c:
-	Initialize lsize and psize fields of file.
-
-	* trans.c:
-	Now passes type HFS_CNAME and has name/len in "normal" order.
-
-Tue May 21 07:02:34 1996  Paul H. Hargrove  <hargrove@sccm.stanford.edu>
-
-	* bnode.c:
-	Attempt to read invalid bnode would have led to an infinite loop under
-	certain circumstances.  One way to cause this was with an invalid
-	partition table which points beyond the end of the device.
-
-Sat May 11 12:38:42 1996  Paul H. Hargrove  <hargrove@sccm.stanford.edu>
-
-	* sysdep.h, sysdep.c, inode_dbl.c, inode_nat.c, super.c, inode_cap.c,
-	  inode.c, hfs_fs.h, hfs_fs_i.h, hfs_fs_sb.h, file_dbl.c, file_nat.c,
-	  hfs_btree.h, extent.c, file.c, file_cap.c, dir_nat.c, dir.c,
-	  dir_cap.c, dir_dbl.c, btree.c, catalog.c, bitmap.c, bitops.c,
-	  bnode.c, bfind.c, bins_del.c, binsert.c, balloc.c, bdelete.c:
-	Another big wave of portability-oriented changes.
-
-Tue May  7 11:28:35 1996  Paul H. Hargrove  <hargrove@sccm.stanford.edu>
-
-	* super.c, sysdep.c, sysdep.h, inode_cap.c, inode_dbl.c, inode_nat.c,
-	  hfs_fs_i.h, inode.c, file_nat.c, hfs_btree.h, hfs_fs.h, file.c,
-	  file_cap.c, file_dbl.c, dir_nat.c, extent.c, dir_cap.c, dir_dbl.c,
-	  btree.c, catalog.c, dir.c, bnode.c, bpath.c, binsert.c, bitmap.c,
-	  bitops.c, bdelete.c, bfind.c, bins_del.c, Makefile, balloc.c:
-	Start a big move to abstract all the Linux-specific stuff
-	out of the lower levels.  Created sysdep.[ch] to hold it.
-
-	* FAQ, TODO:
-	Bring some documentation up-to-date.
-
-Fri May  3 20:15:29 1996  Paul H. Hargrove  <hargrove@sccm.stanford.edu>
-
-	* super.c, inode_dbl.c, inode_nat.c, inode.c, inode_cap.c, extent.c,
-	  hfs_fs.h, hfs_fs_i.h, dir_dbl.c, dir_nat.c, catalog.c, dir.c,
-	  dir_cap.c, bpath.c, btree.c, binsert.c, bnode.c:
-	"FID reform": 'fid' became 'cnid' (Catalog Node ID), and is now
-	a field in (struct hfs_file).  The new name is more consistent
-	with Apple's documentation.  The presence of 'cnid' in (struct
-	hfs_file) help move more of the code toward OS-independence.
-
-	* inode_nat.c, super.c, trans.c, inode.c, inode_cap.c, inode_dbl.c,
-	  hfs_fs.h, file_cap.c, file_dbl.c, file_nat.c, dir_nat.c, extent.c,
-	  file.c, dir.c, dir_cap.c, dir_dbl.c, btree.c, catalog.c, bnode.c,
-	  bpath.c, bins_del.c, binsert.c, bitmap.c, bitops.c, bdelete.c,
-	  bfind.c, balloc.c:
-	A lot of changes in what headers are included and in what order.
-
-Sat Apr 27 12:28:54 1996  Paul H. Hargrove  <hargrove@sccm.stanford.edu>
-
-	* FAQ:
-	Updated for current writability status.
-
-	* .cvsignore:
-	Added ChangeLog.
-
-	* file_dbl.c, file_nat.c, file_cap.c, file.c, dir_dbl.c, dir_nat.c,
-	  dir_cap.c:
-	Added the default fsync() to all file_operations structures.
-
-	* dir_nat.c, hfs_fs.h, dir.c, dir_cap.c, dir_dbl.c:
-	Add rmdir() for normal directories.
-
-	* binsert.c:
-	I had messed up insertion so that is would sometime fail to
-	split the root, but its OK now.
-
-	* dir.c:
-	hfs_do_unlink() decremented directory counts rather than file counts.
-
-Wed Apr 24 13:20:08 1996  Paul H. Hargrove  <hargrove@sccm.stanford.edu>
-
-	* hfs_fs.h, bnode.c, hfs_btree.h:
-	Fixed a couple more type size assumptions.
-
-	* hfs_fs.h, balloc.c, bitmap.c, bitops.c:
-	"Portable" bitmap handling was wrong for just about everything but
-	the i386 and the "inverse big-endian" bit ordering that I thought
-	the m68k port was using.  It seems the m68k port is now using standard
-	big-endian bit-numbering conventions.
-	This code is now correct for the standard big- and little-endian bit
-	orderings. (which should cover all Linux systems?)
-	Also no longer assumes sizeof(long) == 4, though that might still be
-	a problem in other parts of the code.
-
-Tue Apr 23 19:19:27 1996  Paul H. Hargrove  <hargrove@sccm.stanford.edu>
-
-	* FAQ:
-	Bring uptodate for this snapshot.
-
-	* Makefile:
-	Add FAQ to $(MISC)
-
-	* README, TODO:
-	Documentation updates.
-
-	* bdelete.c:
-	Spelling fixes.
-
-	* dir_cap.c:
-	In unlink() don't force metadata into memory if not present.
-
-	* bdelete.c:
-	Some function comments and some clean up.
-
-	* bins_del.c:
-	Added missing function comment for hfs_bnode_update_key().
-
-	* binsert.c, bitmap.c:
-	Spelling and grammar corrections to comments.
-
-	* hfs_btree.h, hfs_fs.h, bins_del.c, binsert.c, Makefile, bdelete.c:
-	Clean up of hfs_bdelete(), splitting bins_del.c into three files:
-		bins_del.c, binsert.c and bdelete.c
-
-	* bpath.c, bins_del.c:
-	hfs_bdelete() is now working "correctly", but needs some cleaning up.
-
-Mon Apr 22 05:35:41 1996  Paul H. Hargrove  <hargrove@sccm.stanford.edu>
-
-	* hfs_fs.h, bpath.c, hfs_btree.h, bins_del.c, bnode.c, balloc.c,
-	  bfind.c:
-	Rewrite bnode handling, heading toward a more write-behind approach.
-	Have done away with HFS_LOCK_BLIND.
-
-	* inode_dbl.c, inode_nat.c, extent.c, hfs_fs_i.h, inode_cap.c:
-	Was trying to truncate resource fork of directories!
-
-Sun Apr 21 08:15:43 1996  Paul H. Hargrove  <hargrove@sccm.stanford.edu>
-
-	* balloc.c:
-	Updated to use truncate() to grow full trees.
-
-	* extent.c, hfs_fs.h, file.c, inode.c:
-	Added truncate() for normal files.
-
-	* bins_del.c:
-	hfs_bdelete() fixes for handling removal of root.
-
-	* inode_cap.c, inode_dbl.c, inode_nat.c:
-	Release storage for deleted files in hfs_*_put_inode().
-
-	* bitmap.c:
-	Make len=0 valid for hfs_{set,clear}_vbm_bits().
-
-	* super.c, inode.c, hfs_fs_i.h, hfs_fs_sb.h, btree.c, balloc.c:
-	Changed from clumpsize to clumpblks.
-
-	* inode_nat.c, hfs_fs.h, inode_cap.c, inode_dbl.c, btree.c, extent.c,
-	  balloc.c:
-	Some extent-related changes in preparation for truncate() support.
-
-Sat Apr 20 10:59:13 1996  Paul H. Hargrove  <hargrove@sccm.stanford.edu>
-
-	* inode_nat.c, hfs_fs_i.h, inode.c, inode_cap.c, inode_dbl.c,
-	  dir_nat.c, hfs_fs.h, dir.c, dir_cap.c, dir_dbl.c:
-	Removed dir.valence from hfs inode.
-	Added unlink(), but still need truncate() and some more support
-	in hfs_*_put_inode() to free the disk space used by deleted files.
-
-	* bnode.c:
-	Check for NULL bnode in hfs_bnode_relse().
-
-	* bins_del.c:
-	Fixed a byte-order problem in bdelete_nonempty().
-
-	* hfs_fs.h, bnode.c, bpath.c, hfs_btree.h, balloc.c, bins_del.c:
-	First attempt at hfs_bdelete().
-
-	* dir.c:
-	The Finder would display strange things if it couldn't set frView.
-	Therefore initialize frView field for new directories.
-
-	* file_cap.c, file_dbl.c, file_nat.c, hfs_fs.h:
-	Define User/Finder info fields of catalog entry in more detail.
-
-	* hfs_fs.h:
-	HFS_BFIND_DELETE should require exact match.
-
-	* dir.c:
-	Set "record in use" bit of filFlags for new files.
-
-	* inode.c:
-	Was doing the wrong thing with i_ctime.
-
-	* dir_nat.c, dir_cap.c, dir_dbl.c:
-	Added some missing updates to the inode in hfs_*_{create,mkdir}().
-
-Sun Apr 14 00:10:52 1996  Paul H. Hargrove  <hargrove@sccm.stanford.edu>
-
-	* hfs_fs.h, file_dbl.c, file_nat.c, file.c:
-	Work around the ever-changing type of f_reada.
-
-Sat Apr 13 00:43:41 1996  Paul H. Hargrove  <hargrove@sccm.stanford.edu>
-
-	* bpath.c, bfind.c:
-	Spelling corrections in comments.
-
-	* bins_del.c:
-	ifdef out shift_left() until it is actually used.
-
-	* hfs_btree.h, hfs_fs.h, bins_del.c, bpath.c, bfind.c:
-	Cleaned up code related to 'flags' argument to hfs_bpath_find().
-
-Fri Apr 12 23:30:01 1996  Paul H. Hargrove  <hargrove@sccm.stanford.edu>
-
-	* bpath.c:
-	Updated comments.
-	Rewrote hfs_bpath_init() and hfs_bpath_next().
-
-	* hfs_btree.h:
-	Updated prototype for hfs_bpath_init().
-
-	* bins_del.c:
-	Updated call to hfs_bpath_init().
-
-	* inode.c, inode_cap.c, inode_dbl.c, inode_nat.c, extent.c, file_cap.c,
-	  file_dbl.c, file_nat.c, dir_cap.c, dir_dbl.c, dir_nat.c, catalog.c,
-	  dir.c:
-	Renamed hfs_brec_relse() to hfs_brelse().
-
-	* hfs_fs.h, hfs_btree.h:
-	Updated prototypes to reflect new names in bpath.c
-
-	* bins_del.c:
-	Updated calls to functions in bpath.c
-	Updated comments.
-
-	* Makefile:
-	Renamed brec.c to bpath.c
-
-	* bfind.c:
-	Updated calls to functions in bpath.c
-	Added hfs_brelse() which was previously hfs_brec_relse() in brec.c
-
-	* bpath.c:
-	brec.c renamed to bpath.c
-	Functions renamed to reflect their current actions.
-	Comments are still out of date.
-	hfs_brec_relse() renamed to hfs_brelse() and moved to bfind.c
-
-	* brec.c:
-	brec.c renamed to bpath.c
-
-Wed Apr 10 07:20:28 1996  Paul H. Hargrove  <hargrove@sccm.stanford.edu>
-
-	* hfs_fs.h, extent.c, hfs_btree.h, brec.c, dir.c, bfind.c,
-	  bins_del.c:
-	Backed-out changes to hfs_binsert() that added the ability to
-	return the new record, since it will probably not ever be needed.
-
-	* extent.c:
-	Since 1.3.45 truncate() has locked the file, so there is no need
-	for all the things I've been doing to hfs_file_extend() & new_extent().
-	Those two functions have been cleaned up a bit (similar to older forms).
-
-	* extent.c:
-	hfs_file_extend() now more "robust", but new_extent() is still
-	not fully "concurrency safe."
-
-Tue Apr  9 09:01:18 1996  Paul H. Hargrove  <hargrove@sccm.stanford.edu>
-
-	* bins_del.c:
-	Made split() inline.
-
-	* inode.c, dir_nat.c, hfs_fs.h, dir_cap.c:
-	Added hfs_itry() to get in-core inodes.
-
-	* inode_dbl.c, inode_nat.c, hfs_fs.h, inode.c, inode_cap.c, file_dbl.c,
-	  file_nat.c, hfs_btree.h, extent.c, file_cap.c, dir_cap.c, dir_dbl.c,
-	  dir_nat.c, brec.c, catalog.c, dir.c, bins_del.c, bnode.c,
-	  bfind.c:
-	Rewrite of all the (struct hfs_brec) stuff.
-
-Mon Apr  8 21:50:01 1996  Paul H. Hargrove  <hargrove@sccm.stanford.edu>
-
-	* btree.c, extent.c, bnode.c:
-	Fixed format strings in a few debugging printk()'s.
-
-	* brec.c, hfs_fs.h:
-	Removed hfs_brec_relse_one().
-
-	* hfs_fs.h, bnode.c, brec.c, hfs_btree.h, bfind.c, bins_del.c, balloc.c:
-	(struct hfs_bnode_ref)s are now returned by value rather than reference
-	and they are in (struct hfs_brec) rather than pointed to.  Cuts down on
-	a lot of kmalloc() and kfree() traffic.
-
-	* hfs_fs.h, dir.c, extent.c, bins_del.c:
-	Modified hfs_binsert() to be able to return the new record.
-
-	* bins_del.c, hfs_btree.h:
-	Added shift_left(), still untested.
-
-	* bins_del.c:
-	new_root() was missing its comment.
-
-	* super.c, trans.c, hfs_fs_i.h, inode.c, inode_dbl.c, inode_nat.c,
-	  file_nat.c, hfs_btree.h, hfs_fs.h, file.c, file_dbl.c, dir_dbl.c,
-	  dir_nat.c, extent.c, dir.c, dir_cap.c, bitops.c, bnode.c, brec.c,
-	  bfind.c, bins_del.c, bitmap.c, balloc.c:
-	Fixed lines over 80 characters and tabified files.
-
-	* bins_del.c:
-	Fixed line(s) over 80 columns.
-
-	* trans.c, inode_nat.c, string.c, super.c, inode.c, inode_cap.c,
-	  inode_dbl.c, hfs_fs_i.h, hfs_fs_sb.h, hfs_btree.h, hfs_fs.h, file.c,
-	  file_cap.c, file_dbl.c, file_nat.c, dir_dbl.c, extent.c, btree.c,
-	  dir_cap.c, bitops.c, bnode.c, brec.c, bfind.c, bins_del.c, bitmap.c,
-	  DOC, README, TODO, balloc.c, CHANGES:
-	About 150 spelling corrections.
-
-Sun Apr  7 23:14:28 1996  Paul H. Hargrove  <hargrove@sccm.stanford.edu>
-
-	* dir_cap.c, dir_dbl.c, dir_nat.c, dir.c:
-	Cleaned-up check for special names in mkdir().
-
-	* extent.c:
-	More verbose error message.
-
-	* inode_dbl.c, inode_nat.c, hfs_fs_i.h, inode.c, inode_cap.c, dir.c,
-	  hfs_fs.h:
-	Limit directories to 32767 entries, since Mac uses 16-bit integer.
-
-Fri Apr  5 07:27:57 1996  Paul H. Hargrove  <hargrove@sccm.stanford.edu>
-
-	* FAQ:
-	Initial version.
-
-	* dir_dbl.c, dir_nat.c, bins_del.c, dir.c, dir_cap.c:
-	Added missing function comments.
-
-Wed Apr  3 06:38:36 1996  Paul H. Hargrove  <hargrove@sccm.stanford.edu>
-
-	* brec.c:
-	Cleaned-up code for brec->flags.
-
-	* extent.c:
-	Added function comments.
-
-	* bins_del.c:
-	Added function comments.
-	hfs_binsert() was incrementing record count even on failure.
-
-Mon Apr  1 08:35:51 1996  Paul H. Hargrove  <hargrove@sccm.stanford.edu>
-
-	* extent.c:
-	Rewrote find_ext() and new_extent() for new hfs_btree_extend().
-	Moved hfs_btree_extend() to balloc.c
-	Fixed potential kernel OOPS in new_extent().
-
-	* brec.c:
-	Fixed potential kernel OOPS in hfs_brec_get_root().
-	Removed hfs_brec_find_first().
-	Fixed return value of hfs_brec_find().
-
-	* bins_del.c:
-	Updated call to hfs_btree_extend().
-
-	* balloc.c:
-	Merged hfs_bnode_add() and hfs_btree_extend() into the later.
-	Commented init_mapnode().
-
-	* bfind.c:
-	Removed hfs_bfind_first().
-
-	* hfs_fs.h, hfs_btree.h:
-	Updated prototypes.
-
-Sat Mar 30 22:56:47 1996  Paul H. Hargrove  <hargrove@sccm.stanford.edu>
-
-	* CHANGES, README, TODO:
-	Updated documentation in preparation for 0.6 release.
-
-	* inode.c, hfs_fs.h:
-	Got rid of HFS_FAKE_EXEC in favor of noexec mount option.
-
-	* inode.c, super.c, DOC, hfs_fs_sb.h:
-	Added "quiet" mount option, like the fat filesystem.
-
-	* inode.c, dir_cap.c, dir_nat.c:
-	Pseudo-directories are read-only (at least for now).
-
-	* hfs_fs.h, dir_dbl.c, dir_nat.c, dir.c, dir_cap.c:
-	mkdir() updated to check against reserved names, but the
-	AppleDouble scheme still has problems with names starting with '%'.
-
-	* dir_dbl.c, dir_nat.c, hfs_fs.h, dir.c, dir_cap.c:
-	Added mkdir(). (It only took 2 tries to get it right!!)
-	Only works in "normal" directories and doesn't yet stop
-	one from creating dirs with the reserved names.
-
-	* brec.c, extent.c, bins_del.c:
-	Now have a way to get an EEXIST back from hfs_binsert().
-
-	* btree.c, inode.c, hfs_fs_i.h, file.c, bfind.c, bnode.c, balloc.c:
-	Added 'dev' field to struct hfs_file.
-
-	* hfs_fs_i.h, inode.c, btree.c, extent.c, file.c, bnode.c, brec.c,
-	  balloc.c:
-	Removed duplicated fields from struct hfs_file since
-	even B*-trees now have that information in the inode.
-
-	* extent.c:
-	zero_blocks() neglected allocation block size in computing start.
-
-Fri Mar 29 16:04:37 1996  Paul H. Hargrove  <hargrove@sccm.stanford.edu>
-
-	* super.c:
-	hfs_statfs(): f_files and f_ffree fields are now -1, which is
-	documented as the value for "undefined" fields in struct statfs.
-
-	* trans.c, inode_nat.c, string.c, super.c, inode_dbl.c, inode_cap.c,
-	  inode.c, file_nat.c, file_dbl.c, file_cap.c, file.c, dir_dbl.c,
-	  extent.c, dir_cap.c, catalog.c, btree.c, brec.c, bnode.c, bitops.c,
-	  bitmap.c, bins_del.c, balloc.c:
-	Stylistic editing: {} for all 'for', 'while' and 'if' blocks.
-	I hope I didn't screw-up anything.
-
-	* hfs_fs.h, dir.c, dir_cap.c, dir_dbl.c, dir_nat.c:
-	Added creation of normal files to all three fork schemes!
-	Strange things may happen when trying to create "non-normal" files.
-
-	* brec.c:
-	Cleaned up some debugging code.
-
-	* hfs_fs_i.h:
-	File and directory counts could have overflown 16-bit integer.
-
-	* hfs_btree.h:
-	Added HFS_BREC_RIGHT to help fix insertion problem.
-
-	* extent.c:
-	Various fixes to hfs_{file,btree}_extend().
-
-	* catalog.c:
-	Made hfs_build_cat_key() more "correct".
-
-	* btree.c:
-	Added and fixed debugging code.
-
-	* brec.c:
-	Fixed overflow detection.
-	Added some debugging code.
-
-	* bnode.c:
-	Dirtied some buffers in places that might have been missed.
-	Fixed some debugging code that had broken.
-
-	* bitops.c:
-	hfs_count_free_bits() was running off end of bitmap.
-
-	* bins_del.c:
-	Fixed various bugs, mostly related to variable-length keys.
-
-	* balloc.c:
-	Had forgotten to set a bit in new mapnodes.
-	Node counts were overflowing 16-bit integers.
-
-	* bitmap.c:
-	Oops! clear/set did opposite operation on full words.
-
-Wed Mar 27 10:59:07 1996  Paul H. Hargrove  <hargrove@sccm.stanford.edu>
-
-	* hfs_fs_i.h:
-	Updated struct hfs_extent for concurrent access.
-	Also caused a slight modification to struct hfs_file.
-
-	* hfs_fs.h, hfs_btree.h:
-	Added/updated prototypes.
-
-	* balloc.c:
-	hfs_bnode_alloc() finished but still untested.
-
-	* bins_del.c:
-	Fixed up deadlock avoidance in hfs_binsert() again.
-	Perhaps I even got it right this time.
-
-	* extent.c:
-	hfs_file_extend() now safe under concurrent operations?
-
-	* file.c:
-	hfs_getblk() now safe under concurrent operations?
-
-Tue Mar 26 23:26:35 1996  Paul H. Hargrove  <hargrove@sccm.stanford.edu>
-
-	* btree.c:
-	Added call to hfs_extent_trim() to fix memory leak.
-
-	* extent.c:
-	Oops, had left a "#define static" in from debugging.
-
-	* bins_del.c:
-	hfs_binsert() rewritten to avoid deadlock when extending
-	the extents B*-tree.
-
-	* btree.c:
-	Moved hfs_btree_extend() to extent.c
-
-	* inode_nat.c, inode_cap.c, inode_dbl.c:
-	hfs_*_put_inode() rewritten to call hfs_extent_trim().
-
-	* extent.c:
-	Big rewrite for new struct hfs_extent:
-		Now keep linked list of extents.
-		Cache is now a pointer to a list element.
-		Now have 'end' field to aid decode_extent().
-	New functions:
-		hfs_extent_trim(): frees linked list.
-		hfs_btree_extend(): for extending B*-trees.
-	Improved debugging output.
-
-	* balloc.c:
-	Added hfs_bnode_add() (incomplete and uncommented).
-
-	* btree.c:
-	Moved some work from hfs_btree_extend() to hfs_bnode_add().
-
-	* bfind.c:
-	Added hfs_bfind_first() as wrapper for hfs_brec_find_first().
-
-	* brec.c:
-	Added hfs_brec_find_first() to search first leaf node.
-
-	* bins_del.c:
-	Added error returns to hfs_binsert() and binsert().
-
-	* bins_del.c:
-	Check to see that we really need ancestors before starting.
-	Check that hfs_btree_alloc() gave us enough nodes.
-	binsert() uses info precomputed by hfs_binsert().
-
-Mon Mar 25 11:33:53 1996  Paul H. Hargrove  <hargrove@sccm.stanford.edu>
-
-	* bnode.c:
-	Collected together the error returns in hfs_bnode_lock().
-
-	* Makefile:
-	Added ChangeLog to $(MISC).
-
-Wed Mar 20 19:41:45 1996  Paul H. Hargrove  <hargrove@sccm.stanford.edu>
-
-	* super.c, hfs_fs.h, file.c, dir_dbl.c, dir_nat.c, dir.c, dir_cap.c:
-	Removed support for kernels older than about 1.3.70
-	Most of that support had been broken recently anyway.
-
-	* super.c:
-	Fixed so DEBUG_MEM works w/o DEBUG_ALL.
-	Updated call to hfs_btree_init().
-
-	* hfs_fs.h:
-	Updated/added prototypes.
-
-	* hfs_btree.h:
-	HFS_BFIND_CHAIN removed.
-	struct hfs_brec gets new 'flags' field with bits:
-		HFS_BREC_{FIRST,OVERFLOW,UNDERFLOW,UNINITIALIZED}
-	Removed bitmap size constants.
-	Changes to struct hfs_btree:
-	        'file' and 'cache' now structs rather than pointers.
-		Added 'reserved' field (used during insertion).
-		Added pointers to size and extent in MDB.
-
-	* file.c:
-	Made hfs_getblk() public.
-	Removed (fil->inode == NULL) special cases.
-
-	* extent.c:
-	{find,update}_ext() are no longer inline.
-	new_extent() fails when called for the extents tree;
-		previously it would hanging calling hfs_binsert().
-	extend_file():
-		renamed to hfs_file_extend() and made public.
-		fixed to work for B*-trees.
-		zeros-out blocks as they are allocated.
-		fixed bugs for (allocation block) != (physical block).
-
-	* btree.c:
-	hfs_btree_{init,free}() modified for changes to struct:
-		'file' and 'cache' moved back into structure
-		file.inode initialized to reduce special cases
-	hfs_btree_init() gets pointer to size in MDB instead of size.
-	Added hfs_btree_extend() (incomplete and uncommented).
-
-	* bnode.c:
-	hfs_bnode_{alloc,free}() moved to separate file.
-	Removed 'const' from some function arguments
-		due to change in struct hfs_btree.
-	hfs_bnode_lock(): added WRITE/RESRV->READ transition.
-
-	* brec.c:
-	hfs_brec_get_{root,child}() now take a 'keep_mask' argument
-		indicating when to keep ancestor nodes, and store
-		information about why ancestors were kept.
-	HFS_BFIND_CHAIN eliminated in favor of HFS_BFIND_{INSERT,DELETE}
-		which are now implemented using 'keep_mask'.
-	Added hfs_brec_relse_one() that doesn't release ancestors.
-
-	* bins_del.c:
-	Lots of rewrites to cleanup insertion.
-	Now tries to extend tree before insertion starts.
-	binsert() iterative rather than recursive.
-	No point in keeping track as it is still not "stable".
-
-	* balloc.c:
-	New file: started with hfs_bnode_{free,alloc}()
-	Added hfs_bnode_init() to initialize a newly allocated bnode.
-	hfs_bnode_free():
-		Renamed hfs_bnode_bitop().
-		Can set or clear a specified bit.
-		Gets bitmap sizes from nodes directly.
-	hfs_bnode_alloc():
-		Returns actual node, calling hfs_bnode_init().
-		Gets bitmap sizes from nodes directly.
-
-	* bfind.c:
-	Removed obsolete comment from hfs_bsucc()
-	Removed 'const' from tree arg of hfs_bfind()
-		due to changes in struct hfs_btree.
-
-	* Makefile:
-	Added new file: balloc.c
-
-Sat Mar  9 22:03:53 1996  Paul H. Hargrove  <hargrove@sccm.stanford.edu>
-
-	* Start of detailed CVS logging.
-
-Mar 09, 1996: snapshot-09Mar96 hargrove@sccm.stanford.edu (Paul H. Hargrove)
-	NOT AN OFFICIAL RELEASE
-	Fixed up debugging code that was broken by split of btree.c
-	Added debugging kmalloc/kfree
-	Fixed memory leak in hfs_bnode_relse()
-
-Mar 08, 1996: snapshot-08Mar96 hargrove@sccm.stanford.edu (Paul H. Hargrove)
-	NOT AN OFFICIAL RELEASE
-	now reset blocksize on device when done.
-	hfs_binsert done (except for the full tree case).
-	btree.c split up into manageable pieces (need to sort out hfs_btree.h)
-
-Feb 26, 1996: snapshot-26Feb96 hargrove@sccm.stanford.edu (Paul H. Hargrove)
-	NOT AN OFFICIAL RELEASE
-	Some writability.
-	Bug with multiple opens of meta data fixed.
-	Netatalk support no longer considered experimental.
-
-Virtually everything has changed, so I've lost track here.
-
-Nov 16, 1995: snapshot-16Nov95 hargrove@sccm.stanford.edu (Paul H. Hargrove)
-	NOT AN OFFICIAL RELEASE
-	Still more comments.
-	btree.c back to 80 columns.  will do same to other files soon.
-	Starting with btree.c have begun to put file contents into some
-		sort of standard order.
-	Moved metadata reading to VFS open() routine and now free it in
-		the VFS release() routine.  Much cleaner than the old way.
-	Unified hfs_iget by shifting scheme-dependent code into a function
-		pointer in the superblock.  This could/should be shifted to
-		a VFS read_inode() routine if that can be done cleanly.
-	Probably lots of other changes; I've lost track.
-
-Nov 05, 1995: version 0.5.3 hargrove@sccm.stanford.edu (Paul H. Hargrove)
-	NOT AN OFFICIAL RELEASE
-	1.2.x compatibility removed
-	Added lots of comments to btree.c and cleanup some code.  The result
-		is that the source file doubled in size while the object
-		file dropped in size by 20%.
-	Added some comments to super.c and dir.c as well.
-	Cleaned up some stuff in dir.c adding some additional error checking
-		and moving closer to using a unified hfs_iget by migrating
-		common code into lookup_parent().
-	Changed btree.c to use a separate bnode cache per filesystem.
-	Renamed a bunch of the bnode functions in btree.c
-
-Jun 29, 1995: version 0.5.2 hargrove@sccm.stanford.edu (Paul H. Hargrove)
-	BUG FIX and 1.3.x-compatibility release.
-	Will compile under 1.2.x or 1.3.x by changing one line in Makefile.
-	Started adding magic numbers to structures for "safety".
-	Don't strip internal symbols when linking or loading, as this made
-		good bug reports rather difficult.
-	Fixed a bug that could cause the fs to lock-up after trying to open
-		a non-existent file.
-	Fixed a bug that allowed files to appear truncated, when in fact it
-		is still not possible to truncate a file.
-	Added more/better comments to header files.
-	Deal with volume and b-tree bitmaps in preparation for writing.
-	Fixed readdir() to deal properly with the case where the directory
-		changes while writing to user-space. (which can't yet
-		actually happen, until directories are writable).
-
-Jun 23, 1995: version 0.5.1 hargrove@sccm.stanford.edu (Paul H. Hargrove)
-	BUG FIX RELEASE
-	Removed two debugging messages that didn't belong.
-	Fixed a typo that prevented modified inodes from being written to disk.
-	Added a missing line which prevented rmmod'ing sometimes.
-	Added a missing line which caused errors when modifying .finderinfo or
-		.resource under the CAP system.
-	Added a notify_change() to keep mode bits sensible, and to cause
-		changes to an inode to affect the data fork and resource fork
-		of a file together.
-
-Jun 22, 1995: version 0.5 hargrove@sccm.stanford.edu (Paul H. Hargrove)
-	Fixed a bug that was giving wrong values for i_blocks
-	Partly writable (can only 'touch' existing files, so far)
-	Removed case= mount option.  It will be back eventually.
-	Can now deal with CDROMs (and hard disks?), many thanks to
-		Holger Schemel for this work.
-	Latin-1 filename conversion also due to Holger Schemel.
-	Rewritten btree operations.
-
-Feb 28, 1995: version 0.4 hargrove@sccm.stanford.edu (Paul H. Hargrove)
-	Requires Linux >= 1.1.94: depends on changes made to asm/byteorder.h
-	Now using string comparison code donated by ARDI (see string.c)
-	Code reorganized to use data structures more like ARDI's.
-	More code reorganization to abstract the btree operations.
-	Added the fork= mount option.
-	Added AppleDouble support.  Executor, from ARDI, can now run programs
-		from HFS filesystems mounted with the HFS module.
-
-Jan 28, 1995: version 0.3 hargrove@sccm.stanford.edu (Paul H. Hargrove)
-	Major code reorganization.
-	Known for certain to work ONLY on floppies.
-	Started caching extents, so got faster on long file reads.
-	Now compiles separate from kernel tree.
-	Supports 5 filename conversion methods.
-	Supports forks, using the method from CAP.
-	All external symbols now start with HFS_ or hfs_
-
-Jan 12, 1995: version 0.2 hargrove@sccm.stanford.edu (Paul H. Hargrove)
-	Should now work on all HFS volumes, but still only tested on floppies.
-	Got smaller and faster with some code reorganization.
-	Since Linus moved htons() and friends to an asm file, should now be
-	 truly endian-independent, but still only tested on Intel machines.
-	Requires Linux >= 1.1.77, since Linus moved htons().
-
-Jan 05, 1995: version 0.1 hargrove@sccm.stanford.edu (Paul H. Hargrove)
-	First release.
-	1.44Mb floppies only
-	no resource forks
-	trivial name mangling only
-	read only
-	for Linux >= 1.1.75
--- diff/fs/hfs/FAQ.txt	2002-10-16 04:26:43.000000000 +0100
+++ source/fs/hfs/FAQ.txt	1970-01-01 01:00:00.000000000 +0100
@@ -1,342 +0,0 @@
-  Frequently Asked Questions about the HFS filesystem for
-  Linux
-  Paul H. Hargrove, hargrove@sccm.Stanford.EDU
-  version 1.0.3, 27 Apr 1997
-
-  This document provides answers to some of the most frequently asked
-  questions about the HFS filesystem for Linux.  It is currently pretty
-  rough and totally unorganized.  Corrections, additions and clarifica-
-  tions are appreciated.  The most current version of this document is
-  kept on The HFS for Linux Page <http://www-sccm.Stanford.EDU/~har-
-  grove/HFS/>.
-  ______________________________________________________________________
-
-  Table of Contents:
-
-  1.      What is this FAQ about?
-
-  2.      What is HFS?
-
-  3.      How I mount AppleShare volumes?
-
-  4.      What is the current version of the HFS filesystem.
-
-  5.      How stable is the current version?
-
-  6.      Is there a mailing list for discussion of the HFS filesystem?
-
-  7.      What version of Linux do I need to be running?
-
-  8.      Will it run on my (your processor type here)?
-
-  9.      Will it run under (your non-Linux operating system here)?
-
-  10.     Why can I mount some HFS CDROMs but not others?
-
-  11.     What does ``only 1024-char blocks implemented (512)'' mean?
-
-  12.     Why do I get a message about a bad or unknown partition table?
-
-  13.     Can I mount multiple HFS partitions from the same Macintosh
-  disk?
-
-  14.     In what ways can I write to HFS filesystems?
-
-  15.     Does the HFS filesystem work with 400 kB or 800 kB Macintosh
-  diskettes?
-
-  16.     How can I format an HFS filesystem?
-
-  17.     How can I fsck an HFS filesystem?
-
-  18.     Why do I get ``error -50'' messages from my Mac when using
-  netatalk?
-
-  19.     Why does my Macintosh show generic application and document
-  icons?
-
-  20.     How owns all the copyrights and trademarks? ;-)
-
-  20.1.   This Document
-
-  20.2.   The Software
-
-  20.3.   Trademarks
-  ______________________________________________________________________
-
-  11..  WWhhaatt iiss tthhiiss FFAAQQ aabboouutt??
-
-  This FAQ is about the HFS filesystem for Linux, which is available in
-  two forms.  The stand-alone version (called hfs_fs) is a Linux kernel
-  loadable module implementing the Macintosh HFS filesystem.  The HFS
-  filesystem is also included in some distributions of the Linux kernel
-  source (in the directory linux/fs/hfs).  This version can be compiled
-  as a loadable module or compiled into the kernel.
-
-  Either version allows a machine running Linux to read and write disks
-  from a Macintosh (almost) as though they were native Linux disks.
-
-  22..  WWhhaatt iiss HHFFSS??
-
-  HFS stands for ``Hierarchical File System'' and is the filesystem used
-  by the Mac Plus and all later Macintosh models.  Earlier Macintosh
-  models used MFS (``Macintosh File System''), which is not supported.
-
-  33..  HHooww II mmoouunntt AApppplleeSShhaarree vvoolluummeess??
-
-  The HFS filesystem is for mounting local filesystems only.  There is
-  an experimental afpfs by Ben Hekster heksterb@acm.org available from
-  http://www.odyssey.co.il/~heksterb/Software/afpfs/.
-
-  44..  WWhhaatt iiss tthhee ccuurrrreenntt vveerrssiioonn ooff tthhee HHFFSS ffiilleessyysstteemm..
-
-  As of version 1.0.3 of this FAQ, version 0.95 is the most recent.  You
-  can always find the most recent version on The HFS for Linux Page
-  <http://www-sccm.Stanford.EDU/~hargrove/HFS/>.  Announcements of new
-  versions are made to the comp.os.linux.announce newsgroup.
-
-  55..  HHooww ssttaabbllee iiss tthhee ccuurrrreenntt vveerrssiioonn??
-
-  Version 0.95 is considered to be ``beta'' software, so I recommend
-  making backups of anything important before you start playing.  It is
-  relatively free of bugs due to lots of testing of the previous
-  releases.
-
-  After a suitable period without new bugs the I will consider the
-  software to be ``stable'' and the version number will jump to 1.0.
-
-  66..  IIss tthheerree aa mmaaiilliinngg lliisstt ffoorr ddiissccuussssiioonn ooff tthhee HHFFSS ffiilleessyysstteemm??
-
-  There is no mailing list devoted exclusively to the HFS filesystem.
-  However, announcements of new versions are posted to the ``linux-
-  atalk'' and ``hfs-interest'' lists.  I will see bug reports sent to
-  those lists but e-mail is more reliable (hargrove@sccm.Stanford.EDU).
-
-  To subscribe to hfs-interest send e-mail with a body of ``subscribe
-  hfs-interest (your e-mail address)'' to majordomo@ccs.neu.edu.
-
-  To subscribe to linux-atalk send e-mail with a body of ``SUBSCRIBE
-  LINUX-ATALK (Your full name)'' to listserv@netspace.org.
-
-  77..  WWhhaatt vveerrssiioonn ooff LLiinnuuxx ddoo II nneeeedd ttoo bbee rruunnnniinngg??
-
-  To compile and use the stand-alone distribution of the HFS filesystem
-  you will need Linux kernel version 2.0.1 or newer compiled with
-  modules enabled (CONFIG_MODULES).  To compile you will need the kernel
-  headers which match the kernel you are running.  This is covered in
-  more detail in the installation instructions in INSTALL.txt.
-
-  If your kernel came with HFS in the kernel source tree then HFS should
-  work with your Linux version.  There may be small problems with a few
-  of the development kernel releases.  For these releases check the HFS
-  for Linux Page <http://www-sccm.Stanford.EDU/~hargrove/HFS/> for
-  patches.
-
-  88..  WWiillll iitt rruunn oonn mmyy ((yyoouurr pprroocceessssoorr ttyyppee hheerree))??
-
-  The code is carefully written to be independent of your processor's
-  word size and byte-order, so if your machine runs Linux it can run the
-  HFS filesystem.  However some younger ports don't yet have support for
-  loadable modules.
-
-  Note that HFS is tested most extensively on Intel platforms.  So there
-  could be subtle compilation problems on other platforms.  If you
-  encounter any that are not addressed by the documentation then please
-  let me know.
-
-  99..  WWiillll iitt rruunn uunnddeerr ((yyoouurr nnoonn--LLiinnuuxx ooppeerraattiinngg ssyysstteemm hheerree))??
-
-  No.  There is a port in progress to NetBSD.  I know of no other active
-  porting attempts.  If you are interested in porting the HFS filesystem
-  to another Unix-like operating system, I am interested in providing
-  what guidance I can.
-
-  1100..  WWhhyy ccaann II mmoouunntt ssoommee HHFFSS CCDDRROOMMss bbuutt nnoott ootthheerrss??
-
-  In the past there was a known incompatibility with some ``hybrid''
-  CDROMs that appear as HFS disks on Macs and as ISO9660 disks on other
-  systems.  I think I have fixed the problem.  So, if you encounter this
-  particular problem or have problems with specific non-hybrid CDROMs
-  please e-mail me with the title and manufacturer of the CD.
-
-  1111..  WWhhaatt ddooeess ````oonnllyy 11002244--cchhaarr bblloocckkss iimmpplleemmeenntteedd ((551122))'''' mmeeaann??
-
-  This message comes from the kernel and indicates that an attempt was
-  made to read a 512-byte block from a device that doesn't support
-  512-byte blocks.  The HFS filesystem only works with 512-byte blocks,
-  and therefore doesn't function with these devices.  Eventually it may
-  be able to use 1024-byte (or even 2048-byte) blocks when necessary.
-  Ideally the device driver should be enhanced to support 512-byte
-  blocks so that the various filesystems which need 512-byte blocks
-  don't each need to work around it.
-
-  1122..  WWhhyy ddoo II ggeett aa mmeessssaaggee aabboouutt aa bbaadd oorr uunnkknnoowwnn ppaarrttiittiioonn ttaabbllee??
-
-  If your Linux kernel doesn't understand Macintosh partition tables it
-  gives this warning when it can't find a partition table it recognizes.
-  To support partitioned media with such kernels, decoding of Mac
-  partition tables is done by the HFS filesystem so you should still be
-  able to mount the disk.  However, to do so you will need to mount the
-  raw device (such as /dev/sdb instead of /dev/sdb4) and use the part
-  mount option to indicate which partition you want.
-
-  1133..  CCaann II mmoouunntt mmuullttiippllee HHFFSS ppaarrttiittiioonnss ffrroomm tthhee ssaammee MMaacciinnttoosshh ddiisskk??
-
-  Only if your kernel understands Macintosh partition tables.  It the
-  kernel doesn't understand the Macintosh partition table, the HFS
-  filesystem must access the raw device.  Therefore, the kernel thinks
-  the entire drive is in use and prevents additional mounts on it.
-
-  1144..  IInn wwhhaatt wwaayyss ccaann II wwrriittee ttoo HHFFSS ffiilleessyysstteemmss??
-
-  The HFS filesystem is as capable as the MS-DOS or VFAT filesystems,
-  except that certain things can only be done with a file's data fork.
-
-  You ccaann:
-
-  +o  Create, delete and rename directories and data forks of files with
-     the caveat that names are case insensitive (so foo and Foo are the
-     same file or directory).
-
-  +o  Run Linux executables or shared libraries on an HFS disk if they
-     are stored in the data fork of a file.
-
-  +o  Read, write and truncate both forks of files and the Finder's
-     metadata of files and directories.
-
-  +o  Mmap data forks of files (and the resource fork if the filesystem
-     is mounted with the fork=cap option).
-
-  +o  Toggle the 'w' permission bits (as a group) of data forks.
-
-  +o  Change the i_mtime of files and directories.
-
-  You ccaannnnoott:
-
-  +o  Create, delete or rename resource forks of files or the Finder's
-     metadata.  Note, however, that they are created (with defaults
-     values), deleted and renamed along with the corresponding data fork
-     or directory.
-
-  +o  Run Linux executables or shared libraries on an HFS disk if they
-     are stored in the resource fork of a file.
-
-  +o  Mmap the Finder's metadata (when fork=cap) or AppleDouble header
-     files (when fork=double or fork=netatalk).
-
-  +o  Change permissions on directories.
-
-  +o  Change the uid or gid of files or directories.
-
-  +o  Set the set-uid, set-gid or sticky permission bits.
-
-  +o  Create multiple links to files.
-
-  +o  Create symlinks, device files, sockets or FIFOs.
-
-  1155..  DDooeess tthhee HHFFSS ffiilleessyysstteemm wwoorrkk wwiitthh 440000kk oorr 880000kk MMaacciinnttoosshh
-  ddiisskkeetttteess??
-
-  Yes and no.  The software is fully capable of dealing with HFS disks
-  of any size.  However, the 400k and 800k diskettes are written in a
-  physical format that is incompatible with most non-Macintosh floppy
-  drives.  Note also that almost all 400k Macintosh diskettes are MFS,
-  not HFS.
-
-  1166..  HHooww ccaann II ffoorrmmaatt aann HHFFSS ffiilleessyysstteemm??
-
-  Robert Leslie (rob@mars.org) has written a package for working with
-  HFS filesystems (like mtools plus a graphical interface).  One program
-  in the package is hformat which can format HFS filesystems.  The
-  latest version can be found on the HFS Utilities home page
-  <http://www.mars.org/home/rob/proj/hfs/>.
-
-  1177..  HHooww ccaann II ffsscckk aann HHFFSS ffiilleessyysstteemm??
-
-  Right now you'll have to use a Macintosh to do this.  However, Rob
-  Leslie is working on an fsck for HFS filesystems.
-
-  1188..  WWhhyy ddoo II ggeett ````eerrrroorr --5500'''' mmeessssaaggeess ffrroomm mmyy MMaacc wwhheenn uussiinngg
-  nneettaattaallkk??
-
-  To be compatible with netatalk's afpd you will need to use netatalk
-  version 1.4b1 or newer and mount the HFS filesystem with the ``afpd''
-  mount option.  More information is provided in the ``afpd'' subsection
-  of the ``Mount Options'' section of the HFS documentation (HFS.txt if
-  you have the stand-alone HFS distribution or
-  linux/Documentation/filesystems/hfs.txt if HFS is in your kernel
-  source tree.)
-
-  1199..  WWhhyy ddooeess mmyy MMaacciinnttoosshh sshhooww ggeenneerriicc aapppplliiccaattiioonn aanndd ddooccuummeenntt
-  iiccoonnss??
-
-  When using the ``afpd'' mount option the Desktop database on the disk
-  is not made available to Netatalk's afpd.  Because of this mounting an
-  HFS filesystem across the network to a Macintosh may result in the
-  Finder showing generic application and document icons.  Additionally
-  double clicking on a document will fail to start the correct
-  application.
-
-  If the disk is writable you can make Netatalk build a new Desktop
-  database in its own format by holding down the Option key while
-  selecting the volume in the Chooser.  If the disk is not writable then
-  these problems can be worked around by copying the application to a
-  local disk on the Macintosh.
-
-  2200..  HHooww oowwnnss aallll tthhee ccooppyyrriigghhttss aanndd ttrraaddeemmaarrkkss?? ;;--))
-
-  2200..11..  TThhiiss DDooccuummeenntt
-
-  This document is Copyright (c) 1996, 1997 by Paul H. Hargrove.
-
-  Permission is granted to make and distribute verbatim copies of this
-  document provided the copyright notice and this permission notice are
-  preserved on all copies.
-
-  Permission is granted to copy and distribute modified versions of this
-  document under the conditions for verbatim copies above, provided a
-  notice clearly stating that the document is a modified version is also
-  included in the modified document.
-
-  Permission is granted to copy and distribute translations of this
-  document into another language, under the conditions specified above
-  for modified versions.
-
-  Permission is granted to convert this document into another media
-  under the conditions specified above for modified versions provided
-  the requirement to acknowledge the source document is fulfilled by
-  inclusion of an obvious reference to the source document in the new
-  media. Where there is any doubt as to what defines ``obvious'' the
-  copyright owner reserves the right to decide.
-
-  2200..22..  TThhee SSooffttwwaarree
-
-  The HFS filesystem software is Copyright (c) 1994-1997 by Paul H.
-  Hargrove.
-
-  The software is free software; you can redistribute it and/or modify
-  it under the terms of the GNU General Public License as published by
-  the Free Software Foundation; either version 2, or (at your option)
-  any later version.
-
-  The software is distributed in the hope that it will be useful, but
-  WITHOUT ANY WARRANTY; without even the implied warranty of
-  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-  General Public License for more details.
-
-  You should have received a copy of the GNU General Public License
-  along with the software in the file ``COPYING''; if not, write to the
-  Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139,
-  USA.
-
-  2200..33..  TTrraaddeemmaarrkkss
-
-  +o  ``Finder'' is a trademark of Apple Computer, Inc.
-
-  +o  ``Apple'', ``AppleShare'', and ``Macintosh'' are registered
-     trademarks of Apple Computer, Inc.
-
-  +o  ``MS-DOS'' is a registered trademarks of Microsoft Corporation.
-
-  +o  All other trademarks are the property of their respective owners.
-
--- diff/fs/hfs/HFS.txt	2002-10-16 04:27:07.000000000 +0100
+++ source/fs/hfs/HFS.txt	1970-01-01 01:00:00.000000000 +0100
@@ -1,1042 +0,0 @@
-  Macintosh HFS Filesystem for Linux
-  Paul H. Hargrove, hargrove@sccm.Stanford.EDU
-  version 0.95, 28 Apr 1997
-
-  This document describes version 0.95 of the Macintosh HFS filesystem
-  for Linux.  The most current versions of this document and the
-  software are kept at The HFS for Linux Page
-  <http://www-sccm.Stanford.EDU/~hargrove/HFS/>.
-  ______________________________________________________________________
-
-  Table of Contents:
-
-  1.      Introduction
-
-  2.      Mounting HFS Filesystems
-
-  2.1.    afpd
-
-  2.2.    case={asis, lower}
-
-  2.3.    conv={auto, binary, text}
-
-  2.4.    creator=cccc
-
-  2.5.    fork={cap, double, netatalk}
-
-  2.6.    gid=n
-
-  2.7.    names={7bit, 8bit, alpha, cap, latin, netatalk, trivial}
-
-  2.8.    part=n
-
-  2.9.    quiet
-
-  2.10.   type=cccc
-
-  2.11.   uid=n
-
-  2.12.   umask=n
-
-  3.      Writing to HFS Filesystems
-
-  3.1.    Writing with fork=cap
-
-  3.2.    Writing with fork=double
-
-  3.3.    Writing with fork=netatalk
-
-  4.      A Guide to Special File Formats
-
-  4.1.    CAP .finderinfo Files
-
-  4.2.    AppleDouble Header Files
-
-  5.      Reporting Bugs
-
-  5.1.    What Goes in a Bug Report
-
-  5.2.    How to Report a Kernel Oops or GPF
-
-  6.      Legal Notices
-
-  6.1.    This Document
-
-  6.2.    The Software
-
-  6.2.1.  The Columbia AppleTalk Package for UNIX
-
-  6.2.2.  Netatalk
-
-  6.3.    Trademarks
-  ______________________________________________________________________
-
-  11..  IInnttrroodduuccttiioonn
-
-  This software implements the Macintosh HFS filesystem under Linux.  It
-  allows you to read and write HFS filesystems on floppy disks, CDROMs,
-  hard drives, ZIP drives, etc.  It is _n_o_t an AppleShare client.
-
-  If you use this software, please send me a note telling of your
-  success or failure with it.  Your feedback lets me know that this
-  project is not a waste of my time.
-
-  This code is still experimental, so backup anything important before
-  you start playing.  I'd like you to know that I've never lost any
-  files while using this software, or I would not release it.  However,
-  a ``better safe than sorry'' attitude is probably best.
-
-  If, for instance, the buffer cache were to become corrupted you could
-  start losing things on other disks.  Because of this, if you get a
-  General Protection Fault, or a kernel Oops, I _s_t_r_o_n_g_l_y recommend that
-  you reboot before writing any files.
-
-  22..  MMoouunnttiinngg HHFFSS FFiilleessyysstteemmss
-
-  Once you have the HFS filesystem compiled into the kernel or installed
-  as a loadable module, you will be able to use hfs as a filesystem type
-  option to mount.  For instance, to mount a Macintosh floppy disk on
-  the directory /mnt using the default mount options you would execute
-  ``mount -t hfs /dev/fd0 /mnt''.
-
-  The remainder of this section describes the several mount options
-  available to control how the HFS filesystem is mapped onto a Linux
-  filesystem structure.  The values for the multiple-choice options
-  (case, conv, fork and names) can be abbreviated by their first
-  character.
-
-  22..11..  aaffppdd
-
-  If included in the options, then the behavior of the filesystem is
-  changed to make it fully read-write compatible with Netatalk's afpd.
-  In this mode you should not use normal user-level tools to modify the
-  filesystem, though reading from it is acceptable.  This is because the
-  return codes from some system calls are changed to fool afpd.  These
-  changes will confuse many user-level tools.  In particular ``rm -r''
-  will loop forever.
-
-  This option implies fork=netatalk, which in turn implies
-  names=netatalk.  If either of these options are explicitly set to
-  something else they will take precedence and will confuse afpd.  The
-  quiet option has no effect.  The case= option functions normally, but
-  afpd usually does the same thing for you.  The conv= and part= options
-  also function normally.
-
-  You will probably want to use the uid=, gid= and umask= mount options.
-  Note that because all the files on an HFS filesystem belong to a
-  single user and group and have a single umask, the full AppleShare
-  permission scheme will not work through Netatalk.
-
-  One additional limitation is that the Desktop database on the disk is
-  stored in afpd's format and is separate from any existing database
-  maintained by the Finder when the volume is used on a Macintosh.
-  Because of this mounting an HFS CDROM across the network to a
-  Macintosh may result in applications and documents showing up with
-  default application and document icons.  Additionally double clicking
-  on a document will fail to start the correct application.  Both of
-  these problems can be worked around by copying the application to a
-  local disk on the Macintosh.
-
-  This mode is known to be compatible with afpd from Netatalk versions
-  1.4b1 and 1.4b2, and known to be incompatible with the afpd from
-  version 1.3.3.  As of this writing Netatalk version 1.4 has not yet
-  been released.  However, it is expected that this mode will be
-  compatible with afpd from Netatalk version 1.4 when it is released.
-
-  22..22..  ccaassee=={{aassiiss,, lloowweerr}}
-
-  default value: asis
-
-  This option determines if Macintosh filenames are presented in their
-  original case or in all lowercase.  Filename lookup is always case
-  insensitive, so either way foo and Foo refer to the same file but ls
-  will list Foo with case=asis, and foo with case=lower.  (Same as for
-  the HPFS filesystem.)
-
-     aassiiss
-        Filenames are reported in the case they were created with.
-
-     lloowweerr
-        Filenames are reported in lowercase.
-
-  22..33..  ccoonnvv=={{aauuttoo,, bbiinnaarryy,, tteexxtt}}
-
-  default value: binary
-
-  This option controls CR<->NL conversion of Macintosh _d_a_t_a _f_o_r_k_s.  Any
-  translation takes place only for files accessed with the read() and
-  write() system calls (either directly or through the stdio functions).
-  Access through mmap() is unaffected.  (Similar to the conv= option for
-  the MS-DOS filesystem.)
-
-     aauuttoo
-        If the Finder's type for a file is TEXT or ttro, then CR
-        characters are converted to NL characters when read, and NL
-        characters are converted to CR characters when written.
-
-        Be warned that some Macintosh applications create files with
-        type TEXT even though the contents is clearly binary.
-
-     bbiinnaarryy
-        No CR<->NL conversion is done.
-
-     tteexxtt
-        In all data forks, regardless of the Finder's type for the file,
-        CR characters are converted to NL characters when read, and NL
-        characters are converted to CR characters when written.
-
-  22..44..  ccrreeaattoorr==cccccccc
-
-  default value: ``????''
-
-  Specifies the 4-character string specifying the Finder's Creator for
-  new files.
-
-  22..55..  ffoorrkk=={{ccaapp,, ddoouubbllee,, nneettaattaallkk}}
-
-  default value: cap
-
-  This option determines how resource forks and the Finder's metadata
-  are represented within the structure of the Linux filesystem.
-
-     ccaapp
-        The scheme used by the Columbia AppleTalk Package's AUFS.
-
-        Associated with each directory are two special directories and a
-        metadata file.  The directory ./bar is represented by:
-
-        ..//bbaarr
-           The directory itself, containing subdirectories, the data
-           forks of files, and the following two special directories.
-
-        ..//bbaarr//..rreessoouurrccee
-           A special directory holding resource forks of the files in
-           ./bar.
-
-        ..//bbaarr//..ffiinnddeerriinnffoo
-           A special directory holding metadata files for the files and
-           subdirectories in ./bar.
-
-        ..//..ffiinnddeerriinnffoo//bbaarr
-           The metadata file for the directory ./bar.
-
-        The files in a directory are represented as three files:
-
-        ..//ffoooo
-           The data fork of the file ./foo.
-
-        ..//..rreessoouurrccee//ffoooo
-           The resource fork of the file ./foo.
-
-        ..//..ffiinnddeerriinnffoo//ffoooo
-           The metadata file for the file ./foo.
-
-        Additionally, the file .rootinfo in the root directory of the
-        HFS filesystem is a metadata file for the root directory.
-
-        Brief documentation on the format of file containing the
-        Finder's metadata is included in the section ``A Guide to
-        Special File Formats'' in this document.  More detailed
-        information is available in the Columbia AppleTalk Package.
-
-     ddoouubbllee
-        The ``AppleDouble'' format recommended by Apple.  (Apple's other
-        recommended format, ``AppleSingle'', is not yet implemented.)
-
-        Associated with each directory is an AppleDouble ``header
-        file''.  The directory ./bar is represented by:
-
-        ..//bbaarr
-           The directory itself, containing subdirectories, the data
-           forks for files, and the header files for files and
-           subdirectories.
-
-        ..//%%bbaarr
-           The header file for the directory ./bar, containing the
-           Finder's metadata for the directory.
-
-        The files in a directory are represented as two files:
-
-        ..//ffoooo
-           The data fork of the file ./foo.
-
-        ..//%%ffoooo
-           The header file for the file ./foo, containing the resource
-           fork and the Finder's metadata for the file.
-
-        Additionally, the file %RootInfo in the root directory of the
-        HFS filesystem is a header file for the root directory.  This is
-        not quite the %RootInfo file referred to in the AppleDouble
-        specification.
-
-        The header files used in this scheme are version 2 AppleDouble
-        header files.  Their format is described briefly in the section
-        ``A Guide to Special File Formats'' in this document.  They are
-        documented in detail in ``AppleSingle/AppleDouble Formats:
-        Developer's Note (9/94)'', available from Apple's Developer
-        Services Page <http://devworld.apple.com>.
-
-        Note that the naming convention for the header file can cause
-        name conflicts.  For instance, using Apple's 7-bit ASCII name
-        conversion (see the names mount option) the name %Desktop could
-        be interpreted either as the header file for the file Desktop or
-        as the file with 0xDE as the hexadecimal representation of its
-        first character, and "sktop" as the remaining 5 characters.  The
-        problem arises when both files exist, since only one will be
-        accessible.  The behavior of the HFS filesystem in the case of
-        such a conflict is undefined, and may change in future releases.
-        (If this causes problems for you, please don't report it as a
-        bug; I didn't design this ``standard'', Apple did.)
-
-     nneettaattaallkk
-        The scheme used by the Netatalk afpd.
-
-        Associated with each directory is a special directory and a
-        metadata file.  The directory ./bar is represented by:
-
-        ..//bbaarr
-           The directory itself, containing subdirectories, the data
-           forks of files, and the following special directory.
-
-        ..//bbaarr//..AApppplleeDDoouubbllee
-           A special directory holding AppleDouble header files for
-           ./bar and the files it contains, but not for the
-           subdirectories it contains.
-
-        ..//bbaarr//..AApppplleeDDoouubbllee//..PPaarreenntt
-           The header file for the directory ./bar, containing the
-           Finder's metadata for the directory.
-
-        The files in a directory are represented as two files:
-
-        ..//ffoooo
-           The data fork of the file ./foo.
-
-        ..//..AApppplleeDDoouubbllee//ffoooo
-           The header file for file ./foo, containing the resource fork
-           and the Finder's metadata.
-
-        The header files used in this scheme are version 1 AppleDouble
-        header files.  They are described briefly in the section ``A
-        Guide to Special File Formats'' in this document.  The format is
-        documented in detail in the ``Apple II File Type Notes'' under
-        the type ``$E0.0002/$E0.0003-AppleDouble'', and in Appendix B of
-        the ``A/UX Toolbox: Macintosh ROM Interface'' manual.
-
-  22..66..  ggiidd==nn
-
-  default value: gid of the mounting process
-
-  Specifies the group that owns all files and directories on the
-  filesystem.  (Same as for the MS-DOS and HPFS filesystems.)
-
-  22..77..  nnaammeess=={{77bbiitt,, 88bbiitt,, aallpphhaa,, ccaapp,, llaattiinn,, nneettaattaallkk,, ttrriivviiaall}}
-
-  default value: varies as follows
-
-  +o  If the fork option is set to double, then names defaults to alpha.
-
-  +o  If the fork option is set to netatalk, then names defaults to
-     netatalk.
-
-  +o  If the fork option is set to cap (or has taken that value by
-     default), then names defaults to cap.
-
-  This option determines how to convert between valid Macintosh
-  filenames and valid Linux filenames.  The 7bit, 8bit and alpha options
-  correspond to Apple's recommended conventions named ``7-bit ASCII'',
-  ``8-bit'' and ``7-bit alphanumeric''.
-
-     77bbiitt
-        When converting from Macintosh filenames to Linux filenames the
-        NULL (0x00), slash (/) and percent (%) characters and the
-        extended 8-bit characters (hexadecimal codes 0x80-0xff) are
-        replaced by a percent character (%) followed by the two-digit
-        hexadecimal code for the character.
-
-        When converting from Linux filenames to Macintosh filenames the
-        string "%YZ" is replaced by the character with hexadecimal code
-        0xYZ.  If 0xYZ is not a valid hexadecimal number or is the code
-        for NULL or colon (:) then the string "%YZ" is unchanged.  A
-        colon (:) is replaced by a pipe character (|).
-
-     88bbiitt
-        When converting from Macintosh filenames to Linux filenames the
-        NULL (0x00), slash (/) and percent (%) characters are replaced
-        by a percent character (%) followed by the two-digit hexadecimal
-        code for the character.
-
-        When converting from Linux filenames to Macintosh filenames the
-        string "%YZ" is replaced by the character with hexadecimal code
-        0xYZ.  If 0xYZ is not a valid hexadecimal number or is the code
-        for NULL or colon (:) then the string "%YZ" is unchanged.  A
-        colon (:) is replaced by a pipe character (|).
-
-     aallpphhaa
-        When converting from Macintosh filenames to Linux filenames only
-        the alphanumeric characters (a-z, A-Z and 0-9), the underscore
-        (_) and the last period (.) in the filename are unchanged.  The
-        remaining characters are replaced by a percent character (%)
-        followed by the two-digit hexadecimal code for the character.
-
-        When converting from Linux filenames to Macintosh filenames the
-        string "%YZ" is replaced by the character with hexadecimal code
-        0xYZ.  If 0xYZ is not a valid hexadecimal number or is the code
-        for NULL or colon (:) then the string "%YZ" is unchanged.  A
-        colon (:) is replaced by a pipe character (|).
-
-     ccaapp
-        The convention used by the Columbia AppleTalk Package's AUFS.
-
-        When converting from Macintosh filenames to Linux filenames the
-        characters from space ( ) through tilde (~) (ASCII 32-126) are
-        unchanged, with the exception of slash (/).  The slash (/) and
-        all characters outside the range 32-126 are replaced by a colon
-        (:) followed by the two-digit hexadecimal code for the
-        character.
-
-        When converting from Linux filenames to Macintosh filenames the
-        string ":YZ" is replaced by the character with hexadecimal code
-        0xYZ.  If 0xYZ is not a valid hexadecimal number or is the code
-        for NULL or colon (:) then the colon is replaced by a pipe
-        character (|).
-
-     llaattiinn
-        When converting from Macintosh filenames to Linux filenames the
-        characters from space ( ) through tilde (~) (ASCII 32-126) are
-        unchanged, with the exception of slash (/) and percent (%).  The
-        extended 8-bit Macintosh characters with equivalents in the
-        Latin-1 character set are replaced by those equivalents.  The
-        remaining characters are replaced by a percent character (%)
-        followed by the two-digit hexadecimal code for the character.
-
-        When converting from Linux filenames to Macintosh filenames the
-        string "%YZ" is replaced by the character with hexadecimal code
-        0xYZ.  If 0xYZ is not a valid hexadecimal number or is the code
-        for NULL or colon (:) then the string "%YZ" is unchanged. The
-        Latin-1 characters with equivalents in the extended 8-bit
-        Macintosh character set are replaced by those equivalents.  A
-        colon (:) is replaced by a pipe character (|).
-
-        Thanks to Holger Schemel (aeglos@valinor.owl.de) for
-        contributing this conversion mode.
-
-     nneettaattaallkk
-        The convention used by the Netatalk afpd.
-
-        When converting from Macintosh filenames to Linux filenames the
-        characters from space ( ) through tilde (~) (ASCII 32-126) are
-        unchanged, with the exception of slash (/) and any initial
-        period (.).  The slash (/) and any initial period (.)  and all
-        characters outside the range 32-126 are replaced by a colon (:)
-        followed by the two-digit hexadecimal code for the character.
-
-        When converting from Linux filenames to Macintosh filenames the
-        string ":YZ" is replaced by the character with hexadecimal code
-        0xYZ.  If 0xYZ is not a valid hexadecimal number or is the code
-        for NULL or colon (:) then the colon is replaced by a pipe
-        character (|).
-
-     ttrriivviiaall
-        When converting from Macintosh filenames to Linux filenames a
-        slash character (/) is replaced by a colon (:).
-
-        When converting from Linux filenames to Macintosh filenames a
-        colon (:) is replaced by a slash character (/).
-
-  22..88..  ppaarrtt==nn
-
-  default value: 0
-
-  Specifies which HFS partition to mount from a Macintosh CDROM or hard
-  drive.  Partitions are numbered from 0 and count only those identified
-  in the partition table as containing HFS filesystems.  This option is
-  only useful when the Linux platform doesn't fully support Macintosh
-  partition tables.  In particular on MkLinux and Linux-Pmac this option
-  is useless.
-
-  Note that in versions before 0.8.3 partitions were numbered from 1.
-
-  22..99..  qquuiieett
-
-  If included in the options, then chown and chmod operations will not
-  return errors, but will instead fail silently.  (Same as for the MS-
-  DOS and HPFS filesystems.)
-
-  22..1100..  ttyyppee==cccccccc
-
-  default value: ``????''
-
-  Specifies the 4-character string specifying the Finder's Type for new
-  files.
-
-  22..1111..  uuiidd==nn
-
-  default value: uid of the mounting process
-
-  Specifies the user that owns all files and directories on the
-  filesystem.  (Same as for the MS-DOS and HPFS filesystems.)
-
-  22..1122..  uummaasskk==nn
-
-  default value: umask of the mounting process
-
-  Specifies (in octal) the umask used for all files and directories.
-  (Same as for the MS-DOS and HPFS filesystems.)
-
-  33..  WWrriittiinngg ttoo HHFFSS FFiilleessyysstteemmss
-
-  Each of the values of the fork mount option yields a different
-  representation of the Macintosh-specific parts of a file within the
-  structure of the Linux filesystem.  There are, therefore, slightly
-  different steps involved in copying files if you want to preserve the
-  resource forks and the Finder's metadata.
-
-  It is important to remember not to use normal user-level tools to
-  modify a filesystem mounted with the afpd mount option.
-
-  Regardless of the value of the fork mount option you can do virtually
-  everything to the data fork of a file that you can to a file on any
-  other filesystem.  The limitations are essentially the same as those
-  imposed by the MS-DOS filesystem:
-
-  +o  You can't change the uid or gid of files.
-
-  +o  You can't set the set-uid, set-gid or sticky permission bits.
-
-  +o  You can't clear the execute permission bits.
-
-  Likewise you can do virtually everything to a directory that you can
-  to a directory on another file system with the following exceptions:
-
-  +o  You can't create, delete or rename resource forks of files or the
-     Finder's metadata.  Note, however, that they are created (with
-     defaults values), deleted and renamed along with the corresponding
-     data fork or directory.
-
-  +o  You can't change permissions on directories.
-
-  +o  You can't change the uid or gid of directories.
-
-  +o  You can't create multiple links to files.
-
-  +o  You can't create symlinks, device files, sockets or FIFOs.
-
-  33..11..  WWrriittiinngg wwiitthh ffoorrkk==ccaapp
-
-  Unlike the other schemes for representing forked files, the CAP scheme
-  presents the resource fork as an independent file; the resource fork
-  of ./foo is ./.resource/foo.  Therefore, you can treat it as a normal
-  file.  You can do anything to a resource fork that you can do to a
-  data fork, except that you cannot enable execute permissions on a
-  resource fork.  Therefore, resource forks are not suitable for holding
-  Linux executables or shared libraries.
-
-  If you plan to use the resource fork on a Macintosh then you must obey
-  the format of a valid resource fork.  This format is documented in
-  Chapter 1 of Apple's _I_n_s_i_d_e _M_a_c_i_n_t_o_s_h_: _M_o_r_e _M_a_c_i_n_t_o_s_h _T_o_o_l_b_o_x.  The
-  filesystem knows nothing about this format and so does nothing to
-  enforce it.
-
-  The current support for reading and writing is sufficient to allow
-  copying of entire directories with tar, as long as both the source and
-  destination are mounted with fork=cap.  tar may complain about being
-  unable to change the uid, gid or mode of files.  This is normal and is
-  an unavoidable side effect of the having a single uid, gid and umask
-  for the entire filesystem.
-
-  It is impossible to create a resource fork or a Finder metadata file.
-  However, they are created automatically when the data fork is created.
-  Therefore, if you wish to copy a single file including both forks and
-  the Finder's metadata then you must create the data fork first.  Then
-  you can copy the resource fork and the Finder's metadata.  For
-  instance to copy the file foo to dir/bar you should do the following:
-
-  1. cp foo dir/bar
-
-  2. cp .resource/foo dir/.resource/bar
-
-  3. cp .finderinfo/foo dir/.finderinfo/bar
-
-  You may get ``Operation not permitted'' errors from cp when it tries
-  to change the permissions on files.  These errors can safely be
-  ignored.  This method will work even if the file dir/bar exists.
-
-  If you wish to move foo to dir/bar and foo and dir are on the same
-  filesystem then you only need to execute ``mv foo dir/bar'' and the
-  resource fork and the Finder's metadata will move too.  However, if
-  foo and dir are on different filesystem then this will lose the
-  resource fork and metadata.  Therefore, it is safest to always move
-  files as follows:
-
-  1. cp foo dir/bar
-
-  2. cp .resource/foo dir/.resource/bar
-
-  3. cp .finderinfo/foo dir/.finderinfo/bar
-
-  4. rm foo
-
-  You may get ``Operation not permitted'' errors from cp when it tries
-  to change the permissions on files.  These errors can safely be
-  ignored.  This method will work even if the file dir/bar exists.
-
-  Directories have no resource fork but you may wish to create a
-  directory which has the same location and view on the Finder's screen
-  as an existing one.  This can be done by copying the Finder metadata
-  file.  To give the directory bar the same location, layout, creation
-  date and modify date as foo you simply execute ``cp .finderinfo/foo
-  .finderinfo/bar''.
-
-  When copying an entire directory with ``cp -R'' you may also wish to
-  copy the metadata for the directory:
-
-  1. cp -R foo bar
-
-  2. cp .finderinfo/foo .finderinfo/bar
-
-  You may get ``Operation not permitted'' errors from cp when it tries
-  to change the permissions on files.  These errors can safely be
-  ignored.
-
-  33..22..  WWrriittiinngg wwiitthh ffoorrkk==ddoouubbllee
-
-  The current support for reading and writing header files is sufficient
-  to allow copying of entire directories with tar, as long as both the
-  source and destination are mounted with fork=double.  tar may complain
-  about being unable to change the uid, gid or mode of files.  This is
-  normal and is an unavoidable side effect of the having a single uid,
-  gid and umask for the entire filesystem.
-
-  It is impossible to create a header file.  However, they are created
-  automatically when the data fork is created.  Therefore, if you wish
-  to copy a single file including both forks and the Finder's metadata
-  then you must create the data fork first.  Then you can copy the
-  header file.  instance to copy the file foo to dir/bar you should do
-  the following:
-
-  1. cp foo dir/bar
-
-  2. cp %foo dir/%bar
-
-  You may get ``Operation not permitted'' errors from cp when it tries
-  to change the permissions on files.  These errors can safely be
-  ignored.  This method will work even if the file dir/bar exists.
-
-  If you wish to move foo to dir/bar and foo and dir are on the same
-  filesystem then you only need to execute ``mv foo dir/bar'' and the
-  header file will move too.  However, if foo and dir are on different
-  filesystem then this will lose the header file.  Therefore, it is
-  safest to always move files as follows:
-
-  1. cp foo dir/bar
-
-  2. cp %foo dir/%bar
-
-  3. rm foo
-
-  You may get ``Operation not permitted'' errors from cp when it tries
-  to change the permissions on files.  These errors can safely be
-  ignored.  This method will work even if the file dir/bar exists.
-
-  Directories have no resource fork but you may wish to create a
-  directory which has the same location and view on the Finder's screen
-  as an existing one.  This can be done by copying the corresponding
-  header file.  To give the directory bar the same location, layout,
-  creation date and modify date as foo simply execute ``cp %foo %bar''.
-
-  When copying an entire directory with ``cp -R'' you may also wish to
-  copy the header file for the directory as well:
-
-  1. cp -R foo bar
-
-  2. cp %foo %bar
-
-  You may get ``Operation not permitted'' errors from cp when it tries
-  to change the permissions on files.  These errors can safely be
-  ignored.
-
-  33..33..  WWrriittiinngg wwiitthh ffoorrkk==nneettaattaallkk
-
-  The current support for reading and writing header files is sufficient
-  to allow copying of entire directories with tar, as long as both the
-  source and destination are mounted fork=netatalk.  tar may complain
-  about being unable to change the uid, gid or mode of files.  This is
-  normal and is an unavoidable side effect of the having a single uid,
-  gid and umask for the entire filesystem.
-
-  It is impossible to create a header file.  However, they are created
-  automatically when the data fork is created.  Therefore, if you wish
-  to copy a single file including both forks and the Finder's metadata
-  then you must create the data fork first.  Then you can copy the
-  header file.  instance to copy the file foo to dir/bar you should do
-  the following:
-
-  1. cp foo dir/bar
-
-  2. cp .AppleDouble/foo dir/.AppleDouble/bar
-
-  You may get ``Operation not permitted'' errors from cp when it tries
-  to change the permissions on files.  These errors can safely be
-  ignored.  This method will work even if the file dir/bar exists.
-
-  If you wish to move foo to dir/bar and foo and dir are on the same
-  filesystem then you only need to execute ``mv foo dir/bar'' and the
-  header file will move too.  However, if foo and dir are on different
-  filesystem then this will lose the header file.  Therefore, it is
-  safest to always move files as follows:
-
-  1. cp foo dir/bar
-
-  2. cp .AppleDouble/foo dir/.AppleDouble/bar
-
-  3. rm foo
-
-  You may get ``Operation not permitted'' errors from cp when it tries
-  to change the permissions on files.  These errors can safely be
-  ignored.  This method will work even if the file dir/bar exists.
-
-  Directories have no resource fork but you may wish to create a
-  directory which has the same location and view on the Finder's screen
-  as an existing one.  This can be done by copying the corresponding
-  header file.  To give the directory bar the same location, layout,
-  creation date and modify date as foo you simply execute ``cp
-  foo/.AppleDouble/.Parent bar/.AppleDouble/.Parent''.
-
-  Because the fork=netatalk scheme holds the header file for a directory
-  within that directory, directories can safely be copied with ``cp -R
-  foo bar'' with no loss of information.  However, you may get
-  ``Operation not permitted'' errors from cp when it tries to change the
-  permissions on files.  These errors can safely be ignored.
-
-  44..  AA GGuuiiddee ttoo SSppeecciiaall FFiillee FFoorrmmaattss
-
-  Each of the values of the fork mount option yields different special
-  files to represent the Macintosh-specific parts of a file within the
-  structure of the Linux filesystem.  You can write to these special
-  files to change things such as the Creator and Type of a file.
-  However, to do so safely you must follow certain rules to avoid
-  corrupting the data.  Additionally, there are certain fields in the
-  special files that you can't change (writes to them will fail
-  silently).
-
-  44..11..  CCAAPP ..ffiinnddeerriinnffoo FFiilleess
-
-  The Finder's metadata for the file ./foo in held in the file
-  ./.finderinfo/foo.  The file has a fixed format defined in hfs_fs.h as
-  follows:
-
-       ______________________________________________________________________
-       struct hfs_cap_info {
-               __u8    fi_fndr[32];            /* Finder's info */
-               __u16   fi_attr;                /* AFP attributes */
-               __u8    fi_magic1;              /* Magic number: */
-       #define HFS_CAP_MAGIC1          0xFF
-               __u8    fi_version;             /* Version of this structure: */
-       #define HFS_CAP_VERSION         0x10
-               __u8    fi_magic;               /* Another magic number: */
-       #define HFS_CAP_MAGIC           0xDA
-               __u8    fi_bitmap;              /* Bitmap of which names are valid: */
-       #define HFS_CAP_SHORTNAME       0x01
-       #define HFS_CAP_LONGNAME        0x02
-               __u8    fi_shortfilename[12+1]; /* "short name" (unused) */
-               __u8    fi_macfilename[32+1];   /* Original (Macintosh) name */
-               __u8    fi_comln;               /* Length of comment (always 0) */
-               __u8    fi_comnt[200];          /* Finder comment (unused) */
-               /* optional:    used by aufs only if compiled with USE_MAC_DATES */
-               __u8    fi_datemagic;           /* Magic number for dates extension: */
-       #define HFS_CAP_DMAGIC          0xDA
-               __u8    fi_datevalid;           /* Bitmap of which dates are valid: */
-       #define HFS_CAP_MDATE           0x01
-       #define HFS_CAP_CDATE           0x02
-               __u8    fi_ctime[4];            /* Creation date (in AFP format) */
-               __u8    fi_mtime[4];            /* Modify date (in AFP format) */
-               __u8    fi_utime[4];            /* Un*x time of last mtime change */
-       };
-       ______________________________________________________________________
-
-  The type __u8 is an unsigned character, and __u16 is an unsigned
-  16-bit integer.
-
-  Currently only the fields fi_fndr, fi_attr, fi_ctime and fi_mtime can
-  be changed.  Writes to the other fields are silently ignored.
-  However, you shouldn't write random bytes to the other fields, since
-  they may be writable in the future.
-
-  The fi_fndr field is the ``Finder info'' and ``Extended Finder info''
-  for a file or directory.  These structures are described in various
-  books on Macintosh programming.  The portion of the most interest is
-  probably the first 8 bytes which, for a file, give the 4-byte Type
-  followed by the 4-byte Creator.
-
-  The fi_attr field is the AFP attributes of the file or directory.
-  While you can write any value to this field, only the ``write-
-  inhibit'' bit is significant.  Setting or clearing this bit will clear
-  or set the write bits in the file's permissions.  When you read from
-  this field anything you may have written is lost.  If the file has
-  write permissions enabled then you will read zero from this field.
-  With write permission disabled you will read back 0x01 0xA0, which
-  corresponds to setting the ``write-inhibit'', ``rename-inhibit'' and
-  ``delete-inhibit'' bits.
-
-  The fi_ctime and fi_mtime are the Macintosh created and modified time
-  for the file or directory, and are 32-bit signed integers in network
-  byteorder giving seconds from 00:00 GMT Jan. 1, 2000.
-
-  44..22..  AApppplleeDDoouubbllee HHeeaaddeerr FFiilleess
-
-  Both the fork=double and fork=netatalk schemes for representing forked
-  files use AppleDouble header files to contain the resource fork and
-  the Finder's metadata together in a single file.
-
-  The AppleDouble format specifies a fixed-format header which describes
-  which fields are contained in the remainder of the file, where they
-  are located in the file and how long they are.  A full description of
-  the version 1 format used when fork=netatalk is available from ??????.
-  The version 2 format used when fork=double is documented in ??????.
-  The discussion that follows assumes you have read and understood these
-  documents, which may be difficult until I've replaced the ``??????''s
-  above with something more informative :-).
-
-  Due to the variable structure of an AppleDouble header file you must
-  not use buffered I/O when reading or writing them; you should only use
-  the read() and write() system calls.  It is also important that you
-  make some effort to coordinate processes that are reading and writing
-  the same header file, since a reader will receive the wrong data if
-  the location of a given entry has changed since it read the descriptor
-  for the entry.  If a process tries to read the descriptor table while
-  it is changing then it is possible to read totally meaningless data.
-
-  When a header file is opened it is initially presented with a default
-  header layout.  You may write to the header to change the layout, but
-  when all file descriptors for the file or directory have been closed
-  the change in format is lost and subsequent opens will yield the
-  default layout.  Changes to supported entries are made directly to the
-  filesystem and are thus preserved when the file is closed and
-  reopened.
-
-  The HFS filesystem currently uses a fixed-size table to hold the
-  descriptors.  Therefore you are limited to HFS_HDR_MAX (currently 10)
-  descriptors.  In the unlikely event that you try to write a header
-  with more descriptors, a warning will be issued by the kernel, and
-  extra descriptors will be ignored.  This should be considered a bug
-  and will hopefully change sooner rather than later.
-
-  The results of specifying overlapping entries is undefined and should
-  not be relied upon to remain unchanged from one version of the HFS
-  filesystem to the next.  There is no valid reason to define
-  overlapping entries, so just don't do it!
-
-  Changes to the magic number and version fields are preserved until all
-  file descriptors are closed, however the only significance given to
-  them internally is that the 16 bytes following the version changes
-  meaning according to the version.  For version 1 header files these 16
-  bytes contain the string ``Macintosh'' followed by 7 spaces.  For any
-  other value of the version field these 16 bytes are all zeros.  In
-  either case writes to these 16 bytes are silently ignored.
-
-  Since the magic number and version are given no other significance
-  internally, you are free to do many things that violate the official
-  formats.  For instance you can create an entry for the data fork in a
-  header file with an AppleDouble magic number or create ``File Info''
-  (id=7) entries in version 2 header files and ``File Dates Info''
-  (id=8) entries in version 1 header files.  However, future versions of
-  the filesystem may enforce the format more strictly.
-
-  Entry id 1 (``Data Fork'') is read-only.  You should use the data file
-  to modify the data fork.  The data fork is, of course, not supported
-  for directories.
-
-  Entry ids 2, 7, 8, 9 and 10 (``Resource Fork'', ``File Info'', ``File
-  Dates Info'', ``Finder Info'' and ``Macintosh File Info'') are fully
-  supported, meaning that their contents may be read and written and
-  that data written is preserved when the file is closed and reopened.
-  The resource fork is, of course, not supported for directories.
-
-  Entry id 7 specifies some of the same data given by ids 8 and 10.  If
-  you create a header file with an entry for id 7 and for ids 8 or 10,
-  then the behavior with respect to their interaction is undefined.  A
-  header that contains an entry for id 7 and for ids 8 or 10 is not
-  valid as either a version 1 or a version 2 header file, so there is no
-  reason to do this and future versions may prevent it.
-
-  Entry id 3 (``Real Name'') is read-only, since it will change
-  automatically when a file is renamed.  Writes to the corresponding
-  entry are silently ignored.
-
-  All other entry ids are ignored.  You may create descriptors for them;
-  in fact the default header layout when fork=netatalk includes a
-  descriptor for id 4 (``Comment'').  However writes to the entries
-  corresponding to the ignored ids fail silently and reads from the
-  entries always return zeros.  However, you shouldn't write random
-  bytes to unsupported entries, since they may be supported in the
-  future.
-
-  All of the supported entry types except the data and resource forks
-  have a fixed length.  If you give them a smaller length in the
-  descriptor then you are unable to access part of the corresponding
-  entry.  If you give them a larger length in the descriptor, then the
-  corresponding entry is padded with zeros and writes to the extra space
-  are silently ignored.
-
-  Writes to the length field of descriptors for the data and resource
-  forks will cause the corresponding fork to grow (with zero padding) or
-  shrink to the indicated length.
-
-  If you have an entry for the data fork then the descriptor's length
-  field does not change automatically to reflect any modification of the
-  data fork directly (the data does change however).  If the data fork
-  is longer than the descriptor indicates, then a portion of it is
-  inaccessible.  If the data fork is shorter than the descriptor
-  indicates then reads will be padded with zeros.
-
-  Writes beyond the end of the resource fork that extend into empty
-  space between entries or beyond the end of the file will extend the
-  fork, automatically changing the length field of the corresponding
-  descriptor.  Writes to any other space between entries are silently
-  ignored and read of such spaces always return zeros.
-
-  Calling truncate() on a header file can change the length of the
-  resource fork and such a change will automatically be reflected in the
-  length field of the corresponding descriptor.  If truncate() shortens
-  the file so that the entry for the resource fork would extend beyond
-  the new end of the file then the fork is shortened to fit in the space
-  that remains, or to zero bytes if the entry is now entirely beyond the
-  end of the file.  If the last entry in a header file is the resource
-  fork then a call to truncate() that extends the header file will
-  extend the fork with zeros.  Note that this happens even if there was
-  previously space between the end of the fork and the end of the file.
-
-  55..  RReeppoorrttiinngg BBuuggss
-
-  If you'd like any problems you encounter fixed, you'll need to provide
-  a detailed bug report.  However, you should check the FAQ (available
-  from the HFS for Linux Page <http://www-sccm.Stanford.EDU/~hargrove/HFS/>)
-  first to be certain that your problem is not a known limitation of the
-  filesystem.  If your bug doesn't appear in the FAQ then you should e-mail
-  me at hargrove@sccm.Stanford.EDU.
-
-  55..11..  WWhhaatt GGooeess iinn aa BBuugg RReeppoorrtt
-
-  When writing your bug report, include any facts you think might be
-  relevant; I'd much rather have a bunch of extra facts than need to
-  e-mail you to get the information.  At a minimum the following
-  information should be included:
-
-  +o  The version of the HFS filesystem you are using (see
-     linux/fs/hfs/version.h).
-
-  +o  The kernel version you are using.
-
-  +o  Any unofficial kernel patches or loadable modules you are using.
-
-  +o  If you are loading the HFS filesystem as a module, then version of
-     the module utilities used to load hfs.o.
-
-  +o  The type of media you are working with (floppy, CDROM, ZIP Drive,
-     etc.).
-
-  +o  The steps required to reproduce the bug, including mount options
-     used.  (If you can't reproduce the bug tell me everything you did
-     the one time it did occur, but be warned that non-reproducible bugs
-     can only rarely be fixed.)
-
-  55..22..  HHooww ttoo RReeppoorrtt aa KKeerrnneell OOooppss oorr GGPPFF
-
-  If you encounter a bug that causes a kernel Oops or a General
-  Protection Fault then you'll need to collect some additional
-  information for the bug report.  If you are loading the HFS filesystem
-  as a module, then is important that you do this before rebooting,
-  since the module is unlikely to be loaded at the same address after
-  the reboot.
-
-  You should include all the information that the kernel prints to the
-  console or to the system logs.  However, the EIP and Stack Trace are
-  addresses in _y_o_u_r kernel and mean nothing to me without more
-  information.  Using your System.map file (or either ksymoops or klogd)
-  determine which functions the EIP and Stack Trace are in.  If you do
-  this by hand using your System.map file then the correct symbol is the
-  one of type t or T with the largest address less than or equal to the
-  one you are resolving.
-
-  If you are loading the HFS filesystem as a module and the Oops or GPF
-  was in the HFS code then the EIP and the top levels of the Stack Trace
-  will be in a loadable module, rather than in the kernel proper.  So,
-  their symbols will not be in the file System.map.  Therefore, you will
-  need to use /proc/ksyms, or a loadmap produced by passing the -m
-  option to insmod, to locate those symbols.
-
-  66..  LLeeggaall NNoottiicceess
-
-  66..11..  TThhiiss DDooccuummeenntt
-
-  This document is Copyright (c) 1996, 1997 by Paul H. Hargrove.
-
-  Permission is granted to make and distribute verbatim copies of this
-  document provided the copyright notice and this permission notice are
-  preserved on all copies.
-
-  Permission is granted to copy and distribute modified versions of this
-  document under the conditions for verbatim copies above, provided a
-  notice clearly stating that the document is a modified version is also
-  included in the modified document.
-
-  Permission is granted to copy and distribute translations of this
-  document into another language, under the conditions specified above
-  for modified versions.
-
-  Permission is granted to convert this document into another media
-  under the conditions specified above for modified versions provided
-  the requirement to acknowledge the source document is fulfilled by
-  inclusion of an obvious reference to the source document in the new
-  media. Where there is any doubt as to what defines ``obvious'' the
-  copyright owner reserves the right to decide.
-
-  66..22..  TThhee SSooffttwwaarree
-
-  The HFS filesystem for Linux is Copyright (c) 1994-1997 by Paul H.
-  Hargrove.
-
-  This software is free software; you can redistribute it and/or modify
-  it under the terms of the GNU General Public License as published by
-  the Free Software Foundation; either version 2, or (at your option)
-  any later version.
-
-  This software is distributed in the hope that it will be useful, but
-  WITHOUT ANY WARRANTY; without even the implied warranty of
-  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-  General Public License for more details.
-
-  You should have received a copy of the GNU General Public License
-  along with this software in the file ``COPYING''; if not, write to the
-  Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139,
-  USA.
-
-  66..22..11..  TThhee CCoolluummbbiiaa AApppplleeTTaallkk PPaacckkaaggee ffoorr UUNNIIXX
-
-  The source code distribution of the Columbia AppleTalk Package for
-  UNIX, version 6.0, (CAP) was used as a _s_p_e_c_i_f_i_c_a_t_i_o_n of the location
-  and format of files used by CAP's Aufs.  No code from CAP appears in
-  the HFS filesystem. The HFS filesystem is not a work ``derived'' from
-  CAP in the sense of intellectual property law.
-
-  66..22..22..  NNeettaattaallkk
-
-  The source code distributions of Netatalk, versions 1.3.3b2 and 1.4b2,
-  were used as a _s_p_e_c_i_f_i_c_a_t_i_o_n of the location and format of files used
-  by Netatalk's afpd.  No code from Netatalk appears in the HFS
-  filesystem.  The HFS filesystem is not a work ``derived'' from
-  Netatalk in the sense of intellectual property law.
-
-  66..33..  TTrraaddeemmaarrkkss
-
-  +o  ``Finder'' is a trademarks of Apple Computer, Inc.
-
-  +o  ``Apple'', ``AppleShare'', ``AppleTalk'' and ``Macintosh'' are
-     registered trademarks of Apple Computer, Inc.
-
-  +o  ``Microsoft'' and ``MS-DOS'' are registered trademarks of Microsoft
-     Corporation.
-
-  +o  All other trademarks are the property of their respective owners.
-
--- diff/fs/hfs/INSTALL.txt	2003-10-09 09:47:34.000000000 +0100
+++ source/fs/hfs/INSTALL.txt	1970-01-01 01:00:00.000000000 +0100
@@ -1,124 +0,0 @@
-  Installation instructions for the HFS Filesystem for Linux
-  Paul H. Hargrove, hargrove@sccm.Stanford.EDU
-  version 0.95 28 Apr 1997
-
-  This document explains how to compile and install version 0.95 of
-  hfs_fs, the HFS filesystem for Linux.
-
-  11..  SSyysstteemm RReeqquuiirreemmeennttss
-
-  You will need the following to compile and use this release of hfs_fs:
-
-  +o  Kernel version 2.0.1 or newer compiled with modules enabled
-     (CONFIG_MODULES).
-
-  +o  The kernel sources (or at least the header files) available online.
-
-  +o  The module utilities package current for your kernel version and an
-     understanding of how to use it.
-
-  22..  IInnssttaallllaattiioonn
-
-  This release of the HFS filesystem is not part of the official kernel
-  distribution.  Therefore, it is compiled as a module and then loaded
-  into the kernel using the module utilities.  Therefore, your kernel
-  must be compiled with CONFIG_MODULES enabled.
-
-  22..11..  CCoommppiilliinngg tthhee llooaaddaabbllee mmoodduullee
-
-  To compile hfs.o you should only need to execute ``make'' in the
-  hfs_fs source directory.
-
-  If gcc complains about not finding a large number of header files with
-  names beginning with ``linux/'' then you probably don't have the
-  kernel header files installed correctly.  Either /usr/include/linux,
-  /usr/include/asm and /usr/include/scsi should be symbolic links to
-  include/linux, include/asm and include/scsi in the kernel source tree
-  for the kernel you wish to use hfs_fs with, or else they should be
-  directories containing the header files for the kernel you wish to use
-  hfs_fs with.
-
-  If gcc complains about not finding linux/version.h, then you will need
-  to run ``make dep'' in the kernel source directory to build it.  Under
-  MkLinux, run ``make include/linux/version.h'' instead.
-
-  If gcc complains about not finding the files linux/config.h or
-  linux/autoconf.h, then you will need to run ``make config'' and ``make
-  dep'' in the kernel source directory to build these two files.
-
-  If you are compiling on a DEC Alpha and receive messages saying
-  assignment from incompatible pointer type when compiling files dir_*.c
-  and file_*.c, then you need to change a single line in the file
-  linux/hfs_fs.h.  Remove the text ``&& !defined(__alpha__)'' from the
-  end of line 217.
-
-  22..22..  IInnssttaalllliinngg tthhee mmoodduullee iinn tthhee mmoodduulleess ddiirreeccttoorryy ((ooppttiioonnaall))
-
-  If you plan to use kerneld to automatically load the module or if you
-  wish to use modprobe or insmod without supplying a complete path to
-  hfs.o, then you will need to copy hfs.o into a directory where the
-  module utilities expect to find it.
-
-  The proper directory may depend slightly on your configuration.
-  However, /lib/modules/default/fs/ is a common one for filesystem
-  modules.  Once hfs.o is in the proper directory you should run depmod
-  -a to update the dependency list used by kerneld and modprobe.
-
-  22..33..  LLooaaddiinngg tthhee mmoodduullee iinnttoo tthhee rruunnnniinngg kkeerrnneell
-
-  There are three ways to accomplish this:
-
-  1. If you are running kerneld and have installed hfs.o in the modules
-     directory then you don't need to issue any commands; the module
-     will be loaded when you attempt to mount an HFS filesystem.
-
-  2. If you are _n_o_t running kerneld then you can load hfs.o manually by
-     running modprobe hfs.o.  If you have not installed hfs.o in one of
-     the standard module directories, then you will need provide a full
-     path to the file hfs.o.
-
-  3. If you have been experiencing kernel crashes with hfs_fs, then you
-     should file a bug report including the names of the functions which
-     the EIP and Stack Trace point into.  To help with this you can ask
-     for relocation map for the module when you load it.  To do this
-     load the module with ``insmod -m hfs.o >loadmap''.  Again, you may
-     need a full path to the file hfs.o if you have not placed it in one
-     of the standard module directories.
-
-  22..44..  UUssiinngg tthhee mmoodduullee wwiitthh vveerrssiioonneedd ssyymmbboollss
-
-  All the interface between the module and the kernel take place through
-  very stable (since the mid-1.3.x kernels) parts of the kernel.  If you
-  enabled versioned symbols (CONFIG_MODVERSIONS) when you compiled your
-  kernel you should often be able to compile this module once and then
-  use it with many kernels newer than the one you compiled it for.
-
-  In any case, it is unlikely that this module will need changes with
-  each new kernel patch; simple recompilation should usually suffice.
-
-  33..  LLeeggaall NNoottiicceess
-
-  33..11..  TThhiiss DDooccuummeenntt
-
-  This document is Copyright (c) 1996, 1997 by Paul H. Hargrove.
-
-  Permission is granted to make and distribute verbatim copies of this
-  document provided the copyright notice and this permission notice are
-  preserved on all copies.
-
-  Permission is granted to copy and distribute modified versions of this
-  document under the conditions for verbatim copies above, provided a
-  notice clearly stating that the document is a modified version is also
-  included in the modified document.
-
-  Permission is granted to copy and distribute translations of this
-  document into another language, under the conditions specified above
-  for modified versions.
-
-  Permission is granted to convert this document into another media
-  under the conditions specified above for modified versions provided
-  the requirement to acknowledge the source document is fulfilled by
-  inclusion of an obvious reference to the source document in the new
-  media. Where there is any doubt as to what defines ``obvious'' the
-  copyright owner reserves the right to decide.
-
--- diff/fs/hfs/TODO	2002-10-16 04:29:02.000000000 +0100
+++ source/fs/hfs/TODO	1970-01-01 01:00:00.000000000 +0100
@@ -1,52 +0,0 @@
-The hfs_fs "to do" list.
-------------------------
-Items are broken down into groups and the groups are listed in order
-from most important to least important.  The items within each group
-are not placed in any particular order.  The order in which items are
-listed probably doesn't correlate well with the order they will be
-addressed.
-
-Genuine bugs:
-1.	Header files have compiled-in limit (currently 10) on descriptors.
-
-Missing features:
-1.	1k block support is needed for some devices.
-2.	An ioctl()-based interface is needed to provide a consistent way
-	to do things under all of the representations of forked files.
-
-Possible additional "fork" mount options:
-1.	AppleSingle.
-2.	The scheme MacOS uses on FAT disks (PC Exchange).
-3.	"Flat" (no resource forks or metadata).
-
-Performance issues:
-1.	Use drAllocPtr to speed block allocations.
-2.	Keep a real cache of bnodes, rather than just a hash table of
-	the ones that are currently in use.
-3.	Keep a real cache of extent records, rather than just a linked
-	list of the ones that are currently in use and the one most
-	recently used.  This is particularly needed to get acceptable
-	performance with multiple readers on a file.  Perhaps simply
-	keep them in memory once they've been read until the file is
-	closed.
-
-Implementation details:
-1.	Allocation scheme could/should be closer to that used by Apple.
-2.	B*-tree insertion could/should be closer to that used by Apple.
-3.	Magic-number checks on data structures are rarely done.
-4.	Error recovery is needed for failed binsert(), bdelete() and rename().
-5.	Deadlock detection is needed to make insert_empty_bnode() and
-	bdelete() less likely to hang on a corrupted B-tree.
-6.	Metadata for covered directories shouldn't appear in the filesystem.
-	Under CAP and AppleDouble it currently does.  However, the obvious
-	solution is a real performance killer and is not worth implementing.
-
-Fantasy features:
-1.	Access Desktop file/database for comment and icon.
-2.	Implement mmap() for AppleDouble header files and CAP info files.
-3.	Implement AppleShare client support.
-
-Suggestions/comments/questions are welcome.
-Code addressing any of the issues listed above is especially welcome.
-Paul H. Hargrove
-hargrove@sccm.Stanford.EDU
--- diff/fs/hfs/balloc.c	2002-10-16 04:28:22.000000000 +0100
+++ source/fs/hfs/balloc.c	1970-01-01 01:00:00.000000000 +0100
@@ -1,439 +0,0 @@
-/*
- * linux/fs/hfs/balloc.c
- *
- * Copyright (C) 1995-1997  Paul H. Hargrove
- * This file may be distributed under the terms of the GNU General Public License.
- *
- * hfs_bnode_alloc() and hfs_bnode_bitop() are based on GPLed code
- * Copyright (C) 1995  Michael Dreher
- *
- * This file contains the code to create and destroy nodes
- * in the B-tree structure.
- *
- * "XXX" in a comment is a note to myself to consider changing something.
- *
- * In function preconditions the term "valid" applied to a pointer to
- * a structure means that the pointer is non-NULL and the structure it
- * points to has all fields initialized to consistent values.
- *
- * The code in this file initializes some structures which contain
- * pointers by calling memset(&foo, 0, sizeof(foo)).
- * This produces the desired behavior only due to the non-ANSI
- * assumption that the machine representation of NULL is all zeros.
- */
-
-#include "hfs_btree.h"
-
-/*================ File-local functions ================*/
-
-/*
- * get_new_node()
- *
- * Get a buffer for a new node with out reading it from disk.
- */
-static hfs_buffer get_new_node(struct hfs_btree *tree, hfs_u32 node)
-{
-	int tmp;
-	hfs_buffer retval = HFS_BAD_BUFFER;
-
-  	tmp = hfs_extent_map(&tree->entry.u.file.data_fork, node, 0);
-	if (tmp) {
-		retval = hfs_buffer_get(tree->sys_mdb, tmp, 0);
-	}
-	return retval;
-}
-
-/*
- * hfs_bnode_init()
- *
- * Description:
- *   Initialize a newly allocated bnode.
- * Input Variable(s):
- *   struct hfs_btree *tree: Pointer to a B-tree
- *   hfs_u32 node: the node number to allocate
- * Output Variable(s):
- *   NONE
- * Returns:
- *   struct hfs_bnode_ref for the new node
- * Preconditions:
- *   'tree' points to a "valid" (struct hfs_btree)
- *   'node' exists and has been allocated in the bitmap of bnodes.
- * Postconditions:
- *   On success:
- *    The node is not read from disk, nor added to the bnode cache.
- *    The 'sticky' and locking-related fields are all zero/NULL.
- *    The bnode's nd{[FB]Link, Type, NHeight} fields are uninitialized.
- *    The bnode's ndNRecs field and offsets table indicate an empty bnode.
- *   On failure:
- *    The node is deallocated.
- */
-static struct hfs_bnode_ref hfs_bnode_init(struct hfs_btree * tree,
-					   hfs_u32 node)
-{
-#if defined(DEBUG_BNODES) || defined(DEBUG_ALL)
-	extern int bnode_count;
-#endif
-	struct hfs_bnode_ref retval;
-
-	retval.lock_type = HFS_LOCK_NONE;
-	if (!HFS_NEW(retval.bn)) {
-		hfs_warn("hfs_bnode_init: out of memory.\n");
-		goto bail2;
-	}
-
-	/* Partially initialize the in-core structure */
-	memset(retval.bn, 0, sizeof(*retval.bn));
-	retval.bn->magic = HFS_BNODE_MAGIC;
-	retval.bn->tree = tree;
-	retval.bn->node = node;
-	hfs_init_waitqueue(&retval.bn->wqueue);
-	hfs_init_waitqueue(&retval.bn->rqueue);
-	hfs_bnode_lock(&retval, HFS_LOCK_WRITE);
-
-	retval.bn->buf = get_new_node(tree, node);
-	if (!hfs_buffer_ok(retval.bn->buf)) {
-		goto bail1;
-	}
-
-#if defined(DEBUG_BNODES) || defined(DEBUG_ALL)
-	++bnode_count;
-#endif
-
-	/* Partially initialize the on-disk structure */
-	memset(hfs_buffer_data(retval.bn->buf), 0, HFS_SECTOR_SIZE);
-	hfs_put_hs(sizeof(struct NodeDescriptor), RECTBL(retval.bn, 1));
-
-	return retval;
-
-bail1:
-	HFS_DELETE(retval.bn);
-bail2:
-	/* clear the bit in the bitmap */
-	hfs_bnode_bitop(tree, node, 0);
-	return retval;
-}
-
-/*
- * init_mapnode()
- *
- * Description:
- *   Initializes a given node as a mapnode in the given tree.
- * Input Variable(s):
- *   struct hfs_bnode *bn: the node to add the mapnode after.
- *   hfs_u32: the node to use as a mapnode.
- * Output Variable(s):
- *   NONE
- * Returns:
- *   struct hfs_bnode *: the new mapnode or NULL
- * Preconditions:
- *   'tree' is a valid (struct hfs_btree).
- *   'node' is the number of the first node in 'tree' that is not
- *    represented by a bit in the existing mapnodes.
- * Postconditions:
- *   On failure 'tree' is unchanged and NULL is returned.
- *   On success the node given by 'node' has been added to the linked
- *    list of mapnodes attached to 'tree', and has been initialized as
- *    a valid mapnode with its first bit set to indicate itself as
- *    allocated.
- */
-static struct hfs_bnode *init_mapnode(struct hfs_bnode *bn, hfs_u32 node)
-{
-#if defined(DEBUG_BNODES) || defined(DEBUG_ALL)
-	extern int bnode_count;
-#endif
-	struct hfs_bnode *retval;
-
-	if (!HFS_NEW(retval)) {
-		hfs_warn("hfs_bnode_add: out of memory.\n");
-		return NULL;
-	}
-
-	memset(retval, 0, sizeof(*retval));
-	retval->magic = HFS_BNODE_MAGIC;
-	retval->tree = bn->tree;
-	retval->node = node;
-	retval->sticky = HFS_STICKY;
-	retval->buf = get_new_node(bn->tree, node);
-	if (!hfs_buffer_ok(retval->buf)) {
-		HFS_DELETE(retval);
-		return NULL;
-	}
-
-#if defined(DEBUG_BNODES) || defined(DEBUG_ALL)
-	++bnode_count;
-#endif
-
-	/* Initialize the bnode data structure */
-	memset(hfs_buffer_data(retval->buf), 0, HFS_SECTOR_SIZE);
-	retval->ndFLink = 0;
-	retval->ndBLink = bn->node;
-	retval->ndType = ndMapNode;
-	retval->ndNHeight = 0;
-	retval->ndNRecs = 1;
-	hfs_put_hs(sizeof(struct NodeDescriptor), RECTBL(retval, 1));
-	hfs_put_hs(0x1fa,                         RECTBL(retval, 2));
-	*((hfs_u8 *)bnode_key(retval, 1)) = 0x80; /* set first bit of bitmap */
-	retval->prev = bn;
-	hfs_bnode_commit(retval);
-
-	bn->ndFLink = node;
-	bn->next = retval;
-	hfs_bnode_commit(bn);
-
-	return retval;
-}
-
-/*================ Global functions ================*/
-
-/*
- * hfs_bnode_bitop()
- *
- * Description:
- *   Allocate/free the requested node of a B-tree of the hfs filesystem
- *   by setting/clearing the corresponding bit in the B-tree bitmap.
- *   The size of the B-tree will not be changed.
- * Input Variable(s):
- *   struct hfs_btree *tree: Pointer to a B-tree
- *   hfs_u32 bitnr: The node number to free
- *   int set: 0 to clear the bit, non-zero to set it.
- * Output Variable(s):
- *   None
- * Returns:
- *    0: no error
- *   -1: The node was already allocated/free, nothing has been done.
- *   -2: The node is out of range of the B-tree.
- *   -4: not enough map nodes to hold all the bits
- * Preconditions:
- *   'tree' points to a "valid" (struct hfs_btree)
- *   'bitnr' is a node number within the range of the btree, which is
- *   currently free/allocated.
- * Postconditions:
- *   The bit number 'bitnr' of the node bitmap is set/cleared and the
- *   number of free nodes in the btree is decremented/incremented by one.
- */
-int hfs_bnode_bitop(struct hfs_btree *tree, hfs_u32 bitnr, int set)
-{
-	struct hfs_bnode *bn;   /* the current bnode */
-	hfs_u16 start;		/* the start (in bits) of the bitmap in node */
-	hfs_u16 len;		/* the len (in bits) of the bitmap in node */
-	hfs_u32 *u32;		/* address of the u32 containing the bit */
-
-	if (bitnr >= tree->bthNNodes) {
-		hfs_warn("hfs_bnode_bitop: node number out of range.\n");
-		return -2;
-	}
-
-	bn = &tree->head;
-	for (;;) {
-		start = bnode_offset(bn, bn->ndNRecs) << 3;
-		len = (bnode_offset(bn, bn->ndNRecs + 1) << 3) - start;
-
-		if (bitnr < len) {
-			break;
-		}
-
-		/* continue on to next map node if available */
-		if (!(bn = bn->next)) {
-			hfs_warn("hfs_bnode_bitop: too few map nodes.\n");
-			return -4;
-		}
-		bitnr -= len;
-	}
-
-	/* Change the correct bit */
-	bitnr += start;
-	u32 = (hfs_u32 *)hfs_buffer_data(bn->buf) + (bitnr >> 5);
-	bitnr %= 32;
-	if ((set && hfs_set_bit(bitnr, u32)) ||
-	    (!set && !hfs_clear_bit(bitnr, u32))) {
-		hfs_warn("hfs_bnode_bitop: bitmap corruption.\n");
-		return -1;
-	}
-	hfs_buffer_dirty(bn->buf);
-
-	/* adjust the free count */
-	tree->bthFree += (set ? -1 : 1);
-	tree->dirt = 1;
-
-	return 0;
-}
-
-/*
- * hfs_bnode_alloc()
- *
- * Description:
- *   Find a cleared bit in the B-tree node bitmap of the hfs filesystem,
- *   set it and return the corresponding bnode, with its contents zeroed.
- *   When there is no free bnode in the tree, an error is returned, no
- *   new nodes will be added by this function!
- * Input Variable(s):
- *   struct hfs_btree *tree: Pointer to a B-tree
- * Output Variable(s):
- *   NONE
- * Returns:
- *   struct hfs_bnode_ref for the new bnode
- * Preconditions:
- *   'tree' points to a "valid" (struct hfs_btree)
- *   There is at least one free bnode.
- * Postconditions:
- *   On success:
- *     The corresponding bit in the btree bitmap is set.
- *     The number of free nodes in the btree is decremented by one.
- *   The node is not read from disk, nor added to the bnode cache.
- *   The 'sticky' field is uninitialized.
- */
-struct hfs_bnode_ref hfs_bnode_alloc(struct hfs_btree *tree)
-{
-	struct hfs_bnode *bn;   /* the current bnode */
-	hfs_u32 bitnr = 0;	/* which bit are we examining */
-	hfs_u16 first;		/* the first clear bit in this bnode */
-	hfs_u16 start;		/* the start (in bits) of the bitmap in node */
-	hfs_u16 end;		/* the end (in bits) of the bitmap in node */
-	hfs_u32 *data;		/* address of the data in this bnode */
-	
-	bn = &tree->head;
-	for (;;) {
-		start = bnode_offset(bn, bn->ndNRecs) << 3;
-		end = bnode_offset(bn, bn->ndNRecs + 1) << 3;
-		data =  (hfs_u32 *)hfs_buffer_data(bn->buf);
-		
-		/* search the current node */
-		first = hfs_find_zero_bit(data, end, start);
-		if (first < end) {
-			break;
-		}
-
-		/* continue search in next map node */
-		bn = bn->next;
-
-		if (!bn) {
-			hfs_warn("hfs_bnode_alloc: too few map nodes.\n");
-			goto bail;
-		}
-		bitnr += (end - start);
-	}
-
-	if ((bitnr += (first - start)) >= tree->bthNNodes) {
-		hfs_warn("hfs_bnode_alloc: no free nodes found, "
-			 "count wrong?\n");
-		goto bail;
-	}
-
-	if (hfs_set_bit(first % 32, data + (first>>5))) {
-		hfs_warn("hfs_bnode_alloc: bitmap corruption.\n");
-		goto bail;
-	}
-	hfs_buffer_dirty(bn->buf);
-
-	/* decrement the free count */
-	--tree->bthFree;
-	tree->dirt = 1;
-
-	return hfs_bnode_init(tree, bitnr);
-
-bail:
-	return (struct hfs_bnode_ref){NULL, HFS_LOCK_NONE};
-}
-
-/*
- * hfs_btree_extend()
- *
- * Description:
- *   Adds nodes to a B*-tree if possible.
- * Input Variable(s):
- *   struct hfs_btree *tree: the btree to add nodes to.
- * Output Variable(s):
- *   NONE
- * Returns:
- *   void
- * Preconditions:
- *   'tree' is a valid (struct hfs_btree *).
- * Postconditions:
- *   If possible the number of nodes indicated by the tree's clumpsize
- *    have been added to the tree, updating all in-core and on-disk
- *    allocation information.
- *   If insufficient disk-space was available then fewer nodes may have
- *    been added than would be expected based on the clumpsize.
- *   In the case of the extents B*-tree this function will add fewer
- *    nodes than expected if adding more would result in an extent
- *    record for the extents tree being added to the extents tree.
- *    The situation could be dealt with, but doing so confuses Macs.
- */
-void hfs_btree_extend(struct hfs_btree *tree)
-{
-	struct hfs_bnode_ref head;
-	struct hfs_bnode *bn, *tmp;
-	struct hfs_cat_entry *entry = &tree->entry;
-	struct hfs_mdb *mdb = entry->mdb;
-	hfs_u32 old_nodes, new_nodes, total_nodes, new_mapnodes, seen;
-
-	old_nodes = entry->u.file.data_fork.psize;
-
-	entry->u.file.data_fork.lsize += 1; /* rounded up to clumpsize */
-	hfs_extent_adj(&entry->u.file.data_fork);
-
-	total_nodes = entry->u.file.data_fork.psize;
-	entry->u.file.data_fork.lsize = total_nodes << HFS_SECTOR_SIZE_BITS;
-	new_nodes = total_nodes - old_nodes;
-	if (!new_nodes) {
-		return;
-	}
-
-	head = hfs_bnode_find(tree, 0, HFS_LOCK_WRITE);
-	if (!(bn = head.bn)) {
-		hfs_warn("hfs_btree_extend: header node not found.\n");
-		return;
-	}
-
-	seen = 0;
-	new_mapnodes = 0;
-	for (;;) {
-		seen += bnode_rsize(bn, bn->ndNRecs) << 3;
-
-		if (seen >= total_nodes) {
-			break;
-		}
-
-		if (!bn->next) {
-			tmp = init_mapnode(bn, seen);
-			if (!tmp) {
-				hfs_warn("hfs_btree_extend: "
-					 "can't build mapnode.\n");
-				hfs_bnode_relse(&head);
-				return;
-			}
-			++new_mapnodes;
-		}
-		bn = bn->next;
-	}
-	hfs_bnode_relse(&head);
-
-	tree->bthNNodes = total_nodes;
-	tree->bthFree += (new_nodes - new_mapnodes);
-	tree->dirt = 1;
-
-	/* write the backup MDB, not returning until it is written */
-	hfs_mdb_commit(mdb, 1);
-
-	return;
-}
-
-/*
- * hfs_bnode_free()
- *
- * Remove a node from the cache and mark it free in the bitmap.
- */
-int hfs_bnode_free(struct hfs_bnode_ref *bnr)
-{
-	hfs_u32 node = bnr->bn->node;
-	struct hfs_btree *tree = bnr->bn->tree;
-
-	if (bnr->bn->count != 1) {
-		hfs_warn("hfs_bnode_free: count != 1.\n");
-		return -EIO;
-	}
-
-	hfs_bnode_relse(bnr);
-	hfs_bnode_bitop(tree, node, 0);
-	return 0;
-}
--- diff/fs/hfs/bdelete.c	2002-10-16 04:28:23.000000000 +0100
+++ source/fs/hfs/bdelete.c	1970-01-01 01:00:00.000000000 +0100
@@ -1,488 +0,0 @@
-/*
- * linux/fs/hfs/bdelete.c
- *
- * Copyright (C) 1995-1997  Paul H. Hargrove
- * This file may be distributed under the terms of the GNU General Public License.
- *
- * This file contains the code to delete records in a B-tree.
- *
- * "XXX" in a comment is a note to myself to consider changing something.
- *
- * In function preconditions the term "valid" applied to a pointer to
- * a structure means that the pointer is non-NULL and the structure it
- * points to has all fields initialized to consistent values.
- */
-
-#include "hfs_btree.h"
-
-/*================ Variable-like macros ================*/
-
-#define FULL (HFS_SECTOR_SIZE - sizeof(struct NodeDescriptor))
-#define NO_SPACE (HFS_SECTOR_SIZE+1)
-
-/*================ File-local functions ================*/
-
-/*
- * bdelete_nonempty()
- *
- * Description:
- *   Deletes a record from a given bnode without regard to it becoming empty.
- * Input Variable(s):
- *   struct hfs_brec* brec: pointer to the brec for the deletion
- *   struct hfs_belem* belem: which node in 'brec' to delete from
- * Output Variable(s):
- *   NONE
- * Returns:
- *   void
- * Preconditions:
- *   'brec' points to a valid (struct hfs_brec).
- *   'belem' points to a valid (struct hfs_belem) in 'brec'.
- * Postconditions:
- *   The record has been inserted in the position indicated by 'brec'.
- */
-static void bdelete_nonempty(struct hfs_brec *brec, struct hfs_belem *belem)
-{
-	int i, rec, nrecs, tomove;
-	hfs_u16 size;
-	hfs_u8 *start;
-	struct hfs_bnode *bnode = belem->bnr.bn;
-
-	rec = belem->record;
-	nrecs = bnode->ndNRecs;
-	size = bnode_rsize(bnode, rec);
-	tomove = bnode_offset(bnode, nrecs+1) - bnode_offset(bnode, rec+1);
-	
-	/* adjust the record table */
-	for (i = rec+1; i <= nrecs; ++i) {
-		hfs_put_hs(bnode_offset(bnode,i+1) - size, RECTBL(bnode,i));
-	}
-
-	/* move it down */
-	start = bnode_key(bnode, rec);
-	memmove(start, start + size, tomove);
-
-	/* update record count */
-	--bnode->ndNRecs;
-}
-
-/*
- * del_root()
- *
- * Description:
- *   Delete the current root bnode.
- * Input Variable(s):
- *   struct hfs_bnode_ref *root: reference to the root bnode
- * Output Variable(s):
- *   NONE
- * Returns:
- *   int: 0 on success, error code on failure
- * Preconditions:
- *   'root' refers to the root bnode with HFS_LOCK_WRITE access.
- *   None of 'root's children are held with HFS_LOCK_WRITE access.
- * Postconditions:
- *   The current 'root' node is removed from the tree and the depth
- *    of the tree is reduced by one.
- *   If 'root' is an index node with exactly one child, then that
- *    child becomes the new root of the tree.
- *   If 'root' is an empty leaf node the tree becomes empty.
- *   Upon return access to 'root' is relinquished.
- */
-static int del_root(struct hfs_bnode_ref *root)
-{
-	struct hfs_btree *tree = root->bn->tree;
-	struct hfs_bnode_ref child;
-	hfs_u32 node;
-
-	if (root->bn->ndNRecs > 1) {
-		return 0;
-	} else if (root->bn->ndNRecs == 0) {
-		/* tree is empty */
-		tree->bthRoot = 0;
-		tree->root = NULL;
-		tree->bthRoot = 0;
-		tree->bthFNode = 0;
-		tree->bthLNode = 0;
-		--tree->bthDepth;
-		tree->dirt = 1;
-		if (tree->bthDepth) {
-			hfs_warn("hfs_bdelete: empty tree with bthDepth=%d\n",
-				 tree->bthDepth);
-			goto bail;
-		}
-		return hfs_bnode_free(root);
-	} else if (root->bn->ndType == ndIndxNode) {
-		/* tree is non-empty */
-		node = hfs_get_hl(bkey_record(bnode_datastart(root->bn)));
-
-		child = hfs_bnode_find(tree, node, HFS_LOCK_READ);
-		if (!child.bn) {
-			hfs_warn("hfs_bdelete: can't read child node.\n");
-			goto bail;
-		}
-			
-		child.bn->sticky = HFS_STICKY;
-        	if (child.bn->next) {
-                	child.bn->next->prev = child.bn->prev;
-        	}
-        	if (child.bn->prev) {
-                	child.bn->prev->next = child.bn->next;
-        	}
-        	if (bhash(tree, child.bn->node) == child.bn) {
-                	bhash(tree, child.bn->node) = child.bn->next;
-        	}
-		child.bn->next = NULL;
-		child.bn->prev = NULL;
-
-		tree->bthRoot = child.bn->node;
-		tree->root = child.bn;
-
-		/* re-assign bthFNode and bthLNode if the new root is
-                   a leaf node. */
-		if (child.bn->ndType == ndLeafNode) {
-			tree->bthFNode = node;
-			tree->bthLNode = node;
-		}
-		hfs_bnode_relse(&child);
-
-		tree->bthRoot = node;
-		--tree->bthDepth;
-		tree->dirt = 1;
-		if (!tree->bthDepth) {
-			hfs_warn("hfs_bdelete: non-empty tree with "
-				 "bthDepth == 0\n");
-			goto bail;
-		}
-		return hfs_bnode_free(root);	/* marks tree dirty */
-	}
-	hfs_bnode_relse(root);
-	return 0;
-
-bail:
-	hfs_bnode_relse(root);
-	return -EIO;
-}
-
-
-/*
- * delete_empty_bnode()
- *
- * Description:
- *   Removes an empty non-root bnode from between 'left' and 'right'
- * Input Variable(s):
- *   hfs_u32 left_node: node number of 'left' or zero if 'left' is invalid
- *   struct hfs_bnode_ref *left: reference to the left neighbor of the
- *    bnode to remove, or invalid if no such neighbor exists.
- *   struct hfs_bnode_ref *center: reference to the bnode to remove
- *   hfs_u32 right_node: node number of 'right' or zero if 'right' is invalid
- *   struct hfs_bnode_ref *right: reference to the right neighbor of the
- *    bnode to remove, or invalid if no such neighbor exists.
- * Output Variable(s):
- *   NONE
- * Returns:
- *   void
- * Preconditions:
- *   'left_node' is as described above.
- *   'left' points to a valid (struct hfs_bnode_ref) having HFS_LOCK_WRITE
- *    access and referring to the left neighbor of 'center' if such a
- *    neighbor exists, or invalid if no such neighbor exists.
- *   'center' points to a valid (struct hfs_bnode_ref) having HFS_LOCK_WRITE
- *    access and referring to the bnode to delete.
- *   'right_node' is as described above.
- *   'right' points to a valid (struct hfs_bnode_ref) having HFS_LOCK_WRITE
- *    access and referring to the right neighbor of 'center' if such a
- *    neighbor exists, or invalid if no such neighbor exists.
- * Postconditions:
- *   If 'left' is valid its 'ndFLink' field becomes 'right_node'.
- *   If 'right' is valid its 'ndBLink' field becomes 'left_node'.
- *   If 'center' was the first leaf node then the tree's 'bthFNode'
- *    field becomes 'right_node' 
- *   If 'center' was the last leaf node then the tree's 'bthLNode'
- *    field becomes 'left_node' 
- *   'center' is NOT freed and access to the nodes is NOT relinquished.
- */
-static void delete_empty_bnode(hfs_u32 left_node, struct hfs_bnode_ref *left,
-			       struct hfs_bnode_ref *center,
-			       hfs_u32 right_node, struct hfs_bnode_ref *right)
-{
-	struct hfs_bnode *bnode = center->bn;
-
-	if (left_node) {
-		left->bn->ndFLink = right_node;
-	} else if (bnode->ndType == ndLeafNode) {
-		bnode->tree->bthFNode = right_node;
-		bnode->tree->dirt = 1;
-	}
-
-	if (right_node) {
-		right->bn->ndBLink = left_node;
-	} else if (bnode->ndType == ndLeafNode) {
-		bnode->tree->bthLNode = left_node;
-		bnode->tree->dirt = 1;
-	}
-}
-
-/*
- * balance()
- *
- * Description:
- *   Attempt to equalize space usage in neighboring bnodes.
- * Input Variable(s):
- *   struct hfs_bnode *left: the left bnode.
- *   struct hfs_bnode *right: the right bnode.
- * Output Variable(s):
- *   NONE
- * Returns:
- *   void
- * Preconditions:
- *   'left' and 'right' point to valid (struct hfs_bnode)s obtained
- *    with HFS_LOCK_WRITE access, and are neighbors.
- * Postconditions:
- *   Records are shifted either left or right to make the space usage
- *   nearly equal.  When exact equality is not possible the break
- *   point is chosen to reduce data movement.
- *   The key corresponding to 'right' in its parent is NOT updated.
- */
-static void balance(struct hfs_bnode *left, struct hfs_bnode *right)
-{
-	int index, left_free, right_free, half;
-
-	left_free = bnode_freespace(left);
-	right_free = bnode_freespace(right);
-	half = (left_free + right_free)/2;
-
-	if (left_free < right_free) {
-		/* shift right to balance */
-		index = left->ndNRecs + 1;
-		while (right_free >= half) {
-			--index;
-			right_free -= bnode_rsize(left,index)+sizeof(hfs_u16);
-		}
-		if (index < left->ndNRecs) {
-#if defined(DEBUG_ALL) || defined(DEBUG_BALANCE)
-			hfs_warn("shifting %d of %d recs right to balance: ",
-			       left->ndNRecs - index, left->ndNRecs);
-#endif
-			hfs_bnode_shift_right(left, right, index+1);
-#if defined(DEBUG_ALL) || defined(DEBUG_BALANCE)
-			hfs_warn("%d,%d\n", left->ndNRecs, right->ndNRecs);
-#endif
-		}
-	} else {
-		/* shift left to balance */
-		index = 0;
-		while (left_free >= half) {
-			++index;
-			left_free -= bnode_rsize(right,index)+sizeof(hfs_u16);
-		}
-		if (index > 1) {
-#if defined(DEBUG_ALL) || defined(DEBUG_BALANCE)
-			hfs_warn("shifting %d of %d recs left to balance: ",
-			       index-1, right->ndNRecs);
-#endif
-			hfs_bnode_shift_left(left, right, index-1);
-#if defined(DEBUG_ALL) || defined(DEBUG_BALANCE)
-			hfs_warn("%d,%d\n", left->ndNRecs, right->ndNRecs);
-#endif
-		}
-	}
-}
-
-/*
- * bdelete()
- *
- * Delete the given record from a B-tree.
- */
-static int bdelete(struct hfs_brec *brec)
-{
-	struct hfs_btree *tree = brec->tree;
-	struct hfs_belem *belem = brec->bottom;
-	struct hfs_belem *parent = (belem-1);
-	struct hfs_bnode *bnode;
-	hfs_u32 left_node, right_node;
-	struct hfs_bnode_ref left, right;
-	int left_space, right_space, min_space;
-	int fix_right_key;
-	int fix_key;
-	
-	while ((belem > brec->top) &&
-	       (belem->flags & (HFS_BPATH_UNDERFLOW | HFS_BPATH_FIRST))) {
-		bnode = belem->bnr.bn;
-		fix_key = belem->flags & HFS_BPATH_FIRST;
-		fix_right_key = 0;
-
-		bdelete_nonempty(brec, belem);
-
-		if (bnode->node == tree->root->node) {
-			del_root(&belem->bnr);
-			--brec->bottom;
-			goto done;
-		}
-
-		/* check for btree corruption which could lead to deadlock */
-		left_node = bnode->ndBLink;
-		right_node = bnode->ndFLink;
-		if ((left_node && hfs_bnode_in_brec(left_node, brec)) ||
-		    (right_node && hfs_bnode_in_brec(right_node, brec)) ||
-		    (left_node == right_node)) {
-			hfs_warn("hfs_bdelete: corrupt btree\n");
-			hfs_brec_relse(brec, NULL);
-			return -EIO;
-		}
-
-		/* grab the left neighbor if it exists */
-		if (left_node) {
-			hfs_bnode_lock(&belem->bnr, HFS_LOCK_RESRV);
-			left = hfs_bnode_find(tree,left_node,HFS_LOCK_WRITE);
-			if (!left.bn) {
-				hfs_warn("hfs_bdelete: unable to read left "
-					 "neighbor.\n");
-				hfs_brec_relse(brec, NULL);
-				return -EIO;
-			}
-			hfs_bnode_lock(&belem->bnr, HFS_LOCK_WRITE);
-			if (parent->record != 1) {
-				left_space = bnode_freespace(left.bn);
-			} else {
-				left_space = NO_SPACE;
-			}
-		} else {
-			left.bn = NULL;
-			left_space = NO_SPACE;
-		}
-
-		/* grab the right neighbor if it exists */
-		if (right_node) {
-			right = hfs_bnode_find(tree,right_node,HFS_LOCK_WRITE);
-			if (!right.bn) {
-				hfs_warn("hfs_bdelete: unable to read right "
-					 "neighbor.\n");
-				hfs_bnode_relse(&left);
-				hfs_brec_relse(brec, NULL);
-				return -EIO;
-			}
-			if (parent->record < parent->bnr.bn->ndNRecs) {
-				right_space = bnode_freespace(right.bn);
-			} else {
-				right_space = NO_SPACE;
-			}
-		} else {
-			right.bn = NULL;
-			right_space = NO_SPACE;
-		}
-
-		if (left_space < right_space) {
-			min_space = left_space;
-		} else {
-			min_space = right_space;
-		}
-
-		if (min_space == NO_SPACE) {
-			hfs_warn("hfs_bdelete: no siblings?\n");
-			hfs_brec_relse(brec, NULL);
-			return -EIO;
-		}
-
-		if (bnode->ndNRecs == 0) {
-			delete_empty_bnode(left_node, &left, &belem->bnr,
-					   right_node, &right);
-		} else if (min_space + bnode_freespace(bnode) >= FULL) {
-			if ((right_space == NO_SPACE) ||
-			    ((right_space == min_space) &&
-			     (left_space != NO_SPACE))) {
-				hfs_bnode_shift_left(left.bn, bnode,
-						     bnode->ndNRecs);
-			} else {
-				hfs_bnode_shift_right(bnode, right.bn, 1);
-				fix_right_key = 1;
-			}
-			delete_empty_bnode(left_node, &left, &belem->bnr,
-					   right_node, &right);
-		} else if (min_space == right_space) {
-			balance(bnode, right.bn);
-			fix_right_key = 1;
-		} else {
-			balance(left.bn, bnode);
-			fix_key = 1;
-		}
-
-		if (fix_right_key) {
-			hfs_bnode_update_key(brec, belem, right.bn, 1);
-		}
-
-		hfs_bnode_relse(&left);
-		hfs_bnode_relse(&right);
-
-		if (bnode->ndNRecs) {
-			if (fix_key) {
-				hfs_bnode_update_key(brec, belem, bnode, 0);
-			}
-			goto done;
-		}
-
-		hfs_bnode_free(&belem->bnr);
-		--brec->bottom;
-		belem = parent;
-		--parent;
-	}
-
-	if (belem < brec->top) {
-		hfs_warn("hfs_bdelete: Missing parent.\n");
-		hfs_brec_relse(brec, NULL);
-		return -EIO;
-	}
-
-	bdelete_nonempty(brec, belem);
-
-done:
-	hfs_brec_relse(brec, NULL);
-	return 0;
-}
-
-/*================ Global functions ================*/
-
-/*
- * hfs_bdelete()
- *
- * Delete the requested record from a B-tree.
- */
-int hfs_bdelete(struct hfs_btree *tree, const struct hfs_bkey *key)
-{ 
-	struct hfs_belem *belem;
-	struct hfs_bnode *bnode;
-	struct hfs_brec brec;
-	int retval;
-
-	if (!tree || (tree->magic != HFS_BTREE_MAGIC) || !key) {
-		hfs_warn("hfs_bdelete: invalid arguments.\n");
-		return -EINVAL;
-	}
-
-	retval = hfs_bfind(&brec, tree, key, HFS_BFIND_DELETE);
-	if (!retval) {
-		belem = brec.bottom;
-		bnode = belem->bnr.bn;
-
-		belem->flags = 0;
-        	if ((bnode->ndNRecs * sizeof(hfs_u16) + bnode_end(bnode) -
-		     bnode_rsize(bnode, belem->record)) < FULL/2) {
-			belem->flags |= HFS_BPATH_UNDERFLOW;
-		}
-		if (belem->record == 1) {
-			belem->flags |= HFS_BPATH_FIRST;
-		}
-
-		if (!belem->flags) {
-			hfs_brec_lock(&brec, brec.bottom);
-		} else {
-			hfs_brec_lock(&brec, NULL);
-		}
-
-		retval = bdelete(&brec);
-		if (!retval) {
-			--brec.tree->bthNRecs;
-			brec.tree->dirt = 1;
-		}
-		hfs_brec_relse(&brec, NULL);
-	}
-	return retval;
-}
--- diff/fs/hfs/bins_del.c	2002-10-16 04:29:02.000000000 +0100
+++ source/fs/hfs/bins_del.c	1970-01-01 01:00:00.000000000 +0100
@@ -1,231 +0,0 @@
-/*
- * linux/fs/hfs/bins_del.c
- *
- * Copyright (C) 1995-1997  Paul H. Hargrove
- * This file may be distributed under the terms of the GNU General Public License.
- *
- * This file contains the code common to inserting and deleting records
- * in a B-tree.
- *
- * "XXX" in a comment is a note to myself to consider changing something.
- *
- * In function preconditions the term "valid" applied to a pointer to
- * a structure means that the pointer is non-NULL and the structure it
- * points to has all fields initialized to consistent values.
- */
-
-#include "hfs_btree.h"
-
-/*================ File-local functions ================*/
-
-/*
- * hfs_bnode_update_key()
- *
- * Description:
- *   Updates the key for a bnode in its parent.
- *   The key change is propagated up the tree as necessary.
- * Input Variable(s):
- *   struct hfs_brec *brec: the search path to update keys in
- *   struct hfs_belem *belem: the search path element with the changed key
- *   struct hfs_bnode *bnode: the bnode with the changed key
- *   int offset: the "distance" from 'belem->bn' to 'bnode':
- *    0 if the change is in 'belem->bn',
- *    1 if the change is in its right sibling, etc.
- * Output Variable(s):
- *   NONE
- * Returns:
- *   void
- * Preconditions:
- *   'brec' points to a valid (struct hfs_brec)
- *   'belem' points to a valid (struct hfs_belem) in 'brec'.
- *   'bnode' points to a valid (struct hfs_bnode) which is non-empty
- *    and is 'belem->bn' or one of its siblings.
- *   'offset' is as described above.
- * Postconditions:
- *   The key change is propagated up the tree as necessary.
- */
-void hfs_bnode_update_key(struct hfs_brec *brec, struct hfs_belem *belem,
-			  struct hfs_bnode *bnode, int offset)
-{
-	int record = (--belem)->record + offset;
-	void *key = bnode_datastart(bnode) + 1;
-	int keysize = brec->tree->bthKeyLen;
-	struct hfs_belem *limit;
-
-  	memcpy(1+bnode_key(belem->bnr.bn, record), key, keysize);
-
-	/* don't trash the header */
-	if (brec->top > &brec->elem[1]) {
-		limit = brec->top;
-	} else {
-		limit = &brec->elem[1];
-	}
-
-	while ((belem > limit) && (record == 1)) {
-		record = (--belem)->record;
-		memcpy(1+belem_key(belem), key, keysize);
-	}
-}
-
-/*
- * hfs_bnode_shift_right()
- *
- * Description:
- *   Shifts some records from a node to its right neighbor.
- * Input Variable(s):
- *   struct hfs_bnode* left: the node to shift records from
- *   struct hfs_bnode* right: the node to shift records to
- *   hfs_u16 first: the number of the first record in 'left' to move to 'right'
- * Output Variable(s):
- *   NONE
- * Returns:
- *   void
- * Preconditions:
- *   'left' and 'right' point to valid (struct hfs_bnode)s.
- *   'left' contains at least 'first' records.
- *   'right' has enough free space to hold the records to be moved from 'left'
- * Postconditions:
- *   The record numbered 'first' and all records after it in 'left' are
- *   placed at the beginning of 'right'.
- *   The key corresponding to 'right' in its parent is NOT updated.
- */
-void hfs_bnode_shift_right(struct hfs_bnode *left, struct hfs_bnode *right,
-			   int first)
-{
-	int i, adjust, nrecs;
-	unsigned size;
-	hfs_u16 *to, *from;
-
-	if ((first <= 0) || (first > left->ndNRecs)) {
-		hfs_warn("bad argument to shift_right: first=%d, nrecs=%d\n",
-		       first, left->ndNRecs);
-		return;
-	}
-
-	/* initialize variables */
-	nrecs = left->ndNRecs + 1 - first;
-	size = bnode_end(left) - bnode_offset(left, first);
-
-	/* move (possibly empty) contents of right node forward */
-	memmove(bnode_datastart(right) + size,
-		bnode_datastart(right), 
-		bnode_end(right) - sizeof(struct NodeDescriptor));
-
-	/* copy in new records */
-	memcpy(bnode_datastart(right), bnode_key(left,first), size);
-
-	/* fix up offsets in right node */
-	i = right->ndNRecs + 1;
-	from = RECTBL(right, i);
-	to = from - nrecs;
-	while (i--) {
-		hfs_put_hs(hfs_get_hs(from++) + size, to++);
-	}
-	adjust = sizeof(struct NodeDescriptor) - bnode_offset(left, first);
-	i = nrecs-1;
-	from = RECTBL(left, first+i);
-	while (i--) {
-		hfs_put_hs(hfs_get_hs(from++) + adjust, to++);
-	}
-
-	/* fix record counts */
-	left->ndNRecs -= nrecs;
-	right->ndNRecs += nrecs;
-}
-
-/*
- * hfs_bnode_shift_left()
- *
- * Description:
- *   Shifts some records from a node to its left neighbor.
- * Input Variable(s):
- *   struct hfs_bnode* left: the node to shift records to
- *   struct hfs_bnode* right: the node to shift records from
- *   hfs_u16 last: the number of the last record in 'right' to move to 'left'
- * Output Variable(s):
- *   NONE
- * Returns:
- *   void
- * Preconditions:
- *   'left' and 'right' point to valid (struct hfs_bnode)s.
- *   'right' contains at least 'last' records.
- *   'left' has enough free space to hold the records to be moved from 'right'
- * Postconditions:
- *   The record numbered 'last' and all records before it in 'right' are
- *   placed at the end of 'left'.
- *   The key corresponding to 'right' in its parent is NOT updated.
- */
-void hfs_bnode_shift_left(struct hfs_bnode *left, struct hfs_bnode *right,
-			  int last)
-{
-	int i, adjust, nrecs;
-	unsigned size;
-	hfs_u16 *to, *from;
-
-	if ((last <= 0) || (last > right->ndNRecs)) {
-		hfs_warn("bad argument to shift_left: last=%d, nrecs=%d\n",
-		       last, right->ndNRecs);
-		return;
-	}
-
-	/* initialize variables */
-	size = bnode_offset(right, last + 1) - sizeof(struct NodeDescriptor);
-
-	/* copy records to left node */
-	memcpy(bnode_dataend(left), bnode_datastart(right), size);
-
-	/* move (possibly empty) remainder of right node backward */
-	memmove(bnode_datastart(right), bnode_datastart(right) + size, 
-			bnode_end(right) - bnode_offset(right, last + 1));
-
-	/* fix up offsets */
-	nrecs = left->ndNRecs;
-	i = last;
-	from = RECTBL(right, 2);
-	to = RECTBL(left, nrecs + 2);
-	adjust = bnode_offset(left, nrecs + 1) - sizeof(struct NodeDescriptor);
-	while (i--) {
-		hfs_put_hs(hfs_get_hs(from--) + adjust, to--);
-	}
-	i = right->ndNRecs + 1 - last;
-	++from;
-	to = RECTBL(right, 1);
-	while (i--) {
-		hfs_put_hs(hfs_get_hs(from--) - size, to--);
-	}
-
-	/* fix record counts */
-	left->ndNRecs += last;
-	right->ndNRecs -= last;
-}
-
-/*
- * hfs_bnode_in_brec()
- *
- * Description:
- *   Determines whethet a given bnode is part of a given brec.
- *   This is used to avoid deadlock in the case of a corrupted b-tree.
- * Input Variable(s):
- *   hfs_u32 node: the number of the node to check for.
- *   struct hfs_brec* brec: the brec to check in.
- * Output Variable(s):
- *   NONE
- * Returns:
- *   int: 1 it found, 0 if not
- * Preconditions:
- *   'brec' points to a valid struct hfs_brec.
- * Postconditions:
- *   'brec' is unchanged.
- */
-int hfs_bnode_in_brec(hfs_u32 node, const struct hfs_brec *brec)
-{
-	const struct hfs_belem *belem = brec->bottom;
-
-	while (belem && (belem >= brec->top)) {
-		if (belem->bnr.bn && (belem->bnr.bn->node == node)) {
-			return 1;
-		}
-		--belem;
-	}
-	return 0;
-}
--- diff/fs/hfs/binsert.c	2002-10-16 04:28:24.000000000 +0100
+++ source/fs/hfs/binsert.c	1970-01-01 01:00:00.000000000 +0100
@@ -1,536 +0,0 @@
-/*
- * linux/fs/hfs/binsert.c
- *
- * Copyright (C) 1995-1997  Paul H. Hargrove
- * This file may be distributed under the terms of the GNU General Public License.
- *
- * This file contains the code to insert records in a B-tree.
- *
- * "XXX" in a comment is a note to myself to consider changing something.
- *
- * In function preconditions the term "valid" applied to a pointer to
- * a structure means that the pointer is non-NULL and the structure it
- * points to has all fields initialized to consistent values.
- */
-
-#include "hfs_btree.h"
-
-/*================ File-local functions ================*/
-/*
- * binsert_nonfull()
- *
- * Description:
- *   Inserts a record in a given bnode known to have sufficient space.
- * Input Variable(s):
- *   struct hfs_brec* brec: pointer to the brec for the insertion
- *   struct hfs_belem* belem: the element in the search path to insert in
- *   struct hfs_bkey* key: pointer to the key for the record to insert
- *   void* data: pointer to the record to insert
- *   hfs_u16 keysize: size of the key to insert
- *   hfs_u16 datasize: size of the record to insert
- * Output Variable(s):
- *   NONE
- * Returns:
- *   NONE
- * Preconditions:
- *   'brec' points to a valid (struct hfs_brec).
- *   'belem' points to a valid (struct hfs_belem) in 'brec', the node
- *    of which has enough free space to insert 'key' and 'data'.
- *   'key' is a pointer to a valid (struct hfs_bkey) of length 'keysize'
- *    which, in sorted order, belongs at the location indicated by 'brec'.
- *   'data' is non-NULL an points to appropriate data of length 'datasize'
- * Postconditions:
- *   The record has been inserted in the position indicated by 'brec'.
- */
-static void binsert_nonfull(struct hfs_brec *brec, struct hfs_belem *belem,
-			    const struct hfs_bkey *key, const void *data,
-			    hfs_u8 keysize, hfs_u16 datasize)
-{
-	int i, rec, nrecs, size, tomove;
-	hfs_u8 *start;
-	struct hfs_bnode *bnode = belem->bnr.bn;
-
-	rec = ++(belem->record);
-	size = ROUND(keysize+1) + datasize;
-	nrecs = bnode->ndNRecs + 1;
-	tomove = bnode_offset(bnode, nrecs) - bnode_offset(bnode, rec);
-	
-	/* adjust the record table */
-	for (i = nrecs; i >= rec; --i) {
-		hfs_put_hs(bnode_offset(bnode,i) + size, RECTBL(bnode,i+1));
-	}
-
-	/* make room */
-	start = bnode_key(bnode, rec);
-	memmove(start + size, start, tomove);
-
-	/* copy in the key and the data*/
-	*start = keysize;
-	keysize = ROUND(keysize+1);
-	memcpy(start + 1, (hfs_u8 *)key + 1, keysize-1);
-	memcpy(start + keysize, data, datasize);
-
-	/* update record count */
-	++bnode->ndNRecs;
-}
-
-/*
- * add_root()
- *
- * Description:
- *   Adds a new root to a B*-tree, increasing its height.
- * Input Variable(s):
- *   struct hfs_btree *tree: the tree to add a new root to
- *   struct hfs_bnode *left: the new root's first child or NULL
- *   struct hfs_bnode *right: the new root's second child or NULL
- * Output Variable(s):
- *   NONE
- * Returns:
- *   void
- * Preconditions:
- *   'tree' points to a valid (struct hfs_btree).
- *   'left' and 'right' point to valid (struct hfs_bnode)s, which
- *    resulted from splitting the old root node, or are both NULL
- *    if there was no root node before.
- * Postconditions:
- *   Upon success a new root node is added to 'tree' with either
- *    two children ('left' and 'right') or none.
- */
-static void add_root(struct hfs_btree *tree,
-		     struct hfs_bnode *left,
-		     struct hfs_bnode *right)
-{
-	struct hfs_bnode_ref bnr;
-	struct hfs_bnode *root;
-	struct hfs_bkey *key;
-	int keylen = tree->bthKeyLen;
-
-	if (left && !right) {
-		hfs_warn("add_root: LEFT but no RIGHT\n");
-		return;
-	}
-
-	bnr = hfs_bnode_alloc(tree);
-	if (!(root = bnr.bn)) {
-		return;
-	}
-
-	root->sticky = HFS_STICKY;
-	tree->root = root;
-	tree->bthRoot = root->node;
-	++tree->bthDepth;
-
-	root->ndNHeight = tree->bthDepth;
-	root->ndFLink = 0;
-	root->ndBLink = 0;
-
-	if (!left) {
-		/* tree was empty */
-		root->ndType  = ndLeafNode;
-		root->ndNRecs = 0;
-
-		tree->bthFNode = root->node;
-		tree->bthLNode = root->node;
-	} else {
-		root->ndType  = ndIndxNode;
-		root->ndNRecs = 2;
-
-		hfs_put_hs(sizeof(struct NodeDescriptor) + ROUND(1+keylen) +
-			   sizeof(hfs_u32), RECTBL(root, 2));
-		key = bnode_key(root, 1);
-		key->KeyLen = keylen;
-		memcpy(key->value,
-		       ((struct hfs_bkey *)bnode_key(left, 1))->value, keylen);
-		hfs_put_hl(left->node, bkey_record(key));
-		
-		hfs_put_hs(sizeof(struct NodeDescriptor) + 2*ROUND(1+keylen) +
-			   2*sizeof(hfs_u32), RECTBL(root, 3));
-		key = bnode_key(root, 2);
-		key->KeyLen = keylen;
-		memcpy(key->value,
-		       ((struct hfs_bkey *)bnode_key(right, 1))->value, keylen);
-		hfs_put_hl(right->node, bkey_record(key));
-
-		/* the former root (left) is now just a normal node */
-		left->sticky = HFS_NOT_STICKY;
-		if ((left->next = bhash(tree, left->node))) {
-			left->next->prev = left;
-		}
-		bhash(tree, left->node) = left;
-	}
-	hfs_bnode_relse(&bnr);
-	tree->dirt = 1;
-}
-
-/*
- * insert_empty_bnode()
- *
- * Description:
- *   Adds an empty node to the right of 'left'.
- * Input Variable(s):
- *   struct hfs_btree *tree: the tree to add a node to
- *   struct hfs_bnode *left: the node to add a node after
- * Output Variable(s):
- *   NONE
- * Returns:
- *   struct hfs_bnode_ref *: reference to the new bnode.
- * Preconditions:
- *   'tree' points to a valid (struct hfs_btree) with at least 1 free node.
- *   'left' points to a valid (struct hfs_bnode) belonging to 'tree'.
- * Postconditions:
- *   If NULL is returned then 'tree' and 'left' are unchanged.
- *   Otherwise a node with 0 records is inserted in the tree to the right
- *   of the node 'left'.  The 'ndFLink' of 'left' and the 'ndBLink' of
- *   the former right-neighbor of 'left' (if one existed) point to the
- *   new node.	If 'left' had no right neighbor and is a leaf node the
- *   the 'bthLNode' of 'tree' points to the new node.  The free-count and
- *   bitmap for 'tree' are kept current by hfs_bnode_alloc() which supplies
- *   the required node.
- */
-static struct hfs_bnode_ref insert_empty_bnode(struct hfs_btree *tree,
-					       struct hfs_bnode *left)
-{
-	struct hfs_bnode_ref retval;
-	struct hfs_bnode_ref right;
-
-	retval = hfs_bnode_alloc(tree);
-	if (!retval.bn) {
-		hfs_warn("hfs_binsert: out of bnodes?.\n");
-		goto done;
-	}
-	retval.bn->sticky = HFS_NOT_STICKY;
-	if ((retval.bn->next = bhash(tree, retval.bn->node))) {
-		retval.bn->next->prev = retval.bn;
-	}
-	bhash(tree, retval.bn->node) = retval.bn;
-
-	if (left->ndFLink) {
-		right = hfs_bnode_find(tree, left->ndFLink, HFS_LOCK_WRITE);
-		if (!right.bn) {
-			hfs_warn("hfs_binsert: corrupt btree.\n");
-			hfs_bnode_bitop(tree, retval.bn->node, 0);
-			hfs_bnode_relse(&retval);
-			goto done;
-		}
-		right.bn->ndBLink = retval.bn->node;
-		hfs_bnode_relse(&right);
-	} else if (left->ndType == ndLeafNode) {
-		tree->bthLNode = retval.bn->node;
-		tree->dirt = 1;
-	}
-
-	retval.bn->ndFLink   = left->ndFLink;
-	retval.bn->ndBLink   = left->node;
-	retval.bn->ndType    = left->ndType;
-	retval.bn->ndNHeight = left->ndNHeight;
-	retval.bn->ndNRecs   = 0;
-
-	left->ndFLink = retval.bn->node;
-
- done:
-	return retval;
-}
-
-/*
- * split()
- *
- * Description:
- *   Splits an over full node during insertion.
- *   Picks the split point that results in the most-nearly equal
- *   space usage in the new and old nodes.
- * Input Variable(s):
- *   struct hfs_belem *elem: the over full node.
- *   int size: the number of bytes to be used by the new record and its key.
- * Output Variable(s):
- *   struct hfs_belem *elem: changed to indicate where the new record
- *    should be inserted.
- * Returns:
- *   struct hfs_bnode_ref: reference to the new bnode.
- * Preconditions:
- *   'elem' points to a valid path element corresponding to the over full node.
- *   'size' is positive.
- * Postconditions:
- *   The records in the node corresponding to 'elem' are redistributed across
- *   the old and new nodes so that after inserting the new record, the space
- *   usage in these two nodes is as equal as possible.
- *   'elem' is updated so that a call to binsert_nonfull() will insert the
- *   new record in the correct location.
- */
-static inline struct hfs_bnode_ref split(struct hfs_belem *elem, int size)
-{
-	struct hfs_bnode *bnode = elem->bnr.bn;
-	int nrecs, cutoff, index, tmp, used, in_right;
-	struct hfs_bnode_ref right;
-
-	right = insert_empty_bnode(bnode->tree, bnode);
-	if (right.bn) {
-		nrecs = bnode->ndNRecs;
-		cutoff = (size + bnode_end(bnode) -
-			      sizeof(struct NodeDescriptor) +
-			      (nrecs+1)*sizeof(hfs_u16))/2;
-		used = 0;
-		in_right = 1;
-		/* note that this only works because records sizes are even */
-		for (index=1; index <= elem->record; ++index) {
-			tmp = (sizeof(hfs_u16) + bnode_rsize(bnode, index))/2;
-			used += tmp;
-			if (used > cutoff) {
-				goto found;
-			}
-			used += tmp;
-		}
-		tmp = (size + sizeof(hfs_u16))/2;
-		used += tmp;
-		if (used > cutoff) {
-			goto found;
-		}
-		in_right = 0;
-		used += tmp;
-		for (; index <= nrecs; ++index) {
-			tmp = (sizeof(hfs_u16) + bnode_rsize(bnode, index))/2;
-			used += tmp;
-			if (used > cutoff) {
-				goto found;
-			}
-			used += tmp;
-		}
-		/* couldn't find the split point! */
-		hfs_bnode_relse(&right);
-	}
-	return right;
-
-found:
-	if (in_right) {
-		elem->bnr = right;
-		elem->record -= index-1;
-	}
-	hfs_bnode_shift_right(bnode, right.bn, index);
-
-	return right;
-}
-
-/*
- * binsert()
- *
- * Description:
- *   Inserts a record in a tree known to have enough room, even if the
- *   insertion requires the splitting of nodes.
- * Input Variable(s):
- *    struct hfs_brec *brec: partial path to the node to insert in
- *    const struct hfs_bkey *key: key for the new record
- *    const void *data: data for the new record
- *    hfs_u8 keysize: size of the key
- *    hfs_u16 datasize: size of the data
- *    int reserve: number of nodes reserved in case of splits
- * Output Variable(s):
- *    *brec = NULL
- * Returns:
- *    int: 0 on success, error code on failure
- * Preconditions:
- *    'brec' points to a valid (struct hfs_brec) corresponding to a
- *     record in a leaf node, after which a record is to be inserted,
- *     or to "record 0" of the leaf node if the record is to be inserted
- *     before all existing records in the node.	 The (struct hfs_brec)
- *     includes all ancestors of the leaf node that are needed to
- *     complete the insertion including the parents of any nodes that
- *     will be split.
- *    'key' points to a valid (struct hfs_bkey) which is appropriate
- *     to this tree, and which belongs at the insertion point.
- *    'data' points data appropriate for the indicated node.
- *    'keysize' gives the size in bytes of the key.
- *    'datasize' gives the size in bytes of the data.
- *    'reserve' gives the number of nodes that have been reserved in the
- *     tree to allow for splitting of nodes.
- * Postconditions:
- *    All 'reserve'd nodes have been either used or released.
- *    *brec = NULL
- *    On success the key and data have been inserted at the indicated
- *    location in the tree, all appropriate fields of the in-core data
- *    structures have been changed and updated versions of the on-disk
- *    data structures have been scheduled for write-back to disk.
- *    On failure the B*-tree is probably invalid both on disk and in-core.
- *
- *    XXX: Some attempt at repair might be made in the event of failure,
- *    or the fs should be remounted read-only so things don't get worse.
- */
-static int binsert(struct hfs_brec *brec, const struct hfs_bkey *key,
-		   const void *data, hfs_u8 keysize, hfs_u16 datasize,
-		   int reserve)
-{
-	struct hfs_bnode_ref left, right, other;
-	struct hfs_btree *tree = brec->tree;
-	struct hfs_belem *belem = brec->bottom;
-	int tmpsize = 1 + tree->bthKeyLen;
-	struct hfs_bkey *tmpkey = hfs_malloc(tmpsize);
-	hfs_u32 node;
-	
-	while ((belem >= brec->top) && (belem->flags & HFS_BPATH_OVERFLOW)) {
-		left = belem->bnr;
-		if (left.bn->ndFLink &&
-                    hfs_bnode_in_brec(left.bn->ndFLink, brec)) {
-			hfs_warn("hfs_binsert: corrupt btree\n");
-			tree->reserved -= reserve;
-			hfs_free(tmpkey, tmpsize);
-			return -EIO;
-		}
-			
-		right = split(belem, ROUND(keysize+1) + ROUND(datasize));
-		--reserve;
-		--tree->reserved;
-		if (!right.bn) {
-			hfs_warn("hfs_binsert: unable to split node!\n");
-			tree->reserved -= reserve;
-			hfs_free(tmpkey, tmpsize);
-			return -ENOSPC;
-		}
-		binsert_nonfull(brec, belem, key, data, keysize, datasize);
-	
-		if (belem->bnr.bn == left.bn) {
-			other = right;
-			if (belem->record == 1) {
-				hfs_bnode_update_key(brec, belem, left.bn, 0);
-			}
-		} else {
-			other = left;
-		}
-
-		if (left.bn->node == tree->root->node) {
-			add_root(tree, left.bn, right.bn);
-			hfs_bnode_relse(&other);
-			goto done;
-		}
-
-		data = &node;
-		datasize = sizeof(node);
-		node = htonl(right.bn->node);
-		key = tmpkey;
-		keysize = tree->bthKeyLen;
-		memcpy(tmpkey, bnode_key(right.bn, 1), keysize+1);
-		hfs_bnode_relse(&other);
-		
-		--belem;
-	}
-
-	if (belem < brec->top) {
-		hfs_warn("hfs_binsert: Missing parent.\n");
-		tree->reserved -= reserve;
-		hfs_free(tmpkey, tmpsize);
-		return -EIO;
-	}
-
-	binsert_nonfull(brec, belem, key, data, keysize, datasize);
-
-done:
-	tree->reserved -= reserve;
-	hfs_free(tmpkey, tmpsize);
-	return 0;
-}
-
-/*================ Global functions ================*/
-
-/*
- * hfs_binsert()
- *
- * Description:
- *   This function inserts a new record into a b-tree.
- * Input Variable(s):
- *   struct hfs_btree *tree: pointer to the (struct hfs_btree) to insert in
- *   struct hfs_bkey *key: pointer to the (struct hfs_bkey) to insert
- *   void *data: pointer to the data to associate with 'key' in the b-tree
- *   unsigned int datasize: the size of the data
- * Output Variable(s):
- *   NONE
- * Returns:
- *   int: 0 on success, error code on failure
- * Preconditions:
- *   'tree' points to a valid (struct hfs_btree)
- *   'key' points to a valid (struct hfs_bkey)
- *   'data' points to valid memory of length 'datasize'
- * Postconditions:
- *   If zero is returned then the record has been inserted in the
- *    indicated location updating all in-core data structures and
- *    scheduling all on-disk data structures for write-back.
- */
-int hfs_binsert(struct hfs_btree *tree, const struct hfs_bkey *key,
-		const void *data, hfs_u16 datasize)
-{ 
-	struct hfs_brec brec;
-	struct hfs_belem *belem;
-	int err, reserve, retval;
-	hfs_u8 keysize;
-
-	if (!tree || (tree->magic != HFS_BTREE_MAGIC) || !key || !data) {
-		hfs_warn("hfs_binsert: invalid arguments.\n");
-		return -EINVAL;
-	}
-
-	if (key->KeyLen > tree->bthKeyLen) {
-		hfs_warn("hfs_binsert: oversized key\n");
-		return -EINVAL;
-	}
-
-restart:
-	if (!tree->bthNRecs) {
-		/* create the root bnode */
-		add_root(tree, NULL, NULL);
-		if (!hfs_brec_init(&brec, tree, HFS_BFIND_INSERT)) {
-			hfs_warn("hfs_binsert: failed to create root.\n");
-			return -ENOSPC;
-		}
-	} else {
-		err = hfs_bfind(&brec, tree, key, HFS_BFIND_INSERT);
-		if (err < 0) {
-			hfs_warn("hfs_binsert: hfs_brec_find failed.\n");
-			return err;
-		} else if (err == 0) {
-			hfs_brec_relse(&brec, NULL);
-			return -EEXIST;
-		}
-	}
-
-	keysize = key->KeyLen;
-	datasize = ROUND(datasize);
-	belem = brec.bottom;
-	belem->flags = 0;
-	if (bnode_freespace(belem->bnr.bn) <
-			    (sizeof(hfs_u16) + ROUND(keysize+1) + datasize)) {
-		belem->flags |= HFS_BPATH_OVERFLOW;
-	}
-	if (belem->record == 0) {
-		belem->flags |= HFS_BPATH_FIRST;
-	}
-
-	if (!belem->flags) {
-		hfs_brec_lock(&brec, brec.bottom);
-		reserve = 0;
-	} else {
-		reserve = brec.bottom - brec.top;
-		if (brec.top == 0) {
-			++reserve;
-		}
-		/* make certain we have enough nodes to proceed */
-		if ((tree->bthFree - tree->reserved) < reserve) {
-			hfs_brec_relse(&brec, NULL);
-			down(&tree->sem);
-			if ((tree->bthFree - tree->reserved) < reserve) {
-				hfs_btree_extend(tree);
-			}
-			up(&tree->sem);
-			if ((tree->bthFree - tree->reserved) < reserve) {
-				return -ENOSPC;
-			} else {
-				goto restart;
-			}
-		}
-		tree->reserved += reserve;
-		hfs_brec_lock(&brec, NULL);
-	}
-
-	retval = binsert(&brec, key, data, keysize, datasize, reserve);
-	hfs_brec_relse(&brec, NULL);
-	if (!retval) {
-		++tree->bthNRecs;
-		tree->dirt = 1;
-	}
-	return retval;
-}
--- diff/fs/hfs/bitops.c	2002-10-16 04:28:34.000000000 +0100
+++ source/fs/hfs/bitops.c	1970-01-01 01:00:00.000000000 +0100
@@ -1,124 +0,0 @@
-/*
- * linux/fs/hfs/bitops.c
- *
- * Copyright (C) 1996  Paul H. Hargrove
- * This file may be distributed under the terms of the GNU General Public License.
- *
- * This file contains functions to handle bitmaps in "left-to-right"
- * bit-order such that the MSB of a 32-bit big-endian word is bit 0.
- * (This corresponds to bit 7 of a 32-bit little-endian word.)
- *
- * I have tested and confirmed that the results are identical on the
- * Intel x86, PowerPC and DEC Alpha processors.
- *
- * "XXX" in a comment is a note to myself to consider changing something.
- */
-
-#include "hfs.h"
-
-/*================ Global functions ================*/
-
-/*
- * hfs_find_zero_bit()
- *
- * Description:
- *  Given a block of memory, its length in bits, and a starting bit number,
- *  determine the number of the first zero bits (in left-to-right ordering)
- *  in that range.
- *
- *  Returns >= 'size' if no zero bits are found in the range.
- *
- *  Accesses memory in 32-bit aligned chunks of 32-bits and thus
- *  may read beyond the 'size'th bit.
- */
-hfs_u32 hfs_find_zero_bit(const hfs_u32 *start, hfs_u32 size, hfs_u32 offset)
-{
-	const hfs_u32 *end   = start + ((size + 31) >> 5);
-	const hfs_u32 *curr  = start + (offset >> 5);
-	int bit = offset % 32;
-	
-	if (offset < size) {
-		/* scan the first partial hfs_u32 for zero bits */
-		if (bit != 0) {
-			do {
-				if (!hfs_test_bit(bit, curr)) {
-					goto done;
-				}
-				++bit;
-			} while (bit < 32);
-			bit = 0;
-			++curr;
-		}
-	
-		/* scan complete hfs_u32s for the first zero bit */
-		while (curr < end) {
-			if (*curr == ~((hfs_u32)0)) {
-				++curr;
-			} else {
-				while (hfs_test_bit(bit, curr)) {
-					++bit;
-				}
-				break;
-			}
-		}
-
-done:
-		bit |= (curr - start) << 5;
-		return bit;
-	} else {
-		return size;
-	}
-}
-
-/*
- * hfs_count_zero_bits()
- *
- * Description:
- *  Given a block of memory, its length in bits, and a starting bit number,
- *  determine the number of consecutive zero bits (in left-to-right ordering)
- *  in that range.
- *
- *  Accesses memory in 32-bit aligned chunks of 32-bits and thus
- *  may read beyond the 'size'th bit.
- */
-hfs_u32 hfs_count_zero_bits(const hfs_u32 *start, hfs_u32 size, hfs_u32 offset)
-{
-	const hfs_u32 *end   = start + ((size + 31) >> 5);
-	const hfs_u32 *curr  = start + (offset >> 5);
-	int bit = offset % 32;
-
-	if (offset < size) {
-		/* scan the first partial hfs_u32 for one bits */
-		if (bit != 0) {
-			do {
-				if (hfs_test_bit(bit, curr)) {
-					goto done;
-				}
-				++bit;
-			} while (bit < 32);
-			bit = 0;
-			++curr;
-		}
-	
-		/* scan complete hfs_u32s for the first one bit */
-		while (curr < end) {
-			if (*curr == ((hfs_u32)0)) {
-				++curr;
-			} else {
-				while (!hfs_test_bit(bit, curr)) {
-					++bit;
-				}
-				break;
-			}
-		}
-
-done:
-		bit |= (curr - start) << 5;
-		if (bit > size) {
-			bit = size;
-		}
-		return bit - offset;
-	} else {
-		return 0;
-	}
-}
--- diff/fs/hfs/dir_cap.c	2003-07-11 09:39:50.000000000 +0100
+++ source/fs/hfs/dir_cap.c	1970-01-01 01:00:00.000000000 +0100
@@ -1,335 +0,0 @@
-/*
- * Copyright (C) 1995-1997  Paul H. Hargrove
- * This file may be distributed under the terms of the GNU General Public License.
- *
- * This file contains the inode_operations and file_operations
- * structures for HFS directories under the CAP scheme.
- *
- * Based on the minix file system code, (C) 1991, 1992 by Linus Torvalds
- *
- * The source code distribution of the Columbia AppleTalk Package for
- * UNIX, version 6.0, (CAP) was used as a specification of the
- * location and format of files used by CAP's Aufs.  No code from CAP
- * appears in hfs_fs.  hfs_fs is not a work ``derived'' from CAP in
- * the sense of intellectual property law.
- *
- * "XXX" in a comment is a note to myself to consider changing something.
- *
- * In function preconditions the term "valid" applied to a pointer to
- * a structure means that the pointer is non-NULL and the structure it
- * points to has all fields initialized to consistent values.
- */
-
-#include "hfs.h"
-#include <linux/hfs_fs_sb.h>
-#include <linux/hfs_fs_i.h>
-#include <linux/hfs_fs.h>
-#include <linux/smp_lock.h>
-
-/*================ Forward declarations ================*/
-
-static struct dentry *cap_lookup(struct inode *, struct dentry *, struct nameidata *);
-static int cap_readdir(struct file *, void *, filldir_t);
-
-/*================ Global variables ================*/
-
-#define DOT_LEN			1
-#define DOT_DOT_LEN		2
-#define DOT_RESOURCE_LEN	9
-#define DOT_FINDERINFO_LEN	11
-#define DOT_ROOTINFO_LEN	9
-
-const struct hfs_name hfs_cap_reserved1[] = {
-	{DOT_LEN,		"."},
-	{DOT_DOT_LEN,		".."},
-	{DOT_RESOURCE_LEN,	".resource"},
-	{DOT_FINDERINFO_LEN,	".finderinfo"},
-	{0,			""},
-};
-
-const struct hfs_name hfs_cap_reserved2[] = {
-	{DOT_ROOTINFO_LEN,	".rootinfo"},
-	{0,			""},
-};
-
-#define DOT		(&hfs_cap_reserved1[0])
-#define DOT_DOT		(&hfs_cap_reserved1[1])
-#define DOT_RESOURCE	(&hfs_cap_reserved1[2])
-#define DOT_FINDERINFO	(&hfs_cap_reserved1[3])
-#define DOT_ROOTINFO	(&hfs_cap_reserved2[0])
-
-struct file_operations hfs_cap_dir_operations = {
-	.read		= generic_read_dir,
-	.readdir	= cap_readdir,
-	.fsync		= file_fsync,
-};
-
-struct inode_operations hfs_cap_ndir_inode_operations = {
-	.create		= hfs_create,
-	.lookup		= cap_lookup,
-	.unlink		= hfs_unlink,
-	.mkdir		= hfs_mkdir,
-	.rmdir		= hfs_rmdir,
-	.rename		= hfs_rename,
-	.setattr	= hfs_notify_change,
-};
-
-struct inode_operations hfs_cap_fdir_inode_operations = {
-	.lookup		= cap_lookup,
-	.setattr	= hfs_notify_change,
-};
-
-struct inode_operations hfs_cap_rdir_inode_operations = {
-	.create		= hfs_create,
-	.lookup		= cap_lookup,
-	.setattr	= hfs_notify_change,
-};
-
-/*================ File-local functions ================*/
-
-/*
- * cap_lookup()
- *
- * This is the lookup() entry in the inode_operations structure for
- * HFS directories in the CAP scheme.  The purpose is to generate the
- * inode corresponding to an entry in a directory, given the inode for
- * the directory and the name (and its length) of the entry.
- */
-static struct dentry *cap_lookup(struct inode * dir, struct dentry *dentry, struct nameidata *nd)
-{
-	ino_t dtype;
-	struct hfs_name cname;
-	struct hfs_cat_entry *entry;
-	struct hfs_cat_key key;
-	struct inode *inode = NULL;
-
-	lock_kernel();
-
-	dentry->d_op = &hfs_dentry_operations;
-	entry = HFS_I(dir)->entry;
-	dtype = HFS_ITYPE(dir->i_ino);
-
-	/* Perform name-mangling */
-	hfs_nameout(dir, &cname, dentry->d_name.name, 
-		    dentry->d_name.len);
-
-	/* no need to check for "."  or ".." */
-
-	/* Check for epecial directories if in a normal directory.
-	   Note that cap_dupdir() does an iput(dir). */
-	if (dtype==HFS_CAP_NDIR) {
-		/* Check for ".resource", ".finderinfo" and ".rootinfo" */
-		if (hfs_streq(cname.Name, cname.Len, 
-			      DOT_RESOURCE->Name, DOT_RESOURCE_LEN)) {
-			++entry->count; /* __hfs_iget() eats one */
-			inode = hfs_iget(entry, HFS_CAP_RDIR, dentry);
-			goto done;
-		} else if (hfs_streq(cname.Name, cname.Len, 
-				     DOT_FINDERINFO->Name, 
-				     DOT_FINDERINFO_LEN)) {
-			++entry->count; /* __hfs_iget() eats one */
-			inode = hfs_iget(entry, HFS_CAP_FDIR, dentry);
-			goto done;
-		} else if ((entry->cnid == htonl(HFS_ROOT_CNID)) &&
-			   hfs_streq(cname.Name, cname.Len, 
-				     DOT_ROOTINFO->Name, DOT_ROOTINFO_LEN)) {
-			++entry->count; /* __hfs_iget() eats one */
-			inode = hfs_iget(entry, HFS_CAP_FNDR, dentry);
-			goto done;
-		}
-	}
-
-	/* Do an hfs_iget() on the mangled name. */
-	hfs_cat_build_key(entry->cnid, &cname, &key);
-	inode = hfs_iget(hfs_cat_get(entry->mdb, &key),
-			 HFS_I(dir)->file_type, dentry);
-
-	/* Don't return a resource fork for a directory */
-	if (inode && (dtype == HFS_CAP_RDIR) && 
-	    (HFS_I(inode)->entry->type == HFS_CDR_DIR)) {
-	        iput(inode); /* this does an hfs_cat_put */
-		inode = NULL;
-	}
-
-done:
-	unlock_kernel();
-	d_add(dentry, inode);
-	return NULL;
-}
-
-/*
- * cap_readdir()
- *
- * This is the readdir() entry in the file_operations structure for
- * HFS directories in the CAP scheme.  The purpose is to enumerate the
- * entries in a directory, given the inode of the directory and a
- * (struct file *), the 'f_pos' field of which indicates the location
- * in the directory.  The (struct file *) is updated so that the next
- * call with the same 'dir' and 'filp' arguments will produce the next
- * directory entry.  The entries are returned in 'dirent', which is
- * "filled-in" by calling filldir().  This allows the same readdir()
- * function be used for different dirent formats.  We try to read in
- * as many entries as we can before filldir() refuses to take any more.
- *
- * XXX: In the future it may be a good idea to consider not generating
- * metadata files for covered directories since the data doesn't
- * correspond to the mounted directory.	 However this requires an
- * iget() for every directory which could be considered an excessive
- * amount of overhead.	Since the inode for a mount point is always
- * in-core this is another argument for a call to get an inode if it
- * is in-core or NULL if it is not.
- */
-static int cap_readdir(struct file * filp,
-		       void * dirent, filldir_t filldir)
-{
-	ino_t type;
-	int skip_dirs;
-	struct hfs_brec brec;
-        struct hfs_cat_entry *entry;
-	struct inode *dir = filp->f_dentry->d_inode;
-
-	lock_kernel();
-
-	entry = HFS_I(dir)->entry;
-	type = HFS_ITYPE(dir->i_ino);
-	skip_dirs = (type == HFS_CAP_RDIR);
-
-	if (filp->f_pos == 0) {
-		/* Entry 0 is for "." */
-		if (filldir(dirent, DOT->Name, DOT_LEN, 0, dir->i_ino, DT_DIR)) {
-			goto out;
-		}
-		filp->f_pos = 1;
-	}
-
-	if (filp->f_pos == 1) {
-		/* Entry 1 is for ".." */
-		hfs_u32 cnid;
-
-		if (type == HFS_CAP_NDIR) {
-			cnid = hfs_get_nl(entry->key.ParID);
-		} else {
-			cnid = entry->cnid;
-		}
-
-		if (filldir(dirent, DOT_DOT->Name,
-			    DOT_DOT_LEN, 1, ntohl(cnid), DT_DIR)) {
-			goto out;
-		}
-		filp->f_pos = 2;
-	}
-
-	if (filp->f_pos < (dir->i_size - 3)) {
-		hfs_u32 cnid;
-		hfs_u8 type;
-
-	    	if (hfs_cat_open(entry, &brec) ||
-	    	    hfs_cat_next(entry, &brec, filp->f_pos - 2, &cnid, &type)) {
-			goto out;
-		}
-		while (filp->f_pos < (dir->i_size - 3)) {
-			if (hfs_cat_next(entry, &brec, 1, &cnid, &type)) {
-				goto out;
-			}
-			if (!skip_dirs || (type != HFS_CDR_DIR)) {
-				ino_t ino;
-				unsigned int len;
-				unsigned char tmp_name[HFS_NAMEMAX];
-
-				ino = ntohl(cnid) | HFS_I(dir)->file_type;
-				len = hfs_namein(dir, tmp_name,
-				    &((struct hfs_cat_key *)brec.key)->CName);
-				if (filldir(dirent, tmp_name, len,
-					    filp->f_pos, ino, DT_UNKNOWN)) {
-					hfs_cat_close(entry, &brec);
-					goto out;
-				}
-			}
-			++filp->f_pos;
-		}
-		hfs_cat_close(entry, &brec);
-	}
-
-	if (filp->f_pos == (dir->i_size - 3)) {
-		if ((entry->cnid == htonl(HFS_ROOT_CNID)) &&
-		    (type == HFS_CAP_NDIR)) {
-			/* In root dir last-2 entry is for ".rootinfo" */
-			if (filldir(dirent, DOT_ROOTINFO->Name,
-				    DOT_ROOTINFO_LEN, filp->f_pos,
-				    ntohl(entry->cnid) | HFS_CAP_FNDR,
-				    DT_UNKNOWN)) {
-				goto out;
-			}
-		}
-		++filp->f_pos;
-	}
-
-	if (filp->f_pos == (dir->i_size - 2)) {
-		if (type == HFS_CAP_NDIR) {
-			/* In normal dirs last-1 entry is for ".finderinfo" */
-			if (filldir(dirent, DOT_FINDERINFO->Name,
-				    DOT_FINDERINFO_LEN, filp->f_pos,
-				    ntohl(entry->cnid) | HFS_CAP_FDIR,
-				    DT_UNKNOWN)) {
-				goto out;
-			}
-		}
-		++filp->f_pos;
-	}
-
-	if (filp->f_pos == (dir->i_size - 1)) {
-		if (type == HFS_CAP_NDIR) {
-			/* In normal dirs last entry is for ".resource" */
-			if (filldir(dirent, DOT_RESOURCE->Name,
-				    DOT_RESOURCE_LEN, filp->f_pos,
-				    ntohl(entry->cnid) | HFS_CAP_RDIR,
-				    DT_UNKNOWN)) {
-				goto out;
-			}
-		}
-		++filp->f_pos;
-	}
-
-out:
-	unlock_kernel();
-	return 0;
-}
-
-
-/* due to the dcache caching negative dentries for non-existent files,
- * we need to drop those entries when a file silently gets created.
- * as far as i can tell, the calls that need to do this are the file
- * related calls (create, rename, and mknod). the directory calls
- * should be immune. the relevant calls in dir.c call drop_dentry 
- * upon successful completion. */
-void hfs_cap_drop_dentry(struct dentry *dentry, const ino_t type)
-{
-  if (type == HFS_CAP_DATA) { /* given name */
-    hfs_drop_special(dentry->d_parent, DOT_FINDERINFO, dentry);
-    hfs_drop_special(dentry->d_parent, DOT_RESOURCE, dentry);
-  } else {
-    struct dentry *de;
-
-    /* given {.resource,.finderinfo}/name, look for name */
-    if ((de = hfs_lookup_dentry(dentry->d_parent->d_parent,
-				dentry->d_name.name, dentry->d_name.len))) {
-      if (!de->d_inode)
-	d_drop(de);
-      dput(de);
-    }
-    
-    switch (type) {
-    case HFS_CAP_RSRC: /* given .resource/name */
-       /* look for .finderinfo/name */
-      hfs_drop_special(dentry->d_parent->d_parent, DOT_FINDERINFO, 
-		       dentry);
-      break;
-    case HFS_CAP_FNDR: /* given .finderinfo/name. i don't this 
-			* happens. */
-      /* look for .resource/name */
-      hfs_drop_special(dentry->d_parent->d_parent, DOT_RESOURCE, 
-		       dentry);
-      break;
-    }
-  }
-}
--- diff/fs/hfs/dir_dbl.c	2003-07-11 09:39:50.000000000 +0100
+++ source/fs/hfs/dir_dbl.c	1970-01-01 01:00:00.000000000 +0100
@@ -1,421 +0,0 @@
-/*
- * linux/fs/hfs/dir_dbl.c
- *
- * Copyright (C) 1995-1997  Paul H. Hargrove
- * This file may be distributed under the terms of the GNU General Public License.
- *
- * This file contains the inode_operations and file_operations
- * structures for HFS directories.
- *
- * Based on the minix file system code, (C) 1991, 1992 by Linus Torvalds
- *
- * "XXX" in a comment is a note to myself to consider changing something.
- *
- * In function preconditions the term "valid" applied to a pointer to
- * a structure means that the pointer is non-NULL and the structure it
- * points to has all fields initialized to consistent values.
- */
-
-#include "hfs.h"
-#include <linux/hfs_fs_sb.h>
-#include <linux/hfs_fs_i.h>
-#include <linux/hfs_fs.h>
-#include <linux/smp_lock.h>
-
-/*================ Forward declarations ================*/
-
-static struct dentry *dbl_lookup(struct inode *, struct dentry *, struct nameidata *);
-static int dbl_readdir(struct file *, void *, filldir_t);
-static int dbl_create(struct inode *, struct dentry *, int, struct nameidata *);
-static int dbl_mkdir(struct inode *, struct dentry *, int);
-static int dbl_unlink(struct inode *, struct dentry *);
-static int dbl_rmdir(struct inode *, struct dentry *);
-static int dbl_rename(struct inode *, struct dentry *,
-		      struct inode *, struct dentry *);
-
-/*================ Global variables ================*/
-
-#define DOT_LEN			1
-#define DOT_DOT_LEN		2
-#define ROOTINFO_LEN		8
-#define PCNT_ROOTINFO_LEN	9
-
-const struct hfs_name hfs_dbl_reserved1[] = {
-	{DOT_LEN,		"."},
-	{DOT_DOT_LEN,		".."},
-	{0,			""},
-};
-
-const struct hfs_name hfs_dbl_reserved2[] = {
-	{ROOTINFO_LEN,		"RootInfo"},
-	{PCNT_ROOTINFO_LEN,	"%RootInfo"},
-	{0,			""},
-};
-
-#define DOT		(&hfs_dbl_reserved1[0])
-#define DOT_DOT		(&hfs_dbl_reserved1[1])
-#define ROOTINFO	(&hfs_dbl_reserved2[0])
-#define PCNT_ROOTINFO	(&hfs_dbl_reserved2[1])
-
-struct file_operations hfs_dbl_dir_operations = {
-	.read		= generic_read_dir,
-	.readdir	= dbl_readdir,
-	.fsync		= file_fsync,
-};
-
-struct inode_operations hfs_dbl_dir_inode_operations = {
-	.create		= dbl_create,
-	.lookup		= dbl_lookup,
-	.unlink		= dbl_unlink,
-	.mkdir		= dbl_mkdir,
-	.rmdir		= dbl_rmdir,
-	.rename		= dbl_rename,
-	.setattr	= hfs_notify_change,
-};
-
-
-/*================ File-local functions ================*/
-
-/*
- * is_hdr()
- */
-static int is_hdr(struct inode *dir, const char *name, int len)
-{
-	int retval = 0;
-
-	if (name[0] == '%') {
-		struct hfs_cat_entry *entry = HFS_I(dir)->entry;
-		struct hfs_cat_entry *victim;
-		struct hfs_name cname;
-		struct hfs_cat_key key;
-
-		hfs_nameout(dir, &cname, name+1, len-1);
-		hfs_cat_build_key(entry->cnid, &cname, &key);
-		if ((victim = hfs_cat_get(entry->mdb, &key))) {
-			hfs_cat_put(victim);
-			retval = 1;
-		}
-	}
-	return retval;
-}
-
-/*
- * dbl_lookup()
- *
- * This is the lookup() entry in the inode_operations structure for
- * HFS directories in the AppleDouble scheme.  The purpose is to
- * generate the inode corresponding to an entry in a directory, given
- * the inode for the directory and the name (and its length) of the
- * entry.
- */
-static struct dentry *dbl_lookup(struct inode * dir, struct dentry *dentry, struct nameidata *nd)
-{
-	struct hfs_name cname;
-	struct hfs_cat_entry *entry;
-	struct hfs_cat_key key;
-	struct inode *inode = NULL;
-
-	lock_kernel();
-	dentry->d_op = &hfs_dentry_operations;
-	entry = HFS_I(dir)->entry;
-	
-	/* Perform name-mangling */
-	hfs_nameout(dir, &cname, dentry->d_name.name, dentry->d_name.len);
- 
-	/* no need to check for "."  or ".." */
-
-	/* Check for "%RootInfo" if in the root directory. */
-	if ((entry->cnid == htonl(HFS_ROOT_CNID)) &&
-	    hfs_streq(cname.Name, cname.Len, 
-		      PCNT_ROOTINFO->Name, PCNT_ROOTINFO_LEN)) {
-		++entry->count; /* __hfs_iget() eats one */
-		inode = hfs_iget(entry, HFS_DBL_HDR, dentry);
-		goto done;
-	}
-
-	/* Do an hfs_iget() on the mangled name. */
-	hfs_cat_build_key(entry->cnid, &cname, &key);
-	inode = hfs_iget(hfs_cat_get(entry->mdb, &key), HFS_DBL_NORM, dentry);
-
-	/* Try as a header if not found and first character is '%' */
-	if (!inode && (dentry->d_name.name[0] == '%')) {
-		hfs_nameout(dir, &cname, dentry->d_name.name+1,
-			    dentry->d_name.len-1);
-		hfs_cat_build_key(entry->cnid, &cname, &key);
-		inode = hfs_iget(hfs_cat_get(entry->mdb, &key),
-				 HFS_DBL_HDR, dentry);
-	}
-	
-done:
-	unlock_kernel();
-	d_add(dentry, inode);
-	return NULL;
-}
-
-/*
- * dbl_readdir()
- *
- * This is the readdir() entry in the file_operations structure for
- * HFS directories in the AppleDouble scheme.  The purpose is to
- * enumerate the entries in a directory, given the inode of the
- * directory and a (struct file *), the 'f_pos' field of which
- * indicates the location in the directory.  The (struct file *) is
- * updated so that the next call with the same 'dir' and 'filp'
- * arguments will produce the next directory entry.  The entries are
- * returned in 'dirent', which is "filled-in" by calling filldir().
- * This allows the same readdir() function be used for different
- * formats.  We try to read in as many entries as we can before
- * filldir() refuses to take any more.
- *
- * XXX: In the future it may be a good idea to consider not generating
- * metadata files for covered directories since the data doesn't
- * correspond to the mounted directory.	 However this requires an
- * iget() for every directory which could be considered an excessive
- * amount of overhead.	Since the inode for a mount point is always
- * in-core this is another argument for a call to get an inode if it
- * is in-core or NULL if it is not.
- */
-static int dbl_readdir(struct file * filp,
-		       void * dirent, filldir_t filldir)
-{
-	struct hfs_brec brec;
-        struct hfs_cat_entry *entry;
-	struct inode *dir = filp->f_dentry->d_inode;
-
-	lock_kernel();
-
-	entry = HFS_I(dir)->entry;
-
-	if (filp->f_pos == 0) {
-		/* Entry 0 is for "." */
-		if (filldir(dirent, DOT->Name, DOT_LEN, 0, dir->i_ino,
-			    DT_DIR)) {
-			goto out;
-		}
-		filp->f_pos = 1;
-	}
-
-	if (filp->f_pos == 1) {
-		/* Entry 1 is for ".." */
-		if (filldir(dirent, DOT_DOT->Name, DOT_DOT_LEN, 1,
-			    hfs_get_hl(entry->key.ParID), DT_DIR)) {
-			goto out;	
-		}
-		filp->f_pos = 2;
-	}
-
-	if (filp->f_pos < (dir->i_size - 1)) {
-                hfs_u32 cnid;
-                hfs_u8 type;
-
-		if (hfs_cat_open(entry, &brec) ||
-		    hfs_cat_next(entry, &brec, (filp->f_pos - 1) >> 1,
-				 &cnid, &type)) {
-			goto out;
-		}
-
-		while (filp->f_pos < (dir->i_size - 1)) {
-			unsigned char tmp_name[HFS_NAMEMAX + 1];
-			ino_t ino;
-			int is_hdr = (filp->f_pos & 1);
-			unsigned int len;
-
-			if (is_hdr) {
-				ino = ntohl(cnid) | HFS_DBL_HDR;
-				tmp_name[0] = '%';
-				len = 1 + hfs_namein(dir, tmp_name + 1,
-				    &((struct hfs_cat_key *)brec.key)->CName);
-			} else {
-				if (hfs_cat_next(entry, &brec, 1,
-							&cnid, &type)) {
-					goto out;
-				}
-				ino = ntohl(cnid);
-				len = hfs_namein(dir, tmp_name,
-				    &((struct hfs_cat_key *)brec.key)->CName);
-			}
-
-			if (filldir(dirent, tmp_name, len, filp->f_pos, ino,
-				    DT_UNKNOWN)) {
-				hfs_cat_close(entry, &brec);
-				goto out;
-			}
-			++filp->f_pos;
-		}
-		hfs_cat_close(entry, &brec);
-	}
-
-	if (filp->f_pos == (dir->i_size - 1)) {
-		if (entry->cnid == htonl(HFS_ROOT_CNID)) {
-			/* In root dir last entry is for "%RootInfo" */
-			if (filldir(dirent, PCNT_ROOTINFO->Name,
-				    PCNT_ROOTINFO_LEN, filp->f_pos,
-				    ntohl(entry->cnid) | HFS_DBL_HDR,
-				    DT_UNKNOWN)) {
-				goto out;
-			}
-		}
-		++filp->f_pos;
-	}
-
-out:
-	unlock_kernel();
-	return 0;
-}
-
-/*
- * dbl_create()
- *
- * This is the create() entry in the inode_operations structure for
- * AppleDouble directories.  The purpose is to create a new file in
- * a directory and return a corresponding inode, given the inode for
- * the directory and the name (and its length) of the new file.
- */
-static int dbl_create(struct inode * dir, struct dentry *dentry,
-		      int mode, struct nameidata *nd)
-{
-	int error;
-
-	lock_kernel();
-	if (is_hdr(dir, dentry->d_name.name, dentry->d_name.len)) {
-		error = -EEXIST;
-	} else {
-		error = hfs_create(dir, dentry, mode, nd);
-	}
-	unlock_kernel();
-	return error;
-}
-
-/*
- * dbl_mkdir()
- *
- * This is the mkdir() entry in the inode_operations structure for
- * AppleDouble directories.  The purpose is to create a new directory
- * in a directory, given the inode for the parent directory and the
- * name (and its length) of the new directory.
- */
-static int dbl_mkdir(struct inode * parent, struct dentry *dentry,
-		     int mode)
-{
-	int error;
-
-	lock_kernel();
-	if (is_hdr(parent, dentry->d_name.name, dentry->d_name.len)) {
-		error = -EEXIST;
-	} else {
-		error = hfs_mkdir(parent, dentry, mode);
-	}
-	unlock_kernel();
-	return error;
-}
-
-/*
- * dbl_unlink()
- *
- * This is the unlink() entry in the inode_operations structure for
- * AppleDouble directories.  The purpose is to delete an existing
- * file, given the inode for the parent directory and the name
- * (and its length) of the existing file.
- */
-static int dbl_unlink(struct inode * dir, struct dentry *dentry)
-{
-	int error;
-
-	lock_kernel();
-	error = hfs_unlink(dir, dentry);
-	if ((error == -ENOENT) && is_hdr(dir, dentry->d_name.name,
-					 dentry->d_name.len)) {
-		error = -EPERM;
-	}
-	unlock_kernel();
-	return error;
-}
-
-/*
- * dbl_rmdir()
- *
- * This is the rmdir() entry in the inode_operations structure for
- * AppleDouble directories.  The purpose is to delete an existing
- * directory, given the inode for the parent directory and the name
- * (and its length) of the existing directory.
- */
-static int dbl_rmdir(struct inode * parent, struct dentry *dentry)
-{
-	int error;
-
-	lock_kernel();
-	error = hfs_rmdir(parent, dentry);
-	if ((error == -ENOENT) && is_hdr(parent, dentry->d_name.name,
-					 dentry->d_name.len)) {
-		error = -ENOTDIR;
-	}
-	unlock_kernel();
-	return error;
-}
-
-/*
- * dbl_rename()
- *
- * This is the rename() entry in the inode_operations structure for
- * AppleDouble directories.  The purpose is to rename an existing
- * file or directory, given the inode for the current directory and
- * the name (and its length) of the existing file/directory and the
- * inode for the new directory and the name (and its length) of the
- * new file/directory.
- * 
- * XXX: how do we handle must_be_dir?
- */
-static int dbl_rename(struct inode *old_dir, struct dentry *old_dentry,
-		      struct inode *new_dir, struct dentry *new_dentry)
-{
-	int error;
-
-	lock_kernel();
-	if (is_hdr(new_dir, new_dentry->d_name.name,
-		   new_dentry->d_name.len)) {
-		error = -EPERM;
-	} else {
-		error = hfs_rename(old_dir, old_dentry,
-				   new_dir, new_dentry);
-		if ((error == -ENOENT) /*&& !must_be_dir*/ &&
-		    is_hdr(old_dir, old_dentry->d_name.name,
-			   old_dentry->d_name.len)) {
-			error = -EPERM;
-		}
-	}
-	unlock_kernel();
-	return error;
-}
-
-
-/* due to the dcache caching negative dentries for non-existent files,
- * we need to drop those entries when a file silently gets created.
- * as far as i can tell, the calls that need to do this are the file
- * related calls (create, rename, and mknod). the directory calls
- * should be immune. the relevant calls in dir.c call drop_dentry 
- * upon successful completion. */
-void hfs_dbl_drop_dentry(struct dentry *dentry, const ino_t type)
-{
-  unsigned char tmp_name[HFS_NAMEMAX + 1];
-  struct dentry *de = NULL;
-
-  switch (type) {
-  case HFS_DBL_HDR:
-   /* given %name, look for name. i don't think this happens. */
-   de = hfs_lookup_dentry(dentry->d_parent,
-			  dentry->d_name.name + 1, dentry->d_name.len - 1);
-    break;
-  case HFS_DBL_DATA:
-    /* given name, look for %name */
-    tmp_name[0] = '%';
-    strncpy(tmp_name + 1, dentry->d_name.name, HFS_NAMELEN - 1);
-    de = hfs_lookup_dentry(dentry->d_parent, 
-			   tmp_name, dentry->d_name.len + 1);
-  }
-
-  if (de) {
-    if (!de->d_inode)
-      d_drop(de);
-    dput(de);
-  }
-}
--- diff/fs/hfs/dir_nat.c	2003-07-11 09:39:50.000000000 +0100
+++ source/fs/hfs/dir_nat.c	1970-01-01 01:00:00.000000000 +0100
@@ -1,467 +0,0 @@
-/*
- * linux/fs/hfs/dir_nat.c
- *
- * Copyright (C) 1995-1997  Paul H. Hargrove
- * This file may be distributed under the terms of the GNU General Public License.
- *
- * This file contains the inode_operations and file_operations
- * structures for HFS directories.
- *
- * Based on the minix file system code, (C) 1991, 1992 by Linus Torvalds
- *
- * The source code distributions of Netatalk, versions 1.3.3b2 and
- * 1.4b2, were used as a specification of the location and format of
- * files used by Netatalk's afpd.  No code from Netatalk appears in
- * hfs_fs.  hfs_fs is not a work ``derived'' from Netatalk in the
- * sense of intellectual property law.
- *
- * "XXX" in a comment is a note to myself to consider changing something.
- *
- * In function preconditions the term "valid" applied to a pointer to
- * a structure means that the pointer is non-NULL and the structure it
- * points to has all fields initialized to consistent values.
- */
-
-#include "hfs.h"
-#include <linux/hfs_fs_sb.h>
-#include <linux/hfs_fs_i.h>
-#include <linux/hfs_fs.h>
-#include <linux/smp_lock.h>
-
-/*================ Forward declarations ================*/
-
-static struct dentry *nat_lookup(struct inode *, struct dentry *, struct nameidata *);
-static int nat_readdir(struct file *, void *, filldir_t);
-static int nat_rmdir(struct inode *, struct dentry *);
-static int nat_hdr_unlink(struct inode *, struct dentry *);
-static int nat_hdr_rename(struct inode *, struct dentry *,
-			  struct inode *, struct dentry *);
-
-/*================ Global variables ================*/
-
-#define DOT_LEN			1
-#define DOT_DOT_LEN		2
-#define DOT_APPLEDOUBLE_LEN	12
-#define DOT_PARENT_LEN		7
-#define ROOTINFO_LEN            8
-
-const struct hfs_name hfs_nat_reserved1[] = {
-	{DOT_LEN,		"."},
-	{DOT_DOT_LEN,		".."},
-	{DOT_APPLEDOUBLE_LEN,	".AppleDouble"},
-	{DOT_PARENT_LEN,	".Parent"},
-	{0,			""},
-};
-
-const struct hfs_name hfs_nat_reserved2[] = {
-	{ROOTINFO_LEN,			"RootInfo"},
-};
-
-#define DOT		(&hfs_nat_reserved1[0])
-#define DOT_DOT		(&hfs_nat_reserved1[1])
-#define DOT_APPLEDOUBLE	(&hfs_nat_reserved1[2])
-#define DOT_PARENT	(&hfs_nat_reserved1[3])
-#define ROOTINFO        (&hfs_nat_reserved2[0])
-
-struct file_operations hfs_nat_dir_operations = {
-	.read		= generic_read_dir,
-	.readdir	= nat_readdir,
-	.fsync		= file_fsync,
-};
-
-struct inode_operations hfs_nat_ndir_inode_operations = {
-	.create		= hfs_create,
-	.lookup		= nat_lookup,
-	.unlink		= hfs_unlink,
-	.mkdir		= hfs_mkdir,
-	.rmdir		= nat_rmdir,
-	.rename		= hfs_rename,
-	.setattr	= hfs_notify_change,
-};
-
-struct inode_operations hfs_nat_hdir_inode_operations = {
-	.create		= hfs_create,
-	.lookup		= nat_lookup,
-	.unlink		= nat_hdr_unlink,
-	.rename		= nat_hdr_rename,
-	.setattr	= hfs_notify_change,
-};
-
-/*================ File-local functions ================*/
-
-/*
- * nat_lookup()
- *
- * This is the lookup() entry in the inode_operations structure for
- * HFS directories in the Netatalk scheme.  The purpose is to generate
- * the inode corresponding to an entry in a directory, given the inode
- * for the directory and the name (and its length) of the entry.
- */
-static struct dentry *nat_lookup(struct inode * dir, struct dentry *dentry, struct nameidata *nd)
-{
-	ino_t dtype;
-	struct hfs_name cname;
-	struct hfs_cat_entry *entry;
-	struct hfs_cat_key key;
-	struct inode *inode = NULL;
-
-	lock_kernel();
-	dentry->d_op = &hfs_dentry_operations;
-	entry = HFS_I(dir)->entry;
-	dtype = HFS_ITYPE(dir->i_ino);
-
-	/* Perform name-mangling */
-	hfs_nameout(dir, &cname, dentry->d_name.name, dentry->d_name.len);
-
-	/* no need to check for "."  or ".." */
-
-	/* Check for ".AppleDouble" if in a normal directory,
-	   and for ".Parent" in ".AppleDouble". */
-	if (dtype==HFS_NAT_NDIR) {
-		/* Check for ".AppleDouble" */
-		if (hfs_streq(cname.Name, cname.Len, 
-			      DOT_APPLEDOUBLE->Name, DOT_APPLEDOUBLE_LEN)) {
-			++entry->count; /* __hfs_iget() eats one */
-			inode = hfs_iget(entry, HFS_NAT_HDIR, dentry);
-			goto done;
-		}
-	} else if (dtype==HFS_NAT_HDIR) {
-		if (hfs_streq(cname.Name, cname.Len, 
-			      DOT_PARENT->Name, DOT_PARENT_LEN)) {
-			++entry->count; /* __hfs_iget() eats one */
-			inode = hfs_iget(entry, HFS_NAT_HDR, dentry);
-			goto done;
-		}
-
-		if ((entry->cnid == htonl(HFS_ROOT_CNID)) &&
-		    hfs_streq(cname.Name, cname.Len, 
-			      ROOTINFO->Name, ROOTINFO_LEN)) {
-			++entry->count; /* __hfs_iget() eats one */
-			inode = hfs_iget(entry, HFS_NAT_HDR, dentry);
-                        goto done;
-		}
-	}
-
-	/* Do an hfs_iget() on the mangled name. */
-	hfs_cat_build_key(entry->cnid, &cname, &key);
-	inode = hfs_iget(hfs_cat_get(entry->mdb, &key), 
-			 HFS_I(dir)->file_type, dentry);
-
-	/* Don't return a header file for a directory other than .Parent */
-	if (inode && (dtype == HFS_NAT_HDIR) &&
-	    (HFS_I(inode)->entry != entry) &&
-	    (HFS_I(inode)->entry->type == HFS_CDR_DIR)) {
-	        iput(inode); /* this does an hfs_cat_put */
-		inode = NULL;
-	}
-
-done:
-	unlock_kernel();
-	d_add(dentry, inode);
-	return NULL;
-}
-
-/*
- * nat_readdir()
- *
- * This is the readdir() entry in the file_operations structure for
- * HFS directories in the netatalk scheme.  The purpose is to
- * enumerate the entries in a directory, given the inode of the
- * directory and a struct file which indicates the location in the
- * directory.  The struct file is updated so that the next call with
- * the same dir and filp will produce the next directory entry.	 The
- * entries are returned in dirent, which is "filled-in" by calling
- * filldir().  This allows the same readdir() function be used for
- * different dirent formats.  We try to read in as many entries as we
- * can before filldir() refuses to take any more.
- *
- * Note that the Netatalk format doesn't have the problem with
- * metadata for covered directories that exists in the other formats,
- * since the metadata is contained within the directory.
- */
-static int nat_readdir(struct file * filp,
-		       void * dirent, filldir_t filldir)
-{
-	ino_t type;
-	int skip_dirs;
-	struct hfs_brec brec;
-        struct hfs_cat_entry *entry;
-	struct inode *dir = filp->f_dentry->d_inode;
-
-	lock_kernel();
-	
-	entry = HFS_I(dir)->entry;
-	type = HFS_ITYPE(dir->i_ino);
-	skip_dirs = (type == HFS_NAT_HDIR);
-
-	if (filp->f_pos == 0) {
-		/* Entry 0 is for "." */
-		if (filldir(dirent, DOT->Name, DOT_LEN, 0, dir->i_ino,
-			    DT_DIR)) {
-			goto out;
-		}
-		filp->f_pos = 1;
-	}
-
-	if (filp->f_pos == 1) {
-		/* Entry 1 is for ".." */
-		hfs_u32 cnid;
-
-		if (type == HFS_NAT_NDIR) {
-			cnid = hfs_get_nl(entry->key.ParID);
-		} else {
-			cnid = entry->cnid;
-		}
-
-		if (filldir(dirent, DOT_DOT->Name,
-			    DOT_DOT_LEN, 1, ntohl(cnid), DT_DIR)) {
-			goto out;
-		}
-		filp->f_pos = 2;
-	}
-
-	if (filp->f_pos < (dir->i_size - 2)) {
-		hfs_u32 cnid;
-		hfs_u8 type;
-
-	    	if (hfs_cat_open(entry, &brec) ||
-		    hfs_cat_next(entry, &brec, filp->f_pos - 2, &cnid, &type)) {
-			goto out;
-		}
-		while (filp->f_pos < (dir->i_size - 2)) {
-			if (hfs_cat_next(entry, &brec, 1, &cnid, &type)) {
-				goto out;
-			}
-			if (!skip_dirs || (type != HFS_CDR_DIR)) {
-				ino_t ino;
-				unsigned int len;
-				unsigned char tmp_name[HFS_NAMEMAX];
-
-				ino = ntohl(cnid) | HFS_I(dir)->file_type;
-				len = hfs_namein(dir, tmp_name,
-				    &((struct hfs_cat_key *)brec.key)->CName);
-				if (filldir(dirent, tmp_name, len,
-					    filp->f_pos, ino, DT_UNKNOWN)) {
-					hfs_cat_close(entry, &brec);
-					goto out;
-				}
-			}
-			++filp->f_pos;
-		}
-		hfs_cat_close(entry, &brec);
-	}
-
-	if (filp->f_pos == (dir->i_size - 2)) {
-		if (type == HFS_NAT_NDIR) {
-			/* In normal dirs entry 2 is for ".AppleDouble" */
-			if (filldir(dirent, DOT_APPLEDOUBLE->Name,
-				    DOT_APPLEDOUBLE_LEN, filp->f_pos,
-				    ntohl(entry->cnid) | HFS_NAT_HDIR,
-				    DT_UNKNOWN)) {
-				goto out;
-			}
-		} else if (type == HFS_NAT_HDIR) {
-			/* In .AppleDouble entry 2 is for ".Parent" */
-			if (filldir(dirent, DOT_PARENT->Name,
-				    DOT_PARENT_LEN, filp->f_pos,
-				    ntohl(entry->cnid) | HFS_NAT_HDR,
-				    DT_UNKNOWN)) {
-				goto out;
-			}
-		}
-		++filp->f_pos;
-	}
-
-	if (filp->f_pos == (dir->i_size - 1)) {
-		/* handle ROOT/.AppleDouble/RootInfo as the last entry. */
-		if ((entry->cnid == htonl(HFS_ROOT_CNID)) &&
-		    (type == HFS_NAT_HDIR)) {
-			if (filldir(dirent, ROOTINFO->Name,
-				    ROOTINFO_LEN, filp->f_pos,
-				    ntohl(entry->cnid) | HFS_NAT_HDR,
-				    DT_UNKNOWN)) {
-				goto out;
-			}
-		}
-		++filp->f_pos;
-	}
-
-out:
-	unlock_kernel();
-	return 0;
-}
-
-/* due to the dcache caching negative dentries for non-existent files,
- * we need to drop those entries when a file silently gets created.
- * as far as i can tell, the calls that need to do this are the file
- * related calls (create, rename, and mknod). the directory calls
- * should be immune. the relevant calls in dir.c call drop_dentry 
- * upon successful completion. */
-void hfs_nat_drop_dentry(struct dentry *dentry, const ino_t type)
-{
-  struct dentry *de;
-  
-  switch (type) {
-  case HFS_NAT_HDR: /* given .AppleDouble/name */
-    /* look for name */
-    de = hfs_lookup_dentry(dentry->d_parent->d_parent,
-			   dentry->d_name.name, dentry->d_name.len);
-
-    if (de) {
-      if (!de->d_inode)
-	d_drop(de);
-      dput(de);
-    }
-    break;
-  case HFS_NAT_DATA: /* given name */
-    /* look for .AppleDouble/name */
-    hfs_drop_special(dentry->d_parent, DOT_APPLEDOUBLE, dentry);
-    break;
-  }
-
-}
-
-/*
- * nat_rmdir()
- *
- * This is the rmdir() entry in the inode_operations structure for
- * Netatalk directories.  The purpose is to delete an existing
- * directory, given the inode for the parent directory and the name
- * (and its length) of the existing directory.
- *
- * We handle .AppleDouble and call hfs_rmdir() for all other cases.
- */
-static int nat_rmdir(struct inode *parent, struct dentry *dentry)
-{
-	struct hfs_cat_entry *entry = HFS_I(parent)->entry;
-	struct hfs_name cname;
-	int error;
-
-	lock_kernel();
-	hfs_nameout(parent, &cname, dentry->d_name.name, dentry->d_name.len);
-	if (hfs_streq(cname.Name, cname.Len,
-		      DOT_APPLEDOUBLE->Name, DOT_APPLEDOUBLE_LEN)) {
-		if (!HFS_SB(parent->i_sb)->s_afpd) {
-			/* Not in AFPD compatibility mode */
-			error = -EPERM;
-		} else if (entry->u.dir.files || entry->u.dir.dirs) {
-			/* AFPD compatible, but the directory is not empty */
-			error = -ENOTEMPTY;
-		} else {
-			/* AFPD compatible, so pretend to succeed */
-			error = 0;
-		}
-	} else {
-		error = hfs_rmdir(parent, dentry);
-	}
-	unlock_kernel();
-	return error;
-}
-
-/*
- * nat_hdr_unlink()
- *
- * This is the unlink() entry in the inode_operations structure for
- * Netatalk .AppleDouble directories.  The purpose is to delete an
- * existing file, given the inode for the parent directory and the name
- * (and its length) of the existing file.
- *
- * WE DON'T ACTUALLY DELETE HEADER THE FILE.
- * In non-afpd-compatible mode:
- *   We return -EPERM.
- * In afpd-compatible mode:
- *   We return success if the file exists or is .Parent.
- *   Otherwise we return -ENOENT.
- */
-static int nat_hdr_unlink(struct inode *dir, struct dentry *dentry)
-{
-	struct hfs_cat_entry *entry;
-	int error = 0;
-
-	lock_kernel();
-	entry = HFS_I(dir)->entry;
-	if (!HFS_SB(dir->i_sb)->s_afpd) {
-		/* Not in AFPD compatibility mode */
-		error = -EPERM;
-	} else {
-		struct hfs_name cname;
-
-		hfs_nameout(dir, &cname, dentry->d_name.name, 
-			    dentry->d_name.len);
-		if (!hfs_streq(cname.Name, cname.Len,
-			       DOT_PARENT->Name, DOT_PARENT_LEN)) {
-			struct hfs_cat_entry *victim;
-			struct hfs_cat_key key;
-
-			hfs_cat_build_key(entry->cnid, &cname, &key);
-			victim = hfs_cat_get(entry->mdb, &key);
-
-			if (victim) {
-				/* pretend to succeed */
-				hfs_cat_put(victim);
-			} else {
-				error = -ENOENT;
-			}
-		}
-	}
-	unlock_kernel();
-	return error;
-}
-
-/*
- * nat_hdr_rename()
- *
- * This is the rename() entry in the inode_operations structure for
- * Netatalk header directories.  The purpose is to rename an existing
- * file given the inode for the current directory and the name 
- * (and its length) of the existing file and the inode for the new
- * directory and the name (and its length) of the new file/directory.
- *
- * WE NEVER MOVE ANYTHING.
- * In non-afpd-compatible mode:
- *   We return -EPERM.
- * In afpd-compatible mode:
- *   If the source header doesn't exist, we return -ENOENT.
- *   If the destination is not a header directory we return -EPERM.
- *   We return success if the destination is also a header directory
- *    and the header exists or is ".Parent".
- */
-static int nat_hdr_rename(struct inode *old_dir, struct dentry *old_dentry,
-			  struct inode *new_dir, struct dentry *new_dentry)
-{
-	struct hfs_cat_entry *entry;
-	int error = 0;
-
-	lock_kernel();
-	entry = HFS_I(old_dir)->entry;
-	if (!HFS_SB(old_dir->i_sb)->s_afpd) {
-		/* Not in AFPD compatibility mode */
-		error = -EPERM;
-	} else {
-		struct hfs_name cname;
-
-		hfs_nameout(old_dir, &cname, old_dentry->d_name.name,
-			    old_dentry->d_name.len);
-		if (!hfs_streq(cname.Name, cname.Len, 
-			       DOT_PARENT->Name, DOT_PARENT_LEN)) {
-			struct hfs_cat_entry *victim;
-			struct hfs_cat_key key;
-
-			hfs_cat_build_key(entry->cnid, &cname, &key);
-			victim = hfs_cat_get(entry->mdb, &key);
-
-			if (victim) {
-				/* pretend to succeed */
-				hfs_cat_put(victim);
-			} else {
-				error = -ENOENT;
-			}
-		}
-
-		if (!error && (HFS_ITYPE(new_dir->i_ino) != HFS_NAT_HDIR)) {
-			error = -EPERM;
-		}
-	}
-	unlock_kernel();
-	return error;
-}
--- diff/fs/hfs/file.c	2003-10-09 09:47:34.000000000 +0100
+++ source/fs/hfs/file.c	1970-01-01 01:00:00.000000000 +0100
@@ -1,527 +0,0 @@
-/*
- * linux/fs/hfs/file.c
- *
- * Copyright (C) 1995, 1996  Paul H. Hargrove
- * This file may be distributed under the terms of the GNU General Public License.
- *
- * This file contains the file-related functions which are independent of
- * which scheme is being used to represent forks.
- *
- * Based on the minix file system code, (C) 1991, 1992 by Linus Torvalds
- *
- * "XXX" in a comment is a note to myself to consider changing something.
- *
- * In function preconditions the term "valid" applied to a pointer to
- * a structure means that the pointer is non-NULL and the structure it
- * points to has all fields initialized to consistent values.
- */
-
-#include "hfs.h"
-#include <linux/hfs_fs_sb.h>
-#include <linux/hfs_fs_i.h>
-#include <linux/hfs_fs.h>
-#include <linux/buffer_head.h>
-#include <linux/smp_lock.h>
-
-/*================ Forward declarations ================*/
-
-static hfs_rwret_t hfs_file_read(struct file *, char __user *, hfs_rwarg_t,
-				 loff_t *);
-static hfs_rwret_t hfs_file_write(struct file *, const char __user *,
-				  hfs_rwarg_t, loff_t *);
-static void hfs_file_truncate(struct inode *);
-
-/*================ Global variables ================*/
-
-struct file_operations hfs_file_operations = {
-	.llseek		= generic_file_llseek,
-	.read		= hfs_file_read,
-	.write		= hfs_file_write,
-	.mmap		= generic_file_mmap,
-	.fsync		= file_fsync,
-};
-
-struct inode_operations hfs_file_inode_operations = {
-	.truncate	= hfs_file_truncate,
-	.setattr	= hfs_notify_change,
-};
-
-/*================ Variable-like macros ================*/
-
-/* maximum number of blocks to try to read in at once */
-#define NBUF 32
-
-/*================ File-local functions ================*/
-
-/*
- * hfs_getblk()
- *
- * Given an hfs_fork and a block number return the buffer_head for
- * that block from the fork.  If 'create' is non-zero then allocate
- * the necessary block(s) to the fork.
- */
-struct buffer_head *hfs_getblk(struct hfs_fork *fork, int block, int create)
-{
-	int tmp;
-	struct super_block *sb = fork->entry->mdb->sys_mdb;
-
-	tmp = hfs_extent_map(fork, block, create);
-
-	if (create) {
-		/* If writing the block, then we have exclusive access
-		   to the file until we return, so it can't have moved.
-		*/
-		if (tmp) {
-			hfs_cat_mark_dirty(fork->entry);
-			return sb_getblk(sb, tmp);
-		}
-		return NULL;
-	} else {
-		/* If reading the block, then retry since the
-		   location on disk could have changed while
-		   we waited on the I/O in getblk to complete.
-		*/
-		do {
-			struct buffer_head *bh = sb_getblk(sb, tmp);
-			int tmp2 = hfs_extent_map(fork, block, 0);
-
-			if (tmp2 == tmp) {
-				return bh;
-			} else {
-				/* The block moved or no longer exists. */
-				brelse(bh);
-				tmp = tmp2;
-			}
-		} while (tmp != 0);
-
-		/* The block no longer exists. */
-		return NULL;
-	}
-}
-
-/*
- * hfs_get_block
- *
- * This is the hfs_get_block() field in the inode_operations structure for
- * "regular" (non-header) files.  The purpose is to translate an inode
- * and a block number within the corresponding file into a physical
- * block number.  This function just calls hfs_extent_map() to do the
- * real work and then stuffs the appropriate info into the buffer_head.
- */
-int hfs_get_block(struct inode *inode, sector_t iblock, struct buffer_head *bh_result, int create)
-{
-	unsigned long phys;
-
-	phys = hfs_extent_map(HFS_I(inode)->fork, iblock, create);
-	if (phys) {
-		if (create)
-			set_buffer_new(bh_result);
-		map_bh(bh_result, inode->i_sb, phys);
-		return 0;
-	}
-
-	if (!create)
-		return 0;
-
-	/* we tried to add stuff, but we couldn't. send back an out-of-space
-	 * error. */
-	return -ENOSPC;
-}
-
-
-/*
- * hfs_file_read()
- *
- * This is the read field in the inode_operations structure for
- * "regular" (non-header) files.  The purpose is to transfer up to
- * 'count' bytes from the file corresponding to 'inode', beginning at
- * 'filp->offset' bytes into the file.	The data is transferred to
- * user-space at the address 'buf'.  Returns the number of bytes
- * successfully transferred.  This function checks the arguments, does
- * some setup and then calls hfs_do_read() to do the actual transfer.  */
-static hfs_rwret_t hfs_file_read(struct file *filp, char __user *buf, 
-				 hfs_rwarg_t count, loff_t *ppos)
-{
-        struct inode *inode = filp->f_dentry->d_inode;
-	hfs_s32 read, left, pos, size;
-
-	if (!S_ISREG(inode->i_mode)) {
-		hfs_warn("hfs_file_read: mode = %07o\n",inode->i_mode);
-		return -EINVAL;
-	}
-	pos = *ppos;
-	if (pos >= HFS_FORK_MAX) {
-		return 0;
-	}
-	size = inode->i_size;
-	if (pos > size) {
-		left = 0;
-	} else {
-		left = size - pos;
-	}
-	if (left > count) {
-		left = count;
-	}
-	if (left <= 0) {
-		return 0;
-	}
-	if ((read = hfs_do_read(inode, HFS_I(inode)->fork, pos, buf, left)) > 0) {
-	        *ppos += read;
-	}
-
-	return read;
-}
-
-/*
- * hfs_file_write()
- *
- * This is the write() entry in the file_operations structure for
- * "regular" files.  The purpose is to transfer up to 'count' bytes
- * to the file corresponding to 'inode' beginning at offset
- * 'file->f_pos' from user-space at the address 'buf'.  The return
- * value is the number of bytes actually transferred.
- */
-static hfs_rwret_t hfs_file_write(struct file *filp, const char __user *buf,
-				  hfs_rwarg_t count, loff_t *ppos)
-{
-        struct inode    *inode = filp->f_dentry->d_inode;
-	struct hfs_fork *fork = HFS_I(inode)->fork;
-	hfs_s32 written, pos;
-
-	if (!S_ISREG(inode->i_mode)) {
-		hfs_warn("hfs_file_write: mode = %07o\n", inode->i_mode);
-		return -EINVAL;
-	}
-
-	pos = (filp->f_flags & O_APPEND) ? inode->i_size : *ppos;
-
-	if (pos >= HFS_FORK_MAX) {
-		return 0;
-	}
-	if (count > HFS_FORK_MAX) {
-		count = HFS_FORK_MAX;
-	}
-	if ((written = hfs_do_write(inode, fork, pos, buf, count)) > 0)
-	        pos += written;
-
-	*ppos = pos;
-	if (*ppos > inode->i_size) {
-	        inode->i_size = *ppos;
-		mark_inode_dirty(inode);
-	}
-
-	return written;
-}
-
-/*
- * hfs_file_truncate()
- *
- * This is the truncate() entry in the file_operations structure for
- * "regular" files.  The purpose is to change the length of the file
- * corresponding to the given inode.  Changes can either lengthen or
- * shorten the file.
- */
-static void hfs_file_truncate(struct inode * inode)
-{
-	struct hfs_fork *fork;
-
-	lock_kernel();
-	fork = HFS_I(inode)->fork;
-	fork->lsize = inode->i_size;
-	hfs_extent_adj(fork);
-	hfs_cat_mark_dirty(HFS_I(inode)->entry);
-
-	inode->i_size = fork->lsize;
-	inode->i_blocks = fork->psize;
-	mark_inode_dirty(inode);
-	unlock_kernel();
-}
-
-/*
- * xlate_to_user()
- *
- * Like copy_to_user() while translating CR->NL.
- */
-static inline void xlate_to_user(char __user *buf, const char *data, int count)
-{
-	char ch;
-
-	while (count--) {
-		ch = *(data++);
-		put_user((ch == '\r') ? '\n' : ch, buf++);
-	}
-}
-
-/*
- * xlate_from_user()
- *
- * Like copy_from_user() while translating NL->CR;
- */
-static inline
-int xlate_from_user(char *data, const char __user *buf, int count)
-{
-	int i;
-
-	i = copy_from_user(data, buf, count);
-	count -= i;
-	while (count--) {
-		if (*data == '\n') {
-			*data = '\r';
-		}
-		++data;
-	}
-	return i;
-}
-
-/*================ Global functions ================*/
-
-/*
- * hfs_do_read()
- *
- * This function transfers actual data from disk to user-space memory,
- * returning the number of bytes successfully transferred.  'fork' tells
- * which file on the disk to read from.  'pos' gives the offset into
- * the Linux file at which to begin the transfer.  Note that this will
- * differ from 'filp->offset' in the case of an AppleDouble header file
- * due to the block of metadata at the beginning of the file, which has
- * no corresponding place in the HFS file.  'count' tells how many
- * bytes to transfer.  'buf' gives an address in user-space to transfer
- * the data to.
- * 
- * This is based on Linus's minix_file_read().
- * It has been changed to take into account that HFS files have no holes.
- */
-hfs_s32 hfs_do_read(struct inode *inode, struct hfs_fork *fork, hfs_u32 pos,
-		    char __user *buf, hfs_u32 count)
-{
-	hfs_s32 size, chars, offset, block, blocks, read = 0;
-	int bhrequest, uptodate;
-	int convert = HFS_I(inode)->convert;
-	struct buffer_head ** bhb, ** bhe;
-	struct buffer_head * bhreq[NBUF];
-	struct buffer_head * buflist[NBUF];
-
-	/* split 'pos' in to block and (byte) offset components */
-	block = pos >> HFS_SECTOR_SIZE_BITS;
-	offset = pos & (HFS_SECTOR_SIZE-1);
-
-	/* compute the logical size of the fork in blocks */
-	size = (fork->lsize + (HFS_SECTOR_SIZE-1)) >> HFS_SECTOR_SIZE_BITS;
-
-	/* compute the number of physical blocks to be transferred */
-	blocks = (count+offset+HFS_SECTOR_SIZE-1) >> HFS_SECTOR_SIZE_BITS;
-
-	bhb = bhe = buflist;
-
-	/* 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 optimized to make maximum use of the
-	   various buffers and caches. */
-
-	do {
-		bhrequest = 0;
-		uptodate = 1;
-		while (blocks) {
-			--blocks;
-			*bhb = hfs_getblk(fork, block++, 0);
-
-			if (!(*bhb)) {
-				/* Since there are no holes in HFS files
-				   we must have encountered an error.
-				   So, stop adding blocks to the queue. */
-				blocks = 0;
-				break;
-			}
-
-			if (!buffer_uptodate(*bhb)) {
-				uptodate = 0;
-				bhreq[bhrequest++] = *bhb;
-			}
-
-			if (++bhb == &buflist[NBUF]) {
-				bhb = buflist;
-			}
-
-			/* If the block we have on hand is uptodate,
-			   go ahead and complete processing. */
-			if (uptodate) {
-				break;
-			}
-			if (bhb == bhe) {
-				break;
-			}
-		}
-
-		/* If the only block in the queue is bad then quit */
-		if (!(*bhe)) {
-			break;
-		}
-
-		/* Now request them all */
-		if (bhrequest) {
-			ll_rw_block(READ, bhrequest, bhreq);
-		}
-
-		do {  /* Finish off all I/O that has actually completed */
-			char *p;
-
-			wait_on_buffer(*bhe);
-
-			if (!buffer_uptodate(*bhe)) {
-				/* read error? */
-				brelse(*bhe);
-				if (++bhe == &buflist[NBUF]) {
-					bhe = buflist;
-				}
-				count = 0;
-				break;
-			}
-
-			if (count < HFS_SECTOR_SIZE - offset) {
-				chars = count;
-			} else {
-				chars = HFS_SECTOR_SIZE - offset;
-			}
-			p = (*bhe)->b_data + offset;
-			if (convert) {
-				xlate_to_user(buf, p, chars);
-			} else {
-				chars -= copy_to_user(buf, p, chars);
-				if (!chars) {
-					brelse(*bhe);
-					count = 0;
-					if (!read)
-						read = -EFAULT;
-					break;
-				}
-			}
-			brelse(*bhe);
-			count -= chars;
-			buf += chars;
-			read += chars;
-			offset = 0;
-			if (++bhe == &buflist[NBUF]) {
-				bhe = buflist;
-			}
-		} while (count && (bhe != bhb) && !buffer_locked(*bhe));
-	} while (count);
-
-	/* Release the read-ahead blocks */
-	while (bhe != bhb) {
-		brelse(*bhe);
-		if (++bhe == &buflist[NBUF]) {
-			bhe = buflist;
-		}
-	}
-	if (!read) {
-		return -EIO;
-	}
-	return read;
-}
- 
-/*
- * hfs_do_write()
- *
- * This function transfers actual data from user-space memory to disk,
- * returning the number of bytes successfully transferred.  'fork' tells
- * which file on the disk to write to.  'pos' gives the offset into
- * the Linux file at which to begin the transfer.  Note that this will
- * differ from 'filp->offset' in the case of an AppleDouble header file
- * due to the block of metadata at the beginning of the file, which has
- * no corresponding place in the HFS file.  'count' tells how many
- * bytes to transfer.  'buf' gives an address in user-space to transfer
- * the data from.
- * 
- * This is just a minor edit of Linus's minix_file_write().
- */
-hfs_s32 hfs_do_write(struct inode *inode, struct hfs_fork *fork, hfs_u32 pos,
-		     const char __user *buf, hfs_u32 count)
-{
-	hfs_s32 written, c;
-	struct buffer_head * bh;
-	char * p;
-	int convert = HFS_I(inode)->convert;
-
-	written = 0;
-	while (written < count) {
-		bh = hfs_getblk(fork, pos/HFS_SECTOR_SIZE, 1);
-		if (!bh) {
-			if (!written) {
-				written = -ENOSPC;
-			}
-			break;
-		}
-		c = HFS_SECTOR_SIZE - (pos % HFS_SECTOR_SIZE);
-		if (c > count - written) {
-			c = count - written;
-		}
-		if (c != HFS_SECTOR_SIZE && !buffer_uptodate(bh)) {
-			ll_rw_block(READ, 1, &bh);
-			wait_on_buffer(bh);
-			if (!buffer_uptodate(bh)) {
-				brelse(bh);
-				if (!written) {
-					written = -EIO;
-				}
-				break;
-			}
-		}
-		p = (pos % HFS_SECTOR_SIZE) + bh->b_data;
-		c -= convert ? xlate_from_user(p, buf, c) :
-			copy_from_user(p, buf, c);
-		if (!c) {
-			brelse(bh);
-			if (!written)
-				written = -EFAULT;
-			break;
-		}
-		pos += c;
-		written += c;
-		buf += c;
-		set_buffer_uptodate(bh);
-		mark_buffer_dirty(bh);
-		brelse(bh);
-	}
-	if (written > 0) {
-		struct hfs_cat_entry *entry = fork->entry;
-
-		inode->i_mtime = inode->i_ctime = CURRENT_TIME;
-		if (pos > fork->lsize) {
-			fork->lsize = pos;
-		}
-		entry->modify_date = hfs_u_to_mtime(get_seconds());
-		hfs_cat_mark_dirty(entry);
-	}
-	return written;
-}
-
-/*
- * hfs_file_fix_mode()
- *
- * Fixes up the permissions on a file after changing the write-inhibit bit.
- */
-void hfs_file_fix_mode(struct hfs_cat_entry *entry)
-{
-	struct dentry **de = entry->sys_entry;
-	int i;
-
-	if (entry->u.file.flags & HFS_FIL_LOCK) {
-		for (i = 0; i < 4; ++i) {
-			if (de[i]) {
-				de[i]->d_inode->i_mode &= ~S_IWUGO;
-			}
-		}
-	} else {
-		for (i = 0; i < 4; ++i) {
-			if (de[i]) {
-			        struct inode *inode = de[i]->d_inode;
-				inode->i_mode |= S_IWUGO;
-				inode->i_mode &= 
-				  ~HFS_SB(inode->i_sb)->s_umask;
-			}
-		}
-	}
-}
--- diff/fs/hfs/file_cap.c	2003-10-09 09:47:34.000000000 +0100
+++ source/fs/hfs/file_cap.c	1970-01-01 01:00:00.000000000 +0100
@@ -1,280 +0,0 @@
-/*
- * linux/fs/hfs/file_cap.c
- *
- * Copyright (C) 1995-1997  Paul H. Hargrove
- * This file may be distributed under the terms of the GNU General Public License.
- *
- * This file contains the file_ops and inode_ops for the metadata
- * files under the CAP representation.
- *
- * The source code distribution of the Columbia AppleTalk Package for
- * UNIX, version 6.0, (CAP) was used as a specification of the
- * location and format of files used by CAP's Aufs.  No code from CAP
- * appears in hfs_fs.  hfs_fs is not a work ``derived'' from CAP in
- * the sense of intellectual property law.
- *
- * "XXX" in a comment is a note to myself to consider changing something.
- *
- * In function preconditions the term "valid" applied to a pointer to
- * a structure means that the pointer is non-NULL and the structure it
- * points to has all fields initialized to consistent values.
- */
-
-#include "hfs.h"
-#include <linux/hfs_fs_sb.h>
-#include <linux/hfs_fs_i.h>
-#include <linux/hfs_fs.h>
-#include <linux/smp_lock.h>
-
-/*================ Forward declarations ================*/
-static loff_t      cap_info_llseek(struct file *, loff_t,
-                                   int);
-static hfs_rwret_t cap_info_read(struct file *, char __user *,
-				 hfs_rwarg_t, loff_t *);
-static hfs_rwret_t cap_info_write(struct file *, const char __user *,
-				  hfs_rwarg_t, loff_t *);
-/*================ Function-like macros ================*/
-
-/*
- * OVERLAPS()
- *
- * Determines if a given range overlaps the specified structure member
- */
-#define OVERLAPS(START, END, TYPE, MEMB) \
-	((END > offsetof(TYPE, MEMB)) && \
-	 (START < offsetof(TYPE, MEMB) + sizeof(((TYPE *)0)->MEMB)))
-
-/*================ Global variables ================*/
-
-struct file_operations hfs_cap_info_operations = {
-	.llseek		= cap_info_llseek,
-	.read		= cap_info_read,
-	.write		= cap_info_write,
-	.fsync		= file_fsync,
-};
-
-struct inode_operations hfs_cap_info_inode_operations = {
-	.setattr	= hfs_notify_change_cap,
-};
-
-/*================ File-local functions ================*/
-
-/*
- * cap_build_meta()
- *
- * Build the metadata structure.
- */
-static void cap_build_meta(struct hfs_cap_info *meta,
-			   struct hfs_cat_entry *entry)
-{
-	memset(meta, 0, sizeof(*meta));
-	memcpy(meta->fi_fndr, &entry->info, 32);
-	if ((entry->type == HFS_CDR_FIL) &&
-	    (entry->u.file.flags & HFS_FIL_LOCK)) {
-		/* Couple the locked bit of the file to the
-		   AFP {write,rename,delete} inhibit bits. */
-		hfs_put_hs(HFS_AFP_RDONLY, meta->fi_attr);
-	}
-	meta->fi_magic1 = HFS_CAP_MAGIC1;
-	meta->fi_version = HFS_CAP_VERSION;
-	meta->fi_magic = HFS_CAP_MAGIC;
-	meta->fi_bitmap = HFS_CAP_LONGNAME;
-	memcpy(meta->fi_macfilename, entry->key.CName.Name,
-	       entry->key.CName.Len);
-	meta->fi_datemagic = HFS_CAP_DMAGIC;
-	meta->fi_datevalid = HFS_CAP_MDATE | HFS_CAP_CDATE;
-	hfs_put_nl(hfs_m_to_htime(entry->create_date), meta->fi_ctime);
-	hfs_put_nl(hfs_m_to_htime(entry->modify_date), meta->fi_mtime);
-	hfs_put_nl(get_seconds(),                       meta->fi_utime);
-}
-
-static loff_t cap_info_llseek(struct file *file, loff_t offset, int origin)
-{
-	long long retval;
-
-	lock_kernel();
-
-	switch (origin) {
-		case 2:
-			offset += file->f_dentry->d_inode->i_size;
-			break;
-		case 1:
-			offset += file->f_pos;
-	}
-	retval = -EINVAL;
-	if (offset>=0 && offset<=HFS_FORK_MAX) {
-		if (offset != file->f_pos) {
-			file->f_pos = offset;
-		}
-		retval = offset;
-	}
-	unlock_kernel();
-	return retval;
-}
-
-/*
- * cap_info_read()
- *
- * This is the read() entry in the file_operations structure for CAP
- * metadata files.  The purpose is to transfer up to 'count' bytes
- * from the file corresponding to 'inode' beginning at offset
- * 'file->f_pos' to user-space at the address 'buf'.  The return value
- * is the number of bytes actually transferred.
- */
-static hfs_rwret_t cap_info_read(struct file *filp, char __user *buf,
-				 hfs_rwarg_t count, loff_t *ppos)
-{
-	struct inode *inode = filp->f_dentry->d_inode;
-	struct hfs_cat_entry *entry = HFS_I(inode)->entry;
-	hfs_s32 left, size, read = 0;
-	hfs_u32 pos;
-
-	if (!S_ISREG(inode->i_mode)) {
-		hfs_warn("hfs_cap_info_read: mode = %07o\n", inode->i_mode);
-		return -EINVAL;
-	}
-
-	pos = *ppos;
-	if (pos > HFS_FORK_MAX) {
-		return 0;
-	}
-	size = inode->i_size;
-	if (pos > size) {
-		left = 0;
-	} else {
-		left = size - pos;
-	}
-	if (left > count) {
-		left = count;
-	}
-	if (left <= 0) {
-		return 0;
-	}
-
-	if (pos < sizeof(struct hfs_cap_info)) {
-		int memcount = sizeof(struct hfs_cap_info) - pos;
-		struct hfs_cap_info meta;
-
-		if (memcount > left) {
-			memcount = left;
-		}
-		cap_build_meta(&meta, entry);
-		memcount -= copy_to_user(buf, ((char *)&meta) + pos, memcount);
-		left -= memcount;
-		read += memcount;
-		pos += memcount;
-		buf += memcount;
-	}
-
-	if (left > 0) {
-		clear_user(buf, left);
-	        pos += left;
-	}
-
-	if (read) {
-		inode->i_atime = CURRENT_TIME;
-		*ppos = pos;
-		mark_inode_dirty(inode);
-	}
-
-	return read;
-}
-
-/*
- * cap_info_write()
- *
- * This is the write() entry in the file_operations structure for CAP
- * metadata files.  The purpose is to transfer up to 'count' bytes
- * to the file corresponding to 'inode' beginning at offset
- * '*ppos' from user-space at the address 'buf'.
- * The return value is the number of bytes actually transferred.
- */
-static hfs_rwret_t cap_info_write(struct file *filp, const char __user *buf, 
-				  hfs_rwarg_t count, loff_t *ppos)
-{
-        struct inode *inode = filp->f_dentry->d_inode;
-	hfs_u32 pos;
-
-	if (!S_ISREG(inode->i_mode)) {
-		hfs_warn("hfs_file_write: mode = %07o\n", inode->i_mode);
-		return -EINVAL;
-	}
-	if (count <= 0) {
-		return 0;
-	}
-	
-	pos = (filp->f_flags & O_APPEND) ? inode->i_size : *ppos;
-
-	if (pos > HFS_FORK_MAX) {
-		return 0;
-	}
-
-	*ppos += count;
-	if (*ppos > HFS_FORK_MAX) {
-		*ppos = HFS_FORK_MAX;
-		count = HFS_FORK_MAX - pos;
-	}
-
-	if (*ppos > inode->i_size)
-	        inode->i_size = *ppos;
-
-	/* Only deal with the part we store in memory */
-	if (pos < sizeof(struct hfs_cap_info)) {
-		int end, mem_count;
-		struct hfs_cat_entry *entry = HFS_I(inode)->entry;
-		struct hfs_cap_info meta;
-
-		mem_count = sizeof(struct hfs_cap_info) - pos;
-		if (mem_count > count) {
-			mem_count = count;
-		}
-		end = pos + mem_count;
-
-		cap_build_meta(&meta, entry);
-		mem_count -= copy_from_user(((char *)&meta) + pos, buf, mem_count);
-
-		/* Update finder attributes if changed */
-		if (OVERLAPS(pos, end, struct hfs_cap_info, fi_fndr)) {
-			memcpy(&entry->info, meta.fi_fndr, 32);
-			hfs_cat_mark_dirty(entry);
-		}
-
-		/* Update file flags if changed */
-		if (OVERLAPS(pos, end, struct hfs_cap_info, fi_attr) &&
-		    (entry->type == HFS_CDR_FIL)) {
-			int locked = hfs_get_ns(&meta.fi_attr) &
-							htons(HFS_AFP_WRI);
-			hfs_u8 new_flags;
-
-			if (locked) {
-				new_flags = entry->u.file.flags | HFS_FIL_LOCK;
-			} else {
-				new_flags = entry->u.file.flags & ~HFS_FIL_LOCK;
-			}
-
-			if (new_flags != entry->u.file.flags) {
-				entry->u.file.flags = new_flags;
-				hfs_cat_mark_dirty(entry);
-				hfs_file_fix_mode(entry);
-			}
-		}
-
-		/* Update CrDat if changed */
-		if (OVERLAPS(pos, end, struct hfs_cap_info, fi_ctime)) {
-			entry->create_date =
-				hfs_h_to_mtime(hfs_get_nl(meta.fi_ctime));
-			hfs_cat_mark_dirty(entry);
-		}
-
-		/* Update MdDat if changed */
-		if (OVERLAPS(pos, end, struct hfs_cap_info, fi_mtime)) {
-			entry->modify_date =
-				hfs_h_to_mtime(hfs_get_nl(meta.fi_mtime));
-			hfs_cat_mark_dirty(entry);
-		}
-	}
-
-	inode->i_mtime = inode->i_ctime = CURRENT_TIME;
-	mark_inode_dirty(inode);
-	return count;
-}
--- diff/fs/hfs/file_hdr.c	2004-02-18 08:54:12.000000000 +0000
+++ source/fs/hfs/file_hdr.c	1970-01-01 01:00:00.000000000 +0100
@@ -1,1033 +0,0 @@
-/*
- * linux/fs/hfs/file_hdr.c
- *
- * Copyright (C) 1995-1997  Paul H. Hargrove
- * This file may be distributed under the terms of the GNU General Public License.
- *
- * This file contains the file_ops and inode_ops for the metadata
- * files under the AppleDouble and Netatalk representations.
- *
- * The source code distributions of Netatalk, versions 1.3.3b2 and
- * 1.4b2, were used as a specification of the location and format of
- * files used by Netatalk's afpd.  No code from Netatalk appears in
- * hfs_fs.  hfs_fs is not a work ``derived'' from Netatalk in the
- * sense of intellectual property law.
- *
- * "XXX" in a comment is a note to myself to consider changing something.
- *
- * In function preconditions the term "valid" applied to a pointer to
- * a structure means that the pointer is non-NULL and the structure it
- * points to has all fields initialized to consistent values.
- *
- * XXX: Note the reason that there is not bmap() for AppleDouble
- * header files is that dynamic nature of their structure make it
- * very difficult to safely mmap them.  Maybe in the distant future
- * I'll get bored enough to implement it.
- */
-
-#include "hfs.h"
-#include <linux/hfs_fs_sb.h>
-#include <linux/hfs_fs_i.h>
-#include <linux/hfs_fs.h>
-#include <linux/smp_lock.h>
-
-/* prodos types */
-#define PRODOSI_FTYPE_DIR   0x0F
-#define PRODOSI_FTYPE_TEXT  0x04
-#define PRODOSI_FTYPE_8BIT  0xFF
-#define PRODOSI_FTYPE_16BIT 0xB3
-
-#define PRODOSI_AUXTYPE_DIR 0x0200
-
-/*================ Forward declarations ================*/
-static loff_t      hdr_llseek(struct file *, loff_t, int);
-static hfs_rwret_t hdr_read(struct file *, char __user *,
-			    hfs_rwarg_t, loff_t *);
-static hfs_rwret_t hdr_write(struct file *, const char __user *,
-			     hfs_rwarg_t, loff_t *);
-/*================ Global variables ================*/
-
-struct file_operations hfs_hdr_operations = {
-	.llseek		= hdr_llseek,
-	.read		= hdr_read,
-	.write		= hdr_write,
-	.fsync		= file_fsync,
-};
-
-struct inode_operations hfs_hdr_inode_operations = {
-	.setattr	= hfs_notify_change_hdr,
-};
-
-const struct hfs_hdr_layout hfs_dbl_fil_hdr_layout = {
-	.magic		= __constant_htonl(HFS_DBL_MAGIC),	/* magic   */
-	.version	= __constant_htonl(HFS_HDR_VERSION_2),	/* version */
-	.entries	= 6,					/* entries */
-	{					/* descr[] */
-		{HFS_HDR_FNAME, offsetof(struct hfs_dbl_hdr, real_name),   ~0},
-		{HFS_HDR_DATES, offsetof(struct hfs_dbl_hdr, create_time), 16},
-		{HFS_HDR_FINFO, offsetof(struct hfs_dbl_hdr, finderinfo),  32},
-		{HFS_HDR_MACI,  offsetof(struct hfs_dbl_hdr, fileinfo),     4},
-		{HFS_HDR_DID,   offsetof(struct hfs_dbl_hdr, cnid),         4},
-		{HFS_HDR_RSRC,  HFS_DBL_HDR_LEN,                           ~0}
-	},
-	{					/* order[] */
-		(struct hfs_hdr_descr *)&hfs_dbl_fil_hdr_layout.descr[0],
-		(struct hfs_hdr_descr *)&hfs_dbl_fil_hdr_layout.descr[1],
-		(struct hfs_hdr_descr *)&hfs_dbl_fil_hdr_layout.descr[2],
-		(struct hfs_hdr_descr *)&hfs_dbl_fil_hdr_layout.descr[3],
-		(struct hfs_hdr_descr *)&hfs_dbl_fil_hdr_layout.descr[4],
-		(struct hfs_hdr_descr *)&hfs_dbl_fil_hdr_layout.descr[5]
-	}
-};
-
-const struct hfs_hdr_layout hfs_dbl_dir_hdr_layout = {
-	.magic		= __constant_htonl(HFS_DBL_MAGIC),	/* magic   */
-	.version	= __constant_htonl(HFS_HDR_VERSION_2),	/* version */
-	.entries	= 5,					/* entries */
-	{					/* descr[] */
-		{HFS_HDR_FNAME, offsetof(struct hfs_dbl_hdr, real_name),   ~0},
-		{HFS_HDR_DATES, offsetof(struct hfs_dbl_hdr, create_time), 16},
-		{HFS_HDR_FINFO, offsetof(struct hfs_dbl_hdr, finderinfo),  32},
-		{HFS_HDR_MACI,  offsetof(struct hfs_dbl_hdr, fileinfo),     4},
-		{HFS_HDR_DID,   offsetof(struct hfs_dbl_hdr, cnid),         4}
-	},
-	{					/* order[] */
-		(struct hfs_hdr_descr *)&hfs_dbl_dir_hdr_layout.descr[0],
-		(struct hfs_hdr_descr *)&hfs_dbl_dir_hdr_layout.descr[1],
-		(struct hfs_hdr_descr *)&hfs_dbl_dir_hdr_layout.descr[2],
-		(struct hfs_hdr_descr *)&hfs_dbl_dir_hdr_layout.descr[3],
-		(struct hfs_hdr_descr *)&hfs_dbl_dir_hdr_layout.descr[4]
-	}
-};
-
-const struct hfs_hdr_layout hfs_nat2_hdr_layout = {
-	.magic		= __constant_htonl(HFS_DBL_MAGIC),	/* magic   */
-	.version	= __constant_htonl(HFS_HDR_VERSION_2),	/* version */
-	.entries	= 9,					/* entries */
-	{					/* descr[] */
-		{HFS_HDR_FNAME, offsetof(struct hfs_dbl_hdr, real_name),   ~0},
-		{HFS_HDR_COMNT, offsetof(struct hfs_dbl_hdr, comment),      0},
-		{HFS_HDR_DATES, offsetof(struct hfs_dbl_hdr, create_time), 16},
-		{HFS_HDR_FINFO, offsetof(struct hfs_dbl_hdr, finderinfo),  32},
-		{HFS_HDR_AFPI,  offsetof(struct hfs_dbl_hdr, fileinfo),     4},
-		{HFS_HDR_DID,   offsetof(struct hfs_dbl_hdr, cnid),         4},
-		{HFS_HDR_SNAME,  offsetof(struct hfs_dbl_hdr, short_name), ~0},
-		{HFS_HDR_PRODOSI,  offsetof(struct hfs_dbl_hdr, prodosi),   8},
-		{HFS_HDR_RSRC,  HFS_NAT_HDR_LEN,                           ~0}
-	},
-	{					/* order[] */
-		(struct hfs_hdr_descr *)&hfs_nat_hdr_layout.descr[0],
-		(struct hfs_hdr_descr *)&hfs_nat_hdr_layout.descr[1],
-		(struct hfs_hdr_descr *)&hfs_nat_hdr_layout.descr[2],
-		(struct hfs_hdr_descr *)&hfs_nat_hdr_layout.descr[3],
-		(struct hfs_hdr_descr *)&hfs_nat_hdr_layout.descr[4],
-		(struct hfs_hdr_descr *)&hfs_nat_hdr_layout.descr[5],
-		(struct hfs_hdr_descr *)&hfs_nat_hdr_layout.descr[6],
-		(struct hfs_hdr_descr *)&hfs_nat_hdr_layout.descr[7],
-		(struct hfs_hdr_descr *)&hfs_nat_hdr_layout.descr[8]
-	}
-};
-
-const struct hfs_hdr_layout hfs_nat_hdr_layout = {
-	.magic		= __constant_htonl(HFS_DBL_MAGIC),	/* magic   */
-	.version	= __constant_htonl(HFS_HDR_VERSION_1),	/* version */
-	.entries	= 5,					/* entries */
-	{					/* descr[] */
-		{HFS_HDR_FNAME, offsetof(struct hfs_dbl_hdr, real_name),   ~0},
-		{HFS_HDR_COMNT, offsetof(struct hfs_dbl_hdr, comment),      0},
-		{HFS_HDR_OLDI,  offsetof(struct hfs_dbl_hdr, create_time), 16},
-		{HFS_HDR_FINFO, offsetof(struct hfs_dbl_hdr, finderinfo),  32},
-		{HFS_HDR_RSRC,  HFS_NAT_HDR_LEN,                           ~0},
-	},
-	{					/* order[] */
-		(struct hfs_hdr_descr *)&hfs_nat_hdr_layout.descr[0],
-		(struct hfs_hdr_descr *)&hfs_nat_hdr_layout.descr[1],
-		(struct hfs_hdr_descr *)&hfs_nat_hdr_layout.descr[2],
-		(struct hfs_hdr_descr *)&hfs_nat_hdr_layout.descr[3],
-		(struct hfs_hdr_descr *)&hfs_nat_hdr_layout.descr[4]
-	}
-};
-
-/*================ File-local variables ================*/
-
-static const char fstype[16] =
-	{'M','a','c','i','n','t','o','s','h',' ',' ',' ',' ',' ',' ',' '};
-
-/*================ File-local data types ================*/
-
-struct hdr_hdr {
-        hfs_lword_t	magic;
-        hfs_lword_t	version;
-        hfs_byte_t	filler[16];
-        hfs_word_t	entries;
-        hfs_byte_t	descrs[12*HFS_HDR_MAX];
-}  __attribute__((packed));
-
-/*================ File-local functions ================*/
-
-/*
- * dlength()
- */
-static int dlength(const struct hfs_hdr_descr *descr,
-		   const struct hfs_cat_entry *entry)
-{
-	hfs_u32 length = descr->length;
-
-	/* handle auto-sized entries */
-	if (length == ~0) {
-		switch (descr->id) {
-		case HFS_HDR_DATA:
-			if (entry->type == HFS_CDR_FIL) {
-				length = entry->u.file.data_fork.lsize;
-			} else {
-				length = 0;
-			}
-			break;
-
-		case HFS_HDR_RSRC:
-			if (entry->type == HFS_CDR_FIL) {
-				length = entry->u.file.rsrc_fork.lsize;
-			} else {
-				length = 0;
-			}
-			break;
-
-		case HFS_HDR_FNAME:
-			length = entry->key.CName.Len;
-			break;
-
-		case HFS_HDR_SNAME:
-		default:
-			length = 0;
-		}
-	}
-	return length;
-}
-
-/*
- * hdr_build_meta()
- */
-static void hdr_build_meta(struct hdr_hdr *meta,
-			   const struct hfs_hdr_layout *layout,
-			   const struct hfs_cat_entry *entry)
-{
-	const struct hfs_hdr_descr *descr;
-	hfs_byte_t *ptr;
-	int lcv;
-
-	hfs_put_nl(layout->magic,   meta->magic);
-	hfs_put_nl(layout->version, meta->version);
-	if (layout->version == htonl(HFS_HDR_VERSION_1)) {
-		memcpy(meta->filler, fstype, 16);
-	} else {
-		memset(meta->filler, 0, 16);
-	}
-	hfs_put_hs(layout->entries, meta->entries);
-	memset(meta->descrs, 0, sizeof(meta->descrs));
-	for (lcv = 0, descr = layout->descr, ptr = meta->descrs;
-	     lcv < layout->entries; ++lcv, ++descr, ptr += 12) {
-		hfs_put_hl(descr->id,             ptr);
-		hfs_put_hl(descr->offset,         ptr + 4);
-		hfs_put_hl(dlength(descr, entry), ptr + 8);
-	}
-}
-
-/*
- * dup_layout ()
- */
-static struct hfs_hdr_layout *dup_layout(const struct hfs_hdr_layout *old)
-{
-	struct hfs_hdr_layout *new;
-	int lcv;
-
-	if (HFS_NEW(new)) {
-		memcpy(new, old, sizeof(*new));
-		for (lcv = 0; lcv < new->entries; ++lcv) {
-			new->order[lcv] = (struct hfs_hdr_descr *)
-			((char *)new->order[lcv] + ((char *)new - (char *)old));
-		}
-	}
-	return new;
-}
-
-/*
- * init_layout()
- */
-static inline void init_layout(struct hfs_hdr_layout *layout,
-			       const hfs_byte_t *descrs)
-{
-	struct hfs_hdr_descr **base, **p, **q, *tmp;
-	int lcv, entries = layout->entries;
-
-	for (lcv = 0; lcv < entries; ++lcv, descrs += 12) {
-		layout->order[lcv] = &layout->descr[lcv];
-		layout->descr[lcv].id     = hfs_get_hl(descrs);
-		layout->descr[lcv].offset = hfs_get_hl(descrs + 4);
-		layout->descr[lcv].length = hfs_get_hl(descrs + 8);
-	}
-	for (lcv = layout->entries; lcv < HFS_HDR_MAX; ++lcv) {
-		layout->order[lcv] = NULL;
-		layout->descr[lcv].id     = 0;
-		layout->descr[lcv].offset = 0;
-		layout->descr[lcv].length = 0;
-	}
-
-	/* Sort the 'order' array using an insertion sort */
-	base = &layout->order[0];
-	for (p = (base+1); p < (base+entries); ++p) {
-		q=p;
-		while ((*q)->offset < (*(q-1))->offset) {
-			tmp = *q;
-			*q = *(q-1);
-			*(--q) = tmp;
-			if (q == base) break;
-		}
-	}
-}
-
-/*
- * adjust_forks()
- */
-static inline void adjust_forks(struct hfs_cat_entry *entry,
-				const struct hfs_hdr_layout *layout)
-{
-	int lcv;
-
-	for (lcv = 0; lcv < layout->entries; ++lcv) {
-		const struct hfs_hdr_descr *descr = &layout->descr[lcv];
-
-		if ((descr->id == HFS_HDR_DATA) &&
-		    (descr->length != entry->u.file.data_fork.lsize)) {
-			entry->u.file.data_fork.lsize = descr->length;
-			hfs_extent_adj(&entry->u.file.data_fork);
-		} else if ((descr->id == HFS_HDR_RSRC) &&
-			   (descr->length != entry->u.file.rsrc_fork.lsize)) {
-			entry->u.file.rsrc_fork.lsize = descr->length;
-			hfs_extent_adj(&entry->u.file.rsrc_fork);
-		}
-	}
-}
-
-/*
- * get_dates()
- */
-static void get_dates(const struct hfs_cat_entry *entry,
-		      const struct inode *inode,  hfs_u32 dates[3])
-{
-	dates[0] = hfs_m_to_htime(entry->create_date);
-	dates[1] = hfs_m_to_htime(entry->modify_date);
-	dates[2] = hfs_m_to_htime(entry->backup_date);
-}
-
-/*
- * set_dates()
- */
-static void set_dates(struct hfs_cat_entry *entry, struct inode *inode,
-		      const hfs_u32 *dates)
-{
-	hfs_u32 tmp;
-
-	tmp = hfs_h_to_mtime(dates[0]);
-	if (entry->create_date != tmp) {
-		entry->create_date = tmp;
-		hfs_cat_mark_dirty(entry);
-	}
-	tmp = hfs_h_to_mtime(dates[1]);
-	if (entry->modify_date != tmp) {
-		entry->modify_date = tmp;
-		inode->i_ctime.tv_sec = inode->i_atime.tv_sec = inode->i_mtime.tv_sec = 
-			hfs_h_to_utime(dates[1]);
-		inode->i_ctime.tv_nsec = 0;
-		inode->i_mtime.tv_nsec = 0;
-		inode->i_atime.tv_nsec = 0;
-		hfs_cat_mark_dirty(entry);
-	}
-	tmp = hfs_h_to_mtime(dates[2]);
-	if (entry->backup_date != tmp) {
-		entry->backup_date = tmp;
-		hfs_cat_mark_dirty(entry);
-	}
-}
-
-loff_t hdr_llseek(struct file *file, loff_t offset, int origin)
-{
-	long long retval;
-
-	lock_kernel();
-
-	switch (origin) {
-		case 2:
-			offset += file->f_dentry->d_inode->i_size;
-			break;
-		case 1:
-			offset += file->f_pos;
-	}
-	retval = -EINVAL;
-	if (offset>=0 && offset<file->f_dentry->d_inode->i_size) {
-		if (offset != file->f_pos) {
-			file->f_pos = offset;
-		}
-		retval = offset;
-	}
-	unlock_kernel();
-	return retval;
-}
-
-/*
- * hdr_read()
- *
- * This is the read field in the inode_operations structure for
- * header files.  The purpose is to transfer up to 'count' bytes
- * from the file corresponding to 'inode', beginning at
- * 'filp->offset' bytes into the file.	The data is transferred to
- * user-space at the address 'buf'.  Returns the number of bytes
- * successfully transferred.
- */
-/* XXX: what about the entry count changing on us? */
-static hfs_rwret_t hdr_read(struct file *filp, char __user *buf, 
-			    hfs_rwarg_t count, loff_t *ppos)
-{
-	struct inode *inode = filp->f_dentry->d_inode;
-	struct hfs_cat_entry *entry = HFS_I(inode)->entry;
-	const struct hfs_hdr_layout *layout;
-	off_t start, length, offset;
-	off_t pos = *ppos;
-	int left, lcv, read = 0;
-
-	if (!S_ISREG(inode->i_mode)) {
-		hfs_warn("hfs_hdr_read: mode = %07o\n",inode->i_mode);
-		return -EINVAL;
-	}
-
-	if (HFS_I(inode)->layout) {
-		layout = HFS_I(inode)->layout;
-	} else {
-		layout = HFS_I(inode)->default_layout;
-	}
-
-	/* Adjust count to fit within the bounds of the file */
-	if ((pos >= inode->i_size) || (count <= 0)) {
-		return 0;
-	} else if (count > inode->i_size - pos) {
-		count = inode->i_size - pos;
-	}
-
-	/* Handle the fixed-location portion */
-	length = sizeof(hfs_u32) + sizeof(hfs_u32) + 16 +
-		 sizeof(hfs_u16) + layout->entries * (3 * sizeof(hfs_u32));
-	if (pos < length) {
-		struct hdr_hdr meta;
-
-		left = length - pos;
-		if (left > count) {
-			left = count;
-		}
-
-		hdr_build_meta(&meta, layout, entry);
-		left -= copy_to_user(buf, ((char *)&meta) + pos, left);
-		count -= left;
-		read += left;
-		pos += left;
-		buf += left;
-	}
-	if (!count) {
-		goto done;
-	}
-
-	/* Handle the actual data */
-	for (lcv = 0; count && (lcv < layout->entries); ++lcv) {
-		const struct hfs_hdr_descr *descr = layout->order[lcv];
-		struct hfs_fork *fork;
-		char tmp[16], *p;
-		off_t limit;
-
-		/* stop reading if we run out of descriptors early */
-		if (!descr) {
-			break;
-		}
-
-		/* find start and length of this entry */
-		start = descr->offset;
-		length = dlength(descr, entry);
-
-		/* Skip to next entry if this one is empty or isn't needed */
-		if (!length || (pos >= start + length)) {
-			continue;
-		}
-
-		/* Pad with zeros to the start of this entry if needed */
-		if (pos < start) {
-			left = start - pos;
-			if (left > count) {
-				left = count;
-			}
-			clear_user(buf, left);
-			count -= left;
-			read += left;
-			pos += left;
-			buf += left;
-		}
-		if (!count) {
-			goto done;
-		}
-
-		/* locate and/or construct the data for this entry */
-		fork = NULL;
-		p = NULL;
-		switch (descr->id) {
-		case HFS_HDR_DATA:
-			fork = &entry->u.file.data_fork;
-			limit = fork->lsize;
-			break;
-
-		case HFS_HDR_RSRC:
-			fork = &entry->u.file.rsrc_fork;
-			limit = fork->lsize;
-			break;
-
-		case HFS_HDR_FNAME:
-			p = entry->key.CName.Name;
-			limit = entry->key.CName.Len;
-			break;
-
-		case HFS_HDR_OLDI:
-		case HFS_HDR_DATES:
-			get_dates(entry, inode, (hfs_u32 *)tmp);
-			if (descr->id == HFS_HDR_DATES) {
-				/* XXX: access date. hfsplus actually
-                                   has this. */
-				memcpy(tmp + 12, tmp + 4, 4);
-			} else if ((entry->type == HFS_CDR_FIL) &&
-				   (entry->u.file.flags & HFS_FIL_LOCK)) {
-				hfs_put_hl(HFS_AFP_RDONLY, tmp + 12);
-			} else {
-				hfs_put_nl(0, tmp + 12);
-			}
-			p = tmp;
-			limit = 16;
-			break;
-
-		case HFS_HDR_FINFO:
-			p = (char *)&entry->info;
-			limit = 32;
-			break;
-
-		case HFS_HDR_AFPI:
-			/* XXX: this needs to do more mac->afp mappings */
-			hfs_put_ns(0, tmp);
-			if ((entry->type == HFS_CDR_FIL) &&
-			    (entry->u.file.flags & HFS_FIL_LOCK)) {
-				hfs_put_hs(HFS_AFP_RDONLY, tmp + 2);
-			} else {
-				hfs_put_ns(0, tmp + 2);
-			}
-			p = tmp;
-			limit = 4;
-		        break;
-
-		case HFS_HDR_PRODOSI:
-			/* XXX: this needs to do mac->prodos translations */
-			memset(tmp, 0, 8);
-#if 0
-			hfs_put_ns(0, tmp); /* access */
-			hfs_put_ns(0, tmp); /* type */
-			hfs_put_nl(0, tmp); /* aux type */
-#endif
-			p = tmp;
-			limit = 8;
-		        break;
-
-		case HFS_HDR_MACI:
-			hfs_put_ns(0, tmp);
-			if (entry->type == HFS_CDR_FIL) {
-				hfs_put_hs(entry->u.file.flags, tmp + 2);
-			} else {
-				hfs_put_ns(entry->u.dir.flags, tmp + 2);
-			}
-			p = tmp;
-			limit = 4;
-			break;
-
-		case HFS_HDR_DID:
-		        /* if it's rootinfo, stick the next available did in
-			 * the did slot. */
-			limit = 4;
-			if (entry->cnid == htonl(HFS_ROOT_CNID)) {
-				struct hfs_mdb *mdb = entry->mdb;
-				const struct hfs_name *reserved = 
-				HFS_SB(mdb->sys_mdb)->s_reserved2;
-				
-				while (reserved->Len) {
-					if (hfs_streq(reserved->Name,
-						      reserved->Len,
-						      entry->key.CName.Name,
-						      entry->key.CName.Len)) {
-						hfs_put_hl(mdb->next_id, tmp);
-						p = tmp;
-						goto hfs_did_done;
-					}
-					reserved++;
-				}
-			}
-			p = (char *) &entry->cnid;
-hfs_did_done:
-			break;
-
-		case HFS_HDR_SNAME:
-		default:
-			limit = 0;
-		}
-		
-		/* limit the transfer to the available data
-		   of to the stated length of the entry. */
-		if (length > limit) {
-			length = limit;
-		}
-		offset = pos - start;
-		left = length - offset;
-		if (left > count) {
-			left = count;
-		}
-		if (left <= 0) {
-			continue;
-		}
-
-		/* transfer the data */
-		if (p) {
-			left -= copy_to_user(buf, p + offset, left);
-		} else if (fork) {
-			left = hfs_do_read(inode, fork, offset, buf, left);
-			if (left > 0) {
-			} else if (!read) {
-				return left;
-			} else {
-				goto done;
-			}
-		}
-		count -= left;
-		read += left;
-		pos += left;
-		buf += left;
-	}
-
-	/* Pad the file out with zeros */
-	if (count) {
-		clear_user(buf, count);
-		read += count;
-		pos += count;
-	}
-		
-done:
-	if (read) {
-		inode->i_atime = CURRENT_TIME;
-		*ppos = pos;
-		mark_inode_dirty(inode);
-	}
-	return read;
-}
-
-/*
- * hdr_write()
- *
- * This is the write() entry in the file_operations structure for
- * header files.  The purpose is to transfer up to 'count' bytes
- * to the file corresponding to 'inode' beginning at offset
- * '*ppos' from user-space at the address 'buf'.
- * The return value is the number of bytes actually transferred.
- */
-static hfs_rwret_t hdr_write(struct file *filp, const char __user *buf,
-			     hfs_rwarg_t count, loff_t *ppos)
-{
-	struct inode *inode = filp->f_dentry->d_inode;
-        struct hfs_cat_entry *entry = HFS_I(inode)->entry;
-        struct hfs_hdr_layout *layout;
-        off_t start, length, offset;
-        int left, lcv, written = 0;
-	struct hdr_hdr meta;
-	int built_meta = 0;
-        off_t pos;
-
-	if (!S_ISREG(inode->i_mode)) {
-		hfs_warn("hfs_hdr_write: mode = %07o\n", inode->i_mode);
-		return -EINVAL;
-	}
-	if (count <= 0) {
-		return 0;
-	}
-
-	pos = (filp->f_flags & O_APPEND) ? inode->i_size : *ppos;
-
-	if (!HFS_I(inode)->layout) {
-		HFS_I(inode)->layout = dup_layout(HFS_I(inode)->default_layout);
-	}
-	layout = HFS_I(inode)->layout;
-
-	/* Handle the 'magic', 'version', 'filler' and 'entries' fields */
-	length = sizeof(hfs_u32) + sizeof(hfs_u32) + 16 + sizeof(hfs_u16);
-	if (pos < length) {
-		hdr_build_meta(&meta, layout, entry);
-		built_meta = 1;
-
-		left = length - pos;
-		if (left > count) {
-			left = count;
-		}
-
-		left -= copy_from_user(((char *)&meta) + pos, buf, left);
-		layout->magic   = hfs_get_nl(meta.magic);
-		layout->version = hfs_get_nl(meta.version);
-		layout->entries = hfs_get_hs(meta.entries);
-		if (layout->entries > HFS_HDR_MAX) {
-			/* XXX: should allocate slots dynamically */
-			hfs_warn("hfs_hdr_write: TRUNCATING TO %d "
-				 "DESCRIPTORS\n", HFS_HDR_MAX);
-			layout->entries = HFS_HDR_MAX;
-		}
-
-		count -= left;
-		written += left;
-		pos += left;
-		buf += left;
-	}
-	if (!count) {
-		goto done;
-	}
-
-	/* We know for certain how many entries we have, so process them */
-	length += layout->entries * 3 * sizeof(hfs_u32);
-	if (pos < length) {
-		if (!built_meta) {
-			hdr_build_meta(&meta, layout, entry);
-		}
-
-		left = length - pos;
-		if (left > count) {
-			left = count;
-		}
-
-		left -= copy_from_user(((char *)&meta) + pos, buf, left);
-		init_layout(layout, meta.descrs);
-
-		count -= left;
-		written += left;
-		pos += left;
-		buf += left;
-
-		/* Handle possible size changes for the forks */
-		if (entry->type == HFS_CDR_FIL) {
-			adjust_forks(entry, layout);
-			hfs_cat_mark_dirty(entry);
-		}
-	}
-
-	/* Handle the actual data */
-	for (lcv = 0; count && (lcv < layout->entries); ++lcv) {
-		struct hfs_hdr_descr *descr = layout->order[lcv];
-		struct hfs_fork *fork;
-		char tmp[16], *p;
-		off_t limit;
-
-		/* stop writing if we run out of descriptors early */
-		if (!descr) {
-			break;
-		}
-
-		/* find start and length of this entry */
-		start = descr->offset;
-		if ((descr->id == HFS_HDR_DATA) ||
-		    (descr->id == HFS_HDR_RSRC)) {
-			if (entry->type == HFS_CDR_FIL) {
-				length = 0x7fffffff - start;
-			} else {
-				continue;
-			}
-		} else {
-			length = dlength(descr, entry);
-		}
-
-		/* Trim length to avoid overlap with the next entry */
-		if (layout->order[lcv+1] &&
-		    ((start + length) > layout->order[lcv+1]->offset)) {
-			length = layout->order[lcv+1]->offset - start;
-		}
-
-		/* Skip to next entry if this one is empty or isn't needed */
-		if (!length || (pos >= start + length)) {
-			continue;
-		}
-
-		/* Skip any padding that may exist between entries */
-		if (pos < start) {
-			left = start - pos;
-			if (left > count) {
-				left = count;
-			}
-			count -= left;
-			written += left;
-			pos += left;
-			buf += left;
-		}
-		if (!count) {
-			goto done;
-		}
-
-		/* locate and/or construct the data for this entry */
-		fork = NULL;
-		p = NULL;
-		switch (descr->id) {
-		case HFS_HDR_DATA:
-#if 0
-/* Can't yet write to the data fork via a header file, since there is the
- * possibility to write via the data file, and the only locking is at the
- * inode level.
- */
-			fork = &entry->u.file.data_fork;
-			limit = length;
-#else
-			limit = 0;
-#endif
-			break;
-
-		case HFS_HDR_RSRC:
-			fork = &entry->u.file.rsrc_fork;
-			limit = length;
-			break;
-
-		case HFS_HDR_OLDI:
-		case HFS_HDR_DATES:
-			get_dates(entry, inode, (hfs_u32 *)tmp);
-			if (descr->id == HFS_HDR_DATES) {
-				memcpy(tmp + 12, tmp + 4, 4);
-			} else if ((entry->type == HFS_CDR_FIL) &&
-				   (entry->u.file.flags & HFS_FIL_LOCK)) {
-				hfs_put_hl(HFS_AFP_RDONLY, tmp + 12);
-			} else {
-				hfs_put_nl(0, tmp + 12);
-			}
-			p = tmp;
-			limit = 16;
-			break;
-
-		case HFS_HDR_FINFO:
-			p = (char *)&entry->info;
-			limit = 32;
-			break;
-
-		case HFS_HDR_AFPI:
-			hfs_put_ns(0, tmp);
-			if ((entry->type == HFS_CDR_FIL) &&
-			    (entry->u.file.flags & HFS_FIL_LOCK)) {
-				hfs_put_hs(HFS_AFP_RDONLY, tmp + 2);
-			} else {
-				hfs_put_ns(0, tmp + 2);
-			}			
-			p = tmp;
-			limit = 4;
-			break;
-
-		case HFS_HDR_PRODOSI:
-			/* XXX: this needs to do mac->prodos translations */
-			memset(tmp, 0, 8); 
-#if 0
-			hfs_put_ns(0, tmp); /* access */
-			hfs_put_ns(0, tmp); /* type */
-			hfs_put_nl(0, tmp); /* aux type */
-#endif
-			p = tmp;
-			limit = 8;
-		        break;
-
-		case HFS_HDR_MACI:
-			hfs_put_ns(0, tmp);
-			if (entry->type == HFS_CDR_FIL) {
-				hfs_put_hs(entry->u.file.flags, tmp + 2);
-			} else {
-				hfs_put_ns(entry->u.dir.flags, tmp + 2);
-			}
-			p = tmp;
-			limit = 4;
-			break;
-
-		case HFS_HDR_FNAME:	/* Can't rename a file this way */
-		case HFS_HDR_DID:       /* can't specify a did this way */
-		default:
-			limit = 0;
-		}
-		
-		/* limit the transfer to the available data
-		   of to the stated length of the entry. */
-		if (length > limit) {
-			length = limit;
-		}
-		offset = pos - start;
-		left = length - offset;
-		if (left > count) {
-			left = count;
-		}
-		if (left <= 0) {
-			continue;
-		}
-
-		/* transfer the data from user space */
-		if (p) {
-			left -= copy_from_user(p + offset, buf, left);
-		} else if (fork) {
-			left = hfs_do_write(inode, fork, offset, buf, left);
-		}
-
-		/* process the data */
-		switch (descr->id) {
-		case HFS_HDR_OLDI:
-			set_dates(entry, inode, (hfs_u32 *)tmp);
-			if (entry->type == HFS_CDR_FIL) {
-				hfs_u8 new_flags = entry->u.file.flags;
-
-				if (hfs_get_nl(tmp+12) & htonl(HFS_AFP_WRI)) {
-					new_flags |= HFS_FIL_LOCK;
-				} else {
-					new_flags &= ~HFS_FIL_LOCK;
-				}
-
-				if (new_flags != entry->u.file.flags) {
-					entry->u.file.flags = new_flags;
-					hfs_cat_mark_dirty(entry);
-					hfs_file_fix_mode(entry);
-				}
-			}
-			break;
-
-		case HFS_HDR_DATES:
-			set_dates(entry, inode, (hfs_u32 *)tmp);
-			break;
-
-		case HFS_HDR_FINFO:
-			hfs_cat_mark_dirty(entry);
-			break;
-
-		case HFS_HDR_MACI:
-			if (entry->type == HFS_CDR_DIR) {
-				hfs_u16 new_flags = hfs_get_ns(tmp + 2);
-
-				if (entry->u.dir.flags != new_flags) {
-					entry->u.dir.flags = new_flags;
-					hfs_cat_mark_dirty(entry);
-				}
-			} else {
-				hfs_u8 new_flags = tmp[3];
-				hfs_u8 changed = entry->u.file.flags^new_flags;
-				
-				if (changed) {
-					entry->u.file.flags = new_flags;
-					hfs_cat_mark_dirty(entry);
-					if (changed & HFS_FIL_LOCK) {
-						hfs_file_fix_mode(entry);
-					}
-				}
-			}
-			break;
-
-		case HFS_HDR_DATA:
-		case HFS_HDR_RSRC:
-			if (left <= 0) {
-				if (!written) {
-					return left;
-				} else {
-					goto done;
-				}
-			} else if (fork->lsize > descr->length) {
-				descr->length = fork->lsize;
-			}
-			break;
-
-		case HFS_HDR_FNAME:	/* Can't rename a file this way */
-		case HFS_HDR_DID:       /* Can't specify a did this way */
-		case HFS_HDR_PRODOSI:   /* not implemented yet */
-		case HFS_HDR_AFPI:      /* ditto */
-		default:
-			break;
-		}
-
-		count -= left;
-		written += left;
-		pos += left;
-		buf += left;
-	}
-
-	/* Skip any padding at the end */
-	if (count) {
-		written += count;
-		pos += count;
-	}
-		
-done:
-	*ppos = pos;
-	if (written > 0) {
-	        if (pos > inode->i_size)
-		        inode->i_size = pos;
-	        inode->i_mtime = inode->i_atime = CURRENT_TIME;
-		mark_inode_dirty(inode);
-	}
-	return written;
-}
-
-/*
- * hdr_truncate()
- *
- * This is the truncate field in the inode_operations structure for
- * header files.  The purpose is to allocate or release blocks as needed
- * to satisfy a change in file length.
- */
-void hdr_truncate(struct inode *inode, size_t size)
-{
-	struct hfs_cat_entry *entry = HFS_I(inode)->entry;
-	struct hfs_hdr_layout *layout;
-	int lcv, last;
-
-	inode->i_size = size;
-	if (!HFS_I(inode)->layout) {
-		HFS_I(inode)->layout = dup_layout(HFS_I(inode)->default_layout);
-	}
-	layout = HFS_I(inode)->layout;
-
-	last = layout->entries - 1;
-	for (lcv = 0; lcv <= last; ++lcv) {
-		struct hfs_hdr_descr *descr = layout->order[lcv];
-		struct hfs_fork *fork;
-		hfs_u32 offset;
-
-		if (!descr) {
-			break;
-		}
-
-		if (descr->id == HFS_HDR_RSRC) {
-			fork = &entry->u.file.rsrc_fork;
-#if 0
-/* Can't yet truncate the data fork via a header file, since there is the
- * possibility to truncate via the data file, and the only locking is at
- * the inode level.
- */
-		} else if (descr->id == HFS_HDR_DATA) {
-			fork = &entry->u.file.data_fork;
-#endif
-		} else {
-			continue;
-		}
-
-		offset = descr->offset;
-
-		if ((lcv != last) && ((offset + descr->length) <= size)) {
-			continue;
-		}
-
-		if (offset < size) {
-			descr->length = size - offset;
-		} else {
-			descr->length = 0;
-		}
-		if (fork->lsize != descr->length) {
-			fork->lsize = descr->length;
-			hfs_extent_adj(fork);
-			hfs_cat_mark_dirty(entry);
-		}
-	}
-}
--- diff/fs/hfs/hfs_btree.h	2002-10-16 04:27:19.000000000 +0100
+++ source/fs/hfs/hfs_btree.h	1970-01-01 01:00:00.000000000 +0100
@@ -1,289 +0,0 @@
-/*
- * linux/fs/hfs/hfs_btree.h
- *
- * Copyright (C) 1995-1997  Paul H. Hargrove
- * This file may be distributed under the terms of the GNU General Public License.
- *
- * This file contains the declarations of the private B-tree
- * structures and functions.
- *
- * "XXX" in a comment is a note to myself to consider changing something.
- */
-
-#ifndef _HFS_BTREE_H
-#define _HFS_BTREE_H
-
-#include "hfs.h"
-
-/*================ Variable-like macros ================*/
-
-/* The stickiness of a (struct hfs_bnode) */
-#define HFS_NOT_STICKY	0
-#define HFS_STICKY	1
-
-/* The number of hash buckets in a B-tree's bnode cache */
-#define HFS_CACHELEN	17	/* primes are best? */
-
-/*
- * Legal values for the 'ndType' field of a (struct NodeDescriptor)
- *
- * Reference: _Inside Macintosh: Files_ p. 2-65
- */
-#define ndIndxNode	0x00	/* An internal (index) node */
-#define ndHdrNode	0x01	/* The tree header node (node 0) */
-#define ndMapNode	0x02	/* Holds part of the bitmap of used nodes */
-#define ndLeafNode	0xFF	/* A leaf (ndNHeight==1) node */
-
-/*
- * Legal values for the bthAtrb field of a (struct BTHdrRec)
- *
- * Reference: TN 1150
- */
-#define bthBadClose     0x00000001  /* b-tree not closed properly. not
-                                       used by hfsplus. */
-#define bthBigKeys      0x00000002  /* key length is u16 instead of u8.
-				       used by hfsplus. */
-#define bthVarIndxKeys  0x00000004  /* variable key length instead of
-                                       max key length. use din catalog
-                                       b-tree but not in extents
-                                       b-tree (hfsplus). */
-
-/*================ Function-like macros ================*/
-
-/* Access the cache slot which should contain the desired node */
-#define bhash(tree, node) ((tree)->cache[(node) % HFS_CACHELEN])
-
-/* round up to multiple of sizeof(hfs_u16) */
-#define ROUND(X) ((X + sizeof(hfs_u16) - 1) & ~(sizeof(hfs_u16)-1))
-
-/* Refer to the (base-1) array of offsets in a bnode */
-#define RECTBL(X,N) \
-	(((hfs_u16 *)(hfs_buffer_data((X)->buf)+HFS_SECTOR_SIZE))-(N))
-
-/*================ Private data types ================*/
-
-/*
- * struct BTHdrRec
- *
- * The B-tree header record
- *
- * This data structure is stored in the first node (512-byte block) of
- * each B-tree file.  It contains important information about the
- * B-tree.  Most fields vary over the life of the tree and are
- * indicated by a 'V' in the comments.	The other fields are fixed for
- * the life of the tree and are indicated by a 'F'.
- *
- * Reference: _Inside Macintosh: Files_ pp. 2-68 through 2-69 */
-struct BTHdrRec {
-	hfs_word_t  bthDepth;	/* (V) The number of levels in this B-tree */
-	hfs_lword_t bthRoot;	/* (V) The node number of the root node */
-	hfs_lword_t bthNRecs;	/* (V) The number of leaf records */
-	hfs_lword_t bthFNode;	/* (V) The number of the first leaf node */
-	hfs_lword_t bthLNode;	/* (V) The number of the last leaf node */
-	hfs_word_t  bthNodeSize;	/* (F) The number of bytes in a node (=512) */
-	hfs_word_t  bthKeyLen;	/* (F) The length of a key in an index node */
-	hfs_lword_t bthNNodes;	/* (V) The total number of nodes */
-	hfs_lword_t bthFree;	/* (V) The number of unused nodes */
-        hfs_word_t  bthResv1;   /* reserved */
-        hfs_lword_t bthClpSiz;  /* (F) clump size. not usually used. */
-        hfs_byte_t  bthType;    /* (F) BTree type */
-        hfs_byte_t  bthResv2;   /* reserved */
-        hfs_lword_t bthAtrb;    /* (F) attributes */
-        hfs_lword_t bthResv3[16]; /* Reserved */
-} __attribute__((packed));
-
-/*
- * struct NodeDescriptor
- *
- * The B-tree node descriptor.
- *
- * This structure begins each node in the B-tree file.	It contains
- * important information about the node's contents.  'V' and 'F' in
- * the comments indicate fields that are variable or fixed over the
- * life of a node, where the 'life' of a node is defined as the period
- * between leaving and reentering the free pool.
- *
- * Reference: _Inside Macintosh: Files_ p. 2-64
- */
-struct NodeDescriptor {
-	hfs_lword_t ndFLink;	/* (V) Number of the next node at this level */
-	hfs_lword_t ndBLink;	/* (V) Number of the prev node at this level */
-	hfs_byte_t  ndType;	/* (F) The type of node */
-	hfs_byte_t  ndNHeight;	/* (F) The level of this node (leaves=1) */
-	hfs_word_t  ndNRecs;	/* (V) The number of records in this node */
-	hfs_word_t  ndResv2;	/* Reserved */
-} __attribute__((packed));
-
-/*
- * typedef hfs_cmpfn
- *
- * The type 'hfs_cmpfn' is a comparison function taking 2 keys and
- * returning a positive, negative or zero integer according to the
- * ordering of the two keys (just like strcmp() does for strings).
- */
-typedef int (*hfs_cmpfn)(const void *, const void *);
-
-/*
- * struct hfs_bnode
- *
- * An in-core B-tree node
- *
- * This structure holds information from the NodeDescriptor in native
- * byte-order, a pointer to the buffer which contains the actual
- * node and fields necessary for locking access to the node during
- * updates.  The use of the locking fields is explained with the
- * locking functions.
- */
-struct hfs_bnode {
-	int		    magic;   /* Magic number to guard against
-					wild pointers */
-	hfs_buffer	    buf;     /* The buffer containing the
-					actual node */
-	struct hfs_btree    *tree;   /* The tree to which this node
-					belongs */
-	struct hfs_bnode    *prev;   /* Next node in this hash bucket */
-	struct hfs_bnode    *next;   /* Previous node in this hash
-					bucket */
-	int		    sticky;  /* Boolean: non-zero means keep
-					this node in-core (set for
-					root and head) */
-	hfs_u32		    node;    /* Node number */
-	hfs_u16             nodeSize; /* node size */
-        hfs_u16             keyLen;  /* key length */
-	/* locking related fields: */
-	hfs_wait_queue	    wqueue;  /* Wait queue for write access */
-	hfs_wait_queue	    rqueue;  /* Wait queue for read or reserve
-					access */
-	int		    count;   /* Number of processes accessing
-					this node */
-	int		    resrv;   /* Boolean, true means a process
-					had placed a 'reservation' on
-					this node */
-	int		    lock;    /* Boolean, true means some
-					process has exclusive access,
-					so KEEP OUT */
-	/* fields from the NodeDescriptor in native byte-order: */
-	hfs_u32		    ndFLink;
-	hfs_u32		    ndBLink;
-	hfs_u16		    ndNRecs;
-	hfs_u8		    ndType;
-	hfs_u8		    ndNHeight;
-};
-
-/*
- * struct hfs_btree
- *
- * An in-core B-tree.
- *
- * This structure holds information from the BTHdrRec, MDB
- * (superblock) and other information needed to work with the B-tree.
- */
-struct hfs_btree {
-	int			magic;	       /* Magic number to
-						  guard against wild
-						  pointers */
-	hfs_cmpfn		compare;       /* Comparison function
-						  for this tree */
-	struct hfs_bnode	head;	       /* in-core copy of node 0 */
-	struct hfs_bnode	*root;	       /* Pointer to the in-core
-						  copy of the root node */
-	hfs_sysmdb		sys_mdb;       /* The "device" holding
-						  the filesystem */
-	int			reserved;      /* bnodes claimed but
-						  not yet used */
-	struct hfs_bnode		       /* The bnode cache */
-				*cache[HFS_CACHELEN];
-	struct hfs_cat_entry	entry;	       /* Fake catalog entry */
-	struct semaphore	sem;
-	int			dirt;
-	int                     keySize;   
-	/* Fields from the BTHdrRec in native byte-order: */
-	hfs_u32			bthRoot;
-	hfs_u32			bthNRecs;
-	hfs_u32			bthFNode;
-	hfs_u32			bthLNode;
-	hfs_u32			bthNNodes;
-	hfs_u32			bthFree;
-	hfs_u16			bthKeyLen;
-	hfs_u16			bthDepth;
-};
-
-/*================ Global functions ================*/
-
-/* Convert a (struct hfs_bnode *) and an index to the value of the
-   n-th offset in the bnode (N >= 1) to the offset */
-extern inline hfs_u16 bnode_offset(const struct hfs_bnode *bnode, int n)
-{ return hfs_get_hs(RECTBL(bnode,n)); }
-
-/* Convert a (struct hfs_bnode *) and an index to the size of the
-   n-th record in the bnode (N >= 1) */
-extern inline hfs_u16 bnode_rsize(const struct hfs_bnode *bnode, int n)
-{ return bnode_offset(bnode, n+1) - bnode_offset(bnode, n); }
-
-/* Convert a (struct hfs_bnode *) to the offset of the empty part */
-extern inline hfs_u16 bnode_end(const struct hfs_bnode *bnode)
-{ return bnode_offset(bnode, bnode->ndNRecs + 1); }
-
-/* Convert a (struct hfs_bnode *) to the number of free bytes it contains */
-extern inline hfs_u16 bnode_freespace(const struct hfs_bnode *bnode)
-{ return HFS_SECTOR_SIZE - bnode_end(bnode)
-	  - (bnode->ndNRecs + 1)*sizeof(hfs_u16); }
-
-/* Convert a (struct hfs_bnode *) X and an index N to
-   the address of the record N in the bnode (N >= 1) */
-extern inline void *bnode_datastart(const struct hfs_bnode *bnode)
-{ return (void *)(hfs_buffer_data(bnode->buf)+sizeof(struct NodeDescriptor)); }
-
-/* Convert a (struct hfs_bnode *) to the address of the empty part */
-extern inline void *bnode_dataend(const struct hfs_bnode *bnode)
-{ return (void *)(hfs_buffer_data(bnode->buf) + bnode_end(bnode)); }
-
-/* Convert various pointers to address of record's key */
-extern inline void *bnode_key(const struct hfs_bnode *bnode, int n)
-{ return (void *)(hfs_buffer_data(bnode->buf) + bnode_offset(bnode, n)); }
-extern inline void *belem_key(const struct hfs_belem *elem)
-{ return bnode_key(elem->bnr.bn, elem->record); }
-extern inline void *brec_key(const struct hfs_brec *brec)
-{ return belem_key(brec->bottom); }
-
-/* Convert various pointers to the address of a record */
-extern inline void *bkey_record(const struct hfs_bkey *key)
-{ return (void *)key + ROUND(key->KeyLen + 1); }
-extern inline void *bnode_record(const struct hfs_bnode *bnode, int n)
-{ return bkey_record(bnode_key(bnode, n)); }
-extern inline void *belem_record(const struct hfs_belem *elem)
-{ return bkey_record(belem_key(elem)); }
-extern inline void *brec_record(const struct hfs_brec *brec)
-{ return bkey_record(brec_key(brec)); }
-
-/*================ Function Prototypes ================*/
-
-/* balloc.c */
-extern int hfs_bnode_bitop(struct hfs_btree *, hfs_u32, int);
-extern struct hfs_bnode_ref hfs_bnode_alloc(struct hfs_btree *);
-extern int hfs_bnode_free(struct hfs_bnode_ref *);
-extern void hfs_btree_extend(struct hfs_btree *);
-
-/* bins_del.c */
-extern void hfs_bnode_update_key(struct hfs_brec *, struct hfs_belem *,
-				 struct hfs_bnode *, int);
-extern void hfs_bnode_shift_right(struct hfs_bnode *, struct hfs_bnode *, int);
-extern void hfs_bnode_shift_left(struct hfs_bnode *, struct hfs_bnode *, int);
-extern int hfs_bnode_in_brec(hfs_u32 node, const struct hfs_brec *brec);
-
-/* bnode.c */
-extern void hfs_bnode_read(struct hfs_bnode *, struct hfs_btree *,
-			   hfs_u32, int);
-extern void hfs_bnode_relse(struct hfs_bnode_ref *);
-extern struct hfs_bnode_ref hfs_bnode_find(struct hfs_btree *, hfs_u32, int);
-extern void hfs_bnode_lock(struct hfs_bnode_ref *, int);
-extern void hfs_bnode_delete(struct hfs_bnode *);
-extern void hfs_bnode_commit(struct hfs_bnode *);
-
-/* brec.c */
-extern void hfs_brec_lock(struct hfs_brec *, struct hfs_belem *);
-extern struct hfs_belem *hfs_brec_init(struct hfs_brec *, struct hfs_btree *,
-				       int);
-extern struct hfs_belem *hfs_brec_next(struct hfs_brec *);
-
-#endif
--- diff/fs/hfs/version.c	2002-10-16 04:27:15.000000000 +0100
+++ source/fs/hfs/version.c	1970-01-01 01:00:00.000000000 +0100
@@ -1,10 +0,0 @@
-/*
- * linux/fs/hfs/version.c
- *
- * Copyright (C) 1995-1997  Paul H. Hargrove
- * This file may be distributed under the terms of the GNU General Public License.
- *
- * This file contains the version string for this release.
- */
-
-const char hfs_version[]="0.96";
--- diff/include/asm-mips/au1000.h	2003-07-08 09:55:19.000000000 +0100
+++ source/include/asm-mips/au1000.h	1970-01-01 01:00:00.000000000 +0100
@@ -1,1007 +0,0 @@
-/*
- *
- * BRIEF MODULE DESCRIPTION
- *	Include file for Alchemy Semiconductor's Au1k CPU.
- *
- * Copyright 2000,2001 MontaVista Software Inc.
- * Author: MontaVista Software, Inc.
- *         	ppopov@mvista.com or source@mvista.com
- *
- *  This program is free software; you can redistribute  it and/or modify it
- *  under  the terms of  the GNU General  Public License as published by the
- *  Free Software Foundation;  either version 2 of the  License, or (at your
- *  option) any later version.
- *
- *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
- *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
- *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
- *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
- *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
- *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- *  You should have received a copy of the  GNU General Public License along
- *  with this program; if not, write  to the Free Software Foundation, Inc.,
- *  675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
- /*
-  * some definitions add by takuzo@sm.sony.co.jp and sato@sm.sony.co.jp
-  */
-
-#ifndef _AU1000_H_
-#define _AU1000_H_
-
-#include <linux/delay.h>
-#include <asm/io.h>
-
-/* cpu pipeline flush */
-void static inline au_sync(void)
-{
-	__asm__ volatile ("sync");
-}
-
-void static inline au_sync_udelay(int us)
-{
-	__asm__ volatile ("sync");
-	udelay(us);
-}
-
-void static inline au_sync_delay(int ms)
-{
-	__asm__ volatile ("sync");
-	mdelay(ms);
-}
-
-void static inline au_writeb(u8 val, int reg)
-{
-	*(volatile u8 *)(reg) = val;
-}
-
-void static inline au_writew(u16 val, int reg)
-{
-	*(volatile u16 *)(reg) = val;
-}
-
-void static inline au_writel(u32 val, int reg)
-{
-	*(volatile u32 *)(reg) = val;
-}
-
-static inline u8 au_readb(unsigned long port)
-{
-	return (*(volatile u8 *)port);
-}
-
-static inline u16 au_readw(unsigned long port)
-{
-	return (*(volatile u16 *)port);
-}
-
-static inline u32 au_readl(unsigned long port)
-{
-	return (*(volatile u32 *)port);
-}
-
-/* arch/mips/au1000/common/clocks.c */
-extern void set_au1x00_speed(unsigned int new_freq);
-extern unsigned int get_au1x00_speed(void);
-extern void set_au1x00_uart_baud_base(unsigned long new_baud_base);
-extern unsigned long get_au1x00_uart_baud_base(void);
-extern void set_au1x00_lcd_clock(void);
-extern unsigned int get_au1x00_lcd_clock(void);
-
-#ifdef CONFIG_PM
-/* no CP0 timer irq */
-#define ALLINTS (IE_IRQ0 | IE_IRQ1 | IE_IRQ2 | IE_IRQ3 | IE_IRQ4)
-#else
-#define ALLINTS (IE_IRQ0 | IE_IRQ1 | IE_IRQ2 | IE_IRQ3 | IE_IRQ4 | IE_IRQ5)
-#endif
-
-/* SDRAM Controller */
-#define MEM_SDMODE0                0xB4000000
-#define MEM_SDMODE1                0xB4000004
-#define MEM_SDMODE2                0xB4000008
-
-#define MEM_SDADDR0                0xB400000C
-#define MEM_SDADDR1                0xB4000010
-#define MEM_SDADDR2                0xB4000014
-
-#define MEM_SDREFCFG               0xB4000018
-#define MEM_SDPRECMD               0xB400001C
-#define MEM_SDAUTOREF              0xB4000020
-
-#define MEM_SDWRMD0                0xB4000024
-#define MEM_SDWRMD1                0xB4000028
-#define MEM_SDWRMD2                0xB400002C
-
-#define MEM_SDSLEEP                0xB4000030
-#define MEM_SDSMCKE                0xB4000034
-
-/* Static Bus Controller */
-#define MEM_STCFG0                 0xB4001000
-#define MEM_STTIME0                0xB4001004
-#define MEM_STADDR0                0xB4001008
-
-#define MEM_STCFG1                 0xB4001010
-#define MEM_STTIME1                0xB4001014
-#define MEM_STADDR1                0xB4001018
-
-#define MEM_STCFG2                 0xB4001020
-#define MEM_STTIME2                0xB4001024
-#define MEM_STADDR2                0xB4001028
-
-#define MEM_STCFG3                 0xB4001030
-#define MEM_STTIME3                0xB4001034
-#define MEM_STADDR3                0xB4001038
-
-/* Interrupt Controller 0 */
-#define IC0_CFG0RD                 0xB0400040
-#define IC0_CFG0SET                0xB0400040
-#define IC0_CFG0CLR                0xB0400044
-
-#define IC0_CFG1RD                 0xB0400048
-#define IC0_CFG1SET                0xB0400048
-#define IC0_CFG1CLR                0xB040004C
-
-#define IC0_CFG2RD                 0xB0400050
-#define IC0_CFG2SET                0xB0400050
-#define IC0_CFG2CLR                0xB0400054
-
-#define IC0_REQ0INT                0xB0400054
-#define IC0_SRCRD                  0xB0400058
-#define IC0_SRCSET                 0xB0400058
-#define IC0_SRCCLR                 0xB040005C
-#define IC0_REQ1INT                0xB040005C
-
-#define IC0_ASSIGNRD               0xB0400060
-#define IC0_ASSIGNSET              0xB0400060
-#define IC0_ASSIGNCLR              0xB0400064
-
-#define IC0_WAKERD                 0xB0400068
-#define IC0_WAKESET                0xB0400068
-#define IC0_WAKECLR                0xB040006C
-
-#define IC0_MASKRD                 0xB0400070
-#define IC0_MASKSET                0xB0400070
-#define IC0_MASKCLR                0xB0400074
-
-#define IC0_RISINGRD               0xB0400078
-#define IC0_RISINGCLR              0xB0400078
-#define IC0_FALLINGRD              0xB040007C
-#define IC0_FALLINGCLR             0xB040007C
-
-#define IC0_TESTBIT                0xB0400080
-
-/* Interrupt Controller 1 */
-#define IC1_CFG0RD                 0xB1800040
-#define IC1_CFG0SET                0xB1800040
-#define IC1_CFG0CLR                0xB1800044
-
-#define IC1_CFG1RD                 0xB1800048
-#define IC1_CFG1SET                0xB1800048
-#define IC1_CFG1CLR                0xB180004C
-
-#define IC1_CFG2RD                 0xB1800050
-#define IC1_CFG2SET                0xB1800050
-#define IC1_CFG2CLR                0xB1800054
-
-#define IC1_REQ0INT                0xB1800054
-#define IC1_SRCRD                  0xB1800058
-#define IC1_SRCSET                 0xB1800058
-#define IC1_SRCCLR                 0xB180005C
-#define IC1_REQ1INT                0xB180005C
-
-#define IC1_ASSIGNRD               0xB1800060
-#define IC1_ASSIGNSET              0xB1800060
-#define IC1_ASSIGNCLR              0xB1800064
-
-#define IC1_WAKERD                 0xB1800068
-#define IC1_WAKESET                0xB1800068
-#define IC1_WAKECLR                0xB180006C
-
-#define IC1_MASKRD                 0xB1800070
-#define IC1_MASKSET                0xB1800070
-#define IC1_MASKCLR                0xB1800074
-
-#define IC1_RISINGRD               0xB1800078
-#define IC1_RISINGCLR              0xB1800078
-#define IC1_FALLINGRD              0xB180007C
-#define IC1_FALLINGCLR             0xB180007C
-
-#define IC1_TESTBIT                0xB1800080
-
-/* Interrupt Configuration Modes */
-#define INTC_INT_DISABLED                0
-#define INTC_INT_RISE_EDGE             0x1
-#define INTC_INT_FALL_EDGE             0x2
-#define INTC_INT_RISE_AND_FALL_EDGE    0x3
-#define INTC_INT_HIGH_LEVEL            0x5
-#define INTC_INT_LOW_LEVEL             0x6
-#define INTC_INT_HIGH_AND_LOW_LEVEL    0x7
-
-/* Interrupt Numbers */
-#define AU1000_UART0_INT          0
-#define AU1000_UART1_INT          1 /* au1000 */
-#define AU1000_UART2_INT          2 /* au1000 */
-
-#define AU1000_PCI_INTA           1 /* au1500 */
-#define AU1000_PCI_INTB           2 /* au1500 */
-
-#define AU1000_UART3_INT          3
-
-#define AU1000_SSI0_INT           4 /* au1000 */
-#define AU1000_SSI1_INT           5 /* au1000 */
-
-#define AU1000_PCI_INTC           4 /* au1500 */
-#define AU1000_PCI_INTD           5 /* au1500 */
-
-#define AU1000_DMA_INT_BASE       6
-#define AU1000_TOY_INT            14
-#define AU1000_TOY_MATCH0_INT     15
-#define AU1000_TOY_MATCH1_INT     16
-#define AU1000_TOY_MATCH2_INT     17
-#define AU1000_RTC_INT            18
-#define AU1000_RTC_MATCH0_INT     19
-#define AU1000_RTC_MATCH1_INT     20
-#define AU1000_RTC_MATCH2_INT     21
-#define AU1000_IRDA_TX_INT        22 /* au1000 */
-#define AU1000_IRDA_RX_INT        23 /* au1000 */
-#define AU1000_USB_DEV_REQ_INT    24
-#define AU1000_USB_DEV_SUS_INT    25
-#define AU1000_USB_HOST_INT       26
-#define AU1000_ACSYNC_INT         27
-#define AU1000_MAC0_DMA_INT       28
-#define AU1000_MAC1_DMA_INT       29
-#define AU1000_ETH0_IRQ           AU1000_MAC0_DMA_INT
-#define AU1000_ETH1_IRQ           AU1000_MAC1_DMA_INT
-#define AU1000_I2S_UO_INT         30 /* au1000 */
-#define AU1000_AC97C_INT          31
-#define AU1000_LAST_INTC0_INT     AU1000_AC97C_INT
-#define AU1000_GPIO_0             32
-#define AU1000_GPIO_1             33
-#define AU1000_GPIO_2             34
-#define AU1000_GPIO_3             35
-#define AU1000_GPIO_4             36
-#define AU1000_GPIO_5             37
-#define AU1000_GPIO_6             38
-#define AU1000_GPIO_7             39
-#define AU1000_GPIO_8             40
-#define AU1000_GPIO_9             41
-#define AU1000_GPIO_10            42
-#define AU1000_GPIO_11            43
-#define AU1000_GPIO_12            44
-#define AU1000_GPIO_13            45
-#define AU1000_GPIO_14            46
-#define AU1000_GPIO_15            47
-
-/* Au1000 only */
-#define AU1000_GPIO_16            48
-#define AU1000_GPIO_17            49
-#define AU1000_GPIO_18            50
-#define AU1000_GPIO_19            51
-#define AU1000_GPIO_20            52
-#define AU1000_GPIO_21            53
-#define AU1000_GPIO_22            54
-#define AU1000_GPIO_23            55
-#define AU1000_GPIO_24            56
-#define AU1000_GPIO_25            57
-#define AU1000_GPIO_26            58
-#define AU1000_GPIO_27            59
-#define AU1000_GPIO_28            60
-#define AU1000_GPIO_29            61
-#define AU1000_GPIO_30            62
-#define AU1000_GPIO_31            63
-
-/* Au1500 only */
-#define AU1500_GPIO_200           48
-#define AU1500_GPIO_201           49
-#define AU1500_GPIO_202           50
-#define AU1500_GPIO_203           51
-#define AU1500_GPIO_20            52
-#define AU1500_GPIO_204           53
-#define AU1500_GPIO_205           54
-#define AU1500_GPIO_23            55
-#define AU1500_GPIO_24            56
-#define AU1500_GPIO_25            57
-#define AU1500_GPIO_26            58
-#define AU1500_GPIO_27            59
-#define AU1500_GPIO_28            60
-#define AU1500_GPIO_206           61
-#define AU1500_GPIO_207           62
-#define AU1500_GPIO_208_215       63
-
-#define AU1000_MAX_INTR           63
-
-#define AU1100_SD		2
-#define	AU1100_GPIO_208_215	29
-// REDEFINE SECONDARY GPIO BLOCK INTO IC1 CONTROLLER HERE
-
-
-
-/* Programmable Counters 0 and 1 */
-#define SYS_BASE                   0xB1900000
-#define SYS_COUNTER_CNTRL          (SYS_BASE + 0x14)
-  #define SYS_CNTRL_E1S            (1<<23)
-  #define SYS_CNTRL_T1S            (1<<20)
-  #define SYS_CNTRL_M21            (1<<19)
-  #define SYS_CNTRL_M11            (1<<18)
-  #define SYS_CNTRL_M01            (1<<17)
-  #define SYS_CNTRL_C1S            (1<<16)
-  #define SYS_CNTRL_BP             (1<<14)
-  #define SYS_CNTRL_EN1            (1<<13)
-  #define SYS_CNTRL_BT1            (1<<12)
-  #define SYS_CNTRL_EN0            (1<<11)
-  #define SYS_CNTRL_BT0            (1<<10)
-  #define SYS_CNTRL_E0             (1<<8)
-  #define SYS_CNTRL_E0S            (1<<7)
-  #define SYS_CNTRL_32S            (1<<5)
-  #define SYS_CNTRL_T0S            (1<<4)
-  #define SYS_CNTRL_M20            (1<<3)
-  #define SYS_CNTRL_M10            (1<<2)
-  #define SYS_CNTRL_M00            (1<<1)
-  #define SYS_CNTRL_C0S            (1<<0)
-
-/* Programmable Counter 0 Registers */
-#define SYS_TOYTRIM                 (SYS_BASE + 0)
-#define SYS_TOYWRITE                (SYS_BASE + 4)
-#define SYS_TOYMATCH0               (SYS_BASE + 8)
-#define SYS_TOYMATCH1               (SYS_BASE + 0xC)
-#define SYS_TOYMATCH2               (SYS_BASE + 0x10)
-#define SYS_TOYREAD                 (SYS_BASE + 0x40)
-
-/* Programmable Counter 1 Registers */
-#define SYS_RTCTRIM                 (SYS_BASE + 0x44)
-#define SYS_RTCWRITE                (SYS_BASE + 0x48)
-#define SYS_RTCMATCH0               (SYS_BASE + 0x4C)
-#define SYS_RTCMATCH1               (SYS_BASE + 0x50)
-#define SYS_RTCMATCH2               (SYS_BASE + 0x54)
-#define SYS_RTCREAD                 (SYS_BASE + 0x58)
-
-/* I2S Controller */
-#define I2S_DATA                    0xB1000000
-  #define I2S_DATA_MASK        (0xffffff)
-#define I2S_CONFIG                0xB1000004
-  #define I2S_CONFIG_XU        (1<<25)
-  #define I2S_CONFIG_XO        (1<<24)
-  #define I2S_CONFIG_RU        (1<<23)
-  #define I2S_CONFIG_RO        (1<<22)
-  #define I2S_CONFIG_TR        (1<<21)
-  #define I2S_CONFIG_TE        (1<<20)
-  #define I2S_CONFIG_TF        (1<<19)
-  #define I2S_CONFIG_RR        (1<<18)
-  #define I2S_CONFIG_RE        (1<<17)
-  #define I2S_CONFIG_RF        (1<<16)
-  #define I2S_CONFIG_PD        (1<<11)
-  #define I2S_CONFIG_LB        (1<<10)
-  #define I2S_CONFIG_IC        (1<<9)
-  #define I2S_CONFIG_FM_BIT    7
-  #define I2S_CONFIG_FM_MASK     (0x3 << I2S_CONFIG_FM_BIT)
-    #define I2S_CONFIG_FM_I2S    (0x0 << I2S_CONFIG_FM_BIT)
-    #define I2S_CONFIG_FM_LJ     (0x1 << I2S_CONFIG_FM_BIT)
-    #define I2S_CONFIG_FM_RJ     (0x2 << I2S_CONFIG_FM_BIT)
-  #define I2S_CONFIG_TN        (1<<6)
-  #define I2S_CONFIG_RN        (1<<5)
-  #define I2S_CONFIG_SZ_BIT    0
-  #define I2S_CONFIG_SZ_MASK     (0x1F << I2S_CONFIG_SZ_BIT)
-
-#define I2S_CONTROL                0xB1000008
-  #define I2S_CONTROL_D         (1<<1)
-  #define I2S_CONTROL_CE        (1<<0)
-
-/* USB Host Controller */
-// We pass USB_OHCI_BASE to ioremap, so it needs to be a physical address
-#define USB_OHCI_BASE             0x10100000
-#define USB_OHCI_LEN              0x00100000
-#define USB_HOST_CONFIG           0xB017fffc
-
-/* USB Device Controller */
-#define USBD_EP0RD                0xB0200000
-#define USBD_EP0WR                0xB0200004
-#define USBD_EP2WR                0xB0200008
-#define USBD_EP3WR                0xB020000C
-#define USBD_EP4RD                0xB0200010
-#define USBD_EP5RD                0xB0200014
-#define USBD_INTEN                0xB0200018
-#define USBD_INTSTAT              0xB020001C
-  #define USBDEV_INT_SOF       (1<<12)
-  #define USBDEV_INT_HF_BIT    6
-  #define USBDEV_INT_HF_MASK   (0x3f << USBDEV_INT_HF_BIT)
-  #define USBDEV_INT_CMPLT_BIT  0
-  #define USBDEV_INT_CMPLT_MASK (0x3f << USBDEV_INT_CMPLT_BIT)
-#define USBD_CONFIG               0xB0200020
-#define USBD_EP0CS                0xB0200024
-#define USBD_EP2CS                0xB0200028
-#define USBD_EP3CS                0xB020002C
-#define USBD_EP4CS                0xB0200030
-#define USBD_EP5CS                0xB0200034
-  #define USBDEV_CS_SU         (1<<14)
-  #define USBDEV_CS_NAK        (1<<13)
-  #define USBDEV_CS_ACK        (1<<12)
-  #define USBDEV_CS_BUSY       (1<<11)
-  #define USBDEV_CS_TSIZE_BIT  1
-  #define USBDEV_CS_TSIZE_MASK (0x3ff << USBDEV_CS_TSIZE_BIT)
-  #define USBDEV_CS_STALL      (1<<0)
-#define USBD_EP0RDSTAT            0xB0200040
-#define USBD_EP0WRSTAT            0xB0200044
-#define USBD_EP2WRSTAT            0xB0200048
-#define USBD_EP3WRSTAT            0xB020004C
-#define USBD_EP4RDSTAT            0xB0200050
-#define USBD_EP5RDSTAT            0xB0200054
-  #define USBDEV_FSTAT_FLUSH     (1<<6)
-  #define USBDEV_FSTAT_UF        (1<<5)
-  #define USBDEV_FSTAT_OF        (1<<4)
-  #define USBDEV_FSTAT_FCNT_BIT  0
-  #define USBDEV_FSTAT_FCNT_MASK (0x0f << USBDEV_FSTAT_FCNT_BIT)
-#define USBD_ENABLE               0xB0200058
-  #define USBDEV_ENABLE (1<<1)
-  #define USBDEV_CE     (1<<0)
-
-/* Ethernet Controllers  */
-#define AU1000_ETH0_BASE          0xB0500000
-#define AU1000_ETH1_BASE          0xB0510000
-#define AU1500_ETH0_BASE	  0xB1500000
-#define AU1500_ETH1_BASE	  0xB1510000
-#define AU1100_ETH0_BASE	  0xB0500000
-
-/* 4 byte offsets from AU1000_ETH_BASE */
-#define MAC_CONTROL                     0x0
-  #define MAC_RX_ENABLE               (1<<2)
-  #define MAC_TX_ENABLE               (1<<3)
-  #define MAC_DEF_CHECK               (1<<5)
-  #define MAC_SET_BL(X)       (((X)&0x3)<<6)
-  #define MAC_AUTO_PAD                (1<<8)
-  #define MAC_DISABLE_RETRY          (1<<10)
-  #define MAC_DISABLE_BCAST          (1<<11)
-  #define MAC_LATE_COL               (1<<12)
-  #define MAC_HASH_MODE              (1<<13)
-  #define MAC_HASH_ONLY              (1<<15)
-  #define MAC_PASS_ALL               (1<<16)
-  #define MAC_INVERSE_FILTER         (1<<17)
-  #define MAC_PROMISCUOUS            (1<<18)
-  #define MAC_PASS_ALL_MULTI         (1<<19)
-  #define MAC_FULL_DUPLEX            (1<<20)
-  #define MAC_NORMAL_MODE                 0
-  #define MAC_INT_LOOPBACK           (1<<21)
-  #define MAC_EXT_LOOPBACK           (1<<22)
-  #define MAC_DISABLE_RX_OWN         (1<<23)
-  #define MAC_BIG_ENDIAN             (1<<30)
-  #define MAC_RX_ALL                 (1<<31)
-#define MAC_ADDRESS_HIGH                0x4
-#define MAC_ADDRESS_LOW                 0x8
-#define MAC_MCAST_HIGH                  0xC
-#define MAC_MCAST_LOW                  0x10
-#define MAC_MII_CNTRL                  0x14
-  #define MAC_MII_BUSY                (1<<0)
-  #define MAC_MII_READ                     0
-  #define MAC_MII_WRITE               (1<<1)
-  #define MAC_SET_MII_SELECT_REG(X)   (((X)&0x1f)<<6)
-  #define MAC_SET_MII_SELECT_PHY(X)   (((X)&0x1f)<<11)
-#define MAC_MII_DATA                   0x18
-#define MAC_FLOW_CNTRL                 0x1C
-  #define MAC_FLOW_CNTRL_BUSY         (1<<0)
-  #define MAC_FLOW_CNTRL_ENABLE       (1<<1)
-  #define MAC_PASS_CONTROL            (1<<2)
-  #define MAC_SET_PAUSE(X)        (((X)&0xffff)<<16)
-#define MAC_VLAN1_TAG                  0x20
-#define MAC_VLAN2_TAG                  0x24
-
-/* Ethernet Controller Enable */
-#define AU1000_MAC0_ENABLE       0xB0520000
-#define AU1000_MAC1_ENABLE       0xB0520004
-#define AU1500_MAC0_ENABLE       0xB1520000
-#define AU1500_MAC1_ENABLE       0xB1520004
-#define AU1100_MAC0_ENABLE       0xB0520000
-
-  #define MAC_EN_CLOCK_ENABLE         (1<<0)
-  #define MAC_EN_RESET0               (1<<1)
-  #define MAC_EN_TOSS                 (0<<2)
-  #define MAC_EN_CACHEABLE            (1<<3)
-  #define MAC_EN_RESET1               (1<<4)
-  #define MAC_EN_RESET2               (1<<5)
-  #define MAC_DMA_RESET               (1<<6)
-
-/* Ethernet Controller DMA Channels */
-
-#define MAC0_TX_DMA_ADDR         0xB4004000
-#define MAC1_TX_DMA_ADDR         0xB4004200
-/* offsets from MAC_TX_RING_ADDR address */
-#define MAC_TX_BUFF0_STATUS             0x0
-  #define TX_FRAME_ABORTED            (1<<0)
-  #define TX_JAB_TIMEOUT              (1<<1)
-  #define TX_NO_CARRIER               (1<<2)
-  #define TX_LOSS_CARRIER             (1<<3)
-  #define TX_EXC_DEF                  (1<<4)
-  #define TX_LATE_COLL_ABORT          (1<<5)
-  #define TX_EXC_COLL                 (1<<6)
-  #define TX_UNDERRUN                 (1<<7)
-  #define TX_DEFERRED                 (1<<8)
-  #define TX_LATE_COLL                (1<<9)
-  #define TX_COLL_CNT_MASK         (0xF<<10)
-  #define TX_PKT_RETRY               (1<<31)
-#define MAC_TX_BUFF0_ADDR                0x4
-  #define TX_DMA_ENABLE               (1<<0)
-  #define TX_T_DONE                   (1<<1)
-  #define TX_GET_DMA_BUFFER(X)    (((X)>>2)&0x3)
-#define MAC_TX_BUFF0_LEN                 0x8
-#define MAC_TX_BUFF1_STATUS             0x10
-#define MAC_TX_BUFF1_ADDR               0x14
-#define MAC_TX_BUFF1_LEN                0x18
-#define MAC_TX_BUFF2_STATUS             0x20
-#define MAC_TX_BUFF2_ADDR               0x24
-#define MAC_TX_BUFF2_LEN                0x28
-#define MAC_TX_BUFF3_STATUS             0x30
-#define MAC_TX_BUFF3_ADDR               0x34
-#define MAC_TX_BUFF3_LEN                0x38
-
-#define MAC0_RX_DMA_ADDR         0xB4004100
-#define MAC1_RX_DMA_ADDR         0xB4004300
-/* offsets from MAC_RX_RING_ADDR */
-#define MAC_RX_BUFF0_STATUS              0x0
-  #define RX_FRAME_LEN_MASK           0x3fff
-  #define RX_WDOG_TIMER              (1<<14)
-  #define RX_RUNT                    (1<<15)
-  #define RX_OVERLEN                 (1<<16)
-  #define RX_COLL                    (1<<17)
-  #define RX_ETHER                   (1<<18)
-  #define RX_MII_ERROR               (1<<19)
-  #define RX_DRIBBLING               (1<<20)
-  #define RX_CRC_ERROR               (1<<21)
-  #define RX_VLAN1                   (1<<22)
-  #define RX_VLAN2                   (1<<23)
-  #define RX_LEN_ERROR               (1<<24)
-  #define RX_CNTRL_FRAME             (1<<25)
-  #define RX_U_CNTRL_FRAME           (1<<26)
-  #define RX_MCAST_FRAME             (1<<27)
-  #define RX_BCAST_FRAME             (1<<28)
-  #define RX_FILTER_FAIL             (1<<29)
-  #define RX_PACKET_FILTER           (1<<30)
-  #define RX_MISSED_FRAME            (1<<31)
-
-  #define RX_ERROR (RX_WDOG_TIMER | RX_RUNT | RX_OVERLEN |  \
-                    RX_COLL | RX_MII_ERROR | RX_CRC_ERROR | \
-                    RX_LEN_ERROR | RX_U_CNTRL_FRAME | RX_MISSED_FRAME)
-#define MAC_RX_BUFF0_ADDR                0x4
-  #define RX_DMA_ENABLE               (1<<0)
-  #define RX_T_DONE                   (1<<1)
-  #define RX_GET_DMA_BUFFER(X)    (((X)>>2)&0x3)
-  #define RX_SET_BUFF_ADDR(X)     ((X)&0xffffffc0)
-#define MAC_RX_BUFF1_STATUS              0x10
-#define MAC_RX_BUFF1_ADDR                0x14
-#define MAC_RX_BUFF2_STATUS              0x20
-#define MAC_RX_BUFF2_ADDR                0x24
-#define MAC_RX_BUFF3_STATUS              0x30
-#define MAC_RX_BUFF3_ADDR                0x34
-
-
-/* UARTS 0-3 */
-#define UART0_ADDR                0xB1100000
-#define UART1_ADDR                0xB1200000
-#define UART2_ADDR                0xB1300000
-#define UART3_ADDR                0xB1400000
-#define UART_BASE                 UART0_ADDR
-#define UART_DEBUG_BASE           UART2_ADDR
-
-#define UART_RX		0	/* Receive buffer */
-#define UART_TX		4	/* Transmit buffer */
-#define UART_IER	8	/* Interrupt Enable Register */
-#define UART_IIR	0xC	/* Interrupt ID Register */
-#define UART_FCR	0x10	/* FIFO Control Register */
-#define UART_LCR	0x14	/* Line Control Register */
-#define UART_MCR	0x18	/* Modem Control Register */
-#define UART_LSR	0x1C	/* Line Status Register */
-#define UART_MSR	0x20	/* Modem Status Register */
-#define UART_CLK	0x28	/* Baud Rate Clock Divider */
-#define UART_MOD_CNTRL	0x100	/* Module Control */
-
-#define UART_FCR_ENABLE_FIFO	0x01 /* Enable the FIFO */
-#define UART_FCR_CLEAR_RCVR	0x02 /* Clear the RCVR FIFO */
-#define UART_FCR_CLEAR_XMIT	0x04 /* Clear the XMIT FIFO */
-#define UART_FCR_DMA_SELECT	0x08 /* For DMA applications */
-#define UART_FCR_TRIGGER_MASK	0xF0 /* Mask for the FIFO trigger range */
-#define UART_FCR_R_TRIGGER_1	0x00 /* Mask for receive trigger set at 1 */
-#define UART_FCR_R_TRIGGER_4	0x40 /* Mask for receive trigger set at 4 */
-#define UART_FCR_R_TRIGGER_8	0x80 /* Mask for receive trigger set at 8 */
-#define UART_FCR_R_TRIGGER_14   0xA0 /* Mask for receive trigger set at 14 */
-#define UART_FCR_T_TRIGGER_0	0x00 /* Mask for transmit trigger set at 0 */
-#define UART_FCR_T_TRIGGER_4	0x10 /* Mask for transmit trigger set at 4 */
-#define UART_FCR_T_TRIGGER_8    0x20 /* Mask for transmit trigger set at 8 */
-#define UART_FCR_T_TRIGGER_12	0x30 /* Mask for transmit trigger set at 12 */
-
-/*
- * These are the definitions for the Line Control Register
- */
-#define UART_LCR_SBC	0x40	/* Set break control */
-#define UART_LCR_SPAR	0x20	/* Stick parity (?) */
-#define UART_LCR_EPAR	0x10	/* Even parity select */
-#define UART_LCR_PARITY	0x08	/* Parity Enable */
-#define UART_LCR_STOP	0x04	/* Stop bits: 0=1 stop bit, 1= 2 stop bits */
-#define UART_LCR_WLEN5  0x00	/* Wordlength: 5 bits */
-#define UART_LCR_WLEN6  0x01	/* Wordlength: 6 bits */
-#define UART_LCR_WLEN7  0x02	/* Wordlength: 7 bits */
-#define UART_LCR_WLEN8  0x03	/* Wordlength: 8 bits */
-
-/*
- * These are the definitions for the Line Status Register
- */
-#define UART_LSR_TEMT	0x40	/* Transmitter empty */
-#define UART_LSR_THRE	0x20	/* Transmit-hold-register empty */
-#define UART_LSR_BI	0x10	/* Break interrupt indicator */
-#define UART_LSR_FE	0x08	/* Frame error indicator */
-#define UART_LSR_PE	0x04	/* Parity error indicator */
-#define UART_LSR_OE	0x02	/* Overrun error indicator */
-#define UART_LSR_DR	0x01	/* Receiver data ready */
-
-/*
- * These are the definitions for the Interrupt Identification Register
- */
-#define UART_IIR_NO_INT	0x01	/* No interrupts pending */
-#define UART_IIR_ID	0x06	/* Mask for the interrupt ID */
-#define UART_IIR_MSI	0x00	/* Modem status interrupt */
-#define UART_IIR_THRI	0x02	/* Transmitter holding register empty */
-#define UART_IIR_RDI	0x04	/* Receiver data interrupt */
-#define UART_IIR_RLSI	0x06	/* Receiver line status interrupt */
-
-/*
- * These are the definitions for the Interrupt Enable Register
- */
-#define UART_IER_MSI	0x08	/* Enable Modem status interrupt */
-#define UART_IER_RLSI	0x04	/* Enable receiver line status interrupt */
-#define UART_IER_THRI	0x02	/* Enable Transmitter holding register int. */
-#define UART_IER_RDI	0x01	/* Enable receiver data interrupt */
-
-/*
- * These are the definitions for the Modem Control Register
- */
-#define UART_MCR_LOOP	0x10	/* Enable loopback test mode */
-#define UART_MCR_OUT2	0x08	/* Out2 complement */
-#define UART_MCR_OUT1	0x04	/* Out1 complement */
-#define UART_MCR_RTS	0x02	/* RTS complement */
-#define UART_MCR_DTR	0x01	/* DTR complement */
-
-/*
- * These are the definitions for the Modem Status Register
- */
-#define UART_MSR_DCD	0x80	/* Data Carrier Detect */
-#define UART_MSR_RI	0x40	/* Ring Indicator */
-#define UART_MSR_DSR	0x20	/* Data Set Ready */
-#define UART_MSR_CTS	0x10	/* Clear to Send */
-#define UART_MSR_DDCD	0x08	/* Delta DCD */
-#define UART_MSR_TERI	0x04	/* Trailing edge ring indicator */
-#define UART_MSR_DDSR	0x02	/* Delta DSR */
-#define UART_MSR_DCTS	0x01	/* Delta CTS */
-#define UART_MSR_ANY_DELTA 0x0F	/* Any of the delta bits! */
-
-
-
-/* SSIO */
-#define SSI0_STATUS                0xB1600000
-  #define SSI_STATUS_BF              (1<<4)
-  #define SSI_STATUS_OF              (1<<3)
-  #define SSI_STATUS_UF              (1<<2)
-  #define SSI_STATUS_D               (1<<1)
-  #define SSI_STATUS_B               (1<<0)
-#define SSI0_INT                   0xB1600004
-  #define SSI_INT_OI                 (1<<3)
-  #define SSI_INT_UI                 (1<<2)
-  #define SSI_INT_DI                 (1<<1)
-#define SSI0_INT_ENABLE            0xB1600008
-  #define SSI_INTE_OIE               (1<<3)
-  #define SSI_INTE_UIE               (1<<2)
-  #define SSI_INTE_DIE               (1<<1)
-#define SSI0_CONFIG                0xB1600020
-  #define SSI_CONFIG_AO              (1<<24)
-  #define SSI_CONFIG_DO              (1<<23)
-  #define SSI_CONFIG_ALEN_BIT        20
-    #define SSI_CONFIG_ALEN_MASK       (0x7<<20)
-  #define SSI_CONFIG_DLEN_BIT        16
-    #define SSI_CONFIG_DLEN_MASK       (0x7<<16)
-  #define SSI_CONFIG_DD              (1<<11)
-  #define SSI_CONFIG_AD              (1<<10)
-  #define SSI_CONFIG_BM_BIT          8
-    #define SSI_CONFIG_BM_MASK         (0x3<<8)
-  #define SSI_CONFIG_CE              (1<<7)
-  #define SSI_CONFIG_DP              (1<<6)
-  #define SSI_CONFIG_DL              (1<<5)
-  #define SSI_CONFIG_EP              (1<<4)
-#define SSI0_ADATA                 0xB1600024
-  #define SSI_AD_D                   (1<<24)
-  #define SSI_AD_ADDR_BIT            16
-    #define SSI_AD_ADDR_MASK           (0xff<<16)
-  #define SSI_AD_DATA_BIT            0
-    #define SSI_AD_DATA_MASK           (0xfff<<0)
-#define SSI0_CLKDIV                0xB1600028
-#define SSI0_CONTROL               0xB1600100
-  #define SSI_CONTROL_CD             (1<<1)
-  #define SSI_CONTROL_E              (1<<0)
-
-/* SSI1 */
-#define SSI1_STATUS                0xB1680000
-#define SSI1_INT                   0xB1680004
-#define SSI1_INT_ENABLE            0xB1680008
-#define SSI1_CONFIG                0xB1680020
-#define SSI1_ADATA                 0xB1680024
-#define SSI1_CLKDIV                0xB1680028
-#define SSI1_ENABLE                0xB1680100
-
-/*
- * Register content definitions
- */
-#define SSI_STATUS_BF				(1<<4)
-#define SSI_STATUS_OF				(1<<3)
-#define SSI_STATUS_UF				(1<<2)
-#define SSI_STATUS_D				(1<<1)
-#define SSI_STATUS_B				(1<<0)
-
-/* SSI_INT */
-#define SSI_INT_OI					(1<<3)
-#define SSI_INT_UI					(1<<2)
-#define SSI_INT_DI					(1<<1)
-
-/* SSI_INTEN */
-#define SSI_INTEN_OIE				(1<<3)
-#define SSI_INTEN_UIE				(1<<2)
-#define SSI_INTEN_DIE				(1<<1)
-
-#define SSI_CONFIG_AO				(1<<24)
-#define SSI_CONFIG_DO				(1<<23)
-#define SSI_CONFIG_ALEN				(7<<20)
-#define SSI_CONFIG_DLEN				(15<<16)
-#define SSI_CONFIG_DD				(1<<11)
-#define SSI_CONFIG_AD				(1<<10)
-#define SSI_CONFIG_BM				(3<<8)
-#define SSI_CONFIG_CE				(1<<7)
-#define SSI_CONFIG_DP				(1<<6)
-#define SSI_CONFIG_DL				(1<<5)
-#define SSI_CONFIG_EP				(1<<4)
-#define SSI_CONFIG_ALEN_N(N)		((N-1)<<20)
-#define SSI_CONFIG_DLEN_N(N)		((N-1)<<16)
-#define SSI_CONFIG_BM_HI			(0<<8)
-#define SSI_CONFIG_BM_LO			(1<<8)
-#define SSI_CONFIG_BM_CY			(2<<8)
-
-#define SSI_ADATA_D					(1<<24)
-#define SSI_ADATA_ADDR				(0xFF<<16)
-#define SSI_ADATA_DATA				(0x0FFF)
-#define SSI_ADATA_ADDR_N(N)			(N<<16)
-
-#define SSI_ENABLE_CD				(1<<1)
-#define SSI_ENABLE_E				(1<<0)
-
-
-/* IrDA Controller */
-#define IRDA_BASE                 0xB0300000
-#define IR_RING_PTR_STATUS        (IRDA_BASE+0x00)
-#define IR_RING_BASE_ADDR_H       (IRDA_BASE+0x04)
-#define IR_RING_BASE_ADDR_L       (IRDA_BASE+0x08)
-#define IR_RING_SIZE              (IRDA_BASE+0x0C)
-#define IR_RING_PROMPT            (IRDA_BASE+0x10)
-#define IR_RING_ADDR_CMPR         (IRDA_BASE+0x14)
-#define IR_INT_CLEAR              (IRDA_BASE+0x18)
-#define IR_CONFIG_1               (IRDA_BASE+0x20)
-  #define IR_RX_INVERT_LED        (1<<0)
-  #define IR_TX_INVERT_LED        (1<<1)
-  #define IR_ST                   (1<<2)
-  #define IR_SF                   (1<<3)
-  #define IR_SIR                  (1<<4)
-  #define IR_MIR                  (1<<5)
-  #define IR_FIR                  (1<<6)
-  #define IR_16CRC                (1<<7)
-  #define IR_TD                   (1<<8)
-  #define IR_RX_ALL               (1<<9)
-  #define IR_DMA_ENABLE           (1<<10)
-  #define IR_RX_ENABLE            (1<<11)
-  #define IR_TX_ENABLE            (1<<12)
-  #define IR_LOOPBACK             (1<<14)
-  #define IR_SIR_MODE	          (IR_SIR | IR_DMA_ENABLE | \
-		                   IR_RX_ALL | IR_RX_ENABLE | IR_SF | IR_16CRC)
-#define IR_SIR_FLAGS              (IRDA_BASE+0x24)
-#define IR_ENABLE                 (IRDA_BASE+0x28)
-  #define IR_RX_STATUS            (1<<9)
-  #define IR_TX_STATUS            (1<<10)
-#define IR_READ_PHY_CONFIG        (IRDA_BASE+0x2C)
-#define IR_WRITE_PHY_CONFIG       (IRDA_BASE+0x30)
-#define IR_MAX_PKT_LEN            (IRDA_BASE+0x34)
-#define IR_RX_BYTE_CNT            (IRDA_BASE+0x38)
-#define IR_CONFIG_2               (IRDA_BASE+0x3C)
-  #define IR_MODE_INV             (1<<0)
-  #define IR_ONE_PIN              (1<<1)
-#define IR_INTERFACE_CONFIG       (IRDA_BASE+0x40)
-
-/* GPIO */
-#define SYS_PINFUNC               0xB190002C
-  #define SYS_PF_USB			(1<<15)	/* 2nd USB device/host */
-  #define SYS_PF_U3			(1<<14)	/* GPIO23/U3TXD */
-  #define SYS_PF_U2			(1<<13) /* GPIO22/U2TXD */
-  #define SYS_PF_U1			(1<<12) /* GPIO21/U1TXD */
-  #define SYS_PF_SRC			(1<<11)	/* GPIO6/SROMCKE */
-  #define SYS_PF_CK5			(1<<10)	/* GPIO3/CLK5 */
-  #define SYS_PF_CK4			(1<<9)	/* GPIO2/CLK4 */
-  #define SYS_PF_IRF			(1<<8)	/* GPIO15/IRFIRSEL */
-  #define SYS_PF_UR3			(1<<7)	/* GPIO[14:9]/UART3 */
-  #define SYS_PF_I2D			(1<<6)	/* GPIO8/I2SDI */
-  #define SYS_PF_I2S			(1<<5)	/* I2S/GPIO[29:31] */
-  #define SYS_PF_NI2			(1<<4)	/* NI2/GPIO[24:28] */
-  #define SYS_PF_U0			(1<<3)	/* U0TXD/GPIO20 */
-  #define SYS_PF_RD			(1<<2)	/* IRTXD/GPIO19 */
-  #define SYS_PF_A97			(1<<1)	/* AC97/SSL1 */
-  #define SYS_PF_S0			(1<<0)	/* SSI_0/GPIO[16:18] */
-#define SYS_TRIOUTRD              0xB1900100
-#define SYS_TRIOUTCLR             0xB1900100
-#define SYS_OUTPUTRD              0xB1900108
-#define SYS_OUTPUTSET             0xB1900108
-#define SYS_OUTPUTCLR             0xB190010C
-#define SYS_PINSTATERD            0xB1900110
-#define SYS_PININPUTEN            0xB1900110
-
-/* GPIO2, Au1500 only */
-#define GPIO2_BASE                0xB1700000
-#define GPIO2_DIR                 (GPIO2_BASE + 0)
-#define GPIO2_DATA_EN             (GPIO2_BASE + 8)
-#define GPIO2_PIN_STATE           (GPIO2_BASE + 0xC)
-#define GPIO2_INT_ENABLE          (GPIO2_BASE + 0x10)
-#define GPIO2_ENABLE              (GPIO2_BASE + 0x14)
-
-/* Power Management */
-#define SYS_SCRATCH0              0xB1900018
-#define SYS_SCRATCH1              0xB190001C
-#define SYS_WAKEMSK               0xB1900034
-#define SYS_ENDIAN                0xB1900038
-#define SYS_POWERCTRL             0xB190003C
-#define SYS_WAKESRC               0xB190005C
-#define SYS_SLPPWR                0xB1900078
-#define SYS_SLEEP                 0xB190007C
-
-/* Clock Controller */
-#define SYS_FREQCTRL0             0xB1900020
-  #define SYS_FC_FRDIV2_BIT         22
-  #define SYS_FC_FRDIV2_MASK        (0xff << FQC2_FRDIV2_BIT)
-  #define SYS_FC_FE2                (1<<21)
-  #define SYS_FC_FS2                (1<<20)
-  #define SYS_FC_FRDIV1_BIT         12
-  #define SYS_FC_FRDIV1_MASK        (0xff << FQC2_FRDIV1_BIT)
-  #define SYS_FC_FE1                (1<<11)
-  #define SYS_FC_FS1                (1<<10)
-  #define SYS_FC_FRDIV0_BIT         2
-  #define SYS_FC_FRDIV0_MASK        (0xff << FQC2_FRDIV0_BIT)
-  #define SYS_FC_FE0                (1<<1)
-  #define SYS_FC_FS0                (1<<0)
-#define SYS_FREQCTRL1             0xB1900024
-  #define SYS_FC_FRDIV5_BIT         22
-  #define SYS_FC_FRDIV5_MASK        (0xff << FQC2_FRDIV5_BIT)
-  #define SYS_FC_FE5                (1<<21)
-  #define SYS_FC_FS5                (1<<20)
-  #define SYS_FC_FRDIV4_BIT         12
-  #define SYS_FC_FRDIV4_MASK        (0xff << FQC2_FRDIV4_BIT)
-  #define SYS_FC_FE4                (1<<11)
-  #define SYS_FC_FS4                (1<<10)
-  #define SYS_FC_FRDIV3_BIT         2
-  #define SYS_FC_FRDIV3_MASK        (0xff << FQC2_FRDIV3_BIT)
-  #define SYS_FC_FE3                (1<<1)
-  #define SYS_FC_FS3                (1<<0)
-#define SYS_CLKSRC                0xB1900028
-  #define SYS_CS_ME1_BIT            27
-  #define SYS_CS_ME1_MASK           (0x7<<CSC_ME1_BIT)
-  #define SYS_CS_DE1                (1<<26)
-  #define SYS_CS_CE1                (1<<25)
-  #define SYS_CS_ME0_BIT            22
-  #define SYS_CS_ME0_MASK           (0x7<<CSC_ME0_BIT)
-  #define SYS_CS_DE0                (1<<21)
-  #define SYS_CS_CE0                (1<<20)
-  #define SYS_CS_MI2_BIT            17
-  #define SYS_CS_MI2_MASK           (0x7<<CSC_MI2_BIT)
-  #define SYS_CS_DI2                (1<<16)
-  #define SYS_CS_CI2                (1<<15)
-  #define SYS_CS_MUH_BIT            12
-  #define SYS_CS_MUH_MASK           (0x7<<CSC_MUH_BIT)
-  #define SYS_CS_DUH                (1<<11)
-  #define SYS_CS_CUH                (1<<10)
-  #define SYS_CS_MUD_BIT            7
-  #define SYS_CS_MUD_MASK           (0x7<<CSC_MUD_BIT)
-  #define SYS_CS_DUD                (1<<6)
-  #define SYS_CS_CUD                (1<<5)
-  #define SYS_CS_MIR_BIT            2
-  #define SYS_CS_MIR_MASK           (0x7<<CSC_MIR_BIT)
-  #define SYS_CS_DIR                (1<<1)
-  #define SYS_CS_CIR                (1<<0)
-
-  #define SYS_CS_MUX_AUX            0x1
-  #define SYS_CS_MUX_FQ0            0x2
-  #define SYS_CS_MUX_FQ1            0x3
-  #define SYS_CS_MUX_FQ2            0x4
-  #define SYS_CS_MUX_FQ3            0x5
-  #define SYS_CS_MUX_FQ4            0x6
-  #define SYS_CS_MUX_FQ5            0x7
-#define SYS_CPUPLL                0xB1900060
-#define SYS_AUXPLL                0xB1900064
-
-/* AC97 Controller */
-#define AC97C_CONFIG              0xB0000000
-  #define AC97C_RECV_SLOTS_BIT  13
-  #define AC97C_RECV_SLOTS_MASK (0x3ff << AC97C_RECV_SLOTS_BIT)
-  #define AC97C_XMIT_SLOTS_BIT  3
-  #define AC97C_XMIT_SLOTS_MASK (0x3ff << AC97C_XMIT_SLOTS_BIT)
-  #define AC97C_SG              (1<<2)
-  #define AC97C_SYNC            (1<<1)
-  #define AC97C_RESET           (1<<0)
-#define AC97C_STATUS              0xB0000004
-  #define AC97C_XU              (1<<11)
-  #define AC97C_XO              (1<<10)
-  #define AC97C_RU              (1<<9)
-  #define AC97C_RO              (1<<8)
-  #define AC97C_READY           (1<<7)
-  #define AC97C_CP              (1<<6)
-  #define AC97C_TR              (1<<5)
-  #define AC97C_TE              (1<<4)
-  #define AC97C_TF              (1<<3)
-  #define AC97C_RR              (1<<2)
-  #define AC97C_RE              (1<<1)
-  #define AC97C_RF              (1<<0)
-#define AC97C_DATA                0xB0000008
-#define AC97C_CMD                 0xB000000C
-  #define AC97C_WD_BIT          16
-  #define AC97C_READ            (1<<7)
-  #define AC97C_INDEX_MASK      0x7f
-#define AC97C_CNTRL               0xB0000010
-  #define AC97C_RS              (1<<1)
-  #define AC97C_CE              (1<<0)
-
-#ifdef CONFIG_SOC_AU1500
-/* Au1500 PCI Controller */
-#define Au1500_CFG_BASE           0xB4005000 // virtual, kseg0 addr
-#define Au1500_PCI_CMEM           (Au1500_CFG_BASE + 0)
-#define Au1500_PCI_CFG            (Au1500_CFG_BASE + 4)
-  #define PCI_ERROR ((1<<22) | (1<<23) | (1<<24) | (1<<25) | (1<<26) | (1<<27))
-#define Au1500_PCI_B2BMASK_CCH    (Au1500_CFG_BASE + 8)
-#define Au1500_PCI_B2B0_VID       (Au1500_CFG_BASE + 0xC)
-#define Au1500_PCI_B2B1_ID        (Au1500_CFG_BASE + 0x10)
-#define Au1500_PCI_MWMASK_DEV     (Au1500_CFG_BASE + 0x14)
-#define Au1500_PCI_MWBASE_REV_CCL (Au1500_CFG_BASE + 0x18)
-#define Au1500_PCI_ERR_ADDR       (Au1500_CFG_BASE + 0x1C)
-#define Au1500_PCI_SPEC_INTACK    (Au1500_CFG_BASE + 0x20)
-#define Au1500_PCI_ID             (Au1500_CFG_BASE + 0x100)
-#define Au1500_PCI_STATCMD        (Au1500_CFG_BASE + 0x104)
-#define Au1500_PCI_CLASSREV       (Au1500_CFG_BASE + 0x108)
-#define Au1500_PCI_HDRTYPE        (Au1500_CFG_BASE + 0x10C)
-#define Au1500_PCI_MBAR           (Au1500_CFG_BASE + 0x110)
-
-#define Au1500_PCI_HDR            0xB4005100 // virtual, kseg0 addr
-
-/* All of our structures, like pci resource, have 32 bit members.
- * Drivers are expected to do an ioremap on the PCI MEM resource, but it's
- * hard to store 0x4 0000 0000 in a 32 bit type.  We require a small patch
- * to __ioremap to check for addresses between (u32)Au1500_PCI_MEM_START and
- * (u32)Au1500_PCI_MEM_END and change those to the full 36 bit PCI MEM
- * addresses.  For PCI IO, it's simpler because we get to do the ioremap
- * ourselves and then adjust the device's resources.
- */
-#define Au1500_EXT_CFG            0x600000000
-#define Au1500_EXT_CFG_TYPE1      0x680000000
-#define Au1500_PCI_IO_START       0x500000000
-#define Au1500_PCI_IO_END         0x5000FFFFF
-#define Au1500_PCI_MEM_START      0x440000000
-#define Au1500_PCI_MEM_END        0x443FFFFFF
-
-#define PCI_IO_START    (Au1500_PCI_IO_START + 0x300)
-#define PCI_IO_END      (Au1500_PCI_IO_END)
-#define PCI_MEM_START   (Au1500_PCI_MEM_START)
-#define PCI_MEM_END     (Au1500_PCI_MEM_END)
-#define PCI_FIRST_DEVFN (0<<3)
-#define PCI_LAST_DEVFN  (19<<3)
-
-#endif
-
-#if defined(CONFIG_SOC_AU1100) || (defined(CONFIG_SOC_AU1000) && !defined(CONFIG_MIPS_PB1000))
-/* no PCI bus controller */
-#define PCI_IO_START    0
-#define PCI_IO_END      0
-#define PCI_MEM_START   0
-#define PCI_MEM_END     0 
-#define PCI_FIRST_DEVFN 0
-#define PCI_LAST_DEVFN  0
-#endif
-
-#endif
--- diff/include/asm-mips/au1000_dma.h	2003-07-08 09:55:19.000000000 +0100
+++ source/include/asm-mips/au1000_dma.h	1970-01-01 01:00:00.000000000 +0100
@@ -1,433 +0,0 @@
-/*
- * BRIEF MODULE DESCRIPTION
- *	Defines for using and allocating dma channels on the Alchemy
- *      Au1000 mips processor.
- *
- * Copyright 2000 MontaVista Software Inc.
- * Author: MontaVista Software, Inc.
- *         	stevel@mvista.com or source@mvista.com
- *
- *  This program is free software; you can redistribute  it and/or modify it
- *  under  the terms of  the GNU General  Public License as published by the
- *  Free Software Foundation;  either version 2 of the  License, or (at your
- *  option) any later version.
- *
- *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
- *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
- *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
- *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
- *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
- *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- *  You should have received a copy of the  GNU General Public License along
- *  with this program; if not, write  to the Free Software Foundation, Inc.,
- *  675 Mass Ave, Cambridge, MA 02139, USA.
- *
- */
-#ifndef __ASM_AU1000_DMA_H
-#define __ASM_AU1000_DMA_H
-
-#include <linux/config.h>
-#include <asm/io.h>		/* need byte IO */
-#include <linux/spinlock.h>	/* And spinlocks */
-#include <linux/delay.h>
-#include <asm/system.h>
-
-#define NUM_AU1000_DMA_CHANNELS	8
-
-/* DMA Channel Base Addresses */
-#define DMA_CHANNEL_BASE	0xB4002000
-#define DMA_CHANNEL_LEN		0x00000100
-
-/* DMA Channel Register Offsets */
-#define DMA_MODE_SET		0x00000000
-#define DMA_MODE_READ		DMA_MODE_SET
-#define DMA_MODE_CLEAR		0x00000004
-/* DMA Mode register bits follow */
-#define DMA_DAH_MASK		(0x0f << 20)
-#define DMA_DID_BIT		16
-#define DMA_DID_MASK		(0x0f << DMA_DID_BIT)
-#define DMA_BE			(1<<13)
-#define DMA_DR			(1<<12)
-#define DMA_TS8			(1<<11)
-#define DMA_DW_BIT		9
-#define DMA_DW_MASK		(0x03 << DMA_DW_BIT)
-#define DMA_DW8			(0 << DMA_DW_BIT)
-#define DMA_DW16		(1 << DMA_DW_BIT)
-#define DMA_DW32		(2 << DMA_DW_BIT)
-#define DMA_NC			(1<<8)
-#define DMA_IE			(1<<7)
-#define DMA_HALT		(1<<6)
-#define DMA_GO			(1<<5)
-#define DMA_AB			(1<<4)
-#define DMA_D1			(1<<3)
-#define DMA_BE1			(1<<2)
-#define DMA_D0			(1<<1)
-#define DMA_BE0			(1<<0)
-
-#define DMA_PERIPHERAL_ADDR       0x00000008
-#define DMA_BUFFER0_START         0x0000000C
-#define DMA_BUFFER1_START         0x00000014
-#define DMA_BUFFER0_COUNT         0x00000010
-#define DMA_BUFFER1_COUNT         0x00000018
-#define DMA_BAH_BIT 16
-#define DMA_BAH_MASK (0x0f << DMA_BAH_BIT)
-#define DMA_COUNT_BIT 0
-#define DMA_COUNT_MASK (0xffff << DMA_COUNT_BIT)
-
-/* DMA Device ID's follow */
-enum {
-	DMA_ID_UART0_TX = 0,
-	DMA_ID_UART0_RX,
-	DMA_ID_GP04,
-	DMA_ID_GP05,
-	DMA_ID_AC97C_TX,
-	DMA_ID_AC97C_RX,
-	DMA_ID_UART3_TX,
-	DMA_ID_UART3_RX,
-	DMA_ID_USBDEV_EP0_RX,
-	DMA_ID_USBDEV_EP0_TX,
-	DMA_ID_USBDEV_EP2_TX,
-	DMA_ID_USBDEV_EP3_TX,
-	DMA_ID_USBDEV_EP4_RX,
-	DMA_ID_USBDEV_EP5_RX,
-	DMA_ID_I2S_TX,
-	DMA_ID_I2S_RX,
-	DMA_NUM_DEV
-};
-
-struct dma_chan {
-	int dev_id;		// this channel is allocated if >=0, free otherwise
-	unsigned int io;
-	const char *dev_str;
-	int irq;
-	void *irq_dev;
-	unsigned int fifo_addr;
-	unsigned int mode;
-};
-
-/* These are in arch/mips/au1000/common/dma.c */
-extern struct dma_chan au1000_dma_table[];
-extern int request_au1000_dma(int dev_id,
-			      const char *dev_str,
-			      void (*irqhandler)(int, void *,
-						 struct pt_regs *),
-			      unsigned long irqflags,
-			      void *irq_dev_id);
-extern void free_au1000_dma(unsigned int dmanr);
-extern int au1000_dma_read_proc(char *buf, char **start, off_t fpos,
-				int length, int *eof, void *data);
-extern void dump_au1000_dma_channel(unsigned int dmanr);
-extern spinlock_t au1000_dma_spin_lock;
-
-
-static __inline__ struct dma_chan *get_dma_chan(unsigned int dmanr)
-{
-	if (dmanr > NUM_AU1000_DMA_CHANNELS
-	    || au1000_dma_table[dmanr].dev_id < 0)
-		return NULL;
-	return &au1000_dma_table[dmanr];
-}
-
-static __inline__ unsigned long claim_dma_lock(void)
-{
-	unsigned long flags;
-	spin_lock_irqsave(&au1000_dma_spin_lock, flags);
-	return flags;
-}
-
-static __inline__ void release_dma_lock(unsigned long flags)
-{
-	spin_unlock_irqrestore(&au1000_dma_spin_lock, flags);
-}
-
-/*
- * Set the DMA buffer enable bits in the mode register.
- */
-static __inline__ void enable_dma_buffer0(unsigned int dmanr)
-{
-	struct dma_chan *chan = get_dma_chan(dmanr);
-	if (!chan)
-		return;
-	au_writel(DMA_BE0, chan->io + DMA_MODE_SET);
-}
-static __inline__ void enable_dma_buffer1(unsigned int dmanr)
-{
-	struct dma_chan *chan = get_dma_chan(dmanr);
-	if (!chan)
-		return;
-	au_writel(DMA_BE1, chan->io + DMA_MODE_SET);
-}
-static __inline__ void enable_dma_buffers(unsigned int dmanr)
-{
-	struct dma_chan *chan = get_dma_chan(dmanr);
-	if (!chan)
-		return;
-	au_writel(DMA_BE0 | DMA_BE1, chan->io + DMA_MODE_SET);
-}
-
-static __inline__ void start_dma(unsigned int dmanr)
-{
-	struct dma_chan *chan = get_dma_chan(dmanr);
-	if (!chan)
-		return;
-
-	au_writel(DMA_GO, chan->io + DMA_MODE_SET);
-}
-
-#define DMA_HALT_POLL 0x5000
-
-static __inline__ void halt_dma(unsigned int dmanr)
-{
-	struct dma_chan *chan = get_dma_chan(dmanr);
-	int i;
-	if (!chan)
-		return;
-
-	au_writel(DMA_GO, chan->io + DMA_MODE_CLEAR);
-	// poll the halt bit
-	for (i = 0; i < DMA_HALT_POLL; i++)
-		if (au_readl(chan->io + DMA_MODE_READ) & DMA_HALT)
-			break;
-	if (i == DMA_HALT_POLL)
-		printk(KERN_INFO "halt_dma: HALT poll expired!\n");
-}
-
-
-static __inline__ void disable_dma(unsigned int dmanr)
-{
-	struct dma_chan *chan = get_dma_chan(dmanr);
-	if (!chan)
-		return;
-
-	halt_dma(dmanr);
-
-		// now we can disable the buffers
-		au_writel(~DMA_GO, chan->io + DMA_MODE_CLEAR);
-}
-
-static __inline__ int dma_halted(unsigned int dmanr)
-{
-	struct dma_chan *chan = get_dma_chan(dmanr);
-	if (!chan)
-		return 1;
-	return (au_readl(chan->io + DMA_MODE_READ) & DMA_HALT) ? 1 : 0;
-}
-
-/* initialize a DMA channel */
-static __inline__ void init_dma(unsigned int dmanr)
-{
-	struct dma_chan *chan = get_dma_chan(dmanr);
-	u32 mode;
-	if (!chan)
-		return;
-
-	disable_dma(dmanr);
-
-	// set device FIFO address
-	au_writel(PHYSADDR(chan->fifo_addr),
-		  chan->io + DMA_PERIPHERAL_ADDR);
-
-	mode = chan->mode | (chan->dev_id << DMA_DID_BIT);
-	if (chan->irq)
-		mode |= DMA_IE;
-
-	au_writel(~mode, chan->io + DMA_MODE_CLEAR);
-	au_writel(mode, chan->io + DMA_MODE_SET);
-}
-
-/*
- * set mode for a specific DMA channel
- */
-static __inline__ void set_dma_mode(unsigned int dmanr, unsigned int mode)
-{
-	struct dma_chan *chan = get_dma_chan(dmanr);
-	if (!chan)
-		return;
-	/*
-	 * set_dma_mode is only allowed to change endianess, direction,
-	 * transfer size, device FIFO width, and coherency settings.
-	 * Make sure anything else is masked off.
-	 */
-	mode &= (DMA_BE | DMA_DR | DMA_TS8 | DMA_DW_MASK | DMA_NC);
-	chan->mode &= ~(DMA_BE | DMA_DR | DMA_TS8 | DMA_DW_MASK | DMA_NC);
-	chan->mode |= mode;
-}
-
-static __inline__ unsigned int get_dma_mode(unsigned int dmanr)
-{
-	struct dma_chan *chan = get_dma_chan(dmanr);
-	if (!chan)
-		return 0;
-	return chan->mode;
-}
-
-static __inline__ int get_dma_active_buffer(unsigned int dmanr)
-{
-	struct dma_chan *chan = get_dma_chan(dmanr);
-	if (!chan)
-		return -1;
-	return (au_readl(chan->io + DMA_MODE_READ) & DMA_AB) ? 1 : 0;
-}
-
-
-/*
- * set the device FIFO address for a specific DMA channel - only
- * applicable to GPO4 and GPO5. All the other devices have fixed
- * FIFO addresses.
- */
-static __inline__ void set_dma_fifo_addr(unsigned int dmanr,
-					 unsigned int a)
-{
-	struct dma_chan *chan = get_dma_chan(dmanr);
-	if (!chan)
-		return;
-
-	if (chan->dev_id != DMA_ID_GP04 && chan->dev_id != DMA_ID_GP05)
-		return;
-
-	au_writel(PHYSADDR(a), chan->io + DMA_PERIPHERAL_ADDR);
-}
-
-/*
- * Clear the DMA buffer done bits in the mode register.
- */
-static __inline__ void clear_dma_done0(unsigned int dmanr)
-{
-	struct dma_chan *chan = get_dma_chan(dmanr);
-	if (!chan)
-		return;
-	au_writel(DMA_D0, chan->io + DMA_MODE_CLEAR);
-}
-static __inline__ void clear_dma_done1(unsigned int dmanr)
-{
-	struct dma_chan *chan = get_dma_chan(dmanr);
-	if (!chan)
-		return;
-	au_writel(DMA_D1, chan->io + DMA_MODE_CLEAR);
-}
-
-/*
- * This does nothing - not applicable to Au1000 DMA.
- */
-static __inline__ void set_dma_page(unsigned int dmanr, char pagenr)
-{
-}
-
-/*
- * Set Buffer 0 transfer address for specific DMA channel.
- */
-static __inline__ void set_dma_addr0(unsigned int dmanr, unsigned int a)
-{
-	struct dma_chan *chan = get_dma_chan(dmanr);
-	if (!chan)
-		return;
-	au_writel(a, chan->io + DMA_BUFFER0_START);
-}
-
-/*
- * Set Buffer 1 transfer address for specific DMA channel.
- */
-static __inline__ void set_dma_addr1(unsigned int dmanr, unsigned int a)
-{
-	struct dma_chan *chan = get_dma_chan(dmanr);
-	if (!chan)
-		return;
-	au_writel(a, chan->io + DMA_BUFFER1_START);
-}
-
-
-/*
- * Set Buffer 0 transfer size (max 64k) for a specific DMA channel.
- */
-static __inline__ void set_dma_count0(unsigned int dmanr,
-				      unsigned int count)
-{
-	struct dma_chan *chan = get_dma_chan(dmanr);
-	if (!chan)
-		return;
-	count &= DMA_COUNT_MASK;
-	au_writel(count, chan->io + DMA_BUFFER0_COUNT);
-}
-
-/*
- * Set Buffer 1 transfer size (max 64k) for a specific DMA channel.
- */
-static __inline__ void set_dma_count1(unsigned int dmanr,
-				      unsigned int count)
-{
-	struct dma_chan *chan = get_dma_chan(dmanr);
-	if (!chan)
-		return;
-	count &= DMA_COUNT_MASK;
-	au_writel(count, chan->io + DMA_BUFFER1_COUNT);
-}
-
-/*
- * Set both buffer transfer sizes (max 64k) for a specific DMA channel.
- */
-static __inline__ void set_dma_count(unsigned int dmanr,
-				     unsigned int count)
-{
-	struct dma_chan *chan = get_dma_chan(dmanr);
-	if (!chan)
-		return;
-	count &= DMA_COUNT_MASK;
-	au_writel(count, chan->io + DMA_BUFFER0_COUNT);
-	au_writel(count, chan->io + DMA_BUFFER1_COUNT);
-}
-
-/*
- * Returns which buffer has its done bit set in the mode register.
- * Returns -1 if neither or both done bits set.
- */
-static __inline__ unsigned int get_dma_buffer_done(unsigned int dmanr)
-{
-	struct dma_chan *chan = get_dma_chan(dmanr);
-	if (!chan)
-		return 0;
-
-    return au_readl(chan->io + DMA_MODE_READ) & (DMA_D0 | DMA_D1);
-}
-
-
-/*
- * Returns the DMA channel's Buffer Done IRQ number.
- */
-static __inline__ int get_dma_done_irq(unsigned int dmanr)
-{
-	struct dma_chan *chan = get_dma_chan(dmanr);
-	if (!chan)
-		return -1;
-
-	return chan->irq;
-}
-
-/*
- * Get DMA residue count. Returns the number of _bytes_ left to transfer.
- */
-static __inline__ int get_dma_residue(unsigned int dmanr)
-{
-	int curBufCntReg, count;
-	struct dma_chan *chan = get_dma_chan(dmanr);
-	if (!chan)
-		return 0;
-
-	curBufCntReg = (au_readl(chan->io + DMA_MODE_READ) & DMA_AB) ?
-	    DMA_BUFFER1_COUNT : DMA_BUFFER0_COUNT;
-
-	count = au_readl(chan->io + curBufCntReg) & DMA_COUNT_MASK;
-
-	if ((chan->mode & DMA_DW_MASK) == DMA_DW16)
-		count <<= 1;
-	else if ((chan->mode & DMA_DW_MASK) == DMA_DW32)
-		count <<= 2;
-
-	return count;
-}
-
-#endif /* __ASM_AU1000_DMA_H */
--- diff/include/asm-mips/au1000_gpio.h	2003-07-08 09:55:19.000000000 +0100
+++ source/include/asm-mips/au1000_gpio.h	1970-01-01 01:00:00.000000000 +0100
@@ -1,56 +0,0 @@
-/*
- * FILE NAME au1000_gpio.h
- *
- * BRIEF MODULE DESCRIPTION
- *	API to Alchemy Au1000 GPIO device.
- *
- *  Author: MontaVista Software, Inc.  <source@mvista.com>
- *          Steve Longerbeam <stevel@mvista.com>
- *
- * Copyright 2001 MontaVista Software Inc.
- *
- *  This program is free software; you can redistribute  it and/or modify it
- *  under  the terms of  the GNU General  Public License as published by the
- *  Free Software Foundation;  either version 2 of the  License, or (at your
- *  option) any later version.
- *
- *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
- *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
- *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
- *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
- *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
- *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- *  You should have received a copy of the  GNU General Public License along
- *  with this program; if not, write  to the Free Software Foundation, Inc.,
- *  675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#ifndef __AU1000_GPIO_H
-#define __AU1000_GPIO_H
-
-#include <linux/ioctl.h>
-
-#define AU1000GPIO_IOC_MAGIC 'A'
-
-#define AU1000GPIO_IN		_IOR (AU1000GPIO_IOC_MAGIC, 0, int)
-#define AU1000GPIO_SET		_IOW (AU1000GPIO_IOC_MAGIC, 1, int)
-#define AU1000GPIO_CLEAR	_IOW (AU1000GPIO_IOC_MAGIC, 2, int)
-#define AU1000GPIO_OUT		_IOW (AU1000GPIO_IOC_MAGIC, 3, int)
-#define AU1000GPIO_TRISTATE	_IOW (AU1000GPIO_IOC_MAGIC, 4, int)
-#define AU1000GPIO_AVAIL_MASK	_IOR (AU1000GPIO_IOC_MAGIC, 5, int)
-
-#ifdef __KERNEL__
-extern u32 get_au1000_avail_gpio_mask(void);
-extern int au1000gpio_tristate(u32 data);
-extern int au1000gpio_in(u32 *data);
-extern int au1000gpio_set(u32 data);
-extern int au1000gpio_clear(u32 data);
-extern int au1000gpio_out(u32 data);
-#endif
-
-#endif
--- diff/include/asm-mips/au1000_pcmcia.h	2003-07-08 09:55:19.000000000 +0100
+++ source/include/asm-mips/au1000_pcmcia.h	1970-01-01 01:00:00.000000000 +0100
@@ -1,111 +0,0 @@
-/*
- *
- * Alchemy Semi Au1000 pcmcia driver include file
- *
- * Copyright 2001 MontaVista Software Inc.
- * Author: MontaVista Software, Inc.
- *         	ppopov@mvista.com or source@mvista.com
- *
- * ########################################################################
- *
- *  This program is free software; you can distribute it and/or modify it
- *  under the terms of the GNU General Public License (Version 2) as
- *  published by the Free Software Foundation.
- *
- *  This program is distributed in the hope it will be useful, but WITHOUT
- *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- *  for more details.
- *
- *  You should have received a copy of the GNU General Public License along
- *  with this program; if not, write to the Free Software Foundation, Inc.,
- *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
- *
- * ########################################################################
- *
- *
- */
-#ifndef __ASM_AU1000_PCMCIA_H
-#define __ASM_AU1000_PCMCIA_H
-
-
-#define AU1000_PCMCIA_POLL_PERIOD    (2*HZ)
-#define AU1000_PCMCIA_IO_SPEED       (255)
-#define AU1000_PCMCIA_MEM_SPEED      (300)
-
-#define AU1X_SOCK0_IO        0xF00000000
-#define AU1X_SOCK0_PHYS_ATTR 0xF40000000
-#define AU1X_SOCK0_PHYS_MEM  0xF80000000
-
-/* pcmcia socket 1 needs external glue logic so the memory map
- * differs from board to board.
- */
-#if defined(CONFIG_MIPS_PB1000) || defined(CONFIG_MIPS_PB1100) || defined(CONFIG_MIPS_PB1500)
-#define AU1X_SOCK1_IO        0xF08000000
-#define AU1X_SOCK1_PHYS_ATTR 0xF48000000
-#define AU1X_SOCK1_PHYS_MEM  0xF88000000
-#elif defined(CONFIG_MIPS_DB1000) || defined(CONFIG_MIPS_DB1100) || defined(CONFIG_MIPS_DB1500)
-#define AU1X_SOCK1_IO        0xF04000000
-#define AU1X_SOCK1_PHYS_ATTR 0xF44000000
-#define AU1X_SOCK1_PHYS_MEM  0xF84000000
-#endif
-
-struct pcmcia_state {
-  unsigned detect: 1,
-            ready: 1,
-           wrprot: 1,
-	     bvd1: 1,
-	     bvd2: 1,
-            vs_3v: 1,
-            vs_Xv: 1;
-};
-
-struct pcmcia_configure {
-  unsigned sock: 8,
-            vcc: 8,
-            vpp: 8,
-         output: 1,
-        speaker: 1,
-          reset: 1;
-};
-
-struct pcmcia_irq_info {
-	unsigned int sock;
-	unsigned int irq;
-};
-
-
-struct au1000_pcmcia_socket {
-	socket_state_t        cs_state;
-	struct pcmcia_state   k_state;
-	unsigned int          irq;
-	void                  (*handler)(void *, unsigned int);
-	void                  *handler_info;
-	pccard_io_map         io_map[MAX_IO_WIN];
-	pccard_mem_map        mem_map[MAX_WIN];
-	u32                   virt_io;
-	ioaddr_t              phys_attr, phys_mem;
-	unsigned short        speed_io, speed_attr, speed_mem;
-};
-
-struct pcmcia_init {
-	void (*handler)(int irq, void *dev, struct pt_regs *regs);
-};
-
-struct pcmcia_low_level {
-	int (*init)(struct pcmcia_init *);
-	int (*shutdown)(void);
-	int (*socket_state)(unsigned sock, struct pcmcia_state *);
-	int (*get_irq_info)(struct pcmcia_irq_info *);
-	int (*configure_socket)(const struct pcmcia_configure *);
-};
-
-#if defined(CONFIG_MIPS_PB1000) || defined(CONFIG_MIPS_PB1100) || defined(CONFIG_MIPS_PB1500)
-extern struct pcmcia_low_level pb1x00_pcmcia_ops;
-#elif defined(CONFIG_MIPS_DB1000) || defined(CONFIG_MIPS_DB1100) || defined(CONFIG_MIPS_DB1500)
-extern struct pcmcia_low_level db1x00_pcmcia_ops;
-#else
-error unknown Au1000 board
-#endif
-
-#endif /* __ASM_AU1000_PCMCIA_H */
--- diff/include/asm-mips/au1000_usbdev.h	2003-07-08 09:55:19.000000000 +0100
+++ source/include/asm-mips/au1000_usbdev.h	1970-01-01 01:00:00.000000000 +0100
@@ -1,73 +0,0 @@
-/*
- * BRIEF MODULE DESCRIPTION
- *	Au1000 USB Device-Side Driver
- *
- * Copyright 2001 MontaVista Software Inc.
- * Author: MontaVista Software, Inc.
- *		stevel@mvista.com or source@mvista.com
- *
- *  This program is free software; you can redistribute	 it and/or modify it
- *  under  the terms of	 the GNU General  Public License as published by the
- *  Free Software Foundation;  either version 2 of the	License, or (at your
- *  option) any later version.
- *
- *  THIS  SOFTWARE  IS PROVIDED	  ``AS	IS'' AND   ANY	EXPRESS OR IMPLIED
- *  WARRANTIES,	  INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
- *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
- *  NO	EVENT  SHALL   THE AUTHOR  BE	 LIABLE FOR ANY	  DIRECT, INDIRECT,
- *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- *  NOT LIMITED	  TO, PROCUREMENT OF  SUBSTITUTE GOODS	OR SERVICES; LOSS OF
- *  USE, DATA,	OR PROFITS; OR	BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- *  ANY THEORY OF LIABILITY, WHETHER IN	 CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- *  You should have received a copy of the  GNU General Public License along
- *  with this program; if not, write  to the Free Software Foundation, Inc.,
- *  675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#define USBDEV_REV 0x0110 // BCD
-#define USBDEV_EP0_MAX_PACKET_SIZE 64
-
-typedef enum {
-	ATTACHED = 0,
-	POWERED,
-	DEFAULT,
-	ADDRESS,
-	CONFIGURED
-} usbdev_state_t;
-
-typedef enum {
-	CB_NEW_STATE = 0,
-	CB_PKT_COMPLETE
-} usbdev_cb_type_t;
-
-
-typedef struct usbdev_pkt {
-	int                ep_addr;    // ep addr this packet routed to
-	int                size;       // size of payload in bytes
-	unsigned           status;     // packet status
-	struct usbdev_pkt* next;       // function layer can't touch this
-	u8                 payload[0]; // the payload
-} usbdev_pkt_t;
-
-#define PKT_STATUS_ACK  (1<<0)
-#define PKT_STATUS_NAK  (1<<1)
-#define PKT_STATUS_SU   (1<<2)
-
-extern int usbdev_init(struct usb_device_descriptor* dev_desc,
-		       struct usb_config_descriptor* config_desc,
-		       struct usb_interface_descriptor* if_desc,
-		       struct usb_endpoint_descriptor* ep_desc,
-		       struct usb_string_descriptor* str_desc[],
-		       void (*cb)(usbdev_cb_type_t, unsigned long, void *),
-		       void* cb_data);
-
-extern void usbdev_exit(void);
-
-extern int usbdev_alloc_packet  (int ep_addr, int data_size,
-				 usbdev_pkt_t** pkt);
-extern int usbdev_send_packet   (int ep_addr, usbdev_pkt_t* pkt);
-extern int usbdev_receive_packet(int ep_addr, usbdev_pkt_t** pkt);
-extern int usbdev_get_byte_count(int ep_addr);
--- diff/include/asm-mips/db1x00.h	2003-07-08 09:55:19.000000000 +0100
+++ source/include/asm-mips/db1x00.h	1970-01-01 01:00:00.000000000 +0100
@@ -1,118 +0,0 @@
-/*
- * AMD Alchemy DB1x00 Reference Boards
- *
- * Copyright 2001 MontaVista Software Inc.
- * Author: MontaVista Software, Inc.
- *         	ppopov@mvista.com or source@mvista.com
- *
- * ########################################################################
- *
- *  This program is free software; you can distribute it and/or modify it
- *  under the terms of the GNU General Public License (Version 2) as
- *  published by the Free Software Foundation.
- *
- *  This program is distributed in the hope it will be useful, but WITHOUT
- *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- *  for more details.
- *
- *  You should have received a copy of the GNU General Public License along
- *  with this program; if not, write to the Free Software Foundation, Inc.,
- *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
- *
- * ########################################################################
- *
- * 
- */
-#ifndef __ASM_DB1X00_H
-#define __ASM_DB1X00_H
-
-
-/*
- * Overlay data structure of the Db1x00 board registers.
- * Registers located at physical 1E0000xx, KSEG1 0xAE0000xx
- */
-typedef volatile struct
-{
-	/*00*/	unsigned long whoami;
-	/*04*/	unsigned long status;
-	/*08*/	unsigned long switches;
-	/*0C*/	unsigned long resets;
-	/*10*/	unsigned long pcmcia;
-	/*14*/	unsigned long specific;
-	/*18*/	unsigned long leds;
-	/*1C*/	unsigned long swreset;
-
-} BCSR;
-
-/*
- * Register/mask bit definitions for the BCSRs
- */
-#define BCSR_WHOAMI_DCID		0x000F
-#define BCSR_WHOAMI_CPLD		0x00F0
-#define BCSR_WHOAMI_BOARD		0x0F00
-
-#define BCSR_STATUS_PC0VS		0x0003
-#define BCSR_STATUS_PC1VS		0x000C
-#define BCSR_STATUS_PC0FI		0x0010
-#define BCSR_STATUS_PC1FI		0x0020
-#define BCSR_STATUS_FLASHBUSY		0x0100
-#define BCSR_STATUS_ROMBUSY		0x0400
-#define BCSR_STATUS_SWAPBOOT		0x2000
-#define BCSR_STATUS_FLASHDEN		0xC000
-
-#define BCSR_SWITCHES_DIP		0x00FF
-#define BCSR_SWITCHES_DIP_1		0x0080
-#define BCSR_SWITCHES_DIP_2		0x0040
-#define BCSR_SWITCHES_DIP_3		0x0020
-#define BCSR_SWITCHES_DIP_4		0x0010
-#define BCSR_SWITCHES_DIP_5		0x0008
-#define BCSR_SWITCHES_DIP_6		0x0004
-#define BCSR_SWITCHES_DIP_7		0x0002
-#define BCSR_SWITCHES_DIP_8		0x0001
-#define BCSR_SWITCHES_ROTARY		0x0F00
-
-#define BCSR_RESETS_PHY0		0x0001
-#define BCSR_RESETS_PHY1		0x0002
-#define BCSR_RESETS_DC			0x0004
-
-#define BCSR_PCMCIA_PC0VPP		0x0003
-#define BCSR_PCMCIA_PC0VCC		0x000C
-#define BCSR_PCMCIA_PC0DRVEN		0x0010
-#define BCSR_PCMCIA_PC0RST		0x0080
-#define BCSR_PCMCIA_PC1VPP		0x0300
-#define BCSR_PCMCIA_PC1VCC		0x0C00
-#define BCSR_PCMCIA_PC1DRVEN		0x1000
-#define BCSR_PCMCIA_PC1RST		0x8000
-
-#define BCSR_BOARD_PCIM66EN		0x0001
-#define BCSR_BOARD_PCIM33		0x0100
-#define BCSR_BOARD_GPIO200RST		0x0400
-#define BCSR_BOARD_PCICFG		0x1000
-
-#define BCSR_LEDS_DECIMALS		0x0003
-#define BCSR_LEDS_LED0			0x0100
-#define BCSR_LEDS_LED1			0x0200
-#define BCSR_LEDS_LED2			0x0400
-#define BCSR_LEDS_LED3			0x0800
-
-#define BCSR_SWRESET_RESET		0x0080
-
-/* PCMCIA Db1x00 specific defines */
-#define PCMCIA_MAX_SOCK 1
-#define PCMCIA_NUM_SOCKS (PCMCIA_MAX_SOCK+1)
-
-/* VPP/VCC */
-#define SET_VCC_VPP(VCC, VPP, SLOT)\
-	((((VCC)<<2) | ((VPP)<<0)) << ((SLOT)*8))
-
-/* MTD CONFIG OPTIONS */
-#if defined(CONFIG_MTD_DB1X00_BOOT) && defined(CONFIG_MTD_DB1X00_USER)
-#define DB1X00_BOTH_BANKS
-#elif defined(CONFIG_MTD_DB1X00_BOOT) && !defined(CONFIG_MTD_DB1X00_USER)
-#define DB1X00_BOOT_ONLY
-#elif !defined(CONFIG_MTD_DB1X00_BOOT) && defined(CONFIG_MTD_DB1X00_USER)
-#define DB1X00_USER_ONLY
-#endif
-
-#endif /* __ASM_DB1X00_H */
--- diff/include/asm-mips/dec/rtc-dec.h	2003-07-08 09:55:19.000000000 +0100
+++ source/include/asm-mips/dec/rtc-dec.h	1970-01-01 01:00:00.000000000 +0100
@@ -1,32 +0,0 @@
-/*
- *	include/asm-mips/dec/rtc-dec.h
- *
- *	RTC definitions for DECstation style attached Dallas DS1287 chip.
- *
- *	Copyright (C) 2002  Maciej W. Rozycki
- *
- *	This program is free software; you can redistribute it and/or
- *	modify it under the terms of the GNU General Public License
- *	as published by the Free Software Foundation; either version
- *	2 of the License, or (at your option) any later version.
- */
-#ifndef __ASM_MIPS_DEC_RTC_DEC_H
-#define __ASM_MIPS_DEC_RTC_DEC_H
-
-#include <linux/types.h>
-
-#include <asm/addrspace.h>
-
-extern volatile u8 *dec_rtc_base;
-extern unsigned long dec_kn_slot_size;
-
-extern struct rtc_ops dec_rtc_ops;
-
-#define RTC_PORT(x)	CPHYSADDR(dec_rtc_base)
-#define RTC_IO_EXTENT	dec_kn_slot_size
-#define RTC_IOMAPPED	0
-#define RTC_IRQ		0
-
-#define RTC_DEC_YEAR	0x3f	/* Where we store the real year on DECs.  */
-
-#endif /* __ASM_MIPS_DEC_RTC_DEC_H */
--- diff/include/asm-mips/galileo-boards/ev64120.h	2003-07-08 09:55:19.000000000 +0100
+++ source/include/asm-mips/galileo-boards/ev64120.h	1970-01-01 01:00:00.000000000 +0100
@@ -1,59 +0,0 @@
-/*
- *  This is a direct copy of the ev96100.h file, with a global
- * search and replace.  The numbers are the same.
- *
- *  The reason I'm duplicating this is so that the 64120/96100
- * defines won't be confusing in the source code.
- */
-#ifndef _MIPS_EV64120_H
-#define _MIPS_EV64120_H
-
-#include <asm/addrspace.h>
-
-/*
- *   GT64120 config space base address
- */
-#define GT64120_BASE    (KSEG1ADDR(0x14000000))
-#define MIPS_GT_BASE    GT64120_BASE
-
-/*
- *   PCI Bus allocation
- */
-#define GT_PCI_MEM_BASE    0x12000000
-#define GT_PCI_MEM_SIZE    0x02000000
-#define GT_PCI_IO_BASE     0x10000000
-#define GT_PCI_IO_SIZE     0x02000000
-#define GT_ISA_IO_BASE     PCI_IO_BASE
-
-/*
- *   Duart I/O ports.
- */
-#define EV64120_COM1_BASE_ADDR  (0x1d000000 + 0x20)
-#define EV64120_COM2_BASE_ADDR  (0x1d000000 + 0x00)
-
-
-/*
- *   EV64120 interrupt controller register base.
- */
-#define EV64120_ICTRL_REGS_BASE   (KSEG1ADDR(0x1f000000))
-
-/*
- *   EV64120 UART register base.
- */
-#define EV64120_UART0_REGS_BASE    (KSEG1ADDR(EV64120_COM1_BASE_ADDR))
-#define EV64120_UART1_REGS_BASE    (KSEG1ADDR(EV64120_COM2_BASE_ADDR))
-#define EV64120_BASE_BAUD ( 3686400 / 16 )
-
-
-/*
- * Because of an error/peculiarity in the Galileo chip, we need to swap the
- * bytes when running bigendian.
- */
-
-#define GT_WRITE(ofs, data)  \
-             *(volatile u32 *)(MIPS_GT_BASE+ofs) = cpu_to_le32(data)
-#define GT_READ(ofs, data)   \
-             *data = le32_to_cpu(*(volatile u32 *)(MIPS_GT_BASE+ofs))
-
-
-#endif /* !(_MIPS_EV64120_H) */
--- diff/include/asm-mips/galileo-boards/ev64120int.h	2003-07-08 09:55:19.000000000 +0100
+++ source/include/asm-mips/galileo-boards/ev64120int.h	1970-01-01 01:00:00.000000000 +0100
@@ -1,36 +0,0 @@
-#ifndef IRQ_HANDLER_
-#define IRQ_HANDLER_
-
-#define INT_CAUSE_MAIN 0
-#define INT_CAUSE_HIGH 1
-
-#define MAX_CAUSE_REGS 4
-#define MAX_CAUSE_REG_WIDTH 32
-
-void hook_irq_handler (int int_cause , int bit_num , void *isr_ptr);
-int disable_galileo_irq (int int_cause , int bit_num);
-int enable_galileo_irq (int int_cause , int bit_num);
-
-extern struct tq_struct irq_handlers[MAX_CAUSE_REGS][MAX_CAUSE_REG_WIDTH];
-
-/*
-  PCI interrupts will come in on either the INTA or
-  INTD interrups lines, which are mapped to the #2 and
-  #5 interrupt pins of the MIPS.  On our boards, they
-  all either come in on IntD or they all come in on
-  IntA, they aren't mixed. There can be numerous PCI
-  interrupts, so we keep a list of the "requested"
-  interrupt numbers and go through the list whenever
-  we get an IntA/D.
-
-  All PCI interrupts have numbers >= 20 by arbitrary convention.  Any
-  interrupt < 8 is an interrupt that is maskable on the
-  MIPS.
-*/
-
-#define TIMER 4
-#define INTA 2
-#define INTD 5
-
-
-#endif /* IRQ_HANDLER_ */
--- diff/include/asm-mips/gt64120/gt64120.h	2003-08-20 14:16:33.000000000 +0100
+++ source/include/asm-mips/gt64120/gt64120.h	1970-01-01 01:00:00.000000000 +0100
@@ -1,444 +0,0 @@
-/*
- * Copyright (C) 2000 MIPS Technologies, Inc.  All rights reserved.
- * Carsten Langgaard, carstenl@mips.com
- *
- * Copyright 2001 MontaVista Software Inc.
- * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net
- *
- *  This program is free software; you can distribute it and/or modify it
- *  under the terms of the GNU General Public License (Version 2) as
- *  published by the Free Software Foundation.
- *
- *  This program is distributed in the hope it will be useful, but WITHOUT
- *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- *  for more details.
- *
- *  You should have received a copy of the GNU General Public License along
- *  with this program; if not, write to the Free Software Foundation, Inc.,
- *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
- */
-#ifndef __ASM_GT64120_GT64120_H
-#define __ASM_GT64120_GT64120_H
-
-#define MSK(n)                    ((1 << (n)) - 1)
-
-/*
- *  Register offset addresses
- */
-#define GT_CPU_OFS		0x000
-
-/*
- * Interrupt Registers
- */
-#define GT_SCS10LD_OFS		0x008
-#define GT_SCS10HD_OFS		0x010
-#define GT_SCS32LD_OFS		0x018
-#define GT_SCS32HD_OFS		0x020
-#define GT_CS20LD_OFS		0x028
-#define GT_CS20HD_OFS		0x030
-#define GT_CS3BOOTLD_OFS	0x038
-#define GT_CS3BOOTHD_OFS	0x040
-#define GT_PCI0IOLD_OFS		0x048
-#define GT_PCI0IOHD_OFS		0x050
-#define GT_PCI0M0LD_OFS		0x058
-#define GT_PCI0M0HD_OFS		0x060
-#define GT_ISD_OFS		0x068
-#define GT_PCI0M1LD_OFS		0x080
-#define GT_PCI0M1HD_OFS		0x088
-#define GT_PCI1IOLD_OFS		0x090
-#define GT_PCI1IOHD_OFS		0x098
-#define GT_PCI1M0LD_OFS		0x0a0
-#define GT_PCI1M0HD_OFS		0x0a8
-#define GT_PCI1M1LD_OFS		0x0b0
-#define GT_PCI1M1HD_OFS		0x0b8
-
-/*
- * GT64120A only
- */
-#define GT_PCI0IOREMAP_OFS	0x0f0
-#define GT_PCI0M0REMAP_OFS	0x0f8
-#define GT_PCI0M1REMAP_OFS	0x100
-#define GT_PCI1IOREMAP_OFS	0x108
-#define GT_PCI1M0REMAP_OFS	0x110
-#define GT_PCI1M1REMAP_OFS	0x118
-
-#define GT_SCS0LD_OFS		0x400
-#define GT_SCS0HD_OFS		0x404
-#define GT_SCS1LD_OFS		0x408
-#define GT_SCS1HD_OFS		0x40c
-#define GT_SCS2LD_OFS		0x410
-#define GT_SCS2HD_OFS		0x414
-#define GT_SCS3LD_OFS		0x418
-#define GT_SCS3HD_OFS		0x41c
-#define GT_CS0LD_OFS		0x420
-#define GT_CS0HD_OFS		0x424
-#define GT_CS1LD_OFS		0x428
-#define GT_CS1HD_OFS		0x42c
-#define GT_CS2LD_OFS		0x430
-#define GT_CS2HD_OFS		0x434
-#define GT_CS3LD_OFS		0x438
-#define GT_CS3HD_OFS		0x43c
-#define GT_BOOTLD_OFS		0x440
-#define GT_BOOTHD_OFS		0x444
-
-#define GT_SDRAM_B0_OFS	    	0x44c
-#define GT_SDRAM_CFG_OFS	0x448
-#define GT_SDRAM_B2_OFS		0x454
-#define GT_SDRAM_OPMODE_OFS	0x474
-#define GT_SDRAM_BM_OFS		0x478
-#define GT_SDRAM_ADDRDECODE_OFS	0x47c
-
-#define GT_PCI0_CMD_OFS		0xc00	/* GT64120A only */
-#define GT_PCI0_TOR_OFS		0xc04
-#define GT_PCI0_BS_SCS10_OFS    0xc08
-#define GT_PCI0_BS_SCS32_OFS    0xc0c
-#define GT_INTRCAUSE_OFS	0xc18
-#define GT_INTRMASK_OFS		0xc1c	/* GT64120A only */
-#define GT_PCI0_IACK_OFS	0xc34
-#define GT_PCI0_BARE_OFS	0xc3c
-#define GT_HINTRCAUSE_OFS	0xc98	/* GT64120A only */
-#define GT_HINTRMASK_OFS	0xc9c	/* GT64120A only */
-#define GT_PCI1_CFGADDR_OFS	0xcf0	/* GT64120A only */
-#define GT_PCI1_CFGDATA_OFS	0xcf4	/* GT64120A only */
-#define GT_PCI0_CFGADDR_OFS	0xcf8
-#define GT_PCI0_CFGDATA_OFS	0xcfc
-
-
-/*
- * Timer/Counter.  GT64120A only.
- */
-#define GT_TC0_OFS		0x850
-#define GT_TC1_OFS		0x854
-#define GT_TC2_OFS		0x858
-#define GT_TC3_OFS		0x85C
-#define GT_TC_CONTROL_OFS	0x864
-
-/*
- * I2O Support Registers
- */
-#define INBOUND_MESSAGE_REGISTER0_PCI_SIDE		0x010
-#define INBOUND_MESSAGE_REGISTER1_PCI_SIDE		0x014
-#define OUTBOUND_MESSAGE_REGISTER0_PCI_SIDE		0x018
-#define OUTBOUND_MESSAGE_REGISTER1_PCI_SIDE		0x01c
-#define INBOUND_DOORBELL_REGISTER_PCI_SIDE		0x020
-#define INBOUND_INTERRUPT_CAUSE_REGISTER_PCI_SIDE	0x024
-#define INBOUND_INTERRUPT_MASK_REGISTER_PCI_SIDE	0x028
-#define OUTBOUND_DOORBELL_REGISTER_PCI_SIDE		0x02c
-#define OUTBOUND_INTERRUPT_CAUSE_REGISTER_PCI_SIDE	0x030
-#define OUTBOUND_INTERRUPT_MASK_REGISTER_PCI_SIDE	0x034
-#define INBOUND_QUEUE_PORT_VIRTUAL_REGISTER_PCI_SIDE	0x040
-#define OUTBOUND_QUEUE_PORT_VIRTUAL_REGISTER_PCI_SIDE	0x044
-#define QUEUE_CONTROL_REGISTER_PCI_SIDE			0x050
-#define QUEUE_BASE_ADDRESS_REGISTER_PCI_SIDE		0x054
-#define INBOUND_FREE_HEAD_POINTER_REGISTER_PCI_SIDE	0x060
-#define INBOUND_FREE_TAIL_POINTER_REGISTER_PCI_SIDE	0x064
-#define INBOUND_POST_HEAD_POINTER_REGISTER_PCI_SIDE	0x068
-#define INBOUND_POST_TAIL_POINTER_REGISTER_PCI_SIDE	0x06c
-#define OUTBOUND_FREE_HEAD_POINTER_REGISTER_PCI_SIDE	0x070
-#define OUTBOUND_FREE_TAIL_POINTER_REGISTER_PCI_SIDE	0x074
-#define OUTBOUND_POST_HEAD_POINTER_REGISTER_PCI_SIDE	0x078
-#define OUTBOUND_POST_TAIL_POINTER_REGISTER_PCI_SIDE	0x07c
-
-#define INBOUND_MESSAGE_REGISTER0_CPU_SIDE		0x1c10
-#define INBOUND_MESSAGE_REGISTER1_CPU_SIDE		0x1c14
-#define OUTBOUND_MESSAGE_REGISTER0_CPU_SIDE		0x1c18
-#define OUTBOUND_MESSAGE_REGISTER1_CPU_SIDE		0x1c1c
-#define INBOUND_DOORBELL_REGISTER_CPU_SIDE		0x1c20
-#define INBOUND_INTERRUPT_CAUSE_REGISTER_CPU_SIDE	0x1c24
-#define INBOUND_INTERRUPT_MASK_REGISTER_CPU_SIDE	0x1c28
-#define OUTBOUND_DOORBELL_REGISTER_CPU_SIDE		0x1c2c
-#define OUTBOUND_INTERRUPT_CAUSE_REGISTER_CPU_SIDE	0x1c30
-#define OUTBOUND_INTERRUPT_MASK_REGISTER_CPU_SIDE	0x1c34
-#define INBOUND_QUEUE_PORT_VIRTUAL_REGISTER_CPU_SIDE	0x1c40
-#define OUTBOUND_QUEUE_PORT_VIRTUAL_REGISTER_CPU_SIDE	0x1c44
-#define QUEUE_CONTROL_REGISTER_CPU_SIDE			0x1c50
-#define QUEUE_BASE_ADDRESS_REGISTER_CPU_SIDE		0x1c54
-#define INBOUND_FREE_HEAD_POINTER_REGISTER_CPU_SIDE	0x1c60
-#define INBOUND_FREE_TAIL_POINTER_REGISTER_CPU_SIDE	0x1c64
-#define INBOUND_POST_HEAD_POINTER_REGISTER_CPU_SIDE	0x1c68
-#define INBOUND_POST_TAIL_POINTER_REGISTER_CPU_SIDE	0x1c6c
-#define OUTBOUND_FREE_HEAD_POINTER_REGISTER_CPU_SIDE	0x1c70
-#define OUTBOUND_FREE_TAIL_POINTER_REGISTER_CPU_SIDE	0x1c74
-#define OUTBOUND_POST_HEAD_POINTER_REGISTER_CPU_SIDE	0x1c78
-#define OUTBOUND_POST_TAIL_POINTER_REGISTER_CPU_SIDE	0x1c7c
-
-/*
- *  Register encodings
- */
-#define GT_CPU_ENDIAN_SHF       12
-#define GT_CPU_ENDIAN_MSK       (MSK(1) << GT_CPU_ENDIAN_SHF)
-#define GT_CPU_ENDIAN_BIT       GT_CPU_ENDIAN_MSK
-#define GT_CPU_WR_SHF		16
-#define GT_CPU_WR_MSK		(MSK(1) << GT_CPU_WR_SHF)
-#define GT_CPU_WR_BIT		GT_CPU_WR_MSK
-#define GT_CPU_WR_DXDXDXDX	0
-#define GT_CPU_WR_DDDD		1
-
-
-#define GT_CFGADDR_CFGEN_SHF	31
-#define GT_CFGADDR_CFGEN_MSK	(MSK(1) << GT_CFGADDR_CFGEN_SHF)
-#define GT_CFGADDR_CFGEN_BIT	GT_CFGADDR_CFGEN_MSK
-
-#define GT_CFGADDR_BUSNUM_SHF	16
-#define GT_CFGADDR_BUSNUM_MSK	(MSK(8) << GT_CFGADDR_BUSNUM_SHF)
-
-#define GT_CFGADDR_DEVNUM_SHF	11
-#define GT_CFGADDR_DEVNUM_MSK	(MSK(5) << GT_CFGADDR_DEVNUM_SHF)
-
-#define GT_CFGADDR_FUNCNUM_SHF	8
-#define GT_CFGADDR_FUNCNUM_MSK	(MSK(3) << GT_CFGADDR_FUNCNUM_SHF)
-
-#define GT_CFGADDR_REGNUM_SHF	2
-#define GT_CFGADDR_REGNUM_MSK	(MSK(6) << GT_CFGADDR_REGNUM_SHF)
-
-
-#define GT_SDRAM_BM_ORDER_SHF	2
-#define GT_SDRAM_BM_ORDER_MSK	(MSK(1) << GT_SDRAM_BM_ORDER_SHF)
-#define GT_SDRAM_BM_ORDER_BIT	GT_SDRAM_BM_ORDER_MSK
-#define GT_SDRAM_BM_ORDER_SUB	1
-#define GT_SDRAM_BM_ORDER_LIN	0
-
-#define GT_SDRAM_BM_RSVD_ALL1	0xffb
-
-
-#define GT_SDRAM_ADDRDECODE_ADDR_SHF	0
-#define GT_SDRAM_ADDRDECODE_ADDR_MSK	(MSK(3) << GT_SDRAM_ADDRDECODE_ADDR_SHF)
-#define GT_SDRAM_ADDRDECODE_ADDR_0	0
-#define GT_SDRAM_ADDRDECODE_ADDR_1	1
-#define GT_SDRAM_ADDRDECODE_ADDR_2	2
-#define GT_SDRAM_ADDRDECODE_ADDR_3	3
-#define GT_SDRAM_ADDRDECODE_ADDR_4	4
-#define GT_SDRAM_ADDRDECODE_ADDR_5	5
-#define GT_SDRAM_ADDRDECODE_ADDR_6	6
-#define GT_SDRAM_ADDRDECODE_ADDR_7	7
-
-
-#define GT_SDRAM_B0_CASLAT_SHF		0
-#define GT_SDRAM_B0_CASLAT_MSK		(MSK(2) << GT_SDRAM_B0__SHF)
-#define GT_SDRAM_B0_CASLAT_2		1
-#define GT_SDRAM_B0_CASLAT_3		2
-
-#define GT_SDRAM_B0_FTDIS_SHF		2
-#define GT_SDRAM_B0_FTDIS_MSK		(MSK(1) << GT_SDRAM_B0_FTDIS_SHF)
-#define GT_SDRAM_B0_FTDIS_BIT		GT_SDRAM_B0_FTDIS_MSK
-
-#define GT_SDRAM_B0_SRASPRCHG_SHF	3
-#define GT_SDRAM_B0_SRASPRCHG_MSK	(MSK(1) << GT_SDRAM_B0_SRASPRCHG_SHF)
-#define GT_SDRAM_B0_SRASPRCHG_BIT	GT_SDRAM_B0_SRASPRCHG_MSK
-#define GT_SDRAM_B0_SRASPRCHG_2		0
-#define GT_SDRAM_B0_SRASPRCHG_3		1
-
-#define GT_SDRAM_B0_B0COMPAB_SHF	4
-#define GT_SDRAM_B0_B0COMPAB_MSK	(MSK(1) << GT_SDRAM_B0_B0COMPAB_SHF)
-#define GT_SDRAM_B0_B0COMPAB_BIT	GT_SDRAM_B0_B0COMPAB_MSK
-
-#define GT_SDRAM_B0_64BITINT_SHF	5
-#define GT_SDRAM_B0_64BITINT_MSK	(MSK(1) << GT_SDRAM_B0_64BITINT_SHF)
-#define GT_SDRAM_B0_64BITINT_BIT	GT_SDRAM_B0_64BITINT_MSK
-#define GT_SDRAM_B0_64BITINT_2		0
-#define GT_SDRAM_B0_64BITINT_4		1
-
-#define GT_SDRAM_B0_BW_SHF		6
-#define GT_SDRAM_B0_BW_MSK		(MSK(1) << GT_SDRAM_B0_BW_SHF)
-#define GT_SDRAM_B0_BW_BIT		GT_SDRAM_B0_BW_MSK
-#define GT_SDRAM_B0_BW_32		0
-#define GT_SDRAM_B0_BW_64		1
-
-#define GT_SDRAM_B0_BLODD_SHF		7
-#define GT_SDRAM_B0_BLODD_MSK		(MSK(1) << GT_SDRAM_B0_BLODD_SHF)
-#define GT_SDRAM_B0_BLODD_BIT		GT_SDRAM_B0_BLODD_MSK
-
-#define GT_SDRAM_B0_PAR_SHF		8
-#define GT_SDRAM_B0_PAR_MSK		(MSK(1) << GT_SDRAM_B0_PAR_SHF)
-#define GT_SDRAM_B0_PAR_BIT		GT_SDRAM_B0_PAR_MSK
-
-#define GT_SDRAM_B0_BYPASS_SHF		9
-#define GT_SDRAM_B0_BYPASS_MSK		(MSK(1) << GT_SDRAM_B0_BYPASS_SHF)
-#define GT_SDRAM_B0_BYPASS_BIT		GT_SDRAM_B0_BYPASS_MSK
-
-#define GT_SDRAM_B0_SRAS2SCAS_SHF	10
-#define GT_SDRAM_B0_SRAS2SCAS_MSK	(MSK(1) << GT_SDRAM_B0_SRAS2SCAS_SHF)
-#define GT_SDRAM_B0_SRAS2SCAS_BIT	GT_SDRAM_B0_SRAS2SCAS_MSK
-#define GT_SDRAM_B0_SRAS2SCAS_2		0
-#define GT_SDRAM_B0_SRAS2SCAS_3		1
-
-#define GT_SDRAM_B0_SIZE_SHF		11
-#define GT_SDRAM_B0_SIZE_MSK		(MSK(1) << GT_SDRAM_B0_SIZE_SHF)
-#define GT_SDRAM_B0_SIZE_BIT		GT_SDRAM_B0_SIZE_MSK
-#define GT_SDRAM_B0_SIZE_16M		0
-#define GT_SDRAM_B0_SIZE_64M		1
-
-#define GT_SDRAM_B0_EXTPAR_SHF		12
-#define GT_SDRAM_B0_EXTPAR_MSK		(MSK(1) << GT_SDRAM_B0_EXTPAR_SHF)
-#define GT_SDRAM_B0_EXTPAR_BIT		GT_SDRAM_B0_EXTPAR_MSK
-
-#define GT_SDRAM_B0_BLEN_SHF		13
-#define GT_SDRAM_B0_BLEN_MSK		(MSK(1) << GT_SDRAM_B0_BLEN_SHF)
-#define GT_SDRAM_B0_BLEN_BIT		GT_SDRAM_B0_BLEN_MSK
-#define GT_SDRAM_B0_BLEN_8		0
-#define GT_SDRAM_B0_BLEN_4		1
-
-
-#define GT_SDRAM_CFG_REFINT_SHF		0
-#define GT_SDRAM_CFG_REFINT_MSK		(MSK(14) << GT_SDRAM_CFG_REFINT_SHF)
-
-#define GT_SDRAM_CFG_NINTERLEAVE_SHF	14
-#define GT_SDRAM_CFG_NINTERLEAVE_MSK    (MSK(1) << GT_SDRAM_CFG_NINTERLEAVE_SHF)
-#define GT_SDRAM_CFG_NINTERLEAVE_BIT	GT_SDRAM_CFG_NINTERLEAVE_MSK
-
-#define GT_SDRAM_CFG_RMW_SHF		15
-#define GT_SDRAM_CFG_RMW_MSK		(MSK(1) << GT_SDRAM_CFG_RMW_SHF)
-#define GT_SDRAM_CFG_RMW_BIT		GT_SDRAM_CFG_RMW_MSK
-
-#define GT_SDRAM_CFG_NONSTAGREF_SHF	16
-#define GT_SDRAM_CFG_NONSTAGREF_MSK	(MSK(1) << GT_SDRAM_CFG_NONSTAGREF_SHF)
-#define GT_SDRAM_CFG_NONSTAGREF_BIT	GT_SDRAM_CFG_NONSTAGREF_MSK
-
-#define GT_SDRAM_CFG_DUPCNTL_SHF	19
-#define GT_SDRAM_CFG_DUPCNTL_MSK	(MSK(1) << GT_SDRAM_CFG_DUPCNTL_SHF)
-#define GT_SDRAM_CFG_DUPCNTL_BIT	GT_SDRAM_CFG_DUPCNTL_MSK
-
-#define GT_SDRAM_CFG_DUPBA_SHF		20
-#define GT_SDRAM_CFG_DUPBA_MSK		(MSK(1) << GT_SDRAM_CFG_DUPBA_SHF)
-#define GT_SDRAM_CFG_DUPBA_BIT		GT_SDRAM_CFG_DUPBA_MSK
-
-#define GT_SDRAM_CFG_DUPEOT0_SHF	21
-#define GT_SDRAM_CFG_DUPEOT0_MSK	(MSK(1) << GT_SDRAM_CFG_DUPEOT0_SHF)
-#define GT_SDRAM_CFG_DUPEOT0_BIT	GT_SDRAM_CFG_DUPEOT0_MSK
-
-#define GT_SDRAM_CFG_DUPEOT1_SHF	22
-#define GT_SDRAM_CFG_DUPEOT1_MSK	(MSK(1) << GT_SDRAM_CFG_DUPEOT1_SHF)
-#define GT_SDRAM_CFG_DUPEOT1_BIT	GT_SDRAM_CFG_DUPEOT1_MSK
-
-#define GT_SDRAM_OPMODE_OP_SHF		0
-#define GT_SDRAM_OPMODE_OP_MSK		(MSK(3) << GT_SDRAM_OPMODE_OP_SHF)
-#define GT_SDRAM_OPMODE_OP_NORMAL	0
-#define GT_SDRAM_OPMODE_OP_NOP		1
-#define GT_SDRAM_OPMODE_OP_PRCHG	2
-#define GT_SDRAM_OPMODE_OP_MODE		3
-#define GT_SDRAM_OPMODE_OP_CBR		4
-
-
-#define GT_PCI0_BARE_SWSCS3BOOTDIS_SHF	0
-#define GT_PCI0_BARE_SWSCS3BOOTDIS_MSK	(MSK(1) << GT_PCI0_BARE_SWSCS3BOOTDIS_SHF)
-#define GT_PCI0_BARE_SWSCS3BOOTDIS_BIT	GT_PCI0_BARE_SWSCS3BOOTDIS_MSK
-
-#define GT_PCI0_BARE_SWSCS32DIS_SHF	1
-#define GT_PCI0_BARE_SWSCS32DIS_MSK	(MSK(1) << GT_PCI0_BARE_SWSCS32DIS_SHF)
-#define GT_PCI0_BARE_SWSCS32DIS_BIT	GT_PCI0_BARE_SWSCS32DIS_MSK
-
-#define GT_PCI0_BARE_SWSCS10DIS_SHF	2
-#define GT_PCI0_BARE_SWSCS10DIS_MSK	(MSK(1) << GT_PCI0_BARE_SWSCS10DIS_SHF)
-#define GT_PCI0_BARE_SWSCS10DIS_BIT	GT_PCI0_BARE_SWSCS10DIS_MSK
-
-#define GT_PCI0_BARE_INTIODIS_SHF	3
-#define GT_PCI0_BARE_INTIODIS_MSK	(MSK(1) << GT_PCI0_BARE_INTIODIS_SHF)
-#define GT_PCI0_BARE_INTIODIS_BIT	GT_PCI0_BARE_INTIODIS_MSK
-
-#define GT_PCI0_BARE_INTMEMDIS_SHF	4
-#define GT_PCI0_BARE_INTMEMDIS_MSK	(MSK(1) << GT_PCI0_BARE_INTMEMDIS_SHF)
-#define GT_PCI0_BARE_INTMEMDIS_BIT	GT_PCI0_BARE_INTMEMDIS_MSK
-
-#define GT_PCI0_BARE_CS3BOOTDIS_SHF	5
-#define GT_PCI0_BARE_CS3BOOTDIS_MSK	(MSK(1) << GT_PCI0_BARE_CS3BOOTDIS_SHF)
-#define GT_PCI0_BARE_CS3BOOTDIS_BIT	GT_PCI0_BARE_CS3BOOTDIS_MSK
-
-#define GT_PCI0_BARE_CS20DIS_SHF	6
-#define GT_PCI0_BARE_CS20DIS_MSK	(MSK(1) << GT_PCI0_BARE_CS20DIS_SHF)
-#define GT_PCI0_BARE_CS20DIS_BIT	GT_PCI0_BARE_CS20DIS_MSK
-
-#define GT_PCI0_BARE_SCS32DIS_SHF	7
-#define GT_PCI0_BARE_SCS32DIS_MSK	(MSK(1) << GT_PCI0_BARE_SCS32DIS_SHF)
-#define GT_PCI0_BARE_SCS32DIS_BIT	GT_PCI0_BARE_SCS32DIS_MSK
-
-#define GT_PCI0_BARE_SCS10DIS_SHF	8
-#define GT_PCI0_BARE_SCS10DIS_MSK	(MSK(1) << GT_PCI0_BARE_SCS10DIS_SHF)
-#define GT_PCI0_BARE_SCS10DIS_BIT	GT_PCI0_BARE_SCS10DIS_MSK
-
-
-#define GT_INTRCAUSE_MASABORT0_SHF	18
-#define GT_INTRCAUSE_MASABORT0_MSK	(MSK(1) << GT_INTRCAUSE_MASABORT0_SHF)
-#define GT_INTRCAUSE_MASABORT0_BIT	GT_INTRCAUSE_MASABORT0_MSK
-
-#define GT_INTRCAUSE_TARABORT0_SHF	19
-#define GT_INTRCAUSE_TARABORT0_MSK	(MSK(1) << GT_INTRCAUSE_TARABORT0_SHF)
-#define GT_INTRCAUSE_TARABORT0_BIT	GT_INTRCAUSE_TARABORT0_MSK
-
-
-#define GT_PCI0_CFGADDR_REGNUM_SHF	2
-#define GT_PCI0_CFGADDR_REGNUM_MSK	(MSK(6) << GT_PCI0_CFGADDR_REGNUM_SHF)
-#define GT_PCI0_CFGADDR_FUNCTNUM_SHF	8
-#define GT_PCI0_CFGADDR_FUNCTNUM_MSK    (MSK(3) << GT_PCI0_CFGADDR_FUNCTNUM_SHF)
-#define GT_PCI0_CFGADDR_DEVNUM_SHF	11
-#define GT_PCI0_CFGADDR_DEVNUM_MSK	(MSK(5) << GT_PCI0_CFGADDR_DEVNUM_SHF)
-#define GT_PCI0_CFGADDR_BUSNUM_SHF	16
-#define GT_PCI0_CFGADDR_BUSNUM_MSK	(MSK(8) << GT_PCI0_CFGADDR_BUSNUM_SHF)
-#define GT_PCI0_CFGADDR_CONFIGEN_SHF	31
-#define GT_PCI0_CFGADDR_CONFIGEN_MSK	(MSK(1) << GT_PCI0_CFGADDR_CONFIGEN_SHF)
-#define GT_PCI0_CFGADDR_CONFIGEN_BIT	GT_PCI0_CFGADDR_CONFIGEN_MSK
-
-#define GT_PCI0_CMD_MBYTESWAP_SHF       0
-#define GT_PCI0_CMD_MBYTESWAP_MSK       (MSK(1) << GT_PCI0_CMD_MBYTESWAP_SHF)
-#define GT_PCI0_CMD_MBYTESWAP_BIT       GT_PCI0_CMD_MBYTESWAP_MSK
-#define GT_PCI0_CMD_MWORDSWAP_SHF       10
-#define GT_PCI0_CMD_MWORDSWAP_MSK       (MSK(1) << GT_PCI0_CMD_MWORDSWAP_SHF)
-#define GT_PCI0_CMD_MWORDSWAP_BIT       GT_PCI0_CMD_MWORDSWAP_MSK
-#define GT_PCI0_CMD_SBYTESWAP_SHF       16
-#define GT_PCI0_CMD_SBYTESWAP_MSK       (MSK(1) << GT_PCI0_CMD_SBYTESWAP_SHF)
-#define GT_PCI0_CMD_SBYTESWAP_BIT       GT_PCI0_CMD_SBYTESWAP_MSK
-#define GT_PCI0_CMD_SWORDSWAP_SHF       11
-#define GT_PCI0_CMD_SWORDSWAP_MSK       (MSK(1) << GT_PCI0_CMD_SWORDSWAP_SHF)
-#define GT_PCI0_CMD_SWORDSWAP_BIT       GT_PCI0_CMD_SWORDSWAP_MSK
-
-/*
- *  Misc
- */
-#define GT_DEF_BASE		0x14000000
-
-#define GT_DEF_PCI0_IO_BASE	0x10000000
-#define GT_DEF_PCI0_IO_SIZE	0x02000000
-#define GT_DEF_PCI0_MEM0_BASE	0x12000000
-#define GT_DEF_PCI0_MEM0_SIZE	0x02000000
-
-#define GT_MAX_BANKSIZE		(256 * 1024 * 1024)   /* Max 256MB bank */
-#define GT_LATTIM_MIN    	6		      /* Minimum lat	*/
-
-
-/***********************************************************************
- *              BOARD-DEPENDENT SECTIONS                               *
- ***********************************************************************
- */
-
-/*
- * include asm/gt64120/<board>/gt64120_dep.h file
- */
-
-#include <linux/config.h>
-#include <linux/init.h>
-#include <linux/pci.h>
-
-#if defined(CONFIG_MOMENCO_OCELOT)
-#include <asm/gt64120/momenco_ocelot/gt64120_dep.h>
-#endif
-
-/*
- * The gt64120_dep.h file must define the following macros
- *
- *   GT_READ(ofs, data_pointer)
- *   GT_WRITE(ofs, data)           - read/write GT64120 registers in 32bit
- *
- *   TIMER 	- gt64120 timer irq, temporary solution until
- *		  full gt64120 cascade interrupt support is in place
- */
-
-/*
- * Board-dependent functions, which must be defined in
- * arch/mips/gt64120/<board>/pci.c file.
- *
- * This function is called by pcibios_fixup_bus(bus), which in turn is
- * invoked a bus is scanned.  You typically fixes IRQ numbers in this routine.
- */
-extern void __init gt64120_board_pcibios_fixup_bus(struct pci_bus *bus);
-
-#endif /* __ASM_GT64120_GT64120_H */
--- diff/include/asm-mips/gt64120/momenco_ocelot/gt64120_dep.h	2003-08-20 14:16:33.000000000 +0100
+++ source/include/asm-mips/gt64120/momenco_ocelot/gt64120_dep.h	1970-01-01 01:00:00.000000000 +0100
@@ -1,49 +0,0 @@
-/***********************************************************************
- * Copyright 2001 MontaVista Software Inc.
- * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net
- *
- * include/asm-mips/gt64120/momenco-ocelot/gt64120-dep.h
- *     Board-dependent definitions for GT-64120 chip.
- *
- * This program is free software; you can redistribute  it and/or modify it
- * under  the terms of  the GNU General  Public License as published by the
- * Free Software Foundation;  either version 2 of the  License, or (at your
- * option) any later version.
- ***********************************************************************
- */
-
-#ifndef _ASM_GT64120_MOMENCO_OCELOT_GT64120_DEP_H
-#define _ASM_GT64120_MOMENCO_OCELOT_GT64120_DEP_H
-
-#include <asm/addrspace.h>		/* for KSEG1ADDR() */
-#include <asm/byteorder.h>		/* for cpu_to_le32() */
-
-/*
- * PCI address allocation
- */
-#define GT_PCI_MEM_BASE    (0x22000000)
-#define GT_PCI_MEM_SIZE    GT_DEF_PCI0_MEM0_SIZE
-#define GT_PCI_IO_BASE     (0x20000000)
-#define GT_PCI_IO_SIZE     GT_DEF_PCI0_IO_SIZE
-
-extern unsigned long gt64120_base;
-
-#define GT64120_BASE       (gt64120_base)
-
-/*
- * Because of an error/peculiarity in the Galileo chip, we need to swap the
- * bytes when running bigendian.
- */
-
-#define GT_WRITE(ofs, data)  \
-        *(volatile u32 *)(GT64120_BASE+ofs) = cpu_to_le32(data)
-#define GT_READ(ofs, data)   \
-        *data = le32_to_cpu(*(volatile u32 *)(GT64120_BASE+ofs))
-
-
-/*
- * gt timer irq
- */
-#define	TIMER		6
-
-#endif  /* _ASM_GT64120_MOMENCO_OCELOT_GT64120_DEP_H */
--- diff/include/asm-mips/jmr3927/ds1742rtc.h	2003-07-08 09:55:19.000000000 +0100
+++ source/include/asm-mips/jmr3927/ds1742rtc.h	1970-01-01 01:00:00.000000000 +0100
@@ -1,67 +0,0 @@
-/*
- * ds1742rtc.h - register definitions for the Real-Time-Clock / CMOS RAM
- *
- *   Based on include/asm-mips/ds1643rtc.h.
- *
- * Copyright (C) 1999-2001 Toshiba Corporation
- * It was written to be part of the Linux operating system.
- */
-/* permission is hereby granted to copy, modify and redistribute this code
- * in terms of the GNU Library General Public License, Version 2 or later,
- * at your option.
- */
-#ifndef _DS1742RTC_H
-#define _DS1742RTC_H
-
-#include <linux/rtc.h>
-#include <asm/mc146818rtc.h>	/* bad name... */
-
-#define RTC_BRAM_SIZE		0x800
-#define RTC_OFFSET		0x7f8
-
-/**********************************************************************
- * register summary
- **********************************************************************/
-#define RTC_CONTROL		(RTC_OFFSET + 0)
-#define RTC_CENTURY		(RTC_OFFSET + 0)
-#define RTC_SECONDS		(RTC_OFFSET + 1)
-#define RTC_MINUTES		(RTC_OFFSET + 2)
-#define RTC_HOURS		(RTC_OFFSET + 3)
-#define RTC_DAY			(RTC_OFFSET + 4)
-#define RTC_DATE		(RTC_OFFSET + 5)
-#define RTC_MONTH		(RTC_OFFSET + 6)
-#define RTC_YEAR		(RTC_OFFSET + 7)
-
-#define RTC_CENTURY_MASK	0x3f
-#define RTC_SECONDS_MASK	0x7f
-#define RTC_DAY_MASK		0x07
-
-/*
- * Bits in the Control/Century register
- */
-#define RTC_WRITE		0x80
-#define RTC_READ		0x40
-
-/*
- * Bits in the Seconds register
- */
-#define RTC_STOP		0x80
-
-/*
- * Bits in the Day register
- */
-#define RTC_BATT_FLAG		0x80
-#define RTC_FREQ_TEST		0x40
-
-/*
- * Conversion between binary and BCD.
- */
-#ifndef BCD_TO_BIN
-#define BCD_TO_BIN(val) ((val)=((val)&15) + ((val)>>4)*10)
-#endif
-
-#ifndef BIN_TO_BCD
-#define BIN_TO_BCD(val) ((val)=(((val)/10)<<4) + (val)%10)
-#endif
-
-#endif /* _DS1742RTC_H */
--- diff/include/asm-mips/jmr3927/pci.h	2003-07-08 09:55:19.000000000 +0100
+++ source/include/asm-mips/jmr3927/pci.h	1970-01-01 01:00:00.000000000 +0100
@@ -1,64 +0,0 @@
-/***********************************************************************
- *
- * Copyright 2001 MontaVista Software Inc.
- * Author: MontaVista Software, Inc.
- *              ahennessy@mvista.com
- *
- * include/asm-mips/jmr3927/pci.h
- * Based on include/asm-mips/ddb5xxx/pci.h
- *
- * This file essentially defines the interface between board
- * specific PCI code and MIPS common PCI code.  Should potentially put
- * into include/asm/pci.h file.
- *
- *  This program is free software; you can redistribute  it and/or modify it
- *  under  the terms of  the GNU General  Public License as published by the
- *  Free Software Foundation;  either version 2 of the  License, or (at your
- *  option) any later version.
- *
- *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
- *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
- *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
- *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
- *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
- *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- *  You should have received a copy of the  GNU General Public License along
- *  with this program; if not, write  to the Free Software Foundation, Inc.,
- *  675 Mass Ave, Cambridge, MA 02139, USA.
- *
- ***********************************************************************
- */
-
-#ifndef __ASM_TX3927_PCI_H
-#define __ASM_TX3927__PCI_H
-
-#include <linux/ioport.h>
-#include <linux/pci.h>
-
-/*
- * Each pci channel is a top-level PCI bus seem by CPU.  A machine  with
- * multiple PCI channels may have multiple PCI host controllers or a
- * single controller supporting multiple channels.
- */
-struct pci_channel {
-	struct pci_ops *pci_ops;
-	struct resource *io_resource;
-	struct resource *mem_resource;
-};
-
-/*
- * each board defines an array of pci_channels, that ends with all NULL entry
- */
-extern struct pci_channel mips_pci_channels[];
-
-/*
- * board supplied pci irq fixup routine
- */
-extern void pcibios_fixup_irqs(void);
-
-#endif  /* __ASM_TX3927_PCI_H */
--- diff/include/asm-mips/keyboard.h	2003-07-08 09:55:19.000000000 +0100
+++ source/include/asm-mips/keyboard.h	1970-01-01 01:00:00.000000000 +0100
@@ -1,96 +0,0 @@
-/*
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (C) 1994 - 1999 Ralf Baechle
- */
-#ifndef _ASM_KEYBOARD_H
-#define _ASM_KEYBOARD_H
-
-#ifdef __KERNEL__
-
-#include <linux/config.h>
-#include <linux/delay.h>
-#include <linux/ioport.h>
-#include <linux/kd.h>
-#include <linux/pm.h>
-
-#define DISABLE_KBD_DURING_INTERRUPTS 0
-
-#ifdef CONFIG_PC_KEYB
-
-extern int pckbd_setkeycode(unsigned int scancode, unsigned int keycode);
-extern int pckbd_getkeycode(unsigned int scancode);
-extern int pckbd_translate(unsigned char scancode, unsigned char *keycode,
-			   char raw_mode);
-extern char pckbd_unexpected_up(unsigned char keycode);
-extern void pckbd_leds(unsigned char leds);
-extern void pckbd_init_hw(void);
-extern int pckbd_pm_resume(struct pm_dev *, pm_request_t, void *);
-extern pm_callback pm_kbd_request_override;
-extern unsigned char pckbd_sysrq_xlate[128];
-extern void kbd_forward_char (int ch);
-
-#define kbd_setkeycode		pckbd_setkeycode
-#define kbd_getkeycode		pckbd_getkeycode
-#define kbd_translate		pckbd_translate
-#define kbd_unexpected_up	pckbd_unexpected_up
-#define kbd_leds		pckbd_leds
-#define kbd_init_hw		pckbd_init_hw
-#define kbd_sysrq_xlate         pckbd_sysrq_xlate
-
-#define SYSRQ_KEY 0x54
-
-/* Some stoneage hardware needs delays after some operations.  */
-#define kbd_pause() do { } while(0)
-
-struct kbd_ops {
-	/* Keyboard driver resource allocation  */
-	void (*kbd_request_region)(void);
-	int (*kbd_request_irq)(void (*handler)(int, void *, struct pt_regs *));
-
-	/* PSaux driver resource management  */
-	int (*aux_request_irq)(void (*handler)(int, void *, struct pt_regs *));
-	void (*aux_free_irq)(void);
-
-	/* Methods to access the keyboard processor's I/O registers  */
-	unsigned char (*kbd_read_input)(void);
-	void (*kbd_write_output)(unsigned char val);
-	void (*kbd_write_command)(unsigned char val);
-	unsigned char (*kbd_read_status)(void);
-};
-
-extern struct kbd_ops *kbd_ops;
-
-/* Do the actual calls via kbd_ops vector  */
-#define kbd_request_region() kbd_ops->kbd_request_region()
-#define kbd_request_irq(handler) kbd_ops->kbd_request_irq(handler)
-
-#define aux_request_irq(hand, dev_id) kbd_ops->aux_request_irq(hand)
-#define aux_free_irq(dev_id) kbd_ops->aux_free_irq()
-
-#define kbd_read_input() kbd_ops->kbd_read_input()
-#define kbd_write_output(val) kbd_ops->kbd_write_output(val)
-#define kbd_write_command(val) kbd_ops->kbd_write_command(val)
-#define kbd_read_status() kbd_ops->kbd_read_status()
-
-#else
-
-extern int kbd_setkeycode(unsigned int scancode, unsigned int keycode);
-extern int kbd_getkeycode(unsigned int scancode);
-extern int kbd_translate(unsigned char scancode, unsigned char *keycode,
-	char raw_mode);
-extern char kbd_unexpected_up(unsigned char keycode);
-extern void kbd_leds(unsigned char leds);
-extern void kbd_init_hw(void);
-extern unsigned char *kbd_sysrq_xlate;
-
-extern unsigned char kbd_sysrq_key;
-#define SYSRQ_KEY kbd_sysrq_key
-
-#endif
-
-#endif /* __KERNEL */
-
-#endif /* _ASM_KEYBOARD_H */
--- diff/include/asm-mips/pb1000.h	2003-07-08 09:55:19.000000000 +0100
+++ source/include/asm-mips/pb1000.h	1970-01-01 01:00:00.000000000 +0100
@@ -1,172 +0,0 @@
-/*
- * Alchemy Semi PB1000 Referrence Board
- *
- * Copyright 2001 MontaVista Software Inc.
- * Author: MontaVista Software, Inc.
- *         	ppopov@mvista.com or source@mvista.com
- *
- * ########################################################################
- *
- *  This program is free software; you can distribute it and/or modify it
- *  under the terms of the GNU General Public License (Version 2) as
- *  published by the Free Software Foundation.
- *
- *  This program is distributed in the hope it will be useful, but WITHOUT
- *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- *  for more details.
- *
- *  You should have received a copy of the GNU General Public License along
- *  with this program; if not, write to the Free Software Foundation, Inc.,
- *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
- *
- * ########################################################################
- *
- *
- */
-#ifndef __ASM_PB1000_H
-#define __ASM_PB1000_H
-
-/* PCMCIA PB1000 specific defines */
-#define PCMCIA_MAX_SOCK 1
-#define PCMCIA_NUM_SOCKS (PCMCIA_MAX_SOCK+1)
-
-#define PB1000_PCR     0xBE000000
-  #define PCR_SLOT_0_VPP0  (1<<0)
-  #define PCR_SLOT_0_VPP1  (1<<1)
-  #define PCR_SLOT_0_VCC0  (1<<2)
-  #define PCR_SLOT_0_VCC1  (1<<3)
-  #define PCR_SLOT_0_RST   (1<<4)
-
-  #define PCR_SLOT_1_VPP0  (1<<8)
-  #define PCR_SLOT_1_VPP1  (1<<9)
-  #define PCR_SLOT_1_VCC0  (1<<10)
-  #define PCR_SLOT_1_VCC1  (1<<11)
-  #define PCR_SLOT_1_RST   (1<<12)
-
-#define PB1000_MDR     0xBE000004
-  #define MDR_PI        (1<<5)  /* pcmcia int latch  */
-  #define MDR_EPI      (1<<14)  /* enable pcmcia int */
-  #define MDR_CPI      (1<<15)  /* clear pcmcia int  */
-
-#define PB1000_ACR1    0xBE000008
-  #define ACR1_SLOT_0_CD1    (1<<0)  /* card detect 1     */
-  #define ACR1_SLOT_0_CD2    (1<<1)  /* card detect 2     */
-  #define ACR1_SLOT_0_READY  (1<<2)  /* ready             */
-  #define ACR1_SLOT_0_STATUS (1<<3)  /* status change     */
-  #define ACR1_SLOT_0_VS1    (1<<4)  /* voltage sense 1   */
-  #define ACR1_SLOT_0_VS2    (1<<5)  /* voltage sense 2   */
-  #define ACR1_SLOT_0_INPACK (1<<6)  /* inpack pin status */
-  #define ACR1_SLOT_1_CD1    (1<<8)  /* card detect 1     */
-  #define ACR1_SLOT_1_CD2    (1<<9)  /* card detect 2     */
-  #define ACR1_SLOT_1_READY  (1<<10) /* ready             */
-  #define ACR1_SLOT_1_STATUS (1<<11) /* status change     */
-  #define ACR1_SLOT_1_VS1    (1<<12) /* voltage sense 1   */
-  #define ACR1_SLOT_1_VS2    (1<<13) /* voltage sense 2   */
-  #define ACR1_SLOT_1_INPACK (1<<14) /* inpack pin status */
-
-#define CPLD_AUX0      0xBE00000C
-#define CPLD_AUX1      0xBE000010
-#define CPLD_AUX2      0xBE000014
-
-/* Voltage levels */
-
-/* VPPEN1 - VPPEN0 */
-#define VPP_GND ((0<<1) | (0<<0))
-#define VPP_5V  ((1<<1) | (0<<0))
-#define VPP_3V  ((0<<1) | (1<<0))
-#define VPP_12V ((0<<1) | (1<<0))
-#define VPP_HIZ ((1<<1) | (1<<0))
-
-/* VCCEN1 - VCCEN0 */
-#define VCC_3V  ((0<<1) | (1<<0))
-#define VCC_5V  ((1<<1) | (0<<0))
-#define VCC_HIZ ((0<<1) | (0<<0))
-
-/* VPP/VCC */
-#define SET_VCC_VPP(VCC, VPP, SLOT)\
-	((((VCC)<<2) | ((VPP)<<0)) << ((SLOT)*8))
-
-
-/* PCI PB1000 specific defines */
-/* The reason these defines are here instead of au1000.h is because
- * the Au1000 does not have a PCI bus controller so the PCI implementation
- * on the some of the older Pb1000 boards was very board specific.
- */
-#define PCI_CONFIG_BASE   0xBA020000 /* the only external slot */
-
-#define SDRAM_DEVID       0xBA010000
-#define SDRAM_CMD         0xBA010004
-#define SDRAM_CLASS       0xBA010008
-#define SDRAM_MISC        0xBA01000C
-#define SDRAM_MBAR        0xBA010010
-
-#define PCI_IO_DATA_PORT  0xBA800000
-
-#define PCI_IO_ADDR       0xBE00001C
-#define PCI_INT_ACK       0xBBC00000
-#define PCI_IO_READ       0xBBC00020
-#define PCI_IO_WRITE      0xBBC00030
-
-#define PCI_BRIDGE_CONFIG 0xBE000018
-
-#define PCI_IO_START      0x10000000
-#define PCI_IO_END        0x1000ffff
-#define PCI_MEM_START     0x18000000
-#define PCI_MEM_END       0x18ffffff
-
-#define PCI_FIRST_DEVFN   0
-#define PCI_LAST_DEVFN    1
-
-static inline u8 au_pci_io_readb(u32 addr)
-{
-	writel(addr, PCI_IO_ADDR);
-	writel((readl(PCI_BRIDGE_CONFIG) & 0xffffcfff) | (1<<12), PCI_BRIDGE_CONFIG);
-	return (readl(PCI_IO_DATA_PORT) & 0xff);
-}
-
-static inline u16 au_pci_io_readw(u32 addr)
-{
-	writel(addr, PCI_IO_ADDR);
-	writel((readl(PCI_BRIDGE_CONFIG) & 0xffffcfff) | (1<<13), PCI_BRIDGE_CONFIG);
-	return (readl(PCI_IO_DATA_PORT) & 0xffff);
-}
-
-static inline u32 au_pci_io_readl(u32 addr)
-{
-	writel(addr, PCI_IO_ADDR);
-	writel((readl(PCI_BRIDGE_CONFIG) & 0xffffcfff), PCI_BRIDGE_CONFIG);
-	return readl(PCI_IO_DATA_PORT);
-}
-
-static inline void au_pci_io_writeb(u8 val, u32 addr)
-{
-	writel(addr, PCI_IO_ADDR);
-	writel((readl(PCI_BRIDGE_CONFIG) & 0xffffcfff) | (1<<12), PCI_BRIDGE_CONFIG);
-	writel(val, PCI_IO_DATA_PORT);
-}
-
-static inline void au_pci_io_writew(u16 val, u32 addr)
-{
-	writel(addr, PCI_IO_ADDR);
-	writel((readl(PCI_BRIDGE_CONFIG) & 0xffffcfff) | (1<<13), PCI_BRIDGE_CONFIG);
-	writel(val, PCI_IO_DATA_PORT);
-}
-
-static inline void au_pci_io_writel(u32 val, u32 addr)
-{
-	writel(addr, PCI_IO_ADDR);
-	writel(readl(PCI_BRIDGE_CONFIG) & 0xffffcfff, PCI_BRIDGE_CONFIG);
-	writel(val, PCI_IO_DATA_PORT);
-}
-
-static inline void set_sdram_extbyte(void)
-{
-	writel(readl(PCI_BRIDGE_CONFIG) & 0xffffff00, PCI_BRIDGE_CONFIG);
-}
-
-static inline void set_slot_extbyte(void)
-{
-	writel((readl(PCI_BRIDGE_CONFIG) & 0xffffbf00) | 0x18, PCI_BRIDGE_CONFIG);
-}
-#endif /* __ASM_PB1000_H */
--- diff/include/asm-mips/pb1100.h	2003-07-08 09:55:19.000000000 +0100
+++ source/include/asm-mips/pb1100.h	1970-01-01 01:00:00.000000000 +0100
@@ -1,85 +0,0 @@
-/*
- * Alchemy Semi PB1100 Referrence Board
- *
- * Copyright 2001 MontaVista Software Inc.
- * Author: MontaVista Software, Inc.
- *         	ppopov@mvista.com or source@mvista.com
- *
- * ########################################################################
- *
- *  This program is free software; you can distribute it and/or modify it
- *  under the terms of the GNU General Public License (Version 2) as
- *  published by the Free Software Foundation.
- *
- *  This program is distributed in the hope it will be useful, but WITHOUT
- *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- *  for more details.
- *
- *  You should have received a copy of the GNU General Public License along
- *  with this program; if not, write to the Free Software Foundation, Inc.,
- *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
- *
- * ########################################################################
- *
- *
- */
-#ifndef __ASM_PB1100_H
-#define __ASM_PB1100_H
-
-#define PB1100_IDENT          0xAE000000
-#define BOARD_STATUS_REG      0xAE000004
-  #define PB1100_ROM_SEL         (1<<15)
-  #define PB1100_ROM_SIZ         (1<<14)
-  #define PB1100_SWAP_BOOT       (1<<13)
-  #define PB1100_FLASH_WP        (1<<12)
-  #define PB1100_ROM_H_STS       (1<<11)
-  #define PB1100_ROM_L_STS       (1<<10)
-  #define PB1100_FLASH_H_STS      (1<<9)
-  #define PB1100_FLASH_L_STS      (1<<8)
-  #define PB1100_SRAM_SIZ         (1<<7)
-  #define PB1100_TSC_BUSY         (1<<6)
-  #define PB1100_PCMCIA_VS_MASK   (3<<4)
-  #define PB1100_RS232_CD         (1<<3)
-  #define PB1100_RS232_CTS        (1<<2)
-  #define PB1100_RS232_DSR        (1<<1)
-  #define PB1100_RS232_RI         (1<<0)
-
-#define PB1100_IRDA_RS232     0xAE00000C
-  #define PB1100_IRDA_FULL       (0<<14) /* full power */
-  #define PB1100_IRDA_SHUTDOWN   (1<<14)
-  #define PB1100_IRDA_TT         (2<<14) /* 2/3 power */
-  #define PB1100_IRDA_OT         (3<<14) /* 1/3 power */
-  #define PB1100_IRDA_FIR        (1<<13)
-
-#define PCMCIA_BOARD_REG     0xAE000010
-  #define PB1100_SD_WP1_RO       (1<<15) /* read only */
-  #define PB1100_SD_WP0_RO       (1<<14) /* read only */
-  #define PB1100_SD_PWR1         (1<<11) /* applies power to SD1 */
-  #define PB1100_SD_PWR0         (1<<10) /* applies power to SD0 */
-  #define PB1100_SEL_SD_CONN1     (1<<9)
-  #define PB1100_SEL_SD_CONN0     (1<<8)
-  #define PC_DEASSERT_RST         (1<<7)
-  #define PC_DRV_EN               (1<<4)
-
-#define PB1100_G_CONTROL      0xAE000014 /* graphics control */
-
-#define PB1100_RST_VDDI       0xAE00001C
-  #define PB1100_SOFT_RESET      (1<<15) /* clear to reset the board */
-  #define PB1100_VDDI_MASK        (0x1F)
-
-#define PB1100_LEDS           0xAE000018
-
-/* 11:8 is 4 discreet LEDs. Clearing a bit illuminates the LED.
- * 7:0 is the LED Display's decimal points.
- */
-#define PB1100_HEX_LED        0xAE000018
-
-/* PCMCIA PB1100 specific defines */
-#define PCMCIA_MAX_SOCK 0
-#define PCMCIA_NUM_SOCKS (PCMCIA_MAX_SOCK+1)
-
-/* VPP/VCC */
-#define SET_VCC_VPP(VCC, VPP) (((VCC)<<2) | ((VPP)<<0))
-
-#endif /* __ASM_PB1100_H */
--- diff/include/asm-mips/pb1500.h	2003-07-08 09:55:19.000000000 +0100
+++ source/include/asm-mips/pb1500.h	1970-01-01 01:00:00.000000000 +0100
@@ -1,51 +0,0 @@
-/*
- * Alchemy Semi PB1500 Referrence Board
- *
- * Copyright 2001 MontaVista Software Inc.
- * Author: MontaVista Software, Inc.
- *         	ppopov@mvista.com or source@mvista.com
- *
- * ########################################################################
- *
- *  This program is free software; you can distribute it and/or modify it
- *  under the terms of the GNU General Public License (Version 2) as
- *  published by the Free Software Foundation.
- *
- *  This program is distributed in the hope it will be useful, but WITHOUT
- *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- *  for more details.
- *
- *  You should have received a copy of the GNU General Public License along
- *  with this program; if not, write to the Free Software Foundation, Inc.,
- *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
- *
- * ########################################################################
- *
- *
- */
-#ifndef __ASM_PB1500_H
-#define __ASM_PB1500_H
-
-
-#define IDENT_BOARD_REG           0xAE000000
-#define BOARD_STATUS_REG          0xAE000004
-#define PCI_BOARD_REG             0xAE000010
-#define PCMCIA_BOARD_REG          0xAE000010
-  #define PC_DEASSERT_RST               0x80
-  #define PC_DRV_EN                     0x10 
-#define PB1500_G_CONTROL          0xAE000014
-#define PB1500_RST_VDDI           0xAE00001C
-#define PB1500_LEDS               0xAE000018
-  
-#define PB1500_HEX_LED            0xAF000004
-#define PB1500_HEX_LED_BLANK      0xAF000008
-
-/* PCMCIA PB1500 specific defines */
-#define PCMCIA_MAX_SOCK 0
-#define PCMCIA_NUM_SOCKS (PCMCIA_MAX_SOCK+1)
-
-/* VPP/VCC */
-#define SET_VCC_VPP(VCC, VPP) (((VCC)<<2) | ((VPP)<<0))
-
-#endif /* __ASM_PB1500_H */
--- diff/include/asm-mips/semaphore-helper.h	2003-07-08 09:55:19.000000000 +0100
+++ source/include/asm-mips/semaphore-helper.h	1970-01-01 01:00:00.000000000 +0100
@@ -1,182 +0,0 @@
-/*
- * SMP- and interrupt-safe semaphores helper functions.
- *
- * Copyright (C) 1996 Linus Torvalds
- * Copyright (C) 1999 Andrea Arcangeli
- * Copyright (C) 1999, 2001, 2002 Ralf Baechle
- * Copyright (C) 1999, 2001 Silicon Graphics, Inc.
- * Copyright (C) 2000 MIPS Technologies, Inc.
- */
-#ifndef _ASM_SEMAPHORE_HELPER_H
-#define _ASM_SEMAPHORE_HELPER_H
-
-#include <linux/config.h>
-#include <linux/errno.h>
-
-#define sem_read(a) ((a)->counter)
-#define sem_inc(a) (((a)->counter)++)
-#define sem_dec(a) (((a)->counter)--)
-/*
- * These two _must_ execute atomically wrt each other.
- */
-static inline void wake_one_more(struct semaphore * sem)
-{
-	atomic_inc(&sem->waking);
-}
-
-#ifdef CONFIG_CPU_HAS_LLSC
-
-static inline int waking_non_zero(struct semaphore *sem)
-{
-	int ret, tmp;
-
-	__asm__ __volatile__(
-	"1:\tll\t%1, %2\t\t\t# waking_non_zero\n\t"
-	"blez\t%1, 2f\n\t"
-	"subu\t%0, %1, 1\n\t"
-	"sc\t%0, %2\n\t"
-	"beqz\t%0, 1b\n"
-	"2:"
-	: "=r" (ret), "=r" (tmp), "+m" (sem->waking)
-	: "0" (0));
-
-	return ret;
-}
-
-#else /* !CONFIG_CPU_HAS_LLSC */
-
-/*
- * It doesn't make sense, IMHO, to endlessly turn interrupts off and on again.
- * Do it once and that's it. ll/sc *has* it's advantages. HK
- */
-
-static inline int waking_non_zero(struct semaphore *sem)
-{
-	unsigned long flags;
-	int ret = 0;
-
-	local_irq_save(flags);
-	if (sem_read(&sem->waking) > 0) {
-		sem_dec(&sem->waking);
-		ret = 1;
-	}
-	local_irq_restore(flags);
-	return ret;
-}
-#endif /* !CONFIG_CPU_HAS_LLSC */
-
-#ifdef CONFIG_CPU_HAS_LLDSCD
-
-/*
- * waking_non_zero_interruptible:
- *	1	got the lock
- *	0	go to sleep
- *	-EINTR	interrupted
- *
- * We must undo the sem->count down_interruptible decrement
- * simultaneously and atomically with the sem->waking adjustment,
- * otherwise we can race with wake_one_more.
- *
- * This is accomplished by doing a 64-bit lld/scd on the 2 32-bit words.
- *
- * This is crazy.  Normally it's strictly forbidden to use 64-bit operations
- * in the 32-bit MIPS kernel.  In this case it's however ok because if an
- * interrupt has destroyed the upper half of registers sc will fail.
- * Note also that this will not work for MIPS32 CPUs!
- *
- * Pseudocode:
- *
- * If(sem->waking > 0) {
- *	Decrement(sem->waking)
- *	Return(SUCCESS)
- * } else If(signal_pending(tsk)) {
- *	Increment(sem->count)
- *	Return(-EINTR)
- * } else {
- *	Return(SLEEP)
- * }
- */
-
-static inline int
-waking_non_zero_interruptible(struct semaphore *sem, struct task_struct *tsk)
-{
-	long ret, tmp;
-
-	__asm__ __volatile__(
-	".set\tpush\t\t\t# waking_non_zero_interruptible\n\t"
-	".set\tmips3\n\t"
-	".set\tnoat\n"
-	"0:\tlld\t%1, %2\n\t"
-	"li\t%0, 0\n\t"
-	"sll\t$1, %1, 0\n\t"
-	"blez\t$1, 1f\n\t"
-	"daddiu\t%1, %1, -1\n\t"
-	"li\t%0, 1\n\t"
-	"b\t2f\n"
-	"1:\tbeqz\t%3, 2f\n\t"
-	"li\t%0, %4\n\t"
-	"dli\t$1, 0x0000000100000000\n\t"
-	"daddu\t%1, %1, $1\n"
-	"2:\tscd\t%1, %2\n\t"
-	"beqz\t%1, 0b\n\t"
-	".set\tpop"
-	: "=&r" (ret), "=&r" (tmp), "=m" (*sem)
-	: "r" (signal_pending(tsk)), "i" (-EINTR));
-
-	return ret;
-}
-
-/*
- * waking_non_zero_trylock is unused.  we do everything in
- * down_trylock and let non-ll/sc hosts bounce around.
- */
-
-static inline int waking_non_zero_trylock(struct semaphore *sem)
-{
-#if WAITQUEUE_DEBUG
-	CHECK_MAGIC(sem->__magic);
-#endif
-
-	return 0;
-}
-
-#else /* !CONFIG_CPU_HAS_LLDSCD */
-
-static inline int waking_non_zero_interruptible(struct semaphore *sem,
-						struct task_struct *tsk)
-{
-	int ret = 0;
-	unsigned long flags;
-
-	local_irq_save(flags);
-	if (sem_read(&sem->waking) > 0) {
-		sem_dec(&sem->waking);
-		ret = 1;
-	} else if (signal_pending(tsk)) {
-		sem_inc(&sem->count);
-		ret = -EINTR;
-	}
-	local_irq_restore(flags);
-	return ret;
-}
-
-static inline int waking_non_zero_trylock(struct semaphore *sem)
-{
-        int ret = 1;
-	unsigned long flags;
-
-	local_irq_save(flags);
-	if (sem_read(&sem->waking) <= 0)
-		sem_inc(&sem->count);
-	else {
-		sem_dec(&sem->waking);
-		ret = 0;
-	}
-	local_irq_restore(flags);
-
-	return ret;
-}
-
-#endif /* !CONFIG_CPU_HAS_LLDSCD */
-
-#endif /* _ASM_SEMAPHORE_HELPER_H */
--- diff/include/asm-mips/smplock.h	2003-07-08 09:55:19.000000000 +0100
+++ source/include/asm-mips/smplock.h	1970-01-01 01:00:00.000000000 +0100
@@ -1,67 +0,0 @@
-/*
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Default SMP lock implementation
- */
-#include <linux/config.h>
-#include <linux/interrupt.h>
-#include <linux/spinlock.h>
-
-extern spinlock_t kernel_flag;
-
-#ifdef CONFIG_SMP
-#define kernel_locked()		spin_is_locked(&kernel_flag)
-#else
-#ifdef CONFIG_PREEMPT
-#define kernel_locked()		preempt_count()
-#else
-#define kernel_locked()		1
-#endif
-#endif
-
-/*
- * Release global kernel lock and global interrupt lock
- */
-#define release_kernel_lock(task)		\
-do {						\
-	if (unlikely(task->lock_depth >= 0))	\
-		spin_unlock(&kernel_flag);	\
-} while (0)
-
-/*
- * Re-acquire the kernel lock
- */
-#define reacquire_kernel_lock(task)		\
-do {						\
-	if (unlikely(task->lock_depth >= 0))	\
-		spin_lock(&kernel_flag);	\
-} while (0)
-
-
-/*
- * Getting the big kernel lock.
- *
- * This cannot happen asynchronously,
- * so we only need to worry about other
- * CPU's.
- */
-static __inline__ void lock_kernel(void)
-{
-#ifdef CONFIG_PREEMPT
-	if (current->lock_depth == -1)
-		spin_lock(&kernel_flag);
-	++current->lock_depth;
-#else
-
-	if (!++current->lock_depth)
-		spin_lock(&kernel_flag);
-#endif
-}
-
-static __inline__ void unlock_kernel(void)
-{
-	if (--current->lock_depth < 0)
-		spin_unlock(&kernel_flag);
-}
--- diff/include/asm-sparc/cprefix.h	2002-10-16 04:28:33.000000000 +0100
+++ source/include/asm-sparc/cprefix.h	1970-01-01 01:00:00.000000000 +0100
@@ -1,25 +0,0 @@
-/* cprefix.h:  This file is included by assembly source which needs
- *             to know what the c-label prefixes are. The newer versions
- *	       of cpp that come with gcc predefine such things to help
- *	       us out. The reason this stuff is needed is to make
- *	       solaris compiles of the kernel work.
- *
- * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
- */
-#ifndef __SPARC_CPREFIX_H
-#define __SPARC_CPREFIX_H
-
-#if defined(__svr4__) || defined(__ELF__)
-#define C_LABEL_PREFIX
-#define C_LABEL_STR(name) #name
-#else
-#define C_LABEL_PREFIX _
-#define C_LABEL_STR(name) "_" #name
-#endif
-
-#define CONCAT(a, b) CONCAT2(a, b)
-#define CONCAT2(a, b) a##b
-
-#define C_LABEL(name) CONCAT(C_LABEL_PREFIX, name)
-
-#endif /* !(__SPARC_CPREFIX_H) */
--- diff/include/linux/dm-ioctl-v1.h	2003-09-30 15:46:20.000000000 +0100
+++ source/include/linux/dm-ioctl-v1.h	1970-01-01 01:00:00.000000000 +0100
@@ -1,149 +0,0 @@
-/*
- * Copyright (C) 2001 Sistina Software (UK) Limited.
- *
- * This file is released under the LGPL.
- */
-
-#ifndef _LINUX_DM_IOCTL_V1_H
-#define _LINUX_DM_IOCTL_V1_H
-
-#include <linux/types.h>
-
-#define DM_DIR "mapper"	/* Slashes not supported */
-#define DM_MAX_TYPE_NAME 16
-#define DM_NAME_LEN 128
-#define DM_UUID_LEN 129
-
-/*
- * Implements a traditional ioctl interface to the device mapper.
- */
-
-/*
- * All ioctl arguments consist of a single chunk of memory, with
- * this structure at the start.  If a uuid is specified any
- * lookup (eg. for a DM_INFO) will be done on that, *not* the
- * name.
- */
-struct dm_ioctl {
-	/*
-	 * The version number is made up of three parts:
-	 * major - no backward or forward compatibility,
-	 * minor - only backwards compatible,
-	 * patch - both backwards and forwards compatible.
-	 *
-	 * All clients of the ioctl interface should fill in the
-	 * version number of the interface that they were
-	 * compiled with.
-	 *
-	 * All recognised ioctl commands (ie. those that don't
-	 * return -ENOTTY) fill out this field, even if the
-	 * command failed.
-	 */
-	uint32_t version[3];	/* in/out */
-	uint32_t data_size;	/* total size of data passed in
-				 * including this struct */
-
-	uint32_t data_start;	/* offset to start of data
-				 * relative to start of this struct */
-
-	uint32_t target_count;	/* in/out */
-	uint32_t open_count;	/* out */
-	uint32_t flags;		/* in/out */
-
-	__kernel_old_dev_t dev;	/* in/out */
-
-	char name[DM_NAME_LEN];	/* device name */
-	char uuid[DM_UUID_LEN];	/* unique identifier for
-				 * the block device */
-};
-
-/*
- * Used to specify tables.  These structures appear after the
- * dm_ioctl.
- */
-struct dm_target_spec {
-	int32_t status;		/* used when reading from kernel only */
-	uint64_t sector_start;
-	uint32_t length;
-
-	/*
-	 * Offset in bytes (from the start of this struct) to
-	 * next target_spec.
-	 */
-	uint32_t next;
-
-	char target_type[DM_MAX_TYPE_NAME];
-
-	/*
-	 * Parameter string starts immediately after this object.
-	 * Be careful to add padding after string to ensure correct
-	 * alignment of subsequent dm_target_spec.
-	 */
-};
-
-/*
- * Used to retrieve the target dependencies.
- */
-struct dm_target_deps {
-	uint32_t count;
-
-	__kernel_old_dev_t dev[0];	/* out */
-};
-
-/*
- * If you change this make sure you make the corresponding change
- * to dm-ioctl.c:lookup_ioctl()
- */
-enum {
-	/* Top level cmds */
-	DM_VERSION_CMD = 0,
-	DM_REMOVE_ALL_CMD,
-
-	/* device level cmds */
-	DM_DEV_CREATE_CMD,
-	DM_DEV_REMOVE_CMD,
-	DM_DEV_RELOAD_CMD,
-	DM_DEV_RENAME_CMD,
-	DM_DEV_SUSPEND_CMD,
-	DM_DEV_DEPS_CMD,
-	DM_DEV_STATUS_CMD,
-
-	/* target level cmds */
-	DM_TARGET_STATUS_CMD,
-	DM_TARGET_WAIT_CMD
-};
-
-#define DM_IOCTL 0xfd
-
-#define DM_VERSION       _IOWR(DM_IOCTL, DM_VERSION_CMD, struct dm_ioctl)
-#define DM_REMOVE_ALL    _IOWR(DM_IOCTL, DM_REMOVE_ALL_CMD, struct dm_ioctl)
-
-#define DM_DEV_CREATE    _IOWR(DM_IOCTL, DM_DEV_CREATE_CMD, struct dm_ioctl)
-#define DM_DEV_REMOVE    _IOWR(DM_IOCTL, DM_DEV_REMOVE_CMD, struct dm_ioctl)
-#define DM_DEV_RELOAD    _IOWR(DM_IOCTL, DM_DEV_RELOAD_CMD, struct dm_ioctl)
-#define DM_DEV_SUSPEND   _IOWR(DM_IOCTL, DM_DEV_SUSPEND_CMD, struct dm_ioctl)
-#define DM_DEV_RENAME    _IOWR(DM_IOCTL, DM_DEV_RENAME_CMD, struct dm_ioctl)
-#define DM_DEV_DEPS      _IOWR(DM_IOCTL, DM_DEV_DEPS_CMD, struct dm_ioctl)
-#define DM_DEV_STATUS    _IOWR(DM_IOCTL, DM_DEV_STATUS_CMD, struct dm_ioctl)
-
-#define DM_TARGET_STATUS _IOWR(DM_IOCTL, DM_TARGET_STATUS_CMD, struct dm_ioctl)
-#define DM_TARGET_WAIT   _IOWR(DM_IOCTL, DM_TARGET_WAIT_CMD, struct dm_ioctl)
-
-#define DM_VERSION_MAJOR	1
-#define DM_VERSION_MINOR	0
-#define DM_VERSION_PATCHLEVEL	6
-#define DM_VERSION_EXTRA	"-ioctl (2002-10-15)"
-
-/* Status bits */
-#define DM_READONLY_FLAG	0x00000001
-#define DM_SUSPEND_FLAG		0x00000002
-#define DM_EXISTS_FLAG		0x00000004
-#define DM_PERSISTENT_DEV_FLAG	0x00000008
-
-/*
- * Flag passed into ioctl STATUS command to get table information
- * rather than current status.
- */
-#define DM_STATUS_TABLE_FLAG	0x00000010
-
-#endif				/* _LINUX_DM_IOCTL_H */
--- diff/include/linux/dm-ioctl-v4.h	2003-08-20 14:16:15.000000000 +0100
+++ source/include/linux/dm-ioctl-v4.h	1970-01-01 01:00:00.000000000 +0100
@@ -1,237 +0,0 @@
-/*
- * Copyright (C) 2001 - 2003 Sistina Software (UK) Limited.
- *
- * This file is released under the LGPL.
- */
-
-#ifndef _LINUX_DM_IOCTL_V4_H
-#define _LINUX_DM_IOCTL_V4_H
-
-#include <linux/types.h>
-
-#define DM_DIR "mapper"		/* Slashes not supported */
-#define DM_MAX_TYPE_NAME 16
-#define DM_NAME_LEN 128
-#define DM_UUID_LEN 129
-
-/*
- * A traditional ioctl interface for the device mapper.
- *
- * Each device can have two tables associated with it, an
- * 'active' table which is the one currently used by io passing
- * through the device, and an 'inactive' one which is a table
- * that is being prepared as a replacement for the 'active' one.
- *
- * DM_VERSION:
- * Just get the version information for the ioctl interface.
- *
- * DM_REMOVE_ALL:
- * Remove all dm devices, destroy all tables.  Only really used
- * for debug.
- *
- * DM_LIST_DEVICES:
- * Get a list of all the dm device names.
- *
- * DM_DEV_CREATE:
- * Create a new device, neither the 'active' or 'inactive' table
- * slots will be filled.  The device will be in suspended state
- * after creation, however any io to the device will get errored
- * since it will be out-of-bounds.
- *
- * DM_DEV_REMOVE:
- * Remove a device, destroy any tables.
- *
- * DM_DEV_RENAME:
- * Rename a device.
- *
- * DM_SUSPEND:
- * This performs both suspend and resume, depending which flag is
- * passed in.
- * Suspend: This command will not return until all pending io to
- * the device has completed.  Further io will be deferred until
- * the device is resumed.
- * Resume: It is no longer an error to issue this command on an
- * unsuspended device.  If a table is present in the 'inactive'
- * slot, it will be moved to the active slot, then the old table
- * from the active slot will be _destroyed_.  Finally the device
- * is resumed.
- *
- * DM_DEV_STATUS:
- * Retrieves the status for the table in the 'active' slot.
- *
- * DM_DEV_WAIT:
- * Wait for a significant event to occur to the device.  This
- * could either be caused by an event triggered by one of the
- * targets of the table in the 'active' slot, or a table change.
- *
- * DM_TABLE_LOAD:
- * Load a table into the 'inactive' slot for the device.  The
- * device does _not_ need to be suspended prior to this command.
- *
- * DM_TABLE_CLEAR:
- * Destroy any table in the 'inactive' slot (ie. abort).
- *
- * DM_TABLE_DEPS:
- * Return a set of device dependencies for the 'active' table.
- *
- * DM_TABLE_STATUS:
- * Return the targets status for the 'active' table.
- */
-
-/*
- * All ioctl arguments consist of a single chunk of memory, with
- * this structure at the start.  If a uuid is specified any
- * lookup (eg. for a DM_INFO) will be done on that, *not* the
- * name.
- */
-struct dm_ioctl {
-	/*
-	 * The version number is made up of three parts:
-	 * major - no backward or forward compatibility,
-	 * minor - only backwards compatible,
-	 * patch - both backwards and forwards compatible.
-	 *
-	 * All clients of the ioctl interface should fill in the
-	 * version number of the interface that they were
-	 * compiled with.
-	 *
-	 * All recognised ioctl commands (ie. those that don't
-	 * return -ENOTTY) fill out this field, even if the
-	 * command failed.
-	 */
-	uint32_t version[3];	/* in/out */
-	uint32_t data_size;	/* total size of data passed in
-				 * including this struct */
-
-	uint32_t data_start;	/* offset to start of data
-				 * relative to start of this struct */
-
-	uint32_t target_count;	/* in/out */
-	int32_t open_count;	/* out */
-	uint32_t flags;		/* in/out */
-	uint32_t event_nr;      	/* in/out */
-	uint32_t padding;
-
-	uint64_t dev;		/* in/out */
-
-	char name[DM_NAME_LEN];	/* device name */
-	char uuid[DM_UUID_LEN];	/* unique identifier for
-				 * the block device */
-};
-
-/*
- * Used to specify tables.  These structures appear after the
- * dm_ioctl.
- */
-struct dm_target_spec {
-	uint64_t sector_start;
-	uint64_t length;
-	int32_t status;		/* used when reading from kernel only */
-
-	/*
-	 * Offset in bytes (from the start of this struct) to
-	 * next target_spec.
-	 */
-	uint32_t next;
-
-	char target_type[DM_MAX_TYPE_NAME];
-
-	/*
-	 * Parameter string starts immediately after this object.
-	 * Be careful to add padding after string to ensure correct
-	 * alignment of subsequent dm_target_spec.
-	 */
-};
-
-/*
- * Used to retrieve the target dependencies.
- */
-struct dm_target_deps {
-	uint32_t count;	/* Array size */
-	uint32_t padding;	/* unused */
-	uint64_t dev[0];	/* out */
-};
-
-/*
- * Used to get a list of all dm devices.
- */
-struct dm_name_list {
-	uint64_t dev;
-	uint32_t next;		/* offset to the next record from
-				   the _start_ of this */
-	char name[0];
-};
-
-/*
- * If you change this make sure you make the corresponding change
- * to dm-ioctl.c:lookup_ioctl()
- */
-enum {
-	/* Top level cmds */
-	DM_VERSION_CMD = 0,
-	DM_REMOVE_ALL_CMD,
-	DM_LIST_DEVICES_CMD,
-
-	/* device level cmds */
-	DM_DEV_CREATE_CMD,
-	DM_DEV_REMOVE_CMD,
-	DM_DEV_RENAME_CMD,
-	DM_DEV_SUSPEND_CMD,
-	DM_DEV_STATUS_CMD,
-	DM_DEV_WAIT_CMD,
-
-	/* Table level cmds */
-	DM_TABLE_LOAD_CMD,
-	DM_TABLE_CLEAR_CMD,
-	DM_TABLE_DEPS_CMD,
-	DM_TABLE_STATUS_CMD,
-};
-
-#define DM_IOCTL 0xfd
-
-#define DM_VERSION       _IOWR(DM_IOCTL, DM_VERSION_CMD, struct dm_ioctl)
-#define DM_REMOVE_ALL    _IOWR(DM_IOCTL, DM_REMOVE_ALL_CMD, struct dm_ioctl)
-#define DM_LIST_DEVICES  _IOWR(DM_IOCTL, DM_LIST_DEVICES_CMD, struct dm_ioctl)
-
-#define DM_DEV_CREATE    _IOWR(DM_IOCTL, DM_DEV_CREATE_CMD, struct dm_ioctl)
-#define DM_DEV_REMOVE    _IOWR(DM_IOCTL, DM_DEV_REMOVE_CMD, struct dm_ioctl)
-#define DM_DEV_RENAME    _IOWR(DM_IOCTL, DM_DEV_RENAME_CMD, struct dm_ioctl)
-#define DM_DEV_SUSPEND   _IOWR(DM_IOCTL, DM_DEV_SUSPEND_CMD, struct dm_ioctl)
-#define DM_DEV_STATUS    _IOWR(DM_IOCTL, DM_DEV_STATUS_CMD, struct dm_ioctl)
-#define DM_DEV_WAIT      _IOWR(DM_IOCTL, DM_DEV_WAIT_CMD, struct dm_ioctl)
-
-#define DM_TABLE_LOAD    _IOWR(DM_IOCTL, DM_TABLE_LOAD_CMD, struct dm_ioctl)
-#define DM_TABLE_CLEAR   _IOWR(DM_IOCTL, DM_TABLE_CLEAR_CMD, struct dm_ioctl)
-#define DM_TABLE_DEPS    _IOWR(DM_IOCTL, DM_TABLE_DEPS_CMD, struct dm_ioctl)
-#define DM_TABLE_STATUS  _IOWR(DM_IOCTL, DM_TABLE_STATUS_CMD, struct dm_ioctl)
-
-#define DM_VERSION_MAJOR	4
-#define DM_VERSION_MINOR	0
-#define DM_VERSION_PATCHLEVEL	0
-#define DM_VERSION_EXTRA	"-ioctl (2003-06-04)"
-
-/* Status bits */
-#define DM_READONLY_FLAG	(1 << 0) /* In/Out */
-#define DM_SUSPEND_FLAG		(1 << 1) /* In/Out */
-#define DM_PERSISTENT_DEV_FLAG	(1 << 3) /* In */
-
-/*
- * Flag passed into ioctl STATUS command to get table information
- * rather than current status.
- */
-#define DM_STATUS_TABLE_FLAG	(1 << 4) /* In */
-
-/*
- * Flags that indicate whether a table is present in either of
- * the two table slots that a device has.
- */
-#define DM_ACTIVE_PRESENT_FLAG   (1 << 5) /* Out */
-#define DM_INACTIVE_PRESENT_FLAG (1 << 6) /* Out */
-
-/*
- * Indicates that the buffer passed in wasn't big enough for the
- * results.
- */
-#define DM_BUFFER_FULL_FLAG	(1 << 8) /* Out */
-
-#endif				/* _LINUX_DM_IOCTL_H */
--- diff/include/linux/hfs_fs.h	2003-10-09 09:47:34.000000000 +0100
+++ source/include/linux/hfs_fs.h	1970-01-01 01:00:00.000000000 +0100
@@ -1,348 +0,0 @@
-/* 
- * linux/include/linux/hfs_fs.h
- *
- * Copyright (C) 1995-1997  Paul H. Hargrove
- * This file may be distributed under the terms of the GNU General Public License.
- *
- * The source code distribution of the Columbia AppleTalk Package for
- * UNIX, version 6.0, (CAP) was used as a specification of the
- * location and format of files used by CAP's Aufs.  No code from CAP
- * appears in hfs_fs.  hfs_fs is not a work ``derived'' from CAP in
- * the sense of intellectual property law.
- *
- * The source code distributions of Netatalk, versions 1.3.3b2 and
- * 1.4b2, were used as a specification of the location and format of
- * files used by Netatalk's afpd.  No code from Netatalk appears in
- * hfs_fs.  hfs_fs is not a work ``derived'' from Netatalk in the
- * sense of intellectual property law.
- */
-
-#ifndef _LINUX_HFS_FS_H
-#define _LINUX_HFS_FS_H
-
-#include <linux/hfs_sysdep.h>
-
-/* magic numbers for Apple Double header files */
-#define HFS_DBL_MAGIC		0x00051607
-#define HFS_SNGL_MAGIC		0x00051600
-#define HFS_HDR_VERSION_1	0x00010000
-#define HFS_HDR_VERSION_2	0x00020000
-
-/* magic numbers for various internal structures */
-#define HFS_INO_MAGIC		0x4821
-#define HFS_SB_MAGIC		0x4822
-
-/* The space used for the AppleDouble or AppleSingle headers */
-#define HFS_DBL_HDR_LEN		1024
-
-/* The space used for the Netatalk header */
-#define HFS_NAT_HDR_LEN		1024  /* 589 for an exact match */
-
-/* Macros to extract CNID and file "type" from the Linux inode number */
-#define HFS_CNID(X)	((X) & 0x3FFFFFFF)
-#define HFS_ITYPE(X)	((X) & 0xC0000000)
-
-/* Macros to enumerate types */
-#define HFS_ITYPE_TO_INT(X)	((X) >> 30)
-#define HFS_INT_TO_ITYPE(X)	((X) << 30)
-
-/* generic ITYPEs */
-#define HFS_ITYPE_0	0x00000000
-#define HFS_ITYPE_1	0x40000000
-#define HFS_ITYPE_2	0x80000000
-#define HFS_ITYPE_3	0xC0000000
-#define HFS_ITYPE_NORM	HFS_ITYPE_0	/* "normal" directory or file */
-
-/* ITYPEs for CAP */
-#define HFS_CAP_NORM	HFS_ITYPE_0	/* data fork or normal directory */
-#define HFS_CAP_DATA	HFS_ITYPE_0	/* data fork of file */
-#define HFS_CAP_NDIR	HFS_ITYPE_0	/* normal directory */
-#define HFS_CAP_FNDR	HFS_ITYPE_1	/* finder info for file or dir */
-#define HFS_CAP_RSRC	HFS_ITYPE_2	/* resource fork of file */
-#define HFS_CAP_RDIR	HFS_ITYPE_2	/* .resource directory */
-#define HFS_CAP_FDIR	HFS_ITYPE_3	/* .finderinfo directory */
-
-/* ITYPEs for Apple Double */
-#define HFS_DBL_NORM	HFS_ITYPE_0	/* data fork or directory */
-#define HFS_DBL_DATA	HFS_ITYPE_0	/* data fork of file */
-#define HFS_DBL_DIR	HFS_ITYPE_0	/* directory */
-#define HFS_DBL_HDR	HFS_ITYPE_1	/* AD header of file or dir */
-
-/* ITYPEs for netatalk */
-#define HFS_NAT_NORM	HFS_ITYPE_0	/* data fork or directory */
-#define HFS_NAT_DATA	HFS_ITYPE_0	/* data fork of file */
-#define HFS_NAT_NDIR	HFS_ITYPE_0	/* normal directory */
-#define HFS_NAT_HDR	HFS_ITYPE_1	/* AD header of file or dir */
-#define HFS_NAT_HDIR	HFS_ITYPE_2	/* directory holding AD headers */
-
-/* ITYPEs for Apple Single */
-#define HFS_SGL_NORM	HFS_ITYPE_0	/* AppleSingle file or directory */
-#define HFS_SGL_SNGL	HFS_ITYPE_0	/* AppleSingle file */
-#define HFS_SGL_DIR	HFS_ITYPE_0	/* directory */
-#define HFS_SGL_DINF	HFS_ITYPE_1	/* %DirInfo for directory */
-
-/* IDs for elements of an AppleDouble or AppleSingle header */
-#define HFS_HDR_DATA	1   /* data fork */
-#define HFS_HDR_RSRC	2   /* resource fork */
-#define HFS_HDR_FNAME	3   /* full (31-character) name */
-#define HFS_HDR_COMNT	4   /* comment */
-#define HFS_HDR_BWICN	5   /* b/w icon */
-#define HFS_HDR_CICON	6   /* color icon info */
-#define HFS_HDR_OLDI	7   /* old file info */
-#define HFS_HDR_DATES	8   /* file dates info */
-#define HFS_HDR_FINFO	9   /* Finder info */
-#define HFS_HDR_MACI	10  /* Macintosh info */
-#define HFS_HDR_PRODOSI 11  /* ProDOS info */
-#define HFS_HDR_MSDOSI  12  /* MSDOS info */
-#define HFS_HDR_SNAME   13  /* short name */
-#define HFS_HDR_AFPI    14  /* AFP file info */
-#define HFS_HDR_DID     15  /* directory id */
-#define HFS_HDR_MAX	16
-
-/*
- * There are three time systems.  All three are based on seconds since
- * a particular time/date.
- *	Unix:	unsigned lil-endian since 00:00 GMT, Jan. 1, 1970
- *	mac:	unsigned big-endian since 00:00 GMT, Jan. 1, 1904
- *	header:	  SIGNED big-endian since 00:00 GMT, Jan. 1, 2000
- *
- */
-#define hfs_h_to_mtime(ARG)	htonl((hfs_s32)ntohl(ARG)+3029529600U)
-#define hfs_m_to_htime(ARG)	((hfs_s32)htonl(ntohl(ARG)-3029529600U))
-#define hfs_h_to_utime(ARG)	((hfs_s32)hfs_to_utc(ntohl(ARG)+946684800U))
-#define hfs_u_to_htime(ARG)	((hfs_s32)htonl(hfs_from_utc(ARG)-946684800U))
-#define hfs_u_to_mtime(ARG)	htonl(hfs_from_utc(ARG)+2082844800U)
-#define hfs_m_to_utime(ARG)	(hfs_to_utc(ntohl(ARG)-2082844800U))
-
-/*======== Data structures kept in memory ========*/
-
-/*
- * A descriptor for a single entry within the header of an
- * AppleDouble or AppleSingle header file.
- * An array of these make up a table of contents for the file.
- */
-struct hfs_hdr_descr {
-	hfs_u32	id;	/* The Apple assigned ID for the entry type */
-	hfs_u32	offset;	/* The offset to reach the entry */
-	hfs_u32	length;	/* The length of the entry */
-};
-
-/*
- * The info needed to reconstruct a given header layout
- */
-struct hfs_hdr_layout {
-	hfs_u32		magic;			/* AppleSingle or AppleDouble */
-	hfs_u32		version;		/* 0x00010000 or 0x00020000 */
-	hfs_u16		entries;		/* How many entries used */
-	struct hfs_hdr_descr	
-			descr[HFS_HDR_MAX];	/* Descriptors */
-	struct hfs_hdr_descr	
-			*order[HFS_HDR_MAX];	/* 'descr' ordered by offset */
-};
-
-/* header layout for netatalk's v1 appledouble file format */
-struct hfs_nat_hdr {
-	hfs_lword_t	magic;
-	hfs_lword_t	version;
-	hfs_byte_t	homefs[16];
-	hfs_word_t	entries;
-	hfs_byte_t	descrs[12*5];
-	hfs_byte_t	real_name[255];	/* id=3 */
-	hfs_byte_t	comment[200];	/* id=4 XXX: not yet implemented */
-	hfs_byte_t	old_info[16];	/* id=7 */
-	hfs_u8		finderinfo[32]; /* id=9 */
-};
-
-/* 
- * Default header layout for Netatalk and AppleDouble
- */
-struct hfs_dbl_hdr {
-	hfs_lword_t	magic;
-	hfs_lword_t	version;
-	hfs_byte_t	filler[16];
-	hfs_word_t	entries;
-	hfs_byte_t	descrs[12*HFS_HDR_MAX];
-	hfs_byte_t	real_name[255];	/* id=3 */
-	hfs_byte_t	comment[200];	/* id=4 XXX: not yet implemented */
-	hfs_u32		create_time;	/* \	          */
-	hfs_u32		modify_time;	/*  | id=8 (or 7) */
-	hfs_u32		backup_time;	/*  |	          */
-	hfs_u32         access_time;    /* /  (attributes with id=7) */
-	hfs_u8		finderinfo[32]; /* id=9 */
-	hfs_u32		fileinfo;	/* id=10 */
-        hfs_u32         cnid;           /* id=15 */
-	hfs_u8          short_name[12]; /* id=13 */
-	hfs_u8          prodosi[8];     /* id=11 */
-};
-
-
-/* finder metadata for CAP */
-struct hfs_cap_info {
-	hfs_byte_t	fi_fndr[32];	/* Finder's info */
-	hfs_word_t	fi_attr;	/* AFP attributes (f=file/d=dir) */
-#define HFS_AFP_INV             0x001   /* Invisible bit (f/d) */
-#define HFS_AFP_EXPFOLDER       0x002   /* exported folder (d) */
-#define HFS_AFP_MULTI           0x002   /* Multiuser bit (f) */
-#define HFS_AFP_SYS             0x004   /* System bit (f/d) */
-#define HFS_AFP_DOPEN           0x008   /* data fork already open (f) */
-#define HFS_AFP_MOUNTED         0x008   /* mounted folder (d) */
-#define HFS_AFP_ROPEN           0x010   /* resource fork already open (f) */
-#define HFS_AFP_INEXPFOLDER     0x010   /* folder in shared area (d) */
-#define HFS_AFP_WRI		0x020	/* Write inhibit bit (readonly) (f) */
-#define HFS_AFP_BACKUP          0x040   /* backup needed bit (f/d)  */
-#define HFS_AFP_RNI		0x080	/* Rename inhibit bit (f/d) */
-#define HFS_AFP_DEI		0x100	/* Delete inhibit bit (f/d) */
-#define HFS_AFP_NOCOPY          0x400   /* Copy protect bit (f) */
-#define HFS_AFP_RDONLY	(	HFS_AFP_WRI|HFS_AFP_RNI|HFS_AFP_DEI)
-	hfs_byte_t	fi_magic1;	/* Magic number: */
-#define HFS_CAP_MAGIC1		0xFF
-	hfs_byte_t	fi_version;	/* Version of this structure: */
-#define HFS_CAP_VERSION		0x10
-	hfs_byte_t	fi_magic;	/* Another magic number: */
-#define HFS_CAP_MAGIC		0xDA
-	hfs_byte_t	fi_bitmap;	/* Bitmap of which names are valid: */
-#define HFS_CAP_SHORTNAME	0x01
-#define HFS_CAP_LONGNAME	0x02
-	hfs_byte_t	fi_shortfilename[12+1];	/* "short name" (unused) */
-	hfs_byte_t	fi_macfilename[32+1];	/* Original (Macintosh) name */
-	hfs_byte_t	fi_comln;	/* Length of comment (always 0) */
-	hfs_byte_t	fi_comnt[200];	/* Finder comment (unused) */
-	/* optional: 	used by aufs only if compiled with USE_MAC_DATES */
-	hfs_byte_t	fi_datemagic;	/* Magic number for dates extension: */
-#define HFS_CAP_DMAGIC		0xDA
-	hfs_byte_t	fi_datevalid;	/* Bitmap of which dates are valid: */
-#define HFS_CAP_MDATE		0x01
-#define HFS_CAP_CDATE		0x02
-	hfs_lword_t	fi_ctime;	/* Creation date (in AFP format) */
-	hfs_lword_t	fi_mtime;	/* Modify date (in AFP format) */
-	hfs_lword_t	fi_utime;	/* Un*x time of last mtime change */
-	hfs_byte_t	pad;
-};
-
-#ifdef __KERNEL__
-
-typedef ssize_t hfs_rwret_t;
-typedef size_t hfs_rwarg_t;
-
-#include <asm/uaccess.h>
-
-/* Some forward declarations */
-struct hfs_fork;
-struct hfs_cat_key;
-struct hfs_cat_entry;
-extern struct hfs_cat_entry *hfs_cat_get(struct hfs_mdb *,
-					 const struct hfs_cat_key *);
-
-/* dir.c */
-extern int hfs_create(struct inode *, struct dentry *, int, struct nameidata *);
-extern int hfs_mkdir(struct inode *, struct dentry *, int);
-extern int hfs_unlink(struct inode *, struct dentry *);
-extern int hfs_rmdir(struct inode *, struct dentry *);
-extern int hfs_rename(struct inode *, struct dentry *,
-		      struct inode *, struct dentry *);
-
-/* dir_cap.c */
-extern const struct hfs_name hfs_cap_reserved1[];
-extern const struct hfs_name hfs_cap_reserved2[];
-extern struct inode_operations hfs_cap_ndir_inode_operations;
-extern struct inode_operations hfs_cap_fdir_inode_operations;
-extern struct inode_operations hfs_cap_rdir_inode_operations;
-extern struct file_operations hfs_cap_dir_operations;
-extern void hfs_cap_drop_dentry(struct dentry *, const ino_t);
-
-/* dir_dbl.c */
-extern const struct hfs_name hfs_dbl_reserved1[];
-extern const struct hfs_name hfs_dbl_reserved2[];
-extern struct inode_operations hfs_dbl_dir_inode_operations;
-extern struct file_operations hfs_dbl_dir_operations;
-extern void hfs_dbl_drop_dentry(struct dentry *, const ino_t);
-
-/* dir_nat.c */
-extern const struct hfs_name hfs_nat_reserved1[];
-extern const struct hfs_name hfs_nat_reserved2[];
-extern struct inode_operations hfs_nat_ndir_inode_operations;
-extern struct inode_operations hfs_nat_hdir_inode_operations;
-extern struct file_operations hfs_nat_dir_operations;
-extern void hfs_nat_drop_dentry(struct dentry *, const ino_t);
-
-/* file.c */
-extern hfs_s32 hfs_do_read(struct inode *, struct hfs_fork *, hfs_u32,
-			   char __user *, hfs_u32);
-extern hfs_s32 hfs_do_write(struct inode *, struct hfs_fork *, hfs_u32,
-			    const char __user *, hfs_u32);
-extern void hfs_file_fix_mode(struct hfs_cat_entry *entry);
-extern struct inode_operations hfs_file_inode_operations;
-extern struct file_operations hfs_file_operations;
-
-/* file_cap.c */
-extern struct inode_operations hfs_cap_info_inode_operations;
-extern struct file_operations hfs_cap_info_operations;
-
-/* file_hdr.c */
-extern struct inode_operations hfs_hdr_inode_operations;
-extern struct file_operations hfs_hdr_operations;
-extern const struct hfs_hdr_layout hfs_dbl_fil_hdr_layout;
-extern const struct hfs_hdr_layout hfs_dbl_dir_hdr_layout;
-extern const struct hfs_hdr_layout hfs_nat_hdr_layout;
-extern const struct hfs_hdr_layout hfs_nat2_hdr_layout;
-extern const struct hfs_hdr_layout hfs_sngl_hdr_layout;
-extern void hdr_truncate(struct inode *,size_t);
-
-/* inode.c */
-extern void hfs_put_inode(struct inode *);
-extern int hfs_notify_change(struct dentry *, struct iattr *);
-extern int hfs_notify_change_cap(struct dentry *, struct iattr *);
-extern int hfs_notify_change_hdr(struct dentry *, struct iattr *);
-extern struct inode *hfs_iget(struct hfs_cat_entry *, ino_t, struct dentry *);
-
-extern void hfs_cap_ifill(struct inode *, ino_t, const int);
-extern void hfs_dbl_ifill(struct inode *, ino_t, const int);
-extern void hfs_nat_ifill(struct inode *, ino_t, const int);
-extern void hfs_sngl_ifill(struct inode *, ino_t, const int);
-
-/* super.c */
-extern int hfs_fill_super(struct super_block *,void *,int);
-
-/* trans.c */
-extern void hfs_colon2mac(struct hfs_name *, const char *, int);
-extern void hfs_prcnt2mac(struct hfs_name *, const char *, int);
-extern void hfs_triv2mac(struct hfs_name *, const char *, int);
-extern void hfs_latin2mac(struct hfs_name *, const char *, int);
-extern int hfs_mac2cap(char *, const struct hfs_name *);
-extern int hfs_mac2nat(char *, const struct hfs_name *);
-extern int hfs_mac2latin(char *, const struct hfs_name *);
-extern int hfs_mac2seven(char *, const struct hfs_name *);
-extern int hfs_mac2eight(char *, const struct hfs_name *);
-extern int hfs_mac2alpha(char *, const struct hfs_name *);
-extern int hfs_mac2triv(char *, const struct hfs_name *);
-extern void hfs_tolower(unsigned char *, int);
-
-#include <linux/hfs_fs_i.h>
-#include <linux/hfs_fs_sb.h>
-
-static inline struct hfs_inode_info *HFS_I(struct inode *inode)
-{
-	return container_of(inode, struct hfs_inode_info, vfs_inode);
-}
-
-static inline struct hfs_sb_info *HFS_SB(struct super_block *sb)
-{
-	return sb->s_fs_info;
-}
-
-static inline void hfs_nameout(struct inode *dir, struct hfs_name *out,
-				   const char *in, int len) {
-	HFS_SB(dir->i_sb)->s_nameout(out, in, len);
-}
-
-static inline int hfs_namein(struct inode *dir, char *out,
-				 const struct hfs_name *in) {
-	int len = HFS_SB(dir->i_sb)->s_namein(out, in);
-	if (HFS_SB(dir->i_sb)->s_lowercase) {
-		hfs_tolower(out, len);
-	}
-	return len;
-}
-
-#endif /* __KERNEL__ */
-#endif
--- diff/include/linux/hfs_fs_i.h	2002-10-16 04:29:06.000000000 +0100
+++ source/include/linux/hfs_fs_i.h	1970-01-01 01:00:00.000000000 +0100
@@ -1,45 +0,0 @@
-/* 
- * linux/include/linux/hfs_fs_i.h
- *
- * Copyright (C) 1995, 1996  Paul H. Hargrove
- * This file may be distributed under the terms of the GNU General Public License.
- *
- * This file defines the type (struct hfs_inode_info) and the two
- * subordinate types hfs_extent and hfs_file.
- */
-
-#ifndef _LINUX_HFS_FS_I_H
-#define _LINUX_HFS_FS_I_H
-
-/*
- * struct hfs_inode_info
- *
- * The HFS-specific part of a Linux (struct inode)
- */
-struct hfs_inode_info {
-	int				magic;     /* A magic number */
-
-	loff_t				mmu_private;
-	struct hfs_cat_entry		*entry;
-
-	/* For a regular or header file */
-	struct hfs_fork 		*fork;
-	int				convert;
-
-	/* For a directory */
-	ino_t				file_type;
-	char				dir_size;
-
-	/* For header files */
-	const struct hfs_hdr_layout	*default_layout;
-	struct hfs_hdr_layout		*layout;
-
-	/* to deal with localtime ugliness */
-	int                             tz_secondswest;
-
-        /* for dentry cleanup */
-        void (*d_drop_op)(struct dentry *, const ino_t);
-	struct inode vfs_inode;
-};
-
-#endif
--- diff/include/linux/hfs_fs_sb.h	2002-10-16 04:27:14.000000000 +0100
+++ source/include/linux/hfs_fs_sb.h	1970-01-01 01:00:00.000000000 +0100
@@ -1,53 +0,0 @@
-/* 
- * linux/include/linux/hfs_fs_sb.h
- *
- * Copyright (C) 1995-1997  Paul H. Hargrove
- * This file may be distributed under the terms of the GNU General Public License.
- *
- * This file defines the type (struct hfs_sb_info) which contains the
- * HFS-specific information in the in-core superblock.
- */
-
-#ifndef _LINUX_HFS_FS_SB_H
-#define _LINUX_HFS_FS_SB_H
-
-/* forward declaration: */
-struct hfs_name;
-
-typedef int (*hfs_namein_fn) (char *, const struct hfs_name *);
-typedef void (*hfs_nameout_fn) (struct hfs_name *, const char *, int);
-typedef void (*hfs_ifill_fn) (struct inode *, ino_t, const int);
-
-/*
- * struct hfs_sb_info
- *
- * The HFS-specific part of a Linux (struct super_block)
- */
-struct hfs_sb_info {
-	int			magic;		/* A magic number */
-	struct hfs_mdb		*s_mdb;		/* The HFS MDB */
-	int			s_quiet;	/* Silent failure when 
-						   changing owner or mode? */
-	int			s_lowercase;	/* Map names to lowercase? */
-	int			s_afpd;		/* AFPD compatible mode? */
-	int                     s_version;      /* version info */
-	hfs_namein_fn		s_namein;	/* The function used to
-						   map Mac filenames to
-						   Linux filenames */
-	hfs_nameout_fn		s_nameout;	/* The function used to
-						    map Linux filenames
-						    to Mac filenames */
-	hfs_ifill_fn		s_ifill;	/* The function used
-						   to fill in inode fields */
-	const struct hfs_name	*s_reserved1;	/* Reserved names */
-	const struct hfs_name	*s_reserved2;	/* Reserved names */
-	__u32			s_type;		/* Type for new files */
-	__u32			s_creator;	/* Creator for new files */
-	umode_t			s_umask;	/* The umask applied to the
-						   permissions on all files */
-	uid_t			s_uid;		/* The uid of all files */
-	gid_t			s_gid;		/* The gid of all files */
-	char			s_conv;		/* Type of text conversion */
-};
-
-#endif
--- diff/include/linux/hfs_sysdep.h	2003-08-20 14:16:14.000000000 +0100
+++ source/include/linux/hfs_sysdep.h	1970-01-01 01:00:00.000000000 +0100
@@ -1,238 +0,0 @@
-/*
- * linux/include/linux/hfs_sysdep.h
- *
- * Copyright (C) 1996-1997  Paul H. Hargrove
- * This file may be distributed under the terms of the GNU General Public License.
- *
- * This file contains constants, types and inline
- * functions for various system dependent things.
- *
- * "XXX" in a comment is a note to myself to consider changing something.
- *
- * In function preconditions the term "valid" applied to a pointer to
- * a structure means that the pointer is non-NULL and the structure it
- * points to has all fields initialized to consistent values.
- */
-
-#ifndef _HFS_SYSDEP_H
-#define _HFS_SYSDEP_H
-
-#include <linux/slab.h>
-#include <linux/types.h>
-#include <linux/fs.h>
-#include <linux/sched.h>
-#include <linux/buffer_head.h>
-
-#include <asm/byteorder.h>
-#include <asm/unaligned.h>
-
-extern struct timezone sys_tz;
-
-/* Typedefs for integer types by size and signedness */
-typedef __u8            hfs_u8;
-typedef __u16           hfs_u16;
-typedef __u32           hfs_u32;
-typedef __s8            hfs_s8;
-typedef __s16           hfs_s16;
-typedef __s32           hfs_s32;
-
-/* Typedefs for unaligned integer types */
-typedef unsigned char hfs_byte_t;
-typedef unsigned char hfs_word_t[2];
-typedef unsigned char hfs_lword_t[4];
-
-/* these funny looking things are GCC variable argument macros */
-#define hfs_warn(format, args...) printk(KERN_WARNING format , ## args)
-#define hfs_error(format, args...) printk(KERN_ERR format , ## args)
-
-
-#if defined(DEBUG_ALL) || defined(DEBUG_MEM)
-extern long int hfs_alloc;
-#endif
-
-static inline void *hfs_malloc(unsigned int size) {
-#if defined(DEBUG_ALL) || defined(DEBUG_MEM)
-	hfs_warn("%ld bytes allocation at %s:%u\n",
-		 (hfs_alloc += size), __FILE__, __LINE__);
-#endif
-	return kmalloc(size, GFP_KERNEL);
-}
-
-static inline void hfs_free(void *ptr, unsigned int size) {
-	kfree(ptr);
-#if defined(DEBUG_ALL) || defined(DEBUG_MEM)
-	hfs_warn("%ld bytes allocation at %s:%u\n",
-		  (hfs_alloc -= ptr ? size : 0), __FILE__, __LINE__);
-#endif
-}
-
-
-/* handle conversion between times. 
- *
- * NOTE: hfs+ doesn't need this. also, we don't use tz_dsttime as that's
- *       not a good thing to do. instead, we depend upon tz_minuteswest
- *       having the correct daylight savings correction. 
- */
-static inline hfs_u32 hfs_from_utc(hfs_s32 time)
-{
-	return time - sys_tz.tz_minuteswest*60; 
-}
-
-static inline hfs_s32 hfs_to_utc(hfs_u32 time)
-{
-	return time + sys_tz.tz_minuteswest*60;
-}
-
-static inline hfs_u32 hfs_time(void) {
-	return htonl(hfs_from_utc(get_seconds())+2082844800U);
-}
-
-
-/*
- * hfs_wait_queue 
- */
-typedef wait_queue_head_t hfs_wait_queue;
-
-static inline void hfs_init_waitqueue(hfs_wait_queue *queue) {
-        init_waitqueue_head(queue);
-}
-
-static inline void hfs_sleep_on(hfs_wait_queue *queue) {
-	sleep_on(queue);
-}
-
-static inline void hfs_wake_up(hfs_wait_queue *queue) {
-	wake_up(queue);
-}
-
-static inline void hfs_relinquish(void) {
-	schedule();
-}
-
-
-/*
- * hfs_sysmdb 
- */
-typedef struct super_block *hfs_sysmdb;
-
-static inline void hfs_mdb_dirty(hfs_sysmdb sys_mdb) {
-	sys_mdb->s_dirt = 1;
-}
-
-static inline const char *hfs_mdb_name(hfs_sysmdb sys_mdb) {
-	return sys_mdb->s_id;
-}
-
-
-/*
- * hfs_sysentry
- */
-typedef struct dentry *hfs_sysentry[4];
-
-/*
- * hfs_buffer
- */
-typedef struct buffer_head *hfs_buffer;
-
-#define HFS_BAD_BUFFER NULL
-
-/* In sysdep.c, since it needs HFS_SECTOR_SIZE */
-extern hfs_buffer hfs_buffer_get(hfs_sysmdb, int, int);
-
-static inline int hfs_buffer_ok(hfs_buffer buffer) {
-	return (buffer != NULL);
-}
-
-static inline void hfs_buffer_put(hfs_buffer buffer) {
-	brelse(buffer);
-}
-
-static inline void hfs_buffer_dirty(hfs_buffer buffer) {
-	mark_buffer_dirty(buffer);
-}
-
-static inline void hfs_buffer_sync(hfs_buffer buffer) {
-	if (buffer_dirty(buffer))
-		sync_dirty_buffer(buffer);
-}
-
-static inline void *hfs_buffer_data(const hfs_buffer buffer) {
-	return buffer->b_data;
-}
-
-
-/*
- * bit operations
- */
-
-#undef BITNR
-#if defined(__BIG_ENDIAN)
-#	define BITNR(X)	((X)^31)
-#	if !defined(__constant_htonl)
-#		define __constant_htonl(x) (x)
-#	endif
-#	if !defined(__constant_htons)
-#		define __constant_htons(x) (x)
-#	endif
-#elif defined(__LITTLE_ENDIAN)
-#	define BITNR(X)	((X)^7)
-#	if !defined(__constant_htonl)
-#		define __constant_htonl(x) \
-        ((unsigned long int)((((unsigned long int)(x) & 0x000000ffU) << 24) | \
-                             (((unsigned long int)(x) & 0x0000ff00U) <<  8) | \
-                             (((unsigned long int)(x) & 0x00ff0000U) >>  8) | \
-                             (((unsigned long int)(x) & 0xff000000U) >> 24)))
-#	endif
-#	if !defined(__constant_htons)
-#		define __constant_htons(x) \
-        ((unsigned short int)((((unsigned short int)(x) & 0x00ff) << 8) | \
-                              (((unsigned short int)(x) & 0xff00) >> 8)))
-#	endif
-#else
-#	error "Don't know if bytes are big- or little-endian!"
-#endif
-
-static inline int hfs_clear_bit(int bitnr, hfs_u32 *lword) {
-	return test_and_clear_bit(BITNR(bitnr), (unsigned long *)lword);
-}
-
-static inline int hfs_set_bit(int bitnr, hfs_u32 *lword) {
-	return test_and_set_bit(BITNR(bitnr), (unsigned long *)lword);
-}
-
-static inline int hfs_test_bit(int bitnr, const hfs_u32 *lword) {
-	/* the kernel should declare the second arg of test_bit as const */
-	return test_bit(BITNR(bitnr), (unsigned long *)lword);
-}
-
-#undef BITNR
-
-/*
- * HFS structures have fields aligned to 16-bit boundaries.
- * So, 16-bit get/put are easy while 32-bit get/put need
- * some care on architectures like the DEC Alpha.
- *
- * In what follows:
- *	ns  = 16-bit integer in network byte-order w/ 16-bit alignment
- *	hs  = 16-bit integer in host byte-order w/ 16-bit alignment
- *	nl  = 32-bit integer in network byte-order w/ unknown alignment
- *	hl  = 32-bit integer in host byte-order w/ unknown alignment
- *	anl = 32-bit integer in network byte-order w/ 32-bit alignment
- *	ahl = 32-bit integer in host byte-order w/ 32-bit alignment
- * Example: hfs_get_hl() gets an unaligned 32-bit integer converting
- *	it to host byte-order.
- */
-#define hfs_get_hs(addr)	ntohs(*((hfs_u16 *)(addr)))
-#define hfs_get_ns(addr)	(*((hfs_u16 *)(addr)))
-#define hfs_get_hl(addr)	ntohl(get_unaligned((hfs_u32 *)(addr)))
-#define hfs_get_nl(addr)	get_unaligned((hfs_u32 *)(addr))
-#define hfs_get_ahl(addr)	ntohl(*((hfs_u32 *)(addr)))
-#define hfs_get_anl(addr)	(*((hfs_u32 *)(addr)))
-#define hfs_put_hs(val, addr) 	((void)(*((hfs_u16 *)(addr)) = ntohs(val)))
-#define hfs_put_ns(val, addr) 	((void)(*((hfs_u16 *)(addr)) = (val)))
-#define hfs_put_hl(val, addr) 	put_unaligned(htonl(val), (hfs_u32 *)(addr))
-#define hfs_put_nl(val, addr) 	put_unaligned((val), (hfs_u32 *)(addr))
-#define hfs_put_ahl(val, addr) 	((void)(*((hfs_u32 *)(addr)) = ntohl(val)))
-#define hfs_put_anl(val, addr) 	((void)(*((hfs_u32 *)(addr)) = (val)))
-
-#endif
--- diff/include/linux/if_pppvar.h	2002-10-16 04:29:05.000000000 +0100
+++ source/include/linux/if_pppvar.h	1970-01-01 01:00:00.000000000 +0100
@@ -1,138 +0,0 @@
-/*	From: if_pppvar.h,v 1.2 1995/06/12 11:36:51 paulus Exp */
-/*
- * if_pppvar.h - private structures and declarations for PPP.
- *
- * Copyright (c) 1994 The Australian National University.
- * All rights reserved.
- *
- * Permission to use, copy, modify, and distribute this software and its
- * documentation is hereby granted, provided that the above copyright
- * notice appears in all copies.  This software is provided without any
- * warranty, express or implied. The Australian National University
- * makes no representations about the suitability of this software for
- * any purpose.
- *
- * IN NO EVENT SHALL THE AUSTRALIAN NATIONAL UNIVERSITY BE LIABLE TO ANY
- * PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
- * THE AUSTRALIAN NATIONAL UNIVERSITY HAVE BEEN ADVISED OF THE POSSIBILITY
- * OF SUCH DAMAGE.
- *
- * THE AUSTRALIAN NATIONAL UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES,
- * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
- * AND FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE AUSTRALIAN NATIONAL UNIVERSITY HAS NO
- * OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS,
- * OR MODIFICATIONS.
- *
- * Copyright (c) 1989 Carnegie Mellon University.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms are permitted
- * provided that the above copyright notice and this paragraph are
- * duplicated in all such forms and that any documentation,
- * advertising materials, and other materials related to such
- * distribution and use acknowledge that the software was developed
- * by Carnegie Mellon University.  The name of the
- * University may not be used to endorse or promote products derived
- * from this software without specific prior written permission.
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
- * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- */
-
-/*
- *  ==FILEVERSION 990806==
- *
- *  NOTE TO MAINTAINERS:
- *   If you modify this file at all, please set the above date.
- *   if_pppvar.h is shipped with a PPP distribution as well as with the kernel;
- *   if everyone increases the FILEVERSION number above, then scripts
- *   can do the right thing when deciding whether to install a new if_pppvar.h
- *   file.  Don't change the format of that line otherwise, so the
- *   installation script can recognize it.
- */
-
-/*
- * Supported network protocols.  These values are used for
- * indexing sc_npmode.
- */
-
-#define NP_IP	0		/* Internet Protocol */
-#define NP_IPX	1		/* IPX protocol */
-#define NP_AT	2		/* Appletalk protocol */
-#define NP_IPV6	3		/* Internet Protocol */
-#define NUM_NP	4		/* Number of NPs. */
-
-#define OBUFSIZE	256	/* # chars of output buffering */
-
-/*
- * Structure describing each ppp unit.
- */
-
-struct ppp {
-	int		magic;		/* magic value for structure	*/
-	struct ppp	*next;		/* unit with next index		*/
-	unsigned long	inuse;		/* are we allocated?		*/
-	int		line;		/* network interface unit #	*/
-	__u32		flags;		/* miscellaneous control flags	*/
-	int		mtu;		/* maximum xmit frame size	*/
-	int		mru;		/* maximum receive frame size	*/
-	struct slcompress *slcomp;	/* for TCP header compression	*/
-	struct sk_buff_head xmt_q;	/* frames to send from pppd	*/
-	struct sk_buff_head rcv_q;	/* frames for pppd to read	*/
-	unsigned long	xmit_busy;	/* bit 0 set when xmitter busy  */
-
-	/* Information specific to using ppp on async serial lines. */
-	struct tty_struct *tty;		/* ptr to TTY structure	*/
-	struct tty_struct *backup_tty;	/* TTY to use if tty gets closed */
-	__u8		escape;		/* 0x20 if prev char was PPP_ESC */
-	__u8		toss;		/* toss this frame		*/
-	volatile __u8	tty_pushing;	/* internal state flag		*/
-	volatile __u8	woke_up;	/* internal state flag		*/
-	__u32		xmit_async_map[8]; /* 1 bit means that given control 
-					   character is quoted on output*/
-	__u32		recv_async_map; /* 1 bit means that given control 
-					   character is ignored on input*/
-	__u32		bytes_sent;	/* Bytes sent on frame	*/
-	__u32		bytes_rcvd;	/* Bytes recvd on frame	*/
-
-	/* Async transmission information */
-	struct sk_buff	*tpkt;		/* frame currently being sent	*/
-	int		tpkt_pos;	/* how much of it we've done	*/
-	__u16		tfcs;		/* FCS so far for it		*/
-	unsigned char	*optr;		/* where we're up to in sending */
-	unsigned char	*olim;		/* points past last valid char	*/
-
-	/* Async reception information */
-	struct sk_buff	*rpkt;		/* frame currently being rcvd	*/
-	__u16		rfcs;		/* FCS so far of rpkt		*/
-
-	/* Queues for select() functionality */
-	wait_queue_head_t read_wait;	/* queue for reading processes	*/
-
-	/* info for detecting idle channels */
-	unsigned long	last_xmit;	/* time of last transmission	*/
-	unsigned long	last_recv;	/* time last packet received    */
-
-	/* Statistic information */
-	struct pppstat	stats;		/* statistic information	*/
-
-	/* PPP compression protocol information */
-	struct	compressor *sc_xcomp;	/* transmit compressor */
-	void	*sc_xc_state;		/* transmit compressor state */
-	struct	compressor *sc_rcomp;	/* receive decompressor */
-	void	*sc_rc_state;		/* receive decompressor state */
-
-	enum	NPmode sc_npmode[NUM_NP]; /* what to do with each NP */
-	int	 sc_xfer;		/* PID of reserved PPP table */
-	char	name[16];		/* space for unit name */
-	struct net_device	dev;		/* net device structure */
-	struct net_device_stats estats;	/* more detailed stats */
-
-	/* tty output buffer */
-	unsigned char	obuf[OBUFSIZE];	/* buffer for characters to send */
-};
-
-#define PPP_MAGIC	0x5002
-#define PPP_VERSION	"2.3.7"
--- diff/include/linux/isdn/fsm.h	2002-11-11 11:09:38.000000000 +0000
+++ source/include/linux/isdn/fsm.h	1970-01-01 01:00:00.000000000 +0100
@@ -1,58 +0,0 @@
-/* Linux ISDN subsystem, finite state machine
- *
- * Author       Karsten Keil
- * Copyright              by Karsten Keil      <keil@isdn4linux.de>
- *              2001-2002 by Kai Germaschewski <kai@germaschewski.name>
- * 
- * This software may be used and distributed according to the terms
- * of the GNU General Public License, incorporated herein by reference.
- */
-
-#ifndef __ISDN_FSM_H__
-#define __ISDN_FSM_H__
-
-#include <linux/kernel.h>
-#include <linux/timer.h>
-
-struct fsm_inst;
-
-typedef int (*fsm_fn)(struct fsm_inst *, int, void *);
-
-struct fsm {
-	fsm_fn *jumpmatrix;
-	int st_cnt, ev_cnt, fn_cnt;
-	char **st_str, **ev_str;
-	struct fsm_node *fn_tbl;
-};
-
-struct fsm_inst {
-	struct fsm *fsm;
-	int state;
-	int debug;
-	void *userdata;
-	int userint;
-	void (*printdebug) (struct fsm_inst *, char *, ...);
-};
-
-struct fsm_node {
-	int st, ev;
-	fsm_fn fn;
-};
-
-struct fsm_timer {
-	struct fsm_inst *fi;
-	struct timer_list tl;
-	int ev;
-	void *arg;
-};
-
-int  fsm_new(struct fsm *fsm);
-void fsm_free(struct fsm *fsm);
-int  fsm_event(struct fsm_inst *fi, int event, void *arg);
-void fsm_change_state(struct fsm_inst *fi, int newstate);
-void fsm_init_timer(struct fsm_inst *fi, struct fsm_timer *ft);
-int  fsm_add_timer(struct fsm_timer *ft, int timeout, int event);
-void fsm_mod_timer(struct fsm_timer *ft, int timeout, int event);
-void fsm_del_timer(struct fsm_timer *ft);
-
-#endif
--- diff/include/linux/modsetver.h	2002-10-16 04:28:20.000000000 +0100
+++ source/include/linux/modsetver.h	1970-01-01 01:00:00.000000000 +0100
@@ -1,10 +0,0 @@
-/* Symbol versioning nastiness.  */
-
-#define __SYMBOL_VERSION(x)       __ver_ ## x
-#define __VERSIONED_SYMBOL2(x,v)  x ## _R ## v
-#define __VERSIONED_SYMBOL1(x,v)  __VERSIONED_SYMBOL2(x,v)
-#define __VERSIONED_SYMBOL(x)     __VERSIONED_SYMBOL1(x,__SYMBOL_VERSION(x))
-
-#ifndef _set_ver
-#define _set_ver(x)		  __VERSIONED_SYMBOL(x)
-#endif
--- diff/include/linux/ppp.h	2002-10-16 04:27:11.000000000 +0100
+++ source/include/linux/ppp.h	1970-01-01 01:00:00.000000000 +0100
@@ -1,4 +0,0 @@
-/*
- *	Back compatibility for a while.
- */
-#include <linux/if_ppp.h>
